diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml new file mode 100644 index 0000000000..ef538d78ec --- /dev/null +++ b/.github/workflows/continuous_integration.yml @@ -0,0 +1,161 @@ +name: Continuous Integration + +on: [push, pull_request] + +jobs: + build: + name: ${{ matrix.config.name }} | ${{ matrix.config.build_type }} + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + config: + - name: Visual Studio 2022 + os: windows-2022 + extra_options: -DCMAKE_TOOLCHAIN_FILE=build/vcpkg/scripts/buildsystems/vcpkg.cmake + build_type: RelWithDebInfo + + - name: Visual Studio 2022 + os: windows-2022 + extra_options: -DCMAKE_TOOLCHAIN_FILE=build/vcpkg/scripts/buildsystems/vcpkg.cmake + build_type: Debug + + - name: macOS + os: macos-12 + deps_cmdline: brew install libvpx webp + build_type: Release + + - name: macOS + os: macos-12 + extra_options: -G Xcode -DDYN_OPENAL=OFF + deps_cmdline: brew install libvpx webp + build_type: Debug + + - name: Linux GCC 9 + os: ubuntu-22.04 + extra_options: -DCMAKE_C_COMPILER=gcc-9 -DCMAKE_CXX_COMPILER=g++-9 + deps_cmdline: sudo apt update && sudo apt install libsdl2-dev libvpx-dev libgtk2.0-dev libwebp-dev + build_type: MinSizeRel + + - name: Linux GCC 12 + os: ubuntu-22.04 + extra_options: -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 + deps_cmdline: sudo apt update && sudo apt install libsdl2-dev libvpx-dev libgtk-3-dev libwebp-dev + build_type: RelWithDebInfo + + - name: Linux Clang 11 + os: ubuntu-22.04 + extra_options: -DCMAKE_C_COMPILER=clang-11 -DCMAKE_CXX_COMPILER=clang++-11 -DDYN_OPENAL=OFF + deps_cmdline: sudo apt update && sudo apt install clang-11 libsdl2-dev libvpx-dev libopenal-dev libwebp-dev + build_type: Debug + + - name: Linux Clang 15 + os: ubuntu-22.04 + extra_options: -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 + deps_cmdline: sudo apt update && sudo apt install clang-15 libsdl2-dev libvpx-dev libwebp-dev + build_type: Release + + steps: + - uses: actions/checkout@v4 + + - name: Install Dependencies + shell: bash + run: | + if [[ -n "${{ matrix.config.deps_cmdline }}" ]]; then + eval ${{ matrix.config.deps_cmdline }} + fi + mkdir build + if [[ "${{ runner.os }}" == 'macOS' ]]; then + export ZMUSIC_PACKAGE=zmusic-1.1.9-macos.tar.xz + elif [[ "${{ runner.os }}" == 'Linux' ]]; then + export ZMUSIC_PACKAGE=zmusic-1.1.9-linux.tar.xz + fi + if [[ -n "${ZMUSIC_PACKAGE}" ]]; then + cd build + wget -q "https://github.com/coelckers/gzdoom/releases/download/ci_deps/${ZMUSIC_PACKAGE}" + tar -xf "${ZMUSIC_PACKAGE}" + fi + + - name: Setup vcpkg + uses: lukka/run-vcpkg@v11 + if: runner.os == 'Windows' + with: + vcpkgDirectory: '${{ github.workspace }}/build/vcpkg' + vcpkgGitCommitId: '2c401863dd54a640aeb26ed736c55489c079323b' + + - name: Configure + shell: bash + run: | + cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DCMAKE_PREFIX_PATH=`pwd`/build/zmusic -DPK3_QUIET_ZIPDIR=ON ${{ matrix.config.extra_options }} . + + - name: Build + shell: bash + run: | + export MAKEFLAGS=--keep-going + cmake --build build --config ${{ matrix.config.build_type }} --parallel 3 + + - name: Create Package + if: (runner.os == 'Windows' || matrix.config.name == 'Linux GCC 12') && matrix.config.build_type == 'RelWithDebInfo' + shell: bash + run: | + cd build + mkdir package + if [[ "${{ runner.os }}" == 'Windows' ]]; then + cp -r ${{ matrix.config.build_type }}/vkdoom.exe ${{ matrix.config.build_type }}/*.pk3 ${{ matrix.config.build_type }}/fm_banks ${{ matrix.config.build_type }}/soundfonts package + cp ../bin/licenses.zip ../bin/windows/libsndfile/64bit/libsndfile-1.dll ../bin/windows/openal/64bit/openal32.dll ../bin/windows/zmusic/64bit/zmusic.dll package + cp ${{ matrix.config.build_type }}/vkdoom-stripped.pdb package/vkdoom.pdb + elif [[ "${{ runner.os }}" == 'macOS' ]]; then + cp -r vkdoom.app package + elif [[ "${{ runner.os }}" == 'Linux' ]]; then + cp vkdoom *.pk3 package + strip package/vkdoom + fi + + - name: Upload Package + if: runner.os == 'Windows' || matrix.config.name == 'Linux GCC 12' + uses: actions/upload-artifact@v4 + with: + path: build/package + name: ${{ matrix.config.name }} ${{ matrix.config.build_type }} + + - name: List Build Directory + if: always() + shell: bash + run: | + git status + ls -lR build + + deploy: + name: Update Latest successful build + runs-on: ubuntu-latest + needs: build + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + + steps: + - name: Download Windows artifact + uses: actions/download-artifact@v4 + with: + name: Visual Studio 2022 RelWithDebInfo + path: build/vkdoom-windows-prerelease + + - name: Download Linux artifact + uses: actions/download-artifact@v4 + with: + name: Linux GCC 12 RelWithDebInfo + path: build/vkdoom-linux-prerelease + + - name: Zip artifacts + shell: bash + run: | + cd build + zip -r vkdoom-windows-prerelease.zip vkdoom-windows-prerelease + zip -r vkdoom-linux-prerelease.zip vkdoom-linux-prerelease + + - name: Update nightly release + uses: pyTooling/Actions/releaser@r0 + with: + tag: nightly + rm: true + token: ${{ secrets.GITHUB_TOKEN }} + files: build/vkdoom-windows-prerelease.zip build/vkdoom-linux-prerelease.zip + diff --git a/.gitignore b/.gitignore index 8be2eccd19..6e9e5b9de1 100644 --- a/.gitignore +++ b/.gitignore @@ -22,8 +22,13 @@ .vscode /src/gl/unused /mapfiles_release/*.map +/AppDir +/appimage-build +*.AppImage .DS_Store /build_vc2017-32 /build2 /build_vc2019-64 /build_vc2019-32 +/build__ +gzdoom-crash.log diff --git a/AppImageBuilder.yml b/AppImageBuilder.yml new file mode 100644 index 0000000000..fcf249f2eb --- /dev/null +++ b/AppImageBuilder.yml @@ -0,0 +1,45 @@ +# appimage-builder recipe see https://appimage-builder.readthedocs.io for details +version: 1 +AppDir: + path: ./AppDir + app_info: + id: com.VKDoom.app + name: VKDoom + icon: game_icon.png + version: latest + exec: ./vkdoom + exec_args: $@ + apt: + arch: amd64 + allow_unauthenticated: true + sources: + - sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy main restricted + - sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates main restricted + include: [] + files: + include: [] + exclude: + - usr/share/man + - usr/share/doc/*/README.* + - usr/share/doc/*/changelog.* + - usr/share/doc/*/NEWS.* + - usr/share/doc/*/TODO.* + test: + fedora-30: + image: appimagecrafters/tests-env:fedora-30 + command: ./AppRun + debian-stable: + image: appimagecrafters/tests-env:debian-stable + command: ./AppRun + archlinux-latest: + image: appimagecrafters/tests-env:archlinux-latest + command: ./AppRun + centos-7: + image: appimagecrafters/tests-env:centos-7 + command: ./AppRun + ubuntu-xenial: + image: appimagecrafters/tests-env:ubuntu-xenial + command: ./AppRun +AppImage: + arch: x86_64 + update-information: guess diff --git a/CMakeLists.txt b/CMakeLists.txt index 95007099a6..8b7f077c2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,4 @@ -cmake_minimum_required( VERSION 3.1.0 ) -project(VkDoom) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - +cmake_minimum_required( VERSION 3.16 ) if( COMMAND cmake_policy ) if( POLICY CMP0011 ) @@ -13,8 +7,47 @@ if( COMMAND cmake_policy ) if( POLICY CMP0054 ) cmake_policy( SET CMP0054 NEW ) endif() + if ( POLICY CMP0067 ) + cmake_policy( SET CMP0067 NEW ) + endif() + if ( POLICY CMP0091 ) + cmake_policy( SET CMP0091 NEW ) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif() +endif() + +if (LIBVPX_VCPKG) + list(APPEND VCPKG_MANIFEST_FEATURES "vcpkg-libvpx") +endif() + +if (OPENAL_SOFT_VCPKG) + list(APPEND VCPKG_MANIFEST_FEATURES "vcpkg-openal-soft") +endif() + +if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR (NOT CMAKE_SYSTEM_NAME AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")) + # Force static triplet on Windows + set(VCPKG_TARGET_TRIPLET "x64-windows-static") +endif() + +project(VkDoom) + +if (WIN32 AND VCPKG_TOOLCHAIN) + option(LIBVPX_VCPKG "Use libvpx from vcpkg" OFF) endif() +if (VCPKG_TOOLCHAIN) + option(OPENAL_SOFT_VCPKG "Use OpenAL from vcpkg" OFF) +endif() + +if (NOT VCPKG_TOOLCHAIN) + set(VCPKG_MANIFEST_FEATURES) +endif() + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + + list( APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ) include( FindPackageHandleStandardArgs ) @@ -146,13 +179,6 @@ endif() if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set( PROFILE 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." ) - - if( CMAKE_CXX_STANDARD ) - # By default, try_compile() invocations ignore CXX_STANDARD value - # CMake 3.8 and newer have CMP0067 policy that fixes the issue, but it should be enabled explicitly - # Older versions require manual specification of the corresponding command line option - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++${CMAKE_CXX_STANDARD}" ) - endif() endif() # Fast math flags, required by some subprojects @@ -188,9 +214,7 @@ endmacro() option( NO_OPENAL "Disable OpenAL sound support" OFF ) find_package( BZip2 ) -find_package( JPEG ) find_package( VPX ) -find_package( ZLIB ) include( TargetArch ) @@ -218,7 +242,7 @@ if( MSVC ) # String pooling # Function-level linking # Disable run-time type information - set( ALL_C_FLAGS "/GF /Gy /permissive-" ) + set( ALL_C_FLAGS "/GF /Gy /permissive- /utf-8" ) if ( HAVE_VULKAN ) set( ALL_C_FLAGS "${ALL_C_FLAGS} /DHAVE_VULKAN" ) @@ -236,28 +260,19 @@ if( MSVC ) # Avoid CRT DLL dependancies in release builds, optionally generate assembly output for checking crash locations. option( ZDOOM_GENERATE_ASM "Generate assembly output." OFF ) if( ZDOOM_GENERATE_ASM ) - set( REL_C_FLAGS "/MT /Oy /Oi /FAcs /GS-" ) + set( REL_C_FLAGS "/Oy /Oi /FAcs /GS-" ) else() - set( REL_C_FLAGS "/MT /Oy /Oi /GS-" ) + set( REL_C_FLAGS "/Oy /Oi /GS-" ) endif() # Debug allocations in debug builds - set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC /MTd" ) + set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC" ) # Disable warnings for unsecure CRT functions from VC8+ set( ALL_C_FLAGS "${ALL_C_FLAGS} /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0600 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS" ) - # The CMake configurations set /GR and /MD by default, which conflict with our settings. - string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} ) - string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL} ) - string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ) string(REPLACE "/Ob1 " "/Ob2 " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ) - string(REPLACE "/MDd " " " CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} ) - string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} ) - string(REPLACE "/MD " " " CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} ) - string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO} ) - string(REPLACE "/MDd " " " CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} ) else() set( REL_LINKER_FLAGS "" ) set( ALL_C_FLAGS "-ffp-contract=off" ) @@ -272,7 +287,7 @@ else() if ( UNIX ) include(CheckSymbolExists) - check_symbol_exists( "fts_set" "fts.h" HAVE_FTS ) + check_symbol_exists( "fts_set" "sys/types.h;sys/stat.h;fts.h" HAVE_FTS ) if ( NOT HAVE_FTS ) include ( FindPkgConfig ) pkg_check_modules( MUSL_FTS musl-fts ) @@ -289,7 +304,7 @@ else() if( APPLE ) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12") + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) # If we're compiling with a custom GCC on the Mac (which we know since g++-4.2 doesn't support C++11) statically link libgcc. set( ALL_C_FLAGS "-static-libgcc" ) @@ -317,8 +332,6 @@ set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${REL_C_FLAGS}" ) set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" ) set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) -option(FORCE_INTERNAL_ZLIB "Use internal zlib") -option(FORCE_INTERNAL_JPEG "Use internal jpeg") option(FORCE_INTERNAL_BZIP2 "Use internal bzip2") option(FORCE_INTERNAL_DRAGONBOOK "Use internal dragonbook" ON) mark_as_advanced( FORCE_INTERNAL_DRAGONBOOK ) @@ -327,22 +340,14 @@ if (HAVE_VULKAN) add_subdirectory( libraries/ZVulkan ) endif() +add_subdirectory( libraries/ZWidget ) +add_subdirectory( libraries/webp ) + add_subdirectory( libraries/discordrpc EXCLUDE_FROM_ALL ) set( DRPC_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/discordrpc/include" ) set( DRPC_LIBRARIES discord-rpc ) set( DRPC_LIBRARY discord-rpc ) -if( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB ) - message( STATUS "Using system zlib, includes found at ${ZLIB_INCLUDE_DIR}" ) -else() - message( STATUS "Using internal zlib" ) - set( SKIP_INSTALL_ALL TRUE ) # Avoid installing zlib - add_subdirectory( libraries/zlib ) - set( ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib ) - set( ZLIB_LIBRARIES z ) - set( ZLIB_LIBRARY z ) -endif() - if( HAVE_VM_JIT AND UNIX ) check_symbol_exists( "backtrace" "execinfo.h" HAVE_BACKTRACE ) if( NOT HAVE_BACKTRACE ) @@ -370,16 +375,6 @@ if( ${HAVE_VM_JIT} ) endif() endif() -if( JPEG_FOUND AND NOT FORCE_INTERNAL_JPEG ) - message( STATUS "Using system jpeg library, includes found at ${JPEG_INCLUDE_DIR}" ) -else() - message( STATUS "Using internal jpeg library" ) - add_subdirectory( libraries/jpeg ) - set( JPEG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libraries/jpeg ) - set( JPEG_LIBRARIES jpeg ) - set( JPEG_LIBRARY jpeg ) -endif() - if( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 ) message( STATUS "Using system bzip2 library, includes found at ${BZIP2_INCLUDE_DIR}" ) else() @@ -411,8 +406,8 @@ install(DIRECTORY docs/ option( DYN_OPENAL "Dynamically load OpenAL" ON ) add_subdirectory( libraries/lzma ) +add_subdirectory( libraries/miniz ) add_subdirectory( tools ) -add_subdirectory( libraries/gdtoa ) add_subdirectory( wadsrc ) add_subdirectory( wadsrc_bm ) add_subdirectory( wadsrc_lights ) diff --git a/README.md b/README.md index f808a0b1f2..a0ea1d01ce 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ ## Welcome to VkDoom! -VkDoom is a source port based on the DOOM engine with a focus on vulkan and modern computers. +VkDoom is a source port based on the DOOM engine with a focus on Vulkan and modern computers. Please see license files for individual contributor licenses. +Visit our [website](https://vkdoom.org) for more details. + ### Licensed under the GPL v3 ##### https://www.gnu.org/licenses/quick-guide-gplv3.en.html diff --git a/auto-setup-linux.sh b/auto-setup-linux.sh new file mode 100755 index 0000000000..c6c09cbf5d --- /dev/null +++ b/auto-setup-linux.sh @@ -0,0 +1,104 @@ +#!/bin/bash +#** +#** auto-setup-linux.sh +#** Automatic (easy) setup and build script for Linux +#** +#** Note that this script assumes you have both 'git' and 'cmake' installed properly and in your PATH! +#** This script also assumes you have installed a build system that cmake can automatically detect. +#** Such as GCC or Clang. Requires appropriate supporting libraries installed too! +#** Without these items, this script will FAIL! So make sure you have your build environment properly +#** set up in order for this script to succeed. +#** +#** The purpose of this script is to get someone easily going with a full working compile of GZDoom. +#** This allows anyone to make simple changes or tweaks to the engine as they see fit and easily +#** compile their own copy without having to follow complex instructions to get it working. +#** Every build environment is different, and every computer system is different - this should work +#** in most typical systems under Windows but it may fail under certain types of systems or conditions. +#** Not guaranteed to work and your mileage will vary. +#** +#** Prerequisite Packages used in testing (from Linux Mint-XFCE): +#** nasm autoconf libtool libsystemd-dev clang-15 libx11-dev libsdl2-dev libgtk-3-dev +#** +#**--------------------------------------------------------------------------- +#** Copyright 2024 Rachael Alexanderson and the GZDoom team +#** 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. The name of the author may not be used to endorse or promote products +#** derived from this software without specific prior written permission. +#** +#** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +#**--------------------------------------------------------------------------- +#** + +# -- Always operate within the build folder +BUILDFOLDER=$(dirname "$0")/build + +if [ ! -d "$BUILDFOLDER" ]; then + mkdir "$BUILDFOLDER" +fi +cd "$BUILDFOLDER" + +if [ -d "vcpkg" ]; then + git -C ./vcpkg pull +fi +if [ ! -d "vcpkg" ]; then + git clone https://github.com/microsoft/vcpkg +fi +if [ -d "zmusic" ]; then + git -C ./zmusic fetch +fi +if [ ! -d "zmusic" ]; then + git clone https://github.com/zdoom/zmusic +fi +if [ -d "zmusic" ]; then + git -C ./zmusic checkout 1.1.12 +fi + +if [ ! -d "zmusic/build" ]; then + mkdir zmusic/build +fi +if [ ! -d "vcpkg_installed" ]; then + mkdir vcpkg_installed +fi + +cmake -S ./zmusic -B ./zmusic/build \ + -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_LIBSNDFILE=1 \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DVCPKG_INSTALLLED_DIR=../vcpkg_installed/ +pushd ./zmusic/build +make -j $(nproc) +popd + +cmake -S .. -B . \ + -DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DVCPKG_INSTALLLED_DIR=./vcpkg_installed/ +make -j $(nproc); rc=$? + +# -- If successful, show the build +if [ $rc -eq 0 ]; then + if [ -f vkdoom ]; then + xdg-open . + fi +fi + +exit $rc diff --git a/auto-setup-windows-arm.cmd b/auto-setup-windows-arm.cmd new file mode 100644 index 0000000000..01c9b13d8e --- /dev/null +++ b/auto-setup-windows-arm.cmd @@ -0,0 +1,89 @@ +@echo off +goto aftercopyright + +** +** auto-setup-windows-arm.cmd +** Automatic (easy) setup and build script for Windows ARM (cross compiling on x64) - please have a +** build of x64 in your build folder ready before executing this script! +** +** Note that this script assumes you have both 'git' and 'cmake' installed properly and in your PATH! +** This script also assumes you have installed a build system that cmake can automatically detect. +** Such as Visual Studio Community. Requires appropriate SDK installed too! +** Without these items, this script will FAIL! So make sure you have your build environment properly +** set up in order for this script to succeed. +** +** The purpose of this script is to get someone easily going with a full working compile of GZDoom. +** This allows anyone to make simple changes or tweaks to the engine as they see fit and easily +** compile their own copy without having to follow complex instructions to get it working. +** Every build environment is different, and every computer system is different - this should work +** in most typical systems under Windows but it may fail under certain types of systems or conditions. +** Not guaranteed to work and your mileage will vary. +** +**--------------------------------------------------------------------------- +** Copyright 2024 Rachael Alexanderson and the GZDoom team +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** + +:aftercopyright + + +setlocal +rem -- Always operate within the build-arm folder +if not exist "%~dp0\build-arm" mkdir "%~dp0\build-arm" +pushd "%~dp0\build-arm" + +if exist ..\build\vcpkg if exist ..\build\vcpkg\* git -C ../build/vcpkg pull +if not exist ..\build\vcpkg goto :nobuild + +if exist zmusic if exist zmusic\* git -C ./zmusic pull +if not exist zmusic git clone https://github.com/zdoom/zmusic + +mkdir "%~dp0\build-arm\zmusic\build" +mkdir "%~dp0\build-arm\vcpkg_installed" + +cmake -A ARM64 -S ./zmusic -B ./zmusic/build ^ + -DCMAKE_TOOLCHAIN_FILE=../../build/vcpkg/scripts/buildsystems/vcpkg.cmake ^ + -DVCPKG_LIBSNDFILE=1 ^ + -DVCPKG_INSTALLLED_DIR=../vcpkg_installed/ ^ + -DCMAKE_CROSSCOMPILING=TRUE +cmake --build ./zmusic/build --config Release -- -maxcpucount -verbosity:minimal + +cmake -A ARM64 -S .. -B . ^ + -DCMAKE_TOOLCHAIN_FILE=../build/vcpkg/scripts/buildsystems/vcpkg.cmake ^ + -DZMUSIC_INCLUDE_DIR=./zmusic/include ^ + -DZMUSIC_LIBRARIES=./zmusic/build/source/Release/zmusic.lib ^ + -DVCPKG_INSTALLLED_DIR=./vcpkg_installed/ ^ + -DFORCE_CROSSCOMPILE=TRUE ^ + -DIMPORT_EXECUTABLES=../build/ImportExecutables.cmake +cmake --build . --config RelWithDebInfo -- -maxcpucount -verbosity:minimal + +rem -- If successful, show the build +if exist RelWithDebInfo\vkdoom.exe explorer.exe RelWithDebInfo + +goto :eof +:nobuild +echo Please use auto-setup-windows.cmd to create an x64 build first! diff --git a/auto-setup-windows.cmd b/auto-setup-windows.cmd new file mode 100644 index 0000000000..845dc17101 --- /dev/null +++ b/auto-setup-windows.cmd @@ -0,0 +1,82 @@ +@echo off +goto aftercopyright + +** +** auto-setup-windows.cmd +** Automatic (easy) setup and build script for Windows +** +** Note that this script assumes you have both 'git' and 'cmake' installed properly and in your PATH! +** This script also assumes you have installed a build system that cmake can automatically detect. +** Such as Visual Studio Community. Requires appropriate SDK installed too! +** Without these items, this script will FAIL! So make sure you have your build environment properly +** set up in order for this script to succeed. +** +** The purpose of this script is to get someone easily going with a full working compile of GZDoom. +** This allows anyone to make simple changes or tweaks to the engine as they see fit and easily +** compile their own copy without having to follow complex instructions to get it working. +** Every build environment is different, and every computer system is different - this should work +** in most typical systems under Windows but it may fail under certain types of systems or conditions. +** Not guaranteed to work and your mileage will vary. +** +**--------------------------------------------------------------------------- +** Copyright 2023-2024 Rachael Alexanderson and the GZDoom team +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** + +:aftercopyright + +setlocal enableextensions + +rem -- Always operate within the build folder +if not exist "%~dp0\build" mkdir "%~dp0\build" +pushd "%~dp0\build" + +if exist vcpkg if exist vcpkg\* git -C ./vcpkg pull +if not exist vcpkg git clone https://github.com/microsoft/vcpkg + +if exist zmusic if exist vcpkg\* git -C ./zmusic pull +if not exist zmusic git clone https://github.com/zdoom/zmusic + +if not exist "%~dp0\build\zmusic\build" mkdir "%~dp0\build\zmusic\build" +if not exist "%~dp0\build\vcpkg_installed" mkdir "%~dp0\build\vcpkg_installed" + +cmake -A x64 -S ./zmusic -B ./zmusic/build ^ + -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ^ + -DVCPKG_LIBSNDFILE=1 ^ + -DVCPKG_INSTALLLED_DIR=../vcpkg_installed/ +cmake --build ./zmusic/build --config Release -- -maxcpucount -verbosity:minimal + +cmake -A x64 -S .. -B . ^ + -DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake ^ + -DZMUSIC_INCLUDE_DIR=./zmusic/include ^ + -DZMUSIC_LIBRARIES=./zmusic/build/source/Release/zmusic.lib ^ + -DVCPKG_INSTALLLED_DIR=./vcpkg_installed/ +cmake --build . --config RelWithDebInfo -- -maxcpucount -verbosity:minimal + +rem -- If successful, show the build +if not errorlevel 1 if exist RelWithDebInfo\vkdoom.exe explorer.exe RelWithDebInfo + diff --git a/bin/licenses.zip b/bin/licenses.zip new file mode 100644 index 0000000000..d1eaa9260c Binary files /dev/null and b/bin/licenses.zip differ diff --git a/bin/windows/libsndfile/64bit/libsndfile-1.dll b/bin/windows/libsndfile/64bit/libsndfile-1.dll new file mode 100644 index 0000000000..14545e4d2f Binary files /dev/null and b/bin/windows/libsndfile/64bit/libsndfile-1.dll differ diff --git a/bin/windows/openal/64bit/openal32.dll b/bin/windows/openal/64bit/openal32.dll new file mode 100644 index 0000000000..bafccf6ca5 Binary files /dev/null and b/bin/windows/openal/64bit/openal32.dll differ diff --git a/bin/windows/zmusic/64bit/zmusic.dll b/bin/windows/zmusic/64bit/zmusic.dll new file mode 100644 index 0000000000..97c92dc065 Binary files /dev/null and b/bin/windows/zmusic/64bit/zmusic.dll differ diff --git a/cmake/FindZMusic.cmake b/cmake/FindZMusic.cmake index dd0c9296dd..43754a8079 100644 --- a/cmake/FindZMusic.cmake +++ b/cmake/FindZMusic.cmake @@ -10,9 +10,15 @@ if(ZMUSIC_INCLUDE_DIR AND ZMUSIC_LIBRARIES) set(ZMUSIC_FIND_QUIETLY TRUE) endif() -find_path(ZMUSIC_INCLUDE_DIR zmusic.h) +find_path(ZMUSIC_INCLUDE_DIR zmusic.h + HINTS + ${CMAKE_SOURCE_DIR}/build/zmusic/include +) -find_library(ZMUSIC_LIBRARIES NAMES zmusic) +find_library(ZMUSIC_LIBRARIES NAMES zmusic + HINTS + ${CMAKE_SOURCE_DIR}/build/zmusic/build/source +) mark_as_advanced(ZMUSIC_LIBRARIES ZMUSIC_INCLUDE_DIR) # handle the QUIETLY and REQUIRED arguments and set ZMUSIC_FOUND to TRUE if diff --git a/libraries/ZVulkan/CMakeLists.txt b/libraries/ZVulkan/CMakeLists.txt index 8a99d6a917..3b47b7b686 100644 --- a/libraries/ZVulkan/CMakeLists.txt +++ b/libraries/ZVulkan/CMakeLists.txt @@ -1,6 +1,17 @@ cmake_minimum_required(VERSION 3.15) project(zvulkan) +option( VULKAN_USE_XLIB "Use Vulkan xlib (X11) WSI integration" ON ) +option( VULKAN_USE_WAYLAND "Use Vulkan Wayland WSI integration" OFF ) + +if ( VULKAN_USE_XLIB ) + add_definitions( -DVULKAN_USE_XLIB=1 ) +else() + if (VULKAN_USE_WAYLAND) + add_definitions( -DVULKAN_USE_WAYLAND=1 ) + endif() +endif() + set(ZVULKAN_SOURCES src/vulkanbuilders.cpp src/vulkandevice.cpp diff --git a/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std.h b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std.h new file mode 100644 index 0000000000..ef7eaf745e --- /dev/null +++ b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std.h @@ -0,0 +1,312 @@ +#ifndef VULKAN_VIDEO_CODEC_H264STD_H_ +#define VULKAN_VIDEO_CODEC_H264STD_H_ 1 + +/* +** Copyright 2015-2023 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h264std is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h264std 1 +#include "vulkan_video_codecs_common.h" +#define STD_VIDEO_H264_CPB_CNT_LIST_SIZE 32 +#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS 6 +#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS 16 +#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS 6 +#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS 64 +#define STD_VIDEO_H264_MAX_NUM_LIST_REF 32 +#define STD_VIDEO_H264_MAX_CHROMA_PLANES 2 +#define STD_VIDEO_H264_NO_REFERENCE_PICTURE 0xFF + +typedef enum StdVideoH264ChromaFormatIdc { + STD_VIDEO_H264_CHROMA_FORMAT_IDC_MONOCHROME = 0, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_420 = 1, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_422 = 2, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_444 = 3, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264ChromaFormatIdc; + +typedef enum StdVideoH264ProfileIdc { + STD_VIDEO_H264_PROFILE_IDC_BASELINE = 66, + STD_VIDEO_H264_PROFILE_IDC_MAIN = 77, + STD_VIDEO_H264_PROFILE_IDC_HIGH = 100, + STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE = 244, + STD_VIDEO_H264_PROFILE_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264ProfileIdc; + +typedef enum StdVideoH264LevelIdc { + STD_VIDEO_H264_LEVEL_IDC_1_0 = 0, + STD_VIDEO_H264_LEVEL_IDC_1_1 = 1, + STD_VIDEO_H264_LEVEL_IDC_1_2 = 2, + STD_VIDEO_H264_LEVEL_IDC_1_3 = 3, + STD_VIDEO_H264_LEVEL_IDC_2_0 = 4, + STD_VIDEO_H264_LEVEL_IDC_2_1 = 5, + STD_VIDEO_H264_LEVEL_IDC_2_2 = 6, + STD_VIDEO_H264_LEVEL_IDC_3_0 = 7, + STD_VIDEO_H264_LEVEL_IDC_3_1 = 8, + STD_VIDEO_H264_LEVEL_IDC_3_2 = 9, + STD_VIDEO_H264_LEVEL_IDC_4_0 = 10, + STD_VIDEO_H264_LEVEL_IDC_4_1 = 11, + STD_VIDEO_H264_LEVEL_IDC_4_2 = 12, + STD_VIDEO_H264_LEVEL_IDC_5_0 = 13, + STD_VIDEO_H264_LEVEL_IDC_5_1 = 14, + STD_VIDEO_H264_LEVEL_IDC_5_2 = 15, + STD_VIDEO_H264_LEVEL_IDC_6_0 = 16, + STD_VIDEO_H264_LEVEL_IDC_6_1 = 17, + STD_VIDEO_H264_LEVEL_IDC_6_2 = 18, + STD_VIDEO_H264_LEVEL_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264LevelIdc; + +typedef enum StdVideoH264PocType { + STD_VIDEO_H264_POC_TYPE_0 = 0, + STD_VIDEO_H264_POC_TYPE_1 = 1, + STD_VIDEO_H264_POC_TYPE_2 = 2, + STD_VIDEO_H264_POC_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_POC_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264PocType; + +typedef enum StdVideoH264AspectRatioIdc { + STD_VIDEO_H264_ASPECT_RATIO_IDC_UNSPECIFIED = 0, + STD_VIDEO_H264_ASPECT_RATIO_IDC_SQUARE = 1, + STD_VIDEO_H264_ASPECT_RATIO_IDC_12_11 = 2, + STD_VIDEO_H264_ASPECT_RATIO_IDC_10_11 = 3, + STD_VIDEO_H264_ASPECT_RATIO_IDC_16_11 = 4, + STD_VIDEO_H264_ASPECT_RATIO_IDC_40_33 = 5, + STD_VIDEO_H264_ASPECT_RATIO_IDC_24_11 = 6, + STD_VIDEO_H264_ASPECT_RATIO_IDC_20_11 = 7, + STD_VIDEO_H264_ASPECT_RATIO_IDC_32_11 = 8, + STD_VIDEO_H264_ASPECT_RATIO_IDC_80_33 = 9, + STD_VIDEO_H264_ASPECT_RATIO_IDC_18_11 = 10, + STD_VIDEO_H264_ASPECT_RATIO_IDC_15_11 = 11, + STD_VIDEO_H264_ASPECT_RATIO_IDC_64_33 = 12, + STD_VIDEO_H264_ASPECT_RATIO_IDC_160_99 = 13, + STD_VIDEO_H264_ASPECT_RATIO_IDC_4_3 = 14, + STD_VIDEO_H264_ASPECT_RATIO_IDC_3_2 = 15, + STD_VIDEO_H264_ASPECT_RATIO_IDC_2_1 = 16, + STD_VIDEO_H264_ASPECT_RATIO_IDC_EXTENDED_SAR = 255, + STD_VIDEO_H264_ASPECT_RATIO_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_ASPECT_RATIO_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264AspectRatioIdc; + +typedef enum StdVideoH264WeightedBipredIdc { + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_DEFAULT = 0, + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_EXPLICIT = 1, + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_IMPLICIT = 2, + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264WeightedBipredIdc; + +typedef enum StdVideoH264ModificationOfPicNumsIdc { + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_SHORT_TERM_SUBTRACT = 0, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_SHORT_TERM_ADD = 1, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_LONG_TERM = 2, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_END = 3, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264ModificationOfPicNumsIdc; + +typedef enum StdVideoH264MemMgmtControlOp { + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_END = 0, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_SHORT_TERM = 1, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_LONG_TERM = 2, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MARK_LONG_TERM = 3, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_SET_MAX_LONG_TERM_INDEX = 4, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_ALL = 5, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MARK_CURRENT_AS_LONG_TERM = 6, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264MemMgmtControlOp; + +typedef enum StdVideoH264CabacInitIdc { + STD_VIDEO_H264_CABAC_INIT_IDC_0 = 0, + STD_VIDEO_H264_CABAC_INIT_IDC_1 = 1, + STD_VIDEO_H264_CABAC_INIT_IDC_2 = 2, + STD_VIDEO_H264_CABAC_INIT_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_CABAC_INIT_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264CabacInitIdc; + +typedef enum StdVideoH264DisableDeblockingFilterIdc { + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_DISABLED = 0, + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_ENABLED = 1, + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_PARTIAL = 2, + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264DisableDeblockingFilterIdc; + +typedef enum StdVideoH264SliceType { + STD_VIDEO_H264_SLICE_TYPE_P = 0, + STD_VIDEO_H264_SLICE_TYPE_B = 1, + STD_VIDEO_H264_SLICE_TYPE_I = 2, + STD_VIDEO_H264_SLICE_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_SLICE_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264SliceType; + +typedef enum StdVideoH264PictureType { + STD_VIDEO_H264_PICTURE_TYPE_P = 0, + STD_VIDEO_H264_PICTURE_TYPE_B = 1, + STD_VIDEO_H264_PICTURE_TYPE_I = 2, + STD_VIDEO_H264_PICTURE_TYPE_IDR = 5, + STD_VIDEO_H264_PICTURE_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_PICTURE_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264PictureType; + +typedef enum StdVideoH264NonVclNaluType { + STD_VIDEO_H264_NON_VCL_NALU_TYPE_SPS = 0, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_PPS = 1, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_AUD = 2, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_PREFIX = 3, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_END_OF_SEQUENCE = 4, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_END_OF_STREAM = 5, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_PRECODED = 6, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264NonVclNaluType; +typedef struct StdVideoH264SpsVuiFlags { + uint32_t aspect_ratio_info_present_flag : 1; + uint32_t overscan_info_present_flag : 1; + uint32_t overscan_appropriate_flag : 1; + uint32_t video_signal_type_present_flag : 1; + uint32_t video_full_range_flag : 1; + uint32_t color_description_present_flag : 1; + uint32_t chroma_loc_info_present_flag : 1; + uint32_t timing_info_present_flag : 1; + uint32_t fixed_frame_rate_flag : 1; + uint32_t bitstream_restriction_flag : 1; + uint32_t nal_hrd_parameters_present_flag : 1; + uint32_t vcl_hrd_parameters_present_flag : 1; +} StdVideoH264SpsVuiFlags; + +typedef struct StdVideoH264HrdParameters { + uint8_t cpb_cnt_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t reserved1; + uint32_t bit_rate_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE]; + uint32_t cpb_size_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE]; + uint8_t cbr_flag[STD_VIDEO_H264_CPB_CNT_LIST_SIZE]; + uint32_t initial_cpb_removal_delay_length_minus1; + uint32_t cpb_removal_delay_length_minus1; + uint32_t dpb_output_delay_length_minus1; + uint32_t time_offset_length; +} StdVideoH264HrdParameters; + +typedef struct StdVideoH264SequenceParameterSetVui { + StdVideoH264SpsVuiFlags flags; + StdVideoH264AspectRatioIdc aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + uint8_t video_format; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t max_num_reorder_frames; + uint8_t max_dec_frame_buffering; + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + uint32_t reserved1; + const StdVideoH264HrdParameters* pHrdParameters; +} StdVideoH264SequenceParameterSetVui; + +typedef struct StdVideoH264SpsFlags { + uint32_t constraint_set0_flag : 1; + uint32_t constraint_set1_flag : 1; + uint32_t constraint_set2_flag : 1; + uint32_t constraint_set3_flag : 1; + uint32_t constraint_set4_flag : 1; + uint32_t constraint_set5_flag : 1; + uint32_t direct_8x8_inference_flag : 1; + uint32_t mb_adaptive_frame_field_flag : 1; + uint32_t frame_mbs_only_flag : 1; + uint32_t delta_pic_order_always_zero_flag : 1; + uint32_t separate_colour_plane_flag : 1; + uint32_t gaps_in_frame_num_value_allowed_flag : 1; + uint32_t qpprime_y_zero_transform_bypass_flag : 1; + uint32_t frame_cropping_flag : 1; + uint32_t seq_scaling_matrix_present_flag : 1; + uint32_t vui_parameters_present_flag : 1; +} StdVideoH264SpsFlags; + +typedef struct StdVideoH264ScalingLists { + uint16_t scaling_list_present_mask; + uint16_t use_default_scaling_matrix_mask; + uint8_t ScalingList4x4[STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS]; + uint8_t ScalingList8x8[STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS]; +} StdVideoH264ScalingLists; + +typedef struct StdVideoH264SequenceParameterSet { + StdVideoH264SpsFlags flags; + StdVideoH264ProfileIdc profile_idc; + StdVideoH264LevelIdc level_idc; + StdVideoH264ChromaFormatIdc chroma_format_idc; + uint8_t seq_parameter_set_id; + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + uint8_t log2_max_frame_num_minus4; + StdVideoH264PocType pic_order_cnt_type; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint8_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t num_ref_frames_in_pic_order_cnt_cycle; + uint8_t max_num_ref_frames; + uint8_t reserved1; + uint32_t pic_width_in_mbs_minus1; + uint32_t pic_height_in_map_units_minus1; + uint32_t frame_crop_left_offset; + uint32_t frame_crop_right_offset; + uint32_t frame_crop_top_offset; + uint32_t frame_crop_bottom_offset; + uint32_t reserved2; + const int32_t* pOffsetForRefFrame; + const StdVideoH264ScalingLists* pScalingLists; + const StdVideoH264SequenceParameterSetVui* pSequenceParameterSetVui; +} StdVideoH264SequenceParameterSet; + +typedef struct StdVideoH264PpsFlags { + uint32_t transform_8x8_mode_flag : 1; + uint32_t redundant_pic_cnt_present_flag : 1; + uint32_t constrained_intra_pred_flag : 1; + uint32_t deblocking_filter_control_present_flag : 1; + uint32_t weighted_pred_flag : 1; + uint32_t bottom_field_pic_order_in_frame_present_flag : 1; + uint32_t entropy_coding_mode_flag : 1; + uint32_t pic_scaling_matrix_present_flag : 1; +} StdVideoH264PpsFlags; + +typedef struct StdVideoH264PictureParameterSet { + StdVideoH264PpsFlags flags; + uint8_t seq_parameter_set_id; + uint8_t pic_parameter_set_id; + uint8_t num_ref_idx_l0_default_active_minus1; + uint8_t num_ref_idx_l1_default_active_minus1; + StdVideoH264WeightedBipredIdc weighted_bipred_idc; + int8_t pic_init_qp_minus26; + int8_t pic_init_qs_minus26; + int8_t chroma_qp_index_offset; + int8_t second_chroma_qp_index_offset; + const StdVideoH264ScalingLists* pScalingLists; +} StdVideoH264PictureParameterSet; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std_decode.h b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std_decode.h new file mode 100644 index 0000000000..dd24112e2c --- /dev/null +++ b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std_decode.h @@ -0,0 +1,77 @@ +#ifndef VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ +#define VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ 1 + +/* +** Copyright 2015-2023 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h264std_decode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h264std_decode 1 +#include "vulkan_video_codec_h264std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_decode" +#define STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE 2 + +typedef enum StdVideoDecodeH264FieldOrderCount { + STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_TOP = 0, + STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_BOTTOM = 1, + STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_INVALID = 0x7FFFFFFF, + STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_MAX_ENUM = 0x7FFFFFFF +} StdVideoDecodeH264FieldOrderCount; +typedef struct StdVideoDecodeH264PictureInfoFlags { + uint32_t field_pic_flag : 1; + uint32_t is_intra : 1; + uint32_t IdrPicFlag : 1; + uint32_t bottom_field_flag : 1; + uint32_t is_reference : 1; + uint32_t complementary_field_pair : 1; +} StdVideoDecodeH264PictureInfoFlags; + +typedef struct StdVideoDecodeH264PictureInfo { + StdVideoDecodeH264PictureInfoFlags flags; + uint8_t seq_parameter_set_id; + uint8_t pic_parameter_set_id; + uint8_t reserved1; + uint8_t reserved2; + uint16_t frame_num; + uint16_t idr_pic_id; + int32_t PicOrderCnt[STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE]; +} StdVideoDecodeH264PictureInfo; + +typedef struct StdVideoDecodeH264ReferenceInfoFlags { + uint32_t top_field_flag : 1; + uint32_t bottom_field_flag : 1; + uint32_t used_for_long_term_reference : 1; + uint32_t is_non_existing : 1; +} StdVideoDecodeH264ReferenceInfoFlags; + +typedef struct StdVideoDecodeH264ReferenceInfo { + StdVideoDecodeH264ReferenceInfoFlags flags; + uint16_t FrameNum; + uint16_t reserved; + int32_t PicOrderCnt[STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE]; +} StdVideoDecodeH264ReferenceInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std_encode.h b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std_encode.h new file mode 100644 index 0000000000..58b8bdb2f6 --- /dev/null +++ b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h264std_encode.h @@ -0,0 +1,147 @@ +#ifndef VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ +#define VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ 1 + +/* +** Copyright 2015-2023 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h264std_encode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h264std_encode 1 +#include "vulkan_video_codec_h264std.h" +// Vulkan 0.9 provisional Vulkan video H.264 encode std specification version number +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_11 VK_MAKE_VIDEO_STD_VERSION(0, 9, 11) + +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_11 +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_encode" +typedef struct StdVideoEncodeH264WeightTableFlags { + uint32_t luma_weight_l0_flag; + uint32_t chroma_weight_l0_flag; + uint32_t luma_weight_l1_flag; + uint32_t chroma_weight_l1_flag; +} StdVideoEncodeH264WeightTableFlags; + +typedef struct StdVideoEncodeH264WeightTable { + StdVideoEncodeH264WeightTableFlags flags; + uint8_t luma_log2_weight_denom; + uint8_t chroma_log2_weight_denom; + int8_t luma_weight_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + int8_t luma_offset_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + int8_t chroma_weight_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES]; + int8_t chroma_offset_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES]; + int8_t luma_weight_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + int8_t luma_offset_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + int8_t chroma_weight_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES]; + int8_t chroma_offset_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES]; +} StdVideoEncodeH264WeightTable; + +typedef struct StdVideoEncodeH264SliceHeaderFlags { + uint32_t direct_spatial_mv_pred_flag : 1; + uint32_t num_ref_idx_active_override_flag : 1; + uint32_t reserved : 30; +} StdVideoEncodeH264SliceHeaderFlags; + +typedef struct StdVideoEncodeH264PictureInfoFlags { + uint32_t IdrPicFlag : 1; + uint32_t is_reference : 1; + uint32_t no_output_of_prior_pics_flag : 1; + uint32_t long_term_reference_flag : 1; + uint32_t adaptive_ref_pic_marking_mode_flag : 1; + uint32_t reserved : 27; +} StdVideoEncodeH264PictureInfoFlags; + +typedef struct StdVideoEncodeH264ReferenceInfoFlags { + uint32_t used_for_long_term_reference : 1; + uint32_t reserved : 31; +} StdVideoEncodeH264ReferenceInfoFlags; + +typedef struct StdVideoEncodeH264ReferenceListsInfoFlags { + uint32_t ref_pic_list_modification_flag_l0 : 1; + uint32_t ref_pic_list_modification_flag_l1 : 1; + uint32_t reserved : 30; +} StdVideoEncodeH264ReferenceListsInfoFlags; + +typedef struct StdVideoEncodeH264RefListModEntry { + StdVideoH264ModificationOfPicNumsIdc modification_of_pic_nums_idc; + uint16_t abs_diff_pic_num_minus1; + uint16_t long_term_pic_num; +} StdVideoEncodeH264RefListModEntry; + +typedef struct StdVideoEncodeH264RefPicMarkingEntry { + StdVideoH264MemMgmtControlOp memory_management_control_operation; + uint16_t difference_of_pic_nums_minus1; + uint16_t long_term_pic_num; + uint16_t long_term_frame_idx; + uint16_t max_long_term_frame_idx_plus1; +} StdVideoEncodeH264RefPicMarkingEntry; + +typedef struct StdVideoEncodeH264ReferenceListsInfo { + StdVideoEncodeH264ReferenceListsInfoFlags flags; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + uint8_t RefPicList0[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + uint8_t RefPicList1[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + uint8_t refList0ModOpCount; + uint8_t refList1ModOpCount; + uint8_t refPicMarkingOpCount; + uint8_t reserved1[7]; + const StdVideoEncodeH264RefListModEntry* pRefList0ModOperations; + const StdVideoEncodeH264RefListModEntry* pRefList1ModOperations; + const StdVideoEncodeH264RefPicMarkingEntry* pRefPicMarkingOperations; +} StdVideoEncodeH264ReferenceListsInfo; + +typedef struct StdVideoEncodeH264PictureInfo { + StdVideoEncodeH264PictureInfoFlags flags; + uint8_t seq_parameter_set_id; + uint8_t pic_parameter_set_id; + uint16_t idr_pic_id; + StdVideoH264PictureType primary_pic_type; + uint32_t frame_num; + int32_t PicOrderCnt; + uint8_t temporal_id; + uint8_t reserved1[3]; + const StdVideoEncodeH264ReferenceListsInfo* pRefLists; +} StdVideoEncodeH264PictureInfo; + +typedef struct StdVideoEncodeH264ReferenceInfo { + StdVideoEncodeH264ReferenceInfoFlags flags; + StdVideoH264PictureType primary_pic_type; + uint32_t FrameNum; + int32_t PicOrderCnt; + uint16_t long_term_pic_num; + uint16_t long_term_frame_idx; + uint8_t temporal_id; +} StdVideoEncodeH264ReferenceInfo; + +typedef struct StdVideoEncodeH264SliceHeader { + StdVideoEncodeH264SliceHeaderFlags flags; + uint32_t first_mb_in_slice; + StdVideoH264SliceType slice_type; + int8_t slice_alpha_c0_offset_div2; + int8_t slice_beta_offset_div2; + int8_t slice_qp_delta; + uint8_t reserved1; + StdVideoH264CabacInitIdc cabac_init_idc; + StdVideoH264DisableDeblockingFilterIdc disable_deblocking_filter_idc; + const StdVideoEncodeH264WeightTable* pWeightTable; +} StdVideoEncodeH264SliceHeader; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std.h b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std.h new file mode 100644 index 0000000000..ff5d0dacbf --- /dev/null +++ b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std.h @@ -0,0 +1,446 @@ +#ifndef VULKAN_VIDEO_CODEC_H265STD_H_ +#define VULKAN_VIDEO_CODEC_H265STD_H_ 1 + +/* +** Copyright 2015-2023 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h265std is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h265std 1 +#include "vulkan_video_codecs_common.h" +#define STD_VIDEO_H265_CPB_CNT_LIST_SIZE 32 +#define STD_VIDEO_H265_SUBLAYERS_LIST_SIZE 7 +#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS 6 +#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS 16 +#define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS 6 +#define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS 64 +#define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS 6 +#define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS 64 +#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS 2 +#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS 64 +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE 6 +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE 19 +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE 21 +#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE 3 +#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE 128 +#define STD_VIDEO_H265_MAX_NUM_LIST_REF 15 +#define STD_VIDEO_H265_MAX_CHROMA_PLANES 2 +#define STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS 64 +#define STD_VIDEO_H265_MAX_DPB_SIZE 16 +#define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32 +#define STD_VIDEO_H265_MAX_LONG_TERM_PICS 16 +#define STD_VIDEO_H265_MAX_DELTA_POC 48 +#define STD_VIDEO_H265_NO_REFERENCE_PICTURE 0xFF + +typedef enum StdVideoH265ChromaFormatIdc { + STD_VIDEO_H265_CHROMA_FORMAT_IDC_MONOCHROME = 0, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_420 = 1, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_422 = 2, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_444 = 3, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265ChromaFormatIdc; + +typedef enum StdVideoH265ProfileIdc { + STD_VIDEO_H265_PROFILE_IDC_MAIN = 1, + STD_VIDEO_H265_PROFILE_IDC_MAIN_10 = 2, + STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE = 3, + STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS = 4, + STD_VIDEO_H265_PROFILE_IDC_SCC_EXTENSIONS = 9, + STD_VIDEO_H265_PROFILE_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265ProfileIdc; + +typedef enum StdVideoH265LevelIdc { + STD_VIDEO_H265_LEVEL_IDC_1_0 = 0, + STD_VIDEO_H265_LEVEL_IDC_2_0 = 1, + STD_VIDEO_H265_LEVEL_IDC_2_1 = 2, + STD_VIDEO_H265_LEVEL_IDC_3_0 = 3, + STD_VIDEO_H265_LEVEL_IDC_3_1 = 4, + STD_VIDEO_H265_LEVEL_IDC_4_0 = 5, + STD_VIDEO_H265_LEVEL_IDC_4_1 = 6, + STD_VIDEO_H265_LEVEL_IDC_5_0 = 7, + STD_VIDEO_H265_LEVEL_IDC_5_1 = 8, + STD_VIDEO_H265_LEVEL_IDC_5_2 = 9, + STD_VIDEO_H265_LEVEL_IDC_6_0 = 10, + STD_VIDEO_H265_LEVEL_IDC_6_1 = 11, + STD_VIDEO_H265_LEVEL_IDC_6_2 = 12, + STD_VIDEO_H265_LEVEL_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265LevelIdc; + +typedef enum StdVideoH265SliceType { + STD_VIDEO_H265_SLICE_TYPE_B = 0, + STD_VIDEO_H265_SLICE_TYPE_P = 1, + STD_VIDEO_H265_SLICE_TYPE_I = 2, + STD_VIDEO_H265_SLICE_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_SLICE_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265SliceType; + +typedef enum StdVideoH265PictureType { + STD_VIDEO_H265_PICTURE_TYPE_P = 0, + STD_VIDEO_H265_PICTURE_TYPE_B = 1, + STD_VIDEO_H265_PICTURE_TYPE_I = 2, + STD_VIDEO_H265_PICTURE_TYPE_IDR = 3, + STD_VIDEO_H265_PICTURE_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_PICTURE_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265PictureType; + +typedef enum StdVideoH265AspectRatioIdc { + STD_VIDEO_H265_ASPECT_RATIO_IDC_UNSPECIFIED = 0, + STD_VIDEO_H265_ASPECT_RATIO_IDC_SQUARE = 1, + STD_VIDEO_H265_ASPECT_RATIO_IDC_12_11 = 2, + STD_VIDEO_H265_ASPECT_RATIO_IDC_10_11 = 3, + STD_VIDEO_H265_ASPECT_RATIO_IDC_16_11 = 4, + STD_VIDEO_H265_ASPECT_RATIO_IDC_40_33 = 5, + STD_VIDEO_H265_ASPECT_RATIO_IDC_24_11 = 6, + STD_VIDEO_H265_ASPECT_RATIO_IDC_20_11 = 7, + STD_VIDEO_H265_ASPECT_RATIO_IDC_32_11 = 8, + STD_VIDEO_H265_ASPECT_RATIO_IDC_80_33 = 9, + STD_VIDEO_H265_ASPECT_RATIO_IDC_18_11 = 10, + STD_VIDEO_H265_ASPECT_RATIO_IDC_15_11 = 11, + STD_VIDEO_H265_ASPECT_RATIO_IDC_64_33 = 12, + STD_VIDEO_H265_ASPECT_RATIO_IDC_160_99 = 13, + STD_VIDEO_H265_ASPECT_RATIO_IDC_4_3 = 14, + STD_VIDEO_H265_ASPECT_RATIO_IDC_3_2 = 15, + STD_VIDEO_H265_ASPECT_RATIO_IDC_2_1 = 16, + STD_VIDEO_H265_ASPECT_RATIO_IDC_EXTENDED_SAR = 255, + STD_VIDEO_H265_ASPECT_RATIO_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_ASPECT_RATIO_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265AspectRatioIdc; +typedef struct StdVideoH265DecPicBufMgr { + uint32_t max_latency_increase_plus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; + uint8_t max_dec_pic_buffering_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; + uint8_t max_num_reorder_pics[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; +} StdVideoH265DecPicBufMgr; + +typedef struct StdVideoH265SubLayerHrdParameters { + uint32_t bit_rate_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; + uint32_t cpb_size_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; + uint32_t cpb_size_du_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; + uint32_t bit_rate_du_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; + uint32_t cbr_flag; +} StdVideoH265SubLayerHrdParameters; + +typedef struct StdVideoH265HrdFlags { + uint32_t nal_hrd_parameters_present_flag : 1; + uint32_t vcl_hrd_parameters_present_flag : 1; + uint32_t sub_pic_hrd_params_present_flag : 1; + uint32_t sub_pic_cpb_params_in_pic_timing_sei_flag : 1; + uint32_t fixed_pic_rate_general_flag : 8; + uint32_t fixed_pic_rate_within_cvs_flag : 8; + uint32_t low_delay_hrd_flag : 8; +} StdVideoH265HrdFlags; + +typedef struct StdVideoH265HrdParameters { + StdVideoH265HrdFlags flags; + uint8_t tick_divisor_minus2; + uint8_t du_cpb_removal_delay_increment_length_minus1; + uint8_t dpb_output_delay_du_length_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t cpb_size_du_scale; + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t au_cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t cpb_cnt_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; + uint16_t elemental_duration_in_tc_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; + uint16_t reserved[3]; + const StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersNal; + const StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersVcl; +} StdVideoH265HrdParameters; + +typedef struct StdVideoH265VpsFlags { + uint32_t vps_temporal_id_nesting_flag : 1; + uint32_t vps_sub_layer_ordering_info_present_flag : 1; + uint32_t vps_timing_info_present_flag : 1; + uint32_t vps_poc_proportional_to_timing_flag : 1; +} StdVideoH265VpsFlags; + +typedef struct StdVideoH265ProfileTierLevelFlags { + uint32_t general_tier_flag : 1; + uint32_t general_progressive_source_flag : 1; + uint32_t general_interlaced_source_flag : 1; + uint32_t general_non_packed_constraint_flag : 1; + uint32_t general_frame_only_constraint_flag : 1; +} StdVideoH265ProfileTierLevelFlags; + +typedef struct StdVideoH265ProfileTierLevel { + StdVideoH265ProfileTierLevelFlags flags; + StdVideoH265ProfileIdc general_profile_idc; + StdVideoH265LevelIdc general_level_idc; +} StdVideoH265ProfileTierLevel; + +typedef struct StdVideoH265VideoParameterSet { + StdVideoH265VpsFlags flags; + uint8_t vps_video_parameter_set_id; + uint8_t vps_max_sub_layers_minus1; + uint8_t reserved1; + uint8_t reserved2; + uint32_t vps_num_units_in_tick; + uint32_t vps_time_scale; + uint32_t vps_num_ticks_poc_diff_one_minus1; + uint32_t reserved3; + const StdVideoH265DecPicBufMgr* pDecPicBufMgr; + const StdVideoH265HrdParameters* pHrdParameters; + const StdVideoH265ProfileTierLevel* pProfileTierLevel; +} StdVideoH265VideoParameterSet; + +typedef struct StdVideoH265ScalingLists { + uint8_t ScalingList4x4[STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS]; + uint8_t ScalingList8x8[STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS]; + uint8_t ScalingList16x16[STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS]; + uint8_t ScalingList32x32[STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS]; + uint8_t ScalingListDCCoef16x16[STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS]; + uint8_t ScalingListDCCoef32x32[STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS]; +} StdVideoH265ScalingLists; + +typedef struct StdVideoH265SpsVuiFlags { + uint32_t aspect_ratio_info_present_flag : 1; + uint32_t overscan_info_present_flag : 1; + uint32_t overscan_appropriate_flag : 1; + uint32_t video_signal_type_present_flag : 1; + uint32_t video_full_range_flag : 1; + uint32_t colour_description_present_flag : 1; + uint32_t chroma_loc_info_present_flag : 1; + uint32_t neutral_chroma_indication_flag : 1; + uint32_t field_seq_flag : 1; + uint32_t frame_field_info_present_flag : 1; + uint32_t default_display_window_flag : 1; + uint32_t vui_timing_info_present_flag : 1; + uint32_t vui_poc_proportional_to_timing_flag : 1; + uint32_t vui_hrd_parameters_present_flag : 1; + uint32_t bitstream_restriction_flag : 1; + uint32_t tiles_fixed_structure_flag : 1; + uint32_t motion_vectors_over_pic_boundaries_flag : 1; + uint32_t restricted_ref_pic_lists_flag : 1; +} StdVideoH265SpsVuiFlags; + +typedef struct StdVideoH265SequenceParameterSetVui { + StdVideoH265SpsVuiFlags flags; + StdVideoH265AspectRatioIdc aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + uint8_t video_format; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coeffs; + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + uint8_t reserved1; + uint8_t reserved2; + uint16_t def_disp_win_left_offset; + uint16_t def_disp_win_right_offset; + uint16_t def_disp_win_top_offset; + uint16_t def_disp_win_bottom_offset; + uint32_t vui_num_units_in_tick; + uint32_t vui_time_scale; + uint32_t vui_num_ticks_poc_diff_one_minus1; + uint16_t min_spatial_segmentation_idc; + uint16_t reserved3; + uint8_t max_bytes_per_pic_denom; + uint8_t max_bits_per_min_cu_denom; + uint8_t log2_max_mv_length_horizontal; + uint8_t log2_max_mv_length_vertical; + const StdVideoH265HrdParameters* pHrdParameters; +} StdVideoH265SequenceParameterSetVui; + +typedef struct StdVideoH265PredictorPaletteEntries { + uint16_t PredictorPaletteEntries[STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE][STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE]; +} StdVideoH265PredictorPaletteEntries; + +typedef struct StdVideoH265SpsFlags { + uint32_t sps_temporal_id_nesting_flag : 1; + uint32_t separate_colour_plane_flag : 1; + uint32_t conformance_window_flag : 1; + uint32_t sps_sub_layer_ordering_info_present_flag : 1; + uint32_t scaling_list_enabled_flag : 1; + uint32_t sps_scaling_list_data_present_flag : 1; + uint32_t amp_enabled_flag : 1; + uint32_t sample_adaptive_offset_enabled_flag : 1; + uint32_t pcm_enabled_flag : 1; + uint32_t pcm_loop_filter_disabled_flag : 1; + uint32_t long_term_ref_pics_present_flag : 1; + uint32_t sps_temporal_mvp_enabled_flag : 1; + uint32_t strong_intra_smoothing_enabled_flag : 1; + uint32_t vui_parameters_present_flag : 1; + uint32_t sps_extension_present_flag : 1; + uint32_t sps_range_extension_flag : 1; + uint32_t transform_skip_rotation_enabled_flag : 1; + uint32_t transform_skip_context_enabled_flag : 1; + uint32_t implicit_rdpcm_enabled_flag : 1; + uint32_t explicit_rdpcm_enabled_flag : 1; + uint32_t extended_precision_processing_flag : 1; + uint32_t intra_smoothing_disabled_flag : 1; + uint32_t high_precision_offsets_enabled_flag : 1; + uint32_t persistent_rice_adaptation_enabled_flag : 1; + uint32_t cabac_bypass_alignment_enabled_flag : 1; + uint32_t sps_scc_extension_flag : 1; + uint32_t sps_curr_pic_ref_enabled_flag : 1; + uint32_t palette_mode_enabled_flag : 1; + uint32_t sps_palette_predictor_initializers_present_flag : 1; + uint32_t intra_boundary_filtering_disabled_flag : 1; +} StdVideoH265SpsFlags; + +typedef struct StdVideoH265ShortTermRefPicSetFlags { + uint32_t inter_ref_pic_set_prediction_flag : 1; + uint32_t delta_rps_sign : 1; +} StdVideoH265ShortTermRefPicSetFlags; + +typedef struct StdVideoH265ShortTermRefPicSet { + StdVideoH265ShortTermRefPicSetFlags flags; + uint32_t delta_idx_minus1; + uint16_t use_delta_flag; + uint16_t abs_delta_rps_minus1; + uint16_t used_by_curr_pic_flag; + uint16_t used_by_curr_pic_s0_flag; + uint16_t used_by_curr_pic_s1_flag; + uint16_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + uint8_t num_negative_pics; + uint8_t num_positive_pics; + uint16_t delta_poc_s0_minus1[STD_VIDEO_H265_MAX_DPB_SIZE]; + uint16_t delta_poc_s1_minus1[STD_VIDEO_H265_MAX_DPB_SIZE]; +} StdVideoH265ShortTermRefPicSet; + +typedef struct StdVideoH265LongTermRefPicsSps { + uint32_t used_by_curr_pic_lt_sps_flag; + uint32_t lt_ref_pic_poc_lsb_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS]; +} StdVideoH265LongTermRefPicsSps; + +typedef struct StdVideoH265SequenceParameterSet { + StdVideoH265SpsFlags flags; + StdVideoH265ChromaFormatIdc chroma_format_idc; + uint32_t pic_width_in_luma_samples; + uint32_t pic_height_in_luma_samples; + uint8_t sps_video_parameter_set_id; + uint8_t sps_max_sub_layers_minus1; + uint8_t sps_seq_parameter_set_id; + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + uint8_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t log2_min_luma_coding_block_size_minus3; + uint8_t log2_diff_max_min_luma_coding_block_size; + uint8_t log2_min_luma_transform_block_size_minus2; + uint8_t log2_diff_max_min_luma_transform_block_size; + uint8_t max_transform_hierarchy_depth_inter; + uint8_t max_transform_hierarchy_depth_intra; + uint8_t num_short_term_ref_pic_sets; + uint8_t num_long_term_ref_pics_sps; + uint8_t pcm_sample_bit_depth_luma_minus1; + uint8_t pcm_sample_bit_depth_chroma_minus1; + uint8_t log2_min_pcm_luma_coding_block_size_minus3; + uint8_t log2_diff_max_min_pcm_luma_coding_block_size; + uint8_t reserved1; + uint8_t reserved2; + uint8_t palette_max_size; + uint8_t delta_palette_max_predictor_size; + uint8_t motion_vector_resolution_control_idc; + uint8_t sps_num_palette_predictor_initializers_minus1; + uint32_t conf_win_left_offset; + uint32_t conf_win_right_offset; + uint32_t conf_win_top_offset; + uint32_t conf_win_bottom_offset; + const StdVideoH265ProfileTierLevel* pProfileTierLevel; + const StdVideoH265DecPicBufMgr* pDecPicBufMgr; + const StdVideoH265ScalingLists* pScalingLists; + const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet; + const StdVideoH265LongTermRefPicsSps* pLongTermRefPicsSps; + const StdVideoH265SequenceParameterSetVui* pSequenceParameterSetVui; + const StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries; +} StdVideoH265SequenceParameterSet; + +typedef struct StdVideoH265PpsFlags { + uint32_t dependent_slice_segments_enabled_flag : 1; + uint32_t output_flag_present_flag : 1; + uint32_t sign_data_hiding_enabled_flag : 1; + uint32_t cabac_init_present_flag : 1; + uint32_t constrained_intra_pred_flag : 1; + uint32_t transform_skip_enabled_flag : 1; + uint32_t cu_qp_delta_enabled_flag : 1; + uint32_t pps_slice_chroma_qp_offsets_present_flag : 1; + uint32_t weighted_pred_flag : 1; + uint32_t weighted_bipred_flag : 1; + uint32_t transquant_bypass_enabled_flag : 1; + uint32_t tiles_enabled_flag : 1; + uint32_t entropy_coding_sync_enabled_flag : 1; + uint32_t uniform_spacing_flag : 1; + uint32_t loop_filter_across_tiles_enabled_flag : 1; + uint32_t pps_loop_filter_across_slices_enabled_flag : 1; + uint32_t deblocking_filter_control_present_flag : 1; + uint32_t deblocking_filter_override_enabled_flag : 1; + uint32_t pps_deblocking_filter_disabled_flag : 1; + uint32_t pps_scaling_list_data_present_flag : 1; + uint32_t lists_modification_present_flag : 1; + uint32_t slice_segment_header_extension_present_flag : 1; + uint32_t pps_extension_present_flag : 1; + uint32_t cross_component_prediction_enabled_flag : 1; + uint32_t chroma_qp_offset_list_enabled_flag : 1; + uint32_t pps_curr_pic_ref_enabled_flag : 1; + uint32_t residual_adaptive_colour_transform_enabled_flag : 1; + uint32_t pps_slice_act_qp_offsets_present_flag : 1; + uint32_t pps_palette_predictor_initializers_present_flag : 1; + uint32_t monochrome_palette_flag : 1; + uint32_t pps_range_extension_flag : 1; +} StdVideoH265PpsFlags; + +typedef struct StdVideoH265PictureParameterSet { + StdVideoH265PpsFlags flags; + uint8_t pps_pic_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t sps_video_parameter_set_id; + uint8_t num_extra_slice_header_bits; + uint8_t num_ref_idx_l0_default_active_minus1; + uint8_t num_ref_idx_l1_default_active_minus1; + int8_t init_qp_minus26; + uint8_t diff_cu_qp_delta_depth; + int8_t pps_cb_qp_offset; + int8_t pps_cr_qp_offset; + int8_t pps_beta_offset_div2; + int8_t pps_tc_offset_div2; + uint8_t log2_parallel_merge_level_minus2; + uint8_t log2_max_transform_skip_block_size_minus2; + uint8_t diff_cu_chroma_qp_offset_depth; + uint8_t chroma_qp_offset_list_len_minus1; + int8_t cb_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE]; + int8_t cr_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE]; + uint8_t log2_sao_offset_scale_luma; + uint8_t log2_sao_offset_scale_chroma; + int8_t pps_act_y_qp_offset_plus5; + int8_t pps_act_cb_qp_offset_plus5; + int8_t pps_act_cr_qp_offset_plus3; + uint8_t pps_num_palette_predictor_initializers; + uint8_t luma_bit_depth_entry_minus8; + uint8_t chroma_bit_depth_entry_minus8; + uint8_t num_tile_columns_minus1; + uint8_t num_tile_rows_minus1; + uint8_t reserved1; + uint8_t reserved2; + uint16_t column_width_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE]; + uint16_t row_height_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE]; + uint32_t reserved3; + const StdVideoH265ScalingLists* pScalingLists; + const StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries; +} StdVideoH265PictureParameterSet; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std_decode.h b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std_decode.h new file mode 100644 index 0000000000..75cf4d0946 --- /dev/null +++ b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std_decode.h @@ -0,0 +1,67 @@ +#ifndef VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ +#define VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ 1 + +/* +** Copyright 2015-2023 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h265std_decode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h265std_decode 1 +#include "vulkan_video_codec_h265std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_decode" +#define STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE 8 +typedef struct StdVideoDecodeH265PictureInfoFlags { + uint32_t IrapPicFlag : 1; + uint32_t IdrPicFlag : 1; + uint32_t IsReference : 1; + uint32_t short_term_ref_pic_set_sps_flag : 1; +} StdVideoDecodeH265PictureInfoFlags; + +typedef struct StdVideoDecodeH265PictureInfo { + StdVideoDecodeH265PictureInfoFlags flags; + uint8_t sps_video_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t pps_pic_parameter_set_id; + uint8_t NumDeltaPocsOfRefRpsIdx; + int32_t PicOrderCntVal; + uint16_t NumBitsForSTRefPicSetInSlice; + uint16_t reserved; + uint8_t RefPicSetStCurrBefore[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE]; + uint8_t RefPicSetStCurrAfter[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE]; + uint8_t RefPicSetLtCurr[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE]; +} StdVideoDecodeH265PictureInfo; + +typedef struct StdVideoDecodeH265ReferenceInfoFlags { + uint32_t used_for_long_term_reference : 1; + uint32_t unused_for_reference : 1; +} StdVideoDecodeH265ReferenceInfoFlags; + +typedef struct StdVideoDecodeH265ReferenceInfo { + StdVideoDecodeH265ReferenceInfoFlags flags; + int32_t PicOrderCntVal; +} StdVideoDecodeH265ReferenceInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std_encode.h b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std_encode.h new file mode 100644 index 0000000000..2a7024caba --- /dev/null +++ b/libraries/ZVulkan/include/vk_video/vulkan_video_codec_h265std_encode.h @@ -0,0 +1,157 @@ +#ifndef VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ +#define VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ 1 + +/* +** Copyright 2015-2023 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h265std_encode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h265std_encode 1 +#include "vulkan_video_codec_h265std.h" +// Vulkan 0.9 provisional Vulkan video H.265 encode std specification version number +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_12 VK_MAKE_VIDEO_STD_VERSION(0, 9, 12) + +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_12 +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_encode" +typedef struct StdVideoEncodeH265WeightTableFlags { + uint16_t luma_weight_l0_flag; + uint16_t chroma_weight_l0_flag; + uint16_t luma_weight_l1_flag; + uint16_t chroma_weight_l1_flag; +} StdVideoEncodeH265WeightTableFlags; + +typedef struct StdVideoEncodeH265WeightTable { + StdVideoEncodeH265WeightTableFlags flags; + uint8_t luma_log2_weight_denom; + int8_t delta_chroma_log2_weight_denom; + int8_t delta_luma_weight_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + int8_t luma_offset_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + int8_t delta_chroma_weight_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES]; + int8_t delta_chroma_offset_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES]; + int8_t delta_luma_weight_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + int8_t luma_offset_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + int8_t delta_chroma_weight_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES]; + int8_t delta_chroma_offset_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES]; +} StdVideoEncodeH265WeightTable; + +typedef struct StdVideoEncodeH265SliceSegmentHeaderFlags { + uint32_t first_slice_segment_in_pic_flag : 1; + uint32_t dependent_slice_segment_flag : 1; + uint32_t slice_sao_luma_flag : 1; + uint32_t slice_sao_chroma_flag : 1; + uint32_t num_ref_idx_active_override_flag : 1; + uint32_t mvd_l1_zero_flag : 1; + uint32_t cabac_init_flag : 1; + uint32_t cu_chroma_qp_offset_enabled_flag : 1; + uint32_t deblocking_filter_override_flag : 1; + uint32_t slice_deblocking_filter_disabled_flag : 1; + uint32_t collocated_from_l0_flag : 1; + uint32_t slice_loop_filter_across_slices_enabled_flag : 1; + uint32_t reserved : 20; +} StdVideoEncodeH265SliceSegmentHeaderFlags; + +typedef struct StdVideoEncodeH265SliceSegmentHeader { + StdVideoEncodeH265SliceSegmentHeaderFlags flags; + StdVideoH265SliceType slice_type; + uint32_t slice_segment_address; + uint8_t collocated_ref_idx; + uint8_t MaxNumMergeCand; + int8_t slice_cb_qp_offset; + int8_t slice_cr_qp_offset; + int8_t slice_beta_offset_div2; + int8_t slice_tc_offset_div2; + int8_t slice_act_y_qp_offset; + int8_t slice_act_cb_qp_offset; + int8_t slice_act_cr_qp_offset; + int8_t slice_qp_delta; + uint16_t reserved1; + const StdVideoEncodeH265WeightTable* pWeightTable; +} StdVideoEncodeH265SliceSegmentHeader; + +typedef struct StdVideoEncodeH265ReferenceListsInfoFlags { + uint32_t ref_pic_list_modification_flag_l0 : 1; + uint32_t ref_pic_list_modification_flag_l1 : 1; + uint32_t reserved : 30; +} StdVideoEncodeH265ReferenceListsInfoFlags; + +typedef struct StdVideoEncodeH265ReferenceListsInfo { + StdVideoEncodeH265ReferenceListsInfoFlags flags; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + uint8_t RefPicList0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + uint8_t RefPicList1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + uint8_t list_entry_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + uint8_t list_entry_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; +} StdVideoEncodeH265ReferenceListsInfo; + +typedef struct StdVideoEncodeH265PictureInfoFlags { + uint32_t is_reference : 1; + uint32_t IrapPicFlag : 1; + uint32_t used_for_long_term_reference : 1; + uint32_t discardable_flag : 1; + uint32_t cross_layer_bla_flag : 1; + uint32_t pic_output_flag : 1; + uint32_t no_output_of_prior_pics_flag : 1; + uint32_t short_term_ref_pic_set_sps_flag : 1; + uint32_t slice_temporal_mvp_enabled_flag : 1; + uint32_t reserved : 23; +} StdVideoEncodeH265PictureInfoFlags; + +typedef struct StdVideoEncodeH265LongTermRefPics { + uint8_t num_long_term_sps; + uint8_t num_long_term_pics; + uint8_t lt_idx_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS]; + uint8_t poc_lsb_lt[STD_VIDEO_H265_MAX_LONG_TERM_PICS]; + uint16_t used_by_curr_pic_lt_flag; + uint8_t delta_poc_msb_present_flag[STD_VIDEO_H265_MAX_DELTA_POC]; + uint8_t delta_poc_msb_cycle_lt[STD_VIDEO_H265_MAX_DELTA_POC]; +} StdVideoEncodeH265LongTermRefPics; + +typedef struct StdVideoEncodeH265PictureInfo { + StdVideoEncodeH265PictureInfoFlags flags; + StdVideoH265PictureType pic_type; + uint8_t sps_video_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t pps_pic_parameter_set_id; + uint8_t short_term_ref_pic_set_idx; + int32_t PicOrderCntVal; + uint8_t TemporalId; + uint8_t reserved1[7]; + const StdVideoEncodeH265ReferenceListsInfo* pRefLists; + const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet; + const StdVideoEncodeH265LongTermRefPics* pLongTermRefPics; +} StdVideoEncodeH265PictureInfo; + +typedef struct StdVideoEncodeH265ReferenceInfoFlags { + uint32_t used_for_long_term_reference : 1; + uint32_t unused_for_reference : 1; + uint32_t reserved : 30; +} StdVideoEncodeH265ReferenceInfoFlags; + +typedef struct StdVideoEncodeH265ReferenceInfo { + StdVideoEncodeH265ReferenceInfoFlags flags; + StdVideoH265PictureType pic_type; + int32_t PicOrderCntVal; + uint8_t TemporalId; +} StdVideoEncodeH265ReferenceInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/ZVulkan/include/vk_video/vulkan_video_codecs_common.h b/libraries/ZVulkan/include/vk_video/vulkan_video_codecs_common.h new file mode 100644 index 0000000000..6568975ee3 --- /dev/null +++ b/libraries/ZVulkan/include/vk_video/vulkan_video_codecs_common.h @@ -0,0 +1,36 @@ +#ifndef VULKAN_VIDEO_CODECS_COMMON_H_ +#define VULKAN_VIDEO_CODECS_COMMON_H_ 1 + +/* +** Copyright 2015-2023 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codecs_common is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codecs_common 1 +#if !defined(VK_NO_STDINT_H) + #include +#endif + +#define VK_MAKE_VIDEO_STD_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/ZVulkan/include/vulkan/vk_icd.h b/libraries/ZVulkan/include/vulkan/vk_icd.h index ae006d06d1..59204a3419 100644 --- a/libraries/ZVulkan/include/vulkan/vk_icd.h +++ b/libraries/ZVulkan/include/vulkan/vk_icd.h @@ -1,27 +1,11 @@ -// -// File: vk_icd.h -// /* - * Copyright (c) 2015-2016 The Khronos Group Inc. - * Copyright (c) 2015-2016 Valve Corporation - * Copyright (c) 2015-2016 LunarG, Inc. - * - * 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. + * Copyright 2015-2023 The Khronos Group Inc. + * Copyright 2015-2023 Valve Corporation + * Copyright 2015-2023 LunarG, Inc. * + * SPDX-License-Identifier: Apache-2.0 */ - -#ifndef VKICD_H -#define VKICD_H +#pragma once #include "vulkan.h" #include @@ -33,7 +17,7 @@ // Version 2 - Add Loader/ICD Interface version negotiation // via vk_icdNegotiateLoaderICDInterfaceVersion. // Version 3 - Add ICD creation/destruction of KHR_surface objects. -// Version 4 - Add unknown physical device extension qyering via +// Version 4 - Add unknown physical device extension querying via // vk_icdGetPhysicalDeviceProcAddr. // Version 5 - Tells ICDs that the loader is now paying attention to the // application version of Vulkan passed into the ApplicationInfo @@ -42,7 +26,17 @@ // call for any API version > 1.0. Otherwise, the loader will // manually determine if it can support the expected version. // Version 6 - Add support for vk_icdEnumerateAdapterPhysicalDevices. -#define CURRENT_LOADER_ICD_INTERFACE_VERSION 6 +// Version 7 - If an ICD supports any of the following functions, they must be +// queryable with vk_icdGetInstanceProcAddr: +// vk_icdNegotiateLoaderICDInterfaceVersion +// vk_icdGetPhysicalDeviceProcAddr +// vk_icdEnumerateAdapterPhysicalDevices (Windows only) +// In addition, these functions no longer need to be exported directly. +// This version allows drivers provided through the extension +// VK_LUNARG_direct_driver_loading be able to support the entire +// Driver-Loader interface. + +#define CURRENT_LOADER_ICD_INTERFACE_VERSION 7 #define MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION 0 #define MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION 4 @@ -70,7 +64,7 @@ extern "C" { #endif VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pVersion); VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName); - VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance isntance, const char* pName); + VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName); #if defined(VK_USE_PLATFORM_WIN32_KHR) VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); @@ -123,6 +117,7 @@ typedef enum { VK_ICD_WSI_PLATFORM_VI, VK_ICD_WSI_PLATFORM_GGP, VK_ICD_WSI_PLATFORM_SCREEN, + VK_ICD_WSI_PLATFORM_FUCHSIA, } VkIcdWsiPlatform; typedef struct { @@ -242,4 +237,8 @@ typedef struct { } VkIcdSurfaceScreen; #endif // VK_USE_PLATFORM_SCREEN_QNX -#endif // VKICD_H +#ifdef VK_USE_PLATFORM_FUCHSIA +typedef struct { + VkIcdSurfaceBase base; +} VkIcdSurfaceImagePipe; +#endif // VK_USE_PLATFORM_FUCHSIA diff --git a/libraries/ZVulkan/include/vulkan/vk_layer.h b/libraries/ZVulkan/include/vulkan/vk_layer.h index 0651870c70..19d88fce4b 100644 --- a/libraries/ZVulkan/include/vulkan/vk_layer.h +++ b/libraries/ZVulkan/include/vulkan/vk_layer.h @@ -1,39 +1,18 @@ -// -// File: vk_layer.h -// /* - * Copyright (c) 2015-2017 The Khronos Group Inc. - * Copyright (c) 2015-2017 Valve Corporation - * Copyright (c) 2015-2017 LunarG, Inc. - * - * 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. + * Copyright 2015-2023 The Khronos Group Inc. + * Copyright 2015-2023 Valve Corporation + * Copyright 2015-2023 LunarG, Inc. * + * SPDX-License-Identifier: Apache-2.0 */ +#pragma once /* Need to define dispatch table * Core struct can then have ptr to dispatch table at the top * Along with object ptrs for current and next OBJ */ -#pragma once -#include "vulkan.h" -#if defined(__GNUC__) && __GNUC__ >= 4 -#define VK_LAYER_EXPORT __attribute__((visibility("default"))) -#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) -#define VK_LAYER_EXPORT __attribute__((visibility("default"))) -#else -#define VK_LAYER_EXPORT -#endif +#include "vulkan_core.h" #define MAX_NUM_UNKNOWN_EXTS 250 diff --git a/libraries/ZVulkan/include/vulkan/vk_platform.h b/libraries/ZVulkan/include/vulkan/vk_platform.h index 18b913abc6..ed67a6004a 100644 --- a/libraries/ZVulkan/include/vulkan/vk_platform.h +++ b/libraries/ZVulkan/include/vulkan/vk_platform.h @@ -2,7 +2,7 @@ // File: vk_platform.h // /* -** Copyright 2014-2021 The Khronos Group Inc. +** Copyright 2014-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -42,7 +42,7 @@ extern "C" #define VKAPI_CALL __stdcall #define VKAPI_PTR VKAPI_CALL #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7 - #error "Vulkan isn't supported for the 'armeabi' NDK ABI" + #error "Vulkan is not supported for the 'armeabi' NDK ABI" #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE) // On Android 32-bit ARM targets, Vulkan functions use the "hardfloat" // calling convention, i.e. float parameters are passed in registers. This diff --git a/libraries/ZVulkan/include/vulkan/vulkan.h b/libraries/ZVulkan/include/vulkan/vulkan.h index 3f7cdba584..426cff58d7 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan.h +++ b/libraries/ZVulkan/include/vulkan/vulkan.h @@ -2,7 +2,7 @@ #define VULKAN_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -38,7 +38,6 @@ #ifdef VK_USE_PLATFORM_WAYLAND_KHR -#include #include "vulkan_wayland.h" #endif @@ -85,6 +84,14 @@ #include "vulkan_screen.h" #endif + +#ifdef VK_USE_PLATFORM_SCI +#include +#include +#include "vulkan_sci.h" +#endif + + #ifdef VK_ENABLE_BETA_EXTENSIONS #include "vulkan_beta.h" #endif diff --git a/libraries/ZVulkan/include/vulkan/vulkan_android.h b/libraries/ZVulkan/include/vulkan/vulkan_android.h index 2160e3e7c6..40b3c67ba6 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_android.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_android.h @@ -2,7 +2,7 @@ #define VULKAN_ANDROID_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_KHR_android_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_android_surface 1 struct ANativeWindow; #define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6 @@ -42,9 +43,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( #endif +// VK_ANDROID_external_memory_android_hardware_buffer is a preprocessor guard. Do not pass it to API calls. #define VK_ANDROID_external_memory_android_hardware_buffer 1 struct AHardwareBuffer; -#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3 +#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 5 #define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer" typedef struct VkAndroidHardwareBufferUsageANDROID { VkStructureType sType; @@ -90,6 +92,19 @@ typedef struct VkExternalFormatANDROID { uint64_t externalFormat; } VkExternalFormatANDROID; +typedef struct VkAndroidHardwareBufferFormatProperties2ANDROID { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + VkFormatFeatureFlags2 formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkAndroidHardwareBufferFormatProperties2ANDROID; + typedef VkResult (VKAPI_PTR *PFN_vkGetAndroidHardwareBufferPropertiesANDROID)(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties); typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryAndroidHardwareBufferANDROID)(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer); @@ -105,6 +120,32 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID( struct AHardwareBuffer** pBuffer); #endif + +// VK_ANDROID_external_format_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_ANDROID_external_format_resolve 1 +#define VK_ANDROID_EXTERNAL_FORMAT_RESOLVE_SPEC_VERSION 1 +#define VK_ANDROID_EXTERNAL_FORMAT_RESOLVE_EXTENSION_NAME "VK_ANDROID_external_format_resolve" +typedef struct VkPhysicalDeviceExternalFormatResolveFeaturesANDROID { + VkStructureType sType; + void* pNext; + VkBool32 externalFormatResolve; +} VkPhysicalDeviceExternalFormatResolveFeaturesANDROID; + +typedef struct VkPhysicalDeviceExternalFormatResolvePropertiesANDROID { + VkStructureType sType; + void* pNext; + VkBool32 nullColorAttachmentWithExternalFormatResolve; + VkChromaLocation externalFormatResolveChromaOffsetX; + VkChromaLocation externalFormatResolveChromaOffsetY; +} VkPhysicalDeviceExternalFormatResolvePropertiesANDROID; + +typedef struct VkAndroidHardwareBufferFormatResolvePropertiesANDROID { + VkStructureType sType; + void* pNext; + VkFormat colorAttachmentFormat; +} VkAndroidHardwareBufferFormatResolvePropertiesANDROID; + + #ifdef __cplusplus } #endif diff --git a/libraries/ZVulkan/include/vulkan/vulkan_beta.h b/libraries/ZVulkan/include/vulkan/vulkan_beta.h index e2337adfde..1871651d26 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_beta.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_beta.h @@ -2,7 +2,7 @@ #define VULKAN_BETA_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,325 +19,7 @@ extern "C" { -#define VK_KHR_video_queue 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionKHR) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionParametersKHR) -#define VK_KHR_VIDEO_QUEUE_SPEC_VERSION 2 -#define VK_KHR_VIDEO_QUEUE_EXTENSION_NAME "VK_KHR_video_queue" - -typedef enum VkQueryResultStatusKHR { - VK_QUERY_RESULT_STATUS_ERROR_KHR = -1, - VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0, - VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1, - VK_QUERY_RESULT_STATUS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkQueryResultStatusKHR; - -typedef enum VkVideoCodecOperationFlagBitsKHR { - VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR = 0, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT = 0x00010000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_EXT = 0x00000001, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_EXT = 0x00000002, -#endif - VK_VIDEO_CODEC_OPERATION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoCodecOperationFlagBitsKHR; -typedef VkFlags VkVideoCodecOperationFlagsKHR; - -typedef enum VkVideoChromaSubsamplingFlagBitsKHR { - VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_BIT_KHR = 0, - VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0x00000001, - VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0x00000002, - VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0x00000004, - VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR = 0x00000008, - VK_VIDEO_CHROMA_SUBSAMPLING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoChromaSubsamplingFlagBitsKHR; -typedef VkFlags VkVideoChromaSubsamplingFlagsKHR; - -typedef enum VkVideoComponentBitDepthFlagBitsKHR { - VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR = 0, - VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR = 0x00000001, - VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR = 0x00000004, - VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR = 0x00000010, - VK_VIDEO_COMPONENT_BIT_DEPTH_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoComponentBitDepthFlagBitsKHR; -typedef VkFlags VkVideoComponentBitDepthFlagsKHR; - -typedef enum VkVideoCapabilityFlagBitsKHR { - VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR = 0x00000001, - VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR = 0x00000002, - VK_VIDEO_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoCapabilityFlagBitsKHR; -typedef VkFlags VkVideoCapabilityFlagsKHR; - -typedef enum VkVideoSessionCreateFlagBitsKHR { - VK_VIDEO_SESSION_CREATE_DEFAULT_KHR = 0, - VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0x00000001, - VK_VIDEO_SESSION_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoSessionCreateFlagBitsKHR; -typedef VkFlags VkVideoSessionCreateFlagsKHR; -typedef VkFlags VkVideoBeginCodingFlagsKHR; -typedef VkFlags VkVideoEndCodingFlagsKHR; - -typedef enum VkVideoCodingControlFlagBitsKHR { - VK_VIDEO_CODING_CONTROL_DEFAULT_KHR = 0, - VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0x00000001, - VK_VIDEO_CODING_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoCodingControlFlagBitsKHR; -typedef VkFlags VkVideoCodingControlFlagsKHR; - -typedef enum VkVideoCodingQualityPresetFlagBitsKHR { - VK_VIDEO_CODING_QUALITY_PRESET_DEFAULT_BIT_KHR = 0, - VK_VIDEO_CODING_QUALITY_PRESET_NORMAL_BIT_KHR = 0x00000001, - VK_VIDEO_CODING_QUALITY_PRESET_POWER_BIT_KHR = 0x00000002, - VK_VIDEO_CODING_QUALITY_PRESET_QUALITY_BIT_KHR = 0x00000004, - VK_VIDEO_CODING_QUALITY_PRESET_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoCodingQualityPresetFlagBitsKHR; -typedef VkFlags VkVideoCodingQualityPresetFlagsKHR; -typedef struct VkVideoQueueFamilyProperties2KHR { - VkStructureType sType; - void* pNext; - VkVideoCodecOperationFlagsKHR videoCodecOperations; -} VkVideoQueueFamilyProperties2KHR; - -typedef struct VkVideoProfileKHR { - VkStructureType sType; - void* pNext; - VkVideoCodecOperationFlagBitsKHR videoCodecOperation; - VkVideoChromaSubsamplingFlagsKHR chromaSubsampling; - VkVideoComponentBitDepthFlagsKHR lumaBitDepth; - VkVideoComponentBitDepthFlagsKHR chromaBitDepth; -} VkVideoProfileKHR; - -typedef struct VkVideoProfilesKHR { - VkStructureType sType; - void* pNext; - uint32_t profileCount; - const VkVideoProfileKHR* pProfiles; -} VkVideoProfilesKHR; - -typedef struct VkVideoCapabilitiesKHR { - VkStructureType sType; - void* pNext; - VkVideoCapabilityFlagsKHR capabilityFlags; - VkDeviceSize minBitstreamBufferOffsetAlignment; - VkDeviceSize minBitstreamBufferSizeAlignment; - VkExtent2D videoPictureExtentGranularity; - VkExtent2D minExtent; - VkExtent2D maxExtent; - uint32_t maxReferencePicturesSlotsCount; - uint32_t maxReferencePicturesActiveCount; -} VkVideoCapabilitiesKHR; - -typedef struct VkPhysicalDeviceVideoFormatInfoKHR { - VkStructureType sType; - void* pNext; - VkImageUsageFlags imageUsage; - const VkVideoProfilesKHR* pVideoProfiles; -} VkPhysicalDeviceVideoFormatInfoKHR; - -typedef struct VkVideoFormatPropertiesKHR { - VkStructureType sType; - void* pNext; - VkFormat format; -} VkVideoFormatPropertiesKHR; - -typedef struct VkVideoPictureResourceKHR { - VkStructureType sType; - const void* pNext; - VkOffset2D codedOffset; - VkExtent2D codedExtent; - uint32_t baseArrayLayer; - VkImageView imageViewBinding; -} VkVideoPictureResourceKHR; - -typedef struct VkVideoReferenceSlotKHR { - VkStructureType sType; - const void* pNext; - int8_t slotIndex; - const VkVideoPictureResourceKHR* pPictureResource; -} VkVideoReferenceSlotKHR; - -typedef struct VkVideoGetMemoryPropertiesKHR { - VkStructureType sType; - const void* pNext; - uint32_t memoryBindIndex; - VkMemoryRequirements2* pMemoryRequirements; -} VkVideoGetMemoryPropertiesKHR; - -typedef struct VkVideoBindMemoryKHR { - VkStructureType sType; - const void* pNext; - uint32_t memoryBindIndex; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; - VkDeviceSize memorySize; -} VkVideoBindMemoryKHR; - -typedef struct VkVideoSessionCreateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t queueFamilyIndex; - VkVideoSessionCreateFlagsKHR flags; - const VkVideoProfileKHR* pVideoProfile; - VkFormat pictureFormat; - VkExtent2D maxCodedExtent; - VkFormat referencePicturesFormat; - uint32_t maxReferencePicturesSlotsCount; - uint32_t maxReferencePicturesActiveCount; -} VkVideoSessionCreateInfoKHR; - -typedef struct VkVideoSessionParametersCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoSessionParametersKHR videoSessionParametersTemplate; - VkVideoSessionKHR videoSession; -} VkVideoSessionParametersCreateInfoKHR; - -typedef struct VkVideoSessionParametersUpdateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t updateSequenceCount; -} VkVideoSessionParametersUpdateInfoKHR; - -typedef struct VkVideoBeginCodingInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoBeginCodingFlagsKHR flags; - VkVideoCodingQualityPresetFlagsKHR codecQualityPreset; - VkVideoSessionKHR videoSession; - VkVideoSessionParametersKHR videoSessionParameters; - uint32_t referenceSlotCount; - const VkVideoReferenceSlotKHR* pReferenceSlots; -} VkVideoBeginCodingInfoKHR; - -typedef struct VkVideoEndCodingInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoEndCodingFlagsKHR flags; -} VkVideoEndCodingInfoKHR; - -typedef struct VkVideoCodingControlInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoCodingControlFlagsKHR flags; -} VkVideoCodingControlInfoKHR; - -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)(VkPhysicalDevice physicalDevice, const VkVideoProfileKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties); -typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionKHR)(VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession); -typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionKHR)(VkDevice device, VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetVideoSessionMemoryRequirementsKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pVideoSessionMemoryRequirementsCount, VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements); -typedef VkResult (VKAPI_PTR *PFN_vkBindVideoSessionMemoryKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t videoSessionBindMemoryCount, const VkVideoBindMemoryKHR* pVideoSessionBindMemories); -typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionParametersKHR)(VkDevice device, const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionParametersKHR* pVideoSessionParameters); -typedef VkResult (VKAPI_PTR *PFN_vkUpdateVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); -typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkCmdBeginVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoBeginCodingInfoKHR* pBeginInfo); -typedef void (VKAPI_PTR *PFN_vkCmdEndVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoEndCodingInfoKHR* pEndCodingInfo); -typedef void (VKAPI_PTR *PFN_vkCmdControlVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoCodingControlInfoKHR* pCodingControlInfo); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoCapabilitiesKHR( - VkPhysicalDevice physicalDevice, - const VkVideoProfileKHR* pVideoProfile, - VkVideoCapabilitiesKHR* pCapabilities); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoFormatPropertiesKHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, - uint32_t* pVideoFormatPropertyCount, - VkVideoFormatPropertiesKHR* pVideoFormatProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionKHR( - VkDevice device, - const VkVideoSessionCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkVideoSessionKHR* pVideoSession); - -VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionKHR( - VkDevice device, - VkVideoSessionKHR videoSession, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetVideoSessionMemoryRequirementsKHR( - VkDevice device, - VkVideoSessionKHR videoSession, - uint32_t* pVideoSessionMemoryRequirementsCount, - VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements); - -VKAPI_ATTR VkResult VKAPI_CALL vkBindVideoSessionMemoryKHR( - VkDevice device, - VkVideoSessionKHR videoSession, - uint32_t videoSessionBindMemoryCount, - const VkVideoBindMemoryKHR* pVideoSessionBindMemories); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionParametersKHR( - VkDevice device, - const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkVideoSessionParametersKHR* pVideoSessionParameters); - -VKAPI_ATTR VkResult VKAPI_CALL vkUpdateVideoSessionParametersKHR( - VkDevice device, - VkVideoSessionParametersKHR videoSessionParameters, - const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); - -VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionParametersKHR( - VkDevice device, - VkVideoSessionParametersKHR videoSessionParameters, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR void VKAPI_CALL vkCmdBeginVideoCodingKHR( - VkCommandBuffer commandBuffer, - const VkVideoBeginCodingInfoKHR* pBeginInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdEndVideoCodingKHR( - VkCommandBuffer commandBuffer, - const VkVideoEndCodingInfoKHR* pEndCodingInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR( - VkCommandBuffer commandBuffer, - const VkVideoCodingControlInfoKHR* pCodingControlInfo); -#endif - - -#define VK_KHR_video_decode_queue 1 -#define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 1 -#define VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME "VK_KHR_video_decode_queue" - -typedef enum VkVideoDecodeFlagBitsKHR { - VK_VIDEO_DECODE_DEFAULT_KHR = 0, - VK_VIDEO_DECODE_RESERVED_0_BIT_KHR = 0x00000001, - VK_VIDEO_DECODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoDecodeFlagBitsKHR; -typedef VkFlags VkVideoDecodeFlagsKHR; -typedef struct VkVideoDecodeInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoDecodeFlagsKHR flags; - VkOffset2D codedOffset; - VkExtent2D codedExtent; - VkBuffer srcBuffer; - VkDeviceSize srcBufferOffset; - VkDeviceSize srcBufferRange; - VkVideoPictureResourceKHR dstPictureResource; - const VkVideoReferenceSlotKHR* pSetupReferenceSlot; - uint32_t referenceSlotCount; - const VkVideoReferenceSlotKHR* pReferenceSlots; -} VkVideoDecodeInfoKHR; - -typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pFrameInfo); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR( - VkCommandBuffer commandBuffer, - const VkVideoDecodeInfoKHR* pFrameInfo); -#endif - - +// VK_KHR_portability_subset is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_portability_subset 1 #define VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION 1 #define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" @@ -369,332 +51,759 @@ typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { +// VK_KHR_video_encode_queue is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_video_encode_queue 1 -#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 2 +#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 10 #define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue" -typedef enum VkVideoEncodeFlagBitsKHR { - VK_VIDEO_ENCODE_DEFAULT_KHR = 0, - VK_VIDEO_ENCODE_RESERVED_0_BIT_KHR = 0x00000001, - VK_VIDEO_ENCODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoEncodeFlagBitsKHR; +typedef enum VkVideoEncodeTuningModeKHR { + VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR = 1, + VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR = 2, + VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR = 3, + VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR = 4, + VK_VIDEO_ENCODE_TUNING_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeTuningModeKHR; typedef VkFlags VkVideoEncodeFlagsKHR; -typedef enum VkVideoEncodeRateControlFlagBitsKHR { - VK_VIDEO_ENCODE_RATE_CONTROL_DEFAULT_KHR = 0, - VK_VIDEO_ENCODE_RATE_CONTROL_RESET_BIT_KHR = 0x00000001, - VK_VIDEO_ENCODE_RATE_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoEncodeRateControlFlagBitsKHR; -typedef VkFlags VkVideoEncodeRateControlFlagsKHR; +typedef enum VkVideoEncodeCapabilityFlagBitsKHR { + VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_CAPABILITY_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_DETECTION_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeCapabilityFlagBitsKHR; +typedef VkFlags VkVideoEncodeCapabilityFlagsKHR; typedef enum VkVideoEncodeRateControlModeFlagBitsKHR { - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR = 0, - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 1, - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 2, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 0x00000004, VK_VIDEO_ENCODE_RATE_CONTROL_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoEncodeRateControlModeFlagBitsKHR; typedef VkFlags VkVideoEncodeRateControlModeFlagsKHR; + +typedef enum VkVideoEncodeFeedbackFlagBitsKHR { + VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_FEEDBACK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeFeedbackFlagBitsKHR; +typedef VkFlags VkVideoEncodeFeedbackFlagsKHR; + +typedef enum VkVideoEncodeUsageFlagBitsKHR { + VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_USAGE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeUsageFlagBitsKHR; +typedef VkFlags VkVideoEncodeUsageFlagsKHR; + +typedef enum VkVideoEncodeContentFlagBitsKHR { + VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_CONTENT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeContentFlagBitsKHR; +typedef VkFlags VkVideoEncodeContentFlagsKHR; +typedef VkFlags VkVideoEncodeRateControlFlagsKHR; typedef struct VkVideoEncodeInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoEncodeFlagsKHR flags; - uint32_t qualityLevel; - VkExtent2D codedExtent; - VkBuffer dstBitstreamBuffer; - VkDeviceSize dstBitstreamBufferOffset; - VkDeviceSize dstBitstreamBufferMaxRange; - VkVideoPictureResourceKHR srcPictureResource; - const VkVideoReferenceSlotKHR* pSetupReferenceSlot; - uint32_t referenceSlotCount; - const VkVideoReferenceSlotKHR* pReferenceSlots; + VkStructureType sType; + const void* pNext; + VkVideoEncodeFlagsKHR flags; + VkBuffer dstBuffer; + VkDeviceSize dstBufferOffset; + VkDeviceSize dstBufferRange; + VkVideoPictureResourceInfoKHR srcPictureResource; + const VkVideoReferenceSlotInfoKHR* pSetupReferenceSlot; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotInfoKHR* pReferenceSlots; + uint32_t precedingExternallyEncodedBytes; } VkVideoEncodeInfoKHR; +typedef struct VkVideoEncodeCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeCapabilityFlagsKHR flags; + VkVideoEncodeRateControlModeFlagsKHR rateControlModes; + uint32_t maxRateControlLayers; + uint64_t maxBitrate; + uint32_t maxQualityLevels; + VkExtent2D encodeInputPictureGranularity; + VkVideoEncodeFeedbackFlagsKHR supportedEncodeFeedbackFlags; +} VkVideoEncodeCapabilitiesKHR; + +typedef struct VkQueryPoolVideoEncodeFeedbackCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeFeedbackFlagsKHR encodeFeedbackFlags; +} VkQueryPoolVideoEncodeFeedbackCreateInfoKHR; + +typedef struct VkVideoEncodeUsageInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeUsageFlagsKHR videoUsageHints; + VkVideoEncodeContentFlagsKHR videoContentHints; + VkVideoEncodeTuningModeKHR tuningMode; +} VkVideoEncodeUsageInfoKHR; + +typedef struct VkVideoEncodeRateControlLayerInfoKHR { + VkStructureType sType; + const void* pNext; + uint64_t averageBitrate; + uint64_t maxBitrate; + uint32_t frameRateNumerator; + uint32_t frameRateDenominator; +} VkVideoEncodeRateControlLayerInfoKHR; + typedef struct VkVideoEncodeRateControlInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoEncodeRateControlFlagsKHR flags; - VkVideoEncodeRateControlModeFlagBitsKHR rateControlMode; - uint32_t averageBitrate; - uint16_t peakToAverageBitrateRatio; - uint16_t frameRateNumerator; - uint16_t frameRateDenominator; - uint32_t virtualBufferSizeInMs; + VkStructureType sType; + const void* pNext; + VkVideoEncodeRateControlFlagsKHR flags; + VkVideoEncodeRateControlModeFlagBitsKHR rateControlMode; + uint32_t layerCount; + const VkVideoEncodeRateControlLayerInfoKHR* pLayers; + uint32_t virtualBufferSizeInMs; + uint32_t initialVirtualBufferSizeInMs; } VkVideoEncodeRateControlInfoKHR; +typedef struct VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR { + VkStructureType sType; + const void* pNext; + const VkVideoProfileInfoKHR* pVideoProfile; + uint32_t qualityLevel; +} VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR; + +typedef struct VkVideoEncodeQualityLevelPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeRateControlModeFlagBitsKHR preferredRateControlMode; + uint32_t preferredRateControlLayerCount; +} VkVideoEncodeQualityLevelPropertiesKHR; + +typedef struct VkVideoEncodeQualityLevelInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t qualityLevel; +} VkVideoEncodeQualityLevelInfoKHR; + +typedef struct VkVideoEncodeSessionParametersGetInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoSessionParametersKHR videoSessionParameters; +} VkVideoEncodeSessionParametersGetInfoKHR; + +typedef struct VkVideoEncodeSessionParametersFeedbackInfoKHR { + VkStructureType sType; + void* pNext; + VkBool32 hasOverrides; +} VkVideoEncodeSessionParametersFeedbackInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo, VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetEncodedVideoSessionParametersKHR)(VkDevice device, const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo, VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo, size_t* pDataSize, void* pData); typedef void (VKAPI_PTR *PFN_vkCmdEncodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); #ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo, + VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetEncodedVideoSessionParametersKHR( + VkDevice device, + const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo, + VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo, + size_t* pDataSize, + void* pData); + VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR( VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); #endif +// VK_EXT_video_encode_h264 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_video_encode_h264 1 #include "vk_video/vulkan_video_codec_h264std.h" #include "vk_video/vulkan_video_codec_h264std_encode.h" -#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 2 +#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 12 #define VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_EXT_video_encode_h264" typedef enum VkVideoEncodeH264CapabilityFlagBitsEXT { - VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BI_PRED_IMPLICIT_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT = 0x00000008, - VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT = 0x00000010, - VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT = 0x00000020, - VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0x00000040, - VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0x00000080, - VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0x00000100, - VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT = 0x00000200, - VK_VIDEO_ENCODE_H264_CAPABILITY_EVENLY_DISTRIBUTED_SLICE_SIZE_BIT_EXT = 0x00000400, + VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0x00000020, + VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_EXT = 0x00000040, + VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_EXT = 0x00000080, + VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_EXT = 0x00000100, VK_VIDEO_ENCODE_H264_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkVideoEncodeH264CapabilityFlagBitsEXT; typedef VkFlags VkVideoEncodeH264CapabilityFlagsEXT; -typedef enum VkVideoEncodeH264InputModeFlagBitsEXT { - VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H264_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH264InputModeFlagBitsEXT; -typedef VkFlags VkVideoEncodeH264InputModeFlagsEXT; - -typedef enum VkVideoEncodeH264OutputModeFlagBitsEXT { - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH264OutputModeFlagBitsEXT; -typedef VkFlags VkVideoEncodeH264OutputModeFlagsEXT; - -typedef enum VkVideoEncodeH264CreateFlagBitsEXT { - VK_VIDEO_ENCODE_H264_CREATE_DEFAULT_EXT = 0, - VK_VIDEO_ENCODE_H264_CREATE_RESERVED_0_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH264CreateFlagBitsEXT; -typedef VkFlags VkVideoEncodeH264CreateFlagsEXT; +typedef enum VkVideoEncodeH264StdFlagBitsEXT { + VK_VIDEO_ENCODE_H264_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_STD_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG_SET_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_STD_CHROMA_QP_INDEX_OFFSET_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H264_STD_SECOND_CHROMA_QP_INDEX_OFFSET_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H264_STD_PIC_INIT_QP_MINUS26_BIT_EXT = 0x00000020, + VK_VIDEO_ENCODE_H264_STD_WEIGHTED_PRED_FLAG_SET_BIT_EXT = 0x00000040, + VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_EXPLICIT_BIT_EXT = 0x00000080, + VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_IMPLICIT_BIT_EXT = 0x00000100, + VK_VIDEO_ENCODE_H264_STD_TRANSFORM_8X8_MODE_FLAG_SET_BIT_EXT = 0x00000200, + VK_VIDEO_ENCODE_H264_STD_DIRECT_SPATIAL_MV_PRED_FLAG_UNSET_BIT_EXT = 0x00000400, + VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_UNSET_BIT_EXT = 0x00000800, + VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_SET_BIT_EXT = 0x00001000, + VK_VIDEO_ENCODE_H264_STD_DIRECT_8X8_INFERENCE_FLAG_UNSET_BIT_EXT = 0x00002000, + VK_VIDEO_ENCODE_H264_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_EXT = 0x00004000, + VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0x00008000, + VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0x00010000, + VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0x00020000, + VK_VIDEO_ENCODE_H264_STD_SLICE_QP_DELTA_BIT_EXT = 0x00080000, + VK_VIDEO_ENCODE_H264_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT = 0x00100000, + VK_VIDEO_ENCODE_H264_STD_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264StdFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264StdFlagsEXT; + +typedef enum VkVideoEncodeH264RateControlFlagBitsEXT { + VK_VIDEO_ENCODE_H264_RATE_CONTROL_ATTEMPT_HRD_COMPLIANCE_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_REGULAR_GOP_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_DYADIC_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_TEMPORAL_LAYER_PATTERN_DYADIC_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264RateControlFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264RateControlFlagsEXT; typedef struct VkVideoEncodeH264CapabilitiesEXT { VkStructureType sType; - const void* pNext; + void* pNext; VkVideoEncodeH264CapabilityFlagsEXT flags; - VkVideoEncodeH264InputModeFlagsEXT inputModeFlags; - VkVideoEncodeH264OutputModeFlagsEXT outputModeFlags; - VkExtent2D minPictureSizeInMbs; - VkExtent2D maxPictureSizeInMbs; - VkExtent2D inputImageDataAlignment; - uint8_t maxNumL0ReferenceForP; - uint8_t maxNumL0ReferenceForB; - uint8_t maxNumL1Reference; - uint8_t qualityLevelCount; - VkExtensionProperties stdExtensionVersion; + StdVideoH264LevelIdc maxLevelIdc; + uint32_t maxSliceCount; + uint32_t maxPPictureL0ReferenceCount; + uint32_t maxBPictureL0ReferenceCount; + uint32_t maxL1ReferenceCount; + uint32_t maxTemporalLayerCount; + VkBool32 expectDyadicTemporalLayerPattern; + int32_t minQp; + int32_t maxQp; + VkBool32 prefersGopRemainingFrames; + VkBool32 requiresGopRemainingFrames; + VkVideoEncodeH264StdFlagsEXT stdSyntaxFlags; } VkVideoEncodeH264CapabilitiesEXT; +typedef struct VkVideoEncodeH264QpEXT { + int32_t qpI; + int32_t qpP; + int32_t qpB; +} VkVideoEncodeH264QpEXT; + +typedef struct VkVideoEncodeH264QualityLevelPropertiesEXT { + VkStructureType sType; + void* pNext; + VkVideoEncodeH264RateControlFlagsEXT preferredRateControlFlags; + uint32_t preferredGopFrameCount; + uint32_t preferredIdrPeriod; + uint32_t preferredConsecutiveBFrameCount; + uint32_t preferredTemporalLayerCount; + VkVideoEncodeH264QpEXT preferredConstantQp; + uint32_t preferredMaxL0ReferenceCount; + uint32_t preferredMaxL1ReferenceCount; + VkBool32 preferredStdEntropyCodingModeFlag; +} VkVideoEncodeH264QualityLevelPropertiesEXT; + typedef struct VkVideoEncodeH264SessionCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkVideoEncodeH264CreateFlagsEXT flags; - VkExtent2D maxPictureSizeInMbs; - const VkExtensionProperties* pStdExtensionVersion; + VkStructureType sType; + const void* pNext; + VkBool32 useMaxLevelIdc; + StdVideoH264LevelIdc maxLevelIdc; } VkVideoEncodeH264SessionCreateInfoEXT; typedef struct VkVideoEncodeH264SessionParametersAddInfoEXT { VkStructureType sType; const void* pNext; - uint32_t spsStdCount; - const StdVideoH264SequenceParameterSet* pSpsStd; - uint32_t ppsStdCount; - const StdVideoH264PictureParameterSet* pPpsStd; + uint32_t stdSPSCount; + const StdVideoH264SequenceParameterSet* pStdSPSs; + uint32_t stdPPSCount; + const StdVideoH264PictureParameterSet* pStdPPSs; } VkVideoEncodeH264SessionParametersAddInfoEXT; typedef struct VkVideoEncodeH264SessionParametersCreateInfoEXT { VkStructureType sType; const void* pNext; - uint32_t maxSpsStdCount; - uint32_t maxPpsStdCount; + uint32_t maxStdSPSCount; + uint32_t maxStdPPSCount; const VkVideoEncodeH264SessionParametersAddInfoEXT* pParametersAddInfo; } VkVideoEncodeH264SessionParametersCreateInfoEXT; -typedef struct VkVideoEncodeH264DpbSlotInfoEXT { +typedef struct VkVideoEncodeH264SessionParametersGetInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 writeStdSPS; + VkBool32 writeStdPPS; + uint32_t stdSPSId; + uint32_t stdPPSId; +} VkVideoEncodeH264SessionParametersGetInfoEXT; + +typedef struct VkVideoEncodeH264SessionParametersFeedbackInfoEXT { + VkStructureType sType; + void* pNext; + VkBool32 hasStdSPSOverrides; + VkBool32 hasStdPPSOverrides; +} VkVideoEncodeH264SessionParametersFeedbackInfoEXT; + +typedef struct VkVideoEncodeH264NaluSliceInfoEXT { VkStructureType sType; const void* pNext; - int8_t slotIndex; - const StdVideoEncodeH264PictureInfo* pStdPictureInfo; -} VkVideoEncodeH264DpbSlotInfoEXT; + int32_t constantQp; + const StdVideoEncodeH264SliceHeader* pStdSliceHeader; +} VkVideoEncodeH264NaluSliceInfoEXT; + +typedef struct VkVideoEncodeH264PictureInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t naluSliceEntryCount; + const VkVideoEncodeH264NaluSliceInfoEXT* pNaluSliceEntries; + const StdVideoEncodeH264PictureInfo* pStdPictureInfo; + VkBool32 generatePrefixNalu; +} VkVideoEncodeH264PictureInfoEXT; -typedef struct VkVideoEncodeH264NaluSliceEXT { - VkStructureType sType; - const void* pNext; - const StdVideoEncodeH264SliceHeader* pSliceHeaderStd; - uint32_t mbCount; - uint8_t refFinalList0EntryCount; - const VkVideoEncodeH264DpbSlotInfoEXT* pRefFinalList0Entries; - uint8_t refFinalList1EntryCount; - const VkVideoEncodeH264DpbSlotInfoEXT* pRefFinalList1Entries; - uint32_t precedingNaluBytes; - uint8_t minQp; - uint8_t maxQp; -} VkVideoEncodeH264NaluSliceEXT; - -typedef struct VkVideoEncodeH264VclFrameInfoEXT { +typedef struct VkVideoEncodeH264DpbSlotInfoEXT { VkStructureType sType; const void* pNext; - uint8_t refDefaultFinalList0EntryCount; - const VkVideoEncodeH264DpbSlotInfoEXT* pRefDefaultFinalList0Entries; - uint8_t refDefaultFinalList1EntryCount; - const VkVideoEncodeH264DpbSlotInfoEXT* pRefDefaultFinalList1Entries; - uint32_t naluSliceEntryCount; - const VkVideoEncodeH264NaluSliceEXT* pNaluSliceEntries; - const VkVideoEncodeH264DpbSlotInfoEXT* pCurrentPictureInfo; -} VkVideoEncodeH264VclFrameInfoEXT; - -typedef struct VkVideoEncodeH264EmitPictureParametersEXT { - VkStructureType sType; - const void* pNext; - uint8_t spsId; - VkBool32 emitSpsEnable; - uint32_t ppsIdEntryCount; - const uint8_t* ppsIdEntries; -} VkVideoEncodeH264EmitPictureParametersEXT; + const StdVideoEncodeH264ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeH264DpbSlotInfoEXT; -typedef struct VkVideoEncodeH264ProfileEXT { +typedef struct VkVideoEncodeH264ProfileInfoEXT { VkStructureType sType; const void* pNext; StdVideoH264ProfileIdc stdProfileIdc; -} VkVideoEncodeH264ProfileEXT; +} VkVideoEncodeH264ProfileInfoEXT; +typedef struct VkVideoEncodeH264RateControlInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH264RateControlFlagsEXT flags; + uint32_t gopFrameCount; + uint32_t idrPeriod; + uint32_t consecutiveBFrameCount; + uint32_t temporalLayerCount; +} VkVideoEncodeH264RateControlInfoEXT; + +typedef struct VkVideoEncodeH264FrameSizeEXT { + uint32_t frameISize; + uint32_t framePSize; + uint32_t frameBSize; +} VkVideoEncodeH264FrameSizeEXT; + +typedef struct VkVideoEncodeH264RateControlLayerInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 useMinQp; + VkVideoEncodeH264QpEXT minQp; + VkBool32 useMaxQp; + VkVideoEncodeH264QpEXT maxQp; + VkBool32 useMaxFrameSize; + VkVideoEncodeH264FrameSizeEXT maxFrameSize; +} VkVideoEncodeH264RateControlLayerInfoEXT; + +typedef struct VkVideoEncodeH264GopRemainingFrameInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 useGopRemainingFrames; + uint32_t gopRemainingI; + uint32_t gopRemainingP; + uint32_t gopRemainingB; +} VkVideoEncodeH264GopRemainingFrameInfoEXT; -#define VK_EXT_video_decode_h264 1 -#include "vk_video/vulkan_video_codec_h264std_decode.h" -#define VK_EXT_VIDEO_DECODE_H264_SPEC_VERSION 3 -#define VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME "VK_EXT_video_decode_h264" -typedef enum VkVideoDecodeH264PictureLayoutFlagBitsEXT { - VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_EXT = 0, - VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_EXT = 0x00000001, - VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_EXT = 0x00000002, - VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoDecodeH264PictureLayoutFlagBitsEXT; -typedef VkFlags VkVideoDecodeH264PictureLayoutFlagsEXT; -typedef VkFlags VkVideoDecodeH264CreateFlagsEXT; -typedef struct VkVideoDecodeH264ProfileEXT { - VkStructureType sType; - const void* pNext; - StdVideoH264ProfileIdc stdProfileIdc; - VkVideoDecodeH264PictureLayoutFlagsEXT pictureLayout; -} VkVideoDecodeH264ProfileEXT; - -typedef struct VkVideoDecodeH264CapabilitiesEXT { - VkStructureType sType; - void* pNext; - uint32_t maxLevel; - VkOffset2D fieldOffsetGranularity; - VkExtensionProperties stdExtensionVersion; -} VkVideoDecodeH264CapabilitiesEXT; - -typedef struct VkVideoDecodeH264SessionCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkVideoDecodeH264CreateFlagsEXT flags; - const VkExtensionProperties* pStdExtensionVersion; -} VkVideoDecodeH264SessionCreateInfoEXT; - -typedef struct VkVideoDecodeH264SessionParametersAddInfoEXT { +// VK_EXT_video_encode_h265 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_video_encode_h265 1 +#include "vk_video/vulkan_video_codec_h265std.h" +#include "vk_video/vulkan_video_codec_h265std_encode.h" +#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 12 +#define VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_EXT_video_encode_h265" + +typedef enum VkVideoEncodeH265CapabilityFlagBitsEXT { + VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_SEGMENT_TYPE_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0x00000020, + VK_VIDEO_ENCODE_H265_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_EXT = 0x00000040, + VK_VIDEO_ENCODE_H265_CAPABILITY_PER_SLICE_SEGMENT_CONSTANT_QP_BIT_EXT = 0x00000080, + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILES_PER_SLICE_SEGMENT_BIT_EXT = 0x00000100, + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_SEGMENTS_PER_TILE_BIT_EXT = 0x00000200, + VK_VIDEO_ENCODE_H265_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265CapabilityFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265CapabilityFlagsEXT; + +typedef enum VkVideoEncodeH265StdFlagBitsEXT { + VK_VIDEO_ENCODE_H265_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_STD_SCALING_LIST_DATA_PRESENT_FLAG_SET_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_STD_PCM_ENABLED_FLAG_SET_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H265_STD_SPS_TEMPORAL_MVP_ENABLED_FLAG_SET_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H265_STD_INIT_QP_MINUS26_BIT_EXT = 0x00000020, + VK_VIDEO_ENCODE_H265_STD_WEIGHTED_PRED_FLAG_SET_BIT_EXT = 0x00000040, + VK_VIDEO_ENCODE_H265_STD_WEIGHTED_BIPRED_FLAG_SET_BIT_EXT = 0x00000080, + VK_VIDEO_ENCODE_H265_STD_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_EXT = 0x00000100, + VK_VIDEO_ENCODE_H265_STD_SIGN_DATA_HIDING_ENABLED_FLAG_SET_BIT_EXT = 0x00000200, + VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_EXT = 0x00000400, + VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_UNSET_BIT_EXT = 0x00000800, + VK_VIDEO_ENCODE_H265_STD_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG_SET_BIT_EXT = 0x00001000, + VK_VIDEO_ENCODE_H265_STD_TRANSQUANT_BYPASS_ENABLED_FLAG_SET_BIT_EXT = 0x00002000, + VK_VIDEO_ENCODE_H265_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_EXT = 0x00004000, + VK_VIDEO_ENCODE_H265_STD_ENTROPY_CODING_SYNC_ENABLED_FLAG_SET_BIT_EXT = 0x00008000, + VK_VIDEO_ENCODE_H265_STD_DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_SET_BIT_EXT = 0x00010000, + VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_EXT = 0x00020000, + VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_EXT = 0x00040000, + VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_EXT = 0x00080000, + VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT = 0x00100000, + VK_VIDEO_ENCODE_H265_STD_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265StdFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265StdFlagsEXT; + +typedef enum VkVideoEncodeH265CtbSizeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_CTB_SIZE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265CtbSizeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265CtbSizeFlagsEXT; + +typedef enum VkVideoEncodeH265TransformBlockSizeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265TransformBlockSizeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265TransformBlockSizeFlagsEXT; + +typedef enum VkVideoEncodeH265RateControlFlagBitsEXT { + VK_VIDEO_ENCODE_H265_RATE_CONTROL_ATTEMPT_HRD_COMPLIANCE_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_REGULAR_GOP_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_DYADIC_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_TEMPORAL_SUB_LAYER_PATTERN_DYADIC_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265RateControlFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265RateControlFlagsEXT; +typedef struct VkVideoEncodeH265CapabilitiesEXT { + VkStructureType sType; + void* pNext; + VkVideoEncodeH265CapabilityFlagsEXT flags; + StdVideoH265LevelIdc maxLevelIdc; + uint32_t maxSliceSegmentCount; + VkExtent2D maxTiles; + VkVideoEncodeH265CtbSizeFlagsEXT ctbSizes; + VkVideoEncodeH265TransformBlockSizeFlagsEXT transformBlockSizes; + uint32_t maxPPictureL0ReferenceCount; + uint32_t maxBPictureL0ReferenceCount; + uint32_t maxL1ReferenceCount; + uint32_t maxSubLayerCount; + VkBool32 expectDyadicTemporalSubLayerPattern; + int32_t minQp; + int32_t maxQp; + VkBool32 prefersGopRemainingFrames; + VkBool32 requiresGopRemainingFrames; + VkVideoEncodeH265StdFlagsEXT stdSyntaxFlags; +} VkVideoEncodeH265CapabilitiesEXT; + +typedef struct VkVideoEncodeH265SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 useMaxLevelIdc; + StdVideoH265LevelIdc maxLevelIdc; +} VkVideoEncodeH265SessionCreateInfoEXT; + +typedef struct VkVideoEncodeH265QpEXT { + int32_t qpI; + int32_t qpP; + int32_t qpB; +} VkVideoEncodeH265QpEXT; + +typedef struct VkVideoEncodeH265QualityLevelPropertiesEXT { + VkStructureType sType; + void* pNext; + VkVideoEncodeH265RateControlFlagsEXT preferredRateControlFlags; + uint32_t preferredGopFrameCount; + uint32_t preferredIdrPeriod; + uint32_t preferredConsecutiveBFrameCount; + uint32_t preferredSubLayerCount; + VkVideoEncodeH265QpEXT preferredConstantQp; + uint32_t preferredMaxL0ReferenceCount; + uint32_t preferredMaxL1ReferenceCount; +} VkVideoEncodeH265QualityLevelPropertiesEXT; + +typedef struct VkVideoEncodeH265SessionParametersAddInfoEXT { VkStructureType sType; const void* pNext; - uint32_t spsStdCount; - const StdVideoH264SequenceParameterSet* pSpsStd; - uint32_t ppsStdCount; - const StdVideoH264PictureParameterSet* pPpsStd; -} VkVideoDecodeH264SessionParametersAddInfoEXT; - -typedef struct VkVideoDecodeH264SessionParametersCreateInfoEXT { + uint32_t stdVPSCount; + const StdVideoH265VideoParameterSet* pStdVPSs; + uint32_t stdSPSCount; + const StdVideoH265SequenceParameterSet* pStdSPSs; + uint32_t stdPPSCount; + const StdVideoH265PictureParameterSet* pStdPPSs; +} VkVideoEncodeH265SessionParametersAddInfoEXT; + +typedef struct VkVideoEncodeH265SessionParametersCreateInfoEXT { VkStructureType sType; const void* pNext; - uint32_t maxSpsStdCount; - uint32_t maxPpsStdCount; - const VkVideoDecodeH264SessionParametersAddInfoEXT* pParametersAddInfo; -} VkVideoDecodeH264SessionParametersCreateInfoEXT; + uint32_t maxStdVPSCount; + uint32_t maxStdSPSCount; + uint32_t maxStdPPSCount; + const VkVideoEncodeH265SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoEncodeH265SessionParametersCreateInfoEXT; + +typedef struct VkVideoEncodeH265SessionParametersGetInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 writeStdVPS; + VkBool32 writeStdSPS; + VkBool32 writeStdPPS; + uint32_t stdVPSId; + uint32_t stdSPSId; + uint32_t stdPPSId; +} VkVideoEncodeH265SessionParametersGetInfoEXT; + +typedef struct VkVideoEncodeH265SessionParametersFeedbackInfoEXT { + VkStructureType sType; + void* pNext; + VkBool32 hasStdVPSOverrides; + VkBool32 hasStdSPSOverrides; + VkBool32 hasStdPPSOverrides; +} VkVideoEncodeH265SessionParametersFeedbackInfoEXT; + +typedef struct VkVideoEncodeH265NaluSliceSegmentInfoEXT { + VkStructureType sType; + const void* pNext; + int32_t constantQp; + const StdVideoEncodeH265SliceSegmentHeader* pStdSliceSegmentHeader; +} VkVideoEncodeH265NaluSliceSegmentInfoEXT; + +typedef struct VkVideoEncodeH265PictureInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t naluSliceSegmentEntryCount; + const VkVideoEncodeH265NaluSliceSegmentInfoEXT* pNaluSliceSegmentEntries; + const StdVideoEncodeH265PictureInfo* pStdPictureInfo; +} VkVideoEncodeH265PictureInfoEXT; + +typedef struct VkVideoEncodeH265DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeH265DpbSlotInfoEXT; + +typedef struct VkVideoEncodeH265ProfileInfoEXT { + VkStructureType sType; + const void* pNext; + StdVideoH265ProfileIdc stdProfileIdc; +} VkVideoEncodeH265ProfileInfoEXT; -typedef struct VkVideoDecodeH264PictureInfoEXT { +typedef struct VkVideoEncodeH265RateControlInfoEXT { VkStructureType sType; const void* pNext; - const StdVideoDecodeH264PictureInfo* pStdPictureInfo; - uint32_t slicesCount; - const uint32_t* pSlicesDataOffsets; -} VkVideoDecodeH264PictureInfoEXT; + VkVideoEncodeH265RateControlFlagsEXT flags; + uint32_t gopFrameCount; + uint32_t idrPeriod; + uint32_t consecutiveBFrameCount; + uint32_t subLayerCount; +} VkVideoEncodeH265RateControlInfoEXT; + +typedef struct VkVideoEncodeH265FrameSizeEXT { + uint32_t frameISize; + uint32_t framePSize; + uint32_t frameBSize; +} VkVideoEncodeH265FrameSizeEXT; + +typedef struct VkVideoEncodeH265RateControlLayerInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 useMinQp; + VkVideoEncodeH265QpEXT minQp; + VkBool32 useMaxQp; + VkVideoEncodeH265QpEXT maxQp; + VkBool32 useMaxFrameSize; + VkVideoEncodeH265FrameSizeEXT maxFrameSize; +} VkVideoEncodeH265RateControlLayerInfoEXT; + +typedef struct VkVideoEncodeH265GopRemainingFrameInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 useGopRemainingFrames; + uint32_t gopRemainingI; + uint32_t gopRemainingP; + uint32_t gopRemainingB; +} VkVideoEncodeH265GopRemainingFrameInfoEXT; -typedef struct VkVideoDecodeH264MvcEXT { - VkStructureType sType; - const void* pNext; - const StdVideoDecodeH264Mvc* pStdMvc; -} VkVideoDecodeH264MvcEXT; -typedef struct VkVideoDecodeH264DpbSlotInfoEXT { + +// VK_AMDX_shader_enqueue is a preprocessor guard. Do not pass it to API calls. +#define VK_AMDX_shader_enqueue 1 +#define VK_AMDX_SHADER_ENQUEUE_SPEC_VERSION 1 +#define VK_AMDX_SHADER_ENQUEUE_EXTENSION_NAME "VK_AMDX_shader_enqueue" +#define VK_SHADER_INDEX_UNUSED_AMDX (~0U) +typedef struct VkPhysicalDeviceShaderEnqueueFeaturesAMDX { + VkStructureType sType; + void* pNext; + VkBool32 shaderEnqueue; +} VkPhysicalDeviceShaderEnqueueFeaturesAMDX; + +typedef struct VkPhysicalDeviceShaderEnqueuePropertiesAMDX { + VkStructureType sType; + void* pNext; + uint32_t maxExecutionGraphDepth; + uint32_t maxExecutionGraphShaderOutputNodes; + uint32_t maxExecutionGraphShaderPayloadSize; + uint32_t maxExecutionGraphShaderPayloadCount; + uint32_t executionGraphDispatchAddressAlignment; +} VkPhysicalDeviceShaderEnqueuePropertiesAMDX; + +typedef struct VkExecutionGraphPipelineScratchSizeAMDX { + VkStructureType sType; + void* pNext; + VkDeviceSize size; +} VkExecutionGraphPipelineScratchSizeAMDX; + +typedef struct VkExecutionGraphPipelineCreateInfoAMDX { VkStructureType sType; const void* pNext; - const StdVideoDecodeH264ReferenceInfo* pStdReferenceInfo; -} VkVideoDecodeH264DpbSlotInfoEXT; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkExecutionGraphPipelineCreateInfoAMDX; + +typedef union VkDeviceOrHostAddressConstAMDX { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstAMDX; + +typedef struct VkDispatchGraphInfoAMDX { + uint32_t nodeIndex; + uint32_t payloadCount; + VkDeviceOrHostAddressConstAMDX payloads; + uint64_t payloadStride; +} VkDispatchGraphInfoAMDX; + +typedef struct VkDispatchGraphCountInfoAMDX { + uint32_t count; + VkDeviceOrHostAddressConstAMDX infos; + uint64_t stride; +} VkDispatchGraphCountInfoAMDX; + +typedef struct VkPipelineShaderStageNodeCreateInfoAMDX { + VkStructureType sType; + const void* pNext; + const char* pName; + uint32_t index; +} VkPipelineShaderStageNodeCreateInfoAMDX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateExecutionGraphPipelinesAMDX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)(VkDevice device, VkPipeline executionGraph, VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)(VkDevice device, VkPipeline executionGraph, const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, uint32_t* pNodeIndex); +typedef void (VKAPI_PTR *PFN_vkCmdInitializeGraphScratchMemoryAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, const VkDispatchGraphCountInfoAMDX* pCountInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, const VkDispatchGraphCountInfoAMDX* pCountInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectCountAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceAddress countInfo); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateExecutionGraphPipelinesAMDX( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); +VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineScratchSizeAMDX( + VkDevice device, + VkPipeline executionGraph, + VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); -#define VK_EXT_video_decode_h265 1 -#include "vk_video/vulkan_video_codec_h265std.h" -#include "vk_video/vulkan_video_codec_h265std_decode.h" -#define VK_EXT_VIDEO_DECODE_H265_SPEC_VERSION 1 -#define VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME "VK_EXT_video_decode_h265" -typedef VkFlags VkVideoDecodeH265CreateFlagsEXT; -typedef struct VkVideoDecodeH265ProfileEXT { - VkStructureType sType; - const void* pNext; - StdVideoH265ProfileIdc stdProfileIdc; -} VkVideoDecodeH265ProfileEXT; - -typedef struct VkVideoDecodeH265CapabilitiesEXT { - VkStructureType sType; - void* pNext; - uint32_t maxLevel; - VkExtensionProperties stdExtensionVersion; -} VkVideoDecodeH265CapabilitiesEXT; - -typedef struct VkVideoDecodeH265SessionCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkVideoDecodeH265CreateFlagsEXT flags; - const VkExtensionProperties* pStdExtensionVersion; -} VkVideoDecodeH265SessionCreateInfoEXT; - -typedef struct VkVideoDecodeH265SessionParametersAddInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t spsStdCount; - const StdVideoH265SequenceParameterSet* pSpsStd; - uint32_t ppsStdCount; - const StdVideoH265PictureParameterSet* pPpsStd; -} VkVideoDecodeH265SessionParametersAddInfoEXT; +VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineNodeIndexAMDX( + VkDevice device, + VkPipeline executionGraph, + const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, + uint32_t* pNodeIndex); -typedef struct VkVideoDecodeH265SessionParametersCreateInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t maxSpsStdCount; - uint32_t maxPpsStdCount; - const VkVideoDecodeH265SessionParametersAddInfoEXT* pParametersAddInfo; -} VkVideoDecodeH265SessionParametersCreateInfoEXT; - -typedef struct VkVideoDecodeH265PictureInfoEXT { - VkStructureType sType; - const void* pNext; - StdVideoDecodeH265PictureInfo* pStdPictureInfo; - uint32_t slicesCount; - const uint32_t* pSlicesDataOffsets; -} VkVideoDecodeH265PictureInfoEXT; - -typedef struct VkVideoDecodeH265DpbSlotInfoEXT { - VkStructureType sType; - const void* pNext; - const StdVideoDecodeH265ReferenceInfo* pStdReferenceInfo; -} VkVideoDecodeH265DpbSlotInfoEXT; +VKAPI_ATTR void VKAPI_CALL vkCmdInitializeGraphScratchMemoryAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + const VkDispatchGraphCountInfoAMDX* pCountInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + const VkDispatchGraphCountInfoAMDX* pCountInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectCountAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceAddress countInfo); +#endif + + +// VK_NV_displacement_micromap is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_displacement_micromap 1 +#define VK_NV_DISPLACEMENT_MICROMAP_SPEC_VERSION 2 +#define VK_NV_DISPLACEMENT_MICROMAP_EXTENSION_NAME "VK_NV_displacement_micromap" + +typedef enum VkDisplacementMicromapFormatNV { + VK_DISPLACEMENT_MICROMAP_FORMAT_64_TRIANGLES_64_BYTES_NV = 1, + VK_DISPLACEMENT_MICROMAP_FORMAT_256_TRIANGLES_128_BYTES_NV = 2, + VK_DISPLACEMENT_MICROMAP_FORMAT_1024_TRIANGLES_128_BYTES_NV = 3, + VK_DISPLACEMENT_MICROMAP_FORMAT_MAX_ENUM_NV = 0x7FFFFFFF +} VkDisplacementMicromapFormatNV; +typedef struct VkPhysicalDeviceDisplacementMicromapFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 displacementMicromap; +} VkPhysicalDeviceDisplacementMicromapFeaturesNV; + +typedef struct VkPhysicalDeviceDisplacementMicromapPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDisplacementMicromapSubdivisionLevel; +} VkPhysicalDeviceDisplacementMicromapPropertiesNV; + +typedef struct VkAccelerationStructureTrianglesDisplacementMicromapNV { + VkStructureType sType; + void* pNext; + VkFormat displacementBiasAndScaleFormat; + VkFormat displacementVectorFormat; + VkDeviceOrHostAddressConstKHR displacementBiasAndScaleBuffer; + VkDeviceSize displacementBiasAndScaleStride; + VkDeviceOrHostAddressConstKHR displacementVectorBuffer; + VkDeviceSize displacementVectorStride; + VkDeviceOrHostAddressConstKHR displacedMicromapPrimitiveFlags; + VkDeviceSize displacedMicromapPrimitiveFlagsStride; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexBuffer; + VkDeviceSize indexStride; + uint32_t baseTriangle; + uint32_t usageCountsCount; + const VkMicromapUsageEXT* pUsageCounts; + const VkMicromapUsageEXT* const* ppUsageCounts; + VkMicromapEXT micromap; +} VkAccelerationStructureTrianglesDisplacementMicromapNV; #ifdef __cplusplus diff --git a/libraries/ZVulkan/include/vulkan/vulkan_core.h b/libraries/ZVulkan/include/vulkan/vulkan_core.h index 9d2b315ddb..71c2874541 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_core.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_core.h @@ -2,7 +2,7 @@ #define VULKAN_CORE_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_VERSION_1_0 is a preprocessor guard. Do not pass it to API calls. #define VK_VERSION_1_0 1 #include "vk_platform.h" @@ -26,7 +27,7 @@ extern "C" { #ifndef VK_USE_64_BIT_PTR_DEFINES - #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64) #define VK_USE_64_BIT_PTR_DEFINES 1 #else #define VK_USE_64_BIT_PTR_DEFINES 0 @@ -58,37 +59,37 @@ extern "C" { #endif #endif -// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. -#define VK_MAKE_VERSION(major, minor, patch) \ - ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) +#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) // DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. -//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 - -#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ - ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) +//#define VK_API_VERSION VK_MAKE_API_VERSION(0, 1, 0, 0) // Patch version should always be set to 0 // Vulkan 1.0 version number #define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 189 +#define VK_HEADER_VERSION 270 // Complete version of this file -#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 2, VK_HEADER_VERSION) +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 3, VK_HEADER_VERSION) + +// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. +#define VK_MAKE_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) // DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. -#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) +#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22U) // DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) // DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) -#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29) -#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU) -#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29U) +#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU) +#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) #define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) typedef uint32_t VkBool32; typedef uint64_t VkDeviceAddress; @@ -120,7 +121,6 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) -#define VK_UUID_SIZE 16U #define VK_ATTACHMENT_UNUSED (~0U) #define VK_FALSE 0U #define VK_LOD_CLAMP_NONE 1000.0F @@ -131,10 +131,11 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) #define VK_TRUE 1U #define VK_WHOLE_SIZE (~0ULL) #define VK_MAX_MEMORY_TYPES 32U -#define VK_MAX_MEMORY_HEAPS 16U #define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256U +#define VK_UUID_SIZE 16U #define VK_MAX_EXTENSION_NAME_SIZE 256U #define VK_MAX_DESCRIPTION_SIZE 256U +#define VK_MAX_MEMORY_HEAPS 16U typedef enum VkResult { VK_SUCCESS = 0, @@ -160,6 +161,7 @@ typedef enum VkResult { VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003, VK_ERROR_FRAGMENTATION = -1000161000, VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000, + VK_PIPELINE_COMPILE_REQUIRED = 1000297000, VK_ERROR_SURFACE_LOST_KHR = -1000000000, VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, VK_SUBOPTIMAL_KHR = 1000001003, @@ -167,20 +169,32 @@ typedef enum VkResult { VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, VK_ERROR_INVALID_SHADER_NV = -1000012000, + VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR = -1000023000, + VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR = -1000023001, + VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR = -1000023002, + VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR = -1000023003, + VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR = -1000023004, + VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR = -1000023005, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, - VK_ERROR_NOT_PERMITTED_EXT = -1000174001, + VK_ERROR_NOT_PERMITTED_KHR = -1000174001, VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, VK_THREAD_IDLE_KHR = 1000268000, VK_THREAD_DONE_KHR = 1000268001, VK_OPERATION_DEFERRED_KHR = 1000268002, VK_OPERATION_NOT_DEFERRED_KHR = 1000268003, - VK_PIPELINE_COMPILE_REQUIRED_EXT = 1000297000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR = -1000299000, +#endif + VK_ERROR_COMPRESSION_EXHAUSTED_EXT = -1000338000, + VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT = 1000482000, VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, + VK_ERROR_NOT_PERMITTED_EXT = VK_ERROR_NOT_PERMITTED_KHR, VK_ERROR_INVALID_DEVICE_ADDRESS_EXT = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, - VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED_EXT, + VK_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED, + VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED, VK_RESULT_MAX_ENUM = 0x7FFFFFFF } VkResult; @@ -349,6 +363,58 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002, VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003, VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000, + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001, + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 = 1000314000, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 = 1000314001, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 = 1000314002, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO = 1000314003, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2 = 1000314004, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO = 1000314005, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO = 1000314006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 = 1000337000, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 = 1000337001, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005, + VK_STRUCTURE_TYPE_BUFFER_COPY_2 = 1000337006, + VK_STRUCTURE_TYPE_IMAGE_COPY_2 = 1000337007, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 = 1000337009, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES = 1000138000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000, + VK_STRUCTURE_TYPE_RENDERING_INFO = 1000044000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO = 1000044001, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO = 1000044002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003, VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, @@ -370,120 +436,132 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000, VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001, VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR = 1000023000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR = 1000023000, VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR = 1000023001, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR = 1000023002, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR = 1000023003, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR = 1000023004, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR = 1000023002, + VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR = 1000023003, + VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR = 1000023004, VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR = 1000023005, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006, + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007, + VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR = 1000023008, + VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR = 1000023009, + VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR = 1000023010, + VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR = 1000023011, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR = 1000023012, + VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR = 1000023013, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014, + VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR = 1000023015, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR = 1000023016, + VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR = 1000024000, + VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR = 1000024001, + VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR = 1000024002, + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, + VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX = 1000029000, + VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX = 1000029001, + VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX = 1000029002, + VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT = 1000038000, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000038001, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR = 1000023008, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038002, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR = 1000023009, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_EXT = 1000038003, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR = 1000023010, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038004, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR = 1000023011, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT = 1000038005, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000023012, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_GOP_REMAINING_FRAME_INFO_EXT = 1000038006, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR = 1000023013, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT = 1000038007, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT = 1000038008, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR = 1000023015, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT = 1000038009, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR = 1000024000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT = 1000038010, #endif - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, - VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX = 1000029000, - VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX = 1000029001, - VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX = 1000029002, - VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000, - VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001, #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT = 1000038000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_EXT = 1000038011, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT = 1000038001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_EXT = 1000038012, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000038002, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_EXT = 1000038013, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038003, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT = 1000038004, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000039001, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038005, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000039002, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT = 1000038006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_EXT = 1000039003, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT = 1000038007, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT = 1000039004, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT = 1000038008, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT = 1000039005, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT = 1000040000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_GOP_REMAINING_FRAME_INFO_EXT = 1000039006, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_CREATE_INFO_EXT = 1000040001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT = 1000039007, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT = 1000040002, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT = 1000039009, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT = 1000040003, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT = 1000039010, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT = 1000040004, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_CREATE_INFO_EXT = 1000039011, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000040005, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_EXT = 1000039012, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000040006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_EXT = 1000039013, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT = 1000040007, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_EXT = 1000039014, #endif + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR = 1000040000, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR = 1000040001, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR = 1000040003, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000040004, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR = 1000040005, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR = 1000040006, VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, @@ -493,9 +571,11 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000, VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000, VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT = 1000066000, VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001, + VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT = 1000068000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT = 1000068001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT = 1000068002, VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000, VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001, VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002, @@ -531,6 +611,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT = 1000102000, VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT = 1000102001, VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RELAXED_LINE_RASTERIZATION_FEATURES_IMG = 1000110000, VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000, VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000, VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001, @@ -565,10 +646,22 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003, VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001, - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002, - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX = 1000134000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_PROPERTIES_AMDX = 1000134001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_EXECUTION_GRAPH_PIPELINE_SCRATCH_SIZE_AMDX = 1000134002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_EXECUTION_GRAPH_PIPELINE_CREATE_INFO_AMDX = 1000134003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NODE_CREATE_INFO_AMDX = 1000134004, +#endif VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, @@ -607,6 +700,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005, + VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT = 1000158006, VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, #ifdef VK_ENABLE_BETA_EXTENSIONS @@ -634,7 +728,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000, VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001, - VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000, VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000, VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002, @@ -642,37 +735,23 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000, VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT = 1000187000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_CREATE_INFO_EXT = 1000187001, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000187002, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000187003, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT = 1000187004, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT = 1000187005, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT = 1000187006, -#endif + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR = 1000187000, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000187001, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR = 1000187002, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR = 1000187003, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR = 1000187004, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR = 1000187005, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR = 1000174000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR = 1000388000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR = 1000388001, VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002, VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP = 1000191000, - VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000192000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = 1000203000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002, @@ -689,14 +768,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000, VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001, VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = 1000215000, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001, VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = 1000225000, - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = 1000225001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = 1000225002, VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000, VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002, @@ -712,7 +787,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV = 1000240000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000, VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = 1000245000, VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT = 1000247000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR = 1000248000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000, @@ -742,8 +816,28 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT = 1000270000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT = 1000270001, + VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT = 1000270002, + VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT = 1000270003, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT = 1000270004, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT = 1000270005, + VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT = 1000270006, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_IMAGE_INFO_EXT = 1000270007, + VK_STRUCTURE_TYPE_SUBRESOURCE_HOST_MEMCPY_SIZE_EXT = 1000270008, + VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT = 1000270009, + VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR = 1000271000, + VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR = 1000271001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = 1000276000, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = 1000274000, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = 1000274002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = 1000275000, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT = 1000275001, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = 1000275002, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT = 1000275003, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = 1000275004, + VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = 1000275005, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002, @@ -755,9 +849,11 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV = 1000278000, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV = 1000278001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = 1000281001, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_BIAS_CONTROL_FEATURES_EXT = 1000283000, + VK_STRUCTURE_TYPE_DEPTH_BIAS_INFO_EXT = 1000283001, + VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT = 1000283002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, @@ -767,85 +863,304 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV = 1000292000, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV = 1000292001, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV = 1000292002, VK_STRUCTURE_TYPE_PRESENT_ID_KHR = 1000294000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = 1000295000, - VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = 1000295001, - VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT = 1000295002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = 1000297000, #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR = 1000299000, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR = 1000299002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR = 1000299003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR = 1000299004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR = 1000299005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR = 1000299007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR = 1000299009, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000299010, #endif VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, - VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR = 1000314000, - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR = 1000314001, - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR = 1000314002, - VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR = 1000314003, - VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR = 1000314004, - VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR = 1000314005, - VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR = 1000314006, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = 1000314007, + VK_STRUCTURE_TYPE_CUDA_MODULE_CREATE_INFO_NV = 1000307000, + VK_STRUCTURE_TYPE_CUDA_FUNCTION_CREATE_INFO_NV = 1000307001, + VK_STRUCTURE_TYPE_CUDA_LAUNCH_INFO_NV = 1000307002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_FEATURES_NV = 1000307003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV = 1000307004, + VK_STRUCTURE_TYPE_QUERY_LOW_LATENCY_SUPPORT_NV = 1000310000, + VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000, + VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001, + VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT = 1000311002, + VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT = 1000311003, + VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT = 1000311004, + VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT = 1000311005, + VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT = 1000311006, + VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT = 1000311007, + VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT = 1000311008, + VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT = 1000311009, + VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311010, + VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311011, VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT = 1000316000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT = 1000316001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT = 1000316002, + VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT = 1000316003, + VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT = 1000316004, + VK_STRUCTURE_TYPE_BUFFER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316005, + VK_STRUCTURE_TYPE_IMAGE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316006, + VK_STRUCTURE_TYPE_IMAGE_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316007, + VK_STRUCTURE_TYPE_SAMPLER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316008, + VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT = 1000316010, + VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT = 1000316011, + VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT = 1000316012, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT = 1000320000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT = 1000320001, + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT = 1000320002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD = 1000321000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR = 1000203000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR = 1000322000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR = 1000323000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = 1000325000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001, VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT = 1000328000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT = 1000328001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001, VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = 1000335000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, - VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR = 1000337000, - VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR = 1000337001, - VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR = 1000337002, - VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR = 1000337003, - VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR = 1000337004, - VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR = 1000337005, - VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR = 1000337006, - VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR = 1000337007, - VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = 1000337008, - VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = 1000337009, - VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = 1000337010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT = 1000338000, + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT = 1000338001, + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT = 1000338004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT = 1000339000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT = 1000341000, + VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT = 1000341001, + VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT = 1000341002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000, VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = 1000351000, - VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = 1000351002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000, VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001, VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT = 1000354000, + VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT = 1000354001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT = 1000355000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT = 1000355001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000, VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000, VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001, VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002, VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365000, VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365001, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1000366000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1000366001, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1000366002, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1000366003, + VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA = 1000366004, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA = 1000366005, + VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA = 1000366006, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA = 1000366007, + VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA = 1000366008, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA = 1000366009, VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI = 1000369000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI = 1000369001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI = 1000369002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI = 1000370000, VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV = 1000371000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001, + VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT = 1000372000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT = 1000372001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT = 1000375000, + VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT = 1000375001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT = 1000376000, + VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT = 1000376001, + VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT = 1000376002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT = 1000377000, VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX = 1000378000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT = 1000381000, VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = 1000388000, - VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = 1000388001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT = 1000382000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR = 1000386000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT = 1000391000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT = 1000391001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT = 1000395000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT = 1000395001, + VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT = 1000396000, + VK_STRUCTURE_TYPE_MICROMAP_VERSION_INFO_EXT = 1000396001, + VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT = 1000396002, + VK_STRUCTURE_TYPE_COPY_MICROMAP_TO_MEMORY_INFO_EXT = 1000396003, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_MICROMAP_INFO_EXT = 1000396004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT = 1000396005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT = 1000396006, + VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT = 1000396007, + VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT = 1000396008, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT = 1000396009, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV = 1000397000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV = 1000397001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV = 1000397002, +#endif + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI = 1000404000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI = 1000404001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000, + VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM = 1000415000, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_SHADER_CORE_CONTROL_CREATE_INFO_ARM = 1000417000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM = 1000417001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_PROPERTIES_ARM = 1000417002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT = 1000418000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_SLICED_CREATE_INFO_EXT = 1000418001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = 1000421000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = 1000425000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = 1000425001, + VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = 1000425002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV = 1000426000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = 1000426001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = 1000427000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = 1000427001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV = 1000428000, + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_INDIRECT_BUFFER_INFO_NV = 1000428001, + VK_STRUCTURE_TYPE_PIPELINE_INDIRECT_DEVICE_ADDRESS_INFO_NV = 1000428002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT = 1000437000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM = 1000440000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM = 1000440001, + VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT = 1000451000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT = 1000451001, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT = 1000453000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT = 1000458000, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT = 1000458001, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000458002, + VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT = 1000458003, + VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG = 1000459000, + VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG = 1000459001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT = 1000462000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT = 1000462001, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT = 1000462002, + VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT = 1000462003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT = 1000342000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV = 1000464000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV = 1000464001, + VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV = 1000464002, + VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV = 1000464003, + VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_INFO_NV = 1000464004, + VK_STRUCTURE_TYPE_OPTICAL_FLOW_EXECUTE_INFO_NV = 1000464005, + VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = 1000466000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID = 1000468000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468001, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = 1000470000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = 1000470001, + VK_STRUCTURE_TYPE_RENDERING_AREA_INFO_KHR = 1000470003, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_SUBRESOURCE_INFO_KHR = 1000470004, + VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_KHR = 1000338002, + VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_KHR = 1000338003, + VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR = 1000470005, + VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR = 1000470006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR = 1000481000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT = 1000482000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT = 1000482001, + VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT = 1000482002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000, + VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM = 1000484001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000, + VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC = 1000485001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV = 1000490000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV = 1000490001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV = 1000492000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV = 1000492001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT = 1000351000, + VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT = 1000499000, + VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV = 1000505000, + VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV = 1000505001, + VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV = 1000505002, + VK_STRUCTURE_TYPE_GET_LATENCY_MARKER_INFO_NV = 1000505003, + VK_STRUCTURE_TYPE_LATENCY_TIMINGS_FRAME_REPORT_NV = 1000505004, + VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV = 1000505005, + VK_STRUCTURE_TYPE_OUT_OF_BAND_QUEUE_TYPE_INFO_NV = 1000505006, + VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV = 1000505007, + VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV = 1000505008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR = 1000506000, + VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM = 1000518000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM = 1000518001, + VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM = 1000518002, + VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM = 1000519000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM = 1000519001, + VK_STRUCTURE_TYPE_BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM = 1000519002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM = 1000520000, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM = 1000520001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM = 1000521000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT = 1000524000, + VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX = 1000529000, + VK_STRUCTURE_TYPE_SCREEN_BUFFER_FORMAT_PROPERTIES_QNX = 1000529001, + VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX = 1000529002, + VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_QNX = 1000529003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX = 1000529004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT = 1000530000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV = 1000546000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_RENDERING_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_INFO, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD, VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, @@ -865,6 +1180,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO, VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES, VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, @@ -907,6 +1223,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO, VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2, @@ -928,13 +1248,16 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES, VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES, VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, @@ -943,12 +1266,17 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT, VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT, VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES, VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, @@ -957,9 +1285,57 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO, VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES, + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO, + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR = VK_STRUCTURE_TYPE_IMAGE_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2, + VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT = VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_KHR, + VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, + VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, + VK_STRUCTURE_TYPE_PIPELINE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS, + VK_STRUCTURE_TYPE_SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; +typedef enum VkPipelineCacheHeaderVersion { + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheHeaderVersion; + typedef enum VkImageLayout { VK_IMAGE_LAYOUT_UNDEFINED = 0, VK_IMAGE_LAYOUT_GENERAL = 1, @@ -976,16 +1352,12 @@ typedef enum VkImageLayout { VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL = 1000314000, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR = 1000024000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR = 1000024001, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR = 1000024002, -#endif VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003, @@ -998,8 +1370,7 @@ typedef enum VkImageLayout { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR = 1000299002, #endif - VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = 1000314000, - VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = 1000314001, + VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT = 1000339000, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, @@ -1007,6 +1378,8 @@ typedef enum VkImageLayout { VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF } VkImageLayout; @@ -1039,17 +1412,14 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_COMMAND_POOL = 25, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT = 1000295000, VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_OBJECT_TYPE_VIDEO_SESSION_KHR = 1000023000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR = 1000023001, -#endif VK_OBJECT_TYPE_CU_MODULE_NVX = 1000029000, VK_OBJECT_TYPE_CU_FUNCTION_NVX = 1000029001, VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, @@ -1059,17 +1429,18 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000, VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000, - VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = 1000295000, + VK_OBJECT_TYPE_CUDA_MODULE_NV = 1000307000, + VK_OBJECT_TYPE_CUDA_FUNCTION_NV = 1000307001, + VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000, + VK_OBJECT_TYPE_MICROMAP_EXT = 1000396000, + VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV = 1000464000, + VK_OBJECT_TYPE_SHADER_EXT = 1000482000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = VK_OBJECT_TYPE_PRIVATE_DATA_SLOT, VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF } VkObjectType; -typedef enum VkPipelineCacheHeaderVersion { - VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, - VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF -} VkPipelineCacheHeaderVersion; - typedef enum VkVendorId { VK_VENDOR_ID_VIV = 0x10001, VK_VENDOR_ID_VSI = 0x10002, @@ -1077,6 +1448,7 @@ typedef enum VkVendorId { VK_VENDOR_ID_CODEPLAY = 0x10004, VK_VENDOR_ID_MESA = 0x10005, VK_VENDOR_ID_POCL = 0x10006, + VK_VENDOR_ID_MOBILEYE = 0x10007, VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF } VkVendorId; @@ -1314,6 +1686,26 @@ typedef enum VkFormat { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031, VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032, VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033, + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM = 1000330000, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 = 1000330001, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 = 1000330002, + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM = 1000330003, + VK_FORMAT_A4R4G4B4_UNORM_PACK16 = 1000340000, + VK_FORMAT_A4B4G4R4_UNORM_PACK16 = 1000340001, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000, + VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK = 1000066001, + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK = 1000066002, + VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK = 1000066003, + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK = 1000066004, + VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK = 1000066005, + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK = 1000066006, + VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK = 1000066007, + VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK = 1000066008, + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK = 1000066009, + VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK = 1000066010, + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK = 1000066011, + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK = 1000066012, + VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK = 1000066013, VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000, VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001, VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002, @@ -1322,26 +1714,23 @@ typedef enum VkFormat { VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, - VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = 1000066000, - VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = 1000066001, - VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = 1000066002, - VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT = 1000066003, - VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT = 1000066004, - VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT = 1000066005, - VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT = 1000066006, - VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT = 1000066007, - VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT = 1000066008, - VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT = 1000066009, - VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT = 1000066010, - VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = 1000066011, - VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = 1000066012, - VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = 1000066013, - VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT = 1000330000, - VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT = 1000330001, - VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT = 1000330002, - VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT = 1000330003, - VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = 1000340000, - VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = 1000340001, + VK_FORMAT_R16G16_S10_5_NV = 1000464000, + VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR = 1000470000, + VK_FORMAT_A8_UNORM_KHR = 1000470001, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK, + VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK, + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK, + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK, + VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK, VK_FORMAT_G8B8G8R8_422_UNORM_KHR = VK_FORMAT_G8B8G8R8_422_UNORM, VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM, VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, @@ -1376,6 +1765,12 @@ typedef enum VkFormat { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT = VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, + VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = VK_FORMAT_A4R4G4B4_UNORM_PACK16, + VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = VK_FORMAT_A4B4G4R4_UNORM_PACK16, VK_FORMAT_MAX_ENUM = 0x7FFFFFFF } VkFormat; @@ -1406,9 +1801,7 @@ typedef enum VkQueryType { VK_QUERY_TYPE_OCCLUSION = 0, VK_QUERY_TYPE_PIPELINE_STATISTICS = 1, VK_QUERY_TYPE_TIMESTAMP = 2, -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR = 1000023000, -#endif VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004, VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000, @@ -1416,8 +1809,14 @@ typedef enum VkQueryType { VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000, + VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR = 1000299000, #endif + VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT = 1000328000, + VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT = 1000382000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR = 1000386000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR = 1000386001, + VK_QUERY_TYPE_MICROMAP_SERIALIZATION_SIZE_EXT = 1000396000, + VK_QUERY_TYPE_MICROMAP_COMPACTED_SIZE_EXT = 1000396001, VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF } VkQueryType; @@ -1549,34 +1948,84 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6, VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7, VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8, + VK_DYNAMIC_STATE_CULL_MODE = 1000267000, + VK_DYNAMIC_STATE_FRONT_FACE = 1000267001, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = 1000267002, + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT = 1000267003, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT = 1000267004, + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE = 1000267005, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE = 1000267006, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE = 1000267007, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP = 1000267008, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE = 1000267009, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE = 1000267010, + VK_DYNAMIC_STATE_STENCIL_OP = 1000267011, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE = 1000377001, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE = 1000377002, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004, VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT = 1000099001, + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT = 1000099002, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000, VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004, VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, + VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV = 1000205000, VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000, VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000, - VK_DYNAMIC_STATE_CULL_MODE_EXT = 1000267000, - VK_DYNAMIC_STATE_FRONT_FACE_EXT = 1000267001, - VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT = 1000267002, - VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT = 1000267003, - VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT = 1000267004, - VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT = 1000267005, - VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT = 1000267006, - VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT = 1000267007, - VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT = 1000267008, - VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT = 1000267009, - VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT = 1000267010, - VK_DYNAMIC_STATE_STENCIL_OP_EXT = 1000267011, VK_DYNAMIC_STATE_VERTEX_INPUT_EXT = 1000352000, VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT = 1000377000, - VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT = 1000377001, - VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT = 1000377002, VK_DYNAMIC_STATE_LOGIC_OP_EXT = 1000377003, - VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT = 1000377004, VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT = 1000381000, + VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT = 1000455002, + VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT = 1000455003, + VK_DYNAMIC_STATE_POLYGON_MODE_EXT = 1000455004, + VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT = 1000455005, + VK_DYNAMIC_STATE_SAMPLE_MASK_EXT = 1000455006, + VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT = 1000455007, + VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT = 1000455008, + VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT = 1000455009, + VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT = 1000455010, + VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT = 1000455011, + VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT = 1000455012, + VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT = 1000455013, + VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT = 1000455014, + VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT = 1000455015, + VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT = 1000455016, + VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT = 1000455017, + VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT = 1000455018, + VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT = 1000455019, + VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT = 1000455020, + VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT = 1000455021, + VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT = 1000455022, + VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV = 1000455023, + VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV = 1000455024, + VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV = 1000455025, + VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV = 1000455026, + VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV = 1000455027, + VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV = 1000455028, + VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV = 1000455029, + VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV = 1000455030, + VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV = 1000455031, + VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV = 1000455032, + VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT = 1000524000, + VK_DYNAMIC_STATE_CULL_MODE_EXT = VK_DYNAMIC_STATE_CULL_MODE, + VK_DYNAMIC_STATE_FRONT_FACE_EXT = VK_DYNAMIC_STATE_FRONT_FACE, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, + VK_DYNAMIC_STATE_STENCIL_OP_EXT = VK_DYNAMIC_STATE_STENCIL_OP, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE, VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF } VkDynamicState; @@ -1662,8 +2111,8 @@ typedef enum VkBorderColor { typedef enum VkFilter { VK_FILTER_NEAREST = 0, VK_FILTER_LINEAR = 1, - VK_FILTER_CUBIC_IMG = 1000015000, - VK_FILTER_CUBIC_EXT = VK_FILTER_CUBIC_IMG, + VK_FILTER_CUBIC_EXT = 1000015000, + VK_FILTER_CUBIC_IMG = VK_FILTER_CUBIC_EXT, VK_FILTER_MAX_ENUM = 0x7FFFFFFF } VkFilter; @@ -1695,10 +2144,14 @@ typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, - VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000, + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, - VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = 1000351000, + VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, + VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001, + VK_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000, + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, + VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = VK_DESCRIPTOR_TYPE_MUTABLE_EXT, VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF } VkDescriptorType; @@ -1713,14 +2166,19 @@ typedef enum VkAttachmentLoadOp { typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_STORE = 0, VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, - VK_ATTACHMENT_STORE_OP_NONE_EXT = 1000301000, - VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE_EXT, + VK_ATTACHMENT_STORE_OP_NONE = 1000301000, + VK_ATTACHMENT_STORE_OP_NONE_KHR = VK_ATTACHMENT_STORE_OP_NONE, + VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE, + VK_ATTACHMENT_STORE_OP_NONE_EXT = VK_ATTACHMENT_STORE_OP_NONE, VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentStoreOp; typedef enum VkPipelineBindPoint { VK_PIPELINE_BIND_POINT_GRAPHICS = 0, VK_PIPELINE_BIND_POINT_COMPUTE = 1, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX = 1000134000, +#endif VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, @@ -1745,6 +2203,7 @@ typedef enum VkIndexType { typedef enum VkSubpassContents { VK_SUBPASS_CONTENTS_INLINE = 0, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, + VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT = 1000451000, VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF } VkSubpassContents; @@ -1766,6 +2225,7 @@ typedef enum VkAccessFlagBits { VK_ACCESS_HOST_WRITE_BIT = 0x00004000, VK_ACCESS_MEMORY_READ_BIT = 0x00008000, VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, + VK_ACCESS_NONE = 0, VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, @@ -1777,10 +2237,10 @@ typedef enum VkAccessFlagBits { VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000, VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000, VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000, - VK_ACCESS_NONE_KHR = 0, VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + VK_ACCESS_NONE_KHR = VK_ACCESS_NONE, VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkAccessFlagBits; typedef VkFlags VkAccessFlags; @@ -1793,6 +2253,7 @@ typedef enum VkImageAspectFlagBits { VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, + VK_IMAGE_ASPECT_NONE = 0, VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080, VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100, VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200, @@ -1800,6 +2261,7 @@ typedef enum VkImageAspectFlagBits { VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, + VK_IMAGE_ASPECT_NONE_KHR = VK_IMAGE_ASPECT_NONE, VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageAspectFlagBits; typedef VkFlags VkImageAspectFlags; @@ -1828,14 +2290,10 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000, VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000, -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000, -#endif VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0x00002000, VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000, VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000, #ifdef VK_ENABLE_BETA_EXTENSIONS @@ -1844,6 +2302,7 @@ typedef enum VkFormatFeatureFlagBits { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000, #endif + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT, @@ -1854,7 +2313,6 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT, VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = VK_FORMAT_FEATURE_DISJOINT_BIT, VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG, VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkFormatFeatureFlagBits; typedef VkFlags VkFormatFeatureFlags; @@ -1875,6 +2333,10 @@ typedef enum VkImageCreateFlagBits { VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000, VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000, VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0x00004000, + VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00010000, + VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT = 0x00040000, + VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT = 0x00020000, + VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM = 0x00008000, VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT, VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT, @@ -1906,17 +2368,12 @@ typedef enum VkImageUsageFlagBits { VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00000400, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00000800, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR = 0x00001000, -#endif VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200, VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00000100, + VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT = 0x00400000, #ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00002000, #endif @@ -1926,11 +2383,19 @@ typedef enum VkImageUsageFlagBits { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR = 0x00008000, #endif + VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x00080000, VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI = 0x00040000, + VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM = 0x00100000, + VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM = 0x00200000, VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageUsageFlagBits; typedef VkFlags VkImageUsageFlags; + +typedef enum VkInstanceCreateFlagBits { + VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR = 0x00000001, + VK_INSTANCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkInstanceCreateFlagBits; typedef VkFlags VkInstanceCreateFlags; typedef enum VkMemoryHeapFlagBits { @@ -1961,12 +2426,11 @@ typedef enum VkQueueFlagBits { VK_QUEUE_TRANSFER_BIT = 0x00000004, VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, VK_QUEUE_PROTECTED_BIT = 0x00000010, -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_QUEUE_VIDEO_DECODE_BIT_KHR = 0x00000020, -#endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_QUEUE_VIDEO_ENCODE_BIT_KHR = 0x00000040, #endif + VK_QUEUE_OPTICAL_FLOW_BIT_NV = 0x00000100, VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueueFlagBits; typedef VkFlags VkQueueFlags; @@ -1996,19 +2460,22 @@ typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_HOST_BIT = 0x00004000, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, + VK_PIPELINE_STAGE_NONE = 0, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, - VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000, - VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000, VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000, VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000, - VK_PIPELINE_STAGE_NONE_KHR = 0, + VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT = 0x00080000, + VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT = 0x00100000, VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT, + VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, + VK_PIPELINE_STAGE_NONE_KHR = VK_PIPELINE_STAGE_NONE, VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineStageFlagBits; typedef VkFlags VkPipelineStageFlags; @@ -2036,7 +2503,8 @@ typedef VkFlags VkFenceCreateFlags; typedef VkFlags VkSemaphoreCreateFlags; typedef enum VkEventCreateFlagBits { - VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = 0x00000001, + VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0x00000001, + VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = VK_EVENT_CREATE_DEVICE_ONLY_BIT, VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkEventCreateFlagBits; typedef VkFlags VkEventCreateFlags; @@ -2053,6 +2521,9 @@ typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100, VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200, VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400, + VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT = 0x00000800, + VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT = 0x00001000, + VK_QUERY_PIPELINE_STATISTIC_CLUSTER_CULLING_SHADER_INVOCATIONS_BIT_HUAWEI = 0x00002000, VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryPipelineStatisticFlagBits; typedef VkFlags VkQueryPipelineStatisticFlags; @@ -2063,9 +2534,7 @@ typedef enum VkQueryResultFlagBits { VK_QUERY_RESULT_WAIT_BIT = 0x00000002, VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004, VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008, -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_QUERY_RESULT_WITH_STATUS_BIT_KHR = 0x00000010, -#endif VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryResultFlagBits; typedef VkFlags VkQueryResultFlags; @@ -2076,6 +2545,7 @@ typedef enum VkBufferCreateFlagBits { VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004, VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000010, + VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000020, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -2093,15 +2563,14 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 0x00020000, -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00004000, -#endif VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000, +#endif VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400, @@ -2111,6 +2580,11 @@ typedef enum VkBufferUsageFlagBits { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000, #endif + VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0x00200000, + VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00400000, + VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0x04000000, + VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0x00800000, + VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT = 0x01000000, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, @@ -2121,18 +2595,16 @@ typedef VkFlags VkBufferViewCreateFlags; typedef enum VkImageViewCreateFlagBits { VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001, + VK_IMAGE_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000004, VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT = 0x00000002, VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageViewCreateFlagBits; typedef VkFlags VkImageViewCreateFlags; - -typedef enum VkShaderModuleCreateFlagBits { - VK_SHADER_MODULE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkShaderModuleCreateFlagBits; typedef VkFlags VkShaderModuleCreateFlags; typedef enum VkPipelineCacheCreateFlagBits { - VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT = 0x00000001, + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001, + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineCacheCreateFlagBits; typedef VkFlags VkPipelineCacheCreateFlags; @@ -2152,6 +2624,10 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 0x00000100, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT = 0x00000200, + VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000, + VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, @@ -2164,19 +2640,34 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080, VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00040000, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0x00000800, - VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = 0x00000100, - VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = 0x00000200, + VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0x20000000, + VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT = 0x00800000, + VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT = 0x00000400, VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000, + VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000, + VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000, + VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_PIPELINE_CREATE_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000, +#endif + VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT = 0x08000000, + VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT = 0x40000000, VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT, VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineCreateFlagBits; typedef VkFlags VkPipelineCreateFlags; typedef enum VkPipelineShaderStageCreateFlagBits { - VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000001, - VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000002, + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT = 0x00000001, + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT = 0x00000002, + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT, + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT, VK_PIPELINE_SHADER_STAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineShaderStageCreateFlagBits; typedef VkFlags VkPipelineShaderStageCreateFlags; @@ -2196,15 +2687,18 @@ typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, - VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040, - VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080, + VK_SHADER_STAGE_TASK_BIT_EXT = 0x00000040, + VK_SHADER_STAGE_MESH_BIT_EXT = 0x00000080, VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0x00004000, + VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI = 0x00080000, VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR, VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR, + VK_SHADER_STAGE_TASK_BIT_NV = VK_SHADER_STAGE_TASK_BIT_EXT, + VK_SHADER_STAGE_MESH_BIT_NV = VK_SHADER_STAGE_MESH_BIT_EXT, VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkShaderStageFlagBits; @@ -2222,15 +2716,37 @@ typedef VkFlags VkPipelineTessellationStateCreateFlags; typedef VkFlags VkPipelineViewportStateCreateFlags; typedef VkFlags VkPipelineRasterizationStateCreateFlags; typedef VkFlags VkPipelineMultisampleStateCreateFlags; + +typedef enum VkPipelineDepthStencilStateCreateFlagBits { + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0x00000001, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0x00000002, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineDepthStencilStateCreateFlagBits; typedef VkFlags VkPipelineDepthStencilStateCreateFlags; + +typedef enum VkPipelineColorBlendStateCreateFlagBits { + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT = 0x00000001, + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT, + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineColorBlendStateCreateFlagBits; typedef VkFlags VkPipelineColorBlendStateCreateFlags; typedef VkFlags VkPipelineDynamicStateCreateFlags; + +typedef enum VkPipelineLayoutCreateFlagBits { + VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0x00000002, + VK_PIPELINE_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineLayoutCreateFlagBits; typedef VkFlags VkPipelineLayoutCreateFlags; typedef VkFlags VkShaderStageFlags; typedef enum VkSamplerCreateFlagBits { VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001, VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002, + VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000008, + VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT = 0x00000004, + VK_SAMPLER_CREATE_IMAGE_PROCESSING_BIT_QCOM = 0x00000010, VK_SAMPLER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSamplerCreateFlagBits; typedef VkFlags VkSamplerCreateFlags; @@ -2238,8 +2754,11 @@ typedef VkFlags VkSamplerCreateFlags; typedef enum VkDescriptorPoolCreateFlagBits { VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002, - VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = 0x00000004, + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT = 0x00000004, + VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV = 0x00000008, + VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV = 0x00000010, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT, VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorPoolCreateFlagBits; typedef VkFlags VkDescriptorPoolCreateFlags; @@ -2248,8 +2767,12 @@ typedef VkFlags VkDescriptorPoolResetFlags; typedef enum VkDescriptorSetLayoutCreateFlagBits { VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = 0x00000004, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00000010, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT = 0x00000020, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00000080, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT = 0x00000004, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT, VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorSetLayoutCreateFlagBits; typedef VkFlags VkDescriptorSetLayoutCreateFlags; @@ -2264,6 +2787,7 @@ typedef enum VkDependencyFlagBits { VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004, VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002, + VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT = 0x00000008, VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT, VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT, VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -2288,6 +2812,13 @@ typedef enum VkSubpassDescriptionFlagBits { VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = 0x00000004, VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = 0x00000008, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT = 0x00000010, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0x00000020, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0x00000040, + VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x00000080, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT, VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSubpassDescriptionFlagBits; typedef VkFlags VkSubpassDescriptionFlags; @@ -4395,6 +4926,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( #endif +// VK_VERSION_1_1 is a preprocessor guard. Do not pass it to API calls. #define VK_VERSION_1_1 1 // Vulkan 1.1 version number #define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)// Patch version should always be set to 0 @@ -4512,6 +5044,7 @@ typedef enum VkExternalMemoryHandleTypeFlagBits { VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100, VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0x00000800, VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0x00001000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX = 0x00004000, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, @@ -5260,6 +5793,7 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( #endif +// VK_VERSION_1_2 is a preprocessor guard. Do not pass it to API calls. #define VK_VERSION_1_2 1 // Vulkan 1.2 version number #define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)// Patch version should always be set to 0 @@ -5285,6 +5819,15 @@ typedef enum VkDriverId { VK_DRIVER_ID_COREAVI_PROPRIETARY = 15, VK_DRIVER_ID_JUICE_PROPRIETARY = 16, VK_DRIVER_ID_VERISILICON_PROPRIETARY = 17, + VK_DRIVER_ID_MESA_TURNIP = 18, + VK_DRIVER_ID_MESA_V3DV = 19, + VK_DRIVER_ID_MESA_PANVK = 20, + VK_DRIVER_ID_SAMSUNG_PROPRIETARY = 21, + VK_DRIVER_ID_MESA_VENUS = 22, + VK_DRIVER_ID_MESA_DOZEN = 23, + VK_DRIVER_ID_MESA_NVK = 24, + VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA = 25, + VK_DRIVER_ID_MESA_AGXV = 26, VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, @@ -5314,6 +5857,7 @@ typedef enum VkSamplerReductionMode { VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0, VK_SAMPLER_REDUCTION_MODE_MIN = 1, VK_SAMPLER_REDUCTION_MODE_MAX = 2, + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM = 1000521000, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, VK_SAMPLER_REDUCTION_MODE_MIN_EXT = VK_SAMPLER_REDUCTION_MODE_MIN, VK_SAMPLER_REDUCTION_MODE_MAX_EXT = VK_SAMPLER_REDUCTION_MODE_MAX, @@ -5334,6 +5878,7 @@ typedef enum VkResolveModeFlagBits { VK_RESOLVE_MODE_AVERAGE_BIT = 0x00000002, VK_RESOLVE_MODE_MIN_BIT = 0x00000004, VK_RESOLVE_MODE_MAX_BIT = 0x00000008, + VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID = 0x00000010, VK_RESOLVE_MODE_NONE_KHR = VK_RESOLVE_MODE_NONE, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, VK_RESOLVE_MODE_AVERAGE_BIT_KHR = VK_RESOLVE_MODE_AVERAGE_BIT, @@ -6006,6678 +6551,11540 @@ VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress( #endif -#define VK_KHR_surface 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) -#define VK_KHR_SURFACE_SPEC_VERSION 25 -#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" +// VK_VERSION_1_3 is a preprocessor guard. Do not pass it to API calls. +#define VK_VERSION_1_3 1 +// Vulkan 1.3 version number +#define VK_API_VERSION_1_3 VK_MAKE_API_VERSION(0, 1, 3, 0)// Patch version should always be set to 0 -typedef enum VkPresentModeKHR { - VK_PRESENT_MODE_IMMEDIATE_KHR = 0, - VK_PRESENT_MODE_MAILBOX_KHR = 1, - VK_PRESENT_MODE_FIFO_KHR = 2, - VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, - VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, - VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, - VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPresentModeKHR; +typedef uint64_t VkFlags64; +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlot) + +typedef enum VkPipelineCreationFeedbackFlagBits { + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 0x00000001, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 0x00000002, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 0x00000004, + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCreationFeedbackFlagBits; +typedef VkFlags VkPipelineCreationFeedbackFlags; + +typedef enum VkToolPurposeFlagBits { + VK_TOOL_PURPOSE_VALIDATION_BIT = 0x00000001, + VK_TOOL_PURPOSE_PROFILING_BIT = 0x00000002, + VK_TOOL_PURPOSE_TRACING_BIT = 0x00000004, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT = 0x00000008, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT = 0x00000010, + VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT = 0x00000020, + VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT = 0x00000040, + VK_TOOL_PURPOSE_VALIDATION_BIT_EXT = VK_TOOL_PURPOSE_VALIDATION_BIT, + VK_TOOL_PURPOSE_PROFILING_BIT_EXT = VK_TOOL_PURPOSE_PROFILING_BIT, + VK_TOOL_PURPOSE_TRACING_BIT_EXT = VK_TOOL_PURPOSE_TRACING_BIT, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT, + VK_TOOL_PURPOSE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkToolPurposeFlagBits; +typedef VkFlags VkToolPurposeFlags; +typedef VkFlags VkPrivateDataSlotCreateFlags; +typedef VkFlags64 VkPipelineStageFlags2; + +// Flag bits for VkPipelineStageFlagBits2 +typedef VkFlags64 VkPipelineStageFlagBits2; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE = 0ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE_KHR = 0ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 0x00000001ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 0x00000002ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 0x00000004ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 0x00000008ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 0x00000040ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 0x00000080ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 0x00000100ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 0x00000200ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 0x00000800ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 0x00002000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT = 0x00004000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 0x00008000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 0x00010000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT = 0x100000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT = 0x200000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT = 0x400000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT = 0x800000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 0x1000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 0x2000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 0x4000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0x04000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0x08000000ULL; +#endif +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT = 0x00080000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT = 0x00100000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI = 0x8000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0x10000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT = 0x40000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI = 0x20000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV = 0x20000000ULL; + +typedef VkFlags64 VkAccessFlags2; + +// Flag bits for VkAccessFlagBits2 +typedef VkFlags64 VkAccessFlagBits2; +static const VkAccessFlagBits2 VK_ACCESS_2_NONE = 0ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_NONE_KHR = 0ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 0x00000001ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT = 0x00000002ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT = 0x00000008ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 0x00000010ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT = 0x00000020ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT = 0x00000040ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 0x00000080ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT = 0x00000800ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT = 0x00001000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT = 0x00002000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT = 0x00004000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT = 0x00008000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT = 0x00010000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 0x100000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 0x200000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 0x400000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL; +#endif +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT = 0x20000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0x8000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR = 0x10000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_READ_BIT_EXT = 0x100000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT = 0x200000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV = 0x40000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV = 0x80000000000ULL; + + +typedef enum VkSubmitFlagBits { + VK_SUBMIT_PROTECTED_BIT = 0x00000001, + VK_SUBMIT_PROTECTED_BIT_KHR = VK_SUBMIT_PROTECTED_BIT, + VK_SUBMIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubmitFlagBits; +typedef VkFlags VkSubmitFlags; + +typedef enum VkRenderingFlagBits { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 0x00000001, + VK_RENDERING_SUSPENDING_BIT = 0x00000002, + VK_RENDERING_RESUMING_BIT = 0x00000004, + VK_RENDERING_CONTENTS_INLINE_BIT_EXT = 0x00000010, + VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x00000008, + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, + VK_RENDERING_SUSPENDING_BIT_KHR = VK_RENDERING_SUSPENDING_BIT, + VK_RENDERING_RESUMING_BIT_KHR = VK_RENDERING_RESUMING_BIT, + VK_RENDERING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderingFlagBits; +typedef VkFlags VkRenderingFlags; +typedef VkFlags64 VkFormatFeatureFlags2; + +// Flag bits for VkFormatFeatureFlagBits2 +typedef VkFlags64 VkFormatFeatureFlagBits2; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT = 0x00000001ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR = 0x00000001ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT = 0x00000002ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR = 0x00000002ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR = 0x00000004ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT = 0x00000010ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000010ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT_KHR = 0x00000020ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT = 0x00000040ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT_KHR = 0x00000040ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT = 0x00000080ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT_KHR = 0x00000080ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT_KHR = 0x00000100ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR = 0x00000200ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT = 0x00000400ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT_KHR = 0x00000400ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT = 0x00000800ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT_KHR = 0x00000800ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT_KHR = 0x00001000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT = 0x00002000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0x00002000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT = 0x00004000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR = 0x00004000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT = 0x00008000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR = 0x00008000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT_KHR = 0x00010000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 0x00020000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 0x00040000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 0x00080000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 0x00100000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 0x00200000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT = 0x00400000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR = 0x00400000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT = 0x00800000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR = 0x00800000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT = 0x80000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR = 0x80000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT = 0x100000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR = 0x100000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT = 0x200000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR = 0x200000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT = 0x400000000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000ULL; +#endif +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV = 0x4000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM = 0x400000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM = 0x800000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM = 0x1000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM = 0x2000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV = 0x10000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV = 0x20000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV = 0x40000000000ULL; + +typedef struct VkPhysicalDeviceVulkan13Features { + VkStructureType sType; + void* pNext; + VkBool32 robustImageAccess; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; + VkBool32 pipelineCreationCacheControl; + VkBool32 privateData; + VkBool32 shaderDemoteToHelperInvocation; + VkBool32 shaderTerminateInvocation; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; + VkBool32 synchronization2; + VkBool32 textureCompressionASTC_HDR; + VkBool32 shaderZeroInitializeWorkgroupMemory; + VkBool32 dynamicRendering; + VkBool32 shaderIntegerDotProduct; + VkBool32 maintenance4; +} VkPhysicalDeviceVulkan13Features; -typedef enum VkColorSpaceKHR { - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, - VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, - VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002, - VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104003, - VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004, - VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005, - VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006, - VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007, - VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008, - VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009, - VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010, - VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011, - VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012, - VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013, - VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014, - VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000, - VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, - VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, - VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkColorSpaceKHR; +typedef struct VkPhysicalDeviceVulkan13Properties { + VkStructureType sType; + void* pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; + uint32_t maxInlineUniformTotalSize; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceVulkan13Properties; + +typedef struct VkPipelineCreationFeedback { + VkPipelineCreationFeedbackFlags flags; + uint64_t duration; +} VkPipelineCreationFeedback; + +typedef struct VkPipelineCreationFeedbackCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreationFeedback* pPipelineCreationFeedback; + uint32_t pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedback* pPipelineStageCreationFeedbacks; +} VkPipelineCreationFeedbackCreateInfo; -typedef enum VkSurfaceTransformFlagBitsKHR { - VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, - VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, - VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004, - VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008, - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010, - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020, - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040, - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080, - VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, - VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkSurfaceTransformFlagBitsKHR; +typedef struct VkPhysicalDeviceShaderTerminateInvocationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderTerminateInvocation; +} VkPhysicalDeviceShaderTerminateInvocationFeatures; -typedef enum VkCompositeAlphaFlagBitsKHR { - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, - VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002, - VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004, - VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008, - VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkCompositeAlphaFlagBitsKHR; -typedef VkFlags VkCompositeAlphaFlagsKHR; -typedef VkFlags VkSurfaceTransformFlagsKHR; -typedef struct VkSurfaceCapabilitiesKHR { - uint32_t minImageCount; - uint32_t maxImageCount; - VkExtent2D currentExtent; - VkExtent2D minImageExtent; - VkExtent2D maxImageExtent; - uint32_t maxImageArrayLayers; - VkSurfaceTransformFlagsKHR supportedTransforms; - VkSurfaceTransformFlagBitsKHR currentTransform; - VkCompositeAlphaFlagsKHR supportedCompositeAlpha; - VkImageUsageFlags supportedUsageFlags; -} VkSurfaceCapabilitiesKHR; - -typedef struct VkSurfaceFormatKHR { - VkFormat format; - VkColorSpaceKHR colorSpace; -} VkSurfaceFormatKHR; - -typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR( - VkInstance instance, - VkSurfaceKHR surface, - const VkAllocationCallbacks* pAllocator); +typedef struct VkPhysicalDeviceToolProperties { + VkStructureType sType; + void* pNext; + char name[VK_MAX_EXTENSION_NAME_SIZE]; + char version[VK_MAX_EXTENSION_NAME_SIZE]; + VkToolPurposeFlags purposes; + char description[VK_MAX_DESCRIPTION_SIZE]; + char layer[VK_MAX_EXTENSION_NAME_SIZE]; +} VkPhysicalDeviceToolProperties; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - VkSurfaceKHR surface, - VkBool32* pSupported); +typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderDemoteToHelperInvocation; +} VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); +typedef struct VkPhysicalDevicePrivateDataFeatures { + VkStructureType sType; + void* pNext; + VkBool32 privateData; +} VkPhysicalDevicePrivateDataFeatures; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - uint32_t* pSurfaceFormatCount, - VkSurfaceFormatKHR* pSurfaceFormats); +typedef struct VkDevicePrivateDataCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t privateDataSlotRequestCount; +} VkDevicePrivateDataCreateInfo; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - uint32_t* pPresentModeCount, - VkPresentModeKHR* pPresentModes); -#endif +typedef struct VkPrivateDataSlotCreateInfo { + VkStructureType sType; + const void* pNext; + VkPrivateDataSlotCreateFlags flags; +} VkPrivateDataSlotCreateInfo; +typedef struct VkPhysicalDevicePipelineCreationCacheControlFeatures { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCreationCacheControl; +} VkPhysicalDevicePipelineCreationCacheControlFeatures; -#define VK_KHR_swapchain 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) -#define VK_KHR_SWAPCHAIN_SPEC_VERSION 70 -#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" +typedef struct VkMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; +} VkMemoryBarrier2; -typedef enum VkSwapchainCreateFlagBitsKHR { - VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001, - VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002, - VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004, - VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkSwapchainCreateFlagBitsKHR; -typedef VkFlags VkSwapchainCreateFlagsKHR; +typedef struct VkBufferMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier2; + +typedef struct VkImageMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier2; -typedef enum VkDeviceGroupPresentModeFlagBitsKHR { - VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001, - VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002, - VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004, - VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008, - VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkDeviceGroupPresentModeFlagBitsKHR; -typedef VkFlags VkDeviceGroupPresentModeFlagsKHR; -typedef struct VkSwapchainCreateInfoKHR { +typedef struct VkDependencyInfo { VkStructureType sType; const void* pNext; - VkSwapchainCreateFlagsKHR flags; - VkSurfaceKHR surface; - uint32_t minImageCount; - VkFormat imageFormat; - VkColorSpaceKHR imageColorSpace; - VkExtent2D imageExtent; - uint32_t imageArrayLayers; - VkImageUsageFlags imageUsage; - VkSharingMode imageSharingMode; - uint32_t queueFamilyIndexCount; - const uint32_t* pQueueFamilyIndices; - VkSurfaceTransformFlagBitsKHR preTransform; - VkCompositeAlphaFlagBitsKHR compositeAlpha; - VkPresentModeKHR presentMode; - VkBool32 clipped; - VkSwapchainKHR oldSwapchain; -} VkSwapchainCreateInfoKHR; - -typedef struct VkPresentInfoKHR { + VkDependencyFlags dependencyFlags; + uint32_t memoryBarrierCount; + const VkMemoryBarrier2* pMemoryBarriers; + uint32_t bufferMemoryBarrierCount; + const VkBufferMemoryBarrier2* pBufferMemoryBarriers; + uint32_t imageMemoryBarrierCount; + const VkImageMemoryBarrier2* pImageMemoryBarriers; +} VkDependencyInfo; + +typedef struct VkSemaphoreSubmitInfo { VkStructureType sType; const void* pNext; - uint32_t waitSemaphoreCount; - const VkSemaphore* pWaitSemaphores; - uint32_t swapchainCount; - const VkSwapchainKHR* pSwapchains; - const uint32_t* pImageIndices; - VkResult* pResults; -} VkPresentInfoKHR; + VkSemaphore semaphore; + uint64_t value; + VkPipelineStageFlags2 stageMask; + uint32_t deviceIndex; +} VkSemaphoreSubmitInfo; -typedef struct VkImageSwapchainCreateInfoKHR { +typedef struct VkCommandBufferSubmitInfo { VkStructureType sType; const void* pNext; - VkSwapchainKHR swapchain; -} VkImageSwapchainCreateInfoKHR; + VkCommandBuffer commandBuffer; + uint32_t deviceMask; +} VkCommandBufferSubmitInfo; -typedef struct VkBindImageMemorySwapchainInfoKHR { +typedef struct VkSubmitInfo2 { + VkStructureType sType; + const void* pNext; + VkSubmitFlags flags; + uint32_t waitSemaphoreInfoCount; + const VkSemaphoreSubmitInfo* pWaitSemaphoreInfos; + uint32_t commandBufferInfoCount; + const VkCommandBufferSubmitInfo* pCommandBufferInfos; + uint32_t signalSemaphoreInfoCount; + const VkSemaphoreSubmitInfo* pSignalSemaphoreInfos; +} VkSubmitInfo2; + +typedef struct VkPhysicalDeviceSynchronization2Features { VkStructureType sType; - const void* pNext; - VkSwapchainKHR swapchain; - uint32_t imageIndex; -} VkBindImageMemorySwapchainInfoKHR; + void* pNext; + VkBool32 synchronization2; +} VkPhysicalDeviceSynchronization2Features; -typedef struct VkAcquireNextImageInfoKHR { +typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures { VkStructureType sType; - const void* pNext; - VkSwapchainKHR swapchain; - uint64_t timeout; - VkSemaphore semaphore; - VkFence fence; - uint32_t deviceMask; -} VkAcquireNextImageInfoKHR; + void* pNext; + VkBool32 shaderZeroInitializeWorkgroupMemory; +} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures; -typedef struct VkDeviceGroupPresentCapabilitiesKHR { - VkStructureType sType; - void* pNext; - uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE]; - VkDeviceGroupPresentModeFlagsKHR modes; -} VkDeviceGroupPresentCapabilitiesKHR; +typedef struct VkPhysicalDeviceImageRobustnessFeatures { + VkStructureType sType; + void* pNext; + VkBool32 robustImageAccess; +} VkPhysicalDeviceImageRobustnessFeatures; -typedef struct VkDeviceGroupPresentInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const uint32_t* pDeviceMasks; - VkDeviceGroupPresentModeFlagBitsKHR mode; -} VkDeviceGroupPresentInfoKHR; +typedef struct VkBufferCopy2 { + VkStructureType sType; + const void* pNext; + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy2; -typedef struct VkDeviceGroupSwapchainCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkDeviceGroupPresentModeFlagsKHR modes; -} VkDeviceGroupSwapchainCreateInfoKHR; +typedef struct VkCopyBufferInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferCopy2* pRegions; +} VkCopyBufferInfo2; -typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain); -typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages); -typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex); -typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects); -typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex); +typedef struct VkImageCopy2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy2; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( - VkDevice device, - const VkSwapchainCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSwapchainKHR* pSwapchain); +typedef struct VkCopyImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2* pRegions; +} VkCopyImageInfo2; + +typedef struct VkBufferImageCopy2 { + VkStructureType sType; + const void* pNext; + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy2; -VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR( - VkDevice device, - VkSwapchainKHR swapchain, - const VkAllocationCallbacks* pAllocator); +typedef struct VkCopyBufferToImageInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkBufferImageCopy2* pRegions; +} VkCopyBufferToImageInfo2; -VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR( - VkDevice device, - VkSwapchainKHR swapchain, - uint32_t* pSwapchainImageCount, - VkImage* pSwapchainImages); +typedef struct VkCopyImageToBufferInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferImageCopy2* pRegions; +} VkCopyImageToBufferInfo2; -VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( - VkDevice device, - VkSwapchainKHR swapchain, - uint64_t timeout, - VkSemaphore semaphore, - VkFence fence, - uint32_t* pImageIndex); +typedef struct VkImageBlit2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit2; -VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( - VkQueue queue, - const VkPresentInfoKHR* pPresentInfo); +typedef struct VkBlitImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageBlit2* pRegions; + VkFilter filter; +} VkBlitImageInfo2; + +typedef struct VkImageResolve2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve2; -VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR( - VkDevice device, - VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); +typedef struct VkResolveImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageResolve2* pRegions; +} VkResolveImageInfo2; -VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR( - VkDevice device, - VkSurfaceKHR surface, - VkDeviceGroupPresentModeFlagsKHR* pModes); +typedef struct VkPhysicalDeviceSubgroupSizeControlFeatures { + VkStructureType sType; + void* pNext; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; +} VkPhysicalDeviceSubgroupSizeControlFeatures; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - uint32_t* pRectCount, - VkRect2D* pRects); +typedef struct VkPhysicalDeviceSubgroupSizeControlProperties { + VkStructureType sType; + void* pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; +} VkPhysicalDeviceSubgroupSizeControlProperties; -VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR( - VkDevice device, - const VkAcquireNextImageInfoKHR* pAcquireInfo, - uint32_t* pImageIndex); -#endif +typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfo { + VkStructureType sType; + void* pNext; + uint32_t requiredSubgroupSize; +} VkPipelineShaderStageRequiredSubgroupSizeCreateInfo; +typedef struct VkPhysicalDeviceInlineUniformBlockFeatures { + VkStructureType sType; + void* pNext; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; +} VkPhysicalDeviceInlineUniformBlockFeatures; -#define VK_KHR_display 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) -#define VK_KHR_DISPLAY_SPEC_VERSION 23 -#define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display" -typedef VkFlags VkDisplayModeCreateFlagsKHR; +typedef struct VkPhysicalDeviceInlineUniformBlockProperties { + VkStructureType sType; + void* pNext; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; +} VkPhysicalDeviceInlineUniformBlockProperties; -typedef enum VkDisplayPlaneAlphaFlagBitsKHR { - VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, - VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002, - VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004, - VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008, - VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkDisplayPlaneAlphaFlagBitsKHR; -typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; -typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; -typedef struct VkDisplayModeParametersKHR { - VkExtent2D visibleRegion; - uint32_t refreshRate; -} VkDisplayModeParametersKHR; +typedef struct VkWriteDescriptorSetInlineUniformBlock { + VkStructureType sType; + const void* pNext; + uint32_t dataSize; + const void* pData; +} VkWriteDescriptorSetInlineUniformBlock; -typedef struct VkDisplayModeCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkDisplayModeCreateFlagsKHR flags; - VkDisplayModeParametersKHR parameters; -} VkDisplayModeCreateInfoKHR; +typedef struct VkDescriptorPoolInlineUniformBlockCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t maxInlineUniformBlockBindings; +} VkDescriptorPoolInlineUniformBlockCreateInfo; -typedef struct VkDisplayModePropertiesKHR { - VkDisplayModeKHR displayMode; - VkDisplayModeParametersKHR parameters; -} VkDisplayModePropertiesKHR; +typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeatures { + VkStructureType sType; + void* pNext; + VkBool32 textureCompressionASTC_HDR; +} VkPhysicalDeviceTextureCompressionASTCHDRFeatures; -typedef struct VkDisplayPlaneCapabilitiesKHR { - VkDisplayPlaneAlphaFlagsKHR supportedAlpha; - VkOffset2D minSrcPosition; - VkOffset2D maxSrcPosition; - VkExtent2D minSrcExtent; - VkExtent2D maxSrcExtent; - VkOffset2D minDstPosition; - VkOffset2D maxDstPosition; - VkExtent2D minDstExtent; - VkExtent2D maxDstExtent; -} VkDisplayPlaneCapabilitiesKHR; +typedef struct VkRenderingAttachmentInfo { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkResolveModeFlagBits resolveMode; + VkImageView resolveImageView; + VkImageLayout resolveImageLayout; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkClearValue clearValue; +} VkRenderingAttachmentInfo; + +typedef struct VkRenderingInfo { + VkStructureType sType; + const void* pNext; + VkRenderingFlags flags; + VkRect2D renderArea; + uint32_t layerCount; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkRenderingAttachmentInfo* pColorAttachments; + const VkRenderingAttachmentInfo* pDepthAttachment; + const VkRenderingAttachmentInfo* pStencilAttachment; +} VkRenderingInfo; + +typedef struct VkPipelineRenderingCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkPipelineRenderingCreateInfo; + +typedef struct VkPhysicalDeviceDynamicRenderingFeatures { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRendering; +} VkPhysicalDeviceDynamicRenderingFeatures; -typedef struct VkDisplayPlanePropertiesKHR { - VkDisplayKHR currentDisplay; - uint32_t currentStackIndex; -} VkDisplayPlanePropertiesKHR; +typedef struct VkCommandBufferInheritanceRenderingInfo { + VkStructureType sType; + const void* pNext; + VkRenderingFlags flags; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; + VkSampleCountFlagBits rasterizationSamples; +} VkCommandBufferInheritanceRenderingInfo; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerDotProduct; +} VkPhysicalDeviceShaderIntegerDotProductFeatures; -typedef struct VkDisplayPropertiesKHR { - VkDisplayKHR display; - const char* displayName; - VkExtent2D physicalDimensions; - VkExtent2D physicalResolution; - VkSurfaceTransformFlagsKHR supportedTransforms; - VkBool32 planeReorderPossible; - VkBool32 persistentContent; -} VkDisplayPropertiesKHR; +typedef struct VkPhysicalDeviceShaderIntegerDotProductProperties { + VkStructureType sType; + void* pNext; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; +} VkPhysicalDeviceShaderIntegerDotProductProperties; + +typedef struct VkPhysicalDeviceTexelBufferAlignmentProperties { + VkStructureType sType; + void* pNext; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; +} VkPhysicalDeviceTexelBufferAlignmentProperties; -typedef struct VkDisplaySurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkDisplaySurfaceCreateFlagsKHR flags; - VkDisplayModeKHR displayMode; - uint32_t planeIndex; - uint32_t planeStackIndex; - VkSurfaceTransformFlagBitsKHR transform; - float globalAlpha; - VkDisplayPlaneAlphaFlagBitsKHR alphaMode; - VkExtent2D imageExtent; -} VkDisplaySurfaceCreateInfoKHR; +typedef struct VkFormatProperties3 { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags2 linearTilingFeatures; + VkFormatFeatureFlags2 optimalTilingFeatures; + VkFormatFeatureFlags2 bufferFeatures; +} VkFormatProperties3; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); -typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode); -typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef struct VkPhysicalDeviceMaintenance4Features { + VkStructureType sType; + void* pNext; + VkBool32 maintenance4; +} VkPhysicalDeviceMaintenance4Features; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkDisplayPropertiesKHR* pProperties); +typedef struct VkPhysicalDeviceMaintenance4Properties { + VkStructureType sType; + void* pNext; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceMaintenance4Properties; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkDisplayPlanePropertiesKHR* pProperties); +typedef struct VkDeviceBufferMemoryRequirements { + VkStructureType sType; + const void* pNext; + const VkBufferCreateInfo* pCreateInfo; +} VkDeviceBufferMemoryRequirements; -VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR( - VkPhysicalDevice physicalDevice, - uint32_t planeIndex, - uint32_t* pDisplayCount, - VkDisplayKHR* pDisplays); +typedef struct VkDeviceImageMemoryRequirements { + VkStructureType sType; + const void* pNext; + const VkImageCreateInfo* pCreateInfo; + VkImageAspectFlagBits planeAspect; +} VkDeviceImageMemoryRequirements; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolProperties)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlot)(VkDevice device, const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlot* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlot)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); +typedef void (VKAPI_PTR *PFN_vkGetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t* pData); +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2)(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRendering)(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRendering)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdSetCullMode)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFace)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopology)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCount)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCount)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnable)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOp)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnable)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOp)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnable)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnable)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirements)(VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); -VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR( +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolProperties( VkPhysicalDevice physicalDevice, - VkDisplayKHR display, - uint32_t* pPropertyCount, - VkDisplayModePropertiesKHR* pProperties); + uint32_t* pToolCount, + VkPhysicalDeviceToolProperties* pToolProperties); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR( - VkPhysicalDevice physicalDevice, - VkDisplayKHR display, - const VkDisplayModeCreateInfoKHR* pCreateInfo, +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlot( + VkDevice device, + const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, - VkDisplayModeKHR* pMode); + VkPrivateDataSlot* pPrivateDataSlot); -VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR( - VkPhysicalDevice physicalDevice, - VkDisplayModeKHR mode, - uint32_t planeIndex, - VkDisplayPlaneCapabilitiesKHR* pCapabilities); +VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlot( + VkDevice device, + VkPrivateDataSlot privateDataSlot, + const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( - VkInstance instance, - const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); -#endif +VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateData( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t data); +VKAPI_ATTR void VKAPI_CALL vkGetPrivateData( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t* pData); -#define VK_KHR_display_swapchain 1 -#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 10 -#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" -typedef struct VkDisplayPresentInfoKHR { - VkStructureType sType; - const void* pNext; - VkRect2D srcRect; - VkRect2D dstRect; - VkBool32 persistent; -} VkDisplayPresentInfoKHR; +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfo* pDependencyInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2 stageMask); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( - VkDevice device, - uint32_t swapchainCount, - const VkSwapchainCreateInfoKHR* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkSwapchainKHR* pSwapchains); -#endif +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfo* pDependencyInfos); +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2( + VkCommandBuffer commandBuffer, + const VkDependencyInfo* pDependencyInfo); -#define VK_KHR_sampler_mirror_clamp_to_edge 1 -#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 3 -#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkQueryPool queryPool, + uint32_t query); +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2* pSubmits, + VkFence fence); -#define VK_KHR_multiview 1 -#define VK_KHR_MULTIVIEW_SPEC_VERSION 1 -#define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" -typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR; +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2* pCopyBufferInfo); -typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR; +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2* pCopyImageInfo); -typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR; +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2* pBlitImageInfo); -#define VK_KHR_get_physical_device_properties2 1 -#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 2 -#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" -typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR; - -typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2* pResolveImageInfo); -typedef VkFormatProperties2 VkFormatProperties2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRendering( + VkCommandBuffer commandBuffer, + const VkRenderingInfo* pRenderingInfo); -typedef VkImageFormatProperties2 VkImageFormatProperties2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdEndRendering( + VkCommandBuffer commandBuffer); -typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdSetCullMode( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode); -typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFace( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace); -typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopology( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology); -typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCount( + VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport* pViewports); -typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCount( + VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D* pScissors); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceFeatures2* pFeatures); +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable); -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceProperties2* pProperties); +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable); -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR( - VkPhysicalDevice physicalDevice, - VkFormat format, - VkFormatProperties2* pFormatProperties); +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOp( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp); -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, - VkImageFormatProperties2* pImageFormatProperties); +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable); -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR( - VkPhysicalDevice physicalDevice, - uint32_t* pQueueFamilyPropertyCount, - VkQueueFamilyProperties2* pQueueFamilyProperties); +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable); -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOp( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp); -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, - uint32_t* pPropertyCount, - VkSparseImageFormatProperties2* pProperties); -#endif +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnable( + VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable); +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable); -#define VK_KHR_device_group 1 -#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 4 -#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group" -typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR; +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnable( + VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable); -typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR; +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirements( + VkDevice device, + const VkDeviceBufferMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); -typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR; +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirements( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); -typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR; +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirements( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif -typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR; -typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR; +// VK_KHR_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_surface 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) +#define VK_KHR_SURFACE_SPEC_VERSION 25 +#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" -typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR; +typedef enum VkPresentModeKHR { + VK_PRESENT_MODE_IMMEDIATE_KHR = 0, + VK_PRESENT_MODE_MAILBOX_KHR = 1, + VK_PRESENT_MODE_FIFO_KHR = 2, + VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, + VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentModeKHR; -typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR; +typedef enum VkColorSpaceKHR { + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, + VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, + VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002, + VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104003, + VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004, + VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005, + VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006, + VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007, + VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008, + VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009, + VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010, + VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011, + VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012, + VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013, + VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014, + VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000, + VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, + VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, + VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkColorSpaceKHR; -typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR; +typedef enum VkSurfaceTransformFlagBitsKHR { + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, + VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004, + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080, + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, + VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSurfaceTransformFlagBitsKHR; -typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR; +typedef enum VkCompositeAlphaFlagBitsKHR { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008, + VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCompositeAlphaFlagBitsKHR; +typedef VkFlags VkCompositeAlphaFlagsKHR; +typedef VkFlags VkSurfaceTransformFlagsKHR; +typedef struct VkSurfaceCapabilitiesKHR { + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; +} VkSurfaceCapabilitiesKHR; -typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR; +typedef struct VkSurfaceFormatKHR { + VkFormat format; + VkColorSpaceKHR colorSpace; +} VkSurfaceFormatKHR; -typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); -typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask); -typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR( - VkDevice device, - uint32_t heapIndex, - uint32_t localDeviceIndex, - uint32_t remoteDeviceIndex, - VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR( - VkCommandBuffer commandBuffer, - uint32_t deviceMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( - VkCommandBuffer commandBuffer, - uint32_t baseGroupX, - uint32_t baseGroupY, - uint32_t baseGroupZ, - uint32_t groupCountX, - uint32_t groupCountY, - uint32_t groupCountZ); -#endif - - -#define VK_KHR_shader_draw_parameters 1 -#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1 -#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters" +VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR( + VkInstance instance, + VkSurfaceKHR surface, + const VkAllocationCallbacks* pAllocator); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + VkSurfaceKHR surface, + VkBool32* pSupported); -#define VK_KHR_maintenance1 1 -#define VK_KHR_MAINTENANCE1_SPEC_VERSION 2 -#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1" -typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR; +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); -typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pSurfaceFormatCount, + VkSurfaceFormatKHR* pSurfaceFormats); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( - VkDevice device, - VkCommandPool commandPool, - VkCommandPoolTrimFlags flags); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pPresentModeCount, + VkPresentModeKHR* pPresentModes); #endif -#define VK_KHR_device_group_creation 1 -#define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1 -#define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation" -#define VK_MAX_DEVICE_GROUP_SIZE_KHR VK_MAX_DEVICE_GROUP_SIZE -typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR; - -typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR; +// VK_KHR_swapchain is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_swapchain 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) +#define VK_KHR_SWAPCHAIN_SPEC_VERSION 70 +#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" -typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR( - VkInstance instance, - uint32_t* pPhysicalDeviceGroupCount, - VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); -#endif - - -#define VK_KHR_external_memory_capabilities 1 -#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities" -#define VK_LUID_SIZE_KHR VK_LUID_SIZE -typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR; - -typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR; +typedef enum VkSwapchainCreateFlagBitsKHR { + VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001, + VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002, + VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004, + VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT = 0x00000008, + VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSwapchainCreateFlagBitsKHR; +typedef VkFlags VkSwapchainCreateFlagsKHR; -typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR; +typedef enum VkDeviceGroupPresentModeFlagBitsKHR { + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001, + VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002, + VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004, + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008, + VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceGroupPresentModeFlagBitsKHR; +typedef VkFlags VkDeviceGroupPresentModeFlagsKHR; +typedef struct VkSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainCreateFlagsKHR flags; + VkSurfaceKHR surface; + uint32_t minImageCount; + VkFormat imageFormat; + VkColorSpaceKHR imageColorSpace; + VkExtent2D imageExtent; + uint32_t imageArrayLayers; + VkImageUsageFlags imageUsage; + VkSharingMode imageSharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; + VkSurfaceTransformFlagBitsKHR preTransform; + VkCompositeAlphaFlagBitsKHR compositeAlpha; + VkPresentModeKHR presentMode; + VkBool32 clipped; + VkSwapchainKHR oldSwapchain; +} VkSwapchainCreateInfoKHR; -typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR; +typedef struct VkPresentInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + uint32_t swapchainCount; + const VkSwapchainKHR* pSwapchains; + const uint32_t* pImageIndices; + VkResult* pResults; +} VkPresentInfoKHR; -typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR; +typedef struct VkImageSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; +} VkImageSwapchainCreateInfoKHR; -typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR; +typedef struct VkBindImageMemorySwapchainInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint32_t imageIndex; +} VkBindImageMemorySwapchainInfoKHR; -typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR; +typedef struct VkAcquireNextImageInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint64_t timeout; + VkSemaphore semaphore; + VkFence fence; + uint32_t deviceMask; +} VkAcquireNextImageInfoKHR; -typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR; +typedef struct VkDeviceGroupPresentCapabilitiesKHR { + VkStructureType sType; + void* pNext; + uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE]; + VkDeviceGroupPresentModeFlagsKHR modes; +} VkDeviceGroupPresentCapabilitiesKHR; -typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR; +typedef struct VkDeviceGroupPresentInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint32_t* pDeviceMasks; + VkDeviceGroupPresentModeFlagBitsKHR mode; +} VkDeviceGroupPresentInfoKHR; -typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR; +typedef struct VkDeviceGroupSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceGroupPresentModeFlagsKHR modes; +} VkDeviceGroupSwapchainCreateInfoKHR; -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain); +typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex); +typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, - VkExternalBufferProperties* pExternalBufferProperties); -#endif - - -#define VK_KHR_external_memory 1 -#define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory" -#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL -typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR; - -typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR; - -typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR; - - +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( + VkDevice device, + const VkSwapchainCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchain); -#define VK_KHR_external_memory_fd 1 -#define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd" -typedef struct VkImportMemoryFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagBits handleType; - int fd; -} VkImportMemoryFdInfoKHR; +VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkAllocationCallbacks* pAllocator); -typedef struct VkMemoryFdPropertiesKHR { - VkStructureType sType; - void* pNext; - uint32_t memoryTypeBits; -} VkMemoryFdPropertiesKHR; +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pSwapchainImageCount, + VkImage* pSwapchainImages); -typedef struct VkMemoryGetFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkDeviceMemory memory; - VkExternalMemoryHandleTypeFlagBits handleType; -} VkMemoryGetFdInfoKHR; +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t timeout, + VkSemaphore semaphore, + VkFence fence, + uint32_t* pImageIndex); -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd); -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); +VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( + VkQueue queue, + const VkPresentInfoKHR* pPresentInfo); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR( VkDevice device, - const VkMemoryGetFdInfoKHR* pGetFdInfo, - int* pFd); + VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR( VkDevice device, - VkExternalMemoryHandleTypeFlagBits handleType, - int fd, - VkMemoryFdPropertiesKHR* pMemoryFdProperties); -#endif + VkSurfaceKHR surface, + VkDeviceGroupPresentModeFlagsKHR* pModes); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pRectCount, + VkRect2D* pRects); -#define VK_KHR_external_semaphore_capabilities 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities" -typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR; +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR( + VkDevice device, + const VkAcquireNextImageInfoKHR* pAcquireInfo, + uint32_t* pImageIndex); +#endif -typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR; -typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR; +// VK_KHR_display is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_display 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) +#define VK_KHR_DISPLAY_SPEC_VERSION 23 +#define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display" +typedef VkFlags VkDisplayModeCreateFlagsKHR; -typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR; +typedef enum VkDisplayPlaneAlphaFlagBitsKHR { + VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008, + VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDisplayPlaneAlphaFlagBitsKHR; +typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; +typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; +typedef struct VkDisplayModeParametersKHR { + VkExtent2D visibleRegion; + uint32_t refreshRate; +} VkDisplayModeParametersKHR; -typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR; +typedef struct VkDisplayModeCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDisplayModeCreateFlagsKHR flags; + VkDisplayModeParametersKHR parameters; +} VkDisplayModeCreateInfoKHR; -typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR; +typedef struct VkDisplayModePropertiesKHR { + VkDisplayModeKHR displayMode; + VkDisplayModeParametersKHR parameters; +} VkDisplayModePropertiesKHR; -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, - VkExternalSemaphoreProperties* pExternalSemaphoreProperties); -#endif +typedef struct VkDisplayPlaneCapabilitiesKHR { + VkDisplayPlaneAlphaFlagsKHR supportedAlpha; + VkOffset2D minSrcPosition; + VkOffset2D maxSrcPosition; + VkExtent2D minSrcExtent; + VkExtent2D maxSrcExtent; + VkOffset2D minDstPosition; + VkOffset2D maxDstPosition; + VkExtent2D minDstExtent; + VkExtent2D maxDstExtent; +} VkDisplayPlaneCapabilitiesKHR; +typedef struct VkDisplayPlanePropertiesKHR { + VkDisplayKHR currentDisplay; + uint32_t currentStackIndex; +} VkDisplayPlanePropertiesKHR; -#define VK_KHR_external_semaphore 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore" -typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR; +typedef struct VkDisplayPropertiesKHR { + VkDisplayKHR display; + const char* displayName; + VkExtent2D physicalDimensions; + VkExtent2D physicalResolution; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkBool32 planeReorderPossible; + VkBool32 persistentContent; +} VkDisplayPropertiesKHR; -typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR; +typedef struct VkDisplaySurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDisplaySurfaceCreateFlagsKHR flags; + VkDisplayModeKHR displayMode; + uint32_t planeIndex; + uint32_t planeStackIndex; + VkSurfaceTransformFlagBitsKHR transform; + float globalAlpha; + VkDisplayPlaneAlphaFlagBitsKHR alphaMode; + VkExtent2D imageExtent; +} VkDisplaySurfaceCreateInfoKHR; -typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR; +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPropertiesKHR* pProperties); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPlanePropertiesKHR* pProperties); -#define VK_KHR_external_semaphore_fd 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd" -typedef struct VkImportSemaphoreFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkSemaphore semaphore; - VkSemaphoreImportFlags flags; - VkExternalSemaphoreHandleTypeFlagBits handleType; - int fd; -} VkImportSemaphoreFdInfoKHR; +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR( + VkPhysicalDevice physicalDevice, + uint32_t planeIndex, + uint32_t* pDisplayCount, + VkDisplayKHR* pDisplays); -typedef struct VkSemaphoreGetFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkSemaphore semaphore; - VkExternalSemaphoreHandleTypeFlagBits handleType; -} VkSemaphoreGetFdInfoKHR; +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + uint32_t* pPropertyCount, + VkDisplayModePropertiesKHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + const VkDisplayModeCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDisplayModeKHR* pMode); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR( - VkDevice device, - const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkDisplayModeKHR mode, + uint32_t planeIndex, + VkDisplayPlaneCapabilitiesKHR* pCapabilities); -VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( - VkDevice device, - const VkSemaphoreGetFdInfoKHR* pGetFdInfo, - int* pFd); +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( + VkInstance instance, + const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); #endif -#define VK_KHR_push_descriptor 1 -#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2 -#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor" -typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR { +// VK_KHR_display_swapchain is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_display_swapchain 1 +#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 10 +#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" +typedef struct VkDisplayPresentInfoKHR { VkStructureType sType; - void* pNext; - uint32_t maxPushDescriptors; -} VkPhysicalDevicePushDescriptorPropertiesKHR; + const void* pNext; + VkRect2D srcRect; + VkRect2D dstRect; + VkBool32 persistent; +} VkDisplayPresentInfoKHR; -typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); -typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( - VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipelineLayout layout, - uint32_t set, - uint32_t descriptorWriteCount, - const VkWriteDescriptorSet* pDescriptorWrites); - -VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( - VkCommandBuffer commandBuffer, - VkDescriptorUpdateTemplate descriptorUpdateTemplate, - VkPipelineLayout layout, - uint32_t set, - const void* pData); +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchains); #endif -#define VK_KHR_shader_float16_int8 1 -#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1 -#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8" -typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceShaderFloat16Int8FeaturesKHR; - -typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceFloat16Int8FeaturesKHR; +// VK_KHR_sampler_mirror_clamp_to_edge is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_sampler_mirror_clamp_to_edge 1 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 3 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" +// VK_KHR_video_queue is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_queue 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionParametersKHR) +#define VK_KHR_VIDEO_QUEUE_SPEC_VERSION 8 +#define VK_KHR_VIDEO_QUEUE_EXTENSION_NAME "VK_KHR_video_queue" -#define VK_KHR_16bit_storage 1 -#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 -#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" -typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR; +typedef enum VkQueryResultStatusKHR { + VK_QUERY_RESULT_STATUS_ERROR_KHR = -1, + VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0, + VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1, + VK_QUERY_RESULT_STATUS_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_KHR = -1000299000, + VK_QUERY_RESULT_STATUS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkQueryResultStatusKHR; +typedef enum VkVideoCodecOperationFlagBitsKHR { + VK_VIDEO_CODEC_OPERATION_NONE_KHR = 0, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT = 0x00010000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT = 0x00020000, +#endif + VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR = 0x00000001, + VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR = 0x00000002, + VK_VIDEO_CODEC_OPERATION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodecOperationFlagBitsKHR; +typedef VkFlags VkVideoCodecOperationFlagsKHR; + +typedef enum VkVideoChromaSubsamplingFlagBitsKHR { + VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR = 0, + VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0x00000001, + VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0x00000002, + VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0x00000004, + VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR = 0x00000008, + VK_VIDEO_CHROMA_SUBSAMPLING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoChromaSubsamplingFlagBitsKHR; +typedef VkFlags VkVideoChromaSubsamplingFlagsKHR; + +typedef enum VkVideoComponentBitDepthFlagBitsKHR { + VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR = 0, + VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR = 0x00000001, + VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR = 0x00000004, + VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR = 0x00000010, + VK_VIDEO_COMPONENT_BIT_DEPTH_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoComponentBitDepthFlagBitsKHR; +typedef VkFlags VkVideoComponentBitDepthFlagsKHR; + +typedef enum VkVideoCapabilityFlagBitsKHR { + VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR = 0x00000001, + VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR = 0x00000002, + VK_VIDEO_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCapabilityFlagBitsKHR; +typedef VkFlags VkVideoCapabilityFlagsKHR; + +typedef enum VkVideoSessionCreateFlagBitsKHR { + VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0x00000001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_SESSION_CREATE_ALLOW_ENCODE_PARAMETER_OPTIMIZATIONS_BIT_KHR = 0x00000002, +#endif + VK_VIDEO_SESSION_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoSessionCreateFlagBitsKHR; +typedef VkFlags VkVideoSessionCreateFlagsKHR; +typedef VkFlags VkVideoSessionParametersCreateFlagsKHR; +typedef VkFlags VkVideoBeginCodingFlagsKHR; +typedef VkFlags VkVideoEndCodingFlagsKHR; + +typedef enum VkVideoCodingControlFlagBitsKHR { + VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0x00000001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR = 0x00000002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR = 0x00000004, +#endif + VK_VIDEO_CODING_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodingControlFlagBitsKHR; +typedef VkFlags VkVideoCodingControlFlagsKHR; +typedef struct VkQueueFamilyQueryResultStatusPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 queryResultStatusSupport; +} VkQueueFamilyQueryResultStatusPropertiesKHR; +typedef struct VkQueueFamilyVideoPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoCodecOperationFlagsKHR videoCodecOperations; +} VkQueueFamilyVideoPropertiesKHR; -#define VK_KHR_incremental_present 1 -#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 2 -#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" -typedef struct VkRectLayerKHR { - VkOffset2D offset; - VkExtent2D extent; - uint32_t layer; -} VkRectLayerKHR; +typedef struct VkVideoProfileInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoCodecOperationFlagBitsKHR videoCodecOperation; + VkVideoChromaSubsamplingFlagsKHR chromaSubsampling; + VkVideoComponentBitDepthFlagsKHR lumaBitDepth; + VkVideoComponentBitDepthFlagsKHR chromaBitDepth; +} VkVideoProfileInfoKHR; -typedef struct VkPresentRegionKHR { - uint32_t rectangleCount; - const VkRectLayerKHR* pRectangles; -} VkPresentRegionKHR; +typedef struct VkVideoProfileListInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t profileCount; + const VkVideoProfileInfoKHR* pProfiles; +} VkVideoProfileListInfoKHR; -typedef struct VkPresentRegionsKHR { +typedef struct VkVideoCapabilitiesKHR { VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const VkPresentRegionKHR* pRegions; -} VkPresentRegionsKHR; + void* pNext; + VkVideoCapabilityFlagsKHR flags; + VkDeviceSize minBitstreamBufferOffsetAlignment; + VkDeviceSize minBitstreamBufferSizeAlignment; + VkExtent2D pictureAccessGranularity; + VkExtent2D minCodedExtent; + VkExtent2D maxCodedExtent; + uint32_t maxDpbSlots; + uint32_t maxActiveReferencePictures; + VkExtensionProperties stdHeaderVersion; +} VkVideoCapabilitiesKHR; + +typedef struct VkPhysicalDeviceVideoFormatInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageUsageFlags imageUsage; +} VkPhysicalDeviceVideoFormatInfoKHR; +typedef struct VkVideoFormatPropertiesKHR { + VkStructureType sType; + void* pNext; + VkFormat format; + VkComponentMapping componentMapping; + VkImageCreateFlags imageCreateFlags; + VkImageType imageType; + VkImageTiling imageTiling; + VkImageUsageFlags imageUsageFlags; +} VkVideoFormatPropertiesKHR; + +typedef struct VkVideoPictureResourceInfoKHR { + VkStructureType sType; + const void* pNext; + VkOffset2D codedOffset; + VkExtent2D codedExtent; + uint32_t baseArrayLayer; + VkImageView imageViewBinding; +} VkVideoPictureResourceInfoKHR; +typedef struct VkVideoReferenceSlotInfoKHR { + VkStructureType sType; + const void* pNext; + int32_t slotIndex; + const VkVideoPictureResourceInfoKHR* pPictureResource; +} VkVideoReferenceSlotInfoKHR; -#define VK_KHR_descriptor_update_template 1 -typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR; +typedef struct VkVideoSessionMemoryRequirementsKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryBindIndex; + VkMemoryRequirements memoryRequirements; +} VkVideoSessionMemoryRequirementsKHR; -#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1 -#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template" -typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR; +typedef struct VkBindVideoSessionMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t memoryBindIndex; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkDeviceSize memorySize; +} VkBindVideoSessionMemoryInfoKHR; -typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR; +typedef struct VkVideoSessionCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + VkVideoSessionCreateFlagsKHR flags; + const VkVideoProfileInfoKHR* pVideoProfile; + VkFormat pictureFormat; + VkExtent2D maxCodedExtent; + VkFormat referencePictureFormat; + uint32_t maxDpbSlots; + uint32_t maxActiveReferencePictures; + const VkExtensionProperties* pStdHeaderVersion; +} VkVideoSessionCreateInfoKHR; + +typedef struct VkVideoSessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoSessionParametersCreateFlagsKHR flags; + VkVideoSessionParametersKHR videoSessionParametersTemplate; + VkVideoSessionKHR videoSession; +} VkVideoSessionParametersCreateInfoKHR; -typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR; +typedef struct VkVideoSessionParametersUpdateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t updateSequenceCount; +} VkVideoSessionParametersUpdateInfoKHR; -typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR; +typedef struct VkVideoBeginCodingInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoBeginCodingFlagsKHR flags; + VkVideoSessionKHR videoSession; + VkVideoSessionParametersKHR videoSessionParameters; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotInfoKHR* pReferenceSlots; +} VkVideoBeginCodingInfoKHR; + +typedef struct VkVideoEndCodingInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEndCodingFlagsKHR flags; +} VkVideoEndCodingInfoKHR; -typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); -typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); +typedef struct VkVideoCodingControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoCodingControlFlagsKHR flags; +} VkVideoCodingControlInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)(VkPhysicalDevice physicalDevice, const VkVideoProfileInfoKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionKHR)(VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession); +typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionKHR)(VkDevice device, VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetVideoSessionMemoryRequirementsKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pMemoryRequirementsCount, VkVideoSessionMemoryRequirementsKHR* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindVideoSessionMemoryKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t bindSessionMemoryInfoCount, const VkBindVideoSessionMemoryInfoKHR* pBindSessionMemoryInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionParametersKHR)(VkDevice device, const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionParametersKHR* pVideoSessionParameters); +typedef VkResult (VKAPI_PTR *PFN_vkUpdateVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); +typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBeginVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoBeginCodingInfoKHR* pBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoEndCodingInfoKHR* pEndCodingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdControlVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoCodingControlInfoKHR* pCodingControlInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + const VkVideoProfileInfoKHR* pVideoProfile, + VkVideoCapabilitiesKHR* pCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoFormatPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, + uint32_t* pVideoFormatPropertyCount, + VkVideoFormatPropertiesKHR* pVideoFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionKHR( VkDevice device, - const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, + const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, - VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); + VkVideoSessionKHR* pVideoSession); -VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR( +VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionKHR( VkDevice device, - VkDescriptorUpdateTemplate descriptorUpdateTemplate, + VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkGetVideoSessionMemoryRequirementsKHR( VkDevice device, - VkDescriptorSet descriptorSet, - VkDescriptorUpdateTemplate descriptorUpdateTemplate, - const void* pData); -#endif + VkVideoSessionKHR videoSession, + uint32_t* pMemoryRequirementsCount, + VkVideoSessionMemoryRequirementsKHR* pMemoryRequirements); +VKAPI_ATTR VkResult VKAPI_CALL vkBindVideoSessionMemoryKHR( + VkDevice device, + VkVideoSessionKHR videoSession, + uint32_t bindSessionMemoryInfoCount, + const VkBindVideoSessionMemoryInfoKHR* pBindSessionMemoryInfos); -#define VK_KHR_imageless_framebuffer 1 -#define VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION 1 -#define VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME "VK_KHR_imageless_framebuffer" -typedef VkPhysicalDeviceImagelessFramebufferFeatures VkPhysicalDeviceImagelessFramebufferFeaturesKHR; - -typedef VkFramebufferAttachmentsCreateInfo VkFramebufferAttachmentsCreateInfoKHR; - -typedef VkFramebufferAttachmentImageInfo VkFramebufferAttachmentImageInfoKHR; - -typedef VkRenderPassAttachmentBeginInfo VkRenderPassAttachmentBeginInfoKHR; - +VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionParametersKHR( + VkDevice device, + const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkVideoSessionParametersKHR* pVideoSessionParameters); +VKAPI_ATTR VkResult VKAPI_CALL vkUpdateVideoSessionParametersKHR( + VkDevice device, + VkVideoSessionParametersKHR videoSessionParameters, + const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); -#define VK_KHR_create_renderpass2 1 -#define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1 -#define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2" -typedef VkRenderPassCreateInfo2 VkRenderPassCreateInfo2KHR; +VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionParametersKHR( + VkDevice device, + VkVideoSessionParametersKHR videoSessionParameters, + const VkAllocationCallbacks* pAllocator); -typedef VkAttachmentDescription2 VkAttachmentDescription2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdBeginVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoBeginCodingInfoKHR* pBeginInfo); -typedef VkAttachmentReference2 VkAttachmentReference2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdEndVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoEndCodingInfoKHR* pEndCodingInfo); -typedef VkSubpassDescription2 VkSubpassDescription2KHR; +VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoCodingControlInfoKHR* pCodingControlInfo); +#endif -typedef VkSubpassDependency2 VkSubpassDependency2KHR; -typedef VkSubpassBeginInfo VkSubpassBeginInfoKHR; +// VK_KHR_video_decode_queue is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_queue 1 +#define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 7 +#define VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME "VK_KHR_video_decode_queue" + +typedef enum VkVideoDecodeCapabilityFlagBitsKHR { + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR = 0x00000001, + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR = 0x00000002, + VK_VIDEO_DECODE_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoDecodeCapabilityFlagBitsKHR; +typedef VkFlags VkVideoDecodeCapabilityFlagsKHR; + +typedef enum VkVideoDecodeUsageFlagBitsKHR { + VK_VIDEO_DECODE_USAGE_DEFAULT_KHR = 0, + VK_VIDEO_DECODE_USAGE_TRANSCODING_BIT_KHR = 0x00000001, + VK_VIDEO_DECODE_USAGE_OFFLINE_BIT_KHR = 0x00000002, + VK_VIDEO_DECODE_USAGE_STREAMING_BIT_KHR = 0x00000004, + VK_VIDEO_DECODE_USAGE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoDecodeUsageFlagBitsKHR; +typedef VkFlags VkVideoDecodeUsageFlagsKHR; +typedef VkFlags VkVideoDecodeFlagsKHR; +typedef struct VkVideoDecodeCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoDecodeCapabilityFlagsKHR flags; +} VkVideoDecodeCapabilitiesKHR; -typedef VkSubpassEndInfo VkSubpassEndInfoKHR; +typedef struct VkVideoDecodeUsageInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoDecodeUsageFlagsKHR videoUsageHints; +} VkVideoDecodeUsageInfoKHR; -typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2KHR)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); -typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); -typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); -typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); +typedef struct VkVideoDecodeInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoDecodeFlagsKHR flags; + VkBuffer srcBuffer; + VkDeviceSize srcBufferOffset; + VkDeviceSize srcBufferRange; + VkVideoPictureResourceInfoKHR dstPictureResource; + const VkVideoReferenceSlotInfoKHR* pSetupReferenceSlot; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotInfoKHR* pReferenceSlots; +} VkVideoDecodeInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pDecodeInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR( - VkDevice device, - const VkRenderPassCreateInfo2* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkRenderPass* pRenderPass); - -VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR( - VkCommandBuffer commandBuffer, - const VkRenderPassBeginInfo* pRenderPassBegin, - const VkSubpassBeginInfo* pSubpassBeginInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR( - VkCommandBuffer commandBuffer, - const VkSubpassBeginInfo* pSubpassBeginInfo, - const VkSubpassEndInfo* pSubpassEndInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR( +VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR( VkCommandBuffer commandBuffer, - const VkSubpassEndInfo* pSubpassEndInfo); + const VkVideoDecodeInfoKHR* pDecodeInfo); #endif -#define VK_KHR_shared_presentable_image 1 -#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 -#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" -typedef struct VkSharedPresentSurfaceCapabilitiesKHR { - VkStructureType sType; - void* pNext; - VkImageUsageFlags sharedPresentSupportedUsageFlags; -} VkSharedPresentSurfaceCapabilitiesKHR; +// VK_KHR_video_decode_h264 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_h264 1 +#include "vk_video/vulkan_video_codec_h264std.h" +#include "vk_video/vulkan_video_codec_h264std_decode.h" +#define VK_KHR_VIDEO_DECODE_H264_SPEC_VERSION 8 +#define VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME "VK_KHR_video_decode_h264" + +typedef enum VkVideoDecodeH264PictureLayoutFlagBitsKHR { + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR = 0, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR = 0x00000001, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR = 0x00000002, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoDecodeH264PictureLayoutFlagBitsKHR; +typedef VkFlags VkVideoDecodeH264PictureLayoutFlagsKHR; +typedef struct VkVideoDecodeH264ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoH264ProfileIdc stdProfileIdc; + VkVideoDecodeH264PictureLayoutFlagBitsKHR pictureLayout; +} VkVideoDecodeH264ProfileInfoKHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain); +typedef struct VkVideoDecodeH264CapabilitiesKHR { + VkStructureType sType; + void* pNext; + StdVideoH264LevelIdc maxLevelIdc; + VkOffset2D fieldOffsetGranularity; +} VkVideoDecodeH264CapabilitiesKHR; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( - VkDevice device, - VkSwapchainKHR swapchain); -#endif +typedef struct VkVideoDecodeH264SessionParametersAddInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t stdSPSCount; + const StdVideoH264SequenceParameterSet* pStdSPSs; + uint32_t stdPPSCount; + const StdVideoH264PictureParameterSet* pStdPPSs; +} VkVideoDecodeH264SessionParametersAddInfoKHR; +typedef struct VkVideoDecodeH264SessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxStdSPSCount; + uint32_t maxStdPPSCount; + const VkVideoDecodeH264SessionParametersAddInfoKHR* pParametersAddInfo; +} VkVideoDecodeH264SessionParametersCreateInfoKHR; -#define VK_KHR_external_fence_capabilities 1 -#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities" -typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR; +typedef struct VkVideoDecodeH264PictureInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264PictureInfo* pStdPictureInfo; + uint32_t sliceCount; + const uint32_t* pSliceOffsets; +} VkVideoDecodeH264PictureInfoKHR; -typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR; +typedef struct VkVideoDecodeH264DpbSlotInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeH264DpbSlotInfoKHR; -typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR; -typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR; -typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR; +// VK_KHR_dynamic_rendering is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_dynamic_rendering 1 +#define VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION 1 +#define VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME "VK_KHR_dynamic_rendering" +typedef VkRenderingFlags VkRenderingFlagsKHR; -typedef VkExternalFenceProperties VkExternalFencePropertiesKHR; +typedef VkRenderingFlagBits VkRenderingFlagBitsKHR; -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); +typedef VkRenderingInfo VkRenderingInfoKHR; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, - VkExternalFenceProperties* pExternalFenceProperties); -#endif +typedef VkRenderingAttachmentInfo VkRenderingAttachmentInfoKHR; +typedef VkPipelineRenderingCreateInfo VkPipelineRenderingCreateInfoKHR; -#define VK_KHR_external_fence 1 -#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence" -typedef VkFenceImportFlags VkFenceImportFlagsKHR; +typedef VkPhysicalDeviceDynamicRenderingFeatures VkPhysicalDeviceDynamicRenderingFeaturesKHR; -typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR; +typedef VkCommandBufferInheritanceRenderingInfo VkCommandBufferInheritanceRenderingInfoKHR; -typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR; +typedef struct VkRenderingFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkExtent2D shadingRateAttachmentTexelSize; +} VkRenderingFragmentShadingRateAttachmentInfoKHR; +typedef struct VkRenderingFragmentDensityMapAttachmentInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; +} VkRenderingFragmentDensityMapAttachmentInfoEXT; +typedef struct VkAttachmentSampleCountInfoAMD { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const VkSampleCountFlagBits* pColorAttachmentSamples; + VkSampleCountFlagBits depthStencilAttachmentSamples; +} VkAttachmentSampleCountInfoAMD; -#define VK_KHR_external_fence_fd 1 -#define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1 -#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd" -typedef struct VkImportFenceFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkFence fence; - VkFenceImportFlags flags; - VkExternalFenceHandleTypeFlagBits handleType; - int fd; -} VkImportFenceFdInfoKHR; +typedef VkAttachmentSampleCountInfoAMD VkAttachmentSampleCountInfoNV; -typedef struct VkFenceGetFdInfoKHR { - VkStructureType sType; - const void* pNext; - VkFence fence; - VkExternalFenceHandleTypeFlagBits handleType; -} VkFenceGetFdInfoKHR; +typedef struct VkMultiviewPerViewAttributesInfoNVX { + VkStructureType sType; + const void* pNext; + VkBool32 perViewAttributes; + VkBool32 perViewAttributesPositionXOnly; +} VkMultiviewPerViewAttributesInfoNVX; -typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderingKHR)(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderingKHR)(VkCommandBuffer commandBuffer); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR( - VkDevice device, - const VkImportFenceFdInfoKHR* pImportFenceFdInfo); +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderingKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInfo* pRenderingInfo); -VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( - VkDevice device, - const VkFenceGetFdInfoKHR* pGetFdInfo, - int* pFd); +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( + VkCommandBuffer commandBuffer); #endif -#define VK_KHR_performance_query 1 -#define VK_KHR_PERFORMANCE_QUERY_SPEC_VERSION 1 -#define VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME "VK_KHR_performance_query" +// VK_KHR_multiview is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_multiview 1 +#define VK_KHR_MULTIVIEW_SPEC_VERSION 1 +#define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" +typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR; -typedef enum VkPerformanceCounterUnitKHR { - VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR = 0, - VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR = 1, - VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR = 2, - VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR = 3, - VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR = 4, - VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR = 5, - VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR = 6, - VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR = 7, - VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR = 8, - VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR = 9, - VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR = 10, - VK_PERFORMANCE_COUNTER_UNIT_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPerformanceCounterUnitKHR; +typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR; -typedef enum VkPerformanceCounterScopeKHR { - VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0, - VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1, - VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2, - VK_QUERY_SCOPE_COMMAND_BUFFER_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR, - VK_QUERY_SCOPE_RENDER_PASS_KHR = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR, - VK_QUERY_SCOPE_COMMAND_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR, - VK_PERFORMANCE_COUNTER_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPerformanceCounterScopeKHR; +typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR; -typedef enum VkPerformanceCounterStorageKHR { - VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR = 0, - VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR = 1, - VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR = 2, - VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR = 3, - VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR = 4, - VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR = 5, - VK_PERFORMANCE_COUNTER_STORAGE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPerformanceCounterStorageKHR; -typedef enum VkPerformanceCounterDescriptionFlagBitsKHR { - VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0x00000001, - VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0x00000002, - VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR, - VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR, - VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPerformanceCounterDescriptionFlagBitsKHR; -typedef VkFlags VkPerformanceCounterDescriptionFlagsKHR; -typedef enum VkAcquireProfilingLockFlagBitsKHR { - VK_ACQUIRE_PROFILING_LOCK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkAcquireProfilingLockFlagBitsKHR; -typedef VkFlags VkAcquireProfilingLockFlagsKHR; -typedef struct VkPhysicalDevicePerformanceQueryFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 performanceCounterQueryPools; - VkBool32 performanceCounterMultipleQueryPools; -} VkPhysicalDevicePerformanceQueryFeaturesKHR; +// VK_KHR_get_physical_device_properties2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_get_physical_device_properties2 1 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 2 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" +typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR; -typedef struct VkPhysicalDevicePerformanceQueryPropertiesKHR { - VkStructureType sType; - void* pNext; - VkBool32 allowCommandBufferQueryCopies; -} VkPhysicalDevicePerformanceQueryPropertiesKHR; +typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR; -typedef struct VkPerformanceCounterKHR { - VkStructureType sType; - void* pNext; - VkPerformanceCounterUnitKHR unit; - VkPerformanceCounterScopeKHR scope; - VkPerformanceCounterStorageKHR storage; - uint8_t uuid[VK_UUID_SIZE]; -} VkPerformanceCounterKHR; +typedef VkFormatProperties2 VkFormatProperties2KHR; -typedef struct VkPerformanceCounterDescriptionKHR { - VkStructureType sType; - void* pNext; - VkPerformanceCounterDescriptionFlagsKHR flags; - char name[VK_MAX_DESCRIPTION_SIZE]; - char category[VK_MAX_DESCRIPTION_SIZE]; - char description[VK_MAX_DESCRIPTION_SIZE]; -} VkPerformanceCounterDescriptionKHR; +typedef VkImageFormatProperties2 VkImageFormatProperties2KHR; -typedef struct VkQueryPoolPerformanceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t queueFamilyIndex; - uint32_t counterIndexCount; - const uint32_t* pCounterIndices; -} VkQueryPoolPerformanceCreateInfoKHR; +typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR; -typedef union VkPerformanceCounterResultKHR { - int32_t int32; - int64_t int64; - uint32_t uint32; - uint64_t uint64; - float float32; - double float64; -} VkPerformanceCounterResultKHR; +typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR; -typedef struct VkAcquireProfilingLockInfoKHR { - VkStructureType sType; - const void* pNext; - VkAcquireProfilingLockFlagsKHR flags; - uint64_t timeout; -} VkAcquireProfilingLockInfoKHR; +typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR; -typedef struct VkPerformanceQuerySubmitInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t counterPassIndex; -} VkPerformanceQuerySubmitInfoKHR; +typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR; -typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters, VkPerformanceCounterDescriptionKHR* pCounterDescriptions); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)(VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses); -typedef VkResult (VKAPI_PTR *PFN_vkAcquireProfilingLockKHR)(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo); -typedef void (VKAPI_PTR *PFN_vkReleaseProfilingLockKHR)(VkDevice device); +typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR( VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - uint32_t* pCounterCount, - VkPerformanceCounterKHR* pCounters, - VkPerformanceCounterDescriptionKHR* pCounterDescriptions); + VkPhysicalDeviceFeatures2* pFeatures); -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR( VkPhysicalDevice physicalDevice, - const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, - uint32_t* pNumPasses); + VkPhysicalDeviceProperties2* pProperties); -VKAPI_ATTR VkResult VKAPI_CALL vkAcquireProfilingLockKHR( - VkDevice device, - const VkAcquireProfilingLockInfoKHR* pInfo); +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); -VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR( - VkDevice device); -#endif +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, + VkImageFormatProperties2* pImageFormatProperties); +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties2* pQueueFamilyProperties); -#define VK_KHR_maintenance2 1 -#define VK_KHR_MAINTENANCE2_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2" -typedef VkPointClippingBehavior VkPointClippingBehaviorKHR; +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties2* pMemoryProperties); -typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR; +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties2* pProperties); +#endif -typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR; -typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR; +// VK_KHR_device_group is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_device_group 1 +#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 4 +#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group" +typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR; -typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR; +typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR; -typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR; +typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR; -typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR; +typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR; +typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR; +typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR; -#define VK_KHR_get_surface_capabilities2 1 -#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1 -#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2" -typedef struct VkPhysicalDeviceSurfaceInfo2KHR { - VkStructureType sType; - const void* pNext; - VkSurfaceKHR surface; -} VkPhysicalDeviceSurfaceInfo2KHR; +typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR; -typedef struct VkSurfaceCapabilities2KHR { - VkStructureType sType; - void* pNext; - VkSurfaceCapabilitiesKHR surfaceCapabilities; -} VkSurfaceCapabilities2KHR; +typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR; -typedef struct VkSurfaceFormat2KHR { - VkStructureType sType; - void* pNext; - VkSurfaceFormatKHR surfaceFormat; -} VkSurfaceFormat2KHR; +typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); +typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR; + +typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, - VkSurfaceCapabilities2KHR* pSurfaceCapabilities); +VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR( + VkDevice device, + uint32_t heapIndex, + uint32_t localDeviceIndex, + uint32_t remoteDeviceIndex, + VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, - uint32_t* pSurfaceFormatCount, - VkSurfaceFormat2KHR* pSurfaceFormats); -#endif +VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR( + VkCommandBuffer commandBuffer, + uint32_t deviceMask); +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( + VkCommandBuffer commandBuffer, + uint32_t baseGroupX, + uint32_t baseGroupY, + uint32_t baseGroupZ, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); +#endif -#define VK_KHR_variable_pointers 1 -#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1 -#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers" -typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeaturesKHR; -typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointersFeaturesKHR; +// VK_KHR_shader_draw_parameters is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_draw_parameters 1 +#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1 +#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters" +// VK_KHR_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance1 1 +#define VK_KHR_MAINTENANCE_1_SPEC_VERSION 2 +#define VK_KHR_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_maintenance1" +#define VK_KHR_MAINTENANCE1_SPEC_VERSION VK_KHR_MAINTENANCE_1_SPEC_VERSION +#define VK_KHR_MAINTENANCE1_EXTENSION_NAME VK_KHR_MAINTENANCE_1_EXTENSION_NAME +typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR; -#define VK_KHR_get_display_properties2 1 -#define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1 -#define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2" -typedef struct VkDisplayProperties2KHR { - VkStructureType sType; - void* pNext; - VkDisplayPropertiesKHR displayProperties; -} VkDisplayProperties2KHR; +typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); -typedef struct VkDisplayPlaneProperties2KHR { - VkStructureType sType; - void* pNext; - VkDisplayPlanePropertiesKHR displayPlaneProperties; -} VkDisplayPlaneProperties2KHR; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolTrimFlags flags); +#endif -typedef struct VkDisplayModeProperties2KHR { - VkStructureType sType; - void* pNext; - VkDisplayModePropertiesKHR displayModeProperties; -} VkDisplayModeProperties2KHR; -typedef struct VkDisplayPlaneInfo2KHR { - VkStructureType sType; - const void* pNext; - VkDisplayModeKHR mode; - uint32_t planeIndex; -} VkDisplayPlaneInfo2KHR; +// VK_KHR_device_group_creation is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_device_group_creation 1 +#define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1 +#define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation" +#define VK_MAX_DEVICE_GROUP_SIZE_KHR VK_MAX_DEVICE_GROUP_SIZE +typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR; -typedef struct VkDisplayPlaneCapabilities2KHR { - VkStructureType sType; - void* pNext; - VkDisplayPlaneCapabilitiesKHR capabilities; -} VkDisplayPlaneCapabilities2KHR; +typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkDisplayProperties2KHR* pProperties); +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR( + VkInstance instance, + uint32_t* pPhysicalDeviceGroupCount, + VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); +#endif -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkDisplayPlaneProperties2KHR* pProperties); -VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR( - VkPhysicalDevice physicalDevice, - VkDisplayKHR display, - uint32_t* pPropertyCount, - VkDisplayModeProperties2KHR* pProperties); +// VK_KHR_external_memory_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_memory_capabilities 1 +#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities" +#define VK_LUID_SIZE_KHR VK_LUID_SIZE +typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR; -VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR( - VkPhysicalDevice physicalDevice, - const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, - VkDisplayPlaneCapabilities2KHR* pCapabilities); -#endif +typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR; +typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR; -#define VK_KHR_dedicated_allocation 1 -#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3 -#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation" -typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR; +typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR; -typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; +typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR; +typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR; +typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR; -#define VK_KHR_storage_buffer_storage_class 1 -#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1 -#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class" +typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR; +typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR; -#define VK_KHR_relaxed_block_layout 1 -#define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1 -#define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout" +typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR; +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); -#define VK_KHR_get_memory_requirements2 1 -#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1 -#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2" -typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, + VkExternalBufferProperties* pExternalBufferProperties); +#endif -typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR; -typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR; +// VK_KHR_external_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_memory 1 +#define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory" +#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL +typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR; -typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; +typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR; -typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR; +typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR; -typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR( - VkDevice device, - const VkImageMemoryRequirementsInfo2* pInfo, - VkMemoryRequirements2* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR( - VkDevice device, - const VkBufferMemoryRequirementsInfo2* pInfo, - VkMemoryRequirements2* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( - VkDevice device, - const VkImageSparseMemoryRequirementsInfo2* pInfo, - uint32_t* pSparseMemoryRequirementCount, - VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); -#endif -#define VK_KHR_image_format_list 1 -#define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1 -#define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list" -typedef VkImageFormatListCreateInfo VkImageFormatListCreateInfoKHR; +// VK_KHR_external_memory_fd is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_memory_fd 1 +#define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd" +typedef struct VkImportMemoryFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + int fd; +} VkImportMemoryFdInfoKHR; +typedef struct VkMemoryFdPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryFdPropertiesKHR; +typedef struct VkMemoryGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetFdInfoKHR; -#define VK_KHR_sampler_ycbcr_conversion 1 -typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR; +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); -#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 14 -#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion" -typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR( + VkDevice device, + const VkMemoryGetFdInfoKHR* pGetFdInfo, + int* pFd); -typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR; +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + int fd, + VkMemoryFdPropertiesKHR* pMemoryFdProperties); +#endif -typedef VkChromaLocation VkChromaLocationKHR; -typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR; +// VK_KHR_external_semaphore_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_semaphore_capabilities 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities" +typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR; -typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR; +typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR; -typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR; +typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR; -typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR; +typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR; -typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR; +typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR; -typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR; +typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR; -typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); -typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR( - VkDevice device, - const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSamplerYcbcrConversion* pYcbcrConversion); - -VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( - VkDevice device, - VkSamplerYcbcrConversion ycbcrConversion, - const VkAllocationCallbacks* pAllocator); +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, + VkExternalSemaphoreProperties* pExternalSemaphoreProperties); #endif -#define VK_KHR_bind_memory2 1 -#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1 -#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2" -typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR; - -typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR; +// VK_KHR_external_semaphore is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_semaphore 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore" +typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR; -typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); -typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); +typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR( - VkDevice device, - uint32_t bindInfoCount, - const VkBindBufferMemoryInfo* pBindInfos); +typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR; -VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( - VkDevice device, - uint32_t bindInfoCount, - const VkBindImageMemoryInfo* pBindInfos); -#endif -#define VK_KHR_maintenance3 1 -#define VK_KHR_MAINTENANCE3_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3" -typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR; +// VK_KHR_external_semaphore_fd is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_semaphore_fd 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd" +typedef struct VkImportSemaphoreFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + int fd; +} VkImportSemaphoreFdInfoKHR; -typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR; +typedef struct VkSemaphoreGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetFdInfoKHR; -typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR( VkDevice device, - const VkDescriptorSetLayoutCreateInfo* pCreateInfo, - VkDescriptorSetLayoutSupport* pSupport); + const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( + VkDevice device, + const VkSemaphoreGetFdInfoKHR* pGetFdInfo, + int* pFd); #endif -#define VK_KHR_draw_indirect_count 1 -#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 -#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count" -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +// VK_KHR_push_descriptor is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_push_descriptor 1 +#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2 +#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor" +typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t maxPushDescriptors; +} VkPhysicalDevicePushDescriptorPropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR( +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkBuffer countBuffer, - VkDeviceSize countBufferOffset, - uint32_t maxDrawCount, - uint32_t stride); + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites); -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR( +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkBuffer countBuffer, - VkDeviceSize countBufferOffset, - uint32_t maxDrawCount, - uint32_t stride); + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData); #endif -#define VK_KHR_shader_subgroup_extended_types 1 -#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION 1 -#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME "VK_KHR_shader_subgroup_extended_types" -typedef VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR; +// VK_KHR_shader_float16_int8 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_float16_int8 1 +#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1 +#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8" +typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceShaderFloat16Int8FeaturesKHR; +typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceFloat16Int8FeaturesKHR; -#define VK_KHR_8bit_storage 1 -#define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1 -#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage" -typedef VkPhysicalDevice8BitStorageFeatures VkPhysicalDevice8BitStorageFeaturesKHR; +// VK_KHR_16bit_storage is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_16bit_storage 1 +#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" +typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR; -#define VK_KHR_shader_atomic_int64 1 -#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1 -#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64" -typedef VkPhysicalDeviceShaderAtomicInt64Features VkPhysicalDeviceShaderAtomicInt64FeaturesKHR; +// VK_KHR_incremental_present is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_incremental_present 1 +#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 2 +#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" +typedef struct VkRectLayerKHR { + VkOffset2D offset; + VkExtent2D extent; + uint32_t layer; +} VkRectLayerKHR; +typedef struct VkPresentRegionKHR { + uint32_t rectangleCount; + const VkRectLayerKHR* pRectangles; +} VkPresentRegionKHR; -#define VK_KHR_shader_clock 1 -#define VK_KHR_SHADER_CLOCK_SPEC_VERSION 1 -#define VK_KHR_SHADER_CLOCK_EXTENSION_NAME "VK_KHR_shader_clock" -typedef struct VkPhysicalDeviceShaderClockFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 shaderSubgroupClock; - VkBool32 shaderDeviceClock; -} VkPhysicalDeviceShaderClockFeaturesKHR; +typedef struct VkPresentRegionsKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentRegionKHR* pRegions; +} VkPresentRegionsKHR; -#define VK_KHR_driver_properties 1 -#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1 -#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties" -#define VK_MAX_DRIVER_NAME_SIZE_KHR VK_MAX_DRIVER_NAME_SIZE -#define VK_MAX_DRIVER_INFO_SIZE_KHR VK_MAX_DRIVER_INFO_SIZE -typedef VkDriverId VkDriverIdKHR; +// VK_KHR_descriptor_update_template is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_descriptor_update_template 1 +typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR; -typedef VkConformanceVersion VkConformanceVersionKHR; +#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1 +#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template" +typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR; -typedef VkPhysicalDeviceDriverProperties VkPhysicalDeviceDriverPropertiesKHR; +typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR; +typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR; +typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR; -#define VK_KHR_shader_float_controls 1 -#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 4 -#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls" -typedef VkShaderFloatControlsIndependence VkShaderFloatControlsIndependenceKHR; - -typedef VkPhysicalDeviceFloatControlsProperties VkPhysicalDeviceFloatControlsPropertiesKHR; - - +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); -#define VK_KHR_depth_stencil_resolve 1 -#define VK_KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION 1 -#define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME "VK_KHR_depth_stencil_resolve" -typedef VkResolveModeFlagBits VkResolveModeFlagBitsKHR; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR( + VkDevice device, + const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); -typedef VkResolveModeFlags VkResolveModeFlagsKHR; +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR( + VkDevice device, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const VkAllocationCallbacks* pAllocator); -typedef VkSubpassDescriptionDepthStencilResolve VkSubpassDescriptionDepthStencilResolveKHR; +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( + VkDevice device, + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const void* pData); +#endif -typedef VkPhysicalDeviceDepthStencilResolveProperties VkPhysicalDeviceDepthStencilResolvePropertiesKHR; +// VK_KHR_imageless_framebuffer is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_imageless_framebuffer 1 +#define VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION 1 +#define VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME "VK_KHR_imageless_framebuffer" +typedef VkPhysicalDeviceImagelessFramebufferFeatures VkPhysicalDeviceImagelessFramebufferFeaturesKHR; +typedef VkFramebufferAttachmentsCreateInfo VkFramebufferAttachmentsCreateInfoKHR; -#define VK_KHR_swapchain_mutable_format 1 -#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1 -#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format" +typedef VkFramebufferAttachmentImageInfo VkFramebufferAttachmentImageInfoKHR; +typedef VkRenderPassAttachmentBeginInfo VkRenderPassAttachmentBeginInfoKHR; -#define VK_KHR_timeline_semaphore 1 -#define VK_KHR_TIMELINE_SEMAPHORE_SPEC_VERSION 2 -#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME "VK_KHR_timeline_semaphore" -typedef VkSemaphoreType VkSemaphoreTypeKHR; -typedef VkSemaphoreWaitFlagBits VkSemaphoreWaitFlagBitsKHR; -typedef VkSemaphoreWaitFlags VkSemaphoreWaitFlagsKHR; +// VK_KHR_create_renderpass2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_create_renderpass2 1 +#define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1 +#define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2" +typedef VkRenderPassCreateInfo2 VkRenderPassCreateInfo2KHR; -typedef VkPhysicalDeviceTimelineSemaphoreFeatures VkPhysicalDeviceTimelineSemaphoreFeaturesKHR; +typedef VkAttachmentDescription2 VkAttachmentDescription2KHR; -typedef VkPhysicalDeviceTimelineSemaphoreProperties VkPhysicalDeviceTimelineSemaphorePropertiesKHR; +typedef VkAttachmentReference2 VkAttachmentReference2KHR; -typedef VkSemaphoreTypeCreateInfo VkSemaphoreTypeCreateInfoKHR; +typedef VkSubpassDescription2 VkSubpassDescription2KHR; -typedef VkTimelineSemaphoreSubmitInfo VkTimelineSemaphoreSubmitInfoKHR; +typedef VkSubpassDependency2 VkSubpassDependency2KHR; -typedef VkSemaphoreWaitInfo VkSemaphoreWaitInfoKHR; +typedef VkSubpassBeginInfo VkSubpassBeginInfoKHR; -typedef VkSemaphoreSignalInfo VkSemaphoreSignalInfoKHR; +typedef VkSubpassEndInfo VkSubpassEndInfoKHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValueKHR)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); -typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphoresKHR)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); -typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphoreKHR)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2KHR)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValueKHR( - VkDevice device, - VkSemaphore semaphore, - uint64_t* pValue); - -VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphoresKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR( VkDevice device, - const VkSemaphoreWaitInfo* pWaitInfo, - uint64_t timeout); + const VkRenderPassCreateInfo2* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); -VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphoreKHR( - VkDevice device, - const VkSemaphoreSignalInfo* pSignalInfo); -#endif +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + const VkSubpassBeginInfo* pSubpassBeginInfo); +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR( + VkCommandBuffer commandBuffer, + const VkSubpassBeginInfo* pSubpassBeginInfo, + const VkSubpassEndInfo* pSubpassEndInfo); -#define VK_KHR_vulkan_memory_model 1 -#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 3 -#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model" -typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryModelFeaturesKHR; +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR( + VkCommandBuffer commandBuffer, + const VkSubpassEndInfo* pSubpassEndInfo); +#endif +// VK_KHR_shared_presentable_image is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shared_presentable_image 1 +#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 +#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" +typedef struct VkSharedPresentSurfaceCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags sharedPresentSupportedUsageFlags; +} VkSharedPresentSurfaceCapabilitiesKHR; -#define VK_KHR_shader_terminate_invocation 1 -#define VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION 1 -#define VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME "VK_KHR_shader_terminate_invocation" -typedef struct VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 shaderTerminateInvocation; -} VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR; +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( + VkDevice device, + VkSwapchainKHR swapchain); +#endif -#define VK_KHR_fragment_shading_rate 1 -#define VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION 1 -#define VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME "VK_KHR_fragment_shading_rate" +// VK_KHR_external_fence_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_fence_capabilities 1 +#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities" +typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR; -typedef enum VkFragmentShadingRateCombinerOpKHR { - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0, - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1, - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2, - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3, - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4, - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_ENUM_KHR = 0x7FFFFFFF -} VkFragmentShadingRateCombinerOpKHR; -typedef struct VkFragmentShadingRateAttachmentInfoKHR { - VkStructureType sType; - const void* pNext; - const VkAttachmentReference2* pFragmentShadingRateAttachment; - VkExtent2D shadingRateAttachmentTexelSize; -} VkFragmentShadingRateAttachmentInfoKHR; +typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR; -typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkExtent2D fragmentSize; - VkFragmentShadingRateCombinerOpKHR combinerOps[2]; -} VkPipelineFragmentShadingRateStateCreateInfoKHR; +typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR; -typedef struct VkPhysicalDeviceFragmentShadingRateFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 pipelineFragmentShadingRate; - VkBool32 primitiveFragmentShadingRate; - VkBool32 attachmentFragmentShadingRate; -} VkPhysicalDeviceFragmentShadingRateFeaturesKHR; +typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR; -typedef struct VkPhysicalDeviceFragmentShadingRatePropertiesKHR { - VkStructureType sType; - void* pNext; - VkExtent2D minFragmentShadingRateAttachmentTexelSize; - VkExtent2D maxFragmentShadingRateAttachmentTexelSize; - uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio; - VkBool32 primitiveFragmentShadingRateWithMultipleViewports; - VkBool32 layeredShadingRateAttachments; - VkBool32 fragmentShadingRateNonTrivialCombinerOps; - VkExtent2D maxFragmentSize; - uint32_t maxFragmentSizeAspectRatio; - uint32_t maxFragmentShadingRateCoverageSamples; - VkSampleCountFlagBits maxFragmentShadingRateRasterizationSamples; - VkBool32 fragmentShadingRateWithShaderDepthStencilWrites; - VkBool32 fragmentShadingRateWithSampleMask; - VkBool32 fragmentShadingRateWithShaderSampleMask; - VkBool32 fragmentShadingRateWithConservativeRasterization; - VkBool32 fragmentShadingRateWithFragmentShaderInterlock; - VkBool32 fragmentShadingRateWithCustomSampleLocations; - VkBool32 fragmentShadingRateStrictMultiplyCombiner; -} VkPhysicalDeviceFragmentShadingRatePropertiesKHR; +typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR; -typedef struct VkPhysicalDeviceFragmentShadingRateKHR { - VkStructureType sType; - void* pNext; - VkSampleCountFlags sampleCounts; - VkExtent2D fragmentSize; -} VkPhysicalDeviceFragmentShadingRateKHR; +typedef VkExternalFenceProperties VkExternalFencePropertiesKHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pFragmentShadingRateCount, VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); -typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateKHR)(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceFragmentShadingRatesKHR( +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( VkPhysicalDevice physicalDevice, - uint32_t* pFragmentShadingRateCount, - VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( - VkCommandBuffer commandBuffer, - const VkExtent2D* pFragmentSize, - const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, + VkExternalFenceProperties* pExternalFenceProperties); #endif -#define VK_KHR_spirv_1_4 1 -#define VK_KHR_SPIRV_1_4_SPEC_VERSION 1 -#define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4" +// VK_KHR_external_fence is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_fence 1 +#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence" +typedef VkFenceImportFlags VkFenceImportFlagsKHR; +typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR; -#define VK_KHR_surface_protected_capabilities 1 -#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION 1 -#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME "VK_KHR_surface_protected_capabilities" -typedef struct VkSurfaceProtectedCapabilitiesKHR { - VkStructureType sType; - const void* pNext; - VkBool32 supportsProtected; -} VkSurfaceProtectedCapabilitiesKHR; +typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR; -#define VK_KHR_separate_depth_stencil_layouts 1 -#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION 1 -#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME "VK_KHR_separate_depth_stencil_layouts" -typedef VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR; +// VK_KHR_external_fence_fd is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_fence_fd 1 +#define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd" +typedef struct VkImportFenceFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkFenceImportFlags flags; + VkExternalFenceHandleTypeFlagBits handleType; + int fd; +} VkImportFenceFdInfoKHR; -typedef VkAttachmentReferenceStencilLayout VkAttachmentReferenceStencilLayoutKHR; +typedef struct VkFenceGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkExternalFenceHandleTypeFlagBits handleType; +} VkFenceGetFdInfoKHR; -typedef VkAttachmentDescriptionStencilLayout VkAttachmentDescriptionStencilLayoutKHR; +typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR( + VkDevice device, + const VkImportFenceFdInfoKHR* pImportFenceFdInfo); +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( + VkDevice device, + const VkFenceGetFdInfoKHR* pGetFdInfo, + int* pFd); +#endif -#define VK_KHR_present_wait 1 -#define VK_KHR_PRESENT_WAIT_SPEC_VERSION 1 -#define VK_KHR_PRESENT_WAIT_EXTENSION_NAME "VK_KHR_present_wait" -typedef struct VkPhysicalDevicePresentWaitFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 presentWait; -} VkPhysicalDevicePresentWaitFeaturesKHR; -typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresentKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout); +// VK_KHR_performance_query is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_performance_query 1 +#define VK_KHR_PERFORMANCE_QUERY_SPEC_VERSION 1 +#define VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME "VK_KHR_performance_query" -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresentKHR( - VkDevice device, - VkSwapchainKHR swapchain, - uint64_t presentId, - uint64_t timeout); -#endif +typedef enum VkPerformanceCounterUnitKHR { + VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR = 0, + VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR = 1, + VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR = 2, + VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR = 3, + VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR = 4, + VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR = 5, + VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR = 6, + VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR = 7, + VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR = 8, + VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR = 9, + VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR = 10, + VK_PERFORMANCE_COUNTER_UNIT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterUnitKHR; + +typedef enum VkPerformanceCounterScopeKHR { + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0, + VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1, + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2, + VK_QUERY_SCOPE_COMMAND_BUFFER_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR, + VK_QUERY_SCOPE_RENDER_PASS_KHR = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR, + VK_QUERY_SCOPE_COMMAND_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR, + VK_PERFORMANCE_COUNTER_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterScopeKHR; +typedef enum VkPerformanceCounterStorageKHR { + VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR = 0, + VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR = 1, + VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR = 2, + VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR = 3, + VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR = 4, + VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR = 5, + VK_PERFORMANCE_COUNTER_STORAGE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterStorageKHR; -#define VK_KHR_uniform_buffer_standard_layout 1 -#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 -#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" -typedef VkPhysicalDeviceUniformBufferStandardLayoutFeatures VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR; +typedef enum VkPerformanceCounterDescriptionFlagBitsKHR { + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0x00000001, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0x00000002, + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterDescriptionFlagBitsKHR; +typedef VkFlags VkPerformanceCounterDescriptionFlagsKHR; +typedef enum VkAcquireProfilingLockFlagBitsKHR { + VK_ACQUIRE_PROFILING_LOCK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAcquireProfilingLockFlagBitsKHR; +typedef VkFlags VkAcquireProfilingLockFlagsKHR; +typedef struct VkPhysicalDevicePerformanceQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 performanceCounterQueryPools; + VkBool32 performanceCounterMultipleQueryPools; +} VkPhysicalDevicePerformanceQueryFeaturesKHR; +typedef struct VkPhysicalDevicePerformanceQueryPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 allowCommandBufferQueryCopies; +} VkPhysicalDevicePerformanceQueryPropertiesKHR; -#define VK_KHR_buffer_device_address 1 -#define VK_KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 1 -#define VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_KHR_buffer_device_address" -typedef VkPhysicalDeviceBufferDeviceAddressFeatures VkPhysicalDeviceBufferDeviceAddressFeaturesKHR; +typedef struct VkPerformanceCounterKHR { + VkStructureType sType; + void* pNext; + VkPerformanceCounterUnitKHR unit; + VkPerformanceCounterScopeKHR scope; + VkPerformanceCounterStorageKHR storage; + uint8_t uuid[VK_UUID_SIZE]; +} VkPerformanceCounterKHR; -typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoKHR; +typedef struct VkPerformanceCounterDescriptionKHR { + VkStructureType sType; + void* pNext; + VkPerformanceCounterDescriptionFlagsKHR flags; + char name[VK_MAX_DESCRIPTION_SIZE]; + char category[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkPerformanceCounterDescriptionKHR; -typedef VkBufferOpaqueCaptureAddressCreateInfo VkBufferOpaqueCaptureAddressCreateInfoKHR; +typedef struct VkQueryPoolPerformanceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + uint32_t counterIndexCount; + const uint32_t* pCounterIndices; +} VkQueryPoolPerformanceCreateInfoKHR; -typedef VkMemoryOpaqueCaptureAddressAllocateInfo VkMemoryOpaqueCaptureAddressAllocateInfoKHR; +typedef union VkPerformanceCounterResultKHR { + int32_t int32; + int64_t int64; + uint32_t uint32; + uint64_t uint64; + float float32; + double float64; +} VkPerformanceCounterResultKHR; -typedef VkDeviceMemoryOpaqueCaptureAddressInfo VkDeviceMemoryOpaqueCaptureAddressInfoKHR; +typedef struct VkAcquireProfilingLockInfoKHR { + VkStructureType sType; + const void* pNext; + VkAcquireProfilingLockFlagsKHR flags; + uint64_t timeout; +} VkAcquireProfilingLockInfoKHR; -typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); -typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); -typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +typedef struct VkPerformanceQuerySubmitInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t counterPassIndex; +} VkPerformanceQuerySubmitInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters, VkPerformanceCounterDescriptionKHR* pCounterDescriptions); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)(VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireProfilingLockKHR)(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkReleaseProfilingLockKHR)(VkDevice device); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressKHR( - VkDevice device, - const VkBufferDeviceAddressInfo* pInfo); +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + uint32_t* pCounterCount, + VkPerformanceCounterKHR* pCounters, + VkPerformanceCounterDescriptionKHR* pCounterDescriptions); -VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddressKHR( - VkDevice device, - const VkBufferDeviceAddressInfo* pInfo); +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( + VkPhysicalDevice physicalDevice, + const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, + uint32_t* pNumPasses); -VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireProfilingLockKHR( VkDevice device, - const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); + const VkAcquireProfilingLockInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR( + VkDevice device); #endif -#define VK_KHR_deferred_host_operations 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) -#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 4 -#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" -typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); -typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); -typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); -typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); -typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); +// VK_KHR_maintenance2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance2 1 +#define VK_KHR_MAINTENANCE_2_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_2_EXTENSION_NAME "VK_KHR_maintenance2" +#define VK_KHR_MAINTENANCE2_SPEC_VERSION VK_KHR_MAINTENANCE_2_SPEC_VERSION +#define VK_KHR_MAINTENANCE2_EXTENSION_NAME VK_KHR_MAINTENANCE_2_EXTENSION_NAME +typedef VkPointClippingBehavior VkPointClippingBehaviorKHR; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( - VkDevice device, - const VkAllocationCallbacks* pAllocator, - VkDeferredOperationKHR* pDeferredOperation); +typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR; -VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( - VkDevice device, - VkDeferredOperationKHR operation, - const VkAllocationCallbacks* pAllocator); +typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR; -VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( - VkDevice device, - VkDeferredOperationKHR operation); +typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR; -VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( - VkDevice device, - VkDeferredOperationKHR operation); +typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR; -VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( - VkDevice device, - VkDeferredOperationKHR operation); -#endif +typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR; +typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR; -#define VK_KHR_pipeline_executable_properties 1 -#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1 -#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties" -typedef enum VkPipelineExecutableStatisticFormatKHR { - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR = 0, - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR = 1, - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR = 2, - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR = 3, - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPipelineExecutableStatisticFormatKHR; -typedef struct VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 pipelineExecutableInfo; -} VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR; -typedef struct VkPipelineInfoKHR { +// VK_KHR_get_surface_capabilities2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_get_surface_capabilities2 1 +#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2" +typedef struct VkPhysicalDeviceSurfaceInfo2KHR { VkStructureType sType; const void* pNext; - VkPipeline pipeline; -} VkPipelineInfoKHR; + VkSurfaceKHR surface; +} VkPhysicalDeviceSurfaceInfo2KHR; -typedef struct VkPipelineExecutablePropertiesKHR { +typedef struct VkSurfaceCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkSurfaceCapabilitiesKHR surfaceCapabilities; +} VkSurfaceCapabilities2KHR; + +typedef struct VkSurfaceFormat2KHR { VkStructureType sType; void* pNext; - VkShaderStageFlags stages; - char name[VK_MAX_DESCRIPTION_SIZE]; - char description[VK_MAX_DESCRIPTION_SIZE]; - uint32_t subgroupSize; -} VkPipelineExecutablePropertiesKHR; + VkSurfaceFormatKHR surfaceFormat; +} VkSurfaceFormat2KHR; -typedef struct VkPipelineExecutableInfoKHR { - VkStructureType sType; - const void* pNext; - VkPipeline pipeline; - uint32_t executableIndex; -} VkPipelineExecutableInfoKHR; +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); -typedef union VkPipelineExecutableStatisticValueKHR { - VkBool32 b32; - int64_t i64; - uint64_t u64; - double f64; -} VkPipelineExecutableStatisticValueKHR; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + VkSurfaceCapabilities2KHR* pSurfaceCapabilities); -typedef struct VkPipelineExecutableStatisticKHR { - VkStructureType sType; - void* pNext; - char name[VK_MAX_DESCRIPTION_SIZE]; - char description[VK_MAX_DESCRIPTION_SIZE]; - VkPipelineExecutableStatisticFormatKHR format; - VkPipelineExecutableStatisticValueKHR value; -} VkPipelineExecutableStatisticKHR; - -typedef struct VkPipelineExecutableInternalRepresentationKHR { - VkStructureType sType; - void* pNext; - char name[VK_MAX_DESCRIPTION_SIZE]; - char description[VK_MAX_DESCRIPTION_SIZE]; - VkBool32 isText; - size_t dataSize; - void* pData; -} VkPipelineExecutableInternalRepresentationKHR; +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + uint32_t* pSurfaceFormatCount, + VkSurfaceFormat2KHR* pSurfaceFormats); +#endif -typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutablePropertiesKHR)(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableStatisticsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics); -typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableInternalRepresentationsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutablePropertiesKHR( - VkDevice device, - const VkPipelineInfoKHR* pPipelineInfo, - uint32_t* pExecutableCount, - VkPipelineExecutablePropertiesKHR* pProperties); +// VK_KHR_variable_pointers is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_variable_pointers 1 +#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1 +#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers" +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeaturesKHR; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableStatisticsKHR( - VkDevice device, - const VkPipelineExecutableInfoKHR* pExecutableInfo, - uint32_t* pStatisticCount, - VkPipelineExecutableStatisticKHR* pStatistics); +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointersFeaturesKHR; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR( - VkDevice device, - const VkPipelineExecutableInfoKHR* pExecutableInfo, - uint32_t* pInternalRepresentationCount, - VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); -#endif -#define VK_KHR_pipeline_library 1 -#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 -#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" -typedef struct VkPipelineLibraryCreateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t libraryCount; - const VkPipeline* pLibraries; -} VkPipelineLibraryCreateInfoKHR; +// VK_KHR_get_display_properties2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_get_display_properties2 1 +#define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2" +typedef struct VkDisplayProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPropertiesKHR displayProperties; +} VkDisplayProperties2KHR; +typedef struct VkDisplayPlaneProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPlanePropertiesKHR displayPlaneProperties; +} VkDisplayPlaneProperties2KHR; +typedef struct VkDisplayModeProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayModePropertiesKHR displayModeProperties; +} VkDisplayModeProperties2KHR; -#define VK_KHR_shader_non_semantic_info 1 -#define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 -#define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" +typedef struct VkDisplayPlaneInfo2KHR { + VkStructureType sType; + const void* pNext; + VkDisplayModeKHR mode; + uint32_t planeIndex; +} VkDisplayPlaneInfo2KHR; +typedef struct VkDisplayPlaneCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPlaneCapabilitiesKHR capabilities; +} VkDisplayPlaneCapabilities2KHR; -#define VK_KHR_present_id 1 -#define VK_KHR_PRESENT_ID_SPEC_VERSION 1 -#define VK_KHR_PRESENT_ID_EXTENSION_NAME "VK_KHR_present_id" -typedef struct VkPresentIdKHR { - VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const uint64_t* pPresentIds; -} VkPresentIdKHR; +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities); -typedef struct VkPhysicalDevicePresentIdFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 presentId; -} VkPhysicalDevicePresentIdFeaturesKHR; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayProperties2KHR* pProperties); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPlaneProperties2KHR* pProperties); +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + uint32_t* pPropertyCount, + VkDisplayModeProperties2KHR* pProperties); -#define VK_KHR_synchronization2 1 -typedef uint64_t VkFlags64; -#define VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION 1 -#define VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME "VK_KHR_synchronization2" -typedef VkFlags64 VkPipelineStageFlags2KHR; - -// Flag bits for VkPipelineStageFlagBits2KHR -typedef VkFlags64 VkPipelineStageFlagBits2KHR; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_NONE_KHR = 0ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL; -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0x04000000ULL; -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0x08000000ULL; -#endif -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL; -static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; - -typedef VkFlags64 VkAccessFlags2KHR; - -// Flag bits for VkAccessFlagBits2KHR -typedef VkFlags64 VkAccessFlagBits2KHR; -static const VkAccessFlagBits2KHR VK_ACCESS_2_NONE_KHR = 0ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL; -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL; -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL; -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL; +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR( + VkPhysicalDevice physicalDevice, + const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, + VkDisplayPlaneCapabilities2KHR* pCapabilities); #endif -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL; -#endif -static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000ULL; -static const VkAccessFlagBits2KHR VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0x8000000000ULL; - - -typedef enum VkSubmitFlagBitsKHR { - VK_SUBMIT_PROTECTED_BIT_KHR = 0x00000001, - VK_SUBMIT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkSubmitFlagBitsKHR; -typedef VkFlags VkSubmitFlagsKHR; -typedef struct VkMemoryBarrier2KHR { - VkStructureType sType; - const void* pNext; - VkPipelineStageFlags2KHR srcStageMask; - VkAccessFlags2KHR srcAccessMask; - VkPipelineStageFlags2KHR dstStageMask; - VkAccessFlags2KHR dstAccessMask; -} VkMemoryBarrier2KHR; -typedef struct VkBufferMemoryBarrier2KHR { - VkStructureType sType; - const void* pNext; - VkPipelineStageFlags2KHR srcStageMask; - VkAccessFlags2KHR srcAccessMask; - VkPipelineStageFlags2KHR dstStageMask; - VkAccessFlags2KHR dstAccessMask; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize size; -} VkBufferMemoryBarrier2KHR; -typedef struct VkImageMemoryBarrier2KHR { - VkStructureType sType; - const void* pNext; - VkPipelineStageFlags2KHR srcStageMask; - VkAccessFlags2KHR srcAccessMask; - VkPipelineStageFlags2KHR dstStageMask; - VkAccessFlags2KHR dstAccessMask; - VkImageLayout oldLayout; - VkImageLayout newLayout; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkImage image; - VkImageSubresourceRange subresourceRange; -} VkImageMemoryBarrier2KHR; - -typedef struct VkDependencyInfoKHR { - VkStructureType sType; - const void* pNext; - VkDependencyFlags dependencyFlags; - uint32_t memoryBarrierCount; - const VkMemoryBarrier2KHR* pMemoryBarriers; - uint32_t bufferMemoryBarrierCount; - const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers; - uint32_t imageMemoryBarrierCount; - const VkImageMemoryBarrier2KHR* pImageMemoryBarriers; -} VkDependencyInfoKHR; - -typedef struct VkSemaphoreSubmitInfoKHR { - VkStructureType sType; - const void* pNext; - VkSemaphore semaphore; - uint64_t value; - VkPipelineStageFlags2KHR stageMask; - uint32_t deviceIndex; -} VkSemaphoreSubmitInfoKHR; +// VK_KHR_dedicated_allocation is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_dedicated_allocation 1 +#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3 +#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation" +typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR; -typedef struct VkCommandBufferSubmitInfoKHR { - VkStructureType sType; - const void* pNext; - VkCommandBuffer commandBuffer; - uint32_t deviceMask; -} VkCommandBufferSubmitInfoKHR; +typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; -typedef struct VkSubmitInfo2KHR { - VkStructureType sType; - const void* pNext; - VkSubmitFlagsKHR flags; - uint32_t waitSemaphoreInfoCount; - const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos; - uint32_t commandBufferInfoCount; - const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos; - uint32_t signalSemaphoreInfoCount; - const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos; -} VkSubmitInfo2KHR; -typedef struct VkPhysicalDeviceSynchronization2FeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 synchronization2; -} VkPhysicalDeviceSynchronization2FeaturesKHR; -typedef struct VkQueueFamilyCheckpointProperties2NV { - VkStructureType sType; - void* pNext; - VkPipelineStageFlags2KHR checkpointExecutionStageMask; -} VkQueueFamilyCheckpointProperties2NV; +// VK_KHR_storage_buffer_storage_class is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_storage_buffer_storage_class 1 +#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1 +#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class" -typedef struct VkCheckpointData2NV { - VkStructureType sType; - void* pNext; - VkPipelineStageFlags2KHR stage; - void* pCheckpointMarker; -} VkCheckpointData2NV; -typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfoKHR* pDependencyInfo); -typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2KHR stageMask); -typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2KHR)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfoKHR* pDependencyInfos); -typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2KHR)(VkCommandBuffer commandBuffer, const VkDependencyInfoKHR* pDependencyInfo); -typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2KHR)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR stage, VkQueryPool queryPool, uint32_t query); -typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR* pSubmits, VkFence fence); -typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarker2AMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR stage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); -typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointData2NV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); +// VK_KHR_relaxed_block_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_relaxed_block_layout 1 +#define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout" -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2KHR( - VkCommandBuffer commandBuffer, - VkEvent event, - const VkDependencyInfoKHR* pDependencyInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2KHR( - VkCommandBuffer commandBuffer, - VkEvent event, - VkPipelineStageFlags2KHR stageMask); +// VK_KHR_get_memory_requirements2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_get_memory_requirements2 1 +#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1 +#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2" +typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR; -VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2KHR( - VkCommandBuffer commandBuffer, - uint32_t eventCount, - const VkEvent* pEvents, - const VkDependencyInfoKHR* pDependencyInfos); +typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR; -VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2KHR( - VkCommandBuffer commandBuffer, - const VkDependencyInfoKHR* pDependencyInfo); +typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR; -VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2KHR( - VkCommandBuffer commandBuffer, - VkPipelineStageFlags2KHR stage, - VkQueryPool queryPool, - uint32_t query); +typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; -VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2KHR( - VkQueue queue, - uint32_t submitCount, - const VkSubmitInfo2KHR* pSubmits, - VkFence fence); +typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR; -VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( - VkCommandBuffer commandBuffer, - VkPipelineStageFlags2KHR stage, - VkBuffer dstBuffer, - VkDeviceSize dstOffset, - uint32_t marker); +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); -VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( - VkQueue queue, - uint32_t* pCheckpointDataCount, - VkCheckpointData2NV* pCheckpointData); -#endif +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR( + VkDevice device, + const VkImageMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR( + VkDevice device, + const VkBufferMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); -#define VK_KHR_shader_subgroup_uniform_control_flow 1 -#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION 1 -#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME "VK_KHR_shader_subgroup_uniform_control_flow" -typedef struct VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 shaderSubgroupUniformControlFlow; -} VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR; +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( + VkDevice device, + const VkImageSparseMemoryRequirementsInfo2* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif +// VK_KHR_image_format_list is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_image_format_list 1 +#define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1 +#define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list" +typedef VkImageFormatListCreateInfo VkImageFormatListCreateInfoKHR; -#define VK_KHR_zero_initialize_workgroup_memory 1 -#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION 1 -#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME "VK_KHR_zero_initialize_workgroup_memory" -typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 shaderZeroInitializeWorkgroupMemory; -} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR; +// VK_KHR_sampler_ycbcr_conversion is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_sampler_ycbcr_conversion 1 +typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR; -#define VK_KHR_workgroup_memory_explicit_layout 1 -#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION 1 -#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME "VK_KHR_workgroup_memory_explicit_layout" -typedef struct VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 workgroupMemoryExplicitLayout; - VkBool32 workgroupMemoryExplicitLayoutScalarBlockLayout; - VkBool32 workgroupMemoryExplicitLayout8BitAccess; - VkBool32 workgroupMemoryExplicitLayout16BitAccess; -} VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR; - +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 14 +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion" +typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR; +typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR; -#define VK_KHR_copy_commands2 1 -#define VK_KHR_COPY_COMMANDS_2_SPEC_VERSION 1 -#define VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME "VK_KHR_copy_commands2" -typedef struct VkBufferCopy2KHR { - VkStructureType sType; - const void* pNext; - VkDeviceSize srcOffset; - VkDeviceSize dstOffset; - VkDeviceSize size; -} VkBufferCopy2KHR; +typedef VkChromaLocation VkChromaLocationKHR; -typedef struct VkCopyBufferInfo2KHR { - VkStructureType sType; - const void* pNext; - VkBuffer srcBuffer; - VkBuffer dstBuffer; - uint32_t regionCount; - const VkBufferCopy2KHR* pRegions; -} VkCopyBufferInfo2KHR; +typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR; -typedef struct VkImageCopy2KHR { - VkStructureType sType; - const void* pNext; - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffset; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffset; - VkExtent3D extent; -} VkImageCopy2KHR; +typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR; -typedef struct VkCopyImageInfo2KHR { - VkStructureType sType; - const void* pNext; - VkImage srcImage; - VkImageLayout srcImageLayout; - VkImage dstImage; - VkImageLayout dstImageLayout; - uint32_t regionCount; - const VkImageCopy2KHR* pRegions; -} VkCopyImageInfo2KHR; +typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR; -typedef struct VkBufferImageCopy2KHR { - VkStructureType sType; - const void* pNext; - VkDeviceSize bufferOffset; - uint32_t bufferRowLength; - uint32_t bufferImageHeight; - VkImageSubresourceLayers imageSubresource; - VkOffset3D imageOffset; - VkExtent3D imageExtent; -} VkBufferImageCopy2KHR; +typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR; -typedef struct VkCopyBufferToImageInfo2KHR { - VkStructureType sType; - const void* pNext; - VkBuffer srcBuffer; - VkImage dstImage; - VkImageLayout dstImageLayout; - uint32_t regionCount; - const VkBufferImageCopy2KHR* pRegions; -} VkCopyBufferToImageInfo2KHR; - -typedef struct VkCopyImageToBufferInfo2KHR { - VkStructureType sType; - const void* pNext; - VkImage srcImage; - VkImageLayout srcImageLayout; - VkBuffer dstBuffer; - uint32_t regionCount; - const VkBufferImageCopy2KHR* pRegions; -} VkCopyImageToBufferInfo2KHR; - -typedef struct VkImageBlit2KHR { - VkStructureType sType; - const void* pNext; - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffsets[2]; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffsets[2]; -} VkImageBlit2KHR; +typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR; -typedef struct VkBlitImageInfo2KHR { - VkStructureType sType; - const void* pNext; - VkImage srcImage; - VkImageLayout srcImageLayout; - VkImage dstImage; - VkImageLayout dstImageLayout; - uint32_t regionCount; - const VkImageBlit2KHR* pRegions; - VkFilter filter; -} VkBlitImageInfo2KHR; +typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR; -typedef struct VkImageResolve2KHR { - VkStructureType sType; - const void* pNext; - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffset; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffset; - VkExtent3D extent; -} VkImageResolve2KHR; +typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); -typedef struct VkResolveImageInfo2KHR { - VkStructureType sType; - const void* pNext; - VkImage srcImage; - VkImageLayout srcImageLayout; - VkImage dstImage; - VkImageLayout dstImageLayout; - uint32_t regionCount; - const VkImageResolve2KHR* pRegions; -} VkResolveImageInfo2KHR; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR( + VkDevice device, + const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversion* pYcbcrConversion); -typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2KHR* pCopyBufferInfo); -typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2KHR* pCopyImageInfo); -typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo); -typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo); -typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2KHR)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2KHR* pBlitImageInfo); -typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2KHR)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2KHR* pResolveImageInfo); +VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( + VkDevice device, + VkSamplerYcbcrConversion ycbcrConversion, + const VkAllocationCallbacks* pAllocator); +#endif -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2KHR( - VkCommandBuffer commandBuffer, - const VkCopyBufferInfo2KHR* pCopyBufferInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2KHR( - VkCommandBuffer commandBuffer, - const VkCopyImageInfo2KHR* pCopyImageInfo); +// VK_KHR_bind_memory2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_bind_memory2 1 +#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1 +#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2" +typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR; -VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2KHR( - VkCommandBuffer commandBuffer, - const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo); +typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR; -VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2KHR( - VkCommandBuffer commandBuffer, - const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo); +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); -VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2KHR( - VkCommandBuffer commandBuffer, - const VkBlitImageInfo2KHR* pBlitImageInfo); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindBufferMemoryInfo* pBindInfos); -VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( - VkCommandBuffer commandBuffer, - const VkResolveImageInfo2KHR* pResolveImageInfo); +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindImageMemoryInfo* pBindInfos); #endif -#define VK_EXT_debug_report 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) -#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 -#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" +// VK_KHR_maintenance3 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance3 1 +#define VK_KHR_MAINTENANCE_3_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_3_EXTENSION_NAME "VK_KHR_maintenance3" +#define VK_KHR_MAINTENANCE3_SPEC_VERSION VK_KHR_MAINTENANCE_3_SPEC_VERSION +#define VK_KHR_MAINTENANCE3_EXTENSION_NAME VK_KHR_MAINTENANCE_3_EXTENSION_NAME +typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR; -typedef enum VkDebugReportObjectTypeEXT { - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0, - VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1, - VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2, - VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3, - VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4, - VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5, - VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6, - VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7, - VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8, - VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9, - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10, - VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11, - VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12, - VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13, - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14, - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15, - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16, - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17, - VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18, - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20, - VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23, - VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24, - VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25, - VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26, - VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27, - VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28, - VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29, - VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30, - VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, - VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, - VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT = 1000029000, - VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT = 1000029001, - VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000, - VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000, - VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDebugReportObjectTypeEXT; +typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR; -typedef enum VkDebugReportFlagBitsEXT { - VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001, - VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002, - VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004, - VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008, - VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010, - VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDebugReportFlagBitsEXT; -typedef VkFlags VkDebugReportFlagsEXT; -typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( - VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage, - void* pUserData); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); -typedef struct VkDebugReportCallbackCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkDebugReportFlagsEXT flags; - PFN_vkDebugReportCallbackEXT pfnCallback; - void* pUserData; -} VkDebugReportCallbackCreateInfoEXT; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + VkDescriptorSetLayoutSupport* pSupport); +#endif -typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); -typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( - VkInstance instance, - const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDebugReportCallbackEXT* pCallback); +// VK_KHR_draw_indirect_count is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_draw_indirect_count 1 +#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 +#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count" +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); -VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT( - VkInstance instance, - VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks* pAllocator); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); -VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( - VkInstance instance, - VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage); +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); #endif -#define VK_NV_glsl_shader 1 -#define VK_NV_GLSL_SHADER_SPEC_VERSION 1 -#define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader" +// VK_KHR_shader_subgroup_extended_types is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_subgroup_extended_types 1 +#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME "VK_KHR_shader_subgroup_extended_types" +typedef VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR; -#define VK_EXT_depth_range_unrestricted 1 -#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1 -#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted" +// VK_KHR_8bit_storage is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_8bit_storage 1 +#define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage" +typedef VkPhysicalDevice8BitStorageFeatures VkPhysicalDevice8BitStorageFeaturesKHR; -#define VK_IMG_filter_cubic 1 -#define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1 -#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic" -#define VK_AMD_rasterization_order 1 -#define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1 -#define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order" +// VK_KHR_shader_atomic_int64 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_atomic_int64 1 +#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64" +typedef VkPhysicalDeviceShaderAtomicInt64Features VkPhysicalDeviceShaderAtomicInt64FeaturesKHR; -typedef enum VkRasterizationOrderAMD { - VK_RASTERIZATION_ORDER_STRICT_AMD = 0, - VK_RASTERIZATION_ORDER_RELAXED_AMD = 1, - VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF -} VkRasterizationOrderAMD; -typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { - VkStructureType sType; - const void* pNext; - VkRasterizationOrderAMD rasterizationOrder; -} VkPipelineRasterizationStateRasterizationOrderAMD; +// VK_KHR_shader_clock is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_clock 1 +#define VK_KHR_SHADER_CLOCK_SPEC_VERSION 1 +#define VK_KHR_SHADER_CLOCK_EXTENSION_NAME "VK_KHR_shader_clock" +typedef struct VkPhysicalDeviceShaderClockFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupClock; + VkBool32 shaderDeviceClock; +} VkPhysicalDeviceShaderClockFeaturesKHR; -#define VK_AMD_shader_trinary_minmax 1 -#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1 -#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax" -#define VK_AMD_shader_explicit_vertex_parameter 1 -#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1 -#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter" +// VK_KHR_video_decode_h265 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_h265 1 +#include "vk_video/vulkan_video_codec_h265std.h" +#include "vk_video/vulkan_video_codec_h265std_decode.h" +#define VK_KHR_VIDEO_DECODE_H265_SPEC_VERSION 7 +#define VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME "VK_KHR_video_decode_h265" +typedef struct VkVideoDecodeH265ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoH265ProfileIdc stdProfileIdc; +} VkVideoDecodeH265ProfileInfoKHR; +typedef struct VkVideoDecodeH265CapabilitiesKHR { + VkStructureType sType; + void* pNext; + StdVideoH265LevelIdc maxLevelIdc; +} VkVideoDecodeH265CapabilitiesKHR; -#define VK_EXT_debug_marker 1 -#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4 -#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker" -typedef struct VkDebugMarkerObjectNameInfoEXT { - VkStructureType sType; - const void* pNext; - VkDebugReportObjectTypeEXT objectType; - uint64_t object; - const char* pObjectName; -} VkDebugMarkerObjectNameInfoEXT; +typedef struct VkVideoDecodeH265SessionParametersAddInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t stdVPSCount; + const StdVideoH265VideoParameterSet* pStdVPSs; + uint32_t stdSPSCount; + const StdVideoH265SequenceParameterSet* pStdSPSs; + uint32_t stdPPSCount; + const StdVideoH265PictureParameterSet* pStdPPSs; +} VkVideoDecodeH265SessionParametersAddInfoKHR; + +typedef struct VkVideoDecodeH265SessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxStdVPSCount; + uint32_t maxStdSPSCount; + uint32_t maxStdPPSCount; + const VkVideoDecodeH265SessionParametersAddInfoKHR* pParametersAddInfo; +} VkVideoDecodeH265SessionParametersCreateInfoKHR; -typedef struct VkDebugMarkerObjectTagInfoEXT { - VkStructureType sType; - const void* pNext; - VkDebugReportObjectTypeEXT objectType; - uint64_t object; - uint64_t tagName; - size_t tagSize; - const void* pTag; -} VkDebugMarkerObjectTagInfoEXT; +typedef struct VkVideoDecodeH265PictureInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH265PictureInfo* pStdPictureInfo; + uint32_t sliceSegmentCount; + const uint32_t* pSliceSegmentOffsets; +} VkVideoDecodeH265PictureInfoKHR; -typedef struct VkDebugMarkerMarkerInfoEXT { +typedef struct VkVideoDecodeH265DpbSlotInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeH265DpbSlotInfoKHR; + + + +// VK_KHR_global_priority is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_global_priority 1 +#define VK_MAX_GLOBAL_PRIORITY_SIZE_KHR 16U +#define VK_KHR_GLOBAL_PRIORITY_SPEC_VERSION 1 +#define VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME "VK_KHR_global_priority" + +typedef enum VkQueueGlobalPriorityKHR { + VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR = 128, + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR = 256, + VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR = 512, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR = 1024, + VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR, + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR, + VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR, + VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM_KHR = 0x7FFFFFFF +} VkQueueGlobalPriorityKHR; +typedef struct VkDeviceQueueGlobalPriorityCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkQueueGlobalPriorityKHR globalPriority; +} VkDeviceQueueGlobalPriorityCreateInfoKHR; + +typedef struct VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR { VkStructureType sType; - const void* pNext; - const char* pMarkerName; - float color[4]; -} VkDebugMarkerMarkerInfoEXT; + void* pNext; + VkBool32 globalPriorityQuery; +} VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR; -typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo); -typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo); -typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); -typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuffer); -typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +typedef struct VkQueueFamilyGlobalPriorityPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t priorityCount; + VkQueueGlobalPriorityKHR priorities[VK_MAX_GLOBAL_PRIORITY_SIZE_KHR]; +} VkQueueFamilyGlobalPriorityPropertiesKHR; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT( - VkDevice device, - const VkDebugMarkerObjectTagInfoEXT* pTagInfo); -VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT( - VkDevice device, - const VkDebugMarkerObjectNameInfoEXT* pNameInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT( - VkCommandBuffer commandBuffer, - const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +// VK_KHR_driver_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_driver_properties 1 +#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties" +#define VK_MAX_DRIVER_NAME_SIZE_KHR VK_MAX_DRIVER_NAME_SIZE +#define VK_MAX_DRIVER_INFO_SIZE_KHR VK_MAX_DRIVER_INFO_SIZE +typedef VkDriverId VkDriverIdKHR; -VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT( - VkCommandBuffer commandBuffer); +typedef VkConformanceVersion VkConformanceVersionKHR; -VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( - VkCommandBuffer commandBuffer, - const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); -#endif +typedef VkPhysicalDeviceDriverProperties VkPhysicalDeviceDriverPropertiesKHR; -#define VK_AMD_gcn_shader 1 -#define VK_AMD_GCN_SHADER_SPEC_VERSION 1 -#define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader" +// VK_KHR_shader_float_controls is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_float_controls 1 +#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 4 +#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls" +typedef VkShaderFloatControlsIndependence VkShaderFloatControlsIndependenceKHR; -#define VK_NV_dedicated_allocation 1 -#define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1 -#define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation" -typedef struct VkDedicatedAllocationImageCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 dedicatedAllocation; -} VkDedicatedAllocationImageCreateInfoNV; +typedef VkPhysicalDeviceFloatControlsProperties VkPhysicalDeviceFloatControlsPropertiesKHR; -typedef struct VkDedicatedAllocationBufferCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 dedicatedAllocation; -} VkDedicatedAllocationBufferCreateInfoNV; -typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { - VkStructureType sType; - const void* pNext; - VkImage image; - VkBuffer buffer; -} VkDedicatedAllocationMemoryAllocateInfoNV; +// VK_KHR_depth_stencil_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_depth_stencil_resolve 1 +#define VK_KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION 1 +#define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME "VK_KHR_depth_stencil_resolve" +typedef VkResolveModeFlagBits VkResolveModeFlagBitsKHR; +typedef VkResolveModeFlags VkResolveModeFlagsKHR; -#define VK_EXT_transform_feedback 1 -#define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1 -#define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback" -typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT; -typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 transformFeedback; - VkBool32 geometryStreams; -} VkPhysicalDeviceTransformFeedbackFeaturesEXT; +typedef VkSubpassDescriptionDepthStencilResolve VkSubpassDescriptionDepthStencilResolveKHR; -typedef struct VkPhysicalDeviceTransformFeedbackPropertiesEXT { - VkStructureType sType; - void* pNext; - uint32_t maxTransformFeedbackStreams; - uint32_t maxTransformFeedbackBuffers; - VkDeviceSize maxTransformFeedbackBufferSize; - uint32_t maxTransformFeedbackStreamDataSize; - uint32_t maxTransformFeedbackBufferDataSize; - uint32_t maxTransformFeedbackBufferDataStride; - VkBool32 transformFeedbackQueries; - VkBool32 transformFeedbackStreamsLinesTriangles; - VkBool32 transformFeedbackRasterizationStreamSelect; - VkBool32 transformFeedbackDraw; -} VkPhysicalDeviceTransformFeedbackPropertiesEXT; +typedef VkPhysicalDeviceDepthStencilResolveProperties VkPhysicalDeviceDepthStencilResolvePropertiesKHR; -typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkPipelineRasterizationStateStreamCreateFlagsEXT flags; - uint32_t rasterizationStream; -} VkPipelineRasterizationStateStreamCreateInfoEXT; -typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes); -typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); -typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); -typedef void (VKAPI_PTR *PFN_vkCmdBeginQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index); -typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index); -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT( - VkCommandBuffer commandBuffer, - uint32_t firstBinding, - uint32_t bindingCount, - const VkBuffer* pBuffers, - const VkDeviceSize* pOffsets, - const VkDeviceSize* pSizes); +// VK_KHR_swapchain_mutable_format is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_swapchain_mutable_format 1 +#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1 +#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format" -VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT( - VkCommandBuffer commandBuffer, - uint32_t firstCounterBuffer, - uint32_t counterBufferCount, - const VkBuffer* pCounterBuffers, - const VkDeviceSize* pCounterBufferOffsets); -VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT( - VkCommandBuffer commandBuffer, - uint32_t firstCounterBuffer, - uint32_t counterBufferCount, - const VkBuffer* pCounterBuffers, - const VkDeviceSize* pCounterBufferOffsets); +// VK_KHR_timeline_semaphore is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_timeline_semaphore 1 +#define VK_KHR_TIMELINE_SEMAPHORE_SPEC_VERSION 2 +#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME "VK_KHR_timeline_semaphore" +typedef VkSemaphoreType VkSemaphoreTypeKHR; -VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t query, - VkQueryControlFlags flags, - uint32_t index); +typedef VkSemaphoreWaitFlagBits VkSemaphoreWaitFlagBitsKHR; -VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t query, - uint32_t index); +typedef VkSemaphoreWaitFlags VkSemaphoreWaitFlagsKHR; -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( - VkCommandBuffer commandBuffer, - uint32_t instanceCount, - uint32_t firstInstance, - VkBuffer counterBuffer, - VkDeviceSize counterBufferOffset, - uint32_t counterOffset, - uint32_t vertexStride); -#endif +typedef VkPhysicalDeviceTimelineSemaphoreFeatures VkPhysicalDeviceTimelineSemaphoreFeaturesKHR; +typedef VkPhysicalDeviceTimelineSemaphoreProperties VkPhysicalDeviceTimelineSemaphorePropertiesKHR; -#define VK_NVX_binary_import 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuModuleNVX) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuFunctionNVX) -#define VK_NVX_BINARY_IMPORT_SPEC_VERSION 1 -#define VK_NVX_BINARY_IMPORT_EXTENSION_NAME "VK_NVX_binary_import" -typedef struct VkCuModuleCreateInfoNVX { - VkStructureType sType; - const void* pNext; - size_t dataSize; - const void* pData; -} VkCuModuleCreateInfoNVX; +typedef VkSemaphoreTypeCreateInfo VkSemaphoreTypeCreateInfoKHR; -typedef struct VkCuFunctionCreateInfoNVX { - VkStructureType sType; - const void* pNext; - VkCuModuleNVX module; - const char* pName; -} VkCuFunctionCreateInfoNVX; +typedef VkTimelineSemaphoreSubmitInfo VkTimelineSemaphoreSubmitInfoKHR; -typedef struct VkCuLaunchInfoNVX { - VkStructureType sType; - const void* pNext; - VkCuFunctionNVX function; - uint32_t gridDimX; - uint32_t gridDimY; - uint32_t gridDimZ; - uint32_t blockDimX; - uint32_t blockDimY; - uint32_t blockDimZ; - uint32_t sharedMemBytes; - size_t paramCount; - const void* const * pParams; - size_t extraCount; - const void* const * pExtras; -} VkCuLaunchInfoNVX; +typedef VkSemaphoreWaitInfo VkSemaphoreWaitInfoKHR; -typedef VkResult (VKAPI_PTR *PFN_vkCreateCuModuleNVX)(VkDevice device, const VkCuModuleCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuModuleNVX* pModule); -typedef VkResult (VKAPI_PTR *PFN_vkCreateCuFunctionNVX)(VkDevice device, const VkCuFunctionCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuFunctionNVX* pFunction); -typedef void (VKAPI_PTR *PFN_vkDestroyCuModuleNVX)(VkDevice device, VkCuModuleNVX module, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkDestroyCuFunctionNVX)(VkDevice device, VkCuFunctionNVX function, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkCmdCuLaunchKernelNVX)(VkCommandBuffer commandBuffer, const VkCuLaunchInfoNVX* pLaunchInfo); +typedef VkSemaphoreSignalInfo VkSemaphoreSignalInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValueKHR)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); +typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphoresKHR)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphoreKHR)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuModuleNVX( +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValueKHR( VkDevice device, - const VkCuModuleCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkCuModuleNVX* pModule); + VkSemaphore semaphore, + uint64_t* pValue); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuFunctionNVX( +VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphoresKHR( VkDevice device, - const VkCuFunctionCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkCuFunctionNVX* pFunction); + const VkSemaphoreWaitInfo* pWaitInfo, + uint64_t timeout); -VKAPI_ATTR void VKAPI_CALL vkDestroyCuModuleNVX( +VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphoreKHR( VkDevice device, - VkCuModuleNVX module, - const VkAllocationCallbacks* pAllocator); + const VkSemaphoreSignalInfo* pSignalInfo); +#endif -VKAPI_ATTR void VKAPI_CALL vkDestroyCuFunctionNVX( - VkDevice device, - VkCuFunctionNVX function, - const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR void VKAPI_CALL vkCmdCuLaunchKernelNVX( - VkCommandBuffer commandBuffer, - const VkCuLaunchInfoNVX* pLaunchInfo); -#endif +// VK_KHR_vulkan_memory_model is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_vulkan_memory_model 1 +#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 3 +#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model" +typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryModelFeaturesKHR; -#define VK_NVX_image_view_handle 1 -#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 2 -#define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" -typedef struct VkImageViewHandleInfoNVX { - VkStructureType sType; - const void* pNext; - VkImageView imageView; - VkDescriptorType descriptorType; - VkSampler sampler; -} VkImageViewHandleInfoNVX; -typedef struct VkImageViewAddressPropertiesNVX { - VkStructureType sType; - void* pNext; - VkDeviceAddress deviceAddress; - VkDeviceSize size; -} VkImageViewAddressPropertiesNVX; +// VK_KHR_shader_terminate_invocation is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_terminate_invocation 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME "VK_KHR_shader_terminate_invocation" +typedef VkPhysicalDeviceShaderTerminateInvocationFeatures VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR; -typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewAddressNVX)(VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX( - VkDevice device, - const VkImageViewHandleInfoNVX* pInfo); -VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX( - VkDevice device, - VkImageView imageView, - VkImageViewAddressPropertiesNVX* pProperties); -#endif +// VK_KHR_fragment_shading_rate is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_fragment_shading_rate 1 +#define VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION 2 +#define VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME "VK_KHR_fragment_shading_rate" + +typedef enum VkFragmentShadingRateCombinerOpKHR { + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_ENUM_KHR = 0x7FFFFFFF +} VkFragmentShadingRateCombinerOpKHR; +typedef struct VkFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + const VkAttachmentReference2* pFragmentShadingRateAttachment; + VkExtent2D shadingRateAttachmentTexelSize; +} VkFragmentShadingRateAttachmentInfoKHR; +typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkExtent2D fragmentSize; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateStateCreateInfoKHR; -#define VK_AMD_draw_indirect_count 1 -#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 2 -#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef struct VkPhysicalDeviceFragmentShadingRateFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineFragmentShadingRate; + VkBool32 primitiveFragmentShadingRate; + VkBool32 attachmentFragmentShadingRate; +} VkPhysicalDeviceFragmentShadingRateFeaturesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRatePropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentShadingRateAttachmentTexelSize; + VkExtent2D maxFragmentShadingRateAttachmentTexelSize; + uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio; + VkBool32 primitiveFragmentShadingRateWithMultipleViewports; + VkBool32 layeredShadingRateAttachments; + VkBool32 fragmentShadingRateNonTrivialCombinerOps; + VkExtent2D maxFragmentSize; + uint32_t maxFragmentSizeAspectRatio; + uint32_t maxFragmentShadingRateCoverageSamples; + VkSampleCountFlagBits maxFragmentShadingRateRasterizationSamples; + VkBool32 fragmentShadingRateWithShaderDepthStencilWrites; + VkBool32 fragmentShadingRateWithSampleMask; + VkBool32 fragmentShadingRateWithShaderSampleMask; + VkBool32 fragmentShadingRateWithConservativeRasterization; + VkBool32 fragmentShadingRateWithFragmentShaderInterlock; + VkBool32 fragmentShadingRateWithCustomSampleLocations; + VkBool32 fragmentShadingRateStrictMultiplyCombiner; +} VkPhysicalDeviceFragmentShadingRatePropertiesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateKHR { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleCounts; + VkExtent2D fragmentSize; +} VkPhysicalDeviceFragmentShadingRateKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pFragmentShadingRateCount, VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateKHR)(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkBuffer countBuffer, - VkDeviceSize countBufferOffset, - uint32_t maxDrawCount, - uint32_t stride); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceFragmentShadingRatesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pFragmentShadingRateCount, + VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); -VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkBuffer countBuffer, - VkDeviceSize countBufferOffset, - uint32_t maxDrawCount, - uint32_t stride); + const VkExtent2D* pFragmentSize, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); #endif -#define VK_AMD_negative_viewport_height 1 -#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1 -#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height" - +// VK_KHR_spirv_1_4 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_spirv_1_4 1 +#define VK_KHR_SPIRV_1_4_SPEC_VERSION 1 +#define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4" -#define VK_AMD_gpu_shader_half_float 1 -#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 2 -#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float" +// VK_KHR_surface_protected_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_surface_protected_capabilities 1 +#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME "VK_KHR_surface_protected_capabilities" +typedef struct VkSurfaceProtectedCapabilitiesKHR { + VkStructureType sType; + const void* pNext; + VkBool32 supportsProtected; +} VkSurfaceProtectedCapabilitiesKHR; -#define VK_AMD_shader_ballot 1 -#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1 -#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot" -#define VK_AMD_texture_gather_bias_lod 1 -#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1 -#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod" -typedef struct VkTextureLODGatherFormatPropertiesAMD { - VkStructureType sType; - void* pNext; - VkBool32 supportsTextureGatherLODBiasAMD; -} VkTextureLODGatherFormatPropertiesAMD; +// VK_KHR_separate_depth_stencil_layouts is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_separate_depth_stencil_layouts 1 +#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION 1 +#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME "VK_KHR_separate_depth_stencil_layouts" +typedef VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR; +typedef VkAttachmentReferenceStencilLayout VkAttachmentReferenceStencilLayoutKHR; +typedef VkAttachmentDescriptionStencilLayout VkAttachmentDescriptionStencilLayoutKHR; -#define VK_AMD_shader_info 1 -#define VK_AMD_SHADER_INFO_SPEC_VERSION 1 -#define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info" -typedef enum VkShaderInfoTypeAMD { - VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0, - VK_SHADER_INFO_TYPE_BINARY_AMD = 1, - VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2, - VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF -} VkShaderInfoTypeAMD; -typedef struct VkShaderResourceUsageAMD { - uint32_t numUsedVgprs; - uint32_t numUsedSgprs; - uint32_t ldsSizePerLocalWorkGroup; - size_t ldsUsageSizeInBytes; - size_t scratchMemUsageInBytes; -} VkShaderResourceUsageAMD; -typedef struct VkShaderStatisticsInfoAMD { - VkShaderStageFlags shaderStageMask; - VkShaderResourceUsageAMD resourceUsage; - uint32_t numPhysicalVgprs; - uint32_t numPhysicalSgprs; - uint32_t numAvailableVgprs; - uint32_t numAvailableSgprs; - uint32_t computeWorkGroupSize[3]; -} VkShaderStatisticsInfoAMD; +// VK_KHR_present_wait is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_wait 1 +#define VK_KHR_PRESENT_WAIT_SPEC_VERSION 1 +#define VK_KHR_PRESENT_WAIT_EXTENSION_NAME "VK_KHR_present_wait" +typedef struct VkPhysicalDevicePresentWaitFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait; +} VkPhysicalDevicePresentWaitFeaturesKHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresentKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresentKHR( VkDevice device, - VkPipeline pipeline, - VkShaderStageFlagBits shaderStage, - VkShaderInfoTypeAMD infoType, - size_t* pInfoSize, - void* pInfo); + VkSwapchainKHR swapchain, + uint64_t presentId, + uint64_t timeout); #endif -#define VK_AMD_shader_image_load_store_lod 1 -#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1 -#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod" - - -#define VK_NV_corner_sampled_image 1 -#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2 -#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image" -typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV { - VkStructureType sType; - void* pNext; - VkBool32 cornerSampledImage; -} VkPhysicalDeviceCornerSampledImageFeaturesNV; +// VK_KHR_uniform_buffer_standard_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_uniform_buffer_standard_layout 1 +#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" +typedef VkPhysicalDeviceUniformBufferStandardLayoutFeatures VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR; -#define VK_IMG_format_pvrtc 1 -#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 -#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" +// VK_KHR_buffer_device_address is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_buffer_device_address 1 +#define VK_KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 1 +#define VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_KHR_buffer_device_address" +typedef VkPhysicalDeviceBufferDeviceAddressFeatures VkPhysicalDeviceBufferDeviceAddressFeaturesKHR; +typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoKHR; -#define VK_NV_external_memory_capabilities 1 -#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 -#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities" +typedef VkBufferOpaqueCaptureAddressCreateInfo VkBufferOpaqueCaptureAddressCreateInfoKHR; -typedef enum VkExternalMemoryHandleTypeFlagBitsNV { - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkExternalMemoryHandleTypeFlagBitsNV; -typedef VkFlags VkExternalMemoryHandleTypeFlagsNV; +typedef VkMemoryOpaqueCaptureAddressAllocateInfo VkMemoryOpaqueCaptureAddressAllocateInfoKHR; -typedef enum VkExternalMemoryFeatureFlagBitsNV { - VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001, - VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002, - VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004, - VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkExternalMemoryFeatureFlagBitsNV; -typedef VkFlags VkExternalMemoryFeatureFlagsNV; -typedef struct VkExternalImageFormatPropertiesNV { - VkImageFormatProperties imageFormatProperties; - VkExternalMemoryFeatureFlagsNV externalMemoryFeatures; - VkExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes; - VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes; -} VkExternalImageFormatPropertiesNV; +typedef VkDeviceMemoryOpaqueCaptureAddressInfo VkDeviceMemoryOpaqueCaptureAddressInfoKHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV( - VkPhysicalDevice physicalDevice, - VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags, - VkExternalMemoryHandleTypeFlagsNV externalHandleType, - VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); -#endif - - -#define VK_NV_external_memory 1 -#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1 -#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory" -typedef struct VkExternalMemoryImageCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagsNV handleTypes; -} VkExternalMemoryImageCreateInfoNV; +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressKHR( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); -typedef struct VkExportMemoryAllocateInfoNV { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagsNV handleTypes; -} VkExportMemoryAllocateInfoNV; +VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddressKHR( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( + VkDevice device, + const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +#endif -#define VK_EXT_validation_flags 1 -#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 2 -#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags" +// VK_KHR_deferred_host_operations is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_deferred_host_operations 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) +#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 4 +#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" +typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); +typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); +typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); -typedef enum VkValidationCheckEXT { - VK_VALIDATION_CHECK_ALL_EXT = 0, - VK_VALIDATION_CHECK_SHADERS_EXT = 1, - VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF -} VkValidationCheckEXT; -typedef struct VkValidationFlagsEXT { - VkStructureType sType; - const void* pNext; - uint32_t disabledValidationCheckCount; - const VkValidationCheckEXT* pDisabledValidationChecks; -} VkValidationFlagsEXT; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( + VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkDeferredOperationKHR* pDeferredOperation); +VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( + VkDevice device, + VkDeferredOperationKHR operation, + const VkAllocationCallbacks* pAllocator); +VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( + VkDevice device, + VkDeferredOperationKHR operation); -#define VK_EXT_shader_subgroup_ballot 1 -#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1 -#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot" +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( + VkDevice device, + VkDeferredOperationKHR operation); +VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif -#define VK_EXT_shader_subgroup_vote 1 -#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1 -#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote" +// VK_KHR_pipeline_executable_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_pipeline_executable_properties 1 +#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties" -#define VK_EXT_texture_compression_astc_hdr 1 -#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION 1 -#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME "VK_EXT_texture_compression_astc_hdr" -typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT { +typedef enum VkPipelineExecutableStatisticFormatKHR { + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR = 0, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR = 1, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR = 2, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR = 3, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPipelineExecutableStatisticFormatKHR; +typedef struct VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR { VkStructureType sType; void* pNext; - VkBool32 textureCompressionASTC_HDR; -} VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT; - - + VkBool32 pipelineExecutableInfo; +} VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR; -#define VK_EXT_astc_decode_mode 1 -#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1 -#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode" -typedef struct VkImageViewASTCDecodeModeEXT { +typedef struct VkPipelineInfoKHR { VkStructureType sType; const void* pNext; - VkFormat decodeMode; -} VkImageViewASTCDecodeModeEXT; - -typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 decodeModeSharedExponent; -} VkPhysicalDeviceASTCDecodeFeaturesEXT; + VkPipeline pipeline; +} VkPipelineInfoKHR; +typedef struct VkPipelineExecutablePropertiesKHR { + VkStructureType sType; + void* pNext; + VkShaderStageFlags stages; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + uint32_t subgroupSize; +} VkPipelineExecutablePropertiesKHR; +typedef struct VkPipelineExecutableInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipeline pipeline; + uint32_t executableIndex; +} VkPipelineExecutableInfoKHR; -#define VK_EXT_conditional_rendering 1 -#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 2 -#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering" +typedef union VkPipelineExecutableStatisticValueKHR { + VkBool32 b32; + int64_t i64; + uint64_t u64; + double f64; +} VkPipelineExecutableStatisticValueKHR; -typedef enum VkConditionalRenderingFlagBitsEXT { - VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001, - VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkConditionalRenderingFlagBitsEXT; -typedef VkFlags VkConditionalRenderingFlagsEXT; -typedef struct VkConditionalRenderingBeginInfoEXT { - VkStructureType sType; - const void* pNext; - VkBuffer buffer; - VkDeviceSize offset; - VkConditionalRenderingFlagsEXT flags; -} VkConditionalRenderingBeginInfoEXT; +typedef struct VkPipelineExecutableStatisticKHR { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkPipelineExecutableStatisticFormatKHR format; + VkPipelineExecutableStatisticValueKHR value; +} VkPipelineExecutableStatisticKHR; -typedef struct VkPhysicalDeviceConditionalRenderingFeaturesEXT { +typedef struct VkPipelineExecutableInternalRepresentationKHR { VkStructureType sType; void* pNext; - VkBool32 conditionalRendering; - VkBool32 inheritedConditionalRendering; -} VkPhysicalDeviceConditionalRenderingFeaturesEXT; - -typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 conditionalRenderingEnable; -} VkCommandBufferInheritanceConditionalRenderingInfoEXT; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkBool32 isText; + size_t dataSize; + void* pData; +} VkPipelineExecutableInternalRepresentationKHR; -typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); -typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutablePropertiesKHR)(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableStatisticsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableInternalRepresentationsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT( - VkCommandBuffer commandBuffer, - const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); - -VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( - VkCommandBuffer commandBuffer); -#endif +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutablePropertiesKHR( + VkDevice device, + const VkPipelineInfoKHR* pPipelineInfo, + uint32_t* pExecutableCount, + VkPipelineExecutablePropertiesKHR* pProperties); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableStatisticsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pStatisticCount, + VkPipelineExecutableStatisticKHR* pStatistics); -#define VK_NV_clip_space_w_scaling 1 -#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 -#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" -typedef struct VkViewportWScalingNV { - float xcoeff; - float ycoeff; -} VkViewportWScalingNV; - -typedef struct VkPipelineViewportWScalingStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 viewportWScalingEnable; - uint32_t viewportCount; - const VkViewportWScalingNV* pViewportWScalings; -} VkPipelineViewportWScalingStateCreateInfoNV; +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pInternalRepresentationCount, + VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); +#endif -typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( - VkCommandBuffer commandBuffer, - uint32_t firstViewport, - uint32_t viewportCount, - const VkViewportWScalingNV* pViewportWScalings); -#endif +// VK_KHR_map_memory2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_map_memory2 1 +#define VK_KHR_MAP_MEMORY_2_SPEC_VERSION 1 +#define VK_KHR_MAP_MEMORY_2_EXTENSION_NAME "VK_KHR_map_memory2" +typedef VkFlags VkMemoryUnmapFlagsKHR; +typedef struct VkMemoryMapInfoKHR { + VkStructureType sType; + const void* pNext; + VkMemoryMapFlags flags; + VkDeviceMemory memory; + VkDeviceSize offset; + VkDeviceSize size; +} VkMemoryMapInfoKHR; +typedef struct VkMemoryUnmapInfoKHR { + VkStructureType sType; + const void* pNext; + VkMemoryUnmapFlagsKHR flags; + VkDeviceMemory memory; +} VkMemoryUnmapInfoKHR; -#define VK_EXT_direct_mode_display 1 -#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1 -#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display" -typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkMapMemory2KHR)(VkDevice device, const VkMemoryMapInfoKHR* pMemoryMapInfo, void** ppData); +typedef VkResult (VKAPI_PTR *PFN_vkUnmapMemory2KHR)(VkDevice device, const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( - VkPhysicalDevice physicalDevice, - VkDisplayKHR display); +VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory2KHR( + VkDevice device, + const VkMemoryMapInfoKHR* pMemoryMapInfo, + void** ppData); + +VKAPI_ATTR VkResult VKAPI_CALL vkUnmapMemory2KHR( + VkDevice device, + const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo); #endif -#define VK_EXT_display_surface_counter 1 -#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1 -#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" +// VK_KHR_shader_integer_dot_product is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_integer_dot_product 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME "VK_KHR_shader_integer_dot_product" +typedef VkPhysicalDeviceShaderIntegerDotProductFeatures VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR; -typedef enum VkSurfaceCounterFlagBitsEXT { - VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0x00000001, - VK_SURFACE_COUNTER_VBLANK_EXT = VK_SURFACE_COUNTER_VBLANK_BIT_EXT, - VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkSurfaceCounterFlagBitsEXT; -typedef VkFlags VkSurfaceCounterFlagsEXT; -typedef struct VkSurfaceCapabilities2EXT { - VkStructureType sType; - void* pNext; - uint32_t minImageCount; - uint32_t maxImageCount; - VkExtent2D currentExtent; - VkExtent2D minImageExtent; - VkExtent2D maxImageExtent; - uint32_t maxImageArrayLayers; - VkSurfaceTransformFlagsKHR supportedTransforms; - VkSurfaceTransformFlagBitsKHR currentTransform; - VkCompositeAlphaFlagsKHR supportedCompositeAlpha; - VkImageUsageFlags supportedUsageFlags; - VkSurfaceCounterFlagsEXT supportedSurfaceCounters; -} VkSurfaceCapabilities2EXT; +typedef VkPhysicalDeviceShaderIntegerDotProductProperties VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( - VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - VkSurfaceCapabilities2EXT* pSurfaceCapabilities); -#endif +// VK_KHR_pipeline_library is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_pipeline_library 1 +#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" +typedef struct VkPipelineLibraryCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t libraryCount; + const VkPipeline* pLibraries; +} VkPipelineLibraryCreateInfoKHR; -#define VK_EXT_display_control 1 -#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1 -#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control" -typedef enum VkDisplayPowerStateEXT { - VK_DISPLAY_POWER_STATE_OFF_EXT = 0, - VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1, - VK_DISPLAY_POWER_STATE_ON_EXT = 2, - VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDisplayPowerStateEXT; -typedef enum VkDeviceEventTypeEXT { - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0, - VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDeviceEventTypeEXT; +// VK_KHR_shader_non_semantic_info is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_non_semantic_info 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" -typedef enum VkDisplayEventTypeEXT { - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0, - VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDisplayEventTypeEXT; -typedef struct VkDisplayPowerInfoEXT { - VkStructureType sType; - const void* pNext; - VkDisplayPowerStateEXT powerState; -} VkDisplayPowerInfoEXT; -typedef struct VkDeviceEventInfoEXT { - VkStructureType sType; - const void* pNext; - VkDeviceEventTypeEXT deviceEvent; -} VkDeviceEventInfoEXT; +// VK_KHR_present_id is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_id 1 +#define VK_KHR_PRESENT_ID_SPEC_VERSION 1 +#define VK_KHR_PRESENT_ID_EXTENSION_NAME "VK_KHR_present_id" +typedef struct VkPresentIdKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint64_t* pPresentIds; +} VkPresentIdKHR; -typedef struct VkDisplayEventInfoEXT { - VkStructureType sType; - const void* pNext; - VkDisplayEventTypeEXT displayEvent; -} VkDisplayEventInfoEXT; +typedef struct VkPhysicalDevicePresentIdFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId; +} VkPhysicalDevicePresentIdFeaturesKHR; -typedef struct VkSwapchainCounterCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkSurfaceCounterFlagsEXT surfaceCounters; -} VkSwapchainCounterCreateInfoEXT; -typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo); -typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); -typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); -typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT( - VkDevice device, - VkDisplayKHR display, - const VkDisplayPowerInfoEXT* pDisplayPowerInfo); +// VK_KHR_synchronization2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_synchronization2 1 +#define VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION 1 +#define VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME "VK_KHR_synchronization2" +typedef VkPipelineStageFlags2 VkPipelineStageFlags2KHR; -VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT( - VkDevice device, - const VkDeviceEventInfoEXT* pDeviceEventInfo, - const VkAllocationCallbacks* pAllocator, - VkFence* pFence); +typedef VkPipelineStageFlagBits2 VkPipelineStageFlagBits2KHR; -VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT( - VkDevice device, - VkDisplayKHR display, - const VkDisplayEventInfoEXT* pDisplayEventInfo, - const VkAllocationCallbacks* pAllocator, - VkFence* pFence); +typedef VkAccessFlags2 VkAccessFlags2KHR; -VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( - VkDevice device, - VkSwapchainKHR swapchain, - VkSurfaceCounterFlagBitsEXT counter, - uint64_t* pCounterValue); -#endif +typedef VkAccessFlagBits2 VkAccessFlagBits2KHR; +typedef VkSubmitFlagBits VkSubmitFlagBitsKHR; -#define VK_GOOGLE_display_timing 1 -#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1 -#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing" -typedef struct VkRefreshCycleDurationGOOGLE { - uint64_t refreshDuration; -} VkRefreshCycleDurationGOOGLE; +typedef VkSubmitFlags VkSubmitFlagsKHR; -typedef struct VkPastPresentationTimingGOOGLE { - uint32_t presentID; - uint64_t desiredPresentTime; - uint64_t actualPresentTime; - uint64_t earliestPresentTime; - uint64_t presentMargin; -} VkPastPresentationTimingGOOGLE; +typedef VkMemoryBarrier2 VkMemoryBarrier2KHR; -typedef struct VkPresentTimeGOOGLE { - uint32_t presentID; - uint64_t desiredPresentTime; -} VkPresentTimeGOOGLE; +typedef VkBufferMemoryBarrier2 VkBufferMemoryBarrier2KHR; -typedef struct VkPresentTimesInfoGOOGLE { - VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const VkPresentTimeGOOGLE* pTimes; -} VkPresentTimesInfoGOOGLE; +typedef VkImageMemoryBarrier2 VkImageMemoryBarrier2KHR; -typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); +typedef VkDependencyInfo VkDependencyInfoKHR; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE( - VkDevice device, - VkSwapchainKHR swapchain, - VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); +typedef VkSubmitInfo2 VkSubmitInfo2KHR; -VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( - VkDevice device, - VkSwapchainKHR swapchain, - uint32_t* pPresentationTimingCount, - VkPastPresentationTimingGOOGLE* pPresentationTimings); -#endif +typedef VkSemaphoreSubmitInfo VkSemaphoreSubmitInfoKHR; +typedef VkCommandBufferSubmitInfo VkCommandBufferSubmitInfoKHR; -#define VK_NV_sample_mask_override_coverage 1 -#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1 -#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage" +typedef VkPhysicalDeviceSynchronization2Features VkPhysicalDeviceSynchronization2FeaturesKHR; +typedef struct VkQueueFamilyCheckpointProperties2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2 checkpointExecutionStageMask; +} VkQueueFamilyCheckpointProperties2NV; -#define VK_NV_geometry_shader_passthrough 1 -#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1 -#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough" +typedef struct VkCheckpointData2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2 stage; + void* pCheckpointMarker; +} VkCheckpointData2NV; +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2KHR)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2KHR)(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2KHR)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarker2AMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointData2NV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); -#define VK_NV_viewport_array2 1 -#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1 -#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2" +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfo* pDependencyInfo); +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2 stageMask); -#define VK_NVX_multiview_per_view_attributes 1 -#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1 -#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes" -typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { - VkStructureType sType; - void* pNext; - VkBool32 perViewPositionAllComponents; -} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX; +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2KHR( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfo* pDependencyInfos); +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2KHR( + VkCommandBuffer commandBuffer, + const VkDependencyInfo* pDependencyInfo); +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2KHR( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkQueryPool queryPool, + uint32_t query); -#define VK_NV_viewport_swizzle 1 -#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1 -#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle" +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2KHR( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2* pSubmits, + VkFence fence); -typedef enum VkViewportCoordinateSwizzleNV { - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0, - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1, - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2, - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3, - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4, - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5, - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6, - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7, - VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF -} VkViewportCoordinateSwizzleNV; -typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV; -typedef struct VkViewportSwizzleNV { - VkViewportCoordinateSwizzleNV x; - VkViewportCoordinateSwizzleNV y; - VkViewportCoordinateSwizzleNV z; - VkViewportCoordinateSwizzleNV w; -} VkViewportSwizzleNV; +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); -typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineViewportSwizzleStateCreateFlagsNV flags; - uint32_t viewportCount; - const VkViewportSwizzleNV* pViewportSwizzles; -} VkPipelineViewportSwizzleStateCreateInfoNV; +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointData2NV* pCheckpointData); +#endif +// VK_KHR_fragment_shader_barycentric is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_fragment_shader_barycentric 1 +#define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 +#define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_KHR_fragment_shader_barycentric" +typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderBarycentric; +} VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR; -#define VK_EXT_discard_rectangles 1 -#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1 -#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" +typedef struct VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 triStripVertexOrderIndependentOfProvokingVertex; +} VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR; -typedef enum VkDiscardRectangleModeEXT { - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0, - VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1, - VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDiscardRectangleModeEXT; -typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT; -typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT { + + +// VK_KHR_shader_subgroup_uniform_control_flow is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_subgroup_uniform_control_flow 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME "VK_KHR_shader_subgroup_uniform_control_flow" +typedef struct VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR { VkStructureType sType; void* pNext; - uint32_t maxDiscardRectangles; -} VkPhysicalDeviceDiscardRectanglePropertiesEXT; + VkBool32 shaderSubgroupUniformControlFlow; +} VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR; -typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkPipelineDiscardRectangleStateCreateFlagsEXT flags; - VkDiscardRectangleModeEXT discardRectangleMode; - uint32_t discardRectangleCount; - const VkRect2D* pDiscardRectangles; -} VkPipelineDiscardRectangleStateCreateInfoEXT; -typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( - VkCommandBuffer commandBuffer, - uint32_t firstDiscardRectangle, - uint32_t discardRectangleCount, - const VkRect2D* pDiscardRectangles); -#endif +// VK_KHR_zero_initialize_workgroup_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_zero_initialize_workgroup_memory 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME "VK_KHR_zero_initialize_workgroup_memory" +typedef VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR; -#define VK_EXT_conservative_rasterization 1 -#define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1 -#define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization" -typedef enum VkConservativeRasterizationModeEXT { - VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0, - VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1, - VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2, - VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkConservativeRasterizationModeEXT; -typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT; -typedef struct VkPhysicalDeviceConservativeRasterizationPropertiesEXT { +// VK_KHR_workgroup_memory_explicit_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_workgroup_memory_explicit_layout 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME "VK_KHR_workgroup_memory_explicit_layout" +typedef struct VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR { VkStructureType sType; void* pNext; - float primitiveOverestimationSize; - float maxExtraPrimitiveOverestimationSize; - float extraPrimitiveOverestimationSizeGranularity; - VkBool32 primitiveUnderestimation; - VkBool32 conservativePointAndLineRasterization; - VkBool32 degenerateTrianglesRasterized; - VkBool32 degenerateLinesRasterized; - VkBool32 fullyCoveredFragmentShaderInputVariable; - VkBool32 conservativeRasterizationPostDepthCoverage; -} VkPhysicalDeviceConservativeRasterizationPropertiesEXT; + VkBool32 workgroupMemoryExplicitLayout; + VkBool32 workgroupMemoryExplicitLayoutScalarBlockLayout; + VkBool32 workgroupMemoryExplicitLayout8BitAccess; + VkBool32 workgroupMemoryExplicitLayout16BitAccess; +} VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR; -typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkPipelineRasterizationConservativeStateCreateFlagsEXT flags; - VkConservativeRasterizationModeEXT conservativeRasterizationMode; - float extraPrimitiveOverestimationSize; -} VkPipelineRasterizationConservativeStateCreateInfoEXT; +// VK_KHR_copy_commands2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_copy_commands2 1 +#define VK_KHR_COPY_COMMANDS_2_SPEC_VERSION 1 +#define VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME "VK_KHR_copy_commands2" +typedef VkCopyBufferInfo2 VkCopyBufferInfo2KHR; -#define VK_EXT_depth_clip_enable 1 -#define VK_EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION 1 -#define VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME "VK_EXT_depth_clip_enable" -typedef VkFlags VkPipelineRasterizationDepthClipStateCreateFlagsEXT; -typedef struct VkPhysicalDeviceDepthClipEnableFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 depthClipEnable; -} VkPhysicalDeviceDepthClipEnableFeaturesEXT; +typedef VkCopyImageInfo2 VkCopyImageInfo2KHR; -typedef struct VkPipelineRasterizationDepthClipStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkPipelineRasterizationDepthClipStateCreateFlagsEXT flags; - VkBool32 depthClipEnable; -} VkPipelineRasterizationDepthClipStateCreateInfoEXT; +typedef VkCopyBufferToImageInfo2 VkCopyBufferToImageInfo2KHR; +typedef VkCopyImageToBufferInfo2 VkCopyImageToBufferInfo2KHR; +typedef VkBlitImageInfo2 VkBlitImageInfo2KHR; -#define VK_EXT_swapchain_colorspace 1 -#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 4 -#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" +typedef VkResolveImageInfo2 VkResolveImageInfo2KHR; +typedef VkBufferCopy2 VkBufferCopy2KHR; -#define VK_EXT_hdr_metadata 1 -#define VK_EXT_HDR_METADATA_SPEC_VERSION 2 -#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" -typedef struct VkXYColorEXT { - float x; - float y; -} VkXYColorEXT; +typedef VkImageCopy2 VkImageCopy2KHR; -typedef struct VkHdrMetadataEXT { - VkStructureType sType; - const void* pNext; - VkXYColorEXT displayPrimaryRed; - VkXYColorEXT displayPrimaryGreen; - VkXYColorEXT displayPrimaryBlue; - VkXYColorEXT whitePoint; - float maxLuminance; - float minLuminance; - float maxContentLightLevel; - float maxFrameAverageLightLevel; -} VkHdrMetadataEXT; +typedef VkImageBlit2 VkImageBlit2KHR; -typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); +typedef VkBufferImageCopy2 VkBufferImageCopy2KHR; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( - VkDevice device, - uint32_t swapchainCount, - const VkSwapchainKHR* pSwapchains, - const VkHdrMetadataEXT* pMetadata); -#endif +typedef VkImageResolve2 VkImageResolve2KHR; +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2KHR)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2KHR)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); -#define VK_EXT_external_memory_dma_buf 1 -#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1 -#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf" +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2* pCopyBufferInfo); +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2* pCopyImageInfo); -#define VK_EXT_queue_family_foreign 1 -#define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1 -#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign" -#define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U) +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); -#define VK_EXT_debug_utils 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT) -#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 2 -#define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils" -typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT; +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2KHR( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2* pBlitImageInfo); -typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { - VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001, - VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010, - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100, - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000, - VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDebugUtilsMessageSeverityFlagBitsEXT; +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2* pResolveImageInfo); +#endif -typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { - VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001, - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002, - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004, - VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDebugUtilsMessageTypeFlagBitsEXT; -typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT; -typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; -typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; -typedef struct VkDebugUtilsLabelEXT { - VkStructureType sType; - const void* pNext; - const char* pLabelName; - float color[4]; -} VkDebugUtilsLabelEXT; -typedef struct VkDebugUtilsObjectNameInfoEXT { - VkStructureType sType; - const void* pNext; - VkObjectType objectType; - uint64_t objectHandle; - const char* pObjectName; -} VkDebugUtilsObjectNameInfoEXT; +// VK_KHR_format_feature_flags2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_format_feature_flags2 1 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION 2 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME "VK_KHR_format_feature_flags2" +typedef VkFormatFeatureFlags2 VkFormatFeatureFlags2KHR; -typedef struct VkDebugUtilsMessengerCallbackDataEXT { - VkStructureType sType; - const void* pNext; - VkDebugUtilsMessengerCallbackDataFlagsEXT flags; - const char* pMessageIdName; - int32_t messageIdNumber; - const char* pMessage; - uint32_t queueLabelCount; - const VkDebugUtilsLabelEXT* pQueueLabels; - uint32_t cmdBufLabelCount; - const VkDebugUtilsLabelEXT* pCmdBufLabels; - uint32_t objectCount; - const VkDebugUtilsObjectNameInfoEXT* pObjects; -} VkDebugUtilsMessengerCallbackDataEXT; +typedef VkFormatFeatureFlagBits2 VkFormatFeatureFlagBits2KHR; -typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)( - VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageTypes, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData); +typedef VkFormatProperties3 VkFormatProperties3KHR; -typedef struct VkDebugUtilsMessengerCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkDebugUtilsMessengerCreateFlagsEXT flags; - VkDebugUtilsMessageSeverityFlagsEXT messageSeverity; - VkDebugUtilsMessageTypeFlagsEXT messageType; - PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback; - void* pUserData; -} VkDebugUtilsMessengerCreateInfoEXT; -typedef struct VkDebugUtilsObjectTagInfoEXT { + +// VK_KHR_ray_tracing_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_ray_tracing_maintenance1 1 +#define VK_KHR_RAY_TRACING_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_ray_tracing_maintenance1" +typedef struct VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR { VkStructureType sType; - const void* pNext; - VkObjectType objectType; - uint64_t objectHandle; - uint64_t tagName; - size_t tagSize; - const void* pTag; -} VkDebugUtilsObjectTagInfoEXT; - -typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo); -typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo); -typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); -typedef void (VKAPI_PTR *PFN_vkQueueEndDebugUtilsLabelEXT)(VkQueue queue); -typedef void (VKAPI_PTR *PFN_vkQueueInsertDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); -typedef void (VKAPI_PTR *PFN_vkCmdBeginDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); -typedef void (VKAPI_PTR *PFN_vkCmdEndDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer); -typedef void (VKAPI_PTR *PFN_vkCmdInsertDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugUtilsMessengerEXT)(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger); -typedef void (VKAPI_PTR *PFN_vkDestroyDebugUtilsMessengerEXT)(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkSubmitDebugUtilsMessageEXT)(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); + void* pNext; + VkBool32 rayTracingMaintenance1; + VkBool32 rayTracingPipelineTraceRaysIndirect2; +} VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR; + +typedef struct VkTraceRaysIndirectCommand2KHR { + VkDeviceAddress raygenShaderRecordAddress; + VkDeviceSize raygenShaderRecordSize; + VkDeviceAddress missShaderBindingTableAddress; + VkDeviceSize missShaderBindingTableSize; + VkDeviceSize missShaderBindingTableStride; + VkDeviceAddress hitShaderBindingTableAddress; + VkDeviceSize hitShaderBindingTableSize; + VkDeviceSize hitShaderBindingTableStride; + VkDeviceAddress callableShaderBindingTableAddress; + VkDeviceSize callableShaderBindingTableSize; + VkDeviceSize callableShaderBindingTableStride; + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommand2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirect2KHR)(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectNameEXT( - VkDevice device, - const VkDebugUtilsObjectNameInfoEXT* pNameInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectTagEXT( - VkDevice device, - const VkDebugUtilsObjectTagInfoEXT* pTagInfo); - -VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT( - VkQueue queue, - const VkDebugUtilsLabelEXT* pLabelInfo); - -VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT( - VkQueue queue); - -VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT( - VkQueue queue, - const VkDebugUtilsLabelEXT* pLabelInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdBeginDebugUtilsLabelEXT( +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirect2KHR( VkCommandBuffer commandBuffer, - const VkDebugUtilsLabelEXT* pLabelInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdEndDebugUtilsLabelEXT( - VkCommandBuffer commandBuffer); - -VKAPI_ATTR void VKAPI_CALL vkCmdInsertDebugUtilsLabelEXT( - VkCommandBuffer commandBuffer, - const VkDebugUtilsLabelEXT* pLabelInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( - VkInstance instance, - const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDebugUtilsMessengerEXT* pMessenger); - -VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( - VkInstance instance, - VkDebugUtilsMessengerEXT messenger, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT( - VkInstance instance, - VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageTypes, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); + VkDeviceAddress indirectDeviceAddress); #endif -#define VK_EXT_sampler_filter_minmax 1 -#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 2 -#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax" -typedef VkSamplerReductionMode VkSamplerReductionModeEXT; +// VK_KHR_portability_enumeration is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_portability_enumeration 1 +#define VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION 1 +#define VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME "VK_KHR_portability_enumeration" -typedef VkSamplerReductionModeCreateInfo VkSamplerReductionModeCreateInfoEXT; -typedef VkPhysicalDeviceSamplerFilterMinmaxProperties VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT; +// VK_KHR_maintenance4 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance4 1 +#define VK_KHR_MAINTENANCE_4_SPEC_VERSION 2 +#define VK_KHR_MAINTENANCE_4_EXTENSION_NAME "VK_KHR_maintenance4" +typedef VkPhysicalDeviceMaintenance4Features VkPhysicalDeviceMaintenance4FeaturesKHR; +typedef VkPhysicalDeviceMaintenance4Properties VkPhysicalDeviceMaintenance4PropertiesKHR; +typedef VkDeviceBufferMemoryRequirements VkDeviceBufferMemoryRequirementsKHR; -#define VK_AMD_gpu_shader_int16 1 -#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 2 -#define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" +typedef VkDeviceImageMemoryRequirements VkDeviceImageMemoryRequirementsKHR; +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirementsKHR)(VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); -#define VK_AMD_mixed_attachment_samples 1 -#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1 -#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples" +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirementsKHR( + VkDevice device, + const VkDeviceBufferMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); -#define VK_AMD_shader_fragment_mask 1 -#define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1 -#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask" +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif -#define VK_EXT_inline_uniform_block 1 -#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1 -#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block" -typedef struct VkPhysicalDeviceInlineUniformBlockFeaturesEXT { +// VK_KHR_maintenance5 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance5 1 +#define VK_KHR_MAINTENANCE_5_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_5_EXTENSION_NAME "VK_KHR_maintenance5" +typedef VkFlags64 VkPipelineCreateFlags2KHR; + +// Flag bits for VkPipelineCreateFlagBits2KHR +typedef VkFlags64 VkPipelineCreateFlagBits2KHR; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR = 0x00000001ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT_KHR = 0x00000002ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DERIVATIVE_BIT_KHR = 0x00000004ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT_KHR = 0x00000010ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DEFER_COMPILE_BIT_NV = 0x00000020ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_CAPTURE_STATISTICS_BIT_KHR = 0x00000040ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR = 0x00000100ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR = 0x00000200ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT = 0x00000400ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT = 0x00800000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR = 0x00000800ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0x00080000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_NV = 0x00040000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT_EXT = 0x08000000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT = 0x40000000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000ULL; +static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT = 0x20000000ULL; + +typedef VkFlags64 VkBufferUsageFlags2KHR; + +// Flag bits for VkBufferUsageFlagBits2KHR +typedef VkFlags64 VkBufferUsageFlagBits2KHR; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR = 0x00000001ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR = 0x00000002ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000004ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR = 0x00000010ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR = 0x00000020ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR = 0x00000040ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR = 0x00000080ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR = 0x00000100ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_RAY_TRACING_BIT_NV = 0x00000400ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR = 0x00004000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000ULL; +#endif +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR = 0x00020000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0x00200000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00400000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0x04000000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0x00800000ULL; +static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT = 0x01000000ULL; + +typedef struct VkPhysicalDeviceMaintenance5FeaturesKHR { VkStructureType sType; void* pNext; - VkBool32 inlineUniformBlock; - VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; -} VkPhysicalDeviceInlineUniformBlockFeaturesEXT; + VkBool32 maintenance5; +} VkPhysicalDeviceMaintenance5FeaturesKHR; -typedef struct VkPhysicalDeviceInlineUniformBlockPropertiesEXT { +typedef struct VkPhysicalDeviceMaintenance5PropertiesKHR { VkStructureType sType; void* pNext; - uint32_t maxInlineUniformBlockSize; - uint32_t maxPerStageDescriptorInlineUniformBlocks; - uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; - uint32_t maxDescriptorSetInlineUniformBlocks; - uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; -} VkPhysicalDeviceInlineUniformBlockPropertiesEXT; - -typedef struct VkWriteDescriptorSetInlineUniformBlockEXT { - VkStructureType sType; - const void* pNext; - uint32_t dataSize; - const void* pData; -} VkWriteDescriptorSetInlineUniformBlockEXT; - -typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT { + VkBool32 earlyFragmentMultisampleCoverageAfterSampleCounting; + VkBool32 earlyFragmentSampleMaskTestBeforeSampleCounting; + VkBool32 depthStencilSwizzleOneSupport; + VkBool32 polygonModePointSize; + VkBool32 nonStrictSinglePixelWideLinesUseParallelogram; + VkBool32 nonStrictWideLinesUseParallelogram; +} VkPhysicalDeviceMaintenance5PropertiesKHR; + +typedef struct VkRenderingAreaInfoKHR { VkStructureType sType; const void* pNext; - uint32_t maxInlineUniformBlockBindings; -} VkDescriptorPoolInlineUniformBlockCreateInfoEXT; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkRenderingAreaInfoKHR; + +typedef struct VkImageSubresource2KHR { + VkStructureType sType; + void* pNext; + VkImageSubresource imageSubresource; +} VkImageSubresource2KHR; +typedef struct VkDeviceImageSubresourceInfoKHR { + VkStructureType sType; + const void* pNext; + const VkImageCreateInfo* pCreateInfo; + const VkImageSubresource2KHR* pSubresource; +} VkDeviceImageSubresourceInfoKHR; +typedef struct VkSubresourceLayout2KHR { + VkStructureType sType; + void* pNext; + VkSubresourceLayout subresourceLayout; +} VkSubresourceLayout2KHR; -#define VK_EXT_shader_stencil_export 1 -#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1 -#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export" +typedef struct VkPipelineCreateFlags2CreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags2KHR flags; +} VkPipelineCreateFlags2CreateInfoKHR; +typedef struct VkBufferUsageFlags2CreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkBufferUsageFlags2KHR usage; +} VkBufferUsageFlags2CreateInfoKHR; -#define VK_EXT_sample_locations 1 -#define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1 -#define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations" -typedef struct VkSampleLocationEXT { - float x; - float y; -} VkSampleLocationEXT; +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer2KHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType); +typedef void (VKAPI_PTR *PFN_vkGetRenderingAreaGranularityKHR)(VkDevice device, const VkRenderingAreaInfoKHR* pRenderingAreaInfo, VkExtent2D* pGranularity); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSubresourceLayoutKHR)(VkDevice device, const VkDeviceImageSubresourceInfoKHR* pInfo, VkSubresourceLayout2KHR* pLayout); +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2KHR)(VkDevice device, VkImage image, const VkImageSubresource2KHR* pSubresource, VkSubresourceLayout2KHR* pLayout); -typedef struct VkSampleLocationsInfoEXT { - VkStructureType sType; - const void* pNext; - VkSampleCountFlagBits sampleLocationsPerPixel; - VkExtent2D sampleLocationGridSize; - uint32_t sampleLocationsCount; - const VkSampleLocationEXT* pSampleLocations; -} VkSampleLocationsInfoEXT; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer2KHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkIndexType indexType); -typedef struct VkAttachmentSampleLocationsEXT { - uint32_t attachmentIndex; - VkSampleLocationsInfoEXT sampleLocationsInfo; -} VkAttachmentSampleLocationsEXT; +VKAPI_ATTR void VKAPI_CALL vkGetRenderingAreaGranularityKHR( + VkDevice device, + const VkRenderingAreaInfoKHR* pRenderingAreaInfo, + VkExtent2D* pGranularity); -typedef struct VkSubpassSampleLocationsEXT { - uint32_t subpassIndex; - VkSampleLocationsInfoEXT sampleLocationsInfo; -} VkSubpassSampleLocationsEXT; +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSubresourceLayoutKHR( + VkDevice device, + const VkDeviceImageSubresourceInfoKHR* pInfo, + VkSubresourceLayout2KHR* pLayout); -typedef struct VkRenderPassSampleLocationsBeginInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t attachmentInitialSampleLocationsCount; - const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations; - uint32_t postSubpassSampleLocationsCount; - const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations; -} VkRenderPassSampleLocationsBeginInfoEXT; +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2KHR( + VkDevice device, + VkImage image, + const VkImageSubresource2KHR* pSubresource, + VkSubresourceLayout2KHR* pLayout); +#endif -typedef struct VkPipelineSampleLocationsStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 sampleLocationsEnable; - VkSampleLocationsInfoEXT sampleLocationsInfo; -} VkPipelineSampleLocationsStateCreateInfoEXT; -typedef struct VkPhysicalDeviceSampleLocationsPropertiesEXT { +// VK_KHR_ray_tracing_position_fetch is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_ray_tracing_position_fetch 1 +#define VK_KHR_RAY_TRACING_POSITION_FETCH_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_POSITION_FETCH_EXTENSION_NAME "VK_KHR_ray_tracing_position_fetch" +typedef struct VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingPositionFetch; +} VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR; + + + +// VK_KHR_cooperative_matrix is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_cooperative_matrix 1 +#define VK_KHR_COOPERATIVE_MATRIX_SPEC_VERSION 2 +#define VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_KHR_cooperative_matrix" + +typedef enum VkComponentTypeKHR { + VK_COMPONENT_TYPE_FLOAT16_KHR = 0, + VK_COMPONENT_TYPE_FLOAT32_KHR = 1, + VK_COMPONENT_TYPE_FLOAT64_KHR = 2, + VK_COMPONENT_TYPE_SINT8_KHR = 3, + VK_COMPONENT_TYPE_SINT16_KHR = 4, + VK_COMPONENT_TYPE_SINT32_KHR = 5, + VK_COMPONENT_TYPE_SINT64_KHR = 6, + VK_COMPONENT_TYPE_UINT8_KHR = 7, + VK_COMPONENT_TYPE_UINT16_KHR = 8, + VK_COMPONENT_TYPE_UINT32_KHR = 9, + VK_COMPONENT_TYPE_UINT64_KHR = 10, + VK_COMPONENT_TYPE_FLOAT16_NV = VK_COMPONENT_TYPE_FLOAT16_KHR, + VK_COMPONENT_TYPE_FLOAT32_NV = VK_COMPONENT_TYPE_FLOAT32_KHR, + VK_COMPONENT_TYPE_FLOAT64_NV = VK_COMPONENT_TYPE_FLOAT64_KHR, + VK_COMPONENT_TYPE_SINT8_NV = VK_COMPONENT_TYPE_SINT8_KHR, + VK_COMPONENT_TYPE_SINT16_NV = VK_COMPONENT_TYPE_SINT16_KHR, + VK_COMPONENT_TYPE_SINT32_NV = VK_COMPONENT_TYPE_SINT32_KHR, + VK_COMPONENT_TYPE_SINT64_NV = VK_COMPONENT_TYPE_SINT64_KHR, + VK_COMPONENT_TYPE_UINT8_NV = VK_COMPONENT_TYPE_UINT8_KHR, + VK_COMPONENT_TYPE_UINT16_NV = VK_COMPONENT_TYPE_UINT16_KHR, + VK_COMPONENT_TYPE_UINT32_NV = VK_COMPONENT_TYPE_UINT32_KHR, + VK_COMPONENT_TYPE_UINT64_NV = VK_COMPONENT_TYPE_UINT64_KHR, + VK_COMPONENT_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkComponentTypeKHR; + +typedef enum VkScopeKHR { + VK_SCOPE_DEVICE_KHR = 1, + VK_SCOPE_WORKGROUP_KHR = 2, + VK_SCOPE_SUBGROUP_KHR = 3, + VK_SCOPE_QUEUE_FAMILY_KHR = 5, + VK_SCOPE_DEVICE_NV = VK_SCOPE_DEVICE_KHR, + VK_SCOPE_WORKGROUP_NV = VK_SCOPE_WORKGROUP_KHR, + VK_SCOPE_SUBGROUP_NV = VK_SCOPE_SUBGROUP_KHR, + VK_SCOPE_QUEUE_FAMILY_NV = VK_SCOPE_QUEUE_FAMILY_KHR, + VK_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkScopeKHR; +typedef struct VkCooperativeMatrixPropertiesKHR { VkStructureType sType; void* pNext; - VkSampleCountFlags sampleLocationSampleCounts; - VkExtent2D maxSampleLocationGridSize; - float sampleLocationCoordinateRange[2]; - uint32_t sampleLocationSubPixelBits; - VkBool32 variableSampleLocations; -} VkPhysicalDeviceSampleLocationsPropertiesEXT; - -typedef struct VkMultisamplePropertiesEXT { + uint32_t MSize; + uint32_t NSize; + uint32_t KSize; + VkComponentTypeKHR AType; + VkComponentTypeKHR BType; + VkComponentTypeKHR CType; + VkComponentTypeKHR ResultType; + VkBool32 saturatingAccumulation; + VkScopeKHR scope; +} VkCooperativeMatrixPropertiesKHR; + +typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesKHR { VkStructureType sType; void* pNext; - VkExtent2D maxSampleLocationGridSize; -} VkMultisamplePropertiesEXT; + VkBool32 cooperativeMatrix; + VkBool32 cooperativeMatrixRobustBufferAccess; +} VkPhysicalDeviceCooperativeMatrixFeaturesKHR; -typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); +typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesKHR { + VkStructureType sType; + void* pNext; + VkShaderStageFlags cooperativeMatrixSupportedStages; +} VkPhysicalDeviceCooperativeMatrixPropertiesKHR; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT( - VkCommandBuffer commandBuffer, - const VkSampleLocationsInfoEXT* pSampleLocationsInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesKHR* pProperties); -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR( VkPhysicalDevice physicalDevice, - VkSampleCountFlagBits samples, - VkMultisamplePropertiesEXT* pMultisampleProperties); + uint32_t* pPropertyCount, + VkCooperativeMatrixPropertiesKHR* pProperties); #endif -#define VK_EXT_blend_operation_advanced 1 -#define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2 -#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced" +// VK_EXT_debug_report is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_debug_report 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) +#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 +#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" -typedef enum VkBlendOverlapEXT { - VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0, - VK_BLEND_OVERLAP_DISJOINT_EXT = 1, - VK_BLEND_OVERLAP_CONJOINT_EXT = 2, - VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF -} VkBlendOverlapEXT; -typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 advancedBlendCoherentOperations; -} VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT; +typedef enum VkDebugReportObjectTypeEXT { + VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0, + VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1, + VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2, + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3, + VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4, + VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5, + VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6, + VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7, + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9, + VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10, + VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11, + VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13, + VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14, + VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17, + VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23, + VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24, + VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25, + VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26, + VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27, + VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28, + VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29, + VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30, + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, + VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT = 1000029000, + VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT = 1000029001, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000, + VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_MODULE_NV = 1000307000, + VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_FUNCTION_NV = 1000307001, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT = 1000366000, + VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugReportObjectTypeEXT; -typedef struct VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT { - VkStructureType sType; - void* pNext; - uint32_t advancedBlendMaxColorAttachments; - VkBool32 advancedBlendIndependentBlend; - VkBool32 advancedBlendNonPremultipliedSrcColor; - VkBool32 advancedBlendNonPremultipliedDstColor; - VkBool32 advancedBlendCorrelatedOverlap; - VkBool32 advancedBlendAllOperations; -} VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT; - -typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 srcPremultiplied; - VkBool32 dstPremultiplied; - VkBlendOverlapEXT blendOverlap; -} VkPipelineColorBlendAdvancedStateCreateInfoEXT; +typedef enum VkDebugReportFlagBitsEXT { + VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001, + VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002, + VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004, + VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008, + VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010, + VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugReportFlagBitsEXT; +typedef VkFlags VkDebugReportFlagsEXT; +typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* pUserData); +typedef struct VkDebugReportCallbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportFlagsEXT flags; + PFN_vkDebugReportCallbackEXT pfnCallback; + void* pUserData; +} VkDebugReportCallbackCreateInfoEXT; +typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); +typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); -#define VK_NV_fragment_coverage_to_color 1 -#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1 -#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color" -typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV; -typedef struct VkPipelineCoverageToColorStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineCoverageToColorStateCreateFlagsNV flags; - VkBool32 coverageToColorEnable; - uint32_t coverageToColorLocation; -} VkPipelineCoverageToColorStateCreateInfoNV; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( + VkInstance instance, + const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugReportCallbackEXT* pCallback); +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT( + VkInstance instance, + VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks* pAllocator); +VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( + VkInstance instance, + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage); +#endif -#define VK_NV_framebuffer_mixed_samples 1 -#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1 -#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples" -typedef enum VkCoverageModulationModeNV { - VK_COVERAGE_MODULATION_MODE_NONE_NV = 0, - VK_COVERAGE_MODULATION_MODE_RGB_NV = 1, - VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2, - VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3, - VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF -} VkCoverageModulationModeNV; -typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV; -typedef struct VkPipelineCoverageModulationStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineCoverageModulationStateCreateFlagsNV flags; - VkCoverageModulationModeNV coverageModulationMode; - VkBool32 coverageModulationTableEnable; - uint32_t coverageModulationTableCount; - const float* pCoverageModulationTable; -} VkPipelineCoverageModulationStateCreateInfoNV; +// VK_NV_glsl_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_glsl_shader 1 +#define VK_NV_GLSL_SHADER_SPEC_VERSION 1 +#define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader" +// VK_EXT_depth_range_unrestricted is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_range_unrestricted 1 +#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1 +#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted" -#define VK_NV_fill_rectangle 1 -#define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1 -#define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle" +// VK_IMG_filter_cubic is a preprocessor guard. Do not pass it to API calls. +#define VK_IMG_filter_cubic 1 +#define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1 +#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic" -#define VK_NV_shader_sm_builtins 1 -#define VK_NV_SHADER_SM_BUILTINS_SPEC_VERSION 1 -#define VK_NV_SHADER_SM_BUILTINS_EXTENSION_NAME "VK_NV_shader_sm_builtins" -typedef struct VkPhysicalDeviceShaderSMBuiltinsPropertiesNV { - VkStructureType sType; - void* pNext; - uint32_t shaderSMCount; - uint32_t shaderWarpsPerSM; -} VkPhysicalDeviceShaderSMBuiltinsPropertiesNV; -typedef struct VkPhysicalDeviceShaderSMBuiltinsFeaturesNV { - VkStructureType sType; - void* pNext; - VkBool32 shaderSMBuiltins; -} VkPhysicalDeviceShaderSMBuiltinsFeaturesNV; +// VK_AMD_rasterization_order is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_rasterization_order 1 +#define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1 +#define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order" +typedef enum VkRasterizationOrderAMD { + VK_RASTERIZATION_ORDER_STRICT_AMD = 0, + VK_RASTERIZATION_ORDER_RELAXED_AMD = 1, + VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF +} VkRasterizationOrderAMD; +typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { + VkStructureType sType; + const void* pNext; + VkRasterizationOrderAMD rasterizationOrder; +} VkPipelineRasterizationStateRasterizationOrderAMD; -#define VK_EXT_post_depth_coverage 1 -#define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1 -#define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage" +// VK_AMD_shader_trinary_minmax is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_trinary_minmax 1 +#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1 +#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax" -#define VK_EXT_image_drm_format_modifier 1 -#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 1 -#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier" -typedef struct VkDrmFormatModifierPropertiesEXT { - uint64_t drmFormatModifier; - uint32_t drmFormatModifierPlaneCount; - VkFormatFeatureFlags drmFormatModifierTilingFeatures; -} VkDrmFormatModifierPropertiesEXT; -typedef struct VkDrmFormatModifierPropertiesListEXT { - VkStructureType sType; - void* pNext; - uint32_t drmFormatModifierCount; - VkDrmFormatModifierPropertiesEXT* pDrmFormatModifierProperties; -} VkDrmFormatModifierPropertiesListEXT; +// VK_AMD_shader_explicit_vertex_parameter is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_explicit_vertex_parameter 1 +#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1 +#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter" -typedef struct VkPhysicalDeviceImageDrmFormatModifierInfoEXT { - VkStructureType sType; - const void* pNext; - uint64_t drmFormatModifier; - VkSharingMode sharingMode; - uint32_t queueFamilyIndexCount; - const uint32_t* pQueueFamilyIndices; -} VkPhysicalDeviceImageDrmFormatModifierInfoEXT; -typedef struct VkImageDrmFormatModifierListCreateInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t drmFormatModifierCount; - const uint64_t* pDrmFormatModifiers; -} VkImageDrmFormatModifierListCreateInfoEXT; +// VK_EXT_debug_marker is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_debug_marker 1 +#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4 +#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker" +typedef struct VkDebugMarkerObjectNameInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportObjectTypeEXT objectType; + uint64_t object; + const char* pObjectName; +} VkDebugMarkerObjectNameInfoEXT; -typedef struct VkImageDrmFormatModifierExplicitCreateInfoEXT { +typedef struct VkDebugMarkerObjectTagInfoEXT { VkStructureType sType; const void* pNext; - uint64_t drmFormatModifier; - uint32_t drmFormatModifierPlaneCount; - const VkSubresourceLayout* pPlaneLayouts; -} VkImageDrmFormatModifierExplicitCreateInfoEXT; + VkDebugReportObjectTypeEXT objectType; + uint64_t object; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugMarkerObjectTagInfoEXT; -typedef struct VkImageDrmFormatModifierPropertiesEXT { +typedef struct VkDebugMarkerMarkerInfoEXT { VkStructureType sType; - void* pNext; - uint64_t drmFormatModifier; -} VkImageDrmFormatModifierPropertiesEXT; + const void* pNext; + const char* pMarkerName; + float color[4]; +} VkDebugMarkerMarkerInfoEXT; -typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo); +typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT( +VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT( VkDevice device, - VkImage image, - VkImageDrmFormatModifierPropertiesEXT* pProperties); -#endif + const VkDebugMarkerObjectTagInfoEXT* pTagInfo); +VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT( + VkDevice device, + const VkDebugMarkerObjectNameInfoEXT* pNameInfo); -#define VK_EXT_validation_cache 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) -#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1 -#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache" +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT( + VkCommandBuffer commandBuffer, + const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); -typedef enum VkValidationCacheHeaderVersionEXT { - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1, - VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF -} VkValidationCacheHeaderVersionEXT; -typedef VkFlags VkValidationCacheCreateFlagsEXT; -typedef struct VkValidationCacheCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkValidationCacheCreateFlagsEXT flags; - size_t initialDataSize; - const void* pInitialData; -} VkValidationCacheCreateInfoEXT; +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT( + VkCommandBuffer commandBuffer); -typedef struct VkShaderModuleValidationCacheCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkValidationCacheEXT validationCache; -} VkShaderModuleValidationCacheCreateInfoEXT; - -typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache); -typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches); -typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT( - VkDevice device, - const VkValidationCacheCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkValidationCacheEXT* pValidationCache); - -VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT( - VkDevice device, - VkValidationCacheEXT validationCache, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT( - VkDevice device, - VkValidationCacheEXT dstCache, - uint32_t srcCacheCount, - const VkValidationCacheEXT* pSrcCaches); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( - VkDevice device, - VkValidationCacheEXT validationCache, - size_t* pDataSize, - void* pData); -#endif - - -#define VK_EXT_descriptor_indexing 1 -#define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2 -#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing" -typedef VkDescriptorBindingFlagBits VkDescriptorBindingFlagBitsEXT; - -typedef VkDescriptorBindingFlags VkDescriptorBindingFlagsEXT; - -typedef VkDescriptorSetLayoutBindingFlagsCreateInfo VkDescriptorSetLayoutBindingFlagsCreateInfoEXT; - -typedef VkPhysicalDeviceDescriptorIndexingFeatures VkPhysicalDeviceDescriptorIndexingFeaturesEXT; - -typedef VkPhysicalDeviceDescriptorIndexingProperties VkPhysicalDeviceDescriptorIndexingPropertiesEXT; - -typedef VkDescriptorSetVariableDescriptorCountAllocateInfo VkDescriptorSetVariableDescriptorCountAllocateInfoEXT; - -typedef VkDescriptorSetVariableDescriptorCountLayoutSupport VkDescriptorSetVariableDescriptorCountLayoutSupportEXT; +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( + VkCommandBuffer commandBuffer, + const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +#endif +// VK_AMD_gcn_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_gcn_shader 1 +#define VK_AMD_GCN_SHADER_SPEC_VERSION 1 +#define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader" -#define VK_EXT_shader_viewport_index_layer 1 -#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1 -#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" +// VK_NV_dedicated_allocation is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_dedicated_allocation 1 +#define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1 +#define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation" +typedef struct VkDedicatedAllocationImageCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 dedicatedAllocation; +} VkDedicatedAllocationImageCreateInfoNV; -#define VK_NV_shading_rate_image 1 -#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3 -#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image" +typedef struct VkDedicatedAllocationBufferCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 dedicatedAllocation; +} VkDedicatedAllocationBufferCreateInfoNV; -typedef enum VkShadingRatePaletteEntryNV { - VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0, - VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1, - VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2, - VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3, - VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4, - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5, - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6, - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7, - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8, - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9, - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10, - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11, - VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF -} VkShadingRatePaletteEntryNV; +typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { + VkStructureType sType; + const void* pNext; + VkImage image; + VkBuffer buffer; +} VkDedicatedAllocationMemoryAllocateInfoNV; -typedef enum VkCoarseSampleOrderTypeNV { - VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0, - VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1, - VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2, - VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3, - VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkCoarseSampleOrderTypeNV; -typedef struct VkShadingRatePaletteNV { - uint32_t shadingRatePaletteEntryCount; - const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries; -} VkShadingRatePaletteNV; -typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 shadingRateImageEnable; - uint32_t viewportCount; - const VkShadingRatePaletteNV* pShadingRatePalettes; -} VkPipelineViewportShadingRateImageStateCreateInfoNV; -typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV { +// VK_EXT_transform_feedback is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_transform_feedback 1 +#define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback" +typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT; +typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 shadingRateImage; - VkBool32 shadingRateCoarseSampleOrder; -} VkPhysicalDeviceShadingRateImageFeaturesNV; + VkBool32 transformFeedback; + VkBool32 geometryStreams; +} VkPhysicalDeviceTransformFeedbackFeaturesEXT; -typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV { +typedef struct VkPhysicalDeviceTransformFeedbackPropertiesEXT { VkStructureType sType; void* pNext; - VkExtent2D shadingRateTexelSize; - uint32_t shadingRatePaletteSize; - uint32_t shadingRateMaxCoarseSamples; -} VkPhysicalDeviceShadingRateImagePropertiesNV; - -typedef struct VkCoarseSampleLocationNV { - uint32_t pixelX; - uint32_t pixelY; - uint32_t sample; -} VkCoarseSampleLocationNV; - -typedef struct VkCoarseSampleOrderCustomNV { - VkShadingRatePaletteEntryNV shadingRate; - uint32_t sampleCount; - uint32_t sampleLocationCount; - const VkCoarseSampleLocationNV* pSampleLocations; -} VkCoarseSampleOrderCustomNV; + uint32_t maxTransformFeedbackStreams; + uint32_t maxTransformFeedbackBuffers; + VkDeviceSize maxTransformFeedbackBufferSize; + uint32_t maxTransformFeedbackStreamDataSize; + uint32_t maxTransformFeedbackBufferDataSize; + uint32_t maxTransformFeedbackBufferDataStride; + VkBool32 transformFeedbackQueries; + VkBool32 transformFeedbackStreamsLinesTriangles; + VkBool32 transformFeedbackRasterizationStreamSelect; + VkBool32 transformFeedbackDraw; +} VkPhysicalDeviceTransformFeedbackPropertiesEXT; -typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkCoarseSampleOrderTypeNV sampleOrderType; - uint32_t customSampleOrderCount; - const VkCoarseSampleOrderCustomNV* pCustomSampleOrders; -} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV; +typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateStreamCreateFlagsEXT flags; + uint32_t rasterizationStream; +} VkPipelineRasterizationStateStreamCreateInfoEXT; -typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); -typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes); -typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); +typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes); +typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV( +VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT( VkCommandBuffer commandBuffer, - VkImageView imageView, - VkImageLayout imageLayout); + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes); -VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV( +VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT( VkCommandBuffer commandBuffer, - uint32_t firstViewport, - uint32_t viewportCount, - const VkShadingRatePaletteNV* pShadingRatePalettes); + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); -VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( +VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT( VkCommandBuffer commandBuffer, - VkCoarseSampleOrderTypeNV sampleOrderType, - uint32_t customSampleOrderCount, - const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); -#endif + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags, + uint32_t index); -#define VK_NV_ray_tracing 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) -#define VK_NV_RAY_TRACING_SPEC_VERSION 3 -#define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" -#define VK_SHADER_UNUSED_KHR (~0U) -#define VK_SHADER_UNUSED_NV VK_SHADER_UNUSED_KHR +VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + uint32_t index); -typedef enum VkRayTracingShaderGroupTypeKHR { - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0, - VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1, - VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2, - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, - VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, - VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, - VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkRayTracingShaderGroupTypeKHR; -typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV; +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( + VkCommandBuffer commandBuffer, + uint32_t instanceCount, + uint32_t firstInstance, + VkBuffer counterBuffer, + VkDeviceSize counterBufferOffset, + uint32_t counterOffset, + uint32_t vertexStride); +#endif -typedef enum VkGeometryTypeKHR { - VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0, - VK_GEOMETRY_TYPE_AABBS_KHR = 1, - VK_GEOMETRY_TYPE_INSTANCES_KHR = 2, - VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, - VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, - VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkGeometryTypeKHR; -typedef VkGeometryTypeKHR VkGeometryTypeNV; +// VK_NVX_binary_import is a preprocessor guard. Do not pass it to API calls. +#define VK_NVX_binary_import 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuModuleNVX) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuFunctionNVX) +#define VK_NVX_BINARY_IMPORT_SPEC_VERSION 1 +#define VK_NVX_BINARY_IMPORT_EXTENSION_NAME "VK_NVX_binary_import" +typedef struct VkCuModuleCreateInfoNVX { + VkStructureType sType; + const void* pNext; + size_t dataSize; + const void* pData; +} VkCuModuleCreateInfoNVX; +typedef struct VkCuFunctionCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuModuleNVX module; + const char* pName; +} VkCuFunctionCreateInfoNVX; -typedef enum VkAccelerationStructureTypeKHR { - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, - VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, - VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, - VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, - VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkAccelerationStructureTypeKHR; -typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV; +typedef struct VkCuLaunchInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuFunctionNVX function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCuLaunchInfoNVX; +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuModuleNVX)(VkDevice device, const VkCuModuleCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuModuleNVX* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuFunctionNVX)(VkDevice device, const VkCuFunctionCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuFunctionNVX* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCuModuleNVX)(VkDevice device, VkCuModuleNVX module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCuFunctionNVX)(VkDevice device, VkCuFunctionNVX function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCuLaunchKernelNVX)(VkCommandBuffer commandBuffer, const VkCuLaunchInfoNVX* pLaunchInfo); -typedef enum VkCopyAccelerationStructureModeKHR { - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0, - VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1, - VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2, - VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3, - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR, - VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR, - VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkCopyAccelerationStructureModeKHR; -typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuModuleNVX( + VkDevice device, + const VkCuModuleCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuModuleNVX* pModule); +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuFunctionNVX( + VkDevice device, + const VkCuFunctionCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuFunctionNVX* pFunction); -typedef enum VkAccelerationStructureMemoryRequirementsTypeNV { - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkAccelerationStructureMemoryRequirementsTypeNV; +VKAPI_ATTR void VKAPI_CALL vkDestroyCuModuleNVX( + VkDevice device, + VkCuModuleNVX module, + const VkAllocationCallbacks* pAllocator); -typedef enum VkGeometryFlagBitsKHR { - VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001, - VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002, - VK_GEOMETRY_OPAQUE_BIT_NV = VK_GEOMETRY_OPAQUE_BIT_KHR, - VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, - VK_GEOMETRY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkGeometryFlagBitsKHR; -typedef VkFlags VkGeometryFlagsKHR; -typedef VkGeometryFlagsKHR VkGeometryFlagsNV; +VKAPI_ATTR void VKAPI_CALL vkDestroyCuFunctionNVX( + VkDevice device, + VkCuFunctionNVX function, + const VkAllocationCallbacks* pAllocator); -typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV; +VKAPI_ATTR void VKAPI_CALL vkCmdCuLaunchKernelNVX( + VkCommandBuffer commandBuffer, + const VkCuLaunchInfoNVX* pLaunchInfo); +#endif -typedef enum VkGeometryInstanceFlagBitsKHR { - VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001, - VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0x00000002, - VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, - VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, - VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR, - VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, - VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, - VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, - VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR, - VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkGeometryInstanceFlagBitsKHR; -typedef VkFlags VkGeometryInstanceFlagsKHR; -typedef VkGeometryInstanceFlagsKHR VkGeometryInstanceFlagsNV; +// VK_NVX_image_view_handle is a preprocessor guard. Do not pass it to API calls. +#define VK_NVX_image_view_handle 1 +#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 2 +#define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" +typedef struct VkImageViewHandleInfoNVX { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkDescriptorType descriptorType; + VkSampler sampler; +} VkImageViewHandleInfoNVX; -typedef VkGeometryInstanceFlagBitsKHR VkGeometryInstanceFlagBitsNV; +typedef struct VkImageViewAddressPropertiesNVX { + VkStructureType sType; + void* pNext; + VkDeviceAddress deviceAddress; + VkDeviceSize size; +} VkImageViewAddressPropertiesNVX; +typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewAddressNVX)(VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties); -typedef enum VkBuildAccelerationStructureFlagBitsKHR { - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001, - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002, - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004, - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, - VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, - VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0x00000020, - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, - VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, - VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkBuildAccelerationStructureFlagBitsKHR; -typedef VkFlags VkBuildAccelerationStructureFlagsKHR; -typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX( + VkDevice device, + const VkImageViewHandleInfoNVX* pInfo); -typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV; +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX( + VkDevice device, + VkImageView imageView, + VkImageViewAddressPropertiesNVX* pProperties); +#endif -typedef struct VkRayTracingShaderGroupCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkRayTracingShaderGroupTypeKHR type; - uint32_t generalShader; - uint32_t closestHitShader; - uint32_t anyHitShader; - uint32_t intersectionShader; -} VkRayTracingShaderGroupCreateInfoNV; -typedef struct VkRayTracingPipelineCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags flags; - uint32_t stageCount; - const VkPipelineShaderStageCreateInfo* pStages; - uint32_t groupCount; - const VkRayTracingShaderGroupCreateInfoNV* pGroups; - uint32_t maxRecursionDepth; - VkPipelineLayout layout; - VkPipeline basePipelineHandle; - int32_t basePipelineIndex; -} VkRayTracingPipelineCreateInfoNV; +// VK_AMD_draw_indirect_count is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_draw_indirect_count 1 +#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 2 +#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); -typedef struct VkGeometryTrianglesNV { - VkStructureType sType; - const void* pNext; - VkBuffer vertexData; - VkDeviceSize vertexOffset; - uint32_t vertexCount; - VkDeviceSize vertexStride; - VkFormat vertexFormat; - VkBuffer indexData; - VkDeviceSize indexOffset; - uint32_t indexCount; - VkIndexType indexType; - VkBuffer transformData; - VkDeviceSize transformOffset; -} VkGeometryTrianglesNV; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); -typedef struct VkGeometryAABBNV { - VkStructureType sType; - const void* pNext; - VkBuffer aabbData; - uint32_t numAABBs; - uint32_t stride; - VkDeviceSize offset; -} VkGeometryAABBNV; +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif -typedef struct VkGeometryDataNV { - VkGeometryTrianglesNV triangles; - VkGeometryAABBNV aabbs; -} VkGeometryDataNV; -typedef struct VkGeometryNV { - VkStructureType sType; - const void* pNext; - VkGeometryTypeKHR geometryType; - VkGeometryDataNV geometry; - VkGeometryFlagsKHR flags; -} VkGeometryNV; +// VK_AMD_negative_viewport_height is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_negative_viewport_height 1 +#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1 +#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height" -typedef struct VkAccelerationStructureInfoNV { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureTypeNV type; - VkBuildAccelerationStructureFlagsNV flags; - uint32_t instanceCount; - uint32_t geometryCount; - const VkGeometryNV* pGeometries; -} VkAccelerationStructureInfoNV; -typedef struct VkAccelerationStructureCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkDeviceSize compactedSize; - VkAccelerationStructureInfoNV info; -} VkAccelerationStructureCreateInfoNV; +// VK_AMD_gpu_shader_half_float is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_gpu_shader_half_float 1 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 2 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float" -typedef struct VkBindAccelerationStructureMemoryInfoNV { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureNV accelerationStructure; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; - uint32_t deviceIndexCount; - const uint32_t* pDeviceIndices; -} VkBindAccelerationStructureMemoryInfoNV; -typedef struct VkWriteDescriptorSetAccelerationStructureNV { - VkStructureType sType; - const void* pNext; - uint32_t accelerationStructureCount; - const VkAccelerationStructureNV* pAccelerationStructures; -} VkWriteDescriptorSetAccelerationStructureNV; +// VK_AMD_shader_ballot is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_ballot 1 +#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1 +#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot" -typedef struct VkAccelerationStructureMemoryRequirementsInfoNV { + +// VK_AMD_texture_gather_bias_lod is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_texture_gather_bias_lod 1 +#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1 +#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod" +typedef struct VkTextureLODGatherFormatPropertiesAMD { + VkStructureType sType; + void* pNext; + VkBool32 supportsTextureGatherLODBiasAMD; +} VkTextureLODGatherFormatPropertiesAMD; + + + +// VK_AMD_shader_info is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_info 1 +#define VK_AMD_SHADER_INFO_SPEC_VERSION 1 +#define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info" + +typedef enum VkShaderInfoTypeAMD { + VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0, + VK_SHADER_INFO_TYPE_BINARY_AMD = 1, + VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2, + VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkShaderInfoTypeAMD; +typedef struct VkShaderResourceUsageAMD { + uint32_t numUsedVgprs; + uint32_t numUsedSgprs; + uint32_t ldsSizePerLocalWorkGroup; + size_t ldsUsageSizeInBytes; + size_t scratchMemUsageInBytes; +} VkShaderResourceUsageAMD; + +typedef struct VkShaderStatisticsInfoAMD { + VkShaderStageFlags shaderStageMask; + VkShaderResourceUsageAMD resourceUsage; + uint32_t numPhysicalVgprs; + uint32_t numPhysicalSgprs; + uint32_t numAvailableVgprs; + uint32_t numAvailableSgprs; + uint32_t computeWorkGroupSize[3]; +} VkShaderStatisticsInfoAMD; + +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( + VkDevice device, + VkPipeline pipeline, + VkShaderStageFlagBits shaderStage, + VkShaderInfoTypeAMD infoType, + size_t* pInfoSize, + void* pInfo); +#endif + + +// VK_AMD_shader_image_load_store_lod is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_image_load_store_lod 1 +#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1 +#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod" + + +// VK_NV_corner_sampled_image is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_corner_sampled_image 1 +#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2 +#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image" +typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cornerSampledImage; +} VkPhysicalDeviceCornerSampledImageFeaturesNV; + + + +// VK_IMG_format_pvrtc is a preprocessor guard. Do not pass it to API calls. +#define VK_IMG_format_pvrtc 1 +#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 +#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" + + +// VK_NV_external_memory_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_memory_capabilities 1 +#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities" + +typedef enum VkExternalMemoryHandleTypeFlagBitsNV { + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkExternalMemoryHandleTypeFlagBitsNV; +typedef VkFlags VkExternalMemoryHandleTypeFlagsNV; + +typedef enum VkExternalMemoryFeatureFlagBitsNV { + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004, + VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkExternalMemoryFeatureFlagBitsNV; +typedef VkFlags VkExternalMemoryFeatureFlagsNV; +typedef struct VkExternalImageFormatPropertiesNV { + VkImageFormatProperties imageFormatProperties; + VkExternalMemoryFeatureFlagsNV externalMemoryFeatures; + VkExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes; + VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes; +} VkExternalImageFormatPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkExternalMemoryHandleTypeFlagsNV externalHandleType, + VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); +#endif + + +// VK_NV_external_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_memory 1 +#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory" +typedef struct VkExternalMemoryImageCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleTypes; +} VkExternalMemoryImageCreateInfoNV; + +typedef struct VkExportMemoryAllocateInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleTypes; +} VkExportMemoryAllocateInfoNV; + + + +// VK_EXT_validation_flags is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_validation_flags 1 +#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 2 +#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags" + +typedef enum VkValidationCheckEXT { + VK_VALIDATION_CHECK_ALL_EXT = 0, + VK_VALIDATION_CHECK_SHADERS_EXT = 1, + VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationCheckEXT; +typedef struct VkValidationFlagsEXT { + VkStructureType sType; + const void* pNext; + uint32_t disabledValidationCheckCount; + const VkValidationCheckEXT* pDisabledValidationChecks; +} VkValidationFlagsEXT; + + + +// VK_EXT_shader_subgroup_ballot is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_subgroup_ballot 1 +#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot" + + +// VK_EXT_shader_subgroup_vote is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_subgroup_vote 1 +#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote" + + +// VK_EXT_texture_compression_astc_hdr is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_texture_compression_astc_hdr 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME "VK_EXT_texture_compression_astc_hdr" +typedef VkPhysicalDeviceTextureCompressionASTCHDRFeatures VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT; + + + +// VK_EXT_astc_decode_mode is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_astc_decode_mode 1 +#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1 +#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode" +typedef struct VkImageViewASTCDecodeModeEXT { + VkStructureType sType; + const void* pNext; + VkFormat decodeMode; +} VkImageViewASTCDecodeModeEXT; + +typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 decodeModeSharedExponent; +} VkPhysicalDeviceASTCDecodeFeaturesEXT; + + + +// VK_EXT_pipeline_robustness is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_robustness 1 +#define VK_EXT_PIPELINE_ROBUSTNESS_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_pipeline_robustness" + +typedef enum VkPipelineRobustnessBufferBehaviorEXT { + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT = 0, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT = 1, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT = 2, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT = 3, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPipelineRobustnessBufferBehaviorEXT; + +typedef enum VkPipelineRobustnessImageBehaviorEXT { + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT = 0, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT = 1, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_EXT = 2, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT = 3, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPipelineRobustnessImageBehaviorEXT; +typedef struct VkPhysicalDevicePipelineRobustnessFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelineRobustness; +} VkPhysicalDevicePipelineRobustnessFeaturesEXT; + +typedef struct VkPhysicalDevicePipelineRobustnessPropertiesEXT { + VkStructureType sType; + void* pNext; + VkPipelineRobustnessBufferBehaviorEXT defaultRobustnessStorageBuffers; + VkPipelineRobustnessBufferBehaviorEXT defaultRobustnessUniformBuffers; + VkPipelineRobustnessBufferBehaviorEXT defaultRobustnessVertexInputs; + VkPipelineRobustnessImageBehaviorEXT defaultRobustnessImages; +} VkPhysicalDevicePipelineRobustnessPropertiesEXT; + +typedef struct VkPipelineRobustnessCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRobustnessBufferBehaviorEXT storageBuffers; + VkPipelineRobustnessBufferBehaviorEXT uniformBuffers; + VkPipelineRobustnessBufferBehaviorEXT vertexInputs; + VkPipelineRobustnessImageBehaviorEXT images; +} VkPipelineRobustnessCreateInfoEXT; + + + +// VK_EXT_conditional_rendering is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_conditional_rendering 1 +#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 2 +#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering" + +typedef enum VkConditionalRenderingFlagBitsEXT { + VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001, + VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConditionalRenderingFlagBitsEXT; +typedef VkFlags VkConditionalRenderingFlagsEXT; +typedef struct VkConditionalRenderingBeginInfoEXT { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; + VkDeviceSize offset; + VkConditionalRenderingFlagsEXT flags; +} VkConditionalRenderingBeginInfoEXT; + +typedef struct VkPhysicalDeviceConditionalRenderingFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 conditionalRendering; + VkBool32 inheritedConditionalRendering; +} VkPhysicalDeviceConditionalRenderingFeaturesEXT; + +typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 conditionalRenderingEnable; +} VkCommandBufferInheritanceConditionalRenderingInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); +typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT( + VkCommandBuffer commandBuffer, + const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( + VkCommandBuffer commandBuffer); +#endif + + +// VK_NV_clip_space_w_scaling is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_clip_space_w_scaling 1 +#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 +#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" +typedef struct VkViewportWScalingNV { + float xcoeff; + float ycoeff; +} VkViewportWScalingNV; + +typedef struct VkPipelineViewportWScalingStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportWScalingEnable; + uint32_t viewportCount; + const VkViewportWScalingNV* pViewportWScalings; +} VkPipelineViewportWScalingStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewportWScalingNV* pViewportWScalings); +#endif + + +// VK_EXT_direct_mode_display is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_direct_mode_display 1 +#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display" +typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); +#endif + + +// VK_EXT_display_surface_counter is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_display_surface_counter 1 +#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1 +#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" + +typedef enum VkSurfaceCounterFlagBitsEXT { + VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0x00000001, + VK_SURFACE_COUNTER_VBLANK_EXT = VK_SURFACE_COUNTER_VBLANK_BIT_EXT, + VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSurfaceCounterFlagBitsEXT; +typedef VkFlags VkSurfaceCounterFlagsEXT; +typedef struct VkSurfaceCapabilities2EXT { + VkStructureType sType; + void* pNext; + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; + VkSurfaceCounterFlagsEXT supportedSurfaceCounters; +} VkSurfaceCapabilities2EXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilities2EXT* pSurfaceCapabilities); +#endif + + +// VK_EXT_display_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_display_control 1 +#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control" + +typedef enum VkDisplayPowerStateEXT { + VK_DISPLAY_POWER_STATE_OFF_EXT = 0, + VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1, + VK_DISPLAY_POWER_STATE_ON_EXT = 2, + VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDisplayPowerStateEXT; + +typedef enum VkDeviceEventTypeEXT { + VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0, + VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceEventTypeEXT; + +typedef enum VkDisplayEventTypeEXT { + VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0, + VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDisplayEventTypeEXT; +typedef struct VkDisplayPowerInfoEXT { + VkStructureType sType; + const void* pNext; + VkDisplayPowerStateEXT powerState; +} VkDisplayPowerInfoEXT; + +typedef struct VkDeviceEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceEventTypeEXT deviceEvent; +} VkDeviceEventInfoEXT; + +typedef struct VkDisplayEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkDisplayEventTypeEXT displayEvent; +} VkDisplayEventInfoEXT; + +typedef struct VkSwapchainCounterCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkSurfaceCounterFlagsEXT surfaceCounters; +} VkSwapchainCounterCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT( + VkDevice device, + VkDisplayKHR display, + const VkDisplayPowerInfoEXT* pDisplayPowerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT( + VkDevice device, + const VkDeviceEventInfoEXT* pDeviceEventInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT( + VkDevice device, + VkDisplayKHR display, + const VkDisplayEventInfoEXT* pDisplayEventInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( + VkDevice device, + VkSwapchainKHR swapchain, + VkSurfaceCounterFlagBitsEXT counter, + uint64_t* pCounterValue); +#endif + + +// VK_GOOGLE_display_timing is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_display_timing 1 +#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1 +#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing" +typedef struct VkRefreshCycleDurationGOOGLE { + uint64_t refreshDuration; +} VkRefreshCycleDurationGOOGLE; + +typedef struct VkPastPresentationTimingGOOGLE { + uint32_t presentID; + uint64_t desiredPresentTime; + uint64_t actualPresentTime; + uint64_t earliestPresentTime; + uint64_t presentMargin; +} VkPastPresentationTimingGOOGLE; + +typedef struct VkPresentTimeGOOGLE { + uint32_t presentID; + uint64_t desiredPresentTime; +} VkPresentTimeGOOGLE; + +typedef struct VkPresentTimesInfoGOOGLE { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentTimeGOOGLE* pTimes; +} VkPresentTimesInfoGOOGLE; + +typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE( + VkDevice device, + VkSwapchainKHR swapchain, + VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pPresentationTimingCount, + VkPastPresentationTimingGOOGLE* pPresentationTimings); +#endif + + +// VK_NV_sample_mask_override_coverage is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_sample_mask_override_coverage 1 +#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1 +#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage" + + +// VK_NV_geometry_shader_passthrough is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_geometry_shader_passthrough 1 +#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1 +#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough" + + +// VK_NV_viewport_array2 is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_viewport_array2 1 +#define VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME "VK_NV_viewport_array2" +#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION +#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME + + +// VK_NVX_multiview_per_view_attributes is a preprocessor guard. Do not pass it to API calls. +#define VK_NVX_multiview_per_view_attributes 1 +#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1 +#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes" +typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { + VkStructureType sType; + void* pNext; + VkBool32 perViewPositionAllComponents; +} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX; + + + +// VK_NV_viewport_swizzle is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_viewport_swizzle 1 +#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle" + +typedef enum VkViewportCoordinateSwizzleNV { + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7, + VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF +} VkViewportCoordinateSwizzleNV; +typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV; +typedef struct VkViewportSwizzleNV { + VkViewportCoordinateSwizzleNV x; + VkViewportCoordinateSwizzleNV y; + VkViewportCoordinateSwizzleNV z; + VkViewportCoordinateSwizzleNV w; +} VkViewportSwizzleNV; + +typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineViewportSwizzleStateCreateFlagsNV flags; + uint32_t viewportCount; + const VkViewportSwizzleNV* pViewportSwizzles; +} VkPipelineViewportSwizzleStateCreateInfoNV; + + + +// VK_EXT_discard_rectangles is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_discard_rectangles 1 +#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 2 +#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" + +typedef enum VkDiscardRectangleModeEXT { + VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0, + VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1, + VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDiscardRectangleModeEXT; +typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxDiscardRectangles; +} VkPhysicalDeviceDiscardRectanglePropertiesEXT; + +typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineDiscardRectangleStateCreateFlagsEXT flags; + VkDiscardRectangleModeEXT discardRectangleMode; + uint32_t discardRectangleCount; + const VkRect2D* pDiscardRectangles; +} VkPipelineDiscardRectangleStateCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 discardRectangleEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleModeEXT)(VkCommandBuffer commandBuffer, VkDiscardRectangleModeEXT discardRectangleMode); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( + VkCommandBuffer commandBuffer, + uint32_t firstDiscardRectangle, + uint32_t discardRectangleCount, + const VkRect2D* pDiscardRectangles); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 discardRectangleEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleModeEXT( + VkCommandBuffer commandBuffer, + VkDiscardRectangleModeEXT discardRectangleMode); +#endif + + +// VK_EXT_conservative_rasterization is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_conservative_rasterization 1 +#define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1 +#define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization" + +typedef enum VkConservativeRasterizationModeEXT { + VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0, + VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1, + VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2, + VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConservativeRasterizationModeEXT; +typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceConservativeRasterizationPropertiesEXT { + VkStructureType sType; + void* pNext; + float primitiveOverestimationSize; + float maxExtraPrimitiveOverestimationSize; + float extraPrimitiveOverestimationSizeGranularity; + VkBool32 primitiveUnderestimation; + VkBool32 conservativePointAndLineRasterization; + VkBool32 degenerateTrianglesRasterized; + VkBool32 degenerateLinesRasterized; + VkBool32 fullyCoveredFragmentShaderInputVariable; + VkBool32 conservativeRasterizationPostDepthCoverage; +} VkPhysicalDeviceConservativeRasterizationPropertiesEXT; + +typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationConservativeStateCreateFlagsEXT flags; + VkConservativeRasterizationModeEXT conservativeRasterizationMode; + float extraPrimitiveOverestimationSize; +} VkPipelineRasterizationConservativeStateCreateInfoEXT; + + + +// VK_EXT_depth_clip_enable is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_clip_enable 1 +#define VK_EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME "VK_EXT_depth_clip_enable" +typedef VkFlags VkPipelineRasterizationDepthClipStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceDepthClipEnableFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthClipEnable; +} VkPhysicalDeviceDepthClipEnableFeaturesEXT; + +typedef struct VkPipelineRasterizationDepthClipStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationDepthClipStateCreateFlagsEXT flags; + VkBool32 depthClipEnable; +} VkPipelineRasterizationDepthClipStateCreateInfoEXT; + + + +// VK_EXT_swapchain_colorspace is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_swapchain_colorspace 1 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 4 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" + + +// VK_EXT_hdr_metadata is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_hdr_metadata 1 +#define VK_EXT_HDR_METADATA_SPEC_VERSION 2 +#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" +typedef struct VkXYColorEXT { + float x; + float y; +} VkXYColorEXT; + +typedef struct VkHdrMetadataEXT { + VkStructureType sType; + const void* pNext; + VkXYColorEXT displayPrimaryRed; + VkXYColorEXT displayPrimaryGreen; + VkXYColorEXT displayPrimaryBlue; + VkXYColorEXT whitePoint; + float maxLuminance; + float minLuminance; + float maxContentLightLevel; + float maxFrameAverageLightLevel; +} VkHdrMetadataEXT; + +typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainKHR* pSwapchains, + const VkHdrMetadataEXT* pMetadata); +#endif + + +// VK_IMG_relaxed_line_rasterization is a preprocessor guard. Do not pass it to API calls. +#define VK_IMG_relaxed_line_rasterization 1 +#define VK_IMG_RELAXED_LINE_RASTERIZATION_SPEC_VERSION 1 +#define VK_IMG_RELAXED_LINE_RASTERIZATION_EXTENSION_NAME "VK_IMG_relaxed_line_rasterization" +typedef struct VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG { + VkStructureType sType; + void* pNext; + VkBool32 relaxedLineRasterization; +} VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG; + + + +// VK_EXT_external_memory_dma_buf is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_external_memory_dma_buf 1 +#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf" + + +// VK_EXT_queue_family_foreign is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_queue_family_foreign 1 +#define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1 +#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign" +#define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U) + + +// VK_EXT_debug_utils is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_debug_utils 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT) +#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 2 +#define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils" +typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT; + +typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugUtilsMessageSeverityFlagBitsEXT; + +typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001, + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002, + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004, + VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT = 0x00000008, + VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugUtilsMessageTypeFlagBitsEXT; +typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT; +typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; +typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; +typedef struct VkDebugUtilsLabelEXT { + VkStructureType sType; + const void* pNext; + const char* pLabelName; + float color[4]; +} VkDebugUtilsLabelEXT; + +typedef struct VkDebugUtilsObjectNameInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + const char* pObjectName; +} VkDebugUtilsObjectNameInfoEXT; + +typedef struct VkDebugUtilsMessengerCallbackDataEXT { + VkStructureType sType; + const void* pNext; + VkDebugUtilsMessengerCallbackDataFlagsEXT flags; + const char* pMessageIdName; + int32_t messageIdNumber; + const char* pMessage; + uint32_t queueLabelCount; + const VkDebugUtilsLabelEXT* pQueueLabels; + uint32_t cmdBufLabelCount; + const VkDebugUtilsLabelEXT* pCmdBufLabels; + uint32_t objectCount; + const VkDebugUtilsObjectNameInfoEXT* pObjects; +} VkDebugUtilsMessengerCallbackDataEXT; + +typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDebugUtilsMessengerCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugUtilsMessengerCreateFlagsEXT flags; + VkDebugUtilsMessageSeverityFlagsEXT messageSeverity; + VkDebugUtilsMessageTypeFlagsEXT messageType; + PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback; + void* pUserData; +} VkDebugUtilsMessengerCreateInfoEXT; + +typedef struct VkDebugUtilsObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugUtilsObjectTagInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo); +typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo); +typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkQueueEndDebugUtilsLabelEXT)(VkQueue queue); +typedef void (VKAPI_PTR *PFN_vkQueueInsertDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdInsertDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugUtilsMessengerEXT)(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger); +typedef void (VKAPI_PTR *PFN_vkDestroyDebugUtilsMessengerEXT)(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkSubmitDebugUtilsMessageEXT)(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectNameEXT( + VkDevice device, + const VkDebugUtilsObjectNameInfoEXT* pNameInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectTagEXT( + VkDevice device, + const VkDebugUtilsObjectTagInfoEXT* pTagInfo); + +VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT( + VkQueue queue, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT( + VkQueue queue); + +VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT( + VkQueue queue, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdInsertDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( + VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugUtilsMessengerEXT* pMessenger); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( + VkInstance instance, + VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT( + VkInstance instance, + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); +#endif + + +// VK_EXT_sampler_filter_minmax is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_sampler_filter_minmax 1 +#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 2 +#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax" +typedef VkSamplerReductionMode VkSamplerReductionModeEXT; + +typedef VkSamplerReductionModeCreateInfo VkSamplerReductionModeCreateInfoEXT; + +typedef VkPhysicalDeviceSamplerFilterMinmaxProperties VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT; + + + +// VK_AMD_gpu_shader_int16 is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_gpu_shader_int16 1 +#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 2 +#define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" + + +// VK_AMD_mixed_attachment_samples is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_mixed_attachment_samples 1 +#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1 +#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples" + + +// VK_AMD_shader_fragment_mask is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_fragment_mask 1 +#define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1 +#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask" + + +// VK_EXT_inline_uniform_block is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_inline_uniform_block 1 +#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1 +#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block" +typedef VkPhysicalDeviceInlineUniformBlockFeatures VkPhysicalDeviceInlineUniformBlockFeaturesEXT; + +typedef VkPhysicalDeviceInlineUniformBlockProperties VkPhysicalDeviceInlineUniformBlockPropertiesEXT; + +typedef VkWriteDescriptorSetInlineUniformBlock VkWriteDescriptorSetInlineUniformBlockEXT; + +typedef VkDescriptorPoolInlineUniformBlockCreateInfo VkDescriptorPoolInlineUniformBlockCreateInfoEXT; + + + +// VK_EXT_shader_stencil_export is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_stencil_export 1 +#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1 +#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export" + + +// VK_EXT_sample_locations is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_sample_locations 1 +#define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1 +#define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations" +typedef struct VkSampleLocationEXT { + float x; + float y; +} VkSampleLocationEXT; + +typedef struct VkSampleLocationsInfoEXT { + VkStructureType sType; + const void* pNext; + VkSampleCountFlagBits sampleLocationsPerPixel; + VkExtent2D sampleLocationGridSize; + uint32_t sampleLocationsCount; + const VkSampleLocationEXT* pSampleLocations; +} VkSampleLocationsInfoEXT; + +typedef struct VkAttachmentSampleLocationsEXT { + uint32_t attachmentIndex; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkAttachmentSampleLocationsEXT; + +typedef struct VkSubpassSampleLocationsEXT { + uint32_t subpassIndex; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkSubpassSampleLocationsEXT; + +typedef struct VkRenderPassSampleLocationsBeginInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentInitialSampleLocationsCount; + const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations; + uint32_t postSubpassSampleLocationsCount; + const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations; +} VkRenderPassSampleLocationsBeginInfoEXT; + +typedef struct VkPipelineSampleLocationsStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 sampleLocationsEnable; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkPipelineSampleLocationsStateCreateInfoEXT; + +typedef struct VkPhysicalDeviceSampleLocationsPropertiesEXT { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleLocationSampleCounts; + VkExtent2D maxSampleLocationGridSize; + float sampleLocationCoordinateRange[2]; + uint32_t sampleLocationSubPixelBits; + VkBool32 variableSampleLocations; +} VkPhysicalDeviceSampleLocationsPropertiesEXT; + +typedef struct VkMultisamplePropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D maxSampleLocationGridSize; +} VkMultisamplePropertiesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT( + VkCommandBuffer commandBuffer, + const VkSampleLocationsInfoEXT* pSampleLocationsInfo); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( + VkPhysicalDevice physicalDevice, + VkSampleCountFlagBits samples, + VkMultisamplePropertiesEXT* pMultisampleProperties); +#endif + + +// VK_EXT_blend_operation_advanced is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_blend_operation_advanced 1 +#define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2 +#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced" + +typedef enum VkBlendOverlapEXT { + VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0, + VK_BLEND_OVERLAP_DISJOINT_EXT = 1, + VK_BLEND_OVERLAP_CONJOINT_EXT = 2, + VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF +} VkBlendOverlapEXT; +typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 advancedBlendCoherentOperations; +} VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT; + +typedef struct VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t advancedBlendMaxColorAttachments; + VkBool32 advancedBlendIndependentBlend; + VkBool32 advancedBlendNonPremultipliedSrcColor; + VkBool32 advancedBlendNonPremultipliedDstColor; + VkBool32 advancedBlendCorrelatedOverlap; + VkBool32 advancedBlendAllOperations; +} VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT; + +typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 srcPremultiplied; + VkBool32 dstPremultiplied; + VkBlendOverlapEXT blendOverlap; +} VkPipelineColorBlendAdvancedStateCreateInfoEXT; + + + +// VK_NV_fragment_coverage_to_color is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_fragment_coverage_to_color 1 +#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color" +typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV; +typedef struct VkPipelineCoverageToColorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageToColorStateCreateFlagsNV flags; + VkBool32 coverageToColorEnable; + uint32_t coverageToColorLocation; +} VkPipelineCoverageToColorStateCreateInfoNV; + + + +// VK_NV_framebuffer_mixed_samples is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_framebuffer_mixed_samples 1 +#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1 +#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples" + +typedef enum VkCoverageModulationModeNV { + VK_COVERAGE_MODULATION_MODE_NONE_NV = 0, + VK_COVERAGE_MODULATION_MODE_RGB_NV = 1, + VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2, + VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3, + VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoverageModulationModeNV; +typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV; +typedef struct VkPipelineCoverageModulationStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageModulationStateCreateFlagsNV flags; + VkCoverageModulationModeNV coverageModulationMode; + VkBool32 coverageModulationTableEnable; + uint32_t coverageModulationTableCount; + const float* pCoverageModulationTable; +} VkPipelineCoverageModulationStateCreateInfoNV; + + + +// VK_NV_fill_rectangle is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_fill_rectangle 1 +#define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1 +#define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle" + + +// VK_NV_shader_sm_builtins is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shader_sm_builtins 1 +#define VK_NV_SHADER_SM_BUILTINS_SPEC_VERSION 1 +#define VK_NV_SHADER_SM_BUILTINS_EXTENSION_NAME "VK_NV_shader_sm_builtins" +typedef struct VkPhysicalDeviceShaderSMBuiltinsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t shaderSMCount; + uint32_t shaderWarpsPerSM; +} VkPhysicalDeviceShaderSMBuiltinsPropertiesNV; + +typedef struct VkPhysicalDeviceShaderSMBuiltinsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shaderSMBuiltins; +} VkPhysicalDeviceShaderSMBuiltinsFeaturesNV; + + + +// VK_EXT_post_depth_coverage is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_post_depth_coverage 1 +#define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1 +#define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage" + + +// VK_EXT_image_drm_format_modifier is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_drm_format_modifier 1 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 2 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier" +typedef struct VkDrmFormatModifierPropertiesEXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags drmFormatModifierTilingFeatures; +} VkDrmFormatModifierPropertiesEXT; + +typedef struct VkDrmFormatModifierPropertiesListEXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierPropertiesEXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesListEXT; + +typedef struct VkPhysicalDeviceImageDrmFormatModifierInfoEXT { + VkStructureType sType; + const void* pNext; + uint64_t drmFormatModifier; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkPhysicalDeviceImageDrmFormatModifierInfoEXT; + +typedef struct VkImageDrmFormatModifierListCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t drmFormatModifierCount; + const uint64_t* pDrmFormatModifiers; +} VkImageDrmFormatModifierListCreateInfoEXT; + +typedef struct VkImageDrmFormatModifierExplicitCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + const VkSubresourceLayout* pPlaneLayouts; +} VkImageDrmFormatModifierExplicitCreateInfoEXT; + +typedef struct VkImageDrmFormatModifierPropertiesEXT { + VkStructureType sType; + void* pNext; + uint64_t drmFormatModifier; +} VkImageDrmFormatModifierPropertiesEXT; + +typedef struct VkDrmFormatModifierProperties2EXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags2 drmFormatModifierTilingFeatures; +} VkDrmFormatModifierProperties2EXT; + +typedef struct VkDrmFormatModifierPropertiesList2EXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierProperties2EXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesList2EXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT( + VkDevice device, + VkImage image, + VkImageDrmFormatModifierPropertiesEXT* pProperties); +#endif + + +// VK_EXT_validation_cache is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_validation_cache 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) +#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1 +#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache" + +typedef enum VkValidationCacheHeaderVersionEXT { + VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1, + VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationCacheHeaderVersionEXT; +typedef VkFlags VkValidationCacheCreateFlagsEXT; +typedef struct VkValidationCacheCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkValidationCacheCreateFlagsEXT flags; + size_t initialDataSize; + const void* pInitialData; +} VkValidationCacheCreateInfoEXT; + +typedef struct VkShaderModuleValidationCacheCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkValidationCacheEXT validationCache; +} VkShaderModuleValidationCacheCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache); +typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches); +typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT( + VkDevice device, + const VkValidationCacheCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkValidationCacheEXT* pValidationCache); + +VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT( + VkDevice device, + VkValidationCacheEXT validationCache, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT( + VkDevice device, + VkValidationCacheEXT dstCache, + uint32_t srcCacheCount, + const VkValidationCacheEXT* pSrcCaches); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( + VkDevice device, + VkValidationCacheEXT validationCache, + size_t* pDataSize, + void* pData); +#endif + + +// VK_EXT_descriptor_indexing is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_descriptor_indexing 1 +#define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2 +#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing" +typedef VkDescriptorBindingFlagBits VkDescriptorBindingFlagBitsEXT; + +typedef VkDescriptorBindingFlags VkDescriptorBindingFlagsEXT; + +typedef VkDescriptorSetLayoutBindingFlagsCreateInfo VkDescriptorSetLayoutBindingFlagsCreateInfoEXT; + +typedef VkPhysicalDeviceDescriptorIndexingFeatures VkPhysicalDeviceDescriptorIndexingFeaturesEXT; + +typedef VkPhysicalDeviceDescriptorIndexingProperties VkPhysicalDeviceDescriptorIndexingPropertiesEXT; + +typedef VkDescriptorSetVariableDescriptorCountAllocateInfo VkDescriptorSetVariableDescriptorCountAllocateInfoEXT; + +typedef VkDescriptorSetVariableDescriptorCountLayoutSupport VkDescriptorSetVariableDescriptorCountLayoutSupportEXT; + + + +// VK_EXT_shader_viewport_index_layer is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_viewport_index_layer 1 +#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1 +#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" + + +// VK_NV_shading_rate_image is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shading_rate_image 1 +#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3 +#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image" + +typedef enum VkShadingRatePaletteEntryNV { + VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0, + VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1, + VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2, + VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3, + VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11, + VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF +} VkShadingRatePaletteEntryNV; + +typedef enum VkCoarseSampleOrderTypeNV { + VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0, + VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1, + VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2, + VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3, + VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoarseSampleOrderTypeNV; +typedef struct VkShadingRatePaletteNV { + uint32_t shadingRatePaletteEntryCount; + const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries; +} VkShadingRatePaletteNV; + +typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 shadingRateImageEnable; + uint32_t viewportCount; + const VkShadingRatePaletteNV* pShadingRatePalettes; +} VkPipelineViewportShadingRateImageStateCreateInfoNV; + +typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shadingRateImage; + VkBool32 shadingRateCoarseSampleOrder; +} VkPhysicalDeviceShadingRateImageFeaturesNV; + +typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV { + VkStructureType sType; + void* pNext; + VkExtent2D shadingRateTexelSize; + uint32_t shadingRatePaletteSize; + uint32_t shadingRateMaxCoarseSamples; +} VkPhysicalDeviceShadingRateImagePropertiesNV; + +typedef struct VkCoarseSampleLocationNV { + uint32_t pixelX; + uint32_t pixelY; + uint32_t sample; +} VkCoarseSampleLocationNV; + +typedef struct VkCoarseSampleOrderCustomNV { + VkShadingRatePaletteEntryNV shadingRate; + uint32_t sampleCount; + uint32_t sampleLocationCount; + const VkCoarseSampleLocationNV* pSampleLocations; +} VkCoarseSampleOrderCustomNV; + +typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCoarseSampleOrderTypeNV sampleOrderType; + uint32_t customSampleOrderCount; + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders; +} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkShadingRatePaletteNV* pShadingRatePalettes); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( + VkCommandBuffer commandBuffer, + VkCoarseSampleOrderTypeNV sampleOrderType, + uint32_t customSampleOrderCount, + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); +#endif + + +// VK_NV_ray_tracing is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_ray_tracing 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) +#define VK_NV_RAY_TRACING_SPEC_VERSION 3 +#define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" +#define VK_SHADER_UNUSED_KHR (~0U) +#define VK_SHADER_UNUSED_NV VK_SHADER_UNUSED_KHR + +typedef enum VkRayTracingShaderGroupTypeKHR { + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2, + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRayTracingShaderGroupTypeKHR; +typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV; + + +typedef enum VkGeometryTypeKHR { + VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0, + VK_GEOMETRY_TYPE_AABBS_KHR = 1, + VK_GEOMETRY_TYPE_INSTANCES_KHR = 2, + VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, + VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryTypeKHR; +typedef VkGeometryTypeKHR VkGeometryTypeNV; + + +typedef enum VkAccelerationStructureTypeKHR { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, + VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureTypeKHR; +typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV; + + +typedef enum VkCopyAccelerationStructureModeKHR { + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1, + VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2, + VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3, + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCopyAccelerationStructureModeKHR; +typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV; + + +typedef enum VkAccelerationStructureMemoryRequirementsTypeNV { + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMemoryRequirementsTypeNV; + +typedef enum VkGeometryFlagBitsKHR { + VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002, + VK_GEOMETRY_OPAQUE_BIT_NV = VK_GEOMETRY_OPAQUE_BIT_KHR, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, + VK_GEOMETRY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryFlagBitsKHR; +typedef VkFlags VkGeometryFlagsKHR; +typedef VkGeometryFlagsKHR VkGeometryFlagsNV; + +typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV; + + +typedef enum VkGeometryInstanceFlagBitsKHR { + VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001, + VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0x00000002, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, + VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT = 0x00000010, + VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT = 0x00000020, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryInstanceFlagBitsKHR; +typedef VkFlags VkGeometryInstanceFlagsKHR; +typedef VkGeometryInstanceFlagsKHR VkGeometryInstanceFlagsNV; + +typedef VkGeometryInstanceFlagBitsKHR VkGeometryInstanceFlagBitsNV; + + +typedef enum VkBuildAccelerationStructureFlagBitsKHR { + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, + VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0x00000020, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT = 0x00000040, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = 0x00000080, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = 0x00000100, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV = 0x00000200, +#endif + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR = 0x00000800, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureFlagBitsKHR; +typedef VkFlags VkBuildAccelerationStructureFlagsKHR; +typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; + +typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV; + +typedef struct VkRayTracingShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; +} VkRayTracingShaderGroupCreateInfoNV; + +typedef struct VkRayTracingPipelineCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoNV* pGroups; + uint32_t maxRecursionDepth; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoNV; + +typedef struct VkGeometryTrianglesNV { + VkStructureType sType; + const void* pNext; + VkBuffer vertexData; + VkDeviceSize vertexOffset; + uint32_t vertexCount; + VkDeviceSize vertexStride; + VkFormat vertexFormat; + VkBuffer indexData; + VkDeviceSize indexOffset; + uint32_t indexCount; + VkIndexType indexType; + VkBuffer transformData; + VkDeviceSize transformOffset; +} VkGeometryTrianglesNV; + +typedef struct VkGeometryAABBNV { + VkStructureType sType; + const void* pNext; + VkBuffer aabbData; + uint32_t numAABBs; + uint32_t stride; + VkDeviceSize offset; +} VkGeometryAABBNV; + +typedef struct VkGeometryDataNV { + VkGeometryTrianglesNV triangles; + VkGeometryAABBNV aabbs; +} VkGeometryDataNV; + +typedef struct VkGeometryNV { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkGeometryDataNV geometry; + VkGeometryFlagsKHR flags; +} VkGeometryNV; + +typedef struct VkAccelerationStructureInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeNV type; + VkBuildAccelerationStructureFlagsNV flags; + uint32_t instanceCount; + uint32_t geometryCount; + const VkGeometryNV* pGeometries; +} VkAccelerationStructureInfoNV; + +typedef struct VkAccelerationStructureCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceSize compactedSize; + VkAccelerationStructureInfoNV info; +} VkAccelerationStructureCreateInfoNV; + +typedef struct VkBindAccelerationStructureMemoryInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureNV accelerationStructure; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindAccelerationStructureMemoryInfoNV; + +typedef struct VkWriteDescriptorSetAccelerationStructureNV { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureNV* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureNV; + +typedef struct VkAccelerationStructureMemoryRequirementsInfoNV { VkStructureType sType; const void* pNext; VkAccelerationStructureMemoryRequirementsTypeNV type; VkAccelerationStructureNV accelerationStructure; } VkAccelerationStructureMemoryRequirementsInfoNV; -typedef struct VkPhysicalDeviceRayTracingPropertiesNV { +typedef struct VkPhysicalDeviceRayTracingPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxTriangleCount; + uint32_t maxDescriptorSetAccelerationStructures; +} VkPhysicalDeviceRayTracingPropertiesNV; + +typedef struct VkTransformMatrixKHR { + float matrix[3][4]; +} VkTransformMatrixKHR; + +typedef VkTransformMatrixKHR VkTransformMatrixNV; + +typedef struct VkAabbPositionsKHR { + float minX; + float minY; + float minZ; + float maxX; + float maxY; + float maxZ; +} VkAabbPositionsKHR; + +typedef VkAabbPositionsKHR VkAabbPositionsNV; + +typedef struct VkAccelerationStructureInstanceKHR { + VkTransformMatrixKHR transform; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureInstanceKHR; + +typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV( + VkDevice device, + const VkAccelerationStructureCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureNV* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV( + VkDevice device, + VkAccelerationStructureNV accelerationStructure, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( + VkDevice device, + const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2KHR* pMemoryRequirements); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV( + VkDevice device, + uint32_t bindInfoCount, + const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( + VkCommandBuffer commandBuffer, + const VkAccelerationStructureInfoNV* pInfo, + VkBuffer instanceData, + VkDeviceSize instanceOffset, + VkBool32 update, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, + VkBuffer scratch, + VkDeviceSize scratchOffset); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( + VkCommandBuffer commandBuffer, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, + VkCopyAccelerationStructureModeKHR mode); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( + VkCommandBuffer commandBuffer, + VkBuffer raygenShaderBindingTableBuffer, + VkDeviceSize raygenShaderBindingOffset, + VkBuffer missShaderBindingTableBuffer, + VkDeviceSize missShaderBindingOffset, + VkDeviceSize missShaderBindingStride, + VkBuffer hitShaderBindingTableBuffer, + VkDeviceSize hitShaderBindingOffset, + VkDeviceSize hitShaderBindingStride, + VkBuffer callableShaderBindingTableBuffer, + VkDeviceSize callableShaderBindingOffset, + VkDeviceSize callableShaderBindingStride, + uint32_t width, + uint32_t height, + uint32_t depth); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoNV* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV( + VkDevice device, + VkAccelerationStructureNV accelerationStructure, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureNV* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + +VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV( + VkDevice device, + VkPipeline pipeline, + uint32_t shader); +#endif + + +// VK_NV_representative_fragment_test is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_representative_fragment_test 1 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 2 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test" +typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 representativeFragmentTest; +} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV; + +typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 representativeFragmentTestEnable; +} VkPipelineRepresentativeFragmentTestStateCreateInfoNV; + + + +// VK_EXT_filter_cubic is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_filter_cubic 1 +#define VK_EXT_FILTER_CUBIC_SPEC_VERSION 3 +#define VK_EXT_FILTER_CUBIC_EXTENSION_NAME "VK_EXT_filter_cubic" +typedef struct VkPhysicalDeviceImageViewImageFormatInfoEXT { + VkStructureType sType; + void* pNext; + VkImageViewType imageViewType; +} VkPhysicalDeviceImageViewImageFormatInfoEXT; + +typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 filterCubic; + VkBool32 filterCubicMinmax; +} VkFilterCubicImageViewImageFormatPropertiesEXT; + + + +// VK_QCOM_render_pass_shader_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_render_pass_shader_resolve 1 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_SPEC_VERSION 4 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME "VK_QCOM_render_pass_shader_resolve" + + +// VK_EXT_global_priority is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_global_priority 1 +#define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 +#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" +typedef VkQueueGlobalPriorityKHR VkQueueGlobalPriorityEXT; + +typedef VkDeviceQueueGlobalPriorityCreateInfoKHR VkDeviceQueueGlobalPriorityCreateInfoEXT; + + + +// VK_EXT_external_memory_host is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_external_memory_host 1 +#define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host" +typedef struct VkImportMemoryHostPointerInfoEXT { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + void* pHostPointer; +} VkImportMemoryHostPointerInfoEXT; + +typedef struct VkMemoryHostPointerPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryHostPointerPropertiesEXT; + +typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize minImportedHostPointerAlignment; +} VkPhysicalDeviceExternalMemoryHostPropertiesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void* pHostPointer, + VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); +#endif + + +// VK_AMD_buffer_marker is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_buffer_marker 1 +#define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1 +#define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker" +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlagBits pipelineStage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); +#endif + + +// VK_AMD_pipeline_compiler_control is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_pipeline_compiler_control 1 +#define VK_AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION 1 +#define VK_AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME "VK_AMD_pipeline_compiler_control" + +typedef enum VkPipelineCompilerControlFlagBitsAMD { + VK_PIPELINE_COMPILER_CONTROL_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkPipelineCompilerControlFlagBitsAMD; +typedef VkFlags VkPipelineCompilerControlFlagsAMD; +typedef struct VkPipelineCompilerControlCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkPipelineCompilerControlFlagsAMD compilerControlFlags; +} VkPipelineCompilerControlCreateInfoAMD; + + + +// VK_EXT_calibrated_timestamps is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_calibrated_timestamps 1 +#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 2 +#define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps" + +typedef enum VkTimeDomainEXT { + VK_TIME_DOMAIN_DEVICE_EXT = 0, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2, + VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3, + VK_TIME_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF +} VkTimeDomainEXT; +typedef struct VkCalibratedTimestampInfoEXT { + VkStructureType sType; + const void* pNext; + VkTimeDomainEXT timeDomain; +} VkCalibratedTimestampInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)(VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains); +typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsEXT)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pTimeDomainCount, + VkTimeDomainEXT* pTimeDomains); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT( + VkDevice device, + uint32_t timestampCount, + const VkCalibratedTimestampInfoEXT* pTimestampInfos, + uint64_t* pTimestamps, + uint64_t* pMaxDeviation); +#endif + + +// VK_AMD_shader_core_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_core_properties 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 2 +#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties" +typedef struct VkPhysicalDeviceShaderCorePropertiesAMD { + VkStructureType sType; + void* pNext; + uint32_t shaderEngineCount; + uint32_t shaderArraysPerEngineCount; + uint32_t computeUnitsPerShaderArray; + uint32_t simdPerComputeUnit; + uint32_t wavefrontsPerSimd; + uint32_t wavefrontSize; + uint32_t sgprsPerSimd; + uint32_t minSgprAllocation; + uint32_t maxSgprAllocation; + uint32_t sgprAllocationGranularity; + uint32_t vgprsPerSimd; + uint32_t minVgprAllocation; + uint32_t maxVgprAllocation; + uint32_t vgprAllocationGranularity; +} VkPhysicalDeviceShaderCorePropertiesAMD; + + + +// VK_AMD_memory_overallocation_behavior is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_memory_overallocation_behavior 1 +#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1 +#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior" + +typedef enum VkMemoryOverallocationBehaviorAMD { + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF +} VkMemoryOverallocationBehaviorAMD; +typedef struct VkDeviceMemoryOverallocationCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkMemoryOverallocationBehaviorAMD overallocationBehavior; +} VkDeviceMemoryOverallocationCreateInfoAMD; + + + +// VK_EXT_vertex_attribute_divisor is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_vertex_attribute_divisor 1 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor" +typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxVertexAttribDivisor; +} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT; + +typedef struct VkVertexInputBindingDivisorDescriptionEXT { + uint32_t binding; + uint32_t divisor; +} VkVertexInputBindingDivisorDescriptionEXT; + +typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t vertexBindingDivisorCount; + const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors; +} VkPipelineVertexInputDivisorStateCreateInfoEXT; + +typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexAttributeInstanceRateDivisor; + VkBool32 vertexAttributeInstanceRateZeroDivisor; +} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT; + + + +// VK_EXT_pipeline_creation_feedback is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_creation_feedback 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback" +typedef VkPipelineCreationFeedbackFlagBits VkPipelineCreationFeedbackFlagBitsEXT; + +typedef VkPipelineCreationFeedbackFlags VkPipelineCreationFeedbackFlagsEXT; + +typedef VkPipelineCreationFeedbackCreateInfo VkPipelineCreationFeedbackCreateInfoEXT; + +typedef VkPipelineCreationFeedback VkPipelineCreationFeedbackEXT; + + + +// VK_NV_shader_subgroup_partitioned is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shader_subgroup_partitioned 1 +#define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1 +#define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned" + + +// VK_NV_compute_shader_derivatives is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_compute_shader_derivatives 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives" +typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 computeDerivativeGroupQuads; + VkBool32 computeDerivativeGroupLinear; +} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV; + + + +// VK_NV_mesh_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_mesh_shader 1 +#define VK_NV_MESH_SHADER_SPEC_VERSION 1 +#define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader" +typedef struct VkPhysicalDeviceMeshShaderFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 taskShader; + VkBool32 meshShader; +} VkPhysicalDeviceMeshShaderFeaturesNV; + +typedef struct VkPhysicalDeviceMeshShaderPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDrawMeshTasksCount; + uint32_t maxTaskWorkGroupInvocations; + uint32_t maxTaskWorkGroupSize[3]; + uint32_t maxTaskTotalMemorySize; + uint32_t maxTaskOutputCount; + uint32_t maxMeshWorkGroupInvocations; + uint32_t maxMeshWorkGroupSize[3]; + uint32_t maxMeshTotalMemorySize; + uint32_t maxMeshOutputVertices; + uint32_t maxMeshOutputPrimitives; + uint32_t maxMeshMultiviewViewCount; + uint32_t meshOutputPerVertexGranularity; + uint32_t meshOutputPerPrimitiveGranularity; +} VkPhysicalDeviceMeshShaderPropertiesNV; + +typedef struct VkDrawMeshTasksIndirectCommandNV { + uint32_t taskCount; + uint32_t firstTask; +} VkDrawMeshTasksIndirectCommandNV; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV( + VkCommandBuffer commandBuffer, + uint32_t taskCount, + uint32_t firstTask); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + + +// VK_NV_fragment_shader_barycentric is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_fragment_shader_barycentric 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric" +typedef VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV; + + + +// VK_NV_shader_image_footprint is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shader_image_footprint 1 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 2 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint" +typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 imageFootprint; +} VkPhysicalDeviceShaderImageFootprintFeaturesNV; + + + +// VK_NV_scissor_exclusive is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_scissor_exclusive 1 +#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 2 +#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive" +typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t exclusiveScissorCount; + const VkRect2D* pExclusiveScissors; +} VkPipelineViewportExclusiveScissorStateCreateInfoNV; + +typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 exclusiveScissor; +} VkPhysicalDeviceExclusiveScissorFeaturesNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorEnableNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkBool32* pExclusiveScissorEnables); +typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorEnableNV( + VkCommandBuffer commandBuffer, + uint32_t firstExclusiveScissor, + uint32_t exclusiveScissorCount, + const VkBool32* pExclusiveScissorEnables); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( + VkCommandBuffer commandBuffer, + uint32_t firstExclusiveScissor, + uint32_t exclusiveScissorCount, + const VkRect2D* pExclusiveScissors); +#endif + + +// VK_NV_device_diagnostic_checkpoints is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_device_diagnostic_checkpoints 1 +#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2 +#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints" +typedef struct VkQueueFamilyCheckpointPropertiesNV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags checkpointExecutionStageMask; +} VkQueueFamilyCheckpointPropertiesNV; + +typedef struct VkCheckpointDataNV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlagBits stage; + void* pCheckpointMarker; +} VkCheckpointDataNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCheckpointNV)(VkCommandBuffer commandBuffer, const void* pCheckpointMarker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV( + VkCommandBuffer commandBuffer, + const void* pCheckpointMarker); + +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointDataNV* pCheckpointData); +#endif + + +// VK_INTEL_shader_integer_functions2 is a preprocessor guard. Do not pass it to API calls. +#define VK_INTEL_shader_integer_functions2 1 +#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION 1 +#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME "VK_INTEL_shader_integer_functions2" +typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerFunctions2; +} VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL; + + + +// VK_INTEL_performance_query is a preprocessor guard. Do not pass it to API calls. +#define VK_INTEL_performance_query 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL) +#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2 +#define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query" + +typedef enum VkPerformanceConfigurationTypeINTEL { + VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0, + VK_PERFORMANCE_CONFIGURATION_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceConfigurationTypeINTEL; + +typedef enum VkQueryPoolSamplingModeINTEL { + VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0, + VK_QUERY_POOL_SAMPLING_MODE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkQueryPoolSamplingModeINTEL; + +typedef enum VkPerformanceOverrideTypeINTEL { + VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0, + VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1, + VK_PERFORMANCE_OVERRIDE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceOverrideTypeINTEL; + +typedef enum VkPerformanceParameterTypeINTEL { + VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0, + VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1, + VK_PERFORMANCE_PARAMETER_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceParameterTypeINTEL; + +typedef enum VkPerformanceValueTypeINTEL { + VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL = 0, + VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL = 1, + VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL = 2, + VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL = 3, + VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4, + VK_PERFORMANCE_VALUE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceValueTypeINTEL; +typedef union VkPerformanceValueDataINTEL { + uint32_t value32; + uint64_t value64; + float valueFloat; + VkBool32 valueBool; + const char* valueString; +} VkPerformanceValueDataINTEL; + +typedef struct VkPerformanceValueINTEL { + VkPerformanceValueTypeINTEL type; + VkPerformanceValueDataINTEL data; +} VkPerformanceValueINTEL; + +typedef struct VkInitializePerformanceApiInfoINTEL { + VkStructureType sType; + const void* pNext; + void* pUserData; +} VkInitializePerformanceApiInfoINTEL; + +typedef struct VkQueryPoolPerformanceQueryCreateInfoINTEL { + VkStructureType sType; + const void* pNext; + VkQueryPoolSamplingModeINTEL performanceCountersSampling; +} VkQueryPoolPerformanceQueryCreateInfoINTEL; + +typedef VkQueryPoolPerformanceQueryCreateInfoINTEL VkQueryPoolCreateInfoINTEL; + +typedef struct VkPerformanceMarkerInfoINTEL { + VkStructureType sType; + const void* pNext; + uint64_t marker; +} VkPerformanceMarkerInfoINTEL; + +typedef struct VkPerformanceStreamMarkerInfoINTEL { + VkStructureType sType; + const void* pNext; + uint32_t marker; +} VkPerformanceStreamMarkerInfoINTEL; + +typedef struct VkPerformanceOverrideInfoINTEL { + VkStructureType sType; + const void* pNext; + VkPerformanceOverrideTypeINTEL type; + VkBool32 enable; + uint64_t parameter; +} VkPerformanceOverrideInfoINTEL; + +typedef struct VkPerformanceConfigurationAcquireInfoINTEL { + VkStructureType sType; + const void* pNext; + VkPerformanceConfigurationTypeINTEL type; +} VkPerformanceConfigurationAcquireInfoINTEL; + +typedef VkResult (VKAPI_PTR *PFN_vkInitializePerformanceApiINTEL)(VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); +typedef void (VKAPI_PTR *PFN_vkUninitializePerformanceApiINTEL)(VkDevice device); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceStreamMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceOverrideINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo); +typedef VkResult (VKAPI_PTR *PFN_vkAcquirePerformanceConfigurationINTEL)(VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration); +typedef VkResult (VKAPI_PTR *PFN_vkReleasePerformanceConfigurationINTEL)(VkDevice device, VkPerformanceConfigurationINTEL configuration); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerformanceConfigurationINTEL)(VkQueue queue, VkPerformanceConfigurationINTEL configuration); +typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceParameterINTEL)(VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkInitializePerformanceApiINTEL( + VkDevice device, + const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); + +VKAPI_ATTR void VKAPI_CALL vkUninitializePerformanceApiINTEL( + VkDevice device); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceMarkerInfoINTEL* pMarkerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceStreamMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceOverrideINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceOverrideInfoINTEL* pOverrideInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquirePerformanceConfigurationINTEL( + VkDevice device, + const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, + VkPerformanceConfigurationINTEL* pConfiguration); + +VKAPI_ATTR VkResult VKAPI_CALL vkReleasePerformanceConfigurationINTEL( + VkDevice device, + VkPerformanceConfigurationINTEL configuration); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerformanceConfigurationINTEL( + VkQueue queue, + VkPerformanceConfigurationINTEL configuration); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceParameterINTEL( + VkDevice device, + VkPerformanceParameterTypeINTEL parameter, + VkPerformanceValueINTEL* pValue); +#endif + + +// VK_EXT_pci_bus_info is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pci_bus_info 1 +#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2 +#define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info" +typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t pciDomain; + uint32_t pciBus; + uint32_t pciDevice; + uint32_t pciFunction; +} VkPhysicalDevicePCIBusInfoPropertiesEXT; + + + +// VK_AMD_display_native_hdr is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_display_native_hdr 1 +#define VK_AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION 1 +#define VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME "VK_AMD_display_native_hdr" +typedef struct VkDisplayNativeHdrSurfaceCapabilitiesAMD { + VkStructureType sType; + void* pNext; + VkBool32 localDimmingSupport; +} VkDisplayNativeHdrSurfaceCapabilitiesAMD; + +typedef struct VkSwapchainDisplayNativeHdrCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkBool32 localDimmingEnable; +} VkSwapchainDisplayNativeHdrCreateInfoAMD; + +typedef void (VKAPI_PTR *PFN_vkSetLocalDimmingAMD)(VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD( + VkDevice device, + VkSwapchainKHR swapChain, + VkBool32 localDimmingEnable); +#endif + + +// VK_EXT_fragment_density_map is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_fragment_density_map 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 2 +#define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map" +typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMap; + VkBool32 fragmentDensityMapDynamic; + VkBool32 fragmentDensityMapNonSubsampledImages; +} VkPhysicalDeviceFragmentDensityMapFeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMapPropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentDensityTexelSize; + VkExtent2D maxFragmentDensityTexelSize; + VkBool32 fragmentDensityInvocations; +} VkPhysicalDeviceFragmentDensityMapPropertiesEXT; + +typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkAttachmentReference fragmentDensityMapAttachment; +} VkRenderPassFragmentDensityMapCreateInfoEXT; + + + +// VK_EXT_scalar_block_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_scalar_block_layout 1 +#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1 +#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout" +typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLayoutFeaturesEXT; + + + +// VK_GOOGLE_hlsl_functionality1 is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_hlsl_functionality1 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME + + +// VK_GOOGLE_decorate_string is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_decorate_string 1 +#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1 +#define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string" + + +// VK_EXT_subgroup_size_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_subgroup_size_control 1 +#define VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION 2 +#define VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME "VK_EXT_subgroup_size_control" +typedef VkPhysicalDeviceSubgroupSizeControlFeatures VkPhysicalDeviceSubgroupSizeControlFeaturesEXT; + +typedef VkPhysicalDeviceSubgroupSizeControlProperties VkPhysicalDeviceSubgroupSizeControlPropertiesEXT; + +typedef VkPipelineShaderStageRequiredSubgroupSizeCreateInfo VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT; + + + +// VK_AMD_shader_core_properties2 is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_core_properties2 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME "VK_AMD_shader_core_properties2" + +typedef enum VkShaderCorePropertiesFlagBitsAMD { + VK_SHADER_CORE_PROPERTIES_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkShaderCorePropertiesFlagBitsAMD; +typedef VkFlags VkShaderCorePropertiesFlagsAMD; +typedef struct VkPhysicalDeviceShaderCoreProperties2AMD { + VkStructureType sType; + void* pNext; + VkShaderCorePropertiesFlagsAMD shaderCoreFeatures; + uint32_t activeComputeUnitCount; +} VkPhysicalDeviceShaderCoreProperties2AMD; + + + +// VK_AMD_device_coherent_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_device_coherent_memory 1 +#define VK_AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION 1 +#define VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME "VK_AMD_device_coherent_memory" +typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 deviceCoherentMemory; +} VkPhysicalDeviceCoherentMemoryFeaturesAMD; + + + +// VK_EXT_shader_image_atomic_int64 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_image_atomic_int64 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME "VK_EXT_shader_image_atomic_int64" +typedef struct VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderImageInt64Atomics; + VkBool32 sparseImageInt64Atomics; +} VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT; + + + +// VK_EXT_memory_budget is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_memory_budget 1 +#define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 +#define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget" +typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize heapBudget[VK_MAX_MEMORY_HEAPS]; + VkDeviceSize heapUsage[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryBudgetPropertiesEXT; + + + +// VK_EXT_memory_priority is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_memory_priority 1 +#define VK_EXT_MEMORY_PRIORITY_SPEC_VERSION 1 +#define VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME "VK_EXT_memory_priority" +typedef struct VkPhysicalDeviceMemoryPriorityFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 memoryPriority; +} VkPhysicalDeviceMemoryPriorityFeaturesEXT; + +typedef struct VkMemoryPriorityAllocateInfoEXT { + VkStructureType sType; + const void* pNext; + float priority; +} VkMemoryPriorityAllocateInfoEXT; + + + +// VK_NV_dedicated_allocation_image_aliasing is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_dedicated_allocation_image_aliasing 1 +#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION 1 +#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME "VK_NV_dedicated_allocation_image_aliasing" +typedef struct VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 dedicatedAllocationImageAliasing; +} VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV; + + + +// VK_EXT_buffer_device_address is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_buffer_device_address 1 +#define VK_EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 2 +#define VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_EXT_buffer_device_address" +typedef struct VkPhysicalDeviceBufferDeviceAddressFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeaturesEXT; + +typedef VkPhysicalDeviceBufferDeviceAddressFeaturesEXT VkPhysicalDeviceBufferAddressFeaturesEXT; + +typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoEXT; + +typedef struct VkBufferDeviceAddressCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddress deviceAddress; +} VkBufferDeviceAddressCreateInfoEXT; + +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressEXT)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressEXT( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); +#endif + + +// VK_EXT_tooling_info is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_tooling_info 1 +#define VK_EXT_TOOLING_INFO_SPEC_VERSION 1 +#define VK_EXT_TOOLING_INFO_EXTENSION_NAME "VK_EXT_tooling_info" +typedef VkToolPurposeFlagBits VkToolPurposeFlagBitsEXT; + +typedef VkToolPurposeFlags VkToolPurposeFlagsEXT; + +typedef VkPhysicalDeviceToolProperties VkPhysicalDeviceToolPropertiesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolPropertiesEXT)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolPropertiesEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pToolCount, + VkPhysicalDeviceToolProperties* pToolProperties); +#endif + + +// VK_EXT_separate_stencil_usage is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_separate_stencil_usage 1 +#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1 +#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage" +typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; + + + +// VK_EXT_validation_features is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_validation_features 1 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 5 +#define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" + +typedef enum VkValidationFeatureEnableEXT { + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, + VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, + VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4, + VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureEnableEXT; + +typedef enum VkValidationFeatureDisableEXT { + VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0, + VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1, + VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2, + VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3, + VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4, + VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5, + VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6, + VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT = 7, + VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureDisableEXT; +typedef struct VkValidationFeaturesEXT { + VkStructureType sType; + const void* pNext; + uint32_t enabledValidationFeatureCount; + const VkValidationFeatureEnableEXT* pEnabledValidationFeatures; + uint32_t disabledValidationFeatureCount; + const VkValidationFeatureDisableEXT* pDisabledValidationFeatures; +} VkValidationFeaturesEXT; + + + +// VK_NV_cooperative_matrix is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cooperative_matrix 1 +#define VK_NV_COOPERATIVE_MATRIX_SPEC_VERSION 1 +#define VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_NV_cooperative_matrix" +typedef VkComponentTypeKHR VkComponentTypeNV; + +typedef VkScopeKHR VkScopeNV; + +typedef struct VkCooperativeMatrixPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t MSize; + uint32_t NSize; + uint32_t KSize; + VkComponentTypeNV AType; + VkComponentTypeNV BType; + VkComponentTypeNV CType; + VkComponentTypeNV DType; + VkScopeNV scope; +} VkCooperativeMatrixPropertiesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrix; + VkBool32 cooperativeMatrixRobustBufferAccess; +} VkPhysicalDeviceCooperativeMatrixFeaturesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesNV { + VkStructureType sType; + void* pNext; + VkShaderStageFlags cooperativeMatrixSupportedStages; +} VkPhysicalDeviceCooperativeMatrixPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkCooperativeMatrixPropertiesNV* pProperties); +#endif + + +// VK_NV_coverage_reduction_mode is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_coverage_reduction_mode 1 +#define VK_NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION 1 +#define VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME "VK_NV_coverage_reduction_mode" + +typedef enum VkCoverageReductionModeNV { + VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0, + VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1, + VK_COVERAGE_REDUCTION_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoverageReductionModeNV; +typedef VkFlags VkPipelineCoverageReductionStateCreateFlagsNV; +typedef struct VkPhysicalDeviceCoverageReductionModeFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 coverageReductionMode; +} VkPhysicalDeviceCoverageReductionModeFeaturesNV; + +typedef struct VkPipelineCoverageReductionStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageReductionStateCreateFlagsNV flags; + VkCoverageReductionModeNV coverageReductionMode; +} VkPipelineCoverageReductionStateCreateInfoNV; + +typedef struct VkFramebufferMixedSamplesCombinationNV { + VkStructureType sType; + void* pNext; + VkCoverageReductionModeNV coverageReductionMode; + VkSampleCountFlagBits rasterizationSamples; + VkSampleCountFlags depthStencilSamples; + VkSampleCountFlags colorSamples; +} VkFramebufferMixedSamplesCombinationNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( + VkPhysicalDevice physicalDevice, + uint32_t* pCombinationCount, + VkFramebufferMixedSamplesCombinationNV* pCombinations); +#endif + + +// VK_EXT_fragment_shader_interlock is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_fragment_shader_interlock 1 +#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME "VK_EXT_fragment_shader_interlock" +typedef struct VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderSampleInterlock; + VkBool32 fragmentShaderPixelInterlock; + VkBool32 fragmentShaderShadingRateInterlock; +} VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT; + + + +// VK_EXT_ycbcr_image_arrays is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_ycbcr_image_arrays 1 +#define VK_EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME "VK_EXT_ycbcr_image_arrays" +typedef struct VkPhysicalDeviceYcbcrImageArraysFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 ycbcrImageArrays; +} VkPhysicalDeviceYcbcrImageArraysFeaturesEXT; + + + +// VK_EXT_provoking_vertex is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_provoking_vertex 1 +#define VK_EXT_PROVOKING_VERTEX_SPEC_VERSION 1 +#define VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME "VK_EXT_provoking_vertex" + +typedef enum VkProvokingVertexModeEXT { + VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0, + VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1, + VK_PROVOKING_VERTEX_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkProvokingVertexModeEXT; +typedef struct VkPhysicalDeviceProvokingVertexFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexLast; + VkBool32 transformFeedbackPreservesProvokingVertex; +} VkPhysicalDeviceProvokingVertexFeaturesEXT; + +typedef struct VkPhysicalDeviceProvokingVertexPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexModePerPipeline; + VkBool32 transformFeedbackPreservesTriangleFanProvokingVertex; +} VkPhysicalDeviceProvokingVertexPropertiesEXT; + +typedef struct VkPipelineRasterizationProvokingVertexStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkProvokingVertexModeEXT provokingVertexMode; +} VkPipelineRasterizationProvokingVertexStateCreateInfoEXT; + + + +// VK_EXT_headless_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_headless_surface 1 +#define VK_EXT_HEADLESS_SURFACE_SPEC_VERSION 1 +#define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" +typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT; +typedef struct VkHeadlessSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkHeadlessSurfaceCreateFlagsEXT flags; +} VkHeadlessSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT( + VkInstance instance, + const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + + +// VK_EXT_line_rasterization is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_line_rasterization 1 +#define VK_EXT_LINE_RASTERIZATION_SPEC_VERSION 1 +#define VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME "VK_EXT_line_rasterization" + +typedef enum VkLineRasterizationModeEXT { + VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = 0, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = 1, + VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = 2, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = 3, + VK_LINE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkLineRasterizationModeEXT; +typedef struct VkPhysicalDeviceLineRasterizationFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 rectangularLines; + VkBool32 bresenhamLines; + VkBool32 smoothLines; + VkBool32 stippledRectangularLines; + VkBool32 stippledBresenhamLines; + VkBool32 stippledSmoothLines; +} VkPhysicalDeviceLineRasterizationFeaturesEXT; + +typedef struct VkPhysicalDeviceLineRasterizationPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t lineSubPixelPrecisionBits; +} VkPhysicalDeviceLineRasterizationPropertiesEXT; + +typedef struct VkPipelineRasterizationLineStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkLineRasterizationModeEXT lineRasterizationMode; + VkBool32 stippledLineEnable; + uint32_t lineStippleFactor; + uint16_t lineStipplePattern; +} VkPipelineRasterizationLineStateCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEXT)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern); +#endif + + +// VK_EXT_shader_atomic_float is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_atomic_float 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME "VK_EXT_shader_atomic_float" +typedef struct VkPhysicalDeviceShaderAtomicFloatFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat32Atomics; + VkBool32 shaderBufferFloat32AtomicAdd; + VkBool32 shaderBufferFloat64Atomics; + VkBool32 shaderBufferFloat64AtomicAdd; + VkBool32 shaderSharedFloat32Atomics; + VkBool32 shaderSharedFloat32AtomicAdd; + VkBool32 shaderSharedFloat64Atomics; + VkBool32 shaderSharedFloat64AtomicAdd; + VkBool32 shaderImageFloat32Atomics; + VkBool32 shaderImageFloat32AtomicAdd; + VkBool32 sparseImageFloat32Atomics; + VkBool32 sparseImageFloat32AtomicAdd; +} VkPhysicalDeviceShaderAtomicFloatFeaturesEXT; + + + +// VK_EXT_host_query_reset is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_host_query_reset 1 +#define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1 +#define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME "VK_EXT_host_query_reset" +typedef VkPhysicalDeviceHostQueryResetFeatures VkPhysicalDeviceHostQueryResetFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkResetQueryPoolEXT)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); +#endif + + +// VK_EXT_index_type_uint8 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_index_type_uint8 1 +#define VK_EXT_INDEX_TYPE_UINT8_SPEC_VERSION 1 +#define VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME "VK_EXT_index_type_uint8" +typedef struct VkPhysicalDeviceIndexTypeUint8FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 indexTypeUint8; +} VkPhysicalDeviceIndexTypeUint8FeaturesEXT; + + + +// VK_EXT_extended_dynamic_state is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_extended_dynamic_state 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_extended_dynamic_state" +typedef struct VkPhysicalDeviceExtendedDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState; +} VkPhysicalDeviceExtendedDynamicStateFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCullModeEXT)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFaceEXT)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopologyEXT)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2EXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOpEXT)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOpEXT)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCullModeEXT( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFaceEXT( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopologyEXT( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOpEXT( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp); +#endif + + +// VK_EXT_host_image_copy is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_host_image_copy 1 +#define VK_EXT_HOST_IMAGE_COPY_SPEC_VERSION 1 +#define VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME "VK_EXT_host_image_copy" + +typedef enum VkHostImageCopyFlagBitsEXT { + VK_HOST_IMAGE_COPY_MEMCPY_EXT = 0x00000001, + VK_HOST_IMAGE_COPY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkHostImageCopyFlagBitsEXT; +typedef VkFlags VkHostImageCopyFlagsEXT; +typedef struct VkPhysicalDeviceHostImageCopyFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 hostImageCopy; +} VkPhysicalDeviceHostImageCopyFeaturesEXT; + +typedef struct VkPhysicalDeviceHostImageCopyPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t copySrcLayoutCount; + VkImageLayout* pCopySrcLayouts; + uint32_t copyDstLayoutCount; + VkImageLayout* pCopyDstLayouts; + uint8_t optimalTilingLayoutUUID[VK_UUID_SIZE]; + VkBool32 identicalMemoryTypeRequirements; +} VkPhysicalDeviceHostImageCopyPropertiesEXT; + +typedef struct VkMemoryToImageCopyEXT { + VkStructureType sType; + const void* pNext; + const void* pHostPointer; + uint32_t memoryRowLength; + uint32_t memoryImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkMemoryToImageCopyEXT; + +typedef struct VkImageToMemoryCopyEXT { + VkStructureType sType; + const void* pNext; + void* pHostPointer; + uint32_t memoryRowLength; + uint32_t memoryImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkImageToMemoryCopyEXT; + +typedef struct VkCopyMemoryToImageInfoEXT { + VkStructureType sType; + const void* pNext; + VkHostImageCopyFlagsEXT flags; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkMemoryToImageCopyEXT* pRegions; +} VkCopyMemoryToImageInfoEXT; + +typedef struct VkCopyImageToMemoryInfoEXT { + VkStructureType sType; + const void* pNext; + VkHostImageCopyFlagsEXT flags; + VkImage srcImage; + VkImageLayout srcImageLayout; + uint32_t regionCount; + const VkImageToMemoryCopyEXT* pRegions; +} VkCopyImageToMemoryInfoEXT; + +typedef struct VkCopyImageToImageInfoEXT { + VkStructureType sType; + const void* pNext; + VkHostImageCopyFlagsEXT flags; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2* pRegions; +} VkCopyImageToImageInfoEXT; + +typedef struct VkHostImageLayoutTransitionInfoEXT { + VkStructureType sType; + const void* pNext; + VkImage image; + VkImageLayout oldLayout; + VkImageLayout newLayout; + VkImageSubresourceRange subresourceRange; +} VkHostImageLayoutTransitionInfoEXT; + +typedef struct VkSubresourceHostMemcpySizeEXT { VkStructureType sType; void* pNext; - uint32_t shaderGroupHandleSize; - uint32_t maxRecursionDepth; - uint32_t maxShaderGroupStride; - uint32_t shaderGroupBaseAlignment; - uint64_t maxGeometryCount; - uint64_t maxInstanceCount; - uint64_t maxTriangleCount; - uint32_t maxDescriptorSetAccelerationStructures; -} VkPhysicalDeviceRayTracingPropertiesNV; + VkDeviceSize size; +} VkSubresourceHostMemcpySizeEXT; -typedef struct VkTransformMatrixKHR { - float matrix[3][4]; -} VkTransformMatrixKHR; +typedef struct VkHostImageCopyDevicePerformanceQueryEXT { + VkStructureType sType; + void* pNext; + VkBool32 optimalDeviceAccess; + VkBool32 identicalMemoryLayout; +} VkHostImageCopyDevicePerformanceQueryEXT; -typedef VkTransformMatrixKHR VkTransformMatrixNV; +typedef VkSubresourceLayout2KHR VkSubresourceLayout2EXT; -typedef struct VkAabbPositionsKHR { - float minX; - float minY; - float minZ; - float maxX; - float maxY; - float maxZ; -} VkAabbPositionsKHR; +typedef VkImageSubresource2KHR VkImageSubresource2EXT; -typedef VkAabbPositionsKHR VkAabbPositionsNV; +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToImageEXT)(VkDevice device, const VkCopyMemoryToImageInfoEXT* pCopyMemoryToImageInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToMemoryEXT)(VkDevice device, const VkCopyImageToMemoryInfoEXT* pCopyImageToMemoryInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToImageEXT)(VkDevice device, const VkCopyImageToImageInfoEXT* pCopyImageToImageInfo); +typedef VkResult (VKAPI_PTR *PFN_vkTransitionImageLayoutEXT)(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfoEXT* pTransitions); +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2EXT)(VkDevice device, VkImage image, const VkImageSubresource2KHR* pSubresource, VkSubresourceLayout2KHR* pLayout); -typedef struct VkAccelerationStructureInstanceKHR { - VkTransformMatrixKHR transform; - uint32_t instanceCustomIndex:24; - uint32_t mask:8; - uint32_t instanceShaderBindingTableRecordOffset:24; - VkGeometryInstanceFlagsKHR flags:8; - uint64_t accelerationStructureReference; -} VkAccelerationStructureInstanceKHR; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToImageEXT( + VkDevice device, + const VkCopyMemoryToImageInfoEXT* pCopyMemoryToImageInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToMemoryEXT( + VkDevice device, + const VkCopyImageToMemoryInfoEXT* pCopyImageToMemoryInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToImageEXT( + VkDevice device, + const VkCopyImageToImageInfoEXT* pCopyImageToImageInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkTransitionImageLayoutEXT( + VkDevice device, + uint32_t transitionCount, + const VkHostImageLayoutTransitionInfoEXT* pTransitions); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2EXT( + VkDevice device, + VkImage image, + const VkImageSubresource2KHR* pSubresource, + VkSubresourceLayout2KHR* pLayout); +#endif + + +// VK_EXT_shader_atomic_float2 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_atomic_float2 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME "VK_EXT_shader_atomic_float2" +typedef struct VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat16Atomics; + VkBool32 shaderBufferFloat16AtomicAdd; + VkBool32 shaderBufferFloat16AtomicMinMax; + VkBool32 shaderBufferFloat32AtomicMinMax; + VkBool32 shaderBufferFloat64AtomicMinMax; + VkBool32 shaderSharedFloat16Atomics; + VkBool32 shaderSharedFloat16AtomicAdd; + VkBool32 shaderSharedFloat16AtomicMinMax; + VkBool32 shaderSharedFloat32AtomicMinMax; + VkBool32 shaderSharedFloat64AtomicMinMax; + VkBool32 shaderImageFloat32AtomicMinMax; + VkBool32 sparseImageFloat32AtomicMinMax; +} VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT; + + + +// VK_EXT_surface_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_surface_maintenance1 1 +#define VK_EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME "VK_EXT_surface_maintenance1" + +typedef enum VkPresentScalingFlagBitsEXT { + VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT = 0x00000001, + VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT = 0x00000002, + VK_PRESENT_SCALING_STRETCH_BIT_EXT = 0x00000004, + VK_PRESENT_SCALING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPresentScalingFlagBitsEXT; +typedef VkFlags VkPresentScalingFlagsEXT; + +typedef enum VkPresentGravityFlagBitsEXT { + VK_PRESENT_GRAVITY_MIN_BIT_EXT = 0x00000001, + VK_PRESENT_GRAVITY_MAX_BIT_EXT = 0x00000002, + VK_PRESENT_GRAVITY_CENTERED_BIT_EXT = 0x00000004, + VK_PRESENT_GRAVITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPresentGravityFlagBitsEXT; +typedef VkFlags VkPresentGravityFlagsEXT; +typedef struct VkSurfacePresentModeEXT { + VkStructureType sType; + void* pNext; + VkPresentModeKHR presentMode; +} VkSurfacePresentModeEXT; + +typedef struct VkSurfacePresentScalingCapabilitiesEXT { + VkStructureType sType; + void* pNext; + VkPresentScalingFlagsEXT supportedPresentScaling; + VkPresentGravityFlagsEXT supportedPresentGravityX; + VkPresentGravityFlagsEXT supportedPresentGravityY; + VkExtent2D minScaledImageExtent; + VkExtent2D maxScaledImageExtent; +} VkSurfacePresentScalingCapabilitiesEXT; + +typedef struct VkSurfacePresentModeCompatibilityEXT { + VkStructureType sType; + void* pNext; + uint32_t presentModeCount; + VkPresentModeKHR* pPresentModes; +} VkSurfacePresentModeCompatibilityEXT; + + + +// VK_EXT_swapchain_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_swapchain_maintenance1 1 +#define VK_EXT_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME "VK_EXT_swapchain_maintenance1" +typedef struct VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 swapchainMaintenance1; +} VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT; + +typedef struct VkSwapchainPresentFenceInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkFence* pFences; +} VkSwapchainPresentFenceInfoEXT; + +typedef struct VkSwapchainPresentModesCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t presentModeCount; + const VkPresentModeKHR* pPresentModes; +} VkSwapchainPresentModesCreateInfoEXT; + +typedef struct VkSwapchainPresentModeInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentModeKHR* pPresentModes; +} VkSwapchainPresentModeInfoEXT; + +typedef struct VkSwapchainPresentScalingCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPresentScalingFlagsEXT scalingBehavior; + VkPresentGravityFlagsEXT presentGravityX; + VkPresentGravityFlagsEXT presentGravityY; +} VkSwapchainPresentScalingCreateInfoEXT; + +typedef struct VkReleaseSwapchainImagesInfoEXT { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint32_t imageIndexCount; + const uint32_t* pImageIndices; +} VkReleaseSwapchainImagesInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkReleaseSwapchainImagesEXT)(VkDevice device, const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseSwapchainImagesEXT( + VkDevice device, + const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo); +#endif + + +// VK_EXT_shader_demote_to_helper_invocation is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_demote_to_helper_invocation 1 +#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1 +#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation" +typedef VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT; + + + +// VK_NV_device_generated_commands is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_device_generated_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV) +#define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 +#define VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NV_device_generated_commands" + +typedef enum VkIndirectCommandsTokenTypeNV { + VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV = 1000328000, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV = 1000428003, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV = 1000428004, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsTokenTypeNV; + +typedef enum VkIndirectStateFlagBitsNV { + VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001, + VK_INDIRECT_STATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectStateFlagBitsNV; +typedef VkFlags VkIndirectStateFlagsNV; + +typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV { + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsLayoutUsageFlagBitsNV; +typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV; +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxGraphicsShaderGroupCount; + uint32_t maxIndirectSequenceCount; + uint32_t maxIndirectCommandsTokenCount; + uint32_t maxIndirectCommandsStreamCount; + uint32_t maxIndirectCommandsTokenOffset; + uint32_t maxIndirectCommandsStreamStride; + uint32_t minSequencesCountBufferOffsetAlignment; + uint32_t minSequencesIndexBufferOffsetAlignment; + uint32_t minIndirectCommandsBufferOffsetAlignment; +} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV; + +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 deviceGeneratedCommands; +} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV; + +typedef struct VkGraphicsShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; +} VkGraphicsShaderGroupCreateInfoNV; + +typedef struct VkGraphicsPipelineShaderGroupsCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t groupCount; + const VkGraphicsShaderGroupCreateInfoNV* pGroups; + uint32_t pipelineCount; + const VkPipeline* pPipelines; +} VkGraphicsPipelineShaderGroupsCreateInfoNV; + +typedef struct VkBindShaderGroupIndirectCommandNV { + uint32_t groupIndex; +} VkBindShaderGroupIndirectCommandNV; + +typedef struct VkBindIndexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + VkIndexType indexType; +} VkBindIndexBufferIndirectCommandNV; + +typedef struct VkBindVertexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + uint32_t stride; +} VkBindVertexBufferIndirectCommandNV; + +typedef struct VkSetStateFlagsIndirectCommandNV { + uint32_t data; +} VkSetStateFlagsIndirectCommandNV; + +typedef struct VkIndirectCommandsStreamNV { + VkBuffer buffer; + VkDeviceSize offset; +} VkIndirectCommandsStreamNV; + +typedef struct VkIndirectCommandsLayoutTokenNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsTokenTypeNV tokenType; + uint32_t stream; + uint32_t offset; + uint32_t vertexBindingUnit; + VkBool32 vertexDynamicStride; + VkPipelineLayout pushconstantPipelineLayout; + VkShaderStageFlags pushconstantShaderStageFlags; + uint32_t pushconstantOffset; + uint32_t pushconstantSize; + VkIndirectStateFlagsNV indirectStateFlags; + uint32_t indexTypeCount; + const VkIndexType* pIndexTypes; + const uint32_t* pIndexTypeValues; +} VkIndirectCommandsLayoutTokenNV; + +typedef struct VkIndirectCommandsLayoutCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsLayoutUsageFlagsNV flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t tokenCount; + const VkIndirectCommandsLayoutTokenNV* pTokens; + uint32_t streamCount; + const uint32_t* pStreamStrides; +} VkIndirectCommandsLayoutCreateInfoNV; + +typedef struct VkGeneratedCommandsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t streamCount; + const VkIndirectCommandsStreamNV* pStreams; + uint32_t sequencesCount; + VkBuffer preprocessBuffer; + VkDeviceSize preprocessOffset; + VkDeviceSize preprocessSize; + VkBuffer sequencesCountBuffer; + VkDeviceSize sequencesCountOffset; + VkBuffer sequencesIndexBuffer; + VkDeviceSize sequencesIndexOffset; +} VkGeneratedCommandsInfoNV; -typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; +typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t maxSequencesCount; +} VkGeneratedCommandsMemoryRequirementsInfoNV; -typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); -typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); -typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); -typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); -typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); -typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth); -typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); -typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); -typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); -typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); -typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader); +typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsNV)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsNV)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsNV)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipelineShaderGroupNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV( - VkDevice device, - const VkAccelerationStructureCreateInfoNV* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkAccelerationStructureNV* pAccelerationStructure); - -VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV( - VkDevice device, - VkAccelerationStructureNV accelerationStructure, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( - VkDevice device, - const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, - VkMemoryRequirements2KHR* pMemoryRequirements); - -VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV( +VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV( VkDevice device, - uint32_t bindInfoCount, - const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); + const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2* pMemoryRequirements); -VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( +VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV( VkCommandBuffer commandBuffer, - const VkAccelerationStructureInfoNV* pInfo, - VkBuffer instanceData, - VkDeviceSize instanceOffset, - VkBool32 update, - VkAccelerationStructureNV dst, - VkAccelerationStructureNV src, - VkBuffer scratch, - VkDeviceSize scratchOffset); + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV( VkCommandBuffer commandBuffer, - VkAccelerationStructureNV dst, - VkAccelerationStructureNV src, - VkCopyAccelerationStructureModeKHR mode); + VkBool32 isPreprocessed, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV( VkCommandBuffer commandBuffer, - VkBuffer raygenShaderBindingTableBuffer, - VkDeviceSize raygenShaderBindingOffset, - VkBuffer missShaderBindingTableBuffer, - VkDeviceSize missShaderBindingOffset, - VkDeviceSize missShaderBindingStride, - VkBuffer hitShaderBindingTableBuffer, - VkDeviceSize hitShaderBindingOffset, - VkDeviceSize hitShaderBindingStride, - VkBuffer callableShaderBindingTableBuffer, - VkDeviceSize callableShaderBindingOffset, - VkDeviceSize callableShaderBindingStride, - uint32_t width, - uint32_t height, - uint32_t depth); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( - VkDevice device, - VkPipelineCache pipelineCache, - uint32_t createInfoCount, - const VkRayTracingPipelineCreateInfoNV* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkPipeline* pPipelines); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( - VkDevice device, - VkPipeline pipeline, - uint32_t firstGroup, - uint32_t groupCount, - size_t dataSize, - void* pData); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( - VkDevice device, + VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, - uint32_t firstGroup, - uint32_t groupCount, - size_t dataSize, - void* pData); + uint32_t groupIndex); -VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV( +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV( VkDevice device, - VkAccelerationStructureNV accelerationStructure, - size_t dataSize, - void* pData); - -VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( - VkCommandBuffer commandBuffer, - uint32_t accelerationStructureCount, - const VkAccelerationStructureNV* pAccelerationStructures, - VkQueryType queryType, - VkQueryPool queryPool, - uint32_t firstQuery); + const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); -VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV( +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( VkDevice device, - VkPipeline pipeline, - uint32_t shader); + VkIndirectCommandsLayoutNV indirectCommandsLayout, + const VkAllocationCallbacks* pAllocator); #endif -#define VK_NV_representative_fragment_test 1 -#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 2 -#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test" -typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV { +// VK_NV_inherited_viewport_scissor is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_inherited_viewport_scissor 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME "VK_NV_inherited_viewport_scissor" +typedef struct VkPhysicalDeviceInheritedViewportScissorFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 representativeFragmentTest; -} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV; - -typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 representativeFragmentTestEnable; -} VkPipelineRepresentativeFragmentTestStateCreateInfoNV; + VkBool32 inheritedViewportScissor2D; +} VkPhysicalDeviceInheritedViewportScissorFeaturesNV; +typedef struct VkCommandBufferInheritanceViewportScissorInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportScissor2D; + uint32_t viewportDepthCount; + const VkViewport* pViewportDepths; +} VkCommandBufferInheritanceViewportScissorInfoNV; -#define VK_EXT_filter_cubic 1 -#define VK_EXT_FILTER_CUBIC_SPEC_VERSION 3 -#define VK_EXT_FILTER_CUBIC_EXTENSION_NAME "VK_EXT_filter_cubic" -typedef struct VkPhysicalDeviceImageViewImageFormatInfoEXT { - VkStructureType sType; - void* pNext; - VkImageViewType imageViewType; -} VkPhysicalDeviceImageViewImageFormatInfoEXT; -typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT { +// VK_EXT_texel_buffer_alignment is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_texel_buffer_alignment 1 +#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 +#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" +typedef struct VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 filterCubic; - VkBool32 filterCubicMinmax; -} VkFilterCubicImageViewImageFormatPropertiesEXT; - + VkBool32 texelBufferAlignment; +} VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT; +typedef VkPhysicalDeviceTexelBufferAlignmentProperties VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT; -#define VK_QCOM_render_pass_shader_resolve 1 -#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_SPEC_VERSION 4 -#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME "VK_QCOM_render_pass_shader_resolve" -#define VK_EXT_global_priority 1 -#define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 -#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" +// VK_QCOM_render_pass_transform is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_render_pass_transform 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 3 +#define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" +typedef struct VkRenderPassTransformBeginInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkRenderPassTransformBeginInfoQCOM; -typedef enum VkQueueGlobalPriorityEXT { - VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = 128, - VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = 256, - VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = 512, - VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = 1024, - VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM_EXT = 0x7FFFFFFF -} VkQueueGlobalPriorityEXT; -typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkQueueGlobalPriorityEXT globalPriority; -} VkDeviceQueueGlobalPriorityCreateInfoEXT; +typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; + VkRect2D renderArea; +} VkCommandBufferInheritanceRenderPassTransformInfoQCOM; -#define VK_EXT_external_memory_host 1 -#define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1 -#define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host" -typedef struct VkImportMemoryHostPointerInfoEXT { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagBits handleType; - void* pHostPointer; -} VkImportMemoryHostPointerInfoEXT; +// VK_EXT_depth_bias_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_bias_control 1 +#define VK_EXT_DEPTH_BIAS_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME "VK_EXT_depth_bias_control" -typedef struct VkMemoryHostPointerPropertiesEXT { +typedef enum VkDepthBiasRepresentationEXT { + VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT = 0, + VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT = 1, + VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT = 2, + VK_DEPTH_BIAS_REPRESENTATION_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDepthBiasRepresentationEXT; +typedef struct VkPhysicalDeviceDepthBiasControlFeaturesEXT { VkStructureType sType; void* pNext; - uint32_t memoryTypeBits; -} VkMemoryHostPointerPropertiesEXT; + VkBool32 depthBiasControl; + VkBool32 leastRepresentableValueForceUnormRepresentation; + VkBool32 floatRepresentation; + VkBool32 depthBiasExact; +} VkPhysicalDeviceDepthBiasControlFeaturesEXT; -typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT { +typedef struct VkDepthBiasInfoEXT { VkStructureType sType; - void* pNext; - VkDeviceSize minImportedHostPointerAlignment; -} VkPhysicalDeviceExternalMemoryHostPropertiesEXT; - -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT( - VkDevice device, - VkExternalMemoryHandleTypeFlagBits handleType, - const void* pHostPointer, - VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); -#endif + const void* pNext; + float depthBiasConstantFactor; + float depthBiasClamp; + float depthBiasSlopeFactor; +} VkDepthBiasInfoEXT; +typedef struct VkDepthBiasRepresentationInfoEXT { + VkStructureType sType; + const void* pNext; + VkDepthBiasRepresentationEXT depthBiasRepresentation; + VkBool32 depthBiasExact; +} VkDepthBiasRepresentationInfoEXT; -#define VK_AMD_buffer_marker 1 -#define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1 -#define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker" -typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias2EXT)(VkCommandBuffer commandBuffer, const VkDepthBiasInfoEXT* pDepthBiasInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD( +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias2EXT( VkCommandBuffer commandBuffer, - VkPipelineStageFlagBits pipelineStage, - VkBuffer dstBuffer, - VkDeviceSize dstOffset, - uint32_t marker); + const VkDepthBiasInfoEXT* pDepthBiasInfo); #endif -#define VK_AMD_pipeline_compiler_control 1 -#define VK_AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION 1 -#define VK_AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME "VK_AMD_pipeline_compiler_control" +// VK_EXT_device_memory_report is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_device_memory_report 1 +#define VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME "VK_EXT_device_memory_report" + +typedef enum VkDeviceMemoryReportEventTypeEXT { + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT = 0, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT = 1, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT = 2, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT = 3, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT = 4, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceMemoryReportEventTypeEXT; +typedef VkFlags VkDeviceMemoryReportFlagsEXT; +typedef struct VkPhysicalDeviceDeviceMemoryReportFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 deviceMemoryReport; +} VkPhysicalDeviceDeviceMemoryReportFeaturesEXT; -typedef enum VkPipelineCompilerControlFlagBitsAMD { - VK_PIPELINE_COMPILER_CONTROL_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF -} VkPipelineCompilerControlFlagBitsAMD; -typedef VkFlags VkPipelineCompilerControlFlagsAMD; -typedef struct VkPipelineCompilerControlCreateInfoAMD { - VkStructureType sType; - const void* pNext; - VkPipelineCompilerControlFlagsAMD compilerControlFlags; -} VkPipelineCompilerControlCreateInfoAMD; +typedef struct VkDeviceMemoryReportCallbackDataEXT { + VkStructureType sType; + void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + VkDeviceMemoryReportEventTypeEXT type; + uint64_t memoryObjectId; + VkDeviceSize size; + VkObjectType objectType; + uint64_t objectHandle; + uint32_t heapIndex; +} VkDeviceMemoryReportCallbackDataEXT; +typedef void (VKAPI_PTR *PFN_vkDeviceMemoryReportCallbackEXT)( + const VkDeviceMemoryReportCallbackDataEXT* pCallbackData, + void* pUserData); +typedef struct VkDeviceDeviceMemoryReportCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback; + void* pUserData; +} VkDeviceDeviceMemoryReportCreateInfoEXT; -#define VK_EXT_calibrated_timestamps 1 -#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 2 -#define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps" -typedef enum VkTimeDomainEXT { - VK_TIME_DOMAIN_DEVICE_EXT = 0, - VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1, - VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2, - VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3, - VK_TIME_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF -} VkTimeDomainEXT; -typedef struct VkCalibratedTimestampInfoEXT { - VkStructureType sType; - const void* pNext; - VkTimeDomainEXT timeDomain; -} VkCalibratedTimestampInfoEXT; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)(VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains); -typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsEXT)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation); +// VK_EXT_acquire_drm_display is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_acquire_drm_display 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_drm_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, uint32_t connectorId, VkDisplayKHR* display); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireDrmDisplayEXT( VkPhysicalDevice physicalDevice, - uint32_t* pTimeDomainCount, - VkTimeDomainEXT* pTimeDomains); + int32_t drmFd, + VkDisplayKHR display); -VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT( - VkDevice device, - uint32_t timestampCount, - const VkCalibratedTimestampInfoEXT* pTimestampInfos, - uint64_t* pTimestamps, - uint64_t* pMaxDeviation); +VKAPI_ATTR VkResult VKAPI_CALL vkGetDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + uint32_t connectorId, + VkDisplayKHR* display); #endif -#define VK_AMD_shader_core_properties 1 -#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 2 -#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties" -typedef struct VkPhysicalDeviceShaderCorePropertiesAMD { +// VK_EXT_robustness2 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_robustness2 1 +#define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 +#define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" +typedef struct VkPhysicalDeviceRobustness2FeaturesEXT { VkStructureType sType; void* pNext; - uint32_t shaderEngineCount; - uint32_t shaderArraysPerEngineCount; - uint32_t computeUnitsPerShaderArray; - uint32_t simdPerComputeUnit; - uint32_t wavefrontsPerSimd; - uint32_t wavefrontSize; - uint32_t sgprsPerSimd; - uint32_t minSgprAllocation; - uint32_t maxSgprAllocation; - uint32_t sgprAllocationGranularity; - uint32_t vgprsPerSimd; - uint32_t minVgprAllocation; - uint32_t maxVgprAllocation; - uint32_t vgprAllocationGranularity; -} VkPhysicalDeviceShaderCorePropertiesAMD; - - + VkBool32 robustBufferAccess2; + VkBool32 robustImageAccess2; + VkBool32 nullDescriptor; +} VkPhysicalDeviceRobustness2FeaturesEXT; -#define VK_AMD_memory_overallocation_behavior 1 -#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1 -#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior" +typedef struct VkPhysicalDeviceRobustness2PropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize robustStorageBufferAccessSizeAlignment; + VkDeviceSize robustUniformBufferAccessSizeAlignment; +} VkPhysicalDeviceRobustness2PropertiesEXT; -typedef enum VkMemoryOverallocationBehaviorAMD { - VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0, - VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1, - VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2, - VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF -} VkMemoryOverallocationBehaviorAMD; -typedef struct VkDeviceMemoryOverallocationCreateInfoAMD { - VkStructureType sType; - const void* pNext; - VkMemoryOverallocationBehaviorAMD overallocationBehavior; -} VkDeviceMemoryOverallocationCreateInfoAMD; +// VK_EXT_custom_border_color is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_custom_border_color 1 +#define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 +#define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" +typedef struct VkSamplerCustomBorderColorCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkClearColorValue customBorderColor; + VkFormat format; +} VkSamplerCustomBorderColorCreateInfoEXT; -#define VK_EXT_vertex_attribute_divisor 1 -#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3 -#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor" -typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT { +typedef struct VkPhysicalDeviceCustomBorderColorPropertiesEXT { VkStructureType sType; void* pNext; - uint32_t maxVertexAttribDivisor; -} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT; - -typedef struct VkVertexInputBindingDivisorDescriptionEXT { - uint32_t binding; - uint32_t divisor; -} VkVertexInputBindingDivisorDescriptionEXT; - -typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t vertexBindingDivisorCount; - const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors; -} VkPipelineVertexInputDivisorStateCreateInfoEXT; + uint32_t maxCustomBorderColorSamplers; +} VkPhysicalDeviceCustomBorderColorPropertiesEXT; -typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT { +typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 vertexAttributeInstanceRateDivisor; - VkBool32 vertexAttributeInstanceRateZeroDivisor; -} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT; - - - -#define VK_EXT_pipeline_creation_feedback 1 -#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 -#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback" - -typedef enum VkPipelineCreationFeedbackFlagBitsEXT { - VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = 0x00000001, - VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = 0x00000002, - VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = 0x00000004, - VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkPipelineCreationFeedbackFlagBitsEXT; -typedef VkFlags VkPipelineCreationFeedbackFlagsEXT; -typedef struct VkPipelineCreationFeedbackEXT { - VkPipelineCreationFeedbackFlagsEXT flags; - uint64_t duration; -} VkPipelineCreationFeedbackEXT; - -typedef struct VkPipelineCreationFeedbackCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback; - uint32_t pipelineStageCreationFeedbackCount; - VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks; -} VkPipelineCreationFeedbackCreateInfoEXT; + VkBool32 customBorderColors; + VkBool32 customBorderColorWithoutFormat; +} VkPhysicalDeviceCustomBorderColorFeaturesEXT; -#define VK_NV_shader_subgroup_partitioned 1 -#define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1 -#define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned" +// VK_GOOGLE_user_type is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_user_type 1 +#define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 +#define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type" -#define VK_NV_compute_shader_derivatives 1 -#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1 -#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives" -typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV { +// VK_NV_present_barrier is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_present_barrier 1 +#define VK_NV_PRESENT_BARRIER_SPEC_VERSION 1 +#define VK_NV_PRESENT_BARRIER_EXTENSION_NAME "VK_NV_present_barrier" +typedef struct VkPhysicalDevicePresentBarrierFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 computeDerivativeGroupQuads; - VkBool32 computeDerivativeGroupLinear; -} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV; - - + VkBool32 presentBarrier; +} VkPhysicalDevicePresentBarrierFeaturesNV; -#define VK_NV_mesh_shader 1 -#define VK_NV_MESH_SHADER_SPEC_VERSION 1 -#define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader" -typedef struct VkPhysicalDeviceMeshShaderFeaturesNV { +typedef struct VkSurfaceCapabilitiesPresentBarrierNV { VkStructureType sType; void* pNext; - VkBool32 taskShader; - VkBool32 meshShader; -} VkPhysicalDeviceMeshShaderFeaturesNV; + VkBool32 presentBarrierSupported; +} VkSurfaceCapabilitiesPresentBarrierNV; -typedef struct VkPhysicalDeviceMeshShaderPropertiesNV { +typedef struct VkSwapchainPresentBarrierCreateInfoNV { VkStructureType sType; void* pNext; - uint32_t maxDrawMeshTasksCount; - uint32_t maxTaskWorkGroupInvocations; - uint32_t maxTaskWorkGroupSize[3]; - uint32_t maxTaskTotalMemorySize; - uint32_t maxTaskOutputCount; - uint32_t maxMeshWorkGroupInvocations; - uint32_t maxMeshWorkGroupSize[3]; - uint32_t maxMeshTotalMemorySize; - uint32_t maxMeshOutputVertices; - uint32_t maxMeshOutputPrimitives; - uint32_t maxMeshMultiviewViewCount; - uint32_t meshOutputPerVertexGranularity; - uint32_t meshOutputPerPrimitiveGranularity; -} VkPhysicalDeviceMeshShaderPropertiesNV; + VkBool32 presentBarrierEnable; +} VkSwapchainPresentBarrierCreateInfoNV; -typedef struct VkDrawMeshTasksIndirectCommandNV { - uint32_t taskCount; - uint32_t firstTask; -} VkDrawMeshTasksIndirectCommandNV; -typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask); -typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +// VK_EXT_private_data is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_private_data 1 +typedef VkPrivateDataSlot VkPrivateDataSlotEXT; + +#define VK_EXT_PRIVATE_DATA_SPEC_VERSION 1 +#define VK_EXT_PRIVATE_DATA_EXTENSION_NAME "VK_EXT_private_data" +typedef VkPrivateDataSlotCreateFlags VkPrivateDataSlotCreateFlagsEXT; + +typedef VkPhysicalDevicePrivateDataFeatures VkPhysicalDevicePrivateDataFeaturesEXT; + +typedef VkDevicePrivateDataCreateInfo VkDevicePrivateDataCreateInfoEXT; + +typedef VkPrivateDataSlotCreateInfo VkPrivateDataSlotCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlotEXT)(VkDevice device, const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlot* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlotEXT)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); +typedef void (VKAPI_PTR *PFN_vkGetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t* pData); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV( - VkCommandBuffer commandBuffer, - uint32_t taskCount, - uint32_t firstTask); +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlotEXT( + VkDevice device, + const VkPrivateDataSlotCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPrivateDataSlot* pPrivateDataSlot); -VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - uint32_t drawCount, - uint32_t stride); +VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlotEXT( + VkDevice device, + VkPrivateDataSlot privateDataSlot, + const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkBuffer countBuffer, - VkDeviceSize countBufferOffset, - uint32_t maxDrawCount, - uint32_t stride); +VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t data); + +VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t* pData); #endif -#define VK_NV_fragment_shader_barycentric 1 -#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 -#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric" -typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV { +// VK_EXT_pipeline_creation_cache_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_creation_cache_control 1 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 3 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control" +typedef VkPhysicalDevicePipelineCreationCacheControlFeatures VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT; + + + +// VK_NV_device_diagnostics_config is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_device_diagnostics_config 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 2 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config" + +typedef enum VkDeviceDiagnosticsConfigFlagBitsNV { + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0x00000001, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0x00000002, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0x00000004, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV = 0x00000008, + VK_DEVICE_DIAGNOSTICS_CONFIG_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkDeviceDiagnosticsConfigFlagBitsNV; +typedef VkFlags VkDeviceDiagnosticsConfigFlagsNV; +typedef struct VkPhysicalDeviceDiagnosticsConfigFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 fragmentShaderBarycentric; -} VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV; + VkBool32 diagnosticsConfig; +} VkPhysicalDeviceDiagnosticsConfigFeaturesNV; +typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceDiagnosticsConfigFlagsNV flags; +} VkDeviceDiagnosticsConfigCreateInfoNV; -#define VK_NV_shader_image_footprint 1 -#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 2 -#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint" -typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV { - VkStructureType sType; - void* pNext; - VkBool32 imageFootprint; -} VkPhysicalDeviceShaderImageFootprintFeaturesNV; +// VK_QCOM_render_pass_store_ops is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_render_pass_store_ops 1 +#define VK_QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION 2 +#define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" -#define VK_NV_scissor_exclusive 1 -#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1 -#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive" -typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV { +// VK_NV_cuda_kernel_launch is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cuda_kernel_launch 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaModuleNV) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaFunctionNV) +#define VK_NV_CUDA_KERNEL_LAUNCH_SPEC_VERSION 2 +#define VK_NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME "VK_NV_cuda_kernel_launch" +typedef struct VkCudaModuleCreateInfoNV { VkStructureType sType; const void* pNext; - uint32_t exclusiveScissorCount; - const VkRect2D* pExclusiveScissors; -} VkPipelineViewportExclusiveScissorStateCreateInfoNV; + size_t dataSize; + const void* pData; +} VkCudaModuleCreateInfoNV; -typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV { +typedef struct VkCudaFunctionCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCudaModuleNV module; + const char* pName; +} VkCudaFunctionCreateInfoNV; + +typedef struct VkCudaLaunchInfoNV { + VkStructureType sType; + const void* pNext; + VkCudaFunctionNV function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCudaLaunchInfoNV; + +typedef struct VkPhysicalDeviceCudaKernelLaunchFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 exclusiveScissor; -} VkPhysicalDeviceExclusiveScissorFeaturesNV; + VkBool32 cudaKernelLaunchFeatures; +} VkPhysicalDeviceCudaKernelLaunchFeaturesNV; -typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); +typedef struct VkPhysicalDeviceCudaKernelLaunchPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t computeCapabilityMinor; + uint32_t computeCapabilityMajor; +} VkPhysicalDeviceCudaKernelLaunchPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaModuleNV)(VkDevice device, const VkCudaModuleCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaModuleNV* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkGetCudaModuleCacheNV)(VkDevice device, VkCudaModuleNV module, size_t* pCacheSize, void* pCacheData); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaFunctionNV)(VkDevice device, const VkCudaFunctionCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaFunctionNV* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCudaModuleNV)(VkDevice device, VkCudaModuleNV module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCudaFunctionNV)(VkDevice device, VkCudaFunctionNV function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCudaLaunchKernelNV)(VkCommandBuffer commandBuffer, const VkCudaLaunchInfoNV* pLaunchInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( - VkCommandBuffer commandBuffer, - uint32_t firstExclusiveScissor, - uint32_t exclusiveScissorCount, - const VkRect2D* pExclusiveScissors); -#endif +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaModuleNV( + VkDevice device, + const VkCudaModuleCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCudaModuleNV* pModule); +VKAPI_ATTR VkResult VKAPI_CALL vkGetCudaModuleCacheNV( + VkDevice device, + VkCudaModuleNV module, + size_t* pCacheSize, + void* pCacheData); -#define VK_NV_device_diagnostic_checkpoints 1 -#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2 -#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints" -typedef struct VkQueueFamilyCheckpointPropertiesNV { - VkStructureType sType; - void* pNext; - VkPipelineStageFlags checkpointExecutionStageMask; -} VkQueueFamilyCheckpointPropertiesNV; +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaFunctionNV( + VkDevice device, + const VkCudaFunctionCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCudaFunctionNV* pFunction); -typedef struct VkCheckpointDataNV { - VkStructureType sType; - void* pNext; - VkPipelineStageFlagBits stage; - void* pCheckpointMarker; -} VkCheckpointDataNV; +VKAPI_ATTR void VKAPI_CALL vkDestroyCudaModuleNV( + VkDevice device, + VkCudaModuleNV module, + const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkCmdSetCheckpointNV)(VkCommandBuffer commandBuffer, const void* pCheckpointMarker); -typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData); +VKAPI_ATTR void VKAPI_CALL vkDestroyCudaFunctionNV( + VkDevice device, + VkCudaFunctionNV function, + const VkAllocationCallbacks* pAllocator); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV( +VKAPI_ATTR void VKAPI_CALL vkCmdCudaLaunchKernelNV( VkCommandBuffer commandBuffer, - const void* pCheckpointMarker); - -VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV( - VkQueue queue, - uint32_t* pCheckpointDataCount, - VkCheckpointDataNV* pCheckpointData); + const VkCudaLaunchInfoNV* pLaunchInfo); #endif -#define VK_INTEL_shader_integer_functions2 1 -#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION 1 -#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME "VK_INTEL_shader_integer_functions2" -typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL { +// VK_NV_low_latency is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_low_latency 1 +#define VK_NV_LOW_LATENCY_SPEC_VERSION 1 +#define VK_NV_LOW_LATENCY_EXTENSION_NAME "VK_NV_low_latency" +typedef struct VkQueryLowLatencySupportNV { VkStructureType sType; - void* pNext; - VkBool32 shaderIntegerFunctions2; -} VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL; - - + const void* pNext; + void* pQueriedLowLatencyData; +} VkQueryLowLatencySupportNV; -#define VK_INTEL_performance_query 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL) -#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2 -#define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query" -typedef enum VkPerformanceConfigurationTypeINTEL { - VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0, - VK_PERFORMANCE_CONFIGURATION_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF -} VkPerformanceConfigurationTypeINTEL; -typedef enum VkQueryPoolSamplingModeINTEL { - VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0, - VK_QUERY_POOL_SAMPLING_MODE_MAX_ENUM_INTEL = 0x7FFFFFFF -} VkQueryPoolSamplingModeINTEL; +// VK_EXT_descriptor_buffer is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_descriptor_buffer 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) +#define VK_EXT_DESCRIPTOR_BUFFER_SPEC_VERSION 1 +#define VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME "VK_EXT_descriptor_buffer" +typedef struct VkPhysicalDeviceDescriptorBufferPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 combinedImageSamplerDescriptorSingleArray; + VkBool32 bufferlessPushDescriptors; + VkBool32 allowSamplerImageViewPostSubmitCreation; + VkDeviceSize descriptorBufferOffsetAlignment; + uint32_t maxDescriptorBufferBindings; + uint32_t maxResourceDescriptorBufferBindings; + uint32_t maxSamplerDescriptorBufferBindings; + uint32_t maxEmbeddedImmutableSamplerBindings; + uint32_t maxEmbeddedImmutableSamplers; + size_t bufferCaptureReplayDescriptorDataSize; + size_t imageCaptureReplayDescriptorDataSize; + size_t imageViewCaptureReplayDescriptorDataSize; + size_t samplerCaptureReplayDescriptorDataSize; + size_t accelerationStructureCaptureReplayDescriptorDataSize; + size_t samplerDescriptorSize; + size_t combinedImageSamplerDescriptorSize; + size_t sampledImageDescriptorSize; + size_t storageImageDescriptorSize; + size_t uniformTexelBufferDescriptorSize; + size_t robustUniformTexelBufferDescriptorSize; + size_t storageTexelBufferDescriptorSize; + size_t robustStorageTexelBufferDescriptorSize; + size_t uniformBufferDescriptorSize; + size_t robustUniformBufferDescriptorSize; + size_t storageBufferDescriptorSize; + size_t robustStorageBufferDescriptorSize; + size_t inputAttachmentDescriptorSize; + size_t accelerationStructureDescriptorSize; + VkDeviceSize maxSamplerDescriptorBufferRange; + VkDeviceSize maxResourceDescriptorBufferRange; + VkDeviceSize samplerDescriptorBufferAddressSpaceSize; + VkDeviceSize resourceDescriptorBufferAddressSpaceSize; + VkDeviceSize descriptorBufferAddressSpaceSize; +} VkPhysicalDeviceDescriptorBufferPropertiesEXT; + +typedef struct VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT { + VkStructureType sType; + void* pNext; + size_t combinedImageSamplerDensityMapDescriptorSize; +} VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT; -typedef enum VkPerformanceOverrideTypeINTEL { - VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0, - VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1, - VK_PERFORMANCE_OVERRIDE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF -} VkPerformanceOverrideTypeINTEL; +typedef struct VkPhysicalDeviceDescriptorBufferFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 descriptorBuffer; + VkBool32 descriptorBufferCaptureReplay; + VkBool32 descriptorBufferImageLayoutIgnored; + VkBool32 descriptorBufferPushDescriptors; +} VkPhysicalDeviceDescriptorBufferFeaturesEXT; -typedef enum VkPerformanceParameterTypeINTEL { - VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0, - VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1, - VK_PERFORMANCE_PARAMETER_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF -} VkPerformanceParameterTypeINTEL; +typedef struct VkDescriptorAddressInfoEXT { + VkStructureType sType; + void* pNext; + VkDeviceAddress address; + VkDeviceSize range; + VkFormat format; +} VkDescriptorAddressInfoEXT; -typedef enum VkPerformanceValueTypeINTEL { - VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL = 0, - VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL = 1, - VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL = 2, - VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL = 3, - VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4, - VK_PERFORMANCE_VALUE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF -} VkPerformanceValueTypeINTEL; -typedef union VkPerformanceValueDataINTEL { - uint32_t value32; - uint64_t value64; - float valueFloat; - VkBool32 valueBool; - const char* valueString; -} VkPerformanceValueDataINTEL; +typedef struct VkDescriptorBufferBindingInfoEXT { + VkStructureType sType; + void* pNext; + VkDeviceAddress address; + VkBufferUsageFlags usage; +} VkDescriptorBufferBindingInfoEXT; -typedef struct VkPerformanceValueINTEL { - VkPerformanceValueTypeINTEL type; - VkPerformanceValueDataINTEL data; -} VkPerformanceValueINTEL; +typedef struct VkDescriptorBufferBindingPushDescriptorBufferHandleEXT { + VkStructureType sType; + void* pNext; + VkBuffer buffer; +} VkDescriptorBufferBindingPushDescriptorBufferHandleEXT; + +typedef union VkDescriptorDataEXT { + const VkSampler* pSampler; + const VkDescriptorImageInfo* pCombinedImageSampler; + const VkDescriptorImageInfo* pInputAttachmentImage; + const VkDescriptorImageInfo* pSampledImage; + const VkDescriptorImageInfo* pStorageImage; + const VkDescriptorAddressInfoEXT* pUniformTexelBuffer; + const VkDescriptorAddressInfoEXT* pStorageTexelBuffer; + const VkDescriptorAddressInfoEXT* pUniformBuffer; + const VkDescriptorAddressInfoEXT* pStorageBuffer; + VkDeviceAddress accelerationStructure; +} VkDescriptorDataEXT; + +typedef struct VkDescriptorGetInfoEXT { + VkStructureType sType; + const void* pNext; + VkDescriptorType type; + VkDescriptorDataEXT data; +} VkDescriptorGetInfoEXT; -typedef struct VkInitializePerformanceApiInfoINTEL { +typedef struct VkBufferCaptureDescriptorDataInfoEXT { VkStructureType sType; const void* pNext; - void* pUserData; -} VkInitializePerformanceApiInfoINTEL; - -typedef struct VkQueryPoolPerformanceQueryCreateInfoINTEL { - VkStructureType sType; - const void* pNext; - VkQueryPoolSamplingModeINTEL performanceCountersSampling; -} VkQueryPoolPerformanceQueryCreateInfoINTEL; - -typedef VkQueryPoolPerformanceQueryCreateInfoINTEL VkQueryPoolCreateInfoINTEL; + VkBuffer buffer; +} VkBufferCaptureDescriptorDataInfoEXT; -typedef struct VkPerformanceMarkerInfoINTEL { +typedef struct VkImageCaptureDescriptorDataInfoEXT { VkStructureType sType; const void* pNext; - uint64_t marker; -} VkPerformanceMarkerInfoINTEL; + VkImage image; +} VkImageCaptureDescriptorDataInfoEXT; -typedef struct VkPerformanceStreamMarkerInfoINTEL { +typedef struct VkImageViewCaptureDescriptorDataInfoEXT { VkStructureType sType; const void* pNext; - uint32_t marker; -} VkPerformanceStreamMarkerInfoINTEL; + VkImageView imageView; +} VkImageViewCaptureDescriptorDataInfoEXT; -typedef struct VkPerformanceOverrideInfoINTEL { - VkStructureType sType; - const void* pNext; - VkPerformanceOverrideTypeINTEL type; - VkBool32 enable; - uint64_t parameter; -} VkPerformanceOverrideInfoINTEL; +typedef struct VkSamplerCaptureDescriptorDataInfoEXT { + VkStructureType sType; + const void* pNext; + VkSampler sampler; +} VkSamplerCaptureDescriptorDataInfoEXT; -typedef struct VkPerformanceConfigurationAcquireInfoINTEL { - VkStructureType sType; - const void* pNext; - VkPerformanceConfigurationTypeINTEL type; -} VkPerformanceConfigurationAcquireInfoINTEL; +typedef struct VkOpaqueCaptureDescriptorDataCreateInfoEXT { + VkStructureType sType; + const void* pNext; + const void* opaqueCaptureDescriptorData; +} VkOpaqueCaptureDescriptorDataCreateInfoEXT; -typedef VkResult (VKAPI_PTR *PFN_vkInitializePerformanceApiINTEL)(VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); -typedef void (VKAPI_PTR *PFN_vkUninitializePerformanceApiINTEL)(VkDevice device); -typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceStreamMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceOverrideINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo); -typedef VkResult (VKAPI_PTR *PFN_vkAcquirePerformanceConfigurationINTEL)(VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration); -typedef VkResult (VKAPI_PTR *PFN_vkReleasePerformanceConfigurationINTEL)(VkDevice device, VkPerformanceConfigurationINTEL configuration); -typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerformanceConfigurationINTEL)(VkQueue queue, VkPerformanceConfigurationINTEL configuration); -typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceParameterINTEL)(VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue); +typedef struct VkAccelerationStructureCaptureDescriptorDataInfoEXT { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; + VkAccelerationStructureNV accelerationStructureNV; +} VkAccelerationStructureCaptureDescriptorDataInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSizeEXT)(VkDevice device, VkDescriptorSetLayout layout, VkDeviceSize* pLayoutSizeInBytes); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutBindingOffsetEXT)(VkDevice device, VkDescriptorSetLayout layout, uint32_t binding, VkDeviceSize* pOffset); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorEXT)(VkDevice device, const VkDescriptorGetInfoEXT* pDescriptorInfo, size_t dataSize, void* pDescriptor); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t bufferCount, const VkDescriptorBufferBindingInfoEXT* pBindingInfos); +typedef void (VKAPI_PTR *PFN_vkCmdSetDescriptorBufferOffsetsEXT)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const uint32_t* pBufferIndices, const VkDeviceSize* pOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set); +typedef VkResult (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkBufferCaptureDescriptorDataInfoEXT* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkImageCaptureDescriptorDataInfoEXT* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkImageViewCaptureDescriptorDataInfoEXT* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkSamplerCaptureDescriptorDataInfoEXT* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkAccelerationStructureCaptureDescriptorDataInfoEXT* pInfo, void* pData); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkInitializePerformanceApiINTEL( +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSizeEXT( VkDevice device, - const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); + VkDescriptorSetLayout layout, + VkDeviceSize* pLayoutSizeInBytes); -VKAPI_ATTR void VKAPI_CALL vkUninitializePerformanceApiINTEL( - VkDevice device); +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutBindingOffsetEXT( + VkDevice device, + VkDescriptorSetLayout layout, + uint32_t binding, + VkDeviceSize* pOffset); -VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceMarkerINTEL( +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorEXT( + VkDevice device, + const VkDescriptorGetInfoEXT* pDescriptorInfo, + size_t dataSize, + void* pDescriptor); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorBuffersEXT( VkCommandBuffer commandBuffer, - const VkPerformanceMarkerInfoINTEL* pMarkerInfo); + uint32_t bufferCount, + const VkDescriptorBufferBindingInfoEXT* pBindingInfos); -VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceStreamMarkerINTEL( +VKAPI_ATTR void VKAPI_CALL vkCmdSetDescriptorBufferOffsetsEXT( VkCommandBuffer commandBuffer, - const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t firstSet, + uint32_t setCount, + const uint32_t* pBufferIndices, + const VkDeviceSize* pOffsets); -VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceOverrideINTEL( +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorBufferEmbeddedSamplersEXT( VkCommandBuffer commandBuffer, - const VkPerformanceOverrideInfoINTEL* pOverrideInfo); + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set); -VKAPI_ATTR VkResult VKAPI_CALL vkAcquirePerformanceConfigurationINTEL( +VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferOpaqueCaptureDescriptorDataEXT( VkDevice device, - const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, - VkPerformanceConfigurationINTEL* pConfiguration); + const VkBufferCaptureDescriptorDataInfoEXT* pInfo, + void* pData); -VKAPI_ATTR VkResult VKAPI_CALL vkReleasePerformanceConfigurationINTEL( +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageOpaqueCaptureDescriptorDataEXT( VkDevice device, - VkPerformanceConfigurationINTEL configuration); + const VkImageCaptureDescriptorDataInfoEXT* pInfo, + void* pData); -VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerformanceConfigurationINTEL( - VkQueue queue, - VkPerformanceConfigurationINTEL configuration); +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewOpaqueCaptureDescriptorDataEXT( + VkDevice device, + const VkImageViewCaptureDescriptorDataInfoEXT* pInfo, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSamplerOpaqueCaptureDescriptorDataEXT( + VkDevice device, + const VkSamplerCaptureDescriptorDataInfoEXT* pInfo, + void* pData); -VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceParameterINTEL( +VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT( VkDevice device, - VkPerformanceParameterTypeINTEL parameter, - VkPerformanceValueINTEL* pValue); + const VkAccelerationStructureCaptureDescriptorDataInfoEXT* pInfo, + void* pData); #endif -#define VK_EXT_pci_bus_info 1 -#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2 -#define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info" -typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT { +// VK_EXT_graphics_pipeline_library is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_graphics_pipeline_library 1 +#define VK_EXT_GRAPHICS_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME "VK_EXT_graphics_pipeline_library" + +typedef enum VkGraphicsPipelineLibraryFlagBitsEXT { + VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT = 0x00000001, + VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT = 0x00000002, + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT = 0x00000004, + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT = 0x00000008, + VK_GRAPHICS_PIPELINE_LIBRARY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkGraphicsPipelineLibraryFlagBitsEXT; +typedef VkFlags VkGraphicsPipelineLibraryFlagsEXT; +typedef struct VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT { VkStructureType sType; void* pNext; - uint32_t pciDomain; - uint32_t pciBus; - uint32_t pciDevice; - uint32_t pciFunction; -} VkPhysicalDevicePCIBusInfoPropertiesEXT; + VkBool32 graphicsPipelineLibrary; +} VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT; + +typedef struct VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 graphicsPipelineLibraryFastLinking; + VkBool32 graphicsPipelineLibraryIndependentInterpolationDecoration; +} VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT; +typedef struct VkGraphicsPipelineLibraryCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkGraphicsPipelineLibraryFlagsEXT flags; +} VkGraphicsPipelineLibraryCreateInfoEXT; -#define VK_AMD_display_native_hdr 1 -#define VK_AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION 1 -#define VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME "VK_AMD_display_native_hdr" -typedef struct VkDisplayNativeHdrSurfaceCapabilitiesAMD { + +// VK_AMD_shader_early_and_late_fragment_tests is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_early_and_late_fragment_tests 1 +#define VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_SPEC_VERSION 1 +#define VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_EXTENSION_NAME "VK_AMD_shader_early_and_late_fragment_tests" +typedef struct VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD { VkStructureType sType; void* pNext; - VkBool32 localDimmingSupport; -} VkDisplayNativeHdrSurfaceCapabilitiesAMD; + VkBool32 shaderEarlyAndLateFragmentTests; +} VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD; -typedef struct VkSwapchainDisplayNativeHdrCreateInfoAMD { + + +// VK_NV_fragment_shading_rate_enums is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_fragment_shading_rate_enums 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME "VK_NV_fragment_shading_rate_enums" + +typedef enum VkFragmentShadingRateTypeNV { + VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0, + VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1, + VK_FRAGMENT_SHADING_RATE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateTypeNV; + +typedef enum VkFragmentShadingRateNV { + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10, + VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11, + VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12, + VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13, + VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14, + VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15, + VK_FRAGMENT_SHADING_RATE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateNV; +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV { VkStructureType sType; - const void* pNext; - VkBool32 localDimmingEnable; -} VkSwapchainDisplayNativeHdrCreateInfoAMD; + void* pNext; + VkBool32 fragmentShadingRateEnums; + VkBool32 supersampleFragmentShadingRates; + VkBool32 noInvocationFragmentShadingRates; +} VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV; -typedef void (VKAPI_PTR *PFN_vkSetLocalDimmingAMD)(VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable); +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV { + VkStructureType sType; + void* pNext; + VkSampleCountFlagBits maxFragmentShadingRateInvocationCount; +} VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV; + +typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkFragmentShadingRateTypeNV shadingRateType; + VkFragmentShadingRateNV shadingRate; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateEnumStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateEnumNV)(VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD( - VkDevice device, - VkSwapchainKHR swapChain, - VkBool32 localDimmingEnable); +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( + VkCommandBuffer commandBuffer, + VkFragmentShadingRateNV shadingRate, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); #endif -#define VK_EXT_fragment_density_map 1 -#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 1 -#define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map" -typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 fragmentDensityMap; - VkBool32 fragmentDensityMapDynamic; - VkBool32 fragmentDensityMapNonSubsampledImages; -} VkPhysicalDeviceFragmentDensityMapFeaturesEXT; +// VK_NV_ray_tracing_motion_blur is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_ray_tracing_motion_blur 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME "VK_NV_ray_tracing_motion_blur" -typedef struct VkPhysicalDeviceFragmentDensityMapPropertiesEXT { - VkStructureType sType; - void* pNext; - VkExtent2D minFragmentDensityTexelSize; - VkExtent2D maxFragmentDensityTexelSize; - VkBool32 fragmentDensityInvocations; -} VkPhysicalDeviceFragmentDensityMapPropertiesEXT; +typedef enum VkAccelerationStructureMotionInstanceTypeNV { + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV = 0, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV = 1, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV = 2, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMotionInstanceTypeNV; +typedef VkFlags VkAccelerationStructureMotionInfoFlagsNV; +typedef VkFlags VkAccelerationStructureMotionInstanceFlagsNV; +typedef union VkDeviceOrHostAddressConstKHR { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstKHR; -typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkAttachmentReference fragmentDensityMapAttachment; -} VkRenderPassFragmentDensityMapCreateInfoEXT; +typedef struct VkAccelerationStructureGeometryMotionTrianglesDataNV { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR vertexData; +} VkAccelerationStructureGeometryMotionTrianglesDataNV; +typedef struct VkAccelerationStructureMotionInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t maxInstances; + VkAccelerationStructureMotionInfoFlagsNV flags; +} VkAccelerationStructureMotionInfoNV; +typedef struct VkAccelerationStructureMatrixMotionInstanceNV { + VkTransformMatrixKHR transformT0; + VkTransformMatrixKHR transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureMatrixMotionInstanceNV; -#define VK_EXT_scalar_block_layout 1 -#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1 -#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout" -typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLayoutFeaturesEXT; +typedef struct VkSRTDataNV { + float sx; + float a; + float b; + float pvx; + float sy; + float c; + float pvy; + float sz; + float pvz; + float qx; + float qy; + float qz; + float qw; + float tx; + float ty; + float tz; +} VkSRTDataNV; +typedef struct VkAccelerationStructureSRTMotionInstanceNV { + VkSRTDataNV transformT0; + VkSRTDataNV transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureSRTMotionInstanceNV; +typedef union VkAccelerationStructureMotionInstanceDataNV { + VkAccelerationStructureInstanceKHR staticInstance; + VkAccelerationStructureMatrixMotionInstanceNV matrixMotionInstance; + VkAccelerationStructureSRTMotionInstanceNV srtMotionInstance; +} VkAccelerationStructureMotionInstanceDataNV; -#define VK_GOOGLE_hlsl_functionality1 1 -#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 1 -#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" +typedef struct VkAccelerationStructureMotionInstanceNV { + VkAccelerationStructureMotionInstanceTypeNV type; + VkAccelerationStructureMotionInstanceFlagsNV flags; + VkAccelerationStructureMotionInstanceDataNV data; +} VkAccelerationStructureMotionInstanceNV; +typedef struct VkPhysicalDeviceRayTracingMotionBlurFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingMotionBlur; + VkBool32 rayTracingMotionBlurPipelineTraceRaysIndirect; +} VkPhysicalDeviceRayTracingMotionBlurFeaturesNV; -#define VK_GOOGLE_decorate_string 1 -#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1 -#define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string" -#define VK_EXT_subgroup_size_control 1 -#define VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION 2 -#define VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME "VK_EXT_subgroup_size_control" -typedef struct VkPhysicalDeviceSubgroupSizeControlFeaturesEXT { +// VK_EXT_ycbcr_2plane_444_formats is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_ycbcr_2plane_444_formats 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME "VK_EXT_ycbcr_2plane_444_formats" +typedef struct VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 subgroupSizeControl; - VkBool32 computeFullSubgroups; -} VkPhysicalDeviceSubgroupSizeControlFeaturesEXT; + VkBool32 ycbcr2plane444Formats; +} VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT; -typedef struct VkPhysicalDeviceSubgroupSizeControlPropertiesEXT { - VkStructureType sType; - void* pNext; - uint32_t minSubgroupSize; - uint32_t maxSubgroupSize; - uint32_t maxComputeWorkgroupSubgroups; - VkShaderStageFlags requiredSubgroupSizeStages; -} VkPhysicalDeviceSubgroupSizeControlPropertiesEXT; -typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT { + +// VK_EXT_fragment_density_map2 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_fragment_density_map2 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME "VK_EXT_fragment_density_map2" +typedef struct VkPhysicalDeviceFragmentDensityMap2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapDeferred; +} VkPhysicalDeviceFragmentDensityMap2FeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { VkStructureType sType; void* pNext; - uint32_t requiredSubgroupSize; -} VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT; + VkBool32 subsampledLoads; + VkBool32 subsampledCoarseReconstructionEarlyAccess; + uint32_t maxSubsampledArrayLayers; + uint32_t maxDescriptorSetSubsampledSamplers; +} VkPhysicalDeviceFragmentDensityMap2PropertiesEXT; -#define VK_AMD_shader_core_properties2 1 -#define VK_AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION 1 -#define VK_AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME "VK_AMD_shader_core_properties2" +// VK_QCOM_rotated_copy_commands is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_rotated_copy_commands 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME "VK_QCOM_rotated_copy_commands" +typedef struct VkCopyCommandTransformInfoQCOM { + VkStructureType sType; + const void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkCopyCommandTransformInfoQCOM; -typedef enum VkShaderCorePropertiesFlagBitsAMD { - VK_SHADER_CORE_PROPERTIES_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF -} VkShaderCorePropertiesFlagBitsAMD; -typedef VkFlags VkShaderCorePropertiesFlagsAMD; -typedef struct VkPhysicalDeviceShaderCoreProperties2AMD { - VkStructureType sType; - void* pNext; - VkShaderCorePropertiesFlagsAMD shaderCoreFeatures; - uint32_t activeComputeUnitCount; -} VkPhysicalDeviceShaderCoreProperties2AMD; +// VK_EXT_image_robustness is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_robustness 1 +#define VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION 1 +#define VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_image_robustness" +typedef VkPhysicalDeviceImageRobustnessFeatures VkPhysicalDeviceImageRobustnessFeaturesEXT; + + + +// VK_EXT_image_compression_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_compression_control 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SPEC_VERSION 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME "VK_EXT_image_compression_control" + +typedef enum VkImageCompressionFlagBitsEXT { + VK_IMAGE_COMPRESSION_DEFAULT_EXT = 0, + VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT = 0x00000001, + VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT = 0x00000002, + VK_IMAGE_COMPRESSION_DISABLED_EXT = 0x00000004, + VK_IMAGE_COMPRESSION_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkImageCompressionFlagBitsEXT; +typedef VkFlags VkImageCompressionFlagsEXT; + +typedef enum VkImageCompressionFixedRateFlagBitsEXT { + VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT = 0, + VK_IMAGE_COMPRESSION_FIXED_RATE_1BPC_BIT_EXT = 0x00000001, + VK_IMAGE_COMPRESSION_FIXED_RATE_2BPC_BIT_EXT = 0x00000002, + VK_IMAGE_COMPRESSION_FIXED_RATE_3BPC_BIT_EXT = 0x00000004, + VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT = 0x00000008, + VK_IMAGE_COMPRESSION_FIXED_RATE_5BPC_BIT_EXT = 0x00000010, + VK_IMAGE_COMPRESSION_FIXED_RATE_6BPC_BIT_EXT = 0x00000020, + VK_IMAGE_COMPRESSION_FIXED_RATE_7BPC_BIT_EXT = 0x00000040, + VK_IMAGE_COMPRESSION_FIXED_RATE_8BPC_BIT_EXT = 0x00000080, + VK_IMAGE_COMPRESSION_FIXED_RATE_9BPC_BIT_EXT = 0x00000100, + VK_IMAGE_COMPRESSION_FIXED_RATE_10BPC_BIT_EXT = 0x00000200, + VK_IMAGE_COMPRESSION_FIXED_RATE_11BPC_BIT_EXT = 0x00000400, + VK_IMAGE_COMPRESSION_FIXED_RATE_12BPC_BIT_EXT = 0x00000800, + VK_IMAGE_COMPRESSION_FIXED_RATE_13BPC_BIT_EXT = 0x00001000, + VK_IMAGE_COMPRESSION_FIXED_RATE_14BPC_BIT_EXT = 0x00002000, + VK_IMAGE_COMPRESSION_FIXED_RATE_15BPC_BIT_EXT = 0x00004000, + VK_IMAGE_COMPRESSION_FIXED_RATE_16BPC_BIT_EXT = 0x00008000, + VK_IMAGE_COMPRESSION_FIXED_RATE_17BPC_BIT_EXT = 0x00010000, + VK_IMAGE_COMPRESSION_FIXED_RATE_18BPC_BIT_EXT = 0x00020000, + VK_IMAGE_COMPRESSION_FIXED_RATE_19BPC_BIT_EXT = 0x00040000, + VK_IMAGE_COMPRESSION_FIXED_RATE_20BPC_BIT_EXT = 0x00080000, + VK_IMAGE_COMPRESSION_FIXED_RATE_21BPC_BIT_EXT = 0x00100000, + VK_IMAGE_COMPRESSION_FIXED_RATE_22BPC_BIT_EXT = 0x00200000, + VK_IMAGE_COMPRESSION_FIXED_RATE_23BPC_BIT_EXT = 0x00400000, + VK_IMAGE_COMPRESSION_FIXED_RATE_24BPC_BIT_EXT = 0x00800000, + VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkImageCompressionFixedRateFlagBitsEXT; +typedef VkFlags VkImageCompressionFixedRateFlagsEXT; +typedef struct VkPhysicalDeviceImageCompressionControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 imageCompressionControl; +} VkPhysicalDeviceImageCompressionControlFeaturesEXT; + +typedef struct VkImageCompressionControlEXT { + VkStructureType sType; + const void* pNext; + VkImageCompressionFlagsEXT flags; + uint32_t compressionControlPlaneCount; + VkImageCompressionFixedRateFlagsEXT* pFixedRateFlags; +} VkImageCompressionControlEXT; + +typedef struct VkImageCompressionPropertiesEXT { + VkStructureType sType; + void* pNext; + VkImageCompressionFlagsEXT imageCompressionFlags; + VkImageCompressionFixedRateFlagsEXT imageCompressionFixedRateFlags; +} VkImageCompressionPropertiesEXT; -#define VK_AMD_device_coherent_memory 1 -#define VK_AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION 1 -#define VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME "VK_AMD_device_coherent_memory" -typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD { + + +// VK_EXT_attachment_feedback_loop_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_attachment_feedback_loop_layout 1 +#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_SPEC_VERSION 2 +#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME "VK_EXT_attachment_feedback_loop_layout" +typedef struct VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 deviceCoherentMemory; -} VkPhysicalDeviceCoherentMemoryFeaturesAMD; + VkBool32 attachmentFeedbackLoopLayout; +} VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT; -#define VK_EXT_shader_image_atomic_int64 1 -#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION 1 -#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME "VK_EXT_shader_image_atomic_int64" -typedef struct VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT { +// VK_EXT_4444_formats is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_4444_formats 1 +#define VK_EXT_4444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_4444_FORMATS_EXTENSION_NAME "VK_EXT_4444_formats" +typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 shaderImageInt64Atomics; - VkBool32 sparseImageInt64Atomics; -} VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT; + VkBool32 formatA4R4G4B4; + VkBool32 formatA4B4G4R4; +} VkPhysicalDevice4444FormatsFeaturesEXT; -#define VK_EXT_memory_budget 1 -#define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 -#define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget" -typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT { +// VK_EXT_device_fault is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_device_fault 1 +#define VK_EXT_DEVICE_FAULT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_FAULT_EXTENSION_NAME "VK_EXT_device_fault" + +typedef enum VkDeviceFaultAddressTypeEXT { + VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT = 0, + VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT = 1, + VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT = 2, + VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT = 3, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT = 4, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT = 5, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT = 6, + VK_DEVICE_FAULT_ADDRESS_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceFaultAddressTypeEXT; + +typedef enum VkDeviceFaultVendorBinaryHeaderVersionEXT { + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT = 1, + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceFaultVendorBinaryHeaderVersionEXT; +typedef struct VkPhysicalDeviceFaultFeaturesEXT { VkStructureType sType; void* pNext; - VkDeviceSize heapBudget[VK_MAX_MEMORY_HEAPS]; - VkDeviceSize heapUsage[VK_MAX_MEMORY_HEAPS]; -} VkPhysicalDeviceMemoryBudgetPropertiesEXT; + VkBool32 deviceFault; + VkBool32 deviceFaultVendorBinary; +} VkPhysicalDeviceFaultFeaturesEXT; +typedef struct VkDeviceFaultCountsEXT { + VkStructureType sType; + void* pNext; + uint32_t addressInfoCount; + uint32_t vendorInfoCount; + VkDeviceSize vendorBinarySize; +} VkDeviceFaultCountsEXT; + +typedef struct VkDeviceFaultAddressInfoEXT { + VkDeviceFaultAddressTypeEXT addressType; + VkDeviceAddress reportedAddress; + VkDeviceSize addressPrecision; +} VkDeviceFaultAddressInfoEXT; + +typedef struct VkDeviceFaultVendorInfoEXT { + char description[VK_MAX_DESCRIPTION_SIZE]; + uint64_t vendorFaultCode; + uint64_t vendorFaultData; +} VkDeviceFaultVendorInfoEXT; +typedef struct VkDeviceFaultInfoEXT { + VkStructureType sType; + void* pNext; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkDeviceFaultAddressInfoEXT* pAddressInfos; + VkDeviceFaultVendorInfoEXT* pVendorInfos; + void* pVendorBinaryData; +} VkDeviceFaultInfoEXT; + +typedef struct VkDeviceFaultVendorBinaryHeaderVersionOneEXT { + uint32_t headerSize; + VkDeviceFaultVendorBinaryHeaderVersionEXT headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint32_t driverVersion; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; + uint32_t applicationNameOffset; + uint32_t applicationVersion; + uint32_t engineNameOffset; + uint32_t engineVersion; + uint32_t apiVersion; +} VkDeviceFaultVendorBinaryHeaderVersionOneEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultInfoEXT)(VkDevice device, VkDeviceFaultCountsEXT* pFaultCounts, VkDeviceFaultInfoEXT* pFaultInfo); -#define VK_EXT_memory_priority 1 -#define VK_EXT_MEMORY_PRIORITY_SPEC_VERSION 1 -#define VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME "VK_EXT_memory_priority" -typedef struct VkPhysicalDeviceMemoryPriorityFeaturesEXT { +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultInfoEXT( + VkDevice device, + VkDeviceFaultCountsEXT* pFaultCounts, + VkDeviceFaultInfoEXT* pFaultInfo); +#endif + + +// VK_ARM_rasterization_order_attachment_access is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_rasterization_order_attachment_access 1 +#define VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION 1 +#define VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME "VK_ARM_rasterization_order_attachment_access" +typedef struct VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 memoryPriority; -} VkPhysicalDeviceMemoryPriorityFeaturesEXT; + VkBool32 rasterizationOrderColorAttachmentAccess; + VkBool32 rasterizationOrderDepthAttachmentAccess; + VkBool32 rasterizationOrderStencilAttachmentAccess; +} VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT; -typedef struct VkMemoryPriorityAllocateInfoEXT { - VkStructureType sType; - const void* pNext; - float priority; -} VkMemoryPriorityAllocateInfoEXT; +typedef VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM; -#define VK_NV_dedicated_allocation_image_aliasing 1 -#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION 1 -#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME "VK_NV_dedicated_allocation_image_aliasing" -typedef struct VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV { +// VK_EXT_rgba10x6_formats is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_rgba10x6_formats 1 +#define VK_EXT_RGBA10X6_FORMATS_SPEC_VERSION 1 +#define VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME "VK_EXT_rgba10x6_formats" +typedef struct VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 dedicatedAllocationImageAliasing; -} VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV; + VkBool32 formatRgba10x6WithoutYCbCrSampler; +} VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT; -#define VK_EXT_buffer_device_address 1 -#define VK_EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 2 -#define VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_EXT_buffer_device_address" -typedef struct VkPhysicalDeviceBufferDeviceAddressFeaturesEXT { +// VK_VALVE_mutable_descriptor_type is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_mutable_descriptor_type 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_VALVE_mutable_descriptor_type" +typedef struct VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 bufferDeviceAddress; - VkBool32 bufferDeviceAddressCaptureReplay; - VkBool32 bufferDeviceAddressMultiDevice; -} VkPhysicalDeviceBufferDeviceAddressFeaturesEXT; + VkBool32 mutableDescriptorType; +} VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT; -typedef VkPhysicalDeviceBufferDeviceAddressFeaturesEXT VkPhysicalDeviceBufferAddressFeaturesEXT; +typedef VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE; -typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoEXT; +typedef struct VkMutableDescriptorTypeListEXT { + uint32_t descriptorTypeCount; + const VkDescriptorType* pDescriptorTypes; +} VkMutableDescriptorTypeListEXT; -typedef struct VkBufferDeviceAddressCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkDeviceAddress deviceAddress; -} VkBufferDeviceAddressCreateInfoEXT; +typedef VkMutableDescriptorTypeListEXT VkMutableDescriptorTypeListVALVE; -typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressEXT)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef struct VkMutableDescriptorTypeCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t mutableDescriptorTypeListCount; + const VkMutableDescriptorTypeListEXT* pMutableDescriptorTypeLists; +} VkMutableDescriptorTypeCreateInfoEXT; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressEXT( - VkDevice device, - const VkBufferDeviceAddressInfo* pInfo); -#endif +typedef VkMutableDescriptorTypeCreateInfoEXT VkMutableDescriptorTypeCreateInfoVALVE; -#define VK_EXT_tooling_info 1 -#define VK_EXT_TOOLING_INFO_SPEC_VERSION 1 -#define VK_EXT_TOOLING_INFO_EXTENSION_NAME "VK_EXT_tooling_info" -typedef enum VkToolPurposeFlagBitsEXT { - VK_TOOL_PURPOSE_VALIDATION_BIT_EXT = 0x00000001, - VK_TOOL_PURPOSE_PROFILING_BIT_EXT = 0x00000002, - VK_TOOL_PURPOSE_TRACING_BIT_EXT = 0x00000004, - VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT = 0x00000008, - VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT = 0x00000010, - VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT = 0x00000020, - VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT = 0x00000040, - VK_TOOL_PURPOSE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkToolPurposeFlagBitsEXT; -typedef VkFlags VkToolPurposeFlagsEXT; -typedef struct VkPhysicalDeviceToolPropertiesEXT { - VkStructureType sType; - void* pNext; - char name[VK_MAX_EXTENSION_NAME_SIZE]; - char version[VK_MAX_EXTENSION_NAME_SIZE]; - VkToolPurposeFlagsEXT purposes; - char description[VK_MAX_DESCRIPTION_SIZE]; - char layer[VK_MAX_EXTENSION_NAME_SIZE]; -} VkPhysicalDeviceToolPropertiesEXT; +// VK_EXT_vertex_input_dynamic_state is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_vertex_input_dynamic_state 1 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION 2 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_vertex_input_dynamic_state" +typedef struct VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexInputDynamicState; +} VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT; + +typedef struct VkVertexInputBindingDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; + uint32_t divisor; +} VkVertexInputBindingDescription2EXT; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolPropertiesEXT)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolPropertiesEXT* pToolProperties); +typedef struct VkVertexInputAttributeDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription2EXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetVertexInputEXT)(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolPropertiesEXT( - VkPhysicalDevice physicalDevice, - uint32_t* pToolCount, - VkPhysicalDeviceToolPropertiesEXT* pToolProperties); +VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( + VkCommandBuffer commandBuffer, + uint32_t vertexBindingDescriptionCount, + const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, + uint32_t vertexAttributeDescriptionCount, + const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); #endif -#define VK_EXT_separate_stencil_usage 1 -#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1 -#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage" -typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; - +// VK_EXT_physical_device_drm is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_physical_device_drm 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME "VK_EXT_physical_device_drm" +typedef struct VkPhysicalDeviceDrmPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 hasPrimary; + VkBool32 hasRender; + int64_t primaryMajor; + int64_t primaryMinor; + int64_t renderMajor; + int64_t renderMinor; +} VkPhysicalDeviceDrmPropertiesEXT; -#define VK_EXT_validation_features 1 -#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 5 -#define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" -typedef enum VkValidationFeatureEnableEXT { - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, - VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, - VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, - VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4, - VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkValidationFeatureEnableEXT; +// VK_EXT_device_address_binding_report is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_device_address_binding_report 1 +#define VK_EXT_DEVICE_ADDRESS_BINDING_REPORT_SPEC_VERSION 1 +#define VK_EXT_DEVICE_ADDRESS_BINDING_REPORT_EXTENSION_NAME "VK_EXT_device_address_binding_report" -typedef enum VkValidationFeatureDisableEXT { - VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0, - VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1, - VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2, - VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3, - VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4, - VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5, - VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6, - VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT = 7, - VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkValidationFeatureDisableEXT; -typedef struct VkValidationFeaturesEXT { - VkStructureType sType; - const void* pNext; - uint32_t enabledValidationFeatureCount; - const VkValidationFeatureEnableEXT* pEnabledValidationFeatures; - uint32_t disabledValidationFeatureCount; - const VkValidationFeatureDisableEXT* pDisabledValidationFeatures; -} VkValidationFeaturesEXT; +typedef enum VkDeviceAddressBindingTypeEXT { + VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT = 0, + VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT = 1, + VK_DEVICE_ADDRESS_BINDING_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceAddressBindingTypeEXT; +typedef enum VkDeviceAddressBindingFlagBitsEXT { + VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT = 0x00000001, + VK_DEVICE_ADDRESS_BINDING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceAddressBindingFlagBitsEXT; +typedef VkFlags VkDeviceAddressBindingFlagsEXT; +typedef struct VkPhysicalDeviceAddressBindingReportFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 reportAddressBinding; +} VkPhysicalDeviceAddressBindingReportFeaturesEXT; +typedef struct VkDeviceAddressBindingCallbackDataEXT { + VkStructureType sType; + void* pNext; + VkDeviceAddressBindingFlagsEXT flags; + VkDeviceAddress baseAddress; + VkDeviceSize size; + VkDeviceAddressBindingTypeEXT bindingType; +} VkDeviceAddressBindingCallbackDataEXT; -#define VK_NV_cooperative_matrix 1 -#define VK_NV_COOPERATIVE_MATRIX_SPEC_VERSION 1 -#define VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_NV_cooperative_matrix" -typedef enum VkComponentTypeNV { - VK_COMPONENT_TYPE_FLOAT16_NV = 0, - VK_COMPONENT_TYPE_FLOAT32_NV = 1, - VK_COMPONENT_TYPE_FLOAT64_NV = 2, - VK_COMPONENT_TYPE_SINT8_NV = 3, - VK_COMPONENT_TYPE_SINT16_NV = 4, - VK_COMPONENT_TYPE_SINT32_NV = 5, - VK_COMPONENT_TYPE_SINT64_NV = 6, - VK_COMPONENT_TYPE_UINT8_NV = 7, - VK_COMPONENT_TYPE_UINT16_NV = 8, - VK_COMPONENT_TYPE_UINT32_NV = 9, - VK_COMPONENT_TYPE_UINT64_NV = 10, - VK_COMPONENT_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkComponentTypeNV; - -typedef enum VkScopeNV { - VK_SCOPE_DEVICE_NV = 1, - VK_SCOPE_WORKGROUP_NV = 2, - VK_SCOPE_SUBGROUP_NV = 3, - VK_SCOPE_QUEUE_FAMILY_NV = 5, - VK_SCOPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkScopeNV; -typedef struct VkCooperativeMatrixPropertiesNV { - VkStructureType sType; - void* pNext; - uint32_t MSize; - uint32_t NSize; - uint32_t KSize; - VkComponentTypeNV AType; - VkComponentTypeNV BType; - VkComponentTypeNV CType; - VkComponentTypeNV DType; - VkScopeNV scope; -} VkCooperativeMatrixPropertiesNV; -typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesNV { +// VK_EXT_depth_clip_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_clip_control 1 +#define VK_EXT_DEPTH_CLIP_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME "VK_EXT_depth_clip_control" +typedef struct VkPhysicalDeviceDepthClipControlFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 cooperativeMatrix; - VkBool32 cooperativeMatrixRobustBufferAccess; -} VkPhysicalDeviceCooperativeMatrixFeaturesNV; + VkBool32 depthClipControl; +} VkPhysicalDeviceDepthClipControlFeaturesEXT; -typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesNV { - VkStructureType sType; - void* pNext; - VkShaderStageFlags cooperativeMatrixSupportedStages; -} VkPhysicalDeviceCooperativeMatrixPropertiesNV; +typedef struct VkPipelineViewportDepthClipControlCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 negativeOneToOne; +} VkPipelineViewportDepthClipControlCreateInfoEXT; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkCooperativeMatrixPropertiesNV* pProperties); -#endif +// VK_EXT_primitive_topology_list_restart is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_primitive_topology_list_restart 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME "VK_EXT_primitive_topology_list_restart" +typedef struct VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitiveTopologyListRestart; + VkBool32 primitiveTopologyPatchListRestart; +} VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT; -#define VK_NV_coverage_reduction_mode 1 -#define VK_NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION 1 -#define VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME "VK_NV_coverage_reduction_mode" -typedef enum VkCoverageReductionModeNV { - VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0, - VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1, - VK_COVERAGE_REDUCTION_MODE_MAX_ENUM_NV = 0x7FFFFFFF -} VkCoverageReductionModeNV; -typedef VkFlags VkPipelineCoverageReductionStateCreateFlagsNV; -typedef struct VkPhysicalDeviceCoverageReductionModeFeaturesNV { + +// VK_HUAWEI_subpass_shading is a preprocessor guard. Do not pass it to API calls. +#define VK_HUAWEI_subpass_shading 1 +#define VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION 3 +#define VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME "VK_HUAWEI_subpass_shading" +typedef struct VkSubpassShadingPipelineCreateInfoHUAWEI { VkStructureType sType; void* pNext; - VkBool32 coverageReductionMode; -} VkPhysicalDeviceCoverageReductionModeFeaturesNV; + VkRenderPass renderPass; + uint32_t subpass; +} VkSubpassShadingPipelineCreateInfoHUAWEI; -typedef struct VkPipelineCoverageReductionStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineCoverageReductionStateCreateFlagsNV flags; - VkCoverageReductionModeNV coverageReductionMode; -} VkPipelineCoverageReductionStateCreateInfoNV; +typedef struct VkPhysicalDeviceSubpassShadingFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 subpassShading; +} VkPhysicalDeviceSubpassShadingFeaturesHUAWEI; -typedef struct VkFramebufferMixedSamplesCombinationNV { - VkStructureType sType; - void* pNext; - VkCoverageReductionModeNV coverageReductionMode; - VkSampleCountFlagBits rasterizationSamples; - VkSampleCountFlags depthStencilSamples; - VkSampleCountFlags colorSamples; -} VkFramebufferMixedSamplesCombinationNV; +typedef struct VkPhysicalDeviceSubpassShadingPropertiesHUAWEI { + VkStructureType sType; + void* pNext; + uint32_t maxSubpassShadingWorkgroupSizeAspectRatio; +} VkPhysicalDeviceSubpassShadingPropertiesHUAWEI; -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)(VkDevice device, VkRenderPass renderpass, VkExtent2D* pMaxWorkgroupSize); +typedef void (VKAPI_PTR *PFN_vkCmdSubpassShadingHUAWEI)(VkCommandBuffer commandBuffer); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( - VkPhysicalDevice physicalDevice, - uint32_t* pCombinationCount, - VkFramebufferMixedSamplesCombinationNV* pCombinations); +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI( + VkDevice device, + VkRenderPass renderpass, + VkExtent2D* pMaxWorkgroupSize); + +VKAPI_ATTR void VKAPI_CALL vkCmdSubpassShadingHUAWEI( + VkCommandBuffer commandBuffer); #endif -#define VK_EXT_fragment_shader_interlock 1 -#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION 1 -#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME "VK_EXT_fragment_shader_interlock" -typedef struct VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT { +// VK_HUAWEI_invocation_mask is a preprocessor guard. Do not pass it to API calls. +#define VK_HUAWEI_invocation_mask 1 +#define VK_HUAWEI_INVOCATION_MASK_SPEC_VERSION 1 +#define VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME "VK_HUAWEI_invocation_mask" +typedef struct VkPhysicalDeviceInvocationMaskFeaturesHUAWEI { VkStructureType sType; void* pNext; - VkBool32 fragmentShaderSampleInterlock; - VkBool32 fragmentShaderPixelInterlock; - VkBool32 fragmentShaderShadingRateInterlock; -} VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT; + VkBool32 invocationMask; +} VkPhysicalDeviceInvocationMaskFeaturesHUAWEI; + +typedef void (VKAPI_PTR *PFN_vkCmdBindInvocationMaskHUAWEI)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindInvocationMaskHUAWEI( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); +#endif -#define VK_EXT_ycbcr_image_arrays 1 -#define VK_EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION 1 -#define VK_EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME "VK_EXT_ycbcr_image_arrays" -typedef struct VkPhysicalDeviceYcbcrImageArraysFeaturesEXT { +// VK_NV_external_memory_rdma is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_memory_rdma 1 +typedef void* VkRemoteAddressNV; +#define VK_NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME "VK_NV_external_memory_rdma" +typedef struct VkMemoryGetRemoteAddressInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetRemoteAddressInfoNV; + +typedef struct VkPhysicalDeviceExternalMemoryRDMAFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 ycbcrImageArrays; -} VkPhysicalDeviceYcbcrImageArraysFeaturesEXT; + VkBool32 externalMemoryRDMA; +} VkPhysicalDeviceExternalMemoryRDMAFeaturesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryRemoteAddressNV)(VkDevice device, const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, VkRemoteAddressNV* pAddress); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryRemoteAddressNV( + VkDevice device, + const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, + VkRemoteAddressNV* pAddress); +#endif -#define VK_EXT_provoking_vertex 1 -#define VK_EXT_PROVOKING_VERTEX_SPEC_VERSION 1 -#define VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME "VK_EXT_provoking_vertex" +// VK_EXT_pipeline_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_properties 1 +#define VK_EXT_PIPELINE_PROPERTIES_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_PROPERTIES_EXTENSION_NAME "VK_EXT_pipeline_properties" +typedef VkPipelineInfoKHR VkPipelineInfoEXT; -typedef enum VkProvokingVertexModeEXT { - VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0, - VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1, - VK_PROVOKING_VERTEX_MODE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkProvokingVertexModeEXT; -typedef struct VkPhysicalDeviceProvokingVertexFeaturesEXT { +typedef struct VkPipelinePropertiesIdentifierEXT { VkStructureType sType; void* pNext; - VkBool32 provokingVertexLast; - VkBool32 transformFeedbackPreservesProvokingVertex; -} VkPhysicalDeviceProvokingVertexFeaturesEXT; + uint8_t pipelineIdentifier[VK_UUID_SIZE]; +} VkPipelinePropertiesIdentifierEXT; -typedef struct VkPhysicalDeviceProvokingVertexPropertiesEXT { +typedef struct VkPhysicalDevicePipelinePropertiesFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 provokingVertexModePerPipeline; - VkBool32 transformFeedbackPreservesTriangleFanProvokingVertex; -} VkPhysicalDeviceProvokingVertexPropertiesEXT; - -typedef struct VkPipelineRasterizationProvokingVertexStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkProvokingVertexModeEXT provokingVertexMode; -} VkPipelineRasterizationProvokingVertexStateCreateInfoEXT; - - - -#define VK_EXT_headless_surface 1 -#define VK_EXT_HEADLESS_SURFACE_SPEC_VERSION 1 -#define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" -typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT; -typedef struct VkHeadlessSurfaceCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkHeadlessSurfaceCreateFlagsEXT flags; -} VkHeadlessSurfaceCreateInfoEXT; + VkBool32 pipelinePropertiesIdentifier; +} VkPhysicalDevicePipelinePropertiesFeaturesEXT; -typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelinePropertiesEXT)(VkDevice device, const VkPipelineInfoEXT* pPipelineInfo, VkBaseOutStructure* pPipelineProperties); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT( - VkInstance instance, - const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelinePropertiesEXT( + VkDevice device, + const VkPipelineInfoEXT* pPipelineInfo, + VkBaseOutStructure* pPipelineProperties); #endif -#define VK_EXT_line_rasterization 1 -#define VK_EXT_LINE_RASTERIZATION_SPEC_VERSION 1 -#define VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME "VK_EXT_line_rasterization" +// VK_EXT_frame_boundary is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_frame_boundary 1 +#define VK_EXT_FRAME_BOUNDARY_SPEC_VERSION 1 +#define VK_EXT_FRAME_BOUNDARY_EXTENSION_NAME "VK_EXT_frame_boundary" -typedef enum VkLineRasterizationModeEXT { - VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = 0, - VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = 1, - VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = 2, - VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = 3, - VK_LINE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkLineRasterizationModeEXT; -typedef struct VkPhysicalDeviceLineRasterizationFeaturesEXT { +typedef enum VkFrameBoundaryFlagBitsEXT { + VK_FRAME_BOUNDARY_FRAME_END_BIT_EXT = 0x00000001, + VK_FRAME_BOUNDARY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkFrameBoundaryFlagBitsEXT; +typedef VkFlags VkFrameBoundaryFlagsEXT; +typedef struct VkPhysicalDeviceFrameBoundaryFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 rectangularLines; - VkBool32 bresenhamLines; - VkBool32 smoothLines; - VkBool32 stippledRectangularLines; - VkBool32 stippledBresenhamLines; - VkBool32 stippledSmoothLines; -} VkPhysicalDeviceLineRasterizationFeaturesEXT; + VkBool32 frameBoundary; +} VkPhysicalDeviceFrameBoundaryFeaturesEXT; -typedef struct VkPhysicalDeviceLineRasterizationPropertiesEXT { +typedef struct VkFrameBoundaryEXT { + VkStructureType sType; + const void* pNext; + VkFrameBoundaryFlagsEXT flags; + uint64_t frameID; + uint32_t imageCount; + const VkImage* pImages; + uint32_t bufferCount; + const VkBuffer* pBuffers; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkFrameBoundaryEXT; + + + +// VK_EXT_multisampled_render_to_single_sampled is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_multisampled_render_to_single_sampled 1 +#define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION 1 +#define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME "VK_EXT_multisampled_render_to_single_sampled" +typedef struct VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT { VkStructureType sType; void* pNext; - uint32_t lineSubPixelPrecisionBits; -} VkPhysicalDeviceLineRasterizationPropertiesEXT; + VkBool32 multisampledRenderToSingleSampled; +} VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT; -typedef struct VkPipelineRasterizationLineStateCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkLineRasterizationModeEXT lineRasterizationMode; - VkBool32 stippledLineEnable; - uint32_t lineStippleFactor; - uint16_t lineStipplePattern; -} VkPipelineRasterizationLineStateCreateInfoEXT; +typedef struct VkSubpassResolvePerformanceQueryEXT { + VkStructureType sType; + void* pNext; + VkBool32 optimal; +} VkSubpassResolvePerformanceQueryEXT; -typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEXT)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); +typedef struct VkMultisampledRenderToSingleSampledInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 multisampledRenderToSingleSampledEnable; + VkSampleCountFlagBits rasterizationSamples; +} VkMultisampledRenderToSingleSampledInfoEXT; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT( - VkCommandBuffer commandBuffer, - uint32_t lineStippleFactor, - uint16_t lineStipplePattern); -#endif -#define VK_EXT_shader_atomic_float 1 -#define VK_EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION 1 -#define VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME "VK_EXT_shader_atomic_float" -typedef struct VkPhysicalDeviceShaderAtomicFloatFeaturesEXT { +// VK_EXT_extended_dynamic_state2 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_extended_dynamic_state2 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME "VK_EXT_extended_dynamic_state2" +typedef struct VkPhysicalDeviceExtendedDynamicState2FeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 shaderBufferFloat32Atomics; - VkBool32 shaderBufferFloat32AtomicAdd; - VkBool32 shaderBufferFloat64Atomics; - VkBool32 shaderBufferFloat64AtomicAdd; - VkBool32 shaderSharedFloat32Atomics; - VkBool32 shaderSharedFloat32AtomicAdd; - VkBool32 shaderSharedFloat64Atomics; - VkBool32 shaderSharedFloat64AtomicAdd; - VkBool32 shaderImageFloat32Atomics; - VkBool32 shaderImageFloat32AtomicAdd; - VkBool32 sparseImageFloat32Atomics; - VkBool32 sparseImageFloat32AtomicAdd; -} VkPhysicalDeviceShaderAtomicFloatFeaturesEXT; + VkBool32 extendedDynamicState2; + VkBool32 extendedDynamicState2LogicOp; + VkBool32 extendedDynamicState2PatchControlPoints; +} VkPhysicalDeviceExtendedDynamicState2FeaturesEXT; +typedef void (VKAPI_PTR *PFN_vkCmdSetPatchControlPointsEXT)(VkCommandBuffer commandBuffer, uint32_t patchControlPoints); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEXT)(VkCommandBuffer commandBuffer, VkLogicOp logicOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPatchControlPointsEXT( + VkCommandBuffer commandBuffer, + uint32_t patchControlPoints); -#define VK_EXT_host_query_reset 1 -#define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1 -#define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME "VK_EXT_host_query_reset" -typedef VkPhysicalDeviceHostQueryResetFeatures VkPhysicalDeviceHostQueryResetFeaturesEXT; +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable); -typedef void (VKAPI_PTR *PFN_vkResetQueryPoolEXT)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( - VkDevice device, - VkQueryPool queryPool, - uint32_t firstQuery, - uint32_t queryCount); +VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEXT( + VkCommandBuffer commandBuffer, + VkLogicOp logicOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable); #endif -#define VK_EXT_index_type_uint8 1 -#define VK_EXT_INDEX_TYPE_UINT8_SPEC_VERSION 1 -#define VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME "VK_EXT_index_type_uint8" -typedef struct VkPhysicalDeviceIndexTypeUint8FeaturesEXT { +// VK_EXT_color_write_enable is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_color_write_enable 1 +#define VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION 1 +#define VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME "VK_EXT_color_write_enable" +typedef struct VkPhysicalDeviceColorWriteEnableFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 indexTypeUint8; -} VkPhysicalDeviceIndexTypeUint8FeaturesEXT; + VkBool32 colorWriteEnable; +} VkPhysicalDeviceColorWriteEnableFeaturesEXT; + +typedef struct VkPipelineColorWriteCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentCount; + const VkBool32* pColorWriteEnables; +} VkPipelineColorWriteCreateInfoEXT; +typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteEnableEXT)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteEnableEXT( + VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkBool32* pColorWriteEnables); +#endif -#define VK_EXT_extended_dynamic_state 1 -#define VK_EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION 1 -#define VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_extended_dynamic_state" -typedef struct VkPhysicalDeviceExtendedDynamicStateFeaturesEXT { + +// VK_EXT_primitives_generated_query is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_primitives_generated_query 1 +#define VK_EXT_PRIMITIVES_GENERATED_QUERY_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME "VK_EXT_primitives_generated_query" +typedef struct VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 extendedDynamicState; -} VkPhysicalDeviceExtendedDynamicStateFeaturesEXT; + VkBool32 primitivesGeneratedQuery; + VkBool32 primitivesGeneratedQueryWithRasterizerDiscard; + VkBool32 primitivesGeneratedQueryWithNonZeroStreams; +} VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT; + -typedef void (VKAPI_PTR *PFN_vkCmdSetCullModeEXT)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); -typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFaceEXT)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); -typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopologyEXT)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); -typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); -typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); -typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2EXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); -typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); -typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); -typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOpEXT)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); -typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); -typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); -typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOpEXT)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetCullModeEXT( - VkCommandBuffer commandBuffer, - VkCullModeFlags cullMode); +// VK_EXT_global_priority_query is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_global_priority_query 1 +#define VK_EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION 1 +#define VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME "VK_EXT_global_priority_query" +#define VK_MAX_GLOBAL_PRIORITY_SIZE_EXT VK_MAX_GLOBAL_PRIORITY_SIZE_KHR +typedef VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT; -VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFaceEXT( - VkCommandBuffer commandBuffer, - VkFrontFace frontFace); +typedef VkQueueFamilyGlobalPriorityPropertiesKHR VkQueueFamilyGlobalPriorityPropertiesEXT; -VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopologyEXT( - VkCommandBuffer commandBuffer, - VkPrimitiveTopology primitiveTopology); -VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCountEXT( - VkCommandBuffer commandBuffer, - uint32_t viewportCount, - const VkViewport* pViewports); -VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCountEXT( - VkCommandBuffer commandBuffer, - uint32_t scissorCount, - const VkRect2D* pScissors); +// VK_EXT_image_view_min_lod is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_view_min_lod 1 +#define VK_EXT_IMAGE_VIEW_MIN_LOD_SPEC_VERSION 1 +#define VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME "VK_EXT_image_view_min_lod" +typedef struct VkPhysicalDeviceImageViewMinLodFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 minLod; +} VkPhysicalDeviceImageViewMinLodFeaturesEXT; -VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2EXT( - VkCommandBuffer commandBuffer, - uint32_t firstBinding, - uint32_t bindingCount, - const VkBuffer* pBuffers, - const VkDeviceSize* pOffsets, - const VkDeviceSize* pSizes, - const VkDeviceSize* pStrides); +typedef struct VkImageViewMinLodCreateInfoEXT { + VkStructureType sType; + const void* pNext; + float minLod; +} VkImageViewMinLodCreateInfoEXT; -VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnableEXT( - VkCommandBuffer commandBuffer, - VkBool32 depthTestEnable); -VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnableEXT( - VkCommandBuffer commandBuffer, - VkBool32 depthWriteEnable); -VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOpEXT( - VkCommandBuffer commandBuffer, - VkCompareOp depthCompareOp); +// VK_EXT_multi_draw is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_multi_draw 1 +#define VK_EXT_MULTI_DRAW_SPEC_VERSION 1 +#define VK_EXT_MULTI_DRAW_EXTENSION_NAME "VK_EXT_multi_draw" +typedef struct VkPhysicalDeviceMultiDrawFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 multiDraw; +} VkPhysicalDeviceMultiDrawFeaturesEXT; -VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnableEXT( - VkCommandBuffer commandBuffer, - VkBool32 depthBoundsTestEnable); +typedef struct VkPhysicalDeviceMultiDrawPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxMultiDrawCount; +} VkPhysicalDeviceMultiDrawPropertiesEXT; -VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnableEXT( +typedef struct VkMultiDrawInfoEXT { + uint32_t firstVertex; + uint32_t vertexCount; +} VkMultiDrawInfoEXT; + +typedef struct VkMultiDrawIndexedInfoEXT { + uint32_t firstIndex; + uint32_t indexCount; + int32_t vertexOffset; +} VkMultiDrawIndexedInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT* pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiIndexedEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiEXT( VkCommandBuffer commandBuffer, - VkBool32 stencilTestEnable); + uint32_t drawCount, + const VkMultiDrawInfoEXT* pVertexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride); -VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( VkCommandBuffer commandBuffer, - VkStencilFaceFlags faceMask, - VkStencilOp failOp, - VkStencilOp passOp, - VkStencilOp depthFailOp, - VkCompareOp compareOp); + uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT* pIndexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride, + const int32_t* pVertexOffset); #endif -#define VK_EXT_shader_atomic_float2 1 -#define VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION 1 -#define VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME "VK_EXT_shader_atomic_float2" -typedef struct VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT { +// VK_EXT_image_2d_view_of_3d is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_2d_view_of_3d 1 +#define VK_EXT_IMAGE_2D_VIEW_OF_3D_SPEC_VERSION 1 +#define VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME "VK_EXT_image_2d_view_of_3d" +typedef struct VkPhysicalDeviceImage2DViewOf3DFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 shaderBufferFloat16Atomics; - VkBool32 shaderBufferFloat16AtomicAdd; - VkBool32 shaderBufferFloat16AtomicMinMax; - VkBool32 shaderBufferFloat32AtomicMinMax; - VkBool32 shaderBufferFloat64AtomicMinMax; - VkBool32 shaderSharedFloat16Atomics; - VkBool32 shaderSharedFloat16AtomicAdd; - VkBool32 shaderSharedFloat16AtomicMinMax; - VkBool32 shaderSharedFloat32AtomicMinMax; - VkBool32 shaderSharedFloat64AtomicMinMax; - VkBool32 shaderImageFloat32AtomicMinMax; - VkBool32 sparseImageFloat32AtomicMinMax; -} VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT; + VkBool32 image2DViewOf3D; + VkBool32 sampler2DViewOf3D; +} VkPhysicalDeviceImage2DViewOf3DFeaturesEXT; -#define VK_EXT_shader_demote_to_helper_invocation 1 -#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1 -#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation" -typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT { +// VK_EXT_shader_tile_image is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_tile_image 1 +#define VK_EXT_SHADER_TILE_IMAGE_SPEC_VERSION 1 +#define VK_EXT_SHADER_TILE_IMAGE_EXTENSION_NAME "VK_EXT_shader_tile_image" +typedef struct VkPhysicalDeviceShaderTileImageFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 shaderDemoteToHelperInvocation; -} VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT; + VkBool32 shaderTileImageColorReadAccess; + VkBool32 shaderTileImageDepthReadAccess; + VkBool32 shaderTileImageStencilReadAccess; +} VkPhysicalDeviceShaderTileImageFeaturesEXT; +typedef struct VkPhysicalDeviceShaderTileImagePropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderTileImageCoherentReadAccelerated; + VkBool32 shaderTileImageReadSampleFromPixelRateInvocation; + VkBool32 shaderTileImageReadFromHelperInvocation; +} VkPhysicalDeviceShaderTileImagePropertiesEXT; -#define VK_NV_device_generated_commands 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV) -#define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 -#define VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NV_device_generated_commands" -typedef enum VkIndirectCommandsTokenTypeNV { - VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkIndirectCommandsTokenTypeNV; +// VK_EXT_opacity_micromap is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_opacity_micromap 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkMicromapEXT) +#define VK_EXT_OPACITY_MICROMAP_SPEC_VERSION 2 +#define VK_EXT_OPACITY_MICROMAP_EXTENSION_NAME "VK_EXT_opacity_micromap" -typedef enum VkIndirectStateFlagBitsNV { - VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001, - VK_INDIRECT_STATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkIndirectStateFlagBitsNV; -typedef VkFlags VkIndirectStateFlagsNV; +typedef enum VkMicromapTypeEXT { + VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT = 0, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_MICROMAP_TYPE_DISPLACEMENT_MICROMAP_NV = 1000397000, +#endif + VK_MICROMAP_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkMicromapTypeEXT; + +typedef enum VkBuildMicromapModeEXT { + VK_BUILD_MICROMAP_MODE_BUILD_EXT = 0, + VK_BUILD_MICROMAP_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkBuildMicromapModeEXT; + +typedef enum VkCopyMicromapModeEXT { + VK_COPY_MICROMAP_MODE_CLONE_EXT = 0, + VK_COPY_MICROMAP_MODE_SERIALIZE_EXT = 1, + VK_COPY_MICROMAP_MODE_DESERIALIZE_EXT = 2, + VK_COPY_MICROMAP_MODE_COMPACT_EXT = 3, + VK_COPY_MICROMAP_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkCopyMicromapModeEXT; + +typedef enum VkOpacityMicromapFormatEXT { + VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT = 1, + VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT = 2, + VK_OPACITY_MICROMAP_FORMAT_MAX_ENUM_EXT = 0x7FFFFFFF +} VkOpacityMicromapFormatEXT; + +typedef enum VkOpacityMicromapSpecialIndexEXT { + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT = -1, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT = -2, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT = -3, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT = -4, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_MAX_ENUM_EXT = 0x7FFFFFFF +} VkOpacityMicromapSpecialIndexEXT; -typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV { - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkIndirectCommandsLayoutUsageFlagBitsNV; -typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV; -typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV { +typedef enum VkAccelerationStructureCompatibilityKHR { + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCompatibilityKHR; + +typedef enum VkAccelerationStructureBuildTypeKHR { + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureBuildTypeKHR; + +typedef enum VkBuildMicromapFlagBitsEXT { + VK_BUILD_MICROMAP_PREFER_FAST_TRACE_BIT_EXT = 0x00000001, + VK_BUILD_MICROMAP_PREFER_FAST_BUILD_BIT_EXT = 0x00000002, + VK_BUILD_MICROMAP_ALLOW_COMPACTION_BIT_EXT = 0x00000004, + VK_BUILD_MICROMAP_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkBuildMicromapFlagBitsEXT; +typedef VkFlags VkBuildMicromapFlagsEXT; + +typedef enum VkMicromapCreateFlagBitsEXT { + VK_MICROMAP_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = 0x00000001, + VK_MICROMAP_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkMicromapCreateFlagBitsEXT; +typedef VkFlags VkMicromapCreateFlagsEXT; +typedef struct VkMicromapUsageEXT { + uint32_t count; + uint32_t subdivisionLevel; + uint32_t format; +} VkMicromapUsageEXT; + +typedef union VkDeviceOrHostAddressKHR { + VkDeviceAddress deviceAddress; + void* hostAddress; +} VkDeviceOrHostAddressKHR; + +typedef struct VkMicromapBuildInfoEXT { + VkStructureType sType; + const void* pNext; + VkMicromapTypeEXT type; + VkBuildMicromapFlagsEXT flags; + VkBuildMicromapModeEXT mode; + VkMicromapEXT dstMicromap; + uint32_t usageCountsCount; + const VkMicromapUsageEXT* pUsageCounts; + const VkMicromapUsageEXT* const* ppUsageCounts; + VkDeviceOrHostAddressConstKHR data; + VkDeviceOrHostAddressKHR scratchData; + VkDeviceOrHostAddressConstKHR triangleArray; + VkDeviceSize triangleArrayStride; +} VkMicromapBuildInfoEXT; + +typedef struct VkMicromapCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkMicromapCreateFlagsEXT createFlags; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; + VkMicromapTypeEXT type; + VkDeviceAddress deviceAddress; +} VkMicromapCreateInfoEXT; + +typedef struct VkPhysicalDeviceOpacityMicromapFeaturesEXT { VkStructureType sType; void* pNext; - uint32_t maxGraphicsShaderGroupCount; - uint32_t maxIndirectSequenceCount; - uint32_t maxIndirectCommandsTokenCount; - uint32_t maxIndirectCommandsStreamCount; - uint32_t maxIndirectCommandsTokenOffset; - uint32_t maxIndirectCommandsStreamStride; - uint32_t minSequencesCountBufferOffsetAlignment; - uint32_t minSequencesIndexBufferOffsetAlignment; - uint32_t minIndirectCommandsBufferOffsetAlignment; -} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV; + VkBool32 micromap; + VkBool32 micromapCaptureReplay; + VkBool32 micromapHostCommands; +} VkPhysicalDeviceOpacityMicromapFeaturesEXT; -typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV { +typedef struct VkPhysicalDeviceOpacityMicromapPropertiesEXT { VkStructureType sType; void* pNext; - VkBool32 deviceGeneratedCommands; -} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV; - -typedef struct VkGraphicsShaderGroupCreateInfoNV { - VkStructureType sType; - const void* pNext; - uint32_t stageCount; - const VkPipelineShaderStageCreateInfo* pStages; - const VkPipelineVertexInputStateCreateInfo* pVertexInputState; - const VkPipelineTessellationStateCreateInfo* pTessellationState; -} VkGraphicsShaderGroupCreateInfoNV; + uint32_t maxOpacity2StateSubdivisionLevel; + uint32_t maxOpacity4StateSubdivisionLevel; +} VkPhysicalDeviceOpacityMicromapPropertiesEXT; -typedef struct VkGraphicsPipelineShaderGroupsCreateInfoNV { - VkStructureType sType; - const void* pNext; - uint32_t groupCount; - const VkGraphicsShaderGroupCreateInfoNV* pGroups; - uint32_t pipelineCount; - const VkPipeline* pPipelines; -} VkGraphicsPipelineShaderGroupsCreateInfoNV; +typedef struct VkMicromapVersionInfoEXT { + VkStructureType sType; + const void* pNext; + const uint8_t* pVersionData; +} VkMicromapVersionInfoEXT; -typedef struct VkBindShaderGroupIndirectCommandNV { - uint32_t groupIndex; -} VkBindShaderGroupIndirectCommandNV; +typedef struct VkCopyMicromapToMemoryInfoEXT { + VkStructureType sType; + const void* pNext; + VkMicromapEXT src; + VkDeviceOrHostAddressKHR dst; + VkCopyMicromapModeEXT mode; +} VkCopyMicromapToMemoryInfoEXT; -typedef struct VkBindIndexBufferIndirectCommandNV { - VkDeviceAddress bufferAddress; - uint32_t size; - VkIndexType indexType; -} VkBindIndexBufferIndirectCommandNV; +typedef struct VkCopyMemoryToMicromapInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR src; + VkMicromapEXT dst; + VkCopyMicromapModeEXT mode; +} VkCopyMemoryToMicromapInfoEXT; -typedef struct VkBindVertexBufferIndirectCommandNV { - VkDeviceAddress bufferAddress; - uint32_t size; - uint32_t stride; -} VkBindVertexBufferIndirectCommandNV; +typedef struct VkCopyMicromapInfoEXT { + VkStructureType sType; + const void* pNext; + VkMicromapEXT src; + VkMicromapEXT dst; + VkCopyMicromapModeEXT mode; +} VkCopyMicromapInfoEXT; -typedef struct VkSetStateFlagsIndirectCommandNV { - uint32_t data; -} VkSetStateFlagsIndirectCommandNV; +typedef struct VkMicromapBuildSizesInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceSize micromapSize; + VkDeviceSize buildScratchSize; + VkBool32 discardable; +} VkMicromapBuildSizesInfoEXT; -typedef struct VkIndirectCommandsStreamNV { - VkBuffer buffer; - VkDeviceSize offset; -} VkIndirectCommandsStreamNV; +typedef struct VkAccelerationStructureTrianglesOpacityMicromapEXT { + VkStructureType sType; + void* pNext; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexBuffer; + VkDeviceSize indexStride; + uint32_t baseTriangle; + uint32_t usageCountsCount; + const VkMicromapUsageEXT* pUsageCounts; + const VkMicromapUsageEXT* const* ppUsageCounts; + VkMicromapEXT micromap; +} VkAccelerationStructureTrianglesOpacityMicromapEXT; + +typedef struct VkMicromapTriangleEXT { + uint32_t dataOffset; + uint16_t subdivisionLevel; + uint16_t format; +} VkMicromapTriangleEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMicromapEXT)(VkDevice device, const VkMicromapCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkMicromapEXT* pMicromap); +typedef void (VKAPI_PTR *PFN_vkDestroyMicromapEXT)(VkDevice device, VkMicromapEXT micromap, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBuildMicromapsEXT)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBuildMicromapsEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMicromapEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMicromapToMemoryEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapToMemoryInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToMicromapEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToMicromapInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteMicromapsPropertiesEXT)(VkDevice device, uint32_t micromapCount, const VkMicromapEXT* pMicromaps, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMicromapEXT)(VkCommandBuffer commandBuffer, const VkCopyMicromapInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMicromapToMemoryEXT)(VkCommandBuffer commandBuffer, const VkCopyMicromapToMemoryInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToMicromapEXT)(VkCommandBuffer commandBuffer, const VkCopyMemoryToMicromapInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteMicromapsPropertiesEXT)(VkCommandBuffer commandBuffer, uint32_t micromapCount, const VkMicromapEXT* pMicromaps, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkGetDeviceMicromapCompatibilityEXT)(VkDevice device, const VkMicromapVersionInfoEXT* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +typedef void (VKAPI_PTR *PFN_vkGetMicromapBuildSizesEXT)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkMicromapBuildInfoEXT* pBuildInfo, VkMicromapBuildSizesInfoEXT* pSizeInfo); -typedef struct VkIndirectCommandsLayoutTokenNV { - VkStructureType sType; - const void* pNext; - VkIndirectCommandsTokenTypeNV tokenType; - uint32_t stream; - uint32_t offset; - uint32_t vertexBindingUnit; - VkBool32 vertexDynamicStride; - VkPipelineLayout pushconstantPipelineLayout; - VkShaderStageFlags pushconstantShaderStageFlags; - uint32_t pushconstantOffset; - uint32_t pushconstantSize; - VkIndirectStateFlagsNV indirectStateFlags; - uint32_t indexTypeCount; - const VkIndexType* pIndexTypes; - const uint32_t* pIndexTypeValues; -} VkIndirectCommandsLayoutTokenNV; +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMicromapEXT( + VkDevice device, + const VkMicromapCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkMicromapEXT* pMicromap); -typedef struct VkIndirectCommandsLayoutCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkIndirectCommandsLayoutUsageFlagsNV flags; - VkPipelineBindPoint pipelineBindPoint; - uint32_t tokenCount; - const VkIndirectCommandsLayoutTokenNV* pTokens; - uint32_t streamCount; - const uint32_t* pStreamStrides; -} VkIndirectCommandsLayoutCreateInfoNV; +VKAPI_ATTR void VKAPI_CALL vkDestroyMicromapEXT( + VkDevice device, + VkMicromapEXT micromap, + const VkAllocationCallbacks* pAllocator); -typedef struct VkGeneratedCommandsInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineBindPoint pipelineBindPoint; - VkPipeline pipeline; - VkIndirectCommandsLayoutNV indirectCommandsLayout; - uint32_t streamCount; - const VkIndirectCommandsStreamNV* pStreams; - uint32_t sequencesCount; - VkBuffer preprocessBuffer; - VkDeviceSize preprocessOffset; - VkDeviceSize preprocessSize; - VkBuffer sequencesCountBuffer; - VkDeviceSize sequencesCountOffset; - VkBuffer sequencesIndexBuffer; - VkDeviceSize sequencesIndexOffset; -} VkGeneratedCommandsInfoNV; +VKAPI_ATTR void VKAPI_CALL vkCmdBuildMicromapsEXT( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkMicromapBuildInfoEXT* pInfos); -typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineBindPoint pipelineBindPoint; - VkPipeline pipeline; - VkIndirectCommandsLayoutNV indirectCommandsLayout; - uint32_t maxSequencesCount; -} VkGeneratedCommandsMemoryRequirementsInfoNV; +VKAPI_ATTR VkResult VKAPI_CALL vkBuildMicromapsEXT( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + uint32_t infoCount, + const VkMicromapBuildInfoEXT* pInfos); -typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsNV)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsNV)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); -typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsNV)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); -typedef void (VKAPI_PTR *PFN_vkCmdBindPipelineShaderGroupNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex); -typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); -typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMicromapEXT( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMicromapInfoEXT* pInfo); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV( +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMicromapToMemoryEXT( VkDevice device, - const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, - VkMemoryRequirements2* pMemoryRequirements); + VkDeferredOperationKHR deferredOperation, + const VkCopyMicromapToMemoryInfoEXT* pInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV( +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToMicromapEXT( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMemoryToMicromapInfoEXT* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkWriteMicromapsPropertiesEXT( + VkDevice device, + uint32_t micromapCount, + const VkMicromapEXT* pMicromaps, + VkQueryType queryType, + size_t dataSize, + void* pData, + size_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMicromapEXT( VkCommandBuffer commandBuffer, - const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + const VkCopyMicromapInfoEXT* pInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV( +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMicromapToMemoryEXT( VkCommandBuffer commandBuffer, - VkBool32 isPreprocessed, - const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + const VkCopyMicromapToMemoryInfoEXT* pInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV( +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToMicromapEXT( VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipeline pipeline, - uint32_t groupIndex); + const VkCopyMemoryToMicromapInfoEXT* pInfo); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV( +VKAPI_ATTR void VKAPI_CALL vkCmdWriteMicromapsPropertiesEXT( + VkCommandBuffer commandBuffer, + uint32_t micromapCount, + const VkMicromapEXT* pMicromaps, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceMicromapCompatibilityEXT( VkDevice device, - const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); + const VkMicromapVersionInfoEXT* pVersionInfo, + VkAccelerationStructureCompatibilityKHR* pCompatibility); -VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( +VKAPI_ATTR void VKAPI_CALL vkGetMicromapBuildSizesEXT( VkDevice device, - VkIndirectCommandsLayoutNV indirectCommandsLayout, - const VkAllocationCallbacks* pAllocator); + VkAccelerationStructureBuildTypeKHR buildType, + const VkMicromapBuildInfoEXT* pBuildInfo, + VkMicromapBuildSizesInfoEXT* pSizeInfo); #endif -#define VK_NV_inherited_viewport_scissor 1 -#define VK_NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION 1 -#define VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME "VK_NV_inherited_viewport_scissor" -typedef struct VkPhysicalDeviceInheritedViewportScissorFeaturesNV { +// VK_EXT_load_store_op_none is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_load_store_op_none 1 +#define VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION 1 +#define VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_EXT_load_store_op_none" + + +// VK_HUAWEI_cluster_culling_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_HUAWEI_cluster_culling_shader 1 +#define VK_HUAWEI_CLUSTER_CULLING_SHADER_SPEC_VERSION 2 +#define VK_HUAWEI_CLUSTER_CULLING_SHADER_EXTENSION_NAME "VK_HUAWEI_cluster_culling_shader" +typedef struct VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI { VkStructureType sType; void* pNext; - VkBool32 inheritedViewportScissor2D; -} VkPhysicalDeviceInheritedViewportScissorFeaturesNV; + VkBool32 clustercullingShader; + VkBool32 multiviewClusterCullingShader; +} VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI; -typedef struct VkCommandBufferInheritanceViewportScissorInfoNV { - VkStructureType sType; - const void* pNext; - VkBool32 viewportScissor2D; - uint32_t viewportDepthCount; - const VkViewport* pViewportDepths; -} VkCommandBufferInheritanceViewportScissorInfoNV; +typedef struct VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI { + VkStructureType sType; + void* pNext; + uint32_t maxWorkGroupCount[3]; + uint32_t maxWorkGroupSize[3]; + uint32_t maxOutputClusterCount; + VkDeviceSize indirectBufferOffsetAlignment; +} VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterHUAWEI)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterIndirectHUAWEI)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterHUAWEI( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); +VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterIndirectHUAWEI( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset); +#endif -#define VK_EXT_texel_buffer_alignment 1 -#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 -#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" -typedef struct VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT { +// VK_EXT_border_color_swizzle is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_border_color_swizzle 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME "VK_EXT_border_color_swizzle" +typedef struct VkPhysicalDeviceBorderColorSwizzleFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 texelBufferAlignment; -} VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT; + VkBool32 borderColorSwizzle; + VkBool32 borderColorSwizzleFromImage; +} VkPhysicalDeviceBorderColorSwizzleFeaturesEXT; + +typedef struct VkSamplerBorderColorComponentMappingCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkComponentMapping components; + VkBool32 srgb; +} VkSamplerBorderColorComponentMappingCreateInfoEXT; + -typedef struct VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT { + +// VK_EXT_pageable_device_local_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pageable_device_local_memory 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME "VK_EXT_pageable_device_local_memory" +typedef struct VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT { VkStructureType sType; void* pNext; - VkDeviceSize storageTexelBufferOffsetAlignmentBytes; - VkBool32 storageTexelBufferOffsetSingleTexelAlignment; - VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; - VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; -} VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT; + VkBool32 pageableDeviceLocalMemory; +} VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT; +typedef void (VKAPI_PTR *PFN_vkSetDeviceMemoryPriorityEXT)(VkDevice device, VkDeviceMemory memory, float priority); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetDeviceMemoryPriorityEXT( + VkDevice device, + VkDeviceMemory memory, + float priority); +#endif -#define VK_QCOM_render_pass_transform 1 -#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 2 -#define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" -typedef struct VkRenderPassTransformBeginInfoQCOM { - VkStructureType sType; - void* pNext; - VkSurfaceTransformFlagBitsKHR transform; -} VkRenderPassTransformBeginInfoQCOM; -typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { - VkStructureType sType; - void* pNext; - VkSurfaceTransformFlagBitsKHR transform; - VkRect2D renderArea; -} VkCommandBufferInheritanceRenderPassTransformInfoQCOM; +// VK_ARM_shader_core_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_shader_core_properties 1 +#define VK_ARM_SHADER_CORE_PROPERTIES_SPEC_VERSION 1 +#define VK_ARM_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_ARM_shader_core_properties" +typedef struct VkPhysicalDeviceShaderCorePropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t pixelRate; + uint32_t texelRate; + uint32_t fmaRate; +} VkPhysicalDeviceShaderCorePropertiesARM; -#define VK_EXT_device_memory_report 1 -#define VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION 2 -#define VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME "VK_EXT_device_memory_report" +// VK_ARM_scheduling_controls is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_scheduling_controls 1 +#define VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION 1 +#define VK_ARM_SCHEDULING_CONTROLS_EXTENSION_NAME "VK_ARM_scheduling_controls" +typedef VkFlags64 VkPhysicalDeviceSchedulingControlsFlagsARM; -typedef enum VkDeviceMemoryReportEventTypeEXT { - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT = 0, - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT = 1, - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT = 2, - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT = 3, - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT = 4, - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDeviceMemoryReportEventTypeEXT; -typedef VkFlags VkDeviceMemoryReportFlagsEXT; -typedef struct VkPhysicalDeviceDeviceMemoryReportFeaturesEXT { +typedef enum VkPhysicalDeviceSchedulingControlsFlagBitsARM { + VK_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_SHADER_CORE_COUNT_ARM = 0x00000001, + VK_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkPhysicalDeviceSchedulingControlsFlagBitsARM; +typedef struct VkDeviceQueueShaderCoreControlCreateInfoARM { VkStructureType sType; void* pNext; - VkBool32 deviceMemoryReport; -} VkPhysicalDeviceDeviceMemoryReportFeaturesEXT; + uint32_t shaderCoreCount; +} VkDeviceQueueShaderCoreControlCreateInfoARM; -typedef struct VkDeviceMemoryReportCallbackDataEXT { - VkStructureType sType; - void* pNext; - VkDeviceMemoryReportFlagsEXT flags; - VkDeviceMemoryReportEventTypeEXT type; - uint64_t memoryObjectId; - VkDeviceSize size; - VkObjectType objectType; - uint64_t objectHandle; - uint32_t heapIndex; -} VkDeviceMemoryReportCallbackDataEXT; +typedef struct VkPhysicalDeviceSchedulingControlsFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 schedulingControls; +} VkPhysicalDeviceSchedulingControlsFeaturesARM; -typedef void (VKAPI_PTR *PFN_vkDeviceMemoryReportCallbackEXT)( - const VkDeviceMemoryReportCallbackDataEXT* pCallbackData, - void* pUserData); +typedef struct VkPhysicalDeviceSchedulingControlsPropertiesARM { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceSchedulingControlsFlagsARM schedulingControlsFlags; +} VkPhysicalDeviceSchedulingControlsPropertiesARM; -typedef struct VkDeviceDeviceMemoryReportCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkDeviceMemoryReportFlagsEXT flags; - PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback; - void* pUserData; -} VkDeviceDeviceMemoryReportCreateInfoEXT; +// VK_EXT_image_sliced_view_of_3d is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_sliced_view_of_3d 1 +#define VK_EXT_IMAGE_SLICED_VIEW_OF_3D_SPEC_VERSION 1 +#define VK_EXT_IMAGE_SLICED_VIEW_OF_3D_EXTENSION_NAME "VK_EXT_image_sliced_view_of_3d" +#define VK_REMAINING_3D_SLICES_EXT (~0U) +typedef struct VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 imageSlicedViewOf3D; +} VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT; -#define VK_EXT_acquire_drm_display 1 -#define VK_EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION 1 -#define VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_drm_display" -typedef VkResult (VKAPI_PTR *PFN_vkAcquireDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, VkDisplayKHR display); -typedef VkResult (VKAPI_PTR *PFN_vkGetDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, uint32_t connectorId, VkDisplayKHR* display); +typedef struct VkImageViewSlicedCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t sliceOffset; + uint32_t sliceCount; +} VkImageViewSlicedCreateInfoEXT; + + + +// VK_VALVE_descriptor_set_host_mapping is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_descriptor_set_host_mapping 1 +#define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_SPEC_VERSION 1 +#define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_EXTENSION_NAME "VK_VALVE_descriptor_set_host_mapping" +typedef struct VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 descriptorSetHostMapping; +} VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE; + +typedef struct VkDescriptorSetBindingReferenceVALVE { + VkStructureType sType; + const void* pNext; + VkDescriptorSetLayout descriptorSetLayout; + uint32_t binding; +} VkDescriptorSetBindingReferenceVALVE; + +typedef struct VkDescriptorSetLayoutHostMappingInfoVALVE { + VkStructureType sType; + void* pNext; + size_t descriptorOffset; + uint32_t descriptorSize; +} VkDescriptorSetLayoutHostMappingInfoVALVE; + +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)(VkDevice device, const VkDescriptorSetBindingReferenceVALVE* pBindingReference, VkDescriptorSetLayoutHostMappingInfoVALVE* pHostMapping); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetHostMappingVALVE)(VkDevice device, VkDescriptorSet descriptorSet, void** ppData); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkAcquireDrmDisplayEXT( - VkPhysicalDevice physicalDevice, - int32_t drmFd, - VkDisplayKHR display); +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutHostMappingInfoVALVE( + VkDevice device, + const VkDescriptorSetBindingReferenceVALVE* pBindingReference, + VkDescriptorSetLayoutHostMappingInfoVALVE* pHostMapping); -VKAPI_ATTR VkResult VKAPI_CALL vkGetDrmDisplayEXT( - VkPhysicalDevice physicalDevice, - int32_t drmFd, - uint32_t connectorId, - VkDisplayKHR* display); +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetHostMappingVALVE( + VkDevice device, + VkDescriptorSet descriptorSet, + void** ppData); #endif -#define VK_EXT_robustness2 1 -#define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 -#define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" -typedef struct VkPhysicalDeviceRobustness2FeaturesEXT { +// VK_EXT_depth_clamp_zero_one is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_clamp_zero_one 1 +#define VK_EXT_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME "VK_EXT_depth_clamp_zero_one" +typedef struct VkPhysicalDeviceDepthClampZeroOneFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthClampZeroOne; +} VkPhysicalDeviceDepthClampZeroOneFeaturesEXT; + + + +// VK_EXT_non_seamless_cube_map is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_non_seamless_cube_map 1 +#define VK_EXT_NON_SEAMLESS_CUBE_MAP_SPEC_VERSION 1 +#define VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME "VK_EXT_non_seamless_cube_map" +typedef struct VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 nonSeamlessCubeMap; +} VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT; + + + +// VK_QCOM_fragment_density_map_offset is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_fragment_density_map_offset 1 +#define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION 1 +#define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME "VK_QCOM_fragment_density_map_offset" +typedef struct VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapOffset; +} VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM; + +typedef struct VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM { + VkStructureType sType; + void* pNext; + VkExtent2D fragmentDensityOffsetGranularity; +} VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM; + +typedef struct VkSubpassFragmentDensityMapOffsetEndInfoQCOM { + VkStructureType sType; + const void* pNext; + uint32_t fragmentDensityOffsetCount; + const VkOffset2D* pFragmentDensityOffsets; +} VkSubpassFragmentDensityMapOffsetEndInfoQCOM; + + + +// VK_NV_copy_memory_indirect is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_copy_memory_indirect 1 +#define VK_NV_COPY_MEMORY_INDIRECT_SPEC_VERSION 1 +#define VK_NV_COPY_MEMORY_INDIRECT_EXTENSION_NAME "VK_NV_copy_memory_indirect" +typedef struct VkCopyMemoryIndirectCommandNV { + VkDeviceAddress srcAddress; + VkDeviceAddress dstAddress; + VkDeviceSize size; +} VkCopyMemoryIndirectCommandNV; + +typedef struct VkCopyMemoryToImageIndirectCommandNV { + VkDeviceAddress srcAddress; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkCopyMemoryToImageIndirectCommandNV; + +typedef struct VkPhysicalDeviceCopyMemoryIndirectFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 robustBufferAccess2; - VkBool32 robustImageAccess2; - VkBool32 nullDescriptor; -} VkPhysicalDeviceRobustness2FeaturesEXT; + VkBool32 indirectCopy; +} VkPhysicalDeviceCopyMemoryIndirectFeaturesNV; -typedef struct VkPhysicalDeviceRobustness2PropertiesEXT { +typedef struct VkPhysicalDeviceCopyMemoryIndirectPropertiesNV { VkStructureType sType; void* pNext; - VkDeviceSize robustStorageBufferAccessSizeAlignment; - VkDeviceSize robustUniformBufferAccessSizeAlignment; -} VkPhysicalDeviceRobustness2PropertiesEXT; + VkQueueFlags supportedQueues; +} VkPhysicalDeviceCopyMemoryIndirectPropertiesNV; +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryIndirectNV)(VkCommandBuffer commandBuffer, VkDeviceAddress copyBufferAddress, uint32_t copyCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToImageIndirectNV)(VkCommandBuffer commandBuffer, VkDeviceAddress copyBufferAddress, uint32_t copyCount, uint32_t stride, VkImage dstImage, VkImageLayout dstImageLayout, const VkImageSubresourceLayers* pImageSubresources); +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryIndirectNV( + VkCommandBuffer commandBuffer, + VkDeviceAddress copyBufferAddress, + uint32_t copyCount, + uint32_t stride); -#define VK_EXT_custom_border_color 1 -#define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 -#define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" -typedef struct VkSamplerCustomBorderColorCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkClearColorValue customBorderColor; - VkFormat format; -} VkSamplerCustomBorderColorCreateInfoEXT; +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageIndirectNV( + VkCommandBuffer commandBuffer, + VkDeviceAddress copyBufferAddress, + uint32_t copyCount, + uint32_t stride, + VkImage dstImage, + VkImageLayout dstImageLayout, + const VkImageSubresourceLayers* pImageSubresources); +#endif -typedef struct VkPhysicalDeviceCustomBorderColorPropertiesEXT { - VkStructureType sType; - void* pNext; - uint32_t maxCustomBorderColorSamplers; -} VkPhysicalDeviceCustomBorderColorPropertiesEXT; -typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { +// VK_NV_memory_decompression is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_memory_decompression 1 +#define VK_NV_MEMORY_DECOMPRESSION_SPEC_VERSION 1 +#define VK_NV_MEMORY_DECOMPRESSION_EXTENSION_NAME "VK_NV_memory_decompression" + +// Flag bits for VkMemoryDecompressionMethodFlagBitsNV +typedef VkFlags64 VkMemoryDecompressionMethodFlagBitsNV; +static const VkMemoryDecompressionMethodFlagBitsNV VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV = 0x00000001ULL; + +typedef VkFlags64 VkMemoryDecompressionMethodFlagsNV; +typedef struct VkDecompressMemoryRegionNV { + VkDeviceAddress srcAddress; + VkDeviceAddress dstAddress; + VkDeviceSize compressedSize; + VkDeviceSize decompressedSize; + VkMemoryDecompressionMethodFlagsNV decompressionMethod; +} VkDecompressMemoryRegionNV; + +typedef struct VkPhysicalDeviceMemoryDecompressionFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 customBorderColors; - VkBool32 customBorderColorWithoutFormat; -} VkPhysicalDeviceCustomBorderColorFeaturesEXT; + VkBool32 memoryDecompression; +} VkPhysicalDeviceMemoryDecompressionFeaturesNV; +typedef struct VkPhysicalDeviceMemoryDecompressionPropertiesNV { + VkStructureType sType; + void* pNext; + VkMemoryDecompressionMethodFlagsNV decompressionMethods; + uint64_t maxDecompressionIndirectCount; +} VkPhysicalDeviceMemoryDecompressionPropertiesNV; +typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryNV)(VkCommandBuffer commandBuffer, uint32_t decompressRegionCount, const VkDecompressMemoryRegionNV* pDecompressMemoryRegions); +typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryIndirectCountNV)(VkCommandBuffer commandBuffer, VkDeviceAddress indirectCommandsAddress, VkDeviceAddress indirectCommandsCountAddress, uint32_t stride); -#define VK_GOOGLE_user_type 1 -#define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 -#define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type" +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryNV( + VkCommandBuffer commandBuffer, + uint32_t decompressRegionCount, + const VkDecompressMemoryRegionNV* pDecompressMemoryRegions); +VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryIndirectCountNV( + VkCommandBuffer commandBuffer, + VkDeviceAddress indirectCommandsAddress, + VkDeviceAddress indirectCommandsCountAddress, + uint32_t stride); +#endif -#define VK_EXT_private_data 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlotEXT) -#define VK_EXT_PRIVATE_DATA_SPEC_VERSION 1 -#define VK_EXT_PRIVATE_DATA_EXTENSION_NAME "VK_EXT_private_data" -typedef enum VkPrivateDataSlotCreateFlagBitsEXT { - VK_PRIVATE_DATA_SLOT_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkPrivateDataSlotCreateFlagBitsEXT; -typedef VkFlags VkPrivateDataSlotCreateFlagsEXT; -typedef struct VkPhysicalDevicePrivateDataFeaturesEXT { +// VK_NV_device_generated_commands_compute is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_device_generated_commands_compute 1 +#define VK_NV_DEVICE_GENERATED_COMMANDS_COMPUTE_SPEC_VERSION 2 +#define VK_NV_DEVICE_GENERATED_COMMANDS_COMPUTE_EXTENSION_NAME "VK_NV_device_generated_commands_compute" +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 privateData; -} VkPhysicalDevicePrivateDataFeaturesEXT; + VkBool32 deviceGeneratedCompute; + VkBool32 deviceGeneratedComputePipelines; + VkBool32 deviceGeneratedComputeCaptureReplay; +} VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV; -typedef struct VkDevicePrivateDataCreateInfoEXT { +typedef struct VkComputePipelineIndirectBufferInfoNV { VkStructureType sType; const void* pNext; - uint32_t privateDataSlotRequestCount; -} VkDevicePrivateDataCreateInfoEXT; + VkDeviceAddress deviceAddress; + VkDeviceSize size; + VkDeviceAddress pipelineDeviceAddressCaptureReplay; +} VkComputePipelineIndirectBufferInfoNV; -typedef struct VkPrivateDataSlotCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkPrivateDataSlotCreateFlagsEXT flags; -} VkPrivateDataSlotCreateInfoEXT; +typedef struct VkPipelineIndirectDeviceAddressInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; +} VkPipelineIndirectDeviceAddressInfoNV; -typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlotEXT)(VkDevice device, const VkPrivateDataSlotCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlotEXT* pPrivateDataSlot); -typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlotEXT)(VkDevice device, VkPrivateDataSlotEXT privateDataSlot, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlotEXT privateDataSlot, uint64_t data); -typedef void (VKAPI_PTR *PFN_vkGetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlotEXT privateDataSlot, uint64_t* pData); +typedef struct VkBindPipelineIndirectCommandNV { + VkDeviceAddress pipelineAddress; +} VkBindPipelineIndirectCommandNV; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlotEXT( - VkDevice device, - const VkPrivateDataSlotCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkPrivateDataSlotEXT* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkGetPipelineIndirectMemoryRequirementsNV)(VkDevice device, const VkComputePipelineCreateInfo* pCreateInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdUpdatePipelineIndirectBufferNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetPipelineIndirectDeviceAddressNV)(VkDevice device, const VkPipelineIndirectDeviceAddressInfoNV* pInfo); -VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlotEXT( +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPipelineIndirectMemoryRequirementsNV( VkDevice device, - VkPrivateDataSlotEXT privateDataSlot, - const VkAllocationCallbacks* pAllocator); + const VkComputePipelineCreateInfo* pCreateInfo, + VkMemoryRequirements2* pMemoryRequirements); -VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateDataEXT( - VkDevice device, - VkObjectType objectType, - uint64_t objectHandle, - VkPrivateDataSlotEXT privateDataSlot, - uint64_t data); +VKAPI_ATTR void VKAPI_CALL vkCmdUpdatePipelineIndirectBufferNV( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline); -VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetPipelineIndirectDeviceAddressNV( VkDevice device, - VkObjectType objectType, - uint64_t objectHandle, - VkPrivateDataSlotEXT privateDataSlot, - uint64_t* pData); + const VkPipelineIndirectDeviceAddressInfoNV* pInfo); #endif -#define VK_EXT_pipeline_creation_cache_control 1 -#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 3 -#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control" -typedef struct VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT { +// VK_NV_linear_color_attachment is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_linear_color_attachment 1 +#define VK_NV_LINEAR_COLOR_ATTACHMENT_SPEC_VERSION 1 +#define VK_NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME "VK_NV_linear_color_attachment" +typedef struct VkPhysicalDeviceLinearColorAttachmentFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 pipelineCreationCacheControl; -} VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT; + VkBool32 linearColorAttachment; +} VkPhysicalDeviceLinearColorAttachmentFeaturesNV; -#define VK_NV_device_diagnostics_config 1 -#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 1 -#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config" +// VK_GOOGLE_surfaceless_query is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_surfaceless_query 1 +#define VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION 2 +#define VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME "VK_GOOGLE_surfaceless_query" -typedef enum VkDeviceDiagnosticsConfigFlagBitsNV { - VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0x00000001, - VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0x00000002, - VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0x00000004, - VK_DEVICE_DIAGNOSTICS_CONFIG_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkDeviceDiagnosticsConfigFlagBitsNV; -typedef VkFlags VkDeviceDiagnosticsConfigFlagsNV; -typedef struct VkPhysicalDeviceDiagnosticsConfigFeaturesNV { + +// VK_EXT_image_compression_control_swapchain is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_compression_control_swapchain 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_SPEC_VERSION 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME "VK_EXT_image_compression_control_swapchain" +typedef struct VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 diagnosticsConfig; -} VkPhysicalDeviceDiagnosticsConfigFeaturesNV; + VkBool32 imageCompressionControlSwapchain; +} VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT; -typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkDeviceDiagnosticsConfigFlagsNV flags; -} VkDeviceDiagnosticsConfigCreateInfoNV; +// VK_QCOM_image_processing is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_image_processing 1 +#define VK_QCOM_IMAGE_PROCESSING_SPEC_VERSION 1 +#define VK_QCOM_IMAGE_PROCESSING_EXTENSION_NAME "VK_QCOM_image_processing" +typedef struct VkImageViewSampleWeightCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkOffset2D filterCenter; + VkExtent2D filterSize; + uint32_t numPhases; +} VkImageViewSampleWeightCreateInfoQCOM; -#define VK_QCOM_render_pass_store_ops 1 -#define VK_QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION 2 -#define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" +typedef struct VkPhysicalDeviceImageProcessingFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 textureSampleWeighted; + VkBool32 textureBoxFilter; + VkBool32 textureBlockMatch; +} VkPhysicalDeviceImageProcessingFeaturesQCOM; +typedef struct VkPhysicalDeviceImageProcessingPropertiesQCOM { + VkStructureType sType; + void* pNext; + uint32_t maxWeightFilterPhases; + VkExtent2D maxWeightFilterDimension; + VkExtent2D maxBlockMatchRegion; + VkExtent2D maxBoxFilterBlockSize; +} VkPhysicalDeviceImageProcessingPropertiesQCOM; -#define VK_NV_fragment_shading_rate_enums 1 -#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION 1 -#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME "VK_NV_fragment_shading_rate_enums" -typedef enum VkFragmentShadingRateTypeNV { - VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0, - VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1, - VK_FRAGMENT_SHADING_RATE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkFragmentShadingRateTypeNV; -typedef enum VkFragmentShadingRateNV { - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0, - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1, - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4, - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5, - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6, - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9, - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10, - VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11, - VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12, - VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13, - VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14, - VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15, - VK_FRAGMENT_SHADING_RATE_MAX_ENUM_NV = 0x7FFFFFFF -} VkFragmentShadingRateNV; -typedef struct VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV { +// VK_EXT_nested_command_buffer is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_nested_command_buffer 1 +#define VK_EXT_NESTED_COMMAND_BUFFER_SPEC_VERSION 1 +#define VK_EXT_NESTED_COMMAND_BUFFER_EXTENSION_NAME "VK_EXT_nested_command_buffer" +typedef struct VkPhysicalDeviceNestedCommandBufferFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 fragmentShadingRateEnums; - VkBool32 supersampleFragmentShadingRates; - VkBool32 noInvocationFragmentShadingRates; -} VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV; + VkBool32 nestedCommandBuffer; + VkBool32 nestedCommandBufferRendering; + VkBool32 nestedCommandBufferSimultaneousUse; +} VkPhysicalDeviceNestedCommandBufferFeaturesEXT; -typedef struct VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV { - VkStructureType sType; - void* pNext; - VkSampleCountFlagBits maxFragmentShadingRateInvocationCount; -} VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV; +typedef struct VkPhysicalDeviceNestedCommandBufferPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxCommandBufferNestingLevel; +} VkPhysicalDeviceNestedCommandBufferPropertiesEXT; -typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkFragmentShadingRateTypeNV shadingRateType; - VkFragmentShadingRateNV shadingRate; - VkFragmentShadingRateCombinerOpKHR combinerOps[2]; -} VkPipelineFragmentShadingRateEnumStateCreateInfoNV; -typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateEnumNV)(VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +// VK_EXT_external_memory_acquire_unmodified is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_external_memory_acquire_unmodified 1 +#define VK_EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXTENSION_NAME "VK_EXT_external_memory_acquire_unmodified" +typedef struct VkExternalMemoryAcquireUnmodifiedEXT { + VkStructureType sType; + const void* pNext; + VkBool32 acquireUnmodifiedMemory; +} VkExternalMemoryAcquireUnmodifiedEXT; + + + +// VK_EXT_extended_dynamic_state3 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_extended_dynamic_state3 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_3_SPEC_VERSION 2 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME "VK_EXT_extended_dynamic_state3" +typedef struct VkPhysicalDeviceExtendedDynamicState3FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState3TessellationDomainOrigin; + VkBool32 extendedDynamicState3DepthClampEnable; + VkBool32 extendedDynamicState3PolygonMode; + VkBool32 extendedDynamicState3RasterizationSamples; + VkBool32 extendedDynamicState3SampleMask; + VkBool32 extendedDynamicState3AlphaToCoverageEnable; + VkBool32 extendedDynamicState3AlphaToOneEnable; + VkBool32 extendedDynamicState3LogicOpEnable; + VkBool32 extendedDynamicState3ColorBlendEnable; + VkBool32 extendedDynamicState3ColorBlendEquation; + VkBool32 extendedDynamicState3ColorWriteMask; + VkBool32 extendedDynamicState3RasterizationStream; + VkBool32 extendedDynamicState3ConservativeRasterizationMode; + VkBool32 extendedDynamicState3ExtraPrimitiveOverestimationSize; + VkBool32 extendedDynamicState3DepthClipEnable; + VkBool32 extendedDynamicState3SampleLocationsEnable; + VkBool32 extendedDynamicState3ColorBlendAdvanced; + VkBool32 extendedDynamicState3ProvokingVertexMode; + VkBool32 extendedDynamicState3LineRasterizationMode; + VkBool32 extendedDynamicState3LineStippleEnable; + VkBool32 extendedDynamicState3DepthClipNegativeOneToOne; + VkBool32 extendedDynamicState3ViewportWScalingEnable; + VkBool32 extendedDynamicState3ViewportSwizzle; + VkBool32 extendedDynamicState3CoverageToColorEnable; + VkBool32 extendedDynamicState3CoverageToColorLocation; + VkBool32 extendedDynamicState3CoverageModulationMode; + VkBool32 extendedDynamicState3CoverageModulationTableEnable; + VkBool32 extendedDynamicState3CoverageModulationTable; + VkBool32 extendedDynamicState3CoverageReductionMode; + VkBool32 extendedDynamicState3RepresentativeFragmentTestEnable; + VkBool32 extendedDynamicState3ShadingRateImageEnable; +} VkPhysicalDeviceExtendedDynamicState3FeaturesEXT; + +typedef struct VkPhysicalDeviceExtendedDynamicState3PropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 dynamicPrimitiveTopologyUnrestricted; +} VkPhysicalDeviceExtendedDynamicState3PropertiesEXT; + +typedef struct VkColorBlendEquationEXT { + VkBlendFactor srcColorBlendFactor; + VkBlendFactor dstColorBlendFactor; + VkBlendOp colorBlendOp; + VkBlendFactor srcAlphaBlendFactor; + VkBlendFactor dstAlphaBlendFactor; + VkBlendOp alphaBlendOp; +} VkColorBlendEquationEXT; + +typedef struct VkColorBlendAdvancedEXT { + VkBlendOp advancedBlendOp; + VkBool32 srcPremultiplied; + VkBool32 dstPremultiplied; + VkBlendOverlapEXT blendOverlap; + VkBool32 clampResults; +} VkColorBlendAdvancedEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetTessellationDomainOriginEXT)(VkCommandBuffer commandBuffer, VkTessellationDomainOrigin domainOrigin); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthClampEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthClampEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetPolygonModeEXT)(VkCommandBuffer commandBuffer, VkPolygonMode polygonMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizationSamplesEXT)(VkCommandBuffer commandBuffer, VkSampleCountFlagBits rasterizationSamples); +typedef void (VKAPI_PTR *PFN_vkCmdSetSampleMaskEXT)(VkCommandBuffer commandBuffer, VkSampleCountFlagBits samples, const VkSampleMask* pSampleMask); +typedef void (VKAPI_PTR *PFN_vkCmdSetAlphaToCoverageEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 alphaToCoverageEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetAlphaToOneEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 alphaToOneEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 logicOpEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorBlendEnableEXT)(VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkBool32* pColorBlendEnables); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorBlendEquationEXT)(VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendEquationEXT* pColorBlendEquations); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteMaskEXT)(VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorComponentFlags* pColorWriteMasks); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizationStreamEXT)(VkCommandBuffer commandBuffer, uint32_t rasterizationStream); +typedef void (VKAPI_PTR *PFN_vkCmdSetConservativeRasterizationModeEXT)(VkCommandBuffer commandBuffer, VkConservativeRasterizationModeEXT conservativeRasterizationMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)(VkCommandBuffer commandBuffer, float extraPrimitiveOverestimationSize); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthClipEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthClipEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 sampleLocationsEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorBlendAdvancedEXT)(VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendAdvancedEXT* pColorBlendAdvanced); +typedef void (VKAPI_PTR *PFN_vkCmdSetProvokingVertexModeEXT)(VkCommandBuffer commandBuffer, VkProvokingVertexModeEXT provokingVertexMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineRasterizationModeEXT)(VkCommandBuffer commandBuffer, VkLineRasterizationModeEXT lineRasterizationMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 stippledLineEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthClipNegativeOneToOneEXT)(VkCommandBuffer commandBuffer, VkBool32 negativeOneToOne); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingEnableNV)(VkCommandBuffer commandBuffer, VkBool32 viewportWScalingEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportSwizzleNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportSwizzleNV* pViewportSwizzles); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageToColorEnableNV)(VkCommandBuffer commandBuffer, VkBool32 coverageToColorEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageToColorLocationNV)(VkCommandBuffer commandBuffer, uint32_t coverageToColorLocation); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageModulationModeNV)(VkCommandBuffer commandBuffer, VkCoverageModulationModeNV coverageModulationMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageModulationTableEnableNV)(VkCommandBuffer commandBuffer, VkBool32 coverageModulationTableEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageModulationTableNV)(VkCommandBuffer commandBuffer, uint32_t coverageModulationTableCount, const float* pCoverageModulationTable); +typedef void (VKAPI_PTR *PFN_vkCmdSetShadingRateImageEnableNV)(VkCommandBuffer commandBuffer, VkBool32 shadingRateImageEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetRepresentativeFragmentTestEnableNV)(VkCommandBuffer commandBuffer, VkBool32 representativeFragmentTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageReductionModeNV)(VkCommandBuffer commandBuffer, VkCoverageReductionModeNV coverageReductionMode); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( +VKAPI_ATTR void VKAPI_CALL vkCmdSetTessellationDomainOriginEXT( VkCommandBuffer commandBuffer, - VkFragmentShadingRateNV shadingRate, - const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); -#endif + VkTessellationDomainOrigin domainOrigin); +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClampEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthClampEnable); -#define VK_NV_ray_tracing_motion_blur 1 -#define VK_NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION 1 -#define VK_NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME "VK_NV_ray_tracing_motion_blur" +VKAPI_ATTR void VKAPI_CALL vkCmdSetPolygonModeEXT( + VkCommandBuffer commandBuffer, + VkPolygonMode polygonMode); -typedef enum VkAccelerationStructureMotionInstanceTypeNV { - VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV = 0, - VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV = 1, - VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV = 2, - VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkAccelerationStructureMotionInstanceTypeNV; -typedef VkFlags VkAccelerationStructureMotionInfoFlagsNV; -typedef VkFlags VkAccelerationStructureMotionInstanceFlagsNV; -typedef union VkDeviceOrHostAddressConstKHR { - VkDeviceAddress deviceAddress; - const void* hostAddress; -} VkDeviceOrHostAddressConstKHR; +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizationSamplesEXT( + VkCommandBuffer commandBuffer, + VkSampleCountFlagBits rasterizationSamples); -typedef struct VkAccelerationStructureGeometryMotionTrianglesDataNV { - VkStructureType sType; - const void* pNext; - VkDeviceOrHostAddressConstKHR vertexData; -} VkAccelerationStructureGeometryMotionTrianglesDataNV; +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleMaskEXT( + VkCommandBuffer commandBuffer, + VkSampleCountFlagBits samples, + const VkSampleMask* pSampleMask); -typedef struct VkAccelerationStructureMotionInfoNV { - VkStructureType sType; - const void* pNext; - uint32_t maxInstances; - VkAccelerationStructureMotionInfoFlagsNV flags; -} VkAccelerationStructureMotionInfoNV; +VKAPI_ATTR void VKAPI_CALL vkCmdSetAlphaToCoverageEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 alphaToCoverageEnable); -typedef struct VkAccelerationStructureMatrixMotionInstanceNV { - VkTransformMatrixKHR transformT0; - VkTransformMatrixKHR transformT1; - uint32_t instanceCustomIndex:24; - uint32_t mask:8; - uint32_t instanceShaderBindingTableRecordOffset:24; - VkGeometryInstanceFlagsKHR flags:8; - uint64_t accelerationStructureReference; -} VkAccelerationStructureMatrixMotionInstanceNV; +VKAPI_ATTR void VKAPI_CALL vkCmdSetAlphaToOneEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 alphaToOneEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 logicOpEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendEnableEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkBool32* pColorBlendEnables); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendEquationEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorBlendEquationEXT* pColorBlendEquations); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteMaskEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorComponentFlags* pColorWriteMasks); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizationStreamEXT( + VkCommandBuffer commandBuffer, + uint32_t rasterizationStream); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetConservativeRasterizationModeEXT( + VkCommandBuffer commandBuffer, + VkConservativeRasterizationModeEXT conservativeRasterizationMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetExtraPrimitiveOverestimationSizeEXT( + VkCommandBuffer commandBuffer, + float extraPrimitiveOverestimationSize); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClipEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthClipEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 sampleLocationsEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendAdvancedEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorBlendAdvancedEXT* pColorBlendAdvanced); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetProvokingVertexModeEXT( + VkCommandBuffer commandBuffer, + VkProvokingVertexModeEXT provokingVertexMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineRasterizationModeEXT( + VkCommandBuffer commandBuffer, + VkLineRasterizationModeEXT lineRasterizationMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stippledLineEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClipNegativeOneToOneEXT( + VkCommandBuffer commandBuffer, + VkBool32 negativeOneToOne); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 viewportWScalingEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportSwizzleNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewportSwizzleNV* pViewportSwizzles); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageToColorEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 coverageToColorEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageToColorLocationNV( + VkCommandBuffer commandBuffer, + uint32_t coverageToColorLocation); -typedef struct VkSRTDataNV { - float sx; - float a; - float b; - float pvx; - float sy; - float c; - float pvy; - float sz; - float pvz; - float qx; - float qy; - float qz; - float qw; - float tx; - float ty; - float tz; -} VkSRTDataNV; +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationModeNV( + VkCommandBuffer commandBuffer, + VkCoverageModulationModeNV coverageModulationMode); -typedef struct VkAccelerationStructureSRTMotionInstanceNV { - VkSRTDataNV transformT0; - VkSRTDataNV transformT1; - uint32_t instanceCustomIndex:24; - uint32_t mask:8; - uint32_t instanceShaderBindingTableRecordOffset:24; - VkGeometryInstanceFlagsKHR flags:8; - uint64_t accelerationStructureReference; -} VkAccelerationStructureSRTMotionInstanceNV; +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationTableEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 coverageModulationTableEnable); -typedef union VkAccelerationStructureMotionInstanceDataNV { - VkAccelerationStructureInstanceKHR staticInstance; - VkAccelerationStructureMatrixMotionInstanceNV matrixMotionInstance; - VkAccelerationStructureSRTMotionInstanceNV srtMotionInstance; -} VkAccelerationStructureMotionInstanceDataNV; +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationTableNV( + VkCommandBuffer commandBuffer, + uint32_t coverageModulationTableCount, + const float* pCoverageModulationTable); -typedef struct VkAccelerationStructureMotionInstanceNV { - VkAccelerationStructureMotionInstanceTypeNV type; - VkAccelerationStructureMotionInstanceFlagsNV flags; - VkAccelerationStructureMotionInstanceDataNV data; -} VkAccelerationStructureMotionInstanceNV; +VKAPI_ATTR void VKAPI_CALL vkCmdSetShadingRateImageEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 shadingRateImageEnable); -typedef struct VkPhysicalDeviceRayTracingMotionBlurFeaturesNV { - VkStructureType sType; - void* pNext; - VkBool32 rayTracingMotionBlur; - VkBool32 rayTracingMotionBlurPipelineTraceRaysIndirect; -} VkPhysicalDeviceRayTracingMotionBlurFeaturesNV; +VKAPI_ATTR void VKAPI_CALL vkCmdSetRepresentativeFragmentTestEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 representativeFragmentTestEnable); +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageReductionModeNV( + VkCommandBuffer commandBuffer, + VkCoverageReductionModeNV coverageReductionMode); +#endif -#define VK_EXT_ycbcr_2plane_444_formats 1 -#define VK_EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION 1 -#define VK_EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME "VK_EXT_ycbcr_2plane_444_formats" -typedef struct VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT { +// VK_EXT_subpass_merge_feedback is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_subpass_merge_feedback 1 +#define VK_EXT_SUBPASS_MERGE_FEEDBACK_SPEC_VERSION 2 +#define VK_EXT_SUBPASS_MERGE_FEEDBACK_EXTENSION_NAME "VK_EXT_subpass_merge_feedback" + +typedef enum VkSubpassMergeStatusEXT { + VK_SUBPASS_MERGE_STATUS_MERGED_EXT = 0, + VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT = 1, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SIDE_EFFECTS_EXT = 2, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SAMPLES_MISMATCH_EXT = 3, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_VIEWS_MISMATCH_EXT = 4, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_ALIASING_EXT = 5, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPENDENCIES_EXT = 6, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INCOMPATIBLE_INPUT_ATTACHMENT_EXT = 7, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_TOO_MANY_ATTACHMENTS_EXT = 8, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INSUFFICIENT_STORAGE_EXT = 9, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPTH_STENCIL_COUNT_EXT = 10, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_RESOLVE_ATTACHMENT_REUSE_EXT = 11, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT = 12, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_UNSPECIFIED_EXT = 13, + VK_SUBPASS_MERGE_STATUS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSubpassMergeStatusEXT; +typedef struct VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 ycbcr2plane444Formats; -} VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT; + VkBool32 subpassMergeFeedback; +} VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT; +typedef struct VkRenderPassCreationControlEXT { + VkStructureType sType; + const void* pNext; + VkBool32 disallowMerging; +} VkRenderPassCreationControlEXT; +typedef struct VkRenderPassCreationFeedbackInfoEXT { + uint32_t postMergeSubpassCount; +} VkRenderPassCreationFeedbackInfoEXT; -#define VK_EXT_fragment_density_map2 1 -#define VK_EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION 1 -#define VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME "VK_EXT_fragment_density_map2" -typedef struct VkPhysicalDeviceFragmentDensityMap2FeaturesEXT { +typedef struct VkRenderPassCreationFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkRenderPassCreationFeedbackInfoEXT* pRenderPassFeedback; +} VkRenderPassCreationFeedbackCreateInfoEXT; + +typedef struct VkRenderPassSubpassFeedbackInfoEXT { + VkSubpassMergeStatusEXT subpassMergeStatus; + char description[VK_MAX_DESCRIPTION_SIZE]; + uint32_t postMergeIndex; +} VkRenderPassSubpassFeedbackInfoEXT; + +typedef struct VkRenderPassSubpassFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkRenderPassSubpassFeedbackInfoEXT* pSubpassFeedback; +} VkRenderPassSubpassFeedbackCreateInfoEXT; + + + +// VK_LUNARG_direct_driver_loading is a preprocessor guard. Do not pass it to API calls. +#define VK_LUNARG_direct_driver_loading 1 +#define VK_LUNARG_DIRECT_DRIVER_LOADING_SPEC_VERSION 1 +#define VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME "VK_LUNARG_direct_driver_loading" + +typedef enum VkDirectDriverLoadingModeLUNARG { + VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG = 0, + VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG = 1, + VK_DIRECT_DRIVER_LOADING_MODE_MAX_ENUM_LUNARG = 0x7FFFFFFF +} VkDirectDriverLoadingModeLUNARG; +typedef VkFlags VkDirectDriverLoadingFlagsLUNARG; +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddrLUNARG)( + VkInstance instance, const char* pName); + +typedef struct VkDirectDriverLoadingInfoLUNARG { + VkStructureType sType; + void* pNext; + VkDirectDriverLoadingFlagsLUNARG flags; + PFN_vkGetInstanceProcAddrLUNARG pfnGetInstanceProcAddr; +} VkDirectDriverLoadingInfoLUNARG; + +typedef struct VkDirectDriverLoadingListLUNARG { + VkStructureType sType; + const void* pNext; + VkDirectDriverLoadingModeLUNARG mode; + uint32_t driverCount; + const VkDirectDriverLoadingInfoLUNARG* pDrivers; +} VkDirectDriverLoadingListLUNARG; + + + +// VK_EXT_shader_module_identifier is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_module_identifier 1 +#define VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT 32U +#define VK_EXT_SHADER_MODULE_IDENTIFIER_SPEC_VERSION 1 +#define VK_EXT_SHADER_MODULE_IDENTIFIER_EXTENSION_NAME "VK_EXT_shader_module_identifier" +typedef struct VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 fragmentDensityMapDeferred; -} VkPhysicalDeviceFragmentDensityMap2FeaturesEXT; + VkBool32 shaderModuleIdentifier; +} VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT; -typedef struct VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { +typedef struct VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT { VkStructureType sType; void* pNext; - VkBool32 subsampledLoads; - VkBool32 subsampledCoarseReconstructionEarlyAccess; - uint32_t maxSubsampledArrayLayers; - uint32_t maxDescriptorSetSubsampledSamplers; -} VkPhysicalDeviceFragmentDensityMap2PropertiesEXT; + uint8_t shaderModuleIdentifierAlgorithmUUID[VK_UUID_SIZE]; +} VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT; +typedef struct VkPipelineShaderStageModuleIdentifierCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t identifierSize; + const uint8_t* pIdentifier; +} VkPipelineShaderStageModuleIdentifierCreateInfoEXT; +typedef struct VkShaderModuleIdentifierEXT { + VkStructureType sType; + void* pNext; + uint32_t identifierSize; + uint8_t identifier[VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT]; +} VkShaderModuleIdentifierEXT; -#define VK_QCOM_rotated_copy_commands 1 -#define VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION 1 -#define VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME "VK_QCOM_rotated_copy_commands" -typedef struct VkCopyCommandTransformInfoQCOM { - VkStructureType sType; - const void* pNext; - VkSurfaceTransformFlagBitsKHR transform; -} VkCopyCommandTransformInfoQCOM; +typedef void (VKAPI_PTR *PFN_vkGetShaderModuleIdentifierEXT)(VkDevice device, VkShaderModule shaderModule, VkShaderModuleIdentifierEXT* pIdentifier); +typedef void (VKAPI_PTR *PFN_vkGetShaderModuleCreateInfoIdentifierEXT)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModuleIdentifierEXT* pIdentifier); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetShaderModuleIdentifierEXT( + VkDevice device, + VkShaderModule shaderModule, + VkShaderModuleIdentifierEXT* pIdentifier); +VKAPI_ATTR void VKAPI_CALL vkGetShaderModuleCreateInfoIdentifierEXT( + VkDevice device, + const VkShaderModuleCreateInfo* pCreateInfo, + VkShaderModuleIdentifierEXT* pIdentifier); +#endif -#define VK_EXT_image_robustness 1 -#define VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION 1 -#define VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_image_robustness" -typedef struct VkPhysicalDeviceImageRobustnessFeaturesEXT { +// VK_EXT_rasterization_order_attachment_access is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_rasterization_order_attachment_access 1 +#define VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION 1 +#define VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME "VK_EXT_rasterization_order_attachment_access" + + +// VK_NV_optical_flow is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_optical_flow 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkOpticalFlowSessionNV) +#define VK_NV_OPTICAL_FLOW_SPEC_VERSION 1 +#define VK_NV_OPTICAL_FLOW_EXTENSION_NAME "VK_NV_optical_flow" + +typedef enum VkOpticalFlowPerformanceLevelNV { + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_UNKNOWN_NV = 0, + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_SLOW_NV = 1, + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_MEDIUM_NV = 2, + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_FAST_NV = 3, + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowPerformanceLevelNV; + +typedef enum VkOpticalFlowSessionBindingPointNV { + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_UNKNOWN_NV = 0, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_INPUT_NV = 1, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_REFERENCE_NV = 2, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_HINT_NV = 3, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_FLOW_VECTOR_NV = 4, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_FLOW_VECTOR_NV = 5, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_COST_NV = 6, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_COST_NV = 7, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_GLOBAL_FLOW_NV = 8, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowSessionBindingPointNV; + +typedef enum VkOpticalFlowGridSizeFlagBitsNV { + VK_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_NV = 0, + VK_OPTICAL_FLOW_GRID_SIZE_1X1_BIT_NV = 0x00000001, + VK_OPTICAL_FLOW_GRID_SIZE_2X2_BIT_NV = 0x00000002, + VK_OPTICAL_FLOW_GRID_SIZE_4X4_BIT_NV = 0x00000004, + VK_OPTICAL_FLOW_GRID_SIZE_8X8_BIT_NV = 0x00000008, + VK_OPTICAL_FLOW_GRID_SIZE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowGridSizeFlagBitsNV; +typedef VkFlags VkOpticalFlowGridSizeFlagsNV; + +typedef enum VkOpticalFlowUsageFlagBitsNV { + VK_OPTICAL_FLOW_USAGE_UNKNOWN_NV = 0, + VK_OPTICAL_FLOW_USAGE_INPUT_BIT_NV = 0x00000001, + VK_OPTICAL_FLOW_USAGE_OUTPUT_BIT_NV = 0x00000002, + VK_OPTICAL_FLOW_USAGE_HINT_BIT_NV = 0x00000004, + VK_OPTICAL_FLOW_USAGE_COST_BIT_NV = 0x00000008, + VK_OPTICAL_FLOW_USAGE_GLOBAL_FLOW_BIT_NV = 0x00000010, + VK_OPTICAL_FLOW_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowUsageFlagBitsNV; +typedef VkFlags VkOpticalFlowUsageFlagsNV; + +typedef enum VkOpticalFlowSessionCreateFlagBitsNV { + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_HINT_BIT_NV = 0x00000001, + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_COST_BIT_NV = 0x00000002, + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_GLOBAL_FLOW_BIT_NV = 0x00000004, + VK_OPTICAL_FLOW_SESSION_CREATE_ALLOW_REGIONS_BIT_NV = 0x00000008, + VK_OPTICAL_FLOW_SESSION_CREATE_BOTH_DIRECTIONS_BIT_NV = 0x00000010, + VK_OPTICAL_FLOW_SESSION_CREATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowSessionCreateFlagBitsNV; +typedef VkFlags VkOpticalFlowSessionCreateFlagsNV; + +typedef enum VkOpticalFlowExecuteFlagBitsNV { + VK_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_NV = 0x00000001, + VK_OPTICAL_FLOW_EXECUTE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowExecuteFlagBitsNV; +typedef VkFlags VkOpticalFlowExecuteFlagsNV; +typedef struct VkPhysicalDeviceOpticalFlowFeaturesNV { VkStructureType sType; void* pNext; - VkBool32 robustImageAccess; -} VkPhysicalDeviceImageRobustnessFeaturesEXT; + VkBool32 opticalFlow; +} VkPhysicalDeviceOpticalFlowFeaturesNV; +typedef struct VkPhysicalDeviceOpticalFlowPropertiesNV { + VkStructureType sType; + void* pNext; + VkOpticalFlowGridSizeFlagsNV supportedOutputGridSizes; + VkOpticalFlowGridSizeFlagsNV supportedHintGridSizes; + VkBool32 hintSupported; + VkBool32 costSupported; + VkBool32 bidirectionalFlowSupported; + VkBool32 globalFlowSupported; + uint32_t minWidth; + uint32_t minHeight; + uint32_t maxWidth; + uint32_t maxHeight; + uint32_t maxNumRegionsOfInterest; +} VkPhysicalDeviceOpticalFlowPropertiesNV; + +typedef struct VkOpticalFlowImageFormatInfoNV { + VkStructureType sType; + const void* pNext; + VkOpticalFlowUsageFlagsNV usage; +} VkOpticalFlowImageFormatInfoNV; +typedef struct VkOpticalFlowImageFormatPropertiesNV { + VkStructureType sType; + const void* pNext; + VkFormat format; +} VkOpticalFlowImageFormatPropertiesNV; -#define VK_EXT_4444_formats 1 -#define VK_EXT_4444_FORMATS_SPEC_VERSION 1 -#define VK_EXT_4444_FORMATS_EXTENSION_NAME "VK_EXT_4444_formats" -typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { +typedef struct VkOpticalFlowSessionCreateInfoNV { + VkStructureType sType; + void* pNext; + uint32_t width; + uint32_t height; + VkFormat imageFormat; + VkFormat flowVectorFormat; + VkFormat costFormat; + VkOpticalFlowGridSizeFlagsNV outputGridSize; + VkOpticalFlowGridSizeFlagsNV hintGridSize; + VkOpticalFlowPerformanceLevelNV performanceLevel; + VkOpticalFlowSessionCreateFlagsNV flags; +} VkOpticalFlowSessionCreateInfoNV; + +typedef struct VkOpticalFlowSessionCreatePrivateDataInfoNV { VkStructureType sType; void* pNext; - VkBool32 formatA4R4G4B4; - VkBool32 formatA4B4G4R4; -} VkPhysicalDevice4444FormatsFeaturesEXT; - + uint32_t id; + uint32_t size; + const void* pPrivateData; +} VkOpticalFlowSessionCreatePrivateDataInfoNV; +typedef struct VkOpticalFlowExecuteInfoNV { + VkStructureType sType; + void* pNext; + VkOpticalFlowExecuteFlagsNV flags; + uint32_t regionCount; + const VkRect2D* pRegions; +} VkOpticalFlowExecuteInfoNV; -#define VK_NV_acquire_winrt_display 1 -#define VK_NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION 1 -#define VK_NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME "VK_NV_acquire_winrt_display" -typedef VkResult (VKAPI_PTR *PFN_vkAcquireWinrtDisplayNV)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); -typedef VkResult (VKAPI_PTR *PFN_vkGetWinrtDisplayNV)(VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV)(VkPhysicalDevice physicalDevice, const VkOpticalFlowImageFormatInfoNV* pOpticalFlowImageFormatInfo, uint32_t* pFormatCount, VkOpticalFlowImageFormatPropertiesNV* pImageFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateOpticalFlowSessionNV)(VkDevice device, const VkOpticalFlowSessionCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkOpticalFlowSessionNV* pSession); +typedef void (VKAPI_PTR *PFN_vkDestroyOpticalFlowSessionNV)(VkDevice device, VkOpticalFlowSessionNV session, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkBindOpticalFlowSessionImageNV)(VkDevice device, VkOpticalFlowSessionNV session, VkOpticalFlowSessionBindingPointNV bindingPoint, VkImageView view, VkImageLayout layout); +typedef void (VKAPI_PTR *PFN_vkCmdOpticalFlowExecuteNV)(VkCommandBuffer commandBuffer, VkOpticalFlowSessionNV session, const VkOpticalFlowExecuteInfoNV* pExecuteInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWinrtDisplayNV( +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceOpticalFlowImageFormatsNV( VkPhysicalDevice physicalDevice, - VkDisplayKHR display); + const VkOpticalFlowImageFormatInfoNV* pOpticalFlowImageFormatInfo, + uint32_t* pFormatCount, + VkOpticalFlowImageFormatPropertiesNV* pImageFormatProperties); -VKAPI_ATTR VkResult VKAPI_CALL vkGetWinrtDisplayNV( - VkPhysicalDevice physicalDevice, - uint32_t deviceRelativeId, - VkDisplayKHR* pDisplay); +VKAPI_ATTR VkResult VKAPI_CALL vkCreateOpticalFlowSessionNV( + VkDevice device, + const VkOpticalFlowSessionCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkOpticalFlowSessionNV* pSession); + +VKAPI_ATTR void VKAPI_CALL vkDestroyOpticalFlowSessionNV( + VkDevice device, + VkOpticalFlowSessionNV session, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindOpticalFlowSessionImageNV( + VkDevice device, + VkOpticalFlowSessionNV session, + VkOpticalFlowSessionBindingPointNV bindingPoint, + VkImageView view, + VkImageLayout layout); + +VKAPI_ATTR void VKAPI_CALL vkCmdOpticalFlowExecuteNV( + VkCommandBuffer commandBuffer, + VkOpticalFlowSessionNV session, + const VkOpticalFlowExecuteInfoNV* pExecuteInfo); #endif -#define VK_VALVE_mutable_descriptor_type 1 -#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 -#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_VALVE_mutable_descriptor_type" -typedef struct VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE { +// VK_EXT_legacy_dithering is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_legacy_dithering 1 +#define VK_EXT_LEGACY_DITHERING_SPEC_VERSION 1 +#define VK_EXT_LEGACY_DITHERING_EXTENSION_NAME "VK_EXT_legacy_dithering" +typedef struct VkPhysicalDeviceLegacyDitheringFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 mutableDescriptorType; -} VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE; - -typedef struct VkMutableDescriptorTypeListVALVE { - uint32_t descriptorTypeCount; - const VkDescriptorType* pDescriptorTypes; -} VkMutableDescriptorTypeListVALVE; - -typedef struct VkMutableDescriptorTypeCreateInfoVALVE { - VkStructureType sType; - const void* pNext; - uint32_t mutableDescriptorTypeListCount; - const VkMutableDescriptorTypeListVALVE* pMutableDescriptorTypeLists; -} VkMutableDescriptorTypeCreateInfoVALVE; + VkBool32 legacyDithering; +} VkPhysicalDeviceLegacyDitheringFeaturesEXT; -#define VK_EXT_vertex_input_dynamic_state 1 -#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION 2 -#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_vertex_input_dynamic_state" -typedef struct VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT { +// VK_EXT_pipeline_protected_access is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_protected_access 1 +#define VK_EXT_PIPELINE_PROTECTED_ACCESS_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_PROTECTED_ACCESS_EXTENSION_NAME "VK_EXT_pipeline_protected_access" +typedef struct VkPhysicalDevicePipelineProtectedAccessFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 vertexInputDynamicState; -} VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT; - -typedef struct VkVertexInputBindingDescription2EXT { - VkStructureType sType; - void* pNext; - uint32_t binding; - uint32_t stride; - VkVertexInputRate inputRate; - uint32_t divisor; -} VkVertexInputBindingDescription2EXT; + VkBool32 pipelineProtectedAccess; +} VkPhysicalDevicePipelineProtectedAccessFeaturesEXT; + + + +// VK_EXT_shader_object is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_object 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderEXT) +#define VK_EXT_SHADER_OBJECT_SPEC_VERSION 1 +#define VK_EXT_SHADER_OBJECT_EXTENSION_NAME "VK_EXT_shader_object" + +typedef enum VkShaderCodeTypeEXT { + VK_SHADER_CODE_TYPE_BINARY_EXT = 0, + VK_SHADER_CODE_TYPE_SPIRV_EXT = 1, + VK_SHADER_CODE_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkShaderCodeTypeEXT; + +typedef enum VkShaderCreateFlagBitsEXT { + VK_SHADER_CREATE_LINK_STAGE_BIT_EXT = 0x00000001, + VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000002, + VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000004, + VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT = 0x00000008, + VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT = 0x00000010, + VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT = 0x00000020, + VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00000040, + VK_SHADER_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkShaderCreateFlagBitsEXT; +typedef VkFlags VkShaderCreateFlagsEXT; +typedef struct VkPhysicalDeviceShaderObjectFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderObject; +} VkPhysicalDeviceShaderObjectFeaturesEXT; -typedef struct VkVertexInputAttributeDescription2EXT { +typedef struct VkPhysicalDeviceShaderObjectPropertiesEXT { VkStructureType sType; void* pNext; - uint32_t location; - uint32_t binding; - VkFormat format; - uint32_t offset; -} VkVertexInputAttributeDescription2EXT; + uint8_t shaderBinaryUUID[VK_UUID_SIZE]; + uint32_t shaderBinaryVersion; +} VkPhysicalDeviceShaderObjectPropertiesEXT; -typedef void (VKAPI_PTR *PFN_vkCmdSetVertexInputEXT)(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); +typedef struct VkShaderCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkShaderCreateFlagsEXT flags; + VkShaderStageFlagBits stage; + VkShaderStageFlags nextStage; + VkShaderCodeTypeEXT codeType; + size_t codeSize; + const void* pCode; + const char* pName; + uint32_t setLayoutCount; + const VkDescriptorSetLayout* pSetLayouts; + uint32_t pushConstantRangeCount; + const VkPushConstantRange* pPushConstantRanges; + const VkSpecializationInfo* pSpecializationInfo; +} VkShaderCreateInfoEXT; + +typedef VkPipelineShaderStageRequiredSubgroupSizeCreateInfo VkShaderRequiredSubgroupSizeCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateShadersEXT)(VkDevice device, uint32_t createInfoCount, const VkShaderCreateInfoEXT* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkShaderEXT* pShaders); +typedef void (VKAPI_PTR *PFN_vkDestroyShaderEXT)(VkDevice device, VkShaderEXT shader, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderBinaryDataEXT)(VkDevice device, VkShaderEXT shader, size_t* pDataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdBindShadersEXT)(VkCommandBuffer commandBuffer, uint32_t stageCount, const VkShaderStageFlagBits* pStages, const VkShaderEXT* pShaders); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( +VKAPI_ATTR VkResult VKAPI_CALL vkCreateShadersEXT( + VkDevice device, + uint32_t createInfoCount, + const VkShaderCreateInfoEXT* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkShaderEXT* pShaders); + +VKAPI_ATTR void VKAPI_CALL vkDestroyShaderEXT( + VkDevice device, + VkShaderEXT shader, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderBinaryDataEXT( + VkDevice device, + VkShaderEXT shader, + size_t* pDataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindShadersEXT( VkCommandBuffer commandBuffer, - uint32_t vertexBindingDescriptionCount, - const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, - uint32_t vertexAttributeDescriptionCount, - const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); + uint32_t stageCount, + const VkShaderStageFlagBits* pStages, + const VkShaderEXT* pShaders); #endif -#define VK_EXT_physical_device_drm 1 -#define VK_EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION 1 -#define VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME "VK_EXT_physical_device_drm" -typedef struct VkPhysicalDeviceDrmPropertiesEXT { +// VK_QCOM_tile_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_tile_properties 1 +#define VK_QCOM_TILE_PROPERTIES_SPEC_VERSION 1 +#define VK_QCOM_TILE_PROPERTIES_EXTENSION_NAME "VK_QCOM_tile_properties" +typedef struct VkPhysicalDeviceTilePropertiesFeaturesQCOM { VkStructureType sType; void* pNext; - VkBool32 hasPrimary; - VkBool32 hasRender; - int64_t primaryMajor; - int64_t primaryMinor; - int64_t renderMajor; - int64_t renderMinor; -} VkPhysicalDeviceDrmPropertiesEXT; + VkBool32 tileProperties; +} VkPhysicalDeviceTilePropertiesFeaturesQCOM; +typedef struct VkTilePropertiesQCOM { + VkStructureType sType; + void* pNext; + VkExtent3D tileSize; + VkExtent2D apronSize; + VkOffset2D origin; +} VkTilePropertiesQCOM; +typedef VkResult (VKAPI_PTR *PFN_vkGetFramebufferTilePropertiesQCOM)(VkDevice device, VkFramebuffer framebuffer, uint32_t* pPropertiesCount, VkTilePropertiesQCOM* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDynamicRenderingTilePropertiesQCOM)(VkDevice device, const VkRenderingInfo* pRenderingInfo, VkTilePropertiesQCOM* pProperties); -#define VK_HUAWEI_subpass_shading 1 -#define VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION 2 -#define VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME "VK_HUAWEI_subpass_shading" -typedef struct VkSubpassShadingPipelineCreateInfoHUAWEI { +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetFramebufferTilePropertiesQCOM( + VkDevice device, + VkFramebuffer framebuffer, + uint32_t* pPropertiesCount, + VkTilePropertiesQCOM* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDynamicRenderingTilePropertiesQCOM( + VkDevice device, + const VkRenderingInfo* pRenderingInfo, + VkTilePropertiesQCOM* pProperties); +#endif + + +// VK_SEC_amigo_profiling is a preprocessor guard. Do not pass it to API calls. +#define VK_SEC_amigo_profiling 1 +#define VK_SEC_AMIGO_PROFILING_SPEC_VERSION 1 +#define VK_SEC_AMIGO_PROFILING_EXTENSION_NAME "VK_SEC_amigo_profiling" +typedef struct VkPhysicalDeviceAmigoProfilingFeaturesSEC { VkStructureType sType; void* pNext; - VkRenderPass renderPass; - uint32_t subpass; -} VkSubpassShadingPipelineCreateInfoHUAWEI; + VkBool32 amigoProfiling; +} VkPhysicalDeviceAmigoProfilingFeaturesSEC; -typedef struct VkPhysicalDeviceSubpassShadingFeaturesHUAWEI { +typedef struct VkAmigoProfilingSubmitInfoSEC { + VkStructureType sType; + const void* pNext; + uint64_t firstDrawTimestamp; + uint64_t swapBufferTimestamp; +} VkAmigoProfilingSubmitInfoSEC; + + + +// VK_QCOM_multiview_per_view_viewports is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_multiview_per_view_viewports 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_VIEWPORTS_SPEC_VERSION 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_VIEWPORTS_EXTENSION_NAME "VK_QCOM_multiview_per_view_viewports" +typedef struct VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM { VkStructureType sType; void* pNext; - VkBool32 subpassShading; -} VkPhysicalDeviceSubpassShadingFeaturesHUAWEI; + VkBool32 multiviewPerViewViewports; +} VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM; -typedef struct VkPhysicalDeviceSubpassShadingPropertiesHUAWEI { + + +// VK_NV_ray_tracing_invocation_reorder is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_ray_tracing_invocation_reorder 1 +#define VK_NV_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME "VK_NV_ray_tracing_invocation_reorder" + +typedef enum VkRayTracingInvocationReorderModeNV { + VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_NV = 0, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV = 1, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkRayTracingInvocationReorderModeNV; +typedef struct VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV { + VkStructureType sType; + void* pNext; + VkRayTracingInvocationReorderModeNV rayTracingInvocationReorderReorderingHint; +} VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV; + +typedef struct VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV { VkStructureType sType; void* pNext; - uint32_t maxSubpassShadingWorkgroupSizeAspectRatio; -} VkPhysicalDeviceSubpassShadingPropertiesHUAWEI; + VkBool32 rayTracingInvocationReorder; +} VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV; -typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)(VkDevice device, VkRenderPass renderpass, VkExtent2D* pMaxWorkgroupSize); -typedef void (VKAPI_PTR *PFN_vkCmdSubpassShadingHUAWEI)(VkCommandBuffer commandBuffer); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI( - VkDevice device, - VkRenderPass renderpass, - VkExtent2D* pMaxWorkgroupSize); -VKAPI_ATTR void VKAPI_CALL vkCmdSubpassShadingHUAWEI( - VkCommandBuffer commandBuffer); -#endif +// VK_NV_extended_sparse_address_space is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_extended_sparse_address_space 1 +#define VK_NV_EXTENDED_SPARSE_ADDRESS_SPACE_SPEC_VERSION 1 +#define VK_NV_EXTENDED_SPARSE_ADDRESS_SPACE_EXTENSION_NAME "VK_NV_extended_sparse_address_space" +typedef struct VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 extendedSparseAddressSpace; +} VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + +typedef struct VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV { + VkStructureType sType; + void* pNext; + VkDeviceSize extendedSparseAddressSpaceSize; + VkImageUsageFlags extendedSparseImageUsageFlags; + VkBufferUsageFlags extendedSparseBufferUsageFlags; +} VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + -#define VK_HUAWEI_invocation_mask 1 -#define VK_HUAWEI_INVOCATION_MASK_SPEC_VERSION 1 -#define VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME "VK_HUAWEI_invocation_mask" -typedef struct VkPhysicalDeviceInvocationMaskFeaturesHUAWEI { +// VK_EXT_mutable_descriptor_type is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_mutable_descriptor_type 1 +#define VK_EXT_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 +#define VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_EXT_mutable_descriptor_type" + + +// VK_ARM_shader_core_builtins is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_shader_core_builtins 1 +#define VK_ARM_SHADER_CORE_BUILTINS_SPEC_VERSION 2 +#define VK_ARM_SHADER_CORE_BUILTINS_EXTENSION_NAME "VK_ARM_shader_core_builtins" +typedef struct VkPhysicalDeviceShaderCoreBuiltinsFeaturesARM { VkStructureType sType; void* pNext; - VkBool32 invocationMask; -} VkPhysicalDeviceInvocationMaskFeaturesHUAWEI; + VkBool32 shaderCoreBuiltins; +} VkPhysicalDeviceShaderCoreBuiltinsFeaturesARM; -typedef void (VKAPI_PTR *PFN_vkCmdBindInvocationMaskHUAWEI)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); +typedef struct VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM { + VkStructureType sType; + void* pNext; + uint64_t shaderCoreMask; + uint32_t shaderCoreCount; + uint32_t shaderWarpsPerCore; +} VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdBindInvocationMaskHUAWEI( - VkCommandBuffer commandBuffer, - VkImageView imageView, - VkImageLayout imageLayout); -#endif -#define VK_NV_external_memory_rdma 1 -typedef void* VkRemoteAddressNV; -#define VK_NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION 1 -#define VK_NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME "VK_NV_external_memory_rdma" -typedef struct VkMemoryGetRemoteAddressInfoNV { - VkStructureType sType; - const void* pNext; - VkDeviceMemory memory; - VkExternalMemoryHandleTypeFlagBits handleType; -} VkMemoryGetRemoteAddressInfoNV; +// VK_EXT_pipeline_library_group_handles is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_library_group_handles 1 +#define VK_EXT_PIPELINE_LIBRARY_GROUP_HANDLES_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_LIBRARY_GROUP_HANDLES_EXTENSION_NAME "VK_EXT_pipeline_library_group_handles" +typedef struct VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelineLibraryGroupHandles; +} VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT; -typedef struct VkPhysicalDeviceExternalMemoryRDMAFeaturesNV { + + +// VK_EXT_dynamic_rendering_unused_attachments is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_dynamic_rendering_unused_attachments 1 +#define VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_SPEC_VERSION 1 +#define VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME "VK_EXT_dynamic_rendering_unused_attachments" +typedef struct VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { VkStructureType sType; void* pNext; - VkBool32 externalMemoryRDMA; -} VkPhysicalDeviceExternalMemoryRDMAFeaturesNV; + VkBool32 dynamicRenderingUnusedAttachments; +} VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT; + + + +// VK_NV_low_latency2 is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_low_latency2 1 +#define VK_NV_LOW_LATENCY_2_SPEC_VERSION 1 +#define VK_NV_LOW_LATENCY_2_EXTENSION_NAME "VK_NV_low_latency2" + +typedef enum VkLatencyMarkerNV { + VK_LATENCY_MARKER_SIMULATION_START_NV = 0, + VK_LATENCY_MARKER_SIMULATION_END_NV = 1, + VK_LATENCY_MARKER_RENDERSUBMIT_START_NV = 2, + VK_LATENCY_MARKER_RENDERSUBMIT_END_NV = 3, + VK_LATENCY_MARKER_PRESENT_START_NV = 4, + VK_LATENCY_MARKER_PRESENT_END_NV = 5, + VK_LATENCY_MARKER_INPUT_SAMPLE_NV = 6, + VK_LATENCY_MARKER_TRIGGER_FLASH_NV = 7, + VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_START_NV = 8, + VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_END_NV = 9, + VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_START_NV = 10, + VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_END_NV = 11, + VK_LATENCY_MARKER_MAX_ENUM_NV = 0x7FFFFFFF +} VkLatencyMarkerNV; + +typedef enum VkOutOfBandQueueTypeNV { + VK_OUT_OF_BAND_QUEUE_TYPE_RENDER_NV = 0, + VK_OUT_OF_BAND_QUEUE_TYPE_PRESENT_NV = 1, + VK_OUT_OF_BAND_QUEUE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkOutOfBandQueueTypeNV; +typedef struct VkLatencySleepModeInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 lowLatencyMode; + VkBool32 lowLatencyBoost; + uint32_t minimumIntervalUs; +} VkLatencySleepModeInfoNV; -typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryRemoteAddressNV)(VkDevice device, const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, VkRemoteAddressNV* pAddress); +typedef struct VkLatencySleepInfoNV { + VkStructureType sType; + const void* pNext; + VkSemaphore signalSemaphore; + uint64_t value; +} VkLatencySleepInfoNV; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryRemoteAddressNV( - VkDevice device, - const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, - VkRemoteAddressNV* pAddress); -#endif +typedef struct VkSetLatencyMarkerInfoNV { + VkStructureType sType; + const void* pNext; + uint64_t presentID; + VkLatencyMarkerNV marker; +} VkSetLatencyMarkerInfoNV; +typedef struct VkLatencyTimingsFrameReportNV { + VkStructureType sType; + const void* pNext; + uint64_t presentID; + uint64_t inputSampleTimeUs; + uint64_t simStartTimeUs; + uint64_t simEndTimeUs; + uint64_t renderSubmitStartTimeUs; + uint64_t renderSubmitEndTimeUs; + uint64_t presentStartTimeUs; + uint64_t presentEndTimeUs; + uint64_t driverStartTimeUs; + uint64_t driverEndTimeUs; + uint64_t osRenderQueueStartTimeUs; + uint64_t osRenderQueueEndTimeUs; + uint64_t gpuRenderStartTimeUs; + uint64_t gpuRenderEndTimeUs; +} VkLatencyTimingsFrameReportNV; + +typedef struct VkGetLatencyMarkerInfoNV { + VkStructureType sType; + const void* pNext; + VkLatencyTimingsFrameReportNV* pTimings; +} VkGetLatencyMarkerInfoNV; -#define VK_EXT_extended_dynamic_state2 1 -#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION 1 -#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME "VK_EXT_extended_dynamic_state2" -typedef struct VkPhysicalDeviceExtendedDynamicState2FeaturesEXT { +typedef struct VkLatencySubmissionPresentIdNV { VkStructureType sType; - void* pNext; - VkBool32 extendedDynamicState2; - VkBool32 extendedDynamicState2LogicOp; - VkBool32 extendedDynamicState2PatchControlPoints; -} VkPhysicalDeviceExtendedDynamicState2FeaturesEXT; + const void* pNext; + uint64_t presentID; +} VkLatencySubmissionPresentIdNV; -typedef void (VKAPI_PTR *PFN_vkCmdSetPatchControlPointsEXT)(VkCommandBuffer commandBuffer, uint32_t patchControlPoints); -typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); -typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); -typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEXT)(VkCommandBuffer commandBuffer, VkLogicOp logicOp); -typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); +typedef struct VkSwapchainLatencyCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 latencyModeEnable; +} VkSwapchainLatencyCreateInfoNV; + +typedef struct VkOutOfBandQueueTypeInfoNV { + VkStructureType sType; + const void* pNext; + VkOutOfBandQueueTypeNV queueType; +} VkOutOfBandQueueTypeInfoNV; + +typedef struct VkLatencySurfaceCapabilitiesNV { + VkStructureType sType; + const void* pNext; + uint32_t presentModeCount; + VkPresentModeKHR* pPresentModes; +} VkLatencySurfaceCapabilitiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkSetLatencySleepModeNV)(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepModeInfoNV* pSleepModeInfo); +typedef VkResult (VKAPI_PTR *PFN_vkLatencySleepNV)(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepInfoNV* pSleepInfo); +typedef void (VKAPI_PTR *PFN_vkSetLatencyMarkerNV)(VkDevice device, VkSwapchainKHR swapchain, const VkSetLatencyMarkerInfoNV* pLatencyMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkGetLatencyTimingsNV)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pTimingCount, VkGetLatencyMarkerInfoNV* pLatencyMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkQueueNotifyOutOfBandNV)(VkQueue queue, const VkOutOfBandQueueTypeInfoNV* pQueueTypeInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetPatchControlPointsEXT( - VkCommandBuffer commandBuffer, - uint32_t patchControlPoints); +VKAPI_ATTR VkResult VKAPI_CALL vkSetLatencySleepModeNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkLatencySleepModeInfoNV* pSleepModeInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnableEXT( - VkCommandBuffer commandBuffer, - VkBool32 rasterizerDiscardEnable); +VKAPI_ATTR VkResult VKAPI_CALL vkLatencySleepNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkLatencySleepInfoNV* pSleepInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnableEXT( - VkCommandBuffer commandBuffer, - VkBool32 depthBiasEnable); +VKAPI_ATTR void VKAPI_CALL vkSetLatencyMarkerNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkSetLatencyMarkerInfoNV* pLatencyMarkerInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEXT( - VkCommandBuffer commandBuffer, - VkLogicOp logicOp); +VKAPI_ATTR void VKAPI_CALL vkGetLatencyTimingsNV( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pTimingCount, + VkGetLatencyMarkerInfoNV* pLatencyMarkerInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnableEXT( - VkCommandBuffer commandBuffer, - VkBool32 primitiveRestartEnable); +VKAPI_ATTR void VKAPI_CALL vkQueueNotifyOutOfBandNV( + VkQueue queue, + const VkOutOfBandQueueTypeInfoNV* pQueueTypeInfo); #endif -#define VK_EXT_color_write_enable 1 -#define VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION 1 -#define VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME "VK_EXT_color_write_enable" -typedef struct VkPhysicalDeviceColorWriteEnableFeaturesEXT { +// VK_QCOM_multiview_per_view_render_areas is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_multiview_per_view_render_areas 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_SPEC_VERSION 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_EXTENSION_NAME "VK_QCOM_multiview_per_view_render_areas" +typedef struct VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { VkStructureType sType; void* pNext; - VkBool32 colorWriteEnable; -} VkPhysicalDeviceColorWriteEnableFeaturesEXT; + VkBool32 multiviewPerViewRenderAreas; +} VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM; -typedef struct VkPipelineColorWriteCreateInfoEXT { +typedef struct VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { VkStructureType sType; const void* pNext; - uint32_t attachmentCount; - const VkBool32* pColorWriteEnables; -} VkPipelineColorWriteCreateInfoEXT; + uint32_t perViewRenderAreaCount; + const VkRect2D* pPerViewRenderAreas; +} VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM; -typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteEnableEXT)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteEnableEXT( - VkCommandBuffer commandBuffer, - uint32_t attachmentCount, - const VkBool32* pColorWriteEnables); -#endif +// VK_QCOM_image_processing2 is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_image_processing2 1 +#define VK_QCOM_IMAGE_PROCESSING_2_SPEC_VERSION 1 +#define VK_QCOM_IMAGE_PROCESSING_2_EXTENSION_NAME "VK_QCOM_image_processing2" -#define VK_EXT_global_priority_query 1 -#define VK_MAX_GLOBAL_PRIORITY_SIZE_EXT 16U -#define VK_EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION 1 -#define VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME "VK_EXT_global_priority_query" -typedef struct VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT { +typedef enum VkBlockMatchWindowCompareModeQCOM { + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MIN_QCOM = 0, + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_QCOM = 1, + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkBlockMatchWindowCompareModeQCOM; +typedef struct VkPhysicalDeviceImageProcessing2FeaturesQCOM { VkStructureType sType; void* pNext; - VkBool32 globalPriorityQuery; -} VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT; + VkBool32 textureBlockMatch2; +} VkPhysicalDeviceImageProcessing2FeaturesQCOM; + +typedef struct VkPhysicalDeviceImageProcessing2PropertiesQCOM { + VkStructureType sType; + void* pNext; + VkExtent2D maxBlockMatchWindow; +} VkPhysicalDeviceImageProcessing2PropertiesQCOM; -typedef struct VkQueueFamilyGlobalPriorityPropertiesEXT { +typedef struct VkSamplerBlockMatchWindowCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkExtent2D windowExtent; + VkBlockMatchWindowCompareModeQCOM windowCompareMode; +} VkSamplerBlockMatchWindowCreateInfoQCOM; + + + +// VK_QCOM_filter_cubic_weights is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_filter_cubic_weights 1 +#define VK_QCOM_FILTER_CUBIC_WEIGHTS_SPEC_VERSION 1 +#define VK_QCOM_FILTER_CUBIC_WEIGHTS_EXTENSION_NAME "VK_QCOM_filter_cubic_weights" + +typedef enum VkCubicFilterWeightsQCOM { + VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM = 0, + VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM = 1, + VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM = 2, + VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM = 3, + VK_CUBIC_FILTER_WEIGHTS_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkCubicFilterWeightsQCOM; +typedef struct VkPhysicalDeviceCubicWeightsFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 selectableCubicWeights; +} VkPhysicalDeviceCubicWeightsFeaturesQCOM; + +typedef struct VkSamplerCubicWeightsCreateInfoQCOM { VkStructureType sType; - void* pNext; - uint32_t priorityCount; - VkQueueGlobalPriorityEXT priorities[VK_MAX_GLOBAL_PRIORITY_SIZE_EXT]; -} VkQueueFamilyGlobalPriorityPropertiesEXT; + const void* pNext; + VkCubicFilterWeightsQCOM cubicWeights; +} VkSamplerCubicWeightsCreateInfoQCOM; +typedef struct VkBlitImageCubicWeightsInfoQCOM { + VkStructureType sType; + const void* pNext; + VkCubicFilterWeightsQCOM cubicWeights; +} VkBlitImageCubicWeightsInfoQCOM; -#define VK_EXT_multi_draw 1 -#define VK_EXT_MULTI_DRAW_SPEC_VERSION 1 -#define VK_EXT_MULTI_DRAW_EXTENSION_NAME "VK_EXT_multi_draw" -typedef struct VkPhysicalDeviceMultiDrawFeaturesEXT { + +// VK_QCOM_ycbcr_degamma is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_ycbcr_degamma 1 +#define VK_QCOM_YCBCR_DEGAMMA_SPEC_VERSION 1 +#define VK_QCOM_YCBCR_DEGAMMA_EXTENSION_NAME "VK_QCOM_ycbcr_degamma" +typedef struct VkPhysicalDeviceYcbcrDegammaFeaturesQCOM { VkStructureType sType; void* pNext; - VkBool32 multiDraw; -} VkPhysicalDeviceMultiDrawFeaturesEXT; + VkBool32 ycbcrDegamma; +} VkPhysicalDeviceYcbcrDegammaFeaturesQCOM; -typedef struct VkPhysicalDeviceMultiDrawPropertiesEXT { +typedef struct VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM { VkStructureType sType; void* pNext; - uint32_t maxMultiDrawCount; -} VkPhysicalDeviceMultiDrawPropertiesEXT; + VkBool32 enableYDegamma; + VkBool32 enableCbCrDegamma; +} VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; -typedef struct VkMultiDrawInfoEXT { - uint32_t firstVertex; - uint32_t vertexCount; -} VkMultiDrawInfoEXT; -typedef struct VkMultiDrawIndexedInfoEXT { - uint32_t firstIndex; - uint32_t indexCount; - int32_t vertexOffset; -} VkMultiDrawIndexedInfoEXT; -typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT* pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiIndexedEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset); +// VK_QCOM_filter_cubic_clamp is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_filter_cubic_clamp 1 +#define VK_QCOM_FILTER_CUBIC_CLAMP_SPEC_VERSION 1 +#define VK_QCOM_FILTER_CUBIC_CLAMP_EXTENSION_NAME "VK_QCOM_filter_cubic_clamp" +typedef struct VkPhysicalDeviceCubicClampFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 cubicRangeClamp; +} VkPhysicalDeviceCubicClampFeaturesQCOM; -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiEXT( - VkCommandBuffer commandBuffer, - uint32_t drawCount, - const VkMultiDrawInfoEXT* pVertexInfo, - uint32_t instanceCount, - uint32_t firstInstance, - uint32_t stride); -VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( + +// VK_EXT_attachment_feedback_loop_dynamic_state is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_attachment_feedback_loop_dynamic_state 1 +#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_SPEC_VERSION 1 +#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_attachment_feedback_loop_dynamic_state" +typedef struct VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 attachmentFeedbackLoopDynamicState; +} VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)(VkCommandBuffer commandBuffer, VkImageAspectFlags aspectMask); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetAttachmentFeedbackLoopEnableEXT( VkCommandBuffer commandBuffer, - uint32_t drawCount, - const VkMultiDrawIndexedInfoEXT* pIndexInfo, - uint32_t instanceCount, - uint32_t firstInstance, - uint32_t stride, - const int32_t* pVertexOffset); + VkImageAspectFlags aspectMask); #endif -#define VK_EXT_load_store_op_none 1 -#define VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION 1 -#define VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_EXT_load_store_op_none" +// VK_MSFT_layered_driver is a preprocessor guard. Do not pass it to API calls. +#define VK_MSFT_layered_driver 1 +#define VK_MSFT_LAYERED_DRIVER_SPEC_VERSION 1 +#define VK_MSFT_LAYERED_DRIVER_EXTENSION_NAME "VK_MSFT_layered_driver" + +typedef enum VkLayeredDriverUnderlyingApiMSFT { + VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT = 0, + VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT = 1, + VK_LAYERED_DRIVER_UNDERLYING_API_MAX_ENUM_MSFT = 0x7FFFFFFF +} VkLayeredDriverUnderlyingApiMSFT; +typedef struct VkPhysicalDeviceLayeredDriverPropertiesMSFT { + VkStructureType sType; + void* pNext; + VkLayeredDriverUnderlyingApiMSFT underlyingAPI; +} VkPhysicalDeviceLayeredDriverPropertiesMSFT; + +// VK_NV_descriptor_pool_overallocation is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_descriptor_pool_overallocation 1 +#define VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_SPEC_VERSION 1 +#define VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME "VK_NV_descriptor_pool_overallocation" +typedef struct VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 descriptorPoolOverallocation; +} VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + + + +// VK_KHR_acceleration_structure is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_acceleration_structure 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) -#define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 12 +#define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 #define VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_KHR_acceleration_structure" typedef enum VkBuildAccelerationStructureModeKHR { @@ -12686,30 +18093,13 @@ typedef enum VkBuildAccelerationStructureModeKHR { VK_BUILD_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF } VkBuildAccelerationStructureModeKHR; -typedef enum VkAccelerationStructureBuildTypeKHR { - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkAccelerationStructureBuildTypeKHR; - -typedef enum VkAccelerationStructureCompatibilityKHR { - VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0, - VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1, - VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR = 0x7FFFFFFF -} VkAccelerationStructureCompatibilityKHR; - typedef enum VkAccelerationStructureCreateFlagBitsKHR { VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001, + VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000008, VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0x00000004, VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkAccelerationStructureCreateFlagBitsKHR; typedef VkFlags VkAccelerationStructureCreateFlagsKHR; -typedef union VkDeviceOrHostAddressKHR { - VkDeviceAddress deviceAddress; - void* hostAddress; -} VkDeviceOrHostAddressKHR; - typedef struct VkAccelerationStructureBuildRangeInfoKHR { uint32_t primitiveCount; uint32_t primitiveOffset; @@ -12968,6 +18358,7 @@ VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( #endif +// VK_KHR_ray_tracing_pipeline is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_ray_tracing_pipeline 1 #define VK_KHR_RAY_TRACING_PIPELINE_SPEC_VERSION 1 #define VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME "VK_KHR_ray_tracing_pipeline" @@ -13104,6 +18495,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetRayTracingPipelineStackSizeKHR( #endif +// VK_KHR_ray_query is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_ray_query 1 #define VK_KHR_RAY_QUERY_SPEC_VERSION 1 #define VK_KHR_RAY_QUERY_EXTENSION_NAME "VK_KHR_ray_query" @@ -13114,6 +18506,88 @@ typedef struct VkPhysicalDeviceRayQueryFeaturesKHR { } VkPhysicalDeviceRayQueryFeaturesKHR; + +// VK_EXT_mesh_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_mesh_shader 1 +#define VK_EXT_MESH_SHADER_SPEC_VERSION 1 +#define VK_EXT_MESH_SHADER_EXTENSION_NAME "VK_EXT_mesh_shader" +typedef struct VkPhysicalDeviceMeshShaderFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 taskShader; + VkBool32 meshShader; + VkBool32 multiviewMeshShader; + VkBool32 primitiveFragmentShadingRateMeshShader; + VkBool32 meshShaderQueries; +} VkPhysicalDeviceMeshShaderFeaturesEXT; + +typedef struct VkPhysicalDeviceMeshShaderPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxTaskWorkGroupTotalCount; + uint32_t maxTaskWorkGroupCount[3]; + uint32_t maxTaskWorkGroupInvocations; + uint32_t maxTaskWorkGroupSize[3]; + uint32_t maxTaskPayloadSize; + uint32_t maxTaskSharedMemorySize; + uint32_t maxTaskPayloadAndSharedMemorySize; + uint32_t maxMeshWorkGroupTotalCount; + uint32_t maxMeshWorkGroupCount[3]; + uint32_t maxMeshWorkGroupInvocations; + uint32_t maxMeshWorkGroupSize[3]; + uint32_t maxMeshSharedMemorySize; + uint32_t maxMeshPayloadAndSharedMemorySize; + uint32_t maxMeshOutputMemorySize; + uint32_t maxMeshPayloadAndOutputMemorySize; + uint32_t maxMeshOutputComponents; + uint32_t maxMeshOutputVertices; + uint32_t maxMeshOutputPrimitives; + uint32_t maxMeshOutputLayers; + uint32_t maxMeshMultiviewViewCount; + uint32_t meshOutputPerVertexGranularity; + uint32_t meshOutputPerPrimitiveGranularity; + uint32_t maxPreferredTaskWorkGroupInvocations; + uint32_t maxPreferredMeshWorkGroupInvocations; + VkBool32 prefersLocalInvocationVertexOutput; + VkBool32 prefersLocalInvocationPrimitiveOutput; + VkBool32 prefersCompactVertexOutput; + VkBool32 prefersCompactPrimitiveOutput; +} VkPhysicalDeviceMeshShaderPropertiesEXT; + +typedef struct VkDrawMeshTasksIndirectCommandEXT { + uint32_t groupCountX; + uint32_t groupCountY; + uint32_t groupCountZ; +} VkDrawMeshTasksIndirectCommandEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksEXT)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectEXT)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountEXT)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksEXT( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectEXT( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountEXT( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + #ifdef __cplusplus } #endif diff --git a/libraries/ZVulkan/include/vulkan/vulkan_directfb.h b/libraries/ZVulkan/include/vulkan/vulkan_directfb.h index 8eaac6e48d..1f11a08273 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_directfb.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_directfb.h @@ -2,7 +2,7 @@ #define VULKAN_DIRECTFB_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_EXT_directfb_surface is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_directfb_surface 1 #define VK_EXT_DIRECTFB_SURFACE_SPEC_VERSION 1 #define VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME "VK_EXT_directfb_surface" diff --git a/libraries/ZVulkan/include/vulkan/vulkan_fuchsia.h b/libraries/ZVulkan/include/vulkan/vulkan_fuchsia.h index d558715738..76e1564832 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_fuchsia.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_fuchsia.h @@ -2,7 +2,7 @@ #define VULKAN_FUCHSIA_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_FUCHSIA_imagepipe_surface is a preprocessor guard. Do not pass it to API calls. #define VK_FUCHSIA_imagepipe_surface 1 #define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1 #define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface" @@ -41,6 +42,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA( #endif +// VK_FUCHSIA_external_memory is a preprocessor guard. Do not pass it to API calls. #define VK_FUCHSIA_external_memory 1 #define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1 #define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory" @@ -81,6 +83,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandlePropertiesFUCHSIA( #endif +// VK_FUCHSIA_external_semaphore is a preprocessor guard. Do not pass it to API calls. #define VK_FUCHSIA_external_semaphore 1 #define VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 #define VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_FUCHSIA_external_semaphore" @@ -114,6 +117,144 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreZirconHandleFUCHSIA( zx_handle_t* pZirconHandle); #endif + +// VK_FUCHSIA_buffer_collection is a preprocessor guard. Do not pass it to API calls. +#define VK_FUCHSIA_buffer_collection 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA) +#define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 2 +#define VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME "VK_FUCHSIA_buffer_collection" +typedef VkFlags VkImageFormatConstraintsFlagsFUCHSIA; + +typedef enum VkImageConstraintsInfoFlagBitsFUCHSIA { + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA = 0x00000001, + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA = 0x00000002, + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA = 0x00000004, + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA = 0x00000008, + VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA = 0x00000010, + VK_IMAGE_CONSTRAINTS_INFO_FLAG_BITS_MAX_ENUM_FUCHSIA = 0x7FFFFFFF +} VkImageConstraintsInfoFlagBitsFUCHSIA; +typedef VkFlags VkImageConstraintsInfoFlagsFUCHSIA; +typedef struct VkBufferCollectionCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + zx_handle_t collectionToken; +} VkBufferCollectionCreateInfoFUCHSIA; + +typedef struct VkImportMemoryBufferCollectionFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkImportMemoryBufferCollectionFUCHSIA; + +typedef struct VkBufferCollectionImageCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionImageCreateInfoFUCHSIA; + +typedef struct VkBufferCollectionConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t minBufferCount; + uint32_t maxBufferCount; + uint32_t minBufferCountForCamping; + uint32_t minBufferCountForDedicatedSlack; + uint32_t minBufferCountForSharedSlack; +} VkBufferCollectionConstraintsInfoFUCHSIA; + +typedef struct VkBufferConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCreateInfo createInfo; + VkFormatFeatureFlags requiredFormatFeatures; + VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints; +} VkBufferConstraintsInfoFUCHSIA; + +typedef struct VkBufferCollectionBufferCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionBufferCreateInfoFUCHSIA; + +typedef struct VkSysmemColorSpaceFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t colorSpace; +} VkSysmemColorSpaceFUCHSIA; + +typedef struct VkBufferCollectionPropertiesFUCHSIA { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; + uint32_t bufferCount; + uint32_t createInfoIndex; + uint64_t sysmemPixelFormat; + VkFormatFeatureFlags formatFeatures; + VkSysmemColorSpaceFUCHSIA sysmemColorSpaceIndex; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkBufferCollectionPropertiesFUCHSIA; + +typedef struct VkImageFormatConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkImageCreateInfo imageCreateInfo; + VkFormatFeatureFlags requiredFormatFeatures; + VkImageFormatConstraintsFlagsFUCHSIA flags; + uint64_t sysmemPixelFormat; + uint32_t colorSpaceCount; + const VkSysmemColorSpaceFUCHSIA* pColorSpaces; +} VkImageFormatConstraintsInfoFUCHSIA; + +typedef struct VkImageConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t formatConstraintsCount; + const VkImageFormatConstraintsInfoFUCHSIA* pFormatConstraints; + VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints; + VkImageConstraintsInfoFlagsFUCHSIA flags; +} VkImageConstraintsInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferCollectionFUCHSIA)(VkDevice device, const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferCollectionFUCHSIA* pCollection); +typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo); +typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo); +typedef void (VKAPI_PTR *PFN_vkDestroyBufferCollectionFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetBufferCollectionPropertiesFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, VkBufferCollectionPropertiesFUCHSIA* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferCollectionFUCHSIA( + VkDevice device, + const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferCollectionFUCHSIA* pCollection); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionImageConstraintsFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionBufferConstraintsFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBufferCollectionFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferCollectionPropertiesFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties); +#endif + #ifdef __cplusplus } #endif diff --git a/libraries/ZVulkan/include/vulkan/vulkan_ggp.h b/libraries/ZVulkan/include/vulkan/vulkan_ggp.h index 9a6a582c5b..9783aa3b38 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_ggp.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_ggp.h @@ -2,7 +2,7 @@ #define VULKAN_GGP_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_GGP_stream_descriptor_surface is a preprocessor guard. Do not pass it to API calls. #define VK_GGP_stream_descriptor_surface 1 #define VK_GGP_STREAM_DESCRIPTOR_SURFACE_SPEC_VERSION 1 #define VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME "VK_GGP_stream_descriptor_surface" @@ -41,6 +42,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateStreamDescriptorSurfaceGGP( #endif +// VK_GGP_frame_token is a preprocessor guard. Do not pass it to API calls. #define VK_GGP_frame_token 1 #define VK_GGP_FRAME_TOKEN_SPEC_VERSION 1 #define VK_GGP_FRAME_TOKEN_EXTENSION_NAME "VK_GGP_frame_token" diff --git a/libraries/ZVulkan/include/vulkan/vulkan_ios.h b/libraries/ZVulkan/include/vulkan/vulkan_ios.h index 6e7e6afea6..211429ff45 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_ios.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_ios.h @@ -2,7 +2,7 @@ #define VULKAN_IOS_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_MVK_ios_surface is a preprocessor guard. Do not pass it to API calls. #define VK_MVK_ios_surface 1 #define VK_MVK_IOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface" diff --git a/libraries/ZVulkan/include/vulkan/vulkan_macos.h b/libraries/ZVulkan/include/vulkan/vulkan_macos.h index c49b123d07..c6509cc8cf 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_macos.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_macos.h @@ -2,7 +2,7 @@ #define VULKAN_MACOS_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_MVK_macos_surface is a preprocessor guard. Do not pass it to API calls. #define VK_MVK_macos_surface 1 #define VK_MVK_MACOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface" diff --git a/libraries/ZVulkan/include/vulkan/vulkan_metal.h b/libraries/ZVulkan/include/vulkan/vulkan_metal.h index 5cf4a703ac..94563a003a 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_metal.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_metal.h @@ -2,7 +2,7 @@ #define VULKAN_METAL_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,8 +19,8 @@ extern "C" { +// VK_EXT_metal_surface is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_metal_surface 1 - #ifdef __OBJC__ @class CAMetalLayer; #else @@ -47,6 +47,147 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT( VkSurfaceKHR* pSurface); #endif + +// VK_EXT_metal_objects is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_metal_objects 1 +#ifdef __OBJC__ +@protocol MTLDevice; +typedef id MTLDevice_id; +#else +typedef void* MTLDevice_id; +#endif + +#ifdef __OBJC__ +@protocol MTLCommandQueue; +typedef id MTLCommandQueue_id; +#else +typedef void* MTLCommandQueue_id; +#endif + +#ifdef __OBJC__ +@protocol MTLBuffer; +typedef id MTLBuffer_id; +#else +typedef void* MTLBuffer_id; +#endif + +#ifdef __OBJC__ +@protocol MTLTexture; +typedef id MTLTexture_id; +#else +typedef void* MTLTexture_id; +#endif + +typedef struct __IOSurface* IOSurfaceRef; +#ifdef __OBJC__ +@protocol MTLSharedEvent; +typedef id MTLSharedEvent_id; +#else +typedef void* MTLSharedEvent_id; +#endif + +#define VK_EXT_METAL_OBJECTS_SPEC_VERSION 1 +#define VK_EXT_METAL_OBJECTS_EXTENSION_NAME "VK_EXT_metal_objects" + +typedef enum VkExportMetalObjectTypeFlagBitsEXT { + VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT = 0x00000001, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT = 0x00000002, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT = 0x00000004, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT = 0x00000008, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT = 0x00000010, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT = 0x00000020, + VK_EXPORT_METAL_OBJECT_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkExportMetalObjectTypeFlagBitsEXT; +typedef VkFlags VkExportMetalObjectTypeFlagsEXT; +typedef struct VkExportMetalObjectCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkExportMetalObjectTypeFlagBitsEXT exportObjectType; +} VkExportMetalObjectCreateInfoEXT; + +typedef struct VkExportMetalObjectsInfoEXT { + VkStructureType sType; + const void* pNext; +} VkExportMetalObjectsInfoEXT; + +typedef struct VkExportMetalDeviceInfoEXT { + VkStructureType sType; + const void* pNext; + MTLDevice_id mtlDevice; +} VkExportMetalDeviceInfoEXT; + +typedef struct VkExportMetalCommandQueueInfoEXT { + VkStructureType sType; + const void* pNext; + VkQueue queue; + MTLCommandQueue_id mtlCommandQueue; +} VkExportMetalCommandQueueInfoEXT; + +typedef struct VkExportMetalBufferInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + MTLBuffer_id mtlBuffer; +} VkExportMetalBufferInfoEXT; + +typedef struct VkImportMetalBufferInfoEXT { + VkStructureType sType; + const void* pNext; + MTLBuffer_id mtlBuffer; +} VkImportMetalBufferInfoEXT; + +typedef struct VkExportMetalTextureInfoEXT { + VkStructureType sType; + const void* pNext; + VkImage image; + VkImageView imageView; + VkBufferView bufferView; + VkImageAspectFlagBits plane; + MTLTexture_id mtlTexture; +} VkExportMetalTextureInfoEXT; + +typedef struct VkImportMetalTextureInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits plane; + MTLTexture_id mtlTexture; +} VkImportMetalTextureInfoEXT; + +typedef struct VkExportMetalIOSurfaceInfoEXT { + VkStructureType sType; + const void* pNext; + VkImage image; + IOSurfaceRef ioSurface; +} VkExportMetalIOSurfaceInfoEXT; + +typedef struct VkImportMetalIOSurfaceInfoEXT { + VkStructureType sType; + const void* pNext; + IOSurfaceRef ioSurface; +} VkImportMetalIOSurfaceInfoEXT; + +typedef struct VkExportMetalSharedEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkEvent event; + MTLSharedEvent_id mtlSharedEvent; +} VkExportMetalSharedEventInfoEXT; + +typedef struct VkImportMetalSharedEventInfoEXT { + VkStructureType sType; + const void* pNext; + MTLSharedEvent_id mtlSharedEvent; +} VkImportMetalSharedEventInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkExportMetalObjectsEXT)(VkDevice device, VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkExportMetalObjectsEXT( + VkDevice device, + VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); +#endif + #ifdef __cplusplus } #endif diff --git a/libraries/ZVulkan/include/vulkan/vulkan_screen.h b/libraries/ZVulkan/include/vulkan/vulkan_screen.h index 92ad9bfab4..981738f738 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_screen.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_screen.h @@ -2,7 +2,7 @@ #define VULKAN_SCREEN_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_QNX_screen_surface is a preprocessor guard. Do not pass it to API calls. #define VK_QNX_screen_surface 1 #define VK_QNX_SCREEN_SURFACE_SPEC_VERSION 1 #define VK_QNX_SCREEN_SURFACE_EXTENSION_NAME "VK_QNX_screen_surface" @@ -47,6 +48,59 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceScreenPresentationSupportQNX( struct _screen_window* window); #endif + +// VK_QNX_external_memory_screen_buffer is a preprocessor guard. Do not pass it to API calls. +#define VK_QNX_external_memory_screen_buffer 1 +#define VK_QNX_EXTERNAL_MEMORY_SCREEN_BUFFER_SPEC_VERSION 1 +#define VK_QNX_EXTERNAL_MEMORY_SCREEN_BUFFER_EXTENSION_NAME "VK_QNX_external_memory_screen_buffer" +typedef struct VkScreenBufferPropertiesQNX { + VkStructureType sType; + void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeBits; +} VkScreenBufferPropertiesQNX; + +typedef struct VkScreenBufferFormatPropertiesQNX { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + uint64_t screenUsage; + VkFormatFeatureFlags formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkScreenBufferFormatPropertiesQNX; + +typedef struct VkImportScreenBufferInfoQNX { + VkStructureType sType; + const void* pNext; + struct _screen_buffer* buffer; +} VkImportScreenBufferInfoQNX; + +typedef struct VkExternalFormatQNX { + VkStructureType sType; + void* pNext; + uint64_t externalFormat; +} VkExternalFormatQNX; + +typedef struct VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX { + VkStructureType sType; + void* pNext; + VkBool32 screenBufferImport; +} VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX; + +typedef VkResult (VKAPI_PTR *PFN_vkGetScreenBufferPropertiesQNX)(VkDevice device, const struct _screen_buffer* buffer, VkScreenBufferPropertiesQNX* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetScreenBufferPropertiesQNX( + VkDevice device, + const struct _screen_buffer* buffer, + VkScreenBufferPropertiesQNX* pProperties); +#endif + #ifdef __cplusplus } #endif diff --git a/libraries/ZVulkan/include/vulkan/vulkan_vi.h b/libraries/ZVulkan/include/vulkan/vulkan_vi.h index 9e0dcca200..c9227e8226 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_vi.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_vi.h @@ -2,7 +2,7 @@ #define VULKAN_VI_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_NN_vi_surface is a preprocessor guard. Do not pass it to API calls. #define VK_NN_vi_surface 1 #define VK_NN_VI_SURFACE_SPEC_VERSION 1 #define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface" diff --git a/libraries/ZVulkan/include/vulkan/vulkan_wayland.h b/libraries/ZVulkan/include/vulkan/vulkan_wayland.h index 2a329be9dd..c93b217872 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_wayland.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_wayland.h @@ -2,7 +2,7 @@ #define VULKAN_WAYLAND_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_KHR_wayland_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_wayland_surface 1 #define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 #define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" diff --git a/libraries/ZVulkan/include/vulkan/vulkan_win32.h b/libraries/ZVulkan/include/vulkan/vulkan_win32.h index 1b680f0b1a..fae3b8532c 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_win32.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_win32.h @@ -2,7 +2,7 @@ #define VULKAN_WIN32_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_KHR_win32_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_win32_surface 1 #define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6 #define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface" @@ -47,6 +48,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR( #endif +// VK_KHR_external_memory_win32 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_memory_win32 1 #define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32" @@ -96,6 +98,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR( #endif +// VK_KHR_win32_keyed_mutex is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_win32_keyed_mutex 1 #define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1 #define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex" @@ -113,6 +116,7 @@ typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR { +// VK_KHR_external_semaphore_win32 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_semaphore_win32 1 #define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32" @@ -165,6 +169,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR( #endif +// VK_KHR_external_fence_win32 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_fence_win32 1 #define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32" @@ -208,6 +213,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR( #endif +// VK_NV_external_memory_win32 is a preprocessor guard. Do not pass it to API calls. #define VK_NV_external_memory_win32 1 #define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 #define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32" @@ -236,6 +242,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV( #endif +// VK_NV_win32_keyed_mutex is a preprocessor guard. Do not pass it to API calls. #define VK_NV_win32_keyed_mutex 1 #define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 2 #define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex" @@ -253,6 +260,7 @@ typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV { +// VK_EXT_full_screen_exclusive is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_full_screen_exclusive 1 #define VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION 4 #define VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME "VK_EXT_full_screen_exclusive" @@ -308,6 +316,25 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT( VkDeviceGroupPresentModeFlagsKHR* pModes); #endif + +// VK_NV_acquire_winrt_display is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_acquire_winrt_display 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME "VK_NV_acquire_winrt_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireWinrtDisplayNV)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetWinrtDisplayNV)(VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + uint32_t deviceRelativeId, + VkDisplayKHR* pDisplay); +#endif + #ifdef __cplusplus } #endif diff --git a/libraries/ZVulkan/include/vulkan/vulkan_xcb.h b/libraries/ZVulkan/include/vulkan/vulkan_xcb.h index 5ba2ad850a..de7405524a 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_xcb.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_xcb.h @@ -2,7 +2,7 @@ #define VULKAN_XCB_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_KHR_xcb_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_xcb_surface 1 #define VK_KHR_XCB_SURFACE_SPEC_VERSION 6 #define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface" diff --git a/libraries/ZVulkan/include/vulkan/vulkan_xlib.h b/libraries/ZVulkan/include/vulkan/vulkan_xlib.h index 75c75dc2e3..1aa632f2ef 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_xlib.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_xlib.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_KHR_xlib_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_xlib_surface 1 #define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6 #define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface" diff --git a/libraries/ZVulkan/include/vulkan/vulkan_xlib_xrandr.h b/libraries/ZVulkan/include/vulkan/vulkan_xlib_xrandr.h index fa27493422..e164ffc91e 100644 --- a/libraries/ZVulkan/include/vulkan/vulkan_xlib_xrandr.h +++ b/libraries/ZVulkan/include/vulkan/vulkan_xlib_xrandr.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_XRANDR_H_ 1 /* -** Copyright 2015-2021 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ extern "C" { +// VK_EXT_acquire_xlib_display is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_acquire_xlib_display 1 #define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1 #define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display" diff --git a/libraries/ZVulkan/include/zvulkan/vk_mem_alloc/vk_mem_alloc.h b/libraries/ZVulkan/include/zvulkan/vk_mem_alloc/vk_mem_alloc.h index 0db362f0ed..39f9d9d42e 100644 --- a/libraries/ZVulkan/include/zvulkan/vk_mem_alloc/vk_mem_alloc.h +++ b/libraries/ZVulkan/include/zvulkan/vk_mem_alloc/vk_mem_alloc.h @@ -121,8 +121,9 @@ for user-defined purpose without allocating any real GPU memory. See documentation chapter: \ref statistics. */ -#include + #ifdef __cplusplus +#include extern "C" { #endif diff --git a/libraries/ZVulkan/include/zvulkan/volk/volk.h b/libraries/ZVulkan/include/zvulkan/volk/volk.h index 2e292ca114..47fbed2391 100644 --- a/libraries/ZVulkan/include/zvulkan/volk/volk.h +++ b/libraries/ZVulkan/include/zvulkan/volk/volk.h @@ -1,7 +1,7 @@ /** * volk * - * Copyright (C) 2018-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2018-2023, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://github.com/zeux/volk * * This library is distributed under the MIT License. See notice at the end of this file. @@ -15,7 +15,7 @@ #endif /* VOLK_GENERATE_VERSION_DEFINE */ -#define VOLK_HEADER_VERSION 190 +#define VOLK_HEADER_VERSION 270 /* VOLK_GENERATE_VERSION_DEFINE */ #ifndef VK_NO_PROTOTYPES @@ -23,8 +23,8 @@ #endif #ifndef VULKAN_H_ -# ifdef VOLK_VULKAN_H_PATH -# include VOLK_VULKAN_H_PATH +# ifdef VOLK_VULKAN_H_PATH +# include VOLK_VULKAN_H_PATH # elif defined(VK_USE_PLATFORM_WIN32_KHR) # include # include @@ -81,6 +81,11 @@ VkResult volkInitialize(void); */ void volkInitializeCustom(PFN_vkGetInstanceProcAddr handler); +/** + * Finalize library by unloading Vulkan loader and resetting global symbols to NULL. + */ +void volkFinalize(void); + /** * Get Vulkan instance version supported by the Vulkan loader, or 0 if Vulkan isn't supported * @@ -285,6 +290,53 @@ struct VolkDeviceTable PFN_vkSignalSemaphore vkSignalSemaphore; PFN_vkWaitSemaphores vkWaitSemaphores; #endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) + PFN_vkCmdBeginRendering vkCmdBeginRendering; + PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2; + PFN_vkCmdBlitImage2 vkCmdBlitImage2; + PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2; + PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2; + PFN_vkCmdCopyImage2 vkCmdCopyImage2; + PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2; + PFN_vkCmdEndRendering vkCmdEndRendering; + PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2; + PFN_vkCmdResetEvent2 vkCmdResetEvent2; + PFN_vkCmdResolveImage2 vkCmdResolveImage2; + PFN_vkCmdSetCullMode vkCmdSetCullMode; + PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable; + PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable; + PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp; + PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable; + PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable; + PFN_vkCmdSetEvent2 vkCmdSetEvent2; + PFN_vkCmdSetFrontFace vkCmdSetFrontFace; + PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable; + PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology; + PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable; + PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount; + PFN_vkCmdSetStencilOp vkCmdSetStencilOp; + PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable; + PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount; + PFN_vkCmdWaitEvents2 vkCmdWaitEvents2; + PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2; + PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot; + PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot; + PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements; + PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements; + PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements; + PFN_vkGetPrivateData vkGetPrivateData; + PFN_vkQueueSubmit2 vkQueueSubmit2; + PFN_vkSetPrivateData vkSetPrivateData; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_AMDX_shader_enqueue) + PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; + PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; + PFN_vkCmdDispatchGraphIndirectCountAMDX vkCmdDispatchGraphIndirectCountAMDX; + PFN_vkCmdInitializeGraphScratchMemoryAMDX vkCmdInitializeGraphScratchMemoryAMDX; + PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAMDX; + PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; + PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; +#endif /* defined(VK_AMDX_shader_enqueue) */ #if defined(VK_AMD_buffer_marker) PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; #endif /* defined(VK_AMD_buffer_marker) */ @@ -302,6 +354,9 @@ struct VolkDeviceTable PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) + PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT; +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ #if defined(VK_EXT_buffer_device_address) PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; #endif /* defined(VK_EXT_buffer_device_address) */ @@ -322,36 +377,40 @@ struct VolkDeviceTable PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT; PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT; #endif /* defined(VK_EXT_debug_marker) */ +#if defined(VK_EXT_depth_bias_control) + PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT; +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) + PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT vkCmdBindDescriptorBufferEmbeddedSamplersEXT; + PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffersEXT; + PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsetsEXT; + PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT vkGetBufferOpaqueCaptureDescriptorDataEXT; + PFN_vkGetDescriptorEXT vkGetDescriptorEXT; + PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffsetEXT; + PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSizeEXT; + PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescriptorDataEXT; + PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; + PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) + PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_device_fault) + PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; +#endif /* defined(VK_EXT_device_fault) */ #if defined(VK_EXT_discard_rectangles) PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; + PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT; PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; #endif /* defined(VK_EXT_display_control) */ -#if defined(VK_EXT_extended_dynamic_state) - PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; - PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; - PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; - PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; - PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; - PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; - PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; - PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; - PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; - PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; - PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; - PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) - PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; - PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; - PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; - PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; - PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; -#endif /* defined(VK_EXT_extended_dynamic_state2) */ #if defined(VK_EXT_external_memory_host) PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; #endif /* defined(VK_EXT_external_memory_host) */ @@ -362,6 +421,12 @@ struct VolkDeviceTable #if defined(VK_EXT_hdr_metadata) PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; #endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_image_copy) + PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT; + PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT; + PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT; + PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT; +#endif /* defined(VK_EXT_host_image_copy) */ #if defined(VK_EXT_host_query_reset) PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; #endif /* defined(VK_EXT_host_query_reset) */ @@ -371,10 +436,40 @@ struct VolkDeviceTable #if defined(VK_EXT_line_rasterization) PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; #endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_mesh_shader) + PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; + PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; + PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_metal_objects) + PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; +#endif /* defined(VK_EXT_metal_objects) */ #if defined(VK_EXT_multi_draw) PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; #endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) + PFN_vkBuildMicromapsEXT vkBuildMicromapsEXT; + PFN_vkCmdBuildMicromapsEXT vkCmdBuildMicromapsEXT; + PFN_vkCmdCopyMemoryToMicromapEXT vkCmdCopyMemoryToMicromapEXT; + PFN_vkCmdCopyMicromapEXT vkCmdCopyMicromapEXT; + PFN_vkCmdCopyMicromapToMemoryEXT vkCmdCopyMicromapToMemoryEXT; + PFN_vkCmdWriteMicromapsPropertiesEXT vkCmdWriteMicromapsPropertiesEXT; + PFN_vkCopyMemoryToMicromapEXT vkCopyMemoryToMicromapEXT; + PFN_vkCopyMicromapEXT vkCopyMicromapEXT; + PFN_vkCopyMicromapToMemoryEXT vkCopyMicromapToMemoryEXT; + PFN_vkCreateMicromapEXT vkCreateMicromapEXT; + PFN_vkDestroyMicromapEXT vkDestroyMicromapEXT; + PFN_vkGetDeviceMicromapCompatibilityEXT vkGetDeviceMicromapCompatibilityEXT; + PFN_vkGetMicromapBuildSizesEXT vkGetMicromapBuildSizesEXT; + PFN_vkWriteMicromapsPropertiesEXT vkWriteMicromapsPropertiesEXT; +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) + PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT; +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) + PFN_vkGetPipelinePropertiesEXT vkGetPipelinePropertiesEXT; +#endif /* defined(VK_EXT_pipeline_properties) */ #if defined(VK_EXT_private_data) PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; @@ -384,6 +479,19 @@ struct VolkDeviceTable #if defined(VK_EXT_sample_locations) PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; #endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) + PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; + PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; + PFN_vkCreateShadersEXT vkCreateShadersEXT; + PFN_vkDestroyShaderEXT vkDestroyShaderEXT; + PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) + PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; +#endif /* defined(VK_EXT_swapchain_maintenance1) */ #if defined(VK_EXT_transform_feedback) PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT; PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT; @@ -398,9 +506,13 @@ struct VolkDeviceTable PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) - PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ +#if defined(VK_FUCHSIA_buffer_collection) + PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; + PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; + PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA; + PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA; + PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA; +#endif /* defined(VK_FUCHSIA_buffer_collection) */ #if defined(VK_FUCHSIA_external_memory) PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; @@ -413,6 +525,10 @@ struct VolkDeviceTable PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; + PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -496,6 +612,10 @@ struct VolkDeviceTable PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; + PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_fd) PFN_vkGetFenceFdKHR vkGetFenceFdKHR; PFN_vkImportFenceFdKHR vkImportFenceFdKHR; @@ -534,6 +654,21 @@ struct VolkDeviceTable #if defined(VK_KHR_maintenance3) PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; #endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) + PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR; + PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; + PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) + PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR; + PFN_vkGetDeviceImageSubresourceLayoutKHR vkGetDeviceImageSubresourceLayoutKHR; + PFN_vkGetImageSubresourceLayout2KHR vkGetImageSubresourceLayout2KHR; + PFN_vkGetRenderingAreaGranularityKHR vkGetRenderingAreaGranularityKHR; +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_map_memory2) + PFN_vkMapMemory2KHR vkMapMemory2KHR; + PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; @@ -549,6 +684,9 @@ struct VolkDeviceTable #if defined(VK_KHR_push_descriptor) PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) + PFN_vkCmdTraceRaysIndirect2KHR vkCmdTraceRaysIndirect2KHR; +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_ray_tracing_pipeline) PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; @@ -596,6 +734,7 @@ struct VolkDeviceTable #endif /* defined(VK_KHR_video_decode_queue) */ #if defined(VK_KHR_video_encode_queue) PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; + PFN_vkGetEncodedVideoSessionParametersKHR vkGetEncodedVideoSessionParametersKHR; #endif /* defined(VK_KHR_video_encode_queue) */ #if defined(VK_KHR_video_queue) PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; @@ -623,6 +762,18 @@ struct VolkDeviceTable #if defined(VK_NV_clip_space_w_scaling) PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; #endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_copy_memory_indirect) + PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; + PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; +#endif /* defined(VK_NV_copy_memory_indirect) */ +#if defined(VK_NV_cuda_kernel_launch) + PFN_vkCmdCudaLaunchKernelNV vkCmdCudaLaunchKernelNV; + PFN_vkCreateCudaFunctionNV vkCreateCudaFunctionNV; + PFN_vkCreateCudaModuleNV vkCreateCudaModuleNV; + PFN_vkDestroyCudaFunctionNV vkDestroyCudaFunctionNV; + PFN_vkDestroyCudaModuleNV vkDestroyCudaModuleNV; + PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; +#endif /* defined(VK_NV_cuda_kernel_launch) */ #if defined(VK_NV_device_diagnostic_checkpoints) PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; @@ -635,6 +786,11 @@ struct VolkDeviceTable PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; #endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) + PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBufferNV; + PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; + PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands_compute) */ #if defined(VK_NV_external_memory_rdma) PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; #endif /* defined(VK_NV_external_memory_rdma) */ @@ -644,11 +800,28 @@ struct VolkDeviceTable #if defined(VK_NV_fragment_shading_rate_enums) PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; + PFN_vkLatencySleepNV vkLatencySleepNV; + PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; + PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; + PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) + PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; + PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; +#endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_optical_flow) + PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; + PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; + PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; + PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; +#endif /* defined(VK_NV_optical_flow) */ #if defined(VK_NV_ray_tracing) PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; @@ -663,6 +836,9 @@ struct VolkDeviceTable PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; #endif /* defined(VK_NV_scissor_exclusive) */ @@ -671,9 +847,94 @@ struct VolkDeviceTable PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_properties) + PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; + PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QNX_external_memory_screen_buffer) + PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) + PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; + PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; + PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; + PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; + PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; + PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; + PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; + PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; + PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; + PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; + PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; + PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; + PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; + PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; + PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; + PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; + PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; + PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; + PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; + PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; + PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; + PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; + PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; + PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; + PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; + PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; + PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; + PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; + PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; + PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; + PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; + PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; + PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; + PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; + PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; + PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; + PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) + PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) + PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) + PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; + PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) + PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; + PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; + PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) + PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) + PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) + PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) + PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ @@ -872,6 +1133,54 @@ extern PFN_vkResetQueryPool vkResetQueryPool; extern PFN_vkSignalSemaphore vkSignalSemaphore; extern PFN_vkWaitSemaphores vkWaitSemaphores; #endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) +extern PFN_vkCmdBeginRendering vkCmdBeginRendering; +extern PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2; +extern PFN_vkCmdBlitImage2 vkCmdBlitImage2; +extern PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2; +extern PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2; +extern PFN_vkCmdCopyImage2 vkCmdCopyImage2; +extern PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2; +extern PFN_vkCmdEndRendering vkCmdEndRendering; +extern PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2; +extern PFN_vkCmdResetEvent2 vkCmdResetEvent2; +extern PFN_vkCmdResolveImage2 vkCmdResolveImage2; +extern PFN_vkCmdSetCullMode vkCmdSetCullMode; +extern PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable; +extern PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable; +extern PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp; +extern PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable; +extern PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable; +extern PFN_vkCmdSetEvent2 vkCmdSetEvent2; +extern PFN_vkCmdSetFrontFace vkCmdSetFrontFace; +extern PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable; +extern PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology; +extern PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable; +extern PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount; +extern PFN_vkCmdSetStencilOp vkCmdSetStencilOp; +extern PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable; +extern PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount; +extern PFN_vkCmdWaitEvents2 vkCmdWaitEvents2; +extern PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2; +extern PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot; +extern PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot; +extern PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements; +extern PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements; +extern PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements; +extern PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties; +extern PFN_vkGetPrivateData vkGetPrivateData; +extern PFN_vkQueueSubmit2 vkQueueSubmit2; +extern PFN_vkSetPrivateData vkSetPrivateData; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_AMDX_shader_enqueue) +extern PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; +extern PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; +extern PFN_vkCmdDispatchGraphIndirectCountAMDX vkCmdDispatchGraphIndirectCountAMDX; +extern PFN_vkCmdInitializeGraphScratchMemoryAMDX vkCmdInitializeGraphScratchMemoryAMDX; +extern PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAMDX; +extern PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; +extern PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; +#endif /* defined(VK_AMDX_shader_enqueue) */ #if defined(VK_AMD_buffer_marker) extern PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; #endif /* defined(VK_AMD_buffer_marker) */ @@ -897,6 +1206,9 @@ extern PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; extern PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; extern PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; #endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) +extern PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT; +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ #if defined(VK_EXT_buffer_device_address) extern PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; #endif /* defined(VK_EXT_buffer_device_address) */ @@ -936,6 +1248,27 @@ extern PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; extern PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; extern PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; #endif /* defined(VK_EXT_debug_utils) */ +#if defined(VK_EXT_depth_bias_control) +extern PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT; +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) +extern PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT vkCmdBindDescriptorBufferEmbeddedSamplersEXT; +extern PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffersEXT; +extern PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsetsEXT; +extern PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT vkGetBufferOpaqueCaptureDescriptorDataEXT; +extern PFN_vkGetDescriptorEXT vkGetDescriptorEXT; +extern PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffsetEXT; +extern PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSizeEXT; +extern PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescriptorDataEXT; +extern PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; +extern PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) +extern PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_device_fault) +extern PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; +#endif /* defined(VK_EXT_device_fault) */ #if defined(VK_EXT_direct_mode_display) extern PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; #endif /* defined(VK_EXT_direct_mode_display) */ @@ -946,6 +1279,10 @@ extern PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDevice #if defined(VK_EXT_discard_rectangles) extern PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 +extern PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; +extern PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) extern PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; extern PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; @@ -955,27 +1292,6 @@ extern PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; #if defined(VK_EXT_display_surface_counter) extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; #endif /* defined(VK_EXT_display_surface_counter) */ -#if defined(VK_EXT_extended_dynamic_state) -extern PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; -extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; -extern PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; -extern PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; -extern PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; -extern PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; -extern PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; -extern PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; -extern PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; -extern PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; -extern PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; -extern PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) -extern PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; -extern PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; -extern PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; -extern PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; -extern PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; -#endif /* defined(VK_EXT_extended_dynamic_state2) */ #if defined(VK_EXT_external_memory_host) extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; #endif /* defined(VK_EXT_external_memory_host) */ @@ -990,6 +1306,12 @@ extern PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; #if defined(VK_EXT_headless_surface) extern PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; #endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_host_image_copy) +extern PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT; +extern PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT; +extern PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT; +extern PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT; +#endif /* defined(VK_EXT_host_image_copy) */ #if defined(VK_EXT_host_query_reset) extern PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; #endif /* defined(VK_EXT_host_query_reset) */ @@ -999,6 +1321,14 @@ extern PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierP #if defined(VK_EXT_line_rasterization) extern PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; #endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_mesh_shader) +extern PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; +extern PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; +extern PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_metal_objects) +extern PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; +#endif /* defined(VK_EXT_metal_objects) */ #if defined(VK_EXT_metal_surface) extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; #endif /* defined(VK_EXT_metal_surface) */ @@ -1006,6 +1336,28 @@ extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; extern PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; extern PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; #endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) +extern PFN_vkBuildMicromapsEXT vkBuildMicromapsEXT; +extern PFN_vkCmdBuildMicromapsEXT vkCmdBuildMicromapsEXT; +extern PFN_vkCmdCopyMemoryToMicromapEXT vkCmdCopyMemoryToMicromapEXT; +extern PFN_vkCmdCopyMicromapEXT vkCmdCopyMicromapEXT; +extern PFN_vkCmdCopyMicromapToMemoryEXT vkCmdCopyMicromapToMemoryEXT; +extern PFN_vkCmdWriteMicromapsPropertiesEXT vkCmdWriteMicromapsPropertiesEXT; +extern PFN_vkCopyMemoryToMicromapEXT vkCopyMemoryToMicromapEXT; +extern PFN_vkCopyMicromapEXT vkCopyMicromapEXT; +extern PFN_vkCopyMicromapToMemoryEXT vkCopyMicromapToMemoryEXT; +extern PFN_vkCreateMicromapEXT vkCreateMicromapEXT; +extern PFN_vkDestroyMicromapEXT vkDestroyMicromapEXT; +extern PFN_vkGetDeviceMicromapCompatibilityEXT vkGetDeviceMicromapCompatibilityEXT; +extern PFN_vkGetMicromapBuildSizesEXT vkGetMicromapBuildSizesEXT; +extern PFN_vkWriteMicromapsPropertiesEXT vkWriteMicromapsPropertiesEXT; +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) +extern PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT; +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) +extern PFN_vkGetPipelinePropertiesEXT vkGetPipelinePropertiesEXT; +#endif /* defined(VK_EXT_pipeline_properties) */ #if defined(VK_EXT_private_data) extern PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; extern PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; @@ -1016,6 +1368,19 @@ extern PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; extern PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; extern PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; #endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) +extern PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; +extern PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) +extern PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; +extern PFN_vkCreateShadersEXT vkCreateShadersEXT; +extern PFN_vkDestroyShaderEXT vkDestroyShaderEXT; +extern PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) +extern PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; +#endif /* defined(VK_EXT_swapchain_maintenance1) */ #if defined(VK_EXT_tooling_info) extern PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; #endif /* defined(VK_EXT_tooling_info) */ @@ -1033,9 +1398,13 @@ extern PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT; extern PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; extern PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) -extern PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ +#if defined(VK_FUCHSIA_buffer_collection) +extern PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; +extern PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; +extern PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA; +extern PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA; +extern PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA; +#endif /* defined(VK_FUCHSIA_buffer_collection) */ #if defined(VK_FUCHSIA_external_memory) extern PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; extern PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; @@ -1054,6 +1423,10 @@ extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) +extern PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; +extern PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) extern PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -1102,6 +1475,9 @@ extern PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; extern PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; extern PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; #endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_cooperative_matrix) +extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR; +#endif /* defined(VK_KHR_cooperative_matrix) */ #if defined(VK_KHR_copy_commands2) extern PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; extern PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; @@ -1152,6 +1528,10 @@ extern PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; extern PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; extern PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) +extern PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; +extern PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_capabilities) extern PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; #endif /* defined(VK_KHR_external_fence_capabilities) */ @@ -1219,6 +1599,21 @@ extern PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; #if defined(VK_KHR_maintenance3) extern PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; #endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) +extern PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR; +extern PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; +extern PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) +extern PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR; +extern PFN_vkGetDeviceImageSubresourceLayoutKHR vkGetDeviceImageSubresourceLayoutKHR; +extern PFN_vkGetImageSubresourceLayout2KHR vkGetImageSubresourceLayout2KHR; +extern PFN_vkGetRenderingAreaGranularityKHR vkGetRenderingAreaGranularityKHR; +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_map_memory2) +extern PFN_vkMapMemory2KHR vkMapMemory2KHR; +extern PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) extern PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; @@ -1236,6 +1631,9 @@ extern PFN_vkWaitForPresentKHR vkWaitForPresentKHR; #if defined(VK_KHR_push_descriptor) extern PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) +extern PFN_vkCmdTraceRaysIndirect2KHR vkCmdTraceRaysIndirect2KHR; +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_ray_tracing_pipeline) extern PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; extern PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; @@ -1290,6 +1688,8 @@ extern PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; #endif /* defined(VK_KHR_video_decode_queue) */ #if defined(VK_KHR_video_encode_queue) extern PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; +extern PFN_vkGetEncodedVideoSessionParametersKHR vkGetEncodedVideoSessionParametersKHR; +extern PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR; #endif /* defined(VK_KHR_video_encode_queue) */ #if defined(VK_KHR_video_queue) extern PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; @@ -1351,9 +1751,21 @@ extern PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; #if defined(VK_NV_cooperative_matrix) extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; #endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_copy_memory_indirect) +extern PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; +extern PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; +#endif /* defined(VK_NV_copy_memory_indirect) */ #if defined(VK_NV_coverage_reduction_mode) extern PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; #endif /* defined(VK_NV_coverage_reduction_mode) */ +#if defined(VK_NV_cuda_kernel_launch) +extern PFN_vkCmdCudaLaunchKernelNV vkCmdCudaLaunchKernelNV; +extern PFN_vkCreateCudaFunctionNV vkCreateCudaFunctionNV; +extern PFN_vkCreateCudaModuleNV vkCreateCudaModuleNV; +extern PFN_vkDestroyCudaFunctionNV vkDestroyCudaFunctionNV; +extern PFN_vkDestroyCudaModuleNV vkDestroyCudaModuleNV; +extern PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; +#endif /* defined(VK_NV_cuda_kernel_launch) */ #if defined(VK_NV_device_diagnostic_checkpoints) extern PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; extern PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; @@ -1366,6 +1778,11 @@ extern PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; extern PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; extern PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; #endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) +extern PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBufferNV; +extern PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; +extern PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands_compute) */ #if defined(VK_NV_external_memory_capabilities) extern PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; #endif /* defined(VK_NV_external_memory_capabilities) */ @@ -1378,11 +1795,29 @@ extern PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; #if defined(VK_NV_fragment_shading_rate_enums) extern PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) +extern PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; +extern PFN_vkLatencySleepNV vkLatencySleepNV; +extern PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; +extern PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; +extern PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) +extern PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; +extern PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; +#endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) extern PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; extern PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; extern PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_optical_flow) +extern PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; +extern PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; +extern PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; +extern PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; +extern PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV vkGetPhysicalDeviceOpticalFlowImageFormatsNV; +#endif /* defined(VK_NV_optical_flow) */ #if defined(VK_NV_ray_tracing) extern PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; extern PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; @@ -1397,6 +1832,9 @@ extern PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV extern PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; extern PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 +extern PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) extern PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; #endif /* defined(VK_NV_scissor_exclusive) */ @@ -1405,13 +1843,98 @@ extern PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; extern PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; extern PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_properties) +extern PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; +extern PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QNX_external_memory_screen_buffer) +extern PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ #if defined(VK_QNX_screen_surface) extern PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; extern PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; #endif /* defined(VK_QNX_screen_surface) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) +extern PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; +extern PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; +extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; +extern PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; +extern PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; +extern PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; +extern PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; +extern PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; +extern PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; +extern PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; +extern PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; +extern PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; +extern PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; +extern PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; +extern PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; +extern PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; +extern PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; +extern PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; +extern PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; +extern PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; +extern PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; +extern PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; +extern PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; +extern PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; +extern PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; +extern PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; +extern PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; +extern PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; +extern PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; +extern PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; +extern PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; +extern PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; +extern PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; +extern PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; +extern PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; +extern PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; +extern PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) +extern PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) +extern PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) +extern PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; +extern PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) +extern PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; +extern PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; +extern PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) +extern PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) +extern PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) +extern PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) extern PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) +extern PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) +extern PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) extern PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ @@ -1433,14 +1956,13 @@ extern PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; #ifdef VOLK_IMPLEMENTATION #undef VOLK_IMPLEMENTATION -// Prevent tools like dependency checkers that don't evaluate -// macros from detecting a cyclic dependency. +/* Prevent tools like dependency checkers from detecting a cyclic dependency */ #define VOLK_SOURCE "volk.c" #include VOLK_SOURCE #endif /** - * Copyright (c) 2018-2019 Arseny Kapoulkine + * Copyright (c) 2018-2023 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h b/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h index 104d9ceef1..4e11676695 100644 --- a/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h +++ b/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h @@ -144,7 +144,7 @@ class ImageViewBuilder ImageViewBuilder(); ImageViewBuilder& Type(VkImageViewType type); - ImageViewBuilder& Image(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT); + ImageViewBuilder& Image(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int mipLevel = 0, int arrayLayer = 0, int levelCount = 0, int layerCount = 0); ImageViewBuilder& DebugName(const char* name) { debugName = name; return *this; } std::unique_ptr Create(VulkanDevice *device); @@ -350,6 +350,22 @@ class FramebufferBuilder const char* debugName = nullptr; }; +class ColorBlendAttachmentBuilder +{ +public: + ColorBlendAttachmentBuilder(); + + ColorBlendAttachmentBuilder& ColorWriteMask(VkColorComponentFlags mask); + ColorBlendAttachmentBuilder& AdditiveBlendMode(); + ColorBlendAttachmentBuilder& AlphaBlendMode(); + ColorBlendAttachmentBuilder& BlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst); + + VkPipelineColorBlendAttachmentState Create() { return colorBlendAttachment; } + +private: + VkPipelineColorBlendAttachmentState colorBlendAttachment = { }; +}; + class GraphicsPipelineBuilder { public: @@ -369,13 +385,9 @@ class GraphicsPipelineBuilder GraphicsPipelineBuilder& DepthFunc(VkCompareOp func); GraphicsPipelineBuilder& DepthClampEnable(bool value); GraphicsPipelineBuilder& DepthBias(bool enable, float biasConstantFactor, float biasClamp, float biasSlopeFactor); - GraphicsPipelineBuilder& ColorWriteMask(VkColorComponentFlags mask); GraphicsPipelineBuilder& Stencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference); - GraphicsPipelineBuilder& AdditiveBlendMode(); - GraphicsPipelineBuilder& AlphaBlendMode(); - GraphicsPipelineBuilder& BlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst); - GraphicsPipelineBuilder& SubpassColorAttachmentCount(int count); + GraphicsPipelineBuilder& AddColorBlendAttachment(VkPipelineColorBlendAttachmentState state); GraphicsPipelineBuilder& AddVertexShader(VulkanShader *shader); GraphicsPipelineBuilder& AddFragmentShader(VulkanShader *shader); @@ -398,7 +410,6 @@ class GraphicsPipelineBuilder VkPipelineViewportStateCreateInfo viewportState = { }; VkPipelineRasterizationStateCreateInfo rasterizer = { }; VkPipelineMultisampleStateCreateInfo multisampling = { }; - VkPipelineColorBlendAttachmentState colorBlendAttachment = { }; VkPipelineColorBlendStateCreateInfo colorBlending = { }; VkPipelineDepthStencilStateCreateInfo depthStencil = { }; VkPipelineDynamicStateCreateInfo dynamicState = {}; @@ -492,8 +503,8 @@ class PipelineBarrier PipelineBarrier& AddMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); PipelineBarrier& AddBuffer(VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); PipelineBarrier& AddBuffer(VulkanBuffer *buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - PipelineBarrier& AddImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); - PipelineBarrier& AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); + PipelineBarrier& AddImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1, int baseArrayLayer = 0, int layerCount = 1); + PipelineBarrier& AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1, int baseArrayLayer = 0, int layerCount = 1); PipelineBarrier& AddQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); PipelineBarrier& AddQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); @@ -546,3 +557,24 @@ class WriteDescriptors std::vector writes; std::vector> writeExtras; }; + +class BufferTransfer +{ +public: + BufferTransfer& AddBuffer(VulkanBuffer* buffer, size_t offset, const void* data, size_t size); + BufferTransfer& AddBuffer(VulkanBuffer* buffer, const void* data, size_t size); + BufferTransfer& AddBuffer(VulkanBuffer* buffer, const void* data0, size_t size0, const void* data1, size_t size1); + std::unique_ptr Execute(VulkanDevice* device, VulkanCommandBuffer* cmdbuffer); + +private: + struct BufferCopy + { + VulkanBuffer* buffer; + size_t offset; + const void* data0; + size_t size0; + const void* data1; + size_t size1; + }; + std::vector bufferCopies; +}; diff --git a/libraries/ZVulkan/include/zvulkan/vulkandevice.h b/libraries/ZVulkan/include/zvulkan/vulkandevice.h index c7d0822d63..87aa2cbe49 100644 --- a/libraries/ZVulkan/include/zvulkan/vulkandevice.h +++ b/libraries/ZVulkan/include/zvulkan/vulkandevice.h @@ -44,8 +44,6 @@ class VulkanDevice void SetObjectName(const char* name, uint64_t handle, VkObjectType type); private: - bool DebugLayerActive = false; - void CreateDevice(); void CreateAllocator(); void ReleaseResources(); diff --git a/libraries/ZVulkan/include/zvulkan/vulkaninstance.h b/libraries/ZVulkan/include/zvulkan/vulkaninstance.h index 8522a8a0f1..1074ce4203 100644 --- a/libraries/ZVulkan/include/zvulkan/vulkaninstance.h +++ b/libraries/ZVulkan/include/zvulkan/vulkaninstance.h @@ -38,6 +38,7 @@ class VulkanDeviceProperties VkPhysicalDeviceMemoryProperties Memory = {}; VkPhysicalDeviceAccelerationStructurePropertiesKHR AccelerationStructure = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR }; VkPhysicalDeviceDescriptorIndexingProperties DescriptorIndexing = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT }; + VkPhysicalDeviceLayeredDriverPropertiesMSFT LayeredDriver = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT }; }; class VulkanPhysicalDevice diff --git a/libraries/ZVulkan/include/zvulkan/vulkanobjects.h b/libraries/ZVulkan/include/zvulkan/vulkanobjects.h index e3bf4505cb..c7842f6701 100644 --- a/libraries/ZVulkan/include/zvulkan/vulkanobjects.h +++ b/libraries/ZVulkan/include/zvulkan/vulkanobjects.h @@ -569,7 +569,7 @@ inline RenderPassBegin& RenderPassBegin::Framebuffer(VulkanFramebuffer* framebuf inline RenderPassBegin& RenderPassBegin::AddClearColor(float r, float g, float b, float a) { VkClearValue clearValue = { }; - clearValue.color = { { r, g, b, a } }; + clearValue.color = { r, g, b, a }; clearValues.push_back(clearValue); renderPassInfo.clearValueCount = (uint32_t)clearValues.size(); diff --git a/libraries/ZVulkan/src/volk/volk.c b/libraries/ZVulkan/src/volk/volk.c index 7a6969b10d..67f85c7f8c 100644 --- a/libraries/ZVulkan/src/volk/volk.c +++ b/libraries/ZVulkan/src/volk/volk.c @@ -5,7 +5,11 @@ #define VK_USE_PLATFORM_MACOS_MVK #define VK_USE_PLATFORM_METAL_EXT #else +#if defined(VULKAN_USE_XLIB) #define VK_USE_PLATFORM_XLIB_KHR +#elif defined(VULKAN_USE_WAYLAND) +#define VK_USE_PLATFORM_WAYLAND_KHR +#endif #endif /* This file is part of volk library; see volk.h for version/license details */ @@ -16,7 +20,9 @@ typedef const char* LPCSTR; typedef struct HINSTANCE__* HINSTANCE; typedef HINSTANCE HMODULE; - #ifdef _WIN64 + #if defined(_MINWINDEF_) + /* minwindef.h defines FARPROC, and attempting to redefine it may conflict with -Wstrict-prototypes */ + #elif defined(_WIN64) typedef __int64 (__stdcall* FARPROC)(void); #else typedef int (__stdcall* FARPROC)(void); @@ -32,8 +38,10 @@ extern "C" { #ifdef _WIN32 __declspec(dllimport) HMODULE __stdcall LoadLibraryA(LPCSTR); __declspec(dllimport) FARPROC __stdcall GetProcAddress(HMODULE, LPCSTR); +__declspec(dllimport) int __stdcall FreeLibrary(HMODULE); #endif +static void* loadedModule = NULL; static VkInstance loadedInstance = VK_NULL_HANDLE; static VkDevice loadedDevice = VK_NULL_HANDLE; @@ -52,6 +60,13 @@ static PFN_vkVoidFunction vkGetDeviceProcAddrStub(void* context, const char* nam return vkGetDeviceProcAddr((VkDevice)context, name); } +static PFN_vkVoidFunction nullProcAddrStub(void* context, const char* name) +{ + (void)context; + (void)name; + return NULL; +} + VkResult volkInitialize(void) { #if defined(_WIN32) @@ -81,6 +96,7 @@ VkResult volkInitialize(void) vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(module, "vkGetInstanceProcAddr"); #endif + loadedModule = module; volkGenLoadLoader(NULL, vkGetInstanceProcAddrStub); return VK_SUCCESS; @@ -90,9 +106,31 @@ void volkInitializeCustom(PFN_vkGetInstanceProcAddr handler) { vkGetInstanceProcAddr = handler; + loadedModule = NULL; volkGenLoadLoader(NULL, vkGetInstanceProcAddrStub); } +void volkFinalize(void) +{ + if (loadedModule) + { +#if defined(_WIN32) + FreeLibrary((HMODULE)loadedModule); +#else + dlclose(loadedModule); +#endif + } + + vkGetInstanceProcAddr = NULL; + volkGenLoadLoader(NULL, nullProcAddrStub); + volkGenLoadInstance(NULL, nullProcAddrStub); + volkGenLoadDevice(NULL, nullProcAddrStub); + + loadedModule = NULL; + loadedInstance = VK_NULL_HANDLE; + loadedDevice = VK_NULL_HANDLE; +} + uint32_t volkGetInstanceVersion(void) { #if defined(VK_VERSION_1_1) @@ -116,11 +154,11 @@ void volkLoadInstance(VkInstance instance) void volkLoadInstanceOnly(VkInstance instance) { - loadedInstance = instance; - volkGenLoadInstance(instance, vkGetInstanceProcAddrStub); + loadedInstance = instance; + volkGenLoadInstance(instance, vkGetInstanceProcAddrStub); } -VkInstance volkGetLoadedInstance() +VkInstance volkGetLoadedInstance(void) { return loadedInstance; } @@ -131,7 +169,7 @@ void volkLoadDevice(VkDevice device) volkGenLoadDevice(device, vkGetDeviceProcAddrStub); } -VkDevice volkGetLoadedDevice() +VkDevice volkGetLoadedDevice(void) { return loadedDevice; } @@ -186,6 +224,9 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, vkGetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2)load(context, "vkGetPhysicalDeviceQueueFamilyProperties2"); vkGetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)load(context, "vkGetPhysicalDeviceSparseImageFormatProperties2"); #endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_3) + vkGetPhysicalDeviceToolProperties = (PFN_vkGetPhysicalDeviceToolProperties)load(context, "vkGetPhysicalDeviceToolProperties"); +#endif /* defined(VK_VERSION_1_3) */ #if defined(VK_EXT_acquire_drm_display) vkAcquireDrmDisplayEXT = (PFN_vkAcquireDrmDisplayEXT)load(context, "vkAcquireDrmDisplayEXT"); vkGetDrmDisplayEXT = (PFN_vkGetDrmDisplayEXT)load(context, "vkGetDrmDisplayEXT"); @@ -249,6 +290,9 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, #if defined(VK_KHR_android_surface) vkCreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)load(context, "vkCreateAndroidSurfaceKHR"); #endif /* defined(VK_KHR_android_surface) */ +#if defined(VK_KHR_cooperative_matrix) + vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR)load(context, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR"); +#endif /* defined(VK_KHR_cooperative_matrix) */ #if defined(VK_KHR_device_group_creation) vkEnumeratePhysicalDeviceGroupsKHR = (PFN_vkEnumeratePhysicalDeviceGroupsKHR)load(context, "vkEnumeratePhysicalDeviceGroupsKHR"); #endif /* defined(VK_KHR_device_group_creation) */ @@ -303,6 +347,9 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)load(context, "vkGetPhysicalDeviceSurfacePresentModesKHR"); vkGetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)load(context, "vkGetPhysicalDeviceSurfaceSupportKHR"); #endif /* defined(VK_KHR_surface) */ +#if defined(VK_KHR_video_encode_queue) + vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR = (PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR)load(context, "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR"); +#endif /* defined(VK_KHR_video_encode_queue) */ #if defined(VK_KHR_video_queue) vkGetPhysicalDeviceVideoCapabilitiesKHR = (PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)load(context, "vkGetPhysicalDeviceVideoCapabilitiesKHR"); vkGetPhysicalDeviceVideoFormatPropertiesKHR = (PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)load(context, "vkGetPhysicalDeviceVideoFormatPropertiesKHR"); @@ -345,6 +392,9 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, #if defined(VK_NV_external_memory_capabilities) vkGetPhysicalDeviceExternalImageFormatPropertiesNV = (PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)load(context, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV"); #endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_optical_flow) + vkGetPhysicalDeviceOpticalFlowImageFormatsNV = (PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV)load(context, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV"); +#endif /* defined(VK_NV_optical_flow) */ #if defined(VK_QNX_screen_surface) vkCreateScreenSurfaceQNX = (PFN_vkCreateScreenSurfaceQNX)load(context, "vkCreateScreenSurfaceQNX"); vkGetPhysicalDeviceScreenPresentationSupportQNX = (PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX)load(context, "vkGetPhysicalDeviceScreenPresentationSupportQNX"); @@ -513,6 +563,53 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkSignalSemaphore = (PFN_vkSignalSemaphore)load(context, "vkSignalSemaphore"); vkWaitSemaphores = (PFN_vkWaitSemaphores)load(context, "vkWaitSemaphores"); #endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) + vkCmdBeginRendering = (PFN_vkCmdBeginRendering)load(context, "vkCmdBeginRendering"); + vkCmdBindVertexBuffers2 = (PFN_vkCmdBindVertexBuffers2)load(context, "vkCmdBindVertexBuffers2"); + vkCmdBlitImage2 = (PFN_vkCmdBlitImage2)load(context, "vkCmdBlitImage2"); + vkCmdCopyBuffer2 = (PFN_vkCmdCopyBuffer2)load(context, "vkCmdCopyBuffer2"); + vkCmdCopyBufferToImage2 = (PFN_vkCmdCopyBufferToImage2)load(context, "vkCmdCopyBufferToImage2"); + vkCmdCopyImage2 = (PFN_vkCmdCopyImage2)load(context, "vkCmdCopyImage2"); + vkCmdCopyImageToBuffer2 = (PFN_vkCmdCopyImageToBuffer2)load(context, "vkCmdCopyImageToBuffer2"); + vkCmdEndRendering = (PFN_vkCmdEndRendering)load(context, "vkCmdEndRendering"); + vkCmdPipelineBarrier2 = (PFN_vkCmdPipelineBarrier2)load(context, "vkCmdPipelineBarrier2"); + vkCmdResetEvent2 = (PFN_vkCmdResetEvent2)load(context, "vkCmdResetEvent2"); + vkCmdResolveImage2 = (PFN_vkCmdResolveImage2)load(context, "vkCmdResolveImage2"); + vkCmdSetCullMode = (PFN_vkCmdSetCullMode)load(context, "vkCmdSetCullMode"); + vkCmdSetDepthBiasEnable = (PFN_vkCmdSetDepthBiasEnable)load(context, "vkCmdSetDepthBiasEnable"); + vkCmdSetDepthBoundsTestEnable = (PFN_vkCmdSetDepthBoundsTestEnable)load(context, "vkCmdSetDepthBoundsTestEnable"); + vkCmdSetDepthCompareOp = (PFN_vkCmdSetDepthCompareOp)load(context, "vkCmdSetDepthCompareOp"); + vkCmdSetDepthTestEnable = (PFN_vkCmdSetDepthTestEnable)load(context, "vkCmdSetDepthTestEnable"); + vkCmdSetDepthWriteEnable = (PFN_vkCmdSetDepthWriteEnable)load(context, "vkCmdSetDepthWriteEnable"); + vkCmdSetEvent2 = (PFN_vkCmdSetEvent2)load(context, "vkCmdSetEvent2"); + vkCmdSetFrontFace = (PFN_vkCmdSetFrontFace)load(context, "vkCmdSetFrontFace"); + vkCmdSetPrimitiveRestartEnable = (PFN_vkCmdSetPrimitiveRestartEnable)load(context, "vkCmdSetPrimitiveRestartEnable"); + vkCmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopology)load(context, "vkCmdSetPrimitiveTopology"); + vkCmdSetRasterizerDiscardEnable = (PFN_vkCmdSetRasterizerDiscardEnable)load(context, "vkCmdSetRasterizerDiscardEnable"); + vkCmdSetScissorWithCount = (PFN_vkCmdSetScissorWithCount)load(context, "vkCmdSetScissorWithCount"); + vkCmdSetStencilOp = (PFN_vkCmdSetStencilOp)load(context, "vkCmdSetStencilOp"); + vkCmdSetStencilTestEnable = (PFN_vkCmdSetStencilTestEnable)load(context, "vkCmdSetStencilTestEnable"); + vkCmdSetViewportWithCount = (PFN_vkCmdSetViewportWithCount)load(context, "vkCmdSetViewportWithCount"); + vkCmdWaitEvents2 = (PFN_vkCmdWaitEvents2)load(context, "vkCmdWaitEvents2"); + vkCmdWriteTimestamp2 = (PFN_vkCmdWriteTimestamp2)load(context, "vkCmdWriteTimestamp2"); + vkCreatePrivateDataSlot = (PFN_vkCreatePrivateDataSlot)load(context, "vkCreatePrivateDataSlot"); + vkDestroyPrivateDataSlot = (PFN_vkDestroyPrivateDataSlot)load(context, "vkDestroyPrivateDataSlot"); + vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)load(context, "vkGetDeviceBufferMemoryRequirements"); + vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)load(context, "vkGetDeviceImageMemoryRequirements"); + vkGetDeviceImageSparseMemoryRequirements = (PFN_vkGetDeviceImageSparseMemoryRequirements)load(context, "vkGetDeviceImageSparseMemoryRequirements"); + vkGetPrivateData = (PFN_vkGetPrivateData)load(context, "vkGetPrivateData"); + vkQueueSubmit2 = (PFN_vkQueueSubmit2)load(context, "vkQueueSubmit2"); + vkSetPrivateData = (PFN_vkSetPrivateData)load(context, "vkSetPrivateData"); +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_AMDX_shader_enqueue) + vkCmdDispatchGraphAMDX = (PFN_vkCmdDispatchGraphAMDX)load(context, "vkCmdDispatchGraphAMDX"); + vkCmdDispatchGraphIndirectAMDX = (PFN_vkCmdDispatchGraphIndirectAMDX)load(context, "vkCmdDispatchGraphIndirectAMDX"); + vkCmdDispatchGraphIndirectCountAMDX = (PFN_vkCmdDispatchGraphIndirectCountAMDX)load(context, "vkCmdDispatchGraphIndirectCountAMDX"); + vkCmdInitializeGraphScratchMemoryAMDX = (PFN_vkCmdInitializeGraphScratchMemoryAMDX)load(context, "vkCmdInitializeGraphScratchMemoryAMDX"); + vkCreateExecutionGraphPipelinesAMDX = (PFN_vkCreateExecutionGraphPipelinesAMDX)load(context, "vkCreateExecutionGraphPipelinesAMDX"); + vkGetExecutionGraphPipelineNodeIndexAMDX = (PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)load(context, "vkGetExecutionGraphPipelineNodeIndexAMDX"); + vkGetExecutionGraphPipelineScratchSizeAMDX = (PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)load(context, "vkGetExecutionGraphPipelineScratchSizeAMDX"); +#endif /* defined(VK_AMDX_shader_enqueue) */ #if defined(VK_AMD_buffer_marker) vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD"); #endif /* defined(VK_AMD_buffer_marker) */ @@ -530,6 +627,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)load(context, "vkGetAndroidHardwareBufferPropertiesANDROID"); vkGetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID)load(context, "vkGetMemoryAndroidHardwareBufferANDROID"); #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) + vkCmdSetAttachmentFeedbackLoopEnableEXT = (PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)load(context, "vkCmdSetAttachmentFeedbackLoopEnableEXT"); +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ #if defined(VK_EXT_buffer_device_address) vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)load(context, "vkGetBufferDeviceAddressEXT"); #endif /* defined(VK_EXT_buffer_device_address) */ @@ -550,36 +650,40 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkDebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)load(context, "vkDebugMarkerSetObjectNameEXT"); vkDebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)load(context, "vkDebugMarkerSetObjectTagEXT"); #endif /* defined(VK_EXT_debug_marker) */ +#if defined(VK_EXT_depth_bias_control) + vkCmdSetDepthBias2EXT = (PFN_vkCmdSetDepthBias2EXT)load(context, "vkCmdSetDepthBias2EXT"); +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) + vkCmdBindDescriptorBufferEmbeddedSamplersEXT = (PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT)load(context, "vkCmdBindDescriptorBufferEmbeddedSamplersEXT"); + vkCmdBindDescriptorBuffersEXT = (PFN_vkCmdBindDescriptorBuffersEXT)load(context, "vkCmdBindDescriptorBuffersEXT"); + vkCmdSetDescriptorBufferOffsetsEXT = (PFN_vkCmdSetDescriptorBufferOffsetsEXT)load(context, "vkCmdSetDescriptorBufferOffsetsEXT"); + vkGetBufferOpaqueCaptureDescriptorDataEXT = (PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT)load(context, "vkGetBufferOpaqueCaptureDescriptorDataEXT"); + vkGetDescriptorEXT = (PFN_vkGetDescriptorEXT)load(context, "vkGetDescriptorEXT"); + vkGetDescriptorSetLayoutBindingOffsetEXT = (PFN_vkGetDescriptorSetLayoutBindingOffsetEXT)load(context, "vkGetDescriptorSetLayoutBindingOffsetEXT"); + vkGetDescriptorSetLayoutSizeEXT = (PFN_vkGetDescriptorSetLayoutSizeEXT)load(context, "vkGetDescriptorSetLayoutSizeEXT"); + vkGetImageOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageOpaqueCaptureDescriptorDataEXT"); + vkGetImageViewOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageViewOpaqueCaptureDescriptorDataEXT"); + vkGetSamplerOpaqueCaptureDescriptorDataEXT = (PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)load(context, "vkGetSamplerOpaqueCaptureDescriptorDataEXT"); +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) + vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT = (PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)load(context, "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT"); +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_device_fault) + vkGetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)load(context, "vkGetDeviceFaultInfoEXT"); +#endif /* defined(VK_EXT_device_fault) */ #if defined(VK_EXT_discard_rectangles) vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + vkCmdSetDiscardRectangleEnableEXT = (PFN_vkCmdSetDiscardRectangleEnableEXT)load(context, "vkCmdSetDiscardRectangleEnableEXT"); + vkCmdSetDiscardRectangleModeEXT = (PFN_vkCmdSetDiscardRectangleModeEXT)load(context, "vkCmdSetDiscardRectangleModeEXT"); +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) vkDisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT)load(context, "vkDisplayPowerControlEXT"); vkGetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT)load(context, "vkGetSwapchainCounterEXT"); vkRegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT)load(context, "vkRegisterDeviceEventEXT"); vkRegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT)load(context, "vkRegisterDisplayEventEXT"); #endif /* defined(VK_EXT_display_control) */ -#if defined(VK_EXT_extended_dynamic_state) - vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); - vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); - vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); - vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); - vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); - vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); - vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); - vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); - vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); - vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); - vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); - vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) - vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); - vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); - vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); - vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); - vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); -#endif /* defined(VK_EXT_extended_dynamic_state2) */ #if defined(VK_EXT_external_memory_host) vkGetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)load(context, "vkGetMemoryHostPointerPropertiesEXT"); #endif /* defined(VK_EXT_external_memory_host) */ @@ -590,6 +694,12 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_EXT_hdr_metadata) vkSetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)load(context, "vkSetHdrMetadataEXT"); #endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_image_copy) + vkCopyImageToImageEXT = (PFN_vkCopyImageToImageEXT)load(context, "vkCopyImageToImageEXT"); + vkCopyImageToMemoryEXT = (PFN_vkCopyImageToMemoryEXT)load(context, "vkCopyImageToMemoryEXT"); + vkCopyMemoryToImageEXT = (PFN_vkCopyMemoryToImageEXT)load(context, "vkCopyMemoryToImageEXT"); + vkTransitionImageLayoutEXT = (PFN_vkTransitionImageLayoutEXT)load(context, "vkTransitionImageLayoutEXT"); +#endif /* defined(VK_EXT_host_image_copy) */ #if defined(VK_EXT_host_query_reset) vkResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)load(context, "vkResetQueryPoolEXT"); #endif /* defined(VK_EXT_host_query_reset) */ @@ -599,10 +709,40 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_EXT_line_rasterization) vkCmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)load(context, "vkCmdSetLineStippleEXT"); #endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_mesh_shader) + vkCmdDrawMeshTasksEXT = (PFN_vkCmdDrawMeshTasksEXT)load(context, "vkCmdDrawMeshTasksEXT"); + vkCmdDrawMeshTasksIndirectCountEXT = (PFN_vkCmdDrawMeshTasksIndirectCountEXT)load(context, "vkCmdDrawMeshTasksIndirectCountEXT"); + vkCmdDrawMeshTasksIndirectEXT = (PFN_vkCmdDrawMeshTasksIndirectEXT)load(context, "vkCmdDrawMeshTasksIndirectEXT"); +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_metal_objects) + vkExportMetalObjectsEXT = (PFN_vkExportMetalObjectsEXT)load(context, "vkExportMetalObjectsEXT"); +#endif /* defined(VK_EXT_metal_objects) */ #if defined(VK_EXT_multi_draw) vkCmdDrawMultiEXT = (PFN_vkCmdDrawMultiEXT)load(context, "vkCmdDrawMultiEXT"); vkCmdDrawMultiIndexedEXT = (PFN_vkCmdDrawMultiIndexedEXT)load(context, "vkCmdDrawMultiIndexedEXT"); #endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) + vkBuildMicromapsEXT = (PFN_vkBuildMicromapsEXT)load(context, "vkBuildMicromapsEXT"); + vkCmdBuildMicromapsEXT = (PFN_vkCmdBuildMicromapsEXT)load(context, "vkCmdBuildMicromapsEXT"); + vkCmdCopyMemoryToMicromapEXT = (PFN_vkCmdCopyMemoryToMicromapEXT)load(context, "vkCmdCopyMemoryToMicromapEXT"); + vkCmdCopyMicromapEXT = (PFN_vkCmdCopyMicromapEXT)load(context, "vkCmdCopyMicromapEXT"); + vkCmdCopyMicromapToMemoryEXT = (PFN_vkCmdCopyMicromapToMemoryEXT)load(context, "vkCmdCopyMicromapToMemoryEXT"); + vkCmdWriteMicromapsPropertiesEXT = (PFN_vkCmdWriteMicromapsPropertiesEXT)load(context, "vkCmdWriteMicromapsPropertiesEXT"); + vkCopyMemoryToMicromapEXT = (PFN_vkCopyMemoryToMicromapEXT)load(context, "vkCopyMemoryToMicromapEXT"); + vkCopyMicromapEXT = (PFN_vkCopyMicromapEXT)load(context, "vkCopyMicromapEXT"); + vkCopyMicromapToMemoryEXT = (PFN_vkCopyMicromapToMemoryEXT)load(context, "vkCopyMicromapToMemoryEXT"); + vkCreateMicromapEXT = (PFN_vkCreateMicromapEXT)load(context, "vkCreateMicromapEXT"); + vkDestroyMicromapEXT = (PFN_vkDestroyMicromapEXT)load(context, "vkDestroyMicromapEXT"); + vkGetDeviceMicromapCompatibilityEXT = (PFN_vkGetDeviceMicromapCompatibilityEXT)load(context, "vkGetDeviceMicromapCompatibilityEXT"); + vkGetMicromapBuildSizesEXT = (PFN_vkGetMicromapBuildSizesEXT)load(context, "vkGetMicromapBuildSizesEXT"); + vkWriteMicromapsPropertiesEXT = (PFN_vkWriteMicromapsPropertiesEXT)load(context, "vkWriteMicromapsPropertiesEXT"); +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) + vkSetDeviceMemoryPriorityEXT = (PFN_vkSetDeviceMemoryPriorityEXT)load(context, "vkSetDeviceMemoryPriorityEXT"); +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) + vkGetPipelinePropertiesEXT = (PFN_vkGetPipelinePropertiesEXT)load(context, "vkGetPipelinePropertiesEXT"); +#endif /* defined(VK_EXT_pipeline_properties) */ #if defined(VK_EXT_private_data) vkCreatePrivateDataSlotEXT = (PFN_vkCreatePrivateDataSlotEXT)load(context, "vkCreatePrivateDataSlotEXT"); vkDestroyPrivateDataSlotEXT = (PFN_vkDestroyPrivateDataSlotEXT)load(context, "vkDestroyPrivateDataSlotEXT"); @@ -612,6 +752,19 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_EXT_sample_locations) vkCmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT)load(context, "vkCmdSetSampleLocationsEXT"); #endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) + vkGetShaderModuleCreateInfoIdentifierEXT = (PFN_vkGetShaderModuleCreateInfoIdentifierEXT)load(context, "vkGetShaderModuleCreateInfoIdentifierEXT"); + vkGetShaderModuleIdentifierEXT = (PFN_vkGetShaderModuleIdentifierEXT)load(context, "vkGetShaderModuleIdentifierEXT"); +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + vkCmdBindShadersEXT = (PFN_vkCmdBindShadersEXT)load(context, "vkCmdBindShadersEXT"); + vkCreateShadersEXT = (PFN_vkCreateShadersEXT)load(context, "vkCreateShadersEXT"); + vkDestroyShaderEXT = (PFN_vkDestroyShaderEXT)load(context, "vkDestroyShaderEXT"); + vkGetShaderBinaryDataEXT = (PFN_vkGetShaderBinaryDataEXT)load(context, "vkGetShaderBinaryDataEXT"); +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) + vkReleaseSwapchainImagesEXT = (PFN_vkReleaseSwapchainImagesEXT)load(context, "vkReleaseSwapchainImagesEXT"); +#endif /* defined(VK_EXT_swapchain_maintenance1) */ #if defined(VK_EXT_transform_feedback) vkCmdBeginQueryIndexedEXT = (PFN_vkCmdBeginQueryIndexedEXT)load(context, "vkCmdBeginQueryIndexedEXT"); vkCmdBeginTransformFeedbackEXT = (PFN_vkCmdBeginTransformFeedbackEXT)load(context, "vkCmdBeginTransformFeedbackEXT"); @@ -626,9 +779,13 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT)load(context, "vkGetValidationCacheDataEXT"); vkMergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT)load(context, "vkMergeValidationCachesEXT"); #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) - vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ +#if defined(VK_FUCHSIA_buffer_collection) + vkCreateBufferCollectionFUCHSIA = (PFN_vkCreateBufferCollectionFUCHSIA)load(context, "vkCreateBufferCollectionFUCHSIA"); + vkDestroyBufferCollectionFUCHSIA = (PFN_vkDestroyBufferCollectionFUCHSIA)load(context, "vkDestroyBufferCollectionFUCHSIA"); + vkGetBufferCollectionPropertiesFUCHSIA = (PFN_vkGetBufferCollectionPropertiesFUCHSIA)load(context, "vkGetBufferCollectionPropertiesFUCHSIA"); + vkSetBufferCollectionBufferConstraintsFUCHSIA = (PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)load(context, "vkSetBufferCollectionBufferConstraintsFUCHSIA"); + vkSetBufferCollectionImageConstraintsFUCHSIA = (PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)load(context, "vkSetBufferCollectionImageConstraintsFUCHSIA"); +#endif /* defined(VK_FUCHSIA_buffer_collection) */ #if defined(VK_FUCHSIA_external_memory) vkGetMemoryZirconHandleFUCHSIA = (PFN_vkGetMemoryZirconHandleFUCHSIA)load(context, "vkGetMemoryZirconHandleFUCHSIA"); vkGetMemoryZirconHandlePropertiesFUCHSIA = (PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)load(context, "vkGetMemoryZirconHandlePropertiesFUCHSIA"); @@ -641,6 +798,10 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)load(context, "vkGetPastPresentationTimingGOOGLE"); vkGetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)load(context, "vkGetRefreshCycleDurationGOOGLE"); #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + vkCmdDrawClusterHUAWEI = (PFN_vkCmdDrawClusterHUAWEI)load(context, "vkCmdDrawClusterHUAWEI"); + vkCmdDrawClusterIndirectHUAWEI = (PFN_vkCmdDrawClusterIndirectHUAWEI)load(context, "vkCmdDrawClusterIndirectHUAWEI"); +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -724,6 +885,10 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)load(context, "vkCmdDrawIndexedIndirectCountKHR"); vkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)load(context, "vkCmdDrawIndirectCountKHR"); #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)load(context, "vkCmdBeginRenderingKHR"); + vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)load(context, "vkCmdEndRenderingKHR"); +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_fd) vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)load(context, "vkGetFenceFdKHR"); vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)load(context, "vkImportFenceFdKHR"); @@ -762,6 +927,21 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_KHR_maintenance3) vkGetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR)load(context, "vkGetDescriptorSetLayoutSupportKHR"); #endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) + vkGetDeviceBufferMemoryRequirementsKHR = (PFN_vkGetDeviceBufferMemoryRequirementsKHR)load(context, "vkGetDeviceBufferMemoryRequirementsKHR"); + vkGetDeviceImageMemoryRequirementsKHR = (PFN_vkGetDeviceImageMemoryRequirementsKHR)load(context, "vkGetDeviceImageMemoryRequirementsKHR"); + vkGetDeviceImageSparseMemoryRequirementsKHR = (PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)load(context, "vkGetDeviceImageSparseMemoryRequirementsKHR"); +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) + vkCmdBindIndexBuffer2KHR = (PFN_vkCmdBindIndexBuffer2KHR)load(context, "vkCmdBindIndexBuffer2KHR"); + vkGetDeviceImageSubresourceLayoutKHR = (PFN_vkGetDeviceImageSubresourceLayoutKHR)load(context, "vkGetDeviceImageSubresourceLayoutKHR"); + vkGetImageSubresourceLayout2KHR = (PFN_vkGetImageSubresourceLayout2KHR)load(context, "vkGetImageSubresourceLayout2KHR"); + vkGetRenderingAreaGranularityKHR = (PFN_vkGetRenderingAreaGranularityKHR)load(context, "vkGetRenderingAreaGranularityKHR"); +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_map_memory2) + vkMapMemory2KHR = (PFN_vkMapMemory2KHR)load(context, "vkMapMemory2KHR"); + vkUnmapMemory2KHR = (PFN_vkUnmapMemory2KHR)load(context, "vkUnmapMemory2KHR"); +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); @@ -777,6 +957,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_KHR_push_descriptor) vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)load(context, "vkCmdPushDescriptorSetKHR"); #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) + vkCmdTraceRaysIndirect2KHR = (PFN_vkCmdTraceRaysIndirect2KHR)load(context, "vkCmdTraceRaysIndirect2KHR"); +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_ray_tracing_pipeline) vkCmdSetRayTracingPipelineStackSizeKHR = (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)load(context, "vkCmdSetRayTracingPipelineStackSizeKHR"); vkCmdTraceRaysIndirectKHR = (PFN_vkCmdTraceRaysIndirectKHR)load(context, "vkCmdTraceRaysIndirectKHR"); @@ -824,6 +1007,7 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #endif /* defined(VK_KHR_video_decode_queue) */ #if defined(VK_KHR_video_encode_queue) vkCmdEncodeVideoKHR = (PFN_vkCmdEncodeVideoKHR)load(context, "vkCmdEncodeVideoKHR"); + vkGetEncodedVideoSessionParametersKHR = (PFN_vkGetEncodedVideoSessionParametersKHR)load(context, "vkGetEncodedVideoSessionParametersKHR"); #endif /* defined(VK_KHR_video_encode_queue) */ #if defined(VK_KHR_video_queue) vkBindVideoSessionMemoryKHR = (PFN_vkBindVideoSessionMemoryKHR)load(context, "vkBindVideoSessionMemoryKHR"); @@ -851,6 +1035,18 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_NV_clip_space_w_scaling) vkCmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV)load(context, "vkCmdSetViewportWScalingNV"); #endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_copy_memory_indirect) + vkCmdCopyMemoryIndirectNV = (PFN_vkCmdCopyMemoryIndirectNV)load(context, "vkCmdCopyMemoryIndirectNV"); + vkCmdCopyMemoryToImageIndirectNV = (PFN_vkCmdCopyMemoryToImageIndirectNV)load(context, "vkCmdCopyMemoryToImageIndirectNV"); +#endif /* defined(VK_NV_copy_memory_indirect) */ +#if defined(VK_NV_cuda_kernel_launch) + vkCmdCudaLaunchKernelNV = (PFN_vkCmdCudaLaunchKernelNV)load(context, "vkCmdCudaLaunchKernelNV"); + vkCreateCudaFunctionNV = (PFN_vkCreateCudaFunctionNV)load(context, "vkCreateCudaFunctionNV"); + vkCreateCudaModuleNV = (PFN_vkCreateCudaModuleNV)load(context, "vkCreateCudaModuleNV"); + vkDestroyCudaFunctionNV = (PFN_vkDestroyCudaFunctionNV)load(context, "vkDestroyCudaFunctionNV"); + vkDestroyCudaModuleNV = (PFN_vkDestroyCudaModuleNV)load(context, "vkDestroyCudaModuleNV"); + vkGetCudaModuleCacheNV = (PFN_vkGetCudaModuleCacheNV)load(context, "vkGetCudaModuleCacheNV"); +#endif /* defined(VK_NV_cuda_kernel_launch) */ #if defined(VK_NV_device_diagnostic_checkpoints) vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)load(context, "vkCmdSetCheckpointNV"); vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)load(context, "vkGetQueueCheckpointDataNV"); @@ -863,6 +1059,11 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkDestroyIndirectCommandsLayoutNV = (PFN_vkDestroyIndirectCommandsLayoutNV)load(context, "vkDestroyIndirectCommandsLayoutNV"); vkGetGeneratedCommandsMemoryRequirementsNV = (PFN_vkGetGeneratedCommandsMemoryRequirementsNV)load(context, "vkGetGeneratedCommandsMemoryRequirementsNV"); #endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) + vkCmdUpdatePipelineIndirectBufferNV = (PFN_vkCmdUpdatePipelineIndirectBufferNV)load(context, "vkCmdUpdatePipelineIndirectBufferNV"); + vkGetPipelineIndirectDeviceAddressNV = (PFN_vkGetPipelineIndirectDeviceAddressNV)load(context, "vkGetPipelineIndirectDeviceAddressNV"); + vkGetPipelineIndirectMemoryRequirementsNV = (PFN_vkGetPipelineIndirectMemoryRequirementsNV)load(context, "vkGetPipelineIndirectMemoryRequirementsNV"); +#endif /* defined(VK_NV_device_generated_commands_compute) */ #if defined(VK_NV_external_memory_rdma) vkGetMemoryRemoteAddressNV = (PFN_vkGetMemoryRemoteAddressNV)load(context, "vkGetMemoryRemoteAddressNV"); #endif /* defined(VK_NV_external_memory_rdma) */ @@ -872,11 +1073,28 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_NV_fragment_shading_rate_enums) vkCmdSetFragmentShadingRateEnumNV = (PFN_vkCmdSetFragmentShadingRateEnumNV)load(context, "vkCmdSetFragmentShadingRateEnumNV"); #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + vkGetLatencyTimingsNV = (PFN_vkGetLatencyTimingsNV)load(context, "vkGetLatencyTimingsNV"); + vkLatencySleepNV = (PFN_vkLatencySleepNV)load(context, "vkLatencySleepNV"); + vkQueueNotifyOutOfBandNV = (PFN_vkQueueNotifyOutOfBandNV)load(context, "vkQueueNotifyOutOfBandNV"); + vkSetLatencyMarkerNV = (PFN_vkSetLatencyMarkerNV)load(context, "vkSetLatencyMarkerNV"); + vkSetLatencySleepModeNV = (PFN_vkSetLatencySleepModeNV)load(context, "vkSetLatencySleepModeNV"); +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) + vkCmdDecompressMemoryIndirectCountNV = (PFN_vkCmdDecompressMemoryIndirectCountNV)load(context, "vkCmdDecompressMemoryIndirectCountNV"); + vkCmdDecompressMemoryNV = (PFN_vkCmdDecompressMemoryNV)load(context, "vkCmdDecompressMemoryNV"); +#endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); vkCmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)load(context, "vkCmdDrawMeshTasksIndirectNV"); vkCmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)load(context, "vkCmdDrawMeshTasksNV"); #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_optical_flow) + vkBindOpticalFlowSessionImageNV = (PFN_vkBindOpticalFlowSessionImageNV)load(context, "vkBindOpticalFlowSessionImageNV"); + vkCmdOpticalFlowExecuteNV = (PFN_vkCmdOpticalFlowExecuteNV)load(context, "vkCmdOpticalFlowExecuteNV"); + vkCreateOpticalFlowSessionNV = (PFN_vkCreateOpticalFlowSessionNV)load(context, "vkCreateOpticalFlowSessionNV"); + vkDestroyOpticalFlowSessionNV = (PFN_vkDestroyOpticalFlowSessionNV)load(context, "vkDestroyOpticalFlowSessionNV"); +#endif /* defined(VK_NV_optical_flow) */ #if defined(VK_NV_ray_tracing) vkBindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV)load(context, "vkBindAccelerationStructureMemoryNV"); vkCmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV)load(context, "vkCmdBuildAccelerationStructureNV"); @@ -891,6 +1109,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV)load(context, "vkGetAccelerationStructureMemoryRequirementsNV"); vkGetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV)load(context, "vkGetRayTracingShaderGroupHandlesNV"); #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + vkCmdSetExclusiveScissorEnableNV = (PFN_vkCmdSetExclusiveScissorEnableNV)load(context, "vkCmdSetExclusiveScissorEnableNV"); +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) vkCmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV)load(context, "vkCmdSetExclusiveScissorNV"); #endif /* defined(VK_NV_scissor_exclusive) */ @@ -899,9 +1120,94 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV)load(context, "vkCmdSetCoarseSampleOrderNV"); vkCmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV)load(context, "vkCmdSetViewportShadingRatePaletteNV"); #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_properties) + vkGetDynamicRenderingTilePropertiesQCOM = (PFN_vkGetDynamicRenderingTilePropertiesQCOM)load(context, "vkGetDynamicRenderingTilePropertiesQCOM"); + vkGetFramebufferTilePropertiesQCOM = (PFN_vkGetFramebufferTilePropertiesQCOM)load(context, "vkGetFramebufferTilePropertiesQCOM"); +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QNX_external_memory_screen_buffer) + vkGetScreenBufferPropertiesQNX = (PFN_vkGetScreenBufferPropertiesQNX)load(context, "vkGetScreenBufferPropertiesQNX"); +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) + vkGetDescriptorSetHostMappingVALVE = (PFN_vkGetDescriptorSetHostMappingVALVE)load(context, "vkGetDescriptorSetHostMappingVALVE"); + vkGetDescriptorSetLayoutHostMappingInfoVALVE = (PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)load(context, "vkGetDescriptorSetLayoutHostMappingInfoVALVE"); +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); + vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); + vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); + vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); + vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); + vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); + vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); + vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); + vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); + vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); + vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); + vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); + vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); + vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); + vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); + vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + vkCmdSetAlphaToCoverageEnableEXT = (PFN_vkCmdSetAlphaToCoverageEnableEXT)load(context, "vkCmdSetAlphaToCoverageEnableEXT"); + vkCmdSetAlphaToOneEnableEXT = (PFN_vkCmdSetAlphaToOneEnableEXT)load(context, "vkCmdSetAlphaToOneEnableEXT"); + vkCmdSetColorBlendAdvancedEXT = (PFN_vkCmdSetColorBlendAdvancedEXT)load(context, "vkCmdSetColorBlendAdvancedEXT"); + vkCmdSetColorBlendEnableEXT = (PFN_vkCmdSetColorBlendEnableEXT)load(context, "vkCmdSetColorBlendEnableEXT"); + vkCmdSetColorBlendEquationEXT = (PFN_vkCmdSetColorBlendEquationEXT)load(context, "vkCmdSetColorBlendEquationEXT"); + vkCmdSetColorWriteMaskEXT = (PFN_vkCmdSetColorWriteMaskEXT)load(context, "vkCmdSetColorWriteMaskEXT"); + vkCmdSetConservativeRasterizationModeEXT = (PFN_vkCmdSetConservativeRasterizationModeEXT)load(context, "vkCmdSetConservativeRasterizationModeEXT"); + vkCmdSetDepthClampEnableEXT = (PFN_vkCmdSetDepthClampEnableEXT)load(context, "vkCmdSetDepthClampEnableEXT"); + vkCmdSetDepthClipEnableEXT = (PFN_vkCmdSetDepthClipEnableEXT)load(context, "vkCmdSetDepthClipEnableEXT"); + vkCmdSetDepthClipNegativeOneToOneEXT = (PFN_vkCmdSetDepthClipNegativeOneToOneEXT)load(context, "vkCmdSetDepthClipNegativeOneToOneEXT"); + vkCmdSetExtraPrimitiveOverestimationSizeEXT = (PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)load(context, "vkCmdSetExtraPrimitiveOverestimationSizeEXT"); + vkCmdSetLineRasterizationModeEXT = (PFN_vkCmdSetLineRasterizationModeEXT)load(context, "vkCmdSetLineRasterizationModeEXT"); + vkCmdSetLineStippleEnableEXT = (PFN_vkCmdSetLineStippleEnableEXT)load(context, "vkCmdSetLineStippleEnableEXT"); + vkCmdSetLogicOpEnableEXT = (PFN_vkCmdSetLogicOpEnableEXT)load(context, "vkCmdSetLogicOpEnableEXT"); + vkCmdSetPolygonModeEXT = (PFN_vkCmdSetPolygonModeEXT)load(context, "vkCmdSetPolygonModeEXT"); + vkCmdSetProvokingVertexModeEXT = (PFN_vkCmdSetProvokingVertexModeEXT)load(context, "vkCmdSetProvokingVertexModeEXT"); + vkCmdSetRasterizationSamplesEXT = (PFN_vkCmdSetRasterizationSamplesEXT)load(context, "vkCmdSetRasterizationSamplesEXT"); + vkCmdSetRasterizationStreamEXT = (PFN_vkCmdSetRasterizationStreamEXT)load(context, "vkCmdSetRasterizationStreamEXT"); + vkCmdSetSampleLocationsEnableEXT = (PFN_vkCmdSetSampleLocationsEnableEXT)load(context, "vkCmdSetSampleLocationsEnableEXT"); + vkCmdSetSampleMaskEXT = (PFN_vkCmdSetSampleMaskEXT)load(context, "vkCmdSetSampleMaskEXT"); + vkCmdSetTessellationDomainOriginEXT = (PFN_vkCmdSetTessellationDomainOriginEXT)load(context, "vkCmdSetTessellationDomainOriginEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) + vkCmdSetViewportWScalingEnableNV = (PFN_vkCmdSetViewportWScalingEnableNV)load(context, "vkCmdSetViewportWScalingEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) + vkCmdSetViewportSwizzleNV = (PFN_vkCmdSetViewportSwizzleNV)load(context, "vkCmdSetViewportSwizzleNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) + vkCmdSetCoverageToColorEnableNV = (PFN_vkCmdSetCoverageToColorEnableNV)load(context, "vkCmdSetCoverageToColorEnableNV"); + vkCmdSetCoverageToColorLocationNV = (PFN_vkCmdSetCoverageToColorLocationNV)load(context, "vkCmdSetCoverageToColorLocationNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) + vkCmdSetCoverageModulationModeNV = (PFN_vkCmdSetCoverageModulationModeNV)load(context, "vkCmdSetCoverageModulationModeNV"); + vkCmdSetCoverageModulationTableEnableNV = (PFN_vkCmdSetCoverageModulationTableEnableNV)load(context, "vkCmdSetCoverageModulationTableEnableNV"); + vkCmdSetCoverageModulationTableNV = (PFN_vkCmdSetCoverageModulationTableNV)load(context, "vkCmdSetCoverageModulationTableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) + vkCmdSetShadingRateImageEnableNV = (PFN_vkCmdSetShadingRateImageEnableNV)load(context, "vkCmdSetShadingRateImageEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) + vkCmdSetRepresentativeFragmentTestEnableNV = (PFN_vkCmdSetRepresentativeFragmentTestEnableNV)load(context, "vkCmdSetRepresentativeFragmentTestEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) + vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) + vkGetImageSubresourceLayout2EXT = (PFN_vkGetImageSubresourceLayout2EXT)load(context, "vkGetImageSubresourceLayout2EXT"); +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) vkCmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)load(context, "vkCmdPushDescriptorSetWithTemplateKHR"); #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ @@ -1073,6 +1379,53 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkSignalSemaphore = (PFN_vkSignalSemaphore)load(context, "vkSignalSemaphore"); table->vkWaitSemaphores = (PFN_vkWaitSemaphores)load(context, "vkWaitSemaphores"); #endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) + table->vkCmdBeginRendering = (PFN_vkCmdBeginRendering)load(context, "vkCmdBeginRendering"); + table->vkCmdBindVertexBuffers2 = (PFN_vkCmdBindVertexBuffers2)load(context, "vkCmdBindVertexBuffers2"); + table->vkCmdBlitImage2 = (PFN_vkCmdBlitImage2)load(context, "vkCmdBlitImage2"); + table->vkCmdCopyBuffer2 = (PFN_vkCmdCopyBuffer2)load(context, "vkCmdCopyBuffer2"); + table->vkCmdCopyBufferToImage2 = (PFN_vkCmdCopyBufferToImage2)load(context, "vkCmdCopyBufferToImage2"); + table->vkCmdCopyImage2 = (PFN_vkCmdCopyImage2)load(context, "vkCmdCopyImage2"); + table->vkCmdCopyImageToBuffer2 = (PFN_vkCmdCopyImageToBuffer2)load(context, "vkCmdCopyImageToBuffer2"); + table->vkCmdEndRendering = (PFN_vkCmdEndRendering)load(context, "vkCmdEndRendering"); + table->vkCmdPipelineBarrier2 = (PFN_vkCmdPipelineBarrier2)load(context, "vkCmdPipelineBarrier2"); + table->vkCmdResetEvent2 = (PFN_vkCmdResetEvent2)load(context, "vkCmdResetEvent2"); + table->vkCmdResolveImage2 = (PFN_vkCmdResolveImage2)load(context, "vkCmdResolveImage2"); + table->vkCmdSetCullMode = (PFN_vkCmdSetCullMode)load(context, "vkCmdSetCullMode"); + table->vkCmdSetDepthBiasEnable = (PFN_vkCmdSetDepthBiasEnable)load(context, "vkCmdSetDepthBiasEnable"); + table->vkCmdSetDepthBoundsTestEnable = (PFN_vkCmdSetDepthBoundsTestEnable)load(context, "vkCmdSetDepthBoundsTestEnable"); + table->vkCmdSetDepthCompareOp = (PFN_vkCmdSetDepthCompareOp)load(context, "vkCmdSetDepthCompareOp"); + table->vkCmdSetDepthTestEnable = (PFN_vkCmdSetDepthTestEnable)load(context, "vkCmdSetDepthTestEnable"); + table->vkCmdSetDepthWriteEnable = (PFN_vkCmdSetDepthWriteEnable)load(context, "vkCmdSetDepthWriteEnable"); + table->vkCmdSetEvent2 = (PFN_vkCmdSetEvent2)load(context, "vkCmdSetEvent2"); + table->vkCmdSetFrontFace = (PFN_vkCmdSetFrontFace)load(context, "vkCmdSetFrontFace"); + table->vkCmdSetPrimitiveRestartEnable = (PFN_vkCmdSetPrimitiveRestartEnable)load(context, "vkCmdSetPrimitiveRestartEnable"); + table->vkCmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopology)load(context, "vkCmdSetPrimitiveTopology"); + table->vkCmdSetRasterizerDiscardEnable = (PFN_vkCmdSetRasterizerDiscardEnable)load(context, "vkCmdSetRasterizerDiscardEnable"); + table->vkCmdSetScissorWithCount = (PFN_vkCmdSetScissorWithCount)load(context, "vkCmdSetScissorWithCount"); + table->vkCmdSetStencilOp = (PFN_vkCmdSetStencilOp)load(context, "vkCmdSetStencilOp"); + table->vkCmdSetStencilTestEnable = (PFN_vkCmdSetStencilTestEnable)load(context, "vkCmdSetStencilTestEnable"); + table->vkCmdSetViewportWithCount = (PFN_vkCmdSetViewportWithCount)load(context, "vkCmdSetViewportWithCount"); + table->vkCmdWaitEvents2 = (PFN_vkCmdWaitEvents2)load(context, "vkCmdWaitEvents2"); + table->vkCmdWriteTimestamp2 = (PFN_vkCmdWriteTimestamp2)load(context, "vkCmdWriteTimestamp2"); + table->vkCreatePrivateDataSlot = (PFN_vkCreatePrivateDataSlot)load(context, "vkCreatePrivateDataSlot"); + table->vkDestroyPrivateDataSlot = (PFN_vkDestroyPrivateDataSlot)load(context, "vkDestroyPrivateDataSlot"); + table->vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)load(context, "vkGetDeviceBufferMemoryRequirements"); + table->vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)load(context, "vkGetDeviceImageMemoryRequirements"); + table->vkGetDeviceImageSparseMemoryRequirements = (PFN_vkGetDeviceImageSparseMemoryRequirements)load(context, "vkGetDeviceImageSparseMemoryRequirements"); + table->vkGetPrivateData = (PFN_vkGetPrivateData)load(context, "vkGetPrivateData"); + table->vkQueueSubmit2 = (PFN_vkQueueSubmit2)load(context, "vkQueueSubmit2"); + table->vkSetPrivateData = (PFN_vkSetPrivateData)load(context, "vkSetPrivateData"); +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_AMDX_shader_enqueue) + table->vkCmdDispatchGraphAMDX = (PFN_vkCmdDispatchGraphAMDX)load(context, "vkCmdDispatchGraphAMDX"); + table->vkCmdDispatchGraphIndirectAMDX = (PFN_vkCmdDispatchGraphIndirectAMDX)load(context, "vkCmdDispatchGraphIndirectAMDX"); + table->vkCmdDispatchGraphIndirectCountAMDX = (PFN_vkCmdDispatchGraphIndirectCountAMDX)load(context, "vkCmdDispatchGraphIndirectCountAMDX"); + table->vkCmdInitializeGraphScratchMemoryAMDX = (PFN_vkCmdInitializeGraphScratchMemoryAMDX)load(context, "vkCmdInitializeGraphScratchMemoryAMDX"); + table->vkCreateExecutionGraphPipelinesAMDX = (PFN_vkCreateExecutionGraphPipelinesAMDX)load(context, "vkCreateExecutionGraphPipelinesAMDX"); + table->vkGetExecutionGraphPipelineNodeIndexAMDX = (PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)load(context, "vkGetExecutionGraphPipelineNodeIndexAMDX"); + table->vkGetExecutionGraphPipelineScratchSizeAMDX = (PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)load(context, "vkGetExecutionGraphPipelineScratchSizeAMDX"); +#endif /* defined(VK_AMDX_shader_enqueue) */ #if defined(VK_AMD_buffer_marker) table->vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD"); #endif /* defined(VK_AMD_buffer_marker) */ @@ -1090,6 +1443,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)load(context, "vkGetAndroidHardwareBufferPropertiesANDROID"); table->vkGetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID)load(context, "vkGetMemoryAndroidHardwareBufferANDROID"); #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) + table->vkCmdSetAttachmentFeedbackLoopEnableEXT = (PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)load(context, "vkCmdSetAttachmentFeedbackLoopEnableEXT"); +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ #if defined(VK_EXT_buffer_device_address) table->vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)load(context, "vkGetBufferDeviceAddressEXT"); #endif /* defined(VK_EXT_buffer_device_address) */ @@ -1110,36 +1466,40 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkDebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)load(context, "vkDebugMarkerSetObjectNameEXT"); table->vkDebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)load(context, "vkDebugMarkerSetObjectTagEXT"); #endif /* defined(VK_EXT_debug_marker) */ +#if defined(VK_EXT_depth_bias_control) + table->vkCmdSetDepthBias2EXT = (PFN_vkCmdSetDepthBias2EXT)load(context, "vkCmdSetDepthBias2EXT"); +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) + table->vkCmdBindDescriptorBufferEmbeddedSamplersEXT = (PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT)load(context, "vkCmdBindDescriptorBufferEmbeddedSamplersEXT"); + table->vkCmdBindDescriptorBuffersEXT = (PFN_vkCmdBindDescriptorBuffersEXT)load(context, "vkCmdBindDescriptorBuffersEXT"); + table->vkCmdSetDescriptorBufferOffsetsEXT = (PFN_vkCmdSetDescriptorBufferOffsetsEXT)load(context, "vkCmdSetDescriptorBufferOffsetsEXT"); + table->vkGetBufferOpaqueCaptureDescriptorDataEXT = (PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT)load(context, "vkGetBufferOpaqueCaptureDescriptorDataEXT"); + table->vkGetDescriptorEXT = (PFN_vkGetDescriptorEXT)load(context, "vkGetDescriptorEXT"); + table->vkGetDescriptorSetLayoutBindingOffsetEXT = (PFN_vkGetDescriptorSetLayoutBindingOffsetEXT)load(context, "vkGetDescriptorSetLayoutBindingOffsetEXT"); + table->vkGetDescriptorSetLayoutSizeEXT = (PFN_vkGetDescriptorSetLayoutSizeEXT)load(context, "vkGetDescriptorSetLayoutSizeEXT"); + table->vkGetImageOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageOpaqueCaptureDescriptorDataEXT"); + table->vkGetImageViewOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageViewOpaqueCaptureDescriptorDataEXT"); + table->vkGetSamplerOpaqueCaptureDescriptorDataEXT = (PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)load(context, "vkGetSamplerOpaqueCaptureDescriptorDataEXT"); +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) + table->vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT = (PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)load(context, "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT"); +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_device_fault) + table->vkGetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)load(context, "vkGetDeviceFaultInfoEXT"); +#endif /* defined(VK_EXT_device_fault) */ #if defined(VK_EXT_discard_rectangles) table->vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + table->vkCmdSetDiscardRectangleEnableEXT = (PFN_vkCmdSetDiscardRectangleEnableEXT)load(context, "vkCmdSetDiscardRectangleEnableEXT"); + table->vkCmdSetDiscardRectangleModeEXT = (PFN_vkCmdSetDiscardRectangleModeEXT)load(context, "vkCmdSetDiscardRectangleModeEXT"); +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) table->vkDisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT)load(context, "vkDisplayPowerControlEXT"); table->vkGetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT)load(context, "vkGetSwapchainCounterEXT"); table->vkRegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT)load(context, "vkRegisterDeviceEventEXT"); table->vkRegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT)load(context, "vkRegisterDisplayEventEXT"); #endif /* defined(VK_EXT_display_control) */ -#if defined(VK_EXT_extended_dynamic_state) - table->vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); - table->vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); - table->vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); - table->vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); - table->vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); - table->vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); - table->vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); - table->vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); - table->vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); - table->vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); - table->vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); - table->vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) - table->vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); - table->vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); - table->vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); - table->vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); - table->vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); -#endif /* defined(VK_EXT_extended_dynamic_state2) */ #if defined(VK_EXT_external_memory_host) table->vkGetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)load(context, "vkGetMemoryHostPointerPropertiesEXT"); #endif /* defined(VK_EXT_external_memory_host) */ @@ -1150,6 +1510,12 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_EXT_hdr_metadata) table->vkSetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)load(context, "vkSetHdrMetadataEXT"); #endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_image_copy) + table->vkCopyImageToImageEXT = (PFN_vkCopyImageToImageEXT)load(context, "vkCopyImageToImageEXT"); + table->vkCopyImageToMemoryEXT = (PFN_vkCopyImageToMemoryEXT)load(context, "vkCopyImageToMemoryEXT"); + table->vkCopyMemoryToImageEXT = (PFN_vkCopyMemoryToImageEXT)load(context, "vkCopyMemoryToImageEXT"); + table->vkTransitionImageLayoutEXT = (PFN_vkTransitionImageLayoutEXT)load(context, "vkTransitionImageLayoutEXT"); +#endif /* defined(VK_EXT_host_image_copy) */ #if defined(VK_EXT_host_query_reset) table->vkResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)load(context, "vkResetQueryPoolEXT"); #endif /* defined(VK_EXT_host_query_reset) */ @@ -1159,10 +1525,40 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_EXT_line_rasterization) table->vkCmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)load(context, "vkCmdSetLineStippleEXT"); #endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_mesh_shader) + table->vkCmdDrawMeshTasksEXT = (PFN_vkCmdDrawMeshTasksEXT)load(context, "vkCmdDrawMeshTasksEXT"); + table->vkCmdDrawMeshTasksIndirectCountEXT = (PFN_vkCmdDrawMeshTasksIndirectCountEXT)load(context, "vkCmdDrawMeshTasksIndirectCountEXT"); + table->vkCmdDrawMeshTasksIndirectEXT = (PFN_vkCmdDrawMeshTasksIndirectEXT)load(context, "vkCmdDrawMeshTasksIndirectEXT"); +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_metal_objects) + table->vkExportMetalObjectsEXT = (PFN_vkExportMetalObjectsEXT)load(context, "vkExportMetalObjectsEXT"); +#endif /* defined(VK_EXT_metal_objects) */ #if defined(VK_EXT_multi_draw) table->vkCmdDrawMultiEXT = (PFN_vkCmdDrawMultiEXT)load(context, "vkCmdDrawMultiEXT"); table->vkCmdDrawMultiIndexedEXT = (PFN_vkCmdDrawMultiIndexedEXT)load(context, "vkCmdDrawMultiIndexedEXT"); #endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) + table->vkBuildMicromapsEXT = (PFN_vkBuildMicromapsEXT)load(context, "vkBuildMicromapsEXT"); + table->vkCmdBuildMicromapsEXT = (PFN_vkCmdBuildMicromapsEXT)load(context, "vkCmdBuildMicromapsEXT"); + table->vkCmdCopyMemoryToMicromapEXT = (PFN_vkCmdCopyMemoryToMicromapEXT)load(context, "vkCmdCopyMemoryToMicromapEXT"); + table->vkCmdCopyMicromapEXT = (PFN_vkCmdCopyMicromapEXT)load(context, "vkCmdCopyMicromapEXT"); + table->vkCmdCopyMicromapToMemoryEXT = (PFN_vkCmdCopyMicromapToMemoryEXT)load(context, "vkCmdCopyMicromapToMemoryEXT"); + table->vkCmdWriteMicromapsPropertiesEXT = (PFN_vkCmdWriteMicromapsPropertiesEXT)load(context, "vkCmdWriteMicromapsPropertiesEXT"); + table->vkCopyMemoryToMicromapEXT = (PFN_vkCopyMemoryToMicromapEXT)load(context, "vkCopyMemoryToMicromapEXT"); + table->vkCopyMicromapEXT = (PFN_vkCopyMicromapEXT)load(context, "vkCopyMicromapEXT"); + table->vkCopyMicromapToMemoryEXT = (PFN_vkCopyMicromapToMemoryEXT)load(context, "vkCopyMicromapToMemoryEXT"); + table->vkCreateMicromapEXT = (PFN_vkCreateMicromapEXT)load(context, "vkCreateMicromapEXT"); + table->vkDestroyMicromapEXT = (PFN_vkDestroyMicromapEXT)load(context, "vkDestroyMicromapEXT"); + table->vkGetDeviceMicromapCompatibilityEXT = (PFN_vkGetDeviceMicromapCompatibilityEXT)load(context, "vkGetDeviceMicromapCompatibilityEXT"); + table->vkGetMicromapBuildSizesEXT = (PFN_vkGetMicromapBuildSizesEXT)load(context, "vkGetMicromapBuildSizesEXT"); + table->vkWriteMicromapsPropertiesEXT = (PFN_vkWriteMicromapsPropertiesEXT)load(context, "vkWriteMicromapsPropertiesEXT"); +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) + table->vkSetDeviceMemoryPriorityEXT = (PFN_vkSetDeviceMemoryPriorityEXT)load(context, "vkSetDeviceMemoryPriorityEXT"); +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) + table->vkGetPipelinePropertiesEXT = (PFN_vkGetPipelinePropertiesEXT)load(context, "vkGetPipelinePropertiesEXT"); +#endif /* defined(VK_EXT_pipeline_properties) */ #if defined(VK_EXT_private_data) table->vkCreatePrivateDataSlotEXT = (PFN_vkCreatePrivateDataSlotEXT)load(context, "vkCreatePrivateDataSlotEXT"); table->vkDestroyPrivateDataSlotEXT = (PFN_vkDestroyPrivateDataSlotEXT)load(context, "vkDestroyPrivateDataSlotEXT"); @@ -1172,6 +1568,19 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_EXT_sample_locations) table->vkCmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT)load(context, "vkCmdSetSampleLocationsEXT"); #endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) + table->vkGetShaderModuleCreateInfoIdentifierEXT = (PFN_vkGetShaderModuleCreateInfoIdentifierEXT)load(context, "vkGetShaderModuleCreateInfoIdentifierEXT"); + table->vkGetShaderModuleIdentifierEXT = (PFN_vkGetShaderModuleIdentifierEXT)load(context, "vkGetShaderModuleIdentifierEXT"); +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + table->vkCmdBindShadersEXT = (PFN_vkCmdBindShadersEXT)load(context, "vkCmdBindShadersEXT"); + table->vkCreateShadersEXT = (PFN_vkCreateShadersEXT)load(context, "vkCreateShadersEXT"); + table->vkDestroyShaderEXT = (PFN_vkDestroyShaderEXT)load(context, "vkDestroyShaderEXT"); + table->vkGetShaderBinaryDataEXT = (PFN_vkGetShaderBinaryDataEXT)load(context, "vkGetShaderBinaryDataEXT"); +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) + table->vkReleaseSwapchainImagesEXT = (PFN_vkReleaseSwapchainImagesEXT)load(context, "vkReleaseSwapchainImagesEXT"); +#endif /* defined(VK_EXT_swapchain_maintenance1) */ #if defined(VK_EXT_transform_feedback) table->vkCmdBeginQueryIndexedEXT = (PFN_vkCmdBeginQueryIndexedEXT)load(context, "vkCmdBeginQueryIndexedEXT"); table->vkCmdBeginTransformFeedbackEXT = (PFN_vkCmdBeginTransformFeedbackEXT)load(context, "vkCmdBeginTransformFeedbackEXT"); @@ -1186,9 +1595,13 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT)load(context, "vkGetValidationCacheDataEXT"); table->vkMergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT)load(context, "vkMergeValidationCachesEXT"); #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) - table->vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ +#if defined(VK_FUCHSIA_buffer_collection) + table->vkCreateBufferCollectionFUCHSIA = (PFN_vkCreateBufferCollectionFUCHSIA)load(context, "vkCreateBufferCollectionFUCHSIA"); + table->vkDestroyBufferCollectionFUCHSIA = (PFN_vkDestroyBufferCollectionFUCHSIA)load(context, "vkDestroyBufferCollectionFUCHSIA"); + table->vkGetBufferCollectionPropertiesFUCHSIA = (PFN_vkGetBufferCollectionPropertiesFUCHSIA)load(context, "vkGetBufferCollectionPropertiesFUCHSIA"); + table->vkSetBufferCollectionBufferConstraintsFUCHSIA = (PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)load(context, "vkSetBufferCollectionBufferConstraintsFUCHSIA"); + table->vkSetBufferCollectionImageConstraintsFUCHSIA = (PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)load(context, "vkSetBufferCollectionImageConstraintsFUCHSIA"); +#endif /* defined(VK_FUCHSIA_buffer_collection) */ #if defined(VK_FUCHSIA_external_memory) table->vkGetMemoryZirconHandleFUCHSIA = (PFN_vkGetMemoryZirconHandleFUCHSIA)load(context, "vkGetMemoryZirconHandleFUCHSIA"); table->vkGetMemoryZirconHandlePropertiesFUCHSIA = (PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)load(context, "vkGetMemoryZirconHandlePropertiesFUCHSIA"); @@ -1201,6 +1614,10 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)load(context, "vkGetPastPresentationTimingGOOGLE"); table->vkGetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)load(context, "vkGetRefreshCycleDurationGOOGLE"); #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + table->vkCmdDrawClusterHUAWEI = (PFN_vkCmdDrawClusterHUAWEI)load(context, "vkCmdDrawClusterHUAWEI"); + table->vkCmdDrawClusterIndirectHUAWEI = (PFN_vkCmdDrawClusterIndirectHUAWEI)load(context, "vkCmdDrawClusterIndirectHUAWEI"); +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) table->vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -1284,6 +1701,10 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)load(context, "vkCmdDrawIndexedIndirectCountKHR"); table->vkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)load(context, "vkCmdDrawIndirectCountKHR"); #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + table->vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)load(context, "vkCmdBeginRenderingKHR"); + table->vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)load(context, "vkCmdEndRenderingKHR"); +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_fd) table->vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)load(context, "vkGetFenceFdKHR"); table->vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)load(context, "vkImportFenceFdKHR"); @@ -1322,6 +1743,21 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_KHR_maintenance3) table->vkGetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR)load(context, "vkGetDescriptorSetLayoutSupportKHR"); #endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) + table->vkGetDeviceBufferMemoryRequirementsKHR = (PFN_vkGetDeviceBufferMemoryRequirementsKHR)load(context, "vkGetDeviceBufferMemoryRequirementsKHR"); + table->vkGetDeviceImageMemoryRequirementsKHR = (PFN_vkGetDeviceImageMemoryRequirementsKHR)load(context, "vkGetDeviceImageMemoryRequirementsKHR"); + table->vkGetDeviceImageSparseMemoryRequirementsKHR = (PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)load(context, "vkGetDeviceImageSparseMemoryRequirementsKHR"); +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) + table->vkCmdBindIndexBuffer2KHR = (PFN_vkCmdBindIndexBuffer2KHR)load(context, "vkCmdBindIndexBuffer2KHR"); + table->vkGetDeviceImageSubresourceLayoutKHR = (PFN_vkGetDeviceImageSubresourceLayoutKHR)load(context, "vkGetDeviceImageSubresourceLayoutKHR"); + table->vkGetImageSubresourceLayout2KHR = (PFN_vkGetImageSubresourceLayout2KHR)load(context, "vkGetImageSubresourceLayout2KHR"); + table->vkGetRenderingAreaGranularityKHR = (PFN_vkGetRenderingAreaGranularityKHR)load(context, "vkGetRenderingAreaGranularityKHR"); +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_map_memory2) + table->vkMapMemory2KHR = (PFN_vkMapMemory2KHR)load(context, "vkMapMemory2KHR"); + table->vkUnmapMemory2KHR = (PFN_vkUnmapMemory2KHR)load(context, "vkUnmapMemory2KHR"); +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) table->vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); table->vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); @@ -1337,6 +1773,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_KHR_push_descriptor) table->vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)load(context, "vkCmdPushDescriptorSetKHR"); #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) + table->vkCmdTraceRaysIndirect2KHR = (PFN_vkCmdTraceRaysIndirect2KHR)load(context, "vkCmdTraceRaysIndirect2KHR"); +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_ray_tracing_pipeline) table->vkCmdSetRayTracingPipelineStackSizeKHR = (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)load(context, "vkCmdSetRayTracingPipelineStackSizeKHR"); table->vkCmdTraceRaysIndirectKHR = (PFN_vkCmdTraceRaysIndirectKHR)load(context, "vkCmdTraceRaysIndirectKHR"); @@ -1384,6 +1823,7 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #endif /* defined(VK_KHR_video_decode_queue) */ #if defined(VK_KHR_video_encode_queue) table->vkCmdEncodeVideoKHR = (PFN_vkCmdEncodeVideoKHR)load(context, "vkCmdEncodeVideoKHR"); + table->vkGetEncodedVideoSessionParametersKHR = (PFN_vkGetEncodedVideoSessionParametersKHR)load(context, "vkGetEncodedVideoSessionParametersKHR"); #endif /* defined(VK_KHR_video_encode_queue) */ #if defined(VK_KHR_video_queue) table->vkBindVideoSessionMemoryKHR = (PFN_vkBindVideoSessionMemoryKHR)load(context, "vkBindVideoSessionMemoryKHR"); @@ -1411,6 +1851,18 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_NV_clip_space_w_scaling) table->vkCmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV)load(context, "vkCmdSetViewportWScalingNV"); #endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_copy_memory_indirect) + table->vkCmdCopyMemoryIndirectNV = (PFN_vkCmdCopyMemoryIndirectNV)load(context, "vkCmdCopyMemoryIndirectNV"); + table->vkCmdCopyMemoryToImageIndirectNV = (PFN_vkCmdCopyMemoryToImageIndirectNV)load(context, "vkCmdCopyMemoryToImageIndirectNV"); +#endif /* defined(VK_NV_copy_memory_indirect) */ +#if defined(VK_NV_cuda_kernel_launch) + table->vkCmdCudaLaunchKernelNV = (PFN_vkCmdCudaLaunchKernelNV)load(context, "vkCmdCudaLaunchKernelNV"); + table->vkCreateCudaFunctionNV = (PFN_vkCreateCudaFunctionNV)load(context, "vkCreateCudaFunctionNV"); + table->vkCreateCudaModuleNV = (PFN_vkCreateCudaModuleNV)load(context, "vkCreateCudaModuleNV"); + table->vkDestroyCudaFunctionNV = (PFN_vkDestroyCudaFunctionNV)load(context, "vkDestroyCudaFunctionNV"); + table->vkDestroyCudaModuleNV = (PFN_vkDestroyCudaModuleNV)load(context, "vkDestroyCudaModuleNV"); + table->vkGetCudaModuleCacheNV = (PFN_vkGetCudaModuleCacheNV)load(context, "vkGetCudaModuleCacheNV"); +#endif /* defined(VK_NV_cuda_kernel_launch) */ #if defined(VK_NV_device_diagnostic_checkpoints) table->vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)load(context, "vkCmdSetCheckpointNV"); table->vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)load(context, "vkGetQueueCheckpointDataNV"); @@ -1423,6 +1875,11 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkDestroyIndirectCommandsLayoutNV = (PFN_vkDestroyIndirectCommandsLayoutNV)load(context, "vkDestroyIndirectCommandsLayoutNV"); table->vkGetGeneratedCommandsMemoryRequirementsNV = (PFN_vkGetGeneratedCommandsMemoryRequirementsNV)load(context, "vkGetGeneratedCommandsMemoryRequirementsNV"); #endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) + table->vkCmdUpdatePipelineIndirectBufferNV = (PFN_vkCmdUpdatePipelineIndirectBufferNV)load(context, "vkCmdUpdatePipelineIndirectBufferNV"); + table->vkGetPipelineIndirectDeviceAddressNV = (PFN_vkGetPipelineIndirectDeviceAddressNV)load(context, "vkGetPipelineIndirectDeviceAddressNV"); + table->vkGetPipelineIndirectMemoryRequirementsNV = (PFN_vkGetPipelineIndirectMemoryRequirementsNV)load(context, "vkGetPipelineIndirectMemoryRequirementsNV"); +#endif /* defined(VK_NV_device_generated_commands_compute) */ #if defined(VK_NV_external_memory_rdma) table->vkGetMemoryRemoteAddressNV = (PFN_vkGetMemoryRemoteAddressNV)load(context, "vkGetMemoryRemoteAddressNV"); #endif /* defined(VK_NV_external_memory_rdma) */ @@ -1432,11 +1889,28 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_NV_fragment_shading_rate_enums) table->vkCmdSetFragmentShadingRateEnumNV = (PFN_vkCmdSetFragmentShadingRateEnumNV)load(context, "vkCmdSetFragmentShadingRateEnumNV"); #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + table->vkGetLatencyTimingsNV = (PFN_vkGetLatencyTimingsNV)load(context, "vkGetLatencyTimingsNV"); + table->vkLatencySleepNV = (PFN_vkLatencySleepNV)load(context, "vkLatencySleepNV"); + table->vkQueueNotifyOutOfBandNV = (PFN_vkQueueNotifyOutOfBandNV)load(context, "vkQueueNotifyOutOfBandNV"); + table->vkSetLatencyMarkerNV = (PFN_vkSetLatencyMarkerNV)load(context, "vkSetLatencyMarkerNV"); + table->vkSetLatencySleepModeNV = (PFN_vkSetLatencySleepModeNV)load(context, "vkSetLatencySleepModeNV"); +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) + table->vkCmdDecompressMemoryIndirectCountNV = (PFN_vkCmdDecompressMemoryIndirectCountNV)load(context, "vkCmdDecompressMemoryIndirectCountNV"); + table->vkCmdDecompressMemoryNV = (PFN_vkCmdDecompressMemoryNV)load(context, "vkCmdDecompressMemoryNV"); +#endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) table->vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); table->vkCmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)load(context, "vkCmdDrawMeshTasksIndirectNV"); table->vkCmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)load(context, "vkCmdDrawMeshTasksNV"); #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_optical_flow) + table->vkBindOpticalFlowSessionImageNV = (PFN_vkBindOpticalFlowSessionImageNV)load(context, "vkBindOpticalFlowSessionImageNV"); + table->vkCmdOpticalFlowExecuteNV = (PFN_vkCmdOpticalFlowExecuteNV)load(context, "vkCmdOpticalFlowExecuteNV"); + table->vkCreateOpticalFlowSessionNV = (PFN_vkCreateOpticalFlowSessionNV)load(context, "vkCreateOpticalFlowSessionNV"); + table->vkDestroyOpticalFlowSessionNV = (PFN_vkDestroyOpticalFlowSessionNV)load(context, "vkDestroyOpticalFlowSessionNV"); +#endif /* defined(VK_NV_optical_flow) */ #if defined(VK_NV_ray_tracing) table->vkBindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV)load(context, "vkBindAccelerationStructureMemoryNV"); table->vkCmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV)load(context, "vkCmdBuildAccelerationStructureNV"); @@ -1451,6 +1925,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV)load(context, "vkGetAccelerationStructureMemoryRequirementsNV"); table->vkGetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV)load(context, "vkGetRayTracingShaderGroupHandlesNV"); #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + table->vkCmdSetExclusiveScissorEnableNV = (PFN_vkCmdSetExclusiveScissorEnableNV)load(context, "vkCmdSetExclusiveScissorEnableNV"); +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) table->vkCmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV)load(context, "vkCmdSetExclusiveScissorNV"); #endif /* defined(VK_NV_scissor_exclusive) */ @@ -1459,9 +1936,94 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV)load(context, "vkCmdSetCoarseSampleOrderNV"); table->vkCmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV)load(context, "vkCmdSetViewportShadingRatePaletteNV"); #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_properties) + table->vkGetDynamicRenderingTilePropertiesQCOM = (PFN_vkGetDynamicRenderingTilePropertiesQCOM)load(context, "vkGetDynamicRenderingTilePropertiesQCOM"); + table->vkGetFramebufferTilePropertiesQCOM = (PFN_vkGetFramebufferTilePropertiesQCOM)load(context, "vkGetFramebufferTilePropertiesQCOM"); +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QNX_external_memory_screen_buffer) + table->vkGetScreenBufferPropertiesQNX = (PFN_vkGetScreenBufferPropertiesQNX)load(context, "vkGetScreenBufferPropertiesQNX"); +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) + table->vkGetDescriptorSetHostMappingVALVE = (PFN_vkGetDescriptorSetHostMappingVALVE)load(context, "vkGetDescriptorSetHostMappingVALVE"); + table->vkGetDescriptorSetLayoutHostMappingInfoVALVE = (PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)load(context, "vkGetDescriptorSetLayoutHostMappingInfoVALVE"); +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + table->vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); + table->vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); + table->vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); + table->vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); + table->vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); + table->vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); + table->vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); + table->vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); + table->vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); + table->vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); + table->vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); + table->vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + table->vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); + table->vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); + table->vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); + table->vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); + table->vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + table->vkCmdSetAlphaToCoverageEnableEXT = (PFN_vkCmdSetAlphaToCoverageEnableEXT)load(context, "vkCmdSetAlphaToCoverageEnableEXT"); + table->vkCmdSetAlphaToOneEnableEXT = (PFN_vkCmdSetAlphaToOneEnableEXT)load(context, "vkCmdSetAlphaToOneEnableEXT"); + table->vkCmdSetColorBlendAdvancedEXT = (PFN_vkCmdSetColorBlendAdvancedEXT)load(context, "vkCmdSetColorBlendAdvancedEXT"); + table->vkCmdSetColorBlendEnableEXT = (PFN_vkCmdSetColorBlendEnableEXT)load(context, "vkCmdSetColorBlendEnableEXT"); + table->vkCmdSetColorBlendEquationEXT = (PFN_vkCmdSetColorBlendEquationEXT)load(context, "vkCmdSetColorBlendEquationEXT"); + table->vkCmdSetColorWriteMaskEXT = (PFN_vkCmdSetColorWriteMaskEXT)load(context, "vkCmdSetColorWriteMaskEXT"); + table->vkCmdSetConservativeRasterizationModeEXT = (PFN_vkCmdSetConservativeRasterizationModeEXT)load(context, "vkCmdSetConservativeRasterizationModeEXT"); + table->vkCmdSetDepthClampEnableEXT = (PFN_vkCmdSetDepthClampEnableEXT)load(context, "vkCmdSetDepthClampEnableEXT"); + table->vkCmdSetDepthClipEnableEXT = (PFN_vkCmdSetDepthClipEnableEXT)load(context, "vkCmdSetDepthClipEnableEXT"); + table->vkCmdSetDepthClipNegativeOneToOneEXT = (PFN_vkCmdSetDepthClipNegativeOneToOneEXT)load(context, "vkCmdSetDepthClipNegativeOneToOneEXT"); + table->vkCmdSetExtraPrimitiveOverestimationSizeEXT = (PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)load(context, "vkCmdSetExtraPrimitiveOverestimationSizeEXT"); + table->vkCmdSetLineRasterizationModeEXT = (PFN_vkCmdSetLineRasterizationModeEXT)load(context, "vkCmdSetLineRasterizationModeEXT"); + table->vkCmdSetLineStippleEnableEXT = (PFN_vkCmdSetLineStippleEnableEXT)load(context, "vkCmdSetLineStippleEnableEXT"); + table->vkCmdSetLogicOpEnableEXT = (PFN_vkCmdSetLogicOpEnableEXT)load(context, "vkCmdSetLogicOpEnableEXT"); + table->vkCmdSetPolygonModeEXT = (PFN_vkCmdSetPolygonModeEXT)load(context, "vkCmdSetPolygonModeEXT"); + table->vkCmdSetProvokingVertexModeEXT = (PFN_vkCmdSetProvokingVertexModeEXT)load(context, "vkCmdSetProvokingVertexModeEXT"); + table->vkCmdSetRasterizationSamplesEXT = (PFN_vkCmdSetRasterizationSamplesEXT)load(context, "vkCmdSetRasterizationSamplesEXT"); + table->vkCmdSetRasterizationStreamEXT = (PFN_vkCmdSetRasterizationStreamEXT)load(context, "vkCmdSetRasterizationStreamEXT"); + table->vkCmdSetSampleLocationsEnableEXT = (PFN_vkCmdSetSampleLocationsEnableEXT)load(context, "vkCmdSetSampleLocationsEnableEXT"); + table->vkCmdSetSampleMaskEXT = (PFN_vkCmdSetSampleMaskEXT)load(context, "vkCmdSetSampleMaskEXT"); + table->vkCmdSetTessellationDomainOriginEXT = (PFN_vkCmdSetTessellationDomainOriginEXT)load(context, "vkCmdSetTessellationDomainOriginEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) + table->vkCmdSetViewportWScalingEnableNV = (PFN_vkCmdSetViewportWScalingEnableNV)load(context, "vkCmdSetViewportWScalingEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) + table->vkCmdSetViewportSwizzleNV = (PFN_vkCmdSetViewportSwizzleNV)load(context, "vkCmdSetViewportSwizzleNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) + table->vkCmdSetCoverageToColorEnableNV = (PFN_vkCmdSetCoverageToColorEnableNV)load(context, "vkCmdSetCoverageToColorEnableNV"); + table->vkCmdSetCoverageToColorLocationNV = (PFN_vkCmdSetCoverageToColorLocationNV)load(context, "vkCmdSetCoverageToColorLocationNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) + table->vkCmdSetCoverageModulationModeNV = (PFN_vkCmdSetCoverageModulationModeNV)load(context, "vkCmdSetCoverageModulationModeNV"); + table->vkCmdSetCoverageModulationTableEnableNV = (PFN_vkCmdSetCoverageModulationTableEnableNV)load(context, "vkCmdSetCoverageModulationTableEnableNV"); + table->vkCmdSetCoverageModulationTableNV = (PFN_vkCmdSetCoverageModulationTableNV)load(context, "vkCmdSetCoverageModulationTableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) + table->vkCmdSetShadingRateImageEnableNV = (PFN_vkCmdSetShadingRateImageEnableNV)load(context, "vkCmdSetShadingRateImageEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) + table->vkCmdSetRepresentativeFragmentTestEnableNV = (PFN_vkCmdSetRepresentativeFragmentTestEnableNV)load(context, "vkCmdSetRepresentativeFragmentTestEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) + table->vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) table->vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) + table->vkGetImageSubresourceLayout2EXT = (PFN_vkGetImageSubresourceLayout2EXT)load(context, "vkGetImageSubresourceLayout2EXT"); +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + table->vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) table->vkCmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)load(context, "vkCmdPushDescriptorSetWithTemplateKHR"); #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ @@ -1668,6 +2230,54 @@ PFN_vkResetQueryPool vkResetQueryPool; PFN_vkSignalSemaphore vkSignalSemaphore; PFN_vkWaitSemaphores vkWaitSemaphores; #endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) +PFN_vkCmdBeginRendering vkCmdBeginRendering; +PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2; +PFN_vkCmdBlitImage2 vkCmdBlitImage2; +PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2; +PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2; +PFN_vkCmdCopyImage2 vkCmdCopyImage2; +PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2; +PFN_vkCmdEndRendering vkCmdEndRendering; +PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2; +PFN_vkCmdResetEvent2 vkCmdResetEvent2; +PFN_vkCmdResolveImage2 vkCmdResolveImage2; +PFN_vkCmdSetCullMode vkCmdSetCullMode; +PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable; +PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable; +PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp; +PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable; +PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable; +PFN_vkCmdSetEvent2 vkCmdSetEvent2; +PFN_vkCmdSetFrontFace vkCmdSetFrontFace; +PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable; +PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology; +PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable; +PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount; +PFN_vkCmdSetStencilOp vkCmdSetStencilOp; +PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable; +PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount; +PFN_vkCmdWaitEvents2 vkCmdWaitEvents2; +PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2; +PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot; +PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot; +PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements; +PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements; +PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements; +PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties; +PFN_vkGetPrivateData vkGetPrivateData; +PFN_vkQueueSubmit2 vkQueueSubmit2; +PFN_vkSetPrivateData vkSetPrivateData; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_AMDX_shader_enqueue) +PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; +PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; +PFN_vkCmdDispatchGraphIndirectCountAMDX vkCmdDispatchGraphIndirectCountAMDX; +PFN_vkCmdInitializeGraphScratchMemoryAMDX vkCmdInitializeGraphScratchMemoryAMDX; +PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAMDX; +PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; +PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; +#endif /* defined(VK_AMDX_shader_enqueue) */ #if defined(VK_AMD_buffer_marker) PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; #endif /* defined(VK_AMD_buffer_marker) */ @@ -1693,6 +2303,9 @@ PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; #endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) +PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT; +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ #if defined(VK_EXT_buffer_device_address) PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; #endif /* defined(VK_EXT_buffer_device_address) */ @@ -1732,6 +2345,27 @@ PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; #endif /* defined(VK_EXT_debug_utils) */ +#if defined(VK_EXT_depth_bias_control) +PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT; +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) +PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT vkCmdBindDescriptorBufferEmbeddedSamplersEXT; +PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffersEXT; +PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsetsEXT; +PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT vkGetBufferOpaqueCaptureDescriptorDataEXT; +PFN_vkGetDescriptorEXT vkGetDescriptorEXT; +PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffsetEXT; +PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSizeEXT; +PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescriptorDataEXT; +PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; +PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) +PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_device_fault) +PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; +#endif /* defined(VK_EXT_device_fault) */ #if defined(VK_EXT_direct_mode_display) PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; #endif /* defined(VK_EXT_direct_mode_display) */ @@ -1742,6 +2376,10 @@ PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectF #if defined(VK_EXT_discard_rectangles) PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 +PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; +PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; @@ -1751,27 +2389,6 @@ PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; #if defined(VK_EXT_display_surface_counter) PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; #endif /* defined(VK_EXT_display_surface_counter) */ -#if defined(VK_EXT_extended_dynamic_state) -PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; -PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; -PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; -PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; -PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; -PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; -PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; -PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; -PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; -PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; -PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; -PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) -PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; -PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; -PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; -PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; -PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; -#endif /* defined(VK_EXT_extended_dynamic_state2) */ #if defined(VK_EXT_external_memory_host) PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; #endif /* defined(VK_EXT_external_memory_host) */ @@ -1786,6 +2403,12 @@ PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; #if defined(VK_EXT_headless_surface) PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; #endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_host_image_copy) +PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT; +PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT; +PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT; +PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT; +#endif /* defined(VK_EXT_host_image_copy) */ #if defined(VK_EXT_host_query_reset) PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; #endif /* defined(VK_EXT_host_query_reset) */ @@ -1795,6 +2418,14 @@ PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierProperti #if defined(VK_EXT_line_rasterization) PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; #endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_mesh_shader) +PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; +PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; +PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_metal_objects) +PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; +#endif /* defined(VK_EXT_metal_objects) */ #if defined(VK_EXT_metal_surface) PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; #endif /* defined(VK_EXT_metal_surface) */ @@ -1802,6 +2433,28 @@ PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; #endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) +PFN_vkBuildMicromapsEXT vkBuildMicromapsEXT; +PFN_vkCmdBuildMicromapsEXT vkCmdBuildMicromapsEXT; +PFN_vkCmdCopyMemoryToMicromapEXT vkCmdCopyMemoryToMicromapEXT; +PFN_vkCmdCopyMicromapEXT vkCmdCopyMicromapEXT; +PFN_vkCmdCopyMicromapToMemoryEXT vkCmdCopyMicromapToMemoryEXT; +PFN_vkCmdWriteMicromapsPropertiesEXT vkCmdWriteMicromapsPropertiesEXT; +PFN_vkCopyMemoryToMicromapEXT vkCopyMemoryToMicromapEXT; +PFN_vkCopyMicromapEXT vkCopyMicromapEXT; +PFN_vkCopyMicromapToMemoryEXT vkCopyMicromapToMemoryEXT; +PFN_vkCreateMicromapEXT vkCreateMicromapEXT; +PFN_vkDestroyMicromapEXT vkDestroyMicromapEXT; +PFN_vkGetDeviceMicromapCompatibilityEXT vkGetDeviceMicromapCompatibilityEXT; +PFN_vkGetMicromapBuildSizesEXT vkGetMicromapBuildSizesEXT; +PFN_vkWriteMicromapsPropertiesEXT vkWriteMicromapsPropertiesEXT; +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) +PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT; +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) +PFN_vkGetPipelinePropertiesEXT vkGetPipelinePropertiesEXT; +#endif /* defined(VK_EXT_pipeline_properties) */ #if defined(VK_EXT_private_data) PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; @@ -1812,6 +2465,19 @@ PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; #endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) +PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; +PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) +PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; +PFN_vkCreateShadersEXT vkCreateShadersEXT; +PFN_vkDestroyShaderEXT vkDestroyShaderEXT; +PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) +PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; +#endif /* defined(VK_EXT_swapchain_maintenance1) */ #if defined(VK_EXT_tooling_info) PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; #endif /* defined(VK_EXT_tooling_info) */ @@ -1829,9 +2495,13 @@ PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT; PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) -PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ +#if defined(VK_FUCHSIA_buffer_collection) +PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; +PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; +PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA; +PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA; +PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA; +#endif /* defined(VK_FUCHSIA_buffer_collection) */ #if defined(VK_FUCHSIA_external_memory) PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; @@ -1850,6 +2520,10 @@ PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) +PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; +PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -1898,6 +2572,9 @@ PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; #endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_cooperative_matrix) +PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR; +#endif /* defined(VK_KHR_cooperative_matrix) */ #if defined(VK_KHR_copy_commands2) PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; @@ -1948,6 +2625,10 @@ PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; #endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) +PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; +PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#endif /* defined(VK_KHR_dynamic_rendering) */ #if defined(VK_KHR_external_fence_capabilities) PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; #endif /* defined(VK_KHR_external_fence_capabilities) */ @@ -2015,6 +2696,21 @@ PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; #if defined(VK_KHR_maintenance3) PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; #endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) +PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR; +PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; +PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) +PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR; +PFN_vkGetDeviceImageSubresourceLayoutKHR vkGetDeviceImageSubresourceLayoutKHR; +PFN_vkGetImageSubresourceLayout2KHR vkGetImageSubresourceLayout2KHR; +PFN_vkGetRenderingAreaGranularityKHR vkGetRenderingAreaGranularityKHR; +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_map_memory2) +PFN_vkMapMemory2KHR vkMapMemory2KHR; +PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; @@ -2032,6 +2728,9 @@ PFN_vkWaitForPresentKHR vkWaitForPresentKHR; #if defined(VK_KHR_push_descriptor) PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) +PFN_vkCmdTraceRaysIndirect2KHR vkCmdTraceRaysIndirect2KHR; +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_ray_tracing_pipeline) PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; @@ -2086,6 +2785,8 @@ PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; #endif /* defined(VK_KHR_video_decode_queue) */ #if defined(VK_KHR_video_encode_queue) PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; +PFN_vkGetEncodedVideoSessionParametersKHR vkGetEncodedVideoSessionParametersKHR; +PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR; #endif /* defined(VK_KHR_video_encode_queue) */ #if defined(VK_KHR_video_queue) PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; @@ -2147,9 +2848,21 @@ PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; #if defined(VK_NV_cooperative_matrix) PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; #endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_copy_memory_indirect) +PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; +PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; +#endif /* defined(VK_NV_copy_memory_indirect) */ #if defined(VK_NV_coverage_reduction_mode) PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; #endif /* defined(VK_NV_coverage_reduction_mode) */ +#if defined(VK_NV_cuda_kernel_launch) +PFN_vkCmdCudaLaunchKernelNV vkCmdCudaLaunchKernelNV; +PFN_vkCreateCudaFunctionNV vkCreateCudaFunctionNV; +PFN_vkCreateCudaModuleNV vkCreateCudaModuleNV; +PFN_vkDestroyCudaFunctionNV vkDestroyCudaFunctionNV; +PFN_vkDestroyCudaModuleNV vkDestroyCudaModuleNV; +PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; +#endif /* defined(VK_NV_cuda_kernel_launch) */ #if defined(VK_NV_device_diagnostic_checkpoints) PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; @@ -2162,6 +2875,11 @@ PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; #endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) +PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBufferNV; +PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; +PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands_compute) */ #if defined(VK_NV_external_memory_capabilities) PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; #endif /* defined(VK_NV_external_memory_capabilities) */ @@ -2174,11 +2892,29 @@ PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; #if defined(VK_NV_fragment_shading_rate_enums) PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) +PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; +PFN_vkLatencySleepNV vkLatencySleepNV; +PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; +PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; +PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) +PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; +PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; +#endif /* defined(VK_NV_memory_decompression) */ #if defined(VK_NV_mesh_shader) PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; #endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_optical_flow) +PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; +PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; +PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; +PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; +PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV vkGetPhysicalDeviceOpticalFlowImageFormatsNV; +#endif /* defined(VK_NV_optical_flow) */ #if defined(VK_NV_ray_tracing) PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; @@ -2193,6 +2929,9 @@ PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV; PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 +PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; #endif /* defined(VK_NV_scissor_exclusive) */ @@ -2201,13 +2940,98 @@ PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; #endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_QCOM_tile_properties) +PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; +PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QNX_external_memory_screen_buffer) +PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ #if defined(VK_QNX_screen_surface) PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; #endif /* defined(VK_QNX_screen_surface) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) +PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; +PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; +PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; +PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; +PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; +PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; +PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; +PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; +PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; +PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; +PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; +PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; +PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; +PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; +PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; +PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; +PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; +PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; +PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; +PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; +PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; +PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; +PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; +PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; +PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; +PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; +PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; +PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; +PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; +PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; +PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; +PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; +PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; +PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; +PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; +PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; +PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) +PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) +PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) +PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; +PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) +PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; +PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; +PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) +PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) +PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) +PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) +PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) +PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ diff --git a/libraries/ZVulkan/src/vulkanbuilders.cpp b/libraries/ZVulkan/src/vulkanbuilders.cpp index de568b8844..e056c6f156 100644 --- a/libraries/ZVulkan/src/vulkanbuilders.cpp +++ b/libraries/ZVulkan/src/vulkanbuilders.cpp @@ -1,4 +1,3 @@ -#include #include "vulkanbuilders.h" #include "vulkansurface.h" #include "vulkancompatibledevice.h" @@ -281,7 +280,7 @@ std::unique_ptr ShaderBuilder::Create(const char *shadername, Vulk bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules, includer); if (!compileSuccess) { - throw std::runtime_error(std::string("Shader compile failed: ") + shader.getInfoLog()); + VulkanError((std::string("Shader compile failed: ") + shader.getInfoLog()).c_str()); } glslang::TProgram program; @@ -289,13 +288,13 @@ std::unique_ptr ShaderBuilder::Create(const char *shadername, Vulk bool linkSuccess = program.link(EShMsgDefault); if (!linkSuccess) { - throw std::runtime_error(std::string("Shader link failed: ") + program.getInfoLog()); + VulkanError((std::string("Shader link failed: ") + program.getInfoLog()).c_str()); } glslang::TIntermediate *intermediate = program.getIntermediate(stage); if (!intermediate) { - throw std::runtime_error("Internal shader compiler error"); + VulkanError("Internal shader compiler error"); } glslang::SpvOptions spvOptions; @@ -315,7 +314,7 @@ std::unique_ptr ShaderBuilder::Create(const char *shadername, Vulk VkShaderModule shaderModule; VkResult result = vkCreateShaderModule(device->device, &createInfo, nullptr, &shaderModule); if (result != VK_SUCCESS) - throw std::runtime_error("Could not create vulkan shader module"); + VulkanError("Could not create vulkan shader module"); auto obj = std::make_unique(device, shaderModule); if (debugName) @@ -505,13 +504,15 @@ ImageViewBuilder& ImageViewBuilder::Type(VkImageViewType type) return *this; } -ImageViewBuilder& ImageViewBuilder::Image(VulkanImage* image, VkFormat format, VkImageAspectFlags aspectMask) +ImageViewBuilder& ImageViewBuilder::Image(VulkanImage* image, VkFormat format, VkImageAspectFlags aspectMask, int mipLevel, int arrayLayer, int levelCount, int layerCount) { viewInfo.image = image->image; viewInfo.format = format; - viewInfo.subresourceRange.levelCount = image->mipLevels; + viewInfo.subresourceRange.levelCount = levelCount == 0 ? image->mipLevels : levelCount; viewInfo.subresourceRange.aspectMask = aspectMask; - viewInfo.subresourceRange.layerCount = image->layerCount; + viewInfo.subresourceRange.layerCount = layerCount == 0 ? image->layerCount : layerCount; + viewInfo.subresourceRange.baseMipLevel = mipLevel; + viewInfo.subresourceRange.baseArrayLayer = arrayLayer; return *this; } @@ -704,7 +705,7 @@ std::unique_ptr AccelerationStructureBuilder::Creat VkAccelerationStructureKHR hande = {}; VkResult result = vkCreateAccelerationStructureKHR(device->device, &createInfo, nullptr, &hande); if (result != VK_SUCCESS) - throw std::runtime_error("vkCreateAccelerationStructureKHR failed"); + VulkanError("vkCreateAccelerationStructureKHR failed"); auto obj = std::make_unique(device, hande); if (debugName) obj->SetDebugName(debugName); @@ -919,6 +920,63 @@ std::unique_ptr FramebufferBuilder::Create(VulkanDevice* devi ///////////////////////////////////////////////////////////////////////////// + +ColorBlendAttachmentBuilder::ColorBlendAttachmentBuilder() +{ + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_FALSE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; +} + +ColorBlendAttachmentBuilder& ColorBlendAttachmentBuilder::ColorWriteMask(VkColorComponentFlags mask) +{ + colorBlendAttachment.colorWriteMask = mask; + return *this; +} + +ColorBlendAttachmentBuilder& ColorBlendAttachmentBuilder::AdditiveBlendMode() +{ + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + return *this; +} + +ColorBlendAttachmentBuilder& ColorBlendAttachmentBuilder::AlphaBlendMode() +{ + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + return *this; +} + +ColorBlendAttachmentBuilder& ColorBlendAttachmentBuilder::BlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst) +{ + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = src; + colorBlendAttachment.dstColorBlendFactor = dst; + colorBlendAttachment.colorBlendOp = op; + colorBlendAttachment.srcAlphaBlendFactor = src; + colorBlendAttachment.dstAlphaBlendFactor = dst; + colorBlendAttachment.alphaBlendOp = op; + return *this; +} + +///////////////////////////////////////////////////////////////////////////// + GraphicsPipelineBuilder::GraphicsPipelineBuilder() { pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; @@ -979,20 +1037,9 @@ GraphicsPipelineBuilder::GraphicsPipelineBuilder() multisampling.alphaToCoverageEnable = VK_FALSE; multisampling.alphaToOneEnable = VK_FALSE; - colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_FALSE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlending.logicOpEnable = VK_FALSE; colorBlending.logicOp = VK_LOGIC_OP_COPY; - colorBlending.attachmentCount = 1; - colorBlending.pAttachments = &colorBlendAttachment; colorBlending.blendConstants[0] = 0.0f; colorBlending.blendConstants[1] = 0.0f; colorBlending.blendConstants[2] = 0.0f; @@ -1113,53 +1160,9 @@ GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthBias(bool enable, float b return *this; } -GraphicsPipelineBuilder& GraphicsPipelineBuilder::ColorWriteMask(VkColorComponentFlags mask) +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddColorBlendAttachment(VkPipelineColorBlendAttachmentState state) { - colorBlendAttachment.colorWriteMask = mask; - return *this; -} - -GraphicsPipelineBuilder& GraphicsPipelineBuilder::AdditiveBlendMode() -{ - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - return *this; -} - -GraphicsPipelineBuilder& GraphicsPipelineBuilder::AlphaBlendMode() -{ - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - return *this; -} - -GraphicsPipelineBuilder& GraphicsPipelineBuilder::BlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst) -{ - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = src; - colorBlendAttachment.dstColorBlendFactor = dst; - colorBlendAttachment.colorBlendOp = op; - colorBlendAttachment.srcAlphaBlendFactor = src; - colorBlendAttachment.dstAlphaBlendFactor = dst; - colorBlendAttachment.alphaBlendOp = op; - return *this; -} - -GraphicsPipelineBuilder& GraphicsPipelineBuilder::SubpassColorAttachmentCount(int count) -{ - colorBlendAttachments.resize(count, colorBlendAttachment); - colorBlending.pAttachments = colorBlendAttachments.data(); - colorBlending.attachmentCount = (uint32_t)colorBlendAttachments.size(); + colorBlendAttachments.push_back(state); return *this; } @@ -1228,6 +1231,11 @@ GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddDynamicState(VkDynamicState std::unique_ptr GraphicsPipelineBuilder::Create(VulkanDevice* device) { + if (colorBlendAttachments.empty()) + colorBlendAttachments.push_back(ColorBlendAttachmentBuilder().Create()); + colorBlending.pAttachments = colorBlendAttachments.data(); + colorBlending.attachmentCount = (uint32_t)colorBlendAttachments.size(); + VkPipeline pipeline = 0; VkResult result = vkCreateGraphicsPipelines(device->device, cache ? cache->cache : VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); CheckVulkanError(result, "Could not create graphics pipeline"); @@ -1459,12 +1467,12 @@ PipelineBarrier& PipelineBarrier::AddBuffer(VulkanBuffer* buffer, VkDeviceSize o return *this; } -PipelineBarrier& PipelineBarrier::AddImage(VulkanImage* image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +PipelineBarrier& PipelineBarrier::AddImage(VulkanImage* image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount, int baseArrayLayer, int layerCount) { - return AddImage(image->image, oldLayout, newLayout, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount); + return AddImage(image->image, oldLayout, newLayout, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount, baseArrayLayer, layerCount); } -PipelineBarrier& PipelineBarrier::AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +PipelineBarrier& PipelineBarrier::AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount, int baseArrayLayer, int layerCount) { VkImageMemoryBarrier barrier = { }; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; @@ -1478,8 +1486,8 @@ PipelineBarrier& PipelineBarrier::AddImage(VkImage image, VkImageLayout oldLayou barrier.subresourceRange.aspectMask = aspectMask; barrier.subresourceRange.baseMipLevel = baseMipLevel; barrier.subresourceRange.levelCount = levelCount; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; + barrier.subresourceRange.baseArrayLayer = baseArrayLayer; + barrier.subresourceRange.layerCount = layerCount; imageMemoryBarriers.push_back(barrier); return *this; } @@ -1754,10 +1762,20 @@ std::shared_ptr VulkanSurfaceBuilder::Create(std::shared_ptr VulkanDeviceBuilder::FindDevices(const std:: // Check if all required features are there if (info.Features.Features.samplerAnisotropy != VK_TRUE || - info.Features.Features.fragmentStoresAndAtomics != VK_TRUE) + info.Features.Features.fragmentStoresAndAtomics != VK_TRUE || + info.Features.Features.multiDrawIndirect != VK_TRUE || + info.Features.Features.independentBlend != VK_TRUE) continue; VulkanCompatibleDevice dev; @@ -1846,6 +1866,8 @@ std::vector VulkanDeviceBuilder::FindDevices(const std:: enabledFeatures.Features.fragmentStoresAndAtomics = deviceFeatures.Features.fragmentStoresAndAtomics; enabledFeatures.Features.depthClamp = deviceFeatures.Features.depthClamp; enabledFeatures.Features.shaderClipDistance = deviceFeatures.Features.shaderClipDistance; + enabledFeatures.Features.multiDrawIndirect = deviceFeatures.Features.multiDrawIndirect; + enabledFeatures.Features.independentBlend = deviceFeatures.Features.independentBlend; enabledFeatures.BufferDeviceAddress.bufferDeviceAddress = deviceFeatures.BufferDeviceAddress.bufferDeviceAddress; enabledFeatures.AccelerationStructure.accelerationStructure = deviceFeatures.AccelerationStructure.accelerationStructure; enabledFeatures.RayQuery.rayQuery = deviceFeatures.RayQuery.rayQuery; @@ -1853,6 +1875,7 @@ std::vector VulkanDeviceBuilder::FindDevices(const std:: enabledFeatures.DescriptorIndexing.descriptorBindingPartiallyBound = deviceFeatures.DescriptorIndexing.descriptorBindingPartiallyBound; enabledFeatures.DescriptorIndexing.descriptorBindingSampledImageUpdateAfterBind = deviceFeatures.DescriptorIndexing.descriptorBindingSampledImageUpdateAfterBind; enabledFeatures.DescriptorIndexing.descriptorBindingVariableDescriptorCount = deviceFeatures.DescriptorIndexing.descriptorBindingVariableDescriptorCount; + enabledFeatures.DescriptorIndexing.shaderSampledImageArrayNonUniformIndexing = deviceFeatures.DescriptorIndexing.shaderSampledImageArrayNonUniformIndexing; // Figure out which queue can present if (surface) @@ -1902,6 +1925,12 @@ std::vector VulkanDeviceBuilder::FindDevices(const std:: if (sortA != sortB) return sortA < sortB; + // Any driver that is emulating vulkan (i.e. via Direct3D 12) should only be chosen as the last option within each GPU type + sortA = a.Device->Properties.LayeredDriver.underlyingAPI; + sortB = b.Device->Properties.LayeredDriver.underlyingAPI; + if (sortA != sortB) + return sortA < sortB; + // Then sort by the device's unique ID so that vk_device uses a consistent order int sortUUID = memcmp(a.Device->Properties.Properties.pipelineCacheUUID, b.Device->Properties.Properties.pipelineCacheUUID, VK_UUID_SIZE); return sortUUID < 0; @@ -1936,3 +1965,64 @@ std::shared_ptr VulkanSwapChainBuilder::Create(VulkanDevice* de { return std::make_shared(device); } + +///////////////////////////////////////////////////////////////////////////// + +BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, size_t offset, const void* data, size_t size) +{ + bufferCopies.push_back({ buffer, offset, data, size, nullptr, 0 }); + return *this; +} + +BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, const void* data, size_t size) +{ + bufferCopies.push_back({ buffer, 0, data, size, nullptr, 0 }); + return *this; +} + +BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, const void* data0, size_t size0, const void* data1, size_t size1) +{ + bufferCopies.push_back({ buffer, 0, data0, size0, data1, size1 }); + return *this; +} + +std::unique_ptr BufferTransfer::Execute(VulkanDevice* device, VulkanCommandBuffer* cmdbuffer) +{ + size_t transferbuffersize = 0; + for (const auto& copy : bufferCopies) + transferbuffersize += copy.size0 + copy.size1; + + if (transferbuffersize == 0) + return nullptr; + + auto transferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(transferbuffersize) + .DebugName("BufferTransfer.transferBuffer") + .Create(device); + + uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize); + size_t pos = 0; + for (const auto& copy : bufferCopies) + { + memcpy(data + pos, copy.data0, copy.size0); + pos += copy.size0; + memcpy(data + pos, copy.data1, copy.size1); + pos += copy.size1; + } + transferBuffer->Unmap(); + + pos = 0; + for (const auto& copy : bufferCopies) + { + if (copy.size0 > 0) + cmdbuffer->copyBuffer(transferBuffer.get(), copy.buffer, pos, copy.offset, copy.size0); + pos += copy.size0; + + if (copy.size1 > 0) + cmdbuffer->copyBuffer(transferBuffer.get(), copy.buffer, pos, copy.offset + copy.size0, copy.size1); + pos += copy.size1; + } + + return transferBuffer; +} diff --git a/libraries/ZVulkan/src/vulkandevice.cpp b/libraries/ZVulkan/src/vulkandevice.cpp index 0adfff5c21..62ea9e7463 100644 --- a/libraries/ZVulkan/src/vulkandevice.cpp +++ b/libraries/ZVulkan/src/vulkandevice.cpp @@ -40,6 +40,10 @@ bool VulkanDevice::SupportsExtension(const char* ext) const Instance->EnabledExtensions.find(ext) != Instance->EnabledExtensions.end(); } +#ifndef VK_KHR_MAINTENANCE4_EXTENSION_NAME +#define VK_KHR_MAINTENANCE4_EXTENSION_NAME "VK_KHR_maintenance4" +#endif + void VulkanDevice::CreateAllocator() { VmaAllocatorCreateInfo allocinfo = {}; @@ -48,6 +52,16 @@ void VulkanDevice::CreateAllocator() allocinfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; if (SupportsExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) allocinfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; + if (SupportsExtension(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME)) + allocinfo.flags |= VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT; + //if (SupportsExtension(VK_KHR_MAINTENANCE4_EXTENSION_NAME)) + // allocinfo.flags |= MA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT; + if (SupportsExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME)) + allocinfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; + if (SupportsExtension(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME)) + allocinfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT; + if (SupportsExtension(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME)) + allocinfo.flags |= VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT; allocinfo.physicalDevice = PhysicalDevice.Device; allocinfo.device = device; allocinfo.instance = Instance->Instance; @@ -150,7 +164,7 @@ void VulkanDevice::ReleaseResources() void VulkanDevice::SetObjectName(const char* name, uint64_t handle, VkObjectType type) { - if (!DebugLayerActive) return; + if (!Instance->DebugLayerActive) return; VkDebugUtilsObjectNameInfoEXT info = {}; info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; diff --git a/libraries/ZVulkan/src/vulkaninstance.cpp b/libraries/ZVulkan/src/vulkaninstance.cpp index 939dc737a0..0641d3987e 100644 --- a/libraries/ZVulkan/src/vulkaninstance.cpp +++ b/libraries/ZVulkan/src/vulkaninstance.cpp @@ -200,11 +200,17 @@ std::vector VulkanInstance::GetPhysicalDevices(VkInstance *next = &dev.Properties.DescriptorIndexing; next = &dev.Properties.DescriptorIndexing.pNext; } + if (checkForExtension(VK_MSFT_LAYERED_DRIVER_EXTENSION_NAME)) + { + *next = &dev.Properties.LayeredDriver; + next = &dev.Properties.LayeredDriver.pNext; + } vkGetPhysicalDeviceProperties2(dev.Device, &deviceProperties2); dev.Properties.Properties = deviceProperties2.properties; dev.Properties.AccelerationStructure.pNext = nullptr; dev.Properties.DescriptorIndexing.pNext = nullptr; + dev.Properties.LayeredDriver.pNext = nullptr; VkPhysicalDeviceFeatures2 deviceFeatures2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; diff --git a/libraries/ZVulkan/src/vulkanswapchain.cpp b/libraries/ZVulkan/src/vulkanswapchain.cpp index 5cdd147684..299913d8cf 100644 --- a/libraries/ZVulkan/src/vulkanswapchain.cpp +++ b/libraries/ZVulkan/src/vulkanswapchain.cpp @@ -1,4 +1,4 @@ -#include + #include "vulkanswapchain.h" #include "vulkanobjects.h" #include "vulkansurface.h" @@ -34,13 +34,13 @@ void VulkanSwapChain::Create(int width, int height, int imageCount, bool vsync, uint32_t imageCount; VkResult result = vkGetSwapchainImagesKHR(device->device, swapchain, &imageCount, nullptr); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetSwapchainImagesKHR failed"); + VulkanError("vkGetSwapchainImagesKHR failed"); std::vector swapchainImages; swapchainImages.resize(imageCount); result = vkGetSwapchainImagesKHR(device->device, swapchain, &imageCount, swapchainImages.data()); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetSwapchainImagesKHR failed (2)"); + VulkanError("vkGetSwapchainImagesKHR failed (2)"); for (VkImage vkimage : swapchainImages) { @@ -103,7 +103,7 @@ bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, boo } if (caps.PresentModes.empty()) - throw std::runtime_error("No surface present modes supported"); + VulkanError("No surface present modes supported"); bool supportsFifoRelaxed = std::find(caps.PresentModes.begin(), caps.PresentModes.end(), VK_PRESENT_MODE_FIFO_RELAXED_KHR) != caps.PresentModes.end(); bool supportsMailbox = std::find(caps.PresentModes.begin(), caps.PresentModes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != caps.PresentModes.end(); @@ -126,9 +126,9 @@ bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, boo } else { - if (supportsMailbox) + /*if (supportsMailbox) presentMode = VK_PRESENT_MODE_MAILBOX_KHR; - else if (supportsImmediate) + else*/ if (supportsImmediate) presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } } @@ -140,6 +140,8 @@ bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, boo actualExtent.height = std::max(caps.Capabilites.minImageExtent.height, std::min(caps.Capabilites.maxImageExtent.height, actualExtent.height)); if (actualExtent.width == 0 || actualExtent.height == 0) { + if (swapchain) + vkDestroySwapchainKHR(device->device, swapchain, nullptr); swapchain = VK_NULL_HANDLE; lost = true; return false; @@ -241,7 +243,8 @@ int VulkanSwapChain::AcquireImage(VulkanSemaphore* semaphore, VulkanFence* fence } else { - throw std::runtime_error("Failed to acquire next image!"); + VulkanError("Failed to acquire next image!"); + return -1; } } @@ -270,15 +273,15 @@ void VulkanSwapChain::QueuePresent(int imageIndex, VulkanSemaphore* semaphore) // The spec says we can recover from this. // However, if we are out of memory it is better to crash now than in some other weird place further away from the source of the problem. - throw std::runtime_error("vkQueuePresentKHR failed: out of memory"); + VulkanError("vkQueuePresentKHR failed: out of memory"); } else if (result == VK_ERROR_DEVICE_LOST) { - throw std::runtime_error("vkQueuePresentKHR failed: device lost"); + VulkanError("vkQueuePresentKHR failed: device lost"); } else { - throw std::runtime_error("vkQueuePresentKHR failed"); + VulkanError("vkQueuePresentKHR failed"); } } @@ -332,7 +335,7 @@ VulkanSurfaceCapabilities VulkanSwapChain::GetSurfaceCapabilities(bool exclusive VkResult result = vkGetPhysicalDeviceSurfaceCapabilities2KHR(device->PhysicalDevice.Device, &surfaceInfo, &caps2); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilities2KHR failed"); + VulkanError("vkGetPhysicalDeviceSurfaceCapabilities2KHR failed"); caps.Capabilites = caps2.surfaceCapabilities; } @@ -340,7 +343,7 @@ VulkanSurfaceCapabilities VulkanSwapChain::GetSurfaceCapabilities(bool exclusive { VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &caps.Capabilites); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed"); + VulkanError("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed"); } #ifdef WIN32 @@ -351,14 +354,14 @@ VulkanSurfaceCapabilities VulkanSwapChain::GetSurfaceCapabilities(bool exclusive uint32_t presentModeCount = 0; VkResult result = vkGetPhysicalDeviceSurfacePresentModes2EXT(device->PhysicalDevice.Device, &surfaceInfo, &presentModeCount, nullptr); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModes2EXT failed"); + VulkanError("vkGetPhysicalDeviceSurfacePresentModes2EXT failed"); if (presentModeCount > 0) { caps.PresentModes.resize(presentModeCount); result = vkGetPhysicalDeviceSurfacePresentModes2EXT(device->PhysicalDevice.Device, &surfaceInfo, &presentModeCount, caps.PresentModes.data()); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModes2EXT failed"); + VulkanError("vkGetPhysicalDeviceSurfacePresentModes2EXT failed"); } } else @@ -367,14 +370,14 @@ VulkanSurfaceCapabilities VulkanSwapChain::GetSurfaceCapabilities(bool exclusive uint32_t presentModeCount = 0; VkResult result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &presentModeCount, nullptr); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModesKHR failed"); + VulkanError("vkGetPhysicalDeviceSurfacePresentModesKHR failed"); if (presentModeCount > 0) { caps.PresentModes.resize(presentModeCount); result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &presentModeCount, caps.PresentModes.data()); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModesKHR failed"); + VulkanError("vkGetPhysicalDeviceSurfacePresentModesKHR failed"); } } @@ -383,14 +386,14 @@ VulkanSurfaceCapabilities VulkanSwapChain::GetSurfaceCapabilities(bool exclusive uint32_t surfaceFormatCount = 0; VkResult result = vkGetPhysicalDeviceSurfaceFormats2KHR(device->PhysicalDevice.Device, &surfaceInfo, &surfaceFormatCount, nullptr); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormats2KHR failed"); + VulkanError("vkGetPhysicalDeviceSurfaceFormats2KHR failed"); if (surfaceFormatCount > 0) { std::vector formats(surfaceFormatCount, { VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR }); result = vkGetPhysicalDeviceSurfaceFormats2KHR(device->PhysicalDevice.Device, &surfaceInfo, &surfaceFormatCount, formats.data()); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormats2KHR failed"); + VulkanError("vkGetPhysicalDeviceSurfaceFormats2KHR failed"); for (VkSurfaceFormat2KHR& fmt : formats) caps.Formats.push_back(fmt.surfaceFormat); @@ -401,14 +404,14 @@ VulkanSurfaceCapabilities VulkanSwapChain::GetSurfaceCapabilities(bool exclusive uint32_t surfaceFormatCount = 0; VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceFormatCount, nullptr); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed"); + VulkanError("vkGetPhysicalDeviceSurfaceFormatsKHR failed"); if (surfaceFormatCount > 0) { caps.Formats.resize(surfaceFormatCount); result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceFormatCount, caps.Formats.data()); if (result != VK_SUCCESS) - throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed"); + VulkanError("vkGetPhysicalDeviceSurfaceFormatsKHR failed"); } } diff --git a/libraries/ZWidget/CMakeLists.txt b/libraries/ZWidget/CMakeLists.txt new file mode 100644 index 0000000000..9967b4ec61 --- /dev/null +++ b/libraries/ZWidget/CMakeLists.txt @@ -0,0 +1,159 @@ +cmake_minimum_required(VERSION 3.11) +project(zwidget) + +set(ZWIDGET_SOURCES + src/core/canvas.cpp + src/core/font.cpp + src/core/image.cpp + src/core/span_layout.cpp + src/core/timer.cpp + src/core/widget.cpp + src/core/theme.cpp + src/core/utf8reader.cpp + src/core/pathfill.cpp + src/core/truetypefont.cpp + src/core/truetypefont.h + src/core/picopng/picopng.cpp + src/core/picopng/picopng.h + src/core/nanosvg/nanosvg.cpp + src/core/nanosvg/nanosvg.h + src/core/nanosvg/nanosvgrast.h + src/widgets/lineedit/lineedit.cpp + src/widgets/mainwindow/mainwindow.cpp + src/widgets/menubar/menubar.cpp + src/widgets/scrollbar/scrollbar.cpp + src/widgets/statusbar/statusbar.cpp + src/widgets/textedit/textedit.cpp + src/widgets/toolbar/toolbar.cpp + src/widgets/toolbar/toolbarbutton.cpp + src/widgets/imagebox/imagebox.cpp + src/widgets/textlabel/textlabel.cpp + src/widgets/pushbutton/pushbutton.cpp + src/widgets/checkboxlabel/checkboxlabel.cpp + src/widgets/listview/listview.cpp + src/widgets/tabwidget/tabwidget.cpp + src/window/window.cpp + src/systemdialogs/folder_browse_dialog.cpp + src/systemdialogs/open_file_dialog.cpp + src/systemdialogs/save_file_dialog.cpp +) + +set(ZWIDGET_INCLUDES + include/zwidget/core/canvas.h + include/zwidget/core/colorf.h + include/zwidget/core/font.h + include/zwidget/core/image.h + include/zwidget/core/rect.h + include/zwidget/core/pathfill.h + include/zwidget/core/span_layout.h + include/zwidget/core/timer.h + include/zwidget/core/widget.h + include/zwidget/core/theme.h + include/zwidget/core/utf8reader.h + include/zwidget/core/resourcedata.h + include/zwidget/widgets/lineedit/lineedit.h + include/zwidget/widgets/mainwindow/mainwindow.h + include/zwidget/widgets/menubar/menubar.h + include/zwidget/widgets/scrollbar/scrollbar.h + include/zwidget/widgets/statusbar/statusbar.h + include/zwidget/widgets/textedit/textedit.h + include/zwidget/widgets/toolbar/toolbar.h + include/zwidget/widgets/toolbar/toolbarbutton.h + include/zwidget/widgets/imagebox/imagebox.h + include/zwidget/widgets/textlabel/textlabel.h + include/zwidget/widgets/pushbutton/pushbutton.h + include/zwidget/widgets/checkboxlabel/checkboxlabel.h + include/zwidget/widgets/listview/listview.h + include/zwidget/widgets/tabwidget/tabwidget.h + include/zwidget/window/window.h + include/zwidget/systemdialogs/folder_browse_dialog.h + include/zwidget/systemdialogs/open_file_dialog.h + include/zwidget/systemdialogs/save_file_dialog.h +) + +set(ZWIDGET_WIN32_SOURCES + src/window/win32/win32displaywindow.cpp + src/window/win32/win32displaywindow.h +) + +set(ZWIDGET_COCOA_SOURCES +) + +set(ZWIDGET_SDL2_SOURCES + src/window/sdl2/sdl2displaywindow.cpp + src/window/sdl2/sdl2displaywindow.h +) + +source_group("src" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/.+") +source_group("src\\core" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/core/.+") +source_group("src\\core\\picopng" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/core/picopng/.+") +source_group("src\\core\\nanosvg" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/core/nanosvg/.+") +source_group("src\\widgets" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/.+") +source_group("src\\widgets\\lineedit" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/lineedit/.+") +source_group("src\\widgets\\mainwindow" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/mainwindow/.+") +source_group("src\\widgets\\menubar" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/menubar/.+") +source_group("src\\widgets\\scrollbar" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/scrollbar/.+") +source_group("src\\widgets\\statusbar" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/statusbar/.+") +source_group("src\\widgets\\textedit" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/textedit/.+") +source_group("src\\widgets\\toolbar" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/toolbar/.+") +source_group("src\\widgets\\imagebox" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/imagebox/.+") +source_group("src\\widgets\\textlabel" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/textlabel/.+") +source_group("src\\widgets\\pushbutton" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/pushbutton/.+") +source_group("src\\widgets\\checkboxlabel" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/checkboxlabel/.+") +source_group("src\\widgets\\listview" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/listview/.+") +source_group("src\\widgets\\tabwidget" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/tabwidget/.+") +source_group("src\\window" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/window/.+") +source_group("src\\systemdialogs" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/systemdialogs/.+") +source_group("include" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/.+") +source_group("include\\core" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/core/.+") +source_group("include\\widgets" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/.+") +source_group("include\\widgets\\lineedit" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/lineedit/.+") +source_group("include\\widgets\\mainwindow" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/mainwindow/.+") +source_group("include\\widgets\\menubar" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/menubar/.+") +source_group("include\\widgets\\scrollbar" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/scrollbar/.+") +source_group("include\\widgets\\statusbar" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/statusbar/.+") +source_group("include\\widgets\\textedit" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/textedit/.+") +source_group("include\\widgets\\toolbar" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/toolbar/.+") +source_group("include\\widgets\\imagebox" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/imagebox/.+") +source_group("include\\widgets\\textlabel" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/textlabel/.+") +source_group("include\\widgets\\pushbutton" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/pushbutton/.+") +source_group("include\\widgets\\checkboxlabel" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/checkboxlabel/.+") +source_group("include\\widgets\\listview" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/listview/.+") +source_group("include\\widgets\\tabwidget" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/widgets/tabwidget/.+") +source_group("include\\window" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/window/.+") +source_group("include\\window\\win32" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/window/win32/.+") +source_group("include\\window\\sdl2" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/window/sdl2/.+") +source_group("include\\systemdialogs" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zwidget/systemdialogs/.+") + +include_directories(include include/zwidget src) + +if(WIN32) + set(ZWIDGET_SOURCES ${ZWIDGET_SOURCES} ${ZWIDGET_WIN32_SOURCES}) + add_definitions(-DUNICODE -D_UNICODE) +elseif(APPLE) + set(ZWIDGET_SOURCES ${ZWIDGET_SOURCES} ${ZWIDGET_COCOA_SOURCES}) + set(ZWIDGET_LIBS ${CMAKE_DL_LIBS} -ldl) + add_definitions(-DUNIX -D_UNIX) + add_link_options(-pthread) +else() + set(ZWIDGET_SOURCES ${ZWIDGET_SOURCES} ${ZWIDGET_SDL2_SOURCES}) + set(ZWIDGET_LIBS ${CMAKE_DL_LIBS} -ldl) + add_definitions(-DUNIX -D_UNIX) + add_link_options(-pthread) +endif() + +if(MSVC) + # Use all cores for compilation + set(CMAKE_CXX_FLAGS "/MP ${CMAKE_CXX_FLAGS}") + + # Ignore warnings in third party code + #set_source_files_properties(${ZWIDGET_SOURCES} PROPERTIES COMPILE_FLAGS "/wd4244 /wd4267 /wd4005 /wd4018 -D_CRT_SECURE_NO_WARNINGS") +endif() + +add_library(zwidget STATIC ${ZWIDGET_SOURCES} ${ZWIDGET_INCLUDES}) +target_link_libraries(zwidget ${ZWIDGET_LIBS}) +set_target_properties(zwidget PROPERTIES CXX_STANDARD 17) + +if(MSVC) + set_property(TARGET zwidget PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +endif() diff --git a/libraries/ZWidget/LICENSE.md b/libraries/ZWidget/LICENSE.md new file mode 100644 index 0000000000..fdc06221ca --- /dev/null +++ b/libraries/ZWidget/LICENSE.md @@ -0,0 +1,21 @@ +# License information + +## License for ZWidget itself + + // Copyright (c) 2023 Magnus Norddahl + // + // 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. diff --git a/libraries/ZWidget/README.md b/libraries/ZWidget/README.md new file mode 100644 index 0000000000..c3bb8e2194 --- /dev/null +++ b/libraries/ZWidget/README.md @@ -0,0 +1,2 @@ +# ZWidget +A framework for building user interface applications diff --git a/libraries/ZWidget/include/zwidget/core/canvas.h b/libraries/ZWidget/include/zwidget/core/canvas.h new file mode 100644 index 0000000000..a546e62cc8 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/canvas.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include + +class Font; +class Image; +class Point; +class Rect; +class Colorf; +class DisplayWindow; +struct VerticalTextPosition; + +class FontMetrics +{ +public: + double ascent = 0.0; + double descent = 0.0; + double external_leading = 0.0; + double height = 0.0; +}; + +class Canvas +{ +public: + static std::unique_ptr create(DisplayWindow* window); + + virtual ~Canvas() = default; + + virtual void begin(const Colorf& color) = 0; + virtual void end() = 0; + + virtual void begin3d() = 0; + virtual void end3d() = 0; + + virtual Point getOrigin() = 0; + virtual void setOrigin(const Point& origin) = 0; + + virtual void pushClip(const Rect& box) = 0; + virtual void popClip() = 0; + + virtual void fillRect(const Rect& box, const Colorf& color) = 0; + virtual void line(const Point& p0, const Point& p1, const Colorf& color) = 0; + + virtual void drawText(const Point& pos, const Colorf& color, const std::string& text) = 0; + virtual Rect measureText(const std::string& text) = 0; + virtual VerticalTextPosition verticalTextAlign() = 0; + + virtual void drawText(const std::shared_ptr& font, const Point& pos, const std::string& text, const Colorf& color) = 0; + virtual void drawTextEllipsis(const std::shared_ptr& font, const Point& pos, const Rect& clipBox, const std::string& text, const Colorf& color) = 0; + virtual Rect measureText(const std::shared_ptr& font, const std::string& text) = 0; + virtual FontMetrics getFontMetrics(const std::shared_ptr& font) = 0; + virtual int getCharacterIndex(const std::shared_ptr& font, const std::string& text, const Point& hitPoint) = 0; + + virtual void drawImage(const std::shared_ptr& image, const Point& pos) = 0; +}; + +struct VerticalTextPosition +{ + double top = 0.0; + double baseline = 0.0; + double bottom = 0.0; +}; diff --git a/libraries/ZWidget/include/zwidget/core/colorf.h b/libraries/ZWidget/include/zwidget/core/colorf.h new file mode 100644 index 0000000000..9352147990 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/colorf.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +class Colorf +{ +public: + Colorf() = default; + Colorf(float r, float g, float b, float a = 1.0f) : r(r), g(g), b(b), a(a) { } + + static Colorf transparent() { return { 0.0f, 0.0f, 0.0f, 0.0f }; } + + static Colorf fromRgba8(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) + { + float s = 1.0f / 255.0f; + return { r * s, g * s, b * s, a * s }; + } + + uint32_t toBgra8() const + { + uint32_t cr = (int)(std::max(std::min(r * 255.0f, 255.0f), 0.0f)); + uint32_t cg = (int)(std::max(std::min(g * 255.0f, 255.0f), 0.0f)); + uint32_t cb = (int)(std::max(std::min(b * 255.0f, 255.0f), 0.0f)); + uint32_t ca = (int)(std::max(std::min(a * 255.0f, 255.0f), 0.0f)); + return (ca << 24) | (cr << 16) | (cg << 8) | cb; + } + + bool operator==(const Colorf& v) const { return r == v.r && g == v.g && b == v.b && a == v.a; } + bool operator!=(const Colorf& v) const { return r != v.r || g != v.g || b != v.b || a != v.a; } + + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + float a = 1.0f; +}; diff --git a/libraries/ZWidget/include/zwidget/core/font.h b/libraries/ZWidget/include/zwidget/core/font.h new file mode 100644 index 0000000000..d4af360616 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/font.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +class Font +{ +public: + virtual ~Font() = default; + + virtual const std::string& GetName() const = 0; + virtual double GetHeight() const = 0; + + static std::shared_ptr Create(const std::string& name, double height); +}; diff --git a/libraries/ZWidget/include/zwidget/core/image.h b/libraries/ZWidget/include/zwidget/core/image.h new file mode 100644 index 0000000000..4cffc195ad --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/image.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +enum class ImageFormat +{ + R8G8B8A8, + B8G8R8A8 +}; + +class Image +{ +public: + virtual ~Image() = default; + + virtual int GetWidth() const = 0; + virtual int GetHeight() const = 0; + virtual ImageFormat GetFormat() const = 0; + virtual void* GetData() const = 0; + + static std::shared_ptr Create(int width, int height, ImageFormat format, const void* data); + static std::shared_ptr LoadResource(const std::string& resourcename, double dpiscale = 1.0); +}; diff --git a/libraries/ZWidget/include/zwidget/core/pathfill.h b/libraries/ZWidget/include/zwidget/core/pathfill.h new file mode 100644 index 0000000000..a6d749806f --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/pathfill.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include +#include +#include "core/rect.h" + +/* +// 3x3 transform matrix +class PathFillTransform +{ +public: + PathFillTransform() { for (int i = 0; i < 9; i++) matrix[i] = 0.0f; matrix[0] = matrix[4] = matrix[8] = 1.0; } + PathFillTransform(const float* mat3x3) { for (int i = 0; i < 9; i++) matrix[i] = (double)mat3x3[i]; } + PathFillTransform(const double* mat3x3) { for (int i = 0; i < 9; i++) matrix[i] = mat3x3[i]; } + + double matrix[9]; +}; +*/ + +enum class PathFillMode +{ + alternate, + winding +}; + +enum class PathFillCommand +{ + line, + quadradic, + cubic +}; + +class PathFillSubpath +{ +public: + PathFillSubpath() : points(1) { } + + std::vector points; + std::vector commands; + bool closed = false; +}; + +class PathFillDesc +{ +public: + PathFillDesc() : subpaths(1) { } + + PathFillMode fill_mode = PathFillMode::alternate; + std::vector subpaths; + + void MoveTo(const Point& point) + { + if (!subpaths.back().commands.empty()) + { + subpaths.push_back(PathFillSubpath()); + } + subpaths.back().points.front() = point; + } + + void LineTo(const Point& point) + { + auto& subpath = subpaths.back(); + subpath.points.push_back(point); + subpath.commands.push_back(PathFillCommand::line); + } + + void BezierTo(const Point& control, const Point& point) + { + auto& subpath = subpaths.back(); + subpath.points.push_back(control); + subpath.points.push_back(point); + subpath.commands.push_back(PathFillCommand::quadradic); + } + + void BezierTo(const Point& control1, const Point& control2, const Point& point) + { + auto& subpath = subpaths.back(); + subpath.points.push_back(control1); + subpath.points.push_back(control2); + subpath.points.push_back(point); + subpath.commands.push_back(PathFillCommand::cubic); + } + + void Close() + { + if (!subpaths.back().commands.empty()) + { + subpaths.back().closed = true; + subpaths.push_back(PathFillSubpath()); + } + } + + void Rasterize(uint8_t* dest, int width, int height, bool blend = false); +}; diff --git a/libraries/ZWidget/include/zwidget/core/rect.h b/libraries/ZWidget/include/zwidget/core/rect.h new file mode 100644 index 0000000000..ad2a4e09ca --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/rect.h @@ -0,0 +1,83 @@ +#pragma once + +class Point +{ +public: + Point() = default; + Point(double x, double y) : x(x), y(y) { } + + double x = 0; + double y = 0; + + Point& operator+=(const Point& p) { x += p.x; y += p.y; return *this; } + Point& operator-=(const Point& p) { x -= p.x; y -= p.y; return *this; } +}; + +class Size +{ +public: + Size() = default; + Size(double width, double height) : width(width), height(height) { } + + double width = 0; + double height = 0; +}; + +class Rect +{ +public: + Rect() = default; + Rect(const Point& p, const Size& s) : x(p.x), y(p.y), width(s.width), height(s.height) { } + Rect(double x, double y, double width, double height) : x(x), y(y), width(width), height(height) { } + + Point pos() const { return { x, y }; } + Size size() const { return { width, height }; } + + Point topLeft() const { return { x, y }; } + Point topRight() const { return { x + width, y }; } + Point bottomLeft() const { return { x, y + height }; } + Point bottomRight() const { return { x + width, y + height }; } + + double left() const { return x; } + double top() const { return y; } + double right() const { return x + width; } + double bottom() const { return y + height; } + + static Rect xywh(double x, double y, double width, double height) { return Rect(x, y, width, height); } + static Rect ltrb(double left, double top, double right, double bottom) { return Rect(left, top, right - left, bottom - top); } + + static Rect shrink(Rect box, double left, double top, double right, double bottom) + { + box.x += left; + box.y += top; + box.width = std::max(box.width - left - right, 0.0); + box.height = std::max(box.height - bottom - top, 0.0); + return box; + } + + bool contains(const Point& p) const { return (p.x >= x && p.x < x + width) && (p.y >= y && p.y < y + height); } + + double x = 0; + double y = 0; + double width = 0; + double height = 0; +}; + +inline Point operator+(const Point& a, const Point& b) { return Point(a.x + b.x, a.y + b.y); } +inline Point operator-(const Point& a, const Point& b) { return Point(a.x - b.x, a.y - b.y); } +inline bool operator==(const Point& a, const Point& b) { return a.x == b.x && a.y == b.y; } +inline bool operator!=(const Point& a, const Point& b) { return a.x != b.x || a.y != b.y; } +inline bool operator==(const Size& a, const Size& b) { return a.width == b.width && a.height == b.height; } +inline bool operator!=(const Size& a, const Size& b) { return a.width != b.width || a.height != b.height; } +inline bool operator==(const Rect& a, const Rect& b) { return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height; } +inline bool operator!=(const Rect& a, const Rect& b) { return a.x != b.x || a.y != b.y || a.width != b.width || a.height != b.height; } + +inline Point operator+(const Point& a, double b) { return Point(a.x + b, a.y + b); } +inline Point operator-(const Point& a, double b) { return Point(a.x - b, a.y - b); } +inline Point operator*(const Point& a, double b) { return Point(a.x * b, a.y * b); } +inline Point operator/(const Point& a, double b) { return Point(a.x / b, a.y / b); } + +inline Size operator+(const Size& a, double b) { return Size(a.width + b, a.height + b); } +inline Size operator-(const Size& a, double b) { return Size(a.width - b, a.height - b); } +inline Size operator*(const Size& a, double b) { return Size(a.width * b, a.height * b); } +inline Size operator/(const Size& a, double b) { return Size(a.width / b, a.height / b); } diff --git a/libraries/ZWidget/include/zwidget/core/resourcedata.h b/libraries/ZWidget/include/zwidget/core/resourcedata.h new file mode 100644 index 0000000000..f29ab261e5 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/resourcedata.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include + +struct SingleFontData +{ + std::vector fontdata; + std::string language; +}; + +std::vector LoadWidgetFontData(const std::string& name); +std::vector LoadWidgetData(const std::string& name); diff --git a/libraries/ZWidget/include/zwidget/core/span_layout.h b/libraries/ZWidget/include/zwidget/core/span_layout.h new file mode 100644 index 0000000000..974feca405 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/span_layout.h @@ -0,0 +1,238 @@ +#pragma once + +#include +#include + +#include "colorf.h" +#include "rect.h" +#include "font.h" +#include "canvas.h" + +class Widget; +class Image; +class Canvas; + +enum SpanAlign +{ + span_left, + span_right, + span_center, + span_justify +}; + +class SpanLayout +{ +public: + SpanLayout(); + ~SpanLayout(); + + struct HitTestResult + { + enum Type + { + no_objects_available, + outside_top, + outside_left, + outside_right, + outside_bottom, + inside + }; + + Type type = {}; + int object_id = -1; + size_t offset = 0; + }; + + void Clear(); + + void AddText(const std::string& text, std::shared_ptr font, const Colorf& color = Colorf(), int id = -1); + void AddImage(const std::shared_ptr image, double baseline_offset = 0, int id = -1); + void AddWidget(Widget* component, double baseline_offset = 0, int id = -1); + + void Layout(Canvas* canvas, double max_width); + + void SetPosition(const Point& pos); + + Size GetSize() const; + Rect GetRect() const; + + std::vector GetRectById(int id) const; + + HitTestResult HitTest(Canvas* canvas, const Point& pos); + + void DrawLayout(Canvas* canvas); + + /// Draw layout generating ellipsis for clipped text + void DrawLayoutEllipsis(Canvas* canvas, const Rect& content_rect); + + void SetComponentGeometry(); + + Size FindPreferredSize(Canvas* canvas); + + void SetSelectionRange(std::string::size_type start, std::string::size_type end); + void SetSelectionColors(const Colorf& foreground, const Colorf& background); + + void ShowCursor(); + void HideCursor(); + + void SetCursorPos(std::string::size_type pos); + void SetCursorOverwriteMode(bool enable); + void SetCursorColor(const Colorf& color); + + std::string GetCombinedText() const; + + void SetAlign(SpanAlign align); + + double GetFirstBaselineOffset(); + double GetLastBaselineOffset(); + +private: + struct TextBlock + { + size_t start = 0; + size_t end = 0; + }; + + enum ObjectType + { + object_text, + object_image, + object_component + }; + + enum FloatType + { + float_none, + float_left, + float_right + }; + + struct SpanObject + { + ObjectType type = object_text; + FloatType float_type = float_none; + + std::shared_ptr font; + Colorf color; + size_t start = 0, end = 0; + + std::shared_ptr image; + Widget* component = nullptr; + double baseline_offset = 0; + + int id = -1; + }; + + struct LineSegment + { + ObjectType type = object_text; + + std::shared_ptr font; + Colorf color; + size_t start = 0; + size_t end = 0; + double ascender = 0; + double descender = 0; + + double x_position = 0; + double width = 0; + + std::shared_ptr image; + Widget* component = nullptr; + double baseline_offset = 0; + + int id = -1; + }; + + struct Line + { + double width = 0; // Width of the entire line (including spaces) + double height = 0; + double ascender = 0; + std::vector segments; + }; + + struct TextSizeResult + { + size_t start = 0; + size_t end = 0; + double width = 0; + double height = 0; + double ascender = 0; + double descender = 0; + int objects_traversed = 0; + std::vector segments; + }; + + struct CurrentLine + { + std::vector::size_type object_index = 0; + Line cur_line; + double x_position = 0; + double y_position = 0; + }; + + struct FloatBox + { + Rect rect; + ObjectType type = object_image; + std::shared_ptr image; + Widget* component = nullptr; + int id = -1; + }; + + TextSizeResult FindTextSize(Canvas* canvas, const TextBlock& block, size_t object_index); + std::vector FindTextBlocks(); + void LayoutLines(Canvas* canvas, double max_width); + void LayoutText(Canvas* canvas, std::vector blocks, std::vector::size_type block_index, CurrentLine& current_line, double max_width); + void LayoutBlock(CurrentLine& current_line, double max_width, std::vector& blocks, std::vector::size_type block_index); + void LayoutFloatBlock(CurrentLine& current_line, double max_width); + void LayoutInlineBlock(CurrentLine& current_line, double max_width, std::vector& blocks, std::vector::size_type block_index); + void ReflowLine(CurrentLine& current_line, double max_width); + FloatBox FloatBoxLeft(FloatBox float_box, double max_width); + FloatBox FloatBoxRight(FloatBox float_box, double max_width); + FloatBox FloatBoxAny(FloatBox box, double max_width, const std::vector& floats1); + bool BoxFitsOnLine(const FloatBox& box, double max_width); + void PlaceLineSegments(CurrentLine& current_line, TextSizeResult& text_size_result); + void ForcePlaceLineSegments(CurrentLine& current_line, TextSizeResult& text_size_result, double max_width); + void NextLine(CurrentLine& current_line); + bool IsNewline(const TextBlock& block); + bool IsWhitespace(const TextBlock& block); + bool FitsOnLine(double x_position, const TextSizeResult& text_size_result, double max_width); + bool LargerThanLine(const TextSizeResult& text_size_result, double max_width); + void AlignJustify(double max_width); + void AlignCenter(double max_width); + void AlignRight(double max_width); + void DrawLayoutImage(Canvas* canvas, Line& line, LineSegment& segment, double x, double y); + void DrawLayoutText(Canvas* canvas, Line& line, LineSegment& segment, double x, double y); + + bool cursor_visible = false; + std::string::size_type cursor_pos = 0; + bool cursor_overwrite_mode = false; + Colorf cursor_color; + + std::string::size_type sel_start = 0, sel_end = 0; + Colorf sel_foreground, sel_background = Colorf::fromRgba8(153, 201, 239); + + std::string text; + std::vector objects; + std::vector lines; + Point position; + + std::vector floats_left, floats_right; + + SpanAlign alignment = span_left; + + struct LayoutCache + { + int object_index = -1; + FontMetrics metrics; + }; + LayoutCache layout_cache; + + bool is_ellipsis_draw = false; + Rect ellipsis_content_rect; + + template + static T clamp(T val, T minval, T maxval) { return std::max(std::min(val, maxval), minval); } +}; diff --git a/libraries/ZWidget/include/zwidget/core/theme.h b/libraries/ZWidget/include/zwidget/core/theme.h new file mode 100644 index 0000000000..5a5271bc35 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/theme.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include +#include +#include +#include "rect.h" +#include "colorf.h" + +class Widget; +class Canvas; + +class WidgetStyle +{ +public: + WidgetStyle(WidgetStyle* parentStyle = nullptr) : ParentStyle(parentStyle) { } + virtual ~WidgetStyle() = default; + virtual void Paint(Widget* widget, Canvas* canvas, Size size) = 0; + + void SetBool(const std::string& state, const std::string& propertyName, bool value); + void SetInt(const std::string& state, const std::string& propertyName, int value); + void SetDouble(const std::string& state, const std::string& propertyName, double value); + void SetString(const std::string& state, const std::string& propertyName, const std::string& value); + void SetColor(const std::string& state, const std::string& propertyName, const Colorf& value); + + void SetBool(const std::string& propertyName, bool value) { SetBool(std::string(), propertyName, value); } + void SetInt(const std::string& propertyName, int value) { SetInt(std::string(), propertyName, value); } + void SetDouble(const std::string& propertyName, double value) { SetDouble(std::string(), propertyName, value); } + void SetString(const std::string& propertyName, const std::string& value) { SetString(std::string(), propertyName, value); } + void SetColor(const std::string& propertyName, const Colorf& value) { SetColor(std::string(), propertyName, value); } + +private: + // Note: do not call these directly. Use widget->GetStyleXX instead since a widget may explicitly override a class style + bool GetBool(const std::string& state, const std::string& propertyName) const; + int GetInt(const std::string& state, const std::string& propertyName) const; + double GetDouble(const std::string& state, const std::string& propertyName) const; + std::string GetString(const std::string& state, const std::string& propertyName) const; + Colorf GetColor(const std::string& state, const std::string& propertyName) const; + + WidgetStyle* ParentStyle = nullptr; + typedef std::variant PropertyVariant; + std::unordered_map> StyleProperties; + + const PropertyVariant* FindProperty(const std::string& state, const std::string& propertyName) const; + + friend class Widget; +}; + +class BasicWidgetStyle : public WidgetStyle +{ +public: + using WidgetStyle::WidgetStyle; + void Paint(Widget* widget, Canvas* canvas, Size size) override; +}; + +class WidgetTheme +{ +public: + virtual ~WidgetTheme() = default; + + WidgetStyle* RegisterStyle(std::unique_ptr widgetStyle, const std::string& widgetClass); + WidgetStyle* GetStyle(const std::string& widgetClass); + + static void SetTheme(std::unique_ptr theme); + static WidgetTheme* GetTheme(); + +private: + std::unordered_map> Styles; +}; + +class DarkWidgetTheme : public WidgetTheme +{ +public: + DarkWidgetTheme(); +}; + +class LightWidgetTheme : public WidgetTheme +{ +public: + LightWidgetTheme(); +}; diff --git a/libraries/ZWidget/include/zwidget/core/timer.h b/libraries/ZWidget/include/zwidget/core/timer.h new file mode 100644 index 0000000000..25e6fb3461 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/timer.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +class Widget; + +class Timer +{ +public: + Timer(Widget* owner); + ~Timer(); + + void Start(int timeoutMilliseconds, bool repeat = true); + void Stop(); + + std::function FuncExpired; + +private: + Widget* OwnerObj = nullptr; + Timer* PrevTimerObj = nullptr; + Timer* NextTimerObj = nullptr; + + void* TimerId = nullptr; + + friend class Widget; +}; diff --git a/libraries/ZWidget/include/zwidget/core/utf8reader.h b/libraries/ZWidget/include/zwidget/core/utf8reader.h new file mode 100644 index 0000000000..f9c186b47d --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/utf8reader.h @@ -0,0 +1,78 @@ +/* +** Copyright (c) 1997-2015 Mark Page +** +** 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. +** +*/ + +#pragma once + +#include + +/// \brief UTF8 reader helper functions. +class UTF8Reader +{ +public: + /// Important: text is not copied by this class and must remain valid during its usage. + UTF8Reader(const std::string::value_type *text, std::string::size_type length); + + /// \brief Returns true if the current position is at the end of the string + bool is_end(); + + /// \brief Get the character at the current position + unsigned int character(); + + /// \brief Returns the length of the current character + std::string::size_type char_length(); + + /// \brief Moves position to the previous character + void prev(); + + /// \brief Moves position to the next character + void next(); + + /// \brief Moves position to the lead byte of the character + void move_to_leadbyte(); + + /// \brief Get the current position of the reader + std::string::size_type position(); + + /// \brief Set the current position of the reader + void set_position(std::string::size_type position); + + static size_t utf8_length(const std::string& text) + { + return utf8_length(text.data(), text.size()); + } + + static size_t utf8_length(const std::string::value_type* text, std::string::size_type length) + { + UTF8Reader reader(text, length); + size_t i = 0; + while (!reader.is_end()) + { + reader.next(); + i++; + } + return i; + } + +private: + std::string::size_type current_position = 0; + std::string::size_type length = 0; + const unsigned char *data = nullptr; +}; diff --git a/libraries/ZWidget/include/zwidget/core/widget.h b/libraries/ZWidget/include/zwidget/core/widget.h new file mode 100644 index 0000000000..2c17507fd2 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/core/widget.h @@ -0,0 +1,223 @@ +#pragma once + +#include +#include +#include +#include +#include "canvas.h" +#include "rect.h" +#include "colorf.h" +#include "../window/window.h" + +class Canvas; +class Timer; + +enum class WidgetType +{ + Child, + Window, + Popup +}; + +class Widget : DisplayWindowHost +{ +public: + Widget(Widget* parent = nullptr, WidgetType type = WidgetType::Child); + virtual ~Widget(); + + void SetParent(Widget* parent); + void MoveBefore(Widget* sibling); + + std::string GetWindowTitle() const; + void SetWindowTitle(const std::string& text); + + // Icon GetWindowIcon() const; + // void SetWindowIcon(const Icon& icon); + + // Widget content box + Size GetSize() const; + double GetWidth() const { return GetSize().width; } + double GetHeight() const { return GetSize().height; } + + // Widget noncontent area + void SetNoncontentSizes(double left, double top, double right, double bottom); + double GetNoncontentLeft() const { return GridFitSize(GetStyleDouble("noncontent-left")); } + double GetNoncontentTop() const { return GridFitSize(GetStyleDouble("noncontent-top")); } + double GetNoncontentRight() const { return GridFitSize(GetStyleDouble("noncontent-right")); } + double GetNoncontentBottom() const { return GridFitSize(GetStyleDouble("noncontent-bottom")); } + + // Get the DPI scale factor for the window the widget is located on + double GetDpiScale() const; + + // Align point to the nearest physical screen pixel + double GridFitPoint(double p) const; + Point GridFitPoint(double x, double y) const { return GridFitPoint(Point(x, y)); } + Point GridFitPoint(Point p) const { return Point(GridFitPoint(p.x), GridFitPoint(p.y)); } + + // Convert size to exactly covering physical screen pixels + double GridFitSize(double s) const; + Size GridFitSize(double w, double h) const { return GridFitSize(Size(w, h)); } + Size GridFitSize(Size s) const { return Size(GridFitSize(s.width), GridFitSize(s.height)); } + + // Widget frame box + Rect GetFrameGeometry() const; + void SetFrameGeometry(const Rect& geometry); + void SetFrameGeometry(double x, double y, double width, double height) { SetFrameGeometry(Rect::xywh(x, y, width, height)); } + + // Style properties + void SetStyleClass(const std::string& styleClass); + const std::string& GetStyleClass() const { return StyleClass; } + void SetStyleState(const std::string& state); + const std::string& GetStyleState() const { return StyleState; } + void SetStyleBool(const std::string& propertyName, bool value); + void SetStyleInt(const std::string& propertyName, int value); + void SetStyleDouble(const std::string& propertyName, double value); + void SetStyleString(const std::string& propertyName, const std::string& value); + void SetStyleColor(const std::string& propertyName, const Colorf& value); + bool GetStyleBool(const std::string& propertyName) const; + int GetStyleInt(const std::string& propertyName) const; + double GetStyleDouble(const std::string& propertyName) const; + std::string GetStyleString(const std::string& propertyName) const; + Colorf GetStyleColor(const std::string& propertyName) const; + + void SetWindowBackground(const Colorf& color); + void SetWindowBorderColor(const Colorf& color); + void SetWindowCaptionColor(const Colorf& color); + void SetWindowCaptionTextColor(const Colorf& color); + + void SetVisible(bool enable) { if (enable) Show(); else Hide(); } + void Show(); + void ShowFullscreen(); + void ShowMaximized(); + void ShowMinimized(); + void ShowNormal(); + void Hide(); + + void ActivateWindow(); + + void Close(); + + void Update(); + void Repaint(); + + bool HasFocus(); + bool IsEnabled(); + bool IsVisible(); + bool IsHidden(); + + void SetFocus(); + void SetEnabled(bool value); + void SetDisabled(bool value) { SetEnabled(!value); } + void SetHidden(bool value) { if (value) Hide(); else Show(); } + + void LockCursor(); + void UnlockCursor(); + void SetCursor(StandardCursor cursor); + void CaptureMouse(); + void ReleaseMouseCapture(); + + bool GetKeyState(InputKey key); + + std::string GetClipboardText(); + void SetClipboardText(const std::string& text); + + Widget* Window() const; + Canvas* GetCanvas() const; + Widget* ChildAt(double x, double y) { return ChildAt(Point(x, y)); } + Widget* ChildAt(const Point& pos); + + Widget* Parent() const { return ParentObj; } + Widget* PrevSibling() const { return PrevSiblingObj; } + Widget* NextSibling() const { return NextSiblingObj; } + Widget* FirstChild() const { return FirstChildObj; } + Widget* LastChild() const { return LastChildObj; } + + Point MapFrom(const Widget* parent, const Point& pos) const; + Point MapFromGlobal(const Point& pos) const; + Point MapFromParent(const Point& pos) const { return MapFrom(Parent(), pos); } + + Point MapTo(const Widget* parent, const Point& pos) const; + Point MapToGlobal(const Point& pos) const; + Point MapToParent(const Point& pos) const { return MapTo(Parent(), pos); } + + static Size GetScreenSize(); + + void* GetNativeHandle(); + +protected: + virtual void OnPaintFrame(Canvas* canvas); + virtual void OnPaint(Canvas* canvas) { } + virtual bool OnMouseDown(const Point& pos, InputKey key) { return false; } + virtual bool OnMouseDoubleclick(const Point& pos, InputKey key) { return false; } + virtual bool OnMouseUp(const Point& pos, InputKey key) { return false; } + virtual bool OnMouseWheel(const Point& pos, InputKey key) { return false; } + virtual void OnMouseMove(const Point& pos) { } + virtual void OnMouseLeave() { } + virtual void OnRawMouseMove(int dx, int dy) { } + virtual void OnKeyChar(std::string chars) { } + virtual void OnKeyDown(InputKey key) { } + virtual void OnKeyUp(InputKey key) { } + virtual void OnGeometryChanged() { } + virtual void OnClose() { delete this; } + virtual void OnSetFocus() { } + virtual void OnLostFocus() { } + virtual void OnEnableChanged() { } + +private: + void DetachFromParent(); + + void Paint(Canvas* canvas); + + // DisplayWindowHost + void OnWindowPaint() override; + void OnWindowMouseMove(const Point& pos) override; + void OnWindowMouseLeave() override; + void OnWindowMouseDown(const Point& pos, InputKey key) override; + void OnWindowMouseDoubleclick(const Point& pos, InputKey key) override; + void OnWindowMouseUp(const Point& pos, InputKey key) override; + void OnWindowMouseWheel(const Point& pos, InputKey key) override; + void OnWindowRawMouseMove(int dx, int dy) override; + void OnWindowKeyChar(std::string chars) override; + void OnWindowKeyDown(InputKey key) override; + void OnWindowKeyUp(InputKey key) override; + void OnWindowGeometryChanged() override; + void OnWindowClose() override; + void OnWindowActivated() override; + void OnWindowDeactivated() override; + void OnWindowDpiScaleChanged() override; + + WidgetType Type = {}; + + Widget* ParentObj = nullptr; + Widget* PrevSiblingObj = nullptr; + Widget* NextSiblingObj = nullptr; + Widget* FirstChildObj = nullptr; + Widget* LastChildObj = nullptr; + + Timer* FirstTimerObj = nullptr; + + Rect FrameGeometry = Rect::xywh(0.0, 0.0, 0.0, 0.0); + Rect ContentGeometry = Rect::xywh(0.0, 0.0, 0.0, 0.0); + + Colorf WindowBackground = Colorf::fromRgba8(240, 240, 240); + + std::string WindowTitle; + std::unique_ptr DispWindow; + std::unique_ptr DispCanvas; + Widget* FocusWidget = nullptr; + Widget* CaptureWidget = nullptr; + Widget* HoverWidget = nullptr; + bool HiddenFlag = false; + + StandardCursor CurrentCursor = StandardCursor::arrow; + + std::string StyleClass = "widget"; + std::string StyleState; + typedef std::variant PropertyVariant; + std::unordered_map StyleProperties; + + Widget(const Widget&) = delete; + Widget& operator=(const Widget&) = delete; + + friend class Timer; +}; diff --git a/libraries/ZWidget/include/zwidget/systemdialogs/folder_browse_dialog.h b/libraries/ZWidget/include/zwidget/systemdialogs/folder_browse_dialog.h new file mode 100644 index 0000000000..991869a5a1 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/systemdialogs/folder_browse_dialog.h @@ -0,0 +1,30 @@ + +#pragma once + +#include +#include + +class Widget; + +/// \brief Displays the system folder browsing dialog +class BrowseFolderDialog +{ +public: + /// \brief Constructs an browse folder dialog. + static std::unique_ptr Create(Widget*owner); + + virtual ~BrowseFolderDialog() = default; + + /// \brief Get the full path of the directory selected. + virtual std::string SelectedPath() const = 0; + + /// \brief Sets the initial directory that is displayed. + virtual void SetInitialDirectory(const std::string& path) = 0; + + /// \brief Sets the text that appears in the title bar. + virtual void SetTitle(const std::string& title) = 0; + + /// \brief Shows the file dialog. + /// \return true if the user clicks the OK button of the dialog that is displayed, false otherwise. + virtual bool Show() = 0; +}; diff --git a/libraries/ZWidget/include/zwidget/systemdialogs/open_file_dialog.h b/libraries/ZWidget/include/zwidget/systemdialogs/open_file_dialog.h new file mode 100644 index 0000000000..29ede966ed --- /dev/null +++ b/libraries/ZWidget/include/zwidget/systemdialogs/open_file_dialog.h @@ -0,0 +1,55 @@ + +#pragma once + +#include +#include +#include + +class Widget; + +/// \brief Displays the system open file dialog. +class OpenFileDialog +{ +public: + /// \brief Constructs an open file dialog. + static std::unique_ptr Create(Widget* owner); + + virtual ~OpenFileDialog() = default; + + /// \brief Get the full path of the file selected. + /// + /// If multiple files are selected, this returns the first file. + virtual std::string Filename() const = 0; + + /// \brief Gets an array that contains one file name for each selected file. + virtual std::vector Filenames() const = 0; + + /// \brief Sets if multiple files can be selected or not. + /// \param multiselect = When true, multiple items can be selected. + virtual void SetMultiSelect(bool multiselect) = 0; + + /// \brief Sets a string containing the full path of the file selected. + virtual void SetFilename(const std::string &filename) = 0; + + /// \brief Sets the default extension to use. + virtual void SetDefaultExtension(const std::string& extension) = 0; + + /// \brief Add a filter that determines what types of files are displayed. + virtual void AddFilter(const std::string &filter_description, const std::string &filter_extension) = 0; + + /// \brief Clears all filters. + virtual void ClearFilters() = 0; + + /// \brief Sets a default filter, on a 0-based index. + virtual void SetFilterIndex(int filter_index) = 0; + + /// \brief Sets the initial directory that is displayed. + virtual void SetInitialDirectory(const std::string &path) = 0; + + /// \brief Sets the text that appears in the title bar. + virtual void SetTitle(const std::string &title) = 0; + + /// \brief Shows the file dialog. + /// \return true if the user clicks the OK button of the dialog that is displayed, false otherwise. + virtual bool Show() = 0; +}; diff --git a/libraries/ZWidget/include/zwidget/systemdialogs/save_file_dialog.h b/libraries/ZWidget/include/zwidget/systemdialogs/save_file_dialog.h new file mode 100644 index 0000000000..ce10a127f3 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/systemdialogs/save_file_dialog.h @@ -0,0 +1,46 @@ + +#pragma once + +#include +#include +#include + +class Widget; + +/// \brief Displays the system save file dialog. +class SaveFileDialog +{ +public: + /// \brief Constructs a save file dialog. + static std::unique_ptr Create(Widget *owner); + + virtual ~SaveFileDialog() = default; + + /// \brief Get the full path of the file selected. + virtual std::string Filename() const = 0; + + /// \brief Sets a string containing the full path of the file selected. + virtual void SetFilename(const std::string &filename) = 0; + + /// \brief Sets the default extension to use. + virtual void SetDefaultExtension(const std::string& extension) = 0; + + /// \brief Add a filter that determines what types of files are displayed. + virtual void AddFilter(const std::string &filter_description, const std::string &filter_extension) = 0; + + /// \brief Clears all filters. + virtual void ClearFilters() = 0; + + /// \brief Sets a default filter, on a 0-based index. + virtual void SetFilterIndex(int filter_index) = 0; + + /// \brief Sets the initial directory that is displayed. + virtual void SetInitialDirectory(const std::string &path) = 0; + + /// \brief Sets the text that appears in the title bar. + virtual void SetTitle(const std::string &title) = 0; + + /// \brief Shows the file dialog. + /// \return true if the user clicks the OK button of the dialog that is displayed, false otherwise. + virtual bool Show() = 0; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/checkboxlabel/checkboxlabel.h b/libraries/ZWidget/include/zwidget/widgets/checkboxlabel/checkboxlabel.h new file mode 100644 index 0000000000..21ce0b697c --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/checkboxlabel/checkboxlabel.h @@ -0,0 +1,34 @@ + +#pragma once + +#include "../../core/widget.h" + +class CheckboxLabel : public Widget +{ +public: + CheckboxLabel(Widget* parent = nullptr); + + void SetText(const std::string& value); + const std::string& GetText() const; + + void SetChecked(bool value); + bool GetChecked() const; + void Toggle(); + + double GetPreferredHeight() const; + std::function FuncChanged; + void SetRadioStyle(bool on) { radiostyle = on; } + +protected: + void OnPaint(Canvas* canvas) override; + bool OnMouseDown(const Point& pos, InputKey key) override; + bool OnMouseUp(const Point& pos, InputKey key) override; + void OnMouseLeave() override; + void OnKeyUp(InputKey key) override; + +private: + std::string text; + bool checked = false; + bool radiostyle = false; + bool mouseDownActive = false; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/imagebox/imagebox.h b/libraries/ZWidget/include/zwidget/widgets/imagebox/imagebox.h new file mode 100644 index 0000000000..7d3aa520e5 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/imagebox/imagebox.h @@ -0,0 +1,22 @@ + +#pragma once + +#include "../../core/widget.h" +#include "../../core/image.h" + +class ImageBox : public Widget +{ +public: + ImageBox(Widget* parent); + + void SetImage(std::shared_ptr newImage); + + double GetPreferredWidth() const; + double GetPreferredHeight() const; + +protected: + void OnPaint(Canvas* canvas) override; + +private: + std::shared_ptr image; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/lineedit/lineedit.h b/libraries/ZWidget/include/zwidget/widgets/lineedit/lineedit.h new file mode 100644 index 0000000000..8c5dcfa89e --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/lineedit/lineedit.h @@ -0,0 +1,159 @@ + +#pragma once + +#include "../../core/widget.h" +#include "../../core/timer.h" +#include + +class LineEdit : public Widget +{ +public: + LineEdit(Widget* parent); + ~LineEdit(); + + enum Alignment + { + align_left, + align_center, + align_right + }; + + Alignment GetAlignment() const; + bool IsReadOnly() const; + bool IsLowercase() const; + bool IsUppercase() const; + bool IsPasswordMode() const; + int GetMaxLength() const; + + std::string GetText() const; + int GetTextInt() const; + float GetTextFloat() const; + + std::string GetSelection() const; + int GetSelectionStart() const; + int GetSelectionLength() const; + + int GetCursorPos() const; + Size GetTextSize(); + + Size GetTextSize(const std::string& str); + double GetPreferredContentWidth(); + double GetPreferredContentHeight(double width); + + void SetSelectAllOnFocusGain(bool enable); + void SelectAll(); + void SetAlignment(Alignment alignment); + void SetReadOnly(bool enable = true); + void SetLowercase(bool enable = true); + void SetUppercase(bool enable = true); + void SetPasswordMode(bool enable = true); + void SetNumericMode(bool enable = true, bool decimals = false); + void SetMaxLength(int length); + void SetText(const std::string& text); + void SetTextInt(int number); + void SetTextFloat(float number, int num_decimal_places = 6); + void SetSelection(int pos, int length); + void ClearSelection(); + void SetCursorPos(int pos); + void DeleteSelectedText(); + void SetInputMask(const std::string& mask); + void SetDecimalCharacter(const std::string& decimal_char); + + std::function FuncIgnoreKeyDown; + std::function FuncFilterKeyChar; + std::function FuncBeforeEditChanged; + std::function FuncAfterEditChanged; + std::function FuncSelectionChanged; + std::function FuncFocusGained; + std::function FuncFocusLost; + std::function FuncEnterPressed; + +protected: + void OnPaint(Canvas* canvas) override; + void OnMouseMove(const Point& pos) override; + bool OnMouseDown(const Point& pos, InputKey key) override; + bool OnMouseDoubleclick(const Point& pos, InputKey key) override; + bool OnMouseUp(const Point& pos, InputKey key) override; + void OnKeyChar(std::string chars) override; + void OnKeyDown(InputKey key) override; + void OnKeyUp(InputKey key) override; + void OnGeometryChanged() override; + void OnEnableChanged() override; + void OnSetFocus() override; + void OnLostFocus() override; + +private: + void OnTimerExpired(); + void OnScrollTimerExpired(); + void UpdateTextClipping(); + + void Move(int steps, bool ctrl, bool shift); + bool InsertText(int pos, const std::string& str); + void Backspace(); + void Del(); + int GetCharacterIndex(double x); + int FindNextBreakCharacter(int pos); + int FindPreviousBreakCharacter(int pos); + std::string GetVisibleTextBeforeSelection(); + std::string GetVisibleTextAfterSelection(); + std::string GetVisibleSelectedText(); + std::string CreatePassword(std::string::size_type num_letters) const; + Size GetVisualTextSize(Canvas* canvas, int pos, int npos) const; + Size GetVisualTextSize(Canvas* canvas) const; + Rect GetCursorRect(); + Rect GetSelectionRect(); + bool InputMaskAcceptsInput(int cursor_pos, const std::string& str); + void SetSelectionStart(int start); + void SetSelectionLength(int length); + void SetTextSelection(int start, int length); + + static std::string ToFixed(float number, int num_decimal_places); + static std::string ToLower(const std::string& text); + static std::string ToUpper(const std::string& text); + + Timer* timer = nullptr; + std::string text; + Alignment alignment = align_left; + int cursor_pos = 0; + int max_length = -1; + bool mouse_selecting = false; + bool lowercase = false; + bool uppercase = false; + bool password_mode = false; + bool numeric_mode = false; + bool numeric_mode_decimals = false; + bool readonly = false; + int selection_start = -1; + int selection_length = 0; + std::string input_mask; + std::string decimal_char = "."; + + VerticalTextPosition vertical_text_align; + Timer* scroll_timer = nullptr; + + bool mouse_moves_left = false; + bool cursor_blink_visible = true; + unsigned int blink_timer = 0; + int clip_start_offset = 0; + int clip_end_offset = 0; + bool ignore_mouse_events = false; + + struct UndoInfo + { + /* set undo text when: + - added char after moving + - destructive block operation (del, cut etc) + - beginning erase + */ + std::string undo_text; + bool first_erase = false; + bool first_text_insert = false; + }; + + UndoInfo undo_info; + + bool select_all_on_focus_gain = true; + + static const std::string break_characters; + static const std::string numeric_mode_characters; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/listview/listview.h b/libraries/ZWidget/include/zwidget/widgets/listview/listview.h new file mode 100644 index 0000000000..3d31703912 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/listview/listview.h @@ -0,0 +1,38 @@ + +#pragma once + +#include "../../core/widget.h" +#include +#include + +class Scrollbar; + +class ListView : public Widget +{ +public: + ListView(Widget* parent = nullptr); + + void AddItem(const std::string& text); + int GetSelectedItem() const { return selectedItem; } + void SetSelectedItem(int index); + void ScrollToItem(int index); + + void Activate(); + + std::function OnChanged; + std::function OnActivated; + +protected: + void OnPaint(Canvas* canvas) override; + bool OnMouseDown(const Point& pos, InputKey key) override; + bool OnMouseDoubleclick(const Point& pos, InputKey key) override; + bool OnMouseWheel(const Point& pos, InputKey key) override; + void OnKeyDown(InputKey key) override; + void OnGeometryChanged() override; + void OnScrollbarScroll(); + + Scrollbar* scrollbar = nullptr; + + std::vector items; + int selectedItem = 0; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/mainwindow/mainwindow.h b/libraries/ZWidget/include/zwidget/widgets/mainwindow/mainwindow.h new file mode 100644 index 0000000000..abba23d6c4 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/mainwindow/mainwindow.h @@ -0,0 +1,31 @@ + +#pragma once + +#include "../../core/widget.h" + +class Menubar; +class Toolbar; +class Statusbar; + +class MainWindow : public Widget +{ +public: + MainWindow(); + ~MainWindow(); + + Menubar* GetMenubar() const { return MenubarWidget; } + Toolbar* GetToolbar() const { return ToolbarWidget; } + Statusbar* GetStatusbar() const { return StatusbarWidget; } + Widget* GetCentralWidget() const { return CentralWidget; } + + void SetCentralWidget(Widget* widget); + +protected: + void OnGeometryChanged() override; + +private: + Menubar* MenubarWidget = nullptr; + Toolbar* ToolbarWidget = nullptr; + Widget* CentralWidget = nullptr; + Statusbar* StatusbarWidget = nullptr; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/menubar/menubar.h b/libraries/ZWidget/include/zwidget/widgets/menubar/menubar.h new file mode 100644 index 0000000000..572d2a2f9c --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/menubar/menubar.h @@ -0,0 +1,99 @@ + +#pragma once + +#include "../../core/widget.h" +#include "../textlabel/textlabel.h" +#include "../imagebox/imagebox.h" +#include + +class Menu; +class MenubarItem; +class MenuItem; +class MenuItemSeparator; + +class Menubar : public Widget +{ +public: + Menubar(Widget* parent); + ~Menubar(); + + MenubarItem* AddItem(std::string text, std::function onOpen, bool alignRight = false); + +protected: + void OnGeometryChanged() override; + +private: + void ShowMenu(MenubarItem* item); + void CloseMenu(); + + std::vector menuItems; + Menu* openMenu = nullptr; + + friend class MenubarItem; +}; + +class MenubarItem : public Widget +{ +public: + MenubarItem(Menubar* menubar, std::string text, bool alignRight); + + void SetOpenCallback(std::function callback) { onOpen = std::move(callback); } + const std::function& GetOpenCallback() const { return onOpen; } + + double GetPreferredWidth() const; + + bool AlignRight = false; + +protected: + void OnPaint(Canvas* canvas) override; + bool OnMouseDown(const Point& pos, InputKey key) override; + bool OnMouseUp(const Point& pos, InputKey key) override; + void OnMouseMove(const Point& pos) override; + void OnMouseLeave() override; + +private: + Menubar* menubar = nullptr; + std::function onOpen; + std::string text; +}; + +class Menu : public Widget +{ +public: + Menu(Widget* parent); + + void SetLeftPosition(const Point& globalPos); + void SetRightPosition(const Point& globalPos); + MenuItem* AddItem(std::shared_ptr icon, std::string text, std::function onClick = {}); + MenuItemSeparator* AddSeparator(); + + double GetPreferredWidth() const; + double GetPreferredHeight() const; + +protected: + void OnGeometryChanged() override; + + std::function onCloseMenu; + + friend class Menubar; +}; + +class MenuItem : public Widget +{ +public: + MenuItem(Widget* parent); + + ImageBox* icon = nullptr; + TextLabel* text = nullptr; + +protected: + void OnMouseMove(const Point& pos) override; + void OnMouseLeave() override; + void OnGeometryChanged() override; +}; + +class MenuItemSeparator : public Widget +{ +public: + MenuItemSeparator(Widget* parent); +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h b/libraries/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h new file mode 100644 index 0000000000..d3fe0295bc --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h @@ -0,0 +1,32 @@ + +#pragma once + +#include "../../core/widget.h" +#include + +class PushButton : public Widget +{ +public: + PushButton(Widget* parent = nullptr); + + void SetText(const std::string& value); + const std::string& GetText() const; + + double GetPreferredHeight() const; + + void Click(); + + std::function OnClick; + +protected: + void OnPaint(Canvas* canvas) override; + bool OnMouseDown(const Point& pos, InputKey key) override; + bool OnMouseUp(const Point& pos, InputKey key) override; + void OnMouseMove(const Point& pos) override; + void OnMouseLeave() override; + void OnKeyDown(InputKey key) override; + void OnKeyUp(InputKey key) override; + +private: + std::string text; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/scrollbar/scrollbar.h b/libraries/ZWidget/include/zwidget/widgets/scrollbar/scrollbar.h new file mode 100644 index 0000000000..6e169b1fe9 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/scrollbar/scrollbar.h @@ -0,0 +1,99 @@ + +#pragma once + +#include "../../core/widget.h" +#include "../../core/timer.h" +#include + +class Scrollbar : public Widget +{ +public: + Scrollbar(Widget* parent); + ~Scrollbar(); + + bool IsVertical() const; + bool IsHorizontal() const; + double GetMin() const; + double GetMax() const; + double GetLineStep() const; + double GetPageStep() const; + double GetPosition() const; + + void SetVertical(); + void SetHorizontal(); + + void SetMin(double scroll_min); + void SetMax(double scroll_max); + void SetLineStep(double step); + void SetPageStep(double step); + + void SetRanges(double scroll_min, double scroll_max, double line_step, double page_step); + void SetRanges(double view_size, double total_size); + + void SetPosition(double pos); + + double GetPreferredWidth() const { return 16.0; } + double GetPreferredHeight() const { return 16.0; } + + std::function FuncScroll; + std::function FuncScrollMin; + std::function FuncScrollMax; + std::function FuncScrollLineDecrement; + std::function FuncScrollLineIncrement; + std::function FuncScrollPageDecrement; + std::function FuncScrollPageIncrement; + std::function FuncScrollThumbRelease; + std::function FuncScrollThumbTrack; + std::function FuncScrollEnd; + +protected: + bool OnMouseDown(const Point& pos, InputKey key) override; + bool OnMouseUp(const Point& pos, InputKey key) override; + void OnMouseMove(const Point& pos) override; + void OnMouseLeave() override; + void OnPaint(Canvas* canvas) override; + void OnEnableChanged() override; + void OnGeometryChanged() override; + +private: + bool UpdatePartPositions(); + double CalculateThumbSize(double track_size); + double CalculateThumbPosition(double thumb_size, double track_size); + Rect CreateRect(double start, double end); + void InvokeScrollEvent(std::function* event_ptr); + void OnTimerExpired(); + + bool vertical = true; + double scroll_min = 0.0; + double scroll_max = 1.0; + double line_step = 1.0; + double page_step = 10.0; + double position = 0.0; + + bool showbuttons = false; + + enum MouseDownMode + { + mouse_down_none, + mouse_down_button_decr, + mouse_down_button_incr, + mouse_down_track_decr, + mouse_down_track_incr, + mouse_down_thumb_drag + } mouse_down_mode = mouse_down_none; + + double thumb_start_position = 0.0; + Point mouse_drag_start_pos; + double thumb_start_pixel_position = 0.0; + + Timer* mouse_down_timer = nullptr; + double last_step_size = 0.0; + + Rect rect_button_decrement; + Rect rect_track_decrement; + Rect rect_thumb; + Rect rect_track_increment; + Rect rect_button_increment; + + std::function* FuncScrollOnMouseDown = nullptr; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/statusbar/statusbar.h b/libraries/ZWidget/include/zwidget/widgets/statusbar/statusbar.h new file mode 100644 index 0000000000..c03a3e282c --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/statusbar/statusbar.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "../../core/widget.h" + +class LineEdit; + +class Statusbar : public Widget +{ +public: + Statusbar(Widget* parent); + ~Statusbar(); + +protected: + void OnPaint(Canvas* canvas) override; + +private: + LineEdit* CommandEdit = nullptr; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h b/libraries/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h new file mode 100644 index 0000000000..00bb3d8905 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h @@ -0,0 +1,120 @@ + +#pragma once + +#include "../../core/widget.h" +#include +#include +#include + +class TabBar; +class TabBarTab; +class TabWidgetStack; +class TextLabel; +class ImageBox; +class Image; + +class TabWidget : public Widget +{ +public: + TabWidget(Widget* parent); + + int AddTab(Widget* page, const std::string& label); + int AddTab(Widget* page, const std::shared_ptr& icon, const std::string& label); + + void SetTabText(int index, const std::string& text); + void SetTabText(Widget* page, const std::string& text); + void SetTabIcon(int index, const std::shared_ptr& icon); + void SetTabIcon(Widget* page, const std::shared_ptr& icon); + + int GetCurrentIndex() const; + Widget* GetCurrentWidget() const; + + int GetPageIndex(Widget* pageWidget) const; + + void SetCurrentIndex(int pageIndex); + void SetCurrentWidget(Widget* pageWidget); + + std::function OnCurrentChanged; + +protected: + void OnGeometryChanged() override; + +private: + void OnBarCurrentChanged(); + + TabBar* Bar = nullptr; + TabWidgetStack* PageStack = nullptr; + std::vector Pages; +}; + +class TabBar : public Widget +{ +public: + TabBar(Widget* parent); + + int AddTab(const std::string& label); + int AddTab(const std::shared_ptr& icon, const std::string& label); + + void SetTabText(int index, const std::string& text); + void SetTabIcon(int index, const std::shared_ptr& icon); + + int GetCurrentIndex() const; + void SetCurrentIndex(int pageIndex); + + double GetPreferredHeight() const { return 30.0; } + + std::function OnCurrentChanged; + +protected: + void OnGeometryChanged() override; + +private: + void OnTabClicked(TabBarTab* tab); + int GetTabIndex(TabBarTab* tab); + + int CurrentIndex = -1; + std::vector Tabs; +}; + +class TabBarTab : public Widget +{ +public: + TabBarTab(Widget* parent); + + void SetText(const std::string& text); + void SetIcon(const std::shared_ptr& icon); + void SetCurrent(bool value); + + double GetPreferredWidth() const; + + std::function OnClick; + +protected: + void OnGeometryChanged() override; + bool OnMouseDown(const Point& pos, InputKey key) override; + bool OnMouseUp(const Point& pos, InputKey key) override; + void OnMouseMove(const Point& pos) override; + void OnMouseLeave() override; + +private: + bool IsCurrent = false; + + ImageBox* Icon = nullptr; + TextLabel* Label = nullptr; + bool hot = false; +}; + +class TabWidgetStack : public Widget +{ +public: + TabWidgetStack(Widget* parent); + + void SetCurrentWidget(Widget* widget); + Widget* GetCurrentWidget() const { return CurrentWidget; } + +protected: + void OnGeometryChanged() override; + +private: + Widget* CurrentWidget = nullptr; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/textedit/textedit.h b/libraries/ZWidget/include/zwidget/widgets/textedit/textedit.h new file mode 100644 index 0000000000..f392f85d67 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/textedit/textedit.h @@ -0,0 +1,155 @@ + +#pragma once + +#include "../../core/widget.h" +#include "../../core/timer.h" +#include "../../core/span_layout.h" +#include "../../core/font.h" +#include + +class Scrollbar; + +class TextEdit : public Widget +{ +public: + TextEdit(Widget* parent); + ~TextEdit(); + + bool IsReadOnly() const; + bool IsLowercase() const; + bool IsUppercase() const; + int GetMaxLength() const; + std::string GetText() const; + int GetLineCount() const; + std::string GetLineText(int line) const; + std::string GetSelection() const; + int GetSelectionStart() const; + int GetSelectionLength() const; + int GetCursorPos() const; + int GetCursorLineNumber() const; + double GetTotalHeight(); + + void SetSelectAllOnFocusGain(bool enable); + void SelectAll(); + void SetReadOnly(bool enable = true); + void SetLowercase(bool enable = true); + void SetUppercase(bool enable = true); + void SetMaxLength(int length); + void SetText(const std::string& text); + void AddText(const std::string& text); + void SetSelection(int pos, int length); + void ClearSelection(); + void SetCursorPos(int pos); + void DeleteSelectedText(); + void SetInputMask(const std::string& mask); + void SetCursorDrawingEnabled(bool enable); + + std::function FuncFilterKeyChar; + std::function FuncBeforeEditChanged; + std::function FuncAfterEditChanged; + std::function FuncSelectionChanged; + std::function FuncFocusGained; + std::function FuncFocusLost; + std::function FuncEnterPressed; + +protected: + void OnPaint(Canvas* canvas) override; + void OnMouseMove(const Point& pos) override; + bool OnMouseDown(const Point& pos, InputKey key) override; + bool OnMouseDoubleclick(const Point& pos, InputKey key) override; + bool OnMouseUp(const Point& pos, InputKey key) override; + void OnKeyChar(std::string chars) override; + void OnKeyDown(InputKey key) override; + void OnKeyUp(InputKey key) override; + void OnGeometryChanged() override; + void OnEnableChanged() override; + void OnSetFocus() override; + void OnLostFocus() override; + +private: + void LayoutLines(Canvas* canvas); + + void OnTimerExpired(); + void OnScrollTimerExpired(); + void CreateComponents(); + void OnVerticalScroll(); + void UpdateVerticalScroll(); + void MoveVerticalScroll(); + double GetTotalLineHeight(); + + struct Line + { + std::string text; + SpanLayout layout; + Rect box; + bool invalidated = true; + }; + + struct ivec2 + { + ivec2() = default; + ivec2(int x, int y) : x(x), y(y) { } + int x = 0; + int y = 0; + + bool operator==(const ivec2& b) const { return x == b.x && y == b.y; } + bool operator!=(const ivec2& b) const { return x != b.x || y != b.y; } + }; + + Scrollbar* vert_scrollbar; + Timer* timer = nullptr; + std::vector lines = { Line() }; + ivec2 cursor_pos = { 0, 0 }; + int max_length = -1; + bool mouse_selecting = false; + bool lowercase = false; + bool uppercase = false; + bool readonly = false; + ivec2 selection_start = { -1, 0 }; + int selection_length = 0; + std::string input_mask; + + static std::string break_characters; + + void Move(int steps, bool shift, bool ctrl); + void InsertText(ivec2 pos, const std::string& str); + void Backspace(); + void Del(); + ivec2 GetCharacterIndex(Point mouse_wincoords); + ivec2 FindNextBreakCharacter(ivec2 pos); + ivec2 FindPreviousBreakCharacter(ivec2 pos); + bool InputMaskAcceptsInput(ivec2 cursor_pos, const std::string& str); + + std::string::size_type ToOffset(ivec2 pos) const; + ivec2 FromOffset(std::string::size_type offset) const; + + VerticalTextPosition vertical_text_align; + Timer* scroll_timer = nullptr; + + bool mouse_moves_left = false; + bool cursor_blink_visible = true; + unsigned int blink_timer = 0; + int clip_start_offset = 0; + int clip_end_offset = 0; + bool ignore_mouse_events = false; + + struct UndoInfo + { + /* set undo text when: + - added char after moving + - destructive block operation (del, cut etc) + - beginning erase + */ + + std::string undo_text; + bool first_erase = false; + bool first_text_insert = false; + } undo_info; + + bool select_all_on_focus_gain = false; + + std::shared_ptr font = Font::Create("NotoSans", 12.0); + + template + static T clamp(T val, T minval, T maxval) { return std::max(std::min(val, maxval), minval); } +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/textlabel/textlabel.h b/libraries/ZWidget/include/zwidget/widgets/textlabel/textlabel.h new file mode 100644 index 0000000000..45515dfcb4 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/textlabel/textlabel.h @@ -0,0 +1,33 @@ + +#pragma once + +#include "../../core/widget.h" + +enum TextLabelAlignment +{ + Left, + Center, + Right +}; + +class TextLabel : public Widget +{ +public: + TextLabel(Widget* parent = nullptr); + + void SetText(const std::string& value); + const std::string& GetText() const; + + void SetTextAlignment(TextLabelAlignment alignment); + TextLabelAlignment GetTextAlignment() const; + + double GetPreferredWidth() const; + double GetPreferredHeight() const; + +protected: + void OnPaint(Canvas* canvas) override; + +private: + std::string text; + TextLabelAlignment textAlignment = TextLabelAlignment::Left; +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/toolbar/toolbar.h b/libraries/ZWidget/include/zwidget/widgets/toolbar/toolbar.h new file mode 100644 index 0000000000..ca0a89c0dc --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/toolbar/toolbar.h @@ -0,0 +1,11 @@ + +#pragma once + +#include "../../core/widget.h" + +class Toolbar : public Widget +{ +public: + Toolbar(Widget* parent); + ~Toolbar(); +}; diff --git a/libraries/ZWidget/include/zwidget/widgets/toolbar/toolbarbutton.h b/libraries/ZWidget/include/zwidget/widgets/toolbar/toolbarbutton.h new file mode 100644 index 0000000000..933a6517ed --- /dev/null +++ b/libraries/ZWidget/include/zwidget/widgets/toolbar/toolbarbutton.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "../../core/widget.h" + +class ToolbarButton : public Widget +{ +public: + ToolbarButton(Widget* parent); + ~ToolbarButton(); + +protected: + void OnPaint(Canvas* canvas) override; +}; diff --git a/libraries/ZWidget/include/zwidget/window/window.h b/libraries/ZWidget/include/zwidget/window/window.h new file mode 100644 index 0000000000..a51519af46 --- /dev/null +++ b/libraries/ZWidget/include/zwidget/window/window.h @@ -0,0 +1,174 @@ +#pragma once + +#include +#include +#include +#include +#include "../core/rect.h" + +class Engine; + +enum class StandardCursor +{ + arrow, + appstarting, + cross, + hand, + ibeam, + no, + size_all, + size_nesw, + size_ns, + size_nwse, + size_we, + uparrow, + wait +}; + +enum class InputKey : uint32_t +{ + None, LeftMouse, RightMouse, Cancel, + MiddleMouse, Unknown05, Unknown06, Unknown07, + Backspace, Tab, Unknown0A, Unknown0B, + Unknown0C, Enter, Unknown0E, Unknown0F, + Shift, Ctrl, Alt, Pause, + CapsLock, Unknown15, Unknown16, Unknown17, + Unknown18, Unknown19, Unknown1A, Escape, + Unknown1C, Unknown1D, Unknown1E, Unknown1F, + Space, PageUp, PageDown, End, + Home, Left, Up, Right, + Down, Select, Print, Execute, + PrintScrn, Insert, Delete, Help, + _0, _1, _2, _3, + _4, _5, _6, _7, + _8, _9, Unknown3A, Unknown3B, + Unknown3C, Unknown3D, Unknown3E, Unknown3F, + Unknown40, A, B, C, + D, E, F, G, + H, I, J, K, + L, M, N, O, + P, Q, R, S, + T, U, V, W, + X, Y, Z, Unknown5B, + Unknown5C, Unknown5D, Unknown5E, Unknown5F, + NumPad0, NumPad1, NumPad2, NumPad3, + NumPad4, NumPad5, NumPad6, NumPad7, + NumPad8, NumPad9, GreyStar, GreyPlus, + Separator, GreyMinus, NumPadPeriod, GreySlash, + F1, F2, F3, F4, + F5, F6, F7, F8, + F9, F10, F11, F12, + F13, F14, F15, F16, + F17, F18, F19, F20, + F21, F22, F23, F24, + Unknown88, Unknown89, Unknown8A, Unknown8B, + Unknown8C, Unknown8D, Unknown8E, Unknown8F, + NumLock, ScrollLock, Unknown92, Unknown93, + Unknown94, Unknown95, Unknown96, Unknown97, + Unknown98, Unknown99, Unknown9A, Unknown9B, + Unknown9C, Unknown9D, Unknown9E, Unknown9F, + LShift, RShift, LControl, RControl, + UnknownA4, UnknownA5, UnknownA6, UnknownA7, + UnknownA8, UnknownA9, UnknownAA, UnknownAB, + UnknownAC, UnknownAD, UnknownAE, UnknownAF, + UnknownB0, UnknownB1, UnknownB2, UnknownB3, + UnknownB4, UnknownB5, UnknownB6, UnknownB7, + UnknownB8, UnknownB9, Semicolon, Equals, + Comma, Minus, Period, Slash, + Tilde, UnknownC1, UnknownC2, UnknownC3, + UnknownC4, UnknownC5, UnknownC6, UnknownC7, + Joy1, Joy2, Joy3, Joy4, + Joy5, Joy6, Joy7, Joy8, + Joy9, Joy10, Joy11, Joy12, + Joy13, Joy14, Joy15, Joy16, + UnknownD8, UnknownD9, UnknownDA, LeftBracket, + Backslash, RightBracket, SingleQuote, UnknownDF, + JoyX, JoyY, JoyZ, JoyR, + MouseX, MouseY, MouseZ, MouseW, + JoyU, JoyV, UnknownEA, UnknownEB, + MouseWheelUp, MouseWheelDown, Unknown10E, Unknown10F, + JoyPovUp, JoyPovDown, JoyPovLeft, JoyPovRight, + UnknownF4, UnknownF5, Attn, CrSel, + ExSel, ErEof, Play, Zoom, + NoName, PA1, OEMClear +}; + +class DisplayWindow; + +class DisplayWindowHost +{ +public: + virtual void OnWindowPaint() = 0; + virtual void OnWindowMouseMove(const Point& pos) = 0; + virtual void OnWindowMouseLeave() = 0; + virtual void OnWindowMouseDown(const Point& pos, InputKey key) = 0; + virtual void OnWindowMouseDoubleclick(const Point& pos, InputKey key) = 0; + virtual void OnWindowMouseUp(const Point& pos, InputKey key) = 0; + virtual void OnWindowMouseWheel(const Point& pos, InputKey key) = 0; + virtual void OnWindowRawMouseMove(int dx, int dy) = 0; + virtual void OnWindowKeyChar(std::string chars) = 0; + virtual void OnWindowKeyDown(InputKey key) = 0; + virtual void OnWindowKeyUp(InputKey key) = 0; + virtual void OnWindowGeometryChanged() = 0; + virtual void OnWindowClose() = 0; + virtual void OnWindowActivated() = 0; + virtual void OnWindowDeactivated() = 0; + virtual void OnWindowDpiScaleChanged() = 0; +}; + +class DisplayWindow +{ +public: + static std::unique_ptr Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner); + + static void ProcessEvents(); + static void RunLoop(); + static void ExitLoop(); + + static void* StartTimer(int timeoutMilliseconds, std::function onTimer); + static void StopTimer(void* timerID); + + static Size GetScreenSize(); + + virtual ~DisplayWindow() = default; + + virtual void SetWindowTitle(const std::string& text) = 0; + virtual void SetWindowFrame(const Rect& box) = 0; + virtual void SetClientFrame(const Rect& box) = 0; + virtual void Show() = 0; + virtual void ShowFullscreen() = 0; + virtual void ShowMaximized() = 0; + virtual void ShowMinimized() = 0; + virtual void ShowNormal() = 0; + virtual void Hide() = 0; + virtual void Activate() = 0; + virtual void ShowCursor(bool enable) = 0; + virtual void LockCursor() = 0; + virtual void UnlockCursor() = 0; + virtual void CaptureMouse() = 0; + virtual void ReleaseMouseCapture() = 0; + virtual void Update() = 0; + virtual bool GetKeyState(InputKey key) = 0; + + virtual void SetCursor(StandardCursor cursor) = 0; + + virtual Rect GetWindowFrame() const = 0; + virtual Size GetClientSize() const = 0; + virtual int GetPixelWidth() const = 0; + virtual int GetPixelHeight() const = 0; + virtual double GetDpiScale() const = 0; + + virtual Point MapFromGlobal(const Point& pos) const = 0; + virtual Point MapToGlobal(const Point& pos) const = 0; + + virtual void SetBorderColor(uint32_t bgra8) = 0; + virtual void SetCaptionColor(uint32_t bgra8) = 0; + virtual void SetCaptionTextColor(uint32_t bgra8) = 0; + + virtual void PresentBitmap(int width, int height, const uint32_t* pixels) = 0; + + virtual std::string GetClipboardText() = 0; + virtual void SetClipboardText(const std::string& text) = 0; + + virtual void* GetNativeHandle() = 0; +}; diff --git a/libraries/ZWidget/src/core/canvas.cpp b/libraries/ZWidget/src/core/canvas.cpp new file mode 100644 index 0000000000..437c25f024 --- /dev/null +++ b/libraries/ZWidget/src/core/canvas.cpp @@ -0,0 +1,960 @@ + +#include "core/canvas.h" +#include "core/rect.h" +#include "core/colorf.h" +#include "core/utf8reader.h" +#include "core/resourcedata.h" +#include "core/image.h" +#include "core/truetypefont.h" +#include "core/pathfill.h" +#include "window/window.h" +#include +#include +#include +#include + +#if defined(__SSE2__) || defined(_M_X64) +#include +#define USE_SSE2 +#endif + +class CanvasTexture +{ +public: + int Width = 0; + int Height = 0; + std::vector Data; +}; + +class CanvasGlyph +{ +public: + struct + { + double leftSideBearing = 0.0; + double yOffset = 0.0; + double advanceWidth = 0.0; + } metrics; + + double u = 0.0; + double v = 0.0; + double uvwidth = 0.0f; + double uvheight = 0.0f; + std::shared_ptr texture; +}; + +class CanvasFont +{ +public: + CanvasFont(const std::string& fontname, double height, std::vector data) : fontname(fontname), height(height) + { + auto tdata = std::make_shared(std::move(data)); + ttf = std::make_unique(tdata); + textmetrics = ttf->GetTextMetrics(height); + } + + ~CanvasFont() + { + } + + CanvasGlyph* getGlyph(uint32_t utfchar) + { + uint32_t glyphIndex = ttf->GetGlyphIndex(utfchar); + if (glyphIndex == 0) return nullptr; + + auto& glyph = glyphs[glyphIndex]; + if (glyph) + return glyph.get(); + + glyph = std::make_unique(); + + TrueTypeGlyph ttfglyph = ttf->LoadGlyph(glyphIndex, height); + + // Create final subpixel version + int w = ttfglyph.width; + int h = ttfglyph.height; + int destwidth = (w + 2) / 3; + auto texture = std::make_shared(); + texture->Width = destwidth; + texture->Height = h; + texture->Data.resize(destwidth * h); + + uint8_t* grayscale = ttfglyph.grayscale.get(); + uint32_t* dest = (uint32_t*)texture->Data.data(); + for (int y = 0; y < h; y++) + { + uint8_t* sline = grayscale + y * w; + uint32_t* dline = dest + y * destwidth; + for (int x = 0; x < w; x += 3) + { + uint32_t values[5] = + { + x > 0 ? sline[x - 1] : 0U, + sline[x], + x + 1 < w ? sline[x + 1] : 0U, + x + 2 < w ? sline[x + 2] : 0U, + x + 3 < w ? sline[x + 3] : 0U + }; + + uint32_t red = (values[0] + values[1] + values[1] + values[2] + 2) >> 2; + uint32_t green = (values[1] + values[2] + values[2] + values[3] + 2) >> 2; + uint32_t blue = (values[2] + values[3] + values[3] + values[4] + 2) >> 2; + uint32_t alpha = (red | green | blue) ? 255 : 0; + + *(dline++) = (alpha << 24) | (red << 16) | (green << 8) | blue; + } + } + + glyph->u = 0.0; + glyph->v = 0.0; + glyph->uvwidth = destwidth; + glyph->uvheight = h; + glyph->texture = std::move(texture); + + glyph->metrics.advanceWidth = (ttfglyph.advanceWidth + 2) / 3; + glyph->metrics.leftSideBearing = (ttfglyph.leftSideBearing + 2) / 3; + glyph->metrics.yOffset = ttfglyph.yOffset; + + return glyph.get(); + } + + std::unique_ptr ttf; + + std::string fontname; + double height = 0.0; + + TrueTypeTextMetrics textmetrics; + std::unordered_map> glyphs; +}; + +class CanvasFontGroup +{ +public: + struct SingleFont + { + std::unique_ptr font; + std::string language; + }; + CanvasFontGroup(const std::string& fontname, double height) : height(height) + { + auto fontdata = LoadWidgetFontData(fontname); + fonts.resize(fontdata.size()); + for (size_t i = 0; i < fonts.size(); i++) + { + fonts[i].font = std::make_unique(fontname, height, fontdata[i].fontdata); + fonts[i].language = fontdata[i].language; + } + } + + CanvasGlyph* getGlyph(uint32_t utfchar, const char* lang = nullptr) + { + for (int i = 0; i < 2; i++) + { + for (auto& fd : fonts) + { + if (i == 1 || lang == nullptr || *lang == 0 || fd.language.empty() || fd.language == lang) + { + auto g = fd.font->getGlyph(utfchar); + if (g) return g; + } + } + } + + return nullptr; + } + + TrueTypeTextMetrics& GetTextMetrics() + { + return fonts[0].font->textmetrics; + } + + double height; + std::vector fonts; + +}; + +class BitmapCanvas : public Canvas +{ +public: + BitmapCanvas(DisplayWindow* window); + ~BitmapCanvas(); + + void begin(const Colorf& color) override; + void end() override; + + void begin3d() override; + void end3d() override; + + Point getOrigin() override; + void setOrigin(const Point& origin) override; + + void pushClip(const Rect& box) override; + void popClip() override; + + void fillRect(const Rect& box, const Colorf& color) override; + void line(const Point& p0, const Point& p1, const Colorf& color) override; + + void drawText(const Point& pos, const Colorf& color, const std::string& text) override; + Rect measureText(const std::string& text) override; + VerticalTextPosition verticalTextAlign() override; + + void drawText(const std::shared_ptr& font, const Point& pos, const std::string& text, const Colorf& color) override { drawText(pos, color, text); } + void drawTextEllipsis(const std::shared_ptr& font, const Point& pos, const Rect& clipBox, const std::string& text, const Colorf& color) override { drawText(pos, color, text); } + Rect measureText(const std::shared_ptr& font, const std::string& text) override { return measureText(text); } + FontMetrics getFontMetrics(const std::shared_ptr& font) override + { + VerticalTextPosition vtp = verticalTextAlign(); + FontMetrics metrics; + metrics.external_leading = vtp.top; + metrics.ascent = vtp.baseline - vtp.top; + metrics.descent = vtp.bottom - vtp.baseline; + metrics.height = metrics.ascent + metrics.descent; + return metrics; + } + int getCharacterIndex(const std::shared_ptr& font, const std::string& text, const Point& hitPoint) override { return 0; } + + void drawImage(const std::shared_ptr& image, const Point& pos) override; + + void drawLineUnclipped(const Point& p0, const Point& p1, const Colorf& color); + + void fillTile(float x, float y, float width, float height, Colorf color); + void drawTile(CanvasTexture* texture, float x, float y, float width, float height, float u, float v, float uvwidth, float uvheight, Colorf color); + void drawGlyph(CanvasTexture* texture, float x, float y, float width, float height, float u, float v, float uvwidth, float uvheight, Colorf color); + + int getClipMinX() const; + int getClipMinY() const; + int getClipMaxX() const; + int getClipMaxY() const; + + void setLanguage(const char* lang) { language = lang; } + + std::unique_ptr createTexture(int width, int height, const void* pixels, ImageFormat format = ImageFormat::B8G8R8A8); + + template + static T clamp(T val, T minval, T maxval) { return std::max(std::min(val, maxval), minval); } + + DisplayWindow* window = nullptr; + + std::unique_ptr font; + std::unique_ptr whiteTexture; + + Point origin; + double uiscale = 1.0f; + std::vector clipStack; + + int width = 0; + int height = 0; + std::vector pixels; + + std::unordered_map, std::unique_ptr> imageTextures; + std::string language; +}; + +BitmapCanvas::BitmapCanvas(DisplayWindow* window) : window(window) +{ + uiscale = window->GetDpiScale(); + uint32_t white = 0xffffffff; + whiteTexture = createTexture(1, 1, &white); + font = std::make_unique("NotoSans", 13.0 * uiscale); +} + +BitmapCanvas::~BitmapCanvas() +{ +} + +Point BitmapCanvas::getOrigin() +{ + return origin; +} + +void BitmapCanvas::setOrigin(const Point& newOrigin) +{ + origin = newOrigin; +} + +void BitmapCanvas::pushClip(const Rect& box) +{ + if (!clipStack.empty()) + { + const Rect& clip = clipStack.back(); + + double x0 = box.x + origin.x; + double y0 = box.y + origin.y; + double x1 = x0 + box.width; + double y1 = y0 + box.height; + + x0 = std::max(x0, clip.x); + y0 = std::max(y0, clip.y); + x1 = std::min(x1, clip.x + clip.width); + y1 = std::min(y1, clip.y + clip.height); + + if (x0 < x1 && y0 < y1) + clipStack.push_back(Rect::ltrb(x0, y0, x1, y1)); + else + clipStack.push_back(Rect::xywh(0.0, 0.0, 0.0, 0.0)); + } + else + { + clipStack.push_back(box); + } +} + +void BitmapCanvas::popClip() +{ + clipStack.pop_back(); +} + +void BitmapCanvas::fillRect(const Rect& box, const Colorf& color) +{ + fillTile((float)((origin.x + box.x) * uiscale), (float)((origin.y + box.y) * uiscale), (float)(box.width * uiscale), (float)(box.height * uiscale), color); +} + +void BitmapCanvas::drawImage(const std::shared_ptr& image, const Point& pos) +{ + auto& texture = imageTextures[image]; + if (!texture) + { + texture = createTexture(image->GetWidth(), image->GetHeight(), image->GetData(), image->GetFormat()); + } + Colorf color(1.0f, 1.0f, 1.0f); + drawTile(texture.get(), (float)((origin.x + pos.x) * uiscale), (float)((origin.y + pos.y) * uiscale), (float)(texture->Width * uiscale), (float)(texture->Height * uiscale), 0.0, 0.0, (float)texture->Width, (float)texture->Height, color); +} + +void BitmapCanvas::line(const Point& p0, const Point& p1, const Colorf& color) +{ + double x0 = origin.x + p0.x; + double y0 = origin.y + p0.y; + double x1 = origin.x + p1.x; + double y1 = origin.y + p1.y; + + if (clipStack.empty())// || (clipStack.back().contains({ x0, y0 }) && clipStack.back().contains({ x1, y1 }))) + { + drawLineUnclipped({ x0, y0 }, { x1, y1 }, color); + } + else + { + const Rect& clip = clipStack.back(); + + if (x0 > x1) + { + std::swap(x0, x1); + std::swap(y0, y1); + } + + if (x1 < clip.x || x0 >= clip.x + clip.width) + return; + + // Clip left edge + if (x0 < clip.x) + { + double dx = x1 - x0; + double dy = y1 - y0; + if (std::abs(dx) < 0.0001) + return; + y0 = y0 + (clip.x - x0) * dy / dx; + x0 = clip.x; + } + + // Clip right edge + if (x1 > clip.x + clip.width) + { + double dx = x1 - x0; + double dy = y1 - y0; + if (std::abs(dx) < 0.0001) + return; + y1 = y1 + (clip.x + clip.width - x1) * dy / dx; + x1 = clip.x + clip.width; + } + + if (y0 > y1) + { + std::swap(x0, x1); + std::swap(y0, y1); + } + + if (y1 < clip.y || y0 >= clip.y + clip.height) + return; + + // Clip top edge + if (y0 < clip.y) + { + double dx = x1 - x0; + double dy = y1 - y0; + if (std::abs(dy) < 0.0001) + return; + x0 = x0 + (clip.y - y0) * dx / dy; + y0 = clip.y; + } + + // Clip bottom edge + if (y1 > clip.y + clip.height) + { + double dx = x1 - x0; + double dy = y1 - y0; + if (std::abs(dy) < 0.0001) + return; + x1 = x1 + (clip.y + clip.height - y1) * dx / dy; + y1 = clip.y + clip.height; + } + + x0 = clamp(x0, clip.x, clip.x + clip.width); + x1 = clamp(x1, clip.x, clip.x + clip.width); + y0 = clamp(y0, clip.y, clip.y + clip.height); + y1 = clamp(y1, clip.y, clip.y + clip.height); + + if (x0 != x1 || y0 != y1) + drawLineUnclipped({ x0, y0 }, { x1, y1 }, color); + } +} + +void BitmapCanvas::drawText(const Point& pos, const Colorf& color, const std::string& text) +{ + double x = std::round((origin.x + pos.x) * uiscale); + double y = std::round((origin.y + pos.y) * uiscale); + + UTF8Reader reader(text.data(), text.size()); + while (!reader.is_end()) + { + CanvasGlyph* glyph = font->getGlyph(reader.character(), language.c_str()); + if (!glyph || !glyph->texture) + { + glyph = font->getGlyph(32); + } + + if (glyph->texture) + { + double gx = std::round(x + glyph->metrics.leftSideBearing); + double gy = std::round(y + glyph->metrics.yOffset); + drawGlyph(glyph->texture.get(), (float)std::round(gx), (float)std::round(gy), (float)glyph->uvwidth, (float)glyph->uvheight, (float)glyph->u, (float)glyph->v, (float)glyph->uvwidth, (float)glyph->uvheight, color); + } + + x += std::round(glyph->metrics.advanceWidth); + reader.next(); + } +} + +Rect BitmapCanvas::measureText(const std::string& text) +{ + double x = 0.0; + double y = font->GetTextMetrics().ascender - font->GetTextMetrics().descender; + + UTF8Reader reader(text.data(), text.size()); + while (!reader.is_end()) + { + CanvasGlyph* glyph = font->getGlyph(reader.character(), language.c_str()); + if (!glyph || !glyph->texture) + { + glyph = font->getGlyph(32); + } + + x += std::round(glyph->metrics.advanceWidth); + reader.next(); + } + + return Rect::xywh(0.0, 0.0, x / uiscale, y / uiscale); +} + +VerticalTextPosition BitmapCanvas::verticalTextAlign() +{ + VerticalTextPosition align; + align.top = 0.0f; + auto tm = font->GetTextMetrics(); + align.baseline = tm.ascender / uiscale; + align.bottom = (tm.ascender - tm.descender) / uiscale; + return align; +} + +std::unique_ptr BitmapCanvas::createTexture(int width, int height, const void* pixels, ImageFormat format) +{ + auto texture = std::make_unique(); + texture->Width = width; + texture->Height = height; + texture->Data.resize(width * height); + if (format == ImageFormat::B8G8R8A8) + { + memcpy(texture->Data.data(), pixels, width * height * sizeof(uint32_t)); + } + else + { + const uint32_t* src = (const uint32_t*)pixels; + uint32_t* dest = texture->Data.data(); + int count = width * height; + for (int i = 0; i < count; i++) + { + uint32_t a = (src[i] >> 24) & 0xff; + uint32_t b = (src[i] >> 16) & 0xff; + uint32_t g = (src[i] >> 8) & 0xff; + uint32_t r = src[i] & 0xff; + dest[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + } + return texture; +} + +void BitmapCanvas::drawLineUnclipped(const Point& p0, const Point& p1, const Colorf& color) +{ + if (p0.x == p1.x) + { + fillTile((float)((p0.x - 0.5) * uiscale), (float)(p0.y * uiscale), (float)uiscale, (float)((p1.y - p0.y) * uiscale), color); + } + else if (p0.y == p1.y) + { + fillTile((float)(p0.x * uiscale), (float)((p0.y - 0.5) * uiscale), (float)((p1.x - p0.x) * uiscale), (float)uiscale, color); + } + else + { + // To do: draw line using bresenham + } +} + +int BitmapCanvas::getClipMinX() const +{ + return clipStack.empty() ? 0 : (int)std::max(clipStack.back().x * uiscale, 0.0); +} + +int BitmapCanvas::getClipMinY() const +{ + return clipStack.empty() ? 0 : (int)std::max(clipStack.back().y * uiscale, 0.0); +} + +int BitmapCanvas::getClipMaxX() const +{ + return clipStack.empty() ? width : (int)std::min((clipStack.back().x + clipStack.back().width) * uiscale, (double)width); +} + +int BitmapCanvas::getClipMaxY() const +{ + return clipStack.empty() ? height : (int)std::min((clipStack.back().y + clipStack.back().height) * uiscale, (double)height); +} + +void BitmapCanvas::fillTile(float left, float top, float width, float height, Colorf color) +{ + if (width <= 0.0f || height <= 0.0f || color.a <= 0.0f) + return; + + int dwidth = this->width; + int dheight = this->height; + uint32_t* dest = this->pixels.data(); + + int x0 = (int)left; + int x1 = (int)(left + width); + int y0 = (int)top; + int y1 = (int)(top + height); + + x0 = std::max(x0, getClipMinX()); + y0 = std::max(y0, getClipMinY()); + x1 = std::min(x1, getClipMaxX()); + y1 = std::min(y1, getClipMaxY()); + if (x1 <= x0 || y1 <= y0) + return; + + uint32_t cred = (int32_t)clamp(color.r * 255.0f, 0.0f, 255.0f); + uint32_t cgreen = (int32_t)clamp(color.g * 255.0f, 0.0f, 255.0f); + uint32_t cblue = (int32_t)clamp(color.b * 255.0f, 0.0f, 255.0f); + uint32_t calpha = (int32_t)clamp(color.a * 255.0f, 0.0f, 255.0f); + uint32_t invalpha = 256 - (calpha + (calpha >> 7)); + + if (invalpha == 0) // Solid fill + { + uint32_t c = (calpha << 24) | (cred << 16) | (cgreen << 8) | cblue; +#ifdef USE_SSE2 + __m128i cargb = _mm_set1_epi32(c); +#endif + + for (int y = y0; y < y1; y++) + { + uint32_t* dline = dest + y * dwidth; + + int x = x0; +#ifdef USE_SSE2 + int ssex1 = x0 + (((x1 - x0) >> 2) << 2); + while (x < ssex1) + { + _mm_storeu_si128((__m128i*)(dline + x), cargb); + x += 4; + } +#endif + + while (x < x1) + { + dline[x] = c; + x++; + } + } + } + else // Alpha blended fill + { + cred <<= 8; + cgreen <<= 8; + cblue <<= 8; + calpha <<= 8; +#ifdef USE_SSE2 + __m128i cargb = _mm_set_epi16(calpha, cred, cgreen, cblue, calpha, cred, cgreen, cblue); + __m128i cinvalpha = _mm_set1_epi16(invalpha); +#endif + + for (int y = y0; y < y1; y++) + { + uint32_t* dline = dest + y * dwidth; + + int x = x0; +#ifdef USE_SSE2 + int ssex1 = x0 + (((x1 - x0) >> 1) << 1); + while (x < ssex1) + { + __m128i dpixel = _mm_loadl_epi64((const __m128i*)(dline + x)); + dpixel = _mm_unpacklo_epi8(dpixel, _mm_setzero_si128()); + + // dest.rgba = color.rgba + dest.rgba * (1-color.a) + __m128i result = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(cargb, _mm_mullo_epi16(dpixel, cinvalpha)), _mm_set1_epi16(127)), 8); + _mm_storel_epi64((__m128i*)(dline + x), _mm_packus_epi16(result, _mm_setzero_si128())); + x += 2; + } +#endif + + while (x < x1) + { + uint32_t dpixel = dline[x]; + uint32_t dalpha = dpixel >> 24; + uint32_t dred = (dpixel >> 16) & 0xff; + uint32_t dgreen = (dpixel >> 8) & 0xff; + uint32_t dblue = dpixel & 0xff; + + // dest.rgba = color.rgba + dest.rgba * (1-color.a) + uint32_t a = (calpha + dalpha * invalpha + 127) >> 8; + uint32_t r = (cred + dred * invalpha + 127) >> 8; + uint32_t g = (cgreen + dgreen * invalpha + 127) >> 8; + uint32_t b = (cblue + dblue * invalpha + 127) >> 8; + dline[x] = (a << 24) | (r << 16) | (g << 8) | b; + x++; + } + } + } +} + +void BitmapCanvas::drawTile(CanvasTexture* texture, float left, float top, float width, float height, float u, float v, float uvwidth, float uvheight, Colorf color) +{ + if (width <= 0.0f || height <= 0.0f || color.a <= 0.0f) + return; + + int swidth = texture->Width; + int sheight = texture->Height; + const uint32_t* src = texture->Data.data(); + + int dwidth = this->width; + int dheight = this->height; + uint32_t* dest = this->pixels.data(); + + int x0 = (int)left; + int x1 = (int)(left + width); + int y0 = (int)top; + int y1 = (int)(top + height); + + x0 = std::max(x0, getClipMinX()); + y0 = std::max(y0, getClipMinY()); + x1 = std::min(x1, getClipMaxX()); + y1 = std::min(y1, getClipMaxY()); + if (x1 <= x0 || y1 <= y0) + return; + + uint32_t cred = (int32_t)clamp(color.r * 256.0f, 0.0f, 256.0f); + uint32_t cgreen = (int32_t)clamp(color.g * 256.0f, 0.0f, 256.0f); + uint32_t cblue = (int32_t)clamp(color.b * 256.0f, 0.0f, 256.0f); + uint32_t calpha = (int32_t)clamp(color.a * 256.0f, 0.0f, 256.0f); +#ifdef USE_SSE2 + __m128i cargb = _mm_set_epi16(calpha, cred, cgreen, cblue, calpha, cred, cgreen, cblue); +#endif + + float uscale = uvwidth / width; + float vscale = uvheight / height; + + for (int y = y0; y < y1; y++) + { + float vpix = v + vscale * (y + 0.5f - top); + const uint32_t* sline = src + ((int)vpix) * swidth; + uint32_t* dline = dest + y * dwidth; + + int x = x0; +#ifdef USE_SSE2 + int ssex1 = x0 + (((x1 - x0) >> 1) << 1); + while (x < ssex1) + { + float upix0 = u + uscale * (x + 0.5f - left); + float upix1 = u + uscale * (x + 1 + 0.5f - left); + uint32_t spixel0 = sline[(int)upix0]; + uint32_t spixel1 = sline[(int)upix1]; + __m128i spixel = _mm_set_epi32(0, 0, spixel1, spixel0); + spixel = _mm_unpacklo_epi8(spixel, _mm_setzero_si128()); + + __m128i dpixel = _mm_loadl_epi64((const __m128i*)(dline + x)); + dpixel = _mm_unpacklo_epi8(dpixel, _mm_setzero_si128()); + + // Pixel shade + spixel = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(spixel, cargb), _mm_set1_epi16(127)), 8); + + // Rescale from [0,255] to [0,256] + __m128i sa = _mm_shufflehi_epi16(_mm_shufflelo_epi16(spixel, _MM_SHUFFLE(3, 3, 3, 3)), _MM_SHUFFLE(3, 3, 3, 3)); + sa = _mm_add_epi16(sa, _mm_srli_epi16(sa, 7)); + __m128i sinva = _mm_sub_epi16(_mm_set1_epi16(256), sa); + + // dest.rgba = color.rgba * src.rgba * src.a + dest.rgba * (1-src.a) + __m128i result = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(_mm_mullo_epi16(spixel, sa), _mm_mullo_epi16(dpixel, sinva)), _mm_set1_epi16(127)), 8); + _mm_storel_epi64((__m128i*)(dline + x), _mm_packus_epi16(result, _mm_setzero_si128())); + x += 2; + } +#endif + + while (x < x1) + { + float upix = u + uscale * (x + 0.5f - left); + uint32_t spixel = sline[(int)upix]; + uint32_t salpha = spixel >> 24; + uint32_t sred = (spixel >> 16) & 0xff; + uint32_t sgreen = (spixel >> 8) & 0xff; + uint32_t sblue = spixel & 0xff; + + uint32_t dpixel = dline[x]; + uint32_t dalpha = dpixel >> 24; + uint32_t dred = (dpixel >> 16) & 0xff; + uint32_t dgreen = (dpixel >> 8) & 0xff; + uint32_t dblue = dpixel & 0xff; + + // Pixel shade + sred = (cred * sred + 127) >> 8; + sgreen = (cgreen * sgreen + 127) >> 8; + sblue = (cblue * sblue + 127) >> 8; + salpha = (calpha * salpha + 127) >> 8; + + // Rescale from [0,255] to [0,256] + uint32_t sa = salpha + (salpha >> 7); + uint32_t sinva = 256 - sa; + + // dest.rgba = color.rgba * src.rgba * src.a + dest.rgba * (1-src.a) + uint32_t a = (salpha * sa + dalpha * sinva + 127) >> 8; + uint32_t r = (sred * sa + dred * sinva + 127) >> 8; + uint32_t g = (sgreen * sa + dgreen * sinva + 127) >> 8; + uint32_t b = (sblue * sa + dblue * sinva + 127) >> 8; + dline[x] = (a << 24) | (r << 16) | (g << 8) | b; + x++; + } + } +} + +void BitmapCanvas::drawGlyph(CanvasTexture* texture, float left, float top, float width, float height, float u, float v, float uvwidth, float uvheight, Colorf color) +{ + if (width <= 0.0f || height <= 0.0f) + return; + + int swidth = texture->Width; + int sheight = texture->Height; + const uint32_t* src = texture->Data.data(); + + int dwidth = this->width; + int dheight = this->height; + uint32_t* dest = this->pixels.data(); + + int x0 = (int)left; + int x1 = (int)(left + width); + int y0 = (int)top; + int y1 = (int)(top + height); + + x0 = std::max(x0, getClipMinX()); + y0 = std::max(y0, getClipMinY()); + x1 = std::min(x1, getClipMaxX()); + y1 = std::min(y1, getClipMaxY()); + if (x1 <= x0 || y1 <= y0) + return; + +#if 1 // Use gamma correction + + // To linear + float cred = color.r * color.r; // std::pow(color.r, 2.2f); + float cgreen = color.g * color.g; // std::pow(color.g, 2.2f); + float cblue = color.b * color.b; // std::pow(color.b, 2.2f); +#ifdef USE_SSE2 + __m128 crgba = _mm_set_ps(0.0f, cred, cgreen, cblue); +#endif + + float uscale = uvwidth / width; + float vscale = uvheight / height; + + for (int y = y0; y < y1; y++) + { + float vpix = v + vscale * (y + 0.5f - top); + const uint32_t* sline = src + ((int)vpix) * swidth; + uint32_t* dline = dest + y * dwidth; + + int x = x0; +#ifdef USE_SSE2 + while (x < x1) + { + float upix = u + uscale * (x + 0.5f - left); + __m128i spixel = _mm_cvtsi32_si128(sline[(int)upix]); + spixel = _mm_unpacklo_epi8(spixel, _mm_setzero_si128()); + spixel = _mm_unpacklo_epi16(spixel, _mm_setzero_si128()); + __m128 srgba = _mm_mul_ps(_mm_cvtepi32_ps(spixel), _mm_set_ps1(1.0f / 255.0f)); + + __m128i dpixel = _mm_cvtsi32_si128(dline[x]); + dpixel = _mm_unpacklo_epi8(dpixel, _mm_setzero_si128()); + dpixel = _mm_unpacklo_epi16(dpixel, _mm_setzero_si128()); + __m128 drgba = _mm_mul_ps(_mm_cvtepi32_ps(dpixel), _mm_set_ps1(1.0f / 255.0f)); + + // To linear + drgba = _mm_mul_ps(drgba, drgba); + + // dest.rgb = color.rgb * src.rgb + dest.rgb * (1-src.rgb) + __m128 frgba = _mm_add_ps(_mm_mul_ps(crgba, srgba), _mm_mul_ps(drgba, _mm_sub_ps(_mm_set_ps1(1.0f), srgba))); + + // To srgb + frgba = _mm_sqrt_ps(frgba); + + __m128i rgba = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(frgba, _mm_set_ps1(255.0f)), _mm_set_ps1(0.5f))); + rgba = _mm_packs_epi32(rgba, _mm_setzero_si128()); + rgba = _mm_packus_epi16(rgba, _mm_setzero_si128()); + dline[x] = ((uint32_t)_mm_cvtsi128_si32(rgba)) | 0xff000000; + x++; + } +#else + while (x < x1) + { + float upix = u + uscale * (x + 0.5f - left); + uint32_t spixel = sline[(int)upix]; + float sred = ((spixel >> 16) & 0xff) * (1.0f / 255.0f); + float sgreen = ((spixel >> 8) & 0xff) * (1.0f / 255.0f); + float sblue = (spixel & 0xff) * (1.0f / 255.0f); + + uint32_t dpixel = dline[x]; + float dred = ((dpixel >> 16) & 0xff) * (1.0f / 255.0f); + float dgreen = ((dpixel >> 8) & 0xff) * (1.0f / 255.0f); + float dblue = (dpixel & 0xff) * (1.0f / 255.0f); + + // To linear + dred = dred * dred; // std::pow(dred, 2.2f); + dgreen = dgreen * dgreen; // std::pow(dgreen, 2.2f); + dblue = dblue * dblue; // std::pow(dblue, 2.2f); + + // dest.rgb = color.rgb * src.rgb + dest.rgb * (1-src.rgb) + double fr = cred * sred + dred * (1.0f - sred); + double fg = cgreen * sgreen + dgreen * (1.0f - sgreen); + double fb = cblue * sblue + dblue * (1.0f - sblue); + + // To srgb + fr = std::sqrt(fr); // std::pow(fr, 1.0f / 2.2f); + fg = std::sqrt(fg); // std::pow(fg, 1.0f / 2.2f); + fb = std::sqrt(fb); // std::pow(fb, 1.0f / 2.2f); + + uint32_t r = (int)(fr * 255.0f + 0.5f); + uint32_t g = (int)(fg * 255.0f + 0.5f); + uint32_t b = (int)(fb * 255.0f + 0.5f); + dline[x] = 0xff000000 | (r << 16) | (g << 8) | b; + x++; + } +#endif + } + +#else + + uint32_t cred = (int32_t)clamp(color.r * 255.0f, 0.0f, 255.0f); + uint32_t cgreen = (int32_t)clamp(color.g * 255.0f, 0.0f, 255.0f); + uint32_t cblue = (int32_t)clamp(color.b * 255.0f, 0.0f, 255.0f); +#ifdef USE_SSE2 + __m128i crgba = _mm_set_epi16(0, cred, cgreen, cblue, 0, cred, cgreen, cblue); +#endif + + float uscale = uvwidth / width; + float vscale = uvheight / height; + + for (int y = y0; y < y1; y++) + { + float vpix = v + vscale * (y + 0.5f - top); + const uint32_t* sline = src + ((int)vpix) * swidth; + uint32_t* dline = dest + y * dwidth; + + int x = x0; +#ifdef USE_SSE2 + int ssex1 = x0 + (((x1 - x0) >> 1) << 1); + while (x < ssex1) + { + float upix0 = u + uscale * (x + 0.5f - left); + float upix1 = u + uscale * (x + 1 + 0.5f - left); + uint32_t spixel0 = sline[(int)upix0]; + uint32_t spixel1 = sline[(int)upix1]; + __m128i spixel = _mm_set_epi32(0, 0, spixel1, spixel0); + spixel = _mm_unpacklo_epi8(spixel, _mm_setzero_si128()); + + __m128i dpixel = _mm_loadl_epi64((const __m128i*)(dline + x)); + dpixel = _mm_unpacklo_epi8(dpixel, _mm_setzero_si128()); + + // Rescale from [0,255] to [0,256] + spixel = _mm_add_epi16(spixel, _mm_srli_epi16(spixel, 7)); + + // dest.rgb = color.rgb * src.rgb + dest.rgb * (1-src.rgb) + __m128i result = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(_mm_mullo_epi16(crgba, spixel), _mm_mullo_epi16(dpixel, _mm_sub_epi16(_mm_set1_epi16(256), spixel))), _mm_set1_epi16(127)), 8); + _mm_storel_epi64((__m128i*)(dline + x), _mm_or_si128(_mm_packus_epi16(result, _mm_setzero_si128()), _mm_set1_epi32(0xff000000))); + x += 2; + } +#endif + + while (x < x1) + { + float upix = u + uscale * (x + 0.5f - left); + uint32_t spixel = sline[(int)upix]; + uint32_t sred = (spixel >> 16) & 0xff; + uint32_t sgreen = (spixel >> 8) & 0xff; + uint32_t sblue = spixel & 0xff; + + uint32_t dpixel = dline[x]; + uint32_t dred = (dpixel >> 16) & 0xff; + uint32_t dgreen = (dpixel >> 8) & 0xff; + uint32_t dblue = dpixel & 0xff; + + // Rescale from [0,255] to [0,256] + sred += sred >> 7; + sgreen += sgreen >> 7; + sblue += sblue >> 7; + + // dest.rgb = color.rgb * src.rgb + dest.rgb * (1-src.rgb) + uint32_t r = (cred * sred + dred * (256 - sred) + 127) >> 8; + uint32_t g = (cgreen * sgreen + dgreen * (256 - sgreen) + 127) >> 8; + uint32_t b = (cblue * sblue + dblue * (256 - sblue) + 127) >> 8; + dline[x] = 0xff000000 | (r << 16) | (g << 8) | b; + x++; + } + } +#endif +} + +void BitmapCanvas::begin(const Colorf& color) +{ + uiscale = window->GetDpiScale(); + + uint32_t r = (int32_t)clamp(color.r * 255.0f, 0.0f, 255.0f); + uint32_t g = (int32_t)clamp(color.g * 255.0f, 0.0f, 255.0f); + uint32_t b = (int32_t)clamp(color.b * 255.0f, 0.0f, 255.0f); + uint32_t a = (int32_t)clamp(color.a * 255.0f, 0.0f, 255.0f); + uint32_t bgcolor = (a << 24) | (r << 16) | (g << 8) | b; + width = window->GetPixelWidth(); + height = window->GetPixelHeight(); + pixels.clear(); + pixels.resize(width * height, bgcolor); +} + +void BitmapCanvas::end() +{ + window->PresentBitmap(width, height, pixels.data()); +} + +void BitmapCanvas::begin3d() +{ +} + +void BitmapCanvas::end3d() +{ +} + +///////////////////////////////////////////////////////////////////////////// + +std::unique_ptr Canvas::create(DisplayWindow* window) +{ + return std::make_unique(window); +} diff --git a/libraries/ZWidget/src/core/font.cpp b/libraries/ZWidget/src/core/font.cpp new file mode 100644 index 0000000000..f646912a9c --- /dev/null +++ b/libraries/ZWidget/src/core/font.cpp @@ -0,0 +1,28 @@ + +#include "core/font.h" + +class FontImpl : public Font +{ +public: + FontImpl(const std::string& name, double height) : Name(name), Height(height) + { + } + + const std::string& GetName() const override + { + return Name; + } + + double GetHeight() const override + { + return Height; + } + + std::string Name; + double Height = 0.0; +}; + +std::shared_ptr Font::Create(const std::string& name, double height) +{ + return std::make_shared(name, height); +} diff --git a/libraries/ZWidget/src/core/image.cpp b/libraries/ZWidget/src/core/image.cpp new file mode 100644 index 0000000000..3998d78e81 --- /dev/null +++ b/libraries/ZWidget/src/core/image.cpp @@ -0,0 +1,110 @@ + +#include "core/image.h" +#include "core/resourcedata.h" +#include "picopng/picopng.h" +#include "nanosvg/nanosvg.h" +#include "nanosvg/nanosvgrast.h" +#include +#include + +class ImageImpl : public Image +{ +public: + ImageImpl(int width, int height, ImageFormat format, const void* data) : Width(width), Height(height), Format(format) + { + Data = std::make_unique(width * height); + if (data) + memcpy(Data.get(), data, width * height * sizeof(uint32_t)); + } + + int GetWidth() const override + { + return Width; + } + + int GetHeight() const override + { + return Height; + } + + ImageFormat GetFormat() const override + { + return Format; + } + + void* GetData() const override + { + return Data.get(); + } + + int Width = 0; + int Height = 0; + ImageFormat Format = {}; + std::unique_ptr Data; +}; + +std::shared_ptr Image::Create(int width, int height, ImageFormat format, const void* data) +{ + return std::make_shared(width, height, format, data); +} + +std::shared_ptr Image::LoadResource(const std::string& resourcename, double dpiscale) +{ + size_t extensionpos = resourcename.find_last_of("./\\"); + if (extensionpos == std::string::npos || resourcename[extensionpos] != '.') + throw std::runtime_error("Unsupported image format"); + std::string extension = resourcename.substr(extensionpos + 1); + for (char& c : extension) + { + if (c >= 'A' && c <= 'Z') + c = c - 'A' + 'a'; + } + + if (extension == "png") + { + auto filedata = LoadWidgetData(resourcename); + + std::vector pixels; + unsigned long width = 0, height = 0; + int result = decodePNG(pixels, width, height, (const unsigned char*)filedata.data(), filedata.size(), true); + if (result != 0) + throw std::runtime_error("Could not decode PNG file"); + + return Image::Create(width, height, ImageFormat::R8G8B8A8, pixels.data()); + } + else if (extension == "svg") + { + auto filedata = LoadWidgetData(resourcename); + filedata.push_back(0); + + NSVGimage* svgimage = nsvgParse((char*)filedata.data(), "px", (float)(96.0 * dpiscale)); + if (!svgimage) + throw std::runtime_error("Could not parse SVG file"); + + try + { + int width = (int)(svgimage->width * dpiscale); + int height = (int)(svgimage->height * dpiscale); + std::shared_ptr image = Image::Create(width, height, ImageFormat::R8G8B8A8, nullptr); + + NSVGrasterizer* rast = nsvgCreateRasterizer(); + if (!rast) + throw std::runtime_error("Could not create SVG rasterizer"); + + nsvgRasterize(rast, svgimage, 0.0f, 0.0f, (float)dpiscale, (unsigned char*)image->GetData(), width, height, width * 4); + + nsvgDeleteRasterizer(rast); + nsvgDelete(svgimage); + return image; + } + catch (...) + { + nsvgDelete(svgimage); + throw; + } + } + else + { + throw std::runtime_error("Unsupported image format"); + } +} diff --git a/libraries/ZWidget/src/core/nanosvg/nanosvg.cpp b/libraries/ZWidget/src/core/nanosvg/nanosvg.cpp new file mode 100644 index 0000000000..764b854b07 --- /dev/null +++ b/libraries/ZWidget/src/core/nanosvg/nanosvg.cpp @@ -0,0 +1,6 @@ + +#define NANOSVG_IMPLEMENTATION +#include "nanosvg.h" + +#define NANOSVGRAST_IMPLEMENTATION +#include "nanosvgrast.h" diff --git a/libraries/ZWidget/src/core/nanosvg/nanosvg.h b/libraries/ZWidget/src/core/nanosvg/nanosvg.h new file mode 100644 index 0000000000..55f9bc5ea4 --- /dev/null +++ b/libraries/ZWidget/src/core/nanosvg/nanosvg.h @@ -0,0 +1,3107 @@ +/* + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org + * + * 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. + * + * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example + * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/) + * + * Arc calculation code based on canvg (https://code.google.com/p/canvg/) + * + * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + * + */ + +#ifndef NANOSVG_H +#define NANOSVG_H + +#ifndef NANOSVG_CPLUSPLUS +#ifdef __cplusplus +extern "C" { +#endif +#endif + +// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes. +// +// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game. +// +// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request! +// +// The shapes in the SVG images are transformed by the viewBox and converted to specified units. +// That is, you should get the same looking data as your designed in your favorite app. +// +// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose +// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters. +// +// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. +// DPI (dots-per-inch) controls how the unit conversion is done. +// +// If you don't know or care about the units stuff, "px" and 96 should get you going. + + +/* Example Usage: + // Load SVG + NSVGimage* image; + image = nsvgParseFromFile("test.svg", "px", 96); + printf("size: %f x %f\n", image->width, image->height); + // Use... + for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) { + for (NSVGpath *path = shape->paths; path != NULL; path = path->next) { + for (int i = 0; i < path->npts-1; i += 3) { + float* p = &path->pts[i*2]; + drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]); + } + } + } + // Delete + nsvgDelete(image); +*/ + +enum NSVGpaintType { + NSVG_PAINT_UNDEF = -1, + NSVG_PAINT_NONE = 0, + NSVG_PAINT_COLOR = 1, + NSVG_PAINT_LINEAR_GRADIENT = 2, + NSVG_PAINT_RADIAL_GRADIENT = 3 +}; + +enum NSVGspreadType { + NSVG_SPREAD_PAD = 0, + NSVG_SPREAD_REFLECT = 1, + NSVG_SPREAD_REPEAT = 2 +}; + +enum NSVGlineJoin { + NSVG_JOIN_MITER = 0, + NSVG_JOIN_ROUND = 1, + NSVG_JOIN_BEVEL = 2 +}; + +enum NSVGlineCap { + NSVG_CAP_BUTT = 0, + NSVG_CAP_ROUND = 1, + NSVG_CAP_SQUARE = 2 +}; + +enum NSVGfillRule { + NSVG_FILLRULE_NONZERO = 0, + NSVG_FILLRULE_EVENODD = 1 +}; + +enum NSVGflags { + NSVG_FLAGS_VISIBLE = 0x01 +}; + +typedef struct NSVGgradientStop { + unsigned int color; + float offset; +} NSVGgradientStop; + +typedef struct NSVGgradient { + float xform[6]; + char spread; + float fx, fy; + int nstops; + NSVGgradientStop stops[1]; +} NSVGgradient; + +typedef struct NSVGpaint { + signed char type; + union { + unsigned int color; + NSVGgradient* gradient; + }; +} NSVGpaint; + +typedef struct NSVGpath +{ + float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ... + int npts; // Total number of bezier points. + char closed; // Flag indicating if shapes should be treated as closed. + float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + struct NSVGpath* next; // Pointer to next path, or NULL if last element. +} NSVGpath; + +typedef struct NSVGshape +{ + char id[64]; // Optional 'id' attr of the shape or its group + NSVGpaint fill; // Fill paint + NSVGpaint stroke; // Stroke paint + float opacity; // Opacity of the shape. + float strokeWidth; // Stroke width (scaled). + float strokeDashOffset; // Stroke dash offset (scaled). + float strokeDashArray[8]; // Stroke dash array (scaled). + char strokeDashCount; // Number of dash values in dash array. + char strokeLineJoin; // Stroke join type. + char strokeLineCap; // Stroke cap type. + float miterLimit; // Miter limit + char fillRule; // Fill rule, see NSVGfillRule. + unsigned char flags; // Logical or of NSVG_FLAGS_* flags + float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + char fillGradient[64]; // Optional 'id' of fill gradient + char strokeGradient[64]; // Optional 'id' of stroke gradient + float xform[6]; // Root transformation for fill/stroke gradient + NSVGpath* paths; // Linked list of paths in the image. + struct NSVGshape* next; // Pointer to next shape, or NULL if last element. +} NSVGshape; + +typedef struct NSVGimage +{ + float width; // Width of the image. + float height; // Height of the image. + NSVGshape* shapes; // Linked list of shapes in the image. +} NSVGimage; + +// Parses SVG file from a file, returns SVG image as paths. +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi); + +// Parses SVG file from a null terminated string, returns SVG image as paths. +// Important note: changes the string. +NSVGimage* nsvgParse(char* input, const char* units, float dpi); + +// Duplicates a path. +NSVGpath* nsvgDuplicatePath(NSVGpath* p); + +// Deletes an image. +void nsvgDelete(NSVGimage* image); + +#ifndef NANOSVG_CPLUSPLUS +#ifdef __cplusplus +} +#endif +#endif + +#ifdef NANOSVG_IMPLEMENTATION + +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4244) +#endif + +#define NSVG_PI (3.14159265358979323846264338327f) +#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs. + +#define NSVG_ALIGN_MIN 0 +#define NSVG_ALIGN_MID 1 +#define NSVG_ALIGN_MAX 2 +#define NSVG_ALIGN_NONE 0 +#define NSVG_ALIGN_MEET 1 +#define NSVG_ALIGN_SLICE 2 + +#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0) +#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16)) + +#ifdef _MSC_VER + #pragma warning (disable: 4996) // Switch off security warnings + #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings + #ifdef __cplusplus + #define NSVG_INLINE inline + #else + #define NSVG_INLINE + #endif +#else + #define NSVG_INLINE inline +#endif + + +static int nsvg__isspace(char c) +{ + return strchr(" \t\n\v\f\r", c) != 0; +} + +static int nsvg__isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; } +static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; } + + +// Simple XML parser + +#define NSVG_XML_TAG 1 +#define NSVG_XML_CONTENT 2 +#define NSVG_XML_MAX_ATTRIBS 256 + +static void nsvg__parseContent(char* s, + void (*contentCb)(void* ud, const char* s), + void* ud) +{ + // Trim start white spaces + while (*s && nsvg__isspace(*s)) s++; + if (!*s) return; + + if (contentCb) + (*contentCb)(ud, s); +} + +static void nsvg__parseElement(char* s, + void (*startelCb)(void* ud, const char* el, const char** attr), + void (*endelCb)(void* ud, const char* el), + void* ud) +{ + const char* attr[NSVG_XML_MAX_ATTRIBS]; + int nattr = 0; + char* name; + int start = 0; + int end = 0; + char quote; + + // Skip white space after the '<' + while (*s && nsvg__isspace(*s)) s++; + + // Check if the tag is end tag + if (*s == '/') { + s++; + end = 1; + } else { + start = 1; + } + + // Skip comments, data and preprocessor stuff. + if (!*s || *s == '?' || *s == '!') + return; + + // Get tag name + name = s; + while (*s && !nsvg__isspace(*s)) s++; + if (*s) { *s++ = '\0'; } + + // Get attribs + while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) { + char* name = NULL; + char* value = NULL; + + // Skip white space before the attrib name + while (*s && nsvg__isspace(*s)) s++; + if (!*s) break; + if (*s == '/') { + end = 1; + break; + } + name = s; + // Find end of the attrib name. + while (*s && !nsvg__isspace(*s) && *s != '=') s++; + if (*s) { *s++ = '\0'; } + // Skip until the beginning of the value. + while (*s && *s != '\"' && *s != '\'') s++; + if (!*s) break; + quote = *s; + s++; + // Store value and find the end of it. + value = s; + while (*s && *s != quote) s++; + if (*s) { *s++ = '\0'; } + + // Store only well formed attributes + if (name && value) { + attr[nattr++] = name; + attr[nattr++] = value; + } + } + + // List terminator + attr[nattr++] = 0; + attr[nattr++] = 0; + + // Call callbacks. + if (start && startelCb) + (*startelCb)(ud, name, attr); + if (end && endelCb) + (*endelCb)(ud, name); +} + +int nsvg__parseXML(char* input, + void (*startelCb)(void* ud, const char* el, const char** attr), + void (*endelCb)(void* ud, const char* el), + void (*contentCb)(void* ud, const char* s), + void* ud) +{ + char* s = input; + char* mark = s; + int state = NSVG_XML_CONTENT; + while (*s) { + if (*s == '<' && state == NSVG_XML_CONTENT) { + // Start of a tag + *s++ = '\0'; + nsvg__parseContent(mark, contentCb, ud); + mark = s; + state = NSVG_XML_TAG; + } else if (*s == '>' && state == NSVG_XML_TAG) { + // Start of a content or new tag. + *s++ = '\0'; + nsvg__parseElement(mark, startelCb, endelCb, ud); + mark = s; + state = NSVG_XML_CONTENT; + } else { + s++; + } + } + + return 1; +} + + +/* Simple SVG parser. */ + +#define NSVG_MAX_ATTR 128 + +enum NSVGgradientUnits { + NSVG_USER_SPACE = 0, + NSVG_OBJECT_SPACE = 1 +}; + +#define NSVG_MAX_DASHES 8 + +enum NSVGunits { + NSVG_UNITS_USER, + NSVG_UNITS_PX, + NSVG_UNITS_PT, + NSVG_UNITS_PC, + NSVG_UNITS_MM, + NSVG_UNITS_CM, + NSVG_UNITS_IN, + NSVG_UNITS_PERCENT, + NSVG_UNITS_EM, + NSVG_UNITS_EX +}; + +typedef struct NSVGcoordinate { + float value; + int units; +} NSVGcoordinate; + +typedef struct NSVGlinearData { + NSVGcoordinate x1, y1, x2, y2; +} NSVGlinearData; + +typedef struct NSVGradialData { + NSVGcoordinate cx, cy, r, fx, fy; +} NSVGradialData; + +typedef struct NSVGgradientData +{ + char id[64]; + char ref[64]; + signed char type; + union { + NSVGlinearData linear; + NSVGradialData radial; + }; + char spread; + char units; + float xform[6]; + int nstops; + NSVGgradientStop* stops; + struct NSVGgradientData* next; +} NSVGgradientData; + +typedef struct NSVGattrib +{ + char id[64]; + float xform[6]; + unsigned int fillColor; + unsigned int strokeColor; + float opacity; + float fillOpacity; + float strokeOpacity; + char fillGradient[64]; + char strokeGradient[64]; + float strokeWidth; + float strokeDashOffset; + float strokeDashArray[NSVG_MAX_DASHES]; + int strokeDashCount; + char strokeLineJoin; + char strokeLineCap; + float miterLimit; + char fillRule; + float fontSize; + unsigned int stopColor; + float stopOpacity; + float stopOffset; + char hasFill; + char hasStroke; + char visible; +} NSVGattrib; + +typedef struct NSVGparser +{ + NSVGattrib attr[NSVG_MAX_ATTR]; + int attrHead; + float* pts; + int npts; + int cpts; + NSVGpath* plist; + NSVGimage* image; + NSVGgradientData* gradients; + NSVGshape* shapesTail; + float viewMinx, viewMiny, viewWidth, viewHeight; + int alignX, alignY, alignType; + float dpi; + char pathFlag; + char defsFlag; +} NSVGparser; + +static void nsvg__xformIdentity(float* t) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = 0.0f; t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformSetTranslation(float* t, float tx, float ty) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = 0.0f; t[3] = 1.0f; + t[4] = tx; t[5] = ty; +} + +static void nsvg__xformSetScale(float* t, float sx, float sy) +{ + t[0] = sx; t[1] = 0.0f; + t[2] = 0.0f; t[3] = sy; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformSetSkewX(float* t, float a) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = tanf(a); t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformSetSkewY(float* t, float a) +{ + t[0] = 1.0f; t[1] = tanf(a); + t[2] = 0.0f; t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformSetRotation(float* t, float a) +{ + float cs = cosf(a), sn = sinf(a); + t[0] = cs; t[1] = sn; + t[2] = -sn; t[3] = cs; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformMultiply(float* t, float* s) +{ + float t0 = t[0] * s[0] + t[1] * s[2]; + float t2 = t[2] * s[0] + t[3] * s[2]; + float t4 = t[4] * s[0] + t[5] * s[2] + s[4]; + t[1] = t[0] * s[1] + t[1] * s[3]; + t[3] = t[2] * s[1] + t[3] * s[3]; + t[5] = t[4] * s[1] + t[5] * s[3] + s[5]; + t[0] = t0; + t[2] = t2; + t[4] = t4; +} + +static void nsvg__xformInverse(float* inv, float* t) +{ + double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1]; + if (det > -1e-6 && det < 1e-6) { + nsvg__xformIdentity(t); + return; + } + invdet = 1.0 / det; + inv[0] = (float)(t[3] * invdet); + inv[2] = (float)(-t[2] * invdet); + inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet); + inv[1] = (float)(-t[1] * invdet); + inv[3] = (float)(t[0] * invdet); + inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet); +} + +static void nsvg__xformPremultiply(float* t, float* s) +{ + float s2[6]; + memcpy(s2, s, sizeof(float)*6); + nsvg__xformMultiply(s2, t); + memcpy(t, s2, sizeof(float)*6); +} + +static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t) +{ + *dx = x*t[0] + y*t[2] + t[4]; + *dy = x*t[1] + y*t[3] + t[5]; +} + +static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t) +{ + *dx = x*t[0] + y*t[2]; + *dy = x*t[1] + y*t[3]; +} + +#define NSVG_EPSILON (1e-12) + +static int nsvg__ptInBounds(float* pt, float* bounds) +{ + return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3]; +} + + +static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3) +{ + double it = 1.0-t; + return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3; +} + +static void nsvg__curveBounds(float* bounds, float* curve) +{ + int i, j, count; + double roots[2], a, b, c, b2ac, t, v; + float* v0 = &curve[0]; + float* v1 = &curve[2]; + float* v2 = &curve[4]; + float* v3 = &curve[6]; + + // Start the bounding box by end points + bounds[0] = nsvg__minf(v0[0], v3[0]); + bounds[1] = nsvg__minf(v0[1], v3[1]); + bounds[2] = nsvg__maxf(v0[0], v3[0]); + bounds[3] = nsvg__maxf(v0[1], v3[1]); + + // Bezier curve fits inside the convex hull of it's control points. + // If control points are inside the bounds, we're done. + if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds)) + return; + + // Add bezier curve inflection points in X and Y. + for (i = 0; i < 2; i++) { + a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i]; + b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i]; + c = 3.0 * v1[i] - 3.0 * v0[i]; + count = 0; + if (fabs(a) < NSVG_EPSILON) { + if (fabs(b) > NSVG_EPSILON) { + t = -c / b; + if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) + roots[count++] = t; + } + } else { + b2ac = b*b - 4.0*c*a; + if (b2ac > NSVG_EPSILON) { + t = (-b + sqrt(b2ac)) / (2.0 * a); + if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) + roots[count++] = t; + t = (-b - sqrt(b2ac)) / (2.0 * a); + if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) + roots[count++] = t; + } + } + for (j = 0; j < count; j++) { + v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]); + bounds[0+i] = nsvg__minf(bounds[0+i], (float)v); + bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v); + } + } +} + +static NSVGparser* nsvg__createParser(void) +{ + NSVGparser* p; + p = (NSVGparser*)malloc(sizeof(NSVGparser)); + if (p == NULL) goto error; + memset(p, 0, sizeof(NSVGparser)); + + p->image = (NSVGimage*)malloc(sizeof(NSVGimage)); + if (p->image == NULL) goto error; + memset(p->image, 0, sizeof(NSVGimage)); + + // Init style + nsvg__xformIdentity(p->attr[0].xform); + memset(p->attr[0].id, 0, sizeof p->attr[0].id); + p->attr[0].fillColor = NSVG_RGB(0,0,0); + p->attr[0].strokeColor = NSVG_RGB(0,0,0); + p->attr[0].opacity = 1; + p->attr[0].fillOpacity = 1; + p->attr[0].strokeOpacity = 1; + p->attr[0].stopOpacity = 1; + p->attr[0].strokeWidth = 1; + p->attr[0].strokeLineJoin = NSVG_JOIN_MITER; + p->attr[0].strokeLineCap = NSVG_CAP_BUTT; + p->attr[0].miterLimit = 4; + p->attr[0].fillRule = NSVG_FILLRULE_NONZERO; + p->attr[0].hasFill = 1; + p->attr[0].visible = 1; + + return p; + +error: + if (p) { + if (p->image) free(p->image); + free(p); + } + return NULL; +} + +static void nsvg__deletePaths(NSVGpath* path) +{ + while (path) { + NSVGpath *next = path->next; + if (path->pts != NULL) + free(path->pts); + free(path); + path = next; + } +} + +static void nsvg__deletePaint(NSVGpaint* paint) +{ + if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT) + free(paint->gradient); +} + +static void nsvg__deleteGradientData(NSVGgradientData* grad) +{ + NSVGgradientData* next; + while (grad != NULL) { + next = grad->next; + free(grad->stops); + free(grad); + grad = next; + } +} + +static void nsvg__deleteParser(NSVGparser* p) +{ + if (p != NULL) { + nsvg__deletePaths(p->plist); + nsvg__deleteGradientData(p->gradients); + nsvgDelete(p->image); + free(p->pts); + free(p); + } +} + +static void nsvg__resetPath(NSVGparser* p) +{ + p->npts = 0; +} + +static void nsvg__addPoint(NSVGparser* p, float x, float y) +{ + if (p->npts+1 > p->cpts) { + p->cpts = p->cpts ? p->cpts*2 : 8; + p->pts = (float*)realloc(p->pts, p->cpts*2*sizeof(float)); + if (!p->pts) return; + } + p->pts[p->npts*2+0] = x; + p->pts[p->npts*2+1] = y; + p->npts++; +} + +static void nsvg__moveTo(NSVGparser* p, float x, float y) +{ + if (p->npts > 0) { + p->pts[(p->npts-1)*2+0] = x; + p->pts[(p->npts-1)*2+1] = y; + } else { + nsvg__addPoint(p, x, y); + } +} + +static void nsvg__lineTo(NSVGparser* p, float x, float y) +{ + float px,py, dx,dy; + if (p->npts > 0) { + px = p->pts[(p->npts-1)*2+0]; + py = p->pts[(p->npts-1)*2+1]; + dx = x - px; + dy = y - py; + nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f); + nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f); + nsvg__addPoint(p, x, y); + } +} + +static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) +{ + if (p->npts > 0) { + nsvg__addPoint(p, cpx1, cpy1); + nsvg__addPoint(p, cpx2, cpy2); + nsvg__addPoint(p, x, y); + } +} + +static NSVGattrib* nsvg__getAttr(NSVGparser* p) +{ + return &p->attr[p->attrHead]; +} + +static void nsvg__pushAttr(NSVGparser* p) +{ + if (p->attrHead < NSVG_MAX_ATTR-1) { + p->attrHead++; + memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib)); + } +} + +static void nsvg__popAttr(NSVGparser* p) +{ + if (p->attrHead > 0) + p->attrHead--; +} + +static float nsvg__actualOrigX(NSVGparser* p) +{ + return p->viewMinx; +} + +static float nsvg__actualOrigY(NSVGparser* p) +{ + return p->viewMiny; +} + +static float nsvg__actualWidth(NSVGparser* p) +{ + return p->viewWidth; +} + +static float nsvg__actualHeight(NSVGparser* p) +{ + return p->viewHeight; +} + +static float nsvg__actualLength(NSVGparser* p) +{ + float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p); + return sqrtf(w*w + h*h) / sqrtf(2.0f); +} + +static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length) +{ + NSVGattrib* attr = nsvg__getAttr(p); + switch (c.units) { + case NSVG_UNITS_USER: return c.value; + case NSVG_UNITS_PX: return c.value; + case NSVG_UNITS_PT: return c.value / 72.0f * p->dpi; + case NSVG_UNITS_PC: return c.value / 6.0f * p->dpi; + case NSVG_UNITS_MM: return c.value / 25.4f * p->dpi; + case NSVG_UNITS_CM: return c.value / 2.54f * p->dpi; + case NSVG_UNITS_IN: return c.value * p->dpi; + case NSVG_UNITS_EM: return c.value * attr->fontSize; + case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; // x-height of Helvetica. + case NSVG_UNITS_PERCENT: return orig + c.value / 100.0f * length; + default: return c.value; + } + return c.value; +} + +static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id) +{ + NSVGgradientData* grad = p->gradients; + if (id == NULL || *id == '\0') + return NULL; + while (grad != NULL) { + if (strcmp(grad->id, id) == 0) + return grad; + grad = grad->next; + } + return NULL; +} + +static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, float *xform, signed char* paintType) +{ + NSVGgradientData* data = NULL; + NSVGgradientData* ref = NULL; + NSVGgradientStop* stops = NULL; + NSVGgradient* grad; + float ox, oy, sw, sh, sl; + int nstops = 0; + int refIter; + + data = nsvg__findGradientData(p, id); + if (data == NULL) return NULL; + + // TODO: use ref to fill in all unset values too. + ref = data; + refIter = 0; + while (ref != NULL) { + NSVGgradientData* nextRef = NULL; + if (stops == NULL && ref->stops != NULL) { + stops = ref->stops; + nstops = ref->nstops; + break; + } + nextRef = nsvg__findGradientData(p, ref->ref); + if (nextRef == ref) break; // prevent infite loops on malformed data + ref = nextRef; + refIter++; + if (refIter > 32) break; // prevent infite loops on malformed data + } + if (stops == NULL) return NULL; + + grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1)); + if (grad == NULL) return NULL; + + // The shape width and height. + if (data->units == NSVG_OBJECT_SPACE) { + ox = localBounds[0]; + oy = localBounds[1]; + sw = localBounds[2] - localBounds[0]; + sh = localBounds[3] - localBounds[1]; + } else { + ox = nsvg__actualOrigX(p); + oy = nsvg__actualOrigY(p); + sw = nsvg__actualWidth(p); + sh = nsvg__actualHeight(p); + } + sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f); + + if (data->type == NSVG_PAINT_LINEAR_GRADIENT) { + float x1, y1, x2, y2, dx, dy; + x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw); + y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh); + x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw); + y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh); + // Calculate transform aligned to the line + dx = x2 - x1; + dy = y2 - y1; + grad->xform[0] = dy; grad->xform[1] = -dx; + grad->xform[2] = dx; grad->xform[3] = dy; + grad->xform[4] = x1; grad->xform[5] = y1; + } else { + float cx, cy, fx, fy, r; + cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw); + cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh); + fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw); + fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh); + r = nsvg__convertToPixels(p, data->radial.r, 0, sl); + // Calculate transform aligned to the circle + grad->xform[0] = r; grad->xform[1] = 0; + grad->xform[2] = 0; grad->xform[3] = r; + grad->xform[4] = cx; grad->xform[5] = cy; + grad->fx = fx / r; + grad->fy = fy / r; + } + + nsvg__xformMultiply(grad->xform, data->xform); + nsvg__xformMultiply(grad->xform, xform); + + grad->spread = data->spread; + memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop)); + grad->nstops = nstops; + + *paintType = data->type; + + return grad; +} + +static float nsvg__getAverageScale(float* t) +{ + float sx = sqrtf(t[0]*t[0] + t[2]*t[2]); + float sy = sqrtf(t[1]*t[1] + t[3]*t[3]); + return (sx + sy) * 0.5f; +} + +static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform) +{ + NSVGpath* path; + float curve[4*2], curveBounds[4]; + int i, first = 1; + for (path = shape->paths; path != NULL; path = path->next) { + nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform); + for (i = 0; i < path->npts-1; i += 3) { + nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform); + nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform); + nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform); + nsvg__curveBounds(curveBounds, curve); + if (first) { + bounds[0] = curveBounds[0]; + bounds[1] = curveBounds[1]; + bounds[2] = curveBounds[2]; + bounds[3] = curveBounds[3]; + first = 0; + } else { + bounds[0] = nsvg__minf(bounds[0], curveBounds[0]); + bounds[1] = nsvg__minf(bounds[1], curveBounds[1]); + bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]); + bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]); + } + curve[0] = curve[6]; + curve[1] = curve[7]; + } + } +} + +static void nsvg__addShape(NSVGparser* p) +{ + NSVGattrib* attr = nsvg__getAttr(p); + float scale = 1.0f; + NSVGshape* shape; + NSVGpath* path; + int i; + + if (p->plist == NULL) + return; + + shape = (NSVGshape*)malloc(sizeof(NSVGshape)); + if (shape == NULL) goto error; + memset(shape, 0, sizeof(NSVGshape)); + + memcpy(shape->id, attr->id, sizeof shape->id); + memcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient); + memcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient); + memcpy(shape->xform, attr->xform, sizeof shape->xform); + scale = nsvg__getAverageScale(attr->xform); + shape->strokeWidth = attr->strokeWidth * scale; + shape->strokeDashOffset = attr->strokeDashOffset * scale; + shape->strokeDashCount = (char)attr->strokeDashCount; + for (i = 0; i < attr->strokeDashCount; i++) + shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale; + shape->strokeLineJoin = attr->strokeLineJoin; + shape->strokeLineCap = attr->strokeLineCap; + shape->miterLimit = attr->miterLimit; + shape->fillRule = attr->fillRule; + shape->opacity = attr->opacity; + + shape->paths = p->plist; + p->plist = NULL; + + // Calculate shape bounds + shape->bounds[0] = shape->paths->bounds[0]; + shape->bounds[1] = shape->paths->bounds[1]; + shape->bounds[2] = shape->paths->bounds[2]; + shape->bounds[3] = shape->paths->bounds[3]; + for (path = shape->paths->next; path != NULL; path = path->next) { + shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]); + shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]); + shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]); + shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]); + } + + // Set fill + if (attr->hasFill == 0) { + shape->fill.type = NSVG_PAINT_NONE; + } else if (attr->hasFill == 1) { + shape->fill.type = NSVG_PAINT_COLOR; + shape->fill.color = attr->fillColor; + shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24; + } else if (attr->hasFill == 2) { + shape->fill.type = NSVG_PAINT_UNDEF; + } + + // Set stroke + if (attr->hasStroke == 0) { + shape->stroke.type = NSVG_PAINT_NONE; + } else if (attr->hasStroke == 1) { + shape->stroke.type = NSVG_PAINT_COLOR; + shape->stroke.color = attr->strokeColor; + shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24; + } else if (attr->hasStroke == 2) { + shape->stroke.type = NSVG_PAINT_UNDEF; + } + + // Set flags + shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00); + + // Add to tail + if (p->image->shapes == NULL) + p->image->shapes = shape; + else + p->shapesTail->next = shape; + p->shapesTail = shape; + + return; + +error: + if (shape) free(shape); +} + +static void nsvg__addPath(NSVGparser* p, char closed) +{ + NSVGattrib* attr = nsvg__getAttr(p); + NSVGpath* path = NULL; + float bounds[4]; + float* curve; + int i; + + if (p->npts < 4) + return; + + if (closed) + nsvg__lineTo(p, p->pts[0], p->pts[1]); + + // Expect 1 + N*3 points (N = number of cubic bezier segments). + if ((p->npts % 3) != 1) + return; + + path = (NSVGpath*)malloc(sizeof(NSVGpath)); + if (path == NULL) goto error; + memset(path, 0, sizeof(NSVGpath)); + + path->pts = (float*)malloc(p->npts*2*sizeof(float)); + if (path->pts == NULL) goto error; + path->closed = closed; + path->npts = p->npts; + + // Transform path. + for (i = 0; i < p->npts; ++i) + nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform); + + // Find bounds + for (i = 0; i < path->npts-1; i += 3) { + curve = &path->pts[i*2]; + nsvg__curveBounds(bounds, curve); + if (i == 0) { + path->bounds[0] = bounds[0]; + path->bounds[1] = bounds[1]; + path->bounds[2] = bounds[2]; + path->bounds[3] = bounds[3]; + } else { + path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]); + path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]); + path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]); + path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]); + } + } + + path->next = p->plist; + p->plist = path; + + return; + +error: + if (path != NULL) { + if (path->pts != NULL) free(path->pts); + free(path); + } +} + +// We roll our own string to float because the std library one uses locale and messes things up. +static double nsvg__atof(const char* s) +{ + char* cur = (char*)s; + char* end = NULL; + double res = 0.0, sign = 1.0; + long long intPart = 0, fracPart = 0; + char hasIntPart = 0, hasFracPart = 0; + + // Parse optional sign + if (*cur == '+') { + cur++; + } else if (*cur == '-') { + sign = -1; + cur++; + } + + // Parse integer part + if (nsvg__isdigit(*cur)) { + // Parse digit sequence + intPart = strtoll(cur, &end, 10); + if (cur != end) { + res = (double)intPart; + hasIntPart = 1; + cur = end; + } + } + + // Parse fractional part. + if (*cur == '.') { + cur++; // Skip '.' + if (nsvg__isdigit(*cur)) { + // Parse digit sequence + fracPart = strtoll(cur, &end, 10); + if (cur != end) { + res += (double)fracPart / pow(10.0, (double)(end - cur)); + hasFracPart = 1; + cur = end; + } + } + } + + // A valid number should have integer or fractional part. + if (!hasIntPart && !hasFracPart) + return 0.0; + + // Parse optional exponent + if (*cur == 'e' || *cur == 'E') { + long expPart = 0; + cur++; // skip 'E' + expPart = strtol(cur, &end, 10); // Parse digit sequence with sign + if (cur != end) { + res *= pow(10.0, (double)expPart); + } + } + + return res * sign; +} + + +static const char* nsvg__parseNumber(const char* s, char* it, const int size) +{ + const int last = size-1; + int i = 0; + + // sign + if (*s == '-' || *s == '+') { + if (i < last) it[i++] = *s; + s++; + } + // integer part + while (*s && nsvg__isdigit(*s)) { + if (i < last) it[i++] = *s; + s++; + } + if (*s == '.') { + // decimal point + if (i < last) it[i++] = *s; + s++; + // fraction part + while (*s && nsvg__isdigit(*s)) { + if (i < last) it[i++] = *s; + s++; + } + } + // exponent + if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) { + if (i < last) it[i++] = *s; + s++; + if (*s == '-' || *s == '+') { + if (i < last) it[i++] = *s; + s++; + } + while (*s && nsvg__isdigit(*s)) { + if (i < last) it[i++] = *s; + s++; + } + } + it[i] = '\0'; + + return s; +} + +static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it) +{ + it[0] = '\0'; + while (*s && (nsvg__isspace(*s) || *s == ',')) s++; + if (!*s) return s; + if (*s == '0' || *s == '1') { + it[0] = *s++; + it[1] = '\0'; + return s; + } + return s; +} + +static const char* nsvg__getNextPathItem(const char* s, char* it) +{ + it[0] = '\0'; + // Skip white spaces and commas + while (*s && (nsvg__isspace(*s) || *s == ',')) s++; + if (!*s) return s; + if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) { + s = nsvg__parseNumber(s, it, 64); + } else { + // Parse command + it[0] = *s++; + it[1] = '\0'; + return s; + } + + return s; +} + +static unsigned int nsvg__parseColorHex(const char* str) +{ + unsigned int r=0, g=0, b=0; + if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3 ) // 2 digit hex + return NSVG_RGB(r, g, b); + if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3 ) // 1 digit hex, e.g. #abc -> 0xccbbaa + return NSVG_RGB(r*17, g*17, b*17); // same effect as (r<<4|r), (g<<4|g), .. + return NSVG_RGB(128, 128, 128); +} + +// Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters). +// This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors +// for backwards compatibility. Note: other image viewers return black instead. + +static unsigned int nsvg__parseColorRGB(const char* str) +{ + int i; + unsigned int rgbi[3]; + float rgbf[3]; + // try decimal integers first + if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) { + // integers failed, try percent values (float, locale independent) + const char delimiter[3] = {',', ',', ')'}; + str += 4; // skip "rgb(" + for (i = 0; i < 3; i++) { + while (*str && (nsvg__isspace(*str))) str++; // skip leading spaces + if (*str == '+') str++; // skip '+' (don't allow '-') + if (!*str) break; + rgbf[i] = nsvg__atof(str); + + // Note 1: it would be great if nsvg__atof() returned how many + // bytes it consumed but it doesn't. We need to skip the number, + // the '%' character, spaces, and the delimiter ',' or ')'. + + // Note 2: The following code does not allow values like "33.%", + // i.e. a decimal point w/o fractional part, but this is consistent + // with other image viewers, e.g. firefox, chrome, eog, gimp. + + while (*str && nsvg__isdigit(*str)) str++; // skip integer part + if (*str == '.') { + str++; + if (!nsvg__isdigit(*str)) break; // error: no digit after '.' + while (*str && nsvg__isdigit(*str)) str++; // skip fractional part + } + if (*str == '%') str++; else break; + while (nsvg__isspace(*str)) str++; + if (*str == delimiter[i]) str++; + else break; + } + if (i == 3) { + rgbi[0] = roundf(rgbf[0] * 2.55f); + rgbi[1] = roundf(rgbf[1] * 2.55f); + rgbi[2] = roundf(rgbf[2] * 2.55f); + } else { + rgbi[0] = rgbi[1] = rgbi[2] = 128; + } + } + // clip values as the CSS spec requires + for (i = 0; i < 3; i++) { + if (rgbi[i] > 255) rgbi[i] = 255; + } + return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]); +} + +typedef struct NSVGNamedColor { + const char* name; + unsigned int color; +} NSVGNamedColor; + +NSVGNamedColor nsvg__colors[] = { + + { "red", NSVG_RGB(255, 0, 0) }, + { "green", NSVG_RGB( 0, 128, 0) }, + { "blue", NSVG_RGB( 0, 0, 255) }, + { "yellow", NSVG_RGB(255, 255, 0) }, + { "cyan", NSVG_RGB( 0, 255, 255) }, + { "magenta", NSVG_RGB(255, 0, 255) }, + { "black", NSVG_RGB( 0, 0, 0) }, + { "grey", NSVG_RGB(128, 128, 128) }, + { "gray", NSVG_RGB(128, 128, 128) }, + { "white", NSVG_RGB(255, 255, 255) }, + +#ifdef NANOSVG_ALL_COLOR_KEYWORDS + { "aliceblue", NSVG_RGB(240, 248, 255) }, + { "antiquewhite", NSVG_RGB(250, 235, 215) }, + { "aqua", NSVG_RGB( 0, 255, 255) }, + { "aquamarine", NSVG_RGB(127, 255, 212) }, + { "azure", NSVG_RGB(240, 255, 255) }, + { "beige", NSVG_RGB(245, 245, 220) }, + { "bisque", NSVG_RGB(255, 228, 196) }, + { "blanchedalmond", NSVG_RGB(255, 235, 205) }, + { "blueviolet", NSVG_RGB(138, 43, 226) }, + { "brown", NSVG_RGB(165, 42, 42) }, + { "burlywood", NSVG_RGB(222, 184, 135) }, + { "cadetblue", NSVG_RGB( 95, 158, 160) }, + { "chartreuse", NSVG_RGB(127, 255, 0) }, + { "chocolate", NSVG_RGB(210, 105, 30) }, + { "coral", NSVG_RGB(255, 127, 80) }, + { "cornflowerblue", NSVG_RGB(100, 149, 237) }, + { "cornsilk", NSVG_RGB(255, 248, 220) }, + { "crimson", NSVG_RGB(220, 20, 60) }, + { "darkblue", NSVG_RGB( 0, 0, 139) }, + { "darkcyan", NSVG_RGB( 0, 139, 139) }, + { "darkgoldenrod", NSVG_RGB(184, 134, 11) }, + { "darkgray", NSVG_RGB(169, 169, 169) }, + { "darkgreen", NSVG_RGB( 0, 100, 0) }, + { "darkgrey", NSVG_RGB(169, 169, 169) }, + { "darkkhaki", NSVG_RGB(189, 183, 107) }, + { "darkmagenta", NSVG_RGB(139, 0, 139) }, + { "darkolivegreen", NSVG_RGB( 85, 107, 47) }, + { "darkorange", NSVG_RGB(255, 140, 0) }, + { "darkorchid", NSVG_RGB(153, 50, 204) }, + { "darkred", NSVG_RGB(139, 0, 0) }, + { "darksalmon", NSVG_RGB(233, 150, 122) }, + { "darkseagreen", NSVG_RGB(143, 188, 143) }, + { "darkslateblue", NSVG_RGB( 72, 61, 139) }, + { "darkslategray", NSVG_RGB( 47, 79, 79) }, + { "darkslategrey", NSVG_RGB( 47, 79, 79) }, + { "darkturquoise", NSVG_RGB( 0, 206, 209) }, + { "darkviolet", NSVG_RGB(148, 0, 211) }, + { "deeppink", NSVG_RGB(255, 20, 147) }, + { "deepskyblue", NSVG_RGB( 0, 191, 255) }, + { "dimgray", NSVG_RGB(105, 105, 105) }, + { "dimgrey", NSVG_RGB(105, 105, 105) }, + { "dodgerblue", NSVG_RGB( 30, 144, 255) }, + { "firebrick", NSVG_RGB(178, 34, 34) }, + { "floralwhite", NSVG_RGB(255, 250, 240) }, + { "forestgreen", NSVG_RGB( 34, 139, 34) }, + { "fuchsia", NSVG_RGB(255, 0, 255) }, + { "gainsboro", NSVG_RGB(220, 220, 220) }, + { "ghostwhite", NSVG_RGB(248, 248, 255) }, + { "gold", NSVG_RGB(255, 215, 0) }, + { "goldenrod", NSVG_RGB(218, 165, 32) }, + { "greenyellow", NSVG_RGB(173, 255, 47) }, + { "honeydew", NSVG_RGB(240, 255, 240) }, + { "hotpink", NSVG_RGB(255, 105, 180) }, + { "indianred", NSVG_RGB(205, 92, 92) }, + { "indigo", NSVG_RGB( 75, 0, 130) }, + { "ivory", NSVG_RGB(255, 255, 240) }, + { "khaki", NSVG_RGB(240, 230, 140) }, + { "lavender", NSVG_RGB(230, 230, 250) }, + { "lavenderblush", NSVG_RGB(255, 240, 245) }, + { "lawngreen", NSVG_RGB(124, 252, 0) }, + { "lemonchiffon", NSVG_RGB(255, 250, 205) }, + { "lightblue", NSVG_RGB(173, 216, 230) }, + { "lightcoral", NSVG_RGB(240, 128, 128) }, + { "lightcyan", NSVG_RGB(224, 255, 255) }, + { "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) }, + { "lightgray", NSVG_RGB(211, 211, 211) }, + { "lightgreen", NSVG_RGB(144, 238, 144) }, + { "lightgrey", NSVG_RGB(211, 211, 211) }, + { "lightpink", NSVG_RGB(255, 182, 193) }, + { "lightsalmon", NSVG_RGB(255, 160, 122) }, + { "lightseagreen", NSVG_RGB( 32, 178, 170) }, + { "lightskyblue", NSVG_RGB(135, 206, 250) }, + { "lightslategray", NSVG_RGB(119, 136, 153) }, + { "lightslategrey", NSVG_RGB(119, 136, 153) }, + { "lightsteelblue", NSVG_RGB(176, 196, 222) }, + { "lightyellow", NSVG_RGB(255, 255, 224) }, + { "lime", NSVG_RGB( 0, 255, 0) }, + { "limegreen", NSVG_RGB( 50, 205, 50) }, + { "linen", NSVG_RGB(250, 240, 230) }, + { "maroon", NSVG_RGB(128, 0, 0) }, + { "mediumaquamarine", NSVG_RGB(102, 205, 170) }, + { "mediumblue", NSVG_RGB( 0, 0, 205) }, + { "mediumorchid", NSVG_RGB(186, 85, 211) }, + { "mediumpurple", NSVG_RGB(147, 112, 219) }, + { "mediumseagreen", NSVG_RGB( 60, 179, 113) }, + { "mediumslateblue", NSVG_RGB(123, 104, 238) }, + { "mediumspringgreen", NSVG_RGB( 0, 250, 154) }, + { "mediumturquoise", NSVG_RGB( 72, 209, 204) }, + { "mediumvioletred", NSVG_RGB(199, 21, 133) }, + { "midnightblue", NSVG_RGB( 25, 25, 112) }, + { "mintcream", NSVG_RGB(245, 255, 250) }, + { "mistyrose", NSVG_RGB(255, 228, 225) }, + { "moccasin", NSVG_RGB(255, 228, 181) }, + { "navajowhite", NSVG_RGB(255, 222, 173) }, + { "navy", NSVG_RGB( 0, 0, 128) }, + { "oldlace", NSVG_RGB(253, 245, 230) }, + { "olive", NSVG_RGB(128, 128, 0) }, + { "olivedrab", NSVG_RGB(107, 142, 35) }, + { "orange", NSVG_RGB(255, 165, 0) }, + { "orangered", NSVG_RGB(255, 69, 0) }, + { "orchid", NSVG_RGB(218, 112, 214) }, + { "palegoldenrod", NSVG_RGB(238, 232, 170) }, + { "palegreen", NSVG_RGB(152, 251, 152) }, + { "paleturquoise", NSVG_RGB(175, 238, 238) }, + { "palevioletred", NSVG_RGB(219, 112, 147) }, + { "papayawhip", NSVG_RGB(255, 239, 213) }, + { "peachpuff", NSVG_RGB(255, 218, 185) }, + { "peru", NSVG_RGB(205, 133, 63) }, + { "pink", NSVG_RGB(255, 192, 203) }, + { "plum", NSVG_RGB(221, 160, 221) }, + { "powderblue", NSVG_RGB(176, 224, 230) }, + { "purple", NSVG_RGB(128, 0, 128) }, + { "rosybrown", NSVG_RGB(188, 143, 143) }, + { "royalblue", NSVG_RGB( 65, 105, 225) }, + { "saddlebrown", NSVG_RGB(139, 69, 19) }, + { "salmon", NSVG_RGB(250, 128, 114) }, + { "sandybrown", NSVG_RGB(244, 164, 96) }, + { "seagreen", NSVG_RGB( 46, 139, 87) }, + { "seashell", NSVG_RGB(255, 245, 238) }, + { "sienna", NSVG_RGB(160, 82, 45) }, + { "silver", NSVG_RGB(192, 192, 192) }, + { "skyblue", NSVG_RGB(135, 206, 235) }, + { "slateblue", NSVG_RGB(106, 90, 205) }, + { "slategray", NSVG_RGB(112, 128, 144) }, + { "slategrey", NSVG_RGB(112, 128, 144) }, + { "snow", NSVG_RGB(255, 250, 250) }, + { "springgreen", NSVG_RGB( 0, 255, 127) }, + { "steelblue", NSVG_RGB( 70, 130, 180) }, + { "tan", NSVG_RGB(210, 180, 140) }, + { "teal", NSVG_RGB( 0, 128, 128) }, + { "thistle", NSVG_RGB(216, 191, 216) }, + { "tomato", NSVG_RGB(255, 99, 71) }, + { "turquoise", NSVG_RGB( 64, 224, 208) }, + { "violet", NSVG_RGB(238, 130, 238) }, + { "wheat", NSVG_RGB(245, 222, 179) }, + { "whitesmoke", NSVG_RGB(245, 245, 245) }, + { "yellowgreen", NSVG_RGB(154, 205, 50) }, +#endif +}; + +static unsigned int nsvg__parseColorName(const char* str) +{ + int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor); + + for (i = 0; i < ncolors; i++) { + if (strcmp(nsvg__colors[i].name, str) == 0) { + return nsvg__colors[i].color; + } + } + + return NSVG_RGB(128, 128, 128); +} + +static unsigned int nsvg__parseColor(const char* str) +{ + size_t len = 0; + while(*str == ' ') ++str; + len = strlen(str); + if (len >= 1 && *str == '#') + return nsvg__parseColorHex(str); + else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(') + return nsvg__parseColorRGB(str); + return nsvg__parseColorName(str); +} + +static float nsvg__parseOpacity(const char* str) +{ + float val = nsvg__atof(str); + if (val < 0.0f) val = 0.0f; + if (val > 1.0f) val = 1.0f; + return val; +} + +static float nsvg__parseMiterLimit(const char* str) +{ + float val = nsvg__atof(str); + if (val < 0.0f) val = 0.0f; + return val; +} + +static int nsvg__parseUnits(const char* units) +{ + if (units[0] == 'p' && units[1] == 'x') + return NSVG_UNITS_PX; + else if (units[0] == 'p' && units[1] == 't') + return NSVG_UNITS_PT; + else if (units[0] == 'p' && units[1] == 'c') + return NSVG_UNITS_PC; + else if (units[0] == 'm' && units[1] == 'm') + return NSVG_UNITS_MM; + else if (units[0] == 'c' && units[1] == 'm') + return NSVG_UNITS_CM; + else if (units[0] == 'i' && units[1] == 'n') + return NSVG_UNITS_IN; + else if (units[0] == '%') + return NSVG_UNITS_PERCENT; + else if (units[0] == 'e' && units[1] == 'm') + return NSVG_UNITS_EM; + else if (units[0] == 'e' && units[1] == 'x') + return NSVG_UNITS_EX; + return NSVG_UNITS_USER; +} + +static int nsvg__isCoordinate(const char* s) +{ + // optional sign + if (*s == '-' || *s == '+') + s++; + // must have at least one digit, or start by a dot + return (nsvg__isdigit(*s) || *s == '.'); +} + +static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) +{ + NSVGcoordinate coord = {0, NSVG_UNITS_USER}; + char buf[64]; + coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64)); + coord.value = nsvg__atof(buf); + return coord; +} + +static NSVGcoordinate nsvg__coord(float v, int units) +{ + NSVGcoordinate coord = {v, units}; + return coord; +} + +static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length) +{ + NSVGcoordinate coord = nsvg__parseCoordinateRaw(str); + return nsvg__convertToPixels(p, coord, orig, length); +} + +static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na) +{ + const char* end; + const char* ptr; + char it[64]; + + *na = 0; + ptr = str; + while (*ptr && *ptr != '(') ++ptr; + if (*ptr == 0) + return 1; + end = ptr; + while (*end && *end != ')') ++end; + if (*end == 0) + return 1; + + while (ptr < end) { + if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) { + if (*na >= maxNa) return 0; + ptr = nsvg__parseNumber(ptr, it, 64); + args[(*na)++] = (float)nsvg__atof(it); + } else { + ++ptr; + } + } + return (int)(end - str); +} + + +static int nsvg__parseMatrix(float* xform, const char* str) +{ + float t[6]; + int na = 0; + int len = nsvg__parseTransformArgs(str, t, 6, &na); + if (na != 6) return len; + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseTranslate(float* xform, const char* str) +{ + float args[2]; + float t[6]; + int na = 0; + int len = nsvg__parseTransformArgs(str, args, 2, &na); + if (na == 1) args[1] = 0.0; + + nsvg__xformSetTranslation(t, args[0], args[1]); + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseScale(float* xform, const char* str) +{ + float args[2]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 2, &na); + if (na == 1) args[1] = args[0]; + nsvg__xformSetScale(t, args[0], args[1]); + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseSkewX(float* xform, const char* str) +{ + float args[1]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 1, &na); + nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI); + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseSkewY(float* xform, const char* str) +{ + float args[1]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 1, &na); + nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI); + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseRotate(float* xform, const char* str) +{ + float args[3]; + int na = 0; + float m[6]; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 3, &na); + if (na == 1) + args[1] = args[2] = 0.0f; + nsvg__xformIdentity(m); + + if (na > 1) { + nsvg__xformSetTranslation(t, -args[1], -args[2]); + nsvg__xformMultiply(m, t); + } + + nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI); + nsvg__xformMultiply(m, t); + + if (na > 1) { + nsvg__xformSetTranslation(t, args[1], args[2]); + nsvg__xformMultiply(m, t); + } + + memcpy(xform, m, sizeof(float)*6); + + return len; +} + +static void nsvg__parseTransform(float* xform, const char* str) +{ + float t[6]; + int len; + nsvg__xformIdentity(xform); + while (*str) + { + if (strncmp(str, "matrix", 6) == 0) + len = nsvg__parseMatrix(t, str); + else if (strncmp(str, "translate", 9) == 0) + len = nsvg__parseTranslate(t, str); + else if (strncmp(str, "scale", 5) == 0) + len = nsvg__parseScale(t, str); + else if (strncmp(str, "rotate", 6) == 0) + len = nsvg__parseRotate(t, str); + else if (strncmp(str, "skewX", 5) == 0) + len = nsvg__parseSkewX(t, str); + else if (strncmp(str, "skewY", 5) == 0) + len = nsvg__parseSkewY(t, str); + else{ + ++str; + continue; + } + if (len != 0) { + str += len; + } else { + ++str; + continue; + } + + nsvg__xformPremultiply(xform, t); + } +} + +static void nsvg__parseUrl(char* id, const char* str) +{ + int i = 0; + str += 4; // "url("; + if (*str && *str == '#') + str++; + while (i < 63 && *str && *str != ')') { + id[i] = *str++; + i++; + } + id[i] = '\0'; +} + +static char nsvg__parseLineCap(const char* str) +{ + if (strcmp(str, "butt") == 0) + return NSVG_CAP_BUTT; + else if (strcmp(str, "round") == 0) + return NSVG_CAP_ROUND; + else if (strcmp(str, "square") == 0) + return NSVG_CAP_SQUARE; + // TODO: handle inherit. + return NSVG_CAP_BUTT; +} + +static char nsvg__parseLineJoin(const char* str) +{ + if (strcmp(str, "miter") == 0) + return NSVG_JOIN_MITER; + else if (strcmp(str, "round") == 0) + return NSVG_JOIN_ROUND; + else if (strcmp(str, "bevel") == 0) + return NSVG_JOIN_BEVEL; + // TODO: handle inherit. + return NSVG_JOIN_MITER; +} + +static char nsvg__parseFillRule(const char* str) +{ + if (strcmp(str, "nonzero") == 0) + return NSVG_FILLRULE_NONZERO; + else if (strcmp(str, "evenodd") == 0) + return NSVG_FILLRULE_EVENODD; + // TODO: handle inherit. + return NSVG_FILLRULE_NONZERO; +} + +static const char* nsvg__getNextDashItem(const char* s, char* it) +{ + int n = 0; + it[0] = '\0'; + // Skip white spaces and commas + while (*s && (nsvg__isspace(*s) || *s == ',')) s++; + // Advance until whitespace, comma or end. + while (*s && (!nsvg__isspace(*s) && *s != ',')) { + if (n < 63) + it[n++] = *s; + s++; + } + it[n++] = '\0'; + return s; +} + +static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray) +{ + char item[64]; + int count = 0, i; + float sum = 0.0f; + + // Handle "none" + if (str[0] == 'n') + return 0; + + // Parse dashes + while (*str) { + str = nsvg__getNextDashItem(str, item); + if (!*item) break; + if (count < NSVG_MAX_DASHES) + strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p))); + } + + for (i = 0; i < count; i++) + sum += strokeDashArray[i]; + if (sum <= 1e-6f) + count = 0; + + return count; +} + +static void nsvg__parseStyle(NSVGparser* p, const char* str); + +static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) +{ + float xform[6]; + NSVGattrib* attr = nsvg__getAttr(p); + if (!attr) return 0; + + if (strcmp(name, "style") == 0) { + nsvg__parseStyle(p, value); + } else if (strcmp(name, "display") == 0) { + if (strcmp(value, "none") == 0) + attr->visible = 0; + // Don't reset ->visible on display:inline, one display:none hides the whole subtree + + } else if (strcmp(name, "fill") == 0) { + if (strcmp(value, "none") == 0) { + attr->hasFill = 0; + } else if (strncmp(value, "url(", 4) == 0) { + attr->hasFill = 2; + nsvg__parseUrl(attr->fillGradient, value); + } else { + attr->hasFill = 1; + attr->fillColor = nsvg__parseColor(value); + } + } else if (strcmp(name, "opacity") == 0) { + attr->opacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "fill-opacity") == 0) { + attr->fillOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "stroke") == 0) { + if (strcmp(value, "none") == 0) { + attr->hasStroke = 0; + } else if (strncmp(value, "url(", 4) == 0) { + attr->hasStroke = 2; + nsvg__parseUrl(attr->strokeGradient, value); + } else { + attr->hasStroke = 1; + attr->strokeColor = nsvg__parseColor(value); + } + } else if (strcmp(name, "stroke-width") == 0) { + attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "stroke-dasharray") == 0) { + attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray); + } else if (strcmp(name, "stroke-dashoffset") == 0) { + attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "stroke-opacity") == 0) { + attr->strokeOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "stroke-linecap") == 0) { + attr->strokeLineCap = nsvg__parseLineCap(value); + } else if (strcmp(name, "stroke-linejoin") == 0) { + attr->strokeLineJoin = nsvg__parseLineJoin(value); + } else if (strcmp(name, "stroke-miterlimit") == 0) { + attr->miterLimit = nsvg__parseMiterLimit(value); + } else if (strcmp(name, "fill-rule") == 0) { + attr->fillRule = nsvg__parseFillRule(value); + } else if (strcmp(name, "font-size") == 0) { + attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "transform") == 0) { + nsvg__parseTransform(xform, value); + nsvg__xformPremultiply(attr->xform, xform); + } else if (strcmp(name, "stop-color") == 0) { + attr->stopColor = nsvg__parseColor(value); + } else if (strcmp(name, "stop-opacity") == 0) { + attr->stopOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "offset") == 0) { + attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f); + } else if (strcmp(name, "id") == 0) { + strncpy(attr->id, value, 63); + attr->id[63] = '\0'; + } else { + return 0; + } + return 1; +} + +static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end) +{ + const char* str; + const char* val; + char name[512]; + char value[512]; + int n; + + str = start; + while (str < end && *str != ':') ++str; + + val = str; + + // Right Trim + while (str > start && (*str == ':' || nsvg__isspace(*str))) --str; + ++str; + + n = (int)(str - start); + if (n > 511) n = 511; + if (n) memcpy(name, start, n); + name[n] = 0; + + while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val; + + n = (int)(end - val); + if (n > 511) n = 511; + if (n) memcpy(value, val, n); + value[n] = 0; + + return nsvg__parseAttr(p, name, value); +} + +static void nsvg__parseStyle(NSVGparser* p, const char* str) +{ + const char* start; + const char* end; + + while (*str) { + // Left Trim + while(*str && nsvg__isspace(*str)) ++str; + start = str; + while(*str && *str != ';') ++str; + end = str; + + // Right Trim + while (end > start && (*end == ';' || nsvg__isspace(*end))) --end; + ++end; + + nsvg__parseNameValue(p, start, end); + if (*str) ++str; + } +} + +static void nsvg__parseAttribs(NSVGparser* p, const char** attr) +{ + int i; + for (i = 0; attr[i]; i += 2) + { + if (strcmp(attr[i], "style") == 0) + nsvg__parseStyle(p, attr[i + 1]); + else + nsvg__parseAttr(p, attr[i], attr[i + 1]); + } +} + +static int nsvg__getArgsPerElement(char cmd) +{ + switch (cmd) { + case 'v': + case 'V': + case 'h': + case 'H': + return 1; + case 'm': + case 'M': + case 'l': + case 'L': + case 't': + case 'T': + return 2; + case 'q': + case 'Q': + case 's': + case 'S': + return 4; + case 'c': + case 'C': + return 6; + case 'a': + case 'A': + return 7; + case 'z': + case 'Z': + return 0; + } + return -1; +} + +static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + if (rel) { + *cpx += args[0]; + *cpy += args[1]; + } else { + *cpx = args[0]; + *cpy = args[1]; + } + nsvg__moveTo(p, *cpx, *cpy); +} + +static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + if (rel) { + *cpx += args[0]; + *cpy += args[1]; + } else { + *cpx = args[0]; + *cpy = args[1]; + } + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + if (rel) + *cpx += args[0]; + else + *cpx = args[0]; + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + if (rel) + *cpy += args[0]; + else + *cpy = args[0]; + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy, + float* cpx2, float* cpy2, float* args, int rel) +{ + float x2, y2, cx1, cy1, cx2, cy2; + + if (rel) { + cx1 = *cpx + args[0]; + cy1 = *cpy + args[1]; + cx2 = *cpx + args[2]; + cy2 = *cpy + args[3]; + x2 = *cpx + args[4]; + y2 = *cpy + args[5]; + } else { + cx1 = args[0]; + cy1 = args[1]; + cx2 = args[2]; + cy2 = args[3]; + x2 = args[4]; + y2 = args[5]; + } + + nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); + + *cpx2 = cx2; + *cpy2 = cy2; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy, + float* cpx2, float* cpy2, float* args, int rel) +{ + float x1, y1, x2, y2, cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + cx2 = *cpx + args[0]; + cy2 = *cpy + args[1]; + x2 = *cpx + args[2]; + y2 = *cpy + args[3]; + } else { + cx2 = args[0]; + cy2 = args[1]; + x2 = args[2]; + y2 = args[3]; + } + + cx1 = 2*x1 - *cpx2; + cy1 = 2*y1 - *cpy2; + + nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); + + *cpx2 = cx2; + *cpy2 = cy2; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy, + float* cpx2, float* cpy2, float* args, int rel) +{ + float x1, y1, x2, y2, cx, cy; + float cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + cx = *cpx + args[0]; + cy = *cpy + args[1]; + x2 = *cpx + args[2]; + y2 = *cpy + args[3]; + } else { + cx = args[0]; + cy = args[1]; + x2 = args[2]; + y2 = args[3]; + } + + // Convert to cubic bezier + cx1 = x1 + 2.0f/3.0f*(cx - x1); + cy1 = y1 + 2.0f/3.0f*(cy - y1); + cx2 = x2 + 2.0f/3.0f*(cx - x2); + cy2 = y2 + 2.0f/3.0f*(cy - y2); + + nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); + + *cpx2 = cx; + *cpy2 = cy; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy, + float* cpx2, float* cpy2, float* args, int rel) +{ + float x1, y1, x2, y2, cx, cy; + float cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + x2 = *cpx + args[0]; + y2 = *cpy + args[1]; + } else { + x2 = args[0]; + y2 = args[1]; + } + + cx = 2*x1 - *cpx2; + cy = 2*y1 - *cpy2; + + // Convert to cubix bezier + cx1 = x1 + 2.0f/3.0f*(cx - x1); + cy1 = y1 + 2.0f/3.0f*(cy - y1); + cx2 = x2 + 2.0f/3.0f*(cx - x2); + cy2 = y2 + 2.0f/3.0f*(cy - y2); + + nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); + + *cpx2 = cx; + *cpy2 = cy; + *cpx = x2; + *cpy = y2; +} + +static float nsvg__sqr(float x) { return x*x; } +static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); } + +static float nsvg__vecrat(float ux, float uy, float vx, float vy) +{ + return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy)); +} + +static float nsvg__vecang(float ux, float uy, float vx, float vy) +{ + float r = nsvg__vecrat(ux,uy, vx,vy); + if (r < -1.0f) r = -1.0f; + if (r > 1.0f) r = 1.0f; + return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r); +} + +static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + // Ported from canvg (https://code.google.com/p/canvg/) + float rx, ry, rotx; + float x1, y1, x2, y2, cx, cy, dx, dy, d; + float x1p, y1p, cxp, cyp, s, sa, sb; + float ux, uy, vx, vy, a1, da; + float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6]; + float sinrx, cosrx; + int fa, fs; + int i, ndivs; + float hda, kappa; + + rx = fabsf(args[0]); // y radius + ry = fabsf(args[1]); // x radius + rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle + fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc + fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction + x1 = *cpx; // start point + y1 = *cpy; + if (rel) { // end point + x2 = *cpx + args[5]; + y2 = *cpy + args[6]; + } else { + x2 = args[5]; + y2 = args[6]; + } + + dx = x1 - x2; + dy = y1 - y2; + d = sqrtf(dx*dx + dy*dy); + if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) { + // The arc degenerates to a line + nsvg__lineTo(p, x2, y2); + *cpx = x2; + *cpy = y2; + return; + } + + sinrx = sinf(rotx); + cosrx = cosf(rotx); + + // Convert to center point parameterization. + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + // 1) Compute x1', y1' + x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f; + y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f; + d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry); + if (d > 1) { + d = sqrtf(d); + rx *= d; + ry *= d; + } + // 2) Compute cx', cy' + s = 0.0f; + sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p); + sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p); + if (sa < 0.0f) sa = 0.0f; + if (sb > 0.0f) + s = sqrtf(sa / sb); + if (fa == fs) + s = -s; + cxp = s * rx * y1p / ry; + cyp = s * -ry * x1p / rx; + + // 3) Compute cx,cy from cx',cy' + cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp; + cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp; + + // 4) Calculate theta1, and delta theta. + ux = (x1p - cxp) / rx; + uy = (y1p - cyp) / ry; + vx = (-x1p - cxp) / rx; + vy = (-y1p - cyp) / ry; + a1 = nsvg__vecang(1.0f,0.0f, ux,uy); // Initial angle + da = nsvg__vecang(ux,uy, vx,vy); // Delta angle + +// if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; +// if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; + + if (fs == 0 && da > 0) + da -= 2 * NSVG_PI; + else if (fs == 1 && da < 0) + da += 2 * NSVG_PI; + + // Approximate the arc using cubic spline segments. + t[0] = cosrx; t[1] = sinrx; + t[2] = -sinrx; t[3] = cosrx; + t[4] = cx; t[5] = cy; + + // Split arc into max 90 degree segments. + // The loop assumes an iteration per end point (including start and end), this +1. + ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f); + hda = (da / (float)ndivs) / 2.0f; + // Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite) + if ((hda < 1e-3f) && (hda > -1e-3f)) + hda *= 0.5f; + else + hda = (1.0f - cosf(hda)) / sinf(hda); + kappa = fabsf(4.0f / 3.0f * hda); + if (da < 0.0f) + kappa = -kappa; + + for (i = 0; i <= ndivs; i++) { + a = a1 + da * ((float)i/(float)ndivs); + dx = cosf(a); + dy = sinf(a); + nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position + nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent + if (i > 0) + nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y); + px = x; + py = y; + ptanx = tanx; + ptany = tany; + } + + *cpx = x2; + *cpy = y2; +} + +static void nsvg__parsePath(NSVGparser* p, const char** attr) +{ + const char* s = NULL; + char cmd = '\0'; + float args[10]; + int nargs; + int rargs = 0; + char initPoint; + float cpx, cpy, cpx2, cpy2; + const char* tmp[4]; + char closedFlag; + int i; + char item[64]; + + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "d") == 0) { + s = attr[i + 1]; + } else { + tmp[0] = attr[i]; + tmp[1] = attr[i + 1]; + tmp[2] = 0; + tmp[3] = 0; + nsvg__parseAttribs(p, tmp); + } + } + + if (s) { + nsvg__resetPath(p); + cpx = 0; cpy = 0; + cpx2 = 0; cpy2 = 0; + initPoint = 0; + closedFlag = 0; + nargs = 0; + + while (*s) { + item[0] = '\0'; + if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4)) + s = nsvg__getNextPathItemWhenArcFlag(s, item); + if (!*item) + s = nsvg__getNextPathItem(s, item); + if (!*item) break; + if (cmd != '\0' && nsvg__isCoordinate(item)) { + if (nargs < 10) + args[nargs++] = (float)nsvg__atof(item); + if (nargs >= rargs) { + switch (cmd) { + case 'm': + case 'M': + nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0); + // Moveto can be followed by multiple coordinate pairs, + // which should be treated as linetos. + cmd = (cmd == 'm') ? 'l' : 'L'; + rargs = nsvg__getArgsPerElement(cmd); + cpx2 = cpx; cpy2 = cpy; + initPoint = 1; + break; + case 'l': + case 'L': + nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0); + cpx2 = cpx; cpy2 = cpy; + break; + case 'H': + case 'h': + nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0); + cpx2 = cpx; cpy2 = cpy; + break; + case 'V': + case 'v': + nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0); + cpx2 = cpx; cpy2 = cpy; + break; + case 'C': + case 'c': + nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0); + break; + case 'S': + case 's': + nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); + break; + case 'Q': + case 'q': + nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0); + break; + case 'T': + case 't': + nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0); + break; + case 'A': + case 'a': + nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0); + cpx2 = cpx; cpy2 = cpy; + break; + default: + if (nargs >= 2) { + cpx = args[nargs-2]; + cpy = args[nargs-1]; + cpx2 = cpx; cpy2 = cpy; + } + break; + } + nargs = 0; + } + } else { + cmd = item[0]; + if (cmd == 'M' || cmd == 'm') { + // Commit path. + if (p->npts > 0) + nsvg__addPath(p, closedFlag); + // Start new subpath. + nsvg__resetPath(p); + closedFlag = 0; + nargs = 0; + } else if (initPoint == 0) { + // Do not allow other commands until initial point has been set (moveTo called once). + cmd = '\0'; + } + if (cmd == 'Z' || cmd == 'z') { + closedFlag = 1; + // Commit path. + if (p->npts > 0) { + // Move current point to first point + cpx = p->pts[0]; + cpy = p->pts[1]; + cpx2 = cpx; cpy2 = cpy; + nsvg__addPath(p, closedFlag); + } + // Start new subpath. + nsvg__resetPath(p); + nsvg__moveTo(p, cpx, cpy); + closedFlag = 0; + nargs = 0; + } + rargs = nsvg__getArgsPerElement(cmd); + if (rargs == -1) { + // Command not recognized + cmd = '\0'; + rargs = 0; + } + } + } + // Commit path. + if (p->npts) + nsvg__addPath(p, closedFlag); + } + + nsvg__addShape(p); +} + +static void nsvg__parseRect(NSVGparser* p, const char** attr) +{ + float x = 0.0f; + float y = 0.0f; + float w = 0.0f; + float h = 0.0f; + float rx = -1.0f; // marks not set + float ry = -1.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)); + if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)); + if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p))); + if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p))); + } + } + + if (rx < 0.0f && ry > 0.0f) rx = ry; + if (ry < 0.0f && rx > 0.0f) ry = rx; + if (rx < 0.0f) rx = 0.0f; + if (ry < 0.0f) ry = 0.0f; + if (rx > w/2.0f) rx = w/2.0f; + if (ry > h/2.0f) ry = h/2.0f; + + if (w != 0.0f && h != 0.0f) { + nsvg__resetPath(p); + + if (rx < 0.00001f || ry < 0.0001f) { + nsvg__moveTo(p, x, y); + nsvg__lineTo(p, x+w, y); + nsvg__lineTo(p, x+w, y+h); + nsvg__lineTo(p, x, y+h); + } else { + // Rounded rectangle + nsvg__moveTo(p, x+rx, y); + nsvg__lineTo(p, x+w-rx, y); + nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry); + nsvg__lineTo(p, x+w, y+h-ry); + nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h); + nsvg__lineTo(p, x+rx, y+h); + nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry); + nsvg__lineTo(p, x, y+ry); + nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y); + } + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseCircle(NSVGparser* p, const char** attr) +{ + float cx = 0.0f; + float cy = 0.0f; + float r = 0.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p))); + } + } + + if (r > 0.0f) { + nsvg__resetPath(p); + + nsvg__moveTo(p, cx+r, cy); + nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r); + nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy); + nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r); + nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy); + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseEllipse(NSVGparser* p, const char** attr) +{ + float cx = 0.0f; + float cy = 0.0f; + float rx = 0.0f; + float ry = 0.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p))); + if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p))); + } + } + + if (rx > 0.0f && ry > 0.0f) { + + nsvg__resetPath(p); + + nsvg__moveTo(p, cx+rx, cy); + nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry); + nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy); + nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry); + nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy); + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseLine(NSVGparser* p, const char** attr) +{ + float x1 = 0.0; + float y1 = 0.0; + float x2 = 0.0; + float y2 = 0.0; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + } + } + + nsvg__resetPath(p); + + nsvg__moveTo(p, x1, y1); + nsvg__lineTo(p, x2, y2); + + nsvg__addPath(p, 0); + + nsvg__addShape(p); +} + +static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag) +{ + int i; + const char* s; + float args[2]; + int nargs, npts = 0; + char item[64]; + + nsvg__resetPath(p); + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "points") == 0) { + s = attr[i + 1]; + nargs = 0; + while (*s) { + s = nsvg__getNextPathItem(s, item); + args[nargs++] = (float)nsvg__atof(item); + if (nargs >= 2) { + if (npts == 0) + nsvg__moveTo(p, args[0], args[1]); + else + nsvg__lineTo(p, args[0], args[1]); + nargs = 0; + npts++; + } + } + } + } + } + + nsvg__addPath(p, (char)closeFlag); + + nsvg__addShape(p); +} + +static void nsvg__parseSVG(NSVGparser* p, const char** attr) +{ + int i; + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "width") == 0) { + p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); + } else if (strcmp(attr[i], "height") == 0) { + p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); + } else if (strcmp(attr[i], "viewBox") == 0) { + const char *s = attr[i + 1]; + char buf[64]; + s = nsvg__parseNumber(s, buf, 64); + p->viewMinx = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; + if (!*s) return; + s = nsvg__parseNumber(s, buf, 64); + p->viewMiny = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; + if (!*s) return; + s = nsvg__parseNumber(s, buf, 64); + p->viewWidth = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; + if (!*s) return; + s = nsvg__parseNumber(s, buf, 64); + p->viewHeight = nsvg__atof(buf); + } else if (strcmp(attr[i], "preserveAspectRatio") == 0) { + if (strstr(attr[i + 1], "none") != 0) { + // No uniform scaling + p->alignType = NSVG_ALIGN_NONE; + } else { + // Parse X align + if (strstr(attr[i + 1], "xMin") != 0) + p->alignX = NSVG_ALIGN_MIN; + else if (strstr(attr[i + 1], "xMid") != 0) + p->alignX = NSVG_ALIGN_MID; + else if (strstr(attr[i + 1], "xMax") != 0) + p->alignX = NSVG_ALIGN_MAX; + // Parse X align + if (strstr(attr[i + 1], "yMin") != 0) + p->alignY = NSVG_ALIGN_MIN; + else if (strstr(attr[i + 1], "yMid") != 0) + p->alignY = NSVG_ALIGN_MID; + else if (strstr(attr[i + 1], "yMax") != 0) + p->alignY = NSVG_ALIGN_MAX; + // Parse meet/slice + p->alignType = NSVG_ALIGN_MEET; + if (strstr(attr[i + 1], "slice") != 0) + p->alignType = NSVG_ALIGN_SLICE; + } + } + } + } +} + +static void nsvg__parseGradient(NSVGparser* p, const char** attr, signed char type) +{ + int i; + NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData)); + if (grad == NULL) return; + memset(grad, 0, sizeof(NSVGgradientData)); + grad->units = NSVG_OBJECT_SPACE; + grad->type = type; + if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) { + grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT); + grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) { + grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + } + + nsvg__xformIdentity(grad->xform); + + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "id") == 0) { + strncpy(grad->id, attr[i+1], 63); + grad->id[63] = '\0'; + } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "gradientUnits") == 0) { + if (strcmp(attr[i+1], "objectBoundingBox") == 0) + grad->units = NSVG_OBJECT_SPACE; + else + grad->units = NSVG_USER_SPACE; + } else if (strcmp(attr[i], "gradientTransform") == 0) { + nsvg__parseTransform(grad->xform, attr[i + 1]); + } else if (strcmp(attr[i], "cx") == 0) { + grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "cy") == 0) { + grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "r") == 0) { + grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "fx") == 0) { + grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "fy") == 0) { + grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "x1") == 0) { + grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "y1") == 0) { + grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "x2") == 0) { + grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "y2") == 0) { + grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "spreadMethod") == 0) { + if (strcmp(attr[i+1], "pad") == 0) + grad->spread = NSVG_SPREAD_PAD; + else if (strcmp(attr[i+1], "reflect") == 0) + grad->spread = NSVG_SPREAD_REFLECT; + else if (strcmp(attr[i+1], "repeat") == 0) + grad->spread = NSVG_SPREAD_REPEAT; + } else if (strcmp(attr[i], "xlink:href") == 0) { + const char *href = attr[i+1]; + strncpy(grad->ref, href+1, 62); + grad->ref[62] = '\0'; + } + } + } + + grad->next = p->gradients; + p->gradients = grad; +} + +static void nsvg__parseGradientStop(NSVGparser* p, const char** attr) +{ + NSVGattrib* curAttr = nsvg__getAttr(p); + NSVGgradientData* grad; + NSVGgradientStop* stop; + int i, idx; + + curAttr->stopOffset = 0; + curAttr->stopColor = 0; + curAttr->stopOpacity = 1.0f; + + for (i = 0; attr[i]; i += 2) { + nsvg__parseAttr(p, attr[i], attr[i + 1]); + } + + // Add stop to the last gradient. + grad = p->gradients; + if (grad == NULL) return; + + grad->nstops++; + grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops); + if (grad->stops == NULL) return; + + // Insert + idx = grad->nstops-1; + for (i = 0; i < grad->nstops-1; i++) { + if (curAttr->stopOffset < grad->stops[i].offset) { + idx = i; + break; + } + } + if (idx != grad->nstops-1) { + for (i = grad->nstops-1; i > idx; i--) + grad->stops[i] = grad->stops[i-1]; + } + + stop = &grad->stops[idx]; + stop->color = curAttr->stopColor; + stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24; + stop->offset = curAttr->stopOffset; +} + +static void nsvg__startElement(void* ud, const char* el, const char** attr) +{ + NSVGparser* p = (NSVGparser*)ud; + + if (p->defsFlag) { + // Skip everything but gradients in defs + if (strcmp(el, "linearGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); + } else if (strcmp(el, "radialGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); + } else if (strcmp(el, "stop") == 0) { + nsvg__parseGradientStop(p, attr); + } + return; + } + + if (strcmp(el, "g") == 0) { + nsvg__pushAttr(p); + nsvg__parseAttribs(p, attr); + } else if (strcmp(el, "path") == 0) { + if (p->pathFlag) // Do not allow nested paths. + return; + nsvg__pushAttr(p); + nsvg__parsePath(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "rect") == 0) { + nsvg__pushAttr(p); + nsvg__parseRect(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "circle") == 0) { + nsvg__pushAttr(p); + nsvg__parseCircle(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "ellipse") == 0) { + nsvg__pushAttr(p); + nsvg__parseEllipse(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "line") == 0) { + nsvg__pushAttr(p); + nsvg__parseLine(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "polyline") == 0) { + nsvg__pushAttr(p); + nsvg__parsePoly(p, attr, 0); + nsvg__popAttr(p); + } else if (strcmp(el, "polygon") == 0) { + nsvg__pushAttr(p); + nsvg__parsePoly(p, attr, 1); + nsvg__popAttr(p); + } else if (strcmp(el, "linearGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); + } else if (strcmp(el, "radialGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); + } else if (strcmp(el, "stop") == 0) { + nsvg__parseGradientStop(p, attr); + } else if (strcmp(el, "defs") == 0) { + p->defsFlag = 1; + } else if (strcmp(el, "svg") == 0) { + nsvg__parseSVG(p, attr); + } +} + +static void nsvg__endElement(void* ud, const char* el) +{ + NSVGparser* p = (NSVGparser*)ud; + + if (strcmp(el, "g") == 0) { + nsvg__popAttr(p); + } else if (strcmp(el, "path") == 0) { + p->pathFlag = 0; + } else if (strcmp(el, "defs") == 0) { + p->defsFlag = 0; + } +} + +static void nsvg__content(void* ud, const char* s) +{ + NSVG_NOTUSED(ud); + NSVG_NOTUSED(s); + // empty +} + +static void nsvg__imageBounds(NSVGparser* p, float* bounds) +{ + NSVGshape* shape; + shape = p->image->shapes; + if (shape == NULL) { + bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0; + return; + } + bounds[0] = shape->bounds[0]; + bounds[1] = shape->bounds[1]; + bounds[2] = shape->bounds[2]; + bounds[3] = shape->bounds[3]; + for (shape = shape->next; shape != NULL; shape = shape->next) { + bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]); + bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]); + bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]); + bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]); + } +} + +static float nsvg__viewAlign(float content, float container, int type) +{ + if (type == NSVG_ALIGN_MIN) + return 0; + else if (type == NSVG_ALIGN_MAX) + return container - content; + // mid + return (container - content) * 0.5f; +} + +static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy) +{ + float t[6]; + nsvg__xformSetTranslation(t, tx, ty); + nsvg__xformMultiply (grad->xform, t); + + nsvg__xformSetScale(t, sx, sy); + nsvg__xformMultiply (grad->xform, t); +} + +static void nsvg__scaleToViewbox(NSVGparser* p, const char* units) +{ + NSVGshape* shape; + NSVGpath* path; + float tx, ty, sx, sy, us, bounds[4], t[6], avgs; + int i; + float* pt; + + // Guess image size if not set completely. + nsvg__imageBounds(p, bounds); + + if (p->viewWidth == 0) { + if (p->image->width > 0) { + p->viewWidth = p->image->width; + } else { + p->viewMinx = bounds[0]; + p->viewWidth = bounds[2] - bounds[0]; + } + } + if (p->viewHeight == 0) { + if (p->image->height > 0) { + p->viewHeight = p->image->height; + } else { + p->viewMiny = bounds[1]; + p->viewHeight = bounds[3] - bounds[1]; + } + } + if (p->image->width == 0) + p->image->width = p->viewWidth; + if (p->image->height == 0) + p->image->height = p->viewHeight; + + tx = -p->viewMinx; + ty = -p->viewMiny; + sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0; + sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0; + // Unit scaling + us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f); + + // Fix aspect ratio + if (p->alignType == NSVG_ALIGN_MEET) { + // fit whole image into viewbox + sx = sy = nsvg__minf(sx, sy); + tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx; + ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy; + } else if (p->alignType == NSVG_ALIGN_SLICE) { + // fill whole viewbox with image + sx = sy = nsvg__maxf(sx, sy); + tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx; + ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy; + } + + // Transform + sx *= us; + sy *= us; + avgs = (sx+sy) / 2.0f; + for (shape = p->image->shapes; shape != NULL; shape = shape->next) { + shape->bounds[0] = (shape->bounds[0] + tx) * sx; + shape->bounds[1] = (shape->bounds[1] + ty) * sy; + shape->bounds[2] = (shape->bounds[2] + tx) * sx; + shape->bounds[3] = (shape->bounds[3] + ty) * sy; + for (path = shape->paths; path != NULL; path = path->next) { + path->bounds[0] = (path->bounds[0] + tx) * sx; + path->bounds[1] = (path->bounds[1] + ty) * sy; + path->bounds[2] = (path->bounds[2] + tx) * sx; + path->bounds[3] = (path->bounds[3] + ty) * sy; + for (i =0; i < path->npts; i++) { + pt = &path->pts[i*2]; + pt[0] = (pt[0] + tx) * sx; + pt[1] = (pt[1] + ty) * sy; + } + } + + if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) { + nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy); + memcpy(t, shape->fill.gradient->xform, sizeof(float)*6); + nsvg__xformInverse(shape->fill.gradient->xform, t); + } + if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) { + nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy); + memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6); + nsvg__xformInverse(shape->stroke.gradient->xform, t); + } + + shape->strokeWidth *= avgs; + shape->strokeDashOffset *= avgs; + for (i = 0; i < shape->strokeDashCount; i++) + shape->strokeDashArray[i] *= avgs; + } +} + +static void nsvg__createGradients(NSVGparser* p) +{ + NSVGshape* shape; + + for (shape = p->image->shapes; shape != NULL; shape = shape->next) { + if (shape->fill.type == NSVG_PAINT_UNDEF) { + if (shape->fillGradient[0] != '\0') { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, shape->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->fill.gradient = nsvg__createGradient(p, shape->fillGradient, localBounds, shape->xform, &shape->fill.type); + } + if (shape->fill.type == NSVG_PAINT_UNDEF) { + shape->fill.type = NSVG_PAINT_NONE; + } + } + if (shape->stroke.type == NSVG_PAINT_UNDEF) { + if (shape->strokeGradient[0] != '\0') { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, shape->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->stroke.gradient = nsvg__createGradient(p, shape->strokeGradient, localBounds, shape->xform, &shape->stroke.type); + } + if (shape->stroke.type == NSVG_PAINT_UNDEF) { + shape->stroke.type = NSVG_PAINT_NONE; + } + } + } +} + +NSVGimage* nsvgParse(char* input, const char* units, float dpi) +{ + NSVGparser* p; + NSVGimage* ret = 0; + + p = nsvg__createParser(); + if (p == NULL) { + return NULL; + } + p->dpi = dpi; + + nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p); + + // Create gradients after all definitions have been parsed + nsvg__createGradients(p); + + // Scale to viewBox + nsvg__scaleToViewbox(p, units); + + ret = p->image; + p->image = NULL; + + nsvg__deleteParser(p); + + return ret; +} + +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) +{ + FILE* fp = NULL; + size_t size; + char* data = NULL; + NSVGimage* image = NULL; + + fp = fopen(filename, "rb"); + if (!fp) goto error; + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + data = (char*)malloc(size+1); + if (data == NULL) goto error; + if (fread(data, 1, size, fp) != size) goto error; + data[size] = '\0'; // Must be null terminated. + fclose(fp); + image = nsvgParse(data, units, dpi); + free(data); + + return image; + +error: + if (fp) fclose(fp); + if (data) free(data); + if (image) nsvgDelete(image); + return NULL; +} + +NSVGpath* nsvgDuplicatePath(NSVGpath* p) +{ + NSVGpath* res = NULL; + + if (p == NULL) + return NULL; + + res = (NSVGpath*)malloc(sizeof(NSVGpath)); + if (res == NULL) goto error; + memset(res, 0, sizeof(NSVGpath)); + + res->pts = (float*)malloc(p->npts*2*sizeof(float)); + if (res->pts == NULL) goto error; + memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2); + res->npts = p->npts; + + memcpy(res->bounds, p->bounds, sizeof(p->bounds)); + + res->closed = p->closed; + + return res; + +error: + if (res != NULL) { + free(res->pts); + free(res); + } + return NULL; +} + +void nsvgDelete(NSVGimage* image) +{ + NSVGshape *snext, *shape; + if (image == NULL) return; + shape = image->shapes; + while (shape != NULL) { + snext = shape->next; + nsvg__deletePaths(shape->paths); + nsvg__deletePaint(&shape->fill); + nsvg__deletePaint(&shape->stroke); + free(shape); + shape = snext; + } + free(image); +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // NANOSVG_IMPLEMENTATION + +#endif // NANOSVG_H diff --git a/libraries/ZWidget/src/core/nanosvg/nanosvgrast.h b/libraries/ZWidget/src/core/nanosvg/nanosvgrast.h new file mode 100644 index 0000000000..89fae3834b --- /dev/null +++ b/libraries/ZWidget/src/core/nanosvg/nanosvgrast.h @@ -0,0 +1,1459 @@ +/* + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org + * + * 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. + * + * The polygon rasterization is heavily based on stb_truetype rasterizer + * by Sean Barrett - http://nothings.org/ + * + */ + +#ifndef NANOSVGRAST_H +#define NANOSVGRAST_H + +#include "nanosvg.h" + +#ifndef NANOSVGRAST_CPLUSPLUS +#ifdef __cplusplus +extern "C" { +#endif +#endif + +typedef struct NSVGrasterizer NSVGrasterizer; + +/* Example Usage: + // Load SVG + NSVGimage* image; + image = nsvgParseFromFile("test.svg", "px", 96); + + // Create rasterizer (can be used to render multiple images). + struct NSVGrasterizer* rast = nsvgCreateRasterizer(); + // Allocate memory for image + unsigned char* img = malloc(w*h*4); + // Rasterize + nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4); +*/ + +// Allocated rasterizer context. +NSVGrasterizer* nsvgCreateRasterizer(void); + +// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) +// r - pointer to rasterizer context +// image - pointer to image to rasterize +// tx,ty - image offset (applied after scaling) +// scale - image scale +// dst - pointer to destination image data, 4 bytes per pixel (RGBA) +// w - width of the image to render +// h - height of the image to render +// stride - number of bytes per scaleline in the destination buffer +void nsvgRasterize(NSVGrasterizer* r, + NSVGimage* image, float tx, float ty, float scale, + unsigned char* dst, int w, int h, int stride); + +// Deletes rasterizer context. +void nsvgDeleteRasterizer(NSVGrasterizer*); + + +#ifndef NANOSVGRAST_CPLUSPLUS +#ifdef __cplusplus +} +#endif +#endif + +#ifdef NANOSVGRAST_IMPLEMENTATION + +#include +#include +#include + +#define NSVG__SUBSAMPLES 5 +#define NSVG__FIXSHIFT 10 +#define NSVG__FIX (1 << NSVG__FIXSHIFT) +#define NSVG__FIXMASK (NSVG__FIX-1) +#define NSVG__MEMPAGE_SIZE 1024 + +typedef struct NSVGedge { + float x0,y0, x1,y1; + int dir; + struct NSVGedge* next; +} NSVGedge; + +typedef struct NSVGpoint { + float x, y; + float dx, dy; + float len; + float dmx, dmy; + unsigned char flags; +} NSVGpoint; + +typedef struct NSVGactiveEdge { + int x,dx; + float ey; + int dir; + struct NSVGactiveEdge *next; +} NSVGactiveEdge; + +typedef struct NSVGmemPage { + unsigned char mem[NSVG__MEMPAGE_SIZE]; + int size; + struct NSVGmemPage* next; +} NSVGmemPage; + +typedef struct NSVGcachedPaint { + signed char type; + char spread; + float xform[6]; + unsigned int colors[256]; +} NSVGcachedPaint; + +struct NSVGrasterizer +{ + float px, py; + + float tessTol; + float distTol; + + NSVGedge* edges; + int nedges; + int cedges; + + NSVGpoint* points; + int npoints; + int cpoints; + + NSVGpoint* points2; + int npoints2; + int cpoints2; + + NSVGactiveEdge* freelist; + NSVGmemPage* pages; + NSVGmemPage* curpage; + + unsigned char* scanline; + int cscanline; + + unsigned char* bitmap; + int width, height, stride; +}; + +NSVGrasterizer* nsvgCreateRasterizer(void) +{ + NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer)); + if (r == NULL) goto error; + memset(r, 0, sizeof(NSVGrasterizer)); + + r->tessTol = 0.25f; + r->distTol = 0.01f; + + return r; + +error: + nsvgDeleteRasterizer(r); + return NULL; +} + +void nsvgDeleteRasterizer(NSVGrasterizer* r) +{ + NSVGmemPage* p; + + if (r == NULL) return; + + p = r->pages; + while (p != NULL) { + NSVGmemPage* next = p->next; + free(p); + p = next; + } + + if (r->edges) free(r->edges); + if (r->points) free(r->points); + if (r->points2) free(r->points2); + if (r->scanline) free(r->scanline); + + free(r); +} + +static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur) +{ + NSVGmemPage *newp; + + // If using existing chain, return the next page in chain + if (cur != NULL && cur->next != NULL) { + return cur->next; + } + + // Alloc new page + newp = (NSVGmemPage*)malloc(sizeof(NSVGmemPage)); + if (newp == NULL) return NULL; + memset(newp, 0, sizeof(NSVGmemPage)); + + // Add to linked list + if (cur != NULL) + cur->next = newp; + else + r->pages = newp; + + return newp; +} + +static void nsvg__resetPool(NSVGrasterizer* r) +{ + NSVGmemPage* p = r->pages; + while (p != NULL) { + p->size = 0; + p = p->next; + } + r->curpage = r->pages; +} + +static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size) +{ + unsigned char* buf; + if (size > NSVG__MEMPAGE_SIZE) return NULL; + if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) { + r->curpage = nsvg__nextPage(r, r->curpage); + } + buf = &r->curpage->mem[r->curpage->size]; + r->curpage->size += size; + return buf; +} + +static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol) +{ + float dx = x2 - x1; + float dy = y2 - y1; + return dx*dx + dy*dy < tol*tol; +} + +static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags) +{ + NSVGpoint* pt; + + if (r->npoints > 0) { + pt = &r->points[r->npoints-1]; + if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) { + pt->flags = (unsigned char)(pt->flags | flags); + return; + } + } + + if (r->npoints+1 > r->cpoints) { + r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; + r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints); + if (r->points == NULL) return; + } + + pt = &r->points[r->npoints]; + pt->x = x; + pt->y = y; + pt->flags = (unsigned char)flags; + r->npoints++; +} + +static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt) +{ + if (r->npoints+1 > r->cpoints) { + r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; + r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints); + if (r->points == NULL) return; + } + r->points[r->npoints] = pt; + r->npoints++; +} + +static void nsvg__duplicatePoints(NSVGrasterizer* r) +{ + if (r->npoints > r->cpoints2) { + r->cpoints2 = r->npoints; + r->points2 = (NSVGpoint*)realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2); + if (r->points2 == NULL) return; + } + + memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints); + r->npoints2 = r->npoints; +} + +static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1) +{ + NSVGedge* e; + + // Skip horizontal edges + if (y0 == y1) + return; + + if (r->nedges+1 > r->cedges) { + r->cedges = r->cedges > 0 ? r->cedges * 2 : 64; + r->edges = (NSVGedge*)realloc(r->edges, sizeof(NSVGedge) * r->cedges); + if (r->edges == NULL) return; + } + + e = &r->edges[r->nedges]; + r->nedges++; + + if (y0 < y1) { + e->x0 = x0; + e->y0 = y0; + e->x1 = x1; + e->y1 = y1; + e->dir = 1; + } else { + e->x0 = x1; + e->y0 = y1; + e->x1 = x0; + e->y1 = y0; + e->dir = -1; + } +} + +static float nsvg__normalize(float *x, float* y) +{ + float d = sqrtf((*x)*(*x) + (*y)*(*y)); + if (d > 1e-6f) { + float id = 1.0f / d; + *x *= id; + *y *= id; + } + return d; +} + +static float nsvg__absf(float x) { return x < 0 ? -x : x; } +static float nsvg__roundf(float x) { return (x >= 0) ? floorf(x + 0.5) : ceilf(x - 0.5); } + +static void nsvg__flattenCubicBez(NSVGrasterizer* r, + float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4, + int level, int type) +{ + float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234; + float dx,dy,d2,d3; + + if (level > 10) return; + + x12 = (x1+x2)*0.5f; + y12 = (y1+y2)*0.5f; + x23 = (x2+x3)*0.5f; + y23 = (y2+y3)*0.5f; + x34 = (x3+x4)*0.5f; + y34 = (y3+y4)*0.5f; + x123 = (x12+x23)*0.5f; + y123 = (y12+y23)*0.5f; + + dx = x4 - x1; + dy = y4 - y1; + d2 = nsvg__absf(((x2 - x4) * dy - (y2 - y4) * dx)); + d3 = nsvg__absf(((x3 - x4) * dy - (y3 - y4) * dx)); + + if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) { + nsvg__addPathPoint(r, x4, y4, type); + return; + } + + x234 = (x23+x34)*0.5f; + y234 = (y23+y34)*0.5f; + x1234 = (x123+x234)*0.5f; + y1234 = (y123+y234)*0.5f; + + nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0); + nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type); +} + +static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale) +{ + int i, j; + NSVGpath* path; + + for (path = shape->paths; path != NULL; path = path->next) { + r->npoints = 0; + // Flatten path + nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); + for (i = 0; i < path->npts-1; i += 3) { + float* p = &path->pts[i*2]; + nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, 0); + } + // Close path + nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); + // Build edges + for (i = 0, j = r->npoints-1; i < r->npoints; j = i++) + nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y); + } +} + +enum NSVGpointFlags +{ + NSVG_PT_CORNER = 0x01, + NSVG_PT_BEVEL = 0x02, + NSVG_PT_LEFT = 0x04 +}; + +static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) +{ + float w = lineWidth * 0.5f; + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + float len = nsvg__normalize(&dx, &dy); + float px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f; + float dlx = dy, dly = -dx; + float lx = px - dlx*w, ly = py - dly*w; + float rx = px + dlx*w, ry = py + dly*w; + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) +{ + float w = lineWidth * 0.5f; + float px = p->x, py = p->y; + float dlx = dy, dly = -dx; + float lx = px - dlx*w, ly = py - dly*w; + float rx = px + dlx*w, ry = py + dly*w; + + nsvg__addEdge(r, lx, ly, rx, ry); + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) +{ + float w = lineWidth * 0.5f; + float px = p->x - dx*w, py = p->y - dy*w; + float dlx = dy, dly = -dx; + float lx = px - dlx*w, ly = py - dly*w; + float rx = px + dlx*w, ry = py + dly*w; + + nsvg__addEdge(r, lx, ly, rx, ry); + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +#ifndef NSVG_PI +#define NSVG_PI (3.14159265358979323846264338327f) +#endif + +static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect) +{ + int i; + float w = lineWidth * 0.5f; + float px = p->x, py = p->y; + float dlx = dy, dly = -dx; + float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0; + + for (i = 0; i < ncap; i++) { + float a = (float)i/(float)(ncap-1)*NSVG_PI; + float ax = cosf(a) * w, ay = sinf(a) * w; + float x = px - dlx*ax - dx*ay; + float y = py - dly*ax - dy*ay; + + if (i > 0) + nsvg__addEdge(r, prevx, prevy, x, y); + + prevx = x; + prevy = y; + + if (i == 0) { + lx = x; ly = y; + } else if (i == ncap-1) { + rx = x; ry = y; + } + } + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) +{ + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w); + float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w); + float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w); + float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w); + + nsvg__addEdge(r, lx0, ly0, left->x, left->y); + nsvg__addEdge(r, lx1, ly1, lx0, ly0); + + nsvg__addEdge(r, right->x, right->y, rx0, ry0); + nsvg__addEdge(r, rx0, ry0, rx1, ry1); + + left->x = lx1; left->y = ly1; + right->x = rx1; right->y = ry1; +} + +static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) +{ + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float lx0, rx0, lx1, rx1; + float ly0, ry0, ly1, ry1; + + if (p1->flags & NSVG_PT_LEFT) { + lx0 = lx1 = p1->x - p1->dmx * w; + ly0 = ly1 = p1->y - p1->dmy * w; + nsvg__addEdge(r, lx1, ly1, left->x, left->y); + + rx0 = p1->x + (dlx0 * w); + ry0 = p1->y + (dly0 * w); + rx1 = p1->x + (dlx1 * w); + ry1 = p1->y + (dly1 * w); + nsvg__addEdge(r, right->x, right->y, rx0, ry0); + nsvg__addEdge(r, rx0, ry0, rx1, ry1); + } else { + lx0 = p1->x - (dlx0 * w); + ly0 = p1->y - (dly0 * w); + lx1 = p1->x - (dlx1 * w); + ly1 = p1->y - (dly1 * w); + nsvg__addEdge(r, lx0, ly0, left->x, left->y); + nsvg__addEdge(r, lx1, ly1, lx0, ly0); + + rx0 = rx1 = p1->x + p1->dmx * w; + ry0 = ry1 = p1->y + p1->dmy * w; + nsvg__addEdge(r, right->x, right->y, rx1, ry1); + } + + left->x = lx1; left->y = ly1; + right->x = rx1; right->y = ry1; +} + +static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap) +{ + int i, n; + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float a0 = atan2f(dly0, dlx0); + float a1 = atan2f(dly1, dlx1); + float da = a1 - a0; + float lx, ly, rx, ry; + + if (da < NSVG_PI) da += NSVG_PI*2; + if (da > NSVG_PI) da -= NSVG_PI*2; + + n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap); + if (n < 2) n = 2; + if (n > ncap) n = ncap; + + lx = left->x; + ly = left->y; + rx = right->x; + ry = right->y; + + for (i = 0; i < n; i++) { + float u = (float)i/(float)(n-1); + float a = a0 + u*da; + float ax = cosf(a) * w, ay = sinf(a) * w; + float lx1 = p1->x - ax, ly1 = p1->y - ay; + float rx1 = p1->x + ax, ry1 = p1->y + ay; + + nsvg__addEdge(r, lx1, ly1, lx, ly); + nsvg__addEdge(r, rx, ry, rx1, ry1); + + lx = lx1; ly = ly1; + rx = rx1; ry = ry1; + } + + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth) +{ + float w = lineWidth * 0.5f; + float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w); + float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w); + + nsvg__addEdge(r, lx, ly, left->x, left->y); + nsvg__addEdge(r, right->x, right->y, rx, ry); + + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static int nsvg__curveDivs(float r, float arc, float tol) +{ + float da = acosf(r / (r + tol)) * 2.0f; + int divs = (int)ceilf(arc / da); + if (divs < 2) divs = 2; + return divs; +} + +static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth) +{ + int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle. + NSVGpoint left = {0,0,0,0,0,0,0,0}, right = {0,0,0,0,0,0,0,0}, firstLeft = {0,0,0,0,0,0,0,0}, firstRight = {0,0,0,0,0,0,0,0}; + NSVGpoint* p0, *p1; + int j, s, e; + + // Build stroke edges + if (closed) { + // Looping + p0 = &points[npoints-1]; + p1 = &points[0]; + s = 0; + e = npoints; + } else { + // Add cap + p0 = &points[0]; + p1 = &points[1]; + s = 1; + e = npoints-1; + } + + if (closed) { + nsvg__initClosed(&left, &right, p0, p1, lineWidth); + firstLeft = left; + firstRight = right; + } else { + // Add cap + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + nsvg__normalize(&dx, &dy); + if (lineCap == NSVG_CAP_BUTT) + nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0); + else if (lineCap == NSVG_CAP_SQUARE) + nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0); + else if (lineCap == NSVG_CAP_ROUND) + nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0); + } + + for (j = s; j < e; ++j) { + if (p1->flags & NSVG_PT_CORNER) { + if (lineJoin == NSVG_JOIN_ROUND) + nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap); + else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL)) + nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth); + else + nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth); + } else { + nsvg__straightJoin(r, &left, &right, p1, lineWidth); + } + p0 = p1++; + } + + if (closed) { + // Loop it + nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y); + nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y); + } else { + // Add cap + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + nsvg__normalize(&dx, &dy); + if (lineCap == NSVG_CAP_BUTT) + nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); + else if (lineCap == NSVG_CAP_SQUARE) + nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); + else if (lineCap == NSVG_CAP_ROUND) + nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1); + } +} + +static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin) +{ + int i, j; + NSVGpoint* p0, *p1; + + p0 = &r->points[r->npoints-1]; + p1 = &r->points[0]; + for (i = 0; i < r->npoints; i++) { + // Calculate segment direction and length + p0->dx = p1->x - p0->x; + p0->dy = p1->y - p0->y; + p0->len = nsvg__normalize(&p0->dx, &p0->dy); + // Advance + p0 = p1++; + } + + // calculate joins + p0 = &r->points[r->npoints-1]; + p1 = &r->points[0]; + for (j = 0; j < r->npoints; j++) { + float dlx0, dly0, dlx1, dly1, dmr2, cross; + dlx0 = p0->dy; + dly0 = -p0->dx; + dlx1 = p1->dy; + dly1 = -p1->dx; + // Calculate extrusions + p1->dmx = (dlx0 + dlx1) * 0.5f; + p1->dmy = (dly0 + dly1) * 0.5f; + dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy; + if (dmr2 > 0.000001f) { + float s2 = 1.0f / dmr2; + if (s2 > 600.0f) { + s2 = 600.0f; + } + p1->dmx *= s2; + p1->dmy *= s2; + } + + // Clear flags, but keep the corner. + p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0; + + // Keep track of left turns. + cross = p1->dx * p0->dy - p0->dx * p1->dy; + if (cross > 0.0f) + p1->flags |= NSVG_PT_LEFT; + + // Check to see if the corner needs to be beveled. + if (p1->flags & NSVG_PT_CORNER) { + if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) { + p1->flags |= NSVG_PT_BEVEL; + } + } + + p0 = p1++; + } +} + +static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale) +{ + int i, j, closed; + NSVGpath* path; + NSVGpoint* p0, *p1; + float miterLimit = shape->miterLimit; + int lineJoin = shape->strokeLineJoin; + int lineCap = shape->strokeLineCap; + float lineWidth = shape->strokeWidth * scale; + + for (path = shape->paths; path != NULL; path = path->next) { + // Flatten path + r->npoints = 0; + nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER); + for (i = 0; i < path->npts-1; i += 3) { + float* p = &path->pts[i*2]; + nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, NSVG_PT_CORNER); + } + if (r->npoints < 2) + continue; + + closed = path->closed; + + // If the first and last points are the same, remove the last, mark as closed path. + p0 = &r->points[r->npoints-1]; + p1 = &r->points[0]; + if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) { + r->npoints--; + p0 = &r->points[r->npoints-1]; + closed = 1; + } + + if (shape->strokeDashCount > 0) { + int idash = 0, dashState = 1; + float totalDist = 0, dashLen, allDashLen, dashOffset; + NSVGpoint cur; + + if (closed) + nsvg__appendPathPoint(r, r->points[0]); + + // Duplicate points -> points2. + nsvg__duplicatePoints(r); + + r->npoints = 0; + cur = r->points2[0]; + nsvg__appendPathPoint(r, cur); + + // Figure out dash offset. + allDashLen = 0; + for (j = 0; j < shape->strokeDashCount; j++) + allDashLen += shape->strokeDashArray[j]; + if (shape->strokeDashCount & 1) + allDashLen *= 2.0f; + // Find location inside pattern + dashOffset = fmodf(shape->strokeDashOffset, allDashLen); + if (dashOffset < 0.0f) + dashOffset += allDashLen; + + while (dashOffset > shape->strokeDashArray[idash]) { + dashOffset -= shape->strokeDashArray[idash]; + idash = (idash + 1) % shape->strokeDashCount; + } + dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale; + + for (j = 1; j < r->npoints2; ) { + float dx = r->points2[j].x - cur.x; + float dy = r->points2[j].y - cur.y; + float dist = sqrtf(dx*dx + dy*dy); + + if ((totalDist + dist) > dashLen) { + // Calculate intermediate point + float d = (dashLen - totalDist) / dist; + float x = cur.x + dx * d; + float y = cur.y + dy * d; + nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER); + + // Stroke + if (r->npoints > 1 && dashState) { + nsvg__prepareStroke(r, miterLimit, lineJoin); + nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); + } + // Advance dash pattern + dashState = !dashState; + idash = (idash+1) % shape->strokeDashCount; + dashLen = shape->strokeDashArray[idash] * scale; + // Restart + cur.x = x; + cur.y = y; + cur.flags = NSVG_PT_CORNER; + totalDist = 0.0f; + r->npoints = 0; + nsvg__appendPathPoint(r, cur); + } else { + totalDist += dist; + cur = r->points2[j]; + nsvg__appendPathPoint(r, cur); + j++; + } + } + // Stroke any leftover path + if (r->npoints > 1 && dashState) + nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); + } else { + nsvg__prepareStroke(r, miterLimit, lineJoin); + nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth); + } + } +} + +static int nsvg__cmpEdge(const void *p, const void *q) +{ + const NSVGedge* a = (const NSVGedge*)p; + const NSVGedge* b = (const NSVGedge*)q; + + if (a->y0 < b->y0) return -1; + if (a->y0 > b->y0) return 1; + return 0; +} + + +static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint) +{ + NSVGactiveEdge* z; + + if (r->freelist != NULL) { + // Restore from freelist. + z = r->freelist; + r->freelist = z->next; + } else { + // Alloc new edge. + z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge)); + if (z == NULL) return NULL; + } + + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); +// STBTT_assert(e->y0 <= start_point); + // round dx down to avoid going too far + if (dxdy < 0) + z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy)); + else + z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy); + z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0))); +// z->x -= off_x * FIX; + z->ey = e->y1; + z->next = 0; + z->dir = e->dir; + + return z; +} + +static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z) +{ + z->next = r->freelist; + r->freelist = z; +} + +static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax) +{ + int i = x0 >> NSVG__FIXSHIFT; + int j = x1 >> NSVG__FIXSHIFT; + if (i < *xmin) *xmin = i; + if (j > *xmax) *xmax = j; + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = (unsigned char)(scanline[i] + maxWeight); + } + } +} + +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule) +{ + // non-zero winding fill + int x0 = 0, w = 0; + + if (fillRule == NSVG_FILLRULE_NONZERO) { + // Non-zero + while (e != NULL) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->dir; + } else { + int x1 = e->x; w += e->dir; + // if we went to zero, we need to draw + if (w == 0) + nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); + } + e = e->next; + } + } else if (fillRule == NSVG_FILLRULE_EVENODD) { + // Even-odd + while (e != NULL) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w = 1; + } else { + int x1 = e->x; w = 0; + nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); + } + e = e->next; + } + } +} + +static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } + +static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24); +} + +static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u) +{ + int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); + int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8; + int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8; + int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8; + int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8; + return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); +} + +static unsigned int nsvg__applyOpacity(unsigned int c, float u) +{ + int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); + int r = (c) & 0xff; + int g = (c>>8) & 0xff; + int b = (c>>16) & 0xff; + int a = (((c>>24) & 0xff)*iu) >> 8; + return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); +} + +static inline int nsvg__div255(int x) +{ + return ((x+1) * 257) >> 16; +} + +static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y, + float tx, float ty, float scale, NSVGcachedPaint* cache) +{ + + if (cache->type == NSVG_PAINT_COLOR) { + int i, cr, cg, cb, ca; + cr = cache->colors[0] & 0xff; + cg = (cache->colors[0] >> 8) & 0xff; + cb = (cache->colors[0] >> 16) & 0xff; + ca = (cache->colors[0] >> 24) & 0xff; + + for (i = 0; i < count; i++) { + int r,g,b; + int a = nsvg__div255((int)cover[0] * ca); + int ia = 255 - a; + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + } + } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) { + // TODO: spread modes. + // TODO: plenty of opportunities to optimize. + float fx, fy, dx, gy; + float* t = cache->xform; + int i, cr, cg, cb, ca; + unsigned int c; + + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; + dx = 1.0f / scale; + + for (i = 0; i < count; i++) { + int r,g,b,a,ia; + gy = fx*t[1] + fy*t[3] + t[5]; + c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)]; + cr = (c) & 0xff; + cg = (c >> 8) & 0xff; + cb = (c >> 16) & 0xff; + ca = (c >> 24) & 0xff; + + a = nsvg__div255((int)cover[0] * ca); + ia = 255 - a; + + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + fx += dx; + } + } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) { + // TODO: spread modes. + // TODO: plenty of opportunities to optimize. + // TODO: focus (fx,fy) + float fx, fy, dx, gx, gy, gd; + float* t = cache->xform; + int i, cr, cg, cb, ca; + unsigned int c; + + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; + dx = 1.0f / scale; + + for (i = 0; i < count; i++) { + int r,g,b,a,ia; + gx = fx*t[0] + fy*t[2] + t[4]; + gy = fx*t[1] + fy*t[3] + t[5]; + gd = sqrtf(gx*gx + gy*gy); + c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)]; + cr = (c) & 0xff; + cg = (c >> 8) & 0xff; + cb = (c >> 16) & 0xff; + ca = (c >> 24) & 0xff; + + a = nsvg__div255((int)cover[0] * ca); + ia = 255 - a; + + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + fx += dx; + } + } +} + +static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule) +{ + NSVGactiveEdge *active = NULL; + int y, s; + int e = 0; + int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline + int xmin, xmax; + + for (y = 0; y < r->height; y++) { + memset(r->scanline, 0, r->width); + xmin = r->width; + xmax = 0; + for (s = 0; s < NSVG__SUBSAMPLES; ++s) { + // find center of pixel for this scanline + float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f; + NSVGactiveEdge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + NSVGactiveEdge *z = *step; + if (z->ey <= scany) { + *step = z->next; // delete from list +// NSVG__assert(z->valid); + nsvg__freeActive(r, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for (;;) { + int changed = 0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + NSVGactiveEdge* t = *step; + NSVGactiveEdge* q = t->next; + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e < r->nedges && r->edges[e].y0 <= scany) { + if (r->edges[e].y1 > scany) { + NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany); + if (z == NULL) break; + // find insertion point + if (active == NULL) { + active = z; + } else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + NSVGactiveEdge* p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + e++; + } + + // now process all active edges in non-zero fashion + if (active != NULL) + nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule); + } + // Blit + if (xmin < 0) xmin = 0; + if (xmax > r->width-1) xmax = r->width-1; + if (xmin <= xmax) { + nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache); + } + } + +} + +static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride) +{ + int x,y; + + // Unpremultiply + for (y = 0; y < h; y++) { + unsigned char *row = &image[y*stride]; + for (x = 0; x < w; x++) { + int r = row[0], g = row[1], b = row[2], a = row[3]; + if (a != 0) { + row[0] = (unsigned char)(r*255/a); + row[1] = (unsigned char)(g*255/a); + row[2] = (unsigned char)(b*255/a); + } + row += 4; + } + } + + // Defringe + for (y = 0; y < h; y++) { + unsigned char *row = &image[y*stride]; + for (x = 0; x < w; x++) { + int r = 0, g = 0, b = 0, a = row[3], n = 0; + if (a == 0) { + if (x-1 > 0 && row[-1] != 0) { + r += row[-4]; + g += row[-3]; + b += row[-2]; + n++; + } + if (x+1 < w && row[7] != 0) { + r += row[4]; + g += row[5]; + b += row[6]; + n++; + } + if (y-1 > 0 && row[-stride+3] != 0) { + r += row[-stride]; + g += row[-stride+1]; + b += row[-stride+2]; + n++; + } + if (y+1 < h && row[stride+3] != 0) { + r += row[stride]; + g += row[stride+1]; + b += row[stride+2]; + n++; + } + if (n > 0) { + row[0] = (unsigned char)(r/n); + row[1] = (unsigned char)(g/n); + row[2] = (unsigned char)(b/n); + } + } + row += 4; + } + } +} + + +static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity) +{ + int i, j; + NSVGgradient* grad; + + cache->type = paint->type; + + if (paint->type == NSVG_PAINT_COLOR) { + cache->colors[0] = nsvg__applyOpacity(paint->color, opacity); + return; + } + + grad = paint->gradient; + + cache->spread = grad->spread; + memcpy(cache->xform, grad->xform, sizeof(float)*6); + + if (grad->nstops == 0) { + for (i = 0; i < 256; i++) + cache->colors[i] = 0; + } else if (grad->nstops == 1) { + for (i = 0; i < 256; i++) + cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity); + } else { + unsigned int ca, cb = 0; + float ua, ub, du, u; + int ia, ib, count; + + ca = nsvg__applyOpacity(grad->stops[0].color, opacity); + ua = nsvg__clampf(grad->stops[0].offset, 0, 1); + ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1); + ia = (int)(ua * 255.0f); + ib = (int)(ub * 255.0f); + for (i = 0; i < ia; i++) { + cache->colors[i] = ca; + } + + for (i = 0; i < grad->nstops-1; i++) { + ca = nsvg__applyOpacity(grad->stops[i].color, opacity); + cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity); + ua = nsvg__clampf(grad->stops[i].offset, 0, 1); + ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1); + ia = (int)(ua * 255.0f); + ib = (int)(ub * 255.0f); + count = ib - ia; + if (count <= 0) continue; + u = 0; + du = 1.0f / (float)count; + for (j = 0; j < count; j++) { + cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u); + u += du; + } + } + + for (i = ib; i < 256; i++) + cache->colors[i] = cb; + } + +} + +/* +static void dumpEdges(NSVGrasterizer* r, const char* name) +{ + float xmin = 0, xmax = 0, ymin = 0, ymax = 0; + NSVGedge *e = NULL; + int i; + if (r->nedges == 0) return; + FILE* fp = fopen(name, "w"); + if (fp == NULL) return; + + xmin = xmax = r->edges[0].x0; + ymin = ymax = r->edges[0].y0; + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + xmin = nsvg__minf(xmin, e->x0); + xmin = nsvg__minf(xmin, e->x1); + xmax = nsvg__maxf(xmax, e->x0); + xmax = nsvg__maxf(xmax, e->x1); + ymin = nsvg__minf(ymin, e->y0); + ymin = nsvg__minf(ymin, e->y1); + ymax = nsvg__maxf(ymax, e->y0); + ymax = nsvg__maxf(ymax, e->y1); + } + + fprintf(fp, "", xmin, ymin, (xmax - xmin), (ymax - ymin)); + + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + fprintf(fp ,"", e->x0,e->y0, e->x1,e->y1); + } + + for (i = 0; i < r->npoints; i++) { + if (i+1 < r->npoints) + fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y); + fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0"); + } + + fprintf(fp, ""); + fclose(fp); +} +*/ + +void nsvgRasterize(NSVGrasterizer* r, + NSVGimage* image, float tx, float ty, float scale, + unsigned char* dst, int w, int h, int stride) +{ + NSVGshape *shape = NULL; + NSVGedge *e = NULL; + NSVGcachedPaint cache; + int i; + + r->bitmap = dst; + r->width = w; + r->height = h; + r->stride = stride; + + if (w > r->cscanline) { + r->cscanline = w; + r->scanline = (unsigned char*)realloc(r->scanline, w); + if (r->scanline == NULL) return; + } + + for (i = 0; i < h; i++) + memset(&dst[i*stride], 0, w*4); + + for (shape = image->shapes; shape != NULL; shape = shape->next) { + if (!(shape->flags & NSVG_FLAGS_VISIBLE)) + continue; + + if (shape->fill.type != NSVG_PAINT_NONE) { + nsvg__resetPool(r); + r->freelist = NULL; + r->nedges = 0; + + nsvg__flattenShape(r, shape, scale); + + // Scale and translate edges + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + e->x0 = tx + e->x0; + e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; + e->x1 = tx + e->x1; + e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; + } + + // Rasterize edges + if (r->nedges != 0) + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + + // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + nsvg__initPaint(&cache, &shape->fill, shape->opacity); + + nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule); + } + if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) { + nsvg__resetPool(r); + r->freelist = NULL; + r->nedges = 0; + + nsvg__flattenShapeStroke(r, shape, scale); + +// dumpEdges(r, "edge.svg"); + + // Scale and translate edges + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + e->x0 = tx + e->x0; + e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; + e->x1 = tx + e->x1; + e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; + } + + // Rasterize edges + if (r->nedges != 0) + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + + // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + nsvg__initPaint(&cache, &shape->stroke, shape->opacity); + + nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO); + } + } + + nsvg__unpremultiplyAlpha(dst, w, h, stride); + + r->bitmap = NULL; + r->width = 0; + r->height = 0; + r->stride = 0; +} + +#endif // NANOSVGRAST_IMPLEMENTATION + +#endif // NANOSVGRAST_H diff --git a/libraries/ZWidget/src/core/pathfill.cpp b/libraries/ZWidget/src/core/pathfill.cpp new file mode 100644 index 0000000000..bac3dfb507 --- /dev/null +++ b/libraries/ZWidget/src/core/pathfill.cpp @@ -0,0 +1,613 @@ + +#include "core/pathfill.h" +#include +#include + +static const int AntialiasLevel = 8; +static const int MaskBlockSize = 16; +static const int MaskBufferSize = MaskBlockSize * MaskBlockSize; +static const int ScanlineBlockSize = MaskBlockSize * AntialiasLevel; + +class PathScanlineEdge +{ +public: + PathScanlineEdge() = default; + PathScanlineEdge(double x, bool up_direction) : x(x), up_direction(up_direction) { } + + double x = 0.0; + bool up_direction = false; +}; + +class PathScanline +{ +public: + std::vector edges; + std::vector pixels; + + void insert_sorted(PathScanlineEdge edge) + { + edges.push_back(edge); + + for (size_t pos = edges.size() - 1; pos > 0 && edges[pos - 1].x >= edge.x; pos--) + { + PathScanlineEdge temp = edges[pos - 1]; + edges[pos - 1] = edges[pos]; + edges[pos] = temp; + } + } +}; + +class PathRasterRange +{ +public: + void Begin(const PathScanline* scanline, PathFillMode mode); + void Next(); + + bool found = false; + int x0; + int x1; + +private: + const PathScanline* scanline = nullptr; + PathFillMode mode; + size_t i = 0; + int nonzero_rule = 0; +}; + +enum class PathFillBlockResult +{ + Empty, + Partial, + Full +}; + +class PathMaskBuffer +{ +public: + void BeginRow(PathScanline* scanlines, PathFillMode mode); + PathFillBlockResult FillBlock(int xpos); + + unsigned char MaskBufferData[MaskBufferSize]; + +private: + bool IsFullBlock(int xpos) const; + + PathRasterRange Range[ScanlineBlockSize]; +}; + +class PathFillRasterizer +{ +public: + void Rasterize(const PathFillDesc& path, uint8_t* dest, int width, int height); + +private: + void Clear(); + + void Begin(double x, double y); + void QuadraticBezier(double cp1_x, double cp1_y, double cp2_x, double cp2_y); + void CubicBezier(double cp1_x, double cp1_y, double cp2_x, double cp2_y, double cp3_x, double cp3_y); + void Line(double x, double y); + void End(bool close); + + void SubdivideBezier(int level, double cp0_x, double cp0_y, double cp1_x, double cp1_y, double cp2_x, double cp2_y, double cp3_x, double cp3_y, double t0, double t1); + static Point PointOnBezier(double cp0_x, double cp0_y, double cp1_x, double cp1_y, double cp2_x, double cp2_y, double cp3_x, double cp3_y, double t); + + void Fill(PathFillMode mode, uint8_t* dest, int dest_width, int dest_height); + + struct Extent + { + Extent() : left(INT_MAX), right(0) {} + int left; + int right; + }; + + Extent FindExtent(const PathScanline* scanline, int max_width); + + double start_x = 0.0; + double start_y = 0.0; + double last_x = 0.0; + double last_y = 0.0; + + int first_scanline = 0; + int last_scanline = 0; + + int width = 0; + int height = 0; + std::vector scanlines; + + PathMaskBuffer mask_blocks; +}; + +///////////////////////////////////////////////////////////////////////////// + +void PathFillDesc::Rasterize(uint8_t* dest, int width, int height, bool blend) +{ + if (!blend) + { + memset(dest, 0, width * height); + } + PathFillRasterizer rasterizer; + rasterizer.Rasterize(*this, dest, width, height); +} + +///////////////////////////////////////////////////////////////////////////// + +void PathFillRasterizer::Rasterize(const PathFillDesc& path, uint8_t* dest, int dest_width, int dest_height) +{ + Clear(); + + // For simplicity of the code, ensure the mask is always a multiple of MaskBlockSize + int block_width = ScanlineBlockSize * ((dest_width + MaskBlockSize - 1) / MaskBlockSize); + int block_height = ScanlineBlockSize * ((dest_height + MaskBlockSize - 1) / MaskBlockSize); + + if (width != block_width || height != block_height) + { + width = block_width; + height = block_height; + + scanlines.resize(block_height); + first_scanline = scanlines.size(); + last_scanline = 0; + } + + for (const auto& subpath : path.subpaths) + { + Point start_point = subpath.points[0]; + Begin(start_point.x, start_point.y); + + size_t i = 1; + for (PathFillCommand command : subpath.commands) + { + if (command == PathFillCommand::line) + { + const Point& next_point = subpath.points[i]; + i++; + + Line(next_point.x, next_point.y); + } + else if (command == PathFillCommand::quadradic) + { + const Point& control = subpath.points[i]; + const Point& next_point = subpath.points[i + 1]; + i += 2; + + QuadraticBezier(control.x, control.y, next_point.x, next_point.y); + } + else if (command == PathFillCommand::cubic) + { + const Point& control1 = subpath.points[i]; + const Point& control2 = subpath.points[i + 1]; + const Point& next_point = subpath.points[i + 2]; + i += 3; + + CubicBezier(control1.x, control1.y, control2.x, control2.y, next_point.x, next_point.y); + } + } + + End(subpath.closed); + } + + Fill(path.fill_mode, dest, dest_width, dest_height); +} + +void PathFillRasterizer::Fill(PathFillMode mode, uint8_t* dest, int dest_width, int dest_height) +{ + if (scanlines.empty()) return; + + int start_y = first_scanline / ScanlineBlockSize * ScanlineBlockSize; + int end_y = (last_scanline + ScanlineBlockSize - 1) / ScanlineBlockSize * ScanlineBlockSize; + + for (int ypos = start_y; ypos < end_y; ypos += ScanlineBlockSize) + { + mask_blocks.BeginRow(&scanlines[ypos], mode); + + Extent extent = FindExtent(&scanlines[ypos], width); + for (int xpos = extent.left; xpos < extent.right; xpos += ScanlineBlockSize) + { + PathFillBlockResult result = mask_blocks.FillBlock(xpos); + + int dest_x = xpos / AntialiasLevel; + int dest_y = ypos / AntialiasLevel; + int count_x = std::min(dest_x + MaskBlockSize, dest_width) - dest_x; + int count_y = std::min(dest_y + MaskBlockSize, dest_height) - dest_y; + + if (result == PathFillBlockResult::Full) + { + for (int i = 0; i < count_y; i++) + { + uint8_t* dline = dest + dest_x + (dest_y + i) * dest_width; + memset(dline, 255, count_x); + } + } + else if (result == PathFillBlockResult::Partial) + { + for (int i = 0; i < count_y; i++) + { + const uint8_t* sline = mask_blocks.MaskBufferData + i * MaskBlockSize; + uint8_t* dline = dest + dest_x + (dest_y + i) * dest_width; + for (int j = 0; j < count_x; j++) + { + dline[j] = std::min((int)dline[j] + (int)sline[j], 255); + } + } + } + } + } +} + +PathFillRasterizer::Extent PathFillRasterizer::FindExtent(const PathScanline* scanline, int max_width) +{ + // Find scanline extents + Extent extent; + for (unsigned int cnt = 0; cnt < ScanlineBlockSize; cnt++, scanline++) + { + if (scanline->edges.empty()) + continue; + + extent.left = std::min(extent.left, (int)scanline->edges.front().x); + extent.right = std::max(extent.right, (int)scanline->edges.back().x); + } + extent.left = std::max(extent.left, 0); + extent.right = std::min(extent.right, max_width); + + return extent; +} + +void PathFillRasterizer::Clear() +{ + for (size_t y = first_scanline; y < last_scanline; y++) + { + auto& scanline = scanlines[y]; + if (!scanline.edges.empty()) + { + scanline.edges.clear(); + } + } + + first_scanline = scanlines.size(); + last_scanline = 0; +} + +void PathFillRasterizer::Begin(double x, double y) +{ + start_x = last_x = x; + start_y = last_y = y; +} + +void PathFillRasterizer::End(bool close) +{ + if (close) + { + Line(start_x, start_y); + } +} + +void PathFillRasterizer::QuadraticBezier(double qcp1_x, double qcp1_y, double qcp2_x, double qcp2_y) +{ + double qcp0_x = last_x; + double qcp0_y = last_y; + + // Convert to cubic: + double cp1_x = qcp0_x + 2.0 * (qcp1_x - qcp0_x) / 3.0; + double cp1_y = qcp0_y + 2.0 * (qcp1_y - qcp0_y) / 3.0; + double cp2_x = qcp1_x + (qcp2_x - qcp1_x) / 3.0; + double cp2_y = qcp1_y + (qcp2_y - qcp1_y) / 3.0; + double cp3_x = qcp2_x; + double cp3_y = qcp2_y; + CubicBezier(cp1_x, cp1_y, cp2_x, cp2_y, cp3_x, cp3_y); +} + +void PathFillRasterizer::CubicBezier(double cp1_x, double cp1_y, double cp2_x, double cp2_y, double cp3_x, double cp3_y) +{ + double cp0_x = last_x; + double cp0_y = last_y; + + double estimated_length = + std::sqrt((cp1_x - cp0_x) * (cp1_x - cp0_x) + (cp1_y - cp0_y) * (cp1_y - cp0_y)) + + std::sqrt((cp1_x - cp0_x) * (cp1_x - cp0_x) + (cp1_y - cp0_y) * (cp1_y - cp0_y)) + + std::sqrt((cp1_x - cp0_x) * (cp1_x - cp0_x) + (cp1_y - cp0_y) * (cp1_y - cp0_y)); + + double min_segs = 10.0; + double segs = estimated_length / 5.0; + int steps = (int)std::ceil(std::sqrt(segs * segs * 0.3f + min_segs)); + for (int i = 0; i < steps; i++) + { + //Point sp = PointOnBezier(cp0_x, cp0_y, cp1_x, cp1_y, cp2_x, cp2_y, cp3_x, cp3_y, i / (double)steps); + Point ep = PointOnBezier(cp0_x, cp0_y, cp1_x, cp1_y, cp2_x, cp2_y, cp3_x, cp3_y, (i + 1) / (double)steps); + Line(ep.x, ep.y); + } + + // http://ciechanowski.me/blog/2014/02/18/drawing-bezier-curves/ + // http://antigrain.com/research/adaptive_bezier/ (best method, unfortunately GPL example code) +} + +void PathFillRasterizer::SubdivideBezier(int level, double cp0_x, double cp0_y, double cp1_x, double cp1_y, double cp2_x, double cp2_y, double cp3_x, double cp3_y, double t0, double t1) +{ + const double split_angle_cos = 0.99f; + + double tc = (t0 + t1) * 0.5f; + + Point sp = PointOnBezier(cp0_x, cp0_y, cp1_x, cp1_y, cp2_x, cp2_y, cp3_x, cp3_y, t0); + Point cp = PointOnBezier(cp0_x, cp0_y, cp1_x, cp1_y, cp2_x, cp2_y, cp3_x, cp3_y, tc); + Point ep = PointOnBezier(cp0_x, cp0_y, cp1_x, cp1_y, cp2_x, cp2_y, cp3_x, cp3_y, t1); + + Point sp2cp(cp.x - sp.x, cp.y - sp.y); + Point cp2ep(ep.x - cp.x, ep.y - cp.y); + + // Normalize + double len_sp2cp = std::sqrt(sp2cp.x * sp2cp.x + sp2cp.y * sp2cp.y); + double len_cp2ep = std::sqrt(cp2ep.x * cp2ep.x + cp2ep.y * cp2ep.y); + if (len_sp2cp > 0.0) { sp2cp.x /= len_sp2cp; sp2cp.y /= len_sp2cp; } + if (len_cp2ep > 0.0) { cp2ep.x /= len_cp2ep; cp2ep.y /= len_cp2ep; } + + double dot = sp2cp.x * cp2ep.x + sp2cp.y * cp2ep.y; + if (dot < split_angle_cos && level < 15) + { + SubdivideBezier(level + 1, cp0_x, cp0_y, cp1_x, cp1_y, cp2_x, cp2_y, cp3_x, cp3_y, t0, tc); + SubdivideBezier(level + 1, cp0_x, cp0_y, cp1_x, cp1_y, cp2_x, cp2_y, cp3_x, cp3_y, tc, t1); + } + else + { + Line(ep.x, ep.y); + } +} + +Point PathFillRasterizer::PointOnBezier(double cp0_x, double cp0_y, double cp1_x, double cp1_y, double cp2_x, double cp2_y, double cp3_x, double cp3_y, double t) +{ + const int num_cp = 4; + + double cp_x[4] = { cp0_x, cp1_x, cp2_x, cp3_x }; + double cp_y[4] = { cp0_y, cp1_y, cp2_y, cp3_y }; + + // Perform deCasteljau iterations: + // (linear interpolate between the control points) + double a = 1.0 - t; + double b = t; + for (int j = num_cp - 1; j > 0; j--) + { + for (int i = 0; i < j; i++) + { + cp_x[i] = a * cp_x[i] + b * cp_x[i + 1]; + cp_y[i] = a * cp_y[i] + b * cp_y[i + 1]; + } + } + + return Point(cp_x[0], cp_y[0]); +} + +void PathFillRasterizer::Line(double x1, double y1) +{ + double x0 = last_x; + double y0 = last_y; + + last_x = x1; + last_y = y1; + + x0 *= static_cast(AntialiasLevel); + x1 *= static_cast(AntialiasLevel); + y0 *= static_cast(AntialiasLevel); + y1 *= static_cast(AntialiasLevel); + + bool up_direction = y1 < y0; + double dy = y1 - y0; + + constexpr const double epsilon = std::numeric_limits::epsilon(); + if (dy < -epsilon || dy > epsilon) + { + int start_y = static_cast(std::floor(std::min(y0, y1) + 0.5f)); + int end_y = static_cast(std::floor(std::max(y0, y1) - 0.5f)) + 1; + + start_y = std::max(start_y, 0); + end_y = std::min(end_y, height); + + double rcp_dy = 1.0 / dy; + + first_scanline = std::min(first_scanline, start_y); + last_scanline = std::max(last_scanline, end_y); + + for (int y = start_y; y < end_y; y++) + { + double ypos = y + 0.5f; + double x = x0 + (x1 - x0) * (ypos - y0) * rcp_dy; + scanlines[y].insert_sorted(PathScanlineEdge(x, up_direction)); + } + } +} + +///////////////////////////////////////////////////////////////////////////// + +void PathRasterRange::Begin(const PathScanline* new_scanline, PathFillMode new_mode) +{ + scanline = new_scanline; + mode = new_mode; + found = false; + i = 0; + nonzero_rule = 0; + Next(); +} + +void PathRasterRange::Next() +{ + if (i + 1 >= scanline->edges.size()) + { + found = false; + return; + } + + if (mode == PathFillMode::alternate) + { + x0 = static_cast(scanline->edges[i].x + 0.5f); + x1 = static_cast(scanline->edges[i + 1].x - 0.5f) + 1; + i += 2; + found = true; + } + else + { + x0 = static_cast(scanline->edges[i].x + 0.5f); + nonzero_rule += scanline->edges[i].up_direction ? 1 : -1; + i++; + + while (i < scanline->edges.size()) + { + nonzero_rule += scanline->edges[i].up_direction ? 1 : -1; + x1 = static_cast(scanline->edges[i].x - 0.5f) + 1; + i++; + + if (nonzero_rule == 0) + { + found = true; + return; + } + } + found = false; + } +} + +///////////////////////////////////////////////////////////////////////// + +void PathMaskBuffer::BeginRow(PathScanline* scanlines, PathFillMode mode) +{ + for (unsigned int cnt = 0; cnt < ScanlineBlockSize; cnt++) + { + Range[cnt].Begin(&scanlines[cnt], mode); + } +} + +#if 0 +PathFillBlockResult PathMaskBuffer::FillBlock(int xpos) +{ + if (IsFullBlock(xpos)) + { + return PathFillBlockResult::Full; + } + + const int block_size = MaskBlockSize / 16 * MaskBlockSize; + __m128i block[block_size]; + + for (auto& elem : block) + elem = _mm_setzero_si128(); + + for (unsigned int cnt = 0; cnt < ScanlineBlockSize; cnt++) + { + __m128i* line = &block[MaskBlockSize / 16 * (cnt / AntialiasLevel)]; + + while (range[cnt].found) + { + int x0 = range[cnt].x0; + if (x0 >= xpos + ScanlineBlockSize) + break; + int x1 = range[cnt].x1; + + x0 = max(x0, xpos); + x1 = min(x1, xpos + ScanlineBlockSize); + + if (x0 >= x1) // Done segment + { + range[cnt].next(); + } + else + { + for (int sse_block = 0; sse_block < MaskBlockSize / 16; sse_block++) + { + for (int alias_cnt = 0; alias_cnt < (AntialiasLevel); alias_cnt++) + { + __m128i start = _mm_set1_epi8((x0 + alias_cnt - xpos) / AntialiasLevel - 16 * sse_block); + __m128i end = _mm_set1_epi8((x1 + alias_cnt - xpos) / AntialiasLevel - 16 * sse_block); + __m128i x = _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + + __m128i left = _mm_cmplt_epi8(x, start); + __m128i right = _mm_cmplt_epi8(x, end); + __m128i mask = _mm_andnot_si128(left, right); + __m128i add_value = _mm_and_si128(mask, _mm_set1_epi8(256 / (AntialiasLevel * AntialiasLevel))); + + line[sse_block] = _mm_adds_epu8(line[sse_block], add_value); + } + } + + range[cnt].x0 = x1; // For next time + } + } + } + + __m128i empty_status = _mm_setzero_si128(); + for (auto& elem : block) + empty_status = _mm_or_si128(empty_status, elem); + + bool empty_block = _mm_movemask_epi8(_mm_cmpeq_epi32(empty_status, _mm_setzero_si128())) == 0xffff; + if (empty_block) return PathFillBlockResult::Empty; + + for (unsigned int cnt = 0; cnt < MaskBlockSize; cnt++) + { + __m128i* input = &block[MaskBlockSize / 16 * cnt]; + __m128i* output = (__m128i*)(MaskBufferData + cnt * mask_texture_size); + + for (int sse_block = 0; sse_block < MaskBlockSize / 16; sse_block++) + _mm_storeu_si128(&output[sse_block], input[sse_block]); + } + + return PathFillBlockResult::Partial; +} + +#else + +PathFillBlockResult PathMaskBuffer::FillBlock(int xpos) +{ + if (IsFullBlock(xpos)) + { + return PathFillBlockResult::Full; + } + + memset(MaskBufferData, 0, MaskBufferSize); + + bool empty_block = true; + for (unsigned int cnt = 0; cnt < ScanlineBlockSize; cnt++) + { + unsigned char* line = MaskBufferData + MaskBlockSize * (cnt / AntialiasLevel); + while (Range[cnt].found) + { + int x0 = Range[cnt].x0; + if (x0 >= xpos + ScanlineBlockSize) + break; + int x1 = Range[cnt].x1; + + x0 = std::max(x0, xpos); + x1 = std::min(x1, xpos + ScanlineBlockSize); + + if (x0 >= x1) // Done segment + { + Range[cnt].Next(); + } + else + { + empty_block = false; + for (int x = x0 - xpos; x < x1 - xpos; x++) + { + int pixel = line[x / AntialiasLevel]; + pixel = std::min(pixel + (256 / (AntialiasLevel * AntialiasLevel)), 255); + line[x / AntialiasLevel] = pixel; + } + Range[cnt].x0 = x1; // For next time + } + } + } + + return empty_block ? PathFillBlockResult::Empty : PathFillBlockResult::Partial; +} + +#endif + +bool PathMaskBuffer::IsFullBlock(int xpos) const +{ + for (auto& elem : Range) + { + if (!elem.found) + { + return false; + } + if ((elem.x0 > xpos) || (elem.x1 < (xpos + ScanlineBlockSize - 1))) + { + return false; + } + } + return true; +} diff --git a/libraries/ZWidget/src/core/picopng/LICENSE.txt b/libraries/ZWidget/src/core/picopng/LICENSE.txt new file mode 100644 index 0000000000..a1f522f51b --- /dev/null +++ b/libraries/ZWidget/src/core/picopng/LICENSE.txt @@ -0,0 +1,18 @@ + // picoPNG version 20101224 + // Copyright (c) 2005-2010 Lode Vandevenne + // + // 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. diff --git a/libraries/ZWidget/src/core/picopng/picopng.cpp b/libraries/ZWidget/src/core/picopng/picopng.cpp new file mode 100644 index 0000000000..97eb3b500f --- /dev/null +++ b/libraries/ZWidget/src/core/picopng/picopng.cpp @@ -0,0 +1,595 @@ +#include +#include +#include + +/* +decodePNG: The picoPNG function, decodes a PNG file buffer in memory, into a raw pixel buffer. +out_image: output parameter, this will contain the raw pixels after decoding. + By default the output is 32-bit RGBA color. + The std::vector is automatically resized to the correct size. +image_width: output_parameter, this will contain the width of the image in pixels. +image_height: output_parameter, this will contain the height of the image in pixels. +in_png: pointer to the buffer of the PNG file in memory. To get it from a file on + disk, load it and store it in a memory buffer yourself first. +in_size: size of the input PNG file in bytes. +convert_to_rgba32: optional parameter, true by default. + Set to true to get the output in RGBA 32-bit (8 bit per channel) color format + no matter what color type the original PNG image had. This gives predictable, + useable data from any random input PNG. + Set to false to do no color conversion at all. The result then has the same data + type as the PNG image, which can range from 1 bit to 64 bits per pixel. + Information about the color type or palette colors are not provided. You need + to know this information yourself to be able to use the data so this only + works for trusted PNG files. Use LodePNG instead of picoPNG if you need this information. +return: 0 if success, not 0 if some error occured. +*/ +int decodePNG(std::vector& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, size_t in_size, bool convert_to_rgba32 = true) +{ + // picoPNG version 20101224 + // Copyright (c) 2005-2010 Lode Vandevenne + // + // 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. + + // picoPNG is a PNG decoder in one C++ function of around 500 lines. Use picoPNG for + // programs that need only 1 .cpp file. Since it's a single function, it's very limited, + // it can convert a PNG to raw pixel data either converted to 32-bit RGBA color or + // with no color conversion at all. For anything more complex, another tiny library + // is available: LodePNG (lodepng.c(pp)), which is a single source and header file. + // Apologies for the compact code style, it's to make this tiny. + + static const unsigned long LENBASE[29] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258}; + static const unsigned long LENEXTRA[29] = {0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; + static const unsigned long DISTBASE[30] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; + static const unsigned long DISTEXTRA[30] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; + static const unsigned long CLCL[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; //code length code lengths + struct Zlib //nested functions for zlib decompression + { + static unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++; return result;} + static unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits) + { + unsigned long result = 0; + for(size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i; + return result; + } + struct HuffmanTree + { + int makeFromLengths(const std::vector& bitlen, unsigned long maxbitlen) + { //make tree given the lengths + unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0; + std::vector tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0); + for(unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; //count number of instances of each code length + for(unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1; + for(unsigned long n = 0; n < numcodes; n++) if(bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; //generate all the codes + tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet + for(unsigned long n = 0; n < numcodes; n++) //the codes + for(unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code + { + unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1; + if(treepos > numcodes - 2) return 55; + if(tree2d[2 * treepos + bit] == 32767) //not yet filled in + { + if(i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; } //last bit + else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; } //addresses are encoded as values > numcodes + } + else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value + } + return 0; + } + int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const + { //Decodes a symbol from the tree + unsigned long numcodes = (unsigned long)tree2d.size() / 2; + if(treepos >= numcodes) return 11; //error: you appeared outside the codetree + result = tree2d[2 * treepos + bit]; + decoded = (result < numcodes); + treepos = decoded ? 0 : result - numcodes; + return 0; + } + std::vector tree2d; //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree. + }; + struct Inflator + { + int error; + void inflate(std::vector& out, const std::vector& in, size_t inpos = 0) + { + size_t bp = 0, pos = 0; //bit pointer and byte pointer + error = 0; + unsigned long BFINAL = 0; + while(!BFINAL && !error) + { + if(bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory + BFINAL = readBitFromStream(bp, &in[inpos]); + unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]); + if(BTYPE == 3) { error = 20; return; } //error: invalid BTYPE + else if(BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size()); + else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE); + } + if(!error) out.resize(pos); //Only now we know the true size of out, resize it to that + } + void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree + { + std::vector bitlen(288, 8), bitlenD(32, 5);; + for(size_t i = 144; i <= 255; i++) bitlen[i] = 9; + for(size_t i = 256; i <= 279; i++) bitlen[i] = 7; + tree.makeFromLengths(bitlen, 15); + treeD.makeFromLengths(bitlenD, 15); + } + HuffmanTree codetree, codetreeD, codelengthcodetree; //the code tree for Huffman codes, dist codes, and code length codes + unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, size_t inlength) + { //decode a single symbol from given list of bits with given code tree. return value is the symbol + bool decoded; unsigned long ct; + for(size_t treepos = 0;;) + { + if((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode + error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); if(error) return 0; //stop, an error happened + if(decoded) return ct; + } + } + void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, size_t& bp, size_t inlength) + { //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree + std::vector bitlen(288, 0), bitlenD(32, 0); + if(bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory + size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257 + size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1 + size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4 + std::vector codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree + for(size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0; + error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if(error) return; + size_t i = 0, replength; + while(i < HLIT + HDIST) + { + unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if(error) return; + if(code <= 15) { if(i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code + else if(code == 16) //repeat previous + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 3 + readBitsFromStream(bp, in, 2); + unsigned long value; //set value to the previous code + if((i - 1) < HLIT) value = bitlen[i - 1]; + else value = bitlenD[i - HLIT - 1]; + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value; + } + } + else if(code == 17) //repeat "0" 3-10 times + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 3 + readBitsFromStream(bp, in, 3); + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; + } + } + else if(code == 18) //repeat "0" 11-138 times + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 11 + readBitsFromStream(bp, in, 7); + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; + } + } + else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen. + } + if(bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0 + error = tree.makeFromLengths(bitlen, 15); if(error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done + error = treeD.makeFromLengths(bitlenD, 15); if(error) return; + } + void inflateHuffmanBlock(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength, unsigned long btype) + { + if(btype == 1) { generateFixedTrees(codetree, codetreeD); } + else if(btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if(error) return; } + for(;;) + { + unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if(error) return; + if(code == 256) return; //end code + else if(code <= 255) //literal symbol + { + if(pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room + out[pos++] = (unsigned char)(code); + } + else if(code >= 257 && code <= 285) //length code + { + size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257]; + if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory + length += readBitsFromStream(bp, in, numextrabits); + unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if(error) return; + if(codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used) + unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD]; + if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory + dist += readBitsFromStream(bp, in, numextrabitsD); + size_t start = pos, back = start - dist; //backwards + if(pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room + for(size_t i = 0; i < length; i++) { out[pos++] = out[back++]; if(back >= start) back = start - dist; } + } + } + } + void inflateNoCompression(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength) + { + while((bp & 0x7) != 0) bp++; //go to first boundary of byte + size_t p = bp / 8; + if(p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory + unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4; + if(LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN + if(pos + LEN >= out.size()) out.resize(pos + LEN); + if(p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer + for(unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data + bp = p * 8; + } + }; + int decompress(std::vector& out, const std::vector& in) //returns error value + { + Inflator inflator; + if(in.size() < 2) { return 53; } //error, size of zlib data too small + if((in[0] * 256 + in[1]) % 31 != 0) { return 24; } //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way + unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1; + if(CM != 8 || CINFO > 7) { return 25; } //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec + if(FDICT != 0) { return 26; } //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary." + inflator.inflate(out, in, 2); + return inflator.error; //note: adler32 checksum was skipped and ignored + } + }; + struct PNG //nested functions for PNG decoding + { + struct Info + { + unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b; + bool key_defined; //is a transparent color key given? + std::vector palette; + } info; + int error; + void decode(std::vector& out, const unsigned char* in, size_t size, bool convert_to_rgba32) + { + error = 0; + if(size == 0 || in == 0) { error = 48; return; } //the given data is empty + readPngHeader(&in[0], size); if(error) return; + size_t pos = 33; //first byte of the first chunk after the header + std::vector idat; //the data from idat chunks + bool IEND = false, known_type = true; + info.key_defined = false; + while(!IEND) //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer + { + if(pos + 8 >= size) { error = 30; return; } //error: size of the in buffer too small to contain next chunk + size_t chunkLength = read32bitInt(&in[pos]); pos += 4; + if(chunkLength > 2147483647) { error = 63; return; } + if(pos + chunkLength >= size) { error = 35; return; } //error: size of the in buffer too small to contain next chunk + if(in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') //IDAT chunk, containing compressed image data + { + idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]); + pos += (4 + chunkLength); + } + else if(in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') { pos += 4; IEND = true; } + else if(in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') //palette chunk (PLTE) + { + pos += 4; //go after the 4 letters + info.palette.resize(4 * (chunkLength / 3)); + if(info.palette.size() > (4 * 256)) { error = 38; return; } //error: palette too big + for(size_t i = 0; i < info.palette.size(); i += 4) + { + for(size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB + info.palette[i + 3] = 255; //alpha + } + } + else if(in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') //palette transparency chunk (tRNS) + { + pos += 4; //go after the 4 letters + if(info.colorType == 3) + { + if(4 * chunkLength > info.palette.size()) { error = 39; return; } //error: more alpha values given than there are palette entries + for(size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++]; + } + else if(info.colorType == 0) + { + if(chunkLength != 2) { error = 40; return; } //error: this chunk must be 2 bytes for greyscale image + info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; + } + else if(info.colorType == 2) + { + if(chunkLength != 6) { error = 41; return; } //error: this chunk must be 6 bytes for RGB image + info.key_defined = 1; + info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2; + info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2; + info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; + } + else { error = 42; return; } //error: tRNS chunk not allowed for other color models + } + else //it's not an implemented chunk type, so ignore it: skip over the data + { + if(!(in[pos + 0] & 32)) { error = 69; return; } //error: unknown critical chunk (5th bit of first byte of chunk type is 0) + pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk + known_type = false; + } + pos += 4; //step over CRC (which is ignored) + } + unsigned long bpp = getBpp(info); + std::vector scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); //now the out buffer will be filled + Zlib zlib; //decompress with the Zlib decompressor + error = zlib.decompress(scanlines, idat); if(error) return; //stop if the zlib decompressor returned an error + size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8; + out.resize(outlength); //time to fill the out buffer + unsigned char* out_ = outlength ? &out[0] : 0; //use a regular pointer to the std::vector for faster code if compiled without optimization + if(info.interlaceMethod == 0) //no interlace, just filter + { + size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; //length in bytes of a scanline, excluding the filtertype byte + if(bpp >= 8) //byte per byte + for(unsigned long y = 0; y < info.height; y++) + { + unsigned long filterType = scanlines[linestart]; + const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; + unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; + linestart += (1 + linelength); //go to start of next scanline + } + else //less than 8 bits per pixel, so fill it up bit per bit + { + std::vector templine((info.width * bpp + 7) >> 3); //only used if bpp < 8 + for(size_t y = 0, obp = 0; y < info.height; y++) + { + unsigned long filterType = scanlines[linestart]; + const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; + unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; + for(size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0])); + linestart += (1 + linelength); //go to start of next scanline + } + } + } + else //interlaceMethod is 1 (Adam7) + { + size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 }; + size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 }; + size_t passstart[7] = {0}; + size_t pattern[28] = {0,4,0,2,0,1,0,0,0,4,0,2,0,1,8,8,4,4,2,2,1,8,8,8,4,4,2,2}; //values for the adam7 passes + for(int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8); + std::vector scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); //"old" and "new" scanline + for(int i = 0; i < 7; i++) + adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp); + } + if(convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) //conversion needed + { + std::vector data = out; + error = convert(out, &data[0], info, info.width, info.height); + } + } + void readPngHeader(const unsigned char* in, size_t inlength) //read the information from the header and store it in the Info + { + if(inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header + if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature + if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; } //error: it doesn't start with a IHDR chunk! + info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]); + info.bitDepth = in[24]; info.colorType = in[25]; + info.compressionMethod = in[26]; if(in[26] != 0) { error = 32; return; } //error: only compression method 0 is allowed in the specification + info.filterMethod = in[27]; if(in[27] != 0) { error = 33; return; } //error: only filter method 0 is allowed in the specification + info.interlaceMethod = in[28]; if(in[28] > 1) { error = 34; return; } //error: only interlace methods 0 and 1 exist in the specification + error = checkColorValidity(info.colorType, info.bitDepth); + } + void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned long filterType, size_t length) + { + switch(filterType) + { + case 0: for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; break; + case 1: + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth]; + break; + case 2: + if(precon) for(size_t i = 0; i < length; i++) recon[i] = scanline[i] + precon[i]; + else for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; + break; + case 3: + if(precon) + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2; + for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2); + } + else + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2; + } + break; + case 4: + if(precon) + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + paethPredictor(0, precon[i], 0); + for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]); + } + else + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0); + } + break; + default: error = 36; return; //error: unexisting filter type given + } + } + void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, unsigned long bpp) + { //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already. + if(passw == 0) return; + size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8); + for(unsigned long y = 0; y < passh; y++) + { + unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo; + unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); if(error) return; + if(bpp >= 8) for(size_t i = 0; i < passw; i++) for(size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel + out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b]; + else for(size_t i = 0; i < passw; i++) + { + size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp; + for(size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0])); + } + unsigned char* temp = linen; linen = lineo; lineo = temp; //swap the two buffer pointers "line old" and "line new" + } + } + static unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++; return result;} + static unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits) + { + unsigned long result = 0; + for(size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i); + return result; + } + void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; } + unsigned long read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } + int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code + { + if((colorType == 2 || colorType == 4 || colorType == 6)) { if(!(bd == 8 || bd == 16)) return 37; else return 0; } + else if(colorType == 0) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; else return 0; } + else if(colorType == 3) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; else return 0; } + else return 31; //unexisting color type + } + unsigned long getBpp(const Info& info) + { + if(info.colorType == 2) return (3 * info.bitDepth); + else if(info.colorType >= 4) return (info.colorType - 2) * info.bitDepth; + else return info.bitDepth; + } + int convert(std::vector& out, const unsigned char* in, Info& infoIn, unsigned long w, unsigned long h) + { //converts from any color type to 32-bit. return value = LodePNG error code + size_t numpixels = w * h, bp = 0; + out.resize(numpixels * 4); + unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization + if(infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i]; + out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color + for(size_t i = 0; i < numpixels; i++) + { + for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c]; + out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette) + for(size_t i = 0; i < numpixels; i++) + { + if(4U * in[i] >= infoIn.palette.size()) return 46; + for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; //get rgb colors from the palette + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0]; + out_[4 * i + 3] = in[2 * i + 1]; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha + else if(infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i]; + out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color + for(size_t i = 0; i < numpixels; i++) + { + for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c]; + out_[4 * i + 3] = (infoIn.key_defined && 256U*in[6*i+0]+in[6*i+1] == infoIn.key_r && 256U*in[6*i+2]+in[6*i+3] == infoIn.key_g && 256U*in[6*i+4]+in[6*i+5] == infoIn.key_b) ? 0 : 255; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte + out_[4 * i + 3] = in[4 * i + 2]; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha + else if(infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1); //scale value from 0 to 255 + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value); + out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255; + } + else if(infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette + for(size_t i = 0; i < numpixels; i++) + { + unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth); + if(4 * value >= infoIn.palette.size()) return 47; + for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; //get rgb colors from the palette + } + return 0; + } + unsigned char paethPredictor(short a, short b, short c) //Paeth predicter, used by PNG filter type 4 + { + short p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = p > c ? (p - c) : (c - p); + return (unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c); + } + }; + PNG decoder; decoder.decode(out_image, in_png, in_size, convert_to_rgba32); + image_width = decoder.info.width; image_height = decoder.info.height; + return decoder.error; +} + +#if 0 + + + +//an example using the PNG loading function: + +#include +#include + +void loadFile(std::vector& buffer, const std::string& filename) //designed for loading files from hard disk in an std::vector +{ + std::ifstream file(filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate); + + //get filesize + std::streamsize size = 0; + if(file.seekg(0, std::ios::end).good()) size = file.tellg(); + if(file.seekg(0, std::ios::beg).good()) size -= file.tellg(); + + //read contents of the file into the vector + if(size > 0) + { + buffer.resize((size_t)size); + file.read((char*)(&buffer[0]), size); + } + else buffer.clear(); +} + +int main(int argc, char *argv[]) +{ + const char* filename = argc > 1 ? argv[1] : "test.png"; + + //load and decode + std::vector buffer, image; + loadFile(buffer, filename); + unsigned long w, h; + int error = decodePNG(image, w, h, buffer.empty() ? 0 : &buffer[0], (unsigned long)buffer.size()); + + //if there's an error, display it + if(error != 0) std::cout << "error: " << error << std::endl; + + //the pixels are now in the vector "image", use it as texture, draw it, ... + + if(image.size() > 4) std::cout << "width: " << w << " height: " << h << " first pixel: " << std::hex << int(image[0]) << int(image[1]) << int(image[2]) << int(image[3]) << std::endl; +} + +/* + //this is test code, it displays the pixels of a 1 bit PNG. To use it, set the flag convert_to_rgba32 to false and load a 1-bit PNG image with a small size (so that its ASCII representation can fit in a console window) + for(int y = 0; y < h; y++) + { + for(int x = 0; x < w; x++) + { + int i = y * h + x; + std::cout << (((image[i/8] >> (7-i%8)) & 1) ? '.' : '#'); + } + std::cout << std::endl; + } +*/ + +#endif diff --git a/libraries/ZWidget/src/core/picopng/picopng.h b/libraries/ZWidget/src/core/picopng/picopng.h new file mode 100644 index 0000000000..87dc961bea --- /dev/null +++ b/libraries/ZWidget/src/core/picopng/picopng.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +int decodePNG(std::vector& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, size_t in_size, bool convert_to_rgba32 = true); diff --git a/libraries/ZWidget/src/core/span_layout.cpp b/libraries/ZWidget/src/core/span_layout.cpp new file mode 100644 index 0000000000..1b68f6ef73 --- /dev/null +++ b/libraries/ZWidget/src/core/span_layout.cpp @@ -0,0 +1,883 @@ + +#include "core/span_layout.h" +#include "core/canvas.h" +#include "core/widget.h" +#include "core/font.h" +#include "core/image.h" + +SpanLayout::SpanLayout() +{ +} + +SpanLayout::~SpanLayout() +{ +} + +void SpanLayout::Clear() +{ + objects.clear(); + text.clear(); + lines.clear(); +} + +std::vector SpanLayout::GetRectById(int id) const +{ + std::vector segment_rects; + + double x = position.x; + double y = position.y; + for (std::vector::size_type line_index = 0; line_index < lines.size(); line_index++) + { + const Line& line = lines[line_index]; + for (std::vector::size_type segment_index = 0; segment_index < line.segments.size(); segment_index++) + { + const LineSegment& segment = line.segments[segment_index]; + if (segment.id == id) + { + segment_rects.push_back(Rect(x + segment.x_position, y, segment.width, y + line.height)); + } + } + y += line.height; + } + + return segment_rects; +} + +void SpanLayout::DrawLayout(Canvas* canvas) +{ + double x = position.x; + double y = position.y; + for (std::vector::size_type line_index = 0; line_index < lines.size(); line_index++) + { + Line& line = lines[line_index]; + for (std::vector::size_type segment_index = 0; segment_index < line.segments.size(); segment_index++) + { + LineSegment& segment = line.segments[segment_index]; + switch (segment.type) + { + case object_text: + DrawLayoutText(canvas, line, segment, x, y); + break; + case object_image: + DrawLayoutImage(canvas, line, segment, x, y); + break; + case object_component: + break; + } + + } + + if (line_index + 1 == lines.size() && !line.segments.empty()) + { + LineSegment& segment = line.segments.back(); + if (cursor_visible && segment.end <= cursor_pos) + { + switch (segment.type) + { + case object_text: + { + double cursor_x = x + segment.x_position + canvas->measureText(segment.font, text.substr(segment.start, segment.end - segment.start)).width; + double cursor_width = 1; + canvas->fillRect(Rect::ltrb(cursor_x, y + line.ascender - segment.ascender, cursor_width, y + line.ascender + segment.descender), cursor_color); + } + break; + } + } + } + + y += line.height; + } +} + +void SpanLayout::DrawLayoutEllipsis(Canvas* canvas, const Rect& content_rect) +{ + is_ellipsis_draw = true; + ellipsis_content_rect = content_rect; + try + { + is_ellipsis_draw = false; + DrawLayout(canvas); + } + catch (...) + { + is_ellipsis_draw = false; + throw; + } +} + +void SpanLayout::DrawLayoutImage(Canvas* canvas, Line& line, LineSegment& segment, double x, double y) +{ + canvas->drawImage(segment.image, Point(x + segment.x_position, y + line.ascender - segment.ascender)); +} + +void SpanLayout::DrawLayoutText(Canvas* canvas, Line& line, LineSegment& segment, double x, double y) +{ + std::string segment_text = text.substr(segment.start, segment.end - segment.start); + + int length = (int)segment_text.length(); + int s1 = clamp((int)sel_start - (int)segment.start, 0, length); + int s2 = clamp((int)sel_end - (int)segment.start, 0, length); + + if (s1 != s2) + { + double xx = x + segment.x_position; + double xx0 = xx + canvas->measureText(segment.font, segment_text.substr(0, s1)).width; + double xx1 = xx0 + canvas->measureText(segment.font, segment_text.substr(s1, s2 - s1)).width; + double sel_width = canvas->measureText(segment.font, segment_text.substr(s1, s2 - s1)).width; + + canvas->fillRect(Rect::ltrb(xx0, y + line.ascender - segment.ascender, xx1, y + line.ascender + segment.descender), sel_background); + + if (cursor_visible && cursor_pos >= segment.start && cursor_pos < segment.end) + { + double cursor_x = x + segment.x_position + canvas->measureText(segment.font, text.substr(segment.start, cursor_pos - segment.start)).width; + double cursor_width = cursor_overwrite_mode ? canvas->measureText(segment.font, text.substr(cursor_pos, 1)).width : 1; + canvas->fillRect(Rect::ltrb(cursor_x, y + line.ascender - segment.ascender, cursor_x + cursor_width, y + line.ascender + segment.descender), cursor_color); + } + + if (s1 > 0) + { + if (is_ellipsis_draw) + canvas->drawTextEllipsis(segment.font, Point(xx, y + line.ascender), ellipsis_content_rect, segment_text.substr(0, s1), segment.color); + else + canvas->drawText(segment.font, Point(xx, y + line.ascender), segment_text.substr(0, s1), segment.color); + } + if (is_ellipsis_draw) + canvas->drawTextEllipsis(segment.font, Point(xx0, y + line.ascender), ellipsis_content_rect, segment_text.substr(s1, s2 - s1), sel_foreground); + else + canvas->drawText(segment.font, Point(xx0, y + line.ascender), segment_text.substr(s1, s2 - s1), sel_foreground); + xx += sel_width; + if (s2 < length) + { + if (is_ellipsis_draw) + canvas->drawTextEllipsis(segment.font, Point(xx1, y + line.ascender), ellipsis_content_rect, segment_text.substr(s2), segment.color); + else + canvas->drawText(segment.font, Point(xx1, y + line.ascender), segment_text.substr(s2), segment.color); + } + } + else + { + if (cursor_visible && cursor_pos >= segment.start && cursor_pos < segment.end) + { + double cursor_x = x + segment.x_position + canvas->measureText(segment.font, text.substr(segment.start, cursor_pos - segment.start)).width; + double cursor_width = cursor_overwrite_mode ? canvas->measureText(segment.font, text.substr(cursor_pos, 1)).width : 1; + canvas->fillRect(Rect::ltrb(cursor_x, y + line.ascender - segment.ascender, cursor_x + cursor_width, y + line.ascender + segment.descender), cursor_color); + } + + if (is_ellipsis_draw) + canvas->drawTextEllipsis(segment.font, Point(x + segment.x_position, y + line.ascender), ellipsis_content_rect, segment_text, segment.color); + else + canvas->drawText(segment.font, Point(x + segment.x_position, y + line.ascender), segment_text, segment.color); + } +} + +SpanLayout::HitTestResult SpanLayout::HitTest(Canvas* canvas, const Point& pos) +{ + SpanLayout::HitTestResult result; + + if (lines.empty()) + { + result.type = SpanLayout::HitTestResult::no_objects_available; + return result; + } + + double x = position.x; + double y = position.y; + + // Check if we are outside to the top + if (pos.y < y) + { + result.type = SpanLayout::HitTestResult::outside_top; + result.object_id = lines[0].segments[0].id; + result.offset = 0; + return result; + } + + for (std::vector::size_type line_index = 0; line_index < lines.size(); line_index++) + { + Line& line = lines[line_index]; + + // Check if we found current line + if (pos.y >= y && pos.y <= y + line.height) + { + for (std::vector::size_type segment_index = 0; segment_index < line.segments.size(); segment_index++) + { + LineSegment& segment = line.segments[segment_index]; + + // Check if we are outside to the left + if (segment_index == 0 && pos.x < x) + { + result.type = SpanLayout::HitTestResult::outside_left; + result.object_id = segment.id; + result.offset = segment.start; + return result; + } + + // Check if we are inside a segment + if (pos.x >= x + segment.x_position && pos.x <= x + segment.x_position + segment.width) + { + std::string segment_text = text.substr(segment.start, segment.end - segment.start); + Point hit_point(pos.x - x - segment.x_position, 0); + size_t offset = segment.start + canvas->getCharacterIndex(segment.font, segment_text, hit_point); + + result.type = SpanLayout::HitTestResult::inside; + result.object_id = segment.id; + result.offset = offset; + return result; + } + + // Check if we are outside to the right + if (segment_index == line.segments.size() - 1 && pos.x > x + segment.x_position + segment.width) + { + result.type = SpanLayout::HitTestResult::outside_right; + result.object_id = segment.id; + result.offset = segment.end; + return result; + } + } + } + + y += line.height; + } + + // We are outside to the bottom + const Line& last_line = lines[lines.size() - 1]; + const LineSegment& last_segment = last_line.segments[last_line.segments.size() - 1]; + + result.type = SpanLayout::HitTestResult::outside_bottom; + result.object_id = last_segment.id; + result.offset = last_segment.end; + return result; +} + +Size SpanLayout::GetSize() const +{ + return GetRect().size(); +} + +Rect SpanLayout::GetRect() const +{ + double x = position.x; + double y = position.y; + + const double max_value = 0x70000000; + double left = max_value; + double top = max_value; + double right = -max_value; + double bottom = -max_value; + + for (std::vector::size_type line_index = 0; line_index < lines.size(); line_index++) + { + const Line& line = lines[line_index]; + for (std::vector::size_type segment_index = 0; segment_index < line.segments.size(); segment_index++) + { + const LineSegment& segment = line.segments[segment_index]; + Rect area(Point(x + segment.x_position, y), Size(segment.width, line.height)); + + left = std::min(left, area.left()); + right = std::max(right, area.right()); + top = std::min(top, area.top()); + bottom = std::max(bottom, area.bottom()); + } + y += line.height; + } + if (left > right) + left = right = position.x; + + if (top > bottom) + top = bottom = position.y; + + return Rect::ltrb(left, top, right, bottom); +} + +void SpanLayout::AddText(const std::string& more_text, std::shared_ptr font, const Colorf& color, int id) +{ + SpanObject object; + object.type = object_text; + object.start = text.length(); + object.end = object.start + more_text.length(); + object.font = font; + object.color = color; + object.id = id; + objects.push_back(object); + text += more_text; +} + +void SpanLayout::AddImage(std::shared_ptr image, double baseline_offset, int id) +{ + SpanObject object; + object.type = object_image; + object.image = image; + object.baseline_offset = baseline_offset; + object.id = id; + object.start = text.length(); + object.end = object.start + 1; + objects.push_back(object); + text += "*"; +} + +void SpanLayout::AddWidget(Widget* component, double baseline_offset, int id) +{ + SpanObject object; + object.type = object_component; + object.component = component; + object.baseline_offset = baseline_offset; + object.id = id; + object.start = text.length(); + object.end = object.start + 1; + objects.push_back(object); + text += "*"; +} + +void SpanLayout::Layout(Canvas* canvas, double max_width) +{ + LayoutLines(canvas, max_width); + + switch (alignment) + { + case span_right: AlignRight(max_width); break; + case span_center: AlignCenter(max_width); break; + case span_justify: AlignJustify(max_width); break; + case span_left: + default: break; + } +} + +void SpanLayout::SetPosition(const Point& pos) +{ + position = pos; +} + +SpanLayout::TextSizeResult SpanLayout::FindTextSize(Canvas* canvas, const TextBlock& block, size_t object_index) +{ + std::shared_ptr font = objects[object_index].font; + if (layout_cache.object_index != (int)object_index) + { + layout_cache.object_index = (int)object_index; + layout_cache.metrics = canvas->getFontMetrics(font); + } + + TextSizeResult result; + result.start = block.start; + size_t pos = block.start; + double x_position = 0; + while (pos != block.end) + { + size_t end = std::min(objects[object_index].end, block.end); + std::string subtext = text.substr(pos, end - pos); + + Size text_size = canvas->measureText(font, subtext).size(); + + result.width += text_size.width; + result.height = std::max(result.height, layout_cache.metrics.height + layout_cache.metrics.external_leading); + result.ascender = std::max(result.ascender, layout_cache.metrics.ascent); + result.descender = std::max(result.descender, layout_cache.metrics.descent); + + LineSegment segment; + segment.type = object_text; + segment.start = pos; + segment.end = end; + segment.font = objects[object_index].font; + segment.color = objects[object_index].color; + segment.id = objects[object_index].id; + segment.x_position = x_position; + segment.width = text_size.width; + segment.ascender = layout_cache.metrics.ascent; + segment.descender = layout_cache.metrics.descent; + x_position += text_size.width; + result.segments.push_back(segment); + + pos = end; + if (pos == objects[object_index].end) + { + object_index++; + result.objects_traversed++; + + if (object_index < objects.size()) + { + layout_cache.object_index = (int)object_index; + font = objects[object_index].font; + layout_cache.metrics = canvas->getFontMetrics(font); + } + } + } + result.end = pos; + return result; +} + +std::vector SpanLayout::FindTextBlocks() +{ + std::vector blocks; + std::vector::iterator block_object_it; + + // Find first object that is not text: + for (block_object_it = objects.begin(); block_object_it != objects.end() && (*block_object_it).type == object_text; ++block_object_it); + + std::string::size_type pos = 0; + while (pos < text.size()) + { + // Find end of text block: + std::string::size_type end_pos; + switch (text[pos]) + { + case ' ': + case '\t': + case '\n': + end_pos = text.find_first_not_of(text[pos], pos); + break; + default: + end_pos = text.find_first_of(" \t\n", pos); + break; + } + + if (end_pos == std::string::npos) + end_pos = text.length(); + + // If we traversed past an object that is not text: + if (block_object_it != objects.end() && (*block_object_it).start < end_pos) + { + // End text block + end_pos = (*block_object_it).start; + if (end_pos > pos) + { + TextBlock block; + block.start = pos; + block.end = end_pos; + blocks.push_back(block); + } + + // Create object block: + pos = end_pos; + end_pos = pos + 1; + + TextBlock block; + block.start = pos; + block.end = end_pos; + blocks.push_back(block); + + // Find next object that is not text: + for (++block_object_it; block_object_it != objects.end() && (*block_object_it).type == object_text; ++block_object_it); + } + else + { + if (end_pos > pos) + { + TextBlock block; + block.start = pos; + block.end = end_pos; + blocks.push_back(block); + } + } + + pos = end_pos; + } + + return blocks; +} + +void SpanLayout::SetAlign(SpanAlign align) +{ + alignment = align; +} + +void SpanLayout::LayoutLines(Canvas* canvas, double max_width) +{ + lines.clear(); + if (objects.empty()) + return; + + layout_cache.metrics = {}; + layout_cache.object_index = -1; + + CurrentLine current_line; + std::vector blocks = FindTextBlocks(); + for (std::vector::size_type block_index = 0; block_index < blocks.size(); block_index++) + { + if (objects[current_line.object_index].type == object_text) + LayoutText(canvas, blocks, block_index, current_line, max_width); + else + LayoutBlock(current_line, max_width, blocks, block_index); + } + NextLine(current_line); +} + +void SpanLayout::LayoutBlock(CurrentLine& current_line, double max_width, std::vector& blocks, std::vector::size_type block_index) +{ + if (objects[current_line.object_index].float_type == float_none) + LayoutInlineBlock(current_line, max_width, blocks, block_index); + else + LayoutFloatBlock(current_line, max_width); + + current_line.object_index++; +} + +void SpanLayout::LayoutInlineBlock(CurrentLine& current_line, double max_width, std::vector& blocks, std::vector::size_type block_index) +{ + Size size; + LineSegment segment; + if (objects[current_line.object_index].type == object_image) + { + size = Size(objects[current_line.object_index].image->GetWidth(), objects[current_line.object_index].image->GetHeight()); + segment.type = object_image; + segment.image = objects[current_line.object_index].image; + } + else if (objects[current_line.object_index].type == object_component) + { + size = objects[current_line.object_index].component->GetSize(); + segment.type = object_component; + segment.component = objects[current_line.object_index].component; + } + + if (current_line.x_position + size.width > max_width) + NextLine(current_line); + + segment.x_position = current_line.x_position; + segment.width = size.width; + segment.start = blocks[block_index].start; + segment.end = blocks[block_index].end; + segment.id = objects[current_line.object_index].id; + segment.ascender = size.height - objects[current_line.object_index].baseline_offset; + current_line.cur_line.segments.push_back(segment); + current_line.cur_line.height = std::max(current_line.cur_line.height, size.height + objects[current_line.object_index].baseline_offset); + current_line.cur_line.ascender = std::max(current_line.cur_line.ascender, segment.ascender); + current_line.x_position += size.width; +} + +void SpanLayout::LayoutFloatBlock(CurrentLine& current_line, double max_width) +{ + FloatBox floatbox; + floatbox.type = objects[current_line.object_index].type; + floatbox.image = objects[current_line.object_index].image; + floatbox.component = objects[current_line.object_index].component; + floatbox.id = objects[current_line.object_index].id; + if (objects[current_line.object_index].type == object_image) + floatbox.rect = Rect::xywh(0, current_line.y_position, floatbox.image->GetWidth(), floatbox.image->GetHeight()); + else if (objects[current_line.object_index].type == object_component) + floatbox.rect = Rect::xywh(0, current_line.y_position, floatbox.component->GetWidth(), floatbox.component->GetHeight()); + + if (objects[current_line.object_index].float_type == float_left) + floats_left.push_back(FloatBoxLeft(floatbox, max_width)); + else + floats_right.push_back(FloatBoxRight(floatbox, max_width)); + + ReflowLine(current_line, max_width); +} + +void SpanLayout::ReflowLine(CurrentLine& step, double max_width) +{ +} + +SpanLayout::FloatBox SpanLayout::FloatBoxLeft(FloatBox box, double max_width) +{ + return FloatBoxAny(box, max_width, floats_left); +} + +SpanLayout::FloatBox SpanLayout::FloatBoxRight(FloatBox box, double max_width) +{ + return FloatBoxAny(box, max_width, floats_right); +} + +SpanLayout::FloatBox SpanLayout::FloatBoxAny(FloatBox box, double max_width, const std::vector& floats1) +{ + bool restart; + do + { + restart = false; + for (size_t i = 0; i < floats1.size(); i++) + { + double top = std::max(floats1[i].rect.top(), box.rect.top()); + double bottom = std::min(floats1[i].rect.bottom(), box.rect.bottom()); + if (bottom > top && box.rect.left() < floats1[i].rect.right()) + { + Size s = box.rect.size(); + box.rect.x = floats1[i].rect.x; + box.rect.width = s.width; + + if (!BoxFitsOnLine(box, max_width)) + { + box.rect.x = 0; + box.rect.width = s.width; + box.rect.y = floats1[i].rect.bottom(); + box.rect.height = s.height; + restart = true; + break; + } + } + } + } while (restart); + return box; +} + +bool SpanLayout::BoxFitsOnLine(const FloatBox& box, double max_width) +{ + for (size_t i = 0; i < floats_right.size(); i++) + { + double top = std::max(floats_right[i].rect.top(), box.rect.top()); + double bottom = std::min(floats_right[i].rect.bottom(), box.rect.bottom()); + if (bottom > top) + { + if (box.rect.right() + floats_right[i].rect.right() > max_width) + return false; + } + } + return true; +} + +void SpanLayout::LayoutText(Canvas* canvas, std::vector blocks, std::vector::size_type block_index, CurrentLine& current_line, double max_width) +{ + TextSizeResult text_size_result = FindTextSize(canvas, blocks[block_index], current_line.object_index); + current_line.object_index += text_size_result.objects_traversed; + + current_line.cur_line.width = current_line.x_position; + + if (IsNewline(blocks[block_index])) + { + current_line.cur_line.height = std::max(current_line.cur_line.height, text_size_result.height); + current_line.cur_line.ascender = std::max(current_line.cur_line.ascender, text_size_result.ascender); + NextLine(current_line); + } + else + { + if (!FitsOnLine(current_line.x_position, text_size_result, max_width) && !IsWhitespace(blocks[block_index])) + { + if (LargerThanLine(text_size_result, max_width)) + { + // force line breaks to make it fit + ForcePlaceLineSegments(current_line, text_size_result, max_width); + } + else + { + NextLine(current_line); + PlaceLineSegments(current_line, text_size_result); + } + } + else + { + PlaceLineSegments(current_line, text_size_result); + } + } +} + +void SpanLayout::NextLine(CurrentLine& current_line) +{ + current_line.cur_line.width = current_line.x_position; + for (std::vector::reverse_iterator it = current_line.cur_line.segments.rbegin(); it != current_line.cur_line.segments.rend(); ++it) + { + LineSegment& segment = *it; + if (segment.type == object_text) + { + std::string s = text.substr(segment.start, segment.end - segment.start); + if (s.find_first_not_of(" \t\r\n") != std::string::npos) + { + current_line.cur_line.width = segment.x_position + segment.width; + break; + } + else + { + // We remove the width so that GetRect() reports the correct sizes + segment.width = 0; + } + } + else + { + current_line.cur_line.width = segment.x_position + segment.width; + break; + } + } + + double height = current_line.cur_line.height; + lines.push_back(current_line.cur_line); + current_line.cur_line = Line(); + current_line.x_position = 0; + current_line.y_position += height; +} + +void SpanLayout::PlaceLineSegments(CurrentLine& current_line, TextSizeResult& text_size_result) +{ + for (std::vector::iterator it = text_size_result.segments.begin(); it != text_size_result.segments.end(); ++it) + { + LineSegment segment = *it; + segment.x_position += current_line.x_position; + current_line.cur_line.segments.push_back(segment); + } + current_line.x_position += text_size_result.width; + current_line.cur_line.height = std::max(current_line.cur_line.height, text_size_result.height); + current_line.cur_line.ascender = std::max(current_line.cur_line.ascender, text_size_result.ascender); +} + +void SpanLayout::ForcePlaceLineSegments(CurrentLine& current_line, TextSizeResult& text_size_result, double max_width) +{ + if (current_line.x_position != 0) + NextLine(current_line); + + // to do: do this properly - for now we just place the entire block on one line + PlaceLineSegments(current_line, text_size_result); +} + +bool SpanLayout::IsNewline(const TextBlock& block) +{ + return block.start != block.end && text[block.start] == '\n'; +} + +bool SpanLayout::IsWhitespace(const TextBlock& block) +{ + return block.start != block.end && text[block.start] == ' '; +} + +bool SpanLayout::FitsOnLine(double x_position, const TextSizeResult& text_size_result, double max_width) +{ + return x_position + text_size_result.width <= max_width; +} + +bool SpanLayout::LargerThanLine(const TextSizeResult& text_size_result, double max_width) +{ + return text_size_result.width > max_width; +} + +void SpanLayout::AlignRight(double max_width) +{ + for (std::vector::size_type line_index = 0; line_index < lines.size(); line_index++) + { + Line& line = lines[line_index]; + double offset = max_width - line.width; + if (offset < 0) offset = 0; + + for (std::vector::size_type segment_index = 0; segment_index < line.segments.size(); segment_index++) + { + LineSegment& segment = line.segments[segment_index]; + segment.x_position += offset; + } + } +} + +void SpanLayout::AlignCenter(double max_width) +{ + for (std::vector::size_type line_index = 0; line_index < lines.size(); line_index++) + { + Line& line = lines[line_index]; + double offset = (max_width - line.width) / 2; + if (offset < 0) offset = 0; + + for (std::vector::size_type segment_index = 0; segment_index < line.segments.size(); segment_index++) + { + LineSegment& segment = line.segments[segment_index]; + segment.x_position += offset; + } + } +} + +void SpanLayout::AlignJustify(double max_width) +{ + // Note, we do not justify the last line + for (std::vector::size_type line_index = 0; line_index + 1 < lines.size(); line_index++) + { + Line& line = lines[line_index]; + double offset = max_width - line.width; + if (offset < 0) offset = 0; + + if (line.segments.size() <= 1) // Do not justify line if only one word exists + continue; + + for (std::vector::size_type segment_index = 0; segment_index < line.segments.size(); segment_index++) + { + LineSegment& segment = line.segments[segment_index]; + segment.x_position += (offset * segment_index) / (line.segments.size() - 1); + } + } +} + +Size SpanLayout::FindPreferredSize(Canvas* canvas) +{ + LayoutLines(canvas, 0x70000000); // Feed it with a very long length so it ends up on one line + return GetRect().size(); +} + +void SpanLayout::SetSelectionRange(std::string::size_type start, std::string::size_type end) +{ + sel_start = start; + sel_end = end; + if (sel_end < sel_start) + sel_end = sel_start; +} + +void SpanLayout::SetSelectionColors(const Colorf& foreground, const Colorf& background) +{ + sel_foreground = foreground; + sel_background = background; +} + +void SpanLayout::ShowCursor() +{ + cursor_visible = true; +} + +void SpanLayout::HideCursor() +{ + cursor_visible = false; +} + +void SpanLayout::SetCursorPos(std::string::size_type pos) +{ + cursor_pos = pos; +} + +void SpanLayout::SetCursorOverwriteMode(bool enable) +{ + cursor_overwrite_mode = enable; +} + +void SpanLayout::SetCursorColor(const Colorf& color) +{ + cursor_color = color; +} + +std::string SpanLayout::GetCombinedText() const +{ + return text; +} + +void SpanLayout::SetComponentGeometry() +{ + double x = position.x; + double y = position.y; + for (size_t i = 0; i < lines.size(); i++) + { + for (size_t j = 0; j < lines[i].segments.size(); j++) + { + if (lines[i].segments[j].type == object_component) + { + Point pos(x + lines[i].segments[j].x_position, y + lines[i].ascender - lines[i].segments[j].ascender); + Size size = lines[i].segments[j].component->GetSize(); + Rect rect(pos, size); + lines[i].segments[j].component->SetFrameGeometry(rect); + } + } + y += lines[i].height; + } +} + +double SpanLayout::GetFirstBaselineOffset() +{ + if (!lines.empty()) + { + return lines.front().ascender; + } + else + { + return 0; + } +} + +double SpanLayout::GetLastBaselineOffset() +{ + if (!lines.empty()) + { + double y = 0; + for (size_t i = 0; i + 1 < lines.size(); i++) + y += lines[i].height; + return y + lines.back().ascender; + } + else + { + return 0; + } +} diff --git a/libraries/ZWidget/src/core/theme.cpp b/libraries/ZWidget/src/core/theme.cpp new file mode 100644 index 0000000000..b92839989c --- /dev/null +++ b/libraries/ZWidget/src/core/theme.cpp @@ -0,0 +1,362 @@ + +#include "core/theme.h" +#include "core/widget.h" +#include "core/canvas.h" + +void WidgetStyle::SetBool(const std::string& state, const std::string& propertyName, bool value) +{ + StyleProperties[state][propertyName] = value; +} + +void WidgetStyle::SetInt(const std::string& state, const std::string& propertyName, int value) +{ + StyleProperties[state][propertyName] = value; +} + +void WidgetStyle::SetDouble(const std::string& state, const std::string& propertyName, double value) +{ + StyleProperties[state][propertyName] = value; +} + +void WidgetStyle::SetString(const std::string& state, const std::string& propertyName, const std::string& value) +{ + StyleProperties[state][propertyName] = value; +} + +void WidgetStyle::SetColor(const std::string& state, const std::string& propertyName, const Colorf& value) +{ + StyleProperties[state][propertyName] = value; +} + +const WidgetStyle::PropertyVariant* WidgetStyle::FindProperty(const std::string& state, const std::string& propertyName) const +{ + const WidgetStyle* style = this; + do + { + // Look for property in the specific state + auto stateIt = style->StyleProperties.find(state); + if (stateIt != style->StyleProperties.end()) + { + auto it = stateIt->second.find(propertyName); + if (it != stateIt->second.end()) + return &it->second; + } + + // Fall back to the widget main style + if (state != std::string()) + { + stateIt = style->StyleProperties.find(std::string()); + if (stateIt != style->StyleProperties.end()) + { + auto it = stateIt->second.find(propertyName); + if (it != stateIt->second.end()) + return &it->second; + } + } + + style = style->ParentStyle; + } while (style); + return nullptr; +} + +bool WidgetStyle::GetBool(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : false; +} + +int WidgetStyle::GetInt(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : 0; +} + +double WidgetStyle::GetDouble(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : 0.0; +} + +std::string WidgetStyle::GetString(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : std::string(); +} + +Colorf WidgetStyle::GetColor(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : Colorf::transparent(); +} + +///////////////////////////////////////////////////////////////////////////// + +void BasicWidgetStyle::Paint(Widget* widget, Canvas* canvas, Size size) +{ + Colorf bgcolor = widget->GetStyleColor("background-color"); + if (bgcolor.a > 0.0f) + canvas->fillRect(Rect::xywh(0.0, 0.0, size.width, size.height), bgcolor); + + Colorf borderleft = widget->GetStyleColor("border-left-color"); + Colorf bordertop = widget->GetStyleColor("border-top-color"); + Colorf borderright = widget->GetStyleColor("border-right-color"); + Colorf borderbottom = widget->GetStyleColor("border-bottom-color"); + + double borderwidth = widget->GridFitSize(1.0); + + if (bordertop.a > 0.0f) + canvas->fillRect(Rect::xywh(0.0, 0.0, size.width, borderwidth), bordertop); + if (borderbottom.a > 0.0f) + canvas->fillRect(Rect::xywh(0.0, size.height - borderwidth, size.width, borderwidth), borderbottom); + if (borderleft.a > 0.0f) + canvas->fillRect(Rect::xywh(0.0, 0.0, borderwidth, size.height), borderleft); + if (borderright.a > 0.0f) + canvas->fillRect(Rect::xywh(size.width - borderwidth, 0.0, borderwidth, size.height), borderright); +} + +///////////////////////////////////////////////////////////////////////////// + +static std::unique_ptr CurrentTheme; + +WidgetStyle* WidgetTheme::RegisterStyle(std::unique_ptr widgetStyle, const std::string& widgetClass) +{ + auto& style = Styles[widgetClass]; + style = std::move(widgetStyle); + return style.get(); +} + +WidgetStyle* WidgetTheme::GetStyle(const std::string& widgetClass) +{ + auto it = Styles.find(widgetClass); + return it != Styles.end() ? it->second.get() : nullptr; +} + +void WidgetTheme::SetTheme(std::unique_ptr theme) +{ + CurrentTheme = std::move(theme); +} + +WidgetTheme* WidgetTheme::GetTheme() +{ + return CurrentTheme.get(); +} + +///////////////////////////////////////////////////////////////////////////// + +DarkWidgetTheme::DarkWidgetTheme() +{ + auto widget = RegisterStyle(std::make_unique(), "widget"); + auto textlabel = RegisterStyle(std::make_unique(widget), "textlabel"); + auto pushbutton = RegisterStyle(std::make_unique(widget), "pushbutton"); + auto lineedit = RegisterStyle(std::make_unique(widget), "lineedit"); + auto textedit = RegisterStyle(std::make_unique(widget), "textedit"); + auto listview = RegisterStyle(std::make_unique(widget), "listview"); + auto scrollbar = RegisterStyle(std::make_unique(widget), "scrollbar"); + auto tabbar = RegisterStyle(std::make_unique(widget), "tabbar"); + auto tabbar_tab = RegisterStyle(std::make_unique(widget), "tabbar-tab"); + auto tabwidget_stack = RegisterStyle(std::make_unique(widget), "tabwidget-stack"); + auto checkbox_label = RegisterStyle(std::make_unique(widget), "checkbox-label"); + auto menubaritem = RegisterStyle(std::make_unique(widget), "menubaritem"); + auto menu = RegisterStyle(std::make_unique(widget), "menu"); + auto menuitem = RegisterStyle(std::make_unique(widget), "menuitem"); + + widget->SetString("font-family", "NotoSans"); + widget->SetColor("color", Colorf::fromRgba8(226, 223, 219)); + widget->SetColor("window-background", Colorf::fromRgba8(51, 51, 51)); + widget->SetColor("window-border", Colorf::fromRgba8(51, 51, 51)); + widget->SetColor("window-caption-color", Colorf::fromRgba8(33, 33, 33)); + widget->SetColor("window-caption-text-color", Colorf::fromRgba8(226, 223, 219)); + + pushbutton->SetDouble("noncontent-left", 10.0); + pushbutton->SetDouble("noncontent-top", 5.0); + pushbutton->SetDouble("noncontent-right", 10.0); + pushbutton->SetDouble("noncontent-bottom", 5.0); + pushbutton->SetColor("background-color", Colorf::fromRgba8(68, 68, 68)); + pushbutton->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + pushbutton->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + pushbutton->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + pushbutton->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + pushbutton->SetColor("hover", "background-color", Colorf::fromRgba8(78, 78, 78)); + pushbutton->SetColor("down", "background-color", Colorf::fromRgba8(88, 88, 88)); + + lineedit->SetDouble("noncontent-left", 5.0); + lineedit->SetDouble("noncontent-top", 3.0); + lineedit->SetDouble("noncontent-right", 5.0); + lineedit->SetDouble("noncontent-bottom", 3.0); + lineedit->SetColor("background-color", Colorf::fromRgba8(38, 38, 38)); + lineedit->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("selection-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("no-focus-selection-color", Colorf::fromRgba8(68, 68, 68)); + + textedit->SetDouble("noncontent-left", 8.0); + textedit->SetDouble("noncontent-top", 8.0); + textedit->SetDouble("noncontent-right", 8.0); + textedit->SetDouble("noncontent-bottom", 8.0); + textedit->SetColor("background-color", Colorf::fromRgba8(38, 38, 38)); + textedit->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + textedit->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + textedit->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + textedit->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + + listview->SetDouble("noncontent-left", 10.0); + listview->SetDouble("noncontent-top", 10.0); + listview->SetDouble("noncontent-right", 3.0); + listview->SetDouble("noncontent-bottom", 10.0); + listview->SetColor("background-color", Colorf::fromRgba8(38, 38, 38)); + listview->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + listview->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + listview->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + listview->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + listview->SetColor("selection-color", Colorf::fromRgba8(100, 100, 100)); + + scrollbar->SetColor("track-color", Colorf::fromRgba8(33, 33, 33)); + scrollbar->SetColor("thumb-color", Colorf::fromRgba8(58, 58, 58)); + + tabbar->SetDouble("noncontent-left", 20.0); + tabbar->SetDouble("noncontent-right", 20.0); + tabbar->SetColor("background-color", Colorf::fromRgba8(38, 38, 38)); + + tabbar_tab->SetDouble("noncontent-left", 15.0); + tabbar_tab->SetDouble("noncontent-right", 15.0); + tabbar_tab->SetColor("hover", "background-color", Colorf::fromRgba8(45, 45, 45)); + tabbar_tab->SetColor("active", "background-color", Colorf::fromRgba8(51, 51, 51)); + + tabwidget_stack->SetDouble("noncontent-left", 20.0); + tabwidget_stack->SetDouble("noncontent-top", 5.0); + tabwidget_stack->SetDouble("noncontent-right", 20.0); + tabwidget_stack->SetDouble("noncontent-bottom", 5.0); + + checkbox_label->SetColor("checked-outer-border-color", Colorf::fromRgba8(100, 100, 100)); + checkbox_label->SetColor("checked-inner-border-color", Colorf::fromRgba8(51, 51, 51)); + checkbox_label->SetColor("checked-color", Colorf::fromRgba8(226, 223, 219)); + checkbox_label->SetColor("unchecked-outer-border-color", Colorf::fromRgba8(99, 99, 99)); + checkbox_label->SetColor("unchecked-inner-border-color", Colorf::fromRgba8(51, 51, 51)); + + menubaritem->SetColor("hover", "background-color", Colorf::fromRgba8(78, 78, 78)); + menubaritem->SetColor("down", "background-color", Colorf::fromRgba8(88, 88, 88)); + + menu->SetDouble("noncontent-left", 5.0); + menu->SetDouble("noncontent-top", 5.0); + menu->SetDouble("noncontent-right", 5.0); + menu->SetDouble("noncontent-bottom", 5.0); + menu->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + menu->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + menu->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + menu->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + + menuitem->SetColor("hover", "background-color", Colorf::fromRgba8(78, 78, 78)); + menuitem->SetColor("down", "background-color", Colorf::fromRgba8(88, 88, 88)); +} + +///////////////////////////////////////////////////////////////////////////// + +LightWidgetTheme::LightWidgetTheme() +{ + auto widget = RegisterStyle(std::make_unique(), "widget"); + auto textlabel = RegisterStyle(std::make_unique(widget), "textlabel"); + auto pushbutton = RegisterStyle(std::make_unique(widget), "pushbutton"); + auto lineedit = RegisterStyle(std::make_unique(widget), "lineedit"); + auto textedit = RegisterStyle(std::make_unique(widget), "textedit"); + auto listview = RegisterStyle(std::make_unique(widget), "listview"); + auto scrollbar = RegisterStyle(std::make_unique(widget), "scrollbar"); + auto tabbar = RegisterStyle(std::make_unique(widget), "tabbar"); + auto tabbar_tab = RegisterStyle(std::make_unique(widget), "tabbar-tab"); + auto tabwidget_stack = RegisterStyle(std::make_unique(widget), "tabwidget-stack"); + auto checkbox_label = RegisterStyle(std::make_unique(widget), "checkbox-label"); + auto menubaritem = RegisterStyle(std::make_unique(widget), "menubaritem"); + auto menu = RegisterStyle(std::make_unique(widget), "menu"); + auto menuitem = RegisterStyle(std::make_unique(widget), "menuitem"); + + widget->SetString("font-family", "NotoSans"); + widget->SetColor("color", Colorf::fromRgba8(0, 0, 0)); + widget->SetColor("window-background", Colorf::fromRgba8(240, 240, 240)); + widget->SetColor("window-border", Colorf::fromRgba8(100, 100, 100)); + widget->SetColor("window-caption-color", Colorf::fromRgba8(70, 70, 70)); + widget->SetColor("window-caption-text-color", Colorf::fromRgba8(226, 223, 219)); + + pushbutton->SetDouble("noncontent-left", 10.0); + pushbutton->SetDouble("noncontent-top", 5.0); + pushbutton->SetDouble("noncontent-right", 10.0); + pushbutton->SetDouble("noncontent-bottom", 5.0); + pushbutton->SetColor("background-color", Colorf::fromRgba8(210, 210, 210)); + pushbutton->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + pushbutton->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + pushbutton->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + pushbutton->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + pushbutton->SetColor("hover", "background-color", Colorf::fromRgba8(200, 200, 200)); + pushbutton->SetColor("down", "background-color", Colorf::fromRgba8(190, 190, 190)); + + lineedit->SetDouble("noncontent-left", 5.0); + lineedit->SetDouble("noncontent-top", 3.0); + lineedit->SetDouble("noncontent-right", 5.0); + lineedit->SetDouble("noncontent-bottom", 3.0); + lineedit->SetColor("background-color", Colorf::fromRgba8(255, 255, 255)); + lineedit->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + lineedit->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + lineedit->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + lineedit->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + lineedit->SetColor("selection-color", Colorf::fromRgba8(210, 210, 255)); + lineedit->SetColor("no-focus-selection-color", Colorf::fromRgba8(240, 240, 255)); + + textedit->SetDouble("noncontent-left", 8.0); + textedit->SetDouble("noncontent-top", 8.0); + textedit->SetDouble("noncontent-right", 8.0); + textedit->SetDouble("noncontent-bottom", 8.0); + textedit->SetColor("background-color", Colorf::fromRgba8(255, 255, 255)); + textedit->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + textedit->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + textedit->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + textedit->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + + listview->SetDouble("noncontent-left", 10.0); + listview->SetDouble("noncontent-top", 10.0); + listview->SetDouble("noncontent-right", 3.0); + listview->SetDouble("noncontent-bottom", 10.0); + listview->SetColor("background-color", Colorf::fromRgba8(230, 230, 230)); + listview->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + listview->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + listview->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + listview->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + listview->SetColor("selection-color", Colorf::fromRgba8(200, 200, 200)); + + scrollbar->SetColor("track-color", Colorf::fromRgba8(210, 210, 220)); + scrollbar->SetColor("thumb-color", Colorf::fromRgba8(180, 180, 180)); + + tabbar->SetDouble("noncontent-left", 20.0); + tabbar->SetDouble("noncontent-right", 20.0); + tabbar->SetColor("background-color", Colorf::fromRgba8(220, 220, 220)); + + tabbar_tab->SetDouble("noncontent-left", 15.0); + tabbar_tab->SetDouble("noncontent-right", 15.0); + tabbar_tab->SetColor("hover", "background-color", Colorf::fromRgba8(210, 210, 210)); + tabbar_tab->SetColor("active", "background-color", Colorf::fromRgba8(240, 240, 240)); + + tabwidget_stack->SetDouble("noncontent-left", 20.0); + tabwidget_stack->SetDouble("noncontent-top", 5.0); + tabwidget_stack->SetDouble("noncontent-right", 20.0); + tabwidget_stack->SetDouble("noncontent-bottom", 5.0); + + checkbox_label->SetColor("checked-outer-border-color", Colorf::fromRgba8(155, 155, 155)); + checkbox_label->SetColor("checked-inner-border-color", Colorf::fromRgba8(200, 200, 200)); + checkbox_label->SetColor("checked-color", Colorf::fromRgba8(50, 50, 50)); + checkbox_label->SetColor("unchecked-outer-border-color", Colorf::fromRgba8(156, 156, 156)); + checkbox_label->SetColor("unchecked-inner-border-color", Colorf::fromRgba8(200, 200, 200)); + + menubaritem->SetColor("hover", "background-color", Colorf::fromRgba8(200, 200, 200)); + menubaritem->SetColor("down", "background-color", Colorf::fromRgba8(190, 190, 190)); + + menu->SetDouble("noncontent-left", 5.0); + menu->SetDouble("noncontent-top", 5.0); + menu->SetDouble("noncontent-right", 5.0); + menu->SetDouble("noncontent-bottom", 5.0); + menu->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + menu->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + menu->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + menu->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + + menuitem->SetColor("hover", "background-color", Colorf::fromRgba8(200, 200, 200)); + menuitem->SetColor("down", "background-color", Colorf::fromRgba8(190, 190, 190)); +} diff --git a/libraries/ZWidget/src/core/timer.cpp b/libraries/ZWidget/src/core/timer.cpp new file mode 100644 index 0000000000..5ebe2612fc --- /dev/null +++ b/libraries/ZWidget/src/core/timer.cpp @@ -0,0 +1,45 @@ + +#include "core/timer.h" +#include "core/widget.h" +#include "window/window.h" + +Timer::Timer(Widget* owner) : OwnerObj(owner) +{ + PrevTimerObj = owner->FirstTimerObj; + if (PrevTimerObj) + PrevTimerObj->PrevTimerObj = this; + owner->FirstTimerObj = this; +} + +Timer::~Timer() +{ + Stop(); + + if (PrevTimerObj) + PrevTimerObj->NextTimerObj = NextTimerObj; + if (NextTimerObj) + NextTimerObj->PrevTimerObj = PrevTimerObj; + if (OwnerObj->FirstTimerObj == this) + OwnerObj->FirstTimerObj = NextTimerObj; +} + +void Timer::Start(int timeoutMilliseconds, bool repeat) +{ + Stop(); + + TimerId = DisplayWindow::StartTimer(timeoutMilliseconds, [=]() { + if (!repeat) + Stop(); + if (FuncExpired) + FuncExpired(); + }); +} + +void Timer::Stop() +{ + if (TimerId != 0) + { + DisplayWindow::StopTimer(TimerId); + TimerId = 0; + } +} diff --git a/libraries/ZWidget/src/core/truetypefont.cpp b/libraries/ZWidget/src/core/truetypefont.cpp new file mode 100644 index 0000000000..ccc65a26c5 --- /dev/null +++ b/libraries/ZWidget/src/core/truetypefont.cpp @@ -0,0 +1,1201 @@ + +// #define DUMP_GLYPH + +#include "core/truetypefont.h" +#include "core/pathfill.h" +#include +#include +#include + +#ifdef DUMP_GLYPH +#include +#endif + +TrueTypeFont::TrueTypeFont(std::shared_ptr initdata, int ttcFontIndex) : data(std::move(initdata)) +{ + if (data->size() > 0x7fffffff) + throw std::runtime_error("TTF file is larger than 2 gigabytes!"); + + TrueTypeFileReader reader(data->data(), data->size()); + ttf_Tag versionTag = reader.ReadTag(); + reader.Seek(0); + + if (memcmp(versionTag.data(), "ttcf", 4) == 0) // TTC header + { + ttcHeader.Load(reader); + if (ttcFontIndex >= ttcHeader.numFonts) + throw std::runtime_error("TTC font index out of bounds"); + reader.Seek(ttcHeader.tableDirectoryOffsets[ttcFontIndex]); + } + + directory.Load(reader); + + if (!directory.ContainsTTFOutlines()) + throw std::runtime_error("Only truetype outline fonts are supported"); + + // Load required tables: + + reader = directory.GetReader(data->data(), data->size(), "head"); + head.Load(reader); + + reader = directory.GetReader(data->data(), data->size(), "hhea"); + hhea.Load(reader); + + reader = directory.GetReader(data->data(), data->size(), "maxp"); + maxp.Load(reader); + + reader = directory.GetReader(data->data(), data->size(), "hmtx"); + hmtx.Load(hhea, maxp, reader); + + reader = directory.GetReader(data->data(), data->size(), "name"); + name.Load(reader); + + reader = directory.GetReader(data->data(), data->size(), "OS/2"); + os2.Load(reader); + + reader = directory.GetReader(data->data(), data->size(), "cmap"); + cmap.Load(reader); + + LoadCharacterMapEncoding(reader); + + // Load TTF Outlines: + + reader = directory.GetReader(data->data(), data->size(), "loca"); + loca.Load(head, maxp, reader); + + glyf = directory.GetRecord("glyf"); + +#ifdef DUMP_GLYPH + LoadGlyph(GetGlyphIndex('6'), 13.0); +#endif +} + +TrueTypeTextMetrics TrueTypeFont::GetTextMetrics(double height) const +{ + double scale = height / head.unitsPerEm; + + TrueTypeTextMetrics metrics; + metrics.ascender = os2.sTypoAscender * scale; + metrics.descender = os2.sTypoDescender * scale; + metrics.lineGap = os2.sTypoLineGap * scale; + return metrics; +} + +TrueTypeGlyph TrueTypeFont::LoadGlyph(uint32_t glyphIndex, double height) const +{ + double scale = height / head.unitsPerEm; + double scaleX = 3.0f; + double scaleY = -1.0f; + + ttf_uint16 advanceWidth = 0; + ttf_int16 lsb = 0; + if (glyphIndex >= hhea.numberOfHMetrics) + { + advanceWidth = hmtx.hMetrics[hhea.numberOfHMetrics - 1].advanceWidth; + lsb = hmtx.leftSideBearings[glyphIndex - hhea.numberOfHMetrics]; + } + else + { + advanceWidth = hmtx.hMetrics[glyphIndex].advanceWidth; + lsb = hmtx.hMetrics[glyphIndex].lsb; + } + + // Glyph is missing if the offset is the same as the next glyph (0 bytes glyph length) + bool missing = glyphIndex + 1 < loca.offsets.size() ? loca.offsets[glyphIndex] == loca.offsets[glyphIndex + 1] : false; + if (missing) + { + TrueTypeGlyph glyph; + + // TBD: gridfit or not? + glyph.advanceWidth = (int)std::round(advanceWidth * scale * scaleX); + glyph.leftSideBearing = (int)std::round(lsb * scale * scaleX); + glyph.yOffset = 0; + + return glyph; + } + + TTF_SimpleGlyph g; + LoadGlyph(g, glyphIndex); + + // Create glyph path: + PathFillDesc path; + path.fill_mode = PathFillMode::winding; + + int startPoint = 0; + int numberOfContours = g.endPtsOfContours.size(); + for (int i = 0; i < numberOfContours; i++) + { + int endPoint = g.endPtsOfContours[i]; + if (endPoint < startPoint) + throw std::runtime_error("Invalid glyph"); + + bool prevIsControlPoint; + bool isControlPoint = !(g.flags[endPoint] & TTF_ON_CURVE_POINT); + bool nextIsControlPoint = !(g.flags[startPoint] & TTF_ON_CURVE_POINT); + if (isControlPoint) + { + Point nextpoint(g.points[startPoint].x, g.points[startPoint].y); + if (nextIsControlPoint) + { + Point curpoint(g.points[endPoint].x, g.points[endPoint].y); + Point midpoint = (curpoint + nextpoint) / 2; + path.MoveTo(midpoint * scale); + prevIsControlPoint = isControlPoint; + } + else + { + path.MoveTo(Point(g.points[startPoint].x, g.points[startPoint].y) * scale); + prevIsControlPoint = false; + } + } + else + { + path.MoveTo(Point(g.points[endPoint].x, g.points[endPoint].y) * scale); + prevIsControlPoint = isControlPoint; + } + + int pos = startPoint; + while (pos <= endPoint) + { + int nextpos = pos + 1 <= endPoint ? pos + 1 : startPoint; + bool isControlPoint = !(g.flags[pos] & TTF_ON_CURVE_POINT); + bool nextIsControlPoint = !(g.flags[nextpos] & TTF_ON_CURVE_POINT); + Point curpoint(g.points[pos].x, g.points[pos].y); + if (isControlPoint) + { + Point nextpoint(g.points[nextpos].x, g.points[nextpos].y); + if (nextIsControlPoint) + { + Point midpoint = (curpoint + nextpoint) / 2; + path.BezierTo(curpoint * scale, midpoint * scale); + prevIsControlPoint = isControlPoint; + pos++; + } + else + { + path.BezierTo(curpoint * scale, nextpoint * scale); + prevIsControlPoint = false; + pos += 2; + } + } + else + { + if (!prevIsControlPoint) + path.LineTo(curpoint * scale); + prevIsControlPoint = isControlPoint; + pos++; + } + } + path.Close(); + + startPoint = endPoint + 1; + } + + // Transform and find the final bounding box + Point bboxMin, bboxMax; + if (!path.subpaths.front().points.empty()) + { + bboxMin = path.subpaths.front().points.front(); + bboxMax = path.subpaths.front().points.front(); + bboxMin.x *= scaleX; + bboxMin.y *= scaleY; + bboxMax.x *= scaleX; + bboxMax.y *= scaleY; + for (auto& subpath : path.subpaths) + { + for (auto& point : subpath.points) + { + point.x *= scaleX; + point.y *= scaleY; + bboxMin.x = std::min(bboxMin.x, point.x); + bboxMin.y = std::min(bboxMin.y, point.y); + bboxMax.x = std::max(bboxMax.x, point.x); + bboxMax.y = std::max(bboxMax.y, point.y); + } + } + } + + bboxMin.x = std::floor(bboxMin.x); + bboxMin.y = std::floor(bboxMin.y); + + // Reposition glyph to bitmap so it begins at (0,0) for our bitmap + for (auto& subpath : path.subpaths) + { + for (auto& point : subpath.points) + { + point.x -= bboxMin.x; + point.y -= bboxMin.y; + } + } + +#ifdef DUMP_GLYPH + std::string svgxmlstart = R"( + + + +)"; + + std::ofstream out("c:\\development\\glyph.svg"); + out << svgxmlstart; + + for (auto& subpath : path.subpaths) + { + size_t pos = 0; + out << "M" << subpath.points[pos].x << " " << subpath.points[pos].y << " "; + pos++; + for (PathFillCommand cmd : subpath.commands) + { + int count = 0; + if (cmd == PathFillCommand::line) + { + out << "L"; + count = 1; + } + else if (cmd == PathFillCommand::quadradic) + { + out << "Q"; + count = 2; + } + else if (cmd == PathFillCommand::cubic) + { + out << "C"; + count = 3; + } + + for (int i = 0; i < count; i++) + { + out << subpath.points[pos].x << " " << subpath.points[pos].y << " "; + pos++; + } + } + if (subpath.closed) + out << "Z"; + } + + out << svgxmlend; + out.close(); +#endif + + TrueTypeGlyph glyph; + + // Rasterize the glyph + glyph.width = (int)std::floor(bboxMax.x - bboxMin.x) + 1; + glyph.height = (int)std::floor(bboxMax.y - bboxMin.y) + 1; + glyph.grayscale.reset(new uint8_t[glyph.width * glyph.height]); + uint8_t* grayscale = glyph.grayscale.get(); + path.Rasterize(grayscale, glyph.width, glyph.height); + + // TBD: gridfit or not? + glyph.advanceWidth = (int)std::round(advanceWidth * scale * scaleX); + glyph.leftSideBearing = (int)std::round(bboxMin.x); + glyph.yOffset = (int)std::round(bboxMin.y); + + return glyph; +} + +void TrueTypeFont::LoadGlyph(TTF_SimpleGlyph& g, uint32_t glyphIndex, int compositeDepth) const +{ + if (glyphIndex >= loca.offsets.size()) + throw std::runtime_error("Glyph index out of bounds"); + + TrueTypeFileReader reader = glyf.GetReader(data->data(), data->size()); + reader.Seek(loca.offsets[glyphIndex]); + + ttf_int16 numberOfContours = reader.ReadInt16(); + ttf_int16 xMin = reader.ReadInt16(); + ttf_int16 yMin = reader.ReadInt16(); + ttf_int16 xMax = reader.ReadInt16(); + ttf_int16 yMax = reader.ReadInt16(); + + if (numberOfContours > 0) // Simple glyph + { + int pointsOffset = g.points.size(); + for (ttf_uint16 i = 0; i < numberOfContours; i++) + g.endPtsOfContours.push_back(pointsOffset + reader.ReadUInt16()); + + ttf_uint16 instructionLength = reader.ReadUInt16(); + std::vector instructions; + instructions.resize(instructionLength); + reader.Read(instructions.data(), instructions.size()); + + int numPoints = (int)g.endPtsOfContours.back() - pointsOffset + 1; + g.points.resize(pointsOffset + numPoints); + + while (g.flags.size() < g.points.size()) + { + ttf_uint8 flag = reader.ReadUInt8(); + if (flag & TTF_REPEAT_FLAG) + { + ttf_uint8 repeatcount = reader.ReadUInt8(); + for (ttf_uint8 i = 0; i < repeatcount; i++) + g.flags.push_back(flag); + } + g.flags.push_back(flag); + } + + for (int i = pointsOffset; i < pointsOffset + numPoints; i++) + { + if (g.flags[i] & TTF_X_SHORT_VECTOR) + { + ttf_int16 x = reader.ReadUInt8(); + g.points[i].x = (g.flags[i] & TTF_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) ? x : -x; + } + else if (g.flags[i] & TTF_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) + { + g.points[i].x = 0; + } + else + { + g.points[i].x = reader.ReadInt16(); + } + } + + for (int i = pointsOffset; i < pointsOffset + numPoints; i++) + { + if (g.flags[i] & TTF_Y_SHORT_VECTOR) + { + ttf_int16 y = reader.ReadUInt8(); + g.points[i].y = (g.flags[i] & TTF_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) ? y : -y; + } + else if (g.flags[i] & TTF_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) + { + g.points[i].y = 0; + } + else + { + g.points[i].y = reader.ReadInt16(); + } + } + + // Convert from relative coordinates to absolute + for (int i = pointsOffset + 1; i < pointsOffset + numPoints; i++) + { + g.points[i].x += g.points[i - 1].x; + g.points[i].y += g.points[i - 1].y; + } + } + else if (numberOfContours < 0) // Composite glyph + { + if (compositeDepth == 8) + throw std::runtime_error("Composite glyph recursion exceeded"); + + int parentPointsOffset = g.points.size(); + + bool weHaveInstructions = false; + while (true) + { + ttf_uint16 flags = reader.ReadUInt16(); + ttf_uint16 childGlyphIndex = reader.ReadUInt16(); + + int argument1, argument2; + if (flags & TTF_ARG_1_AND_2_ARE_WORDS) + { + if (flags & TTF_ARGS_ARE_XY_VALUES) + { + argument1 = reader.ReadInt16(); + argument2 = reader.ReadInt16(); + } + else + { + argument1 = reader.ReadUInt16(); + argument2 = reader.ReadUInt16(); + } + } + else + { + if (flags & TTF_ARGS_ARE_XY_VALUES) + { + argument1 = reader.ReadInt8(); + argument2 = reader.ReadInt8(); + } + else + { + argument1 = reader.ReadUInt8(); + argument2 = reader.ReadUInt8(); + } + } + + float mat2x2[4]; + bool transform = true; + if (flags & TTF_WE_HAVE_A_SCALE) + { + ttf_F2DOT14 scale = F2DOT14_ToFloat(reader.ReadF2DOT14()); + mat2x2[0] = scale; + mat2x2[1] = 0; + mat2x2[2] = 0; + mat2x2[3] = scale; + } + else if (flags & TTF_WE_HAVE_AN_X_AND_Y_SCALE) + { + mat2x2[0] = F2DOT14_ToFloat(reader.ReadF2DOT14()); + mat2x2[1] = 0; + mat2x2[2] = 0; + mat2x2[3] = F2DOT14_ToFloat(reader.ReadF2DOT14()); + } + else if (flags & TTF_WE_HAVE_A_TWO_BY_TWO) + { + mat2x2[0] = F2DOT14_ToFloat(reader.ReadF2DOT14()); + mat2x2[1] = F2DOT14_ToFloat(reader.ReadF2DOT14()); + mat2x2[2] = F2DOT14_ToFloat(reader.ReadF2DOT14()); + mat2x2[3] = F2DOT14_ToFloat(reader.ReadF2DOT14()); + } + else + { + transform = false; + } + + int childPointsOffset = g.points.size(); + LoadGlyph(g, childGlyphIndex, compositeDepth + 1); + + if (transform) + { + for (int i = childPointsOffset; i < g.points.size(); i++) + { + float x = g.points[i].x * mat2x2[0] + g.points[i].y * mat2x2[1]; + float y = g.points[i].x * mat2x2[2] + g.points[i].y * mat2x2[3]; + g.points[i].x = x; + g.points[i].y = y; + } + } + + float dx, dy; + + if (flags & TTF_ARGS_ARE_XY_VALUES) + { + dx = argument1; + dy = argument2; + + // Spec states we must fall back to TTF_UNSCALED_COMPONENT_OFFSET if both flags are set + if ((flags & (TTF_SCALED_COMPONENT_OFFSET | TTF_UNSCALED_COMPONENT_OFFSET)) == TTF_SCALED_COMPONENT_OFFSET) + { + float x = dx * mat2x2[0] + dy * mat2x2[1]; + float y = dx * mat2x2[2] + dy * mat2x2[3]; + dx = x; + dy = y; + } + + if (flags & TTF_ROUND_XY_TO_GRID) + { + // To do: round the offset to the pixel grid + } + } + else + { + int parentPointIndex = parentPointsOffset + argument1; + int childPointIndex = childPointsOffset + argument2; + + if ((size_t)parentPointIndex >= g.points.size() || (size_t)childPointIndex >= g.points.size()) + throw std::runtime_error("Invalid glyph offset"); + + dx = g.points[parentPointIndex].x - g.points[childPointIndex].x; + dy = g.points[parentPointIndex].y - g.points[childPointIndex].y; + } + + for (int i = childPointsOffset; i < g.points.size(); i++) + { + g.points[i].x += dx; + g.points[i].y += dy; + } + + if (flags & TTF_USE_MY_METRICS) + { + // To do: this affects lsb + rsb calculations somehow + } + + if (flags & TTF_WE_HAVE_INSTRUCTIONS) + { + weHaveInstructions = true; + } + + if (!(flags & TTF_MORE_COMPONENTS)) + break; + } + + if (weHaveInstructions) + { + ttf_uint16 instructionLength = reader.ReadUInt16(); + std::vector instructions; + instructions.resize(instructionLength); + reader.Read(instructions.data(), instructions.size()); + } + } +} + +float TrueTypeFont::F2DOT14_ToFloat(ttf_F2DOT14 v) +{ + int a = ((ttf_int16)v) >> 14; + int b = (v & 0x3fff); + return a + b / (float)0x4000; +} + +uint32_t TrueTypeFont::GetGlyphIndex(uint32_t c) const +{ + auto it = std::lower_bound(Ranges.begin(), Ranges.end(), c, [](const TTF_GlyphRange& range, uint32_t c) { return range.endCharCode < c; }); + if (it != Ranges.end() && c >= it->startCharCode && c <= it->endCharCode) + { + return it->startGlyphID + (c - it->startCharCode); + } + + it = std::lower_bound(ManyToOneRanges.begin(), ManyToOneRanges.end(), c, [](const TTF_GlyphRange& range, uint32_t c) { return range.endCharCode < c; }); + if (it != ManyToOneRanges.end() && c >= it->startCharCode && c <= it->endCharCode) + { + return it->startGlyphID; + } + return 0; +} + +void TrueTypeFont::LoadCharacterMapEncoding(TrueTypeFileReader& reader) +{ + // Look for the best encoding available that we support + + TTF_EncodingRecord record; + if (!record.subtableOffset) record = cmap.GetEncoding(3, 12); + if (!record.subtableOffset) record = cmap.GetEncoding(0, 4); + if (!record.subtableOffset) record = cmap.GetEncoding(3, 1); + if (!record.subtableOffset) record = cmap.GetEncoding(0, 3); + if (!record.subtableOffset) + throw std::runtime_error("No supported cmap encoding found in truetype file"); + + reader.Seek(record.subtableOffset); + + ttf_uint16 format = reader.ReadUInt16(); + if (format == 4) + { + TTF_CMapSubtable4 subformat; + subformat.Load(reader); + + for (uint16_t i = 0; i < subformat.segCount; i++) + { + ttf_uint16 startCode = subformat.startCode[i]; + ttf_uint16 endCode = subformat.endCode[i]; + ttf_uint16 idDelta = subformat.idDelta[i]; + ttf_uint16 idRangeOffset = subformat.idRangeOffsets[i]; + if (idRangeOffset == 0) + { + ttf_uint16 glyphId = startCode + idDelta; // Note: relies on modulo 65536 + + TTF_GlyphRange range; + range.startCharCode = startCode; + range.endCharCode = endCode; + range.startGlyphID = glyphId; + Ranges.push_back(range); + } + else if (startCode <= endCode) + { + TTF_GlyphRange range; + range.startCharCode = startCode; + bool firstGlyph = true; + for (ttf_uint16 c = startCode; c <= endCode; c++) + { + int offset = idRangeOffset / 2 + (c - startCode) - ((int)subformat.segCount - i); + if (offset >= 0 && offset < subformat.glyphIdArray.size()) + { + int glyphId = subformat.glyphIdArray[offset]; + if (firstGlyph) + { + range.startGlyphID = glyphId; + firstGlyph = false; + } + else if (range.startGlyphID + (c - range.startCharCode) != glyphId) + { + range.endCharCode = c - 1; + Ranges.push_back(range); + range.startCharCode = c; + range.startGlyphID = glyphId; + } + } + } + if (!firstGlyph) + { + range.endCharCode = endCode; + Ranges.push_back(range); + } + } + } + } + else if (format == 12 || format == 3) + { + TTF_CMapSubtable12 subformat; + subformat.Load(reader); + Ranges = std::move(subformat.groups); + } + else if (format == 13 || format == 3) + { + TTF_CMapSubtable13 subformat; + subformat.Load(reader); + ManyToOneRanges = std::move(subformat.groups); + } +} + +std::vector TrueTypeFont::GetFontNames(const std::shared_ptr& data) +{ + if (data->size() > 0x7fffffff) + throw std::runtime_error("TTF file is larger than 2 gigabytes!"); + + TrueTypeFileReader reader(data->data(), data->size()); + ttf_Tag versionTag = reader.ReadTag(); + reader.Seek(0); + + std::vector names; + if (memcmp(versionTag.data(), "ttcf", 4) == 0) // TTC header + { + TTC_Header ttcHeader; + ttcHeader.Load(reader); + + for (size_t i = 0; i < ttcHeader.tableDirectoryOffsets.size(); i++) + { + reader.Seek(ttcHeader.tableDirectoryOffsets[i]); + + TTF_TableDirectory directory; + directory.Load(reader); + + TTF_NamingTable name; + auto name_reader = directory.GetReader(data->data(), data->size(), "name"); + name.Load(name_reader); + + names.push_back(name.GetFontName()); + } + } + else + { + TTF_TableDirectory directory; + directory.Load(reader); + + TTF_NamingTable name; + auto name_reader = directory.GetReader(data->data(), data->size(), "name"); + name.Load(name_reader); + + names.push_back(name.GetFontName()); + } + return names; +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_CMapSubtable0::Load(TrueTypeFileReader& reader) +{ + length = reader.ReadUInt16(); + language = reader.ReadUInt16(); + glyphIdArray.resize(256); + reader.Read(glyphIdArray.data(), glyphIdArray.size()); +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_CMapSubtable4::Load(TrueTypeFileReader& reader) +{ + length = reader.ReadUInt16(); + language = reader.ReadUInt16(); + + segCount = reader.ReadUInt16() / 2; + ttf_uint16 searchRange = reader.ReadUInt16(); + ttf_uint16 entrySelector = reader.ReadUInt16(); + ttf_uint16 rangeShift = reader.ReadUInt16(); + + endCode.reserve(segCount); + startCode.reserve(segCount); + idDelta.reserve(segCount); + idRangeOffsets.reserve(segCount); + for (ttf_uint16 i = 0; i < segCount; i++) endCode.push_back(reader.ReadUInt16()); + reservedPad = reader.ReadUInt16(); + for (ttf_uint16 i = 0; i < segCount; i++) startCode.push_back(reader.ReadUInt16()); + for (ttf_uint16 i = 0; i < segCount; i++) idDelta.push_back(reader.ReadInt16()); + for (ttf_uint16 i = 0; i < segCount; i++) idRangeOffsets.push_back(reader.ReadUInt16()); + + int glyphIdArraySize = ((int)length - (8 + (int)segCount * 4) * sizeof(ttf_uint16)) / 2; + if (glyphIdArraySize < 0) + throw std::runtime_error("Invalid TTF cmap subtable 4 length"); + glyphIdArray.reserve(glyphIdArraySize); + for (int i = 0; i < glyphIdArraySize; i++) glyphIdArray.push_back(reader.ReadUInt16()); +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_CMapSubtable12::Load(TrueTypeFileReader& reader) +{ + reserved = reader.ReadUInt16(); + length = reader.ReadUInt32(); + language = reader.ReadUInt32(); + numGroups = reader.ReadUInt32(); + for (ttf_uint32 i = 0; i < numGroups; i++) + { + TTF_GlyphRange range; + range.startCharCode = reader.ReadUInt32(); + range.endCharCode = reader.ReadUInt32(); + range.startGlyphID = reader.ReadUInt32(); + groups.push_back(range); + } +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_TableRecord::Load(TrueTypeFileReader& reader) +{ + tableTag = reader.ReadTag(); + checksum = reader.ReadUInt32(); + offset = reader.ReadOffset32(); + length = reader.ReadUInt32(); +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_TableDirectory::Load(TrueTypeFileReader& reader) +{ + sfntVersion = reader.ReadUInt32(); + numTables = reader.ReadUInt16(); + + // opentype spec says we can't use these for security reasons, so we pretend they never was part of the header + ttf_uint16 searchRange = reader.ReadUInt16(); + ttf_uint16 entrySelector = reader.ReadUInt16(); + ttf_uint16 rangeShift = reader.ReadUInt16(); + + for (ttf_uint16 i = 0; i < numTables; i++) + { + TTF_TableRecord record; + record.Load(reader); + tableRecords.push_back(record); + } +} + +///////////////////////////////////////////////////////////////////////////// + +void TTC_Header::Load(TrueTypeFileReader& reader) +{ + ttcTag = reader.ReadTag(); + majorVersion = reader.ReadUInt16(); + minorVersion = reader.ReadUInt16(); + + if (!(majorVersion == 1 && minorVersion == 0) && !(majorVersion == 2 && minorVersion == 0)) + throw std::runtime_error("Unsupported TTC header version"); + + numFonts = reader.ReadUInt32(); + for (ttf_uint16 i = 0; i < numFonts; i++) + { + tableDirectoryOffsets.push_back(reader.ReadOffset32()); + } + + if (majorVersion == 2 && minorVersion == 0) + { + dsigTag = reader.ReadUInt32(); + dsigLength = reader.ReadUInt32(); + dsigOffset = reader.ReadUInt32(); + } +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_CMap::Load(TrueTypeFileReader& reader) +{ + version = reader.ReadUInt16(); + numTables = reader.ReadUInt16(); + + for (ttf_uint16 i = 0; i < numTables; i++) + { + TTF_EncodingRecord record; + record.platformID = reader.ReadUInt16(); + record.encodingID = reader.ReadUInt16(); + record.subtableOffset = reader.ReadOffset32(); + encodingRecords.push_back(record); + } +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_FontHeader::Load(TrueTypeFileReader& reader) +{ + majorVersion = reader.ReadUInt16(); + minorVersion = reader.ReadUInt16(); + fontRevision = reader.ReadFixed(); + checksumAdjustment = reader.ReadUInt32(); + magicNumber = reader.ReadUInt32(); + flags = reader.ReadUInt16(); + unitsPerEm = reader.ReadUInt16(); + created = reader.ReadLONGDATETIME(); + modified = reader.ReadLONGDATETIME(); + xMin = reader.ReadInt16(); + yMin = reader.ReadInt16(); + xMax = reader.ReadInt16(); + yMax = reader.ReadInt16(); + macStyle = reader.ReadUInt16(); + lowestRecPPEM = reader.ReadUInt16(); + fontDirectionHint = reader.ReadInt16(); + indexToLocFormat = reader.ReadInt16(); + glyphDataFormat = reader.ReadInt16(); +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_HorizontalHeader::Load(TrueTypeFileReader& reader) +{ + majorVersion = reader.ReadUInt16(); + minorVersion = reader.ReadUInt16(); + ascender = reader.ReadFWORD(); + descender = reader.ReadFWORD(); + lineGap = reader.ReadFWORD(); + advanceWidthMax = reader.ReadUFWORD(); + minLeftSideBearing = reader.ReadFWORD(); + minRightSideBearing = reader.ReadFWORD(); + xMaxExtent = reader.ReadFWORD(); + caretSlopeRise = reader.ReadInt16(); + caretSlopeRun = reader.ReadInt16(); + caretOffset = reader.ReadInt16(); + reserved0 = reader.ReadInt16(); + reserved1 = reader.ReadInt16(); + reserved2 = reader.ReadInt16(); + reserved3 = reader.ReadInt16(); + metricDataFormat = reader.ReadInt16(); + numberOfHMetrics = reader.ReadUInt16(); +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_HorizontalMetrics::Load(const TTF_HorizontalHeader& hhea, const TTF_MaximumProfile& maxp, TrueTypeFileReader& reader) +{ + for (ttf_uint16 i = 0; i < hhea.numberOfHMetrics; i++) + { + longHorMetric metric; + metric.advanceWidth = reader.ReadUInt16(); + metric.lsb = reader.ReadInt16(); + hMetrics.push_back(metric); + } + + int count = (int)maxp.numGlyphs - (int)hhea.numberOfHMetrics; + if (count < 0) + throw std::runtime_error("Invalid TTF file"); + + for (int i = 0; i < count; i++) + { + leftSideBearings.push_back(reader.ReadInt16()); + } +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_MaximumProfile::Load(TrueTypeFileReader& reader) +{ + version = reader.ReadVersion16Dot16(); + numGlyphs = reader.ReadUInt16(); + + if (version == (1 << 16)) // v1 only + { + maxPoints = reader.ReadUInt16(); + maxContours = reader.ReadUInt16(); + maxCompositePoints = reader.ReadUInt16(); + maxCompositeContours = reader.ReadUInt16(); + maxZones = reader.ReadUInt16(); + maxTwilightPoints = reader.ReadUInt16(); + maxStorage = reader.ReadUInt16(); + maxFunctionDefs = reader.ReadUInt16(); + maxInstructionDefs = reader.ReadUInt16(); + maxStackElements = reader.ReadUInt16(); + maxSizeOfInstructions = reader.ReadUInt16(); + maxComponentElements = reader.ReadUInt16(); + maxComponentDepth = reader.ReadUInt16(); + } +} + +///////////////////////////////////////////////////////////////////////////// + +static std::string unicode_to_utf8(unsigned int value) +{ + char text[8]; + + if ((value < 0x80) && (value > 0)) + { + text[0] = (char)value; + text[1] = 0; + } + else if (value < 0x800) + { + text[0] = (char)(0xc0 | (value >> 6)); + text[1] = (char)(0x80 | (value & 0x3f)); + text[2] = 0; + } + else if (value < 0x10000) + { + text[0] = (char)(0xe0 | (value >> 12)); + text[1] = (char)(0x80 | ((value >> 6) & 0x3f)); + text[2] = (char)(0x80 | (value & 0x3f)); + text[3] = 0; + } + else if (value < 0x200000) + { + text[0] = (char)(0xf0 | (value >> 18)); + text[1] = (char)(0x80 | ((value >> 12) & 0x3f)); + text[2] = (char)(0x80 | ((value >> 6) & 0x3f)); + text[3] = (char)(0x80 | (value & 0x3f)); + text[4] = 0; + } + else if (value < 0x4000000) + { + text[0] = (char)(0xf8 | (value >> 24)); + text[1] = (char)(0x80 | ((value >> 18) & 0x3f)); + text[2] = (char)(0x80 | ((value >> 12) & 0x3f)); + text[3] = (char)(0x80 | ((value >> 6) & 0x3f)); + text[4] = (char)(0x80 | (value & 0x3f)); + text[5] = 0; + } + else if (value < 0x80000000) + { + text[0] = (char)(0xfc | (value >> 30)); + text[1] = (char)(0x80 | ((value >> 24) & 0x3f)); + text[2] = (char)(0x80 | ((value >> 18) & 0x3f)); + text[3] = (char)(0x80 | ((value >> 12) & 0x3f)); + text[4] = (char)(0x80 | ((value >> 6) & 0x3f)); + text[5] = (char)(0x80 | (value & 0x3f)); + text[6] = 0; + } + else + { + text[0] = 0; // Invalid wchar value + } + return text; +} + +void TTF_NamingTable::Load(TrueTypeFileReader& reader) +{ + version = reader.ReadUInt16(); + count = reader.ReadUInt16(); + storageOffset = reader.ReadOffset16(); + for (ttf_uint16 i = 0; i < count; i++) + { + NameRecord record; + record.platformID = reader.ReadUInt16(); + record.encodingID = reader.ReadUInt16(); + record.languageID = reader.ReadUInt16(); + record.nameID = reader.ReadUInt16(); + record.length = reader.ReadUInt16(); + record.stringOffset = reader.ReadOffset16(); + nameRecord.push_back(record); + } + + if (version == 1) + { + langTagCount = reader.ReadUInt16(); + for (ttf_uint16 i = 0; i < langTagCount; i++) + { + LangTagRecord record; + ttf_uint16 length; + ttf_Offset16 langTagOffset; + langTagRecord.push_back(record); + } + } + + for (NameRecord& record : nameRecord) + { + if (record.length > 0 && record.platformID == 3 && record.encodingID == 1) + { + reader.Seek(storageOffset + record.stringOffset); + ttf_uint16 ucs2len = record.length / 2; + for (ttf_uint16 i = 0; i < ucs2len; i++) + { + record.text += unicode_to_utf8(reader.ReadUInt16()); + } + } + } +} + +TTCFontName TTF_NamingTable::GetFontName() const +{ + TTCFontName fname; + for (const auto& record : nameRecord) + { + if (record.nameID == 1) fname.FamilyName = record.text; + if (record.nameID == 2) fname.SubfamilyName = record.text; + if (record.nameID == 3) fname.UniqueID = record.text; + if (record.nameID == 4) fname.FullName = record.text; + if (record.nameID == 5) fname.VersionString = record.text; + if (record.nameID == 6) fname.PostscriptName = record.text; + } + return fname; +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_OS2Windows::Load(TrueTypeFileReader& reader) +{ + version = reader.ReadUInt16(); + xAvgCharWidth = reader.ReadInt16(); + usWeightClass = reader.ReadUInt16(); + usWidthClass = reader.ReadUInt16(); + fsType = reader.ReadUInt16(); + ySubscriptXSize = reader.ReadInt16(); + ySubscriptYSize = reader.ReadInt16(); + ySubscriptXOffset = reader.ReadInt16(); + ySubscriptYOffset = reader.ReadInt16(); + ySuperscriptXSize = reader.ReadInt16(); + ySuperscriptYSize = reader.ReadInt16(); + ySuperscriptXOffset = reader.ReadInt16(); + ySuperscriptYOffset = reader.ReadInt16(); + yStrikeoutSize = reader.ReadInt16(); + yStrikeoutPosition = reader.ReadInt16(); + sFamilyClass = reader.ReadInt16(); + for (int i = 0; i < 10; i++) + { + panose[i] = reader.ReadUInt8(); + } + ulUnicodeRange1 = reader.ReadUInt32(); + ulUnicodeRange2 = reader.ReadUInt32(); + ulUnicodeRange3 = reader.ReadUInt32(); + ulUnicodeRange4 = reader.ReadUInt32(); + achVendID = reader.ReadTag(); + fsSelection = reader.ReadUInt16(); + usFirstCharIndex = reader.ReadUInt16(); + usLastCharIndex = reader.ReadUInt16(); + sTypoAscender = reader.ReadInt16(); + sTypoDescender = reader.ReadInt16(); + sTypoLineGap = reader.ReadInt16(); + if (!reader.IsEndOfData()) // may be missing in v0 due to a bug in Apple's TTF documentation + { + usWinAscent = reader.ReadUInt16(); + usWinDescent = reader.ReadUInt16(); + } + if (version >= 1) + { + ulCodePageRange1 = reader.ReadUInt32(); + ulCodePageRange2 = reader.ReadUInt32(); + } + if (version >= 2) + { + sxHeight = reader.ReadInt16(); + sCapHeight = reader.ReadInt16(); + usDefaultChar = reader.ReadUInt16(); + usBreakChar = reader.ReadUInt16(); + usMaxContext = reader.ReadUInt16(); + } + if (version >= 5) + { + usLowerOpticalPointSize = reader.ReadUInt16(); + usUpperOpticalPointSize = reader.ReadUInt16(); + } +} + +///////////////////////////////////////////////////////////////////////////// + +void TTF_IndexToLocation::Load(const TTF_FontHeader& head, const TTF_MaximumProfile& maxp, TrueTypeFileReader& reader) +{ + int count = (int)maxp.numGlyphs + 1; + if (head.indexToLocFormat == 0) + { + offsets.reserve(count); + for (int i = 0; i < count; i++) + { + offsets.push_back((ttf_Offset32)reader.ReadOffset16() * 2); + } + } + else + { + offsets.reserve(count); + for (int i = 0; i < count; i++) + { + offsets.push_back(reader.ReadOffset32()); + } + } +} + +///////////////////////////////////////////////////////////////////////////// + +ttf_uint8 TrueTypeFileReader::ReadUInt8() +{ + ttf_uint8 v; Read(&v, 1); return v; +} + +ttf_uint16 TrueTypeFileReader::ReadUInt16() +{ + ttf_uint8 v[2]; Read(v, 2); return (((ttf_uint16)v[0]) << 8) | (ttf_uint16)v[1]; +} + +ttf_uint24 TrueTypeFileReader::ReadUInt24() +{ + ttf_uint8 v[3]; Read(v, 3); return (((ttf_uint32)v[0]) << 16) | (((ttf_uint32)v[1]) << 8) | (ttf_uint32)v[2]; +} + +ttf_uint32 TrueTypeFileReader::ReadUInt32() +{ + ttf_uint8 v[4]; Read(v, 4); return (((ttf_uint32)v[0]) << 24) | (((ttf_uint32)v[1]) << 16) | (((ttf_uint32)v[2]) << 8) | (ttf_uint32)v[3]; +} + +ttf_int8 TrueTypeFileReader::ReadInt8() +{ + return ReadUInt8(); +} + +ttf_int16 TrueTypeFileReader::ReadInt16() +{ + return ReadUInt16(); +} + +ttf_int32 TrueTypeFileReader::ReadInt32() +{ + return ReadUInt32(); +} + +ttf_Fixed TrueTypeFileReader::ReadFixed() +{ + return ReadUInt32(); +} + +ttf_UFWORD TrueTypeFileReader::ReadUFWORD() +{ + return ReadUInt16(); +} + +ttf_FWORD TrueTypeFileReader::ReadFWORD() +{ + return ReadUInt16(); +} + +ttf_F2DOT14 TrueTypeFileReader::ReadF2DOT14() +{ + return ReadUInt16(); +} + +ttf_LONGDATETIME TrueTypeFileReader::ReadLONGDATETIME() +{ + ttf_uint8 v[8]; Read(v, 8); + return + (((ttf_LONGDATETIME)v[0]) << 56) | (((ttf_LONGDATETIME)v[1]) << 48) | (((ttf_LONGDATETIME)v[2]) << 40) | (((ttf_LONGDATETIME)v[3]) << 32) | + (((ttf_LONGDATETIME)v[4]) << 24) | (((ttf_LONGDATETIME)v[5]) << 16) | (((ttf_LONGDATETIME)v[6]) << 8) | (ttf_LONGDATETIME)v[7]; +} + +ttf_Tag TrueTypeFileReader::ReadTag() +{ + ttf_Tag v; Read(v.data(), v.size()); return v; +} + +ttf_Offset16 TrueTypeFileReader::ReadOffset16() +{ + return ReadUInt16(); +} + +ttf_Offset24 TrueTypeFileReader::ReadOffset24() +{ + return ReadUInt24(); +} + +ttf_Offset32 TrueTypeFileReader::ReadOffset32() +{ + return ReadUInt32(); +} + +ttf_Version16Dot16 TrueTypeFileReader::ReadVersion16Dot16() +{ + return ReadUInt32(); +} + +void TrueTypeFileReader::Seek(size_t newpos) +{ + if (newpos > size) + throw std::runtime_error("Invalid TTF file"); + + pos = newpos; +} + +void TrueTypeFileReader::Read(void* output, size_t count) +{ + if (pos + count > size) + throw std::runtime_error("Unexpected end of TTF file"); + memcpy(output, data + pos, count); + pos += count; +} diff --git a/libraries/ZWidget/src/core/truetypefont.h b/libraries/ZWidget/src/core/truetypefont.h new file mode 100644 index 0000000000..53d8837fc0 --- /dev/null +++ b/libraries/ZWidget/src/core/truetypefont.h @@ -0,0 +1,527 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +typedef uint8_t ttf_uint8; +typedef uint16_t ttf_uint16; +typedef uint32_t ttf_uint24; // 24-bit unsigned integer +typedef uint32_t ttf_uint32; + +typedef int8_t ttf_int8; +typedef int16_t ttf_int16; +typedef int32_t ttf_int32; + +typedef uint32_t ttf_Fixed; // 32-bit signed fixed-point number (16.16) +typedef uint16_t ttf_UFWORD; // uint16 that describes a quantity in font design units +typedef int16_t ttf_FWORD; // int16 that describes a quantity in font design units +typedef uint16_t ttf_F2DOT14; // 16-bit signed fixed number with the low 14 bits of fraction (2.14) +typedef uint64_t ttf_LONGDATETIME; // number of seconds since 12:00 midnight, January 1, 1904, UTC + +typedef std::array ttf_Tag; // 4 byte identifier + +typedef uint16_t ttf_Offset16; // Short offset to a table, same as uint16, NULL offset = 0x0000 +typedef uint32_t ttf_Offset24; // 24-bit offset to a table, same as uint24, NULL offset = 0x000000 +typedef uint32_t ttf_Offset32; // Long offset to a table, same as uint32, NULL offset = 0x00000000 + +typedef uint32_t ttf_Version16Dot16; // Packed 32-bit value with major and minor version numbers + +class TrueTypeFileReader +{ +public: + TrueTypeFileReader() = default; + TrueTypeFileReader(const void* data, size_t size) : data(static_cast(data)), size(size) { } + + bool IsEndOfData() const { return pos == size; } + + ttf_uint8 ReadUInt8(); + ttf_uint16 ReadUInt16(); + ttf_uint24 ReadUInt24(); + ttf_uint32 ReadUInt32(); + ttf_int8 ReadInt8(); + ttf_int16 ReadInt16(); + ttf_int32 ReadInt32(); + ttf_Fixed ReadFixed(); + ttf_UFWORD ReadUFWORD(); + ttf_FWORD ReadFWORD(); + ttf_F2DOT14 ReadF2DOT14(); + ttf_LONGDATETIME ReadLONGDATETIME(); + ttf_Tag ReadTag(); + ttf_Offset16 ReadOffset16(); + ttf_Offset24 ReadOffset24(); + ttf_Offset32 ReadOffset32(); + ttf_Version16Dot16 ReadVersion16Dot16(); + + void Seek(size_t newpos); + void Read(void* output, size_t count); + +private: + const uint8_t* data = nullptr; + size_t size = 0; + size_t pos = 0; +}; + +struct TTF_TableRecord +{ + ttf_Tag tableTag = {}; + ttf_uint32 checksum = {}; + ttf_Offset32 offset = {}; + ttf_uint32 length = {}; + + void Load(TrueTypeFileReader& reader); + + TrueTypeFileReader GetReader(const void* filedata, size_t filesize) const + { + if ((size_t)offset + length > filesize) + throw std::runtime_error("Invalid TTF table directory record"); + + return TrueTypeFileReader((uint8_t*)filedata + offset, length); + } +}; + +struct TTF_TableDirectory +{ + ttf_uint32 sfntVersion = {}; + ttf_uint16 numTables = {}; + std::vector tableRecords; + + // To do: Apple TTF fonts allow 'true' and 'typ1' for sfntVersion as well. + bool ContainsTTFOutlines() const { return sfntVersion == 0x00010000; } + bool ContainsCFFData() const { return sfntVersion == 0x4F54544F; } + + void Load(TrueTypeFileReader& reader); + + const TTF_TableRecord& GetRecord(const char* tag) const + { + for (const auto& record : tableRecords) + { + if (memcmp(record.tableTag.data(), tag, 4) == 0) + { + return record; + } + } + throw std::runtime_error(std::string("Could not find required '") + tag + "' table entry"); + } + + TrueTypeFileReader GetReader(const void* filedata, size_t filesize, const char* tag) const + { + return GetRecord(tag).GetReader(filedata, filesize); + } +}; + +struct TTC_Header +{ + ttf_Tag ttcTag = {}; + ttf_uint16 majorVersion = {}; + ttf_uint16 minorVersion = {}; + ttf_uint32 numFonts = {}; + std::vector tableDirectoryOffsets; + + // majorVersion = 2, minorVersion = 0: + ttf_uint32 dsigTag = {}; + ttf_uint32 dsigLength = {}; + ttf_uint32 dsigOffset = {}; + + void Load(TrueTypeFileReader& reader); +}; + +struct TTF_EncodingRecord +{ + ttf_uint16 platformID = {}; + ttf_uint16 encodingID = {}; + ttf_Offset32 subtableOffset = {}; +}; + +struct TTF_CMap // 'cmap' Character to glyph mapping +{ + ttf_uint16 version = {}; + ttf_uint16 numTables = {}; + std::vector encodingRecords; // [numTables] + + void Load(TrueTypeFileReader& reader); + + TTF_EncodingRecord GetEncoding(ttf_uint16 platformID, ttf_uint16 encodingID) const + { + for (const TTF_EncodingRecord& record : encodingRecords) + { + if (record.platformID == platformID && record.encodingID == encodingID) + { + return record; + } + } + return {}; + } +}; + +struct TTF_GlyphRange +{ + ttf_uint32 startCharCode = 0; + ttf_uint32 endCharCode = 0; + ttf_uint32 startGlyphID = 0; +}; + +struct TTF_CMapSubtable0 // Byte encoding table +{ + ttf_uint16 length = {}; + ttf_uint16 language = {}; + std::vector glyphIdArray; + + void Load(TrueTypeFileReader& reader); +}; + +struct TTF_CMapSubtable4 // Segment mapping to delta values (U+0000 to U+FFFF) +{ + ttf_uint16 length = {}; + ttf_uint16 language = {}; + ttf_uint16 segCount = {}; + std::vector endCode; + ttf_uint16 reservedPad = {}; + std::vector startCode; + std::vector idDelta; + std::vector idRangeOffsets; + std::vector glyphIdArray; + + void Load(TrueTypeFileReader& reader); +}; + +struct TTF_CMapSubtable12 // Segmented coverage (U+0000 to U+10FFFF) +{ + ttf_uint16 reserved; + ttf_uint32 length; + ttf_uint32 language; + ttf_uint32 numGroups; + std::vector groups; + + void Load(TrueTypeFileReader& reader); +}; + +typedef TTF_CMapSubtable12 TTF_CMapSubtable13; // Many-to-one range mappings + +struct TTF_FontHeader // 'head' Font header +{ + ttf_uint16 majorVersion = {}; + ttf_uint16 minorVersion = {}; + ttf_Fixed fontRevision = {}; + ttf_uint32 checksumAdjustment = {}; + ttf_uint32 magicNumber = {}; + ttf_uint16 flags = {}; + ttf_uint16 unitsPerEm = {}; + ttf_LONGDATETIME created = {}; + ttf_LONGDATETIME modified = {}; + ttf_int16 xMin = {}; + ttf_int16 yMin = {}; + ttf_int16 xMax = {}; + ttf_int16 yMax = {}; + ttf_uint16 macStyle = {}; + ttf_uint16 lowestRecPPEM = {}; + ttf_int16 fontDirectionHint = {}; + ttf_int16 indexToLocFormat = {}; + ttf_int16 glyphDataFormat = {}; + + void Load(TrueTypeFileReader& reader); +}; + +struct TTF_HorizontalHeader // 'hhea' Horizontal header +{ + ttf_uint16 majorVersion = {}; + ttf_uint16 minorVersion = {}; + ttf_FWORD ascender = {}; + ttf_FWORD descender = {}; + ttf_FWORD lineGap = {}; + ttf_UFWORD advanceWidthMax = {}; + ttf_FWORD minLeftSideBearing = {}; + ttf_FWORD minRightSideBearing = {}; + ttf_FWORD xMaxExtent = {}; + ttf_int16 caretSlopeRise = {}; + ttf_int16 caretSlopeRun = {}; + ttf_int16 caretOffset = {}; + ttf_int16 reserved0 = {}; + ttf_int16 reserved1 = {}; + ttf_int16 reserved2 = {}; + ttf_int16 reserved3 = {}; + ttf_int16 metricDataFormat = {}; + ttf_uint16 numberOfHMetrics = {}; + + void Load(TrueTypeFileReader& reader); +}; + +struct TTF_MaximumProfile; + +struct TTF_HorizontalMetrics // 'hmtx' Horizontal metrics +{ + struct longHorMetric + { + ttf_uint16 advanceWidth = {}; + ttf_int16 lsb = {}; + }; + std::vector hMetrics; // [hhea.numberOfHMetrics] + std::vector leftSideBearings; // [maxp.numGlyphs - hhea.numberOfHMetrics] + + void Load(const TTF_HorizontalHeader& hhea, const TTF_MaximumProfile& maxp, TrueTypeFileReader& reader); +}; + +struct TTF_MaximumProfile // 'maxp' Maximum profile +{ + // v0.5 and v1: + ttf_Version16Dot16 version = {}; + ttf_uint16 numGlyphs = {}; + + // v1 only: + ttf_uint16 maxPoints = {}; + ttf_uint16 maxContours = {}; + ttf_uint16 maxCompositePoints = {}; + ttf_uint16 maxCompositeContours = {}; + ttf_uint16 maxZones = {}; + ttf_uint16 maxTwilightPoints = {}; + ttf_uint16 maxStorage = {}; + ttf_uint16 maxFunctionDefs = {}; + ttf_uint16 maxInstructionDefs = {}; + ttf_uint16 maxStackElements = {}; + ttf_uint16 maxSizeOfInstructions = {}; + ttf_uint16 maxComponentElements = {}; + ttf_uint16 maxComponentDepth = {}; + + void Load(TrueTypeFileReader& reader); +}; + +class TTCFontName +{ +public: + std::string FamilyName; // Arial + std::string SubfamilyName; // Regular + std::string FullName; // Arial Regular + std::string UniqueID; + std::string VersionString; + std::string PostscriptName; +}; + +struct TTF_NamingTable // 'name' Naming table +{ + struct NameRecord + { + ttf_uint16 platformID = {}; + ttf_uint16 encodingID = {}; + ttf_uint16 languageID = {}; + ttf_uint16 nameID = {}; + ttf_uint16 length = {}; + ttf_Offset16 stringOffset = {}; + std::string text; + }; + + struct LangTagRecord + { + ttf_uint16 length = {}; + ttf_Offset16 langTagOffset = {}; + }; + + // v0 and v1: + ttf_uint16 version = {}; + ttf_uint16 count = {}; + ttf_Offset16 storageOffset = {}; + std::vector nameRecord; // [count] + + // v1 only: + ttf_uint16 langTagCount = {}; + std::vector langTagRecord; // [langTagCount] + + void Load(TrueTypeFileReader& reader); + + TTCFontName GetFontName() const; +}; + +struct TTF_OS2Windows // 'OS/2' Windows specific metrics +{ + ttf_uint16 version = {}; + ttf_int16 xAvgCharWidth = {}; + ttf_uint16 usWeightClass = {}; + ttf_uint16 usWidthClass = {}; + ttf_uint16 fsType = {}; + ttf_int16 ySubscriptXSize = {}; + ttf_int16 ySubscriptYSize = {}; + ttf_int16 ySubscriptXOffset = {}; + ttf_int16 ySubscriptYOffset = {}; + ttf_int16 ySuperscriptXSize = {}; + ttf_int16 ySuperscriptYSize = {}; + ttf_int16 ySuperscriptXOffset = {}; + ttf_int16 ySuperscriptYOffset = {}; + ttf_int16 yStrikeoutSize = {}; + ttf_int16 yStrikeoutPosition = {}; + ttf_int16 sFamilyClass = {}; + ttf_uint8 panose[10] = {}; + ttf_uint32 ulUnicodeRange1 = {}; + ttf_uint32 ulUnicodeRange2 = {}; + ttf_uint32 ulUnicodeRange3 = {}; + ttf_uint32 ulUnicodeRange4 = {}; + ttf_Tag achVendID = {}; + ttf_uint16 fsSelection = {}; + ttf_uint16 usFirstCharIndex = {}; + ttf_uint16 usLastCharIndex = {}; + ttf_int16 sTypoAscender = {}; + ttf_int16 sTypoDescender = {}; + ttf_int16 sTypoLineGap = {}; + ttf_uint16 usWinAscent = {}; // may be missing in v0 due to bugs in Apple docs + ttf_uint16 usWinDescent = {}; // may be missing in v0 due to bugs in Apple docs + ttf_uint32 ulCodePageRange1 = {}; // v1 + ttf_uint32 ulCodePageRange2 = {}; + ttf_int16 sxHeight = {}; // v2, v3 and v4 + ttf_int16 sCapHeight = {}; + ttf_uint16 usDefaultChar = {}; + ttf_uint16 usBreakChar = {}; + ttf_uint16 usMaxContext = {}; + ttf_uint16 usLowerOpticalPointSize = {}; // v5 + ttf_uint16 usUpperOpticalPointSize = {}; + + void Load(TrueTypeFileReader& reader); +}; + +// Simple glyph flags: +#define TTF_ON_CURVE_POINT 0x01 +#define TTF_X_SHORT_VECTOR 0x02 +#define TTF_Y_SHORT_VECTOR 0x04 +#define TTF_REPEAT_FLAG 0x08 +#define TTF_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR 0x10 +#define TTF_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR 0x20 +#define TTF_OVERLAP_SIMPLE = 0x40 + +// Composite glyph flags: +#define TTF_ARG_1_AND_2_ARE_WORDS 0x0001 +#define TTF_ARGS_ARE_XY_VALUES 0x0002 +#define TTF_ROUND_XY_TO_GRID 0x0004 +#define TTF_WE_HAVE_A_SCALE 0x0008 +#define TTF_MORE_COMPONENTS 0x0020 +#define TTF_WE_HAVE_AN_X_AND_Y_SCALE 0x0040 +#define TTF_WE_HAVE_A_TWO_BY_TWO 0x0080 +#define TTF_WE_HAVE_INSTRUCTIONS 0x0100 +#define TTF_USE_MY_METRICS 0x0200 +#define TTF_OVERLAP_COMPOUND 0x0400 +#define TTF_SCALED_COMPONENT_OFFSET 0x0800 +#define TTF_UNSCALED_COMPONENT_OFFSET 0x1000 + +struct TTF_IndexToLocation // 'loca' Index to location +{ + std::vector offsets; + + void Load(const TTF_FontHeader& head, const TTF_MaximumProfile& maxp, TrueTypeFileReader& reader); +}; + +struct TTF_Point +{ + float x; + float y; +}; + +struct TTF_SimpleGlyph +{ + std::vector endPtsOfContours; + std::vector flags; + std::vector points; +}; + +class TrueTypeGlyph +{ +public: + int advanceWidth = 0; + int leftSideBearing = 0; + int yOffset = 0; + + int width = 0; + int height = 0; + std::unique_ptr grayscale; +}; + +class TrueTypeTextMetrics +{ +public: + double ascender = 0.0; + double descender = 0.0; + double lineGap = 0.0; +}; + +class TrueTypeFontFileData +{ +public: + TrueTypeFontFileData(std::vector data) : dataVector(std::move(data)) + { + dataPtr = dataVector.data(); + dataSize = dataVector.size(); + } + + TrueTypeFontFileData(const void* data, size_t size, bool copyData = true) + { + dataSize = size; + if (copyData) + { + dataPtr = new uint8_t[size]; + deleteDataPtr = true; + memcpy(const_cast(dataPtr), data, size); + } + else + { + dataPtr = data; + } + } + + ~TrueTypeFontFileData() + { + if (deleteDataPtr) + { + delete[](uint8_t*)dataPtr; + } + dataPtr = nullptr; + } + + const void* data() const { return dataPtr; } + size_t size() const { return dataSize; } + +private: + std::vector dataVector; + const void* dataPtr = nullptr; + size_t dataSize = 0; + bool deleteDataPtr = false; + + TrueTypeFontFileData(const TrueTypeFontFileData&) = delete; + TrueTypeFontFileData& operator=(const TrueTypeFontFileData&) = delete; +}; + +class TrueTypeFont +{ +public: + TrueTypeFont(std::shared_ptr data, int ttcFontIndex = 0); + + static std::vector GetFontNames(const std::shared_ptr& data); + + TrueTypeTextMetrics GetTextMetrics(double height) const; + uint32_t GetGlyphIndex(uint32_t codepoint) const; + TrueTypeGlyph LoadGlyph(uint32_t glyphIndex, double height) const; + +private: + void LoadCharacterMapEncoding(TrueTypeFileReader& reader); + void LoadGlyph(TTF_SimpleGlyph& glyph, uint32_t glyphIndex, int compositeDepth = 0) const; + static float F2DOT14_ToFloat(ttf_F2DOT14 v); + + std::shared_ptr data; + + TTC_Header ttcHeader; + TTF_TableDirectory directory; + + // Required for all OpenType fonts: + TTF_CMap cmap; + TTF_FontHeader head; + TTF_HorizontalHeader hhea; + TTF_HorizontalMetrics hmtx; + TTF_MaximumProfile maxp; + TTF_NamingTable name; + TTF_OS2Windows os2; + + // TrueType outlines: + TTF_TableRecord glyf; // Parsed on a per glyph basis using offsets from other tables + TTF_IndexToLocation loca; + + std::vector Ranges; + std::vector ManyToOneRanges; +}; diff --git a/libraries/ZWidget/src/core/utf8reader.cpp b/libraries/ZWidget/src/core/utf8reader.cpp new file mode 100644 index 0000000000..200da9fdc4 --- /dev/null +++ b/libraries/ZWidget/src/core/utf8reader.cpp @@ -0,0 +1,153 @@ +/* +** Copyright (c) 1997-2015 Mark Page +** +** 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. +** +*/ + +#include "core/utf8reader.h" + +namespace +{ + static const char trailing_bytes_for_utf8[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 + }; + + static const unsigned char bitmask_leadbyte_for_utf8[6] = + { + 0x7f, + 0x1f, + 0x0f, + 0x07, + 0x03, + 0x01 + }; +} + +UTF8Reader::UTF8Reader(const std::string::value_type *text, std::string::size_type length) : length(length), data((unsigned char *)text) +{ +} + +bool UTF8Reader::is_end() +{ + return current_position >= length; +} + +unsigned int UTF8Reader::character() +{ + if (current_position >= length) + return 0; + + int trailing_bytes = trailing_bytes_for_utf8[data[current_position]]; + if (trailing_bytes == 0 && (data[current_position] & 0x80) == 0x80) + return '?'; + + if (current_position + 1 + trailing_bytes > length) + { + return '?'; + } + else + { + unsigned int ucs4 = (data[current_position] & bitmask_leadbyte_for_utf8[trailing_bytes]); + for (std::string::size_type i = 0; i < trailing_bytes; i++) + { + if ((data[current_position + 1 + i] & 0xC0) == 0x80) + ucs4 = (ucs4 << 6) + (data[current_position + 1 + i] & 0x3f); + else + return '?'; + } + + // To do: verify that the ucs4 value is in the range for the trailing_bytes specified in the lead byte. + + return ucs4; + } + +} + +std::string::size_type UTF8Reader::char_length() +{ + if (current_position < length) + { + int trailing_bytes = trailing_bytes_for_utf8[data[current_position]]; + if (current_position + 1 + trailing_bytes > length) + return 1; + + for (std::string::size_type i = 0; i < trailing_bytes; i++) + { + if ((data[current_position + 1 + i] & 0xC0) != 0x80) + return 1; + } + + return 1 + trailing_bytes; + } + else + { + return 0; + } +} + +void UTF8Reader::prev() +{ + if (current_position > length) + current_position = length; + + if (current_position > 0) + { + current_position--; + move_to_leadbyte(); + } +} + +void UTF8Reader::next() +{ + current_position += char_length(); + +} + +void UTF8Reader::move_to_leadbyte() +{ + if (current_position < length) + { + int lead_position = (int)current_position; + + while (lead_position > 0 && (data[lead_position] & 0xC0) == 0x80) + lead_position--; + + int trailing_bytes = trailing_bytes_for_utf8[data[lead_position]]; + if (lead_position + trailing_bytes >= current_position) + current_position = lead_position; + } + +} + +std::string::size_type UTF8Reader::position() +{ + return current_position; +} + +void UTF8Reader::set_position(std::string::size_type position) +{ + current_position = position; +} diff --git a/libraries/ZWidget/src/core/widget.cpp b/libraries/ZWidget/src/core/widget.cpp new file mode 100644 index 0000000000..9d380917c3 --- /dev/null +++ b/libraries/ZWidget/src/core/widget.cpp @@ -0,0 +1,879 @@ + +#include "core/widget.h" +#include "core/timer.h" +#include "core/colorf.h" +#include "core/theme.h" +#include +#include +#include + +Widget::Widget(Widget* parent, WidgetType type) : Type(type) +{ + if (type != WidgetType::Child) + { + Widget* owner = parent ? parent->Window() : nullptr; + DispWindow = DisplayWindow::Create(this, type == WidgetType::Popup, owner ? owner->DispWindow.get() : nullptr); + DispCanvas = Canvas::create(DispWindow.get()); + SetStyleState("root"); + + SetWindowBackground(GetStyleColor("window-background")); + if (GetStyleColor("window-border").a > 0.0f) + SetWindowBorderColor(GetStyleColor("window-border")); + if (GetStyleColor("window-caption-color").a > 0.0f) + SetWindowCaptionColor(GetStyleColor("window-caption-color")); + if (GetStyleColor("window-caption-text-color").a > 0.0f) + SetWindowCaptionTextColor(GetStyleColor("window-caption-text-color")); + } + + SetParent(parent); +} + +Widget::~Widget() +{ + while (LastChildObj) + delete LastChildObj; + + while (FirstTimerObj) + delete FirstTimerObj; + + DetachFromParent(); +} + +void Widget::SetParent(Widget* newParent) +{ + if (ParentObj != newParent) + { + if (ParentObj) + DetachFromParent(); + + if (newParent) + { + PrevSiblingObj = newParent->LastChildObj; + if (PrevSiblingObj) PrevSiblingObj->NextSiblingObj = this; + newParent->LastChildObj = this; + if (!newParent->FirstChildObj) newParent->FirstChildObj = this; + ParentObj = newParent; + } + } +} + +void Widget::MoveBefore(Widget* sibling) +{ + if (sibling && sibling->ParentObj != ParentObj) throw std::runtime_error("Invalid sibling passed to Widget.MoveBefore"); + if (!ParentObj) throw std::runtime_error("Widget must have a parent before it can be moved"); + + if (NextSiblingObj != sibling) + { + Widget* p = ParentObj; + DetachFromParent(); + + ParentObj = p; + if (sibling) + { + NextSiblingObj = sibling; + PrevSiblingObj = sibling->PrevSiblingObj; + sibling->PrevSiblingObj = this; + if (PrevSiblingObj) PrevSiblingObj->NextSiblingObj = this; + if (ParentObj->FirstChildObj == sibling) ParentObj->FirstChildObj = this; + } + else + { + PrevSiblingObj = ParentObj->LastChildObj; + if (PrevSiblingObj) PrevSiblingObj->NextSiblingObj = this; + ParentObj->LastChildObj = this; + if (!ParentObj->FirstChildObj) ParentObj->FirstChildObj = this; + } + } +} + +void Widget::DetachFromParent() +{ + for (Widget* cur = ParentObj; cur; cur = cur->ParentObj) + { + if (cur->FocusWidget == this) + cur->FocusWidget = nullptr; + if (cur->CaptureWidget == this) + cur->CaptureWidget = nullptr; + if (cur->HoverWidget == this) + cur->HoverWidget = nullptr; + + if (cur->DispWindow) + break; + } + + if (PrevSiblingObj) + PrevSiblingObj->NextSiblingObj = NextSiblingObj; + if (NextSiblingObj) + NextSiblingObj->PrevSiblingObj = PrevSiblingObj; + if (ParentObj) + { + if (ParentObj->FirstChildObj == this) + ParentObj->FirstChildObj = NextSiblingObj; + if (ParentObj->LastChildObj == this) + ParentObj->LastChildObj = PrevSiblingObj; + } + PrevSiblingObj = nullptr; + NextSiblingObj = nullptr; + ParentObj = nullptr; +} + +std::string Widget::GetWindowTitle() const +{ + return WindowTitle; +} + +void Widget::SetWindowTitle(const std::string& text) +{ + if (WindowTitle != text) + { + WindowTitle = text; + if (DispWindow) + DispWindow->SetWindowTitle(WindowTitle); + } +} + +Size Widget::GetSize() const +{ + return ContentGeometry.size(); +} + +Rect Widget::GetFrameGeometry() const +{ + if (Type == WidgetType::Child) + { + return FrameGeometry; + } + else + { + return DispWindow->GetWindowFrame(); + } +} + +void Widget::SetNoncontentSizes(double left, double top, double right, double bottom) +{ + SetStyleDouble("noncontent-left", left); + SetStyleDouble("noncontent-top", top); + SetStyleDouble("noncontent-right", right); + SetStyleDouble("noncontent-bottom", bottom); +} + +void Widget::SetFrameGeometry(const Rect& geometry) +{ + if (Type == WidgetType::Child) + { + FrameGeometry = geometry; + double left = FrameGeometry.left() + GetNoncontentLeft(); + double top = FrameGeometry.top() + GetNoncontentTop(); + double right = FrameGeometry.right() - GetNoncontentRight(); + double bottom = FrameGeometry.bottom() - GetNoncontentBottom(); + left = std::min(left, FrameGeometry.right()); + top = std::min(top, FrameGeometry.bottom()); + right = std::max(right, FrameGeometry.left()); + bottom = std::max(bottom, FrameGeometry.top()); + left = GridFitPoint(left); + top = GridFitPoint(top); + right = GridFitPoint(right); + bottom = GridFitPoint(bottom); + ContentGeometry = Rect::ltrb(left, top, right, bottom); + OnGeometryChanged(); + } + else + { + DispWindow->SetWindowFrame(geometry); + } +} + +void Widget::Show() +{ + if (Type != WidgetType::Child) + { + DispWindow->Show(); + } + else if (HiddenFlag) + { + HiddenFlag = false; + Update(); + } +} + +void Widget::ShowFullscreen() +{ + if (Type != WidgetType::Child) + { + DispWindow->ShowFullscreen(); + } +} + +void Widget::ShowMaximized() +{ + if (Type != WidgetType::Child) + { + DispWindow->ShowMaximized(); + } +} + +void Widget::ShowMinimized() +{ + if (Type != WidgetType::Child) + { + DispWindow->ShowMinimized(); + } +} + +void Widget::ShowNormal() +{ + if (Type != WidgetType::Child) + { + DispWindow->ShowNormal(); + } +} + +void Widget::Hide() +{ + if (Type != WidgetType::Child) + { + if (DispWindow) + DispWindow->Hide(); + } + else if (!HiddenFlag) + { + HiddenFlag = true; + Update(); + } +} + +void Widget::ActivateWindow() +{ + if (Type != WidgetType::Child) + { + DispWindow->Activate(); + } +} + +void Widget::Close() +{ + OnClose(); +} + +void Widget::SetWindowBackground(const Colorf& color) +{ + Widget* w = Window(); + if (w && w->WindowBackground != color) + { + w->WindowBackground = color; + Update(); + } +} + +void Widget::SetWindowBorderColor(const Colorf& color) +{ + Widget* w = Window(); + if (w) + { + w->DispWindow->SetBorderColor(color.toBgra8()); + w->DispWindow->Update(); + } +} + +void Widget::SetWindowCaptionColor(const Colorf& color) +{ + Widget* w = Window(); + if (w) + { + w->DispWindow->SetCaptionColor(color.toBgra8()); + w->DispWindow->Update(); + } +} + +void Widget::SetWindowCaptionTextColor(const Colorf& color) +{ + Widget* w = Window(); + if (w) + { + w->DispWindow->SetCaptionTextColor(color.toBgra8()); + w->DispWindow->Update(); + } +} + +void Widget::Update() +{ + Widget* w = Window(); + if (w) + { + w->DispWindow->Update(); + } +} + +void Widget::Repaint() +{ + Widget* w = Window(); + w->DispCanvas->begin(WindowBackground); + w->Paint(w->DispCanvas.get()); + w->DispCanvas->end(); +} + +void Widget::Paint(Canvas* canvas) +{ + Point oldOrigin = canvas->getOrigin(); + canvas->pushClip(FrameGeometry); + canvas->setOrigin(oldOrigin + FrameGeometry.topLeft()); + OnPaintFrame(canvas); + canvas->setOrigin(oldOrigin); + canvas->popClip(); + + canvas->pushClip(ContentGeometry); + canvas->setOrigin(oldOrigin + ContentGeometry.topLeft()); + OnPaint(canvas); + for (Widget* w = FirstChild(); w != nullptr; w = w->NextSibling()) + { + if (w->Type == WidgetType::Child && !w->HiddenFlag) + w->Paint(canvas); + } + canvas->setOrigin(oldOrigin); + canvas->popClip(); +} + +void Widget::OnPaintFrame(Canvas* canvas) +{ + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + if (style) + { + style->Paint(this, canvas, GetFrameGeometry().size()); + } +} + +bool Widget::GetKeyState(InputKey key) +{ + Widget* window = Window(); + return window ? window->DispWindow->GetKeyState(key) : false; +} + +bool Widget::HasFocus() +{ + Widget* window = Window(); + return window ? window->FocusWidget == this : false; +} + +bool Widget::IsEnabled() +{ + return true; +} + +bool Widget::IsHidden() +{ + return !IsVisible(); +} + +bool Widget::IsVisible() +{ + if (Type != WidgetType::Child) + { + return true; // DispWindow->IsVisible(); + } + else + { + return !HiddenFlag; + } +} + +void Widget::SetFocus() +{ + Widget* window = Window(); + if (window) + { + if (window->FocusWidget) + window->FocusWidget->OnLostFocus(); + window->FocusWidget = this; + window->FocusWidget->OnSetFocus(); + window->ActivateWindow(); + } +} + +void Widget::SetEnabled(bool value) +{ +} + +void Widget::LockCursor() +{ + Widget* w = Window(); + if (w && w->CaptureWidget != this) + { + w->CaptureWidget = this; + w->DispWindow->LockCursor(); + } +} + +void Widget::UnlockCursor() +{ + Widget* w = Window(); + if (w && w->CaptureWidget != nullptr) + { + w->CaptureWidget = nullptr; + w->DispWindow->UnlockCursor(); + } +} + +void Widget::SetCursor(StandardCursor cursor) +{ + if (CurrentCursor != cursor) + { + CurrentCursor = cursor; + if (HoverWidget == this || CaptureWidget == this) + { + Widget* w = Window(); + if (w) + { + w->DispWindow->SetCursor(CurrentCursor); + } + } + } +} + +void Widget::CaptureMouse() +{ + Widget* w = Window(); + if (w && w->CaptureWidget != this) + { + w->CaptureWidget = this; + w->DispWindow->CaptureMouse(); + } +} + +void Widget::ReleaseMouseCapture() +{ + Widget* w = Window(); + if (w && w->CaptureWidget != nullptr) + { + w->CaptureWidget = nullptr; + w->DispWindow->ReleaseMouseCapture(); + } +} + +std::string Widget::GetClipboardText() +{ + Widget* w = Window(); + if (w) + return w->DispWindow->GetClipboardText(); + else + return {}; +} + +void Widget::SetClipboardText(const std::string& text) +{ + Widget* w = Window(); + if (w) + w->DispWindow->SetClipboardText(text); +} + +Widget* Widget::Window() const +{ + for (const Widget* w = this; w != nullptr; w = w->Parent()) + { + if (w->DispWindow) + return const_cast(w); + } + return nullptr; +} + +Canvas* Widget::GetCanvas() const +{ + for (const Widget* w = this; w != nullptr; w = w->Parent()) + { + if (w->DispCanvas) + return w->DispCanvas.get(); + } + return nullptr; +} + +Widget* Widget::ChildAt(const Point& pos) +{ + for (Widget* cur = LastChild(); cur != nullptr; cur = cur->PrevSibling()) + { + if (cur->Type == WidgetType::Child && !cur->HiddenFlag && cur->FrameGeometry.contains(pos)) + { + Widget* cur2 = cur->ChildAt(pos - cur->ContentGeometry.topLeft()); + return cur2 ? cur2 : cur; + } + } + return nullptr; +} + +Point Widget::MapFrom(const Widget* parent, const Point& pos) const +{ + Point p = pos; + for (const Widget* cur = this; cur != nullptr; cur = cur->Parent()) + { + if (cur == parent) + return p; + p -= cur->ContentGeometry.topLeft(); + } + throw std::runtime_error("MapFrom: not a parent of widget"); +} + +Point Widget::MapFromGlobal(const Point& pos) const +{ + Point p = pos; + for (const Widget* cur = this; cur != nullptr; cur = cur->Parent()) + { + if (cur->DispWindow) + { + return cur->DispWindow->MapFromGlobal(p); + } + p -= cur->ContentGeometry.topLeft(); + } + throw std::runtime_error("MapFromGlobal: no window widget found"); +} + +Point Widget::MapTo(const Widget* parent, const Point& pos) const +{ + Point p = pos; + for (const Widget* cur = this; cur != nullptr; cur = cur->Parent()) + { + if (cur == parent) + return p; + p += cur->ContentGeometry.topLeft(); + } + throw std::runtime_error("MapTo: not a parent of widget"); +} + +Point Widget::MapToGlobal(const Point& pos) const +{ + Point p = pos; + for (const Widget* cur = this; cur != nullptr; cur = cur->Parent()) + { + if (cur->DispWindow) + { + return cur->DispWindow->MapToGlobal(p); + } + p += cur->ContentGeometry.topLeft(); + } + throw std::runtime_error("MapFromGlobal: no window widget found"); +} + +void Widget::OnWindowPaint() +{ + Repaint(); +} + +void Widget::OnWindowMouseMove(const Point& pos) +{ + if (CaptureWidget) + { + DispWindow->SetCursor(CaptureWidget->CurrentCursor); + CaptureWidget->OnMouseMove(CaptureWidget->MapFrom(this, pos)); + } + else + { + Widget* widget = ChildAt(pos); + if (!widget) + widget = this; + + if (HoverWidget != widget) + { + if (HoverWidget) + { + for (Widget* w = HoverWidget; w != widget && w != this; w = w->Parent()) + { + Widget* p = w->Parent(); + if (!w->FrameGeometry.contains(p->MapFrom(this, pos))) + { + w->OnMouseLeave(); + } + } + } + HoverWidget = widget; + } + + DispWindow->SetCursor(widget->CurrentCursor); + + do + { + widget->OnMouseMove(widget->MapFrom(this, pos)); + if (widget == this) + break; + widget = widget->Parent(); + } while (widget); + } +} + +void Widget::OnWindowMouseLeave() +{ + if (HoverWidget) + { + for (Widget* w = HoverWidget; w; w = w->Parent()) + { + w->OnMouseLeave(); + } + HoverWidget = nullptr; + } +} + +void Widget::OnWindowMouseDown(const Point& pos, InputKey key) +{ + if (CaptureWidget) + { + CaptureWidget->OnMouseDown(CaptureWidget->MapFrom(this, pos), key); + } + else + { + Widget* widget = ChildAt(pos); + if (!widget) + widget = this; + while (widget) + { + bool stopPropagation = widget->OnMouseDown(widget->MapFrom(this, pos), key); + if (stopPropagation || widget == this) + break; + widget = widget->Parent(); + } + } +} + +void Widget::OnWindowMouseDoubleclick(const Point& pos, InputKey key) +{ + if (CaptureWidget) + { + CaptureWidget->OnMouseDoubleclick(CaptureWidget->MapFrom(this, pos), key); + } + else + { + Widget* widget = ChildAt(pos); + if (!widget) + widget = this; + while (widget) + { + bool stopPropagation = widget->OnMouseDoubleclick(widget->MapFrom(this, pos), key); + if (stopPropagation || widget == this) + break; + widget = widget->Parent(); + } + } +} + +void Widget::OnWindowMouseUp(const Point& pos, InputKey key) +{ + if (CaptureWidget) + { + CaptureWidget->OnMouseUp(CaptureWidget->MapFrom(this, pos), key); + } + else + { + Widget* widget = ChildAt(pos); + if (!widget) + widget = this; + while (widget) + { + bool stopPropagation = widget->OnMouseUp(widget->MapFrom(this, pos), key); + if (stopPropagation || widget == this) + break; + widget = widget->Parent(); + } + } +} + +void Widget::OnWindowMouseWheel(const Point& pos, InputKey key) +{ + if (CaptureWidget) + { + CaptureWidget->OnMouseWheel(CaptureWidget->MapFrom(this, pos), key); + } + else + { + Widget* widget = ChildAt(pos); + if (!widget) + widget = this; + while (widget) + { + bool stopPropagation = widget->OnMouseWheel(widget->MapFrom(this, pos), key); + if (stopPropagation || widget == this) + break; + widget = widget->Parent(); + } + } +} + +void Widget::OnWindowRawMouseMove(int dx, int dy) +{ + if (CaptureWidget) + { + CaptureWidget->OnRawMouseMove(dx, dy); + } + else if (FocusWidget) + { + FocusWidget->OnRawMouseMove(dx, dy); + } +} + +void Widget::OnWindowKeyChar(std::string chars) +{ + if (FocusWidget) + FocusWidget->OnKeyChar(chars); +} + +void Widget::OnWindowKeyDown(InputKey key) +{ + if (FocusWidget) + FocusWidget->OnKeyDown(key); +} + +void Widget::OnWindowKeyUp(InputKey key) +{ + if (FocusWidget) + FocusWidget->OnKeyUp(key); +} + +void Widget::OnWindowGeometryChanged() +{ + if (!DispWindow) + return; + Size size = DispWindow->GetClientSize(); + FrameGeometry = Rect::xywh(0.0, 0.0, size.width, size.height); + + double left = FrameGeometry.left() + GetNoncontentLeft(); + double top = FrameGeometry.top() + GetNoncontentTop(); + double right = FrameGeometry.right() - GetNoncontentRight(); + double bottom = FrameGeometry.bottom() - GetNoncontentBottom(); + left = std::min(left, FrameGeometry.right()); + top = std::min(top, FrameGeometry.bottom()); + right = std::max(right, FrameGeometry.left()); + bottom = std::max(bottom, FrameGeometry.top()); + ContentGeometry = Rect::ltrb(left, top, right, bottom); + + OnGeometryChanged(); +} + +void Widget::OnWindowClose() +{ + Close(); +} + +void Widget::OnWindowActivated() +{ +} + +void Widget::OnWindowDeactivated() +{ +} + +void Widget::OnWindowDpiScaleChanged() +{ +} + +double Widget::GetDpiScale() const +{ + Widget* w = Window(); + return w ? w->DispWindow->GetDpiScale() : 1.0; +} + +double Widget::GridFitPoint(double p) const +{ + double dpiscale = GetDpiScale(); + return std::round(p * dpiscale) / dpiscale; +} + +double Widget::GridFitSize(double s) const +{ + if (s <= 0.0) + return 0.0; + double dpiscale = GetDpiScale(); + return std::max(std::floor(s * dpiscale + 0.25), 1.0) / dpiscale; +} + +Size Widget::GetScreenSize() +{ + return DisplayWindow::GetScreenSize(); +} + +void* Widget::GetNativeHandle() +{ + Widget* w = Window(); + return w ? w->DispWindow->GetNativeHandle() : nullptr; +} + +void Widget::SetStyleClass(const std::string& themeClass) +{ + if (StyleClass != themeClass) + { + StyleClass = themeClass; + Update(); + } +} + +void Widget::SetStyleState(const std::string& state) +{ + if (StyleState != state) + { + StyleState = state; + Update(); + } +} + +void Widget::SetStyleBool(const std::string& propertyName, bool value) +{ + StyleProperties[propertyName] = value; +} + +void Widget::SetStyleInt(const std::string& propertyName, int value) +{ + StyleProperties[propertyName] = value; +} + +void Widget::SetStyleDouble(const std::string& propertyName, double value) +{ + StyleProperties[propertyName] = value; +} + +void Widget::SetStyleString(const std::string& propertyName, const std::string& value) +{ + StyleProperties[propertyName] = value; +} + +void Widget::SetStyleColor(const std::string& propertyName, const Colorf& value) +{ + StyleProperties[propertyName] = value; +} + +bool Widget::GetStyleBool(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetBool(StyleState, propertyName) : false; +} + +int Widget::GetStyleInt(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetInt(StyleState, propertyName) : 0; +} + +double Widget::GetStyleDouble(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetDouble(StyleState, propertyName) : 0.0; +} + +std::string Widget::GetStyleString(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetString(StyleState, propertyName) : std::string(); +} + +Colorf Widget::GetStyleColor(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetColor(StyleState, propertyName) : Colorf::transparent(); +} diff --git a/libraries/ZWidget/src/systemdialogs/folder_browse_dialog.cpp b/libraries/ZWidget/src/systemdialogs/folder_browse_dialog.cpp new file mode 100644 index 0000000000..754e397e20 --- /dev/null +++ b/libraries/ZWidget/src/systemdialogs/folder_browse_dialog.cpp @@ -0,0 +1,188 @@ + +#include "systemdialogs/folder_browse_dialog.h" +#include "core/widget.h" +#include "window/window.h" +#include + +#if defined(WIN32) +#include + +namespace +{ + static std::string from_utf16(const std::wstring& str) + { + if (str.empty()) return {}; + int needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0, nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + std::string result; + result.resize(needed); + needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size(), nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + return result; + } + + static std::wstring to_utf16(const std::string& str) + { + if (str.empty()) return {}; + int needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + std::wstring result; + result.resize(needed); + needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size()); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + return result; + } + + template + class ComPtr + { + public: + ComPtr() { Ptr = nullptr; } + ComPtr(const ComPtr& other) { Ptr = other.Ptr; if (Ptr) Ptr->AddRef(); } + ComPtr(ComPtr&& move) { Ptr = move.Ptr; move.Ptr = nullptr; } + ~ComPtr() { reset(); } + ComPtr& operator=(const ComPtr& other) { if (this != &other) { if (Ptr) Ptr->Release(); Ptr = other.Ptr; if (Ptr) Ptr->AddRef(); } return *this; } + void reset() { if (Ptr) Ptr->Release(); Ptr = nullptr; } + T* get() { return Ptr; } + static IID GetIID() { return __uuidof(T); } + void** InitPtr() { return (void**)TypedInitPtr(); } + T** TypedInitPtr() { reset(); return &Ptr; } + operator T* () const { return Ptr; } + T* operator ->() const { return Ptr; } + T* Ptr; + }; +} + +class BrowseFolderDialogImpl : public BrowseFolderDialog +{ +public: + BrowseFolderDialogImpl(Widget *owner) : owner(owner) + { + } + + Widget *owner = nullptr; + + std::string selected_path; + std::string initial_directory; + std::string title; + + bool Show() override + { + std::wstring title16 = to_utf16(title); + std::wstring initial_directory16 = to_utf16(initial_directory); + + HRESULT result; + ComPtr open_dialog; + + result = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_ALL, open_dialog.GetIID(), open_dialog.InitPtr()); + throw_if_failed(result, "CoCreateInstance(FileOpenDialog) failed"); + + result = open_dialog->SetTitle(title16.c_str()); + throw_if_failed(result, "IFileOpenDialog.SetTitle failed"); + + result = open_dialog->SetOptions(FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST); + throw_if_failed(result, "IFileOpenDialog.SetOptions((FOS_PICKFOLDERS) failed"); + + if (initial_directory16.length() > 0) + { + LPITEMIDLIST item_id_list = nullptr; + SFGAOF flags = 0; + result = SHParseDisplayName(initial_directory16.c_str(), nullptr, &item_id_list, SFGAO_FILESYSTEM, &flags); + throw_if_failed(result, "SHParseDisplayName failed"); + + ComPtr folder_item; + result = SHCreateShellItem(nullptr, nullptr, item_id_list, folder_item.TypedInitPtr()); + ILFree(item_id_list); + throw_if_failed(result, "SHCreateItemFromParsingName failed"); + + /* This code requires Windows Vista or newer: + ComPtr folder_item; + result = SHCreateItemFromParsingName(initial_directory16.c_str(), nullptr, folder_item.GetIID(), folder_item.InitPtr()); + throw_if_failed(result, "SHCreateItemFromParsingName failed"); + */ + + if (folder_item) + { + result = open_dialog->SetFolder(folder_item); + throw_if_failed(result, "IFileOpenDialog.SetFolder failed"); + } + } + + if (owner && owner->Window()) + result = open_dialog->Show((HWND)owner->Window()->GetNativeHandle()); + else + result = open_dialog->Show(0); + + if (SUCCEEDED(result)) + { + ComPtr chosen_folder; + result = open_dialog->GetResult(chosen_folder.TypedInitPtr()); + throw_if_failed(result, "IFileOpenDialog.GetResult failed"); + + WCHAR *buffer = nullptr; + result = chosen_folder->GetDisplayName(SIGDN_FILESYSPATH, &buffer); + throw_if_failed(result, "IShellItem.GetDisplayName failed"); + + std::wstring output_directory16; + if (buffer) + { + try + { + output_directory16 = buffer; + } + catch (...) + { + CoTaskMemFree(buffer); + throw; + } + } + + CoTaskMemFree(buffer); + selected_path = from_utf16(output_directory16); + return true; + } + else + { + return false; + } + } + + std::string BrowseFolderDialog::SelectedPath() const override + { + return selected_path; + } + + void BrowseFolderDialog::SetInitialDirectory(const std::string& path) override + { + initial_directory = path; + } + + void BrowseFolderDialog::SetTitle(const std::string& newtitle) override + { + title = newtitle; + } + + void throw_if_failed(HRESULT result, const std::string &error) + { + if (FAILED(result)) + throw std::runtime_error(error); + } +}; + +std::unique_ptr BrowseFolderDialog::Create(Widget* owner) +{ + return std::make_unique(owner); +} + +#else + +std::unique_ptr BrowseFolderDialog::Create(Widget* owner) +{ + return {}; +} + +#endif diff --git a/libraries/ZWidget/src/systemdialogs/open_file_dialog.cpp b/libraries/ZWidget/src/systemdialogs/open_file_dialog.cpp new file mode 100644 index 0000000000..ca7bc8f30a --- /dev/null +++ b/libraries/ZWidget/src/systemdialogs/open_file_dialog.cpp @@ -0,0 +1,286 @@ + +#include "systemdialogs/open_file_dialog.h" +#include "core/widget.h" +#include "window/window.h" +#include + +#if defined(WIN32) +#include + +namespace +{ + static std::string from_utf16(const std::wstring& str) + { + if (str.empty()) return {}; + int needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0, nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + std::string result; + result.resize(needed); + needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size(), nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + return result; + } + + static std::wstring to_utf16(const std::string& str) + { + if (str.empty()) return {}; + int needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + std::wstring result; + result.resize(needed); + needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size()); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + return result; + } + + template + class ComPtr + { + public: + ComPtr() { Ptr = nullptr; } + ComPtr(const ComPtr& other) { Ptr = other.Ptr; if (Ptr) Ptr->AddRef(); } + ComPtr(ComPtr&& move) { Ptr = move.Ptr; move.Ptr = nullptr; } + ~ComPtr() { reset(); } + ComPtr& operator=(const ComPtr& other) { if (this != &other) { if (Ptr) Ptr->Release(); Ptr = other.Ptr; if (Ptr) Ptr->AddRef(); } return *this; } + void reset() { if (Ptr) Ptr->Release(); Ptr = nullptr; } + T* get() { return Ptr; } + static IID GetIID() { return __uuidof(T); } + void** InitPtr() { return (void**)TypedInitPtr(); } + T** TypedInitPtr() { reset(); return &Ptr; } + operator T* () const { return Ptr; } + T* operator ->() const { return Ptr; } + T* Ptr; + }; +} + +class OpenFileDialogImpl : public OpenFileDialog +{ +public: + OpenFileDialogImpl(Widget* owner) : owner(owner) + { + } + + Widget* owner = nullptr; + + std::string initial_directory; + std::string initial_filename; + std::string title; + std::vector filenames; + bool multi_select = false; + + struct Filter + { + std::string description; + std::string extension; + }; + std::vector filters; + int filterindex = 0; + std::string defaultext; + + bool Show() override + { + std::wstring title16 = to_utf16(title); + std::wstring initial_directory16 = to_utf16(initial_directory); + + HRESULT result; + ComPtr open_dialog; + + result = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_ALL, open_dialog.GetIID(), open_dialog.InitPtr()); + throw_if_failed(result, "CoCreateInstance(FileOpenDialog) failed"); + + result = open_dialog->SetTitle(title16.c_str()); + throw_if_failed(result, "IFileOpenDialog.SetTitle failed"); + + if (!initial_filename.empty()) + { + result = open_dialog->SetFileName(to_utf16(initial_filename).c_str()); + throw_if_failed(result, "IFileOpenDialog.SetFileName failed"); + } + + FILEOPENDIALOGOPTIONS options = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST; + if (multi_select) + options |= FOS_ALLOWMULTISELECT; + result = open_dialog->SetOptions(options); + throw_if_failed(result, "IFileOpenDialog.SetOptions() failed"); + + if (!filters.empty()) + { + std::vector filterspecs(filters.size()); + std::vector descriptions(filters.size()); + std::vector extensions(filters.size()); + for (size_t i = 0; i < filters.size(); i++) + { + descriptions[i] = to_utf16(filters[i].description); + extensions[i] = to_utf16(filters[i].extension); + COMDLG_FILTERSPEC& spec = filterspecs[i]; + spec.pszName = descriptions[i].c_str(); + spec.pszSpec = extensions[i].c_str(); + } + result = open_dialog->SetFileTypes((UINT)filterspecs.size(), filterspecs.data()); + throw_if_failed(result, "IFileOpenDialog.SetFileTypes() failed"); + + if ((size_t)filterindex < filters.size()) + { + result = open_dialog->SetFileTypeIndex(filterindex); + throw_if_failed(result, "IFileOpenDialog.SetFileTypeIndex() failed"); + } + } + + if (!defaultext.empty()) + { + result = open_dialog->SetDefaultExtension(to_utf16(defaultext).c_str()); + throw_if_failed(result, "IFileOpenDialog.SetDefaultExtension() failed"); + } + + if (initial_directory16.length() > 0) + { + LPITEMIDLIST item_id_list = nullptr; + SFGAOF flags = 0; + result = SHParseDisplayName(initial_directory16.c_str(), nullptr, &item_id_list, SFGAO_FILESYSTEM, &flags); + throw_if_failed(result, "SHParseDisplayName failed"); + + ComPtr folder_item; + result = SHCreateShellItem(nullptr, nullptr, item_id_list, folder_item.TypedInitPtr()); + ILFree(item_id_list); + throw_if_failed(result, "SHCreateItemFromParsingName failed"); + + /* This code requires Windows Vista or newer: + ComPtr folder_item; + result = SHCreateItemFromParsingName(initial_directory16.c_str(), nullptr, folder_item.GetIID(), folder_item.InitPtr()); + throw_if_failed(result, "SHCreateItemFromParsingName failed"); + */ + + if (folder_item) + { + result = open_dialog->SetFolder(folder_item); + throw_if_failed(result, "IFileOpenDialog.SetFolder failed"); + } + } + + if (owner && owner->Window()) + result = open_dialog->Show((HWND)owner->Window()->GetNativeHandle()); + else + result = open_dialog->Show(0); + + if (SUCCEEDED(result)) + { + ComPtr items; + result = open_dialog->GetSelectedItems(items.TypedInitPtr()); + throw_if_failed(result, "IFileOpenDialog.GetSelectedItems failed"); + + DWORD num_items = 0; + result = items->GetCount(&num_items); + throw_if_failed(result, "IShellItemArray.GetCount failed"); + + for (DWORD i = 0; i < num_items; i++) + { + ComPtr item; + result = items->GetItemAt(i, item.TypedInitPtr()); + throw_if_failed(result, "IShellItemArray.GetItemAt failed"); + + WCHAR* buffer = nullptr; + result = item->GetDisplayName(SIGDN_FILESYSPATH, &buffer); + throw_if_failed(result, "IShellItem.GetDisplayName failed"); + + std::wstring output16; + if (buffer) + { + try + { + output16 = buffer; + } + catch (...) + { + CoTaskMemFree(buffer); + throw; + } + } + + CoTaskMemFree(buffer); + filenames.push_back(from_utf16(output16)); + } + return true; + } + else + { + return false; + } + } + + std::string Filename() const override + { + return !filenames.empty() ? filenames.front() : std::string(); + } + + std::vector Filenames() const override + { + return filenames; + } + + void SetMultiSelect(bool new_multi_select) override + { + multi_select = new_multi_select; + } + + void SetFilename(const std::string& filename) override + { + initial_filename = filename; + } + + void AddFilter(const std::string& filter_description, const std::string& filter_extension) override + { + Filter f; + f.description = filter_description; + f.extension = filter_extension; + filters.push_back(std::move(f)); + } + + void ClearFilters() override + { + filters.clear(); + } + + void SetFilterIndex(int filter_index) override + { + filterindex = filter_index; + } + + void SetInitialDirectory(const std::string& path) override + { + initial_directory = path; + } + + void SetTitle(const std::string& newtitle) override + { + title = newtitle; + } + + void SetDefaultExtension(const std::string& extension) override + { + defaultext = extension; + } + + void throw_if_failed(HRESULT result, const std::string& error) + { + if (FAILED(result)) + throw std::runtime_error(error); + } +}; + +std::unique_ptr OpenFileDialog::Create(Widget* owner) +{ + return std::make_unique(owner); +} + +#else + +std::unique_ptr OpenFileDialog::Create(Widget* owner) +{ + return {}; +} + +#endif diff --git a/libraries/ZWidget/src/systemdialogs/save_file_dialog.cpp b/libraries/ZWidget/src/systemdialogs/save_file_dialog.cpp new file mode 100644 index 0000000000..7bd8c00cdb --- /dev/null +++ b/libraries/ZWidget/src/systemdialogs/save_file_dialog.cpp @@ -0,0 +1,263 @@ + +#include "systemdialogs/save_file_dialog.h" +#include "core/widget.h" +#include "window/window.h" +#include + +#if defined(WIN32) +#include + +namespace +{ + static std::string from_utf16(const std::wstring& str) + { + if (str.empty()) return {}; + int needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0, nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + std::string result; + result.resize(needed); + needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size(), nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + return result; + } + + static std::wstring to_utf16(const std::string& str) + { + if (str.empty()) return {}; + int needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + std::wstring result; + result.resize(needed); + needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size()); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + return result; + } + + template + class ComPtr + { + public: + ComPtr() { Ptr = nullptr; } + ComPtr(const ComPtr& other) { Ptr = other.Ptr; if (Ptr) Ptr->AddRef(); } + ComPtr(ComPtr&& move) { Ptr = move.Ptr; move.Ptr = nullptr; } + ~ComPtr() { reset(); } + ComPtr& operator=(const ComPtr& other) { if (this != &other) { if (Ptr) Ptr->Release(); Ptr = other.Ptr; if (Ptr) Ptr->AddRef(); } return *this; } + void reset() { if (Ptr) Ptr->Release(); Ptr = nullptr; } + T* get() { return Ptr; } + static IID GetIID() { return __uuidof(T); } + void** InitPtr() { return (void**)TypedInitPtr(); } + T** TypedInitPtr() { reset(); return &Ptr; } + operator T* () const { return Ptr; } + T* operator ->() const { return Ptr; } + T* Ptr; + }; +} + +class SaveFileDialogImpl : public SaveFileDialog +{ +public: + SaveFileDialogImpl(Widget* owner) : owner(owner) + { + } + + Widget* owner = nullptr; + + std::string filename; + std::string initial_directory; + std::string initial_filename; + std::string title; + std::vector filenames; + + struct Filter + { + std::string description; + std::string extension; + }; + std::vector filters; + int filterindex = 0; + std::string defaultext; + + bool Show() override + { + std::wstring title16 = to_utf16(title); + std::wstring initial_directory16 = to_utf16(initial_directory); + + HRESULT result; + ComPtr save_dialog; + + result = CoCreateInstance(CLSID_FileSaveDialog, nullptr, CLSCTX_ALL, save_dialog.GetIID(), save_dialog.InitPtr()); + throw_if_failed(result, "CoCreateInstance(FileSaveDialog) failed"); + + result = save_dialog->SetTitle(title16.c_str()); + throw_if_failed(result, "IFileSaveDialog.SetTitle failed"); + + if (!initial_filename.empty()) + { + result = save_dialog->SetFileName(to_utf16(initial_filename).c_str()); + throw_if_failed(result, "IFileSaveDialog.SetFileName failed"); + } + + FILEOPENDIALOGOPTIONS options = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST; + result = save_dialog->SetOptions(options); + throw_if_failed(result, "IFileSaveDialog.SetOptions() failed"); + + if (!filters.empty()) + { + std::vector filterspecs(filters.size()); + std::vector descriptions(filters.size()); + std::vector extensions(filters.size()); + for (size_t i = 0; i < filters.size(); i++) + { + descriptions[i] = to_utf16(filters[i].description); + extensions[i] = to_utf16(filters[i].extension); + COMDLG_FILTERSPEC& spec = filterspecs[i]; + spec.pszName = descriptions[i].c_str(); + spec.pszSpec = extensions[i].c_str(); + } + result = save_dialog->SetFileTypes((UINT)filterspecs.size(), filterspecs.data()); + throw_if_failed(result, "IFileOpenDialog.SetFileTypes() failed"); + + if ((size_t)filterindex < filters.size()) + { + result = save_dialog->SetFileTypeIndex(filterindex); + throw_if_failed(result, "IFileOpenDialog.SetFileTypeIndex() failed"); + } + } + + if (!defaultext.empty()) + { + result = save_dialog->SetDefaultExtension(to_utf16(defaultext).c_str()); + throw_if_failed(result, "IFileOpenDialog.SetDefaultExtension() failed"); + } + + if (initial_directory16.length() > 0) + { + LPITEMIDLIST item_id_list = nullptr; + SFGAOF flags = 0; + result = SHParseDisplayName(initial_directory16.c_str(), nullptr, &item_id_list, SFGAO_FILESYSTEM, &flags); + throw_if_failed(result, "SHParseDisplayName failed"); + + ComPtr folder_item; + result = SHCreateShellItem(nullptr, nullptr, item_id_list, folder_item.TypedInitPtr()); + ILFree(item_id_list); + throw_if_failed(result, "SHCreateItemFromParsingName failed"); + + /* This code requires Windows Vista or newer: + ComPtr folder_item; + result = SHCreateItemFromParsingName(initial_directory16.c_str(), nullptr, folder_item.GetIID(), folder_item.InitPtr()); + throw_if_failed(result, "SHCreateItemFromParsingName failed"); + */ + + if (folder_item) + { + result = save_dialog->SetFolder(folder_item); + throw_if_failed(result, "IFileSaveDialog.SetFolder failed"); + } + } + + if (owner && owner->Window()) + result = save_dialog->Show((HWND)owner->Window()->GetNativeHandle()); + else + result = save_dialog->Show(0); + + if (SUCCEEDED(result)) + { + ComPtr chosen_folder; + result = save_dialog->GetResult(chosen_folder.TypedInitPtr()); + throw_if_failed(result, "IFileSaveDialog.GetResult failed"); + + WCHAR* buffer = nullptr; + result = chosen_folder->GetDisplayName(SIGDN_FILESYSPATH, &buffer); + throw_if_failed(result, "IShellItem.GetDisplayName failed"); + + std::wstring output16; + if (buffer) + { + try + { + output16 = buffer; + } + catch (...) + { + CoTaskMemFree(buffer); + throw; + } + } + + CoTaskMemFree(buffer); + filename = from_utf16(output16); + return true; + } + else + { + return false; + } + } + + std::string Filename() const override + { + return filename; + } + + void SetFilename(const std::string& filename) override + { + initial_filename = filename; + } + + void AddFilter(const std::string& filter_description, const std::string& filter_extension) override + { + Filter f; + f.description = filter_description; + f.extension = filter_extension; + filters.push_back(std::move(f)); + } + + void ClearFilters() override + { + filters.clear(); + } + + void SetFilterIndex(int filter_index) override + { + filterindex = filter_index; + } + + void SetInitialDirectory(const std::string& path) override + { + initial_directory = path; + } + + void SetTitle(const std::string& newtitle) override + { + title = newtitle; + } + + void SetDefaultExtension(const std::string& extension) override + { + defaultext = extension; + } + + void throw_if_failed(HRESULT result, const std::string& error) + { + if (FAILED(result)) + throw std::runtime_error(error); + } +}; + +std::unique_ptr SaveFileDialog::Create(Widget* owner) +{ + return std::make_unique(owner); +} + +#else + +std::unique_ptr SaveFileDialog::Create(Widget* owner) +{ + return {}; +} + +#endif diff --git a/libraries/ZWidget/src/widgets/checkboxlabel/checkboxlabel.cpp b/libraries/ZWidget/src/widgets/checkboxlabel/checkboxlabel.cpp new file mode 100644 index 0000000000..77c1bd6458 --- /dev/null +++ b/libraries/ZWidget/src/widgets/checkboxlabel/checkboxlabel.cpp @@ -0,0 +1,101 @@ + +#include "widgets/checkboxlabel/checkboxlabel.h" + +CheckboxLabel::CheckboxLabel(Widget* parent) : Widget(parent) +{ + SetStyleClass("checkbox-label"); +} + +void CheckboxLabel::SetText(const std::string& value) +{ + if (text != value) + { + text = value; + Update(); + } +} + +const std::string& CheckboxLabel::GetText() const +{ + return text; +} + +void CheckboxLabel::SetChecked(bool value) +{ + if (value != checked) + { + checked = value; + Update(); + } +} + +bool CheckboxLabel::GetChecked() const +{ + return checked; +} + +double CheckboxLabel::GetPreferredHeight() const +{ + return 20.0; +} + +void CheckboxLabel::OnPaint(Canvas* canvas) +{ + // To do: add and use GetStyleImage for the checkbox + + double center = GridFitPoint(GetHeight() * 0.5); + double borderwidth = GridFitSize(1.0); + double outerboxsize = GridFitSize(10.0); + double innerboxsize = outerboxsize - 2.0 * borderwidth; + double checkedsize = innerboxsize - 2.0 * borderwidth; + + if (checked) + { + canvas->fillRect(Rect::xywh(0.0, center - 6.0 * borderwidth, outerboxsize, outerboxsize), GetStyleColor("checked-outer-border-color")); + canvas->fillRect(Rect::xywh(1.0 * borderwidth, center - 5.0 * borderwidth, innerboxsize, innerboxsize), GetStyleColor("checked-inner-border-color")); + canvas->fillRect(Rect::xywh(2.0 * borderwidth, center - 4.0 * borderwidth, checkedsize, checkedsize), GetStyleColor("checked-color")); + } + else + { + canvas->fillRect(Rect::xywh(0.0, center - 6.0 * borderwidth, outerboxsize, outerboxsize), GetStyleColor("unchecked-outer-border-color")); + canvas->fillRect(Rect::xywh(1.0 * borderwidth, center - 5.0 * borderwidth, innerboxsize, innerboxsize), GetStyleColor("unchecked-inner-border-color")); + } + + canvas->drawText(Point(14.0, GetHeight() - 5.0), GetStyleColor("color"), text); +} + +bool CheckboxLabel::OnMouseDown(const Point& pos, InputKey key) +{ + mouseDownActive = true; + SetFocus(); + return true; +} + +bool CheckboxLabel::OnMouseUp(const Point& pos, InputKey key) +{ + if (mouseDownActive) + { + Toggle(); + } + mouseDownActive = false; + return true; +} + +void CheckboxLabel::OnMouseLeave() +{ + mouseDownActive = false; +} + +void CheckboxLabel::OnKeyUp(InputKey key) +{ + if (key == InputKey::Space) + Toggle(); +} + +void CheckboxLabel::Toggle() +{ + bool oldchecked = checked; + checked = radiostyle? true : !checked; + Update(); + if (checked != oldchecked && FuncChanged) FuncChanged(checked); +} diff --git a/libraries/ZWidget/src/widgets/imagebox/imagebox.cpp b/libraries/ZWidget/src/widgets/imagebox/imagebox.cpp new file mode 100644 index 0000000000..37253c8578 --- /dev/null +++ b/libraries/ZWidget/src/widgets/imagebox/imagebox.cpp @@ -0,0 +1,39 @@ + +#include "widgets/imagebox/imagebox.h" + +ImageBox::ImageBox(Widget* parent) : Widget(parent) +{ +} + +double ImageBox::GetPreferredWidth() const +{ + if (image) + return (double)image->GetWidth(); + else + return 0.0; +} + +double ImageBox::GetPreferredHeight() const +{ + if (image) + return (double)image->GetHeight(); + else + return 0.0; +} + +void ImageBox::SetImage(std::shared_ptr newImage) +{ + if (image != newImage) + { + image = newImage; + Update(); + } +} + +void ImageBox::OnPaint(Canvas* canvas) +{ + if (image) + { + canvas->drawImage(image, Point((GetWidth() - (double)image->GetWidth()) * 0.5, (GetHeight() - (double)image->GetHeight()) * 0.5)); + } +} diff --git a/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp b/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp new file mode 100644 index 0000000000..7faa25d906 --- /dev/null +++ b/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp @@ -0,0 +1,1182 @@ + +#include "widgets/lineedit/lineedit.h" +#include "core/utf8reader.h" +#include "core/colorf.h" +#include + +LineEdit::LineEdit(Widget* parent) : Widget(parent) +{ + SetStyleClass("lineedit"); + + timer = new Timer(this); + timer->FuncExpired = [=]() { OnTimerExpired(); }; + + scroll_timer = new Timer(this); + scroll_timer->FuncExpired = [=]() { OnScrollTimerExpired(); }; + + SetCursor(StandardCursor::ibeam); +} + +LineEdit::~LineEdit() +{ +} + +bool LineEdit::IsReadOnly() const +{ + return readonly; +} + +LineEdit::Alignment LineEdit::GetAlignment() const +{ + return align_left; +} + +bool LineEdit::IsLowercase() const +{ + return lowercase; +} + +bool LineEdit::IsUppercase() const +{ + return uppercase; +} + +bool LineEdit::IsPasswordMode() const +{ + return password_mode; +} + +int LineEdit::GetMaxLength() const +{ + return max_length; +} + +std::string LineEdit::GetText() const +{ + return text; +} + +int LineEdit::GetTextInt() const +{ + return std::atoi(text.c_str()); +} + +float LineEdit::GetTextFloat() const +{ + return (float)std::atof(text.c_str()); +} + +std::string LineEdit::GetSelection() const +{ + int start = std::min(selection_start, selection_start + selection_length); + return text.substr(start, std::abs(selection_length)); +} + +int LineEdit::GetSelectionStart() const +{ + return selection_start; +} + +int LineEdit::GetSelectionLength() const +{ + return selection_length; +} + +int LineEdit::GetCursorPos() const +{ + return cursor_pos; +} + +Size LineEdit::GetTextSize() +{ + Canvas* canvas = GetCanvas(); + return GetVisualTextSize(canvas); +} + +Size LineEdit::GetTextSize(const std::string& str) +{ + Canvas* canvas = GetCanvas(); + return canvas->measureText(str).size(); +} + +double LineEdit::GetPreferredContentWidth() +{ + return GetTextSize().width; +} + +double LineEdit::GetPreferredContentHeight(double width) +{ + return GetTextSize().height; +} + +void LineEdit::SelectAll() +{ + SetTextSelection(0, (int)text.size()); + Update(); +} + +void LineEdit::SetReadOnly(bool enable) +{ + if (readonly != enable) + { + readonly = enable; + Update(); + } +} + +void LineEdit::SetAlignment(Alignment newalignment) +{ + if (alignment != newalignment) + { + alignment = newalignment; + Update(); + } +} + +void LineEdit::SetLowercase(bool enable) +{ + if (lowercase != enable) + { + lowercase = enable; + text = ToLower(text); + Update(); + } +} + +void LineEdit::SetUppercase(bool enable) +{ + if (uppercase != enable) + { + uppercase = enable; + text = ToUpper(text); + Update(); + } +} + +void LineEdit::SetPasswordMode(bool enable) +{ + if (password_mode != enable) + { + password_mode = enable; + Update(); + } +} + +void LineEdit::SetMaxLength(int length) +{ + if (max_length != length) + { + max_length = length; + if ((int)text.length() > length) + { + if (FuncBeforeEditChanged) + FuncBeforeEditChanged(); + text = text.substr(0, length); + if (FuncAfterEditChanged) + FuncAfterEditChanged(); + } + Update(); + } +} + +void LineEdit::SetText(const std::string& newtext) +{ + if (lowercase) + text = ToLower(newtext); + else if (uppercase) + text = ToUpper(newtext); + else + text = newtext; + + clip_start_offset = 0; + UpdateTextClipping(); + SetCursorPos((int)text.size()); + SetTextSelection(0, 0); + Update(); +} + +void LineEdit::SetTextInt(int number) +{ + text = std::to_string(number); + clip_start_offset = 0; + UpdateTextClipping(); + SetCursorPos((int)text.size()); + SetTextSelection(0, 0); + Update(); +} + +void LineEdit::SetTextFloat(float number, int num_decimal_places) +{ + text = ToFixed(number, num_decimal_places); + clip_start_offset = 0; + UpdateTextClipping(); + SetCursorPos((int)text.size()); + SetTextSelection(0, 0); + Update(); +} + +void LineEdit::SetSelection(int pos, int length) +{ + //don't call FuncSelectionChanged() here, because this + //member is for public usage + selection_start = pos; + selection_length = length; + Update(); +} + +void LineEdit::ClearSelection() +{ + //don't call FuncSelectionChanged() here, because this + //member is for public usage + SetSelection(0, 0); + Update(); +} + +void LineEdit::DeleteSelectedText() +{ + if (GetSelectionLength() == 0) + return; + + int sel_start = selection_start; + int sel_end = selection_start + selection_length; + if (sel_start > sel_end) + std::swap(sel_start, sel_end); + + text = text.substr(0, sel_start) + text.substr(sel_end, text.size()); + cursor_pos = sel_start; + SetTextSelection(0, 0); + int old_pos = GetCursorPos(); + SetCursorPos(0); + SetCursorPos(old_pos); +} + +void LineEdit::SetCursorPos(int pos) +{ + cursor_pos = pos; + UpdateTextClipping(); + Update(); +} + +void LineEdit::SetInputMask(const std::string& mask) +{ + input_mask = mask; +} + +void LineEdit::SetNumericMode(bool enable, bool decimals) +{ + numeric_mode = enable; + numeric_mode_decimals = decimals; +} + +void LineEdit::SetDecimalCharacter(const std::string& new_decimal_char) +{ + decimal_char = new_decimal_char; +} + +void LineEdit::SetSelectAllOnFocusGain(bool enable) +{ + select_all_on_focus_gain = enable; +} + +void LineEdit::OnMouseMove(const Point& pos) +{ + if (mouse_selecting && !ignore_mouse_events) + { + if (pos.x < 0.0 || pos.x >= GetWidth()) + { + if (pos.x < 0.0) + mouse_moves_left = true; + else + mouse_moves_left = false; + + if (!readonly) + scroll_timer->Start(50, true); + } + else + { + scroll_timer->Stop(); + cursor_pos = GetCharacterIndex(pos.x); + SetSelectionLength(cursor_pos - selection_start); + Update(); + } + } +} + +bool LineEdit::OnMouseDown(const Point& pos, InputKey key) +{ + if (key == InputKey::LeftMouse) + { + if (HasFocus()) + { + CaptureMouse(); + mouse_selecting = true; + cursor_pos = GetCharacterIndex(pos.x); + SetTextSelection(cursor_pos, 0); + } + else + { + SetFocus(); + } + Update(); + } + return true; +} + +bool LineEdit::OnMouseDoubleclick(const Point& pos, InputKey key) +{ + return true; +} + +bool LineEdit::OnMouseUp(const Point& pos, InputKey key) +{ + if (mouse_selecting && key == InputKey::LeftMouse) + { + if (ignore_mouse_events) // This prevents text selection from changing from what was set when focus was gained. + { + ReleaseMouseCapture(); + ignore_mouse_events = false; + mouse_selecting = false; + } + else + { + scroll_timer->Stop(); + ReleaseMouseCapture(); + mouse_selecting = false; + int sel_end = GetCharacterIndex(pos.x); + SetSelectionLength(sel_end - selection_start); + cursor_pos = sel_end; + SetFocus(); + Update(); + } + } + return true; +} + +void LineEdit::OnKeyChar(std::string chars) +{ + if (FuncFilterKeyChar) + { + chars = FuncFilterKeyChar(chars); + if (chars.empty()) + return; + } + + if (!chars.empty() && !(chars[0] >= 0 && chars[0] < 32)) + { + if (FuncBeforeEditChanged) + FuncBeforeEditChanged(); + + DeleteSelectedText(); + if (input_mask.empty()) + { + if (numeric_mode) + { + // '-' can only be added once, and only as the first character. + if (chars == "-" && cursor_pos == 0 && text.find("-") == std::string::npos) + { + if (InsertText(cursor_pos, chars)) + cursor_pos += (int)chars.size(); + } + else if (numeric_mode_decimals && chars == decimal_char && cursor_pos > 0) // add decimal char + { + if (text.find(decimal_char) == std::string::npos) // allow only one decimal char. + { + if (InsertText(cursor_pos, chars)) + cursor_pos += (int)chars.size(); + } + } + else if (numeric_mode_characters.find(chars) != std::string::npos) // 0-9 + { + if (InsertText(cursor_pos, chars)) + cursor_pos += (int)chars.size(); + } + } + else + { + // not in any special mode, just insert the string. + if (InsertText(cursor_pos, chars)) + cursor_pos += (int)chars.size(); + } + } + else + { + if (InputMaskAcceptsInput(cursor_pos, chars)) + { + if (InsertText(cursor_pos, chars)) + cursor_pos += (int)chars.size(); + } + } + UpdateTextClipping(); + + if (FuncAfterEditChanged) + FuncAfterEditChanged(); + } +} + +void LineEdit::OnKeyDown(InputKey key) +{ + if (FuncIgnoreKeyDown && FuncIgnoreKeyDown(key)) + return; + + if (key == InputKey::Enter) + { + if (FuncEnterPressed) + FuncEnterPressed(); + return; + } + + if (!readonly) // Do not flash cursor when readonly + { + cursor_blink_visible = true; + timer->Start(500); // don't blink cursor when moving or typing. + } + + if (key == InputKey::Enter || key == InputKey::Escape || key == InputKey::Tab) + { + // Do not consume these. + return; + } + else if (key == InputKey::A && GetKeyState(InputKey::Ctrl)) + { + // select all + SetTextSelection(0, (int)text.size()); + cursor_pos = selection_length; + UpdateTextClipping(); + Update(); + } + else if (key == InputKey::C && GetKeyState(InputKey::Ctrl)) + { + if (!password_mode) // Do not allow copying the password to clipboard + { + std::string str = GetSelection(); + SetClipboardText(str); + } + } + else if (readonly) + { + // Do not consume messages on read only component (only allow CTRL-A and CTRL-C) + return; + } + else if (key == InputKey::Left) + { + Move(-1, GetKeyState(InputKey::Ctrl), GetKeyState(InputKey::Shift)); + } + else if (key == InputKey::Right) + { + Move(1, GetKeyState(InputKey::Ctrl), GetKeyState(InputKey::Shift)); + } + else if (key == InputKey::Backspace) + { + Backspace(); + UpdateTextClipping(); + } + else if (key == InputKey::Delete) + { + Del(); + UpdateTextClipping(); + } + else if (key == InputKey::Home) + { + SetSelectionStart(cursor_pos); + cursor_pos = 0; + if (GetKeyState(InputKey::Shift)) + SetSelectionLength(-selection_start); + else + SetTextSelection(0, 0); + UpdateTextClipping(); + Update(); + } + else if (key == InputKey::End) + { + SetSelectionStart(cursor_pos); + cursor_pos = (int)text.size(); + if (GetKeyState(InputKey::Shift)) + SetSelectionLength((int)text.size() - selection_start); + else + SetTextSelection(0, 0); + UpdateTextClipping(); + Update(); + } + else if (key == InputKey::X && GetKeyState(InputKey::Ctrl)) + { + std::string str = GetSelection(); + DeleteSelectedText(); + SetClipboardText(str); + UpdateTextClipping(); + } + else if (key == InputKey::V && GetKeyState(InputKey::Ctrl)) + { + std::string str = GetClipboardText(); + std::string::const_iterator end_str = std::remove(str.begin(), str.end(), '\n'); + str.resize(end_str - str.begin()); + end_str = std::remove(str.begin(), str.end(), '\r'); + str.resize(end_str - str.begin()); + DeleteSelectedText(); + + if (input_mask.empty()) + { + if (numeric_mode) + { + std::string present_text = GetText(); + + bool present_minus = present_text.find('-') != std::string::npos; + bool str_minus = str.find('-') != std::string::npos; + + if (!present_minus || !str_minus) + { + if ((!present_minus && !str_minus) || //if no minus found + (str_minus && cursor_pos == 0 && str[0] == '-') || //if there's minus in text to paste + (present_minus && cursor_pos > 0)) //if there's minus in the beginning of control's text + { + if (numeric_mode_decimals) + { + std::string::size_type decimal_point_pos; + if ((decimal_point_pos = str.find_first_not_of(numeric_mode_characters, str[0] == '-' ? 1 : 0)) == std::string::npos) //no decimal char inside string to paste + { //we don't look at the position of decimal char inside of text in the textbox, if it's present + if (InsertText(cursor_pos, str)) + SetCursorPos(cursor_pos + (int)str.length()); + } + else + { + if (present_text.find(decimal_char) == std::string::npos && + str[decimal_point_pos] == decimal_char[0] && + str.find_first_not_of(numeric_mode_characters, decimal_point_pos + 1) == std::string::npos) //allow only one decimal char in the string to paste + { + if (InsertText(cursor_pos, str)) + SetCursorPos(cursor_pos + (int)str.length()); + } + } + } + else + { + if (str.find_first_not_of(numeric_mode_characters, str[0] == '-' ? 1 : 0) == std::string::npos) + { + if (InsertText(cursor_pos, str)) + SetCursorPos(cursor_pos + (int)str.length()); + } + } + } + } + } + else + { + if (InsertText(cursor_pos, str)) + SetCursorPos(cursor_pos + (int)str.length()); + } + } + else + { + if (InputMaskAcceptsInput(cursor_pos, str)) + { + if (InsertText(cursor_pos, str)) + SetCursorPos(cursor_pos + (int)str.length()); + } + } + + UpdateTextClipping(); + } + else if (GetKeyState(InputKey::Ctrl) && key == InputKey::Z) + { + if (!readonly) + { + std::string tmp = undo_info.undo_text; + undo_info.undo_text = GetText(); + SetText(tmp); + } + } + else if (key == InputKey::Shift) + { + if (selection_start == -1) + SetTextSelection(cursor_pos, 0); + } + + if (FuncAfterEditChanged) + FuncAfterEditChanged(); +} + +void LineEdit::OnKeyUp(InputKey key) +{ +} + +void LineEdit::OnSetFocus() +{ + if (!readonly) + timer->Start(500); + if (select_all_on_focus_gain) + SelectAll(); + ignore_mouse_events = true; + cursor_pos = (int)text.length(); + + Update(); + + if (FuncFocusGained) + FuncFocusGained(); +} + +void LineEdit::OnLostFocus() +{ + timer->Stop(); + SetTextSelection(0, 0); + + Update(); + + if (FuncFocusLost) + FuncFocusLost(); +} + +void LineEdit::Move(int steps, bool ctrl, bool shift) +{ + if (shift && selection_length == 0) + SetSelectionStart(cursor_pos); + + // Jump over words if control is pressed. + if (ctrl) + { + if (steps < 0) + steps = FindPreviousBreakCharacter(cursor_pos - 1) - cursor_pos; + else + steps = FindNextBreakCharacter(cursor_pos + 1) - cursor_pos; + + cursor_pos += steps; + if (cursor_pos < 0) + cursor_pos = 0; + if (cursor_pos > (int)text.size()) + cursor_pos = (int)text.size(); + } + else + { + UTF8Reader utf8_reader(text.data(), text.length()); + utf8_reader.set_position(cursor_pos); + if (steps > 0) + { + for (int i = 0; i < steps; i++) + utf8_reader.next(); + } + else if (steps < 0) + { + for (int i = 0; i < -steps; i++) + utf8_reader.prev(); + } + + cursor_pos = (int)utf8_reader.position(); + } + + + // Clear the selection if a cursor key is pressed but shift isn't down. + if (shift) + SetSelectionLength(cursor_pos - selection_start); + else + SetTextSelection(-1, 0); + + UpdateTextClipping(); + + Update(); + + undo_info.first_text_insert = true; +} + +bool LineEdit::InsertText(int pos, const std::string& str) +{ + undo_info.first_erase = false; + if (undo_info.first_text_insert) + { + undo_info.undo_text = GetText(); + undo_info.first_text_insert = false; + } + + // checking if insert exceeds max length + if (UTF8Reader::utf8_length(text) + UTF8Reader::utf8_length(str) > max_length) + { + return false; + } + + if (lowercase) + text.insert(pos, ToLower(str)); + else if (uppercase) + text.insert(pos, ToUpper(str)); + else + text.insert(pos, str); + + UpdateTextClipping(); + Update(); + return true; +} + +void LineEdit::Backspace() +{ + if (undo_info.first_erase) + { + undo_info.first_erase = false; + undo_info.undo_text = GetText(); + } + + if (GetSelectionLength() != 0) + { + DeleteSelectedText(); + Update(); + } + else + { + if (cursor_pos > 0) + { + UTF8Reader utf8_reader(text.data(), text.length()); + utf8_reader.set_position(cursor_pos); + utf8_reader.prev(); + size_t length = utf8_reader.char_length(); + text.erase(cursor_pos - length, length); + cursor_pos -= (int)length; + Update(); + } + } + + int old_pos = GetCursorPos(); + SetCursorPos(0); + SetCursorPos(old_pos); +} + +void LineEdit::Del() +{ + if (undo_info.first_erase) + { + undo_info.first_erase = false; + undo_info.undo_text = GetText(); + } + + if (GetSelectionLength() != 0) + { + DeleteSelectedText(); + Update(); + } + else + { + if (cursor_pos < (int)text.size()) + { + UTF8Reader utf8_reader(text.data(), text.length()); + utf8_reader.set_position(cursor_pos); + size_t length = utf8_reader.char_length(); + text.erase(cursor_pos, length); + Update(); + } + } +} + +int LineEdit::GetCharacterIndex(double mouse_x) +{ + if (text.size() <= 1) + { + return (int)text.size(); + } + + Canvas* canvas = GetCanvas(); + UTF8Reader utf8_reader(text.data(), text.length()); + + int seek_start = clip_start_offset; + int seek_end = (int)text.size(); + int seek_center = (seek_start + seek_end) / 2; + + //fast search + while (true) + { + utf8_reader.set_position(seek_center); + utf8_reader.move_to_leadbyte(); + + seek_center = (int)utf8_reader.position(); + + Size text_size = GetVisualTextSize(canvas, clip_start_offset, seek_center - clip_start_offset); + + if (text_size.width > mouse_x) + seek_end = seek_center; + else + seek_start = seek_center; + + if (seek_end - seek_start < 7) + break; //go to accurate search + + seek_center = (seek_start + seek_end) / 2; + } + + utf8_reader.set_position(seek_start); + utf8_reader.move_to_leadbyte(); + + //accurate search + while (true) + { + seek_center = (int)utf8_reader.position(); + + Size text_size = GetVisualTextSize(canvas, clip_start_offset, seek_center - clip_start_offset); + if (text_size.width > mouse_x || utf8_reader.is_end()) + break; + + utf8_reader.next(); + } + + return seek_center; +} + +void LineEdit::UpdateTextClipping() +{ + Canvas* canvas = GetCanvas(); + if (!canvas) + return; + + Size text_size = GetVisualTextSize(canvas, clip_start_offset, (int)text.size() - clip_start_offset); + + if (cursor_pos < clip_start_offset) + clip_start_offset = cursor_pos; + + Rect cursor_rect = GetCursorRect(); + + UTF8Reader utf8_reader(text.data(), text.length()); + double width = GetWidth(); + while (cursor_rect.x + cursor_rect.width > width) + { + utf8_reader.set_position(clip_start_offset); + utf8_reader.next(); + clip_start_offset = (int)utf8_reader.position(); + if (clip_start_offset == text.size()) + break; + cursor_rect = GetCursorRect(); + } + + // Get number of chars of current text fitting in the lineedit. + int search_upper = (int)text.size(); + int search_lower = clip_start_offset; + + while (true) + { + int midpoint = (search_lower + search_upper) / 2; + + utf8_reader.set_position(midpoint); + utf8_reader.move_to_leadbyte(); + if (midpoint != utf8_reader.position()) + utf8_reader.next(); + midpoint = (int)utf8_reader.position(); + + if (midpoint == search_lower || midpoint == search_upper) + break; + + Size midpoint_size = GetVisualTextSize(canvas, clip_start_offset, midpoint - clip_start_offset); + + if (width < midpoint_size.width) + search_upper = midpoint; + else + search_lower = midpoint; + } + clip_end_offset = search_upper; + + if (cursor_rect.x < 0.0) + { + clip_start_offset = cursor_pos; + } +} + +Rect LineEdit::GetCursorRect() +{ + Canvas* canvas = GetCanvas(); + + int substr_end = cursor_pos - clip_start_offset; + if (substr_end < 0) + substr_end = 0; + + std::string clipped_text = text.substr(clip_start_offset, substr_end); + + if (password_mode) + { + // If we are in password mode, we gonna return the right characters + clipped_text = CreatePassword(UTF8Reader::utf8_length(clipped_text)); + } + + Size text_size_before_cursor = canvas->measureText(clipped_text).size(); + + Rect cursor_rect; + cursor_rect.x = text_size_before_cursor.width; + cursor_rect.width = 1.0f; + + cursor_rect.y = vertical_text_align.top; + cursor_rect.height = vertical_text_align.bottom - vertical_text_align.top; + + return cursor_rect; +} + +Rect LineEdit::GetSelectionRect() +{ + Canvas* canvas = GetCanvas(); + + // text before selection: + + std::string txt_before = GetVisibleTextBeforeSelection(); + Size text_size_before_selection = canvas->measureText(txt_before).size(); + + // selection text: + std::string txt_selected = GetVisibleSelectedText(); + Size text_size_selection = canvas->measureText(txt_selected).size(); + + Rect selection_rect; + selection_rect.x = text_size_before_selection.width; + selection_rect.width = text_size_selection.width; + selection_rect.y = vertical_text_align.top; + selection_rect.height = vertical_text_align.bottom - vertical_text_align.top; + return selection_rect; +} + +int LineEdit::FindNextBreakCharacter(int search_start) +{ + if (search_start >= int(text.size()) - 1) + return (int)text.size(); + + size_t pos = text.find_first_of(break_characters, search_start); + if (pos == std::string::npos) + return (int)text.size(); + return (int)pos; +} + +int LineEdit::FindPreviousBreakCharacter(int search_start) +{ + if (search_start <= 0) + return 0; + size_t pos = text.find_last_of(break_characters, search_start); + if (pos == std::string::npos) + return 0; + return (int)pos; +} + +void LineEdit::OnTimerExpired() +{ + if (!IsVisible()) + { + timer->Stop(); + return; + } + + if (cursor_blink_visible) + timer->Start(500); + else + timer->Start(500); + + cursor_blink_visible = !cursor_blink_visible; + Update(); +} + +void LineEdit::OnGeometryChanged() +{ + Canvas* canvas = GetCanvas(); + + vertical_text_align = canvas->verticalTextAlign(); + + clip_start_offset = 0; + cursor_pos = 0; + UpdateTextClipping(); +} + +std::string LineEdit::GetVisibleTextBeforeSelection() +{ + std::string ret; + int sel_start = std::min(selection_start, selection_start + selection_length); + int start = std::min(sel_start, clip_start_offset); + + if (start < clip_start_offset) + return ret; + + int end = std::min(sel_start, clip_end_offset); + + ret = text.substr(start, end - start); + + // If we are in password mode, we gonna return the right characters + if (password_mode) + ret = CreatePassword(UTF8Reader::utf8_length(ret)); + + return ret; +} + +std::string LineEdit::GetVisibleSelectedText() +{ + std::string ret; + + if (selection_length == 0) + return ret; + + int sel_start = std::min(selection_start, selection_start + selection_length); + int sel_end = std::max(selection_start, selection_start + selection_length); + int end = std::min(clip_end_offset, sel_end); + int start = std::max(clip_start_offset, sel_start); + + if (start > end) + return ret; + + if (start == end) + return ret; + + ret = text.substr(start, end - start); + + // If we are in password mode, we gonna return the right characters + if (password_mode) + ret = CreatePassword(UTF8Reader::utf8_length(ret)); + + return ret; +} + +void LineEdit::SetSelectionStart(int start) +{ + if (FuncSelectionChanged && selection_length && selection_start != start) + FuncSelectionChanged(); + + selection_start = start; +} + +void LineEdit::SetSelectionLength(int length) +{ + if (FuncSelectionChanged && selection_length != length) + FuncSelectionChanged(); + + selection_length = length; +} + +void LineEdit::SetTextSelection(int start, int length) +{ + if (FuncSelectionChanged && (selection_length != length || (selection_length && selection_start != start))) + FuncSelectionChanged(); + + selection_start = start; + selection_length = length; +} + +std::string LineEdit::GetVisibleTextAfterSelection() +{ + // returns the whole visible string if there is no selection. + std::string ret; + + int sel_end = std::max(selection_start, selection_start + selection_length); + int start = std::max(clip_start_offset, sel_end); + + int end = clip_end_offset; + if (start > end) + return ret; + + if (clip_end_offset == sel_end) + return ret; + + if (sel_end <= 0) + return ret; + else + { + ret = text.substr(start, end - start); + // If we are in password mode, we gonna return the right characters + if (password_mode) + ret = CreatePassword(UTF8Reader::utf8_length(ret)); + + return ret; + } +} + +void LineEdit::OnPaint(Canvas* canvas) +{ + std::string txt_before = GetVisibleTextBeforeSelection(); + std::string txt_selected = GetVisibleSelectedText(); + std::string txt_after = GetVisibleTextAfterSelection(); + + if (txt_before.empty() && txt_selected.empty() && txt_after.empty()) + { + txt_after = text.substr(clip_start_offset, clip_end_offset - clip_start_offset); + + // If we are in password mode, we gonna return the right characters + if (password_mode) + txt_after = CreatePassword(UTF8Reader::utf8_length(txt_after)); + } + + Size size_before = canvas->measureText(txt_before).size(); + Size size_selected = canvas->measureText(txt_selected).size(); + + if (!txt_selected.empty()) + { + // Draw selection box. + Rect selection_rect = GetSelectionRect(); + canvas->fillRect(selection_rect, HasFocus() ? GetStyleColor("selection-color") : GetStyleColor("no-focus-selection-color")); + } + + // Draw text before selection + if (!txt_before.empty()) + { + canvas->drawText(Point(0.0, canvas->verticalTextAlign().baseline), GetStyleColor("color"), txt_before); + } + if (!txt_selected.empty()) + { + canvas->drawText(Point(size_before.width, canvas->verticalTextAlign().baseline), GetStyleColor("color"), txt_selected); + } + if (!txt_after.empty()) + { + canvas->drawText(Point(size_before.width + size_selected.width, canvas->verticalTextAlign().baseline), GetStyleColor("color"), txt_after); + } + + // draw cursor + if (HasFocus()) + { + if (cursor_blink_visible) + { + Rect cursor_rect = GetCursorRect(); + canvas->fillRect(cursor_rect, GetStyleColor("color")); + } + } +} + +void LineEdit::OnScrollTimerExpired() +{ + if (mouse_moves_left) + Move(-1, false, false); + else + Move(1, false, false); +} + +void LineEdit::OnEnableChanged() +{ + bool enabled = IsEnabled(); + + if (!enabled) + { + cursor_blink_visible = false; + timer->Stop(); + } + Update(); +} + +bool LineEdit::InputMaskAcceptsInput(int cursor_pos, const std::string& str) +{ + return str.find_first_not_of(input_mask) == std::string::npos; +} + +std::string LineEdit::CreatePassword(std::string::size_type num_letters) const +{ + return std::string(num_letters, '*'); +} + +Size LineEdit::GetVisualTextSize(Canvas* canvas, int pos, int npos) const +{ + return canvas->measureText(password_mode ? CreatePassword(UTF8Reader::utf8_length(text.substr(pos, npos))) : text.substr(pos, npos)).size(); +} + +Size LineEdit::GetVisualTextSize(Canvas* canvas) const +{ + return canvas->measureText(password_mode ? CreatePassword(UTF8Reader::utf8_length(text)) : text).size(); +} + +std::string LineEdit::ToFixed(float number, int num_decimal_places) +{ + for (int i = 0; i < num_decimal_places; i++) + number *= 10.0f; + std::string val = std::to_string((int)std::round(number)); + if ((int)val.size() < num_decimal_places) + val.resize(num_decimal_places + 1, 0); + return val.substr(0, val.size() - num_decimal_places) + "." + val.substr(val.size() - num_decimal_places); +} + +std::string LineEdit::ToLower(const std::string& text) +{ + return text; +} + +std::string LineEdit::ToUpper(const std::string& text) +{ + return text; +} + +const std::string LineEdit::break_characters = " ::;,.-"; +const std::string LineEdit::numeric_mode_characters = "0123456789"; diff --git a/libraries/ZWidget/src/widgets/listview/listview.cpp b/libraries/ZWidget/src/widgets/listview/listview.cpp new file mode 100644 index 0000000000..9c9704f4cc --- /dev/null +++ b/libraries/ZWidget/src/widgets/listview/listview.cpp @@ -0,0 +1,150 @@ + +#include "widgets/listview/listview.h" +#include "widgets/scrollbar/scrollbar.h" + +ListView::ListView(Widget* parent) : Widget(parent) +{ + SetStyleClass("listview"); + + scrollbar = new Scrollbar(this); + scrollbar->FuncScroll = [=]() { OnScrollbarScroll(); }; +} + +void ListView::AddItem(const std::string& text) +{ + items.push_back(text); + Update(); +} + +void ListView::Activate() +{ + if (OnActivated) + OnActivated(); +} + +void ListView::SetSelectedItem(int index) +{ + if (selectedItem != index && index >= 0 && index < items.size()) + { + selectedItem = index; + if (OnChanged) OnChanged(selectedItem); + Update(); + } +} + +void ListView::ScrollToItem(int index) +{ + double itemHeight = 20.0; + double y = itemHeight * index; + if (y < scrollbar->GetPosition()) + { + scrollbar->SetPosition(y); + } + else if (y + itemHeight > scrollbar->GetPosition() + GetHeight()) + { + scrollbar->SetPosition(std::max(y + itemHeight - GetHeight(), 0.0)); + } +} + +void ListView::OnScrollbarScroll() +{ + Update(); +} + +void ListView::OnGeometryChanged() +{ + double w = GetWidth(); + double h = GetHeight(); + double sw = scrollbar->GetPreferredWidth(); + scrollbar->SetFrameGeometry(Rect::xywh(w - sw, 0.0, sw, h)); + scrollbar->SetRanges(h, items.size() * 20.0); +} + +void ListView::OnPaint(Canvas* canvas) +{ + double y = -scrollbar->GetPosition(); + double x = 2.0; + double w = GetWidth() - scrollbar->GetPreferredWidth() - 2.0; + double h = 20.0; + + Colorf textColor = GetStyleColor("color"); + Colorf selectionColor = GetStyleColor("selection-color"); + + int index = 0; + for (const std::string& item : items) + { + double itemY = y; + if (itemY + h >= 0.0 && itemY < GetHeight()) + { + if (index == selectedItem) + { + canvas->fillRect(Rect::xywh(x - 2.0, itemY, w, h), selectionColor); + } + canvas->drawText(Point(x, y + 15.0), textColor, item); + } + y += h; + index++; + } +} + +bool ListView::OnMouseDown(const Point& pos, InputKey key) +{ + SetFocus(); + + if (key == InputKey::LeftMouse) + { + int index = (int)((pos.y - 5.0 + scrollbar->GetPosition()) / 20.0); + if (index >= 0 && (size_t)index < items.size()) + { + SetSelectedItem(index); + ScrollToItem(selectedItem); + } + } + return true; +} + +bool ListView::OnMouseDoubleclick(const Point& pos, InputKey key) +{ + if (key == InputKey::LeftMouse) + { + Activate(); + } + return true; +} + +bool ListView::OnMouseWheel(const Point& pos, InputKey key) +{ + if (key == InputKey::MouseWheelUp) + { + scrollbar->SetPosition(std::max(scrollbar->GetPosition() - 20.0, 0.0)); + } + else if (key == InputKey::MouseWheelDown) + { + scrollbar->SetPosition(std::min(scrollbar->GetPosition() + 20.0, scrollbar->GetMax())); + } + return true; +} + +void ListView::OnKeyDown(InputKey key) +{ + if (key == InputKey::Down) + { + if (selectedItem + 1 < (int)items.size()) + { + SetSelectedItem(selectedItem + 1); + } + ScrollToItem(selectedItem); + } + else if (key == InputKey::Up) + { + if (selectedItem > 0) + { + SetSelectedItem(selectedItem - 1); + } + ScrollToItem(selectedItem); + } + else if (key == InputKey::Enter) + { + Activate(); + } +} diff --git a/libraries/ZWidget/src/widgets/mainwindow/mainwindow.cpp b/libraries/ZWidget/src/widgets/mainwindow/mainwindow.cpp new file mode 100644 index 0000000000..7a98a2ce59 --- /dev/null +++ b/libraries/ZWidget/src/widgets/mainwindow/mainwindow.cpp @@ -0,0 +1,40 @@ + +#include "widgets/mainwindow/mainwindow.h" +#include "widgets/menubar/menubar.h" +#include "widgets/toolbar/toolbar.h" +#include "widgets/statusbar/statusbar.h" + +MainWindow::MainWindow() : Widget(nullptr, WidgetType::Window) +{ + MenubarWidget = new Menubar(this); + // ToolbarWidget = new Toolbar(this); + StatusbarWidget = new Statusbar(this); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::SetCentralWidget(Widget* widget) +{ + if (CentralWidget != widget) + { + delete CentralWidget; + CentralWidget = widget; + if (CentralWidget) + CentralWidget->SetParent(this); + OnGeometryChanged(); + } +} + +void MainWindow::OnGeometryChanged() +{ + Size s = GetSize(); + + MenubarWidget->SetFrameGeometry(0.0, 0.0, s.width, 32.0); + // ToolbarWidget->SetFrameGeometry(0.0, 32.0, s.width, 36.0); + StatusbarWidget->SetFrameGeometry(0.0, s.height - 32.0, s.width, 32.0); + + if (CentralWidget) + CentralWidget->SetFrameGeometry(0.0, 32.0, s.width, s.height - 32.0 - 32.0); +} diff --git a/libraries/ZWidget/src/widgets/menubar/menubar.cpp b/libraries/ZWidget/src/widgets/menubar/menubar.cpp new file mode 100644 index 0000000000..517128508f --- /dev/null +++ b/libraries/ZWidget/src/widgets/menubar/menubar.cpp @@ -0,0 +1,217 @@ + +#include "widgets/menubar/menubar.h" +#include "core/colorf.h" + +Menubar::Menubar(Widget* parent) : Widget(parent) +{ + SetStyleClass("menubar"); +} + +Menubar::~Menubar() +{ +} + +MenubarItem* Menubar::AddItem(std::string text, std::function onOpen, bool alignRight) +{ + auto item = new MenubarItem(this, text, alignRight); + item->SetOpenCallback(std::move(onOpen)); + menuItems.push_back(item); + OnGeometryChanged(); + return item; +} + +void Menubar::ShowMenu(MenubarItem* item) +{ + CloseMenu(); + if (item->GetOpenCallback()) + { + openMenu = new Menu(this); + openMenu->onCloseMenu = [=]() { CloseMenu(); }; + item->GetOpenCallback()(openMenu); + if (item->AlignRight) + openMenu->SetRightPosition(item->MapToGlobal(Point(item->GetWidth(), item->GetHeight()))); + else + openMenu->SetLeftPosition(item->MapToGlobal(Point(0.0, item->GetHeight()))); + openMenu->Show(); + } +} + +void Menubar::CloseMenu() +{ + //delete openMenu; + //openMenu = nullptr; +} + +void Menubar::OnGeometryChanged() +{ + double w = GetWidth(); + double h = GetHeight(); + double left = 0.0; + double right = w; + for (MenubarItem* item : menuItems) + { + double itemwidth = item->GetPreferredWidth(); + itemwidth += 16.0; + if (!item->AlignRight) + { + item->SetFrameGeometry(left, 0.0, itemwidth, h); + left += itemwidth; + } + else + { + right -= itemwidth; + item->SetFrameGeometry(right, 0.0, itemwidth, h); + } + } +} + +///////////////////////////////////////////////////////////////////////////// + +MenubarItem::MenubarItem(Menubar* menubar, std::string text, bool alignRight) : Widget(menubar), menubar(menubar), text(text), AlignRight(alignRight) +{ + SetStyleClass("menubaritem"); +} + +bool MenubarItem::OnMouseDown(const Point& pos, InputKey key) +{ + menubar->ShowMenu(this); + return true; +} + +bool MenubarItem::OnMouseUp(const Point& pos, InputKey key) +{ + return true; +} + +void MenubarItem::OnMouseMove(const Point& pos) +{ + if (GetStyleState().empty()) + { + SetStyleState("hover"); + } +} + +void MenubarItem::OnMouseLeave() +{ + SetStyleState(""); +} + +double MenubarItem::GetPreferredWidth() const +{ + Canvas* canvas = GetCanvas(); + return canvas->measureText(text).width; +} + +void MenubarItem::OnPaint(Canvas* canvas) +{ + double x = (GetWidth() - canvas->measureText(text).width) * 0.5; + canvas->drawText(Point(x, 21.0), GetStyleColor("color"), text); +} + +///////////////////////////////////////////////////////////////////////////// + +Menu::Menu(Widget* parent) : Widget(parent, WidgetType::Popup) +{ + SetStyleClass("menu"); +} + +void Menu::SetLeftPosition(const Point& pos) +{ + SetFrameGeometry(Rect::xywh(pos.x, pos.y, GetPreferredWidth() + GetNoncontentLeft() + GetNoncontentRight(), GetPreferredHeight() + GetNoncontentTop() + GetNoncontentBottom())); +} + +void Menu::SetRightPosition(const Point& pos) +{ + SetFrameGeometry(Rect::xywh(pos.x - GetWidth() - GetNoncontentLeft() - GetNoncontentRight(), pos.y, GetWidth() + GetNoncontentLeft() + GetNoncontentRight(), GetHeight() + GetNoncontentTop() + GetNoncontentBottom())); +} + +MenuItem* Menu::AddItem(std::shared_ptr icon, std::string text, std::function onClick) +{ + auto item = new MenuItem(this); + if (icon) + item->icon->SetImage(icon); + item->text->SetText(text); + /* + item->element->addEventListener("click", [=](Event* event) + { + event->stopPropagation(); + if (onCloseMenu) + onCloseMenu(); + if (onClick) + onClick(); + }); + */ + return item; +} + +MenuItemSeparator* Menu::AddSeparator() +{ + auto sep = new MenuItemSeparator(this); + return sep; +} + +double Menu::GetPreferredWidth() const +{ + return 200.0; +} + +double Menu::GetPreferredHeight() const +{ + double h = 0.0; + for (Widget* item = FirstChild(); item != nullptr; item = item->NextSibling()) + { + h += 20.0; + } + return h; +} + +void Menu::OnGeometryChanged() +{ + double w = GetWidth(); + double h = GetHeight(); + double y = 0.0; + for (Widget* item = FirstChild(); item != nullptr; item = item->NextSibling()) + { + item->SetFrameGeometry(Rect::xywh(0.0, y, w, 20.0)); + y += 20.0; + } +} + +///////////////////////////////////////////////////////////////////////////// + +MenuItem::MenuItem(Widget* parent) : Widget(parent) +{ + SetStyleClass("menuitem"); + icon = new ImageBox(this); + text = new TextLabel(this); +} + +void MenuItem::OnMouseMove(const Point& pos) +{ + if (GetStyleState().empty()) + { + SetStyleState("hover"); + } +} + +void MenuItem::OnMouseLeave() +{ + SetStyleState(""); +} + +void MenuItem::OnGeometryChanged() +{ + double iconwidth = icon->GetPreferredWidth(); + double iconheight = icon->GetPreferredHeight(); + double w = GetWidth(); + double h = GetHeight(); + icon->SetFrameGeometry(Rect::xywh(0.0, (h - iconheight) * 0.5, iconwidth, iconheight)); + text->SetFrameGeometry(Rect::xywh(iconwidth, 0.0, w - iconwidth, h)); +} + +///////////////////////////////////////////////////////////////////////////// + +MenuItemSeparator::MenuItemSeparator(Widget* parent) : Widget(parent) +{ + SetStyleClass("menuitemseparator"); +} diff --git a/libraries/ZWidget/src/widgets/pushbutton/pushbutton.cpp b/libraries/ZWidget/src/widgets/pushbutton/pushbutton.cpp new file mode 100644 index 0000000000..e85b2c5575 --- /dev/null +++ b/libraries/ZWidget/src/widgets/pushbutton/pushbutton.cpp @@ -0,0 +1,88 @@ + +#include "widgets/pushbutton/pushbutton.h" + +PushButton::PushButton(Widget* parent) : Widget(parent) +{ + SetStyleClass("pushbutton"); +} + +void PushButton::SetText(const std::string& value) +{ + if (text != value) + { + text = value; + Update(); + } +} + +const std::string& PushButton::GetText() const +{ + return text; +} + +double PushButton::GetPreferredHeight() const +{ + return 30.0; +} + +void PushButton::OnPaint(Canvas* canvas) +{ + Rect box = canvas->measureText(text); + canvas->drawText(Point((GetWidth() - box.width) * 0.5, GetHeight() - 5.0), GetStyleColor("color"), text); +} + +void PushButton::OnMouseMove(const Point& pos) +{ + if (GetStyleState().empty()) + { + SetStyleState("hover"); + } +} + +bool PushButton::OnMouseDown(const Point& pos, InputKey key) +{ + SetFocus(); + SetStyleState("down"); + return true; +} + +bool PushButton::OnMouseUp(const Point& pos, InputKey key) +{ + if (GetStyleState() == "down") + { + SetStyleState(""); + Repaint(); + Click(); + } + return true; +} + +void PushButton::OnMouseLeave() +{ + SetStyleState(""); +} + +void PushButton::OnKeyDown(InputKey key) +{ + if (key == InputKey::Space || key == InputKey::Enter) + { + SetStyleState("down"); + Update(); + } +} + +void PushButton::OnKeyUp(InputKey key) +{ + if (key == InputKey::Space || key == InputKey::Enter) + { + SetStyleState(""); + Repaint(); + Click(); + } +} + +void PushButton::Click() +{ + if (OnClick) + OnClick(); +} diff --git a/libraries/ZWidget/src/widgets/scrollbar/scrollbar.cpp b/libraries/ZWidget/src/widgets/scrollbar/scrollbar.cpp new file mode 100644 index 0000000000..634403fa71 --- /dev/null +++ b/libraries/ZWidget/src/widgets/scrollbar/scrollbar.cpp @@ -0,0 +1,409 @@ + +#include "widgets/scrollbar/scrollbar.h" +#include "core/colorf.h" +#include + +Scrollbar::Scrollbar(Widget* parent) : Widget(parent) +{ + SetStyleClass("scrollbar"); + UpdatePartPositions(); + + mouse_down_timer = new Timer(this); + mouse_down_timer->FuncExpired = [=]() { OnTimerExpired(); }; +} + +Scrollbar::~Scrollbar() +{ +} + +bool Scrollbar::IsVertical() const +{ + return vertical; +} + +bool Scrollbar::IsHorizontal() const +{ + return !vertical; +} + +double Scrollbar::GetMin() const +{ + return scroll_min; +} + +double Scrollbar::GetMax() const +{ + return scroll_max; +} + +double Scrollbar::GetLineStep() const +{ + return line_step; +} + +double Scrollbar::GetPageStep() const +{ + return page_step; +} + +double Scrollbar::GetPosition() const +{ + return position; +} + +void Scrollbar::SetVertical() +{ + vertical = true; + if (UpdatePartPositions()) + Update(); +} + +void Scrollbar::SetHorizontal() +{ + vertical = false; + if (UpdatePartPositions()) + Update(); +} + +void Scrollbar::SetMin(double new_scroll_min) +{ + SetRanges(new_scroll_min, scroll_max, line_step, page_step); +} + +void Scrollbar::SetMax(double new_scroll_max) +{ + SetRanges(scroll_min, new_scroll_max, line_step, page_step); +} + +void Scrollbar::SetLineStep(double step) +{ + SetRanges(scroll_min, scroll_max, step, page_step); +} + +void Scrollbar::SetPageStep(double step) +{ + SetRanges(scroll_min, scroll_max, line_step, step); +} + +void Scrollbar::SetRanges(double new_scroll_min, double new_scroll_max, double new_line_step, double new_page_step) +{ + if (new_scroll_min >= new_scroll_max || new_line_step <= 0.0 || new_page_step <= 0.0) + throw std::runtime_error("Scrollbar ranges out of bounds!"); + scroll_min = new_scroll_min; + scroll_max = new_scroll_max; + line_step = new_line_step; + page_step = new_page_step; + if (position >= scroll_max) + position = scroll_max - 1.0; + if (position < scroll_min) + position = scroll_min; + if (UpdatePartPositions()) + Update(); +} + +void Scrollbar::SetRanges(double view_size, double total_size) +{ + if (view_size <= 0.0 || total_size <= 0.0) + { + SetRanges(0.0, 1.0, 1.0, 1.0); + } + else + { + double scroll_max = std::max(1.0, total_size - view_size + 1.0); + double page_step = std::max(1.0, view_size); + SetRanges(0.0, scroll_max, 10, page_step); + } +} + +void Scrollbar::SetPosition(double pos) +{ + position = pos; + if (pos >= scroll_max) + position = scroll_max - 1.0; + if (pos < scroll_min) + position = scroll_min; + + if (UpdatePartPositions()) + Update(); +} + +void Scrollbar::OnMouseMove(const Point& pos) +{ + if (mouse_down_mode == mouse_down_thumb_drag) + { + double last_position = position; + + if (pos.x < -100.0 || pos.x > GetWidth() + 100.0 || pos.y < -100.0 || pos.y > GetHeight() + 100.0) + { + position = thumb_start_position; + } + else + { + double delta = vertical ? (pos.y - mouse_drag_start_pos.y) : (pos.x - mouse_drag_start_pos.x); + double position_pixels = thumb_start_pixel_position + delta; + + double track_height = 0; + if (vertical) + track_height = rect_track_decrement.height + rect_track_increment.height; + else + track_height = rect_track_decrement.width + rect_track_increment.width; + + if (track_height != 0.0) + position = scroll_min + position_pixels * (scroll_max - scroll_min) / track_height; + else + position = 0; + + if (position >= scroll_max) + position = scroll_max - 1; + if (position < scroll_min) + position = scroll_min; + + } + + if (position != last_position) + { + InvokeScrollEvent(&FuncScrollThumbTrack); + UpdatePartPositions(); + } + } + + Update(); +} + +bool Scrollbar::OnMouseDown(const Point& pos, InputKey key) +{ + mouse_drag_start_pos = pos; + + if (rect_button_decrement.contains(pos)) + { + mouse_down_mode = mouse_down_button_decr; + FuncScrollOnMouseDown = &FuncScrollLineDecrement; + + double last_position = position; + + position -= line_step; + last_step_size = -line_step; + if (position >= scroll_max) + position = scroll_max - 1.0; + if (position < scroll_min) + position = scroll_min; + + if (last_position != position) + InvokeScrollEvent(&FuncScrollLineDecrement); + } + else if (rect_button_increment.contains(pos)) + { + mouse_down_mode = mouse_down_button_incr; + FuncScrollOnMouseDown = &FuncScrollLineIncrement; + + double last_position = position; + + position += line_step; + last_step_size = line_step; + if (position >= scroll_max) + position = scroll_max - 1.0; + if (position < scroll_min) + position = scroll_min; + + if (last_position != position) + InvokeScrollEvent(&FuncScrollLineIncrement); + } + else if (rect_thumb.contains(pos)) + { + mouse_down_mode = mouse_down_thumb_drag; + thumb_start_position = position; + thumb_start_pixel_position = vertical ? (rect_thumb.y - rect_track_decrement.y) : (rect_thumb.x - rect_track_decrement.x); + } + else if (rect_track_decrement.contains(pos)) + { + mouse_down_mode = mouse_down_track_decr; + FuncScrollOnMouseDown = &FuncScrollPageDecrement; + + double last_position = position; + + position -= page_step; + last_step_size = -page_step; + if (position >= scroll_max) + position = scroll_max - 1.0; + if (position < scroll_min) + position = scroll_min; + + if (last_position != position) + InvokeScrollEvent(&FuncScrollPageDecrement); + } + else if (rect_track_increment.contains(pos)) + { + mouse_down_mode = mouse_down_track_incr; + FuncScrollOnMouseDown = &FuncScrollPageIncrement; + + double last_position = position; + + position += page_step; + last_step_size = page_step; + if (position >= scroll_max) + position = scroll_max - 1.0; + if (position < scroll_min) + position = scroll_min; + + if (last_position != position) + InvokeScrollEvent(&FuncScrollPageIncrement); + } + + mouse_down_timer->Start(100, false); + + UpdatePartPositions(); + + Update(); + CaptureMouse(); + return true; +} + +bool Scrollbar::OnMouseUp(const Point& pos, InputKey key) +{ + if (mouse_down_mode == mouse_down_thumb_drag) + { + if (FuncScrollThumbRelease) + FuncScrollThumbRelease(); + } + + mouse_down_mode = mouse_down_none; + mouse_down_timer->Stop(); + + Update(); + ReleaseMouseCapture(); + return true; +} + +void Scrollbar::OnMouseLeave() +{ + Update(); +} + +void Scrollbar::OnGeometryChanged() +{ + UpdatePartPositions(); +} + +void Scrollbar::OnPaint(Canvas* canvas) +{ + /* + part_button_decrement.render_box(canvas, rect_button_decrement); + part_track_decrement.render_box(canvas, rect_track_decrement); + part_thumb.render_box(canvas, rect_thumb); + part_thumb_gripper.render_box(canvas, rect_thumb); + part_track_increment.render_box(canvas, rect_track_increment); + part_button_increment.render_box(canvas, rect_button_increment); + */ + + canvas->fillRect(Rect::shrink(Rect::xywh(0.0, 0.0, GetWidth(), GetHeight()), 4.0, 0.0, 4.0, 0.0), GetStyleColor("track-color")); + canvas->fillRect(Rect::shrink(rect_thumb, 4.0, 0.0, 4.0, 0.0), GetStyleColor("thumb-color")); +} + +// Calculates positions of all parts. Returns true if thumb position was changed compared to previously, false otherwise. +bool Scrollbar::UpdatePartPositions() +{ + double decr_height = showbuttons ? 16.0 : 0.0; + double incr_height = showbuttons ? 16.0 : 0.0; + + double total_height = vertical ? GetHeight() : GetWidth(); + double track_height = std::max(0.0, total_height - decr_height - incr_height); + double thumb_height = CalculateThumbSize(track_height); + + double thumb_offset = decr_height + CalculateThumbPosition(thumb_height, track_height); + + Rect previous_rect_thumb = rect_thumb; + + rect_button_decrement = CreateRect(0.0, decr_height); + rect_track_decrement = CreateRect(decr_height, thumb_offset); + rect_thumb = CreateRect(thumb_offset, thumb_offset + thumb_height); + rect_track_increment = CreateRect(thumb_offset + thumb_height, decr_height + track_height); + rect_button_increment = CreateRect(decr_height + track_height, decr_height + track_height + incr_height); + + return (previous_rect_thumb != rect_thumb); +} + +double Scrollbar::CalculateThumbSize(double track_size) +{ + double minimum_thumb_size = 20.0; + double range = scroll_max - scroll_min; + double length = range + page_step - 1; + double thumb_size = page_step * track_size / length; + if (thumb_size < minimum_thumb_size) + thumb_size = minimum_thumb_size; + if (thumb_size > track_size) + thumb_size = track_size; + return thumb_size; +} + +double Scrollbar::CalculateThumbPosition(double thumb_size, double track_size) +{ + double relative_pos = position - scroll_min; + double range = scroll_max - scroll_min - 1; + if (range != 0) + { + double available_area = std::max(0.0, track_size - thumb_size); + return relative_pos * available_area / range; + } + else + { + return 0; + } +} + +Rect Scrollbar::CreateRect(double start, double end) +{ + if (vertical) + return Rect(0.0, start, GetWidth(), end - start); + else + return Rect(start, 0.0, end - start, GetHeight()); +} + +void Scrollbar::OnTimerExpired() +{ + if (mouse_down_mode == mouse_down_thumb_drag) + return; + + mouse_down_timer->Start(100, false); + + double last_position = position; + position += last_step_size; + if (position >= scroll_max) + position = scroll_max - 1; + + if (position < scroll_min) + position = scroll_min; + + if (position != last_position) + { + InvokeScrollEvent(FuncScrollOnMouseDown); + + if (UpdatePartPositions()) + Update(); + } +} + +void Scrollbar::OnEnableChanged() +{ + Update(); +} + +void Scrollbar::InvokeScrollEvent(std::function* event_ptr) +{ + if (position == scroll_max - 1) + { + if (FuncScrollMax) + FuncScrollMax(); + } + + if (position == scroll_min) + { + if (FuncScrollMin) + FuncScrollMin(); + } + + if (FuncScroll) + FuncScroll(); + + if (event_ptr && *event_ptr) + (*event_ptr)(); +} diff --git a/libraries/ZWidget/src/widgets/statusbar/statusbar.cpp b/libraries/ZWidget/src/widgets/statusbar/statusbar.cpp new file mode 100644 index 0000000000..fd914298c7 --- /dev/null +++ b/libraries/ZWidget/src/widgets/statusbar/statusbar.cpp @@ -0,0 +1,19 @@ + +#include "widgets/statusbar/statusbar.h" +#include "widgets/lineedit/lineedit.h" +#include "core/colorf.h" + +Statusbar::Statusbar(Widget* parent) : Widget(parent) +{ + CommandEdit = new LineEdit(this); + CommandEdit->SetFrameGeometry(Rect::xywh(90.0, 4.0, 400.0, 23.0)); +} + +Statusbar::~Statusbar() +{ +} + +void Statusbar::OnPaint(Canvas* canvas) +{ + canvas->drawText(Point(16.0, 21.0), Colorf::fromRgba8(0, 0, 0), "Command:"); +} diff --git a/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp b/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp new file mode 100644 index 0000000000..4bd7551c7f --- /dev/null +++ b/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp @@ -0,0 +1,329 @@ + +#include "widgets/tabwidget/tabwidget.h" +#include "widgets/textlabel/textlabel.h" +#include "widgets/imagebox/imagebox.h" +#include + +TabWidget::TabWidget(Widget* parent) : Widget(parent) +{ + Bar = new TabBar(this); + PageStack = new TabWidgetStack(this); + + Bar->OnCurrentChanged = [=]() { OnBarCurrentChanged(); }; +} + +int TabWidget::AddTab(Widget* page, const std::string& label) +{ + return AddTab(page, nullptr, label); +} + +int TabWidget::AddTab(Widget* page, const std::shared_ptr& icon, const std::string& label) +{ + int pageIndex = Bar->AddTab(label); + page->SetParent(PageStack); + page->SetVisible(false); + Pages.push_back(page); + if (Pages.size() == 1) + { + PageStack->SetCurrentWidget(page); + } + return pageIndex; +} + +void TabWidget::SetTabText(int index, const std::string& text) +{ + Bar->SetTabText(index, text); +} + +void TabWidget::SetTabText(Widget* page, const std::string& text) +{ + int index = GetPageIndex(page); + if (index != -1) + SetTabText(index, text); +} + +void TabWidget::SetTabIcon(int index, const std::shared_ptr& icon) +{ + Bar->SetTabIcon(index, icon); +} + +void TabWidget::SetTabIcon(Widget* page, const std::shared_ptr& icon) +{ + int index = GetPageIndex(page); + if (index != -1) + SetTabIcon(index, icon); +} + +int TabWidget::GetCurrentIndex() const +{ + return Bar->GetCurrentIndex(); +} + +Widget* TabWidget::GetCurrentWidget() const +{ + return Pages[Bar->GetCurrentIndex()]; +} + +void TabWidget::SetCurrentIndex(int pageIndex) +{ + if (Bar->GetCurrentIndex() != pageIndex) + { + Bar->SetCurrentIndex(pageIndex); + PageStack->SetCurrentWidget(Pages[pageIndex]); + } +} + +void TabWidget::SetCurrentWidget(Widget* pageWidget) +{ + int pageIndex = GetPageIndex(pageWidget); + if (pageIndex != -1) + SetCurrentIndex(pageIndex); +} + +int TabWidget::GetPageIndex(Widget* pageWidget) const +{ + for (size_t i = 0; i < Pages.size(); i++) + { + if (Pages[i] == pageWidget) + return (int)i; + } + return -1; +} + +void TabWidget::OnBarCurrentChanged() +{ + int pageIndex = Bar->GetCurrentIndex(); + PageStack->SetCurrentWidget(Pages[pageIndex]); + if (OnCurrentChanged) + OnCurrentChanged(); +} + +void TabWidget::OnGeometryChanged() +{ + double w = GetWidth(); + double h = GetHeight(); + double barHeight = Bar->GetPreferredHeight(); + Bar->SetFrameGeometry(Rect::xywh(0.0, 0.0, w, barHeight)); + PageStack->SetFrameGeometry(Rect::xywh(0.0, barHeight, w, std::max(h - barHeight, 0.0))); +} + +///////////////////////////////////////////////////////////////////////////// + +TabBar::TabBar(Widget* parent) : Widget(parent) +{ + SetStyleClass("tabbar"); +} + +int TabBar::AddTab(const std::string& label) +{ + return AddTab(nullptr, label); +} + +int TabBar::AddTab(const std::shared_ptr& icon, const std::string& label) +{ + TabBarTab* tab = new TabBarTab(this); + tab->SetIcon(icon); + tab->SetText(label); + tab->OnClick = [=]() { OnTabClicked(tab); }; + int pageIndex = (int)Tabs.size(); + Tabs.push_back(tab); + if (CurrentIndex == -1) + SetCurrentIndex(pageIndex); + OnGeometryChanged(); + return pageIndex; +} + +void TabBar::SetTabText(int index, const std::string& text) +{ + Tabs[index]->SetText(text); + OnGeometryChanged(); +} + +void TabBar::SetTabIcon(int index, const std::shared_ptr& icon) +{ + Tabs[index]->SetIcon(icon); + OnGeometryChanged(); +} + +int TabBar::GetCurrentIndex() const +{ + return CurrentIndex; +} + +void TabBar::SetCurrentIndex(int pageIndex) +{ + if (CurrentIndex != pageIndex) + { + if (CurrentIndex != -1) + Tabs[CurrentIndex]->SetCurrent(false); + CurrentIndex = pageIndex; + if (CurrentIndex != -1) + Tabs[CurrentIndex]->SetCurrent(true); + } +} + +void TabBar::OnTabClicked(TabBarTab* tab) +{ + int pageIndex = GetTabIndex(tab); + if (CurrentIndex != pageIndex) + { + SetCurrentIndex(pageIndex); + if (OnCurrentChanged) + OnCurrentChanged(); + } +} + +int TabBar::GetTabIndex(TabBarTab* tab) +{ + for (size_t i = 0; i < Tabs.size(); i++) + { + if (Tabs[i] == tab) + return (int)i; + } + return -1; +} + +void TabBar::OnGeometryChanged() +{ + double w = GetWidth(); + double h = GetHeight(); + double x = 0.0; + for (TabBarTab* tab : Tabs) + { + double tabWidth = tab->GetNoncontentLeft() + tab->GetPreferredWidth() + tab->GetNoncontentRight(); + tab->SetFrameGeometry(Rect::xywh(x, 0.0, tabWidth, h)); + x += tabWidth; + } +} + +///////////////////////////////////////////////////////////////////////////// + +TabBarTab::TabBarTab(Widget* parent) : Widget(parent) +{ + SetStyleClass("tabbar-tab"); +} + +void TabBarTab::SetText(const std::string& text) +{ + if (!text.empty()) + { + if (!Label) + { + Label = new TextLabel(this); + OnGeometryChanged(); + } + Label->SetText(text); + } + else + { + delete Label; + Label = nullptr; + OnGeometryChanged(); + } +} + +void TabBarTab::SetIcon(const std::shared_ptr& image) +{ + if (image) + { + if (!Icon) + { + Icon = new ImageBox(this); + OnGeometryChanged(); + } + Icon->SetImage(image); + } + else + { + delete Icon; + Icon = nullptr; + OnGeometryChanged(); + } +} + +void TabBarTab::SetCurrent(bool value) +{ + if (IsCurrent != value) + { + IsCurrent = value; + SetStyleState(value ? "active" : ""); + } +} + +double TabBarTab::GetPreferredWidth() const +{ + double x = Icon ? 32.0 + 5.0 : 0.0; + if (Label) x += Label->GetPreferredWidth(); + return x; +} + +void TabBarTab::OnGeometryChanged() +{ + double x = 0.0; + double w = GetWidth(); + double h = GetHeight(); + if (Icon) + { + Icon->SetFrameGeometry(Rect::xywh(x, (h - 32.0) * 0.5, 32.0, 32.0)); + x = 32.0 + 5.0; + } + if (Label) + { + Label->SetFrameGeometry(Rect::xywh(x, (h - Label->GetPreferredHeight()) * 0.5, std::max(w - x, 0.0), Label->GetPreferredHeight())); + } +} + +void TabBarTab::OnMouseMove(const Point& pos) +{ + if (GetStyleState().empty()) + { + SetStyleState("hover"); + } +} + +bool TabBarTab::OnMouseDown(const Point& pos, InputKey key) +{ + if (OnClick) + OnClick(); + return true; +} + +bool TabBarTab::OnMouseUp(const Point& pos, InputKey key) +{ + return true; +} + +void TabBarTab::OnMouseLeave() +{ + if (GetStyleState() == "hover") + SetStyleState(""); + Update(); +} + +///////////////////////////////////////////////////////////////////////////// + +TabWidgetStack::TabWidgetStack(Widget* parent) : Widget(parent) +{ + SetStyleClass("tabwidget-stack"); +} + +void TabWidgetStack::SetCurrentWidget(Widget* widget) +{ + if (widget != CurrentWidget) + { + if (CurrentWidget) + CurrentWidget->SetVisible(false); + CurrentWidget = widget; + if (CurrentWidget) + { + CurrentWidget->SetVisible(true); + OnGeometryChanged(); + } + } +} + +void TabWidgetStack::OnGeometryChanged() +{ + if (CurrentWidget) + CurrentWidget->SetFrameGeometry(Rect::xywh(0.0, 0.0, GetWidth(), GetHeight())); +} diff --git a/libraries/ZWidget/src/widgets/textedit/textedit.cpp b/libraries/ZWidget/src/widgets/textedit/textedit.cpp new file mode 100644 index 0000000000..27a2d02304 --- /dev/null +++ b/libraries/ZWidget/src/widgets/textedit/textedit.cpp @@ -0,0 +1,1039 @@ + +#include "widgets/textedit/textedit.h" +#include "widgets/scrollbar/scrollbar.h" +#include "core/utf8reader.h" +#include "core/colorf.h" + +#ifdef _MSC_VER +#pragma warning(disable: 4267) // warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data +#endif + +TextEdit::TextEdit(Widget* parent) : Widget(parent) +{ + SetStyleClass("textedit"); + + timer = new Timer(this); + timer->FuncExpired = [=]() { OnTimerExpired(); }; + + scroll_timer = new Timer(this); + scroll_timer->FuncExpired = [=]() { OnScrollTimerExpired(); }; + + SetCursor(StandardCursor::ibeam); + + CreateComponents(); +} + +TextEdit::~TextEdit() +{ +} + +bool TextEdit::IsReadOnly() const +{ + return readonly; +} + +bool TextEdit::IsLowercase() const +{ + return lowercase; +} + +bool TextEdit::IsUppercase() const +{ + return uppercase; +} + +int TextEdit::GetMaxLength() const +{ + return max_length; +} + +std::string TextEdit::GetLineText(int line) const +{ + if (line >= 0 && line < (int)lines.size()) + return lines[line].text; + else + return std::string(); +} + +std::string TextEdit::GetText() const +{ + std::string::size_type size = 0; + for (size_t i = 0; i < lines.size(); i++) + size += lines[i].text.size(); + size += lines.size() - 1; + + std::string text; + text.reserve(size); + + for (size_t i = 0; i < lines.size(); i++) + { + if (i > 0) + text.push_back('\n'); + text += lines[i].text; + } + + return text; +} + +int TextEdit::GetLineCount() const +{ + return (int)lines.size(); +} + +std::string TextEdit::GetSelection() const +{ + std::string::size_type offset = ToOffset(selection_start); + int start = (int)std::min(offset, offset + selection_length); + return GetText().substr(start, abs(selection_length)); +} + +int TextEdit::GetSelectionStart() const +{ + return (int)ToOffset(selection_start); +} + +int TextEdit::GetSelectionLength() const +{ + return selection_length; +} + +int TextEdit::GetCursorPos() const +{ + return (int)ToOffset(cursor_pos); +} + +int TextEdit::GetCursorLineNumber() const +{ + return cursor_pos.y; +} + +void TextEdit::SelectAll() +{ + std::string::size_type size = 0; + for (size_t i = 0; i < lines.size(); i++) + size += lines[i].text.size(); + size += lines.size() - 1; + SetSelection(0, (int)size); +} + +void TextEdit::SetReadOnly(bool enable) +{ + if (readonly != enable) + { + readonly = enable; + Update(); + } +} + +void TextEdit::SetLowercase(bool enable) +{ + if (lowercase != enable) + { + lowercase = enable; + Update(); + } +} + +void TextEdit::SetUppercase(bool enable) +{ + if (uppercase != enable) + { + uppercase = enable; + Update(); + } +} + +void TextEdit::SetMaxLength(int length) +{ + if (max_length != length) + { + max_length = length; + + std::string::size_type size = 0; + for (size_t i = 0; i < lines.size(); i++) + size += lines[i].text.size(); + size += lines.size() - 1; + + if ((int)size > length) + { + if (FuncBeforeEditChanged) + FuncBeforeEditChanged(); + SetSelection(length, (int)size - length); + DeleteSelectedText(); + if (FuncAfterEditChanged) + FuncAfterEditChanged(); + } + Update(); + } +} + +void TextEdit::SetText(const std::string& text) +{ + lines.clear(); + std::string::size_type start = 0; + std::string::size_type end = text.find('\n'); + while (end != std::string::npos) + { + TextEdit::Line line; + line.text = text.substr(start, end - start); + lines.push_back(line); + start = end + 1; + end = text.find('\n', start); + } + TextEdit::Line line; + line.text = text.substr(start); + lines.push_back(line); + + clip_start_offset = 0; + SetCursorPos(0); + ClearSelection(); + Update(); +} + +void TextEdit::AddText(const std::string& text) +{ + std::string::size_type start = 0; + std::string::size_type end = text.find('\n'); + while (end != std::string::npos) + { + TextEdit::Line line; + line.text = text.substr(start, end - start); + lines.push_back(line); + start = end + 1; + end = text.find('\n', start); + } + TextEdit::Line line; + line.text = text.substr(start); + lines.push_back(line); + + // clip_start_offset = 0; + // SetCursorPos(0); + ClearSelection(); + Update(); +} + +void TextEdit::SetSelection(int pos, int length) +{ + selection_start = ivec2(pos, 0); + selection_length = length; + Update(); +} + +void TextEdit::ClearSelection() +{ + SetSelection(0, 0); + Update(); +} + +void TextEdit::DeleteSelectedText() +{ + if (GetSelectionLength() == 0) + return; + + std::string::size_type offset = ToOffset(selection_start); + int start = (int)std::min(offset, offset + selection_length); + int length = std::abs(selection_length); + + ClearSelection(); + std::string text = GetText(); + SetText(text.substr(0, start) + text.substr(start + length)); + SetCursorPos(start); +} + +void TextEdit::SetCursorPos(int pos) +{ + cursor_pos = FromOffset(pos); + Update(); +} + +void TextEdit::SetInputMask(const std::string& mask) +{ + input_mask = mask; +} + +void TextEdit::SetCursorDrawingEnabled(bool enable) +{ + if (!readonly) + timer->Start(500); +} + +void TextEdit::SetSelectAllOnFocusGain(bool enable) +{ + select_all_on_focus_gain = enable; +} + +void TextEdit::OnMouseMove(const Point& pos) +{ + if (mouse_selecting && !ignore_mouse_events) + { + if (pos.x < 0.0 || pos.x > GetWidth()) + { + if (pos.x < 0.0) + mouse_moves_left = true; + else + mouse_moves_left = false; + + if (!readonly) + scroll_timer->Start(50, true); + } + else + { + scroll_timer->Stop(); + cursor_pos = GetCharacterIndex(pos); + selection_length = ToOffset(cursor_pos) - ToOffset(selection_start); + Update(); + } + } +} + +bool TextEdit::OnMouseDown(const Point& pos, InputKey key) +{ + if (key == InputKey::LeftMouse) + { + CaptureMouse(); + mouse_selecting = true; + cursor_pos = GetCharacterIndex(pos); + selection_start = cursor_pos; + selection_length = 0; + + Update(); + } + return true; +} + +bool TextEdit::OnMouseDoubleclick(const Point& pos, InputKey key) +{ + return true; +} + +bool TextEdit::OnMouseUp(const Point& pos, InputKey key) +{ + if (mouse_selecting && key == InputKey::LeftMouse) + { + if (ignore_mouse_events) // This prevents text selection from changing from what was set when focus was gained. + { + ReleaseMouseCapture(); + ignore_mouse_events = false; + mouse_selecting = false; + } + else + { + scroll_timer->Stop(); + ReleaseMouseCapture(); + mouse_selecting = false; + ivec2 sel_end = GetCharacterIndex(pos); + selection_length = ToOffset(sel_end) - ToOffset(selection_start); + cursor_pos = sel_end; + SetFocus(); + Update(); + } + } + return true; +} + +void TextEdit::OnKeyChar(std::string chars) +{ + if (!chars.empty() && !(chars[0] >= 0 && chars[0] < 32)) + { + if (FuncBeforeEditChanged) + FuncBeforeEditChanged(); + + DeleteSelectedText(); + ClearSelection(); + if (input_mask.empty()) + { + // not in any special mode, just insert the string. + InsertText(cursor_pos, chars); + cursor_pos.x += chars.size(); + } + else + { + if (InputMaskAcceptsInput(cursor_pos, chars)) + { + InsertText(cursor_pos, chars); + cursor_pos.x += chars.size(); + } + } + + if (FuncAfterEditChanged) + FuncAfterEditChanged(); + } +} + +void TextEdit::OnKeyDown(InputKey key) +{ + if (!readonly && key == InputKey::Enter) + { + if (FuncEnterPressed) + { + FuncEnterPressed(); + } + else + { + ClearSelection(); + InsertText(cursor_pos, "\n"); + SetCursorPos(GetCursorPos() + 1); + } + return; + } + + if (!readonly) // Do not flash cursor when readonly + { + cursor_blink_visible = true; + timer->Start(500); // don't blink cursor when moving or typing. + } + + if (key == InputKey::Enter || key == InputKey::Escape || key == InputKey::Tab) + { + // Do not consume these. + return; + } + else if (key == InputKey::A && GetKeyState(InputKey::Ctrl)) + { + // select all + SelectAll(); + } + else if (key == InputKey::C && GetKeyState(InputKey::Ctrl)) + { + std::string str = GetSelection(); + SetClipboardText(str); + } + else if (readonly) + { + // Do not consume messages on read only component (only allow CTRL-A and CTRL-C) + return; + } + else if (key == InputKey::Up) + { + if (GetKeyState(InputKey::Shift) && selection_length == 0) + selection_start = cursor_pos; + + if (cursor_pos.y > 0) + { + cursor_pos.y--; + cursor_pos.x = std::min(lines[cursor_pos.y].text.size(), (size_t)cursor_pos.x); + } + + if (GetKeyState(InputKey::Shift)) + { + selection_length = ToOffset(cursor_pos) - ToOffset(selection_start); + } + else + { + // Clear the selection if a cursor key is pressed but shift isn't down. + selection_start = ivec2(0, 0); + selection_length = 0; + } + MoveVerticalScroll(); + Update(); + undo_info.first_text_insert = true; + } + else if (key == InputKey::Down) + { + if (GetKeyState(InputKey::Shift) && selection_length == 0) + selection_start = cursor_pos; + + if (cursor_pos.y < lines.size() - 1) + { + cursor_pos.y++; + cursor_pos.x = std::min(lines[cursor_pos.y].text.size(), (size_t)cursor_pos.x); + } + + if (GetKeyState(InputKey::Shift)) + { + selection_length = ToOffset(cursor_pos) - ToOffset(selection_start); + } + else + { + // Clear the selection if a cursor key is pressed but shift isn't down. + selection_start = ivec2(0, 0); + selection_length = 0; + } + MoveVerticalScroll(); + + Update(); + undo_info.first_text_insert = true; + } + else if (key == InputKey::Left) + { + Move(-1, GetKeyState(InputKey::Shift), GetKeyState(InputKey::Ctrl)); + } + else if (key == InputKey::Right) + { + Move(1, GetKeyState(InputKey::Shift), GetKeyState(InputKey::Ctrl)); + } + else if (key == InputKey::Backspace) + { + Backspace(); + } + else if (key == InputKey::Delete) + { + Del(); + } + else if (key == InputKey::Home) + { + if (GetKeyState(InputKey::Ctrl)) + cursor_pos = ivec2(0, 0); + else + cursor_pos.x = 0; + if (GetKeyState(InputKey::Shift)) + selection_length = ToOffset(cursor_pos) - ToOffset(selection_start); + else + ClearSelection(); + Update(); + MoveVerticalScroll(); + } + else if (key == InputKey::End) + { + if (GetKeyState(InputKey::Ctrl)) + cursor_pos = ivec2(lines.back().text.length(), lines.size() - 1); + else + cursor_pos.x = lines[cursor_pos.y].text.size(); + + if (GetKeyState(InputKey::Shift)) + selection_length = ToOffset(cursor_pos) - ToOffset(selection_start); + else + ClearSelection(); + Update(); + } + else if (key == InputKey::X && GetKeyState(InputKey::Ctrl)) + { + std::string str = GetSelection(); + DeleteSelectedText(); + SetClipboardText(str); + } + else if (key == InputKey::V && GetKeyState(InputKey::Ctrl)) + { + std::string str = GetClipboardText(); + std::string::const_iterator end_str = std::remove(str.begin(), str.end(), '\r'); + str.resize(end_str - str.begin()); + DeleteSelectedText(); + + if (input_mask.empty()) + { + InsertText(cursor_pos, str); + SetCursorPos(GetCursorPos() + str.length()); + } + else + { + if (InputMaskAcceptsInput(cursor_pos, str)) + { + InsertText(cursor_pos, str); + SetCursorPos(GetCursorPos() + str.length()); + } + } + MoveVerticalScroll(); + } + else if (GetKeyState(InputKey::Ctrl) && key == InputKey::Z) + { + if (!readonly) + { + std::string tmp = undo_info.undo_text; + undo_info.undo_text = GetText(); + SetText(tmp); + } + } + else if (key == InputKey::Shift) + { + if (selection_length == 0) + selection_start = cursor_pos; + } + + if (FuncAfterEditChanged) + FuncAfterEditChanged(); +} + +void TextEdit::OnKeyUp(InputKey key) +{ +} + +void TextEdit::OnSetFocus() +{ + if (!readonly) + timer->Start(500); + if (select_all_on_focus_gain) + SelectAll(); + ignore_mouse_events = true; + cursor_pos.y = lines.size() - 1; + cursor_pos.x = lines[cursor_pos.y].text.length(); + + Update(); + + if (FuncFocusGained) + FuncFocusGained(); +} + +void TextEdit::OnLostFocus() +{ + timer->Stop(); + ClearSelection(); + + Update(); + + if (FuncFocusLost) + FuncFocusLost(); +} + +void TextEdit::CreateComponents() +{ + vert_scrollbar = new Scrollbar(this); + vert_scrollbar->FuncScroll = [=]() { OnVerticalScroll(); }; + vert_scrollbar->SetVisible(false); + vert_scrollbar->SetVertical(); +} + +void TextEdit::OnVerticalScroll() +{ +} + +void TextEdit::UpdateVerticalScroll() +{ + Rect rect( + GetWidth() - 16.0/*vert_scrollbar->GetWidth()*/, + 0.0, + 16.0/*vert_scrollbar->GetWidth()*/, + GetHeight()); + + vert_scrollbar->SetFrameGeometry(rect); + + double total_height = GetTotalLineHeight(); + double height_per_line = std::max(1.0, total_height / std::max(1.0, (double)lines.size())); + bool visible = total_height > GetHeight(); + vert_scrollbar->SetRanges((int)std::round(GetHeight() / height_per_line), (int)std::round(total_height / height_per_line)); + vert_scrollbar->SetLineStep(1); + vert_scrollbar->SetVisible(visible); + + if (visible == false) + vert_scrollbar->SetPosition(0); +} + +void TextEdit::MoveVerticalScroll() +{ + double total_height = GetTotalLineHeight(); + double height_per_line = std::max(1.0, total_height / std::max((size_t)1, lines.size())); + int lines_fit = (int)(GetHeight() / height_per_line); + if (cursor_pos.y >= vert_scrollbar->GetPosition() + lines_fit) + { + vert_scrollbar->SetPosition(cursor_pos.y - lines_fit + 1); + } + else if (cursor_pos.y < vert_scrollbar->GetPosition()) + { + vert_scrollbar->SetPosition(cursor_pos.y); + } +} + +double TextEdit::GetTotalLineHeight() +{ + double total = 0; + for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); iter++) + { + total += iter->layout.GetSize().height; + } + return total; +} + +void TextEdit::Move(int steps, bool shift, bool ctrl) +{ + if (shift && selection_length == 0) + selection_start = cursor_pos; + + // Jump over words if control is pressed. + if (ctrl) + { + if (steps < 0 && cursor_pos.x == 0 && cursor_pos.y > 0) + { + cursor_pos.x = (int)lines[cursor_pos.y - 1].text.size(); + cursor_pos.y--; + } + else if (steps > 0 && cursor_pos.x == (int)lines[cursor_pos.y].text.size() && cursor_pos.y + 1 < (int)lines.size()) + { + cursor_pos.x = 0; + cursor_pos.y++; + } + + ivec2 new_pos; + if (steps < 0) + new_pos = FindPreviousBreakCharacter(cursor_pos); + else + new_pos = FindNextBreakCharacter(cursor_pos); + + cursor_pos = new_pos; + } + else if (steps < 0 && cursor_pos.x == 0 && cursor_pos.y > 0) + { + cursor_pos.x = (int)lines[cursor_pos.y - 1].text.size(); + cursor_pos.y--; + } + else if (steps > 0 && cursor_pos.x == (int)lines[cursor_pos.y].text.size() && cursor_pos.y + 1 < (int)lines.size()) + { + cursor_pos.x = 0; + cursor_pos.y++; + } + else + { + UTF8Reader utf8_reader(lines[cursor_pos.y].text.data(), lines[cursor_pos.y].text.length()); + utf8_reader.set_position(cursor_pos.x); + if (steps > 0) + { + for (int i = 0; i < steps; i++) + utf8_reader.next(); + } + else if (steps < 0) + { + for (int i = 0; i < -steps; i++) + utf8_reader.prev(); + } + + cursor_pos.x = (int)utf8_reader.position(); + } + + if (shift) + { + selection_length = (int)ToOffset(cursor_pos) - (int)ToOffset(selection_start); + } + else + { + // Clear the selection if a cursor key is pressed but shift isn't down. + selection_start = ivec2(0, 0); + selection_length = 0; + } + + + MoveVerticalScroll(); + Update(); + + undo_info.first_text_insert = true; +} + +std::string TextEdit::break_characters = " ::;,.-"; + +TextEdit::ivec2 TextEdit::FindNextBreakCharacter(ivec2 search_start) +{ + search_start.x++; + if (search_start.x >= int(lines[search_start.y].text.size()) - 1) + return ivec2(lines[search_start.y].text.size(), search_start.y); + + int pos = lines[search_start.y].text.find_first_of(break_characters, search_start.x); + if (pos == std::string::npos) + return ivec2(lines[search_start.y].text.size(), search_start.y); + return ivec2(pos, search_start.y); +} + +TextEdit::ivec2 TextEdit::FindPreviousBreakCharacter(ivec2 search_start) +{ + search_start.x--; + if (search_start.x <= 0) + return ivec2(0, search_start.y); + int pos = lines[search_start.y].text.find_last_of(break_characters, search_start.x); + if (pos == std::string::npos) + return ivec2(0, search_start.y); + return ivec2(pos, search_start.y); +} + +void TextEdit::InsertText(ivec2 pos, const std::string& str) +{ + undo_info.first_erase = false; + if (undo_info.first_text_insert) + { + undo_info.undo_text = GetText(); + undo_info.first_text_insert = false; + } + + // checking if insert exceeds max length + if (ToOffset(ivec2(lines[lines.size() - 1].text.size(), lines.size() - 1)) + str.length() > max_length) + { + return; + } + + std::string::size_type start = 0; + while (true) + { + std::string::size_type next_newline = str.find('\n', start); + + lines[pos.y].text.insert(pos.x, str.substr(start, next_newline - start)); + lines[pos.y].invalidated = true; + + if (next_newline == std::string::npos) + break; + + pos.x += next_newline - start; + + Line line; + line.text = lines[pos.y].text.substr(pos.x); + lines.insert(lines.begin() + pos.y + 1, line); + lines[pos.y].text = lines[pos.y].text.substr(0, pos.x); + lines[pos.y].invalidated = true; + pos = ivec2(0, pos.y + 1); + + start = next_newline + 1; + } + + MoveVerticalScroll(); + + Update(); +} + +void TextEdit::Backspace() +{ + if (undo_info.first_erase) + { + undo_info.first_erase = false; + undo_info.undo_text = GetText(); + } + + if (GetSelectionLength() != 0) + { + DeleteSelectedText(); + ClearSelection(); + Update(); + } + else + { + if (cursor_pos.x > 0) + { + UTF8Reader utf8_reader(lines[cursor_pos.y].text.data(), lines[cursor_pos.y].text.length()); + utf8_reader.set_position(cursor_pos.x); + utf8_reader.prev(); + int length = utf8_reader.char_length(); + lines[cursor_pos.y].text.erase(cursor_pos.x - length, length); + lines[cursor_pos.y].invalidated = true; + cursor_pos.x -= length; + Update(); + } + else if (cursor_pos.y > 0) + { + selection_start = ivec2(lines[cursor_pos.y - 1].text.length(), cursor_pos.y - 1); + selection_length = 1; + DeleteSelectedText(); + } + } + MoveVerticalScroll(); +} + +void TextEdit::Del() +{ + if (undo_info.first_erase) + { + undo_info.first_erase = false; + undo_info.undo_text = GetText(); + } + + if (GetSelectionLength() != 0) + { + DeleteSelectedText(); + ClearSelection(); + Update(); + } + else + { + if (cursor_pos.x < (int)lines[cursor_pos.y].text.size()) + { + UTF8Reader utf8_reader(lines[cursor_pos.y].text.data(), lines[cursor_pos.y].text.length()); + utf8_reader.set_position(cursor_pos.x); + int length = utf8_reader.char_length(); + lines[cursor_pos.y].text.erase(cursor_pos.x, length); + lines[cursor_pos.y].invalidated = true; + Update(); + } + else if (cursor_pos.y + 1 < lines.size()) + { + selection_start = ivec2(lines[cursor_pos.y].text.length(), cursor_pos.y); + selection_length = 1; + DeleteSelectedText(); + } + } + MoveVerticalScroll(); +} + +void TextEdit::OnTimerExpired() +{ + if (IsVisible() == false) + { + timer->Stop(); + return; + } + + if (cursor_blink_visible) + timer->Start(500); + else + timer->Start(500); + + cursor_blink_visible = !cursor_blink_visible; + Update(); +} + +void TextEdit::OnGeometryChanged() +{ + Canvas* canvas = GetCanvas(); + + vertical_text_align = canvas->verticalTextAlign(); + + clip_start_offset = 0; + UpdateVerticalScroll(); +} + +void TextEdit::OnScrollTimerExpired() +{ + if (mouse_moves_left) + Move(-1, false, false); + else + Move(1, false, false); +} + +void TextEdit::OnEnableChanged() +{ + bool enabled = IsEnabled(); + if (!enabled) + { + cursor_blink_visible = false; + timer->Stop(); + } + Update(); +} + +bool TextEdit::InputMaskAcceptsInput(ivec2 cursor_pos, const std::string& str) +{ + return str.find_first_not_of(input_mask) == std::string::npos; +} + +std::string::size_type TextEdit::ToOffset(ivec2 pos) const +{ + if (pos.y < lines.size()) + { + std::string::size_type offset = 0; + for (int line = 0; line < pos.y; line++) + { + offset += lines[line].text.size() + 1; + } + return offset + std::min((size_t)pos.x, lines[pos.y].text.size()); + } + else + { + std::string::size_type offset = 0; + for (size_t line = 0; line < lines.size(); line++) + { + offset += lines[line].text.size() + 1; + } + return offset - 1; + } +} + +TextEdit::ivec2 TextEdit::FromOffset(std::string::size_type offset) const +{ + int line_offset = 0; + for (int line = 0; line < lines.size(); line++) + { + if (offset <= line_offset + lines[line].text.size()) + { + return ivec2(offset - line_offset, line); + } + line_offset += lines[line].text.size() + 1; + } + return ivec2(lines.back().text.size(), lines.size() - 1); +} + +double TextEdit::GetTotalHeight() +{ + Canvas* canvas = GetCanvas(); + LayoutLines(canvas); + if (!lines.empty()) + { + return lines.back().box.bottom(); + } + else + { + return GetHeight(); + } +} + +void TextEdit::LayoutLines(Canvas* canvas) +{ + ivec2 sel_start; + ivec2 sel_end; + if (selection_length > 0) + { + sel_start = selection_start; + sel_end = FromOffset(ToOffset(selection_start) + selection_length); + } + else if (selection_length < 0) + { + sel_start = FromOffset(ToOffset(selection_start) + selection_length); + sel_end = selection_start; + } + + Colorf textColor = GetStyleColor("color"); + Point draw_pos; + for (size_t i = (size_t)vert_scrollbar->GetPosition(); i < lines.size(); i++) + { + Line& line = lines[i]; + if (line.invalidated) + { + line.layout.Clear(); + if (!line.text.empty()) + line.layout.AddText(line.text, font, textColor); + else + line.layout.AddText(" ", font, textColor); // Draw one space character to get the correct height + line.layout.Layout(canvas, GetWidth()); + line.box = Rect(draw_pos, line.layout.GetSize()); + line.invalidated = false; + } + + if (sel_start != sel_end && sel_start.y <= i && sel_end.y >= i) + { + line.layout.SetSelectionRange(sel_start.y < i ? 0 : sel_start.x, sel_end.y > i ? line.text.size() : sel_end.x); + } + else + { + line.layout.SetSelectionRange(0, 0); + } + + line.layout.HideCursor(); + if (HasFocus()) + { + if (cursor_blink_visible && cursor_pos.y == i) + { + line.layout.SetCursorPos(cursor_pos.x); + line.layout.SetCursorColor(textColor); + line.layout.ShowCursor(); + } + } + + line.box.x = draw_pos.x; + line.box.y = draw_pos.y; + line.layout.SetPosition(line.box.topLeft()); + + draw_pos = line.box.bottomLeft(); + } + UpdateVerticalScroll(); +} + +void TextEdit::OnPaint(Canvas* canvas) +{ + LayoutLines(canvas); + for (size_t i = (size_t)vert_scrollbar->GetPosition(); i < lines.size(); i++) + lines[i].layout.DrawLayout(canvas); +} + +TextEdit::ivec2 TextEdit::GetCharacterIndex(Point mouse_wincoords) +{ + Canvas* canvas = GetCanvas(); + for (size_t i = 0; i < lines.size(); i++) + { + Line& line = lines[i]; + if (line.box.top() <= mouse_wincoords.y && line.box.bottom() > mouse_wincoords.y) + { + SpanLayout::HitTestResult result = line.layout.HitTest(canvas, mouse_wincoords); + switch (result.type) + { + case SpanLayout::HitTestResult::inside: + return ivec2(clamp(result.offset, (size_t)0, line.text.size()), i); + case SpanLayout::HitTestResult::outside_left: + return ivec2(0, i); + case SpanLayout::HitTestResult::outside_right: + return ivec2(line.text.size(), i); + } + } + } + + return ivec2(lines.back().text.size(), lines.size() - 1); +} diff --git a/libraries/ZWidget/src/widgets/textlabel/textlabel.cpp b/libraries/ZWidget/src/widgets/textlabel/textlabel.cpp new file mode 100644 index 0000000000..aa6e7e7397 --- /dev/null +++ b/libraries/ZWidget/src/widgets/textlabel/textlabel.cpp @@ -0,0 +1,60 @@ + +#include "widgets/textlabel/textlabel.h" + +TextLabel::TextLabel(Widget* parent) : Widget(parent) +{ +} + +void TextLabel::SetText(const std::string& value) +{ + if (text != value) + { + text = value; + Update(); + } +} + +const std::string& TextLabel::GetText() const +{ + return text; +} + +void TextLabel::SetTextAlignment(TextLabelAlignment alignment) +{ + if (textAlignment != alignment) + { + textAlignment = alignment; + Update(); + } +} + +TextLabelAlignment TextLabel::GetTextAlignment() const +{ + return textAlignment; +} + +double TextLabel::GetPreferredWidth() const +{ + Canvas* canvas = GetCanvas(); + return canvas->measureText(text).width; +} + +double TextLabel::GetPreferredHeight() const +{ + return 20.0; +} + +void TextLabel::OnPaint(Canvas* canvas) +{ + double x = 0.0; + if (textAlignment == TextLabelAlignment::Center) + { + x = (GetWidth() - canvas->measureText(text).width) * 0.5; + } + else if (textAlignment == TextLabelAlignment::Right) + { + x = GetWidth() - canvas->measureText(text).width; + } + + canvas->drawText(Point(x, GetHeight() - 5.0), GetStyleColor("color"), text); +} diff --git a/libraries/ZWidget/src/widgets/toolbar/toolbar.cpp b/libraries/ZWidget/src/widgets/toolbar/toolbar.cpp new file mode 100644 index 0000000000..d028dd2d21 --- /dev/null +++ b/libraries/ZWidget/src/widgets/toolbar/toolbar.cpp @@ -0,0 +1,10 @@ + +#include "widgets/toolbar/toolbar.h" + +Toolbar::Toolbar(Widget* parent) : Widget(parent) +{ +} + +Toolbar::~Toolbar() +{ +} diff --git a/libraries/ZWidget/src/widgets/toolbar/toolbarbutton.cpp b/libraries/ZWidget/src/widgets/toolbar/toolbarbutton.cpp new file mode 100644 index 0000000000..adb6d08bf8 --- /dev/null +++ b/libraries/ZWidget/src/widgets/toolbar/toolbarbutton.cpp @@ -0,0 +1,14 @@ + +#include "widgets/toolbar/toolbarbutton.h" + +ToolbarButton::ToolbarButton(Widget* parent) : Widget(parent) +{ +} + +ToolbarButton::~ToolbarButton() +{ +} + +void ToolbarButton::OnPaint(Canvas* canvas) +{ +} diff --git a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp new file mode 100644 index 0000000000..b863aad029 --- /dev/null +++ b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp @@ -0,0 +1,696 @@ + +#include "sdl2displaywindow.h" +#include + +Uint32 SDL2DisplayWindow::PaintEventNumber = 0xffffffff; +bool SDL2DisplayWindow::ExitRunLoop; +std::unordered_map SDL2DisplayWindow::WindowList; + +class InitSDL +{ +public: + InitSDL() + { + int result = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); + if (result != 0) + throw std::runtime_error(std::string("Unable to initialize SDL:") + SDL_GetError()); + + SDL2DisplayWindow::PaintEventNumber = SDL_RegisterEvents(1); + } +}; + +static void CheckInitSDL() +{ + static InitSDL initsdl; +} + +SDL2DisplayWindow::SDL2DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, SDL2DisplayWindow* owner) : WindowHost(windowHost) +{ + CheckInitSDL(); + + unsigned int flags = SDL_WINDOW_HIDDEN /*| SDL_WINDOW_ALLOW_HIGHDPI*/; + if (popupWindow) + flags |= SDL_WINDOW_BORDERLESS; + int result = SDL_CreateWindowAndRenderer(320, 200, flags, &WindowHandle, &RendererHandle); + if (result != 0) + throw std::runtime_error(std::string("Unable to create SDL window:") + SDL_GetError()); + + WindowList[SDL_GetWindowID(WindowHandle)] = this; +} + +SDL2DisplayWindow::~SDL2DisplayWindow() +{ + WindowList.erase(WindowList.find(SDL_GetWindowID(WindowHandle))); + + if (BackBufferTexture) + { + SDL_DestroyTexture(BackBufferTexture); + BackBufferTexture = nullptr; + } + + SDL_DestroyRenderer(RendererHandle); + SDL_DestroyWindow(WindowHandle); + RendererHandle = nullptr; + WindowHandle = nullptr; +} + +void SDL2DisplayWindow::SetWindowTitle(const std::string& text) +{ + SDL_SetWindowTitle(WindowHandle, text.c_str()); +} + +void SDL2DisplayWindow::SetWindowFrame(const Rect& box) +{ + // SDL2 doesn't really seem to have an API for this. + // The docs aren't clear what you're setting when calling SDL_SetWindowSize. + SetClientFrame(box); +} + +void SDL2DisplayWindow::SetClientFrame(const Rect& box) +{ + // Is there a way to set both in one call? + + double uiscale = GetDpiScale(); + int x = (int)std::round(box.x * uiscale); + int y = (int)std::round(box.y * uiscale); + int w = (int)std::round(box.width * uiscale); + int h = (int)std::round(box.height * uiscale); + + SDL_SetWindowPosition(WindowHandle, x, y); + SDL_SetWindowSize(WindowHandle, w, h); +} + +void SDL2DisplayWindow::Show() +{ + SDL_ShowWindow(WindowHandle); +} + +void SDL2DisplayWindow::ShowFullscreen() +{ + SDL_SetWindowFullscreen(WindowHandle, SDL_WINDOW_FULLSCREEN_DESKTOP); +} + +void SDL2DisplayWindow::ShowMaximized() +{ + SDL_ShowWindow(WindowHandle); + SDL_MaximizeWindow(WindowHandle); +} + +void SDL2DisplayWindow::ShowMinimized() +{ + SDL_ShowWindow(WindowHandle); + SDL_MinimizeWindow(WindowHandle); +} + +void SDL2DisplayWindow::ShowNormal() +{ + SDL_ShowWindow(WindowHandle); + SDL_SetWindowFullscreen(WindowHandle, 0); +} + +void SDL2DisplayWindow::Hide() +{ + SDL_HideWindow(WindowHandle); +} + +void SDL2DisplayWindow::Activate() +{ + SDL_RaiseWindow(WindowHandle); +} + +void SDL2DisplayWindow::ShowCursor(bool enable) +{ + SDL_ShowCursor(enable); +} + +void SDL2DisplayWindow::LockCursor() +{ + SDL_SetWindowGrab(WindowHandle, SDL_TRUE); + SDL_ShowCursor(0); +} + +void SDL2DisplayWindow::UnlockCursor() +{ + SDL_SetWindowGrab(WindowHandle, SDL_FALSE); + SDL_ShowCursor(1); +} + +void SDL2DisplayWindow::CaptureMouse() +{ +} + +void SDL2DisplayWindow::ReleaseMouseCapture() +{ +} + +void SDL2DisplayWindow::SetCursor(StandardCursor cursor) +{ +} + +void SDL2DisplayWindow::Update() +{ + SDL_Event event = {}; + event.type = PaintEventNumber; + event.user.windowID = SDL_GetWindowID(WindowHandle); + SDL_PushEvent(&event); +} + +bool SDL2DisplayWindow::GetKeyState(InputKey key) +{ + int numkeys = 0; + const Uint8* state = SDL_GetKeyboardState(&numkeys); + if (!state) return false; + + SDL_Scancode index = InputKeyToScancode(key); + return (index < numkeys) ? state[index] != 0 : false; +} + +Rect SDL2DisplayWindow::GetWindowFrame() const +{ + int x = 0; + int y = 0; + int w = 0; + int h = 0; + double uiscale = GetDpiScale(); + SDL_GetWindowPosition(WindowHandle, &x, &y); + SDL_GetWindowSize(WindowHandle, &w, &h); + return Rect::xywh(x / uiscale, y / uiscale, w / uiscale, h / uiscale); +} + +Point SDL2DisplayWindow::MapFromGlobal(const Point& pos) const +{ + int x = 0; + int y = 0; + double uiscale = GetDpiScale(); + SDL_GetWindowPosition(WindowHandle, &x, &y); + return Point(pos.x - x / uiscale, pos.y - y / uiscale); +} + +Point SDL2DisplayWindow::MapToGlobal(const Point& pos) const +{ + int x = 0; + int y = 0; + double uiscale = GetDpiScale(); + SDL_GetWindowPosition(WindowHandle, &x, &y); + return Point(pos.x + x / uiscale, pos.y + y / uiscale); +} + +Size SDL2DisplayWindow::GetClientSize() const +{ + int w = 0; + int h = 0; + double uiscale = GetDpiScale(); + SDL_GetWindowSize(WindowHandle, &w, &h); + return Size(w / uiscale, h / uiscale); +} + +int SDL2DisplayWindow::GetPixelWidth() const +{ + int w = 0; + int h = 0; + int result = SDL_GetRendererOutputSize(RendererHandle, &w, &h); + return w; +} + +int SDL2DisplayWindow::GetPixelHeight() const +{ + int w = 0; + int h = 0; + int result = SDL_GetRendererOutputSize(RendererHandle, &w, &h); + return h; +} + +double SDL2DisplayWindow::GetDpiScale() const +{ + // SDL2 doesn't really support this properly. SDL_GetDisplayDPI returns the wrong information according to the docs. + return 1.0; +} + +void SDL2DisplayWindow::PresentBitmap(int width, int height, const uint32_t* pixels) +{ + if (!BackBufferTexture || BackBufferWidth != width || BackBufferHeight != height) + { + if (BackBufferTexture) + { + SDL_DestroyTexture(BackBufferTexture); + BackBufferTexture = nullptr; + } + + BackBufferTexture = SDL_CreateTexture(RendererHandle, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height); + if (!BackBufferTexture) + return; + + BackBufferWidth = width; + BackBufferHeight = height; + } + + int destpitch = 0; + void* dest = nullptr; + int result = SDL_LockTexture(BackBufferTexture, nullptr, &dest, &destpitch); + if (result != 0) return; + for (int y = 0; y < height; y++) + { + const void* sline = pixels + y * width; + void* dline = (uint8_t*)dest + y * destpitch; + memcpy(dline, sline, width << 2); + } + SDL_UnlockTexture(BackBufferTexture); + + SDL_RenderCopy(RendererHandle, BackBufferTexture, nullptr, nullptr); + SDL_RenderPresent(RendererHandle); +} + +void SDL2DisplayWindow::SetBorderColor(uint32_t bgra8) +{ + // SDL doesn't have this +} + +void SDL2DisplayWindow::SetCaptionColor(uint32_t bgra8) +{ + // SDL doesn't have this +} + +void SDL2DisplayWindow::SetCaptionTextColor(uint32_t bgra8) +{ + // SDL doesn't have this +} + +std::string SDL2DisplayWindow::GetClipboardText() +{ + char* buffer = SDL_GetClipboardText(); + if (!buffer) + return {}; + std::string text = buffer; + SDL_free(buffer); + return text; +} + +void SDL2DisplayWindow::SetClipboardText(const std::string& text) +{ + SDL_SetClipboardText(text.c_str()); +} + +void SDL2DisplayWindow::ProcessEvents() +{ + CheckInitSDL(); + + SDL_Event event; + while (SDL_PollEvent(&event) != 0) + { + DispatchEvent(event); + } +} + +void SDL2DisplayWindow::RunLoop() +{ + CheckInitSDL(); + + while (!ExitRunLoop) + { + SDL_Event event = {}; + int result = SDL_WaitEvent(&event); + if (result == 1) + DispatchEvent(event); // Silently ignore if it fails and pray it doesn't busy loop, because SDL and Linux utterly sucks! + } +} + +void SDL2DisplayWindow::ExitLoop() +{ + CheckInitSDL(); + + ExitRunLoop = true; +} + +Size SDL2DisplayWindow::GetScreenSize() +{ + CheckInitSDL(); + + SDL_Rect rect = {}; + int result = SDL_GetDisplayBounds(0, &rect); + if (result != 0) + throw std::runtime_error(std::string("Unable to get screen size:") + SDL_GetError()); + + double uiscale = 1.0; // SDL2 doesn't really support this properly. SDL_GetDisplayDPI returns the wrong information according to the docs. + return Size(rect.w / uiscale, rect.h / uiscale); +} + +void* SDL2DisplayWindow::StartTimer(int timeoutMilliseconds, std::function onTimer) +{ + CheckInitSDL(); + + // To do: implement timers + + return nullptr; +} + +void SDL2DisplayWindow::StopTimer(void* timerID) +{ + CheckInitSDL(); + + // To do: implement timers +} + +SDL2DisplayWindow* SDL2DisplayWindow::FindEventWindow(const SDL_Event& event) +{ + int windowID; + switch (event.type) + { + case SDL_WINDOWEVENT: windowID = event.window.windowID; break; + case SDL_TEXTINPUT: windowID = event.text.windowID; break; + case SDL_KEYUP: windowID = event.key.windowID; break; + case SDL_KEYDOWN: windowID = event.key.windowID; break; + case SDL_MOUSEBUTTONUP: windowID = event.button.windowID; break; + case SDL_MOUSEBUTTONDOWN: windowID = event.button.windowID; break; + case SDL_MOUSEWHEEL: windowID = event.wheel.windowID; break; + case SDL_MOUSEMOTION: windowID = event.motion.windowID; break; + default: + if (event.type == PaintEventNumber) windowID = event.user.windowID; + else return nullptr; + } + + auto it = WindowList.find(windowID); + return it != WindowList.end() ? it->second : nullptr; +} + +void SDL2DisplayWindow::DispatchEvent(const SDL_Event& event) +{ + SDL2DisplayWindow* window = FindEventWindow(event); + if (!window) return; + + switch (event.type) + { + case SDL_WINDOWEVENT: window->OnWindowEvent(event.window); break; + case SDL_TEXTINPUT: window->OnTextInput(event.text); break; + case SDL_KEYUP: window->OnKeyUp(event.key); break; + case SDL_KEYDOWN: window->OnKeyDown(event.key); break; + case SDL_MOUSEBUTTONUP: window->OnMouseButtonUp(event.button); break; + case SDL_MOUSEBUTTONDOWN: window->OnMouseButtonDown(event.button); break; + case SDL_MOUSEWHEEL: window->OnMouseWheel(event.wheel); break; + case SDL_MOUSEMOTION: window->OnMouseMotion(event.motion); break; + default: + if (event.type == PaintEventNumber) window->OnPaintEvent(); + } +} + +void SDL2DisplayWindow::OnWindowEvent(const SDL_WindowEvent& event) +{ + switch (event.event) + { + case SDL_WINDOWEVENT_CLOSE: WindowHost->OnWindowClose(); break; + case SDL_WINDOWEVENT_MOVED: WindowHost->OnWindowGeometryChanged(); break; + case SDL_WINDOWEVENT_RESIZED: WindowHost->OnWindowGeometryChanged(); break; + case SDL_WINDOWEVENT_SHOWN: WindowHost->OnWindowPaint(); break; + case SDL_WINDOWEVENT_EXPOSED: WindowHost->OnWindowPaint(); break; + case SDL_WINDOWEVENT_FOCUS_GAINED: WindowHost->OnWindowActivated(); break; + case SDL_WINDOWEVENT_FOCUS_LOST: WindowHost->OnWindowDeactivated(); break; + } +} + +void SDL2DisplayWindow::OnTextInput(const SDL_TextInputEvent& event) +{ + WindowHost->OnWindowKeyChar(event.text); +} + +void SDL2DisplayWindow::OnKeyUp(const SDL_KeyboardEvent& event) +{ + WindowHost->OnWindowKeyUp(ScancodeToInputKey(event.keysym.scancode)); +} + +void SDL2DisplayWindow::OnKeyDown(const SDL_KeyboardEvent& event) +{ + WindowHost->OnWindowKeyDown(ScancodeToInputKey(event.keysym.scancode)); +} + +InputKey SDL2DisplayWindow::GetMouseButtonKey(const SDL_MouseButtonEvent& event) +{ + switch (event.button) + { + case SDL_BUTTON_LEFT: return InputKey::LeftMouse; + case SDL_BUTTON_MIDDLE: return InputKey::MiddleMouse; + case SDL_BUTTON_RIGHT: return InputKey::RightMouse; + // case SDL_BUTTON_X1: return InputKey::XButton1; + // case SDL_BUTTON_X2: return InputKey::XButton2; + default: return InputKey::None; + } +} + +void SDL2DisplayWindow::OnMouseButtonUp(const SDL_MouseButtonEvent& event) +{ + InputKey key = GetMouseButtonKey(event); + if (key != InputKey::None) + { + WindowHost->OnWindowMouseUp(GetMousePos(event), key); + } +} + +void SDL2DisplayWindow::OnMouseButtonDown(const SDL_MouseButtonEvent& event) +{ + InputKey key = GetMouseButtonKey(event); + if (key != InputKey::None) + { + WindowHost->OnWindowMouseDown(GetMousePos(event), key); + } +} + +void SDL2DisplayWindow::OnMouseWheel(const SDL_MouseWheelEvent& event) +{ + InputKey key = (event.y > 0) ? InputKey::MouseWheelUp : (event.y < 0) ? InputKey::MouseWheelDown : InputKey::None; + if (key != InputKey::None) + { + WindowHost->OnWindowMouseWheel(GetMousePos(event), key); + } +} + +void SDL2DisplayWindow::OnMouseMotion(const SDL_MouseMotionEvent& event) +{ + WindowHost->OnWindowMouseMove(GetMousePos(event)); +} + +void SDL2DisplayWindow::OnPaintEvent() +{ + WindowHost->OnWindowPaint(); +} + +InputKey SDL2DisplayWindow::ScancodeToInputKey(SDL_Scancode keycode) +{ + switch (keycode) + { + case SDL_SCANCODE_BACKSPACE: return InputKey::Backspace; + case SDL_SCANCODE_TAB: return InputKey::Tab; + case SDL_SCANCODE_CLEAR: return InputKey::OEMClear; + case SDL_SCANCODE_RETURN: return InputKey::Enter; + case SDL_SCANCODE_MENU: return InputKey::Alt; + case SDL_SCANCODE_PAUSE: return InputKey::Pause; + case SDL_SCANCODE_ESCAPE: return InputKey::Escape; + case SDL_SCANCODE_SPACE: return InputKey::Space; + case SDL_SCANCODE_END: return InputKey::End; + case SDL_SCANCODE_HOME: return InputKey::Home; + case SDL_SCANCODE_LEFT: return InputKey::Left; + case SDL_SCANCODE_UP: return InputKey::Up; + case SDL_SCANCODE_RIGHT: return InputKey::Right; + case SDL_SCANCODE_DOWN: return InputKey::Down; + case SDL_SCANCODE_SELECT: return InputKey::Select; + case SDL_SCANCODE_PRINTSCREEN: return InputKey::Print; + case SDL_SCANCODE_EXECUTE: return InputKey::Execute; + case SDL_SCANCODE_INSERT: return InputKey::Insert; + case SDL_SCANCODE_DELETE: return InputKey::Delete; + case SDL_SCANCODE_HELP: return InputKey::Help; + case SDL_SCANCODE_0: return InputKey::_0; + case SDL_SCANCODE_1: return InputKey::_1; + case SDL_SCANCODE_2: return InputKey::_2; + case SDL_SCANCODE_3: return InputKey::_3; + case SDL_SCANCODE_4: return InputKey::_4; + case SDL_SCANCODE_5: return InputKey::_5; + case SDL_SCANCODE_6: return InputKey::_6; + case SDL_SCANCODE_7: return InputKey::_7; + case SDL_SCANCODE_8: return InputKey::_8; + case SDL_SCANCODE_9: return InputKey::_9; + case SDL_SCANCODE_A: return InputKey::A; + case SDL_SCANCODE_B: return InputKey::B; + case SDL_SCANCODE_C: return InputKey::C; + case SDL_SCANCODE_D: return InputKey::D; + case SDL_SCANCODE_E: return InputKey::E; + case SDL_SCANCODE_F: return InputKey::F; + case SDL_SCANCODE_G: return InputKey::G; + case SDL_SCANCODE_H: return InputKey::H; + case SDL_SCANCODE_I: return InputKey::I; + case SDL_SCANCODE_J: return InputKey::J; + case SDL_SCANCODE_K: return InputKey::K; + case SDL_SCANCODE_L: return InputKey::L; + case SDL_SCANCODE_M: return InputKey::M; + case SDL_SCANCODE_N: return InputKey::N; + case SDL_SCANCODE_O: return InputKey::O; + case SDL_SCANCODE_P: return InputKey::P; + case SDL_SCANCODE_Q: return InputKey::Q; + case SDL_SCANCODE_R: return InputKey::R; + case SDL_SCANCODE_S: return InputKey::S; + case SDL_SCANCODE_T: return InputKey::T; + case SDL_SCANCODE_U: return InputKey::U; + case SDL_SCANCODE_V: return InputKey::V; + case SDL_SCANCODE_W: return InputKey::W; + case SDL_SCANCODE_X: return InputKey::X; + case SDL_SCANCODE_Y: return InputKey::Y; + case SDL_SCANCODE_Z: return InputKey::Z; + case SDL_SCANCODE_KP_0: return InputKey::NumPad0; + case SDL_SCANCODE_KP_1: return InputKey::NumPad1; + case SDL_SCANCODE_KP_2: return InputKey::NumPad2; + case SDL_SCANCODE_KP_3: return InputKey::NumPad3; + case SDL_SCANCODE_KP_4: return InputKey::NumPad4; + case SDL_SCANCODE_KP_5: return InputKey::NumPad5; + case SDL_SCANCODE_KP_6: return InputKey::NumPad6; + case SDL_SCANCODE_KP_7: return InputKey::NumPad7; + case SDL_SCANCODE_KP_8: return InputKey::NumPad8; + case SDL_SCANCODE_KP_9: return InputKey::NumPad9; + // case SDL_SCANCODE_KP_ENTER: return InputKey::NumPadEnter; + // case SDL_SCANCODE_KP_MULTIPLY: return InputKey::Multiply; + // case SDL_SCANCODE_KP_PLUS: return InputKey::Add; + case SDL_SCANCODE_SEPARATOR: return InputKey::Separator; + // case SDL_SCANCODE_KP_MINUS: return InputKey::Subtract; + case SDL_SCANCODE_KP_PERIOD: return InputKey::NumPadPeriod; + // case SDL_SCANCODE_KP_DIVIDE: return InputKey::Divide; + case SDL_SCANCODE_F1: return InputKey::F1; + case SDL_SCANCODE_F2: return InputKey::F2; + case SDL_SCANCODE_F3: return InputKey::F3; + case SDL_SCANCODE_F4: return InputKey::F4; + case SDL_SCANCODE_F5: return InputKey::F5; + case SDL_SCANCODE_F6: return InputKey::F6; + case SDL_SCANCODE_F7: return InputKey::F7; + case SDL_SCANCODE_F8: return InputKey::F8; + case SDL_SCANCODE_F9: return InputKey::F9; + case SDL_SCANCODE_F10: return InputKey::F10; + case SDL_SCANCODE_F11: return InputKey::F11; + case SDL_SCANCODE_F12: return InputKey::F12; + case SDL_SCANCODE_F13: return InputKey::F13; + case SDL_SCANCODE_F14: return InputKey::F14; + case SDL_SCANCODE_F15: return InputKey::F15; + case SDL_SCANCODE_F16: return InputKey::F16; + case SDL_SCANCODE_F17: return InputKey::F17; + case SDL_SCANCODE_F18: return InputKey::F18; + case SDL_SCANCODE_F19: return InputKey::F19; + case SDL_SCANCODE_F20: return InputKey::F20; + case SDL_SCANCODE_F21: return InputKey::F21; + case SDL_SCANCODE_F22: return InputKey::F22; + case SDL_SCANCODE_F23: return InputKey::F23; + case SDL_SCANCODE_F24: return InputKey::F24; + case SDL_SCANCODE_NUMLOCKCLEAR: return InputKey::NumLock; + case SDL_SCANCODE_SCROLLLOCK: return InputKey::ScrollLock; + case SDL_SCANCODE_LSHIFT: return InputKey::LShift; + case SDL_SCANCODE_RSHIFT: return InputKey::RShift; + case SDL_SCANCODE_LCTRL: return InputKey::LControl; + case SDL_SCANCODE_RCTRL: return InputKey::RControl; + case SDL_SCANCODE_GRAVE: return InputKey::Tilde; + default: return InputKey::None; + } +} + +SDL_Scancode SDL2DisplayWindow::InputKeyToScancode(InputKey inputkey) +{ + switch (inputkey) + { + case InputKey::Backspace: return SDL_SCANCODE_BACKSPACE; + case InputKey::Tab: return SDL_SCANCODE_TAB; + case InputKey::OEMClear: return SDL_SCANCODE_CLEAR; + case InputKey::Enter: return SDL_SCANCODE_RETURN; + case InputKey::Alt: return SDL_SCANCODE_MENU; + case InputKey::Pause: return SDL_SCANCODE_PAUSE; + case InputKey::Escape: return SDL_SCANCODE_ESCAPE; + case InputKey::Space: return SDL_SCANCODE_SPACE; + case InputKey::End: return SDL_SCANCODE_END; + case InputKey::Home: return SDL_SCANCODE_HOME; + case InputKey::Left: return SDL_SCANCODE_LEFT; + case InputKey::Up: return SDL_SCANCODE_UP; + case InputKey::Right: return SDL_SCANCODE_RIGHT; + case InputKey::Down: return SDL_SCANCODE_DOWN; + case InputKey::Select: return SDL_SCANCODE_SELECT; + case InputKey::Print: return SDL_SCANCODE_PRINTSCREEN; + case InputKey::Execute: return SDL_SCANCODE_EXECUTE; + case InputKey::Insert: return SDL_SCANCODE_INSERT; + case InputKey::Delete: return SDL_SCANCODE_DELETE; + case InputKey::Help: return SDL_SCANCODE_HELP; + case InputKey::_0: return SDL_SCANCODE_0; + case InputKey::_1: return SDL_SCANCODE_1; + case InputKey::_2: return SDL_SCANCODE_2; + case InputKey::_3: return SDL_SCANCODE_3; + case InputKey::_4: return SDL_SCANCODE_4; + case InputKey::_5: return SDL_SCANCODE_5; + case InputKey::_6: return SDL_SCANCODE_6; + case InputKey::_7: return SDL_SCANCODE_7; + case InputKey::_8: return SDL_SCANCODE_8; + case InputKey::_9: return SDL_SCANCODE_9; + case InputKey::A: return SDL_SCANCODE_A; + case InputKey::B: return SDL_SCANCODE_B; + case InputKey::C: return SDL_SCANCODE_C; + case InputKey::D: return SDL_SCANCODE_D; + case InputKey::E: return SDL_SCANCODE_E; + case InputKey::F: return SDL_SCANCODE_F; + case InputKey::G: return SDL_SCANCODE_G; + case InputKey::H: return SDL_SCANCODE_H; + case InputKey::I: return SDL_SCANCODE_I; + case InputKey::J: return SDL_SCANCODE_J; + case InputKey::K: return SDL_SCANCODE_K; + case InputKey::L: return SDL_SCANCODE_L; + case InputKey::M: return SDL_SCANCODE_M; + case InputKey::N: return SDL_SCANCODE_N; + case InputKey::O: return SDL_SCANCODE_O; + case InputKey::P: return SDL_SCANCODE_P; + case InputKey::Q: return SDL_SCANCODE_Q; + case InputKey::R: return SDL_SCANCODE_R; + case InputKey::S: return SDL_SCANCODE_S; + case InputKey::T: return SDL_SCANCODE_T; + case InputKey::U: return SDL_SCANCODE_U; + case InputKey::V: return SDL_SCANCODE_V; + case InputKey::W: return SDL_SCANCODE_W; + case InputKey::X: return SDL_SCANCODE_X; + case InputKey::Y: return SDL_SCANCODE_Y; + case InputKey::Z: return SDL_SCANCODE_Z; + case InputKey::NumPad0: return SDL_SCANCODE_KP_0; + case InputKey::NumPad1: return SDL_SCANCODE_KP_1; + case InputKey::NumPad2: return SDL_SCANCODE_KP_2; + case InputKey::NumPad3: return SDL_SCANCODE_KP_3; + case InputKey::NumPad4: return SDL_SCANCODE_KP_4; + case InputKey::NumPad5: return SDL_SCANCODE_KP_5; + case InputKey::NumPad6: return SDL_SCANCODE_KP_6; + case InputKey::NumPad7: return SDL_SCANCODE_KP_7; + case InputKey::NumPad8: return SDL_SCANCODE_KP_8; + case InputKey::NumPad9: return SDL_SCANCODE_KP_9; + // case InputKey::NumPadEnter: return SDL_SCANCODE_KP_ENTER; + // case InputKey::Multiply return SDL_SCANCODE_KP_MULTIPLY:; + // case InputKey::Add: return SDL_SCANCODE_KP_PLUS; + case InputKey::Separator: return SDL_SCANCODE_SEPARATOR; + // case InputKey::Subtract: return SDL_SCANCODE_KP_MINUS; + case InputKey::NumPadPeriod: return SDL_SCANCODE_KP_PERIOD; + // case InputKey::Divide: return SDL_SCANCODE_KP_DIVIDE; + case InputKey::F1: return SDL_SCANCODE_F1; + case InputKey::F2: return SDL_SCANCODE_F2; + case InputKey::F3: return SDL_SCANCODE_F3; + case InputKey::F4: return SDL_SCANCODE_F4; + case InputKey::F5: return SDL_SCANCODE_F5; + case InputKey::F6: return SDL_SCANCODE_F6; + case InputKey::F7: return SDL_SCANCODE_F7; + case InputKey::F8: return SDL_SCANCODE_F8; + case InputKey::F9: return SDL_SCANCODE_F9; + case InputKey::F10: return SDL_SCANCODE_F10; + case InputKey::F11: return SDL_SCANCODE_F11; + case InputKey::F12: return SDL_SCANCODE_F12; + case InputKey::F13: return SDL_SCANCODE_F13; + case InputKey::F14: return SDL_SCANCODE_F14; + case InputKey::F15: return SDL_SCANCODE_F15; + case InputKey::F16: return SDL_SCANCODE_F16; + case InputKey::F17: return SDL_SCANCODE_F17; + case InputKey::F18: return SDL_SCANCODE_F18; + case InputKey::F19: return SDL_SCANCODE_F19; + case InputKey::F20: return SDL_SCANCODE_F20; + case InputKey::F21: return SDL_SCANCODE_F21; + case InputKey::F22: return SDL_SCANCODE_F22; + case InputKey::F23: return SDL_SCANCODE_F23; + case InputKey::F24: return SDL_SCANCODE_F24; + case InputKey::NumLock: return SDL_SCANCODE_NUMLOCKCLEAR; + case InputKey::ScrollLock: return SDL_SCANCODE_SCROLLLOCK; + case InputKey::LShift: return SDL_SCANCODE_LSHIFT; + case InputKey::RShift: return SDL_SCANCODE_RSHIFT; + case InputKey::LControl: return SDL_SCANCODE_LCTRL; + case InputKey::RControl: return SDL_SCANCODE_RCTRL; + case InputKey::Tilde: return SDL_SCANCODE_GRAVE; + default: return (SDL_Scancode)0; + } +} diff --git a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.h b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.h new file mode 100644 index 0000000000..81494dc70a --- /dev/null +++ b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include +#include + +class SDL2DisplayWindow : public DisplayWindow +{ +public: + SDL2DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, SDL2DisplayWindow* owner); + ~SDL2DisplayWindow(); + + void SetWindowTitle(const std::string& text) override; + void SetWindowFrame(const Rect& box) override; + void SetClientFrame(const Rect& box) override; + void Show() override; + void ShowFullscreen() override; + void ShowMaximized() override; + void ShowMinimized() override; + void ShowNormal() override; + void Hide() override; + void Activate() override; + void ShowCursor(bool enable) override; + void LockCursor() override; + void UnlockCursor() override; + void CaptureMouse() override; + void ReleaseMouseCapture() override; + void Update() override; + bool GetKeyState(InputKey key) override; + void SetCursor(StandardCursor cursor) override; + + Rect GetWindowFrame() const override; + Size GetClientSize() const override; + int GetPixelWidth() const override; + int GetPixelHeight() const override; + double GetDpiScale() const override; + + void PresentBitmap(int width, int height, const uint32_t* pixels) override; + + void SetBorderColor(uint32_t bgra8) override; + void SetCaptionColor(uint32_t bgra8) override; + void SetCaptionTextColor(uint32_t bgra8) override; + + std::string GetClipboardText() override; + void SetClipboardText(const std::string& text) override; + + Point MapFromGlobal(const Point& pos) const override; + Point MapToGlobal(const Point& pos) const override; + + void* GetNativeHandle() override { return WindowHandle; } + + static void DispatchEvent(const SDL_Event& event); + static SDL2DisplayWindow* FindEventWindow(const SDL_Event& event); + + void OnWindowEvent(const SDL_WindowEvent& event); + void OnTextInput(const SDL_TextInputEvent& event); + void OnKeyUp(const SDL_KeyboardEvent& event); + void OnKeyDown(const SDL_KeyboardEvent& event); + void OnMouseButtonUp(const SDL_MouseButtonEvent& event); + void OnMouseButtonDown(const SDL_MouseButtonEvent& event); + void OnMouseWheel(const SDL_MouseWheelEvent& event); + void OnMouseMotion(const SDL_MouseMotionEvent& event); + void OnPaintEvent(); + + InputKey GetMouseButtonKey(const SDL_MouseButtonEvent& event); + + static InputKey ScancodeToInputKey(SDL_Scancode keycode); + static SDL_Scancode InputKeyToScancode(InputKey inputkey); + + template + Point GetMousePos(const T& event) + { + double uiscale = GetDpiScale(); + return Point(event.x / uiscale, event.y / uiscale); + } + + static void ProcessEvents(); + static void RunLoop(); + static void ExitLoop(); + static Size GetScreenSize(); + + static void* StartTimer(int timeoutMilliseconds, std::function onTimer); + static void StopTimer(void* timerID); + + DisplayWindowHost* WindowHost = nullptr; + SDL_Window* WindowHandle = nullptr; + SDL_Renderer* RendererHandle = nullptr; + SDL_Texture* BackBufferTexture = nullptr; + int BackBufferWidth = 0; + int BackBufferHeight = 0; + + static bool ExitRunLoop; + static Uint32 PaintEventNumber; + static std::unordered_map WindowList; +}; diff --git a/libraries/ZWidget/src/window/win32/win32displaywindow.cpp b/libraries/ZWidget/src/window/win32/win32displaywindow.cpp new file mode 100644 index 0000000000..eafc4f5272 --- /dev/null +++ b/libraries/ZWidget/src/window/win32/win32displaywindow.cpp @@ -0,0 +1,711 @@ + +#include "win32displaywindow.h" +#include +#include +#include +#include +#include + +#pragma comment(lib, "dwmapi.lib") + +#ifndef HID_USAGE_PAGE_GENERIC +#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01) +#endif + +#ifndef HID_USAGE_GENERIC_MOUSE +#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02) +#endif + +#ifndef HID_USAGE_GENERIC_JOYSTICK +#define HID_USAGE_GENERIC_JOYSTICK ((USHORT) 0x04) +#endif + +#ifndef HID_USAGE_GENERIC_GAMEPAD +#define HID_USAGE_GENERIC_GAMEPAD ((USHORT) 0x05) +#endif + +#ifndef RIDEV_INPUTSINK +#define RIDEV_INPUTSINK (0x100) +#endif + +static std::string from_utf16(const std::wstring& str) +{ + if (str.empty()) return {}; + int needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0, nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + std::string result; + result.resize(needed); + needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size(), nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + return result; +} + +static std::wstring to_utf16(const std::string& str) +{ + if (str.empty()) return {}; + int needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + std::wstring result; + result.resize(needed); + needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size()); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + return result; +} + +Win32DisplayWindow::Win32DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, Win32DisplayWindow* owner) : WindowHost(windowHost) +{ + Windows.push_front(this); + WindowsIterator = Windows.begin(); + + WNDCLASSEX classdesc = {}; + classdesc.cbSize = sizeof(WNDCLASSEX); + classdesc.hInstance = GetModuleHandle(0); + classdesc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + classdesc.lpszClassName = L"ZWidgetWindow"; + classdesc.lpfnWndProc = &Win32DisplayWindow::WndProc; + RegisterClassEx(&classdesc); + + // Microsoft logic at its finest: + // WS_EX_DLGMODALFRAME hides the sysmenu icon + // WS_CAPTION shows the caption (yay! actually a flag that does what it says it does!) + // WS_SYSMENU shows the min/max/close buttons + // WS_THICKFRAME makes the window resizable + + DWORD style = 0, exstyle = 0; + if (popupWindow) + { + style = WS_POPUP; + } + else + { + exstyle = WS_EX_APPWINDOW | WS_EX_DLGMODALFRAME; + style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + } + CreateWindowEx(exstyle, L"ZWidgetWindow", L"", style, 0, 0, 100, 100, owner ? owner->WindowHandle : 0, 0, GetModuleHandle(0), this); + + /* + RAWINPUTDEVICE rid; + rid.usUsagePage = HID_USAGE_PAGE_GENERIC; + rid.usUsage = HID_USAGE_GENERIC_MOUSE; + rid.dwFlags = RIDEV_INPUTSINK; + rid.hwndTarget = WindowHandle; + BOOL result = RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)); + */ +} + +Win32DisplayWindow::~Win32DisplayWindow() +{ + if (WindowHandle) + { + DestroyWindow(WindowHandle); + WindowHandle = 0; + } + + Windows.erase(WindowsIterator); +} + +void Win32DisplayWindow::SetWindowTitle(const std::string& text) +{ + SetWindowText(WindowHandle, to_utf16(text).c_str()); +} + +void Win32DisplayWindow::SetBorderColor(uint32_t bgra8) +{ + bgra8 = bgra8 & 0x00ffffff; + DwmSetWindowAttribute(WindowHandle, 34/*DWMWA_BORDER_COLOR*/, &bgra8, sizeof(uint32_t)); +} + +void Win32DisplayWindow::SetCaptionColor(uint32_t bgra8) +{ + bgra8 = bgra8 & 0x00ffffff; + DwmSetWindowAttribute(WindowHandle, 35/*DWMWA_CAPTION_COLOR*/, &bgra8, sizeof(uint32_t)); +} + +void Win32DisplayWindow::SetCaptionTextColor(uint32_t bgra8) +{ + bgra8 = bgra8 & 0x00ffffff; + DwmSetWindowAttribute(WindowHandle, 36/*DWMWA_TEXT_COLOR*/, &bgra8, sizeof(uint32_t)); +} + +void Win32DisplayWindow::SetWindowFrame(const Rect& box) +{ + double dpiscale = GetDpiScale(); + SetWindowPos(WindowHandle, nullptr, (int)std::round(box.x * dpiscale), (int)std::round(box.y * dpiscale), (int)std::round(box.width * dpiscale), (int)std::round(box.height * dpiscale), SWP_NOACTIVATE | SWP_NOZORDER); +} + +void Win32DisplayWindow::SetClientFrame(const Rect& box) +{ + double dpiscale = GetDpiScale(); + + RECT rect = {}; + rect.left = (int)std::round(box.x * dpiscale); + rect.top = (int)std::round(box.y * dpiscale); + rect.right = rect.left + (int)std::round(box.width * dpiscale); + rect.bottom = rect.top + (int)std::round(box.height * dpiscale); + + DWORD style = (DWORD)GetWindowLongPtr(WindowHandle, GWL_STYLE); + DWORD exstyle = (DWORD)GetWindowLongPtr(WindowHandle, GWL_EXSTYLE); + AdjustWindowRectExForDpi(&rect, style, FALSE, exstyle, GetDpiForWindow(WindowHandle)); + + SetWindowPos(WindowHandle, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER); +} + +void Win32DisplayWindow::Show() +{ + ShowWindow(WindowHandle, SW_SHOW); +} + +void Win32DisplayWindow::ShowFullscreen() +{ + HDC screenDC = GetDC(0); + int width = GetDeviceCaps(screenDC, HORZRES); + int height = GetDeviceCaps(screenDC, VERTRES); + ReleaseDC(0, screenDC); + SetWindowLongPtr(WindowHandle, GWL_EXSTYLE, WS_EX_APPWINDOW); + SetWindowLongPtr(WindowHandle, GWL_STYLE, WS_OVERLAPPED); + SetWindowPos(WindowHandle, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED | SWP_SHOWWINDOW); + Fullscreen = true; +} + +void Win32DisplayWindow::ShowMaximized() +{ + ShowWindow(WindowHandle, SW_SHOWMAXIMIZED); +} + +void Win32DisplayWindow::ShowMinimized() +{ + ShowWindow(WindowHandle, SW_SHOWMINIMIZED); +} + +void Win32DisplayWindow::ShowNormal() +{ + ShowWindow(WindowHandle, SW_NORMAL); +} + +void Win32DisplayWindow::Hide() +{ + ShowWindow(WindowHandle, SW_HIDE); +} + +void Win32DisplayWindow::Activate() +{ + SetFocus(WindowHandle); +} + +void Win32DisplayWindow::ShowCursor(bool enable) +{ +} + +void Win32DisplayWindow::LockCursor() +{ + if (!MouseLocked) + { + MouseLocked = true; + GetCursorPos(&MouseLockPos); + ::ShowCursor(FALSE); + } +} + +void Win32DisplayWindow::UnlockCursor() +{ + if (MouseLocked) + { + MouseLocked = false; + SetCursorPos(MouseLockPos.x, MouseLockPos.y); + ::ShowCursor(TRUE); + } +} + +void Win32DisplayWindow::CaptureMouse() +{ + SetCapture(WindowHandle); +} + +void Win32DisplayWindow::ReleaseMouseCapture() +{ + ReleaseCapture(); +} + +void Win32DisplayWindow::Update() +{ + InvalidateRect(WindowHandle, nullptr, FALSE); +} + +bool Win32DisplayWindow::GetKeyState(InputKey key) +{ + return ::GetKeyState((int)key) & 0x8000; // High bit (0x8000) means key is down, Low bit (0x0001) means key is sticky on (like Caps Lock, Num Lock, etc.) +} + +void Win32DisplayWindow::SetCursor(StandardCursor cursor) +{ + if (cursor != CurrentCursor) + { + CurrentCursor = cursor; + UpdateCursor(); + } +} + +Rect Win32DisplayWindow::GetWindowFrame() const +{ + RECT box = {}; + GetWindowRect(WindowHandle, &box); + double dpiscale = GetDpiScale(); + return Rect(box.left / dpiscale, box.top / dpiscale, box.right / dpiscale, box.bottom / dpiscale); +} + +Point Win32DisplayWindow::MapFromGlobal(const Point& pos) const +{ + double dpiscale = GetDpiScale(); + POINT point = {}; + point.x = (LONG)std::round(pos.x / dpiscale); + point.y = (LONG)std::round(pos.y / dpiscale); + ScreenToClient(WindowHandle, &point); + return Point(point.x * dpiscale, point.y * dpiscale); +} + +Point Win32DisplayWindow::MapToGlobal(const Point& pos) const +{ + double dpiscale = GetDpiScale(); + POINT point = {}; + point.x = (LONG)std::round(pos.x * dpiscale); + point.y = (LONG)std::round(pos.y * dpiscale); + ClientToScreen(WindowHandle, &point); + return Point(point.x / dpiscale, point.y / dpiscale); +} + +Size Win32DisplayWindow::GetClientSize() const +{ + RECT box = {}; + GetClientRect(WindowHandle, &box); + double dpiscale = GetDpiScale(); + return Size(box.right / dpiscale, box.bottom / dpiscale); +} + +int Win32DisplayWindow::GetPixelWidth() const +{ + RECT box = {}; + GetClientRect(WindowHandle, &box); + return box.right; +} + +int Win32DisplayWindow::GetPixelHeight() const +{ + RECT box = {}; + GetClientRect(WindowHandle, &box); + return box.bottom; +} + +double Win32DisplayWindow::GetDpiScale() const +{ + return GetDpiForWindow(WindowHandle) / 96.0; +} + +std::string Win32DisplayWindow::GetClipboardText() +{ + BOOL result = OpenClipboard(WindowHandle); + if (result == FALSE) + throw std::runtime_error("Unable to open clipboard"); + + HANDLE handle = GetClipboardData(CF_UNICODETEXT); + if (handle == 0) + { + CloseClipboard(); + return std::string(); + } + + std::wstring::value_type* data = (std::wstring::value_type*)GlobalLock(handle); + if (data == 0) + { + CloseClipboard(); + return std::string(); + } + std::string str = from_utf16(data); + GlobalUnlock(handle); + + CloseClipboard(); + return str; +} + +void Win32DisplayWindow::SetClipboardText(const std::string& text) +{ + std::wstring text16 = to_utf16(text); + + BOOL result = OpenClipboard(WindowHandle); + if (result == FALSE) + throw std::runtime_error("Unable to open clipboard"); + + result = EmptyClipboard(); + if (result == FALSE) + { + CloseClipboard(); + throw std::runtime_error("Unable to empty clipboard"); + } + + unsigned int length = (unsigned int)((text16.length() + 1) * sizeof(std::wstring::value_type)); + HANDLE handle = GlobalAlloc(GMEM_MOVEABLE, length); + if (handle == 0) + { + CloseClipboard(); + throw std::runtime_error("Unable to allocate clipboard memory"); + } + + void* data = GlobalLock(handle); + if (data == 0) + { + GlobalFree(handle); + CloseClipboard(); + throw std::runtime_error("Unable to lock clipboard memory"); + } + memcpy(data, text16.c_str(), length); + GlobalUnlock(handle); + + HANDLE data_result = SetClipboardData(CF_UNICODETEXT, handle); + + if (data_result == 0) + { + GlobalFree(handle); + CloseClipboard(); + throw std::runtime_error("Unable to set clipboard data"); + } + + CloseClipboard(); +} + +void Win32DisplayWindow::PresentBitmap(int width, int height, const uint32_t* pixels) +{ + BITMAPV5HEADER header = {}; + header.bV5Size = sizeof(BITMAPV5HEADER); + header.bV5Width = width; + header.bV5Height = -height; + header.bV5Planes = 1; + header.bV5BitCount = 32; + header.bV5Compression = BI_BITFIELDS; + header.bV5AlphaMask = 0xff000000; + header.bV5RedMask = 0x00ff0000; + header.bV5GreenMask = 0x0000ff00; + header.bV5BlueMask = 0x000000ff; + header.bV5SizeImage = width * height * sizeof(uint32_t); + header.bV5CSType = LCS_sRGB; + + HDC dc = PaintDC; + if (dc != 0) + { + int result = SetDIBitsToDevice(dc, 0, 0, width, height, 0, 0, 0, height, pixels, (const BITMAPINFO*)&header, BI_RGB); + ReleaseDC(WindowHandle, dc); + } +} + +LRESULT Win32DisplayWindow::OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lparam) +{ + LPARAM result = 0; + if (DwmDefWindowProc(WindowHandle, msg, wparam, lparam, &result)) + return result; + + if (msg == WM_INPUT) + { + bool hasFocus = GetFocus() != 0; + + HRAWINPUT handle = (HRAWINPUT)lparam; + UINT size = 0; + UINT result = GetRawInputData(handle, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER)); + if (result == 0 && size > 0) + { + size *= 2; + std::vector buffer(size); + result = GetRawInputData(handle, RID_INPUT, buffer.data(), &size, sizeof(RAWINPUTHEADER)); + if (result >= 0) + { + RAWINPUT* rawinput = (RAWINPUT*)buffer.data(); + if (rawinput->header.dwType == RIM_TYPEMOUSE) + { + if (hasFocus) + WindowHost->OnWindowRawMouseMove(rawinput->data.mouse.lLastX, rawinput->data.mouse.lLastY); + } + } + } + return DefWindowProc(WindowHandle, msg, wparam, lparam); + } + else if (msg == WM_PAINT) + { + PAINTSTRUCT paintStruct = {}; + PaintDC = BeginPaint(WindowHandle, &paintStruct); + if (PaintDC) + { + WindowHost->OnWindowPaint(); + EndPaint(WindowHandle, &paintStruct); + PaintDC = 0; + } + return 0; + } + else if (msg == WM_ACTIVATE) + { + WindowHost->OnWindowActivated(); + } + else if (msg == WM_MOUSEMOVE) + { + if (MouseLocked && GetFocus() != 0) + { + RECT box = {}; + GetClientRect(WindowHandle, &box); + + POINT center = {}; + center.x = box.right / 2; + center.y = box.bottom / 2; + ClientToScreen(WindowHandle, ¢er); + + SetCursorPos(center.x, center.y); + } + else + { + UpdateCursor(); + } + + if (!TrackMouseActive) + { + TRACKMOUSEEVENT eventTrack = {}; + eventTrack.cbSize = sizeof(TRACKMOUSEEVENT); + eventTrack.hwndTrack = WindowHandle; + eventTrack.dwFlags = TME_LEAVE; + if (TrackMouseEvent(&eventTrack)) + TrackMouseActive = true; + } + + WindowHost->OnWindowMouseMove(GetLParamPos(lparam)); + } + else if (msg == WM_MOUSELEAVE) + { + TrackMouseActive = false; + WindowHost->OnWindowMouseLeave(); + } + else if (msg == WM_LBUTTONDOWN) + { + WindowHost->OnWindowMouseDown(GetLParamPos(lparam), InputKey::LeftMouse); + } + else if (msg == WM_LBUTTONDBLCLK) + { + WindowHost->OnWindowMouseDoubleclick(GetLParamPos(lparam), InputKey::LeftMouse); + } + else if (msg == WM_LBUTTONUP) + { + WindowHost->OnWindowMouseUp(GetLParamPos(lparam), InputKey::LeftMouse); + } + else if (msg == WM_MBUTTONDOWN) + { + WindowHost->OnWindowMouseDown(GetLParamPos(lparam), InputKey::MiddleMouse); + } + else if (msg == WM_MBUTTONDBLCLK) + { + WindowHost->OnWindowMouseDoubleclick(GetLParamPos(lparam), InputKey::MiddleMouse); + } + else if (msg == WM_MBUTTONUP) + { + WindowHost->OnWindowMouseUp(GetLParamPos(lparam), InputKey::MiddleMouse); + } + else if (msg == WM_RBUTTONDOWN) + { + WindowHost->OnWindowMouseDown(GetLParamPos(lparam), InputKey::RightMouse); + } + else if (msg == WM_RBUTTONDBLCLK) + { + WindowHost->OnWindowMouseDoubleclick(GetLParamPos(lparam), InputKey::RightMouse); + } + else if (msg == WM_RBUTTONUP) + { + WindowHost->OnWindowMouseUp(GetLParamPos(lparam), InputKey::RightMouse); + } + else if (msg == WM_MOUSEWHEEL) + { + double delta = GET_WHEEL_DELTA_WPARAM(wparam) / (double)WHEEL_DELTA; + + // Note: WM_MOUSEWHEEL uses screen coordinates. GetLParamPos assumes client coordinates. + double dpiscale = GetDpiScale(); + POINT pos; + pos.x = GET_X_LPARAM(lparam); + pos.y = GET_Y_LPARAM(lparam); + ScreenToClient(WindowHandle, &pos); + + WindowHost->OnWindowMouseWheel(Point(pos.x / dpiscale, pos.y / dpiscale), delta < 0.0 ? InputKey::MouseWheelDown : InputKey::MouseWheelUp); + } + else if (msg == WM_CHAR) + { + wchar_t buf[2] = { (wchar_t)wparam, 0 }; + WindowHost->OnWindowKeyChar(from_utf16(buf)); + } + else if (msg == WM_KEYDOWN) + { + WindowHost->OnWindowKeyDown((InputKey)wparam); + } + else if (msg == WM_KEYUP) + { + WindowHost->OnWindowKeyUp((InputKey)wparam); + } + else if (msg == WM_SETFOCUS) + { + if (MouseLocked) + { + ::ShowCursor(FALSE); + } + } + else if (msg == WM_KILLFOCUS) + { + if (MouseLocked) + { + ::ShowCursor(TRUE); + } + } + else if (msg == WM_CLOSE) + { + WindowHost->OnWindowClose(); + return 0; + } + else if (msg == WM_SIZE) + { + WindowHost->OnWindowGeometryChanged(); + return 0; + } + /*else if (msg == WM_NCCALCSIZE && wparam == TRUE) // calculate client area for the window + { + NCCALCSIZE_PARAMS* calcsize = (NCCALCSIZE_PARAMS*)lparam; + return WVR_REDRAW; + }*/ + + return DefWindowProc(WindowHandle, msg, wparam, lparam); +} + +void Win32DisplayWindow::UpdateCursor() +{ + LPCWSTR cursor = IDC_ARROW; + switch (CurrentCursor) + { + case StandardCursor::arrow: cursor = IDC_ARROW; break; + case StandardCursor::appstarting: cursor = IDC_APPSTARTING; break; + case StandardCursor::cross: cursor = IDC_CROSS; break; + case StandardCursor::hand: cursor = IDC_HAND; break; + case StandardCursor::ibeam: cursor = IDC_IBEAM; break; + case StandardCursor::no: cursor = IDC_NO; break; + case StandardCursor::size_all: cursor = IDC_SIZEALL; break; + case StandardCursor::size_nesw: cursor = IDC_SIZENESW; break; + case StandardCursor::size_ns: cursor = IDC_SIZENS; break; + case StandardCursor::size_nwse: cursor = IDC_SIZENWSE; break; + case StandardCursor::size_we: cursor = IDC_SIZEWE; break; + case StandardCursor::uparrow: cursor = IDC_UPARROW; break; + case StandardCursor::wait: cursor = IDC_WAIT; break; + default: break; + } + + ::SetCursor((HCURSOR)LoadImage(0, cursor, IMAGE_CURSOR, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED)); +} + +Point Win32DisplayWindow::GetLParamPos(LPARAM lparam) const +{ + double dpiscale = GetDpiScale(); + return Point(GET_X_LPARAM(lparam) / dpiscale, GET_Y_LPARAM(lparam) / dpiscale); +} + +LRESULT Win32DisplayWindow::WndProc(HWND windowhandle, UINT msg, WPARAM wparam, LPARAM lparam) +{ + if (msg == WM_CREATE) + { + CREATESTRUCT* createstruct = (CREATESTRUCT*)lparam; + Win32DisplayWindow* viewport = (Win32DisplayWindow*)createstruct->lpCreateParams; + viewport->WindowHandle = windowhandle; + SetWindowLongPtr(windowhandle, GWLP_USERDATA, (LONG_PTR)viewport); + return viewport->OnWindowMessage(msg, wparam, lparam); + } + else + { + Win32DisplayWindow* viewport = (Win32DisplayWindow*)GetWindowLongPtr(windowhandle, GWLP_USERDATA); + if (viewport) + { + LRESULT result = viewport->OnWindowMessage(msg, wparam, lparam); + if (msg == WM_DESTROY) + { + SetWindowLongPtr(windowhandle, GWLP_USERDATA, 0); + viewport->WindowHandle = 0; + } + return result; + } + else + { + return DefWindowProc(windowhandle, msg, wparam, lparam); + } + } +} + +void Win32DisplayWindow::ProcessEvents() +{ + while (true) + { + MSG msg = {}; + if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) <= 0) + break; + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +void Win32DisplayWindow::RunLoop() +{ + while (!ExitRunLoop && !Windows.empty()) + { + MSG msg = {}; + if (GetMessage(&msg, 0, 0, 0) <= 0) + break; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ExitRunLoop = false; +} + +void Win32DisplayWindow::ExitLoop() +{ + ExitRunLoop = true; +} + +Size Win32DisplayWindow::GetScreenSize() +{ + HDC screenDC = GetDC(0); + int screenWidth = GetDeviceCaps(screenDC, HORZRES); + int screenHeight = GetDeviceCaps(screenDC, VERTRES); + double dpiScale = GetDeviceCaps(screenDC, LOGPIXELSX) / 96.0; + ReleaseDC(0, screenDC); + + return Size(screenWidth / dpiScale, screenHeight / dpiScale); +} + +static void CALLBACK Win32TimerCallback(HWND handle, UINT message, UINT_PTR timerID, DWORD timestamp) +{ + auto it = Win32DisplayWindow::Timers.find(timerID); + if (it != Win32DisplayWindow::Timers.end()) + { + it->second(); + } +} + +void* Win32DisplayWindow::StartTimer(int timeoutMilliseconds, std::function onTimer) +{ + UINT_PTR result = SetTimer(0, 0, timeoutMilliseconds, Win32TimerCallback); + if (result == 0) + throw std::runtime_error("Could not create timer"); + Timers[result] = std::move(onTimer); + return (void*)result; +} + +void Win32DisplayWindow::StopTimer(void* timerID) +{ + auto it = Timers.find((UINT_PTR)timerID); + if (it != Timers.end()) + { + Timers.erase(it); + KillTimer(0, (UINT_PTR)timerID); + } +} + +std::list Win32DisplayWindow::Windows; +bool Win32DisplayWindow::ExitRunLoop; + +std::unordered_map> Win32DisplayWindow::Timers; diff --git a/libraries/ZWidget/src/window/win32/win32displaywindow.h b/libraries/ZWidget/src/window/win32/win32displaywindow.h new file mode 100644 index 0000000000..85ed92b64e --- /dev/null +++ b/libraries/ZWidget/src/window/win32/win32displaywindow.h @@ -0,0 +1,93 @@ +#pragma once + +#define NOMINMAX +#define WIN32_MEAN_AND_LEAN +#ifndef WINVER +#define WINVER 0x0605 +#endif +#include + +#include +#include +#include + +class Win32DisplayWindow : public DisplayWindow +{ +public: + Win32DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, Win32DisplayWindow* owner); + ~Win32DisplayWindow(); + + void SetWindowTitle(const std::string& text) override; + void SetWindowFrame(const Rect& box) override; + void SetClientFrame(const Rect& box) override; + void Show() override; + void ShowFullscreen() override; + void ShowMaximized() override; + void ShowMinimized() override; + void ShowNormal() override; + void Hide() override; + void Activate() override; + void ShowCursor(bool enable) override; + void LockCursor() override; + void UnlockCursor() override; + void CaptureMouse() override; + void ReleaseMouseCapture() override; + void Update() override; + bool GetKeyState(InputKey key) override; + + void SetCursor(StandardCursor cursor) override; + void UpdateCursor(); + + Rect GetWindowFrame() const override; + Size GetClientSize() const override; + int GetPixelWidth() const override; + int GetPixelHeight() const override; + double GetDpiScale() const override; + + void PresentBitmap(int width, int height, const uint32_t* pixels) override; + + void SetBorderColor(uint32_t bgra8) override; + void SetCaptionColor(uint32_t bgra8) override; + void SetCaptionTextColor(uint32_t bgra8) override; + + std::string GetClipboardText() override; + void SetClipboardText(const std::string& text) override; + + Point MapFromGlobal(const Point& pos) const override; + Point MapToGlobal(const Point& pos) const override; + + Point GetLParamPos(LPARAM lparam) const; + + void* GetNativeHandle() override { return reinterpret_cast(WindowHandle); } + + static void ProcessEvents(); + static void RunLoop(); + static void ExitLoop(); + static Size GetScreenSize(); + + static void* StartTimer(int timeoutMilliseconds, std::function onTimer); + static void StopTimer(void* timerID); + + static bool ExitRunLoop; + static std::list Windows; + std::list::iterator WindowsIterator; + + static std::unordered_map> Timers; + + LRESULT OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lparam); + static LRESULT CALLBACK WndProc(HWND windowhandle, UINT msg, WPARAM wparam, LPARAM lparam); + + DisplayWindowHost* WindowHost = nullptr; + + HWND WindowHandle = 0; + bool Fullscreen = false; + + bool MouseLocked = false; + POINT MouseLockPos = {}; + + bool TrackMouseActive = false; + + HDC PaintDC = 0; + + StandardCursor CurrentCursor = StandardCursor::arrow; +}; diff --git a/libraries/ZWidget/src/window/window.cpp b/libraries/ZWidget/src/window/window.cpp new file mode 100644 index 0000000000..b19945fedf --- /dev/null +++ b/libraries/ZWidget/src/window/window.cpp @@ -0,0 +1,120 @@ + +#include "window/window.h" +#include + +#ifdef WIN32 + +#include "win32/win32displaywindow.h" + +std::unique_ptr DisplayWindow::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner) +{ + return std::make_unique(windowHost, popupWindow, static_cast(owner)); +} + +void DisplayWindow::ProcessEvents() +{ + Win32DisplayWindow::ProcessEvents(); +} + +void DisplayWindow::RunLoop() +{ + Win32DisplayWindow::RunLoop(); +} + +void DisplayWindow::ExitLoop() +{ + Win32DisplayWindow::ExitLoop(); +} + +Size DisplayWindow::GetScreenSize() +{ + return Win32DisplayWindow::GetScreenSize(); +} + +void* DisplayWindow::StartTimer(int timeoutMilliseconds, std::function onTimer) +{ + return Win32DisplayWindow::StartTimer(timeoutMilliseconds, std::move(onTimer)); +} + +void DisplayWindow::StopTimer(void* timerID) +{ + Win32DisplayWindow::StopTimer(timerID); +} + +#elif defined(__APPLE__) + +std::unique_ptr DisplayWindow::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner) +{ + throw std::runtime_error("DisplayWindow::Create not implemented"); +} + +void DisplayWindow::ProcessEvents() +{ + throw std::runtime_error("DisplayWindow::ProcessEvents not implemented"); +} + +void DisplayWindow::RunLoop() +{ + throw std::runtime_error("DisplayWindow::RunLoop not implemented"); +} + +void DisplayWindow::ExitLoop() +{ + throw std::runtime_error("DisplayWindow::ExitLoop not implemented"); +} + +Size DisplayWindow::GetScreenSize() +{ + throw std::runtime_error("DisplayWindow::GetScreenSize not implemented"); +} + +void* DisplayWindow::StartTimer(int timeoutMilliseconds, std::function onTimer) +{ + throw std::runtime_error("DisplayWindow::StartTimer not implemented"); +} + +void DisplayWindow::StopTimer(void* timerID) +{ + throw std::runtime_error("DisplayWindow::StopTimer not implemented"); +} + +#else + +#include "sdl2/sdl2displaywindow.h" + +std::unique_ptr DisplayWindow::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner) +{ + return std::make_unique(windowHost, popupWindow, static_cast(owner)); +} + +void DisplayWindow::ProcessEvents() +{ + SDL2DisplayWindow::ProcessEvents(); +} + +void DisplayWindow::RunLoop() +{ + SDL2DisplayWindow::RunLoop(); +} + +void DisplayWindow::ExitLoop() +{ + SDL2DisplayWindow::ExitLoop(); +} + +Size DisplayWindow::GetScreenSize() +{ + return SDL2DisplayWindow::GetScreenSize(); +} + +void* DisplayWindow::StartTimer(int timeoutMilliseconds, std::function onTimer) +{ + return SDL2DisplayWindow::StartTimer(timeoutMilliseconds, std::move(onTimer)); +} + +void DisplayWindow::StopTimer(void* timerID) +{ + SDL2DisplayWindow::StopTimer(timerID); +} + +#endif diff --git a/libraries/bzip2/CMakeLists.txt b/libraries/bzip2/CMakeLists.txt index 452954c8a7..c42b46592c 100644 --- a/libraries/bzip2/CMakeLists.txt +++ b/libraries/bzip2/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required( VERSION 3.1.0 ) - make_release_only() if (MSVC) @@ -15,4 +13,5 @@ add_library( bz2 STATIC decompress.c huffman.c randtable.c ) +link_libraries("-static") target_link_libraries( bz2 ) diff --git a/libraries/discordrpc/CMakeLists.txt b/libraries/discordrpc/CMakeLists.txt index a369a7dc16..2c417721a3 100644 --- a/libraries/discordrpc/CMakeLists.txt +++ b/libraries/discordrpc/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required (VERSION 3.2.0) project (DiscordRPC) include(GNUInstallDirs) diff --git a/libraries/dp_rect_pack/dp_rect_pack.h b/libraries/dp_rect_pack/dp_rect_pack.h new file mode 100644 index 0000000000..48c07162ea --- /dev/null +++ b/libraries/dp_rect_pack/dp_rect_pack.h @@ -0,0 +1,672 @@ +/* + * Rectangle packing library. + * v1.1.3 + * + * Copyright (c) 2017-2021 Daniel Plakhotich + * + * 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 acknowledgement 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. + */ + + +#ifndef DP_RECT_PACK_H +#define DP_RECT_PACK_H + +#include +#include +#include + + +#define DP_RECT_PACK_VERSION_MAJOR 1 +#define DP_RECT_PACK_VERSION_MINOR 1 +#define DP_RECT_PACK_VERSION_PATCH 3 + + +namespace dp { +namespace rect_pack { + + +/** + * Status of the RectPacker::InsertResult. + * + * Only InsertStatus::ok indicates a successful insertion; + * all other values are kinds of errors. + */ +struct InsertStatus { + enum Type { + ok, ///< Successful insertion + negativeSize, ///< Width and/or height is negative + zeroSize, ///< Width and/or height is zero + + /** + * Rectangle is too big to fit in a single page. + * + * Width and/or height of the rectangle exceeds the maximum + * size a single page can hold, which is the maximum page size + * minus the padding. + * + * \sa RectPacker::RectPacker() + */ + rectTooBig + }; +}; + + +// A note on the implementation. +// The current algorithm is absolutely the same as in version 1.0.0, +// except that we only keep the leaf nodes of the binary tree. This +// dramatically improves performance and reduces memory usage, but +// growDown() and growRight() methods are harder to understand +// because the leafs insertion order depends on several layers of +// parent branches that don't physically exist. I added comments to +// help you visualize what happens, but it will probably be easier +// to just look at the code of the version 1.0.0. + + +/** + * Rectangle packer. + * + * GeomT is not required to hold negative numbers, and thus can be + * an unsigned integer. It's also possible to use a floating-point + * or a custom numeric type. + * + * A custom type for GeomT should support: + * * Implicit construction from an integer >= 0 + * * Addition and subtraction (including compound assignment) + * * Comparison + * + * \tparam GeomT numeric type to use for geometry + */ +template +class RectPacker { +public: + struct Spacing { + GeomT x; ///< Horizontal spacing + GeomT y; ///< Vertical spacing + + /** + * Construct Spacing with the same spacing for both dimensions. + */ + explicit Spacing(GeomT spacing) + : x(spacing) + , y(spacing) + {} + + Spacing(GeomT x, GeomT y) + : x(x) + , y(y) + {} + }; + + struct Padding { + GeomT top; + GeomT bottom; + GeomT left; + GeomT right; + + /** + * Construct Padding with the same padding for all sides. + */ + explicit Padding(GeomT padding) + : top(padding) + , bottom(padding) + , left(padding) + , right(padding) + {} + + Padding(GeomT top, GeomT bottom, GeomT left, GeomT right) + : top(top) + , bottom(bottom) + , left(left) + , right(right) + {} + }; + + struct Position { + GeomT x; + GeomT y; + + Position() + : x() + , y() + {} + + Position(GeomT x, GeomT y) + : x(x) + , y(y) + {} + }; + + /** + * Result returned by RectPacker::insert(). + */ + struct InsertResult { + /** + * Status of the insertion. + * + * \warning If InsertResult.status is not InsertStatus::ok, + * values of all other fields of InsertResult are undefined. + */ + InsertStatus::Type status; + + /** + * Position of the inserted rectangle within the page. + */ + Position pos; + + /** + * Index of the page in which the rectangle was inserted. + * + * \sa getPageSize() + */ + std::size_t pageIndex; + }; + + /** + * RectPacker constructor. + * + * maxPageWidth and maxPageHeight define the maximum size of + * a single page, including the padding. Depending on this limit + * and the features of GeomT, a RectPacker can work in multipage + * or infinite single-page mode. + * + * To enable infinite single-page mode, you have two choices, + * depending on the properties of GeomT: + * * If GeomT has a physical limit (like any standard integer), + * you can set the maximum size to the maximum positive + * value GeomT can hold. + * * Otherwise, if GeomT is a floating-point type or a custom + * unbounded type, you can set the maximum size to a huge + * value or, if supported by the type, a magic value that + * always bigger than any finite number (like a positive + * infinity for floating-point types). + * + * If GeomT can hold negative values, the maximum page size, spacing, + * and padding will be clamped to 0. Keep in mind that if the + * maximum page size is 0, or if the total padding greater or equal + * to the maximum page size, pages will have no free space for + * rectangles, and all calls to insert() will result in + * InsertStatus::rectTooBig. + * + * \param maxPageWidth maximum width of a page, including + * the horizontal padding + * \param maxPageHeight maximum height of a page, including + * the vertical padding + * \param rectsSpacing space between rectangles + * \param pagePadding space between rectangles and edges of a page + */ + RectPacker( + GeomT maxPageWidth, GeomT maxPageHeight, + const Spacing& rectsSpacing = Spacing(0), + const Padding& pagePadding = Padding(0)) + : ctx(maxPageWidth, maxPageHeight, rectsSpacing, pagePadding) + , pages(1) + {} + + /** + * Return the current number of pages. + * + * \returns number of pages (always > 0) + */ + std::size_t getNumPages() const + { + return pages.size(); + } + + /** + * Return the current size of the page. + * + * \param pageIndex index of the page in range [0..getNumPages()) + * \param[out] width width of the page + * \param[out] height height of the page + * + * \sa getNumPages(), InsertResult::pageIndex + */ + void getPageSize(std::size_t pageIndex, GeomT& width, GeomT& height) const + { + const Size size = pages[pageIndex].getSize(ctx); + width = size.w; + height = size.h; + } + + /** + * Insert a rectangle. + * + * The rectangles you'll feed to insert() should be sorted in + * descending order by comparing first by height, then by width. + * A comparison function for std::sort may look like the following: + * \code + * bool compare(const T& a, const T& b) + * { + * if (a.height != b.height) + * return a.height > b.height; + * else + * return a.width > b.width; + * } + * \endcode + * + * \param width width of the rectangle + * \param height height of the rectangle + * \returns InsertResult + */ + InsertResult insert(GeomT width, GeomT height); +private: + struct Size { + GeomT w; + GeomT h; + + Size(GeomT w, GeomT h) + : w(w) + , h(h) + {} + }; + + struct Context; + class Page { + public: + Page() + : nodes() + , rootSize(0, 0) + , growDownRootBottomIdx(0) + {} + + Size getSize(const Context& ctx) const + { + return Size( + ctx.padding.left + rootSize.w + ctx.padding.right, + ctx.padding.top + rootSize.h + ctx.padding.bottom); + } + + bool insert(Context& ctx, const Size& rect, Position& pos); + private: + struct Node { + Position pos; + Size size; + + Node(GeomT x, GeomT y, GeomT w, GeomT h) + : pos(x, y) + , size(w, h) + {} + }; + + // Leaf nodes of the binary tree in depth-first order + std::vector nodes; + Size rootSize; + // The index of the first leaf bottom node of the new root + // created in growDown(). See the method for more details. + std::size_t growDownRootBottomIdx; + + bool tryInsert(Context& ctx, const Size& rect, Position& pos); + bool findNode( + const Size& rect, + std::size_t& nodeIdx, Position& pos) const; + void subdivideNode( + Context& ctx, std::size_t nodeIdx, const Size& rect); + bool tryGrow(Context& ctx, const Size& rect, Position& pos); + void growDown(Context& ctx, const Size& rect, Position& pos); + void growRight(Context& ctx, const Size& rect, Position& pos); + }; + + struct Context { + Size maxSize; + Spacing spacing; + Padding padding; + + Context( + GeomT maxPageWidth, GeomT maxPageHeight, + const Spacing& rectsSpacing, const Padding& pagePadding); + + static void subtractPadding(GeomT& padding, GeomT& size); + }; + + Context ctx; + std::vector pages; +}; + + +template +typename RectPacker::InsertResult +RectPacker::insert(GeomT width, GeomT height) +{ + InsertResult result; + + if (width < 0 || height < 0) { + result.status = InsertStatus::negativeSize; + return result; + } + + if (width == 0 || height == 0) { + result.status = InsertStatus::zeroSize; + return result; + } + + if (width > ctx.maxSize.w || height > ctx.maxSize.h) { + result.status = InsertStatus::rectTooBig; + return result; + } + + const Size rect(width, height); + + for (std::size_t i = 0; i < pages.size(); ++i) + if (pages[i].insert(ctx, rect, result.pos)) { + result.status = InsertStatus::ok; + result.pageIndex = i; + return result; + } + + pages.push_back(Page()); + Page& page = pages.back(); + page.insert(ctx, rect, result.pos); + result.status = InsertStatus::ok; + result.pageIndex = pages.size() - 1; + + return result; +} + + +template +bool RectPacker::Page::insert( + Context& ctx, const Size& rect, Position& pos) +{ + assert(rect.w > 0); + assert(rect.w <= ctx.maxSize.w); + assert(rect.h > 0); + assert(rect.h <= ctx.maxSize.h); + + // The first insertion should be handled especially since + // growRight() and growDown() add spacing between the root + // and the inserted rectangle. + if (rootSize.w == 0) { + rootSize = rect; + pos.x = ctx.padding.left; + pos.y = ctx.padding.top; + + return true; + } + + return tryInsert(ctx, rect, pos) || tryGrow(ctx, rect, pos); +} + + +template +bool RectPacker::Page::tryInsert( + Context& ctx, const Size& rect, Position& pos) +{ + std::size_t nodeIdx; + if (findNode(rect, nodeIdx, pos)) { + subdivideNode(ctx, nodeIdx, rect); + return true; + } + + return false; +} + + +template +bool RectPacker::Page::findNode( + const Size& rect, std::size_t& nodeIdx, Position& pos) const +{ + for (nodeIdx = 0; nodeIdx < nodes.size(); ++nodeIdx) { + const Node& node = nodes[nodeIdx]; + if (rect.w <= node.size.w && rect.h <= node.size.h) { + pos = node.pos; + return true; + } + } + + return false; +} + + +/** + * Called after a rectangle was inserted in the top left corner of + * a free node to create child nodes from free space, if any. + * + * The node is first cut horizontally along the rect's bottom, + * then vertically along the right edge of the rect. Splitting + * that way is crucial for the algorithm to work correctly. + * + * +---+ + * | | + * +---+---+ + * | | + * +-------+ + */ +template +void RectPacker::Page::subdivideNode( + Context& ctx, std::size_t nodeIdx, const Size& rect) +{ + assert(nodeIdx < nodes.size()); + + Node& node = nodes[nodeIdx]; + + assert(node.size.w >= rect.w); + const GeomT rightW = node.size.w - rect.w; + const bool hasSpaceRight = rightW > ctx.spacing.x; + + assert(node.size.h >= rect.h); + const GeomT bottomH = node.size.h - rect.h; + const bool hasSpaceBelow = bottomH > ctx.spacing.y; + + if (hasSpaceRight) { + // Right node replaces the current + + const GeomT bottomX = node.pos.x; + const GeomT bottomW = node.size.w; + + node.pos.x += rect.w + ctx.spacing.x; + node.size.w = rightW - ctx.spacing.x; + node.size.h = rect.h; + + if (hasSpaceBelow) { + nodes.insert( + nodes.begin() + nodeIdx + 1, + Node( + bottomX, + node.pos.y + rect.h + ctx.spacing.y, + bottomW, + bottomH - ctx.spacing.y)); + + if (nodeIdx <= growDownRootBottomIdx) + ++growDownRootBottomIdx; + } + } else if (hasSpaceBelow) { + // Bottom node replaces the current + node.pos.y += rect.h + ctx.spacing.y; + node.size.h = bottomH - ctx.spacing.y; + } else { + nodes.erase(nodes.begin() + nodeIdx); + if (nodeIdx < growDownRootBottomIdx) + --growDownRootBottomIdx; + } +} + + +template +bool RectPacker::Page::tryGrow( + Context& ctx, const Size& rect, Position& pos) +{ + assert(ctx.maxSize.w >= rootSize.w); + const GeomT freeW = ctx.maxSize.w - rootSize.w; + assert(ctx.maxSize.h >= rootSize.h); + const GeomT freeH = ctx.maxSize.h - rootSize.h; + + const bool canGrowDown = ( + freeH >= rect.h && freeH - rect.h >= ctx.spacing.y); + const bool mustGrowDown = ( + canGrowDown + && freeW >= ctx.spacing.x + && (rootSize.w + ctx.spacing.x + >= rootSize.h + rect.h + ctx.spacing.y)); + if (mustGrowDown) { + growDown(ctx, rect, pos); + return true; + } + + const bool canGrowRight = ( + freeW >= rect.w && freeW - rect.w >= ctx.spacing.x); + if (canGrowRight) { + growRight(ctx, rect, pos); + return true; + } + + if (canGrowDown) { + growDown(ctx, rect, pos); + return true; + } + + return false; +} + + +template +void RectPacker::Page::growDown( + Context& ctx, const Size& rect, Position& pos) +{ + assert(ctx.maxSize.h > rootSize.h); + assert(ctx.maxSize.h - rootSize.h >= rect.h); + assert(ctx.maxSize.h - rootSize.h - rect.h >= ctx.spacing.y); + + pos.x = ctx.padding.left; + pos.y = ctx.padding.top + rootSize.h + ctx.spacing.y; + + if (rootSize.w < rect.w) { + if (rect.w - rootSize.w > ctx.spacing.x) { + // The auxiliary node becomes the right child of the new + // root. It contains the current root (bottom child) and + // free space at the current root's right (right child). + nodes.insert( + nodes.begin(), + Node( + ctx.padding.left + rootSize.w + ctx.spacing.x, + ctx.padding.top, + rect.w - rootSize.w - ctx.spacing.x, + rootSize.h)); + ++growDownRootBottomIdx; + } + + rootSize.w = rect.w; + } else if (rootSize.w - rect.w > ctx.spacing.x) { + // Free space at the right of the inserted rect becomes the + // right child of the rect's node, which in turn is the + // bottom child of the new root. + nodes.insert( + nodes.begin() + growDownRootBottomIdx, + Node( + pos.x + rect.w + ctx.spacing.x, + pos.y, + rootSize.w - rect.w - ctx.spacing.x, + rect.h)); + + // The inserted node is visited before the node from the next + // growDown() since the current new root will be the right + // child of the next root. + ++growDownRootBottomIdx; + } + + rootSize.h += ctx.spacing.y + rect.h; +} + + +template +void RectPacker::Page::growRight( + Context& ctx, const Size& rect, Position& pos) +{ + assert(ctx.maxSize.w > rootSize.w); + assert(ctx.maxSize.w - rootSize.w >= rect.w); + assert(ctx.maxSize.w - rootSize.w - rect.w >= ctx.spacing.x); + + pos.x = ctx.padding.left + rootSize.w + ctx.spacing.x; + pos.y = ctx.padding.top; + + if (rootSize.h < rect.h) { + if (rect.h - rootSize.h > ctx.spacing.y) + // The auxiliary node becomes the bottom child of the + // new root. It contains the current root (right child) + // and free space at the current root's bottom, if any + // (bottom child). + nodes.insert( + nodes.end(), + Node( + ctx.padding.left, + ctx.padding.top + rootSize.h + ctx.spacing.y, + rootSize.w, + rect.h - rootSize.h - ctx.spacing.y)); + + rootSize.h = rect.h; + } else if (rootSize.h - rect.h > ctx.spacing.y) { + // Free space at the bottom of the inserted rect becomes the + // bottom child of the rect's node, which in turn is the + // right child of the new root node. + nodes.insert( + nodes.begin(), + Node( + pos.x, + pos.y + rect.h + ctx.spacing.y, + rect.w, + rootSize.h - rect.h - ctx.spacing.y)); + ++growDownRootBottomIdx; + } + + rootSize.w += ctx.spacing.x + rect.w; +} + + +template +RectPacker::Context::Context( + GeomT maxPageWidth, GeomT maxPageHeight, + const Spacing& rectsSpacing, const Padding& pagePadding) + : maxSize(maxPageWidth, maxPageHeight) + , spacing(rectsSpacing) + , padding(pagePadding) +{ + if (maxSize.w < 0) + maxSize.w = 0; + if (maxSize.h < 0) + maxSize.h = 0; + + if (spacing.x < 0) + spacing.x = 0; + if (spacing.y < 0) + spacing.y = 0; + + subtractPadding(padding.top, maxSize.h); + subtractPadding(padding.bottom, maxSize.h); + subtractPadding(padding.left, maxSize.w); + subtractPadding(padding.right, maxSize.w); +} + + +template +void RectPacker::Context::subtractPadding( + GeomT& padding, GeomT& size) +{ + if (padding < 0) + padding = 0; + else if (padding < size) + size -= padding; + else { + padding = size; + size = 0; + } +} + + +} // namespace rect_pack +} // namespace dp + + +#endif // DP_RECT_PACK_H \ No newline at end of file diff --git a/libraries/gdtoa/CMakeLists.txt b/libraries/gdtoa/CMakeLists.txt deleted file mode 100644 index 834340909d..0000000000 --- a/libraries/gdtoa/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -cmake_minimum_required( VERSION 3.1.0 ) - -set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG" ) - -# Disable warnings for << operator precedence (4554) and -# unreferenced labels (4102) from VC -if( MSVC ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4554 /wd4102" ) -endif() - -if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra" ) -endif() - -include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) -add_definitions( -DINFNAN_CHECK -DMULTIPLE_THREADS ) - -if( NOT MSVC AND NOT APPLE ) - if( NOT CMAKE_CROSSCOMPILING ) - add_executable( arithchk arithchk.c ) - endif() - add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/arith.h - COMMAND arithchk >${CMAKE_CURRENT_BINARY_DIR}/arith.h - DEPENDS arithchk ) - - if( NOT CMAKE_CROSSCOMPILING ) - add_executable( qnan qnan.c arith.h ) - set( CROSS_EXPORTS ${CROSS_EXPORTS} arithchk qnan PARENT_SCOPE ) - endif() - add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h - COMMAND qnan >${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h - DEPENDS qnan ) - - set( GEN_FP_FILES arith.h gd_qnan.h ) - set( GEN_FP_DEPS ${CMAKE_CURRENT_BINARY_DIR}/arith.h ${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h ) -endif() - -add_library( gdtoa STATIC - ${GEN_FP_FILES} - dmisc.c - dtoa.c - misc.c - ) -target_link_libraries( gdtoa ) - diff --git a/libraries/gdtoa/README b/libraries/gdtoa/README deleted file mode 100644 index 1bf7d91e43..0000000000 --- a/libraries/gdtoa/README +++ /dev/null @@ -1,400 +0,0 @@ -This directory contains source for a library of binary -> decimal -and decimal -> binary conversion routines, for single-, double-, -and extended-precision IEEE binary floating-point arithmetic, and -other IEEE-like binary floating-point, including "double double", -as in - - T. J. Dekker, "A Floating-Point Technique for Extending the - Available Precision", Numer. Math. 18 (1971), pp. 224-242 - -and - - "Inside Macintosh: PowerPC Numerics", Addison-Wesley, 1994 - -The conversion routines use double-precision floating-point arithmetic -and, where necessary, high precision integer arithmetic. The routines -are generalizations of the strtod and dtoa routines described in - - David M. Gay, "Correctly Rounded Binary-Decimal and - Decimal-Binary Conversions", Numerical Analysis Manuscript - No. 90-10, Bell Labs, Murray Hill, 1990; - http://cm.bell-labs.com/cm/cs/what/ampl/REFS/rounding.ps.gz - -(based in part on papers by Clinger and Steele & White: see the -references in the above paper). - -The present conversion routines should be able to use any of IEEE binary, -VAX, or IBM-mainframe double-precision arithmetic internally, but I (dmg) -have so far only had a chance to test them with IEEE double precision -arithmetic. - -The core conversion routines are strtodg for decimal -> binary conversions -and gdtoa for binary -> decimal conversions. These routines operate -on arrays of unsigned 32-bit integers of type ULong, a signed 32-bit -exponent of type Long, and arithmetic characteristics described in -struct FPI; FPI, Long, and ULong are defined in gdtoa.h. File arith.h -is supposed to provide #defines that cause gdtoa.h to define its -types correctly. File arithchk.c is source for a program that -generates a suitable arith.h on all systems where I've been able to -test it. - -The core conversion routines are meant to be called by helper routines -that know details of the particular binary arithmetic of interest and -convert. The present directory provides helper routines for 5 variants -of IEEE binary floating-point arithmetic, each indicated by one or -two letters: - - f IEEE single precision - d IEEE double precision - x IEEE extended precision, as on Intel 80x87 - and software emulations of Motorola 68xxx chips - that do not pad the way the 68xxx does, but - only store 80 bits - xL IEEE extended precision, as on Motorola 68xxx chips - Q quad precision, as on Sun Sparc chips - dd double double, pairs of IEEE double numbers - whose sum is the desired value - -For decimal -> binary conversions, there are three families of -helper routines: one for round-nearest (or the current rounding -mode on IEEE-arithmetic systems that provide the C99 fegetround() -function, if compiled with -DHonor_FLT_ROUNDS): - - strtof - strtod - strtodd - strtopd - strtopf - strtopx - strtopxL - strtopQ - -one with rounding direction specified: - - strtorf - strtord - strtordd - strtorx - strtorxL - strtorQ - -and one for computing an interval (at most one bit wide) that contains -the decimal number: - - strtoIf - strtoId - strtoIdd - strtoIx - strtoIxL - strtoIQ - -The latter call strtoIg, which makes one call on strtodg and adjusts -the result to provide the desired interval. On systems where native -arithmetic can easily make one-ulp adjustments on values in the -desired floating-point format, it might be more efficient to use the -native arithmetic. Routine strtodI is a variant of strtoId that -illustrates one way to do this for IEEE binary double-precision -arithmetic -- but whether this is more efficient remains to be seen. - -Functions strtod and strtof have "natural" return types, float and -double -- strtod is specified by the C standard, and strtof appears -in the stdlib.h of some systems, such as (at least some) Linux systems. -The other functions write their results to their final argument(s): -to the final two argument for the strtoI... (interval) functions, -and to the final argument for the others (strtop... and strtor...). -Where possible, these arguments have "natural" return types (double* -or float*), to permit at least some type checking. In reality, they -are viewed as arrays of ULong (or, for the "x" functions, UShort) -values. On systems where long double is the appropriate type, one can -pass long double* final argument(s) to these routines. The int value -that these routines return is the return value from the call they make -on strtodg; see the enum of possible return values in gdtoa.h. - -Source files g_ddfmt.c, misc.c, smisc.c, strtod.c, strtodg.c, and ulp.c -should use true IEEE double arithmetic (not, e.g., double extended), -at least for storing (and viewing the bits of) the variables declared -"double" within them. - -One detail indicated in struct FPI is whether the target binary -arithmetic departs from the IEEE standard by flushing denormalized -numbers to 0. On systems that do this, the helper routines for -conversion to double-double format (when compiled with -Sudden_Underflow #defined) penalize the bottom of the exponent -range so that they return a nonzero result only when the least -significant bit of the less significant member of the pair of -double values returned can be expressed as a normalized double -value. An alternative would be to drop to 53-bit precision near -the bottom of the exponent range. To get correct rounding, this -would (in general) require two calls on strtodg (one specifying -126-bit arithmetic, then, if necessary, one specifying 53-bit -arithmetic). - -By default, the core routine strtodg and strtod set errno to ERANGE -if the result overflows to +Infinity or underflows to 0. Compile -these routines with NO_ERRNO #defined to inhibit errno assignments. - -Routine strtod is based on netlib's "dtoa.c from fp", and -(f = strtod(s,se)) is more efficient for some conversions than, say, -strtord(s,se,1,&f). Parts of strtod require true IEEE double -arithmetic with the default rounding mode (round-to-nearest) and, on -systems with IEEE extended-precision registers, double-precision -(53-bit) rounding precision. If the machine uses (the equivalent of) -Intel 80x87 arithmetic, the call - _control87(PC_53, MCW_PC); -does this with many compilers. Whether this or another call is -appropriate depends on the compiler; for this to work, it may be -necessary to #include "float.h" or another system-dependent header -file. - -Source file strtodnrp.c gives a strtod that does not require 53-bit -rounding precision on systems (such as Intel IA32 systems) that may -suffer double rounding due to use of extended-precision registers. -For some conversions this variant of strtod is less efficient than the -one in strtod.c when the latter is run with 53-bit rounding precision. - -When float or double are involved, the values that the strto* routines -return for NaNs are determined by gd_qnan.h, which the makefile -generates by running the program whose source is qnan.c. For other -types, default NaN values are specified in g__fmt.c and may need -adjusting. Note that the rules for distinguishing signaling from -quiet NaNs are system-dependent. For cross-compilation, you need to -determine arith.h and gd_qnan.h suitably, e.g., using the arithmetic -of the target machine. - -C99's hexadecimal floating-point constants are recognized by the -strto* routines (but this feature has not yet been heavily tested). -Compiling with NO_HEX_FP #defined disables this feature. - -When compiled with -DINFNAN_CHECK, the strto* routines recognize C99's -NaN and Infinity syntax. Moreover, unless No_Hex_NaN is #defined, the -strto* routines also recognize C99's NaN(...) syntax: they accept -(case insensitively) strings of the form NaN(x), where x is a string -of hexadecimal digits and spaces; if there is only one string of -hexadecimal digits, it is taken for the fraction bits of the resulting -NaN; if there are two or more strings of hexadecimal digits, each -string is assigned to the next available sequence of 32-bit words of -fractions bits (starting with the most significant), right-aligned in -each sequence. Strings of hexadecimal digits may be preceded by "0x" -or "0X". - -For binary -> decimal conversions, I've provided a family of helper -routines: - - g_ffmt - g_dfmt - g_ddfmt - g_xfmt - g_xLfmt - g_Qfmt - g_ffmt_p - g_dfmt_p - g_ddfmt_p - g_xfmt_p - g_xLfmt_p - g_Qfmt_p - -which do a "%g" style conversion either to a specified number of decimal -places (if their ndig argument is positive), or to the shortest -decimal string that rounds to the given binary floating-point value -(if ndig <= 0). They write into a buffer supplied as an argument -and return either a pointer to the end of the string (a null character) -in the buffer, if the buffer was long enough, or 0. Other forms of -conversion are easily done with the help of gdtoa(), such as %e or %f -style and conversions with direction of rounding specified (so that, if -desired, the decimal value is either >= or <= the binary value). -On IEEE-arithmetic systems that provide the C99 fegetround() function, -if compiled with -DHonor_FLT_ROUNDS, these routines honor the current -rounding mode. For pedants, the ...fmt_p() routines are similar to the -...fmt() routines, but have an additional final int argument, nik, -that for conversions of Infinity or NaN, determines whether upper, -lower, or mixed case is used, whether (...) is added to NaN values, -and whether the sign of a NaN is reported or suppressed: - - nik = ic + 6*(nb + 3*ns), - -where ic with 0 <= ic < 6 controls the rendering of Infinity and NaN: - - 0 ==> Infinity or NaN - 1 ==> infinity or nan - 2 ==> INFINITY or NAN - 3 ==> Inf or NaN - 4 ==> inf or nan - 5 ==> INF or NAN - -nb with 0 <= nb < 3 determines whether NaN values are rendered -as NaN(...): - - 0 ==> no - 1 ==> yes - 2 ==> no for default NaN values; yes otherwise - -ns = 0 or 1 determines whether the sign of NaN values reported: - - 0 ==> distinguish NaN and -NaN - 1 ==> report both as NaN - -For an example of more general conversions based on dtoa(), see -netlib's "printf.c from ampl/solvers". - -For double-double -> decimal, g_ddfmt() assumes IEEE-like arithmetic -of precision max(126, #bits(input)) bits, where #bits(input) is the -number of mantissa bits needed to represent the sum of the two double -values in the input. - -The makefile creates a library, gdtoa.a. To use the helper -routines, a program only needs to include gdtoa.h. All the -source files for gdtoa.a include a more extensive gdtoaimp.h; -among other things, gdtoaimp.h has #defines that make "internal" -names end in _D2A. To make a "system" library, one could modify -these #defines to make the names start with __. - -Various comments about possible #defines appear in gdtoaimp.h, -but for most purposes, arith.h should set suitable #defines. - -Systems with preemptive scheduling of multiple threads require some -manual intervention. On such systems, it's necessary to compile -dmisc.c, dtoa.c gdota.c, and misc.c with MULTIPLE_THREADS #defined, -and to provide (or suitably #define) two locks, acquired by -ACQUIRE_DTOA_LOCK(n) and freed by FREE_DTOA_LOCK(n) for n = 0 or 1. -(The second lock, accessed in pow5mult, ensures lazy evaluation of -only one copy of high powers of 5; omitting this lock would introduce -a small probability of wasting memory, but would otherwise be harmless.) -Routines that call dtoa or gdtoa directly must also invoke freedtoa(s) -to free the value s returned by dtoa or gdtoa. It's OK to do so whether -or not MULTIPLE_THREADS is #defined, and the helper g_*fmt routines -listed above all do this indirectly (in gfmt_D2A(), which they all call). - -By default, there is a private pool of memory of length 2000 bytes -for intermediate quantities, and MALLOC (see gdtoaimp.h) is called only -if the private pool does not suffice. 2000 is large enough that MALLOC -is called only under very unusual circumstances (decimal -> binary -conversion of very long strings) for conversions to and from double -precision. For systems with preemptively scheduled multiple threads -or for conversions to extended or quad, it may be appropriate to -#define PRIVATE_MEM nnnn, where nnnn is a suitable value > 2000. -For extended and quad precisions, -DPRIVATE_MEM=20000 is probably -plenty even for many digits at the ends of the exponent range. -Use of the private pool avoids some overhead. - -Directory test provides some test routines. See its README. -I've also tested this stuff (except double double conversions) -with Vern Paxson's testbase program: see - - V. Paxson and W. Kahan, "A Program for Testing IEEE Binary-Decimal - Conversion", manuscript, May 1991, - ftp://ftp.ee.lbl.gov/testbase-report.ps.Z . - -(The same ftp directory has source for testbase.) - -Some system-dependent additions to CFLAGS in the makefile: - - HU-UX: -Aa -Ae - OSF (DEC Unix): -ieee_with_no_inexact - SunOS 4.1x: -DKR_headers -DBad_float_h - -If you want to put this stuff into a shared library and your -operating system requires export lists for shared libraries, -the following would be an appropriate export list: - - dtoa - freedtoa - g_Qfmt - g_ddfmt - g_dfmt - g_ffmt - g_xLfmt - g_xfmt - gdtoa - strtoIQ - strtoId - strtoIdd - strtoIf - strtoIx - strtoIxL - strtod - strtodI - strtodg - strtof - strtopQ - strtopd - strtopdd - strtopf - strtopx - strtopxL - strtorQ - strtord - strtordd - strtorf - strtorx - strtorxL - -When time permits, I (dmg) hope to write in more detail about the -present conversion routines; for now, this README file must suffice. -Meanwhile, if you wish to write helper functions for other kinds of -IEEE-like arithmetic, some explanation of struct FPI and the bits -array may be helpful. Both gdtoa and strtodg operate on a bits array -described by FPI *fpi. The bits array is of type ULong, a 32-bit -unsigned integer type. Floating-point numbers have fpi->nbits bits, -with the least significant 32 bits in bits[0], the next 32 bits in -bits[1], etc. These numbers are regarded as integers multiplied by -2^e (i.e., 2 to the power of the exponent e), where e is the second -argument (be) to gdtoa and is stored in *exp by strtodg. The minimum -and maximum exponent values fpi->emin and fpi->emax for normalized -floating-point numbers reflect this arrangement. For example, the -P754 standard for binary IEEE arithmetic specifies doubles as having -53 bits, with normalized values of the form 1.xxxxx... times 2^(b-1023), -with 52 bits (the x's) and the biased exponent b represented explicitly; -b is an unsigned integer in the range 1 <= b <= 2046 for normalized -finite doubles, b = 0 for denormals, and b = 2047 for Infinities and NaNs. -To turn an IEEE double into the representation used by strtodg and gdtoa, -we multiply 1.xxxx... by 2^52 (to make it an integer) and reduce the -exponent e = (b-1023) by 52: - - fpi->emin = 1 - 1023 - 52 - fpi->emax = 1046 - 1023 - 52 - -In various wrappers for IEEE double, we actually write -53 + 1 rather -than -52, to emphasize that there are 53 bits including one implicit bit. -Field fpi->rounding indicates the desired rounding direction, with -possible values - FPI_Round_zero = toward 0, - FPI_Round_near = unbiased rounding -- the IEEE default, - FPI_Round_up = toward +Infinity, and - FPI_Round_down = toward -Infinity -given in gdtoa.h. - -Field fpi->sudden_underflow indicates whether strtodg should return -denormals or flush them to zero. Normal floating-point numbers have -bit fpi->nbits in the bits array on. Denormals have it off, with -exponent = fpi->emin. Strtodg provides distinct return values for normals -and denormals; see gdtoa.h. - -Compiling g__fmt.c, strtod.c, and strtodg.c with -DUSE_LOCALE causes -the decimal-point character to be taken from the current locale; otherwise -it is '.'. - -Source files dtoa.c and strtod.c in this directory are derived from -netlib's "dtoa.c from fp" and are meant to function equivalently. -When compiled with Honor_FLT_ROUNDS #defined (on systems that provide -FLT_ROUNDS and fegetround() as specified in the C99 standard), they -honor the current rounding mode. Because FLT_ROUNDS is buggy on some -(Linux) systems -- not reflecting calls on fesetround(), as the C99 -standard says it should -- when Honor_FLT_ROUNDS is #defined, the -current rounding mode is obtained from fegetround() rather than from -FLT_ROUNDS, unless Trust_FLT_ROUNDS is also #defined. - -Compile with -DUSE_LOCALE to use the current locale; otherwise -decimal points are assumed to be '.'. With -DUSE_LOCALE, unless -you also compile with -DNO_LOCALE_CACHE, the details about the -current "decimal point" character string are cached and assumed not -to change during the program's execution. - -On machines with a 64-bit long double and perhaps a 113-bit "quad" -type, you can invoke "make Printf" to add Printf (and variants, such -as Fprintf) to gdtoa.a. These are analogs, declared in stdio1.h, of -printf and fprintf, etc. in which %La, %Le, %Lf, and %Lg are for long -double and (if appropriate) %Lqa, %Lqe, %Lqf, and %Lqg are for quad -precision printing. - -Please send comments to David M. Gay (dmg at acm dot org, with " at " -changed at "@" and " dot " changed to "."). diff --git a/libraries/gdtoa/arithchk.c b/libraries/gdtoa/arithchk.c deleted file mode 100644 index ef6cda3db4..0000000000 --- a/libraries/gdtoa/arithchk.c +++ /dev/null @@ -1,183 +0,0 @@ -/**************************************************************** -Copyright (C) 1997, 1998 Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -****************************************************************/ - -/* Try to deduce arith.h from arithmetic properties. */ - -#include - - static int dalign; - typedef struct -Akind { - char *name; - int kind; - } Akind; - - static Akind -IEEE_8087 = { "IEEE_8087", 1 }, -IEEE_MC68k = { "IEEE_MC68k", 2 }, -IBM = { "IBM", 3 }, -VAX = { "VAX", 4 }, -CRAY = { "CRAY", 5}; - - static Akind * -Lcheck() -{ - union { - double d; - long L[2]; - } u; - struct { - double d; - long L; - } x[2]; - - if (sizeof(x) > 2*(sizeof(double) + sizeof(long))) - dalign = 1; - u.L[0] = u.L[1] = 0; - u.d = 1e13; - if (u.L[0] == 1117925532 && u.L[1] == -448790528) - return &IEEE_MC68k; - if (u.L[1] == 1117925532 && u.L[0] == -448790528) - return &IEEE_8087; - if (u.L[0] == -2065213935 && u.L[1] == 10752) - return &VAX; - if (u.L[0] == 1267827943 && u.L[1] == 704643072) - return &IBM; - return 0; - } - - static Akind * -icheck() -{ - union { - double d; - int L[2]; - } u; - struct { - double d; - int L; - } x[2]; - - if (sizeof(x) > 2*(sizeof(double) + sizeof(int))) - dalign = 1; - u.L[0] = u.L[1] = 0; - u.d = 1e13; - if (u.L[0] == 1117925532 && u.L[1] == -448790528) - return &IEEE_MC68k; - if (u.L[1] == 1117925532 && u.L[0] == -448790528) - return &IEEE_8087; - if (u.L[0] == -2065213935 && u.L[1] == 10752) - return &VAX; - if (u.L[0] == 1267827943 && u.L[1] == 704643072) - return &IBM; - return 0; - } - -char *emptyfmt = ""; /* avoid possible warning message with printf("") */ - - static Akind * -ccheck() -{ - union { - double d; - long L; - } u; - long Cray1; - - /* Cray1 = 4617762693716115456 -- without overflow on non-Crays */ - Cray1 = printf("%s", emptyfmt) < 0 ? 0 : 4617762; - if (printf(emptyfmt, Cray1) >= 0) - Cray1 = 1000000*Cray1 + 693716; - if (printf(emptyfmt, Cray1) >= 0) - Cray1 = 1000000*Cray1 + 115456; - u.d = 1e13; - if (u.L == Cray1) - return &CRAY; - return 0; - } - - static int -fzcheck() -{ - double a, b; - int i; - - a = 1.; - b = .1; - for(i = 155;; b *= b, i >>= 1) { - if (i & 1) { - a *= b; - if (i == 1) - break; - } - } - b = a * a; - return b == 0.; - } - - int -main() -{ - Akind *a = 0; - int Ldef = 0; - FILE *f; - -#ifdef WRITE_ARITH_H /* for Symantec's buggy "make" */ - f = fopen("arith.h", "w"); - if (!f) { - printf("Cannot open arith.h\n"); - return 1; - } -#else - f = stdout; -#endif - - if (sizeof(double) == 2*sizeof(long)) - a = Lcheck(); - else if (sizeof(double) == 2*sizeof(int)) { - Ldef = 1; - a = icheck(); - } - else if (sizeof(double) == sizeof(long)) - a = ccheck(); - if (a) { - fprintf(f, "#define %s\n#define Arith_Kind_ASL %d\n", - a->name, a->kind); - if (Ldef) - fprintf(f, "#define Long int\n#define Intcast (int)(long)\n"); - if (dalign) - fprintf(f, "#define Double_Align\n"); - if (sizeof(char*) == 8) - fprintf(f, "#define X64_bit_pointers\n"); -#ifndef NO_LONG_LONG - if (sizeof(long long) < 8) -#endif - fprintf(f, "#define NO_LONG_LONG\n"); - if (a->kind <= 2 && fzcheck()) - fprintf(f, "#define Sudden_Underflow\n"); - return 0; - } - fprintf(f, "/* Unknown arithmetic */\n"); - return 1; - } diff --git a/libraries/gdtoa/dmisc.c b/libraries/gdtoa/dmisc.c deleted file mode 100644 index 3e712511bb..0000000000 --- a/libraries/gdtoa/dmisc.c +++ /dev/null @@ -1,216 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#ifndef MULTIPLE_THREADS - char *dtoa_result; -#endif - - char * -#ifdef KR_headers -rv_alloc(i) int i; -#else -rv_alloc(int i) -#endif -{ - int j, k, *r; - - j = sizeof(ULong); - for(k = 0; - sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)(i); - j <<= 1) - k++; - r = (int*)Balloc(k); - *r = k; - return -#ifndef MULTIPLE_THREADS - dtoa_result = -#endif - (char *)(r+1); - } - - char * -#ifdef KR_headers -nrv_alloc(s, rve, n) char *s, **rve; int n; -#else -nrv_alloc(char *s, char **rve, int n) -#endif -{ - char *rv, *t; - - t = rv = rv_alloc(n); - while((*t = *s++) !=0) - t++; - if (rve) - *rve = t; - return rv; - } - -/* freedtoa(s) must be used to free values s returned by dtoa - * when MULTIPLE_THREADS is #defined. It should be used in all cases, - * but for consistency with earlier versions of dtoa, it is optional - * when MULTIPLE_THREADS is not defined. - */ - - void -#ifdef KR_headers -freedtoa(s) char *s; -#else -freedtoa(char *s) -#endif -{ - Bigint *b = (Bigint *)((int *)s - 1); - b->maxwds = 1 << (b->k = *(int*)b); - Bfree(b); -#ifndef MULTIPLE_THREADS - if (s == dtoa_result) - dtoa_result = 0; -#endif - } - - int -quorem -#ifdef KR_headers - (b, S) Bigint *b, *S; -#else - (Bigint *b, Bigint *S) -#endif -{ - int n; - ULong *bx, *bxe, q, *sx, *sxe; -#ifdef ULLong - ULLong borrow, carry, y, ys; -#else - ULong borrow, carry, y, ys; -#ifdef Pack_32 - ULong si, z, zs; -#endif -#endif - - n = S->wds; -#ifdef DEBUG - /*debug*/ if (b->wds > n) - /*debug*/ Bug("oversize b in quorem"); -#endif - if (b->wds < n) - return 0; - sx = S->x; - sxe = sx + --n; - bx = b->x; - bxe = bx + n; - q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ -#ifdef DEBUG - /*debug*/ if (q > 9) - /*debug*/ Bug("oversized quotient in quorem"); -#endif - if (q) { - borrow = 0; - carry = 0; - do { -#ifdef ULLong - ys = *sx++ * (ULLong)q + carry; - carry = ys >> 32; - y = *bx - (ys & 0xffffffffUL) - borrow; - borrow = y >> 32 & 1UL; - *bx++ = (ULong)(y & 0xffffffffUL); -#else -#ifdef Pack_32 - si = *sx++; - ys = (si & 0xffff) * q + carry; - zs = (si >> 16) * q + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#else - ys = *sx++ * q + carry; - carry = ys >> 16; - y = *bx - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - *bx++ = y & 0xffff; -#endif -#endif - } - while(sx <= sxe); - if (!*bxe) { - bx = b->x; - while(--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - if (cmp(b, S) >= 0) { - q++; - borrow = 0; - carry = 0; - bx = b->x; - sx = S->x; - do { -#ifdef ULLong - ys = *sx++ + carry; - carry = ys >> 32; - y = *bx - (ys & 0xffffffffUL) - borrow; - borrow = y >> 32 & 1UL; - *bx++ = (ULong)(y & 0xffffffffUL); -#else -#ifdef Pack_32 - si = *sx++; - ys = (si & 0xffff) + carry; - zs = (si >> 16) + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#else - ys = *sx++ + carry; - carry = ys >> 16; - y = *bx - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - *bx++ = y & 0xffff; -#endif -#endif - } - while(sx <= sxe); - bx = b->x; - bxe = bx + n; - if (!*bxe) { - while(--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - return q; - } diff --git a/libraries/gdtoa/dtoa.c b/libraries/gdtoa/dtoa.c deleted file mode 100644 index c96e6a5452..0000000000 --- a/libraries/gdtoa/dtoa.c +++ /dev/null @@ -1,780 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 1999 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - * - * Inspired by "How to Print Floating-Point Numbers Accurately" by - * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. - * - * Modifications: - * 1. Rather than iterating, we use a simple numeric overestimate - * to determine k = floor(log10(d)). We scale relevant - * quantities using O(log2(k)) rather than O(k) multiplications. - * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - * try to generate digits strictly left to right. Instead, we - * compute with fewer bits and propagate the carry if necessary - * when rounding the final digit up. This is often faster. - * 3. Under the assumption that input will be rounded nearest, - * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - * That is, we allow equality in stopping tests when the - * round-nearest rule will give the same floating-point value - * as would satisfaction of the stopping test with strict - * inequality. - * 4. We remove common factors of powers of 2 from relevant - * quantities. - * 5. When converting floating-point integers less than 1e16, - * we use floating-point arithmetic rather than resorting - * to multiple-precision integers. - * 6. When asked to produce fewer than 15 digits, we first try - * to get by with floating-point arithmetic; we resort to - * multiple-precision integer arithmetic only if we cannot - * guarantee that the floating-point calculation has given - * the correctly rounded result. For k requested digits and - * "uniformly" distributed input, the probability is - * something like 10^(k-15) that we must resort to the Long - * calculation. - */ - -#ifdef Honor_FLT_ROUNDS -#undef Check_FLT_ROUNDS -#define Check_FLT_ROUNDS -#else -#define Rounding Flt_Rounds -#endif - - char * -dtoa -#ifdef KR_headers - (d0, mode, ndigits, decpt, sign, rve) - double d0; int mode, ndigits, *decpt, *sign; char **rve; -#else - (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve) -#endif -{ - /* Arguments ndigits, decpt, sign are similar to those - of ecvt and fcvt; trailing zeros are suppressed from - the returned string. If not null, *rve is set to point - to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to 9999. - - mode: - 0 ==> shortest string that yields d when read in - and rounded to nearest. - 1 ==> like 0, but with Steele & White stopping rule; - e.g. with IEEE P754 arithmetic , mode 0 gives - 1e23 whereas mode 1 gives 9.999999999999999e22. - 2 ==> max(1,ndigits) significant digits. This gives a - return value similar to that of ecvt, except - that trailing zeros are suppressed. - 3 ==> through ndigits past the decimal point. This - gives a return value similar to that from fcvt, - except that trailing zeros are suppressed, and - ndigits can be negative. - 4,5 ==> similar to 2 and 3, respectively, but (in - round-nearest mode) with the tests of mode 0 to - possibly return a shorter string that rounds to d. - With IEEE arithmetic and compilation with - -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same - as modes 2 and 3 when FLT_ROUNDS != 1. - 6-9 ==> Debugging modes similar to mode - 4: don't try - fast floating-point estimate (if applicable). - - Values of mode other than 0-9 are treated as mode 0. - - Sufficient space is allocated to the return value - to hold the suppressed trailing zeros. - */ - - int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, - j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, - spec_case, try_quick; - Long L; -#ifndef Sudden_Underflow - int denorm; - ULong x; -#endif - Bigint *b, *b1, *delta, *mlo, *mhi, *S; - U d, d2, eps; - double ds; - char *s, *s0; -#ifdef SET_INEXACT - int inexact, oldinexact; -#endif -#ifdef Honor_FLT_ROUNDS /*{*/ - int Rounding; -#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ - Rounding = Flt_Rounds; -#else /*}{*/ - Rounding = 1; - switch(fegetround()) { - case FE_TOWARDZERO: Rounding = 0; break; - case FE_UPWARD: Rounding = 2; break; - case FE_DOWNWARD: Rounding = 3; - } -#endif /*}}*/ -#endif /*}*/ - -#ifndef MULTIPLE_THREADS - if (dtoa_result) { - freedtoa(dtoa_result); - dtoa_result = 0; - } -#endif - d.d = d0; - if (word0(&d) & Sign_bit) { - /* set sign for everything, including 0's and NaNs */ - *sign = 1; - word0(&d) &= ~Sign_bit; /* clear sign bit */ - } - else - *sign = 0; - -#if defined(IEEE_Arith) + defined(VAX) -#ifdef IEEE_Arith - if ((word0(&d) & Exp_mask) == Exp_mask) -#else - if (word0(&d) == 0x8000) -#endif - { - /* Infinity or NaN */ - *decpt = 9999; -#ifdef IEEE_Arith - if (!word1(&d) && !(word0(&d) & 0xfffff)) - return nrv_alloc("Infinity", rve, 8); -#endif - return nrv_alloc("NaN", rve, 3); - } -#endif -#ifdef IBM - dval(&d) += 0; /* normalize */ -#endif - if (!dval(&d)) { - *decpt = 1; - return nrv_alloc("0", rve, 1); - } - -#ifdef SET_INEXACT - try_quick = oldinexact = get_inexact(); - inexact = 1; -#endif -#ifdef Honor_FLT_ROUNDS - if (Rounding >= 2) { - if (*sign) - Rounding = Rounding == 2 ? 0 : 2; - else - if (Rounding != 2) - Rounding = 0; - } -#endif - - b = d2b(dval(&d), &be, &bbits); -#ifdef Sudden_Underflow - i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); -#else - if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) { -#endif - dval(&d2) = dval(&d); - word0(&d2) &= Frac_mask1; - word0(&d2) |= Exp_11; -#ifdef IBM - if (( j = 11 - hi0bits(word0(&d2) & Frac_mask) )!=0) - dval(&d2) /= 1 << j; -#endif - - /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 - * log10(x) = log(x) / log(10) - * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2) - * - * This suggests computing an approximation k to log10(&d) by - * - * k = (i - Bias)*0.301029995663981 - * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - * - * We want k to be too large rather than too small. - * The error in the first-order Taylor series approximation - * is in our favor, so we just round up the constant enough - * to compensate for any error in the multiplication of - * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - * adding 1e-13 to the constant term more than suffices. - * Hence we adjust the constant term to 0.1760912590558. - * (We could get a more accurate k by invoking log10, - * but this is probably not worthwhile.) - */ - - i -= Bias; -#ifdef IBM - i <<= 2; - i += j; -#endif -#ifndef Sudden_Underflow - denorm = 0; - } - else { - /* d is denormalized */ - - i = bbits + be + (Bias + (P-1) - 1); - x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32) - : word1(&d) << (32 - i); - dval(&d2) = x; - word0(&d2) -= 31*Exp_msk1; /* adjust exponent */ - i -= (Bias + (P-1) - 1) + 1; - denorm = 1; - } -#endif - ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; - k = (int)ds; - if (ds < 0. && ds != k) - k--; /* want k = floor(ds) */ - k_check = 1; - if (k >= 0 && k <= Ten_pmax) { - if (dval(&d) < tens[k]) - k--; - k_check = 0; - } - j = bbits - i - 1; - if (j >= 0) { - b2 = 0; - s2 = j; - } - else { - b2 = -j; - s2 = 0; - } - if (k >= 0) { - b5 = 0; - s5 = k; - s2 += k; - } - else { - b2 -= k; - b5 = -k; - s5 = 0; - } - if (mode < 0 || mode > 9) - mode = 0; - -#ifndef SET_INEXACT -#ifdef Check_FLT_ROUNDS - try_quick = Rounding == 1; -#else - try_quick = 1; -#endif -#endif /*SET_INEXACT*/ - - if (mode > 5) { - mode -= 4; - try_quick = 0; - } - leftright = 1; - ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ - /* silence erroneous "gcc -Wall" warning. */ - switch(mode) { - case 0: - case 1: - i = 18; - ndigits = 0; - break; - case 2: - leftright = 0; - /* no break */ - case 4: - if (ndigits <= 0) - ndigits = 1; - ilim = ilim1 = i = ndigits; - break; - case 3: - leftright = 0; - /* no break */ - case 5: - i = ndigits + k + 1; - ilim = i; - ilim1 = i - 1; - if (i <= 0) - i = 1; - } - s = s0 = rv_alloc(i); - -#ifdef Honor_FLT_ROUNDS - if (mode > 1 && Rounding != 1) - leftright = 0; -#endif - - if (ilim >= 0 && ilim <= Quick_max && try_quick) { - - /* Try to get by with floating-point arithmetic. */ - - i = 0; - dval(&d2) = dval(&d); - k0 = k; - ilim0 = ilim; - ieps = 2; /* conservative */ - if (k > 0) { - ds = tens[k&0xf]; - j = k >> 4; - if (j & Bletch) { - /* prevent overflows */ - j &= Bletch - 1; - dval(&d) /= bigtens[n_bigtens-1]; - ieps++; - } - for(; j; j >>= 1, i++) - if (j & 1) { - ieps++; - ds *= bigtens[i]; - } - dval(&d) /= ds; - } - else if (( j1 = -k )!=0) { - dval(&d) *= tens[j1 & 0xf]; - for(j = j1 >> 4; j; j >>= 1, i++) - if (j & 1) { - ieps++; - dval(&d) *= bigtens[i]; - } - } - if (k_check && dval(&d) < 1. && ilim > 0) { - if (ilim1 <= 0) - goto fast_failed; - ilim = ilim1; - k--; - dval(&d) *= 10.; - ieps++; - } - dval(&eps) = ieps*dval(&d) + 7.; - word0(&eps) -= (P-1)*Exp_msk1; - if (ilim == 0) { - S = mhi = 0; - dval(&d) -= 5.; - if (dval(&d) > dval(&eps)) - goto one_digit; - if (dval(&d) < -dval(&eps)) - goto no_digits; - goto fast_failed; - } -#ifndef No_leftright - if (leftright) { - /* Use Steele & White method of only - * generating digits needed. - */ - dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); - for(i = 0;;) { - L = (Long)dval(&d); - dval(&d) -= L; - *s++ = '0' + (int)L; - if (dval(&d) < dval(&eps)) - goto ret1; - if (1. - dval(&d) < dval(&eps)) - goto bump_up; - if (++i >= ilim) - break; - dval(&eps) *= 10.; - dval(&d) *= 10.; - } - } - else { -#endif - /* Generate ilim digits, then fix them up. */ - dval(&eps) *= tens[ilim-1]; - for(i = 1;; i++, dval(&d) *= 10.) { - L = (Long)(dval(&d)); - if (!(dval(&d) -= L)) - ilim = i; - *s++ = '0' + (int)L; - if (i == ilim) { - if (dval(&d) > 0.5 + dval(&eps)) - goto bump_up; - else if (dval(&d) < 0.5 - dval(&eps)) { - while(*--s == '0'); - s++; - goto ret1; - } - break; - } - } -#ifndef No_leftright - } -#endif - fast_failed: - s = s0; - dval(&d) = dval(&d2); - k = k0; - ilim = ilim0; - } - - /* Do we have a "small" integer? */ - - if (be >= 0 && k <= Int_max) { - /* Yes. */ - ds = tens[k]; - if (ndigits < 0 && ilim <= 0) { - S = mhi = 0; - if (ilim < 0 || dval(&d) <= 5*ds) - goto no_digits; - goto one_digit; - } - for(i = 1;; i++, dval(&d) *= 10.) { - L = (Long)(dval(&d) / ds); - dval(&d) -= L*ds; -#ifdef Check_FLT_ROUNDS - /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(&d) < 0) { - L--; - dval(&d) += ds; - } -#endif - *s++ = '0' + (int)L; - if (!dval(&d)) { -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - if (i == ilim) { -#ifdef Honor_FLT_ROUNDS - if (mode > 1) - switch(Rounding) { - case 0: goto ret1; - case 2: goto bump_up; - } -#endif - dval(&d) += dval(&d); -#ifdef ROUND_BIASED - if (dval(&d) >= ds) -#else - if (dval(&d) > ds || (dval(&d) == ds && L & 1)) -#endif - { - bump_up: - while(*--s == '9') - if (s == s0) { - k++; - *s = '0'; - break; - } - ++*s++; - } - break; - } - } - goto ret1; - } - - m2 = b2; - m5 = b5; - mhi = mlo = 0; - if (leftright) { - i = -#ifndef Sudden_Underflow - denorm ? be + (Bias + (P-1) - 1 + 1) : -#endif -#ifdef IBM - 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); -#else - 1 + P - bbits; -#endif - b2 += i; - s2 += i; - mhi = i2b(1); - } - if (m2 > 0 && s2 > 0) { - i = m2 < s2 ? m2 : s2; - b2 -= i; - m2 -= i; - s2 -= i; - } - if (b5 > 0) { - if (leftright) { - if (m5 > 0) { - mhi = pow5mult(mhi, m5); - b1 = mult(mhi, b); - Bfree(b); - b = b1; - } - if (( j = b5 - m5 )!=0) - b = pow5mult(b, j); - } - else - b = pow5mult(b, b5); - } - S = i2b(1); - if (s5 > 0) - S = pow5mult(S, s5); - - /* Check for special case that d is a normalized power of 2. */ - - spec_case = 0; - if ((mode < 2 || leftright) -#ifdef Honor_FLT_ROUNDS - && Rounding == 1 -#endif - ) { - if (!word1(&d) && !(word0(&d) & Bndry_mask) -#ifndef Sudden_Underflow - && word0(&d) & (Exp_mask & ~Exp_msk1) -#endif - ) { - /* The special case */ - b2 += Log2P; - s2 += Log2P; - spec_case = 1; - } - } - - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - * - * Perhaps we should just compute leading 28 bits of S once - * and for all and pass them and a shift to quorem, so it - * can do shifts and ors to compute the numerator for q. - */ -#ifdef Pack_32 - if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f )!=0) - i = 32 - i; -#else - if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf )!=0) - i = 16 - i; -#endif - if (i > 4) { - i -= 4; - b2 += i; - m2 += i; - s2 += i; - } - else if (i < 4) { - i += 28; - b2 += i; - m2 += i; - s2 += i; - } - if (b2 > 0) - b = lshift(b, b2); - if (s2 > 0) - S = lshift(S, s2); - if (k_check) { - if (cmp(b,S) < 0) { - k--; - b = multadd(b, 10, 0); /* we botched the k estimate */ - if (leftright) - mhi = multadd(mhi, 10, 0); - ilim = ilim1; - } - } - if (ilim <= 0 && (mode == 3 || mode == 5)) { - if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { - /* no digits, fcvt style */ - no_digits: - k = -1 - ndigits; - goto ret; - } - one_digit: - *s++ = '1'; - k++; - goto ret; - } - if (leftright) { - if (m2 > 0) - mhi = lshift(mhi, m2); - - /* Compute mlo -- check for special case - * that d is a normalized power of 2. - */ - - mlo = mhi; - if (spec_case) { - mhi = Balloc(mhi->k); - Bcopy(mhi, mlo); - mhi = lshift(mhi, Log2P); - } - - for(i = 1;;i++) { - dig = quorem(b,S) + '0'; - /* Do we yet have the shortest decimal string - * that will round to d? - */ - j = cmp(b, mlo); - delta = diff(S, mhi); - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); -#ifndef ROUND_BIASED - if (j1 == 0 && mode != 1 && !(word1(&d) & 1) -#ifdef Honor_FLT_ROUNDS - && Rounding >= 1 -#endif - ) { - if (dig == '9') - goto round_9_up; - if (j > 0) - dig++; -#ifdef SET_INEXACT - else if (!b->x[0] && b->wds <= 1) - inexact = 0; -#endif - *s++ = dig; - goto ret; - } -#endif - if (j < 0 || (j == 0 && mode != 1 -#ifndef ROUND_BIASED - && !(word1(&d) & 1) -#endif - )) { - if (!b->x[0] && b->wds <= 1) { -#ifdef SET_INEXACT - inexact = 0; -#endif - goto accept_dig; - } -#ifdef Honor_FLT_ROUNDS - if (mode > 1) - switch(Rounding) { - case 0: goto accept_dig; - case 2: goto keep_dig; - } -#endif /*Honor_FLT_ROUNDS*/ - if (j1 > 0) { - b = lshift(b, 1); - j1 = cmp(b, S); -#ifdef ROUND_BIASED - if (j1 >= 0 /*)*/ -#else - if ((j1 > 0 || (j1 == 0 && dig & 1)) -#endif - && dig++ == '9') - goto round_9_up; - } - accept_dig: - *s++ = dig; - goto ret; - } - if (j1 > 0) { -#ifdef Honor_FLT_ROUNDS - if (!Rounding) - goto accept_dig; -#endif - if (dig == '9') { /* possible if i == 1 */ - round_9_up: - *s++ = '9'; - goto roundoff; - } - *s++ = dig + 1; - goto ret; - } -#ifdef Honor_FLT_ROUNDS - keep_dig: -#endif - *s++ = dig; - if (i == ilim) - break; - b = multadd(b, 10, 0); - if (mlo == mhi) - mlo = mhi = multadd(mhi, 10, 0); - else { - mlo = multadd(mlo, 10, 0); - mhi = multadd(mhi, 10, 0); - } - } - } - else - for(i = 1;; i++) { - *s++ = dig = quorem(b,S) + '0'; - if (!b->x[0] && b->wds <= 1) { -#ifdef SET_INEXACT - inexact = 0; -#endif - goto ret; - } - if (i >= ilim) - break; - b = multadd(b, 10, 0); - } - - /* Round off last digit */ - -#ifdef Honor_FLT_ROUNDS - switch(Rounding) { - case 0: goto trimzeros; - case 2: goto roundoff; - } -#endif - b = lshift(b, 1); - j = cmp(b, S); -#ifdef ROUND_BIASED - if (j >= 0) -#else - if (j > 0 || (j == 0 && dig & 1)) -#endif - { - roundoff: - while(*--s == '9') - if (s == s0) { - k++; - *s++ = '1'; - goto ret; - } - ++*s++; - } - else { -#ifdef Honor_FLT_ROUNDS - trimzeros: -#endif - while(*--s == '0'); - s++; - } - ret: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } - ret1: -#ifdef SET_INEXACT - if (inexact) { - if (!oldinexact) { - word0(&d) = Exp_1 + (70 << Exp_shift); - word1(&d) = 0; - dval(&d) += 1.; - } - } - else if (!oldinexact) - clear_inexact(); -#endif - Bfree(b); - *s = 0; - *decpt = k + 1; - if (rve) - *rve = s; - return s0; - } diff --git a/libraries/gdtoa/g_Qfmt.c b/libraries/gdtoa/g_Qfmt.c deleted file mode 100644 index 0f06970055..0000000000 --- a/libraries/gdtoa/g_Qfmt.c +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#define _3 3 -#endif -#ifdef IEEE_8087 -#define _0 3 -#define _1 2 -#define _2 1 -#define _3 0 -#endif - - char* -#ifdef KR_headers -g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; -#else -g_Qfmt(char *buf, void *V, int ndig, size_t bufsize) -#endif -{ - static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0, Int_max }; - char *b, *s, *se; - ULong bits[4], *L, sign; - int decpt, ex, i, mode; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - if (ndig < 0) - ndig = 0; - if (bufsize < (size_t)(ndig + 10)) - return 0; - - L = (ULong*)V; - sign = L[_0] & 0x80000000L; - bits[3] = L[_0] & 0xffff; - bits[2] = L[_1]; - bits[1] = L[_2]; - bits[0] = L[_3]; - b = buf; - if ( (ex = (L[_0] & 0x7fff0000L) >> 16) !=0) { - if (ex == 0x7fff) { - /* Infinity or NaN */ - if (bits[0] | bits[1] | bits[2] | bits[3]) - b = strcp(b, "NaN"); - else { - b = buf; - if (sign) - *b++ = '-'; - b = strcp(b, "Infinity"); - } - return b; - } - i = STRTOG_Normal; - bits[3] |= 0x10000; - } - else if (bits[0] | bits[1] | bits[2] | bits[3]) { - i = STRTOG_Denormal; - ex = 1; - } - else { -#ifndef IGNORE_ZERO_SIGN - if (sign) - *b++ = '-'; -#endif - *b++ = '0'; - *b = 0; - return b; - } - ex -= 0x3fff + 112; - mode = 2; - if (ndig <= 0) { - if (bufsize < 48) - return 0; - mode = 0; - } - s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign, bufsize); - } diff --git a/libraries/gdtoa/g__fmt.c b/libraries/gdtoa/g__fmt.c deleted file mode 100644 index 652c82b68e..0000000000 --- a/libraries/gdtoa/g__fmt.c +++ /dev/null @@ -1,203 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#ifdef USE_LOCALE -#include "locale.h" -#endif - -#ifndef ldus_QNAN0 -#define ldus_QNAN0 0x7fff -#endif -#ifndef ldus_QNAN1 -#define ldus_QNAN1 0xc000 -#endif -#ifndef ldus_QNAN2 -#define ldus_QNAN2 0 -#endif -#ifndef ldus_QNAN3 -#define ldus_QNAN3 0 -#endif -#ifndef ldus_QNAN4 -#define ldus_QNAN4 0 -#endif - - const char *InfName[6] = { "Infinity", "infinity", "INFINITY", "Inf", "inf", "INF" }; - const char *NanName[3] = { "NaN", "nan", "NAN" }; - ULong NanDflt_Q_D2A[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }; - ULong NanDflt_d_D2A[2] = { d_QNAN1, d_QNAN0 }; - ULong NanDflt_f_D2A[1] = { f_QNAN }; - ULong NanDflt_xL_D2A[3] = { 1, 0x80000000, 0x7fff0000 }; - UShort NanDflt_ldus_D2A[5] = { ldus_QNAN4, ldus_QNAN3, ldus_QNAN2, ldus_QNAN1, ldus_QNAN0 }; - - char * -#ifdef KR_headers -g__fmt(b, s, se, decpt, sign, blen) char *b; char *s; char *se; int decpt; ULong sign; size_t blen; -#else -g__fmt(char *b, char *s, char *se, int decpt, ULong sign, size_t blen) -#endif -{ - int i, j, k; - char *be, *s0; - size_t len; -#ifdef USE_LOCALE -#ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; - size_t dlen = strlen(decimalpoint); -#else - char *decimalpoint; - static char *decimalpoint_cache; - static size_t dlen; - if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; - dlen = strlen(s0); - if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { - strcpy(decimalpoint_cache, s0); - s0 = decimalpoint_cache; - } - } - decimalpoint = s0; -#endif -#else -#define dlen 0 -#endif - s0 = s; - len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */ - if (blen < len) - goto ret0; - be = b + blen - 1; - if (sign) - *b++ = '-'; - if (decpt <= -4 || decpt > se - s + 5) { - *b++ = *s++; - if (*s) { -#ifdef USE_LOCALE - while((*b = *decimalpoint++)) - ++b; -#else - *b++ = '.'; -#endif - while((*b = *s++) !=0) - b++; - } - *b++ = 'e'; - /* sprintf(b, "%+.2d", decpt - 1); */ - if (--decpt < 0) { - *b++ = '-'; - decpt = -decpt; - } - else - *b++ = '+'; - for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){} - for(;;) { - i = decpt / k; - if (b >= be) - goto ret0; - *b++ = i + '0'; - if (--j <= 0) - break; - decpt -= i*k; - decpt *= 10; - } - *b = 0; - } - else if (decpt <= 0) { -#ifdef USE_LOCALE - while((*b = *decimalpoint++)) - ++b; -#else - *b++ = '.'; -#endif - if (be < b - decpt + (se - s)) - goto ret0; - for(; decpt < 0; decpt++) - *b++ = '0'; - while((*b = *s++) != 0) - b++; - } - else { - while((*b = *s++) != 0) { - b++; - if (--decpt == 0 && *s) { -#ifdef USE_LOCALE - while(*b = *decimalpoint++) - ++b; -#else - *b++ = '.'; -#endif - } - } - if (b + decpt > be) { - ret0: - b = 0; - goto ret; - } - for(; decpt > 0; decpt--) - *b++ = '0'; - *b = 0; - } - ret: - freedtoa(s0); - return b; - } - - char * -add_nanbits_D2A(char *b, size_t blen, ULong *bits, int nb) -{ - ULong t; - char *rv; - int i, j; - size_t L; - static char Hexdig[16] = "0123456789abcdef"; - - while(!bits[--nb]) - if (!nb) - return b; - L = 8*nb + 3; - t = bits[nb]; - do ++L; while((t >>= 4)); - if (L > blen) - return b; - b += L; - *--b = 0; - rv = b; - *--b = /*(*/ ')'; - for(i = 0; i < nb; ++i) { - t = bits[i]; - for(j = 0; j < 8; ++j, t >>= 4) - *--b = Hexdig[t & 0xf]; - } - t = bits[nb]; - do *--b = Hexdig[t & 0xf]; while(t >>= 4); - *--b = '('; /*)*/ - return rv; - } diff --git a/libraries/gdtoa/g_ddfmt.c b/libraries/gdtoa/g_ddfmt.c deleted file mode 100644 index 5ce4a076bb..0000000000 --- a/libraries/gdtoa/g_ddfmt.c +++ /dev/null @@ -1,171 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg@acm.org). */ - -#include "gdtoaimp.h" -#include - - char * -#ifdef KR_headers -g_ddfmt(buf, dd0, ndig, bufsize) char *buf; double *dd0; int ndig; size_t bufsize; -#else -g_ddfmt(char *buf, double *dd0, int ndig, size_t bufsize) -#endif -{ - FPI fpi; - char *b, *s, *se; - ULong *L, bits0[4], *bits, *zx; - int bx, by, decpt, ex, ey, i, j, mode; - Bigint *x, *y, *z; - U *dd, ddx[2]; -#ifdef Honor_FLT_ROUNDS /*{{*/ - int Rounding; -#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ - Rounding = Flt_Rounds; -#else /*}{*/ - Rounding = 1; - switch(fegetround()) { - case FE_TOWARDZERO: Rounding = 0; break; - case FE_UPWARD: Rounding = 2; break; - case FE_DOWNWARD: Rounding = 3; - } -#endif /*}}*/ -#else /*}{*/ -#define Rounding FPI_Round_near -#endif /*}}*/ - - if (bufsize < 10 || bufsize < (size_t)(ndig + 8)) - return 0; - - dd = (U*)dd0; - L = dd->L; - if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) { - /* Infinity or NaN */ - if (L[_0] & 0xfffff || L[_1]) { - nanret: - return strcp(buf, "NaN"); - } - if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) { - if (L[2+_0] & 0xfffff || L[2+_1]) - goto nanret; - if ((L[_0] ^ L[2+_0]) & 0x80000000L) - goto nanret; /* Infinity - Infinity */ - } - infret: - b = buf; - if (L[_0] & 0x80000000L) - *b++ = '-'; - return strcp(b, "Infinity"); - } - if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) { - L += 2; - if (L[_0] & 0xfffff || L[_1]) - goto nanret; - goto infret; - } - if (dval(&dd[0]) + dval(&dd[1]) == 0.) { - b = buf; -#ifndef IGNORE_ZERO_SIGN - if (L[_0] & L[2+_0] & 0x80000000L) - *b++ = '-'; -#endif - *b++ = '0'; - *b = 0; - return b; - } - if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) { - dval(&ddx[1]) = dval(&dd[0]); - dval(&ddx[0]) = dval(&dd[1]); - dd = ddx; - L = dd->L; - } - z = d2b(dval(&dd[0]), &ex, &bx); - if (dval(&dd[1]) == 0.) - goto no_y; - x = z; - y = d2b(dval(&dd[1]), &ey, &by); - if ( (i = ex - ey) !=0) { - if (i > 0) { - x = lshift(x, i); - ex = ey; - } - else - y = lshift(y, -i); - } - if ((L[_0] ^ L[2+_0]) & 0x80000000L) { - z = diff(x, y); - if (L[_0] & 0x80000000L) - z->sign = 1 - z->sign; - } - else { - z = sum(x, y); - if (L[_0] & 0x80000000L) - z->sign = 1; - } - Bfree(x); - Bfree(y); - no_y: - bits = zx = z->x; - for(i = 0; !*zx; zx++) - i += 32; - i += lo0bits(zx); - if (i) { - rshift(z, i); - ex += i; - } - fpi.nbits = z->wds * 32 - hi0bits(z->x[j = z->wds-1]); - if (fpi.nbits < 106) { - fpi.nbits = 106; - if (j < 3) { - for(i = 0; i <= j; i++) - bits0[i] = bits[i]; - while(i < 4) - bits0[i++] = 0; - bits = bits0; - } - } - mode = 2; - if (ndig <= 0) { - if (bufsize < (size_t)((int)(fpi.nbits * .301029995664) + 10)) { - Bfree(z); - return 0; - } - mode = 0; - } - fpi.emin = 1-1023-53+1; - fpi.emax = 2046-1023-106+1; - fpi.rounding = Rounding; - fpi.sudden_underflow = 0; - fpi.int_max = Int_max; - i = STRTOG_Normal; - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - b = g__fmt(buf, s, se, decpt, z->sign, bufsize); - Bfree(z); - return b; - } diff --git a/libraries/gdtoa/g_dfmt.c b/libraries/gdtoa/g_dfmt.c deleted file mode 100644 index d8e1438c4f..0000000000 --- a/libraries/gdtoa/g_dfmt.c +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - char* -#ifdef KR_headers -g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; size_t bufsize; -#else -g_dfmt(char *buf, double *d, int ndig, size_t bufsize) -#endif -{ - static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0, Int_max }; - char *b, *s, *se; - ULong bits[2], *L, sign; - int decpt, ex, i, mode; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - if (ndig < 0) - ndig = 0; - if (bufsize < (size_t)(ndig + 10)) - return 0; - - L = (ULong*)d; - sign = L[_0] & 0x80000000L; - if ((L[_0] & 0x7ff00000) == 0x7ff00000) { - /* Infinity or NaN */ - if (bufsize < 10) - return 0; - if (L[_0] & 0xfffff || L[_1]) { - return strcp(buf, "NaN"); - } - b = buf; - if (sign) - *b++ = '-'; - return strcp(b, "Infinity"); - } - if (L[_1] == 0 && (L[_0] ^ sign) == 0 /*d == 0.*/) { - b = buf; -#ifndef IGNORE_ZERO_SIGN - if (L[_0] & 0x80000000L) - *b++ = '-'; -#endif - *b++ = '0'; - *b = 0; - return b; - } - bits[0] = L[_1]; - bits[1] = L[_0] & 0xfffff; - if ( (ex = (L[_0] >> 20) & 0x7ff) !=0) - bits[1] |= 0x100000; - else - ex = 1; - ex -= 0x3ff + 52; - mode = 2; - if (ndig <= 0) - mode = 0; - i = STRTOG_Normal; - if (sign) - i = STRTOG_Normal | STRTOG_Neg; - s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign, bufsize); - } diff --git a/libraries/gdtoa/g_ffmt.c b/libraries/gdtoa/g_ffmt.c deleted file mode 100644 index 30b53ae7ec..0000000000 --- a/libraries/gdtoa/g_ffmt.c +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - char* -#ifdef KR_headers -g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; size_t bufsize; -#else -g_ffmt(char *buf, float *f, int ndig, size_t bufsize) -#endif -{ - static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, 0, 6 }; - char *b, *s, *se; - ULong bits[1], *L, sign; - int decpt, ex, i, mode; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - if (ndig < 0) - ndig = 0; - if (bufsize < (size_t)(ndig + 10)) - return 0; - - L = (ULong*)f; - sign = L[0] & 0x80000000L; - if ((L[0] & 0x7f800000) == 0x7f800000) { - /* Infinity or NaN */ - if (L[0] & 0x7fffff) { - return strcp(buf, "NaN"); - } - b = buf; - if (sign) - *b++ = '-'; - return strcp(b, "Infinity"); - } - if (*f == 0.) { - b = buf; -#ifndef IGNORE_ZERO_SIGN - if (L[0] & 0x80000000L) - *b++ = '-'; -#endif - *b++ = '0'; - *b = 0; - return b; - } - bits[0] = L[0] & 0x7fffff; - if ( (ex = (L[0] >> 23) & 0xff) !=0) - bits[0] |= 0x800000; - else - ex = 1; - ex -= 0x7f + 23; - mode = 2; - if (ndig <= 0) { - if (bufsize < 16) - return 0; - mode = 0; - } - i = STRTOG_Normal; - s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign, bufsize); - } diff --git a/libraries/gdtoa/g_xLfmt.c b/libraries/gdtoa/g_xLfmt.c deleted file mode 100644 index 5cda8d59e7..0000000000 --- a/libraries/gdtoa/g_xLfmt.c +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#endif -#ifdef IEEE_8087 -#define _0 2 -#define _1 1 -#define _2 0 -#endif - - char* -#ifdef KR_headers -g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; -#else -g_xLfmt(char *buf, void *V, int ndig, size_t bufsize) -#endif -{ - static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0, Int_max }; - char *b, *s, *se; - ULong bits[2], *L, sign; - int decpt, ex, i, mode; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - if (ndig < 0) - ndig = 0; - if (bufsize < (size_t)(ndig + 10)) - return 0; - - L = (ULong*)V; - sign = L[_0] & 0x80000000L; - bits[1] = L[_1]; - bits[0] = L[_2]; - if ( (ex = (L[_0] >> 16) & 0x7fff) !=0) { - if (ex == 0x7fff) { - /* Infinity or NaN */ - if (bits[0] | bits[1]) - b = strcp(buf, "NaN"); - else { - b = buf; - if (sign) - *b++ = '-'; - b = strcp(b, "Infinity"); - } - return b; - } - i = STRTOG_Normal; - } - else if (bits[0] | bits[1]) { - i = STRTOG_Denormal; - } - else { - b = buf; -#ifndef IGNORE_ZERO_SIGN - if (sign) - *b++ = '-'; -#endif - *b++ = '0'; - *b = 0; - return b; - } - ex -= 0x3fff + 63; - mode = 2; - if (ndig <= 0) { - if (bufsize < 32) - return 0; - mode = 0; - } - s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign, bufsize); - } diff --git a/libraries/gdtoa/g_xfmt.c b/libraries/gdtoa/g_xfmt.c deleted file mode 100644 index a0baa518ca..0000000000 --- a/libraries/gdtoa/g_xfmt.c +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#define _3 3 -#define _4 4 -#endif -#ifdef IEEE_8087 -#define _0 4 -#define _1 3 -#define _2 2 -#define _3 1 -#define _4 0 -#endif - - char* -#ifdef KR_headers -g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; -#else -g_xfmt(char *buf, void *V, int ndig, size_t bufsize) -#endif -{ - static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0, Int_max }; - char *b, *s, *se; - ULong bits[2], sign; - UShort *L; - int decpt, ex, i, mode; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - if (ndig < 0) - ndig = 0; - if (bufsize < (size_t)(ndig + 10)) - return 0; - - L = (UShort *)V; - sign = L[_0] & 0x8000; - bits[1] = (L[_1] << 16) | L[_2]; - bits[0] = (L[_3] << 16) | L[_4]; - if ( (ex = L[_0] & 0x7fff) !=0) { - if (ex == 0x7fff) { - /* Infinity or NaN */ - if (!bits[0] && bits[1]== 0x80000000) { - b = buf; - if (sign) - *b++ = '-'; - b = strcp(b, "Infinity"); - } - else - b = strcp(buf, "NaN"); - return b; - } - i = STRTOG_Normal; - } - else if (bits[0] | bits[1]) { - i = STRTOG_Denormal; - ex = 1; - } - else { - b = buf; -#ifndef IGNORE_ZERO_SIGN - if (sign) - *b++ = '-'; -#endif - *b++ = '0'; - *b = 0; - return b; - } - ex -= 0x3fff + 63; - mode = 2; - if (ndig <= 0) { - if (bufsize < 32) - return 0; - mode = 0; - } - s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign, bufsize); - } diff --git a/libraries/gdtoa/gdtoa.c b/libraries/gdtoa/gdtoa.c deleted file mode 100644 index a4759968a5..0000000000 --- a/libraries/gdtoa/gdtoa.c +++ /dev/null @@ -1,764 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 1999 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - static Bigint * -#ifdef KR_headers -bitstob(bits, nbits, bbits) ULong *bits; int nbits; int *bbits; -#else -bitstob(ULong *bits, int nbits, int *bbits) -#endif -{ - int i, k; - Bigint *b; - ULong *be, *x, *x0; - - i = ULbits; - k = 0; - while(i < nbits) { - i <<= 1; - k++; - } -#ifndef Pack_32 - if (!k) - k = 1; -#endif - b = Balloc(k); - be = bits + ((nbits - 1) >> kshift); - x = x0 = b->x; - do { - *x++ = *bits & ALL_ON; -#ifdef Pack_16 - *x++ = (*bits >> 16) & ALL_ON; -#endif - } while(++bits <= be); - i = x - x0; - while(!x0[--i]) - if (!i) { - b->wds = 0; - *bbits = 0; - goto ret; - } - b->wds = i + 1; - *bbits = i*ULbits + 32 - hi0bits(b->x[i]); - ret: - return b; - } - -/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - * - * Inspired by "How to Print Floating-Point Numbers Accurately" by - * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. - * - * Modifications: - * 1. Rather than iterating, we use a simple numeric overestimate - * to determine k = floor(log10(d)). We scale relevant - * quantities using O(log2(k)) rather than O(k) multiplications. - * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - * try to generate digits strictly left to right. Instead, we - * compute with fewer bits and propagate the carry if necessary - * when rounding the final digit up. This is often faster. - * 3. Under the assumption that input will be rounded nearest, - * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - * That is, we allow equality in stopping tests when the - * round-nearest rule will give the same floating-point value - * as would satisfaction of the stopping test with strict - * inequality. - * 4. We remove common factors of powers of 2 from relevant - * quantities. - * 5. When converting floating-point integers less than 1e16, - * we use floating-point arithmetic rather than resorting - * to multiple-precision integers. - * 6. When asked to produce fewer than 15 digits, we first try - * to get by with floating-point arithmetic; we resort to - * multiple-precision integer arithmetic only if we cannot - * guarantee that the floating-point calculation has given - * the correctly rounded result. For k requested digits and - * "uniformly" distributed input, the probability is - * something like 10^(k-15) that we must resort to the Long - * calculation. - */ - - char * -gdtoa -#ifdef KR_headers - (fpi, be, bits, kindp, mode, ndigits, decpt, rve) - FPI *fpi; int be; ULong *bits; - int *kindp, mode, ndigits, *decpt; char **rve; -#else - (FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve) -#endif -{ - /* Arguments ndigits and decpt are similar to the second and third - arguments of ecvt and fcvt; trailing zeros are suppressed from - the returned string. If not null, *rve is set to point - to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to 9999. - be = exponent: value = (integer represented by bits) * (2 to the power of be). - - mode: - 0 ==> shortest string that yields d when read in - and rounded to nearest. - 1 ==> like 0, but with Steele & White stopping rule; - e.g. with IEEE P754 arithmetic , mode 0 gives - 1e23 whereas mode 1 gives 9.999999999999999e22. - 2 ==> max(1,ndigits) significant digits. This gives a - return value similar to that of ecvt, except - that trailing zeros are suppressed. - 3 ==> through ndigits past the decimal point. This - gives a return value similar to that from fcvt, - except that trailing zeros are suppressed, and - ndigits can be negative. - 4-9 should give the same return values as 2-3, i.e., - 4 <= mode <= 9 ==> same return as mode - 2 + (mode & 1). These modes are mainly for - debugging; often they run slower but sometimes - faster than modes 2-3. - 4,5,8,9 ==> left-to-right digit generation. - 6-9 ==> don't try fast floating-point estimate - (if applicable). - - Values of mode other than 0-9 are treated as mode 0. - - Sufficient space is allocated to the return value - to hold the suppressed trailing zeros. - */ - - int bbits, b2, b5, be0, dig, i, ieps, ilim, ilim0, ilim1, inex; - int j, j1, k, k0, k_check, kind, leftright, m2, m5, nbits; - int rdir, s2, s5, spec_case, try_quick; - Long L; - Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S; - double d2, ds; - char *s, *s0; - U d, eps; - -#ifndef MULTIPLE_THREADS - if (dtoa_result) { - freedtoa(dtoa_result); - dtoa_result = 0; - } -#endif - inex = 0; - kind = *kindp &= ~STRTOG_Inexact; - switch(kind & STRTOG_Retmask) { - case STRTOG_Zero: - goto ret_zero; - case STRTOG_Normal: - case STRTOG_Denormal: - break; - case STRTOG_Infinite: - *decpt = -32768; - return nrv_alloc("Infinity", rve, 8); - case STRTOG_NaN: - *decpt = -32768; - return nrv_alloc("NaN", rve, 3); - default: - return 0; - } - b = bitstob(bits, nbits = fpi->nbits, &bbits); - be0 = be; - if ( (i = trailz(b)) !=0) { - rshift(b, i); - be += i; - bbits -= i; - } - if (!b->wds) { - Bfree(b); - ret_zero: - *decpt = 1; - return nrv_alloc("0", rve, 1); - } - - dval(&d) = b2d(b, &i); - i = be + bbits - 1; - word0(&d) &= Frac_mask1; - word0(&d) |= Exp_11; -#ifdef IBM - if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0) - dval(&d) /= 1 << j; -#endif - - /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 - * log10(x) = log(x) / log(10) - * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2) - * - * This suggests computing an approximation k to log10(&d) by - * - * k = (i - Bias)*0.301029995663981 - * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - * - * We want k to be too large rather than too small. - * The error in the first-order Taylor series approximation - * is in our favor, so we just round up the constant enough - * to compensate for any error in the multiplication of - * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - * adding 1e-13 to the constant term more than suffices. - * Hence we adjust the constant term to 0.1760912590558. - * (We could get a more accurate k by invoking log10, - * but this is probably not worthwhile.) - */ -#ifdef IBM - i <<= 2; - i += j; -#endif - ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; - - /* correct assumption about exponent range */ - if ((j = i) < 0) - j = -j; - if ((j -= 1077) > 0) - ds += j * 7e-17; - - k = (int)ds; - if (ds < 0. && ds != k) - k--; /* want k = floor(ds) */ - k_check = 1; -#ifdef IBM - j = be + bbits - 1; - if ( (j1 = j & 3) !=0) - dval(&d) *= 1 << j1; - word0(&d) += j << Exp_shift - 2 & Exp_mask; -#else - word0(&d) += (be + bbits - 1) << Exp_shift; -#endif - if (k >= 0 && k <= Ten_pmax) { - if (dval(&d) < tens[k]) - k--; - k_check = 0; - } - j = bbits - i - 1; - if (j >= 0) { - b2 = 0; - s2 = j; - } - else { - b2 = -j; - s2 = 0; - } - if (k >= 0) { - b5 = 0; - s5 = k; - s2 += k; - } - else { - b2 -= k; - b5 = -k; - s5 = 0; - } - if (mode < 0 || mode > 9) - mode = 0; - try_quick = 1; - if (mode > 5) { - mode -= 4; - try_quick = 0; - } - else if (i >= -4 - Emin || i < Emin) - try_quick = 0; - leftright = 1; - ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ - /* silence erroneous "gcc -Wall" warning. */ - switch(mode) { - case 0: - case 1: - i = (int)(nbits * .30103) + 3; - ndigits = 0; - break; - case 2: - leftright = 0; - /* no break */ - case 4: - if (ndigits <= 0) - ndigits = 1; - ilim = ilim1 = i = ndigits; - break; - case 3: - leftright = 0; - /* no break */ - case 5: - i = ndigits + k + 1; - ilim = i; - ilim1 = i - 1; - if (i <= 0) - i = 1; - } - s = s0 = rv_alloc(i); - - if ( (rdir = fpi->rounding - 1) !=0) { - if (rdir < 0) - rdir = 2; - if (kind & STRTOG_Neg) - rdir = 3 - rdir; - } - - /* Now rdir = 0 ==> round near, 1 ==> round up, 2 ==> round down. */ - - if (ilim >= 0 && ilim <= Quick_max && try_quick && !rdir -#ifndef IMPRECISE_INEXACT - && k == 0 -#endif - ) { - - /* Try to get by with floating-point arithmetic. */ - - i = 0; - d2 = dval(&d); -#ifdef IBM - if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0) - dval(&d) /= 1 << j; -#endif - k0 = k; - ilim0 = ilim; - ieps = 2; /* conservative */ - if (k > 0) { - ds = tens[k&0xf]; - j = k >> 4; - if (j & Bletch) { - /* prevent overflows */ - j &= Bletch - 1; - dval(&d) /= bigtens[n_bigtens-1]; - ieps++; - } - for(; j; j >>= 1, i++) - if (j & 1) { - ieps++; - ds *= bigtens[i]; - } - } - else { - ds = 1.; - if ( (j1 = -k) !=0) { - dval(&d) *= tens[j1 & 0xf]; - for(j = j1 >> 4; j; j >>= 1, i++) - if (j & 1) { - ieps++; - dval(&d) *= bigtens[i]; - } - } - } - if (k_check && dval(&d) < 1. && ilim > 0) { - if (ilim1 <= 0) - goto fast_failed; - ilim = ilim1; - k--; - dval(&d) *= 10.; - ieps++; - } - dval(&eps) = ieps*dval(&d) + 7.; - word0(&eps) -= (P-1)*Exp_msk1; - if (ilim == 0) { - S = mhi = 0; - dval(&d) -= 5.; - if (dval(&d) > dval(&eps)) - goto one_digit; - if (dval(&d) < -dval(&eps)) - goto no_digits; - goto fast_failed; - } -#ifndef No_leftright - if (leftright) { - /* Use Steele & White method of only - * generating digits needed. - */ - dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps); - for(i = 0;;) { - L = (Long)(dval(&d)/ds); - dval(&d) -= L*ds; - *s++ = '0' + (int)L; - if (dval(&d) < dval(&eps)) { - if (dval(&d)) - inex = STRTOG_Inexlo; - goto ret1; - } - if (ds - dval(&d) < dval(&eps)) - goto bump_up; - if (++i >= ilim) - break; - dval(&eps) *= 10.; - dval(&d) *= 10.; - } - } - else { -#endif - /* Generate ilim digits, then fix them up. */ - dval(&eps) *= tens[ilim-1]; - for(i = 1;; i++, dval(&d) *= 10.) { - if ( (L = (Long)(dval(&d)/ds)) !=0) - dval(&d) -= L*ds; - *s++ = '0' + (int)L; - if (i == ilim) { - ds *= 0.5; - if (dval(&d) > ds + dval(&eps)) - goto bump_up; - else if (dval(&d) < ds - dval(&eps)) { - if (dval(&d)) - inex = STRTOG_Inexlo; - goto clear_trailing0; - } - break; - } - } -#ifndef No_leftright - } -#endif - fast_failed: - s = s0; - dval(&d) = d2; - k = k0; - ilim = ilim0; - } - - /* Do we have a "small" integer? */ - - if (be >= 0 && k <= fpi->int_max) { - /* Yes. */ - ds = tens[k]; - if (ndigits < 0 && ilim <= 0) { - S = mhi = 0; - if (ilim < 0 || dval(&d) <= 5*ds) - goto no_digits; - goto one_digit; - } - for(i = 1;; i++, dval(&d) *= 10.) { - L = (Long)(dval(&d) / ds); - dval(&d) -= L*ds; -#ifdef Check_FLT_ROUNDS - /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(&d) < 0) { - L--; - dval(&d) += ds; - } -#endif - *s++ = '0' + (int)L; - if (dval(&d) == 0.) - break; - if (i == ilim) { - if (rdir) { - if (rdir == 1) - goto bump_up; - inex = STRTOG_Inexlo; - goto ret1; - } - dval(&d) += dval(&d); -#ifdef ROUND_BIASED - if (dval(&d) >= ds) -#else - if (dval(&d) > ds || (dval(&d) == ds && L & 1)) -#endif - { - bump_up: - inex = STRTOG_Inexhi; - while(*--s == '9') - if (s == s0) { - k++; - *s = '0'; - break; - } - ++*s++; - } - else { - inex = STRTOG_Inexlo; - clear_trailing0: - while(*--s == '0'){} - ++s; - } - break; - } - } - goto ret1; - } - - m2 = b2; - m5 = b5; - mhi = mlo = 0; - if (leftright) { - i = nbits - bbits; - if (be - i++ < fpi->emin && mode != 3 && mode != 5) { - /* denormal */ - i = be - fpi->emin + 1; - if (mode >= 2 && ilim > 0 && ilim < i) - goto small_ilim; - } - else if (mode >= 2) { - small_ilim: - j = ilim - 1; - if (m5 >= j) - m5 -= j; - else { - s5 += j -= m5; - b5 += j; - m5 = 0; - } - if ((i = ilim) < 0) { - m2 -= i; - i = 0; - } - } - b2 += i; - s2 += i; - mhi = i2b(1); - } - if (m2 > 0 && s2 > 0) { - i = m2 < s2 ? m2 : s2; - b2 -= i; - m2 -= i; - s2 -= i; - } - if (b5 > 0) { - if (leftright) { - if (m5 > 0) { - mhi = pow5mult(mhi, m5); - b1 = mult(mhi, b); - Bfree(b); - b = b1; - } - if ( (j = b5 - m5) !=0) - b = pow5mult(b, j); - } - else - b = pow5mult(b, b5); - } - S = i2b(1); - if (s5 > 0) - S = pow5mult(S, s5); - - /* Check for special case that d is a normalized power of 2. */ - - spec_case = 0; - if (mode < 2) { - if (bbits == 1 && be0 > fpi->emin + 1) { - /* The special case */ - b2++; - s2++; - spec_case = 1; - } - } - - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - * - * Perhaps we should just compute leading 28 bits of S once - * and for all and pass them and a shift to quorem, so it - * can do shifts and ors to compute the numerator for q. - */ - i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask; - m2 += i; - if ((b2 += i) > 0) - b = lshift(b, b2); - if ((s2 += i) > 0) - S = lshift(S, s2); - if (k_check) { - if (cmp(b,S) < 0) { - k--; - b = multadd(b, 10, 0); /* we botched the k estimate */ - if (leftright) - mhi = multadd(mhi, 10, 0); - ilim = ilim1; - } - } - if (ilim <= 0 && mode > 2) { - if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { - /* no digits, fcvt style */ - no_digits: - k = -1 - ndigits; - inex = STRTOG_Inexlo; - goto ret; - } - one_digit: - inex = STRTOG_Inexhi; - *s++ = '1'; - k++; - goto ret; - } - if (leftright) { - if (m2 > 0) - mhi = lshift(mhi, m2); - - /* Compute mlo -- check for special case - * that d is a normalized power of 2. - */ - - mlo = mhi; - if (spec_case) { - mhi = Balloc(mhi->k); - Bcopy(mhi, mlo); - mhi = lshift(mhi, 1); - } - - for(i = 1;;i++) { - dig = quorem(b,S) + '0'; - /* Do we yet have the shortest decimal string - * that will round to d? - */ - j = cmp(b, mlo); - delta = diff(S, mhi); - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); -#ifndef ROUND_BIASED - if (j1 == 0 && !mode && !(bits[0] & 1) && !rdir) { - if (dig == '9') - goto round_9_up; - if (j <= 0) { - if (b->wds > 1 || b->x[0]) - inex = STRTOG_Inexlo; - } - else { - dig++; - inex = STRTOG_Inexhi; - } - *s++ = dig; - goto ret; - } -#endif - if (j < 0 || (j == 0 && !mode -#ifndef ROUND_BIASED - && !(bits[0] & 1) -#endif - )) { - if (rdir && (b->wds > 1 || b->x[0])) { - if (rdir == 2) { - inex = STRTOG_Inexlo; - goto accept; - } - while (cmp(S,mhi) > 0) { - *s++ = dig; - mhi1 = multadd(mhi, 10, 0); - if (mlo == mhi) - mlo = mhi1; - mhi = mhi1; - b = multadd(b, 10, 0); - dig = quorem(b,S) + '0'; - } - if (dig++ == '9') - goto round_9_up; - inex = STRTOG_Inexhi; - goto accept; - } - if (j1 > 0) { - b = lshift(b, 1); - j1 = cmp(b, S); -#ifdef ROUND_BIASED - if (j1 >= 0 /*)*/ -#else - if ((j1 > 0 || (j1 == 0 && dig & 1)) -#endif - && dig++ == '9') - goto round_9_up; - inex = STRTOG_Inexhi; - } - if (b->wds > 1 || b->x[0]) - inex = STRTOG_Inexlo; - accept: - *s++ = dig; - goto ret; - } - if (j1 > 0 && rdir != 2) { - if (dig == '9') { /* possible if i == 1 */ - round_9_up: - *s++ = '9'; - inex = STRTOG_Inexhi; - goto roundoff; - } - inex = STRTOG_Inexhi; - *s++ = dig + 1; - goto ret; - } - *s++ = dig; - if (i == ilim) - break; - b = multadd(b, 10, 0); - if (mlo == mhi) - mlo = mhi = multadd(mhi, 10, 0); - else { - mlo = multadd(mlo, 10, 0); - mhi = multadd(mhi, 10, 0); - } - } - } - else - for(i = 1;; i++) { - *s++ = dig = quorem(b,S) + '0'; - if (i >= ilim) - break; - b = multadd(b, 10, 0); - } - - /* Round off last digit */ - - if (rdir) { - if (rdir == 2 || (b->wds <= 1 && !b->x[0])) - goto chopzeros; - goto roundoff; - } - b = lshift(b, 1); - j = cmp(b, S); -#ifdef ROUND_BIASED - if (j >= 0) -#else - if (j > 0 || (j == 0 && dig & 1)) -#endif - { - roundoff: - inex = STRTOG_Inexhi; - while(*--s == '9') - if (s == s0) { - k++; - *s++ = '1'; - goto ret; - } - ++*s++; - } - else { - chopzeros: - if (b->wds > 1 || b->x[0]) - inex = STRTOG_Inexlo; - while(*--s == '0'){} - ++s; - } - ret: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } - ret1: - Bfree(b); - *s = 0; - *decpt = k + 1; - if (rve) - *rve = s; - *kindp |= inex; - return s0; - } diff --git a/libraries/gdtoa/gdtoa.h b/libraries/gdtoa/gdtoa.h deleted file mode 100644 index 516e6a68c5..0000000000 --- a/libraries/gdtoa/gdtoa.h +++ /dev/null @@ -1,189 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#ifndef GDTOA_H_INCLUDED -#define GDTOA_H_INCLUDED - -#if defined(_MSC_VER) -/* [RH] Generating arith.h strikes me as too cumbersome under Visual - * Studio, so here's the equivalent, given the limited number of - * architectures that MSC can target. (Itanium? Who cares about that?) - */ -#define IEEE_8087 -#define Arith_Kind_ASL 1 -#define Double_Align -#ifdef _M_X64 -#define X64_bit_pointers -#endif -#elif defined(__APPLE__) -/* [BL] While generating the files may be easy, on OS X we have cross - * compiling to deal with, which means we can't run the generation - * program on the target. - */ -#if defined(__x86_64__) || defined(__arm64__) -#define IEEE_8087 -#define Arith_Kind_ASL 1 -#define Long int -#define Intcast (int)(long) -#define Double_Align -#define X64_bit_pointers -#else -#error Unsupported architecture -#endif -#else -#include "arith.h" -#endif -#include /* for size_t */ - -#ifndef Long -#define Long int -#endif -#ifndef ULong -typedef unsigned Long ULong; -#endif -#ifndef UShort -typedef unsigned short UShort; -#endif - -#ifndef ANSI -#ifdef KR_headers -#define ANSI(x) () -#define Void /*nothing*/ -#else -#define ANSI(x) x -#define Void void -#endif -#endif /* ANSI */ - -#ifndef CONST -#ifdef KR_headers -#define CONST /* blank */ -#else -#define CONST const -#endif -#endif /* CONST */ - - enum { /* return values from strtodg */ - STRTOG_Zero = 0, - STRTOG_Normal = 1, - STRTOG_Denormal = 2, - STRTOG_Infinite = 3, - STRTOG_NaN = 4, - STRTOG_NaNbits = 5, - STRTOG_NoNumber = 6, - STRTOG_Retmask = 7, - - /* The following may be or-ed into one of the above values. */ - - STRTOG_Neg = 0x08, /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */ - STRTOG_Inexlo = 0x10, /* returned result rounded toward zero */ - STRTOG_Inexhi = 0x20, /* returned result rounded away from zero */ - STRTOG_Inexact = 0x30, - STRTOG_Underflow= 0x40, - STRTOG_Overflow = 0x80 - }; - - typedef struct -FPI { - int nbits; - int emin; - int emax; - int rounding; - int sudden_underflow; - int int_max; - } FPI; - -enum { /* FPI.rounding values: same as FLT_ROUNDS */ - FPI_Round_zero = 0, - FPI_Round_near = 1, - FPI_Round_up = 2, - FPI_Round_down = 3 - }; - -#ifdef __cplusplus -extern "C" { -#endif - -extern char* dtoa ANSI((double d, int mode, int ndigits, int *decpt, - int *sign, char **rve)); -extern char* gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp, - int mode, int ndigits, int *decpt, char **rve)); -extern void freedtoa ANSI((char*)); -//extern float strtof ANSI((CONST char *, char **)); -//extern double strtod ANSI((CONST char *, char **)); -extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); - -extern char* g_ddfmt ANSI((char*, double*, int, size_t)); -extern char* g_ddfmt_p ANSI((char*, double*, int, size_t, int)); -extern char* g_dfmt ANSI((char*, double*, int, size_t)); -extern char* g_dfmt_p ANSI((char*, double*, int, size_t, int)); -extern char* g_ffmt ANSI((char*, float*, int, size_t)); -extern char* g_ffmt_p ANSI((char*, float*, int, size_t, int)); -extern char* g_Qfmt ANSI((char*, void*, int, size_t)); -extern char* g_Qfmt_p ANSI((char*, void*, int, size_t, int)); -extern char* g_xfmt ANSI((char*, void*, int, size_t)); -extern char* g_xfmt_p ANSI((char*, void*, int, size_t, int)); -extern char* g_xLfmt ANSI((char*, void*, int, size_t)); -extern char* g_xLfmt_p ANSI((char*, void*, int, size_t, int)); - -extern int strtoId ANSI((CONST char*, char**, double*, double*)); -extern int strtoIdd ANSI((CONST char*, char**, double*, double*)); -extern int strtoIf ANSI((CONST char*, char**, float*, float*)); -extern int strtoIQ ANSI((CONST char*, char**, void*, void*)); -extern int strtoIx ANSI((CONST char*, char**, void*, void*)); -extern int strtoIxL ANSI((CONST char*, char**, void*, void*)); -extern int strtord ANSI((CONST char*, char**, int, double*)); -extern int strtordd ANSI((CONST char*, char**, int, double*)); -extern int strtorf ANSI((CONST char*, char**, int, float*)); -extern int strtorQ ANSI((CONST char*, char**, int, void*)); -extern int strtorx ANSI((CONST char*, char**, int, void*)); -extern int strtorxL ANSI((CONST char*, char**, int, void*)); -#if 1 -extern int strtodI ANSI((CONST char*, char**, double*)); -extern int strtopd ANSI((CONST char*, char**, double*)); -extern int strtopdd ANSI((CONST char*, char**, double*)); -extern int strtopf ANSI((CONST char*, char**, float*)); -extern int strtopQ ANSI((CONST char*, char**, void*)); -extern int strtopx ANSI((CONST char*, char**, void*)); -extern int strtopxL ANSI((CONST char*, char**, void*)); -#else -#define strtopd(s,se,x) strtord(s,se,1,x) -#define strtopdd(s,se,x) strtordd(s,se,1,x) -#define strtopf(s,se,x) strtorf(s,se,1,x) -#define strtopQ(s,se,x) strtorQ(s,se,1,x) -#define strtopx(s,se,x) strtorx(s,se,1,x) -#define strtopxL(s,se,x) strtorxL(s,se,1,x) -#endif - -#ifdef __cplusplus -} -#endif -#endif /* GDTOA_H_INCLUDED */ diff --git a/libraries/gdtoa/gdtoa_fltrnds.h b/libraries/gdtoa/gdtoa_fltrnds.h deleted file mode 100644 index 33e5f9e534..0000000000 --- a/libraries/gdtoa/gdtoa_fltrnds.h +++ /dev/null @@ -1,18 +0,0 @@ - FPI *fpi, fpi1; - int Rounding; -#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ - Rounding = Flt_Rounds; -#else /*}{*/ - Rounding = 1; - switch(fegetround()) { - case FE_TOWARDZERO: Rounding = 0; break; - case FE_UPWARD: Rounding = 2; break; - case FE_DOWNWARD: Rounding = 3; - } -#endif /*}}*/ - fpi = &fpi0; - if (Rounding != 1) { - fpi1 = fpi0; - fpi = &fpi1; - fpi1.rounding = Rounding; - } diff --git a/libraries/gdtoa/gdtoaimp.h b/libraries/gdtoa/gdtoaimp.h deleted file mode 100644 index ae7eeb5728..0000000000 --- a/libraries/gdtoa/gdtoaimp.h +++ /dev/null @@ -1,674 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998-2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* This is a variation on dtoa.c that converts arbitary binary - floating-point formats to and from decimal notation. It uses - double-precision arithmetic internally, so there are still - various #ifdefs that adapt the calculations to the native - double-precision arithmetic (any of IEEE, VAX D_floating, - or IBM mainframe arithmetic). - - Please send bug reports to David M. Gay (dmg at acm dot org, - with " at " changed at "@" and " dot " changed to "."). - */ - -/* On a machine with IEEE extended-precision registers, it is - * necessary to specify double-precision (53-bit) rounding precision - * before invoking strtod or dtoa. If the machine uses (the equivalent - * of) Intel 80x87 arithmetic, the call - * _control87(PC_53, MCW_PC); - * does this with many compilers. Whether this or another call is - * appropriate depends on the compiler; for this to work, it may be - * necessary to #include "float.h" or another system-dependent header - * file. - */ - -/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. - * - * This strtod returns a nearest machine number to the input decimal - * string (or sets errno to ERANGE). With IEEE arithmetic, ties are - * broken by the IEEE round-even rule. Otherwise ties are broken by - * biased rounding (add half and chop). - * - * Inspired loosely by William D. Clinger's paper "How to Read Floating - * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 112-126]. - * - * Modifications: - * - * 1. We only require IEEE, IBM, or VAX double-precision - * arithmetic (not IEEE double-extended). - * 2. We get by with floating-point arithmetic in a case that - * Clinger missed -- when we're computing d * 10^n - * for a small integer d and the integer n is not too - * much larger than 22 (the maximum integer k for which - * we can represent 10^k exactly), we may be able to - * compute (d*10^k) * 10^(e-k) with just one roundoff. - * 3. Rather than a bit-at-a-time adjustment of the binary - * result in the hard case, we use floating-point - * arithmetic to determine the adjustment to within - * one bit; only in really hard cases do we need to - * compute a second residual. - * 4. Because of 3., we don't need a large table of powers of 10 - * for ten-to-e (just some small tables, e.g. of 10^k - * for 0 <= k <= 22). - */ - -/* - * #define IEEE_8087 for IEEE-arithmetic machines where the least - * significant byte has the lowest address. - * #define IEEE_MC68k for IEEE-arithmetic machines where the most - * significant byte has the lowest address. - * #define Long int on machines with 32-bit ints and 64-bit longs. - * #define Sudden_Underflow for IEEE-format machines without gradual - * underflow (i.e., that flush to zero on underflow). - * #define IBM for IBM mainframe-style floating-point arithmetic. - * #define VAX for VAX-style floating-point arithmetic (D_floating). - * #define No_leftright to omit left-right logic in fast floating-point - * computation of dtoa and gdtoa. This will cause modes 4 and 5 to be - * treated the same as modes 2 and 3 for some inputs. - * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. - * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines - * that use extended-precision instructions to compute rounded - * products and quotients) with IBM. - * #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic - * that rounds toward +Infinity. - * #define ROUND_BIASED_without_Round_Up for IEEE-format with biased - * rounding when the underlying floating-point arithmetic uses - * unbiased rounding. This prevent using ordinary floating-point - * arithmetic when the result could be computed with one rounding error. - * #define Inaccurate_Divide for IEEE-format with correctly rounded - * products but inaccurate quotients, e.g., for Intel i860. - * #define NO_LONG_LONG on machines that do not have a "long long" - * integer type (of >= 64 bits). On such machines, you can - * #define Just_16 to store 16 bits per 32-bit Long when doing - * high-precision integer arithmetic. Whether this speeds things - * up or slows things down depends on the machine and the number - * being converted. If long long is available and the name is - * something other than "long long", #define Llong to be the name, - * and if "unsigned Llong" does not work as an unsigned version of - * Llong, #define #ULLong to be the corresponding unsigned type. - * #define KR_headers for old-style C function headers. - * #define Bad_float_h if your system lacks a float.h or if it does not - * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, - * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. - * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) - * if memory is available and otherwise does something you deem - * appropriate. If MALLOC is undefined, malloc will be invoked - * directly -- and assumed always to succeed. Similarly, if you - * want something other than the system's free() to be called to - * recycle memory acquired from MALLOC, #define FREE to be the - * name of the alternate routine. (FREE or free is only called in - * pathological cases, e.g., in a gdtoa call after a gdtoa return in - * mode 3 with thousands of digits requested.) - * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making - * memory allocations from a private pool of memory when possible. - * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, - * unless #defined to be a different length. This default length - * suffices to get rid of MALLOC calls except for unusual cases, - * such as decimal-to-binary conversion of a very long string of - * digits. When converting IEEE double precision values, the - * longest string gdtoa can return is about 751 bytes long. For - * conversions by strtod of strings of 800 digits and all gdtoa - * conversions of IEEE doubles in single-threaded executions with - * 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with - * 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate. - * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK - * #defined automatically on IEEE systems. On such systems, - * when INFNAN_CHECK is #defined, strtod checks - * for Infinity and NaN (case insensitively). - * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, - * strtodg also accepts (case insensitively) strings of the form - * NaN(x), where x is a string of hexadecimal digits (optionally - * preceded by 0x or 0X) and spaces; if there is only one string - * of hexadecimal digits, it is taken for the fraction bits of the - * resulting NaN; if there are two or more strings of hexadecimal - * digits, each string is assigned to the next available sequence - * of 32-bit words of fractions bits (starting with the most - * significant), right-aligned in each sequence. - * Unless GDTOA_NON_PEDANTIC_NANCHECK is #defined, input "NaN(...)" - * is consumed even when ... has the wrong form (in which case the - * "(...)" is consumed but ignored). - * #define MULTIPLE_THREADS if the system offers preemptively scheduled - * multiple threads. In this case, you must provide (or suitably - * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed - * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed - * in pow5mult, ensures lazy evaluation of only one copy of high - * powers of 5; omitting this lock would introduce a small - * probability of wasting memory, but would otherwise be harmless.) - * You must also invoke freedtoa(s) to free the value s returned by - * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. - * #define IMPRECISE_INEXACT if you do not care about the setting of - * the STRTOG_Inexact bits in the special case of doing IEEE double - * precision conversions (which could also be done by the strtod in - * dtoa.c). - * #define NO_HEX_FP to disable recognition of C9x's hexadecimal - * floating-point constants. - * #define -DNO_ERRNO to suppress setting errno (in strtod.c and - * strtodg.c). - * #define NO_STRING_H to use private versions of memcpy. - * On some K&R systems, it may also be necessary to - * #define DECLARE_SIZE_T in this case. - * #define USE_LOCALE to use the current locale's decimal_point value. - */ - -#ifndef GDTOAIMP_H_INCLUDED -#define GDTOAIMP_H_INCLUDED -#include "gdtoa.h" - -#if defined(_MSC_VER) -/* [RH] Generating gd_qnan.h strikes me as too cumbersome under Visual - * Studio, so here's the equivalent, given the limited number of - * architectures that MSC can target. (Itanium? Who cares about that?) - */ -#define f_QNAN 0xffc00000 -#define d_QNAN0 0x0 -#define d_QNAN1 0xfff80000 -#define ld_QNAN0 0x0 -#define ld_QNAN1 0xfff80000 -#define ld_QNAN2 0x0 -#define ld_QNAN3 0x0 -#define ldus_QNAN0 0x0 -#define ldus_QNAN1 0x0 -#define ldus_QNAN2 0x0 -#define ldus_QNAN3 0xfff8 -#define ldus_QNAN4 0x0 -/* [RH] Interestingly, MinGW produces something different because - * it turns out that it has a true long double type. I thought that - * all ia32 compilers had phased out extended precision. - */ -#elif defined(__APPLE__) -#if defined(__x86_64__) || defined(__arm64__) -#define f_QNAN 0xffc00000 -#define d_QNAN0 0x0 -#define d_QNAN1 0xfff80000 -#define ld_QNAN0 0x0 -#define ld_QNAN1 0xc0000000 -#define ld_QNAN2 0xffff -#define ld_QNAN3 0x0 -#define ldus_QNAN0 0x0 -#define ldus_QNAN1 0x0 -#define ldus_QNAN2 0x0 -#define ldus_QNAN3 0xc000 -#define ldus_QNAN4 0xffff -#else -#error Unsupported architecture -#endif -#else -#include "gd_qnan.h" -#endif - -#ifdef Honor_FLT_ROUNDS -#include -#endif - -#ifdef DEBUG -#include "stdio.h" -#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} -#endif - -#include "stdlib.h" -#include "string.h" - -#ifdef KR_headers -#define Char char -#else -#define Char void -#endif - -#ifdef MALLOC -extern Char *MALLOC ANSI((size_t)); -#else -#define MALLOC malloc -#endif - -#undef IEEE_Arith -#undef Avoid_Underflow -#ifdef IEEE_MC68k -#define IEEE_Arith -#endif -#ifdef IEEE_8087 -#define IEEE_Arith -#endif - -#include "errno.h" -#ifdef Bad_float_h - -#ifdef IEEE_Arith -#define DBL_DIG 15 -#define DBL_MAX_10_EXP 308 -#define DBL_MAX_EXP 1024 -#define FLT_RADIX 2 -#define DBL_MAX 1.7976931348623157e+308 -#endif - -#ifdef IBM -#define DBL_DIG 16 -#define DBL_MAX_10_EXP 75 -#define DBL_MAX_EXP 63 -#define FLT_RADIX 16 -#define DBL_MAX 7.2370055773322621e+75 -#endif - -#ifdef VAX -#define DBL_DIG 16 -#define DBL_MAX_10_EXP 38 -#define DBL_MAX_EXP 127 -#define FLT_RADIX 2 -#define DBL_MAX 1.7014118346046923e+38 -#define n_bigtens 2 -#endif - -#ifndef LONG_MAX -#define LONG_MAX 2147483647 -#endif - -#else /* ifndef Bad_float_h */ -#include "float.h" -#endif /* Bad_float_h */ - -#ifdef IEEE_Arith -#define Scale_Bit 0x10 -#define n_bigtens 5 -#endif - -#ifdef IBM -#define n_bigtens 3 -#endif - -#ifdef VAX -#define n_bigtens 2 -#endif - -#ifndef __MATH_H__ -#include "math.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 -Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. -#endif - -typedef union { double d; ULong L[2]; } U; - -#ifdef IEEE_8087 -#define word0(x) (x)->L[1] -#define word1(x) (x)->L[0] -#else -#define word0(x) (x)->L[0] -#define word1(x) (x)->L[1] -#endif -#define dval(x) (x)->d - -/* The following definition of Storeinc is appropriate for MIPS processors. - * An alternative that might be better on some machines is - * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) - */ -#if defined(IEEE_8087) + defined(VAX) -#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ -((unsigned short *)a)[0] = (unsigned short)c, a++) -#else -#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ -((unsigned short *)a)[1] = (unsigned short)c, a++) -#endif - -/* #define P DBL_MANT_DIG */ -/* Ten_pmax = floor(P*log(2)/log(5)) */ -/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ -/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ -/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ - -#ifdef IEEE_Arith -#define Exp_shift 20 -#define Exp_shift1 20 -#define Exp_msk1 0x100000 -#define Exp_msk11 0x100000 -#define Exp_mask 0x7ff00000 -#define P 53 -#define Bias 1023 -#define Emin (-1022) -#define Exp_1 0x3ff00000 -#define Exp_11 0x3ff00000 -#define Ebits 11 -#define Frac_mask 0xfffff -#define Frac_mask1 0xfffff -#define Ten_pmax 22 -#define Bletch 0x10 -#define Bndry_mask 0xfffff -#define Bndry_mask1 0xfffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 1 -#define Tiny0 0 -#define Tiny1 1 -#define Quick_max 14 -#define Int_max 14 - -#ifndef Flt_Rounds -#ifdef FLT_ROUNDS -#define Flt_Rounds FLT_ROUNDS -#else -#define Flt_Rounds 1 -#endif -#endif /*Flt_Rounds*/ - -#else /* ifndef IEEE_Arith */ -#undef Sudden_Underflow -#define Sudden_Underflow -#ifdef IBM -#undef Flt_Rounds -#define Flt_Rounds 0 -#define Exp_shift 24 -#define Exp_shift1 24 -#define Exp_msk1 0x1000000 -#define Exp_msk11 0x1000000 -#define Exp_mask 0x7f000000 -#define P 14 -#define Bias 65 -#define Exp_1 0x41000000 -#define Exp_11 0x41000000 -#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ -#define Frac_mask 0xffffff -#define Frac_mask1 0xffffff -#define Bletch 4 -#define Ten_pmax 22 -#define Bndry_mask 0xefffff -#define Bndry_mask1 0xffffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 4 -#define Tiny0 0x100000 -#define Tiny1 0 -#define Quick_max 14 -#define Int_max 15 -#else /* VAX */ -#undef Flt_Rounds -#define Flt_Rounds 1 -#define Exp_shift 23 -#define Exp_shift1 7 -#define Exp_msk1 0x80 -#define Exp_msk11 0x800000 -#define Exp_mask 0x7f80 -#define P 56 -#define Bias 129 -#define Exp_1 0x40800000 -#define Exp_11 0x4080 -#define Ebits 8 -#define Frac_mask 0x7fffff -#define Frac_mask1 0xffff007f -#define Ten_pmax 24 -#define Bletch 2 -#define Bndry_mask 0xffff007f -#define Bndry_mask1 0xffff007f -#define LSB 0x10000 -#define Sign_bit 0x8000 -#define Log2P 1 -#define Tiny0 0x80 -#define Tiny1 0 -#define Quick_max 15 -#define Int_max 15 -#endif /* IBM, VAX */ -#endif /* IEEE_Arith */ - -#ifndef IEEE_Arith -#define ROUND_BIASED -#else -#ifdef ROUND_BIASED_without_Round_Up -#undef ROUND_BIASED -#define ROUND_BIASED -#endif -#endif - -#ifdef RND_PRODQUOT -#define rounded_product(a,b) a = rnd_prod(a, b) -#define rounded_quotient(a,b) a = rnd_quot(a, b) -#ifdef KR_headers -extern double rnd_prod(), rnd_quot(); -#else -extern double rnd_prod(double, double), rnd_quot(double, double); -#endif -#else -#define rounded_product(a,b) a *= b -#define rounded_quotient(a,b) a /= b -#endif - -#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) -#define Big1 0xffffffff - -#undef Pack_16 -#ifndef Pack_32 -#define Pack_32 -#endif - -#ifdef NO_LONG_LONG -#undef ULLong -#ifdef Just_16 -#undef Pack_32 -#define Pack_16 -/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. - * This makes some inner loops simpler and sometimes saves work - * during multiplications, but it often seems to make things slightly - * slower. Hence the default is now to store 32 bits per Long. - */ -#endif -#else /* long long available */ -#ifndef Llong -#define Llong long long -#endif -#ifndef ULLong -#define ULLong unsigned Llong -#endif -#endif /* NO_LONG_LONG */ - -#ifdef Pack_32 -#define ULbits 32 -#define kshift 5 -#define kmask 31 -#define ALL_ON 0xffffffff -#else -#define ULbits 16 -#define kshift 4 -#define kmask 15 -#define ALL_ON 0xffff -#endif - -//#ifndef MULTIPLE_THREADS -#define ACQUIRE_DTOA_LOCK(n) /*nothing*/ -#define FREE_DTOA_LOCK(n) /*nothing*/ -//#endif - -#define Kmax 9 - - struct -Bigint { - struct Bigint *next; - int k, maxwds, sign, wds; - ULong x[1]; - }; - - typedef struct Bigint Bigint; - -#ifdef NO_STRING_H -#ifdef DECLARE_SIZE_T -typedef unsigned int size_t; -#endif -extern void memcpy_D2A ANSI((void*, const void*, size_t)); -#define Bcopy(x,y) memcpy_D2A(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int)) -#else /* !NO_STRING_H */ -#define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int)) -#endif /* NO_STRING_H */ - -#define Balloc Balloc_D2A -#define Bfree Bfree_D2A -#define InfName InfName_D2A -#define NanName NanName_D2A -#define ULtoQ ULtoQ_D2A -#define ULtof ULtof_D2A -#define ULtod ULtod_D2A -#define ULtodd ULtodd_D2A -#define ULtox ULtox_D2A -#define ULtoxL ULtoxL_D2A -#define add_nanbits add_nanbits_D2A -#define any_on any_on_D2A -#define b2d b2d_D2A -#define bigtens bigtens_D2A -#define cmp cmp_D2A -#define copybits copybits_D2A -#define d2b d2b_D2A -#define decrement decrement_D2A -#define diff diff_D2A -#define dtoa_result dtoa_result_D2A -#define g__fmt g__fmt_D2A -#define gethex gethex_D2A -#define hexdig hexdig_D2A -#define hexnan hexnan_D2A -#define hi0bits(x) hi0bits_D2A((ULong)(x)) -#define i2b i2b_D2A -#define increment increment_D2A -#define lo0bits lo0bits_D2A -#define lshift lshift_D2A -#define match match_D2A -#define mult mult_D2A -#define multadd multadd_D2A -#define nrv_alloc nrv_alloc_D2A -#define pow5mult pow5mult_D2A -#define quorem quorem_D2A -#define ratio ratio_D2A -#define rshift rshift_D2A -#define rv_alloc rv_alloc_D2A -#define s2b s2b_D2A -#define set_ones set_ones_D2A -#define strcp strcp_D2A -#define strtoIg strtoIg_D2A -#define sum sum_D2A -#define tens tens_D2A -#define tinytens tinytens_D2A -#define tinytens tinytens_D2A -#define trailz trailz_D2A -#define ulp ulp_D2A - - extern char *add_nanbits ANSI((char*, size_t, ULong*, int)); - extern char *dtoa_result; - extern CONST double bigtens[], tens[], tinytens[]; - extern unsigned char hexdig[]; - extern const char *InfName[6], *NanName[3]; - - extern Bigint *Balloc ANSI((int)); - extern void Bfree ANSI((Bigint*)); - extern void ULtof ANSI((ULong*, ULong*, Long, int)); - extern void ULtod ANSI((ULong*, ULong*, Long, int)); - extern void ULtodd ANSI((ULong*, ULong*, Long, int)); - extern void ULtoQ ANSI((ULong*, ULong*, Long, int)); - extern void ULtox ANSI((UShort*, ULong*, Long, int)); - extern void ULtoxL ANSI((ULong*, ULong*, Long, int)); - extern ULong any_on ANSI((Bigint*, int)); - extern double b2d ANSI((Bigint*, int*)); - extern int cmp ANSI((Bigint*, Bigint*)); - extern void copybits ANSI((ULong*, int, Bigint*)); - extern Bigint *d2b ANSI((double, int*, int*)); - extern void decrement ANSI((Bigint*)); - extern Bigint *diff ANSI((Bigint*, Bigint*)); - extern char *dtoa ANSI((double d, int mode, int ndigits, - int *decpt, int *sign, char **rve)); - extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t)); - extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int)); - extern void hexdig_init_D2A(Void); - extern int hexnan ANSI((CONST char**, FPI*, ULong*)); - extern int hi0bits_D2A ANSI((ULong)); - extern Bigint *i2b ANSI((int)); - extern Bigint *increment ANSI((Bigint*)); - extern int lo0bits ANSI((ULong*)); - extern Bigint *lshift ANSI((Bigint*, int)); - extern int match ANSI((CONST char**, char*)); - extern Bigint *mult ANSI((Bigint*, Bigint*)); - extern Bigint *multadd ANSI((Bigint*, int, int)); - extern char *nrv_alloc ANSI((char*, char **, int)); - extern Bigint *pow5mult ANSI((Bigint*, int)); - extern int quorem ANSI((Bigint*, Bigint*)); - extern double ratio ANSI((Bigint*, Bigint*)); - extern void rshift ANSI((Bigint*, int)); - extern char *rv_alloc ANSI((int)); - extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int)); - extern Bigint *set_ones ANSI((Bigint*, int)); - extern char *strcp ANSI((char*, const char*)); - extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*)); -// extern double strtod ANSI((const char *s00, char **se)); - extern Bigint *sum ANSI((Bigint*, Bigint*)); - extern int trailz ANSI((Bigint*)); - extern double ulp ANSI((U*)); - -#ifdef __cplusplus -} -#endif -/* - * NAN_WORD0 and NAN_WORD1 are only referenced in strtod.c. Prior to - * 20050115, they used to be hard-wired here (to 0x7ff80000 and 0, - * respectively), but now are determined by compiling and running - * qnan.c to generate gd_qnan.h, which specifies d_QNAN0 and d_QNAN1. - * Formerly gdtoaimp.h recommended supplying suitable -DNAN_WORD0=... - * and -DNAN_WORD1=... values if necessary. This should still work. - * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) - */ -#ifdef IEEE_Arith -#ifndef NO_INFNAN_CHECK -#undef INFNAN_CHECK -#define INFNAN_CHECK -#endif -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#ifndef NAN_WORD0 -#define NAN_WORD0 d_QNAN0 -#endif -#ifndef NAN_WORD1 -#define NAN_WORD1 d_QNAN1 -#endif -#else -#define _0 1 -#define _1 0 -#ifndef NAN_WORD0 -#define NAN_WORD0 d_QNAN1 -#endif -#ifndef NAN_WORD1 -#define NAN_WORD1 d_QNAN0 -#endif -#endif -#else -#undef INFNAN_CHECK -#endif - -#undef SI -#ifdef Sudden_Underflow -#define SI 1 -#else -#define SI 0 -#endif - -#endif /* GDTOAIMP_H_INCLUDED */ diff --git a/libraries/gdtoa/gethex.c b/libraries/gdtoa/gethex.c deleted file mode 100644 index 72da9d3261..0000000000 --- a/libraries/gdtoa/gethex.c +++ /dev/null @@ -1,349 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#ifdef USE_LOCALE -#include "locale.h" -#endif - - int -#ifdef KR_headers -gethex(sp, fpi, exp, bp, sign) - CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign; -#else -gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign) -#endif -{ - Bigint *b; - CONST unsigned char *decpt, *s0, *s, *s1; - int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret; - ULong L, lostbits, *x; - Long e, e1; -#ifdef USE_LOCALE - int i; -#ifdef NO_LOCALE_CACHE - const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point; -#else - const unsigned char *decimalpoint; - static unsigned char *decimalpoint_cache; - if (!(s0 = decimalpoint_cache)) { - s0 = (unsigned char*)localeconv()->decimal_point; - if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { - strcpy(decimalpoint_cache, s0); - s0 = decimalpoint_cache; - } - } - decimalpoint = s0; -#endif -#endif - - /**** if (!hexdig['0']) hexdig_init_D2A(); ****/ - *bp = 0; - havedig = 0; - s0 = *(CONST unsigned char **)sp + 2; - while(s0[havedig] == '0') - havedig++; - s0 += havedig; - s = s0; - decpt = 0; - zret = 0; - e = 0; - if (hexdig[*s]) - havedig++; - else { - zret = 1; -#ifdef USE_LOCALE - for(i = 0; decimalpoint[i]; ++i) { - if (s[i] != decimalpoint[i]) - goto pcheck; - } - decpt = s += i; -#else - if (*s != '.') - goto pcheck; - decpt = ++s; -#endif - if (!hexdig[*s]) - goto pcheck; - while(*s == '0') - s++; - if (hexdig[*s]) - zret = 0; - havedig = 1; - s0 = s; - } - while(hexdig[*s]) - s++; -#ifdef USE_LOCALE - if (*s == *decimalpoint && !decpt) { - for(i = 1; decimalpoint[i]; ++i) { - if (s[i] != decimalpoint[i]) - goto pcheck; - } - decpt = s += i; -#else - if (*s == '.' && !decpt) { - decpt = ++s; -#endif - while(hexdig[*s]) - s++; - }/*}*/ - if (decpt) - e = -(((Long)(s-decpt)) << 2); - pcheck: - s1 = s; - big = esign = 0; - switch(*s) { - case 'p': - case 'P': - switch(*++s) { - case '-': - esign = 1; - /* no break */ - case '+': - s++; - } - if ((n = hexdig[*s]) == 0 || n > 0x19) { - s = s1; - break; - } - e1 = n - 0x10; - while((n = hexdig[*++s]) !=0 && n <= 0x19) { - if (e1 & 0xf8000000) - big = 1; - e1 = 10*e1 + n - 0x10; - } - if (esign) - e1 = -e1; - e += e1; - } - *sp = (char*)s; - if (!havedig) - *sp = (char*)s0 - 1; - if (zret) - return STRTOG_Zero; - if (big) { - if (esign) { - switch(fpi->rounding) { - case FPI_Round_up: - if (sign) - break; - goto ret_tiny; - case FPI_Round_down: - if (!sign) - break; - goto ret_tiny; - } - goto retz; - ret_tiny: - b = Balloc(0); - b->wds = 1; - b->x[0] = 1; - goto dret; - } - switch(fpi->rounding) { - case FPI_Round_near: - goto ovfl1; - case FPI_Round_up: - if (!sign) - goto ovfl1; - goto ret_big; - case FPI_Round_down: - if (sign) - goto ovfl1; - goto ret_big; - } - ret_big: - nbits = fpi->nbits; - n0 = n = nbits >> kshift; - if (nbits & kmask) - ++n; - for(j = n, k = 0; j >>= 1; ++k); - *bp = b = Balloc(k); - b->wds = n; - for(j = 0; j < n0; ++j) - b->x[j] = ALL_ON; - if (n > n0) - b->x[j] = ULbits >> (ULbits - (nbits & kmask)); - *exp = fpi->emin; - return STRTOG_Normal | STRTOG_Inexlo; - } - n = s1 - s0 - 1; - for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) - k++; - b = Balloc(k); - x = b->x; - n = 0; - L = 0; -#ifdef USE_LOCALE - for(i = 0; decimalpoint[i+1]; ++i); -#endif - while(s1 > s0) { -#ifdef USE_LOCALE - if (*--s1 == decimalpoint[i]) { - s1 -= i; - continue; - } -#else - if (*--s1 == '.') - continue; -#endif - if (n == ULbits) { - *x++ = L; - L = 0; - n = 0; - } - L |= (hexdig[*s1] & 0x0f) << n; - n += 4; - } - *x++ = L; - b->wds = n = x - b->x; - n = ULbits*n - hi0bits(L); - nbits = fpi->nbits; - lostbits = 0; - x = b->x; - if (n > nbits) { - n -= nbits; - if (any_on(b,n)) { - lostbits = 1; - k = n - 1; - if (x[k>>kshift] & 1 << (k & kmask)) { - lostbits = 2; - if (k > 0 && any_on(b,k)) - lostbits = 3; - } - } - rshift(b, n); - e += n; - } - else if (n < nbits) { - n = nbits - n; - b = lshift(b, n); - e -= n; - x = b->x; - } - if (e > fpi->emax) { - ovfl: - Bfree(b); - ovfl1: -#ifndef NO_ERRNO - errno = ERANGE; -#endif - return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; - } - irv = STRTOG_Normal; - if (e < fpi->emin) { - irv = STRTOG_Denormal; - n = fpi->emin - e; - if (n >= nbits) { - switch (fpi->rounding) { - case FPI_Round_near: - if (n == nbits && (n < 2 || any_on(b,n-1))) - goto one_bit; - break; - case FPI_Round_up: - if (!sign) - goto one_bit; - break; - case FPI_Round_down: - if (sign) { - one_bit: - x[0] = b->wds = 1; - dret: - *bp = b; - *exp = fpi->emin; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - return STRTOG_Denormal | STRTOG_Inexhi - | STRTOG_Underflow; - } - } - Bfree(b); - retz: -#ifndef NO_ERRNO - errno = ERANGE; -#endif - return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow; - } - k = n - 1; - if (lostbits) - lostbits = 1; - else if (k > 0) - lostbits = any_on(b,k); - if (x[k>>kshift] & 1 << (k & kmask)) - lostbits |= 2; - nbits -= n; - rshift(b,n); - e = fpi->emin; - } - if (lostbits) { - up = 0; - switch(fpi->rounding) { - case FPI_Round_zero: - break; - case FPI_Round_near: - if (lostbits & 2 - && (lostbits | x[0]) & 1) - up = 1; - break; - case FPI_Round_up: - up = 1 - sign; - break; - case FPI_Round_down: - up = sign; - } - if (up) { - k = b->wds; - b = increment(b); - x = b->x; - if (irv == STRTOG_Denormal) { - if (nbits == fpi->nbits - 1 - && x[nbits >> kshift] & 1 << (nbits & kmask)) - irv = STRTOG_Normal; - } - else if (b->wds > k - || ((n = nbits & kmask) !=0 - && hi0bits(x[k-1]) < 32-n)) { - rshift(b,1); - if (++e > fpi->emax) - goto ovfl; - } - irv |= STRTOG_Inexhi; - } - else - irv |= STRTOG_Inexlo; - } - *bp = b; - *exp = e; - return irv; - } diff --git a/libraries/gdtoa/gmisc.c b/libraries/gdtoa/gmisc.c deleted file mode 100644 index 8270ef9447..0000000000 --- a/libraries/gdtoa/gmisc.c +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - void -#ifdef KR_headers -rshift(b, k) Bigint *b; int k; -#else -rshift(Bigint *b, int k) -#endif -{ - ULong *x, *x1, *xe, y; - int n; - - x = x1 = b->x; - n = k >> kshift; - if (n < b->wds) { - xe = x + b->wds; - x += n; - if (k &= kmask) { - n = ULbits - k; - y = *x++ >> k; - while(x < xe) { - *x1++ = (y | (*x << n)) & ALL_ON; - y = *x++ >> k; - } - if ((*x1 = y) !=0) - x1++; - } - else - while(x < xe) - *x1++ = *x++; - } - if ((b->wds = x1 - b->x) == 0) - b->x[0] = 0; - } - - int -#ifdef KR_headers -trailz(b) Bigint *b; -#else -trailz(Bigint *b) -#endif -{ - ULong L, *x, *xe; - int n = 0; - - x = b->x; - xe = x + b->wds; - for(n = 0; x < xe && !*x; x++) - n += ULbits; - if (x < xe) { - L = *x; - n += lo0bits(&L); - } - return n; - } diff --git a/libraries/gdtoa/hd_init.c b/libraries/gdtoa/hd_init.c deleted file mode 100644 index d79ae2ec8a..0000000000 --- a/libraries/gdtoa/hd_init.c +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#if 0 - unsigned char hexdig[256]; - - static void -#ifdef KR_headers -htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc; -#else -htinit(unsigned char *h, unsigned char *s, int inc) -#endif -{ - int i, j; - for(i = 0; (j = s[i]) !=0; i++) - h[j] = i + inc; - } - - void -hexdig_init_D2A(Void) /* Use of hexdig_init omitted 20121220 to avoid a */ - /* race condition when multiple threads are used. */ -{ -#define USC (unsigned char *) - htinit(hexdig, USC "0123456789", 0x10); - htinit(hexdig, USC "abcdef", 0x10 + 10); - htinit(hexdig, USC "ABCDEF", 0x10 + 10); - } -#else - unsigned char hexdig[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0, - 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - }; -#endif diff --git a/libraries/gdtoa/hexnan.c b/libraries/gdtoa/hexnan.c deleted file mode 100644 index 80721e97af..0000000000 --- a/libraries/gdtoa/hexnan.c +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - static void -#ifdef KR_headers -L_shift(x, x1, i) ULong *x; ULong *x1; int i; -#else -L_shift(ULong *x, ULong *x1, int i) -#endif -{ - int j; - - i = 8 - i; - i <<= 2; - j = ULbits - i; - do { - *x |= x[1] << j; - x[1] >>= i; - } while(++x < x1); - } - - int -#ifdef KR_headers -hexnan(sp, fpi, x0) - CONST char **sp; FPI *fpi; ULong *x0; -#else -hexnan( CONST char **sp, FPI *fpi, ULong *x0) -#endif -{ - ULong c, h, *x, *x1, *xe; - CONST char *s; - int havedig, hd0, i, nbits; - - /**** if (!hexdig['0']) hexdig_init_D2A(); ****/ - nbits = fpi->nbits; - x = x0 + (nbits >> kshift); - if (nbits & kmask) - x++; - *--x = 0; - x1 = xe = x; - havedig = hd0 = i = 0; - s = *sp; - /* allow optional initial 0x or 0X */ - while((c = *(CONST unsigned char*)(s+1)) && c <= ' ') { - if (!c) - goto retnan; - ++s; - } - if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X') - && *(CONST unsigned char*)(s+3) > ' ') - s += 2; - while((c = *(CONST unsigned char*)++s)) { - if (!(h = hexdig[c])) { - if (c <= ' ') { - if (hd0 < havedig) { - if (x < x1 && i < 8) - L_shift(x, x1, i); - if (x <= x0) { - i = 8; - continue; - } - hd0 = havedig; - *--x = 0; - x1 = x; - i = 0; - } - while((c = *(CONST unsigned char*)(s+1)) <= ' ') { - if (!c) - goto retnan; - ++s; - } - if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X') - && *(CONST unsigned char*)(s+3) > ' ') - s += 2; - continue; - } - if (/*(*/ c == ')' && havedig) { - *sp = s + 1; - break; - } -#ifndef GDTOA_NON_PEDANTIC_NANCHECK - do { - if (/*(*/ c == ')') { - *sp = s + 1; - goto break2; - } - } while((c = *++s)); -#endif - retnan: - return STRTOG_NaN; - } - havedig++; - if (++i > 8) { - if (x <= x0) - continue; - i = 1; - *--x = 0; - } - *x = (*x << 4) | (h & 0xf); - } -#ifndef GDTOA_NON_PEDANTIC_NANCHECK - break2: -#endif - if (!havedig) - return STRTOG_NaN; - if (x < x1 && i < 8) - L_shift(x, x1, i); - if (x > x0) { - x1 = x0; - do *x1++ = *x++; - while(x <= xe); - do *x1++ = 0; - while(x1 <= xe); - } - else { - /* truncate high-order word if necessary */ - if ( (i = nbits & (ULbits-1)) !=0) - *xe &= ((ULong)0xffffffff) >> (ULbits - i); - } - for(x1 = xe;; --x1) { - if (*x1 != 0) - break; - if (x1 == x0) { - *x1 = 1; - break; - } - } - return STRTOG_NaNbits; - } diff --git a/libraries/gdtoa/misc.c b/libraries/gdtoa/misc.c deleted file mode 100644 index d13046732a..0000000000 --- a/libraries/gdtoa/misc.c +++ /dev/null @@ -1,875 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 1999 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - static Bigint *freelist[Kmax+1]; -#ifndef Omit_Private_Memory -#ifndef PRIVATE_MEM -#define PRIVATE_MEM 2304 -#endif -#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) -static double private_mem[PRIVATE_mem], *pmem_next = private_mem; -#endif - - Bigint * -Balloc -#ifdef KR_headers - (k) int k; -#else - (int k) -#endif -{ - int x; - Bigint *rv; -#ifndef Omit_Private_Memory - unsigned int len; -#endif - - ACQUIRE_DTOA_LOCK(0); - /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ - /* but this case seems very unlikely. */ - if (k <= Kmax && (rv = freelist[k]) !=0) { - freelist[k] = rv->next; - } - else { - x = 1 << k; -#ifdef Omit_Private_Memory - rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); -#else - len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) - /sizeof(double); - if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { - rv = (Bigint*)pmem_next; - pmem_next += len; - } - else - rv = (Bigint*)MALLOC(len*sizeof(double)); -#endif - rv->k = k; - rv->maxwds = x; - } - FREE_DTOA_LOCK(0); - rv->sign = rv->wds = 0; - return rv; - } - - void -Bfree -#ifdef KR_headers - (v) Bigint *v; -#else - (Bigint *v) -#endif -{ - if (v) { - if (v->k > Kmax) -#ifdef FREE - FREE((void*)v); -#else - free((void*)v); -#endif - else { - ACQUIRE_DTOA_LOCK(0); - v->next = freelist[v->k]; - freelist[v->k] = v; - FREE_DTOA_LOCK(0); - } - } - } - - int -lo0bits -#ifdef KR_headers - (y) ULong *y; -#else - (ULong *y) -#endif -{ - int k; - ULong x = *y; - - if (x & 7) { - if (x & 1) - return 0; - if (x & 2) { - *y = x >> 1; - return 1; - } - *y = x >> 2; - return 2; - } - k = 0; - if (!(x & 0xffff)) { - k = 16; - x >>= 16; - } - if (!(x & 0xff)) { - k += 8; - x >>= 8; - } - if (!(x & 0xf)) { - k += 4; - x >>= 4; - } - if (!(x & 0x3)) { - k += 2; - x >>= 2; - } - if (!(x & 1)) { - k++; - x >>= 1; - if (!x) - return 32; - } - *y = x; - return k; - } - - Bigint * -multadd -#ifdef KR_headers - (b, m, a) Bigint *b; int m, a; -#else - (Bigint *b, int m, int a) /* multiply by m and add a */ -#endif -{ - int i, wds; -#ifdef ULLong - ULong *x; - ULLong carry, y; -#else - ULong carry, *x, y; -#ifdef Pack_32 - ULong xi, z; -#endif -#endif - Bigint *b1; - - wds = b->wds; - x = b->x; - i = 0; - carry = a; - do { -#ifdef ULLong - y = *x * (ULLong)m + carry; - carry = y >> 32; - *x++ = (ULong)(y & 0xffffffffUL); -#else -#ifdef Pack_32 - xi = *x; - y = (xi & 0xffff) * m + carry; - z = (xi >> 16) * m + (y >> 16); - carry = z >> 16; - *x++ = (z << 16) + (y & 0xffff); -#else - y = *x * m + carry; - carry = y >> 16; - *x++ = y & 0xffff; -#endif -#endif - } - while(++i < wds); - if (carry) { - if (wds >= b->maxwds) { - b1 = Balloc(b->k+1); - Bcopy(b1, b); - Bfree(b); - b = b1; - } - b->x[wds++] = (ULong)carry; - b->wds = wds; - } - return b; - } - - int -hi0bits_D2A -#ifdef KR_headers - (x) ULong x; -#else - (ULong x) -#endif -{ - int k = 0; - - if (!(x & 0xffff0000)) { - k = 16; - x <<= 16; - } - if (!(x & 0xff000000)) { - k += 8; - x <<= 8; - } - if (!(x & 0xf0000000)) { - k += 4; - x <<= 4; - } - if (!(x & 0xc0000000)) { - k += 2; - x <<= 2; - } - if (!(x & 0x80000000)) { - k++; - if (!(x & 0x40000000)) - return 32; - } - return k; - } - - Bigint * -i2b -#ifdef KR_headers - (i) int i; -#else - (int i) -#endif -{ - Bigint *b; - - b = Balloc(1); - b->x[0] = i; - b->wds = 1; - return b; - } - - Bigint * -mult -#ifdef KR_headers - (a, b) Bigint *a, *b; -#else - (Bigint *a, Bigint *b) -#endif -{ - Bigint *c; - int k, wa, wb, wc; - ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; - ULong y; -#ifdef ULLong - ULLong carry, z; -#else - ULong carry, z; -#ifdef Pack_32 - ULong z2; -#endif -#endif - - if (a->wds < b->wds) { - c = a; - a = b; - b = c; - } - k = a->k; - wa = a->wds; - wb = b->wds; - wc = wa + wb; - if (wc > a->maxwds) - k++; - c = Balloc(k); - for(x = c->x, xa = x + wc; x < xa; x++) - *x = 0; - xa = a->x; - xae = xa + wa; - xb = b->x; - xbe = xb + wb; - xc0 = c->x; -#ifdef ULLong - for(; xb < xbe; xc0++) { - if ( (y = *xb++) !=0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * (ULLong)y + *xc + carry; - carry = z >> 32; - *xc++ = (ULong)(z & 0xffffffffUL); - } - while(x < xae); - *xc = (ULong)carry; - } - } -#else -#ifdef Pack_32 - for(; xb < xbe; xb++, xc0++) { - if ( (y = *xb & 0xffff) !=0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; - carry = z >> 16; - z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; - carry = z2 >> 16; - Storeinc(xc, z2, z); - } - while(x < xae); - *xc = carry; - } - if ( (y = *xb >> 16) !=0) { - x = xa; - xc = xc0; - carry = 0; - z2 = *xc; - do { - z = (*x & 0xffff) * y + (*xc >> 16) + carry; - carry = z >> 16; - Storeinc(xc, z, z2); - z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; - carry = z2 >> 16; - } - while(x < xae); - *xc = z2; - } - } -#else - for(; xb < xbe; xc0++) { - if ( (y = *xb++) !=0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * y + *xc + carry; - carry = z >> 16; - *xc++ = z & 0xffff; - } - while(x < xae); - *xc = carry; - } - } -#endif -#endif - for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; - c->wds = wc; - return c; - } - - static Bigint *p5s; - - Bigint * -pow5mult -#ifdef KR_headers - (b, k) Bigint *b; int k; -#else - (Bigint *b, int k) -#endif -{ - Bigint *b1, *p5, *p51; - int i; - static int p05[3] = { 5, 25, 125 }; - - if ( (i = k & 3) !=0) - b = multadd(b, p05[i-1], 0); - - if (!(k >>= 2)) - return b; - if ((p5 = p5s) == 0) { - /* first time */ -#ifdef MULTIPLE_THREADS - ACQUIRE_DTOA_LOCK(1); - if (!(p5 = p5s)) { - p5 = p5s = i2b(625); - p5->next = 0; - } - FREE_DTOA_LOCK(1); -#else - p5 = p5s = i2b(625); - p5->next = 0; -#endif - } - for(;;) { - if (k & 1) { - b1 = mult(b, p5); - Bfree(b); - b = b1; - } - if (!(k >>= 1)) - break; - if ((p51 = p5->next) == 0) { -#ifdef MULTIPLE_THREADS - ACQUIRE_DTOA_LOCK(1); - if (!(p51 = p5->next)) { - p51 = p5->next = mult(p5,p5); - p51->next = 0; - } - FREE_DTOA_LOCK(1); -#else - p51 = p5->next = mult(p5,p5); - p51->next = 0; -#endif - } - p5 = p51; - } - return b; - } - - Bigint * -lshift -#ifdef KR_headers - (b, k) Bigint *b; int k; -#else - (Bigint *b, int k) -#endif -{ - int i, k1, n, n1; - Bigint *b1; - ULong *x, *x1, *xe, z; - - n = k >> kshift; - k1 = b->k; - n1 = n + b->wds + 1; - for(i = b->maxwds; n1 > i; i <<= 1) - k1++; - b1 = Balloc(k1); - x1 = b1->x; - for(i = 0; i < n; i++) - *x1++ = 0; - x = b->x; - xe = x + b->wds; - if (k &= kmask) { -#ifdef Pack_32 - k1 = 32 - k; - z = 0; - do { - *x1++ = *x << k | z; - z = *x++ >> k1; - } - while(x < xe); - if ((*x1 = z) !=0) - ++n1; -#else - k1 = 16 - k; - z = 0; - do { - *x1++ = *x << k & 0xffff | z; - z = *x++ >> k1; - } - while(x < xe); - if (*x1 = z) - ++n1; -#endif - } - else do - *x1++ = *x++; - while(x < xe); - b1->wds = n1 - 1; - Bfree(b); - return b1; - } - - int -cmp -#ifdef KR_headers - (a, b) Bigint *a, *b; -#else - (Bigint *a, Bigint *b) -#endif -{ - ULong *xa, *xa0, *xb, *xb0; - int i, j; - - i = a->wds; - j = b->wds; -#ifdef DEBUG - if (i > 1 && !a->x[i-1]) - Bug("cmp called with a->x[a->wds-1] == 0"); - if (j > 1 && !b->x[j-1]) - Bug("cmp called with b->x[b->wds-1] == 0"); -#endif - if (i -= j) - return i; - xa0 = a->x; - xa = xa0 + j; - xb0 = b->x; - xb = xb0 + j; - for(;;) { - if (*--xa != *--xb) - return *xa < *xb ? -1 : 1; - if (xa <= xa0) - break; - } - return 0; - } - - Bigint * -diff -#ifdef KR_headers - (a, b) Bigint *a, *b; -#else - (Bigint *a, Bigint *b) -#endif -{ - Bigint *c; - int i, wa, wb; - ULong *xa, *xae, *xb, *xbe, *xc; -#ifdef ULLong - ULLong borrow, y; -#else - ULong borrow, y; -#ifdef Pack_32 - ULong z; -#endif -#endif - - i = cmp(a,b); - if (!i) { - c = Balloc(0); - c->wds = 1; - c->x[0] = 0; - return c; - } - if (i < 0) { - c = a; - a = b; - b = c; - i = 1; - } - else - i = 0; - c = Balloc(a->k); - c->sign = i; - wa = a->wds; - xa = a->x; - xae = xa + wa; - wb = b->wds; - xb = b->x; - xbe = xb + wb; - xc = c->x; - borrow = 0; -#ifdef ULLong - do { - y = (ULLong)*xa++ - *xb++ - borrow; - borrow = y >> 32 & 1UL; - *xc++ = (ULong)(y & 0xffffffffUL); - } - while(xb < xbe); - while(xa < xae) { - y = *xa++ - borrow; - borrow = y >> 32 & 1UL; - *xc++ = (ULong)(y & 0xffffffffUL); - } -#else -#ifdef Pack_32 - do { - y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } - while(xb < xbe); - while(xa < xae) { - y = (*xa & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } -#else - do { - y = *xa++ - *xb++ - borrow; - borrow = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } - while(xb < xbe); - while(xa < xae) { - y = *xa++ - borrow; - borrow = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } -#endif -#endif - while(!*--xc) - wa--; - c->wds = wa; - return c; - } - - double -b2d -#ifdef KR_headers - (a, e) Bigint *a; int *e; -#else - (Bigint *a, int *e) -#endif -{ - ULong *xa, *xa0, w, y, z; - int k; - U d; -#ifdef VAX - ULong d0, d1; -#else -#define d0 word0(&d) -#define d1 word1(&d) -#endif - - xa0 = a->x; - xa = xa0 + a->wds; - y = *--xa; -#ifdef DEBUG - if (!y) Bug("zero y in b2d"); -#endif - k = hi0bits(y); - *e = 32 - k; -#ifdef Pack_32 - if (k < Ebits) { - d0 = Exp_1 | y >> (Ebits - k); - w = xa > xa0 ? *--xa : 0; - d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - if (k -= Ebits) { - d0 = Exp_1 | y << k | z >> (32 - k); - y = xa > xa0 ? *--xa : 0; - d1 = z << k | y >> (32 - k); - } - else { - d0 = Exp_1 | y; - d1 = z; - } -#else - if (k < Ebits + 16) { - z = xa > xa0 ? *--xa : 0; - d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; - w = xa > xa0 ? *--xa : 0; - y = xa > xa0 ? *--xa : 0; - d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - w = xa > xa0 ? *--xa : 0; - k -= Ebits + 16; - d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; - y = xa > xa0 ? *--xa : 0; - d1 = w << k + 16 | y << k; -#endif - ret_d: -#ifdef VAX - word0(&d) = d0 >> 16 | d0 << 16; - word1(&d) = d1 >> 16 | d1 << 16; -#endif - return dval(&d); - } -#undef d0 -#undef d1 - - Bigint * -d2b -#ifdef KR_headers - (dd, e, bits) double dd; int *e, *bits; -#else - (double dd, int *e, int *bits) -#endif -{ - Bigint *b; - U d; -#ifndef Sudden_Underflow - int i; -#endif - int de, k; - ULong *x, y, z; -#ifdef VAX - ULong d0, d1; -#else -#define d0 word0(&d) -#define d1 word1(&d) -#endif - d.d = dd; -#ifdef VAX - d0 = word0(&d) >> 16 | word0(&d) << 16; - d1 = word1(&d) >> 16 | word1(&d) << 16; -#endif - -#ifdef Pack_32 - b = Balloc(1); -#else - b = Balloc(2); -#endif - x = b->x; - - z = d0 & Frac_mask; - d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ -#ifdef Sudden_Underflow - de = (int)(d0 >> Exp_shift); -#ifndef IBM - z |= Exp_msk11; -#endif -#else - if ( (de = (int)(d0 >> Exp_shift)) !=0) - z |= Exp_msk1; -#endif -#ifdef Pack_32 - if ( (y = d1) !=0) { - if ( (k = lo0bits(&y)) !=0) { - x[0] = y | z << (32 - k); - z >>= k; - } - else - x[0] = y; -#ifndef Sudden_Underflow - i = -#endif - b->wds = (x[1] = z) !=0 ? 2 : 1; - } - else { - k = lo0bits(&z); - x[0] = z; -#ifndef Sudden_Underflow - i = -#endif - b->wds = 1; - k += 32; - } -#else - if ( (y = d1) !=0) { - if ( (k = lo0bits(&y)) !=0) - if (k >= 16) { - x[0] = y | z << 32 - k & 0xffff; - x[1] = z >> k - 16 & 0xffff; - x[2] = z >> k; - i = 2; - } - else { - x[0] = y & 0xffff; - x[1] = y >> 16 | z << 16 - k & 0xffff; - x[2] = z >> k & 0xffff; - x[3] = z >> k+16; - i = 3; - } - else { - x[0] = y & 0xffff; - x[1] = y >> 16; - x[2] = z & 0xffff; - x[3] = z >> 16; - i = 3; - } - } - else { -#ifdef DEBUG - if (!z) - Bug("Zero passed to d2b"); -#endif - k = lo0bits(&z); - if (k >= 16) { - x[0] = z; - i = 0; - } - else { - x[0] = z & 0xffff; - x[1] = z >> 16; - i = 1; - } - k += 32; - } - while(!x[i]) - --i; - b->wds = i + 1; -#endif -#ifndef Sudden_Underflow - if (de) { -#endif -#ifdef IBM - *e = (de - Bias - (P-1) << 2) + k; - *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask); -#else - *e = de - Bias - (P-1) + k; - *bits = P - k; -#endif -#ifndef Sudden_Underflow - } - else { - *e = de - Bias - (P-1) + 1 + k; -#ifdef Pack_32 - *bits = 32*i - hi0bits(x[i-1]); -#else - *bits = (i+2)*16 - hi0bits(x[i]); -#endif - } -#endif - return b; - } -#undef d0 -#undef d1 - - CONST double -#ifdef IEEE_Arith -bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; -CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 - }; -#else -#ifdef IBM -bigtens[] = { 1e16, 1e32, 1e64 }; -CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 }; -#else -bigtens[] = { 1e16, 1e32 }; -CONST double tinytens[] = { 1e-16, 1e-32 }; -#endif -#endif - - CONST double -tens[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22 -#ifdef VAX - , 1e23, 1e24 -#endif - }; - - char * -#ifdef KR_headers -strcp_D2A(a, b) char *a; char *b; -#else -strcp_D2A(char *a, CONST char *b) -#endif -{ - while((*a = *b++)) - a++; - return a; - } - -#ifdef NO_STRING_H - - Char * -#ifdef KR_headers -memcpy_D2A(a, b, len) Char *a; Char *b; size_t len; -#else -memcpy_D2A(void *a1, void *b1, size_t len) -#endif -{ - char *a = (char*)a1, *ae = a + len; - char *b = (char*)b1, *a0 = a; - while(a < ae) - *a++ = *b++; - return a0; - } - -#endif /* NO_STRING_H */ diff --git a/libraries/gdtoa/qnan.c b/libraries/gdtoa/qnan.c deleted file mode 100644 index ea7e8745ba..0000000000 --- a/libraries/gdtoa/qnan.c +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 2005 by David M. Gay -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that the copyright notice and this permission notice and warranty -disclaimer appear in supporting documentation, and that the name of -the author or any of his current or former employers not be used in -advertising or publicity pertaining to distribution of the software -without specific, written prior permission. - -THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN -NO EVENT SHALL THE AUTHOR OR ANY OF HIS CURRENT OR FORMER EMPLOYERS BE -LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY -DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -/* Program to compute quiet NaNs of various precisions (float, */ -/* double, and perhaps long double) on the current system, */ -/* provided the system uses binary IEEE (P754) arithmetic. */ -/* Note that one system's quiet NaN may be a signaling NaN on */ -/* another system. The IEEE arithmetic standards (P754, P854) */ -/* do not specify how to distinguish signaling NaNs from quiet */ -/* ones, and this detail varies across systems. The computed */ -/* NaN values are encoded in #defines for values for an */ -/* unsigned 32-bit integer type, called Ulong below, and */ -/* (for long double) perhaps as unsigned short values. Once */ -/* upon a time, there were PC compilers for Intel CPUs that */ -/* had sizeof(long double) = 10. Are such compilers still */ -/* distributed? */ - -#include -#include "arith.h" - -#ifndef Long -#define Long long -#endif - -typedef unsigned Long Ulong; - -#undef HAVE_IEEE -#ifdef IEEE_8087 -#define _0 1 -#define _1 0 -#define _3 3 -#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) -static int perm[4] = { 0, 1, 2, 3 }; -#endif -#define HAVE_IEEE -#endif -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _3 0 -#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) -static int perm[4] = { 3, 2, 1, 0 }; -#endif -#define HAVE_IEEE -#endif - -#define UL (unsigned long) - - int -main(void) -{ -#ifdef HAVE_IEEE - typedef union { - float f; - double d; - Ulong L[4]; -#ifndef NO_LONG_LONG - unsigned short u[5]; - long double D; -#endif - } U; - U a, b, c; -#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) - int i; -#endif - - a.L[0] = b.L[0] = 0x7f800000; - c.f = a.f - b.f; - printf("#define f_QNAN 0x%lx\n", UL (c.L[0] & 0x7fffffff)); - a.L[_0] = b.L[_0] = 0x7ff00000; - a.L[_1] = b.L[_1] = 0; - c.d = a.d - b.d; /* quiet NaN */ - c.L[_0] &= 0x7fffffff; - printf("#define d_QNAN0 0x%lx\n", UL c.L[_0]); - printf("#define d_QNAN1 0x%lx\n", UL c.L[_1]); -#ifndef NO_LONG_LONG -#ifdef Gen_ld_QNAN - if (sizeof(a.D) >= 16) { - b.D = c.D = a.d; - if (printf("") < 0) - c.D = 37; /* never executed; just defeat optimization */ - a.L[0] = a.L[1] = a.L[2] = a.L[3] = 0; - a.D = b.D - c.D; - a.L[_3] &= 0x7fffffff; - for(i = 0; i < 4; i++) - printf("#define ld_QNAN%d 0x%lx\n", i, UL a.L[perm[i]]); - } -#endif -#endif -#endif /* HAVE_IEEE */ - return 0; - } diff --git a/libraries/gdtoa/qnan.obj b/libraries/gdtoa/qnan.obj deleted file mode 100644 index 994af47d98..0000000000 Binary files a/libraries/gdtoa/qnan.obj and /dev/null differ diff --git a/libraries/gdtoa/smisc.c b/libraries/gdtoa/smisc.c deleted file mode 100644 index f4dbafb21c..0000000000 --- a/libraries/gdtoa/smisc.c +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 1999 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - Bigint * -s2b -#ifdef KR_headers - (s, nd0, nd, y9, dplen) CONST char *s; int dplen, nd0, nd; ULong y9; -#else - (CONST char *s, int nd0, int nd, ULong y9, int dplen) -#endif -{ - Bigint *b; - int i, k; - Long x, y; - - x = (nd + 8) / 9; - for(k = 0, y = 1; x > y; y <<= 1, k++) ; -#ifdef Pack_32 - b = Balloc(k); - b->x[0] = y9; - b->wds = 1; -#else - b = Balloc(k+1); - b->x[0] = y9 & 0xffff; - b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; -#endif - - i = 9; - if (9 < nd0) { - s += 9; - do b = multadd(b, 10, *s++ - '0'); - while(++i < nd0); - s += dplen; - } - else - s += dplen + 9; - for(; i < nd; i++) - b = multadd(b, 10, *s++ - '0'); - return b; - } - - double -ratio -#ifdef KR_headers - (a, b) Bigint *a, *b; -#else - (Bigint *a, Bigint *b) -#endif -{ - U da, db; - int k, ka, kb; - - dval(&da) = b2d(a, &ka); - dval(&db) = b2d(b, &kb); - k = ka - kb + ULbits*(a->wds - b->wds); -#ifdef IBM - if (k > 0) { - word0(&da) += (k >> 2)*Exp_msk1; - if (k &= 3) - dval(&da) *= 1 << k; - } - else { - k = -k; - word0(&db) += (k >> 2)*Exp_msk1; - if (k &= 3) - dval(&db) *= 1 << k; - } -#else - if (k > 0) - word0(&da) += k*Exp_msk1; - else { - k = -k; - word0(&db) += k*Exp_msk1; - } -#endif - return dval(&da) / dval(&db); - } - -#ifdef INFNAN_CHECK - - int -match -#ifdef KR_headers - (sp, t) char **sp, *t; -#else - (CONST char **sp, char *t) -#endif -{ - int c, d; - CONST char *s = *sp; - - while( (d = *t++) !=0) { - if ((c = *++s) >= 'A' && c <= 'Z') - c += 'a' - 'A'; - if (c != d) - return 0; - } - *sp = s + 1; - return 1; - } -#endif /* INFNAN_CHECK */ - - void -#ifdef KR_headers -copybits(c, n, b) ULong *c; int n; Bigint *b; -#else -copybits(ULong *c, int n, Bigint *b) -#endif -{ - ULong *ce, *x, *xe; -#ifdef Pack_16 - int nw, nw1; -#endif - - ce = c + ((n-1) >> kshift) + 1; - x = b->x; -#ifdef Pack_32 - xe = x + b->wds; - while(x < xe) - *c++ = *x++; -#else - nw = b->wds; - nw1 = nw & 1; - for(xe = x + (nw - nw1); x < xe; x += 2) - Storeinc(c, x[1], x[0]); - if (nw1) - *c++ = *x; -#endif - while(c < ce) - *c++ = 0; - } - - ULong -#ifdef KR_headers -any_on(b, k) Bigint *b; int k; -#else -any_on(Bigint *b, int k) -#endif -{ - int n, nwds; - ULong *x, *x0, x1, x2; - - x = b->x; - nwds = b->wds; - n = k >> kshift; - if (n > nwds) - n = nwds; - else if (n < nwds && (k &= kmask)) { - x1 = x2 = x[n]; - x1 >>= k; - x1 <<= k; - if (x1 != x2) - return 1; - } - x0 = x; - x += n; - while(x > x0) - if (*--x) - return 1; - return 0; - } diff --git a/libraries/gdtoa/strtoIQ.c b/libraries/gdtoa/strtoIQ.c deleted file mode 100644 index 9ce5120e6b..0000000000 --- a/libraries/gdtoa/strtoIQ.c +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtoIQ(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; -#else -strtoIQ(CONST char *s, char **sp, void *a, void *b) -#endif -{ - static FPI fpi = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; - Long exp[2]; - Bigint *B[2]; - int k, rv[2]; - ULong *L = (ULong *)a, *M = (ULong *)b; - - B[0] = Balloc(2); - B[0]->wds = 4; - k = strtoIg(s, sp, &fpi, exp, B, rv); - ULtoQ(L, B[0]->x, exp[0], rv[0]); - Bfree(B[0]); - if (B[1]) { - ULtoQ(M, B[1]->x, exp[1], rv[1]); - Bfree(B[1]); - } - else { - M[0] = L[0]; - M[1] = L[1]; - M[2] = L[2]; - M[3] = L[3]; - } - return k; - } diff --git a/libraries/gdtoa/strtoId.c b/libraries/gdtoa/strtoId.c deleted file mode 100644 index 1c97d382de..0000000000 --- a/libraries/gdtoa/strtoId.c +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtoId(s, sp, f0, f1) CONST char *s; char **sp; double *f0, *f1; -#else -strtoId(CONST char *s, char **sp, double *f0, double *f1) -#endif -{ - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - Long exp[2]; - Bigint *B[2]; - int k, rv[2]; - - B[0] = Balloc(1); - B[0]->wds = 2; - k = strtoIg(s, sp, &fpi, exp, B, rv); - ULtod((ULong*)f0, B[0]->x, exp[0], rv[0]); - Bfree(B[0]); - if (B[1]) { - ULtod((ULong*)f1, B[1]->x, exp[1], rv[1]); - Bfree(B[1]); - } - else { - ((ULong*)f1)[0] = ((ULong*)f0)[0]; - ((ULong*)f1)[1] = ((ULong*)f0)[1]; - } - return k; - } diff --git a/libraries/gdtoa/strtoIdd.c b/libraries/gdtoa/strtoIdd.c deleted file mode 100644 index 40b7936bc0..0000000000 --- a/libraries/gdtoa/strtoIdd.c +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtoIdd(s, sp, f0, f1) CONST char *s; char **sp; double *f0, *f1; -#else -strtoIdd(CONST char *s, char **sp, double *f0, double *f1) -#endif -{ -#ifdef Sudden_Underflow - static FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; -#else - static FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; -#endif - Long exp[2]; - Bigint *B[2]; - int k, rv[2]; - - B[0] = Balloc(2); - B[0]->wds = 4; - k = strtoIg(s, sp, &fpi, exp, B, rv); - ULtodd((ULong*)f0, B[0]->x, exp[0], rv[0]); - Bfree(B[0]); - if (B[1]) { - ULtodd((ULong*)f1, B[1]->x, exp[1], rv[1]); - Bfree(B[1]); - } - else { - ((ULong*)f1)[0] = ((ULong*)f0)[0]; - ((ULong*)f1)[1] = ((ULong*)f0)[1]; - ((ULong*)f1)[2] = ((ULong*)f0)[2]; - ((ULong*)f1)[3] = ((ULong*)f0)[3]; - } - return k; - } diff --git a/libraries/gdtoa/strtoIf.c b/libraries/gdtoa/strtoIf.c deleted file mode 100644 index 65ecab2e0b..0000000000 --- a/libraries/gdtoa/strtoIf.c +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtoIf(s, sp, f0, f1) CONST char *s; char **sp; float *f0, *f1; -#else -strtoIf(CONST char *s, char **sp, float *f0, float *f1) -#endif -{ - static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; - Long exp[2]; - Bigint *B[2]; - int k, rv[2]; - - B[0] = Balloc(0); - B[0]->wds = 1; - k = strtoIg(s, sp, &fpi, exp, B, rv); - ULtof((ULong*)f0, B[0]->x, exp[0], rv[0]); - Bfree(B[0]); - if (B[1]) { - ULtof((ULong*)f1, B[1]->x, exp[1], rv[1]); - Bfree(B[1]); - } - else - *(ULong*)f1 = *(ULong*)f0; - return k; - } diff --git a/libraries/gdtoa/strtoIg.c b/libraries/gdtoa/strtoIg.c deleted file mode 100644 index 6a17760cf5..0000000000 --- a/libraries/gdtoa/strtoIg.c +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtoIg(s00, se, fpi, exp, B, rvp) CONST char *s00; char **se; FPI *fpi; Long *exp; Bigint **B; int *rvp; -#else -strtoIg(CONST char *s00, char **se, FPI *fpi, Long *exp, Bigint **B, int *rvp) -#endif -{ - Bigint *b, *b1; - int i, nb, nw, nw1, rv, rv1, swap; - unsigned int nb1, nb11; - Long e1; - - b = *B; - rv = strtodg(s00, se, fpi, exp, b->x); - if (!(rv & STRTOG_Inexact)) { - B[1] = 0; - return *rvp = rv; - } - e1 = exp[0]; - rv1 = rv ^ STRTOG_Inexact; - b1 = Balloc(b->k); - Bcopy(b1, b); - nb = fpi->nbits; - nb1 = nb & 31; - nb11 = (nb1 - 1) & 31; - nw = b->wds; - nw1 = nw - 1; - if (rv & STRTOG_Inexlo) { - swap = 0; - b1 = increment(b1); - if ((rv & STRTOG_Retmask) == STRTOG_Zero) { - if (fpi->sudden_underflow) { - b1->x[0] = 0; - b1->x[nw1] = 1L << nb11; - rv1 += STRTOG_Normal - STRTOG_Zero; - rv1 &= ~STRTOG_Underflow; - goto swapcheck; - } - rv1 &= STRTOG_Inexlo | STRTOG_Underflow | STRTOG_Zero; - rv1 |= STRTOG_Inexhi | STRTOG_Denormal; - goto swapcheck; - } - if (b1->wds > nw - || (nb1 && b1->x[nw1] & 1L << nb1)) { - if (++e1 > fpi->emax) - rv1 = STRTOG_Infinite | STRTOG_Inexhi; - rshift(b1, 1); - } - else if ((rv & STRTOG_Retmask) == STRTOG_Denormal) { - if (b1->x[nw1] & 1L << nb11) { - rv1 += STRTOG_Normal - STRTOG_Denormal; - rv1 &= ~STRTOG_Underflow; - } - } - } - else { - swap = STRTOG_Neg; - if ((rv & STRTOG_Retmask) == STRTOG_Infinite) { - b1 = set_ones(b1, nb); - e1 = fpi->emax; - rv1 = STRTOG_Normal | STRTOG_Inexlo; - goto swapcheck; - } - decrement(b1); - if ((rv & STRTOG_Retmask) == STRTOG_Denormal) { - for(i = nw1; !b1->x[i]; --i) - if (!i) { - rv1 = STRTOG_Zero | STRTOG_Inexlo; - break; - } - goto swapcheck; - } - if (!(b1->x[nw1] & 1L << nb11)) { - if (e1 == fpi->emin) { - if (fpi->sudden_underflow) - rv1 += STRTOG_Zero - STRTOG_Normal; - else - rv1 += STRTOG_Denormal - STRTOG_Normal; - rv1 |= STRTOG_Underflow; - } - else { - b1 = lshift(b1, 1); - b1->x[0] |= 1; - --e1; - } - } - } - swapcheck: - if (swap ^ (rv & STRTOG_Neg)) { - rvp[0] = rv1; - rvp[1] = rv; - B[0] = b1; - B[1] = b; - exp[1] = exp[0]; - exp[0] = e1; - } - else { - rvp[0] = rv; - rvp[1] = rv1; - B[1] = b1; - exp[1] = e1; - } - return rv; - } diff --git a/libraries/gdtoa/strtoIx.c b/libraries/gdtoa/strtoIx.c deleted file mode 100644 index 783a631f06..0000000000 --- a/libraries/gdtoa/strtoIx.c +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtoIx(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; -#else -strtoIx(CONST char *s, char **sp, void *a, void *b) -#endif -{ - static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - Long exp[2]; - Bigint *B[2]; - int k, rv[2]; - UShort *L = (UShort *)a, *M = (UShort *)b; - - B[0] = Balloc(1); - B[0]->wds = 2; - k = strtoIg(s, sp, &fpi, exp, B, rv); - ULtox(L, B[0]->x, exp[0], rv[0]); - Bfree(B[0]); - if (B[1]) { - ULtox(M, B[1]->x, exp[1], rv[1]); - Bfree(B[1]); - } - else { - M[0] = L[0]; - M[1] = L[1]; - M[2] = L[2]; - M[3] = L[3]; - M[4] = L[4]; - } - return k; - } diff --git a/libraries/gdtoa/strtoIxL.c b/libraries/gdtoa/strtoIxL.c deleted file mode 100644 index 869bfd16fb..0000000000 --- a/libraries/gdtoa/strtoIxL.c +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtoIxL(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; -#else -strtoIxL(CONST char *s, char **sp, void *a, void *b) -#endif -{ - static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - Long exp[2]; - Bigint *B[2]; - int k, rv[2]; - ULong *L = (ULong *)a, *M = (ULong *)b; - - B[0] = Balloc(1); - B[0]->wds = 2; - k = strtoIg(s, sp, &fpi, exp, B, rv); - ULtoxL(L, B[0]->x, exp[0], rv[0]); - Bfree(B[0]); - if (B[1]) { - ULtoxL(M, B[1]->x, exp[1], rv[1]); - Bfree(B[1]); - } - else { - M[0] = L[0]; - M[1] = L[1]; - M[2] = L[2]; - } - return k; - } diff --git a/libraries/gdtoa/strtod.c b/libraries/gdtoa/strtod.c deleted file mode 100644 index 3c22300537..0000000000 --- a/libraries/gdtoa/strtod.c +++ /dev/null @@ -1,1074 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998-2001 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" -#if !defined(NO_FENV_H) && !defined(_MSC_VER) -#include -#endif - -#ifdef USE_LOCALE -#include "locale.h" -#endif - -#ifdef IEEE_Arith -#ifndef NO_IEEE_Scale -#define Avoid_Underflow -#undef tinytens -/* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */ -/* flag unnecessarily. It leads to a song and dance at the end of strtod. */ -static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, - 9007199254740992.*9007199254740992.e-256 - }; -#endif -#endif - -#ifdef Honor_FLT_ROUNDS -#undef Check_FLT_ROUNDS -#define Check_FLT_ROUNDS -#else -#define Rounding Flt_Rounds -#endif - -#ifdef Avoid_Underflow /*{*/ - static double -sulp -#ifdef KR_headers - (x, scale) U *x; int scale; -#else - (U *x, int scale) -#endif -{ - U u; - double rv; - int i; - - rv = ulp(x); - if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0) - return rv; /* Is there an example where i <= 0 ? */ - word0(&u) = Exp_1 + (i << Exp_shift); - word1(&u) = 0; - return rv * u.d; - } -#endif /*}*/ - - double -strtod -#ifdef KR_headers - (s00, se) CONST char *s00; char **se; -#else - (CONST char *s00, char **se) -#endif -{ -#ifdef Avoid_Underflow - int scale; -#endif - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign, - e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; - CONST char *s, *s0, *s1; - double aadj; - Long L; - U adj, aadj1, rv, rv0; - ULong y, z; - Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; -#ifdef Avoid_Underflow - ULong Lsb, Lsb1; -#endif -#ifdef SET_INEXACT - int inexact, oldinexact; -#endif -#ifdef USE_LOCALE /*{{*/ -#ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; - int dplen = strlen(decimalpoint); -#else - char *decimalpoint; - static char *decimalpoint_cache; - static int dplen; - if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; - if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { - strcpy(decimalpoint_cache, s0); - s0 = decimalpoint_cache; - } - dplen = strlen(s0); - } - decimalpoint = (char*)s0; -#endif /*NO_LOCALE_CACHE*/ -#else /*USE_LOCALE}{*/ -#define dplen 1 -#endif /*USE_LOCALE}}*/ - -#ifdef Honor_FLT_ROUNDS /*{*/ - int Rounding; -#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ - Rounding = Flt_Rounds; -#else /*}{*/ - Rounding = 1; - switch(fegetround()) { - case FE_TOWARDZERO: Rounding = 0; break; - case FE_UPWARD: Rounding = 2; break; - case FE_DOWNWARD: Rounding = 3; - } -#endif /*}}*/ -#endif /*}*/ - - sign = nz0 = nz = decpt = 0; - dval(&rv) = 0.; - for(s = s00;;s++) switch(*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - goto ret0; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - default: - goto break2; - } - break2: - if (*s == '0') { -#ifndef NO_HEX_FP /*{*/ - { - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - Long exp; - ULong bits[2]; - switch(s[1]) { - case 'x': - case 'X': - { -#ifdef Honor_FLT_ROUNDS - FPI fpi1 = fpi; - fpi1.rounding = Rounding; -#else -#define fpi1 fpi -#endif - switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) { - case STRTOG_NoNumber: - s = s00; - sign = 0; - case STRTOG_Zero: - break; - default: - if (bb) { - copybits(bits, fpi.nbits, bb); - Bfree(bb); - } - ULtod(((U*)&rv)->L, bits, exp, i); - }} - goto ret; - } - } -#endif /*}*/ - nz0 = 1; - while(*++s == '0') ; - if (!*s) - goto ret; - } - s0 = s; - y = z = 0; - for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = 10*y + c - '0'; - else if (nd < 16) - z = 10*z + c - '0'; - nd0 = nd; -#ifdef USE_LOCALE - if (c == *decimalpoint) { - for(i = 1; decimalpoint[i]; ++i) - if (s[i] != decimalpoint[i]) - goto dig_done; - s += i; - c = *s; -#else - if (c == '.') { - c = *++s; -#endif - decpt = 1; - if (!nd) { - for(; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto have_dig; - } - goto dig_done; - } - for(; c >= '0' && c <= '9'; c = *++s) { - have_dig: - nz++; - if (c -= '0') { - nf += nz; - for(i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 1) - z *= 10; - if (nd++ < 9) - y = 10*y + c; - else if (nd <= DBL_DIG + 1) - z = 10*z + c; - nz = 0; - } - } - }/*}*/ - dig_done: - e = 0; - if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) { - goto ret0; - } - s00 = s; - esign = 0; - switch(c = *++s) { - case '-': - esign = 1; - case '+': - c = *++s; - } - if (c >= '0' && c <= '9') { - while(c == '0') - c = *++s; - if (c > '0' && c <= '9') { - L = c - '0'; - s1 = s; - while((c = *++s) >= '0' && c <= '9') - L = 10*L + c - '0'; - if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = 19999; /* safe for 16 bit ints */ - else - e = (int)L; - if (esign) - e = -e; - } - else - e = 0; - } - else - s = s00; - } - if (!nd) { - if (!nz && !nz0) { -#ifdef INFNAN_CHECK - /* Check for Nan and Infinity */ - ULong bits[2]; - static FPI fpinan = /* only 52 explicit bits */ - { 52, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - if (!decpt) - switch(c) { - case 'i': - case 'I': - if (match(&s,"nf")) { - --s; - if (!match(&s,"inity")) - ++s; - word0(&rv) = 0x7ff00000; - word1(&rv) = 0; - goto ret; - } - break; - case 'n': - case 'N': - if (match(&s, "an")) { -#ifndef No_Hex_NaN - if (*s == '(' /*)*/ - && hexnan(&s, &fpinan, bits) - == STRTOG_NaNbits) { - word0(&rv) = 0x7ff00000 | bits[1]; - word1(&rv) = bits[0]; - } - else { -#endif - word0(&rv) = NAN_WORD0; - word1(&rv) = NAN_WORD1; -#ifndef No_Hex_NaN - } -#endif - goto ret; - } - } -#endif /* INFNAN_CHECK */ - ret0: - s = s00; - sign = 0; - } - goto ret; - } - e1 = e -= nf; - - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - if (!nd0) - nd0 = nd; - k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(&rv) = y; - if (k > 9) { -#ifdef SET_INEXACT - if (k > DBL_DIG) - oldinexact = get_inexact(); -#endif - dval(&rv) = tens[k - 9] * dval(&rv) + z; - } - bd0 = 0; - if (nd <= DBL_DIG -#ifndef RND_PRODQUOT -#ifndef Honor_FLT_ROUNDS - && Flt_Rounds == 1 -#endif -#endif - ) { - if (!e) - goto ret; -#ifndef ROUND_BIASED_without_Round_Up - if (e > 0) { - if (e <= Ten_pmax) { -#ifdef VAX - goto vax_ovfl_check; -#else -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - rv.d = -rv.d; - sign = 0; - } -#endif - /* rv = */ rounded_product(dval(&rv), tens[e]); - goto ret; -#endif - } - i = DBL_DIG - nd; - if (e <= Ten_pmax + i) { - /* A fancier test would sometimes let us do - * this for larger i values. - */ -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - rv.d = -rv.d; - sign = 0; - } -#endif - e -= i; - dval(&rv) *= tens[i]; -#ifdef VAX - /* VAX exponent range is so narrow we must - * worry about overflow here... - */ - vax_ovfl_check: - word0(&rv) -= P*Exp_msk1; - /* rv = */ rounded_product(dval(&rv), tens[e]); - if ((word0(&rv) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) - goto ovfl; - word0(&rv) += P*Exp_msk1; -#else - /* rv = */ rounded_product(dval(&rv), tens[e]); -#endif - goto ret; - } - } -#ifndef Inaccurate_Divide - else if (e >= -Ten_pmax) { -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - rv.d = -rv.d; - sign = 0; - } -#endif - /* rv = */ rounded_quotient(dval(&rv), tens[-e]); - goto ret; - } -#endif -#endif /* ROUND_BIASED_without_Round_Up */ - } - e1 += nd - k; - -#ifdef IEEE_Arith -#ifdef SET_INEXACT - inexact = 1; - if (k <= DBL_DIG) - oldinexact = get_inexact(); -#endif -#ifdef Avoid_Underflow - scale = 0; -#endif -#ifdef Honor_FLT_ROUNDS - if (Rounding >= 2) { - if (sign) - Rounding = Rounding == 2 ? 0 : 2; - else - if (Rounding != 2) - Rounding = 0; - } -#endif -#endif /*IEEE_Arith*/ - - /* Get starting approximation = rv * 10**e1 */ - - if (e1 > 0) { - if ( (i = e1 & 15) !=0) - dval(&rv) *= tens[i]; - if (e1 &= ~15) { - if (e1 > DBL_MAX_10_EXP) { - ovfl: - /* Can't trust HUGE_VAL */ -#ifdef IEEE_Arith -#ifdef Honor_FLT_ROUNDS - switch(Rounding) { - case 0: /* toward 0 */ - case 3: /* toward -infinity */ - word0(&rv) = Big0; - word1(&rv) = Big1; - break; - default: - word0(&rv) = Exp_mask; - word1(&rv) = 0; - } -#else /*Honor_FLT_ROUNDS*/ - word0(&rv) = Exp_mask; - word1(&rv) = 0; -#endif /*Honor_FLT_ROUNDS*/ -#ifdef SET_INEXACT - /* set overflow bit */ - dval(&rv0) = 1e300; - dval(&rv0) *= dval(&rv0); -#endif -#else /*IEEE_Arith*/ - word0(&rv) = Big0; - word1(&rv) = Big1; -#endif /*IEEE_Arith*/ - range_err: - if (bd0) { - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); - } -#ifndef NO_ERRNO - errno = ERANGE; -#endif - goto ret; - } - e1 >>= 4; - for(j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= bigtens[j]; - /* The last multiplication could overflow. */ - word0(&rv) -= P*Exp_msk1; - dval(&rv) *= bigtens[j]; - if ((z = word0(&rv) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-P)) - goto ovfl; - if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { - /* set to largest number */ - /* (Can't trust DBL_MAX) */ - word0(&rv) = Big0; - word1(&rv) = Big1; - } - else - word0(&rv) += P*Exp_msk1; - } - } - else if (e1 < 0) { - e1 = -e1; - if ( (i = e1 & 15) !=0) - dval(&rv) /= tens[i]; - if (e1 >>= 4) { - if (e1 >= 1 << n_bigtens) - goto undfl; -#ifdef Avoid_Underflow - if (e1 & Scale_Bit) - scale = 2*P; - for(j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= tinytens[j]; - if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask) - >> Exp_shift)) > 0) { - /* scaled rv is denormal; zap j low bits */ - if (j >= 32) { - word1(&rv) = 0; - if (j >= 53) - word0(&rv) = (P+2)*Exp_msk1; - else - word0(&rv) &= 0xffffffff << (j-32); - } - else - word1(&rv) &= 0xffffffff << j; - } -#else - for(j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= tinytens[j]; - /* The last multiplication could underflow. */ - dval(&rv0) = dval(&rv); - dval(&rv) *= tinytens[j]; - if (!dval(&rv)) { - dval(&rv) = 2.*dval(&rv0); - dval(&rv) *= tinytens[j]; -#endif - if (!dval(&rv)) { - undfl: - dval(&rv) = 0.; - goto range_err; - } -#ifndef Avoid_Underflow - word0(&rv) = Tiny0; - word1(&rv) = Tiny1; - /* The refinement below will clean - * this approximation up. - */ - } -#endif - } - } - - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - - bd0 = s2b(s0, nd0, nd, y, dplen); - - for(;;) { - bd = Balloc(bd0->k); - Bcopy(bd, bd0); - bb = d2b(dval(&rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ - bs = i2b(1); - - if (e >= 0) { - bb2 = bb5 = 0; - bd2 = bd5 = e; - } - else { - bb2 = bb5 = -e; - bd2 = bd5 = 0; - } - if (bbe >= 0) - bb2 += bbe; - else - bd2 -= bbe; - bs2 = bb2; -#ifdef Honor_FLT_ROUNDS - if (Rounding != 1) - bs2++; -#endif -#ifdef Avoid_Underflow - Lsb = LSB; - Lsb1 = 0; - j = bbe - scale; - i = j + bbbits - 1; /* logb(rv) */ - j = P + 1 - bbbits; - if (i < Emin) { /* denormal */ - i = Emin - i; - j -= i; - if (i < 32) - Lsb <<= i; - else - Lsb1 = Lsb << (i-32); - } -#else /*Avoid_Underflow*/ -#ifdef Sudden_Underflow -#ifdef IBM - j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); -#else - j = P + 1 - bbbits; -#endif -#else /*Sudden_Underflow*/ - j = bbe; - i = j + bbbits - 1; /* logb(&rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - bb2 += j; - bd2 += j; -#ifdef Avoid_Underflow - bd2 += scale; -#endif - i = bb2 < bd2 ? bb2 : bd2; - if (i > bs2) - i = bs2; - if (i > 0) { - bb2 -= i; - bd2 -= i; - bs2 -= i; - } - if (bb5 > 0) { - bs = pow5mult(bs, bb5); - bb1 = mult(bs, bb); - Bfree(bb); - bb = bb1; - } - if (bb2 > 0) - bb = lshift(bb, bb2); - if (bd5 > 0) - bd = pow5mult(bd, bd5); - if (bd2 > 0) - bd = lshift(bd, bd2); - if (bs2 > 0) - bs = lshift(bs, bs2); - delta = diff(bb, bd); - dsign = delta->sign; - delta->sign = 0; - i = cmp(delta, bs); -#ifdef Honor_FLT_ROUNDS - if (Rounding != 1) { - if (i < 0) { - /* Error is less than an ulp */ - if (!delta->x[0] && delta->wds <= 1) { - /* exact */ -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - if (Rounding) { - if (dsign) { - dval(&adj) = 1.; - goto apply_adj; - } - } - else if (!dsign) { - dval(&adj) = -1.; - if (!word1(&rv) - && !(word0(&rv) & Frac_mask)) { - y = word0(&rv) & Exp_mask; -#ifdef Avoid_Underflow - if (!scale || y > 2*P*Exp_msk1) -#else - if (y) -#endif - { - delta = lshift(delta,Log2P); - if (cmp(delta, bs) <= 0) - dval(&adj) = -0.5; - } - } - apply_adj: -#ifdef Avoid_Underflow - if (scale && (y = word0(&rv) & Exp_mask) - <= 2*P*Exp_msk1) - word0(&adj) += (2*P+1)*Exp_msk1 - y; -#else -#ifdef Sudden_Underflow - if ((word0(&rv) & Exp_mask) <= - P*Exp_msk1) { - word0(&rv) += P*Exp_msk1; - dval(&rv) += adj*ulp(&rv); - word0(&rv) -= P*Exp_msk1; - } - else -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - dval(&rv) += adj.d*ulp(&rv); - } - break; - } - dval(&adj) = ratio(delta, bs); - if (adj.d < 1.) - dval(&adj) = 1.; - if (adj.d <= 0x7ffffffe) { - /* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */ - y = adj.d; - if (y != adj.d) { - if (!((Rounding>>1) ^ dsign)) - y++; - dval(&adj) = y; - } - } -#ifdef Avoid_Underflow - if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) - word0(&adj) += (2*P+1)*Exp_msk1 - y; -#else -#ifdef Sudden_Underflow - if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { - word0(&rv) += P*Exp_msk1; - dval(&adj) *= ulp(&rv); - if (dsign) - dval(&rv) += adj; - else - dval(&rv) -= adj; - word0(&rv) -= P*Exp_msk1; - goto cont; - } -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - dval(&adj) *= ulp(&rv); - if (dsign) { - if (word0(&rv) == Big0 && word1(&rv) == Big1) - goto ovfl; - dval(&rv) += adj.d; - } - else - dval(&rv) -= adj.d; - goto cont; - } -#endif /*Honor_FLT_ROUNDS*/ - - if (i < 0) { - /* Error is less than half an ulp -- check for - * special case of mantissa a power of two. - */ - if (dsign || word1(&rv) || word0(&rv) & Bndry_mask -#ifdef IEEE_Arith -#ifdef Avoid_Underflow - || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 -#else - || (word0(&rv) & Exp_mask) <= Exp_msk1 -#endif -#endif - ) { -#ifdef SET_INEXACT - if (!delta->x[0] && delta->wds <= 1) - inexact = 0; -#endif - break; - } - if (!delta->x[0] && delta->wds <= 1) { - /* exact result */ -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - delta = lshift(delta,Log2P); - if (cmp(delta, bs) > 0) - goto drop_down; - break; - } - if (i == 0) { - /* exactly half-way between */ - if (dsign) { - if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 - && word1(&rv) == ( -#ifdef Avoid_Underflow - (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) - ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : -#endif - 0xffffffff)) { - /*boundary case -- increment exponent*/ - if (word0(&rv) == Big0 && word1(&rv) == Big1) - goto ovfl; - word0(&rv) = (word0(&rv) & Exp_mask) - + Exp_msk1 -#ifdef IBM - | Exp_msk1 >> 4 -#endif - ; - word1(&rv) = 0; -#ifdef Avoid_Underflow - dsign = 0; -#endif - break; - } - } - else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { - drop_down: - /* boundary case -- decrement exponent */ -#ifdef Sudden_Underflow /*{{*/ - L = word0(&rv) & Exp_mask; -#ifdef IBM - if (L < Exp_msk1) -#else -#ifdef Avoid_Underflow - if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1)) -#else - if (L <= Exp_msk1) -#endif /*Avoid_Underflow*/ -#endif /*IBM*/ - goto undfl; - L -= Exp_msk1; -#else /*Sudden_Underflow}{*/ -#ifdef Avoid_Underflow - if (scale) { - L = word0(&rv) & Exp_mask; - if (L <= (2*P+1)*Exp_msk1) { - if (L > (P+2)*Exp_msk1) - /* round even ==> */ - /* accept rv */ - break; - /* rv = smallest denormal */ - goto undfl; - } - } -#endif /*Avoid_Underflow*/ - L = (word0(&rv) & Exp_mask) - Exp_msk1; -#endif /*Sudden_Underflow}}*/ - word0(&rv) = L | Bndry_mask1; - word1(&rv) = 0xffffffff; -#ifdef IBM - goto cont; -#else - break; -#endif - } -#ifndef ROUND_BIASED -#ifdef Avoid_Underflow - if (Lsb1) { - if (!(word0(&rv) & Lsb1)) - break; - } - else if (!(word1(&rv) & Lsb)) - break; -#else - if (!(word1(&rv) & LSB)) - break; -#endif -#endif - if (dsign) -#ifdef Avoid_Underflow - dval(&rv) += sulp(&rv, scale); -#else - dval(&rv) += ulp(&rv); -#endif -#ifndef ROUND_BIASED - else { -#ifdef Avoid_Underflow - dval(&rv) -= sulp(&rv, scale); -#else - dval(&rv) -= ulp(&rv); -#endif -#ifndef Sudden_Underflow - if (!dval(&rv)) - goto undfl; -#endif - } -#ifdef Avoid_Underflow - dsign = 1 - dsign; -#endif -#endif - break; - } - if ((aadj = ratio(delta, bs)) <= 2.) { - if (dsign) - aadj = dval(&aadj1) = 1.; - else if (word1(&rv) || word0(&rv) & Bndry_mask) { -#ifndef Sudden_Underflow - if (word1(&rv) == Tiny1 && !word0(&rv)) - goto undfl; -#endif - aadj = 1.; - dval(&aadj1) = -1.; - } - else { - /* special case -- power of FLT_RADIX to be */ - /* rounded down... */ - - if (aadj < 2./FLT_RADIX) - aadj = 1./FLT_RADIX; - else - aadj *= 0.5; - dval(&aadj1) = -aadj; - } - } - else { - aadj *= 0.5; - dval(&aadj1) = dsign ? aadj : -aadj; -#ifdef Check_FLT_ROUNDS - switch(Rounding) { - case 2: /* towards +infinity */ - dval(&aadj1) -= 0.5; - break; - case 0: /* towards 0 */ - case 3: /* towards -infinity */ - dval(&aadj1) += 0.5; - } -#else - if (Flt_Rounds == 0) - dval(&aadj1) += 0.5; -#endif /*Check_FLT_ROUNDS*/ - } - y = word0(&rv) & Exp_mask; - - /* Check for overflow */ - - if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { - dval(&rv0) = dval(&rv); - word0(&rv) -= P*Exp_msk1; - dval(&adj) = dval(&aadj1) * ulp(&rv); - dval(&rv) += dval(&adj); - if ((word0(&rv) & Exp_mask) >= - Exp_msk1*(DBL_MAX_EXP+Bias-P)) { - if (word0(&rv0) == Big0 && word1(&rv0) == Big1) - goto ovfl; - word0(&rv) = Big0; - word1(&rv) = Big1; - goto cont; - } - else - word0(&rv) += P*Exp_msk1; - } - else { -#ifdef Avoid_Underflow - if (scale && y <= 2*P*Exp_msk1) { - if (aadj <= 0x7fffffff) { - if ((z = (ULong)aadj) <= 0) - z = 1; - aadj = z; - dval(&aadj1) = dsign ? aadj : -aadj; - } - word0(&aadj1) += (2*P+1)*Exp_msk1 - y; - } - dval(&adj) = dval(&aadj1) * ulp(&rv); - dval(&rv) += dval(&adj); -#else -#ifdef Sudden_Underflow - if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { - dval(&rv0) = dval(&rv); - word0(&rv) += P*Exp_msk1; - dval(&adj) = dval(&aadj1) * ulp(&rv); - dval(&rv) += adj; -#ifdef IBM - if ((word0(&rv) & Exp_mask) < P*Exp_msk1) -#else - if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) -#endif - { - if (word0(&rv0) == Tiny0 - && word1(&rv0) == Tiny1) - goto undfl; - word0(&rv) = Tiny0; - word1(&rv) = Tiny1; - goto cont; - } - else - word0(&rv) -= P*Exp_msk1; - } - else { - dval(&adj) = dval(&aadj1) * ulp(&rv); - dval(&rv) += adj; - } -#else /*Sudden_Underflow*/ - /* Compute dval(&adj) so that the IEEE rounding rules will - * correctly round rv + dval(&adj) in some half-way cases. - * If rv * ulp(&rv) is denormalized (i.e., - * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid - * trouble from bits lost to denormalization; - * example: 1.2e-307 . - */ - if (y <= (P-1)*Exp_msk1 && aadj > 1.) { - dval(&aadj1) = (double)(int)(aadj + 0.5); - if (!dsign) - dval(&aadj1) = -dval(&aadj1); - } - dval(&adj) = dval(&aadj1) * ulp(&rv); - dval(&rv) += adj; -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - } - z = word0(&rv) & Exp_mask; -#ifndef SET_INEXACT -#ifdef Avoid_Underflow - if (!scale) -#endif - if (y == z) { - /* Can we stop now? */ - L = (Long)aadj; - aadj -= L; - /* The tolerances below are conservative. */ - if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { - if (aadj < .4999999 || aadj > .5000001) - break; - } - else if (aadj < .4999999/FLT_RADIX) - break; - } -#endif - cont: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); - } - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); -#ifdef SET_INEXACT - if (inexact) { - if (!oldinexact) { - word0(&rv0) = Exp_1 + (70 << Exp_shift); - word1(&rv0) = 0; - dval(&rv0) += 1.; - } - } - else if (!oldinexact) - clear_inexact(); -#endif -#ifdef Avoid_Underflow - if (scale) { - word0(&rv0) = Exp_1 - 2*P*Exp_msk1; - word1(&rv0) = 0; - dval(&rv) *= dval(&rv0); -#ifndef NO_ERRNO - /* try to avoid the bug of testing an 8087 register value */ -#ifdef IEEE_Arith - if (!(word0(&rv) & Exp_mask)) -#else - if (word0(&rv) == 0 && word1(&rv) == 0) -#endif - errno = ERANGE; -#endif - } -#endif /* Avoid_Underflow */ -#ifdef SET_INEXACT - if (inexact && !(word0(&rv) & Exp_mask)) { - /* set underflow bit */ - dval(&rv0) = 1e-300; - dval(&rv0) *= dval(&rv0); - } -#endif - ret: - if (se) - *se = (char *)s; - return sign ? -dval(&rv) : dval(&rv); - } - diff --git a/libraries/gdtoa/strtodI.c b/libraries/gdtoa/strtodI.c deleted file mode 100644 index 0b7b8a45c0..0000000000 --- a/libraries/gdtoa/strtodI.c +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - static double -#ifdef KR_headers -ulpdown(d) U *d; -#else -ulpdown(U *d) -#endif -{ - double u; - ULong *L = d->L; - - u = ulp(d); - if (!(L[_1] | (L[_0] & 0xfffff)) - && (L[_0] & 0x7ff00000) > 0x00100000) - u *= 0.5; - return u; - } - - int -#ifdef KR_headers -strtodI(s, sp, dd) CONST char *s; char **sp; double *dd; -#else -strtodI(CONST char *s, char **sp, double *dd) -#endif -{ - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - ULong bits[2], sign; - Long exp; - int j, k; - U *u; - - k = strtodg(s, sp, &fpi, &exp, bits); - u = (U*)dd; - sign = k & STRTOG_Neg ? 0x80000000L : 0; - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - dval(&u[0]) = dval(&u[1]) = 0.; - break; - - case STRTOG_Zero: - dval(&u[0]) = dval(&u[1]) = 0.; -#ifdef Sudden_Underflow - if (k & STRTOG_Inexact) { - if (sign) - word0(&u[0]) = 0x80100000L; - else - word0(&u[1]) = 0x100000L; - } - break; -#else - goto contain; -#endif - - case STRTOG_Denormal: - word1(&u[0]) = bits[0]; - word0(&u[0]) = bits[1]; - goto contain; - - case STRTOG_Normal: - word1(&u[0]) = bits[0]; - word0(&u[0]) = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20); - contain: - j = k & STRTOG_Inexact; - if (sign) { - word0(&u[0]) |= sign; - j = STRTOG_Inexact - j; - } - switch(j) { - case STRTOG_Inexlo: -#ifdef Sudden_Underflow - if ((u->L[_0] & 0x7ff00000) < 0x3500000) { - word0(&u[1]) = word0(&u[0]) + 0x3500000; - word1(&u[1]) = word1(&u[0]); - dval(&u[1]) += ulp(&u[1]); - word0(&u[1]) -= 0x3500000; - if (!(word0(&u[1]) & 0x7ff00000)) { - word0(&u[1]) = sign; - word1(&u[1]) = 0; - } - } - else -#endif - dval(&u[1]) = dval(&u[0]) + ulp(&u[0]); - break; - case STRTOG_Inexhi: - dval(&u[1]) = dval(&u[0]); -#ifdef Sudden_Underflow - if ((word0(&u[0]) & 0x7ff00000) < 0x3500000) { - word0(&u[0]) += 0x3500000; - dval(&u[0]) -= ulpdown(u); - word0(&u[0]) -= 0x3500000; - if (!(word0(&u[0]) & 0x7ff00000)) { - word0(&u[0]) = sign; - word1(&u[0]) = 0; - } - } - else -#endif - dval(&u[0]) -= ulpdown(u); - break; - default: - dval(&u[1]) = dval(&u[0]); - } - break; - - case STRTOG_Infinite: - word0(&u[0]) = word0(&u[1]) = sign | 0x7ff00000; - word1(&u[0]) = word1(&u[1]) = 0; - if (k & STRTOG_Inexact) { - if (sign) { - word0(&u[1]) = 0xffefffffL; - word1(&u[1]) = 0xffffffffL; - } - else { - word0(&u[0]) = 0x7fefffffL; - word1(&u[0]) = 0xffffffffL; - } - } - break; - - case STRTOG_NaN: - u->L[0] = (u+1)->L[0] = d_QNAN0; - u->L[1] = (u+1)->L[1] = d_QNAN1; - break; - - case STRTOG_NaNbits: - word0(&u[0]) = word0(&u[1]) = 0x7ff00000 | sign | bits[1]; - word1(&u[0]) = word1(&u[1]) = bits[0]; - } - return k; - } diff --git a/libraries/gdtoa/strtodg.c b/libraries/gdtoa/strtodg.c deleted file mode 100644 index c2e3365c78..0000000000 --- a/libraries/gdtoa/strtodg.c +++ /dev/null @@ -1,1065 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998-2001 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#ifdef USE_LOCALE -#include "locale.h" -#endif - - static CONST int -fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21, - 24, 26, 28, 31, 33, 35, 38, 40, 42, 45, - 47, 49, 52 -#ifdef VAX - , 54, 56 -#endif - }; - - Bigint * -#ifdef KR_headers -increment(b) Bigint *b; -#else -increment(Bigint *b) -#endif -{ - ULong *x, *xe; - Bigint *b1; -#ifdef Pack_16 - ULong carry = 1, y; -#endif - - x = b->x; - xe = x + b->wds; -#ifdef Pack_32 - do { - if (*x < (ULong)0xffffffffL) { - ++*x; - return b; - } - *x++ = 0; - } while(x < xe); -#else - do { - y = *x + carry; - carry = y >> 16; - *x++ = y & 0xffff; - if (!carry) - return b; - } while(x < xe); - if (carry) -#endif - { - if (b->wds >= b->maxwds) { - b1 = Balloc(b->k+1); - Bcopy(b1,b); - Bfree(b); - b = b1; - } - b->x[b->wds++] = 1; - } - return b; - } - - void -#ifdef KR_headers -decrement(b) Bigint *b; -#else -decrement(Bigint *b) -#endif -{ - ULong *x, *xe; -#ifdef Pack_16 - ULong borrow = 1, y; -#endif - - x = b->x; - xe = x + b->wds; -#ifdef Pack_32 - do { - if (*x) { - --*x; - break; - } - *x++ = 0xffffffffL; - } - while(x < xe); -#else - do { - y = *x - borrow; - borrow = (y & 0x10000) >> 16; - *x++ = y & 0xffff; - } while(borrow && x < xe); -#endif - } - - static int -#ifdef KR_headers -all_on(b, n) Bigint *b; int n; -#else -all_on(Bigint *b, int n) -#endif -{ - ULong *x, *xe; - - x = b->x; - xe = x + (n >> kshift); - while(x < xe) - if ((*x++ & ALL_ON) != ALL_ON) - return 0; - if (n &= kmask) - return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON; - return 1; - } - - Bigint * -#ifdef KR_headers -set_ones(b, n) Bigint *b; int n; -#else -set_ones(Bigint *b, int n) -#endif -{ - int k; - ULong *x, *xe; - - k = (n + ((1 << kshift) - 1)) >> kshift; - if (b->k < k) { - Bfree(b); - b = Balloc(k); - } - k = n >> kshift; - if (n &= kmask) - k++; - b->wds = k; - x = b->x; - xe = x + k; - while(x < xe) - *x++ = ALL_ON; - if (n) - x[-1] >>= ULbits - n; - return b; - } - - static int -rvOK -#ifdef KR_headers - (d, fpi, exp, bits, exact, rd, irv) - U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv; -#else - (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv) -#endif -{ - Bigint *b; - ULong carry, inex, lostbits; - int bdif, e, j, k, k1, nb, rv; - - carry = rv = 0; - b = d2b(dval(d), &e, &bdif); - bdif -= nb = fpi->nbits; - e += bdif; - if (bdif <= 0) { - if (exact) - goto trunc; - goto ret; - } - if (P == nb) { - if ( -#ifndef IMPRECISE_INEXACT - exact && -#endif - fpi->rounding == -#ifdef RND_PRODQUOT - FPI_Round_near -#else - Flt_Rounds -#endif - ) goto trunc; - goto ret; - } - switch(rd) { - case 1: /* round down (toward -Infinity) */ - goto trunc; - case 2: /* round up (toward +Infinity) */ - break; - default: /* round near */ - k = bdif - 1; - if (k < 0) - goto trunc; - if (!k) { - if (!exact) - goto ret; - if (b->x[0] & 2) - break; - goto trunc; - } - if (b->x[k>>kshift] & ((ULong)1 << (k & kmask))) - break; - goto trunc; - } - /* "break" cases: round up 1 bit, then truncate; bdif > 0 */ - carry = 1; - trunc: - inex = lostbits = 0; - if (bdif > 0) { - if ( (lostbits = any_on(b, bdif)) !=0) - inex = STRTOG_Inexlo; - rshift(b, bdif); - if (carry) { - inex = STRTOG_Inexhi; - b = increment(b); - if ( (j = nb & kmask) !=0) - j = ULbits - j; - if (hi0bits(b->x[b->wds - 1]) != j) { - if (!lostbits) - lostbits = b->x[0] & 1; - rshift(b, 1); - e++; - } - } - } - else if (bdif < 0) - b = lshift(b, -bdif); - if (e < fpi->emin) { - k = fpi->emin - e; - e = fpi->emin; - if (k > nb || fpi->sudden_underflow) { - b->wds = inex = 0; - *irv = STRTOG_Underflow | STRTOG_Inexlo; - } - else { - k1 = k - 1; - if (k1 > 0 && !lostbits) - lostbits = any_on(b, k1); - if (!lostbits && !exact) - goto ret; - lostbits |= - carry = b->x[k1>>kshift] & (1 << (k1 & kmask)); - rshift(b, k); - *irv = STRTOG_Denormal; - if (carry) { - b = increment(b); - inex = STRTOG_Inexhi | STRTOG_Underflow; - } - else if (lostbits) - inex = STRTOG_Inexlo | STRTOG_Underflow; - } - } - else if (e > fpi->emax) { - e = fpi->emax + 1; - *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - b->wds = inex = 0; - } - *exp = e; - copybits(bits, nb, b); - *irv |= inex; - rv = 1; - ret: - Bfree(b); - return rv; - } - - static int -#ifdef KR_headers -mantbits(d) U *d; -#else -mantbits(U *d) -#endif -{ - ULong L; -#ifdef VAX - L = word1(d) << 16 | word1(d) >> 16; - if (L) -#else - if ( (L = word1(d)) !=0) -#endif - return P - lo0bits(&L); -#ifdef VAX - L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11; -#else - L = word0(d) | Exp_msk1; -#endif - return P - 32 - lo0bits(&L); - } - - int -strtodg -#ifdef KR_headers - (s00, se, fpi, exp, bits) - CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; -#else - (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) -#endif -{ - int abe, abits, asub; - int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm; - int dsign, e, e1, e2, emin, esign, finished, i, inex, irv; - int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign; - int sudden_underflow; - CONST char *s, *s0, *s1; - double adj0, tol; - Long L; - U adj, rv; - ULong *b, *be, y, z; - Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; -#ifdef USE_LOCALE /*{{*/ -#ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; - int dplen = strlen(decimalpoint); -#else - char *decimalpoint; - static char *decimalpoint_cache; - static int dplen; - if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; - if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { - strcpy(decimalpoint_cache, s0); - s0 = decimalpoint_cache; - } - dplen = strlen(s0); - } - decimalpoint = (char*)s0; -#endif /*NO_LOCALE_CACHE*/ -#else /*USE_LOCALE}{*/ -#define dplen 1 -#endif /*USE_LOCALE}}*/ - - irv = STRTOG_Zero; - denorm = sign = nz0 = nz = 0; - dval(&rv) = 0.; - rvb = 0; - nbits = fpi->nbits; - for(s = s00;;s++) switch(*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - sign = 0; - irv = STRTOG_NoNumber; - s = s00; - goto ret; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - default: - goto break2; - } - break2: - if (*s == '0') { -#ifndef NO_HEX_FP - switch(s[1]) { - case 'x': - case 'X': - irv = gethex(&s, fpi, exp, &rvb, sign); - if (irv == STRTOG_NoNumber) { - s = s00; - sign = 0; - } - goto ret; - } -#endif - nz0 = 1; - while(*++s == '0') ; - if (!*s) - goto ret; - } - sudden_underflow = fpi->sudden_underflow; - s0 = s; - y = z = 0; - for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = 10*y + c - '0'; - else if (nd < 16) - z = 10*z + c - '0'; - nd0 = nd; -#ifdef USE_LOCALE - if (c == *decimalpoint) { - for(i = 1; decimalpoint[i]; ++i) - if (s[i] != decimalpoint[i]) - goto dig_done; - s += i; - c = *s; -#else - if (c == '.') { - c = *++s; -#endif - decpt = 1; - if (!nd) { - for(; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto have_dig; - } - goto dig_done; - } - for(; c >= '0' && c <= '9'; c = *++s) { - have_dig: - nz++; - if (c -= '0') { - nf += nz; - for(i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 1) - z *= 10; - if (nd++ < 9) - y = 10*y + c; - else if (nd <= DBL_DIG + 1) - z = 10*z + c; - nz = 0; - } - } - }/*}*/ - dig_done: - e = 0; - if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) { - irv = STRTOG_NoNumber; - s = s00; - goto ret; - } - s00 = s; - esign = 0; - switch(c = *++s) { - case '-': - esign = 1; - case '+': - c = *++s; - } - if (c >= '0' && c <= '9') { - while(c == '0') - c = *++s; - if (c > '0' && c <= '9') { - L = c - '0'; - s1 = s; - while((c = *++s) >= '0' && c <= '9') - L = 10*L + c - '0'; - if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = 19999; /* safe for 16 bit ints */ - else - e = (int)L; - if (esign) - e = -e; - } - else - e = 0; - } - else - s = s00; - } - if (!nd) { - if (!nz && !nz0) { -#ifdef INFNAN_CHECK - /* Check for Nan and Infinity */ - if (!decpt) - switch(c) { - case 'i': - case 'I': - if (match(&s,"nf")) { - --s; - if (!match(&s,"inity")) - ++s; - irv = STRTOG_Infinite; - goto infnanexp; - } - break; - case 'n': - case 'N': - if (match(&s, "an")) { - irv = STRTOG_NaN; - *exp = fpi->emax + 1; -#ifndef No_Hex_NaN - if (*s == '(') /*)*/ - irv = hexnan(&s, fpi, bits); -#endif - goto infnanexp; - } - } -#endif /* INFNAN_CHECK */ - irv = STRTOG_NoNumber; - s = s00; - } - goto ret; - } - - irv = STRTOG_Normal; - e1 = e -= nf; - rd = 0; - switch(fpi->rounding & 3) { - case FPI_Round_up: - rd = 2 - sign; - break; - case FPI_Round_zero: - rd = 1; - break; - case FPI_Round_down: - rd = 1 + sign; - } - - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - if (!nd0) - nd0 = nd; - k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(&rv) = y; - if (k > 9) - dval(&rv) = tens[k - 9] * dval(&rv) + z; - bd0 = 0; - if (nbits <= P && nd <= DBL_DIG) { - if (!e) { - if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv)) - goto ret; - } - else if (e > 0) { - if (e <= Ten_pmax) { -#ifdef VAX - goto vax_ovfl_check; -#else - i = fivesbits[e] + mantbits(&rv) <= P; - /* rv = */ rounded_product(dval(&rv), tens[e]); - if (rvOK(&rv, fpi, exp, bits, i, rd, &irv)) - goto ret; - e1 -= e; - goto rv_notOK; -#endif - } - i = DBL_DIG - nd; - if (e <= Ten_pmax + i) { - /* A fancier test would sometimes let us do - * this for larger i values. - */ - e2 = e - i; - e1 -= i; - dval(&rv) *= tens[i]; -#ifdef VAX - /* VAX exponent range is so narrow we must - * worry about overflow here... - */ - vax_ovfl_check: - dval(&adj) = dval(&rv); - word0(&adj) -= P*Exp_msk1; - /* adj = */ rounded_product(dval(&adj), tens[e2]); - if ((word0(&adj) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) - goto rv_notOK; - word0(&adj) += P*Exp_msk1; - dval(&rv) = dval(&adj); -#else - /* rv = */ rounded_product(dval(&rv), tens[e2]); -#endif - if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) - goto ret; - e1 -= e2; - } - } -#ifndef Inaccurate_Divide - else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(dval(&rv), tens[-e]); - if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) - goto ret; - e1 -= e; - } -#endif - } - rv_notOK: - e1 += nd - k; - - /* Get starting approximation = rv * 10**e1 */ - - e2 = 0; - if (e1 > 0) { - if ( (i = e1 & 15) !=0) - dval(&rv) *= tens[i]; - if (e1 &= ~15) { - e1 >>= 4; - while(e1 >= (1 << (n_bigtens-1))) { - e2 += ((word0(&rv) & Exp_mask) - >> Exp_shift1) - Bias; - word0(&rv) &= ~Exp_mask; - word0(&rv) |= Bias << Exp_shift1; - dval(&rv) *= bigtens[n_bigtens-1]; - e1 -= 1 << (n_bigtens-1); - } - e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(&rv) &= ~Exp_mask; - word0(&rv) |= Bias << Exp_shift1; - for(j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= bigtens[j]; - } - } - else if (e1 < 0) { - e1 = -e1; - if ( (i = e1 & 15) !=0) - dval(&rv) /= tens[i]; - if (e1 &= ~15) { - e1 >>= 4; - while(e1 >= (1 << (n_bigtens-1))) { - e2 += ((word0(&rv) & Exp_mask) - >> Exp_shift1) - Bias; - word0(&rv) &= ~Exp_mask; - word0(&rv) |= Bias << Exp_shift1; - dval(&rv) *= tinytens[n_bigtens-1]; - e1 -= 1 << (n_bigtens-1); - } - e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(&rv) &= ~Exp_mask; - word0(&rv) |= Bias << Exp_shift1; - for(j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= tinytens[j]; - } - } -#ifdef IBM - /* e2 is a correction to the (base 2) exponent of the return - * value, reflecting adjustments above to avoid overflow in the - * native arithmetic. For native IBM (base 16) arithmetic, we - * must multiply e2 by 4 to change from base 16 to 2. - */ - e2 <<= 2; -#endif - rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */ - rve += e2; - if ((j = rvbits - nbits) > 0) { - rshift(rvb, j); - rvbits = nbits; - rve += j; - } - bb0 = 0; /* trailing zero bits in rvb */ - e2 = rve + rvbits - nbits; - if (e2 > fpi->emax + 1) - goto huge; - rve1 = rve + rvbits - nbits; - if (e2 < (emin = fpi->emin)) { - denorm = 1; - j = rve - emin; - if (j > 0) { - rvb = lshift(rvb, j); - rvbits += j; - } - else if (j < 0) { - rvbits += j; - if (rvbits <= 0) { - if (rvbits < -1) { - ufl: - rvb->wds = 0; - rvb->x[0] = 0; - *exp = emin; - irv = STRTOG_Underflow | STRTOG_Inexlo; - goto ret; - } - rvb->x[0] = rvb->wds = rvbits = 1; - } - else - rshift(rvb, -j); - } - rve = rve1 = emin; - if (sudden_underflow && e2 + 1 < emin) - goto ufl; - } - - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - - bd0 = s2b(s0, nd0, nd, y, dplen); - - for(;;) { - bd = Balloc(bd0->k); - Bcopy(bd, bd0); - bb = Balloc(rvb->k); - Bcopy(bb, rvb); - bbbits = rvbits - bb0; - bbe = rve + bb0; - bs = i2b(1); - - if (e >= 0) { - bb2 = bb5 = 0; - bd2 = bd5 = e; - } - else { - bb2 = bb5 = -e; - bd2 = bd5 = 0; - } - if (bbe >= 0) - bb2 += bbe; - else - bd2 -= bbe; - bs2 = bb2; - j = nbits + 1 - bbbits; - i = bbe + bbbits - nbits; - if (i < emin) /* denormal */ - j += i - emin; - bb2 += j; - bd2 += j; - i = bb2 < bd2 ? bb2 : bd2; - if (i > bs2) - i = bs2; - if (i > 0) { - bb2 -= i; - bd2 -= i; - bs2 -= i; - } - if (bb5 > 0) { - bs = pow5mult(bs, bb5); - bb1 = mult(bs, bb); - Bfree(bb); - bb = bb1; - } - bb2 -= bb0; - if (bb2 > 0) - bb = lshift(bb, bb2); - else if (bb2 < 0) - rshift(bb, -bb2); - if (bd5 > 0) - bd = pow5mult(bd, bd5); - if (bd2 > 0) - bd = lshift(bd, bd2); - if (bs2 > 0) - bs = lshift(bs, bs2); - asub = 1; - inex = STRTOG_Inexhi; - delta = diff(bb, bd); - if (delta->wds <= 1 && !delta->x[0]) - break; - dsign = delta->sign; - delta->sign = finished = 0; - L = 0; - i = cmp(delta, bs); - if (rd && i <= 0) { - irv = STRTOG_Normal; - if ( (finished = dsign ^ (rd&1)) !=0) { - if (dsign != 0) { - irv |= STRTOG_Inexhi; - goto adj1; - } - irv |= STRTOG_Inexlo; - if (rve1 == emin) - goto adj1; - for(i = 0, j = nbits; j >= ULbits; - i++, j -= ULbits) { - if (rvb->x[i] & ALL_ON) - goto adj1; - } - if (j > 1 && lo0bits(rvb->x + i) < j - 1) - goto adj1; - rve = rve1 - 1; - rvb = set_ones(rvb, rvbits = nbits); - break; - } - irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi; - break; - } - if (i < 0) { - /* Error is less than half an ulp -- check for - * special case of mantissa a power of two. - */ - irv = dsign - ? STRTOG_Normal | STRTOG_Inexlo - : STRTOG_Normal | STRTOG_Inexhi; - if (dsign || bbbits > 1 || denorm || rve1 == emin) - break; - delta = lshift(delta,1); - if (cmp(delta, bs) > 0) { - irv = STRTOG_Normal | STRTOG_Inexlo; - goto drop_down; - } - break; - } - if (i == 0) { - /* exactly half-way between */ - if (dsign) { - if (denorm && all_on(rvb, rvbits)) { - /*boundary case -- increment exponent*/ - rvb->wds = 1; - rvb->x[0] = 1; - rve = emin + nbits - (rvbits = 1); - irv = STRTOG_Normal | STRTOG_Inexhi; - denorm = 0; - break; - } - irv = STRTOG_Normal | STRTOG_Inexlo; - } - else if (bbbits == 1) { - irv = STRTOG_Normal; - drop_down: - /* boundary case -- decrement exponent */ - if (rve1 == emin) { - irv = STRTOG_Normal | STRTOG_Inexhi; - if (rvb->wds == 1 && rvb->x[0] == 1) - sudden_underflow = 1; - break; - } - rve -= nbits; - rvb = set_ones(rvb, rvbits = nbits); - break; - } - else - irv = STRTOG_Normal | STRTOG_Inexhi; - if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1)) - break; - if (dsign) { - rvb = increment(rvb); - j = kmask & (ULbits - (rvbits & kmask)); - if (hi0bits(rvb->x[rvb->wds - 1]) != j) - rvbits++; - irv = STRTOG_Normal | STRTOG_Inexhi; - } - else { - if (bbbits == 1) - goto undfl; - decrement(rvb); - irv = STRTOG_Normal | STRTOG_Inexlo; - } - break; - } - if ((dval(&adj) = ratio(delta, bs)) <= 2.) { - adj1: - inex = STRTOG_Inexlo; - if (dsign) { - asub = 0; - inex = STRTOG_Inexhi; - } - else if (denorm && bbbits <= 1) { - undfl: - rvb->wds = 0; - rve = emin; - irv = STRTOG_Underflow | STRTOG_Inexlo; - break; - } - adj0 = dval(&adj) = 1.; - } - else { - adj0 = dval(&adj) *= 0.5; - if (dsign) { - asub = 0; - inex = STRTOG_Inexlo; - } - if (dval(&adj) < 2147483647.) { - L = (Long)adj0; - adj0 -= L; - switch(rd) { - case 0: - if (adj0 >= .5) - goto inc_L; - break; - case 1: - if (asub && adj0 > 0.) - goto inc_L; - break; - case 2: - if (!asub && adj0 > 0.) { - inc_L: - L++; - inex = STRTOG_Inexact - inex; - } - } - dval(&adj) = L; - } - } - y = rve + rvbits; - - /* adj *= ulp(dval(&rv)); */ - /* if (asub) rv -= adj; else rv += adj; */ - - if (!denorm && rvbits < nbits) { - rvb = lshift(rvb, j = nbits - rvbits); - rve -= j; - rvbits = nbits; - } - ab = d2b(dval(&adj), &abe, &abits); - if (abe < 0) - rshift(ab, -abe); - else if (abe > 0) - ab = lshift(ab, abe); - rvb0 = rvb; - if (asub) { - /* rv -= adj; */ - j = hi0bits(rvb->x[rvb->wds-1]); - rvb = diff(rvb, ab); - k = rvb0->wds - 1; - if (denorm) - /* do nothing */; - else if (rvb->wds <= k - || hi0bits( rvb->x[k]) > - hi0bits(rvb0->x[k])) { - /* unlikely; can only have lost 1 high bit */ - if (rve1 == emin) { - --rvbits; - denorm = 1; - } - else { - rvb = lshift(rvb, 1); - --rve; - --rve1; - L = finished = 0; - } - } - } - else { - rvb = sum(rvb, ab); - k = rvb->wds - 1; - if (k >= rvb0->wds - || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) { - if (denorm) { - if (++rvbits == nbits) - denorm = 0; - } - else { - rshift(rvb, 1); - rve++; - rve1++; - L = 0; - } - } - } - Bfree(ab); - Bfree(rvb0); - if (finished) - break; - - z = rve + rvbits; - if (y == z && L) { - /* Can we stop now? */ - tol = dval(&adj) * 5e-16; /* > max rel error */ - dval(&adj) = adj0 - .5; - if (dval(&adj) < -tol) { - if (adj0 > tol) { - irv |= inex; - break; - } - } - else if (dval(&adj) > tol && adj0 < 1. - tol) { - irv |= inex; - break; - } - } - bb0 = denorm ? 0 : trailz(rvb); - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); - } - if (!denorm && (j = nbits - rvbits)) { - if (j > 0) - rvb = lshift(rvb, j); - else - rshift(rvb, -j); - rve -= j; - } - *exp = rve; - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); - if (rve > fpi->emax) { - switch(fpi->rounding & 3) { - case FPI_Round_near: - goto huge; - case FPI_Round_up: - if (!sign) - goto huge; - break; - case FPI_Round_down: - if (sign) - goto huge; - } - /* Round to largest representable magnitude */ - Bfree(rvb); - rvb = 0; - irv = STRTOG_Normal | STRTOG_Inexlo; - *exp = fpi->emax; - b = bits; - be = b + ((fpi->nbits + 31) >> 5); - while(b < be) - *b++ = -1; - if ((j = fpi->nbits & 0x1f)) - *--be >>= (32 - j); - goto ret; - huge: - rvb->wds = 0; - irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - infnanexp: - *exp = fpi->emax + 1; - } - ret: - if (denorm) { - if (sudden_underflow) { - rvb->wds = 0; - irv = STRTOG_Underflow | STRTOG_Inexlo; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - } - else { - irv = (irv & ~STRTOG_Retmask) | - (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero); - if (irv & STRTOG_Inexact) { - irv |= STRTOG_Underflow; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - } - } - } - if (se) - *se = (char *)s; - if (sign) - irv |= STRTOG_Neg; - if (rvb) { - copybits(bits, nbits, rvb); - Bfree(rvb); - } - return irv; - } diff --git a/libraries/gdtoa/strtodnrp.c b/libraries/gdtoa/strtodnrp.c deleted file mode 100644 index 19a769f0b4..0000000000 --- a/libraries/gdtoa/strtodnrp.c +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 2004 by David M. Gay. -All Rights Reserved -Based on material in the rest of /netlib/fp/gdota.tar.gz, -which is copyright (C) 1998, 2000 by Lucent Technologies. - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* This is a variant of strtod that works on Intel ia32 systems */ -/* with the default extended-precision arithmetic -- it does not */ -/* require setting the precision control to 53 bits. */ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - double -#ifdef KR_headers -strtod(s, sp) CONST char *s; char **sp; -#else -strtod(CONST char *s, char **sp) -#endif -{ - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - ULong bits[2]; - Long exp; - int k; - union { ULong L[2]; double d; } u; - - k = strtodg(s, sp, &fpi, &exp, bits); - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - u.L[0] = u.L[1] = 0; - break; - - case STRTOG_Normal: - u.L[_1] = bits[0]; - u.L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20); - break; - - case STRTOG_Denormal: - u.L[_1] = bits[0]; - u.L[_0] = bits[1]; - break; - - case STRTOG_Infinite: - u.L[_0] = 0x7ff00000; - u.L[_1] = 0; - break; - - case STRTOG_NaN: - u.L[0] = d_QNAN0; - u.L[1] = d_QNAN1; - break; - - case STRTOG_NaNbits: - u.L[_0] = 0x7ff00000 | bits[1]; - u.L[_1] = bits[0]; - } - if (k & STRTOG_Neg) - u.L[_0] |= 0x80000000L; - return u.d; - } diff --git a/libraries/gdtoa/strtof.c b/libraries/gdtoa/strtof.c deleted file mode 100644 index a8beb3520a..0000000000 --- a/libraries/gdtoa/strtof.c +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - float -#ifdef KR_headers -strtof(s, sp) CONST char *s; char **sp; -#else -strtof(CONST char *s, char **sp) -#endif -{ - static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; - ULong bits[1]; - Long exp; - int k; - union { ULong L[1]; float f; } u; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - k = strtodg(s, sp, fpi, &exp, bits); - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - u.L[0] = 0; - break; - - case STRTOG_Normal: - case STRTOG_NaNbits: - u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); - break; - - case STRTOG_Denormal: - u.L[0] = bits[0]; - break; - - case STRTOG_Infinite: - u.L[0] = 0x7f800000; - break; - - case STRTOG_NaN: - u.L[0] = f_QNAN; - } - if (k & STRTOG_Neg) - u.L[0] |= 0x80000000L; - return u.f; - } diff --git a/libraries/gdtoa/strtopQ.c b/libraries/gdtoa/strtopQ.c deleted file mode 100644 index 2acf7e9107..0000000000 --- a/libraries/gdtoa/strtopQ.c +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#define _3 3 -#endif -#ifdef IEEE_8087 -#define _0 3 -#define _1 2 -#define _2 1 -#define _3 0 -#endif - - extern ULong NanDflt_Q_D2A[4]; - - - int -#ifdef KR_headers -strtopQ(s, sp, V) CONST char *s; char **sp; void *V; -#else -strtopQ(CONST char *s, char **sp, void *V) -#endif -{ - static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; - ULong bits[4]; - Long exp; - int k; - ULong *L = (ULong*)V; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - k = strtodg(s, sp, fpi, &exp, bits); - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = L[1] = L[2] = L[3] = 0; - break; - - case STRTOG_Normal: - case STRTOG_NaNbits: - L[_3] = bits[0]; - L[_2] = bits[1]; - L[_1] = bits[2]; - L[_0] = (bits[3] & ~0x10000) | ((exp + 0x3fff + 112) << 16); - break; - - case STRTOG_Denormal: - L[_3] = bits[0]; - L[_2] = bits[1]; - L[_1] = bits[2]; - L[_0] = bits[3]; - break; - - case STRTOG_Infinite: - L[_0] = 0x7fff0000; - L[_1] = L[_2] = L[_3] = 0; - break; - - case STRTOG_NaN: - L[_0] = NanDflt_Q_D2A[3]; - L[_1] = NanDflt_Q_D2A[2]; - L[_2] = NanDflt_Q_D2A[1]; - L[_3] = NanDflt_Q_D2A[0]; - } - if (k & STRTOG_Neg) - L[_0] |= 0x80000000L; - return k; - } diff --git a/libraries/gdtoa/strtopd.c b/libraries/gdtoa/strtopd.c deleted file mode 100644 index 0fb35daeaa..0000000000 --- a/libraries/gdtoa/strtopd.c +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtopd(s, sp, d) char *s; char **sp; double *d; -#else -strtopd(CONST char *s, char **sp, double *d) -#endif -{ - static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - ULong bits[2]; - Long exp; - int k; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - k = strtodg(s, sp, fpi, &exp, bits); - ULtod((ULong*)d, bits, exp, k); - return k; - } diff --git a/libraries/gdtoa/strtopdd.c b/libraries/gdtoa/strtopdd.c deleted file mode 100644 index 738372d882..0000000000 --- a/libraries/gdtoa/strtopdd.c +++ /dev/null @@ -1,183 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtopdd(s, sp, dd) CONST char *s; char **sp; double *dd; -#else -strtopdd(CONST char *s, char **sp, double *dd) -#endif -{ -#ifdef Sudden_Underflow - static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; -#else - static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; -#endif - ULong bits[4]; - Long exp; - int i, j, rv; - typedef union { - double d[2]; - ULong L[4]; - } U; - U *u; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - rv = strtodg(s, sp, fpi, &exp, bits); - u = (U*)dd; - switch(rv & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - u->d[0] = u->d[1] = 0.; - break; - - case STRTOG_Normal: - u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL; - u->L[_0] = (bits[2] >> 21) | ((bits[3] << 11) & 0xfffff) - | ((exp + 0x3ff + 105) << 20); - exp += 0x3ff + 52; - if (bits[1] &= 0x1fffff) { - i = hi0bits(bits[1]) - 11; - if (i >= exp) { - i = exp - 1; - exp = 0; - } - else - exp -= i; - if (i > 0) { - bits[1] = bits[1] << i | bits[0] >> (32-i); - bits[0] = bits[0] << i & 0xffffffffL; - } - } - else if (bits[0]) { - i = hi0bits(bits[0]) + 21; - if (i >= exp) { - i = exp - 1; - exp = 0; - } - else - exp -= i; - if (i < 32) { - bits[1] = bits[0] >> (32 - i); - bits[0] = bits[0] << i & 0xffffffffL; - } - else { - bits[1] = bits[0] << (i - 32); - bits[0] = 0; - } - } - else { - u->L[2] = u->L[3] = 0; - break; - } - u->L[2+_1] = bits[0]; - u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20); - break; - - case STRTOG_Denormal: - if (bits[3]) - goto nearly_normal; - if (bits[2]) - goto partly_normal; - if (bits[1] & 0xffe00000) - goto hardly_normal; - /* completely denormal */ - u->L[2] = u->L[3] = 0; - u->L[_1] = bits[0]; - u->L[_0] = bits[1]; - break; - - nearly_normal: - i = hi0bits(bits[3]) - 11; /* i >= 12 */ - j = 32 - i; - u->L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff) - | ((65 - i) << 20); - u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - u->L[2+_0] = bits[1] & ((1L << j) - 1); - u->L[2+_1] = bits[0]; - break; - - partly_normal: - i = hi0bits(bits[2]) - 11; - if (i < 0) { - j = -i; - i += 32; - u->L[_0] = (bits[2] >> j & 0xfffff) | (33 + j) << 20; - u->L[_1] = ((bits[2] << i) | (bits[1] >> j)) & 0xffffffffL; - u->L[2+_0] = bits[1] & ((1L << j) - 1); - u->L[2+_1] = bits[0]; - break; - } - if (i == 0) { - u->L[_0] = (bits[2] & 0xfffff) | (33 << 20); - u->L[_1] = bits[1]; - u->L[2+_0] = 0; - u->L[2+_1] = bits[0]; - break; - } - j = 32 - i; - u->L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff) - | ((j + 1) << 20); - u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; - u->L[2+_0] = 0; - u->L[2+_1] = bits[0] & ((1L << j) - 1); - break; - - hardly_normal: - j = 11 - hi0bits(bits[1]); - i = 32 - j; - u->L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20); - u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; - u->L[2+_0] = 0; - u->L[2+_1] = bits[0] & ((1L << j) - 1); - break; - - case STRTOG_Infinite: - u->L[_0] = u->L[2+_0] = 0x7ff00000; - u->L[_1] = u->L[2+_1] = 0; - break; - - case STRTOG_NaN: - u->L[0] = u->L[2] = d_QNAN0; - u->L[1] = u->L[3] = d_QNAN1; - } - if (rv & STRTOG_Neg) { - u->L[ _0] |= 0x80000000L; - u->L[2+_0] |= 0x80000000L; - } - return rv; - } diff --git a/libraries/gdtoa/strtopf.c b/libraries/gdtoa/strtopf.c deleted file mode 100644 index 23ca5cbe58..0000000000 --- a/libraries/gdtoa/strtopf.c +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - int -#ifdef KR_headers -strtopf(s, sp, f) CONST char *s; char **sp; float *f; -#else -strtopf(CONST char *s, char **sp, float *f) -#endif -{ - static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; - ULong bits[1], *L; - Long exp; - int k; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - k = strtodg(s, sp, fpi, &exp, bits); - L = (ULong*)f; - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = 0; - break; - - case STRTOG_Normal: - case STRTOG_NaNbits: - L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); - break; - - case STRTOG_Denormal: - L[0] = bits[0]; - break; - - case STRTOG_Infinite: - L[0] = 0x7f800000; - break; - - case STRTOG_NaN: - L[0] = f_QNAN; - } - if (k & STRTOG_Neg) - L[0] |= 0x80000000L; - return k; - } diff --git a/libraries/gdtoa/strtopx.c b/libraries/gdtoa/strtopx.c deleted file mode 100644 index 32192c5726..0000000000 --- a/libraries/gdtoa/strtopx.c +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - extern UShort NanDflt_ldus_D2A[5]; - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#define _3 3 -#define _4 4 -#endif -#ifdef IEEE_8087 -#define _0 4 -#define _1 3 -#define _2 2 -#define _3 1 -#define _4 0 -#endif - - int -#ifdef KR_headers -strtopx(s, sp, V) CONST char *s; char **sp; void *V; -#else -strtopx(CONST char *s, char **sp, void *V) -#endif -{ - static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - ULong bits[2]; - Long exp; - int k; - UShort *L = (UShort*)V; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - k = strtodg(s, sp, fpi, &exp, bits); - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = L[1] = L[2] = L[3] = L[4] = 0; - break; - - case STRTOG_Denormal: - L[_0] = 0; - goto normal_bits; - - case STRTOG_Normal: - case STRTOG_NaNbits: - L[_0] = exp + 0x3fff + 63; - normal_bits: - L[_4] = (UShort)bits[0]; - L[_3] = (UShort)(bits[0] >> 16); - L[_2] = (UShort)bits[1]; - L[_1] = (UShort)(bits[1] >> 16); - break; - - case STRTOG_Infinite: - L[_0] = 0x7fff; - L[_1] = 0x8000; - L[_2] = L[_3] = L[_4] = 0; - break; - - case STRTOG_NaN: - L[_4] = NanDflt_ldus_D2A[0]; - L[_3] = NanDflt_ldus_D2A[1]; - L[_2] = NanDflt_ldus_D2A[2]; - L[_1] = NanDflt_ldus_D2A[3]; - L[_0] = NanDflt_ldus_D2A[4]; - } - if (k & STRTOG_Neg) - L[_0] |= 0x8000; - return k; - } diff --git a/libraries/gdtoa/strtopxL.c b/libraries/gdtoa/strtopxL.c deleted file mode 100644 index 6166c1e626..0000000000 --- a/libraries/gdtoa/strtopxL.c +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - extern ULong NanDflt_xL_D2A[3]; - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#endif -#ifdef IEEE_8087 -#define _0 2 -#define _1 1 -#define _2 0 -#endif - - int -#ifdef KR_headers -strtopxL(s, sp, V) CONST char *s; char **sp; void *V; -#else -strtopxL(CONST char *s, char **sp, void *V) -#endif -{ - static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - ULong bits[2]; - Long exp; - int k; - ULong *L = (ULong*)V; -#ifdef Honor_FLT_ROUNDS -#include "gdtoa_fltrnds.h" -#else -#define fpi &fpi0 -#endif - - k = strtodg(s, sp, fpi, &exp, bits); - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = L[1] = L[2] = 0; - break; - - case STRTOG_Normal: - case STRTOG_Denormal: - case STRTOG_NaNbits: - L[_2] = bits[0]; - L[_1] = bits[1]; - L[_0] = (exp + 0x3fff + 63) << 16; - break; - - case STRTOG_Infinite: - L[_0] = 0x7fff << 16; - L[_1] = 0x80000000; - L[_2] = 0; - break; - - case STRTOG_NaN: - L[_0] = NanDflt_xL_D2A[2]; - L[_1] = NanDflt_xL_D2A[1]; - L[_2] = NanDflt_xL_D2A[0]; - } - if (k & STRTOG_Neg) - L[_0] |= 0x80000000L; - return k; - } diff --git a/libraries/gdtoa/strtorQ.c b/libraries/gdtoa/strtorQ.c deleted file mode 100644 index f5fd7bba94..0000000000 --- a/libraries/gdtoa/strtorQ.c +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#define _3 3 -#endif -#ifdef IEEE_8087 -#define _0 3 -#define _1 2 -#define _2 1 -#define _3 0 -#endif - - extern ULong NanDflt_Q_D2A[4]; - - void -#ifdef KR_headers -ULtoQ(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; -#else -ULtoQ(ULong *L, ULong *bits, Long exp, int k) -#endif -{ - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = L[1] = L[2] = L[3] = 0; - break; - - case STRTOG_Normal: - case STRTOG_NaNbits: - L[_3] = bits[0]; - L[_2] = bits[1]; - L[_1] = bits[2]; - L[_0] = (bits[3] & ~0x10000) | ((exp + 0x3fff + 112) << 16); - break; - - case STRTOG_Denormal: - L[_3] = bits[0]; - L[_2] = bits[1]; - L[_1] = bits[2]; - L[_0] = bits[3]; - break; - - case STRTOG_Infinite: - L[_0] = 0x7fff0000; - L[_1] = L[_2] = L[_3] = 0; - break; - - case STRTOG_NaN: - L[_0] = NanDflt_Q_D2A[3]; - L[_1] = NanDflt_Q_D2A[2]; - L[_2] = NanDflt_Q_D2A[1]; - L[_3] = NanDflt_Q_D2A[0]; - } - if (k & STRTOG_Neg) - L[_0] |= 0x80000000L; - } - - int -#ifdef KR_headers -strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; -#else -strtorQ(CONST char *s, char **sp, int rounding, void *L) -#endif -{ - static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; - FPI *fpi, fpi1; - ULong bits[4]; - Long exp; - int k; - - fpi = &fpi0; - if (rounding != FPI_Round_near) { - fpi1 = fpi0; - fpi1.rounding = rounding; - fpi = &fpi1; - } - k = strtodg(s, sp, fpi, &exp, bits); - ULtoQ((ULong*)L, bits, exp, k); - return k; - } diff --git a/libraries/gdtoa/strtord.c b/libraries/gdtoa/strtord.c deleted file mode 100644 index dd0769698c..0000000000 --- a/libraries/gdtoa/strtord.c +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - extern ULong NanDflt_d_D2A[2]; - - void -#ifdef KR_headers -ULtod(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; -#else -ULtod(ULong *L, ULong *bits, Long exp, int k) -#endif -{ - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = L[1] = 0; - break; - - case STRTOG_Denormal: - L[_1] = bits[0]; - L[_0] = bits[1]; - break; - - case STRTOG_Normal: - case STRTOG_NaNbits: - L[_1] = bits[0]; - L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20); - break; - - case STRTOG_Infinite: - L[_0] = 0x7ff00000; - L[_1] = 0; - break; - - case STRTOG_NaN: - L[_0] = NanDflt_d_D2A[1]; - L[_1] = NanDflt_d_D2A[0]; - } - if (k & STRTOG_Neg) - L[_0] |= 0x80000000L; - } - - int -#ifdef KR_headers -strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d; -#else -strtord(CONST char *s, char **sp, int rounding, double *d) -#endif -{ - static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - FPI *fpi, fpi1; - ULong bits[2]; - Long exp; - int k; - - fpi = &fpi0; - if (rounding != FPI_Round_near) { - fpi1 = fpi0; - fpi1.rounding = rounding; - fpi = &fpi1; - } - k = strtodg(s, sp, fpi, &exp, bits); - ULtod((ULong*)d, bits, exp, k); - return k; - } diff --git a/libraries/gdtoa/strtordd.c b/libraries/gdtoa/strtordd.c deleted file mode 100644 index 62152dbd43..0000000000 --- a/libraries/gdtoa/strtordd.c +++ /dev/null @@ -1,202 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - extern ULong NanDflt_d_D2A[2]; - - void -#ifdef KR_headers -ULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; -#else -ULtodd(ULong *L, ULong *bits, Long exp, int k) -#endif -{ - int i, j; - - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = L[1] = L[2] = L[3] = 0; - break; - - case STRTOG_Normal: - L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL; - L[_0] = (bits[2] >> 21) | (bits[3] << 11 & 0xfffff) - | ((exp + 0x3ff + 105) << 20); - exp += 0x3ff + 52; - if (bits[1] &= 0x1fffff) { - i = hi0bits(bits[1]) - 11; - if (i >= exp) { - i = exp - 1; - exp = 0; - } - else - exp -= i; - if (i > 0) { - bits[1] = bits[1] << i | bits[0] >> (32-i); - bits[0] = bits[0] << i & (ULong)0xffffffffL; - } - } - else if (bits[0]) { - i = hi0bits(bits[0]) + 21; - if (i >= exp) { - i = exp - 1; - exp = 0; - } - else - exp -= i; - if (i < 32) { - bits[1] = bits[0] >> (32 - i); - bits[0] = bits[0] << i & (ULong)0xffffffffL; - } - else { - bits[1] = bits[0] << (i - 32); - bits[0] = 0; - } - } - else { - L[2] = L[3] = 0; - break; - } - L[2+_1] = bits[0]; - L[2+_0] = (bits[1] & 0xfffff) | (exp << 20); - break; - - case STRTOG_Denormal: - if (bits[3]) - goto nearly_normal; - if (bits[2]) - goto partly_normal; - if (bits[1] & 0xffe00000) - goto hardly_normal; - /* completely denormal */ - L[2] = L[3] = 0; - L[_1] = bits[0]; - L[_0] = bits[1]; - break; - - nearly_normal: - i = hi0bits(bits[3]) - 11; /* i >= 12 */ - j = 32 - i; - L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff) - | ((65 - i) << 20); - L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - L[2+_0] = bits[1] & (((ULong)1L << j) - 1); - L[2+_1] = bits[0]; - break; - - partly_normal: - i = hi0bits(bits[2]) - 11; - if (i < 0) { - j = -i; - i += 32; - L[_0] = (bits[2] >> j & 0xfffff) | ((33 + j) << 20); - L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - L[2+_0] = bits[1] & (((ULong)1L << j) - 1); - L[2+_1] = bits[0]; - break; - } - if (i == 0) { - L[_0] = (bits[2] & 0xfffff) | (33 << 20); - L[_1] = bits[1]; - L[2+_0] = 0; - L[2+_1] = bits[0]; - break; - } - j = 32 - i; - L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff) - | ((j + 1) << 20); - L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; - L[2+_0] = 0; - L[2+_1] = bits[0] & ((1L << j) - 1); - break; - - hardly_normal: - j = 11 - hi0bits(bits[1]); - i = 32 - j; - L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20); - L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; - L[2+_0] = 0; - L[2+_1] = bits[0] & (((ULong)1L << j) - 1); - break; - - case STRTOG_Infinite: - L[_0] = L[2+_0] = 0x7ff00000; - L[_1] = L[2+_1] = 0; - break; - - case STRTOG_NaN: - L[_0] = L[_0+2] = NanDflt_d_D2A[1]; - L[_1] = L[_1+2] = NanDflt_d_D2A[0]; - break; - - case STRTOG_NaNbits: - L[_1] = (bits[1] >> 20 | bits[2] << 12) & (ULong)0xffffffffL; - L[_0] = bits[2] >> 20 | bits[3] << 12; - L[_0] |= (L[_1] | L[_0]) ? (ULong)0x7ff00000L : (ULong)0x7ff80000L; - L[2+_1] = bits[0] & (ULong)0xffffffffL; - L[2+_0] = bits[1] & 0xfffffL; - L[2+_0] |= (L[2+_1] | L[2+_0]) ? (ULong)0x7ff00000L : (ULong)0x7ff80000L; - } - if (k & STRTOG_Neg) { - L[_0] |= 0x80000000L; - L[2+_0] |= 0x80000000L; - } - } - - int -#ifdef KR_headers -strtordd(s, sp, rounding, dd) CONST char *s; char **sp; int rounding; double *dd; -#else -strtordd(CONST char *s, char **sp, int rounding, double *dd) -#endif -{ -#ifdef Sudden_Underflow - static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; -#else - static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; -#endif - FPI *fpi, fpi1; - ULong bits[4]; - Long exp; - int k; - - fpi = &fpi0; - if (rounding != FPI_Round_near) { - fpi1 = fpi0; - fpi1.rounding = rounding; - fpi = &fpi1; - } - k = strtodg(s, sp, fpi, &exp, bits); - ULtodd((ULong*)dd, bits, exp, k); - return k; - } diff --git a/libraries/gdtoa/strtorf.c b/libraries/gdtoa/strtorf.c deleted file mode 100644 index 99b4ab7107..0000000000 --- a/libraries/gdtoa/strtorf.c +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - extern ULong NanDflt_f_D2A[1]; - - void -#ifdef KR_headers -ULtof(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; -#else -ULtof(ULong *L, ULong *bits, Long exp, int k) -#endif -{ - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - *L = 0; - break; - - case STRTOG_Normal: - case STRTOG_NaNbits: - L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); - break; - - case STRTOG_Denormal: - L[0] = bits[0]; - break; - - case STRTOG_Infinite: - L[0] = 0x7f800000; - break; - - case STRTOG_NaN: - L[0] = NanDflt_f_D2A[0]; - } - if (k & STRTOG_Neg) - L[0] |= 0x80000000L; - } - - int -#ifdef KR_headers -strtorf(s, sp, rounding, f) CONST char *s; char **sp; int rounding; float *f; -#else -strtorf(CONST char *s, char **sp, int rounding, float *f) -#endif -{ - static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; - FPI *fpi, fpi1; - ULong bits[1]; - Long exp; - int k; - - fpi = &fpi0; - if (rounding != FPI_Round_near) { - fpi1 = fpi0; - fpi1.rounding = rounding; - fpi = &fpi1; - } - k = strtodg(s, sp, fpi, &exp, bits); - ULtof((ULong*)f, bits, exp, k); - return k; - } diff --git a/libraries/gdtoa/strtorx.c b/libraries/gdtoa/strtorx.c deleted file mode 100644 index 994ce8e63f..0000000000 --- a/libraries/gdtoa/strtorx.c +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#define _3 3 -#define _4 4 -#endif -#ifdef IEEE_8087 -#define _0 4 -#define _1 3 -#define _2 2 -#define _3 1 -#define _4 0 -#endif - - extern UShort NanDflt_ldus_D2A[5]; - - void -#ifdef KR_headers -ULtox(L, bits, exp, k) UShort *L; ULong *bits; Long exp; int k; -#else -ULtox(UShort *L, ULong *bits, Long exp, int k) -#endif -{ - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = L[1] = L[2] = L[3] = L[4] = 0; - break; - - case STRTOG_Denormal: - L[_0] = 0; - goto normal_bits; - - case STRTOG_Normal: - case STRTOG_NaNbits: - L[_0] = exp + 0x3fff + 63; - normal_bits: - L[_4] = (UShort)bits[0]; - L[_3] = (UShort)(bits[0] >> 16); - L[_2] = (UShort)bits[1]; - L[_1] = (UShort)(bits[1] >> 16); - break; - - case STRTOG_Infinite: - L[_0] = 0x7fff; - L[_1] = 0x8000; - L[_2] = L[_3] = L[_4] = 0; - break; - - case STRTOG_NaN: - L[_4] = NanDflt_ldus_D2A[0]; - L[_3] = NanDflt_ldus_D2A[1]; - L[_2] = NanDflt_ldus_D2A[2]; - L[_1] = NanDflt_ldus_D2A[3]; - L[_0] = NanDflt_ldus_D2A[4]; - } - if (k & STRTOG_Neg) - L[_0] |= 0x8000; - } - - int -#ifdef KR_headers -strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; -#else -strtorx(CONST char *s, char **sp, int rounding, void *L) -#endif -{ - static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - FPI *fpi, fpi1; - ULong bits[2]; - Long exp; - int k; - - fpi = &fpi0; - if (rounding != FPI_Round_near) { - fpi1 = fpi0; - fpi1.rounding = rounding; - fpi = &fpi1; - } - k = strtodg(s, sp, fpi, &exp, bits); - ULtox((UShort*)L, bits, exp, k); - return k; - } diff --git a/libraries/gdtoa/strtorxL.c b/libraries/gdtoa/strtorxL.c deleted file mode 100644 index bac4a0bb15..0000000000 --- a/libraries/gdtoa/strtorxL.c +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 2000 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - -#undef _0 -#undef _1 - -/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ - -#ifdef IEEE_MC68k -#define _0 0 -#define _1 1 -#define _2 2 -#endif -#ifdef IEEE_8087 -#define _0 2 -#define _1 1 -#define _2 0 -#endif - - extern ULong NanDflt_xL_D2A[3]; - - void -#ifdef KR_headers -ULtoxL(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; -#else -ULtoxL(ULong *L, ULong *bits, Long exp, int k) -#endif -{ - switch(k & STRTOG_Retmask) { - case STRTOG_NoNumber: - case STRTOG_Zero: - L[0] = L[1] = L[2] = 0; - break; - - case STRTOG_Normal: - case STRTOG_Denormal: - case STRTOG_NaNbits: - L[_0] = (exp + 0x3fff + 63) << 16; - L[_1] = bits[1]; - L[_2] = bits[0]; - break; - - case STRTOG_Infinite: - L[_0] = 0x7fff0000; - L[_1] = 0x80000000; - L[_2] = 0; - break; - - case STRTOG_NaN: - L[_0] = NanDflt_xL_D2A[2]; - L[_1] = NanDflt_xL_D2A[1]; - L[_2] = NanDflt_xL_D2A[0]; - } - if (k & STRTOG_Neg) - L[_0] |= 0x80000000L; - } - - int -#ifdef KR_headers -strtorxL(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; -#else -strtorxL(CONST char *s, char **sp, int rounding, void *L) -#endif -{ - static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - FPI *fpi, fpi1; - ULong bits[2]; - Long exp; - int k; - - fpi = &fpi0; - if (rounding != FPI_Round_near) { - fpi1 = fpi0; - fpi1.rounding = rounding; - fpi = &fpi1; - } - k = strtodg(s, sp, fpi, &exp, bits); - ULtoxL((ULong*)L, bits, exp, k); - return k; - } diff --git a/libraries/gdtoa/sum.c b/libraries/gdtoa/sum.c deleted file mode 100644 index dc0c88bcfa..0000000000 --- a/libraries/gdtoa/sum.c +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - Bigint * -#ifdef KR_headers -sum(a, b) Bigint *a; Bigint *b; -#else -sum(Bigint *a, Bigint *b) -#endif -{ - Bigint *c; - ULong carry, *xc, *xa, *xb, *xe, y; -#ifdef Pack_32 - ULong z; -#endif - - if (a->wds < b->wds) { - c = b; b = a; a = c; - } - c = Balloc(a->k); - c->wds = a->wds; - carry = 0; - xa = a->x; - xb = b->x; - xc = c->x; - xe = xc + b->wds; -#ifdef Pack_32 - do { - y = (*xa & 0xffff) + (*xb & 0xffff) + carry; - carry = (y & 0x10000) >> 16; - z = (*xa++ >> 16) + (*xb++ >> 16) + carry; - carry = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } - while(xc < xe); - xe += a->wds - b->wds; - while(xc < xe) { - y = (*xa & 0xffff) + carry; - carry = (y & 0x10000) >> 16; - z = (*xa++ >> 16) + carry; - carry = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } -#else - do { - y = *xa++ + *xb++ + carry; - carry = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } - while(xc < xe); - xe += a->wds - b->wds; - while(xc < xe) { - y = *xa++ + carry; - carry = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } -#endif - if (carry) { - if (c->wds == c->maxwds) { - b = Balloc(c->k + 1); - Bcopy(b, c); - Bfree(c); - c = b; - } - c->x[c->wds++] = 1; - } - return c; - } diff --git a/libraries/gdtoa/ulp.c b/libraries/gdtoa/ulp.c deleted file mode 100644 index 17e9f862c4..0000000000 --- a/libraries/gdtoa/ulp.c +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************** - -The author of this software is David M. Gay. - -Copyright (C) 1998, 1999 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -****************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -#include "gdtoaimp.h" - - double -ulp -#ifdef KR_headers - (x) U *x; -#else - (U *x) -#endif -{ - Long L; - U a; - - L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; -#ifndef Sudden_Underflow - if (L > 0) { -#endif -#ifdef IBM - L |= Exp_msk1 >> 4; -#endif - word0(&a) = L; - word1(&a) = 0; -#ifndef Sudden_Underflow - } - else { - L = -L >> Exp_shift; - if (L < Exp_shift) { - word0(&a) = 0x80000 >> L; - word1(&a) = 0; - } - else { - word0(&a) = 0; - L -= Exp_shift; - word1(&a) = L >= 31 ? 1 : 1 << (31 - L); - } - } -#endif - return dval(&a); - } diff --git a/libraries/jpeg/CMakeLists.txt b/libraries/jpeg/CMakeLists.txt deleted file mode 100644 index d57779495e..0000000000 --- a/libraries/jpeg/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required( VERSION 3.1.0 ) - -make_release_only() - -if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -fomit-frame-pointer" ) -endif() - -add_library( jpeg STATIC - jaricom.c - jcomapi.c - jdapimin.c - jdapistd.c - jdarith.c - jdatasrc.c - jdcoefct.c - jdcolor.c - jddctmgr.c - jdhuff.c - jdinput.c - jdmainct.c - jdmarker.c - jdmaster.c - jdmerge.c - jdpostct.c - jdsample.c - jerror.c - jidctflt.c - jidctfst.c - jidctint.c - jmemansi.c - jmemmgr.c - jquant1.c - jquant2.c - jutils.c ) -target_link_libraries( jpeg ) diff --git a/libraries/jpeg/README b/libraries/jpeg/README deleted file mode 100644 index 56cdb60038..0000000000 --- a/libraries/jpeg/README +++ /dev/null @@ -1,378 +0,0 @@ -The Independent JPEG Group's JPEG software -========================================== - -README for release 9c of 14-Jan-2018 -==================================== - -This distribution contains the ninth public release of the Independent JPEG -Group's free JPEG software. You are welcome to redistribute this software and -to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. - -This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone, -Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson, -Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers, -and other members of the Independent JPEG Group. - -IJG is not affiliated with the ISO/IEC JTC1/SC29/WG1 standards committee -(previously known as JPEG, together with ITU-T SG16). - - -DOCUMENTATION ROADMAP -===================== - -This file contains the following sections: - -OVERVIEW General description of JPEG and the IJG software. -LEGAL ISSUES Copyright, lack of warranty, terms of distribution. -REFERENCES Where to learn more about JPEG. -ARCHIVE LOCATIONS Where to find newer versions of this software. -ACKNOWLEDGMENTS Special thanks. -FILE FORMAT WARS Software *not* to get. -TO DO Plans for future IJG releases. - -Other documentation files in the distribution are: - -User documentation: - install.txt How to configure and install the IJG software. - usage.txt Usage instructions for cjpeg, djpeg, jpegtran, - rdjpgcom, and wrjpgcom. - *.1 Unix-style man pages for programs (same info as usage.txt). - wizard.txt Advanced usage instructions for JPEG wizards only. - change.log Version-to-version change highlights. -Programmer and internal documentation: - libjpeg.txt How to use the JPEG library in your own programs. - example.c Sample code for calling the JPEG library. - structure.txt Overview of the JPEG library's internal structure. - filelist.txt Road map of IJG files. - coderules.txt Coding style rules --- please read if you contribute code. - -Please read at least the files install.txt and usage.txt. Some information -can also be found in the JPEG FAQ (Frequently Asked Questions) article. See -ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. - -If you want to understand how the JPEG code works, we suggest reading one or -more of the REFERENCES, then looking at the documentation files (in roughly -the order listed) before diving into the code. - - -OVERVIEW -======== - -This package contains C software to implement JPEG image encoding, decoding, -and transcoding. JPEG (pronounced "jay-peg") is a standardized compression -method for full-color and grayscale images. - -This software implements JPEG baseline, extended-sequential, and progressive -compression processes. Provision is made for supporting all variants of these -processes, although some uncommon parameter settings aren't implemented yet. -We have made no provision for supporting the hierarchical or lossless -processes defined in the standard. - -We provide a set of library routines for reading and writing JPEG image files, -plus two sample applications "cjpeg" and "djpeg", which use the library to -perform conversion between JPEG and some other popular image file formats. -The library is intended to be reused in other applications. - -In order to support file conversion and viewing software, we have included -considerable functionality beyond the bare JPEG coding/decoding capability; -for example, the color quantization modules are not strictly part of JPEG -decoding, but they are essential for output to colormapped file formats or -colormapped displays. These extra functions can be compiled out of the -library if not required for a particular application. - -We have also included "jpegtran", a utility for lossless transcoding between -different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple -applications for inserting and extracting textual comments in JFIF files. - -The emphasis in designing this software has been on achieving portability and -flexibility, while also making it fast enough to be useful. In particular, -the software is not intended to be read as a tutorial on JPEG. (See the -REFERENCES section for introductory material.) Rather, it is intended to -be reliable, portable, industrial-strength code. We do not claim to have -achieved that goal in every aspect of the software, but we strive for it. - -We welcome the use of this software as a component of commercial products. -No royalty is required, but we do ask for an acknowledgement in product -documentation, as described under LEGAL ISSUES. - - -LEGAL ISSUES -============ - -In plain English: - -1. We don't promise that this software works. (But if you find any bugs, - please let us know!) -2. You can use this software for whatever you want. You don't have to pay us. -3. You may not pretend that you wrote this software. If you use it in a - program, you must acknowledge somewhere in your documentation that - you've used the IJG code. - -In legalese: - -The authors make NO WARRANTY or representation, either express or implied, -with respect to this software, its quality, accuracy, merchantability, or -fitness for a particular purpose. This software is provided "AS IS", and you, -its user, assume the entire risk as to its quality and accuracy. - -This software is copyright (C) 1991-2018, Thomas G. Lane, Guido Vollbeding. -All Rights Reserved except as specified below. - -Permission is hereby granted to use, copy, modify, and distribute this -software (or portions thereof) for any purpose, without fee, subject to these -conditions: -(1) If any part of the source code for this software is distributed, then this -README file must be included, with this copyright and no-warranty notice -unaltered; and any additions, deletions, or changes to the original files -must be clearly indicated in accompanying documentation. -(2) If only executable code is distributed, then the accompanying -documentation must state that "this software is based in part on the work of -the Independent JPEG Group". -(3) Permission for use of this software is granted only if the user accepts -full responsibility for any undesirable consequences; the authors accept -NO LIABILITY for damages of any kind. - -These conditions apply to any software derived from or based on the IJG code, -not just to the unmodified library. If you use our work, you ought to -acknowledge us. - -Permission is NOT granted for the use of any IJG author's name or company name -in advertising or publicity relating to this software or products derived from -it. This software may be referred to only as "the Independent JPEG Group's -software". - -We specifically permit and encourage the use of this software as the basis of -commercial products, provided that all warranty or liability claims are -assumed by the product vendor. - - -The Unix configuration script "configure" was produced with GNU Autoconf. -It is copyright by the Free Software Foundation but is freely distributable. -The same holds for its supporting scripts (config.guess, config.sub, -ltmain.sh). Another support script, install-sh, is copyright by X Consortium -but is also freely distributable. - -The IJG distribution formerly included code to read and write GIF files. -To avoid entanglement with the Unisys LZW patent (now expired), GIF reading -support has been removed altogether, and the GIF writer has been simplified -to produce "uncompressed GIFs". This technique does not use the LZW -algorithm; the resulting GIF files are larger than usual, but are readable -by all standard GIF decoders. - - -REFERENCES -========== - -We recommend reading one or more of these references before trying to -understand the innards of the JPEG software. - -The best short technical introduction to the JPEG compression algorithm is - Wallace, Gregory K. "The JPEG Still Picture Compression Standard", - Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. -(Adjacent articles in that issue discuss MPEG motion picture compression, -applications of JPEG, and related topics.) If you don't have the CACM issue -handy, a PDF file containing a revised version of Wallace's article is -available at http://www.ijg.org/files/Wallace.JPEG.pdf. The file (actually -a preprint for an article that appeared in IEEE Trans. Consumer Electronics) -omits the sample images that appeared in CACM, but it includes corrections -and some added material. Note: the Wallace article is copyright ACM and IEEE, -and it may not be used for commercial purposes. - -A somewhat less technical, more leisurely introduction to JPEG can be found in -"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by -M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides -good explanations and example C code for a multitude of compression methods -including JPEG. It is an excellent source if you are comfortable reading C -code but don't know much about data compression in general. The book's JPEG -sample code is far from industrial-strength, but when you are ready to look -at a full implementation, you've got one here... - -The best currently available description of JPEG is the textbook "JPEG Still -Image Data Compression Standard" by William B. Pennebaker and Joan L. -Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. -Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG -standards (DIS 10918-1 and draft DIS 10918-2). -Although this is by far the most detailed and comprehensive exposition of -JPEG publicly available, we point out that it is still missing an explanation -of the most essential properties and algorithms of the underlying DCT -technology. -If you think that you know about DCT-based JPEG after reading this book, -then you are in delusion. The real fundamentals and corresponding potential -of DCT-based JPEG are not publicly known so far, and that is the reason for -all the mistaken developments taking place in the image coding domain. - -The original JPEG standard is divided into two parts, Part 1 being the actual -specification, while Part 2 covers compliance testing methods. Part 1 is -titled "Digital Compression and Coding of Continuous-tone Still Images, -Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS -10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of -Continuous-tone Still Images, Part 2: Compliance testing" and has document -numbers ISO/IEC IS 10918-2, ITU-T T.83. -IJG JPEG 8 introduced an implementation of the JPEG SmartScale extension -which is specified in two documents: A contributed document at ITU and ISO -with title "ITU-T JPEG-Plus Proposal for Extending ITU-T T.81 for Advanced -Image Coding", April 2006, Geneva, Switzerland. The latest version of this -document is Revision 3. And a contributed document ISO/IEC JTC1/SC29/WG1 N -5799 with title "Evolution of JPEG", June/July 2011, Berlin, Germany. -IJG JPEG 9 introduces a reversible color transform for improved lossless -compression which is described in a contributed document ISO/IEC JTC1/SC29/ -WG1 N 6080 with title "JPEG 9 Lossless Coding", June/July 2012, Paris, -France. - -The JPEG standard does not specify all details of an interchangeable file -format. For the omitted details we follow the "JFIF" conventions, version 2. -JFIF version 1 has been adopted as Recommendation ITU-T T.871 (05/2011) : -Information technology - Digital compression and coding of continuous-tone -still images: JPEG File Interchange Format (JFIF). It is available as a -free download in PDF file format from http://www.itu.int/rec/T-REC-T.871. -A PDF file of the older JFIF document is available at -http://www.w3.org/Graphics/JPEG/jfif3.pdf. - -The TIFF 6.0 file format specification can be obtained by FTP from -ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme -found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. -IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). -Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 -(Compression tag 7). Copies of this Note can be obtained from -http://www.ijg.org/files/. It is expected that the next revision -of the TIFF spec will replace the 6.0 JPEG design with the Note's design. -Although IJG's own code does not support TIFF/JPEG, the free libtiff library -uses our library to implement TIFF/JPEG per the Note. - - -ARCHIVE LOCATIONS -================= - -The "official" archive site for this software is www.ijg.org. -The most recent released version can always be found there in -directory "files". This particular version will be archived as -http://www.ijg.org/files/jpegsrc.v9c.tar.gz, and in Windows-compatible -"zip" archive format as http://www.ijg.org/files/jpegsr9c.zip. - -The JPEG FAQ (Frequently Asked Questions) article is a source of some -general information about JPEG. -It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ -and other news.answers archive sites, including the official news.answers -archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. -If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu -with body - send usenet/news.answers/jpeg-faq/part1 - send usenet/news.answers/jpeg-faq/part2 - - -ACKNOWLEDGMENTS -=============== - -Thank to Juergen Bruder for providing me with a copy of the common DCT -algorithm article, only to find out that I had come to the same result -in a more direct and comprehensible way with a more generative approach. - -Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the -ITU JPEG (Study Group 16) meeting in Geneva, Switzerland. - -Thank to Thomas Wiegand and Gary Sullivan for inviting me to the -Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland. - -Thank to Thomas Richter and Daniel Lee for inviting me to the -ISO/IEC JTC1/SC29/WG1 (previously known as JPEG, together with ITU-T SG16) -meeting in Berlin, Germany. - -Thank to John Korejwa and Massimo Ballerini for inviting me to -fruitful consultations in Boston, MA and Milan, Italy. - -Thank to Hendrik Elstner, Roland Fassauer, Simone Zuck, Guenther -Maier-Gerber, Walter Stoeber, Fred Schmitz, and Norbert Braunagel -for corresponding business development. - -Thank to Nico Zschach and Dirk Stelling of the technical support team -at the Digital Images company in Halle for providing me with extra -equipment for configuration tests. - -Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful -communication about JPEG configuration in Sigma Photo Pro software. - -Thank to Andrew Finkenstadt for hosting the ijg.org site. - -Thank to Thomas G. Lane for the original design and development of -this singular software package. - -Thank to Lars Goehler, Andreas Heinecke, Sebastian Fuss, Yvonne Roebert, -Andrej Werner, and Ulf-Dietrich Braumann for support and public relations. - - -FILE FORMAT WARS -================ - -The ISO/IEC JTC1/SC29/WG1 standards committee (previously known as JPEG, -together with ITU-T SG16) currently promotes different formats containing -the name "JPEG" which is misleading because these formats are incompatible -with original DCT-based JPEG and are based on faulty technologies. -IJG therefore does not and will not support such momentary mistakes -(see REFERENCES). -There exist also distributions under the name "OpenJPEG" promoting such -kind of formats which is misleading because they don't support original -JPEG images. -We have no sympathy for the promotion of inferior formats. Indeed, one of -the original reasons for developing this free software was to help force -convergence on common, interoperable format standards for JPEG files. -Don't use an incompatible file format! -(In any case, our decoder will remain capable of reading existing JPEG -image files indefinitely.) - -The ISO committee pretends to be "responsible for the popular JPEG" in their -public reports which is not true because they don't respond to actual -requirements for the maintenance of the original JPEG specification. -Furthermore, the ISO committee pretends to "ensure interoperability" with -their standards which is not true because their "standards" support only -application-specific and proprietary use cases and contain mathematically -incorrect code. - -There are currently different distributions in circulation containing the -name "libjpeg" which is misleading because they don't have the features and -are incompatible with formats supported by actual IJG libjpeg distributions. -One of those fakes is released by members of the ISO committee and just uses -the name of libjpeg for misdirection of people, similar to the abuse of the -name JPEG as described above, while having nothing in common with actual IJG -libjpeg distributions and containing mathematically incorrect code. -The other one claims to be a "derivative" or "fork" of the original libjpeg, -but violates the license conditions as described under LEGAL ISSUES above -and violates basic C programming properties. -We have no sympathy for the release of misleading, incorrect and illegal -distributions derived from obsolete code bases. -Don't use an obsolete code base! - -According to the UCC (Uniform Commercial Code) law, IJG has the lawful and -legal right to foreclose on certain standardization bodies and other -institutions or corporations that knowingly perform substantial and -systematic deceptive acts and practices, fraud, theft, and damaging of the -value of the people of this planet without their knowing, willing and -intentional consent. -The titles, ownership, and rights of these institutions and all their assets -are now duly secured and held in trust for the free people of this planet. -People of the planet, on every country, may have a financial interest in -the assets of these former principals, agents, and beneficiaries of the -foreclosed institutions and corporations. -IJG asserts what is: that each man, woman, and child has unalienable value -and rights granted and deposited in them by the Creator and not any one of -the people is subordinate to any artificial principality, corporate fiction -or the special interest of another without their appropriate knowing, -willing and intentional consent made by contract or accommodation agreement. -IJG expresses that which already was. -The people have already determined and demanded that public administration -entities, national governments, and their supporting judicial systems must -be fully transparent, accountable, and liable. -IJG has secured the value for all concerned free people of the planet. - -A partial list of foreclosed institutions and corporations ("Hall of Shame") -is currently prepared and will be published later. - - -TO DO -===== - -Version 9 is the second release of a new generation JPEG standard -to overcome the limitations of the original JPEG specification, -and is the first true source reference JPEG codec. -More features are being prepared for coming releases... - -Please send bug reports, offers of help, etc. to jpeg-info@jpegclub.org. diff --git a/libraries/jpeg/jaricom.c b/libraries/jpeg/jaricom.c deleted file mode 100644 index 690068861f..0000000000 --- a/libraries/jpeg/jaricom.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * jaricom.c - * - * Developed 1997-2011 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains probability estimation tables for common use in - * arithmetic entropy encoding and decoding routines. - * - * This data represents Table D.3 in the JPEG spec (D.2 in the draft), - * ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81, and Table 24 - * in the JBIG spec, ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -/* The following #define specifies the packing of the four components - * into the compact INT32 representation. - * Note that this formula must match the actual arithmetic encoder - * and decoder implementation. The implementation has to be changed - * if this formula is changed. - * The current organization is leaned on Markus Kuhn's JBIG - * implementation (jbig_tab.c). - */ - -#define V(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) - -const INT32 jpeg_aritab[113+1] = { -/* - * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS - */ - V( 0, 0x5a1d, 1, 1, 1 ), - V( 1, 0x2586, 14, 2, 0 ), - V( 2, 0x1114, 16, 3, 0 ), - V( 3, 0x080b, 18, 4, 0 ), - V( 4, 0x03d8, 20, 5, 0 ), - V( 5, 0x01da, 23, 6, 0 ), - V( 6, 0x00e5, 25, 7, 0 ), - V( 7, 0x006f, 28, 8, 0 ), - V( 8, 0x0036, 30, 9, 0 ), - V( 9, 0x001a, 33, 10, 0 ), - V( 10, 0x000d, 35, 11, 0 ), - V( 11, 0x0006, 9, 12, 0 ), - V( 12, 0x0003, 10, 13, 0 ), - V( 13, 0x0001, 12, 13, 0 ), - V( 14, 0x5a7f, 15, 15, 1 ), - V( 15, 0x3f25, 36, 16, 0 ), - V( 16, 0x2cf2, 38, 17, 0 ), - V( 17, 0x207c, 39, 18, 0 ), - V( 18, 0x17b9, 40, 19, 0 ), - V( 19, 0x1182, 42, 20, 0 ), - V( 20, 0x0cef, 43, 21, 0 ), - V( 21, 0x09a1, 45, 22, 0 ), - V( 22, 0x072f, 46, 23, 0 ), - V( 23, 0x055c, 48, 24, 0 ), - V( 24, 0x0406, 49, 25, 0 ), - V( 25, 0x0303, 51, 26, 0 ), - V( 26, 0x0240, 52, 27, 0 ), - V( 27, 0x01b1, 54, 28, 0 ), - V( 28, 0x0144, 56, 29, 0 ), - V( 29, 0x00f5, 57, 30, 0 ), - V( 30, 0x00b7, 59, 31, 0 ), - V( 31, 0x008a, 60, 32, 0 ), - V( 32, 0x0068, 62, 33, 0 ), - V( 33, 0x004e, 63, 34, 0 ), - V( 34, 0x003b, 32, 35, 0 ), - V( 35, 0x002c, 33, 9, 0 ), - V( 36, 0x5ae1, 37, 37, 1 ), - V( 37, 0x484c, 64, 38, 0 ), - V( 38, 0x3a0d, 65, 39, 0 ), - V( 39, 0x2ef1, 67, 40, 0 ), - V( 40, 0x261f, 68, 41, 0 ), - V( 41, 0x1f33, 69, 42, 0 ), - V( 42, 0x19a8, 70, 43, 0 ), - V( 43, 0x1518, 72, 44, 0 ), - V( 44, 0x1177, 73, 45, 0 ), - V( 45, 0x0e74, 74, 46, 0 ), - V( 46, 0x0bfb, 75, 47, 0 ), - V( 47, 0x09f8, 77, 48, 0 ), - V( 48, 0x0861, 78, 49, 0 ), - V( 49, 0x0706, 79, 50, 0 ), - V( 50, 0x05cd, 48, 51, 0 ), - V( 51, 0x04de, 50, 52, 0 ), - V( 52, 0x040f, 50, 53, 0 ), - V( 53, 0x0363, 51, 54, 0 ), - V( 54, 0x02d4, 52, 55, 0 ), - V( 55, 0x025c, 53, 56, 0 ), - V( 56, 0x01f8, 54, 57, 0 ), - V( 57, 0x01a4, 55, 58, 0 ), - V( 58, 0x0160, 56, 59, 0 ), - V( 59, 0x0125, 57, 60, 0 ), - V( 60, 0x00f6, 58, 61, 0 ), - V( 61, 0x00cb, 59, 62, 0 ), - V( 62, 0x00ab, 61, 63, 0 ), - V( 63, 0x008f, 61, 32, 0 ), - V( 64, 0x5b12, 65, 65, 1 ), - V( 65, 0x4d04, 80, 66, 0 ), - V( 66, 0x412c, 81, 67, 0 ), - V( 67, 0x37d8, 82, 68, 0 ), - V( 68, 0x2fe8, 83, 69, 0 ), - V( 69, 0x293c, 84, 70, 0 ), - V( 70, 0x2379, 86, 71, 0 ), - V( 71, 0x1edf, 87, 72, 0 ), - V( 72, 0x1aa9, 87, 73, 0 ), - V( 73, 0x174e, 72, 74, 0 ), - V( 74, 0x1424, 72, 75, 0 ), - V( 75, 0x119c, 74, 76, 0 ), - V( 76, 0x0f6b, 74, 77, 0 ), - V( 77, 0x0d51, 75, 78, 0 ), - V( 78, 0x0bb6, 77, 79, 0 ), - V( 79, 0x0a40, 77, 48, 0 ), - V( 80, 0x5832, 80, 81, 1 ), - V( 81, 0x4d1c, 88, 82, 0 ), - V( 82, 0x438e, 89, 83, 0 ), - V( 83, 0x3bdd, 90, 84, 0 ), - V( 84, 0x34ee, 91, 85, 0 ), - V( 85, 0x2eae, 92, 86, 0 ), - V( 86, 0x299a, 93, 87, 0 ), - V( 87, 0x2516, 86, 71, 0 ), - V( 88, 0x5570, 88, 89, 1 ), - V( 89, 0x4ca9, 95, 90, 0 ), - V( 90, 0x44d9, 96, 91, 0 ), - V( 91, 0x3e22, 97, 92, 0 ), - V( 92, 0x3824, 99, 93, 0 ), - V( 93, 0x32b4, 99, 94, 0 ), - V( 94, 0x2e17, 93, 86, 0 ), - V( 95, 0x56a8, 95, 96, 1 ), - V( 96, 0x4f46, 101, 97, 0 ), - V( 97, 0x47e5, 102, 98, 0 ), - V( 98, 0x41cf, 103, 99, 0 ), - V( 99, 0x3c3d, 104, 100, 0 ), - V( 100, 0x375e, 99, 93, 0 ), - V( 101, 0x5231, 105, 102, 0 ), - V( 102, 0x4c0f, 106, 103, 0 ), - V( 103, 0x4639, 107, 104, 0 ), - V( 104, 0x415e, 103, 99, 0 ), - V( 105, 0x5627, 105, 106, 1 ), - V( 106, 0x50e7, 108, 107, 0 ), - V( 107, 0x4b85, 109, 103, 0 ), - V( 108, 0x5597, 110, 109, 0 ), - V( 109, 0x504f, 111, 107, 0 ), - V( 110, 0x5a10, 110, 111, 1 ), - V( 111, 0x5522, 112, 109, 0 ), - V( 112, 0x59eb, 112, 111, 1 ), -/* - * This last entry is used for fixed probability estimate of 0.5 - * as suggested in Section 10.3 Table 5 of ITU-T Rec. T.851. - */ - V( 113, 0x5a1d, 113, 113, 0 ) -}; diff --git a/libraries/jpeg/jcomapi.c b/libraries/jpeg/jcomapi.c deleted file mode 100644 index 9b1fa7568a..0000000000 --- a/libraries/jpeg/jcomapi.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * jcomapi.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface routines that are used for both - * compression and decompression. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Abort processing of a JPEG compression or decompression operation, - * but don't destroy the object itself. - * - * For this, we merely clean up all the nonpermanent memory pools. - * Note that temp files (virtual arrays) are not allowed to belong to - * the permanent pool, so we will be able to close all temp files here. - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - -GLOBAL(void) -jpeg_abort (j_common_ptr cinfo) -{ - int pool; - - /* Do nothing if called on a not-initialized or destroyed JPEG object. */ - if (cinfo->mem == NULL) - return; - - /* Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ - for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { - (*cinfo->mem->free_pool) (cinfo, pool); - } - - /* Reset overall state for possible reuse of object */ - if (cinfo->is_decompressor) { - cinfo->global_state = DSTATE_START; - /* Try to keep application from accessing now-deleted marker list. - * A bit kludgy to do it here, but this is the most central place. - */ - ((j_decompress_ptr) cinfo)->marker_list = NULL; - } else { - cinfo->global_state = CSTATE_START; - } -} - - -/* - * Destruction of a JPEG object. - * - * Everything gets deallocated except the master jpeg_compress_struct itself - * and the error manager struct. Both of these are supplied by the application - * and must be freed, if necessary, by the application. (Often they are on - * the stack and so don't need to be freed anyway.) - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - -GLOBAL(void) -jpeg_destroy (j_common_ptr cinfo) -{ - /* We need only tell the memory manager to release everything. */ - /* NB: mem pointer is NULL if memory mgr failed to initialize. */ - if (cinfo->mem != NULL) - (*cinfo->mem->self_destruct) (cinfo); - cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ - cinfo->global_state = 0; /* mark it destroyed */ -} - - -/* - * Convenience routines for allocating quantization and Huffman tables. - * (Would jutils.c be a more reasonable place to put these?) - */ - -GLOBAL(JQUANT_TBL *) -jpeg_alloc_quant_table (j_common_ptr cinfo) -{ - JQUANT_TBL *tbl; - - tbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); - tbl->sent_table = FALSE; /* make sure this is false in any new table */ - return tbl; -} - - -GLOBAL(JHUFF_TBL *) -jpeg_alloc_huff_table (j_common_ptr cinfo) -{ - JHUFF_TBL *tbl; - - tbl = (JHUFF_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); - tbl->sent_table = FALSE; /* make sure this is false in any new table */ - return tbl; -} diff --git a/libraries/jpeg/jconfig.h b/libraries/jpeg/jconfig.h deleted file mode 100644 index 347e6cb0fa..0000000000 --- a/libraries/jpeg/jconfig.h +++ /dev/null @@ -1,32 +0,0 @@ -/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */ -/* see jconfig.doc for explanations */ - -#define HAVE_PROTOTYPES -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -/* #define void char */ -/* #define const */ -#undef CHAR_IS_UNSIGNED -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H -#undef NEED_BSD_STRINGS -#undef NEED_SYS_TYPES_H - -/* Define "boolean" as unsigned char, not int, per Windows custom */ -#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ -typedef unsigned char boolean; -#endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -#ifdef JPEG_INTERNALS - -#undef RIGHT_SHIFT_IS_UNSIGNED - -#endif /* JPEG_INTERNALS */ diff --git a/libraries/jpeg/jdapimin.c b/libraries/jpeg/jdapimin.c deleted file mode 100644 index a6e0dd9fb8..0000000000 --- a/libraries/jpeg/jdapimin.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * jdapimin.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * Modified 2009-2013 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the decompression half - * of the JPEG library. These are the "minimum" API routines that may be - * needed in either the normal full-decompression case or the - * transcoding-only case. - * - * Most of the routines intended to be called directly by an application - * are in this file or in jdapistd.c. But also see jcomapi.c for routines - * shared by compression and decompression, and jdtrans.c for the transcoding - * case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Initialization of a JPEG decompression object. - * The error manager must already be set up (in case memory manager fails). - */ - -GLOBAL(void) -jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) -{ - int i; - - /* Guard against version mismatches between library and caller. */ - cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ - if (version != JPEG_LIB_VERSION) - ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); - if (structsize != SIZEOF(struct jpeg_decompress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); - - /* For debugging purposes, we zero the whole master structure. - * But the application has already set the err pointer, and may have set - * client_data, so we have to save and restore those fields. - * Note: if application hasn't set client_data, tools like Purify may - * complain here. - */ - { - struct jpeg_error_mgr * err = cinfo->err; - void * client_data = cinfo->client_data; /* ignore Purify complaint here */ - MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); - cinfo->err = err; - cinfo->client_data = client_data; - } - cinfo->is_decompressor = TRUE; - - /* Initialize a memory manager instance for this object */ - jinit_memory_mgr((j_common_ptr) cinfo); - - /* Zero out pointers to permanent structures. */ - cinfo->progress = NULL; - cinfo->src = NULL; - - for (i = 0; i < NUM_QUANT_TBLS; i++) - cinfo->quant_tbl_ptrs[i] = NULL; - - for (i = 0; i < NUM_HUFF_TBLS; i++) { - cinfo->dc_huff_tbl_ptrs[i] = NULL; - cinfo->ac_huff_tbl_ptrs[i] = NULL; - } - - /* Initialize marker processor so application can override methods - * for COM, APPn markers before calling jpeg_read_header. - */ - cinfo->marker_list = NULL; - jinit_marker_reader(cinfo); - - /* And initialize the overall input controller. */ - jinit_input_controller(cinfo); - - /* OK, I'm ready */ - cinfo->global_state = DSTATE_START; -} - - -/* - * Destruction of a JPEG decompression object - */ - -GLOBAL(void) -jpeg_destroy_decompress (j_decompress_ptr cinfo) -{ - jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Abort processing of a JPEG decompression operation, - * but don't destroy the object itself. - */ - -GLOBAL(void) -jpeg_abort_decompress (j_decompress_ptr cinfo) -{ - jpeg_abort((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Set default decompression parameters. - */ - -LOCAL(void) -default_decompress_parms (j_decompress_ptr cinfo) -{ - int cid0, cid1, cid2; - - /* Guess the input colorspace, and set output colorspace accordingly. */ - /* Note application may override our guesses. */ - switch (cinfo->num_components) { - case 1: - cinfo->jpeg_color_space = JCS_GRAYSCALE; - cinfo->out_color_space = JCS_GRAYSCALE; - break; - - case 3: - cid0 = cinfo->comp_info[0].component_id; - cid1 = cinfo->comp_info[1].component_id; - cid2 = cinfo->comp_info[2].component_id; - - /* First try to guess from the component IDs */ - if (cid0 == 0x01 && cid1 == 0x02 && cid2 == 0x03) - cinfo->jpeg_color_space = JCS_YCbCr; - else if (cid0 == 0x01 && cid1 == 0x22 && cid2 == 0x23) - cinfo->jpeg_color_space = JCS_BG_YCC; - else if (cid0 == 0x52 && cid1 == 0x47 && cid2 == 0x42) - cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ - else if (cid0 == 0x72 && cid1 == 0x67 && cid2 == 0x62) - cinfo->jpeg_color_space = JCS_BG_RGB; /* ASCII 'r', 'g', 'b' */ - else if (cinfo->saw_JFIF_marker) - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - else if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: - cinfo->jpeg_color_space = JCS_RGB; - break; - case 1: - cinfo->jpeg_color_space = JCS_YCbCr; - break; - default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - break; - } - } else { - TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - } - /* Always guess RGB is proper output colorspace. */ - cinfo->out_color_space = JCS_RGB; - break; - - case 4: - if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: - cinfo->jpeg_color_space = JCS_CMYK; - break; - case 2: - cinfo->jpeg_color_space = JCS_YCCK; - break; - default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ - break; - } - } else { - /* No special markers, assume straight CMYK. */ - cinfo->jpeg_color_space = JCS_CMYK; - } - cinfo->out_color_space = JCS_CMYK; - break; - - default: - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->out_color_space = JCS_UNKNOWN; - break; - } - - /* Set defaults for other decompression parameters. */ - cinfo->scale_num = cinfo->block_size; /* 1:1 scaling */ - cinfo->scale_denom = cinfo->block_size; - cinfo->output_gamma = 1.0; - cinfo->buffered_image = FALSE; - cinfo->raw_data_out = FALSE; - cinfo->dct_method = JDCT_DEFAULT; - cinfo->do_fancy_upsampling = TRUE; - cinfo->do_block_smoothing = TRUE; - cinfo->quantize_colors = FALSE; - /* We set these in case application only sets quantize_colors. */ - cinfo->dither_mode = JDITHER_FS; -#ifdef QUANT_2PASS_SUPPORTED - cinfo->two_pass_quantize = TRUE; -#else - cinfo->two_pass_quantize = FALSE; -#endif - cinfo->desired_number_of_colors = 256; - cinfo->colormap = NULL; - /* Initialize for no mode change in buffered-image mode. */ - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; -} - - -/* - * Decompression startup: read start of JPEG datastream to see what's there. - * Need only initialize JPEG object and supply a data source before calling. - * - * This routine will read as far as the first SOS marker (ie, actual start of - * compressed data), and will save all tables and parameters in the JPEG - * object. It will also initialize the decompression parameters to default - * values, and finally return JPEG_HEADER_OK. On return, the application may - * adjust the decompression parameters and then call jpeg_start_decompress. - * (Or, if the application only wanted to determine the image parameters, - * the data need not be decompressed. In that case, call jpeg_abort or - * jpeg_destroy to release any temporary space.) - * If an abbreviated (tables only) datastream is presented, the routine will - * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then - * re-use the JPEG object to read the abbreviated image datastream(s). - * It is unnecessary (but OK) to call jpeg_abort in this case. - * The JPEG_SUSPENDED return code only occurs if the data source module - * requests suspension of the decompressor. In this case the application - * should load more source data and then re-call jpeg_read_header to resume - * processing. - * If a non-suspending data source is used and require_image is TRUE, then the - * return code need not be inspected since only JPEG_HEADER_OK is possible. - * - * This routine is now just a front end to jpeg_consume_input, with some - * extra error checking. - */ - -GLOBAL(int) -jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) -{ - int retcode; - - if (cinfo->global_state != DSTATE_START && - cinfo->global_state != DSTATE_INHEADER) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - retcode = jpeg_consume_input(cinfo); - - switch (retcode) { - case JPEG_REACHED_SOS: - retcode = JPEG_HEADER_OK; - break; - case JPEG_REACHED_EOI: - if (require_image) /* Complain if application wanted an image */ - ERREXIT(cinfo, JERR_NO_IMAGE); - /* Reset to start state; it would be safer to require the application to - * call jpeg_abort, but we can't change it now for compatibility reasons. - * A side effect is to free any temporary memory (there shouldn't be any). - */ - jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ - retcode = JPEG_HEADER_TABLES_ONLY; - break; - case JPEG_SUSPENDED: - /* no work */ - break; - } - - return retcode; -} - - -/* - * Consume data in advance of what the decompressor requires. - * This can be called at any time once the decompressor object has - * been created and a data source has been set up. - * - * This routine is essentially a state machine that handles a couple - * of critical state-transition actions, namely initial setup and - * transition from header scanning to ready-for-start_decompress. - * All the actual input is done via the input controller's consume_input - * method. - */ - -GLOBAL(int) -jpeg_consume_input (j_decompress_ptr cinfo) -{ - int retcode = JPEG_SUSPENDED; - - /* NB: every possible DSTATE value should be listed in this switch */ - switch (cinfo->global_state) { - case DSTATE_START: - /* Start-of-datastream actions: reset appropriate modules */ - (*cinfo->inputctl->reset_input_controller) (cinfo); - /* Initialize application's data source module */ - (*cinfo->src->init_source) (cinfo); - cinfo->global_state = DSTATE_INHEADER; - /*FALLTHROUGH*/ - case DSTATE_INHEADER: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ - /* Set up default parameters based on header data */ - default_decompress_parms(cinfo); - /* Set global state: ready for start_decompress */ - cinfo->global_state = DSTATE_READY; - } - break; - case DSTATE_READY: - /* Can't advance past first SOS until start_decompress is called */ - retcode = JPEG_REACHED_SOS; - break; - case DSTATE_PRELOAD: - case DSTATE_PRESCAN: - case DSTATE_SCANNING: - case DSTATE_RAW_OK: - case DSTATE_BUFIMAGE: - case DSTATE_BUFPOST: - case DSTATE_STOPPING: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - break; - default: - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - return retcode; -} - - -/* - * Have we finished reading the input file? - */ - -GLOBAL(boolean) -jpeg_input_complete (j_decompress_ptr cinfo) -{ - /* Check for valid jpeg object */ - if (cinfo->global_state < DSTATE_START || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return cinfo->inputctl->eoi_reached; -} - - -/* - * Is there more than one scan? - */ - -GLOBAL(boolean) -jpeg_has_multiple_scans (j_decompress_ptr cinfo) -{ - /* Only valid after jpeg_read_header completes */ - if (cinfo->global_state < DSTATE_READY || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return cinfo->inputctl->has_multiple_scans; -} - - -/* - * Finish JPEG decompression. - * - * This will normally just verify the file trailer and release temp storage. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_finish_decompress (j_decompress_ptr cinfo) -{ - if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { - /* Terminate final pass of non-buffered mode */ - if (cinfo->output_scanline < cinfo->output_height) - ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_STOPPING; - } else if (cinfo->global_state == DSTATE_BUFIMAGE) { - /* Finishing after a buffered-image operation */ - cinfo->global_state = DSTATE_STOPPING; - } else if (cinfo->global_state != DSTATE_STOPPING) { - /* STOPPING = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - /* Read until EOI */ - while (! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ - } - /* Do final cleanup */ - (*cinfo->src->term_source) (cinfo); - /* We can use jpeg_abort to release memory and reset global_state */ - jpeg_abort((j_common_ptr) cinfo); - return TRUE; -} diff --git a/libraries/jpeg/jdapistd.c b/libraries/jpeg/jdapistd.c deleted file mode 100644 index 7f3a78b25a..0000000000 --- a/libraries/jpeg/jdapistd.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * jdapistd.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2002-2013 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the decompression half - * of the JPEG library. These are the "standard" API routines that are - * used in the normal full-decompression case. They are not used by a - * transcoding-only application. Note that if an application links in - * jpeg_start_decompress, it will end up linking in the entire decompressor. - * We thus must separate this file from jdapimin.c to avoid linking the - * whole decompression library into a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); - - -/* - * Decompression initialization. - * jpeg_read_header must be completed before calling this. - * - * If a multipass operating mode was selected, this will do all but the - * last pass, and thus may take a great deal of time. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_start_decompress (j_decompress_ptr cinfo) -{ - if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize master control, select active modules */ - jinit_master_decompress(cinfo); - if (cinfo->buffered_image) { - /* No more work here; expecting jpeg_start_output next */ - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; - } - cinfo->global_state = DSTATE_PRELOAD; - } - if (cinfo->global_state == DSTATE_PRELOAD) { - /* If file has multiple scans, absorb them all into the coef buffer */ - if (cinfo->inputctl->has_multiple_scans) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) - return FALSE; - if (retcode == JPEG_REACHED_EOI) - break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* jdmaster underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } - } - } -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - } - cinfo->output_scan_number = cinfo->input_scan_number; - } else if (cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Perform any dummy output passes, and set up for the final pass */ - return output_pass_setup(cinfo); -} - - -/* - * Set up for an output pass, and perform any dummy pass(es) needed. - * Common subroutine for jpeg_start_decompress and jpeg_start_output. - * Entry: global_state = DSTATE_PRESCAN only if previously suspended. - * Exit: If done, returns TRUE and sets global_state for proper output mode. - * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. - */ - -LOCAL(boolean) -output_pass_setup (j_decompress_ptr cinfo) -{ - if (cinfo->global_state != DSTATE_PRESCAN) { - /* First call: do pass setup */ - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; - cinfo->global_state = DSTATE_PRESCAN; - } - /* Loop over any required dummy passes */ - while (cinfo->master->is_dummy_pass) { -#ifdef QUANT_2PASS_SUPPORTED - /* Crank through the dummy pass */ - while (cinfo->output_scanline < cinfo->output_height) { - JDIMENSION last_scanline; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - /* Process some data */ - last_scanline = cinfo->output_scanline; - (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, - &cinfo->output_scanline, (JDIMENSION) 0); - if (cinfo->output_scanline == last_scanline) - return FALSE; /* No progress made, must suspend */ - } - /* Finish up dummy pass, and set up for another one */ - (*cinfo->master->finish_output_pass) (cinfo); - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* QUANT_2PASS_SUPPORTED */ - } - /* Ready for application to drive output pass through - * jpeg_read_scanlines or jpeg_read_raw_data. - */ - cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; - return TRUE; -} - - -/* - * Read some scanlines of data from the JPEG decompressor. - * - * The return value will be the number of lines actually read. - * This may be less than the number requested in several cases, - * including bottom of image, data source suspension, and operating - * modes that emit multiple scanlines at a time. - * - * Note: we warn about excess calls to jpeg_read_scanlines() since - * this likely signals an application programmer error. However, - * an oversize buffer (max_lines > scanlines remaining) is not an error. - */ - -GLOBAL(JDIMENSION) -jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) -{ - JDIMENSION row_ctr; - - if (cinfo->global_state != DSTATE_SCANNING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Process some data */ - row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); - cinfo->output_scanline += row_ctr; - return row_ctr; -} - - -/* - * Alternate entry point to read raw data. - * Processes exactly one iMCU row per call, unless suspended. - */ - -GLOBAL(JDIMENSION) -jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION max_lines) -{ - JDIMENSION lines_per_iMCU_row; - - if (cinfo->global_state != DSTATE_RAW_OK) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Verify that at least one iMCU row can be returned. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; - if (max_lines < lines_per_iMCU_row) - ERREXIT(cinfo, JERR_BUFFER_SIZE); - - /* Decompress directly into user's buffer. */ - if (! (*cinfo->coef->decompress_data) (cinfo, data)) - return 0; /* suspension forced, can do nothing more */ - - /* OK, we processed one iMCU row. */ - cinfo->output_scanline += lines_per_iMCU_row; - return lines_per_iMCU_row; -} - - -/* Additional entry points for buffered-image mode. */ - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Initialize for an output pass in buffered-image mode. - */ - -GLOBAL(boolean) -jpeg_start_output (j_decompress_ptr cinfo, int scan_number) -{ - if (cinfo->global_state != DSTATE_BUFIMAGE && - cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Limit scan number to valid range */ - if (scan_number <= 0) - scan_number = 1; - if (cinfo->inputctl->eoi_reached && - scan_number > cinfo->input_scan_number) - scan_number = cinfo->input_scan_number; - cinfo->output_scan_number = scan_number; - /* Perform any dummy output passes, and set up for the real pass */ - return output_pass_setup(cinfo); -} - - -/* - * Finish up after an output pass in buffered-image mode. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_finish_output (j_decompress_ptr cinfo) -{ - if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { - /* Terminate this pass. */ - /* We do not require the whole pass to have been completed. */ - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_BUFPOST; - } else if (cinfo->global_state != DSTATE_BUFPOST) { - /* BUFPOST = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - /* Read markers looking for SOS or EOI */ - while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ - } - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/libraries/jpeg/jdarith.c b/libraries/jpeg/jdarith.c deleted file mode 100644 index 5533c07397..0000000000 --- a/libraries/jpeg/jdarith.c +++ /dev/null @@ -1,796 +0,0 @@ -/* - * jdarith.c - * - * Developed 1997-2015 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains portable arithmetic entropy decoding routines for JPEG - * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). - * - * Both sequential and progressive modes are supported in this single module. - * - * Suspension is not currently supported in this module. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Expanded entropy decoder object for arithmetic decoding. */ - -typedef struct { - struct jpeg_entropy_decoder pub; /* public fields */ - - INT32 c; /* C register, base of coding interval + input bit buffer */ - INT32 a; /* A register, normalized size of coding interval */ - int ct; /* bit shift counter, # of bits left in bit buffer part of C */ - /* init: ct = -16 */ - /* run: ct = 0..7 */ - /* error: ct = -1 */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ - int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ - - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to statistics areas (these workspaces have image lifespan) */ - unsigned char * dc_stats[NUM_ARITH_TBLS]; - unsigned char * ac_stats[NUM_ARITH_TBLS]; - - /* Statistics bin for coding with fixed probability 0.5 */ - unsigned char fixed_bin[4]; -} arith_entropy_decoder; - -typedef arith_entropy_decoder * arith_entropy_ptr; - -/* The following two definitions specify the allocation chunk size - * for the statistics area. - * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least - * 49 statistics bins for DC, and 245 statistics bins for AC coding. - * - * We use a compact representation with 1 byte per statistics bin, - * thus the numbers directly represent byte sizes. - * This 1 byte per statistics bin contains the meaning of the MPS - * (more probable symbol) in the highest bit (mask 0x80), and the - * index into the probability estimation state machine table - * in the lower bits (mask 0x7F). - */ - -#define DC_STAT_BINS 64 -#define AC_STAT_BINS 256 - - -LOCAL(int) -get_byte (j_decompress_ptr cinfo) -/* Read next input byte; we do not support suspension in this module. */ -{ - struct jpeg_source_mgr * src = cinfo->src; - - if (src->bytes_in_buffer == 0) - if (! (*src->fill_input_buffer) (cinfo)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - src->bytes_in_buffer--; - return GETJOCTET(*src->next_input_byte++); -} - - -/* - * The core arithmetic decoding routine (common in JPEG and JBIG). - * This needs to go as fast as possible. - * Machine-dependent optimization facilities - * are not utilized in this portable implementation. - * However, this code should be fairly efficient and - * may be a good base for further optimizations anyway. - * - * Return value is 0 or 1 (binary decision). - * - * Note: I've changed the handling of the code base & bit - * buffer register C compared to other implementations - * based on the standards layout & procedures. - * While it also contains both the actual base of the - * coding interval (16 bits) and the next-bits buffer, - * the cut-point between these two parts is floating - * (instead of fixed) with the bit shift counter CT. - * Thus, we also need only one (variable instead of - * fixed size) shift for the LPS/MPS decision, and - * we can do away with any renormalization update - * of C (except for new data insertion, of course). - * - * I've also introduced a new scheme for accessing - * the probability estimation state machine table, - * derived from Markus Kuhn's JBIG implementation. - */ - -LOCAL(int) -arith_decode (j_decompress_ptr cinfo, unsigned char *st) -{ - register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; - register unsigned char nl, nm; - register INT32 qe, temp; - register int sv, data; - - /* Renormalization & data input per section D.2.6 */ - while (e->a < 0x8000L) { - if (--e->ct < 0) { - /* Need to fetch next data byte */ - if (cinfo->unread_marker) - data = 0; /* stuff zero data */ - else { - data = get_byte(cinfo); /* read next input byte */ - if (data == 0xFF) { /* zero stuff or marker code */ - do data = get_byte(cinfo); - while (data == 0xFF); /* swallow extra 0xFF bytes */ - if (data == 0) - data = 0xFF; /* discard stuffed zero byte */ - else { - /* Note: Different from the Huffman decoder, hitting - * a marker while processing the compressed data - * segment is legal in arithmetic coding. - * The convention is to supply zero data - * then until decoding is complete. - */ - cinfo->unread_marker = data; - data = 0; - } - } - } - e->c = (e->c << 8) | data; /* insert data into C register */ - if ((e->ct += 8) < 0) /* update bit shift counter */ - /* Need more initial bytes */ - if (++e->ct == 0) - /* Got 2 initial bytes -> re-init A and exit loop */ - e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */ - } - e->a <<= 1; - } - - /* Fetch values from our compact representation of Table D.3(D.2): - * Qe values and probability estimation state machine - */ - sv = *st; - qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ - nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ - nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ - - /* Decode & estimation procedures per sections D.2.4 & D.2.5 */ - temp = e->a - qe; - e->a = temp; - temp <<= e->ct; - if (e->c >= temp) { - e->c -= temp; - /* Conditional LPS (less probable symbol) exchange */ - if (e->a < qe) { - e->a = qe; - *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ - } else { - e->a = qe; - *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ - sv ^= 0x80; /* Exchange LPS/MPS */ - } - } else if (e->a < 0x8000L) { - /* Conditional MPS (more probable symbol) exchange */ - if (e->a < qe) { - *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ - sv ^= 0x80; /* Exchange LPS/MPS */ - } else { - *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ - } - } - - return sv >> 7; -} - - -/* - * Check for a restart marker & resynchronize decoder. - */ - -LOCAL(void) -process_restart (j_decompress_ptr cinfo) -{ - arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - int ci; - jpeg_component_info * compptr; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - - /* Re-initialize statistics areas */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { - MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); - /* Reset DC predictions to 0 */ - entropy->last_dc_val[ci] = 0; - entropy->dc_context[ci] = 0; - } - if ((! cinfo->progressive_mode && cinfo->lim_Se) || - (cinfo->progressive_mode && cinfo->Ss)) { - MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); - } - } - - /* Reset arithmetic decoding variables */ - entropy->c = 0; - entropy->a = 0; - entropy->ct = -16; /* force reading 2 initial bytes to fill C */ - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Arithmetic MCU decoding. - * Each of these routines decodes and returns one MCU's worth of - * arithmetic-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. - */ - -/* - * MCU decoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - JBLOCKROW block; - unsigned char *st; - int blkn, ci, tbl, sign; - int v, m; - - /* Process restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - process_restart(cinfo); - entropy->restarts_to_go--; - } - - if (entropy->ct == -1) return TRUE; /* if error do nothing */ - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; - - /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ - - /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ - st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; - - /* Figure F.19: Decode_DC_DIFF */ - if (arith_decode(cinfo, st) == 0) - entropy->dc_context[ci] = 0; - else { - /* Figure F.21: Decoding nonzero value v */ - /* Figure F.22: Decoding the sign of v */ - sign = arith_decode(cinfo, st + 1); - st += 2; st += sign; - /* Figure F.23: Decoding the magnitude category of v */ - if ((m = arith_decode(cinfo, st)) != 0) { - st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ - while (arith_decode(cinfo, st)) { - if ((m <<= 1) == 0x8000) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* magnitude overflow */ - return TRUE; - } - st += 1; - } - } - /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ - if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ - else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) - entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ - else - entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ - v = m; - /* Figure F.24: Decoding the magnitude bit pattern of v */ - st += 14; - while (m >>= 1) - if (arith_decode(cinfo, st)) v |= m; - v += 1; if (sign) v = -v; - entropy->last_dc_val[ci] += v; - } - - /* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */ - (*block)[0] = (JCOEF) (entropy->last_dc_val[ci] << cinfo->Al); - } - - return TRUE; -} - - -/* - * MCU decoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - JBLOCKROW block; - unsigned char *st; - int tbl, sign, k; - int v, m; - const int * natural_order; - - /* Process restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - process_restart(cinfo); - entropy->restarts_to_go--; - } - - if (entropy->ct == -1) return TRUE; /* if error do nothing */ - - natural_order = cinfo->natural_order; - - /* There is always only one block per MCU */ - block = MCU_data[0]; - tbl = cinfo->cur_comp_info[0]->ac_tbl_no; - - /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ - - /* Figure F.20: Decode_AC_coefficients */ - k = cinfo->Ss - 1; - do { - st = entropy->ac_stats[tbl] + 3 * k; - if (arith_decode(cinfo, st)) break; /* EOB flag */ - for (;;) { - k++; - if (arith_decode(cinfo, st + 1)) break; - st += 3; - if (k >= cinfo->Se) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* spectral overflow */ - return TRUE; - } - } - /* Figure F.21: Decoding nonzero value v */ - /* Figure F.22: Decoding the sign of v */ - sign = arith_decode(cinfo, entropy->fixed_bin); - st += 2; - /* Figure F.23: Decoding the magnitude category of v */ - if ((m = arith_decode(cinfo, st)) != 0) { - if (arith_decode(cinfo, st)) { - m <<= 1; - st = entropy->ac_stats[tbl] + - (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); - while (arith_decode(cinfo, st)) { - if ((m <<= 1) == 0x8000) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* magnitude overflow */ - return TRUE; - } - st += 1; - } - } - } - v = m; - /* Figure F.24: Decoding the magnitude bit pattern of v */ - st += 14; - while (m >>= 1) - if (arith_decode(cinfo, st)) v |= m; - v += 1; if (sign) v = -v; - /* Scale and output coefficient in natural (dezigzagged) order */ - (*block)[natural_order[k]] = (JCOEF) (v << cinfo->Al); - } while (k < cinfo->Se); - - return TRUE; -} - - -/* - * MCU decoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, - * although the spec is not very clear on the point. - */ - -METHODDEF(boolean) -decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - unsigned char *st; - int p1, blkn; - - /* Process restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - process_restart(cinfo); - entropy->restarts_to_go--; - } - - st = entropy->fixed_bin; /* use fixed probability estimation */ - p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - /* Encoded data is simply the next bit of the two's-complement DC value */ - if (arith_decode(cinfo, st)) - MCU_data[blkn][0][0] |= p1; - } - - return TRUE; -} - - -/* - * MCU decoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - JBLOCKROW block; - JCOEFPTR thiscoef; - unsigned char *st; - int tbl, k, kex; - int p1, m1; - const int * natural_order; - - /* Process restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - process_restart(cinfo); - entropy->restarts_to_go--; - } - - if (entropy->ct == -1) return TRUE; /* if error do nothing */ - - natural_order = cinfo->natural_order; - - /* There is always only one block per MCU */ - block = MCU_data[0]; - tbl = cinfo->cur_comp_info[0]->ac_tbl_no; - - p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ - - /* Establish EOBx (previous stage end-of-block) index */ - kex = cinfo->Se; - do { - if ((*block)[natural_order[kex]]) break; - } while (--kex); - - k = cinfo->Ss - 1; - do { - st = entropy->ac_stats[tbl] + 3 * k; - if (k >= kex) - if (arith_decode(cinfo, st)) break; /* EOB flag */ - for (;;) { - thiscoef = *block + natural_order[++k]; - if (*thiscoef) { /* previously nonzero coef */ - if (arith_decode(cinfo, st + 2)) { - if (*thiscoef < 0) - *thiscoef += m1; - else - *thiscoef += p1; - } - break; - } - if (arith_decode(cinfo, st + 1)) { /* newly nonzero coef */ - if (arith_decode(cinfo, entropy->fixed_bin)) - *thiscoef = m1; - else - *thiscoef = p1; - break; - } - st += 3; - if (k >= cinfo->Se) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* spectral overflow */ - return TRUE; - } - } - } while (k < cinfo->Se); - - return TRUE; -} - - -/* - * Decode one MCU's worth of arithmetic-compressed coefficients. - */ - -METHODDEF(boolean) -decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - jpeg_component_info * compptr; - JBLOCKROW block; - unsigned char *st; - int blkn, ci, tbl, sign, k; - int v, m; - const int * natural_order; - - /* Process restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - process_restart(cinfo); - entropy->restarts_to_go--; - } - - if (entropy->ct == -1) return TRUE; /* if error do nothing */ - - natural_order = cinfo->natural_order; - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - - /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ - - tbl = compptr->dc_tbl_no; - - /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ - st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; - - /* Figure F.19: Decode_DC_DIFF */ - if (arith_decode(cinfo, st) == 0) - entropy->dc_context[ci] = 0; - else { - /* Figure F.21: Decoding nonzero value v */ - /* Figure F.22: Decoding the sign of v */ - sign = arith_decode(cinfo, st + 1); - st += 2; st += sign; - /* Figure F.23: Decoding the magnitude category of v */ - if ((m = arith_decode(cinfo, st)) != 0) { - st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ - while (arith_decode(cinfo, st)) { - if ((m <<= 1) == 0x8000) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* magnitude overflow */ - return TRUE; - } - st += 1; - } - } - /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ - if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ - else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) - entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ - else - entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ - v = m; - /* Figure F.24: Decoding the magnitude bit pattern of v */ - st += 14; - while (m >>= 1) - if (arith_decode(cinfo, st)) v |= m; - v += 1; if (sign) v = -v; - entropy->last_dc_val[ci] += v; - } - - (*block)[0] = (JCOEF) entropy->last_dc_val[ci]; - - /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ - - if (cinfo->lim_Se == 0) continue; - tbl = compptr->ac_tbl_no; - k = 0; - - /* Figure F.20: Decode_AC_coefficients */ - do { - st = entropy->ac_stats[tbl] + 3 * k; - if (arith_decode(cinfo, st)) break; /* EOB flag */ - for (;;) { - k++; - if (arith_decode(cinfo, st + 1)) break; - st += 3; - if (k >= cinfo->lim_Se) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* spectral overflow */ - return TRUE; - } - } - /* Figure F.21: Decoding nonzero value v */ - /* Figure F.22: Decoding the sign of v */ - sign = arith_decode(cinfo, entropy->fixed_bin); - st += 2; - /* Figure F.23: Decoding the magnitude category of v */ - if ((m = arith_decode(cinfo, st)) != 0) { - if (arith_decode(cinfo, st)) { - m <<= 1; - st = entropy->ac_stats[tbl] + - (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); - while (arith_decode(cinfo, st)) { - if ((m <<= 1) == 0x8000) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* magnitude overflow */ - return TRUE; - } - st += 1; - } - } - } - v = m; - /* Figure F.24: Decoding the magnitude bit pattern of v */ - st += 14; - while (m >>= 1) - if (arith_decode(cinfo, st)) v |= m; - v += 1; if (sign) v = -v; - (*block)[natural_order[k]] = (JCOEF) v; - } while (k < cinfo->lim_Se); - } - - return TRUE; -} - - -/* - * Initialize for an arithmetic-compressed scan. - */ - -METHODDEF(void) -start_pass (j_decompress_ptr cinfo) -{ - arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - int ci, tbl; - jpeg_component_info * compptr; - - if (cinfo->progressive_mode) { - /* Validate progressive scan parameters */ - if (cinfo->Ss == 0) { - if (cinfo->Se != 0) - goto bad; - } else { - /* need not check Ss/Se < 0 since they came from unsigned bytes */ - if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) - goto bad; - /* AC scans may have only one component */ - if (cinfo->comps_in_scan != 1) - goto bad; - } - if (cinfo->Ah != 0) { - /* Successive approximation refinement scan: must have Al = Ah-1. */ - if (cinfo->Ah-1 != cinfo->Al) - goto bad; - } - if (cinfo->Al > 13) { /* need not check for < 0 */ - bad: - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - } - /* Update progression status, and verify that scan order is legal. - * Note that inter-scan inconsistencies are treated as warnings - * not fatal errors ... not clear if this is right way to behave. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; - int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; - if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); - for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; - } - } - /* Select MCU decoding routine */ - if (cinfo->Ah == 0) { - if (cinfo->Ss == 0) - entropy->pub.decode_mcu = decode_mcu_DC_first; - else - entropy->pub.decode_mcu = decode_mcu_AC_first; - } else { - if (cinfo->Ss == 0) - entropy->pub.decode_mcu = decode_mcu_DC_refine; - else - entropy->pub.decode_mcu = decode_mcu_AC_refine; - } - } else { - /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. - * This ought to be an error condition, but we make it a warning. - */ - if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || - (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); - /* Select MCU decoding routine */ - entropy->pub.decode_mcu = decode_mcu; - } - - /* Allocate & initialize requested statistics areas */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { - tbl = compptr->dc_tbl_no; - if (tbl < 0 || tbl >= NUM_ARITH_TBLS) - ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); - if (entropy->dc_stats[tbl] == NULL) - entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); - MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); - /* Initialize DC predictions to 0 */ - entropy->last_dc_val[ci] = 0; - entropy->dc_context[ci] = 0; - } - if ((! cinfo->progressive_mode && cinfo->lim_Se) || - (cinfo->progressive_mode && cinfo->Ss)) { - tbl = compptr->ac_tbl_no; - if (tbl < 0 || tbl >= NUM_ARITH_TBLS) - ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); - if (entropy->ac_stats[tbl] == NULL) - entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); - MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); - } - } - - /* Initialize arithmetic decoding variables */ - entropy->c = 0; - entropy->a = 0; - entropy->ct = -16; /* force reading 2 initial bytes to fill C */ - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Finish up at the end of an arithmetic-compressed scan. - */ - -METHODDEF(void) -finish_pass (j_decompress_ptr cinfo) -{ - /* no work necessary here */ -} - - -/* - * Module initialization routine for arithmetic entropy decoding. - */ - -GLOBAL(void) -jinit_arith_decoder (j_decompress_ptr cinfo) -{ - arith_entropy_ptr entropy; - int i; - - entropy = (arith_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(arith_entropy_decoder)); - cinfo->entropy = &entropy->pub; - entropy->pub.start_pass = start_pass; - entropy->pub.finish_pass = finish_pass; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_ARITH_TBLS; i++) { - entropy->dc_stats[i] = NULL; - entropy->ac_stats[i] = NULL; - } - - /* Initialize index for fixed probability estimation */ - entropy->fixed_bin[0] = 113; - - if (cinfo->progressive_mode) { - /* Create progression status table */ - int *coef_bit_ptr, ci; - cinfo->coef_bits = (int (*)[DCTSIZE2]) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components*DCTSIZE2*SIZEOF(int)); - coef_bit_ptr = & cinfo->coef_bits[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; - } -} diff --git a/libraries/jpeg/jdatasrc.c b/libraries/jpeg/jdatasrc.c deleted file mode 100644 index 2a27cfed80..0000000000 --- a/libraries/jpeg/jdatasrc.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * jdatasrc.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2009-2015 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains decompression data source routines for the case of - * reading JPEG data from memory or from a file (or any stdio stream). - * While these routines are sufficient for most applications, - * some will want to use a different source manager. - * IMPORTANT: we assume that fread() will correctly transcribe an array of - * JOCTETs from 8-bit-wide elements on external storage. If char is wider - * than 8 bits on your machine, you may need to do some tweaking. - */ - -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jerror.h" - - -/* Expanded data source object for stdio input */ - -typedef struct { - struct jpeg_source_mgr pub; /* public fields */ - - FILE * infile; /* source stream */ - JOCTET * buffer; /* start of buffer */ - boolean start_of_file; /* have we gotten any data yet? */ -} my_source_mgr; - -typedef my_source_mgr * my_src_ptr; - -#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ - - -/* - * Initialize source --- called by jpeg_read_header - * before any data is actually read. - */ - -METHODDEF(void) -init_source (j_decompress_ptr cinfo) -{ - my_src_ptr src = (my_src_ptr) cinfo->src; - - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - src->start_of_file = TRUE; -} - -METHODDEF(void) -init_mem_source (j_decompress_ptr cinfo) -{ - /* no work necessary here */ -} - - -/* - * Fill the input buffer --- called whenever buffer is emptied. - * - * In typical applications, this should read fresh data into the buffer - * (ignoring the current state of next_input_byte & bytes_in_buffer), - * reset the pointer & count to the start of the buffer, and return TRUE - * indicating that the buffer has been reloaded. It is not necessary to - * fill the buffer entirely, only to obtain at least one more byte. - * - * There is no such thing as an EOF return. If the end of the file has been - * reached, the routine has a choice of ERREXIT() or inserting fake data into - * the buffer. In most cases, generating a warning message and inserting a - * fake EOI marker is the best course of action --- this will allow the - * decompressor to output however much of the image is there. However, - * the resulting error message is misleading if the real problem is an empty - * input file, so we handle that case specially. - * - * In applications that need to be able to suspend compression due to input - * not being available yet, a FALSE return indicates that no more data can be - * obtained right now, but more may be forthcoming later. In this situation, - * the decompressor will return to its caller (with an indication of the - * number of scanlines it has read, if any). The application should resume - * decompression after it has loaded more data into the input buffer. Note - * that there are substantial restrictions on the use of suspension --- see - * the documentation. - * - * When suspending, the decompressor will back up to a convenient restart point - * (typically the start of the current MCU). next_input_byte & bytes_in_buffer - * indicate where the restart point will be if the current call returns FALSE. - * Data beyond this point must be rescanned after resumption, so move it to - * the front of the buffer rather than discarding it. - */ - -METHODDEF(boolean) -fill_input_buffer (j_decompress_ptr cinfo) -{ - my_src_ptr src = (my_src_ptr) cinfo->src; - size_t nbytes; - - nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); - - if (nbytes <= 0) { - if (src->start_of_file) /* Treat empty input file as fatal error */ - ERREXIT(cinfo, JERR_INPUT_EMPTY); - WARNMS(cinfo, JWRN_JPEG_EOF); - /* Insert a fake EOI marker */ - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - nbytes = 2; - } - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = FALSE; - - return TRUE; -} - -METHODDEF(boolean) -fill_mem_input_buffer (j_decompress_ptr cinfo) -{ - static const JOCTET mybuffer[4] = { - (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0 - }; - - /* The whole JPEG data is expected to reside in the supplied memory - * buffer, so any request for more data beyond the given buffer size - * is treated as an error. - */ - WARNMS(cinfo, JWRN_JPEG_EOF); - - /* Insert a fake EOI marker */ - - cinfo->src->next_input_byte = mybuffer; - cinfo->src->bytes_in_buffer = 2; - - return TRUE; -} - - -/* - * Skip data --- used to skip over a potentially large amount of - * uninteresting data (such as an APPn marker). - * - * Writers of suspendable-input applications must note that skip_input_data - * is not granted the right to give a suspension return. If the skip extends - * beyond the data currently in the buffer, the buffer can be marked empty so - * that the next read will cause a fill_input_buffer call that can suspend. - * Arranging for additional bytes to be discarded before reloading the input - * buffer is the application writer's problem. - */ - -METHODDEF(void) -skip_input_data (j_decompress_ptr cinfo, long num_bytes) -{ - struct jpeg_source_mgr * src = cinfo->src; - - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if (num_bytes > 0) { - while (num_bytes > (long) src->bytes_in_buffer) { - num_bytes -= (long) src->bytes_in_buffer; - (void) (*src->fill_input_buffer) (cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->next_input_byte += (size_t) num_bytes; - src->bytes_in_buffer -= (size_t) num_bytes; - } -} - - -/* - * An additional method that can be provided by data source modules is the - * resync_to_restart method for error recovery in the presence of RST markers. - * For the moment, this source module just uses the default resync method - * provided by the JPEG library. That method assumes that no backtracking - * is possible. - */ - - -/* - * Terminate source --- called by jpeg_finish_decompress - * after all data has been read. Often a no-op. - * - * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding - * application must deal with any cleanup that should happen even - * for error exit. - */ - -METHODDEF(void) -term_source (j_decompress_ptr cinfo) -{ - /* no work necessary here */ -} - - -/* - * Prepare for input from a stdio stream. - * The caller must have already opened the stream, and is responsible - * for closing it after finishing decompression. - */ - -GLOBAL(void) -jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) -{ - my_src_ptr src; - - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling jpeg_stdio_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_source_mgr)); - src = (my_src_ptr) cinfo->src; - src->buffer = (JOCTET *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * SIZEOF(JOCTET)); - } - - src = (my_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = term_source; - src->infile = infile; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ -} - - -/* - * Prepare for input from a supplied memory buffer. - * The buffer must contain the whole JPEG data. - */ - -GLOBAL(void) -jpeg_mem_src (j_decompress_ptr cinfo, - const unsigned char * inbuffer, unsigned long insize) -{ - struct jpeg_source_mgr * src; - - if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ - ERREXIT(cinfo, JERR_INPUT_EMPTY); - - /* The source object is made permanent so that a series of JPEG images - * can be read from the same buffer by calling jpeg_mem_src only before - * the first one. - */ - if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(struct jpeg_source_mgr)); - } - - src = cinfo->src; - src->init_source = init_mem_source; - src->fill_input_buffer = fill_mem_input_buffer; - src->skip_input_data = skip_input_data; - src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->term_source = term_source; - src->bytes_in_buffer = (size_t) insize; - src->next_input_byte = (const JOCTET *) inbuffer; -} diff --git a/libraries/jpeg/jdcoefct.c b/libraries/jpeg/jdcoefct.c deleted file mode 100644 index ed02fc378f..0000000000 --- a/libraries/jpeg/jdcoefct.c +++ /dev/null @@ -1,741 +0,0 @@ -/* - * jdcoefct.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * Modified 2002-2011 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the coefficient buffer controller for decompression. - * This controller is the top level of the JPEG decompressor proper. - * The coefficient buffer lies between entropy decoding and inverse-DCT steps. - * - * In buffered-image mode, this controller is the interface between - * input-oriented processing and output-oriented processing. - * Also, the input side (only) is used when reading a file for transcoding. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -/* Block smoothing is only applicable for progressive JPEG, so: */ -#ifndef D_PROGRESSIVE_SUPPORTED -#undef BLOCK_SMOOTHING_SUPPORTED -#endif - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_coef_controller pub; /* public fields */ - - /* These variables keep track of the current location of the input side. */ - /* cinfo->input_iMCU_row is also used for this. */ - JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* The output side's location is represented by cinfo->output_iMCU_row. */ - - /* In single-pass modes, it's sufficient to buffer just one MCU. - * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, - * and let the entropy decoder write into that workspace each time. - * (On 80x86, the workspace is FAR even though it's not really very big; - * this is to keep the module interfaces unchanged when a large coefficient - * buffer is necessary.) - * In multi-pass modes, this array points to the current MCU's blocks - * within the virtual arrays; it is used only by the input side. - */ - JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* In multi-pass modes, we need a virtual block array for each component. */ - jvirt_barray_ptr whole_image[MAX_COMPONENTS]; -#endif - -#ifdef BLOCK_SMOOTHING_SUPPORTED - /* When doing block smoothing, we latch coefficient Al values here */ - int * coef_bits_latch; -#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ -#endif -} my_coef_controller; - -typedef my_coef_controller * my_coef_ptr; - -/* Forward declarations */ -METHODDEF(int) decompress_onepass - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#ifdef D_MULTISCAN_FILES_SUPPORTED -METHODDEF(int) decompress_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif -#ifdef BLOCK_SMOOTHING_SUPPORTED -LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); -METHODDEF(int) decompress_smooth_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif - - -LOCAL(void) -start_iMCU_row (j_decompress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row (input side) */ -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; - } else { - if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - coef->MCU_ctr = 0; - coef->MCU_vert_offset = 0; -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - cinfo->input_iMCU_row = 0; - start_iMCU_row(cinfo); -} - - -/* - * Initialize for an output processing pass. - */ - -METHODDEF(void) -start_output_pass (j_decompress_ptr cinfo) -{ -#ifdef BLOCK_SMOOTHING_SUPPORTED - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* If multipass, check to see whether to use block smoothing on this pass */ - if (coef->pub.coef_arrays != NULL) { - if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) - coef->pub.decompress_data = decompress_smooth_data; - else - coef->pub.decompress_data = decompress_data; - } -#endif - cinfo->output_iMCU_row = 0; -} - - -/* - * Decompress and return some data in the single-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Input and output must run in lockstep since we have only a one-MCU buffer. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - -METHODDEF(int) -decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int blkn, ci, xindex, yindex, yoffset, useful_width; - JSAMPARRAY output_ptr; - JDIMENSION start_col, output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - - /* Loop to process as much as one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; - MCU_col_num++) { - /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ - if (cinfo->lim_Se) /* can bypass in DC only case */ - FMEMZERO((void FAR *) coef->MCU_buffer[0], - (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; - } - /* Determine where data should go in output_buf and do the IDCT thing. - * We skip dummy blocks at the right and bottom edges (but blkn gets - * incremented past them!). Note the inner loop relies on having - * allocated the MCU_buffer[] blocks sequentially. - */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) { - blkn += compptr->MCU_blocks; - continue; - } - inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; - useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - output_ptr = output_buf[compptr->component_index] + - yoffset * compptr->DCT_v_scaled_size; - start_col = MCU_col_num * compptr->MCU_sample_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (cinfo->input_iMCU_row < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - output_col = start_col; - for (xindex = 0; xindex < useful_width; xindex++) { - (*inverse_DCT) (cinfo, compptr, - (JCOEFPTR) coef->MCU_buffer[blkn+xindex], - output_ptr, output_col); - output_col += compptr->DCT_h_scaled_size; - } - } - blkn += compptr->MCU_width; - output_ptr += compptr->DCT_v_scaled_size; - } - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - cinfo->output_iMCU_row++; - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Dummy consume-input routine for single-pass operation. - */ - -METHODDEF(int) -dummy_consume_data (j_decompress_ptr cinfo) -{ - return JPEG_SUSPENDED; /* Always indicate nothing was done */ -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Consume input data and store it in the full-image coefficient buffer. - * We read as much as one fully interleaved MCU row ("iMCU" row) per call, - * ie, v_samp_factor block rows for each component in the scan. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - */ - -METHODDEF(int) -consume_data (j_decompress_ptr cinfo) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - int blkn, ci, xindex, yindex, yoffset; - JDIMENSION start_col; - JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW buffer_ptr; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - cinfo->input_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - /* Note: entropy decoder expects buffer to be zeroed, - * but this is handled automatically by the memory manager - * because we requested a pre-zeroed array. - */ - } - - /* Loop to process one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; - } - } - } - /* Try to fetch the MCU. */ - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Decompress and return some data in the multi-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image. - */ - -METHODDEF(int) -decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION block_num; - int ci, block_row, block_rows; - JBLOCKARRAY buffer; - JBLOCKROW buffer_ptr; - JSAMPARRAY output_ptr; - JDIMENSION output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number < cinfo->output_scan_number || - (cinfo->input_scan_number == cinfo->output_scan_number && - cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - cinfo->output_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) - block_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - output_col = 0; - for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { - (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, - output_ptr, output_col); - buffer_ptr++; - output_col += compptr->DCT_h_scaled_size; - } - output_ptr += compptr->DCT_v_scaled_size; - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -#ifdef BLOCK_SMOOTHING_SUPPORTED - -/* - * This code applies interblock smoothing as described by section K.8 - * of the JPEG standard: the first 5 AC coefficients are estimated from - * the DC values of a DCT block and its 8 neighboring blocks. - * We apply smoothing only for progressive JPEG decoding, and only if - * the coefficients it can estimate are not yet known to full precision. - */ - -/* Natural-order array positions of the first 5 zigzag-order coefficients */ -#define Q01_POS 1 -#define Q10_POS 8 -#define Q20_POS 16 -#define Q11_POS 9 -#define Q02_POS 2 - -/* - * Determine whether block smoothing is applicable and safe. - * We also latch the current states of the coef_bits[] entries for the - * AC coefficients; otherwise, if the input side of the decompressor - * advances into a new scan, we might think the coefficients are known - * more accurately than they really are. - */ - -LOCAL(boolean) -smoothing_ok (j_decompress_ptr cinfo) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - boolean smoothing_useful = FALSE; - int ci, coefi; - jpeg_component_info *compptr; - JQUANT_TBL * qtable; - int * coef_bits; - int * coef_bits_latch; - - if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) - return FALSE; - - /* Allocate latch area if not already done */ - if (coef->coef_bits_latch == NULL) - coef->coef_bits_latch = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * - (SAVED_COEFS * SIZEOF(int))); - coef_bits_latch = coef->coef_bits_latch; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* All components' quantization values must already be latched. */ - if ((qtable = compptr->quant_table) == NULL) - return FALSE; - /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ - if (qtable->quantval[0] == 0 || - qtable->quantval[Q01_POS] == 0 || - qtable->quantval[Q10_POS] == 0 || - qtable->quantval[Q20_POS] == 0 || - qtable->quantval[Q11_POS] == 0 || - qtable->quantval[Q02_POS] == 0) - return FALSE; - /* DC values must be at least partly known for all components. */ - coef_bits = cinfo->coef_bits[ci]; - if (coef_bits[0] < 0) - return FALSE; - /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ - for (coefi = 1; coefi <= 5; coefi++) { - coef_bits_latch[coefi] = coef_bits[coefi]; - if (coef_bits[coefi] != 0) - smoothing_useful = TRUE; - } - coef_bits_latch += SAVED_COEFS; - } - - return smoothing_useful; -} - - -/* - * Variant of decompress_data for use when doing block smoothing. - */ - -METHODDEF(int) -decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION block_num, last_block_column; - int ci, block_row, block_rows, access_rows; - JBLOCKARRAY buffer; - JBLOCKROW buffer_ptr, prev_block_row, next_block_row; - JSAMPARRAY output_ptr; - JDIMENSION output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - boolean first_row, last_row; - JBLOCK workspace; - int *coef_bits; - JQUANT_TBL *quanttbl; - INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; - int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; - int Al, pred; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { - if (cinfo->input_scan_number == cinfo->output_scan_number) { - /* If input is working on current scan, we ordinarily want it to - * have completed the current row. But if input scan is DC, - * we want it to keep one row ahead so that next block row's DC - * values are up to date. - */ - JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; - if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) - break; - } - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) { - block_rows = compptr->v_samp_factor; - access_rows = block_rows * 2; /* this and next iMCU row */ - last_row = FALSE; - } else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - access_rows = block_rows; /* this iMCU row only */ - last_row = TRUE; - } - /* Align the virtual buffer for this component. */ - if (cinfo->output_iMCU_row > 0) { - access_rows += compptr->v_samp_factor; /* prior iMCU row too */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, - (JDIMENSION) access_rows, FALSE); - buffer += compptr->v_samp_factor; /* point to current iMCU row */ - first_row = FALSE; - } else { - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); - first_row = TRUE; - } - /* Fetch component-dependent info */ - coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); - quanttbl = compptr->quant_table; - Q00 = quanttbl->quantval[0]; - Q01 = quanttbl->quantval[Q01_POS]; - Q10 = quanttbl->quantval[Q10_POS]; - Q20 = quanttbl->quantval[Q20_POS]; - Q11 = quanttbl->quantval[Q11_POS]; - Q02 = quanttbl->quantval[Q02_POS]; - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - if (first_row && block_row == 0) - prev_block_row = buffer_ptr; - else - prev_block_row = buffer[block_row-1]; - if (last_row && block_row == block_rows-1) - next_block_row = buffer_ptr; - else - next_block_row = buffer[block_row+1]; - /* We fetch the surrounding DC values using a sliding-register approach. - * Initialize all nine here so as to do the right thing on narrow pics. - */ - DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; - DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; - DC7 = DC8 = DC9 = (int) next_block_row[0][0]; - output_col = 0; - last_block_column = compptr->width_in_blocks - 1; - for (block_num = 0; block_num <= last_block_column; block_num++) { - /* Fetch current DCT block into workspace so we can modify it. */ - jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); - /* Update DC values */ - if (block_num < last_block_column) { - DC3 = (int) prev_block_row[1][0]; - DC6 = (int) buffer_ptr[1][0]; - DC9 = (int) next_block_row[1][0]; - } - /* Compute coefficient estimates per K.8. - * An estimate is applied only if coefficient is still zero, - * and is not known to be fully accurate. - */ - /* AC01 */ - if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { - num = 36 * Q00 * (DC4 - DC6); - if (num >= 0) { - pred = (int) (((Q01<<7) + num) / (Q01<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q10<<7) + num) / (Q10<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q20<<7) + num) / (Q20<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q11<<7) + num) / (Q11<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q02<<7) + num) / (Q02<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_h_scaled_size; - } - output_ptr += compptr->DCT_v_scaled_size; - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* BLOCK_SMOOTHING_SUPPORTED */ - - -/* - * Initialize coefficient buffer controller. - */ - -GLOBAL(void) -jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_coef_ptr coef; - - coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); - cinfo->coef = (struct jpeg_d_coef_controller *) coef; - coef->pub.start_input_pass = start_input_pass; - coef->pub.start_output_pass = start_output_pass; -#ifdef BLOCK_SMOOTHING_SUPPORTED - coef->coef_bits_latch = NULL; -#endif - - /* Create the coefficient buffer. */ - if (need_full_buffer) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor DCT blocks in each direction. */ - /* Note we ask for a pre-zeroed array. */ - int ci, access_rows; - jpeg_component_info *compptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - access_rows = compptr->v_samp_factor; -#ifdef BLOCK_SMOOTHING_SUPPORTED - /* If block smoothing could be used, need a bigger window */ - if (cinfo->progressive_mode) - access_rows *= 3; -#endif - coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, - (JDIMENSION) jround_up((long) compptr->width_in_blocks, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor), - (JDIMENSION) access_rows); - } - coef->pub.consume_data = consume_data; - coef->pub.decompress_data = decompress_data; - coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - /* We only need a single-MCU buffer. */ - JBLOCKROW buffer; - int i; - - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { - coef->MCU_buffer[i] = buffer + i; - } - if (cinfo->lim_Se == 0) /* DC only case: want to bypass later */ - FMEMZERO((void FAR *) buffer, - (size_t) (D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK))); - coef->pub.consume_data = dummy_consume_data; - coef->pub.decompress_data = decompress_onepass; - coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ - } -} diff --git a/libraries/jpeg/jdcolor.c b/libraries/jpeg/jdcolor.c deleted file mode 100644 index 0316354dac..0000000000 --- a/libraries/jpeg/jdcolor.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * jdcolor.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2011-2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains output colorspace conversion routines. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -#if RANGE_BITS < 2 - /* Deliberate syntax err */ - Sorry, this code requires 2 or more range extension bits. -#endif - - -/* Private subobject */ - -typedef struct { - struct jpeg_color_deconverter pub; /* public fields */ - - /* Private state for YCbCr->RGB and BG_YCC->RGB conversion */ - int * Cr_r_tab; /* => table for Cr to R conversion */ - int * Cb_b_tab; /* => table for Cb to B conversion */ - INT32 * Cr_g_tab; /* => table for Cr to G conversion */ - INT32 * Cb_g_tab; /* => table for Cb to G conversion */ - - /* Private state for RGB->Y conversion */ - INT32 * rgb_y_tab; /* => table for RGB to Y conversion */ -} my_color_deconverter; - -typedef my_color_deconverter * my_cconvert_ptr; - - -/*************** YCbCr -> RGB conversion: most common case **************/ -/*************** BG_YCC -> RGB conversion: less common case **************/ -/*************** RGB -> Y conversion: less common case **************/ - -/* - * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011), - * previously known as Recommendation CCIR 601-1, except that Cb and Cr - * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999. - * sYCC (standard luma-chroma-chroma color space with extended gamut) - * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F. - * bg-sRGB and bg-sYCC (big gamut standard color spaces) - * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G. - * Note that the derived conversion coefficients given in some of these - * documents are imprecise. The general conversion equations are - * - * R = Y + K * (1 - Kr) * Cr - * G = Y - K * (Kb * (1 - Kb) * Cb + Kr * (1 - Kr) * Cr) / (1 - Kr - Kb) - * B = Y + K * (1 - Kb) * Cb - * - * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B - * - * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993 - * from the 1953 FCC NTSC primaries and CIE Illuminant C), K = 2 for sYCC, - * the conversion equations to be implemented are therefore - * - * R = Y + 1.402 * Cr - * G = Y - 0.344136286 * Cb - 0.714136286 * Cr - * B = Y + 1.772 * Cb - * - * Y = 0.299 * R + 0.587 * G + 0.114 * B - * - * where Cb and Cr represent the incoming values less CENTERJSAMPLE. - * For bg-sYCC, with K = 4, the equations are - * - * R = Y + 2.804 * Cr - * G = Y - 0.688272572 * Cb - 1.428272572 * Cr - * B = Y + 3.544 * Cb - * - * To avoid floating-point arithmetic, we represent the fractional constants - * as integers scaled up by 2^16 (about 4 digits precision); we have to divide - * the products by 2^16, with appropriate rounding, to get the correct answer. - * Notice that Y, being an integral input, does not contribute any fraction - * so it need not participate in the rounding. - * - * For even more speed, we avoid doing any multiplications in the inner loop - * by precalculating the constants times Cb and Cr for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 9-bit to 12-bit samples it is still acceptable. It's not very - * reasonable for 16-bit samples, but if you want lossless storage you - * shouldn't be changing colorspace anyway. - * The Cr=>R and Cb=>B values can be rounded to integers in advance; the - * values for the G calculation are left scaled up, since we must add them - * together before rounding. - */ - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L<Y conversion and divide it up into - * three parts, instead of doing three alloc_small requests. This lets us - * use a single table base address, which can be held in a register in the - * inner loops on many machines (more than can hold all three addresses, - * anyway). - */ - -#define R_Y_OFF 0 /* offset to R => Y section */ -#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ -#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ -#define TABLE_SIZE (3*(MAXJSAMPLE+1)) - - -/* - * Initialize tables for YCbCr->RGB and BG_YCC->RGB colorspace conversion. - */ - -LOCAL(void) -build_ycc_rgb_table (j_decompress_ptr cinfo) -/* Normal case, sYCC */ -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - int i; - INT32 x; - SHIFT_TEMPS - - cconvert->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - cconvert->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.402 * x */ - cconvert->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.402) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.772 * x */ - cconvert->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.772) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.714136286 * x */ - cconvert->Cr_g_tab[i] = (- FIX(0.714136286)) * x; - /* Cb=>G value is scaled-up -0.344136286 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - cconvert->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF; - } -} - - -LOCAL(void) -build_bg_ycc_rgb_table (j_decompress_ptr cinfo) -/* Wide gamut case, bg-sYCC */ -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - int i; - INT32 x; - SHIFT_TEMPS - - cconvert->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - cconvert->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 2.804 * x */ - cconvert->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(2.804) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 3.544 * x */ - cconvert->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(3.544) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -1.428272572 * x */ - cconvert->Cr_g_tab[i] = (- FIX(1.428272572)) * x; - /* Cb=>G value is scaled-up -0.688272572 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - cconvert->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF; - } -} - - -/* - * Convert some rows of samples to the output colorspace. - * - * Note that we change from noninterleaved, one-plane-per-component format - * to interleaved-pixel format. The output buffer is therefore three times - * as wide as the input buffer. - * A starting row offset is provided only for the input buffer. The caller - * can easily adjust the passed output_buf value to accommodate any row - * offset required on that side. - */ - -METHODDEF(void) -ycc_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses, - * for extended gamut (sYCC) and wide gamut (bg-sYCC) encodings. - */ - outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; - outptr[RGB_GREEN] = range_limit[y + - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS))]; - outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/**************** Cases other than YCC -> RGB ****************/ - - -/* - * Initialize for RGB->grayscale colorspace conversion. - */ - -LOCAL(void) -build_rgb_y_table (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - INT32 * rgb_y_tab; - INT32 i; - - /* Allocate and fill in the conversion tables. */ - cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (TABLE_SIZE * SIZEOF(INT32))); - - for (i = 0; i <= MAXJSAMPLE; i++) { - rgb_y_tab[i+R_Y_OFF] = FIX(0.299) * i; - rgb_y_tab[i+G_Y_OFF] = FIX(0.587) * i; - rgb_y_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF; - } -} - - -/* - * Convert RGB to grayscale. - */ - -METHODDEF(void) -rgb_gray_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register INT32 * ctab = cconvert->rgb_y_tab; - register int r, g, b; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr0[col]); - g = GETJSAMPLE(inptr1[col]); - b = GETJSAMPLE(inptr2[col]); - /* Y */ - outptr[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - } - } -} - - -/* - * [R-G,G,B-G] to [R,G,B] conversion with modulo calculation - * (inverse color transform). - * This can be seen as an adaption of the general YCbCr->RGB - * conversion equation with Kr = Kb = 0, while replacing the - * normalization by modulo calculation. - */ - -METHODDEF(void) -rgb1_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register int r, g, b; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr0[col]); - g = GETJSAMPLE(inptr1[col]); - b = GETJSAMPLE(inptr2[col]); - /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD - * (modulo) operator is equivalent to the bitmask operator AND. - */ - outptr[RGB_RED] = (JSAMPLE) ((r + g - CENTERJSAMPLE) & MAXJSAMPLE); - outptr[RGB_GREEN] = (JSAMPLE) g; - outptr[RGB_BLUE] = (JSAMPLE) ((b + g - CENTERJSAMPLE) & MAXJSAMPLE); - outptr += RGB_PIXELSIZE; - } - } -} - - -/* - * [R-G,G,B-G] to grayscale conversion with modulo calculation - * (inverse color transform). - */ - -METHODDEF(void) -rgb1_gray_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register INT32 * ctab = cconvert->rgb_y_tab; - register int r, g, b; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr0[col]); - g = GETJSAMPLE(inptr1[col]); - b = GETJSAMPLE(inptr2[col]); - /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD - * (modulo) operator is equivalent to the bitmask operator AND. - */ - r = (r + g - CENTERJSAMPLE) & MAXJSAMPLE; - b = (b + g - CENTERJSAMPLE) & MAXJSAMPLE; - /* Y */ - outptr[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - } - } -} - - -/* - * No colorspace change, but conversion from separate-planes - * to interleaved representation. - */ - -METHODDEF(void) -rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - /* We can dispense with GETJSAMPLE() here */ - outptr[RGB_RED] = inptr0[col]; - outptr[RGB_GREEN] = inptr1[col]; - outptr[RGB_BLUE] = inptr2[col]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/* - * Color conversion for no colorspace change: just copy the data, - * converting from separate-planes to interleaved representation. - */ - -METHODDEF(void) -null_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - int ci; - register int nc = cinfo->num_components; - register JSAMPROW outptr; - register JSAMPROW inptr; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - while (--num_rows >= 0) { - for (ci = 0; ci < nc; ci++) { - inptr = input_buf[ci][input_row]; - outptr = output_buf[0] + ci; - for (col = 0; col < num_cols; col++) { - *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ - outptr += nc; - } - } - input_row++; - output_buf++; - } -} - - -/* - * Color conversion for grayscale: just copy the data. - * This also works for YCC -> grayscale conversion, in which - * we just copy the Y (luminance) component and ignore chrominance. - */ - -METHODDEF(void) -grayscale_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, - num_rows, cinfo->output_width); -} - - -/* - * Convert grayscale to RGB: just duplicate the graylevel three times. - * This is provided to support applications that don't want to cope - * with grayscale as a separate case. - */ - -METHODDEF(void) -gray_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register JSAMPROW outptr; - register JSAMPROW inptr; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - while (--num_rows >= 0) { - inptr = input_buf[0][input_row++]; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - /* We can dispense with GETJSAMPLE() here */ - outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/* - * Adobe-style YCCK->CMYK conversion. - * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same - * conversion as above, while passing K (black) unchanged. - * We assume build_ycc_rgb_table has been called. - */ - -METHODDEF(void) -ycck_cmyk_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2, inptr3; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - inptr3 = input_buf[3][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses, - * and for extended gamut encodings (sYCC). - */ - outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ - outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS)))]; - outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ - /* K passes through unchanged */ - outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ - outptr += 4; - } - } -} - - -/* - * Empty method for start_pass. - */ - -METHODDEF(void) -start_pass_dcolor (j_decompress_ptr cinfo) -{ - /* no work needed */ -} - - -/* - * Module initialization routine for output colorspace conversion. - */ - -GLOBAL(void) -jinit_color_deconverter (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert; - int ci; - - cconvert = (my_cconvert_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_color_deconverter)); - cinfo->cconvert = &cconvert->pub; - cconvert->pub.start_pass = start_pass_dcolor; - - /* Make sure num_components agrees with jpeg_color_space */ - switch (cinfo->jpeg_color_space) { - case JCS_GRAYSCALE: - if (cinfo->num_components != 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - case JCS_RGB: - case JCS_YCbCr: - case JCS_BG_RGB: - case JCS_BG_YCC: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - case JCS_CMYK: - case JCS_YCCK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - default: /* JCS_UNKNOWN can be anything */ - if (cinfo->num_components < 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - } - - /* Support color transform only for RGB colorspaces */ - if (cinfo->color_transform && - cinfo->jpeg_color_space != JCS_RGB && - cinfo->jpeg_color_space != JCS_BG_RGB) - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - - /* Set out_color_components and conversion method based on requested space. - * Also clear the component_needed flags for any unused components, - * so that earlier pipeline stages can avoid useless computation. - */ - - switch (cinfo->out_color_space) { - case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - switch (cinfo->jpeg_color_space) { - case JCS_GRAYSCALE: - case JCS_YCbCr: - case JCS_BG_YCC: - cconvert->pub.color_convert = grayscale_convert; - /* For color->grayscale conversion, only the Y (0) component is needed */ - for (ci = 1; ci < cinfo->num_components; ci++) - cinfo->comp_info[ci].component_needed = FALSE; - break; - case JCS_RGB: - switch (cinfo->color_transform) { - case JCT_NONE: - cconvert->pub.color_convert = rgb_gray_convert; - break; - case JCT_SUBTRACT_GREEN: - cconvert->pub.color_convert = rgb1_gray_convert; - break; - default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - } - build_rgb_y_table(cinfo); - break; - default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - } - break; - - case JCS_RGB: - cinfo->out_color_components = RGB_PIXELSIZE; - switch (cinfo->jpeg_color_space) { - case JCS_GRAYSCALE: - cconvert->pub.color_convert = gray_rgb_convert; - break; - case JCS_YCbCr: - cconvert->pub.color_convert = ycc_rgb_convert; - build_ycc_rgb_table(cinfo); - break; - case JCS_BG_YCC: - cconvert->pub.color_convert = ycc_rgb_convert; - build_bg_ycc_rgb_table(cinfo); - break; - case JCS_RGB: - switch (cinfo->color_transform) { - case JCT_NONE: - cconvert->pub.color_convert = rgb_convert; - break; - case JCT_SUBTRACT_GREEN: - cconvert->pub.color_convert = rgb1_rgb_convert; - break; - default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - } - break; - default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - } - break; - - case JCS_BG_RGB: - cinfo->out_color_components = RGB_PIXELSIZE; - if (cinfo->jpeg_color_space == JCS_BG_RGB) { - switch (cinfo->color_transform) { - case JCT_NONE: - cconvert->pub.color_convert = rgb_convert; - break; - case JCT_SUBTRACT_GREEN: - cconvert->pub.color_convert = rgb1_rgb_convert; - break; - default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - } - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_CMYK: - cinfo->out_color_components = 4; - switch (cinfo->jpeg_color_space) { - case JCS_YCCK: - cconvert->pub.color_convert = ycck_cmyk_convert; - build_ycc_rgb_table(cinfo); - break; - case JCS_CMYK: - cconvert->pub.color_convert = null_convert; - break; - default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - } - break; - - default: - /* Permit null conversion to same output space */ - if (cinfo->out_color_space == cinfo->jpeg_color_space) { - cinfo->out_color_components = cinfo->num_components; - cconvert->pub.color_convert = null_convert; - } else /* unsupported non-null conversion */ - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - } - - if (cinfo->quantize_colors) - cinfo->output_components = 1; /* single colormapped output component */ - else - cinfo->output_components = cinfo->out_color_components; -} diff --git a/libraries/jpeg/jdct.h b/libraries/jpeg/jdct.h deleted file mode 100644 index bcfedfcfd2..0000000000 --- a/libraries/jpeg/jdct.h +++ /dev/null @@ -1,416 +0,0 @@ -/* - * jdct.h - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2002-2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file contains common declarations for the forward and - * inverse DCT modules. These declarations are private to the DCT managers - * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. - * The individual DCT algorithms are kept in separate files to ease - * machine-dependent tuning (e.g., assembly coding). - */ - - -/* - * A forward DCT routine is given a pointer to an input sample array and - * a pointer to a work area of type DCTELEM[]; the DCT is to be performed - * in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32 - * for 12-bit samples. (NOTE: Floating-point DCT implementations use an - * array of type FAST_FLOAT, instead.) - * The input data is to be fetched from the sample array starting at a - * specified column. (Any row offset needed will be applied to the array - * pointer before it is passed to the FDCT code.) - * Note that the number of samples fetched by the FDCT routine is - * DCT_h_scaled_size * DCT_v_scaled_size. - * The DCT outputs are returned scaled up by a factor of 8; they therefore - * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This - * convention improves accuracy in integer implementations and saves some - * work in floating-point ones. - * Quantization of the output coefficients is done by jcdctmgr.c. - */ - -#if BITS_IN_JSAMPLE == 8 -typedef int DCTELEM; /* 16 or 32 bits is fine */ -#else -typedef INT32 DCTELEM; /* must have 32 bits */ -#endif - -typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, - JSAMPARRAY sample_data, - JDIMENSION start_col)); -typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, - JSAMPARRAY sample_data, - JDIMENSION start_col)); - - -/* - * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer - * to an output sample array. The routine must dequantize the input data as - * well as perform the IDCT; for dequantization, it uses the multiplier table - * pointed to by compptr->dct_table. The output data is to be placed into the - * sample array starting at a specified column. (Any row offset needed will - * be applied to the array pointer before it is passed to the IDCT code.) - * Note that the number of samples emitted by the IDCT routine is - * DCT_h_scaled_size * DCT_v_scaled_size. - */ - -/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ - -/* - * Each IDCT routine has its own ideas about the best dct_table element type. - */ - -typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ -#if BITS_IN_JSAMPLE == 8 -typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ -#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ -#else -typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ -#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ -#endif -typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ - - -/* - * Each IDCT routine is responsible for range-limiting its results and - * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could - * be quite far out of range if the input data is corrupt, so a bulletproof - * range-limiting step is required. We use a mask-and-table-lookup method - * to do the combined operations quickly, assuming that RANGE_CENTER - * (defined in jpegint.h) is a power of 2. See the comments with - * prepare_range_limit_table (in jdmaster.c) for more info. - */ - -#define RANGE_MASK (RANGE_CENTER * 2 - 1) -#define RANGE_SUBSET (RANGE_CENTER - CENTERJSAMPLE) - -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit - RANGE_SUBSET) - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_fdct_islow jFDislow -#define jpeg_fdct_ifast jFDifast -#define jpeg_fdct_float jFDfloat -#define jpeg_fdct_7x7 jFD7x7 -#define jpeg_fdct_6x6 jFD6x6 -#define jpeg_fdct_5x5 jFD5x5 -#define jpeg_fdct_4x4 jFD4x4 -#define jpeg_fdct_3x3 jFD3x3 -#define jpeg_fdct_2x2 jFD2x2 -#define jpeg_fdct_1x1 jFD1x1 -#define jpeg_fdct_9x9 jFD9x9 -#define jpeg_fdct_10x10 jFD10x10 -#define jpeg_fdct_11x11 jFD11x11 -#define jpeg_fdct_12x12 jFD12x12 -#define jpeg_fdct_13x13 jFD13x13 -#define jpeg_fdct_14x14 jFD14x14 -#define jpeg_fdct_15x15 jFD15x15 -#define jpeg_fdct_16x16 jFD16x16 -#define jpeg_fdct_16x8 jFD16x8 -#define jpeg_fdct_14x7 jFD14x7 -#define jpeg_fdct_12x6 jFD12x6 -#define jpeg_fdct_10x5 jFD10x5 -#define jpeg_fdct_8x4 jFD8x4 -#define jpeg_fdct_6x3 jFD6x3 -#define jpeg_fdct_4x2 jFD4x2 -#define jpeg_fdct_2x1 jFD2x1 -#define jpeg_fdct_8x16 jFD8x16 -#define jpeg_fdct_7x14 jFD7x14 -#define jpeg_fdct_6x12 jFD6x12 -#define jpeg_fdct_5x10 jFD5x10 -#define jpeg_fdct_4x8 jFD4x8 -#define jpeg_fdct_3x6 jFD3x6 -#define jpeg_fdct_2x4 jFD2x4 -#define jpeg_fdct_1x2 jFD1x2 -#define jpeg_idct_islow jRDislow -#define jpeg_idct_ifast jRDifast -#define jpeg_idct_float jRDfloat -#define jpeg_idct_7x7 jRD7x7 -#define jpeg_idct_6x6 jRD6x6 -#define jpeg_idct_5x5 jRD5x5 -#define jpeg_idct_4x4 jRD4x4 -#define jpeg_idct_3x3 jRD3x3 -#define jpeg_idct_2x2 jRD2x2 -#define jpeg_idct_1x1 jRD1x1 -#define jpeg_idct_9x9 jRD9x9 -#define jpeg_idct_10x10 jRD10x10 -#define jpeg_idct_11x11 jRD11x11 -#define jpeg_idct_12x12 jRD12x12 -#define jpeg_idct_13x13 jRD13x13 -#define jpeg_idct_14x14 jRD14x14 -#define jpeg_idct_15x15 jRD15x15 -#define jpeg_idct_16x16 jRD16x16 -#define jpeg_idct_16x8 jRD16x8 -#define jpeg_idct_14x7 jRD14x7 -#define jpeg_idct_12x6 jRD12x6 -#define jpeg_idct_10x5 jRD10x5 -#define jpeg_idct_8x4 jRD8x4 -#define jpeg_idct_6x3 jRD6x3 -#define jpeg_idct_4x2 jRD4x2 -#define jpeg_idct_2x1 jRD2x1 -#define jpeg_idct_8x16 jRD8x16 -#define jpeg_idct_7x14 jRD7x14 -#define jpeg_idct_6x12 jRD6x12 -#define jpeg_idct_5x10 jRD5x10 -#define jpeg_idct_4x8 jRD4x8 -#define jpeg_idct_3x6 jRD3x8 -#define jpeg_idct_2x4 jRD2x4 -#define jpeg_idct_1x2 jRD1x2 -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Extern declarations for the forward and inverse DCT routines. */ - -EXTERN(void) jpeg_fdct_islow - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_ifast - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_float - JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_7x7 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_6x6 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_5x5 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_4x4 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_3x3 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_2x2 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_1x1 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_9x9 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_10x10 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_11x11 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_12x12 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_13x13 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_14x14 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_15x15 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_16x16 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_16x8 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_14x7 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_12x6 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_10x5 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_8x4 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_6x3 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_4x2 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_2x1 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_8x16 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_7x14 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_6x12 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_5x10 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_4x8 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_3x6 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_2x4 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_1x2 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); - -EXTERN(void) jpeg_idct_islow - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_ifast - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_float - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_7x7 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_6x6 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_5x5 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_4x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_3x3 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_2x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_1x1 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_9x9 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_10x10 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_11x11 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_12x12 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_13x13 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_14x14 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_15x15 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_16x16 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_16x8 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_14x7 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_12x6 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_10x5 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_8x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_6x3 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_4x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_2x1 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_8x16 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_7x14 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_6x12 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_5x10 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_4x8 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_3x6 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_2x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_1x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); - - -/* - * Macros for handling fixed-point arithmetic; these are used by many - * but not all of the DCT/IDCT modules. - * - * All values are expected to be of type INT32. - * Fractional constants are scaled left by CONST_BITS bits. - * CONST_BITS is defined within each module using these macros, - * and may differ from one module to the next. - */ - -#define ONE ((INT32) 1) -#define CONST_SCALE (ONE << CONST_BITS) - -/* Convert a positive real constant to an integer scaled by CONST_SCALE. - * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, - * thus causing a lot of useless floating-point operations at run time. - */ - -#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) - -/* Descale and correctly round an INT32 value that's scaled by N bits. - * We assume RIGHT_SHIFT rounds towards minus infinity, so adding - * the fudge factor is correct for either sign of X. - */ - -#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * This macro is used only when the two inputs will actually be no more than - * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a - * full 32x32 multiply. This provides a useful speedup on many machines. - * Unfortunately there is no way to specify a 16x16->32 multiply portably - * in C, but some C compilers will do the right thing if you provide the - * correct combination of casts. - */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) -#endif -#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) -#endif - -#ifndef MULTIPLY16C16 /* default definition */ -#define MULTIPLY16C16(var,const) ((var) * (const)) -#endif - -/* Same except both inputs are variables. */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) -#endif - -#ifndef MULTIPLY16V16 /* default definition */ -#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) -#endif - -/* Like RIGHT_SHIFT, but applies to a DCTELEM. - * We assume that int right shift is unsigned if INT32 right shift is. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS DCTELEM ishift_temp; -#if BITS_IN_JSAMPLE == 8 -#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ -#else -#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ -#endif -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif diff --git a/libraries/jpeg/jddctmgr.c b/libraries/jpeg/jddctmgr.c deleted file mode 100644 index 9ecfbb5107..0000000000 --- a/libraries/jpeg/jddctmgr.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * jddctmgr.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2002-2013 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the inverse-DCT management logic. - * This code selects a particular IDCT implementation to be used, - * and it performs related housekeeping chores. No code in this file - * is executed per IDCT step, only during output pass setup. - * - * Note that the IDCT routines are responsible for performing coefficient - * dequantization as well as the IDCT proper. This module sets up the - * dequantization multiplier table needed by the IDCT routine. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - - -/* - * The decompressor input side (jdinput.c) saves away the appropriate - * quantization table for each component at the start of the first scan - * involving that component. (This is necessary in order to correctly - * decode files that reuse Q-table slots.) - * When we are ready to make an output pass, the saved Q-table is converted - * to a multiplier table that will actually be used by the IDCT routine. - * The multiplier table contents are IDCT-method-dependent. To support - * application changes in IDCT method between scans, we can remake the - * multiplier tables if necessary. - * In buffered-image mode, the first output pass may occur before any data - * has been seen for some components, and thus before their Q-tables have - * been saved away. To handle this case, multiplier tables are preset - * to zeroes; the result of the IDCT will be a neutral gray level. - */ - - -/* Private subobject for this module */ - -typedef struct { - struct jpeg_inverse_dct pub; /* public fields */ - - /* This array contains the IDCT method code that each multiplier table - * is currently set up for, or -1 if it's not yet set up. - * The actual multiplier tables are pointed to by dct_table in the - * per-component comp_info structures. - */ - int cur_method[MAX_COMPONENTS]; -} my_idct_controller; - -typedef my_idct_controller * my_idct_ptr; - - -/* Allocated multiplier tables: big enough for any supported variant */ - -typedef union { - ISLOW_MULT_TYPE islow_array[DCTSIZE2]; -#ifdef DCT_IFAST_SUPPORTED - IFAST_MULT_TYPE ifast_array[DCTSIZE2]; -#endif -#ifdef DCT_FLOAT_SUPPORTED - FLOAT_MULT_TYPE float_array[DCTSIZE2]; -#endif -} multiplier_table; - - -/* The current scaled-IDCT routines require ISLOW-style multiplier tables, - * so be sure to compile that code if either ISLOW or SCALING is requested. - */ -#ifdef DCT_ISLOW_SUPPORTED -#define PROVIDE_ISLOW_TABLES -#else -#ifdef IDCT_SCALING_SUPPORTED -#define PROVIDE_ISLOW_TABLES -#endif -#endif - - -/* - * Prepare for an output pass. - * Here we select the proper IDCT routine for each component and build - * a matching multiplier table. - */ - -METHODDEF(void) -start_pass (j_decompress_ptr cinfo) -{ - my_idct_ptr idct = (my_idct_ptr) cinfo->idct; - int ci, i; - jpeg_component_info *compptr; - int method = 0; - inverse_DCT_method_ptr method_ptr = NULL; - JQUANT_TBL * qtbl; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Select the proper IDCT routine for this component's scaling */ - switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { -#ifdef IDCT_SCALING_SUPPORTED - case ((1 << 8) + 1): - method_ptr = jpeg_idct_1x1; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((2 << 8) + 2): - method_ptr = jpeg_idct_2x2; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((3 << 8) + 3): - method_ptr = jpeg_idct_3x3; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((4 << 8) + 4): - method_ptr = jpeg_idct_4x4; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((5 << 8) + 5): - method_ptr = jpeg_idct_5x5; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((6 << 8) + 6): - method_ptr = jpeg_idct_6x6; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((7 << 8) + 7): - method_ptr = jpeg_idct_7x7; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((9 << 8) + 9): - method_ptr = jpeg_idct_9x9; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((10 << 8) + 10): - method_ptr = jpeg_idct_10x10; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((11 << 8) + 11): - method_ptr = jpeg_idct_11x11; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((12 << 8) + 12): - method_ptr = jpeg_idct_12x12; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((13 << 8) + 13): - method_ptr = jpeg_idct_13x13; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((14 << 8) + 14): - method_ptr = jpeg_idct_14x14; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((15 << 8) + 15): - method_ptr = jpeg_idct_15x15; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((16 << 8) + 16): - method_ptr = jpeg_idct_16x16; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((16 << 8) + 8): - method_ptr = jpeg_idct_16x8; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((14 << 8) + 7): - method_ptr = jpeg_idct_14x7; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((12 << 8) + 6): - method_ptr = jpeg_idct_12x6; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((10 << 8) + 5): - method_ptr = jpeg_idct_10x5; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((8 << 8) + 4): - method_ptr = jpeg_idct_8x4; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((6 << 8) + 3): - method_ptr = jpeg_idct_6x3; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((4 << 8) + 2): - method_ptr = jpeg_idct_4x2; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((2 << 8) + 1): - method_ptr = jpeg_idct_2x1; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((8 << 8) + 16): - method_ptr = jpeg_idct_8x16; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((7 << 8) + 14): - method_ptr = jpeg_idct_7x14; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((6 << 8) + 12): - method_ptr = jpeg_idct_6x12; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((5 << 8) + 10): - method_ptr = jpeg_idct_5x10; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((4 << 8) + 8): - method_ptr = jpeg_idct_4x8; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((3 << 8) + 6): - method_ptr = jpeg_idct_3x6; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((2 << 8) + 4): - method_ptr = jpeg_idct_2x4; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; - case ((1 << 8) + 2): - method_ptr = jpeg_idct_1x2; - method = JDCT_ISLOW; /* jidctint uses islow-style table */ - break; -#endif - case ((DCTSIZE << 8) + DCTSIZE): - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - method_ptr = jpeg_idct_islow; - method = JDCT_ISLOW; - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - method_ptr = jpeg_idct_ifast; - method = JDCT_IFAST; - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - method_ptr = jpeg_idct_float; - method = JDCT_FLOAT; - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - break; - default: - ERREXIT2(cinfo, JERR_BAD_DCTSIZE, - compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); - break; - } - idct->pub.inverse_DCT[ci] = method_ptr; - /* Create multiplier table from quant table. - * However, we can skip this if the component is uninteresting - * or if we already built the table. Also, if no quant table - * has yet been saved for the component, we leave the - * multiplier table all-zero; we'll be reading zeroes from the - * coefficient controller's buffer anyway. - */ - if (! compptr->component_needed || idct->cur_method[ci] == method) - continue; - qtbl = compptr->quant_table; - if (qtbl == NULL) /* happens if no data yet for component */ - continue; - idct->cur_method[ci] = method; - switch (method) { -#ifdef PROVIDE_ISLOW_TABLES - case JDCT_ISLOW: - { - /* For LL&M IDCT method, multipliers are equal to raw quantization - * coefficients, but are stored as ints to ensure access efficiency. - */ - ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; - for (i = 0; i < DCTSIZE2; i++) { - ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; - } - } - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * For integer operation, the multiplier table is to be scaled by - * IFAST_SCALE_BITS. - */ - IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; -#define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS - - for (i = 0; i < DCTSIZE2; i++) { - ifmtbl[i] = (IFAST_MULT_TYPE) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-IFAST_SCALE_BITS); - } - } - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 1/8. - */ - FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fmtbl[i] = (FLOAT_MULT_TYPE) - ((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 0.125); - i++; - } - } - } - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - } -} - - -/* - * Initialize IDCT manager. - */ - -GLOBAL(void) -jinit_inverse_dct (j_decompress_ptr cinfo) -{ - my_idct_ptr idct; - int ci; - jpeg_component_info *compptr; - - idct = (my_idct_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_idct_controller)); - cinfo->idct = &idct->pub; - idct->pub.start_pass = start_pass; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Allocate and pre-zero a multiplier table for each component */ - compptr->dct_table = - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(multiplier_table)); - MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); - /* Mark multiplier table not yet set up for any method */ - idct->cur_method[ci] = -1; - } -} diff --git a/libraries/jpeg/jdhuff.c b/libraries/jpeg/jdhuff.c deleted file mode 100644 index 835d06ecb6..0000000000 --- a/libraries/jpeg/jdhuff.c +++ /dev/null @@ -1,1553 +0,0 @@ -/* - * jdhuff.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2006-2016 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines. - * Both sequential and progressive modes are supported in this single module. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Derived data constructed for each Huffman table */ - -#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ - -typedef struct { - /* Basic tables: (element [0] of each array is unused) */ - INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ - INT32 valoffset[17]; /* huffval[] offset for codes of length k */ - /* valoffset[k] = huffval[] index of 1st symbol of code length k, less - * the smallest code of length k; so given a code of length k, the - * corresponding symbol is huffval[code + valoffset[k]] - */ - - /* Link to public Huffman table (needed only in jpeg_huff_decode) */ - JHUFF_TBL *pub; - - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of - * the input data stream. If the next Huffman code is no more - * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. - */ - int look_nbits[1< 32 bits on your machine, and shifting/masking longs is - * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE - * appropriately should be a win. Unfortunately we can't define the size - * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) - * because not all machines measure sizeof in 8-bit bytes. - */ - -typedef struct { /* Bitreading state saved across MCUs */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ -} bitread_perm_state; - -typedef struct { /* Bitreading working state within an MCU */ - /* Current data source location */ - /* We need a copy, rather than munging the original, in case of suspension */ - const JOCTET * next_input_byte; /* => next byte to read from source */ - size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ - /* Bit input buffer --- note these values are kept in register variables, - * not in this struct, inside the inner loops. - */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ - /* Pointer needed by jpeg_fill_bit_buffer. */ - j_decompress_ptr cinfo; /* back link to decompress master record */ -} bitread_working_state; - -/* Macros to declare and load/save bitread local variables. */ -#define BITREAD_STATE_VARS \ - register bit_buf_type get_buffer; \ - register int bits_left; \ - bitread_working_state br_state - -#define BITREAD_LOAD_STATE(cinfop,permstate) \ - br_state.cinfo = cinfop; \ - br_state.next_input_byte = cinfop->src->next_input_byte; \ - br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ - get_buffer = permstate.get_buffer; \ - bits_left = permstate.bits_left; - -#define BITREAD_SAVE_STATE(cinfop,permstate) \ - cinfop->src->next_input_byte = br_state.next_input_byte; \ - cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ - permstate.get_buffer = get_buffer; \ - permstate.bits_left = bits_left - -/* - * These macros provide the in-line portion of bit fetching. - * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer - * before using GET_BITS, PEEK_BITS, or DROP_BITS. - * The variables get_buffer and bits_left are assumed to be locals, - * but the state struct might not be (jpeg_huff_decode needs this). - * CHECK_BIT_BUFFER(state,n,action); - * Ensure there are N bits in get_buffer; if suspend, take action. - * val = GET_BITS(n); - * Fetch next N bits. - * val = PEEK_BITS(n); - * Fetch next N bits without removing them from the buffer. - * DROP_BITS(n); - * Discard next N bits. - * The value N should be a simple variable, not an expression, because it - * is evaluated multiple times. - */ - -#define CHECK_BIT_BUFFER(state,nbits,action) \ - { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } - -#define GET_BITS(nbits) \ - (((int) (get_buffer >> (bits_left -= (nbits)))) & BIT_MASK(nbits)) - -#define PEEK_BITS(nbits) \ - (((int) (get_buffer >> (bits_left - (nbits)))) & BIT_MASK(nbits)) - -#define DROP_BITS(nbits) \ - (bits_left -= (nbits)) - - -/* - * Code for extracting next Huffman-coded symbol from input bit stream. - * Again, this is time-critical and we make the main paths be macros. - * - * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits - * without looping. Usually, more than 95% of the Huffman codes will be 8 - * or fewer bits long. The few overlength codes are handled with a loop, - * which need not be inline code. - * - * Notes about the HUFF_DECODE macro: - * 1. Near the end of the data segment, we may fail to get enough bits - * for a lookahead. In that case, we do it the hard way. - * 2. If the lookahead table contains no entry, the next code must be - * more than HUFF_LOOKAHEAD bits long. - * 3. jpeg_huff_decode returns -1 if forced to suspend. - */ - -#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ -{ register int nb, look; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - nb = 1; goto slowlabel; \ - } \ - } \ - look = PEEK_BITS(HUFF_LOOKAHEAD); \ - if ((nb = htbl->look_nbits[look]) != 0) { \ - DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ - } else { \ - nb = HUFF_LOOKAHEAD+1; \ -slowlabel: \ - if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ - { failaction; } \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - } \ -} - - -/* - * Expanded entropy decoder object for Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).EOBRUN = (src).EOBRUN, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_decoder pub; /* public fields */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - bitread_perm_state bitstate; /* Bit buffer at start of MCU */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - boolean insufficient_data; /* set TRUE after emitting warning */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Following two fields used only in progressive mode */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ - - /* Following fields used only in sequential mode */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; - - /* Precalculated info set up by start_pass for use in decode_mcu: */ - - /* Pointers to derived tables to be used for each block within an MCU */ - d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; - d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; - /* Whether we care about the DC and AC coefficient values for each block */ - int coef_limit[D_MAX_BLOCKS_IN_MCU]; -} huff_entropy_decoder; - -typedef huff_entropy_decoder * huff_entropy_ptr; - - -static const int jpeg_zigzag_order[8][8] = { - { 0, 1, 5, 6, 14, 15, 27, 28 }, - { 2, 4, 7, 13, 16, 26, 29, 42 }, - { 3, 8, 12, 17, 25, 30, 41, 43 }, - { 9, 11, 18, 24, 31, 40, 44, 53 }, - { 10, 19, 23, 32, 39, 45, 52, 54 }, - { 20, 22, 33, 38, 46, 51, 55, 60 }, - { 21, 34, 37, 47, 50, 56, 59, 61 }, - { 35, 36, 48, 49, 57, 58, 62, 63 } -}; - -static const int jpeg_zigzag_order7[7][7] = { - { 0, 1, 5, 6, 14, 15, 27 }, - { 2, 4, 7, 13, 16, 26, 28 }, - { 3, 8, 12, 17, 25, 29, 38 }, - { 9, 11, 18, 24, 30, 37, 39 }, - { 10, 19, 23, 31, 36, 40, 45 }, - { 20, 22, 32, 35, 41, 44, 46 }, - { 21, 33, 34, 42, 43, 47, 48 } -}; - -static const int jpeg_zigzag_order6[6][6] = { - { 0, 1, 5, 6, 14, 15 }, - { 2, 4, 7, 13, 16, 25 }, - { 3, 8, 12, 17, 24, 26 }, - { 9, 11, 18, 23, 27, 32 }, - { 10, 19, 22, 28, 31, 33 }, - { 20, 21, 29, 30, 34, 35 } -}; - -static const int jpeg_zigzag_order5[5][5] = { - { 0, 1, 5, 6, 14 }, - { 2, 4, 7, 13, 15 }, - { 3, 8, 12, 16, 21 }, - { 9, 11, 17, 20, 22 }, - { 10, 18, 19, 23, 24 } -}; - -static const int jpeg_zigzag_order4[4][4] = { - { 0, 1, 5, 6 }, - { 2, 4, 7, 12 }, - { 3, 8, 11, 13 }, - { 9, 10, 14, 15 } -}; - -static const int jpeg_zigzag_order3[3][3] = { - { 0, 1, 5 }, - { 2, 4, 6 }, - { 3, 7, 8 } -}; - -static const int jpeg_zigzag_order2[2][2] = { - { 0, 1 }, - { 2, 3 } -}; - - -/* - * Compute the derived values for a Huffman table. - * This routine also performs some validation checks on the table. - */ - -LOCAL(void) -jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, - d_derived_tbl ** pdtbl) -{ - JHUFF_TBL *htbl; - d_derived_tbl *dtbl; - int p, i, l, si, numsymbols; - int lookbits, ctr; - char huffsize[257]; - unsigned int huffcode[257]; - unsigned int code; - - /* Note that huffsize[] and huffcode[] are filled in code-length order, - * paralleling the order of the symbols themselves in htbl->huffval[]. - */ - - /* Find the input Huffman table */ - if (tblno < 0 || tblno >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - htbl = - isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; - if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - - /* Allocate a workspace if we haven't already done so. */ - if (*pdtbl == NULL) - *pdtbl = (d_derived_tbl *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(d_derived_tbl)); - dtbl = *pdtbl; - dtbl->pub = htbl; /* fill in back link */ - - /* Figure C.1: make table of Huffman code length for each symbol */ - - p = 0; - for (l = 1; l <= 16; l++) { - i = (int) htbl->bits[l]; - if (i < 0 || p + i > 256) /* protect against table overrun */ - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - while (i--) - huffsize[p++] = (char) l; - } - huffsize[p] = 0; - numsymbols = p; - - /* Figure C.2: generate the codes themselves */ - /* We also validate that the counts represent a legal Huffman code tree. */ - - code = 0; - si = huffsize[0]; - p = 0; - while (huffsize[p]) { - while (((int) huffsize[p]) == si) { - huffcode[p++] = code; - code++; - } - /* code is now 1 more than the last code used for codelength si; but - * it must still fit in si bits, since no code is allowed to be all ones. - */ - if (((INT32) code) >= (((INT32) 1) << si)) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - code <<= 1; - si++; - } - - /* Figure F.15: generate decoding tables for bit-sequential decoding */ - - p = 0; - for (l = 1; l <= 16; l++) { - if (htbl->bits[l]) { - /* valoffset[l] = huffval[] index of 1st symbol of code length l, - * minus the minimum code of length l - */ - dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; - p += htbl->bits[l]; - dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ - } else { - dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ - } - } - dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ - - /* Compute lookahead tables to speed up decoding. - * First we set all the table entries to 0, indicating "too long"; - * then we iterate through the Huffman codes that are short enough and - * fill in all the entries that correspond to bit sequences starting - * with that code. - */ - - MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); - - p = 0; - for (l = 1; l <= HUFF_LOOKAHEAD; l++) { - for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { - /* l = current code's length, p = its index in huffcode[] & huffval[]. */ - /* Generate left-justified code followed by all possible bit sequences */ - lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); - for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { - dtbl->look_nbits[lookbits] = l; - dtbl->look_sym[lookbits] = htbl->huffval[p]; - lookbits++; - } - } - } - - /* Validate symbols as being reasonable. - * For AC tables, we make no check, but accept all byte values 0..255. - * For DC tables, we require the symbols to be in range 0..15. - * (Tighter bounds could be applied depending on the data depth and mode, - * but this is sufficient to ensure safe decoding.) - */ - if (isDC) { - for (i = 0; i < numsymbols; i++) { - int sym = htbl->huffval[i]; - if (sym < 0 || sym > 15) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - } - } -} - - -/* - * Out-of-line code for bit fetching. - * Note: current values of get_buffer and bits_left are passed as parameters, - * but are returned in the corresponding fields of the state struct. - * - * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width - * of get_buffer to be used. (On machines with wider words, an even larger - * buffer could be used.) However, on some machines 32-bit shifts are - * quite slow and take time proportional to the number of places shifted. - * (This is true with most PC compilers, for instance.) In this case it may - * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the - * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. - */ - -#ifdef SLOW_SHIFT_32 -#define MIN_GET_BITS 15 /* minimum allowable value */ -#else -#define MIN_GET_BITS (BIT_BUF_SIZE-7) -#endif - - -LOCAL(boolean) -jpeg_fill_bit_buffer (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - int nbits) -/* Load up the bit buffer to a depth of at least nbits */ -{ - /* Copy heavily used state fields into locals (hopefully registers) */ - register const JOCTET * next_input_byte = state->next_input_byte; - register size_t bytes_in_buffer = state->bytes_in_buffer; - j_decompress_ptr cinfo = state->cinfo; - - /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ - /* (It is assumed that no request will be for more than that many bits.) */ - /* We fail to do so only if we hit a marker or are forced to suspend. */ - - if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ - while (bits_left < MIN_GET_BITS) { - register int c; - - /* Attempt to read a byte */ - if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - - /* If it's 0xFF, check and discard stuffed zero byte */ - if (c == 0xFF) { - /* Loop here to discard any padding FF's on terminating marker, - * so that we can save a valid unread_marker value. NOTE: we will - * accept multiple FF's followed by a 0 as meaning a single FF data - * byte. This data pattern is not valid according to the standard. - */ - do { - if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - } while (c == 0xFF); - - if (c == 0) { - /* Found FF/00, which represents an FF data byte */ - c = 0xFF; - } else { - /* Oops, it's actually a marker indicating end of compressed data. - * Save the marker code for later use. - * Fine point: it might appear that we should save the marker into - * bitread working state, not straight into permanent state. But - * once we have hit a marker, we cannot need to suspend within the - * current MCU, because we will read no more bytes from the data - * source. So it is OK to update permanent state right away. - */ - cinfo->unread_marker = c; - /* See if we need to insert some fake zero bits. */ - goto no_more_bytes; - } - } - - /* OK, load c into get_buffer */ - get_buffer = (get_buffer << 8) | c; - bits_left += 8; - } /* end while */ - } else { - no_more_bytes: - /* We get here if we've read the marker that terminates the compressed - * data segment. There should be enough bits in the buffer register - * to satisfy the request; if so, no problem. - */ - if (nbits > bits_left) { - /* Uh-oh. Report corrupted data to user and stuff zeroes into - * the data stream, so that we can produce some kind of image. - * We use a nonvolatile flag to ensure that only one warning message - * appears per data segment. - */ - if (! ((huff_entropy_ptr) cinfo->entropy)->insufficient_data) { - WARNMS(cinfo, JWRN_HIT_MARKER); - ((huff_entropy_ptr) cinfo->entropy)->insufficient_data = TRUE; - } - /* Fill the buffer with zero bits */ - get_buffer <<= MIN_GET_BITS - bits_left; - bits_left = MIN_GET_BITS; - } - } - - /* Unload the local registers */ - state->next_input_byte = next_input_byte; - state->bytes_in_buffer = bytes_in_buffer; - state->get_buffer = get_buffer; - state->bits_left = bits_left; - - return TRUE; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and sub will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define BIT_MASK(nbits) ((1<<(nbits))-1) -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) - ((1<<(s))-1) : (x)) - -#else - -#define BIT_MASK(nbits) bmask[nbits] -#define HUFF_EXTEND(x,s) ((x) <= bmask[(s) - 1] ? (x) - bmask[s] : (x)) - -static const int bmask[16] = /* bmask[n] is mask for n rightmost bits */ - { 0, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, - 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF }; - -#endif /* AVOID_TABLES */ - - -/* - * Out-of-line code for Huffman code decoding. - */ - -LOCAL(int) -jpeg_huff_decode (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - d_derived_tbl * htbl, int min_bits) -{ - register int l = min_bits; - register INT32 code; - - /* HUFF_DECODE has determined that the code is at least min_bits */ - /* bits long, so fetch that many bits in one swoop. */ - - CHECK_BIT_BUFFER(*state, l, return -1); - code = GET_BITS(l); - - /* Collect the rest of the Huffman code one bit at a time. */ - /* This is per Figure F.16 in the JPEG spec. */ - - while (code > htbl->maxcode[l]) { - code <<= 1; - CHECK_BIT_BUFFER(*state, 1, return -1); - code |= GET_BITS(1); - l++; - } - - /* Unload the local registers */ - state->get_buffer = get_buffer; - state->bits_left = bits_left; - - /* With garbage input we may reach the sentinel value l = 17. */ - - if (l > 16) { - WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); - return 0; /* fake a zero as the safest result */ - } - - return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; -} - - -/* - * Finish up at the end of a Huffman-compressed scan. - */ - -METHODDEF(void) -finish_pass_huff (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; -} - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL(boolean) -process_restart (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci; - - finish_pass_huff(cinfo); - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Re-init EOB run count, too */ - entropy->saved.EOBRUN = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Huffman MCU decoding. - * Each of these routines decodes and returns one MCU's worth of - * Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. - * (Wholesale zeroing is usually a little faster than retail...) - * - * We return FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * spectral selection, since we'll just re-assign them on the next call. - * Successive approximation AC refinement has to be more careful, however.) - */ - -/* - * MCU decoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int Al = cinfo->Al; - register int s, r; - int blkn, ci; - JBLOCKROW block; - BITREAD_STATE_VARS; - savable_state state; - d_derived_tbl * tbl; - jpeg_component_info * compptr; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - tbl = entropy->derived_tbls[compptr->dc_tbl_no]; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, tbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - /* Convert DC difference to actual value, update last_dc_val */ - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ - (*block)[0] = (JCOEF) (s << Al); - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - register int s, k, r; - unsigned int EOBRUN; - int Se, Al; - const int * natural_order; - JBLOCKROW block; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->insufficient_data) { - - /* Load up working state. - * We can avoid loading/saving bitread state if in an EOB run. - */ - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - - if (EOBRUN) /* if it's a band of zeroes... */ - EOBRUN--; /* ...process it now (we do nothing) */ - else { - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - Se = cinfo->Se; - Al = cinfo->Al; - natural_order = cinfo->natural_order; - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - for (k = cinfo->Ss; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, return FALSE, label2); - r = s >> 4; - s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Scale and output coefficient in natural (dezigzagged) order */ - (*block)[natural_order[k]] = (JCOEF) (s << Al); - } else { - if (r != 15) { /* EOBr, run length is 2^r + appended bits */ - if (r) { /* EOBr, r > 0 */ - EOBRUN = 1 << r; - CHECK_BIT_BUFFER(br_state, r, return FALSE); - r = GET_BITS(r); - EOBRUN += r; - EOBRUN--; /* this band is processed at this moment */ - } - break; /* force end-of-band */ - } - k += 15; /* ZRL: skip 15 zeroes in band */ - } - } - - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - } - - /* Completed MCU, so update state */ - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, - * although the spec is not very clear on the point. - */ - -METHODDEF(boolean) -decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int p1, blkn; - BITREAD_STATE_VARS; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* Not worth the cycles to check insufficient_data here, - * since we will not change the data anyway if we read zeroes. - */ - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - - p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - /* Encoded data is simply the next bit of the two's-complement DC value */ - CHECK_BIT_BUFFER(br_state, 1, return FALSE); - if (GET_BITS(1)) - MCU_data[blkn][0][0] |= p1; - /* Note: since we use |=, repeating the assignment later is safe */ - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - register int s, k, r; - unsigned int EOBRUN; - int Se, p1, m1; - const int * natural_order; - JBLOCKROW block; - JCOEFPTR thiscoef; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - int num_newnz; - int newnz_pos[DCTSIZE2]; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, don't modify the MCU. - */ - if (! entropy->insufficient_data) { - - Se = cinfo->Se; - p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ - natural_order = cinfo->natural_order; - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - /* If we are forced to suspend, we must undo the assignments to any newly - * nonzero coefficients in the block, because otherwise we'd get confused - * next time about which coefficients were already nonzero. - * But we need not undo addition of bits to already-nonzero coefficients; - * instead, we can test the current bit to see if we already did it. - */ - num_newnz = 0; - - /* initialize coefficient loop counter to start of band */ - k = cinfo->Ss; - - if (EOBRUN == 0) { - do { - HUFF_DECODE(s, br_state, tbl, goto undoit, label3); - r = s >> 4; - s &= 15; - if (s) { - if (s != 1) /* size of new coef should always be 1 */ - WARNMS(cinfo, JWRN_HUFF_BAD_CODE); - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) - s = p1; /* newly nonzero coef is positive */ - else - s = m1; /* newly nonzero coef is negative */ - } else { - if (r != 15) { - EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ - if (r) { - CHECK_BIT_BUFFER(br_state, r, goto undoit); - r = GET_BITS(r); - EOBRUN += r; - } - break; /* rest of block is handled by EOB logic */ - } - /* note s = 0 for processing ZRL */ - } - /* Advance over already-nonzero coefs and r still-zero coefs, - * appending correction bits to the nonzeroes. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - do { - thiscoef = *block + natural_order[k]; - if (*thiscoef) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } else { - if (--r < 0) - break; /* reached target zero coefficient */ - } - k++; - } while (k <= Se); - if (s) { - int pos = natural_order[k]; - /* Output newly nonzero coefficient */ - (*block)[pos] = (JCOEF) s; - /* Remember its position in case we have to suspend */ - newnz_pos[num_newnz++] = pos; - } - k++; - } while (k <= Se); - } - - if (EOBRUN) { - /* Scan any remaining coefficient positions after the end-of-band - * (the last newly nonzero coefficient, if any). Append a correction - * bit to each already-nonzero coefficient. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - do { - thiscoef = *block + natural_order[k]; - if (*thiscoef) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } - k++; - } while (k <= Se); - /* Count one block completed in EOB run */ - EOBRUN--; - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; - -undoit: - /* Re-zero any output coefficients that we made newly nonzero */ - while (num_newnz) - (*block)[newnz_pos[--num_newnz]] = 0; - - return FALSE; -} - - -/* - * Decode one MCU's worth of Huffman-compressed coefficients, - * partial blocks. - */ - -METHODDEF(boolean) -decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - const int * natural_order; - int Se, blkn; - BITREAD_STATE_VARS; - savable_state state; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->insufficient_data) { - - natural_order = cinfo->natural_order; - Se = cinfo->lim_Se; - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - JBLOCKROW block = MCU_data[blkn]; - d_derived_tbl * htbl; - register int s, k, r; - int coef_limit, ci; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - htbl = entropy->dc_cur_tbls[blkn]; - HUFF_DECODE(s, br_state, htbl, return FALSE, label1); - - htbl = entropy->ac_cur_tbls[blkn]; - k = 1; - coef_limit = entropy->coef_limit[blkn]; - if (coef_limit) { - /* Convert DC difference to actual value, update last_dc_val */ - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - ci = cinfo->MCU_membership[blkn]; - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient */ - (*block)[0] = (JCOEF) s; - - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (; k < coef_limit; k++) { - HUFF_DECODE(s, br_state, htbl, return FALSE, label2); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in natural_order[] will save us - * if k > Se, which could happen if the data is corrupted. - */ - (*block)[natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - goto EndOfBlock; - k += 15; - } - } - } else { - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } - } - - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ - for (; k <= Se; k++) { - HUFF_DECODE(s, br_state, htbl, return FALSE, label3); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } - } - - EndOfBlock: ; - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * Decode one MCU's worth of Huffman-compressed coefficients, - * full-size blocks. - */ - -METHODDEF(boolean) -decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int blkn; - BITREAD_STATE_VARS; - savable_state state; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - JBLOCKROW block = MCU_data[blkn]; - d_derived_tbl * htbl; - register int s, k, r; - int coef_limit, ci; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - htbl = entropy->dc_cur_tbls[blkn]; - HUFF_DECODE(s, br_state, htbl, return FALSE, label1); - - htbl = entropy->ac_cur_tbls[blkn]; - k = 1; - coef_limit = entropy->coef_limit[blkn]; - if (coef_limit) { - /* Convert DC difference to actual value, update last_dc_val */ - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - ci = cinfo->MCU_membership[blkn]; - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient */ - (*block)[0] = (JCOEF) s; - - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (; k < coef_limit; k++) { - HUFF_DECODE(s, br_state, htbl, return FALSE, label2); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in jpeg_natural_order[] will save us - * if k >= DCTSIZE2, which could happen if the data is corrupted. - */ - (*block)[jpeg_natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - goto EndOfBlock; - k += 15; - } - } - } else { - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } - } - - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ - for (; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, htbl, return FALSE, label3); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } - } - - EndOfBlock: ; - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, blkn, tbl, i; - jpeg_component_info * compptr; - - if (cinfo->progressive_mode) { - /* Validate progressive scan parameters */ - if (cinfo->Ss == 0) { - if (cinfo->Se != 0) - goto bad; - } else { - /* need not check Ss/Se < 0 since they came from unsigned bytes */ - if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) - goto bad; - /* AC scans may have only one component */ - if (cinfo->comps_in_scan != 1) - goto bad; - } - if (cinfo->Ah != 0) { - /* Successive approximation refinement scan: must have Al = Ah-1. */ - if (cinfo->Ah-1 != cinfo->Al) - goto bad; - } - if (cinfo->Al > 13) { /* need not check for < 0 */ - /* Arguably the maximum Al value should be less than 13 for 8-bit precision, - * but the spec doesn't say so, and we try to be liberal about what we - * accept. Note: large Al values could result in out-of-range DC - * coefficients during early scans, leading to bizarre displays due to - * overflows in the IDCT math. But we won't crash. - */ - bad: - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - } - /* Update progression status, and verify that scan order is legal. - * Note that inter-scan inconsistencies are treated as warnings - * not fatal errors ... not clear if this is right way to behave. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; - int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; - if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); - for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; - } - } - - /* Select MCU decoding routine */ - if (cinfo->Ah == 0) { - if (cinfo->Ss == 0) - entropy->pub.decode_mcu = decode_mcu_DC_first; - else - entropy->pub.decode_mcu = decode_mcu_AC_first; - } else { - if (cinfo->Ss == 0) - entropy->pub.decode_mcu = decode_mcu_DC_refine; - else - entropy->pub.decode_mcu = decode_mcu_AC_refine; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Make sure requested tables are present, and compute derived tables. - * We may build same derived table more than once, but it's not expensive. - */ - if (cinfo->Ss == 0) { - if (cinfo->Ah == 0) { /* DC refinement needs no table */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->derived_tbls[tbl]); - } - } else { - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->derived_tbls[tbl]); - /* remember the single active table */ - entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize private state variables */ - entropy->saved.EOBRUN = 0; - } else { - /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. - * This ought to be an error condition, but we make it a warning because - * there are some baseline files out there with all zeroes in these bytes. - */ - if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || - ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && - cinfo->Se != cinfo->lim_Se)) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); - - /* Select MCU decoding routine */ - /* We retain the hard-coded case for full-size blocks. - * This is not necessary, but it appears that this version is slightly - * more performant in the given implementation. - * With an improved implementation we would prefer a single optimized - * function. - */ - if (cinfo->lim_Se != DCTSIZE2-1) - entropy->pub.decode_mcu = decode_mcu_sub; - else - entropy->pub.decode_mcu = decode_mcu; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->dc_derived_tbls[tbl]); - if (cinfo->lim_Se) { /* AC needs no table when not present */ - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->ac_derived_tbls[tbl]); - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Precalculate decoding info for each block in an MCU of this scan */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - /* Precalculate which table to use for each block */ - entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; - entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; - /* Decide whether we really care about the coefficient values */ - if (compptr->component_needed) { - ci = compptr->DCT_v_scaled_size; - i = compptr->DCT_h_scaled_size; - switch (cinfo->lim_Se) { - case (1*1-1): - entropy->coef_limit[blkn] = 1; - break; - case (2*2-1): - if (ci <= 0 || ci > 2) ci = 2; - if (i <= 0 || i > 2) i = 2; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; - break; - case (3*3-1): - if (ci <= 0 || ci > 3) ci = 3; - if (i <= 0 || i > 3) i = 3; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; - break; - case (4*4-1): - if (ci <= 0 || ci > 4) ci = 4; - if (i <= 0 || i > 4) i = 4; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; - break; - case (5*5-1): - if (ci <= 0 || ci > 5) ci = 5; - if (i <= 0 || i > 5) i = 5; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; - break; - case (6*6-1): - if (ci <= 0 || ci > 6) ci = 6; - if (i <= 0 || i > 6) i = 6; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; - break; - case (7*7-1): - if (ci <= 0 || ci > 7) ci = 7; - if (i <= 0 || i > 7) i = 7; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; - break; - default: - if (ci <= 0 || ci > 8) ci = 8; - if (i <= 0 || i > 8) i = 8; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; - break; - } - } else { - entropy->coef_limit[blkn] = 0; - } - } - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->insufficient_data = FALSE; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Module initialization routine for Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy; - int i; - - entropy = (huff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(huff_entropy_decoder)); - cinfo->entropy = &entropy->pub; - entropy->pub.start_pass = start_pass_huff_decoder; - entropy->pub.finish_pass = finish_pass_huff; - - if (cinfo->progressive_mode) { - /* Create progression status table */ - int *coef_bit_ptr, ci; - cinfo->coef_bits = (int (*)[DCTSIZE2]) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components*DCTSIZE2*SIZEOF(int)); - coef_bit_ptr = & cinfo->coef_bits[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; - - /* Mark derived tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - } - } else { - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; - } - } -} diff --git a/libraries/jpeg/jdinput.c b/libraries/jpeg/jdinput.c deleted file mode 100644 index 0199553e89..0000000000 --- a/libraries/jpeg/jdinput.c +++ /dev/null @@ -1,662 +0,0 @@ -/* - * jdinput.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2002-2013 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains input control logic for the JPEG decompressor. - * These routines are concerned with controlling the decompressor's input - * processing (marker reading and coefficient decoding). The actual input - * reading is done in jdmarker.c, jdhuff.c, and jdarith.c. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef struct { - struct jpeg_input_controller pub; /* public fields */ - - int inheaders; /* Nonzero until first SOS is reached */ -} my_input_controller; - -typedef my_input_controller * my_inputctl_ptr; - - -/* Forward declarations */ -METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); - - -/* - * Routines to calculate various quantities related to the size of the image. - */ - - -/* - * Compute output image dimensions and related values. - * NOTE: this is exported for possible use by application. - * Hence it mustn't do anything that can't be done twice. - */ - -GLOBAL(void) -jpeg_core_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase. - * This function is used for transcoding and full decompression. - */ -{ -#ifdef IDCT_SCALING_SUPPORTED - int ci; - jpeg_component_info *compptr; - - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom) { - /* Provide 1/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 1; - cinfo->min_DCT_v_scaled_size = 1; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 2) { - /* Provide 2/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 2L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 2L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 2; - cinfo->min_DCT_v_scaled_size = 2; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 3) { - /* Provide 3/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 3L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 3L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 3; - cinfo->min_DCT_v_scaled_size = 3; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 4) { - /* Provide 4/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 4L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 4L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 4; - cinfo->min_DCT_v_scaled_size = 4; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 5) { - /* Provide 5/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 5L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 5L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 5; - cinfo->min_DCT_v_scaled_size = 5; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 6) { - /* Provide 6/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 6L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 6L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 6; - cinfo->min_DCT_v_scaled_size = 6; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 7) { - /* Provide 7/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 7L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 7L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 7; - cinfo->min_DCT_v_scaled_size = 7; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 8) { - /* Provide 8/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 8L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 8L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 8; - cinfo->min_DCT_v_scaled_size = 8; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 9) { - /* Provide 9/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 9L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 9L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 9; - cinfo->min_DCT_v_scaled_size = 9; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 10) { - /* Provide 10/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 10L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 10L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 10; - cinfo->min_DCT_v_scaled_size = 10; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 11) { - /* Provide 11/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 11L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 11L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 11; - cinfo->min_DCT_v_scaled_size = 11; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 12) { - /* Provide 12/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 12L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 12L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 12; - cinfo->min_DCT_v_scaled_size = 12; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 13) { - /* Provide 13/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 13L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 13L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 13; - cinfo->min_DCT_v_scaled_size = 13; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 14) { - /* Provide 14/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 14L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 14L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 14; - cinfo->min_DCT_v_scaled_size = 14; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 15) { - /* Provide 15/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 15L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 15L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 15; - cinfo->min_DCT_v_scaled_size = 15; - } else { - /* Provide 16/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 16L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 16L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 16; - cinfo->min_DCT_v_scaled_size = 16; - } - - /* Recompute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size; - compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size; - } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* initial_setup has already initialized DCT_scaled_size, - * and has computed unscaled downsampled_width and downsampled_height. - */ - -#endif /* IDCT_SCALING_SUPPORTED */ -} - - -LOCAL(void) -initial_setup (j_decompress_ptr cinfo) -/* Called once, when first SOS marker is reached */ -{ - int ci; - jpeg_component_info *compptr; - - /* Make sure image isn't bigger than I can handle */ - if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - - /* Only 8 to 12 bits data precision are supported for DCT based JPEG */ - if (cinfo->data_precision < 8 || cinfo->data_precision > 12) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - - /* Check that number of components won't exceed internal array sizes */ - if (cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - - /* Compute maximum sampling factors; check factor validity */ - cinfo->max_h_samp_factor = 1; - cinfo->max_v_samp_factor = 1; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || - compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) - ERREXIT(cinfo, JERR_BAD_SAMPLING); - cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, - compptr->h_samp_factor); - cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, - compptr->v_samp_factor); - } - - /* Derive block_size, natural_order, and lim_Se */ - if (cinfo->is_baseline || (cinfo->progressive_mode && - cinfo->comps_in_scan)) { /* no pseudo SOS marker */ - cinfo->block_size = DCTSIZE; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - } else - switch (cinfo->Se) { - case (1*1-1): - cinfo->block_size = 1; - cinfo->natural_order = jpeg_natural_order; /* not needed */ - cinfo->lim_Se = cinfo->Se; - break; - case (2*2-1): - cinfo->block_size = 2; - cinfo->natural_order = jpeg_natural_order2; - cinfo->lim_Se = cinfo->Se; - break; - case (3*3-1): - cinfo->block_size = 3; - cinfo->natural_order = jpeg_natural_order3; - cinfo->lim_Se = cinfo->Se; - break; - case (4*4-1): - cinfo->block_size = 4; - cinfo->natural_order = jpeg_natural_order4; - cinfo->lim_Se = cinfo->Se; - break; - case (5*5-1): - cinfo->block_size = 5; - cinfo->natural_order = jpeg_natural_order5; - cinfo->lim_Se = cinfo->Se; - break; - case (6*6-1): - cinfo->block_size = 6; - cinfo->natural_order = jpeg_natural_order6; - cinfo->lim_Se = cinfo->Se; - break; - case (7*7-1): - cinfo->block_size = 7; - cinfo->natural_order = jpeg_natural_order7; - cinfo->lim_Se = cinfo->Se; - break; - case (8*8-1): - cinfo->block_size = 8; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (9*9-1): - cinfo->block_size = 9; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (10*10-1): - cinfo->block_size = 10; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (11*11-1): - cinfo->block_size = 11; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (12*12-1): - cinfo->block_size = 12; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (13*13-1): - cinfo->block_size = 13; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (14*14-1): - cinfo->block_size = 14; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (15*15-1): - cinfo->block_size = 15; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (16*16-1): - cinfo->block_size = 16; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - default: - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - break; - } - - /* We initialize DCT_scaled_size and min_DCT_scaled_size to block_size. - * In the full decompressor, - * this will be overridden by jpeg_calc_output_dimensions in jdmaster.c; - * but in the transcoder, - * jpeg_calc_output_dimensions is not used, so we must do it here. - */ - cinfo->min_DCT_h_scaled_size = cinfo->block_size; - cinfo->min_DCT_v_scaled_size = cinfo->block_size; - - /* Compute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->DCT_h_scaled_size = cinfo->block_size; - compptr->DCT_v_scaled_size = cinfo->block_size; - /* Size in DCT blocks */ - compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - /* downsampled_width and downsampled_height will also be overridden by - * jdmaster.c if we are doing full decompression. The transcoder library - * doesn't use these values, but the calling application might. - */ - /* Size in samples */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed, until color conversion says otherwise */ - compptr->component_needed = TRUE; - /* Mark no quantization table yet saved for component */ - compptr->quant_table = NULL; - } - - /* Compute number of fully interleaved MCU rows. */ - cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - - /* Decide whether file contains multiple scans */ - if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) - cinfo->inputctl->has_multiple_scans = TRUE; - else - cinfo->inputctl->has_multiple_scans = FALSE; -} - - -LOCAL(void) -per_scan_setup (j_decompress_ptr cinfo) -/* Do computations that are needed before processing a JPEG scan */ -/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ -{ - int ci, mcublks, tmp; - jpeg_component_info *compptr; - - if (cinfo->comps_in_scan == 1) { - - /* Noninterleaved (single-component) scan */ - compptr = cinfo->cur_comp_info[0]; - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_blocks; - cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - - /* For noninterleaved scan, always one block per MCU */ - compptr->MCU_width = 1; - compptr->MCU_height = 1; - compptr->MCU_blocks = 1; - compptr->MCU_sample_width = compptr->DCT_h_scaled_size; - compptr->last_col_width = 1; - /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. - */ - tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (tmp == 0) tmp = compptr->v_samp_factor; - compptr->last_row_height = tmp; - - /* Prepare array describing MCU composition */ - cinfo->blocks_in_MCU = 1; - cinfo->MCU_membership[0] = 0; - - } else { - - /* Interleaved (multi-component) scan */ - if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - - cinfo->blocks_in_MCU = 0; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ - compptr->MCU_width = compptr->h_samp_factor; - compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; - /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); - if (tmp == 0) tmp = compptr->MCU_width; - compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); - if (tmp == 0) tmp = compptr->MCU_height; - compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_blocks; - if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) - ERREXIT(cinfo, JERR_BAD_MCU_SIZE); - while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; - } - } - - } -} - - -/* - * Save away a copy of the Q-table referenced by each component present - * in the current scan, unless already saved during a prior scan. - * - * In a multiple-scan JPEG file, the encoder could assign different components - * the same Q-table slot number, but change table definitions between scans - * so that each component uses a different Q-table. (The IJG encoder is not - * currently capable of doing this, but other encoders might.) Since we want - * to be able to dequantize all the components at the end of the file, this - * means that we have to save away the table actually used for each component. - * We do this by copying the table at the start of the first scan containing - * the component. - * The JPEG spec prohibits the encoder from changing the contents of a Q-table - * slot between scans of a component using that slot. If the encoder does so - * anyway, this decoder will simply use the Q-table values that were current - * at the start of the first scan for the component. - * - * The decompressor output side looks only at the saved quant tables, - * not at the current Q-table slots. - */ - -LOCAL(void) -latch_quant_tables (j_decompress_ptr cinfo) -{ - int ci, qtblno; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* No work if we already saved Q-table for this component */ - if (compptr->quant_table != NULL) - continue; - /* Make sure specified quantization table is present */ - qtblno = compptr->quant_tbl_no; - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - /* OK, save away the quantization table */ - qtbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(JQUANT_TBL)); - MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); - compptr->quant_table = qtbl; - } -} - - -/* - * Initialize the input modules to read a scan of compressed data. - * The first call to this is done by jdmaster.c after initializing - * the entire decompressor (during jpeg_start_decompress). - * Subsequent calls come from consume_markers, below. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - per_scan_setup(cinfo); - latch_quant_tables(cinfo); - (*cinfo->entropy->start_pass) (cinfo); - (*cinfo->coef->start_input_pass) (cinfo); - cinfo->inputctl->consume_input = cinfo->coef->consume_data; -} - - -/* - * Finish up after inputting a compressed-data scan. - * This is called by the coefficient controller after it's read all - * the expected data of the scan. - */ - -METHODDEF(void) -finish_input_pass (j_decompress_ptr cinfo) -{ - (*cinfo->entropy->finish_pass) (cinfo); - cinfo->inputctl->consume_input = consume_markers; -} - - -/* - * Read JPEG markers before, between, or after compressed-data scans. - * Change state as necessary when a new scan is reached. - * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - * - * The consume_input method pointer points either here or to the - * coefficient controller's consume_data routine, depending on whether - * we are reading a compressed data segment or inter-segment markers. - * - * Note: This function should NOT return a pseudo SOS marker (with zero - * component number) to the caller. A pseudo marker received by - * read_markers is processed and then skipped for other markers. - */ - -METHODDEF(int) -consume_markers (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; - int val; - - if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ - return JPEG_REACHED_EOI; - - for (;;) { /* Loop to pass pseudo SOS marker */ - val = (*cinfo->marker->read_markers) (cinfo); - - switch (val) { - case JPEG_REACHED_SOS: /* Found SOS */ - if (inputctl->inheaders) { /* 1st SOS */ - if (inputctl->inheaders == 1) - initial_setup(cinfo); - if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ - inputctl->inheaders = 2; - break; - } - inputctl->inheaders = 0; - /* Note: start_input_pass must be called by jdmaster.c - * before any more input can be consumed. jdapimin.c is - * responsible for enforcing this sequencing. - */ - } else { /* 2nd or later SOS marker */ - if (! inputctl->pub.has_multiple_scans) - ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ - if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ - break; - start_input_pass(cinfo); - } - return val; - case JPEG_REACHED_EOI: /* Found EOI */ - inputctl->pub.eoi_reached = TRUE; - if (inputctl->inheaders) { /* Tables-only datastream, apparently */ - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_NO_SOS); - } else { - /* Prevent infinite loop in coef ctlr's decompress_data routine - * if user set output_scan_number larger than number of scans. - */ - if (cinfo->output_scan_number > cinfo->input_scan_number) - cinfo->output_scan_number = cinfo->input_scan_number; - } - return val; - case JPEG_SUSPENDED: - return val; - default: - return val; - } - } -} - - -/* - * Reset state to begin a fresh datastream. - */ - -METHODDEF(void) -reset_input_controller (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; - - inputctl->pub.consume_input = consume_markers; - inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ - inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = 1; - /* Reset other modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->marker->reset_marker_reader) (cinfo); - /* Reset progression state -- would be cleaner if entropy decoder did this */ - cinfo->coef_bits = NULL; -} - - -/* - * Initialize the input controller module. - * This is called only once, when the decompression object is created. - */ - -GLOBAL(void) -jinit_input_controller (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl; - - /* Create subobject in permanent pool */ - inputctl = (my_inputctl_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_input_controller)); - cinfo->inputctl = &inputctl->pub; - /* Initialize method pointers */ - inputctl->pub.consume_input = consume_markers; - inputctl->pub.reset_input_controller = reset_input_controller; - inputctl->pub.start_input_pass = start_input_pass; - inputctl->pub.finish_input_pass = finish_input_pass; - /* Initialize state: can't use reset_input_controller since we don't - * want to try to reset other modules yet. - */ - inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ - inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = 1; -} diff --git a/libraries/jpeg/jdmainct.c b/libraries/jpeg/jdmainct.c deleted file mode 100644 index 4d738fbaed..0000000000 --- a/libraries/jpeg/jdmainct.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * jdmainct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2002-2016 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the main buffer controller for decompression. - * The main buffer lies between the JPEG decompressor proper and the - * post-processor; it holds downsampled data in the JPEG colorspace. - * - * Note that this code is bypassed in raw-data mode, since the application - * supplies the equivalent of the main buffer in that case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * In the current system design, the main buffer need never be a full-image - * buffer; any full-height buffers will be found inside the coefficient or - * postprocessing controllers. Nonetheless, the main controller is not - * trivial. Its responsibility is to provide context rows for upsampling/ - * rescaling, and doing this in an efficient fashion is a bit tricky. - * - * Postprocessor input data is counted in "row groups". A row group is - * defined to be (v_samp_factor * DCT_v_scaled_size / min_DCT_v_scaled_size) - * sample rows of each component. (We require DCT_scaled_size values to be - * chosen such that these numbers are integers. In practice DCT_scaled_size - * values will likely be powers of two, so we actually have the stronger - * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) - * Upsampling will typically produce max_v_samp_factor pixel rows from each - * row group (times any additional scale factor that the upsampler is - * applying). - * - * The coefficient controller will deliver data to us one iMCU row at a time; - * each iMCU row contains v_samp_factor * DCT_v_scaled_size sample rows, or - * exactly min_DCT_v_scaled_size row groups. (This amount of data corresponds - * to one row of MCUs when the image is fully interleaved.) Note that the - * number of sample rows varies across components, but the number of row - * groups does not. Some garbage sample rows may be included in the last iMCU - * row at the bottom of the image. - * - * Depending on the vertical scaling algorithm used, the upsampler may need - * access to the sample row(s) above and below its current input row group. - * The upsampler is required to set need_context_rows TRUE at global selection - * time if so. When need_context_rows is FALSE, this controller can simply - * obtain one iMCU row at a time from the coefficient controller and dole it - * out as row groups to the postprocessor. - * - * When need_context_rows is TRUE, this controller guarantees that the buffer - * passed to postprocessing contains at least one row group's worth of samples - * above and below the row group(s) being processed. Note that the context - * rows "above" the first passed row group appear at negative row offsets in - * the passed buffer. At the top and bottom of the image, the required - * context rows are manufactured by duplicating the first or last real sample - * row; this avoids having special cases in the upsampling inner loops. - * - * The amount of context is fixed at one row group just because that's a - * convenient number for this controller to work with. The existing - * upsamplers really only need one sample row of context. An upsampler - * supporting arbitrary output rescaling might wish for more than one row - * group of context when shrinking the image; tough, we don't handle that. - * (This is justified by the assumption that downsizing will be handled mostly - * by adjusting the DCT_scaled_size values, so that the actual scale factor at - * the upsample step needn't be much less than one.) - * - * To provide the desired context, we have to retain the last two row groups - * of one iMCU row while reading in the next iMCU row. (The last row group - * can't be processed until we have another row group for its below-context, - * and so we have to save the next-to-last group too for its above-context.) - * We could do this most simply by copying data around in our buffer, but - * that'd be very slow. We can avoid copying any data by creating a rather - * strange pointer structure. Here's how it works. We allocate a workspace - * consisting of M+2 row groups (where M = min_DCT_v_scaled_size is the number - * of row groups per iMCU row). We create two sets of redundant pointers to - * the workspace. Labeling the physical row groups 0 to M+1, the synthesized - * pointer lists look like this: - * M+1 M-1 - * master pointer --> 0 master pointer --> 0 - * 1 1 - * ... ... - * M-3 M-3 - * M-2 M - * M-1 M+1 - * M M-2 - * M+1 M-1 - * 0 0 - * We read alternate iMCU rows using each master pointer; thus the last two - * row groups of the previous iMCU row remain un-overwritten in the workspace. - * The pointer lists are set up so that the required context rows appear to - * be adjacent to the proper places when we pass the pointer lists to the - * upsampler. - * - * The above pictures describe the normal state of the pointer lists. - * At top and bottom of the image, we diddle the pointer lists to duplicate - * the first or last sample row as necessary (this is cheaper than copying - * sample rows around). - * - * This scheme breaks down if M < 2, ie, min_DCT_v_scaled_size is 1. In that - * situation each iMCU row provides only one row group so the buffering logic - * must be different (eg, we must read two iMCU rows before we can emit the - * first row group). For now, we simply do not support providing context - * rows when min_DCT_v_scaled_size is 1. That combination seems unlikely to - * be worth providing --- if someone wants a 1/8th-size preview, they probably - * want it quick and dirty, so a context-free upsampler is sufficient. - */ - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_main_controller pub; /* public fields */ - - /* Pointer to allocated workspace (M or M+2 row groups). */ - JSAMPARRAY buffer[MAX_COMPONENTS]; - - JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ - JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ - - /* Remaining fields are only used in the context case. */ - - boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ - - /* These are the master pointers to the funny-order pointer lists. */ - JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ - - int whichptr; /* indicates which pointer set is now in use */ - int context_state; /* process_data state machine status */ - JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ -} my_main_controller; - -typedef my_main_controller * my_main_ptr; - -/* context_state values: */ -#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ -#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ -#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ - - -/* Forward declarations */ -METHODDEF(void) process_data_simple_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -METHODDEF(void) process_data_context_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -#ifdef QUANT_2PASS_SUPPORTED -METHODDEF(void) process_data_crank_post - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -#endif - - -LOCAL(void) -alloc_funny_pointers (j_decompress_ptr cinfo) -/* Allocate space for the funny pointer lists. - * This is done only once, not once per pass. - */ -{ - my_main_ptr mainp = (my_main_ptr) cinfo->main; - int ci, rgroup; - int M = cinfo->min_DCT_v_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY xbuf; - - /* Get top-level space for component array pointers. - * We alloc both arrays with one call to save a few cycles. - */ - mainp->xbuffer[0] = (JSAMPIMAGE) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); - mainp->xbuffer[1] = mainp->xbuffer[0] + cinfo->num_components; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / - cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ - /* Get space for pointer lists --- M+4 row groups in each list. - * We alloc both pointer lists with one call to save a few cycles. - */ - xbuf = (JSAMPARRAY) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); - xbuf += rgroup; /* want one row group at negative offsets */ - mainp->xbuffer[0][ci] = xbuf; - xbuf += rgroup * (M + 4); - mainp->xbuffer[1][ci] = xbuf; - } -} - - -LOCAL(void) -make_funny_pointers (j_decompress_ptr cinfo) -/* Create the funny pointer lists discussed in the comments above. - * The actual workspace is already allocated (in mainp->buffer), - * and the space for the pointer lists is allocated too. - * This routine just fills in the curiously ordered lists. - * This will be repeated at the beginning of each pass. - */ -{ - my_main_ptr mainp = (my_main_ptr) cinfo->main; - int ci, i, rgroup; - int M = cinfo->min_DCT_v_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY buf, xbuf0, xbuf1; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / - cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ - xbuf0 = mainp->xbuffer[0][ci]; - xbuf1 = mainp->xbuffer[1][ci]; - /* First copy the workspace pointers as-is */ - buf = mainp->buffer[ci]; - for (i = 0; i < rgroup * (M + 2); i++) { - xbuf0[i] = xbuf1[i] = buf[i]; - } - /* In the second list, put the last four row groups in swapped order */ - for (i = 0; i < rgroup * 2; i++) { - xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; - xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; - } - /* The wraparound pointers at top and bottom will be filled later - * (see set_wraparound_pointers, below). Initially we want the "above" - * pointers to duplicate the first actual data line. This only needs - * to happen in xbuffer[0]. - */ - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[0]; - } - } -} - - -LOCAL(void) -set_wraparound_pointers (j_decompress_ptr cinfo) -/* Set up the "wraparound" pointers at top and bottom of the pointer lists. - * This changes the pointer list state from top-of-image to the normal state. - */ -{ - my_main_ptr mainp = (my_main_ptr) cinfo->main; - int ci, i, rgroup; - int M = cinfo->min_DCT_v_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY xbuf0, xbuf1; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / - cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ - xbuf0 = mainp->xbuffer[0][ci]; - xbuf1 = mainp->xbuffer[1][ci]; - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; - xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; - xbuf0[rgroup*(M+2) + i] = xbuf0[i]; - xbuf1[rgroup*(M+2) + i] = xbuf1[i]; - } - } -} - - -LOCAL(void) -set_bottom_pointers (j_decompress_ptr cinfo) -/* Change the pointer lists to duplicate the last sample row at the bottom - * of the image. whichptr indicates which xbuffer holds the final iMCU row. - * Also sets rowgroups_avail to indicate number of nondummy row groups in row. - */ -{ - my_main_ptr mainp = (my_main_ptr) cinfo->main; - int ci, i, rgroup, iMCUheight, rows_left; - jpeg_component_info *compptr; - JSAMPARRAY xbuf; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Count sample rows in one iMCU row and in one row group */ - iMCUheight = compptr->v_samp_factor * compptr->DCT_v_scaled_size; - rgroup = iMCUheight / cinfo->min_DCT_v_scaled_size; - /* Count nondummy sample rows remaining for this component */ - rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); - if (rows_left == 0) rows_left = iMCUheight; - /* Count nondummy row groups. Should get same answer for each component, - * so we need only do it once. - */ - if (ci == 0) { - mainp->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); - } - /* Duplicate the last real sample row rgroup*2 times; this pads out the - * last partial rowgroup and ensures at least one full rowgroup of context. - */ - xbuf = mainp->xbuffer[mainp->whichptr][ci]; - for (i = 0; i < rgroup * 2; i++) { - xbuf[rows_left + i] = xbuf[rows_left-1]; - } - } -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_main_ptr mainp = (my_main_ptr) cinfo->main; - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (cinfo->upsample->need_context_rows) { - mainp->pub.process_data = process_data_context_main; - make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ - mainp->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ - mainp->context_state = CTX_PREPARE_FOR_IMCU; - mainp->iMCU_row_ctr = 0; - mainp->buffer_full = FALSE; /* Mark buffer empty */ - } else { - /* Simple case with no context needed */ - mainp->pub.process_data = process_data_simple_main; - mainp->rowgroup_ctr = mainp->rowgroups_avail; /* Mark buffer empty */ - } - break; -#ifdef QUANT_2PASS_SUPPORTED - case JBUF_CRANK_DEST: - /* For last pass of 2-pass quantization, just crank the postprocessor */ - mainp->pub.process_data = process_data_crank_post; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -/* - * Process some data. - * This handles the simple case where no context is required. - */ - -METHODDEF(void) -process_data_simple_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_main_ptr mainp = (my_main_ptr) cinfo->main; - - /* Read input data if we haven't filled the main buffer yet */ - if (mainp->rowgroup_ctr >= mainp->rowgroups_avail) { - if (! (*cinfo->coef->decompress_data) (cinfo, mainp->buffer)) - return; /* suspension forced, can do nothing more */ - mainp->rowgroup_ctr = 0; /* OK, we have an iMCU row to work with */ - } - - /* Note: at the bottom of the image, we may pass extra garbage row groups - * to the postprocessor. The postprocessor has to check for bottom - * of image anyway (at row resolution), so no point in us doing it too. - */ - - /* Feed the postprocessor */ - (*cinfo->post->post_process_data) (cinfo, mainp->buffer, - &mainp->rowgroup_ctr, mainp->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); -} - - -/* - * Process some data. - * This handles the case where context rows must be provided. - */ - -METHODDEF(void) -process_data_context_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_main_ptr mainp = (my_main_ptr) cinfo->main; - - /* Read input data if we haven't filled the main buffer yet */ - if (! mainp->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, - mainp->xbuffer[mainp->whichptr])) - return; /* suspension forced, can do nothing more */ - mainp->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - mainp->iMCU_row_ctr++; /* count rows received */ - } - - /* Postprocessor typically will not swallow all the input data it is handed - * in one call (due to filling the output buffer first). Must be prepared - * to exit and restart. This switch lets us keep track of how far we got. - * Note that each case falls through to the next on successful completion. - */ - switch (mainp->context_state) { - case CTX_POSTPONED_ROW: - /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, mainp->xbuffer[mainp->whichptr], - &mainp->rowgroup_ctr, mainp->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - if (mainp->rowgroup_ctr < mainp->rowgroups_avail) - return; /* Need to suspend */ - mainp->context_state = CTX_PREPARE_FOR_IMCU; - if (*out_row_ctr >= out_rows_avail) - return; /* Postprocessor exactly filled output buf */ - /*FALLTHROUGH*/ - case CTX_PREPARE_FOR_IMCU: - /* Prepare to process first M-1 row groups of this iMCU row */ - mainp->rowgroup_ctr = 0; - mainp->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size - 1); - /* Check for bottom of image: if so, tweak pointers to "duplicate" - * the last sample row, and adjust rowgroups_avail to ignore padding rows. - */ - if (mainp->iMCU_row_ctr == cinfo->total_iMCU_rows) - set_bottom_pointers(cinfo); - mainp->context_state = CTX_PROCESS_IMCU; - /*FALLTHROUGH*/ - case CTX_PROCESS_IMCU: - /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, mainp->xbuffer[mainp->whichptr], - &mainp->rowgroup_ctr, mainp->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - if (mainp->rowgroup_ctr < mainp->rowgroups_avail) - return; /* Need to suspend */ - /* After the first iMCU, change wraparound pointers to normal state */ - if (mainp->iMCU_row_ctr == 1) - set_wraparound_pointers(cinfo); - /* Prepare to load new iMCU row using other xbuffer list */ - mainp->whichptr ^= 1; /* 0=>1 or 1=>0 */ - mainp->buffer_full = FALSE; - /* Still need to process last row group of this iMCU row, */ - /* which is saved at index M+1 of the other xbuffer */ - mainp->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 1); - mainp->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 2); - mainp->context_state = CTX_POSTPONED_ROW; - } -} - - -/* - * Process some data. - * Final pass of two-pass quantization: just call the postprocessor. - * Source data will be the postprocessor controller's internal buffer. - */ - -#ifdef QUANT_2PASS_SUPPORTED - -METHODDEF(void) -process_data_crank_post (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, - (JDIMENSION *) NULL, (JDIMENSION) 0, - output_buf, out_row_ctr, out_rows_avail); -} - -#endif /* QUANT_2PASS_SUPPORTED */ - - -/* - * Initialize main buffer controller. - */ - -GLOBAL(void) -jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_main_ptr mainp; - int ci, rgroup, ngroups; - jpeg_component_info *compptr; - - mainp = (my_main_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_main_controller)); - cinfo->main = &mainp->pub; - mainp->pub.start_pass = start_pass_main; - - if (need_full_buffer) /* shouldn't happen */ - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - /* Allocate the workspace. - * ngroups is the number of row groups we need. - */ - if (cinfo->upsample->need_context_rows) { - if (cinfo->min_DCT_v_scaled_size < 2) /* unsupported, see comments above */ - ERREXIT(cinfo, JERR_NOTIMPL); - alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ - ngroups = cinfo->min_DCT_v_scaled_size + 2; - } else { - /* There are always min_DCT_v_scaled_size row groups in an iMCU row. */ - ngroups = cinfo->min_DCT_v_scaled_size; - mainp->rowgroups_avail = (JDIMENSION) ngroups; - } - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / - cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ - mainp->buffer[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), - (JDIMENSION) (rgroup * ngroups)); - } -} diff --git a/libraries/jpeg/jdmarker.c b/libraries/jpeg/jdmarker.c deleted file mode 100644 index 3fbe5c1657..0000000000 --- a/libraries/jpeg/jdmarker.c +++ /dev/null @@ -1,1511 +0,0 @@ -/* - * jdmarker.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2009-2013 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains routines to decode JPEG datastream markers. - * Most of the complexity arises from our desire to support input - * suspension: if not all of the data for a marker is available, - * we must exit back to the application. On resumption, we reprocess - * the marker. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -typedef enum { /* JPEG marker codes */ - M_SOF0 = 0xc0, - M_SOF1 = 0xc1, - M_SOF2 = 0xc2, - M_SOF3 = 0xc3, - - M_SOF5 = 0xc5, - M_SOF6 = 0xc6, - M_SOF7 = 0xc7, - - M_JPG = 0xc8, - M_SOF9 = 0xc9, - M_SOF10 = 0xca, - M_SOF11 = 0xcb, - - M_SOF13 = 0xcd, - M_SOF14 = 0xce, - M_SOF15 = 0xcf, - - M_DHT = 0xc4, - - M_DAC = 0xcc, - - M_RST0 = 0xd0, - M_RST1 = 0xd1, - M_RST2 = 0xd2, - M_RST3 = 0xd3, - M_RST4 = 0xd4, - M_RST5 = 0xd5, - M_RST6 = 0xd6, - M_RST7 = 0xd7, - - M_SOI = 0xd8, - M_EOI = 0xd9, - M_SOS = 0xda, - M_DQT = 0xdb, - M_DNL = 0xdc, - M_DRI = 0xdd, - M_DHP = 0xde, - M_EXP = 0xdf, - - M_APP0 = 0xe0, - M_APP1 = 0xe1, - M_APP2 = 0xe2, - M_APP3 = 0xe3, - M_APP4 = 0xe4, - M_APP5 = 0xe5, - M_APP6 = 0xe6, - M_APP7 = 0xe7, - M_APP8 = 0xe8, - M_APP9 = 0xe9, - M_APP10 = 0xea, - M_APP11 = 0xeb, - M_APP12 = 0xec, - M_APP13 = 0xed, - M_APP14 = 0xee, - M_APP15 = 0xef, - - M_JPG0 = 0xf0, - M_JPG8 = 0xf8, - M_JPG13 = 0xfd, - M_COM = 0xfe, - - M_TEM = 0x01, - - M_ERROR = 0x100 -} JPEG_MARKER; - - -/* Private state */ - -typedef struct { - struct jpeg_marker_reader pub; /* public fields */ - - /* Application-overridable marker processing methods */ - jpeg_marker_parser_method process_COM; - jpeg_marker_parser_method process_APPn[16]; - - /* Limit on marker data length to save for each marker type */ - unsigned int length_limit_COM; - unsigned int length_limit_APPn[16]; - - /* Status of COM/APPn marker saving */ - jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ - unsigned int bytes_read; /* data bytes read so far in marker */ - /* Note: cur_marker is not linked into marker_list until it's all read. */ -} my_marker_reader; - -typedef my_marker_reader * my_marker_ptr; - - -/* - * Macros for fetching data from the data source module. - * - * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect - * the current restart point; we update them only when we have reached a - * suitable place to restart if a suspension occurs. - */ - -/* Declare and initialize local copies of input pointer/count */ -#define INPUT_VARS(cinfo) \ - struct jpeg_source_mgr * datasrc = (cinfo)->src; \ - const JOCTET * next_input_byte = datasrc->next_input_byte; \ - size_t bytes_in_buffer = datasrc->bytes_in_buffer - -/* Unload the local copies --- do this only at a restart boundary */ -#define INPUT_SYNC(cinfo) \ - ( datasrc->next_input_byte = next_input_byte, \ - datasrc->bytes_in_buffer = bytes_in_buffer ) - -/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ -#define INPUT_RELOAD(cinfo) \ - ( next_input_byte = datasrc->next_input_byte, \ - bytes_in_buffer = datasrc->bytes_in_buffer ) - -/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. - * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, - * but we must reload the local copies after a successful fill. - */ -#define MAKE_BYTE_AVAIL(cinfo,action) \ - if (bytes_in_buffer == 0) { \ - if (! (*datasrc->fill_input_buffer) (cinfo)) \ - { action; } \ - INPUT_RELOAD(cinfo); \ - } - -/* Read a byte into variable V. - * If must suspend, take the specified action (typically "return FALSE"). - */ -#define INPUT_BYTE(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) - -/* As above, but read two bytes interpreted as an unsigned 16-bit integer. - * V should be declared unsigned int or perhaps INT32. - */ -#define INPUT_2BYTES(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V += GETJOCTET(*next_input_byte++); ) - - -/* - * Routines to process JPEG markers. - * - * Entry condition: JPEG marker itself has been read and its code saved - * in cinfo->unread_marker; input restart point is just after the marker. - * - * Exit: if return TRUE, have read and processed any parameters, and have - * updated the restart point to point after the parameters. - * If return FALSE, was forced to suspend before reaching end of - * marker parameters; restart point has not been moved. Same routine - * will be called again after application supplies more input data. - * - * This approach to suspension assumes that all of a marker's parameters - * can fit into a single input bufferload. This should hold for "normal" - * markers. Some COM/APPn markers might have large parameter segments - * that might not fit. If we are simply dropping such a marker, we use - * skip_input_data to get past it, and thereby put the problem on the - * source manager's shoulders. If we are saving the marker's contents - * into memory, we use a slightly different convention: when forced to - * suspend, the marker processor updates the restart point to the end of - * what it's consumed (ie, the end of the buffer) before returning FALSE. - * On resumption, cinfo->unread_marker still contains the marker code, - * but the data source will point to the next chunk of marker data. - * The marker processor must retain internal state to deal with this. - * - * Note that we don't bother to avoid duplicate trace messages if a - * suspension occurs within marker parameters. Other side effects - * require more care. - */ - - -LOCAL(boolean) -get_soi (j_decompress_ptr cinfo) -/* Process an SOI marker */ -{ - int i; - - TRACEMS(cinfo, 1, JTRC_SOI); - - if (cinfo->marker->saw_SOI) - ERREXIT(cinfo, JERR_SOI_DUPLICATE); - - /* Reset all parameters that are defined to be reset by SOI */ - - for (i = 0; i < NUM_ARITH_TBLS; i++) { - cinfo->arith_dc_L[i] = 0; - cinfo->arith_dc_U[i] = 1; - cinfo->arith_ac_K[i] = 5; - } - cinfo->restart_interval = 0; - - /* Set initial assumptions for colorspace etc */ - - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->color_transform = JCT_NONE; - cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ - - cinfo->saw_JFIF_marker = FALSE; - cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ - cinfo->JFIF_minor_version = 1; - cinfo->density_unit = 0; - cinfo->X_density = 1; - cinfo->Y_density = 1; - cinfo->saw_Adobe_marker = FALSE; - cinfo->Adobe_transform = 0; - - cinfo->marker->saw_SOI = TRUE; - - return TRUE; -} - - -LOCAL(boolean) -get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, - boolean is_arith) -/* Process a SOFn marker */ -{ - INT32 length; - int c, ci, i; - jpeg_component_info * compptr; - INPUT_VARS(cinfo); - - cinfo->is_baseline = is_baseline; - cinfo->progressive_mode = is_prog; - cinfo->arith_code = is_arith; - - INPUT_2BYTES(cinfo, length, return FALSE); - - INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); - INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); - INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); - INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); - - length -= 8; - - TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, - (int) cinfo->image_width, (int) cinfo->image_height, - cinfo->num_components); - - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_DUPLICATE); - - /* We don't support files in which the image height is initially specified */ - /* as 0 and is later redefined by DNL. As long as we have to check that, */ - /* might as well have a general sanity check. */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || - cinfo->num_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); - - if (length != (cinfo->num_components * 3)) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - if (cinfo->comp_info == NULL) /* do only once, even if suspend */ - cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * SIZEOF(jpeg_component_info)); - - for (ci = 0; ci < cinfo->num_components; ci++) { - INPUT_BYTE(cinfo, c, return FALSE); - /* Check to see whether component id has already been seen */ - /* (in violation of the spec, but unfortunately seen in some */ - /* files). If so, create "fake" component id equal to the */ - /* max id seen so far + 1. */ - for (i = 0, compptr = cinfo->comp_info; i < ci; i++, compptr++) { - if (c == compptr->component_id) { - compptr = cinfo->comp_info; - c = compptr->component_id; - compptr++; - for (i = 1; i < ci; i++, compptr++) { - if (compptr->component_id > c) c = compptr->component_id; - } - c++; - break; - } - } - compptr->component_id = c; - compptr->component_index = ci; - INPUT_BYTE(cinfo, c, return FALSE); - compptr->h_samp_factor = (c >> 4) & 15; - compptr->v_samp_factor = (c ) & 15; - INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); - - TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, - compptr->component_id, compptr->h_samp_factor, - compptr->v_samp_factor, compptr->quant_tbl_no); - } - - cinfo->marker->saw_SOF = TRUE; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_sos (j_decompress_ptr cinfo) -/* Process a SOS marker */ -{ - INT32 length; - int c, ci, i, n; - jpeg_component_info * compptr; - INPUT_VARS(cinfo); - - if (! cinfo->marker->saw_SOF) - ERREXITS(cinfo, JERR_SOF_BEFORE, "SOS"); - - INPUT_2BYTES(cinfo, length, return FALSE); - - INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ - - TRACEMS1(cinfo, 1, JTRC_SOS, n); - - if (length != (n * 2 + 6) || n > MAX_COMPS_IN_SCAN || - (n == 0 && !cinfo->progressive_mode)) - /* pseudo SOS marker only allowed in progressive mode */ - ERREXIT(cinfo, JERR_BAD_LENGTH); - - cinfo->comps_in_scan = n; - - /* Collect the component-spec parameters */ - - for (i = 0; i < n; i++) { - INPUT_BYTE(cinfo, c, return FALSE); - - /* Detect the case where component id's are not unique, and, if so, */ - /* create a fake component id using the same logic as in get_sof. */ - /* Note: This also ensures that all of the SOF components are */ - /* referenced in the single scan case, which prevents access to */ - /* uninitialized memory in later decoding stages. */ - for (ci = 0; ci < i; ci++) { - if (c == cinfo->cur_comp_info[ci]->component_id) { - c = cinfo->cur_comp_info[0]->component_id; - for (ci = 1; ci < i; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (compptr->component_id > c) c = compptr->component_id; - } - c++; - break; - } - } - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (c == compptr->component_id) - goto id_found; - } - - ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, c); - - id_found: - - cinfo->cur_comp_info[i] = compptr; - INPUT_BYTE(cinfo, c, return FALSE); - compptr->dc_tbl_no = (c >> 4) & 15; - compptr->ac_tbl_no = (c ) & 15; - - TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, compptr->component_id, - compptr->dc_tbl_no, compptr->ac_tbl_no); - } - - /* Collect the additional scan parameters Ss, Se, Ah/Al. */ - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Ss = c; - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Se = c; - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Ah = (c >> 4) & 15; - cinfo->Al = (c ) & 15; - - TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, - cinfo->Ah, cinfo->Al); - - /* Prepare to scan data & restart markers */ - cinfo->marker->next_restart_num = 0; - - /* Count another (non-pseudo) SOS marker */ - if (n) cinfo->input_scan_number++; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -#ifdef D_ARITH_CODING_SUPPORTED - -LOCAL(boolean) -get_dac (j_decompress_ptr cinfo) -/* Process a DAC marker */ -{ - INT32 length; - int index, val; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - INPUT_BYTE(cinfo, index, return FALSE); - INPUT_BYTE(cinfo, val, return FALSE); - - length -= 2; - - TRACEMS2(cinfo, 1, JTRC_DAC, index, val); - - if (index < 0 || index >= (2*NUM_ARITH_TBLS)) - ERREXIT1(cinfo, JERR_DAC_INDEX, index); - - if (index >= NUM_ARITH_TBLS) { /* define AC table */ - cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; - } else { /* define DC table */ - cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); - cinfo->arith_dc_U[index] = (UINT8) (val >> 4); - if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) - ERREXIT1(cinfo, JERR_DAC_VALUE, val); - } - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - -#else /* ! D_ARITH_CODING_SUPPORTED */ - -#define get_dac(cinfo) skip_variable(cinfo) - -#endif /* D_ARITH_CODING_SUPPORTED */ - - -LOCAL(boolean) -get_dht (j_decompress_ptr cinfo) -/* Process a DHT marker */ -{ - INT32 length; - UINT8 bits[17]; - UINT8 huffval[256]; - int i, index, count; - JHUFF_TBL **htblptr; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 16) { - INPUT_BYTE(cinfo, index, return FALSE); - - TRACEMS1(cinfo, 1, JTRC_DHT, index); - - bits[0] = 0; - count = 0; - for (i = 1; i <= 16; i++) { - INPUT_BYTE(cinfo, bits[i], return FALSE); - count += bits[i]; - } - - length -= 1 + 16; - - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[1], bits[2], bits[3], bits[4], - bits[5], bits[6], bits[7], bits[8]); - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[9], bits[10], bits[11], bits[12], - bits[13], bits[14], bits[15], bits[16]); - - /* Here we just do minimal validation of the counts to avoid walking - * off the end of our table space. jdhuff.c will check more carefully. - */ - if (count > 256 || ((INT32) count) > length) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - - MEMZERO(huffval, SIZEOF(huffval)); /* pre-zero array for later copy */ - - for (i = 0; i < count; i++) - INPUT_BYTE(cinfo, huffval[i], return FALSE); - - length -= count; - - if (index & 0x10) { /* AC table definition */ - index -= 0x10; - htblptr = &cinfo->ac_huff_tbl_ptrs[index]; - } else { /* DC table definition */ - htblptr = &cinfo->dc_huff_tbl_ptrs[index]; - } - - if (index < 0 || index >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_DHT_INDEX, index); - - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - - MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); - MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_dqt (j_decompress_ptr cinfo) -/* Process a DQT marker */ -{ - INT32 length, count, i; - int n, prec; - unsigned int tmp; - JQUANT_TBL *quant_ptr; - const int *natural_order; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - length--; - INPUT_BYTE(cinfo, n, return FALSE); - prec = n >> 4; - n &= 0x0F; - - TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); - - if (n >= NUM_QUANT_TBLS) - ERREXIT1(cinfo, JERR_DQT_INDEX, n); - - if (cinfo->quant_tbl_ptrs[n] == NULL) - cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); - quant_ptr = cinfo->quant_tbl_ptrs[n]; - - if (prec) { - if (length < DCTSIZE2 * 2) { - /* Initialize full table for safety. */ - for (i = 0; i < DCTSIZE2; i++) { - quant_ptr->quantval[i] = 1; - } - count = length >> 1; - } else - count = DCTSIZE2; - } else { - if (length < DCTSIZE2) { - /* Initialize full table for safety. */ - for (i = 0; i < DCTSIZE2; i++) { - quant_ptr->quantval[i] = 1; - } - count = length; - } else - count = DCTSIZE2; - } - - switch (count) { - case (2*2): natural_order = jpeg_natural_order2; break; - case (3*3): natural_order = jpeg_natural_order3; break; - case (4*4): natural_order = jpeg_natural_order4; break; - case (5*5): natural_order = jpeg_natural_order5; break; - case (6*6): natural_order = jpeg_natural_order6; break; - case (7*7): natural_order = jpeg_natural_order7; break; - default: natural_order = jpeg_natural_order; break; - } - - for (i = 0; i < count; i++) { - if (prec) - INPUT_2BYTES(cinfo, tmp, return FALSE); - else - INPUT_BYTE(cinfo, tmp, return FALSE); - /* We convert the zigzag-order table to natural array order. */ - quant_ptr->quantval[natural_order[i]] = (UINT16) tmp; - } - - if (cinfo->err->trace_level >= 2) { - for (i = 0; i < DCTSIZE2; i += 8) { - TRACEMS8(cinfo, 2, JTRC_QUANTVALS, - quant_ptr->quantval[i], quant_ptr->quantval[i+1], - quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], - quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], - quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); - } - } - - length -= count; - if (prec) length -= count; - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_dri (j_decompress_ptr cinfo) -/* Process a DRI marker */ -{ - INT32 length; - unsigned int tmp; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - - if (length != 4) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_2BYTES(cinfo, tmp, return FALSE); - - TRACEMS1(cinfo, 1, JTRC_DRI, tmp); - - cinfo->restart_interval = tmp; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_lse (j_decompress_ptr cinfo) -/* Process an LSE marker */ -{ - INT32 length; - unsigned int tmp; - int cid; - INPUT_VARS(cinfo); - - if (! cinfo->marker->saw_SOF) - ERREXITS(cinfo, JERR_SOF_BEFORE, "LSE"); - - if (cinfo->num_components < 3) goto bad; - - INPUT_2BYTES(cinfo, length, return FALSE); - - if (length != 24) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_BYTE(cinfo, tmp, return FALSE); - if (tmp != 0x0D) /* ID inverse transform specification */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - INPUT_2BYTES(cinfo, tmp, return FALSE); - if (tmp != MAXJSAMPLE) goto bad; /* MAXTRANS */ - INPUT_BYTE(cinfo, tmp, return FALSE); - if (tmp != 3) goto bad; /* Nt=3 */ - INPUT_BYTE(cinfo, cid, return FALSE); - if (cid != cinfo->comp_info[1].component_id) goto bad; - INPUT_BYTE(cinfo, cid, return FALSE); - if (cid != cinfo->comp_info[0].component_id) goto bad; - INPUT_BYTE(cinfo, cid, return FALSE); - if (cid != cinfo->comp_info[2].component_id) goto bad; - INPUT_BYTE(cinfo, tmp, return FALSE); - if (tmp != 0x80) goto bad; /* F1: CENTER1=1, NORM1=0 */ - INPUT_2BYTES(cinfo, tmp, return FALSE); - if (tmp != 0) goto bad; /* A(1,1)=0 */ - INPUT_2BYTES(cinfo, tmp, return FALSE); - if (tmp != 0) goto bad; /* A(1,2)=0 */ - INPUT_BYTE(cinfo, tmp, return FALSE); - if (tmp != 0) goto bad; /* F2: CENTER2=0, NORM2=0 */ - INPUT_2BYTES(cinfo, tmp, return FALSE); - if (tmp != 1) goto bad; /* A(2,1)=1 */ - INPUT_2BYTES(cinfo, tmp, return FALSE); - if (tmp != 0) goto bad; /* A(2,2)=0 */ - INPUT_BYTE(cinfo, tmp, return FALSE); - if (tmp != 0) goto bad; /* F3: CENTER3=0, NORM3=0 */ - INPUT_2BYTES(cinfo, tmp, return FALSE); - if (tmp != 1) goto bad; /* A(3,1)=1 */ - INPUT_2BYTES(cinfo, tmp, return FALSE); - if (tmp != 0) { /* A(3,2)=0 */ - bad: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - } - - /* OK, valid transform that we can handle. */ - cinfo->color_transform = JCT_SUBTRACT_GREEN; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -/* - * Routines for processing APPn and COM markers. - * These are either saved in memory or discarded, per application request. - * APP0 and APP14 are specially checked to see if they are - * JFIF and Adobe markers, respectively. - */ - -#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ -#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ -#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ - - -LOCAL(void) -examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) -/* Examine first few bytes from an APP0. - * Take appropriate action if it is a JFIF marker. - * datalen is # of bytes at data[], remaining is length of rest of marker data. - */ -{ - INT32 totallen = (INT32) datalen + remaining; - - if (datalen >= APP0_DATA_LEN && - GETJOCTET(data[0]) == 0x4A && - GETJOCTET(data[1]) == 0x46 && - GETJOCTET(data[2]) == 0x49 && - GETJOCTET(data[3]) == 0x46 && - GETJOCTET(data[4]) == 0) { - /* Found JFIF APP0 marker: save info */ - cinfo->saw_JFIF_marker = TRUE; - cinfo->JFIF_major_version = GETJOCTET(data[5]); - cinfo->JFIF_minor_version = GETJOCTET(data[6]); - cinfo->density_unit = GETJOCTET(data[7]); - cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); - cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); - /* Check version. - * Major version must be 1 or 2, anything else signals an incompatible - * change. - * (We used to treat this as an error, but now it's a nonfatal warning, - * because some bozo at Hijaak couldn't read the spec.) - * Minor version should be 0..2, but process anyway if newer. - */ - if (cinfo->JFIF_major_version != 1 && cinfo->JFIF_major_version != 2) - WARNMS2(cinfo, JWRN_JFIF_MAJOR, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version); - /* Generate trace messages */ - TRACEMS5(cinfo, 1, JTRC_JFIF, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version, - cinfo->X_density, cinfo->Y_density, cinfo->density_unit); - /* Validate thumbnail dimensions and issue appropriate messages */ - if (GETJOCTET(data[12]) | GETJOCTET(data[13])) - TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, - GETJOCTET(data[12]), GETJOCTET(data[13])); - totallen -= APP0_DATA_LEN; - if (totallen != - ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) - TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); - } else if (datalen >= 6 && - GETJOCTET(data[0]) == 0x4A && - GETJOCTET(data[1]) == 0x46 && - GETJOCTET(data[2]) == 0x58 && - GETJOCTET(data[3]) == 0x58 && - GETJOCTET(data[4]) == 0) { - /* Found JFIF "JFXX" extension APP0 marker */ - /* The library doesn't actually do anything with these, - * but we try to produce a helpful trace message. - */ - switch (GETJOCTET(data[5])) { - case 0x10: - TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); - break; - case 0x11: - TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); - break; - case 0x13: - TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); - break; - default: - TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, - GETJOCTET(data[5]), (int) totallen); - break; - } - } else { - /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ - TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); - } -} - - -LOCAL(void) -examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) -/* Examine first few bytes from an APP14. - * Take appropriate action if it is an Adobe marker. - * datalen is # of bytes at data[], remaining is length of rest of marker data. - */ -{ - unsigned int version, flags0, flags1, transform; - - if (datalen >= APP14_DATA_LEN && - GETJOCTET(data[0]) == 0x41 && - GETJOCTET(data[1]) == 0x64 && - GETJOCTET(data[2]) == 0x6F && - GETJOCTET(data[3]) == 0x62 && - GETJOCTET(data[4]) == 0x65) { - /* Found Adobe APP14 marker */ - version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); - flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); - flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); - transform = GETJOCTET(data[11]); - TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); - cinfo->saw_Adobe_marker = TRUE; - cinfo->Adobe_transform = (UINT8) transform; - } else { - /* Start of APP14 does not match "Adobe", or too short */ - TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); - } -} - - -METHODDEF(boolean) -get_interesting_appn (j_decompress_ptr cinfo) -/* Process an APP0 or APP14 marker without saving it */ -{ - INT32 length; - JOCTET b[APPN_DATA_LEN]; - unsigned int i, numtoread; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - /* get the interesting part of the marker data */ - if (length >= APPN_DATA_LEN) - numtoread = APPN_DATA_LEN; - else if (length > 0) - numtoread = (unsigned int) length; - else - numtoread = 0; - for (i = 0; i < numtoread; i++) - INPUT_BYTE(cinfo, b[i], return FALSE); - length -= numtoread; - - /* process it */ - switch (cinfo->unread_marker) { - case M_APP0: - examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); - break; - case M_APP14: - examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); - break; - default: - /* can't get here unless jpeg_save_markers chooses wrong processor */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; - } - - /* skip any remaining data -- could be lots */ - INPUT_SYNC(cinfo); - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - - -#ifdef SAVE_MARKERS_SUPPORTED - -METHODDEF(boolean) -save_marker (j_decompress_ptr cinfo) -/* Save an APPn or COM marker into the marker list */ -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - jpeg_saved_marker_ptr cur_marker = marker->cur_marker; - unsigned int bytes_read, data_length; - JOCTET FAR * data; - INT32 length = 0; - INPUT_VARS(cinfo); - - if (cur_marker == NULL) { - /* begin reading a marker */ - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - if (length >= 0) { /* watch out for bogus length word */ - /* figure out how much we want to save */ - unsigned int limit; - if (cinfo->unread_marker == (int) M_COM) - limit = marker->length_limit_COM; - else - limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; - if ((unsigned int) length < limit) - limit = (unsigned int) length; - /* allocate and initialize the marker item */ - cur_marker = (jpeg_saved_marker_ptr) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(struct jpeg_marker_struct) + limit); - cur_marker->next = NULL; - cur_marker->marker = (UINT8) cinfo->unread_marker; - cur_marker->original_length = (unsigned int) length; - cur_marker->data_length = limit; - /* data area is just beyond the jpeg_marker_struct */ - data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); - marker->cur_marker = cur_marker; - marker->bytes_read = 0; - bytes_read = 0; - data_length = limit; - } else { - /* deal with bogus length word */ - bytes_read = data_length = 0; - data = NULL; - } - } else { - /* resume reading a marker */ - bytes_read = marker->bytes_read; - data_length = cur_marker->data_length; - data = cur_marker->data + bytes_read; - } - - while (bytes_read < data_length) { - INPUT_SYNC(cinfo); /* move the restart point to here */ - marker->bytes_read = bytes_read; - /* If there's not at least one byte in buffer, suspend */ - MAKE_BYTE_AVAIL(cinfo, return FALSE); - /* Copy bytes with reasonable rapidity */ - while (bytes_read < data_length && bytes_in_buffer > 0) { - *data++ = *next_input_byte++; - bytes_in_buffer--; - bytes_read++; - } - } - - /* Done reading what we want to read */ - if (cur_marker != NULL) { /* will be NULL if bogus length word */ - /* Add new marker to end of list */ - if (cinfo->marker_list == NULL) { - cinfo->marker_list = cur_marker; - } else { - jpeg_saved_marker_ptr prev = cinfo->marker_list; - while (prev->next != NULL) - prev = prev->next; - prev->next = cur_marker; - } - /* Reset pointer & calc remaining data length */ - data = cur_marker->data; - length = cur_marker->original_length - data_length; - } - /* Reset to initial state for next marker */ - marker->cur_marker = NULL; - - /* Process the marker if interesting; else just make a generic trace msg */ - switch (cinfo->unread_marker) { - case M_APP0: - examine_app0(cinfo, data, data_length, length); - break; - case M_APP14: - examine_app14(cinfo, data, data_length, length); - break; - default: - TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, - (int) (data_length + length)); - break; - } - - /* skip any remaining data -- could be lots */ - INPUT_SYNC(cinfo); /* do before skip_input_data */ - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - -#endif /* SAVE_MARKERS_SUPPORTED */ - - -METHODDEF(boolean) -skip_variable (j_decompress_ptr cinfo) -/* Skip over an unknown or uninteresting variable-length marker */ -{ - INT32 length; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); - - INPUT_SYNC(cinfo); /* do before skip_input_data */ - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - - -/* - * Find the next JPEG marker, save it in cinfo->unread_marker. - * Returns FALSE if had to suspend before reaching a marker; - * in that case cinfo->unread_marker is unchanged. - * - * Note that the result might not be a valid marker code, - * but it will never be 0 or FF. - */ - -LOCAL(boolean) -next_marker (j_decompress_ptr cinfo) -{ - int c; - INPUT_VARS(cinfo); - - for (;;) { - INPUT_BYTE(cinfo, c, return FALSE); - /* Skip any non-FF bytes. - * This may look a bit inefficient, but it will not occur in a valid file. - * We sync after each discarded byte so that a suspending data source - * can discard the byte from its buffer. - */ - while (c != 0xFF) { - cinfo->marker->discarded_bytes++; - INPUT_SYNC(cinfo); - INPUT_BYTE(cinfo, c, return FALSE); - } - /* This loop swallows any duplicate FF bytes. Extra FFs are legal as - * pad bytes, so don't count them in discarded_bytes. We assume there - * will not be so many consecutive FF bytes as to overflow a suspending - * data source's input buffer. - */ - do { - INPUT_BYTE(cinfo, c, return FALSE); - } while (c == 0xFF); - if (c != 0) - break; /* found a valid marker, exit loop */ - /* Reach here if we found a stuffed-zero data sequence (FF/00). - * Discard it and loop back to try again. - */ - cinfo->marker->discarded_bytes += 2; - INPUT_SYNC(cinfo); - } - - if (cinfo->marker->discarded_bytes != 0) { - WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); - cinfo->marker->discarded_bytes = 0; - } - - cinfo->unread_marker = c; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -first_marker (j_decompress_ptr cinfo) -/* Like next_marker, but used to obtain the initial SOI marker. */ -/* For this marker, we do not allow preceding garbage or fill; otherwise, - * we might well scan an entire input file before realizing it ain't JPEG. - * If an application wants to process non-JFIF files, it must seek to the - * SOI before calling the JPEG library. - */ -{ - int c, c2; - INPUT_VARS(cinfo); - - INPUT_BYTE(cinfo, c, return FALSE); - INPUT_BYTE(cinfo, c2, return FALSE); - if (c != 0xFF || c2 != (int) M_SOI) - ERREXIT2(cinfo, JERR_NO_SOI, c, c2); - - cinfo->unread_marker = c2; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -/* - * Read markers until SOS or EOI. - * - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - * - * Note: This function may return a pseudo SOS marker (with zero - * component number) for treat by input controller's consume_input. - * consume_input itself should filter out (skip) the pseudo marker - * after processing for the caller. - */ - -METHODDEF(int) -read_markers (j_decompress_ptr cinfo) -{ - /* Outer loop repeats once for each marker. */ - for (;;) { - /* Collect the marker proper, unless we already did. */ - /* NB: first_marker() enforces the requirement that SOI appear first. */ - if (cinfo->unread_marker == 0) { - if (! cinfo->marker->saw_SOI) { - if (! first_marker(cinfo)) - return JPEG_SUSPENDED; - } else { - if (! next_marker(cinfo)) - return JPEG_SUSPENDED; - } - } - /* At this point cinfo->unread_marker contains the marker code and the - * input point is just past the marker proper, but before any parameters. - * A suspension will cause us to return with this state still true. - */ - switch (cinfo->unread_marker) { - case M_SOI: - if (! get_soi(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_SOF0: /* Baseline */ - if (! get_sof(cinfo, TRUE, FALSE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF1: /* Extended sequential, Huffman */ - if (! get_sof(cinfo, FALSE, FALSE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF2: /* Progressive, Huffman */ - if (! get_sof(cinfo, FALSE, TRUE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF9: /* Extended sequential, arithmetic */ - if (! get_sof(cinfo, FALSE, FALSE, TRUE)) - return JPEG_SUSPENDED; - break; - - case M_SOF10: /* Progressive, arithmetic */ - if (! get_sof(cinfo, FALSE, TRUE, TRUE)) - return JPEG_SUSPENDED; - break; - - /* Currently unsupported SOFn types */ - case M_SOF3: /* Lossless, Huffman */ - case M_SOF5: /* Differential sequential, Huffman */ - case M_SOF6: /* Differential progressive, Huffman */ - case M_SOF7: /* Differential lossless, Huffman */ - case M_JPG: /* Reserved for JPEG extensions */ - case M_SOF11: /* Lossless, arithmetic */ - case M_SOF13: /* Differential sequential, arithmetic */ - case M_SOF14: /* Differential progressive, arithmetic */ - case M_SOF15: /* Differential lossless, arithmetic */ - ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); - break; - - case M_SOS: - if (! get_sos(cinfo)) - return JPEG_SUSPENDED; - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_SOS; - - case M_EOI: - TRACEMS(cinfo, 1, JTRC_EOI); - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_EOI; - - case M_DAC: - if (! get_dac(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DHT: - if (! get_dht(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DQT: - if (! get_dqt(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DRI: - if (! get_dri(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_JPG8: - if (! get_lse(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_APP0: - case M_APP1: - case M_APP2: - case M_APP3: - case M_APP4: - case M_APP5: - case M_APP6: - case M_APP7: - case M_APP8: - case M_APP9: - case M_APP10: - case M_APP11: - case M_APP12: - case M_APP13: - case M_APP14: - case M_APP15: - if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ - cinfo->unread_marker - (int) M_APP0]) (cinfo)) - return JPEG_SUSPENDED; - break; - - case M_COM: - if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) - return JPEG_SUSPENDED; - break; - - case M_RST0: /* these are all parameterless */ - case M_RST1: - case M_RST2: - case M_RST3: - case M_RST4: - case M_RST5: - case M_RST6: - case M_RST7: - case M_TEM: - TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); - break; - - case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ - if (! skip_variable(cinfo)) - return JPEG_SUSPENDED; - break; - - default: /* must be DHP, EXP, JPGn, or RESn */ - /* For now, we treat the reserved markers as fatal errors since they are - * likely to be used to signal incompatible JPEG Part 3 extensions. - * Once the JPEG 3 version-number marker is well defined, this code - * ought to change! - */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; - } - /* Successfully processed marker, so reset state variable */ - cinfo->unread_marker = 0; - } /* end loop */ -} - - -/* - * Read a restart marker, which is expected to appear next in the datastream; - * if the marker is not there, take appropriate recovery action. - * Returns FALSE if suspension is required. - * - * This is called by the entropy decoder after it has read an appropriate - * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder - * has already read a marker from the data source. Under normal conditions - * cinfo->unread_marker will be reset to 0 before returning; if not reset, - * it holds a marker which the decoder will be unable to read past. - */ - -METHODDEF(boolean) -read_restart_marker (j_decompress_ptr cinfo) -{ - /* Obtain a marker unless we already did. */ - /* Note that next_marker will complain if it skips any data. */ - if (cinfo->unread_marker == 0) { - if (! next_marker(cinfo)) - return FALSE; - } - - if (cinfo->unread_marker == - ((int) M_RST0 + cinfo->marker->next_restart_num)) { - /* Normal case --- swallow the marker and let entropy decoder continue */ - TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); - cinfo->unread_marker = 0; - } else { - /* Uh-oh, the restart markers have been messed up. */ - /* Let the data source manager determine how to resync. */ - if (! (*cinfo->src->resync_to_restart) (cinfo, - cinfo->marker->next_restart_num)) - return FALSE; - } - - /* Update next-restart state */ - cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; - - return TRUE; -} - - -/* - * This is the default resync_to_restart method for data source managers - * to use if they don't have any better approach. Some data source managers - * may be able to back up, or may have additional knowledge about the data - * which permits a more intelligent recovery strategy; such managers would - * presumably supply their own resync method. - * - * read_restart_marker calls resync_to_restart if it finds a marker other than - * the restart marker it was expecting. (This code is *not* used unless - * a nonzero restart interval has been declared.) cinfo->unread_marker is - * the marker code actually found (might be anything, except 0 or FF). - * The desired restart marker number (0..7) is passed as a parameter. - * This routine is supposed to apply whatever error recovery strategy seems - * appropriate in order to position the input stream to the next data segment. - * Note that cinfo->unread_marker is treated as a marker appearing before - * the current data-source input point; usually it should be reset to zero - * before returning. - * Returns FALSE if suspension is required. - * - * This implementation is substantially constrained by wanting to treat the - * input as a data stream; this means we can't back up. Therefore, we have - * only the following actions to work with: - * 1. Simply discard the marker and let the entropy decoder resume at next - * byte of file. - * 2. Read forward until we find another marker, discarding intervening - * data. (In theory we could look ahead within the current bufferload, - * without having to discard data if we don't find the desired marker. - * This idea is not implemented here, in part because it makes behavior - * dependent on buffer size and chance buffer-boundary positions.) - * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). - * This will cause the entropy decoder to process an empty data segment, - * inserting dummy zeroes, and then we will reprocess the marker. - * - * #2 is appropriate if we think the desired marker lies ahead, while #3 is - * appropriate if the found marker is a future restart marker (indicating - * that we have missed the desired restart marker, probably because it got - * corrupted). - * We apply #2 or #3 if the found marker is a restart marker no more than - * two counts behind or ahead of the expected one. We also apply #2 if the - * found marker is not a legal JPEG marker code (it's certainly bogus data). - * If the found marker is a restart marker more than 2 counts away, we do #1 - * (too much risk that the marker is erroneous; with luck we will be able to - * resync at some future point). - * For any valid non-restart JPEG marker, we apply #3. This keeps us from - * overrunning the end of a scan. An implementation limited to single-scan - * files might find it better to apply #2 for markers other than EOI, since - * any other marker would have to be bogus data in that case. - */ - -GLOBAL(boolean) -jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) -{ - int marker = cinfo->unread_marker; - int action = 1; - - /* Always put up a warning. */ - WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); - - /* Outer loop handles repeated decision after scanning forward. */ - for (;;) { - if (marker < (int) M_SOF0) - action = 2; /* invalid marker */ - else if (marker < (int) M_RST0 || marker > (int) M_RST7) - action = 3; /* valid non-restart marker */ - else { - if (marker == ((int) M_RST0 + ((desired+1) & 7)) || - marker == ((int) M_RST0 + ((desired+2) & 7))) - action = 3; /* one of the next two expected restarts */ - else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || - marker == ((int) M_RST0 + ((desired-2) & 7))) - action = 2; /* a prior restart, so advance */ - else - action = 1; /* desired restart or too far away */ - } - TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); - switch (action) { - case 1: - /* Discard marker and let entropy decoder resume processing. */ - cinfo->unread_marker = 0; - return TRUE; - case 2: - /* Scan to the next marker, and repeat the decision loop. */ - if (! next_marker(cinfo)) - return FALSE; - marker = cinfo->unread_marker; - break; - case 3: - /* Return without advancing past this marker. */ - /* Entropy decoder will be forced to process an empty segment. */ - return TRUE; - } - } /* end loop */ -} - - -/* - * Reset marker processing state to begin a fresh datastream. - */ - -METHODDEF(void) -reset_marker_reader (j_decompress_ptr cinfo) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - - cinfo->comp_info = NULL; /* until allocated by get_sof */ - cinfo->input_scan_number = 0; /* no SOS seen yet */ - cinfo->unread_marker = 0; /* no pending marker */ - marker->pub.saw_SOI = FALSE; /* set internal state too */ - marker->pub.saw_SOF = FALSE; - marker->pub.discarded_bytes = 0; - marker->cur_marker = NULL; -} - - -/* - * Initialize the marker reader module. - * This is called only once, when the decompression object is created. - */ - -GLOBAL(void) -jinit_marker_reader (j_decompress_ptr cinfo) -{ - my_marker_ptr marker; - int i; - - /* Create subobject in permanent pool */ - marker = (my_marker_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_marker_reader)); - cinfo->marker = &marker->pub; - /* Initialize public method pointers */ - marker->pub.reset_marker_reader = reset_marker_reader; - marker->pub.read_markers = read_markers; - marker->pub.read_restart_marker = read_restart_marker; - /* Initialize COM/APPn processing. - * By default, we examine and then discard APP0 and APP14, - * but simply discard COM and all other APPn. - */ - marker->process_COM = skip_variable; - marker->length_limit_COM = 0; - for (i = 0; i < 16; i++) { - marker->process_APPn[i] = skip_variable; - marker->length_limit_APPn[i] = 0; - } - marker->process_APPn[0] = get_interesting_appn; - marker->process_APPn[14] = get_interesting_appn; - /* Reset marker processing state */ - reset_marker_reader(cinfo); -} - - -/* - * Control saving of COM and APPn markers into marker_list. - */ - -#ifdef SAVE_MARKERS_SUPPORTED - -GLOBAL(void) -jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - long maxlength; - jpeg_marker_parser_method processor; - - /* Length limit mustn't be larger than what we can allocate - * (should only be a concern in a 16-bit environment). - */ - maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); - if (((long) length_limit) > maxlength) - length_limit = (unsigned int) maxlength; - - /* Choose processor routine to use. - * APP0/APP14 have special requirements. - */ - if (length_limit) { - processor = save_marker; - /* If saving APP0/APP14, save at least enough for our internal use. */ - if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) - length_limit = APP0_DATA_LEN; - else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) - length_limit = APP14_DATA_LEN; - } else { - processor = skip_variable; - /* If discarding APP0/APP14, use our regular on-the-fly processor. */ - if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) - processor = get_interesting_appn; - } - - if (marker_code == (int) M_COM) { - marker->process_COM = processor; - marker->length_limit_COM = length_limit; - } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { - marker->process_APPn[marker_code - (int) M_APP0] = processor; - marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; - } else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); -} - -#endif /* SAVE_MARKERS_SUPPORTED */ - - -/* - * Install a special processing method for COM or APPn markers. - */ - -GLOBAL(void) -jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - - if (marker_code == (int) M_COM) - marker->process_COM = routine; - else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) - marker->process_APPn[marker_code - (int) M_APP0] = routine; - else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); -} diff --git a/libraries/jpeg/jdmaster.c b/libraries/jpeg/jdmaster.c deleted file mode 100644 index 62c07671f7..0000000000 --- a/libraries/jpeg/jdmaster.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * jdmaster.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2002-2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains master control logic for the JPEG decompressor. - * These routines are concerned with selecting the modules to be executed - * and with determining the number of passes and the work to be done in each - * pass. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef struct { - struct jpeg_decomp_master pub; /* public fields */ - - int pass_number; /* # of passes completed */ - - boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ - - /* Saved references to initialized quantizer modules, - * in case we need to switch modes. - */ - struct jpeg_color_quantizer * quantizer_1pass; - struct jpeg_color_quantizer * quantizer_2pass; -} my_decomp_master; - -typedef my_decomp_master * my_master_ptr; - - -/* - * Determine whether merged upsample/color conversion should be used. - * CRUCIAL: this must match the actual capabilities of jdmerge.c! - */ - -LOCAL(boolean) -use_merged_upsample (j_decompress_ptr cinfo) -{ -#ifdef UPSAMPLE_MERGING_SUPPORTED - /* Merging is the equivalent of plain box-filter upsampling. */ - /* The following condition is only needed if fancy shall select - * a different upsampling method. In our current implementation - * fancy only affects the DCT scaling, thus we can use fancy - * upsampling and merged upsample simultaneously, in particular - * with scaled DCT sizes larger than the default DCTSIZE. - */ -#if 0 - if (cinfo->do_fancy_upsampling) - return FALSE; -#endif - if (cinfo->CCIR601_sampling) - return FALSE; - /* jdmerge.c only supports YCC=>RGB color conversion */ - if ((cinfo->jpeg_color_space != JCS_YCbCr && - cinfo->jpeg_color_space != JCS_BG_YCC) || - cinfo->num_components != 3 || - cinfo->out_color_space != JCS_RGB || - cinfo->out_color_components != RGB_PIXELSIZE || - cinfo->color_transform) - return FALSE; - /* and it only handles 2h1v or 2h2v sampling ratios */ - if (cinfo->comp_info[0].h_samp_factor != 2 || - cinfo->comp_info[1].h_samp_factor != 1 || - cinfo->comp_info[2].h_samp_factor != 1 || - cinfo->comp_info[0].v_samp_factor > 2 || - cinfo->comp_info[1].v_samp_factor != 1 || - cinfo->comp_info[2].v_samp_factor != 1) - return FALSE; - /* furthermore, it doesn't work if we've scaled the IDCTs differently */ - if (cinfo->comp_info[0].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || - cinfo->comp_info[1].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || - cinfo->comp_info[2].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || - cinfo->comp_info[0].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || - cinfo->comp_info[1].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || - cinfo->comp_info[2].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size) - return FALSE; - /* ??? also need to test for upsample-time rescaling, when & if supported */ - return TRUE; /* by golly, it'll work... */ -#else - return FALSE; -#endif -} - - -/* - * Compute output image dimensions and related values. - * NOTE: this is exported for possible use by application. - * Hence it mustn't do anything that can't be done twice. - * Also note that it may be called before the master module is initialized! - */ - -GLOBAL(void) -jpeg_calc_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase. - * This function is used for full decompression. - */ -{ -#ifdef IDCT_SCALING_SUPPORTED - int ci; - jpeg_component_info *compptr; -#endif - - /* Prevent application from calling me at wrong times */ - if (cinfo->global_state != DSTATE_READY) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* Compute core output image dimensions and DCT scaling choices. */ - jpeg_core_output_dimensions(cinfo); - -#ifdef IDCT_SCALING_SUPPORTED - - /* In selecting the actual DCT scaling for each component, we try to - * scale up the chroma components via IDCT scaling rather than upsampling. - * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code adapts subsampling ratios which are powers of 2. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - int ssize = 1; - while (cinfo->min_DCT_h_scaled_size * ssize <= - (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && - (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { - ssize = ssize * 2; - } - compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; - ssize = 1; - while (cinfo->min_DCT_v_scaled_size * ssize <= - (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && - (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { - ssize = ssize * 2; - } - compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; - - /* We don't support IDCT ratios larger than 2. */ - if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; - else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) - compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; - } - - /* Recompute downsampled dimensions of components; - * application needs to know these if using raw downsampled data. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Size in samples, after IDCT scaling */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * - (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * - (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - } - -#endif /* IDCT_SCALING_SUPPORTED */ - - /* Report number of components in selected colorspace. */ - /* Probably this should be in the color conversion module... */ - switch (cinfo->out_color_space) { - case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - break; - case JCS_RGB: - case JCS_BG_RGB: - cinfo->out_color_components = RGB_PIXELSIZE; - break; - case JCS_YCbCr: - case JCS_BG_YCC: - cinfo->out_color_components = 3; - break; - case JCS_CMYK: - case JCS_YCCK: - cinfo->out_color_components = 4; - break; - default: /* else must be same colorspace as in file */ - cinfo->out_color_components = cinfo->num_components; - break; - } - cinfo->output_components = (cinfo->quantize_colors ? 1 : - cinfo->out_color_components); - - /* See if upsampler will want to emit more than one row at a time */ - if (use_merged_upsample(cinfo)) - cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; - else - cinfo->rec_outbuf_height = 1; -} - - -/* - * Several decompression processes need to range-limit values to the range - * 0..MAXJSAMPLE; the input value may fall somewhat outside this range - * due to noise introduced by quantization, roundoff error, etc. These - * processes are inner loops and need to be as fast as possible. On most - * machines, particularly CPUs with pipelines or instruction prefetch, - * a (subscript-check-less) C table lookup - * x = sample_range_limit[x]; - * is faster than explicit tests - * if (x < 0) x = 0; - * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; - * These processes all use a common table prepared by the routine below. - * - * For most steps we can mathematically guarantee that the initial value - * of x is within 2*(MAXJSAMPLE+1) of the legal range, so a table running - * from -2*(MAXJSAMPLE+1) to 3*MAXJSAMPLE+2 is sufficient. But for the - * initial limiting step (just after the IDCT), a wildly out-of-range value - * is possible if the input data is corrupt. To avoid any chance of indexing - * off the end of memory and getting a bad-pointer trap, we perform the - * post-IDCT limiting thus: - * x = (sample_range_limit - SUBSET)[(x + CENTER) & MASK]; - * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit - * samples. Under normal circumstances this is more than enough range and - * a correct output will be generated; with bogus input data the mask will - * cause wraparound, and we will safely generate a bogus-but-in-range output. - * For the post-IDCT step, we want to convert the data from signed to unsigned - * representation by adding CENTERJSAMPLE at the same time that we limit it. - * This is accomplished with SUBSET = CENTER - CENTERJSAMPLE. - * - * Note that the table is allocated in near data space on PCs; it's small - * enough and used often enough to justify this. - */ - -LOCAL(void) -prepare_range_limit_table (j_decompress_ptr cinfo) -/* Allocate and fill in the sample_range_limit table */ -{ - JSAMPLE * table; - int i; - - table = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, - JPOOL_IMAGE, (RANGE_CENTER * 2 + MAXJSAMPLE + 1) * SIZEOF(JSAMPLE)); - /* First segment of range limit table: limit[x] = 0 for x < 0 */ - MEMZERO(table, RANGE_CENTER * SIZEOF(JSAMPLE)); - table += RANGE_CENTER; /* allow negative subscripts of table */ - cinfo->sample_range_limit = table; - /* Main part of range limit table: limit[x] = x */ - for (i = 0; i <= MAXJSAMPLE; i++) - table[i] = (JSAMPLE) i; - /* End of range limit table: limit[x] = MAXJSAMPLE for x > MAXJSAMPLE */ - for (; i <= MAXJSAMPLE + RANGE_CENTER; i++) - table[i] = MAXJSAMPLE; -} - - -/* - * Master selection of decompression modules. - * This is done once at jpeg_start_decompress time. We determine - * which modules will be used and give them appropriate initialization calls. - * We also initialize the decompressor input side to begin consuming data. - * - * Since jpeg_read_header has finished, we know what is in the SOF - * and (first) SOS markers. We also have all the application parameter - * settings. - */ - -LOCAL(void) -master_selection (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - boolean use_c_buffer; - long samplesperrow; - JDIMENSION jd_samplesperrow; - - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - - /* Initialize dimensions and other stuff */ - jpeg_calc_output_dimensions(cinfo); - prepare_range_limit_table(cinfo); - - /* Sanity check on image dimensions */ - if (cinfo->output_height <= 0 || cinfo->output_width <= 0 || - cinfo->out_color_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); - - /* Width of an output scanline must be representable as JDIMENSION. */ - samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; - jd_samplesperrow = (JDIMENSION) samplesperrow; - if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - - /* Initialize my private state */ - master->pass_number = 0; - master->using_merged_upsample = use_merged_upsample(cinfo); - - /* Color quantizer selection */ - master->quantizer_1pass = NULL; - master->quantizer_2pass = NULL; - /* No mode changes if not using buffered-image mode. */ - if (! cinfo->quantize_colors || ! cinfo->buffered_image) { - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - } - if (cinfo->quantize_colors) { - if (cinfo->raw_data_out) - ERREXIT(cinfo, JERR_NOTIMPL); - /* 2-pass quantizer only works in 3-component color space. */ - if (cinfo->out_color_components != 3) { - cinfo->enable_1pass_quant = TRUE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - cinfo->colormap = NULL; - } else if (cinfo->colormap != NULL) { - cinfo->enable_external_quant = TRUE; - } else if (cinfo->two_pass_quantize) { - cinfo->enable_2pass_quant = TRUE; - } else { - cinfo->enable_1pass_quant = TRUE; - } - - if (cinfo->enable_1pass_quant) { -#ifdef QUANT_1PASS_SUPPORTED - jinit_1pass_quantizer(cinfo); - master->quantizer_1pass = cinfo->cquantize; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } - - /* We use the 2-pass code to map to external colormaps. */ - if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { -#ifdef QUANT_2PASS_SUPPORTED - jinit_2pass_quantizer(cinfo); - master->quantizer_2pass = cinfo->cquantize; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } - /* If both quantizers are initialized, the 2-pass one is left active; - * this is necessary for starting with quantization to an external map. - */ - } - - /* Post-processing: in particular, color conversion first */ - if (! cinfo->raw_data_out) { - if (master->using_merged_upsample) { -#ifdef UPSAMPLE_MERGING_SUPPORTED - jinit_merged_upsampler(cinfo); /* does color conversion too */ -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - jinit_color_deconverter(cinfo); - jinit_upsampler(cinfo); - } - jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); - } - /* Inverse DCT */ - jinit_inverse_dct(cinfo); - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) - jinit_arith_decoder(cinfo); - else { - jinit_huff_decoder(cinfo); - } - - /* Initialize principal buffer controllers. */ - use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; - jinit_d_coef_controller(cinfo, use_c_buffer); - - if (! cinfo->raw_data_out) - jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Initialize input side of decompressor to consume first scan. */ - (*cinfo->inputctl->start_input_pass) (cinfo); - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* If jpeg_start_decompress will read the whole file, initialize - * progress monitoring appropriately. The input step is counted - * as one pass. - */ - if (cinfo->progress != NULL && ! cinfo->buffered_image && - cinfo->inputctl->has_multiple_scans) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); - /* Count the input pass as done */ - master->pass_number++; - } -#endif /* D_MULTISCAN_FILES_SUPPORTED */ -} - - -/* - * Per-pass setup. - * This is called at the beginning of each output pass. We determine which - * modules will be active during this pass and give them appropriate - * start_pass calls. We also set is_dummy_pass to indicate whether this - * is a "real" output pass or a dummy pass for color quantization. - * (In the latter case, jdapistd.c will crank the pass to completion.) - */ - -METHODDEF(void) -prepare_for_output_pass (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - if (master->pub.is_dummy_pass) { -#ifdef QUANT_2PASS_SUPPORTED - /* Final pass of 2-pass quantization */ - master->pub.is_dummy_pass = FALSE; - (*cinfo->cquantize->start_pass) (cinfo, FALSE); - (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); - (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* QUANT_2PASS_SUPPORTED */ - } else { - if (cinfo->quantize_colors && cinfo->colormap == NULL) { - /* Select new quantization method */ - if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { - cinfo->cquantize = master->quantizer_2pass; - master->pub.is_dummy_pass = TRUE; - } else if (cinfo->enable_1pass_quant) { - cinfo->cquantize = master->quantizer_1pass; - } else { - ERREXIT(cinfo, JERR_MODE_CHANGE); - } - } - (*cinfo->idct->start_pass) (cinfo); - (*cinfo->coef->start_output_pass) (cinfo); - if (! cinfo->raw_data_out) { - if (! master->using_merged_upsample) - (*cinfo->cconvert->start_pass) (cinfo); - (*cinfo->upsample->start_pass) (cinfo); - if (cinfo->quantize_colors) - (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); - (*cinfo->post->start_pass) (cinfo, - (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); - (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); - } - } - - /* Set up progress monitor's pass info if present */ - if (cinfo->progress != NULL) { - cinfo->progress->completed_passes = master->pass_number; - cinfo->progress->total_passes = master->pass_number + - (master->pub.is_dummy_pass ? 2 : 1); - /* In buffered-image mode, we assume one more output pass if EOI not - * yet reached, but no more passes if EOI has been reached. - */ - if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { - cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); - } - } -} - - -/* - * Finish up at end of an output pass. - */ - -METHODDEF(void) -finish_output_pass (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - if (cinfo->quantize_colors) - (*cinfo->cquantize->finish_pass) (cinfo); - master->pass_number++; -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Switch to a new external colormap between output passes. - */ - -GLOBAL(void) -jpeg_new_colormap (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - /* Prevent application from calling me at wrong times */ - if (cinfo->global_state != DSTATE_BUFIMAGE) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - if (cinfo->quantize_colors && cinfo->enable_external_quant && - cinfo->colormap != NULL) { - /* Select 2-pass quantizer for external colormap use */ - cinfo->cquantize = master->quantizer_2pass; - /* Notify quantizer of colormap change */ - (*cinfo->cquantize->new_color_map) (cinfo); - master->pub.is_dummy_pass = FALSE; /* just in case */ - } else - ERREXIT(cinfo, JERR_MODE_CHANGE); -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -/* - * Initialize master decompression control and select active modules. - * This is performed at the start of jpeg_start_decompress. - */ - -GLOBAL(void) -jinit_master_decompress (j_decompress_ptr cinfo) -{ - my_master_ptr master; - - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_decomp_master)); - cinfo->master = &master->pub; - master->pub.prepare_for_output_pass = prepare_for_output_pass; - master->pub.finish_output_pass = finish_output_pass; - - master->pub.is_dummy_pass = FALSE; - - master_selection(cinfo); -} diff --git a/libraries/jpeg/jdmerge.c b/libraries/jpeg/jdmerge.c deleted file mode 100644 index 866693f529..0000000000 --- a/libraries/jpeg/jdmerge.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * jdmerge.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2013-2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains code for merged upsampling/color conversion. - * - * This file combines functions from jdsample.c and jdcolor.c; - * read those files first to understand what's going on. - * - * When the chroma components are to be upsampled by simple replication - * (ie, box filtering), we can save some work in color conversion by - * calculating all the output pixels corresponding to a pair of chroma - * samples at one time. In the conversion equations - * R = Y + K1 * Cr - * G = Y + K2 * Cb + K3 * Cr - * B = Y + K4 * Cb - * only the Y term varies among the group of pixels corresponding to a pair - * of chroma samples, so the rest of the terms can be calculated just once. - * At typical sampling ratios, this eliminates half or three-quarters of the - * multiplications needed for color conversion. - * - * This file currently provides implementations for the following cases: - * YCC => RGB color conversion only (YCbCr or BG_YCC). - * Sampling ratios of 2h1v or 2h2v. - * No scaling needed at upsample time. - * Corner-aligned (non-CCIR601) sampling alignment. - * Other special cases could be added, but in most applications these are - * the only common cases. (For uncommon cases we fall back on the more - * general code in jdsample.c and jdcolor.c.) - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -#ifdef UPSAMPLE_MERGING_SUPPORTED - - -#if RANGE_BITS < 2 - /* Deliberate syntax err */ - Sorry, this code requires 2 or more range extension bits. -#endif - - -/* Private subobject */ - -typedef struct { - struct jpeg_upsampler pub; /* public fields */ - - /* Pointer to routine to do actual upsampling/conversion of one row group */ - JMETHOD(void, upmethod, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf)); - - /* Private state for YCC->RGB conversion */ - int * Cr_r_tab; /* => table for Cr to R conversion */ - int * Cb_b_tab; /* => table for Cb to B conversion */ - INT32 * Cr_g_tab; /* => table for Cr to G conversion */ - INT32 * Cb_g_tab; /* => table for Cb to G conversion */ - - /* For 2:1 vertical sampling, we produce two output rows at a time. - * We need a "spare" row buffer to hold the second output row if the - * application provides just a one-row buffer; we also use the spare - * to discard the dummy last row if the image height is odd. - */ - JSAMPROW spare_row; - boolean spare_full; /* T if spare buffer is occupied */ - - JDIMENSION out_row_width; /* samples per output row */ - JDIMENSION rows_to_go; /* counts rows remaining in image */ -} my_upsampler; - -typedef my_upsampler * my_upsample_ptr; - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L<RGB and BG_YCC->RGB colorspace conversion. - * This is taken directly from jdcolor.c; see that file for more info. - */ - -LOCAL(void) -build_ycc_rgb_table (j_decompress_ptr cinfo) -/* Normal case, sYCC */ -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - int i; - INT32 x; - SHIFT_TEMPS - - upsample->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - upsample->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - upsample->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - upsample->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.402 * x */ - upsample->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.402) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.772 * x */ - upsample->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.772) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.714136286 * x */ - upsample->Cr_g_tab[i] = (- FIX(0.714136286)) * x; - /* Cb=>G value is scaled-up -0.344136286 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - upsample->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF; - } -} - - -LOCAL(void) -build_bg_ycc_rgb_table (j_decompress_ptr cinfo) -/* Wide gamut case, bg-sYCC */ -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - int i; - INT32 x; - SHIFT_TEMPS - - upsample->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - upsample->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - upsample->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - upsample->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 2.804 * x */ - upsample->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(2.804) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 3.544 * x */ - upsample->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(3.544) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -1.428272572 * x */ - upsample->Cr_g_tab[i] = (- FIX(1.428272572)) * x; - /* Cb=>G value is scaled-up -0.688272572 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - upsample->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF; - } -} - - -/* - * Initialize for an upsampling pass. - */ - -METHODDEF(void) -start_pass_merged_upsample (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Mark the spare buffer empty */ - upsample->spare_full = FALSE; - /* Initialize total-height counter for detecting bottom of image */ - upsample->rows_to_go = cinfo->output_height; -} - - -/* - * Control routine to do upsampling (and color conversion). - * - * The control routine just handles the row buffering considerations. - */ - -METHODDEF(void) -merged_2v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -/* 2:1 vertical sampling case: may need a spare row. */ -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - JSAMPROW work_ptrs[2]; - JDIMENSION num_rows; /* number of rows returned to caller */ - - if (upsample->spare_full) { - /* If we have a spare row saved from a previous cycle, just return it. */ - jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, - 1, upsample->out_row_width); - num_rows = 1; - upsample->spare_full = FALSE; - } else { - /* Figure number of rows to return to caller. */ - num_rows = 2; - /* Not more than the distance to the end of the image. */ - if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ - out_rows_avail -= *out_row_ctr; - if (num_rows > out_rows_avail) - num_rows = out_rows_avail; - /* Create output pointer array for upsampler. */ - work_ptrs[0] = output_buf[*out_row_ctr]; - if (num_rows > 1) { - work_ptrs[1] = output_buf[*out_row_ctr + 1]; - } else { - work_ptrs[1] = upsample->spare_row; - upsample->spare_full = TRUE; - } - /* Now do the upsampling. */ - (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); - } - - /* Adjust counts */ - *out_row_ctr += num_rows; - upsample->rows_to_go -= num_rows; - /* When the buffer is emptied, declare this input row group consumed */ - if (! upsample->spare_full) - (*in_row_group_ctr)++; -} - - -METHODDEF(void) -merged_1v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -/* 1:1 vertical sampling case: much easier, never need a spare row. */ -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Just do the upsampling. */ - (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, - output_buf + *out_row_ctr); - /* Adjust counts */ - (*out_row_ctr)++; - (*in_row_group_ctr)++; -} - - -/* - * These are the routines invoked by the control routines to do - * the actual upsampling/conversion. One row group is processed per call. - * - * Note: since we may be writing directly into application-supplied buffers, - * we have to be honest about the output width; we can't assume the buffer - * has been rounded up to an even width. - */ - - -/* - * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. - */ - -METHODDEF(void) -h2v1_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - register int y, cred, cgreen, cblue; - int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; - JDIMENSION col; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - int * Crrtab = upsample->Cr_r_tab; - int * Cbbtab = upsample->Cb_b_tab; - INT32 * Crgtab = upsample->Cr_g_tab; - INT32 * Cbgtab = upsample->Cb_g_tab; - SHIFT_TEMPS - - inptr0 = input_buf[0][in_row_group_ctr]; - inptr1 = input_buf[1][in_row_group_ctr]; - inptr2 = input_buf[2][in_row_group_ctr]; - outptr = output_buf[0]; - /* Loop for each pair of output pixels */ - for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 2 Y values and emit 2 pixels */ - y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - outptr += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - outptr += RGB_PIXELSIZE; - } - /* If image width is odd, do the last output column separately */ - if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr0); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - } -} - - -/* - * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. - */ - -METHODDEF(void) -h2v2_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - register int y, cred, cgreen, cblue; - int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; - JDIMENSION col; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - int * Crrtab = upsample->Cr_r_tab; - int * Cbbtab = upsample->Cb_b_tab; - INT32 * Crgtab = upsample->Cr_g_tab; - INT32 * Cbgtab = upsample->Cb_g_tab; - SHIFT_TEMPS - - inptr00 = input_buf[0][in_row_group_ctr*2]; - inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; - inptr1 = input_buf[1][in_row_group_ctr]; - inptr2 = input_buf[2][in_row_group_ctr]; - outptr0 = output_buf[0]; - outptr1 = output_buf[1]; - /* Loop for each group of output pixels */ - for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 4 Y values and emit 4 pixels */ - y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - } - /* If image width is odd, do the last output column separately */ - if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr00); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - y = GETJSAMPLE(*inptr01); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - } -} - - -/* - * Module initialization routine for merged upsampling/color conversion. - * - * NB: this is called under the conditions determined by use_merged_upsample() - * in jdmaster.c. That routine MUST correspond to the actual capabilities - * of this module; no safety checks are made here. - */ - -GLOBAL(void) -jinit_merged_upsampler (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample; - - upsample = (my_upsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = &upsample->pub; - upsample->pub.start_pass = start_pass_merged_upsample; - upsample->pub.need_context_rows = FALSE; - - upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; - - if (cinfo->max_v_samp_factor == 2) { - upsample->pub.upsample = merged_2v_upsample; - upsample->upmethod = h2v2_merged_upsample; - /* Allocate a spare row buffer */ - upsample->spare_row = (JSAMPROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); - } else { - upsample->pub.upsample = merged_1v_upsample; - upsample->upmethod = h2v1_merged_upsample; - /* No spare row needed */ - upsample->spare_row = NULL; - } - - if (cinfo->jpeg_color_space == JCS_BG_YCC) - build_bg_ycc_rgb_table(cinfo); - else - build_ycc_rgb_table(cinfo); -} - -#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/libraries/jpeg/jdpostct.c b/libraries/jpeg/jdpostct.c deleted file mode 100644 index 571563d728..0000000000 --- a/libraries/jpeg/jdpostct.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * jdpostct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the decompression postprocessing controller. - * This controller manages the upsampling, color conversion, and color - * quantization/reduction steps; specifically, it controls the buffering - * between upsample/color conversion and color quantization/reduction. - * - * If no color quantization/reduction is required, then this module has no - * work to do, and it just hands off to the upsample/color conversion code. - * An integrated upsample/convert/quantize process would replace this module - * entirely. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_post_controller pub; /* public fields */ - - /* Color quantization source buffer: this holds output data from - * the upsample/color conversion step to be passed to the quantizer. - * For two-pass color quantization, we need a full-image buffer; - * for one-pass operation, a strip buffer is sufficient. - */ - jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ - JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ - JDIMENSION strip_height; /* buffer size in rows */ - /* for two-pass mode only: */ - JDIMENSION starting_row; /* row # of first row in current strip */ - JDIMENSION next_row; /* index of next row to fill/empty in strip */ -} my_post_controller; - -typedef my_post_controller * my_post_ptr; - - -/* Forward declarations */ -METHODDEF(void) post_process_1pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -#ifdef QUANT_2PASS_SUPPORTED -METHODDEF(void) post_process_prepass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -METHODDEF(void) post_process_2pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -#endif - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (cinfo->quantize_colors) { - /* Single-pass processing with color quantization. */ - post->pub.post_process_data = post_process_1pass; - /* We could be doing buffered-image output before starting a 2-pass - * color quantization; in that case, jinit_d_post_controller did not - * allocate a strip buffer. Use the virtual-array buffer as workspace. - */ - if (post->buffer == NULL) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - (JDIMENSION) 0, post->strip_height, TRUE); - } - } else { - /* For single-pass processing without color quantization, - * I have no work to do; just call the upsampler directly. - */ - post->pub.post_process_data = cinfo->upsample->upsample; - } - break; -#ifdef QUANT_2PASS_SUPPORTED - case JBUF_SAVE_AND_PASS: - /* First pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_prepass; - break; - case JBUF_CRANK_DEST: - /* Second pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_2pass; - break; -#endif /* QUANT_2PASS_SUPPORTED */ - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } - post->starting_row = post->next_row = 0; -} - - -/* - * Process some data in the one-pass (strip buffer) case. - * This is used for color precision reduction as well as one-pass quantization. - */ - -METHODDEF(void) -post_process_1pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION num_rows, max_rows; - - /* Fill the buffer, but not more than what we can dump out in one go. */ - /* Note we rely on the upsampler to detect bottom of image. */ - max_rows = out_rows_avail - *out_row_ctr; - if (max_rows > post->strip_height) - max_rows = post->strip_height; - num_rows = 0; - (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &num_rows, max_rows); - /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer, output_buf + *out_row_ctr, (int) num_rows); - *out_row_ctr += num_rows; -} - - -#ifdef QUANT_2PASS_SUPPORTED - -/* - * Process some data in the first pass of 2-pass quantization. - */ - -METHODDEF(void) -post_process_prepass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION old_next_row, num_rows; - - /* Reposition virtual buffer if at start of strip. */ - if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, TRUE); - } - - /* Upsample some data (up to a strip height's worth). */ - old_next_row = post->next_row; - (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &post->next_row, post->strip_height); - - /* Allow quantizer to scan new data. No data is emitted, */ - /* but we advance out_row_ctr so outer loop can tell when we're done. */ - if (post->next_row > old_next_row) { - num_rows = post->next_row - old_next_row; - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, - (JSAMPARRAY) NULL, (int) num_rows); - *out_row_ctr += num_rows; - } - - /* Advance if we filled the strip. */ - if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; - } -} - - -/* - * Process some data in the second pass of 2-pass quantization. - */ - -METHODDEF(void) -post_process_2pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION num_rows, max_rows; - - /* Reposition virtual buffer if at start of strip. */ - if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, FALSE); - } - - /* Determine number of rows to emit. */ - num_rows = post->strip_height - post->next_row; /* available in strip */ - max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ - if (num_rows > max_rows) - num_rows = max_rows; - /* We have to check bottom of image here, can't depend on upsampler. */ - max_rows = cinfo->output_height - post->starting_row; - if (num_rows > max_rows) - num_rows = max_rows; - - /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer + post->next_row, output_buf + *out_row_ctr, - (int) num_rows); - *out_row_ctr += num_rows; - - /* Advance if we filled the strip. */ - post->next_row += num_rows; - if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; - } -} - -#endif /* QUANT_2PASS_SUPPORTED */ - - -/* - * Initialize postprocessing controller. - */ - -GLOBAL(void) -jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_post_ptr post; - - post = (my_post_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_post_controller)); - cinfo->post = (struct jpeg_d_post_controller *) post; - post->pub.start_pass = start_pass_dpost; - post->whole_image = NULL; /* flag for no virtual arrays */ - post->buffer = NULL; /* flag for no strip buffer */ - - /* Create the quantization buffer, if needed */ - if (cinfo->quantize_colors) { - /* The buffer strip height is max_v_samp_factor, which is typically - * an efficient number of rows for upsampling to return. - * (In the presence of output rescaling, we might want to be smarter?) - */ - post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; - if (need_full_buffer) { - /* Two-pass color quantization: need full-image storage. */ - /* We round up the number of rows to a multiple of the strip height. */ -#ifdef QUANT_2PASS_SUPPORTED - post->whole_image = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - cinfo->output_width * cinfo->out_color_components, - (JDIMENSION) jround_up((long) cinfo->output_height, - (long) post->strip_height), - post->strip_height); -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif /* QUANT_2PASS_SUPPORTED */ - } else { - /* One-pass color quantization: just make a strip buffer. */ - post->buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->output_width * cinfo->out_color_components, - post->strip_height); - } - } -} diff --git a/libraries/jpeg/jdsample.c b/libraries/jpeg/jdsample.c deleted file mode 100644 index fd9907e20c..0000000000 --- a/libraries/jpeg/jdsample.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * jdsample.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2002-2015 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains upsampling routines. - * - * Upsampling input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_v_scaled_size / min_DCT_v_scaled_size) - * sample rows of each component. Upsampling will normally produce - * max_v_samp_factor pixel rows from each row group (but this could vary - * if the upsampler is applying a scale factor of its own). - * - * An excellent reference for image resampling is - * Digital Image Warping, George Wolberg, 1990. - * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Pointer to routine to upsample a single component */ -typedef JMETHOD(void, upsample1_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); - -/* Private subobject */ - -typedef struct { - struct jpeg_upsampler pub; /* public fields */ - - /* Color conversion buffer. When using separate upsampling and color - * conversion steps, this buffer holds one upsampled row group until it - * has been color converted and output. - * Note: we do not allocate any storage for component(s) which are full-size, - * ie do not need rescaling. The corresponding entry of color_buf[] is - * simply set to point to the input data array, thereby avoiding copying. - */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; - - /* Per-component upsampling method pointers */ - upsample1_ptr methods[MAX_COMPONENTS]; - - int next_row_out; /* counts rows emitted from color_buf */ - JDIMENSION rows_to_go; /* counts rows remaining in image */ - - /* Height of an input row group for each component. */ - int rowgroup_height[MAX_COMPONENTS]; - - /* These arrays save pixel expansion factors so that int_expand need not - * recompute them each time. They are unused for other upsampling methods. - */ - UINT8 h_expand[MAX_COMPONENTS]; - UINT8 v_expand[MAX_COMPONENTS]; -} my_upsampler; - -typedef my_upsampler * my_upsample_ptr; - - -/* - * Initialize for an upsampling pass. - */ - -METHODDEF(void) -start_pass_upsample (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Mark the conversion buffer empty */ - upsample->next_row_out = cinfo->max_v_samp_factor; - /* Initialize total-height counter for detecting bottom of image */ - upsample->rows_to_go = cinfo->output_height; -} - - -/* - * Control routine to do upsampling (and color conversion). - * - * In this version we upsample each component independently. - * We upsample one row group into the conversion buffer, then apply - * color conversion a row at a time. - */ - -METHODDEF(void) -sep_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - int ci; - jpeg_component_info * compptr; - JDIMENSION num_rows; - - /* Fill the conversion buffer, if it's empty */ - if (upsample->next_row_out >= cinfo->max_v_samp_factor) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Invoke per-component upsample method. Notice we pass a POINTER - * to color_buf[ci], so that fullsize_upsample can change it. - */ - (*upsample->methods[ci]) (cinfo, compptr, - input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), - upsample->color_buf + ci); - } - upsample->next_row_out = 0; - } - - /* Color-convert and emit rows */ - - /* How many we have in the buffer: */ - num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); - /* Not more than the distance to the end of the image. Need this test - * in case the image height is not a multiple of max_v_samp_factor: - */ - if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ - out_rows_avail -= *out_row_ctr; - if (num_rows > out_rows_avail) - num_rows = out_rows_avail; - - (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, - (JDIMENSION) upsample->next_row_out, - output_buf + *out_row_ctr, - (int) num_rows); - - /* Adjust counts */ - *out_row_ctr += num_rows; - upsample->rows_to_go -= num_rows; - upsample->next_row_out += num_rows; - /* When the buffer is emptied, declare this input row group consumed */ - if (upsample->next_row_out >= cinfo->max_v_samp_factor) - (*in_row_group_ctr)++; -} - - -/* - * These are the routines invoked by sep_upsample to upsample pixel values - * of a single component. One row group is processed per call. - */ - - -/* - * For full-size components, we just make color_buf[ci] point at the - * input buffer, and thus avoid copying any data. Note that this is - * safe only because sep_upsample doesn't declare the input row group - * "consumed" until we are done color converting and emitting it. - */ - -METHODDEF(void) -fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - *output_data_ptr = input_data; -} - - -/* - * This is a no-op version used for "uninteresting" components. - * These components will not be referenced by color conversion. - */ - -METHODDEF(void) -noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - *output_data_ptr = NULL; /* safety check */ -} - - -/* - * This version handles any integral sampling ratios. - * This is not used for typical JPEG files, so it need not be fast. - * Nor, for that matter, is it particularly accurate: the algorithm is - * simple replication of the input pixel onto the corresponding output - * pixels. The hi-falutin sampling literature refers to this as a - * "box filter". A box filter tends to introduce visible artifacts, - * so if you are actually going to use 3:1 or 4:1 sampling ratios - * you would be well advised to improve this code. - */ - -METHODDEF(void) -int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - register int h; - JSAMPROW outend; - int h_expand, v_expand; - int inrow, outrow; - - h_expand = upsample->h_expand[compptr->component_index]; - v_expand = upsample->v_expand[compptr->component_index]; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - /* Generate one output row with proper horizontal expansion */ - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - for (h = h_expand; h > 0; h--) { - *outptr++ = invalue; - } - } - /* Generate any additional output rows by duplicating the first one */ - if (v_expand > 1) { - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - v_expand-1, cinfo->output_width); - } - inrow++; - outrow += v_expand; - } -} - - -/* - * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. - * It's still a box filter. - */ - -METHODDEF(void) -h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; - int outrow; - - for (outrow = 0; outrow < cinfo->max_v_samp_factor; outrow++) { - inptr = input_data[outrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - } -} - - -/* - * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. - * It's still a box filter. - */ - -METHODDEF(void) -h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; - int inrow, outrow; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - 1, cinfo->output_width); - inrow++; - outrow += 2; - } -} - - -/* - * Module initialization routine for upsampling. - */ - -GLOBAL(void) -jinit_upsampler (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample; - int ci; - jpeg_component_info * compptr; - int h_in_group, v_in_group, h_out_group, v_out_group; - - upsample = (my_upsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = &upsample->pub; - upsample->pub.start_pass = start_pass_upsample; - upsample->pub.upsample = sep_upsample; - upsample->pub.need_context_rows = FALSE; /* until we find out differently */ - - if (cinfo->CCIR601_sampling) /* this isn't supported */ - ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - - /* Verify we can handle the sampling factors, select per-component methods, - * and create storage as needed. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Compute size of an "input group" after IDCT scaling. This many samples - * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. - */ - h_in_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / - cinfo->min_DCT_h_scaled_size; - v_in_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / - cinfo->min_DCT_v_scaled_size; - h_out_group = cinfo->max_h_samp_factor; - v_out_group = cinfo->max_v_samp_factor; - upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ - if (! compptr->component_needed) { - /* Don't bother to upsample an uninteresting component. */ - upsample->methods[ci] = noop_upsample; - continue; /* don't need to allocate buffer */ - } - if (h_in_group == h_out_group && v_in_group == v_out_group) { - /* Fullsize components can be processed without any work. */ - upsample->methods[ci] = fullsize_upsample; - continue; /* don't need to allocate buffer */ - } - if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { - /* Special case for 2h1v upsampling */ - upsample->methods[ci] = h2v1_upsample; - } else if (h_in_group * 2 == h_out_group && - v_in_group * 2 == v_out_group) { - /* Special case for 2h2v upsampling */ - upsample->methods[ci] = h2v2_upsample; - } else if ((h_out_group % h_in_group) == 0 && - (v_out_group % v_in_group) == 0) { - /* Generic integral-factors upsampling method */ - upsample->methods[ci] = int_upsample; - upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); - upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); - } else - ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) cinfo->output_width, - (long) cinfo->max_h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); - } -} diff --git a/libraries/jpeg/jerror.c b/libraries/jpeg/jerror.c deleted file mode 100644 index 7163af699c..0000000000 --- a/libraries/jpeg/jerror.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * jerror.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2012-2015 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains simple error-reporting and trace-message routines. - * These are suitable for Unix-like systems and others where writing to - * stderr is the right thing to do. Many applications will want to replace - * some or all of these routines. - * - * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, - * you get a Windows-specific hack to display error messages in a dialog box. - * It ain't much, but it beats dropping error messages into the bit bucket, - * which is what happens to output to stderr under most Windows C compilers. - * - * These routines are used by both the compression and decompression code. - */ - -#ifdef USE_WINDOWS_MESSAGEBOX -#include -#endif - -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jversion.h" -#include "jerror.h" - -#ifndef EXIT_FAILURE /* define exit() codes if not provided */ -#define EXIT_FAILURE 1 -#endif - - -/* - * Create the message string table. - * We do this from the master message list in jerror.h by re-reading - * jerror.h with a suitable definition for macro JMESSAGE. - * The message table is made an external symbol just in case any applications - * want to refer to it directly. - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_message_table jMsgTable -#endif - -#define JMESSAGE(code,string) string , - -const char * const jpeg_std_message_table[] = { -#include "jerror.h" - NULL -}; - - -/* - * Error exit handler: must not return to caller. - * - * Applications may override this if they want to get control back after - * an error. Typically one would longjmp somewhere instead of exiting. - * The setjmp buffer can be made a private field within an expanded error - * handler object. Note that the info needed to generate an error message - * is stored in the error object, so you can generate the message now or - * later, at your convenience. - * You should make sure that the JPEG object is cleaned up (with jpeg_abort - * or jpeg_destroy) at some point. - */ - -METHODDEF(noreturn_t) -error_exit (j_common_ptr cinfo) -{ - /* Always display the message */ - (*cinfo->err->output_message) (cinfo); - - /* Let the memory manager delete any temp files before we die */ - jpeg_destroy(cinfo); - - exit(EXIT_FAILURE); -} - - -/* - * Actual output of an error or trace message. - * Applications may override this method to send JPEG messages somewhere - * other than stderr. - * - * On Windows, printing to stderr is generally completely useless, - * so we provide optional code to produce an error-dialog popup. - * Most Windows applications will still prefer to override this routine, - * but if they don't, it'll do something at least marginally useful. - * - * NOTE: to use the library in an environment that doesn't support the - * C stdio library, you may have to delete the call to fprintf() entirely, - * not just not use this routine. - */ - -METHODDEF(void) -output_message (j_common_ptr cinfo) -{ - char buffer[JMSG_LENGTH_MAX]; - - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); - -#ifdef USE_WINDOWS_MESSAGEBOX - /* Display it in a message dialog box */ - MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", - MB_OK | MB_ICONERROR); -#else - /* Send it to stderr, adding a newline */ - fprintf(stderr, "%s\n", buffer); -#endif -} - - -/* - * Decide whether to emit a trace or warning message. - * msg_level is one of: - * -1: recoverable corrupt-data warning, may want to abort. - * 0: important advisory messages (always display to user). - * 1: first level of tracing detail. - * 2,3,...: successively more detailed tracing messages. - * An application might override this method if it wanted to abort on warnings - * or change the policy about which messages to display. - */ - -METHODDEF(void) -emit_message (j_common_ptr cinfo, int msg_level) -{ - struct jpeg_error_mgr * err = cinfo->err; - - if (msg_level < 0) { - /* It's a warning message. Since corrupt files may generate many warnings, - * the policy implemented here is to show only the first warning, - * unless trace_level >= 3. - */ - if (err->num_warnings == 0 || err->trace_level >= 3) - (*err->output_message) (cinfo); - /* Always count warnings in num_warnings. */ - err->num_warnings++; - } else { - /* It's a trace message. Show it if trace_level >= msg_level. */ - if (err->trace_level >= msg_level) - (*err->output_message) (cinfo); - } -} - - -/* - * Format a message string for the most recent JPEG error or message. - * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX - * characters. Note that no '\n' character is added to the string. - * Few applications should need to override this method. - */ - -METHODDEF(void) -format_message (j_common_ptr cinfo, char * buffer) -{ - struct jpeg_error_mgr * err = cinfo->err; - int msg_code = err->msg_code; - const char * msgtext = NULL; - const char * msgptr; - char ch; - boolean isstring; - - /* Look up message string in proper table */ - if (msg_code > 0 && msg_code <= err->last_jpeg_message) { - msgtext = err->jpeg_message_table[msg_code]; - } else if (err->addon_message_table != NULL && - msg_code >= err->first_addon_message && - msg_code <= err->last_addon_message) { - msgtext = err->addon_message_table[msg_code - err->first_addon_message]; - } - - /* Defend against bogus message number */ - if (msgtext == NULL) { - err->msg_parm.i[0] = msg_code; - msgtext = err->jpeg_message_table[0]; - } - - /* Check for string parameter, as indicated by %s in the message text */ - isstring = FALSE; - msgptr = msgtext; - while ((ch = *msgptr++) != '\0') { - if (ch == '%') { - if (*msgptr == 's') isstring = TRUE; - break; - } - } - - /* Format the message into the passed buffer */ - if (isstring) - sprintf(buffer, msgtext, err->msg_parm.s); - else - sprintf(buffer, msgtext, - err->msg_parm.i[0], err->msg_parm.i[1], - err->msg_parm.i[2], err->msg_parm.i[3], - err->msg_parm.i[4], err->msg_parm.i[5], - err->msg_parm.i[6], err->msg_parm.i[7]); -} - - -/* - * Reset error state variables at start of a new image. - * This is called during compression startup to reset trace/error - * processing to default state, without losing any application-specific - * method pointers. An application might possibly want to override - * this method if it has additional error processing state. - */ - -METHODDEF(void) -reset_error_mgr (j_common_ptr cinfo) -{ - cinfo->err->num_warnings = 0; - /* trace_level is not reset since it is an application-supplied parameter */ - cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ -} - - -/* - * Fill in the standard error-handling methods in a jpeg_error_mgr object. - * Typical call is: - * struct jpeg_compress_struct cinfo; - * struct jpeg_error_mgr err; - * - * cinfo.err = jpeg_std_error(&err); - * after which the application may override some of the methods. - */ - -GLOBAL(struct jpeg_error_mgr *) -jpeg_std_error (struct jpeg_error_mgr * err) -{ - err->error_exit = error_exit; - err->emit_message = emit_message; - err->output_message = output_message; - err->format_message = format_message; - err->reset_error_mgr = reset_error_mgr; - - err->trace_level = 0; /* default = no tracing */ - err->num_warnings = 0; /* no warnings emitted yet */ - err->msg_code = 0; /* may be useful as a flag for "no error" */ - - /* Initialize message table pointers */ - err->jpeg_message_table = jpeg_std_message_table; - err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; - - err->addon_message_table = NULL; - err->first_addon_message = 0; /* for safety */ - err->last_addon_message = 0; - - return err; -} diff --git a/libraries/jpeg/jerror.h b/libraries/jpeg/jerror.h deleted file mode 100644 index a4b661f716..0000000000 --- a/libraries/jpeg/jerror.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * jerror.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * Modified 1997-2012 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the JPEG library. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - * A set of error-reporting macros are defined too. Some applications using - * the JPEG library may wish to include this file to get the error codes - * and/or the macros. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef JERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* JERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ - -/* For maintenance convenience, list is alphabetical by message code name */ -JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") -JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") -JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") -JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") -JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") -JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") -JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") -JMESSAGE(JERR_BAD_DROP_SAMPLING, - "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") -JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") -JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") -JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") -JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") -JMESSAGE(JERR_BAD_LIB_VERSION, - "Wrong JPEG library version: library is %d, caller expects %d") -JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") -JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") -JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") -JMESSAGE(JERR_BAD_PROGRESSION, - "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") -JMESSAGE(JERR_BAD_PROG_SCRIPT, - "Invalid progressive parameters at scan script entry %d") -JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") -JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") -JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") -JMESSAGE(JERR_BAD_STRUCT_SIZE, - "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") -JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") -JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") -JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") -JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") -JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") -JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") -JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") -JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") -JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") -JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") -JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") -JMESSAGE(JERR_EMS_READ, "Read from EMS failed") -JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") -JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") -JMESSAGE(JERR_FILE_READ, "Input file read error") -JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") -JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") -JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") -JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") -JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") -JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") -JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") -JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, - "Cannot transcode due to multiple use of quantization table %d") -JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") -JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") -JMESSAGE(JERR_NOTIMPL, "Not implemented yet") -JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") -JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") -JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") -JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") -JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") -JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") -JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") -JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") -JMESSAGE(JERR_QUANT_COMPONENTS, - "Cannot quantize more than %d color components") -JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") -JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") -JMESSAGE(JERR_SOF_BEFORE, "Invalid JPEG file structure: %s before SOF") -JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") -JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") -JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") -JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") -JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") -JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") -JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") -JMESSAGE(JERR_TFILE_WRITE, - "Write failed on temporary file --- out of disk space?") -JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") -JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") -JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") -JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") -JMESSAGE(JERR_XMS_READ, "Read from XMS failed") -JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") -JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) -JMESSAGE(JMSG_VERSION, JVERSION) -JMESSAGE(JTRC_16BIT_TABLES, - "Caution: quantization tables are too coarse for baseline JPEG") -JMESSAGE(JTRC_ADOBE, - "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") -JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") -JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") -JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") -JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") -JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") -JMESSAGE(JTRC_DRI, "Define Restart Interval %u") -JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") -JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") -JMESSAGE(JTRC_EOI, "End Of Image") -JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") -JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") -JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, - "Warning: thumbnail image size does not match data length %u") -JMESSAGE(JTRC_JFIF_EXTENSION, - "JFIF extension marker: type 0x%02x, length %u") -JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") -JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") -JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") -JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") -JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") -JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") -JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") -JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") -JMESSAGE(JTRC_RST, "RST%d") -JMESSAGE(JTRC_SMOOTH_NOTIMPL, - "Smoothing not supported with nonstandard sampling ratios") -JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") -JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") -JMESSAGE(JTRC_SOI, "Start of Image") -JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") -JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") -JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") -JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") -JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") -JMESSAGE(JTRC_THUMB_JPEG, - "JFIF extension marker: JPEG-compressed thumbnail image, length %u") -JMESSAGE(JTRC_THUMB_PALETTE, - "JFIF extension marker: palette thumbnail image, length %u") -JMESSAGE(JTRC_THUMB_RGB, - "JFIF extension marker: RGB thumbnail image, length %u") -JMESSAGE(JTRC_UNKNOWN_IDS, - "Unrecognized component IDs %d %d %d, assuming YCbCr") -JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") -JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") -JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") -JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") -JMESSAGE(JWRN_BOGUS_PROGRESSION, - "Inconsistent progression sequence for component %d coefficient %d") -JMESSAGE(JWRN_EXTRANEOUS_DATA, - "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") -JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") -JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") -JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") -JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") -JMESSAGE(JWRN_MUST_RESYNC, - "Corrupt JPEG data: found marker 0x%02x instead of RST%d") -JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") -JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTMSGCODE -} J_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE - - -#ifndef JERROR_H -#define JERROR_H - -/* Macros to simplify using the error and trace message stuff */ -/* The first parameter is either type of cinfo pointer */ - -/* Fatal errors (print message and exit) */ -#define ERREXIT(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT3(cinfo,code,p1,p2,p3) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (cinfo)->err->msg_parm.i[3] = (p4), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (cinfo)->err->msg_parm.i[3] = (p4), \ - (cinfo)->err->msg_parm.i[4] = (p5), \ - (cinfo)->err->msg_parm.i[5] = (p6), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXITS(cinfo,code,str) \ - ((cinfo)->err->msg_code = (code), \ - strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) - -#define MAKESTMT(stuff) do { stuff } while (0) - -/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ -#define WARNMS(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) - -/* Informational/debugging messages */ -#define TRACEMS(cinfo,lvl,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS1(cinfo,lvl,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS2(cinfo,lvl,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMSS(cinfo,lvl,code,str) \ - ((cinfo)->err->msg_code = (code), \ - strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) - -#endif /* JERROR_H */ diff --git a/libraries/jpeg/jidctflt.c b/libraries/jpeg/jidctflt.c deleted file mode 100644 index e33a2b5e42..0000000000 --- a/libraries/jpeg/jidctflt.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * jidctflt.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * Modified 2010-2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a floating-point implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * This implementation should be more accurate than either of the integer - * IDCT implementations. However, it may not give the same results on all - * machines because of differences in roundoff behavior. Speed will depend - * on the hardware's floating point capacity. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with a fixed-point - * implementation, accuracy is lost due to imprecise representation of the - * scaled quantization values. However, that problem does not arise if - * we use floating point arithmetic. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_FLOAT_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce a float result. - */ - -#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - * - * cK represents cos(K*pi/16). - */ - -GLOBAL(void) -jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - FAST_FLOAT tmp10, tmp11, tmp12, tmp13; - FAST_FLOAT z5, z10, z11, z12, z13; - JCOEFPTR inptr; - FLOAT_MULT_TYPE * quantptr; - FAST_FLOAT * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ - - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ - tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 - tmp5; - - wsptr[DCTSIZE*0] = tmp0 + tmp7; - wsptr[DCTSIZE*7] = tmp0 - tmp7; - wsptr[DCTSIZE*1] = tmp1 + tmp6; - wsptr[DCTSIZE*6] = tmp1 - tmp6; - wsptr[DCTSIZE*2] = tmp2 + tmp5; - wsptr[DCTSIZE*5] = tmp2 - tmp5; - wsptr[DCTSIZE*3] = tmp3 + tmp4; - wsptr[DCTSIZE*4] = tmp3 - tmp4; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * And testing floats for zero is relatively expensive, so we don't bother. - */ - - /* Even part */ - - /* Prepare range-limit and float->int conversion */ - z5 = wsptr[0] + (((FAST_FLOAT) RANGE_CENTER) + ((FAST_FLOAT) 0.5)); - tmp10 = z5 + wsptr[4]; - tmp11 = z5 - wsptr[4]; - - tmp13 = wsptr[2] + wsptr[6]; - tmp12 = (wsptr[2] - wsptr[6]) * - ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - z13 = wsptr[5] + wsptr[3]; - z10 = wsptr[5] - wsptr[3]; - z11 = wsptr[1] + wsptr[7]; - z12 = wsptr[1] - wsptr[7]; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ - - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ - tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 - tmp5; - - /* Final output stage: float->int conversion and range-limit */ - - outptr[0] = range_limit[(int) (tmp0 + tmp7) & RANGE_MASK]; - outptr[7] = range_limit[(int) (tmp0 - tmp7) & RANGE_MASK]; - outptr[1] = range_limit[(int) (tmp1 + tmp6) & RANGE_MASK]; - outptr[6] = range_limit[(int) (tmp1 - tmp6) & RANGE_MASK]; - outptr[2] = range_limit[(int) (tmp2 + tmp5) & RANGE_MASK]; - outptr[5] = range_limit[(int) (tmp2 - tmp5) & RANGE_MASK]; - outptr[3] = range_limit[(int) (tmp3 + tmp4) & RANGE_MASK]; - outptr[4] = range_limit[(int) (tmp3 - tmp4) & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/libraries/jpeg/jidctfst.c b/libraries/jpeg/jidctfst.c deleted file mode 100644 index 1ac3e39cb7..0000000000 --- a/libraries/jpeg/jidctfst.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * jidctfst.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * Modified 2015-2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a fast, not so accurate integer implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with fixed-point math, - * accuracy is lost due to imprecise representation of the scaled - * quantization values. The smaller the quantization table entry, the less - * precise the scaled value, so this implementation does worse with high- - * quality-setting files than with low-quality ones. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_IFAST_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ -#endif - - -/* Scaling decisions are generally the same as in the LL&M algorithm; - * see jidctint.c for more details. However, we choose to descale - * (right shift) multiplication products as soon as they are formed, - * rather than carrying additional fractional bits into subsequent additions. - * This compromises accuracy slightly, but it lets us save a few shifts. - * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) - * everywhere except in the multiplications proper; this saves a good deal - * of work on 16-bit-int machines. - * - * The dequantized coefficients are not integers because the AA&N scaling - * factors have been incorporated. We represent them scaled up by PASS1_BITS, - * so that the first and second IDCT rounds have the same input scaling. - * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to - * avoid a descaling shift; this compromises accuracy rather drastically - * for small quantization table entries, but it saves a lot of shifts. - * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, - * so we use a much larger scaling factor to preserve accuracy. - * - * A final compromise is to represent the multiplicative constants to only - * 8 fractional bits, rather than 13. This saves some shifting work on some - * machines, and may also reduce the cost of multiplication (since there - * are fewer one-bits in the constants). - */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 8 -#define PASS1_BITS 2 -#else -#define CONST_BITS 8 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 8 -#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ -#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ -#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ -#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ -#else -#define FIX_1_082392200 FIX(1.082392200) -#define FIX_1_414213562 FIX(1.414213562) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_2_613125930 FIX(2.613125930) -#endif - - -/* We can gain a little more speed, with a further compromise in accuracy, - * by omitting the addition in a descaling shift. This yields an incorrectly - * rounded result half the time... - */ - -#ifndef USE_ACCURATE_ROUNDING -#undef DESCALE -#define DESCALE(x,n) RIGHT_SHIFT(x, n) -#endif - - -/* Multiply a DCTELEM variable by an INT32 constant, and immediately - * descale to yield a DCTELEM result. - */ - -#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 - * multiplication will do. For 12-bit data, the multiplier table is - * declared INT32, so a 32-bit multiply will be used. - */ - -#if BITS_IN_JSAMPLE == 8 -#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) -#else -#define DEQUANTIZE(coef,quantval) \ - DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) -#endif - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - * - * cK represents cos(K*pi/16). - */ - -GLOBAL(void) -jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - DCTELEM tmp10, tmp11, tmp12, tmp13; - DCTELEM z5, z10, z11, z12, z13; - JCOEFPTR inptr; - IFAST_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS /* for DESCALE */ - ISHIFT_TEMPS /* for IRIGHT_SHIFT */ - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = z5 - MULTIPLY(z12, FIX_1_082392200); /* 2*(c2-c6) */ - tmp12 = z5 - MULTIPLY(z10, FIX_2_613125930); /* 2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 - tmp5; - - wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); - wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); - wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); - wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); - wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); - wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); - wsptr[DCTSIZE*3] = (int) (tmp3 + tmp4); - wsptr[DCTSIZE*4] = (int) (tmp3 - tmp4); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. - * Note that we must descale the results by a factor of 8 == 2**3, - * and also undo the PASS1_BITS scaling. - */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Add range center and fudge factor for final descale and range-limit. */ - z5 = (DCTELEM) wsptr[0] + - ((((DCTELEM) RANGE_CENTER) << (PASS1_BITS+3)) + - (1 << (PASS1_BITS+2))); - - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) IRIGHT_SHIFT(z5, PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp10 = z5 + (DCTELEM) wsptr[4]; - tmp11 = z5 - (DCTELEM) wsptr[4]; - - tmp13 = (DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]; - tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], - FIX_1_414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; - z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; - z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; - z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = z5 - MULTIPLY(z12, FIX_1_082392200); /* 2*(c2-c6) */ - tmp12 = z5 - MULTIPLY(z10, FIX_2_613125930); /* 2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 - tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit */ - - outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp1 + tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) IRIGHT_SHIFT(tmp1 - tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) IRIGHT_SHIFT(tmp2 + tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) IRIGHT_SHIFT(tmp2 - tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) IRIGHT_SHIFT(tmp3 + tmp4, PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) IRIGHT_SHIFT(tmp3 - tmp4, PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_IFAST_SUPPORTED */ diff --git a/libraries/jpeg/jidctint.c b/libraries/jpeg/jidctint.c deleted file mode 100644 index 6437079a31..0000000000 --- a/libraries/jpeg/jidctint.c +++ /dev/null @@ -1,5240 +0,0 @@ -/* - * jidctint.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * Modification developed 2002-2016 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a slow-but-accurate integer implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on an algorithm described in - * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT - * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, - * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. - * The primary algorithm described there uses 11 multiplies and 29 adds. - * We use their alternate method with 12 multiplies and 32 adds. - * The advantage of this method is that no data path contains more than one - * multiplication; this allows a very simple and accurate implementation in - * scaled fixed-point arithmetic, with a minimal number of shifts. - * - * We also provide IDCT routines with various output sample block sizes for - * direct resolution reduction or enlargement and for direct resolving the - * common 2x1 and 1x2 subsampling cases without additional resampling: NxN - * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 input DCT block. - * - * For N<8 we simply take the corresponding low-frequency coefficients of - * the 8x8 input DCT block and apply an NxN point IDCT on the sub-block - * to yield the downscaled outputs. - * This can be seen as direct low-pass downsampling from the DCT domain - * point of view rather than the usual spatial domain point of view, - * yielding significant computational savings and results at least - * as good as common bilinear (averaging) spatial downsampling. - * - * For N>8 we apply a partial NxN IDCT on the 8 input coefficients as - * lower frequencies and higher frequencies assumed to be zero. - * It turns out that the computational effort is similar to the 8x8 IDCT - * regarding the output size. - * Furthermore, the scaling and descaling is the same for all IDCT sizes. - * - * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases - * since there would be too many additional constants to pre-calculate. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_ISLOW_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ -#endif - - -/* - * The poop on this scaling stuff is as follows: - * - * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) - * larger than the true IDCT outputs. The final outputs are therefore - * a factor of N larger than desired; since N=8 this can be cured by - * a simple right shift at the end of the algorithm. The advantage of - * this arrangement is that we save two multiplications per 1-D IDCT, - * because the y0 and y4 inputs need not be divided by sqrt(N). - * - * We have to do addition and subtraction of the integer inputs, which - * is no problem, and multiplication by fractional constants, which is - * a problem to do in integer arithmetic. We multiply all the constants - * by CONST_SCALE and convert them to integer constants (thus retaining - * CONST_BITS bits of precision in the constants). After doing a - * multiplication we have to divide the product by CONST_SCALE, with proper - * rounding, to produce the correct output. This division can be done - * cheaply as a right shift of CONST_BITS bits. We postpone shifting - * as long as possible so that partial sums can be added together with - * full fractional precision. - * - * The outputs of the first pass are scaled up by PASS1_BITS bits so that - * they are represented to better-than-integral precision. These outputs - * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word - * with the recommended scaling. (To scale up 12-bit sample data further, an - * intermediate INT32 array would be needed.) - * - * To avoid overflow of the 32-bit intermediate results in pass 2, we must - * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis - * shows that the values given below are the most effective. - */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ -#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ -#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ -#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ -#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ -#else -#define FIX_0_298631336 FIX(0.298631336) -#define FIX_0_390180644 FIX(0.390180644) -#define FIX_0_541196100 FIX(0.541196100) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_175875602 FIX(1.175875602) -#define FIX_1_501321110 FIX(1.501321110) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_1_961570560 FIX(1.961570560) -#define FIX_2_053119869 FIX(2.053119869) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_072711026 FIX(3.072711026) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - -#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - * - * Optimized algorithm with 12 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/16). - */ - -GLOBAL(void) -jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * Note results are scaled up by sqrt(8) compared to a true IDCT; - * furthermore, we scale the results by 2**PASS1_BITS. - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part: reverse the even part of the forward DCT. - * The rotator is c(-6). - */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z2 <<= CONST_BITS; - z3 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z2 += ONE << (CONST_BITS-PASS1_BITS-1); - - tmp0 = z2 + z3; - tmp1 = z2 - z3; - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - tmp10 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - tmp11 = tmp1 + tmp3; - tmp12 = tmp1 - tmp3; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - z2 = tmp0 + tmp2; - z3 = tmp1 + tmp3; - - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ - z2 += z1; - z3 += z1; - - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp0 += z1 + z2; - tmp3 += z1 + z3; - - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp1 += z1 + z3; - tmp2 += z1 + z2; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. - * Note that we must descale the results by a factor of 8 == 2**3, - * and also undo the PASS1_BITS scaling. - */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Add range center and fudge factor for final descale and range-limit. */ - z2 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) RIGHT_SHIFT(z2, PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part: reverse the even part of the forward DCT. - * The rotator is c(-6). - */ - - z3 = (INT32) wsptr[4]; - - tmp0 = (z2 + z3) << CONST_BITS; - tmp1 = (z2 - z3) << CONST_BITS; - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - tmp10 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - tmp11 = tmp1 + tmp3; - tmp12 = tmp1 - tmp3; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = (INT32) wsptr[7]; - tmp1 = (INT32) wsptr[5]; - tmp2 = (INT32) wsptr[3]; - tmp3 = (INT32) wsptr[1]; - - z2 = tmp0 + tmp2; - z3 = tmp1 + tmp3; - - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ - z2 += z1; - z3 += z1; - - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp0 += z1 + z2; - tmp3 += z1 + z3; - - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp1 += z1 + z3; - tmp2 += z1 + z2; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#ifdef IDCT_SCALING_SUPPORTED - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 7x7 output block. - * - * Optimized algorithm with 12 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/14). - */ - -GLOBAL(void) -jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[7*7]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp13 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp13 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp13 += ONE << (CONST_BITS-PASS1_BITS-1); - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ - tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ - tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ - tmp0 = z1 + z3; - z2 -= tmp0; - tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ - tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ - tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ - tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - - tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ - tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ - tmp0 = tmp1 - tmp2; - tmp1 += tmp2; - tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ - tmp1 += tmp2; - z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ - tmp0 += z2; - tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ - - /* Final output stage */ - - wsptr[7*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[7*6] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[7*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[7*5] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[7*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[7*4] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[7*3] = (int) RIGHT_SHIFT(tmp13, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 7 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 7; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp13 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp13 <<= CONST_BITS; - - z1 = (INT32) wsptr[2]; - z2 = (INT32) wsptr[4]; - z3 = (INT32) wsptr[6]; - - tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ - tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ - tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ - tmp0 = z1 + z3; - z2 -= tmp0; - tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ - tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ - tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ - tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - - tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ - tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ - tmp0 = tmp1 - tmp2; - tmp1 += tmp2; - tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ - tmp1 += tmp2; - z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ - tmp0 += z2; - tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 7; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 6x6 output block. - * - * Optimized algorithm with 3 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/12). - */ - -GLOBAL(void) -jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[6*6]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ - tmp1 = tmp0 + tmp10; - tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); - tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ - tmp10 = tmp1 + tmp0; - tmp12 = tmp1 - tmp0; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ - tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); - tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); - tmp1 = (z1 - z2 - z3) << PASS1_BITS; - - /* Final output stage */ - - wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[6*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[6*1] = (int) (tmp11 + tmp1); - wsptr[6*4] = (int) (tmp11 - tmp1); - wsptr[6*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[6*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 6 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 6; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp0 <<= CONST_BITS; - tmp2 = (INT32) wsptr[4]; - tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ - tmp1 = tmp0 + tmp10; - tmp11 = tmp0 - tmp10 - tmp10; - tmp10 = (INT32) wsptr[2]; - tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ - tmp10 = tmp1 + tmp0; - tmp12 = tmp1 - tmp0; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ - tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); - tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); - tmp1 = (z1 - z2 - z3) << CONST_BITS; - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 6; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 5x5 output block. - * - * Optimized algorithm with 5 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/10). - */ - -GLOBAL(void) -jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp10, tmp11, tmp12; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[5*5]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp12 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp0 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ - z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ - z3 = tmp12 + z2; - tmp10 = z3 + z1; - tmp11 = z3 - z1; - tmp12 -= z2 << 2; - - /* Odd part */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - - z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ - tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ - tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ - - /* Final output stage */ - - wsptr[5*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[5*4] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[5*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[5*3] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[5*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 5 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 5; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp12 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp12 <<= CONST_BITS; - tmp0 = (INT32) wsptr[2]; - tmp1 = (INT32) wsptr[4]; - z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ - z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ - z3 = tmp12 + z2; - tmp10 = z3 + z1; - tmp11 = z3 - z1; - tmp12 -= z2 << 2; - - /* Odd part */ - - z2 = (INT32) wsptr[1]; - z3 = (INT32) wsptr[3]; - - z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ - tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ - tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 5; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 4x4 output block. - * - * Optimized algorithm with 3 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. - */ - -GLOBAL(void) -jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp2, tmp10, tmp12; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[4*4]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - - tmp10 = (tmp0 + tmp2) << PASS1_BITS; - tmp12 = (tmp0 - tmp2) << PASS1_BITS; - - /* Odd part */ - /* Same rotation as in the even part of the 8x8 LL&M IDCT */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - /* Add fudge factor here for final descale. */ - z1 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ - CONST_BITS-PASS1_BITS); - tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ - CONST_BITS-PASS1_BITS); - - /* Final output stage */ - - wsptr[4*0] = (int) (tmp10 + tmp0); - wsptr[4*3] = (int) (tmp10 - tmp0); - wsptr[4*1] = (int) (tmp12 + tmp2); - wsptr[4*2] = (int) (tmp12 - tmp2); - } - - /* Pass 2: process 4 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp2 = (INT32) wsptr[2]; - - tmp10 = (tmp0 + tmp2) << CONST_BITS; - tmp12 = (tmp0 - tmp2) << CONST_BITS; - - /* Odd part */ - /* Same rotation as in the even part of the 8x8 LL&M IDCT */ - - z2 = (INT32) wsptr[1]; - z3 = (INT32) wsptr[3]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 4; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 3x3 output block. - * - * Optimized algorithm with 2 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/6). - */ - -GLOBAL(void) -jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp2, tmp10, tmp12; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[3*3]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ - tmp10 = tmp0 + tmp12; - tmp2 = tmp0 - tmp12 - tmp12; - - /* Odd part */ - - tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ - - /* Final output stage */ - - wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[3*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[3*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 3 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 3; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp0 <<= CONST_BITS; - tmp2 = (INT32) wsptr[2]; - tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ - tmp10 = tmp0 + tmp12; - tmp2 = tmp0 - tmp12 - tmp12; - - /* Odd part */ - - tmp12 = (INT32) wsptr[1]; - tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 3; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 2x2 output block. - * - * Multiplication-less algorithm. - */ - -GLOBAL(void) -jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - ISLOW_MULT_TYPE * quantptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - ISHIFT_TEMPS - - /* Pass 1: process columns from input. */ - - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - - /* Column 0 */ - tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); - /* Add range center and fudge factor for final descale and range-limit. */ - tmp4 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); - - tmp0 = tmp4 + tmp5; - tmp2 = tmp4 - tmp5; - - /* Column 1 */ - tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0+1], quantptr[DCTSIZE*0+1]); - tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1+1], quantptr[DCTSIZE*1+1]); - - tmp1 = tmp4 + tmp5; - tmp3 = tmp4 - tmp5; - - /* Pass 2: process 2 rows, store into output array. */ - - /* Row 0 */ - outptr = output_buf[0] + output_col; - - outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; - outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; - - /* Row 1 */ - outptr = output_buf[1] + output_col; - - outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp2 + tmp3, 3) & RANGE_MASK]; - outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp2 - tmp3, 3) & RANGE_MASK]; -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 1x1 output block. - * - * We hardly need an inverse DCT routine for this: just take the - * average pixel value, which is one-eighth of the DC coefficient. - */ - -GLOBAL(void) -jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - DCTELEM dcval; - ISLOW_MULT_TYPE * quantptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - ISHIFT_TEMPS - - /* 1x1 is trivial: just take the DC coefficient divided by 8. */ - - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - - dcval = DEQUANTIZE(coef_block[0], quantptr[0]); - /* Add range center and fudge factor for descale and range-limit. */ - dcval += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); - - output_buf[0][output_col] = - range_limit[(int) IRIGHT_SHIFT(dcval, 3) & RANGE_MASK]; -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 9x9 output block. - * - * Optimized algorithm with 10 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/18). - */ - -GLOBAL(void) -jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*9]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ - tmp1 = tmp0 + tmp3; - tmp2 = tmp0 - tmp3 - tmp3; - - tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ - tmp11 = tmp2 + tmp0; - tmp14 = tmp2 - tmp0 - tmp0; - - tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ - tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ - tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ - - tmp10 = tmp1 + tmp0 - tmp3; - tmp12 = tmp1 - tmp0 + tmp2; - tmp13 = tmp1 - tmp2 + tmp3; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ - - tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ - tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ - tmp0 = tmp2 + tmp3 - z2; - tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ - tmp2 += z2 - tmp1; - tmp3 += z2 + tmp1; - tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[8*7] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp14, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 9 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 9; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp0 <<= CONST_BITS; - - z1 = (INT32) wsptr[2]; - z2 = (INT32) wsptr[4]; - z3 = (INT32) wsptr[6]; - - tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ - tmp1 = tmp0 + tmp3; - tmp2 = tmp0 - tmp3 - tmp3; - - tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ - tmp11 = tmp2 + tmp0; - tmp14 = tmp2 - tmp0 - tmp0; - - tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ - tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ - tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ - - tmp10 = tmp1 + tmp0 - tmp3; - tmp12 = tmp1 - tmp0 + tmp2; - tmp13 = tmp1 - tmp2 + tmp3; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - - z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ - - tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ - tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ - tmp0 = tmp2 + tmp3 - z2; - tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ - tmp2 += z2 - tmp1; - tmp3 += z2 + tmp1; - tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 10x10 output block. - * - * Optimized algorithm with 12 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/20). - */ - -GLOBAL(void) -jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24; - INT32 z1, z2, z3, z4, z5; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*10]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z3 += ONE << (CONST_BITS-PASS1_BITS-1); - z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ - z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ - tmp10 = z3 + z1; - tmp11 = z3 - z2; - - tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ - CONST_BITS-PASS1_BITS); - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ - tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ - tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ - - tmp20 = tmp10 + tmp12; - tmp24 = tmp10 - tmp12; - tmp21 = tmp11 + tmp13; - tmp23 = tmp11 - tmp13; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp11 = z2 + z4; - tmp13 = z2 - z4; - - tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ - z5 = z3 << CONST_BITS; - - z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ - z4 = z5 + tmp12; - - tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ - tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ - - z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ - z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); - - tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; - - tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ - tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) (tmp22 + tmp12); - wsptr[8*7] = (int) (tmp22 - tmp12); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 10 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 10; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z3 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z3 <<= CONST_BITS; - z4 = (INT32) wsptr[4]; - z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ - z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ - tmp10 = z3 + z1; - tmp11 = z3 - z2; - - tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ - tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ - tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ - - tmp20 = tmp10 + tmp12; - tmp24 = tmp10 - tmp12; - tmp21 = tmp11 + tmp13; - tmp23 = tmp11 - tmp13; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z3 <<= CONST_BITS; - z4 = (INT32) wsptr[7]; - - tmp11 = z2 + z4; - tmp13 = z2 - z4; - - tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ - - z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ - z4 = z3 + tmp12; - - tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ - tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ - - z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ - z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); - - tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; - - tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ - tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 11x11 output block. - * - * Optimized algorithm with 24 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/22). - */ - -GLOBAL(void) -jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*11]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp10 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ - tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ - z4 = z1 + z3; - tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ - z4 -= z2; - tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ - tmp21 = tmp20 + tmp23 + tmp25 - - MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ - tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ - tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ - tmp24 += tmp25; - tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ - tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ - MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ - tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp11 = z1 + z2; - tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ - tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ - tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ - tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ - tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ - z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ - tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ - tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ - z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ - tmp11 += z1; - tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ - tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ - MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ - MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*10] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*9] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*7] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp25, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 11 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 11; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp10 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp10 <<= CONST_BITS; - - z1 = (INT32) wsptr[2]; - z2 = (INT32) wsptr[4]; - z3 = (INT32) wsptr[6]; - - tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ - tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ - z4 = z1 + z3; - tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ - z4 -= z2; - tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ - tmp21 = tmp20 + tmp23 + tmp25 - - MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ - tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ - tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ - tmp24 += tmp25; - tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ - tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ - MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ - tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - - tmp11 = z1 + z2; - tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ - tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ - tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ - tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ - tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ - z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ - tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ - tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ - z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ - tmp11 += z1; - tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ - tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ - MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ - MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 12x12 output block. - * - * Optimized algorithm with 15 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/24). - */ - -GLOBAL(void) -jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*12]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z3 += ONE << (CONST_BITS-PASS1_BITS-1); - - z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ - - tmp10 = z3 + z4; - tmp11 = z3 - z4; - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ - z1 <<= CONST_BITS; - z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z2 <<= CONST_BITS; - - tmp12 = z1 - z2; - - tmp21 = z3 + tmp12; - tmp24 = z3 - tmp12; - - tmp12 = z4 + z2; - - tmp20 = tmp10 + tmp12; - tmp25 = tmp10 - tmp12; - - tmp12 = z4 - z1 - z2; - - tmp22 = tmp11 + tmp12; - tmp23 = tmp11 - tmp12; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ - tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ - - tmp10 = z1 + z3; - tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ - tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ - tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ - tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ - tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ - tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ - tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ - MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ - - z1 -= z4; - z2 -= z3; - z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ - tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ - tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 12 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 12; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z3 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z3 <<= CONST_BITS; - - z4 = (INT32) wsptr[4]; - z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ - - tmp10 = z3 + z4; - tmp11 = z3 - z4; - - z1 = (INT32) wsptr[2]; - z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ - z1 <<= CONST_BITS; - z2 = (INT32) wsptr[6]; - z2 <<= CONST_BITS; - - tmp12 = z1 - z2; - - tmp21 = z3 + tmp12; - tmp24 = z3 - tmp12; - - tmp12 = z4 + z2; - - tmp20 = tmp10 + tmp12; - tmp25 = tmp10 - tmp12; - - tmp12 = z4 - z1 - z2; - - tmp22 = tmp11 + tmp12; - tmp23 = tmp11 - tmp12; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - - tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ - tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ - - tmp10 = z1 + z3; - tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ - tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ - tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ - tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ - tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ - tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ - tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ - MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ - - z1 -= z4; - z2 -= z3; - z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ - tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ - tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 13x13 output block. - * - * Optimized algorithm with 29 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/26). - */ - -GLOBAL(void) -jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*13]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z1 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z1 += ONE << (CONST_BITS-PASS1_BITS-1); - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = z3 + z4; - tmp11 = z3 - z4; - - tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ - tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ - - tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ - tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ - - tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ - tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ - - tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ - tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ - - tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ - tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ - - tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ - tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ - - tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ - tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ - tmp15 = z1 + z4; - tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ - tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ - tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ - tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ - tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ - tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ - tmp11 += tmp14; - tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ - tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ - tmp12 += tmp14; - tmp13 += tmp14; - tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ - tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ - MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ - z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ - tmp14 += z1; - tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ - MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*12] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*11] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*10] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*9] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); - wsptr[8*7] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp26, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 13 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 13; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z1 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z1 <<= CONST_BITS; - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[4]; - z4 = (INT32) wsptr[6]; - - tmp10 = z3 + z4; - tmp11 = z3 - z4; - - tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ - tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ - - tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ - tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ - - tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ - tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ - - tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ - tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ - - tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ - tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ - - tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ - tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ - - tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - - tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ - tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ - tmp15 = z1 + z4; - tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ - tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ - tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ - tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ - tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ - tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ - tmp11 += tmp14; - tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ - tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ - tmp12 += tmp14; - tmp13 += tmp14; - tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ - tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ - MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ - z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ - tmp14 += z1; - tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ - MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 14x14 output block. - * - * Optimized algorithm with 20 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/28). - */ - -GLOBAL(void) -jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*14]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z1 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z1 += ONE << (CONST_BITS-PASS1_BITS-1); - z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ - z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ - z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ - - tmp10 = z1 + z2; - tmp11 = z1 + z3; - tmp12 = z1 - z4; - - tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ - CONST_BITS-PASS1_BITS); - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ - - tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ - tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ - tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ - MULTIPLY(z2, FIX(1.378756276)); /* c2 */ - - tmp20 = tmp10 + tmp13; - tmp26 = tmp10 - tmp13; - tmp21 = tmp11 + tmp14; - tmp25 = tmp11 - tmp14; - tmp22 = tmp12 + tmp15; - tmp24 = tmp12 - tmp15; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp13 = z4 << CONST_BITS; - - tmp14 = z1 + z3; - tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ - tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ - tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ - tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ - tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ - z1 -= z2; - tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ - tmp16 += tmp15; - z1 += z4; - z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ - tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ - tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ - z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ - tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ - tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ - - tmp13 = (z1 - z3) << PASS1_BITS; - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) (tmp23 + tmp13); - wsptr[8*10] = (int) (tmp23 - tmp13); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); - wsptr[8*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 14 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 14; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z1 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z1 <<= CONST_BITS; - z4 = (INT32) wsptr[4]; - z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ - z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ - z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ - - tmp10 = z1 + z2; - tmp11 = z1 + z3; - tmp12 = z1 - z4; - - tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ - - z1 = (INT32) wsptr[2]; - z2 = (INT32) wsptr[6]; - - z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ - - tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ - tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ - tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ - MULTIPLY(z2, FIX(1.378756276)); /* c2 */ - - tmp20 = tmp10 + tmp13; - tmp26 = tmp10 - tmp13; - tmp21 = tmp11 + tmp14; - tmp25 = tmp11 - tmp14; - tmp22 = tmp12 + tmp15; - tmp24 = tmp12 - tmp15; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - z4 <<= CONST_BITS; - - tmp14 = z1 + z3; - tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ - tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ - tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ - tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ - tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ - z1 -= z2; - tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ - tmp16 += tmp15; - tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ - tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ - tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ - tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ - tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ - tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ - - tmp13 = ((z1 - z3) << CONST_BITS) + z4; - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 15x15 output block. - * - * Optimized algorithm with 22 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/30). - */ - -GLOBAL(void) -jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*15]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z1 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z1 += ONE << (CONST_BITS-PASS1_BITS-1); - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ - tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ - - tmp12 = z1 - tmp10; - tmp13 = z1 + tmp11; - z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ - - z4 = z2 - z3; - z3 += z2; - tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ - tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ - z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ - - tmp20 = tmp13 + tmp10 + tmp11; - tmp23 = tmp12 - tmp10 + tmp11 + z2; - - tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ - tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ - - tmp25 = tmp13 - tmp10 - tmp11; - tmp26 = tmp12 + tmp10 - tmp11 - z2; - - tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ - tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ - - tmp21 = tmp12 + tmp10 + tmp11; - tmp24 = tmp13 - tmp10 + tmp11; - tmp11 += tmp11; - tmp22 = z1 + tmp11; /* c10 = c6-c12 */ - tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z4 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp13 = z2 - z4; - tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ - tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ - tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ - - tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ - tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ - z2 = z1 - z4; - tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ - - tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ - tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ - tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ - z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ - tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ - tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*14] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*13] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*12] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*11] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*10] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); - wsptr[8*9] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); - wsptr[8*7] = (int) RIGHT_SHIFT(tmp27, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 15 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 15; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z1 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z1 <<= CONST_BITS; - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[4]; - z4 = (INT32) wsptr[6]; - - tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ - tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ - - tmp12 = z1 - tmp10; - tmp13 = z1 + tmp11; - z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ - - z4 = z2 - z3; - z3 += z2; - tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ - tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ - z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ - - tmp20 = tmp13 + tmp10 + tmp11; - tmp23 = tmp12 - tmp10 + tmp11 + z2; - - tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ - tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ - - tmp25 = tmp13 - tmp10 - tmp11; - tmp26 = tmp12 + tmp10 - tmp11 - z2; - - tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ - tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ - - tmp21 = tmp12 + tmp10 + tmp11; - tmp24 = tmp13 - tmp10 + tmp11; - tmp11 += tmp11; - tmp22 = z1 + tmp11; /* c10 = c6-c12 */ - tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z4 = (INT32) wsptr[5]; - z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ - z4 = (INT32) wsptr[7]; - - tmp13 = z2 - z4; - tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ - tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ - tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ - - tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ - tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ - z2 = z1 - z4; - tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ - - tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ - tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ - tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ - z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ - tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ - tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 16x16 output block. - * - * Optimized algorithm with 28 multiplications in the 1-D kernel. - * cK represents sqrt(2) * cos(K*pi/32). - */ - -GLOBAL(void) -jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*16]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); - - z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ - tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ - - tmp10 = tmp0 + tmp1; - tmp11 = tmp0 - tmp1; - tmp12 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z3 = z1 - z2; - z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ - z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ - - tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ - tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ - tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ - tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ - - tmp20 = tmp10 + tmp0; - tmp27 = tmp10 - tmp0; - tmp21 = tmp12 + tmp1; - tmp26 = tmp12 - tmp1; - tmp22 = tmp13 + tmp2; - tmp25 = tmp13 - tmp2; - tmp23 = tmp11 + tmp3; - tmp24 = tmp11 - tmp3; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp11 = z1 + z3; - - tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ - tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ - tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ - tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ - tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ - tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ - tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ - tmp13 = tmp10 + tmp11 + tmp12 - - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ - z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ - tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ - tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ - z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ - tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ - tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ - z2 += z4; - z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ - tmp1 += z1; - tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ - z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ - tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ - tmp12 += z2; - z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ - tmp2 += z2; - tmp3 += z2; - z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ - tmp10 += z2; - tmp11 += z2; - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 16 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 16; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp0 <<= CONST_BITS; - - z1 = (INT32) wsptr[4]; - tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ - tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ - - tmp10 = tmp0 + tmp1; - tmp11 = tmp0 - tmp1; - tmp12 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - - z1 = (INT32) wsptr[2]; - z2 = (INT32) wsptr[6]; - z3 = z1 - z2; - z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ - z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ - - tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ - tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ - tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ - tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ - - tmp20 = tmp10 + tmp0; - tmp27 = tmp10 - tmp0; - tmp21 = tmp12 + tmp1; - tmp26 = tmp12 - tmp1; - tmp22 = tmp13 + tmp2; - tmp25 = tmp13 - tmp2; - tmp23 = tmp11 + tmp3; - tmp24 = tmp11 - tmp3; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - - tmp11 = z1 + z3; - - tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ - tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ - tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ - tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ - tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ - tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ - tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ - tmp13 = tmp10 + tmp11 + tmp12 - - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ - z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ - tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ - tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ - z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ - tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ - tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ - z2 += z4; - z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ - tmp1 += z1; - tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ - z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ - tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ - tmp12 += z2; - z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ - tmp2 += z2; - tmp3 += z2; - z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ - tmp10 += z2; - tmp11 += z2; - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 16x8 output block. - * - * 8-point IDCT in pass 1 (columns), 16-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*8]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * Note results are scaled up by sqrt(8) compared to a true IDCT; - * furthermore, we scale the results by 2**PASS1_BITS. - * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part: reverse the even part of the forward DCT. - * The rotator is c(-6). - */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z2 <<= CONST_BITS; - z3 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z2 += ONE << (CONST_BITS-PASS1_BITS-1); - - tmp0 = z2 + z3; - tmp1 = z2 - z3; - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - tmp10 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - tmp11 = tmp1 + tmp3; - tmp12 = tmp1 - tmp3; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - z2 = tmp0 + tmp2; - z3 = tmp1 + tmp3; - - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ - z2 += z1; - z3 += z1; - - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp0 += z1 + z2; - tmp3 += z1 + z3; - - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp1 += z1 + z3; - tmp2 += z1 + z2; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process 8 rows from work array, store into output array. - * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp0 <<= CONST_BITS; - - z1 = (INT32) wsptr[4]; - tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ - tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ - - tmp10 = tmp0 + tmp1; - tmp11 = tmp0 - tmp1; - tmp12 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - - z1 = (INT32) wsptr[2]; - z2 = (INT32) wsptr[6]; - z3 = z1 - z2; - z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ - z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ - - tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ - tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ - tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ - tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ - - tmp20 = tmp10 + tmp0; - tmp27 = tmp10 - tmp0; - tmp21 = tmp12 + tmp1; - tmp26 = tmp12 - tmp1; - tmp22 = tmp13 + tmp2; - tmp25 = tmp13 - tmp2; - tmp23 = tmp11 + tmp3; - tmp24 = tmp11 - tmp3; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - - tmp11 = z1 + z3; - - tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ - tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ - tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ - tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ - tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ - tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ - tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ - tmp13 = tmp10 + tmp11 + tmp12 - - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ - z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ - tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ - tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ - z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ - tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ - tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ - z2 += z4; - z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ - tmp1 += z1; - tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ - z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ - tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ - tmp12 += z2; - z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ - tmp2 += z2; - tmp3 += z2; - z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ - tmp10 += z2; - tmp11 += z2; - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 14x7 output block. - * - * 7-point IDCT in pass 1 (columns), 14-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*7]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp23 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp23 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp23 += ONE << (CONST_BITS-PASS1_BITS-1); - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ - tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ - tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ - tmp10 = z1 + z3; - z2 -= tmp10; - tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ - tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ - tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ - tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - - tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ - tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ - tmp10 = tmp11 - tmp12; - tmp11 += tmp12; - tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ - tmp11 += tmp12; - z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ - tmp10 += z2; - tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp23, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 7 rows from work array, store into output array. - * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 7; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z1 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z1 <<= CONST_BITS; - z4 = (INT32) wsptr[4]; - z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ - z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ - z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ - - tmp10 = z1 + z2; - tmp11 = z1 + z3; - tmp12 = z1 - z4; - - tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ - - z1 = (INT32) wsptr[2]; - z2 = (INT32) wsptr[6]; - - z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ - - tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ - tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ - tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ - MULTIPLY(z2, FIX(1.378756276)); /* c2 */ - - tmp20 = tmp10 + tmp13; - tmp26 = tmp10 - tmp13; - tmp21 = tmp11 + tmp14; - tmp25 = tmp11 - tmp14; - tmp22 = tmp12 + tmp15; - tmp24 = tmp12 - tmp15; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - z4 <<= CONST_BITS; - - tmp14 = z1 + z3; - tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ - tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ - tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ - tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ - tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ - z1 -= z2; - tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ - tmp16 += tmp15; - tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ - tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ - tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ - tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ - tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ - tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ - - tmp13 = ((z1 - z3) << CONST_BITS) + z4; - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 12x6 output block. - * - * 6-point IDCT in pass 1 (columns), 12-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*6]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp10 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp12 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ - tmp11 = tmp10 + tmp20; - tmp21 = RIGHT_SHIFT(tmp10 - tmp20 - tmp20, CONST_BITS-PASS1_BITS); - tmp20 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ - tmp20 = tmp11 + tmp10; - tmp22 = tmp11 - tmp10; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ - tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); - tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); - tmp11 = (z1 - z2 - z3) << PASS1_BITS; - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) (tmp21 + tmp11); - wsptr[8*4] = (int) (tmp21 - tmp11); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 6 rows from work array, store into output array. - * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 6; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z3 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z3 <<= CONST_BITS; - - z4 = (INT32) wsptr[4]; - z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ - - tmp10 = z3 + z4; - tmp11 = z3 - z4; - - z1 = (INT32) wsptr[2]; - z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ - z1 <<= CONST_BITS; - z2 = (INT32) wsptr[6]; - z2 <<= CONST_BITS; - - tmp12 = z1 - z2; - - tmp21 = z3 + tmp12; - tmp24 = z3 - tmp12; - - tmp12 = z4 + z2; - - tmp20 = tmp10 + tmp12; - tmp25 = tmp10 - tmp12; - - tmp12 = z4 - z1 - z2; - - tmp22 = tmp11 + tmp12; - tmp23 = tmp11 - tmp12; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z4 = (INT32) wsptr[7]; - - tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ - tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ - - tmp10 = z1 + z3; - tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ - tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ - tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ - tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ - tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ - tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ - tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ - MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ - - z1 -= z4; - z2 -= z3; - z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ - tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ - tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 10x5 output block. - * - * 5-point IDCT in pass 1 (columns), 10-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*5]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp12 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp13 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp14 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ - z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ - z3 = tmp12 + z2; - tmp10 = z3 + z1; - tmp11 = z3 - z1; - tmp12 -= z2 << 2; - - /* Odd part */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - - z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ - tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ - tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp10 - tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp11 - tmp14, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 5 rows from work array, store into output array. - * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 5; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z3 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z3 <<= CONST_BITS; - z4 = (INT32) wsptr[4]; - z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ - z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ - tmp10 = z3 + z1; - tmp11 = z3 - z2; - - tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ - tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ - tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ - - tmp20 = tmp10 + tmp12; - tmp24 = tmp10 - tmp12; - tmp21 = tmp11 + tmp13; - tmp23 = tmp11 - tmp13; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - z3 <<= CONST_BITS; - z4 = (INT32) wsptr[7]; - - tmp11 = z2 + z4; - tmp13 = z2 - z4; - - tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ - - z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ - z4 = z3 + tmp12; - - tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ - tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ - - z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ - z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); - - tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; - - tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ - tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 8; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 8x4 output block. - * - * 4-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*4]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 4-point IDCT kernel, - * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - - tmp10 = (tmp0 + tmp2) << PASS1_BITS; - tmp12 = (tmp0 - tmp2) << PASS1_BITS; - - /* Odd part */ - /* Same rotation as in the even part of the 8x8 LL&M IDCT */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - /* Add fudge factor here for final descale. */ - z1 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ - CONST_BITS-PASS1_BITS); - tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ - CONST_BITS-PASS1_BITS); - - /* Final output stage */ - - wsptr[8*0] = (int) (tmp10 + tmp0); - wsptr[8*3] = (int) (tmp10 - tmp0); - wsptr[8*1] = (int) (tmp12 + tmp2); - wsptr[8*2] = (int) (tmp12 - tmp2); - } - - /* Pass 2: process rows from work array, store into output array. - * Note that we must descale the results by a factor of 8 == 2**3, - * and also undo the PASS1_BITS scaling. - * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part: reverse the even part of the forward DCT. - * The rotator is c(-6). - */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z2 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z3 = (INT32) wsptr[4]; - - tmp0 = (z2 + z3) << CONST_BITS; - tmp1 = (z2 - z3) << CONST_BITS; - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - tmp10 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - tmp11 = tmp1 + tmp3; - tmp12 = tmp1 - tmp3; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = (INT32) wsptr[7]; - tmp1 = (INT32) wsptr[5]; - tmp2 = (INT32) wsptr[3]; - tmp3 = (INT32) wsptr[1]; - - z2 = tmp0 + tmp2; - z3 = tmp1 + tmp3; - - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ - z2 += z1; - z3 += z1; - - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp0 += z1 + z2; - tmp3 += z1 + z3; - - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp1 += z1 + z3; - tmp2 += z1 + z2; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 6x3 output block. - * - * 3-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[6*3]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ - tmp10 = tmp0 + tmp12; - tmp2 = tmp0 - tmp12 - tmp12; - - /* Odd part */ - - tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ - - /* Final output stage */ - - wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[6*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[6*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 3 rows from work array, store into output array. - * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 3; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp0 <<= CONST_BITS; - tmp2 = (INT32) wsptr[4]; - tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ - tmp1 = tmp0 + tmp10; - tmp11 = tmp0 - tmp10 - tmp10; - tmp10 = (INT32) wsptr[2]; - tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ - tmp10 = tmp1 + tmp0; - tmp12 = tmp1 - tmp0; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ - tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); - tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); - tmp1 = (z1 - z2 - z3) << CONST_BITS; - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 6; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 4x2 output block. - * - * 2-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp2, tmp10, tmp12; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - INT32 * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - INT32 workspace[4*2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - - /* Odd part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - /* Final output stage */ - - wsptr[4*0] = tmp10 + tmp0; - wsptr[4*1] = tmp10 - tmp0; - } - - /* Pass 2: process 2 rows from work array, store into output array. - * 4-point IDCT kernel, - * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. - */ - - wsptr = workspace; - for (ctr = 0; ctr < 2; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = wsptr[0] + ((((INT32) RANGE_CENTER) << 3) + (ONE << 2)); - tmp2 = wsptr[2]; - - tmp10 = (tmp0 + tmp2) << CONST_BITS; - tmp12 = (tmp0 - tmp2) << CONST_BITS; - - /* Odd part */ - /* Same rotation as in the even part of the 8x8 LL&M IDCT */ - - z2 = wsptr[1]; - z3 = wsptr[3]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+3) - & RANGE_MASK]; - - wsptr += 4; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 2x1 output block. - * - * 1-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - DCTELEM tmp0, tmp1; - ISLOW_MULT_TYPE * quantptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - ISHIFT_TEMPS - - /* Pass 1: empty. */ - - /* Pass 2: process 1 row from input, store into output array. */ - - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - outptr = output_buf[0] + output_col; - - /* Even part */ - - tmp0 = DEQUANTIZE(coef_block[0], quantptr[0]); - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); - - /* Odd part */ - - tmp1 = DEQUANTIZE(coef_block[1], quantptr[1]); - - /* Final output stage */ - - outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; - outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 8x16 output block. - * - * 16-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[8*16]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); - - z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ - tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ - - tmp10 = tmp0 + tmp1; - tmp11 = tmp0 - tmp1; - tmp12 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z3 = z1 - z2; - z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ - z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ - - tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ - tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ - tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ - tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ - - tmp20 = tmp10 + tmp0; - tmp27 = tmp10 - tmp0; - tmp21 = tmp12 + tmp1; - tmp26 = tmp12 - tmp1; - tmp22 = tmp13 + tmp2; - tmp25 = tmp13 - tmp2; - tmp23 = tmp11 + tmp3; - tmp24 = tmp11 - tmp3; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp11 = z1 + z3; - - tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ - tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ - tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ - tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ - tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ - tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ - tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ - tmp13 = tmp10 + tmp11 + tmp12 - - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ - z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ - tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ - tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ - z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ - tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ - tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ - z2 += z4; - z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ - tmp1 += z1; - tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ - z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ - tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ - tmp12 += z2; - z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ - tmp2 += z2; - tmp3 += z2; - z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ - tmp10 += z2; - tmp11 += z2; - - /* Final output stage */ - - wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process rows from work array, store into output array. - * Note that we must descale the results by a factor of 8 == 2**3, - * and also undo the PASS1_BITS scaling. - * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 16; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part: reverse the even part of the forward DCT. - * The rotator is c(-6). - */ - - /* Add range center and fudge factor for final descale and range-limit. */ - z2 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - z3 = (INT32) wsptr[4]; - - tmp0 = (z2 + z3) << CONST_BITS; - tmp1 = (z2 - z3) << CONST_BITS; - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - tmp10 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - tmp11 = tmp1 + tmp3; - tmp12 = tmp1 - tmp3; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = (INT32) wsptr[7]; - tmp1 = (INT32) wsptr[5]; - tmp2 = (INT32) wsptr[3]; - tmp3 = (INT32) wsptr[1]; - - z2 = tmp0 + tmp2; - z3 = tmp1 + tmp3; - - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ - z2 += z1; - z3 += z1; - - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp0 += z1 + z2; - tmp3 += z1 + z3; - - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp1 += z1 + z3; - tmp2 += z1 + z2; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 7x14 output block. - * - * 14-point IDCT in pass 1 (columns), 7-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[7*14]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z1 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z1 += ONE << (CONST_BITS-PASS1_BITS-1); - z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ - z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ - z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ - - tmp10 = z1 + z2; - tmp11 = z1 + z3; - tmp12 = z1 - z4; - - tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ - CONST_BITS-PASS1_BITS); - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ - - tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ - tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ - tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ - MULTIPLY(z2, FIX(1.378756276)); /* c2 */ - - tmp20 = tmp10 + tmp13; - tmp26 = tmp10 - tmp13; - tmp21 = tmp11 + tmp14; - tmp25 = tmp11 - tmp14; - tmp22 = tmp12 + tmp15; - tmp24 = tmp12 - tmp15; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp13 = z4 << CONST_BITS; - - tmp14 = z1 + z3; - tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ - tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ - tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ - tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ - tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ - z1 -= z2; - tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ - tmp16 += tmp15; - z1 += z4; - z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ - tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ - tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ - z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ - tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ - tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ - - tmp13 = (z1 - z3) << PASS1_BITS; - - /* Final output stage */ - - wsptr[7*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[7*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[7*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[7*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[7*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[7*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[7*3] = (int) (tmp23 + tmp13); - wsptr[7*10] = (int) (tmp23 - tmp13); - wsptr[7*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[7*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - wsptr[7*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); - wsptr[7*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); - wsptr[7*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); - wsptr[7*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 14 rows from work array, store into output array. - * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 14; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp23 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp23 <<= CONST_BITS; - - z1 = (INT32) wsptr[2]; - z2 = (INT32) wsptr[4]; - z3 = (INT32) wsptr[6]; - - tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ - tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ - tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ - tmp10 = z1 + z3; - z2 -= tmp10; - tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ - tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ - tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ - tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - - tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ - tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ - tmp10 = tmp11 - tmp12; - tmp11 += tmp12; - tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ - tmp11 += tmp12; - z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ - tmp10 += z2; - tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 7; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 6x12 output block. - * - * 12-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[6*12]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z3 += ONE << (CONST_BITS-PASS1_BITS-1); - - z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ - - tmp10 = z3 + z4; - tmp11 = z3 - z4; - - z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ - z1 <<= CONST_BITS; - z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z2 <<= CONST_BITS; - - tmp12 = z1 - z2; - - tmp21 = z3 + tmp12; - tmp24 = z3 - tmp12; - - tmp12 = z4 + z2; - - tmp20 = tmp10 + tmp12; - tmp25 = tmp10 - tmp12; - - tmp12 = z4 - z1 - z2; - - tmp22 = tmp11 + tmp12; - tmp23 = tmp11 - tmp12; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ - tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ - - tmp10 = z1 + z3; - tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ - tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ - tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ - tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ - tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ - tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ - tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ - MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ - - z1 -= z4; - z2 -= z3; - z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ - tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ - tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ - - /* Final output stage */ - - wsptr[6*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[6*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[6*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[6*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[6*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); - wsptr[6*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); - wsptr[6*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[6*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); - wsptr[6*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[6*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - wsptr[6*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); - wsptr[6*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 12 rows from work array, store into output array. - * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 12; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp10 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp10 <<= CONST_BITS; - tmp12 = (INT32) wsptr[4]; - tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ - tmp11 = tmp10 + tmp20; - tmp21 = tmp10 - tmp20 - tmp20; - tmp20 = (INT32) wsptr[2]; - tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ - tmp20 = tmp11 + tmp10; - tmp22 = tmp11 - tmp10; - - /* Odd part */ - - z1 = (INT32) wsptr[1]; - z2 = (INT32) wsptr[3]; - z3 = (INT32) wsptr[5]; - tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ - tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); - tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); - tmp11 = (z1 - z2 - z3) << CONST_BITS; - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 6; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 5x10 output block. - * - * 10-point IDCT in pass 1 (columns), 5-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp10, tmp11, tmp12, tmp13, tmp14; - INT32 tmp20, tmp21, tmp22, tmp23, tmp24; - INT32 z1, z2, z3, z4, z5; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[5*10]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z3 += ONE << (CONST_BITS-PASS1_BITS-1); - z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ - z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ - tmp10 = z3 + z1; - tmp11 = z3 - z2; - - tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ - CONST_BITS-PASS1_BITS); - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ - tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ - tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ - - tmp20 = tmp10 + tmp12; - tmp24 = tmp10 - tmp12; - tmp21 = tmp11 + tmp13; - tmp23 = tmp11 - tmp13; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - tmp11 = z2 + z4; - tmp13 = z2 - z4; - - tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ - z5 = z3 << CONST_BITS; - - z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ - z4 = z5 + tmp12; - - tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ - tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ - - z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ - z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); - - tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; - - tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ - tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ - - /* Final output stage */ - - wsptr[5*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); - wsptr[5*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); - wsptr[5*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); - wsptr[5*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); - wsptr[5*2] = (int) (tmp22 + tmp12); - wsptr[5*7] = (int) (tmp22 - tmp12); - wsptr[5*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); - wsptr[5*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); - wsptr[5*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); - wsptr[5*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 10 rows from work array, store into output array. - * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 10; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp12 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp12 <<= CONST_BITS; - tmp13 = (INT32) wsptr[2]; - tmp14 = (INT32) wsptr[4]; - z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ - z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ - z3 = tmp12 + z2; - tmp10 = z3 + z1; - tmp11 = z3 - z1; - tmp12 -= z2 << 2; - - /* Odd part */ - - z2 = (INT32) wsptr[1]; - z3 = (INT32) wsptr[3]; - - z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ - tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ - tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 5; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 4x8 output block. - * - * 8-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[4*8]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * Note results are scaled up by sqrt(8) compared to a true IDCT; - * furthermore, we scale the results by 2**PASS1_BITS. - * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 4; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[4*0] = dcval; - wsptr[4*1] = dcval; - wsptr[4*2] = dcval; - wsptr[4*3] = dcval; - wsptr[4*4] = dcval; - wsptr[4*5] = dcval; - wsptr[4*6] = dcval; - wsptr[4*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part: reverse the even part of the forward DCT. - * The rotator is c(-6). - */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z2 <<= CONST_BITS; - z3 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - z2 += ONE << (CONST_BITS-PASS1_BITS-1); - - tmp0 = z2 + z3; - tmp1 = z2 - z3; - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - tmp10 = tmp0 + tmp2; - tmp13 = tmp0 - tmp2; - tmp11 = tmp1 + tmp3; - tmp12 = tmp1 - tmp3; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - z2 = tmp0 + tmp2; - z3 = tmp1 + tmp3; - - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ - z2 += z1; - z3 += z1; - - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp0 += z1 + z2; - tmp3 += z1 + z3; - - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp1 += z1 + z3; - tmp2 += z1 + z2; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - wsptr[4*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[4*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[4*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[4*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[4*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[4*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[4*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[4*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process 8 rows from work array, store into output array. - * 4-point IDCT kernel, - * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. - */ - - wsptr = workspace; - for (ctr = 0; ctr < 8; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp2 = (INT32) wsptr[2]; - - tmp10 = (tmp0 + tmp2) << CONST_BITS; - tmp12 = (tmp0 - tmp2) << CONST_BITS; - - /* Odd part */ - /* Same rotation as in the even part of the 8x8 LL&M IDCT */ - - z2 = (INT32) wsptr[1]; - z3 = (INT32) wsptr[3]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 4; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 3x6 output block. - * - * 6-point IDCT in pass 1 (columns), 3-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[3*6]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= CONST_BITS; - /* Add fudge factor here for final descale. */ - tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ - tmp1 = tmp0 + tmp10; - tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); - tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ - tmp10 = tmp1 + tmp0; - tmp12 = tmp1 - tmp0; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ - tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); - tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); - tmp1 = (z1 - z2 - z3) << PASS1_BITS; - - /* Final output stage */ - - wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[3*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); - wsptr[3*1] = (int) (tmp11 + tmp1); - wsptr[3*4] = (int) (tmp11 - tmp1); - wsptr[3*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[3*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); - } - - /* Pass 2: process 6 rows from work array, store into output array. - * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). - */ - - wsptr = workspace; - for (ctr = 0; ctr < 6; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 = (INT32) wsptr[0] + - ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + - (ONE << (PASS1_BITS+2))); - tmp0 <<= CONST_BITS; - tmp2 = (INT32) wsptr[2]; - tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ - tmp10 = tmp0 + tmp12; - tmp2 = tmp0 - tmp12 - tmp12; - - /* Odd part */ - - tmp12 = (INT32) wsptr[1]; - tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += 3; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 2x4 output block. - * - * 4-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp2, tmp10, tmp12; - INT32 z1, z2, z3; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - INT32 * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - INT32 workspace[2*4]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. - * 4-point IDCT kernel, - * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. - */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = 0; ctr < 2; ctr++, inptr++, quantptr++, wsptr++) { - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - - tmp10 = (tmp0 + tmp2) << CONST_BITS; - tmp12 = (tmp0 - tmp2) << CONST_BITS; - - /* Odd part */ - /* Same rotation as in the even part of the 8x8 LL&M IDCT */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ - tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ - tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - - /* Final output stage */ - - wsptr[2*0] = tmp10 + tmp0; - wsptr[2*3] = tmp10 - tmp0; - wsptr[2*1] = tmp12 + tmp2; - wsptr[2*2] = tmp12 - tmp2; - } - - /* Pass 2: process 4 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++) { - outptr = output_buf[ctr] + output_col; - - /* Even part */ - - /* Add range center and fudge factor for final descale and range-limit. */ - tmp10 = wsptr[0] + - ((((INT32) RANGE_CENTER) << (CONST_BITS+3)) + - (ONE << (CONST_BITS+2))); - - /* Odd part */ - - tmp0 = wsptr[1]; - - /* Final output stage */ - - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+3) - & RANGE_MASK]; - - wsptr += 2; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a 1x2 output block. - * - * 2-point IDCT in pass 1 (columns), 1-point in pass 2 (rows). - */ - -GLOBAL(void) -jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - DCTELEM tmp0, tmp1; - ISLOW_MULT_TYPE * quantptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - ISHIFT_TEMPS - - /* Process 1 column from input, store into output array. */ - - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - - /* Even part */ - - tmp0 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); - /* Add range center and fudge factor for final descale and range-limit. */ - tmp0 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); - - /* Odd part */ - - tmp1 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); - - /* Final output stage */ - - output_buf[0][output_col] = - range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; - output_buf[1][output_col] = - range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; -} - -#endif /* IDCT_SCALING_SUPPORTED */ -#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/libraries/jpeg/jinclude.h b/libraries/jpeg/jinclude.h deleted file mode 100644 index 20ed4ef11f..0000000000 --- a/libraries/jpeg/jinclude.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * jinclude.h - * - * Copyright (C) 1991-1994, Thomas G. Lane. - * Modified 2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file exists to provide a single place to fix any problems with - * including the wrong system include files. (Common problems are taken - * care of by the standard jconfig symbols, but on really weird systems - * you may have to edit this file.) - * - * NOTE: this file is NOT intended to be included by applications using the - * JPEG library. Most applications need only include jpeglib.h. - */ - - -/* Include auto-config file to find out which system include files we need. */ - -#include "jconfig.h" /* auto configuration options */ -#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ - -/* - * We need the NULL macro and size_t typedef. - * On an ANSI-conforming system it is sufficient to include . - * Otherwise, we get them from or ; we may have to - * pull in as well. - * Note that the core JPEG library does not require ; - * only the default error handler and data source/destination modules do. - * But we must pull it in because of the references to FILE in jpeglib.h. - * You can remove those references if you want to compile without . - */ - -#ifdef HAVE_STDDEF_H -#include -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef NEED_SYS_TYPES_H -#include -#endif - -#include - -/* - * We need memory copying and zeroing functions, plus strncpy(). - * ANSI and System V implementations declare these in . - * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). - * Some systems may declare memset and memcpy in . - * - * NOTE: we assume the size parameters to these functions are of type size_t. - * Change the casts in these macros if not! - */ - -#ifdef NEED_BSD_STRINGS - -#include -#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) -#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) - -#else /* not BSD, assume ANSI/SysV string lib */ - -#include -#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) -#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) - -#endif - -/* - * In ANSI C, and indeed any rational implementation, size_t is also the - * type returned by sizeof(). However, it seems there are some irrational - * implementations out there, in which sizeof() returns an int even though - * size_t is defined as long or unsigned long. To ensure consistent results - * we always use this SIZEOF() macro in place of using sizeof() directly. - */ - -#define SIZEOF(object) ((size_t) sizeof(object)) - -/* - * The modules that use fread() and fwrite() always invoke them through - * these macros. On some systems you may need to twiddle the argument casts. - * CAUTION: argument order is different from underlying functions! - * - * Furthermore, macros are provided for fflush() and ferror() in order - * to facilitate adaption by applications using an own FILE class. - */ - -#define JFREAD(file,buf,sizeofbuf) \ - ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) -#define JFWRITE(file,buf,sizeofbuf) \ - ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) -#define JFFLUSH(file) fflush(file) -#define JFERROR(file) ferror(file) diff --git a/libraries/jpeg/jmemansi.c b/libraries/jpeg/jmemansi.c deleted file mode 100644 index 2d93e49625..0000000000 --- a/libraries/jpeg/jmemansi.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * jmemansi.c - * - * Copyright (C) 1992-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides a simple generic implementation of the system- - * dependent portion of the JPEG memory manager. This implementation - * assumes that you have the ANSI-standard library routine tmpfile(). - * Also, the problem of determining the amount of memory available - * is shoved onto the user. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jmemsys.h" /* import the system-dependent declarations */ - -#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ -extern void * malloc JPP((size_t size)); -extern void free JPP((void *ptr)); -#endif - -#ifndef SEEK_SET /* pre-ANSI systems may not define this; */ -#define SEEK_SET 0 /* if not, assume 0 is correct */ -#endif - - -/* - * Memory allocation and freeing are controlled by the regular library - * routines malloc() and free(). - */ - -GLOBAL(void *) -jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) -{ - return (void *) malloc(sizeofobject); -} - -GLOBAL(void) -jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) -{ - free(object); -} - - -/* - * "Large" objects are treated the same as "small" ones. - * NB: although we include FAR keywords in the routine declarations, - * this file won't actually work in 80x86 small/medium model; at least, - * you probably won't be able to process useful-size images in only 64KB. - */ - -GLOBAL(void FAR *) -jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) -{ - return (void FAR *) malloc(sizeofobject); -} - -GLOBAL(void) -jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) -{ - free(object); -} - - -/* - * This routine computes the total memory space available for allocation. - * It's impossible to do this in a portable way; our current solution is - * to make the user tell us (with a default value set at compile time). - * If you can actually get the available space, it's a good idea to subtract - * a slop factor of 5% or so. - */ - -#ifndef DEFAULT_MAX_MEM /* so can override from makefile */ -#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ -#endif - -GLOBAL(long) -jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, - long max_bytes_needed, long already_allocated) -{ - return cinfo->mem->max_memory_to_use - already_allocated; -} - - -/* - * Backing store (temporary file) management. - * Backing store objects are only used when the value returned by - * jpeg_mem_available is less than the total space needed. You can dispense - * with these routines if you have plenty of virtual memory; see jmemnobs.c. - */ - - -METHODDEF(void) -read_backing_store (j_common_ptr cinfo, backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count) -{ - if (fseek(info->temp_file, file_offset, SEEK_SET)) - ERREXIT(cinfo, JERR_TFILE_SEEK); - if (JFREAD(info->temp_file, buffer_address, byte_count) - != (size_t) byte_count) - ERREXIT(cinfo, JERR_TFILE_READ); -} - - -METHODDEF(void) -write_backing_store (j_common_ptr cinfo, backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count) -{ - if (fseek(info->temp_file, file_offset, SEEK_SET)) - ERREXIT(cinfo, JERR_TFILE_SEEK); - if (JFWRITE(info->temp_file, buffer_address, byte_count) - != (size_t) byte_count) - ERREXIT(cinfo, JERR_TFILE_WRITE); -} - - -METHODDEF(void) -close_backing_store (j_common_ptr cinfo, backing_store_ptr info) -{ - fclose(info->temp_file); - /* Since this implementation uses tmpfile() to create the file, - * no explicit file deletion is needed. - */ -} - - -/* - * Initial opening of a backing-store object. - * - * This version uses tmpfile(), which constructs a suitable file name - * behind the scenes. We don't have to use info->temp_name[] at all; - * indeed, we can't even find out the actual name of the temp file. - */ - -GLOBAL(void) -jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, - long total_bytes_needed) -{ - if ((info->temp_file = tmpfile()) == NULL) - ERREXITS(cinfo, JERR_TFILE_CREATE, ""); - info->read_backing_store = read_backing_store; - info->write_backing_store = write_backing_store; - info->close_backing_store = close_backing_store; -} - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. - */ - -GLOBAL(long) -jpeg_mem_init (j_common_ptr cinfo) -{ - return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ -} - -GLOBAL(void) -jpeg_mem_term (j_common_ptr cinfo) -{ - /* no work */ -} diff --git a/libraries/jpeg/jmemmgr.c b/libraries/jpeg/jmemmgr.c deleted file mode 100644 index 0a137cdde4..0000000000 --- a/libraries/jpeg/jmemmgr.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * jmemmgr.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2011-2012 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the JPEG system-independent memory management - * routines. This code is usable across a wide variety of machines; most - * of the system dependencies have been isolated in a separate file. - * The major functions provided here are: - * * pool-based allocation and freeing of memory; - * * policy decisions about how to divide available memory among the - * virtual arrays; - * * control logic for swapping virtual arrays between main memory and - * backing storage. - * The separate system-dependent file provides the actual backing-storage - * access code, and it contains the policy decision about how much total - * main memory to use. - * This file is system-dependent in the sense that some of its functions - * are unnecessary in some systems. For example, if there is enough virtual - * memory so that backing storage will never be used, much of the virtual - * array control logic could be removed. (Of course, if you have that much - * memory then you shouldn't care about a little bit of unused code...) - */ - -#define JPEG_INTERNALS -#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jmemsys.h" /* import the system-dependent declarations */ - -#ifndef NO_GETENV -#ifndef HAVE_STDLIB_H /* should declare getenv() */ -extern char * getenv JPP((const char * name)); -#endif -#endif - - -/* - * Some important notes: - * The allocation routines provided here must never return NULL. - * They should exit to error_exit if unsuccessful. - * - * It's not a good idea to try to merge the sarray and barray routines, - * even though they are textually almost the same, because samples are - * usually stored as bytes while coefficients are shorts or ints. Thus, - * in machines where byte pointers have a different representation from - * word pointers, the resulting machine code could not be the same. - */ - - -/* - * Many machines require storage alignment: longs must start on 4-byte - * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() - * always returns pointers that are multiples of the worst-case alignment - * requirement, and we had better do so too. - * There isn't any really portable way to determine the worst-case alignment - * requirement. This module assumes that the alignment requirement is - * multiples of sizeof(ALIGN_TYPE). - * By default, we define ALIGN_TYPE as double. This is necessary on some - * workstations (where doubles really do need 8-byte alignment) and will work - * fine on nearly everything. If your machine has lesser alignment needs, - * you can save a few bytes by making ALIGN_TYPE smaller. - * The only place I know of where this will NOT work is certain Macintosh - * 680x0 compilers that define double as a 10-byte IEEE extended float. - * Doing 10-byte alignment is counterproductive because longwords won't be - * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have - * such a compiler. - */ - -#ifndef ALIGN_TYPE /* so can override from jconfig.h */ -#define ALIGN_TYPE double -#endif - - -/* - * We allocate objects from "pools", where each pool is gotten with a single - * request to jpeg_get_small() or jpeg_get_large(). There is no per-object - * overhead within a pool, except for alignment padding. Each pool has a - * header with a link to the next pool of the same class. - * Small and large pool headers are identical except that the latter's - * link pointer must be FAR on 80x86 machines. - * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE - * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple - * of the alignment requirement of ALIGN_TYPE. - */ - -typedef union small_pool_struct * small_pool_ptr; - -typedef union small_pool_struct { - struct { - small_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ - } hdr; - ALIGN_TYPE dummy; /* included in union to ensure alignment */ -} small_pool_hdr; - -typedef union large_pool_struct FAR * large_pool_ptr; - -typedef union large_pool_struct { - struct { - large_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ - } hdr; - ALIGN_TYPE dummy; /* included in union to ensure alignment */ -} large_pool_hdr; - - -/* - * Here is the full definition of a memory manager object. - */ - -typedef struct { - struct jpeg_memory_mgr pub; /* public fields */ - - /* Each pool identifier (lifetime class) names a linked list of pools. */ - small_pool_ptr small_list[JPOOL_NUMPOOLS]; - large_pool_ptr large_list[JPOOL_NUMPOOLS]; - - /* Since we only have one lifetime class of virtual arrays, only one - * linked list is necessary (for each datatype). Note that the virtual - * array control blocks being linked together are actually stored somewhere - * in the small-pool list. - */ - jvirt_sarray_ptr virt_sarray_list; - jvirt_barray_ptr virt_barray_list; - - /* This counts total space obtained from jpeg_get_small/large */ - long total_space_allocated; - - /* alloc_sarray and alloc_barray set this value for use by virtual - * array routines. - */ - JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ -} my_memory_mgr; - -typedef my_memory_mgr * my_mem_ptr; - - -/* - * The control blocks for virtual arrays. - * Note that these blocks are allocated in the "small" pool area. - * System-dependent info for the associated backing store (if any) is hidden - * inside the backing_store_info struct. - */ - -struct jvirt_sarray_control { - JSAMPARRAY mem_buffer; /* => the in-memory buffer */ - JDIMENSION rows_in_array; /* total virtual array height */ - JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ - JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ - JDIMENSION rows_in_mem; /* height of memory buffer */ - JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ - JDIMENSION cur_start_row; /* first logical row # in the buffer */ - JDIMENSION first_undef_row; /* row # of first uninitialized row */ - boolean pre_zero; /* pre-zero mode requested? */ - boolean dirty; /* do current buffer contents need written? */ - boolean b_s_open; /* is backing-store data valid? */ - jvirt_sarray_ptr next; /* link to next virtual sarray control block */ - backing_store_info b_s_info; /* System-dependent control info */ -}; - -struct jvirt_barray_control { - JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ - JDIMENSION rows_in_array; /* total virtual array height */ - JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ - JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ - JDIMENSION rows_in_mem; /* height of memory buffer */ - JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ - JDIMENSION cur_start_row; /* first logical row # in the buffer */ - JDIMENSION first_undef_row; /* row # of first uninitialized row */ - boolean pre_zero; /* pre-zero mode requested? */ - boolean dirty; /* do current buffer contents need written? */ - boolean b_s_open; /* is backing-store data valid? */ - jvirt_barray_ptr next; /* link to next virtual barray control block */ - backing_store_info b_s_info; /* System-dependent control info */ -}; - - -#ifdef MEM_STATS /* optional extra stuff for statistics */ - -LOCAL(void) -print_mem_stats (j_common_ptr cinfo, int pool_id) -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr shdr_ptr; - large_pool_ptr lhdr_ptr; - - /* Since this is only a debugging stub, we can cheat a little by using - * fprintf directly rather than going through the trace message code. - * This is helpful because message parm array can't handle longs. - */ - fprintf(stderr, "Freeing pool %d, total space = %ld\n", - pool_id, mem->total_space_allocated); - - for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; - lhdr_ptr = lhdr_ptr->hdr.next) { - fprintf(stderr, " Large chunk used %ld\n", - (long) lhdr_ptr->hdr.bytes_used); - } - - for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; - shdr_ptr = shdr_ptr->hdr.next) { - fprintf(stderr, " Small chunk used %ld free %ld\n", - (long) shdr_ptr->hdr.bytes_used, - (long) shdr_ptr->hdr.bytes_left); - } -} - -#endif /* MEM_STATS */ - - -LOCAL(noreturn_t) -out_of_memory (j_common_ptr cinfo, int which) -/* Report an out-of-memory error and stop execution */ -/* If we compiled MEM_STATS support, report alloc requests before dying */ -{ -#ifdef MEM_STATS - cinfo->err->trace_level = 2; /* force self_destruct to report stats */ -#endif - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); -} - - -/* - * Allocation of "small" objects. - * - * For these, we use pooled storage. When a new pool must be created, - * we try to get enough space for the current request plus a "slop" factor, - * where the slop will be the amount of leftover space in the new pool. - * The speed vs. space tradeoff is largely determined by the slop values. - * A different slop value is provided for each pool class (lifetime), - * and we also distinguish the first pool of a class from later ones. - * NOTE: the values given work fairly well on both 16- and 32-bit-int - * machines, but may be too small if longs are 64 bits or more. - */ - -static const size_t first_pool_slop[JPOOL_NUMPOOLS] = -{ - 1600, /* first PERMANENT pool */ - 16000 /* first IMAGE pool */ -}; - -static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = -{ - 0, /* additional PERMANENT pools */ - 5000 /* additional IMAGE pools */ -}; - -#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ - - -METHODDEF(void *) -alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "small" object */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr hdr_ptr, prev_hdr_ptr; - char * data_ptr; - size_t odd_bytes, min_request, slop; - - /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) - out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ - - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ - odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); - if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - - /* See if space is available in any existing pool */ - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - prev_hdr_ptr = NULL; - hdr_ptr = mem->small_list[pool_id]; - while (hdr_ptr != NULL) { - if (hdr_ptr->hdr.bytes_left >= sizeofobject) - break; /* found pool with enough space */ - prev_hdr_ptr = hdr_ptr; - hdr_ptr = hdr_ptr->hdr.next; - } - - /* Time to make a new pool? */ - if (hdr_ptr == NULL) { - /* min_request is what we need now, slop is what will be leftover */ - min_request = sizeofobject + SIZEOF(small_pool_hdr); - if (prev_hdr_ptr == NULL) /* first pool in class? */ - slop = first_pool_slop[pool_id]; - else - slop = extra_pool_slop[pool_id]; - /* Don't ask for more than MAX_ALLOC_CHUNK */ - if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) - slop = (size_t) (MAX_ALLOC_CHUNK-min_request); - /* Try to get space, if fail reduce slop and try again */ - for (;;) { - hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); - if (hdr_ptr != NULL) - break; - slop /= 2; - if (slop < MIN_SLOP) /* give up when it gets real small */ - out_of_memory(cinfo, 2); /* jpeg_get_small failed */ - } - mem->total_space_allocated += min_request + slop; - /* Success, initialize the new pool header and add to end of list */ - hdr_ptr->hdr.next = NULL; - hdr_ptr->hdr.bytes_used = 0; - hdr_ptr->hdr.bytes_left = sizeofobject + slop; - if (prev_hdr_ptr == NULL) /* first pool in class? */ - mem->small_list[pool_id] = hdr_ptr; - else - prev_hdr_ptr->hdr.next = hdr_ptr; - } - - /* OK, allocate the object from the current pool */ - data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ - data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ - hdr_ptr->hdr.bytes_used += sizeofobject; - hdr_ptr->hdr.bytes_left -= sizeofobject; - - return (void *) data_ptr; -} - - -/* - * Allocation of "large" objects. - * - * The external semantics of these are the same as "small" objects, - * except that FAR pointers are used on 80x86. However the pool - * management heuristics are quite different. We assume that each - * request is large enough that it may as well be passed directly to - * jpeg_get_large; the pool management just links everything together - * so that we can free it all on demand. - * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY - * structures. The routines that create these structures (see below) - * deliberately bunch rows together to ensure a large request size. - */ - -METHODDEF(void FAR *) -alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "large" object */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - large_pool_ptr hdr_ptr; - size_t odd_bytes; - - /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) - out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ - - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ - odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); - if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - - /* Always make a new pool */ - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + - SIZEOF(large_pool_hdr)); - if (hdr_ptr == NULL) - out_of_memory(cinfo, 4); /* jpeg_get_large failed */ - mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); - - /* Success, initialize the new pool header and add to list */ - hdr_ptr->hdr.next = mem->large_list[pool_id]; - /* We maintain space counts in each pool header for statistical purposes, - * even though they are not needed for allocation. - */ - hdr_ptr->hdr.bytes_used = sizeofobject; - hdr_ptr->hdr.bytes_left = 0; - mem->large_list[pool_id] = hdr_ptr; - - return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ -} - - -/* - * Creation of 2-D sample arrays. - * The pointers are in near heap, the samples themselves in FAR heap. - * - * To minimize allocation overhead and to allow I/O of large contiguous - * blocks, we allocate the sample rows in groups of as many rows as possible - * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. - * NB: the virtual array control routines, later in this file, know about - * this chunking of rows. The rowsperchunk value is left in the mem manager - * object so that it can be saved away if this sarray is the workspace for - * a virtual array. - */ - -METHODDEF(JSAMPARRAY) -alloc_sarray (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, JDIMENSION numrows) -/* Allocate a 2-D sample array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JSAMPARRAY result; - JSAMPROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) samplesperrow * SIZEOF(JSAMPLE)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JSAMPARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JSAMPROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JSAMPROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow - * SIZEOF(JSAMPLE))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += samplesperrow; - } - } - - return result; -} - - -/* - * Creation of 2-D coefficient-block arrays. - * This is essentially the same as the code for sample arrays, above. - */ - -METHODDEF(JBLOCKARRAY) -alloc_barray (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, JDIMENSION numrows) -/* Allocate a 2-D coefficient-block array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JBLOCKARRAY result; - JBLOCKROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) blocksperrow * SIZEOF(JBLOCK)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JBLOCKROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow - * SIZEOF(JBLOCK))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += blocksperrow; - } - } - - return result; -} - - -/* - * About virtual array management: - * - * The above "normal" array routines are only used to allocate strip buffers - * (as wide as the image, but just a few rows high). Full-image-sized buffers - * are handled as "virtual" arrays. The array is still accessed a strip at a - * time, but the memory manager must save the whole array for repeated - * accesses. The intended implementation is that there is a strip buffer in - * memory (as high as is possible given the desired memory limit), plus a - * backing file that holds the rest of the array. - * - * The request_virt_array routines are told the total size of the image and - * the maximum number of rows that will be accessed at once. The in-memory - * buffer must be at least as large as the maxaccess value. - * - * The request routines create control blocks but not the in-memory buffers. - * That is postponed until realize_virt_arrays is called. At that time the - * total amount of space needed is known (approximately, anyway), so free - * memory can be divided up fairly. - * - * The access_virt_array routines are responsible for making a specific strip - * area accessible (after reading or writing the backing file, if necessary). - * Note that the access routines are told whether the caller intends to modify - * the accessed strip; during a read-only pass this saves having to rewrite - * data to disk. The access routines are also responsible for pre-zeroing - * any newly accessed rows, if pre-zeroing was requested. - * - * In current usage, the access requests are usually for nonoverlapping - * strips; that is, successive access start_row numbers differ by exactly - * num_rows = maxaccess. This means we can get good performance with simple - * buffer dump/reload logic, by making the in-memory buffer be a multiple - * of the access height; then there will never be accesses across bufferload - * boundaries. The code will still work with overlapping access requests, - * but it doesn't handle bufferload overlaps very efficiently. - */ - - -METHODDEF(jvirt_sarray_ptr) -request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION samplesperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D sample array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - jvirt_sarray_ptr result; - - /* Only IMAGE-lifetime virtual arrays are currently supported */ - if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - /* get control block */ - result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_sarray_control)); - - result->mem_buffer = NULL; /* marks array not yet realized */ - result->rows_in_array = numrows; - result->samplesperrow = samplesperrow; - result->maxaccess = maxaccess; - result->pre_zero = pre_zero; - result->b_s_open = FALSE; /* no associated backing-store object */ - result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ - mem->virt_sarray_list = result; - - return result; -} - - -METHODDEF(jvirt_barray_ptr) -request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION blocksperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D coefficient-block array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - jvirt_barray_ptr result; - - /* Only IMAGE-lifetime virtual arrays are currently supported */ - if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - /* get control block */ - result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_barray_control)); - - result->mem_buffer = NULL; /* marks array not yet realized */ - result->rows_in_array = numrows; - result->blocksperrow = blocksperrow; - result->maxaccess = maxaccess; - result->pre_zero = pre_zero; - result->b_s_open = FALSE; /* no associated backing-store object */ - result->next = mem->virt_barray_list; /* add to list of virtual arrays */ - mem->virt_barray_list = result; - - return result; -} - - -METHODDEF(void) -realize_virt_arrays (j_common_ptr cinfo) -/* Allocate the in-memory buffers for any unrealized virtual arrays */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - long space_per_minheight, maximum_space, avail_mem; - long minheights, max_minheights; - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; - - /* Compute the minimum space needed (maxaccess rows in each buffer) - * and the maximum space needed (full image height in each buffer). - * These may be of use to the system-dependent jpeg_mem_available routine. - */ - space_per_minheight = 0; - maximum_space = 0; - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) sptr->maxaccess * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - maximum_space += (long) sptr->rows_in_array * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - } - } - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) bptr->maxaccess * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - maximum_space += (long) bptr->rows_in_array * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - } - } - - if (space_per_minheight <= 0) - return; /* no unrealized arrays, no work */ - - /* Determine amount of memory to actually use; this is system-dependent. */ - avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, - mem->total_space_allocated); - - /* If the maximum space needed is available, make all the buffers full - * height; otherwise parcel it out with the same number of minheights - * in each buffer. - */ - if (avail_mem >= maximum_space) - max_minheights = 1000000000L; - else { - max_minheights = avail_mem / space_per_minheight; - /* If there doesn't seem to be enough space, try to get the minimum - * anyway. This allows a "stub" implementation of jpeg_mem_available(). - */ - if (max_minheights <= 0) - max_minheights = 1; - } - - /* Allocate the in-memory buffers and initialize backing store as needed. */ - - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ - sptr->rows_in_mem = sptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ - sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); - jpeg_open_backing_store(cinfo, & sptr->b_s_info, - (long) sptr->rows_in_array * - (long) sptr->samplesperrow * - (long) SIZEOF(JSAMPLE)); - sptr->b_s_open = TRUE; - } - sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, - sptr->samplesperrow, sptr->rows_in_mem); - sptr->rowsperchunk = mem->last_rowsperchunk; - sptr->cur_start_row = 0; - sptr->first_undef_row = 0; - sptr->dirty = FALSE; - } - } - - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ - bptr->rows_in_mem = bptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ - bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); - jpeg_open_backing_store(cinfo, & bptr->b_s_info, - (long) bptr->rows_in_array * - (long) bptr->blocksperrow * - (long) SIZEOF(JBLOCK)); - bptr->b_s_open = TRUE; - } - bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, - bptr->blocksperrow, bptr->rows_in_mem); - bptr->rowsperchunk = mem->last_rowsperchunk; - bptr->cur_start_row = 0; - bptr->first_undef_row = 0; - bptr->dirty = FALSE; - } - } -} - - -LOCAL(void) -do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual sample array */ -{ - long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); - file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ - for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - file_offset += byte_count; - } -} - - -LOCAL(void) -do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual coefficient-block array */ -{ - long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); - file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ - for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - file_offset += byte_count; - } -} - - -METHODDEF(JSAMPARRAY) -access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual sample array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ -{ - JDIMENSION end_row = start_row + num_rows; - JDIMENSION undef_row; - - /* debugging check */ - if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_sarray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_sarray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { - FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } - } - /* Flag the buffer dirty if caller will write in it */ - if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ - return ptr->mem_buffer + (start_row - ptr->cur_start_row); -} - - -METHODDEF(JBLOCKARRAY) -access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual block array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ -{ - JDIMENSION end_row = start_row + num_rows; - JDIMENSION undef_row; - - /* debugging check */ - if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_barray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_barray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { - FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } - } - /* Flag the buffer dirty if caller will write in it */ - if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ - return ptr->mem_buffer + (start_row - ptr->cur_start_row); -} - - -/* - * Release all objects belonging to a specified pool. - */ - -METHODDEF(void) -free_pool (j_common_ptr cinfo, int pool_id) -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr shdr_ptr; - large_pool_ptr lhdr_ptr; - size_t space_freed; - - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - -#ifdef MEM_STATS - if (cinfo->err->trace_level > 1) - print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ -#endif - - /* If freeing IMAGE pool, close any virtual arrays first */ - if (pool_id == JPOOL_IMAGE) { - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; - - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->b_s_open) { /* there may be no backing store */ - sptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); - } - } - mem->virt_sarray_list = NULL; - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->b_s_open) { /* there may be no backing store */ - bptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); - } - } - mem->virt_barray_list = NULL; - } - - /* Release large objects */ - lhdr_ptr = mem->large_list[pool_id]; - mem->large_list[pool_id] = NULL; - - while (lhdr_ptr != NULL) { - large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; - space_freed = lhdr_ptr->hdr.bytes_used + - lhdr_ptr->hdr.bytes_left + - SIZEOF(large_pool_hdr); - jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - lhdr_ptr = next_lhdr_ptr; - } - - /* Release small objects */ - shdr_ptr = mem->small_list[pool_id]; - mem->small_list[pool_id] = NULL; - - while (shdr_ptr != NULL) { - small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; - space_freed = shdr_ptr->hdr.bytes_used + - shdr_ptr->hdr.bytes_left + - SIZEOF(small_pool_hdr); - jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - shdr_ptr = next_shdr_ptr; - } -} - - -/* - * Close up shop entirely. - * Note that this cannot be called unless cinfo->mem is non-NULL. - */ - -METHODDEF(void) -self_destruct (j_common_ptr cinfo) -{ - int pool; - - /* Close all backing store, release all memory. - * Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ - for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - free_pool(cinfo, pool); - } - - /* Release the memory manager control block too. */ - jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); - cinfo->mem = NULL; /* ensures I will be called only once */ - - jpeg_mem_term(cinfo); /* system-dependent cleanup */ -} - - -/* - * Memory manager initialization. - * When this is called, only the error manager pointer is valid in cinfo! - */ - -GLOBAL(void) -jinit_memory_mgr (j_common_ptr cinfo) -{ - my_mem_ptr mem; - long max_to_use; - int pool; - size_t test_mac; - - cinfo->mem = NULL; /* for safety if init fails */ - - /* Check for configuration errors. - * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably - * doesn't reflect any real hardware alignment requirement. - * The test is a little tricky: for X>0, X and X-1 have no one-bits - * in common if and only if X is a power of 2, ie has only one one-bit. - * Some compilers may give an "unreachable code" warning here; ignore it. - */ - if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) - ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); - /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be - * a multiple of SIZEOF(ALIGN_TYPE). - * Again, an "unreachable code" warning may be ignored here. - * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. - */ - test_mac = (size_t) MAX_ALLOC_CHUNK; - if ((long) test_mac != MAX_ALLOC_CHUNK || - (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) - ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); - - max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ - - /* Attempt to allocate memory manager's control block */ - mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); - - if (mem == NULL) { - jpeg_mem_term(cinfo); /* system-dependent cleanup */ - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); - } - - /* OK, fill in the method pointers */ - mem->pub.alloc_small = alloc_small; - mem->pub.alloc_large = alloc_large; - mem->pub.alloc_sarray = alloc_sarray; - mem->pub.alloc_barray = alloc_barray; - mem->pub.request_virt_sarray = request_virt_sarray; - mem->pub.request_virt_barray = request_virt_barray; - mem->pub.realize_virt_arrays = realize_virt_arrays; - mem->pub.access_virt_sarray = access_virt_sarray; - mem->pub.access_virt_barray = access_virt_barray; - mem->pub.free_pool = free_pool; - mem->pub.self_destruct = self_destruct; - - /* Make MAX_ALLOC_CHUNK accessible to other modules */ - mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; - - /* Initialize working state */ - mem->pub.max_memory_to_use = max_to_use; - - for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - mem->small_list[pool] = NULL; - mem->large_list[pool] = NULL; - } - mem->virt_sarray_list = NULL; - mem->virt_barray_list = NULL; - - mem->total_space_allocated = SIZEOF(my_memory_mgr); - - /* Declare ourselves open for business */ - cinfo->mem = & mem->pub; - - /* Check for an environment variable JPEGMEM; if found, override the - * default max_memory setting from jpeg_mem_init. Note that the - * surrounding application may again override this value. - * If your system doesn't support getenv(), define NO_GETENV to disable - * this feature. - */ -#ifndef NO_GETENV - { char * memenv; - - if ((memenv = getenv("JPEGMEM")) != NULL) { - char ch = 'x'; - - if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { - if (ch == 'm' || ch == 'M') - max_to_use *= 1000L; - mem->pub.max_memory_to_use = max_to_use * 1000L; - } - } - } -#endif - -} diff --git a/libraries/jpeg/jmemsys.h b/libraries/jpeg/jmemsys.h deleted file mode 100644 index 6c3c6d348f..0000000000 --- a/libraries/jpeg/jmemsys.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * jmemsys.h - * - * Copyright (C) 1992-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file defines the interface between the system-independent - * and system-dependent portions of the JPEG memory manager. No other - * modules need include it. (The system-independent portion is jmemmgr.c; - * there are several different versions of the system-dependent portion.) - * - * This file works as-is for the system-dependent memory managers supplied - * in the IJG distribution. You may need to modify it if you write a - * custom memory manager. If system-dependent changes are needed in - * this file, the best method is to #ifdef them based on a configuration - * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR - * and USE_MAC_MEMMGR. - */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_get_small jGetSmall -#define jpeg_free_small jFreeSmall -#define jpeg_get_large jGetLarge -#define jpeg_free_large jFreeLarge -#define jpeg_mem_available jMemAvail -#define jpeg_open_backing_store jOpenBackStore -#define jpeg_mem_init jMemInit -#define jpeg_mem_term jMemTerm -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * These two functions are used to allocate and release small chunks of - * memory. (Typically the total amount requested through jpeg_get_small is - * no more than 20K or so; this will be requested in chunks of a few K each.) - * Behavior should be the same as for the standard library functions malloc - * and free; in particular, jpeg_get_small must return NULL on failure. - * On most systems, these ARE malloc and free. jpeg_free_small is passed the - * size of the object being freed, just in case it's needed. - * On an 80x86 machine using small-data memory model, these manage near heap. - */ - -EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); -EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, - size_t sizeofobject)); - -/* - * These two functions are used to allocate and release large chunks of - * memory (up to the total free space designated by jpeg_mem_available). - * The interface is the same as above, except that on an 80x86 machine, - * far pointers are used. On most other machines these are identical to - * the jpeg_get/free_small routines; but we keep them separate anyway, - * in case a different allocation strategy is desirable for large chunks. - */ - -EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, - size_t sizeofobject)); -EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, - size_t sizeofobject)); - -/* - * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may - * be requested in a single call to jpeg_get_large (and jpeg_get_small for that - * matter, but that case should never come into play). This macro is needed - * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. - * On those machines, we expect that jconfig.h will provide a proper value. - * On machines with 32-bit flat address spaces, any large constant may be used. - * - * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type - * size_t and will be a multiple of sizeof(align_type). - */ - -#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ -#define MAX_ALLOC_CHUNK 1000000000L -#endif - -/* - * This routine computes the total space still available for allocation by - * jpeg_get_large. If more space than this is needed, backing store will be - * used. NOTE: any memory already allocated must not be counted. - * - * There is a minimum space requirement, corresponding to the minimum - * feasible buffer sizes; jmemmgr.c will request that much space even if - * jpeg_mem_available returns zero. The maximum space needed, enough to hold - * all working storage in memory, is also passed in case it is useful. - * Finally, the total space already allocated is passed. If no better - * method is available, cinfo->mem->max_memory_to_use - already_allocated - * is often a suitable calculation. - * - * It is OK for jpeg_mem_available to underestimate the space available - * (that'll just lead to more backing-store access than is really necessary). - * However, an overestimate will lead to failure. Hence it's wise to subtract - * a slop factor from the true available space. 5% should be enough. - * - * On machines with lots of virtual memory, any large constant may be returned. - * Conversely, zero may be returned to always use the minimum amount of memory. - */ - -EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, - long min_bytes_needed, - long max_bytes_needed, - long already_allocated)); - - -/* - * This structure holds whatever state is needed to access a single - * backing-store object. The read/write/close method pointers are called - * by jmemmgr.c to manipulate the backing-store object; all other fields - * are private to the system-dependent backing store routines. - */ - -#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ - - -#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ - -typedef unsigned short XMSH; /* type of extended-memory handles */ -typedef unsigned short EMSH; /* type of expanded-memory handles */ - -typedef union { - short file_handle; /* DOS file handle if it's a temp file */ - XMSH xms_handle; /* handle if it's a chunk of XMS */ - EMSH ems_handle; /* handle if it's a chunk of EMS */ -} handle_union; - -#endif /* USE_MSDOS_MEMMGR */ - -#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ -#include -#endif /* USE_MAC_MEMMGR */ - - -typedef struct backing_store_struct * backing_store_ptr; - -typedef struct backing_store_struct { - /* Methods for reading/writing/closing this backing-store object */ - JMETHOD(void, read_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, write_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, close_backing_store, (j_common_ptr cinfo, - backing_store_ptr info)); - - /* Private fields for system-dependent backing-store management */ -#ifdef USE_MSDOS_MEMMGR - /* For the MS-DOS manager (jmemdos.c), we need: */ - handle_union handle; /* reference to backing-store storage object */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else -#ifdef USE_MAC_MEMMGR - /* For the Mac manager (jmemmac.c), we need: */ - short temp_file; /* file reference number to temp file */ - FSSpec tempSpec; /* the FSSpec for the temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else - /* For a typical implementation with temp files, we need: */ - FILE * temp_file; /* stdio reference to temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ -#endif -#endif -} backing_store_info; - - -/* - * Initial opening of a backing-store object. This must fill in the - * read/write/close pointers in the object. The read/write routines - * may take an error exit if the specified maximum file size is exceeded. - * (If jpeg_mem_available always returns a large value, this routine can - * just take an error exit.) - */ - -EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, - backing_store_ptr info, - long total_bytes_needed)); - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. jpeg_mem_init will be called before anything is - * allocated (and, therefore, nothing in cinfo is of use except the error - * manager pointer). It should return a suitable default value for - * max_memory_to_use; this may subsequently be overridden by the surrounding - * application. (Note that max_memory_to_use is only important if - * jpeg_mem_available chooses to consult it ... no one else will.) - * jpeg_mem_term may assume that all requested memory has been freed and that - * all opened backing-store objects have been closed. - */ - -EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/libraries/jpeg/jmorecfg.h b/libraries/jpeg/jmorecfg.h deleted file mode 100644 index 679d68bdc5..0000000000 --- a/libraries/jpeg/jmorecfg.h +++ /dev/null @@ -1,446 +0,0 @@ -/* - * jmorecfg.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2013 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains additional configuration options that customize the - * JPEG software for special applications or support machine-dependent - * optimizations. Most users will not need to touch this file. - */ - - -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 9 for 9-bit sample values - * 10 for 10-bit sample values - * 11 for 11-bit sample values - * 12 for 12-bit sample values - * Only 8, 9, 10, 11, and 12 bits sample data precision are supported for - * full-feature DCT processing. Further depths up to 16-bit may be added - * later for the lossless modes of operation. - * Run-time selection and conversion of data precision will be added later - * and are currently not supported, sorry. - * Exception: The transcoding part (jpegtran) supports all settings in a - * single instance, since it operates on the level of DCT coefficients and - * not sample values. The DCT coefficients are of the same type (16 bits) - * in all cases (see below). - */ - -#define BITS_IN_JSAMPLE 8 /* use 8, 9, 10, 11, or 12 */ - - -/* - * Maximum number of components (color channels) allowed in JPEG image. - * To meet the letter of the JPEG spec, set this to 255. However, darn - * few applications need more than 4 channels (maybe 5 for CMYK + alpha - * mask). We recommend 10 as a reasonable compromise; use 4 if you are - * really short on memory. (Each allowed component costs a hundred or so - * bytes of storage, whether actually used in an image or not.) - */ - -#define MAX_COMPONENTS 10 /* maximum number of image components */ - - -/* - * Basic data types. - * You may need to change these if you have a machine with unusual data - * type sizes; for example, "char" not 8 bits, "short" not 16 bits, - * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, - * but it had better be at least 16. - */ - -/* Representation of a single sample (pixel element value). - * We frequently allocate large arrays of these, so it's important to keep - * them small. But if you have memory to burn and access to char or short - * arrays is very slow on your hardware, you might want to change these. - */ - -#if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - * You can use a signed char by having GETJSAMPLE mask it with 0xFF. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JSAMPLE; -#ifdef CHAR_IS_UNSIGNED -#define GETJSAMPLE(value) ((int) (value)) -#else -#define GETJSAMPLE(value) ((int) (value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 - -#endif /* BITS_IN_JSAMPLE == 8 */ - - -#if BITS_IN_JSAMPLE == 9 -/* JSAMPLE should be the smallest type that will hold the values 0..511. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 511 -#define CENTERJSAMPLE 256 - -#endif /* BITS_IN_JSAMPLE == 9 */ - - -#if BITS_IN_JSAMPLE == 10 -/* JSAMPLE should be the smallest type that will hold the values 0..1023. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 1023 -#define CENTERJSAMPLE 512 - -#endif /* BITS_IN_JSAMPLE == 10 */ - - -#if BITS_IN_JSAMPLE == 11 -/* JSAMPLE should be the smallest type that will hold the values 0..2047. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 2047 -#define CENTERJSAMPLE 1024 - -#endif /* BITS_IN_JSAMPLE == 11 */ - - -#if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 4095 -#define CENTERJSAMPLE 2048 - -#endif /* BITS_IN_JSAMPLE == 12 */ - - -/* Representation of a DCT frequency coefficient. - * This should be a signed value of at least 16 bits; "short" is usually OK. - * Again, we allocate large arrays of these, but you can change to int - * if you have memory to burn and "short" is really slow. - */ - -typedef short JCOEF; - - -/* Compressed datastreams are represented as arrays of JOCTET. - * These must be EXACTLY 8 bits wide, at least once they are written to - * external storage. Note that when using the stdio data source/destination - * managers, this is also the data type passed to fread/fwrite. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JOCTET; -#define GETJOCTET(value) (value) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JOCTET; -#ifdef CHAR_IS_UNSIGNED -#define GETJOCTET(value) (value) -#else -#define GETJOCTET(value) ((value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - - -/* These typedefs are used for various table entries and so forth. - * They must be at least as wide as specified; but making them too big - * won't cost a huge amount of memory, so we don't provide special - * extraction code like we did for JSAMPLE. (In other words, these - * typedefs live at a different point on the speed/space tradeoff curve.) - */ - -/* UINT8 must hold at least the values 0..255. */ - -#ifdef HAVE_UNSIGNED_CHAR -typedef unsigned char UINT8; -#else /* not HAVE_UNSIGNED_CHAR */ -#ifdef CHAR_IS_UNSIGNED -typedef char UINT8; -#else /* not CHAR_IS_UNSIGNED */ -typedef short UINT8; -#endif /* CHAR_IS_UNSIGNED */ -#endif /* HAVE_UNSIGNED_CHAR */ - -/* UINT16 must hold at least the values 0..65535. */ - -#ifdef HAVE_UNSIGNED_SHORT -typedef unsigned short UINT16; -#else /* not HAVE_UNSIGNED_SHORT */ -typedef unsigned int UINT16; -#endif /* HAVE_UNSIGNED_SHORT */ - -/* INT16 must hold at least the values -32768..32767. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ -typedef short INT16; -#endif - -/* INT32 must hold at least signed 32-bit values. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ -#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ -#ifndef _BASETSD_H /* MinGW is slightly different */ -#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ -typedef long INT32; -#endif -#endif -#endif -#endif - -/* Datatype used for image dimensions. The JPEG standard only supports - * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore - * "unsigned int" is sufficient on all machines. However, if you need to - * handle larger images and you don't mind deviating from the spec, you - * can change this datatype. - */ - -typedef unsigned int JDIMENSION; - -#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ - - -/* These macros are used in all function definitions and extern declarations. - * You could modify them if you need to change function linkage conventions; - * in particular, you'll need to do that to make the library a Windows DLL. - * Another application is to make all functions global for use with debuggers - * or code profilers that require it. - */ - -/* a function called through method pointers: */ -#define METHODDEF(type) static type -/* a function used only in its module: */ -#define LOCAL(type) static type -/* a function referenced thru EXTERNs: */ -#define GLOBAL(type) type -/* a reference to a GLOBAL function: */ -#define EXTERN(type) extern type - - -/* This macro is used to declare a "method", that is, a function pointer. - * We want to supply prototype parameters if the compiler can cope. - * Note that the arglist parameter must be parenthesized! - * Again, you can customize this if you need special linkage keywords. - */ - -#ifdef HAVE_PROTOTYPES -#define JMETHOD(type,methodname,arglist) type (*methodname) arglist -#else -#define JMETHOD(type,methodname,arglist) type (*methodname) () -#endif - - -/* The noreturn type identifier is used to declare functions - * which cannot return. - * Compilers can thus create more optimized code and perform - * better checks for warnings and errors. - * Static analyzer tools can make improved inferences about - * execution paths and are prevented from giving false alerts. - * - * Unfortunately, the proposed specifications of corresponding - * extensions in the Dec 2011 ISO C standard revision (C11), - * GCC, MSVC, etc. are not viable. - * Thus we introduce a user defined type to declare noreturn - * functions at least for clarity. A proper compiler would - * have a suitable noreturn type to match in place of void. - */ - -#ifndef HAVE_NORETURN_T -typedef void noreturn_t; -#endif - - -/* Here is the pseudo-keyword for declaring pointers that must be "far" - * on 80x86 machines. Most of the specialized coding for 80x86 is handled - * by just saying "FAR *" where such a pointer is needed. In a few places - * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. - */ - -#ifndef FAR -#ifdef NEED_FAR_POINTERS -#define FAR far -#else -#define FAR -#endif -#endif - - -/* - * On a few systems, type boolean and/or its values FALSE, TRUE may appear - * in standard header files. Or you may have conflicts with application- - * specific header files that you want to include together with these files. - * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. - */ - -#ifndef HAVE_BOOLEAN -#if defined FALSE || defined TRUE || defined QGLOBAL_H -/* Qt3 defines FALSE and TRUE as "const" variables in qglobal.h */ -typedef int boolean; -#ifndef FALSE /* in case these macros already exist */ -#define FALSE 0 /* values of boolean */ -#endif -#ifndef TRUE -#define TRUE 1 -#endif -#else -typedef enum { FALSE = 0, TRUE = 1 } boolean; -#endif -#endif - - -/* - * The remaining options affect code selection within the JPEG library, - * but they don't need to be visible to most applications using the library. - * To minimize application namespace pollution, the symbols won't be - * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. - */ - -#ifdef JPEG_INTERNALS -#define JPEG_INTERNAL_OPTIONS -#endif - -#ifdef JPEG_INTERNAL_OPTIONS - - -/* - * These defines indicate whether to include various optional functions. - * Undefining some of these symbols will produce a smaller but less capable - * library. Note that you can leave certain source files out of the - * compilation/linking process if you've #undef'd the corresponding symbols. - * (You may HAVE to do that if your compiler doesn't like null source files.) - */ - -/* Capability options common to encoder and decoder: */ - -#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ -#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ -#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ - -/* Encoder capability options: */ - -#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ -#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected more than 8-bit data precision, it is dangerous to - * turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only - * good for 8-bit precision, so arithmetic coding is recommended for higher - * precision. The Huffman encoder normally uses entropy optimization to - * compute usable tables for higher precision. Otherwise, you'll have to - * supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) - */ -#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ - -/* Decoder capability options: */ - -#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/ -#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ -#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ -#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ -#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ -#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ - -/* more capability options later, no doubt */ - - -/* - * Ordering of RGB data in scanlines passed to or from the application. - * If your application wants to deal with data in the order B,G,R, just - * change these macros. You can also deal with formats such as R,G,B,X - * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing - * the offsets will also change the order in which colormap data is organized. - * RESTRICTIONS: - * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. - * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE - * is not 3 (they don't understand about dummy color components!). So you - * can't use color quantization if you change that value. - */ - -#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ -#define RGB_GREEN 1 /* Offset of Green */ -#define RGB_BLUE 2 /* Offset of Blue */ -#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ - - -/* Definitions for speed-related optimizations. */ - - -/* If your compiler supports inline functions, define INLINE - * as the inline keyword; otherwise define it as empty. - */ - -#ifndef INLINE -#ifdef __GNUC__ /* for instance, GNU C knows about inline */ -#define INLINE __inline__ -#endif -#ifndef INLINE -#define INLINE /* default is to define it as empty */ -#endif -#endif - - -/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying - * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER - * as short on such a machine. MULTIPLIER must be at least 16 bits wide. - */ - -#ifndef MULTIPLIER -#define MULTIPLIER int /* type for fastest integer multiply */ -#endif - - -/* FAST_FLOAT should be either float or double, whichever is done faster - * by your compiler. (Note that this type is only used in the floating point - * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) - * Typically, float is faster in ANSI C compilers, while double is faster in - * pre-ANSI compilers (because they insist on converting to double anyway). - * The code below therefore chooses float if we have ANSI-style prototypes. - */ - -#ifndef FAST_FLOAT -#ifdef HAVE_PROTOTYPES -#define FAST_FLOAT float -#else -#define FAST_FLOAT double -#endif -#endif - -#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/libraries/jpeg/jpegint.h b/libraries/jpeg/jpegint.h deleted file mode 100644 index e312e1af97..0000000000 --- a/libraries/jpeg/jpegint.h +++ /dev/null @@ -1,439 +0,0 @@ -/* - * jpegint.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides common declarations for the various JPEG modules. - * These declarations are considered internal to the JPEG library; most - * applications using the library shouldn't need to include this file. - */ - - -/* Declarations for both compression & decompression */ - -typedef enum { /* Operating modes for buffer controllers */ - JBUF_PASS_THRU, /* Plain stripwise operation */ - /* Remaining modes require a full-image buffer to have been created */ - JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ - JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ - JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ -} J_BUF_MODE; - -/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ -#define CSTATE_START 100 /* after create_compress */ -#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ -#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ -#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ -#define DSTATE_START 200 /* after create_decompress */ -#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ -#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ -#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ -#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ -#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ -#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ -#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ -#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ -#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ -#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ - - -/* Declarations for compression modules */ - -/* Master control module */ -struct jpeg_comp_master { - JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); - JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean call_pass_startup; /* True if pass_startup must be called */ - boolean is_last_pass; /* True during last pass */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_c_main_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail)); -}; - -/* Compression preprocessing (downsampling input buffer control) */ -struct jpeg_c_prep_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, - JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_c_coef_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf)); -}; - -/* Colorspace conversion */ -struct jpeg_color_converter { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, color_convert, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows)); -}; - -/* Downsampling */ -struct jpeg_downsampler { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, downsample, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, - JDIMENSION out_row_group_index)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Forward DCT (also controls coefficient quantization) */ -typedef JMETHOD(void, forward_DCT_ptr, - (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); - -struct jpeg_forward_dct { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - /* It is useful to allow each component to have a separate FDCT method. */ - forward_DCT_ptr forward_DCT[MAX_COMPONENTS]; -}; - -/* Entropy encoding */ -struct jpeg_entropy_encoder { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); - JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); -}; - -/* Marker writing */ -struct jpeg_marker_writer { - JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); - JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); - /* These routines are exported to allow insertion of extra markers */ - /* Probably only COM and APPn markers should be written this way */ - JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, - unsigned int datalen)); - JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); -}; - - -/* Declarations for decompression modules */ - -/* Master control module */ -struct jpeg_decomp_master { - JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ -}; - -/* Input control module */ -struct jpeg_input_controller { - JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); - JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean has_multiple_scans; /* True if file has multiple scans */ - boolean eoi_reached; /* True when EOI has been consumed */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_d_main_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_d_coef_controller { - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); - JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, - JSAMPIMAGE output_buf)); - /* Pointer to array of coefficient virtual arrays, or NULL if none */ - jvirt_barray_ptr *coef_arrays; -}; - -/* Decompression postprocessing (color quantization buffer control) */ -struct jpeg_d_post_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Marker reading & parsing */ -struct jpeg_marker_reader { - JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); - /* Read markers until SOS or EOI. - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); - /* Read a restart marker --- exported for use by entropy decoder only */ - jpeg_marker_parser_method read_restart_marker; - - /* State of marker reader --- nominally internal, but applications - * supplying COM or APPn handlers might like to know the state. - */ - boolean saw_SOI; /* found SOI? */ - boolean saw_SOF; /* found SOF? */ - int next_restart_num; /* next restart number expected (0-7) */ - unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ -}; - -/* Entropy decoding */ -struct jpeg_entropy_decoder { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); - JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); -}; - -/* Inverse DCT (also performs dequantization) */ -typedef JMETHOD(void, inverse_DCT_method_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col)); - -struct jpeg_inverse_dct { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - /* It is useful to allow each component to have a separate IDCT method. */ - inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; -}; - -/* Upsampling (note that upsampler must also call color converter) */ -struct jpeg_upsampler { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, upsample, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Colorspace conversion */ -struct jpeg_color_deconverter { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, color_convert, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows)); -}; - -/* Color quantization or color precision reduction */ -struct jpeg_color_quantizer { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); - JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, - int num_rows)); - JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); -}; - - -/* Definition of range extension bits for decompression processes. - * See the comments with prepare_range_limit_table (in jdmaster.c) - * for more info. - * The recommended default value for normal applications is 2. - * Applications with special requirements may use a different value. - * For example, Ghostscript wants to use 3 for proper handling of - * wacky images with oversize coefficient values. - */ - -#define RANGE_BITS 2 -#define RANGE_CENTER (CENTERJSAMPLE << RANGE_BITS) - - -/* Miscellaneous useful macros */ - -#undef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#undef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - - -/* We assume that right shift corresponds to signed division by 2 with - * rounding towards minus infinity. This is correct for typical "arithmetic - * shift" instructions that shift in copies of the sign bit. But some - * C compilers implement >> with an unsigned shift. For these machines you - * must define RIGHT_SHIFT_IS_UNSIGNED. - * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. - * It is only applied with constant shift counts. SHIFT_TEMPS must be - * included in the variables of any routine using RIGHT_SHIFT. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define SHIFT_TEMPS INT32 shift_temp; -#define RIGHT_SHIFT(x,shft) \ - ((shift_temp = (x)) < 0 ? \ - (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ - (shift_temp >> (shft))) -#else -#define SHIFT_TEMPS -#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_compress_master jICompress -#define jinit_c_master_control jICMaster -#define jinit_c_main_controller jICMainC -#define jinit_c_prep_controller jICPrepC -#define jinit_c_coef_controller jICCoefC -#define jinit_color_converter jICColor -#define jinit_downsampler jIDownsampler -#define jinit_forward_dct jIFDCT -#define jinit_huff_encoder jIHEncoder -#define jinit_arith_encoder jIAEncoder -#define jinit_marker_writer jIMWriter -#define jinit_master_decompress jIDMaster -#define jinit_d_main_controller jIDMainC -#define jinit_d_coef_controller jIDCoefC -#define jinit_d_post_controller jIDPostC -#define jinit_input_controller jIInCtlr -#define jinit_marker_reader jIMReader -#define jinit_huff_decoder jIHDecoder -#define jinit_arith_decoder jIADecoder -#define jinit_inverse_dct jIIDCT -#define jinit_upsampler jIUpsampler -#define jinit_color_deconverter jIDColor -#define jinit_1pass_quantizer jI1Quant -#define jinit_2pass_quantizer jI2Quant -#define jinit_merged_upsampler jIMUpsampler -#define jinit_memory_mgr jIMemMgr -#define jdiv_round_up jDivRound -#define jround_up jRound -#define jzero_far jZeroFar -#define jcopy_sample_rows jCopySamples -#define jcopy_block_row jCopyBlocks -#define jpeg_zigzag_order jZIGTable -#define jpeg_natural_order jZAGTable -#define jpeg_natural_order7 jZAG7Table -#define jpeg_natural_order6 jZAG6Table -#define jpeg_natural_order5 jZAG5Table -#define jpeg_natural_order4 jZAG4Table -#define jpeg_natural_order3 jZAG3Table -#define jpeg_natural_order2 jZAG2Table -#define jpeg_aritab jAriTab -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays - * and coefficient-block arrays. This won't work on 80x86 because the arrays - * are FAR and we're assuming a small-pointer memory model. However, some - * DOS compilers provide far-pointer versions of memcpy() and memset() even - * in the small-model libraries. These will be used if USE_FMEM is defined. - * Otherwise, the routines in jutils.c do it the hard way. - */ - -#ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */ -#define FMEMZERO(target,size) MEMZERO(target,size) -#else /* 80x86 case */ -#ifdef USE_FMEM -#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) -#else -EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); -#define FMEMZERO(target,size) jzero_far(target, size) -#endif -#endif - - -/* Compression module initialization routines */ -EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, - boolean transcode_only)); -EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); -/* Decompression module initialization routines */ -EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); -/* Memory manager initialization */ -EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); - -/* Utility routines in jutils.c */ -EXTERN(long) jdiv_round_up JPP((long a, long b)); -EXTERN(long) jround_up JPP((long a, long b)); -EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols)); -EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks)); -/* Constant tables in jutils.c */ -#if 0 /* This table is not actually needed in v6a */ -extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ -#endif -extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ -extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ -extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ -extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ -extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ -extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ -extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ - -/* Arithmetic coding probability estimation tables in jaricom.c */ -extern const INT32 jpeg_aritab[]; - -/* Suppress undefined-structure complaints if necessary. */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -#endif -#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/libraries/jpeg/jpeglib.h b/libraries/jpeg/jpeglib.h deleted file mode 100644 index 4bd985316e..0000000000 --- a/libraries/jpeg/jpeglib.h +++ /dev/null @@ -1,1180 +0,0 @@ -/* - * jpeglib.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2002-2017 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the application interface for the JPEG library. - * Most applications using the library need only include this file, - * and perhaps jerror.h if they want to know the exact error codes. - */ - -#ifndef JPEGLIB_H -#define JPEGLIB_H - -/* - * First we include the configuration files that record how this - * installation of the JPEG library is set up. jconfig.h can be - * generated automatically for many systems. jmorecfg.h contains - * manual configuration options that most people need not worry about. - */ - -#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ -#include "jconfig.h" /* widely used configuration options */ -#endif -#include "jmorecfg.h" /* seldom changed options */ - - -#ifdef __cplusplus -#ifndef DONT_USE_EXTERN_C -extern "C" { -#endif -#endif - -/* Version IDs for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 90". - */ - -#define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */ -#define JPEG_LIB_VERSION_MAJOR 9 -#define JPEG_LIB_VERSION_MINOR 3 - - -/* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, - * so don't change them if you want to be compatible. - */ - -#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ -#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ -#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ -#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ -#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ -#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ -#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ -/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; - * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. - * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU - * to handle it. We even let you do this from the jconfig.h file. However, - * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe - * sometimes emits noncompliant files doesn't mean you should too. - */ -#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ -#ifndef D_MAX_BLOCKS_IN_MCU -#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ -#endif - - -/* Data structures for images (arrays of samples and of DCT coefficients). - * On 80x86 machines, the image arrays are too big for near pointers, - * but the pointer arrays can fit in near memory. - */ - -typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ -typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ -typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ - -typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ -typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ -typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ -typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ - -typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ - - -/* Types for JPEG compression parameters and working tables. */ - - -/* DCT coefficient quantization tables. */ - -typedef struct { - /* This array gives the coefficient quantizers in natural array order - * (not the zigzag order in which they are stored in a JPEG DQT marker). - * CAUTION: IJG versions prior to v6a kept this array in zigzag order. - */ - UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JQUANT_TBL; - - -/* Huffman coding tables. */ - -typedef struct { - /* These two fields directly represent the contents of a JPEG DHT marker */ - UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ - /* length k bits; bits[0] is unused */ - UINT8 huffval[256]; /* The symbols, in order of incr code length */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JHUFF_TBL; - - -/* Basic info about one component (color channel). */ - -typedef struct { - /* These values are fixed over the whole image. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOF marker. */ - int component_id; /* identifier for this component (0..255) */ - int component_index; /* its index in SOF or cinfo->comp_info[] */ - int h_samp_factor; /* horizontal sampling factor (1..4) */ - int v_samp_factor; /* vertical sampling factor (1..4) */ - int quant_tbl_no; /* quantization table selector (0..3) */ - /* These values may vary between scans. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOS marker. */ - /* The decompressor output side may not use these variables. */ - int dc_tbl_no; /* DC entropy table selector (0..3) */ - int ac_tbl_no; /* AC entropy table selector (0..3) */ - - /* Remaining fields should be treated as private by applications. */ - - /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. - */ - JDIMENSION width_in_blocks; - JDIMENSION height_in_blocks; - /* Size of a DCT block in samples, - * reflecting any scaling we choose to apply during the DCT step. - * Values from 1 to 16 are supported. - * Note that different components may receive different DCT scalings. - */ - int DCT_h_scaled_size; - int DCT_v_scaled_size; - /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface); - * DCT scaling is included, so - * downsampled_width = - * ceil(image_width * Hi/Hmax * DCT_h_scaled_size/block_size) - * and similarly for height. - */ - JDIMENSION downsampled_width; /* actual width in samples */ - JDIMENSION downsampled_height; /* actual height in samples */ - /* For decompression, in cases where some of the components will be - * ignored (eg grayscale output from YCbCr image), we can skip most - * computations for the unused components. - * For compression, some of the components will need further quantization - * scale by factor of 2 after DCT (eg BG_YCC output from normal RGB input). - * The field is first set TRUE for decompression, FALSE for compression - * in initial_setup, and then adapted in color conversion setup. - */ - boolean component_needed; - - /* These values are computed before starting a scan of the component. */ - /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of blocks per MCU, horizontally */ - int MCU_height; /* number of blocks per MCU, vertically */ - int MCU_blocks; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ - int last_col_width; /* # of non-dummy blocks across in last MCU */ - int last_row_height; /* # of non-dummy blocks down in last MCU */ - - /* Saved quantization table for component; NULL if none yet saved. - * See jdinput.c comments about the need for this information. - * This field is currently used only for decompression. - */ - JQUANT_TBL * quant_table; - - /* Private per-component storage for DCT or IDCT subsystem. */ - void * dct_table; -} jpeg_component_info; - - -/* The script for encoding a multiple-scan file is an array of these: */ - -typedef struct { - int comps_in_scan; /* number of components encoded in this scan */ - int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms */ - int Ah, Al; /* progressive JPEG successive approx. parms */ -} jpeg_scan_info; - -/* The decompressor can save APPn and COM markers in a list of these: */ - -typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; - -struct jpeg_marker_struct { - jpeg_saved_marker_ptr next; /* next in list, or NULL */ - UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ - unsigned int original_length; /* # bytes of data in the file */ - unsigned int data_length; /* # bytes of data saved at data[] */ - JOCTET FAR * data; /* the data contained in the marker */ - /* the marker length word is not counted in data_length or original_length */ -}; - -/* Known color spaces. */ - -typedef enum { - JCS_UNKNOWN, /* error/unspecified */ - JCS_GRAYSCALE, /* monochrome */ - JCS_RGB, /* red/green/blue, standard RGB (sRGB) */ - JCS_YCbCr, /* Y/Cb/Cr (also known as YUV), standard YCC */ - JCS_CMYK, /* C/M/Y/K */ - JCS_YCCK, /* Y/Cb/Cr/K */ - JCS_BG_RGB, /* big gamut red/green/blue, bg-sRGB */ - JCS_BG_YCC /* big gamut Y/Cb/Cr, bg-sYCC */ -} J_COLOR_SPACE; - -/* Supported color transforms. */ - -typedef enum { - JCT_NONE = 0, - JCT_SUBTRACT_GREEN = 1 -} J_COLOR_TRANSFORM; - -/* DCT/IDCT algorithm options. */ - -typedef enum { - JDCT_ISLOW, /* slow but accurate integer algorithm */ - JDCT_IFAST, /* faster, less accurate integer method */ - JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ -} J_DCT_METHOD; - -#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ -#define JDCT_DEFAULT JDCT_ISLOW -#endif -#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ -#define JDCT_FASTEST JDCT_IFAST -#endif - -/* Dithering options for decompression. */ - -typedef enum { - JDITHER_NONE, /* no dithering */ - JDITHER_ORDERED, /* simple ordered dither */ - JDITHER_FS /* Floyd-Steinberg error diffusion dither */ -} J_DITHER_MODE; - - -/* Common fields between JPEG compression and decompression master structs. */ - -#define jpeg_common_fields \ - struct jpeg_error_mgr * err; /* Error handler module */\ - struct jpeg_memory_mgr * mem; /* Memory manager module */\ - struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ - void * client_data; /* Available for use by application */\ - boolean is_decompressor; /* So common code can tell which is which */\ - int global_state /* For checking call sequence validity */ - -/* Routines that are to be used by both halves of the library are declared - * to receive a pointer to this structure. There are no actual instances of - * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. - */ -struct jpeg_common_struct { - jpeg_common_fields; /* Fields common to both master struct types */ - /* Additional fields follow in an actual jpeg_compress_struct or - * jpeg_decompress_struct. All three structs must agree on these - * initial fields! (This would be a lot cleaner in C++.) - */ -}; - -typedef struct jpeg_common_struct * j_common_ptr; -typedef struct jpeg_compress_struct * j_compress_ptr; -typedef struct jpeg_decompress_struct * j_decompress_ptr; - - -/* Master record for a compression instance */ - -struct jpeg_compress_struct { - jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ - - /* Destination for compressed data */ - struct jpeg_destination_mgr * dest; - - /* Description of source image --- these fields must be filled in by - * outer application before starting compression. in_color_space must - * be correct before you can even call jpeg_set_defaults(). - */ - - JDIMENSION image_width; /* input image width */ - JDIMENSION image_height; /* input image height */ - int input_components; /* # of color components in input image */ - J_COLOR_SPACE in_color_space; /* colorspace of input image */ - - double input_gamma; /* image gamma of input image */ - - /* Compression parameters --- these fields must be set before calling - * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to - * initialize everything to reasonable defaults, then changing anything - * the application specifically wants to change. That way you won't get - * burnt when new parameters are added. Also note that there are several - * helper routines to simplify changing parameters. - */ - - unsigned int scale_num, scale_denom; /* fraction by which to scale image */ - - JDIMENSION jpeg_width; /* scaled JPEG image width */ - JDIMENSION jpeg_height; /* scaled JPEG image height */ - /* Dimensions of actual JPEG image that will be written to file, - * derived from input dimensions by scaling factors above. - * These fields are computed by jpeg_start_compress(). - * You can also use jpeg_calc_jpeg_dimensions() to determine these values - * in advance of calling jpeg_start_compress(). - */ - - int data_precision; /* bits of precision in image data */ - - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - int q_scale_factor[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined, - * and corresponding scale factors (percentage, initialized 100). - */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - int num_scans; /* # of entries in scan_info array */ - const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ - /* The default value of scan_info is NULL, which causes a single-scan - * sequential JPEG file to be emitted. To create a multi-scan file, - * set num_scans and scan_info to point to an array of scan definitions. - */ - - boolean raw_data_in; /* TRUE=caller supplies downsampled data */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ - int smoothing_factor; /* 1..100, or 0 for no input smoothing */ - J_DCT_METHOD dct_method; /* DCT algorithm selector */ - - /* The restart interval can be specified in absolute MCUs by setting - * restart_interval, or in MCU rows by setting restart_in_rows - * (in which case the correct restart_interval will be figured - * for each scan). - */ - unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ - int restart_in_rows; /* if > 0, MCU rows per restart interval */ - - /* Parameters controlling emission of special markers. */ - - boolean write_JFIF_header; /* should a JFIF marker be written? */ - UINT8 JFIF_major_version; /* What to write for the JFIF version number */ - UINT8 JFIF_minor_version; - /* These three values are not used by the JPEG code, merely copied */ - /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ - /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ - /* ratio is defined by X_density/Y_density even when density_unit=0. */ - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean write_Adobe_marker; /* should an Adobe marker be written? */ - - J_COLOR_TRANSFORM color_transform; - /* Color transform identifier, writes LSE marker if nonzero */ - - /* State variable: index of next scanline to be written to - * jpeg_write_scanlines(). Application may use this to control its - * processing loop, e.g., "while (next_scanline < image_height)". - */ - - JDIMENSION next_scanline; /* 0 .. image_height-1 */ - - /* Remaining fields are known throughout compressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during compression startup - */ - boolean progressive_mode; /* TRUE if scan script uses progressive mode */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ - int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCT_v_scaled_size sample rows of each component - * in an "iMCU" (interleaved MCU) row. - */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[C_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - int block_size; /* the basic DCT block size: 1..16 */ - const int * natural_order; /* natural-order position array */ - int lim_Se; /* min( Se, DCTSIZE2-1 ) */ - - /* - * Links to compression subobjects (methods and private variables of modules) - */ - struct jpeg_comp_master * master; - struct jpeg_c_main_controller * main; - struct jpeg_c_prep_controller * prep; - struct jpeg_c_coef_controller * coef; - struct jpeg_marker_writer * marker; - struct jpeg_color_converter * cconvert; - struct jpeg_downsampler * downsample; - struct jpeg_forward_dct * fdct; - struct jpeg_entropy_encoder * entropy; - jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ - int script_space_size; -}; - - -/* Master record for a decompression instance */ - -struct jpeg_decompress_struct { - jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ - - /* Source of compressed data */ - struct jpeg_source_mgr * src; - - /* Basic description of image --- filled in by jpeg_read_header(). */ - /* Application may inspect these values to decide how to process image. */ - - JDIMENSION image_width; /* nominal image width (from SOF marker) */ - JDIMENSION image_height; /* nominal image height */ - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - /* Decompression processing parameters --- these fields must be set before - * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes - * them to default values. - */ - - J_COLOR_SPACE out_color_space; /* colorspace for output */ - - unsigned int scale_num, scale_denom; /* fraction by which to scale image */ - - double output_gamma; /* image gamma wanted in output */ - - boolean buffered_image; /* TRUE=multiple output passes */ - boolean raw_data_out; /* TRUE=downsampled data wanted */ - - J_DCT_METHOD dct_method; /* IDCT algorithm selector */ - boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ - boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ - - boolean quantize_colors; /* TRUE=colormapped output wanted */ - /* the following are ignored if not quantize_colors: */ - J_DITHER_MODE dither_mode; /* type of color dithering to use */ - boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ - int desired_number_of_colors; /* max # colors to use in created colormap */ - /* these are significant only in buffered-image mode: */ - boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ - boolean enable_external_quant;/* enable future use of external colormap */ - boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ - - /* Description of actual output image that will be returned to application. - * These fields are computed by jpeg_start_decompress(). - * You can also use jpeg_calc_output_dimensions() to determine these values - * in advance of calling jpeg_start_decompress(). - */ - - JDIMENSION output_width; /* scaled image width */ - JDIMENSION output_height; /* scaled image height */ - int out_color_components; /* # of color components in out_color_space */ - int output_components; /* # of color components returned */ - /* output_components is 1 (a colormap index) when quantizing colors; - * otherwise it equals out_color_components. - */ - int rec_outbuf_height; /* min recommended height of scanline buffer */ - /* If the buffer passed to jpeg_read_scanlines() is less than this many rows - * high, space and time will be wasted due to unnecessary data copying. - * Usually rec_outbuf_height will be 1 or 2, at most 4. - */ - - /* When quantizing colors, the output colormap is described by these fields. - * The application can supply a colormap by setting colormap non-NULL before - * calling jpeg_start_decompress; otherwise a colormap is created during - * jpeg_start_decompress or jpeg_start_output. - * The map has out_color_components rows and actual_number_of_colors columns. - */ - int actual_number_of_colors; /* number of entries in use */ - JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ - - /* State variables: these variables indicate the progress of decompression. - * The application may examine these but must not modify them. - */ - - /* Row index of next scanline to be read from jpeg_read_scanlines(). - * Application may use this to control its processing loop, e.g., - * "while (output_scanline < output_height)". - */ - JDIMENSION output_scanline; /* 0 .. output_height-1 */ - - /* Current input scan number and number of iMCU rows completed in scan. - * These indicate the progress of the decompressor input side. - */ - int input_scan_number; /* Number of SOS markers seen so far */ - JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ - - /* The "output scan number" is the notional scan being displayed by the - * output side. The decompressor will not allow output scan/row number - * to get ahead of input scan/row, but it can fall arbitrarily far behind. - */ - int output_scan_number; /* Nominal scan number being displayed */ - JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ - - /* Current progression status. coef_bits[c][i] indicates the precision - * with which component c's DCT coefficient i (in zigzag order) is known. - * It is -1 when no data has yet been received, otherwise it is the point - * transform (shift) value for the most recent scan of the coefficient - * (thus, 0 at completion of the progression). - * This pointer is NULL when reading a non-progressive file. - */ - int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ - - /* Internal JPEG parameters --- the application usually need not look at - * these fields. Note that the decompressor output side may not use - * any parameters that can change between scans. - */ - - /* Quantization and Huffman tables are carried forward across input - * datastreams when processing abbreviated JPEG datastreams. - */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - /* These parameters are never carried across datastreams, since they - * are given in SOF/SOS markers or defined to be reset by SOI. - */ - - int data_precision; /* bits of precision in image data */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ - boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ - - /* These fields record data obtained from optional markers recognized by - * the JPEG library. - */ - boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ - /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ - UINT8 JFIF_major_version; /* JFIF version number */ - UINT8 JFIF_minor_version; - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ - UINT8 Adobe_transform; /* Color transform code from Adobe marker */ - - J_COLOR_TRANSFORM color_transform; - /* Color transform identifier derived from LSE marker, otherwise zero */ - - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - - /* Aside from the specific data retained from APPn markers known to the - * library, the uninterpreted contents of any or all APPn and COM markers - * can be saved in a list for examination by the application. - */ - jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ - - /* Remaining fields are known throughout decompressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during decompression startup - */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ - int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains - * v_samp_factor * DCT_v_scaled_size sample rows of a component per iMCU row. - */ - - JSAMPLE * sample_range_limit; /* table for fast range-limiting */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - * Note that the decompressor output side must not use these fields. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[D_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* These fields are derived from Se of first SOS marker. - */ - int block_size; /* the basic DCT block size: 1..16 */ - const int * natural_order; /* natural-order position array for entropy decode */ - int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ - - /* This field is shared between entropy decoder and marker parser. - * It is either zero or the code of a JPEG marker that has been - * read from the data source, but has not yet been processed. - */ - int unread_marker; - - /* - * Links to decompression subobjects (methods, private variables of modules) - */ - struct jpeg_decomp_master * master; - struct jpeg_d_main_controller * main; - struct jpeg_d_coef_controller * coef; - struct jpeg_d_post_controller * post; - struct jpeg_input_controller * inputctl; - struct jpeg_marker_reader * marker; - struct jpeg_entropy_decoder * entropy; - struct jpeg_inverse_dct * idct; - struct jpeg_upsampler * upsample; - struct jpeg_color_deconverter * cconvert; - struct jpeg_color_quantizer * cquantize; -}; - - -/* "Object" declarations for JPEG modules that may be supplied or called - * directly by the surrounding application. - * As with all objects in the JPEG library, these structs only define the - * publicly visible methods and state variables of a module. Additional - * private fields may exist after the public ones. - */ - - -/* Error handler object */ - -struct jpeg_error_mgr { - /* Error exit handler: does not return to caller */ - JMETHOD(noreturn_t, error_exit, (j_common_ptr cinfo)); - /* Conditionally emit a trace or warning message */ - JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); - /* Routine that actually outputs a trace or error message */ - JMETHOD(void, output_message, (j_common_ptr cinfo)); - /* Format a message string for the most recent JPEG error or message */ - JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); -#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ - /* Reset error state variables at start of a new image */ - JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - - /* The message ID code and any parameters are saved here. - * A message can have one string parameter or up to 8 int parameters. - */ - int msg_code; -#define JMSG_STR_PARM_MAX 80 - union { - int i[8]; - char s[JMSG_STR_PARM_MAX]; - } msg_parm; - - /* Standard state variables for error facility */ - - int trace_level; /* max msg_level that will be displayed */ - - /* For recoverable corrupt-data errors, we emit a warning message, - * but keep going unless emit_message chooses to abort. emit_message - * should count warnings in num_warnings. The surrounding application - * can check for bad data by seeing if num_warnings is nonzero at the - * end of processing. - */ - long num_warnings; /* number of corrupt-data warnings */ - - /* These fields point to the table(s) of error message strings. - * An application can change the table pointer to switch to a different - * message list (typically, to change the language in which errors are - * reported). Some applications may wish to add additional error codes - * that will be handled by the JPEG library error mechanism; the second - * table pointer is used for this purpose. - * - * First table includes all errors generated by JPEG library itself. - * Error code 0 is reserved for a "no such error string" message. - */ - const char * const * jpeg_message_table; /* Library errors */ - int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ - /* Second table can be added by application (see cjpeg/djpeg for example). - * It contains strings numbered first_addon_message..last_addon_message. - */ - const char * const * addon_message_table; /* Non-library errors */ - int first_addon_message; /* code for first string in addon table */ - int last_addon_message; /* code for last string in addon table */ -}; - - -/* Progress monitor object */ - -struct jpeg_progress_mgr { - JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); - - long pass_counter; /* work units completed in this pass */ - long pass_limit; /* total number of work units in this pass */ - int completed_passes; /* passes completed so far */ - int total_passes; /* total number of passes expected */ -}; - - -/* Data destination object for compression */ - -struct jpeg_destination_mgr { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - - JMETHOD(void, init_destination, (j_compress_ptr cinfo)); - JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); - JMETHOD(void, term_destination, (j_compress_ptr cinfo)); -}; - - -/* Data source object for decompression */ - -struct jpeg_source_mgr { - const JOCTET * next_input_byte; /* => next byte to read from buffer */ - size_t bytes_in_buffer; /* # of bytes remaining in buffer */ - - JMETHOD(void, init_source, (j_decompress_ptr cinfo)); - JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); - JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); - JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); - JMETHOD(void, term_source, (j_decompress_ptr cinfo)); -}; - - -/* Memory manager object. - * Allocates "small" objects (a few K total), "large" objects (tens of K), - * and "really big" objects (virtual arrays with backing store if needed). - * The memory manager does not allow individual objects to be freed; rather, - * each created object is assigned to a pool, and whole pools can be freed - * at once. This is faster and more convenient than remembering exactly what - * to free, especially where malloc()/free() are not too speedy. - * NB: alloc routines never return NULL. They exit to error_exit if not - * successful. - */ - -#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ -#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ -#define JPOOL_NUMPOOLS 2 - -typedef struct jvirt_sarray_control * jvirt_sarray_ptr; -typedef struct jvirt_barray_control * jvirt_barray_ptr; - - -struct jpeg_memory_mgr { - /* Method pointers */ - JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, - JDIMENSION numrows)); - JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, - JDIMENSION numrows)); - JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION samplesperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION blocksperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); - JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, - jvirt_sarray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, - jvirt_barray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); - JMETHOD(void, self_destruct, (j_common_ptr cinfo)); - - /* Limit on memory allocation for this JPEG object. (Note that this is - * merely advisory, not a guaranteed maximum; it only affects the space - * used for virtual-array buffers.) May be changed by outer application - * after creating the JPEG object. - */ - long max_memory_to_use; - - /* Maximum allocation request accepted by alloc_large. */ - long max_alloc_chunk; -}; - - -/* Routine signature for application-supplied marker processing methods. - * Need not pass marker code since it is stored in cinfo->unread_marker. - */ -typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); - - -/* Declarations for routines called by application. - * The JPP macro hides prototype parameters from compilers that can't cope. - * Note JPP requires double parentheses. - */ - -#ifdef HAVE_PROTOTYPES -#define JPP(arglist) arglist -#else -#define JPP(arglist) () -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. - * We shorten external names to be unique in the first six letters, which - * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 - * characters, you are out of luck. Get a better compiler.) - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_error jStdError -#define jpeg_CreateCompress jCreaCompress -#define jpeg_CreateDecompress jCreaDecompress -#define jpeg_destroy_compress jDestCompress -#define jpeg_destroy_decompress jDestDecompress -#define jpeg_stdio_dest jStdDest -#define jpeg_stdio_src jStdSrc -#define jpeg_mem_dest jMemDest -#define jpeg_mem_src jMemSrc -#define jpeg_set_defaults jSetDefaults -#define jpeg_set_colorspace jSetColorspace -#define jpeg_default_colorspace jDefColorspace -#define jpeg_set_quality jSetQuality -#define jpeg_set_linear_quality jSetLQuality -#define jpeg_default_qtables jDefQTables -#define jpeg_add_quant_table jAddQuantTable -#define jpeg_quality_scaling jQualityScaling -#define jpeg_simple_progression jSimProgress -#define jpeg_suppress_tables jSuppressTables -#define jpeg_alloc_quant_table jAlcQTable -#define jpeg_alloc_huff_table jAlcHTable -#define jpeg_start_compress jStrtCompress -#define jpeg_write_scanlines jWrtScanlines -#define jpeg_finish_compress jFinCompress -#define jpeg_calc_jpeg_dimensions jCjpegDimensions -#define jpeg_write_raw_data jWrtRawData -#define jpeg_write_marker jWrtMarker -#define jpeg_write_m_header jWrtMHeader -#define jpeg_write_m_byte jWrtMByte -#define jpeg_write_tables jWrtTables -#define jpeg_read_header jReadHeader -#define jpeg_start_decompress jStrtDecompress -#define jpeg_read_scanlines jReadScanlines -#define jpeg_finish_decompress jFinDecompress -#define jpeg_read_raw_data jReadRawData -#define jpeg_has_multiple_scans jHasMultScn -#define jpeg_start_output jStrtOutput -#define jpeg_finish_output jFinOutput -#define jpeg_input_complete jInComplete -#define jpeg_new_colormap jNewCMap -#define jpeg_consume_input jConsumeInput -#define jpeg_core_output_dimensions jCoreDimensions -#define jpeg_calc_output_dimensions jCalcDimensions -#define jpeg_save_markers jSaveMarkers -#define jpeg_set_marker_processor jSetMarker -#define jpeg_read_coefficients jReadCoefs -#define jpeg_write_coefficients jWrtCoefs -#define jpeg_copy_critical_parameters jCopyCrit -#define jpeg_abort_compress jAbrtCompress -#define jpeg_abort_decompress jAbrtDecompress -#define jpeg_abort jAbort -#define jpeg_destroy jDestroy -#define jpeg_resync_to_restart jResyncRestart -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Default error-management setup */ -EXTERN(struct jpeg_error_mgr *) jpeg_std_error - JPP((struct jpeg_error_mgr * err)); - -/* Initialization of JPEG compression objects. - * jpeg_create_compress() and jpeg_create_decompress() are the exported - * names that applications should call. These expand to calls on - * jpeg_CreateCompress and jpeg_CreateDecompress with additional information - * passed for version mismatch checking. - * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. - */ -#define jpeg_create_compress(cinfo) \ - jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_compress_struct)) -#define jpeg_create_decompress(cinfo) \ - jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_decompress_struct)) -EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, - int version, size_t structsize)); -EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, - int version, size_t structsize)); -/* Destruction of JPEG compression objects */ -EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); - -/* Standard data source and destination managers: stdio streams. */ -/* Caller is responsible for opening the file before and closing after. */ -EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); -EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); - -/* Data source and destination managers: memory buffers. */ -EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, - unsigned char ** outbuffer, - unsigned long * outsize)); -EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, - const unsigned char * inbuffer, - unsigned long insize)); - -/* Default parameter setup for compression */ -EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); -/* Compression parameter setup aids */ -EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, - J_COLOR_SPACE colorspace)); -EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, - boolean force_baseline)); -EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, - int scale_factor, - boolean force_baseline)); -EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, - boolean force_baseline)); -EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, - boolean force_baseline)); -EXTERN(int) jpeg_quality_scaling JPP((int quality)); -EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, - boolean suppress)); -EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); -EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); - -/* Main entry points for compression */ -EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, - boolean write_all_tables)); -EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION num_lines)); -EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); - -/* Precalculate JPEG dimensions for current compression parameters. */ -EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); - -/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION num_lines)); - -/* Write a special marker. See libjpeg.txt concerning safe usage. */ -EXTERN(void) jpeg_write_marker - JPP((j_compress_ptr cinfo, int marker, - const JOCTET * dataptr, unsigned int datalen)); -/* Same, but piecemeal. */ -EXTERN(void) jpeg_write_m_header - JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); -EXTERN(void) jpeg_write_m_byte - JPP((j_compress_ptr cinfo, int val)); - -/* Alternate compression function: just write an abbreviated table file */ -EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); - -/* Decompression startup: read start of JPEG datastream to see what's there */ -EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, - boolean require_image)); -/* Return value is one of: */ -#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ -#define JPEG_HEADER_OK 1 /* Found valid image datastream */ -#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ -/* If you pass require_image = TRUE (normal case), you need not check for - * a TABLES_ONLY return code; an abbreviated file will cause an error exit. - * JPEG_SUSPENDED is only possible if you use a data source module that can - * give a suspension return (the stdio source module doesn't). - */ - -/* Main entry points for decompression */ -EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION max_lines)); -EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); - -/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION max_lines)); - -/* Additional entry points for buffered-image mode. */ -EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, - int scan_number)); -EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); -EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); -/* Return value is one of: */ -/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ -#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ -#define JPEG_REACHED_EOI 2 /* Reached end of image */ -#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ -#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ - -/* Precalculate output dimensions for current decompression parameters. */ -EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); - -/* Control saving of COM and APPn markers into marker_list. */ -EXTERN(void) jpeg_save_markers - JPP((j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit)); - -/* Install a special processing method for COM or APPn markers. */ -EXTERN(void) jpeg_set_marker_processor - JPP((j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine)); - -/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ -EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays)); -EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, - j_compress_ptr dstinfo)); - -/* If you choose to abort compression or decompression before completing - * jpeg_finish_(de)compress, then you need to clean up to release memory, - * temporary files, etc. You can just call jpeg_destroy_(de)compress - * if you're done with the JPEG object, but if you want to clean it up and - * reuse it, call this: - */ -EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); - -/* Generic versions of jpeg_abort and jpeg_destroy that work on either - * flavor of JPEG object. These may be more convenient in some places. - */ -EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); - -/* Default restart-marker-resync procedure for use by data source modules */ -EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, - int desired)); - - -/* These marker codes are exported since applications and data source modules - * are likely to want to use them. - */ - -#define JPEG_RST0 0xD0 /* RST0 marker code */ -#define JPEG_EOI 0xD9 /* EOI marker code */ -#define JPEG_APP0 0xE0 /* APP0 marker code */ -#define JPEG_COM 0xFE /* COM marker code */ - - -/* If we have a brain-damaged compiler that emits warnings (or worse, errors) - * for structure definitions that are never filled in, keep it quiet by - * supplying dummy definitions for the various substructures. - */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -struct jpeg_comp_master { long dummy; }; -struct jpeg_c_main_controller { long dummy; }; -struct jpeg_c_prep_controller { long dummy; }; -struct jpeg_c_coef_controller { long dummy; }; -struct jpeg_marker_writer { long dummy; }; -struct jpeg_color_converter { long dummy; }; -struct jpeg_downsampler { long dummy; }; -struct jpeg_forward_dct { long dummy; }; -struct jpeg_entropy_encoder { long dummy; }; -struct jpeg_decomp_master { long dummy; }; -struct jpeg_d_main_controller { long dummy; }; -struct jpeg_d_coef_controller { long dummy; }; -struct jpeg_d_post_controller { long dummy; }; -struct jpeg_input_controller { long dummy; }; -struct jpeg_marker_reader { long dummy; }; -struct jpeg_entropy_decoder { long dummy; }; -struct jpeg_inverse_dct { long dummy; }; -struct jpeg_upsampler { long dummy; }; -struct jpeg_color_deconverter { long dummy; }; -struct jpeg_color_quantizer { long dummy; }; -#endif /* JPEG_INTERNALS */ -#endif /* INCOMPLETE_TYPES_BROKEN */ - - -/* - * The JPEG library modules define JPEG_INTERNALS before including this file. - * The internal structure declarations are read only when that is true. - * Applications using the library should not include jpegint.h, but may wish - * to include jerror.h. - */ - -#ifdef JPEG_INTERNALS -#include "jpegint.h" /* fetch private declarations */ -#include "jerror.h" /* fetch error codes too */ -#endif - -#ifdef __cplusplus -#ifndef DONT_USE_EXTERN_C -} -#endif -#endif - -#endif /* JPEGLIB_H */ diff --git a/libraries/jpeg/jquant1.c b/libraries/jpeg/jquant1.c deleted file mode 100644 index 9d11f70669..0000000000 --- a/libraries/jpeg/jquant1.c +++ /dev/null @@ -1,857 +0,0 @@ -/* - * jquant1.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2011 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains 1-pass color quantization (color mapping) routines. - * These routines provide mapping to a fixed color map using equally spaced - * color values. Optional Floyd-Steinberg or ordered dithering is available. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -#ifdef QUANT_1PASS_SUPPORTED - - -/* - * The main purpose of 1-pass quantization is to provide a fast, if not very - * high quality, colormapped output capability. A 2-pass quantizer usually - * gives better visual quality; however, for quantized grayscale output this - * quantizer is perfectly adequate. Dithering is highly recommended with this - * quantizer, though you can turn it off if you really want to. - * - * In 1-pass quantization the colormap must be chosen in advance of seeing the - * image. We use a map consisting of all combinations of Ncolors[i] color - * values for the i'th component. The Ncolors[] values are chosen so that - * their product, the total number of colors, is no more than that requested. - * (In most cases, the product will be somewhat less.) - * - * Since the colormap is orthogonal, the representative value for each color - * component can be determined without considering the other components; - * then these indexes can be combined into a colormap index by a standard - * N-dimensional-array-subscript calculation. Most of the arithmetic involved - * can be precalculated and stored in the lookup table colorindex[]. - * colorindex[i][j] maps pixel value j in component i to the nearest - * representative value (grid plane) for that component; this index is - * multiplied by the array stride for component i, so that the - * index of the colormap entry closest to a given pixel value is just - * sum( colorindex[component-number][pixel-component-value] ) - * Aside from being fast, this scheme allows for variable spacing between - * representative values with no additional lookup cost. - * - * If gamma correction has been applied in color conversion, it might be wise - * to adjust the color grid spacing so that the representative colors are - * equidistant in linear space. At this writing, gamma correction is not - * implemented by jdcolor, so nothing is done here. - */ - - -/* Declarations for ordered dithering. - * - * We use a standard 16x16 ordered dither array. The basic concept of ordered - * dithering is described in many references, for instance Dale Schumacher's - * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). - * In place of Schumacher's comparisons against a "threshold" value, we add a - * "dither" value to the input pixel and then round the result to the nearest - * output value. The dither value is equivalent to (0.5 - threshold) times - * the distance between output values. For ordered dithering, we assume that - * the output colors are equally spaced; if not, results will probably be - * worse, since the dither may be too much or too little at a given point. - * - * The normal calculation would be to form pixel value + dither, range-limit - * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. - * We can skip the separate range-limiting step by extending the colorindex - * table in both directions. - */ - -#define ODITHER_SIZE 16 /* dimension of dither matrix */ -/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ -#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ -#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ - -typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; -typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; - -static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { - /* Bayer's order-4 dither array. Generated by the code given in - * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. - * The values in this array must range from 0 to ODITHER_CELLS-1. - */ - { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, - { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, - { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, - { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, - { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, - { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, - { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, - { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, - { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, - { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, - { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, - { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, - { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, - { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, - { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, - { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } -}; - - -/* Declarations for Floyd-Steinberg dithering. - * - * Errors are accumulated into the array fserrors[], at a resolution of - * 1/16th of a pixel count. The error at a given pixel is propagated - * to its not-yet-processed neighbors using the standard F-S fractions, - * ... (here) 7/16 - * 3/16 5/16 1/16 - * We work left-to-right on even rows, right-to-left on odd rows. - * - * We can get away with a single array (holding one row's worth of errors) - * by using it to store the current row's errors at pixel columns not yet - * processed, but the next row's errors at columns already processed. We - * need only a few extra variables to hold the errors immediately around the - * current column. (If we are lucky, those variables are in registers, but - * even if not, they're probably cheaper to access than array elements are.) - * - * The fserrors[] array is indexed [component#][position]. - * We provide (#columns + 2) entries per component; the extra entry at each - * end saves us from special-casing the first and last pixels. - * - * Note: on a wide image, we might not have enough room in a PC's near data - * segment to hold the error array; so it is allocated with alloc_large. - */ - -#if BITS_IN_JSAMPLE == 8 -typedef INT16 FSERROR; /* 16 bits should be enough */ -typedef int LOCFSERROR; /* use 'int' for calculation temps */ -#else -typedef INT32 FSERROR; /* may need more than 16 bits */ -typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ -#endif - -typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ - - -/* Private subobject */ - -#define MAX_Q_COMPS 4 /* max components I can handle */ - -typedef struct { - struct jpeg_color_quantizer pub; /* public fields */ - - /* Initially allocated colormap is saved here */ - JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ - int sv_actual; /* number of entries in use */ - - JSAMPARRAY colorindex; /* Precomputed mapping for speed */ - /* colorindex[i][j] = index of color closest to pixel value j in component i, - * premultiplied as described above. Since colormap indexes must fit into - * JSAMPLEs, the entries of this array will too. - */ - boolean is_padded; /* is the colorindex padded for odither? */ - - int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ - - /* Variables for ordered dithering */ - int row_index; /* cur row's vertical index in dither matrix */ - ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ - - /* Variables for Floyd-Steinberg dithering */ - FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ - boolean on_odd_row; /* flag to remember which row we are on */ -} my_cquantizer; - -typedef my_cquantizer * my_cquantize_ptr; - - -/* - * Policy-making subroutines for create_colormap and create_colorindex. - * These routines determine the colormap to be used. The rest of the module - * only assumes that the colormap is orthogonal. - * - * * select_ncolors decides how to divvy up the available colors - * among the components. - * * output_value defines the set of representative values for a component. - * * largest_input_value defines the mapping from input values to - * representative values for a component. - * Note that the latter two routines may impose different policies for - * different components, though this is not currently done. - */ - - -LOCAL(int) -select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) -/* Determine allocation of desired colors to components, */ -/* and fill in Ncolors[] array to indicate choice. */ -/* Return value is total number of colors (product of Ncolors[] values). */ -{ - int nc = cinfo->out_color_components; /* number of color components */ - int max_colors = cinfo->desired_number_of_colors; - int total_colors, iroot, i, j; - boolean changed; - long temp; - static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; - - /* We can allocate at least the nc'th root of max_colors per component. */ - /* Compute floor(nc'th root of max_colors). */ - iroot = 1; - do { - iroot++; - temp = iroot; /* set temp = iroot ** nc */ - for (i = 1; i < nc; i++) - temp *= iroot; - } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ - iroot--; /* now iroot = floor(root) */ - - /* Must have at least 2 color values per component */ - if (iroot < 2) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); - - /* Initialize to iroot color values for each component */ - total_colors = 1; - for (i = 0; i < nc; i++) { - Ncolors[i] = iroot; - total_colors *= iroot; - } - /* We may be able to increment the count for one or more components without - * exceeding max_colors, though we know not all can be incremented. - * Sometimes, the first component can be incremented more than once! - * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) - * In RGB colorspace, try to increment G first, then R, then B. - */ - do { - changed = FALSE; - for (i = 0; i < nc; i++) { - j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); - /* calculate new total_colors if Ncolors[j] is incremented */ - temp = total_colors / Ncolors[j]; - temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ - if (temp > (long) max_colors) - break; /* won't fit, done with this pass */ - Ncolors[j]++; /* OK, apply the increment */ - total_colors = (int) temp; - changed = TRUE; - } - } while (changed); - - return total_colors; -} - - -LOCAL(int) -output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) -/* Return j'th output value, where j will range from 0 to maxj */ -/* The output values must fall in 0..MAXJSAMPLE in increasing order */ -{ - /* We always provide values 0 and MAXJSAMPLE for each component; - * any additional values are equally spaced between these limits. - * (Forcing the upper and lower values to the limits ensures that - * dithering can't produce a color outside the selected gamut.) - */ - return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); -} - - -LOCAL(int) -largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) -/* Return largest input value that should map to j'th output value */ -/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ -{ - /* Breakpoints are halfway between values returned by output_value */ - return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); -} - - -/* - * Create the colormap. - */ - -LOCAL(void) -create_colormap (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - JSAMPARRAY colormap; /* Created colormap */ - int total_colors; /* Number of distinct output colors */ - int i,j,k, nci, blksize, blkdist, ptr, val; - - /* Select number of colors for each component */ - total_colors = select_ncolors(cinfo, cquantize->Ncolors); - - /* Report selected color counts */ - if (cinfo->out_color_components == 3) - TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, - total_colors, cquantize->Ncolors[0], - cquantize->Ncolors[1], cquantize->Ncolors[2]); - else - TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); - - /* Allocate and fill in the colormap. */ - /* The colors are ordered in the map in standard row-major order, */ - /* i.e. rightmost (highest-indexed) color changes most rapidly. */ - - colormap = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); - - /* blksize is number of adjacent repeated entries for a component */ - /* blkdist is distance between groups of identical entries for a component */ - blkdist = total_colors; - - for (i = 0; i < cinfo->out_color_components; i++) { - /* fill in colormap entries for i'th color component */ - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - blksize = blkdist / nci; - for (j = 0; j < nci; j++) { - /* Compute j'th output value (out of nci) for component */ - val = output_value(cinfo, i, j, nci-1); - /* Fill in all colormap entries that have this value of this component */ - for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { - /* fill in blksize entries beginning at ptr */ - for (k = 0; k < blksize; k++) - colormap[i][ptr+k] = (JSAMPLE) val; - } - } - blkdist = blksize; /* blksize of this color is blkdist of next */ - } - - /* Save the colormap in private storage, - * where it will survive color quantization mode changes. - */ - cquantize->sv_colormap = colormap; - cquantize->sv_actual = total_colors; -} - - -/* - * Create the color index table. - */ - -LOCAL(void) -create_colorindex (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - JSAMPROW indexptr; - int i,j,k, nci, blksize, val, pad; - - /* For ordered dither, we pad the color index tables by MAXJSAMPLE in - * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). - * This is not necessary in the other dithering modes. However, we - * flag whether it was done in case user changes dithering mode. - */ - if (cinfo->dither_mode == JDITHER_ORDERED) { - pad = MAXJSAMPLE*2; - cquantize->is_padded = TRUE; - } else { - pad = 0; - cquantize->is_padded = FALSE; - } - - cquantize->colorindex = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (MAXJSAMPLE+1 + pad), - (JDIMENSION) cinfo->out_color_components); - - /* blksize is number of adjacent repeated entries for a component */ - blksize = cquantize->sv_actual; - - for (i = 0; i < cinfo->out_color_components; i++) { - /* fill in colorindex entries for i'th color component */ - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - blksize = blksize / nci; - - /* adjust colorindex pointers to provide padding at negative indexes. */ - if (pad) - cquantize->colorindex[i] += MAXJSAMPLE; - - /* in loop, val = index of current output value, */ - /* and k = largest j that maps to current val */ - indexptr = cquantize->colorindex[i]; - val = 0; - k = largest_input_value(cinfo, i, 0, nci-1); - for (j = 0; j <= MAXJSAMPLE; j++) { - while (j > k) /* advance val if past boundary */ - k = largest_input_value(cinfo, i, ++val, nci-1); - /* premultiply so that no multiplication needed in main processing */ - indexptr[j] = (JSAMPLE) (val * blksize); - } - /* Pad at both ends if necessary */ - if (pad) - for (j = 1; j <= MAXJSAMPLE; j++) { - indexptr[-j] = indexptr[0]; - indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; - } - } -} - - -/* - * Create an ordered-dither array for a component having ncolors - * distinct output values. - */ - -LOCAL(ODITHER_MATRIX_PTR) -make_odither_array (j_decompress_ptr cinfo, int ncolors) -{ - ODITHER_MATRIX_PTR odither; - int j,k; - INT32 num,den; - - odither = (ODITHER_MATRIX_PTR) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(ODITHER_MATRIX)); - /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). - * Hence the dither value for the matrix cell with fill order f - * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). - * On 16-bit-int machine, be careful to avoid overflow. - */ - den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); - for (j = 0; j < ODITHER_SIZE; j++) { - for (k = 0; k < ODITHER_SIZE; k++) { - num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) - * MAXJSAMPLE; - /* Ensure round towards zero despite C's lack of consistency - * about rounding negative values in integer division... - */ - odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); - } - } - return odither; -} - - -/* - * Create the ordered-dither tables. - * Components having the same number of representative colors may - * share a dither table. - */ - -LOCAL(void) -create_odither_tables (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - ODITHER_MATRIX_PTR odither; - int i, j, nci; - - for (i = 0; i < cinfo->out_color_components; i++) { - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - odither = NULL; /* search for matching prior component */ - for (j = 0; j < i; j++) { - if (nci == cquantize->Ncolors[j]) { - odither = cquantize->odither[j]; - break; - } - } - if (odither == NULL) /* need a new table? */ - odither = make_odither_array(cinfo, nci); - cquantize->odither[i] = odither; - } -} - - -/* - * Map some rows of pixels to the output colormapped representation. - */ - -METHODDEF(void) -color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* General case, no dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - JSAMPARRAY colorindex = cquantize->colorindex; - register int pixcode, ci; - register JSAMPROW ptrin, ptrout; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - register int nc = cinfo->out_color_components; - - for (row = 0; row < num_rows; row++) { - ptrin = input_buf[row]; - ptrout = output_buf[row]; - for (col = width; col > 0; col--) { - pixcode = 0; - for (ci = 0; ci < nc; ci++) { - pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); - } - *ptrout++ = (JSAMPLE) pixcode; - } - } -} - - -METHODDEF(void) -color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* Fast path for out_color_components==3, no dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register int pixcode; - register JSAMPROW ptrin, ptrout; - JSAMPROW colorindex0 = cquantize->colorindex[0]; - JSAMPROW colorindex1 = cquantize->colorindex[1]; - JSAMPROW colorindex2 = cquantize->colorindex[2]; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - ptrin = input_buf[row]; - ptrout = output_buf[row]; - for (col = width; col > 0; col--) { - pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); - pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); - pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); - *ptrout++ = (JSAMPLE) pixcode; - } - } -} - - -METHODDEF(void) -quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* General case, with ordered dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex_ci; - int * dither; /* points to active row of dither matrix */ - int row_index, col_index; /* current indexes into dither matrix */ - int nc = cinfo->out_color_components; - int ci; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - /* Initialize output values to 0 so can process components separately */ - FMEMZERO((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); - row_index = cquantize->row_index; - for (ci = 0; ci < nc; ci++) { - input_ptr = input_buf[row] + ci; - output_ptr = output_buf[row]; - colorindex_ci = cquantize->colorindex[ci]; - dither = cquantize->odither[ci][row_index]; - col_index = 0; - - for (col = width; col > 0; col--) { - /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, - * select output value, accumulate into output code for this pixel. - * Range-limiting need not be done explicitly, as we have extended - * the colorindex table to produce the right answers for out-of-range - * inputs. The maximum dither is +- MAXJSAMPLE; this sets the - * required amount of padding. - */ - *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; - input_ptr += nc; - output_ptr++; - col_index = (col_index + 1) & ODITHER_MASK; - } - } - /* Advance row index for next row */ - row_index = (row_index + 1) & ODITHER_MASK; - cquantize->row_index = row_index; - } -} - - -METHODDEF(void) -quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* Fast path for out_color_components==3, with ordered dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register int pixcode; - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex0 = cquantize->colorindex[0]; - JSAMPROW colorindex1 = cquantize->colorindex[1]; - JSAMPROW colorindex2 = cquantize->colorindex[2]; - int * dither0; /* points to active row of dither matrix */ - int * dither1; - int * dither2; - int row_index, col_index; /* current indexes into dither matrix */ - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - row_index = cquantize->row_index; - input_ptr = input_buf[row]; - output_ptr = output_buf[row]; - dither0 = cquantize->odither[0][row_index]; - dither1 = cquantize->odither[1][row_index]; - dither2 = cquantize->odither[2][row_index]; - col_index = 0; - - for (col = width; col > 0; col--) { - pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + - dither0[col_index]]); - pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + - dither1[col_index]]); - pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + - dither2[col_index]]); - *output_ptr++ = (JSAMPLE) pixcode; - col_index = (col_index + 1) & ODITHER_MASK; - } - row_index = (row_index + 1) & ODITHER_MASK; - cquantize->row_index = row_index; - } -} - - -METHODDEF(void) -quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* General case, with Floyd-Steinberg dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register LOCFSERROR cur; /* current error or pixel value */ - LOCFSERROR belowerr; /* error for pixel below cur */ - LOCFSERROR bpreverr; /* error for below/prev col */ - LOCFSERROR bnexterr; /* error for below/next col */ - LOCFSERROR delta; - register FSERRPTR errorptr; /* => fserrors[] at column before current */ - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex_ci; - JSAMPROW colormap_ci; - int pixcode; - int nc = cinfo->out_color_components; - int dir; /* 1 for left-to-right, -1 for right-to-left */ - int dirnc; /* dir * nc */ - int ci; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; - SHIFT_TEMPS - - for (row = 0; row < num_rows; row++) { - /* Initialize output values to 0 so can process components separately */ - FMEMZERO((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); - for (ci = 0; ci < nc; ci++) { - input_ptr = input_buf[row] + ci; - output_ptr = output_buf[row]; - if (cquantize->on_odd_row) { - /* work right to left in this row */ - input_ptr += (width-1) * nc; /* so point to rightmost pixel */ - output_ptr += width-1; - dir = -1; - dirnc = -nc; - errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ - } else { - /* work left to right in this row */ - dir = 1; - dirnc = nc; - errorptr = cquantize->fserrors[ci]; /* => entry before first column */ - } - colorindex_ci = cquantize->colorindex[ci]; - colormap_ci = cquantize->sv_colormap[ci]; - /* Preset error values: no error propagated to first pixel from left */ - cur = 0; - /* and no error propagated to row below yet */ - belowerr = bpreverr = 0; - - for (col = width; col > 0; col--) { - /* cur holds the error propagated from the previous pixel on the - * current line. Add the error propagated from the previous line - * to form the complete error correction term for this pixel, and - * round the error term (which is expressed * 16) to an integer. - * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. - * Note: errorptr points to *previous* column's array entry. - */ - cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE; this sets the required size - * of the range_limit array. - */ - cur += GETJSAMPLE(*input_ptr); - cur = GETJSAMPLE(range_limit[cur]); - /* Select output value, accumulate into output code for this pixel */ - pixcode = GETJSAMPLE(colorindex_ci[cur]); - *output_ptr += (JSAMPLE) pixcode; - /* Compute actual representation error at this pixel */ - /* Note: we can do this even though we don't have the final */ - /* pixel code, because the colormap is orthogonal. */ - cur -= GETJSAMPLE(colormap_ci[pixcode]); - /* Compute error fractions to be propagated to adjacent pixels. - * Add these into the running sums, and simultaneously shift the - * next-line error sums left by 1 column. - */ - bnexterr = cur; - delta = cur * 2; - cur += delta; /* form error * 3 */ - errorptr[0] = (FSERROR) (bpreverr + cur); - cur += delta; /* form error * 5 */ - bpreverr = belowerr + cur; - belowerr = bnexterr; - cur += delta; /* form error * 7 */ - /* At this point cur contains the 7/16 error value to be propagated - * to the next pixel on the current line, and all the errors for the - * next line have been shifted over. We are therefore ready to move on. - */ - input_ptr += dirnc; /* advance input ptr to next column */ - output_ptr += dir; /* advance output ptr to next column */ - errorptr += dir; /* advance errorptr to current column */ - } - /* Post-loop cleanup: we must unload the final error value into the - * final fserrors[] entry. Note we need not unload belowerr because - * it is for the dummy column before or after the actual array. - */ - errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ - } - cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); - } -} - - -/* - * Allocate workspace for Floyd-Steinberg errors. - */ - -LOCAL(void) -alloc_fs_workspace (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - size_t arraysize; - int i; - - arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); - for (i = 0; i < cinfo->out_color_components; i++) { - cquantize->fserrors[i] = (FSERRPTR) - (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); - } -} - - -/* - * Initialize for one-pass color quantization. - */ - -METHODDEF(void) -start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - size_t arraysize; - int i; - - /* Install my colormap. */ - cinfo->colormap = cquantize->sv_colormap; - cinfo->actual_number_of_colors = cquantize->sv_actual; - - /* Initialize for desired dithering mode. */ - switch (cinfo->dither_mode) { - case JDITHER_NONE: - if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = color_quantize3; - else - cquantize->pub.color_quantize = color_quantize; - break; - case JDITHER_ORDERED: - if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = quantize3_ord_dither; - else - cquantize->pub.color_quantize = quantize_ord_dither; - cquantize->row_index = 0; /* initialize state for ordered dither */ - /* If user changed to ordered dither from another mode, - * we must recreate the color index table with padding. - * This will cost extra space, but probably isn't very likely. - */ - if (! cquantize->is_padded) - create_colorindex(cinfo); - /* Create ordered-dither tables if we didn't already. */ - if (cquantize->odither[0] == NULL) - create_odither_tables(cinfo); - break; - case JDITHER_FS: - cquantize->pub.color_quantize = quantize_fs_dither; - cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ - /* Allocate Floyd-Steinberg workspace if didn't already. */ - if (cquantize->fserrors[0] == NULL) - alloc_fs_workspace(cinfo); - /* Initialize the propagated errors to zero. */ - arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); - for (i = 0; i < cinfo->out_color_components; i++) - FMEMZERO((void FAR *) cquantize->fserrors[i], arraysize); - break; - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } -} - - -/* - * Finish up at the end of the pass. - */ - -METHODDEF(void) -finish_pass_1_quant (j_decompress_ptr cinfo) -{ - /* no work in 1-pass case */ -} - - -/* - * Switch to a new external colormap between output passes. - * Shouldn't get to this module! - */ - -METHODDEF(void) -new_color_map_1_quant (j_decompress_ptr cinfo) -{ - ERREXIT(cinfo, JERR_MODE_CHANGE); -} - - -/* - * Module initialization routine for 1-pass color quantization. - */ - -GLOBAL(void) -jinit_1pass_quantizer (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize; - - cquantize = (my_cquantize_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_cquantizer)); - cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; - cquantize->pub.start_pass = start_pass_1_quant; - cquantize->pub.finish_pass = finish_pass_1_quant; - cquantize->pub.new_color_map = new_color_map_1_quant; - cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ - cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ - - /* Make sure my internal arrays won't overflow */ - if (cinfo->out_color_components > MAX_Q_COMPS) - ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); - /* Make sure colormap indexes can be represented by JSAMPLEs */ - if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); - - /* Create the colormap and color index table. */ - create_colormap(cinfo); - create_colorindex(cinfo); - - /* Allocate Floyd-Steinberg workspace now if requested. - * We do this now since it is FAR storage and may affect the memory - * manager's space calculations. If the user changes to FS dither - * mode in a later pass, we will allocate the space then, and will - * possibly overrun the max_memory_to_use setting. - */ - if (cinfo->dither_mode == JDITHER_FS) - alloc_fs_workspace(cinfo); -} - -#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/libraries/jpeg/jquant2.c b/libraries/jpeg/jquant2.c deleted file mode 100644 index 38fc2af7a5..0000000000 --- a/libraries/jpeg/jquant2.c +++ /dev/null @@ -1,1311 +0,0 @@ -/* - * jquant2.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2011 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains 2-pass color quantization (color mapping) routines. - * These routines provide selection of a custom color map for an image, - * followed by mapping of the image to that color map, with optional - * Floyd-Steinberg dithering. - * It is also possible to use just the second pass to map to an arbitrary - * externally-given color map. - * - * Note: ordered dithering is not supported, since there isn't any fast - * way to compute intercolor distances; it's unclear that ordered dither's - * fundamental assumptions even hold with an irregularly spaced color map. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -#ifdef QUANT_2PASS_SUPPORTED - - -/* - * This module implements the well-known Heckbert paradigm for color - * quantization. Most of the ideas used here can be traced back to - * Heckbert's seminal paper - * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", - * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. - * - * In the first pass over the image, we accumulate a histogram showing the - * usage count of each possible color. To keep the histogram to a reasonable - * size, we reduce the precision of the input; typical practice is to retain - * 5 or 6 bits per color, so that 8 or 4 different input values are counted - * in the same histogram cell. - * - * Next, the color-selection step begins with a box representing the whole - * color space, and repeatedly splits the "largest" remaining box until we - * have as many boxes as desired colors. Then the mean color in each - * remaining box becomes one of the possible output colors. - * - * The second pass over the image maps each input pixel to the closest output - * color (optionally after applying a Floyd-Steinberg dithering correction). - * This mapping is logically trivial, but making it go fast enough requires - * considerable care. - * - * Heckbert-style quantizers vary a good deal in their policies for choosing - * the "largest" box and deciding where to cut it. The particular policies - * used here have proved out well in experimental comparisons, but better ones - * may yet be found. - * - * In earlier versions of the IJG code, this module quantized in YCbCr color - * space, processing the raw upsampled data without a color conversion step. - * This allowed the color conversion math to be done only once per colormap - * entry, not once per pixel. However, that optimization precluded other - * useful optimizations (such as merging color conversion with upsampling) - * and it also interfered with desired capabilities such as quantizing to an - * externally-supplied colormap. We have therefore abandoned that approach. - * The present code works in the post-conversion color space, typically RGB. - * - * To improve the visual quality of the results, we actually work in scaled - * RGB space, giving G distances more weight than R, and R in turn more than - * B. To do everything in integer math, we must use integer scale factors. - * The 2/3/1 scale factors used here correspond loosely to the relative - * weights of the colors in the NTSC grayscale equation. - * If you want to use this code to quantize a non-RGB color space, you'll - * probably need to change these scale factors. - */ - -#define R_SCALE 2 /* scale R distances by this much */ -#define G_SCALE 3 /* scale G distances by this much */ -#define B_SCALE 1 /* and B by this much */ - -/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined - * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B - * and B,G,R orders. If you define some other weird order in jmorecfg.h, - * you'll get compile errors until you extend this logic. In that case - * you'll probably want to tweak the histogram sizes too. - */ - -#if RGB_RED == 0 -#define C0_SCALE R_SCALE -#endif -#if RGB_BLUE == 0 -#define C0_SCALE B_SCALE -#endif -#if RGB_GREEN == 1 -#define C1_SCALE G_SCALE -#endif -#if RGB_RED == 2 -#define C2_SCALE R_SCALE -#endif -#if RGB_BLUE == 2 -#define C2_SCALE B_SCALE -#endif - - -/* - * First we have the histogram data structure and routines for creating it. - * - * The number of bits of precision can be adjusted by changing these symbols. - * We recommend keeping 6 bits for G and 5 each for R and B. - * If you have plenty of memory and cycles, 6 bits all around gives marginally - * better results; if you are short of memory, 5 bits all around will save - * some space but degrade the results. - * To maintain a fully accurate histogram, we'd need to allocate a "long" - * (preferably unsigned long) for each cell. In practice this is overkill; - * we can get by with 16 bits per cell. Few of the cell counts will overflow, - * and clamping those that do overflow to the maximum value will give close- - * enough results. This reduces the recommended histogram size from 256Kb - * to 128Kb, which is a useful savings on PC-class machines. - * (In the second pass the histogram space is re-used for pixel mapping data; - * in that capacity, each cell must be able to store zero to the number of - * desired colors. 16 bits/cell is plenty for that too.) - * Since the JPEG code is intended to run in small memory model on 80x86 - * machines, we can't just allocate the histogram in one chunk. Instead - * of a true 3-D array, we use a row of pointers to 2-D arrays. Each - * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and - * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that - * on 80x86 machines, the pointer row is in near memory but the actual - * arrays are in far memory (same arrangement as we use for image arrays). - */ - -#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ - -/* These will do the right thing for either R,G,B or B,G,R color order, - * but you may not like the results for other color orders. - */ -#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ -#define HIST_C1_BITS 6 /* bits of precision in G histogram */ -#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ - -/* Number of elements along histogram axes. */ -#define HIST_C0_ELEMS (1<cquantize; - register JSAMPROW ptr; - register histptr histp; - register hist3d histogram = cquantize->histogram; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - ptr = input_buf[row]; - for (col = width; col > 0; col--) { - /* get pixel value and index into the histogram */ - histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] - [GETJSAMPLE(ptr[1]) >> C1_SHIFT] - [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; - /* increment, check for overflow and undo increment if so. */ - if (++(*histp) <= 0) - (*histp)--; - ptr += 3; - } - } -} - - -/* - * Next we have the really interesting routines: selection of a colormap - * given the completed histogram. - * These routines work with a list of "boxes", each representing a rectangular - * subset of the input color space (to histogram precision). - */ - -typedef struct { - /* The bounds of the box (inclusive); expressed as histogram indexes */ - int c0min, c0max; - int c1min, c1max; - int c2min, c2max; - /* The volume (actually 2-norm) of the box */ - INT32 volume; - /* The number of nonzero histogram cells within this box */ - long colorcount; -} box; - -typedef box * boxptr; - - -LOCAL(boxptr) -find_biggest_color_pop (boxptr boxlist, int numboxes) -/* Find the splittable box with the largest color population */ -/* Returns NULL if no splittable boxes remain */ -{ - register boxptr boxp; - register int i; - register long maxc = 0; - boxptr which = NULL; - - for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { - if (boxp->colorcount > maxc && boxp->volume > 0) { - which = boxp; - maxc = boxp->colorcount; - } - } - return which; -} - - -LOCAL(boxptr) -find_biggest_volume (boxptr boxlist, int numboxes) -/* Find the splittable box with the largest (scaled) volume */ -/* Returns NULL if no splittable boxes remain */ -{ - register boxptr boxp; - register int i; - register INT32 maxv = 0; - boxptr which = NULL; - - for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { - if (boxp->volume > maxv) { - which = boxp; - maxv = boxp->volume; - } - } - return which; -} - - -LOCAL(void) -update_box (j_decompress_ptr cinfo, boxptr boxp) -/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ -/* and recompute its volume and population */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - histptr histp; - int c0,c1,c2; - int c0min,c0max,c1min,c1max,c2min,c2max; - INT32 dist0,dist1,dist2; - long ccount; - - c0min = boxp->c0min; c0max = boxp->c0max; - c1min = boxp->c1min; c1max = boxp->c1max; - c2min = boxp->c2min; c2max = boxp->c2max; - - if (c0max > c0min) - for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c0min = c0min = c0; - goto have_c0min; - } - } - have_c0min: - if (c0max > c0min) - for (c0 = c0max; c0 >= c0min; c0--) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c0max = c0max = c0; - goto have_c0max; - } - } - have_c0max: - if (c1max > c1min) - for (c1 = c1min; c1 <= c1max; c1++) - for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c1min = c1min = c1; - goto have_c1min; - } - } - have_c1min: - if (c1max > c1min) - for (c1 = c1max; c1 >= c1min; c1--) - for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c1max = c1max = c1; - goto have_c1max; - } - } - have_c1max: - if (c2max > c2min) - for (c2 = c2min; c2 <= c2max; c2++) - for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) - if (*histp != 0) { - boxp->c2min = c2min = c2; - goto have_c2min; - } - } - have_c2min: - if (c2max > c2min) - for (c2 = c2max; c2 >= c2min; c2--) - for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) - if (*histp != 0) { - boxp->c2max = c2max = c2; - goto have_c2max; - } - } - have_c2max: - - /* Update box volume. - * We use 2-norm rather than real volume here; this biases the method - * against making long narrow boxes, and it has the side benefit that - * a box is splittable iff norm > 0. - * Since the differences are expressed in histogram-cell units, - * we have to shift back to JSAMPLE units to get consistent distances; - * after which, we scale according to the selected distance scale factors. - */ - dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; - dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; - dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; - boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; - - /* Now scan remaining volume of box and compute population */ - ccount = 0; - for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++, histp++) - if (*histp != 0) { - ccount++; - } - } - boxp->colorcount = ccount; -} - - -LOCAL(int) -median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, - int desired_colors) -/* Repeatedly select and split the largest box until we have enough boxes */ -{ - int n,lb; - int c0,c1,c2,cmax; - register boxptr b1,b2; - - while (numboxes < desired_colors) { - /* Select box to split. - * Current algorithm: by population for first half, then by volume. - */ - if (numboxes*2 <= desired_colors) { - b1 = find_biggest_color_pop(boxlist, numboxes); - } else { - b1 = find_biggest_volume(boxlist, numboxes); - } - if (b1 == NULL) /* no splittable boxes left! */ - break; - b2 = &boxlist[numboxes]; /* where new box will go */ - /* Copy the color bounds to the new box. */ - b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; - b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; - /* Choose which axis to split the box on. - * Current algorithm: longest scaled axis. - * See notes in update_box about scaling distances. - */ - c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; - c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; - c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; - /* We want to break any ties in favor of green, then red, blue last. - * This code does the right thing for R,G,B or B,G,R color orders only. - */ -#if RGB_RED == 0 - cmax = c1; n = 1; - if (c0 > cmax) { cmax = c0; n = 0; } - if (c2 > cmax) { n = 2; } -#else - cmax = c1; n = 1; - if (c2 > cmax) { cmax = c2; n = 2; } - if (c0 > cmax) { n = 0; } -#endif - /* Choose split point along selected axis, and update box bounds. - * Current algorithm: split at halfway point. - * (Since the box has been shrunk to minimum volume, - * any split will produce two nonempty subboxes.) - * Note that lb value is max for lower box, so must be < old max. - */ - switch (n) { - case 0: - lb = (b1->c0max + b1->c0min) / 2; - b1->c0max = lb; - b2->c0min = lb+1; - break; - case 1: - lb = (b1->c1max + b1->c1min) / 2; - b1->c1max = lb; - b2->c1min = lb+1; - break; - case 2: - lb = (b1->c2max + b1->c2min) / 2; - b1->c2max = lb; - b2->c2min = lb+1; - break; - } - /* Update stats for boxes */ - update_box(cinfo, b1); - update_box(cinfo, b2); - numboxes++; - } - return numboxes; -} - - -LOCAL(void) -compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) -/* Compute representative color for a box, put it in colormap[icolor] */ -{ - /* Current algorithm: mean weighted by pixels (not colors) */ - /* Note it is important to get the rounding correct! */ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - histptr histp; - int c0,c1,c2; - int c0min,c0max,c1min,c1max,c2min,c2max; - long count; - long total = 0; - long c0total = 0; - long c1total = 0; - long c2total = 0; - - c0min = boxp->c0min; c0max = boxp->c0max; - c1min = boxp->c1min; c1max = boxp->c1max; - c2min = boxp->c2min; c2max = boxp->c2max; - - for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) { - if ((count = *histp++) != 0) { - total += count; - c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; - c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; - c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; - } - } - } - - cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); - cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); - cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); -} - - -LOCAL(void) -select_colors (j_decompress_ptr cinfo, int desired_colors) -/* Master routine for color selection */ -{ - boxptr boxlist; - int numboxes; - int i; - - /* Allocate workspace for box list */ - boxlist = (boxptr) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); - /* Initialize one box containing whole space */ - numboxes = 1; - boxlist[0].c0min = 0; - boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; - boxlist[0].c1min = 0; - boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; - boxlist[0].c2min = 0; - boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; - /* Shrink it to actually-used volume and set its statistics */ - update_box(cinfo, & boxlist[0]); - /* Perform median-cut to produce final box list */ - numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); - /* Compute the representative color for each box, fill colormap */ - for (i = 0; i < numboxes; i++) - compute_color(cinfo, & boxlist[i], i); - cinfo->actual_number_of_colors = numboxes; - TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); -} - - -/* - * These routines are concerned with the time-critical task of mapping input - * colors to the nearest color in the selected colormap. - * - * We re-use the histogram space as an "inverse color map", essentially a - * cache for the results of nearest-color searches. All colors within a - * histogram cell will be mapped to the same colormap entry, namely the one - * closest to the cell's center. This may not be quite the closest entry to - * the actual input color, but it's almost as good. A zero in the cache - * indicates we haven't found the nearest color for that cell yet; the array - * is cleared to zeroes before starting the mapping pass. When we find the - * nearest color for a cell, its colormap index plus one is recorded in the - * cache for future use. The pass2 scanning routines call fill_inverse_cmap - * when they need to use an unfilled entry in the cache. - * - * Our method of efficiently finding nearest colors is based on the "locally - * sorted search" idea described by Heckbert and on the incremental distance - * calculation described by Spencer W. Thomas in chapter III.1 of Graphics - * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that - * the distances from a given colormap entry to each cell of the histogram can - * be computed quickly using an incremental method: the differences between - * distances to adjacent cells themselves differ by a constant. This allows a - * fairly fast implementation of the "brute force" approach of computing the - * distance from every colormap entry to every histogram cell. Unfortunately, - * it needs a work array to hold the best-distance-so-far for each histogram - * cell (because the inner loop has to be over cells, not colormap entries). - * The work array elements have to be INT32s, so the work array would need - * 256Kb at our recommended precision. This is not feasible in DOS machines. - * - * To get around these problems, we apply Thomas' method to compute the - * nearest colors for only the cells within a small subbox of the histogram. - * The work array need be only as big as the subbox, so the memory usage - * problem is solved. Furthermore, we need not fill subboxes that are never - * referenced in pass2; many images use only part of the color gamut, so a - * fair amount of work is saved. An additional advantage of this - * approach is that we can apply Heckbert's locality criterion to quickly - * eliminate colormap entries that are far away from the subbox; typically - * three-fourths of the colormap entries are rejected by Heckbert's criterion, - * and we need not compute their distances to individual cells in the subbox. - * The speed of this approach is heavily influenced by the subbox size: too - * small means too much overhead, too big loses because Heckbert's criterion - * can't eliminate as many colormap entries. Empirically the best subbox - * size seems to be about 1/512th of the histogram (1/8th in each direction). - * - * Thomas' article also describes a refined method which is asymptotically - * faster than the brute-force method, but it is also far more complex and - * cannot efficiently be applied to small subboxes. It is therefore not - * useful for programs intended to be portable to DOS machines. On machines - * with plenty of memory, filling the whole histogram in one shot with Thomas' - * refined method might be faster than the present code --- but then again, - * it might not be any faster, and it's certainly more complicated. - */ - - -/* log2(histogram cells in update box) for each axis; this can be adjusted */ -#define BOX_C0_LOG (HIST_C0_BITS-3) -#define BOX_C1_LOG (HIST_C1_BITS-3) -#define BOX_C2_LOG (HIST_C2_BITS-3) - -#define BOX_C0_ELEMS (1<actual_number_of_colors; - int maxc0, maxc1, maxc2; - int centerc0, centerc1, centerc2; - int i, x, ncolors; - INT32 minmaxdist, min_dist, max_dist, tdist; - INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ - - /* Compute true coordinates of update box's upper corner and center. - * Actually we compute the coordinates of the center of the upper-corner - * histogram cell, which are the upper bounds of the volume we care about. - * Note that since ">>" rounds down, the "center" values may be closer to - * min than to max; hence comparisons to them must be "<=", not "<". - */ - maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); - centerc0 = (minc0 + maxc0) >> 1; - maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); - centerc1 = (minc1 + maxc1) >> 1; - maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); - centerc2 = (minc2 + maxc2) >> 1; - - /* For each color in colormap, find: - * 1. its minimum squared-distance to any point in the update box - * (zero if color is within update box); - * 2. its maximum squared-distance to any point in the update box. - * Both of these can be found by considering only the corners of the box. - * We save the minimum distance for each color in mindist[]; - * only the smallest maximum distance is of interest. - */ - minmaxdist = 0x7FFFFFFFL; - - for (i = 0; i < numcolors; i++) { - /* We compute the squared-c0-distance term, then add in the other two. */ - x = GETJSAMPLE(cinfo->colormap[0][i]); - if (x < minc0) { - tdist = (x - minc0) * C0_SCALE; - min_dist = tdist*tdist; - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist*tdist; - } else if (x > maxc0) { - tdist = (x - maxc0) * C0_SCALE; - min_dist = tdist*tdist; - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - min_dist = 0; - if (x <= centerc0) { - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist*tdist; - } else { - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist*tdist; - } - } - - x = GETJSAMPLE(cinfo->colormap[1][i]); - if (x < minc1) { - tdist = (x - minc1) * C1_SCALE; - min_dist += tdist*tdist; - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist*tdist; - } else if (x > maxc1) { - tdist = (x - maxc1) * C1_SCALE; - min_dist += tdist*tdist; - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - if (x <= centerc1) { - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist*tdist; - } else { - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist*tdist; - } - } - - x = GETJSAMPLE(cinfo->colormap[2][i]); - if (x < minc2) { - tdist = (x - minc2) * C2_SCALE; - min_dist += tdist*tdist; - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist*tdist; - } else if (x > maxc2) { - tdist = (x - maxc2) * C2_SCALE; - min_dist += tdist*tdist; - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - if (x <= centerc2) { - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist*tdist; - } else { - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist*tdist; - } - } - - mindist[i] = min_dist; /* save away the results */ - if (max_dist < minmaxdist) - minmaxdist = max_dist; - } - - /* Now we know that no cell in the update box is more than minmaxdist - * away from some colormap entry. Therefore, only colors that are - * within minmaxdist of some part of the box need be considered. - */ - ncolors = 0; - for (i = 0; i < numcolors; i++) { - if (mindist[i] <= minmaxdist) - colorlist[ncolors++] = (JSAMPLE) i; - } - return ncolors; -} - - -LOCAL(void) -find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) -/* Find the closest colormap entry for each cell in the update box, - * given the list of candidate colors prepared by find_nearby_colors. - * Return the indexes of the closest entries in the bestcolor[] array. - * This routine uses Thomas' incremental distance calculation method to - * find the distance from a colormap entry to successive cells in the box. - */ -{ - int ic0, ic1, ic2; - int i, icolor; - register INT32 * bptr; /* pointer into bestdist[] array */ - JSAMPLE * cptr; /* pointer into bestcolor[] array */ - INT32 dist0, dist1; /* initial distance values */ - register INT32 dist2; /* current distance in inner loop */ - INT32 xx0, xx1; /* distance increments */ - register INT32 xx2; - INT32 inc0, inc1, inc2; /* initial values for increments */ - /* This array holds the distance to the nearest-so-far color for each cell */ - INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; - - /* Initialize best-distance for each cell of the update box */ - bptr = bestdist; - for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) - *bptr++ = 0x7FFFFFFFL; - - /* For each color selected by find_nearby_colors, - * compute its distance to the center of each cell in the box. - * If that's less than best-so-far, update best distance and color number. - */ - - /* Nominal steps between cell centers ("x" in Thomas article) */ -#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) -#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) -#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) - - for (i = 0; i < numcolors; i++) { - icolor = GETJSAMPLE(colorlist[i]); - /* Compute (square of) distance from minc0/c1/c2 to this color */ - inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; - dist0 = inc0*inc0; - inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; - dist0 += inc1*inc1; - inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; - dist0 += inc2*inc2; - /* Form the initial difference increments */ - inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; - inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; - inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; - /* Now loop over all cells in box, updating distance per Thomas method */ - bptr = bestdist; - cptr = bestcolor; - xx0 = inc0; - for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { - dist1 = dist0; - xx1 = inc1; - for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { - dist2 = dist1; - xx2 = inc2; - for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { - if (dist2 < *bptr) { - *bptr = dist2; - *cptr = (JSAMPLE) icolor; - } - dist2 += xx2; - xx2 += 2 * STEP_C2 * STEP_C2; - bptr++; - cptr++; - } - dist1 += xx1; - xx1 += 2 * STEP_C1 * STEP_C1; - } - dist0 += xx0; - xx0 += 2 * STEP_C0 * STEP_C0; - } - } -} - - -LOCAL(void) -fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) -/* Fill the inverse-colormap entries in the update box that contains */ -/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ -/* we can fill as many others as we wish.) */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - int minc0, minc1, minc2; /* lower left corner of update box */ - int ic0, ic1, ic2; - register JSAMPLE * cptr; /* pointer into bestcolor[] array */ - register histptr cachep; /* pointer into main cache array */ - /* This array lists the candidate colormap indexes. */ - JSAMPLE colorlist[MAXNUMCOLORS]; - int numcolors; /* number of candidate colors */ - /* This array holds the actually closest colormap index for each cell. */ - JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; - - /* Convert cell coordinates to update box ID */ - c0 >>= BOX_C0_LOG; - c1 >>= BOX_C1_LOG; - c2 >>= BOX_C2_LOG; - - /* Compute true coordinates of update box's origin corner. - * Actually we compute the coordinates of the center of the corner - * histogram cell, which are the lower bounds of the volume we care about. - */ - minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); - minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); - minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); - - /* Determine which colormap entries are close enough to be candidates - * for the nearest entry to some cell in the update box. - */ - numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); - - /* Determine the actually nearest colors. */ - find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, - bestcolor); - - /* Save the best color numbers (plus 1) in the main cache array */ - c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ - c1 <<= BOX_C1_LOG; - c2 <<= BOX_C2_LOG; - cptr = bestcolor; - for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { - for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { - cachep = & histogram[c0+ic0][c1+ic1][c2]; - for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { - *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); - } - } - } -} - - -/* - * Map some rows of pixels to the output colormapped representation. - */ - -METHODDEF(void) -pass2_no_dither (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) -/* This version performs no dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - register JSAMPROW inptr, outptr; - register histptr cachep; - register int c0, c1, c2; - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - - for (row = 0; row < num_rows; row++) { - inptr = input_buf[row]; - outptr = output_buf[row]; - for (col = width; col > 0; col--) { - /* get pixel value and index into the cache */ - c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; - c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; - c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; - cachep = & histogram[c0][c1][c2]; - /* If we have not seen this color before, find nearest colormap entry */ - /* and update the cache */ - if (*cachep == 0) - fill_inverse_cmap(cinfo, c0,c1,c2); - /* Now emit the colormap index for this cell */ - *outptr++ = (JSAMPLE) (*cachep - 1); - } - } -} - - -METHODDEF(void) -pass2_fs_dither (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) -/* This version performs Floyd-Steinberg dithering */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ - LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ - LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ - register FSERRPTR errorptr; /* => fserrors[] at column before current */ - JSAMPROW inptr; /* => current input pixel */ - JSAMPROW outptr; /* => current output pixel */ - histptr cachep; - int dir; /* +1 or -1 depending on direction */ - int dir3; /* 3*dir, for advancing inptr & errorptr */ - int row; - JDIMENSION col; - JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; - int *error_limit = cquantize->error_limiter; - JSAMPROW colormap0 = cinfo->colormap[0]; - JSAMPROW colormap1 = cinfo->colormap[1]; - JSAMPROW colormap2 = cinfo->colormap[2]; - SHIFT_TEMPS - - for (row = 0; row < num_rows; row++) { - inptr = input_buf[row]; - outptr = output_buf[row]; - if (cquantize->on_odd_row) { - /* work right to left in this row */ - inptr += (width-1) * 3; /* so point to rightmost pixel */ - outptr += width-1; - dir = -1; - dir3 = -3; - errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ - cquantize->on_odd_row = FALSE; /* flip for next time */ - } else { - /* work left to right in this row */ - dir = 1; - dir3 = 3; - errorptr = cquantize->fserrors; /* => entry before first real column */ - cquantize->on_odd_row = TRUE; /* flip for next time */ - } - /* Preset error values: no error propagated to first pixel from left */ - cur0 = cur1 = cur2 = 0; - /* and no error propagated to row below yet */ - belowerr0 = belowerr1 = belowerr2 = 0; - bpreverr0 = bpreverr1 = bpreverr2 = 0; - - for (col = width; col > 0; col--) { - /* curN holds the error propagated from the previous pixel on the - * current line. Add the error propagated from the previous line - * to form the complete error correction term for this pixel, and - * round the error term (which is expressed * 16) to an integer. - * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. - * Note: errorptr points to *previous* column's array entry. - */ - cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); - cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); - cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); - /* Limit the error using transfer function set by init_error_limit. - * See comments with init_error_limit for rationale. - */ - cur0 = error_limit[cur0]; - cur1 = error_limit[cur1]; - cur2 = error_limit[cur2]; - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE (or less with error limiting); - * this sets the required size of the range_limit array. - */ - cur0 += GETJSAMPLE(inptr[0]); - cur1 += GETJSAMPLE(inptr[1]); - cur2 += GETJSAMPLE(inptr[2]); - cur0 = GETJSAMPLE(range_limit[cur0]); - cur1 = GETJSAMPLE(range_limit[cur1]); - cur2 = GETJSAMPLE(range_limit[cur2]); - /* Index into the cache with adjusted pixel value */ - cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; - /* If we have not seen this color before, find nearest colormap */ - /* entry and update the cache */ - if (*cachep == 0) - fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); - /* Now emit the colormap index for this cell */ - { register int pixcode = *cachep - 1; - *outptr = (JSAMPLE) pixcode; - /* Compute representation error for this pixel */ - cur0 -= GETJSAMPLE(colormap0[pixcode]); - cur1 -= GETJSAMPLE(colormap1[pixcode]); - cur2 -= GETJSAMPLE(colormap2[pixcode]); - } - /* Compute error fractions to be propagated to adjacent pixels. - * Add these into the running sums, and simultaneously shift the - * next-line error sums left by 1 column. - */ - { register LOCFSERROR bnexterr, delta; - - bnexterr = cur0; /* Process component 0 */ - delta = cur0 * 2; - cur0 += delta; /* form error * 3 */ - errorptr[0] = (FSERROR) (bpreverr0 + cur0); - cur0 += delta; /* form error * 5 */ - bpreverr0 = belowerr0 + cur0; - belowerr0 = bnexterr; - cur0 += delta; /* form error * 7 */ - bnexterr = cur1; /* Process component 1 */ - delta = cur1 * 2; - cur1 += delta; /* form error * 3 */ - errorptr[1] = (FSERROR) (bpreverr1 + cur1); - cur1 += delta; /* form error * 5 */ - bpreverr1 = belowerr1 + cur1; - belowerr1 = bnexterr; - cur1 += delta; /* form error * 7 */ - bnexterr = cur2; /* Process component 2 */ - delta = cur2 * 2; - cur2 += delta; /* form error * 3 */ - errorptr[2] = (FSERROR) (bpreverr2 + cur2); - cur2 += delta; /* form error * 5 */ - bpreverr2 = belowerr2 + cur2; - belowerr2 = bnexterr; - cur2 += delta; /* form error * 7 */ - } - /* At this point curN contains the 7/16 error value to be propagated - * to the next pixel on the current line, and all the errors for the - * next line have been shifted over. We are therefore ready to move on. - */ - inptr += dir3; /* Advance pixel pointers to next column */ - outptr += dir; - errorptr += dir3; /* advance errorptr to current column */ - } - /* Post-loop cleanup: we must unload the final error values into the - * final fserrors[] entry. Note we need not unload belowerrN because - * it is for the dummy column before or after the actual array. - */ - errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ - errorptr[1] = (FSERROR) bpreverr1; - errorptr[2] = (FSERROR) bpreverr2; - } -} - - -/* - * Initialize the error-limiting transfer function (lookup table). - * The raw F-S error computation can potentially compute error values of up to - * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be - * much less, otherwise obviously wrong pixels will be created. (Typical - * effects include weird fringes at color-area boundaries, isolated bright - * pixels in a dark area, etc.) The standard advice for avoiding this problem - * is to ensure that the "corners" of the color cube are allocated as output - * colors; then repeated errors in the same direction cannot cause cascading - * error buildup. However, that only prevents the error from getting - * completely out of hand; Aaron Giles reports that error limiting improves - * the results even with corner colors allocated. - * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty - * well, but the smoother transfer function used below is even better. Thanks - * to Aaron Giles for this idea. - */ - -LOCAL(void) -init_error_limit (j_decompress_ptr cinfo) -/* Allocate and fill in the error_limiter table */ -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - int * table; - int in, out; - - table = (int *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); - table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ - cquantize->error_limiter = table; - -#define STEPSIZE ((MAXJSAMPLE+1)/16) - /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ - out = 0; - for (in = 0; in < STEPSIZE; in++, out++) { - table[in] = out; table[-in] = -out; - } - /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ - for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { - table[in] = out; table[-in] = -out; - } - /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ - for (; in <= MAXJSAMPLE; in++) { - table[in] = out; table[-in] = -out; - } -#undef STEPSIZE -} - - -/* - * Finish up at the end of each pass. - */ - -METHODDEF(void) -finish_pass1 (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - - /* Select the representative colors and fill in cinfo->colormap */ - cinfo->colormap = cquantize->sv_colormap; - select_colors(cinfo, cquantize->desired); - /* Force next pass to zero the color index table */ - cquantize->needs_zeroed = TRUE; -} - - -METHODDEF(void) -finish_pass2 (j_decompress_ptr cinfo) -{ - /* no work */ -} - - -/* - * Initialize for each processing pass. - */ - -METHODDEF(void) -start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - int i; - - /* Only F-S dithering or no dithering is supported. */ - /* If user asks for ordered dither, give him F-S. */ - if (cinfo->dither_mode != JDITHER_NONE) - cinfo->dither_mode = JDITHER_FS; - - if (is_pre_scan) { - /* Set up method pointers */ - cquantize->pub.color_quantize = prescan_quantize; - cquantize->pub.finish_pass = finish_pass1; - cquantize->needs_zeroed = TRUE; /* Always zero histogram */ - } else { - /* Set up method pointers */ - if (cinfo->dither_mode == JDITHER_FS) - cquantize->pub.color_quantize = pass2_fs_dither; - else - cquantize->pub.color_quantize = pass2_no_dither; - cquantize->pub.finish_pass = finish_pass2; - - /* Make sure color count is acceptable */ - i = cinfo->actual_number_of_colors; - if (i < 1) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); - if (i > MAXNUMCOLORS) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - - if (cinfo->dither_mode == JDITHER_FS) { - size_t arraysize = (size_t) ((cinfo->output_width + 2) * - (3 * SIZEOF(FSERROR))); - /* Allocate Floyd-Steinberg workspace if we didn't already. */ - if (cquantize->fserrors == NULL) - cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); - /* Initialize the propagated errors to zero. */ - FMEMZERO((void FAR *) cquantize->fserrors, arraysize); - /* Make the error-limit table if we didn't already. */ - if (cquantize->error_limiter == NULL) - init_error_limit(cinfo); - cquantize->on_odd_row = FALSE; - } - - } - /* Zero the histogram or inverse color map, if necessary */ - if (cquantize->needs_zeroed) { - for (i = 0; i < HIST_C0_ELEMS; i++) { - FMEMZERO((void FAR *) histogram[i], - HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); - } - cquantize->needs_zeroed = FALSE; - } -} - - -/* - * Switch to a new external colormap between output passes. - */ - -METHODDEF(void) -new_color_map_2_quant (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - - /* Reset the inverse color map */ - cquantize->needs_zeroed = TRUE; -} - - -/* - * Module initialization routine for 2-pass color quantization. - */ - -GLOBAL(void) -jinit_2pass_quantizer (j_decompress_ptr cinfo) -{ - my_cquantize_ptr cquantize; - int i; - - cquantize = (my_cquantize_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_cquantizer)); - cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; - cquantize->pub.start_pass = start_pass_2_quant; - cquantize->pub.new_color_map = new_color_map_2_quant; - cquantize->fserrors = NULL; /* flag optional arrays not allocated */ - cquantize->error_limiter = NULL; - - /* Make sure jdmaster didn't give me a case I can't handle */ - if (cinfo->out_color_components != 3) - ERREXIT(cinfo, JERR_NOTIMPL); - - /* Allocate the histogram/inverse colormap storage */ - cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); - for (i = 0; i < HIST_C0_ELEMS; i++) { - cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); - } - cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ - - /* Allocate storage for the completed colormap, if required. - * We do this now since it is FAR storage and may affect - * the memory manager's space calculations. - */ - if (cinfo->enable_2pass_quant) { - /* Make sure color count is acceptable */ - int desired = cinfo->desired_number_of_colors; - /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ - if (desired < 8) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); - /* Make sure colormap indexes can be represented by JSAMPLEs */ - if (desired > MAXNUMCOLORS) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); - cquantize->desired = desired; - } else - cquantize->sv_colormap = NULL; - - /* Only F-S dithering or no dithering is supported. */ - /* If user asks for ordered dither, give him F-S. */ - if (cinfo->dither_mode != JDITHER_NONE) - cinfo->dither_mode = JDITHER_FS; - - /* Allocate Floyd-Steinberg workspace if necessary. - * This isn't really needed until pass 2, but again it is FAR storage. - * Although we will cope with a later change in dither_mode, - * we do not promise to honor max_memory_to_use if dither_mode changes. - */ - if (cinfo->dither_mode == JDITHER_FS) { - cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); - /* Might as well create the error-limiting table too. */ - init_error_limit(cinfo); - } -} - -#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/libraries/jpeg/jutils.c b/libraries/jpeg/jutils.c deleted file mode 100644 index 5b16b6d03c..0000000000 --- a/libraries/jpeg/jutils.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * jutils.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2009-2011 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains tables and miscellaneous utility routines needed - * for both compression and decompression. - * Note we prefix all global names with "j" to minimize conflicts with - * a surrounding application. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element - * of a DCT block read in natural order (left to right, top to bottom). - */ - -#if 0 /* This table is not actually needed in v6a */ - -const int jpeg_zigzag_order[DCTSIZE2] = { - 0, 1, 5, 6, 14, 15, 27, 28, - 2, 4, 7, 13, 16, 26, 29, 42, - 3, 8, 12, 17, 25, 30, 41, 43, - 9, 11, 18, 24, 31, 40, 44, 53, - 10, 19, 23, 32, 39, 45, 52, 54, - 20, 22, 33, 38, 46, 51, 55, 60, - 21, 34, 37, 47, 50, 56, 59, 61, - 35, 36, 48, 49, 57, 58, 62, 63 -}; - -#endif - -/* - * jpeg_natural_order[i] is the natural-order position of the i'th element - * of zigzag order. - * - * When reading corrupted data, the Huffman decoders could attempt - * to reference an entry beyond the end of this array (if the decoded - * zero run length reaches past the end of the block). To prevent - * wild stores without adding an inner-loop test, we put some extra - * "63"s after the real entries. This will cause the extra coefficient - * to be stored in location 63 of the block, not somewhere random. - * The worst case would be a run-length of 15, which means we need 16 - * fake entries. - */ - -const int jpeg_natural_order[DCTSIZE2+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order7[7*7+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 14, 21, 28, 35, - 42, 49, 50, 43, 36, 29, 22, 30, - 37, 44, 51, 52, 45, 38, 46, 53, - 54, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order6[6*6+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 41, 34, 27, - 20, 13, 21, 28, 35, 42, 43, 36, - 29, 37, 44, 45, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order5[5*5+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 12, - 19, 26, 33, 34, 27, 20, 28, 35, - 36, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order4[4*4+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 25, 18, 11, 19, 26, 27, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order3[3*3+16] = { - 0, 1, 8, 16, 9, 2, 10, 17, - 18, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order2[2*2+16] = { - 0, 1, 8, 9, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - - -/* - * Arithmetic utilities - */ - -GLOBAL(long) -jdiv_round_up (long a, long b) -/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ -/* Assumes a >= 0, b > 0 */ -{ - return (a + b - 1L) / b; -} - - -GLOBAL(long) -jround_up (long a, long b) -/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ -/* Assumes a >= 0, b > 0 */ -{ - a += b - 1L; - return a - (a % b); -} - - -/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays - * and coefficient-block arrays. This won't work on 80x86 because the arrays - * are FAR and we're assuming a small-pointer memory model. However, some - * DOS compilers provide far-pointer versions of memcpy() and memset() even - * in the small-model libraries. These will be used if USE_FMEM is defined. - * Otherwise, the routines below do it the hard way. (The performance cost - * is not all that great, because these routines aren't very heavily used.) - */ - -#ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */ -#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) -#else /* 80x86 case, define if we can */ -#ifdef USE_FMEM -#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) -#else -/* This function is for use by the FMEMZERO macro defined in jpegint.h. - * Do not call this function directly, use the FMEMZERO macro instead. - */ -GLOBAL(void) -jzero_far (void FAR * target, size_t bytestozero) -/* Zero out a chunk of FAR memory. */ -/* This might be sample-array data, block-array data, or alloc_large data. */ -{ - register char FAR * ptr = (char FAR *) target; - register size_t count; - - for (count = bytestozero; count > 0; count--) { - *ptr++ = 0; - } -} -#endif -#endif - - -GLOBAL(void) -jcopy_sample_rows (JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols) -/* Copy some rows of samples from one place to another. - * num_rows rows are copied from input_array[source_row++] - * to output_array[dest_row++]; these areas may overlap for duplication. - * The source and destination arrays must be at least as wide as num_cols. - */ -{ - register JSAMPROW inptr, outptr; -#ifdef FMEMCOPY - register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); -#else - register JDIMENSION count; -#endif - register int row; - - input_array += source_row; - output_array += dest_row; - - for (row = num_rows; row > 0; row--) { - inptr = *input_array++; - outptr = *output_array++; -#ifdef FMEMCOPY - FMEMCOPY(outptr, inptr, count); -#else - for (count = num_cols; count > 0; count--) - *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ -#endif - } -} - - -GLOBAL(void) -jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks) -/* Copy a row of coefficient blocks from one place to another. */ -{ -#ifdef FMEMCOPY - FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); -#else - register JCOEFPTR inptr, outptr; - register long count; - - inptr = (JCOEFPTR) input_row; - outptr = (JCOEFPTR) output_row; - for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { - *outptr++ = *inptr++; - } -#endif -} diff --git a/libraries/jpeg/jversion.h b/libraries/jpeg/jversion.h deleted file mode 100644 index d096384f7e..0000000000 --- a/libraries/jpeg/jversion.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * jversion.h - * - * Copyright (C) 1991-2018, Thomas G. Lane, Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains software version identification. - */ - - -#define JVERSION "9c 14-Jan-2018" - -#define JCOPYRIGHT "Copyright (C) 2018, Thomas G. Lane, Guido Vollbeding" diff --git a/libraries/lzma/C/7z.h b/libraries/lzma/C/7z.h index 304f75ffc5..9e27c01521 100644 --- a/libraries/lzma/C/7z.h +++ b/libraries/lzma/C/7z.h @@ -1,8 +1,8 @@ /* 7z.h -- 7z interface -2018-07-02 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __7Z_H -#define __7Z_H +#ifndef ZIP7_INC_7Z_H +#define ZIP7_INC_7Z_H #include "7zTypes.h" @@ -98,7 +98,7 @@ typedef struct UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex); SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, - ILookInStream *stream, UInt64 startPos, + ILookInStreamPtr stream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAllocPtr allocMain); @@ -174,7 +174,7 @@ UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 SRes SzArEx_Extract( const CSzArEx *db, - ILookInStream *inStream, + ILookInStreamPtr inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ @@ -196,7 +196,7 @@ SZ_ERROR_INPUT_EOF SZ_ERROR_FAIL */ -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, +SRes SzArEx_Open(CSzArEx *p, ILookInStreamPtr inStream, ISzAllocPtr allocMain, ISzAllocPtr allocTemp); EXTERN_C_END diff --git a/libraries/lzma/C/7zAlloc.c b/libraries/lzma/C/7zAlloc.c new file mode 100644 index 0000000000..2f0659af6f --- /dev/null +++ b/libraries/lzma/C/7zAlloc.c @@ -0,0 +1,89 @@ +/* 7zAlloc.c -- Allocation functions for 7z processing +2023-03-04 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zAlloc.h" + +/* #define SZ_ALLOC_DEBUG */ +/* use SZ_ALLOC_DEBUG to debug alloc/free operations */ + +#ifdef SZ_ALLOC_DEBUG + +/* +#ifdef _WIN32 +#include "7zWindows.h" +#endif +*/ + +#include +static int g_allocCount = 0; +static int g_allocCountTemp = 0; + +static void Print_Alloc(const char *s, size_t size, int *counter) +{ + const unsigned size2 = (unsigned)size; + fprintf(stderr, "\n%s count = %10d : %10u bytes; ", s, *counter, size2); + (*counter)++; +} +static void Print_Free(const char *s, int *counter) +{ + (*counter)--; + fprintf(stderr, "\n%s count = %10d", s, *counter); +} +#endif + +void *SzAlloc(ISzAllocPtr p, size_t size) +{ + UNUSED_VAR(p) + if (size == 0) + return 0; + #ifdef SZ_ALLOC_DEBUG + Print_Alloc("Alloc", size, &g_allocCount); + #endif + return malloc(size); +} + +void SzFree(ISzAllocPtr p, void *address) +{ + UNUSED_VAR(p) + #ifdef SZ_ALLOC_DEBUG + if (address) + Print_Free("Free ", &g_allocCount); + #endif + free(address); +} + +void *SzAllocTemp(ISzAllocPtr p, size_t size) +{ + UNUSED_VAR(p) + if (size == 0) + return 0; + #ifdef SZ_ALLOC_DEBUG + Print_Alloc("Alloc_temp", size, &g_allocCountTemp); + /* + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + */ + #endif + return malloc(size); +} + +void SzFreeTemp(ISzAllocPtr p, void *address) +{ + UNUSED_VAR(p) + #ifdef SZ_ALLOC_DEBUG + if (address) + Print_Free("Free_temp ", &g_allocCountTemp); + /* + #ifdef _WIN32 + HeapFree(GetProcessHeap(), 0, address); + return; + #endif + */ + #endif + free(address); +} diff --git a/libraries/lzma/C/7zAlloc.h b/libraries/lzma/C/7zAlloc.h new file mode 100644 index 0000000000..b2b8b0cdd9 --- /dev/null +++ b/libraries/lzma/C/7zAlloc.h @@ -0,0 +1,19 @@ +/* 7zAlloc.h -- Allocation functions +2023-03-04 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_7Z_ALLOC_H +#define ZIP7_INC_7Z_ALLOC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void *SzAlloc(ISzAllocPtr p, size_t size); +void SzFree(ISzAllocPtr p, void *address); + +void *SzAllocTemp(ISzAllocPtr p, size_t size); +void SzFreeTemp(ISzAllocPtr p, void *address); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/7zArcIn.c b/libraries/lzma/C/7zArcIn.c index 0d9dec41e5..43fa7c2145 100644 --- a/libraries/lzma/C/7zArcIn.c +++ b/libraries/lzma/C/7zArcIn.c @@ -1,5 +1,5 @@ /* 7zArcIn.c -- 7z Input functions -2021-02-09 : Igor Pavlov : Public domain */ +2023-05-11 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -10,10 +10,11 @@ #include "7zCrc.h" #include "CpuArch.h" -#define MY_ALLOC(T, p, size, alloc) { \ - if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } +#define MY_ALLOC(T, p, size, alloc) \ + { if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } -#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) } +#define MY_ALLOC_ZE(T, p, size, alloc) \ + { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) } #define MY_ALLOC_AND_CPY(to, size, from, alloc) \ { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); } @@ -58,7 +59,7 @@ enum EIdEnum const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; -#define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } +#define SzBitUi32s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; } static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) { @@ -69,8 +70,8 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) } else { - MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc); - MY_ALLOC(UInt32, p->Vals, num, alloc); + MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc) + MY_ALLOC(UInt32, p->Vals, num, alloc) } return SZ_OK; } @@ -81,7 +82,7 @@ static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; } -#define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } +#define SzBitUi64s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; } static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) { @@ -96,7 +97,7 @@ static void SzAr_Init(CSzAr *p) p->NumFolders = 0; p->PackPositions = NULL; - SzBitUi32s_Init(&p->FolderCRCs); + SzBitUi32s_INIT(&p->FolderCRCs) p->FoCodersOffsets = NULL; p->FoStartPackStreamIndex = NULL; @@ -142,11 +143,11 @@ void SzArEx_Init(CSzArEx *p) p->FileNameOffsets = NULL; p->FileNames = NULL; - SzBitUi32s_Init(&p->CRCs); - SzBitUi32s_Init(&p->Attribs); - // SzBitUi32s_Init(&p->Parents); - SzBitUi64s_Init(&p->MTime); - SzBitUi64s_Init(&p->CTime); + SzBitUi32s_INIT(&p->CRCs) + SzBitUi32s_INIT(&p->Attribs) + // SzBitUi32s_INIT(&p->Parents) + SzBitUi64s_INIT(&p->MTime) + SzBitUi64s_INIT(&p->CTime) } void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc) @@ -180,11 +181,20 @@ static int TestSignatureCandidate(const Byte *testBytes) return 1; } -#define SzData_Clear(p) { (p)->Data = NULL; (p)->Size = 0; } +#define SzData_CLEAR(p) { (p)->Data = NULL; (p)->Size = 0; } + +#define SZ_READ_BYTE_SD_NOCHECK(_sd_, dest) \ + (_sd_)->Size--; dest = *(_sd_)->Data++; + +#define SZ_READ_BYTE_SD(_sd_, dest) \ + if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; \ + SZ_READ_BYTE_SD_NOCHECK(_sd_, dest) -#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++; #define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest) -#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++; + +#define SZ_READ_BYTE_2(dest) \ + if (sd.Size == 0) return SZ_ERROR_ARCHIVE; \ + sd.Size--; dest = *sd.Data++; #define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } #define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } @@ -192,25 +202,25 @@ static int TestSignatureCandidate(const Byte *testBytes) #define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \ dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4); -static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) +static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte, mask; unsigned i; UInt32 v; - SZ_READ_BYTE(firstByte); + SZ_READ_BYTE(firstByte) if ((firstByte & 0x80) == 0) { *value = firstByte; return SZ_OK; } - SZ_READ_BYTE(v); + SZ_READ_BYTE(v) if ((firstByte & 0x40) == 0) { *value = (((UInt32)firstByte & 0x3F) << 8) | v; return SZ_OK; } - SZ_READ_BYTE(mask); + SZ_READ_BYTE(mask) *value = v | ((UInt32)mask << 8); mask = 0x20; for (i = 2; i < 8; i++) @@ -218,11 +228,11 @@ static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) Byte b; if ((firstByte & mask) == 0) { - UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1); + const UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1); *value |= (highPart << (8 * i)); return SZ_OK; } - SZ_READ_BYTE(b); + SZ_READ_BYTE(b) *value |= ((UInt64)b << (8 * i)); mask >>= 1; } @@ -230,7 +240,7 @@ static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) } -static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) +static Z7_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) { Byte firstByte; UInt64 value64; @@ -244,7 +254,7 @@ static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) sd->Size--; return SZ_OK; } - RINOK(ReadNumber(sd, &value64)); + RINOK(ReadNumber(sd, &value64)) if (value64 >= (UInt32)0x80000000 - 1) return SZ_ERROR_UNSUPPORTED; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4))) @@ -258,10 +268,10 @@ static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) static SRes SkipData(CSzData *sd) { UInt64 size; - RINOK(ReadNumber(sd, &size)); + RINOK(ReadNumber(sd, &size)) if (size > sd->Size) return SZ_ERROR_ARCHIVE; - SKIP_DATA(sd, size); + SKIP_DATA(sd, size) return SZ_OK; } @@ -270,22 +280,22 @@ static SRes WaitId(CSzData *sd, UInt32 id) for (;;) { UInt64 type; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) if (type == id) return SZ_OK; if (type == k7zIdEnd) return SZ_ERROR_ARCHIVE; - RINOK(SkipData(sd)); + RINOK(SkipData(sd)) } } static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v) { - UInt32 numBytes = (numItems + 7) >> 3; + const UInt32 numBytes = (numItems + 7) >> 3; if (numBytes > sd->Size) return SZ_ERROR_ARCHIVE; *v = sd->Data; - SKIP_DATA(sd, numBytes); + SKIP_DATA(sd, numBytes) return SZ_OK; } @@ -307,48 +317,48 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) return sum; } -static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc) +static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc) { Byte allAreDefined; Byte *v2; - UInt32 numBytes = (numItems + 7) >> 3; + const UInt32 numBytes = (numItems + 7) >> 3; *v = NULL; - SZ_READ_BYTE(allAreDefined); + SZ_READ_BYTE(allAreDefined) if (numBytes == 0) return SZ_OK; if (allAreDefined == 0) { if (numBytes > sd->Size) return SZ_ERROR_ARCHIVE; - MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc); - SKIP_DATA(sd, numBytes); + MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc) + SKIP_DATA(sd, numBytes) return SZ_OK; } - MY_ALLOC(Byte, *v, numBytes, alloc); + MY_ALLOC(Byte, *v, numBytes, alloc) v2 = *v; memset(v2, 0xFF, (size_t)numBytes); { - unsigned numBits = (unsigned)numItems & 7; + const unsigned numBits = (unsigned)numItems & 7; if (numBits != 0) v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); } return SZ_OK; } -static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) +static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) { UInt32 i; CSzData sd; UInt32 *vals; const Byte *defs; - MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc); + MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc) sd = *sd2; defs = crcs->Defs; vals = crcs->Vals; for (i = 0; i < numItems; i++) if (SzBitArray_Check(defs, i)) { - SZ_READ_32(vals[i]); + SZ_READ_32(vals[i]) } else vals[i] = 0; @@ -359,7 +369,7 @@ static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *c static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) { SzBitUi32s_Free(crcs, alloc); - RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)); + RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)) return ReadUi32s(sd, numItems, crcs, alloc); } @@ -367,36 +377,36 @@ static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) { Byte allAreDefined; UInt32 numDefined = numItems; - SZ_READ_BYTE(allAreDefined); + SZ_READ_BYTE(allAreDefined) if (!allAreDefined) { - size_t numBytes = (numItems + 7) >> 3; + const size_t numBytes = (numItems + 7) >> 3; if (numBytes > sd->Size) return SZ_ERROR_ARCHIVE; numDefined = CountDefinedBits(sd->Data, numItems); - SKIP_DATA(sd, numBytes); + SKIP_DATA(sd, numBytes) } if (numDefined > (sd->Size >> 2)) return SZ_ERROR_ARCHIVE; - SKIP_DATA(sd, (size_t)numDefined * 4); + SKIP_DATA(sd, (size_t)numDefined * 4) return SZ_OK; } static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) { - RINOK(SzReadNumber32(sd, &p->NumPackStreams)); + RINOK(SzReadNumber32(sd, &p->NumPackStreams)) - RINOK(WaitId(sd, k7zIdSize)); - MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc); + RINOK(WaitId(sd, k7zIdSize)) + MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc) { UInt64 sum = 0; UInt32 i; - UInt32 numPackStreams = p->NumPackStreams; + const UInt32 numPackStreams = p->NumPackStreams; for (i = 0; i < numPackStreams; i++) { UInt64 packSize; p->PackPositions[i] = sum; - RINOK(ReadNumber(sd, &packSize)); + RINOK(ReadNumber(sd, &packSize)) sum += packSize; if (sum < packSize) return SZ_ERROR_ARCHIVE; @@ -407,16 +417,16 @@ static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) for (;;) { UInt64 type; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { /* CRC of packed streams is unused now */ - RINOK(SkipBitUi32s(sd, p->NumPackStreams)); + RINOK(SkipBitUi32s(sd, p->NumPackStreams)) continue; } - RINOK(SkipData(sd)); + RINOK(SkipData(sd)) } } @@ -442,7 +452,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) f->NumPackStreams = 0; f->UnpackStream = 0; - RINOK(SzReadNumber32(sd, &numCoders)); + RINOK(SzReadNumber32(sd, &numCoders)) if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) return SZ_ERROR_UNSUPPORTED; @@ -453,7 +463,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) unsigned idSize, j; UInt64 id; - SZ_READ_BYTE(mainByte); + SZ_READ_BYTE(mainByte) if ((mainByte & 0xC0) != 0) return SZ_ERROR_UNSUPPORTED; @@ -481,12 +491,12 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) { UInt32 numStreams; - RINOK(SzReadNumber32(sd, &numStreams)); + RINOK(SzReadNumber32(sd, &numStreams)) if (numStreams > k_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; coder->NumStreams = (Byte)numStreams; - RINOK(SzReadNumber32(sd, &numStreams)); + RINOK(SzReadNumber32(sd, &numStreams)) if (numStreams != 1) return SZ_ERROR_UNSUPPORTED; } @@ -499,7 +509,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) if ((mainByte & 0x20) != 0) { UInt32 propsSize = 0; - RINOK(SzReadNumber32(sd, &propsSize)); + RINOK(SzReadNumber32(sd, &propsSize)) if (propsSize > sd->Size) return SZ_ERROR_ARCHIVE; if (propsSize >= 0x80) @@ -549,12 +559,12 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) { CSzBond *bp = f->Bonds + i; - RINOK(SzReadNumber32(sd, &bp->InIndex)); + RINOK(SzReadNumber32(sd, &bp->InIndex)) if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex]) return SZ_ERROR_ARCHIVE; streamUsed[bp->InIndex] = True; - RINOK(SzReadNumber32(sd, &bp->OutIndex)); + RINOK(SzReadNumber32(sd, &bp->OutIndex)) if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex]) return SZ_ERROR_ARCHIVE; coderUsed[bp->OutIndex] = True; @@ -584,7 +594,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) for (i = 0; i < numPackStreams; i++) { UInt32 index; - RINOK(SzReadNumber32(sd, &index)); + RINOK(SzReadNumber32(sd, &index)) if (index >= numInStreams || streamUsed[index]) return SZ_ERROR_ARCHIVE; streamUsed[index] = True; @@ -598,7 +608,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) } -static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) +static Z7_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) { CSzData sd; sd = *sd2; @@ -606,7 +616,7 @@ static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) { Byte firstByte, mask; unsigned i; - SZ_READ_BYTE_2(firstByte); + SZ_READ_BYTE_2(firstByte) if ((firstByte & 0x80) == 0) continue; if ((firstByte & 0x40) == 0) @@ -622,7 +632,7 @@ static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) mask >>= 1; if (i > sd.Size) return SZ_ERROR_ARCHIVE; - SKIP_DATA2(sd, i); + SKIP_DATA2(sd, i) } *sd2 = sd; return SZ_OK; @@ -645,30 +655,30 @@ static SRes ReadUnpackInfo(CSzAr *p, const Byte *startBufPtr; Byte external; - RINOK(WaitId(sd2, k7zIdFolder)); + RINOK(WaitId(sd2, k7zIdFolder)) - RINOK(SzReadNumber32(sd2, &numFolders)); + RINOK(SzReadNumber32(sd2, &numFolders)) if (numFolders > numFoldersMax) return SZ_ERROR_UNSUPPORTED; p->NumFolders = numFolders; - SZ_READ_BYTE_SD(sd2, external); + SZ_READ_BYTE_SD(sd2, external) if (external == 0) sd = *sd2; else { UInt32 index; - RINOK(SzReadNumber32(sd2, &index)); + RINOK(SzReadNumber32(sd2, &index)) if (index >= numTempBufs) return SZ_ERROR_ARCHIVE; sd.Data = tempBufs[index].data; sd.Size = tempBufs[index].size; } - MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc); - MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc); - MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc); - MY_ALLOC_ZE(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc); + MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc) + MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc) + MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc) + MY_ALLOC_ZE(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc) startBufPtr = sd.Data; @@ -681,7 +691,7 @@ static SRes ReadUnpackInfo(CSzAr *p, p->FoCodersOffsets[fo] = (size_t)(sd.Data - startBufPtr); - RINOK(SzReadNumber32(&sd, &numCoders)); + RINOK(SzReadNumber32(&sd, &numCoders)) if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) return SZ_ERROR_UNSUPPORTED; @@ -691,7 +701,7 @@ static SRes ReadUnpackInfo(CSzAr *p, unsigned idSize; UInt32 coderInStreams; - SZ_READ_BYTE_2(mainByte); + SZ_READ_BYTE_2(mainByte) if ((mainByte & 0xC0) != 0) return SZ_ERROR_UNSUPPORTED; idSize = (mainByte & 0xF); @@ -699,15 +709,15 @@ static SRes ReadUnpackInfo(CSzAr *p, return SZ_ERROR_UNSUPPORTED; if (idSize > sd.Size) return SZ_ERROR_ARCHIVE; - SKIP_DATA2(sd, idSize); + SKIP_DATA2(sd, idSize) coderInStreams = 1; if ((mainByte & 0x10) != 0) { UInt32 coderOutStreams; - RINOK(SzReadNumber32(&sd, &coderInStreams)); - RINOK(SzReadNumber32(&sd, &coderOutStreams)); + RINOK(SzReadNumber32(&sd, &coderInStreams)) + RINOK(SzReadNumber32(&sd, &coderOutStreams)) if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1) return SZ_ERROR_UNSUPPORTED; } @@ -717,10 +727,10 @@ static SRes ReadUnpackInfo(CSzAr *p, if ((mainByte & 0x20) != 0) { UInt32 propsSize; - RINOK(SzReadNumber32(&sd, &propsSize)); + RINOK(SzReadNumber32(&sd, &propsSize)) if (propsSize > sd.Size) return SZ_ERROR_ARCHIVE; - SKIP_DATA2(sd, propsSize); + SKIP_DATA2(sd, propsSize) } } @@ -734,7 +744,7 @@ static SRes ReadUnpackInfo(CSzAr *p, Byte coderUsed[k_Scan_NumCoders_MAX]; UInt32 i; - UInt32 numBonds = numCoders - 1; + const UInt32 numBonds = numCoders - 1; if (numInStreams < numBonds) return SZ_ERROR_ARCHIVE; @@ -750,12 +760,12 @@ static SRes ReadUnpackInfo(CSzAr *p, { UInt32 index; - RINOK(SzReadNumber32(&sd, &index)); + RINOK(SzReadNumber32(&sd, &index)) if (index >= numInStreams || streamUsed[index]) return SZ_ERROR_ARCHIVE; streamUsed[index] = True; - RINOK(SzReadNumber32(&sd, &index)); + RINOK(SzReadNumber32(&sd, &index)) if (index >= numCoders || coderUsed[index]) return SZ_ERROR_ARCHIVE; coderUsed[index] = True; @@ -767,7 +777,7 @@ static SRes ReadUnpackInfo(CSzAr *p, for (i = 0; i < numPackStreams; i++) { UInt32 index; - RINOK(SzReadNumber32(&sd, &index)); + RINOK(SzReadNumber32(&sd, &index)) if (index >= numInStreams || streamUsed[index]) return SZ_ERROR_ARCHIVE; streamUsed[index] = True; @@ -802,7 +812,7 @@ static SRes ReadUnpackInfo(CSzAr *p, const size_t dataSize = (size_t)(sd.Data - startBufPtr); p->FoStartPackStreamIndex[fo] = packStreamIndex; p->FoCodersOffsets[fo] = dataSize; - MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc); + MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc) } if (external != 0) @@ -812,21 +822,21 @@ static SRes ReadUnpackInfo(CSzAr *p, sd = *sd2; } - RINOK(WaitId(&sd, k7zIdCodersUnpackSize)); + RINOK(WaitId(&sd, k7zIdCodersUnpackSize)) - MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc); + MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc) { UInt32 i; for (i = 0; i < numCodersOutStreams; i++) { - RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)); + RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)) } } for (;;) { UInt64 type; - RINOK(ReadID(&sd, &type)); + RINOK(ReadID(&sd, &type)) if (type == k7zIdEnd) { *sd2 = sd; @@ -834,10 +844,10 @@ static SRes ReadUnpackInfo(CSzAr *p, } if (type == k7zIdCRC) { - RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)); + RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)) continue; } - RINOK(SkipData(&sd)); + RINOK(SkipData(&sd)) } } @@ -862,13 +872,13 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { UInt64 type = 0; UInt32 numSubDigests = 0; - UInt32 numFolders = p->NumFolders; + const UInt32 numFolders = p->NumFolders; UInt32 numUnpackStreams = numFolders; UInt32 numUnpackSizesInData = 0; for (;;) { - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) if (type == k7zIdNumUnpackStream) { UInt32 i; @@ -878,7 +888,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) for (i = 0; i < numFolders; i++) { UInt32 numStreams; - RINOK(SzReadNumber32(sd, &numStreams)); + RINOK(SzReadNumber32(sd, &numStreams)) if (numUnpackStreams > numUnpackStreams + numStreams) return SZ_ERROR_UNSUPPORTED; numUnpackStreams += numStreams; @@ -892,7 +902,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) } if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) break; - RINOK(SkipData(sd)); + RINOK(SkipData(sd)) } if (!ssi->sdNumSubStreams.Data) @@ -908,9 +918,9 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) if (type == k7zIdSize) { ssi->sdSizes.Data = sd->Data; - RINOK(SkipNumbers(sd, numUnpackSizesInData)); + RINOK(SkipNumbers(sd, numUnpackSizesInData)) ssi->sdSizes.Size = (size_t)(sd->Data - ssi->sdSizes.Data); - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) } for (;;) @@ -920,14 +930,14 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) if (type == k7zIdCRC) { ssi->sdCRCs.Data = sd->Data; - RINOK(SkipBitUi32s(sd, numSubDigests)); + RINOK(SkipBitUi32s(sd, numSubDigests)) ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data); } else { - RINOK(SkipData(sd)); + RINOK(SkipData(sd)) } - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) } } @@ -940,31 +950,31 @@ static SRes SzReadStreamsInfo(CSzAr *p, { UInt64 type; - SzData_Clear(&ssi->sdSizes); - SzData_Clear(&ssi->sdCRCs); - SzData_Clear(&ssi->sdNumSubStreams); + SzData_CLEAR(&ssi->sdSizes) + SzData_CLEAR(&ssi->sdCRCs) + SzData_CLEAR(&ssi->sdNumSubStreams) *dataOffset = 0; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) if (type == k7zIdPackInfo) { - RINOK(ReadNumber(sd, dataOffset)); + RINOK(ReadNumber(sd, dataOffset)) if (*dataOffset > p->RangeLimit) return SZ_ERROR_ARCHIVE; - RINOK(ReadPackInfo(p, sd, alloc)); + RINOK(ReadPackInfo(p, sd, alloc)) if (p->PackPositions[p->NumPackStreams] > p->RangeLimit - *dataOffset) return SZ_ERROR_ARCHIVE; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) } if (type == k7zIdUnpackInfo) { - RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc)); - RINOK(ReadID(sd, &type)); + RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc)) + RINOK(ReadID(sd, &type)) } if (type == k7zIdSubStreamsInfo) { - RINOK(ReadSubStreamsInfo(p, sd, ssi)); - RINOK(ReadID(sd, &type)); + RINOK(ReadSubStreamsInfo(p, sd, ssi)) + RINOK(ReadID(sd, &type)) } else { @@ -976,7 +986,7 @@ static SRes SzReadStreamsInfo(CSzAr *p, } static SRes SzReadAndDecodePackedStreams( - ILookInStream *inStream, + ILookInStreamPtr inStream, CSzData *sd, CBuf *tempBufs, UInt32 numFoldersMax, @@ -988,7 +998,7 @@ static SRes SzReadAndDecodePackedStreams( UInt32 fo; CSubStreamInfo ssi; - RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)); + RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)) dataStartPos += baseOffset; if (p->NumFolders == 0) @@ -1000,7 +1010,7 @@ static SRes SzReadAndDecodePackedStreams( for (fo = 0; fo < p->NumFolders; fo++) { CBuf *tempBuf = tempBufs + fo; - UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo); + const UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo); if ((size_t)unpackSize != unpackSize) return SZ_ERROR_MEM; if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp)) @@ -1010,8 +1020,8 @@ static SRes SzReadAndDecodePackedStreams( for (fo = 0; fo < p->NumFolders; fo++) { const CBuf *tempBuf = tempBufs + fo; - RINOK(LookInStream_SeekTo(inStream, dataStartPos)); - RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)); + RINOK(LookInStream_SeekTo(inStream, dataStartPos)) + RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)) } return SZ_OK; @@ -1046,7 +1056,7 @@ static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; } -static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, +static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, CSzData *sd2, const CBuf *tempBufs, UInt32 numTempBufs, ISzAllocPtr alloc) @@ -1057,22 +1067,22 @@ static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, Byte *defs; Byte external; - RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)); + RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)) - SZ_READ_BYTE_SD(sd2, external); + SZ_READ_BYTE_SD(sd2, external) if (external == 0) sd = *sd2; else { UInt32 index; - RINOK(SzReadNumber32(sd2, &index)); + RINOK(SzReadNumber32(sd2, &index)) if (index >= numTempBufs) return SZ_ERROR_ARCHIVE; sd.Data = tempBufs[index].data; sd.Size = tempBufs[index].size; } - MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc); + MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc) vals = p->Vals; defs = p->Defs; for (i = 0; i < num; i++) @@ -1082,7 +1092,7 @@ static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, return SZ_ERROR_ARCHIVE; vals[i].Low = GetUi32(sd.Data); vals[i].High = GetUi32(sd.Data + 4); - SKIP_DATA2(sd, 8); + SKIP_DATA2(sd, 8) } else vals[i].High = vals[i].Low = 0; @@ -1100,7 +1110,7 @@ static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, - ILookInStream *inStream, + ILookInStreamPtr inStream, CBuf *tempBufs, UInt32 *numTempBufs, ISzAllocPtr allocMain, ISzAllocPtr allocTemp @@ -1111,26 +1121,26 @@ static SRes SzReadHeader2( { UInt64 type; - SzData_Clear(&ssi.sdSizes); - SzData_Clear(&ssi.sdCRCs); - SzData_Clear(&ssi.sdNumSubStreams); + SzData_CLEAR(&ssi.sdSizes) + SzData_CLEAR(&ssi.sdCRCs) + SzData_CLEAR(&ssi.sdNumSubStreams) ssi.NumSubDigests = 0; ssi.NumTotalSubStreams = 0; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) if (type == k7zIdArchiveProperties) { for (;;) { UInt64 type2; - RINOK(ReadID(sd, &type2)); + RINOK(ReadID(sd, &type2)) if (type2 == k7zIdEnd) break; - RINOK(SkipData(sd)); + RINOK(SkipData(sd)) } - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) } if (type == k7zIdAdditionalStreamsInfo) @@ -1148,15 +1158,15 @@ static SRes SzReadHeader2( if (res != SZ_OK) return res; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs, - &p->dataPos, &ssi, allocMain)); + &p->dataPos, &ssi, allocMain)) p->dataPos += p->startPosAfterHeader; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) } if (type == k7zIdEnd) @@ -1174,23 +1184,23 @@ static SRes SzReadHeader2( const Byte *emptyStreams = NULL; const Byte *emptyFiles = NULL; - RINOK(SzReadNumber32(sd, &numFiles)); + RINOK(SzReadNumber32(sd, &numFiles)) p->NumFiles = numFiles; for (;;) { UInt64 type; UInt64 size; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) if (type == k7zIdEnd) break; - RINOK(ReadNumber(sd, &size)); + RINOK(ReadNumber(sd, &size)) if (size > sd->Size) return SZ_ERROR_ARCHIVE; if (type >= ((UInt32)1 << 8)) { - SKIP_DATA(sd, size); + SKIP_DATA(sd, size) } else switch ((unsigned)type) { @@ -1200,7 +1210,7 @@ static SRes SzReadHeader2( const Byte *namesData; Byte external; - SZ_READ_BYTE(external); + SZ_READ_BYTE(external) if (external == 0) { namesSize = (size_t)size - 1; @@ -1209,7 +1219,7 @@ static SRes SzReadHeader2( else { UInt32 index; - RINOK(SzReadNumber32(sd, &index)); + RINOK(SzReadNumber32(sd, &index)) if (index >= *numTempBufs) return SZ_ERROR_ARCHIVE; namesData = (tempBufs)[index].data; @@ -1218,25 +1228,25 @@ static SRes SzReadHeader2( if ((namesSize & 1) != 0) return SZ_ERROR_ARCHIVE; - MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); - MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain); + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain) + MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain) RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) if (external == 0) { - SKIP_DATA(sd, namesSize); + SKIP_DATA(sd, namesSize) } break; } case k7zIdEmptyStream: { - RINOK(RememberBitVector(sd, numFiles, &emptyStreams)); + RINOK(RememberBitVector(sd, numFiles, &emptyStreams)) numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); emptyFiles = NULL; break; } case k7zIdEmptyFile: { - RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)); + RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)) break; } case k7zIdWinAttrib: @@ -1245,22 +1255,22 @@ static SRes SzReadHeader2( CSzData sdSwitch; CSzData *sdPtr; SzBitUi32s_Free(&p->Attribs, allocMain); - RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)); + RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)) - SZ_READ_BYTE(external); + SZ_READ_BYTE(external) if (external == 0) sdPtr = sd; else { UInt32 index; - RINOK(SzReadNumber32(sd, &index)); + RINOK(SzReadNumber32(sd, &index)) if (index >= *numTempBufs) return SZ_ERROR_ARCHIVE; sdSwitch.Data = (tempBufs)[index].data; sdSwitch.Size = (tempBufs)[index].size; sdPtr = &sdSwitch; } - RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)); + RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)) break; } /* @@ -1273,11 +1283,11 @@ static SRes SzReadHeader2( break; } */ - case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; - case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break; + case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break; default: { - SKIP_DATA(sd, size); + SKIP_DATA(sd, size) } } } @@ -1288,10 +1298,10 @@ static SRes SzReadHeader2( for (;;) { UInt64 type; - RINOK(ReadID(sd, &type)); + RINOK(ReadID(sd, &type)) if (type == k7zIdEnd) break; - RINOK(SkipData(sd)); + RINOK(SkipData(sd)) } { @@ -1303,40 +1313,37 @@ static SRes SzReadHeader2( UInt64 unpackPos = 0; const Byte *digestsDefs = NULL; const Byte *digestsVals = NULL; - UInt32 digestsValsIndex = 0; - UInt32 digestIndex; - Byte allDigestsDefined = 0; + UInt32 digestIndex = 0; Byte isDirMask = 0; Byte crcMask = 0; Byte mask = 0x80; - MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain); - MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain); - MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain); - MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain); + MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain) + MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain) + MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain) + MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain) - RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain)); + RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain)) if (ssi.sdCRCs.Size != 0) { - SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined); + Byte allDigestsDefined = 0; + SZ_READ_BYTE_SD_NOCHECK(&ssi.sdCRCs, allDigestsDefined) if (allDigestsDefined) digestsVals = ssi.sdCRCs.Data; else { - size_t numBytes = (ssi.NumSubDigests + 7) >> 3; + const size_t numBytes = (ssi.NumSubDigests + 7) >> 3; digestsDefs = ssi.sdCRCs.Data; digestsVals = digestsDefs + numBytes; } } - digestIndex = 0; - for (i = 0; i < numFiles; i++, mask >>= 1) { if (mask == 0) { - UInt32 byteIndex = (i - 1) >> 3; + const UInt32 byteIndex = (i - 1) >> 3; p->IsDirs[byteIndex] = isDirMask; p->CRCs.Defs[byteIndex] = crcMask; isDirMask = 0; @@ -1374,18 +1381,17 @@ static SRes SzReadHeader2( numSubStreams = 1; if (ssi.sdNumSubStreams.Data) { - RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)); + RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)) } remSubStreams = numSubStreams; if (numSubStreams != 0) break; { - UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + const UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); unpackPos += folderUnpackSize; if (unpackPos < folderUnpackSize) return SZ_ERROR_ARCHIVE; } - folderIndex++; } } @@ -1397,47 +1403,44 @@ static SRes SzReadHeader2( if (--remSubStreams == 0) { - UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); - UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]]; + const UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + const UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]]; if (folderUnpackSize < unpackPos - startFolderUnpackPos) return SZ_ERROR_ARCHIVE; unpackPos = startFolderUnpackPos + folderUnpackSize; if (unpackPos < folderUnpackSize) return SZ_ERROR_ARCHIVE; - if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i)) + if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex)) { p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex]; crcMask |= mask; } - else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) - { - p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); - digestsValsIndex++; - crcMask |= mask; - } - folderIndex++; } else { UInt64 v; - RINOK(ReadNumber(&ssi.sdSizes, &v)); + RINOK(ReadNumber(&ssi.sdSizes, &v)) unpackPos += v; if (unpackPos < v) return SZ_ERROR_ARCHIVE; - if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + } + if ((crcMask & mask) == 0 && digestsVals) + { + if (!digestsDefs || SzBitArray_Check(digestsDefs, digestIndex)) { - p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); - digestsValsIndex++; + p->CRCs.Vals[i] = GetUi32(digestsVals); + digestsVals += 4; crcMask |= mask; } + digestIndex++; } } if (mask != 0x80) { - UInt32 byteIndex = (i - 1) >> 3; + const UInt32 byteIndex = (i - 1) >> 3; p->IsDirs[byteIndex] = isDirMask; p->CRCs.Defs[byteIndex] = crcMask; } @@ -1454,7 +1457,7 @@ static SRes SzReadHeader2( break; if (!ssi.sdNumSubStreams.Data) return SZ_ERROR_ARCHIVE; - RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)); + RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)) if (numSubStreams != 0) return SZ_ERROR_ARCHIVE; /* @@ -1479,7 +1482,7 @@ static SRes SzReadHeader2( static SRes SzReadHeader( CSzArEx *p, CSzData *sd, - ILookInStream *inStream, + ILookInStreamPtr inStream, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { @@ -1498,7 +1501,7 @@ static SRes SzReadHeader( for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) Buf_Free(tempBufs + i, allocTemp); - RINOK(res); + RINOK(res) if (sd->Size != 0) return SZ_ERROR_FAIL; @@ -1508,7 +1511,7 @@ static SRes SzReadHeader( static SRes SzArEx_Open2( CSzArEx *p, - ILookInStream *inStream, + ILookInStreamPtr inStream, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { @@ -1521,9 +1524,9 @@ static SRes SzArEx_Open2( SRes res; startArcPos = 0; - RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR)); + RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR)) - RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); + RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)) if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; @@ -1552,14 +1555,14 @@ static SRes SzArEx_Open2( { Int64 pos = 0; - RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END)); + RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END)) if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset || (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } - RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset)); + RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset)) if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; @@ -1634,10 +1637,10 @@ static SRes SzArEx_Open2( } -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, +SRes SzArEx_Open(CSzArEx *p, ILookInStreamPtr inStream, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { - SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); + const SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); if (res != SZ_OK) SzArEx_Free(p, allocMain); return res; @@ -1646,7 +1649,7 @@ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, SRes SzArEx_Extract( const CSzArEx *p, - ILookInStream *inStream, + ILookInStreamPtr inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **tempBuf, @@ -1656,7 +1659,7 @@ SRes SzArEx_Extract( ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { - UInt32 folderIndex = p->FileToFolder[fileIndex]; + const UInt32 folderIndex = p->FileToFolder[fileIndex]; SRes res = SZ_OK; *offset = 0; @@ -1673,13 +1676,13 @@ SRes SzArEx_Extract( if (*tempBuf == NULL || *blockIndex != folderIndex) { - UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + const UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); /* UInt64 unpackSizeSpec = p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] - p->UnpackPositions[p->FolderToFile[folderIndex]]; */ - size_t unpackSize = (size_t)unpackSizeSpec; + const size_t unpackSize = (size_t)unpackSizeSpec; if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; @@ -1707,7 +1710,7 @@ SRes SzArEx_Extract( if (res == SZ_OK) { - UInt64 unpackPos = p->UnpackPositions[fileIndex]; + const UInt64 unpackPos = p->UnpackPositions[fileIndex]; *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]); *outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos); if (*offset + *outSizeProcessed > *outBufferSize) @@ -1723,8 +1726,8 @@ SRes SzArEx_Extract( size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) { - size_t offs = p->FileNameOffsets[fileIndex]; - size_t len = p->FileNameOffsets[fileIndex + 1] - offs; + const size_t offs = p->FileNameOffsets[fileIndex]; + const size_t len = p->FileNameOffsets[fileIndex + 1] - offs; if (dest != 0) { size_t i; diff --git a/libraries/lzma/C/7zBuf.h b/libraries/lzma/C/7zBuf.h index 81d1b5b646..c0ba8a7b60 100644 --- a/libraries/lzma/C/7zBuf.h +++ b/libraries/lzma/C/7zBuf.h @@ -1,8 +1,8 @@ /* 7zBuf.h -- Byte Buffer -2017-04-03 : Igor Pavlov : Public domain */ +2023-03-04 : Igor Pavlov : Public domain */ -#ifndef __7Z_BUF_H -#define __7Z_BUF_H +#ifndef ZIP7_INC_7Z_BUF_H +#define ZIP7_INC_7Z_BUF_H #include "7zTypes.h" diff --git a/libraries/lzma/C/7zBuf2.c b/libraries/lzma/C/7zBuf2.c new file mode 100644 index 0000000000..2083474165 --- /dev/null +++ b/libraries/lzma/C/7zBuf2.c @@ -0,0 +1,52 @@ +/* 7zBuf2.c -- Byte Buffer +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zBuf.h" + +void DynBuf_Construct(CDynBuf *p) +{ + p->data = 0; + p->size = 0; + p->pos = 0; +} + +void DynBuf_SeekToBeg(CDynBuf *p) +{ + p->pos = 0; +} + +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc) +{ + if (size > p->size - p->pos) + { + size_t newSize = p->pos + size; + Byte *data; + newSize += newSize / 4; + data = (Byte *)ISzAlloc_Alloc(alloc, newSize); + if (!data) + return 0; + p->size = newSize; + if (p->pos != 0) + memcpy(data, p->data, p->pos); + ISzAlloc_Free(alloc, p->data); + p->data = data; + } + if (size != 0) + { + memcpy(p->data + p->pos, buf, size); + p->pos += size; + } + return 1; +} + +void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->data); + p->data = 0; + p->size = 0; + p->pos = 0; +} diff --git a/libraries/lzma/C/7zCrc.c b/libraries/lzma/C/7zCrc.c index f186324ddc..c995a8be40 100644 --- a/libraries/lzma/C/7zCrc.c +++ b/libraries/lzma/C/7zCrc.c @@ -1,5 +1,5 @@ -/* 7zCrc.c -- CRC32 init -2021-04-01 : Igor Pavlov : Public domain */ +/* 7zCrc.c -- CRC32 calculation and init +2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -13,22 +13,20 @@ #else #define CRC_NUM_TABLES 9 - #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) - - UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); - UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table); + UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); + UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table); #endif #ifndef MY_CPU_BE - UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); - UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); + UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); + UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); #endif -typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); - +/* extern CRC_FUNC g_CrcUpdateT4; CRC_FUNC g_CrcUpdateT4; +*/ extern CRC_FUNC g_CrcUpdateT8; CRC_FUNC g_CrcUpdateT8; @@ -44,20 +42,22 @@ CRC_FUNC g_CrcUpdate; UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; -UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) +UInt32 Z7_FASTCALL CrcUpdate(UInt32 v, const void *data, size_t size) { return g_CrcUpdate(v, data, size, g_CrcTable); } -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) +UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size) { return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; } +#if CRC_NUM_TABLES < 4 \ + || (CRC_NUM_TABLES == 4 && defined(MY_CPU_BE)) \ + || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE)) #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) - -UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table); -UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) +UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; const Byte *pEnd = p + size; @@ -65,7 +65,7 @@ UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const U v = CRC_UPDATE_BYTE_2(v, *p); return v; } - +#endif /* ---------- hardware CRC ---------- */ @@ -78,16 +78,29 @@ UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const U #if defined(_MSC_VER) #if defined(MY_CPU_ARM64) #if (_MSC_VER >= 1910) + #ifndef __clang__ #define USE_ARM64_CRC + #include + #endif #endif #endif #elif (defined(__clang__) && (__clang_major__ >= 3)) \ || (defined(__GNUC__) && (__GNUC__ > 4)) #if !defined(__ARM_FEATURE_CRC32) #define __ARM_FEATURE_CRC32 1 - #if (!defined(__clang__) || (__clang_major__ > 3)) // fix these numbers + #if defined(__clang__) + #if defined(MY_CPU_ARM64) + #define ATTRIB_CRC __attribute__((__target__("crc"))) + #else + #define ATTRIB_CRC __attribute__((__target__("armv8-a,crc"))) + #endif + #else + #if defined(MY_CPU_ARM64) + #define ATTRIB_CRC __attribute__((__target__("+crc"))) + #else #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc"))) #endif + #endif #endif #if defined(__ARM_FEATURE_CRC32) #define USE_ARM64_CRC @@ -105,7 +118,7 @@ UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const U #pragma message("ARM64 CRC emulation") -MY_FORCE_INLINE +Z7_FORCE_INLINE UInt32 __crc32b(UInt32 v, UInt32 data) { const UInt32 *table = g_CrcTable; @@ -113,7 +126,7 @@ UInt32 __crc32b(UInt32 v, UInt32 data) return v; } -MY_FORCE_INLINE +Z7_FORCE_INLINE UInt32 __crc32w(UInt32 v, UInt32 data) { const UInt32 *table = g_CrcTable; @@ -124,7 +137,7 @@ UInt32 __crc32w(UInt32 v, UInt32 data) return v; } -MY_FORCE_INLINE +Z7_FORCE_INLINE UInt32 __crc32d(UInt32 v, UInt64 data) { const UInt32 *table = g_CrcTable; @@ -156,9 +169,9 @@ UInt32 __crc32d(UInt32 v, UInt64 data) // #pragma message("USE ARM HW CRC") ATTRIB_CRC -UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table); ATTRIB_CRC -UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table) +UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; UNUSED_VAR(table); @@ -188,9 +201,9 @@ UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, cons } ATTRIB_CRC -UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table); ATTRIB_CRC -UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table) +UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; UNUSED_VAR(table); @@ -219,6 +232,9 @@ UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, cons return v; } +#undef T0_32_UNROLL_BYTES +#undef T0_64_UNROLL_BYTES + #endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) #endif // MY_CPU_LE @@ -226,7 +242,7 @@ UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, cons -void MY_FAST_CALL CrcGenerateTable() +void Z7_FASTCALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) @@ -239,64 +255,62 @@ void MY_FAST_CALL CrcGenerateTable() } for (i = 256; i < 256 * CRC_NUM_TABLES; i++) { - UInt32 r = g_CrcTable[(size_t)i - 256]; + const UInt32 r = g_CrcTable[(size_t)i - 256]; g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); } #if CRC_NUM_TABLES < 4 - - g_CrcUpdate = CrcUpdateT1; - - #else - - #ifdef MY_CPU_LE - - g_CrcUpdateT4 = CrcUpdateT4; - g_CrcUpdate = CrcUpdateT4; - - #if CRC_NUM_TABLES >= 8 + g_CrcUpdate = CrcUpdateT1; + #elif defined(MY_CPU_LE) + // g_CrcUpdateT4 = CrcUpdateT4; + #if CRC_NUM_TABLES < 8 + g_CrcUpdate = CrcUpdateT4; + #else // CRC_NUM_TABLES >= 8 g_CrcUpdateT8 = CrcUpdateT8; - + /* #ifdef MY_CPU_X86_OR_AMD64 if (!CPU_Is_InOrder()) #endif - g_CrcUpdate = CrcUpdateT8; + */ + g_CrcUpdate = CrcUpdateT8; #endif - #else { - #ifndef MY_CPU_BE + #ifndef MY_CPU_BE UInt32 k = 0x01020304; const Byte *p = (const Byte *)&k; if (p[0] == 4 && p[1] == 3) { - g_CrcUpdateT4 = CrcUpdateT4; - g_CrcUpdate = CrcUpdateT4; - #if CRC_NUM_TABLES >= 8 - g_CrcUpdateT8 = CrcUpdateT8; - g_CrcUpdate = CrcUpdateT8; + #if CRC_NUM_TABLES < 8 + // g_CrcUpdateT4 = CrcUpdateT4; + g_CrcUpdate = CrcUpdateT4; + #else // CRC_NUM_TABLES >= 8 + g_CrcUpdateT8 = CrcUpdateT8; + g_CrcUpdate = CrcUpdateT8; #endif } else if (p[0] != 1 || p[1] != 2) g_CrcUpdate = CrcUpdateT1; else - #endif + #endif // MY_CPU_BE { for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) { - UInt32 x = g_CrcTable[(size_t)i - 256]; - g_CrcTable[i] = CRC_UINT32_SWAP(x); + const UInt32 x = g_CrcTable[(size_t)i - 256]; + g_CrcTable[i] = Z7_BSWAP32(x); } - g_CrcUpdateT4 = CrcUpdateT1_BeT4; - g_CrcUpdate = CrcUpdateT1_BeT4; - #if CRC_NUM_TABLES >= 8 - g_CrcUpdateT8 = CrcUpdateT1_BeT8; - g_CrcUpdate = CrcUpdateT1_BeT8; + #if CRC_NUM_TABLES <= 4 + g_CrcUpdate = CrcUpdateT1; + #elif CRC_NUM_TABLES <= 8 + // g_CrcUpdateT4 = CrcUpdateT1_BeT4; + g_CrcUpdate = CrcUpdateT1_BeT4; + #else // CRC_NUM_TABLES > 8 + g_CrcUpdateT8 = CrcUpdateT1_BeT8; + g_CrcUpdate = CrcUpdateT1_BeT8; #endif } } - #endif - #endif + #endif // CRC_NUM_TABLES < 4 #ifdef MY_CPU_LE #ifdef USE_ARM64_CRC @@ -320,3 +334,7 @@ void MY_FAST_CALL CrcGenerateTable() #endif #endif } + +#undef kCrcPoly +#undef CRC64_NUM_TABLES +#undef CRC_UPDATE_BYTE_2 diff --git a/libraries/lzma/C/7zCrc.h b/libraries/lzma/C/7zCrc.h index 8fd5795871..4afaeae4a8 100644 --- a/libraries/lzma/C/7zCrc.h +++ b/libraries/lzma/C/7zCrc.h @@ -1,8 +1,8 @@ /* 7zCrc.h -- CRC32 calculation -2013-01-18 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __7Z_CRC_H -#define __7Z_CRC_H +#ifndef ZIP7_INC_7Z_CRC_H +#define ZIP7_INC_7Z_CRC_H #include "7zTypes.h" @@ -11,14 +11,16 @@ EXTERN_C_BEGIN extern UInt32 g_CrcTable[]; /* Call CrcGenerateTable one time before other CRC functions */ -void MY_FAST_CALL CrcGenerateTable(void); +void Z7_FASTCALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) -UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); +UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size); +UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size); + +typedef UInt32 (Z7_FASTCALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); EXTERN_C_END diff --git a/libraries/lzma/C/7zCrcOpt.c b/libraries/lzma/C/7zCrcOpt.c index 69fad9ca2b..9c649290df 100644 --- a/libraries/lzma/C/7zCrcOpt.c +++ b/libraries/lzma/C/7zCrcOpt.c @@ -1,5 +1,5 @@ /* 7zCrcOpt.c -- CRC32 calculation -2021-02-09 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -9,8 +9,8 @@ #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) -UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); -UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) @@ -29,8 +29,8 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U return v; } -UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); -UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) @@ -61,11 +61,11 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U #ifndef MY_CPU_LE -#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) +#define CRC_UINT32_SWAP(v) Z7_BSWAP32(v) #define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8)) -UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; table += 0x100; @@ -86,7 +86,7 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, co return CRC_UINT32_SWAP(v); } -UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; table += 0x100; diff --git a/libraries/lzma/C/7zDec.c b/libraries/lzma/C/7zDec.c index fbfd016e1e..96c60359a4 100644 --- a/libraries/lzma/C/7zDec.c +++ b/libraries/lzma/C/7zDec.c @@ -1,11 +1,11 @@ /* 7zDec.c -- Decoding from 7z folder -2021-02-09 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" #include -/* #define _7ZIP_PPMD_SUPPPORT */ +/* #define Z7_PPMD_SUPPORT */ #include "7z.h" #include "7zCrc.h" @@ -16,27 +16,49 @@ #include "Delta.h" #include "LzmaDec.h" #include "Lzma2Dec.h" -#ifdef _7ZIP_PPMD_SUPPPORT +#ifdef Z7_PPMD_SUPPORT #include "Ppmd7.h" #endif #define k_Copy 0 -#ifndef _7Z_NO_METHOD_LZMA2 +#ifndef Z7_NO_METHOD_LZMA2 #define k_LZMA2 0x21 #endif #define k_LZMA 0x30101 #define k_BCJ2 0x303011B -#ifndef _7Z_NO_METHODS_FILTERS + +#if !defined(Z7_NO_METHODS_FILTERS) +#define Z7_USE_BRANCH_FILTER +#endif + +#if !defined(Z7_NO_METHODS_FILTERS) || \ + defined(Z7_USE_NATIVE_BRANCH_FILTER) && defined(MY_CPU_ARM64) +#define Z7_USE_FILTER_ARM64 +#ifndef Z7_USE_BRANCH_FILTER +#define Z7_USE_BRANCH_FILTER +#endif +#define k_ARM64 0xa +#endif + +#if !defined(Z7_NO_METHODS_FILTERS) || \ + defined(Z7_USE_NATIVE_BRANCH_FILTER) && defined(MY_CPU_ARMT) +#define Z7_USE_FILTER_ARMT +#ifndef Z7_USE_BRANCH_FILTER +#define Z7_USE_BRANCH_FILTER +#endif +#define k_ARMT 0x3030701 +#endif + +#ifndef Z7_NO_METHODS_FILTERS #define k_Delta 3 #define k_BCJ 0x3030103 #define k_PPC 0x3030205 #define k_IA64 0x3030401 #define k_ARM 0x3030501 -#define k_ARMT 0x3030701 #define k_SPARC 0x3030805 #endif -#ifdef _7ZIP_PPMD_SUPPPORT +#ifdef Z7_PPMD_SUPPORT #define k_PPMD 0x30401 @@ -49,12 +71,12 @@ typedef struct UInt64 processed; BoolInt extra; SRes res; - const ILookInStream *inStream; + ILookInStreamPtr inStream; } CByteInToLook; -static Byte ReadByte(const IByteIn *pp) +static Byte ReadByte(IByteInPtr pp) { - CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt); + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CByteInToLook) if (p->cur != p->end) return *p->cur++; if (p->res == SZ_OK) @@ -67,13 +89,13 @@ static Byte ReadByte(const IByteIn *pp) p->cur = p->begin; p->end = p->begin + size; if (size != 0) - return *p->cur++;; + return *p->cur++; } p->extra = True; return 0; } -static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream, +static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStreamPtr inStream, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) { CPpmd7 ppmd; @@ -138,14 +160,14 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, c #endif -static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, +static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStreamPtr inStream, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) { CLzmaDec state; SRes res = SZ_OK; - LzmaDec_Construct(&state); - RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); + LzmaDec_CONSTRUCT(&state) + RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)) state.dic = outBuffer; state.dicBufSize = outSize; LzmaDec_Init(&state); @@ -196,18 +218,18 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I } -#ifndef _7Z_NO_METHOD_LZMA2 +#ifndef Z7_NO_METHOD_LZMA2 -static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, +static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStreamPtr inStream, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) { CLzma2Dec state; SRes res = SZ_OK; - Lzma2Dec_Construct(&state); + Lzma2Dec_CONSTRUCT(&state) if (propsSize != 1) return SZ_ERROR_DATA; - RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); + RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)) state.decoder.dic = outBuffer; state.decoder.dicBufSize = outSize; Lzma2Dec_Init(&state); @@ -257,7 +279,7 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, #endif -static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) +static SRes SzDecodeCopy(UInt64 inSize, ILookInStreamPtr inStream, Byte *outBuffer) { while (inSize > 0) { @@ -265,13 +287,13 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer size_t curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)inSize; - RINOK(ILookInStream_Look(inStream, &inBuf, &curSize)); + RINOK(ILookInStream_Look(inStream, &inBuf, &curSize)) if (curSize == 0) return SZ_ERROR_INPUT_EOF; memcpy(outBuffer, inBuf, curSize); outBuffer += curSize; inSize -= curSize; - RINOK(ILookInStream_Skip(inStream, curSize)); + RINOK(ILookInStream_Skip(inStream, curSize)) } return SZ_OK; } @@ -282,12 +304,12 @@ static BoolInt IS_MAIN_METHOD(UInt32 m) { case k_Copy: case k_LZMA: - #ifndef _7Z_NO_METHOD_LZMA2 + #ifndef Z7_NO_METHOD_LZMA2 case k_LZMA2: - #endif - #ifdef _7ZIP_PPMD_SUPPPORT + #endif + #ifdef Z7_PPMD_SUPPORT case k_PPMD: - #endif + #endif return True; } return False; @@ -317,7 +339,7 @@ static SRes CheckSupportedFolder(const CSzFolder *f) } - #ifndef _7Z_NO_METHODS_FILTERS + #if defined(Z7_USE_BRANCH_FILTER) if (f->NumCoders == 2) { @@ -333,13 +355,20 @@ static SRes CheckSupportedFolder(const CSzFolder *f) return SZ_ERROR_UNSUPPORTED; switch ((UInt32)c->MethodID) { + #if !defined(Z7_NO_METHODS_FILTERS) case k_Delta: case k_BCJ: case k_PPC: case k_IA64: case k_SPARC: case k_ARM: + #endif + #ifdef Z7_USE_FILTER_ARM64 + case k_ARM64: + #endif + #ifdef Z7_USE_FILTER_ARMT case k_ARMT: + #endif break; default: return SZ_ERROR_UNSUPPORTED; @@ -372,15 +401,16 @@ static SRes CheckSupportedFolder(const CSzFolder *f) return SZ_ERROR_UNSUPPORTED; } -#ifndef _7Z_NO_METHODS_FILTERS -#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; -#endif + + + + static SRes SzFolder_Decode2(const CSzFolder *folder, const Byte *propsData, const UInt64 *unpackSizes, const UInt64 *packPositions, - ILookInStream *inStream, UInt64 startPos, + ILookInStreamPtr inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain, Byte *tempBuf[]) { @@ -389,7 +419,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, SizeT tempSize3 = 0; Byte *tempBuf3 = 0; - RINOK(CheckSupportedFolder(folder)); + RINOK(CheckSupportedFolder(folder)) for (ci = 0; ci < folder->NumCoders; ci++) { @@ -404,8 +434,8 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, SizeT outSizeCur = outSize; if (folder->NumCoders == 4) { - UInt32 indices[] = { 3, 2, 0 }; - UInt64 unpackSize = unpackSizes[ci]; + const UInt32 indices[] = { 3, 2, 0 }; + const UInt64 unpackSize = unpackSizes[ci]; si = indices[ci]; if (ci < 2) { @@ -431,37 +461,37 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, } offset = packPositions[si]; inSize = packPositions[(size_t)si + 1] - offset; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + RINOK(LookInStream_SeekTo(inStream, startPos + offset)) if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) /* check it */ return SZ_ERROR_DATA; - RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); + RINOK(SzDecodeCopy(inSize, inStream, outBufCur)) } else if (coder->MethodID == k_LZMA) { - RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)) } - #ifndef _7Z_NO_METHOD_LZMA2 + #ifndef Z7_NO_METHOD_LZMA2 else if (coder->MethodID == k_LZMA2) { - RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)) } - #endif - #ifdef _7ZIP_PPMD_SUPPPORT + #endif + #ifdef Z7_PPMD_SUPPORT else if (coder->MethodID == k_PPMD) { - RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)) } - #endif + #endif else return SZ_ERROR_UNSUPPORTED; } else if (coder->MethodID == k_BCJ2) { - UInt64 offset = packPositions[1]; - UInt64 s3Size = packPositions[2] - offset; + const UInt64 offset = packPositions[1]; + const UInt64 s3Size = packPositions[2] - offset; if (ci != 3) return SZ_ERROR_UNSUPPORTED; @@ -473,8 +503,8 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, if (!tempBuf[2] && tempSizes[2] != 0) return SZ_ERROR_MEM; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])); + RINOK(LookInStream_SeekTo(inStream, startPos + offset)) + RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])) if ((tempSizes[0] & 3) != 0 || (tempSizes[1] & 3) != 0 || @@ -493,26 +523,22 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, p.destLim = outBuffer + outSize; Bcj2Dec_Init(&p); - RINOK(Bcj2Dec_Decode(&p)); + RINOK(Bcj2Dec_Decode(&p)) { unsigned i; for (i = 0; i < 4; i++) if (p.bufs[i] != p.lims[i]) return SZ_ERROR_DATA; - - if (!Bcj2Dec_IsFinished(&p)) - return SZ_ERROR_DATA; - - if (p.dest != p.destLim - || p.state != BCJ2_STREAM_MAIN) + if (p.dest != p.destLim || !Bcj2Dec_IsMaybeFinished(&p)) return SZ_ERROR_DATA; } } } - #ifndef _7Z_NO_METHODS_FILTERS + #if defined(Z7_USE_BRANCH_FILTER) else if (ci == 1) { + #if !defined(Z7_NO_METHODS_FILTERS) if (coder->MethodID == k_Delta) { if (coder->PropsSize != 1) @@ -522,31 +548,53 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, Delta_Init(state); Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize); } + continue; } - else + #endif + + #ifdef Z7_USE_FILTER_ARM64 + if (coder->MethodID == k_ARM64) + { + UInt32 pc = 0; + if (coder->PropsSize == 4) + pc = GetUi32(propsData + coder->PropsOffset); + else if (coder->PropsSize != 0) + return SZ_ERROR_UNSUPPORTED; + z7_BranchConv_ARM64_Dec(outBuffer, outSize, pc); + continue; + } + #endif + + #if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT) { if (coder->PropsSize != 0) return SZ_ERROR_UNSUPPORTED; + #define CASE_BRA_CONV(isa) case k_ ## isa: Z7_BRANCH_CONV_DEC(isa)(outBuffer, outSize, 0); break; // pc = 0; switch (coder->MethodID) { + #if !defined(Z7_NO_METHODS_FILTERS) case k_BCJ: { - UInt32 state; - x86_Convert_Init(state); - x86_Convert(outBuffer, outSize, 0, &state, 0); + UInt32 state = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL; + z7_BranchConvSt_X86_Dec(outBuffer, outSize, 0, &state); // pc = 0 break; } CASE_BRA_CONV(PPC) CASE_BRA_CONV(IA64) CASE_BRA_CONV(SPARC) CASE_BRA_CONV(ARM) + #endif + #if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT) CASE_BRA_CONV(ARMT) + #endif default: return SZ_ERROR_UNSUPPORTED; } + continue; } - } - #endif + #endif + } // (c == 1) + #endif else return SZ_ERROR_UNSUPPORTED; } @@ -556,7 +604,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, - ILookInStream *inStream, UInt64 startPos, + ILookInStreamPtr inStream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAllocPtr allocMain) { diff --git a/libraries/lzma/C/7zFile.c b/libraries/lzma/C/7zFile.c new file mode 100644 index 0000000000..ba5daa133b --- /dev/null +++ b/libraries/lzma/C/7zFile.c @@ -0,0 +1,443 @@ +/* 7zFile.c -- File IO +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zFile.h" + +#ifndef USE_WINDOWS_FILE + + #include + + #ifndef USE_FOPEN + #include + #include + #ifdef _WIN32 + #include + typedef int ssize_t; + typedef int off_t; + #else + #include + #endif + #endif + +#else + +/* + ReadFile and WriteFile functions in Windows have BUG: + If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) + from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES + (Insufficient system resources exist to complete the requested service). + Probably in some version of Windows there are problems with other sizes: + for 32 MB (maybe also for 16 MB). + And message can be "Network connection was lost" +*/ + +#endif + +#define kChunkSizeMax (1 << 22) + +void File_Construct(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + p->handle = INVALID_HANDLE_VALUE; + #elif defined(USE_FOPEN) + p->file = NULL; + #else + p->fd = -1; + #endif +} + +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) + +static WRes File_Open(CSzFile *p, const char *name, int writeMode) +{ + #ifdef USE_WINDOWS_FILE + + p->handle = CreateFileA(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); + + #elif defined(USE_FOPEN) + + p->file = fopen(name, writeMode ? "wb+" : "rb"); + return (p->file != 0) ? 0 : + #ifdef UNDER_CE + 2; /* ENOENT */ + #else + errno; + #endif + + #else + + int flags = (writeMode ? (O_CREAT | O_EXCL | O_WRONLY) : O_RDONLY); + #ifdef O_BINARY + flags |= O_BINARY; + #endif + p->fd = open(name, flags, 0666); + return (p->fd != -1) ? 0 : errno; + + #endif +} + +WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } + +WRes OutFile_Open(CSzFile *p, const char *name) +{ + #if defined(USE_WINDOWS_FILE) || defined(USE_FOPEN) + return File_Open(p, name, 1); + #else + p->fd = creat(name, 0666); + return (p->fd != -1) ? 0 : errno; + #endif +} + +#endif + + +#ifdef USE_WINDOWS_FILE +static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) +{ + p->handle = CreateFileW(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); +} +WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } +#endif + +WRes File_Close(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + + if (p->handle != INVALID_HANDLE_VALUE) + { + if (!CloseHandle(p->handle)) + return GetLastError(); + p->handle = INVALID_HANDLE_VALUE; + } + + #elif defined(USE_FOPEN) + + if (p->file != NULL) + { + int res = fclose(p->file); + if (res != 0) + { + if (res == EOF) + return errno; + return res; + } + p->file = NULL; + } + + #else + + if (p->fd != -1) + { + if (close(p->fd) != 0) + return errno; + p->fd = -1; + } + + #endif + + return 0; +} + + +WRes File_Read(CSzFile *p, void *data, size_t *size) +{ + size_t originalSize = *size; + *size = 0; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + do + { + const DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + const BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + // debug : we can break here for partial reading mode + if (processed == 0) + break; + } + while (originalSize > 0); + + #elif defined(USE_FOPEN) + + do + { + const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; + const size_t processed = fread(data, 1, curSize, p->file); + data = (void *)((Byte *)data + (size_t)processed); + originalSize -= processed; + *size += processed; + if (processed != curSize) + return ferror(p->file); + // debug : we can break here for partial reading mode + if (processed == 0) + break; + } + while (originalSize > 0); + + #else + + do + { + const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; + const ssize_t processed = read(p->fd, data, curSize); + if (processed == -1) + return errno; + if (processed == 0) + break; + data = (void *)((Byte *)data + (size_t)processed); + originalSize -= (size_t)processed; + *size += (size_t)processed; + // debug : we can break here for partial reading mode + // break; + } + while (originalSize > 0); + + #endif + + return 0; +} + + +WRes File_Write(CSzFile *p, const void *data, size_t *size) +{ + size_t originalSize = *size; + *size = 0; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + do + { + const DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + const BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); + data = (const void *)((const Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + + #elif defined(USE_FOPEN) + + do + { + const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; + const size_t processed = fwrite(data, 1, curSize, p->file); + data = (void *)((Byte *)data + (size_t)processed); + originalSize -= processed; + *size += processed; + if (processed != curSize) + return ferror(p->file); + if (processed == 0) + break; + } + while (originalSize > 0); + + #else + + do + { + const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; + const ssize_t processed = write(p->fd, data, curSize); + if (processed == -1) + return errno; + if (processed == 0) + break; + data = (const void *)((const Byte *)data + (size_t)processed); + originalSize -= (size_t)processed; + *size += (size_t)processed; + } + while (originalSize > 0); + + #endif + + return 0; +} + + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) +{ + #ifdef USE_WINDOWS_FILE + + DWORD moveMethod; + UInt32 low = (UInt32)*pos; + LONG high = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ + // (int) to eliminate clang warning + switch ((int)origin) + { + case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; + case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; + case SZ_SEEK_END: moveMethod = FILE_END; break; + default: return ERROR_INVALID_PARAMETER; + } + low = SetFilePointer(p->handle, (LONG)low, &high, moveMethod); + if (low == (UInt32)0xFFFFFFFF) + { + WRes res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *pos = ((Int64)high << 32) | low; + return 0; + + #else + + int moveMethod; // = origin; + + switch ((int)origin) + { + case SZ_SEEK_SET: moveMethod = SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = SEEK_END; break; + default: return EINVAL; + } + + #if defined(USE_FOPEN) + { + int res = fseek(p->file, (long)*pos, moveMethod); + if (res == -1) + return errno; + *pos = ftell(p->file); + if (*pos == -1) + return errno; + return 0; + } + #else + { + off_t res = lseek(p->fd, (off_t)*pos, moveMethod); + if (res == -1) + return errno; + *pos = res; + return 0; + } + + #endif // USE_FOPEN + #endif // USE_WINDOWS_FILE +} + + +WRes File_GetLength(CSzFile *p, UInt64 *length) +{ + #ifdef USE_WINDOWS_FILE + + DWORD sizeHigh; + DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + { + DWORD res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *length = (((UInt64)sizeHigh) << 32) + sizeLow; + return 0; + + #elif defined(USE_FOPEN) + + long pos = ftell(p->file); + int res = fseek(p->file, 0, SEEK_END); + *length = ftell(p->file); + fseek(p->file, pos, SEEK_SET); + return res; + + #else + + off_t pos; + *length = 0; + pos = lseek(p->fd, 0, SEEK_CUR); + if (pos != -1) + { + const off_t len2 = lseek(p->fd, 0, SEEK_END); + const off_t res2 = lseek(p->fd, pos, SEEK_SET); + if (len2 != -1) + { + *length = (UInt64)len2; + if (res2 != -1) + return 0; + } + } + return errno; + + #endif +} + + +/* ---------- FileSeqInStream ---------- */ + +static SRes FileSeqInStream_Read(ISeqInStreamPtr pp, void *buf, size_t *size) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileSeqInStream) + const WRes wres = File_Read(&p->file, buf, size); + p->wres = wres; + return (wres == 0) ? SZ_OK : SZ_ERROR_READ; +} + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p) +{ + p->vt.Read = FileSeqInStream_Read; +} + + +/* ---------- FileInStream ---------- */ + +static SRes FileInStream_Read(ISeekInStreamPtr pp, void *buf, size_t *size) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileInStream) + const WRes wres = File_Read(&p->file, buf, size); + p->wres = wres; + return (wres == 0) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes FileInStream_Seek(ISeekInStreamPtr pp, Int64 *pos, ESzSeek origin) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileInStream) + const WRes wres = File_Seek(&p->file, pos, origin); + p->wres = wres; + return (wres == 0) ? SZ_OK : SZ_ERROR_READ; +} + +void FileInStream_CreateVTable(CFileInStream *p) +{ + p->vt.Read = FileInStream_Read; + p->vt.Seek = FileInStream_Seek; +} + + +/* ---------- FileOutStream ---------- */ + +static size_t FileOutStream_Write(ISeqOutStreamPtr pp, const void *data, size_t size) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileOutStream) + const WRes wres = File_Write(&p->file, data, &size); + p->wres = wres; + return size; +} + +void FileOutStream_CreateVTable(CFileOutStream *p) +{ + p->vt.Write = FileOutStream_Write; +} diff --git a/libraries/lzma/C/7zFile.h b/libraries/lzma/C/7zFile.h new file mode 100644 index 0000000000..f5069cd9ee --- /dev/null +++ b/libraries/lzma/C/7zFile.h @@ -0,0 +1,92 @@ +/* 7zFile.h -- File IO +2023-03-05 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_FILE_H +#define ZIP7_INC_FILE_H + +#ifdef _WIN32 +#define USE_WINDOWS_FILE +// #include +#endif + +#ifdef USE_WINDOWS_FILE +#include "7zWindows.h" + +#else +// note: USE_FOPEN mode is limited to 32-bit file size +// #define USE_FOPEN +// #include +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* ---------- File ---------- */ + +typedef struct +{ + #ifdef USE_WINDOWS_FILE + HANDLE handle; + #elif defined(USE_FOPEN) + FILE *file; + #else + int fd; + #endif +} CSzFile; + +void File_Construct(CSzFile *p); +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +WRes InFile_Open(CSzFile *p, const char *name); +WRes OutFile_Open(CSzFile *p, const char *name); +#endif +#ifdef USE_WINDOWS_FILE +WRes InFile_OpenW(CSzFile *p, const WCHAR *name); +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); +#endif +WRes File_Close(CSzFile *p); + +/* reads max(*size, remain file's size) bytes */ +WRes File_Read(CSzFile *p, void *data, size_t *size); + +/* writes *size bytes */ +WRes File_Write(CSzFile *p, const void *data, size_t *size); + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); +WRes File_GetLength(CSzFile *p, UInt64 *length); + + +/* ---------- FileInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + CSzFile file; + WRes wres; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream vt; + CSzFile file; + WRes wres; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream vt; + CSzFile file; + WRes wres; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/7zStream.c b/libraries/lzma/C/7zStream.c index 28a14604fb..74e75b65aa 100644 --- a/libraries/lzma/C/7zStream.c +++ b/libraries/lzma/C/7zStream.c @@ -1,5 +1,5 @@ /* 7zStream.c -- 7z Stream functions -2021-02-09 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -7,12 +7,33 @@ #include "7zTypes.h" -SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType) + +SRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize) +{ + size_t size = *processedSize; + *processedSize = 0; + while (size != 0) + { + size_t cur = size; + const SRes res = ISeqInStream_Read(stream, buf, &cur); + *processedSize += cur; + buf = (void *)((Byte *)buf + cur); + size -= cur; + if (res != SZ_OK) + return res; + if (cur == 0) + return SZ_OK; + } + return SZ_OK; +} + +/* +SRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; - RINOK(ISeqInStream_Read(stream, buf, &processed)); + RINOK(ISeqInStream_Read(stream, buf, &processed)) if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); @@ -21,42 +42,44 @@ SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes return SZ_OK; } -SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size) +SRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size) { return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } +*/ + -SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf) +SRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf) { size_t processed = 1; - RINOK(ISeqInStream_Read(stream, buf, &processed)); + RINOK(ISeqInStream_Read(stream, buf, &processed)) return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; } -SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset) +SRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset) { Int64 t = (Int64)offset; return ILookInStream_Seek(stream, &t, SZ_SEEK_SET); } -SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size) +SRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size) { const void *lookBuf; if (*size == 0) return SZ_OK; - RINOK(ILookInStream_Look(stream, &lookBuf, size)); + RINOK(ILookInStream_Look(stream, &lookBuf, size)) memcpy(buf, lookBuf, *size); return ILookInStream_Skip(stream, *size); } -SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType) +SRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; - RINOK(ILookInStream_Read(stream, buf, &processed)); + RINOK(ILookInStream_Read(stream, buf, &processed)) if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); @@ -65,16 +88,16 @@ SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRe return SZ_OK; } -SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size) +SRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size) { return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } -#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt); +#define GET_LookToRead2 Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLookToRead2) -static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size) +static SRes LookToRead2_Look_Lookahead(ILookInStreamPtr pp, const void **buf, size_t *size) { SRes res = SZ_OK; GET_LookToRead2 @@ -93,7 +116,7 @@ static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf return res; } -static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size) +static SRes LookToRead2_Look_Exact(ILookInStreamPtr pp, const void **buf, size_t *size) { SRes res = SZ_OK; GET_LookToRead2 @@ -113,14 +136,14 @@ static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, si return res; } -static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset) +static SRes LookToRead2_Skip(ILookInStreamPtr pp, size_t offset) { GET_LookToRead2 p->pos += offset; return SZ_OK; } -static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size) +static SRes LookToRead2_Read(ILookInStreamPtr pp, void *buf, size_t *size) { GET_LookToRead2 size_t rem = p->size - p->pos; @@ -134,7 +157,7 @@ static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size) return SZ_OK; } -static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin) +static SRes LookToRead2_Seek(ILookInStreamPtr pp, Int64 *pos, ESzSeek origin) { GET_LookToRead2 p->pos = p->size = 0; @@ -153,9 +176,9 @@ void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead) -static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size) +static SRes SecToLook_Read(ISeqInStreamPtr pp, void *buf, size_t *size) { - CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt); + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToLook) return LookInStream_LookRead(p->realStream, buf, size); } @@ -164,9 +187,9 @@ void SecToLook_CreateVTable(CSecToLook *p) p->vt.Read = SecToLook_Read; } -static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size) +static SRes SecToRead_Read(ISeqInStreamPtr pp, void *buf, size_t *size) { - CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt); + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToRead) return ILookInStream_Read(p->realStream, buf, size); } diff --git a/libraries/lzma/C/7zTypes.h b/libraries/lzma/C/7zTypes.h index fe4fde3ffc..1fcb2473e1 100644 --- a/libraries/lzma/C/7zTypes.h +++ b/libraries/lzma/C/7zTypes.h @@ -1,8 +1,8 @@ /* 7zTypes.h -- Basic types -2021-12-25 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __7Z_TYPES_H -#define __7Z_TYPES_H +#ifndef ZIP7_7Z_TYPES_H +#define ZIP7_7Z_TYPES_H #ifdef _WIN32 /* #include */ @@ -52,6 +52,11 @@ typedef int SRes; #define MY_ALIGN(n) #endif #else + /* + // C11/C++11: + #include + #define MY_ALIGN(n) alignas(n) + */ #define MY_ALIGN(n) __attribute__ ((aligned(n))) #endif @@ -62,7 +67,7 @@ typedef int SRes; typedef unsigned WRes; #define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) -// #define MY_HRES_ERROR__INTERNAL_ERROR MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR) +// #define MY_HRES_ERROR_INTERNAL_ERROR MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR) #else // _WIN32 @@ -70,13 +75,13 @@ typedef unsigned WRes; typedef int WRes; // (FACILITY_ERRNO = 0x800) is 7zip's FACILITY constant to represent (errno) errors in HRESULT -#define MY__FACILITY_ERRNO 0x800 -#define MY__FACILITY_WIN32 7 -#define MY__FACILITY__WRes MY__FACILITY_ERRNO +#define MY_FACILITY_ERRNO 0x800 +#define MY_FACILITY_WIN32 7 +#define MY_FACILITY_WRes MY_FACILITY_ERRNO #define MY_HRESULT_FROM_errno_CONST_ERROR(x) ((HRESULT)( \ ( (HRESULT)(x) & 0x0000FFFF) \ - | (MY__FACILITY__WRes << 16) \ + | (MY_FACILITY_WRes << 16) \ | (HRESULT)0x80000000 )) #define MY_SRes_HRESULT_FROM_WRes(x) \ @@ -120,23 +125,19 @@ typedef int WRes; #define ERROR_INVALID_REPARSE_DATA ((HRESULT)0x80071128L) #define ERROR_REPARSE_TAG_INVALID ((HRESULT)0x80071129L) -// if (MY__FACILITY__WRes != FACILITY_WIN32), +// if (MY_FACILITY_WRes != FACILITY_WIN32), // we use FACILITY_WIN32 for COM errors: #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) -#define MY__E_ERROR_NEGATIVE_SEEK ((HRESULT)0x80070083L) +#define MY_E_ERROR_NEGATIVE_SEEK ((HRESULT)0x80070083L) /* // we can use FACILITY_ERRNO for some COM errors, that have errno equivalents: #define E_OUTOFMEMORY MY_HRESULT_FROM_errno_CONST_ERROR(ENOMEM) #define E_INVALIDARG MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) -#define MY__E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) +#define MY_E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) */ -// gcc / clang : (sizeof(long) == sizeof(void*)) in 32/64 bits -typedef long INT_PTR; -typedef unsigned long UINT_PTR; - #define TEXT(quote) quote #define FILE_ATTRIBUTE_READONLY 0x0001 @@ -160,18 +161,18 @@ typedef unsigned long UINT_PTR; #ifndef RINOK -#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#define RINOK(x) { const int _result_ = (x); if (_result_ != 0) return _result_; } #endif #ifndef RINOK_WRes -#define RINOK_WRes(x) { WRes __result__ = (x); if (__result__ != 0) return __result__; } +#define RINOK_WRes(x) { const WRes _result_ = (x); if (_result_ != 0) return _result_; } #endif typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; -#ifdef _LZMA_UINT32_IS_ULONG +#ifdef Z7_DECL_Int32_AS_long typedef long Int32; typedef unsigned long UInt32; #else @@ -210,37 +211,51 @@ typedef size_t SIZE_T; #endif // _WIN32 -#define MY_HRES_ERROR__INTERNAL_ERROR ((HRESULT)0x8007054FL) - +#define MY_HRES_ERROR_INTERNAL_ERROR ((HRESULT)0x8007054FL) -#ifdef _SZ_NO_INT_64 -/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. - NOTES: Some code will work incorrectly in that case! */ +#ifdef Z7_DECL_Int64_AS_long typedef long Int64; typedef unsigned long UInt64; #else -#if defined(_MSC_VER) || defined(__BORLANDC__) +#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__clang__) typedef __int64 Int64; typedef unsigned __int64 UInt64; -#define UINT64_CONST(n) n +#else +#if defined(__clang__) || defined(__GNUC__) +#include +typedef int64_t Int64; +typedef uint64_t UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; -#define UINT64_CONST(n) n ## ULL +// #define UINT64_CONST(n) n ## ULL +#endif #endif #endif -#ifdef _LZMA_NO_SYSTEM_SIZE_T -typedef UInt32 SizeT; +#define UINT64_CONST(n) n + + +#ifdef Z7_DECL_SizeT_AS_unsigned_int +typedef unsigned int SizeT; #else typedef size_t SizeT; #endif +/* +#if (defined(_MSC_VER) && _MSC_VER <= 1200) +typedef size_t MY_uintptr_t; +#else +#include +typedef uintptr_t MY_uintptr_t; +#endif +*/ + typedef int BoolInt; /* typedef BoolInt Bool; */ #define True 1 @@ -248,23 +263,23 @@ typedef int BoolInt; #ifdef _WIN32 -#define MY_STD_CALL __stdcall +#define Z7_STDCALL __stdcall #else -#define MY_STD_CALL +#define Z7_STDCALL #endif #ifdef _MSC_VER #if _MSC_VER >= 1300 -#define MY_NO_INLINE __declspec(noinline) +#define Z7_NO_INLINE __declspec(noinline) #else -#define MY_NO_INLINE +#define Z7_NO_INLINE #endif -#define MY_FORCE_INLINE __forceinline +#define Z7_FORCE_INLINE __forceinline -#define MY_CDECL __cdecl -#define MY_FAST_CALL __fastcall +#define Z7_CDECL __cdecl +#define Z7_FASTCALL __fastcall #else // _MSC_VER @@ -272,27 +287,25 @@ typedef int BoolInt; || (defined(__clang__) && (__clang_major__ >= 4)) \ || defined(__INTEL_COMPILER) \ || defined(__xlC__) -#define MY_NO_INLINE __attribute__((noinline)) -// #define MY_FORCE_INLINE __attribute__((always_inline)) inline +#define Z7_NO_INLINE __attribute__((noinline)) +#define Z7_FORCE_INLINE __attribute__((always_inline)) inline #else -#define MY_NO_INLINE +#define Z7_NO_INLINE +#define Z7_FORCE_INLINE #endif -#define MY_FORCE_INLINE - - -#define MY_CDECL +#define Z7_CDECL #if defined(_M_IX86) \ || defined(__i386__) -// #define MY_FAST_CALL __attribute__((fastcall)) -// #define MY_FAST_CALL __attribute__((cdecl)) -#define MY_FAST_CALL +// #define Z7_FASTCALL __attribute__((fastcall)) +// #define Z7_FASTCALL __attribute__((cdecl)) +#define Z7_FASTCALL #elif defined(MY_CPU_AMD64) -// #define MY_FAST_CALL __attribute__((ms_abi)) -#define MY_FAST_CALL +// #define Z7_FASTCALL __attribute__((ms_abi)) +#define Z7_FASTCALL #else -#define MY_FAST_CALL +#define Z7_FASTCALL #endif #endif // _MSC_VER @@ -300,41 +313,49 @@ typedef int BoolInt; /* The following interfaces use first parameter as pointer to structure */ -typedef struct IByteIn IByteIn; -struct IByteIn +// #define Z7_C_IFACE_CONST_QUAL +#define Z7_C_IFACE_CONST_QUAL const + +#define Z7_C_IFACE_DECL(a) \ + struct a ## _; \ + typedef Z7_C_IFACE_CONST_QUAL struct a ## _ * a ## Ptr; \ + typedef struct a ## _ a; \ + struct a ## _ + + +Z7_C_IFACE_DECL (IByteIn) { - Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */ + Byte (*Read)(IByteInPtr p); /* reads one byte, returns 0 in case of EOF or error */ }; #define IByteIn_Read(p) (p)->Read(p) -typedef struct IByteOut IByteOut; -struct IByteOut +Z7_C_IFACE_DECL (IByteOut) { - void (*Write)(const IByteOut *p, Byte b); + void (*Write)(IByteOutPtr p, Byte b); }; #define IByteOut_Write(p, b) (p)->Write(p, b) -typedef struct ISeqInStream ISeqInStream; -struct ISeqInStream +Z7_C_IFACE_DECL (ISeqInStream) { - SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size); + SRes (*Read)(ISeqInStreamPtr p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ }; #define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size) +/* try to read as much as avail in stream and limited by (*processedSize) */ +SRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize); /* it can return SZ_ERROR_INPUT_EOF */ -SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size); -SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType); -SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf); +// SRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size); +// SRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf); -typedef struct ISeqOutStream ISeqOutStream; -struct ISeqOutStream +Z7_C_IFACE_DECL (ISeqOutStream) { - size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size); + size_t (*Write)(ISeqOutStreamPtr p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ }; @@ -348,29 +369,26 @@ typedef enum } ESzSeek; -typedef struct ISeekInStream ISeekInStream; -struct ISeekInStream +Z7_C_IFACE_DECL (ISeekInStream) { - SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ - SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin); + SRes (*Read)(ISeekInStreamPtr p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(ISeekInStreamPtr p, Int64 *pos, ESzSeek origin); }; #define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size) #define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) -typedef struct ILookInStream ILookInStream; -struct ILookInStream +Z7_C_IFACE_DECL (ILookInStream) { - SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size); + SRes (*Look)(ILookInStreamPtr p, const void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ - SRes (*Skip)(const ILookInStream *p, size_t offset); + SRes (*Skip)(ILookInStreamPtr p, size_t offset); /* offset must be <= output(*size) of Look */ - - SRes (*Read)(const ILookInStream *p, void *buf, size_t *size); + SRes (*Read)(ILookInStreamPtr p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ - SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin); + SRes (*Seek)(ILookInStreamPtr p, Int64 *pos, ESzSeek origin); }; #define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size) @@ -379,19 +397,18 @@ struct ILookInStream #define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) -SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size); -SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset); +SRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset); /* reads via ILookInStream::Read */ -SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType); -SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size); - +SRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size); typedef struct { ILookInStream vt; - const ISeekInStream *realStream; + ISeekInStreamPtr realStream; size_t pos; size_t size; /* it's data size */ @@ -403,13 +420,13 @@ typedef struct void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead); -#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; } +#define LookToRead2_INIT(p) { (p)->pos = (p)->size = 0; } typedef struct { ISeqInStream vt; - const ILookInStream *realStream; + ILookInStreamPtr realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); @@ -419,20 +436,19 @@ void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream vt; - const ILookInStream *realStream; + ILookInStreamPtr realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); -typedef struct ICompressProgress ICompressProgress; - -struct ICompressProgress +Z7_C_IFACE_DECL (ICompressProgress) { - SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize); + SRes (*Progress)(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ }; + #define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize) @@ -470,13 +486,13 @@ struct ISzAlloc -#ifndef MY_container_of +#ifndef Z7_container_of /* -#define MY_container_of(ptr, type, m) container_of(ptr, type, m) -#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m) -#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m))) -#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m)))) +#define Z7_container_of(ptr, type, m) container_of(ptr, type, m) +#define Z7_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m) +#define Z7_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m))) +#define Z7_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m)))) */ /* @@ -485,24 +501,64 @@ struct ISzAlloc GCC 4.8.1 : classes with non-public variable members" */ -#define MY_container_of(ptr, type, m) ((type *)(void *)((char *)(void *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) +#define Z7_container_of(ptr, type, m) \ + ((type *)(void *)((char *)(void *) \ + (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m))) -#endif - -#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr)) +#define Z7_container_of_CONST(ptr, type, m) \ + ((const type *)(const void *)((const char *)(const void *) \ + (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m))) /* -#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +#define Z7_container_of_NON_CONST_FROM_CONST(ptr, type, m) \ + ((type *)(void *)(const void *)((const char *)(const void *) \ + (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m))) */ -#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m) -#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +#endif + +#define Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr)) + +// #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +#define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_container_of(ptr, type, m) +// #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_container_of_NON_CONST_FROM_CONST(ptr, type, m) + +#define Z7_CONTAINER_FROM_VTBL_CONST(ptr, type, m) Z7_container_of_CONST(ptr, type, m) + +#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) /* -#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m) +#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m) */ +#if defined (__clang__) || defined(__GNUC__) +#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#define Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL \ + _Pragma("GCC diagnostic pop") +#else +#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL +#define Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL +#endif + +#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \ + Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL \ + type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \ + Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL + +#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p) -#define MY_memset_0_ARRAY(a) memset((a), 0, sizeof(a)) +// #define ZIP7_DECLARE_HANDLE(name) typedef void *name; +#define Z7_DECLARE_HANDLE(name) struct name##_dummy{int unused;}; typedef struct name##_dummy *name; + + +#define Z7_memset_0_ARRAY(a) memset((a), 0, sizeof(a)) + +#ifndef Z7_ARRAY_SIZE +#define Z7_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + #ifdef _WIN32 @@ -520,6 +576,22 @@ struct ISzAlloc #endif +#define k_PropVar_TimePrec_0 0 +#define k_PropVar_TimePrec_Unix 1 +#define k_PropVar_TimePrec_DOS 2 +#define k_PropVar_TimePrec_HighPrec 3 +#define k_PropVar_TimePrec_Base 16 +#define k_PropVar_TimePrec_100ns (k_PropVar_TimePrec_Base + 7) +#define k_PropVar_TimePrec_1ns (k_PropVar_TimePrec_Base + 9) + EXTERN_C_END #endif + +/* +#ifndef Z7_ST +#ifdef _7ZIP_ST +#define Z7_ST +#endif +#endif +*/ diff --git a/libraries/lzma/C/7zVersion.h b/libraries/lzma/C/7zVersion.h index e9363d37be..7549239614 100644 --- a/libraries/lzma/C/7zVersion.h +++ b/libraries/lzma/C/7zVersion.h @@ -1,7 +1,7 @@ -#define MY_VER_MAJOR 21 -#define MY_VER_MINOR 07 +#define MY_VER_MAJOR 23 +#define MY_VER_MINOR 01 #define MY_VER_BUILD 0 -#define MY_VERSION_NUMBERS "21.07" +#define MY_VERSION_NUMBERS "23.01" #define MY_VERSION MY_VERSION_NUMBERS #ifdef MY_CPU_NAME @@ -10,12 +10,12 @@ #define MY_VERSION_CPU MY_VERSION #endif -#define MY_DATE "2021-12-26" +#define MY_DATE "2023-06-20" #undef MY_COPYRIGHT #undef MY_VERSION_COPYRIGHT_DATE #define MY_AUTHOR_NAME "Igor Pavlov" #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" -#define MY_COPYRIGHT_CR "Copyright (c) 1999-2021 Igor Pavlov" +#define MY_COPYRIGHT_CR "Copyright (c) 1999-2023 Igor Pavlov" #ifdef USE_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR diff --git a/libraries/lzma/C/7zWindows.h b/libraries/lzma/C/7zWindows.h new file mode 100644 index 0000000000..42c6db8bfc --- /dev/null +++ b/libraries/lzma/C/7zWindows.h @@ -0,0 +1,101 @@ +/* 7zWindows.h -- StdAfx +2023-04-02 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_7Z_WINDOWS_H +#define ZIP7_INC_7Z_WINDOWS_H + +#ifdef _WIN32 + +#if defined(__clang__) +# pragma clang diagnostic push +#endif + +#if defined(_MSC_VER) + +#pragma warning(push) +#pragma warning(disable : 4668) // '_WIN32_WINNT' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' + +#if _MSC_VER == 1900 +// for old kit10 versions +// #pragma warning(disable : 4255) // winuser.h(13979): warning C4255: 'GetThreadDpiAwarenessContext': +#endif +// win10 Windows Kit: +#endif // _MSC_VER + +#if defined(_MSC_VER) && _MSC_VER <= 1200 && !defined(_WIN64) +// for msvc6 without sdk2003 +#define RPC_NO_WINDOWS_H +#endif + +#if defined(__MINGW32__) || defined(__MINGW64__) +// #if defined(__GNUC__) && !defined(__clang__) +#include +#else +#include +#endif +// #include +// #include + +// but if precompiled with clang-cl then we need +// #include +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + +#if defined(_MSC_VER) && _MSC_VER <= 1200 && !defined(_WIN64) +#ifndef _W64 + +typedef long LONG_PTR, *PLONG_PTR; +typedef unsigned long ULONG_PTR, *PULONG_PTR; +typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; + +#define Z7_OLD_WIN_SDK +#endif // _W64 +#endif // _MSC_VER == 1200 + +#ifdef Z7_OLD_WIN_SDK + +#ifndef INVALID_FILE_ATTRIBUTES +#define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +#endif +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif +#ifndef FILE_SPECIAL_ACCESS +#define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) +#endif + +// ShlObj.h: +// #define BIF_NEWDIALOGSTYLE 0x0040 + +#pragma warning(disable : 4201) +// #pragma warning(disable : 4115) + +#undef VARIANT_TRUE +#define VARIANT_TRUE ((VARIANT_BOOL)-1) +#endif + +#endif // Z7_OLD_WIN_SDK + +#ifdef UNDER_CE +#undef VARIANT_TRUE +#define VARIANT_TRUE ((VARIANT_BOOL)-1) +#endif + + +#if defined(_MSC_VER) +#if _MSC_VER >= 1400 && _MSC_VER <= 1600 + // BaseTsd.h(148) : 'HandleToULong' : unreferenced inline function has been removed + // string.h + // #pragma warning(disable : 4514) +#endif +#endif + + +/* #include "7zTypes.h" */ + +#endif diff --git a/libraries/lzma/C/Alloc.c b/libraries/lzma/C/Alloc.c new file mode 100644 index 0000000000..d841bf20a3 --- /dev/null +++ b/libraries/lzma/C/Alloc.c @@ -0,0 +1,535 @@ +/* Alloc.c -- Memory allocation functions +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifdef _WIN32 +#include "7zWindows.h" +#endif +#include + +#include "Alloc.h" + +#ifdef _WIN32 +#ifdef Z7_LARGE_PAGES +#if defined(__clang__) || defined(__GNUC__) +typedef void (*Z7_voidFunction)(void); +#define MY_CAST_FUNC (Z7_voidFunction) +#elif defined(_MSC_VER) && _MSC_VER > 1920 +#define MY_CAST_FUNC (void *) +// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()' +#else +#define MY_CAST_FUNC +#endif +#endif // Z7_LARGE_PAGES +#endif // _WIN32 + +// #define SZ_ALLOC_DEBUG +/* #define SZ_ALLOC_DEBUG */ + +/* use SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef SZ_ALLOC_DEBUG + +#include +#include +static int g_allocCount = 0; +#ifdef _WIN32 +static int g_allocCountMid = 0; +static int g_allocCountBig = 0; +#endif + + +#define CONVERT_INT_TO_STR(charType, tempSize) \ + char temp[tempSize]; unsigned i = 0; \ + while (val >= 10) { temp[i++] = (char)('0' + (unsigned)(val % 10)); val /= 10; } \ + *s++ = (charType)('0' + (unsigned)val); \ + while (i != 0) { i--; *s++ = temp[i]; } \ + *s = 0; + +static void ConvertUInt64ToString(UInt64 val, char *s) +{ + CONVERT_INT_TO_STR(char, 24) +} + +#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + +static void ConvertUInt64ToHex(UInt64 val, char *s) +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0xF); + val >>= 4; + s[--i] = GET_HEX_CHAR(t); + } + while (i); +} + +#define DEBUG_OUT_STREAM stderr + +static void Print(const char *s) +{ + fputs(s, DEBUG_OUT_STREAM); +} + +static void PrintAligned(const char *s, size_t align) +{ + size_t len = strlen(s); + for(;;) + { + fputc(' ', DEBUG_OUT_STREAM); + if (len >= align) + break; + ++len; + } + Print(s); +} + +static void PrintLn(void) +{ + Print("\n"); +} + +static void PrintHex(UInt64 v, size_t align) +{ + char s[32]; + ConvertUInt64ToHex(v, s); + PrintAligned(s, align); +} + +static void PrintDec(int v, size_t align) +{ + char s[32]; + ConvertUInt64ToString((unsigned)v, s); + PrintAligned(s, align); +} + +static void PrintAddr(void *p) +{ + PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12); +} + + +#define PRINT_REALLOC(name, cnt, size, ptr) { \ + Print(name " "); \ + if (!ptr) PrintDec(cnt++, 10); \ + PrintHex(size, 10); \ + PrintAddr(ptr); \ + PrintLn(); } + +#define PRINT_ALLOC(name, cnt, size, ptr) { \ + Print(name " "); \ + PrintDec(cnt++, 10); \ + PrintHex(size, 10); \ + PrintAddr(ptr); \ + PrintLn(); } + +#define PRINT_FREE(name, cnt, ptr) if (ptr) { \ + Print(name " "); \ + PrintDec(--cnt, 10); \ + PrintAddr(ptr); \ + PrintLn(); } + +#else + +#ifdef _WIN32 +#define PRINT_ALLOC(name, cnt, size, ptr) +#endif +#define PRINT_FREE(name, cnt, ptr) +#define Print(s) +#define PrintLn() +#define PrintHex(v, align) +#define PrintAddr(p) + +#endif + + +/* +by specification: + malloc(non_NULL, 0) : returns NULL or a unique pointer value that can later be successfully passed to free() + realloc(NULL, size) : the call is equivalent to malloc(size) + realloc(non_NULL, 0) : the call is equivalent to free(ptr) + +in main compilers: + malloc(0) : returns non_NULL + realloc(NULL, 0) : returns non_NULL + realloc(non_NULL, 0) : returns NULL +*/ + + +void *MyAlloc(size_t size) +{ + if (size == 0) + return NULL; + // PRINT_ALLOC("Alloc ", g_allocCount, size, NULL) + #ifdef SZ_ALLOC_DEBUG + { + void *p = malloc(size); + if (p) + { + PRINT_ALLOC("Alloc ", g_allocCount, size, p) + } + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + PRINT_FREE("Free ", g_allocCount, address) + + free(address); +} + +void *MyRealloc(void *address, size_t size) +{ + if (size == 0) + { + MyFree(address); + return NULL; + } + // PRINT_REALLOC("Realloc ", g_allocCount, size, address) + #ifdef SZ_ALLOC_DEBUG + { + void *p = realloc(address, size); + if (p) + { + PRINT_REALLOC("Realloc ", g_allocCount, size, address) + } + return p; + } + #else + return realloc(address, size); + #endif +} + + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return NULL; + #ifdef SZ_ALLOC_DEBUG + { + void *p = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); + if (p) + { + PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, p) + } + return p; + } + #else + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); + #endif +} + +void MidFree(void *address) +{ + PRINT_FREE("Free-Mid", g_allocCountMid, address) + + if (!address) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifdef Z7_LARGE_PAGES + +#ifdef MEM_LARGE_PAGES + #define MY__MEM_LARGE_PAGES MEM_LARGE_PAGES +#else + #define MY__MEM_LARGE_PAGES 0x20000000 +#endif + +extern +SIZE_T g_LargePageSize; +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID); + +void SetLargePageSize(void) +{ + #ifdef Z7_LARGE_PAGES + SIZE_T size; + const + Func_GetLargePageMinimum fn = + (Func_GetLargePageMinimum) MY_CAST_FUNC GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), + "GetLargePageMinimum"); + if (!fn) + return; + size = fn(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + +#endif // Z7_LARGE_PAGES + +void *BigAlloc(size_t size) +{ + if (size == 0) + return NULL; + + PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL) + + #ifdef Z7_LARGE_PAGES + { + SIZE_T ps = g_LargePageSize; + if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) + { + size_t size2; + ps--; + size2 = (size + ps) & ~ps; + if (size2 >= size) + { + void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY__MEM_LARGE_PAGES, PAGE_READWRITE); + if (p) + { + PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p) + return p; + } + } + } + } + #endif + + return MidAlloc(size); +} + +void BigFree(void *address) +{ + PRINT_FREE("Free-Big", g_allocCountBig, address) + MidFree(address); +} + +#endif // _WIN32 + + +static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MyAlloc(size); } +static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MyFree(address); } +const ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +#ifdef _WIN32 +static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MidAlloc(size); } +static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MidFree(address); } +static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return BigAlloc(size); } +static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) BigFree(address); } +const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; +const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; +#endif + +/* + uintptr_t : C99 (optional) + : unsupported in VS6 +*/ + +#ifdef _WIN32 + typedef UINT_PTR UIntPtr; +#else + /* + typedef uintptr_t UIntPtr; + */ + typedef ptrdiff_t UIntPtr; +#endif + + +#define ADJUST_ALLOC_SIZE 0 +/* +#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1) +*/ +/* + Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if + MyAlloc() can return address that is NOT multiple of sizeof(void *). +*/ + + +/* +#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1)))) +*/ +#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1)))) + + +#if !defined(_WIN32) && defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) + #define USE_posix_memalign +#endif + +#ifndef USE_posix_memalign +#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align) +#endif + +/* + This posix_memalign() is for test purposes only. + We also need special Free() function instead of free(), + if this posix_memalign() is used. +*/ + +/* +static int posix_memalign(void **ptr, size_t align, size_t size) +{ + size_t newSize = size + align; + void *p; + void *pAligned; + *ptr = NULL; + if (newSize < size) + return 12; // ENOMEM + p = MyAlloc(newSize); + if (!p) + return 12; // ENOMEM + pAligned = MY_ALIGN_PTR_UP_PLUS(p, align); + ((void **)pAligned)[-1] = p; + *ptr = pAligned; + return 0; +} +*/ + +/* + ALLOC_ALIGN_SIZE >= sizeof(void *) + ALLOC_ALIGN_SIZE >= cache_line_size +*/ + +#define ALLOC_ALIGN_SIZE ((size_t)1 << 7) + +static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) +{ + #ifndef USE_posix_memalign + + void *p; + void *pAligned; + size_t newSize; + UNUSED_VAR(pp) + + /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned + block to prevent cache line sharing with another allocated blocks */ + + newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE; + if (newSize < size) + return NULL; + + p = MyAlloc(newSize); + + if (!p) + return NULL; + pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE); + + Print(" size="); PrintHex(size, 8); + Print(" a_size="); PrintHex(newSize, 8); + Print(" ptr="); PrintAddr(p); + Print(" a_ptr="); PrintAddr(pAligned); + PrintLn(); + + ((void **)pAligned)[-1] = p; + + return pAligned; + + #else + + void *p; + UNUSED_VAR(pp) + if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) + return NULL; + + Print(" posix_memalign="); PrintAddr(p); + PrintLn(); + + return p; + + #endif +} + + +static void SzAlignedFree(ISzAllocPtr pp, void *address) +{ + UNUSED_VAR(pp) + #ifndef USE_posix_memalign + if (address) + MyFree(((void **)address)[-1]); + #else + free(address); + #endif +} + + +const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree }; + + + +#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *)) + +/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ +#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] +/* +#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1] +*/ + +static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) +{ + const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); + void *adr; + void *pAligned; + size_t newSize; + size_t extra; + size_t alignSize = (size_t)1 << p->numAlignBits; + + if (alignSize < sizeof(void *)) + alignSize = sizeof(void *); + + if (p->offset >= alignSize) + return NULL; + + /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned + block to prevent cache line sharing with another allocated blocks */ + extra = p->offset & (sizeof(void *) - 1); + newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE; + if (newSize < size) + return NULL; + + adr = ISzAlloc_Alloc(p->baseAlloc, newSize); + + if (!adr) + return NULL; + + pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + + alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; + + PrintLn(); + Print("- Aligned: "); + Print(" size="); PrintHex(size, 8); + Print(" a_size="); PrintHex(newSize, 8); + Print(" ptr="); PrintAddr(adr); + Print(" a_ptr="); PrintAddr(pAligned); + PrintLn(); + + REAL_BLOCK_PTR_VAR(pAligned) = adr; + + return pAligned; +} + + +static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) +{ + if (address) + { + const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); + PrintLn(); + Print("- Aligned Free: "); + PrintLn(); + ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); + } +} + + +void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p) +{ + p->vt.Alloc = AlignOffsetAlloc_Alloc; + p->vt.Free = AlignOffsetAlloc_Free; +} diff --git a/libraries/lzma/C/Alloc.h b/libraries/lzma/C/Alloc.h new file mode 100644 index 0000000000..fac5b62fb9 --- /dev/null +++ b/libraries/lzma/C/Alloc.h @@ -0,0 +1,71 @@ +/* Alloc.h -- Memory allocation functions +2023-03-04 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_ALLOC_H +#define ZIP7_INC_ALLOC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* + MyFree(NULL) : is allowed, as free(NULL) + MyAlloc(0) : returns NULL : but malloc(0) is allowed to return NULL or non_NULL + MyRealloc(NULL, 0) : returns NULL : but realloc(NULL, 0) is allowed to return NULL or non_NULL +MyRealloc() is similar to realloc() for the following cases: + MyRealloc(non_NULL, 0) : returns NULL and always calls MyFree(ptr) + MyRealloc(NULL, non_ZERO) : returns NULL, if allocation failed + MyRealloc(non_NULL, non_ZERO) : returns NULL, if reallocation failed +*/ + +void *MyAlloc(size_t size); +void MyFree(void *address); +void *MyRealloc(void *address, size_t size); + +#ifdef _WIN32 + +#ifdef Z7_LARGE_PAGES +void SetLargePageSize(void); +#endif + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +extern const ISzAlloc g_Alloc; + +#ifdef _WIN32 +extern const ISzAlloc g_BigAlloc; +extern const ISzAlloc g_MidAlloc; +#else +#define g_BigAlloc g_AlignedAlloc +#define g_MidAlloc g_AlignedAlloc +#endif + +extern const ISzAlloc g_AlignedAlloc; + + +typedef struct +{ + ISzAlloc vt; + ISzAllocPtr baseAlloc; + unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */ + size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */ +} CAlignOffsetAlloc; + +void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p); + + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/Bcj2.c b/libraries/lzma/C/Bcj2.c index c7b956708f..7cb57ad62d 100644 --- a/libraries/lzma/C/Bcj2.c +++ b/libraries/lzma/C/Bcj2.c @@ -1,29 +1,24 @@ /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) -2021-02-09 : Igor Pavlov : Public domain */ +2023-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Bcj2.h" #include "CpuArch.h" -#define CProb UInt16 - #define kTopValue ((UInt32)1 << 24) -#define kNumModelBits 11 -#define kBitModelTotal (1 << kNumModelBits) +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 -#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound) -#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); -#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits)); +// UInt32 bcj2_stats[256 + 2][2]; void Bcj2Dec_Init(CBcj2Dec *p) { unsigned i; - - p->state = BCJ2_DEC_STATE_OK; + p->state = BCJ2_STREAM_RC; // BCJ2_DEC_STATE_OK; p->ip = 0; - p->temp[3] = 0; + p->temp = 0; p->range = 0; p->code = 0; for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) @@ -32,217 +27,248 @@ void Bcj2Dec_Init(CBcj2Dec *p) SRes Bcj2Dec_Decode(CBcj2Dec *p) { + UInt32 v = p->temp; + // const Byte *src; if (p->range <= 5) { - p->state = BCJ2_DEC_STATE_OK; + UInt32 code = p->code; + p->state = BCJ2_DEC_STATE_ERROR; /* for case if we return SZ_ERROR_DATA; */ for (; p->range != 5; p->range++) { - if (p->range == 1 && p->code != 0) + if (p->range == 1 && code != 0) return SZ_ERROR_DATA; - if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) { p->state = BCJ2_STREAM_RC; return SZ_OK; } - - p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; + code = (code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; + p->code = code; } - - if (p->code == 0xFFFFFFFF) + if (code == 0xffffffff) return SZ_ERROR_DATA; - - p->range = 0xFFFFFFFF; + p->range = 0xffffffff; } - else if (p->state >= BCJ2_DEC_STATE_ORIG_0) + // else { - while (p->state <= BCJ2_DEC_STATE_ORIG_3) + unsigned state = p->state; + // we check BCJ2_IS_32BIT_STREAM() here instead of check in the main loop + if (BCJ2_IS_32BIT_STREAM(state)) { - Byte *dest = p->dest; - if (dest == p->destLim) + const Byte *cur = p->bufs[state]; + if (cur == p->lims[state]) return SZ_OK; - *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0]; - p->state++; - p->dest = dest + 1; + p->bufs[state] = cur + 4; + { + const UInt32 ip = p->ip + 4; + v = GetBe32a(cur) - ip; + p->ip = ip; + } + state = BCJ2_DEC_STATE_ORIG_0; } - } - - /* - if (BCJ2_IS_32BIT_STREAM(p->state)) - { - const Byte *cur = p->bufs[p->state]; - if (cur == p->lims[p->state]) - return SZ_OK; - p->bufs[p->state] = cur + 4; - + if ((unsigned)(state - BCJ2_DEC_STATE_ORIG_0) < 4) { - UInt32 val; - Byte *dest; - SizeT rem; - - p->ip += 4; - val = GetBe32(cur) - p->ip; - dest = p->dest; - rem = p->destLim - dest; - if (rem < 4) + Byte *dest = p->dest; + for (;;) { - SizeT i; - SetUi32(p->temp, val); - for (i = 0; i < rem; i++) - dest[i] = p->temp[i]; - p->dest = dest + rem; - p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; - return SZ_OK; + if (dest == p->destLim) + { + p->state = state; + p->temp = v; + return SZ_OK; + } + *dest++ = (Byte)v; + p->dest = dest; + if (++state == BCJ2_DEC_STATE_ORIG_3 + 1) + break; + v >>= 8; } - SetUi32(dest, val); - p->temp[3] = (Byte)(val >> 24); - p->dest = dest + 4; - p->state = BCJ2_DEC_STATE_OK; } } - */ + // src = p->bufs[BCJ2_STREAM_MAIN]; for (;;) { + /* if (BCJ2_IS_32BIT_STREAM(p->state)) p->state = BCJ2_DEC_STATE_OK; else + */ { if (p->range < kTopValue) { if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) { p->state = BCJ2_STREAM_RC; + p->temp = v; return SZ_OK; } p->range <<= 8; p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; } - { const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; const Byte *srcLim; - Byte *dest; - SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src); - - if (num == 0) + Byte *dest = p->dest; { - p->state = BCJ2_STREAM_MAIN; - return SZ_OK; + const SizeT rem = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src); + SizeT num = (SizeT)(p->destLim - dest); + if (num >= rem) + num = rem; + #define NUM_ITERS 4 + #if (NUM_ITERS & (NUM_ITERS - 1)) == 0 + num &= ~((SizeT)NUM_ITERS - 1); // if (NUM_ITERS == (1 << x)) + #else + num -= num % NUM_ITERS; // if (NUM_ITERS != (1 << x)) + #endif + srcLim = src + num; } - - dest = p->dest; - if (num > (SizeT)(p->destLim - dest)) + + #define NUM_SHIFT_BITS 24 + #define ONE_ITER(indx) { \ + const unsigned b = src[indx]; \ + *dest++ = (Byte)b; \ + v = (v << NUM_SHIFT_BITS) | b; \ + if (((b + (0x100 - 0xe8)) & 0xfe) == 0) break; \ + if (((v - (((UInt32)0x0f << (NUM_SHIFT_BITS)) + 0x80)) & \ + ((((UInt32)1 << (4 + NUM_SHIFT_BITS)) - 0x1) << 4)) == 0) break; \ + /* ++dest */; /* v = b; */ } + + if (src != srcLim) + for (;;) { - num = (SizeT)(p->destLim - dest); - if (num == 0) - { - p->state = BCJ2_DEC_STATE_ORIG; - return SZ_OK; - } + /* The dependency chain of 2-cycle for (v) calculation is not big problem here. + But we can remove dependency chain with v = b in the end of loop. */ + ONE_ITER(0) + #if (NUM_ITERS > 1) + ONE_ITER(1) + #if (NUM_ITERS > 2) + ONE_ITER(2) + #if (NUM_ITERS > 3) + ONE_ITER(3) + #if (NUM_ITERS > 4) + ONE_ITER(4) + #if (NUM_ITERS > 5) + ONE_ITER(5) + #if (NUM_ITERS > 6) + ONE_ITER(6) + #if (NUM_ITERS > 7) + ONE_ITER(7) + #endif + #endif + #endif + #endif + #endif + #endif + #endif + + src += NUM_ITERS; + if (src == srcLim) + break; } - - srcLim = src + num; - if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80) - *dest = src[0]; - else for (;;) + if (src == srcLim) + #if (NUM_ITERS > 1) + for (;;) + #endif { - Byte b = *src; - *dest = b; - if (b != 0x0F) + #if (NUM_ITERS > 1) + if (src == p->lims[BCJ2_STREAM_MAIN] || dest == p->destLim) + #endif { - if ((b & 0xFE) == 0xE8) - break; - dest++; - if (++src != srcLim) - continue; - break; + const SizeT num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]); + p->bufs[BCJ2_STREAM_MAIN] = src; + p->dest = dest; + p->ip += (UInt32)num; + /* state BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ + p->state = + src == p->lims[BCJ2_STREAM_MAIN] ? + (unsigned)BCJ2_STREAM_MAIN : + (unsigned)BCJ2_DEC_STATE_ORIG; + p->temp = v; + return SZ_OK; } - dest++; - if (++src == srcLim) - break; - if ((*src & 0xF0) != 0x80) - continue; - *dest = *src; - break; + #if (NUM_ITERS > 1) + ONE_ITER(0) + src++; + #endif } - - num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]); - - if (src == srcLim) + { - p->temp[3] = src[-1]; - p->bufs[BCJ2_STREAM_MAIN] = src; + const SizeT num = (SizeT)(dest - p->dest); + p->dest = dest; // p->dest += num; + p->bufs[BCJ2_STREAM_MAIN] += num; // = src; p->ip += (UInt32)num; - p->dest += num; - p->state = - p->bufs[BCJ2_STREAM_MAIN] == - p->lims[BCJ2_STREAM_MAIN] ? - (unsigned)BCJ2_STREAM_MAIN : - (unsigned)BCJ2_DEC_STATE_ORIG; - return SZ_OK; } - { UInt32 bound, ttt; - CProb *prob; - Byte b = src[0]; - Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]); - - p->temp[3] = b; - p->bufs[BCJ2_STREAM_MAIN] = src + 1; - num++; - p->ip += (UInt32)num; - p->dest += num; - - prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0)); - - _IF_BIT_0 + CBcj2Prob *prob; // unsigned index; + /* + prob = p->probs + (unsigned)((Byte)v == 0xe8 ? + 2 + (Byte)(v >> 8) : + ((v >> 5) & 1)); // ((Byte)v < 0xe8 ? 0 : 1)); + */ { - _UPDATE_0 + const unsigned c = ((v + 0x17) >> 6) & 1; + prob = p->probs + (unsigned) + (((0 - c) & (Byte)(v >> NUM_SHIFT_BITS)) + c + ((v >> 5) & 1)); + // (Byte) + // 8x->0 : e9->1 : xxe8->xx+2 + // 8x->0x100 : e9->0x101 : xxe8->xx + // (((0x100 - (e & ~v)) & (0x100 | (v >> 8))) + (e & v)); + // (((0x101 + (~e | v)) & (0x100 | (v >> 8))) + (e & v)); + } + ttt = *prob; + bound = (p->range >> kNumBitModelTotalBits) * ttt; + if (p->code < bound) + { + // bcj2_stats[prob - p->probs][0]++; + p->range = bound; + *prob = (CBcj2Prob)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); continue; } - _UPDATE_1 - + { + // bcj2_stats[prob - p->probs][1]++; + p->range -= bound; + p->code -= bound; + *prob = (CBcj2Prob)(ttt - (ttt >> kNumMoveBits)); + } } } } - { - UInt32 val; - unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; + /* (v == 0xe8 ? 0 : 1) uses setcc instruction with additional zero register usage in x64 MSVC. */ + // const unsigned cj = ((Byte)v == 0xe8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; + const unsigned cj = (((v + 0x57) >> 6) & 1) + BCJ2_STREAM_CALL; const Byte *cur = p->bufs[cj]; Byte *dest; SizeT rem; - if (cur == p->lims[cj]) { p->state = cj; break; } - - val = GetBe32(cur); + v = GetBe32a(cur); p->bufs[cj] = cur + 4; - - p->ip += 4; - val -= p->ip; + { + const UInt32 ip = p->ip + 4; + v -= ip; + p->ip = ip; + } dest = p->dest; rem = (SizeT)(p->destLim - dest); - if (rem < 4) { - p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8; - p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8; - p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8; - p->temp[3] = (Byte)val; + if ((unsigned)rem > 0) { dest[0] = (Byte)v; v >>= 8; + if ((unsigned)rem > 1) { dest[1] = (Byte)v; v >>= 8; + if ((unsigned)rem > 2) { dest[2] = (Byte)v; v >>= 8; }}} + p->temp = v; p->dest = dest + rem; p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; break; } - - SetUi32(dest, val); - p->temp[3] = (Byte)(val >> 24); + SetUi32(dest, v) + v >>= 24; p->dest = dest + 4; } } @@ -252,6 +278,13 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) p->range <<= 8; p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; } - return SZ_OK; } + +#undef NUM_ITERS +#undef ONE_ITER +#undef NUM_SHIFT_BITS +#undef kTopValue +#undef kNumBitModelTotalBits +#undef kBitModelTotal +#undef kNumMoveBits diff --git a/libraries/lzma/C/Bcj2.h b/libraries/lzma/C/Bcj2.h index 8824080acf..4575545b62 100644 --- a/libraries/lzma/C/Bcj2.h +++ b/libraries/lzma/C/Bcj2.h @@ -1,8 +1,8 @@ -/* Bcj2.h -- BCJ2 Converter for x86 code -2014-11-10 : Igor Pavlov : Public domain */ +/* Bcj2.h -- BCJ2 converter for x86 code (Branch CALL/JUMP variant2) +2023-03-02 : Igor Pavlov : Public domain */ -#ifndef __BCJ2_H -#define __BCJ2_H +#ifndef ZIP7_INC_BCJ2_H +#define ZIP7_INC_BCJ2_H #include "7zTypes.h" @@ -26,37 +26,68 @@ enum BCJ2_DEC_STATE_ORIG_3, BCJ2_DEC_STATE_ORIG, - BCJ2_DEC_STATE_OK + BCJ2_DEC_STATE_ERROR /* after detected data error */ }; enum { BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS, - BCJ2_ENC_STATE_OK + BCJ2_ENC_STATE_FINISHED /* it's state after fully encoded stream */ }; -#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) +/* #define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) */ +#define BCJ2_IS_32BIT_STREAM(s) ((unsigned)((unsigned)(s) - (unsigned)BCJ2_STREAM_CALL) < 2) /* CBcj2Dec / CBcj2Enc bufs sizes: BUF_SIZE(n) = lims[n] - bufs[n] -bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4: +bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be multiply of 4: (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0 (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0 */ +// typedef UInt32 CBcj2Prob; +typedef UInt16 CBcj2Prob; + +/* +BCJ2 encoder / decoder internal requirements: + - If last bytes of stream contain marker (e8/e8/0f8x), then + there is also encoded symbol (0 : no conversion) in RC stream. + - One case of overlapped instructions is supported, + if last byte of converted instruction is (0f) and next byte is (8x): + marker [xx xx xx 0f] 8x + then the pair (0f 8x) is treated as marker. +*/ + +/* ---------- BCJ2 Decoder ---------- */ + /* CBcj2Dec: -dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: +(dest) is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: bufs[BCJ2_STREAM_MAIN] >= dest && - bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv + + bufs[BCJ2_STREAM_MAIN] - dest >= BUF_SIZE(BCJ2_STREAM_CALL) + BUF_SIZE(BCJ2_STREAM_JUMP) - tempReserv = 0 : for first call of Bcj2Dec_Decode - tempReserv = 4 : for any other calls of Bcj2Dec_Decode - overlap with offset = 1 is not allowed + reserve = bufs[BCJ2_STREAM_MAIN] - dest - + ( BUF_SIZE(BCJ2_STREAM_CALL) + + BUF_SIZE(BCJ2_STREAM_JUMP) ) + and additional conditions: + if (it's first call of Bcj2Dec_Decode() after Bcj2Dec_Init()) + { + (reserve != 1) : if (ver < v23.00) + } + else // if there are more than one calls of Bcj2Dec_Decode() after Bcj2Dec_Init()) + { + (reserve >= 6) : if (ver < v23.00) + (reserve >= 4) : if (ver >= v23.00) + We need that (reserve) because after first call of Bcj2Dec_Decode(), + CBcj2Dec::temp can contain up to 4 bytes for writing to (dest). + } + (reserve == 0) is allowed, if we decode full stream via single call of Bcj2Dec_Decode(). + (reserve == 0) also is allowed in case of multi-call, if we use fixed buffers, + and (reserve) is calculated from full (final) sizes of all streams before first call. */ typedef struct @@ -68,21 +99,65 @@ typedef struct unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ - UInt32 ip; - Byte temp[4]; + UInt32 ip; /* property of starting base for decoding */ + UInt32 temp; /* Byte temp[4]; */ UInt32 range; UInt32 code; - UInt16 probs[2 + 256]; + CBcj2Prob probs[2 + 256]; } CBcj2Dec; + +/* Note: + Bcj2Dec_Init() sets (CBcj2Dec::ip = 0) + if (ip != 0) property is required, the caller must set CBcj2Dec::ip after Bcj2Dec_Init() +*/ void Bcj2Dec_Init(CBcj2Dec *p); -/* Returns: SZ_OK or SZ_ERROR_DATA */ + +/* Bcj2Dec_Decode(): + returns: + SZ_OK + SZ_ERROR_DATA : if data in 5 starting bytes of BCJ2_STREAM_RC stream are not correct +*/ SRes Bcj2Dec_Decode(CBcj2Dec *p); -#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0) +/* To check that decoding was finished you can compare + sizes of processed streams with sizes known from another sources. + You must do at least one mandatory check from the two following options: + - the check for size of processed output (ORIG) stream. + - the check for size of processed input (MAIN) stream. + additional optional checks: + - the checks for processed sizes of all input streams (MAIN, CALL, JUMP, RC) + - the checks Bcj2Dec_IsMaybeFinished*() + also before actual decoding you can check that the + following condition is met for stream sizes: + ( size(ORIG) == size(MAIN) + size(CALL) + size(JUMP) ) +*/ +/* (state == BCJ2_STREAM_MAIN) means that decoder is ready for + additional input data in BCJ2_STREAM_MAIN stream. + Note that (state == BCJ2_STREAM_MAIN) is allowed for non-finished decoding. +*/ +#define Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) ((_p_)->state == BCJ2_STREAM_MAIN) +/* if the stream decoding was finished correctly, then range decoder + part of CBcj2Dec also was finished, and then (CBcj2Dec::code == 0). + Note that (CBcj2Dec::code == 0) is allowed for non-finished decoding. +*/ +#define Bcj2Dec_IsMaybeFinished_code(_p_) ((_p_)->code == 0) + +/* use Bcj2Dec_IsMaybeFinished() only as additional check + after at least one mandatory check from the two following options: + - the check for size of processed output (ORIG) stream. + - the check for size of processed input (MAIN) stream. +*/ +#define Bcj2Dec_IsMaybeFinished(_p_) ( \ + Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) && \ + Bcj2Dec_IsMaybeFinished_code(_p_)) + + + +/* ---------- BCJ2 Encoder ---------- */ typedef enum { @@ -91,6 +166,91 @@ typedef enum BCJ2_ENC_FINISH_MODE_END_STREAM } EBcj2Enc_FinishMode; +/* + BCJ2_ENC_FINISH_MODE_CONTINUE: + process non finished encoding. + It notifies the encoder that additional further calls + can provide more input data (src) than provided by current call. + In that case the CBcj2Enc encoder still can move (src) pointer + up to (srcLim), but CBcj2Enc encoder can store some of the last + processed bytes (up to 4 bytes) from src to internal CBcj2Enc::temp[] buffer. + at return: + (CBcj2Enc::src will point to position that includes + processed data and data copied to (temp[]) buffer) + That data from (temp[]) buffer will be used in further calls. + + BCJ2_ENC_FINISH_MODE_END_BLOCK: + finish encoding of current block (ended at srcLim) without RC flushing. + at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_ORIG) && + CBcj2Enc::src == CBcj2Enc::srcLim) + : it shows that block encoding was finished. And the encoder is + ready for new (src) data or for stream finish operation. + finished block means + { + CBcj2Enc has completed block encoding up to (srcLim). + (1 + 4 bytes) or (2 + 4 bytes) CALL/JUMP cortages will + not cross block boundary at (srcLim). + temporary CBcj2Enc buffer for (ORIG) src data is empty. + 3 output uncompressed streams (MAIN, CALL, JUMP) were flushed. + RC stream was not flushed. And RC stream will cross block boundary. + } + Note: some possible implementation of BCJ2 encoder could + write branch marker (e8/e8/0f8x) in one call of Bcj2Enc_Encode(), + and it could calculate symbol for RC in another call of Bcj2Enc_Encode(). + BCJ2 encoder uses ip/fileIp/fileSize/relatLimit values to calculate RC symbol. + And these CBcj2Enc variables can have different values in different Bcj2Enc_Encode() calls. + So caller must finish each block with BCJ2_ENC_FINISH_MODE_END_BLOCK + to ensure that RC symbol is calculated and written in proper block. + + BCJ2_ENC_FINISH_MODE_END_STREAM + finish encoding of stream (ended at srcLim) fully including RC flushing. + at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_FINISHED) + : it shows that stream encoding was finished fully, + and all output streams were flushed fully. + also Bcj2Enc_IsFinished() can be called. +*/ + + +/* + 32-bit relative offset in JUMP/CALL commands is + - (mod 4 GiB) for 32-bit x86 code + - signed Int32 for 64-bit x86-64 code + BCJ2 encoder also does internal relative to absolute address conversions. + And there are 2 possible ways to do it: + before v23: we used 32-bit variables and (mod 4 GiB) conversion + since v23: we use 64-bit variables and (signed Int32 offset) conversion. + The absolute address condition for conversion in v23: + ((UInt64)((Int64)ip64 - (Int64)fileIp64 + 5 + (Int32)offset) < (UInt64)fileSize64) + note that if (fileSize64 > 2 GiB). there is difference between + old (mod 4 GiB) way (v22) and new (signed Int32 offset) way (v23). + And new (v23) way is more suitable to encode 64-bit x86-64 code for (fileSize64 > 2 GiB) cases. +*/ + +/* +// for old (v22) way for conversion: +typedef UInt32 CBcj2Enc_ip_unsigned; +typedef Int32 CBcj2Enc_ip_signed; +#define BCJ2_ENC_FileSize_MAX ((UInt32)1 << 31) +*/ +typedef UInt64 CBcj2Enc_ip_unsigned; +typedef Int64 CBcj2Enc_ip_signed; + +/* maximum size of file that can be used for conversion condition */ +#define BCJ2_ENC_FileSize_MAX ((CBcj2Enc_ip_unsigned)0 - 2) + +/* default value of fileSize64_minus1 variable that means + that absolute address limitation will not be used */ +#define BCJ2_ENC_FileSizeField_UNLIMITED ((CBcj2Enc_ip_unsigned)0 - 1) + +/* calculate value that later can be set to CBcj2Enc::fileSize64_minus1 */ +#define BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize) \ + ((CBcj2Enc_ip_unsigned)(fileSize) - 1) + +/* set CBcj2Enc::fileSize64_minus1 variable from size of file */ +#define Bcj2Enc_SET_FileSize(p, fileSize) \ + (p)->fileSize64_minus1 = BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize); + + typedef struct { Byte *bufs[BCJ2_NUM_STREAMS]; @@ -101,45 +261,71 @@ typedef struct unsigned state; EBcj2Enc_FinishMode finishMode; - Byte prevByte; + Byte context; + Byte flushRem; + Byte isFlushState; Byte cache; UInt32 range; UInt64 low; UInt64 cacheSize; + + // UInt32 context; // for marker version, it can include marker flag. - UInt32 ip; - - /* 32-bit ralative offset in JUMP/CALL commands is - - (mod 4 GB) in 32-bit mode - - signed Int32 in 64-bit mode - We use (mod 4 GB) check for fileSize. - Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */ - UInt32 fileIp; - UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */ - UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */ + /* (ip64) and (fileIp64) correspond to virtual source stream position + that doesn't include data in temp[] */ + CBcj2Enc_ip_unsigned ip64; /* current (ip) position */ + CBcj2Enc_ip_unsigned fileIp64; /* start (ip) position of current file */ + CBcj2Enc_ip_unsigned fileSize64_minus1; /* size of current file (for conversion limitation) */ + UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)) : 0 means disable_conversion */ + // UInt32 relatExcludeBits; UInt32 tempTarget; - unsigned tempPos; - Byte temp[4 * 2]; - - unsigned flushPos; - - UInt16 probs[2 + 256]; + unsigned tempPos; /* the number of bytes that were copied to temp[] buffer + (tempPos <= 4) outside of Bcj2Enc_Encode() */ + // Byte temp[4]; // for marker version + Byte temp[8]; + CBcj2Prob probs[2 + 256]; } CBcj2Enc; void Bcj2Enc_Init(CBcj2Enc *p); -void Bcj2Enc_Encode(CBcj2Enc *p); -#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos) -#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5) +/* +Bcj2Enc_Encode(): at exit: + p->State < BCJ2_NUM_STREAMS : we need more buffer space for output stream + (bufs[p->State] == lims[p->State]) + p->State == BCJ2_ENC_STATE_ORIG : we need more data in input src stream + (src == srcLim) + p->State == BCJ2_ENC_STATE_FINISHED : after fully encoded stream +*/ +void Bcj2Enc_Encode(CBcj2Enc *p); -#define BCJ2_RELAT_LIMIT_NUM_BITS 26 -#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS) +/* Bcj2Enc encoder can look ahead for up 4 bytes of source stream. + CBcj2Enc::tempPos : is the number of bytes that were copied from input stream to temp[] buffer. + (CBcj2Enc::src) after Bcj2Enc_Encode() is starting position after + fully processed data and after data copied to temp buffer. + So if the caller needs to get real number of fully processed input + bytes (without look ahead data in temp buffer), + the caller must subtruct (CBcj2Enc::tempPos) value from processed size + value that is calculated based on current (CBcj2Enc::src): + cur_processed_pos = Calc_Big_Processed_Pos(enc.src)) - + Bcj2Enc_Get_AvailInputSize_in_Temp(&enc); +*/ +/* get the size of input data that was stored in temp[] buffer: */ +#define Bcj2Enc_Get_AvailInputSize_in_Temp(p) ((p)->tempPos) -/* limit for CBcj2Enc::fileSize variable */ -#define BCJ2_FileSize_MAX ((UInt32)1 << 31) +#define Bcj2Enc_IsFinished(p) ((p)->flushRem == 0) + +/* Note : the decoder supports overlapping of marker (0f 80). + But we can eliminate such overlapping cases by setting + the limit for relative offset conversion as + CBcj2Enc::relatLimit <= (0x0f << 24) == (240 MiB) +*/ +/* default value for CBcj2Enc::relatLimit */ +#define BCJ2_ENC_RELAT_LIMIT_DEFAULT ((UInt32)0x0f << 24) +#define BCJ2_ENC_RELAT_LIMIT_MAX ((UInt32)1 << 31) +// #define BCJ2_RELAT_EXCLUDE_NUM_BITS 5 EXTERN_C_END diff --git a/libraries/lzma/C/Bcj2Enc.c b/libraries/lzma/C/Bcj2Enc.c new file mode 100644 index 0000000000..79460bb150 --- /dev/null +++ b/libraries/lzma/C/Bcj2Enc.c @@ -0,0 +1,506 @@ +/* Bcj2Enc.c -- BCJ2 Encoder converter for x86 code (Branch CALL/JUMP variant2) +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +/* #define SHOW_STAT */ +#ifdef SHOW_STAT +#include +#define PRF2(s) printf("%s ip=%8x tempPos=%d src= %8x\n", s, (unsigned)p->ip64, p->tempPos, (unsigned)(p->srcLim - p->src)); +#else +#define PRF2(s) +#endif + +#include "Bcj2.h" +#include "CpuArch.h" + +#define kTopValue ((UInt32)1 << 24) +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +void Bcj2Enc_Init(CBcj2Enc *p) +{ + unsigned i; + p->state = BCJ2_ENC_STATE_ORIG; + p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + p->context = 0; + p->flushRem = 5; + p->isFlushState = 0; + p->cache = 0; + p->range = 0xffffffff; + p->low = 0; + p->cacheSize = 1; + p->ip64 = 0; + p->fileIp64 = 0; + p->fileSize64_minus1 = BCJ2_ENC_FileSizeField_UNLIMITED; + p->relatLimit = BCJ2_ENC_RELAT_LIMIT_DEFAULT; + // p->relatExcludeBits = 0; + p->tempPos = 0; + for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) + p->probs[i] = kBitModelTotal >> 1; +} + +// Z7_NO_INLINE +Z7_FORCE_INLINE +static BoolInt Bcj2_RangeEnc_ShiftLow(CBcj2Enc *p) +{ + const UInt32 low = (UInt32)p->low; + const unsigned high = (unsigned) + #if defined(Z7_MSC_VER_ORIGINAL) \ + && defined(MY_CPU_X86) \ + && defined(MY_CPU_LE) \ + && !defined(MY_CPU_64BIT) + // we try to rid of __aullshr() call in MSVS-x86 + (((const UInt32 *)&p->low)[1]); // [1] : for little-endian only + #else + (p->low >> 32); + #endif + if (low < (UInt32)0xff000000 || high != 0) + { + Byte *buf = p->bufs[BCJ2_STREAM_RC]; + do + { + if (buf == p->lims[BCJ2_STREAM_RC]) + { + p->state = BCJ2_STREAM_RC; + p->bufs[BCJ2_STREAM_RC] = buf; + return True; + } + *buf++ = (Byte)(p->cache + high); + p->cache = 0xff; + } + while (--p->cacheSize); + p->bufs[BCJ2_STREAM_RC] = buf; + p->cache = (Byte)(low >> 24); + } + p->cacheSize++; + p->low = low << 8; + return False; +} + + +/* +We can use 2 alternative versions of code: +1) non-marker version: + Byte CBcj2Enc::context + Byte temp[8]; + Last byte of marker (e8/e9/[0f]8x) can be written to temp[] buffer. + Encoder writes last byte of marker (e8/e9/[0f]8x) to dest, only in conjunction + with writing branch symbol to range coder in same Bcj2Enc_Encode_2() call. + +2) marker version: + UInt32 CBcj2Enc::context + Byte CBcj2Enc::temp[4]; + MARKER_FLAG in CBcj2Enc::context shows that CBcj2Enc::context contains finded marker. + it's allowed that + one call of Bcj2Enc_Encode_2() writes last byte of marker (e8/e9/[0f]8x) to dest, + and another call of Bcj2Enc_Encode_2() does offset conversion. + So different values of (fileIp) and (fileSize) are possible + in these different Bcj2Enc_Encode_2() calls. + +Also marker version requires additional if((v & MARKER_FLAG) == 0) check in main loop. +So we use non-marker version. +*/ + +/* + Corner cases with overlap in multi-block. + before v23: there was one corner case, where converted instruction + could start in one sub-stream and finish in next sub-stream. + If multi-block (solid) encoding is used, + and BCJ2_ENC_FINISH_MODE_END_BLOCK is used for each sub-stream. + and (0f) is last byte of previous sub-stream + and (8x) is first byte of current sub-stream + then (0f 8x) pair is treated as marker by BCJ2 encoder and decoder. + BCJ2 encoder can converts 32-bit offset for that (0f 8x) cortage, + if that offset meets limit requirements. + If encoder allows 32-bit offset conversion for such overlap case, + then the data in 3 uncompressed BCJ2 streams for some sub-stream + can depend from data of previous sub-stream. + That corner case is not big problem, and it's rare case. + Since v23.00 we do additional check to prevent conversions in such overlap cases. +*/ + +/* + Bcj2Enc_Encode_2() output variables at exit: + { + if (Bcj2Enc_Encode_2() exits with (p->state == BCJ2_ENC_STATE_ORIG)) + { + it means that encoder needs more input data. + if (p->srcLim == p->src) at exit, then + { + (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM) + all input data were read and processed, and we are ready for + new input data. + } + else + { + (p->srcLim != p->src) + (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE) + The encoder have found e8/e9/0f_8x marker, + and p->src points to last byte of that marker, + Bcj2Enc_Encode_2() needs more input data to get totally + 5 bytes (last byte of marker and 32-bit branch offset) + as continuous array starting from p->src. + (p->srcLim - p->src < 5) requirement is met after exit. + So non-processed resedue from p->src to p->srcLim is always less than 5 bytes. + } + } + } +*/ + +Z7_NO_INLINE +static void Bcj2Enc_Encode_2(CBcj2Enc *p) +{ + if (!p->isFlushState) + { + const Byte *src; + UInt32 v; + { + const unsigned state = p->state; + if (BCJ2_IS_32BIT_STREAM(state)) + { + Byte *cur = p->bufs[state]; + if (cur == p->lims[state]) + return; + SetBe32a(cur, p->tempTarget) + p->bufs[state] = cur + 4; + } + } + p->state = BCJ2_ENC_STATE_ORIG; // for main reason of exit + src = p->src; + v = p->context; + + // #define WRITE_CONTEXT p->context = v; // for marker version + #define WRITE_CONTEXT p->context = (Byte)v; + #define WRITE_CONTEXT_AND_SRC p->src = src; WRITE_CONTEXT + + for (;;) + { + // const Byte *src; + // UInt32 v; + CBcj2Enc_ip_unsigned ip; + if (p->range < kTopValue) + { + // to reduce register pressure and code size: we save and restore local variables. + WRITE_CONTEXT_AND_SRC + if (Bcj2_RangeEnc_ShiftLow(p)) + return; + p->range <<= 8; + src = p->src; + v = p->context; + } + // src = p->src; + // #define MARKER_FLAG ((UInt32)1 << 17) + // if ((v & MARKER_FLAG) == 0) // for marker version + { + const Byte *srcLim; + Byte *dest = p->bufs[BCJ2_STREAM_MAIN]; + { + const SizeT remSrc = (SizeT)(p->srcLim - src); + SizeT rem = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest); + if (rem >= remSrc) + rem = remSrc; + srcLim = src + rem; + } + /* p->context contains context of previous byte: + bits [0 : 7] : src[-1], if (src) was changed in this call + bits [8 : 31] : are undefined for non-marker version + */ + // v = p->context; + #define NUM_SHIFT_BITS 24 + #define CONV_FLAG ((UInt32)1 << 16) + #define ONE_ITER { \ + b = src[0]; \ + *dest++ = (Byte)b; \ + v = (v << NUM_SHIFT_BITS) | b; \ + if (((b + (0x100 - 0xe8)) & 0xfe) == 0) break; \ + if (((v - (((UInt32)0x0f << (NUM_SHIFT_BITS)) + 0x80)) & \ + ((((UInt32)1 << (4 + NUM_SHIFT_BITS)) - 0x1) << 4)) == 0) break; \ + src++; if (src == srcLim) { break; } } + + if (src != srcLim) + for (;;) + { + /* clang can generate ineffective code with setne instead of two jcc instructions. + we can use 2 iterations and external (unsigned b) to avoid that ineffective code genaration. */ + unsigned b; + ONE_ITER + ONE_ITER + } + + ip = p->ip64 + (CBcj2Enc_ip_unsigned)(SizeT)(dest - p->bufs[BCJ2_STREAM_MAIN]); + p->bufs[BCJ2_STREAM_MAIN] = dest; + p->ip64 = ip; + + if (src == srcLim) + { + WRITE_CONTEXT_AND_SRC + if (src != p->srcLim) + { + p->state = BCJ2_STREAM_MAIN; + return; + } + /* (p->src == p->srcLim) + (p->state == BCJ2_ENC_STATE_ORIG) */ + if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM) + return; + /* (p->finishMode == BCJ2_ENC_FINISH_MODE_END_STREAM */ + // (p->flushRem == 5); + p->isFlushState = 1; + break; + } + src++; + // p->src = src; + } + // ip = p->ip; // for marker version + /* marker was found */ + /* (v) contains marker that was found: + bits [NUM_SHIFT_BITS : NUM_SHIFT_BITS + 7] + : value of src[-2] : xx/xx/0f + bits [0 : 7] : value of src[-1] : e8/e9/8x + */ + { + { + #if NUM_SHIFT_BITS != 24 + v &= ~(UInt32)CONV_FLAG; + #endif + // UInt32 relat = 0; + if ((SizeT)(p->srcLim - src) >= 4) + { + /* + if (relat != 0 || (Byte)v != 0xe8) + BoolInt isBigOffset = True; + */ + const UInt32 relat = GetUi32(src); + /* + #define EXCLUDE_FLAG ((UInt32)1 << 4) + #define NEED_CONVERT(rel) ((((rel) + EXCLUDE_FLAG) & (0 - EXCLUDE_FLAG * 2)) != 0) + if (p->relatExcludeBits != 0) + { + const UInt32 flag = (UInt32)1 << (p->relatExcludeBits - 1); + isBigOffset = (((relat + flag) & (0 - flag * 2)) != 0); + } + // isBigOffset = False; // for debug + */ + ip -= p->fileIp64; + // Use the following if check, if (ip) is 64-bit: + if (ip > (((v + 0x20) >> 5) & 1)) // 23.00 : we eliminate milti-block overlap for (Of 80) and (e8/e9) + if ((CBcj2Enc_ip_unsigned)((CBcj2Enc_ip_signed)ip + 4 + (Int32)relat) <= p->fileSize64_minus1) + if (((UInt32)(relat + p->relatLimit) >> 1) < p->relatLimit) + v |= CONV_FLAG; + } + else if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE) + { + // (p->srcLim - src < 4) + // /* + // for non-marker version + p->ip64--; // p->ip = ip - 1; + p->bufs[BCJ2_STREAM_MAIN]--; + src--; + v >>= NUM_SHIFT_BITS; + // (0 < p->srcLim - p->src <= 4) + // */ + // v |= MARKER_FLAG; // for marker version + /* (p->state == BCJ2_ENC_STATE_ORIG) */ + WRITE_CONTEXT_AND_SRC + return; + } + { + const unsigned c = ((v + 0x17) >> 6) & 1; + CBcj2Prob *prob = p->probs + (unsigned) + (((0 - c) & (Byte)(v >> NUM_SHIFT_BITS)) + c + ((v >> 5) & 1)); + /* + ((Byte)v == 0xe8 ? 2 + ((Byte)(v >> 8)) : + ((Byte)v < 0xe8 ? 0 : 1)); // ((v >> 5) & 1)); + */ + const unsigned ttt = *prob; + const UInt32 bound = (p->range >> kNumBitModelTotalBits) * ttt; + if ((v & CONV_FLAG) == 0) + { + // static int yyy = 0; yyy++; printf("\n!needConvert = %d\n", yyy); + // v = (Byte)v; // for marker version + p->range = bound; + *prob = (CBcj2Prob)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); + // WRITE_CONTEXT_AND_SRC + continue; + } + p->low += bound; + p->range -= bound; + *prob = (CBcj2Prob)(ttt - (ttt >> kNumMoveBits)); + } + // p->context = src[3]; + { + // const unsigned cj = ((Byte)v == 0xe8 ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP); + const unsigned cj = (((v + 0x57) >> 6) & 1) + BCJ2_STREAM_CALL; + ip = p->ip64; + v = GetUi32(src); // relat + ip += 4; + p->ip64 = ip; + src += 4; + // p->src = src; + { + const UInt32 absol = (UInt32)ip + v; + Byte *cur = p->bufs[cj]; + v >>= 24; + // WRITE_CONTEXT + if (cur == p->lims[cj]) + { + p->state = cj; + p->tempTarget = absol; + WRITE_CONTEXT_AND_SRC + return; + } + SetBe32a(cur, absol) + p->bufs[cj] = cur + 4; + } + } + } + } + } // end of loop + } + + for (; p->flushRem != 0; p->flushRem--) + if (Bcj2_RangeEnc_ShiftLow(p)) + return; + p->state = BCJ2_ENC_STATE_FINISHED; +} + + +/* +BCJ2 encoder needs look ahead for up to 4 bytes in (src) buffer. +So base function Bcj2Enc_Encode_2() + in BCJ2_ENC_FINISH_MODE_CONTINUE mode can return with + (p->state == BCJ2_ENC_STATE_ORIG && p->src < p->srcLim) +Bcj2Enc_Encode() solves that look ahead problem by using p->temp[] buffer. + so if (p->state == BCJ2_ENC_STATE_ORIG) after Bcj2Enc_Encode(), + then (p->src == p->srcLim). + And the caller's code is simpler with Bcj2Enc_Encode(). +*/ + +Z7_NO_INLINE +void Bcj2Enc_Encode(CBcj2Enc *p) +{ + PRF2("\n----") + if (p->tempPos != 0) + { + /* extra: number of bytes that were copied from (src) to (temp) buffer in this call */ + unsigned extra = 0; + /* We will touch only minimal required number of bytes in input (src) stream. + So we will add input bytes from (src) stream to temp[] with step of 1 byte. + We don't add new bytes to temp[] before Bcj2Enc_Encode_2() call + in first loop iteration because + - previous call of Bcj2Enc_Encode() could use another (finishMode), + - previous call could finish with (p->state != BCJ2_ENC_STATE_ORIG). + the case with full temp[] buffer (p->tempPos == 4) is possible here. + */ + for (;;) + { + // (0 < p->tempPos <= 5) // in non-marker version + /* p->src : the current src data position including extra bytes + that were copied to temp[] buffer in this call */ + const Byte *src = p->src; + const Byte *srcLim = p->srcLim; + const EBcj2Enc_FinishMode finishMode = p->finishMode; + if (src != srcLim) + { + /* if there are some src data after the data copied to temp[], + then we use MODE_CONTINUE for temp data */ + p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + } + p->src = p->temp; + p->srcLim = p->temp + p->tempPos; + PRF2(" ") + Bcj2Enc_Encode_2(p); + { + const unsigned num = (unsigned)(p->src - p->temp); + const unsigned tempPos = p->tempPos - num; + unsigned i; + p->tempPos = tempPos; + for (i = 0; i < tempPos; i++) + p->temp[i] = p->temp[(SizeT)i + num]; + // tempPos : number of bytes in temp buffer + p->src = src; + p->srcLim = srcLim; + p->finishMode = finishMode; + if (p->state != BCJ2_ENC_STATE_ORIG) + { + // (p->tempPos <= 4) // in non-marker version + /* if (the reason of exit from Bcj2Enc_Encode_2() + is not BCJ2_ENC_STATE_ORIG), + then we exit from Bcj2Enc_Encode() with same reason */ + // optional code begin : we rollback (src) and tempPos, if it's possible: + if (extra >= tempPos) + extra = tempPos; + p->src = src - extra; + p->tempPos = tempPos - extra; + // optional code end : rollback of (src) and tempPos + return; + } + /* (p->tempPos <= 4) + (p->state == BCJ2_ENC_STATE_ORIG) + so encoder needs more data than in temp[] */ + if (src == srcLim) + return; // src buffer has no more input data. + /* (src != srcLim) + so we can provide more input data from src for Bcj2Enc_Encode_2() */ + if (extra >= tempPos) + { + /* (extra >= tempPos) means that temp buffer contains + only data from src buffer of this call. + So now we can encode without temp buffer */ + p->src = src - tempPos; // rollback (src) + p->tempPos = 0; + break; + } + // we append one additional extra byte from (src) to temp[] buffer: + p->temp[tempPos] = *src; + p->tempPos = tempPos + 1; + // (0 < p->tempPos <= 5) // in non-marker version + p->src = src + 1; + extra++; + } + } + } + + PRF2("++++") + // (p->tempPos == 0) + Bcj2Enc_Encode_2(p); + PRF2("====") + + if (p->state == BCJ2_ENC_STATE_ORIG) + { + const Byte *src = p->src; + const Byte *srcLim = p->srcLim; + const unsigned rem = (unsigned)(srcLim - src); + /* (rem <= 4) here. + if (p->src != p->srcLim), then + - we copy non-processed bytes from (p->src) to temp[] buffer, + - we set p->src equal to p->srcLim. + */ + if (rem) + { + unsigned i = 0; + p->src = srcLim; + p->tempPos = rem; + // (0 < p->tempPos <= 4) + do + p->temp[i] = src[i]; + while (++i != rem); + } + // (p->tempPos <= 4) + // (p->src == p->srcLim) + } +} + +#undef PRF2 +#undef CONV_FLAG +#undef MARKER_FLAG +#undef WRITE_CONTEXT +#undef WRITE_CONTEXT_AND_SRC +#undef ONE_ITER +#undef NUM_SHIFT_BITS +#undef kTopValue +#undef kNumBitModelTotalBits +#undef kBitModelTotal +#undef kNumMoveBits diff --git a/libraries/lzma/C/Bra.c b/libraries/lzma/C/Bra.c index 3b854d9cad..22e0e478ec 100644 --- a/libraries/lzma/C/Bra.c +++ b/libraries/lzma/C/Bra.c @@ -1,230 +1,420 @@ -/* Bra.c -- Converters for RISC code -2021-02-09 : Igor Pavlov : Public domain */ +/* Bra.c -- Branch converters for RISC code +2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" -#include "CpuArch.h" #include "Bra.h" +#include "CpuArch.h" +#include "RotateDefs.h" + +#if defined(MY_CPU_SIZEOF_POINTER) \ + && ( MY_CPU_SIZEOF_POINTER == 4 \ + || MY_CPU_SIZEOF_POINTER == 8) + #define BR_CONV_USE_OPT_PC_PTR +#endif + +#ifdef BR_CONV_USE_OPT_PC_PTR +#define BR_PC_INIT pc -= (UInt32)(SizeT)p; +#define BR_PC_GET (pc + (UInt32)(SizeT)p) +#else +#define BR_PC_INIT pc += (UInt32)size; +#define BR_PC_GET (pc - (UInt32)(SizeT)(lim - p)) +// #define BR_PC_INIT +// #define BR_PC_GET (pc + (UInt32)(SizeT)(p - data)) +#endif + +#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c; +// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c; + +#define Z7_BRANCH_CONV(name) z7_BranchConv_ ## name + +#define Z7_BRANCH_FUNC_MAIN(name) \ +static \ +Z7_FORCE_INLINE \ +Z7_ATTRIB_NO_VECTOR \ +Byte *Z7_BRANCH_CONV(name)(Byte *p, SizeT size, UInt32 pc, int encoding) -SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +#define Z7_BRANCH_FUNC_IMP(name, m, encoding) \ +Z7_NO_INLINE \ +Z7_ATTRIB_NO_VECTOR \ +Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \ + { return Z7_BRANCH_CONV(name)(data, size, pc, encoding); } \ + +#ifdef Z7_EXTRACT_ONLY +#define Z7_BRANCH_FUNCS_IMP(name) \ + Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC, 0) +#else +#define Z7_BRANCH_FUNCS_IMP(name) \ + Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC, 0) \ + Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC, 1) +#endif + +#if defined(__clang__) +#define BR_EXTERNAL_FOR +#define BR_NEXT_ITERATION continue; +#else +#define BR_EXTERNAL_FOR for (;;) +#define BR_NEXT_ITERATION break; +#endif + +#if defined(__clang__) && (__clang_major__ >= 8) \ + || defined(__GNUC__) && (__GNUC__ >= 1000) \ + // GCC is not good for __builtin_expect() here + /* || defined(_MSC_VER) && (_MSC_VER >= 1920) */ + // #define Z7_unlikely [[unlikely]] + // #define Z7_LIKELY(x) (__builtin_expect((x), 1)) + #define Z7_UNLIKELY(x) (__builtin_expect((x), 0)) + // #define Z7_likely [[likely]] +#else + // #define Z7_LIKELY(x) (x) + #define Z7_UNLIKELY(x) (x) + // #define Z7_likely +#endif + + +Z7_BRANCH_FUNC_MAIN(ARM64) { - Byte *p; + // Byte *p = data; const Byte *lim; - size &= ~(size_t)3; - ip += 4; - p = data; - lim = data + size; + const UInt32 flag = (UInt32)1 << (24 - 4); + const UInt32 mask = ((UInt32)1 << 24) - (flag << 1); + size &= ~(SizeT)3; + // if (size == 0) return p; + lim = p + size; + BR_PC_INIT + pc -= 4; // because (p) will point to next instruction + + BR_EXTERNAL_FOR + { + // Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + for (;;) + { + UInt32 v; + if Z7_UNLIKELY(p == lim) + return p; + v = GetUi32a(p); + p += 4; + if Z7_UNLIKELY(((v - 0x94000000) & 0xfc000000) == 0) + { + UInt32 c = BR_PC_GET >> 2; + BR_CONVERT_VAL(v, c) + v &= 0x03ffffff; + v |= 0x94000000; + SetUi32a(p - 4, v) + BR_NEXT_ITERATION + } + // v = rotlFixed(v, 8); v += (flag << 8) - 0x90; if Z7_UNLIKELY((v & ((mask << 8) + 0x9f)) == 0) + v -= 0x90000000; if Z7_UNLIKELY((v & 0x9f000000) == 0) + { + UInt32 z, c; + // v = rotrFixed(v, 8); + v += flag; if Z7_UNLIKELY(v & mask) continue; + z = (v & 0xffffffe0) | (v >> 26); + c = (BR_PC_GET >> (12 - 3)) & ~(UInt32)7; + BR_CONVERT_VAL(z, c) + v &= 0x1f; + v |= 0x90000000; + v |= z << 26; + v |= 0x00ffffe0 & ((z & (((flag << 1) - 1))) - flag); + SetUi32a(p - 4, v) + } + } + } +} +Z7_BRANCH_FUNCS_IMP(ARM64) - if (encoding) +Z7_BRANCH_FUNC_MAIN(ARM) +{ + // Byte *p = data; + const Byte *lim; + size &= ~(SizeT)3; + lim = p + size; + BR_PC_INIT + /* in ARM: branch offset is relative to the +2 instructions from current instruction. + (p) will point to next instruction */ + pc += 8 - 4; + for (;;) { for (;;) { - if (p >= lim) - return (SizeT)(p - data); - p += 4; - if (p[-1] == 0xEB) - break; + if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break; + if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break; } { - UInt32 v = GetUi32(p - 4); - v <<= 2; - v += ip + (UInt32)(p - data); - v >>= 2; - v &= 0x00FFFFFF; - v |= 0xEB000000; - SetUi32(p - 4, v); + UInt32 v = GetUi32a(p - 4); + UInt32 c = BR_PC_GET >> 2; + BR_CONVERT_VAL(v, c) + v &= 0x00ffffff; + v |= 0xeb000000; + SetUi32a(p - 4, v) } } +} +Z7_BRANCH_FUNCS_IMP(ARM) + +Z7_BRANCH_FUNC_MAIN(PPC) +{ + // Byte *p = data; + const Byte *lim; + size &= ~(SizeT)3; + lim = p + size; + BR_PC_INIT + pc -= 4; // because (p) will point to next instruction + for (;;) { + UInt32 v; for (;;) { - if (p >= lim) - return (SizeT)(p - data); + if Z7_UNLIKELY(p == lim) + return p; + // v = GetBe32a(p); + v = *(UInt32 *)(void *)p; p += 4; - if (p[-1] == 0xEB) - break; + // if ((v & 0xfc000003) == 0x48000001) break; + // if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) break; + if Z7_UNLIKELY( + ((v - Z7_CONV_BE_TO_NATIVE_CONST32(0x48000001)) + & Z7_CONV_BE_TO_NATIVE_CONST32(0xfc000003)) == 0) break; } { - UInt32 v = GetUi32(p - 4); - v <<= 2; - v -= ip + (UInt32)(p - data); - v >>= 2; - v &= 0x00FFFFFF; - v |= 0xEB000000; - SetUi32(p - 4, v); + v = Z7_CONV_NATIVE_TO_BE_32(v); + { + UInt32 c = BR_PC_GET; + BR_CONVERT_VAL(v, c) + } + v &= 0x03ffffff; + v |= 0x48000000; + SetBe32a(p - 4, v) } } } +Z7_BRANCH_FUNCS_IMP(PPC) -SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +#ifdef Z7_CPU_FAST_ROTATE_SUPPORTED +#define BR_SPARC_USE_ROTATE +#endif + +Z7_BRANCH_FUNC_MAIN(SPARC) { - Byte *p; + // Byte *p = data; const Byte *lim; - size &= ~(size_t)1; - p = data; - lim = data + size - 4; - - if (encoding) - + const UInt32 flag = (UInt32)1 << 22; + size &= ~(SizeT)3; + lim = p + size; + BR_PC_INIT + pc -= 4; // because (p) will point to next instruction for (;;) { - UInt32 b1; + UInt32 v; for (;;) { - UInt32 b3; - if (p > lim) - return (SizeT)(p - data); - b1 = p[1]; - b3 = p[3]; - p += 2; - b1 ^= 8; - if ((b3 & b1) >= 0xF8) + if Z7_UNLIKELY(p == lim) + return p; + /* // the code without GetBe32a(): + { const UInt32 v = GetUi16a(p) & 0xc0ff; p += 4; if (v == 0x40 || v == 0xc07f) break; } + */ + v = GetBe32a(p); + p += 4; + #ifdef BR_SPARC_USE_ROTATE + v = rotlFixed(v, 2); + v += (flag << 2) - 1; + if Z7_UNLIKELY((v & (3 - (flag << 3))) == 0) + #else + v += (UInt32)5 << 29; + v ^= (UInt32)7 << 29; + v += flag; + if Z7_UNLIKELY((v & (0 - (flag << 1))) == 0) + #endif break; } { - UInt32 v = - ((UInt32)b1 << 19) - + (((UInt32)p[1] & 0x7) << 8) - + (((UInt32)p[-2] << 11)) - + (p[0]); - - p += 2; + // UInt32 v = GetBe32a(p - 4); + #ifndef BR_SPARC_USE_ROTATE + v <<= 2; + #endif { - UInt32 cur = (ip + (UInt32)(p - data)) >> 1; - v += cur; + UInt32 c = BR_PC_GET; + BR_CONVERT_VAL(v, c) } - - p[-4] = (Byte)(v >> 11); - p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7)); - p[-2] = (Byte)v; - p[-1] = (Byte)(0xF8 | (v >> 8)); + v &= (flag << 3) - 1; + #ifdef BR_SPARC_USE_ROTATE + v -= (flag << 2) - 1; + v = rotrFixed(v, 2); + #else + v -= (flag << 2); + v >>= 2; + v |= (UInt32)1 << 30; + #endif + SetBe32a(p - 4, v) } } +} +Z7_BRANCH_FUNCS_IMP(SPARC) + + +Z7_BRANCH_FUNC_MAIN(ARMT) +{ + // Byte *p = data; + Byte *lim; + size &= ~(SizeT)1; + // if (size == 0) return p; + if (size <= 2) return p; + size -= 2; + lim = p + size; + BR_PC_INIT + /* in ARM: branch offset is relative to the +2 instructions from current instruction. + (p) will point to the +2 instructions from current instruction */ + // pc += 4 - 4; + // if (encoding) pc -= 0xf800 << 1; else pc += 0xf800 << 1; + // #define ARMT_TAIL_PROC { goto armt_tail; } + #define ARMT_TAIL_PROC { return p; } - for (;;) + do { - UInt32 b1; + /* in MSVC 32-bit x86 compilers: + UInt32 version : it loads value from memory with movzx + Byte version : it loads value to 8-bit register (AL/CL) + movzx version is slightly faster in some cpus + */ + unsigned b1; + // Byte / unsigned + b1 = p[1]; + // optimized version to reduce one (p >= lim) check: + // unsigned a1 = p[1]; b1 = p[3]; p += 2; if Z7_LIKELY((b1 & (a1 ^ 8)) < 0xf8) for (;;) { - UInt32 b3; - if (p > lim) - return (SizeT)(p - data); - b1 = p[1]; - b3 = p[3]; - p += 2; - b1 ^= 8; - if ((b3 & b1) >= 0xF8) - break; + unsigned b3; // Byte / UInt32 + /* (Byte)(b3) normalization can use low byte computations in MSVC. + It gives smaller code, and no loss of speed in some compilers/cpus. + But new MSVC 32-bit x86 compilers use more slow load + from memory to low byte register in that case. + So we try to use full 32-bit computations for faster code. + */ + // if (p >= lim) { ARMT_TAIL_PROC } b3 = b1 + 8; b1 = p[3]; p += 2; if ((b3 & b1) >= 0xf8) break; + if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b3 = p[3]; p += 2; if Z7_UNLIKELY((b3 & (b1 ^ 8)) >= 0xf8) break; + if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b1 = p[3]; p += 2; if Z7_UNLIKELY((b1 & (b3 ^ 8)) >= 0xf8) break; } { + /* we can adjust pc for (0xf800) to rid of (& 0x7FF) operation. + But gcc/clang for arm64 can use bfi instruction for full code here */ UInt32 v = - ((UInt32)b1 << 19) + ((UInt32)GetUi16a(p - 2) << 11) | + ((UInt32)GetUi16a(p) & 0x7FF); + /* + UInt32 v = + ((UInt32)p[1 - 2] << 19) + (((UInt32)p[1] & 0x7) << 8) + (((UInt32)p[-2] << 11)) + (p[0]); - + */ p += 2; { - UInt32 cur = (ip + (UInt32)(p - data)) >> 1; - v -= cur; + UInt32 c = BR_PC_GET >> 1; + BR_CONVERT_VAL(v, c) } - + SetUi16a(p - 4, (UInt16)(((v >> 11) & 0x7ff) | 0xf000)) + SetUi16a(p - 2, (UInt16)(v | 0xf800)) /* - SetUi16(p - 4, (UInt16)(((v >> 11) & 0x7FF) | 0xF000)); - SetUi16(p - 2, (UInt16)(v | 0xF800)); - */ - p[-4] = (Byte)(v >> 11); - p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7)); + p[-3] = (Byte)(0xf0 | ((v >> 19) & 0x7)); p[-2] = (Byte)v; - p[-1] = (Byte)(0xF8 | (v >> 8)); + p[-1] = (Byte)(0xf8 | (v >> 8)); + */ } } + while (p < lim); + return p; + // armt_tail: + // if ((Byte)((lim[1] & 0xf8)) != 0xf0) { lim += 2; } return lim; + // return (Byte *)(lim + ((Byte)((lim[1] ^ 0xf0) & 0xf8) == 0 ? 0 : 2)); + // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2)); + // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2)); } +Z7_BRANCH_FUNCS_IMP(ARMT) -SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) -{ - Byte *p; - const Byte *lim; - size &= ~(size_t)3; - ip -= 4; - p = data; - lim = data + size; - - for (;;) - { - for (;;) - { - if (p >= lim) - return (SizeT)(p - data); - p += 4; - /* if ((v & 0xFC000003) == 0x48000001) */ - if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) - break; - } - { - UInt32 v = GetBe32(p - 4); - if (encoding) - v += ip + (UInt32)(p - data); - else - v -= ip + (UInt32)(p - data); - v &= 0x03FFFFFF; - v |= 0x48000000; - SetBe32(p - 4, v); - } - } -} - +// #define BR_IA64_NO_INLINE -SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +Z7_BRANCH_FUNC_MAIN(IA64) { - Byte *p; + // Byte *p = data; const Byte *lim; - size &= ~(size_t)3; - ip -= 4; - p = data; - lim = data + size; - + size &= ~(SizeT)15; + lim = p + size; + pc -= 1 << 4; + pc >>= 4 - 1; + // pc -= 1 << 1; + for (;;) { + unsigned m; for (;;) { - if (p >= lim) - return (SizeT)(p - data); - /* - v = GetBe32(p); - p += 4; - m = v + ((UInt32)5 << 29); - m ^= (UInt32)7 << 29; - m += (UInt32)1 << 22; - if ((m & ((UInt32)0x1FF << 23)) == 0) - break; - */ - p += 4; - if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) || - (p[-4] == 0x7F && (p[-3] >= 0xC0))) + if Z7_UNLIKELY(p == lim) + return p; + m = (unsigned)((UInt32)0x334b0000 >> (*p & 0x1e)); + p += 16; + pc += 1 << 1; + if (m &= 3) break; } { - UInt32 v = GetBe32(p - 4); - v <<= 2; - if (encoding) - v += ip + (UInt32)(p - data); - else - v -= ip + (UInt32)(p - data); - - v &= 0x01FFFFFF; - v -= (UInt32)1 << 24; - v ^= 0xFF000000; - v >>= 2; - v |= 0x40000000; - SetBe32(p - 4, v); + p += (ptrdiff_t)m * 5 - 20; // negative value is expected here. + do + { + const UInt32 t = + #if defined(MY_CPU_X86_OR_AMD64) + // we use 32-bit load here to reduce code size on x86: + GetUi32(p); + #else + GetUi16(p); + #endif + UInt32 z = GetUi32(p + 1) >> m; + p += 5; + if (((t >> m) & (0x70 << 1)) == 0 + && ((z - (0x5000000 << 1)) & (0xf000000 << 1)) == 0) + { + UInt32 v = (UInt32)((0x8fffff << 1) | 1) & z; + z ^= v; + #ifdef BR_IA64_NO_INLINE + v |= (v & ((UInt32)1 << (23 + 1))) >> 3; + { + UInt32 c = pc; + BR_CONVERT_VAL(v, c) + } + v &= (0x1fffff << 1) | 1; + #else + { + if (encoding) + { + // pc &= ~(0xc00000 << 1); // we just need to clear at least 2 bits + pc &= (0x1fffff << 1) | 1; + v += pc; + } + else + { + // pc |= 0xc00000 << 1; // we need to set at least 2 bits + pc |= ~(UInt32)((0x1fffff << 1) | 1); + v -= pc; + } + } + v &= ~(UInt32)(0x600000 << 1); + #endif + v += (0x700000 << 1); + v &= (0x8fffff << 1) | 1; + z |= v; + z <<= m; + SetUi32(p + 1 - 5, z) + } + m++; + } + while (m &= 3); // while (m < 4); } } } +Z7_BRANCH_FUNCS_IMP(IA64) diff --git a/libraries/lzma/C/Bra.h b/libraries/lzma/C/Bra.h index 855e37a6b5..a4ee568e21 100644 --- a/libraries/lzma/C/Bra.h +++ b/libraries/lzma/C/Bra.h @@ -1,64 +1,99 @@ /* Bra.h -- Branch converters for executables -2013-01-18 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __BRA_H -#define __BRA_H +#ifndef ZIP7_INC_BRA_H +#define ZIP7_INC_BRA_H #include "7zTypes.h" EXTERN_C_BEGIN +#define Z7_BRANCH_CONV_DEC(name) z7_BranchConv_ ## name ## _Dec +#define Z7_BRANCH_CONV_ENC(name) z7_BranchConv_ ## name ## _Enc +#define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec +#define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc + +#define Z7_BRANCH_CONV_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc) +#define Z7_BRANCH_CONV_ST_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc, UInt32 *state) + +typedef Z7_BRANCH_CONV_DECL( (*z7_Func_BranchConv)); +typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt)); + +#define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0 +Z7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_DEC(X86)); +Z7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_ENC(X86)); + +#define Z7_BRANCH_FUNCS_DECL(name) \ +Z7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_DEC(name)); \ +Z7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_ENC(name)); + +Z7_BRANCH_FUNCS_DECL(ARM64) +Z7_BRANCH_FUNCS_DECL(ARM) +Z7_BRANCH_FUNCS_DECL(ARMT) +Z7_BRANCH_FUNCS_DECL(PPC) +Z7_BRANCH_FUNCS_DECL(SPARC) +Z7_BRANCH_FUNCS_DECL(IA64) + /* -These functions convert relative addresses to absolute addresses -in CALL instructions to increase the compression ratio. - - In: - data - data buffer - size - size of data - ip - current virtual Instruction Pinter (IP) value - state - state variable for x86 converter - encoding - 0 (for decoding), 1 (for encoding) - - Out: - state - state variable for x86 converter +These functions convert data that contain CPU instructions. +Each such function converts relative addresses to absolute addresses in some +branch instructions: CALL (in all converters) and JUMP (X86 converter only). +Such conversion allows to increase compression ratio, if we compress that data. + +There are 2 types of converters: + Byte * Conv_RISC (Byte *data, SizeT size, UInt32 pc); + Byte * ConvSt_X86(Byte *data, SizeT size, UInt32 pc, UInt32 *state); +Each Converter supports 2 versions: one for encoding +and one for decoding (_Enc/_Dec postfixes in function name). - Returns: - The number of processed bytes. If you call these functions with multiple calls, - you must start next call with first byte after block of processed bytes. +In params: + data : data buffer + size : size of data + pc : current virtual Program Counter (Instruction Pinter) value +In/Out param: + state : pointer to state variable (for X86 converter only) + +Return: + The pointer to position in (data) buffer after last byte that was processed. + If the caller calls converter again, it must call it starting with that position. + But the caller is allowed to move data in buffer. so pointer to + current processed position also will be changed for next call. + Also the caller must increase internal (pc) value for next call. +Each converter has some characteristics: Endian, Alignment, LookAhead. Type Endian Alignment LookAhead - x86 little 1 4 + X86 little 1 4 ARMT little 2 2 ARM little 4 0 + ARM64 little 4 0 PPC big 4 0 SPARC big 4 0 IA64 little 16 0 - size must be >= Alignment + LookAhead, if it's not last block. - If (size < Alignment + LookAhead), converter returns 0. - - Example: + (data) must be aligned for (Alignment). + processed size can be calculated as: + SizeT processed = Conv(data, size, pc) - data; + if (processed == 0) + it means that converter needs more data for processing. + If (size < Alignment + LookAhead) + then (processed == 0) is allowed. - UInt32 ip = 0; - for () - { - ; size must be >= Alignment + LookAhead, if it's not last block - SizeT processed = Convert(data, size, ip, 1); - data += processed; - size -= processed; - ip += processed; - } +Example code for conversion in loop: + UInt32 pc = 0; + size = 0; + for (;;) + { + size += Load_more_input_data(data + size); + SizeT processed = Conv(data, size, pc) - data; + if (processed == 0 && no_more_input_data_after_size) + break; // we stop convert loop + data += processed; + size -= processed; + pc += processed; + } */ -#define x86_Convert_Init(state) { state = 0; } -SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); -SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); - EXTERN_C_END #endif diff --git a/libraries/lzma/C/Bra86.c b/libraries/lzma/C/Bra86.c index 10a0fbd161..d81f392ae0 100644 --- a/libraries/lzma/C/Bra86.c +++ b/libraries/lzma/C/Bra86.c @@ -1,82 +1,187 @@ -/* Bra86.c -- Converter for x86 code (BCJ) -2021-02-09 : Igor Pavlov : Public domain */ +/* Bra86.c -- Branch converter for X86 code (BCJ) +2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Bra.h" +#include "CpuArch.h" -#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) -SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +#if defined(MY_CPU_SIZEOF_POINTER) \ + && ( MY_CPU_SIZEOF_POINTER == 4 \ + || MY_CPU_SIZEOF_POINTER == 8) + #define BR_CONV_USE_OPT_PC_PTR +#endif + +#ifdef BR_CONV_USE_OPT_PC_PTR +#define BR_PC_INIT pc -= (UInt32)(SizeT)p; // (MY_uintptr_t) +#define BR_PC_GET (pc + (UInt32)(SizeT)p) +#else +#define BR_PC_INIT pc += (UInt32)size; +#define BR_PC_GET (pc - (UInt32)(SizeT)(lim - p)) +// #define BR_PC_INIT +// #define BR_PC_GET (pc + (UInt32)(SizeT)(p - data)) +#endif + +#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c; +// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c; + +#define Z7_BRANCH_CONV_ST(name) z7_BranchConvSt_ ## name + +#define BR86_NEED_CONV_FOR_MS_BYTE(b) ((((b) + 1) & 0xfe) == 0) + +#ifdef MY_CPU_LE_UNALIGN + #define BR86_PREPARE_BCJ_SCAN const UInt32 v = GetUi32(p) ^ 0xe8e8e8e8; + #define BR86_IS_BCJ_BYTE(n) ((v & ((UInt32)0xfe << (n) * 8)) == 0) +#else + #define BR86_PREPARE_BCJ_SCAN + // bad for MSVC X86 (partial write to byte reg): + #define BR86_IS_BCJ_BYTE(n) ((p[n - 4] & 0xfe) == 0xe8) + // bad for old MSVC (partial write to byte reg): + // #define BR86_IS_BCJ_BYTE(n) (((*p ^ 0xe8) & 0xfe) == 0) +#endif + +static +Z7_FORCE_INLINE +Z7_ATTRIB_NO_VECTOR +Byte *Z7_BRANCH_CONV_ST(X86)(Byte *p, SizeT size, UInt32 pc, UInt32 *state, int encoding) { - SizeT pos = 0; - UInt32 mask = *state & 7; if (size < 5) - return 0; - size -= 4; - ip += 5; + return p; + { + // Byte *p = data; + const Byte *lim = p + size - 4; + unsigned mask = (unsigned)*state; // & 7; +#ifdef BR_CONV_USE_OPT_PC_PTR + /* if BR_CONV_USE_OPT_PC_PTR is defined: we need to adjust (pc) for (+4), + because call/jump offset is relative to the next instruction. + if BR_CONV_USE_OPT_PC_PTR is not defined : we don't need to adjust (pc) for (+4), + because BR_PC_GET uses (pc - (lim - p)), and lim was adjusted for (-4) before. + */ + pc += 4; +#endif + BR_PC_INIT + goto start; - for (;;) + for (;; mask |= 4) { - Byte *p = data + pos; - const Byte *limit = data + size; - for (; p < limit; p++) - if ((*p & 0xFE) == 0xE8) - break; - + // cont: mask |= 4; + start: + if (p >= lim) + goto fin; { - SizeT d = (SizeT)(p - data) - pos; - pos = (SizeT)(p - data); - if (p >= limit) - { - *state = (d > 2 ? 0 : mask >> (unsigned)d); - return pos; - } - if (d > 2) - mask = 0; - else - { - mask >>= (unsigned)d; - if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1]))) - { - mask = (mask >> 1) | 4; - pos++; - continue; - } - } + BR86_PREPARE_BCJ_SCAN + p += 4; + if (BR86_IS_BCJ_BYTE(0)) { goto m0; } mask >>= 1; + if (BR86_IS_BCJ_BYTE(1)) { goto m1; } mask >>= 1; + if (BR86_IS_BCJ_BYTE(2)) { goto m2; } mask = 0; + if (BR86_IS_BCJ_BYTE(3)) { goto a3; } } + goto main_loop; - if (Test86MSByte(p[4])) + m0: p--; + m1: p--; + m2: p--; + if (mask == 0) + goto a3; + if (p > lim) + goto fin_p; + + // if (((0x17u >> mask) & 1) == 0) + if (mask > 4 || mask == 3) + { + mask >>= 1; + continue; // goto cont; + } + mask >>= 1; + if (BR86_NEED_CONV_FOR_MS_BYTE(p[mask])) + continue; // goto cont; + // if (!BR86_NEED_CONV_FOR_MS_BYTE(p[3])) continue; // goto cont; { - UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); - UInt32 cur = ip + (UInt32)pos; - pos += 5; - if (encoding) - v += cur; - else - v -= cur; - if (mask != 0) + UInt32 v = GetUi32(p); + UInt32 c; + v += (1 << 24); if (v & 0xfe000000) continue; // goto cont; + c = BR_PC_GET; + BR_CONVERT_VAL(v, c) { - unsigned sh = (mask & 6) << 2; - if (Test86MSByte((Byte)(v >> sh))) + mask <<= 3; + if (BR86_NEED_CONV_FOR_MS_BYTE(v >> mask)) { - v ^= (((UInt32)0x100 << sh) - 1); - if (encoding) - v += cur; - else - v -= cur; + v ^= (((UInt32)0x100 << mask) - 1); + #ifdef MY_CPU_X86 + // for X86 : we can recalculate (c) to reduce register pressure + c = BR_PC_GET; + #endif + BR_CONVERT_VAL(v, c) } mask = 0; } - p[1] = (Byte)v; - p[2] = (Byte)(v >> 8); - p[3] = (Byte)(v >> 16); - p[4] = (Byte)(0 - ((v >> 24) & 1)); + // v = (v & ((1 << 24) - 1)) - (v & (1 << 24)); + v &= (1 << 25) - 1; v -= (1 << 24); + SetUi32(p, v) + p += 4; + goto main_loop; } - else + + main_loop: + if (p >= lim) + goto fin; + for (;;) { - mask = (mask >> 1) | 4; - pos++; + BR86_PREPARE_BCJ_SCAN + p += 4; + if (BR86_IS_BCJ_BYTE(0)) { goto a0; } + if (BR86_IS_BCJ_BYTE(1)) { goto a1; } + if (BR86_IS_BCJ_BYTE(2)) { goto a2; } + if (BR86_IS_BCJ_BYTE(3)) { goto a3; } + if (p >= lim) + goto fin; + } + + a0: p--; + a1: p--; + a2: p--; + a3: + if (p > lim) + goto fin_p; + // if (!BR86_NEED_CONV_FOR_MS_BYTE(p[3])) continue; // goto cont; + { + UInt32 v = GetUi32(p); + UInt32 c; + v += (1 << 24); if (v & 0xfe000000) continue; // goto cont; + c = BR_PC_GET; + BR_CONVERT_VAL(v, c) + // v = (v & ((1 << 24) - 1)) - (v & (1 << 24)); + v &= (1 << 25) - 1; v -= (1 << 24); + SetUi32(p, v) + p += 4; + goto main_loop; } } + +fin_p: + p--; +fin: + // the following processing for tail is optional and can be commented + /* + lim += 4; + for (; p < lim; p++, mask >>= 1) + if ((*p & 0xfe) == 0xe8) + break; + */ + *state = (UInt32)mask; + return p; + } } + + +#define Z7_BRANCH_CONV_ST_FUNC_IMP(name, m, encoding) \ +Z7_NO_INLINE \ +Z7_ATTRIB_NO_VECTOR \ +Byte *m(name)(Byte *data, SizeT size, UInt32 pc, UInt32 *state) \ + { return Z7_BRANCH_CONV_ST(name)(data, size, pc, state, encoding); } + +Z7_BRANCH_CONV_ST_FUNC_IMP(X86, Z7_BRANCH_CONV_ST_DEC, 0) +#ifndef Z7_EXTRACT_ONLY +Z7_BRANCH_CONV_ST_FUNC_IMP(X86, Z7_BRANCH_CONV_ST_ENC, 1) +#endif diff --git a/libraries/lzma/C/BraIA64.c b/libraries/lzma/C/BraIA64.c deleted file mode 100644 index d1dbc62c55..0000000000 --- a/libraries/lzma/C/BraIA64.c +++ /dev/null @@ -1,53 +0,0 @@ -/* BraIA64.c -- Converter for IA-64 code -2017-01-26 : Igor Pavlov : Public domain */ - -#include "Precomp.h" - -#include "CpuArch.h" -#include "Bra.h" - -SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) -{ - SizeT i; - if (size < 16) - return 0; - size -= 16; - i = 0; - do - { - unsigned m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3; - if (m) - { - m++; - do - { - Byte *p = data + (i + (size_t)m * 5 - 8); - if (((p[3] >> m) & 15) == 5 - && (((p[-1] | ((UInt32)p[0] << 8)) >> m) & 0x70) == 0) - { - unsigned raw = GetUi32(p); - unsigned v = raw >> m; - v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3); - - v <<= 4; - if (encoding) - v += ip + (UInt32)i; - else - v -= ip + (UInt32)i; - v >>= 4; - - v &= 0x1FFFFF; - v += 0x700000; - v &= 0x8FFFFF; - raw &= ~((UInt32)0x8FFFFF << m); - raw |= (v << m); - SetUi32(p, raw); - } - } - while (++m <= 4); - } - i += 16; - } - while (i <= size); - return i; -} diff --git a/libraries/lzma/C/Compiler.h b/libraries/lzma/C/Compiler.h index a9816fa5ad..185a52deb5 100644 --- a/libraries/lzma/C/Compiler.h +++ b/libraries/lzma/C/Compiler.h @@ -1,12 +1,37 @@ -/* Compiler.h -2021-01-05 : Igor Pavlov : Public domain */ +/* Compiler.h : Compiler specific defines and pragmas +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __7Z_COMPILER_H -#define __7Z_COMPILER_H +#ifndef ZIP7_INC_COMPILER_H +#define ZIP7_INC_COMPILER_H + +#if defined(__clang__) +# define Z7_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#endif +#if defined(__clang__) && defined(__apple_build_version__) +# define Z7_APPLE_CLANG_VERSION Z7_CLANG_VERSION +#elif defined(__clang__) +# define Z7_LLVM_CLANG_VERSION Z7_CLANG_VERSION +#elif defined(__GNUC__) +# define Z7_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +#ifdef _MSC_VER +#if !defined(__clang__) && !defined(__GNUC__) +#define Z7_MSC_VER_ORIGINAL _MSC_VER +#endif +#endif + +#if defined(__MINGW32__) || defined(__MINGW64__) +#define Z7_MINGW +#endif + +// #pragma GCC diagnostic ignored "-Wunknown-pragmas" + +#ifdef __clang__ +// padding size of '' with 4 bytes to alignment boundary +#pragma GCC diagnostic ignored "-Wpadded" +#endif - #ifdef __clang__ - #pragma clang diagnostic ignored "-Wunused-private-field" - #endif #ifdef _MSC_VER @@ -17,24 +42,115 @@ #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int #endif - #if _MSC_VER >= 1300 - #pragma warning(disable : 4996) // This function or variable may be unsafe - #else - #pragma warning(disable : 4511) // copy constructor could not be generated - #pragma warning(disable : 4512) // assignment operator could not be generated - #pragma warning(disable : 4514) // unreferenced inline function has been removed - #pragma warning(disable : 4702) // unreachable code - #pragma warning(disable : 4710) // not inlined - #pragma warning(disable : 4714) // function marked as __forceinline not inlined - #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information - #endif +#if defined(_MSC_VER) && _MSC_VER >= 1800 +#pragma warning(disable : 4464) // relative include path contains '..' +#endif + +// == 1200 : -O1 : for __forceinline +// >= 1900 : -O1 : for printf +#pragma warning(disable : 4710) // function not inlined + +#if _MSC_VER < 1900 +// winnt.h: 'Int64ShllMod32' +#pragma warning(disable : 4514) // unreferenced inline function has been removed +#endif + +#if _MSC_VER < 1300 +// #pragma warning(disable : 4702) // unreachable code +// Bra.c : -O1: +#pragma warning(disable : 4714) // function marked as __forceinline not inlined +#endif + +/* +#if _MSC_VER > 1400 && _MSC_VER <= 1900 +// strcat: This function or variable may be unsafe +// sysinfoapi.h: kit10: GetVersion was declared deprecated +#pragma warning(disable : 4996) +#endif +*/ + +#if _MSC_VER > 1200 +// -Wall warnings + +#pragma warning(disable : 4711) // function selected for automatic inline expansion +#pragma warning(disable : 4820) // '2' bytes padding added after data member + +#if _MSC_VER >= 1400 && _MSC_VER < 1920 +// 1400: string.h: _DBG_MEMCPY_INLINE_ +// 1600 - 191x : smmintrin.h __cplusplus' +// is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' +#pragma warning(disable : 4668) + +// 1400 - 1600 : WinDef.h : 'FARPROC' : +// 1900 - 191x : immintrin.h: _readfsbase_u32 +// no function prototype given : converting '()' to '(void)' +#pragma warning(disable : 4255) +#endif + +#if _MSC_VER >= 1914 +// Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified +#pragma warning(disable : 5045) +#endif + +#endif // _MSC_VER > 1200 +#endif // _MSC_VER + + +#if defined(__clang__) && (__clang_major__ >= 4) + #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \ + _Pragma("clang loop unroll(disable)") \ + _Pragma("clang loop vectorize(disable)") + #define Z7_ATTRIB_NO_VECTORIZE +#elif defined(__GNUC__) && (__GNUC__ >= 5) + #define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) + // __attribute__((optimize("no-unroll-loops"))); + #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE +#elif defined(_MSC_VER) && (_MSC_VER >= 1920) + #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \ + _Pragma("loop( no_vector )") + #define Z7_ATTRIB_NO_VECTORIZE +#else + #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + #define Z7_ATTRIB_NO_VECTORIZE +#endif + +#if defined(MY_CPU_X86_OR_AMD64) && ( \ + defined(__clang__) && (__clang_major__ >= 4) \ + || defined(__GNUC__) && (__GNUC__ >= 5)) + #define Z7_ATTRIB_NO_SSE __attribute__((__target__("no-sse"))) +#else + #define Z7_ATTRIB_NO_SSE +#endif + +#define Z7_ATTRIB_NO_VECTOR \ + Z7_ATTRIB_NO_VECTORIZE \ + Z7_ATTRIB_NO_SSE + + +#if defined(__clang__) && (__clang_major__ >= 8) \ + || defined(__GNUC__) && (__GNUC__ >= 1000) \ + /* || defined(_MSC_VER) && (_MSC_VER >= 1920) */ + // GCC is not good for __builtin_expect() + #define Z7_LIKELY(x) (__builtin_expect((x), 1)) + #define Z7_UNLIKELY(x) (__builtin_expect((x), 0)) + // #define Z7_unlikely [[unlikely]] + // #define Z7_likely [[likely]] +#else + #define Z7_LIKELY(x) (x) + #define Z7_UNLIKELY(x) (x) + // #define Z7_likely +#endif - #ifdef __clang__ - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - #pragma clang diagnostic ignored "-Wmicrosoft-exception-spec" - // #pragma clang diagnostic ignored "-Wreserved-id-macro" - #endif +#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 36000)) +#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wreserved-macro-identifier\"") +#define Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \ + _Pragma("GCC diagnostic pop") +#else +#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER +#define Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #define UNUSED_VAR(x) (void)x; diff --git a/libraries/lzma/C/CpuArch.c b/libraries/lzma/C/CpuArch.c index fa9afe3970..33f8a3ab4c 100644 --- a/libraries/lzma/C/CpuArch.c +++ b/libraries/lzma/C/CpuArch.c @@ -1,187 +1,318 @@ /* CpuArch.c -- CPU specific code -2021-07-13 : Igor Pavlov : Public domain */ +2023-05-18 : Igor Pavlov : Public domain */ #include "Precomp.h" +// #include + #include "CpuArch.h" #ifdef MY_CPU_X86_OR_AMD64 -#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) -#define USE_ASM +#undef NEED_CHECK_FOR_CPUID +#if !defined(MY_CPU_AMD64) +#define NEED_CHECK_FOR_CPUID #endif -#if !defined(USE_ASM) && _MSC_VER >= 1500 -#include +/* + cpuid instruction supports (subFunction) parameter in ECX, + that is used only with some specific (function) parameter values. + But we always use only (subFunction==0). +*/ +/* + __cpuid(): MSVC and GCC/CLANG use same function/macro name + but parameters are different. + We use MSVC __cpuid() parameters style for our z7_x86_cpuid() function. +*/ + +#if defined(__GNUC__) /* && (__GNUC__ >= 10) */ \ + || defined(__clang__) /* && (__clang_major__ >= 10) */ + +/* there was some CLANG/GCC compilers that have issues with + rbx(ebx) handling in asm blocks in -fPIC mode (__PIC__ is defined). + compiler's contains the macro __cpuid() that is similar to our code. + The history of __cpuid() changes in CLANG/GCC: + GCC: + 2007: it preserved ebx for (__PIC__ && __i386__) + 2013: it preserved rbx and ebx for __PIC__ + 2014: it doesn't preserves rbx and ebx anymore + we suppose that (__GNUC__ >= 5) fixed that __PIC__ ebx/rbx problem. + CLANG: + 2014+: it preserves rbx, but only for 64-bit code. No __PIC__ check. + Why CLANG cares about 64-bit mode only, and doesn't care about ebx (in 32-bit)? + Do we need __PIC__ test for CLANG or we must care about rbx even if + __PIC__ is not defined? +*/ + +#define ASM_LN "\n" + +#if defined(MY_CPU_AMD64) && defined(__PIC__) \ + && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) + +#define x86_cpuid_MACRO(p, func) { \ + __asm__ __volatile__ ( \ + ASM_LN "mov %%rbx, %q1" \ + ASM_LN "cpuid" \ + ASM_LN "xchg %%rbx, %q1" \ + : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } + + /* "=&r" selects free register. It can select even rbx, if that register is free. + "=&D" for (RDI) also works, but the code can be larger with "=&D" + "2"(0) means (subFunction = 0), + 2 is (zero-based) index in the output constraint list "=c" (ECX). */ + +#elif defined(MY_CPU_X86) && defined(__PIC__) \ + && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) + +#define x86_cpuid_MACRO(p, func) { \ + __asm__ __volatile__ ( \ + ASM_LN "mov %%ebx, %k1" \ + ASM_LN "cpuid" \ + ASM_LN "xchg %%ebx, %k1" \ + : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } + +#else + +#define x86_cpuid_MACRO(p, func) { \ + __asm__ __volatile__ ( \ + ASM_LN "cpuid" \ + : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } + #endif -#if defined(USE_ASM) && !defined(MY_CPU_AMD64) -static UInt32 CheckFlag(UInt32 flag) -{ - #ifdef _MSC_VER - __asm pushfd; - __asm pop EAX; - __asm mov EDX, EAX; - __asm xor EAX, flag; - __asm push EAX; - __asm popfd; - __asm pushfd; - __asm pop EAX; - __asm xor EAX, EDX; - __asm push EDX; - __asm popfd; - __asm and flag, EAX; - #else + +void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) +{ + x86_cpuid_MACRO(p, func) +} + + +Z7_NO_INLINE +UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) +{ + #if defined(NEED_CHECK_FOR_CPUID) + #define EFALGS_CPUID_BIT 21 + UInt32 a; __asm__ __volatile__ ( - "pushf\n\t" - "pop %%EAX\n\t" - "movl %%EAX,%%EDX\n\t" - "xorl %0,%%EAX\n\t" - "push %%EAX\n\t" - "popf\n\t" - "pushf\n\t" - "pop %%EAX\n\t" - "xorl %%EDX,%%EAX\n\t" - "push %%EDX\n\t" - "popf\n\t" - "andl %%EAX, %0\n\t": - "=c" (flag) : "c" (flag) : - "%eax", "%edx"); + ASM_LN "pushf" + ASM_LN "pushf" + ASM_LN "pop %0" + // ASM_LN "movl %0, %1" + // ASM_LN "xorl $0x200000, %0" + ASM_LN "btc %1, %0" + ASM_LN "push %0" + ASM_LN "popf" + ASM_LN "pushf" + ASM_LN "pop %0" + ASM_LN "xorl (%%esp), %0" + + ASM_LN "popf" + ASM_LN + : "=&r" (a) // "=a" + : "i" (EFALGS_CPUID_BIT) + ); + if ((a & (1 << EFALGS_CPUID_BIT)) == 0) + return 0; + #endif + { + UInt32 p[4]; + x86_cpuid_MACRO(p, 0) + return p[0]; + } +} + +#undef ASM_LN + +#elif !defined(_MSC_VER) + +/* +// for gcc/clang and other: we can try to use __cpuid macro: +#include +void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) +{ + __cpuid(func, p[0], p[1], p[2], p[3]); +} +UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) +{ + return (UInt32)__get_cpuid_max(0, NULL); +} +*/ +// for unsupported cpuid: +void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) +{ + UNUSED_VAR(func) + p[0] = p[1] = p[2] = p[3] = 0; +} +UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) +{ + return 0; +} + +#else // _MSC_VER + +#if !defined(MY_CPU_AMD64) + +UInt32 __declspec(naked) Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) +{ + #if defined(NEED_CHECK_FOR_CPUID) + #define EFALGS_CPUID_BIT 21 + __asm pushfd + __asm pushfd + /* + __asm pop eax + // __asm mov edx, eax + __asm btc eax, EFALGS_CPUID_BIT + __asm push eax + */ + __asm btc dword ptr [esp], EFALGS_CPUID_BIT + __asm popfd + __asm pushfd + __asm pop eax + // __asm xor eax, edx + __asm xor eax, [esp] + // __asm push edx + __asm popfd + __asm and eax, (1 shl EFALGS_CPUID_BIT) + __asm jz end_func + #endif + __asm push ebx + __asm xor eax, eax // func + __asm xor ecx, ecx // subFunction (optional) for (func == 0) + __asm cpuid + __asm pop ebx + #if defined(NEED_CHECK_FOR_CPUID) + end_func: #endif - return flag; + __asm ret 0 } -#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; -#else -#define CHECK_CPUID_IS_SUPPORTED -#endif -#ifndef USE_ASM - #ifdef _MSC_VER +void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) +{ + UNUSED_VAR(p) + UNUSED_VAR(func) + __asm push ebx + __asm push edi + __asm mov edi, ecx // p + __asm mov eax, edx // func + __asm xor ecx, ecx // subfunction (optional) for (func == 0) + __asm cpuid + __asm mov [edi ], eax + __asm mov [edi + 4], ebx + __asm mov [edi + 8], ecx + __asm mov [edi + 12], edx + __asm pop edi + __asm pop ebx + __asm ret 0 +} + +#else // MY_CPU_AMD64 + #if _MSC_VER >= 1600 - #define MY__cpuidex __cpuidex + #include + #define MY_cpuidex __cpuidex #else - /* - __cpuid (function == 4) requires subfunction number in ECX. + __cpuid (func == (0 or 7)) requires subfunction number in ECX. MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction. __cpuid() in new MSVC clears ECX. - __cpuid() in old MSVC (14.00) doesn't clear ECX - We still can use __cpuid for low (function) values that don't require ECX, - but __cpuid() in old MSVC will be incorrect for some function values: (function == 4). + __cpuid() in old MSVC (14.00) x64 doesn't clear ECX + We still can use __cpuid for low (func) values that don't require ECX, + but __cpuid() in old MSVC will be incorrect for some func values: (func == 7). So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction, - where ECX value is first parameter for FAST_CALL / NO_INLINE function, - So the caller of MY__cpuidex_HACK() sets ECX as subFunction, and + where ECX value is first parameter for FASTCALL / NO_INLINE func, + So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value. - DON'T remove MY_NO_INLINE and MY_FAST_CALL for MY__cpuidex_HACK() !!! +DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!! */ - static -MY_NO_INLINE -void MY_FAST_CALL MY__cpuidex_HACK(UInt32 subFunction, int *CPUInfo, UInt32 function) +Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(UInt32 subFunction, UInt32 func, int *CPUInfo) { - UNUSED_VAR(subFunction); - __cpuid(CPUInfo, function); + UNUSED_VAR(subFunction) + __cpuid(CPUInfo, func); } - - #define MY__cpuidex(info, func, func2) MY__cpuidex_HACK(func2, info, func) - #pragma message("======== MY__cpuidex_HACK WAS USED ========") - #endif - #else - #define MY__cpuidex(info, func, func2) __cpuid(info, func) - #pragma message("======== (INCORRECT ?) cpuid WAS USED ========") - #endif + #define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info) + #pragma message("======== MY_cpuidex_HACK WAS USED ========") + #endif // _MSC_VER >= 1600 + +#if !defined(MY_CPU_AMD64) +/* inlining for __cpuid() in MSVC x86 (32-bit) produces big ineffective code, + so we disable inlining here */ +Z7_NO_INLINE #endif - - - - -void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) +void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) { - #ifdef USE_ASM - - #ifdef _MSC_VER - - UInt32 a2, b2, c2, d2; - __asm xor EBX, EBX; - __asm xor ECX, ECX; - __asm xor EDX, EDX; - __asm mov EAX, function; - __asm cpuid; - __asm mov a2, EAX; - __asm mov b2, EBX; - __asm mov c2, ECX; - __asm mov d2, EDX; - - *a = a2; - *b = b2; - *c = c2; - *d = d2; - - #else - - __asm__ __volatile__ ( - #if defined(MY_CPU_AMD64) && defined(__PIC__) - "mov %%rbx, %%rdi;" - "cpuid;" - "xchg %%rbx, %%rdi;" - : "=a" (*a) , - "=D" (*b) , - #elif defined(MY_CPU_X86) && defined(__PIC__) - "mov %%ebx, %%edi;" - "cpuid;" - "xchgl %%ebx, %%edi;" - : "=a" (*a) , - "=D" (*b) , - #else - "cpuid" - : "=a" (*a) , - "=b" (*b) , - #endif - "=c" (*c) , - "=d" (*d) - : "0" (function), "c"(0) ) ; - - #endif - - #else + MY_cpuidex((int *)p, (int)func, 0); +} - int CPUInfo[4]; +Z7_NO_INLINE +UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) +{ + int a[4]; + MY_cpuidex(a, 0, 0); + return a[0]; +} - MY__cpuidex(CPUInfo, (int)function, 0); +#endif // MY_CPU_AMD64 +#endif // _MSC_VER - *a = (UInt32)CPUInfo[0]; - *b = (UInt32)CPUInfo[1]; - *c = (UInt32)CPUInfo[2]; - *d = (UInt32)CPUInfo[3]; +#if defined(NEED_CHECK_FOR_CPUID) +#define CHECK_CPUID_IS_SUPPORTED { if (z7_x86_cpuid_GetMaxFunc() == 0) return 0; } +#else +#define CHECK_CPUID_IS_SUPPORTED +#endif +#undef NEED_CHECK_FOR_CPUID - #endif -} -BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p) +static +BoolInt x86cpuid_Func_1(UInt32 *p) { CHECK_CPUID_IS_SUPPORTED - MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); - MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); + z7_x86_cpuid(p, 1); return True; } -static const UInt32 kVendors[][3] = +/* +static const UInt32 kVendors[][1] = { - { 0x756E6547, 0x49656E69, 0x6C65746E}, - { 0x68747541, 0x69746E65, 0x444D4163}, - { 0x746E6543, 0x48727561, 0x736C7561} + { 0x756E6547 }, // , 0x49656E69, 0x6C65746E }, + { 0x68747541 }, // , 0x69746E65, 0x444D4163 }, + { 0x746E6543 } // , 0x48727561, 0x736C7561 } }; +*/ + +/* +typedef struct +{ + UInt32 maxFunc; + UInt32 vendor[3]; + UInt32 ver; + UInt32 b; + UInt32 c; + UInt32 d; +} Cx86cpuid; + +enum +{ + CPU_FIRM_INTEL, + CPU_FIRM_AMD, + CPU_FIRM_VIA +}; +int x86cpuid_GetFirm(const Cx86cpuid *p); +#define x86cpuid_ver_GetFamily(ver) (((ver >> 16) & 0xff0) | ((ver >> 8) & 0xf)) +#define x86cpuid_ver_GetModel(ver) (((ver >> 12) & 0xf0) | ((ver >> 4) & 0xf)) +#define x86cpuid_ver_GetStepping(ver) (ver & 0xf) int x86cpuid_GetFirm(const Cx86cpuid *p) { unsigned i; - for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) + for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[0]); i++) { const UInt32 *v = kVendors[i]; - if (v[0] == p->vendor[0] && - v[1] == p->vendor[1] && - v[2] == p->vendor[2]) + if (v[0] == p->vendor[0] + // && v[1] == p->vendor[1] + // && v[2] == p->vendor[2] + ) return (int)i; } return -1; @@ -190,41 +321,55 @@ int x86cpuid_GetFirm(const Cx86cpuid *p) BoolInt CPU_Is_InOrder() { Cx86cpuid p; - int firm; UInt32 family, model; if (!x86cpuid_CheckAndRead(&p)) return True; - family = x86cpuid_GetFamily(p.ver); - model = x86cpuid_GetModel(p.ver); - - firm = x86cpuid_GetFirm(&p); + family = x86cpuid_ver_GetFamily(p.ver); + model = x86cpuid_ver_GetModel(p.ver); - switch (firm) + switch (x86cpuid_GetFirm(&p)) { case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( - /* In-Order Atom CPU */ - model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ - || model == 0x26 /* 45 nm, Z6xx */ - || model == 0x27 /* 32 nm, Z2460 */ - || model == 0x35 /* 32 nm, Z2760 */ - || model == 0x36 /* 32 nm, N2xxx, D2xxx */ + // In-Order Atom CPU + model == 0x1C // 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 + || model == 0x26 // 45 nm, Z6xx + || model == 0x27 // 32 nm, Z2460 + || model == 0x35 // 32 nm, Z2760 + || model == 0x36 // 32 nm, N2xxx, D2xxx ))); case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); } - return True; + return False; // v23 : unknown processors are not In-Order } +*/ + +#ifdef _WIN32 +#include "7zWindows.h" +#endif #if !defined(MY_CPU_AMD64) && defined(_WIN32) -#include -static BoolInt CPU_Sys_Is_SSE_Supported() + +/* for legacy SSE ia32: there is no user-space cpu instruction to check + that OS supports SSE register storing/restoring on context switches. + So we need some OS-specific function to check that it's safe to use SSE registers. +*/ + +Z7_FORCE_INLINE +static BoolInt CPU_Sys_Is_SSE_Supported(void) { - OSVERSIONINFO vi; - vi.dwOSVersionInfoSize = sizeof(vi); - if (!GetVersionEx(&vi)) - return False; - return (vi.dwMajorVersion >= 5); +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable : 4996) // `GetVersion': was declared deprecated +#endif + /* low byte is major version of Windows + We suppose that any Windows version since + Windows2000 (major == 5) supports SSE registers */ + return (Byte)GetVersion() >= 5; +#if defined(_MSC_VER) + #pragma warning(pop) +#endif } #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; #else @@ -232,94 +377,300 @@ static BoolInt CPU_Sys_Is_SSE_Supported() #endif -static UInt32 X86_CPUID_ECX_Get_Flags() +#if !defined(MY_CPU_AMD64) + +BoolInt CPU_IsSupported_CMOV(void) { - Cx86cpuid p; + UInt32 a[4]; + if (!x86cpuid_Func_1(&a[0])) + return 0; + return (a[3] >> 15) & 1; +} + +BoolInt CPU_IsSupported_SSE(void) +{ + UInt32 a[4]; CHECK_SYS_SSE_SUPPORT - if (!x86cpuid_CheckAndRead(&p)) + if (!x86cpuid_Func_1(&a[0])) + return 0; + return (a[3] >> 25) & 1; +} + +BoolInt CPU_IsSupported_SSE2(void) +{ + UInt32 a[4]; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_Func_1(&a[0])) + return 0; + return (a[3] >> 26) & 1; +} + +#endif + + +static UInt32 x86cpuid_Func_1_ECX(void) +{ + UInt32 a[4]; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_Func_1(&a[0])) return 0; - return p.c; + return a[2]; } -BoolInt CPU_IsSupported_AES() +BoolInt CPU_IsSupported_AES(void) { - return (X86_CPUID_ECX_Get_Flags() >> 25) & 1; + return (x86cpuid_Func_1_ECX() >> 25) & 1; } -BoolInt CPU_IsSupported_SSSE3() +BoolInt CPU_IsSupported_SSSE3(void) { - return (X86_CPUID_ECX_Get_Flags() >> 9) & 1; + return (x86cpuid_Func_1_ECX() >> 9) & 1; } -BoolInt CPU_IsSupported_SSE41() +BoolInt CPU_IsSupported_SSE41(void) { - return (X86_CPUID_ECX_Get_Flags() >> 19) & 1; + return (x86cpuid_Func_1_ECX() >> 19) & 1; } -BoolInt CPU_IsSupported_SHA() +BoolInt CPU_IsSupported_SHA(void) { - Cx86cpuid p; CHECK_SYS_SSE_SUPPORT - if (!x86cpuid_CheckAndRead(&p)) - return False; - if (p.maxFunc < 7) + if (z7_x86_cpuid_GetMaxFunc() < 7) return False; { - UInt32 d[4] = { 0 }; - MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + UInt32 d[4]; + z7_x86_cpuid(d, 7); return (d[1] >> 29) & 1; } } -// #include +/* +MSVC: _xgetbv() intrinsic is available since VS2010SP1. + MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in + that we can use or check. + For any 32-bit x86 we can use asm code in MSVC, + but MSVC asm code is huge after compilation. + So _xgetbv() is better + +ICC: _xgetbv() intrinsic is available (in what version of ICC?) + ICC defines (__GNUC___) and it supports gnu assembler + also ICC supports MASM style code with -use-msasm switch. + but ICC doesn't support __attribute__((__target__)) + +GCC/CLANG 9: + _xgetbv() is macro that works via __builtin_ia32_xgetbv() + and we need __attribute__((__target__("xsave")). + But with __target__("xsave") the function will be not + inlined to function that has no __target__("xsave") attribute. + If we want _xgetbv() call inlining, then we should use asm version + instead of calling _xgetbv(). + Note:intrinsic is broke before GCC 8.2: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684 +*/ -#ifdef _WIN32 -#include +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) \ + || defined(_MSC_VER) && (_MSC_VER >= 1600) && (_MSC_FULL_VER >= 160040219) \ + || defined(__GNUC__) && (__GNUC__ >= 9) \ + || defined(__clang__) && (__clang_major__ >= 9) +// we define ATTRIB_XGETBV, if we want to use predefined _xgetbv() from compiler +#if defined(__INTEL_COMPILER) +#define ATTRIB_XGETBV +#elif defined(__GNUC__) || defined(__clang__) +// we don't define ATTRIB_XGETBV here, because asm version is better for inlining. +// #define ATTRIB_XGETBV __attribute__((__target__("xsave"))) +#else +#define ATTRIB_XGETBV +#endif +#endif + +#if defined(ATTRIB_XGETBV) +#include #endif -BoolInt CPU_IsSupported_AVX2() + +// XFEATURE_ENABLED_MASK/XCR0 +#define MY_XCR_XFEATURE_ENABLED_MASK 0 + +#if defined(ATTRIB_XGETBV) +ATTRIB_XGETBV +#endif +static UInt64 x86_xgetbv_0(UInt32 num) { - Cx86cpuid p; - CHECK_SYS_SSE_SUPPORT +#if defined(ATTRIB_XGETBV) + { + return + #if (defined(_MSC_VER)) + _xgetbv(num); + #else + __builtin_ia32_xgetbv( + #if !defined(__clang__) + (int) + #endif + num); + #endif + } + +#elif defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC) + + UInt32 a, d; + #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __asm__ + ( + "xgetbv" + : "=a"(a), "=d"(d) : "c"(num) : "cc" + ); + #else // is old gcc + __asm__ + ( + ".byte 0x0f, 0x01, 0xd0" "\n\t" + : "=a"(a), "=d"(d) : "c"(num) : "cc" + ); + #endif + return ((UInt64)d << 32) | a; + // return a; + +#elif defined(_MSC_VER) && !defined(MY_CPU_AMD64) + + UInt32 a, d; + __asm { + push eax + push edx + push ecx + mov ecx, num; + // xor ecx, ecx // = MY_XCR_XFEATURE_ENABLED_MASK + _emit 0x0f + _emit 0x01 + _emit 0xd0 + mov a, eax + mov d, edx + pop ecx + pop edx + pop eax + } + return ((UInt64)d << 32) | a; + // return a; + +#else // it's unknown compiler + // #error "Need xgetbv function" + UNUSED_VAR(num) + // for MSVC-X64 we could call external function from external file. + /* Actually we had checked OSXSAVE/AVX in cpuid before. + So it's expected that OS supports at least AVX and below. */ + // if (num != MY_XCR_XFEATURE_ENABLED_MASK) return 0; // if not XCR0 + return + // (1 << 0) | // x87 + (1 << 1) // SSE + | (1 << 2); // AVX + +#endif +} +#ifdef _WIN32 +/* + Windows versions do not know about new ISA extensions that + can be introduced. But we still can use new extensions, + even if Windows doesn't report about supporting them, + But we can use new extensions, only if Windows knows about new ISA extension + that changes the number or size of registers: SSE, AVX/XSAVE, AVX512 + So it's enough to check + MY_PF_AVX_INSTRUCTIONS_AVAILABLE + instead of + MY_PF_AVX2_INSTRUCTIONS_AVAILABLE +*/ +#define MY_PF_XSAVE_ENABLED 17 +// #define MY_PF_SSSE3_INSTRUCTIONS_AVAILABLE 36 +// #define MY_PF_SSE4_1_INSTRUCTIONS_AVAILABLE 37 +// #define MY_PF_SSE4_2_INSTRUCTIONS_AVAILABLE 38 +// #define MY_PF_AVX_INSTRUCTIONS_AVAILABLE 39 +// #define MY_PF_AVX2_INSTRUCTIONS_AVAILABLE 40 +// #define MY_PF_AVX512F_INSTRUCTIONS_AVAILABLE 41 +#endif + +BoolInt CPU_IsSupported_AVX(void) +{ #ifdef _WIN32 - #define MY__PF_XSAVE_ENABLED 17 - if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED)) + if (!IsProcessorFeaturePresent(MY_PF_XSAVE_ENABLED)) return False; + /* PF_AVX_INSTRUCTIONS_AVAILABLE probably is supported starting from + some latest Win10 revisions. But we need AVX in older Windows also. + So we don't use the following check: */ + /* + if (!IsProcessorFeaturePresent(MY_PF_AVX_INSTRUCTIONS_AVAILABLE)) + return False; + */ #endif - if (!x86cpuid_CheckAndRead(&p)) + /* + OS must use new special XSAVE/XRSTOR instructions to save + AVX registers when it required for context switching. + At OS statring: + OS sets CR4.OSXSAVE flag to signal the processor that OS supports the XSAVE extensions. + Also OS sets bitmask in XCR0 register that defines what + registers will be processed by XSAVE instruction: + XCR0.SSE[bit 0] - x87 registers and state + XCR0.SSE[bit 1] - SSE registers and state + XCR0.AVX[bit 2] - AVX registers and state + CR4.OSXSAVE is reflected to CPUID.1:ECX.OSXSAVE[bit 27]. + So we can read that bit in user-space. + XCR0 is available for reading in user-space by new XGETBV instruction. + */ + { + const UInt32 c = x86cpuid_Func_1_ECX(); + if (0 == (1 + & (c >> 28) // AVX instructions are supported by hardware + & (c >> 27))) // OSXSAVE bit: XSAVE and related instructions are enabled by OS. + return False; + } + + /* also we can check + CPUID.1:ECX.XSAVE [bit 26] : that shows that + XSAVE, XRESTOR, XSETBV, XGETBV instructions are supported by hardware. + But that check is redundant, because if OSXSAVE bit is set, then XSAVE is also set */ + + /* If OS have enabled XSAVE extension instructions (OSXSAVE == 1), + in most cases we expect that OS also will support storing/restoring + for AVX and SSE states at least. + But to be ensure for that we call user-space instruction + XGETBV(0) to get XCR0 value that contains bitmask that defines + what exact states(registers) OS have enabled for storing/restoring. + */ + + { + const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK); + // printf("\n=== XGetBV=%d\n", bm); + return 1 + & (bm >> 1) // SSE state is supported (set by OS) for storing/restoring + & (bm >> 2); // AVX state is supported (set by OS) for storing/restoring + } + // since Win7SP1: we can use GetEnabledXStateFeatures(); +} + + +BoolInt CPU_IsSupported_AVX2(void) +{ + if (!CPU_IsSupported_AVX()) return False; - if (p.maxFunc < 7) + if (z7_x86_cpuid_GetMaxFunc() < 7) return False; { - UInt32 d[4] = { 0 }; - MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + UInt32 d[4]; + z7_x86_cpuid(d, 7); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); return 1 & (d[1] >> 5); // avx2 } } -BoolInt CPU_IsSupported_VAES_AVX2() +BoolInt CPU_IsSupported_VAES_AVX2(void) { - Cx86cpuid p; - CHECK_SYS_SSE_SUPPORT - - #ifdef _WIN32 - #define MY__PF_XSAVE_ENABLED 17 - if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED)) + if (!CPU_IsSupported_AVX()) return False; - #endif - - if (!x86cpuid_CheckAndRead(&p)) - return False; - if (p.maxFunc < 7) + if (z7_x86_cpuid_GetMaxFunc() < 7) return False; { - UInt32 d[4] = { 0 }; - MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + UInt32 d[4]; + z7_x86_cpuid(d, 7); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); return 1 & (d[1] >> 5) // avx2 @@ -328,20 +679,15 @@ BoolInt CPU_IsSupported_VAES_AVX2() } } -BoolInt CPU_IsSupported_PageGB() +BoolInt CPU_IsSupported_PageGB(void) { - Cx86cpuid cpuid; - if (!x86cpuid_CheckAndRead(&cpuid)) - return False; + CHECK_CPUID_IS_SUPPORTED { - UInt32 d[4] = { 0 }; - MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]); + UInt32 d[4]; + z7_x86_cpuid(d, 0x80000000); if (d[0] < 0x80000001) return False; - } - { - UInt32 d[4] = { 0 }; - MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]); + z7_x86_cpuid(d, 0x80000001); return (d[3] >> 26) & 1; } } @@ -351,11 +697,11 @@ BoolInt CPU_IsSupported_PageGB() #ifdef _WIN32 -#include +#include "7zWindows.h" -BoolInt CPU_IsSupported_CRC32() { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } -BoolInt CPU_IsSupported_CRYPTO() { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } -BoolInt CPU_IsSupported_NEON() { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } +BoolInt CPU_IsSupported_CRC32(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } +BoolInt CPU_IsSupported_CRYPTO(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } +BoolInt CPU_IsSupported_NEON(void) { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } #else @@ -378,28 +724,27 @@ static void Print_sysctlbyname(const char *name) } } */ +/* + Print_sysctlbyname("hw.pagesize"); + Print_sysctlbyname("machdep.cpu.brand_string"); +*/ -static BoolInt My_sysctlbyname_Get_BoolInt(const char *name) +static BoolInt z7_sysctlbyname_Get_BoolInt(const char *name) { UInt32 val = 0; - if (My_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1) + if (z7_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1) return 1; return 0; } - /* - Print_sysctlbyname("hw.pagesize"); - Print_sysctlbyname("machdep.cpu.brand_string"); - */ - BoolInt CPU_IsSupported_CRC32(void) { - return My_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32"); + return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32"); } BoolInt CPU_IsSupported_NEON(void) { - return My_sysctlbyname_Get_BoolInt("hw.optional.neon"); + return z7_sysctlbyname_Get_BoolInt("hw.optional.neon"); } #ifdef MY_CPU_ARM64 @@ -461,15 +806,15 @@ MY_HWCAP_CHECK_FUNC (AES) #include -int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize) +int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize) { return sysctlbyname(name, buf, bufSize, NULL, 0); } -int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val) +int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val) { size_t bufSize = sizeof(*val); - int res = My_sysctlbyname_Get(name, val, &bufSize); + const int res = z7_sysctlbyname_Get(name, val, &bufSize); if (res == 0 && bufSize != sizeof(*val)) return EFAULT; return res; diff --git a/libraries/lzma/C/CpuArch.h b/libraries/lzma/C/CpuArch.h index 529d3a502b..8e5d8a543f 100644 --- a/libraries/lzma/C/CpuArch.h +++ b/libraries/lzma/C/CpuArch.h @@ -1,8 +1,8 @@ /* CpuArch.h -- CPU specific code -2021-07-13 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __CPU_ARCH_H -#define __CPU_ARCH_H +#ifndef ZIP7_INC_CPU_ARCH_H +#define ZIP7_INC_CPU_ARCH_H #include "7zTypes.h" @@ -51,7 +51,13 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. || defined(__AARCH64EB__) \ || defined(__aarch64__) #define MY_CPU_ARM64 - #define MY_CPU_NAME "arm64" + #ifdef __ILP32__ + #define MY_CPU_NAME "arm64-32" + #define MY_CPU_SIZEOF_POINTER 4 + #else + #define MY_CPU_NAME "arm64" + #define MY_CPU_SIZEOF_POINTER 8 + #endif #define MY_CPU_64BIT #endif @@ -68,8 +74,10 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #define MY_CPU_ARM #if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT) + #define MY_CPU_ARMT #define MY_CPU_NAME "armt" #else + #define MY_CPU_ARM32 #define MY_CPU_NAME "arm" #endif /* #define MY_CPU_32BIT */ @@ -103,6 +111,8 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. || defined(__PPC__) \ || defined(_POWER) +#define MY_CPU_PPC_OR_PPC64 + #if defined(__ppc64__) \ || defined(__powerpc64__) \ || defined(_LP64) \ @@ -123,12 +133,15 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #endif -#if defined(__sparc64__) - #define MY_CPU_NAME "sparc64" - #define MY_CPU_64BIT -#elif defined(__sparc__) - #define MY_CPU_NAME "sparc" - /* #define MY_CPU_32BIT */ +#if defined(__riscv) \ + || defined(__riscv__) + #if __riscv_xlen == 32 + #define MY_CPU_NAME "riscv32" + #elif __riscv_xlen == 64 + #define MY_CPU_NAME "riscv64" + #else + #define MY_CPU_NAME "riscv" + #endif #endif @@ -194,6 +207,9 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #error Stop_Compiling_Bad_Endian #endif +#if !defined(MY_CPU_LE) && !defined(MY_CPU_BE) + #error Stop_Compiling_CPU_ENDIAN_must_be_detected_at_compile_time +#endif #if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT) #error Stop_Compiling_Bad_32_64_BIT @@ -250,6 +266,67 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. +#ifdef __has_builtin + #define Z7_has_builtin(x) __has_builtin(x) +#else + #define Z7_has_builtin(x) 0 +#endif + + +#define Z7_BSWAP32_CONST(v) \ + ( (((UInt32)(v) << 24) ) \ + | (((UInt32)(v) << 8) & (UInt32)0xff0000) \ + | (((UInt32)(v) >> 8) & (UInt32)0xff00 ) \ + | (((UInt32)(v) >> 24) )) + + +#if defined(_MSC_VER) && (_MSC_VER >= 1300) + +#include + +/* Note: these macros will use bswap instruction (486), that is unsupported in 386 cpu */ + +#pragma intrinsic(_byteswap_ushort) +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) + +#define Z7_BSWAP16(v) _byteswap_ushort(v) +#define Z7_BSWAP32(v) _byteswap_ulong (v) +#define Z7_BSWAP64(v) _byteswap_uint64(v) +#define Z7_CPU_FAST_BSWAP_SUPPORTED + +#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ + || (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) + +#define Z7_BSWAP16(v) __builtin_bswap16(v) +#define Z7_BSWAP32(v) __builtin_bswap32(v) +#define Z7_BSWAP64(v) __builtin_bswap64(v) +#define Z7_CPU_FAST_BSWAP_SUPPORTED + +#else + +#define Z7_BSWAP16(v) ((UInt16) \ + ( ((UInt32)(v) << 8) \ + | ((UInt32)(v) >> 8) \ + )) + +#define Z7_BSWAP32(v) Z7_BSWAP32_CONST(v) + +#define Z7_BSWAP64(v) \ + ( ( ( (UInt64)(v) ) << 8 * 7 ) \ + | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 1) ) << 8 * 5 ) \ + | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 2) ) << 8 * 3 ) \ + | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 3) ) << 8 * 1 ) \ + | ( ( (UInt64)(v) >> 8 * 1 ) & ((UInt32)0xff << 8 * 3) ) \ + | ( ( (UInt64)(v) >> 8 * 3 ) & ((UInt32)0xff << 8 * 2) ) \ + | ( ( (UInt64)(v) >> 8 * 5 ) & ((UInt32)0xff << 8 * 1) ) \ + | ( ( (UInt64)(v) >> 8 * 7 ) ) \ + ) + +#endif + + + #ifdef MY_CPU_LE #if defined(MY_CPU_X86_OR_AMD64) \ || defined(MY_CPU_ARM64) @@ -269,13 +346,11 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #define GetUi32(p) (*(const UInt32 *)(const void *)(p)) #ifdef MY_CPU_LE_UNALIGN_64 #define GetUi64(p) (*(const UInt64 *)(const void *)(p)) +#define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); } #endif #define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); } #define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); } -#ifdef MY_CPU_LE_UNALIGN_64 -#define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); } -#endif #else @@ -302,51 +377,26 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #endif -#ifndef MY_CPU_LE_UNALIGN_64 - +#ifndef GetUi64 #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) +#endif +#ifndef SetUi64 #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ - SetUi32(_ppp2_ , (UInt32)_vvv2_); \ - SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } - + SetUi32(_ppp2_ , (UInt32)_vvv2_) \ + SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)) } #endif +#if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) +#define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p)) +#define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); } -#ifdef __has_builtin - #define MY__has_builtin(x) __has_builtin(x) -#else - #define MY__has_builtin(x) 0 +#if defined(MY_CPU_LE_UNALIGN_64) +#define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p)) #endif -#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ defined(_MSC_VER) && (_MSC_VER >= 1300) - -/* Note: we use bswap instruction, that is unsupported in 386 cpu */ - -#include - -#pragma intrinsic(_byteswap_ushort) -#pragma intrinsic(_byteswap_ulong) -#pragma intrinsic(_byteswap_uint64) - -/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */ -#define GetBe32(p) _byteswap_ulong (*(const UInt32 *)(const void *)(p)) -#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const void *)(p)) - -#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) - -#elif defined(MY_CPU_LE_UNALIGN) && ( \ - (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ - || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) ) - -/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const void *)(p)) */ -#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const void *)(p)) -#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const void *)(p)) - -#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v) - #else #define GetBe32(p) ( \ @@ -355,8 +405,6 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. ((UInt32)((const Byte *)(p))[2] << 8) | \ ((const Byte *)(p))[3] ) -#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) - #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ _ppp_[0] = (Byte)(_vvv_ >> 24); \ _ppp_[1] = (Byte)(_vvv_ >> 16); \ @@ -365,50 +413,83 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #endif +#ifndef GetBe64 +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) +#endif #ifndef GetBe16 - #define GetBe16(p) ( (UInt16) ( \ ((UInt16)((const Byte *)(p))[0] << 8) | \ ((const Byte *)(p))[1] )) +#endif + +#if defined(MY_CPU_BE) +#define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v) +#define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) +#define Z7_CONV_NATIVE_TO_BE_32(v) (v) +#elif defined(MY_CPU_LE) +#define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) +#define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v) +#define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v) +#else +#error Stop_Compiling_Unknown_Endian_CONV #endif +#if defined(MY_CPU_BE) -#ifdef MY_CPU_X86_OR_AMD64 +#define GetBe32a(p) (*(const UInt32 *)(const void *)(p)) +#define GetBe16a(p) (*(const UInt16 *)(const void *)(p)) +#define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } +#define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); } -typedef struct -{ - UInt32 maxFunc; - UInt32 vendor[3]; - UInt32 ver; - UInt32 b; - UInt32 c; - UInt32 d; -} Cx86cpuid; +#define GetUi32a(p) GetUi32(p) +#define GetUi16a(p) GetUi16(p) +#define SetUi32a(p, v) SetUi32(p, v) +#define SetUi16a(p, v) SetUi16(p, v) -enum -{ - CPU_FIRM_INTEL, - CPU_FIRM_AMD, - CPU_FIRM_VIA -}; +#elif defined(MY_CPU_LE) -void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d); +#define GetUi32a(p) (*(const UInt32 *)(const void *)(p)) +#define GetUi16a(p) (*(const UInt16 *)(const void *)(p)) +#define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); } +#define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); } -BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p); -int x86cpuid_GetFirm(const Cx86cpuid *p); +#define GetBe32a(p) GetBe32(p) +#define GetBe16a(p) GetBe16(p) +#define SetBe32a(p, v) SetBe32(p, v) +#define SetBe16a(p, v) SetBe16(p, v) -#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF)) -#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) -#define x86cpuid_GetStepping(ver) (ver & 0xF) +#else +#error Stop_Compiling_Unknown_Endian_CPU_a +#endif -BoolInt CPU_Is_InOrder(void); + +#if defined(MY_CPU_X86_OR_AMD64) \ + || defined(MY_CPU_ARM_OR_ARM64) \ + || defined(MY_CPU_PPC_OR_PPC64) + #define Z7_CPU_FAST_ROTATE_SUPPORTED +#endif + + +#ifdef MY_CPU_X86_OR_AMD64 + +void Z7_FASTCALL z7_x86_cpuid(UInt32 a[4], UInt32 function); +UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void); +#if defined(MY_CPU_AMD64) +#define Z7_IF_X86_CPUID_SUPPORTED +#else +#define Z7_IF_X86_CPUID_SUPPORTED if (z7_x86_cpuid_GetMaxFunc()) +#endif BoolInt CPU_IsSupported_AES(void); +BoolInt CPU_IsSupported_AVX(void); BoolInt CPU_IsSupported_AVX2(void); BoolInt CPU_IsSupported_VAES_AVX2(void); +BoolInt CPU_IsSupported_CMOV(void); +BoolInt CPU_IsSupported_SSE(void); +BoolInt CPU_IsSupported_SSE2(void); BoolInt CPU_IsSupported_SSSE3(void); BoolInt CPU_IsSupported_SSE41(void); BoolInt CPU_IsSupported_SHA(void); @@ -433,8 +514,8 @@ BoolInt CPU_IsSupported_AES(void); #endif #if defined(__APPLE__) -int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize); -int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val); +int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize); +int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val); #endif EXTERN_C_END diff --git a/libraries/lzma/C/Delta.h b/libraries/lzma/C/Delta.h index 2fa54ad67b..706095417a 100644 --- a/libraries/lzma/C/Delta.h +++ b/libraries/lzma/C/Delta.h @@ -1,8 +1,8 @@ /* Delta.h -- Delta converter -2013-01-18 : Igor Pavlov : Public domain */ +2023-03-03 : Igor Pavlov : Public domain */ -#ifndef __DELTA_H -#define __DELTA_H +#ifndef ZIP7_INC_DELTA_H +#define ZIP7_INC_DELTA_H #include "7zTypes.h" diff --git a/libraries/lzma/C/DllSecur.c b/libraries/lzma/C/DllSecur.c new file mode 100644 index 0000000000..02a0f977ea --- /dev/null +++ b/libraries/lzma/C/DllSecur.c @@ -0,0 +1,111 @@ +/* DllSecur.c -- DLL loading security +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifdef _WIN32 + +#include "7zWindows.h" + +#include "DllSecur.h" + +#ifndef UNDER_CE + +#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__) + // #pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + +#if defined(__clang__) || defined(__GNUC__) +typedef void (*Z7_voidFunction)(void); +#define MY_CAST_FUNC (Z7_voidFunction) +#elif defined(_MSC_VER) && _MSC_VER > 1920 +#define MY_CAST_FUNC (void *) +// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()' +#else +#define MY_CAST_FUNC +#endif + +typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags); + +#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400 +#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32 0x800 + +#define DELIM "\0" + +static const char * const g_Dlls = + "userenv" + DELIM "setupapi" + DELIM "apphelp" + DELIM "propsys" + DELIM "dwmapi" + DELIM "cryptbase" + DELIM "oleacc" + DELIM "clbcatq" + DELIM "version" + #ifndef _CONSOLE + DELIM "uxtheme" + #endif + DELIM; + +#endif + +#ifdef __clang__ + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif +#if defined (_MSC_VER) && _MSC_VER >= 1900 +// sysinfoapi.h: kit10: GetVersion was declared deprecated +#pragma warning(disable : 4996) +#endif + +#define IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN \ + if ((UInt16)GetVersion() != 6) { \ + const \ + Func_SetDefaultDllDirectories setDllDirs = \ + (Func_SetDefaultDllDirectories) MY_CAST_FUNC GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), \ + "SetDefaultDllDirectories"); \ + if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; } + +void My_SetDefaultDllDirectories(void) +{ + #ifndef UNDER_CE + IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN + #endif +} + + +void LoadSecurityDlls(void) +{ + #ifndef UNDER_CE + // at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ??? + IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN + { + wchar_t buf[MAX_PATH + 100]; + const char *dll; + unsigned pos = GetSystemDirectoryW(buf, MAX_PATH + 2); + if (pos == 0 || pos > MAX_PATH) + return; + if (buf[pos - 1] != '\\') + buf[pos++] = '\\'; + for (dll = g_Dlls; *dll != 0;) + { + wchar_t *dest = &buf[pos]; + for (;;) + { + const char c = *dll++; + if (c == 0) + break; + *dest++ = (Byte)c; + } + dest[0] = '.'; + dest[1] = 'd'; + dest[2] = 'l'; + dest[3] = 'l'; + dest[4] = 0; + // lstrcatW(buf, L".dll"); + LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + } + } + #endif +} + +#endif // _WIN32 diff --git a/libraries/lzma/C/DllSecur.h b/libraries/lzma/C/DllSecur.h new file mode 100644 index 0000000000..9fa4153826 --- /dev/null +++ b/libraries/lzma/C/DllSecur.h @@ -0,0 +1,20 @@ +/* DllSecur.h -- DLL loading for security +2023-03-03 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_DLL_SECUR_H +#define ZIP7_INC_DLL_SECUR_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#ifdef _WIN32 + +void My_SetDefaultDllDirectories(void); +void LoadSecurityDlls(void); + +#endif + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/LzFind.c b/libraries/lzma/C/LzFind.c index 1b73c28484..0fbd5aae56 100644 --- a/libraries/lzma/C/LzFind.c +++ b/libraries/lzma/C/LzFind.c @@ -1,5 +1,5 @@ /* LzFind.c -- Match finder for LZ algorithms -2021-11-29 : Igor Pavlov : Public domain */ +2023-03-14 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -17,7 +17,7 @@ #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0) -// #define kMaxValForNormalize ((UInt32)(1 << 20) + 0xFFF) // for debug +// #define kMaxValForNormalize ((UInt32)(1 << 20) + 0xfff) // for debug // #define kNormalizeAlign (1 << 7) // alignment for speculated accesses @@ -67,10 +67,10 @@ static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) { - if (!p->directInput) + // if (!p->directInput) { - ISzAlloc_Free(alloc, p->bufferBase); - p->bufferBase = NULL; + ISzAlloc_Free(alloc, p->bufBase); + p->bufBase = NULL; } } @@ -79,7 +79,7 @@ static int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr all { if (blockSize == 0) return 0; - if (!p->bufferBase || p->blockSize != blockSize) + if (!p->bufBase || p->blockSize != blockSize) { // size_t blockSizeT; LzInWindow_Free(p, alloc); @@ -101,11 +101,11 @@ static int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr all #endif */ - p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, blockSize); - // printf("\nbufferBase = %p\n", p->bufferBase); + p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, blockSize); + // printf("\nbufferBase = %p\n", p->bufBase); // return 0; // for debug } - return (p->bufferBase != NULL); + return (p->bufBase != NULL); } static const Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } @@ -113,7 +113,7 @@ static const Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return GET_AVAIL_BYTES(p); } -MY_NO_INLINE +Z7_NO_INLINE static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) @@ -127,8 +127,8 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) UInt32 curSize = 0xFFFFFFFF - GET_AVAIL_BYTES(p); if (curSize > p->directInputRem) curSize = (UInt32)p->directInputRem; - p->directInputRem -= curSize; p->streamPos += curSize; + p->directInputRem -= curSize; if (p->directInputRem == 0) p->streamEndWasReached = 1; return; @@ -136,8 +136,8 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) for (;;) { - Byte *dest = p->buffer + GET_AVAIL_BYTES(p); - size_t size = (size_t)(p->bufferBase + p->blockSize - dest); + const Byte *dest = p->buffer + GET_AVAIL_BYTES(p); + size_t size = (size_t)(p->bufBase + p->blockSize - dest); if (size == 0) { /* we call ReadBlock() after NeedMove() and MoveBlock(). @@ -153,7 +153,14 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) // #define kRead 3 // if (size > kRead) size = kRead; // for debug - p->result = ISeqInStream_Read(p->stream, dest, &size); + /* + // we need cast (Byte *)dest. + #ifdef __clang__ + #pragma GCC diagnostic ignored "-Wcast-qual" + #endif + */ + p->result = ISeqInStream_Read(p->stream, + p->bufBase + (dest - p->bufBase), &size); if (p->result != SZ_OK) return; if (size == 0) @@ -173,14 +180,14 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) -MY_NO_INLINE +Z7_NO_INLINE void MatchFinder_MoveBlock(CMatchFinder *p) { - const size_t offset = (size_t)(p->buffer - p->bufferBase) - p->keepSizeBefore; + const size_t offset = (size_t)(p->buffer - p->bufBase) - p->keepSizeBefore; const size_t keepBefore = (offset & (kBlockMoveAlign - 1)) + p->keepSizeBefore; - p->buffer = p->bufferBase + keepBefore; - memmove(p->bufferBase, - p->bufferBase + (offset & ~((size_t)kBlockMoveAlign - 1)), + p->buffer = p->bufBase + keepBefore; + memmove(p->bufBase, + p->bufBase + (offset & ~((size_t)kBlockMoveAlign - 1)), keepBefore + (size_t)GET_AVAIL_BYTES(p)); } @@ -198,7 +205,7 @@ int MatchFinder_NeedMove(CMatchFinder *p) return 0; if (p->streamEndWasReached || p->result != SZ_OK) return 0; - return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); + return ((size_t)(p->bufBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) @@ -214,6 +221,8 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p) p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; + p->numHashBytes_Min = 2; + p->numHashOutBits = 0; p->bigHash = 0; } @@ -222,8 +231,10 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p) void MatchFinder_Construct(CMatchFinder *p) { unsigned i; - p->bufferBase = NULL; + p->buffer = NULL; + p->bufBase = NULL; p->directInput = 0; + p->stream = NULL; p->hash = NULL; p->expectedDataSize = (UInt64)(Int64)-1; MatchFinder_SetDefaultSettings(p); @@ -238,6 +249,8 @@ void MatchFinder_Construct(CMatchFinder *p) } } +#undef kCrcPoly + static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->hash); @@ -252,7 +265,7 @@ void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc) static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc) { - size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + const size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return NULL; return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes); @@ -298,6 +311,62 @@ static UInt32 GetBlockSize(CMatchFinder *p, UInt32 historySize) } +// input is historySize +static UInt32 MatchFinder_GetHashMask2(CMatchFinder *p, UInt32 hs) +{ + if (p->numHashBytes == 2) + return (1 << 16) - 1; + if (hs != 0) + hs--; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + // we propagated 16 bits in (hs). Low 16 bits must be set later + if (hs >= (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ + } + // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2) + hs |= (1 << 16) - 1; /* don't change it! */ + // bt5: we adjust the size with recommended minimum size + if (p->numHashBytes >= 5) + hs |= (256 << kLzHash_CrcShift_2) - 1; + return hs; +} + +// input is historySize +static UInt32 MatchFinder_GetHashMask(CMatchFinder *p, UInt32 hs) +{ + if (p->numHashBytes == 2) + return (1 << 16) - 1; + if (hs != 0) + hs--; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + // we propagated 16 bits in (hs). Low 16 bits must be set later + hs >>= 1; + if (hs >= (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ + } + // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2) + hs |= (1 << 16) - 1; /* don't change it! */ + // bt5: we adjust the size with recommended minimum size + if (p->numHashBytes >= 5) + hs |= (256 << kLzHash_CrcShift_2) - 1; + return hs; +} + + int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) @@ -318,78 +387,91 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, p->blockSize = 0; if (p->directInput || LzInWindow_Create2(p, GetBlockSize(p, historySize), alloc)) { - const UInt32 newCyclicBufferSize = historySize + 1; // do not change it - UInt32 hs; - p->matchMaxLen = matchMaxLen; + size_t hashSizeSum; { - // UInt32 hs4; - p->fixedHashSize = 0; - hs = (1 << 16) - 1; - if (p->numHashBytes != 2) + UInt32 hs; + UInt32 hsCur; + + if (p->numHashOutBits != 0) { - hs = historySize; - if (hs > p->expectedDataSize) - hs = (UInt32)p->expectedDataSize; - if (hs != 0) - hs--; - hs |= (hs >> 1); - hs |= (hs >> 2); - hs |= (hs >> 4); - hs |= (hs >> 8); - // we propagated 16 bits in (hs). Low 16 bits must be set later - hs >>= 1; - if (hs >= (1 << 24)) - { - if (p->numHashBytes == 3) - hs = (1 << 24) - 1; - else - hs >>= 1; - /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ - } - - // hs = ((UInt32)1 << 25) - 1; // for test - + unsigned numBits = p->numHashOutBits; + const unsigned nbMax = + (p->numHashBytes == 2 ? 16 : + (p->numHashBytes == 3 ? 24 : 32)); + if (numBits > nbMax) + numBits = nbMax; + if (numBits >= 32) + hs = (UInt32)0 - 1; + else + hs = ((UInt32)1 << numBits) - 1; // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2) hs |= (1 << 16) - 1; /* don't change it! */ - - // bt5: we adjust the size with recommended minimum size if (p->numHashBytes >= 5) hs |= (256 << kLzHash_CrcShift_2) - 1; + { + const UInt32 hs2 = MatchFinder_GetHashMask2(p, historySize); + if (hs > hs2) + hs = hs2; + } + hsCur = hs; + if (p->expectedDataSize < historySize) + { + const UInt32 hs2 = MatchFinder_GetHashMask2(p, (UInt32)p->expectedDataSize); + if (hsCur > hs2) + hsCur = hs2; + } } - p->hashMask = hs; - hs++; - - /* - hs4 = (1 << 20); - if (hs4 > hs) - hs4 = hs; - // hs4 = (1 << 16); // for test - p->hash4Mask = hs4 - 1; - */ + else + { + hs = MatchFinder_GetHashMask(p, historySize); + hsCur = hs; + if (p->expectedDataSize < historySize) + { + hsCur = MatchFinder_GetHashMask(p, (UInt32)p->expectedDataSize); + if (hsCur > hs) // is it possible? + hsCur = hs; + } + } + + p->hashMask = hsCur; - if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; - if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; - // if (p->numHashBytes > 4) p->fixedHashSize += hs4; // kHash4Size; - hs += p->fixedHashSize; + hashSizeSum = hs; + hashSizeSum++; + if (hashSizeSum < hs) + return 0; + { + UInt32 fixedHashSize = 0; + if (p->numHashBytes > 2 && p->numHashBytes_Min <= 2) fixedHashSize += kHash2Size; + if (p->numHashBytes > 3 && p->numHashBytes_Min <= 3) fixedHashSize += kHash3Size; + // if (p->numHashBytes > 4) p->fixedHashSize += hs4; // kHash4Size; + hashSizeSum += fixedHashSize; + p->fixedHashSize = fixedHashSize; + } } + p->matchMaxLen = matchMaxLen; + { size_t newSize; size_t numSons; + const UInt32 newCyclicBufferSize = historySize + 1; // do not change it p->historySize = historySize; - p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; // it must be = (historySize + 1) numSons = newCyclicBufferSize; if (p->btMode) numSons <<= 1; - newSize = hs + numSons; + newSize = hashSizeSum + numSons; + + if (numSons < newCyclicBufferSize || newSize < numSons) + return 0; // aligned size is not required here, but it can be better for some loops #define NUM_REFS_ALIGN_MASK 0xF newSize = (newSize + NUM_REFS_ALIGN_MASK) & ~(size_t)NUM_REFS_ALIGN_MASK; - if (p->hash && p->numRefs == newSize) + // 22.02: we don't reallocate buffer, if old size is enough + if (p->hash && p->numRefs >= newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); @@ -398,7 +480,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, if (p->hash) { - p->son = p->hash + p->hashSizeSum; + p->son = p->hash + hashSizeSum; return 1; } } @@ -470,7 +552,8 @@ void MatchFinder_Init_HighHash(CMatchFinder *p) void MatchFinder_Init_4(CMatchFinder *p) { - p->buffer = p->bufferBase; + if (!p->directInput) + p->buffer = p->bufBase; { /* kEmptyHashValue = 0 (Zero) is used in hash tables as NO-VALUE marker. the code in CMatchFinderMt expects (pos = 1) */ @@ -507,20 +590,20 @@ void MatchFinder_Init(CMatchFinder *p) #ifdef MY_CPU_X86_OR_AMD64 - #if defined(__clang__) && (__clang_major__ >= 8) \ - || defined(__GNUC__) && (__GNUC__ >= 8) \ - || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) - #define USE_SATUR_SUB_128 - #define USE_AVX2 - #define ATTRIB_SSE41 __attribute__((__target__("sse4.1"))) - #define ATTRIB_AVX2 __attribute__((__target__("avx2"))) + #if defined(__clang__) && (__clang_major__ >= 4) \ + || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701) + // || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) + + #define USE_LZFIND_SATUR_SUB_128 + #define USE_LZFIND_SATUR_SUB_256 + #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("sse4.1"))) + #define LZFIND_ATTRIB_AVX2 __attribute__((__target__("avx2"))) #elif defined(_MSC_VER) #if (_MSC_VER >= 1600) - #define USE_SATUR_SUB_128 - #if (_MSC_VER >= 1900) - #define USE_AVX2 - #include // avx - #endif + #define USE_LZFIND_SATUR_SUB_128 + #endif + #if (_MSC_VER >= 1900) + #define USE_LZFIND_SATUR_SUB_256 #endif #endif @@ -529,16 +612,16 @@ void MatchFinder_Init(CMatchFinder *p) #if defined(__clang__) && (__clang_major__ >= 8) \ || defined(__GNUC__) && (__GNUC__ >= 8) - #define USE_SATUR_SUB_128 + #define USE_LZFIND_SATUR_SUB_128 #ifdef MY_CPU_ARM64 - // #define ATTRIB_SSE41 __attribute__((__target__(""))) + // #define LZFIND_ATTRIB_SSE41 __attribute__((__target__(""))) #else - // #define ATTRIB_SSE41 __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) + // #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) #endif #elif defined(_MSC_VER) #if (_MSC_VER >= 1910) - #define USE_SATUR_SUB_128 + #define USE_LZFIND_SATUR_SUB_128 #endif #endif @@ -550,121 +633,130 @@ void MatchFinder_Init(CMatchFinder *p) #endif -/* -#ifndef ATTRIB_SSE41 - #define ATTRIB_SSE41 -#endif -#ifndef ATTRIB_AVX2 - #define ATTRIB_AVX2 -#endif -*/ -#ifdef USE_SATUR_SUB_128 +#ifdef USE_LZFIND_SATUR_SUB_128 -// #define _SHOW_HW_STATUS +// #define Z7_SHOW_HW_STATUS -#ifdef _SHOW_HW_STATUS +#ifdef Z7_SHOW_HW_STATUS #include -#define _PRF(x) x -_PRF(;) +#define PRF(x) x +PRF(;) #else -#define _PRF(x) +#define PRF(x) #endif + #ifdef MY_CPU_ARM_OR_ARM64 #ifdef MY_CPU_ARM64 -// #define FORCE_SATUR_SUB_128 +// #define FORCE_LZFIND_SATUR_SUB_128 #endif +typedef uint32x4_t LzFind_v128; +#define SASUB_128_V(v, s) \ + vsubq_u32(vmaxq_u32(v, s), s) -typedef uint32x4_t v128; -#define SASUB_128(i) \ - *(v128 *)(void *)(items + (i) * 4) = \ - vsubq_u32(vmaxq_u32(*(const v128 *)(const void *)(items + (i) * 4), sub2), sub2); - -#else +#else // MY_CPU_ARM_OR_ARM64 #include // sse4.1 -typedef __m128i v128; -#define SASUB_128(i) \ - *(v128 *)(void *)(items + (i) * 4) = \ - _mm_sub_epi32(_mm_max_epu32(*(const v128 *)(const void *)(items + (i) * 4), sub2), sub2); // SSE 4.1 +typedef __m128i LzFind_v128; +// SSE 4.1 +#define SASUB_128_V(v, s) \ + _mm_sub_epi32(_mm_max_epu32(v, s), s) -#endif +#endif // MY_CPU_ARM_OR_ARM64 +#define SASUB_128(i) \ + *( LzFind_v128 *)( void *)(items + (i) * 4) = SASUB_128_V( \ + *(const LzFind_v128 *)(const void *)(items + (i) * 4), sub2); + -MY_NO_INLINE +Z7_NO_INLINE static -#ifdef ATTRIB_SSE41 -ATTRIB_SSE41 +#ifdef LZFIND_ATTRIB_SSE41 +LZFIND_ATTRIB_SSE41 #endif void -MY_FAST_CALL +Z7_FASTCALL LzFind_SaturSub_128(UInt32 subValue, CLzRef *items, const CLzRef *lim) { - v128 sub2 = + const LzFind_v128 sub2 = #ifdef MY_CPU_ARM_OR_ARM64 vdupq_n_u32(subValue); #else _mm_set_epi32((Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); #endif + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { - SASUB_128(0) - SASUB_128(1) - SASUB_128(2) - SASUB_128(3) - items += 4 * 4; + SASUB_128(0) SASUB_128(1) items += 2 * 4; + SASUB_128(0) SASUB_128(1) items += 2 * 4; } while (items != lim); } -#ifdef USE_AVX2 +#ifdef USE_LZFIND_SATUR_SUB_256 #include // avx +/* +clang :immintrin.h uses +#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ + defined(__AVX2__) +#include +#endif +so we need for clang-cl */ -#define SASUB_256(i) *(__m256i *)(void *)(items + (i) * 8) = _mm256_sub_epi32(_mm256_max_epu32(*(const __m256i *)(const void *)(items + (i) * 8), sub2), sub2); // AVX2 +#if defined(__clang__) +#include +#include +#endif -MY_NO_INLINE +// AVX2: +#define SASUB_256(i) \ + *( __m256i *)( void *)(items + (i) * 8) = \ + _mm256_sub_epi32(_mm256_max_epu32( \ + *(const __m256i *)(const void *)(items + (i) * 8), sub2), sub2); + +Z7_NO_INLINE static -#ifdef ATTRIB_AVX2 -ATTRIB_AVX2 +#ifdef LZFIND_ATTRIB_AVX2 +LZFIND_ATTRIB_AVX2 #endif void -MY_FAST_CALL +Z7_FASTCALL LzFind_SaturSub_256(UInt32 subValue, CLzRef *items, const CLzRef *lim) { - __m256i sub2 = _mm256_set_epi32( + const __m256i sub2 = _mm256_set_epi32( (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { - SASUB_256(0) - SASUB_256(1) - items += 2 * 8; + SASUB_256(0) SASUB_256(1) items += 2 * 8; + SASUB_256(0) SASUB_256(1) items += 2 * 8; } while (items != lim); } -#endif // USE_AVX2 +#endif // USE_LZFIND_SATUR_SUB_256 -#ifndef FORCE_SATUR_SUB_128 -typedef void (MY_FAST_CALL *LZFIND_SATUR_SUB_CODE_FUNC)( +#ifndef FORCE_LZFIND_SATUR_SUB_128 +typedef void (Z7_FASTCALL *LZFIND_SATUR_SUB_CODE_FUNC)( UInt32 subValue, CLzRef *items, const CLzRef *lim); static LZFIND_SATUR_SUB_CODE_FUNC g_LzFind_SaturSub; -#endif // FORCE_SATUR_SUB_128 +#endif // FORCE_LZFIND_SATUR_SUB_128 -#endif // USE_SATUR_SUB_128 +#endif // USE_LZFIND_SATUR_SUB_128 // kEmptyHashValue must be zero -// #define SASUB_32(i) v = items[i]; m = v - subValue; if (v < subValue) m = kEmptyHashValue; items[i] = m; -#define SASUB_32(i) v = items[i]; if (v < subValue) v = subValue; items[i] = v - subValue; +// #define SASUB_32(i) { UInt32 v = items[i]; UInt32 m = v - subValue; if (v < subValue) m = kEmptyHashValue; items[i] = m; } +#define SASUB_32(i) { UInt32 v = items[i]; if (v < subValue) v = subValue; items[i] = v - subValue; } -#ifdef FORCE_SATUR_SUB_128 +#ifdef FORCE_LZFIND_SATUR_SUB_128 #define DEFAULT_SaturSub LzFind_SaturSub_128 @@ -672,24 +764,19 @@ static LZFIND_SATUR_SUB_CODE_FUNC g_LzFind_SaturSub; #define DEFAULT_SaturSub LzFind_SaturSub_32 -MY_NO_INLINE +Z7_NO_INLINE static void -MY_FAST_CALL +Z7_FASTCALL LzFind_SaturSub_32(UInt32 subValue, CLzRef *items, const CLzRef *lim) { + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { - UInt32 v; - SASUB_32(0) - SASUB_32(1) - SASUB_32(2) - SASUB_32(3) - SASUB_32(4) - SASUB_32(5) - SASUB_32(6) - SASUB_32(7) - items += 8; + SASUB_32(0) SASUB_32(1) items += 2; + SASUB_32(0) SASUB_32(1) items += 2; + SASUB_32(0) SASUB_32(1) items += 2; + SASUB_32(0) SASUB_32(1) items += 2; } while (items != lim); } @@ -697,27 +784,23 @@ LzFind_SaturSub_32(UInt32 subValue, CLzRef *items, const CLzRef *lim) #endif -MY_NO_INLINE +Z7_NO_INLINE void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) { - #define K_NORM_ALIGN_BLOCK_SIZE (1 << 6) - - CLzRef *lim; - - for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (K_NORM_ALIGN_BLOCK_SIZE - 1)) != 0; numItems--) + #define LZFIND_NORM_ALIGN_BLOCK_SIZE (1 << 7) + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (LZFIND_NORM_ALIGN_BLOCK_SIZE - 1)) != 0; numItems--) { - UInt32 v; - SASUB_32(0); + SASUB_32(0) items++; } - { - #define K_NORM_ALIGN_MASK (K_NORM_ALIGN_BLOCK_SIZE / 4 - 1) - lim = items + (numItems & ~(size_t)K_NORM_ALIGN_MASK); - numItems &= K_NORM_ALIGN_MASK; + const size_t k_Align_Mask = (LZFIND_NORM_ALIGN_BLOCK_SIZE / 4 - 1); + CLzRef *lim = items + (numItems & ~(size_t)k_Align_Mask); + numItems &= k_Align_Mask; if (items != lim) { - #if defined(USE_SATUR_SUB_128) && !defined(FORCE_SATUR_SUB_128) + #if defined(USE_LZFIND_SATUR_SUB_128) && !defined(FORCE_LZFIND_SATUR_SUB_128) if (g_LzFind_SaturSub) g_LzFind_SaturSub(subValue, items, lim); else @@ -726,12 +809,10 @@ void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) } items = lim; } - - + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE for (; numItems != 0; numItems--) { - UInt32 v; - SASUB_32(0); + SASUB_32(0) items++; } } @@ -740,7 +821,7 @@ void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) // call MatchFinder_CheckLimits() only after (p->pos++) update -MY_NO_INLINE +Z7_NO_INLINE static void MatchFinder_CheckLimits(CMatchFinder *p) { if (// !p->streamEndWasReached && p->result == SZ_OK && @@ -768,11 +849,14 @@ static void MatchFinder_CheckLimits(CMatchFinder *p) const UInt32 subValue = (p->pos - p->historySize - 1) /* & ~(UInt32)(kNormalizeAlign - 1) */; // const UInt32 subValue = (1 << 15); // for debug // printf("\nMatchFinder_Normalize() subValue == 0x%x\n", subValue); - size_t numSonRefs = p->cyclicBufferSize; - if (p->btMode) - numSonRefs <<= 1; - Inline_MatchFinder_ReduceOffsets(p, subValue); - MatchFinder_Normalize3(subValue, p->hash, (size_t)p->hashSizeSum + numSonRefs); + MatchFinder_REDUCE_OFFSETS(p, subValue) + MatchFinder_Normalize3(subValue, p->hash, (size_t)p->hashMask + 1 + p->fixedHashSize); + { + size_t numSonRefs = p->cyclicBufferSize; + if (p->btMode) + numSonRefs <<= 1; + MatchFinder_Normalize3(subValue, p->son, numSonRefs); + } } if (p->cyclicBufferPos == p->cyclicBufferSize) @@ -785,7 +869,7 @@ static void MatchFinder_CheckLimits(CMatchFinder *p) /* (lenLimit > maxLen) */ -MY_FORCE_INLINE +Z7_FORCE_INLINE static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *d, unsigned maxLen) @@ -867,7 +951,7 @@ static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos, } -MY_FORCE_INLINE +Z7_FORCE_INLINE UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *d, UInt32 maxLen) @@ -1004,7 +1088,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const #define MOVE_POS_RET MOVE_POS return distances; -MY_NO_INLINE +Z7_NO_INLINE static void MatchFinder_MovePos(CMatchFinder *p) { /* we go here at the end of stream data, when (avail < num_hash_bytes) @@ -1015,11 +1099,11 @@ static void MatchFinder_MovePos(CMatchFinder *p) if (p->btMode) p->sons[(p->cyclicBufferPos << p->btMode) + 1] = 0; // kEmptyHashValue */ - MOVE_POS; + MOVE_POS } #define GET_MATCHES_HEADER2(minLen, ret_op) \ - unsigned lenLimit; UInt32 hv; Byte *cur; UInt32 curMatch; \ + unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \ lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; @@ -1028,11 +1112,11 @@ static void MatchFinder_MovePos(CMatchFinder *p) #define MF_PARAMS(p) lenLimit, curMatch, p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue -#define SKIP_FOOTER SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS; } while (--num); +#define SKIP_FOOTER SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS } while (--num); #define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \ distances = func(MF_PARAMS(p), \ - distances, (UInt32)_maxLen_); MOVE_POS_RET; + distances, (UInt32)_maxLen_); MOVE_POS_RET #define GET_MATCHES_FOOTER_BT(_maxLen_) \ GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1) @@ -1052,7 +1136,7 @@ static void MatchFinder_MovePos(CMatchFinder *p) static UInt32* Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { GET_MATCHES_HEADER(2) - HASH2_CALC; + HASH2_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; GET_MATCHES_FOOTER_BT(1) @@ -1061,7 +1145,7 @@ static UInt32* Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { GET_MATCHES_HEADER(3) - HASH_ZIP_CALC; + HASH_ZIP_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; GET_MATCHES_FOOTER_BT(2) @@ -1082,7 +1166,7 @@ static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32 *hash; GET_MATCHES_HEADER(3) - HASH3_CALC; + HASH3_CALC hash = p->hash; pos = p->pos; @@ -1107,7 +1191,7 @@ static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) if (maxLen == lenLimit) { SkipMatchesSpec(MF_PARAMS(p)); - MOVE_POS_RET; + MOVE_POS_RET } } @@ -1123,7 +1207,7 @@ static UInt32* Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32 *hash; GET_MATCHES_HEADER(4) - HASH4_CALC; + HASH4_CALC hash = p->hash; pos = p->pos; @@ -1190,7 +1274,7 @@ static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32 *hash; GET_MATCHES_HEADER(5) - HASH5_CALC; + HASH5_CALC hash = p->hash; pos = p->pos; @@ -1246,7 +1330,7 @@ static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) if (maxLen == lenLimit) { SkipMatchesSpec(MF_PARAMS(p)); - MOVE_POS_RET; + MOVE_POS_RET } break; } @@ -1263,7 +1347,7 @@ static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32 *hash; GET_MATCHES_HEADER(4) - HASH4_CALC; + HASH4_CALC hash = p->hash; pos = p->pos; @@ -1314,12 +1398,12 @@ static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS_RET; + MOVE_POS_RET } break; } - GET_MATCHES_FOOTER_HC(maxLen); + GET_MATCHES_FOOTER_HC(maxLen) } @@ -1330,7 +1414,7 @@ static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32 *hash; GET_MATCHES_HEADER(5) - HASH5_CALC; + HASH5_CALC hash = p->hash; pos = p->pos; @@ -1386,19 +1470,19 @@ static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS_RET; + MOVE_POS_RET } break; } - GET_MATCHES_FOOTER_HC(maxLen); + GET_MATCHES_FOOTER_HC(maxLen) } UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { GET_MATCHES_HEADER(3) - HASH_ZIP_CALC; + HASH_ZIP_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; GET_MATCHES_FOOTER_HC(2) @@ -1409,7 +1493,7 @@ static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { SKIP_HEADER(2) { - HASH2_CALC; + HASH2_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; } @@ -1420,7 +1504,7 @@ void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { SKIP_HEADER(3) { - HASH_ZIP_CALC; + HASH_ZIP_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; } @@ -1433,7 +1517,7 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { UInt32 h2; UInt32 *hash; - HASH3_CALC; + HASH3_CALC hash = p->hash; curMatch = (hash + kFix3HashSize)[hv]; hash[h2] = @@ -1448,7 +1532,7 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { UInt32 h2, h3; UInt32 *hash; - HASH4_CALC; + HASH4_CALC hash = p->hash; curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = @@ -1464,7 +1548,7 @@ static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { UInt32 h2, h3; UInt32 *hash; - HASH5_CALC; + HASH5_CALC hash = p->hash; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = @@ -1478,7 +1562,7 @@ static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) #define HC_SKIP_HEADER(minLen) \ do { if (p->lenLimit < minLen) { MatchFinder_MovePos(p); num--; continue; } { \ - Byte *cur; \ + const Byte *cur; \ UInt32 *hash; \ UInt32 *son; \ UInt32 pos = p->pos; \ @@ -1510,7 +1594,7 @@ static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) HC_SKIP_HEADER(4) UInt32 h2, h3; - HASH4_CALC; + HASH4_CALC curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = @@ -1540,7 +1624,7 @@ void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { HC_SKIP_HEADER(3) - HASH_ZIP_CALC; + HASH_ZIP_CALC curMatch = hash[hv]; hash[hv] = pos; @@ -1590,17 +1674,17 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable) -void LzFindPrepare() +void LzFindPrepare(void) { - #ifndef FORCE_SATUR_SUB_128 - #ifdef USE_SATUR_SUB_128 + #ifndef FORCE_LZFIND_SATUR_SUB_128 + #ifdef USE_LZFIND_SATUR_SUB_128 LZFIND_SATUR_SUB_CODE_FUNC f = NULL; #ifdef MY_CPU_ARM_OR_ARM64 { if (CPU_IsSupported_NEON()) { // #pragma message ("=== LzFind NEON") - _PRF(printf("\n=== LzFind NEON\n")); + PRF(printf("\n=== LzFind NEON\n")); f = LzFind_SaturSub_128; } // f = 0; // for debug @@ -1609,20 +1693,25 @@ void LzFindPrepare() if (CPU_IsSupported_SSE41()) { // #pragma message ("=== LzFind SSE41") - _PRF(printf("\n=== LzFind SSE41\n")); + PRF(printf("\n=== LzFind SSE41\n")); f = LzFind_SaturSub_128; - #ifdef USE_AVX2 + #ifdef USE_LZFIND_SATUR_SUB_256 if (CPU_IsSupported_AVX2()) { // #pragma message ("=== LzFind AVX2") - _PRF(printf("\n=== LzFind AVX2\n")); + PRF(printf("\n=== LzFind AVX2\n")); f = LzFind_SaturSub_256; } #endif } #endif // MY_CPU_ARM_OR_ARM64 g_LzFind_SaturSub = f; - #endif // USE_SATUR_SUB_128 - #endif // FORCE_SATUR_SUB_128 + #endif // USE_LZFIND_SATUR_SUB_128 + #endif // FORCE_LZFIND_SATUR_SUB_128 } + + +#undef MOVE_POS +#undef MOVE_POS_RET +#undef PRF diff --git a/libraries/lzma/C/LzFind.h b/libraries/lzma/C/LzFind.h index eea873ff61..a3f72c9870 100644 --- a/libraries/lzma/C/LzFind.h +++ b/libraries/lzma/C/LzFind.h @@ -1,8 +1,8 @@ /* LzFind.h -- Match finder for LZ algorithms -2021-07-13 : Igor Pavlov : Public domain */ +2023-03-04 : Igor Pavlov : Public domain */ -#ifndef __LZ_FIND_H -#define __LZ_FIND_H +#ifndef ZIP7_INC_LZ_FIND_H +#define ZIP7_INC_LZ_FIND_H #include "7zTypes.h" @@ -10,9 +10,9 @@ EXTERN_C_BEGIN typedef UInt32 CLzRef; -typedef struct _CMatchFinder +typedef struct { - Byte *buffer; + const Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */ @@ -32,8 +32,8 @@ typedef struct _CMatchFinder UInt32 hashMask; UInt32 cutValue; - Byte *bufferBase; - ISeqInStream *stream; + Byte *bufBase; + ISeqInStreamPtr stream; UInt32 blockSize; UInt32 keepSizeBefore; @@ -43,7 +43,9 @@ typedef struct _CMatchFinder size_t directInputRem; UInt32 historySize; UInt32 fixedHashSize; - UInt32 hashSizeSum; + Byte numHashBytes_Min; + Byte numHashOutBits; + Byte _pad2_[2]; SRes result; UInt32 crc[256]; size_t numRefs; @@ -69,24 +71,45 @@ void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); -/* Conditions: - historySize <= 3 GB - keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +/* (directInput = 0) is default value. + It's required to provide correct (directInput) value + before calling MatchFinder_Create(). + You can set (directInput) by any of the following calls: + - MatchFinder_SET_DIRECT_INPUT_BUF() + - MatchFinder_SET_STREAM() + - MatchFinder_SET_STREAM_MODE() */ + +#define MatchFinder_SET_DIRECT_INPUT_BUF(p, _src_, _srcLen_) { \ + (p)->stream = NULL; \ + (p)->directInput = 1; \ + (p)->buffer = (_src_); \ + (p)->directInputRem = (_srcLen_); } + +/* +#define MatchFinder_SET_STREAM_MODE(p) { \ + (p)->directInput = 0; } +*/ + +#define MatchFinder_SET_STREAM(p, _stream_) { \ + (p)->stream = _stream_; \ + (p)->directInput = 0; } + + int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc); void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems); -// void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); /* -#define Inline_MatchFinder_InitPos(p, val) \ +#define MatchFinder_INIT_POS(p, val) \ (p)->pos = (val); \ (p)->streamPos = (val); */ -#define Inline_MatchFinder_ReduceOffsets(p, subValue) \ +// void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); +#define MatchFinder_REDUCE_OFFSETS(p, subValue) \ (p)->pos -= (subValue); \ (p)->streamPos -= (subValue); @@ -107,7 +130,7 @@ typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 * (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); -typedef struct _IMatchFinder +typedef struct { Mf_Init_Func Init; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; diff --git a/libraries/lzma/C/LzFindMt.c b/libraries/lzma/C/LzFindMt.c index 4e67fc3f2f..5253e6ebb3 100644 --- a/libraries/lzma/C/LzFindMt.c +++ b/libraries/lzma/C/LzFindMt.c @@ -1,5 +1,5 @@ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms -2021-12-21 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -69,7 +69,7 @@ extern UInt64 g_NumIters_Bytes; UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } -#define __MT_HASH4_CALC { \ +#define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ h2 = temp & (kHash2Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \ @@ -79,14 +79,14 @@ extern UInt64 g_NumIters_Bytes; */ -MY_NO_INLINE +Z7_NO_INLINE static void MtSync_Construct(CMtSync *p) { p->affinity = 0; p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; - Thread_Construct(&p->thread); + Thread_CONSTRUCT(&p->thread) Event_Construct(&p->canStart); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); @@ -116,7 +116,7 @@ static void MtSync_Construct(CMtSync *p) (p)->csWasEntered = False; } -MY_NO_INLINE +Z7_NO_INLINE static UInt32 MtSync_GetNextBlock(CMtSync *p) { UInt32 numBlocks = 0; @@ -140,14 +140,14 @@ static UInt32 MtSync_GetNextBlock(CMtSync *p) // buffer is UNLOCKED here Semaphore_Wait(&p->filledSemaphore); - LOCK_BUFFER(p); + LOCK_BUFFER(p) return numBlocks; } /* if Writing (Processing) thread was started, we must call MtSync_StopWriting() */ -MY_NO_INLINE +Z7_NO_INLINE static void MtSync_StopWriting(CMtSync *p) { if (!Thread_WasCreated(&p->thread) || p->needStart) @@ -185,7 +185,7 @@ static void MtSync_StopWriting(CMtSync *p) } -MY_NO_INLINE +Z7_NO_INLINE static void MtSync_Destruct(CMtSync *p) { PRF(printf("\nMtSync_Destruct %p\n", p)); @@ -220,11 +220,11 @@ static void MtSync_Destruct(CMtSync *p) // #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } // we want to get real system error codes here instead of SZ_ERROR_THREAD -#define RINOK_THREAD(x) RINOK(x) +#define RINOK_THREAD(x) RINOK_WRes(x) // call it before each new file (when new starting is required): -MY_NO_INLINE +Z7_NO_INLINE static SRes MtSync_Init(CMtSync *p, UInt32 numBlocks) { WRes wres; @@ -245,12 +245,12 @@ static WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void * if (p->wasCreated) return SZ_OK; - RINOK_THREAD(CriticalSection_Init(&p->cs)); + RINOK_THREAD(CriticalSection_Init(&p->cs)) p->csWasInitialized = True; p->csWasEntered = False; - RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); - RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)) + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)) p->needStart = True; p->exit = True; /* p->exit is unused before (canStart) Event. @@ -264,13 +264,13 @@ static WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void * else wres = Thread_Create(&p->thread, startAddress, obj); - RINOK_THREAD(wres); + RINOK_THREAD(wres) p->wasCreated = True; return SZ_OK; } -MY_NO_INLINE +Z7_NO_INLINE static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) { const WRes wres = MtSync_Create_WRes(p, startAddress, obj); @@ -519,7 +519,7 @@ static void HashThreadFunc(CMatchFinderMt *mt) if (mf->pos > (UInt32)kMtMaxValForNormalize - num) { const UInt32 subValue = (mf->pos - mf->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); - Inline_MatchFinder_ReduceOffsets(mf, subValue); + MatchFinder_REDUCE_OFFSETS(mf, subValue) MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); } @@ -560,7 +560,7 @@ static void HashThreadFunc(CMatchFinderMt *mt) */ -UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, +UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 *posRes); @@ -749,7 +749,7 @@ static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) } -MY_NO_INLINE +Z7_NO_INLINE static void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; @@ -864,15 +864,15 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZ_ERROR_MEM; - RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p)); - RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p)); + RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p)) + RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p)) return SZ_OK; } SRes MatchFinderMt_InitMt(CMatchFinderMt *p) { - RINOK(MtSync_Init(&p->hashSync, kMtHashNumBlocks)); + RINOK(MtSync_Init(&p->hashSync, kMtHashNumBlocks)) return MtSync_Init(&p->btSync, kMtBtNumBlocks); } @@ -941,7 +941,7 @@ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) } -MY_NO_INLINE +Z7_NO_INLINE static UInt32 MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { if (p->failure_LZ_BT) @@ -1163,7 +1163,7 @@ UInt32* MatchFinderMt_GetMatches_Bt4(CMatchFinderMt *p, UInt32 *d) */ -static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) +static UInt32 * MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) { UInt32 h2, h3, /* h4, */ c2, c3 /* , c4 */; UInt32 *hash = p->hash; @@ -1179,9 +1179,8 @@ static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) (hash + kFix3HashSize)[h3] = m; // (hash + kFix4HashSize)[h4] = m; - #define _USE_H2 - - #ifdef _USE_H2 + // #define BT5_USE_H2 + // #ifdef BT5_USE_H2 if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { d[1] = m - c2 - 1; @@ -1197,8 +1196,8 @@ static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) } d[0] = 3; d += 2; - - #ifdef _USE_H4 + + #ifdef BT5_USE_H4 if (c4 >= matchMinPos) if ( cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && @@ -1214,7 +1213,7 @@ static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) d[0] = 2; d += 2; } - #endif + // #endif if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) { @@ -1228,7 +1227,7 @@ static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) d += 2; } - #ifdef _USE_H4 + #ifdef BT5_USE_H4 if (c4 >= matchMinPos) if ( cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && @@ -1244,7 +1243,7 @@ static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) } -static UInt32* MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d) +static UInt32 * MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d) { const UInt32 *bt = p->btBufPos; const UInt32 len = *bt++; @@ -1268,7 +1267,7 @@ static UInt32* MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d) -static UInt32* MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d) +static UInt32 * MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d) { const UInt32 *bt = p->btBufPos; UInt32 len = *bt++; @@ -1398,3 +1397,10 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable) break; } } + +#undef RINOK_THREAD +#undef PRF +#undef MF +#undef GetUi24hi_from32 +#undef LOCK_BUFFER +#undef UNLOCK_BUFFER diff --git a/libraries/lzma/C/LzFindMt.h b/libraries/lzma/C/LzFindMt.h index 660b7244d1..db5923ea05 100644 --- a/libraries/lzma/C/LzFindMt.h +++ b/libraries/lzma/C/LzFindMt.h @@ -1,15 +1,15 @@ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms -2021-07-12 : Igor Pavlov : Public domain */ +2023-03-05 : Igor Pavlov : Public domain */ -#ifndef __LZ_FIND_MT_H -#define __LZ_FIND_MT_H +#ifndef ZIP7_INC_LZ_FIND_MT_H +#define ZIP7_INC_LZ_FIND_MT_H #include "LzFind.h" #include "Threads.h" EXTERN_C_BEGIN -typedef struct _CMtSync +typedef struct { UInt32 numProcessedBlocks; CThread thread; @@ -39,7 +39,7 @@ typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distance typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); -typedef struct _CMatchFinderMt +typedef struct { /* LZ */ const Byte *pointerToCurPos; diff --git a/libraries/lzma/C/LzFindOpt.c b/libraries/lzma/C/LzFindOpt.c index 8ff006e074..85bdc136d6 100644 --- a/libraries/lzma/C/LzFindOpt.c +++ b/libraries/lzma/C/LzFindOpt.c @@ -1,5 +1,5 @@ /* LzFindOpt.c -- multithreaded Match finder for LZ algorithms -2021-07-13 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -41,8 +41,8 @@ UInt64 g_NumIters_Bytes; // #define CYC_TO_POS_OFFSET 1 // for debug /* -MY_NO_INLINE -UInt32 * MY_FAST_CALL GetMatchesSpecN_1(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, +Z7_NO_INLINE +UInt32 * Z7_FASTCALL GetMatchesSpecN_1(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, UInt32 *posRes) { do @@ -214,13 +214,13 @@ else to eliminate "movsx" BUG in old MSVC x64 compiler. */ -UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, +UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 *posRes); -MY_NO_INLINE -UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, +Z7_NO_INLINE +UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 *posRes) @@ -404,7 +404,7 @@ else /* typedef UInt32 uint32plus; // size_t -UInt32 * MY_FAST_CALL GetMatchesSpecN_3(uint32plus lenLimit, size_t pos, const Byte *cur, CLzRef *son, +UInt32 * Z7_FASTCALL GetMatchesSpecN_3(uint32plus lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, uint32plus _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 *posRes) diff --git a/libraries/lzma/C/LzHash.h b/libraries/lzma/C/LzHash.h index 77b898cfab..2b6290b64c 100644 --- a/libraries/lzma/C/LzHash.h +++ b/libraries/lzma/C/LzHash.h @@ -1,8 +1,8 @@ -/* LzHash.h -- HASH functions for LZ algorithms -2019-10-30 : Igor Pavlov : Public domain */ +/* LzHash.h -- HASH constants for LZ algorithms +2023-03-05 : Igor Pavlov : Public domain */ -#ifndef __LZ_HASH_H -#define __LZ_HASH_H +#ifndef ZIP7_INC_LZ_HASH_H +#define ZIP7_INC_LZ_HASH_H /* (kHash2Size >= (1 << 8)) : Required diff --git a/libraries/lzma/C/Lzma2Dec.c b/libraries/lzma/C/Lzma2Dec.c index ac970a843d..388cbc7173 100644 --- a/libraries/lzma/C/Lzma2Dec.c +++ b/libraries/lzma/C/Lzma2Dec.c @@ -1,5 +1,5 @@ /* Lzma2Dec.c -- LZMA2 Decoder -2021-02-09 : Igor Pavlov : Public domain */ +2023-03-03 : Igor Pavlov : Public domain */ /* #define SHOW_DEBUG_INFO */ @@ -71,14 +71,14 @@ static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) { Byte props[LZMA_PROPS_SIZE]; - RINOK(Lzma2Dec_GetOldProps(prop, props)); + RINOK(Lzma2Dec_GetOldProps(prop, props)) return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); } SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) { Byte props[LZMA_PROPS_SIZE]; - RINOK(Lzma2Dec_GetOldProps(prop, props)); + RINOK(Lzma2Dec_GetOldProps(prop, props)) return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); } @@ -474,8 +474,8 @@ SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SizeT outSize = *destLen, inSize = *srcLen; *destLen = *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; - Lzma2Dec_Construct(&p); - RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); + Lzma2Dec_CONSTRUCT(&p) + RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)) p.decoder.dic = dest; p.decoder.dicBufSize = outSize; Lzma2Dec_Init(&p); @@ -487,3 +487,5 @@ SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Lzma2Dec_FreeProbs(&p, alloc); return res; } + +#undef PRF diff --git a/libraries/lzma/C/Lzma2Dec.h b/libraries/lzma/C/Lzma2Dec.h index b8ddeac890..1f5233a728 100644 --- a/libraries/lzma/C/Lzma2Dec.h +++ b/libraries/lzma/C/Lzma2Dec.h @@ -1,8 +1,8 @@ /* Lzma2Dec.h -- LZMA2 Decoder -2018-02-19 : Igor Pavlov : Public domain */ +2023-03-03 : Igor Pavlov : Public domain */ -#ifndef __LZMA2_DEC_H -#define __LZMA2_DEC_H +#ifndef ZIP7_INC_LZMA2_DEC_H +#define ZIP7_INC_LZMA2_DEC_H #include "LzmaDec.h" @@ -22,9 +22,10 @@ typedef struct CLzmaDec decoder; } CLzma2Dec; -#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) -#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc) -#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc) +#define Lzma2Dec_CONSTRUCT(p) LzmaDec_CONSTRUCT(&(p)->decoder) +#define Lzma2Dec_Construct(p) Lzma2Dec_CONSTRUCT(p) +#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc) +#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc) SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); @@ -90,7 +91,7 @@ Lzma2Dec_GetUnpackExtra() returns the value that shows at current input positon. */ -#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0); +#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0) /* ---------- One Call Interface ---------- */ diff --git a/libraries/lzma/C/Lzma2DecMt.c b/libraries/lzma/C/Lzma2DecMt.c new file mode 100644 index 0000000000..4bc4ddeb5c --- /dev/null +++ b/libraries/lzma/C/Lzma2DecMt.c @@ -0,0 +1,1095 @@ +/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread +2023-04-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #define SHOW_DEBUG_INFO +// #define Z7_ST + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include "Alloc.h" + +#include "Lzma2Dec.h" +#include "Lzma2DecMt.h" + +#ifndef Z7_ST +#include "MtDec.h" + +#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28) +#endif + + +#ifndef Z7_ST +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif +#define PRF_STR(s) PRF(printf("\n" s "\n");) +#define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2);) +#endif + + +void Lzma2DecMtProps_Init(CLzma2DecMtProps *p) +{ + p->inBufSize_ST = 1 << 20; + p->outStep_ST = 1 << 20; + + #ifndef Z7_ST + p->numThreads = 1; + p->inBufSize_MT = 1 << 18; + p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT; + p->inBlockMax = p->outBlockMax + p->outBlockMax / 16; + #endif +} + + + +#ifndef Z7_ST + +/* ---------- CLzma2DecMtThread ---------- */ + +typedef struct +{ + CLzma2Dec dec; + Byte dec_created; + Byte needInit; + + Byte *outBuf; + size_t outBufSize; + + EMtDecParseState state; + ELzma2ParseStatus parseStatus; + + size_t inPreSize; + size_t outPreSize; + + size_t inCodeSize; + size_t outCodeSize; + SRes codeRes; + + CAlignOffsetAlloc alloc; + + Byte mtPad[1 << 7]; +} CLzma2DecMtThread; + +#endif + + +/* ---------- CLzma2DecMt ---------- */ + +struct CLzma2DecMt +{ + // ISzAllocPtr alloc; + ISzAllocPtr allocMid; + + CAlignOffsetAlloc alignOffsetAlloc; + CLzma2DecMtProps props; + Byte prop; + + ISeqInStreamPtr inStream; + ISeqOutStreamPtr outStream; + ICompressProgressPtr progress; + + BoolInt finishMode; + BoolInt outSize_Defined; + UInt64 outSize; + + UInt64 outProcessed; + UInt64 inProcessed; + BoolInt readWasFinished; + SRes readRes; + + Byte *inBuf; + size_t inBufSize; + Byte dec_created; + CLzma2Dec dec; + + size_t inPos; + size_t inLim; + + #ifndef Z7_ST + UInt64 outProcessed_Parse; + BoolInt mtc_WasConstructed; + CMtDec mtc; + CLzma2DecMtThread coders[MTDEC_THREADS_MAX]; + #endif +}; + + + +CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) +{ + CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt)); + if (!p) + return NULL; + + // p->alloc = alloc; + p->allocMid = allocMid; + + AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); + p->alignOffsetAlloc.numAlignBits = 7; + p->alignOffsetAlloc.offset = 0; + p->alignOffsetAlloc.baseAlloc = alloc; + + p->inBuf = NULL; + p->inBufSize = 0; + p->dec_created = False; + + // Lzma2DecMtProps_Init(&p->props); + + #ifndef Z7_ST + p->mtc_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTDEC_THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + t->dec_created = False; + t->outBuf = NULL; + t->outBufSize = 0; + } + } + #endif + + return (CLzma2DecMtHandle)(void *)p; +} + + +#ifndef Z7_ST + +static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p) +{ + unsigned i; + for (i = 0; i < MTDEC_THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + if (t->outBuf) + { + ISzAlloc_Free(p->allocMid, t->outBuf); + t->outBuf = NULL; + t->outBufSize = 0; + } + } +} + +#endif + + +static void Lzma2DecMt_FreeSt(CLzma2DecMt *p) +{ + if (p->dec_created) + { + Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt); + p->dec_created = False; + } + if (p->inBuf) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBuf = NULL; + } + p->inBufSize = 0; +} + + +// #define GET_CLzma2DecMt_p CLzma2DecMt *p = (CLzma2DecMt *)(void *)pp; + +void Lzma2DecMt_Destroy(CLzma2DecMtHandle p) +{ + // GET_CLzma2DecMt_p + + Lzma2DecMt_FreeSt(p); + + #ifndef Z7_ST + + if (p->mtc_WasConstructed) + { + MtDec_Destruct(&p->mtc); + p->mtc_WasConstructed = False; + } + { + unsigned i; + for (i = 0; i < MTDEC_THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + if (t->dec_created) + { + // we don't need to free dict here + Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!! + t->dec_created = False; + } + } + } + Lzma2DecMt_FreeOutBufs(p); + + #endif + + ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p); +} + + + +#ifndef Z7_ST + +static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) +{ + CLzma2DecMt *me = (CLzma2DecMt *)obj; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + + PRF_STR_INT_2("Parse", coderIndex, cc->srcSize) + + cc->state = MTDEC_PARSE_CONTINUE; + + if (cc->startCall) + { + if (!t->dec_created) + { + Lzma2Dec_CONSTRUCT(&t->dec) + t->dec_created = True; + AlignOffsetAlloc_CreateVTable(&t->alloc); + { + /* (1 << 12) is expected size of one way in data cache. + We optimize alignment for cache line size of 128 bytes and smaller */ + const unsigned kNumAlignBits = 12; + const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */ + t->alloc.numAlignBits = kNumAlignBits; + t->alloc.offset = ((UInt32)coderIndex * (((unsigned)1 << 11) + (1 << 8) + (1 << 6))) & (((unsigned)1 << kNumAlignBits) - ((unsigned)1 << kNumCacheLineBits)); + t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc; + } + } + Lzma2Dec_Init(&t->dec); + + t->inPreSize = 0; + t->outPreSize = 0; + // t->blockWasFinished = False; + // t->finishedWithMark = False; + t->parseStatus = (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED; + t->state = MTDEC_PARSE_CONTINUE; + + t->inCodeSize = 0; + t->outCodeSize = 0; + t->codeRes = SZ_OK; + + // (cc->srcSize == 0) is allowed + } + + { + ELzma2ParseStatus status; + BoolInt overflow; + UInt32 unpackRem = 0; + + int checkFinishBlock = True; + size_t limit = me->props.outBlockMax; + if (me->outSize_Defined) + { + UInt64 rem = me->outSize - me->outProcessed_Parse; + if (limit >= rem) + { + limit = (size_t)rem; + if (!me->finishMode) + checkFinishBlock = False; + } + } + + // checkFinishBlock = False, if we want to decode partial data + // that must be finished at position <= outBlockMax. + + { + const size_t srcOrig = cc->srcSize; + SizeT srcSize_Point = 0; + SizeT dicPos_Point = 0; + + cc->srcSize = 0; + overflow = False; + + for (;;) + { + SizeT srcCur = (SizeT)(srcOrig - cc->srcSize); + + status = Lzma2Dec_Parse(&t->dec, + (SizeT)limit - t->dec.decoder.dicPos, + cc->src + cc->srcSize, &srcCur, + checkFinishBlock); + + cc->srcSize += srcCur; + + if (status == LZMA2_PARSE_STATUS_NEW_CHUNK) + { + if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos) + { + overflow = True; + break; + } + continue; + } + + if (status == LZMA2_PARSE_STATUS_NEW_BLOCK) + { + if (t->dec.decoder.dicPos == 0) + continue; + // we decode small blocks in one thread + if (t->dec.decoder.dicPos >= (1 << 14)) + break; + dicPos_Point = t->dec.decoder.dicPos; + srcSize_Point = (SizeT)cc->srcSize; + continue; + } + + if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock + // && limit == t->dec.decoder.dicPos + // && limit == me->props.outBlockMax + ) + { + overflow = True; + break; + } + + unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec); + break; + } + + if (dicPos_Point != 0 + && (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK + && (int)status != LZMA_STATUS_FINISHED_WITH_MARK + && (int)status != LZMA_STATUS_NOT_SPECIFIED) + { + // we revert to latest newBlock state + status = LZMA2_PARSE_STATUS_NEW_BLOCK; + unpackRem = 0; + t->dec.decoder.dicPos = dicPos_Point; + cc->srcSize = srcSize_Point; + overflow = False; + } + } + + t->inPreSize += cc->srcSize; + t->parseStatus = status; + + if (overflow) + cc->state = MTDEC_PARSE_OVERFLOW; + else + { + size_t dicPos = t->dec.decoder.dicPos; + + if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (status == LZMA2_PARSE_STATUS_NEW_BLOCK) + { + cc->state = MTDEC_PARSE_NEW; + cc->srcSize--; // we don't need control byte of next block + t->inPreSize--; + } + else + { + cc->state = MTDEC_PARSE_END; + if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK) + { + // (status == LZMA_STATUS_NOT_SPECIFIED) + // (status == LZMA_STATUS_NOT_FINISHED) + if (unpackRem != 0) + { + /* we also reserve space for max possible number of output bytes of current LZMA chunk */ + size_t rem = limit - dicPos; + if (rem > unpackRem) + rem = unpackRem; + dicPos += rem; + } + } + } + + me->outProcessed_Parse += dicPos; + } + + cc->outPos = dicPos; + t->outPreSize = (size_t)dicPos; + } + + t->state = cc->state; + return; + } +} + + +static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + Byte *dest = t->outBuf; + + if (t->inPreSize == 0) + { + t->codeRes = SZ_ERROR_DATA; + return t->codeRes; + } + + if (!dest || t->outBufSize < t->outPreSize) + { + if (dest) + { + ISzAlloc_Free(me->allocMid, dest); + t->outBuf = NULL; + t->outBufSize = 0; + } + + dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize + // + (1 << 28) + ); + // Sleep(200); + if (!dest) + return SZ_ERROR_MEM; + t->outBuf = dest; + t->outBufSize = t->outPreSize; + } + + t->dec.decoder.dic = dest; + t->dec.decoder.dicBufSize = (SizeT)t->outPreSize; + + t->needInit = True; + + return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt +} + + +static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + // int finished, int blockFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + + UNUSED_VAR(srcFinished) + + PRF_STR_INT_2("Code", coderIndex, srcSize) + + *inCodePos = t->inCodeSize; + *outCodePos = 0; + *stop = True; + + if (t->needInit) + { + Lzma2Dec_Init(&t->dec); + t->needInit = False; + } + + { + ELzmaStatus status; + SizeT srcProcessed = (SizeT)srcSize; + BoolInt blockWasFinished = + ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK); + + SRes res = Lzma2Dec_DecodeToDic(&t->dec, + (SizeT)t->outPreSize, + src, &srcProcessed, + blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY, + &status); + + t->codeRes = res; + + t->inCodeSize += srcProcessed; + *inCodePos = t->inCodeSize; + t->outCodeSize = t->dec.decoder.dicPos; + *outCodePos = t->dec.decoder.dicPos; + + if (res != SZ_OK) + return res; + + if (srcProcessed == srcSize) + *stop = False; + + if (blockWasFinished) + { + if (srcSize != srcProcessed) + return SZ_ERROR_FAIL; + + if (t->inPreSize == t->inCodeSize) + { + if (t->outPreSize != t->outCodeSize) + return SZ_ERROR_FAIL; + *stop = True; + } + } + else + { + if (t->outPreSize == t->outCodeSize) + *stop = True; + } + + return SZ_OK; + } +} + + +#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24) + +static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex, + BoolInt needWriteToStream, + const Byte *src, size_t srcSize, BoolInt isCross, + BoolInt *needContinue, BoolInt *canRecode) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + const CLzma2DecMtThread *t = &me->coders[coderIndex]; + size_t size = t->outCodeSize; + const Byte *data = t->outBuf; + BoolInt needContinue2 = True; + + UNUSED_VAR(src) + UNUSED_VAR(srcSize) + UNUSED_VAR(isCross) + + PRF_STR_INT_2("Write", coderIndex, srcSize) + + *needContinue = False; + *canRecode = True; + + if ( + // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + t->state == MTDEC_PARSE_OVERFLOW + || t->state == MTDEC_PARSE_END) + needContinue2 = False; + + + if (!needWriteToStream) + return SZ_OK; + + me->mtc.inProcessed += t->inCodeSize; + + if (t->codeRes == SZ_OK) + if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK) + if (t->outPreSize != t->outCodeSize + || t->inPreSize != t->inCodeSize) + return SZ_ERROR_FAIL; + + *canRecode = False; + + if (me->outStream) + { + for (;;) + { + size_t cur = size; + size_t written; + if (cur > LZMA2DECMT_STREAM_WRITE_STEP) + cur = LZMA2DECMT_STREAM_WRITE_STEP; + + written = ISeqOutStream_Write(me->outStream, data, cur); + + me->outProcessed += written; + // me->mtc.writtenTotal += written; + if (written != cur) + return SZ_ERROR_WRITE; + data += cur; + size -= cur; + if (size == 0) + { + *needContinue = needContinue2; + return SZ_OK; + } + RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0)) + } + } + + return SZ_ERROR_FAIL; + /* + if (size > me->outBufSize) + return SZ_ERROR_OUTPUT_EOF; + memcpy(me->outBuf, data, size); + me->outBufSize -= size; + me->outBuf += size; + *needContinue = needContinue2; + return SZ_OK; + */ +} + +#endif + + +static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p) +{ + if (!p->dec_created) + { + Lzma2Dec_CONSTRUCT(&p->dec) + p->dec_created = True; + } + + RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt)) + + if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBufSize = 0; + p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); + if (!p->inBuf) + return SZ_ERROR_MEM; + p->inBufSize = p->props.inBufSize_ST; + } + + Lzma2Dec_Init(&p->dec); + + return SZ_OK; +} + + +static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p + #ifndef Z7_ST + , BoolInt tMode + #endif + ) +{ + SizeT wrPos; + size_t inPos, inLim; + const Byte *inData; + UInt64 inPrev, outPrev; + + CLzma2Dec *dec; + + #ifndef Z7_ST + if (tMode) + { + Lzma2DecMt_FreeOutBufs(p); + tMode = MtDec_PrepareRead(&p->mtc); + } + #endif + + RINOK(Lzma2Dec_Prepare_ST(p)) + + dec = &p->dec; + + inPrev = p->inProcessed; + outPrev = p->outProcessed; + + inPos = 0; + inLim = 0; + inData = NULL; + wrPos = dec->decoder.dicPos; + + for (;;) + { + SizeT dicPos; + SizeT size; + ELzmaFinishMode finishMode; + SizeT inProcessed; + ELzmaStatus status; + SRes res; + + SizeT outProcessed; + BoolInt outFinished; + BoolInt needStop; + + if (inPos == inLim) + { + #ifndef Z7_ST + if (tMode) + { + inData = MtDec_Read(&p->mtc, &inLim); + inPos = 0; + if (inData) + continue; + tMode = False; + inLim = 0; + } + #endif + + if (!p->readWasFinished) + { + inPos = 0; + inLim = p->inBufSize; + inData = p->inBuf; + p->readRes = ISeqInStream_Read(p->inStream, (void *)(p->inBuf), &inLim); + // p->readProcessed += inLim; + // inLim -= 5; p->readWasFinished = True; // for test + if (inLim == 0 || p->readRes != SZ_OK) + p->readWasFinished = True; + } + } + + dicPos = dec->decoder.dicPos; + { + SizeT next = dec->decoder.dicBufSize; + if (next - wrPos > p->props.outStep_ST) + next = wrPos + (SizeT)p->props.outStep_ST; + size = next - dicPos; + } + + finishMode = LZMA_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (size >= rem) + { + size = (SizeT)rem; + if (p->finishMode) + finishMode = LZMA_FINISH_END; + } + } + + inProcessed = (SizeT)(inLim - inPos); + + res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status); + + inPos += inProcessed; + p->inProcessed += inProcessed; + outProcessed = dec->decoder.dicPos - dicPos; + p->outProcessed += outProcessed; + + outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed); + + needStop = (res != SZ_OK + || (inProcessed == 0 && outProcessed == 0) + || status == LZMA_STATUS_FINISHED_WITH_MARK + || (!p->finishMode && outFinished)); + + if (needStop || outProcessed >= size) + { + SRes res2; + { + size_t writeSize = dec->decoder.dicPos - wrPos; + size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize); + res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE; + } + + if (dec->decoder.dicPos == dec->decoder.dicBufSize) + dec->decoder.dicPos = 0; + wrPos = dec->decoder.dicPos; + + RINOK(res2) + + if (needStop) + { + if (res != SZ_OK) + return res; + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (p->finishMode) + { + if (p->outSize_Defined && p->outSize != p->outProcessed) + return SZ_ERROR_DATA; + } + return SZ_OK; + } + + if (!p->finishMode && outFinished) + return SZ_OK; + + if (status == LZMA_STATUS_NEEDS_MORE_INPUT) + return SZ_ERROR_INPUT_EOF; + + return SZ_ERROR_DATA; + } + } + + if (p->progress) + { + UInt64 inDelta = p->inProcessed - inPrev; + UInt64 outDelta = p->outProcessed - outPrev; + if (inDelta >= (1 << 22) || outDelta >= (1 << 22)) + { + RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed)) + inPrev = p->inProcessed; + outPrev = p->outProcessed; + } + } + } +} + + + +SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p, + Byte prop, + const CLzma2DecMtProps *props, + ISeqOutStreamPtr outStream, const UInt64 *outDataSize, int finishMode, + // Byte *outBuf, size_t *outBufSize, + ISeqInStreamPtr inStream, + // const Byte *inData, size_t inDataSize, + UInt64 *inProcessed, + // UInt64 *outProcessed, + int *isMT, + ICompressProgressPtr progress) +{ + // GET_CLzma2DecMt_p + #ifndef Z7_ST + BoolInt tMode; + #endif + + *inProcessed = 0; + + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + + p->prop = prop; + p->props = *props; + + p->inStream = inStream; + p->outStream = outStream; + p->progress = progress; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + p->finishMode = finishMode; + + p->outProcessed = 0; + p->inProcessed = 0; + + p->readWasFinished = False; + p->readRes = SZ_OK; + + *isMT = False; + + + #ifndef Z7_ST + + tMode = False; + + // p->mtc.parseRes = SZ_OK; + + // p->mtc.numFilledThreads = 0; + // p->mtc.crossStart = 0; + // p->mtc.crossEnd = 0; + // p->mtc.allocError_for_Read_BlockIndex = 0; + // p->mtc.isAllocError = False; + + if (p->props.numThreads > 1) + { + IMtDecCallback2 vt; + + Lzma2DecMt_FreeSt(p); + + p->outProcessed_Parse = 0; + + if (!p->mtc_WasConstructed) + { + p->mtc_WasConstructed = True; + MtDec_Construct(&p->mtc); + } + + p->mtc.progress = progress; + p->mtc.inStream = inStream; + + // p->outBuf = NULL; + // p->outBufSize = 0; + /* + if (!outStream) + { + // p->outBuf = outBuf; + // p->outBufSize = *outBufSize; + // *outBufSize = 0; + return SZ_ERROR_PARAM; + } + */ + + // p->mtc.inBlockMax = p->props.inBlockMax; + p->mtc.alloc = &p->alignOffsetAlloc.vt; + // p->alignOffsetAlloc.baseAlloc; + // p->mtc.inData = inData; + // p->mtc.inDataSize = inDataSize; + p->mtc.mtCallback = &vt; + p->mtc.mtCallbackObject = p; + + p->mtc.inBufSize = p->props.inBufSize_MT; + + p->mtc.numThreadsMax = p->props.numThreads; + + *isMT = True; + + vt.Parse = Lzma2DecMt_MtCallback_Parse; + vt.PreCode = Lzma2DecMt_MtCallback_PreCode; + vt.Code = Lzma2DecMt_MtCallback_Code; + vt.Write = Lzma2DecMt_MtCallback_Write; + + { + BoolInt needContinue = False; + + SRes res = MtDec_Code(&p->mtc); + + /* + if (!outStream) + *outBufSize = p->outBuf - outBuf; + */ + + *inProcessed = p->mtc.inProcessed; + + needContinue = False; + + if (res == SZ_OK) + { + if (p->mtc.mtProgress.res != SZ_OK) + res = p->mtc.mtProgress.res; + else + needContinue = p->mtc.needContinue; + } + + if (!needContinue) + { + if (res == SZ_OK) + return p->mtc.readRes; + return res; + } + + tMode = True; + p->readRes = p->mtc.readRes; + p->readWasFinished = p->mtc.readWasFinished; + p->inProcessed = p->mtc.inProcessed; + + PRF_STR("----- decoding ST -----") + } + } + + #endif + + + *isMT = False; + + { + SRes res = Lzma2Dec_Decode_ST(p + #ifndef Z7_ST + , tMode + #endif + ); + + *inProcessed = p->inProcessed; + + // res = SZ_OK; // for test + if (res == SZ_ERROR_INPUT_EOF) + { + if (p->readRes != SZ_OK) + res = p->readRes; + } + else if (res == SZ_OK && p->readRes != SZ_OK) + res = p->readRes; + + /* + #ifndef Z7_ST + if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK) + res = p->mtc.parseRes; + #endif + */ + + return res; + } +} + + +/* ---------- Read from CLzma2DecMtHandle Interface ---------- */ + +SRes Lzma2DecMt_Init(CLzma2DecMtHandle p, + Byte prop, + const CLzma2DecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqInStreamPtr inStream) +{ + // GET_CLzma2DecMt_p + + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + + p->prop = prop; + p->props = *props; + + p->inStream = inStream; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + p->finishMode = finishMode; + + p->outProcessed = 0; + p->inProcessed = 0; + + p->inPos = 0; + p->inLim = 0; + + return Lzma2Dec_Prepare_ST(p); +} + + +SRes Lzma2DecMt_Read(CLzma2DecMtHandle p, + Byte *data, size_t *outSize, + UInt64 *inStreamProcessed) +{ + // GET_CLzma2DecMt_p + ELzmaFinishMode finishMode; + SRes readRes; + size_t size = *outSize; + + *outSize = 0; + *inStreamProcessed = 0; + + finishMode = LZMA_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (size >= rem) + { + size = (size_t)rem; + if (p->finishMode) + finishMode = LZMA_FINISH_END; + } + } + + readRes = SZ_OK; + + for (;;) + { + SizeT inCur; + SizeT outCur; + ELzmaStatus status; + SRes res; + + if (p->inPos == p->inLim && readRes == SZ_OK) + { + p->inPos = 0; + p->inLim = p->props.inBufSize_ST; + readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim); + } + + inCur = (SizeT)(p->inLim - p->inPos); + outCur = (SizeT)size; + + res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur, + p->inBuf + p->inPos, &inCur, finishMode, &status); + + p->inPos += inCur; + p->inProcessed += inCur; + *inStreamProcessed += inCur; + p->outProcessed += outCur; + *outSize += outCur; + size -= outCur; + data += outCur; + + if (res != 0) + return res; + + /* + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + return readRes; + + if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize) + return SZ_ERROR_DATA; + return readRes; + } + */ + + if (inCur == 0 && outCur == 0) + return readRes; + } +} + +#undef PRF +#undef PRF_STR +#undef PRF_STR_INT_2 diff --git a/libraries/lzma/C/Lzma2DecMt.h b/libraries/lzma/C/Lzma2DecMt.h new file mode 100644 index 0000000000..93a5cd59e6 --- /dev/null +++ b/libraries/lzma/C/Lzma2DecMt.h @@ -0,0 +1,81 @@ +/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread +2023-04-13 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_LZMA2_DEC_MT_H +#define ZIP7_INC_LZMA2_DEC_MT_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef struct +{ + size_t inBufSize_ST; + size_t outStep_ST; + + #ifndef Z7_ST + unsigned numThreads; + size_t inBufSize_MT; + size_t outBlockMax; + size_t inBlockMax; + #endif +} CLzma2DecMtProps; + +/* init to single-thread mode */ +void Lzma2DecMtProps_Init(CLzma2DecMtProps *p); + + +/* ---------- CLzma2DecMtHandle Interface ---------- */ + +/* Lzma2DecMt_ * functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + // SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef struct CLzma2DecMt CLzma2DecMt; +typedef CLzma2DecMt * CLzma2DecMtHandle; +// Z7_DECLARE_HANDLE(CLzma2DecMtHandle) + +CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid); +void Lzma2DecMt_Destroy(CLzma2DecMtHandle p); + +SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p, + Byte prop, + const CLzma2DecMtProps *props, + ISeqOutStreamPtr outStream, + const UInt64 *outDataSize, // NULL means undefined + int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished + // Byte *outBuf, size_t *outBufSize, + ISeqInStreamPtr inStream, + // const Byte *inData, size_t inDataSize, + + // out variables: + UInt64 *inProcessed, + int *isMT, /* out: (*isMT == 0), if single thread decoding was used */ + + // UInt64 *outProcessed, + ICompressProgressPtr progress); + + +/* ---------- Read from CLzma2DecMtHandle Interface ---------- */ + +SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp, + Byte prop, + const CLzma2DecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqInStreamPtr inStream); + +SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp, + Byte *data, size_t *outSize, + UInt64 *inStreamProcessed); + + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/Lzma2Enc.c b/libraries/lzma/C/Lzma2Enc.c new file mode 100644 index 0000000000..703e146b57 --- /dev/null +++ b/libraries/lzma/C/Lzma2Enc.c @@ -0,0 +1,805 @@ +/* Lzma2Enc.c -- LZMA2 Encoder +2023-04-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define Z7_ST */ + +#include "Lzma2Enc.h" + +#ifndef Z7_ST +#include "MtCoder.h" +#else +#define MTCODER_THREADS_MAX 1 +#endif + +#define LZMA2_CONTROL_LZMA (1 << 7) +#define LZMA2_CONTROL_COPY_NO_RESET 2 +#define LZMA2_CONTROL_COPY_RESET_DIC 1 +#define LZMA2_CONTROL_EOF 0 + +#define LZMA2_LCLP_MAX 4 + +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#define LZMA2_PACK_SIZE_MAX (1 << 16) +#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX +#define LZMA2_UNPACK_SIZE_MAX (1 << 21) +#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX + +#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16) + + +#define PRF(x) /* x */ + + +/* ---------- CLimitedSeqInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + ISeqInStreamPtr realStream; + UInt64 limit; + UInt64 processed; + int finished; +} CLimitedSeqInStream; + +static void LimitedSeqInStream_Init(CLimitedSeqInStream *p) +{ + p->limit = (UInt64)(Int64)-1; + p->processed = 0; + p->finished = 0; +} + +static SRes LimitedSeqInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLimitedSeqInStream) + size_t size2 = *size; + SRes res = SZ_OK; + + if (p->limit != (UInt64)(Int64)-1) + { + const UInt64 rem = p->limit - p->processed; + if (size2 > rem) + size2 = (size_t)rem; + } + if (size2 != 0) + { + res = ISeqInStream_Read(p->realStream, data, &size2); + p->finished = (size2 == 0 ? 1 : 0); + p->processed += size2; + } + *size = size2; + return res; +} + + +/* ---------- CLzma2EncInt ---------- */ + +typedef struct +{ + CLzmaEncHandle enc; + Byte propsAreSet; + Byte propsByte; + Byte needInitState; + Byte needInitProp; + UInt64 srcPos; +} CLzma2EncInt; + + +static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props) +{ + if (!p->propsAreSet) + { + SizeT propsSize = LZMA_PROPS_SIZE; + Byte propsEncoded[LZMA_PROPS_SIZE]; + RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)) + RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)) + p->propsByte = propsEncoded[0]; + p->propsAreSet = True; + } + return SZ_OK; +} + +static void Lzma2EncInt_InitBlock(CLzma2EncInt *p) +{ + p->srcPos = 0; + p->needInitState = True; + p->needInitProp = True; +} + + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p); +void LzmaEnc_Finish(CLzmaEncHandle p); +void LzmaEnc_SaveState(CLzmaEncHandle p); +void LzmaEnc_RestoreState(CLzmaEncHandle p); + +/* +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p); +*/ + +static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, + size_t *packSizeRes, ISeqOutStreamPtr outStream) +{ + size_t packSizeLimit = *packSizeRes; + size_t packSize = packSizeLimit; + UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX; + unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0); + BoolInt useCopyBlock; + SRes res; + + *packSizeRes = 0; + if (packSize < lzHeaderSize) + return SZ_ERROR_OUTPUT_EOF; + packSize -= lzHeaderSize; + + LzmaEnc_SaveState(p->enc); + res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState, + outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize); + + PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize)); + + if (unpackSize == 0) + return res; + + if (res == SZ_OK) + useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16)); + else + { + if (res != SZ_ERROR_OUTPUT_EOF) + return res; + res = SZ_OK; + useCopyBlock = True; + } + + if (useCopyBlock) + { + size_t destPos = 0; + PRF(printf("################# COPY ")); + + while (unpackSize > 0) + { + const UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; + if (packSizeLimit - destPos < u + 3) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET); + outBuf[destPos++] = (Byte)((u - 1) >> 8); + outBuf[destPos++] = (Byte)(u - 1); + memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u); + unpackSize -= u; + destPos += u; + p->srcPos += u; + + if (outStream) + { + *packSizeRes += destPos; + if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + destPos = 0; + } + else + *packSizeRes = destPos; + /* needInitState = True; */ + } + + LzmaEnc_RestoreState(p->enc); + return SZ_OK; + } + + { + size_t destPos = 0; + const UInt32 u = unpackSize - 1; + const UInt32 pm = (UInt32)(packSize - 1); + const unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0); + + PRF(printf(" ")); + + outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F)); + outBuf[destPos++] = (Byte)(u >> 8); + outBuf[destPos++] = (Byte)u; + outBuf[destPos++] = (Byte)(pm >> 8); + outBuf[destPos++] = (Byte)pm; + + if (p->needInitProp) + outBuf[destPos++] = p->propsByte; + + p->needInitProp = False; + p->needInitState = False; + destPos += packSize; + p->srcPos += unpackSize; + + if (outStream) + if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + + *packSizeRes = destPos; + return SZ_OK; + } +} + + +/* ---------- Lzma2 Props ---------- */ + +void Lzma2EncProps_Init(CLzma2EncProps *p) +{ + LzmaEncProps_Init(&p->lzmaProps); + p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO; + p->numBlockThreads_Reduced = -1; + p->numBlockThreads_Max = -1; + p->numTotalThreads = -1; +} + +void Lzma2EncProps_Normalize(CLzma2EncProps *p) +{ + UInt64 fileSize; + int t1, t1n, t2, t2r, t3; + { + CLzmaEncProps lzmaProps = p->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + t1n = lzmaProps.numThreads; + } + + t1 = p->lzmaProps.numThreads; + t2 = p->numBlockThreads_Max; + t3 = p->numTotalThreads; + + if (t2 > MTCODER_THREADS_MAX) + t2 = MTCODER_THREADS_MAX; + + if (t3 <= 0) + { + if (t2 <= 0) + t2 = 1; + t3 = t1n * t2; + } + else if (t2 <= 0) + { + t2 = t3 / t1n; + if (t2 == 0) + { + t1 = 1; + t2 = t3; + } + if (t2 > MTCODER_THREADS_MAX) + t2 = MTCODER_THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzmaProps.numThreads = t1; + + t2r = t2; + + fileSize = p->lzmaProps.reduceSize; + + if ( p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID + && p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO + && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) + p->lzmaProps.reduceSize = p->blockSize; + + LzmaEncProps_Normalize(&p->lzmaProps); + + p->lzmaProps.reduceSize = fileSize; + + t1 = p->lzmaProps.numThreads; + + if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID) + { + t2r = t2 = 1; + t3 = t1; + } + else if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO && t2 <= 1) + { + /* if there is no block multi-threading, we use SOLID block */ + p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID; + } + else + { + if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO) + { + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + const UInt32 dictSize = p->lzmaProps.dictSize; + UInt64 blockSize = (UInt64)dictSize << 2; + if (blockSize < kMinSize) blockSize = kMinSize; + if (blockSize > kMaxSize) blockSize = kMaxSize; + if (blockSize < dictSize) blockSize = dictSize; + blockSize += (kMinSize - 1); + blockSize &= ~(UInt64)(kMinSize - 1); + p->blockSize = blockSize; + } + + if (t2 > 1 && fileSize != (UInt64)(Int64)-1) + { + UInt64 numBlocks = fileSize / p->blockSize; + if (numBlocks * p->blockSize != fileSize) + numBlocks++; + if (numBlocks < (unsigned)t2) + { + t2r = (int)numBlocks; + if (t2r == 0) + t2r = 1; + t3 = t1 * t2r; + } + } + } + + p->numBlockThreads_Max = t2; + p->numBlockThreads_Reduced = t2r; + p->numTotalThreads = t3; +} + + +static SRes Progress(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize) +{ + return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; +} + + +/* ---------- Lzma2 ---------- */ + +struct CLzma2Enc +{ + Byte propEncoded; + CLzma2EncProps props; + UInt64 expectedDataSize; + + Byte *tempBufLzma; + + ISzAllocPtr alloc; + ISzAllocPtr allocBig; + + CLzma2EncInt coders[MTCODER_THREADS_MAX]; + + #ifndef Z7_ST + + ISeqOutStreamPtr outStream; + Byte *outBuf; + size_t outBuf_Rem; /* remainder in outBuf */ + + size_t outBufSize; /* size of allocated outBufs[i] */ + size_t outBufsDataSizes[MTCODER_BLOCKS_MAX]; + BoolInt mtCoder_WasConstructed; + CMtCoder mtCoder; + Byte *outBufs[MTCODER_BLOCKS_MAX]; + + #endif +}; + + + +CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc)); + if (!p) + return NULL; + Lzma2EncProps_Init(&p->props); + Lzma2EncProps_Normalize(&p->props); + p->expectedDataSize = (UInt64)(Int64)-1; + p->tempBufLzma = NULL; + p->alloc = alloc; + p->allocBig = allocBig; + { + unsigned i; + for (i = 0; i < MTCODER_THREADS_MAX; i++) + p->coders[i].enc = NULL; + } + + #ifndef Z7_ST + p->mtCoder_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTCODER_BLOCKS_MAX; i++) + p->outBufs[i] = NULL; + p->outBufSize = 0; + } + #endif + + return (CLzma2EncHandle)p; +} + + +#ifndef Z7_ST + +static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p) +{ + unsigned i; + for (i = 0; i < MTCODER_BLOCKS_MAX; i++) + if (p->outBufs[i]) + { + ISzAlloc_Free(p->alloc, p->outBufs[i]); + p->outBufs[i] = NULL; + } + p->outBufSize = 0; +} + +#endif + +// #define GET_CLzma2Enc_p CLzma2Enc *p = (CLzma2Enc *)(void *)p; + +void Lzma2Enc_Destroy(CLzma2EncHandle p) +{ + // GET_CLzma2Enc_p + unsigned i; + for (i = 0; i < MTCODER_THREADS_MAX; i++) + { + CLzma2EncInt *t = &p->coders[i]; + if (t->enc) + { + LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); + t->enc = NULL; + } + } + + + #ifndef Z7_ST + if (p->mtCoder_WasConstructed) + { + MtCoder_Destruct(&p->mtCoder); + p->mtCoder_WasConstructed = False; + } + Lzma2Enc_FreeOutBufs(p); + #endif + + ISzAlloc_Free(p->alloc, p->tempBufLzma); + p->tempBufLzma = NULL; + + ISzAlloc_Free(p->alloc, p); +} + + +SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props) +{ + // GET_CLzma2Enc_p + CLzmaEncProps lzmaProps = props->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX) + return SZ_ERROR_PARAM; + p->props = *props; + Lzma2EncProps_Normalize(&p->props); + return SZ_OK; +} + + +void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize) +{ + // GET_CLzma2Enc_p + p->expectedDataSize = expectedDataSiize; +} + + +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p) +{ + // GET_CLzma2Enc_p + unsigned i; + UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps); + for (i = 0; i < 40; i++) + if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i)) + break; + return (Byte)i; +} + + +static SRes Lzma2Enc_EncodeMt1( + CLzma2Enc *me, + CLzma2EncInt *p, + ISeqOutStreamPtr outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStreamPtr inStream, + const Byte *inData, size_t inDataSize, + int finished, + ICompressProgressPtr progress) +{ + UInt64 unpackTotal = 0; + UInt64 packTotal = 0; + size_t outLim = 0; + CLimitedSeqInStream limitedInStream; + + if (outBuf) + { + outLim = *outBufSize; + *outBufSize = 0; + } + + if (!p->enc) + { + p->propsAreSet = False; + p->enc = LzmaEnc_Create(me->alloc); + if (!p->enc) + return SZ_ERROR_MEM; + } + + limitedInStream.realStream = inStream; + if (inStream) + { + limitedInStream.vt.Read = LimitedSeqInStream_Read; + } + + if (!outBuf) + { + // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma + if (!me->tempBufLzma) + { + me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); + if (!me->tempBufLzma) + return SZ_ERROR_MEM; + } + } + + RINOK(Lzma2EncInt_InitStream(p, &me->props)) + + for (;;) + { + SRes res = SZ_OK; + SizeT inSizeCur = 0; + + Lzma2EncInt_InitBlock(p); + + LimitedSeqInStream_Init(&limitedInStream); + limitedInStream.limit = me->props.blockSize; + + if (inStream) + { + UInt64 expected = (UInt64)(Int64)-1; + // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize + if (me->expectedDataSize != (UInt64)(Int64)-1 + && me->expectedDataSize >= unpackTotal) + expected = me->expectedDataSize - unpackTotal; + if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID + && expected > me->props.blockSize) + expected = (size_t)me->props.blockSize; + + LzmaEnc_SetDataSize(p->enc, expected); + + RINOK(LzmaEnc_PrepareForLzma2(p->enc, + &limitedInStream.vt, + LZMA2_KEEP_WINDOW_SIZE, + me->alloc, + me->allocBig)) + } + else + { + inSizeCur = (SizeT)(inDataSize - (size_t)unpackTotal); + if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID + && inSizeCur > me->props.blockSize) + inSizeCur = (SizeT)(size_t)me->props.blockSize; + + // LzmaEnc_SetDataSize(p->enc, inSizeCur); + + RINOK(LzmaEnc_MemPrepare(p->enc, + inData + (size_t)unpackTotal, inSizeCur, + LZMA2_KEEP_WINDOW_SIZE, + me->alloc, + me->allocBig)) + } + + for (;;) + { + size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; + if (outBuf) + packSize = outLim - (size_t)packTotal; + + res = Lzma2EncInt_EncodeSubblock(p, + outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize, + outBuf ? NULL : outStream); + + if (res != SZ_OK) + break; + + packTotal += packSize; + if (outBuf) + *outBufSize = (size_t)packTotal; + + res = Progress(progress, unpackTotal + p->srcPos, packTotal); + if (res != SZ_OK) + break; + + /* + if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0) + break; + */ + + if (packSize == 0) + break; + } + + LzmaEnc_Finish(p->enc); + + unpackTotal += p->srcPos; + + RINOK(res) + + if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur)) + return SZ_ERROR_FAIL; + + if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize)) + { + if (finished) + { + if (outBuf) + { + const size_t destPos = *outBufSize; + if (destPos >= outLim) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos] = LZMA2_CONTROL_EOF; // 0 + *outBufSize = destPos + 1; + } + else + { + const Byte b = LZMA2_CONTROL_EOF; // 0; + if (ISeqOutStream_Write(outStream, &b, 1) != 1) + return SZ_ERROR_WRITE; + } + } + return SZ_OK; + } + } +} + + + +#ifndef Z7_ST + +static SRes Lzma2Enc_MtCallback_Code(void *p, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished) +{ + CLzma2Enc *me = (CLzma2Enc *)p; + size_t destSize = me->outBufSize; + SRes res; + CMtProgressThunk progressThunk; + + Byte *dest = me->outBufs[outBufIndex]; + + me->outBufsDataSizes[outBufIndex] = 0; + + if (!dest) + { + dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); + if (!dest) + return SZ_ERROR_MEM; + me->outBufs[outBufIndex] = dest; + } + + MtProgressThunk_CreateVTable(&progressThunk); + progressThunk.mtProgress = &me->mtCoder.mtProgress; + progressThunk.inSize = 0; + progressThunk.outSize = 0; + + res = Lzma2Enc_EncodeMt1(me, + &me->coders[coderIndex], + NULL, dest, &destSize, + NULL, src, srcSize, + finished, + &progressThunk.vt); + + me->outBufsDataSizes[outBufIndex] = destSize; + + return res; +} + + +static SRes Lzma2Enc_MtCallback_Write(void *p, unsigned outBufIndex) +{ + CLzma2Enc *me = (CLzma2Enc *)p; + size_t size = me->outBufsDataSizes[outBufIndex]; + const Byte *data = me->outBufs[outBufIndex]; + + if (me->outStream) + return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE; + + if (size > me->outBuf_Rem) + return SZ_ERROR_OUTPUT_EOF; + memcpy(me->outBuf, data, size); + me->outBuf_Rem -= size; + me->outBuf += size; + return SZ_OK; +} + +#endif + + + +SRes Lzma2Enc_Encode2(CLzma2EncHandle p, + ISeqOutStreamPtr outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStreamPtr inStream, + const Byte *inData, size_t inDataSize, + ICompressProgressPtr progress) +{ + // GET_CLzma2Enc_p + + if (inStream && inData) + return SZ_ERROR_PARAM; + + if (outStream && outBuf) + return SZ_ERROR_PARAM; + + { + unsigned i; + for (i = 0; i < MTCODER_THREADS_MAX; i++) + p->coders[i].propsAreSet = False; + } + + #ifndef Z7_ST + + if (p->props.numBlockThreads_Reduced > 1) + { + IMtCoderCallback2 vt; + + if (!p->mtCoder_WasConstructed) + { + p->mtCoder_WasConstructed = True; + MtCoder_Construct(&p->mtCoder); + } + + vt.Code = Lzma2Enc_MtCallback_Code; + vt.Write = Lzma2Enc_MtCallback_Write; + + p->outStream = outStream; + p->outBuf = NULL; + p->outBuf_Rem = 0; + if (!outStream) + { + p->outBuf = outBuf; + p->outBuf_Rem = *outBufSize; + *outBufSize = 0; + } + + p->mtCoder.allocBig = p->allocBig; + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.inData = inData; + p->mtCoder.inDataSize = inDataSize; + p->mtCoder.mtCallback = &vt; + p->mtCoder.mtCallbackObject = p; + + p->mtCoder.blockSize = (size_t)p->props.blockSize; + if (p->mtCoder.blockSize != p->props.blockSize) + return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ + + { + const size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16; + if (destBlockSize < p->mtCoder.blockSize) + return SZ_ERROR_PARAM; + if (p->outBufSize != destBlockSize) + Lzma2Enc_FreeOutBufs(p); + p->outBufSize = destBlockSize; + } + + p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max; + p->mtCoder.expectedDataSize = p->expectedDataSize; + + { + const SRes res = MtCoder_Code(&p->mtCoder); + if (!outStream) + *outBufSize = (size_t)(p->outBuf - outBuf); + return res; + } + } + + #endif + + + return Lzma2Enc_EncodeMt1(p, + &p->coders[0], + outStream, outBuf, outBufSize, + inStream, inData, inDataSize, + True, /* finished */ + progress); +} + +#undef PRF diff --git a/libraries/lzma/C/Lzma2Enc.h b/libraries/lzma/C/Lzma2Enc.h new file mode 100644 index 0000000000..cb25275c6b --- /dev/null +++ b/libraries/lzma/C/Lzma2Enc.h @@ -0,0 +1,57 @@ +/* Lzma2Enc.h -- LZMA2 Encoder +2023-04-13 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_LZMA2_ENC_H +#define ZIP7_INC_LZMA2_ENC_H + +#include "LzmaEnc.h" + +EXTERN_C_BEGIN + +#define LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO 0 +#define LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID ((UInt64)(Int64)-1) + +typedef struct +{ + CLzmaEncProps lzmaProps; + UInt64 blockSize; + int numBlockThreads_Reduced; + int numBlockThreads_Max; + int numTotalThreads; +} CLzma2EncProps; + +void Lzma2EncProps_Init(CLzma2EncProps *p); +void Lzma2EncProps_Normalize(CLzma2EncProps *p); + +/* ---------- CLzmaEnc2Handle Interface ---------- */ + +/* Lzma2Enc_* functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef struct CLzma2Enc CLzma2Enc; +typedef CLzma2Enc * CLzma2EncHandle; +// Z7_DECLARE_HANDLE(CLzma2EncHandle) + +CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig); +void Lzma2Enc_Destroy(CLzma2EncHandle p); +SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props); +void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize); +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p); +SRes Lzma2Enc_Encode2(CLzma2EncHandle p, + ISeqOutStreamPtr outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStreamPtr inStream, + const Byte *inData, size_t inDataSize, + ICompressProgressPtr progress); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/LzmaDec.c b/libraries/lzma/C/LzmaDec.c index d6742e5af8..69bb8bba9d 100644 --- a/libraries/lzma/C/LzmaDec.c +++ b/libraries/lzma/C/LzmaDec.c @@ -1,5 +1,5 @@ /* LzmaDec.c -- LZMA Decoder -2021-04-01 : Igor Pavlov : Public domain */ +2023-04-07 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -8,15 +8,15 @@ /* #include "CpuArch.h" */ #include "LzmaDec.h" -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) +// #define kNumTopBits 24 +#define kTopValue ((UInt32)1 << 24) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define RC_INIT_SIZE 5 -#ifndef _LZMA_DEC_OPT +#ifndef Z7_LZMA_DEC_OPT #define kNumMoveBits 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } @@ -25,14 +25,14 @@ #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ - { UPDATE_0(p); i = (i + i); A0; } else \ - { UPDATE_1(p); i = (i + i) + 1; A1; } + { UPDATE_0(p) i = (i + i); A0; } else \ + { UPDATE_1(p) i = (i + i) + 1; A1; } #define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); } #define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \ - { UPDATE_0(p + i); A0; } else \ - { UPDATE_1(p + i); A1; } + { UPDATE_0(p + i) A0; } else \ + { UPDATE_1(p + i) A1; } #define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; ) #define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; ) #define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; ) @@ -40,19 +40,19 @@ #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } -/* #define _LZMA_SIZE_OPT */ +/* #define Z7_LZMA_SIZE_OPT */ -#ifdef _LZMA_SIZE_OPT +#ifdef Z7_LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i) \ + TREE_GET_BIT(probs, i) \ + TREE_GET_BIT(probs, i) \ + TREE_GET_BIT(probs, i) \ + TREE_GET_BIT(probs, i) \ + TREE_GET_BIT(probs, i) \ i -= 0x40; } #endif @@ -64,25 +64,25 @@ probLit = prob + (offs + bit + symbol); \ GET_BIT2(probLit, symbol, offs ^= bit; , ;) -#endif // _LZMA_DEC_OPT +#endif // Z7_LZMA_DEC_OPT #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_INPUT_EOF; range <<= 8; code = (code << 8) | (*buf++); } -#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ - { UPDATE_0_CHECK; i = (i + i); A0; } else \ - { UPDATE_1_CHECK; i = (i + i) + 1; A1; } + { UPDATE_0_CHECK i = (i + i); A0; } else \ + { UPDATE_1_CHECK i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \ - { UPDATE_0_CHECK; i += m; m += m; } else \ - { UPDATE_1_CHECK; m += m; i += m; } + { UPDATE_0_CHECK i += m; m += m; } else \ + { UPDATE_1_CHECK m += m; i += m; } #define kNumPosBitsMax 4 @@ -224,14 +224,14 @@ LZMA_DECODE_REAL() */ -#ifdef _LZMA_DEC_OPT +#ifdef Z7_LZMA_DEC_OPT -int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit); +int Z7_FASTCALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit); #else static -int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +int Z7_FASTCALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = GET_PROBS; unsigned state = (unsigned)p->state; @@ -263,7 +263,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit IF_BIT_0(prob) { unsigned symbol; - UPDATE_0(prob); + UPDATE_0(prob) prob = probs + Literal; if (processedPos != 0 || checkDicSize != 0) prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc); @@ -273,7 +273,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit { state -= (state < 4) ? state : 3; symbol = 1; - #ifdef _LZMA_SIZE_OPT + #ifdef Z7_LZMA_SIZE_OPT do { NORMAL_LITER_DEC } while (symbol < 0x100); #else NORMAL_LITER_DEC @@ -292,7 +292,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit unsigned offs = 0x100; state -= (state < 10) ? 3 : 6; symbol = 1; - #ifdef _LZMA_SIZE_OPT + #ifdef Z7_LZMA_SIZE_OPT do { unsigned bit; @@ -321,25 +321,25 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit } { - UPDATE_1(prob); + UPDATE_1(prob) prob = probs + IsRep + state; IF_BIT_0(prob) { - UPDATE_0(prob); + UPDATE_0(prob) state += kNumStates; prob = probs + LenCoder; } else { - UPDATE_1(prob); + UPDATE_1(prob) prob = probs + IsRepG0 + state; IF_BIT_0(prob) { - UPDATE_0(prob); + UPDATE_0(prob) prob = probs + IsRep0Long + COMBINED_PS_STATE; IF_BIT_0(prob) { - UPDATE_0(prob); + UPDATE_0(prob) // that case was checked before with kBadRepCode // if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; } @@ -353,30 +353,30 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit state = state < kNumLitStates ? 9 : 11; continue; } - UPDATE_1(prob); + UPDATE_1(prob) } else { UInt32 distance; - UPDATE_1(prob); + UPDATE_1(prob) prob = probs + IsRepG1 + state; IF_BIT_0(prob) { - UPDATE_0(prob); + UPDATE_0(prob) distance = rep1; } else { - UPDATE_1(prob); + UPDATE_1(prob) prob = probs + IsRepG2 + state; IF_BIT_0(prob) { - UPDATE_0(prob); + UPDATE_0(prob) distance = rep2; } else { - UPDATE_1(prob); + UPDATE_1(prob) distance = rep3; rep3 = rep2; } @@ -389,37 +389,37 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit prob = probs + RepLenCoder; } - #ifdef _LZMA_SIZE_OPT + #ifdef Z7_LZMA_SIZE_OPT { unsigned lim, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { - UPDATE_0(probLen); + UPDATE_0(probLen) probLen = prob + LenLow + GET_LEN_STATE; offset = 0; lim = (1 << kLenNumLowBits); } else { - UPDATE_1(probLen); + UPDATE_1(probLen) probLen = prob + LenChoice2; IF_BIT_0(probLen) { - UPDATE_0(probLen); + UPDATE_0(probLen) probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); offset = kLenNumLowSymbols; lim = (1 << kLenNumLowBits); } else { - UPDATE_1(probLen); + UPDATE_1(probLen) probLen = prob + LenHigh; offset = kLenNumLowSymbols * 2; lim = (1 << kLenNumHighBits); } } - TREE_DECODE(probLen, lim, len); + TREE_DECODE(probLen, lim, len) len += offset; } #else @@ -427,32 +427,32 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { - UPDATE_0(probLen); + UPDATE_0(probLen) probLen = prob + LenLow + GET_LEN_STATE; len = 1; - TREE_GET_BIT(probLen, len); - TREE_GET_BIT(probLen, len); - TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len) + TREE_GET_BIT(probLen, len) + TREE_GET_BIT(probLen, len) len -= 8; } else { - UPDATE_1(probLen); + UPDATE_1(probLen) probLen = prob + LenChoice2; IF_BIT_0(probLen) { - UPDATE_0(probLen); + UPDATE_0(probLen) probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); len = 1; - TREE_GET_BIT(probLen, len); - TREE_GET_BIT(probLen, len); - TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len) + TREE_GET_BIT(probLen, len) + TREE_GET_BIT(probLen, len) } else { - UPDATE_1(probLen); + UPDATE_1(probLen) probLen = prob + LenHigh; - TREE_DECODE(probLen, (1 << kLenNumHighBits), len); + TREE_DECODE(probLen, (1 << kLenNumHighBits), len) len += kLenNumLowSymbols * 2; } } @@ -464,7 +464,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); - TREE_6_DECODE(prob, distance); + TREE_6_DECODE(prob, distance) if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; @@ -479,7 +479,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit distance++; do { - REV_BIT_VAR(prob, distance, m); + REV_BIT_VAR(prob, distance, m) } while (--numDirectBits); distance -= m; @@ -514,10 +514,10 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit distance <<= kNumAlignBits; { unsigned i = 1; - REV_BIT_CONST(prob, i, 1); - REV_BIT_CONST(prob, i, 2); - REV_BIT_CONST(prob, i, 4); - REV_BIT_LAST (prob, i, 8); + REV_BIT_CONST(prob, i, 1) + REV_BIT_CONST(prob, i, 2) + REV_BIT_CONST(prob, i, 4) + REV_BIT_LAST (prob, i, 8) distance |= i; } if (distance == (UInt32)0xFFFFFFFF) @@ -592,7 +592,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit } while (dicPos < limit && buf < bufLimit); - NORMALIZE; + NORMALIZE p->buf = buf; p->range = range; @@ -613,7 +613,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit -static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +static void Z7_FASTCALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { unsigned len = (unsigned)p->remainLen; if (len == 0 /* || len >= kMatchSpecLenStart */) @@ -683,7 +683,7 @@ and we support the following state of (p->checkDicSize): (p->checkDicSize == p->prop.dicSize) */ -static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +static int Z7_FASTCALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { if (p->checkDicSize == 0) { @@ -767,54 +767,54 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byt else { unsigned len; - UPDATE_1_CHECK; + UPDATE_1_CHECK prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { - UPDATE_0_CHECK; + UPDATE_0_CHECK state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { - UPDATE_1_CHECK; + UPDATE_1_CHECK res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { - UPDATE_0_CHECK; + UPDATE_0_CHECK prob = probs + IsRep0Long + COMBINED_PS_STATE; IF_BIT_0_CHECK(prob) { - UPDATE_0_CHECK; + UPDATE_0_CHECK break; } else { - UPDATE_1_CHECK; + UPDATE_1_CHECK } } else { - UPDATE_1_CHECK; + UPDATE_1_CHECK prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { - UPDATE_0_CHECK; + UPDATE_0_CHECK } else { - UPDATE_1_CHECK; + UPDATE_1_CHECK prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { - UPDATE_0_CHECK; + UPDATE_0_CHECK } else { - UPDATE_1_CHECK; + UPDATE_1_CHECK } } } @@ -826,31 +826,31 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byt const CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { - UPDATE_0_CHECK; + UPDATE_0_CHECK probLen = prob + LenLow + GET_LEN_STATE; offset = 0; limit = 1 << kLenNumLowBits; } else { - UPDATE_1_CHECK; + UPDATE_1_CHECK probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { - UPDATE_0_CHECK; + UPDATE_0_CHECK probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumLowBits; } else { - UPDATE_1_CHECK; + UPDATE_1_CHECK probLen = prob + LenHigh; offset = kLenNumLowSymbols * 2; limit = 1 << kLenNumHighBits; } } - TREE_DECODE_CHECK(probLen, limit, len); + TREE_DECODE_CHECK(probLen, limit, len) len += offset; } @@ -860,7 +860,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byt prob = probs + PosSlot + ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); - TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot) if (posSlot >= kStartPosModelIndex) { unsigned numDirectBits = ((posSlot >> 1) - 1); @@ -888,7 +888,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byt unsigned m = 1; do { - REV_BIT_CHECK(prob, i, m); + REV_BIT_CHECK(prob, i, m) } while (--numDirectBits); } @@ -897,7 +897,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byt } break; } - NORMALIZE_CHECK; + NORMALIZE_CHECK *bufOut = buf; return res; @@ -943,7 +943,7 @@ When the decoder lookahead, and the lookahead symbol is not end_marker, we have */ -#define RETURN__NOT_FINISHED__FOR_FINISH \ +#define RETURN_NOT_FINISHED_FOR_FINISH \ *status = LZMA_STATUS_NOT_FINISHED; \ return SZ_ERROR_DATA; // for strict mode // return SZ_OK; // for relaxed mode @@ -1029,7 +1029,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr } if (p->remainLen != 0) { - RETURN__NOT_FINISHED__FOR_FINISH; + RETURN_NOT_FINISHED_FOR_FINISH } checkEndMarkNow = 1; } @@ -1072,7 +1072,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr for (i = 0; i < (unsigned)dummyProcessed; i++) p->tempBuf[i] = src[i]; // p->remainLen = kMatchSpecLen_Error_Data; - RETURN__NOT_FINISHED__FOR_FINISH; + RETURN_NOT_FINISHED_FOR_FINISH } bufLimit = src; @@ -1150,7 +1150,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr (*srcLen) += (unsigned)dummyProcessed - p->tempBufSize; p->tempBufSize = (unsigned)dummyProcessed; // p->remainLen = kMatchSpecLen_Error_Data; - RETURN__NOT_FINISHED__FOR_FINISH; + RETURN_NOT_FINISHED_FOR_FINISH } } @@ -1299,8 +1299,8 @@ static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAl SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) { CLzmaProps propNew; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + RINOK(LzmaProps_Decode(&propNew, props, propsSize)) + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)) p->prop = propNew; return SZ_OK; } @@ -1309,14 +1309,14 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll { CLzmaProps propNew; SizeT dicBufSize; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + RINOK(LzmaProps_Decode(&propNew, props, propsSize)) + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)) { UInt32 dictSize = propNew.dicSize; SizeT mask = ((UInt32)1 << 12) - 1; if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1; - else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;; + else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1; dicBufSize = ((SizeT)dictSize + mask) & ~mask; if (dicBufSize < dictSize) dicBufSize = dictSize; @@ -1348,8 +1348,8 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, *status = LZMA_STATUS_NOT_SPECIFIED; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; - LzmaDec_Construct(&p); - RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)); + LzmaDec_CONSTRUCT(&p) + RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)) p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); diff --git a/libraries/lzma/C/LzmaDec.h b/libraries/lzma/C/LzmaDec.h index 6f1296250c..b0ce28fa02 100644 --- a/libraries/lzma/C/LzmaDec.h +++ b/libraries/lzma/C/LzmaDec.h @@ -1,19 +1,19 @@ /* LzmaDec.h -- LZMA Decoder -2020-03-19 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __LZMA_DEC_H -#define __LZMA_DEC_H +#ifndef ZIP7_INC_LZMA_DEC_H +#define ZIP7_INC_LZMA_DEC_H #include "7zTypes.h" EXTERN_C_BEGIN -/* #define _LZMA_PROB32 */ -/* _LZMA_PROB32 can increase the speed on some CPUs, +/* #define Z7_LZMA_PROB32 */ +/* Z7_LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ typedef -#ifdef _LZMA_PROB32 +#ifdef Z7_LZMA_PROB32 UInt32 #else UInt16 @@ -25,7 +25,7 @@ typedef #define LZMA_PROPS_SIZE 5 -typedef struct _CLzmaProps +typedef struct { Byte lc; Byte lp; @@ -73,7 +73,8 @@ typedef struct Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; -#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; } +#define LzmaDec_CONSTRUCT(p) { (p)->dic = NULL; (p)->probs = NULL; } +#define LzmaDec_Construct(p) LzmaDec_CONSTRUCT(p) void LzmaDec_Init(CLzmaDec *p); diff --git a/libraries/lzma/C/LzmaEnc.c b/libraries/lzma/C/LzmaEnc.c index b04a7b7b71..6d13cac8ce 100644 --- a/libraries/lzma/C/LzmaEnc.c +++ b/libraries/lzma/C/LzmaEnc.c @@ -1,5 +1,5 @@ /* LzmaEnc.c -- LZMA Encoder -2021-11-18: Igor Pavlov : Public domain */ +2023-04-13: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -16,22 +16,22 @@ #include "LzmaEnc.h" #include "LzFind.h" -#ifndef _7ZIP_ST +#ifndef Z7_ST #include "LzFindMt.h" #endif /* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */ -SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); -SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, +SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); -SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); -const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); -void LzmaEnc_Finish(CLzmaEncHandle pp); -void LzmaEnc_SaveState(CLzmaEncHandle pp); -void LzmaEnc_RestoreState(CLzmaEncHandle pp); +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p); +void LzmaEnc_Finish(CLzmaEncHandle p); +void LzmaEnc_SaveState(CLzmaEncHandle p); +void LzmaEnc_RestoreState(CLzmaEncHandle p); #ifdef SHOW_STAT static unsigned g_STAT_OFFSET = 0; @@ -40,8 +40,8 @@ static unsigned g_STAT_OFFSET = 0; /* for good normalization speed we still reserve 256 MB before 4 GB range */ #define kLzmaMaxHistorySize ((UInt32)15 << 28) -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) +// #define kNumTopBits 24 +#define kTopValue ((UInt32)1 << 24) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) @@ -60,6 +60,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) p->dictSize = p->mc = 0; p->reduceSize = (UInt64)(Int64)-1; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->numHashOutBits = 0; p->writeEndMark = 0; p->affinity = 0; } @@ -99,7 +100,7 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (p->numThreads < 0) p->numThreads = - #ifndef _7ZIP_ST + #ifndef Z7_ST ((p->btMode && p->algo) ? 2 : 1); #else 1; @@ -293,7 +294,7 @@ typedef struct #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) typedef -#ifdef _LZMA_PROB32 +#ifdef Z7_LZMA_PROB32 UInt32 #else UInt16 @@ -350,7 +351,7 @@ typedef struct Byte *buf; Byte *bufLim; Byte *bufBase; - ISeqOutStream *outStream; + ISeqOutStreamPtr outStream; UInt64 processed; SRes res; } CRangeEnc; @@ -383,7 +384,7 @@ typedef struct typedef UInt32 CProbPrice; -typedef struct +struct CLzmaEnc { void *matchFinderObj; IMatchFinder2 matchFinder; @@ -426,7 +427,7 @@ typedef struct UInt32 dictSize; SRes result; - #ifndef _7ZIP_ST + #ifndef Z7_ST BoolInt mtMode; // begin of CMatchFinderMt is used in LZ thread CMatchFinderMt matchFinderMt; @@ -439,7 +440,7 @@ typedef struct // we suppose that we have 8-bytes alignment after CMatchFinder - #ifndef _7ZIP_ST + #ifndef Z7_ST Byte pad[128]; #endif @@ -479,77 +480,59 @@ typedef struct CSaveState saveState; // BoolInt mf_Failure; - #ifndef _7ZIP_ST + #ifndef Z7_ST Byte pad2[128]; #endif -} CLzmaEnc; +}; #define MFB (p->matchFinderBase) /* -#ifndef _7ZIP_ST +#ifndef Z7_ST #define MFB (p->matchFinderMt.MatchFinder) #endif */ -#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr)); - -void LzmaEnc_SaveState(CLzmaEncHandle pp) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - CSaveState *dest = &p->saveState; - - dest->state = p->state; - - dest->lenProbs = p->lenProbs; - dest->repLenProbs = p->repLenProbs; - - COPY_ARR(dest, p, reps); - - COPY_ARR(dest, p, posAlignEncoder); - COPY_ARR(dest, p, isRep); - COPY_ARR(dest, p, isRepG0); - COPY_ARR(dest, p, isRepG1); - COPY_ARR(dest, p, isRepG2); - COPY_ARR(dest, p, isMatch); - COPY_ARR(dest, p, isRep0Long); - COPY_ARR(dest, p, posSlotEncoder); - COPY_ARR(dest, p, posEncoders); - - memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb)); +// #define GET_CLzmaEnc_p CLzmaEnc *p = (CLzmaEnc*)(void *)p; +// #define GET_const_CLzmaEnc_p const CLzmaEnc *p = (const CLzmaEnc*)(const void *)p; + +#define COPY_ARR(dest, src, arr) memcpy((dest)->arr, (src)->arr, sizeof((src)->arr)); + +#define COPY_LZMA_ENC_STATE(d, s, p) \ + (d)->state = (s)->state; \ + COPY_ARR(d, s, reps) \ + COPY_ARR(d, s, posAlignEncoder) \ + COPY_ARR(d, s, isRep) \ + COPY_ARR(d, s, isRepG0) \ + COPY_ARR(d, s, isRepG1) \ + COPY_ARR(d, s, isRepG2) \ + COPY_ARR(d, s, isMatch) \ + COPY_ARR(d, s, isRep0Long) \ + COPY_ARR(d, s, posSlotEncoder) \ + COPY_ARR(d, s, posEncoders) \ + (d)->lenProbs = (s)->lenProbs; \ + (d)->repLenProbs = (s)->repLenProbs; \ + memcpy((d)->litProbs, (s)->litProbs, ((UInt32)0x300 << (p)->lclp) * sizeof(CLzmaProb)); + +void LzmaEnc_SaveState(CLzmaEncHandle p) +{ + // GET_CLzmaEnc_p + CSaveState *v = &p->saveState; + COPY_LZMA_ENC_STATE(v, p, p) } - -void LzmaEnc_RestoreState(CLzmaEncHandle pp) +void LzmaEnc_RestoreState(CLzmaEncHandle p) { - CLzmaEnc *dest = (CLzmaEnc *)pp; - const CSaveState *p = &dest->saveState; - - dest->state = p->state; - - dest->lenProbs = p->lenProbs; - dest->repLenProbs = p->repLenProbs; - - COPY_ARR(dest, p, reps); - - COPY_ARR(dest, p, posAlignEncoder); - COPY_ARR(dest, p, isRep); - COPY_ARR(dest, p, isRepG0); - COPY_ARR(dest, p, isRepG1); - COPY_ARR(dest, p, isRepG2); - COPY_ARR(dest, p, isMatch); - COPY_ARR(dest, p, isRep0Long); - COPY_ARR(dest, p, posSlotEncoder); - COPY_ARR(dest, p, posEncoders); - - memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb)); + // GET_CLzmaEnc_p + const CSaveState *v = &p->saveState; + COPY_LZMA_ENC_STATE(p, v, p) } - -SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +Z7_NO_INLINE +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props2) { - CLzmaEnc *p = (CLzmaEnc *)pp; + // GET_CLzmaEnc_p CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); @@ -585,6 +568,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) p->fastMode = (props.algo == 0); // p->_maxMode = True; MFB.btMode = (Byte)(props.btMode ? 1 : 0); + // MFB.btMode = (Byte)(props.btMode); { unsigned numHashBytes = 4; if (props.btMode) @@ -595,13 +579,15 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) if (props.numHashBytes >= 5) numHashBytes = 5; MFB.numHashBytes = numHashBytes; + // MFB.numHashBytes_Min = 2; + MFB.numHashOutBits = (Byte)props.numHashOutBits; } MFB.cutValue = props.mc; p->writeEndMark = (BoolInt)props.writeEndMark; - #ifndef _7ZIP_ST + #ifndef Z7_ST /* if (newMultiThread != _multiThread) { @@ -618,9 +604,9 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) } -void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) +void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize) { - CLzmaEnc *p = (CLzmaEnc *)pp; + // GET_CLzmaEnc_p MFB.expectedDataSize = expectedDataSiize; } @@ -684,7 +670,7 @@ static void RangeEnc_Init(CRangeEnc *p) p->res = SZ_OK; } -MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) +Z7_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) { const size_t num = (size_t)(p->buf - p->bufBase); if (p->res == SZ_OK) @@ -696,7 +682,7 @@ MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) p->buf = p->bufBase; } -MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +Z7_NO_INLINE static void Z7_FASTCALL RangeEnc_ShiftLow(CRangeEnc *p) { UInt32 low = (UInt32)p->low; unsigned high = (unsigned)(p->low >> 32); @@ -741,9 +727,9 @@ static void RangeEnc_FlushData(CRangeEnc *p) ttt = *(prob); \ newBound = (range >> kNumBitModelTotalBits) * ttt; -// #define _LZMA_ENC_USE_BRANCH +// #define Z7_LZMA_ENC_USE_BRANCH -#ifdef _LZMA_ENC_USE_BRANCH +#ifdef Z7_LZMA_ENC_USE_BRANCH #define RC_BIT(p, prob, bit) { \ RC_BIT_PRE(p, prob) \ @@ -811,7 +797,7 @@ static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym) CLzmaProb *prob = probs + (sym >> 8); UInt32 bit = (sym >> 7) & 1; sym <<= 1; - RC_BIT(p, prob, bit); + RC_BIT(p, prob, bit) } while (sym < 0x10000); p->range = range; @@ -833,7 +819,7 @@ static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UIn bit = (sym >> 7) & 1; sym <<= 1; offs &= ~(matchByte ^ sym); - RC_BIT(p, prob, bit); + RC_BIT(p, prob, bit) } while (sym < 0x10000); p->range = range; @@ -867,10 +853,10 @@ static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices) #define GET_PRICE(prob, bit) \ - p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits] #define GET_PRICEa(prob, bit) \ - ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits] #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] @@ -921,7 +907,7 @@ static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBi unsigned bit = sym & 1; // RangeEnc_EncodeBit(rc, probs + m, bit); sym >>= 1; - RC_BIT(rc, probs + m, bit); + RC_BIT(rc, probs + m, bit) m = (m << 1) | bit; } while (--numBits); @@ -944,15 +930,15 @@ static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posS UInt32 range, ttt, newBound; CLzmaProb *probs = p->low; range = rc->range; - RC_BIT_PRE(rc, probs); + RC_BIT_PRE(rc, probs) if (sym >= kLenNumLowSymbols) { - RC_BIT_1(rc, probs); + RC_BIT_1(rc, probs) probs += kLenNumLowSymbols; - RC_BIT_PRE(rc, probs); + RC_BIT_PRE(rc, probs) if (sym >= kLenNumLowSymbols * 2) { - RC_BIT_1(rc, probs); + RC_BIT_1(rc, probs) rc->range = range; // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2); LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2); @@ -965,11 +951,11 @@ static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posS { unsigned m; unsigned bit; - RC_BIT_0(rc, probs); + RC_BIT_0(rc, probs) probs += (posState << (1 + kLenNumLowBits)); - bit = (sym >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit; - bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit; - bit = sym & 1; RC_BIT(rc, probs + m, bit); + bit = (sym >> 2) ; RC_BIT(rc, probs + 1, bit) m = (1 << 1) + bit; + bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit) m = (m << 1) + bit; + bit = sym & 1; RC_BIT(rc, probs + m, bit) rc->range = range; } } @@ -990,7 +976,7 @@ static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *price } -MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables( +Z7_NO_INLINE static void Z7_FASTCALL LenPriceEnc_UpdateTables( CLenPriceEnc *p, unsigned numPosStates, const CLenEnc *enc, @@ -1152,7 +1138,7 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) + GET_PRICE_1(p->isRep[state]) \ + GET_PRICE_0(p->isRepG0[state]) -MY_FORCE_INLINE +Z7_FORCE_INLINE static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState) { UInt32 price; @@ -1331,7 +1317,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } - MakeAs_Lit(&p->opt[1]); + MakeAs_Lit(&p->opt[1]) matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); @@ -1343,7 +1329,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; - MakeAs_ShortRep(&p->opt[1]); + MakeAs_ShortRep(&p->opt[1]) } if (last < 2) { @@ -1410,7 +1396,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) else { unsigned slot; - GetPosSlot2(dist, slot); + GetPosSlot2(dist, slot) price += p->alignPrices[dist & kAlignMask]; price += p->posSlotPrices[lenToPosState][slot]; } @@ -1486,7 +1472,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) unsigned delta = best - cur; if (delta != 0) { - MOVE_POS(p, delta); + MOVE_POS(p, delta) } } cur = best; @@ -1633,7 +1619,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) { nextOpt->price = litPrice; nextOpt->len = 1; - MakeAs_Lit(nextOpt); + MakeAs_Lit(nextOpt) nextIsLit = True; } } @@ -1667,7 +1653,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) { nextOpt->price = shortRepPrice; nextOpt->len = 1; - MakeAs_ShortRep(nextOpt); + MakeAs_ShortRep(nextOpt) nextIsLit = False; } } @@ -1871,7 +1857,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) dist = MATCHES[(size_t)offs + 1]; // if (dist >= kNumFullDistances) - GetPosSlot2(dist, posSlot); + GetPosSlot2(dist, posSlot) for (len = /*2*/ startLen; ; len++) { @@ -1962,7 +1948,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) break; dist = MATCHES[(size_t)offs + 1]; // if (dist >= kNumFullDistances) - GetPosSlot2(dist, posSlot); + GetPosSlot2(dist, posSlot) } } } @@ -2138,7 +2124,7 @@ static void WriteEndMarker(CLzmaEnc *p, unsigned posState) { UInt32 ttt, newBound; RC_BIT_PRE(p, probs + m) - RC_BIT_1(&p->rc, probs + m); + RC_BIT_1(&p->rc, probs + m) m = (m << 1) + 1; } while (m < (1 << kNumPosSlotBits)); @@ -2163,7 +2149,7 @@ static void WriteEndMarker(CLzmaEnc *p, unsigned posState) { UInt32 ttt, newBound; RC_BIT_PRE(p, probs + m) - RC_BIT_1(&p->rc, probs + m); + RC_BIT_1(&p->rc, probs + m) m = (m << 1) + 1; } while (m < kAlignTableSize); @@ -2179,7 +2165,7 @@ static SRes CheckErrors(CLzmaEnc *p) if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; - #ifndef _7ZIP_ST + #ifndef Z7_ST if ( // p->mf_Failure || (p->mtMode && @@ -2187,7 +2173,7 @@ static SRes CheckErrors(CLzmaEnc *p) p->matchFinderMt.failure_LZ_BT)) ) { - p->result = MY_HRES_ERROR__INTERNAL_ERROR; + p->result = MY_HRES_ERROR_INTERNAL_ERROR; // printf("\nCheckErrors p->matchFinderMt.failureLZ\n"); } #endif @@ -2201,7 +2187,7 @@ static SRes CheckErrors(CLzmaEnc *p) } -MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +Z7_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; @@ -2213,7 +2199,7 @@ MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos) } -MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p) +Z7_NO_INLINE static void FillAlignPrices(CLzmaEnc *p) { unsigned i; const CProbPrice *ProbPrices = p->ProbPrices; @@ -2237,7 +2223,7 @@ MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p) } -MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p) +Z7_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p) { // int y; for (y = 0; y < 100; y++) { @@ -2337,7 +2323,7 @@ static void LzmaEnc_Construct(CLzmaEnc *p) RangeEnc_Construct(&p->rc); MatchFinder_Construct(&MFB); - #ifndef _7ZIP_ST + #ifndef Z7_ST p->matchFinderMt.MatchFinder = &MFB; MatchFinderMt_Construct(&p->matchFinderMt); #endif @@ -2345,7 +2331,7 @@ static void LzmaEnc_Construct(CLzmaEnc *p) { CLzmaEncProps props; LzmaEncProps_Init(&props); - LzmaEnc_SetProps(p, &props); + LzmaEnc_SetProps((CLzmaEncHandle)(void *)p, &props); } #ifndef LZMA_LOG_BSR @@ -2376,7 +2362,7 @@ static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) { - #ifndef _7ZIP_ST + #ifndef Z7_ST MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif @@ -2387,21 +2373,22 @@ static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBi void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig) { - LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + // GET_CLzmaEnc_p + LzmaEnc_Destruct(p, alloc, allocBig); ISzAlloc_Free(alloc, p); } -MY_NO_INLINE +Z7_NO_INLINE static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->needInit) { - #ifndef _7ZIP_ST + #ifndef Z7_ST if (p->mtMode) { - RINOK(MatchFinderMt_InitMt(&p->matchFinderMt)); + RINOK(MatchFinderMt_InitMt(&p->matchFinderMt)) } #endif p->matchFinder.Init(p->matchFinderObj); @@ -2410,7 +2397,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa if (p->finished) return p->result; - RINOK(CheckErrors(p)); + RINOK(CheckErrors(p)) nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; @@ -2473,7 +2460,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa const Byte *data; unsigned state; - RC_BIT_0(&p->rc, probs); + RC_BIT_0(&p->rc, probs) p->rc.range = range; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; probs = LIT_PROBS(nowPos32, *(data - 1)); @@ -2487,53 +2474,53 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa } else { - RC_BIT_1(&p->rc, probs); + RC_BIT_1(&p->rc, probs) probs = &p->isRep[p->state]; RC_BIT_PRE(&p->rc, probs) if (dist < LZMA_NUM_REPS) { - RC_BIT_1(&p->rc, probs); + RC_BIT_1(&p->rc, probs) probs = &p->isRepG0[p->state]; RC_BIT_PRE(&p->rc, probs) if (dist == 0) { - RC_BIT_0(&p->rc, probs); + RC_BIT_0(&p->rc, probs) probs = &p->isRep0Long[p->state][posState]; RC_BIT_PRE(&p->rc, probs) if (len != 1) { - RC_BIT_1_BASE(&p->rc, probs); + RC_BIT_1_BASE(&p->rc, probs) } else { - RC_BIT_0_BASE(&p->rc, probs); + RC_BIT_0_BASE(&p->rc, probs) p->state = kShortRepNextStates[p->state]; } } else { - RC_BIT_1(&p->rc, probs); + RC_BIT_1(&p->rc, probs) probs = &p->isRepG1[p->state]; RC_BIT_PRE(&p->rc, probs) if (dist == 1) { - RC_BIT_0_BASE(&p->rc, probs); + RC_BIT_0_BASE(&p->rc, probs) dist = p->reps[1]; } else { - RC_BIT_1(&p->rc, probs); + RC_BIT_1(&p->rc, probs) probs = &p->isRepG2[p->state]; RC_BIT_PRE(&p->rc, probs) if (dist == 2) { - RC_BIT_0_BASE(&p->rc, probs); + RC_BIT_0_BASE(&p->rc, probs) dist = p->reps[2]; } else { - RC_BIT_1_BASE(&p->rc, probs); + RC_BIT_1_BASE(&p->rc, probs) dist = p->reps[3]; p->reps[3] = p->reps[2]; } @@ -2557,7 +2544,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa else { unsigned posSlot; - RC_BIT_0(&p->rc, probs); + RC_BIT_0(&p->rc, probs) p->rc.range = range; p->state = kMatchNextStates[p->state]; @@ -2571,7 +2558,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa p->reps[0] = dist + 1; p->matchPriceCount++; - GetPosSlot(dist, posSlot); + GetPosSlot(dist, posSlot) // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot); { UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits); @@ -2582,7 +2569,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa CLzmaProb *prob = probs + (sym >> kNumPosSlotBits); UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1; sym <<= 1; - RC_BIT(&p->rc, prob, bit); + RC_BIT(&p->rc, prob, bit) } while (sym < (1 << kNumPosSlotBits * 2)); p->rc.range = range; @@ -2626,10 +2613,10 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa { unsigned m = 1; unsigned bit; - bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; - bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; - bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; - bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit) m = (m << 1) + bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit) m = (m << 1) + bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit) m = (m << 1) + bit; + bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit) p->rc.range = range; // p->alignPriceCount++; } @@ -2704,7 +2691,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; - #ifndef _7ZIP_ST + #ifndef Z7_ST p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0)); #endif @@ -2748,15 +2735,14 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, (numFastBytes + LZMA_MATCH_LEN_MAX + 1) */ - #ifndef _7ZIP_ST + #ifndef Z7_ST if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */ - , allocBig)); + , allocBig)) p->matchFinderObj = &p->matchFinderMt; - MFB.bigHash = (Byte)( - (p->dictSize > kBigHashDicLimit && MFB.hashMask >= 0xFFFFFF) ? 1 : 0); + MFB.bigHash = (Byte)(MFB.hashMask >= 0xFFFFFF ? 1 : 0); MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else @@ -2872,59 +2858,53 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr p->finished = False; p->result = SZ_OK; - RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + p->nowPos64 = 0; + p->needInit = 1; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); - p->nowPos64 = 0; return SZ_OK; } -static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, +static SRes LzmaEnc_Prepare(CLzmaEncHandle p, + ISeqOutStreamPtr outStream, + ISeqInStreamPtr inStream, ISzAllocPtr alloc, ISzAllocPtr allocBig) { - CLzmaEnc *p = (CLzmaEnc *)pp; - MFB.stream = inStream; - p->needInit = 1; + // GET_CLzmaEnc_p + MatchFinder_SET_STREAM(&MFB, inStream) p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } -SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, - ISeqInStream *inStream, UInt32 keepWindowSize, +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, + ISeqInStreamPtr inStream, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) { - CLzmaEnc *p = (CLzmaEnc *)pp; - MFB.stream = inStream; - p->needInit = 1; + // GET_CLzmaEnc_p + MatchFinder_SET_STREAM(&MFB, inStream) return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } -static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) -{ - MFB.directInput = 1; - MFB.bufferBase = (Byte *)src; - MFB.directInputRem = srcLen; -} - -SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, - UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, + const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig) { - CLzmaEnc *p = (CLzmaEnc *)pp; - LzmaEnc_SetInputBuf(p, src, srcLen); - p->needInit = 1; - - LzmaEnc_SetDataSize(pp, srcLen); + // GET_CLzmaEnc_p + MatchFinder_SET_DIRECT_INPUT_BUF(&MFB, src, srcLen) + LzmaEnc_SetDataSize(p, srcLen); return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } -void LzmaEnc_Finish(CLzmaEncHandle pp) +void LzmaEnc_Finish(CLzmaEncHandle p) { - #ifndef _7ZIP_ST - CLzmaEnc *p = (CLzmaEnc *)pp; + #ifndef Z7_ST + // GET_CLzmaEnc_p if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else - UNUSED_VAR(pp); + UNUSED_VAR(p) #endif } @@ -2933,13 +2913,13 @@ typedef struct { ISeqOutStream vt; Byte *data; - SizeT rem; + size_t rem; BoolInt overflow; } CLzmaEnc_SeqOutStreamBuf; -static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size) +static size_t SeqOutStreamBuf_Write(ISeqOutStreamPtr pp, const void *data, size_t size) { - CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt); + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLzmaEnc_SeqOutStreamBuf) if (p->rem < size) { size = p->rem; @@ -2956,24 +2936,25 @@ static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, s /* -UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p) { - const CLzmaEnc *p = (CLzmaEnc *)pp; + GET_const_CLzmaEnc_p return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } */ -const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p) { - const CLzmaEnc *p = (CLzmaEnc *)pp; + // GET_const_CLzmaEnc_p return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } -SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, +// (desiredPackSize == 0) is not allowed +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { - CLzmaEnc *p = (CLzmaEnc *)pp; + // GET_CLzmaEnc_p UInt64 nowPos64; SRes res; CLzmaEnc_SeqOutStreamBuf outStream; @@ -2990,14 +2971,10 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); - - nowPos64 = p->nowPos64; RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.vt; - - if (desiredPackSize == 0) - return SZ_ERROR_OUTPUT_EOF; - + nowPos64 = p->nowPos64; + res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); @@ -3009,12 +2986,12 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, } -MY_NO_INLINE -static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) +Z7_NO_INLINE +static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgressPtr progress) { SRes res = SZ_OK; - #ifndef _7ZIP_ST + #ifndef Z7_ST Byte allocaDummy[0x300]; allocaDummy[0] = 0; allocaDummy[1] = allocaDummy[0]; @@ -3036,7 +3013,7 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) } } - LzmaEnc_Finish(p); + LzmaEnc_Finish((CLzmaEncHandle)(void *)p); /* if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB)) @@ -3048,21 +3025,22 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) } -SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) { - RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); - return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); + // GET_CLzmaEnc_p + RINOK(LzmaEnc_Prepare(p, outStream, inStream, alloc, allocBig)) + return LzmaEnc_Encode2(p, progress); } -SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *props, SizeT *size) { if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; { - const CLzmaEnc *p = (const CLzmaEnc *)pp; + // GET_CLzmaEnc_p const UInt32 dictSize = p->dictSize; UInt32 v; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); @@ -3086,23 +3064,24 @@ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) while (v < dictSize); } - SetUi32(props + 1, v); + SetUi32(props + 1, v) return SZ_OK; } } -unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp) +unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p) { - return (unsigned)((CLzmaEnc *)pp)->writeEndMark; + // GET_CLzmaEnc_p + return (unsigned)p->writeEndMark; } -SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) { SRes res; - CLzmaEnc *p = (CLzmaEnc *)pp; + // GET_CLzmaEnc_p CLzmaEnc_SeqOutStreamBuf outStream; @@ -3114,7 +3093,7 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte p->writeEndMark = writeEndMark; p->rc.outStream = &outStream.vt; - res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); + res = LzmaEnc_MemPrepare(p, src, srcLen, 0, alloc, allocBig); if (res == SZ_OK) { @@ -3123,7 +3102,7 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte res = SZ_ERROR_FAIL; } - *destLen -= outStream.rem; + *destLen -= (SizeT)outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; @@ -3132,9 +3111,9 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, - ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) + ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) { - CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + CLzmaEncHandle p = LzmaEnc_Create(alloc); SRes res; if (!p) return SZ_ERROR_MEM; @@ -3154,10 +3133,10 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, /* -#ifndef _7ZIP_ST -void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]) +#ifndef Z7_ST +void LzmaEnc_GetLzThreads(CLzmaEncHandle p, HANDLE lz_threads[2]) { - const CLzmaEnc *p = (CLzmaEnc *)pp; + GET_const_CLzmaEnc_p lz_threads[0] = p->matchFinderMt.hashSync.thread; lz_threads[1] = p->matchFinderMt.btSync.thread; } diff --git a/libraries/lzma/C/LzmaEnc.h b/libraries/lzma/C/LzmaEnc.h index bc2ed5042b..9f8039a103 100644 --- a/libraries/lzma/C/LzmaEnc.h +++ b/libraries/lzma/C/LzmaEnc.h @@ -1,8 +1,8 @@ /* LzmaEnc.h -- LZMA Encoder -2019-10-30 : Igor Pavlov : Public domain */ +2023-04-13 : Igor Pavlov : Public domain */ -#ifndef __LZMA_ENC_H -#define __LZMA_ENC_H +#ifndef ZIP7_INC_LZMA_ENC_H +#define ZIP7_INC_LZMA_ENC_H #include "7zTypes.h" @@ -10,7 +10,7 @@ EXTERN_C_BEGIN #define LZMA_PROPS_SIZE 5 -typedef struct _CLzmaEncProps +typedef struct { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version @@ -23,10 +23,13 @@ typedef struct _CLzmaEncProps int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ + unsigned numHashOutBits; /* default = ? */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ + // int _pad; + UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. Encoder uses this value to reduce dictionary size */ @@ -51,7 +54,9 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) */ -typedef void * CLzmaEncHandle; +typedef struct CLzmaEnc CLzmaEnc; +typedef CLzmaEnc * CLzmaEncHandle; +// Z7_DECLARE_HANDLE(CLzmaEncHandle) CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig); @@ -61,17 +66,17 @@ void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p); -SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, - ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, + ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); + int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); /* ---------- One Call Interface ---------- */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, - ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); + ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); EXTERN_C_END diff --git a/libraries/lzma/C/LzmaLib.c b/libraries/lzma/C/LzmaLib.c new file mode 100644 index 0000000000..785e884874 --- /dev/null +++ b/libraries/lzma/C/LzmaLib.c @@ -0,0 +1,42 @@ +/* LzmaLib.c -- LZMA library wrapper +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Alloc.h" +#include "LzmaDec.h" +#include "LzmaEnc.h" +#include "LzmaLib.h" + +Z7_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads /* 1 or 2, default = 2 */ +) +{ + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + props.lc = lc; + props.lp = lp; + props.pb = pb; + props.fb = fb; + props.numThreads = numThreads; + + return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); +} + + +Z7_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, + const unsigned char *props, size_t propsSize) +{ + ELzmaStatus status; + return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); +} diff --git a/libraries/lzma/C/LzmaLib.h b/libraries/lzma/C/LzmaLib.h new file mode 100644 index 0000000000..d7c0724de5 --- /dev/null +++ b/libraries/lzma/C/LzmaLib.h @@ -0,0 +1,138 @@ +/* LzmaLib.h -- LZMA library interface +2023-04-02 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_LZMA_LIB_H +#define ZIP7_INC_LZMA_LIB_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define Z7_STDAPI int Z7_STDCALL + +#define LZMA_PROPS_SIZE 5 + +/* +RAM requirements for LZMA: + for compression: (dictSize * 11.5 + 6 MB) + state_size + for decompression: dictSize + state_size + state_size = (4 + (1.5 << (lc + lp))) KB + by default (lc=3, lp=0), state_size = 16 KB. + +LZMA properties (5 bytes) format + Offset Size Description + 0 1 lc, lp and pb in encoded form. + 1 4 dictSize (little endian). +*/ + +/* +LzmaCompress +------------ + +outPropsSize - + In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + + LZMA Encoder will use defult values for any parameter, if it is + -1 for any from: level, loc, lp, pb, fb, numThreads + 0 for dictSize + +level - compression level: 0 <= level <= 9; + + level dictSize algo fb + 0: 64 KB 0 32 + 1: 256 KB 0 32 + 2: 1 MB 0 32 + 3: 4 MB 0 32 + 4: 16 MB 0 32 + 5: 16 MB 1 32 + 6: 32 MB 1 32 + 7: 32 MB 1 64 + 8: 64 MB 1 64 + 9: 64 MB 1 64 + + The default value for "level" is 5. + + algo = 0 means fast method + algo = 1 means normal method + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + +lc - The number of literal context bits (high bits of previous literal). + It can be in the range from 0 to 8. The default value is 3. + Sometimes lc=4 gives the gain for big files. + +lp - The number of literal pos bits (low bits of current position for literals). + It can be in the range from 0 to 4. The default value is 0. + The lp switch is intended for periodical data when the period is equal to 2^lp. + For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's + better to set lc=0, if you change lp switch. + +pb - The number of pos bits (low bits of current position). + It can be in the range from 0 to 4. The default value is 2. + The pb switch is intended for periodical data when the period is equal 2^pb. + +fb - Word size (the number of fast bytes). + It can be in the range from 5 to 273. The default value is 32. + Usually, a big number gives a little bit better compression ratio and + slower compression process. + +numThreads - The number of thereads. 1 or 2. The default value is 2. + Fast mode (algo = 0) can use only 1 thread. + +In: + dest - output data buffer + destLen - output data buffer size + src - input data + srcLen - input data size +Out: + destLen - processed output size +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +Z7_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* default = (1 << 24) */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads /* 1 or 2, default = 2 */ + ); + +/* +LzmaUncompress +-------------- +In: + dest - output data buffer + destLen - output data buffer size + src - input data + srcLen - input data size +Out: + destLen - processed output size + srcLen - processed input size +Returns: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation arror + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) +*/ + +Z7_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, + const unsigned char *props, size_t propsSize); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/MtCoder.c b/libraries/lzma/C/MtCoder.c new file mode 100644 index 0000000000..6f58abb2a3 --- /dev/null +++ b/libraries/lzma/C/MtCoder.c @@ -0,0 +1,571 @@ +/* MtCoder.c -- Multi-thread Coder +2023-04-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "MtCoder.h" + +#ifndef Z7_ST + +static SRes MtProgressThunk_Progress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CMtProgressThunk) + UInt64 inSize2 = 0; + UInt64 outSize2 = 0; + if (inSize != (UInt64)(Int64)-1) + { + inSize2 = inSize - p->inSize; + p->inSize = inSize; + } + if (outSize != (UInt64)(Int64)-1) + { + outSize2 = outSize - p->outSize; + p->outSize = outSize; + } + return MtProgress_ProgressAdd(p->mtProgress, inSize2, outSize2); +} + + +void MtProgressThunk_CreateVTable(CMtProgressThunk *p) +{ + p->vt.Progress = MtProgressThunk_Progress; +} + + + +#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } + + +static THREAD_FUNC_DECL ThreadFunc(void *pp); + + +static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t) +{ + WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->startEvent); + if (wres == 0) + { + t->stop = False; + if (!Thread_WasCreated(&t->thread)) + wres = Thread_Create(&t->thread, ThreadFunc, t); + if (wres == 0) + wres = Event_Set(&t->startEvent); + } + if (wres == 0) + return SZ_OK; + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +static void MtCoderThread_Destruct(CMtCoderThread *t) +{ + if (Thread_WasCreated(&t->thread)) + { + t->stop = 1; + Event_Set(&t->startEvent); + Thread_Wait_Close(&t->thread); + } + + Event_Close(&t->startEvent); + + if (t->inBuf) + { + ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf); + t->inBuf = NULL; + } +} + + + + +/* + ThreadFunc2() returns: + SZ_OK - in all normal cases (even for stream error or memory allocation error) + SZ_ERROR_THREAD - in case of failure in system synch function +*/ + +static SRes ThreadFunc2(CMtCoderThread *t) +{ + CMtCoder *mtc = t->mtCoder; + + for (;;) + { + unsigned bi; + SRes res; + SRes res2; + BoolInt finished; + unsigned bufIndex; + size_t size; + const Byte *inData; + UInt64 readProcessed = 0; + + RINOK_THREAD(Event_Wait(&mtc->readEvent)) + + /* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */ + + if (mtc->stopReading) + { + return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD; + } + + res = MtProgress_GetError(&mtc->mtProgress); + + size = 0; + inData = NULL; + finished = True; + + if (res == SZ_OK) + { + size = mtc->blockSize; + if (mtc->inStream) + { + if (!t->inBuf) + { + t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize); + if (!t->inBuf) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = SeqInStream_ReadMax(mtc->inStream, t->inBuf, &size); + readProcessed = mtc->readProcessed + size; + mtc->readProcessed = readProcessed; + } + if (res != SZ_OK) + { + mtc->readRes = res; + /* after reading error - we can stop encoding of previous blocks */ + MtProgress_SetError(&mtc->mtProgress, res); + } + else + finished = (size != mtc->blockSize); + } + else + { + size_t rem; + readProcessed = mtc->readProcessed; + rem = mtc->inDataSize - (size_t)readProcessed; + if (size > rem) + size = rem; + inData = mtc->inData + (size_t)readProcessed; + readProcessed += size; + mtc->readProcessed = readProcessed; + finished = (mtc->inDataSize == (size_t)readProcessed); + } + } + + /* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */ + + res2 = SZ_OK; + + if (Semaphore_Wait(&mtc->blocksSemaphore) != 0) + { + res2 = SZ_ERROR_THREAD; + if (res == SZ_OK) + { + res = res2; + // MtProgress_SetError(&mtc->mtProgress, res); + } + } + + bi = mtc->blockIndex; + + if (++mtc->blockIndex >= mtc->numBlocksMax) + mtc->blockIndex = 0; + + bufIndex = (unsigned)(int)-1; + + if (res == SZ_OK) + res = MtProgress_GetError(&mtc->mtProgress); + + if (res != SZ_OK) + finished = True; + + if (!finished) + { + if (mtc->numStartedThreads < mtc->numStartedThreadsLimit + && mtc->expectedDataSize != readProcessed) + { + res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]); + if (res == SZ_OK) + mtc->numStartedThreads++; + else + { + MtProgress_SetError(&mtc->mtProgress, res); + finished = True; + } + } + } + + if (finished) + mtc->stopReading = True; + + RINOK_THREAD(Event_Set(&mtc->readEvent)) + + if (res2 != SZ_OK) + return res2; + + if (res == SZ_OK) + { + CriticalSection_Enter(&mtc->cs); + bufIndex = mtc->freeBlockHead; + mtc->freeBlockHead = mtc->freeBlockList[bufIndex]; + CriticalSection_Leave(&mtc->cs); + + res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex, + mtc->inStream ? t->inBuf : inData, size, finished); + + // MtProgress_Reinit(&mtc->mtProgress, t->index); + + if (res != SZ_OK) + MtProgress_SetError(&mtc->mtProgress, res); + } + + { + CMtCoderBlock *block = &mtc->blocks[bi]; + block->res = res; + block->bufIndex = bufIndex; + block->finished = finished; + } + + #ifdef MTCODER_USE_WRITE_THREAD + RINOK_THREAD(Event_Set(&mtc->writeEvents[bi])) + #else + { + unsigned wi; + { + CriticalSection_Enter(&mtc->cs); + wi = mtc->writeIndex; + if (wi == bi) + mtc->writeIndex = (unsigned)(int)-1; + else + mtc->ReadyBlocks[bi] = True; + CriticalSection_Leave(&mtc->cs); + } + + if (wi != bi) + { + if (res != SZ_OK || finished) + return 0; + continue; + } + + if (mtc->writeRes != SZ_OK) + res = mtc->writeRes; + + for (;;) + { + if (res == SZ_OK && bufIndex != (unsigned)(int)-1) + { + res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex); + if (res != SZ_OK) + { + mtc->writeRes = res; + MtProgress_SetError(&mtc->mtProgress, res); + } + } + + if (++wi >= mtc->numBlocksMax) + wi = 0; + { + BoolInt isReady; + + CriticalSection_Enter(&mtc->cs); + + if (bufIndex != (unsigned)(int)-1) + { + mtc->freeBlockList[bufIndex] = mtc->freeBlockHead; + mtc->freeBlockHead = bufIndex; + } + + isReady = mtc->ReadyBlocks[wi]; + + if (isReady) + mtc->ReadyBlocks[wi] = False; + else + mtc->writeIndex = wi; + + CriticalSection_Leave(&mtc->cs); + + RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore)) + + if (!isReady) + break; + } + + { + CMtCoderBlock *block = &mtc->blocks[wi]; + if (res == SZ_OK && block->res != SZ_OK) + res = block->res; + bufIndex = block->bufIndex; + finished = block->finished; + } + } + } + #endif + + if (finished || res != SZ_OK) + return 0; + } +} + + +static THREAD_FUNC_DECL ThreadFunc(void *pp) +{ + CMtCoderThread *t = (CMtCoderThread *)pp; + for (;;) + { + if (Event_Wait(&t->startEvent) != 0) + return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD; + if (t->stop) + return 0; + { + SRes res = ThreadFunc2(t); + CMtCoder *mtc = t->mtCoder; + if (res != SZ_OK) + { + MtProgress_SetError(&mtc->mtProgress, res); + } + + #ifndef MTCODER_USE_WRITE_THREAD + { + unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads); + if (numFinished == mtc->numStartedThreads) + if (Event_Set(&mtc->finishedEvent) != 0) + return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD; + } + #endif + } + } +} + + + +void MtCoder_Construct(CMtCoder *p) +{ + unsigned i; + + p->blockSize = 0; + p->numThreadsMax = 0; + p->expectedDataSize = (UInt64)(Int64)-1; + + p->inStream = NULL; + p->inData = NULL; + p->inDataSize = 0; + + p->progress = NULL; + p->allocBig = NULL; + + p->mtCallback = NULL; + p->mtCallbackObject = NULL; + + p->allocatedBufsSize = 0; + + Event_Construct(&p->readEvent); + Semaphore_Construct(&p->blocksSemaphore); + + for (i = 0; i < MTCODER_THREADS_MAX; i++) + { + CMtCoderThread *t = &p->threads[i]; + t->mtCoder = p; + t->index = i; + t->inBuf = NULL; + t->stop = False; + Event_Construct(&t->startEvent); + Thread_CONSTRUCT(&t->thread) + } + + #ifdef MTCODER_USE_WRITE_THREAD + for (i = 0; i < MTCODER_BLOCKS_MAX; i++) + Event_Construct(&p->writeEvents[i]); + #else + Event_Construct(&p->finishedEvent); + #endif + + CriticalSection_Init(&p->cs); + CriticalSection_Init(&p->mtProgress.cs); +} + + + + +static void MtCoder_Free(CMtCoder *p) +{ + unsigned i; + + /* + p->stopReading = True; + if (Event_IsCreated(&p->readEvent)) + Event_Set(&p->readEvent); + */ + + for (i = 0; i < MTCODER_THREADS_MAX; i++) + MtCoderThread_Destruct(&p->threads[i]); + + Event_Close(&p->readEvent); + Semaphore_Close(&p->blocksSemaphore); + + #ifdef MTCODER_USE_WRITE_THREAD + for (i = 0; i < MTCODER_BLOCKS_MAX; i++) + Event_Close(&p->writeEvents[i]); + #else + Event_Close(&p->finishedEvent); + #endif +} + + +void MtCoder_Destruct(CMtCoder *p) +{ + MtCoder_Free(p); + + CriticalSection_Delete(&p->cs); + CriticalSection_Delete(&p->mtProgress.cs); +} + + +SRes MtCoder_Code(CMtCoder *p) +{ + unsigned numThreads = p->numThreadsMax; + unsigned numBlocksMax; + unsigned i; + SRes res = SZ_OK; + + if (numThreads > MTCODER_THREADS_MAX) + numThreads = MTCODER_THREADS_MAX; + numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads); + + if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++; + if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++; + if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++; + + if (numBlocksMax > MTCODER_BLOCKS_MAX) + numBlocksMax = MTCODER_BLOCKS_MAX; + + if (p->blockSize != p->allocatedBufsSize) + { + for (i = 0; i < MTCODER_THREADS_MAX; i++) + { + CMtCoderThread *t = &p->threads[i]; + if (t->inBuf) + { + ISzAlloc_Free(p->allocBig, t->inBuf); + t->inBuf = NULL; + } + } + p->allocatedBufsSize = p->blockSize; + } + + p->readRes = SZ_OK; + + MtProgress_Init(&p->mtProgress, p->progress); + + #ifdef MTCODER_USE_WRITE_THREAD + for (i = 0; i < numBlocksMax; i++) + { + RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->writeEvents[i])) + } + #else + RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent)) + #endif + + { + RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent)) + RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, numBlocksMax, numBlocksMax)) + } + + for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++) + p->freeBlockList[i] = i + 1; + p->freeBlockList[MTCODER_BLOCKS_MAX - 1] = (unsigned)(int)-1; + p->freeBlockHead = 0; + + p->readProcessed = 0; + p->blockIndex = 0; + p->numBlocksMax = numBlocksMax; + p->stopReading = False; + + #ifndef MTCODER_USE_WRITE_THREAD + p->writeIndex = 0; + p->writeRes = SZ_OK; + for (i = 0; i < MTCODER_BLOCKS_MAX; i++) + p->ReadyBlocks[i] = False; + p->numFinishedThreads = 0; + #endif + + p->numStartedThreadsLimit = numThreads; + p->numStartedThreads = 0; + + // for (i = 0; i < numThreads; i++) + { + CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++]; + RINOK(MtCoderThread_CreateAndStart(nextThread)) + } + + RINOK_THREAD(Event_Set(&p->readEvent)) + + #ifdef MTCODER_USE_WRITE_THREAD + { + unsigned bi = 0; + + for (;; bi++) + { + if (bi >= numBlocksMax) + bi = 0; + + RINOK_THREAD(Event_Wait(&p->writeEvents[bi])) + + { + const CMtCoderBlock *block = &p->blocks[bi]; + unsigned bufIndex = block->bufIndex; + BoolInt finished = block->finished; + if (res == SZ_OK && block->res != SZ_OK) + res = block->res; + + if (bufIndex != (unsigned)(int)-1) + { + if (res == SZ_OK) + { + res = p->mtCallback->Write(p->mtCallbackObject, bufIndex); + if (res != SZ_OK) + MtProgress_SetError(&p->mtProgress, res); + } + + CriticalSection_Enter(&p->cs); + { + p->freeBlockList[bufIndex] = p->freeBlockHead; + p->freeBlockHead = bufIndex; + } + CriticalSection_Leave(&p->cs); + } + + RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore)) + + if (finished) + break; + } + } + } + #else + { + WRes wres = Event_Wait(&p->finishedEvent); + res = MY_SRes_HRESULT_FROM_WRes(wres); + } + #endif + + if (res == SZ_OK) + res = p->readRes; + + if (res == SZ_OK) + res = p->mtProgress.res; + + #ifndef MTCODER_USE_WRITE_THREAD + if (res == SZ_OK) + res = p->writeRes; + #endif + + if (res != SZ_OK) + MtCoder_Free(p); + return res; +} + +#endif + +#undef RINOK_THREAD diff --git a/libraries/lzma/C/MtCoder.h b/libraries/lzma/C/MtCoder.h new file mode 100644 index 0000000000..1231d3c2a5 --- /dev/null +++ b/libraries/lzma/C/MtCoder.h @@ -0,0 +1,141 @@ +/* MtCoder.h -- Multi-thread Coder +2023-04-13 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_MT_CODER_H +#define ZIP7_INC_MT_CODER_H + +#include "MtDec.h" + +EXTERN_C_BEGIN + +/* + if ( defined MTCODER_USE_WRITE_THREAD) : main thread writes all data blocks to output stream + if (not defined MTCODER_USE_WRITE_THREAD) : any coder thread can write data blocks to output stream +*/ +/* #define MTCODER_USE_WRITE_THREAD */ + +#ifndef Z7_ST + #define MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1) + #define MTCODER_THREADS_MAX 64 + #define MTCODER_BLOCKS_MAX (MTCODER_GET_NUM_BLOCKS_FROM_THREADS(MTCODER_THREADS_MAX) + 3) +#else + #define MTCODER_THREADS_MAX 1 + #define MTCODER_BLOCKS_MAX 1 +#endif + + +#ifndef Z7_ST + + +typedef struct +{ + ICompressProgress vt; + CMtProgress *mtProgress; + UInt64 inSize; + UInt64 outSize; +} CMtProgressThunk; + +void MtProgressThunk_CreateVTable(CMtProgressThunk *p); + +#define MtProgressThunk_INIT(p) { (p)->inSize = 0; (p)->outSize = 0; } + + +struct CMtCoder_; + + +typedef struct +{ + struct CMtCoder_ *mtCoder; + unsigned index; + int stop; + Byte *inBuf; + + CAutoResetEvent startEvent; + CThread thread; +} CMtCoderThread; + + +typedef struct +{ + SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished); + SRes (*Write)(void *p, unsigned outBufIndex); +} IMtCoderCallback2; + + +typedef struct +{ + SRes res; + unsigned bufIndex; + BoolInt finished; +} CMtCoderBlock; + + +typedef struct CMtCoder_ +{ + /* input variables */ + + size_t blockSize; /* size of input block */ + unsigned numThreadsMax; + UInt64 expectedDataSize; + + ISeqInStreamPtr inStream; + const Byte *inData; + size_t inDataSize; + + ICompressProgressPtr progress; + ISzAllocPtr allocBig; + + IMtCoderCallback2 *mtCallback; + void *mtCallbackObject; + + + /* internal variables */ + + size_t allocatedBufsSize; + + CAutoResetEvent readEvent; + CSemaphore blocksSemaphore; + + BoolInt stopReading; + SRes readRes; + + #ifdef MTCODER_USE_WRITE_THREAD + CAutoResetEvent writeEvents[MTCODER_BLOCKS_MAX]; + #else + CAutoResetEvent finishedEvent; + SRes writeRes; + unsigned writeIndex; + Byte ReadyBlocks[MTCODER_BLOCKS_MAX]; + LONG numFinishedThreads; + #endif + + unsigned numStartedThreadsLimit; + unsigned numStartedThreads; + + unsigned numBlocksMax; + unsigned blockIndex; + UInt64 readProcessed; + + CCriticalSection cs; + + unsigned freeBlockHead; + unsigned freeBlockList[MTCODER_BLOCKS_MAX]; + + CMtProgress mtProgress; + CMtCoderBlock blocks[MTCODER_BLOCKS_MAX]; + CMtCoderThread threads[MTCODER_THREADS_MAX]; +} CMtCoder; + + +void MtCoder_Construct(CMtCoder *p); +void MtCoder_Destruct(CMtCoder *p); +SRes MtCoder_Code(CMtCoder *p); + + +#endif + + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/MtDec.c b/libraries/lzma/C/MtDec.c new file mode 100644 index 0000000000..782069926d --- /dev/null +++ b/libraries/lzma/C/MtDec.c @@ -0,0 +1,1114 @@ +/* MtDec.c -- Multi-thread Decoder +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #define SHOW_DEBUG_INFO + +// #include +#include + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include "MtDec.h" + +#ifndef Z7_ST + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) + +void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress) +{ + p->progress = progress; + p->res = SZ_OK; + p->totalInSize = 0; + p->totalOutSize = 0; +} + + +SRes MtProgress_Progress_ST(CMtProgress *p) +{ + if (p->res == SZ_OK && p->progress) + if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) + p->res = SZ_ERROR_PROGRESS; + return p->res; +} + + +SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize) +{ + SRes res; + CriticalSection_Enter(&p->cs); + + p->totalInSize += inSize; + p->totalOutSize += outSize; + if (p->res == SZ_OK && p->progress) + if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) + p->res = SZ_ERROR_PROGRESS; + res = p->res; + + CriticalSection_Leave(&p->cs); + return res; +} + + +SRes MtProgress_GetError(CMtProgress *p) +{ + SRes res; + CriticalSection_Enter(&p->cs); + res = p->res; + CriticalSection_Leave(&p->cs); + return res; +} + + +void MtProgress_SetError(CMtProgress *p, SRes res) +{ + CriticalSection_Enter(&p->cs); + if (p->res == SZ_OK) + p->res = res; + CriticalSection_Leave(&p->cs); +} + + +#define RINOK_THREAD(x) RINOK_WRes(x) + + +struct CMtDecBufLink_ +{ + struct CMtDecBufLink_ *next; + void *pad[3]; +}; + +typedef struct CMtDecBufLink_ CMtDecBufLink; + +#define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink) +#define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET) + + + +static THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp); + + +static WRes MtDecThread_CreateEvents(CMtDecThread *t) +{ + WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->canWrite); + if (wres == 0) + { + wres = AutoResetEvent_OptCreate_And_Reset(&t->canRead); + if (wres == 0) + return SZ_OK; + } + return wres; +} + + +static SRes MtDecThread_CreateAndStart(CMtDecThread *t) +{ + WRes wres = MtDecThread_CreateEvents(t); + // wres = 17; // for test + if (wres == 0) + { + if (Thread_WasCreated(&t->thread)) + return SZ_OK; + wres = Thread_Create(&t->thread, MtDec_ThreadFunc, t); + if (wres == 0) + return SZ_OK; + } + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +void MtDecThread_FreeInBufs(CMtDecThread *t) +{ + if (t->inBuf) + { + void *link = t->inBuf; + t->inBuf = NULL; + do + { + void *next = ((CMtDecBufLink *)link)->next; + ISzAlloc_Free(t->mtDec->alloc, link); + link = next; + } + while (link); + } +} + + +static void MtDecThread_CloseThread(CMtDecThread *t) +{ + if (Thread_WasCreated(&t->thread)) + { + Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */ + Event_Set(&t->canRead); + Thread_Wait_Close(&t->thread); + } + + Event_Close(&t->canRead); + Event_Close(&t->canWrite); +} + +static void MtDec_CloseThreads(CMtDec *p) +{ + unsigned i; + for (i = 0; i < MTDEC_THREADS_MAX; i++) + MtDecThread_CloseThread(&p->threads[i]); +} + +static void MtDecThread_Destruct(CMtDecThread *t) +{ + MtDecThread_CloseThread(t); + MtDecThread_FreeInBufs(t); +} + + + +static SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, BoolInt *wasInterrupted) +{ + SRes res; + CriticalSection_Enter(&p->mtProgress.cs); + *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); + res = p->mtProgress.res; + CriticalSection_Leave(&p->mtProgress.cs); + return res; +} + +static SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, BoolInt *wasInterrupted) +{ + SRes res; + CriticalSection_Enter(&p->mtProgress.cs); + + p->mtProgress.totalInSize += inSize; + p->mtProgress.totalOutSize += outSize; + if (p->mtProgress.res == SZ_OK && p->mtProgress.progress) + if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK) + p->mtProgress.res = SZ_ERROR_PROGRESS; + + *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); + res = p->mtProgress.res; + + CriticalSection_Leave(&p->mtProgress.cs); + + return res; +} + +static void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex) +{ + CriticalSection_Enter(&p->mtProgress.cs); + if (!p->needInterrupt || interruptIndex < p->interruptIndex) + { + p->interruptIndex = interruptIndex; + p->needInterrupt = True; + } + CriticalSection_Leave(&p->mtProgress.cs); +} + +Byte *MtDec_GetCrossBuff(CMtDec *p) +{ + Byte *cr = p->crossBlock; + if (!cr) + { + cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); + if (!cr) + return NULL; + p->crossBlock = cr; + } + return MTDEC__DATA_PTR_FROM_LINK(cr); +} + + +/* + MtDec_ThreadFunc2() returns: + 0 - in all normal cases (even for stream error or memory allocation error) + (!= 0) - WRes error return by system threading function +*/ + +// #define MTDEC_ProgessStep (1 << 22) +#define MTDEC_ProgessStep (1 << 0) + +static WRes MtDec_ThreadFunc2(CMtDecThread *t) +{ + CMtDec *p = t->mtDec; + + PRF_STR_INT("MtDec_ThreadFunc2", t->index) + + // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index); + + for (;;) + { + SRes res, codeRes; + BoolInt wasInterrupted, isAllocError, overflow, finish; + SRes threadingErrorSRes; + BoolInt needCode, needWrite, needContinue; + + size_t inDataSize_Start; + UInt64 inDataSize; + // UInt64 inDataSize_Full; + + UInt64 blockIndex; + + UInt64 inPrev = 0; + UInt64 outPrev = 0; + UInt64 inCodePos; + UInt64 outCodePos; + + Byte *afterEndData = NULL; + size_t afterEndData_Size = 0; + BoolInt afterEndData_IsCross = False; + + BoolInt canCreateNewThread = False; + // CMtDecCallbackInfo parse; + CMtDecThread *nextThread; + + PRF_STR_INT("=============== Event_Wait(&t->canRead)", t->index) + + RINOK_THREAD(Event_Wait(&t->canRead)) + if (p->exitThread) + return 0; + + PRF_STR_INT("after Event_Wait(&t->canRead)", t->index) + + // if (t->index == 3) return 19; // for test + + blockIndex = p->blockIndex++; + + // PRF(printf("\ncanRead\n")) + + res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); + + finish = p->readWasFinished; + needCode = False; + needWrite = False; + isAllocError = False; + overflow = False; + + inDataSize_Start = 0; + inDataSize = 0; + // inDataSize_Full = 0; + + if (res == SZ_OK && !wasInterrupted) + { + // if (p->inStream) + { + CMtDecBufLink *prev = NULL; + CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; + size_t crossSize = p->crossEnd - p->crossStart; + + PRF(printf("\ncrossSize = %d\n", crossSize)); + + for (;;) + { + if (!link) + { + link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); + if (!link) + { + finish = True; + // p->allocError_for_Read_BlockIndex = blockIndex; + isAllocError = True; + break; + } + link->next = NULL; + if (prev) + { + // static unsigned g_num = 0; + // printf("\n%6d : %x", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev)); + prev->next = link; + } + else + t->inBuf = (void *)link; + } + + { + Byte *data = MTDEC__DATA_PTR_FROM_LINK(link); + Byte *parseData = data; + size_t size; + + if (crossSize != 0) + { + inDataSize = crossSize; + // inDataSize_Full = inDataSize; + inDataSize_Start = crossSize; + size = crossSize; + parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; + PRF(printf("\ncross : crossStart = %7d crossEnd = %7d finish = %1d", + (int)p->crossStart, (int)p->crossEnd, (int)finish)); + } + else + { + size = p->inBufSize; + + res = SeqInStream_ReadMax(p->inStream, data, &size); + + // size = 10; // test + + inDataSize += size; + // inDataSize_Full = inDataSize; + if (!prev) + inDataSize_Start = size; + + p->readProcessed += size; + finish = (size != p->inBufSize); + if (finish) + p->readWasFinished = True; + + // res = E_INVALIDARG; // test + + if (res != SZ_OK) + { + // PRF(printf("\nRead error = %d\n", res)) + // we want to decode all data before error + p->readRes = res; + // p->readError_BlockIndex = blockIndex; + p->readWasFinished = True; + finish = True; + res = SZ_OK; + // break; + } + + if (inDataSize - inPrev >= MTDEC_ProgessStep) + { + res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); + if (res != SZ_OK || wasInterrupted) + break; + inPrev = inDataSize; + } + } + + { + CMtDecCallbackInfo parse; + + parse.startCall = (prev == NULL); + parse.src = parseData; + parse.srcSize = size; + parse.srcFinished = finish; + parse.canCreateNewThread = True; + + PRF(printf("\nParse size = %d\n", (unsigned)size)); + + p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse); + + PRF(printf(" Parse processed = %d, state = %d \n", (unsigned)parse.srcSize, (unsigned)parse.state)); + + needWrite = True; + canCreateNewThread = parse.canCreateNewThread; + + // printf("\n\n%12I64u %12I64u", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize); + + if ( + // parseRes != SZ_OK || + // inDataSize - (size - parse.srcSize) > p->inBlockMax + // || + parse.state == MTDEC_PARSE_OVERFLOW + // || wasInterrupted + ) + { + // Overflow or Parse error - switch from MT decoding to ST decoding + finish = True; + overflow = True; + + { + PRF(printf("\n Overflow")); + // PRF(printf("\nisBlockFinished = %d", (unsigned)parse.blockWasFinished)); + PRF(printf("\n inDataSize = %d", (unsigned)inDataSize)); + } + + if (crossSize != 0) + memcpy(data, parseData, size); + p->crossStart = 0; + p->crossEnd = 0; + break; + } + + if (crossSize != 0) + { + memcpy(data, parseData, parse.srcSize); + p->crossStart += parse.srcSize; + } + + if (parse.state != MTDEC_PARSE_CONTINUE || finish) + { + // we don't need to parse in current thread anymore + + if (parse.state == MTDEC_PARSE_END) + finish = True; + + needCode = True; + // p->crossFinished = finish; + + if (parse.srcSize == size) + { + // full parsed - no cross transfer + p->crossStart = 0; + p->crossEnd = 0; + break; + } + + if (parse.state == MTDEC_PARSE_END) + { + afterEndData = parseData + parse.srcSize; + afterEndData_Size = size - parse.srcSize; + if (crossSize != 0) + afterEndData_IsCross = True; + // we reduce data size to required bytes (parsed only) + inDataSize -= afterEndData_Size; + if (!prev) + inDataSize_Start = parse.srcSize; + break; + } + + { + // partial parsed - need cross transfer + if (crossSize != 0) + inDataSize = parse.srcSize; // it's only parsed now + else + { + // partial parsed - is not in initial cross block - we need to copy new data to cross block + Byte *cr = MtDec_GetCrossBuff(p); + if (!cr) + { + { + PRF(printf("\ncross alloc error error\n")); + // res = SZ_ERROR_MEM; + finish = True; + // p->allocError_for_Read_BlockIndex = blockIndex; + isAllocError = True; + break; + } + } + + { + size_t crSize = size - parse.srcSize; + inDataSize -= crSize; + p->crossEnd = crSize; + p->crossStart = 0; + memcpy(cr, parseData + parse.srcSize, crSize); + } + } + + // inDataSize_Full = inDataSize; + if (!prev) + inDataSize_Start = parse.srcSize; // it's partial size (parsed only) + + finish = False; + break; + } + } + + if (parse.srcSize != size) + { + res = SZ_ERROR_FAIL; + PRF(printf("\nfinished error SZ_ERROR_FAIL = %d\n", res)); + break; + } + } + } + + prev = link; + link = link->next; + + if (crossSize != 0) + { + crossSize = 0; + p->crossStart = 0; + p->crossEnd = 0; + } + } + } + + if (res == SZ_OK) + res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted); + } + + codeRes = SZ_OK; + + if (res == SZ_OK && needCode && !wasInterrupted) + { + codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index); + if (codeRes != SZ_OK) + { + needCode = False; + finish = True; + // SZ_ERROR_MEM is expected error here. + // if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later. + // if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding. + } + } + + if (res != SZ_OK || wasInterrupted) + finish = True; + + nextThread = NULL; + threadingErrorSRes = SZ_OK; + + if (!finish) + { + if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread) + { + SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]); + if (res2 == SZ_OK) + { + // if (p->numStartedThreads % 1000 == 0) PRF(printf("\n numStartedThreads=%d\n", p->numStartedThreads)); + p->numStartedThreads++; + } + else + { + PRF(printf("\nERROR: numStartedThreads=%d\n", p->numStartedThreads)); + if (p->numStartedThreads == 1) + { + // if only one thread is possible, we leave muti-threading code + finish = True; + needCode = False; + threadingErrorSRes = res2; + } + else + p->numStartedThreads_Limit = p->numStartedThreads; + } + } + + if (!finish) + { + unsigned nextIndex = t->index + 1; + nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex]; + RINOK_THREAD(Event_Set(&nextThread->canRead)) + // We have started executing for new iteration (with next thread) + // And that next thread now is responsible for possible exit from decoding (threading_code) + } + } + + // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite) + // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case + // if ( finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block): + // - if (needContinue) after Write(&needContinue), we restore decoding with new iteration + // - otherwise we stop decoding and exit from MtDec_ThreadFunc2() + + // Don't change (finish) variable in the further code + + + // ---------- CODE ---------- + + inPrev = 0; + outPrev = 0; + inCodePos = 0; + outCodePos = 0; + + if (res == SZ_OK && needCode && codeRes == SZ_OK) + { + BoolInt isStartBlock = True; + CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; + + for (;;) + { + size_t inSize; + int stop; + + if (isStartBlock) + inSize = inDataSize_Start; + else + { + UInt64 rem = inDataSize - inCodePos; + inSize = p->inBufSize; + if (inSize > rem) + inSize = (size_t)rem; + } + + inCodePos += inSize; + stop = True; + + codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index, + (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize, + (inCodePos == inDataSize), // srcFinished + &inCodePos, &outCodePos, &stop); + + if (codeRes != SZ_OK) + { + PRF(printf("\nCode Interrupt error = %x\n", codeRes)); + // we interrupt only later blocks + MtDec_Interrupt(p, blockIndex); + break; + } + + if (stop || inCodePos == inDataSize) + break; + + { + const UInt64 inDelta = inCodePos - inPrev; + const UInt64 outDelta = outCodePos - outPrev; + if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep) + { + // Sleep(1); + res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted); + if (res != SZ_OK || wasInterrupted) + break; + inPrev = inCodePos; + outPrev = outCodePos; + } + } + + link = link->next; + isStartBlock = False; + } + } + + + // ---------- WRITE ---------- + + RINOK_THREAD(Event_Wait(&t->canWrite)) + + { + BoolInt isErrorMode = False; + BoolInt canRecode = True; + BoolInt needWriteToStream = needWrite; + + if (p->exitThread) return 0; // it's never executed in normal cases + + if (p->wasInterrupted) + wasInterrupted = True; + else + { + if (codeRes != SZ_OK) // || !needCode // check it !!! + { + p->wasInterrupted = True; + p->codeRes = codeRes; + if (codeRes == SZ_ERROR_MEM) + isAllocError = True; + } + + if (threadingErrorSRes) + { + p->wasInterrupted = True; + p->threadingErrorSRes = threadingErrorSRes; + needWriteToStream = False; + } + if (isAllocError) + { + p->wasInterrupted = True; + p->isAllocError = True; + needWriteToStream = False; + } + if (overflow) + { + p->wasInterrupted = True; + p->overflow = True; + needWriteToStream = False; + } + } + + if (needCode) + { + if (wasInterrupted) + { + inCodePos = 0; + outCodePos = 0; + } + { + const UInt64 inDelta = inCodePos - inPrev; + const UInt64 outDelta = outCodePos - outPrev; + // if (inDelta != 0 || outDelta != 0) + res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta); + } + } + + needContinue = (!finish); + + // if (res == SZ_OK && needWrite && !wasInterrupted) + if (needWrite) + { + // p->inProcessed += inCodePos; + + PRF(printf("\n--Write afterSize = %d\n", (unsigned)afterEndData_Size)); + + res = p->mtCallback->Write(p->mtCallbackObject, t->index, + res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite + afterEndData, afterEndData_Size, afterEndData_IsCross, + &needContinue, + &canRecode); + + // res = SZ_ERROR_FAIL; // for test + + PRF(printf("\nAfter Write needContinue = %d\n", (unsigned)needContinue)); + PRF(printf("\nprocessed = %d\n", (unsigned)p->inProcessed)); + + if (res != SZ_OK) + { + PRF(printf("\nWrite error = %d\n", res)); + isErrorMode = True; + p->wasInterrupted = True; + } + if (res != SZ_OK + || (!needContinue && !finish)) + { + PRF(printf("\nWrite Interrupt error = %x\n", res)); + MtDec_Interrupt(p, blockIndex); + } + } + + if (canRecode) + if (!needCode + || res != SZ_OK + || p->wasInterrupted + || codeRes != SZ_OK + || wasInterrupted + || p->numFilledThreads != 0 + || isErrorMode) + { + if (p->numFilledThreads == 0) + p->filledThreadStart = t->index; + if (inDataSize != 0 || !finish) + { + t->inDataSize_Start = inDataSize_Start; + t->inDataSize = inDataSize; + p->numFilledThreads++; + } + PRF(printf("\np->numFilledThreads = %d\n", p->numFilledThreads)); + PRF(printf("p->filledThreadStart = %d\n", p->filledThreadStart)); + } + + if (!finish) + { + RINOK_THREAD(Event_Set(&nextThread->canWrite)) + } + else + { + if (needContinue) + { + // we restore decoding with new iteration + RINOK_THREAD(Event_Set(&p->threads[0].canWrite)) + } + else + { + // we exit from decoding + if (t->index == 0) + return SZ_OK; + p->exitThread = True; + } + RINOK_THREAD(Event_Set(&p->threads[0].canRead)) + } + } + } +} + +#ifdef _WIN32 +#define USE_ALLOCA +#endif + +#ifdef USE_ALLOCA +#ifdef _WIN32 +#include +#else +#include +#endif +#endif + + +static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp) +{ + WRes res; + + CMtDecThread *t = (CMtDecThread *)pp; + CMtDec *p; + + // fprintf(stdout, "\n%d = %p\n", t->index, &t); + + res = MtDec_ThreadFunc2(t); + p = t->mtDec; + if (res == 0) + return (THREAD_FUNC_RET_TYPE)(UINT_PTR)p->exitThreadWRes; + { + // it's unexpected situation for some threading function error + if (p->exitThreadWRes == 0) + p->exitThreadWRes = res; + PRF(printf("\nthread exit error = %d\n", res)); + p->exitThread = True; + Event_Set(&p->threads[0].canRead); + Event_Set(&p->threads[0].canWrite); + MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res)); + } + return (THREAD_FUNC_RET_TYPE)(UINT_PTR)res; +} + +static Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp) +{ + #ifdef USE_ALLOCA + CMtDecThread *t = (CMtDecThread *)pp; + // fprintf(stderr, "\n%d = %p - before", t->index, &t); + t->allocaPtr = alloca(t->index * 128); + #endif + return MtDec_ThreadFunc1(pp); +} + + +int MtDec_PrepareRead(CMtDec *p) +{ + if (p->crossBlock && p->crossStart == p->crossEnd) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + + { + unsigned i; + for (i = 0; i < MTDEC_THREADS_MAX; i++) + if (i > p->numStartedThreads + || p->numFilledThreads <= + (i >= p->filledThreadStart ? + i - p->filledThreadStart : + i + p->numStartedThreads - p->filledThreadStart)) + MtDecThread_FreeInBufs(&p->threads[i]); + } + + return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd); +} + + +const Byte *MtDec_Read(CMtDec *p, size_t *inLim) +{ + while (p->numFilledThreads != 0) + { + CMtDecThread *t = &p->threads[p->filledThreadStart]; + + if (*inLim != 0) + { + { + void *link = t->inBuf; + void *next = ((CMtDecBufLink *)link)->next; + ISzAlloc_Free(p->alloc, link); + t->inBuf = next; + } + + if (t->inDataSize == 0) + { + MtDecThread_FreeInBufs(t); + if (--p->numFilledThreads == 0) + break; + if (++p->filledThreadStart == p->numStartedThreads) + p->filledThreadStart = 0; + t = &p->threads[p->filledThreadStart]; + } + } + + { + size_t lim = t->inDataSize_Start; + if (lim != 0) + t->inDataSize_Start = 0; + else + { + UInt64 rem = t->inDataSize; + lim = p->inBufSize; + if (lim > rem) + lim = (size_t)rem; + } + t->inDataSize -= lim; + *inLim = lim; + return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf); + } + } + + { + size_t crossSize = p->crossEnd - p->crossStart; + if (crossSize != 0) + { + const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; + *inLim = crossSize; + p->crossStart = 0; + p->crossEnd = 0; + return data; + } + *inLim = 0; + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + return NULL; + } +} + + +void MtDec_Construct(CMtDec *p) +{ + unsigned i; + + p->inBufSize = (size_t)1 << 18; + + p->numThreadsMax = 0; + + p->inStream = NULL; + + // p->inData = NULL; + // p->inDataSize = 0; + + p->crossBlock = NULL; + p->crossStart = 0; + p->crossEnd = 0; + + p->numFilledThreads = 0; + + p->progress = NULL; + p->alloc = NULL; + + p->mtCallback = NULL; + p->mtCallbackObject = NULL; + + p->allocatedBufsSize = 0; + + for (i = 0; i < MTDEC_THREADS_MAX; i++) + { + CMtDecThread *t = &p->threads[i]; + t->mtDec = p; + t->index = i; + t->inBuf = NULL; + Event_Construct(&t->canRead); + Event_Construct(&t->canWrite); + Thread_CONSTRUCT(&t->thread) + } + + // Event_Construct(&p->finishedEvent); + + CriticalSection_Init(&p->mtProgress.cs); +} + + +static void MtDec_Free(CMtDec *p) +{ + unsigned i; + + p->exitThread = True; + + for (i = 0; i < MTDEC_THREADS_MAX; i++) + MtDecThread_Destruct(&p->threads[i]); + + // Event_Close(&p->finishedEvent); + + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } +} + + +void MtDec_Destruct(CMtDec *p) +{ + MtDec_Free(p); + + CriticalSection_Delete(&p->mtProgress.cs); +} + + +SRes MtDec_Code(CMtDec *p) +{ + unsigned i; + + p->inProcessed = 0; + + p->blockIndex = 1; // it must be larger than not_defined index (0) + p->isAllocError = False; + p->overflow = False; + p->threadingErrorSRes = SZ_OK; + + p->needContinue = True; + + p->readWasFinished = False; + p->needInterrupt = False; + p->interruptIndex = (UInt64)(Int64)-1; + + p->readProcessed = 0; + p->readRes = SZ_OK; + p->codeRes = SZ_OK; + p->wasInterrupted = False; + + p->crossStart = 0; + p->crossEnd = 0; + + p->filledThreadStart = 0; + p->numFilledThreads = 0; + + { + unsigned numThreads = p->numThreadsMax; + if (numThreads > MTDEC_THREADS_MAX) + numThreads = MTDEC_THREADS_MAX; + p->numStartedThreads_Limit = numThreads; + p->numStartedThreads = 0; + } + + if (p->inBufSize != p->allocatedBufsSize) + { + for (i = 0; i < MTDEC_THREADS_MAX; i++) + { + CMtDecThread *t = &p->threads[i]; + if (t->inBuf) + MtDecThread_FreeInBufs(t); + } + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + + p->allocatedBufsSize = p->inBufSize; + } + + MtProgress_Init(&p->mtProgress, p->progress); + + // RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent)) + p->exitThread = False; + p->exitThreadWRes = 0; + + { + WRes wres; + SRes sres; + CMtDecThread *nextThread = &p->threads[p->numStartedThreads++]; + // wres = MtDecThread_CreateAndStart(nextThread); + wres = MtDecThread_CreateEvents(nextThread); + if (wres == 0) { wres = Event_Set(&nextThread->canWrite); + if (wres == 0) { wres = Event_Set(&nextThread->canRead); + if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread); + wres = (WRes)(UINT_PTR)res; + if (wres != 0) + { + p->needContinue = False; + MtDec_CloseThreads(p); + }}}} + + // wres = 17; // for test + // wres = Event_Wait(&p->finishedEvent); + + sres = MY_SRes_HRESULT_FROM_WRes(wres); + + if (sres != 0) + p->threadingErrorSRes = sres; + + if ( + // wres == 0 + // wres != 0 + // || p->mtc.codeRes == SZ_ERROR_MEM + p->isAllocError + || p->threadingErrorSRes != SZ_OK + || p->overflow) + { + // p->needContinue = True; + } + else + p->needContinue = False; + + if (p->needContinue) + return SZ_OK; + + // if (sres != SZ_OK) + return sres; + // return SZ_ERROR_FAIL; + } +} + +#endif + +#undef PRF diff --git a/libraries/lzma/C/MtDec.h b/libraries/lzma/C/MtDec.h new file mode 100644 index 0000000000..c28e8d9acf --- /dev/null +++ b/libraries/lzma/C/MtDec.h @@ -0,0 +1,202 @@ +/* MtDec.h -- Multi-thread Decoder +2023-04-02 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_MT_DEC_H +#define ZIP7_INC_MT_DEC_H + +#include "7zTypes.h" + +#ifndef Z7_ST +#include "Threads.h" +#endif + +EXTERN_C_BEGIN + +#ifndef Z7_ST + +#ifndef Z7_ST + #define MTDEC_THREADS_MAX 32 +#else + #define MTDEC_THREADS_MAX 1 +#endif + + +typedef struct +{ + ICompressProgressPtr progress; + SRes res; + UInt64 totalInSize; + UInt64 totalOutSize; + CCriticalSection cs; +} CMtProgress; + +void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress); +SRes MtProgress_Progress_ST(CMtProgress *p); +SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize); +SRes MtProgress_GetError(CMtProgress *p); +void MtProgress_SetError(CMtProgress *p, SRes res); + +struct CMtDec; + +typedef struct +{ + struct CMtDec_ *mtDec; + unsigned index; + void *inBuf; + + size_t inDataSize_Start; // size of input data in start block + UInt64 inDataSize; // total size of input data in all blocks + + CThread thread; + CAutoResetEvent canRead; + CAutoResetEvent canWrite; + void *allocaPtr; +} CMtDecThread; + +void MtDecThread_FreeInBufs(CMtDecThread *t); + + +typedef enum +{ + MTDEC_PARSE_CONTINUE, // continue this block with more input data + MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread + MTDEC_PARSE_NEW, // new block + MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue) +} EMtDecParseState; + +typedef struct +{ + // in + int startCall; + const Byte *src; + size_t srcSize; + // in : (srcSize == 0) is allowed + // out : it's allowed to return less that actually was used ? + int srcFinished; + + // out + EMtDecParseState state; + BoolInt canCreateNewThread; + UInt64 outPos; // check it (size_t) +} CMtDecCallbackInfo; + + +typedef struct +{ + void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci); + + // PreCode() and Code(): + // (SRes_return_result != SZ_OK) means stop decoding, no need another blocks + SRes (*PreCode)(void *p, unsigned coderIndex); + SRes (*Code)(void *p, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop); + // stop - means stop another Code calls + + + /* Write() must be called, if Parse() was called + set (needWrite) if + { + && (was not interrupted by progress) + && (was not interrupted in previous block) + } + + out: + if (*needContinue), decoder still need to continue decoding with new iteration, + even after MTDEC_PARSE_END + if (*canRecode), we didn't flush current block data, so we still can decode current block later. + */ + SRes (*Write)(void *p, unsigned coderIndex, + BoolInt needWriteToStream, + const Byte *src, size_t srcSize, BoolInt isCross, + // int srcFinished, + BoolInt *needContinue, + BoolInt *canRecode); + +} IMtDecCallback2; + + + +typedef struct CMtDec_ +{ + /* input variables */ + + size_t inBufSize; /* size of input block */ + unsigned numThreadsMax; + // size_t inBlockMax; + unsigned numThreadsMax_2; + + ISeqInStreamPtr inStream; + // const Byte *inData; + // size_t inDataSize; + + ICompressProgressPtr progress; + ISzAllocPtr alloc; + + IMtDecCallback2 *mtCallback; + void *mtCallbackObject; + + + /* internal variables */ + + size_t allocatedBufsSize; + + BoolInt exitThread; + WRes exitThreadWRes; + + UInt64 blockIndex; + BoolInt isAllocError; + BoolInt overflow; + SRes threadingErrorSRes; + + BoolInt needContinue; + + // CAutoResetEvent finishedEvent; + + SRes readRes; + SRes codeRes; + + BoolInt wasInterrupted; + + unsigned numStartedThreads_Limit; + unsigned numStartedThreads; + + Byte *crossBlock; + size_t crossStart; + size_t crossEnd; + UInt64 readProcessed; + BoolInt readWasFinished; + UInt64 inProcessed; + + unsigned filledThreadStart; + unsigned numFilledThreads; + + #ifndef Z7_ST + BoolInt needInterrupt; + UInt64 interruptIndex; + CMtProgress mtProgress; + CMtDecThread threads[MTDEC_THREADS_MAX]; + #endif +} CMtDec; + + +void MtDec_Construct(CMtDec *p); +void MtDec_Destruct(CMtDec *p); + +/* +MtDec_Code() returns: + SZ_OK - in most cases + MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function +*/ + +SRes MtDec_Code(CMtDec *p); +Byte *MtDec_GetCrossBuff(CMtDec *p); + +int MtDec_PrepareRead(CMtDec *p); +const Byte *MtDec_Read(CMtDec *p, size_t *inLim); + +#endif + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/Ppmd.h b/libraries/lzma/C/Ppmd.h index b198792087..66b26266ff 100644 --- a/libraries/lzma/C/Ppmd.h +++ b/libraries/lzma/C/Ppmd.h @@ -1,9 +1,9 @@ /* Ppmd.h -- PPMD codec common code -2021-04-13 : Igor Pavlov : Public domain +2023-03-05 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ -#ifndef __PPMD_H -#define __PPMD_H +#ifndef ZIP7_INC_PPMD_H +#define ZIP7_INC_PPMD_H #include "CpuArch.h" @@ -48,8 +48,10 @@ typedef struct Byte Count; /* Count to next change of Shift */ } CPpmd_See; -#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ - { (p)->Summ = (UInt16)((p)->Summ << 1); (p)->Count = (Byte)(3 << (p)->Shift++); } +#define Ppmd_See_UPDATE(p) \ + { if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ + { (p)->Summ = (UInt16)((p)->Summ << 1); \ + (p)->Count = (Byte)(3 << (p)->Shift++); }} typedef struct diff --git a/libraries/lzma/C/Ppmd7.c b/libraries/lzma/C/Ppmd7.c index cf401cb37c..6e1307e2d3 100644 --- a/libraries/lzma/C/Ppmd7.c +++ b/libraries/lzma/C/Ppmd7.c @@ -1,5 +1,5 @@ /* Ppmd7.c -- PPMdH codec -2021-04-13 : Igor Pavlov : Public domain +2023-04-02 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Precomp.h" @@ -14,7 +14,7 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ MY_ALIGN(16) static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; MY_ALIGN(16) -static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; +static const UInt16 PPMD7_kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; #define MAX_FREQ 124 #define UNIT_SIZE 12 @@ -33,7 +33,7 @@ static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) #define SUFFIX(ctx) CTX((ctx)->Suffix) -typedef CPpmd7_Context * CTX_PTR; +typedef CPpmd7_Context * PPMD7_CTX_PTR; struct CPpmd7_Node_; @@ -107,14 +107,14 @@ BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc) // ---------- Internal Memory Allocator ---------- /* We can use CPpmd7_Node in list of free units (as in Ppmd8) - But we still need one additional list walk pass in GlueFreeBlocks(). - So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in InsertNode() / RemoveNode() + But we still need one additional list walk pass in Ppmd7_GlueFreeBlocks(). + So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in Ppmd7_InsertNode() / Ppmd7_RemoveNode() */ #define EMPTY_NODE 0 -static void InsertNode(CPpmd7 *p, void *node, unsigned indx) +static void Ppmd7_InsertNode(CPpmd7 *p, void *node, unsigned indx) { *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)p->FreeList[indx]; @@ -124,7 +124,7 @@ static void InsertNode(CPpmd7 *p, void *node, unsigned indx) } -static void *RemoveNode(CPpmd7 *p, unsigned indx) +static void *Ppmd7_RemoveNode(CPpmd7 *p, unsigned indx) { CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); p->FreeList[indx] = *node; @@ -134,32 +134,32 @@ static void *RemoveNode(CPpmd7 *p, unsigned indx) } -static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) +static void Ppmd7_SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) { unsigned i, nu = I2U(oldIndx) - I2U(newIndx); ptr = (Byte *)ptr + U2B(I2U(newIndx)); if (I2U(i = U2I(nu)) != nu) { unsigned k = I2U(--i); - InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); + Ppmd7_InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); } - InsertNode(p, ptr, i); + Ppmd7_InsertNode(p, ptr, i); } /* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */ -typedef union _CPpmd7_Node_Union +typedef union { CPpmd7_Node Node; CPpmd7_Node_Ref NextRef; } CPpmd7_Node_Union; -/* Original PPmdH (Ppmd7) code uses doubly linked list in GlueFreeBlocks() +/* Original PPmdH (Ppmd7) code uses doubly linked list in Ppmd7_GlueFreeBlocks() we use single linked list similar to Ppmd8 code */ -static void GlueFreeBlocks(CPpmd7 *p) +static void Ppmd7_GlueFreeBlocks(CPpmd7 *p) { /* we use first UInt16 field of 12-bytes UNITs as record type stamp @@ -239,27 +239,27 @@ static void GlueFreeBlocks(CPpmd7 *p) if (nu == 0) continue; for (; nu > 128; nu -= 128, node += 128) - InsertNode(p, node, PPMD_NUM_INDEXES - 1); + Ppmd7_InsertNode(p, node, PPMD_NUM_INDEXES - 1); if (I2U(i = U2I(nu)) != nu) { unsigned k = I2U(--i); - InsertNode(p, node + k, (unsigned)nu - k - 1); + Ppmd7_InsertNode(p, node + k, (unsigned)nu - k - 1); } - InsertNode(p, node, i); + Ppmd7_InsertNode(p, node, i); } } -MY_NO_INLINE -static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) +Z7_NO_INLINE +static void *Ppmd7_AllocUnitsRare(CPpmd7 *p, unsigned indx) { unsigned i; if (p->GlueCount == 0) { - GlueFreeBlocks(p); + Ppmd7_GlueFreeBlocks(p); if (p->FreeList[indx] != 0) - return RemoveNode(p, indx); + return Ppmd7_RemoveNode(p, indx); } i = indx; @@ -277,17 +277,17 @@ static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) while (p->FreeList[i] == 0); { - void *block = RemoveNode(p, i); - SplitBlock(p, block, i, indx); + void *block = Ppmd7_RemoveNode(p, i); + Ppmd7_SplitBlock(p, block, i, indx); return block; } } -static void *AllocUnits(CPpmd7 *p, unsigned indx) +static void *Ppmd7_AllocUnits(CPpmd7 *p, unsigned indx) { if (p->FreeList[indx] != 0) - return RemoveNode(p, indx); + return Ppmd7_RemoveNode(p, indx); { UInt32 numBytes = U2B(I2U(indx)); Byte *lo = p->LoUnit; @@ -297,11 +297,11 @@ static void *AllocUnits(CPpmd7 *p, unsigned indx) return lo; } } - return AllocUnitsRare(p, indx); + return Ppmd7_AllocUnitsRare(p, indx); } -#define MyMem12Cpy(dest, src, num) \ +#define MEM_12_CPY(dest, src, num) \ { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } @@ -315,12 +315,12 @@ static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU return oldPtr; if (p->FreeList[i1] != 0) { - void *ptr = RemoveNode(p, i1); - MyMem12Cpy(ptr, oldPtr, newNU); - InsertNode(p, oldPtr, i0); + void *ptr = Ppmd7_RemoveNode(p, i1); + MEM_12_CPY(ptr, oldPtr, newNU) + Ppmd7_InsertNode(p, oldPtr, i0); return ptr; } - SplitBlock(p, oldPtr, i0, i1); + Ppmd7_SplitBlock(p, oldPtr, i0, i1); return oldPtr; } */ @@ -329,14 +329,14 @@ static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) { - Ppmd_SET_SUCCESSOR(p, v); + Ppmd_SET_SUCCESSOR(p, v) } -MY_NO_INLINE +Z7_NO_INLINE static -void RestartModel(CPpmd7 *p) +void Ppmd7_RestartModel(CPpmd7 *p) { unsigned i, k; @@ -352,8 +352,8 @@ void RestartModel(CPpmd7 *p) p->PrevSuccess = 0; { - CPpmd7_Context *mc = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ - CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ + CPpmd7_Context *mc = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ + CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* Ppmd7_AllocUnits(p, PPMD_NUM_INDEXES - 1); */ p->LoUnit += U2B(256 / 2); p->MaxContext = p->MinContext = mc; @@ -391,7 +391,7 @@ void RestartModel(CPpmd7 *p) { unsigned m; UInt16 *dest = p->BinSumm[i] + k; - UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); + const UInt16 val = (UInt16)(PPMD_BIN_SCALE - PPMD7_kInitBinEsc[k] / (i + 2)); for (m = 0; m < 64; m += 8) dest[m] = val; } @@ -423,13 +423,13 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) { p->MaxOrder = maxOrder; - RestartModel(p); + Ppmd7_RestartModel(p); } /* - CreateSuccessors() + Ppmd7_CreateSuccessors() It's called when (FoundState->Successor) is RAW-Successor, that is the link to position in Raw text. So we create Context records and write the links to @@ -445,10 +445,10 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) also it can return pointer to real context of same order, */ -MY_NO_INLINE -static CTX_PTR CreateSuccessors(CPpmd7 *p) +Z7_NO_INLINE +static PPMD7_CTX_PTR Ppmd7_CreateSuccessors(CPpmd7 *p) { - CTX_PTR c = p->MinContext; + PPMD7_CTX_PTR c = p->MinContext; CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); Byte newSym, newFreq; unsigned numPs = 0; @@ -522,15 +522,15 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p) do { - CTX_PTR c1; + PPMD7_CTX_PTR c1; /* = AllocContext(p); */ if (p->HiUnit != p->LoUnit) - c1 = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); + c1 = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); else if (p->FreeList[0] != 0) - c1 = (CTX_PTR)RemoveNode(p, 0); + c1 = (PPMD7_CTX_PTR)Ppmd7_RemoveNode(p, 0); else { - c1 = (CTX_PTR)AllocUnitsRare(p, 0); + c1 = (PPMD7_CTX_PTR)Ppmd7_AllocUnitsRare(p, 0); if (!c1) return NULL; } @@ -550,16 +550,16 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p) -#define SwapStates(s) \ +#define SWAP_STATES(s) \ { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; } void Ppmd7_UpdateModel(CPpmd7 *p); -MY_NO_INLINE +Z7_NO_INLINE void Ppmd7_UpdateModel(CPpmd7 *p) { CPpmd_Void_Ref maxSuccessor, minSuccessor; - CTX_PTR c, mc; + PPMD7_CTX_PTR c, mc; unsigned s0, ns; @@ -592,7 +592,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p) if (s[0].Freq >= s[-1].Freq) { - SwapStates(s); + SWAP_STATES(s) s--; } } @@ -610,10 +610,10 @@ void Ppmd7_UpdateModel(CPpmd7 *p) { /* MAX ORDER context */ /* (FoundState->Successor) is RAW-Successor. */ - p->MaxContext = p->MinContext = CreateSuccessors(p); + p->MaxContext = p->MinContext = Ppmd7_CreateSuccessors(p); if (!p->MinContext) { - RestartModel(p); + Ppmd7_RestartModel(p); return; } SetSuccessor(p->FoundState, REF(p->MinContext)); @@ -629,7 +629,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p) p->Text = text; if (text >= p->UnitsStart) { - RestartModel(p); + Ppmd7_RestartModel(p); return; } maxSuccessor = REF(text); @@ -645,10 +645,10 @@ void Ppmd7_UpdateModel(CPpmd7 *p) if (minSuccessor <= maxSuccessor) { // minSuccessor is RAW-Successor. So we will create real contexts records: - CTX_PTR cs = CreateSuccessors(p); + PPMD7_CTX_PTR cs = Ppmd7_CreateSuccessors(p); if (!cs) { - RestartModel(p); + Ppmd7_RestartModel(p); return; } minSuccessor = REF(cs); @@ -715,16 +715,16 @@ void Ppmd7_UpdateModel(CPpmd7 *p) unsigned i = U2I(oldNU); if (i != U2I((size_t)oldNU + 1)) { - void *ptr = AllocUnits(p, i + 1); + void *ptr = Ppmd7_AllocUnits(p, i + 1); void *oldPtr; if (!ptr) { - RestartModel(p); + Ppmd7_RestartModel(p); return; } oldPtr = STATS(c); - MyMem12Cpy(ptr, oldPtr, oldNU); - InsertNode(p, oldPtr, i); + MEM_12_CPY(ptr, oldPtr, oldNU) + Ppmd7_InsertNode(p, oldPtr, i); c->Union4.Stats = STATS_REF(ptr); } } @@ -739,10 +739,10 @@ void Ppmd7_UpdateModel(CPpmd7 *p) else { // instead of One-symbol context we create 2-symbol context - CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); + CPpmd_State *s = (CPpmd_State*)Ppmd7_AllocUnits(p, 0); if (!s) { - RestartModel(p); + Ppmd7_RestartModel(p); return; } { @@ -795,8 +795,8 @@ void Ppmd7_UpdateModel(CPpmd7 *p) -MY_NO_INLINE -static void Rescale(CPpmd7 *p) +Z7_NO_INLINE +static void Ppmd7_Rescale(CPpmd7 *p) { unsigned i, adder, sumFreq, escFreq; CPpmd_State *stats = STATS(p->MinContext); @@ -885,7 +885,7 @@ static void Rescale(CPpmd7 *p) *s = *stats; s->Freq = (Byte)freq; // (freq <= 260 / 4) p->FoundState = s; - InsertNode(p, stats, U2I(n0)); + Ppmd7_InsertNode(p, stats, U2I(n0)); return; } @@ -899,13 +899,13 @@ static void Rescale(CPpmd7 *p) { if (p->FreeList[i1] != 0) { - void *ptr = RemoveNode(p, i1); + void *ptr = Ppmd7_RemoveNode(p, i1); p->MinContext->Union4.Stats = STATS_REF(ptr); - MyMem12Cpy(ptr, (const void *)stats, n1); - InsertNode(p, stats, i0); + MEM_12_CPY(ptr, (const void *)stats, n1) + Ppmd7_InsertNode(p, stats, i0); } else - SplitBlock(p, stats, i0, i1); + Ppmd7_SplitBlock(p, stats, i0, i1); } } } @@ -948,9 +948,9 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) } -static void NextContext(CPpmd7 *p) +static void Ppmd7_NextContext(CPpmd7 *p) { - CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); + PPMD7_CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); if (p->OrderFall == 0 && (const Byte *)c > p->Text) p->MaxContext = p->MinContext = c; else @@ -967,12 +967,12 @@ void Ppmd7_Update1(CPpmd7 *p) s->Freq = (Byte)freq; if (freq > s[-1].Freq) { - SwapStates(s); + SWAP_STATES(s) p->FoundState = --s; if (freq > MAX_FREQ) - Rescale(p); + Ppmd7_Rescale(p); } - NextContext(p); + Ppmd7_NextContext(p); } @@ -988,8 +988,8 @@ void Ppmd7_Update1_0(CPpmd7 *p) freq += 4; s->Freq = (Byte)freq; if (freq > MAX_FREQ) - Rescale(p); - NextContext(p); + Ppmd7_Rescale(p); + Ppmd7_NextContext(p); } @@ -1000,7 +1000,7 @@ void Ppmd7_UpdateBin(CPpmd7 *p) p->FoundState->Freq = (Byte)(freq + (freq < 128)); p->PrevSuccess = 1; p->RunLength++; - NextContext(p); + Ppmd7_NextContext(p); } */ @@ -1013,7 +1013,7 @@ void Ppmd7_Update2(CPpmd7 *p) p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); s->Freq = (Byte)freq; if (freq > MAX_FREQ) - Rescale(p); + Ppmd7_Rescale(p); Ppmd7_UpdateModel(p); } @@ -1042,8 +1042,8 @@ Last UNIT of array at offset (Size - 12) is root order-0 CPpmd7_Context record. The code can free UNITs memory blocks that were allocated to store CPpmd_State vectors. The code doesn't free UNITs allocated for CPpmd7_Context records. -The code calls RestartModel(), when there is no free memory for allocation. -And RestartModel() changes the state to orignal start state, with full free block. +The code calls Ppmd7_RestartModel(), when there is no free memory for allocation. +And Ppmd7_RestartModel() changes the state to orignal start state, with full free block. The code allocates UNITs with the following order: @@ -1051,14 +1051,14 @@ The code allocates UNITs with the following order: Allocation of 1 UNIT for Context record - from free space (HiUnit) down to (LoUnit) - from FreeList[0] - - AllocUnitsRare() + - Ppmd7_AllocUnitsRare() -AllocUnits() for CPpmd_State vectors: +Ppmd7_AllocUnits() for CPpmd_State vectors: - from FreeList[i] - from free space (LoUnit) up to (HiUnit) - - AllocUnitsRare() + - Ppmd7_AllocUnitsRare() -AllocUnitsRare() +Ppmd7_AllocUnitsRare() - if (GlueCount == 0) { Glue lists, GlueCount = 255, allocate from FreeList[i]] } - loop for all higher sized FreeList[...] lists @@ -1093,8 +1093,8 @@ The PPMd code tries to fulfill the condition: We have (Sum(Stats[].Freq) <= 256 * 124), because of (MAX_FREQ = 124) So (4 = 128 - 124) is average reserve for Escape_Freq for each symbol. If (CPpmd_State::Freq) is not aligned for 4, the reserve can be 5, 6 or 7. -SummFreq and Escape_Freq can be changed in Rescale() and *Update*() functions. -Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Rescale() for +SummFreq and Escape_Freq can be changed in Ppmd7_Rescale() and *Update*() functions. +Ppmd7_Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Ppmd7_Rescale() for max-order context. When the PPMd code still break (Total <= RC::Range) condition in range coder, @@ -1102,3 +1102,21 @@ we have two ways to resolve that problem: 1) we can report error, if we want to keep compatibility with original PPMd code that has no fix for such cases. 2) we can reduce (Total) value to (RC::Range) by reducing (Escape_Freq) part of (Total) value. */ + +#undef MAX_FREQ +#undef UNIT_SIZE +#undef U2B +#undef U2I +#undef I2U +#undef I2U_UInt16 +#undef REF +#undef STATS_REF +#undef CTX +#undef STATS +#undef ONE_STATE +#undef SUFFIX +#undef NODE +#undef EMPTY_NODE +#undef MEM_12_CPY +#undef SUCCESSOR +#undef SWAP_STATES diff --git a/libraries/lzma/C/Ppmd7.h b/libraries/lzma/C/Ppmd7.h index d31809aebd..d9eb326d60 100644 --- a/libraries/lzma/C/Ppmd7.h +++ b/libraries/lzma/C/Ppmd7.h @@ -1,11 +1,11 @@ /* Ppmd7.h -- Ppmd7 (PPMdH) compression codec -2021-04-13 : Igor Pavlov : Public domain +2023-04-02 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001): Dmitry Shkarin : Public domain */ -#ifndef __PPMD7_H -#define __PPMD7_H +#ifndef ZIP7_INC_PPMD7_H +#define ZIP7_INC_PPMD7_H #include "Ppmd.h" @@ -55,7 +55,7 @@ typedef struct UInt32 Range; UInt32 Code; UInt32 Low; - IByteIn *Stream; + IByteInPtr Stream; } CPpmd7_RangeDec; @@ -66,7 +66,7 @@ typedef struct // Byte _dummy_[3]; UInt64 Low; UInt64 CacheSize; - IByteOut *Stream; + IByteOutPtr Stream; } CPpmd7z_RangeEnc; diff --git a/libraries/lzma/C/Ppmd7Dec.c b/libraries/lzma/C/Ppmd7Dec.c index 55d74ff9dc..832382828d 100644 --- a/libraries/lzma/C/Ppmd7Dec.c +++ b/libraries/lzma/C/Ppmd7Dec.c @@ -1,5 +1,5 @@ /* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder -2021-04-13 : Igor Pavlov : Public domain +2023-04-02 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001): Dmitry Shkarin : Public domain */ @@ -8,7 +8,7 @@ This code is based on: #include "Ppmd7.h" -#define kTopValue (1 << 24) +#define kTopValue ((UInt32)1 << 24) #define READ_BYTE(p) IByteIn_Read((p)->Stream) @@ -37,9 +37,9 @@ BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p) #define R (&p->rc.dec) -MY_FORCE_INLINE -// MY_NO_INLINE -static void RangeDec_Decode(CPpmd7 *p, UInt32 start, UInt32 size) +Z7_FORCE_INLINE +// Z7_NO_INLINE +static void Ppmd7z_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size) { @@ -48,18 +48,18 @@ static void RangeDec_Decode(CPpmd7 *p, UInt32 start, UInt32 size) RC_NORM_LOCAL(R) } -#define RC_Decode(start, size) RangeDec_Decode(p, start, size); -#define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R) -#define RC_GetThreshold(total) (R->Code / (R->Range /= (total))) +#define RC_Decode(start, size) Ppmd7z_RD_Decode(p, start, size); +#define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R) +#define RC_GetThreshold(total) (R->Code / (R->Range /= (total))) #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) -typedef CPpmd7_Context * CTX_PTR; +// typedef CPpmd7_Context * CTX_PTR; #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) void Ppmd7_UpdateModel(CPpmd7 *p); #define MASK(sym) ((unsigned char *)charMask)[sym] -// MY_FORCE_INLINE +// Z7_FORCE_INLINE // static int Ppmd7z_DecodeSymbol(CPpmd7 *p) { @@ -70,7 +70,7 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); unsigned i; UInt32 count, hiCnt; - UInt32 summFreq = p->MinContext->Union2.SummFreq; + const UInt32 summFreq = p->MinContext->Union2.SummFreq; @@ -81,7 +81,7 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) if ((Int32)(count -= s->Freq) < 0) { Byte sym; - RC_DecodeFinal(0, s->Freq); + RC_DecodeFinal(0, s->Freq) p->FoundState = s; sym = s->Symbol; Ppmd7_Update1_0(p); @@ -96,7 +96,7 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) if ((Int32)(count -= (++s)->Freq) < 0) { Byte sym; - RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq); + RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq) p->FoundState = s; sym = s->Symbol; Ppmd7_Update1(p); @@ -109,10 +109,10 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) return PPMD7_SYM_ERROR; hiCnt -= count; - RC_Decode(hiCnt, summFreq - hiCnt); + RC_Decode(hiCnt, summFreq - hiCnt) p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); - PPMD_SetAllBitsIn256Bytes(charMask); + PPMD_SetAllBitsIn256Bytes(charMask) // i = p->MinContext->NumStats - 1; // do { MASK((--s)->Symbol) = 0; } while (--i); { @@ -152,7 +152,7 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) // Ppmd7_UpdateBin(p); { unsigned freq = s->Freq; - CTX_PTR c = CTX(SUCCESSOR(s)); + CPpmd7_Context *c = CTX(SUCCESSOR(s)); sym = s->Symbol; p->FoundState = s; p->PrevSuccess = 1; @@ -176,7 +176,7 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) R->Range -= size0; RC_NORM_LOCAL(R) - PPMD_SetAllBitsIn256Bytes(charMask); + PPMD_SetAllBitsIn256Bytes(charMask) MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; p->PrevSuccess = 0; } @@ -245,13 +245,13 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) { count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; - }; + } } s--; - RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq); + RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq) // new (see->Summ) value can overflow over 16-bits in some rare cases - Ppmd_See_Update(see); + Ppmd_See_UPDATE(see) p->FoundState = s; sym = s->Symbol; Ppmd7_Update2(p); @@ -261,7 +261,7 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) if (count >= freqSum) return PPMD7_SYM_ERROR; - RC_Decode(hiCnt, freqSum - hiCnt); + RC_Decode(hiCnt, freqSum - hiCnt) // We increase (see->Summ) for sum of Freqs of all non_Masked symbols. // new (see->Summ) value can overflow over 16-bits in some rare cases @@ -295,3 +295,18 @@ Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim) return buf; } */ + +#undef kTopValue +#undef READ_BYTE +#undef RC_NORM_BASE +#undef RC_NORM_1 +#undef RC_NORM +#undef RC_NORM_LOCAL +#undef RC_NORM_REMOTE +#undef R +#undef RC_Decode +#undef RC_DecodeFinal +#undef RC_GetThreshold +#undef CTX +#undef SUCCESSOR +#undef MASK diff --git a/libraries/lzma/C/Ppmd7Enc.c b/libraries/lzma/C/Ppmd7Enc.c new file mode 100644 index 0000000000..41106bab45 --- /dev/null +++ b/libraries/lzma/C/Ppmd7Enc.c @@ -0,0 +1,338 @@ +/* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder +2023-04-02 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001): Dmitry Shkarin : Public domain */ + + +#include "Precomp.h" + +#include "Ppmd7.h" + +#define kTopValue ((UInt32)1 << 24) + +#define R (&p->rc.enc) + +void Ppmd7z_Init_RangeEnc(CPpmd7 *p) +{ + R->Low = 0; + R->Range = 0xFFFFFFFF; + R->Cache = 0; + R->CacheSize = 1; +} + +Z7_NO_INLINE +static void Ppmd7z_RangeEnc_ShiftLow(CPpmd7 *p) +{ + if ((UInt32)R->Low < (UInt32)0xFF000000 || (unsigned)(R->Low >> 32) != 0) + { + Byte temp = R->Cache; + do + { + IByteOut_Write(R->Stream, (Byte)(temp + (Byte)(R->Low >> 32))); + temp = 0xFF; + } + while (--R->CacheSize != 0); + R->Cache = (Byte)((UInt32)R->Low >> 24); + } + R->CacheSize++; + R->Low = (UInt32)((UInt32)R->Low << 8); +} + +#define RC_NORM_BASE(p) if (R->Range < kTopValue) { R->Range <<= 8; Ppmd7z_RangeEnc_ShiftLow(p); +#define RC_NORM_1(p) RC_NORM_BASE(p) } +#define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }} + +// we must use only one type of Normalization from two: LOCAL or REMOTE +#define RC_NORM_LOCAL(p) // RC_NORM(p) +#define RC_NORM_REMOTE(p) RC_NORM(p) + +/* +#define Ppmd7z_RangeEnc_Encode(p, start, _size_) \ + { UInt32 size = _size_; \ + R->Low += start * R->Range; \ + R->Range *= size; \ + RC_NORM_LOCAL(p); } +*/ + +Z7_FORCE_INLINE +// Z7_NO_INLINE +static void Ppmd7z_RangeEnc_Encode(CPpmd7 *p, UInt32 start, UInt32 size) +{ + R->Low += start * R->Range; + R->Range *= size; + RC_NORM_LOCAL(p) +} + +void Ppmd7z_Flush_RangeEnc(CPpmd7 *p) +{ + unsigned i; + for (i = 0; i < 5; i++) + Ppmd7z_RangeEnc_ShiftLow(p); +} + + + +#define RC_Encode(start, size) Ppmd7z_RangeEnc_Encode(p, start, size); +#define RC_EncodeFinal(start, size) RC_Encode(start, size) RC_NORM_REMOTE(p) + +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +#define SUFFIX(ctx) CTX((ctx)->Suffix) +// typedef CPpmd7_Context * CTX_PTR; +#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) + +void Ppmd7_UpdateModel(CPpmd7 *p); + +#define MASK(sym) ((unsigned char *)charMask)[sym] + +Z7_FORCE_INLINE +static +void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol) +{ + size_t charMask[256 / sizeof(size_t)]; + + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + UInt32 sum; + unsigned i; + + + + + R->Range /= p->MinContext->Union2.SummFreq; + + if (s->Symbol == symbol) + { + // R->Range /= p->MinContext->Union2.SummFreq; + RC_EncodeFinal(0, s->Freq) + p->FoundState = s; + Ppmd7_Update1_0(p); + return; + } + p->PrevSuccess = 0; + sum = s->Freq; + i = (unsigned)p->MinContext->NumStats - 1; + do + { + if ((++s)->Symbol == symbol) + { + // R->Range /= p->MinContext->Union2.SummFreq; + RC_EncodeFinal(sum, s->Freq) + p->FoundState = s; + Ppmd7_Update1(p); + return; + } + sum += s->Freq; + } + while (--i); + + // R->Range /= p->MinContext->Union2.SummFreq; + RC_Encode(sum, p->MinContext->Union2.SummFreq - sum) + + p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); + PPMD_SetAllBitsIn256Bytes(charMask) + // MASK(s->Symbol) = 0; + // i = p->MinContext->NumStats - 1; + // do { MASK((--s)->Symbol) = 0; } while (--i); + { + CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); + MASK(s->Symbol) = 0; + do + { + unsigned sym0 = s2[0].Symbol; + unsigned sym1 = s2[1].Symbol; + s2 += 2; + MASK(sym0) = 0; + MASK(sym1) = 0; + } + while (s2 < s); + } + } + else + { + UInt16 *prob = Ppmd7_GetBinSumm(p); + CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); + UInt32 pr = *prob; + const UInt32 bound = (R->Range >> 14) * pr; + pr = PPMD_UPDATE_PROB_1(pr); + if (s->Symbol == symbol) + { + *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); + // RangeEnc_EncodeBit_0(p, bound); + R->Range = bound; + RC_NORM_1(p) + + // p->FoundState = s; + // Ppmd7_UpdateBin(p); + { + const unsigned freq = s->Freq; + CPpmd7_Context *c = CTX(SUCCESSOR(s)); + p->FoundState = s; + p->PrevSuccess = 1; + p->RunLength++; + s->Freq = (Byte)(freq + (freq < 128)); + // NextContext(p); + if (p->OrderFall == 0 && (const Byte *)c > p->Text) + p->MaxContext = p->MinContext = c; + else + Ppmd7_UpdateModel(p); + } + return; + } + + *prob = (UInt16)pr; + p->InitEsc = p->ExpEscape[pr >> 10]; + // RangeEnc_EncodeBit_1(p, bound); + R->Low += bound; + R->Range -= bound; + RC_NORM_LOCAL(p) + + PPMD_SetAllBitsIn256Bytes(charMask) + MASK(s->Symbol) = 0; + p->PrevSuccess = 0; + } + + for (;;) + { + CPpmd_See *see; + CPpmd_State *s; + UInt32 sum, escFreq; + CPpmd7_Context *mc; + unsigned i, numMasked; + + RC_NORM_REMOTE(p) + + mc = p->MinContext; + numMasked = mc->NumStats; + + do + { + p->OrderFall++; + if (!mc->Suffix) + return; /* EndMarker (symbol = -1) */ + mc = Ppmd7_GetContext(p, mc->Suffix); + i = mc->NumStats; + } + while (i == numMasked); + + p->MinContext = mc; + + // see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); + { + if (i != 256) + { + unsigned nonMasked = i - numMasked; + see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + + p->HiBitsFlag + + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - i) + + 2 * (unsigned)(mc->Union2.SummFreq < 11 * i) + + 4 * (unsigned)(numMasked > nonMasked); + { + // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ + unsigned summ = (UInt16)see->Summ; // & 0xFFFF + unsigned r = (summ >> see->Shift); + see->Summ = (UInt16)(summ - r); + escFreq = r + (r == 0); + } + } + else + { + see = &p->DummySee; + escFreq = 1; + } + } + + s = Ppmd7_GetStats(p, mc); + sum = 0; + // i = mc->NumStats; + + do + { + const unsigned cur = s->Symbol; + if ((int)cur == symbol) + { + const UInt32 low = sum; + const UInt32 freq = s->Freq; + unsigned num2; + + Ppmd_See_UPDATE(see) + p->FoundState = s; + sum += escFreq; + + num2 = i / 2; + i &= 1; + sum += freq & (0 - (UInt32)i); + if (num2 != 0) + { + s += i; + for (;;) + { + unsigned sym0 = s[0].Symbol; + unsigned sym1 = s[1].Symbol; + s += 2; + sum += (s[-2].Freq & (unsigned)(MASK(sym0))); + sum += (s[-1].Freq & (unsigned)(MASK(sym1))); + if (--num2 == 0) + break; + } + } + + + R->Range /= sum; + RC_EncodeFinal(low, freq) + Ppmd7_Update2(p); + return; + } + sum += (s->Freq & (unsigned)(MASK(cur))); + s++; + } + while (--i); + + { + const UInt32 total = sum + escFreq; + see->Summ = (UInt16)(see->Summ + total); + + R->Range /= total; + RC_Encode(sum, escFreq) + } + + { + const CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); + s--; + MASK(s->Symbol) = 0; + do + { + const unsigned sym0 = s2[0].Symbol; + const unsigned sym1 = s2[1].Symbol; + s2 += 2; + MASK(sym0) = 0; + MASK(sym1) = 0; + } + while (s2 < s); + } + } +} + + +void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim) +{ + for (; buf < lim; buf++) + { + Ppmd7z_EncodeSymbol(p, *buf); + } +} + +#undef kTopValue +#undef WRITE_BYTE +#undef RC_NORM_BASE +#undef RC_NORM_1 +#undef RC_NORM +#undef RC_NORM_LOCAL +#undef RC_NORM_REMOTE +#undef R +#undef RC_Encode +#undef RC_EncodeFinal +#undef SUFFIX +#undef CTX +#undef SUCCESSOR +#undef MASK diff --git a/libraries/lzma/C/Precomp.h b/libraries/lzma/C/Precomp.h index e8ff8b40e8..69afb2ffd1 100644 --- a/libraries/lzma/C/Precomp.h +++ b/libraries/lzma/C/Precomp.h @@ -1,8 +1,8 @@ /* Precomp.h -- StdAfx -2013-11-12 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __7Z_PRECOMP_H -#define __7Z_PRECOMP_H +#ifndef ZIP7_INC_PRECOMP_H +#define ZIP7_INC_PRECOMP_H #include "Compiler.h" /* #include "7zTypes.h" */ diff --git a/libraries/lzma/C/RotateDefs.h b/libraries/lzma/C/RotateDefs.h new file mode 100644 index 0000000000..c16b4f8e6a --- /dev/null +++ b/libraries/lzma/C/RotateDefs.h @@ -0,0 +1,50 @@ +/* RotateDefs.h -- Rotate functions +2023-06-18 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_ROTATE_DEFS_H +#define ZIP7_INC_ROTATE_DEFS_H + +#ifdef _MSC_VER + +#include + +/* don't use _rotl with old MINGW. It can insert slow call to function. */ + +/* #if (_MSC_VER >= 1200) */ +#pragma intrinsic(_rotl) +#pragma intrinsic(_rotr) +/* #endif */ + +#define rotlFixed(x, n) _rotl((x), (n)) +#define rotrFixed(x, n) _rotr((x), (n)) + +#if (_MSC_VER >= 1300) +#define Z7_ROTL64(x, n) _rotl64((x), (n)) +#define Z7_ROTR64(x, n) _rotr64((x), (n)) +#else +#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) +#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) +#endif + +#else + +/* new compilers can translate these macros to fast commands. */ + +#if defined(__clang__) && (__clang_major__ >= 4) \ + || defined(__GNUC__) && (__GNUC__ >= 5) +/* GCC 4.9.0 and clang 3.5 can recognize more correct version: */ +#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (-(n) & 31))) +#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (-(n) & 31))) +#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (-(n) & 63))) +#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (-(n) & 63))) +#else +/* for old GCC / clang: */ +#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) +#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) +#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) +#endif + +#endif + +#endif diff --git a/libraries/lzma/C/Sha256.c b/libraries/lzma/C/Sha256.c new file mode 100644 index 0000000000..018cf6f4b4 --- /dev/null +++ b/libraries/lzma/C/Sha256.c @@ -0,0 +1,516 @@ +/* Sha256.c -- SHA-256 Hash +2023-04-02 : Igor Pavlov : Public domain +This code is based on public domain code from Wei Dai's Crypto++ library. */ + +#include "Precomp.h" + +#include + +#include "CpuArch.h" +#include "RotateDefs.h" +#include "Sha256.h" + +#if defined(_MSC_VER) && (_MSC_VER < 1900) +// #define USE_MY_MM +#endif + +#ifdef MY_CPU_X86_OR_AMD64 + #ifdef _MSC_VER + #if _MSC_VER >= 1200 + #define Z7_COMPILER_SHA256_SUPPORTED + #endif + #elif defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define Z7_COMPILER_SHA256_SUPPORTED + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 8) // fix that check + #define Z7_COMPILER_SHA256_SUPPORTED + #endif + #elif defined(__INTEL_COMPILER) + #if (__INTEL_COMPILER >= 1800) // fix that check + #define Z7_COMPILER_SHA256_SUPPORTED + #endif + #endif +#elif defined(MY_CPU_ARM_OR_ARM64) + #ifdef _MSC_VER + #if _MSC_VER >= 1910 + #define Z7_COMPILER_SHA256_SUPPORTED + #endif + #elif defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define Z7_COMPILER_SHA256_SUPPORTED + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define Z7_COMPILER_SHA256_SUPPORTED + #endif + #endif +#endif + +void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); + +#ifdef Z7_COMPILER_SHA256_SUPPORTED + void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); + + static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS = Sha256_UpdateBlocks; + static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS_HW; + + #define SHA256_UPDATE_BLOCKS(p) p->func_UpdateBlocks +#else + #define SHA256_UPDATE_BLOCKS(p) Sha256_UpdateBlocks +#endif + + +BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo) +{ + SHA256_FUNC_UPDATE_BLOCKS func = Sha256_UpdateBlocks; + + #ifdef Z7_COMPILER_SHA256_SUPPORTED + if (algo != SHA256_ALGO_SW) + { + if (algo == SHA256_ALGO_DEFAULT) + func = g_SHA256_FUNC_UPDATE_BLOCKS; + else + { + if (algo != SHA256_ALGO_HW) + return False; + func = g_SHA256_FUNC_UPDATE_BLOCKS_HW; + if (!func) + return False; + } + } + #else + if (algo > 1) + return False; + #endif + + p->func_UpdateBlocks = func; + return True; +} + + +/* define it for speed optimization */ + +#ifdef Z7_SFX + #define STEP_PRE 1 + #define STEP_MAIN 1 +#else + #define STEP_PRE 2 + #define STEP_MAIN 4 + // #define Z7_SHA256_UNROLL +#endif + +#undef Z7_SHA256_BIG_W +#if STEP_MAIN != 16 + #define Z7_SHA256_BIG_W +#endif + + + + +void Sha256_InitState(CSha256 *p) +{ + p->count = 0; + p->state[0] = 0x6a09e667; + p->state[1] = 0xbb67ae85; + p->state[2] = 0x3c6ef372; + p->state[3] = 0xa54ff53a; + p->state[4] = 0x510e527f; + p->state[5] = 0x9b05688c; + p->state[6] = 0x1f83d9ab; + p->state[7] = 0x5be0cd19; +} + +void Sha256_Init(CSha256 *p) +{ + p->func_UpdateBlocks = + #ifdef Z7_COMPILER_SHA256_SUPPORTED + g_SHA256_FUNC_UPDATE_BLOCKS; + #else + NULL; + #endif + Sha256_InitState(p); +} + +#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22)) +#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25)) +#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) +#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + + +#define W_PRE(i) (W[(i) + (size_t)(j)] = GetBe32(data + ((size_t)(j) + i) * 4)) + +#define blk2_main(j, i) s1(w(j, (i)-2)) + w(j, (i)-7) + s0(w(j, (i)-15)) + +#ifdef Z7_SHA256_BIG_W + // we use +i instead of +(i) to change the order to solve CLANG compiler warning for signed/unsigned. + #define w(j, i) W[(size_t)(j) + i] + #define blk2(j, i) (w(j, i) = w(j, (i)-16) + blk2_main(j, i)) +#else + #if STEP_MAIN == 16 + #define w(j, i) W[(i) & 15] + #else + #define w(j, i) W[((size_t)(j) + (i)) & 15] + #endif + #define blk2(j, i) (w(j, i) += blk2_main(j, i)) +#endif + +#define W_MAIN(i) blk2(j, i) + + +#define T1(wx, i) \ + tmp = h + S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ + h = g; \ + g = f; \ + f = e; \ + e = d + tmp; \ + tmp += S0(a) + Maj(a, b, c); \ + d = c; \ + c = b; \ + b = a; \ + a = tmp; \ + +#define R1_PRE(i) T1( W_PRE, i) +#define R1_MAIN(i) T1( W_MAIN, i) + +#if (!defined(Z7_SHA256_UNROLL) || STEP_MAIN < 8) && (STEP_MAIN >= 4) +#define R2_MAIN(i) \ + R1_MAIN(i) \ + R1_MAIN(i + 1) \ + +#endif + + + +#if defined(Z7_SHA256_UNROLL) && STEP_MAIN >= 8 + +#define T4( a,b,c,d,e,f,g,h, wx, i) \ + h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ + tmp = h; \ + h += d; \ + d = tmp + S0(a) + Maj(a, b, c); \ + +#define R4( wx, i) \ + T4 ( a,b,c,d,e,f,g,h, wx, (i )); \ + T4 ( d,a,b,c,h,e,f,g, wx, (i+1)); \ + T4 ( c,d,a,b,g,h,e,f, wx, (i+2)); \ + T4 ( b,c,d,a,f,g,h,e, wx, (i+3)); \ + +#define R4_PRE(i) R4( W_PRE, i) +#define R4_MAIN(i) R4( W_MAIN, i) + + +#define T8( a,b,c,d,e,f,g,h, wx, i) \ + h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ + d += h; \ + h += S0(a) + Maj(a, b, c); \ + +#define R8( wx, i) \ + T8 ( a,b,c,d,e,f,g,h, wx, i ); \ + T8 ( h,a,b,c,d,e,f,g, wx, i+1); \ + T8 ( g,h,a,b,c,d,e,f, wx, i+2); \ + T8 ( f,g,h,a,b,c,d,e, wx, i+3); \ + T8 ( e,f,g,h,a,b,c,d, wx, i+4); \ + T8 ( d,e,f,g,h,a,b,c, wx, i+5); \ + T8 ( c,d,e,f,g,h,a,b, wx, i+6); \ + T8 ( b,c,d,e,f,g,h,a, wx, i+7); \ + +#define R8_PRE(i) R8( W_PRE, i) +#define R8_MAIN(i) R8( W_MAIN, i) + +#endif + +void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); + +// static +extern MY_ALIGN(64) +const UInt32 SHA256_K_ARRAY[64]; + +MY_ALIGN(64) +const UInt32 SHA256_K_ARRAY[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define K SHA256_K_ARRAY + + +Z7_NO_INLINE +void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks) +{ + UInt32 W + #ifdef Z7_SHA256_BIG_W + [64]; + #else + [16]; + #endif + + unsigned j; + + UInt32 a,b,c,d,e,f,g,h; + + #if !defined(Z7_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4) + UInt32 tmp; + #endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + while (numBlocks) + { + + for (j = 0; j < 16; j += STEP_PRE) + { + #if STEP_PRE > 4 + + #if STEP_PRE < 8 + R4_PRE(0); + #else + R8_PRE(0); + #if STEP_PRE == 16 + R8_PRE(8); + #endif + #endif + + #else + + R1_PRE(0) + #if STEP_PRE >= 2 + R1_PRE(1) + #if STEP_PRE >= 4 + R1_PRE(2) + R1_PRE(3) + #endif + #endif + + #endif + } + + for (j = 16; j < 64; j += STEP_MAIN) + { + #if defined(Z7_SHA256_UNROLL) && STEP_MAIN >= 8 + + #if STEP_MAIN < 8 + R4_MAIN(0) + #else + R8_MAIN(0) + #if STEP_MAIN == 16 + R8_MAIN(8) + #endif + #endif + + #else + + R1_MAIN(0) + #if STEP_MAIN >= 2 + R1_MAIN(1) + #if STEP_MAIN >= 4 + R2_MAIN(2) + #if STEP_MAIN >= 8 + R2_MAIN(4) + R2_MAIN(6) + #if STEP_MAIN >= 16 + R2_MAIN(8) + R2_MAIN(10) + R2_MAIN(12) + R2_MAIN(14) + #endif + #endif + #endif + #endif + #endif + } + + a += state[0]; state[0] = a; + b += state[1]; state[1] = b; + c += state[2]; state[2] = c; + d += state[3]; state[3] = d; + e += state[4]; state[4] = e; + f += state[5]; state[5] = f; + g += state[6]; state[6] = g; + h += state[7]; state[7] = h; + + data += 64; + numBlocks--; + } + + /* Wipe variables */ + /* memset(W, 0, sizeof(W)); */ +} + +#undef S0 +#undef S1 +#undef s0 +#undef s1 +#undef K + +#define Sha256_UpdateBlock(p) SHA256_UPDATE_BLOCKS(p)(p->state, p->buffer, 1) + +void Sha256_Update(CSha256 *p, const Byte *data, size_t size) +{ + if (size == 0) + return; + + { + unsigned pos = (unsigned)p->count & 0x3F; + unsigned num; + + p->count += size; + + num = 64 - pos; + if (num > size) + { + memcpy(p->buffer + pos, data, size); + return; + } + + if (pos != 0) + { + size -= num; + memcpy(p->buffer + pos, data, num); + data += num; + Sha256_UpdateBlock(p); + } + } + { + size_t numBlocks = size >> 6; + SHA256_UPDATE_BLOCKS(p)(p->state, data, numBlocks); + size &= 0x3F; + if (size == 0) + return; + data += (numBlocks << 6); + memcpy(p->buffer, data, size); + } +} + + +void Sha256_Final(CSha256 *p, Byte *digest) +{ + unsigned pos = (unsigned)p->count & 0x3F; + unsigned i; + + p->buffer[pos++] = 0x80; + + if (pos > (64 - 8)) + { + while (pos != 64) { p->buffer[pos++] = 0; } + // memset(&p->buf.buffer[pos], 0, 64 - pos); + Sha256_UpdateBlock(p); + pos = 0; + } + + /* + if (pos & 3) + { + p->buffer[pos] = 0; + p->buffer[pos + 1] = 0; + p->buffer[pos + 2] = 0; + pos += 3; + pos &= ~3; + } + { + for (; pos < 64 - 8; pos += 4) + *(UInt32 *)(&p->buffer[pos]) = 0; + } + */ + + memset(&p->buffer[pos], 0, (64 - 8) - pos); + + { + UInt64 numBits = (p->count << 3); + SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32)) + SetBe32(p->buffer + 64 - 4, (UInt32)(numBits)) + } + + Sha256_UpdateBlock(p); + + for (i = 0; i < 8; i += 2) + { + UInt32 v0 = p->state[i]; + UInt32 v1 = p->state[(size_t)i + 1]; + SetBe32(digest , v0) + SetBe32(digest + 4, v1) + digest += 8; + } + + Sha256_InitState(p); +} + + +void Sha256Prepare(void) +{ + #ifdef Z7_COMPILER_SHA256_SUPPORTED + SHA256_FUNC_UPDATE_BLOCKS f, f_hw; + f = Sha256_UpdateBlocks; + f_hw = NULL; + #ifdef MY_CPU_X86_OR_AMD64 + #ifndef USE_MY_MM + if (CPU_IsSupported_SHA() + && CPU_IsSupported_SSSE3() + // && CPU_IsSupported_SSE41() + ) + #endif + #else + if (CPU_IsSupported_SHA2()) + #endif + { + // printf("\n========== HW SHA256 ======== \n"); + f = f_hw = Sha256_UpdateBlocks_HW; + } + g_SHA256_FUNC_UPDATE_BLOCKS = f; + g_SHA256_FUNC_UPDATE_BLOCKS_HW = f_hw; + #endif +} + +#undef S0 +#undef S1 +#undef s0 +#undef s1 +#undef Ch +#undef Maj +#undef W_MAIN +#undef W_PRE +#undef w +#undef blk2_main +#undef blk2 +#undef T1 +#undef T4 +#undef T8 +#undef R1_PRE +#undef R1_MAIN +#undef R2_MAIN +#undef R4 +#undef R4_PRE +#undef R4_MAIN +#undef R8 +#undef R8_PRE +#undef R8_MAIN +#undef STEP_PRE +#undef STEP_MAIN +#undef Z7_SHA256_BIG_W +#undef Z7_SHA256_UNROLL +#undef Z7_COMPILER_SHA256_SUPPORTED diff --git a/libraries/lzma/C/Sha256.h b/libraries/lzma/C/Sha256.h new file mode 100644 index 0000000000..9e0422320c --- /dev/null +++ b/libraries/lzma/C/Sha256.h @@ -0,0 +1,76 @@ +/* Sha256.h -- SHA-256 Hash +2023-04-02 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_SHA256_H +#define ZIP7_INC_SHA256_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define SHA256_NUM_BLOCK_WORDS 16 +#define SHA256_NUM_DIGEST_WORDS 8 + +#define SHA256_BLOCK_SIZE (SHA256_NUM_BLOCK_WORDS * 4) +#define SHA256_DIGEST_SIZE (SHA256_NUM_DIGEST_WORDS * 4) + +typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks); + +/* + if (the system supports different SHA256 code implementations) + { + (CSha256::func_UpdateBlocks) will be used + (CSha256::func_UpdateBlocks) can be set by + Sha256_Init() - to default (fastest) + Sha256_SetFunction() - to any algo + } + else + { + (CSha256::func_UpdateBlocks) is ignored. + } +*/ + +typedef struct +{ + SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks; + UInt64 count; + UInt64 _pad_2[2]; + UInt32 state[SHA256_NUM_DIGEST_WORDS]; + + Byte buffer[SHA256_BLOCK_SIZE]; +} CSha256; + + +#define SHA256_ALGO_DEFAULT 0 +#define SHA256_ALGO_SW 1 +#define SHA256_ALGO_HW 2 + +/* +Sha256_SetFunction() +return: + 0 - (algo) value is not supported, and func_UpdateBlocks was not changed + 1 - func_UpdateBlocks was set according (algo) value. +*/ + +BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo); + +void Sha256_InitState(CSha256 *p); +void Sha256_Init(CSha256 *p); +void Sha256_Update(CSha256 *p, const Byte *data, size_t size); +void Sha256_Final(CSha256 *p, Byte *digest); + + + + +// void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); + +/* +call Sha256Prepare() once at program start. +It prepares all supported implementations, and detects the fastest implementation. +*/ + +void Sha256Prepare(void); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/Sha256Opt.c b/libraries/lzma/C/Sha256Opt.c new file mode 100644 index 0000000000..e4465e3e7d --- /dev/null +++ b/libraries/lzma/C/Sha256Opt.c @@ -0,0 +1,386 @@ +/* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" +#include "Compiler.h" +#include "CpuArch.h" + +#if defined(_MSC_VER) +#if (_MSC_VER < 1900) && (_MSC_VER >= 1200) +// #define USE_MY_MM +#endif +#endif + +#ifdef MY_CPU_X86_OR_AMD64 + #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check + #define USE_HW_SHA + #elif defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \ + || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \ + || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) + #define USE_HW_SHA + #if !defined(_INTEL_COMPILER) + // icc defines __GNUC__, but icc doesn't support __attribute__(__target__) + #if !defined(__SHA__) || !defined(__SSSE3__) + #define ATTRIB_SHA __attribute__((__target__("sha,ssse3"))) + #endif + #endif + #elif defined(_MSC_VER) + #ifdef USE_MY_MM + #define USE_VER_MIN 1300 + #else + #define USE_VER_MIN 1900 + #endif + #if (_MSC_VER >= USE_VER_MIN) + #define USE_HW_SHA + #endif + #endif +// #endif // MY_CPU_X86_OR_AMD64 + +#ifdef USE_HW_SHA + +// #pragma message("Sha256 HW") + +// sse/sse2/ssse3: +#include +// sha*: +#include + +#if defined (__clang__) && defined(_MSC_VER) + // #if !defined(__SSSE3__) + // #endif + #if !defined(__SHA__) + #include + #endif +#else + +#ifdef USE_MY_MM +#include "My_mm.h" +#endif + +#endif + +/* +SHA256 uses: +SSE2: + _mm_loadu_si128 + _mm_storeu_si128 + _mm_set_epi32 + _mm_add_epi32 + _mm_shuffle_epi32 / pshufd + + + +SSSE3: + _mm_shuffle_epi8 / pshufb + _mm_alignr_epi8 +SHA: + _mm_sha256* +*/ + +// K array must be aligned for 16-bytes at least. +// The compiler can look align attribute and selects +// movdqu - for code without align attribute +// movdqa - for code with align attribute +extern +MY_ALIGN(64) +const UInt32 SHA256_K_ARRAY[64]; + +#define K SHA256_K_ARRAY + + +#define ADD_EPI32(dest, src) dest = _mm_add_epi32(dest, src); +#define SHA256_MSG1(dest, src) dest = _mm_sha256msg1_epu32(dest, src); +#define SHA25G_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src); + + +#define LOAD_SHUFFLE(m, k) \ + m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \ + m = _mm_shuffle_epi8(m, mask); \ + +#define SM1(g0, g1, g2, g3) \ + SHA256_MSG1(g3, g0); \ + +#define SM2(g0, g1, g2, g3) \ + tmp = _mm_alignr_epi8(g1, g0, 4); \ + ADD_EPI32(g2, tmp) \ + SHA25G_MSG2(g2, g1); \ + +// #define LS0(k, g0, g1, g2, g3) LOAD_SHUFFLE(g0, k) +// #define LS1(k, g0, g1, g2, g3) LOAD_SHUFFLE(g1, k+1) + + +#define NNN(g0, g1, g2, g3) + + +#define RND2(t0, t1) \ + t0 = _mm_sha256rnds2_epu32(t0, t1, msg); + +#define RND2_0(m, k) \ + msg = _mm_add_epi32(m, *(const __m128i *) (const void *) &K[(k) * 4]); \ + RND2(state0, state1); \ + msg = _mm_shuffle_epi32(msg, 0x0E); \ + + +#define RND2_1 \ + RND2(state1, state0); \ + + +// We use scheme with 3 rounds ahead for SHA256_MSG1 / 2 rounds ahead for SHA256_MSG2 + +#define R4(k, g0, g1, g2, g3, OP0, OP1) \ + RND2_0(g0, k) \ + OP0(g0, g1, g2, g3) \ + RND2_1 \ + OP1(g0, g1, g2, g3) \ + +#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ + R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \ + R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \ + R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \ + R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \ + +#define PREPARE_STATE \ + tmp = _mm_shuffle_epi32(state0, 0x1B); /* abcd */ \ + state0 = _mm_shuffle_epi32(state1, 0x1B); /* efgh */ \ + state1 = state0; \ + state0 = _mm_unpacklo_epi64(state0, tmp); /* cdgh */ \ + state1 = _mm_unpackhi_epi64(state1, tmp); /* abef */ \ + + +void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); +#ifdef ATTRIB_SHA +ATTRIB_SHA +#endif +void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) +{ + const __m128i mask = _mm_set_epi32(0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203); + __m128i tmp; + __m128i state0, state1; + + if (numBlocks == 0) + return; + + state0 = _mm_loadu_si128((const __m128i *) (const void *) &state[0]); + state1 = _mm_loadu_si128((const __m128i *) (const void *) &state[4]); + + PREPARE_STATE + + do + { + __m128i state0_save, state1_save; + __m128i m0, m1, m2, m3; + __m128i msg; + // #define msg tmp + + state0_save = state0; + state1_save = state1; + + LOAD_SHUFFLE (m0, 0) + LOAD_SHUFFLE (m1, 1) + LOAD_SHUFFLE (m2, 2) + LOAD_SHUFFLE (m3, 3) + + + + R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ) + R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) + R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) + R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ) + + ADD_EPI32(state0, state0_save) + ADD_EPI32(state1, state1_save) + + data += 64; + } + while (--numBlocks); + + PREPARE_STATE + + _mm_storeu_si128((__m128i *) (void *) &state[0], state0); + _mm_storeu_si128((__m128i *) (void *) &state[4], state1); +} + +#endif // USE_HW_SHA + +#elif defined(MY_CPU_ARM_OR_ARM64) + + #if defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define USE_HW_SHA + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define USE_HW_SHA + #endif + #elif defined(_MSC_VER) + #if _MSC_VER >= 1910 + #define USE_HW_SHA + #endif + #endif + +#ifdef USE_HW_SHA + +// #pragma message("=== Sha256 HW === ") + +#if defined(__clang__) || defined(__GNUC__) + #ifdef MY_CPU_ARM64 + #define ATTRIB_SHA __attribute__((__target__("+crypto"))) + #else + #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) + #endif +#else + // _MSC_VER + // for arm32 + #define _ARM_USE_NEW_NEON_INTRINSICS +#endif + +#if defined(_MSC_VER) && defined(MY_CPU_ARM64) +#include +#else +#include +#endif + +typedef uint32x4_t v128; +// typedef __n128 v128; // MSVC + +#ifdef MY_CPU_BE + #define MY_rev32_for_LE(x) +#else + #define MY_rev32_for_LE(x) x = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(x))) +#endif + +#define LOAD_128(_p) (*(const v128 *)(const void *)(_p)) +#define STORE_128(_p, _v) *(v128 *)(void *)(_p) = (_v) + +#define LOAD_SHUFFLE(m, k) \ + m = LOAD_128((data + (k) * 16)); \ + MY_rev32_for_LE(m); \ + +// K array must be aligned for 16-bytes at least. +extern +MY_ALIGN(64) +const UInt32 SHA256_K_ARRAY[64]; + +#define K SHA256_K_ARRAY + + +#define SHA256_SU0(dest, src) dest = vsha256su0q_u32(dest, src); +#define SHA25G_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3); + +#define SM1(g0, g1, g2, g3) SHA256_SU0(g3, g0) +#define SM2(g0, g1, g2, g3) SHA25G_SU1(g2, g0, g1) +#define NNN(g0, g1, g2, g3) + + +#define R4(k, g0, g1, g2, g3, OP0, OP1) \ + msg = vaddq_u32(g0, *(const v128 *) (const void *) &K[(k) * 4]); \ + tmp = state0; \ + state0 = vsha256hq_u32( state0, state1, msg ); \ + state1 = vsha256h2q_u32( state1, tmp, msg ); \ + OP0(g0, g1, g2, g3); \ + OP1(g0, g1, g2, g3); \ + + +#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ + R4 ( (k)*4+0, m0, m1, m2, m3, OP0, OP1 ) \ + R4 ( (k)*4+1, m1, m2, m3, m0, OP2, OP3 ) \ + R4 ( (k)*4+2, m2, m3, m0, m1, OP4, OP5 ) \ + R4 ( (k)*4+3, m3, m0, m1, m2, OP6, OP7 ) \ + + +void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); +#ifdef ATTRIB_SHA +ATTRIB_SHA +#endif +void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) +{ + v128 state0, state1; + + if (numBlocks == 0) + return; + + state0 = LOAD_128(&state[0]); + state1 = LOAD_128(&state[4]); + + do + { + v128 state0_save, state1_save; + v128 m0, m1, m2, m3; + v128 msg, tmp; + + state0_save = state0; + state1_save = state1; + + LOAD_SHUFFLE (m0, 0) + LOAD_SHUFFLE (m1, 1) + LOAD_SHUFFLE (m2, 2) + LOAD_SHUFFLE (m3, 3) + + R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ); + R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); + R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); + R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ); + + state0 = vaddq_u32(state0, state0_save); + state1 = vaddq_u32(state1, state1_save); + + data += 64; + } + while (--numBlocks); + + STORE_128(&state[0], state0); + STORE_128(&state[4], state1); +} + +#endif // USE_HW_SHA + +#endif // MY_CPU_ARM_OR_ARM64 + + +#ifndef USE_HW_SHA + +// #error Stop_Compiling_UNSUPPORTED_SHA +// #include + +// #include "Sha256.h" +void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); + +#pragma message("Sha256 HW-SW stub was used") + +void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); +void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) +{ + Sha256_UpdateBlocks(state, data, numBlocks); + /* + UNUSED_VAR(state); + UNUSED_VAR(data); + UNUSED_VAR(numBlocks); + exit(1); + return; + */ +} + +#endif + + + +#undef K +#undef RND2 +#undef RND2_0 +#undef RND2_1 + +#undef MY_rev32_for_LE +#undef NNN +#undef LOAD_128 +#undef STORE_128 +#undef LOAD_SHUFFLE +#undef SM1 +#undef SM2 + +#undef NNN +#undef R4 +#undef R16 +#undef PREPARE_STATE +#undef USE_HW_SHA +#undef ATTRIB_SHA +#undef USE_VER_MIN diff --git a/libraries/lzma/C/Sort.c b/libraries/lzma/C/Sort.c new file mode 100644 index 0000000000..e1097e3806 --- /dev/null +++ b/libraries/lzma/C/Sort.c @@ -0,0 +1,141 @@ +/* Sort.c -- Sort functions +2014-04-05 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Sort.h" + +#define HeapSortDown(p, k, size, temp) \ + { for (;;) { \ + size_t s = (k << 1); \ + if (s > size) break; \ + if (s < size && p[s + 1] > p[s]) s++; \ + if (temp >= p[s]) break; \ + p[k] = p[s]; k = s; \ + } p[k] = temp; } + +void HeapSort(UInt32 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt32 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt32 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt32 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt32 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + +void HeapSort64(UInt64 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt64 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt64 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt64 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt64 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + +/* +#define HeapSortRefDown(p, vals, n, size, temp) \ + { size_t k = n; UInt32 val = vals[temp]; for (;;) { \ + size_t s = (k << 1); \ + if (s > size) break; \ + if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ + if (val >= vals[p[s]]) break; \ + p[k] = p[s]; k = s; \ + } p[k] = temp; } + +void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt32 temp = p[i]; + HeapSortRefDown(p, vals, i, size, temp); + } + while (--i != 0); + } + do + { + UInt32 temp = p[size]; + p[size--] = p[1]; + HeapSortRefDown(p, vals, 1, size, temp); + } + while (size > 1); +} +*/ diff --git a/libraries/lzma/C/Sort.h b/libraries/lzma/C/Sort.h new file mode 100644 index 0000000000..1817b652f5 --- /dev/null +++ b/libraries/lzma/C/Sort.h @@ -0,0 +1,18 @@ +/* Sort.h -- Sort functions +2023-03-05 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_SORT_H +#define ZIP7_INC_SORT_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void HeapSort(UInt32 *p, size_t size); +void HeapSort64(UInt64 *p, size_t size); + +/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */ + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/SwapBytes.c b/libraries/lzma/C/SwapBytes.c new file mode 100644 index 0000000000..7901bbaa87 --- /dev/null +++ b/libraries/lzma/C/SwapBytes.c @@ -0,0 +1,800 @@ +/* SwapBytes.c -- Byte Swap conversion filter +2023-04-07 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Compiler.h" +#include "CpuArch.h" +#include "RotateDefs.h" +#include "SwapBytes.h" + +typedef UInt16 CSwapUInt16; +typedef UInt32 CSwapUInt32; + +// #define k_SwapBytes_Mode_BASE 0 + +#ifdef MY_CPU_X86_OR_AMD64 + +#define k_SwapBytes_Mode_SSE2 1 +#define k_SwapBytes_Mode_SSSE3 2 +#define k_SwapBytes_Mode_AVX2 3 + + // #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) + #if defined(__clang__) && (__clang_major__ >= 4) \ + || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701) + #define k_SwapBytes_Mode_MAX k_SwapBytes_Mode_AVX2 + #define SWAP_ATTRIB_SSE2 __attribute__((__target__("sse2"))) + #define SWAP_ATTRIB_SSSE3 __attribute__((__target__("ssse3"))) + #define SWAP_ATTRIB_AVX2 __attribute__((__target__("avx2"))) + #elif defined(_MSC_VER) + #if (_MSC_VER == 1900) + #pragma warning(disable : 4752) // found Intel(R) Advanced Vector Extensions; consider using /arch:AVX + #endif + #if (_MSC_VER >= 1900) + #define k_SwapBytes_Mode_MAX k_SwapBytes_Mode_AVX2 + #elif (_MSC_VER >= 1500) // (VS2008) + #define k_SwapBytes_Mode_MAX k_SwapBytes_Mode_SSSE3 + #elif (_MSC_VER >= 1310) // (VS2003) + #define k_SwapBytes_Mode_MAX k_SwapBytes_Mode_SSE2 + #endif + #endif // _MSC_VER + +/* +// for debug +#ifdef k_SwapBytes_Mode_MAX +#undef k_SwapBytes_Mode_MAX +#endif +*/ + +#ifndef k_SwapBytes_Mode_MAX +#define k_SwapBytes_Mode_MAX 0 +#endif + +#if (k_SwapBytes_Mode_MAX != 0) && defined(MY_CPU_AMD64) + #define k_SwapBytes_Mode_MIN k_SwapBytes_Mode_SSE2 +#else + #define k_SwapBytes_Mode_MIN 0 +#endif + +#if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_AVX2) + #define USE_SWAP_AVX2 +#endif +#if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_SSSE3) + #define USE_SWAP_SSSE3 +#endif +#if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_SSE2) + #define USE_SWAP_128 +#endif + +#if k_SwapBytes_Mode_MAX <= k_SwapBytes_Mode_MIN || !defined(USE_SWAP_128) +#define FORCE_SWAP_MODE +#endif + + +#ifdef USE_SWAP_128 +/* + MMX + SSE + SSE2 + SSE3 + SSSE3 + SSE4.1 + SSE4.2 + SSE4A + AES + AVX, AVX2, FMA +*/ + +#include // sse2 +// typedef __m128i v128; + +#define SWAP2_128(i) { \ + const __m128i v = *(const __m128i *)(const void *)(items + (i) * 8); \ + *( __m128i *)( void *)(items + (i) * 8) = \ + _mm_or_si128( \ + _mm_slli_epi16(v, 8), \ + _mm_srli_epi16(v, 8)); } +// _mm_or_si128() has more ports to execute than _mm_add_epi16(). + +static +#ifdef SWAP_ATTRIB_SSE2 +SWAP_ATTRIB_SSE2 +#endif +void +Z7_FASTCALL +SwapBytes2_128(CSwapUInt16 *items, const CSwapUInt16 *lim) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SWAP2_128(0) SWAP2_128(1) items += 2 * 8; + SWAP2_128(0) SWAP2_128(1) items += 2 * 8; + } + while (items != lim); +} + +/* +// sse2 +#define SWAP4_128_pack(i) { \ + __m128i v = *(const __m128i *)(const void *)(items + (i) * 4); \ + __m128i v0 = _mm_unpacklo_epi8(v, mask); \ + __m128i v1 = _mm_unpackhi_epi8(v, mask); \ + v0 = _mm_shufflelo_epi16(v0, 0x1b); \ + v1 = _mm_shufflelo_epi16(v1, 0x1b); \ + v0 = _mm_shufflehi_epi16(v0, 0x1b); \ + v1 = _mm_shufflehi_epi16(v1, 0x1b); \ + *(__m128i *)(void *)(items + (i) * 4) = _mm_packus_epi16(v0, v1); } + +static +#ifdef SWAP_ATTRIB_SSE2 +SWAP_ATTRIB_SSE2 +#endif +void +Z7_FASTCALL +SwapBytes4_128_pack(CSwapUInt32 *items, const CSwapUInt32 *lim) +{ + const __m128i mask = _mm_setzero_si128(); + // const __m128i mask = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, 0); + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SWAP4_128_pack(0); items += 1 * 4; + // SWAP4_128_pack(0); SWAP4_128_pack(1); items += 2 * 4; + } + while (items != lim); +} + +// sse2 +#define SWAP4_128_shift(i) { \ + __m128i v = *(const __m128i *)(const void *)(items + (i) * 4); \ + __m128i v2; \ + v2 = _mm_or_si128( \ + _mm_slli_si128(_mm_and_si128(v, mask), 1), \ + _mm_and_si128(_mm_srli_si128(v, 1), mask)); \ + v = _mm_or_si128( \ + _mm_slli_epi32(v, 24), \ + _mm_srli_epi32(v, 24)); \ + *(__m128i *)(void *)(items + (i) * 4) = _mm_or_si128(v2, v); } + +static +#ifdef SWAP_ATTRIB_SSE2 +SWAP_ATTRIB_SSE2 +#endif +void +Z7_FASTCALL +SwapBytes4_128_shift(CSwapUInt32 *items, const CSwapUInt32 *lim) +{ + #define M1 0xff00 + const __m128i mask = _mm_set_epi32(M1, M1, M1, M1); + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + // SWAP4_128_shift(0) SWAP4_128_shift(1) items += 2 * 4; + // SWAP4_128_shift(0) SWAP4_128_shift(1) items += 2 * 4; + SWAP4_128_shift(0); items += 1 * 4; + } + while (items != lim); +} +*/ + + +#if defined(USE_SWAP_SSSE3) || defined(USE_SWAP_AVX2) + +#define SWAP_SHUF_REV_SEQ_2_VALS(v) (v)+1, (v) +#define SWAP_SHUF_REV_SEQ_4_VALS(v) (v)+3, (v)+2, (v)+1, (v) + +#define SWAP2_SHUF_MASK_16_BYTES \ + SWAP_SHUF_REV_SEQ_2_VALS (0 * 2), \ + SWAP_SHUF_REV_SEQ_2_VALS (1 * 2), \ + SWAP_SHUF_REV_SEQ_2_VALS (2 * 2), \ + SWAP_SHUF_REV_SEQ_2_VALS (3 * 2), \ + SWAP_SHUF_REV_SEQ_2_VALS (4 * 2), \ + SWAP_SHUF_REV_SEQ_2_VALS (5 * 2), \ + SWAP_SHUF_REV_SEQ_2_VALS (6 * 2), \ + SWAP_SHUF_REV_SEQ_2_VALS (7 * 2) + +#define SWAP4_SHUF_MASK_16_BYTES \ + SWAP_SHUF_REV_SEQ_4_VALS (0 * 4), \ + SWAP_SHUF_REV_SEQ_4_VALS (1 * 4), \ + SWAP_SHUF_REV_SEQ_4_VALS (2 * 4), \ + SWAP_SHUF_REV_SEQ_4_VALS (3 * 4) + +#if defined(USE_SWAP_AVX2) +/* if we use 256_BIT_INIT_MASK, each static array mask will be larger for 16 bytes */ +// #define SWAP_USE_256_BIT_INIT_MASK +#endif + +#if defined(SWAP_USE_256_BIT_INIT_MASK) && defined(USE_SWAP_AVX2) +#define SWAP_MASK_INIT_SIZE 32 +#else +#define SWAP_MASK_INIT_SIZE 16 +#endif + +MY_ALIGN(SWAP_MASK_INIT_SIZE) +static const Byte k_ShufMask_Swap2[] = +{ + SWAP2_SHUF_MASK_16_BYTES + #if SWAP_MASK_INIT_SIZE > 16 + , SWAP2_SHUF_MASK_16_BYTES + #endif +}; + +MY_ALIGN(SWAP_MASK_INIT_SIZE) +static const Byte k_ShufMask_Swap4[] = +{ + SWAP4_SHUF_MASK_16_BYTES + #if SWAP_MASK_INIT_SIZE > 16 + , SWAP4_SHUF_MASK_16_BYTES + #endif +}; + + +#ifdef USE_SWAP_SSSE3 + +#include // ssse3 + +#define SHUF_128(i) *(items + (i)) = \ + _mm_shuffle_epi8(*(items + (i)), mask); // SSSE3 + +// Z7_NO_INLINE +static +#ifdef SWAP_ATTRIB_SSSE3 +SWAP_ATTRIB_SSSE3 +#endif +Z7_ATTRIB_NO_VECTORIZE +void +Z7_FASTCALL +ShufBytes_128(void *items8, const void *lim8, const void *mask128_ptr) +{ + __m128i *items = (__m128i *)items8; + const __m128i *lim = (const __m128i *)lim8; + // const __m128i mask = _mm_set_epi8(SHUF_SWAP2_MASK_16_VALS); + // const __m128i mask = _mm_set_epi8(SHUF_SWAP4_MASK_16_VALS); + // const __m128i mask = _mm_load_si128((const __m128i *)(const void *)&(k_ShufMask_Swap4[0])); + // const __m128i mask = _mm_load_si128((const __m128i *)(const void *)&(k_ShufMask_Swap4[0])); + // const __m128i mask = *(const __m128i *)(const void *)&(k_ShufMask_Swap4[0]); + const __m128i mask = *(const __m128i *)mask128_ptr; + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SHUF_128(0) SHUF_128(1) items += 2; + SHUF_128(0) SHUF_128(1) items += 2; + } + while (items != lim); +} + +#endif // USE_SWAP_SSSE3 + + + +#ifdef USE_SWAP_AVX2 + +#include // avx, avx2 +#if defined(__clang__) +#include +#include +#endif + +#define SHUF_256(i) *(items + (i)) = \ + _mm256_shuffle_epi8(*(items + (i)), mask); // AVX2 + +// Z7_NO_INLINE +static +#ifdef SWAP_ATTRIB_AVX2 +SWAP_ATTRIB_AVX2 +#endif +Z7_ATTRIB_NO_VECTORIZE +void +Z7_FASTCALL +ShufBytes_256(void *items8, const void *lim8, const void *mask128_ptr) +{ + __m256i *items = (__m256i *)items8; + const __m256i *lim = (const __m256i *)lim8; + /* + UNUSED_VAR(mask128_ptr) + __m256i mask = + for Swap4: _mm256_setr_epi8(SWAP4_SHUF_MASK_16_BYTES, SWAP4_SHUF_MASK_16_BYTES); + for Swap2: _mm256_setr_epi8(SWAP2_SHUF_MASK_16_BYTES, SWAP2_SHUF_MASK_16_BYTES); + */ + const __m256i mask = + #if SWAP_MASK_INIT_SIZE > 16 + *(const __m256i *)(const void *)mask128_ptr; + #else + /* msvc: broadcastsi128() version reserves the stack for no reason + msvc 19.29-: _mm256_insertf128_si256() / _mm256_set_m128i)) versions use non-avx movdqu xmm0,XMMWORD PTR [r8] + msvc 19.30+ (VS2022): replaces _mm256_set_m128i(m,m) to vbroadcastf128(m) as we want + */ + // _mm256_broadcastsi128_si256(*mask128_ptr); + /* + #define MY_mm256_set_m128i(hi, lo) _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1) + MY_mm256_set_m128i + */ + _mm256_set_m128i( + *(const __m128i *)mask128_ptr, + *(const __m128i *)mask128_ptr); + #endif + + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SHUF_256(0) SHUF_256(1) items += 2; + SHUF_256(0) SHUF_256(1) items += 2; + } + while (items != lim); +} + +#endif // USE_SWAP_AVX2 +#endif // USE_SWAP_SSSE3 || USE_SWAP_AVX2 +#endif // USE_SWAP_128 + + + +// compile message "NEON intrinsics not available with the soft-float ABI" +#elif defined(MY_CPU_ARM_OR_ARM64) || \ + (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) +// #elif defined(MY_CPU_ARM64) + + #if defined(__clang__) && (__clang_major__ >= 8) \ + || defined(__GNUC__) && (__GNUC__ >= 8) + #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) \ + || defined(MY_CPU_ARM64) + #define USE_SWAP_128 + #endif + #ifdef MY_CPU_ARM64 + // #define SWAP_ATTRIB_NEON __attribute__((__target__(""))) + #else + // #define SWAP_ATTRIB_NEON __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) + #endif + #elif defined(_MSC_VER) + #if (_MSC_VER >= 1910) + #define USE_SWAP_128 + #endif + #endif + + #if defined(_MSC_VER) && defined(MY_CPU_ARM64) + #include + #else + #include + #endif + +#ifndef USE_SWAP_128 + #define FORCE_SWAP_MODE +#else + +#ifdef MY_CPU_ARM64 + // for debug : comment it + #define FORCE_SWAP_MODE +#else + #define k_SwapBytes_Mode_NEON 1 +#endif +// typedef uint8x16_t v128; +#define SWAP2_128(i) *(uint8x16_t *) (void *)(items + (i) * 8) = \ + vrev16q_u8(*(const uint8x16_t *)(const void *)(items + (i) * 8)); +#define SWAP4_128(i) *(uint8x16_t *) (void *)(items + (i) * 4) = \ + vrev32q_u8(*(const uint8x16_t *)(const void *)(items + (i) * 4)); + +// Z7_NO_INLINE +static +#ifdef SWAP_ATTRIB_NEON +SWAP_ATTRIB_NEON +#endif +Z7_ATTRIB_NO_VECTORIZE +void +Z7_FASTCALL +SwapBytes2_128(CSwapUInt16 *items, const CSwapUInt16 *lim) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SWAP2_128(0) SWAP2_128(1) items += 2 * 8; + SWAP2_128(0) SWAP2_128(1) items += 2 * 8; + } + while (items != lim); +} + +// Z7_NO_INLINE +static +#ifdef SWAP_ATTRIB_NEON +SWAP_ATTRIB_NEON +#endif +Z7_ATTRIB_NO_VECTORIZE +void +Z7_FASTCALL +SwapBytes4_128(CSwapUInt32 *items, const CSwapUInt32 *lim) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SWAP4_128(0) SWAP4_128(1) items += 2 * 4; + SWAP4_128(0) SWAP4_128(1) items += 2 * 4; + } + while (items != lim); +} + +#endif // USE_SWAP_128 + +#else // MY_CPU_ARM_OR_ARM64 +#define FORCE_SWAP_MODE +#endif // MY_CPU_ARM_OR_ARM64 + + + + + + +#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_X86) + /* _byteswap_ushort() in MSVC x86 32-bit works via slow { mov dh, al; mov dl, ah } + So we use own versions of byteswap function */ + #if (_MSC_VER < 1400 ) // old MSVC-X86 without _rotr16() support + #define SWAP2_16(i) { UInt32 v = items[i]; v += (v << 16); v >>= 8; items[i] = (CSwapUInt16)v; } + #else // is new MSVC-X86 with fast _rotr16() + #include + #define SWAP2_16(i) { items[i] = _rotr16(items[i], 8); } + #endif +#else // is not MSVC-X86 + #define SWAP2_16(i) { CSwapUInt16 v = items[i]; items[i] = Z7_BSWAP16(v); } +#endif // MSVC-X86 + +#if defined(Z7_CPU_FAST_BSWAP_SUPPORTED) + #define SWAP4_32(i) { CSwapUInt32 v = items[i]; items[i] = Z7_BSWAP32(v); } +#else + #define SWAP4_32(i) \ + { UInt32 v = items[i]; \ + v = ((v & 0xff00ff) << 8) + ((v >> 8) & 0xff00ff); \ + v = rotlFixed(v, 16); \ + items[i] = v; } +#endif + + + + +#if defined(FORCE_SWAP_MODE) && defined(USE_SWAP_128) + #define DEFAULT_Swap2 SwapBytes2_128 + #if !defined(MY_CPU_X86_OR_AMD64) + #define DEFAULT_Swap4 SwapBytes4_128 + #endif +#endif + +#if !defined(DEFAULT_Swap2) || !defined(DEFAULT_Swap4) + +#define SWAP_BASE_FUNCS_PREFIXES \ +Z7_FORCE_INLINE \ +static \ +Z7_ATTRIB_NO_VECTOR \ +void Z7_FASTCALL + + +#ifdef MY_CPU_64BIT + +#if defined(MY_CPU_ARM64) \ + && defined(__ARM_ARCH) && (__ARM_ARCH >= 8) \ + && ( (defined(__GNUC__) && (__GNUC__ >= 4)) \ + || (defined(__clang__) && (__clang_major__ >= 4))) + + #define SWAP2_64_VAR(v) asm ("rev16 %x0,%x0" : "+r" (v)); + #define SWAP4_64_VAR(v) asm ("rev32 %x0,%x0" : "+r" (v)); + +#else // is not ARM64-GNU + +#if !defined(MY_CPU_X86_OR_AMD64) || (k_SwapBytes_Mode_MIN == 0) || !defined(USE_SWAP_128) + #define SWAP2_64_VAR(v) \ + v = ( 0x00ff00ff00ff00ff & (v >> 8)) \ + + ((0x00ff00ff00ff00ff & v) << 8); + /* plus gives faster code in MSVC */ +#endif + +#ifdef Z7_CPU_FAST_BSWAP_SUPPORTED + #define SWAP4_64_VAR(v) \ + v = Z7_BSWAP64(v); \ + v = Z7_ROTL64(v, 32); +#else + #define SWAP4_64_VAR(v) \ + v = ( 0x000000ff000000ff & (v >> 24)) \ + + ((0x000000ff000000ff & v) << 24 ) \ + + ( 0x0000ff000000ff00 & (v >> 8)) \ + + ((0x0000ff000000ff00 & v) << 8 ) \ + ; +#endif + +#endif // ARM64-GNU + + +#ifdef SWAP2_64_VAR + +#define SWAP2_64(i) { \ + UInt64 v = *(const UInt64 *)(const void *)(items + (i) * 4); \ + SWAP2_64_VAR(v) \ + *(UInt64 *)(void *)(items + (i) * 4) = v; } + +SWAP_BASE_FUNCS_PREFIXES +SwapBytes2_64(CSwapUInt16 *items, const CSwapUInt16 *lim) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SWAP2_64(0) SWAP2_64(1) items += 2 * 4; + SWAP2_64(0) SWAP2_64(1) items += 2 * 4; + } + while (items != lim); +} + + #define DEFAULT_Swap2 SwapBytes2_64 + #if !defined(FORCE_SWAP_MODE) + #define SWAP2_DEFAULT_MODE 0 + #endif +#else // !defined(SWAP2_64_VAR) + #define DEFAULT_Swap2 SwapBytes2_128 + #if !defined(FORCE_SWAP_MODE) + #define SWAP2_DEFAULT_MODE 1 + #endif +#endif // SWAP2_64_VAR + + +#define SWAP4_64(i) { \ + UInt64 v = *(const UInt64 *)(const void *)(items + (i) * 2); \ + SWAP4_64_VAR(v) \ + *(UInt64 *)(void *)(items + (i) * 2) = v; } + +SWAP_BASE_FUNCS_PREFIXES +SwapBytes4_64(CSwapUInt32 *items, const CSwapUInt32 *lim) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SWAP4_64(0) SWAP4_64(1) items += 2 * 2; + SWAP4_64(0) SWAP4_64(1) items += 2 * 2; + } + while (items != lim); +} + +#define DEFAULT_Swap4 SwapBytes4_64 + +#else // is not 64BIT + + +#if defined(MY_CPU_ARM_OR_ARM64) \ + && defined(__ARM_ARCH) && (__ARM_ARCH >= 6) \ + && ( (defined(__GNUC__) && (__GNUC__ >= 4)) \ + || (defined(__clang__) && (__clang_major__ >= 4))) + +#ifdef MY_CPU_64BIT + #define SWAP2_32_VAR(v) asm ("rev16 %w0,%w0" : "+r" (v)); +#else + #define SWAP2_32_VAR(v) asm ("rev16 %0,%0" : "+r" (v)); // for clang/gcc + // asm ("rev16 %r0,%r0" : "+r" (a)); // for gcc +#endif + +#elif defined(_MSC_VER) && (_MSC_VER < 1300) && defined(MY_CPU_X86) \ + || !defined(Z7_CPU_FAST_BSWAP_SUPPORTED) \ + || !defined(Z7_CPU_FAST_ROTATE_SUPPORTED) + // old msvc doesn't support _byteswap_ulong() + #define SWAP2_32_VAR(v) \ + v = ((v & 0xff00ff) << 8) + ((v >> 8) & 0xff00ff); + +#else // is not ARM and is not old-MSVC-X86 and fast BSWAP/ROTATE are supported + #define SWAP2_32_VAR(v) \ + v = Z7_BSWAP32(v); \ + v = rotlFixed(v, 16); + +#endif // GNU-ARM* + +#define SWAP2_32(i) { \ + UInt32 v = *(const UInt32 *)(const void *)(items + (i) * 2); \ + SWAP2_32_VAR(v); \ + *(UInt32 *)(void *)(items + (i) * 2) = v; } + + +SWAP_BASE_FUNCS_PREFIXES +SwapBytes2_32(CSwapUInt16 *items, const CSwapUInt16 *lim) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SWAP2_32(0) SWAP2_32(1) items += 2 * 2; + SWAP2_32(0) SWAP2_32(1) items += 2 * 2; + } + while (items != lim); +} + + +SWAP_BASE_FUNCS_PREFIXES +SwapBytes4_32(CSwapUInt32 *items, const CSwapUInt32 *lim) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + do + { + SWAP4_32(0) SWAP4_32(1) items += 2; + SWAP4_32(0) SWAP4_32(1) items += 2; + } + while (items != lim); +} + +#define DEFAULT_Swap2 SwapBytes2_32 +#define DEFAULT_Swap4 SwapBytes4_32 +#if !defined(FORCE_SWAP_MODE) + #define SWAP2_DEFAULT_MODE 0 +#endif + +#endif // MY_CPU_64BIT +#endif // if !defined(DEFAULT_Swap2) || !defined(DEFAULT_Swap4) + + + +#if !defined(FORCE_SWAP_MODE) +static unsigned g_SwapBytes_Mode; +#endif + +/* size of largest unrolled loop iteration: 128 bytes = 4 * 32 bytes (AVX). */ +#define SWAP_ITERATION_BLOCK_SIZE_MAX (1 << 7) + +// 32 bytes for (AVX) or 2 * 16-bytes for NEON. +#define SWAP_VECTOR_ALIGN_SIZE (1 << 5) + +Z7_NO_INLINE +void z7_SwapBytes2(CSwapUInt16 *items, size_t numItems) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (SWAP_VECTOR_ALIGN_SIZE - 1)) != 0; numItems--) + { + SWAP2_16(0) + items++; + } + { + const size_t k_Align_Mask = SWAP_ITERATION_BLOCK_SIZE_MAX / sizeof(CSwapUInt16) - 1; + size_t numItems2 = numItems; + CSwapUInt16 *lim; + numItems &= k_Align_Mask; + numItems2 &= ~(size_t)k_Align_Mask; + lim = items + numItems2; + if (numItems2 != 0) + { + #if !defined(FORCE_SWAP_MODE) + #ifdef MY_CPU_X86_OR_AMD64 + #ifdef USE_SWAP_AVX2 + if (g_SwapBytes_Mode > k_SwapBytes_Mode_SSSE3) + ShufBytes_256((__m256i *)(void *)items, + (const __m256i *)(const void *)lim, + (const __m128i *)(const void *)&(k_ShufMask_Swap2[0])); + else + #endif + #ifdef USE_SWAP_SSSE3 + if (g_SwapBytes_Mode >= k_SwapBytes_Mode_SSSE3) + ShufBytes_128((__m128i *)(void *)items, + (const __m128i *)(const void *)lim, + (const __m128i *)(const void *)&(k_ShufMask_Swap2[0])); + else + #endif + #endif // MY_CPU_X86_OR_AMD64 + #if SWAP2_DEFAULT_MODE == 0 + if (g_SwapBytes_Mode != 0) + SwapBytes2_128(items, lim); + else + #endif + #endif // FORCE_SWAP_MODE + DEFAULT_Swap2(items, lim); + } + items = lim; + } + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + for (; numItems != 0; numItems--) + { + SWAP2_16(0) + items++; + } +} + + +Z7_NO_INLINE +void z7_SwapBytes4(CSwapUInt32 *items, size_t numItems) +{ + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (SWAP_VECTOR_ALIGN_SIZE - 1)) != 0; numItems--) + { + SWAP4_32(0) + items++; + } + { + const size_t k_Align_Mask = SWAP_ITERATION_BLOCK_SIZE_MAX / sizeof(CSwapUInt32) - 1; + size_t numItems2 = numItems; + CSwapUInt32 *lim; + numItems &= k_Align_Mask; + numItems2 &= ~(size_t)k_Align_Mask; + lim = items + numItems2; + if (numItems2 != 0) + { + #if !defined(FORCE_SWAP_MODE) + #ifdef MY_CPU_X86_OR_AMD64 + #ifdef USE_SWAP_AVX2 + if (g_SwapBytes_Mode > k_SwapBytes_Mode_SSSE3) + ShufBytes_256((__m256i *)(void *)items, + (const __m256i *)(const void *)lim, + (const __m128i *)(const void *)&(k_ShufMask_Swap4[0])); + else + #endif + #ifdef USE_SWAP_SSSE3 + if (g_SwapBytes_Mode >= k_SwapBytes_Mode_SSSE3) + ShufBytes_128((__m128i *)(void *)items, + (const __m128i *)(const void *)lim, + (const __m128i *)(const void *)&(k_ShufMask_Swap4[0])); + else + #endif + #else // MY_CPU_X86_OR_AMD64 + + if (g_SwapBytes_Mode != 0) + SwapBytes4_128(items, lim); + else + #endif // MY_CPU_X86_OR_AMD64 + #endif // FORCE_SWAP_MODE + DEFAULT_Swap4(items, lim); + } + items = lim; + } + Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE + for (; numItems != 0; numItems--) + { + SWAP4_32(0) + items++; + } +} + + +// #define SHOW_HW_STATUS + +#ifdef SHOW_HW_STATUS +#include +#define PRF(x) x +#else +#define PRF(x) +#endif + +void z7_SwapBytesPrepare(void) +{ +#ifndef FORCE_SWAP_MODE + unsigned mode = 0; // k_SwapBytes_Mode_BASE; + +#ifdef MY_CPU_ARM_OR_ARM64 + { + if (CPU_IsSupported_NEON()) + { + // #pragma message ("=== SwapBytes NEON") + PRF(printf("\n=== SwapBytes NEON\n");) + mode = k_SwapBytes_Mode_NEON; + } + } +#else // MY_CPU_ARM_OR_ARM64 + { + #ifdef USE_SWAP_AVX2 + if (CPU_IsSupported_AVX2()) + { + // #pragma message ("=== SwapBytes AVX2") + PRF(printf("\n=== SwapBytes AVX2\n");) + mode = k_SwapBytes_Mode_AVX2; + } + else + #endif + #ifdef USE_SWAP_SSSE3 + if (CPU_IsSupported_SSSE3()) + { + // #pragma message ("=== SwapBytes SSSE3") + PRF(printf("\n=== SwapBytes SSSE3\n");) + mode = k_SwapBytes_Mode_SSSE3; + } + else + #endif + #if !defined(MY_CPU_AMD64) + if (CPU_IsSupported_SSE2()) + #endif + { + // #pragma message ("=== SwapBytes SSE2") + PRF(printf("\n=== SwapBytes SSE2\n");) + mode = k_SwapBytes_Mode_SSE2; + } + } +#endif // MY_CPU_ARM_OR_ARM64 + g_SwapBytes_Mode = mode; + // g_SwapBytes_Mode = 0; // for debug +#endif // FORCE_SWAP_MODE + PRF(printf("\n=== SwapBytesPrepare\n");) +} + +#undef PRF diff --git a/libraries/lzma/C/SwapBytes.h b/libraries/lzma/C/SwapBytes.h new file mode 100644 index 0000000000..d442467386 --- /dev/null +++ b/libraries/lzma/C/SwapBytes.h @@ -0,0 +1,17 @@ +/* SwapBytes.h -- Byte Swap conversion filter +2023-04-02 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_SWAP_BYTES_H +#define ZIP7_INC_SWAP_BYTES_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void z7_SwapBytes2(UInt16 *data, size_t numItems); +void z7_SwapBytes4(UInt32 *data, size_t numItems); +void z7_SwapBytesPrepare(void); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/Threads.c b/libraries/lzma/C/Threads.c index 58eb90ffa0..cf52bd3030 100644 --- a/libraries/lzma/C/Threads.c +++ b/libraries/lzma/C/Threads.c @@ -1,5 +1,5 @@ /* Threads.c -- multithreading library -2021-12-21 : Igor Pavlov : Public domain */ +2023-03-04 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -11,9 +11,9 @@ #include "Threads.h" -static WRes GetError() +static WRes GetError(void) { - DWORD res = GetLastError(); + const DWORD res = GetLastError(); return res ? (WRes)res : 1; } @@ -173,6 +173,9 @@ WRes CriticalSection_Init(CCriticalSection *p) Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception Windows Vista+ : no exceptions */ #ifdef _MSC_VER + #ifdef __clang__ + #pragma GCC diagnostic ignored "-Wlanguage-extension-token" + #endif __try #endif { @@ -193,18 +196,26 @@ WRes CriticalSection_Init(CCriticalSection *p) // ---------- POSIX ---------- #ifndef __APPLE__ -#ifndef _7ZIP_AFFINITY_DISABLE +#ifndef Z7_AFFINITY_DISABLE // _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET +// clang < 3.6 : unknown warning group '-Wreserved-id-macro' +// clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier" +// clang >= 13 : do not give warning +#if !defined(_GNU_SOURCE) + #if defined(__clang__) && (__clang_major__ >= 4) && (__clang_major__ <= 12) + #pragma GCC diagnostic ignored "-Wreserved-id-macro" + #endif #define _GNU_SOURCE -#endif -#endif +#endif // !defined(_GNU_SOURCE) +#endif // Z7_AFFINITY_DISABLE +#endif // __APPLE__ #include "Threads.h" #include #include #include -#ifdef _7ZIP_AFFINITY_SUPPORTED +#ifdef Z7_AFFINITY_SUPPORTED // #include #endif @@ -212,15 +223,12 @@ WRes CriticalSection_Init(CCriticalSection *p) // #include // #define PRF(p) p #define PRF(p) - -#define Print(s) PRF(printf("\n%s\n", s)) - -// #include +#define Print(s) PRF(printf("\n%s\n", s);) WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet) { // new thread in Posix probably inherits affinity from parrent thread - Print("Thread_Create_With_CpuSet"); + Print("Thread_Create_With_CpuSet") pthread_attr_t attr; int ret; @@ -228,7 +236,7 @@ WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, p->_created = 0; - RINOK(pthread_attr_init(&attr)); + RINOK(pthread_attr_init(&attr)) ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); @@ -236,7 +244,7 @@ WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, { if (cpuSet) { - #ifdef _7ZIP_AFFINITY_SUPPORTED + #ifdef Z7_AFFINITY_SUPPORTED /* printf("\n affinity :"); @@ -292,7 +300,7 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) { - Print("Thread_Create_WithAffinity"); + Print("Thread_Create_WithAffinity") CCpuSet cs; unsigned i; CpuSet_Zero(&cs); @@ -312,7 +320,7 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param WRes Thread_Close(CThread *p) { - // Print("Thread_Close"); + // Print("Thread_Close") int ret; if (!p->_created) return 0; @@ -326,7 +334,7 @@ WRes Thread_Close(CThread *p) WRes Thread_Wait_Close(CThread *p) { - // Print("Thread_Wait_Close"); + // Print("Thread_Wait_Close") void *thread_return; int ret; if (!p->_created) @@ -343,8 +351,8 @@ WRes Thread_Wait_Close(CThread *p) static WRes Event_Create(CEvent *p, int manualReset, int signaled) { - RINOK(pthread_mutex_init(&p->_mutex, NULL)); - RINOK(pthread_cond_init(&p->_cond, NULL)); + RINOK(pthread_mutex_init(&p->_mutex, NULL)) + RINOK(pthread_cond_init(&p->_cond, NULL)) p->_manual_reset = manualReset; p->_state = (signaled ? True : False); p->_created = 1; @@ -363,7 +371,7 @@ WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) WRes Event_Set(CEvent *p) { - RINOK(pthread_mutex_lock(&p->_mutex)); + RINOK(pthread_mutex_lock(&p->_mutex)) p->_state = True; int res1 = pthread_cond_broadcast(&p->_cond); int res2 = pthread_mutex_unlock(&p->_mutex); @@ -372,14 +380,14 @@ WRes Event_Set(CEvent *p) WRes Event_Reset(CEvent *p) { - RINOK(pthread_mutex_lock(&p->_mutex)); + RINOK(pthread_mutex_lock(&p->_mutex)) p->_state = False; return pthread_mutex_unlock(&p->_mutex); } WRes Event_Wait(CEvent *p) { - RINOK(pthread_mutex_lock(&p->_mutex)); + RINOK(pthread_mutex_lock(&p->_mutex)) while (p->_state == False) { // ETIMEDOUT @@ -411,8 +419,8 @@ WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { if (initCount > maxCount || maxCount < 1) return EINVAL; - RINOK(pthread_mutex_init(&p->_mutex, NULL)); - RINOK(pthread_cond_init(&p->_cond, NULL)); + RINOK(pthread_mutex_init(&p->_mutex, NULL)) + RINOK(pthread_cond_init(&p->_cond, NULL)) p->_count = initCount; p->_maxCount = maxCount; p->_created = 1; @@ -448,7 +456,7 @@ WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) if (releaseCount < 1) return EINVAL; - RINOK(pthread_mutex_lock(&p->_mutex)); + RINOK(pthread_mutex_lock(&p->_mutex)) newCount = p->_count + releaseCount; if (newCount > p->_maxCount) @@ -458,13 +466,13 @@ WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) p->_count = newCount; ret = pthread_cond_broadcast(&p->_cond); } - RINOK(pthread_mutex_unlock(&p->_mutex)); + RINOK(pthread_mutex_unlock(&p->_mutex)) return ret; } WRes Semaphore_Wait(CSemaphore *p) { - RINOK(pthread_mutex_lock(&p->_mutex)); + RINOK(pthread_mutex_lock(&p->_mutex)) while (p->_count < 1) { pthread_cond_wait(&p->_cond, &p->_mutex); @@ -489,7 +497,7 @@ WRes Semaphore_Close(CSemaphore *p) WRes CriticalSection_Init(CCriticalSection *p) { - // Print("CriticalSection_Init"); + // Print("CriticalSection_Init") if (!p) return EINTR; return pthread_mutex_init(&p->_mutex, NULL); @@ -497,7 +505,7 @@ WRes CriticalSection_Init(CCriticalSection *p) void CriticalSection_Enter(CCriticalSection *p) { - // Print("CriticalSection_Enter"); + // Print("CriticalSection_Enter") if (p) { // int ret = @@ -507,7 +515,7 @@ void CriticalSection_Enter(CCriticalSection *p) void CriticalSection_Leave(CCriticalSection *p) { - // Print("CriticalSection_Leave"); + // Print("CriticalSection_Leave") if (p) { // int ret = @@ -517,7 +525,7 @@ void CriticalSection_Leave(CCriticalSection *p) void CriticalSection_Delete(CCriticalSection *p) { - // Print("CriticalSection_Delete"); + // Print("CriticalSection_Delete") if (p) { // int ret = @@ -527,14 +535,28 @@ void CriticalSection_Delete(CCriticalSection *p) LONG InterlockedIncrement(LONG volatile *addend) { - // Print("InterlockedIncrement"); + // Print("InterlockedIncrement") #ifdef USE_HACK_UNSAFE_ATOMIC LONG val = *addend + 1; *addend = val; return val; #else + + #if defined(__clang__) && (__clang_major__ >= 8) + #pragma GCC diagnostic ignored "-Watomic-implicit-seq-cst" + #endif return __sync_add_and_fetch(addend, 1); #endif } #endif // _WIN32 + +WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p) +{ + if (Event_IsCreated(p)) + return Event_Reset(p); + return AutoResetEvent_CreateNotSignaled(p); +} + +#undef PRF +#undef Print diff --git a/libraries/lzma/C/Threads.h b/libraries/lzma/C/Threads.h index 89ecb92be9..4028464a33 100644 --- a/libraries/lzma/C/Threads.h +++ b/libraries/lzma/C/Threads.h @@ -1,18 +1,19 @@ /* Threads.h -- multithreading library -2021-12-21 : Igor Pavlov : Public domain */ +2023-04-02 : Igor Pavlov : Public domain */ -#ifndef __7Z_THREADS_H -#define __7Z_THREADS_H +#ifndef ZIP7_INC_THREADS_H +#define ZIP7_INC_THREADS_H #ifdef _WIN32 -#include +#include "7zWindows.h" + #else #if defined(__linux__) #if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) -#ifndef _7ZIP_AFFINITY_DISABLE -#define _7ZIP_AFFINITY_SUPPORTED -// #pragma message(" ==== _7ZIP_AFFINITY_SUPPORTED") +#ifndef Z7_AFFINITY_DISABLE +#define Z7_AFFINITY_SUPPORTED +// #pragma message(" ==== Z7_AFFINITY_SUPPORTED") // #define _GNU_SOURCE #endif #endif @@ -33,7 +34,7 @@ WRes Handle_WaitObject(HANDLE h); typedef HANDLE CThread; -#define Thread_Construct(p) { *(p) = NULL; } +#define Thread_CONSTRUCT(p) { *(p) = NULL; } #define Thread_WasCreated(p) (*(p) != NULL) #define Thread_Close(p) HandlePtr_Close(p) // #define Thread_Wait(p) Handle_WaitObject(*(p)) @@ -52,42 +53,46 @@ typedef #endif THREAD_FUNC_RET_TYPE; +#define THREAD_FUNC_RET_ZERO 0 + typedef DWORD_PTR CAffinityMask; typedef DWORD_PTR CCpuSet; -#define CpuSet_Zero(p) { *(p) = 0; } -#define CpuSet_Set(p, cpu) { *(p) |= ((DWORD_PTR)1 << (cpu)); } +#define CpuSet_Zero(p) *(p) = (0) +#define CpuSet_Set(p, cpu) *(p) |= ((DWORD_PTR)1 << (cpu)) #else // _WIN32 -typedef struct _CThread +typedef struct { pthread_t _tid; int _created; } CThread; -#define Thread_Construct(p) { (p)->_tid = 0; (p)->_created = 0; } -#define Thread_WasCreated(p) ((p)->_created != 0) +#define Thread_CONSTRUCT(p) { (p)->_tid = 0; (p)->_created = 0; } +#define Thread_WasCreated(p) ((p)->_created != 0) WRes Thread_Close(CThread *p); // #define Thread_Wait Thread_Wait_Close typedef void * THREAD_FUNC_RET_TYPE; +#define THREAD_FUNC_RET_ZERO NULL + typedef UInt64 CAffinityMask; -#ifdef _7ZIP_AFFINITY_SUPPORTED +#ifdef Z7_AFFINITY_SUPPORTED typedef cpu_set_t CCpuSet; -#define CpuSet_Zero(p) CPU_ZERO(p) -#define CpuSet_Set(p, cpu) CPU_SET(cpu, p) -#define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p) +#define CpuSet_Zero(p) CPU_ZERO(p) +#define CpuSet_Set(p, cpu) CPU_SET(cpu, p) +#define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p) #else typedef UInt64 CCpuSet; -#define CpuSet_Zero(p) { *(p) = 0; } -#define CpuSet_Set(p, cpu) { *(p) |= ((UInt64)1 << (cpu)); } -#define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0) +#define CpuSet_Zero(p) *(p) = (0) +#define CpuSet_Set(p, cpu) *(p) |= ((UInt64)1 << (cpu)) +#define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0) #endif @@ -95,7 +100,7 @@ typedef UInt64 CCpuSet; #endif // _WIN32 -#define THREAD_FUNC_CALL_TYPE MY_STD_CALL +#define THREAD_FUNC_CALL_TYPE Z7_STDCALL #if defined(_WIN32) && defined(__GNUC__) /* GCC compiler for x86 32-bit uses the rule: @@ -187,6 +192,7 @@ WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); + WRes Event_Set(CEvent *p); WRes Event_Reset(CEvent *p); WRes Event_Wait(CEvent *p); @@ -227,6 +233,8 @@ LONG InterlockedIncrement(LONG volatile *addend); #endif // _WIN32 +WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p); + EXTERN_C_END #endif diff --git a/libraries/lzma/C/Xz.c b/libraries/lzma/C/Xz.c new file mode 100644 index 0000000000..4ad071060a --- /dev/null +++ b/libraries/lzma/C/Xz.c @@ -0,0 +1,90 @@ +/* Xz.c - Xz +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" +#include "XzCrc64.h" + +const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 }; +/* const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; */ + +unsigned Xz_WriteVarInt(Byte *buf, UInt64 v) +{ + unsigned i = 0; + do + { + buf[i++] = (Byte)((v & 0x7F) | 0x80); + v >>= 7; + } + while (v != 0); + buf[(size_t)i - 1] &= 0x7F; + return i; +} + +void Xz_Construct(CXzStream *p) +{ + p->numBlocks = 0; + p->blocks = NULL; + p->flags = 0; +} + +void Xz_Free(CXzStream *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->blocks); + p->numBlocks = 0; + p->blocks = NULL; +} + +unsigned XzFlags_GetCheckSize(CXzStreamFlags f) +{ + unsigned t = XzFlags_GetCheckType(f); + return (t == 0) ? 0 : ((unsigned)4 << ((t - 1) / 3)); +} + +void XzCheck_Init(CXzCheck *p, unsigned mode) +{ + p->mode = mode; + switch (mode) + { + case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break; + case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break; + case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break; + } +} + +void XzCheck_Update(CXzCheck *p, const void *data, size_t size) +{ + switch (p->mode) + { + case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break; + case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break; + case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break; + } +} + +int XzCheck_Final(CXzCheck *p, Byte *digest) +{ + switch (p->mode) + { + case XZ_CHECK_CRC32: + SetUi32(digest, CRC_GET_DIGEST(p->crc)) + break; + case XZ_CHECK_CRC64: + { + int i; + UInt64 v = CRC64_GET_DIGEST(p->crc64); + for (i = 0; i < 8; i++, v >>= 8) + digest[i] = (Byte)(v & 0xFF); + break; + } + case XZ_CHECK_SHA256: + Sha256_Final(&p->sha, digest); + break; + default: + return 0; + } + return 1; +} diff --git a/libraries/lzma/C/Xz.h b/libraries/lzma/C/Xz.h new file mode 100644 index 0000000000..d5001f6cac --- /dev/null +++ b/libraries/lzma/C/Xz.h @@ -0,0 +1,535 @@ +/* Xz.h - Xz interface +2023-04-13 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_XZ_H +#define ZIP7_INC_XZ_H + +#include "Sha256.h" +#include "Delta.h" + +EXTERN_C_BEGIN + +#define XZ_ID_Subblock 1 +#define XZ_ID_Delta 3 +#define XZ_ID_X86 4 +#define XZ_ID_PPC 5 +#define XZ_ID_IA64 6 +#define XZ_ID_ARM 7 +#define XZ_ID_ARMT 8 +#define XZ_ID_SPARC 9 +#define XZ_ID_ARM64 0xa +#define XZ_ID_LZMA2 0x21 + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value); +unsigned Xz_WriteVarInt(Byte *buf, UInt64 v); + +/* ---------- xz block ---------- */ + +#define XZ_BLOCK_HEADER_SIZE_MAX 1024 + +#define XZ_NUM_FILTERS_MAX 4 +#define XZ_BF_NUM_FILTERS_MASK 3 +#define XZ_BF_PACK_SIZE (1 << 6) +#define XZ_BF_UNPACK_SIZE (1 << 7) + +#define XZ_FILTER_PROPS_SIZE_MAX 20 + +typedef struct +{ + UInt64 id; + UInt32 propsSize; + Byte props[XZ_FILTER_PROPS_SIZE_MAX]; +} CXzFilter; + +typedef struct +{ + UInt64 packSize; + UInt64 unpackSize; + Byte flags; + CXzFilter filters[XZ_NUM_FILTERS_MAX]; +} CXzBlock; + +#define XzBlock_GetNumFilters(p) (((unsigned)(p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1) +#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0) +#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0) +#define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0) + +SRes XzBlock_Parse(CXzBlock *p, const Byte *header); +SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes); + +/* ---------- xz stream ---------- */ + +#define XZ_SIG_SIZE 6 +#define XZ_FOOTER_SIG_SIZE 2 + +extern const Byte XZ_SIG[XZ_SIG_SIZE]; + +/* +extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE]; +*/ + +#define XZ_FOOTER_SIG_0 'Y' +#define XZ_FOOTER_SIG_1 'Z' + +#define XZ_STREAM_FLAGS_SIZE 2 +#define XZ_STREAM_CRC_SIZE 4 + +#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE) +#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4) + +#define XZ_CHECK_MASK 0xF +#define XZ_CHECK_NO 0 +#define XZ_CHECK_CRC32 1 +#define XZ_CHECK_CRC64 4 +#define XZ_CHECK_SHA256 10 + +typedef struct +{ + unsigned mode; + UInt32 crc; + UInt64 crc64; + CSha256 sha; +} CXzCheck; + +void XzCheck_Init(CXzCheck *p, unsigned mode); +void XzCheck_Update(CXzCheck *p, const void *data, size_t size); +int XzCheck_Final(CXzCheck *p, Byte *digest); + +typedef UInt16 CXzStreamFlags; + +#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK) +#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK) +#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32) +unsigned XzFlags_GetCheckSize(CXzStreamFlags f); + +SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf); +SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream); + +typedef struct +{ + UInt64 unpackSize; + UInt64 totalSize; +} CXzBlockSizes; + +typedef struct +{ + CXzStreamFlags flags; + // Byte _pad[6]; + size_t numBlocks; + CXzBlockSizes *blocks; + UInt64 startOffset; +} CXzStream; + +void Xz_Construct(CXzStream *p); +void Xz_Free(CXzStream *p, ISzAllocPtr alloc); + +#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1) + +UInt64 Xz_GetUnpackSize(const CXzStream *p); +UInt64 Xz_GetPackSize(const CXzStream *p); + +typedef struct +{ + size_t num; + size_t numAllocated; + CXzStream *streams; +} CXzs; + +void Xzs_Construct(CXzs *p); +void Xzs_Free(CXzs *p, ISzAllocPtr alloc); +SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr inStream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc); + +UInt64 Xzs_GetNumBlocks(const CXzs *p); +UInt64 Xzs_GetUnpackSize(const CXzs *p); + + +// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder + +typedef enum +{ + CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */ + CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + CODER_STATUS_NOT_FINISHED, /* stream was not finished */ + CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */ +} ECoderStatus; + + +// ECoderFinishMode values are identical to ELzmaFinishMode + +typedef enum +{ + CODER_FINISH_ANY, /* finish at any point */ + CODER_FINISH_END /* block must be finished at the end */ +} ECoderFinishMode; + + +typedef struct +{ + void *p; // state object; + void (*Free)(void *p, ISzAllocPtr alloc); + SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc); + void (*Init)(void *p); + SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished, + ECoderStatus *status); + SizeT (*Filter)(void *p, Byte *data, SizeT size); +} IStateCoder; + + +typedef struct +{ + UInt32 methodId; + UInt32 delta; + UInt32 ip; + UInt32 X86_State; + Byte delta_State[DELTA_STATE_SIZE]; +} CXzBcFilterStateBase; + +typedef SizeT (*Xz_Func_BcFilterStateBase_Filter)(CXzBcFilterStateBase *p, Byte *data, SizeT size); + +SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id, + Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc); + + +#define MIXCODER_NUM_FILTERS_MAX 4 + +typedef struct +{ + ISzAllocPtr alloc; + Byte *buf; + unsigned numCoders; + + Byte *outBuf; + size_t outBufSize; + size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode) + BoolInt wasFinished; + SRes res; + ECoderStatus status; + // BoolInt SingleBufMode; + + int finished[MIXCODER_NUM_FILTERS_MAX - 1]; + size_t pos[MIXCODER_NUM_FILTERS_MAX - 1]; + size_t size[MIXCODER_NUM_FILTERS_MAX - 1]; + UInt64 ids[MIXCODER_NUM_FILTERS_MAX]; + SRes results[MIXCODER_NUM_FILTERS_MAX]; + IStateCoder coders[MIXCODER_NUM_FILTERS_MAX]; +} CMixCoder; + + +typedef enum +{ + XZ_STATE_STREAM_HEADER, + XZ_STATE_STREAM_INDEX, + XZ_STATE_STREAM_INDEX_CRC, + XZ_STATE_STREAM_FOOTER, + XZ_STATE_STREAM_PADDING, + XZ_STATE_BLOCK_HEADER, + XZ_STATE_BLOCK, + XZ_STATE_BLOCK_FOOTER +} EXzState; + + +typedef struct +{ + EXzState state; + UInt32 pos; + unsigned alignPos; + unsigned indexPreSize; + + CXzStreamFlags streamFlags; + + UInt32 blockHeaderSize; + UInt64 packSize; + UInt64 unpackSize; + + UInt64 numBlocks; // number of finished blocks in current stream + UInt64 indexSize; + UInt64 indexPos; + UInt64 padSize; + + UInt64 numStartedStreams; + UInt64 numFinishedStreams; + UInt64 numTotalBlocks; + + UInt32 crc; + CMixCoder decoder; + CXzBlock block; + CXzCheck check; + CSha256 sha; + + BoolInt parseMode; + BoolInt headerParsedOk; + BoolInt decodeToStreamSignature; + unsigned decodeOnlyOneBlock; + + Byte *outBuf; + size_t outBufSize; + size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked + + Byte shaDigest[SHA256_DIGEST_SIZE]; + Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; +} CXzUnpacker; + +/* alloc : aligned for cache line allocation is better */ +void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc); +void XzUnpacker_Init(CXzUnpacker *p); +void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize); +void XzUnpacker_Free(CXzUnpacker *p); + +/* + XzUnpacker + The sequence for decoding functions: + { + XzUnpacker_Construct() + [Decoding_Calls] + XzUnpacker_Free() + } + + [Decoding_Calls] + + There are 3 types of interfaces for [Decoding_Calls] calls: + + Interface-1 : Partial output buffers: + { + XzUnpacker_Init() + for() + { + XzUnpacker_Code(); + } + XzUnpacker_IsStreamWasFinished() + } + + Interface-2 : Direct output buffer: + Use it, if you know exact size of decoded data, and you need + whole xz unpacked data in one output buffer. + xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode. + { + XzUnpacker_Init() + XzUnpacker_SetOutBufMode(); // to set output buffer and size + for() + { + XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code() + } + XzUnpacker_IsStreamWasFinished() + } + + Interface-3 : Direct output buffer : One call full decoding + It unpacks whole input buffer to output buffer in one call. + It uses Interface-2 internally. + { + XzUnpacker_CodeFull() + XzUnpacker_IsStreamWasFinished() + } +*/ + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + CODER_FINISH_ANY - use smallest number of input bytes + CODER_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + CODER_STATUS_NOT_FINISHED, + CODER_STATUS_NEEDS_MORE_INPUT - the decoder can return it in two cases: + 1) it needs more input data to finish current xz stream + 2) xz stream was finished successfully. But the decoder supports multiple + concatented xz streams. So it expects more input data for new xz streams. + Call XzUnpacker_IsStreamWasFinished() to check that latest xz stream was finished successfully. + + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_DATA - Data error + SZ_ERROR_UNSUPPORTED - Unsupported method or method properties + SZ_ERROR_CRC - CRC error + // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons: + - xz Stream Signature failure + - CRC32 of xz Stream Header is failed + - The size of Stream padding is not multiple of four bytes. + It's possible to get that error, if xz stream was finished and the stream + contains some another data. In that case you can call XzUnpacker_GetExtraSize() + function to get real size of xz stream. +*/ + + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcFinished, + ECoderFinishMode finishMode, ECoderStatus *status); + +SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, + ECoderFinishMode finishMode, ECoderStatus *status); + +/* +If you decode full xz stream(s), then you can call XzUnpacker_IsStreamWasFinished() +after successful XzUnpacker_CodeFull() or after last call of XzUnpacker_Code(). +*/ + +BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p); + +/* +XzUnpacker_GetExtraSize() returns then number of unconfirmed bytes, + if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state. +These bytes can be some data after xz archive, or +it can be start of new xz stream. + +Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of +xz stream in two cases, if XzUnpacker_Code() returns: + res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT + res == SZ_ERROR_NO_ARCHIVE +*/ + +UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p); + + +/* + for random block decoding: + XzUnpacker_Init(); + set CXzUnpacker::streamFlags + XzUnpacker_PrepareToRandomBlockDecoding() + loop + { + XzUnpacker_Code() + XzUnpacker_IsBlockFinished() + } +*/ + +void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p); +BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p); + +#define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags)) + + + + + + +/* ---- Single-Thread and Multi-Thread xz Decoding with Input/Output Streams ---- */ + +/* + if (CXzDecMtProps::numThreads > 1), the decoder can try to use + Multi-Threading. The decoder analyses xz block header, and if + there are pack size and unpack size values stored in xz block header, + the decoder reads compressed data of block to internal buffers, + and then it can start parallel decoding, if there are another blocks. + The decoder can switch back to Single-Thread decoding after some conditions. + + The sequence of calls for xz decoding with in/out Streams: + { + XzDecMt_Create() + XzDecMtProps_Init(XzDecMtProps) to set default values of properties + // then you can change some XzDecMtProps parameters with required values + // here you can set the number of threads and (memUseMax) - the maximum + Memory usage for multithreading decoding. + for() + { + XzDecMt_Decode() // one call per one file + } + XzDecMt_Destroy() + } +*/ + + +typedef struct +{ + size_t inBufSize_ST; // size of input buffer for Single-Thread decoding + size_t outStep_ST; // size of output buffer for Single-Thread decoding + BoolInt ignoreErrors; // if set to 1, the decoder can ignore some errors and it skips broken parts of data. + + #ifndef Z7_ST + unsigned numThreads; // the number of threads for Multi-Thread decoding. if (umThreads == 1) it will use Single-thread decoding + size_t inBufSize_MT; // size of small input data buffers for Multi-Thread decoding. Big number of such small buffers can be created + size_t memUseMax; // the limit of total memory usage for Multi-Thread decoding. + // it's recommended to set (memUseMax) manually to value that is smaller of total size of RAM in computer. + #endif +} CXzDecMtProps; + +void XzDecMtProps_Init(CXzDecMtProps *p); + +typedef struct CXzDecMt CXzDecMt; +typedef CXzDecMt * CXzDecMtHandle; +// Z7_DECLARE_HANDLE(CXzDecMtHandle) + +/* + alloc : XzDecMt uses CAlignOffsetAlloc internally for addresses allocated by (alloc). + allocMid : for big allocations, aligned allocation is better +*/ + +CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid); +void XzDecMt_Destroy(CXzDecMtHandle p); + + +typedef struct +{ + Byte UnpackSize_Defined; + Byte NumStreams_Defined; + Byte NumBlocks_Defined; + + Byte DataAfterEnd; // there are some additional data after good xz streams, and that data is not new xz stream. + Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data + + UInt64 InSize; // pack size processed. That value doesn't include the data after + // end of xz stream, if that data was not correct + UInt64 OutSize; + + UInt64 NumStreams; + UInt64 NumBlocks; + + SRes DecodeRes; // the error code of xz streams data decoding + SRes ReadRes; // error code from ISeqInStream:Read() + SRes ProgressRes; // error code from ICompressProgress:Progress() + + SRes CombinedRes; // Combined result error code that shows main rusult + // = S_OK, if there is no error. + // but check also (DataAfterEnd) that can show additional minor errors. + + SRes CombinedRes_Type; // = SZ_ERROR_READ, if error from ISeqInStream + // = SZ_ERROR_PROGRESS, if error from ICompressProgress + // = SZ_ERROR_WRITE, if error from ISeqOutStream + // = SZ_ERROR_* codes for decoding +} CXzStatInfo; + +void XzStatInfo_Clear(CXzStatInfo *p); + +/* + +XzDecMt_Decode() +SRes: it's combined decoding result. It also is equal to stat->CombinedRes. + + SZ_OK - no error + check also output value in (stat->DataAfterEnd) + that can show additional possible error + + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_NO_ARCHIVE - is not xz archive + SZ_ERROR_ARCHIVE - Headers error + SZ_ERROR_DATA - Data Error + SZ_ERROR_UNSUPPORTED - Unsupported method or method properties + SZ_ERROR_CRC - CRC Error + SZ_ERROR_INPUT_EOF - it needs more input data + SZ_ERROR_WRITE - ISeqOutStream error + (SZ_ERROR_READ) - ISeqInStream errors + (SZ_ERROR_PROGRESS) - ICompressProgress errors + // SZ_ERROR_THREAD - error in multi-threading functions + MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function +*/ + +SRes XzDecMt_Decode(CXzDecMtHandle p, + const CXzDecMtProps *props, + const UInt64 *outDataSize, // NULL means undefined + int finishMode, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished + ISeqOutStreamPtr outStream, + // Byte *outBuf, size_t *outBufSize, + ISeqInStreamPtr inStream, + // const Byte *inData, size_t inDataSize, + CXzStatInfo *stat, // out: decoding results and statistics + int *isMT, // out: 0 means that ST (Single-Thread) version was used + // 1 means that MT (Multi-Thread) version was used + ICompressProgressPtr progress); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/XzCrc64.c b/libraries/lzma/C/XzCrc64.c new file mode 100644 index 0000000000..c2fad6cdaa --- /dev/null +++ b/libraries/lzma/C/XzCrc64.c @@ -0,0 +1,80 @@ +/* XzCrc64.c -- CRC64 calculation +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "XzCrc64.h" +#include "CpuArch.h" + +#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) + +#ifdef MY_CPU_LE + #define CRC64_NUM_TABLES 4 +#else + #define CRC64_NUM_TABLES 5 + + UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +#ifndef MY_CPU_BE + UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +typedef UInt64 (Z7_FASTCALL *CRC64_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); + +static CRC64_FUNC g_Crc64Update; +UInt64 g_Crc64Table[256 * CRC64_NUM_TABLES]; + +UInt64 Z7_FASTCALL Crc64Update(UInt64 v, const void *data, size_t size) +{ + return g_Crc64Update(v, data, size, g_Crc64Table); +} + +UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size) +{ + return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL; +} + +void Z7_FASTCALL Crc64GenerateTable(void) +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt64 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1))); + g_Crc64Table[i] = r; + } + for (i = 256; i < 256 * CRC64_NUM_TABLES; i++) + { + const UInt64 r = g_Crc64Table[(size_t)i - 256]; + g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); + } + + #ifdef MY_CPU_LE + + g_Crc64Update = XzCrc64UpdateT4; + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_Crc64Update = XzCrc64UpdateT4; + else + #endif + { + for (i = 256 * CRC64_NUM_TABLES - 1; i >= 256; i--) + { + const UInt64 x = g_Crc64Table[(size_t)i - 256]; + g_Crc64Table[i] = Z7_BSWAP64(x); + } + g_Crc64Update = XzCrc64UpdateT1_BeT4; + } + } + #endif +} + +#undef kCrc64Poly +#undef CRC64_NUM_TABLES diff --git a/libraries/lzma/C/XzCrc64.h b/libraries/lzma/C/XzCrc64.h new file mode 100644 index 0000000000..ca46869a64 --- /dev/null +++ b/libraries/lzma/C/XzCrc64.h @@ -0,0 +1,26 @@ +/* XzCrc64.h -- CRC64 calculation +2023-04-02 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_XZ_CRC64_H +#define ZIP7_INC_XZ_CRC64_H + +#include + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +extern UInt64 g_Crc64Table[]; + +void Z7_FASTCALL Crc64GenerateTable(void); + +#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF) +#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL) +#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt64 Z7_FASTCALL Crc64Update(UInt64 crc, const void *data, size_t size); +UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/XzCrc64Opt.c b/libraries/lzma/C/XzCrc64Opt.c new file mode 100644 index 0000000000..d03374c006 --- /dev/null +++ b/libraries/lzma/C/XzCrc64Opt.c @@ -0,0 +1,61 @@ +/* XzCrc64Opt.c -- CRC64 calculation +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifndef MY_CPU_BE + +#define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC64_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + const UInt32 d = (UInt32)v ^ *(const UInt32 *)(const void *)p; + v = (v >> 32) + ^ (table + 0x300)[((d ) & 0xFF)] + ^ (table + 0x200)[((d >> 8) & 0xFF)] + ^ (table + 0x100)[((d >> 16) & 0xFF)] + ^ (table + 0x000)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC64_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8)) + +UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + table += 0x100; + v = Z7_BSWAP64(v); + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC64_UPDATE_BYTE_2_BE(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + const UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)(const void *)p; + v = (v << 32) + ^ (table + 0x000)[((d ) & 0xFF)] + ^ (table + 0x100)[((d >> 8) & 0xFF)] + ^ (table + 0x200)[((d >> 16) & 0xFF)] + ^ (table + 0x300)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC64_UPDATE_BYTE_2_BE(v, *p); + return Z7_BSWAP64(v); +} + +#endif diff --git a/libraries/lzma/C/XzDec.c b/libraries/lzma/C/XzDec.c new file mode 100644 index 0000000000..a5f703966d --- /dev/null +++ b/libraries/lzma/C/XzDec.c @@ -0,0 +1,2875 @@ +/* XzDec.c -- Xz Decode +2023-04-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #include + +// #define XZ_DUMP + +/* #define XZ_DUMP */ + +#ifdef XZ_DUMP +#include +#endif + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#define PRF_STR(s) PRF(printf("\n" s "\n")) +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) + +#include +#include + +#include "7zCrc.h" +#include "Alloc.h" +#include "Bra.h" +#include "CpuArch.h" +#include "Delta.h" +#include "Lzma2Dec.h" + +// #define USE_SUBBLOCK + +#ifdef USE_SUBBLOCK +#include "Bcj3Dec.c" +#include "SbDec.h" +#endif + +#include "Xz.h" + +#define XZ_CHECK_SIZE_MAX 64 + +#define CODER_BUF_SIZE ((size_t)1 << 17) + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) +{ + unsigned i, limit; + *value = 0; + limit = (maxSize > 9) ? 9 : (unsigned)maxSize; + + for (i = 0; i < limit;) + { + Byte b = p[i]; + *value |= (UInt64)(b & 0x7F) << (7 * i++); + if ((b & 0x80) == 0) + return (b == 0 && i != 1) ? 0 : i; + } + return 0; +} + + +/* ---------- XzBcFilterState ---------- */ + +#define BRA_BUF_SIZE (1 << 14) + +typedef struct +{ + size_t bufPos; + size_t bufConv; + size_t bufTotal; + Byte *buf; // must be aligned for 4 bytes + Xz_Func_BcFilterStateBase_Filter filter_func; + // int encodeMode; + CXzBcFilterStateBase base; + // Byte buf[BRA_BUF_SIZE]; +} CXzBcFilterState; + + +static void XzBcFilterState_Free(void *pp, ISzAllocPtr alloc) +{ + if (pp) + { + CXzBcFilterState *p = ((CXzBcFilterState *)pp); + ISzAlloc_Free(alloc, p->buf); + ISzAlloc_Free(alloc, pp); + } +} + + +static SRes XzBcFilterState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + CXzBcFilterStateBase *p = &((CXzBcFilterState *)pp)->base; + UNUSED_VAR(alloc) + p->ip = 0; + if (p->methodId == XZ_ID_Delta) + { + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + p->delta = (unsigned)props[0] + 1; + } + else + { + if (propSize == 4) + { + UInt32 v = GetUi32(props); + switch (p->methodId) + { + case XZ_ID_PPC: + case XZ_ID_ARM: + case XZ_ID_SPARC: + case XZ_ID_ARM64: + if ((v & 3) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + case XZ_ID_ARMT: + if ((v & 1) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + case XZ_ID_IA64: + if ((v & 0xF) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + } + p->ip = v; + } + else if (propSize != 0) + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; +} + + +static void XzBcFilterState_Init(void *pp) +{ + CXzBcFilterState *p = ((CXzBcFilterState *)pp); + p->bufPos = p->bufConv = p->bufTotal = 0; + p->base.X86_State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL; + if (p->base.methodId == XZ_ID_Delta) + Delta_Init(p->base.delta_State); +} + + +static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] = +{ + Z7_BRANCH_CONV_DEC(PPC), + Z7_BRANCH_CONV_DEC(IA64), + Z7_BRANCH_CONV_DEC(ARM), + Z7_BRANCH_CONV_DEC(ARMT), + Z7_BRANCH_CONV_DEC(SPARC), + Z7_BRANCH_CONV_DEC(ARM64) +}; + +static SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size) +{ + switch (p->methodId) + { + case XZ_ID_Delta: + Delta_Decode(p->delta_State, p->delta, data, size); + break; + case XZ_ID_X86: + size = (SizeT)(z7_BranchConvSt_X86_Dec(data, size, p->ip, &p->X86_State) - data); + break; + default: + if (p->methodId >= XZ_ID_PPC) + { + const UInt32 i = p->methodId - XZ_ID_PPC; + if (i < Z7_ARRAY_SIZE(g_Funcs_BranchConv_RISC_Dec)) + size = (SizeT)(g_Funcs_BranchConv_RISC_Dec[i](data, size, p->ip) - data); + } + break; + } + p->ip += (UInt32)size; + return size; +} + + +static SizeT XzBcFilterState_Filter(void *pp, Byte *data, SizeT size) +{ + CXzBcFilterState *p = ((CXzBcFilterState *)pp); + return p->filter_func(&p->base, data, size); +} + + +static SRes XzBcFilterState_Code2(void *pp, + Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode, + // int *wasFinished + ECoderStatus *status) +{ + CXzBcFilterState *p = ((CXzBcFilterState *)pp); + SizeT destRem = *destLen; + SizeT srcRem = *srcLen; + UNUSED_VAR(finishMode) + + *destLen = 0; + *srcLen = 0; + // *wasFinished = False; + *status = CODER_STATUS_NOT_FINISHED; + + while (destRem != 0) + { + { + size_t size = p->bufConv - p->bufPos; + if (size) + { + if (size > destRem) + size = destRem; + memcpy(dest, p->buf + p->bufPos, size); + p->bufPos += size; + *destLen += size; + dest += size; + destRem -= size; + continue; + } + } + + p->bufTotal -= p->bufPos; + memmove(p->buf, p->buf + p->bufPos, p->bufTotal); + p->bufPos = 0; + p->bufConv = 0; + { + size_t size = BRA_BUF_SIZE - p->bufTotal; + if (size > srcRem) + size = srcRem; + memcpy(p->buf + p->bufTotal, src, size); + *srcLen += size; + src += size; + srcRem -= size; + p->bufTotal += size; + } + if (p->bufTotal == 0) + break; + + p->bufConv = p->filter_func(&p->base, p->buf, p->bufTotal); + + if (p->bufConv == 0) + { + if (!srcWasFinished) + break; + p->bufConv = p->bufTotal; + } + } + + if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished) + { + *status = CODER_STATUS_FINISHED_WITH_MARK; + // *wasFinished = 1; + } + + return SZ_OK; +} + + +#define XZ_IS_SUPPORTED_FILTER_ID(id) \ + ((id) >= XZ_ID_Delta && (id) <= XZ_ID_ARM64) + +SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id, + Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc) +{ + CXzBcFilterState *decoder; + if (!XZ_IS_SUPPORTED_FILTER_ID(id)) + return SZ_ERROR_UNSUPPORTED; + decoder = (CXzBcFilterState *)p->p; + if (!decoder) + { + decoder = (CXzBcFilterState *)ISzAlloc_Alloc(alloc, sizeof(CXzBcFilterState)); + if (!decoder) + return SZ_ERROR_MEM; + decoder->buf = ISzAlloc_Alloc(alloc, BRA_BUF_SIZE); + if (!decoder->buf) + { + ISzAlloc_Free(alloc, decoder); + return SZ_ERROR_MEM; + } + p->p = decoder; + p->Free = XzBcFilterState_Free; + p->SetProps = XzBcFilterState_SetProps; + p->Init = XzBcFilterState_Init; + p->Code2 = XzBcFilterState_Code2; + p->Filter = XzBcFilterState_Filter; + decoder->filter_func = func; + } + decoder->base.methodId = (UInt32)id; + // decoder->encodeMode = encodeMode; + return SZ_OK; +} + + + +/* ---------- SbState ---------- */ + +#ifdef USE_SUBBLOCK + +static void SbState_Free(void *pp, ISzAllocPtr alloc) +{ + CSbDec *p = (CSbDec *)pp; + SbDec_Free(p); + ISzAlloc_Free(alloc, pp); +} + +static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + UNUSED_VAR(pp) + UNUSED_VAR(props) + UNUSED_VAR(alloc) + return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static void SbState_Init(void *pp) +{ + SbDec_Init((CSbDec *)pp); +} + +static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished + ECoderStatus *status) +{ + CSbDec *p = (CSbDec *)pp; + SRes res; + UNUSED_VAR(srcWasFinished) + p->dest = dest; + p->destLen = *destLen; + p->src = src; + p->srcLen = *srcLen; + p->finish = finishMode; /* change it */ + res = SbDec_Decode((CSbDec *)pp); + *destLen -= p->destLen; + *srcLen -= p->srcLen; + // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */ + *status = (*destLen == 0 && *srcLen == 0) ? + CODER_STATUS_FINISHED_WITH_MARK : + CODER_STATUS_NOT_FINISHED; + return res; +} + +static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc) +{ + CSbDec *decoder = (CSbDec *)p->p; + if (!decoder) + { + decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec)); + if (!decoder) + return SZ_ERROR_MEM; + p->p = decoder; + p->Free = SbState_Free; + p->SetProps = SbState_SetProps; + p->Init = SbState_Init; + p->Code2 = SbState_Code2; + p->Filter = NULL; + } + SbDec_Construct(decoder); + SbDec_SetAlloc(decoder, alloc); + return SZ_OK; +} + +#endif + + + +/* ---------- Lzma2 ---------- */ + +typedef struct +{ + CLzma2Dec decoder; + BoolInt outBufMode; +} CLzma2Dec_Spec; + + +static void Lzma2State_Free(void *pp, ISzAllocPtr alloc) +{ + CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; + if (p->outBufMode) + Lzma2Dec_FreeProbs(&p->decoder, alloc); + else + Lzma2Dec_Free(&p->decoder, alloc); + ISzAlloc_Free(alloc, pp); +} + +static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + { + CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; + if (p->outBufMode) + return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc); + else + return Lzma2Dec_Allocate(&p->decoder, props[0], alloc); + } +} + +static void Lzma2State_Init(void *pp) +{ + Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder); +} + + +/* + if (outBufMode), then (dest) is not used. Use NULL. + Data is unpacked to (spec->decoder.decoder.dic) output buffer. +*/ + +static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished, + ECoderStatus *status) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp; + ELzmaStatus status2; + /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ + SRes res; + UNUSED_VAR(srcWasFinished) + if (spec->outBufMode) + { + SizeT dicPos = spec->decoder.decoder.dicPos; + SizeT dicLimit = dicPos + *destLen; + res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2); + *destLen = spec->decoder.decoder.dicPos - dicPos; + } + else + res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2); + // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK); + // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder + *status = (ECoderStatus)status2; + return res; +} + + +static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; + if (!spec) + { + spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec)); + if (!spec) + return SZ_ERROR_MEM; + p->p = spec; + p->Free = Lzma2State_Free; + p->SetProps = Lzma2State_SetProps; + p->Init = Lzma2State_Init; + p->Code2 = Lzma2State_Code2; + p->Filter = NULL; + Lzma2Dec_CONSTRUCT(&spec->decoder) + } + spec->outBufMode = False; + if (outBuf) + { + spec->outBufMode = True; + spec->decoder.decoder.dic = outBuf; + spec->decoder.decoder.dicBufSize = outBufSize; + } + return SZ_OK; +} + + +static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; + if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf)) + return SZ_ERROR_FAIL; + if (outBuf) + { + spec->decoder.decoder.dic = outBuf; + spec->decoder.decoder.dicBufSize = outBufSize; + } + return SZ_OK; +} + + + +static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc) +{ + unsigned i; + p->alloc = alloc; + p->buf = NULL; + p->numCoders = 0; + + p->outBufSize = 0; + p->outBuf = NULL; + // p->SingleBufMode = False; + + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) + p->coders[i].p = NULL; +} + + +static void MixCoder_Free(CMixCoder *p) +{ + unsigned i; + p->numCoders = 0; + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) + { + IStateCoder *sc = &p->coders[i]; + if (sc->p) + { + sc->Free(sc->p, p->alloc); + sc->p = NULL; + } + } + if (p->buf) + { + ISzAlloc_Free(p->alloc, p->buf); + p->buf = NULL; /* 9.31: the BUG was fixed */ + } +} + +static void MixCoder_Init(CMixCoder *p) +{ + unsigned i; + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++) + { + p->size[i] = 0; + p->pos[i] = 0; + p->finished[i] = 0; + } + for (i = 0; i < p->numCoders; i++) + { + IStateCoder *coder = &p->coders[i]; + coder->Init(coder->p); + p->results[i] = SZ_OK; + } + p->outWritten = 0; + p->wasFinished = False; + p->res = SZ_OK; + p->status = CODER_STATUS_NOT_SPECIFIED; +} + + +static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) +{ + IStateCoder *sc = &p->coders[coderIndex]; + p->ids[coderIndex] = methodId; + switch (methodId) + { + case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc); + #ifdef USE_SUBBLOCK + case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc); + #endif + } + if (coderIndex == 0) + return SZ_ERROR_UNSUPPORTED; + return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId, + XzBcFilterStateBase_Filter_Dec, p->alloc); +} + + +static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) +{ + IStateCoder *sc = &p->coders[coderIndex]; + switch (methodId) + { + case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize); + } + return SZ_ERROR_UNSUPPORTED; +} + + + +/* + if (destFinish) - then unpack data block is finished at (*destLen) position, + and we can return data that were not processed by filter + +output (status) can be : + CODER_STATUS_NOT_FINISHED + CODER_STATUS_FINISHED_WITH_MARK + CODER_STATUS_NEEDS_MORE_INPUT - not implemented still +*/ + +static SRes MixCoder_Code(CMixCoder *p, + Byte *dest, SizeT *destLen, int destFinish, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + + *destLen = 0; + *srcLen = 0; + + if (p->wasFinished) + return p->res; + + p->status = CODER_STATUS_NOT_FINISHED; + + // if (p->SingleBufMode) + if (p->outBuf) + { + SRes res; + SizeT destLen2, srcLen2; + int wasFinished; + + PRF_STR("------- MixCoder Single ----------") + + srcLen2 = srcLenOrig; + destLen2 = destLenOrig; + + { + IStateCoder *coder = &p->coders[0]; + res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode, + // &wasFinished, + &p->status); + wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK); + } + + p->res = res; + + /* + if (wasFinished) + p->status = CODER_STATUS_FINISHED_WITH_MARK; + else + { + if (res == SZ_OK) + if (destLen2 != destLenOrig) + p->status = CODER_STATUS_NEEDS_MORE_INPUT; + } + */ + + + *srcLen = srcLen2; + src += srcLen2; + p->outWritten += destLen2; + + if (res != SZ_OK || srcWasFinished || wasFinished) + p->wasFinished = True; + + if (p->numCoders == 1) + *destLen = destLen2; + else if (p->wasFinished) + { + unsigned i; + size_t processed = p->outWritten; + + for (i = 1; i < p->numCoders; i++) + { + IStateCoder *coder = &p->coders[i]; + processed = coder->Filter(coder->p, p->outBuf, processed); + if (wasFinished || (destFinish && p->outWritten == destLenOrig)) + processed = p->outWritten; + PRF_STR_INT("filter", i) + } + *destLen = processed; + } + return res; + } + + PRF_STR("standard mix") + + if (p->numCoders != 1) + { + if (!p->buf) + { + p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); + if (!p->buf) + return SZ_ERROR_MEM; + } + + finishMode = CODER_FINISH_ANY; + } + + for (;;) + { + BoolInt processed = False; + BoolInt allFinished = True; + SRes resMain = SZ_OK; + unsigned i; + + p->status = CODER_STATUS_NOT_FINISHED; + /* + if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) + break; + */ + + for (i = 0; i < p->numCoders; i++) + { + SRes res; + IStateCoder *coder = &p->coders[i]; + Byte *dest2; + SizeT destLen2, srcLen2; // destLen2_Orig; + const Byte *src2; + int srcFinished2; + int encodingWasFinished; + ECoderStatus status2; + + if (i == 0) + { + src2 = src; + srcLen2 = srcLenOrig - *srcLen; + srcFinished2 = srcWasFinished; + } + else + { + size_t k = i - 1; + src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k]; + srcLen2 = p->size[k] - p->pos[k]; + srcFinished2 = p->finished[k]; + } + + if (i == p->numCoders - 1) + { + dest2 = dest; + destLen2 = destLenOrig - *destLen; + } + else + { + if (p->pos[i] != p->size[i]) + continue; + dest2 = p->buf + (CODER_BUF_SIZE * i); + destLen2 = CODER_BUF_SIZE; + } + + // destLen2_Orig = destLen2; + + if (p->results[i] != SZ_OK) + { + if (resMain == SZ_OK) + resMain = p->results[i]; + continue; + } + + res = coder->Code2(coder->p, + dest2, &destLen2, + src2, &srcLen2, srcFinished2, + finishMode, + // &encodingWasFinished, + &status2); + + if (res != SZ_OK) + { + p->results[i] = res; + if (resMain == SZ_OK) + resMain = res; + } + + encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK); + + if (!encodingWasFinished) + { + allFinished = False; + if (p->numCoders == 1 && res == SZ_OK) + p->status = status2; + } + + if (i == 0) + { + *srcLen += srcLen2; + src += srcLen2; + } + else + p->pos[(size_t)i - 1] += srcLen2; + + if (i == p->numCoders - 1) + { + *destLen += destLen2; + dest += destLen2; + } + else + { + p->size[i] = destLen2; + p->pos[i] = 0; + p->finished[i] = encodingWasFinished; + } + + if (destLen2 != 0 || srcLen2 != 0) + processed = True; + } + + if (!processed) + { + if (allFinished) + p->status = CODER_STATUS_FINISHED_WITH_MARK; + return resMain; + } + } +} + + +SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf) +{ + *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE); + if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) != + GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE)) + return SZ_ERROR_NO_ARCHIVE; + return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) +{ + return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) + && GetUi32(buf) == CrcCalc(buf + 4, 6) + && flags == GetBe16(buf + 8) + && buf[10] == XZ_FOOTER_SIG_0 + && buf[11] == XZ_FOOTER_SIG_1; +} + +#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ + { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ + if (s == 0) return SZ_ERROR_ARCHIVE; \ + pos += s; } + + +static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p) +{ + const unsigned numFilters = XzBlock_GetNumFilters(p) - 1; + unsigned i; + { + const CXzFilter *f = &p->filters[numFilters]; + if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40) + return False; + } + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &p->filters[i]; + if (f->id == XZ_ID_Delta) + { + if (f->propsSize != 1) + return False; + } + else if (!XZ_IS_SUPPORTED_FILTER_ID(f->id) + || (f->propsSize != 0 && f->propsSize != 4)) + return False; + } + return True; +} + + +SRes XzBlock_Parse(CXzBlock *p, const Byte *header) +{ + unsigned pos; + unsigned numFilters, i; + unsigned headerSize = (unsigned)header[0] << 2; + + /* (headerSize != 0) : another code checks */ + + if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) + return SZ_ERROR_ARCHIVE; + + pos = 1; + p->flags = header[pos++]; + + p->packSize = (UInt64)(Int64)-1; + if (XzBlock_HasPackSize(p)) + { + READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize) + if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63) + return SZ_ERROR_ARCHIVE; + } + + p->unpackSize = (UInt64)(Int64)-1; + if (XzBlock_HasUnpackSize(p)) + { + READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize) + } + + numFilters = XzBlock_GetNumFilters(p); + for (i = 0; i < numFilters; i++) + { + CXzFilter *filter = p->filters + i; + UInt64 size; + READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id) + READ_VARINT_AND_CHECK(header, pos, headerSize, &size) + if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX) + return SZ_ERROR_ARCHIVE; + filter->propsSize = (UInt32)size; + memcpy(filter->props, header + pos, (size_t)size); + pos += (unsigned)size; + + #ifdef XZ_DUMP + printf("\nf[%u] = %2X: ", i, (unsigned)filter->id); + { + unsigned i; + for (i = 0; i < size; i++) + printf(" %2X", filter->props[i]); + } + #endif + } + + if (XzBlock_HasUnsupportedFlags(p)) + return SZ_ERROR_UNSUPPORTED; + + while (pos < headerSize) + if (header[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return SZ_OK; +} + + + + +static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize) +{ + unsigned i; + BoolInt needReInit = True; + unsigned numFilters = XzBlock_GetNumFilters(block); + + if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf))) + { + needReInit = False; + for (i = 0; i < numFilters; i++) + if (p->ids[i] != block->filters[numFilters - 1 - i].id) + { + needReInit = True; + break; + } + } + + // p->SingleBufMode = (outBuf != NULL); + p->outBuf = outBuf; + p->outBufSize = outBufSize; + + // p->SingleBufMode = False; + // outBuf = NULL; + + if (needReInit) + { + MixCoder_Free(p); + for (i = 0; i < numFilters; i++) + { + RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize)) + } + p->numCoders = numFilters; + } + else + { + RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize)) + } + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &block->filters[numFilters - 1 - i]; + IStateCoder *sc = &p->coders[i]; + RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)) + } + + MixCoder_Init(p); + return SZ_OK; +} + + + +void XzUnpacker_Init(CXzUnpacker *p) +{ + p->state = XZ_STATE_STREAM_HEADER; + p->pos = 0; + p->numStartedStreams = 0; + p->numFinishedStreams = 0; + p->numTotalBlocks = 0; + p->padSize = 0; + p->decodeOnlyOneBlock = 0; + + p->parseMode = False; + p->decodeToStreamSignature = False; + + // p->outBuf = NULL; + // p->outBufSize = 0; + p->outDataWritten = 0; +} + + +void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize) +{ + p->outBuf = outBuf; + p->outBufSize = outBufSize; +} + + +void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc) +{ + MixCoder_Construct(&p->decoder, alloc); + p->outBuf = NULL; + p->outBufSize = 0; + XzUnpacker_Init(p); +} + + +void XzUnpacker_Free(CXzUnpacker *p) +{ + MixCoder_Free(&p->decoder); +} + + +void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p) +{ + p->indexSize = 0; + p->numBlocks = 0; + Sha256_Init(&p->sha); + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + p->decodeOnlyOneBlock = 1; +} + + +static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize) +{ + Byte temp[32]; + unsigned num = Xz_WriteVarInt(temp, packSize); + num += Xz_WriteVarInt(temp + num, unpackSize); + Sha256_Update(&p->sha, temp, num); + p->indexSize += num; + p->numBlocks++; +} + + + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcFinished, + ECoderFinishMode finishMode, ECoderStatus *status) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + *destLen = 0; + *srcLen = 0; + *status = CODER_STATUS_NOT_SPECIFIED; + + for (;;) + { + SizeT srcRem; + + if (p->state == XZ_STATE_BLOCK) + { + SizeT destLen2 = destLenOrig - *destLen; + SizeT srcLen2 = srcLenOrig - *srcLen; + SRes res; + + ECoderFinishMode finishMode2 = finishMode; + BoolInt srcFinished2 = srcFinished; + BoolInt destFinish = False; + + if (p->block.packSize != (UInt64)(Int64)-1) + { + UInt64 rem = p->block.packSize - p->packSize; + if (srcLen2 >= rem) + { + srcFinished2 = True; + srcLen2 = (SizeT)rem; + } + if (rem == 0 && p->block.unpackSize == p->unpackSize) + return SZ_ERROR_DATA; + } + + if (p->block.unpackSize != (UInt64)(Int64)-1) + { + UInt64 rem = p->block.unpackSize - p->unpackSize; + if (destLen2 >= rem) + { + destFinish = True; + finishMode2 = CODER_FINISH_END; + destLen2 = (SizeT)rem; + } + } + + /* + if (srcLen2 == 0 && destLen2 == 0) + { + *status = CODER_STATUS_NOT_FINISHED; + return SZ_OK; + } + */ + + { + res = MixCoder_Code(&p->decoder, + (p->outBuf ? NULL : dest), &destLen2, destFinish, + src, &srcLen2, srcFinished2, + finishMode2); + + *status = p->decoder.status; + XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2); + if (!p->outBuf) + dest += destLen2; + p->outDataWritten += destLen2; + } + + (*srcLen) += srcLen2; + src += srcLen2; + p->packSize += srcLen2; + (*destLen) += destLen2; + p->unpackSize += destLen2; + + RINOK(res) + + if (*status != CODER_STATUS_FINISHED_WITH_MARK) + { + if (p->block.packSize == p->packSize + && *status == CODER_STATUS_NEEDS_MORE_INPUT) + { + PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT") + *status = CODER_STATUS_NOT_SPECIFIED; + return SZ_ERROR_DATA; + } + + return SZ_OK; + } + { + XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize); + p->state = XZ_STATE_BLOCK_FOOTER; + p->pos = 0; + p->alignPos = 0; + *status = CODER_STATUS_NOT_SPECIFIED; + + if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize) + || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize)) + { + PRF_STR("ERROR: block.size mismatch") + return SZ_ERROR_DATA; + } + } + // continue; + } + + srcRem = srcLenOrig - *srcLen; + + // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes + if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + switch (p->state) + { + case XZ_STATE_STREAM_HEADER: + { + if (p->pos < XZ_STREAM_HEADER_SIZE) + { + if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos]) + return SZ_ERROR_NO_ARCHIVE; + if (p->decodeToStreamSignature) + return SZ_OK; + p->buf[p->pos++] = *src++; + (*srcLen)++; + } + else + { + RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)) + p->numStartedStreams++; + p->indexSize = 0; + p->numBlocks = 0; + Sha256_Init(&p->sha); + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + } + break; + } + + case XZ_STATE_BLOCK_HEADER: + { + if (p->pos == 0) + { + p->buf[p->pos++] = *src++; + (*srcLen)++; + if (p->buf[0] == 0) + { + if (p->decodeOnlyOneBlock) + return SZ_ERROR_DATA; + p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); + p->indexPos = p->indexPreSize; + p->indexSize += p->indexPreSize; + Sha256_Final(&p->sha, p->shaDigest); + Sha256_Init(&p->sha); + p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); + p->state = XZ_STATE_STREAM_INDEX; + break; + } + p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; + break; + } + + if (p->pos != p->blockHeaderSize) + { + UInt32 cur = p->blockHeaderSize - p->pos; + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + } + else + { + RINOK(XzBlock_Parse(&p->block, p->buf)) + if (!XzBlock_AreSupportedFilters(&p->block)) + return SZ_ERROR_UNSUPPORTED; + p->numTotalBlocks++; + p->state = XZ_STATE_BLOCK; + p->packSize = 0; + p->unpackSize = 0; + XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); + if (p->parseMode) + { + p->headerParsedOk = True; + return SZ_OK; + } + RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize)) + } + break; + } + + case XZ_STATE_BLOCK_FOOTER: + { + if ((((unsigned)p->packSize + p->alignPos) & 3) != 0) + { + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->alignPos++; + if (*src++ != 0) + return SZ_ERROR_CRC; + } + else + { + UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); + UInt32 cur = checkSize - p->pos; + if (cur != 0) + { + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + if (checkSize != p->pos) + break; + } + { + Byte digest[XZ_CHECK_SIZE_MAX]; + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) + return SZ_ERROR_CRC; + if (p->decodeOnlyOneBlock) + { + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + } + } + } + break; + } + + case XZ_STATE_STREAM_INDEX: + { + if (p->pos < p->indexPreSize) + { + (*srcLen)++; + if (*src++ != p->buf[p->pos++]) + return SZ_ERROR_CRC; + } + else + { + if (p->indexPos < p->indexSize) + { + UInt64 cur = p->indexSize - p->indexPos; + if (srcRem > cur) + srcRem = (SizeT)cur; + p->crc = CrcUpdate(p->crc, src, srcRem); + Sha256_Update(&p->sha, src, srcRem); + (*srcLen) += srcRem; + src += srcRem; + p->indexPos += srcRem; + } + else if ((p->indexPos & 3) != 0) + { + Byte b = *src++; + p->crc = CRC_UPDATE_BYTE(p->crc, b); + (*srcLen)++; + p->indexPos++; + p->indexSize++; + if (b != 0) + return SZ_ERROR_CRC; + } + else + { + Byte digest[SHA256_DIGEST_SIZE]; + p->state = XZ_STATE_STREAM_INDEX_CRC; + p->indexSize += 4; + p->pos = 0; + Sha256_Final(&p->sha, digest); + if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) + return SZ_ERROR_CRC; + } + } + break; + } + + case XZ_STATE_STREAM_INDEX_CRC: + { + if (p->pos < 4) + { + (*srcLen)++; + p->buf[p->pos++] = *src++; + } + else + { + const Byte *ptr = p->buf; + p->state = XZ_STATE_STREAM_FOOTER; + p->pos = 0; + if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr)) + return SZ_ERROR_CRC; + } + break; + } + + case XZ_STATE_STREAM_FOOTER: + { + UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + if (p->pos == XZ_STREAM_FOOTER_SIZE) + { + p->state = XZ_STATE_STREAM_PADDING; + p->numFinishedStreams++; + p->padSize = 0; + if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) + return SZ_ERROR_CRC; + } + break; + } + + case XZ_STATE_STREAM_PADDING: + { + if (*src != 0) + { + if (((UInt32)p->padSize & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + p->pos = 0; + p->state = XZ_STATE_STREAM_HEADER; + } + else + { + (*srcLen)++; + src++; + p->padSize++; + } + break; + } + + case XZ_STATE_BLOCK: break; /* to disable GCC warning */ + } + } + /* + if (p->state == XZ_STATE_FINISHED) + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + */ +} + + +SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, + ECoderFinishMode finishMode, ECoderStatus *status) +{ + XzUnpacker_Init(p); + XzUnpacker_SetOutBuf(p, dest, *destLen); + + return XzUnpacker_Code(p, + NULL, destLen, + src, srcLen, True, + finishMode, status); +} + + +BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p) +{ + return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0); +} + +BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p) +{ + return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); +} + +UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p) +{ + UInt64 num = 0; + if (p->state == XZ_STATE_STREAM_PADDING) + num = p->padSize; + else if (p->state == XZ_STATE_STREAM_HEADER) + num = p->padSize + p->pos; + return num; +} + + + + + + + + + + + + + + + + + + + + + +#ifndef Z7_ST +#include "MtDec.h" +#endif + + +void XzDecMtProps_Init(CXzDecMtProps *p) +{ + p->inBufSize_ST = 1 << 18; + p->outStep_ST = 1 << 20; + p->ignoreErrors = False; + + #ifndef Z7_ST + p->numThreads = 1; + p->inBufSize_MT = 1 << 18; + p->memUseMax = sizeof(size_t) << 28; + #endif +} + + + +#ifndef Z7_ST + +/* ---------- CXzDecMtThread ---------- */ + +typedef struct +{ + Byte *outBuf; + size_t outBufSize; + size_t outPreSize; + size_t inPreSize; + size_t inPreHeaderSize; + size_t blockPackSize_for_Index; // including block header and checksum. + size_t blockPackTotal; // including stream header, block header and checksum. + size_t inCodeSize; + size_t outCodeSize; + ECoderStatus status; + SRes codeRes; + BoolInt skipMode; + // BoolInt finishedWithMark; + EMtDecParseState parseState; + BoolInt parsing_Truncated; + BoolInt atBlockHeader; + CXzStreamFlags streamFlags; + // UInt64 numFinishedStreams + UInt64 numStreams; + UInt64 numTotalBlocks; + UInt64 numBlocks; + + BoolInt dec_created; + CXzUnpacker dec; + + Byte mtPad[1 << 7]; +} CXzDecMtThread; + +#endif + + +/* ---------- CXzDecMt ---------- */ + +struct CXzDecMt +{ + CAlignOffsetAlloc alignOffsetAlloc; + ISzAllocPtr allocMid; + + CXzDecMtProps props; + size_t unpackBlockMaxSize; + + ISeqInStreamPtr inStream; + ISeqOutStreamPtr outStream; + ICompressProgressPtr progress; + + BoolInt finishMode; + BoolInt outSize_Defined; + UInt64 outSize; + + UInt64 outProcessed; + UInt64 inProcessed; + UInt64 readProcessed; + BoolInt readWasFinished; + SRes readRes; + SRes writeRes; + + Byte *outBuf; + size_t outBufSize; + Byte *inBuf; + size_t inBufSize; + + CXzUnpacker dec; + + ECoderStatus status; + SRes codeRes; + + #ifndef Z7_ST + BoolInt mainDecoderWasCalled; + // int statErrorDefined; + int finishedDecoderIndex; + + // global values that are used in Parse stage + CXzStreamFlags streamFlags; + // UInt64 numFinishedStreams + UInt64 numStreams; + UInt64 numTotalBlocks; + UInt64 numBlocks; + + // UInt64 numBadBlocks; + SRes mainErrorCode; // it's set to error code, if the size Code() output doesn't patch the size from Parsing stage + // it can be = SZ_ERROR_INPUT_EOF + // it can be = SZ_ERROR_DATA, in some another cases + BoolInt isBlockHeaderState_Parse; + BoolInt isBlockHeaderState_Write; + UInt64 outProcessed_Parse; + BoolInt parsing_Truncated; + + BoolInt mtc_WasConstructed; + CMtDec mtc; + CXzDecMtThread coders[MTDEC_THREADS_MAX]; + #endif +}; + + + +CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) +{ + CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt)); + if (!p) + return NULL; + + AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); + p->alignOffsetAlloc.baseAlloc = alloc; + p->alignOffsetAlloc.numAlignBits = 7; + p->alignOffsetAlloc.offset = 0; + + p->allocMid = allocMid; + + p->outBuf = NULL; + p->outBufSize = 0; + p->inBuf = NULL; + p->inBufSize = 0; + + XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt); + + p->unpackBlockMaxSize = 0; + + XzDecMtProps_Init(&p->props); + + #ifndef Z7_ST + p->mtc_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTDEC_THREADS_MAX; i++) + { + CXzDecMtThread *coder = &p->coders[i]; + coder->dec_created = False; + coder->outBuf = NULL; + coder->outBufSize = 0; + } + } + #endif + + return (CXzDecMtHandle)p; +} + + +#ifndef Z7_ST + +static void XzDecMt_FreeOutBufs(CXzDecMt *p) +{ + unsigned i; + for (i = 0; i < MTDEC_THREADS_MAX; i++) + { + CXzDecMtThread *coder = &p->coders[i]; + if (coder->outBuf) + { + ISzAlloc_Free(p->allocMid, coder->outBuf); + coder->outBuf = NULL; + coder->outBufSize = 0; + } + } + p->unpackBlockMaxSize = 0; +} + +#endif + + + +static void XzDecMt_FreeSt(CXzDecMt *p) +{ + XzUnpacker_Free(&p->dec); + + if (p->outBuf) + { + ISzAlloc_Free(p->allocMid, p->outBuf); + p->outBuf = NULL; + } + p->outBufSize = 0; + + if (p->inBuf) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBuf = NULL; + } + p->inBufSize = 0; +} + + +// #define GET_CXzDecMt_p CXzDecMt *p = pp; + +void XzDecMt_Destroy(CXzDecMtHandle p) +{ + // GET_CXzDecMt_p + + XzDecMt_FreeSt(p); + + #ifndef Z7_ST + + if (p->mtc_WasConstructed) + { + MtDec_Destruct(&p->mtc); + p->mtc_WasConstructed = False; + } + { + unsigned i; + for (i = 0; i < MTDEC_THREADS_MAX; i++) + { + CXzDecMtThread *t = &p->coders[i]; + if (t->dec_created) + { + // we don't need to free dict here + XzUnpacker_Free(&t->dec); + t->dec_created = False; + } + } + } + XzDecMt_FreeOutBufs(p); + + #endif + + ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p); +} + + + +#ifndef Z7_ST + +static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) +{ + CXzDecMt *me = (CXzDecMt *)obj; + CXzDecMtThread *coder = &me->coders[coderIndex]; + size_t srcSize = cc->srcSize; + + cc->srcSize = 0; + cc->outPos = 0; + cc->state = MTDEC_PARSE_CONTINUE; + + cc->canCreateNewThread = True; + + if (cc->startCall) + { + coder->outPreSize = 0; + coder->inPreSize = 0; + coder->inPreHeaderSize = 0; + coder->parseState = MTDEC_PARSE_CONTINUE; + coder->parsing_Truncated = False; + coder->skipMode = False; + coder->codeRes = SZ_OK; + coder->status = CODER_STATUS_NOT_SPECIFIED; + coder->inCodeSize = 0; + coder->outCodeSize = 0; + + coder->numStreams = me->numStreams; + coder->numTotalBlocks = me->numTotalBlocks; + coder->numBlocks = me->numBlocks; + + if (!coder->dec_created) + { + XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt); + coder->dec_created = True; + } + + XzUnpacker_Init(&coder->dec); + + if (me->isBlockHeaderState_Parse) + { + coder->dec.streamFlags = me->streamFlags; + coder->atBlockHeader = True; + XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec); + } + else + { + coder->atBlockHeader = False; + me->isBlockHeaderState_Parse = True; + } + + coder->dec.numStartedStreams = me->numStreams; + coder->dec.numTotalBlocks = me->numTotalBlocks; + coder->dec.numBlocks = me->numBlocks; + } + + while (!coder->skipMode) + { + ECoderStatus status; + SRes res; + size_t srcSize2 = srcSize; + size_t destSize = (size_t)0 - 1; + + coder->dec.parseMode = True; + coder->dec.headerParsedOk = False; + + PRF_STR_INT("Parse", srcSize2) + + res = XzUnpacker_Code(&coder->dec, + NULL, &destSize, + cc->src, &srcSize2, cc->srcFinished, + CODER_FINISH_END, &status); + + // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2)); + + coder->codeRes = res; + coder->status = status; + cc->srcSize += srcSize2; + srcSize -= srcSize2; + coder->inPreHeaderSize += srcSize2; + coder->inPreSize = coder->inPreHeaderSize; + + if (res != SZ_OK) + { + cc->state = + coder->parseState = MTDEC_PARSE_END; + /* + if (res == SZ_ERROR_MEM) + return res; + return SZ_OK; + */ + return; // res; + } + + if (coder->dec.headerParsedOk) + { + const CXzBlock *block = &coder->dec.block; + if (XzBlock_HasUnpackSize(block) + // && block->unpackSize <= me->props.outBlockMax + && XzBlock_HasPackSize(block)) + { + { + if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax) + { + cc->state = MTDEC_PARSE_OVERFLOW; + return; // SZ_OK; + } + } + { + UInt64 packSize = block->packSize; + UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); + UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags); + UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize; + // if (blockPackSum <= me->props.inBlockMax) + // unpackBlockMaxSize + { + coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize); + coder->blockPackTotal = (size_t)blockPackSum; + coder->outPreSize = (size_t)block->unpackSize; + coder->streamFlags = coder->dec.streamFlags; + me->streamFlags = coder->dec.streamFlags; + coder->skipMode = True; + break; + } + } + } + } + else + // if (coder->inPreSize <= me->props.inBlockMax) + { + if (!cc->srcFinished) + return; // SZ_OK; + cc->state = + coder->parseState = MTDEC_PARSE_END; + return; // SZ_OK; + } + cc->state = MTDEC_PARSE_OVERFLOW; + return; // SZ_OK; + } + + // ---------- skipMode ---------- + { + UInt64 rem = coder->blockPackTotal - coder->inPreSize; + size_t cur = srcSize; + if (cur > rem) + cur = (size_t)rem; + cc->srcSize += cur; + coder->inPreSize += cur; + srcSize -= cur; + + if (coder->inPreSize == coder->blockPackTotal) + { + if (srcSize == 0) + { + if (!cc->srcFinished) + return; // SZ_OK; + cc->state = MTDEC_PARSE_END; + } + else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block + cc->state = MTDEC_PARSE_END; + else + { + cc->state = MTDEC_PARSE_NEW; + + { + size_t blockMax = me->unpackBlockMaxSize; + if (blockMax < coder->outPreSize) + blockMax = coder->outPreSize; + { + UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2; + if (me->props.memUseMax < required) + cc->canCreateNewThread = False; + } + } + + if (me->outSize_Defined) + { + // next block can be zero size + const UInt64 rem2 = me->outSize - me->outProcessed_Parse; + if (rem2 < coder->outPreSize) + { + coder->parsing_Truncated = True; + cc->state = MTDEC_PARSE_END; + } + me->outProcessed_Parse += coder->outPreSize; + } + } + } + else if (cc->srcFinished) + cc->state = MTDEC_PARSE_END; + else + return; // SZ_OK; + + coder->parseState = cc->state; + cc->outPos = coder->outPreSize; + + me->numStreams = coder->dec.numStartedStreams; + me->numTotalBlocks = coder->dec.numTotalBlocks; + me->numBlocks = coder->dec.numBlocks + 1; + return; // SZ_OK; + } +} + + +static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex) +{ + CXzDecMt *me = (CXzDecMt *)pp; + CXzDecMtThread *coder = &me->coders[coderIndex]; + Byte *dest; + + if (!coder->dec.headerParsedOk) + return SZ_OK; + + dest = coder->outBuf; + + if (!dest || coder->outBufSize < coder->outPreSize) + { + if (dest) + { + ISzAlloc_Free(me->allocMid, dest); + coder->outBuf = NULL; + coder->outBufSize = 0; + } + { + size_t outPreSize = coder->outPreSize; + if (outPreSize == 0) + outPreSize = 1; + dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize); + } + if (!dest) + return SZ_ERROR_MEM; + coder->outBuf = dest; + coder->outBufSize = coder->outPreSize; + + if (coder->outBufSize > me->unpackBlockMaxSize) + me->unpackBlockMaxSize = coder->outBufSize; + } + + // return SZ_ERROR_MEM; + + XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize); + + { + SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize); + // res = SZ_ERROR_UNSUPPORTED; // to test + coder->codeRes = res; + if (res != SZ_OK) + { + // if (res == SZ_ERROR_MEM) return res; + if (me->props.ignoreErrors && res != SZ_ERROR_MEM) + return SZ_OK; + return res; + } + } + + return SZ_OK; +} + + +static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + // int finished, int blockFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop) +{ + CXzDecMt *me = (CXzDecMt *)pp; + CXzDecMtThread *coder = &me->coders[coderIndex]; + + *inCodePos = coder->inCodeSize; + *outCodePos = coder->outCodeSize; + *stop = True; + + if (srcSize > coder->inPreSize - coder->inCodeSize) + return SZ_ERROR_FAIL; + + if (coder->inCodeSize < coder->inPreHeaderSize) + { + size_t step = coder->inPreHeaderSize - coder->inCodeSize; + if (step > srcSize) + step = srcSize; + src += step; + srcSize -= step; + coder->inCodeSize += step; + *inCodePos = coder->inCodeSize; + if (coder->inCodeSize < coder->inPreHeaderSize) + { + *stop = False; + return SZ_OK; + } + } + + if (!coder->dec.headerParsedOk) + return SZ_OK; + if (!coder->outBuf) + return SZ_OK; + + if (coder->codeRes == SZ_OK) + { + ECoderStatus status; + SRes res; + size_t srcProcessed = srcSize; + size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten; + + // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur)); + + res = XzUnpacker_Code(&coder->dec, + NULL, &outSizeCur, + src, &srcProcessed, srcFinished, + // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY, + CODER_FINISH_END, + &status); + + // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur)); + + coder->codeRes = res; + coder->status = status; + coder->inCodeSize += srcProcessed; + coder->outCodeSize = coder->dec.outDataWritten; + *inCodePos = coder->inCodeSize; + *outCodePos = coder->outCodeSize; + + if (res == SZ_OK) + { + if (srcProcessed == srcSize) + *stop = False; + return SZ_OK; + } + } + + if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM) + { + *inCodePos = coder->inPreSize; + *outCodePos = coder->outPreSize; + return SZ_OK; + } + return coder->codeRes; +} + + +#define XZDECMT_STREAM_WRITE_STEP (1 << 24) + +static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex, + BoolInt needWriteToStream, + const Byte *src, size_t srcSize, BoolInt isCross, + // int srcFinished, + BoolInt *needContinue, + BoolInt *canRecode) +{ + CXzDecMt *me = (CXzDecMt *)pp; + const CXzDecMtThread *coder = &me->coders[coderIndex]; + + // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize)); + + *needContinue = False; + *canRecode = True; + + if (!needWriteToStream) + return SZ_OK; + + if (!coder->dec.headerParsedOk || !coder->outBuf) + { + if (me->finishedDecoderIndex < 0) + me->finishedDecoderIndex = (int)coderIndex; + return SZ_OK; + } + + if (me->finishedDecoderIndex >= 0) + return SZ_OK; + + me->mtc.inProcessed += coder->inCodeSize; + + *canRecode = False; + + { + SRes res; + size_t size = coder->outCodeSize; + Byte *data = coder->outBuf; + + // we use in me->dec: sha, numBlocks, indexSize + + if (!me->isBlockHeaderState_Write) + { + XzUnpacker_PrepareToRandomBlockDecoding(&me->dec); + me->dec.decodeOnlyOneBlock = False; + me->dec.numStartedStreams = coder->dec.numStartedStreams; + me->dec.streamFlags = coder->streamFlags; + + me->isBlockHeaderState_Write = True; + } + + me->dec.numTotalBlocks = coder->dec.numTotalBlocks; + XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize); + + if (coder->outPreSize != size) + { + if (me->props.ignoreErrors) + { + memset(data + size, 0, coder->outPreSize - size); + size = coder->outPreSize; + } + // me->numBadBlocks++; + if (me->mainErrorCode == SZ_OK) + { + if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT) + me->mainErrorCode = SZ_ERROR_INPUT_EOF; + else + me->mainErrorCode = SZ_ERROR_DATA; + } + } + + if (me->writeRes != SZ_OK) + return me->writeRes; + + res = SZ_OK; + { + if (me->outSize_Defined) + { + const UInt64 rem = me->outSize - me->outProcessed; + if (size > rem) + size = (SizeT)rem; + } + + for (;;) + { + size_t cur = size; + size_t written; + if (cur > XZDECMT_STREAM_WRITE_STEP) + cur = XZDECMT_STREAM_WRITE_STEP; + + written = ISeqOutStream_Write(me->outStream, data, cur); + + // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written)); + + me->outProcessed += written; + if (written != cur) + { + me->writeRes = SZ_ERROR_WRITE; + res = me->writeRes; + break; + } + data += cur; + size -= cur; + // PRF_STR_INT("Written size =", size) + if (size == 0) + break; + res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0); + if (res != SZ_OK) + break; + } + } + + if (coder->codeRes != SZ_OK) + if (!me->props.ignoreErrors) + { + me->finishedDecoderIndex = (int)coderIndex; + return res; + } + + RINOK(res) + + if (coder->inPreSize != coder->inCodeSize + || coder->blockPackTotal != coder->inCodeSize) + { + me->finishedDecoderIndex = (int)coderIndex; + return SZ_OK; + } + + if (coder->parseState != MTDEC_PARSE_END) + { + *needContinue = True; + return SZ_OK; + } + } + + // (coder->state == MTDEC_PARSE_END) means that there are no other working threads + // so we can use mtc variables without lock + + PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed) + + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + { + CXzUnpacker *dec = &me->dec; + + PRF_STR_INT("PostSingle", srcSize) + + { + size_t srcProcessed = srcSize; + ECoderStatus status; + size_t outSizeCur = 0; + SRes res; + + // dec->decodeOnlyOneBlock = False; + dec->decodeToStreamSignature = True; + + me->mainDecoderWasCalled = True; + + if (coder->parsing_Truncated) + { + me->parsing_Truncated = True; + return SZ_OK; + } + + /* + We have processed all xz-blocks of stream, + And xz unpacker is at XZ_STATE_BLOCK_HEADER state, where + (src) is a pointer to xz-Index structure. + We finish reading of current xz-Stream, including Zero padding after xz-Stream. + We exit, if we reach extra byte (first byte of new-Stream or another data). + But we don't update input stream pointer for that new extra byte. + If extra byte is not correct first byte of xz-signature, + we have SZ_ERROR_NO_ARCHIVE error here. + */ + + res = XzUnpacker_Code(dec, + NULL, &outSizeCur, + src, &srcProcessed, + me->mtc.readWasFinished, // srcFinished + CODER_FINISH_END, // CODER_FINISH_ANY, + &status); + + // res = SZ_ERROR_ARCHIVE; // for failure test + + me->status = status; + me->codeRes = res; + + if (isCross) + me->mtc.crossStart += srcProcessed; + + me->mtc.inProcessed += srcProcessed; + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + + srcSize -= srcProcessed; + src += srcProcessed; + + if (res != SZ_OK) + { + return SZ_OK; + // return res; + } + + if (dec->state == XZ_STATE_STREAM_HEADER) + { + *needContinue = True; + me->isBlockHeaderState_Parse = False; + me->isBlockHeaderState_Write = False; + + if (!isCross) + { + Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); + if (!crossBuf) + return SZ_ERROR_MEM; + if (srcSize != 0) + memcpy(crossBuf, src, srcSize); + me->mtc.crossStart = 0; + me->mtc.crossEnd = srcSize; + } + + PRF_STR_INT("XZ_STATE_STREAM_HEADER crossEnd = ", (unsigned)me->mtc.crossEnd) + + return SZ_OK; + } + + if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0) + { + return SZ_ERROR_FAIL; + } + + if (me->mtc.readWasFinished) + { + return SZ_OK; + } + } + + { + size_t inPos; + size_t inLim; + // const Byte *inData; + UInt64 inProgressPrev = me->mtc.inProcessed; + + // XzDecMt_Prepare_InBuf_ST(p); + Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); + if (!crossBuf) + return SZ_ERROR_MEM; + + inPos = 0; + inLim = 0; + + // inData = crossBuf; + + for (;;) + { + SizeT inProcessed; + SizeT outProcessed; + ECoderStatus status; + SRes res; + + if (inPos == inLim) + { + if (!me->mtc.readWasFinished) + { + inPos = 0; + inLim = me->mtc.inBufSize; + me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim); + me->mtc.readProcessed += inLim; + if (inLim == 0 || me->mtc.readRes != SZ_OK) + me->mtc.readWasFinished = True; + } + } + + inProcessed = inLim - inPos; + outProcessed = 0; + + res = XzUnpacker_Code(dec, + NULL, &outProcessed, + crossBuf + inPos, &inProcessed, + (inProcessed == 0), // srcFinished + CODER_FINISH_END, &status); + + me->codeRes = res; + me->status = status; + inPos += inProcessed; + me->mtc.inProcessed += inProcessed; + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + + if (res != SZ_OK) + { + return SZ_OK; + // return res; + } + + if (dec->state == XZ_STATE_STREAM_HEADER) + { + *needContinue = True; + me->mtc.crossStart = inPos; + me->mtc.crossEnd = inLim; + me->isBlockHeaderState_Parse = False; + me->isBlockHeaderState_Write = False; + return SZ_OK; + } + + if (status != CODER_STATUS_NEEDS_MORE_INPUT) + return SZ_ERROR_FAIL; + + if (me->mtc.progress) + { + UInt64 inDelta = me->mtc.inProcessed - inProgressPrev; + if (inDelta >= (1 << 22)) + { + RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress)) + inProgressPrev = me->mtc.inProcessed; + } + } + if (me->mtc.readWasFinished) + return SZ_OK; + } + } + } +} + + +#endif + + + +void XzStatInfo_Clear(CXzStatInfo *p) +{ + p->InSize = 0; + p->OutSize = 0; + + p->NumStreams = 0; + p->NumBlocks = 0; + + p->UnpackSize_Defined = False; + + p->NumStreams_Defined = False; + p->NumBlocks_Defined = False; + + p->DataAfterEnd = False; + p->DecodingTruncated = False; + + p->DecodeRes = SZ_OK; + p->ReadRes = SZ_OK; + p->ProgressRes = SZ_OK; + + p->CombinedRes = SZ_OK; + p->CombinedRes_Type = SZ_OK; +} + + + +/* + XzDecMt_Decode_ST() can return SZ_OK or the following errors + - SZ_ERROR_MEM for memory allocation error + - error from XzUnpacker_Code() function + - SZ_ERROR_WRITE for ISeqOutStream::Write(). stat->CombinedRes_Type = SZ_ERROR_WRITE in that case + - ICompressProgress::Progress() error, stat->CombinedRes_Type = SZ_ERROR_PROGRESS. + But XzDecMt_Decode_ST() doesn't return ISeqInStream::Read() errors. + ISeqInStream::Read() result is set to p->readRes. + also it can set stat->CombinedRes_Type to SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. +*/ + +static SRes XzDecMt_Decode_ST(CXzDecMt *p + #ifndef Z7_ST + , BoolInt tMode + #endif + , CXzStatInfo *stat) +{ + size_t outPos; + size_t inPos, inLim; + const Byte *inData; + UInt64 inPrev, outPrev; + + CXzUnpacker *dec; + + #ifndef Z7_ST + if (tMode) + { + XzDecMt_FreeOutBufs(p); + tMode = MtDec_PrepareRead(&p->mtc); + } + #endif + + if (!p->outBuf || p->outBufSize != p->props.outStep_ST) + { + ISzAlloc_Free(p->allocMid, p->outBuf); + p->outBufSize = 0; + p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST); + if (!p->outBuf) + return SZ_ERROR_MEM; + p->outBufSize = p->props.outStep_ST; + } + + if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBufSize = 0; + p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); + if (!p->inBuf) + return SZ_ERROR_MEM; + p->inBufSize = p->props.inBufSize_ST; + } + + dec = &p->dec; + dec->decodeToStreamSignature = False; + // dec->decodeOnlyOneBlock = False; + + XzUnpacker_SetOutBuf(dec, NULL, 0); + + inPrev = p->inProcessed; + outPrev = p->outProcessed; + + inPos = 0; + inLim = 0; + inData = NULL; + outPos = 0; + + for (;;) + { + SizeT outSize; + BoolInt finished; + ECoderFinishMode finishMode; + SizeT inProcessed; + ECoderStatus status; + SRes res; + + SizeT outProcessed; + + + + if (inPos == inLim) + { + #ifndef Z7_ST + if (tMode) + { + inData = MtDec_Read(&p->mtc, &inLim); + inPos = 0; + if (inData) + continue; + tMode = False; + inLim = 0; + } + #endif + + if (!p->readWasFinished) + { + inPos = 0; + inLim = p->inBufSize; + inData = p->inBuf; + p->readRes = ISeqInStream_Read(p->inStream, (void *)p->inBuf, &inLim); + p->readProcessed += inLim; + if (inLim == 0 || p->readRes != SZ_OK) + p->readWasFinished = True; + } + } + + outSize = p->props.outStep_ST - outPos; + + finishMode = CODER_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (outSize >= rem) + { + outSize = (SizeT)rem; + if (p->finishMode) + finishMode = CODER_FINISH_END; + } + } + + inProcessed = inLim - inPos; + outProcessed = outSize; + + res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed, + inData + inPos, &inProcessed, + (inPos == inLim), // srcFinished + finishMode, &status); + + p->codeRes = res; + p->status = status; + + inPos += inProcessed; + outPos += outProcessed; + p->inProcessed += inProcessed; + p->outProcessed += outProcessed; + + finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK); + + if (finished || outProcessed >= outSize) + if (outPos != 0) + { + const size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos); + // p->outProcessed += written; // 21.01: BUG fixed + if (written != outPos) + { + stat->CombinedRes_Type = SZ_ERROR_WRITE; + return SZ_ERROR_WRITE; + } + outPos = 0; + } + + if (p->progress && res == SZ_OK) + { + if (p->inProcessed - inPrev >= (1 << 22) || + p->outProcessed - outPrev >= (1 << 22)) + { + res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed); + if (res != SZ_OK) + { + stat->CombinedRes_Type = SZ_ERROR_PROGRESS; + stat->ProgressRes = res; + return res; + } + inPrev = p->inProcessed; + outPrev = p->outProcessed; + } + } + + if (finished) + { + // p->codeRes is preliminary error from XzUnpacker_Code. + // and it can be corrected later as final result + // so we return SZ_OK here instead of (res); + return SZ_OK; + // return res; + } + } +} + + + +/* +XzStatInfo_SetStat() transforms + CXzUnpacker return code and status to combined CXzStatInfo results. + it can convert SZ_OK to SZ_ERROR_INPUT_EOF + it can convert SZ_ERROR_NO_ARCHIVE to SZ_OK and (DataAfterEnd = 1) +*/ + +static void XzStatInfo_SetStat(const CXzUnpacker *dec, + int finishMode, + // UInt64 readProcessed, + UInt64 inProcessed, + SRes res, // it's result from CXzUnpacker unpacker + ECoderStatus status, + BoolInt decodingTruncated, + CXzStatInfo *stat) +{ + UInt64 extraSize; + + stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0); + stat->InSize = inProcessed; + stat->NumStreams = dec->numStartedStreams; + stat->NumBlocks = dec->numTotalBlocks; + + stat->UnpackSize_Defined = True; + stat->NumStreams_Defined = True; + stat->NumBlocks_Defined = True; + + extraSize = XzUnpacker_GetExtraSize(dec); + + if (res == SZ_OK) + { + if (status == CODER_STATUS_NEEDS_MORE_INPUT) + { + // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams + // any extra data is part of correct data + extraSize = 0; + // if xz stream was not finished, then we need more data + if (!XzUnpacker_IsStreamWasFinished(dec)) + res = SZ_ERROR_INPUT_EOF; + } + else + { + // CODER_STATUS_FINISHED_WITH_MARK is not possible for multi stream xz decoding + // so he we have (status == CODER_STATUS_NOT_FINISHED) + // if (status != CODER_STATUS_FINISHED_WITH_MARK) + if (!decodingTruncated || finishMode) + res = SZ_ERROR_DATA; + } + } + else if (res == SZ_ERROR_NO_ARCHIVE) + { + /* + SZ_ERROR_NO_ARCHIVE is possible for 2 states: + XZ_STATE_STREAM_HEADER - if bad signature or bad CRC + XZ_STATE_STREAM_PADDING - if non-zero padding data + extraSize and inProcessed don't include "bad" byte + */ + // if (inProcessed == extraSize), there was no any good xz stream header, and we keep error + if (inProcessed != extraSize) // if there were good xz streams before error + { + // if (extraSize != 0 || readProcessed != inProcessed) + { + // he we suppose that all xz streams were finsihed OK, and we have + // some extra data after all streams + stat->DataAfterEnd = True; + res = SZ_OK; + } + } + } + + if (stat->DecodeRes == SZ_OK) + stat->DecodeRes = res; + + stat->InSize -= extraSize; +} + + + +SRes XzDecMt_Decode(CXzDecMtHandle p, + const CXzDecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqOutStreamPtr outStream, + // Byte *outBuf, size_t *outBufSize, + ISeqInStreamPtr inStream, + // const Byte *inData, size_t inDataSize, + CXzStatInfo *stat, + int *isMT, + ICompressProgressPtr progress) +{ + // GET_CXzDecMt_p + #ifndef Z7_ST + BoolInt tMode; + #endif + + XzStatInfo_Clear(stat); + + p->props = *props; + + p->inStream = inStream; + p->outStream = outStream; + p->progress = progress; + // p->stat = stat; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + + p->finishMode = finishMode; + + // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test + + p->writeRes = SZ_OK; + p->outProcessed = 0; + p->inProcessed = 0; + p->readProcessed = 0; + p->readWasFinished = False; + p->readRes = SZ_OK; + + p->codeRes = SZ_OK; + p->status = CODER_STATUS_NOT_SPECIFIED; + + XzUnpacker_Init(&p->dec); + + *isMT = False; + + /* + p->outBuf = NULL; + p->outBufSize = 0; + if (!outStream) + { + p->outBuf = outBuf; + p->outBufSize = *outBufSize; + *outBufSize = 0; + } + */ + + + #ifndef Z7_ST + + p->isBlockHeaderState_Parse = False; + p->isBlockHeaderState_Write = False; + // p->numBadBlocks = 0; + p->mainErrorCode = SZ_OK; + p->mainDecoderWasCalled = False; + + tMode = False; + + if (p->props.numThreads > 1) + { + IMtDecCallback2 vt; + BoolInt needContinue; + SRes res; + // we just free ST buffers here + // but we still keep state variables, that was set in XzUnpacker_Init() + XzDecMt_FreeSt(p); + + p->outProcessed_Parse = 0; + p->parsing_Truncated = False; + + p->numStreams = 0; + p->numTotalBlocks = 0; + p->numBlocks = 0; + p->finishedDecoderIndex = -1; + + if (!p->mtc_WasConstructed) + { + p->mtc_WasConstructed = True; + MtDec_Construct(&p->mtc); + } + + p->mtc.mtCallback = &vt; + p->mtc.mtCallbackObject = p; + + p->mtc.progress = progress; + p->mtc.inStream = inStream; + p->mtc.alloc = &p->alignOffsetAlloc.vt; + // p->mtc.inData = inData; + // p->mtc.inDataSize = inDataSize; + p->mtc.inBufSize = p->props.inBufSize_MT; + // p->mtc.inBlockMax = p->props.inBlockMax; + p->mtc.numThreadsMax = p->props.numThreads; + + *isMT = True; + + vt.Parse = XzDecMt_Callback_Parse; + vt.PreCode = XzDecMt_Callback_PreCode; + vt.Code = XzDecMt_Callback_Code; + vt.Write = XzDecMt_Callback_Write; + + + res = MtDec_Code(&p->mtc); + + + stat->InSize = p->mtc.inProcessed; + + p->inProcessed = p->mtc.inProcessed; + p->readRes = p->mtc.readRes; + p->readWasFinished = p->mtc.readWasFinished; + p->readProcessed = p->mtc.readProcessed; + + tMode = True; + needContinue = False; + + if (res == SZ_OK) + { + if (p->mtc.mtProgress.res != SZ_OK) + { + res = p->mtc.mtProgress.res; + stat->ProgressRes = res; + stat->CombinedRes_Type = SZ_ERROR_PROGRESS; + } + else + needContinue = p->mtc.needContinue; + } + + if (!needContinue) + { + { + SRes codeRes; + BoolInt truncated = False; + ECoderStatus status; + const CXzUnpacker *dec; + + stat->OutSize = p->outProcessed; + + if (p->finishedDecoderIndex >= 0) + { + const CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex]; + codeRes = coder->codeRes; + dec = &coder->dec; + status = coder->status; + } + else if (p->mainDecoderWasCalled) + { + codeRes = p->codeRes; + dec = &p->dec; + status = p->status; + truncated = p->parsing_Truncated; + } + else + return SZ_ERROR_FAIL; + + if (p->mainErrorCode != SZ_OK) + stat->DecodeRes = p->mainErrorCode; + + XzStatInfo_SetStat(dec, p->finishMode, + // p->mtc.readProcessed, + p->mtc.inProcessed, + codeRes, status, + truncated, + stat); + } + + if (res == SZ_OK) + { + stat->ReadRes = p->mtc.readRes; + + if (p->writeRes != SZ_OK) + { + res = p->writeRes; + stat->CombinedRes_Type = SZ_ERROR_WRITE; + } + else if (p->mtc.readRes != SZ_OK + // && p->mtc.inProcessed == p->mtc.readProcessed + && stat->DecodeRes == SZ_ERROR_INPUT_EOF) + { + res = p->mtc.readRes; + stat->CombinedRes_Type = SZ_ERROR_READ; + } + else if (stat->DecodeRes != SZ_OK) + res = stat->DecodeRes; + } + + stat->CombinedRes = res; + if (stat->CombinedRes_Type == SZ_OK) + stat->CombinedRes_Type = res; + return res; + } + + PRF_STR("----- decoding ST -----") + } + + #endif + + + *isMT = False; + + { + SRes res = XzDecMt_Decode_ST(p + #ifndef Z7_ST + , tMode + #endif + , stat + ); + + #ifndef Z7_ST + // we must set error code from MT decoding at first + if (p->mainErrorCode != SZ_OK) + stat->DecodeRes = p->mainErrorCode; + #endif + + XzStatInfo_SetStat(&p->dec, + p->finishMode, + // p->readProcessed, + p->inProcessed, + p->codeRes, p->status, + False, // truncated + stat); + + stat->ReadRes = p->readRes; + + if (res == SZ_OK) + { + if (p->readRes != SZ_OK + // && p->inProcessed == p->readProcessed + && stat->DecodeRes == SZ_ERROR_INPUT_EOF) + { + // we set read error as combined error, only if that error was the reason + // of decoding problem + res = p->readRes; + stat->CombinedRes_Type = SZ_ERROR_READ; + } + else if (stat->DecodeRes != SZ_OK) + res = stat->DecodeRes; + } + + stat->CombinedRes = res; + if (stat->CombinedRes_Type == SZ_OK) + stat->CombinedRes_Type = res; + return res; + } +} + +#undef PRF +#undef PRF_STR +#undef PRF_STR_INT_2 diff --git a/libraries/lzma/C/XzEnc.c b/libraries/lzma/C/XzEnc.c new file mode 100644 index 0000000000..22408e2618 --- /dev/null +++ b/libraries/lzma/C/XzEnc.c @@ -0,0 +1,1362 @@ +/* XzEnc.c -- Xz Encode +2023-04-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include +#include + +#include "7zCrc.h" +#include "Bra.h" +#include "CpuArch.h" + +#ifdef USE_SUBBLOCK +#include "Bcj3Enc.c" +#include "SbFind.c" +#include "SbEnc.c" +#endif + +#include "XzEnc.h" + +// #define Z7_ST + +#ifndef Z7_ST +#include "MtCoder.h" +#else +#define MTCODER_THREADS_MAX 1 +#define MTCODER_BLOCKS_MAX 1 +#endif + +#define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3) + +/* max pack size for LZMA2 block + check-64bytrs: */ +#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + 64) + +#define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize)) + + +// #define XzBlock_ClearFlags(p) (p)->flags = 0; +#define XzBlock_ClearFlags_SetNumFilters(p, n) (p)->flags = (Byte)((n) - 1); +#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE; +#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE; + + +static SRes WriteBytes(ISeqOutStreamPtr s, const void *buf, size_t size) +{ + return (ISeqOutStream_Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE; +} + +static SRes WriteBytes_UpdateCrc(ISeqOutStreamPtr s, const void *buf, size_t size, UInt32 *crc) +{ + *crc = CrcUpdate(*crc, buf, size); + return WriteBytes(s, buf, size); +} + + +static SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStreamPtr s) +{ + UInt32 crc; + Byte header[XZ_STREAM_HEADER_SIZE]; + memcpy(header, XZ_SIG, XZ_SIG_SIZE); + header[XZ_SIG_SIZE] = (Byte)(f >> 8); + header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF); + crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE); + SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc) + return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE); +} + + +static SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStreamPtr s) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + + unsigned pos = 1; + unsigned numFilters, i; + header[pos++] = p->flags; + + if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize); + if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize); + numFilters = XzBlock_GetNumFilters(p); + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &p->filters[i]; + pos += Xz_WriteVarInt(header + pos, f->id); + pos += Xz_WriteVarInt(header + pos, f->propsSize); + memcpy(header + pos, f->props, f->propsSize); + pos += f->propsSize; + } + + while ((pos & 3) != 0) + header[pos++] = 0; + + header[0] = (Byte)(pos >> 2); + SetUi32(header + pos, CrcCalc(header, pos)) + return WriteBytes(s, header, pos + 4); +} + + + + +typedef struct +{ + size_t numBlocks; + size_t size; + size_t allocated; + Byte *blocks; +} CXzEncIndex; + + +static void XzEncIndex_Construct(CXzEncIndex *p) +{ + p->numBlocks = 0; + p->size = 0; + p->allocated = 0; + p->blocks = NULL; +} + +static void XzEncIndex_Init(CXzEncIndex *p) +{ + p->numBlocks = 0; + p->size = 0; +} + +static void XzEncIndex_Free(CXzEncIndex *p, ISzAllocPtr alloc) +{ + if (p->blocks) + { + ISzAlloc_Free(alloc, p->blocks); + p->blocks = NULL; + } + p->numBlocks = 0; + p->size = 0; + p->allocated = 0; +} + + +static SRes XzEncIndex_ReAlloc(CXzEncIndex *p, size_t newSize, ISzAllocPtr alloc) +{ + Byte *blocks = (Byte *)ISzAlloc_Alloc(alloc, newSize); + if (!blocks) + return SZ_ERROR_MEM; + if (p->size != 0) + memcpy(blocks, p->blocks, p->size); + if (p->blocks) + ISzAlloc_Free(alloc, p->blocks); + p->blocks = blocks; + p->allocated = newSize; + return SZ_OK; +} + + +static SRes XzEncIndex_PreAlloc(CXzEncIndex *p, UInt64 numBlocks, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc) +{ + UInt64 pos; + { + Byte buf[32]; + unsigned pos2 = Xz_WriteVarInt(buf, totalSize); + pos2 += Xz_WriteVarInt(buf + pos2, unpackSize); + pos = numBlocks * pos2; + } + + if (pos <= p->allocated - p->size) + return SZ_OK; + { + UInt64 newSize64 = p->size + pos; + size_t newSize = (size_t)newSize64; + if (newSize != newSize64) + return SZ_ERROR_MEM; + return XzEncIndex_ReAlloc(p, newSize, alloc); + } +} + + +static SRes XzEncIndex_AddIndexRecord(CXzEncIndex *p, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc) +{ + Byte buf[32]; + unsigned pos = Xz_WriteVarInt(buf, totalSize); + pos += Xz_WriteVarInt(buf + pos, unpackSize); + + if (pos > p->allocated - p->size) + { + size_t newSize = p->allocated * 2 + 16 * 2; + if (newSize < p->size + pos) + return SZ_ERROR_MEM; + RINOK(XzEncIndex_ReAlloc(p, newSize, alloc)) + } + memcpy(p->blocks + p->size, buf, pos); + p->size += pos; + p->numBlocks++; + return SZ_OK; +} + + +static SRes XzEncIndex_WriteFooter(const CXzEncIndex *p, CXzStreamFlags flags, ISeqOutStreamPtr s) +{ + Byte buf[32]; + UInt64 globalPos; + UInt32 crc = CRC_INIT_VAL; + unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks); + + globalPos = pos; + buf[0] = 0; + RINOK(WriteBytes_UpdateCrc(s, buf, pos, &crc)) + RINOK(WriteBytes_UpdateCrc(s, p->blocks, p->size, &crc)) + globalPos += p->size; + + pos = XZ_GET_PAD_SIZE(globalPos); + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + globalPos += pos; + + crc = CrcUpdate(crc, buf + 4 - pos, pos); + SetUi32(buf + 4, CRC_GET_DIGEST(crc)) + + SetUi32(buf + 8 + 4, (UInt32)(globalPos >> 2)) + buf[8 + 8] = (Byte)(flags >> 8); + buf[8 + 9] = (Byte)(flags & 0xFF); + SetUi32(buf + 8, CrcCalc(buf + 8 + 4, 6)) + buf[8 + 10] = XZ_FOOTER_SIG_0; + buf[8 + 11] = XZ_FOOTER_SIG_1; + + return WriteBytes(s, buf + 4 - pos, pos + 4 + 12); +} + + + +/* ---------- CSeqCheckInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + ISeqInStreamPtr realStream; + const Byte *data; + UInt64 limit; + UInt64 processed; + int realStreamFinished; + CXzCheck check; +} CSeqCheckInStream; + +static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned checkMode) +{ + p->limit = (UInt64)(Int64)-1; + p->processed = 0; + p->realStreamFinished = 0; + XzCheck_Init(&p->check, checkMode); +} + +static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest) +{ + XzCheck_Final(&p->check, digest); +} + +static SRes SeqCheckInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqCheckInStream) + size_t size2 = *size; + SRes res = SZ_OK; + + if (p->limit != (UInt64)(Int64)-1) + { + UInt64 rem = p->limit - p->processed; + if (size2 > rem) + size2 = (size_t)rem; + } + if (size2 != 0) + { + if (p->realStream) + { + res = ISeqInStream_Read(p->realStream, data, &size2); + p->realStreamFinished = (size2 == 0) ? 1 : 0; + } + else + memcpy(data, p->data + (size_t)p->processed, size2); + XzCheck_Update(&p->check, data, size2); + p->processed += size2; + } + *size = size2; + return res; +} + + +/* ---------- CSeqSizeOutStream ---------- */ + +typedef struct +{ + ISeqOutStream vt; + ISeqOutStreamPtr realStream; + Byte *outBuf; + size_t outBufLimit; + UInt64 processed; +} CSeqSizeOutStream; + +static size_t SeqSizeOutStream_Write(ISeqOutStreamPtr pp, const void *data, size_t size) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqSizeOutStream) + if (p->realStream) + size = ISeqOutStream_Write(p->realStream, data, size); + else + { + if (size > p->outBufLimit - (size_t)p->processed) + return 0; + memcpy(p->outBuf + (size_t)p->processed, data, size); + } + p->processed += size; + return size; +} + + +/* ---------- CSeqInFilter ---------- */ + +#define FILTER_BUF_SIZE (1 << 20) + +typedef struct +{ + ISeqInStream vt; + ISeqInStreamPtr realStream; + IStateCoder StateCoder; + Byte *buf; + size_t curPos; + size_t endPos; + int srcWasFinished; +} CSeqInFilter; + + +static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Enc[] = +{ + Z7_BRANCH_CONV_ENC(PPC), + Z7_BRANCH_CONV_ENC(IA64), + Z7_BRANCH_CONV_ENC(ARM), + Z7_BRANCH_CONV_ENC(ARMT), + Z7_BRANCH_CONV_ENC(SPARC), + Z7_BRANCH_CONV_ENC(ARM64) +}; + +static SizeT XzBcFilterStateBase_Filter_Enc(CXzBcFilterStateBase *p, Byte *data, SizeT size) +{ + switch (p->methodId) + { + case XZ_ID_Delta: + Delta_Encode(p->delta_State, p->delta, data, size); + break; + case XZ_ID_X86: + size = (SizeT)(z7_BranchConvSt_X86_Enc(data, size, p->ip, &p->X86_State) - data); + break; + default: + if (p->methodId >= XZ_ID_PPC) + { + const UInt32 i = p->methodId - XZ_ID_PPC; + if (i < Z7_ARRAY_SIZE(g_Funcs_BranchConv_RISC_Enc)) + size = (SizeT)(g_Funcs_BranchConv_RISC_Enc[i](data, size, p->ip) - data); + } + break; + } + p->ip += (UInt32)size; + return size; +} + + +static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props, ISzAllocPtr alloc) +{ + if (!p->buf) + { + p->buf = (Byte *)ISzAlloc_Alloc(alloc, FILTER_BUF_SIZE); + if (!p->buf) + return SZ_ERROR_MEM; + } + p->curPos = p->endPos = 0; + p->srcWasFinished = 0; + RINOK(Xz_StateCoder_Bc_SetFromMethod_Func(&p->StateCoder, props->id, XzBcFilterStateBase_Filter_Enc, alloc)) + RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, alloc)) + p->StateCoder.Init(p->StateCoder.p); + return SZ_OK; +} + + +static SRes SeqInFilter_Read(ISeqInStreamPtr pp, void *data, size_t *size) +{ + Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqInFilter) + const size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return SZ_OK; + *size = 0; + + for (;;) + { + if (!p->srcWasFinished && p->curPos == p->endPos) + { + p->curPos = 0; + p->endPos = FILTER_BUF_SIZE; + RINOK(ISeqInStream_Read(p->realStream, p->buf, &p->endPos)) + if (p->endPos == 0) + p->srcWasFinished = 1; + } + { + SizeT srcLen = p->endPos - p->curPos; + ECoderStatus status; + SRes res; + *size = sizeOriginal; + res = p->StateCoder.Code2(p->StateCoder.p, + (Byte *)data, size, + p->buf + p->curPos, &srcLen, + p->srcWasFinished, CODER_FINISH_ANY, + &status); + p->curPos += srcLen; + if (*size != 0 || srcLen == 0 || res != SZ_OK) + return res; + } + } +} + +static void SeqInFilter_Construct(CSeqInFilter *p) +{ + p->buf = NULL; + p->StateCoder.p = NULL; + p->vt.Read = SeqInFilter_Read; +} + +static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc) +{ + if (p->StateCoder.p) + { + p->StateCoder.Free(p->StateCoder.p, alloc); + p->StateCoder.p = NULL; + } + if (p->buf) + { + ISzAlloc_Free(alloc, p->buf); + p->buf = NULL; + } +} + + +/* ---------- CSbEncInStream ---------- */ + +#ifdef USE_SUBBLOCK + +typedef struct +{ + ISeqInStream vt; + ISeqInStreamPtr inStream; + CSbEnc enc; +} CSbEncInStream; + +static SRes SbEncInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size) +{ + CSbEncInStream *p = Z7_CONTAINER_FROM_VTBL(pp, CSbEncInStream, vt); + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return SZ_OK; + + for (;;) + { + if (p->enc.needRead && !p->enc.readWasFinished) + { + size_t processed = p->enc.needReadSizeMax; + RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed)) + p->enc.readPos += processed; + if (processed == 0) + { + p->enc.readWasFinished = True; + p->enc.isFinalFinished = True; + } + p->enc.needRead = False; + } + + *size = sizeOriginal; + RINOK(SbEnc_Read(&p->enc, data, size)) + if (*size != 0 || !p->enc.needRead) + return SZ_OK; + } +} + +void SbEncInStream_Construct(CSbEncInStream *p, ISzAllocPtr alloc) +{ + SbEnc_Construct(&p->enc, alloc); + p->vt.Read = SbEncInStream_Read; +} + +SRes SbEncInStream_Init(CSbEncInStream *p) +{ + return SbEnc_Init(&p->enc); +} + +void SbEncInStream_Free(CSbEncInStream *p) +{ + SbEnc_Free(&p->enc); +} + +#endif + + + +/* ---------- CXzProps ---------- */ + + +void XzFilterProps_Init(CXzFilterProps *p) +{ + p->id = 0; + p->delta = 0; + p->ip = 0; + p->ipDefined = False; +} + +void XzProps_Init(CXzProps *p) +{ + p->checkId = XZ_CHECK_CRC32; + p->blockSize = XZ_PROPS_BLOCK_SIZE_AUTO; + p->numBlockThreads_Reduced = -1; + p->numBlockThreads_Max = -1; + p->numTotalThreads = -1; + p->reduceSize = (UInt64)(Int64)-1; + p->forceWriteSizesInHeader = 0; + // p->forceWriteSizesInHeader = 1; + + XzFilterProps_Init(&p->filterProps); + Lzma2EncProps_Init(&p->lzma2Props); +} + + +static void XzEncProps_Normalize_Fixed(CXzProps *p) +{ + UInt64 fileSize; + int t1, t1n, t2, t2r, t3; + { + CLzma2EncProps tp = p->lzma2Props; + if (tp.numTotalThreads <= 0) + tp.numTotalThreads = p->numTotalThreads; + Lzma2EncProps_Normalize(&tp); + t1n = tp.numTotalThreads; + } + + t1 = p->lzma2Props.numTotalThreads; + t2 = p->numBlockThreads_Max; + t3 = p->numTotalThreads; + + if (t2 > MTCODER_THREADS_MAX) + t2 = MTCODER_THREADS_MAX; + + if (t3 <= 0) + { + if (t2 <= 0) + t2 = 1; + t3 = t1n * t2; + } + else if (t2 <= 0) + { + t2 = t3 / t1n; + if (t2 == 0) + { + t1 = 1; + t2 = t3; + } + if (t2 > MTCODER_THREADS_MAX) + t2 = MTCODER_THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzma2Props.numTotalThreads = t1; + + t2r = t2; + + fileSize = p->reduceSize; + + if ((p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) + p->lzma2Props.lzmaProps.reduceSize = p->blockSize; + + Lzma2EncProps_Normalize(&p->lzma2Props); + + t1 = p->lzma2Props.numTotalThreads; + + { + if (t2 > 1 && fileSize != (UInt64)(Int64)-1) + { + UInt64 numBlocks = fileSize / p->blockSize; + if (numBlocks * p->blockSize != fileSize) + numBlocks++; + if (numBlocks < (unsigned)t2) + { + t2r = (int)numBlocks; + if (t2r == 0) + t2r = 1; + t3 = t1 * t2r; + } + } + } + + p->numBlockThreads_Max = t2; + p->numBlockThreads_Reduced = t2r; + p->numTotalThreads = t3; +} + + +static void XzProps_Normalize(CXzProps *p) +{ + /* we normalize xzProps properties, but we normalize only some of CXzProps::lzma2Props properties. + Lzma2Enc_SetProps() will normalize lzma2Props later. */ + + if (p->blockSize == XZ_PROPS_BLOCK_SIZE_SOLID) + { + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + p->numBlockThreads_Reduced = 1; + p->numBlockThreads_Max = 1; + if (p->lzma2Props.numTotalThreads <= 0) + p->lzma2Props.numTotalThreads = p->numTotalThreads; + return; + } + else + { + CLzma2EncProps *lzma2 = &p->lzma2Props; + if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO) + { + // xz-auto + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + + if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID) + { + // if (xz-auto && lzma2-solid) - we use solid for both + p->blockSize = XZ_PROPS_BLOCK_SIZE_SOLID; + p->numBlockThreads_Reduced = 1; + p->numBlockThreads_Max = 1; + if (p->lzma2Props.numTotalThreads <= 0) + p->lzma2Props.numTotalThreads = p->numTotalThreads; + } + else + { + // if (xz-auto && (lzma2-auto || lzma2-fixed_) + // we calculate block size for lzma2 and use that block size for xz, lzma2 uses single-chunk per block + CLzma2EncProps tp = p->lzma2Props; + if (tp.numTotalThreads <= 0) + tp.numTotalThreads = p->numTotalThreads; + + Lzma2EncProps_Normalize(&tp); + + p->blockSize = tp.blockSize; // fixed or solid + p->numBlockThreads_Reduced = tp.numBlockThreads_Reduced; + p->numBlockThreads_Max = tp.numBlockThreads_Max; + if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO) + lzma2->blockSize = tp.blockSize; // fixed or solid, LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID + if (lzma2->lzmaProps.reduceSize > tp.blockSize && tp.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID) + lzma2->lzmaProps.reduceSize = tp.blockSize; + lzma2->numBlockThreads_Reduced = 1; + lzma2->numBlockThreads_Max = 1; + return; + } + } + else + { + // xz-fixed + // we can use xz::reduceSize or xz::blockSize as base for lzmaProps::reduceSize + + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + { + UInt64 r = p->reduceSize; + if (r > p->blockSize || r == (UInt64)(Int64)-1) + r = p->blockSize; + lzma2->lzmaProps.reduceSize = r; + } + if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO) + lzma2->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID; + else if (lzma2->blockSize > p->blockSize && lzma2->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID) + lzma2->blockSize = p->blockSize; + + XzEncProps_Normalize_Fixed(p); + } + } +} + + +/* ---------- CLzma2WithFilters ---------- */ + +typedef struct +{ + CLzma2EncHandle lzma2; + CSeqInFilter filter; + + #ifdef USE_SUBBLOCK + CSbEncInStream sb; + #endif +} CLzma2WithFilters; + + +static void Lzma2WithFilters_Construct(CLzma2WithFilters *p) +{ + p->lzma2 = NULL; + SeqInFilter_Construct(&p->filter); + + #ifdef USE_SUBBLOCK + SbEncInStream_Construct(&p->sb, alloc); + #endif +} + + +static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p, ISzAllocPtr alloc, ISzAllocPtr bigAlloc) +{ + if (!p->lzma2) + { + p->lzma2 = Lzma2Enc_Create(alloc, bigAlloc); + if (!p->lzma2) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + + +static void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc) +{ + #ifdef USE_SUBBLOCK + SbEncInStream_Free(&p->sb); + #endif + + SeqInFilter_Free(&p->filter, alloc); + if (p->lzma2) + { + Lzma2Enc_Destroy(p->lzma2); + p->lzma2 = NULL; + } +} + + +typedef struct +{ + UInt64 unpackSize; + UInt64 totalSize; + size_t headerSize; +} CXzEncBlockInfo; + + +static SRes Xz_CompressBlock( + CLzma2WithFilters *lzmaf, + + ISeqOutStreamPtr outStream, + Byte *outBufHeader, + Byte *outBufData, size_t outBufDataLimit, + + ISeqInStreamPtr inStream, + // UInt64 expectedSize, + const Byte *inBuf, // used if (!inStream) + size_t inBufSize, // used if (!inStream), it's block size, props->blockSize is ignored + + const CXzProps *props, + ICompressProgressPtr progress, + int *inStreamFinished, /* only for inStream version */ + CXzEncBlockInfo *blockSizes, + ISzAllocPtr alloc, + ISzAllocPtr allocBig) +{ + CSeqCheckInStream checkInStream; + CSeqSizeOutStream seqSizeOutStream; + CXzBlock block; + unsigned filterIndex = 0; + CXzFilter *filter = NULL; + const CXzFilterProps *fp = &props->filterProps; + if (fp->id == 0) + fp = NULL; + + *inStreamFinished = False; + + RINOK(Lzma2WithFilters_Create(lzmaf, alloc, allocBig)) + + RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, &props->lzma2Props)) + + // XzBlock_ClearFlags(&block) + XzBlock_ClearFlags_SetNumFilters(&block, 1 + (fp ? 1 : 0)) + + if (fp) + { + filter = &block.filters[filterIndex++]; + filter->id = fp->id; + filter->propsSize = 0; + + if (fp->id == XZ_ID_Delta) + { + filter->props[0] = (Byte)(fp->delta - 1); + filter->propsSize = 1; + } + else if (fp->ipDefined) + { + Byte *ptr = filter->props; + SetUi32(ptr, fp->ip) + filter->propsSize = 4; + } + } + + { + CXzFilter *f = &block.filters[filterIndex++]; + f->id = XZ_ID_LZMA2; + f->propsSize = 1; + f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2); + } + + seqSizeOutStream.vt.Write = SeqSizeOutStream_Write; + seqSizeOutStream.realStream = outStream; + seqSizeOutStream.outBuf = outBufData; + seqSizeOutStream.outBufLimit = outBufDataLimit; + seqSizeOutStream.processed = 0; + + /* + if (expectedSize != (UInt64)(Int64)-1) + { + block.unpackSize = expectedSize; + if (props->blockSize != (UInt64)(Int64)-1) + if (expectedSize > props->blockSize) + block.unpackSize = props->blockSize; + XzBlock_SetHasUnpackSize(&block) + } + */ + + if (outStream) + { + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt)) + } + + checkInStream.vt.Read = SeqCheckInStream_Read; + SeqCheckInStream_Init(&checkInStream, props->checkId); + + checkInStream.realStream = inStream; + checkInStream.data = inBuf; + checkInStream.limit = props->blockSize; + if (!inStream) + checkInStream.limit = inBufSize; + + if (fp) + { + #ifdef USE_SUBBLOCK + if (fp->id == XZ_ID_Subblock) + { + lzmaf->sb.inStream = &checkInStream.vt; + RINOK(SbEncInStream_Init(&lzmaf->sb)) + } + else + #endif + { + lzmaf->filter.realStream = &checkInStream.vt; + RINOK(SeqInFilter_Init(&lzmaf->filter, filter, alloc)) + } + } + + { + SRes res; + Byte *outBuf = NULL; + size_t outSize = 0; + BoolInt useStream = (fp || inStream); + // useStream = True; + + if (!useStream) + { + XzCheck_Update(&checkInStream.check, inBuf, inBufSize); + checkInStream.processed = inBufSize; + } + + if (!outStream) + { + outBuf = seqSizeOutStream.outBuf; // + (size_t)seqSizeOutStream.processed; + outSize = seqSizeOutStream.outBufLimit; // - (size_t)seqSizeOutStream.processed; + } + + res = Lzma2Enc_Encode2(lzmaf->lzma2, + outBuf ? NULL : &seqSizeOutStream.vt, + outBuf, + outBuf ? &outSize : NULL, + + useStream ? + (fp ? + ( + #ifdef USE_SUBBLOCK + (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.vt: + #endif + &lzmaf->filter.vt) : + &checkInStream.vt) : NULL, + + useStream ? NULL : inBuf, + useStream ? 0 : inBufSize, + + progress); + + if (outBuf) + seqSizeOutStream.processed += outSize; + + RINOK(res) + blockSizes->unpackSize = checkInStream.processed; + } + { + Byte buf[4 + 64]; + unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed); + UInt64 packSize = seqSizeOutStream.processed; + + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + + SeqCheckInStream_GetDigest(&checkInStream, buf + 4); + RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize), padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId))) + + blockSizes->totalSize = seqSizeOutStream.processed - padSize; + + if (!outStream) + { + seqSizeOutStream.outBuf = outBufHeader; + seqSizeOutStream.outBufLimit = XZ_BLOCK_HEADER_SIZE_MAX; + seqSizeOutStream.processed = 0; + + block.unpackSize = blockSizes->unpackSize; + XzBlock_SetHasUnpackSize(&block) + + block.packSize = packSize; + XzBlock_SetHasPackSize(&block) + + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt)) + + blockSizes->headerSize = (size_t)seqSizeOutStream.processed; + blockSizes->totalSize += seqSizeOutStream.processed; + } + } + + if (inStream) + *inStreamFinished = checkInStream.realStreamFinished; + else + { + *inStreamFinished = False; + if (checkInStream.processed != inBufSize) + return SZ_ERROR_FAIL; + } + + return SZ_OK; +} + + + +typedef struct +{ + ICompressProgress vt; + ICompressProgressPtr progress; + UInt64 inOffset; + UInt64 outOffset; +} CCompressProgress_XzEncOffset; + + +static SRes CompressProgress_XzEncOffset_Progress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize) +{ + const CCompressProgress_XzEncOffset *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CCompressProgress_XzEncOffset, vt); + inSize += p->inOffset; + outSize += p->outOffset; + return ICompressProgress_Progress(p->progress, inSize, outSize); +} + + + + +struct CXzEnc +{ + ISzAllocPtr alloc; + ISzAllocPtr allocBig; + + CXzProps xzProps; + UInt64 expectedDataSize; + + CXzEncIndex xzIndex; + + CLzma2WithFilters lzmaf_Items[MTCODER_THREADS_MAX]; + + size_t outBufSize; /* size of allocated outBufs[i] */ + Byte *outBufs[MTCODER_BLOCKS_MAX]; + + #ifndef Z7_ST + unsigned checkType; + ISeqOutStreamPtr outStream; + BoolInt mtCoder_WasConstructed; + CMtCoder mtCoder; + CXzEncBlockInfo EncBlocks[MTCODER_BLOCKS_MAX]; + #endif +}; + + +static void XzEnc_Construct(CXzEnc *p) +{ + unsigned i; + + XzEncIndex_Construct(&p->xzIndex); + + for (i = 0; i < MTCODER_THREADS_MAX; i++) + Lzma2WithFilters_Construct(&p->lzmaf_Items[i]); + + #ifndef Z7_ST + p->mtCoder_WasConstructed = False; + { + for (i = 0; i < MTCODER_BLOCKS_MAX; i++) + p->outBufs[i] = NULL; + p->outBufSize = 0; + } + #endif +} + + +static void XzEnc_FreeOutBufs(CXzEnc *p) +{ + unsigned i; + for (i = 0; i < MTCODER_BLOCKS_MAX; i++) + if (p->outBufs[i]) + { + ISzAlloc_Free(p->alloc, p->outBufs[i]); + p->outBufs[i] = NULL; + } + p->outBufSize = 0; +} + + +static void XzEnc_Free(CXzEnc *p, ISzAllocPtr alloc) +{ + unsigned i; + + XzEncIndex_Free(&p->xzIndex, alloc); + + for (i = 0; i < MTCODER_THREADS_MAX; i++) + Lzma2WithFilters_Free(&p->lzmaf_Items[i], alloc); + + #ifndef Z7_ST + if (p->mtCoder_WasConstructed) + { + MtCoder_Destruct(&p->mtCoder); + p->mtCoder_WasConstructed = False; + } + XzEnc_FreeOutBufs(p); + #endif +} + + +CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CXzEnc *p = (CXzEnc *)ISzAlloc_Alloc(alloc, sizeof(CXzEnc)); + if (!p) + return NULL; + XzEnc_Construct(p); + XzProps_Init(&p->xzProps); + XzProps_Normalize(&p->xzProps); + p->expectedDataSize = (UInt64)(Int64)-1; + p->alloc = alloc; + p->allocBig = allocBig; + return (CXzEncHandle)p; +} + +// #define GET_CXzEnc_p CXzEnc *p = (CXzEnc *)(void *)pp; + +void XzEnc_Destroy(CXzEncHandle p) +{ + // GET_CXzEnc_p + XzEnc_Free(p, p->alloc); + ISzAlloc_Free(p->alloc, p); +} + + +SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props) +{ + // GET_CXzEnc_p + p->xzProps = *props; + XzProps_Normalize(&p->xzProps); + return SZ_OK; +} + + +void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize) +{ + // GET_CXzEnc_p + p->expectedDataSize = expectedDataSiize; +} + + + + +#ifndef Z7_ST + +static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished) +{ + CXzEnc *me = (CXzEnc *)pp; + SRes res; + CMtProgressThunk progressThunk; + + Byte *dest = me->outBufs[outBufIndex]; + + UNUSED_VAR(finished) + + { + CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; + bInfo->totalSize = 0; + bInfo->unpackSize = 0; + bInfo->headerSize = 0; + } + + if (!dest) + { + dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); + if (!dest) + return SZ_ERROR_MEM; + me->outBufs[outBufIndex] = dest; + } + + MtProgressThunk_CreateVTable(&progressThunk); + progressThunk.mtProgress = &me->mtCoder.mtProgress; + MtProgressThunk_INIT(&progressThunk) + + { + CXzEncBlockInfo blockSizes; + int inStreamFinished; + + res = Xz_CompressBlock( + &me->lzmaf_Items[coderIndex], + + NULL, + dest, + dest + XZ_BLOCK_HEADER_SIZE_MAX, me->outBufSize - XZ_BLOCK_HEADER_SIZE_MAX, + + NULL, + // srcSize, // expectedSize + src, srcSize, + + &me->xzProps, + &progressThunk.vt, + &inStreamFinished, + &blockSizes, + me->alloc, + me->allocBig); + + if (res == SZ_OK) + me->EncBlocks[outBufIndex] = blockSizes; + + return res; + } +} + + +static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex) +{ + CXzEnc *me = (CXzEnc *)pp; + + const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; + const Byte *data = me->outBufs[outBufIndex]; + + RINOK(WriteBytes(me->outStream, data, bInfo->headerSize)) + + { + UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize); + RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize)) + } + + return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc); +} + +#endif + + + +SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress) +{ + // GET_CXzEnc_p + + const CXzProps *props = &p->xzProps; + + XzEncIndex_Init(&p->xzIndex); + { + UInt64 numBlocks = 1; + UInt64 blockSize = props->blockSize; + + if (blockSize != XZ_PROPS_BLOCK_SIZE_SOLID + && props->reduceSize != (UInt64)(Int64)-1) + { + numBlocks = props->reduceSize / blockSize; + if (numBlocks * blockSize != props->reduceSize) + numBlocks++; + } + else + blockSize = (UInt64)1 << 62; + + RINOK(XzEncIndex_PreAlloc(&p->xzIndex, numBlocks, blockSize, XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(blockSize), p->alloc)) + } + + RINOK(Xz_WriteHeader((CXzStreamFlags)props->checkId, outStream)) + + + #ifndef Z7_ST + if (props->numBlockThreads_Reduced > 1) + { + IMtCoderCallback2 vt; + + if (!p->mtCoder_WasConstructed) + { + p->mtCoder_WasConstructed = True; + MtCoder_Construct(&p->mtCoder); + } + + vt.Code = XzEnc_MtCallback_Code; + vt.Write = XzEnc_MtCallback_Write; + + p->checkType = props->checkId; + p->xzProps = *props; + + p->outStream = outStream; + + p->mtCoder.allocBig = p->allocBig; + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.inData = NULL; + p->mtCoder.inDataSize = 0; + p->mtCoder.mtCallback = &vt; + p->mtCoder.mtCallbackObject = p; + + if ( props->blockSize == XZ_PROPS_BLOCK_SIZE_SOLID + || props->blockSize == XZ_PROPS_BLOCK_SIZE_AUTO) + return SZ_ERROR_FAIL; + + p->mtCoder.blockSize = (size_t)props->blockSize; + if (p->mtCoder.blockSize != props->blockSize) + return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ + + { + size_t destBlockSize = XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(p->mtCoder.blockSize); + if (destBlockSize < p->mtCoder.blockSize) + return SZ_ERROR_PARAM; + if (p->outBufSize != destBlockSize) + XzEnc_FreeOutBufs(p); + p->outBufSize = destBlockSize; + } + + p->mtCoder.numThreadsMax = (unsigned)props->numBlockThreads_Max; + p->mtCoder.expectedDataSize = p->expectedDataSize; + + RINOK(MtCoder_Code(&p->mtCoder)) + } + else + #endif + { + int writeStartSizes; + CCompressProgress_XzEncOffset progress2; + Byte *bufData = NULL; + size_t bufSize = 0; + + progress2.vt.Progress = CompressProgress_XzEncOffset_Progress; + progress2.inOffset = 0; + progress2.outOffset = 0; + progress2.progress = progress; + + writeStartSizes = 0; + + if (props->blockSize != XZ_PROPS_BLOCK_SIZE_SOLID) + { + writeStartSizes = (props->forceWriteSizesInHeader > 0); + + if (writeStartSizes) + { + size_t t2; + size_t t = (size_t)props->blockSize; + if (t != props->blockSize) + return SZ_ERROR_PARAM; + t = XZ_GET_MAX_BLOCK_PACK_SIZE(t); + if (t < props->blockSize) + return SZ_ERROR_PARAM; + t2 = XZ_BLOCK_HEADER_SIZE_MAX + t; + if (!p->outBufs[0] || t2 != p->outBufSize) + { + XzEnc_FreeOutBufs(p); + p->outBufs[0] = (Byte *)ISzAlloc_Alloc(p->alloc, t2); + if (!p->outBufs[0]) + return SZ_ERROR_MEM; + p->outBufSize = t2; + } + bufData = p->outBufs[0] + XZ_BLOCK_HEADER_SIZE_MAX; + bufSize = t; + } + } + + for (;;) + { + CXzEncBlockInfo blockSizes; + int inStreamFinished; + + /* + UInt64 rem = (UInt64)(Int64)-1; + if (props->reduceSize != (UInt64)(Int64)-1 + && props->reduceSize >= progress2.inOffset) + rem = props->reduceSize - progress2.inOffset; + */ + + blockSizes.headerSize = 0; // for GCC + + RINOK(Xz_CompressBlock( + &p->lzmaf_Items[0], + + writeStartSizes ? NULL : outStream, + writeStartSizes ? p->outBufs[0] : NULL, + bufData, bufSize, + + inStream, + // rem, + NULL, 0, + + props, + progress ? &progress2.vt : NULL, + &inStreamFinished, + &blockSizes, + p->alloc, + p->allocBig)) + + { + UInt64 totalPackFull = blockSizes.totalSize + XZ_GET_PAD_SIZE(blockSizes.totalSize); + + if (writeStartSizes) + { + RINOK(WriteBytes(outStream, p->outBufs[0], blockSizes.headerSize)) + RINOK(WriteBytes(outStream, bufData, (size_t)totalPackFull - blockSizes.headerSize)) + } + + RINOK(XzEncIndex_AddIndexRecord(&p->xzIndex, blockSizes.unpackSize, blockSizes.totalSize, p->alloc)) + + progress2.inOffset += blockSizes.unpackSize; + progress2.outOffset += totalPackFull; + } + + if (inStreamFinished) + break; + } + } + + return XzEncIndex_WriteFooter(&p->xzIndex, (CXzStreamFlags)props->checkId, outStream); +} + + +#include "Alloc.h" + +SRes Xz_Encode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, + const CXzProps *props, ICompressProgressPtr progress) +{ + SRes res; + CXzEncHandle xz = XzEnc_Create(&g_Alloc, &g_BigAlloc); + if (!xz) + return SZ_ERROR_MEM; + res = XzEnc_SetProps(xz, props); + if (res == SZ_OK) + res = XzEnc_Encode(xz, outStream, inStream, progress); + XzEnc_Destroy(xz); + return res; +} + + +SRes Xz_EncodeEmpty(ISeqOutStreamPtr outStream) +{ + SRes res; + CXzEncIndex xzIndex; + XzEncIndex_Construct(&xzIndex); + res = Xz_WriteHeader((CXzStreamFlags)0, outStream); + if (res == SZ_OK) + res = XzEncIndex_WriteFooter(&xzIndex, (CXzStreamFlags)0, outStream); + XzEncIndex_Free(&xzIndex, NULL); // g_Alloc + return res; +} diff --git a/libraries/lzma/C/XzEnc.h b/libraries/lzma/C/XzEnc.h new file mode 100644 index 0000000000..77b78c014b --- /dev/null +++ b/libraries/lzma/C/XzEnc.h @@ -0,0 +1,61 @@ +/* XzEnc.h -- Xz Encode +2023-04-13 : Igor Pavlov : Public domain */ + +#ifndef ZIP7_INC_XZ_ENC_H +#define ZIP7_INC_XZ_ENC_H + +#include "Lzma2Enc.h" + +#include "Xz.h" + +EXTERN_C_BEGIN + + +#define XZ_PROPS_BLOCK_SIZE_AUTO LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO +#define XZ_PROPS_BLOCK_SIZE_SOLID LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID + + +typedef struct +{ + UInt32 id; + UInt32 delta; + UInt32 ip; + int ipDefined; +} CXzFilterProps; + +void XzFilterProps_Init(CXzFilterProps *p); + + +typedef struct +{ + CLzma2EncProps lzma2Props; + CXzFilterProps filterProps; + unsigned checkId; + UInt64 blockSize; + int numBlockThreads_Reduced; + int numBlockThreads_Max; + int numTotalThreads; + int forceWriteSizesInHeader; + UInt64 reduceSize; +} CXzProps; + +void XzProps_Init(CXzProps *p); + +typedef struct CXzEnc CXzEnc; +typedef CXzEnc * CXzEncHandle; +// Z7_DECLARE_HANDLE(CXzEncHandle) + +CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig); +void XzEnc_Destroy(CXzEncHandle p); +SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props); +void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize); +SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress); + +SRes Xz_Encode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, + const CXzProps *props, ICompressProgressPtr progress); + +SRes Xz_EncodeEmpty(ISeqOutStreamPtr outStream); + +EXTERN_C_END + +#endif diff --git a/libraries/lzma/C/XzIn.c b/libraries/lzma/C/XzIn.c new file mode 100644 index 0000000000..d0fc763679 --- /dev/null +++ b/libraries/lzma/C/XzIn.c @@ -0,0 +1,340 @@ +/* XzIn.c - Xz input +2023-04-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" + +/* +#define XZ_FOOTER_SIG_CHECK(p) (memcmp((p), XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0) +*/ +#define XZ_FOOTER_SIG_CHECK(p) ((p)[0] == XZ_FOOTER_SIG_0 && (p)[1] == XZ_FOOTER_SIG_1) + + +SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream) +{ + Byte sig[XZ_STREAM_HEADER_SIZE]; + size_t processedSize = XZ_STREAM_HEADER_SIZE; + RINOK(SeqInStream_ReadMax(inStream, sig, &processedSize)) + if (processedSize != XZ_STREAM_HEADER_SIZE + || memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0) + return SZ_ERROR_NO_ARCHIVE; + return Xz_ParseHeader(p, sig); +} + +#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ + { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ + if (s == 0) return SZ_ERROR_ARCHIVE; \ + pos += s; } + +SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + unsigned headerSize; + *headerSizeRes = 0; + RINOK(SeqInStream_ReadByte(inStream, &header[0])) + headerSize = (unsigned)header[0]; + if (headerSize == 0) + { + *headerSizeRes = 1; + *isIndex = True; + return SZ_OK; + } + + *isIndex = False; + headerSize = (headerSize << 2) + 4; + *headerSizeRes = headerSize; + { + size_t processedSize = headerSize - 1; + RINOK(SeqInStream_ReadMax(inStream, header + 1, &processedSize)) + if (processedSize != headerSize - 1) + return SZ_ERROR_INPUT_EOF; + } + return XzBlock_Parse(p, header); +} + +#define ADD_SIZE_CHECK(size, val) \ + { UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } + +UInt64 Xz_GetUnpackSize(const CXzStream *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->numBlocks; i++) + { + ADD_SIZE_CHECK(size, p->blocks[i].unpackSize) + } + return size; +} + +UInt64 Xz_GetPackSize(const CXzStream *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->numBlocks; i++) + { + ADD_SIZE_CHECK(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3) + } + return size; +} + +/* +SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStreamPtr inStream) +{ + return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f)); +} +*/ + +static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc) +{ + size_t numBlocks, pos = 1; + UInt32 crc; + + if (size < 5 || buf[0] != 0) + return SZ_ERROR_ARCHIVE; + + size -= 4; + crc = CrcCalc(buf, size); + if (crc != GetUi32(buf + size)) + return SZ_ERROR_ARCHIVE; + + { + UInt64 numBlocks64; + READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64) + numBlocks = (size_t)numBlocks64; + if (numBlocks != numBlocks64 || numBlocks * 2 > size) + return SZ_ERROR_ARCHIVE; + } + + Xz_Free(p, alloc); + if (numBlocks != 0) + { + size_t i; + p->numBlocks = numBlocks; + p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); + if (!p->blocks) + return SZ_ERROR_MEM; + for (i = 0; i < numBlocks; i++) + { + CXzBlockSizes *block = &p->blocks[i]; + READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize) + READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize) + if (block->totalSize == 0) + return SZ_ERROR_ARCHIVE; + } + } + while ((pos & 3) != 0) + if (buf[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static SRes Xz_ReadIndex(CXzStream *p, ILookInStreamPtr stream, UInt64 indexSize, ISzAllocPtr alloc) +{ + SRes res; + size_t size; + Byte *buf; + if (indexSize > ((UInt32)1 << 31)) + return SZ_ERROR_UNSUPPORTED; + size = (size_t)indexSize; + if (size != indexSize) + return SZ_ERROR_UNSUPPORTED; + buf = (Byte *)ISzAlloc_Alloc(alloc, size); + if (!buf) + return SZ_ERROR_MEM; + res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); + if (res == SZ_OK) + res = Xz_ReadIndex2(p, buf, size, alloc); + ISzAlloc_Free(alloc, buf); + return res; +} + +static SRes LookInStream_SeekRead_ForArc(ILookInStreamPtr stream, UInt64 offset, void *buf, size_t size) +{ + RINOK(LookInStream_SeekTo(stream, offset)) + return LookInStream_Read(stream, buf, size); + /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */ +} + +static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startOffset, ISzAllocPtr alloc) +{ + UInt64 indexSize; + Byte buf[XZ_STREAM_FOOTER_SIZE]; + UInt64 pos = (UInt64)*startOffset; + + if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + + pos -= XZ_STREAM_FOOTER_SIZE; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)) + + if (!XZ_FOOTER_SIG_CHECK(buf + 10)) + { + UInt32 total = 0; + pos += XZ_STREAM_FOOTER_SIZE; + + for (;;) + { + size_t i; + #define TEMP_BUF_SIZE (1 << 10) + Byte temp[TEMP_BUF_SIZE]; + + i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos; + pos -= i; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i)) + total += (UInt32)i; + for (; i != 0; i--) + if (temp[i - 1] != 0) + break; + if (i != 0) + { + if ((i & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + pos += i; + break; + } + if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) + return SZ_ERROR_NO_ARCHIVE; + } + + if (pos < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + pos -= XZ_STREAM_FOOTER_SIZE; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)) + if (!XZ_FOOTER_SIG_CHECK(buf + 10)) + return SZ_ERROR_NO_ARCHIVE; + } + + p->flags = (CXzStreamFlags)GetBe16(buf + 8); + + if (!XzFlags_IsSupported(p->flags)) + return SZ_ERROR_UNSUPPORTED; + + { + /* to eliminate GCC 6.3 warning: + dereferencing type-punned pointer will break strict-aliasing rules */ + const Byte *buf_ptr = buf; + if (GetUi32(buf_ptr) != CrcCalc(buf + 4, 6)) + return SZ_ERROR_ARCHIVE; + } + + indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; + + if (pos < indexSize) + return SZ_ERROR_ARCHIVE; + + pos -= indexSize; + RINOK(LookInStream_SeekTo(stream, pos)) + RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)) + + { + UInt64 totalSize = Xz_GetPackSize(p); + if (totalSize == XZ_SIZE_OVERFLOW + || totalSize >= ((UInt64)1 << 63) + || pos < totalSize + XZ_STREAM_HEADER_SIZE) + return SZ_ERROR_ARCHIVE; + pos -= (totalSize + XZ_STREAM_HEADER_SIZE); + RINOK(LookInStream_SeekTo(stream, pos)) + *startOffset = (Int64)pos; + } + { + CXzStreamFlags headerFlags; + CSecToRead secToRead; + SecToRead_CreateVTable(&secToRead); + secToRead.realStream = stream; + + RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt)) + return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; + } +} + + +/* ---------- Xz Streams ---------- */ + +void Xzs_Construct(CXzs *p) +{ + p->num = p->numAllocated = 0; + p->streams = 0; +} + +void Xzs_Free(CXzs *p, ISzAllocPtr alloc) +{ + size_t i; + for (i = 0; i < p->num; i++) + Xz_Free(&p->streams[i], alloc); + ISzAlloc_Free(alloc, p->streams); + p->num = p->numAllocated = 0; + p->streams = 0; +} + +UInt64 Xzs_GetNumBlocks(const CXzs *p) +{ + UInt64 num = 0; + size_t i; + for (i = 0; i < p->num; i++) + num += p->streams[i].numBlocks; + return num; +} + +UInt64 Xzs_GetUnpackSize(const CXzs *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->num; i++) + { + ADD_SIZE_CHECK(size, Xz_GetUnpackSize(&p->streams[i])) + } + return size; +} + +/* +UInt64 Xzs_GetPackSize(const CXzs *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->num; i++) + { + ADD_SIZE_CHECK(size, Xz_GetTotalSize(&p->streams[i])) + } + return size; +} +*/ + +SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr stream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc) +{ + Int64 endOffset = 0; + RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END)) + *startOffset = endOffset; + for (;;) + { + CXzStream st; + SRes res; + Xz_Construct(&st); + res = Xz_ReadBackward(&st, stream, startOffset, alloc); + st.startOffset = (UInt64)*startOffset; + RINOK(res) + if (p->num == p->numAllocated) + { + const size_t newNum = p->num + p->num / 4 + 1; + void *data = ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream)); + if (!data) + return SZ_ERROR_MEM; + p->numAllocated = newNum; + if (p->num != 0) + memcpy(data, p->streams, p->num * sizeof(CXzStream)); + ISzAlloc_Free(alloc, p->streams); + p->streams = (CXzStream *)data; + } + p->streams[p->num++] = st; + if (*startOffset == 0) + break; + RINOK(LookInStream_SeekTo(stream, (UInt64)*startOffset)) + if (progress && ICompressProgress_Progress(progress, (UInt64)(endOffset - *startOffset), (UInt64)(Int64)-1) != SZ_OK) + return SZ_ERROR_PROGRESS; + } + return SZ_OK; +} diff --git a/libraries/lzma/CMakeLists.txt b/libraries/lzma/CMakeLists.txt index 2ef5b078fb..e1c668b296 100644 --- a/libraries/lzma/CMakeLists.txt +++ b/libraries/lzma/CMakeLists.txt @@ -1,32 +1,51 @@ -cmake_minimum_required( VERSION 3.1.0 ) - make_release_only() -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_PPMD_SUPPPORT" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DZ7_PPMD_SUPPORT" ) find_package(Threads) add_library( lzma STATIC + C/7zAlloc.c C/7zArcIn.c C/7zBuf.c + C/7zBuf2.c C/7zCrc.c C/7zCrcOpt.c C/7zDec.c + C/7zFile.c C/7zStream.c + C/Alloc.c C/Bcj2.c + C/Bcj2Enc.c C/Bra.c C/Bra86.c - C/BraIA64.c C/CpuArch.c C/Delta.c + C/DllSecur.c C/LzFind.c C/LzFindMt.c C/LzFindOpt.c C/Lzma2Dec.c + C/Lzma2DecMt.c + C/Lzma2Enc.c C/LzmaDec.c C/LzmaEnc.c + C/LzmaLib.c + C/MtCoder.c + C/MtDec.c C/Ppmd7.c C/Ppmd7Dec.c + C/Ppmd7Enc.c + C/Sha256.c + C/Sha256Opt.c + C/Sort.c + C/SwapBytes.c C/Threads.c + C/Xz.c + C/XzCrc64.c + C/XzCrc64Opt.c + C/XzDec.c + C/XzEnc.c + C/XzIn.c ) target_link_libraries( lzma Threads::Threads ) diff --git a/libraries/miniz/CMakeLists.txt b/libraries/miniz/CMakeLists.txt new file mode 100644 index 0000000000..b5a5529f24 --- /dev/null +++ b/libraries/miniz/CMakeLists.txt @@ -0,0 +1,9 @@ +make_release_only() + +if (MSVC) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4244" ) +endif() + +add_library( miniz miniz.c ) +target_compile_definitions( miniz PRIVATE -DMINIZ_NO_STDIO ) +target_include_directories( miniz INTERFACE "$" ) \ No newline at end of file diff --git a/libraries/miniz/miniz.c b/libraries/miniz/miniz.c new file mode 100644 index 0000000000..8d0032f9e4 --- /dev/null +++ b/libraries/miniz/miniz.c @@ -0,0 +1,7833 @@ +#include "miniz.h" +/************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * All Rights Reserved. + * + * 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. + * + **************************************************************************/ + + + +typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1]; +typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1]; +typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1]; + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- zlib-style API's */ + +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) +{ + mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); + size_t block_len = buf_len % 5552; + if (!ptr) + return MZ_ADLER32_INIT; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) + s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; + } + return (s2 << 16) + s1; +} + +/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */ +#if 0 + mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) + { + static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; + mz_uint32 crcu32 = (mz_uint32)crc; + if (!ptr) + return MZ_CRC32_INIT; + crcu32 = ~crcu32; + while (buf_len--) + { + mz_uint8 b = *ptr++; + crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; + crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; + } + return ~crcu32; + } +#elif defined(USE_EXTERNAL_MZCRC) +/* If USE_EXTERNAL_CRC is defined, an external module will export the + * mz_crc32() symbol for us to use, e.g. an SSE-accelerated version. + * Depending on the impl, it may be necessary to ~ the input/output crc values. + */ +mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len); +#else +/* Faster, but larger CPU cache footprint. + */ +mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) +{ + static const mz_uint32 s_crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, + 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, + 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, + 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, + 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, + 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, + 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, + 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, + 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, + 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, + 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, + 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, + 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, + 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, + 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, + 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, + 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, + 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, + 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, + 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, + 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, + 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, + 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF; + const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr; + + while (buf_len >= 4) + { + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF]; + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF]; + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF]; + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF]; + pByte_buf += 4; + buf_len -= 4; + } + + while (buf_len) + { + crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF]; + ++pByte_buf; + --buf_len; + } + + return ~crc32; +} +#endif + +void mz_free(void *p) +{ + MZ_FREE(p); +} + +MINIZ_EXPORT void *miniz_def_alloc_func(void *opaque, size_t items, size_t size) +{ + (void)opaque, (void)items, (void)size; + return MZ_MALLOC(items * size); +} +MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address) +{ + (void)opaque, (void)address; + MZ_FREE(address); +} +MINIZ_EXPORT void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size) +{ + (void)opaque, (void)address, (void)items, (void)size; + return MZ_REALLOC(address, items * size); +} + +const char *mz_version(void) +{ + return MZ_VERSION; +} + +#ifndef MINIZ_NO_ZLIB_APIS + +#ifndef MINIZ_NO_DEFLATE_APIS + +int mz_deflateInit(mz_streamp pStream, int level) +{ + return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); +} + +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) +{ + tdefl_compressor *pComp; + mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); + + if (!pStream) + return MZ_STREAM_ERROR; + if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) + return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = MZ_ADLER32_INIT; + pStream->msg = NULL; + pStream->reserved = 0; + pStream->total_in = 0; + pStream->total_out = 0; + if (!pStream->zalloc) + pStream->zalloc = miniz_def_alloc_func; + if (!pStream->zfree) + pStream->zfree = miniz_def_free_func; + + pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pComp; + + if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) + { + mz_deflateEnd(pStream); + return MZ_PARAM_ERROR; + } + + return MZ_OK; +} + +int mz_deflateReset(mz_streamp pStream) +{ + if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) + return MZ_STREAM_ERROR; + pStream->total_in = pStream->total_out = 0; + tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags); + return MZ_OK; +} + +int mz_deflate(mz_streamp pStream, int flush) +{ + size_t in_bytes, out_bytes; + mz_ulong orig_total_in, orig_total_out; + int mz_status = MZ_OK; + + if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) + return MZ_STREAM_ERROR; + if (!pStream->avail_out) + return MZ_BUF_ERROR; + + if (flush == MZ_PARTIAL_FLUSH) + flush = MZ_SYNC_FLUSH; + + if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) + return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; + + orig_total_in = pStream->total_in; + orig_total_out = pStream->total_out; + for (;;) + { + tdefl_status defl_status; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; + + defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state); + + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (defl_status < 0) + { + mz_status = MZ_STREAM_ERROR; + break; + } + else if (defl_status == TDEFL_STATUS_DONE) + { + mz_status = MZ_STREAM_END; + break; + } + else if (!pStream->avail_out) + break; + else if ((!pStream->avail_in) && (flush != MZ_FINISH)) + { + if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) + break; + return MZ_BUF_ERROR; /* Can't make forward progress without some input. + */ + } + } + return mz_status; +} + +int mz_deflateEnd(mz_streamp pStream) +{ + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) +{ + (void)pStream; + /* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */ + return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); +} + +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) +{ + int status; + mz_stream stream; + memset(&stream, 0, sizeof(stream)); + + /* In case mz_ulong is 64-bits (argh I hate longs). */ + if ((mz_uint64)(source_len | *pDest_len) > 0xFFFFFFFFU) + return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_deflateInit(&stream, level); + if (status != MZ_OK) + return status; + + status = mz_deflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_deflateEnd(&stream); + return (status == MZ_OK) ? MZ_BUF_ERROR : status; + } + + *pDest_len = stream.total_out; + return mz_deflateEnd(&stream); +} + +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); +} + +mz_ulong mz_compressBound(mz_ulong source_len) +{ + return mz_deflateBound(NULL, source_len); +} + +#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ + +#ifndef MINIZ_NO_INFLATE_APIS + +typedef struct +{ + tinfl_decompressor m_decomp; + mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; + int m_window_bits; + mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; + tinfl_status m_last_status; +} inflate_state; + +int mz_inflateInit2(mz_streamp pStream, int window_bits) +{ + inflate_state *pDecomp; + if (!pStream) + return MZ_STREAM_ERROR; + if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) + return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + if (!pStream->zalloc) + pStream->zalloc = miniz_def_alloc_func; + if (!pStream->zfree) + pStream->zfree = miniz_def_free_func; + + pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); + if (!pDecomp) + return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pDecomp; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + pDecomp->m_window_bits = window_bits; + + return MZ_OK; +} + +int mz_inflateInit(mz_streamp pStream) +{ + return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); +} + +int mz_inflateReset(mz_streamp pStream) +{ + inflate_state *pDecomp; + if (!pStream) + return MZ_STREAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + + pDecomp = (inflate_state *)pStream->state; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + /* pDecomp->m_window_bits = window_bits */; + + return MZ_OK; +} + +int mz_inflate(mz_streamp pStream, int flush) +{ + inflate_state *pState; + mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; + size_t in_bytes, out_bytes, orig_avail_in; + tinfl_status status; + + if ((!pStream) || (!pStream->state)) + return MZ_STREAM_ERROR; + if (flush == MZ_PARTIAL_FLUSH) + flush = MZ_SYNC_FLUSH; + if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) + return MZ_STREAM_ERROR; + + pState = (inflate_state *)pStream->state; + if (pState->m_window_bits > 0) + decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; + orig_avail_in = pStream->avail_in; + + first_call = pState->m_first_call; + pState->m_first_call = 0; + if (pState->m_last_status < 0) + return MZ_DATA_ERROR; + + if (pState->m_has_flushed && (flush != MZ_FINISH)) + return MZ_STREAM_ERROR; + pState->m_has_flushed |= (flush == MZ_FINISH); + + if ((flush == MZ_FINISH) && (first_call)) + { + /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */ + decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); + pState->m_last_status = status; + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (status < 0) + return MZ_DATA_ERROR; + else if (status != TINFL_STATUS_DONE) + { + pState->m_last_status = TINFL_STATUS_FAILED; + return MZ_BUF_ERROR; + } + return MZ_STREAM_END; + } + /* flush != MZ_FINISH then we must assume there's more input. */ + if (flush != MZ_FINISH) + decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; + + if (pState->m_dict_avail) + { + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + } + + for (;;) + { + in_bytes = pStream->avail_in; + out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); + pState->m_last_status = status; + + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + + pState->m_dict_avail = (mz_uint)out_bytes; + + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + + if (status < 0) + return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */ + else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */ + else if (flush == MZ_FINISH) + { + /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */ + if (status == TINFL_STATUS_DONE) + return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; + /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */ + else if (!pStream->avail_out) + return MZ_BUF_ERROR; + } + else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + break; + } + + return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; +} + +int mz_inflateEnd(mz_streamp pStream) +{ + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} +int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len) +{ + mz_stream stream; + int status; + memset(&stream, 0, sizeof(stream)); + + /* In case mz_ulong is 64-bits (argh I hate longs). */ + if ((mz_uint64)(*pSource_len | *pDest_len) > 0xFFFFFFFFU) + return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)*pSource_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_inflateInit(&stream); + if (status != MZ_OK) + return status; + + status = mz_inflate(&stream, MZ_FINISH); + *pSource_len = *pSource_len - stream.avail_in; + if (status != MZ_STREAM_END) + { + mz_inflateEnd(&stream); + return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; + } + *pDest_len = stream.total_out; + + return mz_inflateEnd(&stream); +} + +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + return mz_uncompress2(pDest, pDest_len, pSource, &source_len); +} + +#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ + +const char *mz_error(int err) +{ + static struct + { + int m_err; + const char *m_pDesc; + } s_error_descs[] = + { + { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } + }; + mz_uint i; + for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) + if (s_error_descs[i].m_err == err) + return s_error_descs[i].m_pDesc; + return NULL; +} + +#endif /*MINIZ_NO_ZLIB_APIS */ + +#ifdef __cplusplus +} +#endif + +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + 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 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. + + For more information, please refer to +*/ +/************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * All Rights Reserved. + * + * 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. + * + **************************************************************************/ + + + +#ifndef MINIZ_NO_DEFLATE_APIS + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- Low-level Compression (independent from all decompression API's) */ + +/* Purposely making these tables static for faster init and thread safety. */ +static const mz_uint16 s_tdefl_len_sym[256] = + { + 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, + 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285 + }; + +static const mz_uint8 s_tdefl_len_extra[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0 + }; + +static const mz_uint8 s_tdefl_small_dist_sym[512] = + { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 + }; + +static const mz_uint8 s_tdefl_small_dist_extra[512] = + { + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7 + }; + +static const mz_uint8 s_tdefl_large_dist_sym[128] = + { + 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 + }; + +static const mz_uint8 s_tdefl_large_dist_extra[128] = + { + 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 + }; + +/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */ +typedef struct +{ + mz_uint16 m_key, m_sym_index; +} tdefl_sym_freq; +static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1) +{ + mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; + tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1; + MZ_CLEAR_ARR(hist); + for (i = 0; i < num_syms; i++) + { + mz_uint freq = pSyms0[i].m_key; + hist[freq & 0xFF]++; + hist[256 + ((freq >> 8) & 0xFF)]++; + } + while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) + total_passes--; + for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) + { + const mz_uint32 *pHist = &hist[pass << 8]; + mz_uint offsets[256], cur_ofs = 0; + for (i = 0; i < 256; i++) + { + offsets[i] = cur_ofs; + cur_ofs += pHist[i]; + } + for (i = 0; i < num_syms; i++) + pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; + { + tdefl_sym_freq *t = pCur_syms; + pCur_syms = pNew_syms; + pNew_syms = t; + } + } + return pCur_syms; +} + +/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */ +static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) +{ + int root, leaf, next, avbl, used, dpth; + if (n == 0) + return; + else if (n == 1) + { + A[0].m_key = 1; + return; + } + A[0].m_key += A[1].m_key; + root = 0; + leaf = 2; + for (next = 1; next < n - 1; next++) + { + if (leaf >= n || A[root].m_key < A[leaf].m_key) + { + A[next].m_key = A[root].m_key; + A[root++].m_key = (mz_uint16)next; + } + else + A[next].m_key = A[leaf++].m_key; + if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) + { + A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); + A[root++].m_key = (mz_uint16)next; + } + else + A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key); + } + A[n - 2].m_key = 0; + for (next = n - 3; next >= 0; next--) + A[next].m_key = A[A[next].m_key].m_key + 1; + avbl = 1; + used = dpth = 0; + root = n - 2; + next = n - 1; + while (avbl > 0) + { + while (root >= 0 && (int)A[root].m_key == dpth) + { + used++; + root--; + } + while (avbl > used) + { + A[next--].m_key = (mz_uint16)(dpth); + avbl--; + } + avbl = 2 * used; + dpth++; + used = 0; + } +} + +/* Limits canonical Huffman code table's max code size. */ +enum +{ + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 +}; +static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) +{ + int i; + mz_uint32 total = 0; + if (code_list_len <= 1) + return; + for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) + pNum_codes[max_code_size] += pNum_codes[i]; + for (i = max_code_size; i > 0; i--) + total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); + while (total != (1UL << max_code_size)) + { + pNum_codes[max_code_size]--; + for (i = max_code_size - 1; i > 0; i--) + if (pNum_codes[i]) + { + pNum_codes[i]--; + pNum_codes[i + 1] += 2; + break; + } + total--; + } +} + +static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) +{ + int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; + mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; + MZ_CLEAR_ARR(num_codes); + if (static_table) + { + for (i = 0; i < table_len; i++) + num_codes[d->m_huff_code_sizes[table_num][i]]++; + } + else + { + tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; + int num_used_syms = 0; + const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; + for (i = 0; i < table_len; i++) + if (pSym_count[i]) + { + syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; + syms0[num_used_syms++].m_sym_index = (mz_uint16)i; + } + + pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); + tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); + + for (i = 0; i < num_used_syms; i++) + num_codes[pSyms[i].m_key]++; + + tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); + + MZ_CLEAR_ARR(d->m_huff_code_sizes[table_num]); + MZ_CLEAR_ARR(d->m_huff_codes[table_num]); + for (i = 1, j = num_used_syms; i <= code_size_limit; i++) + for (l = num_codes[i]; l > 0; l--) + d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); + } + + next_code[1] = 0; + for (j = 0, i = 2; i <= code_size_limit; i++) + next_code[i] = j = ((j + num_codes[i - 1]) << 1); + + for (i = 0; i < table_len; i++) + { + mz_uint rev_code = 0, code, code_size; + if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) + continue; + code = next_code[code_size]++; + for (l = code_size; l > 0; l--, code >>= 1) + rev_code = (rev_code << 1) | (code & 1); + d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; + } +} + +#define TDEFL_PUT_BITS(b, l) \ + do \ + { \ + mz_uint bits = b; \ + mz_uint len = l; \ + MZ_ASSERT(bits <= ((1U << len) - 1U)); \ + d->m_bit_buffer |= (bits << d->m_bits_in); \ + d->m_bits_in += len; \ + while (d->m_bits_in >= 8) \ + { \ + if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ + *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ + d->m_bit_buffer >>= 8; \ + d->m_bits_in -= 8; \ + } \ + } \ + MZ_MACRO_END + +#define TDEFL_RLE_PREV_CODE_SIZE() \ + { \ + if (rle_repeat_count) \ + { \ + if (rle_repeat_count < 3) \ + { \ + d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ + while (rle_repeat_count--) \ + packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ + } \ + else \ + { \ + d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 16; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ + } \ + rle_repeat_count = 0; \ + } \ + } + +#define TDEFL_RLE_ZERO_CODE_SIZE() \ + { \ + if (rle_z_count) \ + { \ + if (rle_z_count < 3) \ + { \ + d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \ + while (rle_z_count--) \ + packed_code_sizes[num_packed_code_sizes++] = 0; \ + } \ + else if (rle_z_count <= 10) \ + { \ + d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 17; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ + } \ + else \ + { \ + d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 18; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ + } \ + rle_z_count = 0; \ + } \ + } + +static const mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + +static void tdefl_start_dynamic_block(tdefl_compressor *d) +{ + int num_lit_codes, num_dist_codes, num_bit_lengths; + mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; + mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; + + d->m_huff_count[0][256] = 1; + + tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); + tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); + + for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) + if (d->m_huff_code_sizes[0][num_lit_codes - 1]) + break; + for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) + if (d->m_huff_code_sizes[1][num_dist_codes - 1]) + break; + + memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); + memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); + total_code_sizes_to_pack = num_lit_codes + num_dist_codes; + num_packed_code_sizes = 0; + rle_z_count = 0; + rle_repeat_count = 0; + + memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); + for (i = 0; i < total_code_sizes_to_pack; i++) + { + mz_uint8 code_size = code_sizes_to_pack[i]; + if (!code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + if (++rle_z_count == 138) + { + TDEFL_RLE_ZERO_CODE_SIZE(); + } + } + else + { + TDEFL_RLE_ZERO_CODE_SIZE(); + if (code_size != prev_code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); + packed_code_sizes[num_packed_code_sizes++] = code_size; + } + else if (++rle_repeat_count == 6) + { + TDEFL_RLE_PREV_CODE_SIZE(); + } + } + prev_code_size = code_size; + } + if (rle_repeat_count) + { + TDEFL_RLE_PREV_CODE_SIZE(); + } + else + { + TDEFL_RLE_ZERO_CODE_SIZE(); + } + + tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); + + TDEFL_PUT_BITS(2, 2); + + TDEFL_PUT_BITS(num_lit_codes - 257, 5); + TDEFL_PUT_BITS(num_dist_codes - 1, 5); + + for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) + if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) + break; + num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); + TDEFL_PUT_BITS(num_bit_lengths - 4, 4); + for (i = 0; (int)i < num_bit_lengths; i++) + TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); + + for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) + { + mz_uint code = packed_code_sizes[packed_code_sizes_index++]; + MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); + TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); + if (code >= 16) + TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); + } +} + +static void tdefl_start_static_block(tdefl_compressor *d) +{ + mz_uint i; + mz_uint8 *p = &d->m_huff_code_sizes[0][0]; + + for (i = 0; i <= 143; ++i) + *p++ = 8; + for (; i <= 255; ++i) + *p++ = 9; + for (; i <= 279; ++i) + *p++ = 7; + for (; i <= 287; ++i) + *p++ = 8; + + memset(d->m_huff_code_sizes[1], 5, 32); + + tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); + tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); + + TDEFL_PUT_BITS(1, 2); +} + +static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + mz_uint8 *pOutput_buf = d->m_pOutput_buf; + mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; + mz_uint64 bit_buffer = d->m_bit_buffer; + mz_uint bits_in = d->m_bits_in; + +#define TDEFL_PUT_BITS_FAST(b, l) \ + { \ + bit_buffer |= (((mz_uint64)(b)) << bits_in); \ + bits_in += (l); \ + } + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + + if (flags & 1) + { + mz_uint s0, s1, n0, n1, sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0]; + mz_uint match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); + pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + /* This sequence coaxes MSVC into using cmov's vs. jmp's. */ + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + n0 = s_tdefl_small_dist_extra[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[match_dist >> 8]; + n1 = s_tdefl_large_dist_extra[match_dist >> 8]; + sym = (match_dist < 512) ? s0 : s1; + num_extra_bits = (match_dist < 512) ? n0 : n1; + + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + } + + if (pOutput_buf >= d->m_pOutput_buf_end) + return MZ_FALSE; + + memcpy(pOutput_buf, &bit_buffer, sizeof(mz_uint64)); + pOutput_buf += (bits_in >> 3); + bit_buffer >>= (bits_in & ~7); + bits_in &= 7; + } + +#undef TDEFL_PUT_BITS_FAST + + d->m_pOutput_buf = pOutput_buf; + d->m_bits_in = 0; + d->m_bit_buffer = 0; + + while (bits_in) + { + mz_uint32 n = MZ_MIN(bits_in, 16); + TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); + bit_buffer >>= n; + bits_in -= n; + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#else +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + if (flags & 1) + { + mz_uint sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); + pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + if (match_dist < 512) + { + sym = s_tdefl_small_dist_sym[match_dist]; + num_extra_bits = s_tdefl_small_dist_extra[match_dist]; + } + else + { + sym = s_tdefl_large_dist_sym[match_dist >> 8]; + num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; + } + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */ + +static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) +{ + if (static_block) + tdefl_start_static_block(d); + else + tdefl_start_dynamic_block(d); + return tdefl_compress_lz_codes(d); +} + +static const mz_uint s_tdefl_num_probes[11]; + +static int tdefl_flush_block(tdefl_compressor *d, int flush) +{ + mz_uint saved_bit_buf, saved_bits_in; + mz_uint8 *pSaved_output_buf; + mz_bool comp_block_succeeded = MZ_FALSE; + int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; + mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; + + d->m_pOutput_buf = pOutput_buf_start; + d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; + + MZ_ASSERT(!d->m_output_flush_remaining); + d->m_output_flush_ofs = 0; + d->m_output_flush_remaining = 0; + + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); + d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); + + if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) + { + const mz_uint8 cmf = 0x78; + mz_uint8 flg, flevel = 3; + mz_uint header, i, mz_un = sizeof(s_tdefl_num_probes) / sizeof(mz_uint); + + /* Determine compression level by reversing the process in tdefl_create_comp_flags_from_zip_params() */ + for (i = 0; i < mz_un; i++) + if (s_tdefl_num_probes[i] == (d->m_flags & 0xFFF)) break; + + if (i < 2) + flevel = 0; + else if (i < 6) + flevel = 1; + else if (i == 6) + flevel = 2; + + header = cmf << 8 | (flevel << 6); + header += 31 - (header % 31); + flg = header & 0xFF; + + TDEFL_PUT_BITS(cmf, 8); + TDEFL_PUT_BITS(flg, 8); + } + + TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); + + pSaved_output_buf = d->m_pOutput_buf; + saved_bit_buf = d->m_bit_buffer; + saved_bits_in = d->m_bits_in; + + if (!use_raw_block) + comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); + + /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */ + if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && + ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) + { + mz_uint i; + d->m_pOutput_buf = pSaved_output_buf; + d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + TDEFL_PUT_BITS(0, 2); + if (d->m_bits_in) + { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) + { + TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); + } + for (i = 0; i < d->m_total_lz_bytes; ++i) + { + TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); + } + } + /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */ + else if (!comp_block_succeeded) + { + d->m_pOutput_buf = pSaved_output_buf; + d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + tdefl_compress_block(d, MZ_TRUE); + } + + if (flush) + { + if (flush == TDEFL_FINISH) + { + if (d->m_bits_in) + { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) + { + mz_uint i, a = d->m_adler32; + for (i = 0; i < 4; i++) + { + TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); + a <<= 8; + } + } + } + else + { + mz_uint i, z = 0; + TDEFL_PUT_BITS(0, 3); + if (d->m_bits_in) + { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + for (i = 2; i; --i, z ^= 0xFFFF) + { + TDEFL_PUT_BITS(z & 0xFFFF, 16); + } + } + } + + MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); + + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; + d->m_pLZ_flags = d->m_lz_code_buf; + d->m_num_flags_left = 8; + d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; + d->m_total_lz_bytes = 0; + d->m_block_index++; + + if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) + { + if (d->m_pPut_buf_func) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) + return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); + } + else if (pOutput_buf_start == d->m_output_buf) + { + int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); + d->m_out_buf_ofs += bytes_to_copy; + if ((n -= bytes_to_copy) != 0) + { + d->m_output_flush_ofs = bytes_to_copy; + d->m_output_flush_remaining = n; + } + } + else + { + d->m_out_buf_ofs += n; + } + } + + return d->m_output_flush_remaining; +} + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES +#ifdef MINIZ_UNALIGNED_USE_MEMCPY +static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p) +{ + mz_uint16 ret; + memcpy(&ret, p, sizeof(mz_uint16)); + return ret; +} +static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p) +{ + mz_uint16 ret; + memcpy(&ret, p, sizeof(mz_uint16)); + return ret; +} +#else +#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p) +#define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p) +#endif +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q; + mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s); + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); + if (max_match_len <= match_len) + return; + for (;;) + { + for (;;) + { + if (--num_probes_left == 0) + return; +#define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ + return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \ + break; + TDEFL_PROBE; + TDEFL_PROBE; + TDEFL_PROBE; + } + if (!dist) + break; + q = (const mz_uint16 *)(d->m_dict + probe_pos); + if (TDEFL_READ_UNALIGNED_WORD2(q) != s01) + continue; + p = s; + probe_len = 32; + do + { + } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && + (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0)); + if (!probe_len) + { + *pMatch_dist = dist; + *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN); + break; + } + else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len) + { + *pMatch_dist = dist; + if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) + break; + c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); + } + } +} +#else +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint8 *s = d->m_dict + pos, *p, *q; + mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); + if (max_match_len <= match_len) + return; + for (;;) + { + for (;;) + { + if (--num_probes_left == 0) + return; +#define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ + return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \ + break; + TDEFL_PROBE; + TDEFL_PROBE; + TDEFL_PROBE; + } + if (!dist) + break; + p = s; + q = d->m_dict + probe_pos; + for (probe_len = 0; probe_len < max_match_len; probe_len++) + if (*p++ != *q++) + break; + if (probe_len > match_len) + { + *pMatch_dist = dist; + if ((*pMatch_len = match_len = probe_len) == max_match_len) + return; + c0 = d->m_dict[pos + match_len]; + c1 = d->m_dict[pos + match_len - 1]; + } + } +} +#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */ + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN +#ifdef MINIZ_UNALIGNED_USE_MEMCPY +static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p) +{ + mz_uint32 ret; + memcpy(&ret, p, sizeof(mz_uint32)); + return ret; +} +#else +#define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p) +#endif +static mz_bool tdefl_compress_fast(tdefl_compressor *d) +{ + /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */ + mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; + mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; + mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + + while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) + { + const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; + mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); + d->m_src_buf_left -= num_bytes_to_process; + lookahead_size += num_bytes_to_process; + + while (num_bytes_to_process) + { + mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); + memcpy(d->m_dict + dst_pos, d->m_pSrc, n); + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); + d->m_pSrc += n; + dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; + num_bytes_to_process -= n; + } + + dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); + if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) + break; + + while (lookahead_size >= 4) + { + mz_uint cur_match_dist, cur_match_len = 1; + mz_uint8 *pCur_dict = d->m_dict + cur_pos; + mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF; + mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; + mz_uint probe_pos = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)lookahead_pos; + + if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((TDEFL_READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) + { + const mz_uint16 *p = (const mz_uint16 *)pCur_dict; + const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); + mz_uint32 probe_len = 32; + do + { + } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && + (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0)); + cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); + if (!probe_len) + cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; + + if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U))) + { + cur_match_len = 1; + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + else + { + mz_uint32 s0, s1; + cur_match_len = MZ_MIN(cur_match_len, lookahead_size); + + MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); + + cur_match_dist--; + + pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); +#ifdef MINIZ_UNALIGNED_USE_MEMCPY + memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist)); +#else + *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; +#endif + pLZ_code_buf += 3; + *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); + + s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; + s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; + d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; + + d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; + } + } + else + { + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + + if (--num_flags_left == 0) + { + num_flags_left = 8; + pLZ_flags = pLZ_code_buf++; + } + + total_lz_bytes += cur_match_len; + lookahead_pos += cur_match_len; + dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; + MZ_ASSERT(lookahead_size >= cur_match_len); + lookahead_size -= cur_match_len; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; + pLZ_code_buf = d->m_pLZ_code_buf; + pLZ_flags = d->m_pLZ_flags; + num_flags_left = d->m_num_flags_left; + } + } + + while (lookahead_size) + { + mz_uint8 lit = d->m_dict[cur_pos]; + + total_lz_bytes++; + *pLZ_code_buf++ = lit; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + if (--num_flags_left == 0) + { + num_flags_left = 8; + pLZ_flags = pLZ_code_buf++; + } + + d->m_huff_count[0][lit]++; + + lookahead_pos++; + dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + lookahead_size--; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; + pLZ_code_buf = d->m_pLZ_code_buf; + pLZ_flags = d->m_pLZ_flags; + num_flags_left = d->m_num_flags_left; + } + } + } + + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + return MZ_TRUE; +} +#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */ + +static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) +{ + d->m_total_lz_bytes++; + *d->m_pLZ_code_buf++ = lit; + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); + if (--d->m_num_flags_left == 0) + { + d->m_num_flags_left = 8; + d->m_pLZ_flags = d->m_pLZ_code_buf++; + } + d->m_huff_count[0][lit]++; +} + +static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) +{ + mz_uint32 s0, s1; + + MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); + + d->m_total_lz_bytes += match_len; + + d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); + + match_dist -= 1; + d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); + d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); + d->m_pLZ_code_buf += 3; + + *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); + if (--d->m_num_flags_left == 0) + { + d->m_num_flags_left = 8; + d->m_pLZ_flags = d->m_pLZ_code_buf++; + } + + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; + d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; + d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; +} + +static mz_bool tdefl_compress_normal(tdefl_compressor *d) +{ + const mz_uint8 *pSrc = d->m_pSrc; + size_t src_buf_left = d->m_src_buf_left; + tdefl_flush flush = d->m_flush; + + while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) + { + mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; + /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */ + if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) + { + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; + mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); + const mz_uint8 *pSrc_end = pSrc ? pSrc + num_bytes_to_process : NULL; + src_buf_left -= num_bytes_to_process; + d->m_lookahead_size += num_bytes_to_process; + while (pSrc != pSrc_end) + { + mz_uint8 c = *pSrc++; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)(ins_pos); + dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + ins_pos++; + } + } + else + { + while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + { + mz_uint8 c = *pSrc++; + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + src_buf_left--; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) + { + mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; + mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)(ins_pos); + } + } + } + d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); + if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + break; + + /* Simple lazy/greedy parsing state machine. */ + len_to_move = 1; + cur_match_dist = 0; + cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); + cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) + { + if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) + { + mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; + cur_match_len = 0; + while (cur_match_len < d->m_lookahead_size) + { + if (d->m_dict[cur_pos + cur_match_len] != c) + break; + cur_match_len++; + } + if (cur_match_len < TDEFL_MIN_MATCH_LEN) + cur_match_len = 0; + else + cur_match_dist = 1; + } + } + else + { + tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); + } + if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) + { + cur_match_dist = cur_match_len = 0; + } + if (d->m_saved_match_len) + { + if (cur_match_len > d->m_saved_match_len) + { + tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); + if (cur_match_len >= 128) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + d->m_saved_match_len = 0; + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[cur_pos]; + d->m_saved_match_dist = cur_match_dist; + d->m_saved_match_len = cur_match_len; + } + } + else + { + tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); + len_to_move = d->m_saved_match_len - 1; + d->m_saved_match_len = 0; + } + } + else if (!cur_match_dist) + tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); + else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; + d->m_saved_match_dist = cur_match_dist; + d->m_saved_match_len = cur_match_len; + } + /* Move the lookahead forward by len_to_move bytes. */ + d->m_lookahead_pos += len_to_move; + MZ_ASSERT(d->m_lookahead_size >= len_to_move); + d->m_lookahead_size -= len_to_move; + d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE); + /* Check if it's time to flush the current LZ codes to the internal output buffer. */ + if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || + ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) + { + int n; + d->m_pSrc = pSrc; + d->m_src_buf_left = src_buf_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + } + } + + d->m_pSrc = pSrc; + d->m_src_buf_left = src_buf_left; + return MZ_TRUE; +} + +static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) +{ + if (d->m_pIn_buf_size) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + } + + if (d->m_pOut_buf_size) + { + size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); + d->m_output_flush_ofs += (mz_uint)n; + d->m_output_flush_remaining -= (mz_uint)n; + d->m_out_buf_ofs += n; + + *d->m_pOut_buf_size = d->m_out_buf_ofs; + } + + return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) +{ + if (!d) + { + if (pIn_buf_size) + *pIn_buf_size = 0; + if (pOut_buf_size) + *pOut_buf_size = 0; + return TDEFL_STATUS_BAD_PARAM; + } + + d->m_pIn_buf = pIn_buf; + d->m_pIn_buf_size = pIn_buf_size; + d->m_pOut_buf = pOut_buf; + d->m_pOut_buf_size = pOut_buf_size; + d->m_pSrc = (const mz_uint8 *)(pIn_buf); + d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; + d->m_out_buf_ofs = 0; + d->m_flush = flush; + + if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || + (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf)) + { + if (pIn_buf_size) + *pIn_buf_size = 0; + if (pOut_buf_size) + *pOut_buf_size = 0; + return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); + } + d->m_wants_to_finish |= (flush == TDEFL_FINISH); + + if ((d->m_output_flush_remaining) || (d->m_finished)) + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && + ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && + ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) + { + if (!tdefl_compress_fast(d)) + return d->m_prev_return_status; + } + else +#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */ + { + if (!tdefl_compress_normal(d)) + return d->m_prev_return_status; + } + + if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) + d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); + + if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) + { + if (tdefl_flush_block(d, flush) < 0) + return d->m_prev_return_status; + d->m_finished = (flush == TDEFL_FINISH); + if (flush == TDEFL_FULL_FLUSH) + { + MZ_CLEAR_ARR(d->m_hash); + MZ_CLEAR_ARR(d->m_next); + d->m_dict_size = 0; + } + } + + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); +} + +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) +{ + MZ_ASSERT(d->m_pPut_buf_func); + return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); +} + +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + d->m_pPut_buf_func = pPut_buf_func; + d->m_pPut_buf_user = pPut_buf_user; + d->m_flags = (mz_uint)(flags); + d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; + d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; + d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; + if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) + MZ_CLEAR_ARR(d->m_hash); + d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; + d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; + d->m_pLZ_flags = d->m_lz_code_buf; + *d->m_pLZ_flags = 0; + d->m_num_flags_left = 8; + d->m_pOutput_buf = d->m_output_buf; + d->m_pOutput_buf_end = d->m_output_buf; + d->m_prev_return_status = TDEFL_STATUS_OKAY; + d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; + d->m_adler32 = 1; + d->m_pIn_buf = NULL; + d->m_pOut_buf = NULL; + d->m_pIn_buf_size = NULL; + d->m_pOut_buf_size = NULL; + d->m_flush = TDEFL_NO_FLUSH; + d->m_pSrc = NULL; + d->m_src_buf_left = 0; + d->m_out_buf_ofs = 0; + if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) + MZ_CLEAR_ARR(d->m_dict); + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + return TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) +{ + return d->m_prev_return_status; +} + +mz_uint32 tdefl_get_adler32(tdefl_compressor *d) +{ + return d->m_adler32; +} + +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + tdefl_compressor *pComp; + mz_bool succeeded; + if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) + return MZ_FALSE; + pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); + if (!pComp) + return MZ_FALSE; + succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); + succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); + MZ_FREE(pComp); + return succeeded; +} + +typedef struct +{ + size_t m_size, m_capacity; + mz_uint8 *m_pBuf; + mz_bool m_expandable; +} tdefl_output_buffer; + +static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) +{ + tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; + size_t new_size = p->m_size + len; + if (new_size > p->m_capacity) + { + size_t new_capacity = p->m_capacity; + mz_uint8 *pNew_buf; + if (!p->m_expandable) + return MZ_FALSE; + do + { + new_capacity = MZ_MAX(128U, new_capacity << 1U); + } while (new_size > new_capacity); + pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity); + if (!pNew_buf) + return MZ_FALSE; + p->m_pBuf = pNew_buf; + p->m_capacity = new_capacity; + } + memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len); + p->m_size = new_size; + return MZ_TRUE; +} + +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tdefl_output_buffer out_buf; + MZ_CLEAR_OBJ(out_buf); + if (!pOut_len) + return MZ_FALSE; + else + *pOut_len = 0; + out_buf.m_expandable = MZ_TRUE; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) + return NULL; + *pOut_len = out_buf.m_size; + return out_buf.m_pBuf; +} + +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tdefl_output_buffer out_buf; + MZ_CLEAR_OBJ(out_buf); + if (!pOut_buf) + return 0; + out_buf.m_pBuf = (mz_uint8 *)pOut_buf; + out_buf.m_capacity = out_buf_len; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) + return 0; + return out_buf.m_size; +} + +static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + +/* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */ +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) +{ + mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (window_bits > 0) + comp_flags |= TDEFL_WRITE_ZLIB_HEADER; + + if (!level) + comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + else if (strategy == MZ_FILTERED) + comp_flags |= TDEFL_FILTER_MATCHES; + else if (strategy == MZ_HUFFMAN_ONLY) + comp_flags &= ~TDEFL_MAX_PROBES_MASK; + else if (strategy == MZ_FIXED) + comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; + else if (strategy == MZ_RLE) + comp_flags |= TDEFL_RLE_MATCHES; + + return comp_flags; +} + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */ +#endif + +/* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at + http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. + This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */ +void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip) +{ + /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */ + static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); + tdefl_output_buffer out_buf; + int i, bpl = w * num_chans, y, z; + mz_uint32 c; + *pLen_out = 0; + if (!pComp) + return NULL; + MZ_CLEAR_OBJ(out_buf); + out_buf.m_expandable = MZ_TRUE; + out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h); + if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) + { + MZ_FREE(pComp); + return NULL; + } + /* write dummy header */ + for (z = 41; z; --z) + tdefl_output_buffer_putter(&z, 1, &out_buf); + /* compress image data */ + tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); + for (y = 0; y < h; ++y) + { + tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); + tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); + } + if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) + { + MZ_FREE(pComp); + MZ_FREE(out_buf.m_pBuf); + return NULL; + } + /* write real header */ + *pLen_out = out_buf.m_size - 41; + { + static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 }; + mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, + 0x0a, 0x1a, 0x0a, 0x00, 0x00, + 0x00, 0x0d, 0x49, 0x48, 0x44, + 0x52, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x44, 0x41, + 0x54 }; + pnghdr[18] = (mz_uint8)(w >> 8); + pnghdr[19] = (mz_uint8)w; + pnghdr[22] = (mz_uint8)(h >> 8); + pnghdr[23] = (mz_uint8)h; + pnghdr[25] = chans[num_chans]; + pnghdr[33] = (mz_uint8)(*pLen_out >> 24); + pnghdr[34] = (mz_uint8)(*pLen_out >> 16); + pnghdr[35] = (mz_uint8)(*pLen_out >> 8); + pnghdr[36] = (mz_uint8)*pLen_out; + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17); + for (i = 0; i < 4; ++i, c <<= 8) + ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24); + memcpy(out_buf.m_pBuf, pnghdr, 41); + } + /* write footer (IDAT CRC-32, followed by IEND chunk) */ + if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) + { + *pLen_out = 0; + MZ_FREE(pComp); + MZ_FREE(out_buf.m_pBuf); + return NULL; + } + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4); + for (i = 0; i < 4; ++i, c <<= 8) + (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24); + /* compute final size of file, grab compressed data buffer and return */ + *pLen_out += 57; + MZ_FREE(pComp); + return out_buf.m_pBuf; +} +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) +{ + /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */ + return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); +} + +#ifndef MINIZ_NO_MALLOC +/* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */ +/* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */ +/* structure size and allocation mechanism. */ +tdefl_compressor *tdefl_compressor_alloc(void) +{ + return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); +} + +void tdefl_compressor_free(tdefl_compressor *pComp) +{ + MZ_FREE(pComp); +} +#endif + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ + /************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * All Rights Reserved. + * + * 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. + * + **************************************************************************/ + + + +#ifndef MINIZ_NO_INFLATE_APIS + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- Low-level Decompression (completely independent from all compression API's) */ + +#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) +#define TINFL_MEMSET(p, c, l) memset(p, c, l) + +#define TINFL_CR_BEGIN \ + switch (r->m_state) \ + { \ + case 0: +#define TINFL_CR_RETURN(state_index, result) \ + do \ + { \ + status = result; \ + r->m_state = state_index; \ + goto common_exit; \ + case state_index:; \ + } \ + MZ_MACRO_END +#define TINFL_CR_RETURN_FOREVER(state_index, result) \ + do \ + { \ + for (;;) \ + { \ + TINFL_CR_RETURN(state_index, result); \ + } \ + } \ + MZ_MACRO_END +#define TINFL_CR_FINISH } + +#define TINFL_GET_BYTE(state_index, c) \ + do \ + { \ + while (pIn_buf_cur >= pIn_buf_end) \ + { \ + TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \ + } \ + c = *pIn_buf_cur++; \ + } \ + MZ_MACRO_END + +#define TINFL_NEED_BITS(state_index, n) \ + do \ + { \ + mz_uint c; \ + TINFL_GET_BYTE(state_index, c); \ + bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \ + num_bits += 8; \ + } while (num_bits < (mz_uint)(n)) +#define TINFL_SKIP_BITS(state_index, n) \ + do \ + { \ + if (num_bits < (mz_uint)(n)) \ + { \ + TINFL_NEED_BITS(state_index, n); \ + } \ + bit_buf >>= (n); \ + num_bits -= (n); \ + } \ + MZ_MACRO_END +#define TINFL_GET_BITS(state_index, b, n) \ + do \ + { \ + if (num_bits < (mz_uint)(n)) \ + { \ + TINFL_NEED_BITS(state_index, n); \ + } \ + b = bit_buf & ((1 << (n)) - 1); \ + bit_buf >>= (n); \ + num_bits -= (n); \ + } \ + MZ_MACRO_END + +/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */ +/* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */ +/* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */ +/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */ +#define TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree) \ + do \ + { \ + temp = pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ + if (temp >= 0) \ + { \ + code_len = temp >> 9; \ + if ((code_len) && (num_bits >= code_len)) \ + break; \ + } \ + else if (num_bits > TINFL_FAST_LOOKUP_BITS) \ + { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do \ + { \ + temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while ((temp < 0) && (num_bits >= (code_len + 1))); \ + if (temp >= 0) \ + break; \ + } \ + TINFL_GET_BYTE(state_index, c); \ + bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \ + num_bits += 8; \ + } while (num_bits < 15); + +/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */ +/* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */ +/* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */ +/* The slow path is only executed at the very end of the input buffer. */ +/* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */ +/* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */ +#define TINFL_HUFF_DECODE(state_index, sym, pLookUp, pTree) \ + do \ + { \ + int temp; \ + mz_uint code_len, c; \ + if (num_bits < 15) \ + { \ + if ((pIn_buf_end - pIn_buf_cur) < 2) \ + { \ + TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree); \ + } \ + else \ + { \ + bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \ + pIn_buf_cur += 2; \ + num_bits += 16; \ + } \ + } \ + if ((temp = pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ + code_len = temp >> 9, temp &= 511; \ + else \ + { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do \ + { \ + temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while (temp < 0); \ + } \ + sym = temp; \ + bit_buf >>= code_len; \ + num_bits -= code_len; \ + } \ + MZ_MACRO_END + +static void tinfl_clear_tree(tinfl_decompressor *r) +{ + if (r->m_type == 0) + MZ_CLEAR_ARR(r->m_tree_0); + else if (r->m_type == 1) + MZ_CLEAR_ARR(r->m_tree_1); + else + MZ_CLEAR_ARR(r->m_tree_2); +} + +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) +{ + static const mz_uint16 s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 }; + static const mz_uint8 s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 }; + static const mz_uint16 s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 }; + static const mz_uint8 s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 }; + static const mz_uint8 s_length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + static const mz_uint16 s_min_table_sizes[3] = { 257, 1, 4 }; + + mz_int16 *pTrees[3]; + mz_uint8 *pCode_sizes[3]; + + tinfl_status status = TINFL_STATUS_FAILED; + mz_uint32 num_bits, dist, counter, num_extra; + tinfl_bit_buf_t bit_buf; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next ? pOut_buf_next + *pOut_buf_size : NULL; + size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; + + /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */ + if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) + { + *pIn_buf_size = *pOut_buf_size = 0; + return TINFL_STATUS_BAD_PARAM; + } + + pTrees[0] = r->m_tree_0; + pTrees[1] = r->m_tree_1; + pTrees[2] = r->m_tree_2; + pCode_sizes[0] = r->m_code_size_0; + pCode_sizes[1] = r->m_code_size_1; + pCode_sizes[2] = r->m_code_size_2; + + num_bits = r->m_num_bits; + bit_buf = r->m_bit_buf; + dist = r->m_dist; + counter = r->m_counter; + num_extra = r->m_num_extra; + dist_from_out_buf_start = r->m_dist_from_out_buf_start; + TINFL_CR_BEGIN + + bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; + r->m_z_adler32 = r->m_check_adler32 = 1; + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_GET_BYTE(1, r->m_zhdr0); + TINFL_GET_BYTE(2, r->m_zhdr1); + counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); + if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)((size_t)1 << (8U + (r->m_zhdr0 >> 4))))); + if (counter) + { + TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); + } + } + + do + { + TINFL_GET_BITS(3, r->m_final, 3); + r->m_type = r->m_final >> 1; + if (r->m_type == 0) + { + TINFL_SKIP_BITS(5, num_bits & 7); + for (counter = 0; counter < 4; ++counter) + { + if (num_bits) + TINFL_GET_BITS(6, r->m_raw_header[counter], 8); + else + TINFL_GET_BYTE(7, r->m_raw_header[counter]); + } + if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) + { + TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); + } + while ((counter) && (num_bits)) + { + TINFL_GET_BITS(51, dist, 8); + while (pOut_buf_cur >= pOut_buf_end) + { + TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = (mz_uint8)dist; + counter--; + } + while (counter) + { + size_t n; + while (pOut_buf_cur >= pOut_buf_end) + { + TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); + } + while (pIn_buf_cur >= pIn_buf_end) + { + TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); + } + n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); + TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); + pIn_buf_cur += n; + pOut_buf_cur += n; + counter -= (mz_uint)n; + } + } + else if (r->m_type == 3) + { + TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); + } + else + { + if (r->m_type == 1) + { + mz_uint8 *p = r->m_code_size_0; + mz_uint i; + r->m_table_sizes[0] = 288; + r->m_table_sizes[1] = 32; + TINFL_MEMSET(r->m_code_size_1, 5, 32); + for (i = 0; i <= 143; ++i) + *p++ = 8; + for (; i <= 255; ++i) + *p++ = 9; + for (; i <= 279; ++i) + *p++ = 7; + for (; i <= 287; ++i) + *p++ = 8; + } + else + { + for (counter = 0; counter < 3; counter++) + { + TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); + r->m_table_sizes[counter] += s_min_table_sizes[counter]; + } + MZ_CLEAR_ARR(r->m_code_size_2); + for (counter = 0; counter < r->m_table_sizes[2]; counter++) + { + mz_uint s; + TINFL_GET_BITS(14, s, 3); + r->m_code_size_2[s_length_dezigzag[counter]] = (mz_uint8)s; + } + r->m_table_sizes[2] = 19; + } + for (; (int)r->m_type >= 0; r->m_type--) + { + int tree_next, tree_cur; + mz_int16 *pLookUp; + mz_int16 *pTree; + mz_uint8 *pCode_size; + mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; + pLookUp = r->m_look_up[r->m_type]; + pTree = pTrees[r->m_type]; + pCode_size = pCode_sizes[r->m_type]; + MZ_CLEAR_ARR(total_syms); + TINFL_MEMSET(pLookUp, 0, sizeof(r->m_look_up[0])); + tinfl_clear_tree(r); + for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) + total_syms[pCode_size[i]]++; + used_syms = 0, total = 0; + next_code[0] = next_code[1] = 0; + for (i = 1; i <= 15; ++i) + { + used_syms += total_syms[i]; + next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); + } + if ((65536 != total) && (used_syms > 1)) + { + TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); + } + for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) + { + mz_uint rev_code = 0, l, cur_code, code_size = pCode_size[sym_index]; + if (!code_size) + continue; + cur_code = next_code[code_size]++; + for (l = code_size; l > 0; l--, cur_code >>= 1) + rev_code = (rev_code << 1) | (cur_code & 1); + if (code_size <= TINFL_FAST_LOOKUP_BITS) + { + mz_int16 k = (mz_int16)((code_size << 9) | sym_index); + while (rev_code < TINFL_FAST_LOOKUP_SIZE) + { + pLookUp[rev_code] = k; + rev_code += (1 << code_size); + } + continue; + } + if (0 == (tree_cur = pLookUp[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) + { + pLookUp[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); + for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) + { + tree_cur -= ((rev_code >>= 1) & 1); + if (!pTree[-tree_cur - 1]) + { + pTree[-tree_cur - 1] = (mz_int16)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + else + tree_cur = pTree[-tree_cur - 1]; + } + tree_cur -= ((rev_code >>= 1) & 1); + pTree[-tree_cur - 1] = (mz_int16)sym_index; + } + if (r->m_type == 2) + { + for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) + { + mz_uint s; + TINFL_HUFF_DECODE(16, dist, r->m_look_up[2], r->m_tree_2); + if (dist < 16) + { + r->m_len_codes[counter++] = (mz_uint8)dist; + continue; + } + if ((dist == 16) && (!counter)) + { + TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + } + num_extra = "\02\03\07"[dist - 16]; + TINFL_GET_BITS(18, s, num_extra); + s += "\03\03\013"[dist - 16]; + TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); + counter += s; + } + if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) + { + TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); + } + TINFL_MEMCPY(r->m_code_size_0, r->m_len_codes, r->m_table_sizes[0]); + TINFL_MEMCPY(r->m_code_size_1, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); + } + } + for (;;) + { + mz_uint8 *pSrc; + for (;;) + { + if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) + { + TINFL_HUFF_DECODE(23, counter, r->m_look_up[0], r->m_tree_0); + if (counter >= 256) + break; + while (pOut_buf_cur >= pOut_buf_end) + { + TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = (mz_uint8)counter; + } + else + { + int sym2; + mz_uint code_len; +#if TINFL_USE_64BIT_BITBUF + if (num_bits < 30) + { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 4; + num_bits += 32; + } +#else + if (num_bits < 15) + { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 2; + num_bits += 16; + } +#endif + if ((sym2 = r->m_look_up[0][bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; + do + { + sym2 = r->m_tree_0[~sym2 + ((bit_buf >> code_len++) & 1)]; + } while (sym2 < 0); + } + counter = sym2; + bit_buf >>= code_len; + num_bits -= code_len; + if (counter & 256) + break; + +#if !TINFL_USE_64BIT_BITBUF + if (num_bits < 15) + { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 2; + num_bits += 16; + } +#endif + if ((sym2 = r->m_look_up[0][bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; + do + { + sym2 = r->m_tree_0[~sym2 + ((bit_buf >> code_len++) & 1)]; + } while (sym2 < 0); + } + bit_buf >>= code_len; + num_bits -= code_len; + + pOut_buf_cur[0] = (mz_uint8)counter; + if (sym2 & 256) + { + pOut_buf_cur++; + counter = sym2; + break; + } + pOut_buf_cur[1] = (mz_uint8)sym2; + pOut_buf_cur += 2; + } + } + if ((counter &= 511) == 256) + break; + + num_extra = s_length_extra[counter - 257]; + counter = s_length_base[counter - 257]; + if (num_extra) + { + mz_uint extra_bits; + TINFL_GET_BITS(25, extra_bits, num_extra); + counter += extra_bits; + } + + TINFL_HUFF_DECODE(26, dist, r->m_look_up[1], r->m_tree_1); + num_extra = s_dist_extra[dist]; + dist = s_dist_base[dist]; + if (num_extra) + { + mz_uint extra_bits; + TINFL_GET_BITS(27, extra_bits, num_extra); + dist += extra_bits; + } + + dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; + if ((dist == 0 || dist > dist_from_out_buf_start || dist_from_out_buf_start == 0) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + { + TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); + } + + pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); + + if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) + { + while (counter--) + { + while (pOut_buf_cur >= pOut_buf_end) + { + TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; + } + continue; + } +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + else if ((counter >= 9) && (counter <= dist)) + { + const mz_uint8 *pSrc_end = pSrc + (counter & ~7); + do + { +#ifdef MINIZ_UNALIGNED_USE_MEMCPY + memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2); +#else + ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; + ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; +#endif + pOut_buf_cur += 8; + } while ((pSrc += 8) < pSrc_end); + if ((counter &= 7) < 3) + { + if (counter) + { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + continue; + } + } +#endif + while(counter>2) + { + pOut_buf_cur[0] = pSrc[0]; + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur[2] = pSrc[2]; + pOut_buf_cur += 3; + pSrc += 3; + counter -= 3; + } + if (counter > 0) + { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + } + } + } while (!(r->m_final & 1)); + + /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */ + /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */ + TINFL_SKIP_BITS(32, num_bits & 7); + while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) + { + --pIn_buf_cur; + num_bits -= 8; + } + bit_buf &= ~(~(tinfl_bit_buf_t)0 << num_bits); + MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */ + + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + for (counter = 0; counter < 4; ++counter) + { + mz_uint s; + if (num_bits) + TINFL_GET_BITS(41, s, 8); + else + TINFL_GET_BYTE(42, s); + r->m_z_adler32 = (r->m_z_adler32 << 8) | s; + } + } + TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); + + TINFL_CR_FINISH + +common_exit: + /* As long as we aren't telling the caller that we NEED more input to make forward progress: */ + /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */ + /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */ + if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS)) + { + while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) + { + --pIn_buf_cur; + num_bits -= 8; + } + } + r->m_num_bits = num_bits; + r->m_bit_buf = bit_buf & ~(~(tinfl_bit_buf_t)0 << num_bits); + r->m_dist = dist; + r->m_counter = counter; + r->m_num_extra = num_extra; + r->m_dist_from_out_buf_start = dist_from_out_buf_start; + *pIn_buf_size = pIn_buf_cur - pIn_buf_next; + *pOut_buf_size = pOut_buf_cur - pOut_buf_next; + if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) + { + const mz_uint8 *ptr = pOut_buf_next; + size_t buf_len = *pOut_buf_size; + mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; + size_t block_len = buf_len % 5552; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) + s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; + } + r->m_check_adler32 = (s2 << 16) + s1; + if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) + status = TINFL_STATUS_ADLER32_MISMATCH; + } + return status; +} + +/* Higher level helper functions. */ +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tinfl_decompressor decomp; + void *pBuf = NULL, *pNew_buf; + size_t src_buf_ofs = 0, out_buf_capacity = 0; + *pOut_len = 0; + tinfl_init(&decomp); + for (;;) + { + size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) + { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + src_buf_ofs += src_buf_size; + *pOut_len += dst_buf_size; + if (status == TINFL_STATUS_DONE) + break; + new_out_buf_capacity = out_buf_capacity * 2; + if (new_out_buf_capacity < 128) + new_out_buf_capacity = 128; + pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); + if (!pNew_buf) + { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + pBuf = pNew_buf; + out_buf_capacity = new_out_buf_capacity; + } + return pBuf; +} + +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tinfl_decompressor decomp; + tinfl_status status; + tinfl_init(&decomp); + status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; +} + +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + int result = 0; + tinfl_decompressor decomp; + mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE); + size_t in_buf_ofs = 0, dict_ofs = 0; + if (!pDict) + return TINFL_STATUS_FAILED; + memset(pDict,0,TINFL_LZ_DICT_SIZE); + tinfl_init(&decomp); + for (;;) + { + size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, + (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + in_buf_ofs += in_buf_size; + if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) + break; + if (status != TINFL_STATUS_HAS_MORE_OUTPUT) + { + result = (status == TINFL_STATUS_DONE); + break; + } + dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); + } + MZ_FREE(pDict); + *pIn_buf_size = in_buf_ofs; + return result; +} + +#ifndef MINIZ_NO_MALLOC +tinfl_decompressor *tinfl_decompressor_alloc(void) +{ + tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor)); + if (pDecomp) + tinfl_init(pDecomp); + return pDecomp; +} + +void tinfl_decompressor_free(tinfl_decompressor *pDecomp) +{ + MZ_FREE(pDecomp); +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ + /************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * Copyright 2016 Martin Raiber + * All Rights Reserved. + * + * 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. + * + **************************************************************************/ + + +#ifndef MINIZ_NO_ARCHIVE_APIS + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- .ZIP archive reading */ + +#ifdef MINIZ_NO_STDIO +#define MZ_FILE void * +#else +#include + +#if defined(_MSC_VER) || defined(__MINGW64__) + +#define WIN32_LEAN_AND_MEAN +#include + +static WCHAR* mz_utf8z_to_widechar(const char* str) +{ + int reqChars = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); + WCHAR* wStr = (WCHAR*)malloc(reqChars * sizeof(WCHAR)); + MultiByteToWideChar(CP_UTF8, 0, str, -1, wStr, reqChars); + return wStr; +} + +static FILE *mz_fopen(const char *pFilename, const char *pMode) +{ + WCHAR* wFilename = mz_utf8z_to_widechar(pFilename); + WCHAR* wMode = mz_utf8z_to_widechar(pMode); + FILE* pFile = NULL; + errno_t err = _wfopen_s(&pFile, wFilename, wMode); + free(wFilename); + free(wMode); + return err ? NULL : pFile; +} + +static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) +{ + WCHAR* wPath = mz_utf8z_to_widechar(pPath); + WCHAR* wMode = mz_utf8z_to_widechar(pMode); + FILE* pFile = NULL; + errno_t err = _wfreopen_s(&pFile, wPath, wMode, pStream); + free(wPath); + free(wMode); + return err ? NULL : pFile; +} + +static int mz_stat64(const char *path, struct __stat64 *buffer) +{ + WCHAR* wPath = mz_utf8z_to_widechar(path); + int res = _wstat64(wPath, buffer); + free(wPath); + return res; +} + +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN mz_fopen +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 _ftelli64 +#define MZ_FSEEK64 _fseeki64 +#define MZ_FILE_STAT_STRUCT _stat64 +#define MZ_FILE_STAT mz_stat64 +#define MZ_FFLUSH fflush +#define MZ_FREOPEN mz_freopen +#define MZ_DELETE_FILE remove + +#elif defined(__MINGW32__) || defined(__WATCOMC__) +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 _ftelli64 +#define MZ_FSEEK64 _fseeki64 +#define MZ_FILE_STAT_STRUCT stat +#define MZ_FILE_STAT stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(f, m, s) freopen(f, m, s) +#define MZ_DELETE_FILE remove + +#elif defined(__TINYC__) +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 ftell +#define MZ_FSEEK64 fseek +#define MZ_FILE_STAT_STRUCT stat +#define MZ_FILE_STAT stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(f, m, s) freopen(f, m, s) +#define MZ_DELETE_FILE remove + +#elif defined(__USE_LARGEFILE64) /* gcc, clang */ +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen64(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 ftello64 +#define MZ_FSEEK64 fseeko64 +#define MZ_FILE_STAT_STRUCT stat64 +#define MZ_FILE_STAT stat64 +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(p, m, s) freopen64(p, m, s) +#define MZ_DELETE_FILE remove + +#elif defined(__APPLE__) || defined(__FreeBSD__) +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#define MZ_FTELL64 ftello +#define MZ_FSEEK64 fseeko +#define MZ_FILE_STAT_STRUCT stat +#define MZ_FILE_STAT stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(p, m, s) freopen(p, m, s) +#define MZ_DELETE_FILE remove + +#else +#pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.") +#ifndef MINIZ_NO_TIME +#include +#endif +#define MZ_FOPEN(f, m) fopen(f, m) +#define MZ_FCLOSE fclose +#define MZ_FREAD fread +#define MZ_FWRITE fwrite +#ifdef __STRICT_ANSI__ +#define MZ_FTELL64 ftell +#define MZ_FSEEK64 fseek +#else +#define MZ_FTELL64 ftello +#define MZ_FSEEK64 fseeko +#endif +#define MZ_FILE_STAT_STRUCT stat +#define MZ_FILE_STAT stat +#define MZ_FFLUSH fflush +#define MZ_FREOPEN(f, m, s) freopen(f, m, s) +#define MZ_DELETE_FILE remove +#endif /* #ifdef _MSC_VER */ +#endif /* #ifdef MINIZ_NO_STDIO */ + +#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) + +/* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */ +enum +{ + /* ZIP archive identifiers and record sizes */ + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, + MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, + + /* ZIP64 archive identifier and record sizes */ + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50, + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50, + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56, + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20, + MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001, + MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50, + MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24, + MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16, + + /* Central directory header record offsets */ + MZ_ZIP_CDH_SIG_OFS = 0, + MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, + MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, + MZ_ZIP_CDH_BIT_FLAG_OFS = 8, + MZ_ZIP_CDH_METHOD_OFS = 10, + MZ_ZIP_CDH_FILE_TIME_OFS = 12, + MZ_ZIP_CDH_FILE_DATE_OFS = 14, + MZ_ZIP_CDH_CRC32_OFS = 16, + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, + MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, + MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, + MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, + MZ_ZIP_CDH_DISK_START_OFS = 34, + MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, + MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, + + /* Local directory header offsets */ + MZ_ZIP_LDH_SIG_OFS = 0, + MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, + MZ_ZIP_LDH_BIT_FLAG_OFS = 6, + MZ_ZIP_LDH_METHOD_OFS = 8, + MZ_ZIP_LDH_FILE_TIME_OFS = 10, + MZ_ZIP_LDH_FILE_DATE_OFS = 12, + MZ_ZIP_LDH_CRC32_OFS = 14, + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, + MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, + MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, + MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3, + + /* End of central directory offsets */ + MZ_ZIP_ECDH_SIG_OFS = 0, + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, + MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, + MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, + MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, + + /* ZIP64 End of central directory locator offsets */ + MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */ + MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */ + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */ + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */ + + /* ZIP64 End of central directory header offsets */ + MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */ + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */ + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */ + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */ + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */ + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */ + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */ + MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0, + MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11 +}; + +typedef struct +{ + void *m_p; + size_t m_size, m_capacity; + mz_uint m_element_size; +} mz_zip_array; + +struct mz_zip_internal_state_tag +{ + mz_zip_array m_central_dir; + mz_zip_array m_central_dir_offsets; + mz_zip_array m_sorted_central_dir_offsets; + + /* The flags passed in when the archive is initially opened. */ + mz_uint32 m_init_flags; + + /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */ + mz_bool m_zip64; + + /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */ + mz_bool m_zip64_has_extended_info_fields; + + /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */ + MZ_FILE *m_pFile; + mz_uint64 m_file_archive_start_ofs; + + void *m_pMem; + size_t m_mem_size; + size_t m_mem_capacity; +}; + +#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size + +#if defined(DEBUG) || defined(_DEBUG) +static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index) +{ + MZ_ASSERT(index < pArray->m_size); + return index; +} +#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)] +#else +#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] +#endif + +static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size) +{ + memset(pArray, 0, sizeof(mz_zip_array)); + pArray->m_element_size = element_size; +} + +static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) +{ + pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); + memset(pArray, 0, sizeof(mz_zip_array)); +} + +static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) +{ + void *pNew_p; + size_t new_capacity = min_new_capacity; + MZ_ASSERT(pArray->m_element_size); + if (pArray->m_capacity >= min_new_capacity) + return MZ_TRUE; + if (growing) + { + new_capacity = MZ_MAX(1, pArray->m_capacity); + while (new_capacity < min_new_capacity) + new_capacity *= 2; + } + if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) + return MZ_FALSE; + pArray->m_p = pNew_p; + pArray->m_capacity = new_capacity; + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) +{ + if (new_capacity > pArray->m_capacity) + { + if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) + return MZ_FALSE; + } + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) +{ + if (new_size > pArray->m_capacity) + { + if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) + return MZ_FALSE; + } + pArray->m_size = new_size; + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) +{ + return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) +{ + size_t orig_size = pArray->m_size; + if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) + return MZ_FALSE; + if (n > 0) + memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); + return MZ_TRUE; +} + +#ifndef MINIZ_NO_TIME +static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date) +{ + struct tm tm; + memset(&tm, 0, sizeof(tm)); + tm.tm_isdst = -1; + tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; + tm.tm_mon = ((dos_date >> 5) & 15) - 1; + tm.tm_mday = dos_date & 31; + tm.tm_hour = (dos_time >> 11) & 31; + tm.tm_min = (dos_time >> 5) & 63; + tm.tm_sec = (dos_time << 1) & 62; + return mktime(&tm); +} + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS +static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) +{ +#ifdef _MSC_VER + struct tm tm_struct; + struct tm *tm = &tm_struct; + errno_t err = localtime_s(tm, &time); + if (err) + { + *pDOS_date = 0; + *pDOS_time = 0; + return; + } +#else + struct tm *tm = localtime(&time); +#endif /* #ifdef _MSC_VER */ + + *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); + *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); +} +#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */ + +#ifndef MINIZ_NO_STDIO +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS +static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime) +{ + struct MZ_FILE_STAT_STRUCT file_stat; + + /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */ + if (MZ_FILE_STAT(pFilename, &file_stat) != 0) + return MZ_FALSE; + + *pTime = file_stat.st_mtime; + + return MZ_TRUE; +} +#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/ + +static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time) +{ + struct utimbuf t; + + memset(&t, 0, sizeof(t)); + t.actime = access_time; + t.modtime = modified_time; + + return !utime(pFilename, &t); +} +#endif /* #ifndef MINIZ_NO_STDIO */ +#endif /* #ifndef MINIZ_NO_TIME */ + +static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num) +{ + if (pZip) + pZip->m_last_error = err_num; + return MZ_FALSE; +} + +static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags) +{ + (void)flags; + if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!pZip->m_pAlloc) + pZip->m_pAlloc = miniz_def_alloc_func; + if (!pZip->m_pFree) + pZip->m_pFree = miniz_def_free_func; + if (!pZip->m_pRealloc) + pZip->m_pRealloc = miniz_def_realloc_func; + + pZip->m_archive_size = 0; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + pZip->m_last_error = MZ_ZIP_NO_ERROR; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + pZip->m_pState->m_init_flags = flags; + pZip->m_pState->m_zip64 = MZ_FALSE; + pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE; + + pZip->m_zip_mode = MZ_ZIP_MODE_READING; + + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) +{ + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; + pR++; + } + return (pL == pE) ? (l_len < r_len) : (l < r); +} + +#define MZ_SWAP_UINT32(a, b) \ + do \ + { \ + mz_uint32 t = a; \ + a = b; \ + b = t; \ + } \ + MZ_MACRO_END + +/* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */ +static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState = pZip->m_pState; + const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array *pCentral_dir = &pState->m_central_dir; + mz_uint32 *pIndices; + mz_uint32 start, end; + const mz_uint32 size = pZip->m_total_files; + + if (size <= 1U) + return; + + pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + + start = (size - 2U) >> 1U; + for (;;) + { + mz_uint64 child, root = start; + for (;;) + { + if ((child = (root << 1U) + 1U) >= size) + break; + child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]))); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); + root = child; + } + if (!start) + break; + start--; + } + + end = size - 1; + while (end > 0) + { + mz_uint64 child, root = 0; + MZ_SWAP_UINT32(pIndices[end], pIndices[0]); + for (;;) + { + if ((child = (root << 1U) + 1U) >= end) + break; + child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); + root = child; + } + end--; + } +} + +static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs) +{ + mz_int64 cur_file_ofs; + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; + mz_uint8 *pBuf = (mz_uint8 *)buf_u32; + + /* Basic sanity checks - reject files which are too small */ + if (pZip->m_archive_size < record_size) + return MZ_FALSE; + + /* Find the record by scanning the file from the end towards the beginning. */ + cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); + for (;;) + { + int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); + + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) + return MZ_FALSE; + + for (i = n - 4; i >= 0; --i) + { + mz_uint s = MZ_READ_LE32(pBuf + i); + if (s == record_sig) + { + if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size) + break; + } + } + + if (i >= 0) + { + cur_file_ofs += i; + break; + } + + /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */ + if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size))) + return MZ_FALSE; + + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); + } + + *pOfs = cur_file_ofs; + return MZ_TRUE; +} + +static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags) +{ + mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0; + mz_uint64 cdir_ofs = 0; + mz_int64 cur_file_ofs = 0; + const mz_uint8 *p; + + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; + mz_uint8 *pBuf = (mz_uint8 *)buf_u32; + mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); + mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32; + + mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32; + + mz_uint64 zip64_end_of_central_dir_ofs = 0; + + /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */ + if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs)) + return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR); + + /* Read and verify the end of central directory record. */ + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) + { + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) + { + if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) + { + zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS); + if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) + { + if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) + { + pZip->m_pState->m_zip64 = MZ_TRUE; + } + } + } + } + } + + pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS); + cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); + num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); + cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); + cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS); + cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); + + if (pZip->m_pState->m_zip64) + { + mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS); + mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS); + mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); + mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS); + mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS); + + if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (zip64_total_num_of_disks != 1U) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + /* Check for miniz's practical limits */ + if (zip64_cdir_total_entries > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + + pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries; + + if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + + cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk; + + /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */ + if (zip64_size_of_central_directory > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + cdir_size = (mz_uint32)zip64_size_of_central_directory; + + num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS); + + cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS); + + cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS); + } + + if (pZip->m_total_files != cdir_entries_on_this_disk) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + if (cdir_size < (mz_uint64)pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + pZip->m_central_directory_file_ofs = cdir_ofs; + + if (pZip->m_total_files) + { + mz_uint i, n; + /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */ + if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || + (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (sort_central_dir) + { + if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + /* Now create an index into the central directory file records, do some basic sanity checking on each record */ + p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; + for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) + { + mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size; + mz_uint64 comp_size, decomp_size, local_header_ofs; + + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); + + if (sort_central_dir) + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; + + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); + + if ((!pZip->m_pState->m_zip64_has_extended_info_fields) && + (ext_data_size) && + (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX)) + { + /* Attempt to find zip64 extended information field in the entry's extra data */ + mz_uint32 extra_size_remaining = ext_data_size; + + if (extra_size_remaining) + { + const mz_uint8 *pExtra_data; + void* buf = NULL; + + if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n) + { + buf = MZ_MALLOC(ext_data_size); + if(buf==NULL) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + pExtra_data = (mz_uint8*)buf; + } + else + { + pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; + } + + do + { + mz_uint32 field_id; + mz_uint32 field_data_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + + if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */ + pZip->m_pState->m_zip64 = MZ_TRUE; + pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE; + break; + } + + pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; + extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; + } while (extra_size_remaining); + + MZ_FREE(buf); + } + } + + /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */ + if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) + { + if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); + if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1))) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + if (comp_size != MZ_UINT32_MAX) + { + if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + n -= total_header_size; + p += total_header_size; + } + } + + if (sort_central_dir) + mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); + + return MZ_TRUE; +} + +void mz_zip_zero_struct(mz_zip_archive *pZip) +{ + if (pZip) + MZ_CLEAR_PTR(pZip); +} + +static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error) +{ + mz_bool status = MZ_TRUE; + + if (!pZip) + return MZ_FALSE; + + if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + { + if (set_last_error) + pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER; + + return MZ_FALSE; + } + + if (pZip->m_pState) + { + mz_zip_internal_state *pState = pZip->m_pState; + pZip->m_pState = NULL; + + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +#ifndef MINIZ_NO_STDIO + if (pState->m_pFile) + { + if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + { + if (MZ_FCLOSE(pState->m_pFile) == EOF) + { + if (set_last_error) + pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED; + status = MZ_FALSE; + } + } + pState->m_pFile = NULL; + } +#endif /* #ifndef MINIZ_NO_STDIO */ + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + } + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + + return status; +} + +mz_bool mz_zip_reader_end(mz_zip_archive *pZip) +{ + return mz_zip_reader_end_internal(pZip, MZ_TRUE); +} +mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags) +{ + if ((!pZip) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + + pZip->m_zip_type = MZ_ZIP_TYPE_USER; + pZip->m_archive_size = size; + + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); + memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); + return s; +} + +mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags) +{ + if (!pMem) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + + pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY; + pZip->m_archive_size = size; + pZip->m_pRead = mz_zip_mem_read_func; + pZip->m_pIO_opaque = pZip; + pZip->m_pNeeds_keepalive = NULL; + +#ifdef __cplusplus + pZip->m_pState->m_pMem = const_cast(pMem); +#else + pZip->m_pState->m_pMem = (void *)pMem; +#endif + + pZip->m_pState->m_mem_size = size; + + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + + file_ofs += pZip->m_pState->m_file_archive_start_ofs; + + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + + return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); +} + +mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) +{ + return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0); +} + +mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size) +{ + mz_uint64 file_size; + MZ_FILE *pFile; + + if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pFile = MZ_FOPEN(pFilename, "rb"); + if (!pFile) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + + file_size = archive_size; + if (!file_size) + { + if (MZ_FSEEK64(pFile, 0, SEEK_END)) + { + MZ_FCLOSE(pFile); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); + } + + file_size = MZ_FTELL64(pFile); + } + + /* TODO: Better sanity check archive_size and the # of actual remaining bytes */ + + if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + { + MZ_FCLOSE(pFile); + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + } + + if (!mz_zip_reader_init_internal(pZip, flags)) + { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + + pZip->m_zip_type = MZ_ZIP_TYPE_FILE; + pZip->m_pRead = mz_zip_file_read_func; + pZip->m_pIO_opaque = pZip; + pZip->m_pState->m_pFile = pFile; + pZip->m_archive_size = file_size; + pZip->m_pState->m_file_archive_start_ofs = file_start_ofs; + + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags) +{ + mz_uint64 cur_file_ofs; + + if ((!pZip) || (!pFile)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + + cur_file_ofs = MZ_FTELL64(pFile); + + if (!archive_size) + { + if (MZ_FSEEK64(pFile, 0, SEEK_END)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); + + archive_size = MZ_FTELL64(pFile) - cur_file_ofs; + + if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + } + + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + + pZip->m_zip_type = MZ_ZIP_TYPE_CFILE; + pZip->m_pRead = mz_zip_file_read_func; + + pZip->m_pIO_opaque = pZip; + pZip->m_pState->m_pFile = pFile; + pZip->m_archive_size = archive_size; + pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs; + + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +#endif /* #ifndef MINIZ_NO_STDIO */ + +static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index) +{ + if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files)) + return NULL; + return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); +} + +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint m_bit_flag; + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + if (!p) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return MZ_FALSE; + } + + m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0; +} + +mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint bit_flag; + mz_uint method; + + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + if (!p) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return MZ_FALSE; + } + + method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); + bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + + if ((method != 0) && (method != MZ_DEFLATED)) + { + mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + return MZ_FALSE; + } + + if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) + { + mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + return MZ_FALSE; + } + + if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG) + { + mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint filename_len, attribute_mapping_id, external_attr; + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + if (!p) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return MZ_FALSE; + } + + filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_len) + { + if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') + return MZ_TRUE; + } + + /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */ + /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */ + /* FIXME: Remove this check? Is it necessary - we already check the filename. */ + attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8; + (void)attribute_mapping_id; + + external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0) + { + return MZ_TRUE; + } + + return MZ_FALSE; +} + +static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data) +{ + mz_uint n; + const mz_uint8 *p = pCentral_dir_header; + + if (pFound_zip64_extra_data) + *pFound_zip64_extra_data = MZ_FALSE; + + if ((!p) || (!pStat)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* Extract fields from the central directory record. */ + pStat->m_file_index = file_index; + pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); + pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); + pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); + pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); +#ifndef MINIZ_NO_TIME + pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); +#endif + pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); + pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); + pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + + /* Copy as much of the filename and comment as possible. */ + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); + memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pStat->m_filename[n] = '\0'; + + n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); + n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); + pStat->m_comment_size = n; + memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); + pStat->m_comment[n] = '\0'; + + /* Set some flags for convienance */ + pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index); + pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index); + pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index); + + /* See if we need to read any zip64 extended information fields. */ + /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */ + if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX) + { + /* Attempt to find zip64 extended information field in the entry's extra data */ + mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); + + if (extra_size_remaining) + { + const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + + do + { + mz_uint32 field_id; + mz_uint32 field_data_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + + if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2; + mz_uint32 field_data_remaining = field_data_size; + + if (pFound_zip64_extra_data) + *pFound_zip64_extra_data = MZ_TRUE; + + if (pStat->m_uncomp_size == MZ_UINT32_MAX) + { + if (field_data_remaining < sizeof(mz_uint64)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + pStat->m_uncomp_size = MZ_READ_LE64(pField_data); + pField_data += sizeof(mz_uint64); + field_data_remaining -= sizeof(mz_uint64); + } + + if (pStat->m_comp_size == MZ_UINT32_MAX) + { + if (field_data_remaining < sizeof(mz_uint64)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + pStat->m_comp_size = MZ_READ_LE64(pField_data); + pField_data += sizeof(mz_uint64); + field_data_remaining -= sizeof(mz_uint64); + } + + if (pStat->m_local_header_ofs == MZ_UINT32_MAX) + { + if (field_data_remaining < sizeof(mz_uint64)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + pStat->m_local_header_ofs = MZ_READ_LE64(pField_data); + pField_data += sizeof(mz_uint64); + field_data_remaining -= sizeof(mz_uint64); + } + + break; + } + + pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; + extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; + } while (extra_size_remaining); + } + } + + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) +{ + mz_uint i; + if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) + return 0 == memcmp(pA, pB, len); + for (i = 0; i < len; ++i) + if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) + return MZ_FALSE; + return MZ_TRUE; +} + +static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) +{ + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; + pR++; + } + return (pL == pE) ? (int)(l_len - r_len) : (l - r); +} + +static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex) +{ + mz_zip_internal_state *pState = pZip->m_pState; + const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array *pCentral_dir = &pState->m_central_dir; + mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const mz_uint32 size = pZip->m_total_files; + const mz_uint filename_len = (mz_uint)strlen(pFilename); + + if (pIndex) + *pIndex = 0; + + if (size) + { + /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */ + /* honestly the major expense here on 32-bit CPU's will still be the filename compare */ + mz_int64 l = 0, h = (mz_int64)size - 1; + + while (l <= h) + { + mz_int64 m = l + ((h - l) >> 1); + mz_uint32 file_index = pIndices[(mz_uint32)m]; + + int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); + if (!comp) + { + if (pIndex) + *pIndex = file_index; + return MZ_TRUE; + } + else if (comp < 0) + l = m + 1; + else + h = m - 1; + } + } + + return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND); +} + +int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) +{ + mz_uint32 index; + if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index)) + return -1; + else + return (int)index; +} + +mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex) +{ + mz_uint file_index; + size_t name_len, comment_len; + + if (pIndex) + *pIndex = 0; + + if ((!pZip) || (!pZip->m_pState) || (!pName)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* See if we can use a binary search */ + if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) && + (pZip->m_zip_mode == MZ_ZIP_MODE_READING) && + ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) + { + return mz_zip_locate_file_binary_search(pZip, pName, pIndex); + } + + /* Locate the entry by scanning the entire central directory */ + name_len = strlen(pName); + if (name_len > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + comment_len = pComment ? strlen(pComment) : 0; + if (comment_len > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + for (file_index = 0; file_index < pZip->m_total_files; file_index++) + { + const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); + mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); + const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + if (filename_len < name_len) + continue; + if (comment_len) + { + mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); + const char *pFile_comment = pFilename + filename_len + file_extra_len; + if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags))) + continue; + } + if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) + { + int ofs = filename_len - 1; + do + { + if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) + break; + } while (--ofs >= 0); + ofs++; + pFilename += ofs; + filename_len -= ofs; + } + if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags))) + { + if (pIndex) + *pIndex = file_index; + return MZ_TRUE; + } + } + + return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND); +} + +static +mz_bool mz_zip_reader_extract_to_mem_no_alloc1(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size, const mz_zip_archive_file_stat *st) +{ + int status = TINFL_STATUS_DONE; + mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; + mz_zip_archive_file_stat file_stat; + void *pRead_buf; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + tinfl_decompressor inflator; + + if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (st) { + file_stat = *st; + } else + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + /* A directory or zero length file */ + if ((file_stat.m_is_directory) || (!file_stat.m_comp_size)) + return MZ_TRUE; + + /* Encryption and patch files are not supported. */ + if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + + /* This function only supports decompressing stored and deflate. */ + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + + /* Ensure supplied output buffer is large enough. */ + needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; + if (buf_size < needed_size) + return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL); + + /* Read and parse the local directory entry. */ + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + /* The file is stored or the caller has requested the compressed data. */ + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0) + { + if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) + return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED); + } +#endif + + return MZ_TRUE; + } + + /* Decompress the file either directly from memory or from a file input buffer. */ + tinfl_init(&inflator); + + if (pZip->m_pState->m_pMem) + { + /* Read directly from the archive in memory. */ + pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else if (pUser_read_buf) + { + /* Use a user provided read buffer. */ + if (!user_read_buf_size) + return MZ_FALSE; + pRead_buf = (mz_uint8 *)pUser_read_buf; + read_buf_size = user_read_buf_size; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + else + { + /* Temporarily allocate a read buffer. */ + read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); + if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + do + { + /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */ + size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + out_buf_ofs += out_buf_size; + } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); + + if (status == TINFL_STATUS_DONE) + { + /* Make sure the entire file was decompressed, and check its CRC. */ + if (out_buf_ofs != file_stat.m_uncomp_size) + { + mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); + status = TINFL_STATUS_FAILED; + } +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) + { + mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED); + status = TINFL_STATUS_FAILED; + } +#endif + } + + if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + + return status == TINFL_STATUS_DONE; +} + +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +{ + return mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size, NULL); +} + +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + return MZ_FALSE; + return mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size, NULL); +} + +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) +{ + return mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, buf_size, flags, NULL, 0, NULL); +} + +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) +{ + return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); +} + +void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) +{ + mz_zip_archive_file_stat file_stat; + mz_uint64 alloc_size; + void *pBuf; + + if (pSize) + *pSize = 0; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return NULL; + + alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; + if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) + { + mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + return NULL; + } + + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + return NULL; + } + + if (!mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, (size_t)alloc_size, flags, NULL, 0, &file_stat)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return NULL; + } + + if (pSize) + *pSize = (size_t)alloc_size; + return pBuf; +} + +void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + { + if (pSize) + *pSize = 0; + return MZ_FALSE; + } + return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); +} + +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +{ + int status = TINFL_STATUS_DONE; +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + mz_uint file_crc32 = MZ_CRC32_INIT; +#endif + mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; + mz_zip_archive_file_stat file_stat; + void *pRead_buf = NULL; + void *pWrite_buf = NULL; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + + if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + /* A directory or zero length file */ + if ((file_stat.m_is_directory) || (!file_stat.m_comp_size)) + return MZ_TRUE; + + /* Encryption and patch files are not supported. */ + if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + + /* This function only supports decompressing stored and deflate. */ + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + + /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */ + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + /* Decompress the file either directly from memory or from a file input buffer. */ + if (pZip->m_pState->m_pMem) + { + pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + /* The file is stored or the caller has requested the compressed data. */ + if (pZip->m_pState->m_pMem) + { + if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) + { + mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); + status = TINFL_STATUS_FAILED; + } + else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); +#endif + } + + cur_file_ofs += file_stat.m_comp_size; + out_buf_ofs += file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + while (comp_remaining) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); + } +#endif + + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + + cur_file_ofs += read_buf_avail; + out_buf_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + } + } + } + else + { + tinfl_decompressor inflator; + tinfl_init(&inflator); + + if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + status = TINFL_STATUS_FAILED; + } + else + { + do + { + mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + + if (out_buf_size) + { + if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) + { + mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); +#endif + if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) + { + mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); + status = TINFL_STATUS_FAILED; + break; + } + } + } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); + } + } + + if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + { + /* Make sure the entire file was decompressed, and check its CRC. */ + if (out_buf_ofs != file_stat.m_uncomp_size) + { + mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); + status = TINFL_STATUS_FAILED; + } +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + else if (file_crc32 != file_stat.m_crc32) + { + mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); + status = TINFL_STATUS_FAILED; + } +#endif + } + + if (!pZip->m_pState->m_pMem) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + + if (pWrite_buf) + pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); + + return status == TINFL_STATUS_DONE; +} + +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + return MZ_FALSE; + + return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); +} + +mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags) +{ + mz_zip_reader_extract_iter_state *pState; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + + /* Argument sanity check */ + if ((!pZip) || (!pZip->m_pState)) + return NULL; + + /* Allocate an iterator status structure */ + pState = (mz_zip_reader_extract_iter_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state)); + if (!pState) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + return NULL; + } + + /* Fetch file details */ + if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + return NULL; + } + + /* Encryption and patch files are not supported. */ + if (pState->file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) + { + mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + return NULL; + } + + /* This function only supports decompressing stored and deflate. */ + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED)) + { + mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + return NULL; + } + + /* Init state - save args */ + pState->pZip = pZip; + pState->flags = flags; + + /* Init state - reset variables to defaults */ + pState->status = TINFL_STATUS_DONE; +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + pState->file_crc32 = MZ_CRC32_INIT; +#endif + pState->read_buf_ofs = 0; + pState->out_buf_ofs = 0; + pState->pRead_buf = NULL; + pState->pWrite_buf = NULL; + pState->out_blk_remain = 0; + + /* Read and parse the local directory entry. */ + pState->cur_file_ofs = pState->file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + return NULL; + } + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + return NULL; + } + + pState->cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + return NULL; + } + + /* Decompress the file either directly from memory or from a file input buffer. */ + if (pZip->m_pState->m_pMem) + { + pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs; + pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size; + pState->comp_remaining = pState->file_stat.m_comp_size; + } + else + { + if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))) + { + /* Decompression required, therefore intermediate read buffer required */ + pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); + if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size))) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + return NULL; + } + } + else + { + /* Decompression not required - we will be reading directly into user buffer, no temp buf required */ + pState->read_buf_size = 0; + } + pState->read_buf_avail = 0; + pState->comp_remaining = pState->file_stat.m_comp_size; + } + + if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))) + { + /* Decompression required, init decompressor */ + tinfl_init( &pState->inflator ); + + /* Allocate write buffer */ + if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + if (pState->pRead_buf) + pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf); + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + return NULL; + } + } + + return pState; +} + +mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags) +{ + mz_uint32 file_index; + + /* Locate file index by name */ + if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) + return NULL; + + /* Construct iterator */ + return mz_zip_reader_extract_iter_new(pZip, file_index, flags); +} + +size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size) +{ + size_t copied_to_caller = 0; + + /* Argument sanity check */ + if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf)) + return 0; + + if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)) + { + /* The file is stored or the caller has requested the compressed data, calc amount to return. */ + copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining ); + + /* Zip is in memory....or requires reading from a file? */ + if (pState->pZip->m_pState->m_pMem) + { + /* Copy data to caller's buffer */ + memcpy( pvBuf, pState->pRead_buf, copied_to_caller ); + pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller; + } + else + { + /* Read directly into caller's buffer */ + if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller) + { + /* Failed to read all that was asked for, flag failure and alert user */ + mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED); + pState->status = TINFL_STATUS_FAILED; + copied_to_caller = 0; + } + } + +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + /* Compute CRC if not returning compressed data only */ + if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller); +#endif + + /* Advance offsets, dec counters */ + pState->cur_file_ofs += copied_to_caller; + pState->out_buf_ofs += copied_to_caller; + pState->comp_remaining -= copied_to_caller; + } + else + { + do + { + /* Calc ptr to write buffer - given current output pos and block size */ + mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + + /* Calc max output size - given current output pos and block size */ + size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + + if (!pState->out_blk_remain) + { + /* Read more data from file if none available (and reading from file) */ + if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem)) + { + /* Calc read size */ + pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining); + if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pState->pRead_buf, (size_t)pState->read_buf_avail) != pState->read_buf_avail) + { + mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED); + pState->status = TINFL_STATUS_FAILED; + break; + } + + /* Advance offsets, dec counters */ + pState->cur_file_ofs += pState->read_buf_avail; + pState->comp_remaining -= pState->read_buf_avail; + pState->read_buf_ofs = 0; + } + + /* Perform decompression */ + in_buf_size = (size_t)pState->read_buf_avail; + pState->status = tinfl_decompress(&pState->inflator, (const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs, &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur, &out_buf_size, pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); + pState->read_buf_avail -= in_buf_size; + pState->read_buf_ofs += in_buf_size; + + /* Update current output block size remaining */ + pState->out_blk_remain = out_buf_size; + } + + if (pState->out_blk_remain) + { + /* Calc amount to return. */ + size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain ); + + /* Copy data to caller's buffer */ + memcpy( (mz_uint8*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy ); + +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + /* Perform CRC */ + pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy); +#endif + + /* Decrement data consumed from block */ + pState->out_blk_remain -= to_copy; + + /* Inc output offset, while performing sanity check */ + if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size) + { + mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED); + pState->status = TINFL_STATUS_FAILED; + break; + } + + /* Increment counter of data copied to caller */ + copied_to_caller += to_copy; + } + } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) ); + } + + /* Return how many bytes were copied into user buffer */ + return copied_to_caller; +} + +mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState) +{ + int status; + + /* Argument sanity check */ + if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState)) + return MZ_FALSE; + + /* Was decompression completed and requested? */ + if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + { + /* Make sure the entire file was decompressed, and check its CRC. */ + if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size) + { + mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); + pState->status = TINFL_STATUS_FAILED; + } +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + else if (pState->file_crc32 != pState->file_stat.m_crc32) + { + mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED); + pState->status = TINFL_STATUS_FAILED; + } +#endif + } + + /* Free buffers */ + if (!pState->pZip->m_pState->m_pMem) + pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf); + if (pState->pWrite_buf) + pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf); + + /* Save status */ + status = pState->status; + + /* Free context */ + pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState); + + return status == TINFL_STATUS_DONE; +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) +{ + (void)ofs; + + return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque); +} + +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) +{ + mz_bool status; + mz_zip_archive_file_stat file_stat; + MZ_FILE *pFile; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + if ((file_stat.m_is_directory) || (!file_stat.m_is_supported)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); + + pFile = MZ_FOPEN(pDst_filename, "wb"); + if (!pFile) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + + status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); + + if (MZ_FCLOSE(pFile) == EOF) + { + if (status) + mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); + + status = MZ_FALSE; + } + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO) + if (status) + mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); +#endif + + return status; +} + +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) + return MZ_FALSE; + + return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); +} + +mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags) +{ + mz_zip_archive_file_stat file_stat; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + if ((file_stat.m_is_directory) || (!file_stat.m_is_supported)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); + + return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); +} + +mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags) +{ + mz_uint32 file_index; + if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) + return MZ_FALSE; + + return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags); +} +#endif /* #ifndef MINIZ_NO_STDIO */ + +static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_uint32 *p = (mz_uint32 *)pOpaque; + (void)file_ofs; + *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n); + return n; +} + +mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags) +{ + mz_zip_archive_file_stat file_stat; + mz_zip_internal_state *pState; + const mz_uint8 *pCentral_dir_header; + mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE; + mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + mz_uint64 local_header_ofs = 0; + mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32; + mz_uint64 local_header_comp_size, local_header_uncomp_size; + mz_uint32 uncomp_crc32 = MZ_CRC32_INIT; + mz_bool has_data_descriptor; + mz_uint32 local_header_bit_flags; + + mz_zip_array file_data_array; + mz_zip_array_init(&file_data_array, 1); + + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (file_index > pZip->m_total_files) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + pCentral_dir_header = mz_zip_get_cdh(pZip, file_index); + + if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir)) + return MZ_FALSE; + + /* A directory or zero length file */ + if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size)) + return MZ_TRUE; + + /* Encryption and patch files are not supported. */ + if (file_stat.m_is_encrypted) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + + /* This function only supports stored and deflate. */ + if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); + + if (!file_stat.m_is_supported) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); + + /* Read and parse the local directory entry. */ + local_header_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS); + local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS); + local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS); + local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS); + local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); + has_data_descriptor = (local_header_bit_flags & 8) != 0; + + if (local_header_filename_len != strlen(file_stat.m_filename)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE)) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + goto handle_failure; + } + + if (local_header_filename_len) + { + if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + goto handle_failure; + } + + /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */ + if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0) + { + mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + goto handle_failure; + } + } + + if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX))) + { + mz_uint32 extra_size_remaining = local_header_extra_len; + const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p; + + if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + goto handle_failure; + } + + do + { + mz_uint32 field_id, field_data_size, field_total_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + goto handle_failure; + } + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + field_total_size = field_data_size + sizeof(mz_uint16) * 2; + + if (field_total_size > extra_size_remaining) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + goto handle_failure; + } + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32); + + if (field_data_size < sizeof(mz_uint64) * 2) + { + mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + goto handle_failure; + } + + local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data); + local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); + + found_zip64_ext_data_in_ldir = MZ_TRUE; + break; + } + + pExtra_data += field_total_size; + extra_size_remaining -= field_total_size; + } while (extra_size_remaining); + } + + /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */ + /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */ + if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32)) + { + mz_uint8 descriptor_buf[32]; + mz_bool has_id; + const mz_uint8 *pSrc; + mz_uint32 file_crc32; + mz_uint64 comp_size = 0, uncomp_size = 0; + + mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4; + + if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s)) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + goto handle_failure; + } + + has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID); + pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf; + + file_crc32 = MZ_READ_LE32(pSrc); + + if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) + { + comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32)); + uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64)); + } + else + { + comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32)); + uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32)); + } + + if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size)) + { + mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + goto handle_failure; + } + } + else + { + if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size)) + { + mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + goto handle_failure; + } + } + + mz_zip_array_clear(pZip, &file_data_array); + + if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0) + { + if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0)) + return MZ_FALSE; + + /* 1 more check to be sure, although the extract checks too. */ + if (uncomp_crc32 != file_stat.m_crc32) + { + mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + return MZ_FALSE; + } + } + + return MZ_TRUE; + +handle_failure: + mz_zip_array_clear(pZip, &file_data_array); + return MZ_FALSE; +} + +mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags) +{ + mz_zip_internal_state *pState; + mz_uint32 i; + + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + /* Basic sanity checks */ + if (!pState->m_zip64) + { + if (pZip->m_total_files > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + if (pZip->m_archive_size > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + } + else + { + if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + } + + for (i = 0; i < pZip->m_total_files; i++) + { + if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags) + { + mz_uint32 found_index; + mz_zip_archive_file_stat stat; + + if (!mz_zip_reader_file_stat(pZip, i, &stat)) + return MZ_FALSE; + + if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index)) + return MZ_FALSE; + + /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */ + if (found_index != i) + return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); + } + + if (!mz_zip_validate_file(pZip, i, flags)) + return MZ_FALSE; + } + + return MZ_TRUE; +} + +mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr) +{ + mz_bool success = MZ_TRUE; + mz_zip_archive zip; + mz_zip_error actual_err = MZ_ZIP_NO_ERROR; + + if ((!pMem) || (!size)) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_PARAMETER; + return MZ_FALSE; + } + + mz_zip_zero_struct(&zip); + + if (!mz_zip_reader_init_mem(&zip, pMem, size, flags)) + { + if (pErr) + *pErr = zip.m_last_error; + return MZ_FALSE; + } + + if (!mz_zip_validate_archive(&zip, flags)) + { + actual_err = zip.m_last_error; + success = MZ_FALSE; + } + + if (!mz_zip_reader_end_internal(&zip, success)) + { + if (!actual_err) + actual_err = zip.m_last_error; + success = MZ_FALSE; + } + + if (pErr) + *pErr = actual_err; + + return success; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr) +{ + mz_bool success = MZ_TRUE; + mz_zip_archive zip; + mz_zip_error actual_err = MZ_ZIP_NO_ERROR; + + if (!pFilename) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_PARAMETER; + return MZ_FALSE; + } + + mz_zip_zero_struct(&zip); + + if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0)) + { + if (pErr) + *pErr = zip.m_last_error; + return MZ_FALSE; + } + + if (!mz_zip_validate_archive(&zip, flags)) + { + actual_err = zip.m_last_error; + success = MZ_FALSE; + } + + if (!mz_zip_reader_end_internal(&zip, success)) + { + if (!actual_err) + actual_err = zip.m_last_error; + success = MZ_FALSE; + } + + if (pErr) + *pErr = actual_err; + + return success; +} +#endif /* #ifndef MINIZ_NO_STDIO */ + +/* ------------------- .ZIP archive writing */ + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v) +{ + p[0] = (mz_uint8)v; + p[1] = (mz_uint8)(v >> 8); +} +static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v) +{ + p[0] = (mz_uint8)v; + p[1] = (mz_uint8)(v >> 8); + p[2] = (mz_uint8)(v >> 16); + p[3] = (mz_uint8)(v >> 24); +} +static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v) +{ + mz_write_le32(p, (mz_uint32)v); + mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32)); +} + +#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) +#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) +#define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v)) + +static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_zip_internal_state *pState = pZip->m_pState; + mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); + + if (!n) + return 0; + + /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */ + if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); + return 0; + } + + if (new_size > pState->m_mem_capacity) + { + void *pNew_block; + size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); + + while (new_capacity < new_size) + new_capacity *= 2; + + if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) + { + mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + return 0; + } + + pState->m_pMem = pNew_block; + pState->m_mem_capacity = new_capacity; + } + memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); + pState->m_mem_size = (size_t)new_size; + return n; +} + +static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error) +{ + mz_zip_internal_state *pState; + mz_bool status = MZ_TRUE; + + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) + { + if (set_last_error) + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return MZ_FALSE; + } + + pState = pZip->m_pState; + pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +#ifndef MINIZ_NO_STDIO + if (pState->m_pFile) + { + if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + { + if (MZ_FCLOSE(pState->m_pFile) == EOF) + { + if (set_last_error) + mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); + status = MZ_FALSE; + } + } + + pState->m_pFile = NULL; + } +#endif /* #ifndef MINIZ_NO_STDIO */ + + if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); + pState->m_pMem = NULL; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + return status; +} + +mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags) +{ + mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0; + + if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + { + if (!pZip->m_pRead) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + } + + if (pZip->m_file_offset_alignment) + { + /* Ensure user specified file offset alignment is a power of 2. */ + if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + } + + if (!pZip->m_pAlloc) + pZip->m_pAlloc = miniz_def_alloc_func; + if (!pZip->m_pFree) + pZip->m_pFree = miniz_def_free_func; + if (!pZip->m_pRealloc) + pZip->m_pRealloc = miniz_def_realloc_func; + + pZip->m_archive_size = existing_size; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + + pZip->m_pState->m_zip64 = zip64; + pZip->m_pState->m_zip64_has_extended_info_fields = zip64; + + pZip->m_zip_type = MZ_ZIP_TYPE_USER; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) +{ + return mz_zip_writer_init_v2(pZip, existing_size, 0); +} + +mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags) +{ + pZip->m_pWrite = mz_zip_heap_write_func; + pZip->m_pNeeds_keepalive = NULL; + + if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + pZip->m_pRead = mz_zip_mem_read_func; + + pZip->m_pIO_opaque = pZip; + + if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) + return MZ_FALSE; + + pZip->m_zip_type = MZ_ZIP_TYPE_HEAP; + + if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) + { + if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) + { + mz_zip_writer_end_internal(pZip, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + pZip->m_pState->m_mem_capacity = initial_allocation_size; + } + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) +{ + return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0); +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + + file_ofs += pZip->m_pState->m_file_archive_start_ofs; + + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); + return 0; + } + + return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); +} + +mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) +{ + return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0); +} + +mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags) +{ + MZ_FILE *pFile; + + pZip->m_pWrite = mz_zip_file_write_func; + pZip->m_pNeeds_keepalive = NULL; + + if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + pZip->m_pRead = mz_zip_file_read_func; + + pZip->m_pIO_opaque = pZip; + + if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) + return MZ_FALSE; + + if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb"))) + { + mz_zip_writer_end(pZip); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + } + + pZip->m_pState->m_pFile = pFile; + pZip->m_zip_type = MZ_ZIP_TYPE_FILE; + + if (size_to_reserve_at_beginning) + { + mz_uint64 cur_ofs = 0; + char buf[4096]; + + MZ_CLEAR_ARR(buf); + + do + { + size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) + { + mz_zip_writer_end(pZip); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + cur_ofs += n; + size_to_reserve_at_beginning -= n; + } while (size_to_reserve_at_beginning); + } + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags) +{ + pZip->m_pWrite = mz_zip_file_write_func; + pZip->m_pNeeds_keepalive = NULL; + + if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) + pZip->m_pRead = mz_zip_file_read_func; + + pZip->m_pIO_opaque = pZip; + + if (!mz_zip_writer_init_v2(pZip, 0, flags)) + return MZ_FALSE; + + pZip->m_pState->m_pFile = pFile; + pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + pZip->m_zip_type = MZ_ZIP_TYPE_CFILE; + + return MZ_TRUE; +} +#endif /* #ifndef MINIZ_NO_STDIO */ + +mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags) +{ + mz_zip_internal_state *pState; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (flags & MZ_ZIP_FLAG_WRITE_ZIP64) + { + /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */ + if (!pZip->m_pState->m_zip64) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + } + + /* No sense in trying to write to an archive that's already at the support max size */ + if (pZip->m_pState->m_zip64) + { + if (pZip->m_total_files == MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + if (pZip->m_total_files == MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + + if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); + } + + pState = pZip->m_pState; + + if (pState->m_pFile) + { +#ifdef MINIZ_NO_STDIO + (void)pFilename; + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); +#else + if (pZip->m_pIO_opaque != pZip) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) + { + if (!pFilename) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */ + if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) + { + /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */ + mz_zip_reader_end_internal(pZip, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + } + } + + pZip->m_pWrite = mz_zip_file_write_func; + pZip->m_pNeeds_keepalive = NULL; +#endif /* #ifdef MINIZ_NO_STDIO */ + } + else if (pState->m_pMem) + { + /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */ + if (pZip->m_pIO_opaque != pZip) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState->m_mem_capacity = pState->m_mem_size; + pZip->m_pWrite = mz_zip_heap_write_func; + pZip->m_pNeeds_keepalive = NULL; + } + /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */ + else if (!pZip->m_pWrite) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* Start writing new files at the archive's current central directory location. */ + /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */ + pZip->m_archive_size = pZip->m_central_directory_file_ofs; + pZip->m_central_directory_file_ofs = 0; + + /* Clear the sorted central dir offsets, they aren't useful or maintained now. */ + /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */ + /* TODO: We could easily maintain the sorted central directory offsets. */ + mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets); + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) +{ + return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0); +} + +/* TODO: pArchive_name is a terrible name here! */ +mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) +{ + return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); +} + +typedef struct +{ + mz_zip_archive *m_pZip; + mz_uint64 m_cur_archive_file_ofs; + mz_uint64 m_comp_size; +} mz_zip_writer_add_state; + +static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser) +{ + mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; + if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) + return MZ_FALSE; + + pState->m_cur_archive_file_ofs += len; + pState->m_comp_size += len; + return MZ_TRUE; +} + +#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2) +#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3) +static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs) +{ + mz_uint8 *pDst = pBuf; + mz_uint32 field_size = 0; + + MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID); + MZ_WRITE_LE16(pDst + 2, 0); + pDst += sizeof(mz_uint16) * 2; + + if (pUncomp_size) + { + MZ_WRITE_LE64(pDst, *pUncomp_size); + pDst += sizeof(mz_uint64); + field_size += sizeof(mz_uint64); + } + + if (pComp_size) + { + MZ_WRITE_LE64(pDst, *pComp_size); + pDst += sizeof(mz_uint64); + field_size += sizeof(mz_uint64); + } + + if (pLocal_header_ofs) + { + MZ_WRITE_LE64(pDst, *pLocal_header_ofs); + pDst += sizeof(mz_uint64); + field_size += sizeof(mz_uint64); + } + + MZ_WRITE_LE16(pBuf + 2, field_size); + + return (mz_uint32)(pDst - pBuf); +} + +static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) +{ + (void)pZip; + memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, + mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, + mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, + mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, + mz_uint64 local_header_ofs, mz_uint32 ext_attributes) +{ + (void)pZip; + memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX)); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX)); + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, + const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, + mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, + mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, + mz_uint64 local_header_ofs, mz_uint32 ext_attributes, + const char *user_extra_data, mz_uint user_extra_data_len) +{ + mz_zip_internal_state *pState = pZip->m_pState; + mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; + size_t orig_central_dir_size = pState->m_central_dir.m_size; + mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + + if (!pZip->m_pState->m_zip64) + { + if (local_header_ofs > 0xFFFFFFFF) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); + } + + /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ + if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, (mz_uint16)(extra_size + user_extra_data_len), comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) + { + /* Try to resize the central directory array back into its original state. */ + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) +{ + /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */ + if (*pArchive_name == '/') + return MZ_FALSE; + + /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/ + + return MZ_TRUE; +} + +static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) +{ + mz_uint32 n; + if (!pZip->m_file_offset_alignment) + return 0; + n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); + return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1)); +} + +static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) +{ + char buf[4096]; + memset(buf, 0, MZ_MIN(sizeof(buf), n)); + while (n) + { + mz_uint32 s = MZ_MIN(sizeof(buf), n); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_file_ofs += s; + n -= s; + } + return MZ_TRUE; +} + +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) +{ + return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0); +} + +mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, + mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, + const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) +{ + mz_uint16 method = 0, dos_time = 0, dos_date = 0; + mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; + mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + tdefl_compressor *pComp = NULL; + mz_bool store_data_uncompressed; + mz_zip_internal_state *pState; + mz_uint8 *pExtra_data = NULL; + mz_uint32 extra_size = 0; + mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; + mz_uint16 bit_flags = 0; + + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + + if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; + + if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME)) + bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; + + level = level_and_flags & 0xF; + store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + if (pState->m_zip64) + { + if (pZip->m_total_files == MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + if (pZip->m_total_files == MZ_UINT16_MAX) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */ + } + if (((mz_uint64)buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + } + } + + if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); + +#ifndef MINIZ_NO_TIME + if (last_modified != NULL) + { + mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date); + } + else + { + MZ_TIME_T cur_time; + time(&cur_time); + mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date); + } +#endif /* #ifndef MINIZ_NO_TIME */ + + if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size); + uncomp_size = buf_size; + if (uncomp_size <= 3) + { + level = 0; + store_data_uncompressed = MZ_TRUE; + } + } + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ + if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + if (!pState->m_zip64) + { + /* Bail early if the archive would obviously become too large */ + if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len + + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len + + MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + } + } + + if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) + { + /* Set DOS Subdirectory attribute bit. */ + ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG; + + /* Subdirectories cannot contain data. */ + if ((buf_size) || (uncomp_size)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + } + + /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */ + if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if ((!store_data_uncompressed) && (buf_size)) + { + if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) + { + MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + cur_archive_file_ofs += num_alignment_padding_bytes; + + MZ_CLEAR_ARR(local_dir_header); + + if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + method = MZ_DEFLATED; + } + + if (pState->m_zip64) + { + if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) + { + pExtra_data = extra_data; + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, bit_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + cur_archive_file_ofs += archive_name_size; + + if (pExtra_data != NULL) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += extra_size; + } + } + else + { + if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + cur_archive_file_ofs += archive_name_size; + } + + if (user_extra_data_len > 0) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += user_extra_data_len; + } + + if (store_data_uncompressed) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_file_ofs += buf_size; + comp_size = buf_size; + } + else if (buf_size) + { + mz_zip_writer_add_state state; + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || + (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED); + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pComp = NULL; + + if (uncomp_size) + { + mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64]; + mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32; + + MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR); + + MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); + MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); + if (pExtra_data == NULL) + { + if (comp_size > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + MZ_WRITE_LE32(local_dir_footer + 8, comp_size); + MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size); + } + else + { + MZ_WRITE_LE64(local_dir_footer + 8, comp_size); + MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size); + local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64; + } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size) + return MZ_FALSE; + + cur_archive_file_ofs += local_dir_footer_size; + } + + if (pExtra_data != NULL) + { + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, + comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes, + user_extra_data_central, user_extra_data_central_len)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) +{ + mz_uint16 gen_flags; + mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; + mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; + mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + mz_uint8 *pExtra_data = NULL; + mz_uint32 extra_size = 0; + mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; + mz_zip_internal_state *pState; + mz_uint64 file_ofs = 0, cur_archive_header_file_ofs; + + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + + gen_flags = (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) ? 0 : MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; + + if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME)) + gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; + + /* Sanity checks */ + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX)) + { + /* Source file is too large for non-zip64 */ + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + pState->m_zip64 = MZ_TRUE; + } + + /* We could support this, but why? */ + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); + + if (pState->m_zip64) + { + if (pZip->m_total_files == MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + if (pZip->m_total_files == MZ_UINT16_MAX) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */ + } + } + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ + if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + if (!pState->m_zip64) + { + /* Bail early if the archive would obviously become too large */ + if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024 + + MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF) + { + pState->m_zip64 = MZ_TRUE; + /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ + } + } + +#ifndef MINIZ_NO_TIME + if (pFile_time) + { + mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date); + } +#endif + + if (max_size <= 3) + level = 0; + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) + { + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_file_ofs += num_alignment_padding_bytes; + local_dir_header_ofs = cur_archive_file_ofs; + + if (pZip->m_file_offset_alignment) + { + MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + + if (max_size && level) + { + method = MZ_DEFLATED; + } + + MZ_CLEAR_ARR(local_dir_header); + if (pState->m_zip64) + { + if (max_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) + { + pExtra_data = extra_data; + if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, + (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + else + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, NULL, + NULL, + (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_file_ofs += archive_name_size; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += extra_size; + } + else + { + if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_file_ofs += archive_name_size; + } + + if (user_extra_data_len > 0) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_file_ofs += user_extra_data_len; + } + + if (max_size) + { + void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); + if (!pRead_buf) + { + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!level) + { + while (1) + { + size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE); + if (n == 0) + break; + + if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + file_ofs += n; + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); + cur_archive_file_ofs += n; + } + uncomp_size = file_ofs; + comp_size = uncomp_size; + } + else + { + mz_bool result = MZ_FALSE; + mz_zip_writer_add_state state; + tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + } + + for (;;) + { + tdefl_status status; + tdefl_flush flush = TDEFL_NO_FLUSH; + + size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE); + if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size)) + { + mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + break; + } + + file_ofs += n; + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); + + if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque)) + flush = TDEFL_FULL_FLUSH; + + if (n == 0) + flush = TDEFL_FINISH; + + status = tdefl_compress_buffer(pComp, pRead_buf, n, flush); + if (status == TDEFL_STATUS_DONE) + { + result = MZ_TRUE; + break; + } + else if (status != TDEFL_STATUS_OKAY) + { + mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED); + break; + } + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + + if (!result) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return MZ_FALSE; + } + + uncomp_size = file_ofs; + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + } + + if (!(level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)) + { + mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64]; + mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32; + + MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); + MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); + if (pExtra_data == NULL) + { + if (comp_size > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + MZ_WRITE_LE32(local_dir_footer + 8, comp_size); + MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size); + } + else + { + MZ_WRITE_LE64(local_dir_footer + 8, comp_size); + MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size); + local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64; + } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size) + return MZ_FALSE; + + cur_archive_file_ofs += local_dir_footer_size; + } + + if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) + { + if (pExtra_data != NULL) + { + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, + (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), + (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size, + (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size, + uncomp_crc32, method, gen_flags, dos_time, dos_date)) + return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); + + cur_archive_header_file_ofs = local_dir_header_ofs; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + if (pExtra_data != NULL) + { + cur_archive_header_file_ofs += sizeof(local_dir_header); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_archive_header_file_ofs += archive_name_size; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, extra_data, extra_size) != extra_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_archive_header_file_ofs += extra_size; + } + } + + if (pExtra_data != NULL) + { + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + } + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, comment_size, + uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes, + user_extra_data_central, user_extra_data_central_len)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO + +static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pSrc_file); + + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + + return MZ_FREAD(pBuf, 1, n, pSrc_file); +} + +mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) +{ + return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, max_size, pFile_time, pComment, comment_size, level_and_flags, + user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len); +} + +mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +{ + MZ_FILE *pSrc_file = NULL; + mz_uint64 uncomp_size = 0; + MZ_TIME_T file_modified_time; + MZ_TIME_T *pFile_time = NULL; + mz_bool status; + + memset(&file_modified_time, 0, sizeof(file_modified_time)); + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO) + pFile_time = &file_modified_time; + if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED); +#endif + + pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); + if (!pSrc_file) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); + + MZ_FSEEK64(pSrc_file, 0, SEEK_END); + uncomp_size = MZ_FTELL64(pSrc_file); + MZ_FSEEK64(pSrc_file, 0, SEEK_SET); + + status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0); + + MZ_FCLOSE(pSrc_file); + + return status; +} +#endif /* #ifndef MINIZ_NO_STDIO */ + +static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, mz_uint32 ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start) +{ + /* + 64 should be enough for any new zip64 data */ + if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE); + + if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start)) + { + mz_uint8 new_ext_block[64]; + mz_uint8 *pDst = new_ext_block; + mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID); + mz_write_le16(pDst + sizeof(mz_uint16), 0); + pDst += sizeof(mz_uint16) * 2; + + if (pUncomp_size) + { + mz_write_le64(pDst, *pUncomp_size); + pDst += sizeof(mz_uint64); + } + + if (pComp_size) + { + mz_write_le64(pDst, *pComp_size); + pDst += sizeof(mz_uint64); + } + + if (pLocal_header_ofs) + { + mz_write_le64(pDst, *pLocal_header_ofs); + pDst += sizeof(mz_uint64); + } + + if (pDisk_start) + { + mz_write_le32(pDst, *pDisk_start); + pDst += sizeof(mz_uint32); + } + + mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2)); + + if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if ((pExt) && (ext_len)) + { + mz_uint32 extra_size_remaining = ext_len; + const mz_uint8 *pExtra_data = pExt; + + do + { + mz_uint32 field_id, field_data_size, field_total_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + field_total_size = field_data_size + sizeof(mz_uint16) * 2; + + if (field_total_size > extra_size_remaining) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + pExtra_data += field_total_size; + extra_size_remaining -= field_total_size; + } while (extra_size_remaining); + } + + return MZ_TRUE; +} + +/* TODO: This func is now pretty freakin complex due to zip64, split it up? */ +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index) +{ + mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size; + mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs; + mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + size_t orig_central_dir_size; + mz_zip_internal_state *pState; + void *pBuf; + const mz_uint8 *pSrc_central_header; + mz_zip_archive_file_stat src_file_stat; + mz_uint32 src_filename_len, src_comment_len, src_ext_len; + mz_uint32 local_header_filename_size, local_header_extra_len; + mz_uint64 local_header_comp_size, local_header_uncomp_size; + mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE; + + /* Sanity checks */ + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */ + if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + /* Get pointer to the source central dir header and crack it */ + if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index))) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS); + src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); + src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS); + src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len; + + /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */ + if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + if (!pState->m_zip64) + { + if (pZip->m_total_files == MZ_UINT16_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */ + if (pZip->m_total_files == MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + + if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL)) + return MZ_FALSE; + + cur_src_file_ofs = src_file_stat.m_local_header_ofs; + cur_dst_file_ofs = pZip->m_archive_size; + + /* Read the source archive's local dir header */ + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + /* Compute the total size we need to copy (filename+extra data+compressed data) */ + local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS); + local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS); + local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS); + src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size; + + /* Try to find a zip64 extended information field */ + if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX))) + { + mz_zip_array file_data_array; + const mz_uint8 *pExtra_data; + mz_uint32 extra_size_remaining = local_header_extra_len; + + mz_zip_array_init(&file_data_array, 1); + if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE)) + { + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len) + { + mz_zip_array_clear(pZip, &file_data_array); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + pExtra_data = (const mz_uint8 *)file_data_array.m_p; + + do + { + mz_uint32 field_id, field_data_size, field_total_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + { + mz_zip_array_clear(pZip, &file_data_array); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + field_total_size = field_data_size + sizeof(mz_uint16) * 2; + + if (field_total_size > extra_size_remaining) + { + mz_zip_array_clear(pZip, &file_data_array); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) + { + const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32); + + if (field_data_size < sizeof(mz_uint64) * 2) + { + mz_zip_array_clear(pZip, &file_data_array); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data); + local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */ + + found_zip64_ext_data_in_ldir = MZ_TRUE; + break; + } + + pExtra_data += field_total_size; + extra_size_remaining -= field_total_size; + } while (extra_size_remaining); + + mz_zip_array_clear(pZip, &file_data_array); + } + + if (!pState->m_zip64) + { + /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */ + /* We also check when the archive is finalized so this doesn't need to be perfect. */ + mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) + + pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64; + + if (approx_new_archive_size >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + } + + /* Write dest archive padding */ + if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) + return MZ_FALSE; + + cur_dst_file_ofs += num_alignment_padding_bytes; + + local_dir_header_ofs = cur_dst_file_ofs; + if (pZip->m_file_offset_alignment) + { + MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + + /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */ + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */ + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining))))) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + while (src_archive_bytes_remaining) + { + n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining); + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + cur_src_file_ofs += n; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + cur_dst_file_ofs += n; + + src_archive_bytes_remaining -= n; + } + + /* Now deal with the optional data descriptor */ + bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); + if (bit_flags & 8) + { + /* Copy data descriptor */ + if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir)) + { + /* src is zip64, dest must be zip64 */ + + /* name uint32_t's */ + /* id 1 (optional in zip64?) */ + /* crc 1 */ + /* comp_size 2 */ + /* uncomp_size 2 */ + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5); + } + else + { + /* src is NOT zip64 */ + mz_bool has_id; + + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID); + + if (pZip->m_pState->m_zip64) + { + /* dest is zip64, so upgrade the data descriptor */ + const mz_uint8 *pSrc_descriptor = (const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0); + const mz_uint32 src_crc32 = MZ_READ_LE32(pSrc_descriptor); + const mz_uint64 src_comp_size = MZ_READ_LE32(pSrc_descriptor + sizeof(mz_uint32)); + const mz_uint64 src_uncomp_size = MZ_READ_LE32(pSrc_descriptor + 2*sizeof(mz_uint32)); + + mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID); + mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32); + mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size); + mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size); + + n = sizeof(mz_uint32) * 6; + } + else + { + /* dest is NOT zip64, just copy it as-is */ + n = sizeof(mz_uint32) * (has_id ? 4 : 3); + } + } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + + cur_src_file_ofs += n; + cur_dst_file_ofs += n; + } + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + + /* Finally, add the new central dir header */ + orig_central_dir_size = pState->m_central_dir.m_size; + + memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + + if (pState->m_zip64) + { + /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */ + const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len; + mz_zip_array new_ext_block; + + mz_zip_array_init(&new_ext_block, sizeof(mz_uint8)); + + MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX); + MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX); + MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX); + + if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL)) + { + mz_zip_array_clear(pZip, &new_ext_block); + return MZ_FALSE; + } + + MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size); + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + { + mz_zip_array_clear(pZip, &new_ext_block); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len)) + { + mz_zip_array_clear(pZip, &new_ext_block); + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size)) + { + mz_zip_array_clear(pZip, &new_ext_block); + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len)) + { + mz_zip_array_clear(pZip, &new_ext_block); + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + mz_zip_array_clear(pZip, &new_ext_block); + } + else + { + /* sanity checks */ + if (cur_dst_file_ofs > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + if (local_dir_header_ofs >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); + + MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + } + + /* This shouldn't trigger unless we screwed up during the initial sanity checks */ + if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) + { + /* TODO: Support central dirs >= 32-bits in size */ + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + } + + n = (mz_uint32)orig_central_dir_size; + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + } + + pZip->m_total_files++; + pZip->m_archive_size = cur_dst_file_ofs; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState; + mz_uint64 central_dir_ofs, central_dir_size; + mz_uint8 hdr[256]; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + pState = pZip->m_pState; + + if (pState->m_zip64) + { + if ((mz_uint64)pState->m_central_dir.m_size >= MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + else + { + if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + } + + central_dir_ofs = 0; + central_dir_size = 0; + if (pZip->m_total_files) + { + /* Write central directory */ + central_dir_ofs = pZip->m_archive_size; + central_dir_size = pState->m_central_dir.m_size; + pZip->m_central_directory_file_ofs = central_dir_ofs; + if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + pZip->m_archive_size += central_dir_size; + } + + if (pState->m_zip64) + { + /* Write zip64 end of central directory header */ + mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size; + + MZ_CLEAR_ARR(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - sizeof(mz_uint32) - sizeof(mz_uint64)); + MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */ + MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs); + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE; + + /* Write zip64 end of central directory locator */ + MZ_CLEAR_ARR(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG); + MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr); + MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1); + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + + pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE; + } + + /* Write end of central directory record */ + MZ_CLEAR_ARR(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files)); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files)); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size)); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs)); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + +#ifndef MINIZ_NO_STDIO + if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); +#endif /* #ifndef MINIZ_NO_STDIO */ + + pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE; + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; + return MZ_TRUE; +} + +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize) +{ + if ((!ppBuf) || (!pSize)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + *ppBuf = NULL; + *pSize = 0; + + if ((!pZip) || (!pZip->m_pState)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (pZip->m_pWrite != mz_zip_heap_write_func) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + if (!mz_zip_writer_finalize_archive(pZip)) + return MZ_FALSE; + + *ppBuf = pZip->m_pState->m_pMem; + *pSize = pZip->m_pState->m_mem_size; + pZip->m_pState->m_pMem = NULL; + pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_end(mz_zip_archive *pZip) +{ + return mz_zip_writer_end_internal(pZip, MZ_TRUE); +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +{ + return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL); +} + +mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr) +{ + mz_bool status, created_new_archive = MZ_FALSE; + mz_zip_archive zip_archive; + struct MZ_FILE_STAT_STRUCT file_stat; + mz_zip_error actual_err = MZ_ZIP_NO_ERROR; + + mz_zip_zero_struct(&zip_archive); + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + + if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_PARAMETER; + return MZ_FALSE; + } + + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_FILENAME; + return MZ_FALSE; + } + + /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */ + /* So be sure to compile with _LARGEFILE64_SOURCE 1 */ + if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) + { + /* Create a new archive. */ + if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags)) + { + if (pErr) + *pErr = zip_archive.m_last_error; + return MZ_FALSE; + } + + created_new_archive = MZ_TRUE; + } + else + { + /* Append to an existing archive. */ + if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) + { + if (pErr) + *pErr = zip_archive.m_last_error; + return MZ_FALSE; + } + + if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags)) + { + if (pErr) + *pErr = zip_archive.m_last_error; + + mz_zip_reader_end_internal(&zip_archive, MZ_FALSE); + + return MZ_FALSE; + } + } + + status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); + actual_err = zip_archive.m_last_error; + + /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */ + if (!mz_zip_writer_finalize_archive(&zip_archive)) + { + if (!actual_err) + actual_err = zip_archive.m_last_error; + + status = MZ_FALSE; + } + + if (!mz_zip_writer_end_internal(&zip_archive, status)) + { + if (!actual_err) + actual_err = zip_archive.m_last_error; + + status = MZ_FALSE; + } + + if ((!status) && (created_new_archive)) + { + /* It's a new archive and something went wrong, so just delete it. */ + int ignoredStatus = MZ_DELETE_FILE(pZip_filename); + (void)ignoredStatus; + } + + if (pErr) + *pErr = actual_err; + + return status; +} + +void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr) +{ + mz_uint32 file_index; + mz_zip_archive zip_archive; + void *p = NULL; + + if (pSize) + *pSize = 0; + + if ((!pZip_filename) || (!pArchive_name)) + { + if (pErr) + *pErr = MZ_ZIP_INVALID_PARAMETER; + + return NULL; + } + + mz_zip_zero_struct(&zip_archive); + if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) + { + if (pErr) + *pErr = zip_archive.m_last_error; + + return NULL; + } + + if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index)) + { + p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); + } + + mz_zip_reader_end_internal(&zip_archive, p != NULL); + + if (pErr) + *pErr = zip_archive.m_last_error; + + return p; +} + +void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) +{ + return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL); +} + +#endif /* #ifndef MINIZ_NO_STDIO */ + +#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */ + +/* ------------------- Misc utils */ + +mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip) +{ + return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID; +} + +mz_zip_type mz_zip_get_type(mz_zip_archive *pZip) +{ + return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID; +} + +mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num) +{ + mz_zip_error prev_err; + + if (!pZip) + return MZ_ZIP_INVALID_PARAMETER; + + prev_err = pZip->m_last_error; + + pZip->m_last_error = err_num; + return prev_err; +} + +mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip) +{ + if (!pZip) + return MZ_ZIP_INVALID_PARAMETER; + + return pZip->m_last_error; +} + +mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip) +{ + return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR); +} + +mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip) +{ + mz_zip_error prev_err; + + if (!pZip) + return MZ_ZIP_INVALID_PARAMETER; + + prev_err = pZip->m_last_error; + + pZip->m_last_error = MZ_ZIP_NO_ERROR; + return prev_err; +} + +const char *mz_zip_get_error_string(mz_zip_error mz_err) +{ + switch (mz_err) + { + case MZ_ZIP_NO_ERROR: + return "no error"; + case MZ_ZIP_UNDEFINED_ERROR: + return "undefined error"; + case MZ_ZIP_TOO_MANY_FILES: + return "too many files"; + case MZ_ZIP_FILE_TOO_LARGE: + return "file too large"; + case MZ_ZIP_UNSUPPORTED_METHOD: + return "unsupported method"; + case MZ_ZIP_UNSUPPORTED_ENCRYPTION: + return "unsupported encryption"; + case MZ_ZIP_UNSUPPORTED_FEATURE: + return "unsupported feature"; + case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR: + return "failed finding central directory"; + case MZ_ZIP_NOT_AN_ARCHIVE: + return "not a ZIP archive"; + case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED: + return "invalid header or archive is corrupted"; + case MZ_ZIP_UNSUPPORTED_MULTIDISK: + return "unsupported multidisk archive"; + case MZ_ZIP_DECOMPRESSION_FAILED: + return "decompression failed or archive is corrupted"; + case MZ_ZIP_COMPRESSION_FAILED: + return "compression failed"; + case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE: + return "unexpected decompressed size"; + case MZ_ZIP_CRC_CHECK_FAILED: + return "CRC-32 check failed"; + case MZ_ZIP_UNSUPPORTED_CDIR_SIZE: + return "unsupported central directory size"; + case MZ_ZIP_ALLOC_FAILED: + return "allocation failed"; + case MZ_ZIP_FILE_OPEN_FAILED: + return "file open failed"; + case MZ_ZIP_FILE_CREATE_FAILED: + return "file create failed"; + case MZ_ZIP_FILE_WRITE_FAILED: + return "file write failed"; + case MZ_ZIP_FILE_READ_FAILED: + return "file read failed"; + case MZ_ZIP_FILE_CLOSE_FAILED: + return "file close failed"; + case MZ_ZIP_FILE_SEEK_FAILED: + return "file seek failed"; + case MZ_ZIP_FILE_STAT_FAILED: + return "file stat failed"; + case MZ_ZIP_INVALID_PARAMETER: + return "invalid parameter"; + case MZ_ZIP_INVALID_FILENAME: + return "invalid filename"; + case MZ_ZIP_BUF_TOO_SMALL: + return "buffer too small"; + case MZ_ZIP_INTERNAL_ERROR: + return "internal error"; + case MZ_ZIP_FILE_NOT_FOUND: + return "file not found"; + case MZ_ZIP_ARCHIVE_TOO_LARGE: + return "archive is too large"; + case MZ_ZIP_VALIDATION_FAILED: + return "validation failed"; + case MZ_ZIP_WRITE_CALLBACK_FAILED: + return "write callback failed"; + case MZ_ZIP_TOTAL_ERRORS: + return "total errors"; + default: + break; + } + + return "unknown error"; +} + +/* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */ +mz_bool mz_zip_is_zip64(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState)) + return MZ_FALSE; + + return pZip->m_pState->m_zip64; +} + +size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState)) + return 0; + + return pZip->m_pState->m_central_dir.m_size; +} + +mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) +{ + return pZip ? pZip->m_total_files : 0; +} + +mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip) +{ + if (!pZip) + return 0; + return pZip->m_archive_size; +} + +mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState)) + return 0; + return pZip->m_pState->m_file_archive_start_ofs; +} + +MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState)) + return 0; + return pZip->m_pState->m_pFile; +} + +size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + + return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n); +} + +mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) +{ + mz_uint n; + const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); + if (!p) + { + if (filename_buf_size) + pFilename[0] = '\0'; + mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); + return 0; + } + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_buf_size) + { + n = MZ_MIN(n, filename_buf_size - 1); + memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pFilename[n] = '\0'; + } + return n + 1; +} + +mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) +{ + return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL); +} + +mz_bool mz_zip_end(mz_zip_archive *pZip) +{ + if (!pZip) + return MZ_FALSE; + + if (pZip->m_zip_mode == MZ_ZIP_MODE_READING) + return mz_zip_reader_end(pZip); +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)) + return mz_zip_writer_end(pZip); +#endif + + return MZ_FALSE; +} + +#ifdef __cplusplus +} +#endif + +#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/ diff --git a/libraries/miniz/miniz.h b/libraries/miniz/miniz.h new file mode 100644 index 0000000000..9fcfffcc8c --- /dev/null +++ b/libraries/miniz/miniz.h @@ -0,0 +1,1422 @@ +#ifndef MINIZ_EXPORT +#define MINIZ_EXPORT +#endif +/* miniz.c 3.0.0 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing + See "unlicense" statement at the end of this file. + Rich Geldreich , last updated Oct. 13, 2013 + Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt + + Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define + MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros). + + * Low-level Deflate/Inflate implementation notes: + + Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or + greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses + approximately as well as zlib. + + Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function + coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory + block large enough to hold the entire file. + + The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. + + * zlib-style API notes: + + miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in + zlib replacement in many apps: + The z_stream struct, optional memory allocation callbacks + deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound + inflateInit/inflateInit2/inflate/inflateReset/inflateEnd + compress, compress2, compressBound, uncompress + CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. + Supports raw deflate streams or standard zlib streams with adler-32 checking. + + Limitations: + The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries. + I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but + there are no guarantees that miniz.c pulls this off perfectly. + + * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by + Alex Evans. Supports 1-4 bytes/pixel images. + + * ZIP archive API notes: + + The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to + get the job done with minimal fuss. There are simple API's to retrieve file information, read files from + existing archives, create new archives, append new files to existing archives, or clone archive data from + one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h), + or you can specify custom file read/write callbacks. + + - Archive reading: Just call this function to read a single file from a disk archive: + + void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, + size_t *pSize, mz_uint zip_flags); + + For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central + directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files. + + - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file: + + int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); + + The locate operation can optionally check file comments too, which (as one example) can be used to identify + multiple versions of the same file in an archive. This function uses a simple linear search through the central + directory, so it's not very fast. + + Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and + retrieve detailed info on each file by calling mz_zip_reader_file_stat(). + + - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data + to disk and builds an exact image of the central directory in memory. The central directory image is written + all at once at the end of the archive file when the archive is finalized. + + The archive writer can optionally align each file's local header and file data to any power of 2 alignment, + which can be useful when the archive will be read from optical media. Also, the writer supports placing + arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still + readable by any ZIP tool. + + - Archive appending: The simple way to add a single file to an archive is to call this function: + + mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, + const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + + The archive will be created if it doesn't already exist, otherwise it'll be appended to. + Note the appending is done in-place and is not an atomic operation, so if something goes wrong + during the operation it's possible the archive could be left without a central directory (although the local + file headers and file data will be fine, so the archive will be recoverable). + + For more complex archive modification scenarios: + 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to + preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the + compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and + you're done. This is safe but requires a bunch of temporary disk space or heap memory. + + 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(), + append new files as needed, then finalize the archive which will write an updated central directory to the + original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a + possibility that the archive's central directory could be lost with this method if anything goes wrong, though. + + - ZIP archive support limitations: + No spanning support. Extraction functions can only handle unencrypted, stored or deflated files. + Requires streams capable of seeking. + + * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the + below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it. + + * Important: For best perf. be sure to customize the below macros for your target platform: + #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 + #define MINIZ_LITTLE_ENDIAN 1 + #define MINIZ_HAS_64BIT_REGISTERS 1 + + * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz + uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files + (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes). +*/ +#pragma once + + + +/* Defines to completely disable specific portions of miniz.c: + If all macros here are defined the only functionality remaining will be CRC-32 and adler-32. */ + +/* Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. */ +/*#define MINIZ_NO_STDIO */ + +/* If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or */ +/* get/set file times, and the C run-time funcs that get/set times won't be called. */ +/* The current downside is the times written to your archives will be from 1979. */ +/*#define MINIZ_NO_TIME */ + +/* Define MINIZ_NO_DEFLATE_APIS to disable all compression API's. */ +/*#define MINIZ_NO_DEFLATE_APIS */ + +/* Define MINIZ_NO_INFLATE_APIS to disable all decompression API's. */ +/*#define MINIZ_NO_INFLATE_APIS */ + +/* Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. */ +/*#define MINIZ_NO_ARCHIVE_APIS */ + +/* Define MINIZ_NO_ARCHIVE_WRITING_APIS to disable all writing related ZIP archive API's. */ +/*#define MINIZ_NO_ARCHIVE_WRITING_APIS */ + +/* Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. */ +/*#define MINIZ_NO_ZLIB_APIS */ + +/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. */ +/*#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES */ + +/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. + Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc + callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user + functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. */ +/*#define MINIZ_NO_MALLOC */ + +#ifdef MINIZ_NO_INFLATE_APIS +#define MINIZ_NO_ARCHIVE_APIS +#endif + +#ifdef MINIZ_NO_DEFLATE_APIS +#define MINIZ_NO_ARCHIVE_WRITING_APIS +#endif + +#if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) +/* TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux */ +#define MINIZ_NO_TIME +#endif + +#include + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) +#include +#endif + +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) +/* MINIZ_X86_OR_X64_CPU is only used to help set the below macros. */ +#define MINIZ_X86_OR_X64_CPU 1 +#else +#define MINIZ_X86_OR_X64_CPU 0 +#endif + +/* Set MINIZ_LITTLE_ENDIAN only if not set */ +#if !defined(MINIZ_LITTLE_ENDIAN) +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) + +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +/* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */ +#define MINIZ_LITTLE_ENDIAN 1 +#else +#define MINIZ_LITTLE_ENDIAN 0 +#endif + +#else + +#if MINIZ_X86_OR_X64_CPU +#define MINIZ_LITTLE_ENDIAN 1 +#else +#define MINIZ_LITTLE_ENDIAN 0 +#endif + +#endif +#endif + +/* Using unaligned loads and stores causes errors when using UBSan */ +#if defined(__has_feature) +#if __has_feature(undefined_behavior_sanitizer) +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 +#endif +#endif + +/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */ +#if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES) +#if MINIZ_X86_OR_X64_CPU +/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */ +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 +#define MINIZ_UNALIGNED_USE_MEMCPY +#else +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 +#endif +#endif + +#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) +/* Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). */ +#define MINIZ_HAS_64BIT_REGISTERS 1 +#else +#define MINIZ_HAS_64BIT_REGISTERS 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------- zlib-style API Definitions. */ + +/* For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! */ +typedef unsigned long mz_ulong; + +/* mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. */ +MINIZ_EXPORT void mz_free(void *p); + +#define MZ_ADLER32_INIT (1) +/* mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. */ +MINIZ_EXPORT mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); + +#define MZ_CRC32_INIT (0) +/* mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. */ +MINIZ_EXPORT mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); + +/* Compression strategies. */ +enum +{ + MZ_DEFAULT_STRATEGY = 0, + MZ_FILTERED = 1, + MZ_HUFFMAN_ONLY = 2, + MZ_RLE = 3, + MZ_FIXED = 4 +}; + +/* Method */ +#define MZ_DEFLATED 8 + +/* Heap allocation callbacks. +Note that mz_alloc_func parameter types purposely differ from zlib's: items/size is size_t, not unsigned long. */ +typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); +typedef void (*mz_free_func)(void *opaque, void *address); +typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); + +/* Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. */ +enum +{ + MZ_NO_COMPRESSION = 0, + MZ_BEST_SPEED = 1, + MZ_BEST_COMPRESSION = 9, + MZ_UBER_COMPRESSION = 10, + MZ_DEFAULT_LEVEL = 6, + MZ_DEFAULT_COMPRESSION = -1 +}; + +#define MZ_VERSION "11.0.2" +#define MZ_VERNUM 0xB002 +#define MZ_VER_MAJOR 11 +#define MZ_VER_MINOR 2 +#define MZ_VER_REVISION 0 +#define MZ_VER_SUBREVISION 0 + +#ifndef MINIZ_NO_ZLIB_APIS + +/* Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). */ +enum +{ + MZ_NO_FLUSH = 0, + MZ_PARTIAL_FLUSH = 1, + MZ_SYNC_FLUSH = 2, + MZ_FULL_FLUSH = 3, + MZ_FINISH = 4, + MZ_BLOCK = 5 +}; + +/* Return status codes. MZ_PARAM_ERROR is non-standard. */ +enum +{ + MZ_OK = 0, + MZ_STREAM_END = 1, + MZ_NEED_DICT = 2, + MZ_ERRNO = -1, + MZ_STREAM_ERROR = -2, + MZ_DATA_ERROR = -3, + MZ_MEM_ERROR = -4, + MZ_BUF_ERROR = -5, + MZ_VERSION_ERROR = -6, + MZ_PARAM_ERROR = -10000 +}; + +/* Window bits */ +#define MZ_DEFAULT_WINDOW_BITS 15 + +struct mz_internal_state; + +/* Compression/decompression stream struct. */ +typedef struct mz_stream_s +{ + const unsigned char *next_in; /* pointer to next byte to read */ + unsigned int avail_in; /* number of bytes available at next_in */ + mz_ulong total_in; /* total number of bytes consumed so far */ + + unsigned char *next_out; /* pointer to next byte to write */ + unsigned int avail_out; /* number of bytes that can be written to next_out */ + mz_ulong total_out; /* total number of bytes produced so far */ + + char *msg; /* error msg (unused) */ + struct mz_internal_state *state; /* internal state, allocated by zalloc/zfree */ + + mz_alloc_func zalloc; /* optional heap allocation function (defaults to malloc) */ + mz_free_func zfree; /* optional heap free function (defaults to free) */ + void *opaque; /* heap alloc function user pointer */ + + int data_type; /* data_type (unused) */ + mz_ulong adler; /* adler32 of the source or uncompressed data */ + mz_ulong reserved; /* not used */ +} mz_stream; + +typedef mz_stream *mz_streamp; + +/* Returns the version string of miniz.c. */ +MINIZ_EXPORT const char *mz_version(void); + +#ifndef MINIZ_NO_DEFLATE_APIS + +/* mz_deflateInit() initializes a compressor with default options: */ +/* Parameters: */ +/* pStream must point to an initialized mz_stream struct. */ +/* level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. */ +/* level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. */ +/* (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) */ +/* Return values: */ +/* MZ_OK on success. */ +/* MZ_STREAM_ERROR if the stream is bogus. */ +/* MZ_PARAM_ERROR if the input parameters are bogus. */ +/* MZ_MEM_ERROR on out of memory. */ +MINIZ_EXPORT int mz_deflateInit(mz_streamp pStream, int level); + +/* mz_deflateInit2() is like mz_deflate(), except with more control: */ +/* Additional parameters: */ +/* method must be MZ_DEFLATED */ +/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) */ +/* mem_level must be between [1, 9] (it's checked but ignored by miniz.c) */ +MINIZ_EXPORT int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); + +/* Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). */ +MINIZ_EXPORT int mz_deflateReset(mz_streamp pStream); + +/* mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. */ +/* Parameters: */ +/* pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. */ +/* flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. */ +/* Return values: */ +/* MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). */ +/* MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. */ +/* MZ_STREAM_ERROR if the stream is bogus. */ +/* MZ_PARAM_ERROR if one of the parameters is invalid. */ +/* MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) */ +MINIZ_EXPORT int mz_deflate(mz_streamp pStream, int flush); + +/* mz_deflateEnd() deinitializes a compressor: */ +/* Return values: */ +/* MZ_OK on success. */ +/* MZ_STREAM_ERROR if the stream is bogus. */ +MINIZ_EXPORT int mz_deflateEnd(mz_streamp pStream); + +/* mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. */ +MINIZ_EXPORT mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); + +/* Single-call compression functions mz_compress() and mz_compress2(): */ +/* Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. */ +MINIZ_EXPORT int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +MINIZ_EXPORT int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); + +/* mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). */ +MINIZ_EXPORT mz_ulong mz_compressBound(mz_ulong source_len); + +#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ + +#ifndef MINIZ_NO_INFLATE_APIS + +/* Initializes a decompressor. */ +MINIZ_EXPORT int mz_inflateInit(mz_streamp pStream); + +/* mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: */ +/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). */ +MINIZ_EXPORT int mz_inflateInit2(mz_streamp pStream, int window_bits); + +/* Quickly resets a compressor without having to reallocate anything. Same as calling mz_inflateEnd() followed by mz_inflateInit()/mz_inflateInit2(). */ +MINIZ_EXPORT int mz_inflateReset(mz_streamp pStream); + +/* Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. */ +/* Parameters: */ +/* pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. */ +/* flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. */ +/* On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). */ +/* MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. */ +/* Return values: */ +/* MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. */ +/* MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. */ +/* MZ_STREAM_ERROR if the stream is bogus. */ +/* MZ_DATA_ERROR if the deflate stream is invalid. */ +/* MZ_PARAM_ERROR if one of the parameters is invalid. */ +/* MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again */ +/* with more input data, or with more room in the output buffer (except when using single call decompression, described above). */ +MINIZ_EXPORT int mz_inflate(mz_streamp pStream, int flush); + +/* Deinitializes a decompressor. */ +MINIZ_EXPORT int mz_inflateEnd(mz_streamp pStream); + +/* Single-call decompression. */ +/* Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. */ +MINIZ_EXPORT int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +MINIZ_EXPORT int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len); +#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ + +/* Returns a string description of the specified error code, or NULL if the error code is invalid. */ +MINIZ_EXPORT const char *mz_error(int err); + +/* Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. */ +/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. */ +#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES +typedef unsigned char Byte; +typedef unsigned int uInt; +typedef mz_ulong uLong; +typedef Byte Bytef; +typedef uInt uIntf; +typedef char charf; +typedef int intf; +typedef void *voidpf; +typedef uLong uLongf; +typedef void *voidp; +typedef void *const voidpc; +#define Z_NULL 0 +#define Z_NO_FLUSH MZ_NO_FLUSH +#define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH +#define Z_SYNC_FLUSH MZ_SYNC_FLUSH +#define Z_FULL_FLUSH MZ_FULL_FLUSH +#define Z_FINISH MZ_FINISH +#define Z_BLOCK MZ_BLOCK +#define Z_OK MZ_OK +#define Z_STREAM_END MZ_STREAM_END +#define Z_NEED_DICT MZ_NEED_DICT +#define Z_ERRNO MZ_ERRNO +#define Z_STREAM_ERROR MZ_STREAM_ERROR +#define Z_DATA_ERROR MZ_DATA_ERROR +#define Z_MEM_ERROR MZ_MEM_ERROR +#define Z_BUF_ERROR MZ_BUF_ERROR +#define Z_VERSION_ERROR MZ_VERSION_ERROR +#define Z_PARAM_ERROR MZ_PARAM_ERROR +#define Z_NO_COMPRESSION MZ_NO_COMPRESSION +#define Z_BEST_SPEED MZ_BEST_SPEED +#define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION +#define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION +#define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY +#define Z_FILTERED MZ_FILTERED +#define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY +#define Z_RLE MZ_RLE +#define Z_FIXED MZ_FIXED +#define Z_DEFLATED MZ_DEFLATED +#define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS +#define alloc_func mz_alloc_func +#define free_func mz_free_func +#define internal_state mz_internal_state +#define z_stream mz_stream + +#ifndef MINIZ_NO_DEFLATE_APIS +#define deflateInit mz_deflateInit +#define deflateInit2 mz_deflateInit2 +#define deflateReset mz_deflateReset +#define deflate mz_deflate +#define deflateEnd mz_deflateEnd +#define deflateBound mz_deflateBound +#define compress mz_compress +#define compress2 mz_compress2 +#define compressBound mz_compressBound +#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ + +#ifndef MINIZ_NO_INFLATE_APIS +#define inflateInit mz_inflateInit +#define inflateInit2 mz_inflateInit2 +#define inflateReset mz_inflateReset +#define inflate mz_inflate +#define inflateEnd mz_inflateEnd +#define uncompress mz_uncompress +#define uncompress2 mz_uncompress2 +#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ + +#define crc32 mz_crc32 +#define adler32 mz_adler32 +#define MAX_WBITS 15 +#define MAX_MEM_LEVEL 9 +#define zError mz_error +#define ZLIB_VERSION MZ_VERSION +#define ZLIB_VERNUM MZ_VERNUM +#define ZLIB_VER_MAJOR MZ_VER_MAJOR +#define ZLIB_VER_MINOR MZ_VER_MINOR +#define ZLIB_VER_REVISION MZ_VER_REVISION +#define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION +#define zlibVersion mz_version +#define zlib_version mz_version() +#endif /* #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES */ + +#endif /* MINIZ_NO_ZLIB_APIS */ + +#ifdef __cplusplus +} +#endif + + + + + +#pragma once +#include +#include +#include +#include + + + +/* ------------------- Types and macros */ +typedef unsigned char mz_uint8; +typedef signed short mz_int16; +typedef unsigned short mz_uint16; +typedef unsigned int mz_uint32; +typedef unsigned int mz_uint; +typedef int64_t mz_int64; +typedef uint64_t mz_uint64; +typedef int mz_bool; + +#define MZ_FALSE (0) +#define MZ_TRUE (1) + +/* Works around MSVC's spammy "warning C4127: conditional expression is constant" message. */ +#ifdef _MSC_VER +#define MZ_MACRO_END while (0, 0) +#else +#define MZ_MACRO_END while (0) +#endif + +#ifdef MINIZ_NO_STDIO +#define MZ_FILE void * +#else +#include +#define MZ_FILE FILE +#endif /* #ifdef MINIZ_NO_STDIO */ + +#ifdef MINIZ_NO_TIME +typedef struct mz_dummy_time_t_tag +{ + mz_uint32 m_dummy1; + mz_uint32 m_dummy2; +} mz_dummy_time_t; +#define MZ_TIME_T mz_dummy_time_t +#else +#define MZ_TIME_T time_t +#endif + +#define MZ_ASSERT(x) assert(x) + +#ifdef MINIZ_NO_MALLOC +#define MZ_MALLOC(x) NULL +#define MZ_FREE(x) (void)x, ((void)0) +#define MZ_REALLOC(p, x) NULL +#else +#define MZ_MALLOC(x) malloc(x) +#define MZ_FREE(x) free(x) +#define MZ_REALLOC(p, x) realloc(p, x) +#endif + +#define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) +#define MZ_CLEAR_ARR(obj) memset((obj), 0, sizeof(obj)) +#define MZ_CLEAR_PTR(obj) memset((obj), 0, sizeof(*obj)) + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN +#define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) +#define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) +#else +#define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) +#define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) +#endif + +#define MZ_READ_LE64(p) (((mz_uint64)MZ_READ_LE32(p)) | (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) << 32U)) + +#ifdef _MSC_VER +#define MZ_FORCEINLINE __forceinline +#elif defined(__GNUC__) +#define MZ_FORCEINLINE __inline__ __attribute__((__always_inline__)) +#else +#define MZ_FORCEINLINE inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern MINIZ_EXPORT void *miniz_def_alloc_func(void *opaque, size_t items, size_t size); +extern MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address); +extern MINIZ_EXPORT void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size); + +#define MZ_UINT16_MAX (0xFFFFU) +#define MZ_UINT32_MAX (0xFFFFFFFFU) + +#ifdef __cplusplus +} +#endif + #pragma once + + +#ifndef MINIZ_NO_DEFLATE_APIS + +#ifdef __cplusplus +extern "C" { +#endif +/* ------------------- Low-level Compression API Definitions */ + +/* Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). */ +#define TDEFL_LESS_MEMORY 0 + +/* tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): */ +/* TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). */ +enum +{ + TDEFL_HUFFMAN_ONLY = 0, + TDEFL_DEFAULT_MAX_PROBES = 128, + TDEFL_MAX_PROBES_MASK = 0xFFF +}; + +/* TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. */ +/* TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). */ +/* TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. */ +/* TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). */ +/* TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) */ +/* TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. */ +/* TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. */ +/* TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. */ +/* The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). */ +enum +{ + TDEFL_WRITE_ZLIB_HEADER = 0x01000, + TDEFL_COMPUTE_ADLER32 = 0x02000, + TDEFL_GREEDY_PARSING_FLAG = 0x04000, + TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, + TDEFL_RLE_MATCHES = 0x10000, + TDEFL_FILTER_MATCHES = 0x20000, + TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, + TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 +}; + +/* High level compression functions: */ +/* tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). */ +/* On entry: */ +/* pSrc_buf, src_buf_len: Pointer and size of source block to compress. */ +/* flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. */ +/* On return: */ +/* Function returns a pointer to the compressed data, or NULL on failure. */ +/* *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. */ +/* The caller must free() the returned block when it's no longer needed. */ +MINIZ_EXPORT void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +/* tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. */ +/* Returns 0 on failure. */ +MINIZ_EXPORT size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +/* Compresses an image to a compressed PNG file in memory. */ +/* On entry: */ +/* pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. */ +/* The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. */ +/* level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL */ +/* If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). */ +/* On return: */ +/* Function returns a pointer to the compressed data, or NULL on failure. */ +/* *pLen_out will be set to the size of the PNG image file. */ +/* The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. */ +MINIZ_EXPORT void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip); +MINIZ_EXPORT void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); + +/* Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. */ +typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser); + +/* tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. */ +MINIZ_EXPORT mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +enum +{ + TDEFL_MAX_HUFF_TABLES = 3, + TDEFL_MAX_HUFF_SYMBOLS_0 = 288, + TDEFL_MAX_HUFF_SYMBOLS_1 = 32, + TDEFL_MAX_HUFF_SYMBOLS_2 = 19, + TDEFL_LZ_DICT_SIZE = 32768, + TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, + TDEFL_MIN_MATCH_LEN = 3, + TDEFL_MAX_MATCH_LEN = 258 +}; + +/* TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). */ +#if TDEFL_LESS_MEMORY +enum +{ + TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, + TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, + TDEFL_MAX_HUFF_SYMBOLS = 288, + TDEFL_LZ_HASH_BITS = 12, + TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, + TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, + TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS +}; +#else +enum +{ + TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, + TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, + TDEFL_MAX_HUFF_SYMBOLS = 288, + TDEFL_LZ_HASH_BITS = 15, + TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, + TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, + TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS +}; +#endif + +/* The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. */ +typedef enum { + TDEFL_STATUS_BAD_PARAM = -2, + TDEFL_STATUS_PUT_BUF_FAILED = -1, + TDEFL_STATUS_OKAY = 0, + TDEFL_STATUS_DONE = 1 +} tdefl_status; + +/* Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums */ +typedef enum { + TDEFL_NO_FLUSH = 0, + TDEFL_SYNC_FLUSH = 2, + TDEFL_FULL_FLUSH = 3, + TDEFL_FINISH = 4 +} tdefl_flush; + +/* tdefl's compression state structure. */ +typedef struct +{ + tdefl_put_buf_func_ptr m_pPut_buf_func; + void *m_pPut_buf_user; + mz_uint m_flags, m_max_probes[2]; + int m_greedy_parsing; + mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; + mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; + mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; + mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; + tdefl_status m_prev_return_status; + const void *m_pIn_buf; + void *m_pOut_buf; + size_t *m_pIn_buf_size, *m_pOut_buf_size; + tdefl_flush m_flush; + const mz_uint8 *m_pSrc; + size_t m_src_buf_left, m_out_buf_ofs; + mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; + mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; + mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; + mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; + mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; +} tdefl_compressor; + +/* Initializes the compressor. */ +/* There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. */ +/* pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. */ +/* If pBut_buf_func is NULL the user should always call the tdefl_compress() API. */ +/* flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) */ +MINIZ_EXPORT tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +/* Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. */ +MINIZ_EXPORT tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); + +/* tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. */ +/* tdefl_compress_buffer() always consumes the entire input buffer. */ +MINIZ_EXPORT tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); + +MINIZ_EXPORT tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); +MINIZ_EXPORT mz_uint32 tdefl_get_adler32(tdefl_compressor *d); + +/* Create tdefl_compress() flags given zlib-style compression parameters. */ +/* level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) */ +/* window_bits may be -15 (raw deflate) or 15 (zlib) */ +/* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED */ +MINIZ_EXPORT mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); + +#ifndef MINIZ_NO_MALLOC +/* Allocate the tdefl_compressor structure in C so that */ +/* non-C language bindings to tdefl_ API don't need to worry about */ +/* structure size and allocation mechanism. */ +MINIZ_EXPORT tdefl_compressor *tdefl_compressor_alloc(void); +MINIZ_EXPORT void tdefl_compressor_free(tdefl_compressor *pComp); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ + #pragma once + +/* ------------------- Low-level Decompression API Definitions */ + +#ifndef MINIZ_NO_INFLATE_APIS + +#ifdef __cplusplus +extern "C" { +#endif +/* Decompression flags used by tinfl_decompress(). */ +/* TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. */ +/* TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. */ +/* TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). */ +/* TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. */ +enum +{ + TINFL_FLAG_PARSE_ZLIB_HEADER = 1, + TINFL_FLAG_HAS_MORE_INPUT = 2, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, + TINFL_FLAG_COMPUTE_ADLER32 = 8 +}; + +/* High level decompression functions: */ +/* tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). */ +/* On entry: */ +/* pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. */ +/* On return: */ +/* Function returns a pointer to the decompressed data, or NULL on failure. */ +/* *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. */ +/* The caller must call mz_free() on the returned block when it's no longer needed. */ +MINIZ_EXPORT void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +/* tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. */ +/* Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. */ +#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) +MINIZ_EXPORT size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +/* tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. */ +/* Returns 1 on success or 0 on failure. */ +typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser); +MINIZ_EXPORT int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +struct tinfl_decompressor_tag; +typedef struct tinfl_decompressor_tag tinfl_decompressor; + +#ifndef MINIZ_NO_MALLOC +/* Allocate the tinfl_decompressor structure in C so that */ +/* non-C language bindings to tinfl_ API don't need to worry about */ +/* structure size and allocation mechanism. */ +MINIZ_EXPORT tinfl_decompressor *tinfl_decompressor_alloc(void); +MINIZ_EXPORT void tinfl_decompressor_free(tinfl_decompressor *pDecomp); +#endif + +/* Max size of LZ dictionary. */ +#define TINFL_LZ_DICT_SIZE 32768 + +/* Return status. */ +typedef enum { + /* This flags indicates the inflator needs 1 or more input bytes to make forward progress, but the caller is indicating that no more are available. The compressed data */ + /* is probably corrupted. If you call the inflator again with more bytes it'll try to continue processing the input but this is a BAD sign (either the data is corrupted or you called it incorrectly). */ + /* If you call it again with no input you'll just get TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS again. */ + TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS = -4, + + /* This flag indicates that one or more of the input parameters was obviously bogus. (You can try calling it again, but if you get this error the calling code is wrong.) */ + TINFL_STATUS_BAD_PARAM = -3, + + /* This flags indicate the inflator is finished but the adler32 check of the uncompressed data didn't match. If you call it again it'll return TINFL_STATUS_DONE. */ + TINFL_STATUS_ADLER32_MISMATCH = -2, + + /* This flags indicate the inflator has somehow failed (bad code, corrupted input, etc.). If you call it again without resetting via tinfl_init() it it'll just keep on returning the same status failure code. */ + TINFL_STATUS_FAILED = -1, + + /* Any status code less than TINFL_STATUS_DONE must indicate a failure. */ + + /* This flag indicates the inflator has returned every byte of uncompressed data that it can, has consumed every byte that it needed, has successfully reached the end of the deflate stream, and */ + /* if zlib headers and adler32 checking enabled that it has successfully checked the uncompressed data's adler32. If you call it again you'll just get TINFL_STATUS_DONE over and over again. */ + TINFL_STATUS_DONE = 0, + + /* This flag indicates the inflator MUST have more input data (even 1 byte) before it can make any more forward progress, or you need to clear the TINFL_FLAG_HAS_MORE_INPUT */ + /* flag on the next call if you don't have any more source data. If the source data was somehow corrupted it's also possible (but unlikely) for the inflator to keep on demanding input to */ + /* proceed, so be sure to properly set the TINFL_FLAG_HAS_MORE_INPUT flag. */ + TINFL_STATUS_NEEDS_MORE_INPUT = 1, + + /* This flag indicates the inflator definitely has 1 or more bytes of uncompressed data available, but it cannot write this data into the output buffer. */ + /* Note if the source compressed data was corrupted it's possible for the inflator to return a lot of uncompressed data to the caller. I've been assuming you know how much uncompressed data to expect */ + /* (either exact or worst case) and will stop calling the inflator and fail after receiving too much. In pure streaming scenarios where you have no idea how many bytes to expect this may not be possible */ + /* so I may need to add some code to address this. */ + TINFL_STATUS_HAS_MORE_OUTPUT = 2 +} tinfl_status; + +/* Initializes the decompressor to its initial state. */ +#define tinfl_init(r) \ + do \ + { \ + (r)->m_state = 0; \ + } \ + MZ_MACRO_END +#define tinfl_get_adler32(r) (r)->m_check_adler32 + +/* Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. */ +/* This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. */ +MINIZ_EXPORT tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); + +/* Internal/private bits follow. */ +enum +{ + TINFL_MAX_HUFF_TABLES = 3, + TINFL_MAX_HUFF_SYMBOLS_0 = 288, + TINFL_MAX_HUFF_SYMBOLS_1 = 32, + TINFL_MAX_HUFF_SYMBOLS_2 = 19, + TINFL_FAST_LOOKUP_BITS = 10, + TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS +}; + +#if MINIZ_HAS_64BIT_REGISTERS +#define TINFL_USE_64BIT_BITBUF 1 +#else +#define TINFL_USE_64BIT_BITBUF 0 +#endif + +#if TINFL_USE_64BIT_BITBUF +typedef mz_uint64 tinfl_bit_buf_t; +#define TINFL_BITBUF_SIZE (64) +#else +typedef mz_uint32 tinfl_bit_buf_t; +#define TINFL_BITBUF_SIZE (32) +#endif + +struct tinfl_decompressor_tag +{ + mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; + tinfl_bit_buf_t m_bit_buf; + size_t m_dist_from_out_buf_start; + mz_int16 m_look_up[TINFL_MAX_HUFF_TABLES][TINFL_FAST_LOOKUP_SIZE]; + mz_int16 m_tree_0[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; + mz_int16 m_tree_1[TINFL_MAX_HUFF_SYMBOLS_1 * 2]; + mz_int16 m_tree_2[TINFL_MAX_HUFF_SYMBOLS_2 * 2]; + mz_uint8 m_code_size_0[TINFL_MAX_HUFF_SYMBOLS_0]; + mz_uint8 m_code_size_1[TINFL_MAX_HUFF_SYMBOLS_1]; + mz_uint8 m_code_size_2[TINFL_MAX_HUFF_SYMBOLS_2]; + mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ + +#pragma once + + +/* ------------------- ZIP archive reading/writing */ + +#ifndef MINIZ_NO_ARCHIVE_APIS + +#ifdef __cplusplus +extern "C" { +#endif + +enum +{ + /* Note: These enums can be reduced as needed to save memory or stack space - they are pretty conservative. */ + MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024, + MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 512, + MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 512 +}; + +typedef struct +{ + /* Central directory file index. */ + mz_uint32 m_file_index; + + /* Byte offset of this entry in the archive's central directory. Note we currently only support up to UINT_MAX or less bytes in the central dir. */ + mz_uint64 m_central_dir_ofs; + + /* These fields are copied directly from the zip's central dir. */ + mz_uint16 m_version_made_by; + mz_uint16 m_version_needed; + mz_uint16 m_bit_flag; + mz_uint16 m_method; + + /* CRC-32 of uncompressed data. */ + mz_uint32 m_crc32; + + /* File's compressed size. */ + mz_uint64 m_comp_size; + + /* File's uncompressed size. Note, I've seen some old archives where directory entries had 512 bytes for their uncompressed sizes, but when you try to unpack them you actually get 0 bytes. */ + mz_uint64 m_uncomp_size; + + /* Zip internal and external file attributes. */ + mz_uint16 m_internal_attr; + mz_uint32 m_external_attr; + + /* Entry's local header file offset in bytes. */ + mz_uint64 m_local_header_ofs; + + /* Size of comment in bytes. */ + mz_uint32 m_comment_size; + + /* MZ_TRUE if the entry appears to be a directory. */ + mz_bool m_is_directory; + + /* MZ_TRUE if the entry uses encryption/strong encryption (which miniz_zip doesn't support) */ + mz_bool m_is_encrypted; + + /* MZ_TRUE if the file is not encrypted, a patch file, and if it uses a compression method we support. */ + mz_bool m_is_supported; + + /* Filename. If string ends in '/' it's a subdirectory entry. */ + /* Guaranteed to be zero terminated, may be truncated to fit. */ + char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; + + /* Comment field. */ + /* Guaranteed to be zero terminated, may be truncated to fit. */ + char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; + +#ifdef MINIZ_NO_TIME + MZ_TIME_T m_padding; +#else + MZ_TIME_T m_time; +#endif +} mz_zip_archive_file_stat; + +typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); +typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); +typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque); + +struct mz_zip_internal_state_tag; +typedef struct mz_zip_internal_state_tag mz_zip_internal_state; + +typedef enum { + MZ_ZIP_MODE_INVALID = 0, + MZ_ZIP_MODE_READING = 1, + MZ_ZIP_MODE_WRITING = 2, + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 +} mz_zip_mode; + +typedef enum { + MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, + MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, + MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, + MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800, + MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG = 0x1000, /* if enabled, mz_zip_reader_locate_file() will be called on each file as its validated to ensure the func finds the file in the central dir (intended for testing) */ + MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY = 0x2000, /* validate the local headers, but don't decompress the entire file and check the crc32 */ + MZ_ZIP_FLAG_WRITE_ZIP64 = 0x4000, /* always use the zip64 file format, instead of the original zip file format with automatic switch to zip64. Use as flags parameter with mz_zip_writer_init*_v2 */ + MZ_ZIP_FLAG_WRITE_ALLOW_READING = 0x8000, + MZ_ZIP_FLAG_ASCII_FILENAME = 0x10000, + /*After adding a compressed file, seek back + to local file header and set the correct sizes*/ + MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE = 0x20000 +} mz_zip_flags; + +typedef enum { + MZ_ZIP_TYPE_INVALID = 0, + MZ_ZIP_TYPE_USER, + MZ_ZIP_TYPE_MEMORY, + MZ_ZIP_TYPE_HEAP, + MZ_ZIP_TYPE_FILE, + MZ_ZIP_TYPE_CFILE, + MZ_ZIP_TOTAL_TYPES +} mz_zip_type; + +/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or modify this enum. */ +typedef enum { + MZ_ZIP_NO_ERROR = 0, + MZ_ZIP_UNDEFINED_ERROR, + MZ_ZIP_TOO_MANY_FILES, + MZ_ZIP_FILE_TOO_LARGE, + MZ_ZIP_UNSUPPORTED_METHOD, + MZ_ZIP_UNSUPPORTED_ENCRYPTION, + MZ_ZIP_UNSUPPORTED_FEATURE, + MZ_ZIP_FAILED_FINDING_CENTRAL_DIR, + MZ_ZIP_NOT_AN_ARCHIVE, + MZ_ZIP_INVALID_HEADER_OR_CORRUPTED, + MZ_ZIP_UNSUPPORTED_MULTIDISK, + MZ_ZIP_DECOMPRESSION_FAILED, + MZ_ZIP_COMPRESSION_FAILED, + MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE, + MZ_ZIP_CRC_CHECK_FAILED, + MZ_ZIP_UNSUPPORTED_CDIR_SIZE, + MZ_ZIP_ALLOC_FAILED, + MZ_ZIP_FILE_OPEN_FAILED, + MZ_ZIP_FILE_CREATE_FAILED, + MZ_ZIP_FILE_WRITE_FAILED, + MZ_ZIP_FILE_READ_FAILED, + MZ_ZIP_FILE_CLOSE_FAILED, + MZ_ZIP_FILE_SEEK_FAILED, + MZ_ZIP_FILE_STAT_FAILED, + MZ_ZIP_INVALID_PARAMETER, + MZ_ZIP_INVALID_FILENAME, + MZ_ZIP_BUF_TOO_SMALL, + MZ_ZIP_INTERNAL_ERROR, + MZ_ZIP_FILE_NOT_FOUND, + MZ_ZIP_ARCHIVE_TOO_LARGE, + MZ_ZIP_VALIDATION_FAILED, + MZ_ZIP_WRITE_CALLBACK_FAILED, + MZ_ZIP_TOTAL_ERRORS +} mz_zip_error; + +typedef struct +{ + mz_uint64 m_archive_size; + mz_uint64 m_central_directory_file_ofs; + + /* We only support up to UINT32_MAX files in zip64 mode. */ + mz_uint32 m_total_files; + mz_zip_mode m_zip_mode; + mz_zip_type m_zip_type; + mz_zip_error m_last_error; + + mz_uint64 m_file_offset_alignment; + + mz_alloc_func m_pAlloc; + mz_free_func m_pFree; + mz_realloc_func m_pRealloc; + void *m_pAlloc_opaque; + + mz_file_read_func m_pRead; + mz_file_write_func m_pWrite; + mz_file_needs_keepalive m_pNeeds_keepalive; + void *m_pIO_opaque; + + mz_zip_internal_state *m_pState; + +} mz_zip_archive; + +typedef struct +{ + mz_zip_archive *pZip; + mz_uint flags; + + int status; + + mz_uint64 read_buf_size, read_buf_ofs, read_buf_avail, comp_remaining, out_buf_ofs, cur_file_ofs; + mz_zip_archive_file_stat file_stat; + void *pRead_buf; + void *pWrite_buf; + + size_t out_blk_remain; + + tinfl_decompressor inflator; + +#ifdef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS + mz_uint padding; +#else + mz_uint file_crc32; +#endif + +} mz_zip_reader_extract_iter_state; + +/* -------- ZIP reading */ + +/* Inits a ZIP archive reader. */ +/* These functions read and validate the archive's central directory. */ +MINIZ_EXPORT mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags); + +MINIZ_EXPORT mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags); + +#ifndef MINIZ_NO_STDIO +/* Read a archive from a disk file. */ +/* file_start_ofs is the file offset where the archive actually begins, or 0. */ +/* actual_archive_size is the true total size of the archive, which may be smaller than the file's actual size on disk. If zero the entire file is treated as the archive. */ +MINIZ_EXPORT mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); +MINIZ_EXPORT mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size); + +/* Read an archive from an already opened FILE, beginning at the current file position. */ +/* The archive is assumed to be archive_size bytes long. If archive_size is 0, then the entire rest of the file is assumed to contain the archive. */ +/* The FILE will NOT be closed when mz_zip_reader_end() is called. */ +MINIZ_EXPORT mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags); +#endif + +/* Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. */ +MINIZ_EXPORT mz_bool mz_zip_reader_end(mz_zip_archive *pZip); + +/* -------- ZIP reading or writing */ + +/* Clears a mz_zip_archive struct to all zeros. */ +/* Important: This must be done before passing the struct to any mz_zip functions. */ +MINIZ_EXPORT void mz_zip_zero_struct(mz_zip_archive *pZip); + +MINIZ_EXPORT mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip); +MINIZ_EXPORT mz_zip_type mz_zip_get_type(mz_zip_archive *pZip); + +/* Returns the total number of files in the archive. */ +MINIZ_EXPORT mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); + +MINIZ_EXPORT mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip); +MINIZ_EXPORT mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip); +MINIZ_EXPORT MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip); + +/* Reads n bytes of raw archive data, starting at file offset file_ofs, to pBuf. */ +MINIZ_EXPORT size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n); + +/* All mz_zip funcs set the m_last_error field in the mz_zip_archive struct. These functions retrieve/manipulate this field. */ +/* Note that the m_last_error functionality is not thread safe. */ +MINIZ_EXPORT mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num); +MINIZ_EXPORT mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip); +MINIZ_EXPORT mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip); +MINIZ_EXPORT mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip); +MINIZ_EXPORT const char *mz_zip_get_error_string(mz_zip_error mz_err); + +/* MZ_TRUE if the archive file entry is a directory entry. */ +MINIZ_EXPORT mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); + +/* MZ_TRUE if the file is encrypted/strong encrypted. */ +MINIZ_EXPORT mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); + +/* MZ_TRUE if the compression method is supported, and the file is not encrypted, and the file is not a compressed patch file. */ +MINIZ_EXPORT mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index); + +/* Retrieves the filename of an archive file entry. */ +/* Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. */ +MINIZ_EXPORT mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); + +/* Attempts to locates a file in the archive's central directory. */ +/* Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH */ +/* Returns -1 if the file cannot be found. */ +MINIZ_EXPORT int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); +MINIZ_EXPORT mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *file_index); + +/* Returns detailed information about an archive file entry. */ +MINIZ_EXPORT mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); + +/* MZ_TRUE if the file is in zip64 format. */ +/* A file is considered zip64 if it contained a zip64 end of central directory marker, or if it contained any zip64 extended file information fields in the central directory. */ +MINIZ_EXPORT mz_bool mz_zip_is_zip64(mz_zip_archive *pZip); + +/* Returns the total central directory size in bytes. */ +/* The current max supported size is <= MZ_UINT32_MAX. */ +MINIZ_EXPORT size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip); + +/* Extracts a archive file to a memory buffer using no memory allocation. */ +/* There must be at least enough room on the stack to store the inflator's state (~34KB or so). */ +MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); +MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); + +/* Extracts a archive file to a memory buffer. */ +MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); +MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); + +/* Extracts a archive file to a dynamically allocated heap buffer. */ +/* The memory will be allocated via the mz_zip_archive's alloc/realloc functions. */ +/* Returns NULL and sets the last error on failure. */ +MINIZ_EXPORT void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); +MINIZ_EXPORT void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); + +/* Extracts a archive file using a callback function to output the file's data. */ +MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); +MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); + +/* Extract a file iteratively */ +MINIZ_EXPORT mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); +MINIZ_EXPORT mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags); +MINIZ_EXPORT size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size); +MINIZ_EXPORT mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState); + +#ifndef MINIZ_NO_STDIO +/* Extracts a archive file to a disk file and sets its last accessed and modified times. */ +/* This function only extracts files, not archive directory records. */ +MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); +MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); + +/* Extracts a archive file starting at the current position in the destination FILE stream. */ +MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *File, mz_uint flags); +MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags); +#endif + +#if 0 +/* TODO */ + typedef void *mz_zip_streaming_extract_state_ptr; + mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); + mz_uint64 mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + mz_uint64 mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, mz_uint64 new_ofs); + size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size); + mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); +#endif + +/* This function compares the archive's local headers, the optional local zip64 extended information block, and the optional descriptor following the compressed data vs. the data in the central directory. */ +/* It also validates that each file can be successfully uncompressed unless the MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY is specified. */ +MINIZ_EXPORT mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); + +/* Validates an entire archive by calling mz_zip_validate_file() on each file. */ +MINIZ_EXPORT mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags); + +/* Misc utils/helpers, valid for ZIP reading or writing */ +MINIZ_EXPORT mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr); +#ifndef MINIZ_NO_STDIO +MINIZ_EXPORT mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr); +#endif + +/* Universal end function - calls either mz_zip_reader_end() or mz_zip_writer_end(). */ +MINIZ_EXPORT mz_bool mz_zip_end(mz_zip_archive *pZip); + +/* -------- ZIP writing */ + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +/* Inits a ZIP archive writer. */ +/*Set pZip->m_pWrite (and pZip->m_pIO_opaque) before calling mz_zip_writer_init or mz_zip_writer_init_v2*/ +/*The output is streamable, i.e. file_ofs in mz_file_write_func always increases only by n*/ +MINIZ_EXPORT mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); +MINIZ_EXPORT mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags); + +MINIZ_EXPORT mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); +MINIZ_EXPORT mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags); + +#ifndef MINIZ_NO_STDIO +MINIZ_EXPORT mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); +MINIZ_EXPORT mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags); +MINIZ_EXPORT mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags); +#endif + +/* Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. */ +/* For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. */ +/* For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). */ +/* Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. */ +/* Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before */ +/* the archive is finalized the file's central directory will be hosed. */ +MINIZ_EXPORT mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); +MINIZ_EXPORT mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags); + +/* Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. */ +/* To add a directory entry, call this method with an archive name ending in a forwardslash with an empty buffer. */ +/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ +MINIZ_EXPORT mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); + +/* Like mz_zip_writer_add_mem(), except you can specify a file comment field, and optionally supply the function with already compressed data. */ +/* uncomp_size/uncomp_crc32 are only used if the MZ_ZIP_FLAG_COMPRESSED_DATA flag is specified. */ +MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); + +MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data_local, mz_uint user_extra_data_local_len, + const char *user_extra_data_central, mz_uint user_extra_data_central_len); + +/* Adds the contents of a file to an archive. This function also records the disk file's modified time into the archive. */ +/* File data is supplied via a read callback function. User mz_zip_writer_add_(c)file to add a file directly.*/ +MINIZ_EXPORT mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size, + const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len, + const char *user_extra_data_central, mz_uint user_extra_data_central_len); + + +#ifndef MINIZ_NO_STDIO +/* Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. */ +/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ +MINIZ_EXPORT mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + +/* Like mz_zip_writer_add_file(), except the file data is read from the specified FILE stream. */ +MINIZ_EXPORT mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 max_size, + const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len, + const char *user_extra_data_central, mz_uint user_extra_data_central_len); +#endif + +/* Adds a file to an archive by fully cloning the data from another archive. */ +/* This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data (it may add or modify the zip64 local header extra data field), and the optional descriptor following the compressed data. */ +MINIZ_EXPORT mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index); + +/* Finalizes the archive by writing the central directory records followed by the end of central directory record. */ +/* After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). */ +/* An archive must be manually finalized by calling this function for it to be valid. */ +MINIZ_EXPORT mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); + +/* Finalizes a heap archive, returning a pointer to the heap block and its size. */ +/* The heap block will be allocated using the mz_zip_archive's alloc/realloc callbacks. */ +MINIZ_EXPORT mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize); + +/* Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. */ +/* Note for the archive to be valid, it *must* have been finalized before ending (this function will not do it for you). */ +MINIZ_EXPORT mz_bool mz_zip_writer_end(mz_zip_archive *pZip); + +/* -------- Misc. high-level helper functions: */ + +/* mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. */ +/* Note this is NOT a fully safe operation. If it crashes or dies in some way your archive can be left in a screwed up state (without a central directory). */ +/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ +/* TODO: Perhaps add an option to leave the existing central dir in place in case the add dies? We could then truncate the file (so the old central dir would be at the end) if something goes wrong. */ +MINIZ_EXPORT mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); +MINIZ_EXPORT mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr); + +#ifndef MINIZ_NO_STDIO +/* Reads a single file from an archive into a heap block. */ +/* If pComment is not NULL, only the file with the specified comment will be extracted. */ +/* Returns NULL on failure. */ +MINIZ_EXPORT void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags); +MINIZ_EXPORT void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr); +#endif + +#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */ + +#ifdef __cplusplus +} +#endif + +#endif /* MINIZ_NO_ARCHIVE_APIS */ diff --git a/libraries/webp/AUTHORS b/libraries/webp/AUTHORS new file mode 100644 index 0000000000..8359b20da9 --- /dev/null +++ b/libraries/webp/AUTHORS @@ -0,0 +1,60 @@ +Contributors: +- Aidan O'Loan (aidanol at gmail dot com) +- Alan Browning (browning at google dot com) +- Alexandru Ardelean (ardeleanalex at gmail dot com) +- Brian Ledger (brianpl at google dot com) +- Charles Munger (clm at google dot com) +- Cheng Yi (cyi at google dot com) +- Christian Duvivier (cduvivier at google dot com) +- Christopher Degawa (ccom at randomderp dot com) +- Clement Courbet (courbet at google dot com) +- Djordje Pesut (djordje dot pesut at imgtec dot com) +- Frank Barchard (fbarchard at google dot com) +- Hui Su (huisu at google dot com) +- H. Vetinari (h dot vetinari at gmx dot com) +- Ilya Kurdyukov (jpegqs at gmail dot com) +- Ingvar Stepanyan (rreverser at google dot com) +- James Zern (jzern at google dot com) +- Jan Engelhardt (jengelh at medozas dot de) +- Jehan (jehan at girinstud dot io) +- Jeremy Maitin-Shepard (jbms at google dot com) +- Johann Koenig (johann dot koenig at duck dot com) +- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) +- Jyrki Alakuijala (jyrki at google dot com) +- Konstantin Ivlev (tomskside at gmail dot com) +- Lode Vandevenne (lode at google dot com) +- Lou Quillio (louquillio at google dot com) +- Mans Rullgard (mans at mansr dot com) +- Marcin Kowalczyk (qrczak at google dot com) +- Martin Olsson (mnemo at minimum dot se) +- Maryla Ustarroz-Calonge (maryla at google dot com) +- Mikołaj Zalewski (mikolajz at google dot com) +- Mislav Bradac (mislavm at google dot com) +- Nico Weber (thakis at chromium dot org) +- Noel Chromium (noel at chromium dot org) +- Nozomi Isozaki (nontan at pixiv dot co dot jp) +- Oliver Wolff (oliver dot wolff at qt dot io) +- Owen Rodley (orodley at google dot com) +- Parag Salasakar (img dot mips1 at gmail dot com) +- Pascal Massimino (pascal dot massimino at gmail dot com) +- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org) +- Pierre Joye (pierre dot php at gmail dot com) +- Roberto Alanis (alanisbaez at google dot com) +- Sam Clegg (sbc at chromium dot org) +- Scott Hancher (seh at google dot com) +- Scott LaVarnway (slavarnway at google dot com) +- Scott Talbot (s at chikachow dot org) +- Slobodan Prijic (slobodan dot prijic at imgtec dot com) +- Somnath Banerjee (somnath dot banerjee at gmail dot com) +- Sriraman Tallam (tmsriram at google dot com) +- Tamar Levy (tamar dot levy at intel dot com) +- Thiago Perrotta (tperrotta at google dot com) +- Timothy Gu (timothygu99 at gmail dot com) +- Urvang Joshi (urvang at google dot com) +- Vikas Arora (vikasa at google dot com) +- Vincent Rabaud (vrabaud at google dot com) +- Vlad Tsyrklevich (vtsyrklevich at chromium dot org) +- Wan-Teh Chang (wtc at google dot com) +- Yang Zhang (yang dot zhang at arm dot com) +- Yannis Guyon (yguyon at google dot com) +- Zhi An Ng (zhin at chromium dot org) diff --git a/libraries/webp/CMakeLists.txt b/libraries/webp/CMakeLists.txt new file mode 100644 index 0000000000..9bd3fa9f70 --- /dev/null +++ b/libraries/webp/CMakeLists.txt @@ -0,0 +1,211 @@ +cmake_minimum_required(VERSION 3.11) +project(webp) + +set(WEBP_SOURCES + src/dec/alphai_dec.h + src/dec/alpha_dec.c + src/dec/buffer_dec.c + src/dec/common_dec.h + src/dec/frame_dec.c + src/dec/idec_dec.c + src/dec/io_dec.c + src/dec/quant_dec.c + src/dec/tree_dec.c + src/dec/vp8i_dec.h + src/dec/vp8li_dec.h + src/dec/vp8l_dec.c + src/dec/vp8_dec.c + src/dec/vp8_dec.h + src/dec/webpi_dec.h + src/dec/webp_dec.c + src/demux/anim_decode.c + src/demux/demux.c + src/dsp/alpha_processing.c + src/dsp/alpha_processing_mips_dsp_r2.c + src/dsp/alpha_processing_neon.c + src/dsp/alpha_processing_sse2.c + src/dsp/alpha_processing_sse41.c + src/dsp/common_sse2.h + src/dsp/common_sse41.h + src/dsp/cost.c + src/dsp/cost_mips32.c + src/dsp/cost_mips_dsp_r2.c + src/dsp/cost_neon.c + src/dsp/cost_sse2.c + src/dsp/cpu.c + src/dsp/cpu.h + src/dsp/dec.c + src/dsp/dec_clip_tables.c + src/dsp/dec_mips32.c + src/dsp/dec_mips_dsp_r2.c + src/dsp/dec_msa.c + src/dsp/dec_neon.c + src/dsp/dec_sse2.c + src/dsp/dec_sse41.c + src/dsp/dsp.h + src/dsp/enc.c + src/dsp/enc_mips32.c + src/dsp/enc_mips_dsp_r2.c + src/dsp/enc_msa.c + src/dsp/enc_neon.c + src/dsp/enc_sse2.c + src/dsp/enc_sse41.c + src/dsp/filters.c + src/dsp/filters_mips_dsp_r2.c + src/dsp/filters_msa.c + src/dsp/filters_neon.c + src/dsp/filters_sse2.c + src/dsp/lossless.c + src/dsp/lossless.h + src/dsp/lossless_common.h + src/dsp/lossless_enc.c + src/dsp/lossless_enc_mips32.c + src/dsp/lossless_enc_mips_dsp_r2.c + src/dsp/lossless_enc_msa.c + src/dsp/lossless_enc_neon.c + src/dsp/lossless_enc_sse2.c + src/dsp/lossless_enc_sse41.c + src/dsp/lossless_mips_dsp_r2.c + src/dsp/lossless_msa.c + src/dsp/lossless_neon.c + src/dsp/lossless_sse2.c + src/dsp/lossless_sse41.c + src/dsp/mips_macro.h + src/dsp/msa_macro.h + src/dsp/neon.h + src/dsp/quant.h + src/dsp/rescaler.c + src/dsp/rescaler_mips32.c + src/dsp/rescaler_mips_dsp_r2.c + src/dsp/rescaler_msa.c + src/dsp/rescaler_neon.c + src/dsp/rescaler_sse2.c + src/dsp/ssim.c + src/dsp/ssim_sse2.c + src/dsp/upsampling.c + src/dsp/upsampling_mips_dsp_r2.c + src/dsp/upsampling_msa.c + src/dsp/upsampling_neon.c + src/dsp/upsampling_sse2.c + src/dsp/upsampling_sse41.c + src/dsp/yuv.c + src/dsp/yuv.h + src/dsp/yuv_mips32.c + src/dsp/yuv_mips_dsp_r2.c + src/dsp/yuv_neon.c + src/dsp/yuv_sse2.c + src/dsp/yuv_sse41.c + src/enc/alpha_enc.c + src/enc/analysis_enc.c + src/enc/backward_references_cost_enc.c + src/enc/backward_references_enc.c + src/enc/backward_references_enc.h + src/enc/config_enc.c + src/enc/cost_enc.c + src/enc/cost_enc.h + src/enc/filter_enc.c + src/enc/frame_enc.c + src/enc/histogram_enc.c + src/enc/histogram_enc.h + src/enc/iterator_enc.c + src/enc/near_lossless_enc.c + src/enc/picture_csp_enc.c + src/enc/picture_enc.c + src/enc/picture_psnr_enc.c + src/enc/picture_rescale_enc.c + src/enc/picture_tools_enc.c + src/enc/predictor_enc.c + src/enc/quant_enc.c + src/enc/syntax_enc.c + src/enc/token_enc.c + src/enc/tree_enc.c + src/enc/vp8i_enc.h + src/enc/vp8li_enc.h + src/enc/vp8l_enc.c + src/enc/webp_enc.c + src/mux/animi.h + src/mux/anim_encode.c + src/mux/muxedit.c + src/mux/muxi.h + src/mux/muxinternal.c + src/mux/muxread.c + src/utils/bit_reader_inl_utils.h + src/utils/bit_reader_utils.c + src/utils/bit_reader_utils.h + src/utils/bit_writer_utils.c + src/utils/bit_writer_utils.h + src/utils/color_cache_utils.c + src/utils/color_cache_utils.h + src/utils/endian_inl_utils.h + src/utils/filters_utils.c + src/utils/filters_utils.h + src/utils/huffman_encode_utils.c + src/utils/huffman_encode_utils.h + src/utils/huffman_utils.c + src/utils/huffman_utils.h + src/utils/palette.c + src/utils/palette.h + src/utils/quant_levels_dec_utils.c + src/utils/quant_levels_dec_utils.h + src/utils/quant_levels_utils.c + src/utils/quant_levels_utils.h + src/utils/random_utils.c + src/utils/random_utils.h + src/utils/rescaler_utils.c + src/utils/rescaler_utils.h + src/utils/thread_utils.c + src/utils/thread_utils.h + src/utils/utils.c + src/utils/utils.h + sharpyuv/sharpyuv.c + sharpyuv/sharpyuv.h + sharpyuv/sharpyuv_cpu.c + sharpyuv/sharpyuv_cpu.h + sharpyuv/sharpyuv_csp.c + sharpyuv/sharpyuv_csp.h + sharpyuv/sharpyuv_dsp.c + sharpyuv/sharpyuv_dsp.h + sharpyuv/sharpyuv_gamma.c + sharpyuv/sharpyuv_gamma.h + sharpyuv/sharpyuv_neon.c + sharpyuv/sharpyuv_sse2.c +) + +set(WEBP_INCLUDES + include/webp/decode.h + include/webp/demux.h + include/webp/encode.h + include/webp/format_constants.h + include/webp/mux.h + include/webp/mux_types.h + include/webp/types.h +) + +source_group("src" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/.+") +source_group("src\\dec" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/dec/.+") +source_group("src\\demux" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/demux/.+") +source_group("src\\dsp" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/dsp/.+") +source_group("src\\enc" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/enc/.+") +source_group("src\\mux" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/mux/.+") +source_group("src\\utils" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/utils/.+") +source_group("sharpyuv" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/.+") +source_group("include" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/webp/.+") +source_group("include\\webp" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/webp/core/.+") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +if(MSVC) + # Use all cores for compilation + set(CMAKE_CXX_FLAGS "/MP ${CMAKE_CXX_FLAGS}") + + # Ignore warnings in third party code + #set_source_files_properties(${WEBP_SOURCES} PROPERTIES COMPILE_FLAGS "/wd4244 /wd4267 /wd4005 /wd4018 -D_CRT_SECURE_NO_WARNINGS") +endif() + +add_library(webp STATIC ${WEBP_SOURCES} ${WEBP_INCLUDES}) +target_link_libraries(webp ${WEBP_LIBS}) +set_target_properties(webp PROPERTIES CXX_STANDARD 17) + +if(MSVC) + set_property(TARGET webp PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +endif() diff --git a/libraries/webp/COPYING b/libraries/webp/COPYING new file mode 100644 index 0000000000..7a6f99547d --- /dev/null +++ b/libraries/webp/COPYING @@ -0,0 +1,30 @@ +Copyright (c) 2010, Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of Google 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. + diff --git a/libraries/webp/PATENTS b/libraries/webp/PATENTS new file mode 100644 index 0000000000..caedf607e9 --- /dev/null +++ b/libraries/webp/PATENTS @@ -0,0 +1,23 @@ +Additional IP Rights Grant (Patents) +------------------------------------ + +"These implementations" means the copyrightable works that implement the WebM +codecs distributed by Google as part of the WebM Project. + +Google 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, transfer, and otherwise +run, modify and propagate the contents of these implementations of WebM, where +such license applies only to those patent claims, both currently owned by +Google and acquired in the future, licensable by Google that are necessarily +infringed by these implementations of WebM. This grant does not include claims +that would be infringed only as a consequence of further modification of these +implementations. If you or your agent or exclusive licensee institute or order +or agree to the institution of patent litigation or any other patent +enforcement activity against any entity (including a cross-claim or +counterclaim in a lawsuit) alleging that any of these implementations of WebM +or any code incorporated within any of these implementations of WebM +constitute direct or contributory patent infringement, or inducement of +patent infringement, then any patent rights granted to you under this License +for these implementations of WebM shall terminate as of the date such +litigation is filed. diff --git a/libraries/webp/README.md b/libraries/webp/README.md new file mode 100644 index 0000000000..a9f2c0e12b --- /dev/null +++ b/libraries/webp/README.md @@ -0,0 +1,53 @@ +# WebP Codec + +``` + __ __ ____ ____ ____ + / \\/ \/ _ \/ _ )/ _ \ + \ / __/ _ \ __/ + \__\__/\____/\_____/__/ ____ ___ + / _/ / \ \ / _ \/ _/ + / \_/ / / \ \ __/ \__ + \____/____/\_____/_____/____/v1.3.2 +``` + +WebP codec is a library to encode and decode images in WebP format. This package +contains the library that can be used in other programs to add WebP support, as +well as the command line tools 'cwebp' and 'dwebp' to compress and decompress +images respectively. + +See https://developers.google.com/speed/webp for details on the image format. + +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp + +It is released under the same license as the WebM project. See +https://www.webmproject.org/license/software/ or the "COPYING" file for details. +An additional intellectual property rights grant can be found in the file +PATENTS. + +## Building + +See the [building documentation](doc/building.md). + +## Encoding and Decoding Tools + +The examples/ directory contains tools to encode and decode images and +animations, view information about WebP images, and more. See the +[tools documentation](doc/tools.md). + +## APIs + +See the [APIs documentation](doc/api.md), and API usage examples in the +`examples/` directory. + +## Bugs + +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp + +Patches welcome! See [how to contribute](CONTRIBUTING.md). + +## Discuss + +Email: webp-discuss@webmproject.org + +Web: https://groups.google.com/a/webmproject.org/group/webp-discuss diff --git a/libraries/webp/include/webp/decode.h b/libraries/webp/include/webp/decode.h new file mode 100644 index 0000000000..d6895f5c55 --- /dev/null +++ b/libraries/webp/include/webp/decode.h @@ -0,0 +1,506 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WebP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_DECODE_H_ +#define WEBP_WEBP_DECODE_H_ + +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_DECODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum VP8StatusCode VP8StatusCode; +// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; +typedef struct WebPRGBABuffer WebPRGBABuffer; +typedef struct WebPYUVABuffer WebPYUVABuffer; +typedef struct WebPDecBuffer WebPDecBuffer; +typedef struct WebPIDecoder WebPIDecoder; +typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; +typedef struct WebPDecoderOptions WebPDecoderOptions; +typedef struct WebPDecoderConfig WebPDecoderConfig; + +// Return the decoder's version number, packed in hexadecimal using 8bits for +// each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetDecoderVersion(void); + +// Retrieve basic header information: width, height. +// This function will also validate the header, returning true on success, +// false otherwise. '*width' and '*height' are only valid on successful return. +// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +WEBP_NODISCARD WEBP_EXTERN int WebPGetInfo( + const uint8_t* data, size_t data_size, int* width, int* height); + +// Decodes WebP images pointed to by 'data' and returns RGBA samples, along +// with the dimensions in *width and *height. The ordering of samples in +// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). +// The returned pointer should be deleted calling WebPFree(). +// Returns NULL in case of error. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBA( + const uint8_t* data, size_t data_size, int* width, int* height); + +// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeARGB( + const uint8_t* data, size_t data_size, int* width, int* height); + +// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRA( + const uint8_t* data, size_t data_size, int* width, int* height); + +// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. +// If the bitstream contains transparency, it is ignored. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGB( + const uint8_t* data, size_t data_size, int* width, int* height); + +// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGR( + const uint8_t* data, size_t data_size, int* width, int* height); + +// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer +// returned is the Y samples buffer. Upon return, *u and *v will point to +// the U and V chroma data. These U and V buffers need NOT be passed to +// WebPFree(), unlike the returned Y luma one. The dimension of the U and V +// planes are both (*width + 1) / 2 and (*height + 1) / 2. +// Upon return, the Y buffer has a stride returned as '*stride', while U and V +// have a common stride returned as '*uv_stride'. +// 'width' and 'height' may be NULL, the other pointers must not be. +// Returns NULL in case of error. +// (*) Also named Y'CbCr. See: https://en.wikipedia.org/wiki/YCbCr +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeYUV( + const uint8_t* data, size_t data_size, int* width, int* height, + uint8_t** u, uint8_t** v, int* stride, int* uv_stride); + +// These five functions are variants of the above ones, that decode the image +// directly into a pre-allocated buffer 'output_buffer'. The maximum storage +// available in this buffer is indicated by 'output_buffer_size'. If this +// storage is not sufficient (or an error occurred), NULL is returned. +// Otherwise, output_buffer is returned, for convenience. +// The parameter 'output_stride' specifies the distance (in bytes) +// between scanlines. Hence, output_buffer_size is expected to be at least +// output_stride x picture-height. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeARGBInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// RGB and BGR variants. Here too the transparency information, if present, +// will be dropped and ignored. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly +// into pre-allocated luma/chroma plane buffers. This function requires the +// strides to be passed: one for the luma plane and one for each of the +// chroma ones. The size of each plane buffer is passed as 'luma_size', +// 'u_size' and 'v_size' respectively. +// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred +// during decoding (or because some buffers were found to be too small). +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeYUVInto( + const uint8_t* data, size_t data_size, + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride); + +//------------------------------------------------------------------------------ +// Output colorspaces and buffer + +// Colorspaces +// Note: the naming describes the byte-ordering of packed samples in memory. +// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... +// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. +// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: +// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... +// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... +// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for +// these two modes: +// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... +// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... + +typedef enum WEBP_CSP_MODE { + MODE_RGB = 0, MODE_RGBA = 1, + MODE_BGR = 2, MODE_BGRA = 3, + MODE_ARGB = 4, MODE_RGBA_4444 = 5, + MODE_RGB_565 = 6, + // RGB-premultiplied transparent modes (alpha value is preserved) + MODE_rgbA = 7, + MODE_bgrA = 8, + MODE_Argb = 9, + MODE_rgbA_4444 = 10, + // YUV modes must come after RGB ones. + MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 + MODE_LAST = 13 +} WEBP_CSP_MODE; + +// Some useful macros: +static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { + return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb || + mode == MODE_rgbA_4444); +} + +static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) { + return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB || + mode == MODE_RGBA_4444 || mode == MODE_YUVA || + WebPIsPremultipliedMode(mode)); +} + +static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { + return (mode < MODE_YUV); +} + +//------------------------------------------------------------------------------ +// WebPDecBuffer: Generic structure for describing the output sample buffer. + +struct WebPRGBABuffer { // view as RGBA + uint8_t* rgba; // pointer to RGBA samples + int stride; // stride in bytes from one scanline to the next. + size_t size; // total size of the *rgba buffer. +}; + +struct WebPYUVABuffer { // view as YUVA + uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples + int y_stride; // luma stride + int u_stride, v_stride; // chroma strides + int a_stride; // alpha stride + size_t y_size; // luma plane size + size_t u_size, v_size; // chroma planes size + size_t a_size; // alpha-plane size +}; + +// Output buffer +struct WebPDecBuffer { + WEBP_CSP_MODE colorspace; // Colorspace. + int width, height; // Dimensions. + int is_external_memory; // If non-zero, 'internal_memory' pointer is not + // used. If value is '2' or more, the external + // memory is considered 'slow' and multiple + // read/write will be avoided. + union { + WebPRGBABuffer RGBA; + WebPYUVABuffer YUVA; + } u; // Nameless union of buffer parameters. + uint32_t pad[4]; // padding for later use + + uint8_t* private_memory; // Internally allocated memory (only when + // is_external_memory is 0). Should not be used + // externally, but accessed via the buffer union. +}; + +// Internal, version-checked, entry point +WEBP_NODISCARD WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); + +// Initialize the structure as empty. Must be called before any other use. +// Returns false in case of version mismatch +WEBP_NODISCARD static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { + return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); +} + +// Free any memory associated with the buffer. Must always be called last. +// Note: doesn't free the 'buffer' structure itself. +WEBP_EXTERN void WebPFreeDecBuffer(WebPDecBuffer* buffer); + +//------------------------------------------------------------------------------ +// Enumeration of the status codes + +typedef enum WEBP_NODISCARD VP8StatusCode { + VP8_STATUS_OK = 0, + VP8_STATUS_OUT_OF_MEMORY, + VP8_STATUS_INVALID_PARAM, + VP8_STATUS_BITSTREAM_ERROR, + VP8_STATUS_UNSUPPORTED_FEATURE, + VP8_STATUS_SUSPENDED, + VP8_STATUS_USER_ABORT, + VP8_STATUS_NOT_ENOUGH_DATA +} VP8StatusCode; + +//------------------------------------------------------------------------------ +// Incremental decoding +// +// This API allows streamlined decoding of partial data. +// Picture can be incrementally decoded as data become available thanks to the +// WebPIDecoder object. This object can be left in a SUSPENDED state if the +// picture is only partially decoded, pending additional input. +// Code example: +/* + WebPInitDecBuffer(&output_buffer); + output_buffer.colorspace = mode; + ... + WebPIDecoder* idec = WebPINewDecoder(&output_buffer); + while (additional_data_is_available) { + // ... (get additional data in some new_data[] buffer) + status = WebPIAppend(idec, new_data, new_data_size); + if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { + break; // an error occurred. + } + + // The above call decodes the current available buffer. + // Part of the image can now be refreshed by calling + // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. + } + WebPIDelete(idec); +*/ + +// Creates a new incremental decoder with the supplied buffer parameter. +// This output_buffer can be passed NULL, in which case a default output buffer +// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' +// is kept, which means that the lifespan of 'output_buffer' must be larger than +// that of the returned WebPIDecoder object. +// The supplied 'output_buffer' content MUST NOT be changed between calls to +// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is +// not set to 0. In such a case, it is allowed to modify the pointers, size and +// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain +// within valid bounds. +// All other fields of WebPDecBuffer MUST remain constant between calls. +// Returns NULL if the allocation failed. +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewDecoder( + WebPDecBuffer* output_buffer); + +// This function allocates and initializes an incremental-decoder object, which +// will output the RGB/A samples specified by 'csp' into a preallocated +// buffer 'output_buffer'. The size of this buffer is at least +// 'output_buffer_size' and the stride (distance in bytes between two scanlines) +// is specified by 'output_stride'. +// Additionally, output_buffer can be passed NULL in which case the output +// buffer will be allocated automatically when the decoding starts. The +// colorspace 'csp' is taken into account for allocating this buffer. All other +// parameters are ignored. +// Returns NULL if the allocation failed, or if some parameters are invalid. +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewRGB( + WEBP_CSP_MODE csp, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// This function allocates and initializes an incremental-decoder object, which +// will output the raw luma/chroma samples into a preallocated planes if +// supplied. The luma plane is specified by its pointer 'luma', its size +// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane +// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v +// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer +// can be pass NULL in case one is not interested in the transparency plane. +// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. +// In this case, the output buffer will be automatically allocated (using +// MODE_YUVA) when decoding starts. All parameters are then ignored. +// Returns NULL if the allocation failed or if a parameter is invalid. +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewYUVA( + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride, + uint8_t* a, size_t a_size, int a_stride); + +// Deprecated version of the above, without the alpha plane. +// Kept for backward compatibility. +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewYUV( + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride); + +// Deletes the WebPIDecoder object and associated memory. Must always be called +// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. +WEBP_EXTERN void WebPIDelete(WebPIDecoder* idec); + +// Copies and decodes the next available data. Returns VP8_STATUS_OK when +// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more +// data is expected. Returns error in other cases. +WEBP_EXTERN VP8StatusCode WebPIAppend( + WebPIDecoder* idec, const uint8_t* data, size_t data_size); + +// A variant of the above function to be used when data buffer contains +// partial data from the beginning. In this case data buffer is not copied +// to the internal memory. +// Note that the value of the 'data' pointer can change between calls to +// WebPIUpdate, for instance when the data buffer is resized to fit larger data. +WEBP_EXTERN VP8StatusCode WebPIUpdate( + WebPIDecoder* idec, const uint8_t* data, size_t data_size); + +// Returns the RGB/A image decoded so far. Returns NULL if output params +// are not initialized yet. The RGB/A output type corresponds to the colorspace +// specified during call to WebPINewDecoder() or WebPINewRGB(). +// *last_y is the index of last decoded row in raster scan order. Some pointers +// (*last_y, *width etc.) can be NULL if corresponding information is not +// needed. The values in these pointers are only valid on successful (non-NULL) +// return. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPIDecGetRGB( + const WebPIDecoder* idec, int* last_y, + int* width, int* height, int* stride); + +// Same as above function to get a YUVA image. Returns pointer to the luma +// plane or NULL in case of error. If there is no alpha information +// the alpha pointer '*a' will be returned NULL. +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPIDecGetYUVA( + const WebPIDecoder* idec, int* last_y, + uint8_t** u, uint8_t** v, uint8_t** a, + int* width, int* height, int* stride, int* uv_stride, int* a_stride); + +// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the +// alpha information (if present). Kept for backward compatibility. +WEBP_NODISCARD static WEBP_INLINE uint8_t* WebPIDecGetYUV( + const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, + int* width, int* height, int* stride, int* uv_stride) { + return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, + stride, uv_stride, NULL); +} + +// Generic call to retrieve information about the displayable area. +// If non NULL, the left/right/width/height pointers are filled with the visible +// rectangular area so far. +// Returns NULL in case the incremental decoder object is in an invalid state. +// Otherwise returns the pointer to the internal representation. This structure +// is read-only, tied to WebPIDecoder's lifespan and should not be modified. +WEBP_NODISCARD WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( + const WebPIDecoder* idec, int* left, int* top, int* width, int* height); + +//------------------------------------------------------------------------------ +// Advanced decoding parametrization +// +// Code sample for using the advanced decoding API +/* + // A) Init a configuration object + WebPDecoderConfig config; + CHECK(WebPInitDecoderConfig(&config)); + + // B) optional: retrieve the bitstream's features. + CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); + + // C) Adjust 'config', if needed + config.options.no_fancy_upsampling = 1; + config.output.colorspace = MODE_BGRA; + // etc. + + // Note that you can also make config.output point to an externally + // supplied memory buffer, provided it's big enough to store the decoded + // picture. Otherwise, config.output will just be used to allocate memory + // and store the decoded picture. + + // D) Decode! + CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); + + // E) Decoded image is now in config.output (and config.output.u.RGBA) + + // F) Reclaim memory allocated in config's object. It's safe to call + // this function even if the memory is external and wasn't allocated + // by WebPDecode(). + WebPFreeDecBuffer(&config.output); +*/ + +// Features gathered from the bitstream +struct WebPBitstreamFeatures { + int width; // Width in pixels, as read from the bitstream. + int height; // Height in pixels, as read from the bitstream. + int has_alpha; // True if the bitstream contains an alpha channel. + int has_animation; // True if the bitstream is an animation. + int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless + + uint32_t pad[5]; // padding for later use +}; + +// Internal, version-checked, entry point +WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal( + const uint8_t*, size_t, WebPBitstreamFeatures*, int); + +// Retrieve features from the bitstream. The *features structure is filled +// with information gathered from the bitstream. +// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns +// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the +// features from headers. Returns error in other cases. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +static WEBP_INLINE VP8StatusCode WebPGetFeatures( + const uint8_t* data, size_t data_size, + WebPBitstreamFeatures* features) { + return WebPGetFeaturesInternal(data, data_size, features, + WEBP_DECODER_ABI_VERSION); +} + +// Decoding options +struct WebPDecoderOptions { + int bypass_filtering; // if true, skip the in-loop filtering + int no_fancy_upsampling; // if true, use faster pointwise upsampler + int use_cropping; // if true, cropping is applied _first_ + int crop_left, crop_top; // top-left position for cropping. + // Will be snapped to even values. + int crop_width, crop_height; // dimension of the cropping area + int use_scaling; // if true, scaling is applied _afterward_ + int scaled_width, scaled_height; // final resolution + int use_threads; // if true, use multi-threaded decoding + int dithering_strength; // dithering strength (0=Off, 100=full) + int flip; // if true, flip output vertically + int alpha_dithering_strength; // alpha dithering strength in [0..100] + + uint32_t pad[5]; // padding for later use +}; + +// Main object storing the configuration for advanced decoding. +struct WebPDecoderConfig { + WebPBitstreamFeatures input; // Immutable bitstream features (optional) + WebPDecBuffer output; // Output buffer (can point to external mem) + WebPDecoderOptions options; // Decoding options +}; + +// Internal, version-checked, entry point +WEBP_NODISCARD WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, + int); + +// Initialize the configuration as empty. This function must always be +// called first, unless WebPGetFeatures() is to be called. +// Returns false in case of mismatched version. +WEBP_NODISCARD static WEBP_INLINE int WebPInitDecoderConfig( + WebPDecoderConfig* config) { + return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); +} + +// Instantiate a new incremental decoder object with the requested +// configuration. The bitstream can be passed using 'data' and 'data_size' +// parameter, in which case the features will be parsed and stored into +// config->input. Otherwise, 'data' can be NULL and no parsing will occur. +// Note that 'config' can be NULL too, in which case a default configuration +// is used. If 'config' is not NULL, it must outlive the WebPIDecoder object +// as some references to its fields will be used. No internal copy of 'config' +// is made. +// The return WebPIDecoder object must always be deleted calling WebPIDelete(). +// Returns NULL in case of error (and config->status will then reflect +// the error condition, if available). +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPIDecode( + const uint8_t* data, size_t data_size, WebPDecoderConfig* config); + +// Non-incremental version. This version decodes the full data at once, taking +// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK +// if the decoding was successful). Note that 'config' cannot be NULL. +WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_DECODE_H_ diff --git a/libraries/webp/include/webp/demux.h b/libraries/webp/include/webp/demux.h new file mode 100644 index 0000000000..8d246550ca --- /dev/null +++ b/libraries/webp/include/webp/demux.h @@ -0,0 +1,367 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Demux API. +// Enables extraction of image and extended format data from WebP files. + +// Code Example: Demuxing WebP data to extract all the frames, ICC profile +// and EXIF/XMP metadata. +/* + WebPDemuxer* demux = WebPDemux(&webp_data); + + uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); + uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); + // ... (Get information about the features present in the WebP file). + uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); + + // ... (Iterate over all frames). + WebPIterator iter; + if (WebPDemuxGetFrame(demux, 1, &iter)) { + do { + // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), + // ... and get other frame properties like width, height, offsets etc. + // ... see 'struct WebPIterator' below for more info). + } while (WebPDemuxNextFrame(&iter)); + WebPDemuxReleaseIterator(&iter); + } + + // ... (Extract metadata). + WebPChunkIterator chunk_iter; + if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); + // ... (Consume the ICC profile in 'chunk_iter.chunk'). + WebPDemuxReleaseChunkIterator(&chunk_iter); + if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); + // ... (Consume the EXIF metadata in 'chunk_iter.chunk'). + WebPDemuxReleaseChunkIterator(&chunk_iter); + if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); + // ... (Consume the XMP metadata in 'chunk_iter.chunk'). + WebPDemuxReleaseChunkIterator(&chunk_iter); + WebPDemuxDelete(demux); +*/ + +#ifndef WEBP_WEBP_DEMUX_H_ +#define WEBP_WEBP_DEMUX_H_ + +#include "./decode.h" // for WEBP_CSP_MODE +#include "./mux_types.h" +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_DEMUX_ABI_VERSION 0x0107 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPDemuxState WebPDemuxState; +// typedef enum WebPFormatFeature WebPFormatFeature; +typedef struct WebPDemuxer WebPDemuxer; +typedef struct WebPIterator WebPIterator; +typedef struct WebPChunkIterator WebPChunkIterator; +typedef struct WebPAnimInfo WebPAnimInfo; +typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions; + +//------------------------------------------------------------------------------ + +// Returns the version number of the demux library, packed in hexadecimal using +// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetDemuxVersion(void); + +//------------------------------------------------------------------------------ +// Life of a Demux object + +typedef enum WebPDemuxState { + WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing. + WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header. + WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete, + // data may be available. + WEBP_DEMUX_DONE = 2 // Entire file has been parsed. +} WebPDemuxState; + +// Internal, version-checked, entry point +WEBP_NODISCARD WEBP_EXTERN WebPDemuxer* WebPDemuxInternal( + const WebPData*, int, WebPDemuxState*, int); + +// Parses the full WebP file given by 'data'. For single images the WebP file +// header alone or the file header and the chunk header may be absent. +// Returns a WebPDemuxer object on successful parse, NULL otherwise. +WEBP_NODISCARD static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { + return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); +} + +// Parses the possibly incomplete WebP file given by 'data'. +// If 'state' is non-NULL it will be set to indicate the status of the demuxer. +// Returns NULL in case of error or if there isn't enough data to start parsing; +// and a WebPDemuxer object on successful parse. +// Note that WebPDemuxer keeps internal pointers to 'data' memory segment. +// If this data is volatile, the demuxer object should be deleted (by calling +// WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data. +// This is usually an inexpensive operation. +WEBP_NODISCARD static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( + const WebPData* data, WebPDemuxState* state) { + return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); +} + +// Frees memory associated with 'dmux'. +WEBP_EXTERN void WebPDemuxDelete(WebPDemuxer* dmux); + +//------------------------------------------------------------------------------ +// Data/information extraction. + +typedef enum WebPFormatFeature { + WEBP_FF_FORMAT_FLAGS, // bit-wise combination of WebPFeatureFlags + // corresponding to the 'VP8X' chunk (if present). + WEBP_FF_CANVAS_WIDTH, + WEBP_FF_CANVAS_HEIGHT, + WEBP_FF_LOOP_COUNT, // only relevant for animated file + WEBP_FF_BACKGROUND_COLOR, // idem. + WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. + // In case of a partial demux, this is the number + // of frames seen so far, with the last frame + // possibly being partial. +} WebPFormatFeature; + +// Get the 'feature' value from the 'dmux'. +// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() +// returned a state > WEBP_DEMUX_PARSING_HEADER. +// If 'feature' is WEBP_FF_FORMAT_FLAGS, the returned value is a bit-wise +// combination of WebPFeatureFlags values. +// If 'feature' is WEBP_FF_LOOP_COUNT, WEBP_FF_BACKGROUND_COLOR, the returned +// value is only meaningful if the bitstream is animated. +WEBP_EXTERN uint32_t WebPDemuxGetI( + const WebPDemuxer* dmux, WebPFormatFeature feature); + +//------------------------------------------------------------------------------ +// Frame iteration. + +struct WebPIterator { + int frame_num; + int num_frames; // equivalent to WEBP_FF_FRAME_COUNT. + int x_offset, y_offset; // offset relative to the canvas. + int width, height; // dimensions of this frame. + int duration; // display duration in milliseconds. + WebPMuxAnimDispose dispose_method; // dispose method for the frame. + int complete; // true if 'fragment' contains a full frame. partial images + // may still be decoded with the WebP incremental decoder. + WebPData fragment; // The frame given by 'frame_num'. Note for historical + // reasons this is called a fragment. + int has_alpha; // True if the frame contains transparency. + WebPMuxAnimBlend blend_method; // Blend operation for the frame. + + uint32_t pad[2]; // padding for later use. + void* private_; // for internal use only. +}; + +// Retrieves frame 'frame_number' from 'dmux'. +// 'iter->fragment' points to the frame on return from this function. +// Setting 'frame_number' equal to 0 will return the last frame of the image. +// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. +// Call WebPDemuxReleaseIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of 'iter'. +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxGetFrame( + const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); + +// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or +// previous ('iter->frame_num' - 1) frame. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxNextFrame(WebPIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxPrevFrame(WebPIterator* iter); + +// Releases any memory associated with 'iter'. +// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same +// iter. Also, must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN void WebPDemuxReleaseIterator(WebPIterator* iter); + +//------------------------------------------------------------------------------ +// Chunk iteration. + +struct WebPChunkIterator { + // The current and total number of chunks with the fourcc given to + // WebPDemuxGetChunk(). + int chunk_num; + int num_chunks; + WebPData chunk; // The payload of the chunk. + + uint32_t pad[6]; // padding for later use + void* private_; +}; + +// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from +// 'dmux'. +// 'fourcc' is a character array containing the fourcc of the chunk to return, +// e.g., "ICCP", "XMP ", "EXIF", etc. +// Setting 'chunk_number' equal to 0 will return the last chunk in a set. +// Returns true if the chunk is found, false otherwise. Image related chunk +// payloads are accessed through WebPDemuxGetFrame() and related functions. +// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of the iterator. +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], + int chunk_number, + WebPChunkIterator* iter); + +// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous +// ('iter->chunk_num' - 1) chunk. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxNextChunk(WebPChunkIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxPrevChunk(WebPChunkIterator* iter); + +// Releases any memory associated with 'iter'. +// Must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); + +//------------------------------------------------------------------------------ +// WebPAnimDecoder API +// +// This API allows decoding (possibly) animated WebP images. +// +// Code Example: +/* + WebPAnimDecoderOptions dec_options; + WebPAnimDecoderOptionsInit(&dec_options); + // Tune 'dec_options' as needed. + WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); + WebPAnimInfo anim_info; + WebPAnimDecoderGetInfo(dec, &anim_info); + for (uint32_t i = 0; i < anim_info.loop_count; ++i) { + while (WebPAnimDecoderHasMoreFrames(dec)) { + uint8_t* buf; + int timestamp; + WebPAnimDecoderGetNext(dec, &buf, ×tamp); + // ... (Render 'buf' based on 'timestamp'). + // ... (Do NOT free 'buf', as it is owned by 'dec'). + } + WebPAnimDecoderReset(dec); + } + const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); + // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). + WebPAnimDecoderDelete(dec); +*/ + +typedef struct WebPAnimDecoder WebPAnimDecoder; // Main opaque object. + +// Global options. +struct WebPAnimDecoderOptions { + // Output colorspace. Only the following modes are supported: + // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA. + WEBP_CSP_MODE color_mode; + int use_threads; // If true, use multi-threaded decoding. + uint32_t padding[7]; // Padding for later use. +}; + +// Internal, version-checked, entry point. +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderOptionsInitInternal( + WebPAnimDecoderOptions*, int); + +// Should always be called, to initialize a fresh WebPAnimDecoderOptions +// structure before modification. Returns false in case of version mismatch. +// WebPAnimDecoderOptionsInit() must have succeeded before using the +// 'dec_options' object. +WEBP_NODISCARD static WEBP_INLINE int WebPAnimDecoderOptionsInit( + WebPAnimDecoderOptions* dec_options) { + return WebPAnimDecoderOptionsInitInternal(dec_options, + WEBP_DEMUX_ABI_VERSION); +} + +// Internal, version-checked, entry point. +WEBP_NODISCARD WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( + const WebPData*, const WebPAnimDecoderOptions*, int); + +// Creates and initializes a WebPAnimDecoder object. +// Parameters: +// webp_data - (in) WebP bitstream. This should remain unchanged during the +// lifetime of the output WebPAnimDecoder object. +// dec_options - (in) decoding options. Can be passed NULL to choose +// reasonable defaults (in particular, color mode MODE_RGBA +// will be picked). +// Returns: +// A pointer to the newly created WebPAnimDecoder object, or NULL in case of +// parsing error, invalid option or memory error. +WEBP_NODISCARD static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( + const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) { + return WebPAnimDecoderNewInternal(webp_data, dec_options, + WEBP_DEMUX_ABI_VERSION); +} + +// Global information about the animation.. +struct WebPAnimInfo { + uint32_t canvas_width; + uint32_t canvas_height; + uint32_t loop_count; + uint32_t bgcolor; + uint32_t frame_count; + uint32_t pad[4]; // padding for later use +}; + +// Get global information about the animation. +// Parameters: +// dec - (in) decoder instance to get information from. +// info - (out) global information fetched from the animation. +// Returns: +// True on success. +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderGetInfo( + const WebPAnimDecoder* dec, WebPAnimInfo* info); + +// Fetch the next frame from 'dec' based on options supplied to +// WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size +// 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The +// returned buffer 'buf' is valid only until the next call to +// WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete(). +// Parameters: +// dec - (in/out) decoder instance from which the next frame is to be fetched. +// buf - (out) decoded frame. +// timestamp - (out) timestamp of the frame in milliseconds. +// Returns: +// False if any of the arguments are NULL, or if there is a parsing or +// decoding error, or if there are no more frames. Otherwise, returns true. +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf, + int* timestamp); + +// Check if there are more frames left to decode. +// Parameters: +// dec - (in) decoder instance to be checked. +// Returns: +// True if 'dec' is not NULL and some frames are yet to be decoded. +// Otherwise, returns false. +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderHasMoreFrames( + const WebPAnimDecoder* dec); + +// Resets the WebPAnimDecoder object, so that next call to +// WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be +// helpful when all frames need to be decoded multiple times (e.g. +// info.loop_count times) without destroying and recreating the 'dec' object. +// Parameters: +// dec - (in/out) decoder instance to be reset +WEBP_EXTERN void WebPAnimDecoderReset(WebPAnimDecoder* dec); + +// Grab the internal demuxer object. +// Getting the demuxer object can be useful if one wants to use operations only +// available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned +// demuxer object is owned by 'dec' and is valid only until the next call to +// WebPAnimDecoderDelete(). +// +// Parameters: +// dec - (in) decoder instance from which the demuxer object is to be fetched. +WEBP_NODISCARD WEBP_EXTERN const WebPDemuxer* WebPAnimDecoderGetDemuxer( + const WebPAnimDecoder* dec); + +// Deletes the WebPAnimDecoder object. +// Parameters: +// dec - (in/out) decoder instance to be deleted +WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_DEMUX_H_ diff --git a/libraries/webp/include/webp/encode.h b/libraries/webp/include/webp/encode.h new file mode 100644 index 0000000000..f3d59297c8 --- /dev/null +++ b/libraries/webp/include/webp/encode.h @@ -0,0 +1,557 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main interface +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_ENCODE_H_ +#define WEBP_WEBP_ENCODE_H_ + +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_ENCODER_ABI_VERSION 0x020f // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPImageHint WebPImageHint; +// typedef enum WebPEncCSP WebPEncCSP; +// typedef enum WebPPreset WebPPreset; +// typedef enum WebPEncodingError WebPEncodingError; +typedef struct WebPConfig WebPConfig; +typedef struct WebPPicture WebPPicture; // main structure for I/O +typedef struct WebPAuxStats WebPAuxStats; +typedef struct WebPMemoryWriter WebPMemoryWriter; + +// Return the encoder's version number, packed in hexadecimal using 8bits for +// each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetEncoderVersion(void); + +//------------------------------------------------------------------------------ +// One-stop-shop call! No questions asked: + +// Returns the size of the compressed data (pointed to by *output), or 0 if +// an error occurred. The compressed data must be released by the caller +// using the call 'WebPFree(*output)'. +// These functions compress using the lossy format, and the quality_factor +// can go from 0 (smaller output, lower quality) to 100 (best quality, +// larger output). +WEBP_EXTERN size_t WebPEncodeRGB(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN size_t WebPEncodeBGR(const uint8_t* bgr, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN size_t WebPEncodeRGBA(const uint8_t* rgba, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN size_t WebPEncodeBGRA(const uint8_t* bgra, + int width, int height, int stride, + float quality_factor, uint8_t** output); + +// These functions are the equivalent of the above, but compressing in a +// lossless manner. Files are usually larger than lossy format, but will +// not suffer any compression loss. +// Note these functions, like the lossy versions, use the library's default +// settings. For lossless this means 'exact' is disabled. RGB values in +// transparent areas will be modified to improve compression. To avoid this, +// use WebPEncode() and set WebPConfig::exact to 1. +WEBP_EXTERN size_t WebPEncodeLosslessRGB(const uint8_t* rgb, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN size_t WebPEncodeLosslessBGR(const uint8_t* bgr, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, + int width, int height, int stride, + uint8_t** output); + +//------------------------------------------------------------------------------ +// Coding parameters + +// Image characteristics hint for the underlying encoder. +typedef enum WebPImageHint { + WEBP_HINT_DEFAULT = 0, // default preset. + WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot + WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting + WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc). + WEBP_HINT_LAST +} WebPImageHint; + +// Compression parameters. +struct WebPConfig { + int lossless; // Lossless encoding (0=lossy(default), 1=lossless). + float quality; // between 0 and 100. For lossy, 0 gives the smallest + // size and 100 the largest. For lossless, this + // parameter is the amount of effort put into the + // compression: 0 is the fastest but gives larger + // files compared to the slowest, but best, 100. + int method; // quality/speed trade-off (0=fast, 6=slower-better) + + WebPImageHint image_hint; // Hint for image type (lossless only for now). + + int target_size; // if non-zero, set the desired target size in bytes. + // Takes precedence over the 'compression' parameter. + float target_PSNR; // if non-zero, specifies the minimal distortion to + // try to achieve. Takes precedence over target_size. + int segments; // maximum number of segments to use, in [1..4] + int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum. + int filter_strength; // range: [0 = off .. 100 = strongest] + int filter_sharpness; // range: [0 = off .. 7 = least sharp] + int filter_type; // filtering type: 0 = simple, 1 = strong (only used + // if filter_strength > 0 or autofilter > 0) + int autofilter; // Auto adjust filter's strength [0 = off, 1 = on] + int alpha_compression; // Algorithm for encoding the alpha plane (0 = none, + // 1 = compressed with WebP lossless). Default is 1. + int alpha_filtering; // Predictive filtering method for alpha plane. + // 0: none, 1: fast, 2: best. Default if 1. + int alpha_quality; // Between 0 (smallest size) and 100 (lossless). + // Default is 100. + int pass; // number of entropy-analysis passes (in [1..10]). + + int show_compressed; // if true, export the compressed picture back. + // In-loop filtering is not applied. + int preprocessing; // preprocessing filter: + // 0=none, 1=segment-smooth, 2=pseudo-random dithering + int partitions; // log2(number of token partitions) in [0..3]. Default + // is set to 0 for easier progressive decoding. + int partition_limit; // quality degradation allowed to fit the 512k limit + // on prediction modes coding (0: no degradation, + // 100: maximum possible degradation). + int emulate_jpeg_size; // If true, compression parameters will be remapped + // to better match the expected output size from + // JPEG compression. Generally, the output size will + // be similar but the degradation will be lower. + int thread_level; // If non-zero, try and use multi-threaded encoding. + int low_memory; // If set, reduce memory usage (but increase CPU use). + + int near_lossless; // Near lossless encoding [0 = max loss .. 100 = off + // (default)]. + int exact; // if non-zero, preserve the exact RGB values under + // transparent area. Otherwise, discard this invisible + // RGB information for better compression. The default + // value is 0. + + int use_delta_palette; // reserved for future lossless feature + int use_sharp_yuv; // if needed, use sharp (and slow) RGB->YUV conversion + + int qmin; // minimum permissible quality factor + int qmax; // maximum permissible quality factor +}; + +// Enumerate some predefined settings for WebPConfig, depending on the type +// of source picture. These presets are used when calling WebPConfigPreset(). +typedef enum WebPPreset { + WEBP_PRESET_DEFAULT = 0, // default preset. + WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot + WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting + WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details + WEBP_PRESET_ICON, // small-sized colorful images + WEBP_PRESET_TEXT // text-like +} WebPPreset; + +// Internal, version-checked, entry point +WEBP_NODISCARD WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, + float, int); + +// Should always be called, to initialize a fresh WebPConfig structure before +// modification. Returns false in case of version mismatch. WebPConfigInit() +// must have succeeded before using the 'config' object. +// Note that the default values are lossless=0 and quality=75. +WEBP_NODISCARD static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { + return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, + WEBP_ENCODER_ABI_VERSION); +} + +// This function will initialize the configuration according to a predefined +// set of parameters (referred to by 'preset') and a given quality factor. +// This function can be called as a replacement to WebPConfigInit(). Will +// return false in case of error. +WEBP_NODISCARD static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, + WebPPreset preset, + float quality) { + return WebPConfigInitInternal(config, preset, quality, + WEBP_ENCODER_ABI_VERSION); +} + +// Activate the lossless compression mode with the desired efficiency level +// between 0 (fastest, lowest compression) and 9 (slower, best compression). +// A good default level is '6', providing a fair tradeoff between compression +// speed and final compressed size. +// This function will overwrite several fields from config: 'method', 'quality' +// and 'lossless'. Returns false in case of parameter error. +WEBP_NODISCARD WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, + int level); + +// Returns true if 'config' is non-NULL and all configuration parameters are +// within their valid ranges. +WEBP_NODISCARD WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config); + +//------------------------------------------------------------------------------ +// Input / Output +// Structure for storing auxiliary statistics. + +struct WebPAuxStats { + int coded_size; // final size + + float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha + int block_count[3]; // number of intra4/intra16/skipped macroblocks + int header_bytes[2]; // approximate number of bytes spent for header + // and mode-partition #0 + int residual_bytes[3][4]; // approximate number of bytes spent for + // DC/AC/uv coefficients for each (0..3) segments. + int segment_size[4]; // number of macroblocks in each segments + int segment_quant[4]; // quantizer values for each segments + int segment_level[4]; // filtering strength for each segments [0..63] + + int alpha_data_size; // size of the transparency data + int layer_data_size; // size of the enhancement layer data + + // lossless encoder statistics + uint32_t lossless_features; // bit0:predictor bit1:cross-color transform + // bit2:subtract-green bit3:color indexing + int histogram_bits; // number of precision bits of histogram + int transform_bits; // precision bits for transform + int cache_bits; // number of bits for color cache lookup + int palette_size; // number of color in palette, if used + int lossless_size; // final lossless size + int lossless_hdr_size; // lossless header (transform, huffman etc) size + int lossless_data_size; // lossless image data size + + uint32_t pad[2]; // padding for later use +}; + +// Signature for output function. Should return true if writing was successful. +// data/data_size is the segment of data to write, and 'picture' is for +// reference (and so one can make use of picture->custom_ptr). +typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size, + const WebPPicture* picture); + +// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using +// the following WebPMemoryWriter object (to be set as a custom_ptr). +struct WebPMemoryWriter { + uint8_t* mem; // final buffer (of size 'max_size', larger than 'size'). + size_t size; // final size + size_t max_size; // total capacity + uint32_t pad[1]; // padding for later use +}; + +// The following must be called first before any use. +WEBP_EXTERN void WebPMemoryWriterInit(WebPMemoryWriter* writer); + +// The following must be called to deallocate writer->mem memory. The 'writer' +// object itself is not deallocated. +WEBP_EXTERN void WebPMemoryWriterClear(WebPMemoryWriter* writer); +// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon +// completion, writer.mem and writer.size will hold the coded data. +// writer.mem must be freed by calling WebPMemoryWriterClear. +WEBP_NODISCARD WEBP_EXTERN int WebPMemoryWrite( + const uint8_t* data, size_t data_size, const WebPPicture* picture); + +// Progress hook, called from time to time to report progress. It can return +// false to request an abort of the encoding process, or true otherwise if +// everything is OK. +typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); + +// Color spaces. +typedef enum WebPEncCSP { + // chroma sampling + WEBP_YUV420 = 0, // 4:2:0 + WEBP_YUV420A = 4, // alpha channel variant + WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors + WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present +} WebPEncCSP; + +// Encoding error conditions. +typedef enum WebPEncodingError { + VP8_ENC_OK = 0, + VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects + VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits + VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL + VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid + VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height + VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k + VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M + VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes + VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G + VP8_ENC_ERROR_USER_ABORT, // abort request by user + VP8_ENC_ERROR_LAST // list terminator. always last. +} WebPEncodingError; + +// maximum width/height allowed (inclusive), in pixels +#define WEBP_MAX_DIMENSION 16383 + +// Main exchange structure (input samples, output bytes, statistics) +// +// Once WebPPictureInit() has been called, it's ok to make all the INPUT fields +// (use_argb, y/u/v, argb, ...) point to user-owned data, even if +// WebPPictureAlloc() has been called. Depending on the value use_argb, +// it's guaranteed that either *argb or *y/*u/*v content will be kept untouched. +struct WebPPicture { + // INPUT + ////////////// + // Main flag for encoder selecting between ARGB or YUV input. + // It is recommended to use ARGB input (*argb, argb_stride) for lossless + // compression, and YUV input (*y, *u, *v, etc.) for lossy compression + // since these are the respective native colorspace for these formats. + int use_argb; + + // YUV input (mostly used for input to lossy compression) + WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr). + int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION) + uint8_t* y, *u, *v; // pointers to luma/chroma planes. + int y_stride, uv_stride; // luma/chroma strides. + uint8_t* a; // pointer to the alpha plane + int a_stride; // stride of the alpha plane + uint32_t pad1[2]; // padding for later use + + // ARGB input (mostly used for input to lossless compression) + uint32_t* argb; // Pointer to argb (32 bit) plane. + int argb_stride; // This is stride in pixels units, not bytes. + uint32_t pad2[3]; // padding for later use + + // OUTPUT + /////////////// + // Byte-emission hook, to store compressed bytes as they are ready. + WebPWriterFunction writer; // can be NULL + void* custom_ptr; // can be used by the writer. + + // map for extra information (only for lossy compression mode) + int extra_info_type; // 1: intra type, 2: segment, 3: quant + // 4: intra-16 prediction mode, + // 5: chroma prediction mode, + // 6: bit cost, 7: distortion + uint8_t* extra_info; // if not NULL, points to an array of size + // ((width + 15) / 16) * ((height + 15) / 16) that + // will be filled with a macroblock map, depending + // on extra_info_type. + + // STATS AND REPORTS + /////////////////////////// + // Pointer to side statistics (updated only if not NULL) + WebPAuxStats* stats; + + // Error code for the latest error encountered during encoding + WebPEncodingError error_code; + + // If not NULL, report progress during encoding. + WebPProgressHook progress_hook; + + void* user_data; // this field is free to be set to any value and + // used during callbacks (like progress-report e.g.). + + uint32_t pad3[3]; // padding for later use + + // Unused for now + uint8_t* pad4, *pad5; + uint32_t pad6[8]; // padding for later use + + // PRIVATE FIELDS + //////////////////// + void* memory_; // row chunk of memory for yuva planes + void* memory_argb_; // and for argb too. + void* pad7[2]; // padding for later use +}; + +// Internal, version-checked, entry point +WEBP_NODISCARD WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int); + +// Should always be called, to initialize the structure. Returns false in case +// of version mismatch. WebPPictureInit() must have succeeded before using the +// 'picture' object. +// Note that, by default, use_argb is false and colorspace is WEBP_YUV420. +WEBP_NODISCARD static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { + return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); +} + +//------------------------------------------------------------------------------ +// WebPPicture utils + +// Convenience allocation / deallocation based on picture->width/height: +// Allocate y/u/v buffers as per colorspace/width/height specification. +// Note! This function will free the previous buffer if needed. +// Returns false in case of memory error. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture); + +// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). +// Note that this function does _not_ free the memory used by the 'picture' +// object itself. +// Besides memory (which is reclaimed) all other fields of 'picture' are +// preserved. +WEBP_EXTERN void WebPPictureFree(WebPPicture* picture); + +// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst +// will fully own the copied pixels (this is not a view). The 'dst' picture need +// not be initialized as its content is overwritten. +// Returns false in case of memory allocation error. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, + WebPPicture* dst); + +// Compute the single distortion for packed planes of samples. +// 'src' will be compared to 'ref', and the raw distortion stored into +// '*distortion'. The refined metric (log(MSE), log(1 - ssim),...' will be +// stored in '*result'. +// 'x_step' is the horizontal stride (in bytes) between samples. +// 'src/ref_stride' is the byte distance between rows. +// Returns false in case of error (bad parameter, memory allocation error, ...). +WEBP_NODISCARD WEBP_EXTERN int WebPPlaneDistortion( + const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, int width, int height, size_t x_step, + int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM + float* distortion, float* result); + +// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results +// are in dB, stored in result[] in the B/G/R/A/All order. The distortion is +// always performed using ARGB samples. Hence if the input is YUV(A), the +// picture will be internally converted to ARGB (just for the measurement). +// Warning: this function is rather CPU-intensive. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureDistortion( + const WebPPicture* src, const WebPPicture* ref, + int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM + float result[5]); + +// self-crops a picture to the rectangle defined by top/left/width/height. +// Returns false in case of memory allocation error, or if the rectangle is +// outside of the source picture. +// The rectangle for the view is defined by the top-left corner pixel +// coordinates (left, top) as well as its width and height. This rectangle +// must be fully be comprised inside the 'src' source picture. If the source +// picture uses the YUV420 colorspace, the top and left coordinates will be +// snapped to even values. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureCrop( + WebPPicture* picture, int left, int top, int width, int height); + +// Extracts a view from 'src' picture into 'dst'. The rectangle for the view +// is defined by the top-left corner pixel coordinates (left, top) as well +// as its width and height. This rectangle must be fully be comprised inside +// the 'src' source picture. If the source picture uses the YUV420 colorspace, +// the top and left coordinates will be snapped to even values. +// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed +// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so, +// the original dimension will be lost). Picture 'dst' need not be initialized +// with WebPPictureInit() if it is different from 'src', since its content will +// be overwritten. +// Returns false in case of invalid parameters. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureView( + const WebPPicture* src, int left, int top, int width, int height, + WebPPicture* dst); + +// Returns true if the 'picture' is actually a view and therefore does +// not own the memory for pixels. +WEBP_EXTERN int WebPPictureIsView(const WebPPicture* picture); + +// Rescale a picture to new dimension width x height. +// If either 'width' or 'height' (but not both) is 0 the corresponding +// dimension will be calculated preserving the aspect ratio. +// No gamma correction is applied. +// Returns false in case of error (invalid parameter or insufficient memory). +WEBP_NODISCARD WEBP_EXTERN int WebPPictureRescale(WebPPicture* picture, + int width, int height); + +// Colorspace conversion function to import RGB samples. +// Previous buffer will be free'd, if any. +// *rgb buffer should have a size of at least height * rgb_stride. +// Returns false in case of memory error. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGB( + WebPPicture* picture, const uint8_t* rgb, int rgb_stride); +// Same, but for RGBA buffer. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGBA( + WebPPicture* picture, const uint8_t* rgba, int rgba_stride); +// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format +// input buffer ignoring the alpha channel. Avoids needing to copy the data +// to a temporary 24-bit RGB buffer to import the RGB only. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGBX( + WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); + +// Variants of the above, but taking BGR(A|X) input. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGR( + WebPPicture* picture, const uint8_t* bgr, int bgr_stride); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGRA( + WebPPicture* picture, const uint8_t* bgra, int bgra_stride); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGRX( + WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); + +// Converts picture->argb data to the YUV420A format. The 'colorspace' +// parameter is deprecated and should be equal to WEBP_YUV420. +// Upon return, picture->use_argb is set to false. The presence of real +// non-opaque transparent values is detected, and 'colorspace' will be +// adjusted accordingly. Note that this method is lossy. +// Returns false in case of error. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureARGBToYUVA( + WebPPicture* picture, WebPEncCSP /*colorspace = WEBP_YUV420*/); + +// Same as WebPPictureARGBToYUVA(), but the conversion is done using +// pseudo-random dithering with a strength 'dithering' between +// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful +// for photographic picture. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureARGBToYUVADithered( + WebPPicture* picture, WebPEncCSP colorspace, float dithering); + +// Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion +// Downsampling is handled with extra care in case of color clipping. This +// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better +// and sharper YUV representation. +// Returns false in case of error. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture); +// kept for backward compatibility: +WEBP_NODISCARD WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); + +// Converts picture->yuv to picture->argb and sets picture->use_argb to true. +// The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to +// ARGB incurs a small loss too. +// Note that the use of this colorspace is discouraged if one has access to the +// raw ARGB samples, since using YUV420 is comparatively lossy. +// Returns false in case of error. +WEBP_NODISCARD WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture); + +// Helper function: given a width x height plane of RGBA or YUV(A) samples +// clean-up or smoothen the YUV or RGB samples under fully transparent area, +// to help compressibility (no guarantee, though). +WEBP_EXTERN void WebPCleanupTransparentArea(WebPPicture* picture); + +// Scan the picture 'picture' for the presence of non fully opaque alpha values. +// Returns true in such case. Otherwise returns false (indicating that the +// alpha plane can be ignored altogether e.g.). +WEBP_EXTERN int WebPPictureHasTransparency(const WebPPicture* picture); + +// Remove the transparency information (if present) by blending the color with +// the background color 'background_rgb' (specified as 24bit RGB triplet). +// After this call, all alpha values are reset to 0xff. +WEBP_EXTERN void WebPBlendAlpha(WebPPicture* picture, uint32_t background_rgb); + +//------------------------------------------------------------------------------ +// Main call + +// Main encoding call, after config and picture have been initialized. +// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION), +// and the 'config' object must be a valid one. +// Returns false in case of error, true otherwise. +// In case of error, picture->error_code is updated accordingly. +// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending +// on the value of 'picture->use_argb'. It is highly recommended to use +// the former for lossy encoding, and the latter for lossless encoding +// (when config.lossless is true). Automatic conversion from one format to +// another is provided but they both incur some loss. +WEBP_NODISCARD WEBP_EXTERN int WebPEncode(const WebPConfig* config, + WebPPicture* picture); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_ENCODE_H_ diff --git a/libraries/webp/include/webp/format_constants.h b/libraries/webp/include/webp/format_constants.h new file mode 100644 index 0000000000..999035c5d2 --- /dev/null +++ b/libraries/webp/include/webp/format_constants.h @@ -0,0 +1,87 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_ +#define WEBP_WEBP_FORMAT_CONSTANTS_H_ + +// Create fourcc of the chunk from the chunk tag characters. +#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24) + +// VP8 related constants. +#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. +#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition +#define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition +#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data. + +// VP8L related constants. +#define VP8L_SIGNATURE_SIZE 1 // VP8L signature size. +#define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte. +#define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store + // width and height. +#define VP8L_VERSION_BITS 3 // 3 bits reserved for version. +#define VP8L_VERSION 0 // version 0 +#define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header. + +#define MAX_PALETTE_SIZE 256 +#define MAX_CACHE_BITS 11 +#define HUFFMAN_CODES_PER_META_CODE 5 +#define ARGB_BLACK 0xff000000 + +#define DEFAULT_CODE_LENGTH 8 +#define MAX_ALLOWED_CODE_LENGTH 15 + +#define NUM_LITERAL_CODES 256 +#define NUM_LENGTH_CODES 24 +#define NUM_DISTANCE_CODES 40 +#define CODE_LENGTH_CODES 19 + +#define MIN_HUFFMAN_BITS 2 // min number of Huffman bits +#define MAX_HUFFMAN_BITS 9 // max number of Huffman bits + +#define TRANSFORM_PRESENT 1 // The bit to be written when next data + // to be read is a transform. +#define NUM_TRANSFORMS 4 // Maximum number of allowed transform + // in a bitstream. +typedef enum { + PREDICTOR_TRANSFORM = 0, + CROSS_COLOR_TRANSFORM = 1, + SUBTRACT_GREEN_TRANSFORM = 2, + COLOR_INDEXING_TRANSFORM = 3 +} VP8LImageTransformType; + +// Alpha related constants. +#define ALPHA_HEADER_LEN 1 +#define ALPHA_NO_COMPRESSION 0 +#define ALPHA_LOSSLESS_COMPRESSION 1 +#define ALPHA_PREPROCESSED_LEVELS 1 + +// Mux related constants. +#define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L"). +#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size. +#define CHUNK_HEADER_SIZE 8 // Size of a chunk header. +#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP"). +#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk. +#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk. +#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. + +#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. +#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. +#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count +#define MAX_DURATION (1 << 24) // maximum duration +#define MAX_POSITION_OFFSET (1 << 24) // maximum frame x/y offset + +// Maximum chunk payload is such that adding the header and padding won't +// overflow a uint32_t. +#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1) + +#endif // WEBP_WEBP_FORMAT_CONSTANTS_H_ diff --git a/libraries/webp/include/webp/mux.h b/libraries/webp/include/webp/mux.h new file mode 100644 index 0000000000..8fb067e435 --- /dev/null +++ b/libraries/webp/include/webp/mux.h @@ -0,0 +1,591 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// RIFF container manipulation and encoding for WebP images. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +#ifndef WEBP_WEBP_MUX_H_ +#define WEBP_WEBP_MUX_H_ + +#include "./mux_types.h" +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_MUX_ABI_VERSION 0x0109 // MAJOR(8b) + MINOR(8b) + +//------------------------------------------------------------------------------ +// Mux API +// +// This API allows manipulation of WebP container images containing features +// like color profile, metadata, animation. +// +// Code Example#1: Create a WebPMux object with image data, color profile and +// XMP metadata. +/* + int copy_data = 0; + WebPMux* mux = WebPMuxNew(); + // ... (Prepare image data). + WebPMuxSetImage(mux, &image, copy_data); + // ... (Prepare ICCP color profile data). + WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); + // ... (Prepare XMP metadata). + WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); + // Get data from mux in WebP RIFF format. + WebPMuxAssemble(mux, &output_data); + WebPMuxDelete(mux); + // ... (Consume output_data; e.g. write output_data.bytes to file). + WebPDataClear(&output_data); +*/ + +// Code Example#2: Get image and color profile data from a WebP file. +/* + int copy_data = 0; + // ... (Read data from file). + WebPMux* mux = WebPMuxCreate(&data, copy_data); + WebPMuxGetFrame(mux, 1, &image); + // ... (Consume image; e.g. call WebPDecode() to decode the data). + WebPMuxGetChunk(mux, "ICCP", &icc_profile); + // ... (Consume icc_data). + WebPMuxDelete(mux); + WebPFree(data); +*/ + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPMuxError WebPMuxError; +// typedef enum WebPChunkId WebPChunkId; +typedef struct WebPMux WebPMux; // main opaque object. +typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; +typedef struct WebPMuxAnimParams WebPMuxAnimParams; +typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions; + +// Error codes +typedef enum WEBP_NODISCARD WebPMuxError { + WEBP_MUX_OK = 1, + WEBP_MUX_NOT_FOUND = 0, + WEBP_MUX_INVALID_ARGUMENT = -1, + WEBP_MUX_BAD_DATA = -2, + WEBP_MUX_MEMORY_ERROR = -3, + WEBP_MUX_NOT_ENOUGH_DATA = -4 +} WebPMuxError; + +// IDs for different types of chunks. +typedef enum WebPChunkId { + WEBP_CHUNK_VP8X, // VP8X + WEBP_CHUNK_ICCP, // ICCP + WEBP_CHUNK_ANIM, // ANIM + WEBP_CHUNK_ANMF, // ANMF + WEBP_CHUNK_DEPRECATED, // (deprecated from FRGM) + WEBP_CHUNK_ALPHA, // ALPH + WEBP_CHUNK_IMAGE, // VP8/VP8L + WEBP_CHUNK_EXIF, // EXIF + WEBP_CHUNK_XMP, // XMP + WEBP_CHUNK_UNKNOWN, // Other chunks. + WEBP_CHUNK_NIL +} WebPChunkId; + +//------------------------------------------------------------------------------ + +// Returns the version number of the mux library, packed in hexadecimal using +// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetMuxVersion(void); + +//------------------------------------------------------------------------------ +// Life of a Mux object + +// Internal, version-checked, entry point +WEBP_NODISCARD WEBP_EXTERN WebPMux* WebPNewInternal(int); + +// Creates an empty mux object. +// Returns: +// A pointer to the newly created empty mux object. +// Or NULL in case of memory error. +WEBP_NODISCARD static WEBP_INLINE WebPMux* WebPMuxNew(void) { + return WebPNewInternal(WEBP_MUX_ABI_VERSION); +} + +// Deletes the mux object. +// Parameters: +// mux - (in/out) object to be deleted +WEBP_EXTERN void WebPMuxDelete(WebPMux* mux); + +//------------------------------------------------------------------------------ +// Mux creation. + +// Internal, version-checked, entry point +WEBP_NODISCARD WEBP_EXTERN WebPMux* WebPMuxCreateInternal(const WebPData*, int, + int); + +// Creates a mux object from raw data given in WebP RIFF format. +// Parameters: +// bitstream - (in) the bitstream data in WebP RIFF format +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist for the lifetime of the +// mux object. +// Returns: +// A pointer to the mux object created from given data - on success. +// NULL - In case of invalid data or memory error. +WEBP_NODISCARD static WEBP_INLINE WebPMux* WebPMuxCreate( + const WebPData* bitstream, int copy_data) { + return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION); +} + +//------------------------------------------------------------------------------ +// Non-image chunks. + +// Note: Only non-image related chunks should be managed through chunk APIs. +// (Image related chunks are: "ANMF", "VP8 ", "VP8L" and "ALPH"). +// To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(), +// WebPMuxGetFrame() and WebPMuxDeleteFrame(). + +// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object. +// Any existing chunk(s) with the same id will be removed. +// Parameters: +// mux - (in/out) object to which the chunk is to be added +// fourcc - (in) a character array containing the fourcc of the given chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// chunk_data - (in) the chunk data to be added +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxSetChunk( + WebPMux* mux, const char fourcc[4], const WebPData* chunk_data, + int copy_data); + +// Gets a reference to the data of the chunk with id 'fourcc' in the mux object. +// The caller should NOT free the returned data. +// Parameters: +// mux - (in) object from which the chunk data is to be fetched +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// chunk_data - (out) returned chunk data +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetChunk( + const WebPMux* mux, const char fourcc[4], WebPData* chunk_data); + +// Deletes the chunk with the given 'fourcc' from the mux object. +// Parameters: +// mux - (in/out) object from which the chunk is to be deleted +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxDeleteChunk( + WebPMux* mux, const char fourcc[4]); + +//------------------------------------------------------------------------------ +// Images. + +// Encapsulates data about a single frame. +struct WebPMuxFrameInfo { + WebPData bitstream; // image data: can be a raw VP8/VP8L bitstream + // or a single-image WebP file. + int x_offset; // x-offset of the frame. + int y_offset; // y-offset of the frame. + int duration; // duration of the frame (in milliseconds). + + WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF + // or WEBP_CHUNK_IMAGE + WebPMuxAnimDispose dispose_method; // Disposal method for the frame. + WebPMuxAnimBlend blend_method; // Blend operation for the frame. + uint32_t pad[1]; // padding for later use +}; + +// Sets the (non-animated) image in the mux object. +// Note: Any existing images (including frames) will be removed. +// Parameters: +// mux - (in/out) object in which the image is to be set +// bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image +// WebP file (non-animated) +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxSetImage( + WebPMux* mux, const WebPData* bitstream, int copy_data); + +// Adds a frame at the end of the mux object. +// Notes: (1) frame.id should be WEBP_CHUNK_ANMF +// (2) For setting a non-animated image, use WebPMuxSetImage() instead. +// (3) Type of frame being pushed must be same as the frames in mux. +// (4) As WebP only supports even offsets, any odd offset will be snapped +// to an even location using: offset &= ~1 +// Parameters: +// mux - (in/out) object to which the frame is to be added +// frame - (in) frame data. +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL +// or if content of 'frame' is invalid. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxPushFrame( + WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); + +// Gets the nth frame from the mux object. +// The content of 'frame->bitstream' is allocated using WebPMalloc(), and NOT +// owned by the 'mux' object. It MUST be deallocated by the caller by calling +// WebPDataClear(). +// nth=0 has a special meaning - last position. +// Parameters: +// mux - (in) object from which the info is to be fetched +// nth - (in) index of the frame in the mux object +// frame - (out) data of the returned frame +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL. +// WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object. +// WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetFrame( + const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); + +// Deletes a frame from the mux object. +// nth=0 has a special meaning - last position. +// Parameters: +// mux - (in/out) object from which a frame is to be deleted +// nth - (in) The position from which the frame is to be deleted +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL. +// WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object +// before deletion. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); + +//------------------------------------------------------------------------------ +// Animation. + +// Animation parameters. +struct WebPMuxAnimParams { + uint32_t bgcolor; // Background color of the canvas stored (in MSB order) as: + // Bits 00 to 07: Alpha. + // Bits 08 to 15: Red. + // Bits 16 to 23: Green. + // Bits 24 to 31: Blue. + int loop_count; // Number of times to repeat the animation [0 = infinite]. +}; + +// Sets the animation parameters in the mux object. Any existing ANIM chunks +// will be removed. +// Parameters: +// mux - (in/out) object in which ANIM chunk is to be set/added +// params - (in) animation parameters. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxSetAnimationParams( + WebPMux* mux, const WebPMuxAnimParams* params); + +// Gets the animation parameters from the mux object. +// Parameters: +// mux - (in) object from which the animation parameters to be fetched +// params - (out) animation parameters extracted from the ANIM chunk +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. +// WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetAnimationParams( + const WebPMux* mux, WebPMuxAnimParams* params); + +//------------------------------------------------------------------------------ +// Misc Utilities. + +// Sets the canvas size for the mux object. The width and height can be +// specified explicitly or left as zero (0, 0). +// * When width and height are specified explicitly, then this frame bound is +// enforced during subsequent calls to WebPMuxAssemble() and an error is +// reported if any animated frame does not completely fit within the canvas. +// * When unspecified (0, 0), the constructed canvas will get the frame bounds +// from the bounding-box over all frames after calling WebPMuxAssemble(). +// Parameters: +// mux - (in) object to which the canvas size is to be set +// width - (in) canvas width +// height - (in) canvas height +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or +// width or height are invalid or out of bounds +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, + int width, int height); + +// Gets the canvas size from the mux object. +// Note: This method assumes that the VP8X chunk, if present, is up-to-date. +// That is, the mux object hasn't been modified since the last call to +// WebPMuxAssemble() or WebPMuxCreate(). +// Parameters: +// mux - (in) object from which the canvas size is to be fetched +// width - (out) canvas width +// height - (out) canvas height +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL. +// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, + int* width, int* height); + +// Gets the feature flags from the mux object. +// Note: This method assumes that the VP8X chunk, if present, is up-to-date. +// That is, the mux object hasn't been modified since the last call to +// WebPMuxAssemble() or WebPMuxCreate(). +// Parameters: +// mux - (in) object from which the features are to be fetched +// flags - (out) the flags specifying which features are present in the +// mux object. This will be an OR of various flag values. +// Enum 'WebPFeatureFlags' can be used to test individual flag values. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL. +// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, + uint32_t* flags); + +// Gets number of chunks with the given 'id' in the mux object. +// Parameters: +// mux - (in) object from which the info is to be fetched +// id - (in) chunk id specifying the type of chunk +// num_elements - (out) number of chunks with the given chunk id +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxNumChunks(const WebPMux* mux, + WebPChunkId id, int* num_elements); + +// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'. +// This function also validates the mux object. +// Note: The content of 'assembled_data' will be ignored and overwritten. +// Also, the content of 'assembled_data' is allocated using WebPMalloc(), and +// NOT owned by the 'mux' object. It MUST be deallocated by the caller by +// calling WebPDataClear(). It's always safe to call WebPDataClear() upon +// return, even in case of error. +// Parameters: +// mux - (in/out) object whose chunks are to be assembled +// assembled_data - (out) assembled WebP data +// Returns: +// WEBP_MUX_BAD_DATA - if mux object is invalid. +// WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxAssemble(WebPMux* mux, + WebPData* assembled_data); + +//------------------------------------------------------------------------------ +// WebPAnimEncoder API +// +// This API allows encoding (possibly) animated WebP images. +// +// Code Example: +/* + WebPAnimEncoderOptions enc_options; + WebPAnimEncoderOptionsInit(&enc_options); + // Tune 'enc_options' as needed. + WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); + while() { + WebPConfig config; + WebPConfigInit(&config); + // Tune 'config' as needed. + WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config); + } + WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL); + WebPAnimEncoderAssemble(enc, webp_data); + WebPAnimEncoderDelete(enc); + // Write the 'webp_data' to a file, or re-mux it further. +*/ + +typedef struct WebPAnimEncoder WebPAnimEncoder; // Main opaque object. + +// Forward declarations. Defined in encode.h. +struct WebPPicture; +struct WebPConfig; + +// Global options. +struct WebPAnimEncoderOptions { + WebPMuxAnimParams anim_params; // Animation parameters. + int minimize_size; // If true, minimize the output size (slow). Implicitly + // disables key-frame insertion. + int kmin; + int kmax; // Minimum and maximum distance between consecutive key + // frames in the output. The library may insert some key + // frames as needed to satisfy this criteria. + // Note that these conditions should hold: kmax > kmin + // and kmin >= kmax / 2 + 1. Also, if kmax <= 0, then + // key-frame insertion is disabled; and if kmax == 1, + // then all frames will be key-frames (kmin value does + // not matter for these special cases). + int allow_mixed; // If true, use mixed compression mode; may choose + // either lossy and lossless for each frame. + int verbose; // If true, print info and warning messages to stderr. + + uint32_t padding[4]; // Padding for later use. +}; + +// Internal, version-checked, entry point. +WEBP_EXTERN int WebPAnimEncoderOptionsInitInternal( + WebPAnimEncoderOptions*, int); + +// Should always be called, to initialize a fresh WebPAnimEncoderOptions +// structure before modification. Returns false in case of version mismatch. +// WebPAnimEncoderOptionsInit() must have succeeded before using the +// 'enc_options' object. +WEBP_NODISCARD static WEBP_INLINE int WebPAnimEncoderOptionsInit( + WebPAnimEncoderOptions* enc_options) { + return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION); +} + +// Internal, version-checked, entry point. +WEBP_EXTERN WebPAnimEncoder* WebPAnimEncoderNewInternal( + int, int, const WebPAnimEncoderOptions*, int); + +// Creates and initializes a WebPAnimEncoder object. +// Parameters: +// width/height - (in) canvas width and height of the animation. +// enc_options - (in) encoding options; can be passed NULL to pick +// reasonable defaults. +// Returns: +// A pointer to the newly created WebPAnimEncoder object. +// Or NULL in case of memory error. +static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( + int width, int height, const WebPAnimEncoderOptions* enc_options) { + return WebPAnimEncoderNewInternal(width, height, enc_options, + WEBP_MUX_ABI_VERSION); +} + +// Optimize the given frame for WebP, encode it and add it to the +// WebPAnimEncoder object. +// The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which +// indicates that no more frames are to be added. This call is also used to +// determine the duration of the last frame. +// Parameters: +// enc - (in/out) object to which the frame is to be added. +// frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A) +// format, it will be converted to ARGB, which incurs a small loss. +// timestamp_ms - (in) timestamp of this frame in milliseconds. +// Duration of a frame would be calculated as +// "timestamp of next frame - timestamp of this frame". +// Hence, timestamps should be in non-decreasing order. +// config - (in) encoding options; can be passed NULL to pick +// reasonable defaults. +// Returns: +// On error, returns false and frame->error_code is set appropriately. +// Otherwise, returns true. +WEBP_NODISCARD WEBP_EXTERN int WebPAnimEncoderAdd( + WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, + const struct WebPConfig* config); + +// Assemble all frames added so far into a WebP bitstream. +// This call should be preceded by a call to 'WebPAnimEncoderAdd' with +// frame = NULL; if not, the duration of the last frame will be internally +// estimated. +// Parameters: +// enc - (in/out) object from which the frames are to be assembled. +// webp_data - (out) generated WebP bitstream. +// Returns: +// True on success. +WEBP_NODISCARD WEBP_EXTERN int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, + WebPData* webp_data); + +// Get error string corresponding to the most recent call using 'enc'. The +// returned string is owned by 'enc' and is valid only until the next call to +// WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete(). +// Parameters: +// enc - (in/out) object from which the error string is to be fetched. +// Returns: +// NULL if 'enc' is NULL. Otherwise, returns the error string if the last call +// to 'enc' had an error, or an empty string if the last call was a success. +WEBP_EXTERN const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc); + +// Deletes the WebPAnimEncoder object. +// Parameters: +// enc - (in/out) object to be deleted +WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc); + +//------------------------------------------------------------------------------ +// Non-image chunks. + +// Note: Only non-image related chunks should be managed through chunk APIs. +// (Image related chunks are: "ANMF", "VP8 ", "VP8L" and "ALPH"). + +// Adds a chunk with id 'fourcc' and data 'chunk_data' in the enc object. +// Any existing chunk(s) with the same id will be removed. +// Parameters: +// enc - (in/out) object to which the chunk is to be added +// fourcc - (in) a character array containing the fourcc of the given chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// chunk_data - (in) the chunk data to be added +// copy_data - (in) value 1 indicates given data WILL be copied to the enc +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPAnimEncoderAssemble() is made. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc, fourcc or chunk_data is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderSetChunk( + WebPAnimEncoder* enc, const char fourcc[4], const WebPData* chunk_data, + int copy_data); + +// Gets a reference to the data of the chunk with id 'fourcc' in the enc object. +// The caller should NOT free the returned data. +// Parameters: +// enc - (in) object from which the chunk data is to be fetched +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// chunk_data - (out) returned chunk data +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc, fourcc or chunk_data is NULL. +// WEBP_MUX_NOT_FOUND - If enc does not contain a chunk with the given id. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderGetChunk( + const WebPAnimEncoder* enc, const char fourcc[4], WebPData* chunk_data); + +// Deletes the chunk with the given 'fourcc' from the enc object. +// Parameters: +// enc - (in/out) object from which the chunk is to be deleted +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc or fourcc is NULL. +// WEBP_MUX_NOT_FOUND - If enc does not contain a chunk with the given fourcc. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderDeleteChunk( + WebPAnimEncoder* enc, const char fourcc[4]); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_MUX_H_ diff --git a/libraries/webp/include/webp/mux_types.h b/libraries/webp/include/webp/mux_types.h new file mode 100644 index 0000000000..c585d2082f --- /dev/null +++ b/libraries/webp/include/webp/mux_types.h @@ -0,0 +1,99 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Data-types common to the mux and demux libraries. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_WEBP_MUX_TYPES_H_ +#define WEBP_WEBP_MUX_TYPES_H_ + +#include // memset() +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPFeatureFlags WebPFeatureFlags; +// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; +// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend; +typedef struct WebPData WebPData; + +// VP8X Feature Flags. +typedef enum WebPFeatureFlags { + ANIMATION_FLAG = 0x00000002, + XMP_FLAG = 0x00000004, + EXIF_FLAG = 0x00000008, + ALPHA_FLAG = 0x00000010, + ICCP_FLAG = 0x00000020, + + ALL_VALID_FLAGS = 0x0000003e +} WebPFeatureFlags; + +// Dispose method (animation only). Indicates how the area used by the current +// frame is to be treated before rendering the next frame on the canvas. +typedef enum WebPMuxAnimDispose { + WEBP_MUX_DISPOSE_NONE, // Do not dispose. + WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. +} WebPMuxAnimDispose; + +// Blend operation (animation only). Indicates how transparent pixels of the +// current frame are blended with those of the previous canvas. +typedef enum WebPMuxAnimBlend { + WEBP_MUX_BLEND, // Blend. + WEBP_MUX_NO_BLEND // Do not blend. +} WebPMuxAnimBlend; + +// Data type used to describe 'raw' data, e.g., chunk data +// (ICC profile, metadata) and WebP compressed image data. +// 'bytes' memory must be allocated using WebPMalloc() and such. +struct WebPData { + const uint8_t* bytes; + size_t size; +}; + +// Initializes the contents of the 'webp_data' object with default values. +static WEBP_INLINE void WebPDataInit(WebPData* webp_data) { + if (webp_data != NULL) { + memset(webp_data, 0, sizeof(*webp_data)); + } +} + +// Clears the contents of the 'webp_data' object by calling WebPFree(). +// Does not deallocate the object itself. +static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { + if (webp_data != NULL) { + WebPFree((void*)webp_data->bytes); + WebPDataInit(webp_data); + } +} + +// Allocates necessary storage for 'dst' and copies the contents of 'src'. +// Returns true on success. +WEBP_NODISCARD static WEBP_INLINE int WebPDataCopy(const WebPData* src, + WebPData* dst) { + if (src == NULL || dst == NULL) return 0; + WebPDataInit(dst); + if (src->bytes != NULL && src->size != 0) { + dst->bytes = (uint8_t*)WebPMalloc(src->size); + if (dst->bytes == NULL) return 0; + memcpy((void*)dst->bytes, src->bytes, src->size); + dst->size = src->size; + } + return 1; +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_MUX_TYPES_H_ diff --git a/libraries/webp/include/webp/types.h b/libraries/webp/include/webp/types.h new file mode 100644 index 0000000000..0e7ef1295b --- /dev/null +++ b/libraries/webp/include/webp/types.h @@ -0,0 +1,87 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_TYPES_H_ +#define WEBP_WEBP_TYPES_H_ + +#include // for size_t + +#ifndef _MSC_VER +#include +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#define WEBP_INLINE inline +#else +#define WEBP_INLINE +#endif +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; +typedef long long int int64_t; +#define WEBP_INLINE __forceinline +#endif /* _MSC_VER */ + +#if defined(WEBP_ENABLE_NODISCARD) || \ + (defined(__cplusplus) && __cplusplus >= 201700L) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +#define WEBP_NODISCARD [[nodiscard]] +#else +// gcc's __has_attribute does not work for enums. +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(warn_unused_result) +#define WEBP_NODISCARD __attribute__((warn_unused_result)) +#else +#define WEBP_NODISCARD +#endif +#else +#define WEBP_NODISCARD +#endif +#endif + +#ifndef WEBP_EXTERN +// This explicitly marks library functions and allows for changing the +// signature for e.g., Windows DLL builds. +# if defined(_WIN32) && defined(WEBP_DLL) +# define WEBP_EXTERN __declspec(dllexport) +# elif defined(__GNUC__) && __GNUC__ >= 4 +# define WEBP_EXTERN extern __attribute__ ((visibility ("default"))) +# else +# define WEBP_EXTERN extern +# endif /* defined(_WIN32) && defined(WEBP_DLL) */ +#endif /* WEBP_EXTERN */ + +// Macro to check ABI compatibility (same major revision number) +#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) + +#ifdef __cplusplus +extern "C" { +#endif + +// Allocates 'size' bytes of memory. Returns NULL upon error. Memory +// must be deallocated by calling WebPFree(). This function is made available +// by the core 'libwebp' library. +WEBP_NODISCARD WEBP_EXTERN void* WebPMalloc(size_t size); + +// Releases memory returned by the WebPDecode*() functions (from decode.h). +WEBP_EXTERN void WebPFree(void* ptr); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_TYPES_H_ diff --git a/libraries/webp/sharpyuv/sharpyuv.c b/libraries/webp/sharpyuv/sharpyuv.c new file mode 100644 index 0000000000..c779e7383c --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv.c @@ -0,0 +1,574 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Sharp RGB to YUV conversion. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "sharpyuv/sharpyuv.h" + +#include +#include +#include +#include +#include + +#include "include/webp/types.h" +#include "sharpyuv/sharpyuv_cpu.h" +#include "sharpyuv/sharpyuv_dsp.h" +#include "sharpyuv/sharpyuv_gamma.h" + +//------------------------------------------------------------------------------ + +int SharpYuvGetVersion(void) { + return SHARPYUV_VERSION; +} + +//------------------------------------------------------------------------------ +// Sharp RGB->YUV conversion + +static const int kNumIterations = 4; + +#define YUV_FIX 16 // fixed-point precision for RGB->YUV +static const int kYuvHalf = 1 << (YUV_FIX - 1); + +// Max bit depth so that intermediate calculations fit in 16 bits. +static const int kMaxBitDepth = 14; + +// Returns the precision shift to use based on the input rgb_bit_depth. +static int GetPrecisionShift(int rgb_bit_depth) { + // Try to add 2 bits of precision if it fits in kMaxBitDepth. Otherwise remove + // bits if needed. + return ((rgb_bit_depth + 2) <= kMaxBitDepth) ? 2 + : (kMaxBitDepth - rgb_bit_depth); +} + +typedef int16_t fixed_t; // signed type with extra precision for UV +typedef uint16_t fixed_y_t; // unsigned type with extra precision for W + +//------------------------------------------------------------------------------ + +static uint8_t clip_8b(fixed_t v) { + return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u; +} + +static uint16_t clip(fixed_t v, int max) { + return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; +} + +static fixed_y_t clip_bit_depth(int y, int bit_depth) { + const int max = (1 << bit_depth) - 1; + return (!(y & ~max)) ? (fixed_y_t)y : (y < 0) ? 0 : max; +} + +//------------------------------------------------------------------------------ + +static int RGBToGray(int64_t r, int64_t g, int64_t b) { + const int64_t luma = 13933 * r + 46871 * g + 4732 * b + kYuvHalf; + return (int)(luma >> YUV_FIX); +} + +static uint32_t ScaleDown(uint16_t a, uint16_t b, uint16_t c, uint16_t d, + int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { + const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); + const uint32_t A = SharpYuvGammaToLinear(a, bit_depth, transfer_type); + const uint32_t B = SharpYuvGammaToLinear(b, bit_depth, transfer_type); + const uint32_t C = SharpYuvGammaToLinear(c, bit_depth, transfer_type); + const uint32_t D = SharpYuvGammaToLinear(d, bit_depth, transfer_type); + return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth, + transfer_type); +} + +static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w, + int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { + const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); + int i = 0; + do { + const uint32_t R = + SharpYuvGammaToLinear(src[0 * w + i], bit_depth, transfer_type); + const uint32_t G = + SharpYuvGammaToLinear(src[1 * w + i], bit_depth, transfer_type); + const uint32_t B = + SharpYuvGammaToLinear(src[2 * w + i], bit_depth, transfer_type); + const uint32_t Y = RGBToGray(R, G, B); + dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth, transfer_type); + } while (++i < w); +} + +static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2, + fixed_t* dst, int uv_w, int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { + int i = 0; + do { + const int r = + ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1], src2[0 * uv_w + 0], + src2[0 * uv_w + 1], rgb_bit_depth, transfer_type); + const int g = + ScaleDown(src1[2 * uv_w + 0], src1[2 * uv_w + 1], src2[2 * uv_w + 0], + src2[2 * uv_w + 1], rgb_bit_depth, transfer_type); + const int b = + ScaleDown(src1[4 * uv_w + 0], src1[4 * uv_w + 1], src2[4 * uv_w + 0], + src2[4 * uv_w + 1], rgb_bit_depth, transfer_type); + const int W = RGBToGray(r, g, b); + dst[0 * uv_w] = (fixed_t)(r - W); + dst[1 * uv_w] = (fixed_t)(g - W); + dst[2 * uv_w] = (fixed_t)(b - W); + dst += 1; + src1 += 2; + src2 += 2; + } while (++i < uv_w); +} + +static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) { + int i = 0; + assert(w > 0); + do { + y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]); + } while (++i < w); +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE fixed_y_t Filter2(int A, int B, int W0, int bit_depth) { + const int v0 = (A * 3 + B + 2) >> 2; + return clip_bit_depth(v0 + W0, bit_depth); +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int Shift(int v, int shift) { + return (shift >= 0) ? (v << shift) : (v >> -shift); +} + +static void ImportOneRow(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + int rgb_step, + int rgb_bit_depth, + int pic_width, + fixed_y_t* const dst) { + // Convert the rgb_step from a number of bytes to a number of uint8_t or + // uint16_t values depending the bit depth. + const int step = (rgb_bit_depth > 8) ? rgb_step / 2 : rgb_step; + int i = 0; + const int w = (pic_width + 1) & ~1; + do { + const int off = i * step; + const int shift = GetPrecisionShift(rgb_bit_depth); + if (rgb_bit_depth == 8) { + dst[i + 0 * w] = Shift(r_ptr[off], shift); + dst[i + 1 * w] = Shift(g_ptr[off], shift); + dst[i + 2 * w] = Shift(b_ptr[off], shift); + } else { + dst[i + 0 * w] = Shift(((uint16_t*)r_ptr)[off], shift); + dst[i + 1 * w] = Shift(((uint16_t*)g_ptr)[off], shift); + dst[i + 2 * w] = Shift(((uint16_t*)b_ptr)[off], shift); + } + } while (++i < pic_width); + if (pic_width & 1) { // replicate rightmost pixel + dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1]; + dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1]; + dst[pic_width + 2 * w] = dst[pic_width + 2 * w - 1]; + } +} + +static void InterpolateTwoRows(const fixed_y_t* const best_y, + const fixed_t* prev_uv, + const fixed_t* cur_uv, + const fixed_t* next_uv, + int w, + fixed_y_t* out1, + fixed_y_t* out2, + int rgb_bit_depth) { + const int uv_w = w >> 1; + const int len = (w - 1) >> 1; // length to filter + int k = 3; + const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); + while (k-- > 0) { // process each R/G/B segments in turn + // special boundary case for i==0 + out1[0] = Filter2(cur_uv[0], prev_uv[0], best_y[0], bit_depth); + out2[0] = Filter2(cur_uv[0], next_uv[0], best_y[w], bit_depth); + + SharpYuvFilterRow(cur_uv, prev_uv, len, best_y + 0 + 1, out1 + 1, + bit_depth); + SharpYuvFilterRow(cur_uv, next_uv, len, best_y + w + 1, out2 + 1, + bit_depth); + + // special boundary case for i == w - 1 when w is even + if (!(w & 1)) { + out1[w - 1] = Filter2(cur_uv[uv_w - 1], prev_uv[uv_w - 1], + best_y[w - 1 + 0], bit_depth); + out2[w - 1] = Filter2(cur_uv[uv_w - 1], next_uv[uv_w - 1], + best_y[w - 1 + w], bit_depth); + } + out1 += w; + out2 += w; + prev_uv += uv_w; + cur_uv += uv_w; + next_uv += uv_w; + } +} + +static WEBP_INLINE int RGBToYUVComponent(int r, int g, int b, + const int coeffs[4], int sfix) { + const int srounder = 1 << (YUV_FIX + sfix - 1); + const int luma = coeffs[0] * r + coeffs[1] * g + coeffs[2] * b + + coeffs[3] + srounder; + return (luma >> (YUV_FIX + sfix)); +} + +static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv, + uint8_t* y_ptr, int y_stride, uint8_t* u_ptr, + int u_stride, uint8_t* v_ptr, int v_stride, + int rgb_bit_depth, + int yuv_bit_depth, int width, int height, + const SharpYuvConversionMatrix* yuv_matrix) { + int i, j; + const fixed_t* const best_uv_base = best_uv; + const int w = (width + 1) & ~1; + const int h = (height + 1) & ~1; + const int uv_w = w >> 1; + const int uv_h = h >> 1; + const int sfix = GetPrecisionShift(rgb_bit_depth); + const int yuv_max = (1 << yuv_bit_depth) - 1; + + best_uv = best_uv_base; + j = 0; + do { + i = 0; + do { + const int off = (i >> 1); + const int W = best_y[i]; + const int r = best_uv[off + 0 * uv_w] + W; + const int g = best_uv[off + 1 * uv_w] + W; + const int b = best_uv[off + 2 * uv_w] + W; + const int y = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_y, sfix); + if (yuv_bit_depth <= 8) { + y_ptr[i] = clip_8b(y); + } else { + ((uint16_t*)y_ptr)[i] = clip(y, yuv_max); + } + } while (++i < width); + best_y += w; + best_uv += (j & 1) * 3 * uv_w; + y_ptr += y_stride; + } while (++j < height); + + best_uv = best_uv_base; + j = 0; + do { + i = 0; + do { + // Note r, g and b values here are off by W, but a constant offset on all + // 3 components doesn't change the value of u and v with a YCbCr matrix. + const int r = best_uv[i + 0 * uv_w]; + const int g = best_uv[i + 1 * uv_w]; + const int b = best_uv[i + 2 * uv_w]; + const int u = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_u, sfix); + const int v = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_v, sfix); + if (yuv_bit_depth <= 8) { + u_ptr[i] = clip_8b(u); + v_ptr[i] = clip_8b(v); + } else { + ((uint16_t*)u_ptr)[i] = clip(u, yuv_max); + ((uint16_t*)v_ptr)[i] = clip(v, yuv_max); + } + } while (++i < uv_w); + best_uv += 3 * uv_w; + u_ptr += u_stride; + v_ptr += v_stride; + } while (++j < uv_h); + return 1; +} + +//------------------------------------------------------------------------------ +// Main function + +static void* SafeMalloc(uint64_t nmemb, size_t size) { + const uint64_t total_size = nmemb * (uint64_t)size; + if (total_size != (size_t)total_size) return NULL; + return malloc((size_t)total_size); +} + +#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((uint64_t)(W) * (H), sizeof(T))) + +static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, + const uint8_t* b_ptr, int rgb_step, int rgb_stride, + int rgb_bit_depth, uint8_t* y_ptr, int y_stride, + uint8_t* u_ptr, int u_stride, uint8_t* v_ptr, + int v_stride, int yuv_bit_depth, int width, + int height, + const SharpYuvConversionMatrix* yuv_matrix, + SharpYuvTransferFunctionType transfer_type) { + // we expand the right/bottom border if needed + const int w = (width + 1) & ~1; + const int h = (height + 1) & ~1; + const int uv_w = w >> 1; + const int uv_h = h >> 1; + const int y_bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); + uint64_t prev_diff_y_sum = ~0; + int j, iter; + + // TODO(skal): allocate one big memory chunk. But for now, it's easier + // for valgrind debugging to have several chunks. + fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch + fixed_y_t* const best_y_base = SAFE_ALLOC(w, h, fixed_y_t); + fixed_y_t* const target_y_base = SAFE_ALLOC(w, h, fixed_y_t); + fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t); + fixed_t* const best_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); + fixed_t* const target_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); + fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t); + fixed_y_t* best_y = best_y_base; + fixed_y_t* target_y = target_y_base; + fixed_t* best_uv = best_uv_base; + fixed_t* target_uv = target_uv_base; + const uint64_t diff_y_threshold = (uint64_t)(3.0 * w * h); + int ok; + assert(w > 0); + assert(h > 0); + + if (best_y_base == NULL || best_uv_base == NULL || + target_y_base == NULL || target_uv_base == NULL || + best_rgb_y == NULL || best_rgb_uv == NULL || + tmp_buffer == NULL) { + ok = 0; + goto End; + } + + // Import RGB samples to W/RGB representation. + for (j = 0; j < height; j += 2) { + const int is_last_row = (j == height - 1); + fixed_y_t* const src1 = tmp_buffer + 0 * w; + fixed_y_t* const src2 = tmp_buffer + 3 * w; + + // prepare two rows of input + ImportOneRow(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, width, + src1); + if (!is_last_row) { + ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride, + rgb_step, rgb_bit_depth, width, src2); + } else { + memcpy(src2, src1, 3 * w * sizeof(*src2)); + } + StoreGray(src1, best_y + 0, w); + StoreGray(src2, best_y + w, w); + + UpdateW(src1, target_y, w, rgb_bit_depth, transfer_type); + UpdateW(src2, target_y + w, w, rgb_bit_depth, transfer_type); + UpdateChroma(src1, src2, target_uv, uv_w, rgb_bit_depth, transfer_type); + memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv)); + best_y += 2 * w; + best_uv += 3 * uv_w; + target_y += 2 * w; + target_uv += 3 * uv_w; + r_ptr += 2 * rgb_stride; + g_ptr += 2 * rgb_stride; + b_ptr += 2 * rgb_stride; + } + + // Iterate and resolve clipping conflicts. + for (iter = 0; iter < kNumIterations; ++iter) { + const fixed_t* cur_uv = best_uv_base; + const fixed_t* prev_uv = best_uv_base; + uint64_t diff_y_sum = 0; + + best_y = best_y_base; + best_uv = best_uv_base; + target_y = target_y_base; + target_uv = target_uv_base; + j = 0; + do { + fixed_y_t* const src1 = tmp_buffer + 0 * w; + fixed_y_t* const src2 = tmp_buffer + 3 * w; + { + const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0); + InterpolateTwoRows(best_y, prev_uv, cur_uv, next_uv, w, + src1, src2, rgb_bit_depth); + prev_uv = cur_uv; + cur_uv = next_uv; + } + + UpdateW(src1, best_rgb_y + 0 * w, w, rgb_bit_depth, transfer_type); + UpdateW(src2, best_rgb_y + 1 * w, w, rgb_bit_depth, transfer_type); + UpdateChroma(src1, src2, best_rgb_uv, uv_w, rgb_bit_depth, transfer_type); + + // update two rows of Y and one row of RGB + diff_y_sum += + SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, y_bit_depth); + SharpYuvUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w); + + best_y += 2 * w; + best_uv += 3 * uv_w; + target_y += 2 * w; + target_uv += 3 * uv_w; + j += 2; + } while (j < h); + // test exit condition + if (iter > 0) { + if (diff_y_sum < diff_y_threshold) break; + if (diff_y_sum > prev_diff_y_sum) break; + } + prev_diff_y_sum = diff_y_sum; + } + + // final reconstruction + ok = ConvertWRGBToYUV(best_y_base, best_uv_base, y_ptr, y_stride, u_ptr, + u_stride, v_ptr, v_stride, rgb_bit_depth, yuv_bit_depth, + width, height, yuv_matrix); + + End: + free(best_y_base); + free(best_uv_base); + free(target_y_base); + free(target_uv_base); + free(best_rgb_y); + free(best_rgb_uv); + free(tmp_buffer); + return ok; +} + +#undef SAFE_ALLOC + +#if defined(WEBP_USE_THREAD) && !defined(_WIN32) +#include // NOLINT + +#define LOCK_ACCESS \ + static pthread_mutex_t sharpyuv_lock = PTHREAD_MUTEX_INITIALIZER; \ + if (pthread_mutex_lock(&sharpyuv_lock)) return +#define UNLOCK_ACCESS_AND_RETURN \ + do { \ + (void)pthread_mutex_unlock(&sharpyuv_lock); \ + return; \ + } while (0) +#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32)) +#define LOCK_ACCESS do {} while (0) +#define UNLOCK_ACCESS_AND_RETURN return +#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32) + +// Hidden exported init function. +// By default SharpYuvConvert calls it with SharpYuvGetCPUInfo. If needed, +// users can declare it as extern and call it with an alternate VP8CPUInfo +// function. +extern VP8CPUInfo SharpYuvGetCPUInfo; +SHARPYUV_EXTERN void SharpYuvInit(VP8CPUInfo cpu_info_func); +void SharpYuvInit(VP8CPUInfo cpu_info_func) { + static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used = + (VP8CPUInfo)&sharpyuv_last_cpuinfo_used; + LOCK_ACCESS; + // Only update SharpYuvGetCPUInfo when called from external code to avoid a + // race on reading the value in SharpYuvConvert(). + if (cpu_info_func != (VP8CPUInfo)&SharpYuvGetCPUInfo) { + SharpYuvGetCPUInfo = cpu_info_func; + } + if (sharpyuv_last_cpuinfo_used == SharpYuvGetCPUInfo) { + UNLOCK_ACCESS_AND_RETURN; + } + + SharpYuvInitDsp(); + SharpYuvInitGammaTables(); + + sharpyuv_last_cpuinfo_used = SharpYuvGetCPUInfo; + UNLOCK_ACCESS_AND_RETURN; +} + +int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr, + int rgb_step, int rgb_stride, int rgb_bit_depth, + void* y_ptr, int y_stride, void* u_ptr, int u_stride, + void* v_ptr, int v_stride, int yuv_bit_depth, int width, + int height, const SharpYuvConversionMatrix* yuv_matrix) { + SharpYuvOptions options; + options.yuv_matrix = yuv_matrix; + options.transfer_type = kSharpYuvTransferFunctionSrgb; + return SharpYuvConvertWithOptions( + r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, rgb_bit_depth, y_ptr, y_stride, + u_ptr, u_stride, v_ptr, v_stride, yuv_bit_depth, width, height, &options); +} + +int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix* yuv_matrix, + SharpYuvOptions* options, int version) { + const int major = (version >> 24); + const int minor = (version >> 16) & 0xff; + if (options == NULL || yuv_matrix == NULL || + (major == SHARPYUV_VERSION_MAJOR && major == 0 && + minor != SHARPYUV_VERSION_MINOR) || + (major != SHARPYUV_VERSION_MAJOR)) { + return 0; + } + options->yuv_matrix = yuv_matrix; + options->transfer_type = kSharpYuvTransferFunctionSrgb; + return 1; +} + +int SharpYuvConvertWithOptions(const void* r_ptr, const void* g_ptr, + const void* b_ptr, int rgb_step, int rgb_stride, + int rgb_bit_depth, void* y_ptr, int y_stride, + void* u_ptr, int u_stride, void* v_ptr, + int v_stride, int yuv_bit_depth, int width, + int height, const SharpYuvOptions* options) { + const SharpYuvConversionMatrix* yuv_matrix = options->yuv_matrix; + SharpYuvTransferFunctionType transfer_type = options->transfer_type; + SharpYuvConversionMatrix scaled_matrix; + const int rgb_max = (1 << rgb_bit_depth) - 1; + const int rgb_round = 1 << (rgb_bit_depth - 1); + const int yuv_max = (1 << yuv_bit_depth) - 1; + const int sfix = GetPrecisionShift(rgb_bit_depth); + + if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX || + r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || y_ptr == NULL || + u_ptr == NULL || v_ptr == NULL) { + return 0; + } + if (rgb_bit_depth != 8 && rgb_bit_depth != 10 && rgb_bit_depth != 12 && + rgb_bit_depth != 16) { + return 0; + } + if (yuv_bit_depth != 8 && yuv_bit_depth != 10 && yuv_bit_depth != 12) { + return 0; + } + if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride % 2 != 0)) { + // Step/stride should be even for uint16_t buffers. + return 0; + } + if (yuv_bit_depth > 8 && + (y_stride % 2 != 0 || u_stride % 2 != 0 || v_stride % 2 != 0)) { + // Stride should be even for uint16_t buffers. + return 0; + } + // The address of the function pointer is used to avoid a read race. + SharpYuvInit((VP8CPUInfo)&SharpYuvGetCPUInfo); + + // Add scaling factor to go from rgb_bit_depth to yuv_bit_depth, to the + // rgb->yuv conversion matrix. + if (rgb_bit_depth == yuv_bit_depth) { + memcpy(&scaled_matrix, yuv_matrix, sizeof(scaled_matrix)); + } else { + int i; + for (i = 0; i < 3; ++i) { + scaled_matrix.rgb_to_y[i] = + (yuv_matrix->rgb_to_y[i] * yuv_max + rgb_round) / rgb_max; + scaled_matrix.rgb_to_u[i] = + (yuv_matrix->rgb_to_u[i] * yuv_max + rgb_round) / rgb_max; + scaled_matrix.rgb_to_v[i] = + (yuv_matrix->rgb_to_v[i] * yuv_max + rgb_round) / rgb_max; + } + } + // Also incorporate precision change scaling. + scaled_matrix.rgb_to_y[3] = Shift(yuv_matrix->rgb_to_y[3], sfix); + scaled_matrix.rgb_to_u[3] = Shift(yuv_matrix->rgb_to_u[3], sfix); + scaled_matrix.rgb_to_v[3] = Shift(yuv_matrix->rgb_to_v[3], sfix); + + return DoSharpArgbToYuv(r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, + rgb_bit_depth, y_ptr, y_stride, u_ptr, u_stride, + v_ptr, v_stride, yuv_bit_depth, width, height, + &scaled_matrix, transfer_type); +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/sharpyuv/sharpyuv.h b/libraries/webp/sharpyuv/sharpyuv.h new file mode 100644 index 0000000000..fe95891599 --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv.h @@ -0,0 +1,172 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Sharp RGB to YUV conversion. + +#ifndef WEBP_SHARPYUV_SHARPYUV_H_ +#define WEBP_SHARPYUV_SHARPYUV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SHARPYUV_EXTERN +#ifdef WEBP_EXTERN +#define SHARPYUV_EXTERN WEBP_EXTERN +#else +// This explicitly marks library functions and allows for changing the +// signature for e.g., Windows DLL builds. +#if defined(_WIN32) && defined(WEBP_DLL) +#define SHARPYUV_EXTERN __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define SHARPYUV_EXTERN extern __attribute__((visibility("default"))) +#else +#define SHARPYUV_EXTERN extern +#endif /* defined(_WIN32) && defined(WEBP_DLL) */ +#endif /* WEBP_EXTERN */ +#endif /* SHARPYUV_EXTERN */ + +#ifndef SHARPYUV_INLINE +#ifdef WEBP_INLINE +#define SHARPYUV_INLINE WEBP_INLINE +#else +#ifndef _MSC_VER +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#define SHARPYUV_INLINE inline +#else +#define SHARPYUV_INLINE +#endif +#else +#define SHARPYUV_INLINE __forceinline +#endif /* _MSC_VER */ +#endif /* WEBP_INLINE */ +#endif /* SHARPYUV_INLINE */ + +// SharpYUV API version following the convention from semver.org +#define SHARPYUV_VERSION_MAJOR 0 +#define SHARPYUV_VERSION_MINOR 4 +#define SHARPYUV_VERSION_PATCH 0 +// Version as a uint32_t. The major number is the high 8 bits. +// The minor number is the middle 8 bits. The patch number is the low 16 bits. +#define SHARPYUV_MAKE_VERSION(MAJOR, MINOR, PATCH) \ + (((MAJOR) << 24) | ((MINOR) << 16) | (PATCH)) +#define SHARPYUV_VERSION \ + SHARPYUV_MAKE_VERSION(SHARPYUV_VERSION_MAJOR, SHARPYUV_VERSION_MINOR, \ + SHARPYUV_VERSION_PATCH) + +// Returns the library's version number, packed in hexadecimal. See +// SHARPYUV_VERSION. +SHARPYUV_EXTERN int SharpYuvGetVersion(void); + +// RGB to YUV conversion matrix, in 16 bit fixed point. +// y = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3] +// u = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3] +// v = rgb_to_v[0] * r + rgb_to_v[1] * g + rgb_to_v[2] * b + rgb_to_v[3] +// Then y, u and v values are divided by 1<<16 and rounded. +typedef struct { + int rgb_to_y[4]; + int rgb_to_u[4]; + int rgb_to_v[4]; +} SharpYuvConversionMatrix; + +typedef struct SharpYuvOptions SharpYuvOptions; + +// Enums for transfer functions, as defined in H.273, +// https://www.itu.int/rec/T-REC-H.273-202107-I/en +typedef enum SharpYuvTransferFunctionType { + // 0 is reserved + kSharpYuvTransferFunctionBt709 = 1, + // 2 is unspecified + // 3 is reserved + kSharpYuvTransferFunctionBt470M = 4, + kSharpYuvTransferFunctionBt470Bg = 5, + kSharpYuvTransferFunctionBt601 = 6, + kSharpYuvTransferFunctionSmpte240 = 7, + kSharpYuvTransferFunctionLinear = 8, + kSharpYuvTransferFunctionLog100 = 9, + kSharpYuvTransferFunctionLog100_Sqrt10 = 10, + kSharpYuvTransferFunctionIec61966 = 11, + kSharpYuvTransferFunctionBt1361 = 12, + kSharpYuvTransferFunctionSrgb = 13, + kSharpYuvTransferFunctionBt2020_10Bit = 14, + kSharpYuvTransferFunctionBt2020_12Bit = 15, + kSharpYuvTransferFunctionSmpte2084 = 16, // PQ + kSharpYuvTransferFunctionSmpte428 = 17, + kSharpYuvTransferFunctionHlg = 18, + kSharpYuvTransferFunctionNum +} SharpYuvTransferFunctionType; + +// Converts RGB to YUV420 using a downsampling algorithm that minimizes +// artefacts caused by chroma subsampling. +// This is slower than standard downsampling (averaging of 4 UV values). +// Assumes that the image will be upsampled using a bilinear filter. If nearest +// neighbor is used instead, the upsampled image might look worse than with +// standard downsampling. +// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point +// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise. +// rgb_step: distance in bytes between two horizontally adjacent pixels on the +// r, g and b channels. If rgb_bit_depth is > 8, it should be a +// multiple of 2. +// rgb_stride: distance in bytes between two vertically adjacent pixels on the +// r, g, and b channels. If rgb_bit_depth is > 8, it should be a +// multiple of 2. +// rgb_bit_depth: number of bits for each r/g/b value. One of: 8, 10, 12, 16. +// Note: 16 bit input is truncated to 14 bits before conversion to yuv. +// yuv_bit_depth: number of bits for each y/u/v value. One of: 8, 10, 12. +// y_ptr, u_ptr, v_ptr: pointers to the destination y, u and v channels. Should +// point to uint8_t buffers if yuv_bit_depth is 8, or uint16_t buffers +// otherwise. +// y_stride, u_stride, v_stride: distance in bytes between two vertically +// adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they +// should be multiples of 2. +// width, height: width and height of the image in pixels +// This function calls SharpYuvConvertWithOptions with a default transfer +// function of kSharpYuvTransferFunctionSrgb. +SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr, + const void* b_ptr, int rgb_step, + int rgb_stride, int rgb_bit_depth, + void* y_ptr, int y_stride, void* u_ptr, + int u_stride, void* v_ptr, int v_stride, + int yuv_bit_depth, int width, int height, + const SharpYuvConversionMatrix* yuv_matrix); + +struct SharpYuvOptions { + // This matrix cannot be NULL and can be initialized by + // SharpYuvComputeConversionMatrix. + const SharpYuvConversionMatrix* yuv_matrix; + SharpYuvTransferFunctionType transfer_type; +}; + +// Internal, version-checked, entry point +SHARPYUV_EXTERN int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix*, + SharpYuvOptions*, int); + +// Should always be called, to initialize a fresh SharpYuvOptions +// structure before modification. SharpYuvOptionsInit() must have succeeded +// before using the 'options' object. +static SHARPYUV_INLINE int SharpYuvOptionsInit( + const SharpYuvConversionMatrix* yuv_matrix, SharpYuvOptions* options) { + return SharpYuvOptionsInitInternal(yuv_matrix, options, SHARPYUV_VERSION); +} + +SHARPYUV_EXTERN int SharpYuvConvertWithOptions( + const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step, + int rgb_stride, int rgb_bit_depth, void* y_ptr, int y_stride, void* u_ptr, + int u_stride, void* v_ptr, int v_stride, int yuv_bit_depth, int width, + int height, const SharpYuvOptions* options); + +// TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422 +// support (it's rarely used in practice, especially for images). + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_SHARPYUV_SHARPYUV_H_ diff --git a/libraries/webp/sharpyuv/sharpyuv_cpu.c b/libraries/webp/sharpyuv/sharpyuv_cpu.c new file mode 100644 index 0000000000..29425a0c49 --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_cpu.c @@ -0,0 +1,14 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +#include "sharpyuv/sharpyuv_cpu.h" + +// Include src/dsp/cpu.c to create SharpYuvGetCPUInfo from VP8GetCPUInfo. The +// function pointer is renamed in sharpyuv_cpu.h. +#include "src/dsp/cpu.c" diff --git a/libraries/webp/sharpyuv/sharpyuv_cpu.h b/libraries/webp/sharpyuv/sharpyuv_cpu.h new file mode 100644 index 0000000000..176ca3eb16 --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_cpu.h @@ -0,0 +1,22 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +#ifndef WEBP_SHARPYUV_SHARPYUV_CPU_H_ +#define WEBP_SHARPYUV_SHARPYUV_CPU_H_ + +#include "sharpyuv/sharpyuv.h" + +// Avoid exporting SharpYuvGetCPUInfo in shared object / DLL builds. +// SharpYuvInit() replaces the use of the function pointer. +#undef WEBP_EXTERN +#define WEBP_EXTERN extern +#define VP8GetCPUInfo SharpYuvGetCPUInfo +#include "src/dsp/cpu.h" + +#endif // WEBP_SHARPYUV_SHARPYUV_CPU_H_ diff --git a/libraries/webp/sharpyuv/sharpyuv_csp.c b/libraries/webp/sharpyuv/sharpyuv_csp.c new file mode 100644 index 0000000000..0ad22be945 --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_csp.c @@ -0,0 +1,110 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Colorspace utilities. + +#include "sharpyuv/sharpyuv_csp.h" + +#include +#include +#include + +static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); } + +void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space, + SharpYuvConversionMatrix* matrix) { + const float kr = yuv_color_space->kr; + const float kb = yuv_color_space->kb; + const float kg = 1.0f - kr - kb; + const float cr = 0.5f / (1.0f - kb); + const float cb = 0.5f / (1.0f - kr); + + const int shift = yuv_color_space->bit_depth - 8; + + const float denom = (float)((1 << yuv_color_space->bit_depth) - 1); + float scale_y = 1.0f; + float add_y = 0.0f; + float scale_u = cr; + float scale_v = cb; + float add_uv = (float)(128 << shift); + assert(yuv_color_space->bit_depth >= 8); + + if (yuv_color_space->range == kSharpYuvRangeLimited) { + scale_y *= (219 << shift) / denom; + scale_u *= (224 << shift) / denom; + scale_v *= (224 << shift) / denom; + add_y = (float)(16 << shift); + } + + matrix->rgb_to_y[0] = ToFixed16(kr * scale_y); + matrix->rgb_to_y[1] = ToFixed16(kg * scale_y); + matrix->rgb_to_y[2] = ToFixed16(kb * scale_y); + matrix->rgb_to_y[3] = ToFixed16(add_y); + + matrix->rgb_to_u[0] = ToFixed16(-kr * scale_u); + matrix->rgb_to_u[1] = ToFixed16(-kg * scale_u); + matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scale_u); + matrix->rgb_to_u[3] = ToFixed16(add_uv); + + matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scale_v); + matrix->rgb_to_v[1] = ToFixed16(-kg * scale_v); + matrix->rgb_to_v[2] = ToFixed16(-kb * scale_v); + matrix->rgb_to_v[3] = ToFixed16(add_uv); +} + +// Matrices are in YUV_FIX fixed point precision. +// WebP's matrix, similar but not identical to kRec601LimitedMatrix. +static const SharpYuvConversionMatrix kWebpMatrix = { + {16839, 33059, 6420, 16 << 16}, + {-9719, -19081, 28800, 128 << 16}, + {28800, -24116, -4684, 128 << 16}, +}; +// Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeLimited +static const SharpYuvConversionMatrix kRec601LimitedMatrix = { + {16829, 33039, 6416, 16 << 16}, + {-9714, -19071, 28784, 128 << 16}, + {28784, -24103, -4681, 128 << 16}, +}; +// Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeFull +static const SharpYuvConversionMatrix kRec601FullMatrix = { + {19595, 38470, 7471, 0}, + {-11058, -21710, 32768, 128 << 16}, + {32768, -27439, -5329, 128 << 16}, +}; +// Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeLimited +static const SharpYuvConversionMatrix kRec709LimitedMatrix = { + {11966, 40254, 4064, 16 << 16}, + {-6596, -22189, 28784, 128 << 16}, + {28784, -26145, -2639, 128 << 16}, +}; +// Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeFull +static const SharpYuvConversionMatrix kRec709FullMatrix = { + {13933, 46871, 4732, 0}, + {-7509, -25259, 32768, 128 << 16}, + {32768, -29763, -3005, 128 << 16}, +}; + +const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix( + SharpYuvMatrixType matrix_type) { + switch (matrix_type) { + case kSharpYuvMatrixWebp: + return &kWebpMatrix; + case kSharpYuvMatrixRec601Limited: + return &kRec601LimitedMatrix; + case kSharpYuvMatrixRec601Full: + return &kRec601FullMatrix; + case kSharpYuvMatrixRec709Limited: + return &kRec709LimitedMatrix; + case kSharpYuvMatrixRec709Full: + return &kRec709FullMatrix; + case kSharpYuvMatrixNum: + return NULL; + } + return NULL; +} diff --git a/libraries/webp/sharpyuv/sharpyuv_csp.h b/libraries/webp/sharpyuv/sharpyuv_csp.h new file mode 100644 index 0000000000..3214e3ac60 --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_csp.h @@ -0,0 +1,60 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Colorspace utilities. + +#ifndef WEBP_SHARPYUV_SHARPYUV_CSP_H_ +#define WEBP_SHARPYUV_SHARPYUV_CSP_H_ + +#include "sharpyuv/sharpyuv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Range of YUV values. +typedef enum { + kSharpYuvRangeFull, // YUV values between [0;255] (for 8 bit) + kSharpYuvRangeLimited // Y in [16;235], YUV in [16;240] (for 8 bit) +} SharpYuvRange; + +// Constants that define a YUV color space. +typedef struct { + // Kr and Kb are defined such that: + // Y = Kr * r + Kg * g + Kb * b where Kg = 1 - Kr - Kb. + float kr; + float kb; + int bit_depth; // 8, 10 or 12 + SharpYuvRange range; +} SharpYuvColorSpace; + +// Fills in 'matrix' for the given YUVColorSpace. +SHARPYUV_EXTERN void SharpYuvComputeConversionMatrix( + const SharpYuvColorSpace* yuv_color_space, + SharpYuvConversionMatrix* matrix); + +// Enums for precomputed conversion matrices. +typedef enum { + kSharpYuvMatrixWebp = 0, + kSharpYuvMatrixRec601Limited, + kSharpYuvMatrixRec601Full, + kSharpYuvMatrixRec709Limited, + kSharpYuvMatrixRec709Full, + kSharpYuvMatrixNum +} SharpYuvMatrixType; + +// Returns a pointer to a matrix for one of the predefined colorspaces. +SHARPYUV_EXTERN const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix( + SharpYuvMatrixType matrix_type); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_SHARPYUV_SHARPYUV_CSP_H_ diff --git a/libraries/webp/sharpyuv/sharpyuv_dsp.c b/libraries/webp/sharpyuv/sharpyuv_dsp.c new file mode 100644 index 0000000000..b539d61e13 --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_dsp.c @@ -0,0 +1,104 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions for Sharp YUV. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "sharpyuv/sharpyuv_dsp.h" + +#include +#include + +#include "sharpyuv/sharpyuv_cpu.h" +#include "include/webp/types.h" + +//----------------------------------------------------------------------------- + +#if !WEBP_NEON_OMIT_C_CODE +static uint16_t clip(int v, int max) { + return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; +} + +static uint64_t SharpYuvUpdateY_C(const uint16_t* ref, const uint16_t* src, + uint16_t* dst, int len, int bit_depth) { + uint64_t diff = 0; + int i; + const int max_y = (1 << bit_depth) - 1; + for (i = 0; i < len; ++i) { + const int diff_y = ref[i] - src[i]; + const int new_y = (int)dst[i] + diff_y; + dst[i] = clip(new_y, max_y); + diff += (uint64_t)abs(diff_y); + } + return diff; +} + +static void SharpYuvUpdateRGB_C(const int16_t* ref, const int16_t* src, + int16_t* dst, int len) { + int i; + for (i = 0; i < len; ++i) { + const int diff_uv = ref[i] - src[i]; + dst[i] += diff_uv; + } +} + +static void SharpYuvFilterRow_C(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth) { + int i; + const int max_y = (1 << bit_depth) - 1; + for (i = 0; i < len; ++i, ++A, ++B) { + const int v0 = (A[0] * 9 + A[1] * 3 + B[0] * 3 + B[1] + 8) >> 4; + const int v1 = (A[1] * 9 + A[0] * 3 + B[1] * 3 + B[0] + 8) >> 4; + out[2 * i + 0] = clip(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip(best_y[2 * i + 1] + v1, max_y); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//----------------------------------------------------------------------------- + +uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref, + uint16_t* dst, int len, int bit_depth); +void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, int16_t* dst, + int len); +void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, int bit_depth); + +extern VP8CPUInfo SharpYuvGetCPUInfo; +extern void InitSharpYuvSSE2(void); +extern void InitSharpYuvNEON(void); + +void SharpYuvInitDsp(void) { +#if !WEBP_NEON_OMIT_C_CODE + SharpYuvUpdateY = SharpYuvUpdateY_C; + SharpYuvUpdateRGB = SharpYuvUpdateRGB_C; + SharpYuvFilterRow = SharpYuvFilterRow_C; +#endif + + if (SharpYuvGetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (SharpYuvGetCPUInfo(kSSE2)) { + InitSharpYuvSSE2(); + } +#endif // WEBP_HAVE_SSE2 + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (SharpYuvGetCPUInfo != NULL && SharpYuvGetCPUInfo(kNEON))) { + InitSharpYuvNEON(); + } +#endif // WEBP_HAVE_NEON + + assert(SharpYuvUpdateY != NULL); + assert(SharpYuvUpdateRGB != NULL); + assert(SharpYuvFilterRow != NULL); +} diff --git a/libraries/webp/sharpyuv/sharpyuv_dsp.h b/libraries/webp/sharpyuv/sharpyuv_dsp.h new file mode 100644 index 0000000000..1822375015 --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_dsp.h @@ -0,0 +1,28 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions for Sharp YUV. + +#ifndef WEBP_SHARPYUV_SHARPYUV_DSP_H_ +#define WEBP_SHARPYUV_SHARPYUV_DSP_H_ + +#include "sharpyuv/sharpyuv_cpu.h" +#include "include/webp/types.h" + +extern uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref, + uint16_t* dst, int len, int bit_depth); +extern void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, + int16_t* dst, int len); +extern void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth); + +void SharpYuvInitDsp(void); + +#endif // WEBP_SHARPYUV_SHARPYUV_DSP_H_ diff --git a/libraries/webp/sharpyuv/sharpyuv_gamma.c b/libraries/webp/sharpyuv/sharpyuv_gamma.c new file mode 100644 index 0000000000..4c79d634ff --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_gamma.c @@ -0,0 +1,419 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Gamma correction utilities. + +#include "sharpyuv/sharpyuv_gamma.h" + +#include +#include +#include + +#include "include/webp/types.h" + +// Gamma correction compensates loss of resolution during chroma subsampling. +// Size of pre-computed table for converting from gamma to linear. +#define GAMMA_TO_LINEAR_TAB_BITS 10 +#define GAMMA_TO_LINEAR_TAB_SIZE (1 << GAMMA_TO_LINEAR_TAB_BITS) +static uint32_t kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE + 2]; +#define LINEAR_TO_GAMMA_TAB_BITS 9 +#define LINEAR_TO_GAMMA_TAB_SIZE (1 << LINEAR_TO_GAMMA_TAB_BITS) +static uint32_t kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 2]; + +static const double kGammaF = 1. / 0.45; +#define GAMMA_TO_LINEAR_BITS 16 + +static volatile int kGammaTablesSOk = 0; +void SharpYuvInitGammaTables(void) { + assert(GAMMA_TO_LINEAR_BITS <= 16); + if (!kGammaTablesSOk) { + int v; + const double a = 0.09929682680944; + const double thresh = 0.018053968510807; + const double final_scale = 1 << GAMMA_TO_LINEAR_BITS; + // Precompute gamma to linear table. + { + const double norm = 1. / GAMMA_TO_LINEAR_TAB_SIZE; + const double a_rec = 1. / (1. + a); + for (v = 0; v <= GAMMA_TO_LINEAR_TAB_SIZE; ++v) { + const double g = norm * v; + double value; + if (g <= thresh * 4.5) { + value = g / 4.5; + } else { + value = pow(a_rec * (g + a), kGammaF); + } + kGammaToLinearTabS[v] = (uint32_t)(value * final_scale + .5); + } + // to prevent small rounding errors to cause read-overflow: + kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE + 1] = + kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE]; + } + // Precompute linear to gamma table. + { + const double scale = 1. / LINEAR_TO_GAMMA_TAB_SIZE; + for (v = 0; v <= LINEAR_TO_GAMMA_TAB_SIZE; ++v) { + const double g = scale * v; + double value; + if (g <= thresh) { + value = 4.5 * g; + } else { + value = (1. + a) * pow(g, 1. / kGammaF) - a; + } + kLinearToGammaTabS[v] = + (uint32_t)(final_scale * value + 0.5); + } + // to prevent small rounding errors to cause read-overflow: + kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 1] = + kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE]; + } + kGammaTablesSOk = 1; + } +} + +static WEBP_INLINE int Shift(int v, int shift) { + return (shift >= 0) ? (v << shift) : (v >> -shift); +} + +static WEBP_INLINE uint32_t FixedPointInterpolation(int v, uint32_t* tab, + int tab_pos_shift_right, + int tab_value_shift) { + const uint32_t tab_pos = Shift(v, -tab_pos_shift_right); + // fractional part, in 'tab_pos_shift' fixed-point precision + const uint32_t x = v - (tab_pos << tab_pos_shift_right); // fractional part + // v0 / v1 are in kGammaToLinearBits fixed-point precision (range [0..1]) + const uint32_t v0 = Shift(tab[tab_pos + 0], tab_value_shift); + const uint32_t v1 = Shift(tab[tab_pos + 1], tab_value_shift); + // Final interpolation. + const uint32_t v2 = (v1 - v0) * x; // note: v1 >= v0. + const int half = + (tab_pos_shift_right > 0) ? 1 << (tab_pos_shift_right - 1) : 0; + const uint32_t result = v0 + ((v2 + half) >> tab_pos_shift_right); + return result; +} + +static uint32_t ToLinearSrgb(uint16_t v, int bit_depth) { + const int shift = GAMMA_TO_LINEAR_TAB_BITS - bit_depth; + if (shift > 0) { + return kGammaToLinearTabS[v << shift]; + } + return FixedPointInterpolation(v, kGammaToLinearTabS, -shift, 0); +} + +static uint16_t FromLinearSrgb(uint32_t value, int bit_depth) { + return FixedPointInterpolation( + value, kLinearToGammaTabS, + (GAMMA_TO_LINEAR_BITS - LINEAR_TO_GAMMA_TAB_BITS), + bit_depth - GAMMA_TO_LINEAR_BITS); +} + +//////////////////////////////////////////////////////////////////////////////// + +#define CLAMP(x, low, high) \ + (((x) < (low)) ? (low) : (((high) < (x)) ? (high) : (x))) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +static WEBP_INLINE float Roundf(float x) { + if (x < 0) + return (float)ceil((double)(x - 0.5f)); + else + return (float)floor((double)(x + 0.5f)); +} + +static WEBP_INLINE float Powf(float base, float exp) { + return (float)pow((double)base, (double)exp); +} + +static WEBP_INLINE float Log10f(float x) { return (float)log10((double)x); } + +static float ToLinear709(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinear709(float linear) { + if (linear < 0.f) { + return 0.f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } else if (linear < 1.f) { + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; + } + return 1.f; +} + +static float ToLinear470M(float gamma) { + return Powf(CLAMP(gamma, 0.f, 1.f), 2.2f); +} + +static float FromLinear470M(float linear) { + return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.2f); +} + +static float ToLinear470Bg(float gamma) { + return Powf(CLAMP(gamma, 0.f, 1.f), 2.8f); +} + +static float FromLinear470Bg(float linear) { + return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.8f); +} + +static float ToLinearSmpte240(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma < 4.f * 0.022821585529445f) { + return gamma / 4.f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.111572195921731f) / 1.111572195921731f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinearSmpte240(float linear) { + if (linear < 0.f) { + return 0.f; + } else if (linear < 0.022821585529445f) { + return linear * 4.f; + } else if (linear < 1.f) { + return 1.111572195921731f * Powf(linear, 0.45f) - 0.111572195921731f; + } + return 1.f; +} + +static float ToLinearLog100(float gamma) { + // The function is non-bijective so choose the middle of [0, 0.01]. + const float mid_interval = 0.01f / 2.f; + return (gamma <= 0.0f) ? mid_interval + : Powf(10.0f, 2.f * (MIN(gamma, 1.f) - 1.0f)); +} + +static float FromLinearLog100(float linear) { + return (linear < 0.01f) ? 0.0f : 1.0f + Log10f(MIN(linear, 1.f)) / 2.0f; +} + +static float ToLinearLog100Sqrt10(float gamma) { + // The function is non-bijective so choose the middle of [0, 0.00316227766f[. + const float mid_interval = 0.00316227766f / 2.f; + return (gamma <= 0.0f) ? mid_interval + : Powf(10.0f, 2.5f * (MIN(gamma, 1.f) - 1.0f)); +} + +static float FromLinearLog100Sqrt10(float linear) { + return (linear < 0.00316227766f) ? 0.0f + : 1.0f + Log10f(MIN(linear, 1.f)) / 2.5f; +} + +static float ToLinearIec61966(float gamma) { + if (gamma <= -4.5f * 0.018053968510807f) { + return Powf((-gamma + 0.09929682680944f) / -1.09929682680944f, 1.f / 0.45f); + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); +} + +static float FromLinearIec61966(float linear) { + if (linear <= -0.018053968510807f) { + return -1.09929682680944f * Powf(-linear, 0.45f) + 0.09929682680944f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; +} + +static float ToLinearBt1361(float gamma) { + if (gamma < -0.25f) { + return -0.25f; + } else if (gamma < 0.f) { + return Powf((gamma - 0.02482420670236f) / -0.27482420670236f, 1.f / 0.45f) / + -4.f; + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinearBt1361(float linear) { + if (linear < -0.25f) { + return -0.25f; + } else if (linear < 0.f) { + return -0.27482420670236f * Powf(-4.f * linear, 0.45f) + 0.02482420670236f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } else if (linear < 1.f) { + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; + } + return 1.f; +} + +static float ToLinearPq(float gamma) { + if (gamma > 0.f) { + const float pow_gamma = Powf(gamma, 32.f / 2523.f); + const float num = MAX(pow_gamma - 107.f / 128.f, 0.0f); + const float den = MAX(2413.f / 128.f - 2392.f / 128.f * pow_gamma, FLT_MIN); + return Powf(num / den, 4096.f / 653.f); + } + return 0.f; +} + +static float FromLinearPq(float linear) { + if (linear > 0.f) { + const float pow_linear = Powf(linear, 653.f / 4096.f); + const float num = 107.f / 128.f + 2413.f / 128.f * pow_linear; + const float den = 1.0f + 2392.f / 128.f * pow_linear; + return Powf(num / den, 2523.f / 32.f); + } + return 0.f; +} + +static float ToLinearSmpte428(float gamma) { + return Powf(MAX(gamma, 0.f), 2.6f) / 0.91655527974030934f; +} + +static float FromLinearSmpte428(float linear) { + return Powf(0.91655527974030934f * MAX(linear, 0.f), 1.f / 2.6f); +} + +// Conversion in BT.2100 requires RGB info. Simplify to gamma correction here. +static float ToLinearHlg(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma <= 0.5f) { + return Powf((gamma * gamma) * (1.f / 3.f), 1.2f); + } + return Powf((expf((gamma - 0.55991073f) / 0.17883277f) + 0.28466892f) / 12.0f, + 1.2f); +} + +static float FromLinearHlg(float linear) { + linear = Powf(linear, 1.f / 1.2f); + if (linear < 0.f) { + return 0.f; + } else if (linear <= (1.f / 12.f)) { + return sqrtf(3.f * linear); + } + return 0.17883277f * logf(12.f * linear - 0.28466892f) + 0.55991073f; +} + +uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type) { + float v_float, linear; + if (transfer_type == kSharpYuvTransferFunctionSrgb) { + return ToLinearSrgb(v, bit_depth); + } + v_float = (float)v / ((1 << bit_depth) - 1); + switch (transfer_type) { + case kSharpYuvTransferFunctionBt709: + case kSharpYuvTransferFunctionBt601: + case kSharpYuvTransferFunctionBt2020_10Bit: + case kSharpYuvTransferFunctionBt2020_12Bit: + linear = ToLinear709(v_float); + break; + case kSharpYuvTransferFunctionBt470M: + linear = ToLinear470M(v_float); + break; + case kSharpYuvTransferFunctionBt470Bg: + linear = ToLinear470Bg(v_float); + break; + case kSharpYuvTransferFunctionSmpte240: + linear = ToLinearSmpte240(v_float); + break; + case kSharpYuvTransferFunctionLinear: + return v; + case kSharpYuvTransferFunctionLog100: + linear = ToLinearLog100(v_float); + break; + case kSharpYuvTransferFunctionLog100_Sqrt10: + linear = ToLinearLog100Sqrt10(v_float); + break; + case kSharpYuvTransferFunctionIec61966: + linear = ToLinearIec61966(v_float); + break; + case kSharpYuvTransferFunctionBt1361: + linear = ToLinearBt1361(v_float); + break; + case kSharpYuvTransferFunctionSmpte2084: + linear = ToLinearPq(v_float); + break; + case kSharpYuvTransferFunctionSmpte428: + linear = ToLinearSmpte428(v_float); + break; + case kSharpYuvTransferFunctionHlg: + linear = ToLinearHlg(v_float); + break; + default: + assert(0); + linear = 0; + break; + } + return (uint32_t)Roundf(linear * ((1 << 16) - 1)); +} + +uint16_t SharpYuvLinearToGamma(uint32_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type) { + float v_float, linear; + if (transfer_type == kSharpYuvTransferFunctionSrgb) { + return FromLinearSrgb(v, bit_depth); + } + v_float = (float)v / ((1 << 16) - 1); + switch (transfer_type) { + case kSharpYuvTransferFunctionBt709: + case kSharpYuvTransferFunctionBt601: + case kSharpYuvTransferFunctionBt2020_10Bit: + case kSharpYuvTransferFunctionBt2020_12Bit: + linear = FromLinear709(v_float); + break; + case kSharpYuvTransferFunctionBt470M: + linear = FromLinear470M(v_float); + break; + case kSharpYuvTransferFunctionBt470Bg: + linear = FromLinear470Bg(v_float); + break; + case kSharpYuvTransferFunctionSmpte240: + linear = FromLinearSmpte240(v_float); + break; + case kSharpYuvTransferFunctionLinear: + return v; + case kSharpYuvTransferFunctionLog100: + linear = FromLinearLog100(v_float); + break; + case kSharpYuvTransferFunctionLog100_Sqrt10: + linear = FromLinearLog100Sqrt10(v_float); + break; + case kSharpYuvTransferFunctionIec61966: + linear = FromLinearIec61966(v_float); + break; + case kSharpYuvTransferFunctionBt1361: + linear = FromLinearBt1361(v_float); + break; + case kSharpYuvTransferFunctionSmpte2084: + linear = FromLinearPq(v_float); + break; + case kSharpYuvTransferFunctionSmpte428: + linear = FromLinearSmpte428(v_float); + break; + case kSharpYuvTransferFunctionHlg: + linear = FromLinearHlg(v_float); + break; + default: + assert(0); + linear = 0; + break; + } + return (uint16_t)Roundf(linear * ((1 << bit_depth) - 1)); +} diff --git a/libraries/webp/sharpyuv/sharpyuv_gamma.h b/libraries/webp/sharpyuv/sharpyuv_gamma.h new file mode 100644 index 0000000000..d5215069ed --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_gamma.h @@ -0,0 +1,38 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Gamma correction utilities. + +#ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ +#define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ + +#include "sharpyuv/sharpyuv.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Initializes precomputed tables. Must be called once before calling +// SharpYuvGammaToLinear or SharpYuvLinearToGamma. +void SharpYuvInitGammaTables(void); + +// Converts a 'bit_depth'-bit gamma color value to a 16-bit linear value. +uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type); + +// Converts a 16-bit linear color value to a 'bit_depth'-bit gamma value. +uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth, + SharpYuvTransferFunctionType transfer_type); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ diff --git a/libraries/webp/sharpyuv/sharpyuv_neon.c b/libraries/webp/sharpyuv/sharpyuv_neon.c new file mode 100644 index 0000000000..5840914865 --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_neon.c @@ -0,0 +1,181 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions for Sharp YUV. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "sharpyuv/sharpyuv_dsp.h" + +#if defined(WEBP_USE_NEON) +#include +#include +#include + +static uint16_t clip_NEON(int v, int max) { + return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; +} + +static uint64_t SharpYuvUpdateY_NEON(const uint16_t* ref, const uint16_t* src, + uint16_t* dst, int len, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const int16x8_t zero = vdupq_n_s16(0); + const int16x8_t max = vdupq_n_s16(max_y); + uint64x2_t sum = vdupq_n_u64(0); + uint64_t diff; + + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t A = vreinterpretq_s16_u16(vld1q_u16(ref + i)); + const int16x8_t B = vreinterpretq_s16_u16(vld1q_u16(src + i)); + const int16x8_t C = vreinterpretq_s16_u16(vld1q_u16(dst + i)); + const int16x8_t D = vsubq_s16(A, B); // diff_y + const int16x8_t F = vaddq_s16(C, D); // new_y + const uint16x8_t H = + vreinterpretq_u16_s16(vmaxq_s16(vminq_s16(F, max), zero)); + const int16x8_t I = vabsq_s16(D); // abs(diff_y) + vst1q_u16(dst + i, H); + sum = vpadalq_u32(sum, vpaddlq_u16(vreinterpretq_u16_s16(I))); + } + diff = vgetq_lane_u64(sum, 0) + vgetq_lane_u64(sum, 1); + for (; i < len; ++i) { + const int diff_y = ref[i] - src[i]; + const int new_y = (int)(dst[i]) + diff_y; + dst[i] = clip_NEON(new_y, max_y); + diff += (uint64_t)(abs(diff_y)); + } + return diff; +} + +static void SharpYuvUpdateRGB_NEON(const int16_t* ref, const int16_t* src, + int16_t* dst, int len) { + int i; + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t A = vld1q_s16(ref + i); + const int16x8_t B = vld1q_s16(src + i); + const int16x8_t C = vld1q_s16(dst + i); + const int16x8_t D = vsubq_s16(A, B); // diff_uv + const int16x8_t E = vaddq_s16(C, D); // new_uv + vst1q_s16(dst + i, E); + } + for (; i < len; ++i) { + const int diff_uv = ref[i] - src[i]; + dst[i] += diff_uv; + } +} + +static void SharpYuvFilterRow16_NEON(const int16_t* A, const int16_t* B, + int len, const uint16_t* best_y, + uint16_t* out, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const int16x8_t max = vdupq_n_s16(max_y); + const int16x8_t zero = vdupq_n_s16(0); + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t a0 = vld1q_s16(A + i + 0); + const int16x8_t a1 = vld1q_s16(A + i + 1); + const int16x8_t b0 = vld1q_s16(B + i + 0); + const int16x8_t b1 = vld1q_s16(B + i + 1); + const int16x8_t a0b1 = vaddq_s16(a0, b1); + const int16x8_t a1b0 = vaddq_s16(a1, b0); + const int16x8_t a0a1b0b1 = vaddq_s16(a0b1, a1b0); // A0+A1+B0+B1 + const int16x8_t a0b1_2 = vaddq_s16(a0b1, a0b1); // 2*(A0+B1) + const int16x8_t a1b0_2 = vaddq_s16(a1b0, a1b0); // 2*(A1+B0) + const int16x8_t c0 = vshrq_n_s16(vaddq_s16(a0b1_2, a0a1b0b1), 3); + const int16x8_t c1 = vshrq_n_s16(vaddq_s16(a1b0_2, a0a1b0b1), 3); + const int16x8_t e0 = vrhaddq_s16(c1, a0); + const int16x8_t e1 = vrhaddq_s16(c0, a1); + const int16x8x2_t f = vzipq_s16(e0, e1); + const int16x8_t g0 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 0)); + const int16x8_t g1 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 8)); + const int16x8_t h0 = vaddq_s16(g0, f.val[0]); + const int16x8_t h1 = vaddq_s16(g1, f.val[1]); + const int16x8_t i0 = vmaxq_s16(vminq_s16(h0, max), zero); + const int16x8_t i1 = vmaxq_s16(vminq_s16(h1, max), zero); + vst1q_u16(out + 2 * i + 0, vreinterpretq_u16_s16(i0)); + vst1q_u16(out + 2 * i + 8, vreinterpretq_u16_s16(i1)); + } + for (; i < len; ++i) { + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_NEON(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip_NEON(best_y[2 * i + 1] + v1, max_y); + } +} + +static void SharpYuvFilterRow32_NEON(const int16_t* A, const int16_t* B, + int len, const uint16_t* best_y, + uint16_t* out, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const uint16x8_t max = vdupq_n_u16(max_y); + for (i = 0; i + 4 <= len; i += 4) { + const int16x4_t a0 = vld1_s16(A + i + 0); + const int16x4_t a1 = vld1_s16(A + i + 1); + const int16x4_t b0 = vld1_s16(B + i + 0); + const int16x4_t b1 = vld1_s16(B + i + 1); + const int32x4_t a0b1 = vaddl_s16(a0, b1); + const int32x4_t a1b0 = vaddl_s16(a1, b0); + const int32x4_t a0a1b0b1 = vaddq_s32(a0b1, a1b0); // A0+A1+B0+B1 + const int32x4_t a0b1_2 = vaddq_s32(a0b1, a0b1); // 2*(A0+B1) + const int32x4_t a1b0_2 = vaddq_s32(a1b0, a1b0); // 2*(A1+B0) + const int32x4_t c0 = vshrq_n_s32(vaddq_s32(a0b1_2, a0a1b0b1), 3); + const int32x4_t c1 = vshrq_n_s32(vaddq_s32(a1b0_2, a0a1b0b1), 3); + const int32x4_t e0 = vrhaddq_s32(c1, vmovl_s16(a0)); + const int32x4_t e1 = vrhaddq_s32(c0, vmovl_s16(a1)); + const int32x4x2_t f = vzipq_s32(e0, e1); + + const int16x8_t g = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i)); + const int32x4_t h0 = vaddw_s16(f.val[0], vget_low_s16(g)); + const int32x4_t h1 = vaddw_s16(f.val[1], vget_high_s16(g)); + const uint16x8_t i_16 = vcombine_u16(vqmovun_s32(h0), vqmovun_s32(h1)); + const uint16x8_t i_clamped = vminq_u16(i_16, max); + vst1q_u16(out + 2 * i + 0, i_clamped); + } + for (; i < len; ++i) { + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_NEON(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip_NEON(best_y[2 * i + 1] + v1, max_y); + } +} + +static void SharpYuvFilterRow_NEON(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth) { + if (bit_depth <= 10) { + SharpYuvFilterRow16_NEON(A, B, len, best_y, out, bit_depth); + } else { + SharpYuvFilterRow32_NEON(A, B, len, best_y, out, bit_depth); + } +} + +//------------------------------------------------------------------------------ + +extern void InitSharpYuvNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvNEON(void) { + SharpYuvUpdateY = SharpYuvUpdateY_NEON; + SharpYuvUpdateRGB = SharpYuvUpdateRGB_NEON; + SharpYuvFilterRow = SharpYuvFilterRow_NEON; +} + +#else // !WEBP_USE_NEON + +extern void InitSharpYuvNEON(void); + +void InitSharpYuvNEON(void) {} + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/sharpyuv/sharpyuv_sse2.c b/libraries/webp/sharpyuv/sharpyuv_sse2.c new file mode 100644 index 0000000000..9744d1bb6c --- /dev/null +++ b/libraries/webp/sharpyuv/sharpyuv_sse2.c @@ -0,0 +1,201 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions for Sharp YUV. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "sharpyuv/sharpyuv_dsp.h" + +#if defined(WEBP_USE_SSE2) +#include +#include + +static uint16_t clip_SSE2(int v, int max) { + return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; +} + +static uint64_t SharpYuvUpdateY_SSE2(const uint16_t* ref, const uint16_t* src, + uint16_t* dst, int len, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + uint64_t diff = 0; + uint32_t tmp[4]; + int i; + const __m128i zero = _mm_setzero_si128(); + const __m128i max = _mm_set1_epi16(max_y); + const __m128i one = _mm_set1_epi16(1); + __m128i sum = zero; + + for (i = 0; i + 8 <= len; i += 8) { + const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i)); + const __m128i B = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i)); + const __m128i D = _mm_sub_epi16(A, B); // diff_y + const __m128i E = _mm_cmpgt_epi16(zero, D); // sign (-1 or 0) + const __m128i F = _mm_add_epi16(C, D); // new_y + const __m128i G = _mm_or_si128(E, one); // -1 or 1 + const __m128i H = _mm_max_epi16(_mm_min_epi16(F, max), zero); + const __m128i I = _mm_madd_epi16(D, G); // sum(abs(...)) + _mm_storeu_si128((__m128i*)(dst + i), H); + sum = _mm_add_epi32(sum, I); + } + _mm_storeu_si128((__m128i*)tmp, sum); + diff = tmp[3] + tmp[2] + tmp[1] + tmp[0]; + for (; i < len; ++i) { + const int diff_y = ref[i] - src[i]; + const int new_y = (int)dst[i] + diff_y; + dst[i] = clip_SSE2(new_y, max_y); + diff += (uint64_t)abs(diff_y); + } + return diff; +} + +static void SharpYuvUpdateRGB_SSE2(const int16_t* ref, const int16_t* src, + int16_t* dst, int len) { + int i = 0; + for (i = 0; i + 8 <= len; i += 8) { + const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i)); + const __m128i B = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i)); + const __m128i D = _mm_sub_epi16(A, B); // diff_uv + const __m128i E = _mm_add_epi16(C, D); // new_uv + _mm_storeu_si128((__m128i*)(dst + i), E); + } + for (; i < len; ++i) { + const int diff_uv = ref[i] - src[i]; + dst[i] += diff_uv; + } +} + +static void SharpYuvFilterRow16_SSE2(const int16_t* A, const int16_t* B, + int len, const uint16_t* best_y, + uint16_t* out, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const __m128i kCst8 = _mm_set1_epi16(8); + const __m128i max = _mm_set1_epi16(max_y); + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i + 8 <= len; i += 8) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(A + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(A + i + 1)); + const __m128i b0 = _mm_loadu_si128((const __m128i*)(B + i + 0)); + const __m128i b1 = _mm_loadu_si128((const __m128i*)(B + i + 1)); + const __m128i a0b1 = _mm_add_epi16(a0, b1); + const __m128i a1b0 = _mm_add_epi16(a1, b0); + const __m128i a0a1b0b1 = _mm_add_epi16(a0b1, a1b0); // A0+A1+B0+B1 + const __m128i a0a1b0b1_8 = _mm_add_epi16(a0a1b0b1, kCst8); + const __m128i a0b1_2 = _mm_add_epi16(a0b1, a0b1); // 2*(A0+B1) + const __m128i a1b0_2 = _mm_add_epi16(a1b0, a1b0); // 2*(A1+B0) + const __m128i c0 = _mm_srai_epi16(_mm_add_epi16(a0b1_2, a0a1b0b1_8), 3); + const __m128i c1 = _mm_srai_epi16(_mm_add_epi16(a1b0_2, a0a1b0b1_8), 3); + const __m128i d0 = _mm_add_epi16(c1, a0); + const __m128i d1 = _mm_add_epi16(c0, a1); + const __m128i e0 = _mm_srai_epi16(d0, 1); + const __m128i e1 = _mm_srai_epi16(d1, 1); + const __m128i f0 = _mm_unpacklo_epi16(e0, e1); + const __m128i f1 = _mm_unpackhi_epi16(e0, e1); + const __m128i g0 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0)); + const __m128i g1 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 8)); + const __m128i h0 = _mm_add_epi16(g0, f0); + const __m128i h1 = _mm_add_epi16(g1, f1); + const __m128i i0 = _mm_max_epi16(_mm_min_epi16(h0, max), zero); + const __m128i i1 = _mm_max_epi16(_mm_min_epi16(h1, max), zero); + _mm_storeu_si128((__m128i*)(out + 2 * i + 0), i0); + _mm_storeu_si128((__m128i*)(out + 2 * i + 8), i1); + } + for (; i < len; ++i) { + // (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 = + // = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4 + // We reuse the common sub-expressions. + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_SSE2(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip_SSE2(best_y[2 * i + 1] + v1, max_y); + } +} + +static WEBP_INLINE __m128i s16_to_s32(__m128i in) { + return _mm_srai_epi32(_mm_unpacklo_epi16(in, in), 16); +} + +static void SharpYuvFilterRow32_SSE2(const int16_t* A, const int16_t* B, + int len, const uint16_t* best_y, + uint16_t* out, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const __m128i kCst8 = _mm_set1_epi32(8); + const __m128i max = _mm_set1_epi16(max_y); + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i + 4 <= len; i += 4) { + const __m128i a0 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(A + i + 0))); + const __m128i a1 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(A + i + 1))); + const __m128i b0 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(B + i + 0))); + const __m128i b1 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(B + i + 1))); + const __m128i a0b1 = _mm_add_epi32(a0, b1); + const __m128i a1b0 = _mm_add_epi32(a1, b0); + const __m128i a0a1b0b1 = _mm_add_epi32(a0b1, a1b0); // A0+A1+B0+B1 + const __m128i a0a1b0b1_8 = _mm_add_epi32(a0a1b0b1, kCst8); + const __m128i a0b1_2 = _mm_add_epi32(a0b1, a0b1); // 2*(A0+B1) + const __m128i a1b0_2 = _mm_add_epi32(a1b0, a1b0); // 2*(A1+B0) + const __m128i c0 = _mm_srai_epi32(_mm_add_epi32(a0b1_2, a0a1b0b1_8), 3); + const __m128i c1 = _mm_srai_epi32(_mm_add_epi32(a1b0_2, a0a1b0b1_8), 3); + const __m128i d0 = _mm_add_epi32(c1, a0); + const __m128i d1 = _mm_add_epi32(c0, a1); + const __m128i e0 = _mm_srai_epi32(d0, 1); + const __m128i e1 = _mm_srai_epi32(d1, 1); + const __m128i f0 = _mm_unpacklo_epi32(e0, e1); + const __m128i f1 = _mm_unpackhi_epi32(e0, e1); + const __m128i g = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0)); + const __m128i h_16 = _mm_add_epi16(g, _mm_packs_epi32(f0, f1)); + const __m128i final = _mm_max_epi16(_mm_min_epi16(h_16, max), zero); + _mm_storeu_si128((__m128i*)(out + 2 * i + 0), final); + } + for (; i < len; ++i) { + // (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 = + // = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4 + // We reuse the common sub-expressions. + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_SSE2(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip_SSE2(best_y[2 * i + 1] + v1, max_y); + } +} + +static void SharpYuvFilterRow_SSE2(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth) { + if (bit_depth <= 10) { + SharpYuvFilterRow16_SSE2(A, B, len, best_y, out, bit_depth); + } else { + SharpYuvFilterRow32_SSE2(A, B, len, best_y, out, bit_depth); + } +} + +//------------------------------------------------------------------------------ + +extern void InitSharpYuvSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvSSE2(void) { + SharpYuvUpdateY = SharpYuvUpdateY_SSE2; + SharpYuvUpdateRGB = SharpYuvUpdateRGB_SSE2; + SharpYuvFilterRow = SharpYuvFilterRow_SSE2; +} +#else // !WEBP_USE_SSE2 + +extern void InitSharpYuvSSE2(void); + +void InitSharpYuvSSE2(void) {} + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dec/alpha_dec.c b/libraries/webp/src/dec/alpha_dec.c new file mode 100644 index 0000000000..540646b8cb --- /dev/null +++ b/libraries/webp/src/dec/alpha_dec.c @@ -0,0 +1,239 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha-plane decompression. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dsp/dsp.h" +#include "src/utils/quant_levels_dec_utils.h" +#include "src/utils/utils.h" +#include "include/webp/format_constants.h" +#include "include/webp/types.h" + +//------------------------------------------------------------------------------ +// ALPHDecoder object. + +// Allocates a new alpha decoder instance. +WEBP_NODISCARD static ALPHDecoder* ALPHNew(void) { + ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + return dec; +} + +// Clears and deallocates an alpha decoder instance. +static void ALPHDelete(ALPHDecoder* const dec) { + if (dec != NULL) { + VP8LDelete(dec->vp8l_dec_); + dec->vp8l_dec_ = NULL; + WebPSafeFree(dec); + } +} + +//------------------------------------------------------------------------------ +// Decoding. + +// Initialize alpha decoding by parsing the alpha header and decoding the image +// header for alpha data stored using lossless compression. +// Returns false in case of error in alpha header (data too short, invalid +// compression method or filter, error in lossless header data etc). +WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, + size_t data_size, const VP8Io* const src_io, + uint8_t* output) { + int ok = 0; + const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; + const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; + int rsrv; + VP8Io* const io = &dec->io_; + + assert(data != NULL && output != NULL && src_io != NULL); + + VP8FiltersInit(); + dec->output_ = output; + dec->width_ = src_io->width; + dec->height_ = src_io->height; + assert(dec->width_ > 0 && dec->height_ > 0); + + if (data_size <= ALPHA_HEADER_LEN) { + return 0; + } + + dec->method_ = (data[0] >> 0) & 0x03; + dec->filter_ = (WEBP_FILTER_TYPE)((data[0] >> 2) & 0x03); + dec->pre_processing_ = (data[0] >> 4) & 0x03; + rsrv = (data[0] >> 6) & 0x03; + if (dec->method_ < ALPHA_NO_COMPRESSION || + dec->method_ > ALPHA_LOSSLESS_COMPRESSION || + dec->filter_ >= WEBP_FILTER_LAST || + dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || + rsrv != 0) { + return 0; + } + + // Copy the necessary parameters from src_io to io + if (!VP8InitIo(io)) { + return 0; + } + WebPInitCustomIo(NULL, io); + io->opaque = dec; + io->width = src_io->width; + io->height = src_io->height; + + io->use_cropping = src_io->use_cropping; + io->crop_left = src_io->crop_left; + io->crop_right = src_io->crop_right; + io->crop_top = src_io->crop_top; + io->crop_bottom = src_io->crop_bottom; + // No need to copy the scaling parameters. + + if (dec->method_ == ALPHA_NO_COMPRESSION) { + const size_t alpha_decoded_size = dec->width_ * dec->height_; + ok = (alpha_data_size >= alpha_decoded_size); + } else { + assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION); + ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size); + } + + return ok; +} + +// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha +// starting from row number 'row'. It assumes that rows up to (row - 1) have +// already been decoded. +// Returns false in case of bitstream error. +WEBP_NODISCARD static int ALPHDecode(VP8Decoder* const dec, int row, + int num_rows) { + ALPHDecoder* const alph_dec = dec->alph_dec_; + const int width = alph_dec->width_; + const int height = alph_dec->io_.crop_bottom; + if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { + int y; + const uint8_t* prev_line = dec->alpha_prev_line_; + const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width; + uint8_t* dst = dec->alpha_plane_ + row * width; + assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]); + assert(WebPUnfilters[alph_dec->filter_] != NULL); + for (y = 0; y < num_rows; ++y) { + WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width); + prev_line = dst; + dst += width; + deltas += width; + } + dec->alpha_prev_line_ = prev_line; + } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION + assert(alph_dec->vp8l_dec_ != NULL); + if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { + return 0; + } + } + + if (row + num_rows >= height) { + dec->is_alpha_decoded_ = 1; + } + return 1; +} + +WEBP_NODISCARD static int AllocateAlphaPlane(VP8Decoder* const dec, + const VP8Io* const io) { + const int stride = io->width; + const int height = io->crop_bottom; + const uint64_t alpha_size = (uint64_t)stride * height; + assert(dec->alpha_plane_mem_ == NULL); + dec->alpha_plane_mem_ = + (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_)); + if (dec->alpha_plane_mem_ == NULL) { + return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "Alpha decoder initialization failed."); + } + dec->alpha_plane_ = dec->alpha_plane_mem_; + dec->alpha_prev_line_ = NULL; + return 1; +} + +void WebPDeallocateAlphaMemory(VP8Decoder* const dec) { + assert(dec != NULL); + WebPSafeFree(dec->alpha_plane_mem_); + dec->alpha_plane_mem_ = NULL; + dec->alpha_plane_ = NULL; + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; +} + +//------------------------------------------------------------------------------ +// Main entry point. + +WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, + int row, int num_rows) { + const int width = io->width; + const int height = io->crop_bottom; + + assert(dec != NULL && io != NULL); + + if (row < 0 || num_rows <= 0 || row + num_rows > height) { + return NULL; + } + + if (!dec->is_alpha_decoded_) { + if (dec->alph_dec_ == NULL) { // Initialize decoder. + dec->alph_dec_ = ALPHNew(); + if (dec->alph_dec_ == NULL) { + VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "Alpha decoder initialization failed."); + return NULL; + } + if (!AllocateAlphaPlane(dec, io)) goto Error; + if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, + io, dec->alpha_plane_)) { + VP8LDecoder* const vp8l_dec = dec->alph_dec_->vp8l_dec_; + VP8SetError(dec, + (vp8l_dec == NULL) ? VP8_STATUS_OUT_OF_MEMORY + : vp8l_dec->status_, + "Alpha decoder initialization failed."); + goto Error; + } + // if we allowed use of alpha dithering, check whether it's needed at all + if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) { + dec->alpha_dithering_ = 0; // disable dithering + } else { + num_rows = height - row; // decode everything in one pass + } + } + + assert(dec->alph_dec_ != NULL); + assert(row + num_rows <= height); + if (!ALPHDecode(dec, row, num_rows)) goto Error; + + if (dec->is_alpha_decoded_) { // finished? + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; + if (dec->alpha_dithering_ > 0) { + uint8_t* const alpha = dec->alpha_plane_ + io->crop_top * width + + io->crop_left; + if (!WebPDequantizeLevels(alpha, + io->crop_right - io->crop_left, + io->crop_bottom - io->crop_top, + width, dec->alpha_dithering_)) { + goto Error; + } + } + } + } + + // Return a pointer to the current decoded row. + return dec->alpha_plane_ + row * width; + + Error: + WebPDeallocateAlphaMemory(dec); + return NULL; +} diff --git a/libraries/webp/src/dec/alphai_dec.h b/libraries/webp/src/dec/alphai_dec.h new file mode 100644 index 0000000000..a64104abeb --- /dev/null +++ b/libraries/webp/src/dec/alphai_dec.h @@ -0,0 +1,54 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha decoder: internal header. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_DEC_ALPHAI_DEC_H_ +#define WEBP_DEC_ALPHAI_DEC_H_ + +#include "src/dec/webpi_dec.h" +#include "src/utils/filters_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct VP8LDecoder; // Defined in dec/vp8li.h. + +typedef struct ALPHDecoder ALPHDecoder; +struct ALPHDecoder { + int width_; + int height_; + int method_; + WEBP_FILTER_TYPE filter_; + int pre_processing_; + struct VP8LDecoder* vp8l_dec_; + VP8Io io_; + int use_8b_decode_; // Although alpha channel requires only 1 byte per + // pixel, sometimes VP8LDecoder may need to allocate + // 4 bytes per pixel internally during decode. + uint8_t* output_; + const uint8_t* prev_line_; // last output row (or NULL) +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +// Deallocate memory associated to dec->alpha_plane_ decoding +void WebPDeallocateAlphaMemory(VP8Decoder* const dec); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_ALPHAI_DEC_H_ diff --git a/libraries/webp/src/dec/buffer_dec.c b/libraries/webp/src/dec/buffer_dec.c new file mode 100644 index 0000000000..11ce76f19e --- /dev/null +++ b/libraries/webp/src/dec/buffer_dec.c @@ -0,0 +1,310 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Everything about WebPDecBuffer +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dec/vp8i_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// WebPDecBuffer + +// Number of bytes per pixel for the different color-spaces. +static const uint8_t kModeBpp[MODE_LAST] = { + 3, 4, 3, 4, 4, 2, 2, + 4, 4, 4, 2, // pre-multiplied modes + 1, 1 }; + +// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE. +// Convert to an integer to handle both the unsigned/signed enum cases +// without the need for casting to remove type limit warnings. +static int IsValidColorspace(int webp_csp_mode) { + return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST); +} + +// strictly speaking, the very last (or first, if flipped) row +// doesn't require padding. +#define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \ + ((uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH)) + +static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { + int ok = 1; + const WEBP_CSP_MODE mode = buffer->colorspace; + const int width = buffer->width; + const int height = buffer->height; + if (!IsValidColorspace(mode)) { + ok = 0; + } else if (!WebPIsRGBMode(mode)) { // YUV checks + const WebPYUVABuffer* const buf = &buffer->u.YUVA; + const int uv_width = (width + 1) / 2; + const int uv_height = (height + 1) / 2; + const int y_stride = abs(buf->y_stride); + const int u_stride = abs(buf->u_stride); + const int v_stride = abs(buf->v_stride); + const int a_stride = abs(buf->a_stride); + const uint64_t y_size = MIN_BUFFER_SIZE(width, height, y_stride); + const uint64_t u_size = MIN_BUFFER_SIZE(uv_width, uv_height, u_stride); + const uint64_t v_size = MIN_BUFFER_SIZE(uv_width, uv_height, v_stride); + const uint64_t a_size = MIN_BUFFER_SIZE(width, height, a_stride); + ok &= (y_size <= buf->y_size); + ok &= (u_size <= buf->u_size); + ok &= (v_size <= buf->v_size); + ok &= (y_stride >= width); + ok &= (u_stride >= uv_width); + ok &= (v_stride >= uv_width); + ok &= (buf->y != NULL); + ok &= (buf->u != NULL); + ok &= (buf->v != NULL); + if (mode == MODE_YUVA) { + ok &= (a_stride >= width); + ok &= (a_size <= buf->a_size); + ok &= (buf->a != NULL); + } + } else { // RGB checks + const WebPRGBABuffer* const buf = &buffer->u.RGBA; + const int stride = abs(buf->stride); + const uint64_t size = + MIN_BUFFER_SIZE((uint64_t)width * kModeBpp[mode], height, stride); + ok &= (size <= buf->size); + ok &= (stride >= width * kModeBpp[mode]); + ok &= (buf->rgba != NULL); + } + return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM; +} +#undef MIN_BUFFER_SIZE + +static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) { + const int w = buffer->width; + const int h = buffer->height; + const WEBP_CSP_MODE mode = buffer->colorspace; + + if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) { + return VP8_STATUS_INVALID_PARAM; + } + + if (buffer->is_external_memory <= 0 && buffer->private_memory == NULL) { + uint8_t* output; + int uv_stride = 0, a_stride = 0; + uint64_t uv_size = 0, a_size = 0, total_size; + // We need memory and it hasn't been allocated yet. + // => initialize output buffer, now that dimensions are known. + int stride; + uint64_t size; + + if ((uint64_t)w * kModeBpp[mode] >= (1ull << 31)) { + return VP8_STATUS_INVALID_PARAM; + } + stride = w * kModeBpp[mode]; + size = (uint64_t)stride * h; + if (!WebPIsRGBMode(mode)) { + uv_stride = (w + 1) / 2; + uv_size = (uint64_t)uv_stride * ((h + 1) / 2); + if (mode == MODE_YUVA) { + a_stride = w; + a_size = (uint64_t)a_stride * h; + } + } + total_size = size + 2 * uv_size + a_size; + + output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output)); + if (output == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + buffer->private_memory = output; + + if (!WebPIsRGBMode(mode)) { // YUVA initialization + WebPYUVABuffer* const buf = &buffer->u.YUVA; + buf->y = output; + buf->y_stride = stride; + buf->y_size = (size_t)size; + buf->u = output + size; + buf->u_stride = uv_stride; + buf->u_size = (size_t)uv_size; + buf->v = output + size + uv_size; + buf->v_stride = uv_stride; + buf->v_size = (size_t)uv_size; + if (mode == MODE_YUVA) { + buf->a = output + size + 2 * uv_size; + } + buf->a_size = (size_t)a_size; + buf->a_stride = a_stride; + } else { // RGBA initialization + WebPRGBABuffer* const buf = &buffer->u.RGBA; + buf->rgba = output; + buf->stride = stride; + buf->size = (size_t)size; + } + } + return CheckDecBuffer(buffer); +} + +VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) { + if (buffer == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + if (WebPIsRGBMode(buffer->colorspace)) { + WebPRGBABuffer* const buf = &buffer->u.RGBA; + buf->rgba += (int64_t)(buffer->height - 1) * buf->stride; + buf->stride = -buf->stride; + } else { + WebPYUVABuffer* const buf = &buffer->u.YUVA; + const int64_t H = buffer->height; + buf->y += (H - 1) * buf->y_stride; + buf->y_stride = -buf->y_stride; + buf->u += ((H - 1) >> 1) * buf->u_stride; + buf->u_stride = -buf->u_stride; + buf->v += ((H - 1) >> 1) * buf->v_stride; + buf->v_stride = -buf->v_stride; + if (buf->a != NULL) { + buf->a += (H - 1) * buf->a_stride; + buf->a_stride = -buf->a_stride; + } + } + return VP8_STATUS_OK; +} + +VP8StatusCode WebPAllocateDecBuffer(int width, int height, + const WebPDecoderOptions* const options, + WebPDecBuffer* const buffer) { + VP8StatusCode status; + if (buffer == NULL || width <= 0 || height <= 0) { + return VP8_STATUS_INVALID_PARAM; + } + if (options != NULL) { // First, apply options if there is any. + if (options->use_cropping) { + const int cw = options->crop_width; + const int ch = options->crop_height; + const int x = options->crop_left & ~1; + const int y = options->crop_top & ~1; + if (!WebPCheckCropDimensions(width, height, x, y, cw, ch)) { + return VP8_STATUS_INVALID_PARAM; // out of frame boundary. + } + width = cw; + height = ch; + } + + if (options->use_scaling) { +#if !defined(WEBP_REDUCE_SIZE) + int scaled_width = options->scaled_width; + int scaled_height = options->scaled_height; + if (!WebPRescalerGetScaledDimensions( + width, height, &scaled_width, &scaled_height)) { + return VP8_STATUS_INVALID_PARAM; + } + width = scaled_width; + height = scaled_height; +#else + return VP8_STATUS_INVALID_PARAM; // rescaling not supported +#endif + } + } + buffer->width = width; + buffer->height = height; + + // Then, allocate buffer for real. + status = AllocateBuffer(buffer); + if (status != VP8_STATUS_OK) return status; + + // Use the stride trick if vertical flip is needed. + if (options != NULL && options->flip) { + status = WebPFlipBuffer(buffer); + } + return status; +} + +//------------------------------------------------------------------------------ +// constructors / destructors + +int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return 0; // version mismatch + } + if (buffer == NULL) return 0; + memset(buffer, 0, sizeof(*buffer)); + return 1; +} + +void WebPFreeDecBuffer(WebPDecBuffer* buffer) { + if (buffer != NULL) { + if (buffer->is_external_memory <= 0) { + WebPSafeFree(buffer->private_memory); + } + buffer->private_memory = NULL; + } +} + +void WebPCopyDecBuffer(const WebPDecBuffer* const src, + WebPDecBuffer* const dst) { + if (src != NULL && dst != NULL) { + *dst = *src; + if (src->private_memory != NULL) { + dst->is_external_memory = 1; // dst buffer doesn't own the memory. + dst->private_memory = NULL; + } + } +} + +// Copy and transfer ownership from src to dst (beware of parameter order!) +void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) { + if (src != NULL && dst != NULL) { + *dst = *src; + if (src->private_memory != NULL) { + src->is_external_memory = 1; // src relinquishes ownership + src->private_memory = NULL; + } + } +} + +VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src_buf, + WebPDecBuffer* const dst_buf) { + assert(src_buf != NULL && dst_buf != NULL); + assert(src_buf->colorspace == dst_buf->colorspace); + + dst_buf->width = src_buf->width; + dst_buf->height = src_buf->height; + if (CheckDecBuffer(dst_buf) != VP8_STATUS_OK) { + return VP8_STATUS_INVALID_PARAM; + } + if (WebPIsRGBMode(src_buf->colorspace)) { + const WebPRGBABuffer* const src = &src_buf->u.RGBA; + const WebPRGBABuffer* const dst = &dst_buf->u.RGBA; + WebPCopyPlane(src->rgba, src->stride, dst->rgba, dst->stride, + src_buf->width * kModeBpp[src_buf->colorspace], + src_buf->height); + } else { + const WebPYUVABuffer* const src = &src_buf->u.YUVA; + const WebPYUVABuffer* const dst = &dst_buf->u.YUVA; + WebPCopyPlane(src->y, src->y_stride, dst->y, dst->y_stride, + src_buf->width, src_buf->height); + WebPCopyPlane(src->u, src->u_stride, dst->u, dst->u_stride, + (src_buf->width + 1) / 2, (src_buf->height + 1) / 2); + WebPCopyPlane(src->v, src->v_stride, dst->v, dst->v_stride, + (src_buf->width + 1) / 2, (src_buf->height + 1) / 2); + if (WebPIsAlphaMode(src_buf->colorspace)) { + WebPCopyPlane(src->a, src->a_stride, dst->a, dst->a_stride, + src_buf->width, src_buf->height); + } + } + return VP8_STATUS_OK; +} + +int WebPAvoidSlowMemory(const WebPDecBuffer* const output, + const WebPBitstreamFeatures* const features) { + assert(output != NULL); + return (output->is_external_memory >= 2) && + WebPIsPremultipliedMode(output->colorspace) && + (features != NULL && features->has_alpha); +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dec/common_dec.h b/libraries/webp/src/dec/common_dec.h new file mode 100644 index 0000000000..b158550a80 --- /dev/null +++ b/libraries/webp/src/dec/common_dec.h @@ -0,0 +1,54 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Definitions and macros common to encoding and decoding +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DEC_COMMON_DEC_H_ +#define WEBP_DEC_COMMON_DEC_H_ + +// intra prediction modes +enum { B_DC_PRED = 0, // 4x4 modes + B_TM_PRED = 1, + B_VE_PRED = 2, + B_HE_PRED = 3, + B_RD_PRED = 4, + B_VR_PRED = 5, + B_LD_PRED = 6, + B_VL_PRED = 7, + B_HD_PRED = 8, + B_HU_PRED = 9, + NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10 + + // Luma16 or UV modes + DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED, + H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED, + B_PRED = NUM_BMODES, // refined I4x4 mode + NUM_PRED_MODES = 4, + + // special modes + B_DC_PRED_NOTOP = 4, + B_DC_PRED_NOLEFT = 5, + B_DC_PRED_NOTOPLEFT = 6, + NUM_B_DC_MODES = 7 }; + +enum { MB_FEATURE_TREE_PROBS = 3, + NUM_MB_SEGMENTS = 4, + NUM_REF_LF_DELTAS = 4, + NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT + MAX_NUM_PARTITIONS = 8, + // Probabilities + NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC + NUM_BANDS = 8, + NUM_CTX = 3, + NUM_PROBAS = 11 + }; + +#endif // WEBP_DEC_COMMON_DEC_H_ diff --git a/libraries/webp/src/dec/frame_dec.c b/libraries/webp/src/dec/frame_dec.c new file mode 100644 index 0000000000..91ca1f8609 --- /dev/null +++ b/libraries/webp/src/dec/frame_dec.c @@ -0,0 +1,803 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Frame-reconstruction function. Memory allocation. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Main reconstruction function. + +static const uint16_t kScan[16] = { + 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, + 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, + 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, + 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS +}; + +static int CheckMode(int mb_x, int mb_y, int mode) { + if (mode == B_DC_PRED) { + if (mb_x == 0) { + return (mb_y == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT; + } else { + return (mb_y == 0) ? B_DC_PRED_NOTOP : B_DC_PRED; + } + } + return mode; +} + +static void Copy32b(uint8_t* const dst, const uint8_t* const src) { + memcpy(dst, src, 4); +} + +static WEBP_INLINE void DoTransform(uint32_t bits, const int16_t* const src, + uint8_t* const dst) { + switch (bits >> 30) { + case 3: + VP8Transform(src, dst, 0); + break; + case 2: + VP8TransformAC3(src, dst); + break; + case 1: + VP8TransformDC(src, dst); + break; + default: + break; + } +} + +static void DoUVTransform(uint32_t bits, const int16_t* const src, + uint8_t* const dst) { + if (bits & 0xff) { // any non-zero coeff at all? + if (bits & 0xaa) { // any non-zero AC coefficient? + VP8TransformUV(src, dst); // note we don't use the AC3 variant for U/V + } else { + VP8TransformDCUV(src, dst); + } + } +} + +static void ReconstructRow(const VP8Decoder* const dec, + const VP8ThreadContext* ctx) { + int j; + int mb_x; + const int mb_y = ctx->mb_y_; + const int cache_id = ctx->id_; + uint8_t* const y_dst = dec->yuv_b_ + Y_OFF; + uint8_t* const u_dst = dec->yuv_b_ + U_OFF; + uint8_t* const v_dst = dec->yuv_b_ + V_OFF; + + // Initialize left-most block. + for (j = 0; j < 16; ++j) { + y_dst[j * BPS - 1] = 129; + } + for (j = 0; j < 8; ++j) { + u_dst[j * BPS - 1] = 129; + v_dst[j * BPS - 1] = 129; + } + + // Init top-left sample on left column too. + if (mb_y > 0) { + y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129; + } else { + // we only need to do this init once at block (0,0). + // Afterward, it remains valid for the whole topmost row. + memset(y_dst - BPS - 1, 127, 16 + 4 + 1); + memset(u_dst - BPS - 1, 127, 8 + 1); + memset(v_dst - BPS - 1, 127, 8 + 1); + } + + // Reconstruct one row. + for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { + const VP8MBData* const block = ctx->mb_data_ + mb_x; + + // Rotate in the left samples from previously decoded block. We move four + // pixels at a time for alignment reason, and because of in-loop filter. + if (mb_x > 0) { + for (j = -1; j < 16; ++j) { + Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]); + } + for (j = -1; j < 8; ++j) { + Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]); + Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]); + } + } + { + // bring top samples into the cache + VP8TopSamples* const top_yuv = dec->yuv_t_ + mb_x; + const int16_t* const coeffs = block->coeffs_; + uint32_t bits = block->non_zero_y_; + int n; + + if (mb_y > 0) { + memcpy(y_dst - BPS, top_yuv[0].y, 16); + memcpy(u_dst - BPS, top_yuv[0].u, 8); + memcpy(v_dst - BPS, top_yuv[0].v, 8); + } + + // predict and add residuals + if (block->is_i4x4_) { // 4x4 + uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16); + + if (mb_y > 0) { + if (mb_x >= dec->mb_w_ - 1) { // on rightmost border + memset(top_right, top_yuv[0].y[15], sizeof(*top_right)); + } else { + memcpy(top_right, top_yuv[1].y, sizeof(*top_right)); + } + } + // replicate the top-right pixels below + top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0]; + + // predict and add residuals for all 4x4 blocks in turn. + for (n = 0; n < 16; ++n, bits <<= 2) { + uint8_t* const dst = y_dst + kScan[n]; + VP8PredLuma4[block->imodes_[n]](dst); + DoTransform(bits, coeffs + n * 16, dst); + } + } else { // 16x16 + const int pred_func = CheckMode(mb_x, mb_y, block->imodes_[0]); + VP8PredLuma16[pred_func](y_dst); + if (bits != 0) { + for (n = 0; n < 16; ++n, bits <<= 2) { + DoTransform(bits, coeffs + n * 16, y_dst + kScan[n]); + } + } + } + { + // Chroma + const uint32_t bits_uv = block->non_zero_uv_; + const int pred_func = CheckMode(mb_x, mb_y, block->uvmode_); + VP8PredChroma8[pred_func](u_dst); + VP8PredChroma8[pred_func](v_dst); + DoUVTransform(bits_uv >> 0, coeffs + 16 * 16, u_dst); + DoUVTransform(bits_uv >> 8, coeffs + 20 * 16, v_dst); + } + + // stash away top samples for next block + if (mb_y < dec->mb_h_ - 1) { + memcpy(top_yuv[0].y, y_dst + 15 * BPS, 16); + memcpy(top_yuv[0].u, u_dst + 7 * BPS, 8); + memcpy(top_yuv[0].v, v_dst + 7 * BPS, 8); + } + } + // Transfer reconstructed samples from yuv_b_ cache to final destination. + { + const int y_offset = cache_id * 16 * dec->cache_y_stride_; + const int uv_offset = cache_id * 8 * dec->cache_uv_stride_; + uint8_t* const y_out = dec->cache_y_ + mb_x * 16 + y_offset; + uint8_t* const u_out = dec->cache_u_ + mb_x * 8 + uv_offset; + uint8_t* const v_out = dec->cache_v_ + mb_x * 8 + uv_offset; + for (j = 0; j < 16; ++j) { + memcpy(y_out + j * dec->cache_y_stride_, y_dst + j * BPS, 16); + } + for (j = 0; j < 8; ++j) { + memcpy(u_out + j * dec->cache_uv_stride_, u_dst + j * BPS, 8); + memcpy(v_out + j * dec->cache_uv_stride_, v_dst + j * BPS, 8); + } + } + } +} + +//------------------------------------------------------------------------------ +// Filtering + +// kFilterExtraRows[] = How many extra lines are needed on the MB boundary +// for caching, given a filtering level. +// Simple filter: up to 2 luma samples are read and 1 is written. +// Complex filter: up to 4 luma samples are read and 3 are written. Same for +// U/V, so it's 8 samples total (because of the 2x upsampling). +static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 }; + +static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) { + const VP8ThreadContext* const ctx = &dec->thread_ctx_; + const int cache_id = ctx->id_; + const int y_bps = dec->cache_y_stride_; + const VP8FInfo* const f_info = ctx->f_info_ + mb_x; + uint8_t* const y_dst = dec->cache_y_ + cache_id * 16 * y_bps + mb_x * 16; + const int ilevel = f_info->f_ilevel_; + const int limit = f_info->f_limit_; + if (limit == 0) { + return; + } + assert(limit >= 3); + if (dec->filter_type_ == 1) { // simple + if (mb_x > 0) { + VP8SimpleHFilter16(y_dst, y_bps, limit + 4); + } + if (f_info->f_inner_) { + VP8SimpleHFilter16i(y_dst, y_bps, limit); + } + if (mb_y > 0) { + VP8SimpleVFilter16(y_dst, y_bps, limit + 4); + } + if (f_info->f_inner_) { + VP8SimpleVFilter16i(y_dst, y_bps, limit); + } + } else { // complex + const int uv_bps = dec->cache_uv_stride_; + uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8; + uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8; + const int hev_thresh = f_info->hev_thresh_; + if (mb_x > 0) { + VP8HFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh); + VP8HFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh); + } + if (f_info->f_inner_) { + VP8HFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh); + VP8HFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh); + } + if (mb_y > 0) { + VP8VFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh); + VP8VFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh); + } + if (f_info->f_inner_) { + VP8VFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh); + VP8VFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh); + } + } +} + +// Filter the decoded macroblock row (if needed) +static void FilterRow(const VP8Decoder* const dec) { + int mb_x; + const int mb_y = dec->thread_ctx_.mb_y_; + assert(dec->thread_ctx_.filter_row_); + for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) { + DoFilter(dec, mb_x, mb_y); + } +} + +//------------------------------------------------------------------------------ +// Precompute the filtering strength for each segment and each i4x4/i16x16 mode. + +static void PrecomputeFilterStrengths(VP8Decoder* const dec) { + if (dec->filter_type_ > 0) { + int s; + const VP8FilterHeader* const hdr = &dec->filter_hdr_; + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + int i4x4; + // First, compute the initial level + int base_level; + if (dec->segment_hdr_.use_segment_) { + base_level = dec->segment_hdr_.filter_strength_[s]; + if (!dec->segment_hdr_.absolute_delta_) { + base_level += hdr->level_; + } + } else { + base_level = hdr->level_; + } + for (i4x4 = 0; i4x4 <= 1; ++i4x4) { + VP8FInfo* const info = &dec->fstrengths_[s][i4x4]; + int level = base_level; + if (hdr->use_lf_delta_) { + level += hdr->ref_lf_delta_[0]; + if (i4x4) { + level += hdr->mode_lf_delta_[0]; + } + } + level = (level < 0) ? 0 : (level > 63) ? 63 : level; + if (level > 0) { + int ilevel = level; + if (hdr->sharpness_ > 0) { + if (hdr->sharpness_ > 4) { + ilevel >>= 2; + } else { + ilevel >>= 1; + } + if (ilevel > 9 - hdr->sharpness_) { + ilevel = 9 - hdr->sharpness_; + } + } + if (ilevel < 1) ilevel = 1; + info->f_ilevel_ = ilevel; + info->f_limit_ = 2 * level + ilevel; + info->hev_thresh_ = (level >= 40) ? 2 : (level >= 15) ? 1 : 0; + } else { + info->f_limit_ = 0; // no filtering + } + info->f_inner_ = i4x4; + } + } + } +} + +//------------------------------------------------------------------------------ +// Dithering + +// minimal amp that will provide a non-zero dithering effect +#define MIN_DITHER_AMP 4 + +#define DITHER_AMP_TAB_SIZE 12 +static const uint8_t kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { + // roughly, it's dqm->uv_mat_[1] + 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1 +}; + +void VP8InitDithering(const WebPDecoderOptions* const options, + VP8Decoder* const dec) { + assert(dec != NULL); + if (options != NULL) { + const int d = options->dithering_strength; + const int max_amp = (1 << VP8_RANDOM_DITHER_FIX) - 1; + const int f = (d < 0) ? 0 : (d > 100) ? max_amp : (d * max_amp / 100); + if (f > 0) { + int s; + int all_amp = 0; + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8QuantMatrix* const dqm = &dec->dqm_[s]; + if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) { + const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_; + dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3; + } + all_amp |= dqm->dither_; + } + if (all_amp != 0) { + VP8InitRandom(&dec->dithering_rg_, 1.0f); + dec->dither_ = 1; + } + } + // potentially allow alpha dithering + dec->alpha_dithering_ = options->alpha_dithering_strength; + if (dec->alpha_dithering_ > 100) { + dec->alpha_dithering_ = 100; + } else if (dec->alpha_dithering_ < 0) { + dec->alpha_dithering_ = 0; + } + } +} + +// Convert to range: [-2,2] for dither=50, [-4,4] for dither=100 +static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) { + uint8_t dither[64]; + int i; + for (i = 0; i < 8 * 8; ++i) { + dither[i] = VP8RandomBits2(rg, VP8_DITHER_AMP_BITS + 1, amp); + } + VP8DitherCombine8x8(dither, dst, bps); +} + +static void DitherRow(VP8Decoder* const dec) { + int mb_x; + assert(dec->dither_); + for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) { + const VP8ThreadContext* const ctx = &dec->thread_ctx_; + const VP8MBData* const data = ctx->mb_data_ + mb_x; + const int cache_id = ctx->id_; + const int uv_bps = dec->cache_uv_stride_; + if (data->dither_ >= MIN_DITHER_AMP) { + uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8; + uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8; + Dither8x8(&dec->dithering_rg_, u_dst, uv_bps, data->dither_); + Dither8x8(&dec->dithering_rg_, v_dst, uv_bps, data->dither_); + } + } +} + +//------------------------------------------------------------------------------ +// This function is called after a row of macroblocks is finished decoding. +// It also takes into account the following restrictions: +// * In case of in-loop filtering, we must hold off sending some of the bottom +// pixels as they are yet unfiltered. They will be when the next macroblock +// row is decoded. Meanwhile, we must preserve them by rotating them in the +// cache area. This doesn't hold for the very bottom row of the uncropped +// picture of course. +// * we must clip the remaining pixels against the cropping area. The VP8Io +// struct must have the following fields set correctly before calling put(): + +#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB + +// Finalize and transmit a complete row. Return false in case of user-abort. +static int FinishRow(void* arg1, void* arg2) { + VP8Decoder* const dec = (VP8Decoder*)arg1; + VP8Io* const io = (VP8Io*)arg2; + int ok = 1; + const VP8ThreadContext* const ctx = &dec->thread_ctx_; + const int cache_id = ctx->id_; + const int extra_y_rows = kFilterExtraRows[dec->filter_type_]; + const int ysize = extra_y_rows * dec->cache_y_stride_; + const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_; + const int y_offset = cache_id * 16 * dec->cache_y_stride_; + const int uv_offset = cache_id * 8 * dec->cache_uv_stride_; + uint8_t* const ydst = dec->cache_y_ - ysize + y_offset; + uint8_t* const udst = dec->cache_u_ - uvsize + uv_offset; + uint8_t* const vdst = dec->cache_v_ - uvsize + uv_offset; + const int mb_y = ctx->mb_y_; + const int is_first_row = (mb_y == 0); + const int is_last_row = (mb_y >= dec->br_mb_y_ - 1); + + if (dec->mt_method_ == 2) { + ReconstructRow(dec, ctx); + } + + if (ctx->filter_row_) { + FilterRow(dec); + } + + if (dec->dither_) { + DitherRow(dec); + } + + if (io->put != NULL) { + int y_start = MACROBLOCK_VPOS(mb_y); + int y_end = MACROBLOCK_VPOS(mb_y + 1); + if (!is_first_row) { + y_start -= extra_y_rows; + io->y = ydst; + io->u = udst; + io->v = vdst; + } else { + io->y = dec->cache_y_ + y_offset; + io->u = dec->cache_u_ + uv_offset; + io->v = dec->cache_v_ + uv_offset; + } + + if (!is_last_row) { + y_end -= extra_y_rows; + } + if (y_end > io->crop_bottom) { + y_end = io->crop_bottom; // make sure we don't overflow on last row. + } + // If dec->alpha_data_ is not NULL, we have some alpha plane present. + io->a = NULL; + if (dec->alpha_data_ != NULL && y_start < y_end) { + io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start); + if (io->a == NULL) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "Could not decode alpha data."); + } + } + if (y_start < io->crop_top) { + const int delta_y = io->crop_top - y_start; + y_start = io->crop_top; + assert(!(delta_y & 1)); + io->y += dec->cache_y_stride_ * delta_y; + io->u += dec->cache_uv_stride_ * (delta_y >> 1); + io->v += dec->cache_uv_stride_ * (delta_y >> 1); + if (io->a != NULL) { + io->a += io->width * delta_y; + } + } + if (y_start < y_end) { + io->y += io->crop_left; + io->u += io->crop_left >> 1; + io->v += io->crop_left >> 1; + if (io->a != NULL) { + io->a += io->crop_left; + } + io->mb_y = y_start - io->crop_top; + io->mb_w = io->crop_right - io->crop_left; + io->mb_h = y_end - y_start; + ok = io->put(io); + } + } + // rotate top samples if needed + if (cache_id + 1 == dec->num_caches_) { + if (!is_last_row) { + memcpy(dec->cache_y_ - ysize, ydst + 16 * dec->cache_y_stride_, ysize); + memcpy(dec->cache_u_ - uvsize, udst + 8 * dec->cache_uv_stride_, uvsize); + memcpy(dec->cache_v_ - uvsize, vdst + 8 * dec->cache_uv_stride_, uvsize); + } + } + + return ok; +} + +#undef MACROBLOCK_VPOS + +//------------------------------------------------------------------------------ + +int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) { + int ok = 1; + VP8ThreadContext* const ctx = &dec->thread_ctx_; + const int filter_row = + (dec->filter_type_ > 0) && + (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_); + if (dec->mt_method_ == 0) { + // ctx->id_ and ctx->f_info_ are already set + ctx->mb_y_ = dec->mb_y_; + ctx->filter_row_ = filter_row; + ReconstructRow(dec, ctx); + ok = FinishRow(dec, io); + } else { + WebPWorker* const worker = &dec->worker_; + // Finish previous job *before* updating context + ok &= WebPGetWorkerInterface()->Sync(worker); + assert(worker->status_ == OK); + if (ok) { // spawn a new deblocking/output job + ctx->io_ = *io; + ctx->id_ = dec->cache_id_; + ctx->mb_y_ = dec->mb_y_; + ctx->filter_row_ = filter_row; + if (dec->mt_method_ == 2) { // swap macroblock data + VP8MBData* const tmp = ctx->mb_data_; + ctx->mb_data_ = dec->mb_data_; + dec->mb_data_ = tmp; + } else { + // perform reconstruction directly in main thread + ReconstructRow(dec, ctx); + } + if (filter_row) { // swap filter info + VP8FInfo* const tmp = ctx->f_info_; + ctx->f_info_ = dec->f_info_; + dec->f_info_ = tmp; + } + // (reconstruct)+filter in parallel + WebPGetWorkerInterface()->Launch(worker); + if (++dec->cache_id_ == dec->num_caches_) { + dec->cache_id_ = 0; + } + } + } + return ok; +} + +//------------------------------------------------------------------------------ +// Finish setting up the decoding parameter once user's setup() is called. + +VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) { + // Call setup() first. This may trigger additional decoding features on 'io'. + // Note: Afterward, we must call teardown() no matter what. + if (io->setup != NULL && !io->setup(io)) { + VP8SetError(dec, VP8_STATUS_USER_ABORT, "Frame setup failed"); + return dec->status_; + } + + // Disable filtering per user request + if (io->bypass_filtering) { + dec->filter_type_ = 0; + } + + // Define the area where we can skip in-loop filtering, in case of cropping. + // + // 'Simple' filter reads two luma samples outside of the macroblock + // and filters one. It doesn't filter the chroma samples. Hence, we can + // avoid doing the in-loop filtering before crop_top/crop_left position. + // For the 'Complex' filter, 3 samples are read and up to 3 are filtered. + // Means: there's a dependency chain that goes all the way up to the + // top-left corner of the picture (MB #0). We must filter all the previous + // macroblocks. + { + const int extra_pixels = kFilterExtraRows[dec->filter_type_]; + if (dec->filter_type_ == 2) { + // For complex filter, we need to preserve the dependency chain. + dec->tl_mb_x_ = 0; + dec->tl_mb_y_ = 0; + } else { + // For simple filter, we can filter only the cropped region. + // We include 'extra_pixels' on the other side of the boundary, since + // vertical or horizontal filtering of the previous macroblock can + // modify some abutting pixels. + dec->tl_mb_x_ = (io->crop_left - extra_pixels) >> 4; + dec->tl_mb_y_ = (io->crop_top - extra_pixels) >> 4; + if (dec->tl_mb_x_ < 0) dec->tl_mb_x_ = 0; + if (dec->tl_mb_y_ < 0) dec->tl_mb_y_ = 0; + } + // We need some 'extra' pixels on the right/bottom. + dec->br_mb_y_ = (io->crop_bottom + 15 + extra_pixels) >> 4; + dec->br_mb_x_ = (io->crop_right + 15 + extra_pixels) >> 4; + if (dec->br_mb_x_ > dec->mb_w_) { + dec->br_mb_x_ = dec->mb_w_; + } + if (dec->br_mb_y_ > dec->mb_h_) { + dec->br_mb_y_ = dec->mb_h_; + } + } + PrecomputeFilterStrengths(dec); + return VP8_STATUS_OK; +} + +int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) { + int ok = 1; + if (dec->mt_method_ > 0) { + ok = WebPGetWorkerInterface()->Sync(&dec->worker_); + } + + if (io->teardown != NULL) { + io->teardown(io); + } + return ok; +} + +//------------------------------------------------------------------------------ +// For multi-threaded decoding we need to use 3 rows of 16 pixels as delay line. +// +// Reason is: the deblocking filter cannot deblock the bottom horizontal edges +// immediately, and needs to wait for first few rows of the next macroblock to +// be decoded. Hence, deblocking is lagging behind by 4 or 8 pixels (depending +// on strength). +// With two threads, the vertical positions of the rows being decoded are: +// Decode: [ 0..15][16..31][32..47][48..63][64..79][... +// Deblock: [ 0..11][12..27][28..43][44..59][... +// If we use two threads and two caches of 16 pixels, the sequence would be: +// Decode: [ 0..15][16..31][ 0..15!!][16..31][ 0..15][... +// Deblock: [ 0..11][12..27!!][-4..11][12..27][... +// The problem occurs during row [12..15!!] that both the decoding and +// deblocking threads are writing simultaneously. +// With 3 cache lines, one get a safe write pattern: +// Decode: [ 0..15][16..31][32..47][ 0..15][16..31][32..47][0.. +// Deblock: [ 0..11][12..27][28..43][-4..11][12..27][28... +// Note that multi-threaded output _without_ deblocking can make use of two +// cache lines of 16 pixels only, since there's no lagging behind. The decoding +// and output process have non-concurrent writing: +// Decode: [ 0..15][16..31][ 0..15][16..31][... +// io->put: [ 0..15][16..31][ 0..15][... + +#define MT_CACHE_LINES 3 +#define ST_CACHE_LINES 1 // 1 cache row only for single-threaded case + +// Initialize multi/single-thread worker +static int InitThreadContext(VP8Decoder* const dec) { + dec->cache_id_ = 0; + if (dec->mt_method_ > 0) { + WebPWorker* const worker = &dec->worker_; + if (!WebPGetWorkerInterface()->Reset(worker)) { + return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "thread initialization failed."); + } + worker->data1 = dec; + worker->data2 = (void*)&dec->thread_ctx_.io_; + worker->hook = FinishRow; + dec->num_caches_ = + (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1; + } else { + dec->num_caches_ = ST_CACHE_LINES; + } + return 1; +} + +int VP8GetThreadMethod(const WebPDecoderOptions* const options, + const WebPHeaderStructure* const headers, + int width, int height) { + if (options == NULL || options->use_threads == 0) { + return 0; + } + (void)headers; + (void)width; + (void)height; + assert(headers == NULL || !headers->is_lossless); +#if defined(WEBP_USE_THREAD) + if (width >= MIN_WIDTH_FOR_THREADS) return 2; +#endif + return 0; +} + +#undef MT_CACHE_LINES +#undef ST_CACHE_LINES + +//------------------------------------------------------------------------------ +// Memory setup + +static int AllocateMemory(VP8Decoder* const dec) { + const int num_caches = dec->num_caches_; + const int mb_w = dec->mb_w_; + // Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise. + const size_t intra_pred_mode_size = 4 * mb_w * sizeof(uint8_t); + const size_t top_size = sizeof(VP8TopSamples) * mb_w; + const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB); + const size_t f_info_size = + (dec->filter_type_ > 0) ? + mb_w * (dec->mt_method_ > 0 ? 2 : 1) * sizeof(VP8FInfo) + : 0; + const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_); + const size_t mb_data_size = + (dec->mt_method_ == 2 ? 2 : 1) * mb_w * sizeof(*dec->mb_data_); + const size_t cache_height = (16 * num_caches + + kFilterExtraRows[dec->filter_type_]) * 3 / 2; + const size_t cache_size = top_size * cache_height; + // alpha_size is the only one that scales as width x height. + const uint64_t alpha_size = (dec->alpha_data_ != NULL) ? + (uint64_t)dec->pic_hdr_.width_ * dec->pic_hdr_.height_ : 0ULL; + const uint64_t needed = (uint64_t)intra_pred_mode_size + + top_size + mb_info_size + f_info_size + + yuv_size + mb_data_size + + cache_size + alpha_size + WEBP_ALIGN_CST; + uint8_t* mem; + + if (!CheckSizeOverflow(needed)) return 0; // check for overflow + if (needed > dec->mem_size_) { + WebPSafeFree(dec->mem_); + dec->mem_size_ = 0; + dec->mem_ = WebPSafeMalloc(needed, sizeof(uint8_t)); + if (dec->mem_ == NULL) { + return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "no memory during frame initialization."); + } + // down-cast is ok, thanks to WebPSafeMalloc() above. + dec->mem_size_ = (size_t)needed; + } + + mem = (uint8_t*)dec->mem_; + dec->intra_t_ = mem; + mem += intra_pred_mode_size; + + dec->yuv_t_ = (VP8TopSamples*)mem; + mem += top_size; + + dec->mb_info_ = ((VP8MB*)mem) + 1; + mem += mb_info_size; + + dec->f_info_ = f_info_size ? (VP8FInfo*)mem : NULL; + mem += f_info_size; + dec->thread_ctx_.id_ = 0; + dec->thread_ctx_.f_info_ = dec->f_info_; + if (dec->filter_type_ > 0 && dec->mt_method_ > 0) { + // secondary cache line. The deblocking process need to make use of the + // filtering strength from previous macroblock row, while the new ones + // are being decoded in parallel. We'll just swap the pointers. + dec->thread_ctx_.f_info_ += mb_w; + } + + mem = (uint8_t*)WEBP_ALIGN(mem); + assert((yuv_size & WEBP_ALIGN_CST) == 0); + dec->yuv_b_ = mem; + mem += yuv_size; + + dec->mb_data_ = (VP8MBData*)mem; + dec->thread_ctx_.mb_data_ = (VP8MBData*)mem; + if (dec->mt_method_ == 2) { + dec->thread_ctx_.mb_data_ += mb_w; + } + mem += mb_data_size; + + dec->cache_y_stride_ = 16 * mb_w; + dec->cache_uv_stride_ = 8 * mb_w; + { + const int extra_rows = kFilterExtraRows[dec->filter_type_]; + const int extra_y = extra_rows * dec->cache_y_stride_; + const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_; + dec->cache_y_ = mem + extra_y; + dec->cache_u_ = dec->cache_y_ + + 16 * num_caches * dec->cache_y_stride_ + extra_uv; + dec->cache_v_ = dec->cache_u_ + + 8 * num_caches * dec->cache_uv_stride_ + extra_uv; + dec->cache_id_ = 0; + } + mem += cache_size; + + // alpha plane + dec->alpha_plane_ = alpha_size ? mem : NULL; + mem += alpha_size; + assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_); + + // note: left/top-info is initialized once for all. + memset(dec->mb_info_ - 1, 0, mb_info_size); + VP8InitScanline(dec); // initialize left too. + + // initialize top + memset(dec->intra_t_, B_DC_PRED, intra_pred_mode_size); + + return 1; +} + +static void InitIo(VP8Decoder* const dec, VP8Io* io) { + // prepare 'io' + io->mb_y = 0; + io->y = dec->cache_y_; + io->u = dec->cache_u_; + io->v = dec->cache_v_; + io->y_stride = dec->cache_y_stride_; + io->uv_stride = dec->cache_uv_stride_; + io->a = NULL; +} + +int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io) { + if (!InitThreadContext(dec)) return 0; // call first. Sets dec->num_caches_. + if (!AllocateMemory(dec)) return 0; + InitIo(dec, io); + VP8DspInit(); // Init critical function pointers and look-up tables. + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dec/idec_dec.c b/libraries/webp/src/dec/idec_dec.c new file mode 100644 index 0000000000..78428d24b3 --- /dev/null +++ b/libraries/webp/src/dec/idec_dec.c @@ -0,0 +1,920 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Incremental decoding +// +// Author: somnath@google.com (Somnath Banerjee) + +#include +#include +#include + +#include "src/dec/alphai_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/dec/vp8_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" +#include "include/webp/decode.h" + +// In append mode, buffer allocations increase as multiples of this value. +// Needs to be a power of 2. +#define CHUNK_SIZE 4096 +#define MAX_MB_SIZE 4096 + +//------------------------------------------------------------------------------ +// Data structures for memory and states + +// Decoding states. State normally flows as: +// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and +// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. +// If there is any error the decoder goes into state ERROR. +typedef enum { + STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk. + STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk). + STATE_VP8_PARTS0, + STATE_VP8_DATA, + STATE_VP8L_HEADER, + STATE_VP8L_DATA, + STATE_DONE, + STATE_ERROR +} DecState; + +// Operating state for the MemBuffer +typedef enum { + MEM_MODE_NONE = 0, + MEM_MODE_APPEND, + MEM_MODE_MAP +} MemBufferMode; + +// storage for partition #0 and partial data (in a rolling fashion) +typedef struct { + MemBufferMode mode_; // Operation mode + size_t start_; // start location of the data to be decoded + size_t end_; // end location + size_t buf_size_; // size of the allocated buffer + uint8_t* buf_; // We don't own this buffer in case WebPIUpdate() + + size_t part0_size_; // size of partition #0 + const uint8_t* part0_buf_; // buffer to store partition #0 +} MemBuffer; + +struct WebPIDecoder { + DecState state_; // current decoding state + WebPDecParams params_; // Params to store output info + int is_lossless_; // for down-casting 'dec_'. + void* dec_; // either a VP8Decoder or a VP8LDecoder instance + VP8Io io_; + + MemBuffer mem_; // input memory buffer. + WebPDecBuffer output_; // output buffer (when no external one is supplied, + // or if the external one has slow-memory) + WebPDecBuffer* final_output_; // Slow-memory output to copy to eventually. + size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header. + + int last_mb_y_; // last row reached for intra-mode decoding +}; + +// MB context to restore in case VP8DecodeMB() fails +typedef struct { + VP8MB left_; + VP8MB info_; + VP8BitReader token_br_; +} MBContext; + +//------------------------------------------------------------------------------ +// MemBuffer: incoming data handling + +static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { + return (mem->end_ - mem->start_); +} + +// Check if we need to preserve the compressed alpha data, as it may not have +// been decoded yet. +static int NeedCompressedAlpha(const WebPIDecoder* const idec) { + if (idec->state_ == STATE_WEBP_HEADER) { + // We haven't parsed the headers yet, so we don't know whether the image is + // lossy or lossless. This also means that we haven't parsed the ALPH chunk. + return 0; + } + if (idec->is_lossless_) { + return 0; // ALPH chunk is not present for lossless images. + } else { + const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + assert(dec != NULL); // Must be true as idec->state_ != STATE_WEBP_HEADER. + return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_; + } +} + +static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { + MemBuffer* const mem = &idec->mem_; + const uint8_t* const new_base = mem->buf_ + mem->start_; + // note: for VP8, setting up idec->io_ is only really needed at the beginning + // of the decoding, till partition #0 is complete. + idec->io_.data = new_base; + idec->io_.data_size = MemDataSize(mem); + + if (idec->dec_ != NULL) { + if (!idec->is_lossless_) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + const uint32_t last_part = dec->num_parts_minus_one_; + if (offset != 0) { + uint32_t p; + for (p = 0; p <= last_part; ++p) { + VP8RemapBitReader(dec->parts_ + p, offset); + } + // Remap partition #0 data pointer to new offset, but only in MAP + // mode (in APPEND mode, partition #0 is copied into a fixed memory). + if (mem->mode_ == MEM_MODE_MAP) { + VP8RemapBitReader(&dec->br_, offset); + } + } + { + const uint8_t* const last_start = dec->parts_[last_part].buf_; + VP8BitReaderSetBuffer(&dec->parts_[last_part], last_start, + mem->buf_ + mem->end_ - last_start); + } + if (NeedCompressedAlpha(idec)) { + ALPHDecoder* const alph_dec = dec->alph_dec_; + dec->alpha_data_ += offset; + if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) { + if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { + VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; + assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); + VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, + dec->alpha_data_ + ALPHA_HEADER_LEN, + dec->alpha_data_size_ - ALPHA_HEADER_LEN); + } else { // alph_dec->method_ == ALPHA_NO_COMPRESSION + // Nothing special to do in this case. + } + } + } + } else { // Resize lossless bitreader + VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; + VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); + } + } +} + +// Appends data to the end of MemBuffer->buf_. It expands the allocated memory +// size if required and also updates VP8BitReader's if new memory is allocated. +WEBP_NODISCARD static int AppendToMemBuffer(WebPIDecoder* const idec, + const uint8_t* const data, + size_t data_size) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + MemBuffer* const mem = &idec->mem_; + const int need_compressed_alpha = NeedCompressedAlpha(idec); + const uint8_t* const old_start = + (mem->buf_ == NULL) ? NULL : mem->buf_ + mem->start_; + const uint8_t* const old_base = + need_compressed_alpha ? dec->alpha_data_ : old_start; + assert(mem->buf_ != NULL || mem->start_ == 0); + assert(mem->mode_ == MEM_MODE_APPEND); + if (data_size > MAX_CHUNK_PAYLOAD) { + // security safeguard: trying to allocate more than what the format + // allows for a chunk should be considered a smoke smell. + return 0; + } + + if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory + const size_t new_mem_start = old_start - old_base; + const size_t current_size = MemDataSize(mem) + new_mem_start; + const uint64_t new_size = (uint64_t)current_size + data_size; + const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); + uint8_t* const new_buf = + (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); + if (new_buf == NULL) return 0; + if (old_base != NULL) memcpy(new_buf, old_base, current_size); + WebPSafeFree(mem->buf_); + mem->buf_ = new_buf; + mem->buf_size_ = (size_t)extra_size; + mem->start_ = new_mem_start; + mem->end_ = current_size; + } + + assert(mem->buf_ != NULL); + memcpy(mem->buf_ + mem->end_, data, data_size); + mem->end_ += data_size; + assert(mem->end_ <= mem->buf_size_); + + DoRemap(idec, mem->buf_ + mem->start_ - old_start); + return 1; +} + +WEBP_NODISCARD static int RemapMemBuffer(WebPIDecoder* const idec, + const uint8_t* const data, + size_t data_size) { + MemBuffer* const mem = &idec->mem_; + const uint8_t* const old_buf = mem->buf_; + const uint8_t* const old_start = + (old_buf == NULL) ? NULL : old_buf + mem->start_; + assert(old_buf != NULL || mem->start_ == 0); + assert(mem->mode_ == MEM_MODE_MAP); + + if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! + + mem->buf_ = (uint8_t*)data; + mem->end_ = mem->buf_size_ = data_size; + + DoRemap(idec, mem->buf_ + mem->start_ - old_start); + return 1; +} + +static void InitMemBuffer(MemBuffer* const mem) { + mem->mode_ = MEM_MODE_NONE; + mem->buf_ = NULL; + mem->buf_size_ = 0; + mem->part0_buf_ = NULL; + mem->part0_size_ = 0; +} + +static void ClearMemBuffer(MemBuffer* const mem) { + assert(mem); + if (mem->mode_ == MEM_MODE_APPEND) { + WebPSafeFree(mem->buf_); + WebPSafeFree((void*)mem->part0_buf_); + } +} + +WEBP_NODISCARD static int CheckMemBufferMode(MemBuffer* const mem, + MemBufferMode expected) { + if (mem->mode_ == MEM_MODE_NONE) { + mem->mode_ = expected; // switch to the expected mode + } else if (mem->mode_ != expected) { + return 0; // we mixed the modes => error + } + assert(mem->mode_ == expected); // mode is ok + return 1; +} + +// To be called last. +WEBP_NODISCARD static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { + const WebPDecoderOptions* const options = idec->params_.options; + WebPDecBuffer* const output = idec->params_.output; + + idec->state_ = STATE_DONE; + if (options != NULL && options->flip) { + const VP8StatusCode status = WebPFlipBuffer(output); + if (status != VP8_STATUS_OK) return status; + } + if (idec->final_output_ != NULL) { + const VP8StatusCode status = WebPCopyDecBufferPixels( + output, idec->final_output_); // do the slow-copy + WebPFreeDecBuffer(&idec->output_); + if (status != VP8_STATUS_OK) return status; + *output = *idec->final_output_; + idec->final_output_ = NULL; + } + return VP8_STATUS_OK; +} + +//------------------------------------------------------------------------------ +// Macroblock-decoding contexts + +static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, + MBContext* const context) { + context->left_ = dec->mb_info_[-1]; + context->info_ = dec->mb_info_[dec->mb_x_]; + context->token_br_ = *token_br; +} + +static void RestoreContext(const MBContext* context, VP8Decoder* const dec, + VP8BitReader* const token_br) { + dec->mb_info_[-1] = context->left_; + dec->mb_info_[dec->mb_x_] = context->info_; + *token_br = context->token_br_; +} + +//------------------------------------------------------------------------------ + +static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { + if (idec->state_ == STATE_VP8_DATA) { + // Synchronize the thread, clean-up and check for errors. + (void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); + } + idec->state_ = STATE_ERROR; + return error; +} + +static void ChangeState(WebPIDecoder* const idec, DecState new_state, + size_t consumed_bytes) { + MemBuffer* const mem = &idec->mem_; + idec->state_ = new_state; + mem->start_ += consumed_bytes; + assert(mem->start_ <= mem->end_); + idec->io_.data = mem->buf_ + mem->start_; + idec->io_.data_size = MemDataSize(mem); +} + +// Headers +static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { + MemBuffer* const mem = &idec->mem_; + const uint8_t* data = mem->buf_ + mem->start_; + size_t curr_size = MemDataSize(mem); + VP8StatusCode status; + WebPHeaderStructure headers; + + headers.data = data; + headers.data_size = curr_size; + headers.have_all_data = 0; + status = WebPParseHeaders(&headers); + if (status == VP8_STATUS_NOT_ENOUGH_DATA) { + return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet. + } else if (status != VP8_STATUS_OK) { + return IDecError(idec, status); + } + + idec->chunk_size_ = headers.compressed_size; + idec->is_lossless_ = headers.is_lossless; + if (!idec->is_lossless_) { + VP8Decoder* const dec = VP8New(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + dec->incremental_ = 1; + idec->dec_ = dec; + dec->alpha_data_ = headers.alpha_data; + dec->alpha_data_size_ = headers.alpha_data_size; + ChangeState(idec, STATE_VP8_HEADER, headers.offset); + } else { + VP8LDecoder* const dec = VP8LNew(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + idec->dec_ = dec; + ChangeState(idec, STATE_VP8L_HEADER, headers.offset); + } + return VP8_STATUS_OK; +} + +static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { + const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; + const size_t curr_size = MemDataSize(&idec->mem_); + int width, height; + uint32_t bits; + + if (curr_size < VP8_FRAME_HEADER_SIZE) { + // Not enough data bytes to extract VP8 Frame Header. + return VP8_STATUS_SUSPENDED; + } + if (!VP8GetInfo(data, curr_size, idec->chunk_size_, &width, &height)) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + + bits = data[0] | (data[1] << 8) | (data[2] << 16); + idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE; + + idec->io_.data = data; + idec->io_.data_size = curr_size; + idec->state_ = STATE_VP8_PARTS0; + return VP8_STATUS_OK; +} + +// Partition #0 +static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + VP8BitReader* const br = &dec->br_; + const size_t part_size = br->buf_end_ - br->buf_; + MemBuffer* const mem = &idec->mem_; + assert(!idec->is_lossless_); + assert(mem->part0_buf_ == NULL); + // the following is a format limitation, no need for runtime check: + assert(part_size <= mem->part0_size_); + if (part_size == 0) { // can't have zero-size partition #0 + return VP8_STATUS_BITSTREAM_ERROR; + } + if (mem->mode_ == MEM_MODE_APPEND) { + // We copy and grab ownership of the partition #0 data. + uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size); + if (part0_buf == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + memcpy(part0_buf, br->buf_, part_size); + mem->part0_buf_ = part0_buf; + VP8BitReaderSetBuffer(br, part0_buf, part_size); + } else { + // Else: just keep pointers to the partition #0's data in dec_->br_. + } + mem->start_ += part_size; + return VP8_STATUS_OK; +} + +static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + VP8Io* const io = &idec->io_; + const WebPDecParams* const params = &idec->params_; + WebPDecBuffer* const output = params->output; + + // Wait till we have enough data for the whole partition #0 + if (MemDataSize(&idec->mem_) < idec->mem_.part0_size_) { + return VP8_STATUS_SUSPENDED; + } + + if (!VP8GetHeaders(dec, io)) { + const VP8StatusCode status = dec->status_; + if (status == VP8_STATUS_SUSPENDED || + status == VP8_STATUS_NOT_ENOUGH_DATA) { + // treating NOT_ENOUGH_DATA as SUSPENDED state + return VP8_STATUS_SUSPENDED; + } + return IDecError(idec, status); + } + + // Allocate/Verify output buffer now + dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, + output); + if (dec->status_ != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); + } + // This change must be done before calling VP8InitFrame() + dec->mt_method_ = VP8GetThreadMethod(params->options, NULL, + io->width, io->height); + VP8InitDithering(params->options, dec); + + dec->status_ = CopyParts0Data(idec); + if (dec->status_ != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); + } + + // Finish setting up the decoding parameters. Will call io->setup(). + if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); + } + + // Note: past this point, teardown() must always be called + // in case of error. + idec->state_ = STATE_VP8_DATA; + // Allocate memory and prepare everything. + if (!VP8InitFrame(dec, io)) { + return IDecError(idec, dec->status_); + } + return VP8_STATUS_OK; +} + +// Remaining partitions +static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + VP8Io* const io = &idec->io_; + + // Make sure partition #0 has been read before, to set dec to ready_. + if (!dec->ready_) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { + if (idec->last_mb_y_ != dec->mb_y_) { + if (!VP8ParseIntraModeRow(&dec->br_, dec)) { + // note: normally, error shouldn't occur since we already have the whole + // partition0 available here in DecodeRemaining(). Reaching EOF while + // reading intra modes really means a BITSTREAM_ERROR. + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + idec->last_mb_y_ = dec->mb_y_; + } + for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { + VP8BitReader* const token_br = + &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_]; + MBContext context; + SaveContext(dec, token_br, &context); + if (!VP8DecodeMB(dec, token_br)) { + // We shouldn't fail when MAX_MB data was available + if (dec->num_parts_minus_one_ == 0 && + MemDataSize(&idec->mem_) > MAX_MB_SIZE) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + // Synchronize the threads. + if (dec->mt_method_ > 0) { + if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + } + RestoreContext(&context, dec, token_br); + return VP8_STATUS_SUSPENDED; + } + // Release buffer only if there is only one partition + if (dec->num_parts_minus_one_ == 0) { + idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; + assert(idec->mem_.start_ <= idec->mem_.end_); + } + } + VP8InitScanline(dec); // Prepare for next scanline + + // Reconstruct, filter and emit the row. + if (!VP8ProcessRow(dec, io)) { + return IDecError(idec, VP8_STATUS_USER_ABORT); + } + } + // Synchronize the thread and check for errors. + if (!VP8ExitCritical(dec, io)) { + idec->state_ = STATE_ERROR; // prevent re-entry in IDecError + return IDecError(idec, VP8_STATUS_USER_ABORT); + } + dec->ready_ = 0; + return FinishDecoding(idec); +} + +static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec, + VP8StatusCode status) { + if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { + return VP8_STATUS_SUSPENDED; + } + return IDecError(idec, status); +} + +static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { + VP8Io* const io = &idec->io_; + VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; + const WebPDecParams* const params = &idec->params_; + WebPDecBuffer* const output = params->output; + size_t curr_size = MemDataSize(&idec->mem_); + assert(idec->is_lossless_); + + // Wait until there's enough data for decoding header. + if (curr_size < (idec->chunk_size_ >> 3)) { + dec->status_ = VP8_STATUS_SUSPENDED; + return ErrorStatusLossless(idec, dec->status_); + } + + if (!VP8LDecodeHeader(dec, io)) { + if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && + curr_size < idec->chunk_size_) { + dec->status_ = VP8_STATUS_SUSPENDED; + } + return ErrorStatusLossless(idec, dec->status_); + } + // Allocate/verify output buffer now. + dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, + output); + if (dec->status_ != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); + } + + idec->state_ = STATE_VP8L_DATA; + return VP8_STATUS_OK; +} + +static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { + VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; + const size_t curr_size = MemDataSize(&idec->mem_); + assert(idec->is_lossless_); + + // Switch to incremental decoding if we don't have all the bytes available. + dec->incremental_ = (curr_size < idec->chunk_size_); + + if (!VP8LDecodeImage(dec)) { + return ErrorStatusLossless(idec, dec->status_); + } + assert(dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED); + return (dec->status_ == VP8_STATUS_SUSPENDED) ? dec->status_ + : FinishDecoding(idec); +} + + // Main decoding loop +static VP8StatusCode IDecode(WebPIDecoder* idec) { + VP8StatusCode status = VP8_STATUS_SUSPENDED; + + if (idec->state_ == STATE_WEBP_HEADER) { + status = DecodeWebPHeaders(idec); + } else { + if (idec->dec_ == NULL) { + return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. + } + } + if (idec->state_ == STATE_VP8_HEADER) { + status = DecodeVP8FrameHeader(idec); + } + if (idec->state_ == STATE_VP8_PARTS0) { + status = DecodePartition0(idec); + } + if (idec->state_ == STATE_VP8_DATA) { + const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + if (dec == NULL) { + return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. + } + status = DecodeRemaining(idec); + } + if (idec->state_ == STATE_VP8L_HEADER) { + status = DecodeVP8LHeader(idec); + } + if (idec->state_ == STATE_VP8L_DATA) { + status = DecodeVP8LData(idec); + } + return status; +} + +//------------------------------------------------------------------------------ +// Internal constructor + +WEBP_NODISCARD static WebPIDecoder* NewDecoder( + WebPDecBuffer* const output_buffer, + const WebPBitstreamFeatures* const features) { + WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); + if (idec == NULL) { + return NULL; + } + + idec->state_ = STATE_WEBP_HEADER; + idec->chunk_size_ = 0; + + idec->last_mb_y_ = -1; + + InitMemBuffer(&idec->mem_); + if (!WebPInitDecBuffer(&idec->output_) || !VP8InitIo(&idec->io_)) { + WebPSafeFree(idec); + return NULL; + } + + WebPResetDecParams(&idec->params_); + if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) { + idec->params_.output = &idec->output_; + idec->final_output_ = output_buffer; + if (output_buffer != NULL) { + idec->params_.output->colorspace = output_buffer->colorspace; + } + } else { + idec->params_.output = output_buffer; + idec->final_output_ = NULL; + } + WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. + + return idec; +} + +//------------------------------------------------------------------------------ +// Public functions + +WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { + return NewDecoder(output_buffer, NULL); +} + +WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config) { + WebPIDecoder* idec; + WebPBitstreamFeatures tmp_features; + WebPBitstreamFeatures* const features = + (config == NULL) ? &tmp_features : &config->input; + memset(&tmp_features, 0, sizeof(tmp_features)); + + // Parse the bitstream's features, if requested: + if (data != NULL && data_size > 0) { + if (WebPGetFeatures(data, data_size, features) != VP8_STATUS_OK) { + return NULL; + } + } + + // Create an instance of the incremental decoder + idec = (config != NULL) ? NewDecoder(&config->output, features) + : NewDecoder(NULL, features); + if (idec == NULL) { + return NULL; + } + // Finish initialization + if (config != NULL) { + idec->params_.options = &config->options; + } + return idec; +} + +void WebPIDelete(WebPIDecoder* idec) { + if (idec == NULL) return; + if (idec->dec_ != NULL) { + if (!idec->is_lossless_) { + if (idec->state_ == STATE_VP8_DATA) { + // Synchronize the thread, clean-up and check for errors. + // TODO(vrabaud) do we care about the return result? + (void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); + } + VP8Delete((VP8Decoder*)idec->dec_); + } else { + VP8LDelete((VP8LDecoder*)idec->dec_); + } + } + ClearMemBuffer(&idec->mem_); + WebPFreeDecBuffer(&idec->output_); + WebPSafeFree(idec); +} + +//------------------------------------------------------------------------------ +// Wrapper toward WebPINewDecoder + +WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE csp, uint8_t* output_buffer, + size_t output_buffer_size, int output_stride) { + const int is_external_memory = (output_buffer != NULL) ? 1 : 0; + WebPIDecoder* idec; + + if (csp >= MODE_YUV) return NULL; + if (is_external_memory == 0) { // Overwrite parameters to sane values. + output_buffer_size = 0; + output_stride = 0; + } else { // A buffer was passed. Validate the other params. + if (output_stride == 0 || output_buffer_size == 0) { + return NULL; // invalid parameter. + } + } + idec = WebPINewDecoder(NULL); + if (idec == NULL) return NULL; + idec->output_.colorspace = csp; + idec->output_.is_external_memory = is_external_memory; + idec->output_.u.RGBA.rgba = output_buffer; + idec->output_.u.RGBA.stride = output_stride; + idec->output_.u.RGBA.size = output_buffer_size; + return idec; +} + +WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride, + uint8_t* a, size_t a_size, int a_stride) { + const int is_external_memory = (luma != NULL) ? 1 : 0; + WebPIDecoder* idec; + WEBP_CSP_MODE colorspace; + + if (is_external_memory == 0) { // Overwrite parameters to sane values. + luma_size = u_size = v_size = a_size = 0; + luma_stride = u_stride = v_stride = a_stride = 0; + u = v = a = NULL; + colorspace = MODE_YUVA; + } else { // A luma buffer was passed. Validate the other parameters. + if (u == NULL || v == NULL) return NULL; + if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; + if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; + if (a != NULL) { + if (a_size == 0 || a_stride == 0) return NULL; + } + colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; + } + + idec = WebPINewDecoder(NULL); + if (idec == NULL) return NULL; + + idec->output_.colorspace = colorspace; + idec->output_.is_external_memory = is_external_memory; + idec->output_.u.YUVA.y = luma; + idec->output_.u.YUVA.y_stride = luma_stride; + idec->output_.u.YUVA.y_size = luma_size; + idec->output_.u.YUVA.u = u; + idec->output_.u.YUVA.u_stride = u_stride; + idec->output_.u.YUVA.u_size = u_size; + idec->output_.u.YUVA.v = v; + idec->output_.u.YUVA.v_stride = v_stride; + idec->output_.u.YUVA.v_size = v_size; + idec->output_.u.YUVA.a = a; + idec->output_.u.YUVA.a_stride = a_stride; + idec->output_.u.YUVA.a_size = a_size; + return idec; +} + +WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride) { + return WebPINewYUVA(luma, luma_size, luma_stride, + u, u_size, u_stride, + v, v_size, v_stride, + NULL, 0, 0); +} + +//------------------------------------------------------------------------------ + +static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) { + assert(idec); + if (idec->state_ == STATE_ERROR) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (idec->state_ == STATE_DONE) { + return VP8_STATUS_OK; + } + return VP8_STATUS_SUSPENDED; +} + +VP8StatusCode WebPIAppend(WebPIDecoder* idec, + const uint8_t* data, size_t data_size) { + VP8StatusCode status; + if (idec == NULL || data == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + status = IDecCheckStatus(idec); + if (status != VP8_STATUS_SUSPENDED) { + return status; + } + // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. + if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) { + return VP8_STATUS_INVALID_PARAM; + } + // Append data to memory buffer + if (!AppendToMemBuffer(idec, data, data_size)) { + return VP8_STATUS_OUT_OF_MEMORY; + } + return IDecode(idec); +} + +VP8StatusCode WebPIUpdate(WebPIDecoder* idec, + const uint8_t* data, size_t data_size) { + VP8StatusCode status; + if (idec == NULL || data == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + status = IDecCheckStatus(idec); + if (status != VP8_STATUS_SUSPENDED) { + return status; + } + // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. + if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) { + return VP8_STATUS_INVALID_PARAM; + } + // Make the memory buffer point to the new buffer + if (!RemapMemBuffer(idec, data, data_size)) { + return VP8_STATUS_INVALID_PARAM; + } + return IDecode(idec); +} + +//------------------------------------------------------------------------------ + +static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { + if (idec == NULL || idec->dec_ == NULL) { + return NULL; + } + if (idec->state_ <= STATE_VP8_PARTS0) { + return NULL; + } + if (idec->final_output_ != NULL) { + return NULL; // not yet slow-copied + } + return idec->params_.output; +} + +const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, + int* left, int* top, + int* width, int* height) { + const WebPDecBuffer* const src = GetOutputBuffer(idec); + if (left != NULL) *left = 0; + if (top != NULL) *top = 0; + if (src != NULL) { + if (width != NULL) *width = src->width; + if (height != NULL) *height = idec->params_.last_y; + } else { + if (width != NULL) *width = 0; + if (height != NULL) *height = 0; + } + return src; +} + +WEBP_NODISCARD uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, + int* width, int* height, int* stride) { + const WebPDecBuffer* const src = GetOutputBuffer(idec); + if (src == NULL) return NULL; + if (src->colorspace >= MODE_YUV) { + return NULL; + } + + if (last_y != NULL) *last_y = idec->params_.last_y; + if (width != NULL) *width = src->width; + if (height != NULL) *height = src->height; + if (stride != NULL) *stride = src->u.RGBA.stride; + + return src->u.RGBA.rgba; +} + +WEBP_NODISCARD uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, + uint8_t** u, uint8_t** v, uint8_t** a, + int* width, int* height, int* stride, + int* uv_stride, int* a_stride) { + const WebPDecBuffer* const src = GetOutputBuffer(idec); + if (src == NULL) return NULL; + if (src->colorspace < MODE_YUV) { + return NULL; + } + + if (last_y != NULL) *last_y = idec->params_.last_y; + if (u != NULL) *u = src->u.YUVA.u; + if (v != NULL) *v = src->u.YUVA.v; + if (a != NULL) *a = src->u.YUVA.a; + if (width != NULL) *width = src->width; + if (height != NULL) *height = src->height; + if (stride != NULL) *stride = src->u.YUVA.y_stride; + if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride; + if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; + + return src->u.YUVA.y; +} + +int WebPISetIOHooks(WebPIDecoder* const idec, + VP8IoPutHook put, + VP8IoSetupHook setup, + VP8IoTeardownHook teardown, + void* user_data) { + if (idec == NULL || idec->state_ > STATE_WEBP_HEADER) { + return 0; + } + + idec->io_.put = put; + idec->io_.setup = setup; + idec->io_.teardown = teardown; + idec->io_.opaque = user_data; + + return 1; +} diff --git a/libraries/webp/src/dec/io_dec.c b/libraries/webp/src/dec/io_dec.c new file mode 100644 index 0000000000..5ef6298886 --- /dev/null +++ b/libraries/webp/src/dec/io_dec.c @@ -0,0 +1,662 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// functions for sample output. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include "src/dec/vp8i_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/dsp/dsp.h" +#include "src/dsp/yuv.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Main YUV<->RGB conversion functions + +static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) { + WebPDecBuffer* output = p->output; + const WebPYUVABuffer* const buf = &output->u.YUVA; + uint8_t* const y_dst = buf->y + (size_t)io->mb_y * buf->y_stride; + uint8_t* const u_dst = buf->u + (size_t)(io->mb_y >> 1) * buf->u_stride; + uint8_t* const v_dst = buf->v + (size_t)(io->mb_y >> 1) * buf->v_stride; + const int mb_w = io->mb_w; + const int mb_h = io->mb_h; + const int uv_w = (mb_w + 1) / 2; + const int uv_h = (mb_h + 1) / 2; + WebPCopyPlane(io->y, io->y_stride, y_dst, buf->y_stride, mb_w, mb_h); + WebPCopyPlane(io->u, io->uv_stride, u_dst, buf->u_stride, uv_w, uv_h); + WebPCopyPlane(io->v, io->uv_stride, v_dst, buf->v_stride, uv_w, uv_h); + return io->mb_h; +} + +// Point-sampling U/V sampler. +static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) { + WebPDecBuffer* const output = p->output; + WebPRGBABuffer* const buf = &output->u.RGBA; + uint8_t* const dst = buf->rgba + (size_t)io->mb_y * buf->stride; + WebPSamplerProcessPlane(io->y, io->y_stride, + io->u, io->v, io->uv_stride, + dst, buf->stride, io->mb_w, io->mb_h, + WebPSamplers[output->colorspace]); + return io->mb_h; +} + +//------------------------------------------------------------------------------ +// Fancy upsampling + +#ifdef FANCY_UPSAMPLING +static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) { + int num_lines_out = io->mb_h; // a priori guess + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* dst = buf->rgba + (size_t)io->mb_y * buf->stride; + WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace]; + const uint8_t* cur_y = io->y; + const uint8_t* cur_u = io->u; + const uint8_t* cur_v = io->v; + const uint8_t* top_u = p->tmp_u; + const uint8_t* top_v = p->tmp_v; + int y = io->mb_y; + const int y_end = io->mb_y + io->mb_h; + const int mb_w = io->mb_w; + const int uv_w = (mb_w + 1) / 2; + + if (y == 0) { + // First line is special cased. We mirror the u/v samples at boundary. + upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w); + } else { + // We can finish the left-over line from previous call. + upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v, + dst - buf->stride, dst, mb_w); + ++num_lines_out; + } + // Loop over each output pairs of row. + for (; y + 2 < y_end; y += 2) { + top_u = cur_u; + top_v = cur_v; + cur_u += io->uv_stride; + cur_v += io->uv_stride; + dst += 2 * buf->stride; + cur_y += 2 * io->y_stride; + upsample(cur_y - io->y_stride, cur_y, + top_u, top_v, cur_u, cur_v, + dst - buf->stride, dst, mb_w); + } + // move to last row + cur_y += io->y_stride; + if (io->crop_top + y_end < io->crop_bottom) { + // Save the unfinished samples for next call (as we're not done yet). + memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y)); + memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u)); + memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v)); + // The fancy upsampler leaves a row unfinished behind + // (except for the very last row) + num_lines_out--; + } else { + // Process the very last row of even-sized picture + if (!(y_end & 1)) { + upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, + dst + buf->stride, NULL, mb_w); + } + } + return num_lines_out; +} + +#endif /* FANCY_UPSAMPLING */ + +//------------------------------------------------------------------------------ + +static void FillAlphaPlane(uint8_t* dst, int w, int h, int stride) { + int j; + for (j = 0; j < h; ++j) { + memset(dst, 0xff, w * sizeof(*dst)); + dst += stride; + } +} + +static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p, + int expected_num_lines_out) { + const uint8_t* alpha = io->a; + const WebPYUVABuffer* const buf = &p->output->u.YUVA; + const int mb_w = io->mb_w; + const int mb_h = io->mb_h; + uint8_t* dst = buf->a + (size_t)io->mb_y * buf->a_stride; + int j; + (void)expected_num_lines_out; + assert(expected_num_lines_out == mb_h); + if (alpha != NULL) { + for (j = 0; j < mb_h; ++j) { + memcpy(dst, alpha, mb_w * sizeof(*dst)); + alpha += io->width; + dst += buf->a_stride; + } + } else if (buf->a != NULL) { + // the user requested alpha, but there is none, set it to opaque. + FillAlphaPlane(dst, mb_w, mb_h, buf->a_stride); + } + return 0; +} + +static int GetAlphaSourceRow(const VP8Io* const io, + const uint8_t** alpha, int* const num_rows) { + int start_y = io->mb_y; + *num_rows = io->mb_h; + + // Compensate for the 1-line delay of the fancy upscaler. + // This is similar to EmitFancyRGB(). + if (io->fancy_upsampling) { + if (start_y == 0) { + // We don't process the last row yet. It'll be done during the next call. + --*num_rows; + } else { + --start_y; + // Fortunately, *alpha data is persistent, so we can go back + // one row and finish alpha blending, now that the fancy upscaler + // completed the YUV->RGB interpolation. + *alpha -= io->width; + } + if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) { + // If it's the very last call, we process all the remaining rows! + *num_rows = io->crop_bottom - io->crop_top - start_y; + } + } + return start_y; +} + +static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p, + int expected_num_lines_out) { + const uint8_t* alpha = io->a; + if (alpha != NULL) { + const int mb_w = io->mb_w; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const int alpha_first = + (colorspace == MODE_ARGB || colorspace == MODE_Argb); + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + int num_rows; + const size_t start_y = GetAlphaSourceRow(io, &alpha, &num_rows); + uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; + uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3); + const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w, + num_rows, dst, buf->stride); + (void)expected_num_lines_out; + assert(expected_num_lines_out == num_rows); + // has_alpha is true if there's non-trivial alpha to premultiply with. + if (has_alpha && WebPIsPremultipliedMode(colorspace)) { + WebPApplyAlphaMultiply(base_rgba, alpha_first, + mb_w, num_rows, buf->stride); + } + } + return 0; +} + +static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p, + int expected_num_lines_out) { + const uint8_t* alpha = io->a; + if (alpha != NULL) { + const int mb_w = io->mb_w; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + int num_rows; + const size_t start_y = GetAlphaSourceRow(io, &alpha, &num_rows); + uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; +#if (WEBP_SWAP_16BIT_CSP == 1) + uint8_t* alpha_dst = base_rgba; +#else + uint8_t* alpha_dst = base_rgba + 1; +#endif + uint32_t alpha_mask = 0x0f; + int i, j; + for (j = 0; j < num_rows; ++j) { + for (i = 0; i < mb_w; ++i) { + // Fill in the alpha value (converted to 4 bits). + const uint32_t alpha_value = alpha[i] >> 4; + alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; + alpha_mask &= alpha_value; + } + alpha += io->width; + alpha_dst += buf->stride; + } + (void)expected_num_lines_out; + assert(expected_num_lines_out == num_rows); + if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) { + WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride); + } + } + return 0; +} + +//------------------------------------------------------------------------------ +// YUV rescaling (no final RGB conversion needed) + +#if !defined(WEBP_REDUCE_SIZE) +static int Rescale(const uint8_t* src, int src_stride, + int new_lines, WebPRescaler* const wrk) { + int num_lines_out = 0; + while (new_lines > 0) { // import new contributions of source rows. + const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride); + src += lines_in * src_stride; + new_lines -= lines_in; + num_lines_out += WebPRescalerExport(wrk); // emit output row(s) + } + return num_lines_out; +} + +static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) { + const int mb_h = io->mb_h; + const int uv_mb_h = (mb_h + 1) >> 1; + WebPRescaler* const scaler = p->scaler_y; + int num_lines_out = 0; + if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) { + // Before rescaling, we premultiply the luma directly into the io->y + // internal buffer. This is OK since these samples are not used for + // intra-prediction (the top samples are saved in cache_y_/u_/v_). + // But we need to cast the const away, though. + WebPMultRows((uint8_t*)io->y, io->y_stride, + io->a, io->width, io->mb_w, mb_h, 0); + } + num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler); + Rescale(io->u, io->uv_stride, uv_mb_h, p->scaler_u); + Rescale(io->v, io->uv_stride, uv_mb_h, p->scaler_v); + return num_lines_out; +} + +static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p, + int expected_num_lines_out) { + const WebPYUVABuffer* const buf = &p->output->u.YUVA; + uint8_t* const dst_a = buf->a + (size_t)p->last_y * buf->a_stride; + if (io->a != NULL) { + uint8_t* const dst_y = buf->y + (size_t)p->last_y * buf->y_stride; + const int num_lines_out = Rescale(io->a, io->width, io->mb_h, p->scaler_a); + assert(expected_num_lines_out == num_lines_out); + if (num_lines_out > 0) { // unmultiply the Y + WebPMultRows(dst_y, buf->y_stride, dst_a, buf->a_stride, + p->scaler_a->dst_width, num_lines_out, 1); + } + } else if (buf->a != NULL) { + // the user requested alpha, but there is none, set it to opaque. + assert(p->last_y + expected_num_lines_out <= io->scaled_height); + FillAlphaPlane(dst_a, io->scaled_width, expected_num_lines_out, + buf->a_stride); + } + return 0; +} + +static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) { + const int has_alpha = WebPIsAlphaMode(p->output->colorspace); + const WebPYUVABuffer* const buf = &p->output->u.YUVA; + const int out_width = io->scaled_width; + const int out_height = io->scaled_height; + const int uv_out_width = (out_width + 1) >> 1; + const int uv_out_height = (out_height + 1) >> 1; + const int uv_in_width = (io->mb_w + 1) >> 1; + const int uv_in_height = (io->mb_h + 1) >> 1; + // scratch memory for luma rescaler + const size_t work_size = 2 * (size_t)out_width; + const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones + uint64_t total_size; + size_t rescaler_size; + rescaler_t* work; + WebPRescaler* scalers; + const int num_rescalers = has_alpha ? 4 : 3; + + total_size = ((uint64_t)work_size + 2 * uv_work_size) * sizeof(*work); + if (has_alpha) { + total_size += (uint64_t)work_size * sizeof(*work); + } + rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST; + total_size += rescaler_size; + if (!CheckSizeOverflow(total_size)) { + return 0; + } + + p->memory = WebPSafeMalloc(1ULL, (size_t)total_size); + if (p->memory == NULL) { + return 0; // memory error + } + work = (rescaler_t*)p->memory; + + scalers = (WebPRescaler*)WEBP_ALIGN( + (const uint8_t*)work + total_size - rescaler_size); + p->scaler_y = &scalers[0]; + p->scaler_u = &scalers[1]; + p->scaler_v = &scalers[2]; + p->scaler_a = has_alpha ? &scalers[3] : NULL; + + if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h, + buf->y, out_width, out_height, buf->y_stride, 1, + work) || + !WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height, + buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, + work + work_size) || + !WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height, + buf->v, uv_out_width, uv_out_height, buf->v_stride, 1, + work + work_size + uv_work_size)) { + return 0; + } + p->emit = EmitRescaledYUV; + + if (has_alpha) { + if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h, + buf->a, out_width, out_height, buf->a_stride, 1, + work + work_size + 2 * uv_work_size)) { + return 0; + } + p->emit_alpha = EmitRescaledAlphaYUV; + WebPInitAlphaProcessing(); + } + return 1; +} + +//------------------------------------------------------------------------------ +// RGBA rescaling + +static int ExportRGB(WebPDecParams* const p, int y_pos) { + const WebPYUV444Converter convert = + WebPYUV444Converters[p->output->colorspace]; + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* dst = buf->rgba + (size_t)y_pos * buf->stride; + int num_lines_out = 0; + // For RGB rescaling, because of the YUV420, current scan position + // U/V can be +1/-1 line from the Y one. Hence the double test. + while (WebPRescalerHasPendingOutput(p->scaler_y) && + WebPRescalerHasPendingOutput(p->scaler_u)) { + assert(y_pos + num_lines_out < p->output->height); + assert(p->scaler_u->y_accum == p->scaler_v->y_accum); + WebPRescalerExportRow(p->scaler_y); + WebPRescalerExportRow(p->scaler_u); + WebPRescalerExportRow(p->scaler_v); + convert(p->scaler_y->dst, p->scaler_u->dst, p->scaler_v->dst, + dst, p->scaler_y->dst_width); + dst += buf->stride; + ++num_lines_out; + } + return num_lines_out; +} + +static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) { + const int mb_h = io->mb_h; + const int uv_mb_h = (mb_h + 1) >> 1; + int j = 0, uv_j = 0; + int num_lines_out = 0; + while (j < mb_h) { + const int y_lines_in = + WebPRescalerImport(p->scaler_y, mb_h - j, + io->y + (size_t)j * io->y_stride, io->y_stride); + j += y_lines_in; + if (WebPRescaleNeededLines(p->scaler_u, uv_mb_h - uv_j)) { + const int u_lines_in = WebPRescalerImport( + p->scaler_u, uv_mb_h - uv_j, io->u + (size_t)uv_j * io->uv_stride, + io->uv_stride); + const int v_lines_in = WebPRescalerImport( + p->scaler_v, uv_mb_h - uv_j, io->v + (size_t)uv_j * io->uv_stride, + io->uv_stride); + (void)v_lines_in; // remove a gcc warning + assert(u_lines_in == v_lines_in); + uv_j += u_lines_in; + } + num_lines_out += ExportRGB(p, p->last_y + num_lines_out); + } + return num_lines_out; +} + +static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) { + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* const base_rgba = buf->rgba + (size_t)y_pos * buf->stride; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const int alpha_first = + (colorspace == MODE_ARGB || colorspace == MODE_Argb); + uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); + int num_lines_out = 0; + const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); + uint32_t non_opaque = 0; + const int width = p->scaler_a->dst_width; + + while (WebPRescalerHasPendingOutput(p->scaler_a) && + num_lines_out < max_lines_out) { + assert(y_pos + num_lines_out < p->output->height); + WebPRescalerExportRow(p->scaler_a); + non_opaque |= WebPDispatchAlpha(p->scaler_a->dst, 0, width, 1, dst, 0); + dst += buf->stride; + ++num_lines_out; + } + if (is_premult_alpha && non_opaque) { + WebPApplyAlphaMultiply(base_rgba, alpha_first, + width, num_lines_out, buf->stride); + } + return num_lines_out; +} + +static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos, + int max_lines_out) { + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* const base_rgba = buf->rgba + (size_t)y_pos * buf->stride; +#if (WEBP_SWAP_16BIT_CSP == 1) + uint8_t* alpha_dst = base_rgba; +#else + uint8_t* alpha_dst = base_rgba + 1; +#endif + int num_lines_out = 0; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const int width = p->scaler_a->dst_width; + const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); + uint32_t alpha_mask = 0x0f; + + while (WebPRescalerHasPendingOutput(p->scaler_a) && + num_lines_out < max_lines_out) { + int i; + assert(y_pos + num_lines_out < p->output->height); + WebPRescalerExportRow(p->scaler_a); + for (i = 0; i < width; ++i) { + // Fill in the alpha value (converted to 4 bits). + const uint32_t alpha_value = p->scaler_a->dst[i] >> 4; + alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; + alpha_mask &= alpha_value; + } + alpha_dst += buf->stride; + ++num_lines_out; + } + if (is_premult_alpha && alpha_mask != 0x0f) { + WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride); + } + return num_lines_out; +} + +static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p, + int expected_num_out_lines) { + if (io->a != NULL) { + WebPRescaler* const scaler = p->scaler_a; + int lines_left = expected_num_out_lines; + const int y_end = p->last_y + lines_left; + while (lines_left > 0) { + const int64_t row_offset = (int64_t)scaler->src_y - io->mb_y; + WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y, + io->a + row_offset * io->width, io->width); + lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left); + } + } + return 0; +} + +static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { + const int has_alpha = WebPIsAlphaMode(p->output->colorspace); + const int out_width = io->scaled_width; + const int out_height = io->scaled_height; + const int uv_in_width = (io->mb_w + 1) >> 1; + const int uv_in_height = (io->mb_h + 1) >> 1; + // scratch memory for one rescaler + const size_t work_size = 2 * (size_t)out_width; + rescaler_t* work; // rescalers work area + uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion + uint64_t tmp_size1, tmp_size2, total_size; + size_t rescaler_size; + WebPRescaler* scalers; + const int num_rescalers = has_alpha ? 4 : 3; + + tmp_size1 = (uint64_t)num_rescalers * work_size; + tmp_size2 = (uint64_t)num_rescalers * out_width; + total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); + rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST; + total_size += rescaler_size; + if (!CheckSizeOverflow(total_size)) { + return 0; + } + + p->memory = WebPSafeMalloc(1ULL, (size_t)total_size); + if (p->memory == NULL) { + return 0; // memory error + } + work = (rescaler_t*)p->memory; + tmp = (uint8_t*)(work + tmp_size1); + + scalers = (WebPRescaler*)WEBP_ALIGN( + (const uint8_t*)work + total_size - rescaler_size); + p->scaler_y = &scalers[0]; + p->scaler_u = &scalers[1]; + p->scaler_v = &scalers[2]; + p->scaler_a = has_alpha ? &scalers[3] : NULL; + + if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h, + tmp + 0 * out_width, out_width, out_height, 0, 1, + work + 0 * work_size) || + !WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height, + tmp + 1 * out_width, out_width, out_height, 0, 1, + work + 1 * work_size) || + !WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height, + tmp + 2 * out_width, out_width, out_height, 0, 1, + work + 2 * work_size)) { + return 0; + } + p->emit = EmitRescaledRGB; + WebPInitYUV444Converters(); + + if (has_alpha) { + if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h, + tmp + 3 * out_width, out_width, out_height, 0, 1, + work + 3 * work_size)) { + return 0; + } + p->emit_alpha = EmitRescaledAlphaRGB; + if (p->output->colorspace == MODE_RGBA_4444 || + p->output->colorspace == MODE_rgbA_4444) { + p->emit_alpha_row = ExportAlphaRGBA4444; + } else { + p->emit_alpha_row = ExportAlpha; + } + WebPInitAlphaProcessing(); + } + return 1; +} + +#endif // WEBP_REDUCE_SIZE + +//------------------------------------------------------------------------------ +// Default custom functions + +static int CustomSetup(VP8Io* io) { + WebPDecParams* const p = (WebPDecParams*)io->opaque; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const int is_rgb = WebPIsRGBMode(colorspace); + const int is_alpha = WebPIsAlphaMode(colorspace); + + p->memory = NULL; + p->emit = NULL; + p->emit_alpha = NULL; + p->emit_alpha_row = NULL; + if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) { + return 0; + } + if (is_alpha && WebPIsPremultipliedMode(colorspace)) { + WebPInitUpsamplers(); + } + if (io->use_scaling) { +#if !defined(WEBP_REDUCE_SIZE) + const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); + if (!ok) { + return 0; // memory error + } +#else + return 0; // rescaling support not compiled +#endif + } else { + if (is_rgb) { + WebPInitSamplers(); + p->emit = EmitSampledRGB; // default + if (io->fancy_upsampling) { +#ifdef FANCY_UPSAMPLING + const int uv_width = (io->mb_w + 1) >> 1; + p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width)); + if (p->memory == NULL) { + return 0; // memory error. + } + p->tmp_y = (uint8_t*)p->memory; + p->tmp_u = p->tmp_y + io->mb_w; + p->tmp_v = p->tmp_u + uv_width; + p->emit = EmitFancyRGB; + WebPInitUpsamplers(); +#endif + } + } else { + p->emit = EmitYUV; + } + if (is_alpha) { // need transparency output + p->emit_alpha = + (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ? + EmitAlphaRGBA4444 + : is_rgb ? EmitAlphaRGB + : EmitAlphaYUV; + if (is_rgb) { + WebPInitAlphaProcessing(); + } + } + } + + return 1; +} + +//------------------------------------------------------------------------------ + +static int CustomPut(const VP8Io* io) { + WebPDecParams* const p = (WebPDecParams*)io->opaque; + const int mb_w = io->mb_w; + const int mb_h = io->mb_h; + int num_lines_out; + assert(!(io->mb_y & 1)); + + if (mb_w <= 0 || mb_h <= 0) { + return 0; + } + num_lines_out = p->emit(io, p); + if (p->emit_alpha != NULL) { + p->emit_alpha(io, p, num_lines_out); + } + p->last_y += num_lines_out; + return 1; +} + +//------------------------------------------------------------------------------ + +static void CustomTeardown(const VP8Io* io) { + WebPDecParams* const p = (WebPDecParams*)io->opaque; + WebPSafeFree(p->memory); + p->memory = NULL; +} + +//------------------------------------------------------------------------------ +// Main entry point + +void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) { + io->put = CustomPut; + io->setup = CustomSetup; + io->teardown = CustomTeardown; + io->opaque = params; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dec/quant_dec.c b/libraries/webp/src/dec/quant_dec.c new file mode 100644 index 0000000000..a0ac018b0f --- /dev/null +++ b/libraries/webp/src/dec/quant_dec.c @@ -0,0 +1,115 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Quantizer initialization +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dec/vp8i_dec.h" + +static WEBP_INLINE int clip(int v, int M) { + return v < 0 ? 0 : v > M ? M : v; +} + +// Paragraph 14.1 +static const uint8_t kDcTable[128] = { + 4, 5, 6, 7, 8, 9, 10, 10, + 11, 12, 13, 14, 15, 16, 17, 17, + 18, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 25, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, + 91, 93, 95, 96, 98, 100, 101, 102, + 104, 106, 108, 110, 112, 114, 116, 118, + 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 143, 145, 148, 151, 154, 157 +}; + +static const uint16_t kAcTable[128] = { + 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 60, + 62, 64, 66, 68, 70, 72, 74, 76, + 78, 80, 82, 84, 86, 88, 90, 92, + 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, + 131, 134, 137, 140, 143, 146, 149, 152, + 155, 158, 161, 164, 167, 170, 173, 177, + 181, 185, 189, 193, 197, 201, 205, 209, + 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284 +}; + +//------------------------------------------------------------------------------ +// Paragraph 9.6 + +void VP8ParseQuant(VP8Decoder* const dec) { + VP8BitReader* const br = &dec->br_; + const int base_q0 = VP8GetValue(br, 7, "global-header"); + const int dqy1_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dqy2_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dqy2_ac = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dquv_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dquv_ac = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + + const VP8SegmentHeader* const hdr = &dec->segment_hdr_; + int i; + + for (i = 0; i < NUM_MB_SEGMENTS; ++i) { + int q; + if (hdr->use_segment_) { + q = hdr->quantizer_[i]; + if (!hdr->absolute_delta_) { + q += base_q0; + } + } else { + if (i > 0) { + dec->dqm_[i] = dec->dqm_[0]; + continue; + } else { + q = base_q0; + } + } + { + VP8QuantMatrix* const m = &dec->dqm_[i]; + m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)]; + m->y1_mat_[1] = kAcTable[clip(q + 0, 127)]; + + m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2; + // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16. + // The smallest precision for that is '(x*6349) >> 12' but 16 is a good + // word size. + m->y2_mat_[1] = (kAcTable[clip(q + dqy2_ac, 127)] * 101581) >> 16; + if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8; + + m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)]; + m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)]; + + m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation + } + } +} + +//------------------------------------------------------------------------------ + diff --git a/libraries/webp/src/dec/tree_dec.c b/libraries/webp/src/dec/tree_dec.c new file mode 100644 index 0000000000..2434605953 --- /dev/null +++ b/libraries/webp/src/dec/tree_dec.c @@ -0,0 +1,538 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Coding trees and probas +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dec/vp8i_dec.h" +#include "src/dsp/cpu.h" +#include "src/utils/bit_reader_inl_utils.h" + +#if !defined(USE_GENERIC_TREE) +#if !defined(__arm__) && !defined(_M_ARM) && !WEBP_AARCH64 +// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then. +#define USE_GENERIC_TREE 1 // ALTERNATE_CODE +#else +#define USE_GENERIC_TREE 0 +#endif +#endif // USE_GENERIC_TREE + +#if (USE_GENERIC_TREE == 1) +static const int8_t kYModesIntra4[18] = { + -B_DC_PRED, 1, + -B_TM_PRED, 2, + -B_VE_PRED, 3, + 4, 6, + -B_HE_PRED, 5, + -B_RD_PRED, -B_VR_PRED, + -B_LD_PRED, 7, + -B_VL_PRED, 8, + -B_HD_PRED, -B_HU_PRED +}; +#endif + +//------------------------------------------------------------------------------ +// Default probabilities + +// Paragraph 13.5 +static const uint8_t + CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { + { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, + { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, + { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } + }, + { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, + { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, + { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, + }, + { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, + { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, + { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, + }, + { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, + { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, + { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } + }, + { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, + { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, + { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } + }, + { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, + { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, + { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } + }, + { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, + { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, + { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } + }, + { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, + { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, + { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } + }, + { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, + { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, + { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } + }, + { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, + { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, + { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } + }, + { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, + { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, + { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } + }, + { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, + { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, + { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } + }, + { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, + { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, + { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } + }, + { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } + } + }, + { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, + { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, + { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } + }, + { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, + { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, + { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } + }, + { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, + { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, + { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } + }, + { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, + { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, + { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, + { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } + }, + { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, + { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, + { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } + }, + { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, + { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, + { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } + }, + { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, + { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, + { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } + }, + { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, + { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, + { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } + }, + { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, + { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, + { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } + }, + { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, + { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, + { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } + }, + { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + } + } +}; + +// Paragraph 11.5 +static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = { + { { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, + { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, + { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, + { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, + { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, + { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, + { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, + { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, + { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, + { 81, 40, 11, 96, 182, 84, 29, 16, 36 } }, + { { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, + { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, + { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, + { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, + { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, + { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, + { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, + { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, + { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, + { 66, 45, 25, 102, 197, 189, 23, 18, 22 } }, + { { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, + { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, + { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, + { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, + { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, + { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, + { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, + { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, + { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, + { 62, 18, 78, 95, 85, 57, 50, 48, 51 } }, + { { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, + { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, + { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, + { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, + { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, + { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, + { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, + { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, + { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, + { 51, 50, 17, 168, 209, 192, 23, 25, 82 } }, + { { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, + { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, + { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, + { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, + { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, + { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, + { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, + { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, + { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, + { 87, 37, 9, 115, 59, 77, 64, 21, 47 } }, + { { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, + { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, + { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, + { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, + { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, + { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, + { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, + { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, + { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, + { 55, 38, 70, 124, 73, 102, 1, 34, 98 } }, + { { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, + { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, + { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, + { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, + { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, + { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, + { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, + { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, + { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, + { 117, 20, 15, 36, 163, 128, 68, 1, 26 } }, + { { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, + { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, + { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, + { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, + { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, + { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, + { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, + { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, + { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, + { 58, 15, 20, 82, 135, 57, 26, 121, 40 } }, + { { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, + { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, + { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, + { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, + { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, + { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, + { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, + { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, + { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, + { 35, 27, 10, 146, 174, 171, 12, 26, 128 } }, + { { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, + { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, + { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, + { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, + { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, + { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, + { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, + { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, + { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, + { 112, 19, 12, 61, 195, 128, 48, 4, 24 } } +}; + +void VP8ResetProba(VP8Proba* const proba) { + memset(proba->segments_, 255u, sizeof(proba->segments_)); + // proba->bands_[][] is initialized later +} + +static void ParseIntraMode(VP8BitReader* const br, + VP8Decoder* const dec, int mb_x) { + uint8_t* const top = dec->intra_t_ + 4 * mb_x; + uint8_t* const left = dec->intra_l_; + VP8MBData* const block = dec->mb_data_ + mb_x; + + // Note: we don't save segment map (yet), as we don't expect + // to decode more than 1 keyframe. + if (dec->segment_hdr_.update_map_) { + // Hardcoded tree parsing + block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0], "segments") + ? VP8GetBit(br, dec->proba_.segments_[1], "segments") + : VP8GetBit(br, dec->proba_.segments_[2], "segments") + 2; + } else { + block->segment_ = 0; // default for intra + } + if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_, "skip"); + + block->is_i4x4_ = !VP8GetBit(br, 145, "block-size"); + if (!block->is_i4x4_) { + // Hardcoded 16x16 intra-mode decision tree. + const int ymode = + VP8GetBit(br, 156, "pred-modes") ? + (VP8GetBit(br, 128, "pred-modes") ? TM_PRED : H_PRED) : + (VP8GetBit(br, 163, "pred-modes") ? V_PRED : DC_PRED); + block->imodes_[0] = ymode; + memset(top, ymode, 4 * sizeof(*top)); + memset(left, ymode, 4 * sizeof(*left)); + } else { + uint8_t* modes = block->imodes_; + int y; + for (y = 0; y < 4; ++y) { + int ymode = left[y]; + int x; + for (x = 0; x < 4; ++x) { + const uint8_t* const prob = kBModesProba[top[x]][ymode]; +#if (USE_GENERIC_TREE == 1) + // Generic tree-parsing + int i = kYModesIntra4[VP8GetBit(br, prob[0], "pred-modes")]; + while (i > 0) { + i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i], "pred-modes")]; + } + ymode = -i; +#else + // Hardcoded tree parsing + ymode = !VP8GetBit(br, prob[0], "pred-modes") ? B_DC_PRED : + !VP8GetBit(br, prob[1], "pred-modes") ? B_TM_PRED : + !VP8GetBit(br, prob[2], "pred-modes") ? B_VE_PRED : + !VP8GetBit(br, prob[3], "pred-modes") ? + (!VP8GetBit(br, prob[4], "pred-modes") ? B_HE_PRED : + (!VP8GetBit(br, prob[5], "pred-modes") ? B_RD_PRED + : B_VR_PRED)) : + (!VP8GetBit(br, prob[6], "pred-modes") ? B_LD_PRED : + (!VP8GetBit(br, prob[7], "pred-modes") ? B_VL_PRED : + (!VP8GetBit(br, prob[8], "pred-modes") ? B_HD_PRED + : B_HU_PRED)) + ); +#endif // USE_GENERIC_TREE + top[x] = ymode; + } + memcpy(modes, top, 4 * sizeof(*top)); + modes += 4; + left[y] = ymode; + } + } + // Hardcoded UVMode decision tree + block->uvmode_ = !VP8GetBit(br, 142, "pred-modes-uv") ? DC_PRED + : !VP8GetBit(br, 114, "pred-modes-uv") ? V_PRED + : VP8GetBit(br, 183, "pred-modes-uv") ? TM_PRED : H_PRED; +} + +int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) { + int mb_x; + for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { + ParseIntraMode(br, dec, mb_x); + } + return !dec->br_.eof_; +} + +//------------------------------------------------------------------------------ +// Paragraph 13 + +static const uint8_t + CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { + { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, + { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } + }, + { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + } +}; + +// Paragraph 9.9 + +static const uint8_t kBands[16 + 1] = { + 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 0 // extra entry as sentinel +}; + +void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { + VP8Proba* const proba = &dec->proba_; + int t, b, c, p; + for (t = 0; t < NUM_TYPES; ++t) { + for (b = 0; b < NUM_BANDS; ++b) { + for (c = 0; c < NUM_CTX; ++c) { + for (p = 0; p < NUM_PROBAS; ++p) { + const int v = + VP8GetBit(br, CoeffsUpdateProba[t][b][c][p], "global-header") ? + VP8GetValue(br, 8, "global-header") : + CoeffsProba0[t][b][c][p]; + proba->bands_[t][b].probas_[c][p] = v; + } + } + } + for (b = 0; b < 16 + 1; ++b) { + proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]]; + } + } + dec->use_skip_proba_ = VP8Get(br, "global-header"); + if (dec->use_skip_proba_) { + dec->skip_p_ = VP8GetValue(br, 8, "global-header"); + } +} diff --git a/libraries/webp/src/dec/vp8_dec.c b/libraries/webp/src/dec/vp8_dec.c new file mode 100644 index 0000000000..2ee8900605 --- /dev/null +++ b/libraries/webp/src/dec/vp8_dec.c @@ -0,0 +1,728 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// main entry for the decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/bit_reader_inl_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ + +int WebPGetDecoderVersion(void) { + return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION; +} + +//------------------------------------------------------------------------------ +// Signature and pointer-to-function for GetCoeffs() variants below. + +typedef int (*GetCoeffsFunc)(VP8BitReader* const br, + const VP8BandProbas* const prob[], + int ctx, const quant_t dq, int n, int16_t* out); +static volatile GetCoeffsFunc GetCoeffs = NULL; + +static void InitGetCoeffs(void); + +//------------------------------------------------------------------------------ +// VP8Decoder + +static void SetOk(VP8Decoder* const dec) { + dec->status_ = VP8_STATUS_OK; + dec->error_msg_ = "OK"; +} + +int VP8InitIoInternal(VP8Io* const io, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return 0; // mismatch error + } + if (io != NULL) { + memset(io, 0, sizeof(*io)); + } + return 1; +} + +VP8Decoder* VP8New(void) { + VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + if (dec != NULL) { + SetOk(dec); + WebPGetWorkerInterface()->Init(&dec->worker_); + dec->ready_ = 0; + dec->num_parts_minus_one_ = 0; + InitGetCoeffs(); + } + return dec; +} + +VP8StatusCode VP8Status(VP8Decoder* const dec) { + if (!dec) return VP8_STATUS_INVALID_PARAM; + return dec->status_; +} + +const char* VP8StatusMessage(VP8Decoder* const dec) { + if (dec == NULL) return "no object"; + if (!dec->error_msg_) return "OK"; + return dec->error_msg_; +} + +void VP8Delete(VP8Decoder* const dec) { + if (dec != NULL) { + VP8Clear(dec); + WebPSafeFree(dec); + } +} + +int VP8SetError(VP8Decoder* const dec, + VP8StatusCode error, const char* const msg) { + // VP8_STATUS_SUSPENDED is only meaningful in incremental decoding. + assert(dec->incremental_ || error != VP8_STATUS_SUSPENDED); + // The oldest error reported takes precedence over the new one. + if (dec->status_ == VP8_STATUS_OK) { + dec->status_ = error; + dec->error_msg_ = msg; + dec->ready_ = 0; + } + return 0; +} + +//------------------------------------------------------------------------------ + +int VP8CheckSignature(const uint8_t* const data, size_t data_size) { + return (data_size >= 3 && + data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a); +} + +int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size, + int* const width, int* const height) { + if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) { + return 0; // not enough data + } + // check signature + if (!VP8CheckSignature(data + 3, data_size - 3)) { + return 0; // Wrong signature. + } else { + const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); + const int key_frame = !(bits & 1); + const int w = ((data[7] << 8) | data[6]) & 0x3fff; + const int h = ((data[9] << 8) | data[8]) & 0x3fff; + + if (!key_frame) { // Not a keyframe. + return 0; + } + + if (((bits >> 1) & 7) > 3) { + return 0; // unknown profile + } + if (!((bits >> 4) & 1)) { + return 0; // first frame is invisible! + } + if (((bits >> 5)) >= chunk_size) { // partition_length + return 0; // inconsistent size information. + } + if (w == 0 || h == 0) { + return 0; // We don't support both width and height to be zero. + } + + if (width) { + *width = w; + } + if (height) { + *height = h; + } + + return 1; + } +} + +//------------------------------------------------------------------------------ +// Header parsing + +static void ResetSegmentHeader(VP8SegmentHeader* const hdr) { + assert(hdr != NULL); + hdr->use_segment_ = 0; + hdr->update_map_ = 0; + hdr->absolute_delta_ = 1; + memset(hdr->quantizer_, 0, sizeof(hdr->quantizer_)); + memset(hdr->filter_strength_, 0, sizeof(hdr->filter_strength_)); +} + +// Paragraph 9.3 +static int ParseSegmentHeader(VP8BitReader* br, + VP8SegmentHeader* hdr, VP8Proba* proba) { + assert(br != NULL); + assert(hdr != NULL); + hdr->use_segment_ = VP8Get(br, "global-header"); + if (hdr->use_segment_) { + hdr->update_map_ = VP8Get(br, "global-header"); + if (VP8Get(br, "global-header")) { // update data + int s; + hdr->absolute_delta_ = VP8Get(br, "global-header"); + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + hdr->quantizer_[s] = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 7, "global-header") : 0; + } + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + hdr->filter_strength_[s] = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 6, "global-header") : 0; + } + } + if (hdr->update_map_) { + int s; + for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { + proba->segments_[s] = VP8Get(br, "global-header") ? + VP8GetValue(br, 8, "global-header") : 255u; + } + } + } else { + hdr->update_map_ = 0; + } + return !br->eof_; +} + +// Paragraph 9.5 +// If we don't have all the necessary data in 'buf', this function returns +// VP8_STATUS_SUSPENDED in incremental decoding, VP8_STATUS_NOT_ENOUGH_DATA +// otherwise. +// In incremental decoding, this case is not necessarily an error. Still, no +// bitreader is ever initialized to make it possible to read unavailable memory. +// If we don't even have the partitions' sizes, then VP8_STATUS_NOT_ENOUGH_DATA +// is returned, and this is an unrecoverable error. +// If the partitions were positioned ok, VP8_STATUS_OK is returned. +static VP8StatusCode ParsePartitions(VP8Decoder* const dec, + const uint8_t* buf, size_t size) { + VP8BitReader* const br = &dec->br_; + const uint8_t* sz = buf; + const uint8_t* buf_end = buf + size; + const uint8_t* part_start; + size_t size_left = size; + size_t last_part; + size_t p; + + dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2, "global-header")) - 1; + last_part = dec->num_parts_minus_one_; + if (size < 3 * last_part) { + // we can't even read the sizes with sz[]! That's a failure. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + part_start = buf + last_part * 3; + size_left -= last_part * 3; + for (p = 0; p < last_part; ++p) { + size_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16); + if (psize > size_left) psize = size_left; + VP8InitBitReader(dec->parts_ + p, part_start, psize); + part_start += psize; + size_left -= psize; + sz += 3; + } + VP8InitBitReader(dec->parts_ + last_part, part_start, size_left); + if (part_start < buf_end) return VP8_STATUS_OK; + return dec->incremental_ + ? VP8_STATUS_SUSPENDED // Init is ok, but there's not enough data + : VP8_STATUS_NOT_ENOUGH_DATA; +} + +// Paragraph 9.4 +static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { + VP8FilterHeader* const hdr = &dec->filter_hdr_; + hdr->simple_ = VP8Get(br, "global-header"); + hdr->level_ = VP8GetValue(br, 6, "global-header"); + hdr->sharpness_ = VP8GetValue(br, 3, "global-header"); + hdr->use_lf_delta_ = VP8Get(br, "global-header"); + if (hdr->use_lf_delta_) { + if (VP8Get(br, "global-header")) { // update lf-delta? + int i; + for (i = 0; i < NUM_REF_LF_DELTAS; ++i) { + if (VP8Get(br, "global-header")) { + hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); + } + } + for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) { + if (VP8Get(br, "global-header")) { + hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); + } + } + } + } + dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2; + return !br->eof_; +} + +// Topmost call +int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { + const uint8_t* buf; + size_t buf_size; + VP8FrameHeader* frm_hdr; + VP8PictureHeader* pic_hdr; + VP8BitReader* br; + VP8StatusCode status; + + if (dec == NULL) { + return 0; + } + SetOk(dec); + if (io == NULL) { + return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, + "null VP8Io passed to VP8GetHeaders()"); + } + buf = io->data; + buf_size = io->data_size; + if (buf_size < 4) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "Truncated header."); + } + + // Paragraph 9.1 + { + const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16); + frm_hdr = &dec->frm_hdr_; + frm_hdr->key_frame_ = !(bits & 1); + frm_hdr->profile_ = (bits >> 1) & 7; + frm_hdr->show_ = (bits >> 4) & 1; + frm_hdr->partition_length_ = (bits >> 5); + if (frm_hdr->profile_ > 3) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "Incorrect keyframe parameters."); + } + if (!frm_hdr->show_) { + return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, + "Frame not displayable."); + } + buf += 3; + buf_size -= 3; + } + + pic_hdr = &dec->pic_hdr_; + if (frm_hdr->key_frame_) { + // Paragraph 9.2 + if (buf_size < 7) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "cannot parse picture header"); + } + if (!VP8CheckSignature(buf, buf_size)) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "Bad code word"); + } + pic_hdr->width_ = ((buf[4] << 8) | buf[3]) & 0x3fff; + pic_hdr->xscale_ = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2 + pic_hdr->height_ = ((buf[6] << 8) | buf[5]) & 0x3fff; + pic_hdr->yscale_ = buf[6] >> 6; + buf += 7; + buf_size -= 7; + + dec->mb_w_ = (pic_hdr->width_ + 15) >> 4; + dec->mb_h_ = (pic_hdr->height_ + 15) >> 4; + + // Setup default output area (can be later modified during io->setup()) + io->width = pic_hdr->width_; + io->height = pic_hdr->height_; + // IMPORTANT! use some sane dimensions in crop_* and scaled_* fields. + // So they can be used interchangeably without always testing for + // 'use_cropping'. + io->use_cropping = 0; + io->crop_top = 0; + io->crop_left = 0; + io->crop_right = io->width; + io->crop_bottom = io->height; + io->use_scaling = 0; + io->scaled_width = io->width; + io->scaled_height = io->height; + + io->mb_w = io->width; // for soundness + io->mb_h = io->height; // ditto + + VP8ResetProba(&dec->proba_); + ResetSegmentHeader(&dec->segment_hdr_); + } + + // Check if we have all the partition #0 available, and initialize dec->br_ + // to read this partition (and this partition only). + if (frm_hdr->partition_length_ > buf_size) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "bad partition length"); + } + + br = &dec->br_; + VP8InitBitReader(br, buf, frm_hdr->partition_length_); + buf += frm_hdr->partition_length_; + buf_size -= frm_hdr->partition_length_; + + if (frm_hdr->key_frame_) { + pic_hdr->colorspace_ = VP8Get(br, "global-header"); + pic_hdr->clamp_type_ = VP8Get(br, "global-header"); + } + if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "cannot parse segment header"); + } + // Filter specs + if (!ParseFilterHeader(br, dec)) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "cannot parse filter header"); + } + status = ParsePartitions(dec, buf, buf_size); + if (status != VP8_STATUS_OK) { + return VP8SetError(dec, status, "cannot parse partitions"); + } + + // quantizer change + VP8ParseQuant(dec); + + // Frame buffer marking + if (!frm_hdr->key_frame_) { + return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, + "Not a key frame."); + } + + VP8Get(br, "global-header"); // ignore the value of update_proba_ + + VP8ParseProba(br, dec); + + // sanitized state + dec->ready_ = 1; + return 1; +} + +//------------------------------------------------------------------------------ +// Residual decoding (Paragraph 13.2 / 13.3) + +static const uint8_t kCat3[] = { 173, 148, 140, 0 }; +static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 }; +static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 }; +static const uint8_t kCat6[] = + { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 }; +static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 }; +static const uint8_t kZigzag[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + +// See section 13-2: https://datatracker.ietf.org/doc/html/rfc6386#section-13.2 +static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { + int v; + if (!VP8GetBit(br, p[3], "coeffs")) { + if (!VP8GetBit(br, p[4], "coeffs")) { + v = 2; + } else { + v = 3 + VP8GetBit(br, p[5], "coeffs"); + } + } else { + if (!VP8GetBit(br, p[6], "coeffs")) { + if (!VP8GetBit(br, p[7], "coeffs")) { + v = 5 + VP8GetBit(br, 159, "coeffs"); + } else { + v = 7 + 2 * VP8GetBit(br, 165, "coeffs"); + v += VP8GetBit(br, 145, "coeffs"); + } + } else { + const uint8_t* tab; + const int bit1 = VP8GetBit(br, p[8], "coeffs"); + const int bit0 = VP8GetBit(br, p[9 + bit1], "coeffs"); + const int cat = 2 * bit1 + bit0; + v = 0; + for (tab = kCat3456[cat]; *tab; ++tab) { + v += v + VP8GetBit(br, *tab, "coeffs"); + } + v += 3 + (8 << cat); + } + } + return v; +} + +// Returns the position of the last non-zero coeff plus one +static int GetCoeffsFast(VP8BitReader* const br, + const VP8BandProbas* const prob[], + int ctx, const quant_t dq, int n, int16_t* out) { + const uint8_t* p = prob[n]->probas_[ctx]; + for (; n < 16; ++n) { + if (!VP8GetBit(br, p[0], "coeffs")) { + return n; // previous coeff was last non-zero coeff + } + while (!VP8GetBit(br, p[1], "coeffs")) { // sequence of zero coeffs + p = prob[++n]->probas_[0]; + if (n == 16) return 16; + } + { // non zero coeff + const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; + int v; + if (!VP8GetBit(br, p[2], "coeffs")) { + v = 1; + p = p_ctx[1]; + } else { + v = GetLargeValue(br, p); + p = p_ctx[2]; + } + out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; + } + } + return 16; +} + +// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version +// of VP8GetBitAlt() targeting specific platforms. +static int GetCoeffsAlt(VP8BitReader* const br, + const VP8BandProbas* const prob[], + int ctx, const quant_t dq, int n, int16_t* out) { + const uint8_t* p = prob[n]->probas_[ctx]; + for (; n < 16; ++n) { + if (!VP8GetBitAlt(br, p[0], "coeffs")) { + return n; // previous coeff was last non-zero coeff + } + while (!VP8GetBitAlt(br, p[1], "coeffs")) { // sequence of zero coeffs + p = prob[++n]->probas_[0]; + if (n == 16) return 16; + } + { // non zero coeff + const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; + int v; + if (!VP8GetBitAlt(br, p[2], "coeffs")) { + v = 1; + p = p_ctx[1]; + } else { + v = GetLargeValue(br, p); + p = p_ctx[2]; + } + out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; + } + } + return 16; +} + +extern VP8CPUInfo VP8GetCPUInfo; + +WEBP_DSP_INIT_FUNC(InitGetCoeffs) { + if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) { + GetCoeffs = GetCoeffsAlt; + } else { + GetCoeffs = GetCoeffsFast; + } +} + +static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) { + nz_coeffs <<= 2; + nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz; + return nz_coeffs; +} + +static int ParseResiduals(VP8Decoder* const dec, + VP8MB* const mb, VP8BitReader* const token_br) { + const VP8BandProbas* (* const bands)[16 + 1] = dec->proba_.bands_ptr_; + const VP8BandProbas* const * ac_proba; + VP8MBData* const block = dec->mb_data_ + dec->mb_x_; + const VP8QuantMatrix* const q = &dec->dqm_[block->segment_]; + int16_t* dst = block->coeffs_; + VP8MB* const left_mb = dec->mb_info_ - 1; + uint8_t tnz, lnz; + uint32_t non_zero_y = 0; + uint32_t non_zero_uv = 0; + int x, y, ch; + uint32_t out_t_nz, out_l_nz; + int first; + + memset(dst, 0, 384 * sizeof(*dst)); + if (!block->is_i4x4_) { // parse DC + int16_t dc[16] = { 0 }; + const int ctx = mb->nz_dc_ + left_mb->nz_dc_; + const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc); + mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0); + if (nz > 1) { // more than just the DC -> perform the full transform + VP8TransformWHT(dc, dst); + } else { // only DC is non-zero -> inlined simplified transform + int i; + const int dc0 = (dc[0] + 3) >> 3; + for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0; + } + first = 1; + ac_proba = bands[0]; + } else { + first = 0; + ac_proba = bands[3]; + } + + tnz = mb->nz_ & 0x0f; + lnz = left_mb->nz_ & 0x0f; + for (y = 0; y < 4; ++y) { + int l = lnz & 1; + uint32_t nz_coeffs = 0; + for (x = 0; x < 4; ++x) { + const int ctx = l + (tnz & 1); + const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst); + l = (nz > first); + tnz = (tnz >> 1) | (l << 7); + nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); + dst += 16; + } + tnz >>= 4; + lnz = (lnz >> 1) | (l << 7); + non_zero_y = (non_zero_y << 8) | nz_coeffs; + } + out_t_nz = tnz; + out_l_nz = lnz >> 4; + + for (ch = 0; ch < 4; ch += 2) { + uint32_t nz_coeffs = 0; + tnz = mb->nz_ >> (4 + ch); + lnz = left_mb->nz_ >> (4 + ch); + for (y = 0; y < 2; ++y) { + int l = lnz & 1; + for (x = 0; x < 2; ++x) { + const int ctx = l + (tnz & 1); + const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst); + l = (nz > 0); + tnz = (tnz >> 1) | (l << 3); + nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); + dst += 16; + } + tnz >>= 2; + lnz = (lnz >> 1) | (l << 5); + } + // Note: we don't really need the per-4x4 details for U/V blocks. + non_zero_uv |= nz_coeffs << (4 * ch); + out_t_nz |= (tnz << 4) << ch; + out_l_nz |= (lnz & 0xf0) << ch; + } + mb->nz_ = out_t_nz; + left_mb->nz_ = out_l_nz; + + block->non_zero_y_ = non_zero_y; + block->non_zero_uv_ = non_zero_uv; + + // We look at the mode-code of each block and check if some blocks have less + // than three non-zero coeffs (code < 2). This is to avoid dithering flat and + // empty blocks. + block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_; + + return !(non_zero_y | non_zero_uv); // will be used for further optimization +} + +//------------------------------------------------------------------------------ +// Main loop + +int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) { + VP8MB* const left = dec->mb_info_ - 1; + VP8MB* const mb = dec->mb_info_ + dec->mb_x_; + VP8MBData* const block = dec->mb_data_ + dec->mb_x_; + int skip = dec->use_skip_proba_ ? block->skip_ : 0; + + if (!skip) { + skip = ParseResiduals(dec, mb, token_br); + } else { + left->nz_ = mb->nz_ = 0; + if (!block->is_i4x4_) { + left->nz_dc_ = mb->nz_dc_ = 0; + } + block->non_zero_y_ = 0; + block->non_zero_uv_ = 0; + block->dither_ = 0; + } + + if (dec->filter_type_ > 0) { // store filter info + VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_; + *finfo = dec->fstrengths_[block->segment_][block->is_i4x4_]; + finfo->f_inner_ |= !skip; + } + + return !token_br->eof_; +} + +void VP8InitScanline(VP8Decoder* const dec) { + VP8MB* const left = dec->mb_info_ - 1; + left->nz_ = 0; + left->nz_dc_ = 0; + memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_)); + dec->mb_x_ = 0; +} + +static int ParseFrame(VP8Decoder* const dec, VP8Io* io) { + for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) { + // Parse bitstream for this row. + VP8BitReader* const token_br = + &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_]; + if (!VP8ParseIntraModeRow(&dec->br_, dec)) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "Premature end-of-partition0 encountered."); + } + for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { + if (!VP8DecodeMB(dec, token_br)) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "Premature end-of-file encountered."); + } + } + VP8InitScanline(dec); // Prepare for next scanline + + // Reconstruct, filter and emit the row. + if (!VP8ProcessRow(dec, io)) { + return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted."); + } + } + if (dec->mt_method_ > 0) { + if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0; + } + + return 1; +} + +// Main entry point +int VP8Decode(VP8Decoder* const dec, VP8Io* const io) { + int ok = 0; + if (dec == NULL) { + return 0; + } + if (io == NULL) { + return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, + "NULL VP8Io parameter in VP8Decode()."); + } + + if (!dec->ready_) { + if (!VP8GetHeaders(dec, io)) { + return 0; + } + } + assert(dec->ready_); + + // Finish setting up the decoding parameter. Will call io->setup(). + ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK); + if (ok) { // good to go. + // Will allocate memory and prepare everything. + if (ok) ok = VP8InitFrame(dec, io); + + // Main decoding loop + if (ok) ok = ParseFrame(dec, io); + + // Exit. + ok &= VP8ExitCritical(dec, io); + } + + if (!ok) { + VP8Clear(dec); + return 0; + } + + dec->ready_ = 0; + return ok; +} + +void VP8Clear(VP8Decoder* const dec) { + if (dec == NULL) { + return; + } + WebPGetWorkerInterface()->End(&dec->worker_); + WebPDeallocateAlphaMemory(dec); + WebPSafeFree(dec->mem_); + dec->mem_ = NULL; + dec->mem_size_ = 0; + memset(&dec->br_, 0, sizeof(dec->br_)); + dec->ready_ = 0; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dec/vp8_dec.h b/libraries/webp/src/dec/vp8_dec.h new file mode 100644 index 0000000000..c649539cf2 --- /dev/null +++ b/libraries/webp/src/dec/vp8_dec.h @@ -0,0 +1,184 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Low-level API for VP8 decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DEC_VP8_DEC_H_ +#define WEBP_DEC_VP8_DEC_H_ + +#include "include/webp/decode.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Lower-level API +// +// These functions provide fine-grained control of the decoding process. +// The call flow should resemble: +// +// VP8Io io; +// VP8InitIo(&io); +// io.data = data; +// io.data_size = size; +// /* customize io's functions (setup()/put()/teardown()) if needed. */ +// +// VP8Decoder* dec = VP8New(); +// int ok = VP8Decode(dec, &io); +// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); +// VP8Delete(dec); +// return ok; + +// Input / Output +typedef struct VP8Io VP8Io; +typedef int (*VP8IoPutHook)(const VP8Io* io); +typedef int (*VP8IoSetupHook)(VP8Io* io); +typedef void (*VP8IoTeardownHook)(const VP8Io* io); + +struct VP8Io { + // set by VP8GetHeaders() + int width, height; // picture dimensions, in pixels (invariable). + // These are the original, uncropped dimensions. + // The actual area passed to put() is stored + // in mb_w / mb_h fields. + + // set before calling put() + int mb_y; // position of the current rows (in pixels) + int mb_w; // number of columns in the sample + int mb_h; // number of rows in the sample + const uint8_t* y, *u, *v; // rows to copy (in yuv420 format) + int y_stride; // row stride for luma + int uv_stride; // row stride for chroma + + void* opaque; // user data + + // called when fresh samples are available. Currently, samples are in + // YUV420 format, and can be up to width x 24 in size (depending on the + // in-loop filtering level, e.g.). Should return false in case of error + // or abort request. The actual size of the area to update is mb_w x mb_h + // in size, taking cropping into account. + VP8IoPutHook put; + + // called just before starting to decode the blocks. + // Must return false in case of setup error, true otherwise. If false is + // returned, teardown() will NOT be called. But if the setup succeeded + // and true is returned, then teardown() will always be called afterward. + VP8IoSetupHook setup; + + // Called just after block decoding is finished (or when an error occurred + // during put()). Is NOT called if setup() failed. + VP8IoTeardownHook teardown; + + // this is a recommendation for the user-side yuv->rgb converter. This flag + // is set when calling setup() hook and can be overwritten by it. It then + // can be taken into consideration during the put() method. + int fancy_upsampling; + + // Input buffer. + size_t data_size; + const uint8_t* data; + + // If true, in-loop filtering will not be performed even if present in the + // bitstream. Switching off filtering may speed up decoding at the expense + // of more visible blocking. Note that output will also be non-compliant + // with the VP8 specifications. + int bypass_filtering; + + // Cropping parameters. + int use_cropping; + int crop_left, crop_right, crop_top, crop_bottom; + + // Scaling parameters. + int use_scaling; + int scaled_width, scaled_height; + + // If non NULL, pointer to the alpha data (if present) corresponding to the + // start of the current row (That is: it is pre-offset by mb_y and takes + // cropping into account). + const uint8_t* a; +}; + +// Internal, version-checked, entry point +WEBP_NODISCARD int VP8InitIoInternal(VP8Io* const, int); + +// Set the custom IO function pointers and user-data. The setter for IO hooks +// should be called before initiating incremental decoding. Returns true if +// WebPIDecoder object is successfully modified, false otherwise. +WEBP_NODISCARD int WebPISetIOHooks(WebPIDecoder* const idec, VP8IoPutHook put, + VP8IoSetupHook setup, + VP8IoTeardownHook teardown, void* user_data); + +// Main decoding object. This is an opaque structure. +typedef struct VP8Decoder VP8Decoder; + +// Create a new decoder object. +VP8Decoder* VP8New(void); + +// Must be called to make sure 'io' is initialized properly. +// Returns false in case of version mismatch. Upon such failure, no other +// decoding function should be called (VP8Decode, VP8GetHeaders, ...) +WEBP_NODISCARD static WEBP_INLINE int VP8InitIo(VP8Io* const io) { + return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION); +} + +// Decode the VP8 frame header. Returns true if ok. +// Note: 'io->data' must be pointing to the start of the VP8 frame header. +WEBP_NODISCARD int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); + +// Decode a picture. Will call VP8GetHeaders() if it wasn't done already. +// Returns false in case of error. +WEBP_NODISCARD int VP8Decode(VP8Decoder* const dec, VP8Io* const io); + +// Return current status of the decoder: +VP8StatusCode VP8Status(VP8Decoder* const dec); + +// return readable string corresponding to the last status. +const char* VP8StatusMessage(VP8Decoder* const dec); + +// Resets the decoder in its initial state, reclaiming memory. +// Not a mandatory call between calls to VP8Decode(). +void VP8Clear(VP8Decoder* const dec); + +// Destroy the decoder object. +void VP8Delete(VP8Decoder* const dec); + +//------------------------------------------------------------------------------ +// Miscellaneous VP8/VP8L bitstream probing functions. + +// Returns true if the next 3 bytes in data contain the VP8 signature. +WEBP_EXTERN int VP8CheckSignature(const uint8_t* const data, size_t data_size); + +// Validates the VP8 data-header and retrieves basic header information viz +// width and height. Returns 0 in case of formatting error. *width/*height +// can be passed NULL. +WEBP_EXTERN int VP8GetInfo( + const uint8_t* data, + size_t data_size, // data available so far + size_t chunk_size, // total data size expected in the chunk + int* const width, int* const height); + +// Returns true if the next byte(s) in data is a VP8L signature. +WEBP_EXTERN int VP8LCheckSignature(const uint8_t* const data, size_t size); + +// Validates the VP8L data-header and retrieves basic header information viz +// width, height and alpha. Returns 0 in case of formatting error. +// width/height/has_alpha can be passed NULL. +WEBP_EXTERN int VP8LGetInfo( + const uint8_t* data, size_t data_size, // data available so far + int* const width, int* const height, int* const has_alpha); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_VP8_DEC_H_ diff --git a/libraries/webp/src/dec/vp8i_dec.h b/libraries/webp/src/dec/vp8i_dec.h new file mode 100644 index 0000000000..e46bf50f10 --- /dev/null +++ b/libraries/webp/src/dec/vp8i_dec.h @@ -0,0 +1,322 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// VP8 decoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DEC_VP8I_DEC_H_ +#define WEBP_DEC_VP8I_DEC_H_ + +#include // for memcpy() +#include "src/dec/common_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/random_utils.h" +#include "src/utils/thread_utils.h" +#include "src/dsp/dsp.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Various defines and enums + +// version numbers +#define DEC_MAJ_VERSION 1 +#define DEC_MIN_VERSION 3 +#define DEC_REV_VERSION 2 + +// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). +// Constraints are: We need to store one 16x16 block of luma samples (y), +// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned, +// in order to be SIMD-friendly. We also need to store the top, left and +// top-left samples (from previously decoded blocks), along with four +// extra top-right samples for luma (intra4x4 prediction only). +// One possible layout is, using 32 * (17 + 9) bytes: +// +// .+------ <- only 1 pixel high +// .|yyyyt. +// .|yyyyt. +// .|yyyyt. +// .|yyyy.. +// .+--.+-- <- only 1 pixel high +// .|uu.|vv +// .|uu.|vv +// +// Every character is a 4x4 block, with legend: +// '.' = unused +// 'y' = y-samples 'u' = u-samples 'v' = u-samples +// '|' = left sample, '-' = top sample, '+' = top-left sample +// 't' = extra top-right sample for 4x4 modes +#define YUV_SIZE (BPS * 17 + BPS * 9) +#define Y_OFF (BPS * 1 + 8) +#define U_OFF (Y_OFF + BPS * 16 + BPS) +#define V_OFF (U_OFF + 16) + +// minimal width under which lossy multi-threading is always disabled +#define MIN_WIDTH_FOR_THREADS 512 + +//------------------------------------------------------------------------------ +// Headers + +typedef struct { + uint8_t key_frame_; + uint8_t profile_; + uint8_t show_; + uint32_t partition_length_; +} VP8FrameHeader; + +typedef struct { + uint16_t width_; + uint16_t height_; + uint8_t xscale_; + uint8_t yscale_; + uint8_t colorspace_; // 0 = YCbCr + uint8_t clamp_type_; +} VP8PictureHeader; + +// segment features +typedef struct { + int use_segment_; + int update_map_; // whether to update the segment map or not + int absolute_delta_; // absolute or delta values for quantizer and filter + int8_t quantizer_[NUM_MB_SEGMENTS]; // quantization changes + int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments +} VP8SegmentHeader; + +// probas associated to one of the contexts +typedef uint8_t VP8ProbaArray[NUM_PROBAS]; + +typedef struct { // all the probas associated to one band + VP8ProbaArray probas_[NUM_CTX]; +} VP8BandProbas; + +// Struct collecting all frame-persistent probabilities. +typedef struct { + uint8_t segments_[MB_FEATURE_TREE_PROBS]; + // Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4 + VP8BandProbas bands_[NUM_TYPES][NUM_BANDS]; + const VP8BandProbas* bands_ptr_[NUM_TYPES][16 + 1]; +} VP8Proba; + +// Filter parameters +typedef struct { + int simple_; // 0=complex, 1=simple + int level_; // [0..63] + int sharpness_; // [0..7] + int use_lf_delta_; + int ref_lf_delta_[NUM_REF_LF_DELTAS]; + int mode_lf_delta_[NUM_MODE_LF_DELTAS]; +} VP8FilterHeader; + +//------------------------------------------------------------------------------ +// Informations about the macroblocks. + +typedef struct { // filter specs + uint8_t f_limit_; // filter limit in [3..189], or 0 if no filtering + uint8_t f_ilevel_; // inner limit in [1..63] + uint8_t f_inner_; // do inner filtering? + uint8_t hev_thresh_; // high edge variance threshold in [0..2] +} VP8FInfo; + +typedef struct { // Top/Left Contexts used for syntax-parsing + uint8_t nz_; // non-zero AC/DC coeffs (4bit for luma + 4bit for chroma) + uint8_t nz_dc_; // non-zero DC coeff (1bit) +} VP8MB; + +// Dequantization matrices +typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower). +typedef struct { + quant_t y1_mat_, y2_mat_, uv_mat_; + + int uv_quant_; // U/V quantizer value + int dither_; // dithering amplitude (0 = off, max=255) +} VP8QuantMatrix; + +// Data needed to reconstruct a macroblock +typedef struct { + int16_t coeffs_[384]; // 384 coeffs = (16+4+4) * 4*4 + uint8_t is_i4x4_; // true if intra4x4 + uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes + uint8_t uvmode_; // chroma prediction mode + // bit-wise info about the content of each sub-4x4 blocks (in decoding order). + // Each of the 4x4 blocks for y/u/v is associated with a 2b code according to: + // code=0 -> no coefficient + // code=1 -> only DC + // code=2 -> first three coefficients are non-zero + // code=3 -> more than three coefficients are non-zero + // This allows to call specialized transform functions. + uint32_t non_zero_y_; + uint32_t non_zero_uv_; + uint8_t dither_; // local dithering strength (deduced from non_zero_*) + uint8_t skip_; + uint8_t segment_; +} VP8MBData; + +// Persistent information needed by the parallel processing +typedef struct { + int id_; // cache row to process (in [0..2]) + int mb_y_; // macroblock position of the row + int filter_row_; // true if row-filtering is needed + VP8FInfo* f_info_; // filter strengths (swapped with dec->f_info_) + VP8MBData* mb_data_; // reconstruction data (swapped with dec->mb_data_) + VP8Io io_; // copy of the VP8Io to pass to put() +} VP8ThreadContext; + +// Saved top samples, per macroblock. Fits into a cache-line. +typedef struct { + uint8_t y[16], u[8], v[8]; +} VP8TopSamples; + +//------------------------------------------------------------------------------ +// VP8Decoder: the main opaque structure handed over to user + +struct VP8Decoder { + VP8StatusCode status_; + int ready_; // true if ready to decode a picture with VP8Decode() + const char* error_msg_; // set when status_ is not OK. + + // Main data source + VP8BitReader br_; + int incremental_; // if true, incremental decoding is expected + + // headers + VP8FrameHeader frm_hdr_; + VP8PictureHeader pic_hdr_; + VP8FilterHeader filter_hdr_; + VP8SegmentHeader segment_hdr_; + + // Worker + WebPWorker worker_; + int mt_method_; // multi-thread method: 0=off, 1=[parse+recon][filter] + // 2=[parse][recon+filter] + int cache_id_; // current cache row + int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3) + VP8ThreadContext thread_ctx_; // Thread context + + // dimension, in macroblock units. + int mb_w_, mb_h_; + + // Macroblock to process/filter, depending on cropping and filter_type. + int tl_mb_x_, tl_mb_y_; // top-left MB that must be in-loop filtered + int br_mb_x_, br_mb_y_; // last bottom-right MB that must be decoded + + // number of partitions minus one. + uint32_t num_parts_minus_one_; + // per-partition boolean decoders. + VP8BitReader parts_[MAX_NUM_PARTITIONS]; + + // Dithering strength, deduced from decoding options + int dither_; // whether to use dithering or not + VP8Random dithering_rg_; // random generator for dithering + + // dequantization (one set of DC/AC dequant factor per segment) + VP8QuantMatrix dqm_[NUM_MB_SEGMENTS]; + + // probabilities + VP8Proba proba_; + int use_skip_proba_; + uint8_t skip_p_; + + // Boundary data cache and persistent buffers. + uint8_t* intra_t_; // top intra modes values: 4 * mb_w_ + uint8_t intra_l_[4]; // left intra modes values + + VP8TopSamples* yuv_t_; // top y/u/v samples + + VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1) + VP8FInfo* f_info_; // filter strength info + uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE) + + uint8_t* cache_y_; // macroblock row for storing unfiltered samples + uint8_t* cache_u_; + uint8_t* cache_v_; + int cache_y_stride_; + int cache_uv_stride_; + + // main memory chunk for the above data. Persistent. + void* mem_; + size_t mem_size_; + + // Per macroblock non-persistent infos. + int mb_x_, mb_y_; // current position, in macroblock units + VP8MBData* mb_data_; // parsed reconstruction data + + // Filtering side-info + int filter_type_; // 0=off, 1=simple, 2=complex + VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type + + // Alpha + struct ALPHDecoder* alph_dec_; // alpha-plane decoder object + const uint8_t* alpha_data_; // compressed alpha data (if present) + size_t alpha_data_size_; + int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_ + uint8_t* alpha_plane_mem_; // memory allocated for alpha_plane_ + uint8_t* alpha_plane_; // output. Persistent, contains the whole data. + const uint8_t* alpha_prev_line_; // last decoded alpha row (or NULL) + int alpha_dithering_; // derived from decoding options (0=off, 100=full) +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +// in vp8.c +int VP8SetError(VP8Decoder* const dec, + VP8StatusCode error, const char* const msg); + +// in tree.c +void VP8ResetProba(VP8Proba* const proba); +void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec); +// parses one row of intra mode data in partition 0, returns !eof +int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec); + +// in quant.c +void VP8ParseQuant(VP8Decoder* const dec); + +// in frame.c +WEBP_NODISCARD int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); +// Call io->setup() and finish setting up scan parameters. +// After this call returns, one must always call VP8ExitCritical() with the +// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK +// if ok, otherwise sets and returns the error status on *dec. +VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io); +// Must always be called in pair with VP8EnterCritical(). +// Returns false in case of error. +WEBP_NODISCARD int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); +// Return the multi-threading method to use (0=off), depending +// on options and bitstream size. Only for lossy decoding. +int VP8GetThreadMethod(const WebPDecoderOptions* const options, + const WebPHeaderStructure* const headers, + int width, int height); +// Initialize dithering post-process if needed. +void VP8InitDithering(const WebPDecoderOptions* const options, + VP8Decoder* const dec); +// Process the last decoded row (filtering + output). +WEBP_NODISCARD int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); +// To be called at the start of a new scanline, to initialize predictors. +void VP8InitScanline(VP8Decoder* const dec); +// Decode one macroblock. Returns false if there is not enough data. +WEBP_NODISCARD int VP8DecodeMB(VP8Decoder* const dec, + VP8BitReader* const token_br); + +// in alpha.c +const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, + int row, int num_rows); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_VP8I_DEC_H_ diff --git a/libraries/webp/src/dec/vp8l_dec.c b/libraries/webp/src/dec/vp8l_dec.c new file mode 100644 index 0000000000..11c00ea964 --- /dev/null +++ b/libraries/webp/src/dec/vp8l_dec.c @@ -0,0 +1,1778 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// main entry for the decoder +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) + +#include +#include + +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/dsp/yuv.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" + +#define NUM_ARGB_CACHE_ROWS 16 + +static const int kCodeLengthLiterals = 16; +static const int kCodeLengthRepeatCode = 16; +static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 }; +static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; + +// ----------------------------------------------------------------------------- +// Five Huffman codes are used at each meta code: +// 1. green + length prefix codes + color cache codes, +// 2. alpha, +// 3. red, +// 4. blue, and, +// 5. distance prefix codes. +typedef enum { + GREEN = 0, + RED = 1, + BLUE = 2, + ALPHA = 3, + DIST = 4 +} HuffIndex; + +static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = { + NUM_LITERAL_CODES + NUM_LENGTH_CODES, + NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES, + NUM_DISTANCE_CODES +}; + +static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = { + 0, 1, 1, 1, 0 +}; + +#define NUM_CODE_LENGTH_CODES 19 +static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = { + 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +#define CODE_TO_PLANE_CODES 120 +static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = { + 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, + 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, + 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, + 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, + 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, + 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, + 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, + 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, + 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, + 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, + 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, + 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 +}; + +// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha +// and distance alphabets are constant (256 for red, blue and alpha, 40 for +// distance) and lookup table sizes for them in worst case are 630 and 410 +// respectively. Size of green alphabet depends on color cache size and is equal +// to 256 (green component values) + 24 (length prefix values) +// + color_cache_size (between 0 and 2048). +// All values computed for 8-bit first level lookup with Mark Adler's tool: +// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c +#define FIXED_TABLE_SIZE (630 * 3 + 410) +static const uint16_t kTableSize[12] = { + FIXED_TABLE_SIZE + 654, + FIXED_TABLE_SIZE + 656, + FIXED_TABLE_SIZE + 658, + FIXED_TABLE_SIZE + 662, + FIXED_TABLE_SIZE + 670, + FIXED_TABLE_SIZE + 686, + FIXED_TABLE_SIZE + 718, + FIXED_TABLE_SIZE + 782, + FIXED_TABLE_SIZE + 912, + FIXED_TABLE_SIZE + 1168, + FIXED_TABLE_SIZE + 1680, + FIXED_TABLE_SIZE + 2704 +}; + +static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) { + // The oldest error reported takes precedence over the new one. + if (dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED) { + dec->status_ = error; + } + return 0; +} + +static int DecodeImageStream(int xsize, int ysize, + int is_level0, + VP8LDecoder* const dec, + uint32_t** const decoded_data); + +//------------------------------------------------------------------------------ + +int VP8LCheckSignature(const uint8_t* const data, size_t size) { + return (size >= VP8L_FRAME_HEADER_SIZE && + data[0] == VP8L_MAGIC_BYTE && + (data[4] >> 5) == 0); // version +} + +static int ReadImageInfo(VP8LBitReader* const br, + int* const width, int* const height, + int* const has_alpha) { + if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0; + *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; + *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; + *has_alpha = VP8LReadBits(br, 1); + if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0; + return !br->eos_; +} + +int VP8LGetInfo(const uint8_t* data, size_t data_size, + int* const width, int* const height, int* const has_alpha) { + if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) { + return 0; // not enough data + } else if (!VP8LCheckSignature(data, data_size)) { + return 0; // bad signature + } else { + int w, h, a; + VP8LBitReader br; + VP8LInitBitReader(&br, data, data_size); + if (!ReadImageInfo(&br, &w, &h, &a)) { + return 0; + } + if (width != NULL) *width = w; + if (height != NULL) *height = h; + if (has_alpha != NULL) *has_alpha = a; + return 1; + } +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int GetCopyDistance(int distance_symbol, + VP8LBitReader* const br) { + int extra_bits, offset; + if (distance_symbol < 4) { + return distance_symbol + 1; + } + extra_bits = (distance_symbol - 2) >> 1; + offset = (2 + (distance_symbol & 1)) << extra_bits; + return offset + VP8LReadBits(br, extra_bits) + 1; +} + +static WEBP_INLINE int GetCopyLength(int length_symbol, + VP8LBitReader* const br) { + // Length and distance prefixes are encoded the same way. + return GetCopyDistance(length_symbol, br); +} + +static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) { + if (plane_code > CODE_TO_PLANE_CODES) { + return plane_code - CODE_TO_PLANE_CODES; + } else { + const int dist_code = kCodeToPlane[plane_code - 1]; + const int yoffset = dist_code >> 4; + const int xoffset = 8 - (dist_code & 0xf); + const int dist = yoffset * xsize + xoffset; + return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small + } +} + +//------------------------------------------------------------------------------ +// Decodes the next Huffman code from bit-stream. +// VP8LFillBitWindow(br) needs to be called at minimum every second call +// to ReadSymbol, in order to pre-fetch enough bits. +static WEBP_INLINE int ReadSymbol(const HuffmanCode* table, + VP8LBitReader* const br) { + int nbits; + uint32_t val = VP8LPrefetchBits(br); + table += val & HUFFMAN_TABLE_MASK; + nbits = table->bits - HUFFMAN_TABLE_BITS; + if (nbits > 0) { + VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS); + val = VP8LPrefetchBits(br); + table += table->value; + table += val & ((1 << nbits) - 1); + } + VP8LSetBitPos(br, br->bit_pos_ + table->bits); + return table->value; +} + +// Reads packed symbol depending on GREEN channel +#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask) +#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES +static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group, + VP8LBitReader* const br, + uint32_t* const dst) { + const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1); + const HuffmanCode32 code = group->packed_table[val]; + assert(group->use_packed_table); + if (code.bits < BITS_SPECIAL_MARKER) { + VP8LSetBitPos(br, br->bit_pos_ + code.bits); + *dst = code.value; + return PACKED_NON_LITERAL_CODE; + } else { + VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER); + assert(code.value >= NUM_LITERAL_CODES); + return code.value; + } +} + +static int AccumulateHCode(HuffmanCode hcode, int shift, + HuffmanCode32* const huff) { + huff->bits += hcode.bits; + huff->value |= (uint32_t)hcode.value << shift; + assert(huff->bits <= HUFFMAN_TABLE_BITS); + return hcode.bits; +} + +static void BuildPackedTable(HTreeGroup* const htree_group) { + uint32_t code; + for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) { + uint32_t bits = code; + HuffmanCode32* const huff = &htree_group->packed_table[bits]; + HuffmanCode hcode = htree_group->htrees[GREEN][bits]; + if (hcode.value >= NUM_LITERAL_CODES) { + huff->bits = hcode.bits + BITS_SPECIAL_MARKER; + huff->value = hcode.value; + } else { + huff->bits = 0; + huff->value = 0; + bits >>= AccumulateHCode(hcode, 8, huff); + bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff); + bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff); + bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff); + (void)bits; + } + } +} + +static int ReadHuffmanCodeLengths( + VP8LDecoder* const dec, const int* const code_length_code_lengths, + int num_symbols, int* const code_lengths) { + int ok = 0; + VP8LBitReader* const br = &dec->br_; + int symbol; + int max_symbol; + int prev_code_len = DEFAULT_CODE_LENGTH; + HuffmanTables tables; + + if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) || + !VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS, + code_length_code_lengths, NUM_CODE_LENGTH_CODES)) { + goto End; + } + + if (VP8LReadBits(br, 1)) { // use length + const int length_nbits = 2 + 2 * VP8LReadBits(br, 3); + max_symbol = 2 + VP8LReadBits(br, length_nbits); + if (max_symbol > num_symbols) { + goto End; + } + } else { + max_symbol = num_symbols; + } + + symbol = 0; + while (symbol < num_symbols) { + const HuffmanCode* p; + int code_len; + if (max_symbol-- == 0) break; + VP8LFillBitWindow(br); + p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK]; + VP8LSetBitPos(br, br->bit_pos_ + p->bits); + code_len = p->value; + if (code_len < kCodeLengthLiterals) { + code_lengths[symbol++] = code_len; + if (code_len != 0) prev_code_len = code_len; + } else { + const int use_prev = (code_len == kCodeLengthRepeatCode); + const int slot = code_len - kCodeLengthLiterals; + const int extra_bits = kCodeLengthExtraBits[slot]; + const int repeat_offset = kCodeLengthRepeatOffsets[slot]; + int repeat = VP8LReadBits(br, extra_bits) + repeat_offset; + if (symbol + repeat > num_symbols) { + goto End; + } else { + const int length = use_prev ? prev_code_len : 0; + while (repeat-- > 0) code_lengths[symbol++] = length; + } + } + } + ok = 1; + + End: + VP8LHuffmanTablesDeallocate(&tables); + if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + return ok; +} + +// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman +// tree. +static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, + int* const code_lengths, + HuffmanTables* const table) { + int ok = 0; + int size = 0; + VP8LBitReader* const br = &dec->br_; + const int simple_code = VP8LReadBits(br, 1); + + memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths)); + + if (simple_code) { // Read symbols, codes & code lengths directly. + const int num_symbols = VP8LReadBits(br, 1) + 1; + const int first_symbol_len_code = VP8LReadBits(br, 1); + // The first code is either 1 bit or 8 bit code. + int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8); + code_lengths[symbol] = 1; + // The second code (if present), is always 8 bits long. + if (num_symbols == 2) { + symbol = VP8LReadBits(br, 8); + code_lengths[symbol] = 1; + } + ok = 1; + } else { // Decode Huffman-coded code lengths. + int i; + int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; + const int num_codes = VP8LReadBits(br, 4) + 4; + assert(num_codes <= NUM_CODE_LENGTH_CODES); + + for (i = 0; i < num_codes; ++i) { + code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3); + } + ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size, + code_lengths); + } + + ok = ok && !br->eos_; + if (ok) { + size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, + code_lengths, alphabet_size); + } + if (!ok || size == 0) { + return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + } + return size; +} + +static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, + int color_cache_bits, int allow_recursion) { + int i; + VP8LBitReader* const br = &dec->br_; + VP8LMetadata* const hdr = &dec->hdr_; + uint32_t* huffman_image = NULL; + HTreeGroup* htree_groups = NULL; + HuffmanTables* huffman_tables = &hdr->huffman_tables_; + int num_htree_groups = 1; + int num_htree_groups_max = 1; + int* mapping = NULL; + int ok = 0; + + // Check the table has been 0 initialized (through InitMetadata). + assert(huffman_tables->root.start == NULL); + assert(huffman_tables->curr_segment == NULL); + + if (allow_recursion && VP8LReadBits(br, 1)) { + // use meta Huffman codes. + const int huffman_precision = VP8LReadBits(br, 3) + 2; + const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision); + const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); + const int huffman_pixs = huffman_xsize * huffman_ysize; + if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec, + &huffman_image)) { + goto Error; + } + hdr->huffman_subsample_bits_ = huffman_precision; + for (i = 0; i < huffman_pixs; ++i) { + // The huffman data is stored in red and green bytes. + const int group = (huffman_image[i] >> 8) & 0xffff; + huffman_image[i] = group; + if (group >= num_htree_groups_max) { + num_htree_groups_max = group + 1; + } + } + // Check the validity of num_htree_groups_max. If it seems too big, use a + // smaller value for later. This will prevent big memory allocations to end + // up with a bad bitstream anyway. + // The value of 1000 is totally arbitrary. We know that num_htree_groups_max + // is smaller than (1 << 16) and should be smaller than the number of pixels + // (though the format allows it to be bigger). + if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) { + // Create a mapping from the used indices to the minimal set of used + // values [0, num_htree_groups) + mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping)); + if (mapping == NULL) { + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto Error; + } + // -1 means a value is unmapped, and therefore unused in the Huffman + // image. + memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping)); + for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) { + // Get the current mapping for the group and remap the Huffman image. + int* const mapped_group = &mapping[huffman_image[i]]; + if (*mapped_group == -1) *mapped_group = num_htree_groups++; + huffman_image[i] = *mapped_group; + } + } else { + num_htree_groups = num_htree_groups_max; + } + } + + if (br->eos_) goto Error; + + if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups, + num_htree_groups_max, mapping, dec, + huffman_tables, &htree_groups)) { + goto Error; + } + ok = 1; + + // All OK. Finalize pointers. + hdr->huffman_image_ = huffman_image; + hdr->num_htree_groups_ = num_htree_groups; + hdr->htree_groups_ = htree_groups; + + Error: + WebPSafeFree(mapping); + if (!ok) { + WebPSafeFree(huffman_image); + VP8LHuffmanTablesDeallocate(huffman_tables); + VP8LHtreeGroupsFree(htree_groups); + } + return ok; +} + +int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups, + int num_htree_groups_max, const int* const mapping, + VP8LDecoder* const dec, + HuffmanTables* const huffman_tables, + HTreeGroup** const htree_groups) { + int i, j, ok = 0; + const int max_alphabet_size = + kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0); + const int table_size = kTableSize[color_cache_bits]; + int* code_lengths = NULL; + + if ((mapping == NULL && num_htree_groups != num_htree_groups_max) || + num_htree_groups > num_htree_groups_max) { + goto Error; + } + + code_lengths = + (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths)); + *htree_groups = VP8LHtreeGroupsNew(num_htree_groups); + + if (*htree_groups == NULL || code_lengths == NULL || + !VP8LHuffmanTablesAllocate(num_htree_groups * table_size, + huffman_tables)) { + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto Error; + } + + for (i = 0; i < num_htree_groups_max; ++i) { + // If the index "i" is unused in the Huffman image, just make sure the + // coefficients are valid but do not store them. + if (mapping != NULL && mapping[i] == -1) { + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + int alphabet_size = kAlphabetSize[j]; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += (1 << color_cache_bits); + } + // Passing in NULL so that nothing gets filled. + if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) { + goto Error; + } + } + } else { + HTreeGroup* const htree_group = + &(*htree_groups)[(mapping == NULL) ? i : mapping[i]]; + HuffmanCode** const htrees = htree_group->htrees; + int size; + int total_size = 0; + int is_trivial_literal = 1; + int max_bits = 0; + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + int alphabet_size = kAlphabetSize[j]; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += (1 << color_cache_bits); + } + size = + ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables); + htrees[j] = huffman_tables->curr_segment->curr_table; + if (size == 0) { + goto Error; + } + if (is_trivial_literal && kLiteralMap[j] == 1) { + is_trivial_literal = (htrees[j]->bits == 0); + } + total_size += htrees[j]->bits; + huffman_tables->curr_segment->curr_table += size; + if (j <= ALPHA) { + int local_max_bits = code_lengths[0]; + int k; + for (k = 1; k < alphabet_size; ++k) { + if (code_lengths[k] > local_max_bits) { + local_max_bits = code_lengths[k]; + } + } + max_bits += local_max_bits; + } + } + htree_group->is_trivial_literal = is_trivial_literal; + htree_group->is_trivial_code = 0; + if (is_trivial_literal) { + const int red = htrees[RED][0].value; + const int blue = htrees[BLUE][0].value; + const int alpha = htrees[ALPHA][0].value; + htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue; + if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { + htree_group->is_trivial_code = 1; + htree_group->literal_arb |= htrees[GREEN][0].value << 8; + } + } + htree_group->use_packed_table = + !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS); + if (htree_group->use_packed_table) BuildPackedTable(htree_group); + } + } + ok = 1; + + Error: + WebPSafeFree(code_lengths); + if (!ok) { + VP8LHuffmanTablesDeallocate(huffman_tables); + VP8LHtreeGroupsFree(*htree_groups); + *htree_groups = NULL; + } + return ok; +} + +//------------------------------------------------------------------------------ +// Scaling. + +#if !defined(WEBP_REDUCE_SIZE) +static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { + const int num_channels = 4; + const int in_width = io->mb_w; + const int out_width = io->scaled_width; + const int in_height = io->mb_h; + const int out_height = io->scaled_height; + const uint64_t work_size = 2 * num_channels * (uint64_t)out_width; + rescaler_t* work; // Rescaler work area. + const uint64_t scaled_data_size = (uint64_t)out_width; + uint32_t* scaled_data; // Temporary storage for scaled BGRA data. + const uint64_t memory_size = sizeof(*dec->rescaler) + + work_size * sizeof(*work) + + scaled_data_size * sizeof(*scaled_data); + uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory)); + if (memory == NULL) { + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } + assert(dec->rescaler_memory == NULL); + dec->rescaler_memory = memory; + + dec->rescaler = (WebPRescaler*)memory; + memory += sizeof(*dec->rescaler); + work = (rescaler_t*)memory; + memory += work_size * sizeof(*work); + scaled_data = (uint32_t*)memory; + + if (!WebPRescalerInit(dec->rescaler, in_width, in_height, + (uint8_t*)scaled_data, out_width, out_height, + 0, num_channels, work)) { + return 0; + } + return 1; +} +#endif // WEBP_REDUCE_SIZE + +//------------------------------------------------------------------------------ +// Export to ARGB + +#if !defined(WEBP_REDUCE_SIZE) + +// We have special "export" function since we need to convert from BGRA +static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, + int rgba_stride, uint8_t* const rgba) { + uint32_t* const src = (uint32_t*)rescaler->dst; + uint8_t* dst = rgba; + const int dst_width = rescaler->dst_width; + int num_lines_out = 0; + while (WebPRescalerHasPendingOutput(rescaler)) { + WebPRescalerExportRow(rescaler); + WebPMultARGBRow(src, dst_width, 1); + VP8LConvertFromBGRA(src, dst_width, colorspace, dst); + dst += rgba_stride; + ++num_lines_out; + } + return num_lines_out; +} + +// Emit scaled rows. +static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, + uint8_t* in, int in_stride, int mb_h, + uint8_t* const out, int out_stride) { + const WEBP_CSP_MODE colorspace = dec->output_->colorspace; + int num_lines_in = 0; + int num_lines_out = 0; + while (num_lines_in < mb_h) { + uint8_t* const row_in = in + (uint64_t)num_lines_in * in_stride; + uint8_t* const row_out = out + (uint64_t)num_lines_out * out_stride; + const int lines_left = mb_h - num_lines_in; + const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); + int lines_imported; + assert(needed_lines > 0 && needed_lines <= lines_left); + WebPMultARGBRows(row_in, in_stride, + dec->rescaler->src_width, needed_lines, 0); + lines_imported = + WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride); + assert(lines_imported == needed_lines); + num_lines_in += lines_imported; + num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); + } + return num_lines_out; +} + +#endif // WEBP_REDUCE_SIZE + +// Emit rows without any scaling. +static int EmitRows(WEBP_CSP_MODE colorspace, + const uint8_t* row_in, int in_stride, + int mb_w, int mb_h, + uint8_t* const out, int out_stride) { + int lines = mb_h; + uint8_t* row_out = out; + while (lines-- > 0) { + VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out); + row_in += in_stride; + row_out += out_stride; + } + return mb_h; // Num rows out == num rows in. +} + +//------------------------------------------------------------------------------ +// Export to YUVA + +static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos, + const WebPDecBuffer* const output) { + const WebPYUVABuffer* const buf = &output->u.YUVA; + + // first, the luma plane + WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width); + + // then U/V planes + { + uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride; + uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride; + // even lines: store values + // odd lines: average with previous values + WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1)); + } + // Lastly, store alpha if needed. + if (buf->a != NULL) { + uint8_t* const a = buf->a + y_pos * buf->a_stride; +#if defined(WORDS_BIGENDIAN) + WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0); +#else + WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0); +#endif + } +} + +static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) { + WebPRescaler* const rescaler = dec->rescaler; + uint32_t* const src = (uint32_t*)rescaler->dst; + const int dst_width = rescaler->dst_width; + int num_lines_out = 0; + while (WebPRescalerHasPendingOutput(rescaler)) { + WebPRescalerExportRow(rescaler); + WebPMultARGBRow(src, dst_width, 1); + ConvertToYUVA(src, dst_width, y_pos, dec->output_); + ++y_pos; + ++num_lines_out; + } + return num_lines_out; +} + +static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, + uint8_t* in, int in_stride, int mb_h) { + int num_lines_in = 0; + int y_pos = dec->last_out_row_; + while (num_lines_in < mb_h) { + const int lines_left = mb_h - num_lines_in; + const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); + int lines_imported; + WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0); + lines_imported = + WebPRescalerImport(dec->rescaler, lines_left, in, in_stride); + assert(lines_imported == needed_lines); + num_lines_in += lines_imported; + in += needed_lines * in_stride; + y_pos += ExportYUVA(dec, y_pos); + } + return y_pos; +} + +static int EmitRowsYUVA(const VP8LDecoder* const dec, + const uint8_t* in, int in_stride, + int mb_w, int num_rows) { + int y_pos = dec->last_out_row_; + while (num_rows-- > 0) { + ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_); + in += in_stride; + ++y_pos; + } + return y_pos; +} + +//------------------------------------------------------------------------------ +// Cropping. + +// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and +// crop options. Also updates the input data pointer, so that it points to the +// start of the cropped window. Note that pixels are in ARGB format even if +// 'in_data' is uint8_t*. +// Returns true if the crop window is not empty. +static int SetCropWindow(VP8Io* const io, int y_start, int y_end, + uint8_t** const in_data, int pixel_stride) { + assert(y_start < y_end); + assert(io->crop_left < io->crop_right); + if (y_end > io->crop_bottom) { + y_end = io->crop_bottom; // make sure we don't overflow on last row. + } + if (y_start < io->crop_top) { + const int delta = io->crop_top - y_start; + y_start = io->crop_top; + *in_data += delta * pixel_stride; + } + if (y_start >= y_end) return 0; // Crop window is empty. + + *in_data += io->crop_left * sizeof(uint32_t); + + io->mb_y = y_start - io->crop_top; + io->mb_w = io->crop_right - io->crop_left; + io->mb_h = y_end - y_start; + return 1; // Non-empty crop window. +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int GetMetaIndex( + const uint32_t* const image, int xsize, int bits, int x, int y) { + if (bits == 0) return 0; + return image[xsize * (y >> bits) + (x >> bits)]; +} + +static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr, + int x, int y) { + const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_, + hdr->huffman_subsample_bits_, x, y); + assert(meta_index < hdr->num_htree_groups_); + return hdr->htree_groups_ + meta_index; +} + +//------------------------------------------------------------------------------ +// Main loop, with custom row-processing function + +typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); + +static void ApplyInverseTransforms(VP8LDecoder* const dec, + int start_row, int num_rows, + const uint32_t* const rows) { + int n = dec->next_transform_; + const int cache_pixs = dec->width_ * num_rows; + const int end_row = start_row + num_rows; + const uint32_t* rows_in = rows; + uint32_t* const rows_out = dec->argb_cache_; + + // Inverse transforms. + while (n-- > 0) { + VP8LTransform* const transform = &dec->transforms_[n]; + VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); + rows_in = rows_out; + } + if (rows_in != rows_out) { + // No transform called, hence just copy. + memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); + } +} + +// Processes (transforms, scales & color-converts) the rows decoded after the +// last call. +static void ProcessRows(VP8LDecoder* const dec, int row) { + const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; + const int num_rows = row - dec->last_row_; + + assert(row <= dec->io_->crop_bottom); + // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size + // of argb_cache_), but we currently don't need more than that. + assert(num_rows <= NUM_ARGB_CACHE_ROWS); + if (num_rows > 0) { // Emit output. + VP8Io* const io = dec->io_; + uint8_t* rows_data = (uint8_t*)dec->argb_cache_; + const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA + ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows); + if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { + // Nothing to output (this time). + } else { + const WebPDecBuffer* const output = dec->output_; + if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA + const WebPRGBABuffer* const buf = &output->u.RGBA; + uint8_t* const rgba = + buf->rgba + (int64_t)dec->last_out_row_ * buf->stride; + const int num_rows_out = +#if !defined(WEBP_REDUCE_SIZE) + io->use_scaling ? + EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, + rgba, buf->stride) : +#endif // WEBP_REDUCE_SIZE + EmitRows(output->colorspace, rows_data, in_stride, + io->mb_w, io->mb_h, rgba, buf->stride); + // Update 'last_out_row_'. + dec->last_out_row_ += num_rows_out; + } else { // convert to YUVA + dec->last_out_row_ = io->use_scaling ? + EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) : + EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h); + } + assert(dec->last_out_row_ <= output->height); + } + } + + // Update 'last_row_'. + dec->last_row_ = row; + assert(dec->last_row_ <= dec->height_); +} + +// Row-processing for the special case when alpha data contains only one +// transform (color indexing), and trivial non-green literals. +static int Is8bOptimizable(const VP8LMetadata* const hdr) { + int i; + if (hdr->color_cache_size_ > 0) return 0; + // When the Huffman tree contains only one symbol, we can skip the + // call to ReadSymbol() for red/blue/alpha channels. + for (i = 0; i < hdr->num_htree_groups_; ++i) { + HuffmanCode** const htrees = hdr->htree_groups_[i].htrees; + if (htrees[RED][0].bits > 0) return 0; + if (htrees[BLUE][0].bits > 0) return 0; + if (htrees[ALPHA][0].bits > 0) return 0; + } + return 1; +} + +static void AlphaApplyFilter(ALPHDecoder* const alph_dec, + int first_row, int last_row, + uint8_t* out, int stride) { + if (alph_dec->filter_ != WEBP_FILTER_NONE) { + int y; + const uint8_t* prev_line = alph_dec->prev_line_; + assert(WebPUnfilters[alph_dec->filter_] != NULL); + for (y = first_row; y < last_row; ++y) { + WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride); + prev_line = out; + out += stride; + } + alph_dec->prev_line_ = prev_line; + } +} + +static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) { + // For vertical and gradient filtering, we need to decode the part above the + // crop_top row, in order to have the correct spatial predictors. + ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; + const int top_row = + (alph_dec->filter_ == WEBP_FILTER_NONE || + alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top + : dec->last_row_; + const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_; + assert(last_row <= dec->io_->crop_bottom); + if (last_row > first_row) { + // Special method for paletted alpha data. We only process the cropped area. + const int width = dec->io_->width; + uint8_t* out = alph_dec->output_ + width * first_row; + const uint8_t* const in = + (uint8_t*)dec->pixels_ + dec->width_ * first_row; + VP8LTransform* const transform = &dec->transforms_[0]; + assert(dec->next_transform_ == 1); + assert(transform->type_ == COLOR_INDEXING_TRANSFORM); + VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row, + in, out); + AlphaApplyFilter(alph_dec, first_row, last_row, out, width); + } + dec->last_row_ = dec->last_out_row_ = last_row; +} + +//------------------------------------------------------------------------------ +// Helper functions for fast pattern copy (8b and 32b) + +// cyclic rotation of pattern word +static WEBP_INLINE uint32_t Rotate8b(uint32_t V) { +#if defined(WORDS_BIGENDIAN) + return ((V & 0xff000000u) >> 24) | (V << 8); +#else + return ((V & 0xffu) << 24) | (V >> 8); +#endif +} + +// copy 1, 2 or 4-bytes pattern +static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst, + int length, uint32_t pattern) { + int i; + // align 'dst' to 4-bytes boundary. Adjust the pattern along the way. + while ((uintptr_t)dst & 3) { + *dst++ = *src++; + pattern = Rotate8b(pattern); + --length; + } + // Copy the pattern 4 bytes at a time. + for (i = 0; i < (length >> 2); ++i) { + ((uint32_t*)dst)[i] = pattern; + } + // Finish with left-overs. 'pattern' is still correctly positioned, + // so no Rotate8b() call is needed. + for (i <<= 2; i < length; ++i) { + dst[i] = src[i]; + } +} + +static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) { + const uint8_t* src = dst - dist; + if (length >= 8) { + uint32_t pattern = 0; + switch (dist) { + case 1: + pattern = src[0]; +#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much + pattern |= pattern << 8; + pattern |= pattern << 16; +#elif defined(WEBP_USE_MIPS_DSP_R2) + __asm__ volatile ("replv.qb %0, %0" : "+r"(pattern)); +#else + pattern = 0x01010101u * pattern; +#endif + break; + case 2: +#if !defined(WORDS_BIGENDIAN) + memcpy(&pattern, src, sizeof(uint16_t)); +#else + pattern = ((uint32_t)src[0] << 8) | src[1]; +#endif +#if defined(__arm__) || defined(_M_ARM) + pattern |= pattern << 16; +#elif defined(WEBP_USE_MIPS_DSP_R2) + __asm__ volatile ("replv.ph %0, %0" : "+r"(pattern)); +#else + pattern = 0x00010001u * pattern; +#endif + break; + case 4: + memcpy(&pattern, src, sizeof(uint32_t)); + break; + default: + goto Copy; + } + CopySmallPattern8b(src, dst, length, pattern); + return; + } + Copy: + if (dist >= length) { // no overlap -> use memcpy() + memcpy(dst, src, length * sizeof(*dst)); + } else { + int i; + for (i = 0; i < length; ++i) dst[i] = src[i]; + } +} + +// copy pattern of 1 or 2 uint32_t's +static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src, + uint32_t* dst, + int length, uint64_t pattern) { + int i; + if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary. + *dst++ = *src++; + pattern = (pattern >> 32) | (pattern << 32); + --length; + } + assert(0 == ((uintptr_t)dst & 7)); + for (i = 0; i < (length >> 1); ++i) { + ((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time. + } + if (length & 1) { // Finish with left-over. + dst[i << 1] = src[i << 1]; + } +} + +static WEBP_INLINE void CopyBlock32b(uint32_t* const dst, + int dist, int length) { + const uint32_t* const src = dst - dist; + if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) { + uint64_t pattern; + if (dist == 1) { + pattern = (uint64_t)src[0]; + pattern |= pattern << 32; + } else { + memcpy(&pattern, src, sizeof(pattern)); + } + CopySmallPattern32b(src, dst, length, pattern); + } else if (dist >= length) { // no overlap + memcpy(dst, src, length * sizeof(*dst)); + } else { + int i; + for (i = 0; i < length; ++i) dst[i] = src[i]; + } +} + +//------------------------------------------------------------------------------ + +static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, + int width, int height, int last_row) { + int ok = 1; + int row = dec->last_pixel_ / width; + int col = dec->last_pixel_ % width; + VP8LBitReader* const br = &dec->br_; + VP8LMetadata* const hdr = &dec->hdr_; + int pos = dec->last_pixel_; // current position + const int end = width * height; // End of data + const int last = width * last_row; // Last pixel to decode + const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; + const int mask = hdr->huffman_mask_; + const HTreeGroup* htree_group = + (pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL; + assert(pos <= end); + assert(last_row <= height); + assert(Is8bOptimizable(hdr)); + + while (!br->eos_ && pos < last) { + int code; + // Only update when changing tile. + if ((col & mask) == 0) { + htree_group = GetHtreeGroupForPos(hdr, col, row); + } + assert(htree_group != NULL); + VP8LFillBitWindow(br); + code = ReadSymbol(htree_group->htrees[GREEN], br); + if (code < NUM_LITERAL_CODES) { // Literal + data[pos] = code; + ++pos; + ++col; + if (col >= width) { + col = 0; + ++row; + if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { + ExtractPalettedAlphaRows(dec, row); + } + } + } else if (code < len_code_limit) { // Backward reference + int dist_code, dist; + const int length_sym = code - NUM_LITERAL_CODES; + const int length = GetCopyLength(length_sym, br); + const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); + VP8LFillBitWindow(br); + dist_code = GetCopyDistance(dist_symbol, br); + dist = PlaneCodeToDistance(width, dist_code); + if (pos >= dist && end - pos >= length) { + CopyBlock8b(data + pos, dist, length); + } else { + ok = 0; + goto End; + } + pos += length; + col += length; + while (col >= width) { + col -= width; + ++row; + if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { + ExtractPalettedAlphaRows(dec, row); + } + } + if (pos < last && (col & mask)) { + htree_group = GetHtreeGroupForPos(hdr, col, row); + } + } else { // Not reached + ok = 0; + goto End; + } + br->eos_ = VP8LIsEndOfStream(br); + } + // Process the remaining rows corresponding to last row-block. + ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row); + + End: + br->eos_ = VP8LIsEndOfStream(br); + if (!ok || (br->eos_ && pos < end)) { + return VP8LSetError( + dec, br->eos_ ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR); + } + dec->last_pixel_ = pos; + return ok; +} + +static void SaveState(VP8LDecoder* const dec, int last_pixel) { + assert(dec->incremental_); + dec->saved_br_ = dec->br_; + dec->saved_last_pixel_ = last_pixel; + if (dec->hdr_.color_cache_size_ > 0) { + VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_); + } +} + +static void RestoreState(VP8LDecoder* const dec) { + assert(dec->br_.eos_); + dec->status_ = VP8_STATUS_SUSPENDED; + dec->br_ = dec->saved_br_; + dec->last_pixel_ = dec->saved_last_pixel_; + if (dec->hdr_.color_cache_size_ > 0) { + VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_); + } +} + +#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points +static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, + int width, int height, int last_row, + ProcessRowsFunc process_func) { + int row = dec->last_pixel_ / width; + int col = dec->last_pixel_ % width; + VP8LBitReader* const br = &dec->br_; + VP8LMetadata* const hdr = &dec->hdr_; + uint32_t* src = data + dec->last_pixel_; + uint32_t* last_cached = src; + uint32_t* const src_end = data + width * height; // End of data + uint32_t* const src_last = data + width * last_row; // Last pixel to decode + const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; + const int color_cache_limit = len_code_limit + hdr->color_cache_size_; + int next_sync_row = dec->incremental_ ? row : 1 << 24; + VP8LColorCache* const color_cache = + (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; + const int mask = hdr->huffman_mask_; + const HTreeGroup* htree_group = + (src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL; + assert(dec->last_row_ < last_row); + assert(src_last <= src_end); + + while (src < src_last) { + int code; + if (row >= next_sync_row) { + SaveState(dec, (int)(src - data)); + next_sync_row = row + SYNC_EVERY_N_ROWS; + } + // Only update when changing tile. Note we could use this test: + // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed + // but that's actually slower and needs storing the previous col/row. + if ((col & mask) == 0) { + htree_group = GetHtreeGroupForPos(hdr, col, row); + } + assert(htree_group != NULL); + if (htree_group->is_trivial_code) { + *src = htree_group->literal_arb; + goto AdvanceByOne; + } + VP8LFillBitWindow(br); + if (htree_group->use_packed_table) { + code = ReadPackedSymbols(htree_group, br, src); + if (VP8LIsEndOfStream(br)) break; + if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; + } else { + code = ReadSymbol(htree_group->htrees[GREEN], br); + } + if (VP8LIsEndOfStream(br)) break; + if (code < NUM_LITERAL_CODES) { // Literal + if (htree_group->is_trivial_literal) { + *src = htree_group->literal_arb | (code << 8); + } else { + int red, blue, alpha; + red = ReadSymbol(htree_group->htrees[RED], br); + VP8LFillBitWindow(br); + blue = ReadSymbol(htree_group->htrees[BLUE], br); + alpha = ReadSymbol(htree_group->htrees[ALPHA], br); + if (VP8LIsEndOfStream(br)) break; + *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; + } + AdvanceByOne: + ++src; + ++col; + if (col >= width) { + col = 0; + ++row; + if (process_func != NULL) { + if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { + process_func(dec, row); + } + } + if (color_cache != NULL) { + while (last_cached < src) { + VP8LColorCacheInsert(color_cache, *last_cached++); + } + } + } + } else if (code < len_code_limit) { // Backward reference + int dist_code, dist; + const int length_sym = code - NUM_LITERAL_CODES; + const int length = GetCopyLength(length_sym, br); + const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); + VP8LFillBitWindow(br); + dist_code = GetCopyDistance(dist_symbol, br); + dist = PlaneCodeToDistance(width, dist_code); + + if (VP8LIsEndOfStream(br)) break; + if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { + goto Error; + } else { + CopyBlock32b(src, dist, length); + } + src += length; + col += length; + while (col >= width) { + col -= width; + ++row; + if (process_func != NULL) { + if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { + process_func(dec, row); + } + } + } + // Because of the check done above (before 'src' was incremented by + // 'length'), the following holds true. + assert(src <= src_end); + if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); + if (color_cache != NULL) { + while (last_cached < src) { + VP8LColorCacheInsert(color_cache, *last_cached++); + } + } + } else if (code < color_cache_limit) { // Color cache + const int key = code - len_code_limit; + assert(color_cache != NULL); + while (last_cached < src) { + VP8LColorCacheInsert(color_cache, *last_cached++); + } + *src = VP8LColorCacheLookup(color_cache, key); + goto AdvanceByOne; + } else { // Not reached + goto Error; + } + } + + br->eos_ = VP8LIsEndOfStream(br); + // In incremental decoding: + // br->eos_ && src < src_last: if 'br' reached the end of the buffer and + // 'src_last' has not been reached yet, there is not enough data. 'dec' has to + // be reset until there is more data. + // !br->eos_ && src < src_last: this cannot happen as either the buffer is + // fully read, either enough has been read to reach 'src_last'. + // src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go + // beyond 'src_last' in case the image is cropped and an LZ77 goes further. + // The buffer might have been enough or there is some left. 'br->eos_' does + // not matter. + assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last); + if (dec->incremental_ && br->eos_ && src < src_last) { + RestoreState(dec); + } else if ((dec->incremental_ && src >= src_last) || !br->eos_) { + // Process the remaining rows corresponding to last row-block. + if (process_func != NULL) { + process_func(dec, row > last_row ? last_row : row); + } + dec->status_ = VP8_STATUS_OK; + dec->last_pixel_ = (int)(src - data); // end-of-scan marker + } else { + // if not incremental, and we are past the end of buffer (eos_=1), then this + // is a real bitstream error. + goto Error; + } + return 1; + + Error: + return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); +} + +// ----------------------------------------------------------------------------- +// VP8LTransform + +static void ClearTransform(VP8LTransform* const transform) { + WebPSafeFree(transform->data_); + transform->data_ = NULL; +} + +// For security reason, we need to remap the color map to span +// the total possible bundled values, and not just the num_colors. +static int ExpandColorMap(int num_colors, VP8LTransform* const transform) { + int i; + const int final_num_colors = 1 << (8 >> transform->bits_); + uint32_t* const new_color_map = + (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors, + sizeof(*new_color_map)); + if (new_color_map == NULL) { + return 0; + } else { + uint8_t* const data = (uint8_t*)transform->data_; + uint8_t* const new_data = (uint8_t*)new_color_map; + new_color_map[0] = transform->data_[0]; + for (i = 4; i < 4 * num_colors; ++i) { + // Equivalent to VP8LAddPixels(), on a byte-basis. + new_data[i] = (data[i] + new_data[i - 4]) & 0xff; + } + for (; i < 4 * final_num_colors; ++i) { + new_data[i] = 0; // black tail. + } + WebPSafeFree(transform->data_); + transform->data_ = new_color_map; + } + return 1; +} + +static int ReadTransform(int* const xsize, int const* ysize, + VP8LDecoder* const dec) { + int ok = 1; + VP8LBitReader* const br = &dec->br_; + VP8LTransform* transform = &dec->transforms_[dec->next_transform_]; + const VP8LImageTransformType type = + (VP8LImageTransformType)VP8LReadBits(br, 2); + + // Each transform type can only be present once in the stream. + if (dec->transforms_seen_ & (1U << type)) { + return 0; // Already there, let's not accept the second same transform. + } + dec->transforms_seen_ |= (1U << type); + + transform->type_ = type; + transform->xsize_ = *xsize; + transform->ysize_ = *ysize; + transform->data_ = NULL; + ++dec->next_transform_; + assert(dec->next_transform_ <= NUM_TRANSFORMS); + + switch (type) { + case PREDICTOR_TRANSFORM: + case CROSS_COLOR_TRANSFORM: + transform->bits_ = VP8LReadBits(br, 3) + 2; + ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_, + transform->bits_), + VP8LSubSampleSize(transform->ysize_, + transform->bits_), + /*is_level0=*/0, dec, &transform->data_); + break; + case COLOR_INDEXING_TRANSFORM: { + const int num_colors = VP8LReadBits(br, 8) + 1; + const int bits = (num_colors > 16) ? 0 + : (num_colors > 4) ? 1 + : (num_colors > 2) ? 2 + : 3; + *xsize = VP8LSubSampleSize(transform->xsize_, bits); + transform->bits_ = bits; + ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec, + &transform->data_); + if (ok && !ExpandColorMap(num_colors, transform)) { + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } + break; + } + case SUBTRACT_GREEN_TRANSFORM: + break; + default: + assert(0); // can't happen + break; + } + + return ok; +} + +// ----------------------------------------------------------------------------- +// VP8LMetadata + +static void InitMetadata(VP8LMetadata* const hdr) { + assert(hdr != NULL); + memset(hdr, 0, sizeof(*hdr)); +} + +static void ClearMetadata(VP8LMetadata* const hdr) { + assert(hdr != NULL); + + WebPSafeFree(hdr->huffman_image_); + VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_); + VP8LHtreeGroupsFree(hdr->htree_groups_); + VP8LColorCacheClear(&hdr->color_cache_); + VP8LColorCacheClear(&hdr->saved_color_cache_); + InitMetadata(hdr); +} + +// ----------------------------------------------------------------------------- +// VP8LDecoder + +VP8LDecoder* VP8LNew(void) { + VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + if (dec == NULL) return NULL; + dec->status_ = VP8_STATUS_OK; + dec->state_ = READ_DIM; + + VP8LDspInit(); // Init critical function pointers. + + return dec; +} + +void VP8LClear(VP8LDecoder* const dec) { + int i; + if (dec == NULL) return; + ClearMetadata(&dec->hdr_); + + WebPSafeFree(dec->pixels_); + dec->pixels_ = NULL; + for (i = 0; i < dec->next_transform_; ++i) { + ClearTransform(&dec->transforms_[i]); + } + dec->next_transform_ = 0; + dec->transforms_seen_ = 0; + + WebPSafeFree(dec->rescaler_memory); + dec->rescaler_memory = NULL; + + dec->output_ = NULL; // leave no trace behind +} + +void VP8LDelete(VP8LDecoder* const dec) { + if (dec != NULL) { + VP8LClear(dec); + WebPSafeFree(dec); + } +} + +static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) { + VP8LMetadata* const hdr = &dec->hdr_; + const int num_bits = hdr->huffman_subsample_bits_; + dec->width_ = width; + dec->height_ = height; + + hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits); + hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1; +} + +static int DecodeImageStream(int xsize, int ysize, + int is_level0, + VP8LDecoder* const dec, + uint32_t** const decoded_data) { + int ok = 1; + int transform_xsize = xsize; + int transform_ysize = ysize; + VP8LBitReader* const br = &dec->br_; + VP8LMetadata* const hdr = &dec->hdr_; + uint32_t* data = NULL; + int color_cache_bits = 0; + + // Read the transforms (may recurse). + if (is_level0) { + while (ok && VP8LReadBits(br, 1)) { + ok = ReadTransform(&transform_xsize, &transform_ysize, dec); + } + } + + // Color cache + if (ok && VP8LReadBits(br, 1)) { + color_cache_bits = VP8LReadBits(br, 4); + ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS); + if (!ok) { + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + goto End; + } + } + + // Read the Huffman codes (may recurse). + ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize, + color_cache_bits, is_level0); + if (!ok) { + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + goto End; + } + + // Finish setting up the color-cache + if (color_cache_bits > 0) { + hdr->color_cache_size_ = 1 << color_cache_bits; + if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) { + ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto End; + } + } else { + hdr->color_cache_size_ = 0; + } + UpdateDecoder(dec, transform_xsize, transform_ysize); + + if (is_level0) { // level 0 complete + dec->state_ = READ_HDR; + goto End; + } + + { + const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize; + data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data)); + if (data == NULL) { + ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto End; + } + } + + // Use the Huffman trees to decode the LZ77 encoded data. + ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, + transform_ysize, NULL); + ok = ok && !br->eos_; + + End: + if (!ok) { + WebPSafeFree(data); + ClearMetadata(hdr); + } else { + if (decoded_data != NULL) { + *decoded_data = data; + } else { + // We allocate image data in this function only for transforms. At level 0 + // (that is: not the transforms), we shouldn't have allocated anything. + assert(data == NULL); + assert(is_level0); + } + dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls. + if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind. + } + return ok; +} + +//------------------------------------------------------------------------------ +// Allocate internal buffers dec->pixels_ and dec->argb_cache_. +static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) { + const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_; + // Scratch buffer corresponding to top-prediction row for transforming the + // first row in the row-blocks. Not needed for paletted alpha. + const uint64_t cache_top_pixels = (uint16_t)final_width; + // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. + const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS; + const uint64_t total_num_pixels = + num_pixels + cache_top_pixels + cache_pixels; + + assert(dec->width_ <= final_width); + dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t)); + if (dec->pixels_ == NULL) { + dec->argb_cache_ = NULL; // for soundness + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } + dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels; + return 1; +} + +static int AllocateInternalBuffers8b(VP8LDecoder* const dec) { + const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_; + dec->argb_cache_ = NULL; // for soundness + dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t)); + if (dec->pixels_ == NULL) { + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } + return 1; +} + +//------------------------------------------------------------------------------ + +// Special row-processing that only stores the alpha data. +static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) { + int cur_row = dec->last_row_; + int num_rows = last_row - cur_row; + const uint32_t* in = dec->pixels_ + dec->width_ * cur_row; + + assert(last_row <= dec->io_->crop_bottom); + while (num_rows > 0) { + const int num_rows_to_process = + (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows; + // Extract alpha (which is stored in the green plane). + ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; + uint8_t* const output = alph_dec->output_; + const int width = dec->io_->width; // the final width (!= dec->width_) + const int cache_pixs = width * num_rows_to_process; + uint8_t* const dst = output + width * cur_row; + const uint32_t* const src = dec->argb_cache_; + ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in); + WebPExtractGreen(src, dst, cache_pixs); + AlphaApplyFilter(alph_dec, + cur_row, cur_row + num_rows_to_process, dst, width); + num_rows -= num_rows_to_process; + in += num_rows_to_process * dec->width_; + cur_row += num_rows_to_process; + } + assert(cur_row == last_row); + dec->last_row_ = dec->last_out_row_ = last_row; +} + +int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, + const uint8_t* const data, size_t data_size) { + int ok = 0; + VP8LDecoder* dec = VP8LNew(); + + if (dec == NULL) return 0; + + assert(alph_dec != NULL); + + dec->width_ = alph_dec->width_; + dec->height_ = alph_dec->height_; + dec->io_ = &alph_dec->io_; + dec->io_->opaque = alph_dec; + dec->io_->width = alph_dec->width_; + dec->io_->height = alph_dec->height_; + + dec->status_ = VP8_STATUS_OK; + VP8LInitBitReader(&dec->br_, data, data_size); + + if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, /*is_level0=*/1, + dec, /*decoded_data=*/NULL)) { + goto Err; + } + + // Special case: if alpha data uses only the color indexing transform and + // doesn't use color cache (a frequent case), we will use DecodeAlphaData() + // method that only needs allocation of 1 byte per pixel (alpha channel). + if (dec->next_transform_ == 1 && + dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && + Is8bOptimizable(&dec->hdr_)) { + alph_dec->use_8b_decode_ = 1; + ok = AllocateInternalBuffers8b(dec); + } else { + // Allocate internal buffers (note that dec->width_ may have changed here). + alph_dec->use_8b_decode_ = 0; + ok = AllocateInternalBuffers32b(dec, alph_dec->width_); + } + + if (!ok) goto Err; + + // Only set here, once we are sure it is valid (to avoid thread races). + alph_dec->vp8l_dec_ = dec; + return 1; + + Err: + VP8LDelete(dec); + return 0; +} + +int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { + VP8LDecoder* const dec = alph_dec->vp8l_dec_; + assert(dec != NULL); + assert(last_row <= dec->height_); + + if (dec->last_row_ >= last_row) { + return 1; // done + } + + if (!alph_dec->use_8b_decode_) WebPInitAlphaProcessing(); + + // Decode (with special row processing). + return alph_dec->use_8b_decode_ ? + DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, + last_row) : + DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, + last_row, ExtractAlphaRows); +} + +//------------------------------------------------------------------------------ + +int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { + int width, height, has_alpha; + + if (dec == NULL) return 0; + if (io == NULL) { + return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); + } + + dec->io_ = io; + dec->status_ = VP8_STATUS_OK; + VP8LInitBitReader(&dec->br_, io->data, io->data_size); + if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) { + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + goto Error; + } + dec->state_ = READ_DIM; + io->width = width; + io->height = height; + + if (!DecodeImageStream(width, height, /*is_level0=*/1, dec, + /*decoded_data=*/NULL)) { + goto Error; + } + return 1; + + Error: + VP8LClear(dec); + assert(dec->status_ != VP8_STATUS_OK); + return 0; +} + +int VP8LDecodeImage(VP8LDecoder* const dec) { + VP8Io* io = NULL; + WebPDecParams* params = NULL; + + if (dec == NULL) return 0; + + assert(dec->hdr_.huffman_tables_.root.start != NULL); + assert(dec->hdr_.htree_groups_ != NULL); + assert(dec->hdr_.num_htree_groups_ > 0); + + io = dec->io_; + assert(io != NULL); + params = (WebPDecParams*)io->opaque; + assert(params != NULL); + + // Initialization. + if (dec->state_ != READ_DATA) { + dec->output_ = params->output; + assert(dec->output_ != NULL); + + if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) { + VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); + goto Err; + } + + if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; + +#if !defined(WEBP_REDUCE_SIZE) + if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; +#else + if (io->use_scaling) { + VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); + goto Err; + } +#endif + if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { + // need the alpha-multiply functions for premultiplied output or rescaling + WebPInitAlphaProcessing(); + } + + if (!WebPIsRGBMode(dec->output_->colorspace)) { + WebPInitConvertARGBToYUV(); + if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing(); + } + if (dec->incremental_) { + if (dec->hdr_.color_cache_size_ > 0 && + dec->hdr_.saved_color_cache_.colors_ == NULL) { + if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_, + dec->hdr_.color_cache_.hash_bits_)) { + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto Err; + } + } + } + dec->state_ = READ_DATA; + } + + // Decode. + if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, + io->crop_bottom, ProcessRows)) { + goto Err; + } + + params->last_y = dec->last_out_row_; + return 1; + + Err: + VP8LClear(dec); + assert(dec->status_ != VP8_STATUS_OK); + return 0; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dec/vp8li_dec.h b/libraries/webp/src/dec/vp8li_dec.h new file mode 100644 index 0000000000..e863b4b60d --- /dev/null +++ b/libraries/webp/src/dec/vp8li_dec.h @@ -0,0 +1,149 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Lossless decoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora(vikaas.arora@gmail.com) + +#ifndef WEBP_DEC_VP8LI_DEC_H_ +#define WEBP_DEC_VP8LI_DEC_H_ + +#include // for memcpy() +#include "src/dec/webpi_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/huffman_utils.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + READ_DATA = 0, + READ_HDR = 1, + READ_DIM = 2 +} VP8LDecodeState; + +typedef struct VP8LTransform VP8LTransform; +struct VP8LTransform { + VP8LImageTransformType type_; // transform type. + int bits_; // subsampling bits defining transform window. + int xsize_; // transform window X index. + int ysize_; // transform window Y index. + uint32_t* data_; // transform data. +}; + +typedef struct { + int color_cache_size_; + VP8LColorCache color_cache_; + VP8LColorCache saved_color_cache_; // for incremental + + int huffman_mask_; + int huffman_subsample_bits_; + int huffman_xsize_; + uint32_t* huffman_image_; + int num_htree_groups_; + HTreeGroup* htree_groups_; + HuffmanTables huffman_tables_; +} VP8LMetadata; + +typedef struct VP8LDecoder VP8LDecoder; +struct VP8LDecoder { + VP8StatusCode status_; + VP8LDecodeState state_; + VP8Io* io_; + + const WebPDecBuffer* output_; // shortcut to io->opaque->output + + uint32_t* pixels_; // Internal data: either uint8_t* for alpha + // or uint32_t* for BGRA. + uint32_t* argb_cache_; // Scratch buffer for temporary BGRA storage. + + VP8LBitReader br_; + int incremental_; // if true, incremental decoding is expected + VP8LBitReader saved_br_; // note: could be local variables too + int saved_last_pixel_; + + int width_; + int height_; + int last_row_; // last input row decoded so far. + int last_pixel_; // last pixel decoded so far. However, it may + // not be transformed, scaled and + // color-converted yet. + int last_out_row_; // last row output so far. + + VP8LMetadata hdr_; + + int next_transform_; + VP8LTransform transforms_[NUM_TRANSFORMS]; + // or'd bitset storing the transforms types. + uint32_t transforms_seen_; + + uint8_t* rescaler_memory; // Working memory for rescaling work. + WebPRescaler* rescaler; // Common rescaler for all channels. +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +struct ALPHDecoder; // Defined in dec/alphai.h. + +// in vp8l.c + +// Decodes image header for alpha data stored using lossless compression. +// Returns false in case of error. +WEBP_NODISCARD int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec, + const uint8_t* const data, + size_t data_size); + +// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are +// already decoded in previous call(s), it will resume decoding from where it +// was paused. +// Returns false in case of bitstream error. +WEBP_NODISCARD int VP8LDecodeAlphaImageStream( + struct ALPHDecoder* const alph_dec, int last_row); + +// Allocates and initialize a new lossless decoder instance. +WEBP_NODISCARD VP8LDecoder* VP8LNew(void); + +// Decodes the image header. Returns false in case of error. +WEBP_NODISCARD int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io); + +// Decodes an image. It's required to decode the lossless header before calling +// this function. Returns false in case of error, with updated dec->status_. +WEBP_NODISCARD int VP8LDecodeImage(VP8LDecoder* const dec); + +// Resets the decoder in its initial state, reclaiming memory. +// Preserves the dec->status_ value. +void VP8LClear(VP8LDecoder* const dec); + +// Clears and deallocate a lossless decoder instance. +void VP8LDelete(VP8LDecoder* const dec); + +// Helper function for reading the different Huffman codes and storing them in +// 'huffman_tables' and 'htree_groups'. +// If mapping is NULL 'num_htree_groups_max' must equal 'num_htree_groups'. +// If it is not NULL, it maps 'num_htree_groups_max' indices to the +// 'num_htree_groups' groups. If 'num_htree_groups_max' > 'num_htree_groups', +// some of those indices map to -1. This is used for non-balanced codes to +// limit memory usage. +WEBP_NODISCARD int ReadHuffmanCodesHelper( + int color_cache_bits, int num_htree_groups, int num_htree_groups_max, + const int* const mapping, VP8LDecoder* const dec, + HuffmanTables* const huffman_tables, HTreeGroup** const htree_groups); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_VP8LI_DEC_H_ diff --git a/libraries/webp/src/dec/webp_dec.c b/libraries/webp/src/dec/webp_dec.c new file mode 100644 index 0000000000..3aa87dab05 --- /dev/null +++ b/libraries/webp/src/dec/webp_dec.c @@ -0,0 +1,871 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WEBP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dec/vp8_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/utils.h" +#include "include/webp/mux_types.h" // ALPHA_FLAG +#include "include/webp/decode.h" +#include "include/webp/types.h" + +//------------------------------------------------------------------------------ +// RIFF layout is: +// Offset tag +// 0...3 "RIFF" 4-byte tag +// 4...7 size of image data (including metadata) starting at offset 8 +// 8...11 "WEBP" our form-type signature +// The RIFF container (12 bytes) is followed by appropriate chunks: +// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format +// 16..19 size of the raw VP8 image data, starting at offset 20 +// 20.... the VP8 bytes +// Or, +// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format +// 16..19 size of the raw VP8L image data, starting at offset 20 +// 20.... the VP8L bytes +// Or, +// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk. +// 16..19 size of the VP8X chunk starting at offset 20. +// 20..23 VP8X flags bit-map corresponding to the chunk-types present. +// 24..26 Width of the Canvas Image. +// 27..29 Height of the Canvas Image. +// There can be extra chunks after the "VP8X" chunk (ICCP, ANMF, VP8, VP8L, +// XMP, EXIF ...) +// All sizes are in little-endian order. +// Note: chunk data size must be padded to multiple of 2 when written. + +// Validates the RIFF container (if detected) and skips over it. +// If a RIFF container is detected, returns: +// VP8_STATUS_BITSTREAM_ERROR for invalid header, +// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true, +// and VP8_STATUS_OK otherwise. +// In case there are not enough bytes (partial RIFF container), return 0 for +// *riff_size. Else return the RIFF size extracted from the header. +static VP8StatusCode ParseRIFF(const uint8_t** const data, + size_t* const data_size, int have_all_data, + size_t* const riff_size) { + assert(data != NULL); + assert(data_size != NULL); + assert(riff_size != NULL); + + *riff_size = 0; // Default: no RIFF present. + if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { + if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { + return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. + } else { + const uint32_t size = GetLE32(*data + TAG_SIZE); + // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). + if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + } + // We have a RIFF container. Skip it. + *riff_size = size; + *data += RIFF_HEADER_SIZE; + *data_size -= RIFF_HEADER_SIZE; + } + } + return VP8_STATUS_OK; +} + +// Validates the VP8X header and skips over it. +// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr, +// *height_ptr and *flags_ptr are set to the corresponding values extracted +// from the VP8X chunk. +static VP8StatusCode ParseVP8X(const uint8_t** const data, + size_t* const data_size, + int* const found_vp8x, + int* const width_ptr, int* const height_ptr, + uint32_t* const flags_ptr) { + const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + assert(data != NULL); + assert(data_size != NULL); + assert(found_vp8x != NULL); + + *found_vp8x = 0; + + if (*data_size < CHUNK_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + + if (!memcmp(*data, "VP8X", TAG_SIZE)) { + int width, height; + uint32_t flags; + const uint32_t chunk_size = GetLE32(*data + TAG_SIZE); + if (chunk_size != VP8X_CHUNK_SIZE) { + return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. + } + + // Verify if enough data is available to validate the VP8X chunk. + if (*data_size < vp8x_size) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + flags = GetLE32(*data + 8); + width = 1 + GetLE24(*data + 12); + height = 1 + GetLE24(*data + 15); + if (width * (uint64_t)height >= MAX_IMAGE_AREA) { + return VP8_STATUS_BITSTREAM_ERROR; // image is too large + } + + if (flags_ptr != NULL) *flags_ptr = flags; + if (width_ptr != NULL) *width_ptr = width; + if (height_ptr != NULL) *height_ptr = height; + // Skip over VP8X header bytes. + *data += vp8x_size; + *data_size -= vp8x_size; + *found_vp8x = 1; + } + return VP8_STATUS_OK; +} + +// Skips to the next VP8/VP8L chunk header in the data given the size of the +// RIFF chunk 'riff_size'. +// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If an alpha chunk is found, *alpha_data and *alpha_size are set +// appropriately. +static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, + size_t* const data_size, + size_t const riff_size, + const uint8_t** const alpha_data, + size_t* const alpha_size) { + const uint8_t* buf; + size_t buf_size; + uint32_t total_size = TAG_SIZE + // "WEBP". + CHUNK_HEADER_SIZE + // "VP8Xnnnn". + VP8X_CHUNK_SIZE; // data. + assert(data != NULL); + assert(data_size != NULL); + buf = *data; + buf_size = *data_size; + + assert(alpha_data != NULL); + assert(alpha_size != NULL); + *alpha_data = NULL; + *alpha_size = 0; + + while (1) { + uint32_t chunk_size; + uint32_t disk_chunk_size; // chunk_size with padding + + *data = buf; + *data_size = buf_size; + + if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + + chunk_size = GetLE32(buf + TAG_SIZE); + if (chunk_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } + // For odd-sized chunk-payload, there's one byte padding at the end. + disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1u; + total_size += disk_chunk_size; + + // Check that total bytes skipped so far does not exceed riff_size. + if (riff_size > 0 && (total_size > riff_size)) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } + + // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have + // parsed all the optional chunks. + // Note: This check must occur before the check 'buf_size < disk_chunk_size' + // below to allow incomplete VP8/VP8L chunks. + if (!memcmp(buf, "VP8 ", TAG_SIZE) || + !memcmp(buf, "VP8L", TAG_SIZE)) { + return VP8_STATUS_OK; + } + + if (buf_size < disk_chunk_size) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + + if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. + *alpha_data = buf + CHUNK_HEADER_SIZE; + *alpha_size = chunk_size; + } + + // We have a full and valid chunk; skip it. + buf += disk_chunk_size; + buf_size -= disk_chunk_size; + } +} + +// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. +// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than +// riff_size) VP8/VP8L header, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes +// extracted from the VP8/VP8L chunk header. +// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data. +static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr, + size_t* const data_size, int have_all_data, + size_t riff_size, size_t* const chunk_size, + int* const is_lossless) { + const uint8_t* const data = *data_ptr; + const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); + const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); + const uint32_t minimal_size = + TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR + // "WEBP" + "VP8Lnnnn" + assert(data != NULL); + assert(data_size != NULL); + assert(chunk_size != NULL); + assert(is_lossless != NULL); + + if (*data_size < CHUNK_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + + if (is_vp8 || is_vp8l) { + // Bitstream contains VP8/VP8L header. + const uint32_t size = GetLE32(data + TAG_SIZE); + if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { + return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. + } + if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + } + // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. + *chunk_size = size; + *data_ptr += CHUNK_HEADER_SIZE; + *data_size -= CHUNK_HEADER_SIZE; + *is_lossless = is_vp8l; + } else { + // Raw VP8/VP8L bitstream (no header). + *is_lossless = VP8LCheckSignature(data, *data_size); + *chunk_size = *data_size; + } + + return VP8_STATUS_OK; +} + +//------------------------------------------------------------------------------ + +// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on +// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the +// minimal amount will be read to fetch the remaining parameters. +// If 'headers' is non-NULL this function will attempt to locate both alpha +// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L). +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +static VP8StatusCode ParseHeadersInternal(const uint8_t* data, + size_t data_size, + int* const width, + int* const height, + int* const has_alpha, + int* const has_animation, + int* const format, + WebPHeaderStructure* const headers) { + int canvas_width = 0; + int canvas_height = 0; + int image_width = 0; + int image_height = 0; + int found_riff = 0; + int found_vp8x = 0; + int animation_present = 0; + const int have_all_data = (headers != NULL) ? headers->have_all_data : 0; + + VP8StatusCode status; + WebPHeaderStructure hdrs; + + if (data == NULL || data_size < RIFF_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; + } + memset(&hdrs, 0, sizeof(hdrs)); + hdrs.data = data; + hdrs.data_size = data_size; + + // Skip over RIFF header. + status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size); + if (status != VP8_STATUS_OK) { + return status; // Wrong RIFF header / insufficient data. + } + found_riff = (hdrs.riff_size > 0); + + // Skip over VP8X. + { + uint32_t flags = 0; + status = ParseVP8X(&data, &data_size, &found_vp8x, + &canvas_width, &canvas_height, &flags); + if (status != VP8_STATUS_OK) { + return status; // Wrong VP8X / insufficient data. + } + animation_present = !!(flags & ANIMATION_FLAG); + if (!found_riff && found_vp8x) { + // Note: This restriction may be removed in the future, if it becomes + // necessary to send VP8X chunk to the decoder. + return VP8_STATUS_BITSTREAM_ERROR; + } + if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG); + if (has_animation != NULL) *has_animation = animation_present; + if (format != NULL) *format = 0; // default = undefined + + image_width = canvas_width; + image_height = canvas_height; + if (found_vp8x && animation_present && headers == NULL) { + status = VP8_STATUS_OK; + goto ReturnWidthHeight; // Just return features from VP8X header. + } + } + + if (data_size < TAG_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + + // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". + if ((found_riff && found_vp8x) || + (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) { + status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size, + &hdrs.alpha_data, &hdrs.alpha_data_size); + if (status != VP8_STATUS_OK) { + goto ReturnWidthHeight; // Invalid chunk size / insufficient data. + } + } + + // Skip over VP8/VP8L header. + status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size, + &hdrs.compressed_size, &hdrs.is_lossless); + if (status != VP8_STATUS_OK) { + goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data. + } + if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; + } + + if (format != NULL && !animation_present) { + *format = hdrs.is_lossless ? 2 : 1; + } + + if (!hdrs.is_lossless) { + if (data_size < VP8_FRAME_HEADER_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + // Validates raw VP8 data. + if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size, + &image_width, &image_height)) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } else { + if (data_size < VP8L_FRAME_HEADER_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + // Validates raw VP8L data. + if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } + // Validates image size coherency. + if (found_vp8x) { + if (canvas_width != image_width || canvas_height != image_height) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } + if (headers != NULL) { + *headers = hdrs; + headers->offset = data - headers->data; + assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD); + assert(headers->offset == headers->data_size - data_size); + } + ReturnWidthHeight: + if (status == VP8_STATUS_OK || + (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) { + if (has_alpha != NULL) { + // If the data did not contain a VP8X/VP8L chunk the only definitive way + // to set this is by looking for alpha data (from an ALPH chunk). + *has_alpha |= (hdrs.alpha_data != NULL); + } + if (width != NULL) *width = image_width; + if (height != NULL) *height = image_height; + return VP8_STATUS_OK; + } else { + return status; + } +} + +VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { + // status is marked volatile as a workaround for a clang-3.8 (aarch64) bug + volatile VP8StatusCode status; + int has_animation = 0; + assert(headers != NULL); + // fill out headers, ignore width/height/has_alpha. + status = ParseHeadersInternal(headers->data, headers->data_size, + NULL, NULL, NULL, &has_animation, + NULL, headers); + if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { + // The WebPDemux API + libwebp can be used to decode individual + // uncomposited frames or the WebPAnimDecoder can be used to fully + // reconstruct them (see webp/demux.h). + if (has_animation) { + status = VP8_STATUS_UNSUPPORTED_FEATURE; + } + } + return status; +} + +//------------------------------------------------------------------------------ +// WebPDecParams + +void WebPResetDecParams(WebPDecParams* const params) { + if (params != NULL) { + memset(params, 0, sizeof(*params)); + } +} + +//------------------------------------------------------------------------------ +// "Into" decoding variants + +// Main flow +WEBP_NODISCARD static VP8StatusCode DecodeInto(const uint8_t* const data, + size_t data_size, + WebPDecParams* const params) { + VP8StatusCode status; + VP8Io io; + WebPHeaderStructure headers; + + headers.data = data; + headers.data_size = data_size; + headers.have_all_data = 1; + status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks. + if (status != VP8_STATUS_OK) { + return status; + } + + assert(params != NULL); + if (!VP8InitIo(&io)) { + return VP8_STATUS_INVALID_PARAM; + } + io.data = headers.data + headers.offset; + io.data_size = headers.data_size - headers.offset; + WebPInitCustomIo(params, &io); // Plug the I/O functions. + + if (!headers.is_lossless) { + VP8Decoder* const dec = VP8New(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + dec->alpha_data_ = headers.alpha_data; + dec->alpha_data_size_ = headers.alpha_data_size; + + // Decode bitstream header, update io->width/io->height. + if (!VP8GetHeaders(dec, &io)) { + status = dec->status_; // An error occurred. Grab error status. + } else { + // Allocate/check output buffers. + status = WebPAllocateDecBuffer(io.width, io.height, params->options, + params->output); + if (status == VP8_STATUS_OK) { // Decode + // This change must be done before calling VP8Decode() + dec->mt_method_ = VP8GetThreadMethod(params->options, &headers, + io.width, io.height); + VP8InitDithering(params->options, dec); + if (!VP8Decode(dec, &io)) { + status = dec->status_; + } + } + } + VP8Delete(dec); + } else { + VP8LDecoder* const dec = VP8LNew(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + if (!VP8LDecodeHeader(dec, &io)) { + status = dec->status_; // An error occurred. Grab error status. + } else { + // Allocate/check output buffers. + status = WebPAllocateDecBuffer(io.width, io.height, params->options, + params->output); + if (status == VP8_STATUS_OK) { // Decode + if (!VP8LDecodeImage(dec)) { + status = dec->status_; + } + } + } + VP8LDelete(dec); + } + + if (status != VP8_STATUS_OK) { + WebPFreeDecBuffer(params->output); + } else { + if (params->options != NULL && params->options->flip) { + // This restores the original stride values if options->flip was used + // during the call to WebPAllocateDecBuffer above. + status = WebPFlipBuffer(params->output); + } + } + return status; +} + +// Helpers +WEBP_NODISCARD static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, + const uint8_t* const data, + size_t data_size, + uint8_t* const rgba, + int stride, size_t size) { + WebPDecParams params; + WebPDecBuffer buf; + if (rgba == NULL || !WebPInitDecBuffer(&buf)) { + return NULL; + } + WebPResetDecParams(¶ms); + params.output = &buf; + buf.colorspace = colorspace; + buf.u.RGBA.rgba = rgba; + buf.u.RGBA.stride = stride; + buf.u.RGBA.size = size; + buf.is_external_memory = 1; + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + return rgba; +} + +uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride) { + WebPDecParams params; + WebPDecBuffer output; + if (luma == NULL || !WebPInitDecBuffer(&output)) return NULL; + WebPResetDecParams(¶ms); + params.output = &output; + output.colorspace = MODE_YUV; + output.u.YUVA.y = luma; + output.u.YUVA.y_stride = luma_stride; + output.u.YUVA.y_size = luma_size; + output.u.YUVA.u = u; + output.u.YUVA.u_stride = u_stride; + output.u.YUVA.u_size = u_size; + output.u.YUVA.v = v; + output.u.YUVA.v_stride = v_stride; + output.u.YUVA.v_size = v_size; + output.is_external_memory = 1; + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + return luma; +} + +//------------------------------------------------------------------------------ + +WEBP_NODISCARD static uint8_t* Decode(WEBP_CSP_MODE mode, + const uint8_t* const data, + size_t data_size, int* const width, + int* const height, + WebPDecBuffer* const keep_info) { + WebPDecParams params; + WebPDecBuffer output; + + if (!WebPInitDecBuffer(&output)) { + return NULL; + } + WebPResetDecParams(¶ms); + params.output = &output; + output.colorspace = mode; + + // Retrieve (and report back) the required dimensions from bitstream. + if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { + return NULL; + } + if (width != NULL) *width = output.width; + if (height != NULL) *height = output.height; + + // Decode + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + if (keep_info != NULL) { // keep track of the side-info + WebPCopyDecBuffer(&output, keep_info); + } + // return decoded samples (don't clear 'output'!) + return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y; +} + +uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_RGB, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_RGBA, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_ARGB, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_BGR, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_BGRA, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, + int* width, int* height, uint8_t** u, uint8_t** v, + int* stride, int* uv_stride) { + // data, width and height are checked by Decode(). + if (u == NULL || v == NULL || stride == NULL || uv_stride == NULL) { + return NULL; + } + + { + WebPDecBuffer output; // only to preserve the side-infos + uint8_t* const out = Decode(MODE_YUV, data, data_size, + width, height, &output); + + if (out != NULL) { + const WebPYUVABuffer* const buf = &output.u.YUVA; + *u = buf->u; + *v = buf->v; + *stride = buf->y_stride; + *uv_stride = buf->u_stride; + assert(buf->u_stride == buf->v_stride); + } + return out; + } +} + +static void DefaultFeatures(WebPBitstreamFeatures* const features) { + assert(features != NULL); + memset(features, 0, sizeof(*features)); +} + +static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size, + WebPBitstreamFeatures* const features) { + if (features == NULL || data == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + DefaultFeatures(features); + + // Only parse enough of the data to retrieve the features. + return ParseHeadersInternal(data, data_size, + &features->width, &features->height, + &features->has_alpha, &features->has_animation, + &features->format, NULL); +} + +//------------------------------------------------------------------------------ +// WebPGetInfo() + +int WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height) { + WebPBitstreamFeatures features; + + if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) { + return 0; + } + + if (width != NULL) { + *width = features.width; + } + if (height != NULL) { + *height = features.height; + } + + return 1; +} + +//------------------------------------------------------------------------------ +// Advance decoding API + +int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, + int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return 0; // version mismatch + } + if (config == NULL) { + return 0; + } + memset(config, 0, sizeof(*config)); + DefaultFeatures(&config->input); + if (!WebPInitDecBuffer(&config->output)) { + return 0; + } + return 1; +} + +VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size, + WebPBitstreamFeatures* features, + int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return VP8_STATUS_INVALID_PARAM; // version mismatch + } + if (features == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + return GetFeatures(data, data_size, features); +} + +VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config) { + WebPDecParams params; + VP8StatusCode status; + + if (config == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + + status = GetFeatures(data, data_size, &config->input); + if (status != VP8_STATUS_OK) { + if (status == VP8_STATUS_NOT_ENOUGH_DATA) { + return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error. + } + return status; + } + + WebPResetDecParams(¶ms); + params.options = &config->options; + params.output = &config->output; + if (WebPAvoidSlowMemory(params.output, &config->input)) { + // decoding to slow memory: use a temporary in-mem buffer to decode into. + WebPDecBuffer in_mem_buffer; + if (!WebPInitDecBuffer(&in_mem_buffer)) { + return VP8_STATUS_INVALID_PARAM; + } + in_mem_buffer.colorspace = config->output.colorspace; + in_mem_buffer.width = config->input.width; + in_mem_buffer.height = config->input.height; + params.output = &in_mem_buffer; + status = DecodeInto(data, data_size, ¶ms); + if (status == VP8_STATUS_OK) { // do the slow-copy + status = WebPCopyDecBufferPixels(&in_mem_buffer, &config->output); + } + WebPFreeDecBuffer(&in_mem_buffer); + } else { + status = DecodeInto(data, data_size, ¶ms); + } + + return status; +} + +//------------------------------------------------------------------------------ +// Cropping and rescaling. + +int WebPCheckCropDimensions(int image_width, int image_height, + int x, int y, int w, int h) { + return !(x < 0 || y < 0 || w <= 0 || h <= 0 || + x >= image_width || w > image_width || w > image_width - x || + y >= image_height || h > image_height || h > image_height - y); +} + +int WebPIoInitFromOptions(const WebPDecoderOptions* const options, + VP8Io* const io, WEBP_CSP_MODE src_colorspace) { + const int W = io->width; + const int H = io->height; + int x = 0, y = 0, w = W, h = H; + + // Cropping + io->use_cropping = (options != NULL) && options->use_cropping; + if (io->use_cropping) { + w = options->crop_width; + h = options->crop_height; + x = options->crop_left; + y = options->crop_top; + if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 + x &= ~1; + y &= ~1; + } + if (!WebPCheckCropDimensions(W, H, x, y, w, h)) { + return 0; // out of frame boundary error + } + } + io->crop_left = x; + io->crop_top = y; + io->crop_right = x + w; + io->crop_bottom = y + h; + io->mb_w = w; + io->mb_h = h; + + // Scaling + io->use_scaling = (options != NULL) && options->use_scaling; + if (io->use_scaling) { + int scaled_width = options->scaled_width; + int scaled_height = options->scaled_height; + if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) { + return 0; + } + io->scaled_width = scaled_width; + io->scaled_height = scaled_height; + } + + // Filter + io->bypass_filtering = (options != NULL) && options->bypass_filtering; + + // Fancy upsampler +#ifdef FANCY_UPSAMPLING + io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling); +#endif + + if (io->use_scaling) { + // disable filter (only for large downscaling ratio). + io->bypass_filtering |= (io->scaled_width < W * 3 / 4) && + (io->scaled_height < H * 3 / 4); + io->fancy_upsampling = 0; + } + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dec/webpi_dec.h b/libraries/webp/src/dec/webpi_dec.h new file mode 100644 index 0000000000..4ff1d141e4 --- /dev/null +++ b/libraries/webp/src/dec/webpi_dec.h @@ -0,0 +1,139 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header: WebP decoding parameters and custom IO on buffer +// +// Author: somnath@google.com (Somnath Banerjee) + +#ifndef WEBP_DEC_WEBPI_DEC_H_ +#define WEBP_DEC_WEBPI_DEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "src/utils/rescaler_utils.h" +#include "src/dec/vp8_dec.h" +#include "include/webp/decode.h" + +//------------------------------------------------------------------------------ +// WebPDecParams: Decoding output parameters. Transient internal object. + +typedef struct WebPDecParams WebPDecParams; +typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p); +typedef int (*OutputAlphaFunc)(const VP8Io* const io, WebPDecParams* const p, + int expected_num_out_lines); +typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos, + int max_out_lines); + +struct WebPDecParams { + WebPDecBuffer* output; // output buffer. + uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler + // or used for tmp rescaling + + int last_y; // coordinate of the line that was last output + const WebPDecoderOptions* options; // if not NULL, use alt decoding features + + WebPRescaler* scaler_y, *scaler_u, *scaler_v, *scaler_a; // rescalers + void* memory; // overall scratch memory for the output work. + + OutputFunc emit; // output RGB or YUV samples + OutputAlphaFunc emit_alpha; // output alpha channel + OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values +}; + +// Should be called first, before any use of the WebPDecParams object. +void WebPResetDecParams(WebPDecParams* const params); + +//------------------------------------------------------------------------------ +// Header parsing helpers + +// Structure storing a description of the RIFF headers. +typedef struct { + const uint8_t* data; // input buffer + size_t data_size; // input buffer size + int have_all_data; // true if all data is known to be available + size_t offset; // offset to main data chunk (VP8 or VP8L) + const uint8_t* alpha_data; // points to alpha chunk (if present) + size_t alpha_data_size; // alpha chunk size + size_t compressed_size; // VP8/VP8L compressed data size + size_t riff_size; // size of the riff payload (or 0 if absent) + int is_lossless; // true if a VP8L chunk is present +} WebPHeaderStructure; + +// Skips over all valid chunks prior to the first VP8/VP8L frame header. +// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk), +// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE +// in the case of non-decodable features (animation for instance). +// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless +// fields are updated appropriately upon success. +VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers); + +//------------------------------------------------------------------------------ +// Misc utils + +// Returns true if crop dimensions are within image bounds. +int WebPCheckCropDimensions(int image_width, int image_height, + int x, int y, int w, int h); + +// Initializes VP8Io with custom setup, io and teardown functions. The default +// hooks will use the supplied 'params' as io->opaque handle. +void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io); + +// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers +// to the *compressed* format, not the output one. +WEBP_NODISCARD int WebPIoInitFromOptions( + const WebPDecoderOptions* const options, VP8Io* const io, + WEBP_CSP_MODE src_colorspace); + +//------------------------------------------------------------------------------ +// Internal functions regarding WebPDecBuffer memory (in buffer.c). +// Don't really need to be externally visible for now. + +// Prepare 'buffer' with the requested initial dimensions width/height. +// If no external storage is supplied, initializes buffer by allocating output +// memory and setting up the stride information. Validate the parameters. Return +// an error code in case of problem (no memory, or invalid stride / size / +// dimension / etc.). If *options is not NULL, also verify that the options' +// parameters are valid and apply them to the width/height dimensions of the +// output buffer. This takes cropping / scaling / rotation into account. +// Also incorporates the options->flip flag to flip the buffer parameters if +// needed. +VP8StatusCode WebPAllocateDecBuffer(int width, int height, + const WebPDecoderOptions* const options, + WebPDecBuffer* const buffer); + +// Flip buffer vertically by negating the various strides. +VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer); + +// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the +// memory (still held by 'src'). No pixels are copied. +void WebPCopyDecBuffer(const WebPDecBuffer* const src, + WebPDecBuffer* const dst); + +// Copy and transfer ownership from src to dst (beware of parameter order!) +void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst); + +// Copy pixels from 'src' into a *preallocated* 'dst' buffer. Returns +// VP8_STATUS_INVALID_PARAM if the 'dst' is not set up correctly for the copy. +VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src, + WebPDecBuffer* const dst); + +// Returns true if decoding will be slow with the current configuration +// and bitstream features. +int WebPAvoidSlowMemory(const WebPDecBuffer* const output, + const WebPBitstreamFeatures* const features); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_WEBPI_DEC_H_ diff --git a/libraries/webp/src/demux/anim_decode.c b/libraries/webp/src/demux/anim_decode.c new file mode 100644 index 0000000000..03b8dc6257 --- /dev/null +++ b/libraries/webp/src/demux/anim_decode.c @@ -0,0 +1,479 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// AnimDecoder implementation. +// + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include +#include + +#include "src/utils/utils.h" +#include "include/webp/decode.h" +#include "include/webp/demux.h" +#include "include/webp/types.h" + +#define NUM_CHANNELS 4 + +// Channel extraction from a uint32_t representation of a uint8_t RGBA/BGRA +// buffer. +#ifdef WORDS_BIGENDIAN +#define CHANNEL_SHIFT(i) (24 - (i) * 8) +#else +#define CHANNEL_SHIFT(i) ((i) * 8) +#endif + +typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int); +static void BlendPixelRowNonPremult(uint32_t* const src, + const uint32_t* const dst, int num_pixels); +static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, + int num_pixels); + +struct WebPAnimDecoder { + WebPDemuxer* demux_; // Demuxer created from given WebP bitstream. + WebPDecoderConfig config_; // Decoder config. + // Note: we use a pointer to a function blending multiple pixels at a time to + // allow possible inlining of per-pixel blending function. + BlendRowFunc blend_func_; // Pointer to the chose blend row function. + WebPAnimInfo info_; // Global info about the animation. + uint8_t* curr_frame_; // Current canvas (not disposed). + uint8_t* prev_frame_disposed_; // Previous canvas (properly disposed). + int prev_frame_timestamp_; // Previous frame timestamp (milliseconds). + WebPIterator prev_iter_; // Iterator object for previous frame. + int prev_frame_was_keyframe_; // True if previous frame was a keyframe. + int next_frame_; // Index of the next frame to be decoded + // (starting from 1). +}; + +static void DefaultDecoderOptions(WebPAnimDecoderOptions* const dec_options) { + dec_options->color_mode = MODE_RGBA; + dec_options->use_threads = 0; +} + +int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options, + int abi_version) { + if (dec_options == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { + return 0; + } + DefaultDecoderOptions(dec_options); + return 1; +} + +WEBP_NODISCARD static int ApplyDecoderOptions( + const WebPAnimDecoderOptions* const dec_options, + WebPAnimDecoder* const dec) { + WEBP_CSP_MODE mode; + WebPDecoderConfig* config = &dec->config_; + assert(dec_options != NULL); + + mode = dec_options->color_mode; + if (mode != MODE_RGBA && mode != MODE_BGRA && + mode != MODE_rgbA && mode != MODE_bgrA) { + return 0; + } + dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA) + ? &BlendPixelRowNonPremult + : &BlendPixelRowPremult; + if (!WebPInitDecoderConfig(config)) { + return 0; + } + config->output.colorspace = mode; + config->output.is_external_memory = 1; + config->options.use_threads = dec_options->use_threads; + // Note: config->output.u.RGBA is set at the time of decoding each frame. + return 1; +} + +WebPAnimDecoder* WebPAnimDecoderNewInternal( + const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options, + int abi_version) { + WebPAnimDecoderOptions options; + WebPAnimDecoder* dec = NULL; + WebPBitstreamFeatures features; + if (webp_data == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { + return NULL; + } + + // Validate the bitstream before doing expensive allocations. The demuxer may + // be more tolerant than the decoder. + if (WebPGetFeatures(webp_data->bytes, webp_data->size, &features) != + VP8_STATUS_OK) { + return NULL; + } + + // Note: calloc() so that the pointer members are initialized to NULL. + dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + if (dec == NULL) goto Error; + + if (dec_options != NULL) { + options = *dec_options; + } else { + DefaultDecoderOptions(&options); + } + if (!ApplyDecoderOptions(&options, dec)) goto Error; + + dec->demux_ = WebPDemux(webp_data); + if (dec->demux_ == NULL) goto Error; + + dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH); + dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT); + dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT); + dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR); + dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT); + + // Note: calloc() because we fill frame with zeroes as well. + dec->curr_frame_ = (uint8_t*)WebPSafeCalloc( + dec->info_.canvas_width * NUM_CHANNELS, dec->info_.canvas_height); + if (dec->curr_frame_ == NULL) goto Error; + dec->prev_frame_disposed_ = (uint8_t*)WebPSafeCalloc( + dec->info_.canvas_width * NUM_CHANNELS, dec->info_.canvas_height); + if (dec->prev_frame_disposed_ == NULL) goto Error; + + WebPAnimDecoderReset(dec); + return dec; + + Error: + WebPAnimDecoderDelete(dec); + return NULL; +} + +int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) { + if (dec == NULL || info == NULL) return 0; + *info = dec->info_; + return 1; +} + +// Returns true if the frame covers the full canvas. +static int IsFullFrame(int width, int height, int canvas_width, + int canvas_height) { + return (width == canvas_width && height == canvas_height); +} + +// Clear the canvas to transparent. +WEBP_NODISCARD static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, + uint32_t canvas_height) { + const uint64_t size = + (uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf); + if (!CheckSizeOverflow(size)) return 0; + memset(buf, 0, (size_t)size); + return 1; +} + +// Clear given frame rectangle to transparent. +static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, + int y_offset, int width, int height) { + int j; + assert(width * NUM_CHANNELS <= buf_stride); + buf += y_offset * buf_stride + x_offset * NUM_CHANNELS; + for (j = 0; j < height; ++j) { + memset(buf, 0, width * NUM_CHANNELS); + buf += buf_stride; + } +} + +// Copy width * height pixels from 'src' to 'dst'. +WEBP_NODISCARD static int CopyCanvas(const uint8_t* src, uint8_t* dst, + uint32_t width, uint32_t height) { + const uint64_t size = (uint64_t)width * height * NUM_CHANNELS; + if (!CheckSizeOverflow(size)) return 0; + assert(src != NULL && dst != NULL); + memcpy(dst, src, (size_t)size); + return 1; +} + +// Returns true if the current frame is a key-frame. +static int IsKeyFrame(const WebPIterator* const curr, + const WebPIterator* const prev, + int prev_frame_was_key_frame, + int canvas_width, int canvas_height) { + if (curr->frame_num == 1) { + return 1; + } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) && + IsFullFrame(curr->width, curr->height, + canvas_width, canvas_height)) { + return 1; + } else { + return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) && + (IsFullFrame(prev->width, prev->height, canvas_width, + canvas_height) || + prev_frame_was_key_frame); + } +} + + +// Blend a single channel of 'src' over 'dst', given their alpha channel values. +// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha. +static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a, + uint32_t dst, uint8_t dst_a, + uint32_t scale, int shift) { + const uint8_t src_channel = (src >> shift) & 0xff; + const uint8_t dst_channel = (dst >> shift) & 0xff; + const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a; + assert(blend_unscaled < (1ULL << 32) / scale); + return (blend_unscaled * scale) >> CHANNEL_SHIFT(3); +} + +// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha. +static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) { + const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff; + + if (src_a == 0) { + return dst; + } else { + const uint8_t dst_a = (dst >> CHANNEL_SHIFT(3)) & 0xff; + // This is the approximate integer arithmetic for the actual formula: + // dst_factor_a = (dst_a * (255 - src_a)) / 255. + const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8; + const uint8_t blend_a = src_a + dst_factor_a; + const uint32_t scale = (1UL << 24) / blend_a; + + const uint8_t blend_r = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(0)); + const uint8_t blend_g = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(1)); + const uint8_t blend_b = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(2)); + assert(src_a + dst_factor_a < 256); + + return ((uint32_t)blend_r << CHANNEL_SHIFT(0)) | + ((uint32_t)blend_g << CHANNEL_SHIFT(1)) | + ((uint32_t)blend_b << CHANNEL_SHIFT(2)) | + ((uint32_t)blend_a << CHANNEL_SHIFT(3)); + } +} + +// Blend 'num_pixels' in 'src' over 'dst' assuming they are NOT pre-multiplied +// by alpha. +static void BlendPixelRowNonPremult(uint32_t* const src, + const uint32_t* const dst, int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff; + if (src_alpha != 0xff) { + src[i] = BlendPixelNonPremult(src[i], dst[i]); + } + } +} + +// Individually multiply each channel in 'pix' by 'scale'. +static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) { + uint32_t mask = 0x00FF00FF; + uint32_t rb = ((pix & mask) * scale) >> 8; + uint32_t ag = ((pix >> 8) & mask) * scale; + return (rb & mask) | (ag & ~mask); +} + +// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha. +static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) { + const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff; + return src + ChannelwiseMultiply(dst, 256 - src_a); +} + +// Blend 'num_pixels' in 'src' over 'dst' assuming they are pre-multiplied by +// alpha. +static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, + int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff; + if (src_alpha != 0xff) { + src[i] = BlendPixelPremult(src[i], dst[i]); + } + } +} + +// Returns two ranges ( pairs) at row 'canvas_y', that belong to +// 'src' but not 'dst'. A point range is empty if the corresponding width is 0. +static void FindBlendRangeAtRow(const WebPIterator* const src, + const WebPIterator* const dst, int canvas_y, + int* const left1, int* const width1, + int* const left2, int* const width2) { + const int src_max_x = src->x_offset + src->width; + const int dst_max_x = dst->x_offset + dst->width; + const int dst_max_y = dst->y_offset + dst->height; + assert(canvas_y >= src->y_offset && canvas_y < (src->y_offset + src->height)); + *left1 = -1; + *width1 = 0; + *left2 = -1; + *width2 = 0; + + if (canvas_y < dst->y_offset || canvas_y >= dst_max_y || + src->x_offset >= dst_max_x || src_max_x <= dst->x_offset) { + *left1 = src->x_offset; + *width1 = src->width; + return; + } + + if (src->x_offset < dst->x_offset) { + *left1 = src->x_offset; + *width1 = dst->x_offset - src->x_offset; + } + + if (src_max_x > dst_max_x) { + *left2 = dst_max_x; + *width2 = src_max_x - dst_max_x; + } +} + +int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf_ptr, int* timestamp_ptr) { + WebPIterator iter; + uint32_t width; + uint32_t height; + int is_key_frame; + int timestamp; + BlendRowFunc blend_row; + + if (dec == NULL || buf_ptr == NULL || timestamp_ptr == NULL) return 0; + if (!WebPAnimDecoderHasMoreFrames(dec)) return 0; + + width = dec->info_.canvas_width; + height = dec->info_.canvas_height; + blend_row = dec->blend_func_; + + // Get compressed frame. + if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) { + return 0; + } + timestamp = dec->prev_frame_timestamp_ + iter.duration; + + // Initialize. + is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_, + dec->prev_frame_was_keyframe_, width, height); + if (is_key_frame) { + if (!ZeroFillCanvas(dec->curr_frame_, width, height)) { + goto Error; + } + } else { + if (!CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, + width, height)) { + goto Error; + } + } + + // Decode. + { + const uint8_t* in = iter.fragment.bytes; + const size_t in_size = iter.fragment.size; + const uint32_t stride = width * NUM_CHANNELS; // at most 25 + 2 bits + const uint64_t out_offset = (uint64_t)iter.y_offset * stride + + (uint64_t)iter.x_offset * NUM_CHANNELS; // 53b + const uint64_t size = (uint64_t)iter.height * stride; // at most 25 + 27b + WebPDecoderConfig* const config = &dec->config_; + WebPRGBABuffer* const buf = &config->output.u.RGBA; + if ((size_t)size != size) goto Error; + buf->stride = (int)stride; + buf->size = (size_t)size; + buf->rgba = dec->curr_frame_ + out_offset; + + if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) { + goto Error; + } + } + + // During the decoding of current frame, we may have set some pixels to be + // transparent (i.e. alpha < 255). However, the value of each of these + // pixels should have been determined by blending it against the value of + // that pixel in the previous frame if blending method of is WEBP_MUX_BLEND. + if (iter.frame_num > 1 && iter.blend_method == WEBP_MUX_BLEND && + !is_key_frame) { + if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_NONE) { + int y; + // Blend transparent pixels with pixels in previous canvas. + for (y = 0; y < iter.height; ++y) { + const size_t offset = + (iter.y_offset + y) * width + iter.x_offset; + blend_row((uint32_t*)dec->curr_frame_ + offset, + (uint32_t*)dec->prev_frame_disposed_ + offset, iter.width); + } + } else { + int y; + assert(dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND); + // We need to blend a transparent pixel with its value just after + // initialization. That is, blend it with: + // * Fully transparent pixel if it belongs to prevRect <-- No-op. + // * The pixel in the previous canvas otherwise <-- Need alpha-blending. + for (y = 0; y < iter.height; ++y) { + const int canvas_y = iter.y_offset + y; + int left1, width1, left2, width2; + FindBlendRangeAtRow(&iter, &dec->prev_iter_, canvas_y, &left1, &width1, + &left2, &width2); + if (width1 > 0) { + const size_t offset1 = canvas_y * width + left1; + blend_row((uint32_t*)dec->curr_frame_ + offset1, + (uint32_t*)dec->prev_frame_disposed_ + offset1, width1); + } + if (width2 > 0) { + const size_t offset2 = canvas_y * width + left2; + blend_row((uint32_t*)dec->curr_frame_ + offset2, + (uint32_t*)dec->prev_frame_disposed_ + offset2, width2); + } + } + } + } + + // Update info of the previous frame and dispose it for the next iteration. + dec->prev_frame_timestamp_ = timestamp; + WebPDemuxReleaseIterator(&dec->prev_iter_); + dec->prev_iter_ = iter; + dec->prev_frame_was_keyframe_ = is_key_frame; + if (!CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height)) { + goto Error; + } + if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { + ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, + dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, + dec->prev_iter_.width, dec->prev_iter_.height); + } + ++dec->next_frame_; + + // All OK, fill in the values. + *buf_ptr = dec->curr_frame_; + *timestamp_ptr = timestamp; + return 1; + + Error: + WebPDemuxReleaseIterator(&iter); + return 0; +} + +int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) { + if (dec == NULL) return 0; + return (dec->next_frame_ <= (int)dec->info_.frame_count); +} + +void WebPAnimDecoderReset(WebPAnimDecoder* dec) { + if (dec != NULL) { + dec->prev_frame_timestamp_ = 0; + WebPDemuxReleaseIterator(&dec->prev_iter_); + memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_)); + dec->prev_frame_was_keyframe_ = 0; + dec->next_frame_ = 1; + } +} + +const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) { + if (dec == NULL) return NULL; + return dec->demux_; +} + +void WebPAnimDecoderDelete(WebPAnimDecoder* dec) { + if (dec != NULL) { + WebPDemuxReleaseIterator(&dec->prev_iter_); + WebPDemuxDelete(dec->demux_); + WebPSafeFree(dec->curr_frame_); + WebPSafeFree(dec->prev_frame_disposed_); + WebPSafeFree(dec); + } +} diff --git a/libraries/webp/src/demux/demux.c b/libraries/webp/src/demux/demux.c new file mode 100644 index 0000000000..d1aa475369 --- /dev/null +++ b/libraries/webp/src/demux/demux.c @@ -0,0 +1,975 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP container demux. +// + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include +#include +#include + +#include "src/utils/utils.h" +#include "include/webp/decode.h" // WebPGetFeatures +#include "include/webp/demux.h" +#include "include/webp/format_constants.h" + +#define DMUX_MAJ_VERSION 1 +#define DMUX_MIN_VERSION 3 +#define DMUX_REV_VERSION 2 + +typedef struct { + size_t start_; // start location of the data + size_t end_; // end location + size_t riff_end_; // riff chunk end location, can be > end_. + size_t buf_size_; // size of the buffer + const uint8_t* buf_; +} MemBuffer; + +typedef struct { + size_t offset_; + size_t size_; +} ChunkData; + +typedef struct Frame { + int x_offset_, y_offset_; + int width_, height_; + int has_alpha_; + int duration_; + WebPMuxAnimDispose dispose_method_; + WebPMuxAnimBlend blend_method_; + int frame_num_; + int complete_; // img_components_ contains a full image. + ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH + struct Frame* next_; +} Frame; + +typedef struct Chunk { + ChunkData data_; + struct Chunk* next_; +} Chunk; + +struct WebPDemuxer { + MemBuffer mem_; + WebPDemuxState state_; + int is_ext_format_; + uint32_t feature_flags_; + int canvas_width_, canvas_height_; + int loop_count_; + uint32_t bgcolor_; + int num_frames_; + Frame* frames_; + Frame** frames_tail_; + Chunk* chunks_; // non-image chunks + Chunk** chunks_tail_; +}; + +typedef enum { + PARSE_OK, + PARSE_NEED_MORE_DATA, + PARSE_ERROR +} ParseStatus; + +typedef struct ChunkParser { + uint8_t id[4]; + ParseStatus (*parse)(WebPDemuxer* const dmux); + int (*valid)(const WebPDemuxer* const dmux); +} ChunkParser; + +static ParseStatus ParseSingleImage(WebPDemuxer* const dmux); +static ParseStatus ParseVP8X(WebPDemuxer* const dmux); +static int IsValidSimpleFormat(const WebPDemuxer* const dmux); +static int IsValidExtendedFormat(const WebPDemuxer* const dmux); + +static const ChunkParser kMasterChunks[] = { + { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat }, + { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat }, + { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat }, + { { '0', '0', '0', '0' }, NULL, NULL }, +}; + +//------------------------------------------------------------------------------ + +int WebPGetDemuxVersion(void) { + return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION; +} + +// ----------------------------------------------------------------------------- +// MemBuffer + +static int RemapMemBuffer(MemBuffer* const mem, + const uint8_t* data, size_t size) { + if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer! + + mem->buf_ = data; + mem->end_ = mem->buf_size_ = size; + return 1; +} + +static int InitMemBuffer(MemBuffer* const mem, + const uint8_t* data, size_t size) { + memset(mem, 0, sizeof(*mem)); + return RemapMemBuffer(mem, data, size); +} + +// Return the remaining data size available in 'mem'. +static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) { + return (mem->end_ - mem->start_); +} + +// Return true if 'size' exceeds the end of the RIFF chunk. +static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) { + return (size > mem->riff_end_ - mem->start_); +} + +static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) { + mem->start_ += size; +} + +static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) { + mem->start_ -= size; +} + +static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) { + return mem->buf_ + mem->start_; +} + +// Read from 'mem' and skip the read bytes. +static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) { + const uint8_t byte = mem->buf_[mem->start_]; + Skip(mem, 1); + return byte; +} + +static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const int val = GetLE16(data); + Skip(mem, 2); + return val; +} + +static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const int val = GetLE24(data); + Skip(mem, 3); + return val; +} + +static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const uint32_t val = GetLE32(data); + Skip(mem, 4); + return val; +} + +// ----------------------------------------------------------------------------- +// Secondary chunk parsing + +static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { + *dmux->chunks_tail_ = chunk; + chunk->next_ = NULL; + dmux->chunks_tail_ = &chunk->next_; +} + +// Add a frame to the end of the list, ensuring the last frame is complete. +// Returns true on success, false otherwise. +static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) { + const Frame* const last_frame = *dmux->frames_tail_; + if (last_frame != NULL && !last_frame->complete_) return 0; + + *dmux->frames_tail_ = frame; + frame->next_ = NULL; + dmux->frames_tail_ = &frame->next_; + return 1; +} + +static void SetFrameInfo(size_t start_offset, size_t size, + int frame_num, int complete, + const WebPBitstreamFeatures* const features, + Frame* const frame) { + frame->img_components_[0].offset_ = start_offset; + frame->img_components_[0].size_ = size; + frame->width_ = features->width; + frame->height_ = features->height; + frame->has_alpha_ |= features->has_alpha; + frame->frame_num_ = frame_num; + frame->complete_ = complete; +} + +// Store image bearing chunks to 'frame'. 'min_size' is an optional size +// requirement, it may be zero. +static ParseStatus StoreFrame(int frame_num, uint32_t min_size, + MemBuffer* const mem, Frame* const frame) { + int alpha_chunks = 0; + int image_chunks = 0; + int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE || + MemDataSize(mem) < min_size); + ParseStatus status = PARSE_OK; + + if (done) return PARSE_NEED_MORE_DATA; + + do { + const size_t chunk_start_offset = mem->start_; + const uint32_t fourcc = ReadLE32(mem); + const uint32_t payload_size = ReadLE32(mem); + uint32_t payload_size_padded; + size_t payload_available; + size_t chunk_size; + + if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + + payload_size_padded = payload_size + (payload_size & 1); + payload_available = (payload_size_padded > MemDataSize(mem)) + ? MemDataSize(mem) : payload_size_padded; + chunk_size = CHUNK_HEADER_SIZE + payload_available; + if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR; + if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA; + + switch (fourcc) { + case MKFOURCC('A', 'L', 'P', 'H'): + if (alpha_chunks == 0) { + ++alpha_chunks; + frame->img_components_[1].offset_ = chunk_start_offset; + frame->img_components_[1].size_ = chunk_size; + frame->has_alpha_ = 1; + frame->frame_num_ = frame_num; + Skip(mem, payload_available); + } else { + goto Done; + } + break; + case MKFOURCC('V', 'P', '8', 'L'): + if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha + // fall through + case MKFOURCC('V', 'P', '8', ' '): + if (image_chunks == 0) { + // Extract the bitstream features, tolerating failures when the data + // is incomplete. + WebPBitstreamFeatures features; + const VP8StatusCode vp8_status = + WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size, + &features); + if (status == PARSE_NEED_MORE_DATA && + vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) { + return PARSE_NEED_MORE_DATA; + } else if (vp8_status != VP8_STATUS_OK) { + // We have enough data, and yet WebPGetFeatures() failed. + return PARSE_ERROR; + } + ++image_chunks; + SetFrameInfo(chunk_start_offset, chunk_size, frame_num, + status == PARSE_OK, &features, frame); + Skip(mem, payload_available); + } else { + goto Done; + } + break; + Done: + default: + // Restore fourcc/size when moving up one level in parsing. + Rewind(mem, CHUNK_HEADER_SIZE); + done = 1; + break; + } + + if (mem->start_ == mem->riff_end_) { + done = 1; + } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { + status = PARSE_NEED_MORE_DATA; + } + } while (!done && status == PARSE_OK); + + return status; +} + +// Creates a new Frame if 'actual_size' is within bounds and 'mem' contains +// enough data ('min_size') to parse the payload. +// Returns PARSE_OK on success with *frame pointing to the new Frame. +// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise. +static ParseStatus NewFrame(const MemBuffer* const mem, + uint32_t min_size, uint32_t actual_size, + Frame** frame) { + if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; + if (actual_size < min_size) return PARSE_ERROR; + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + + *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame)); + return (*frame == NULL) ? PARSE_ERROR : PARSE_OK; +} + +// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow. +// 'frame_chunk_size' is the previously validated, padded chunk size. +static ParseStatus ParseAnimationFrame( + WebPDemuxer* const dmux, uint32_t frame_chunk_size) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE; + int added_frame = 0; + int bits; + MemBuffer* const mem = &dmux->mem_; + Frame* frame; + size_t start_offset; + ParseStatus status = + NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); + if (status != PARSE_OK) return status; + + frame->x_offset_ = 2 * ReadLE24s(mem); + frame->y_offset_ = 2 * ReadLE24s(mem); + frame->width_ = 1 + ReadLE24s(mem); + frame->height_ = 1 + ReadLE24s(mem); + frame->duration_ = ReadLE24s(mem); + bits = ReadByte(mem); + frame->dispose_method_ = + (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; + frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; + if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) { + WebPSafeFree(frame); + return PARSE_ERROR; + } + + // Store a frame only if the animation flag is set there is some data for + // this frame is available. + start_offset = mem->start_; + status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame); + if (status != PARSE_ERROR && mem->start_ - start_offset > anmf_payload_size) { + status = PARSE_ERROR; + } + if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) { + added_frame = AddFrame(dmux, frame); + if (added_frame) { + ++dmux->num_frames_; + } else { + status = PARSE_ERROR; + } + } + + if (!added_frame) WebPSafeFree(frame); + return status; +} + +// General chunk storage, starting with the header at 'start_offset', allowing +// the user to request the payload via a fourcc string. 'size' includes the +// header and the unpadded payload size. +// Returns true on success, false otherwise. +static int StoreChunk(WebPDemuxer* const dmux, + size_t start_offset, uint32_t size) { + Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk)); + if (chunk == NULL) return 0; + + chunk->data_.offset_ = start_offset; + chunk->data_.size_ = size; + AddChunk(dmux, chunk); + return 1; +} + +// ----------------------------------------------------------------------------- +// Primary chunk parsing + +static ParseStatus ReadHeader(MemBuffer* const mem) { + const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE; + uint32_t riff_size; + + // Basic file level validation. + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) || + memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) { + return PARSE_ERROR; + } + + riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); + if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR; + if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + + // There's no point in reading past the end of the RIFF chunk + mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE; + if (mem->buf_size_ > mem->riff_end_) { + mem->buf_size_ = mem->end_ = mem->riff_end_; + } + + Skip(mem, RIFF_HEADER_SIZE); + return PARSE_OK; +} + +static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { + const size_t min_size = CHUNK_HEADER_SIZE; + MemBuffer* const mem = &dmux->mem_; + Frame* frame; + ParseStatus status; + int image_added = 0; + + if (dmux->frames_ != NULL) return PARSE_ERROR; + if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + + frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); + if (frame == NULL) return PARSE_ERROR; + + // For the single image case we allow parsing of a partial frame, so no + // minimum size is imposed here. + status = StoreFrame(1, 0, &dmux->mem_, frame); + if (status != PARSE_ERROR) { + const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); + // Clear any alpha when the alpha flag is missing. + if (!has_alpha && frame->img_components_[1].size_ > 0) { + frame->img_components_[1].offset_ = 0; + frame->img_components_[1].size_ = 0; + frame->has_alpha_ = 0; + } + + // Use the frame width/height as the canvas values for non-vp8x files. + // Also, set ALPHA_FLAG if this is a lossless image with alpha. + if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) { + dmux->state_ = WEBP_DEMUX_PARSED_HEADER; + dmux->canvas_width_ = frame->width_; + dmux->canvas_height_ = frame->height_; + dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; + } + if (!AddFrame(dmux, frame)) { + status = PARSE_ERROR; // last frame was left incomplete + } else { + image_added = 1; + dmux->num_frames_ = 1; + } + } + + if (!image_added) WebPSafeFree(frame); + return status; +} + +static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + MemBuffer* const mem = &dmux->mem_; + int anim_chunks = 0; + ParseStatus status = PARSE_OK; + + do { + int store_chunk = 1; + const size_t chunk_start_offset = mem->start_; + const uint32_t fourcc = ReadLE32(mem); + const uint32_t chunk_size = ReadLE32(mem); + uint32_t chunk_size_padded; + + if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + + chunk_size_padded = chunk_size + (chunk_size & 1); + if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR; + + switch (fourcc) { + case MKFOURCC('V', 'P', '8', 'X'): { + return PARSE_ERROR; + } + case MKFOURCC('A', 'L', 'P', 'H'): + case MKFOURCC('V', 'P', '8', ' '): + case MKFOURCC('V', 'P', '8', 'L'): { + // check that this isn't an animation (all frames should be in an ANMF). + if (anim_chunks > 0 || is_animation) return PARSE_ERROR; + + Rewind(mem, CHUNK_HEADER_SIZE); + status = ParseSingleImage(dmux); + break; + } + case MKFOURCC('A', 'N', 'I', 'M'): { + if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR; + + if (MemDataSize(mem) < chunk_size_padded) { + status = PARSE_NEED_MORE_DATA; + } else if (anim_chunks == 0) { + ++anim_chunks; + dmux->bgcolor_ = ReadLE32(mem); + dmux->loop_count_ = ReadLE16s(mem); + Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE); + } else { + store_chunk = 0; + goto Skip; + } + break; + } + case MKFOURCC('A', 'N', 'M', 'F'): { + if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames. + status = ParseAnimationFrame(dmux, chunk_size_padded); + break; + } + case MKFOURCC('I', 'C', 'C', 'P'): { + store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); + goto Skip; + } + case MKFOURCC('E', 'X', 'I', 'F'): { + store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); + goto Skip; + } + case MKFOURCC('X', 'M', 'P', ' '): { + store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); + goto Skip; + } + Skip: + default: { + if (chunk_size_padded <= MemDataSize(mem)) { + if (store_chunk) { + // Store only the chunk header and unpadded size as only the payload + // will be returned to the user. + if (!StoreChunk(dmux, chunk_start_offset, + CHUNK_HEADER_SIZE + chunk_size)) { + return PARSE_ERROR; + } + } + Skip(mem, chunk_size_padded); + } else { + status = PARSE_NEED_MORE_DATA; + } + } + } + + if (mem->start_ == mem->riff_end_) { + break; + } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { + status = PARSE_NEED_MORE_DATA; + } + } while (status == PARSE_OK); + + return status; +} + +static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { + MemBuffer* const mem = &dmux->mem_; + uint32_t vp8x_size; + + if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; + + dmux->is_ext_format_ = 1; + Skip(mem, TAG_SIZE); // VP8X + vp8x_size = ReadLE32(mem); + if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; + vp8x_size += vp8x_size & 1; + if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; + if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; + + dmux->feature_flags_ = ReadByte(mem); + Skip(mem, 3); // Reserved. + dmux->canvas_width_ = 1 + ReadLE24s(mem); + dmux->canvas_height_ = 1 + ReadLE24s(mem); + if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { + return PARSE_ERROR; // image final dimension is too large + } + Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data. + dmux->state_ = WEBP_DEMUX_PARSED_HEADER; + + if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR; + if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; + + return ParseVP8XChunks(dmux); +} + +// ----------------------------------------------------------------------------- +// Format validation + +static int IsValidSimpleFormat(const WebPDemuxer* const dmux) { + const Frame* const frame = dmux->frames_; + if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; + + if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; + if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0; + + if (frame->width_ <= 0 || frame->height_ <= 0) return 0; + return 1; +} + +// If 'exact' is true, check that the image resolution matches the canvas. +// If 'exact' is false, check that the x/y offsets do not exceed the canvas. +static int CheckFrameBounds(const Frame* const frame, int exact, + int canvas_width, int canvas_height) { + if (exact) { + if (frame->x_offset_ != 0 || frame->y_offset_ != 0) { + return 0; + } + if (frame->width_ != canvas_width || frame->height_ != canvas_height) { + return 0; + } + } else { + if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0; + if (frame->width_ + frame->x_offset_ > canvas_width) return 0; + if (frame->height_ + frame->y_offset_ > canvas_height) return 0; + } + return 1; +} + +static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + const Frame* f = dmux->frames_; + + if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; + + if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; + if (dmux->loop_count_ < 0) return 0; + if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0; + if (dmux->feature_flags_ & ~ALL_VALID_FLAGS) return 0; // invalid bitstream + + while (f != NULL) { + const int cur_frame_set = f->frame_num_; + + // Check frame properties. + for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) { + const ChunkData* const image = f->img_components_; + const ChunkData* const alpha = f->img_components_ + 1; + + if (!is_animation && f->frame_num_ > 1) return 0; + + if (f->complete_) { + if (alpha->size_ == 0 && image->size_ == 0) return 0; + // Ensure alpha precedes image bitstream. + if (alpha->size_ > 0 && alpha->offset_ > image->offset_) { + return 0; + } + + if (f->width_ <= 0 || f->height_ <= 0) return 0; + } else { + // There shouldn't be a partial frame in a complete file. + if (dmux->state_ == WEBP_DEMUX_DONE) return 0; + + // Ensure alpha precedes image bitstream. + if (alpha->size_ > 0 && image->size_ > 0 && + alpha->offset_ > image->offset_) { + return 0; + } + // There shouldn't be any frames after an incomplete one. + if (f->next_ != NULL) return 0; + } + + if (f->width_ > 0 && f->height_ > 0 && + !CheckFrameBounds(f, !is_animation, + dmux->canvas_width_, dmux->canvas_height_)) { + return 0; + } + } + } + return 1; +} + +// ----------------------------------------------------------------------------- +// WebPDemuxer object + +static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) { + dmux->state_ = WEBP_DEMUX_PARSING_HEADER; + dmux->loop_count_ = 1; + dmux->bgcolor_ = 0xFFFFFFFF; // White background by default. + dmux->canvas_width_ = -1; + dmux->canvas_height_ = -1; + dmux->frames_tail_ = &dmux->frames_; + dmux->chunks_tail_ = &dmux->chunks_; + dmux->mem_ = *mem; +} + +static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem, + WebPDemuxer** demuxer) { + WebPBitstreamFeatures features; + const VP8StatusCode status = + WebPGetFeatures(mem->buf_, mem->buf_size_, &features); + *demuxer = NULL; + if (status != VP8_STATUS_OK) { + return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA + : PARSE_ERROR; + } + + { + WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); + Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); + if (dmux == NULL || frame == NULL) goto Error; + InitDemux(dmux, mem); + SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features, + frame); + if (!AddFrame(dmux, frame)) goto Error; + dmux->state_ = WEBP_DEMUX_DONE; + dmux->canvas_width_ = frame->width_; + dmux->canvas_height_ = frame->height_; + dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; + dmux->num_frames_ = 1; + assert(IsValidSimpleFormat(dmux)); + *demuxer = dmux; + return PARSE_OK; + + Error: + WebPSafeFree(dmux); + WebPSafeFree(frame); + return PARSE_ERROR; + } +} + +WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, + WebPDemuxState* state, int version) { + const ChunkParser* parser; + int partial; + ParseStatus status = PARSE_ERROR; + MemBuffer mem; + WebPDemuxer* dmux; + + if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR; + + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; + if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; + + if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; + status = ReadHeader(&mem); + if (status != PARSE_OK) { + // If parsing of the webp file header fails attempt to handle a raw + // VP8/VP8L frame. Note 'allow_partial' is ignored in this case. + if (status == PARSE_ERROR) { + status = CreateRawImageDemuxer(&mem, &dmux); + if (status == PARSE_OK) { + if (state != NULL) *state = WEBP_DEMUX_DONE; + return dmux; + } + } + if (state != NULL) { + *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER + : WEBP_DEMUX_PARSE_ERROR; + } + return NULL; + } + + partial = (mem.buf_size_ < mem.riff_end_); + if (!allow_partial && partial) return NULL; + + dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); + if (dmux == NULL) return NULL; + InitDemux(dmux, &mem); + + status = PARSE_ERROR; + for (parser = kMasterChunks; parser->parse != NULL; ++parser) { + if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { + status = parser->parse(dmux); + if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; + if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; + if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; + if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR; + break; + } + } + if (state != NULL) *state = dmux->state_; + + if (status == PARSE_ERROR) { + WebPDemuxDelete(dmux); + return NULL; + } + return dmux; +} + +void WebPDemuxDelete(WebPDemuxer* dmux) { + Chunk* c; + Frame* f; + if (dmux == NULL) return; + + for (f = dmux->frames_; f != NULL;) { + Frame* const cur_frame = f; + f = f->next_; + WebPSafeFree(cur_frame); + } + for (c = dmux->chunks_; c != NULL;) { + Chunk* const cur_chunk = c; + c = c->next_; + WebPSafeFree(cur_chunk); + } + WebPSafeFree(dmux); +} + +// ----------------------------------------------------------------------------- + +uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) { + if (dmux == NULL) return 0; + + switch (feature) { + case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_; + case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_; + case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_; + case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_; + case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_; + case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_; + } + return 0; +} + +// ----------------------------------------------------------------------------- +// Frame iteration + +static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) { + const Frame* f; + for (f = dmux->frames_; f != NULL; f = f->next_) { + if (frame_num == f->frame_num_) break; + } + return f; +} + +static const uint8_t* GetFramePayload(const uint8_t* const mem_buf, + const Frame* const frame, + size_t* const data_size) { + *data_size = 0; + if (frame != NULL) { + const ChunkData* const image = frame->img_components_; + const ChunkData* const alpha = frame->img_components_ + 1; + size_t start_offset = image->offset_; + *data_size = image->size_; + + // if alpha exists it precedes image, update the size allowing for + // intervening chunks. + if (alpha->size_ > 0) { + const size_t inter_size = (image->offset_ > 0) + ? image->offset_ - (alpha->offset_ + alpha->size_) + : 0; + start_offset = alpha->offset_; + *data_size += alpha->size_ + inter_size; + } + return mem_buf + start_offset; + } + return NULL; +} + +// Create a whole 'frame' from VP8 (+ alpha) or lossless. +static int SynthesizeFrame(const WebPDemuxer* const dmux, + const Frame* const frame, + WebPIterator* const iter) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + size_t payload_size = 0; + const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size); + if (payload == NULL) return 0; + assert(frame != NULL); + + iter->frame_num = frame->frame_num_; + iter->num_frames = dmux->num_frames_; + iter->x_offset = frame->x_offset_; + iter->y_offset = frame->y_offset_; + iter->width = frame->width_; + iter->height = frame->height_; + iter->has_alpha = frame->has_alpha_; + iter->duration = frame->duration_; + iter->dispose_method = frame->dispose_method_; + iter->blend_method = frame->blend_method_; + iter->complete = frame->complete_; + iter->fragment.bytes = payload; + iter->fragment.size = payload_size; + return 1; +} + +static int SetFrame(int frame_num, WebPIterator* const iter) { + const Frame* frame; + const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; + if (dmux == NULL || frame_num < 0) return 0; + if (frame_num > dmux->num_frames_) return 0; + if (frame_num == 0) frame_num = dmux->num_frames_; + + frame = GetFrame(dmux, frame_num); + if (frame == NULL) return 0; + + return SynthesizeFrame(dmux, frame, iter); +} + +int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) { + if (iter == NULL) return 0; + + memset(iter, 0, sizeof(*iter)); + iter->private_ = (void*)dmux; + return SetFrame(frame, iter); +} + +int WebPDemuxNextFrame(WebPIterator* iter) { + if (iter == NULL) return 0; + return SetFrame(iter->frame_num + 1, iter); +} + +int WebPDemuxPrevFrame(WebPIterator* iter) { + if (iter == NULL) return 0; + if (iter->frame_num <= 1) return 0; + return SetFrame(iter->frame_num - 1, iter); +} + +void WebPDemuxReleaseIterator(WebPIterator* iter) { + (void)iter; +} + +// ----------------------------------------------------------------------------- +// Chunk iteration + +static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* c; + int count = 0; + for (c = dmux->chunks_; c != NULL; c = c->next_) { + const uint8_t* const header = mem_buf + c->data_.offset_; + if (!memcmp(header, fourcc, TAG_SIZE)) ++count; + } + return count; +} + +static const Chunk* GetChunk(const WebPDemuxer* const dmux, + const char fourcc[4], int chunk_num) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* c; + int count = 0; + for (c = dmux->chunks_; c != NULL; c = c->next_) { + const uint8_t* const header = mem_buf + c->data_.offset_; + if (!memcmp(header, fourcc, TAG_SIZE)) ++count; + if (count == chunk_num) break; + } + return c; +} + +static int SetChunk(const char fourcc[4], int chunk_num, + WebPChunkIterator* const iter) { + const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; + int count; + + if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0; + count = ChunkCount(dmux, fourcc); + if (count == 0) return 0; + if (chunk_num == 0) chunk_num = count; + + if (chunk_num <= count) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num); + iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE; + iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE; + iter->num_chunks = count; + iter->chunk_num = chunk_num; + return 1; + } + return 0; +} + +int WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], int chunk_num, + WebPChunkIterator* iter) { + if (iter == NULL) return 0; + + memset(iter, 0, sizeof(*iter)); + iter->private_ = (void*)dmux; + return SetChunk(fourcc, chunk_num, iter); +} + +int WebPDemuxNextChunk(WebPChunkIterator* iter) { + if (iter != NULL) { + const char* const fourcc = + (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; + return SetChunk(fourcc, iter->chunk_num + 1, iter); + } + return 0; +} + +int WebPDemuxPrevChunk(WebPChunkIterator* iter) { + if (iter != NULL && iter->chunk_num > 1) { + const char* const fourcc = + (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; + return SetChunk(fourcc, iter->chunk_num - 1, iter); + } + return 0; +} + +void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) { + (void)iter; +} + diff --git a/libraries/webp/src/dsp/alpha_processing.c b/libraries/webp/src/dsp/alpha_processing.c new file mode 100644 index 0000000000..1d152f24da --- /dev/null +++ b/libraries/webp/src/dsp/alpha_processing.c @@ -0,0 +1,496 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "src/dsp/dsp.h" + +// Tables can be faster on some platform but incur some extra binary size (~2k). +#if !defined(USE_TABLES_FOR_ALPHA_MULT) +#define USE_TABLES_FOR_ALPHA_MULT 0 // ALTERNATE_CODE +#endif + + +// ----------------------------------------------------------------------------- + +#define MFIX 24 // 24bit fixed-point arithmetic +#define HALF ((1u << MFIX) >> 1) +#define KINV_255 ((1u << MFIX) / 255u) + +static uint32_t Mult(uint8_t x, uint32_t mult) { + const uint32_t v = (x * mult + HALF) >> MFIX; + assert(v <= 255); // <- 24bit precision is enough to ensure that. + return v; +} + +#if (USE_TABLES_FOR_ALPHA_MULT == 1) + +static const uint32_t kMultTables[2][256] = { + { // (255u << MFIX) / alpha + 0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000, + 0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2, + 0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000, + 0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8, + 0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3, + 0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492, + 0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3, + 0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8, + 0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7, + 0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0, + 0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4, + 0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6, + 0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace, + 0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a, + 0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf, + 0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b, + 0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d, + 0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec, + 0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9, + 0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249, + 0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70, + 0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213, + 0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10, + 0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5, + 0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed, + 0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a, + 0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741, + 0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0, + 0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e, + 0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157, + 0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67, + 0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4, + 0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc, + 0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b, + 0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830, + 0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be, + 0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276, + 0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc, + 0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2, + 0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358, + 0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0, + 0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465, + 0x01030c30, 0x01020612, 0x01010204, 0x01000000 }, + { // alpha * KINV_255 + 0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505, + 0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, + 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111, + 0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717, + 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d, + 0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323, + 0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929, + 0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, + 0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535, + 0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, + 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141, + 0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747, + 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d, + 0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353, + 0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959, + 0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, + 0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565, + 0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, + 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171, + 0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777, + 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d, + 0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383, + 0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989, + 0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, + 0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595, + 0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, + 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1, + 0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, + 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad, + 0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, + 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9, + 0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, + 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5, + 0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, + 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1, + 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, + 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd, + 0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, + 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9, + 0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, + 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5, + 0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, + 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff } +}; + +static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { + return kMultTables[!inverse][a]; +} + +#else + +static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { + return inverse ? (255u << MFIX) / a : a * KINV_255; +} + +#endif // USE_TABLES_FOR_ALPHA_MULT + +void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse) { + int x; + for (x = 0; x < width; ++x) { + const uint32_t argb = ptr[x]; + if (argb < 0xff000000u) { // alpha < 255 + if (argb <= 0x00ffffffu) { // alpha == 0 + ptr[x] = 0; + } else { + const uint32_t alpha = (argb >> 24) & 0xff; + const uint32_t scale = GetScale(alpha, inverse); + uint32_t out = argb & 0xff000000u; + out |= Mult(argb >> 0, scale) << 0; + out |= Mult(argb >> 8, scale) << 8; + out |= Mult(argb >> 16, scale) << 16; + ptr[x] = out; + } + } + } +} + +void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse) { + int x; + for (x = 0; x < width; ++x) { + const uint32_t a = alpha[x]; + if (a != 255) { + if (a == 0) { + ptr[x] = 0; + } else { + const uint32_t scale = GetScale(a, inverse); + ptr[x] = Mult(ptr[x], scale); + } + } + } +} + +#undef KINV_255 +#undef HALF +#undef MFIX + +void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); +void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse); + +//------------------------------------------------------------------------------ +// Generic per-plane calls + +void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, + int inverse) { + int n; + for (n = 0; n < num_rows; ++n) { + WebPMultARGBRow((uint32_t*)ptr, width, inverse); + ptr += stride; + } +} + +void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride, + const uint8_t* WEBP_RESTRICT alpha, int alpha_stride, + int width, int num_rows, int inverse) { + int n; + for (n = 0; n < num_rows; ++n) { + WebPMultRow(ptr, alpha, width, inverse); + ptr += stride; + alpha += alpha_stride; + } +} + +//------------------------------------------------------------------------------ +// Premultiplied modes + +// non dithered-modes + +// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) +// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), +// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 +#if 1 // (int)(x * a / 255.) +#define MULTIPLIER(a) ((a) * 32897U) +#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) +#else // (int)(x * a / 255. + .5) +#define MULTIPLIER(a) ((a) * 65793U) +#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24) +#endif + +#if !WEBP_NEON_OMIT_C_CODE +static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first, + int w, int h, int stride) { + while (h-- > 0) { + uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); + const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); + int i; + for (i = 0; i < w; ++i) { + const uint32_t a = alpha[4 * i]; + if (a != 0xff) { + const uint32_t mult = MULTIPLIER(a); + rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); + rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); + rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); + } + } + rgba += stride; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE +#undef MULTIPLIER +#undef PREMULTIPLY + +// rgbA4444 + +#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15 + +static WEBP_INLINE uint8_t dither_hi(uint8_t x) { + return (x & 0xf0) | (x >> 4); +} + +static WEBP_INLINE uint8_t dither_lo(uint8_t x) { + return (x & 0x0f) | (x << 4); +} + +static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { + return (x * m) >> 16; +} + +static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444, + int w, int h, int stride, + int rg_byte_pos /* 0 or 1 */) { + while (h-- > 0) { + int i; + for (i = 0; i < w; ++i) { + const uint32_t rg = rgba4444[2 * i + rg_byte_pos]; + const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)]; + const uint8_t a = ba & 0x0f; + const uint32_t mult = MULTIPLIER(a); + const uint8_t r = multiply(dither_hi(rg), mult); + const uint8_t g = multiply(dither_lo(rg), mult); + const uint8_t b = multiply(dither_hi(ba), mult); + rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f); + rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a; + } + rgba4444 += stride; + } +} +#undef MULTIPLIER + +static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444, + int w, int h, int stride) { +#if (WEBP_SWAP_16BIT_CSP == 1) + ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1); +#else + ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 0); +#endif +} + +#if !WEBP_NEON_OMIT_C_CODE +static int DispatchAlpha_C(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride, + int width, int height, + uint8_t* WEBP_RESTRICT dst, int dst_stride) { + uint32_t alpha_mask = 0xff; + int i, j; + + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + const uint32_t alpha_value = alpha[i]; + dst[4 * i] = alpha_value; + alpha_mask &= alpha_value; + } + alpha += alpha_stride; + dst += dst_stride; + } + + return (alpha_mask != 0xff); +} + +static void DispatchAlphaToGreen_C(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint32_t* WEBP_RESTRICT dst, + int dst_stride) { + int i, j; + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + dst[i] = alpha[i] << 8; // leave A/R/B channels zero'd. + } + alpha += alpha_stride; + dst += dst_stride; + } +} + +static int ExtractAlpha_C(const uint8_t* WEBP_RESTRICT argb, int argb_stride, + int width, int height, + uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { + uint8_t alpha_mask = 0xff; + int i, j; + + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + const uint8_t alpha_value = argb[4 * i]; + alpha[i] = alpha_value; + alpha_mask &= alpha_value; + } + argb += argb_stride; + alpha += alpha_stride; + } + return (alpha_mask == 0xff); +} + +static void ExtractGreen_C(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size) { + int i; + for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8; +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ + +static int HasAlpha8b_C(const uint8_t* src, int length) { + while (length-- > 0) if (*src++ != 0xff) return 1; + return 0; +} + +static int HasAlpha32b_C(const uint8_t* src, int length) { + int x; + for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1; + return 0; +} + +static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) { + int x; + for (x = 0; x < length; ++x) if ((src[x] >> 24) == 0) src[x] = color; +} + +//------------------------------------------------------------------------------ +// Simple channel manipulations. + +static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { + return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); +} + +#ifdef WORDS_BIGENDIAN +static void PackARGB_C(const uint8_t* WEBP_RESTRICT a, + const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, uint32_t* WEBP_RESTRICT out) { + int i; + for (i = 0; i < len; ++i) { + out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]); + } +} +#endif + +static void PackRGB_C(const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, int step, uint32_t* WEBP_RESTRICT out) { + int i, offset = 0; + for (i = 0; i < len; ++i) { + out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]); + offset += step; + } +} + +void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int); +void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int); +int (*WebPDispatchAlpha)(const uint8_t* WEBP_RESTRICT, int, int, int, + uint8_t* WEBP_RESTRICT, int); +void (*WebPDispatchAlphaToGreen)(const uint8_t* WEBP_RESTRICT, int, int, int, + uint32_t* WEBP_RESTRICT, int); +int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT, int, int, int, + uint8_t* WEBP_RESTRICT, int); +void (*WebPExtractGreen)(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size); +#ifdef WORDS_BIGENDIAN +void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r, const uint8_t* g, + const uint8_t* b, int, uint32_t*); +#endif +void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, int step, uint32_t* WEBP_RESTRICT out); + +int (*WebPHasAlpha8b)(const uint8_t* src, int length); +int (*WebPHasAlpha32b)(const uint8_t* src, int length); +void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color); + +//------------------------------------------------------------------------------ +// Init function + +extern VP8CPUInfo VP8GetCPUInfo; +extern void WebPInitAlphaProcessingMIPSdspR2(void); +extern void WebPInitAlphaProcessingSSE2(void); +extern void WebPInitAlphaProcessingSSE41(void); +extern void WebPInitAlphaProcessingNEON(void); + +WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) { + WebPMultARGBRow = WebPMultARGBRow_C; + WebPMultRow = WebPMultRow_C; + WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C; + +#ifdef WORDS_BIGENDIAN + WebPPackARGB = PackARGB_C; +#endif + WebPPackRGB = PackRGB_C; +#if !WEBP_NEON_OMIT_C_CODE + WebPApplyAlphaMultiply = ApplyAlphaMultiply_C; + WebPDispatchAlpha = DispatchAlpha_C; + WebPDispatchAlphaToGreen = DispatchAlphaToGreen_C; + WebPExtractAlpha = ExtractAlpha_C; + WebPExtractGreen = ExtractGreen_C; +#endif + + WebPHasAlpha8b = HasAlpha8b_C; + WebPHasAlpha32b = HasAlpha32b_C; + WebPAlphaReplace = AlphaReplace_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitAlphaProcessingSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitAlphaProcessingSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPInitAlphaProcessingMIPSdspR2(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitAlphaProcessingNEON(); + } +#endif + + assert(WebPMultARGBRow != NULL); + assert(WebPMultRow != NULL); + assert(WebPApplyAlphaMultiply != NULL); + assert(WebPApplyAlphaMultiply4444 != NULL); + assert(WebPDispatchAlpha != NULL); + assert(WebPDispatchAlphaToGreen != NULL); + assert(WebPExtractAlpha != NULL); + assert(WebPExtractGreen != NULL); +#ifdef WORDS_BIGENDIAN + assert(WebPPackARGB != NULL); +#endif + assert(WebPPackRGB != NULL); + assert(WebPHasAlpha8b != NULL); + assert(WebPHasAlpha32b != NULL); + assert(WebPAlphaReplace != NULL); +} diff --git a/libraries/webp/src/dsp/alpha_processing_mips_dsp_r2.c b/libraries/webp/src/dsp/alpha_processing_mips_dsp_r2.c new file mode 100644 index 0000000000..0090e87cd1 --- /dev/null +++ b/libraries/webp/src/dsp/alpha_processing_mips_dsp_r2.c @@ -0,0 +1,228 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel. +// +// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) +// Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +static int DispatchAlpha_MIPSdspR2(const uint8_t* alpha, int alpha_stride, + int width, int height, + uint8_t* dst, int dst_stride) { + uint32_t alpha_mask = 0xffffffff; + int i, j, temp0; + + for (j = 0; j < height; ++j) { + uint8_t* pdst = dst; + const uint8_t* palpha = alpha; + for (i = 0; i < (width >> 2); ++i) { + int temp1, temp2, temp3; + + __asm__ volatile ( + "ulw %[temp0], 0(%[palpha]) \n\t" + "addiu %[palpha], %[palpha], 4 \n\t" + "addiu %[pdst], %[pdst], 16 \n\t" + "srl %[temp1], %[temp0], 8 \n\t" + "srl %[temp2], %[temp0], 16 \n\t" + "srl %[temp3], %[temp0], 24 \n\t" + "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" + "sb %[temp0], -16(%[pdst]) \n\t" + "sb %[temp1], -12(%[pdst]) \n\t" + "sb %[temp2], -8(%[pdst]) \n\t" + "sb %[temp3], -4(%[pdst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [palpha]"+r"(palpha), [pdst]"+r"(pdst), + [alpha_mask]"+r"(alpha_mask) + : + : "memory" + ); + } + + for (i = 0; i < (width & 3); ++i) { + __asm__ volatile ( + "lbu %[temp0], 0(%[palpha]) \n\t" + "addiu %[palpha], %[palpha], 1 \n\t" + "sb %[temp0], 0(%[pdst]) \n\t" + "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" + "addiu %[pdst], %[pdst], 4 \n\t" + : [temp0]"=&r"(temp0), [palpha]"+r"(palpha), [pdst]"+r"(pdst), + [alpha_mask]"+r"(alpha_mask) + : + : "memory" + ); + } + alpha += alpha_stride; + dst += dst_stride; + } + + __asm__ volatile ( + "ext %[temp0], %[alpha_mask], 0, 16 \n\t" + "srl %[alpha_mask], %[alpha_mask], 16 \n\t" + "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" + "ext %[temp0], %[alpha_mask], 0, 8 \n\t" + "srl %[alpha_mask], %[alpha_mask], 8 \n\t" + "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" + : [temp0]"=&r"(temp0), [alpha_mask]"+r"(alpha_mask) + : + ); + + return (alpha_mask != 0xff); +} + +static void MultARGBRow_MIPSdspR2(uint32_t* const ptr, int width, + int inverse) { + int x; + const uint32_t c_00ffffff = 0x00ffffffu; + const uint32_t c_ff000000 = 0xff000000u; + const uint32_t c_8000000 = 0x00800000u; + const uint32_t c_8000080 = 0x00800080u; + for (x = 0; x < width; ++x) { + const uint32_t argb = ptr[x]; + if (argb < 0xff000000u) { // alpha < 255 + if (argb <= 0x00ffffffu) { // alpha == 0 + ptr[x] = 0; + } else { + int temp0, temp1, temp2, temp3, alpha; + __asm__ volatile ( + "srl %[alpha], %[argb], 24 \n\t" + "replv.qb %[temp0], %[alpha] \n\t" + "and %[temp0], %[temp0], %[c_00ffffff] \n\t" + "beqz %[inverse], 0f \n\t" + "divu $zero, %[c_ff000000], %[alpha] \n\t" + "mflo %[temp0] \n\t" + "0: \n\t" + "andi %[temp1], %[argb], 0xff \n\t" + "ext %[temp2], %[argb], 8, 8 \n\t" + "ext %[temp3], %[argb], 16, 8 \n\t" + "mul %[temp1], %[temp1], %[temp0] \n\t" + "mul %[temp2], %[temp2], %[temp0] \n\t" + "mul %[temp3], %[temp3], %[temp0] \n\t" + "precrq.ph.w %[temp1], %[temp2], %[temp1] \n\t" + "addu %[temp3], %[temp3], %[c_8000000] \n\t" + "addu %[temp1], %[temp1], %[c_8000080] \n\t" + "precrq.ph.w %[temp3], %[argb], %[temp3] \n\t" + "precrq.qb.ph %[temp1], %[temp3], %[temp1] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [alpha]"=&r"(alpha) + : [inverse]"r"(inverse), [c_00ffffff]"r"(c_00ffffff), + [c_8000000]"r"(c_8000000), [c_8000080]"r"(c_8000080), + [c_ff000000]"r"(c_ff000000), [argb]"r"(argb) + : "memory", "hi", "lo" + ); + ptr[x] = temp1; + } + } + } +} + +#ifdef WORDS_BIGENDIAN +static void PackARGB_MIPSdspR2(const uint8_t* a, const uint8_t* r, + const uint8_t* g, const uint8_t* b, int len, + uint32_t* out) { + int temp0, temp1, temp2, temp3, offset; + const int rest = len & 1; + const uint32_t* const loop_end = out + len - rest; + const int step = 4; + __asm__ volatile ( + "xor %[offset], %[offset], %[offset] \n\t" + "beq %[loop_end], %[out], 0f \n\t" + "2: \n\t" + "lbux %[temp0], %[offset](%[a]) \n\t" + "lbux %[temp1], %[offset](%[r]) \n\t" + "lbux %[temp2], %[offset](%[g]) \n\t" + "lbux %[temp3], %[offset](%[b]) \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "ins %[temp3], %[temp2], 16, 16 \n\t" + "addiu %[out], %[out], 4 \n\t" + "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t" + "sw %[temp0], -4(%[out]) \n\t" + "addu %[offset], %[offset], %[step] \n\t" + "bne %[loop_end], %[out], 2b \n\t" + "0: \n\t" + "beq %[rest], $zero, 1f \n\t" + "lbux %[temp0], %[offset](%[a]) \n\t" + "lbux %[temp1], %[offset](%[r]) \n\t" + "lbux %[temp2], %[offset](%[g]) \n\t" + "lbux %[temp3], %[offset](%[b]) \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "ins %[temp3], %[temp2], 16, 16 \n\t" + "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t" + "sw %[temp0], 0(%[out]) \n\t" + "1: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [offset]"=&r"(offset), [out]"+&r"(out) + : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), + [loop_end]"r"(loop_end), [rest]"r"(rest) + : "memory" + ); +} +#endif // WORDS_BIGENDIAN + +static void PackRGB_MIPSdspR2(const uint8_t* r, const uint8_t* g, + const uint8_t* b, int len, int step, + uint32_t* out) { + int temp0, temp1, temp2, offset; + const int rest = len & 1; + const int a = 0xff; + const uint32_t* const loop_end = out + len - rest; + __asm__ volatile ( + "xor %[offset], %[offset], %[offset] \n\t" + "beq %[loop_end], %[out], 0f \n\t" + "2: \n\t" + "lbux %[temp0], %[offset](%[r]) \n\t" + "lbux %[temp1], %[offset](%[g]) \n\t" + "lbux %[temp2], %[offset](%[b]) \n\t" + "ins %[temp0], %[a], 16, 16 \n\t" + "ins %[temp2], %[temp1], 16, 16 \n\t" + "addiu %[out], %[out], 4 \n\t" + "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" + "sw %[temp0], -4(%[out]) \n\t" + "addu %[offset], %[offset], %[step] \n\t" + "bne %[loop_end], %[out], 2b \n\t" + "0: \n\t" + "beq %[rest], $zero, 1f \n\t" + "lbux %[temp0], %[offset](%[r]) \n\t" + "lbux %[temp1], %[offset](%[g]) \n\t" + "lbux %[temp2], %[offset](%[b]) \n\t" + "ins %[temp0], %[a], 16, 16 \n\t" + "ins %[temp2], %[temp1], 16, 16 \n\t" + "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" + "sw %[temp0], 0(%[out]) \n\t" + "1: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [offset]"=&r"(offset), [out]"+&r"(out) + : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), + [loop_end]"r"(loop_end), [rest]"r"(rest) + : "memory" + ); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitAlphaProcessingMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingMIPSdspR2(void) { + WebPDispatchAlpha = DispatchAlpha_MIPSdspR2; + WebPMultARGBRow = MultARGBRow_MIPSdspR2; +#ifdef WORDS_BIGENDIAN + WebPPackARGB = PackARGB_MIPSdspR2; +#endif + WebPPackRGB = PackRGB_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/alpha_processing_neon.c b/libraries/webp/src/dsp/alpha_processing_neon.c new file mode 100644 index 0000000000..6716fb77f0 --- /dev/null +++ b/libraries/webp/src/dsp/alpha_processing_neon.c @@ -0,0 +1,194 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel, NEON version. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include "src/dsp/neon.h" + +//------------------------------------------------------------------------------ + +#define MULTIPLIER(a) ((a) * 0x8081) +#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) + +#define MULTIPLY_BY_ALPHA(V, ALPHA, OTHER) do { \ + const uint8x8_t alpha = (V).val[(ALPHA)]; \ + const uint16x8_t r1 = vmull_u8((V).val[1], alpha); \ + const uint16x8_t g1 = vmull_u8((V).val[2], alpha); \ + const uint16x8_t b1 = vmull_u8((V).val[(OTHER)], alpha); \ + /* we use: v / 255 = (v + 1 + (v >> 8)) >> 8 */ \ + const uint16x8_t r2 = vsraq_n_u16(r1, r1, 8); \ + const uint16x8_t g2 = vsraq_n_u16(g1, g1, 8); \ + const uint16x8_t b2 = vsraq_n_u16(b1, b1, 8); \ + const uint16x8_t r3 = vaddq_u16(r2, kOne); \ + const uint16x8_t g3 = vaddq_u16(g2, kOne); \ + const uint16x8_t b3 = vaddq_u16(b2, kOne); \ + (V).val[1] = vshrn_n_u16(r3, 8); \ + (V).val[2] = vshrn_n_u16(g3, 8); \ + (V).val[(OTHER)] = vshrn_n_u16(b3, 8); \ +} while (0) + +static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first, + int w, int h, int stride) { + const uint16x8_t kOne = vdupq_n_u16(1u); + while (h-- > 0) { + uint32_t* const rgbx = (uint32_t*)rgba; + int i = 0; + if (alpha_first) { + for (; i + 8 <= w; i += 8) { + // load aaaa...|rrrr...|gggg...|bbbb... + uint8x8x4_t RGBX = vld4_u8((const uint8_t*)(rgbx + i)); + MULTIPLY_BY_ALPHA(RGBX, 0, 3); + vst4_u8((uint8_t*)(rgbx + i), RGBX); + } + } else { + for (; i + 8 <= w; i += 8) { + uint8x8x4_t RGBX = vld4_u8((const uint8_t*)(rgbx + i)); + MULTIPLY_BY_ALPHA(RGBX, 3, 0); + vst4_u8((uint8_t*)(rgbx + i), RGBX); + } + } + // Finish with left-overs. + for (; i < w; ++i) { + uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); + const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); + const uint32_t a = alpha[4 * i]; + if (a != 0xff) { + const uint32_t mult = MULTIPLIER(a); + rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); + rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); + rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); + } + } + rgba += stride; + } +} +#undef MULTIPLY_BY_ALPHA +#undef MULTIPLIER +#undef PREMULTIPLY + +//------------------------------------------------------------------------------ + +static int DispatchAlpha_NEON(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint8_t* WEBP_RESTRICT dst, int dst_stride) { + uint32_t alpha_mask = 0xffu; + uint8x8_t mask8 = vdup_n_u8(0xff); + uint32_t tmp[2]; + int i, j; + for (j = 0; j < height; ++j) { + // We don't know if alpha is first or last in dst[] (depending on rgbA/Argb + // mode). So we must be sure dst[4*i + 8 - 1] is writable for the store. + // Hence the test with 'width - 1' instead of just 'width'. + for (i = 0; i + 8 <= width - 1; i += 8) { + uint8x8x4_t rgbX = vld4_u8((const uint8_t*)(dst + 4 * i)); + const uint8x8_t alphas = vld1_u8(alpha + i); + rgbX.val[0] = alphas; + vst4_u8((uint8_t*)(dst + 4 * i), rgbX); + mask8 = vand_u8(mask8, alphas); + } + for (; i < width; ++i) { + const uint32_t alpha_value = alpha[i]; + dst[4 * i] = alpha_value; + alpha_mask &= alpha_value; + } + alpha += alpha_stride; + dst += dst_stride; + } + vst1_u8((uint8_t*)tmp, mask8); + alpha_mask *= 0x01010101; + alpha_mask &= tmp[0]; + alpha_mask &= tmp[1]; + return (alpha_mask != 0xffffffffu); +} + +static void DispatchAlphaToGreen_NEON(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint32_t* WEBP_RESTRICT dst, + int dst_stride) { + int i, j; + uint8x8x4_t greens; // leave A/R/B channels zero'd. + greens.val[0] = vdup_n_u8(0); + greens.val[2] = vdup_n_u8(0); + greens.val[3] = vdup_n_u8(0); + for (j = 0; j < height; ++j) { + for (i = 0; i + 8 <= width; i += 8) { + greens.val[1] = vld1_u8(alpha + i); + vst4_u8((uint8_t*)(dst + i), greens); + } + for (; i < width; ++i) dst[i] = alpha[i] << 8; + alpha += alpha_stride; + dst += dst_stride; + } +} + +static int ExtractAlpha_NEON(const uint8_t* WEBP_RESTRICT argb, int argb_stride, + int width, int height, + uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { + uint32_t alpha_mask = 0xffu; + uint8x8_t mask8 = vdup_n_u8(0xff); + uint32_t tmp[2]; + int i, j; + for (j = 0; j < height; ++j) { + // We don't know if alpha is first or last in dst[] (depending on rgbA/Argb + // mode). So we must be sure dst[4*i + 8 - 1] is writable for the store. + // Hence the test with 'width - 1' instead of just 'width'. + for (i = 0; i + 8 <= width - 1; i += 8) { + const uint8x8x4_t rgbX = vld4_u8((const uint8_t*)(argb + 4 * i)); + const uint8x8_t alphas = rgbX.val[0]; + vst1_u8((uint8_t*)(alpha + i), alphas); + mask8 = vand_u8(mask8, alphas); + } + for (; i < width; ++i) { + alpha[i] = argb[4 * i]; + alpha_mask &= alpha[i]; + } + argb += argb_stride; + alpha += alpha_stride; + } + vst1_u8((uint8_t*)tmp, mask8); + alpha_mask *= 0x01010101; + alpha_mask &= tmp[0]; + alpha_mask &= tmp[1]; + return (alpha_mask == 0xffffffffu); +} + +static void ExtractGreen_NEON(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size) { + int i; + for (i = 0; i + 16 <= size; i += 16) { + const uint8x16x4_t rgbX = vld4q_u8((const uint8_t*)(argb + i)); + const uint8x16_t greens = rgbX.val[1]; + vst1q_u8(alpha + i, greens); + } + for (; i < size; ++i) alpha[i] = (argb[i] >> 8) & 0xff; +} + +//------------------------------------------------------------------------------ + +extern void WebPInitAlphaProcessingNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingNEON(void) { + WebPApplyAlphaMultiply = ApplyAlphaMultiply_NEON; + WebPDispatchAlpha = DispatchAlpha_NEON; + WebPDispatchAlphaToGreen = DispatchAlphaToGreen_NEON; + WebPExtractAlpha = ExtractAlpha_NEON; + WebPExtractGreen = ExtractGreen_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/alpha_processing_sse2.c b/libraries/webp/src/dsp/alpha_processing_sse2.c new file mode 100644 index 0000000000..aa0cc2848a --- /dev/null +++ b/libraries/webp/src/dsp/alpha_processing_sse2.c @@ -0,0 +1,408 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) +#include + +//------------------------------------------------------------------------------ + +static int DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint8_t* WEBP_RESTRICT dst, int dst_stride) { + // alpha_and stores an 'and' operation of all the alpha[] values. The final + // value is not 0xff if any of the alpha[] is not equal to 0xff. + uint32_t alpha_and = 0xff; + int i, j; + const __m128i zero = _mm_setzero_si128(); + const __m128i rgb_mask = _mm_set1_epi32((int)0xffffff00); // to preserve RGB + const __m128i all_0xff = _mm_set_epi32(0, 0, ~0, ~0); + __m128i all_alphas = all_0xff; + + // We must be able to access 3 extra bytes after the last written byte + // 'dst[4 * width - 4]', because we don't know if alpha is the first or the + // last byte of the quadruplet. + const int limit = (width - 1) & ~7; + + for (j = 0; j < height; ++j) { + __m128i* out = (__m128i*)dst; + for (i = 0; i < limit; i += 8) { + // load 8 alpha bytes + const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[i]); + const __m128i a1 = _mm_unpacklo_epi8(a0, zero); + const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); + const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); + // load 8 dst pixels (32 bytes) + const __m128i b0_lo = _mm_loadu_si128(out + 0); + const __m128i b0_hi = _mm_loadu_si128(out + 1); + // mask dst alpha values + const __m128i b1_lo = _mm_and_si128(b0_lo, rgb_mask); + const __m128i b1_hi = _mm_and_si128(b0_hi, rgb_mask); + // combine + const __m128i b2_lo = _mm_or_si128(b1_lo, a2_lo); + const __m128i b2_hi = _mm_or_si128(b1_hi, a2_hi); + // store + _mm_storeu_si128(out + 0, b2_lo); + _mm_storeu_si128(out + 1, b2_hi); + // accumulate eight alpha 'and' in parallel + all_alphas = _mm_and_si128(all_alphas, a0); + out += 2; + } + for (; i < width; ++i) { + const uint32_t alpha_value = alpha[i]; + dst[4 * i] = alpha_value; + alpha_and &= alpha_value; + } + alpha += alpha_stride; + dst += dst_stride; + } + // Combine the eight alpha 'and' into a 8-bit mask. + alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); + return (alpha_and != 0xff); +} + +static void DispatchAlphaToGreen_SSE2(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint32_t* WEBP_RESTRICT dst, + int dst_stride) { + int i, j; + const __m128i zero = _mm_setzero_si128(); + const int limit = width & ~15; + for (j = 0; j < height; ++j) { + for (i = 0; i < limit; i += 16) { // process 16 alpha bytes + const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]); + const __m128i a1 = _mm_unpacklo_epi8(zero, a0); // note the 'zero' first! + const __m128i b1 = _mm_unpackhi_epi8(zero, a0); + const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); + const __m128i b2_lo = _mm_unpacklo_epi16(b1, zero); + const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); + const __m128i b2_hi = _mm_unpackhi_epi16(b1, zero); + _mm_storeu_si128((__m128i*)&dst[i + 0], a2_lo); + _mm_storeu_si128((__m128i*)&dst[i + 4], a2_hi); + _mm_storeu_si128((__m128i*)&dst[i + 8], b2_lo); + _mm_storeu_si128((__m128i*)&dst[i + 12], b2_hi); + } + for (; i < width; ++i) dst[i] = alpha[i] << 8; + alpha += alpha_stride; + dst += dst_stride; + } +} + +static int ExtractAlpha_SSE2(const uint8_t* WEBP_RESTRICT argb, int argb_stride, + int width, int height, + uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { + // alpha_and stores an 'and' operation of all the alpha[] values. The final + // value is not 0xff if any of the alpha[] is not equal to 0xff. + uint32_t alpha_and = 0xff; + int i, j; + const __m128i a_mask = _mm_set1_epi32(0xff); // to preserve alpha + const __m128i all_0xff = _mm_set_epi32(0, 0, ~0, ~0); + __m128i all_alphas = all_0xff; + + // We must be able to access 3 extra bytes after the last written byte + // 'src[4 * width - 4]', because we don't know if alpha is the first or the + // last byte of the quadruplet. + const int limit = (width - 1) & ~7; + + for (j = 0; j < height; ++j) { + const __m128i* src = (const __m128i*)argb; + for (i = 0; i < limit; i += 8) { + // load 32 argb bytes + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i b0 = _mm_and_si128(a0, a_mask); + const __m128i b1 = _mm_and_si128(a1, a_mask); + const __m128i c0 = _mm_packs_epi32(b0, b1); + const __m128i d0 = _mm_packus_epi16(c0, c0); + // store + _mm_storel_epi64((__m128i*)&alpha[i], d0); + // accumulate eight alpha 'and' in parallel + all_alphas = _mm_and_si128(all_alphas, d0); + src += 2; + } + for (; i < width; ++i) { + const uint32_t alpha_value = argb[4 * i]; + alpha[i] = alpha_value; + alpha_and &= alpha_value; + } + argb += argb_stride; + alpha += alpha_stride; + } + // Combine the eight alpha 'and' into a 8-bit mask. + alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); + return (alpha_and == 0xff); +} + +static void ExtractGreen_SSE2(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size) { + int i; + const __m128i mask = _mm_set1_epi32(0xff); + const __m128i* src = (const __m128i*)argb; + + for (i = 0; i + 16 <= size; i += 16, src += 4) { + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i a2 = _mm_loadu_si128(src + 2); + const __m128i a3 = _mm_loadu_si128(src + 3); + const __m128i b0 = _mm_srli_epi32(a0, 8); + const __m128i b1 = _mm_srli_epi32(a1, 8); + const __m128i b2 = _mm_srli_epi32(a2, 8); + const __m128i b3 = _mm_srli_epi32(a3, 8); + const __m128i c0 = _mm_and_si128(b0, mask); + const __m128i c1 = _mm_and_si128(b1, mask); + const __m128i c2 = _mm_and_si128(b2, mask); + const __m128i c3 = _mm_and_si128(b3, mask); + const __m128i d0 = _mm_packs_epi32(c0, c1); + const __m128i d1 = _mm_packs_epi32(c2, c3); + const __m128i e = _mm_packus_epi16(d0, d1); + // store + _mm_storeu_si128((__m128i*)&alpha[i], e); + } + if (i + 8 <= size) { + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i b0 = _mm_srli_epi32(a0, 8); + const __m128i b1 = _mm_srli_epi32(a1, 8); + const __m128i c0 = _mm_and_si128(b0, mask); + const __m128i c1 = _mm_and_si128(b1, mask); + const __m128i d = _mm_packs_epi32(c0, c1); + const __m128i e = _mm_packus_epi16(d, d); + _mm_storel_epi64((__m128i*)&alpha[i], e); + i += 8; + } + for (; i < size; ++i) alpha[i] = argb[i] >> 8; +} + +//------------------------------------------------------------------------------ +// Non-dither premultiplied modes + +#define MULTIPLIER(a) ((a) * 0x8081) +#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) + +// We can't use a 'const int' for the SHUFFLE value, because it has to be an +// immediate in the _mm_shufflexx_epi16() instruction. We really need a macro. +// We use: v / 255 = (v * 0x8081) >> 23, where v = alpha * {r,g,b} is a 16bit +// value. +#define APPLY_ALPHA(RGBX, SHUFFLE) do { \ + const __m128i argb0 = _mm_loadu_si128((const __m128i*)&(RGBX)); \ + const __m128i argb1_lo = _mm_unpacklo_epi8(argb0, zero); \ + const __m128i argb1_hi = _mm_unpackhi_epi8(argb0, zero); \ + const __m128i alpha0_lo = _mm_or_si128(argb1_lo, kMask); \ + const __m128i alpha0_hi = _mm_or_si128(argb1_hi, kMask); \ + const __m128i alpha1_lo = _mm_shufflelo_epi16(alpha0_lo, SHUFFLE); \ + const __m128i alpha1_hi = _mm_shufflelo_epi16(alpha0_hi, SHUFFLE); \ + const __m128i alpha2_lo = _mm_shufflehi_epi16(alpha1_lo, SHUFFLE); \ + const __m128i alpha2_hi = _mm_shufflehi_epi16(alpha1_hi, SHUFFLE); \ + /* alpha2 = [ff a0 a0 a0][ff a1 a1 a1] */ \ + const __m128i A0_lo = _mm_mullo_epi16(alpha2_lo, argb1_lo); \ + const __m128i A0_hi = _mm_mullo_epi16(alpha2_hi, argb1_hi); \ + const __m128i A1_lo = _mm_mulhi_epu16(A0_lo, kMult); \ + const __m128i A1_hi = _mm_mulhi_epu16(A0_hi, kMult); \ + const __m128i A2_lo = _mm_srli_epi16(A1_lo, 7); \ + const __m128i A2_hi = _mm_srli_epi16(A1_hi, 7); \ + const __m128i A3 = _mm_packus_epi16(A2_lo, A2_hi); \ + _mm_storeu_si128((__m128i*)&(RGBX), A3); \ +} while (0) + +static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first, + int w, int h, int stride) { + const __m128i zero = _mm_setzero_si128(); + const __m128i kMult = _mm_set1_epi16((short)0x8081); + const __m128i kMask = _mm_set_epi16(0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0); + const int kSpan = 4; + while (h-- > 0) { + uint32_t* const rgbx = (uint32_t*)rgba; + int i; + if (!alpha_first) { + for (i = 0; i + kSpan <= w; i += kSpan) { + APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(2, 3, 3, 3)); + } + } else { + for (i = 0; i + kSpan <= w; i += kSpan) { + APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 0, 0, 1)); + } + } + // Finish with left-overs. + for (; i < w; ++i) { + uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); + const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); + const uint32_t a = alpha[4 * i]; + if (a != 0xff) { + const uint32_t mult = MULTIPLIER(a); + rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); + rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); + rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); + } + } + rgba += stride; + } +} +#undef MULTIPLIER +#undef PREMULTIPLY + +//------------------------------------------------------------------------------ +// Alpha detection + +static int HasAlpha8b_SSE2(const uint8_t* src, int length) { + const __m128i all_0xff = _mm_set1_epi8((char)0xff); + int i = 0; + for (; i + 16 <= length; i += 16) { + const __m128i v = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i bits = _mm_cmpeq_epi8(v, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i < length; ++i) if (src[i] != 0xff) return 1; + return 0; +} + +static int HasAlpha32b_SSE2(const uint8_t* src, int length) { + const __m128i alpha_mask = _mm_set1_epi32(0xff); + const __m128i all_0xff = _mm_set1_epi8((char)0xff); + int i = 0; + // We don't know if we can access the last 3 bytes after the last alpha + // value 'src[4 * length - 4]' (because we don't know if alpha is the first + // or the last byte of the quadruplet). Hence the '-3' protection below. + length = length * 4 - 3; // size in bytes + for (; i + 64 <= length; i += 64) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 16)); + const __m128i a2 = _mm_loadu_si128((const __m128i*)(src + i + 32)); + const __m128i a3 = _mm_loadu_si128((const __m128i*)(src + i + 48)); + const __m128i b0 = _mm_and_si128(a0, alpha_mask); + const __m128i b1 = _mm_and_si128(a1, alpha_mask); + const __m128i b2 = _mm_and_si128(a2, alpha_mask); + const __m128i b3 = _mm_and_si128(a3, alpha_mask); + const __m128i c0 = _mm_packs_epi32(b0, b1); + const __m128i c1 = _mm_packs_epi32(b2, b3); + const __m128i d = _mm_packus_epi16(c0, c1); + const __m128i bits = _mm_cmpeq_epi8(d, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i + 32 <= length; i += 32) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 16)); + const __m128i b0 = _mm_and_si128(a0, alpha_mask); + const __m128i b1 = _mm_and_si128(a1, alpha_mask); + const __m128i c = _mm_packs_epi32(b0, b1); + const __m128i d = _mm_packus_epi16(c, c); + const __m128i bits = _mm_cmpeq_epi8(d, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i <= length; i += 4) if (src[i] != 0xff) return 1; + return 0; +} + +static void AlphaReplace_SSE2(uint32_t* src, int length, uint32_t color) { + const __m128i m_color = _mm_set1_epi32((int)color); + const __m128i zero = _mm_setzero_si128(); + int i = 0; + for (; i + 8 <= length; i += 8) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 4)); + const __m128i b0 = _mm_srai_epi32(a0, 24); + const __m128i b1 = _mm_srai_epi32(a1, 24); + const __m128i c0 = _mm_cmpeq_epi32(b0, zero); + const __m128i c1 = _mm_cmpeq_epi32(b1, zero); + const __m128i d0 = _mm_and_si128(c0, m_color); + const __m128i d1 = _mm_and_si128(c1, m_color); + const __m128i e0 = _mm_andnot_si128(c0, a0); + const __m128i e1 = _mm_andnot_si128(c1, a1); + _mm_storeu_si128((__m128i*)(src + i + 0), _mm_or_si128(d0, e0)); + _mm_storeu_si128((__m128i*)(src + i + 4), _mm_or_si128(d1, e1)); + } + for (; i < length; ++i) if ((src[i] >> 24) == 0) src[i] = color; +} + +// ----------------------------------------------------------------------------- +// Apply alpha value to rows + +static void MultARGBRow_SSE2(uint32_t* const ptr, int width, int inverse) { + int x = 0; + if (!inverse) { + const int kSpan = 2; + const __m128i zero = _mm_setzero_si128(); + const __m128i k128 = _mm_set1_epi16(128); + const __m128i kMult = _mm_set1_epi16(0x0101); + const __m128i kMask = _mm_set_epi16(0, 0xff, 0, 0, 0, 0xff, 0, 0); + for (x = 0; x + kSpan <= width; x += kSpan) { + // To compute 'result = (int)(a * x / 255. + .5)', we use: + // tmp = a * v + 128, result = (tmp * 0x0101u) >> 16 + const __m128i A0 = _mm_loadl_epi64((const __m128i*)&ptr[x]); + const __m128i A1 = _mm_unpacklo_epi8(A0, zero); + const __m128i A2 = _mm_or_si128(A1, kMask); + const __m128i A3 = _mm_shufflelo_epi16(A2, _MM_SHUFFLE(2, 3, 3, 3)); + const __m128i A4 = _mm_shufflehi_epi16(A3, _MM_SHUFFLE(2, 3, 3, 3)); + // here, A4 = [ff a0 a0 a0][ff a1 a1 a1] + const __m128i A5 = _mm_mullo_epi16(A4, A1); + const __m128i A6 = _mm_add_epi16(A5, k128); + const __m128i A7 = _mm_mulhi_epu16(A6, kMult); + const __m128i A10 = _mm_packus_epi16(A7, zero); + _mm_storel_epi64((__m128i*)&ptr[x], A10); + } + } + width -= x; + if (width > 0) WebPMultARGBRow_C(ptr + x, width, inverse); +} + +static void MultRow_SSE2(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse) { + int x = 0; + if (!inverse) { + const __m128i zero = _mm_setzero_si128(); + const __m128i k128 = _mm_set1_epi16(128); + const __m128i kMult = _mm_set1_epi16(0x0101); + for (x = 0; x + 8 <= width; x += 8) { + const __m128i v0 = _mm_loadl_epi64((__m128i*)&ptr[x]); + const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[x]); + const __m128i v1 = _mm_unpacklo_epi8(v0, zero); + const __m128i a1 = _mm_unpacklo_epi8(a0, zero); + const __m128i v2 = _mm_mullo_epi16(v1, a1); + const __m128i v3 = _mm_add_epi16(v2, k128); + const __m128i v4 = _mm_mulhi_epu16(v3, kMult); + const __m128i v5 = _mm_packus_epi16(v4, zero); + _mm_storel_epi64((__m128i*)&ptr[x], v5); + } + } + width -= x; + if (width > 0) WebPMultRow_C(ptr + x, alpha + x, width, inverse); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitAlphaProcessingSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) { + WebPMultARGBRow = MultARGBRow_SSE2; + WebPMultRow = MultRow_SSE2; + WebPApplyAlphaMultiply = ApplyAlphaMultiply_SSE2; + WebPDispatchAlpha = DispatchAlpha_SSE2; + WebPDispatchAlphaToGreen = DispatchAlphaToGreen_SSE2; + WebPExtractAlpha = ExtractAlpha_SSE2; + WebPExtractGreen = ExtractGreen_SSE2; + + WebPHasAlpha8b = HasAlpha8b_SSE2; + WebPHasAlpha32b = HasAlpha32b_SSE2; + WebPAlphaReplace = AlphaReplace_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/alpha_processing_sse41.c b/libraries/webp/src/dsp/alpha_processing_sse41.c new file mode 100644 index 0000000000..1156ac3417 --- /dev/null +++ b/libraries/webp/src/dsp/alpha_processing_sse41.c @@ -0,0 +1,92 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel, SSE4.1 variant. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) + +#include + +//------------------------------------------------------------------------------ + +static int ExtractAlpha_SSE41(const uint8_t* WEBP_RESTRICT argb, + int argb_stride, int width, int height, + uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { + // alpha_and stores an 'and' operation of all the alpha[] values. The final + // value is not 0xff if any of the alpha[] is not equal to 0xff. + uint32_t alpha_and = 0xff; + int i, j; + const __m128i all_0xff = _mm_set1_epi32(~0); + __m128i all_alphas = all_0xff; + + // We must be able to access 3 extra bytes after the last written byte + // 'src[4 * width - 4]', because we don't know if alpha is the first or the + // last byte of the quadruplet. + const int limit = (width - 1) & ~15; + const __m128i kCstAlpha0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 12, 8, 4, 0); + const __m128i kCstAlpha1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, + 12, 8, 4, 0, -1, -1, -1, -1); + const __m128i kCstAlpha2 = _mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0, + -1, -1, -1, -1, -1, -1, -1, -1); + const __m128i kCstAlpha3 = _mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1); + for (j = 0; j < height; ++j) { + const __m128i* src = (const __m128i*)argb; + for (i = 0; i < limit; i += 16) { + // load 64 argb bytes + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i a2 = _mm_loadu_si128(src + 2); + const __m128i a3 = _mm_loadu_si128(src + 3); + const __m128i b0 = _mm_shuffle_epi8(a0, kCstAlpha0); + const __m128i b1 = _mm_shuffle_epi8(a1, kCstAlpha1); + const __m128i b2 = _mm_shuffle_epi8(a2, kCstAlpha2); + const __m128i b3 = _mm_shuffle_epi8(a3, kCstAlpha3); + const __m128i c0 = _mm_or_si128(b0, b1); + const __m128i c1 = _mm_or_si128(b2, b3); + const __m128i d0 = _mm_or_si128(c0, c1); + // store + _mm_storeu_si128((__m128i*)&alpha[i], d0); + // accumulate sixteen alpha 'and' in parallel + all_alphas = _mm_and_si128(all_alphas, d0); + src += 4; + } + for (; i < width; ++i) { + const uint32_t alpha_value = argb[4 * i]; + alpha[i] = alpha_value; + alpha_and &= alpha_value; + } + argb += argb_stride; + alpha += alpha_stride; + } + // Combine the sixteen alpha 'and' into an 8-bit mask. + alpha_and |= 0xff00u; // pretend the upper bits [8..15] were tested ok. + alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); + return (alpha_and == 0xffffu); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitAlphaProcessingSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE41(void) { + WebPExtractAlpha = ExtractAlpha_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/libraries/webp/src/dsp/common_sse2.h b/libraries/webp/src/dsp/common_sse2.h new file mode 100644 index 0000000000..e9f1ebff44 --- /dev/null +++ b/libraries/webp/src/dsp/common_sse2.h @@ -0,0 +1,194 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 code common to several files. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_DSP_COMMON_SSE2_H_ +#define WEBP_DSP_COMMON_SSE2_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(WEBP_USE_SSE2) + +#include + +//------------------------------------------------------------------------------ +// Quite useful macro for debugging. Left here for convenience. + +#if 0 +#include +static WEBP_INLINE void PrintReg(const __m128i r, const char* const name, + int size) { + int n; + union { + __m128i r; + uint8_t i8[16]; + uint16_t i16[8]; + uint32_t i32[4]; + uint64_t i64[2]; + } tmp; + tmp.r = r; + fprintf(stderr, "%s\t: ", name); + if (size == 8) { + for (n = 0; n < 16; ++n) fprintf(stderr, "%.2x ", tmp.i8[n]); + } else if (size == 16) { + for (n = 0; n < 8; ++n) fprintf(stderr, "%.4x ", tmp.i16[n]); + } else if (size == 32) { + for (n = 0; n < 4; ++n) fprintf(stderr, "%.8x ", tmp.i32[n]); + } else { + for (n = 0; n < 2; ++n) fprintf(stderr, "%.16lx ", tmp.i64[n]); + } + fprintf(stderr, "\n"); +} +#endif + +//------------------------------------------------------------------------------ +// Math functions. + +// Return the sum of all the 8b in the register. +static WEBP_INLINE int VP8HorizontalAdd8b(const __m128i* const a) { + const __m128i zero = _mm_setzero_si128(); + const __m128i sad8x2 = _mm_sad_epu8(*a, zero); + // sum the two sads: sad8x2[0:1] + sad8x2[8:9] + const __m128i sum = _mm_add_epi32(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); + return _mm_cvtsi128_si32(sum); +} + +// Transpose two 4x4 16b matrices horizontally stored in registers. +static WEBP_INLINE void VP8Transpose_2_4x4_16b( + const __m128i* const in0, const __m128i* const in1, + const __m128i* const in2, const __m128i* const in3, __m128i* const out0, + __m128i* const out1, __m128i* const out2, __m128i* const out3) { + // Transpose the two 4x4. + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + const __m128i transpose0_0 = _mm_unpacklo_epi16(*in0, *in1); + const __m128i transpose0_1 = _mm_unpacklo_epi16(*in2, *in3); + const __m128i transpose0_2 = _mm_unpackhi_epi16(*in0, *in1); + const __m128i transpose0_3 = _mm_unpackhi_epi16(*in2, *in3); + // a00 a10 a01 a11 a02 a12 a03 a13 + // a20 a30 a21 a31 a22 a32 a23 a33 + // b00 b10 b01 b11 b02 b12 b03 b13 + // b20 b30 b21 b31 b22 b32 b23 b33 + const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); + const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); + const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); + const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); + // a00 a10 a20 a30 a01 a11 a21 a31 + // b00 b10 b20 b30 b01 b11 b21 b31 + // a02 a12 a22 a32 a03 a13 a23 a33 + // b02 b12 a22 b32 b03 b13 b23 b33 + *out0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); + *out1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); + *out2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); + *out3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); + // a00 a10 a20 a30 b00 b10 b20 b30 + // a01 a11 a21 a31 b01 b11 b21 b31 + // a02 a12 a22 a32 b02 b12 b22 b32 + // a03 a13 a23 a33 b03 b13 b23 b33 +} + +//------------------------------------------------------------------------------ +// Channel mixing. + +// Function used several times in VP8PlanarTo24b. +// It samples the in buffer as follows: one every two unsigned char is stored +// at the beginning of the buffer, while the other half is stored at the end. +#define VP8PlanarTo24bHelper(IN, OUT) \ + do { \ + const __m128i v_mask = _mm_set1_epi16(0x00ff); \ + /* Take one every two upper 8b values.*/ \ + (OUT##0) = _mm_packus_epi16(_mm_and_si128((IN##0), v_mask), \ + _mm_and_si128((IN##1), v_mask)); \ + (OUT##1) = _mm_packus_epi16(_mm_and_si128((IN##2), v_mask), \ + _mm_and_si128((IN##3), v_mask)); \ + (OUT##2) = _mm_packus_epi16(_mm_and_si128((IN##4), v_mask), \ + _mm_and_si128((IN##5), v_mask)); \ + /* Take one every two lower 8b values.*/ \ + (OUT##3) = _mm_packus_epi16(_mm_srli_epi16((IN##0), 8), \ + _mm_srli_epi16((IN##1), 8)); \ + (OUT##4) = _mm_packus_epi16(_mm_srli_epi16((IN##2), 8), \ + _mm_srli_epi16((IN##3), 8)); \ + (OUT##5) = _mm_packus_epi16(_mm_srli_epi16((IN##4), 8), \ + _mm_srli_epi16((IN##5), 8)); \ + } while (0) + +// Pack the planar buffers +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... +static WEBP_INLINE void VP8PlanarTo24b_SSE2( + __m128i* const in0, __m128i* const in1, __m128i* const in2, + __m128i* const in3, __m128i* const in4, __m128i* const in5) { + // The input is 6 registers of sixteen 8b but for the sake of explanation, + // let's take 6 registers of four 8b values. + // To pack, we will keep taking one every two 8b integer and move it + // around as follows: + // Input: + // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 + // Split the 6 registers in two sets of 3 registers: the first set as the even + // 8b bytes, the second the odd ones: + // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 + // Repeat the same permutations twice more: + // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 + // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + VP8PlanarTo24bHelper(*in, tmp); + VP8PlanarTo24bHelper(tmp, *in); + VP8PlanarTo24bHelper(*in, tmp); + // We need to do it two more times than the example as we have sixteen bytes. + { + __m128i out0, out1, out2, out3, out4, out5; + VP8PlanarTo24bHelper(tmp, out); + VP8PlanarTo24bHelper(out, *in); + } +} + +#undef VP8PlanarTo24bHelper + +// Convert four packed four-channel buffers like argbargbargbargb... into the +// split channels aaaaa ... rrrr ... gggg .... bbbbb ...... +static WEBP_INLINE void VP8L32bToPlanar_SSE2(__m128i* const in0, + __m128i* const in1, + __m128i* const in2, + __m128i* const in3) { + // Column-wise transpose. + const __m128i A0 = _mm_unpacklo_epi8(*in0, *in1); + const __m128i A1 = _mm_unpackhi_epi8(*in0, *in1); + const __m128i A2 = _mm_unpacklo_epi8(*in2, *in3); + const __m128i A3 = _mm_unpackhi_epi8(*in2, *in3); + const __m128i B0 = _mm_unpacklo_epi8(A0, A1); + const __m128i B1 = _mm_unpackhi_epi8(A0, A1); + const __m128i B2 = _mm_unpacklo_epi8(A2, A3); + const __m128i B3 = _mm_unpackhi_epi8(A2, A3); + // C0 = g7 g6 ... g1 g0 | b7 b6 ... b1 b0 + // C1 = a7 a6 ... a1 a0 | r7 r6 ... r1 r0 + const __m128i C0 = _mm_unpacklo_epi8(B0, B1); + const __m128i C1 = _mm_unpackhi_epi8(B0, B1); + const __m128i C2 = _mm_unpacklo_epi8(B2, B3); + const __m128i C3 = _mm_unpackhi_epi8(B2, B3); + // Gather the channels. + *in0 = _mm_unpackhi_epi64(C1, C3); + *in1 = _mm_unpacklo_epi64(C1, C3); + *in2 = _mm_unpackhi_epi64(C0, C2); + *in3 = _mm_unpacklo_epi64(C0, C2); +} + +#endif // WEBP_USE_SSE2 + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_COMMON_SSE2_H_ diff --git a/libraries/webp/src/dsp/common_sse41.h b/libraries/webp/src/dsp/common_sse41.h new file mode 100644 index 0000000000..2f173c024a --- /dev/null +++ b/libraries/webp/src/dsp/common_sse41.h @@ -0,0 +1,132 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE4 code common to several files. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_DSP_COMMON_SSE41_H_ +#define WEBP_DSP_COMMON_SSE41_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(WEBP_USE_SSE41) +#include + +//------------------------------------------------------------------------------ +// Channel mixing. +// Shuffles the input buffer as A0 0 0 A1 0 0 A2 ... +#define WEBP_SSE41_SHUFF(OUT, IN0, IN1) \ + OUT##0 = _mm_shuffle_epi8(*IN0, shuff0); \ + OUT##1 = _mm_shuffle_epi8(*IN0, shuff1); \ + OUT##2 = _mm_shuffle_epi8(*IN0, shuff2); \ + OUT##3 = _mm_shuffle_epi8(*IN1, shuff0); \ + OUT##4 = _mm_shuffle_epi8(*IN1, shuff1); \ + OUT##5 = _mm_shuffle_epi8(*IN1, shuff2); + +// Pack the planar buffers +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... +static WEBP_INLINE void VP8PlanarTo24b_SSE41( + __m128i* const in0, __m128i* const in1, __m128i* const in2, + __m128i* const in3, __m128i* const in4, __m128i* const in5) { + __m128i R0, R1, R2, R3, R4, R5; + __m128i G0, G1, G2, G3, G4, G5; + __m128i B0, B1, B2, B3, B4, B5; + + // Process R. + { + const __m128i shuff0 = _mm_set_epi8( + 5, -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0); + const __m128i shuff1 = _mm_set_epi8( + -1, 10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1); + const __m128i shuff2 = _mm_set_epi8( + -1, -1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1); + WEBP_SSE41_SHUFF(R, in0, in1) + } + + // Process G. + { + // Same as before, just shifted to the left by one and including the right + // padding. + const __m128i shuff0 = _mm_set_epi8( + -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1); + const __m128i shuff1 = _mm_set_epi8( + 10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5); + const __m128i shuff2 = _mm_set_epi8( + -1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1); + WEBP_SSE41_SHUFF(G, in2, in3) + } + + // Process B. + { + const __m128i shuff0 = _mm_set_epi8( + -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1, -1); + const __m128i shuff1 = _mm_set_epi8( + -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5, -1); + const __m128i shuff2 = _mm_set_epi8( + 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1, 10); + WEBP_SSE41_SHUFF(B, in4, in5) + } + + // OR the different channels. + { + const __m128i RG0 = _mm_or_si128(R0, G0); + const __m128i RG1 = _mm_or_si128(R1, G1); + const __m128i RG2 = _mm_or_si128(R2, G2); + const __m128i RG3 = _mm_or_si128(R3, G3); + const __m128i RG4 = _mm_or_si128(R4, G4); + const __m128i RG5 = _mm_or_si128(R5, G5); + *in0 = _mm_or_si128(RG0, B0); + *in1 = _mm_or_si128(RG1, B1); + *in2 = _mm_or_si128(RG2, B2); + *in3 = _mm_or_si128(RG3, B3); + *in4 = _mm_or_si128(RG4, B4); + *in5 = _mm_or_si128(RG5, B5); + } +} + +#undef WEBP_SSE41_SHUFF + +// Convert four packed four-channel buffers like argbargbargbargb... into the +// split channels aaaaa ... rrrr ... gggg .... bbbbb ...... +static WEBP_INLINE void VP8L32bToPlanar_SSE41(__m128i* const in0, + __m128i* const in1, + __m128i* const in2, + __m128i* const in3) { + // aaaarrrrggggbbbb + const __m128i shuff0 = + _mm_set_epi8(15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0); + const __m128i A0 = _mm_shuffle_epi8(*in0, shuff0); + const __m128i A1 = _mm_shuffle_epi8(*in1, shuff0); + const __m128i A2 = _mm_shuffle_epi8(*in2, shuff0); + const __m128i A3 = _mm_shuffle_epi8(*in3, shuff0); + // A0A1R0R1 + // G0G1B0B1 + // A2A3R2R3 + // G0G1B0B1 + const __m128i B0 = _mm_unpacklo_epi32(A0, A1); + const __m128i B1 = _mm_unpackhi_epi32(A0, A1); + const __m128i B2 = _mm_unpacklo_epi32(A2, A3); + const __m128i B3 = _mm_unpackhi_epi32(A2, A3); + *in3 = _mm_unpacklo_epi64(B0, B2); + *in2 = _mm_unpackhi_epi64(B0, B2); + *in1 = _mm_unpacklo_epi64(B1, B3); + *in0 = _mm_unpackhi_epi64(B1, B3); +} + +#endif // WEBP_USE_SSE41 + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_COMMON_SSE41_H_ diff --git a/libraries/webp/src/dsp/cost.c b/libraries/webp/src/dsp/cost.c new file mode 100644 index 0000000000..73d2140177 --- /dev/null +++ b/libraries/webp/src/dsp/cost.c @@ -0,0 +1,412 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" +#include "src/enc/cost_enc.h" + +//------------------------------------------------------------------------------ +// Boolean-cost cost table + +const uint16_t VP8EntropyCost[256] = { + 1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216, + 1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951, + 939, 911, 896, 878, 871, 854, 838, 820, 811, 794, + 786, 768, 768, 752, 740, 732, 720, 709, 704, 690, + 683, 672, 666, 655, 647, 640, 631, 622, 615, 607, + 598, 592, 586, 576, 572, 564, 559, 555, 547, 541, + 534, 528, 522, 512, 512, 504, 500, 494, 488, 483, + 477, 473, 467, 461, 458, 452, 448, 443, 438, 434, + 427, 424, 419, 415, 410, 406, 403, 399, 394, 390, + 384, 384, 377, 374, 370, 366, 362, 359, 355, 351, + 347, 342, 342, 336, 333, 330, 326, 323, 320, 316, + 312, 308, 305, 302, 299, 296, 293, 288, 287, 283, + 280, 277, 274, 272, 268, 266, 262, 256, 256, 256, + 251, 248, 245, 242, 240, 237, 234, 232, 228, 226, + 223, 221, 218, 216, 214, 211, 208, 205, 203, 201, + 198, 196, 192, 191, 188, 187, 183, 181, 179, 176, + 175, 171, 171, 168, 165, 163, 160, 159, 156, 154, + 152, 150, 148, 146, 144, 142, 139, 138, 135, 133, + 131, 128, 128, 125, 123, 121, 119, 117, 115, 113, + 111, 110, 107, 105, 103, 102, 100, 98, 96, 94, + 92, 91, 89, 86, 86, 83, 82, 80, 77, 76, + 74, 73, 71, 69, 67, 66, 64, 63, 61, 59, + 57, 55, 54, 52, 51, 49, 47, 46, 44, 43, + 41, 40, 38, 36, 35, 33, 32, 30, 29, 27, + 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, + 10, 9, 7, 6, 4, 3 +}; + +//------------------------------------------------------------------------------ +// Level cost tables + +// fixed costs for coding levels, deduce from the coding tree. +// This is only the part that doesn't depend on the probability state. +const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = { + 0, 256, 256, 256, 256, 432, 618, 630, + 731, 640, 640, 828, 901, 948, 1021, 1101, + 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202, + 1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497, + 1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358, + 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532, + 1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679, + 1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853, + 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759, + 1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832, + 1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910, + 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983, + 1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059, + 2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132, + 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210, + 2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283, + 2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200, + 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273, + 2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351, + 2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424, + 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500, + 2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573, + 2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651, + 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724, + 2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572, + 2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645, + 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723, + 2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796, + 2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872, + 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945, + 2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023, + 3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096, + 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013, + 3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086, + 3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164, + 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237, + 3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313, + 3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386, + 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464, + 3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537, + 3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848, + 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921, + 2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999, + 3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072, + 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148, + 3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221, + 3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299, + 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372, + 3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289, + 3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362, + 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440, + 3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513, + 3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589, + 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662, + 3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740, + 3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813, + 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661, + 3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734, + 3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812, + 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885, + 3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961, + 3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034, + 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112, + 4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185, + 4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102, + 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175, + 4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253, + 4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326, + 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402, + 4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475, + 4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553, + 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626, + 4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547, + 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620, + 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, + 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, + 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847, + 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, + 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, + 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071, + 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, + 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, + 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139, + 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, + 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, + 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361, + 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, + 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, + 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360, + 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, + 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, + 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584, + 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, + 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, + 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811, + 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, + 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, + 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874, + 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, + 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, + 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101, + 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, + 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, + 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325, + 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, + 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, + 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787, + 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, + 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, + 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009, + 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, + 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, + 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077, + 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, + 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, + 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301, + 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, + 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, + 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528, + 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, + 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, + 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522, + 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, + 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, + 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749, + 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, + 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, + 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973, + 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, + 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, + 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041, + 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, + 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, + 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263, + 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, + 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, + 6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547, + 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620, + 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, + 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, + 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847, + 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, + 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, + 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071, + 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, + 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, + 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139, + 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, + 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, + 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361, + 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, + 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, + 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360, + 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, + 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, + 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584, + 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, + 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, + 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811, + 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, + 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, + 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874, + 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, + 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, + 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101, + 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, + 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, + 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325, + 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, + 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, + 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787, + 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, + 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, + 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009, + 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, + 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, + 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077, + 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, + 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, + 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301, + 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, + 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, + 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528, + 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, + 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, + 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522, + 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, + 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, + 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749, + 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, + 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, + 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973, + 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, + 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, + 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041, + 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, + 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, + 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263, + 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, + 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, + 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335, + 5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408, + 5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486, + 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559, + 5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635, + 5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708, + 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786, + 5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859, + 5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776, + 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849, + 5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927, + 5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000, + 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076, + 6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149, + 6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227, + 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300, + 6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148, + 6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221, + 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299, + 6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372, + 6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448, + 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521, + 6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599, + 6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672, + 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589, + 6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662, + 6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740, + 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813, + 6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889, + 6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962, + 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040, + 7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113, + 7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424, + 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497, + 6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575, + 6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648, + 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724, + 6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797, + 6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875, + 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948, + 6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865, + 6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938, + 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016, + 7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089, + 7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165, + 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238, + 7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316, + 7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389, + 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237, + 7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310, + 7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388, + 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461, + 7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537, + 7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610, + 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688, + 7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761 +}; + +//------------------------------------------------------------------------------ +// Tables for level coding + +const uint8_t VP8EncBands[16 + 1] = { + 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 0 // sentinel +}; + +//------------------------------------------------------------------------------ +// Mode costs + +static int GetResidualCost_C(int ctx0, const VP8Residual* const res) { + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + for (; n < res->last; ++n) { + const int v = abs(res->coeffs[n]); + const int ctx = (v >= 2) ? 2 : v; + cost += VP8LevelCost(t, v); + t = costs[n + 1][ctx]; + } + // Last coefficient is always non-zero + { + const int v = abs(res->coeffs[n]); + assert(v != 0); + cost += VP8LevelCost(t, v); + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = (v == 1) ? 1 : 2; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +static void SetResidualCoeffs_C(const int16_t* const coeffs, + VP8Residual* const res) { + int n; + res->last = -1; + assert(res->first == 0 || coeffs[0] == 0); + for (n = 15; n >= 0; --n) { + if (coeffs[n]) { + res->last = n; + break; + } + } + res->coeffs = coeffs; +} + +//------------------------------------------------------------------------------ +// init function + +VP8GetResidualCostFunc VP8GetResidualCost; +VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8EncDspCostInitMIPS32(void); +extern void VP8EncDspCostInitMIPSdspR2(void); +extern void VP8EncDspCostInitSSE2(void); +extern void VP8EncDspCostInitNEON(void); + +WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) { + VP8GetResidualCost = GetResidualCost_C; + VP8SetResidualCoeffs = SetResidualCoeffs_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8EncDspCostInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8EncDspCostInitMIPSdspR2(); + } +#endif +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8EncDspCostInitSSE2(); + } +#endif +#if defined(WEBP_HAVE_NEON) + if (VP8GetCPUInfo(kNEON)) { + VP8EncDspCostInitNEON(); + } +#endif + } +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dsp/cost_mips32.c b/libraries/webp/src/dsp/cost_mips32.c new file mode 100644 index 0000000000..0500f88c13 --- /dev/null +++ b/libraries/webp/src/dsp/cost_mips32.c @@ -0,0 +1,154 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) + +#include "src/enc/cost_enc.h" + +static int GetResidualCost_MIPS32(int ctx0, const VP8Residual* const res) { + int temp0, temp1; + int v_reg, ctx_reg; + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + const int16_t* res_coeffs = res->coeffs; + const int res_last = res->last; + const int const_max_level = MAX_VARIABLE_LEVEL; + const int const_2 = 2; + const uint16_t** p_costs = &costs[n][0]; + const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs); + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "subu %[temp1], %[res_last], %[n] \n\t" + "sll %[temp0], %[n], 1 \n\t" + "blez %[temp1], 2f \n\t" + " addu %[res_coeffs], %[res_coeffs], %[temp0] \n\t" + "1: \n\t" + "lh %[v_reg], 0(%[res_coeffs]) \n\t" + "addiu %[n], %[n], 1 \n\t" + "negu %[temp0], %[v_reg] \n\t" + "slti %[temp1], %[v_reg], 0 \n\t" + "movn %[v_reg], %[temp0], %[temp1] \n\t" + "sltiu %[temp0], %[v_reg], 2 \n\t" + "move %[ctx_reg], %[v_reg] \n\t" + "movz %[ctx_reg], %[const_2], %[temp0] \n\t" + "sll %[temp1], %[v_reg], 1 \n\t" + "addu %[temp1], %[temp1], %[VP8LevelFixedCosts] \n\t" + "lhu %[temp1], 0(%[temp1]) \n\t" + "slt %[temp0], %[v_reg], %[const_max_level] \n\t" + "movz %[v_reg], %[const_max_level], %[temp0] \n\t" + "addu %[cost], %[cost], %[temp1] \n\t" + "sll %[v_reg], %[v_reg], 1 \n\t" + "sll %[ctx_reg], %[ctx_reg], 2 \n\t" + "addu %[v_reg], %[v_reg], %[t] \n\t" + "lhu %[temp0], 0(%[v_reg]) \n\t" + "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t" + "addu %[t], %[p_costs], %[ctx_reg] \n\t" + "addu %[cost], %[cost], %[temp0] \n\t" + "addiu %[res_coeffs], %[res_coeffs], 2 \n\t" + "bne %[n], %[res_last], 1b \n\t" + " lw %[t], 0(%[t]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg), + [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1), [res_coeffs]"+&r"(res_coeffs) + : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level), + [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last), + [inc_p_costs]"r"(inc_p_costs) + : "memory" + ); + + // Last coefficient is always non-zero + { + const int v = abs(res->coeffs[n]); + assert(v != 0); + cost += VP8LevelCost(t, v); + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = (v == 1) ? 1 : 2; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +static void SetResidualCoeffs_MIPS32(const int16_t* const coeffs, + VP8Residual* const res) { + const int16_t* p_coeffs = (int16_t*)coeffs; + int temp0, temp1, temp2, n, n1; + assert(res->first == 0 || coeffs[0] == 0); + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[p_coeffs], %[p_coeffs], 28 \n\t" + "li %[n], 15 \n\t" + "li %[temp2], -1 \n\t" + "0: \n\t" + "ulw %[temp0], 0(%[p_coeffs]) \n\t" + "beqz %[temp0], 1f \n\t" +#if defined(WORDS_BIGENDIAN) + " sll %[temp1], %[temp0], 16 \n\t" +#else + " srl %[temp1], %[temp0], 16 \n\t" +#endif + "addiu %[n1], %[n], -1 \n\t" + "movz %[temp0], %[n1], %[temp1] \n\t" + "movn %[temp0], %[n], %[temp1] \n\t" + "j 2f \n\t" + " addiu %[temp2], %[temp0], 0 \n\t" + "1: \n\t" + "addiu %[n], %[n], -2 \n\t" + "bgtz %[n], 0b \n\t" + " addiu %[p_coeffs], %[p_coeffs], -4 \n\t" + "2: \n\t" + ".set pop \n\t" + : [p_coeffs]"+&r"(p_coeffs), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [n]"=&r"(n), [n1]"=&r"(n1) + : + : "memory" + ); + res->last = temp2; + res->coeffs = coeffs; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspCostInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPS32(void) { + VP8GetResidualCost = GetResidualCost_MIPS32; + VP8SetResidualCoeffs = SetResidualCoeffs_MIPS32; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/libraries/webp/src/dsp/cost_mips_dsp_r2.c b/libraries/webp/src/dsp/cost_mips_dsp_r2.c new file mode 100644 index 0000000000..51248de7a1 --- /dev/null +++ b/libraries/webp/src/dsp/cost_mips_dsp_r2.c @@ -0,0 +1,107 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/enc/cost_enc.h" + +static int GetResidualCost_MIPSdspR2(int ctx0, const VP8Residual* const res) { + int temp0, temp1; + int v_reg, ctx_reg; + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + const int16_t* res_coeffs = res->coeffs; + const int res_last = res->last; + const int const_max_level = MAX_VARIABLE_LEVEL; + const int const_2 = 2; + const uint16_t** p_costs = &costs[n][0]; + const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs); + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "subu %[temp1], %[res_last], %[n] \n\t" + "blez %[temp1], 2f \n\t" + " nop \n\t" + "1: \n\t" + "sll %[temp0], %[n], 1 \n\t" + "lhx %[v_reg], %[temp0](%[res_coeffs]) \n\t" + "addiu %[n], %[n], 1 \n\t" + "absq_s.w %[v_reg], %[v_reg] \n\t" + "sltiu %[temp0], %[v_reg], 2 \n\t" + "move %[ctx_reg], %[v_reg] \n\t" + "movz %[ctx_reg], %[const_2], %[temp0] \n\t" + "sll %[temp1], %[v_reg], 1 \n\t" + "lhx %[temp1], %[temp1](%[VP8LevelFixedCosts]) \n\t" + "slt %[temp0], %[v_reg], %[const_max_level] \n\t" + "movz %[v_reg], %[const_max_level], %[temp0] \n\t" + "addu %[cost], %[cost], %[temp1] \n\t" + "sll %[v_reg], %[v_reg], 1 \n\t" + "sll %[ctx_reg], %[ctx_reg], 2 \n\t" + "lhx %[temp0], %[v_reg](%[t]) \n\t" + "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t" + "addu %[t], %[p_costs], %[ctx_reg] \n\t" + "addu %[cost], %[cost], %[temp0] \n\t" + "bne %[n], %[res_last], 1b \n\t" + " lw %[t], 0(%[t]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg), + [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1) + : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level), + [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last), + [res_coeffs]"r"(res_coeffs), [inc_p_costs]"r"(inc_p_costs) + : "memory" + ); + + // Last coefficient is always non-zero + { + const int v = abs(res->coeffs[n]); + assert(v != 0); + cost += VP8LevelCost(t, v); + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = (v == 1) ? 1 : 2; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspCostInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPSdspR2(void) { + VP8GetResidualCost = GetResidualCost_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/cost_neon.c b/libraries/webp/src/dsp/cost_neon.c new file mode 100644 index 0000000000..6582669cb3 --- /dev/null +++ b/libraries/webp/src/dsp/cost_neon.c @@ -0,0 +1,122 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// ARM NEON version of cost functions + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include "src/dsp/neon.h" +#include "src/enc/cost_enc.h" + +static const uint8_t position[16] = { 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16 }; + +static void SetResidualCoeffs_NEON(const int16_t* const coeffs, + VP8Residual* const res) { + const int16x8_t minus_one = vdupq_n_s16(-1); + const int16x8_t coeffs_0 = vld1q_s16(coeffs); + const int16x8_t coeffs_1 = vld1q_s16(coeffs + 8); + const uint16x8_t eob_0 = vtstq_s16(coeffs_0, minus_one); + const uint16x8_t eob_1 = vtstq_s16(coeffs_1, minus_one); + const uint8x16_t eob = vcombine_u8(vqmovn_u16(eob_0), vqmovn_u16(eob_1)); + const uint8x16_t masked = vandq_u8(eob, vld1q_u8(position)); + +#if WEBP_AARCH64 + res->last = vmaxvq_u8(masked) - 1; +#else + const uint8x8_t eob_8x8 = vmax_u8(vget_low_u8(masked), vget_high_u8(masked)); + const uint16x8_t eob_16x8 = vmovl_u8(eob_8x8); + const uint16x4_t eob_16x4 = + vmax_u16(vget_low_u16(eob_16x8), vget_high_u16(eob_16x8)); + const uint32x4_t eob_32x4 = vmovl_u16(eob_16x4); + uint32x2_t eob_32x2 = + vmax_u32(vget_low_u32(eob_32x4), vget_high_u32(eob_32x4)); + eob_32x2 = vpmax_u32(eob_32x2, eob_32x2); + + vst1_lane_s32(&res->last, vreinterpret_s32_u32(eob_32x2), 0); + --res->last; +#endif // WEBP_AARCH64 + + res->coeffs = coeffs; +} + +static int GetResidualCost_NEON(int ctx0, const VP8Residual* const res) { + uint8_t levels[16], ctxs[16]; + uint16_t abs_levels[16]; + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + { // precompute clamped levels and contexts, packed to 8b. + const uint8x16_t kCst2 = vdupq_n_u8(2); + const uint8x16_t kCst67 = vdupq_n_u8(MAX_VARIABLE_LEVEL); + const int16x8_t c0 = vld1q_s16(res->coeffs); + const int16x8_t c1 = vld1q_s16(res->coeffs + 8); + const uint16x8_t E0 = vreinterpretq_u16_s16(vabsq_s16(c0)); + const uint16x8_t E1 = vreinterpretq_u16_s16(vabsq_s16(c1)); + const uint8x16_t F = vcombine_u8(vqmovn_u16(E0), vqmovn_u16(E1)); + const uint8x16_t G = vminq_u8(F, kCst2); // context = 0,1,2 + const uint8x16_t H = vminq_u8(F, kCst67); // clamp_level in [0..67] + + vst1q_u8(ctxs, G); + vst1q_u8(levels, H); + + vst1q_u16(abs_levels, E0); + vst1q_u16(abs_levels + 8, E1); + } + for (; n < res->last; ++n) { + const int ctx = ctxs[n]; + const int level = levels[n]; + const int flevel = abs_levels[n]; // full level + cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost() + t = costs[n + 1][ctx]; + } + // Last coefficient is always non-zero + { + const int level = levels[n]; + const int flevel = abs_levels[n]; + assert(flevel != 0); + cost += VP8LevelFixedCosts[flevel] + t[level]; + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = ctxs[n]; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspCostInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitNEON(void) { + VP8SetResidualCoeffs = SetResidualCoeffs_NEON; + VP8GetResidualCost = GetResidualCost_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8EncDspCostInitNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/cost_sse2.c b/libraries/webp/src/dsp/cost_sse2.c new file mode 100644 index 0000000000..487a079921 --- /dev/null +++ b/libraries/webp/src/dsp/cost_sse2.c @@ -0,0 +1,119 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of cost functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) +#include + +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ + +static void SetResidualCoeffs_SSE2(const int16_t* const coeffs, + VP8Residual* const res) { + const __m128i c0 = _mm_loadu_si128((const __m128i*)(coeffs + 0)); + const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8)); + // Use SSE2 to compare 16 values with a single instruction. + const __m128i zero = _mm_setzero_si128(); + const __m128i m0 = _mm_packs_epi16(c0, c1); + const __m128i m1 = _mm_cmpeq_epi8(m0, zero); + // Get the comparison results as a bitmask into 16bits. Negate the mask to get + // the position of entries that are not equal to zero. We don't need to mask + // out least significant bits according to res->first, since coeffs[0] is 0 + // if res->first > 0. + const uint32_t mask = 0x0000ffffu ^ (uint32_t)_mm_movemask_epi8(m1); + // The position of the most significant non-zero bit indicates the position of + // the last non-zero value. + assert(res->first == 0 || coeffs[0] == 0); + res->last = mask ? BitsLog2Floor(mask) : -1; + res->coeffs = coeffs; +} + +static int GetResidualCost_SSE2(int ctx0, const VP8Residual* const res) { + uint8_t levels[16], ctxs[16]; + uint16_t abs_levels[16]; + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + { // precompute clamped levels and contexts, packed to 8b. + const __m128i zero = _mm_setzero_si128(); + const __m128i kCst2 = _mm_set1_epi8(2); + const __m128i kCst67 = _mm_set1_epi8(MAX_VARIABLE_LEVEL); + const __m128i c0 = _mm_loadu_si128((const __m128i*)&res->coeffs[0]); + const __m128i c1 = _mm_loadu_si128((const __m128i*)&res->coeffs[8]); + const __m128i D0 = _mm_sub_epi16(zero, c0); + const __m128i D1 = _mm_sub_epi16(zero, c1); + const __m128i E0 = _mm_max_epi16(c0, D0); // abs(v), 16b + const __m128i E1 = _mm_max_epi16(c1, D1); + const __m128i F = _mm_packs_epi16(E0, E1); + const __m128i G = _mm_min_epu8(F, kCst2); // context = 0,1,2 + const __m128i H = _mm_min_epu8(F, kCst67); // clamp_level in [0..67] + + _mm_storeu_si128((__m128i*)&ctxs[0], G); + _mm_storeu_si128((__m128i*)&levels[0], H); + + _mm_storeu_si128((__m128i*)&abs_levels[0], E0); + _mm_storeu_si128((__m128i*)&abs_levels[8], E1); + } + for (; n < res->last; ++n) { + const int ctx = ctxs[n]; + const int level = levels[n]; + const int flevel = abs_levels[n]; // full level + cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost() + t = costs[n + 1][ctx]; + } + // Last coefficient is always non-zero + { + const int level = levels[n]; + const int flevel = abs_levels[n]; + assert(flevel != 0); + cost += VP8LevelFixedCosts[flevel] + t[level]; + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = ctxs[n]; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspCostInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitSSE2(void) { + VP8SetResidualCoeffs = SetResidualCoeffs_SSE2; + VP8GetResidualCost = GetResidualCost_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8EncDspCostInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/cpu.c b/libraries/webp/src/dsp/cpu.c new file mode 100644 index 0000000000..8ba8f68335 --- /dev/null +++ b/libraries/webp/src/dsp/cpu.c @@ -0,0 +1,247 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// CPU detection +// +// Author: Christian Duvivier (cduvivier@google.com) + +#include "src/dsp/cpu.h" + +#if defined(WEBP_HAVE_NEON_RTCD) +#include +#include +#endif + +#if defined(WEBP_ANDROID_NEON) +#include +#endif + +//------------------------------------------------------------------------------ +// SSE2 detection. +// + +// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC. +#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__) +static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { + __asm__ volatile ( + "mov %%ebx, %%edi\n" + "cpuid\n" + "xchg %%edi, %%ebx\n" + : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) + : "a"(info_type), "c"(0)); +} +#elif defined(__i386__) || defined(__x86_64__) +static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { + __asm__ volatile ( + "cpuid\n" + : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) + : "a"(info_type), "c"(0)); +} +#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) + +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 +#include +#define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0 +#define WEBP_HAVE_MSC_CPUID +#elif _MSC_VER > 1310 +#include +#define GetCPUInfo __cpuid +#define WEBP_HAVE_MSC_CPUID +#endif + +#endif + +// NaCl has no support for xgetbv or the raw opcode. +#if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__)) +static WEBP_INLINE uint64_t xgetbv(void) { + const uint32_t ecx = 0; + uint32_t eax, edx; + // Use the raw opcode for xgetbv for compatibility with older toolchains. + __asm__ volatile ( + ".byte 0x0f, 0x01, 0xd0\n" + : "=a"(eax), "=d"(edx) : "c" (ecx)); + return ((uint64_t)edx << 32) | eax; +} +#elif (defined(_M_X64) || defined(_M_IX86)) && \ + defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 +#include +#define xgetbv() _xgetbv(0) +#elif defined(_MSC_VER) && defined(_M_IX86) +static WEBP_INLINE uint64_t xgetbv(void) { + uint32_t eax_, edx_; + __asm { + xor ecx, ecx // ecx = 0 + // Use the raw opcode for xgetbv for compatibility with older toolchains. + __asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0 + mov eax_, eax + mov edx_, edx + } + return ((uint64_t)edx_ << 32) | eax_; +} +#else +#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains. +#endif + +#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_HAVE_MSC_CPUID) + +// helper function for run-time detection of slow SSSE3 platforms +static int CheckSlowModel(int info) { + // Table listing display models with longer latencies for the bsr instruction + // (ie 2 cycles vs 10/16 cycles) and some SSSE3 instructions like pshufb. + // Refer to Intel 64 and IA-32 Architectures Optimization Reference Manual. + static const uint8_t kSlowModels[] = { + 0x37, 0x4a, 0x4d, // Silvermont Microarchitecture + 0x1c, 0x26, 0x27 // Atom Microarchitecture + }; + const uint32_t model = ((info & 0xf0000) >> 12) | ((info >> 4) & 0xf); + const uint32_t family = (info >> 8) & 0xf; + if (family == 0x06) { + size_t i; + for (i = 0; i < sizeof(kSlowModels) / sizeof(kSlowModels[0]); ++i) { + if (model == kSlowModels[i]) return 1; + } + } + return 0; +} + +static int x86CPUInfo(CPUFeature feature) { + int max_cpuid_value; + int cpu_info[4]; + int is_intel = 0; + + // get the highest feature value cpuid supports + GetCPUInfo(cpu_info, 0); + max_cpuid_value = cpu_info[0]; + if (max_cpuid_value < 1) { + return 0; + } else { + const int VENDOR_ID_INTEL_EBX = 0x756e6547; // uneG + const int VENDOR_ID_INTEL_EDX = 0x49656e69; // Ieni + const int VENDOR_ID_INTEL_ECX = 0x6c65746e; // letn + is_intel = (cpu_info[1] == VENDOR_ID_INTEL_EBX && + cpu_info[2] == VENDOR_ID_INTEL_ECX && + cpu_info[3] == VENDOR_ID_INTEL_EDX); // genuine Intel? + } + + GetCPUInfo(cpu_info, 1); + if (feature == kSSE2) { + return !!(cpu_info[3] & (1 << 26)); + } + if (feature == kSSE3) { + return !!(cpu_info[2] & (1 << 0)); + } + if (feature == kSlowSSSE3) { + if (is_intel && (cpu_info[2] & (1 << 9))) { // SSSE3? + return CheckSlowModel(cpu_info[0]); + } + return 0; + } + + if (feature == kSSE4_1) { + return !!(cpu_info[2] & (1 << 19)); + } + if (feature == kAVX) { + // bits 27 (OSXSAVE) & 28 (256-bit AVX) + if ((cpu_info[2] & 0x18000000) == 0x18000000) { + // XMM state and YMM state enabled by the OS. + return (xgetbv() & 0x6) == 0x6; + } + } + if (feature == kAVX2) { + if (x86CPUInfo(kAVX) && max_cpuid_value >= 7) { + GetCPUInfo(cpu_info, 7); + return !!(cpu_info[1] & (1 << 5)); + } + } + return 0; +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = x86CPUInfo; +#elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test. +static int AndroidCPUInfo(CPUFeature feature) { + const AndroidCpuFamily cpu_family = android_getCpuFamily(); + const uint64_t cpu_features = android_getCpuFeatures(); + if (feature == kNEON) { + return cpu_family == ANDROID_CPU_FAMILY_ARM && + (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON) != 0; + } + return 0; +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo; +#elif defined(EMSCRIPTEN) // also needs to be before generic NEON test +// Use compile flags as an indicator of SIMD support instead of a runtime check. +static int wasmCPUInfo(CPUFeature feature) { + switch (feature) { +#ifdef WEBP_HAVE_SSE2 + case kSSE2: + return 1; +#endif +#ifdef WEBP_HAVE_SSE41 + case kSSE3: + case kSlowSSSE3: + case kSSE4_1: + return 1; +#endif +#ifdef WEBP_HAVE_NEON + case kNEON: + return 1; +#endif + default: + break; + } + return 0; +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = wasmCPUInfo; +#elif defined(WEBP_HAVE_NEON) +// In most cases this function doesn't check for NEON support (it's assumed by +// the configuration), but enables turning off NEON at runtime, for testing +// purposes, by setting VP8GetCPUInfo = NULL. +static int armCPUInfo(CPUFeature feature) { + if (feature != kNEON) return 0; +#if defined(__linux__) && defined(WEBP_HAVE_NEON_RTCD) + { + int has_neon = 0; + char line[200]; + FILE* const cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo == NULL) return 0; + while (fgets(line, sizeof(line), cpuinfo)) { + if (!strncmp(line, "Features", 8)) { + if (strstr(line, " neon ") != NULL) { + has_neon = 1; + break; + } + } + } + fclose(cpuinfo); + return has_neon; + } +#else + return 1; +#endif +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = armCPUInfo; +#elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2) || \ + defined(WEBP_USE_MSA) +static int mipsCPUInfo(CPUFeature feature) { + if ((feature == kMIPS32) || (feature == kMIPSdspR2) || (feature == kMSA)) { + return 1; + } else { + return 0; + } + +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo; +#else +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = NULL; +#endif diff --git a/libraries/webp/src/dsp/cpu.h b/libraries/webp/src/dsp/cpu.h new file mode 100644 index 0000000000..9d4d19f32f --- /dev/null +++ b/libraries/webp/src/dsp/cpu.h @@ -0,0 +1,266 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// CPU detection functions and macros. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DSP_CPU_H_ +#define WEBP_DSP_CPU_H_ + +#include + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include "include/webp/types.h" + +#if defined(__GNUC__) +#define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) +#define LOCAL_GCC_PREREQ(maj, min) (LOCAL_GCC_VERSION >= (((maj) << 8) | (min))) +#else +#define LOCAL_GCC_VERSION 0 +#define LOCAL_GCC_PREREQ(maj, min) 0 +#endif + +#if defined(__clang__) +#define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__) +#define LOCAL_CLANG_PREREQ(maj, min) \ + (LOCAL_CLANG_VERSION >= (((maj) << 8) | (min))) +#else +#define LOCAL_CLANG_VERSION 0 +#define LOCAL_CLANG_PREREQ(maj, min) 0 +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +//------------------------------------------------------------------------------ +// x86 defines. + +#if !defined(HAVE_CONFIG_H) +#if defined(_MSC_VER) && _MSC_VER > 1310 && \ + (defined(_M_X64) || defined(_M_IX86)) +#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1500 && \ + (defined(_M_X64) || defined(_M_IX86)) +#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets +#endif +#endif + +// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp +// files without intrinsics, allowing the corresponding Init() to be called. +// Files containing intrinsics will need to be built targeting the instruction +// set so should succeed on one of the earlier tests. +#if (defined(__SSE2__) || defined(WEBP_MSC_SSE2)) && \ + (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE2)) +#define WEBP_USE_SSE2 +#endif + +#if defined(WEBP_USE_SSE2) && !defined(WEBP_HAVE_SSE2) +#define WEBP_HAVE_SSE2 +#endif + +#if (defined(__SSE4_1__) || defined(WEBP_MSC_SSE41)) && \ + (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE41)) +#define WEBP_USE_SSE41 +#endif + +#if defined(WEBP_USE_SSE41) && !defined(WEBP_HAVE_SSE41) +#define WEBP_HAVE_SSE41 +#endif + +#undef WEBP_MSC_SSE41 +#undef WEBP_MSC_SSE2 + +//------------------------------------------------------------------------------ +// Arm defines. + +// The intrinsics currently cause compiler errors with arm-nacl-gcc and the +// inline assembly would need to be modified for use with Native Client. +#if ((defined(__ARM_NEON__) || defined(__aarch64__)) && \ + (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_NEON))) && \ + !defined(__native_client__) +#define WEBP_USE_NEON +#endif + +#if !defined(WEBP_USE_NEON) && defined(__ANDROID__) && \ + defined(__ARM_ARCH_7A__) && defined(HAVE_CPU_FEATURES_H) +#define WEBP_ANDROID_NEON // Android targets that may have NEON +#define WEBP_USE_NEON +#endif + +// Note: ARM64 is supported in Visual Studio 2017, but requires the direct +// inclusion of arm64_neon.h; Visual Studio 2019 includes this file in +// arm_neon.h. Compile errors were seen with Visual Studio 2019 16.4 with +// vtbl4_u8(); a fix was made in 16.6. +#if defined(_MSC_VER) && \ + ((_MSC_VER >= 1700 && defined(_M_ARM)) || \ + (_MSC_VER >= 1926 && (defined(_M_ARM64) || defined(_M_ARM64EC)))) +#define WEBP_USE_NEON +#define WEBP_USE_INTRINSICS +#endif + +#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#define WEBP_AARCH64 1 +#else +#define WEBP_AARCH64 0 +#endif + +#if defined(WEBP_USE_NEON) && !defined(WEBP_HAVE_NEON) +#define WEBP_HAVE_NEON +#endif + +//------------------------------------------------------------------------------ +// MIPS defines. + +#if defined(__mips__) && !defined(__mips64) && defined(__mips_isa_rev) && \ + (__mips_isa_rev >= 1) && (__mips_isa_rev < 6) +#define WEBP_USE_MIPS32 +#if (__mips_isa_rev >= 2) +#define WEBP_USE_MIPS32_R2 +#if defined(__mips_dspr2) || (defined(__mips_dsp_rev) && __mips_dsp_rev >= 2) +#define WEBP_USE_MIPS_DSP_R2 +#endif +#endif +#endif + +#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5) +#define WEBP_USE_MSA +#endif + +//------------------------------------------------------------------------------ + +#ifndef WEBP_DSP_OMIT_C_CODE +#define WEBP_DSP_OMIT_C_CODE 1 +#endif + +#if defined(WEBP_USE_NEON) && WEBP_DSP_OMIT_C_CODE +#define WEBP_NEON_OMIT_C_CODE 1 +#else +#define WEBP_NEON_OMIT_C_CODE 0 +#endif + +#if !(LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 8) || WEBP_AARCH64) +#define WEBP_NEON_WORK_AROUND_GCC 1 +#else +#define WEBP_NEON_WORK_AROUND_GCC 0 +#endif + +//------------------------------------------------------------------------------ + +// This macro prevents thread_sanitizer from reporting known concurrent writes. +#define WEBP_TSAN_IGNORE_FUNCTION +#if defined(__has_feature) +#if __has_feature(thread_sanitizer) +#undef WEBP_TSAN_IGNORE_FUNCTION +#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread)) +#endif +#endif + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define WEBP_MSAN +#endif +#endif + +#if defined(WEBP_USE_THREAD) && !defined(_WIN32) +#include // NOLINT + +#define WEBP_DSP_INIT(func) \ + do { \ + static volatile VP8CPUInfo func##_last_cpuinfo_used = \ + (VP8CPUInfo)&func##_last_cpuinfo_used; \ + static pthread_mutex_t func##_lock = PTHREAD_MUTEX_INITIALIZER; \ + if (pthread_mutex_lock(&func##_lock)) break; \ + if (func##_last_cpuinfo_used != VP8GetCPUInfo) func(); \ + func##_last_cpuinfo_used = VP8GetCPUInfo; \ + (void)pthread_mutex_unlock(&func##_lock); \ + } while (0) +#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32)) +#define WEBP_DSP_INIT(func) \ + do { \ + static volatile VP8CPUInfo func##_last_cpuinfo_used = \ + (VP8CPUInfo)&func##_last_cpuinfo_used; \ + if (func##_last_cpuinfo_used == VP8GetCPUInfo) break; \ + func(); \ + func##_last_cpuinfo_used = VP8GetCPUInfo; \ + } while (0) +#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32) + +// Defines an Init + helper function that control multiple initialization of +// function pointers / tables. +/* Usage: + WEBP_DSP_INIT_FUNC(InitFunc) { + ...function body + } +*/ +#define WEBP_DSP_INIT_FUNC(name) \ + static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void); \ + WEBP_TSAN_IGNORE_FUNCTION void name(void) { WEBP_DSP_INIT(name##_body); } \ + static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void) + +#define WEBP_UBSAN_IGNORE_UNDEF +#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(no_sanitize) +// This macro prevents the undefined behavior sanitizer from reporting +// failures. This is only meant to silence unaligned loads on platforms that +// are known to support them. +#undef WEBP_UBSAN_IGNORE_UNDEF +#define WEBP_UBSAN_IGNORE_UNDEF __attribute__((no_sanitize("undefined"))) + +// This macro prevents the undefined behavior sanitizer from reporting +// failures related to unsigned integer overflows. This is only meant to +// silence cases where this well defined behavior is expected. +#undef WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW +#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW \ + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif +#endif + +// If 'ptr' is NULL, returns NULL. Otherwise returns 'ptr + off'. +// Prevents undefined behavior sanitizer nullptr-with-nonzero-offset warning. +#if !defined(WEBP_OFFSET_PTR) +#define WEBP_OFFSET_PTR(ptr, off) (((ptr) == NULL) ? NULL : ((ptr) + (off))) +#endif + +// Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility) +#if !defined(WEBP_SWAP_16BIT_CSP) +#define WEBP_SWAP_16BIT_CSP 0 +#endif + +// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) +#if !defined(WORDS_BIGENDIAN) && \ + (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \ + (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) +#define WORDS_BIGENDIAN +#endif + +typedef enum { + kSSE2, + kSSE3, + kSlowSSSE3, // special feature for slow SSSE3 architectures + kSSE4_1, + kAVX, + kAVX2, + kNEON, + kMIPS32, + kMIPSdspR2, + kMSA +} CPUFeature; + +// returns true if the CPU supports the feature. +typedef int (*VP8CPUInfo)(CPUFeature feature); + +#endif // WEBP_DSP_CPU_H_ diff --git a/libraries/webp/src/dsp/dec.c b/libraries/webp/src/dsp/dec.c new file mode 100644 index 0000000000..451d649d58 --- /dev/null +++ b/libraries/webp/src/dsp/dec.c @@ -0,0 +1,887 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical decoding functions, default plain-C implementations. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dsp/dsp.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ + +static WEBP_INLINE uint8_t clip_8b(int v) { + return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; +} + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +#define STORE(x, y, v) \ + dst[(x) + (y) * BPS] = clip_8b(dst[(x) + (y) * BPS] + ((v) >> 3)) + +#define STORE2(y, dc, d, c) do { \ + const int DC = (dc); \ + STORE(0, y, DC + (d)); \ + STORE(1, y, DC + (c)); \ + STORE(2, y, DC - (c)); \ + STORE(3, y, DC - (d)); \ +} while (0) + +#if !WEBP_NEON_OMIT_C_CODE +static void TransformOne_C(const int16_t* in, uint8_t* dst) { + int C[4 * 4], *tmp; + int i; + tmp = C; + for (i = 0; i < 4; ++i) { // vertical pass + const int a = in[0] + in[8]; // [-4096, 4094] + const int b = in[0] - in[8]; // [-4095, 4095] + const int c = WEBP_TRANSFORM_AC3_MUL2(in[4]) - + WEBP_TRANSFORM_AC3_MUL1(in[12]); // [-3783, 3783] + const int d = WEBP_TRANSFORM_AC3_MUL1(in[4]) + + WEBP_TRANSFORM_AC3_MUL2(in[12]); // [-3785, 3781] + tmp[0] = a + d; // [-7881, 7875] + tmp[1] = b + c; // [-7878, 7878] + tmp[2] = b - c; // [-7878, 7878] + tmp[3] = a - d; // [-7877, 7879] + tmp += 4; + in++; + } + // Each pass is expanding the dynamic range by ~3.85 (upper bound). + // The exact value is (2. + (20091 + 35468) / 65536). + // After the second pass, maximum interval is [-3794, 3794], assuming + // an input in [-2048, 2047] interval. We then need to add a dst value + // in the [0, 255] range. + // In the worst case scenario, the input to clip_8b() can be as large as + // [-60713, 60968]. + tmp = C; + for (i = 0; i < 4; ++i) { // horizontal pass + const int dc = tmp[0] + 4; + const int a = dc + tmp[8]; + const int b = dc - tmp[8]; + const int c = + WEBP_TRANSFORM_AC3_MUL2(tmp[4]) - WEBP_TRANSFORM_AC3_MUL1(tmp[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(tmp[4]) + WEBP_TRANSFORM_AC3_MUL2(tmp[12]); + STORE(0, 0, a + d); + STORE(1, 0, b + c); + STORE(2, 0, b - c); + STORE(3, 0, a - d); + tmp++; + dst += BPS; + } +} + +// Simplified transform when only in[0], in[1] and in[4] are non-zero +static void TransformAC3_C(const int16_t* in, uint8_t* dst) { + const int a = in[0] + 4; + const int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); + STORE2(0, a + d4, d1, c1); + STORE2(1, a + c4, d1, c1); + STORE2(2, a - c4, d1, c1); + STORE2(3, a - d4, d1, c1); +} +#undef STORE2 + +static void TransformTwo_C(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne_C(in, dst); + if (do_two) { + TransformOne_C(in + 16, dst + 4); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void TransformUV_C(const int16_t* in, uint8_t* dst) { + VP8Transform(in + 0 * 16, dst, 1); + VP8Transform(in + 2 * 16, dst + 4 * BPS, 1); +} + +#if !WEBP_NEON_OMIT_C_CODE +static void TransformDC_C(const int16_t* in, uint8_t* dst) { + const int DC = in[0] + 4; + int i, j; + for (j = 0; j < 4; ++j) { + for (i = 0; i < 4; ++i) { + STORE(i, j, DC); + } + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void TransformDCUV_C(const int16_t* in, uint8_t* dst) { + if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst); + if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4); + if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS); + if (in[3 * 16]) VP8TransformDC(in + 3 * 16, dst + 4 * BPS + 4); +} + +#undef STORE + +//------------------------------------------------------------------------------ +// Paragraph 14.3 + +#if !WEBP_NEON_OMIT_C_CODE +static void TransformWHT_C(const int16_t* in, int16_t* out) { + int tmp[16]; + int i; + for (i = 0; i < 4; ++i) { + const int a0 = in[0 + i] + in[12 + i]; + const int a1 = in[4 + i] + in[ 8 + i]; + const int a2 = in[4 + i] - in[ 8 + i]; + const int a3 = in[0 + i] - in[12 + i]; + tmp[0 + i] = a0 + a1; + tmp[8 + i] = a0 - a1; + tmp[4 + i] = a3 + a2; + tmp[12 + i] = a3 - a2; + } + for (i = 0; i < 4; ++i) { + const int dc = tmp[0 + i * 4] + 3; // w/ rounder + const int a0 = dc + tmp[3 + i * 4]; + const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4]; + const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4]; + const int a3 = dc - tmp[3 + i * 4]; + out[ 0] = (a0 + a1) >> 3; + out[16] = (a3 + a2) >> 3; + out[32] = (a0 - a1) >> 3; + out[48] = (a3 - a2) >> 3; + out += 64; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +void (*VP8TransformWHT)(const int16_t* in, int16_t* out); + +//------------------------------------------------------------------------------ +// Intra predictions + +#define DST(x, y) dst[(x) + (y) * BPS] + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { + const uint8_t* top = dst - BPS; + const uint8_t* const clip0 = VP8kclip1 - top[-1]; + int y; + for (y = 0; y < size; ++y) { + const uint8_t* const clip = clip0 + dst[-1]; + int x; + for (x = 0; x < size; ++x) { + dst[x] = clip[top[x]]; + } + dst += BPS; + } +} +static void TM4_C(uint8_t* dst) { TrueMotion(dst, 4); } +static void TM8uv_C(uint8_t* dst) { TrueMotion(dst, 8); } +static void TM16_C(uint8_t* dst) { TrueMotion(dst, 16); } + +//------------------------------------------------------------------------------ +// 16x16 + +static void VE16_C(uint8_t* dst) { // vertical + int j; + for (j = 0; j < 16; ++j) { + memcpy(dst + j * BPS, dst - BPS, 16); + } +} + +static void HE16_C(uint8_t* dst) { // horizontal + int j; + for (j = 16; j > 0; --j) { + memset(dst, dst[-1], 16); + dst += BPS; + } +} + +static WEBP_INLINE void Put16(int v, uint8_t* dst) { + int j; + for (j = 0; j < 16; ++j) { + memset(dst + j * BPS, v, 16); + } +} + +static void DC16_C(uint8_t* dst) { // DC + int DC = 16; + int j; + for (j = 0; j < 16; ++j) { + DC += dst[-1 + j * BPS] + dst[j - BPS]; + } + Put16(DC >> 5, dst); +} + +static void DC16NoTop_C(uint8_t* dst) { // DC with top samples not available + int DC = 8; + int j; + for (j = 0; j < 16; ++j) { + DC += dst[-1 + j * BPS]; + } + Put16(DC >> 4, dst); +} + +static void DC16NoLeft_C(uint8_t* dst) { // DC with left samples not available + int DC = 8; + int i; + for (i = 0; i < 16; ++i) { + DC += dst[i - BPS]; + } + Put16(DC >> 4, dst); +} + +static void DC16NoTopLeft_C(uint8_t* dst) { // DC with no top and left samples + Put16(0x80, dst); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES]; + +//------------------------------------------------------------------------------ +// 4x4 + +#define AVG3(a, b, c) ((uint8_t)(((a) + 2 * (b) + (c) + 2) >> 2)) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +#if !WEBP_NEON_OMIT_C_CODE +static void VE4_C(uint8_t* dst) { // vertical + const uint8_t* top = dst - BPS; + const uint8_t vals[4] = { + AVG3(top[-1], top[0], top[1]), + AVG3(top[ 0], top[1], top[2]), + AVG3(top[ 1], top[2], top[3]), + AVG3(top[ 2], top[3], top[4]) + }; + int i; + for (i = 0; i < 4; ++i) { + memcpy(dst + i * BPS, vals, sizeof(vals)); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void HE4_C(uint8_t* dst) { // horizontal + const int A = dst[-1 - BPS]; + const int B = dst[-1]; + const int C = dst[-1 + BPS]; + const int D = dst[-1 + 2 * BPS]; + const int E = dst[-1 + 3 * BPS]; + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(A, B, C)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(B, C, D)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(C, D, E)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(D, E, E)); +} + +#if !WEBP_NEON_OMIT_C_CODE +static void DC4_C(uint8_t* dst) { // DC + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS]; + dc >>= 3; + for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4); +} + +static void RD4_C(uint8_t* dst) { // Down-right + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int L = dst[-1 + 3 * BPS]; + const int X = dst[-1 - BPS]; + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + const int D = dst[3 - BPS]; + DST(0, 3) = AVG3(J, K, L); + DST(1, 3) = DST(0, 2) = AVG3(I, J, K); + DST(2, 3) = DST(1, 2) = DST(0, 1) = AVG3(X, I, J); + DST(3, 3) = DST(2, 2) = DST(1, 1) = DST(0, 0) = AVG3(A, X, I); + DST(3, 2) = DST(2, 1) = DST(1, 0) = AVG3(B, A, X); + DST(3, 1) = DST(2, 0) = AVG3(C, B, A); + DST(3, 0) = AVG3(D, C, B); +} + +static void LD4_C(uint8_t* dst) { // Down-Left + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + const int D = dst[3 - BPS]; + const int E = dst[4 - BPS]; + const int F = dst[5 - BPS]; + const int G = dst[6 - BPS]; + const int H = dst[7 - BPS]; + DST(0, 0) = AVG3(A, B, C); + DST(1, 0) = DST(0, 1) = AVG3(B, C, D); + DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E); + DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F); + DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G); + DST(3, 2) = DST(2, 3) = AVG3(F, G, H); + DST(3, 3) = AVG3(G, H, H); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void VR4_C(uint8_t* dst) { // Vertical-Right + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int X = dst[-1 - BPS]; + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + const int D = dst[3 - BPS]; + DST(0, 0) = DST(1, 2) = AVG2(X, A); + DST(1, 0) = DST(2, 2) = AVG2(A, B); + DST(2, 0) = DST(3, 2) = AVG2(B, C); + DST(3, 0) = AVG2(C, D); + + DST(0, 3) = AVG3(K, J, I); + DST(0, 2) = AVG3(J, I, X); + DST(0, 1) = DST(1, 3) = AVG3(I, X, A); + DST(1, 1) = DST(2, 3) = AVG3(X, A, B); + DST(2, 1) = DST(3, 3) = AVG3(A, B, C); + DST(3, 1) = AVG3(B, C, D); +} + +static void VL4_C(uint8_t* dst) { // Vertical-Left + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + const int D = dst[3 - BPS]; + const int E = dst[4 - BPS]; + const int F = dst[5 - BPS]; + const int G = dst[6 - BPS]; + const int H = dst[7 - BPS]; + DST(0, 0) = AVG2(A, B); + DST(1, 0) = DST(0, 2) = AVG2(B, C); + DST(2, 0) = DST(1, 2) = AVG2(C, D); + DST(3, 0) = DST(2, 2) = AVG2(D, E); + + DST(0, 1) = AVG3(A, B, C); + DST(1, 1) = DST(0, 3) = AVG3(B, C, D); + DST(2, 1) = DST(1, 3) = AVG3(C, D, E); + DST(3, 1) = DST(2, 3) = AVG3(D, E, F); + DST(3, 2) = AVG3(E, F, G); + DST(3, 3) = AVG3(F, G, H); +} + +static void HU4_C(uint8_t* dst) { // Horizontal-Up + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int L = dst[-1 + 3 * BPS]; + DST(0, 0) = AVG2(I, J); + DST(2, 0) = DST(0, 1) = AVG2(J, K); + DST(2, 1) = DST(0, 2) = AVG2(K, L); + DST(1, 0) = AVG3(I, J, K); + DST(3, 0) = DST(1, 1) = AVG3(J, K, L); + DST(3, 1) = DST(1, 2) = AVG3(K, L, L); + DST(3, 2) = DST(2, 2) = + DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; +} + +static void HD4_C(uint8_t* dst) { // Horizontal-Down + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int L = dst[-1 + 3 * BPS]; + const int X = dst[-1 - BPS]; + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + + DST(0, 0) = DST(2, 1) = AVG2(I, X); + DST(0, 1) = DST(2, 2) = AVG2(J, I); + DST(0, 2) = DST(2, 3) = AVG2(K, J); + DST(0, 3) = AVG2(L, K); + + DST(3, 0) = AVG3(A, B, C); + DST(2, 0) = AVG3(X, A, B); + DST(1, 0) = DST(3, 1) = AVG3(I, X, A); + DST(1, 1) = DST(3, 2) = AVG3(J, I, X); + DST(1, 2) = DST(3, 3) = AVG3(K, J, I); + DST(1, 3) = AVG3(L, K, J); +} + +#undef DST +#undef AVG3 +#undef AVG2 + +VP8PredFunc VP8PredLuma4[NUM_BMODES]; + +//------------------------------------------------------------------------------ +// Chroma + +#if !WEBP_NEON_OMIT_C_CODE +static void VE8uv_C(uint8_t* dst) { // vertical + int j; + for (j = 0; j < 8; ++j) { + memcpy(dst + j * BPS, dst - BPS, 8); + } +} + +static void HE8uv_C(uint8_t* dst) { // horizontal + int j; + for (j = 0; j < 8; ++j) { + memset(dst, dst[-1], 8); + dst += BPS; + } +} + +// helper for chroma-DC predictions +static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) { + int j; + for (j = 0; j < 8; ++j) { + memset(dst + j * BPS, value, 8); + } +} + +static void DC8uv_C(uint8_t* dst) { // DC + int dc0 = 8; + int i; + for (i = 0; i < 8; ++i) { + dc0 += dst[i - BPS] + dst[-1 + i * BPS]; + } + Put8x8uv(dc0 >> 4, dst); +} + +static void DC8uvNoLeft_C(uint8_t* dst) { // DC with no left samples + int dc0 = 4; + int i; + for (i = 0; i < 8; ++i) { + dc0 += dst[i - BPS]; + } + Put8x8uv(dc0 >> 3, dst); +} + +static void DC8uvNoTop_C(uint8_t* dst) { // DC with no top samples + int dc0 = 4; + int i; + for (i = 0; i < 8; ++i) { + dc0 += dst[-1 + i * BPS]; + } + Put8x8uv(dc0 >> 3, dst); +} + +static void DC8uvNoTopLeft_C(uint8_t* dst) { // DC with nothing + Put8x8uv(0x80, dst); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES]; + +//------------------------------------------------------------------------------ +// Edge filtering functions + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +// 4 pixels in, 2 pixels out +static WEBP_INLINE void DoFilter2_C(uint8_t* p, int step) { + const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; + const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892] + const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15] + const int a2 = VP8ksclip2[(a + 3) >> 3]; + p[-step] = VP8kclip1[p0 + a2]; + p[ 0] = VP8kclip1[q0 - a1]; +} + +// 4 pixels in, 4 pixels out +static WEBP_INLINE void DoFilter4_C(uint8_t* p, int step) { + const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; + const int a = 3 * (q0 - p0); + const int a1 = VP8ksclip2[(a + 4) >> 3]; + const int a2 = VP8ksclip2[(a + 3) >> 3]; + const int a3 = (a1 + 1) >> 1; + p[-2*step] = VP8kclip1[p1 + a3]; + p[- step] = VP8kclip1[p0 + a2]; + p[ 0] = VP8kclip1[q0 - a1]; + p[ step] = VP8kclip1[q1 - a3]; +} + +// 6 pixels in, 6 pixels out +static WEBP_INLINE void DoFilter6_C(uint8_t* p, int step) { + const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step]; + const int q0 = p[0], q1 = p[step], q2 = p[2*step]; + const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; + // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] + const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 + const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 + const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 + p[-3*step] = VP8kclip1[p2 + a3]; + p[-2*step] = VP8kclip1[p1 + a2]; + p[- step] = VP8kclip1[p0 + a1]; + p[ 0] = VP8kclip1[q0 - a1]; + p[ step] = VP8kclip1[q1 - a2]; + p[ 2*step] = VP8kclip1[q2 - a3]; +} + +static WEBP_INLINE int Hev(const uint8_t* p, int step, int thresh) { + const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE int NeedsFilter_C(const uint8_t* p, int step, int t) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) <= t); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static WEBP_INLINE int NeedsFilter2_C(const uint8_t* p, + int step, int t, int it) { + const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step]; + const int p0 = p[-step], q0 = p[0]; + const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; + if ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) > t) return 0; + return VP8kabs0[p3 - p2] <= it && VP8kabs0[p2 - p1] <= it && + VP8kabs0[p1 - p0] <= it && VP8kabs0[q3 - q2] <= it && + VP8kabs0[q2 - q1] <= it && VP8kabs0[q1 - q0] <= it; +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +#if !WEBP_NEON_OMIT_C_CODE +static void SimpleVFilter16_C(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + for (i = 0; i < 16; ++i) { + if (NeedsFilter_C(p + i, stride, thresh2)) { + DoFilter2_C(p + i, stride); + } + } +} + +static void SimpleHFilter16_C(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + for (i = 0; i < 16; ++i) { + if (NeedsFilter_C(p + i * stride, 1, thresh2)) { + DoFilter2_C(p + i * stride, 1); + } + } +} + +static void SimpleVFilter16i_C(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + SimpleVFilter16_C(p, stride, thresh); + } +} + +static void SimpleHFilter16i_C(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + SimpleHFilter16_C(p, stride, thresh); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// Complex In-loop filtering (Paragraph 15.3) + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static WEBP_INLINE void FilterLoop26_C(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, + int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + while (size-- > 0) { + if (NeedsFilter2_C(p, hstride, thresh2, ithresh)) { + if (Hev(p, hstride, hev_thresh)) { + DoFilter2_C(p, hstride); + } else { + DoFilter6_C(p, hstride); + } + } + p += vstride; + } +} + +static WEBP_INLINE void FilterLoop24_C(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, + int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + while (size-- > 0) { + if (NeedsFilter2_C(p, hstride, thresh2, ithresh)) { + if (Hev(p, hstride, hev_thresh)) { + DoFilter2_C(p, hstride); + } else { + DoFilter4_C(p, hstride); + } + } + p += vstride; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +#if !WEBP_NEON_OMIT_C_CODE +// on macroblock edges +static void VFilter16_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(p, stride, 1, 16, thresh, ithresh, hev_thresh); +} + +static void HFilter16_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(p, 1, stride, 16, thresh, ithresh, hev_thresh); +} + +// on three inner edges +static void VFilter16i_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + FilterLoop24_C(p, stride, 1, 16, thresh, ithresh, hev_thresh); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter16i_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + FilterLoop24_C(p, 1, stride, 16, thresh, ithresh, hev_thresh); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +#if !WEBP_NEON_OMIT_C_CODE +// 8-pixels wide variant, for chroma filtering +static void VFilter8_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(u, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop26_C(v, stride, 1, 8, thresh, ithresh, hev_thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter8_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(u, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop26_C(v, 1, stride, 8, thresh, ithresh, hev_thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +#if !WEBP_NEON_OMIT_C_CODE +static void VFilter8i_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24_C(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop24_C(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter8i_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24_C(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop24_C(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +//------------------------------------------------------------------------------ + +static void DitherCombine8x8_C(const uint8_t* dither, uint8_t* dst, + int dst_stride) { + int i, j; + for (j = 0; j < 8; ++j) { + for (i = 0; i < 8; ++i) { + const int delta0 = dither[i] - VP8_DITHER_AMP_CENTER; + const int delta1 = + (delta0 + VP8_DITHER_DESCALE_ROUNDER) >> VP8_DITHER_DESCALE; + dst[i] = clip_8b((int)dst[i] + delta1); + } + dst += dst_stride; + dither += 8; + } +} + +//------------------------------------------------------------------------------ + +VP8DecIdct2 VP8Transform; +VP8DecIdct VP8TransformAC3; +VP8DecIdct VP8TransformUV; +VP8DecIdct VP8TransformDC; +VP8DecIdct VP8TransformDCUV; + +VP8LumaFilterFunc VP8VFilter16; +VP8LumaFilterFunc VP8HFilter16; +VP8ChromaFilterFunc VP8VFilter8; +VP8ChromaFilterFunc VP8HFilter8; +VP8LumaFilterFunc VP8VFilter16i; +VP8LumaFilterFunc VP8HFilter16i; +VP8ChromaFilterFunc VP8VFilter8i; +VP8ChromaFilterFunc VP8HFilter8i; +VP8SimpleFilterFunc VP8SimpleVFilter16; +VP8SimpleFilterFunc VP8SimpleHFilter16; +VP8SimpleFilterFunc VP8SimpleVFilter16i; +VP8SimpleFilterFunc VP8SimpleHFilter16i; + +void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst, + int dst_stride); + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8DspInitSSE2(void); +extern void VP8DspInitSSE41(void); +extern void VP8DspInitNEON(void); +extern void VP8DspInitMIPS32(void); +extern void VP8DspInitMIPSdspR2(void); +extern void VP8DspInitMSA(void); + +WEBP_DSP_INIT_FUNC(VP8DspInit) { + VP8InitClipTables(); + +#if !WEBP_NEON_OMIT_C_CODE + VP8TransformWHT = TransformWHT_C; + VP8Transform = TransformTwo_C; + VP8TransformDC = TransformDC_C; + VP8TransformAC3 = TransformAC3_C; +#endif + VP8TransformUV = TransformUV_C; + VP8TransformDCUV = TransformDCUV_C; + +#if !WEBP_NEON_OMIT_C_CODE + VP8VFilter16 = VFilter16_C; + VP8VFilter16i = VFilter16i_C; + VP8HFilter16 = HFilter16_C; + VP8VFilter8 = VFilter8_C; + VP8VFilter8i = VFilter8i_C; + VP8SimpleVFilter16 = SimpleVFilter16_C; + VP8SimpleHFilter16 = SimpleHFilter16_C; + VP8SimpleVFilter16i = SimpleVFilter16i_C; + VP8SimpleHFilter16i = SimpleHFilter16i_C; +#endif + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + VP8HFilter16i = HFilter16i_C; + VP8HFilter8 = HFilter8_C; + VP8HFilter8i = HFilter8i_C; +#endif + +#if !WEBP_NEON_OMIT_C_CODE + VP8PredLuma4[0] = DC4_C; + VP8PredLuma4[1] = TM4_C; + VP8PredLuma4[2] = VE4_C; + VP8PredLuma4[4] = RD4_C; + VP8PredLuma4[6] = LD4_C; +#endif + + VP8PredLuma4[3] = HE4_C; + VP8PredLuma4[5] = VR4_C; + VP8PredLuma4[7] = VL4_C; + VP8PredLuma4[8] = HD4_C; + VP8PredLuma4[9] = HU4_C; + +#if !WEBP_NEON_OMIT_C_CODE + VP8PredLuma16[0] = DC16_C; + VP8PredLuma16[1] = TM16_C; + VP8PredLuma16[2] = VE16_C; + VP8PredLuma16[3] = HE16_C; + VP8PredLuma16[4] = DC16NoTop_C; + VP8PredLuma16[5] = DC16NoLeft_C; + VP8PredLuma16[6] = DC16NoTopLeft_C; + + VP8PredChroma8[0] = DC8uv_C; + VP8PredChroma8[1] = TM8uv_C; + VP8PredChroma8[2] = VE8uv_C; + VP8PredChroma8[3] = HE8uv_C; + VP8PredChroma8[4] = DC8uvNoTop_C; + VP8PredChroma8[5] = DC8uvNoLeft_C; + VP8PredChroma8[6] = DC8uvNoTopLeft_C; +#endif + + VP8DitherCombine8x8 = DitherCombine8x8_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8DspInitSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + VP8DspInitSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8DspInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8DspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8DspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8DspInitNEON(); + } +#endif + + assert(VP8TransformWHT != NULL); + assert(VP8Transform != NULL); + assert(VP8TransformDC != NULL); + assert(VP8TransformAC3 != NULL); + assert(VP8TransformUV != NULL); + assert(VP8TransformDCUV != NULL); + assert(VP8VFilter16 != NULL); + assert(VP8HFilter16 != NULL); + assert(VP8VFilter8 != NULL); + assert(VP8HFilter8 != NULL); + assert(VP8VFilter16i != NULL); + assert(VP8HFilter16i != NULL); + assert(VP8VFilter8i != NULL); + assert(VP8HFilter8i != NULL); + assert(VP8SimpleVFilter16 != NULL); + assert(VP8SimpleHFilter16 != NULL); + assert(VP8SimpleVFilter16i != NULL); + assert(VP8SimpleHFilter16i != NULL); + assert(VP8PredLuma4[0] != NULL); + assert(VP8PredLuma4[1] != NULL); + assert(VP8PredLuma4[2] != NULL); + assert(VP8PredLuma4[3] != NULL); + assert(VP8PredLuma4[4] != NULL); + assert(VP8PredLuma4[5] != NULL); + assert(VP8PredLuma4[6] != NULL); + assert(VP8PredLuma4[7] != NULL); + assert(VP8PredLuma4[8] != NULL); + assert(VP8PredLuma4[9] != NULL); + assert(VP8PredLuma16[0] != NULL); + assert(VP8PredLuma16[1] != NULL); + assert(VP8PredLuma16[2] != NULL); + assert(VP8PredLuma16[3] != NULL); + assert(VP8PredLuma16[4] != NULL); + assert(VP8PredLuma16[5] != NULL); + assert(VP8PredLuma16[6] != NULL); + assert(VP8PredChroma8[0] != NULL); + assert(VP8PredChroma8[1] != NULL); + assert(VP8PredChroma8[2] != NULL); + assert(VP8PredChroma8[3] != NULL); + assert(VP8PredChroma8[4] != NULL); + assert(VP8PredChroma8[5] != NULL); + assert(VP8PredChroma8[6] != NULL); + assert(VP8DitherCombine8x8 != NULL); +} diff --git a/libraries/webp/src/dsp/dec_clip_tables.c b/libraries/webp/src/dsp/dec_clip_tables.c new file mode 100644 index 0000000000..427b74f776 --- /dev/null +++ b/libraries/webp/src/dsp/dec_clip_tables.c @@ -0,0 +1,369 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Clipping tables for filtering +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +// define to 0 to have run-time table initialization +#if !defined(USE_STATIC_TABLES) +#define USE_STATIC_TABLES 1 // ALTERNATE_CODE +#endif + +#if (USE_STATIC_TABLES == 1) + +static const uint8_t abs0[255 + 255 + 1] = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, + 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, + 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, + 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, + 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, + 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, + 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, + 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, + 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, + 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, + 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, + 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, + 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, + 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, + 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, + 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, + 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, + 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, + 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, + 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +static const uint8_t sclip1[1020 + 1020 + 1] = { + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f +}; + +static const uint8_t sclip2[112 + 112 + 1] = { + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, + 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f +}; + +static const uint8_t clip1[255 + 511 + 1] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, + 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, + 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +#else + +// uninitialized tables +static uint8_t abs0[255 + 255 + 1]; +static int8_t sclip1[1020 + 1020 + 1]; +static int8_t sclip2[112 + 112 + 1]; +static uint8_t clip1[255 + 511 + 1]; + +// We declare this variable 'volatile' to prevent instruction reordering +// and make sure it's set to true _last_ (so as to be thread-safe) +static volatile int tables_ok = 0; + +#endif // USE_STATIC_TABLES + +const int8_t* const VP8ksclip1 = (const int8_t*)&sclip1[1020]; +const int8_t* const VP8ksclip2 = (const int8_t*)&sclip2[112]; +const uint8_t* const VP8kclip1 = &clip1[255]; +const uint8_t* const VP8kabs0 = &abs0[255]; + +WEBP_TSAN_IGNORE_FUNCTION void VP8InitClipTables(void) { +#if (USE_STATIC_TABLES == 0) + int i; + if (!tables_ok) { + for (i = -255; i <= 255; ++i) { + abs0[255 + i] = (i < 0) ? -i : i; + } + for (i = -1020; i <= 1020; ++i) { + sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i; + } + for (i = -112; i <= 112; ++i) { + sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i; + } + for (i = -255; i <= 255 + 255; ++i) { + clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i; + } + tables_ok = 1; + } +#endif // USE_STATIC_TABLES +} diff --git a/libraries/webp/src/dsp/dec_mips32.c b/libraries/webp/src/dsp/dec_mips32.c new file mode 100644 index 0000000000..f0e7de4ac4 --- /dev/null +++ b/libraries/webp/src/dsp/dec_mips32.c @@ -0,0 +1,571 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of dsp functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) + +#include "src/dsp/mips_macro.h" + +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; + +static WEBP_INLINE int abs_mips32(int x) { + const int sign = x >> 31; + return (x ^ sign) - sign; +} + +// 4 pixels in, 2 pixels out +static WEBP_INLINE void do_filter2(uint8_t* p, int step) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; + const int a1 = VP8ksclip2[(a + 4) >> 3]; + const int a2 = VP8ksclip2[(a + 3) >> 3]; + p[-step] = VP8kclip1[p0 + a2]; + p[ 0] = VP8kclip1[q0 - a1]; +} + +// 4 pixels in, 4 pixels out +static WEBP_INLINE void do_filter4(uint8_t* p, int step) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + const int a = 3 * (q0 - p0); + const int a1 = VP8ksclip2[(a + 4) >> 3]; + const int a2 = VP8ksclip2[(a + 3) >> 3]; + const int a3 = (a1 + 1) >> 1; + p[-2 * step] = VP8kclip1[p1 + a3]; + p[- step] = VP8kclip1[p0 + a2]; + p[ 0] = VP8kclip1[q0 - a1]; + p[ step] = VP8kclip1[q1 - a3]; +} + +// 6 pixels in, 6 pixels out +static WEBP_INLINE void do_filter6(uint8_t* p, int step) { + const int p2 = p[-3 * step], p1 = p[-2 * step], p0 = p[-step]; + const int q0 = p[0], q1 = p[step], q2 = p[2 * step]; + const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; + // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] + const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 + const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 + const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 + p[-3 * step] = VP8kclip1[p2 + a3]; + p[-2 * step] = VP8kclip1[p1 + a2]; + p[- step] = VP8kclip1[p0 + a1]; + p[ 0] = VP8kclip1[q0 - a1]; + p[ step] = VP8kclip1[q1 - a2]; + p[ 2 * step] = VP8kclip1[q2 - a3]; +} + +static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return (abs_mips32(p1 - p0) > thresh) || (abs_mips32(q1 - q0) > thresh); +} + +static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) <= t); +} + +static WEBP_INLINE int needs_filter2(const uint8_t* p, + int step, int t, int it) { + const int p3 = p[-4 * step], p2 = p[-3 * step]; + const int p1 = p[-2 * step], p0 = p[-step]; + const int q0 = p[0], q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; + if ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) > t) { + return 0; + } + return abs_mips32(p3 - p2) <= it && abs_mips32(p2 - p1) <= it && + abs_mips32(p1 - p0) <= it && abs_mips32(q3 - q2) <= it && + abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it; +} + +static WEBP_INLINE void FilterLoop26(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + while (size-- > 0) { + if (needs_filter2(p, hstride, thresh2, ithresh)) { + if (hev(p, hstride, hev_thresh)) { + do_filter2(p, hstride); + } else { + do_filter6(p, hstride); + } + } + p += vstride; + } +} + +static WEBP_INLINE void FilterLoop24(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + while (size-- > 0) { + if (needs_filter2(p, hstride, thresh2, ithresh)) { + if (hev(p, hstride, hev_thresh)) { + do_filter2(p, hstride); + } else { + do_filter4(p, hstride); + } + } + p += vstride; + } +} + +// on macroblock edges +static void VFilter16(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); +} + +static void HFilter16(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); +} + +// 8-pixels wide variant, for chroma filtering +static void VFilter8(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); +} + +static void HFilter8(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); +} + +static void VFilter8i(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); +} + +static void HFilter8i(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); +} + +// on three inner edges +static void VFilter16i(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); + } +} + +static void HFilter16i(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); + } +} + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + for (i = 0; i < 16; ++i) { + if (needs_filter(p + i, stride, thresh2)) { + do_filter2(p + i, stride); + } + } +} + +static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + for (i = 0; i < 16; ++i) { + if (needs_filter(p + i * stride, 1, thresh2)) { + do_filter2(p + i * stride, 1); + } + } +} + +static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + SimpleVFilter16(p, stride, thresh); + } +} + +static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + SimpleHFilter16(p, stride, thresh); + } +} + +static void TransformOne(const int16_t* in, uint8_t* dst) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14; + int temp15, temp16, temp17, temp18, temp19; + int16_t* p_in = (int16_t*)in; + + // loops unrolled and merged to avoid usage of tmp buffer + // and to reduce number of stalls. MUL macro is written + // in assembler and inlined + __asm__ volatile( + "lh %[temp0], 0(%[in]) \n\t" + "lh %[temp8], 16(%[in]) \n\t" + "lh %[temp4], 8(%[in]) \n\t" + "lh %[temp12], 24(%[in]) \n\t" + "addu %[temp16], %[temp0], %[temp8] \n\t" + "subu %[temp0], %[temp0], %[temp8] \n\t" + "mul %[temp8], %[temp4], %[kC2] \n\t" + MUL_SHIFT_C1(temp17, temp12) + MUL_SHIFT_C1_IO(temp4, temp19) + "mul %[temp12], %[temp12], %[kC2] \n\t" + "lh %[temp1], 2(%[in]) \n\t" + "lh %[temp5], 10(%[in]) \n\t" + "lh %[temp9], 18(%[in]) \n\t" + "lh %[temp13], 26(%[in]) \n\t" + "sra %[temp8], %[temp8], 16 \n\t" + "sra %[temp12], %[temp12], 16 \n\t" + "lh %[temp2], 4(%[in]) \n\t" + "lh %[temp6], 12(%[in]) \n\t" + "lh %[temp10], 20(%[in]) \n\t" + "lh %[temp14], 28(%[in]) \n\t" + "subu %[temp17], %[temp8], %[temp17] \n\t" + "addu %[temp4], %[temp4], %[temp12] \n\t" + "addu %[temp8], %[temp16], %[temp4] \n\t" + "subu %[temp4], %[temp16], %[temp4] \n\t" + "addu %[temp16], %[temp1], %[temp9] \n\t" + "subu %[temp1], %[temp1], %[temp9] \n\t" + "lh %[temp3], 6(%[in]) \n\t" + "lh %[temp7], 14(%[in]) \n\t" + "lh %[temp11], 22(%[in]) \n\t" + "lh %[temp15], 30(%[in]) \n\t" + "addu %[temp12], %[temp0], %[temp17] \n\t" + "subu %[temp0], %[temp0], %[temp17] \n\t" + "mul %[temp9], %[temp5], %[kC2] \n\t" + MUL_SHIFT_C1(temp17, temp13) + MUL_SHIFT_C1_IO(temp5, temp19) + "mul %[temp13], %[temp13], %[kC2] \n\t" + "sra %[temp9], %[temp9], 16 \n\t" + "subu %[temp17], %[temp9], %[temp17] \n\t" + "sra %[temp13], %[temp13], 16 \n\t" + "addu %[temp5], %[temp5], %[temp13] \n\t" + "addu %[temp13], %[temp1], %[temp17] \n\t" + "subu %[temp1], %[temp1], %[temp17] \n\t" + MUL_SHIFT_C1(temp17, temp14) + "mul %[temp14], %[temp14], %[kC2] \n\t" + "addu %[temp9], %[temp16], %[temp5] \n\t" + "subu %[temp5], %[temp16], %[temp5] \n\t" + "addu %[temp16], %[temp2], %[temp10] \n\t" + "subu %[temp2], %[temp2], %[temp10] \n\t" + "mul %[temp10], %[temp6], %[kC2] \n\t" + MUL_SHIFT_C1_IO(temp6, temp19) + "sra %[temp14], %[temp14], 16 \n\t" + "sra %[temp10], %[temp10], 16 \n\t" + "subu %[temp17], %[temp10], %[temp17] \n\t" + "addu %[temp6], %[temp6], %[temp14] \n\t" + "addu %[temp10], %[temp16], %[temp6] \n\t" + "subu %[temp6], %[temp16], %[temp6] \n\t" + "addu %[temp14], %[temp2], %[temp17] \n\t" + "subu %[temp2], %[temp2], %[temp17] \n\t" + MUL_SHIFT_C1(temp17, temp15) + "mul %[temp15], %[temp15], %[kC2] \n\t" + "addu %[temp16], %[temp3], %[temp11] \n\t" + "subu %[temp3], %[temp3], %[temp11] \n\t" + "mul %[temp11], %[temp7], %[kC2] \n\t" + MUL_SHIFT_C1_IO(temp7, temp19) + "addiu %[temp8], %[temp8], 4 \n\t" + "addiu %[temp12], %[temp12], 4 \n\t" + "addiu %[temp0], %[temp0], 4 \n\t" + "addiu %[temp4], %[temp4], 4 \n\t" + "sra %[temp15], %[temp15], 16 \n\t" + "sra %[temp11], %[temp11], 16 \n\t" + "subu %[temp17], %[temp11], %[temp17] \n\t" + "addu %[temp7], %[temp7], %[temp15] \n\t" + "addu %[temp15], %[temp3], %[temp17] \n\t" + "subu %[temp3], %[temp3], %[temp17] \n\t" + "addu %[temp11], %[temp16], %[temp7] \n\t" + "subu %[temp7], %[temp16], %[temp7] \n\t" + "addu %[temp16], %[temp8], %[temp10] \n\t" + "subu %[temp8], %[temp8], %[temp10] \n\t" + "mul %[temp10], %[temp9], %[kC2] \n\t" + MUL_SHIFT_C1(temp17, temp11) + MUL_SHIFT_C1_IO(temp9, temp19) + "mul %[temp11], %[temp11], %[kC2] \n\t" + "sra %[temp10], %[temp10], 16 \n\t" + "sra %[temp11], %[temp11], 16 \n\t" + "subu %[temp17], %[temp10], %[temp17] \n\t" + "addu %[temp11], %[temp9], %[temp11] \n\t" + "addu %[temp10], %[temp12], %[temp14] \n\t" + "subu %[temp12], %[temp12], %[temp14] \n\t" + "mul %[temp14], %[temp13], %[kC2] \n\t" + MUL_SHIFT_C1(temp9, temp15) + MUL_SHIFT_C1_IO(temp13, temp19) + "mul %[temp15], %[temp15], %[kC2] \n\t" + "sra %[temp14], %[temp14], 16 \n\t" + "sra %[temp15], %[temp15], 16 \n\t" + "subu %[temp9], %[temp14], %[temp9] \n\t" + "addu %[temp15], %[temp13], %[temp15] \n\t" + "addu %[temp14], %[temp0], %[temp2] \n\t" + "subu %[temp0], %[temp0], %[temp2] \n\t" + "mul %[temp2], %[temp1], %[kC2] \n\t" + MUL_SHIFT_C1(temp13, temp3) + MUL_SHIFT_C1_IO(temp1, temp19) + "mul %[temp3], %[temp3], %[kC2] \n\t" + "sra %[temp2], %[temp2], 16 \n\t" + "sra %[temp3], %[temp3], 16 \n\t" + "subu %[temp13], %[temp2], %[temp13] \n\t" + "addu %[temp3], %[temp1], %[temp3] \n\t" + "addu %[temp2], %[temp4], %[temp6] \n\t" + "subu %[temp4], %[temp4], %[temp6] \n\t" + "mul %[temp6], %[temp5], %[kC2] \n\t" + MUL_SHIFT_C1(temp1, temp7) + MUL_SHIFT_C1_IO(temp5, temp19) + "mul %[temp7], %[temp7], %[kC2] \n\t" + "sra %[temp6], %[temp6], 16 \n\t" + "sra %[temp7], %[temp7], 16 \n\t" + "subu %[temp1], %[temp6], %[temp1] \n\t" + "addu %[temp7], %[temp5], %[temp7] \n\t" + "addu %[temp5], %[temp16], %[temp11] \n\t" + "subu %[temp16], %[temp16], %[temp11] \n\t" + "addu %[temp11], %[temp8], %[temp17] \n\t" + "subu %[temp8], %[temp8], %[temp17] \n\t" + "sra %[temp5], %[temp5], 3 \n\t" + "sra %[temp16], %[temp16], 3 \n\t" + "sra %[temp11], %[temp11], 3 \n\t" + "sra %[temp8], %[temp8], 3 \n\t" + "addu %[temp17], %[temp10], %[temp15] \n\t" + "subu %[temp10], %[temp10], %[temp15] \n\t" + "addu %[temp15], %[temp12], %[temp9] \n\t" + "subu %[temp12], %[temp12], %[temp9] \n\t" + "sra %[temp17], %[temp17], 3 \n\t" + "sra %[temp10], %[temp10], 3 \n\t" + "sra %[temp15], %[temp15], 3 \n\t" + "sra %[temp12], %[temp12], 3 \n\t" + "addu %[temp9], %[temp14], %[temp3] \n\t" + "subu %[temp14], %[temp14], %[temp3] \n\t" + "addu %[temp3], %[temp0], %[temp13] \n\t" + "subu %[temp0], %[temp0], %[temp13] \n\t" + "sra %[temp9], %[temp9], 3 \n\t" + "sra %[temp14], %[temp14], 3 \n\t" + "sra %[temp3], %[temp3], 3 \n\t" + "sra %[temp0], %[temp0], 3 \n\t" + "addu %[temp13], %[temp2], %[temp7] \n\t" + "subu %[temp2], %[temp2], %[temp7] \n\t" + "addu %[temp7], %[temp4], %[temp1] \n\t" + "subu %[temp4], %[temp4], %[temp1] \n\t" + "sra %[temp13], %[temp13], 3 \n\t" + "sra %[temp2], %[temp2], 3 \n\t" + "sra %[temp7], %[temp7], 3 \n\t" + "sra %[temp4], %[temp4], 3 \n\t" + "addiu %[temp6], $zero, 255 \n\t" + "lbu %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp1], %[temp1], %[temp5] \n\t" + "sra %[temp5], %[temp1], 8 \n\t" + "sra %[temp18], %[temp1], 31 \n\t" + "beqz %[temp5], 1f \n\t" + "xor %[temp1], %[temp1], %[temp1] \n\t" + "movz %[temp1], %[temp6], %[temp18] \n\t" + "1: \n\t" + "lbu %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp18], %[temp18], %[temp11] \n\t" + "sra %[temp11], %[temp18], 8 \n\t" + "sra %[temp1], %[temp18], 31 \n\t" + "beqz %[temp11], 2f \n\t" + "xor %[temp18], %[temp18], %[temp18] \n\t" + "movz %[temp18], %[temp6], %[temp1] \n\t" + "2: \n\t" + "lbu %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp1], %[temp1], %[temp8] \n\t" + "sra %[temp8], %[temp1], 8 \n\t" + "sra %[temp18], %[temp1], 31 \n\t" + "beqz %[temp8], 3f \n\t" + "xor %[temp1], %[temp1], %[temp1] \n\t" + "movz %[temp1], %[temp6], %[temp18] \n\t" + "3: \n\t" + "lbu %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp18], %[temp18], %[temp16] \n\t" + "sra %[temp16], %[temp18], 8 \n\t" + "sra %[temp1], %[temp18], 31 \n\t" + "beqz %[temp16], 4f \n\t" + "xor %[temp18], %[temp18], %[temp18] \n\t" + "movz %[temp18], %[temp6], %[temp1] \n\t" + "4: \n\t" + "sb %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp5], %[temp5], %[temp17] \n\t" + "addu %[temp8], %[temp8], %[temp15] \n\t" + "addu %[temp11], %[temp11], %[temp12] \n\t" + "addu %[temp16], %[temp16], %[temp10] \n\t" + "sra %[temp18], %[temp5], 8 \n\t" + "sra %[temp1], %[temp5], 31 \n\t" + "beqz %[temp18], 5f \n\t" + "xor %[temp5], %[temp5], %[temp5] \n\t" + "movz %[temp5], %[temp6], %[temp1] \n\t" + "5: \n\t" + "sra %[temp18], %[temp8], 8 \n\t" + "sra %[temp1], %[temp8], 31 \n\t" + "beqz %[temp18], 6f \n\t" + "xor %[temp8], %[temp8], %[temp8] \n\t" + "movz %[temp8], %[temp6], %[temp1] \n\t" + "6: \n\t" + "sra %[temp18], %[temp11], 8 \n\t" + "sra %[temp1], %[temp11], 31 \n\t" + "sra %[temp17], %[temp16], 8 \n\t" + "sra %[temp15], %[temp16], 31 \n\t" + "beqz %[temp18], 7f \n\t" + "xor %[temp11], %[temp11], %[temp11] \n\t" + "movz %[temp11], %[temp6], %[temp1] \n\t" + "7: \n\t" + "beqz %[temp17], 8f \n\t" + "xor %[temp16], %[temp16], %[temp16] \n\t" + "movz %[temp16], %[temp6], %[temp15] \n\t" + "8: \n\t" + "sb %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp5], %[temp5], %[temp9] \n\t" + "addu %[temp8], %[temp8], %[temp3] \n\t" + "addu %[temp11], %[temp11], %[temp0] \n\t" + "addu %[temp16], %[temp16], %[temp14] \n\t" + "sra %[temp18], %[temp5], 8 \n\t" + "sra %[temp1], %[temp5], 31 \n\t" + "sra %[temp17], %[temp8], 8 \n\t" + "sra %[temp15], %[temp8], 31 \n\t" + "sra %[temp12], %[temp11], 8 \n\t" + "sra %[temp10], %[temp11], 31 \n\t" + "sra %[temp9], %[temp16], 8 \n\t" + "sra %[temp3], %[temp16], 31 \n\t" + "beqz %[temp18], 9f \n\t" + "xor %[temp5], %[temp5], %[temp5] \n\t" + "movz %[temp5], %[temp6], %[temp1] \n\t" + "9: \n\t" + "beqz %[temp17], 10f \n\t" + "xor %[temp8], %[temp8], %[temp8] \n\t" + "movz %[temp8], %[temp6], %[temp15] \n\t" + "10: \n\t" + "beqz %[temp12], 11f \n\t" + "xor %[temp11], %[temp11], %[temp11] \n\t" + "movz %[temp11], %[temp6], %[temp10] \n\t" + "11: \n\t" + "beqz %[temp9], 12f \n\t" + "xor %[temp16], %[temp16], %[temp16] \n\t" + "movz %[temp16], %[temp6], %[temp3] \n\t" + "12: \n\t" + "sb %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp5], %[temp5], %[temp13] \n\t" + "addu %[temp8], %[temp8], %[temp7] \n\t" + "addu %[temp11], %[temp11], %[temp4] \n\t" + "addu %[temp16], %[temp16], %[temp2] \n\t" + "sra %[temp18], %[temp5], 8 \n\t" + "sra %[temp1], %[temp5], 31 \n\t" + "sra %[temp17], %[temp8], 8 \n\t" + "sra %[temp15], %[temp8], 31 \n\t" + "sra %[temp12], %[temp11], 8 \n\t" + "sra %[temp10], %[temp11], 31 \n\t" + "sra %[temp9], %[temp16], 8 \n\t" + "sra %[temp3], %[temp16], 31 \n\t" + "beqz %[temp18], 13f \n\t" + "xor %[temp5], %[temp5], %[temp5] \n\t" + "movz %[temp5], %[temp6], %[temp1] \n\t" + "13: \n\t" + "beqz %[temp17], 14f \n\t" + "xor %[temp8], %[temp8], %[temp8] \n\t" + "movz %[temp8], %[temp6], %[temp15] \n\t" + "14: \n\t" + "beqz %[temp12], 15f \n\t" + "xor %[temp11], %[temp11], %[temp11] \n\t" + "movz %[temp11], %[temp6], %[temp10] \n\t" + "15: \n\t" + "beqz %[temp9], 16f \n\t" + "xor %[temp16], %[temp16], %[temp16] \n\t" + "movz %[temp16], %[temp6], %[temp3] \n\t" + "16: \n\t" + "sb %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), + [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), + [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), + [temp18]"=&r"(temp18), [temp19]"=&r"(temp19) + : [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst) + : "memory", "hi", "lo" + ); +} + +static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne(in, dst); + if (do_two) { + TransformOne(in + 16, dst + 4); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPS32(void) { + VP8InitClipTables(); + + VP8Transform = TransformTwo; + + VP8VFilter16 = VFilter16; + VP8HFilter16 = HFilter16; + VP8VFilter8 = VFilter8; + VP8HFilter8 = HFilter8; + VP8VFilter16i = VFilter16i; + VP8HFilter16i = HFilter16i; + VP8VFilter8i = VFilter8i; + VP8HFilter8i = HFilter8i; + + VP8SimpleVFilter16 = SimpleVFilter16; + VP8SimpleHFilter16 = SimpleHFilter16; + VP8SimpleVFilter16i = SimpleVFilter16i; + VP8SimpleHFilter16i = SimpleHFilter16i; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(VP8DspInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/libraries/webp/src/dsp/dec_mips_dsp_r2.c b/libraries/webp/src/dsp/dec_mips_dsp_r2.c new file mode 100644 index 0000000000..0ba706a2ef --- /dev/null +++ b/libraries/webp/src/dsp/dec_mips_dsp_r2.c @@ -0,0 +1,990 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of dsp functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/mips_macro.h" + +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; + +static void TransformDC(const int16_t* in, uint8_t* dst) { + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10; + + __asm__ volatile ( + LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, dst, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + "lh %[temp5], 0(%[in]) \n\t" + "addiu %[temp5], %[temp5], 4 \n\t" + "ins %[temp5], %[temp5], 16, 16 \n\t" + "shra.ph %[temp5], %[temp5], 3 \n\t" + CONVERT_2_BYTES_TO_HALF(temp6, temp7, temp8, temp9, temp10, temp1, temp2, + temp3, temp1, temp2, temp3, temp4) + STORE_SAT_SUM_X2(temp6, temp7, temp8, temp9, temp10, temp1, temp2, temp3, + temp5, temp5, temp5, temp5, temp5, temp5, temp5, temp5, + dst, 0, 1, 2, 3, BPS) + + OUTPUT_EARLY_CLOBBER_REGS_10() + : [in]"r"(in), [dst]"r"(dst) + : "memory" + ); +} + +static void TransformAC3(const int16_t* in, uint8_t* dst) { + const int a = in[0] + 4; + int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; + + __asm__ volatile ( + "ins %[c4], %[d4], 16, 16 \n\t" + "replv.ph %[temp1], %[a] \n\t" + "replv.ph %[temp4], %[d1] \n\t" + ADD_SUB_HALVES(temp2, temp3, temp1, c4) + "replv.ph %[temp5], %[c1] \n\t" + SHIFT_R_SUM_X2(temp1, temp6, temp7, temp8, temp2, temp9, temp10, temp4, + temp2, temp2, temp3, temp3, temp4, temp5, temp4, temp5) + LOAD_WITH_OFFSET_X4(temp3, temp5, temp11, temp12, dst, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp13, temp14, temp3, temp15, temp5, temp16, + temp11, temp17, temp3, temp5, temp11, temp12) + PACK_2_HALVES_TO_WORD(temp12, temp18, temp7, temp6, temp1, temp8, temp2, + temp4, temp7, temp6, temp10, temp9) + STORE_SAT_SUM_X2(temp13, temp14, temp3, temp15, temp5, temp16, temp11, + temp17, temp12, temp18, temp1, temp8, temp2, temp4, + temp7, temp6, dst, 0, 1, 2, 3, BPS) + + OUTPUT_EARLY_CLOBBER_REGS_18(), + [c4]"+&r"(c4) + : [dst]"r"(dst), [a]"r"(a), [d1]"r"(d1), [d4]"r"(d4), [c1]"r"(c1) + : "memory" + ); +} + +static void TransformOne(const int16_t* in, uint8_t* dst) { + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; + + __asm__ volatile ( + "ulw %[temp1], 0(%[in]) \n\t" + "ulw %[temp2], 16(%[in]) \n\t" + LOAD_IN_X2(temp5, temp6, 24, 26) + ADD_SUB_HALVES(temp3, temp4, temp1, temp2) + LOAD_IN_X2(temp1, temp2, 8, 10) + MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, + temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6, + temp13, temp11, temp14, temp12) + INSERT_HALF_X2(temp8, temp7, temp10, temp9) + "ulw %[temp17], 4(%[in]) \n\t" + "ulw %[temp18], 20(%[in]) \n\t" + ADD_SUB_HALVES(temp1, temp2, temp3, temp8) + ADD_SUB_HALVES(temp5, temp6, temp4, temp7) + ADD_SUB_HALVES(temp7, temp8, temp17, temp18) + LOAD_IN_X2(temp17, temp18, 12, 14) + LOAD_IN_X2(temp9, temp10, 28, 30) + MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17, + temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10, + temp15, temp4, temp16, temp17) + INSERT_HALF_X2(temp11, temp12, temp13, temp14) + ADD_SUB_HALVES(temp17, temp8, temp8, temp11) + ADD_SUB_HALVES(temp3, temp4, temp7, temp12) + + // horizontal + SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6) + INSERT_HALF_X2(temp1, temp6, temp5, temp2) + SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8) + "repl.ph %[temp2], 0x4 \n\t" + INSERT_HALF_X2(temp3, temp8, temp17, temp4) + "addq.ph %[temp1], %[temp1], %[temp2] \n\t" + "addq.ph %[temp6], %[temp6], %[temp2] \n\t" + ADD_SUB_HALVES(temp2, temp4, temp1, temp3) + ADD_SUB_HALVES(temp5, temp7, temp6, temp8) + MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18, + temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15, + temp6, temp17, temp8, temp18) + MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16, + temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14, + temp18, temp12, temp17, temp16) + INSERT_HALF_X2(temp1, temp3, temp9, temp13) + INSERT_HALF_X2(temp6, temp8, temp11, temp15) + SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15, + temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8, + temp6) + PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13, + temp16, temp11, temp10, temp15, temp14) + LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, dst, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10, + temp11, temp10, temp11, temp14, temp15) + STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11, + temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4, + dst, 0, 1, 2, 3, BPS) + + OUTPUT_EARLY_CLOBBER_REGS_18() + : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2) + : "memory", "hi", "lo" + ); +} + +static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne(in, dst); + if (do_two) { + TransformOne(in + 16, dst + 4); + } +} + +static WEBP_INLINE void FilterLoop26(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "1: \n\t" + "negu %[temp1], %[hstride] \n\t" + "addiu %[size], %[size], -1 \n\t" + "sll %[temp2], %[hstride], 1 \n\t" + "sll %[temp3], %[temp1], 1 \n\t" + "addu %[temp4], %[temp2], %[hstride] \n\t" + "addu %[temp5], %[temp3], %[temp1] \n\t" + "lbu %[temp7], 0(%[p]) \n\t" + "sll %[temp6], %[temp3], 1 \n\t" + "lbux %[temp8], %[temp5](%[p]) \n\t" + "lbux %[temp9], %[temp3](%[p]) \n\t" + "lbux %[temp10], %[temp1](%[p]) \n\t" + "lbux %[temp11], %[temp6](%[p]) \n\t" + "lbux %[temp12], %[hstride](%[p]) \n\t" + "lbux %[temp13], %[temp2](%[p]) \n\t" + "lbux %[temp14], %[temp4](%[p]) \n\t" + "subu %[temp1], %[temp10], %[temp7] \n\t" + "subu %[temp2], %[temp9], %[temp12] \n\t" + "absq_s.w %[temp3], %[temp1] \n\t" + "absq_s.w %[temp4], %[temp2] \n\t" + "negu %[temp1], %[temp1] \n\t" + "sll %[temp3], %[temp3], 2 \n\t" + "addu %[temp15], %[temp3], %[temp4] \n\t" + "subu %[temp3], %[temp15], %[thresh2] \n\t" + "sll %[temp6], %[temp1], 1 \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp4], %[temp11], %[temp8] \n\t" + "absq_s.w %[temp4], %[temp4] \n\t" + "shll_s.w %[temp2], %[temp2], 24 \n\t" + "subu %[temp4], %[temp4], %[ithresh] \n\t" + "bgtz %[temp4], 3f \n\t" + " subu %[temp3], %[temp8], %[temp9] \n\t" + "absq_s.w %[temp3], %[temp3] \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp5], %[temp9], %[temp10] \n\t" + "absq_s.w %[temp3], %[temp5] \n\t" + "absq_s.w %[temp5], %[temp5] \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp3], %[temp14], %[temp13] \n\t" + "absq_s.w %[temp3], %[temp3] \n\t" + "slt %[temp5], %[hev_thresh], %[temp5] \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp3], %[temp13], %[temp12] \n\t" + "absq_s.w %[temp3], %[temp3] \n\t" + "sra %[temp4], %[temp2], 24 \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp15], %[temp12], %[temp7] \n\t" + "absq_s.w %[temp3], %[temp15] \n\t" + "absq_s.w %[temp15], %[temp15] \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " slt %[temp15], %[hev_thresh], %[temp15] \n\t" + "addu %[temp3], %[temp6], %[temp1] \n\t" + "or %[temp2], %[temp5], %[temp15] \n\t" + "addu %[temp5], %[temp4], %[temp3] \n\t" + "beqz %[temp2], 4f \n\t" + " shra_r.w %[temp1], %[temp5], 3 \n\t" + "addiu %[temp2], %[temp5], 3 \n\t" + "sra %[temp2], %[temp2], 3 \n\t" + "shll_s.w %[temp1], %[temp1], 27 \n\t" + "shll_s.w %[temp2], %[temp2], 27 \n\t" + "subu %[temp3], %[p], %[hstride] \n\t" + "sra %[temp1], %[temp1], 27 \n\t" + "sra %[temp2], %[temp2], 27 \n\t" + "subu %[temp1], %[temp7], %[temp1] \n\t" + "addu %[temp2], %[temp10], %[temp2] \n\t" + "lbux %[temp2], %[temp2](%[VP8kclip1]) \n\t" + "lbux %[temp1], %[temp1](%[VP8kclip1]) \n\t" + "sb %[temp2], 0(%[temp3]) \n\t" + "j 3f \n\t" + " sb %[temp1], 0(%[p]) \n\t" + "4: \n\t" + "shll_s.w %[temp5], %[temp5], 24 \n\t" + "subu %[temp14], %[p], %[hstride] \n\t" + "subu %[temp11], %[temp14], %[hstride] \n\t" + "sra %[temp6], %[temp5], 24 \n\t" + "sll %[temp1], %[temp6], 3 \n\t" + "subu %[temp15], %[temp11], %[hstride] \n\t" + "addu %[temp2], %[temp6], %[temp1] \n\t" + "sll %[temp3], %[temp2], 1 \n\t" + "addu %[temp4], %[temp3], %[temp2] \n\t" + "addiu %[temp2], %[temp2], 63 \n\t" + "addiu %[temp3], %[temp3], 63 \n\t" + "addiu %[temp4], %[temp4], 63 \n\t" + "sra %[temp2], %[temp2], 7 \n\t" + "sra %[temp3], %[temp3], 7 \n\t" + "sra %[temp4], %[temp4], 7 \n\t" + "addu %[temp1], %[temp8], %[temp2] \n\t" + "addu %[temp5], %[temp9], %[temp3] \n\t" + "addu %[temp6], %[temp10], %[temp4] \n\t" + "subu %[temp8], %[temp7], %[temp4] \n\t" + "subu %[temp7], %[temp12], %[temp3] \n\t" + "addu %[temp10], %[p], %[hstride] \n\t" + "subu %[temp9], %[temp13], %[temp2] \n\t" + "addu %[temp12], %[temp10], %[hstride] \n\t" + "lbux %[temp2], %[temp1](%[VP8kclip1]) \n\t" + "lbux %[temp3], %[temp5](%[VP8kclip1]) \n\t" + "lbux %[temp4], %[temp6](%[VP8kclip1]) \n\t" + "lbux %[temp5], %[temp8](%[VP8kclip1]) \n\t" + "lbux %[temp6], %[temp7](%[VP8kclip1]) \n\t" + "lbux %[temp8], %[temp9](%[VP8kclip1]) \n\t" + "sb %[temp2], 0(%[temp15]) \n\t" + "sb %[temp3], 0(%[temp11]) \n\t" + "sb %[temp4], 0(%[temp14]) \n\t" + "sb %[temp5], 0(%[p]) \n\t" + "sb %[temp6], 0(%[temp10]) \n\t" + "sb %[temp8], 0(%[temp12]) \n\t" + "3: \n\t" + "bgtz %[size], 1b \n\t" + " addu %[p], %[p], %[vstride] \n\t" + ".set pop \n\t" + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),[temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), + [temp7]"=&r"(temp7),[temp8]"=&r"(temp8),[temp9]"=&r"(temp9), + [temp10]"=&r"(temp10),[temp11]"=&r"(temp11),[temp12]"=&r"(temp12), + [temp13]"=&r"(temp13),[temp14]"=&r"(temp14),[temp15]"=&r"(temp15), + [size]"+&r"(size), [p]"+&r"(p) + : [hstride]"r"(hstride), [thresh2]"r"(thresh2), + [ithresh]"r"(ithresh),[vstride]"r"(vstride), [hev_thresh]"r"(hev_thresh), + [VP8kclip1]"r"(VP8kclip1) + : "memory" + ); +} + +static WEBP_INLINE void FilterLoop24(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, int hev_thresh) { + int p0, q0, p1, q1, p2, q2, p3, q3; + int step1, step2, temp1, temp2, temp3, temp4; + uint8_t* pTemp0; + uint8_t* pTemp1; + const int thresh2 = 2 * thresh + 1; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "bltz %[size], 3f \n\t" + " nop \n\t" + "2: \n\t" + "negu %[step1], %[hstride] \n\t" + "lbu %[q0], 0(%[p]) \n\t" + "lbux %[p0], %[step1](%[p]) \n\t" + "subu %[step1], %[step1], %[hstride] \n\t" + "lbux %[q1], %[hstride](%[p]) \n\t" + "subu %[temp1], %[p0], %[q0] \n\t" + "lbux %[p1], %[step1](%[p]) \n\t" + "addu %[step2], %[hstride], %[hstride] \n\t" + "absq_s.w %[temp2], %[temp1] \n\t" + "subu %[temp3], %[p1], %[q1] \n\t" + "absq_s.w %[temp4], %[temp3] \n\t" + "sll %[temp2], %[temp2], 2 \n\t" + "addu %[temp2], %[temp2], %[temp4] \n\t" + "subu %[temp4], %[temp2], %[thresh2] \n\t" + "subu %[step1], %[step1], %[hstride] \n\t" + "bgtz %[temp4], 0f \n\t" + " lbux %[p2], %[step1](%[p]) \n\t" + "subu %[step1], %[step1], %[hstride] \n\t" + "lbux %[q2], %[step2](%[p]) \n\t" + "lbux %[p3], %[step1](%[p]) \n\t" + "subu %[temp4], %[p2], %[p1] \n\t" + "addu %[step2], %[step2], %[hstride] \n\t" + "subu %[temp2], %[p3], %[p2] \n\t" + "absq_s.w %[temp4], %[temp4] \n\t" + "absq_s.w %[temp2], %[temp2] \n\t" + "lbux %[q3], %[step2](%[p]) \n\t" + "subu %[temp4], %[temp4], %[ithresh] \n\t" + "negu %[temp1], %[temp1] \n\t" + "bgtz %[temp4], 0f \n\t" + " subu %[temp2], %[temp2], %[ithresh] \n\t" + "subu %[p3], %[p1], %[p0] \n\t" + "bgtz %[temp2], 0f \n\t" + " absq_s.w %[p3], %[p3] \n\t" + "subu %[temp4], %[q3], %[q2] \n\t" + "subu %[pTemp0], %[p], %[hstride] \n\t" + "absq_s.w %[temp4], %[temp4] \n\t" + "subu %[temp2], %[p3], %[ithresh] \n\t" + "sll %[step1], %[temp1], 1 \n\t" + "bgtz %[temp2], 0f \n\t" + " subu %[temp4], %[temp4], %[ithresh] \n\t" + "subu %[temp2], %[q2], %[q1] \n\t" + "bgtz %[temp4], 0f \n\t" + " absq_s.w %[temp2], %[temp2] \n\t" + "subu %[q3], %[q1], %[q0] \n\t" + "absq_s.w %[q3], %[q3] \n\t" + "subu %[temp2], %[temp2], %[ithresh] \n\t" + "addu %[temp1], %[temp1], %[step1] \n\t" + "bgtz %[temp2], 0f \n\t" + " subu %[temp4], %[q3], %[ithresh] \n\t" + "slt %[p3], %[hev_thresh], %[p3] \n\t" + "bgtz %[temp4], 0f \n\t" + " slt %[q3], %[hev_thresh], %[q3] \n\t" + "or %[q3], %[q3], %[p3] \n\t" + "bgtz %[q3], 1f \n\t" + " shra_r.w %[temp2], %[temp1], 3 \n\t" + "addiu %[temp1], %[temp1], 3 \n\t" + "sra %[temp1], %[temp1], 3 \n\t" + "shll_s.w %[temp2], %[temp2], 27 \n\t" + "shll_s.w %[temp1], %[temp1], 27 \n\t" + "addu %[pTemp1], %[p], %[hstride] \n\t" + "sra %[temp2], %[temp2], 27 \n\t" + "sra %[temp1], %[temp1], 27 \n\t" + "addiu %[step1], %[temp2], 1 \n\t" + "sra %[step1], %[step1], 1 \n\t" + "addu %[p0], %[p0], %[temp1] \n\t" + "addu %[p1], %[p1], %[step1] \n\t" + "subu %[q0], %[q0], %[temp2] \n\t" + "subu %[q1], %[q1], %[step1] \n\t" + "lbux %[temp2], %[p0](%[VP8kclip1]) \n\t" + "lbux %[temp3], %[q0](%[VP8kclip1]) \n\t" + "lbux %[temp4], %[q1](%[VP8kclip1]) \n\t" + "sb %[temp2], 0(%[pTemp0]) \n\t" + "lbux %[temp1], %[p1](%[VP8kclip1]) \n\t" + "subu %[pTemp0], %[pTemp0], %[hstride] \n\t" + "sb %[temp3], 0(%[p]) \n\t" + "sb %[temp4], 0(%[pTemp1]) \n\t" + "j 0f \n\t" + " sb %[temp1], 0(%[pTemp0]) \n\t" + "1: \n\t" + "shll_s.w %[temp3], %[temp3], 24 \n\t" + "sra %[temp3], %[temp3], 24 \n\t" + "addu %[temp1], %[temp1], %[temp3] \n\t" + "shra_r.w %[temp2], %[temp1], 3 \n\t" + "addiu %[temp1], %[temp1], 3 \n\t" + "shll_s.w %[temp2], %[temp2], 27 \n\t" + "sra %[temp1], %[temp1], 3 \n\t" + "shll_s.w %[temp1], %[temp1], 27 \n\t" + "sra %[temp2], %[temp2], 27 \n\t" + "sra %[temp1], %[temp1], 27 \n\t" + "addu %[p0], %[p0], %[temp1] \n\t" + "subu %[q0], %[q0], %[temp2] \n\t" + "lbux %[temp1], %[p0](%[VP8kclip1]) \n\t" + "lbux %[temp2], %[q0](%[VP8kclip1]) \n\t" + "sb %[temp2], 0(%[p]) \n\t" + "sb %[temp1], 0(%[pTemp0]) \n\t" + "0: \n\t" + "subu %[size], %[size], 1 \n\t" + "bgtz %[size], 2b \n\t" + " addu %[p], %[p], %[vstride] \n\t" + "3: \n\t" + ".set pop \n\t" + : [p0]"=&r"(p0), [q0]"=&r"(q0), [p1]"=&r"(p1), [q1]"=&r"(q1), + [p2]"=&r"(p2), [q2]"=&r"(q2), [p3]"=&r"(p3), [q3]"=&r"(q3), + [step2]"=&r"(step2), [step1]"=&r"(step1), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), + [pTemp0]"=&r"(pTemp0), [pTemp1]"=&r"(pTemp1), [p]"+&r"(p), + [size]"+&r"(size) + : [vstride]"r"(vstride), [ithresh]"r"(ithresh), + [hev_thresh]"r"(hev_thresh), [hstride]"r"(hstride), + [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) + : "memory" + ); +} + +// on macroblock edges +static void VFilter16(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); +} + +static void HFilter16(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); +} + +// 8-pixels wide variant, for chroma filtering +static void VFilter8(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); +} + +static void HFilter8(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); +} + +// on three inner edges +static void VFilter16i(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); + } +} + +static void HFilter16i(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); + } +} + +static void VFilter8i(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); +} + +static void HFilter8i(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); +} + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + uint8_t* p1 = p - stride; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "li %[i], 16 \n\t" + "0: \n\t" + "negu %[temp4], %[stride] \n\t" + "sll %[temp5], %[temp4], 1 \n\t" + "lbu %[temp2], 0(%[p]) \n\t" + "lbux %[temp3], %[stride](%[p]) \n\t" + "lbux %[temp1], %[temp4](%[p]) \n\t" + "lbux %[temp0], %[temp5](%[p]) \n\t" + "subu %[temp7], %[temp1], %[temp2] \n\t" + "subu %[temp6], %[temp0], %[temp3] \n\t" + "absq_s.w %[temp4], %[temp7] \n\t" + "absq_s.w %[temp5], %[temp6] \n\t" + "sll %[temp4], %[temp4], 2 \n\t" + "subu %[temp5], %[temp5], %[thresh2] \n\t" + "addu %[temp5], %[temp4], %[temp5] \n\t" + "negu %[temp8], %[temp7] \n\t" + "bgtz %[temp5], 1f \n\t" + " addiu %[i], %[i], -1 \n\t" + "sll %[temp4], %[temp8], 1 \n\t" + "shll_s.w %[temp5], %[temp6], 24 \n\t" + "addu %[temp3], %[temp4], %[temp8] \n\t" + "sra %[temp5], %[temp5], 24 \n\t" + "addu %[temp3], %[temp3], %[temp5] \n\t" + "addiu %[temp7], %[temp3], 3 \n\t" + "sra %[temp7], %[temp7], 3 \n\t" + "shra_r.w %[temp8], %[temp3], 3 \n\t" + "shll_s.w %[temp0], %[temp7], 27 \n\t" + "shll_s.w %[temp4], %[temp8], 27 \n\t" + "sra %[temp0], %[temp0], 27 \n\t" + "sra %[temp4], %[temp4], 27 \n\t" + "addu %[temp7], %[temp1], %[temp0] \n\t" + "subu %[temp2], %[temp2], %[temp4] \n\t" + "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t" + "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t" + "sb %[temp3], 0(%[p1]) \n\t" + "sb %[temp4], 0(%[p]) \n\t" + "1: \n\t" + "addiu %[p1], %[p1], 1 \n\t" + "bgtz %[i], 0b \n\t" + " addiu %[p], %[p], 1 \n\t" + " .set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [p]"+&r"(p), [i]"=&r"(i), [p1]"+&r"(p1) + : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) + : "memory" + ); +} + +// TEMP0 = SRC[A + A1 * BPS] +// TEMP1 = SRC[B + B1 * BPS] +// TEMP2 = SRC[C + C1 * BPS] +// TEMP3 = SRC[D + D1 * BPS] +#define LOAD_4_BYTES(TEMP0, TEMP1, TEMP2, TEMP3, \ + A, A1, B, B1, C, C1, D, D1, SRC) \ + "lbu %[" #TEMP0 "], " #A "+" #A1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + "lbu %[" #TEMP1 "], " #B "+" #B1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + "lbu %[" #TEMP2 "], " #C "+" #C1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + "lbu %[" #TEMP3 "], " #D "+" #D1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + +static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "li %[i], 16 \n\t" + "0: \n\t" + LOAD_4_BYTES(temp0, temp1, temp2, temp3, -2, 0, -1, 0, 0, 0, 1, 0, p) + "subu %[temp7], %[temp1], %[temp2] \n\t" + "subu %[temp6], %[temp0], %[temp3] \n\t" + "absq_s.w %[temp4], %[temp7] \n\t" + "absq_s.w %[temp5], %[temp6] \n\t" + "sll %[temp4], %[temp4], 2 \n\t" + "addu %[temp5], %[temp4], %[temp5] \n\t" + "subu %[temp5], %[temp5], %[thresh2] \n\t" + "negu %[temp8], %[temp7] \n\t" + "bgtz %[temp5], 1f \n\t" + " addiu %[i], %[i], -1 \n\t" + "sll %[temp4], %[temp8], 1 \n\t" + "shll_s.w %[temp5], %[temp6], 24 \n\t" + "addu %[temp3], %[temp4], %[temp8] \n\t" + "sra %[temp5], %[temp5], 24 \n\t" + "addu %[temp3], %[temp3], %[temp5] \n\t" + "addiu %[temp7], %[temp3], 3 \n\t" + "sra %[temp7], %[temp7], 3 \n\t" + "shra_r.w %[temp8], %[temp3], 3 \n\t" + "shll_s.w %[temp0], %[temp7], 27 \n\t" + "shll_s.w %[temp4], %[temp8], 27 \n\t" + "sra %[temp0], %[temp0], 27 \n\t" + "sra %[temp4], %[temp4], 27 \n\t" + "addu %[temp7], %[temp1], %[temp0] \n\t" + "subu %[temp2], %[temp2], %[temp4] \n\t" + "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t" + "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t" + "sb %[temp3], -1(%[p]) \n\t" + "sb %[temp4], 0(%[p]) \n\t" + "1: \n\t" + "bgtz %[i], 0b \n\t" + " addu %[p], %[p], %[stride] \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [p]"+&r"(p), [i]"=&r"(i) + : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) + : "memory" + ); +} + +static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + SimpleVFilter16(p, stride, thresh); + } +} + +static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + SimpleHFilter16(p, stride, thresh); + } +} + +// DST[A * BPS] = TEMP0 +// DST[B + C * BPS] = TEMP1 +#define STORE_8_BYTES(TEMP0, TEMP1, A, B, C, DST) \ + "usw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #DST "]) \n\t" \ + "usw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #DST "]) \n\t" + +static void VE4(uint8_t* dst) { // vertical + const uint8_t* top = dst - BPS; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + __asm__ volatile ( + "ulw %[temp0], -1(%[top]) \n\t" + "ulh %[temp1], 3(%[top]) \n\t" + "preceu.ph.qbr %[temp2], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" + "packrl.ph %[temp6], %[temp4], %[temp3] \n\t" + "shll.ph %[temp5], %[temp5], 1 \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp2], %[temp5], %[temp2] \n\t" + "addq.ph %[temp6], %[temp6], %[temp4] \n\t" + "addq.ph %[temp2], %[temp2], %[temp3] \n\t" + "addq.ph %[temp6], %[temp6], %[temp3] \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" + STORE_8_BYTES(temp4, temp4, 0, 0, 1, dst) + STORE_8_BYTES(temp4, temp4, 2, 0, 3, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void DC4(uint8_t* dst) { // DC + int temp0, temp1, temp2, temp3, temp4; + __asm__ volatile ( + "ulw %[temp0], -1*" XSTR(BPS) "(%[dst]) \n\t" + LOAD_4_BYTES(temp1, temp2, temp3, temp4, -1, 0, -1, 1, -1, 2, -1, 3, dst) + "ins %[temp1], %[temp2], 8, 8 \n\t" + "ins %[temp1], %[temp3], 16, 8 \n\t" + "ins %[temp1], %[temp4], 24, 8 \n\t" + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "shra_r.w %[temp0], %[temp0], 3 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + STORE_8_BYTES(temp0, temp0, 0, 0, 1, dst) + STORE_8_BYTES(temp0, temp0, 2, 0, 3, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4) + : [dst]"r"(dst) + : "memory" + ); +} + +static void RD4(uint8_t* dst) { // Down-right + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8; + __asm__ volatile ( + LOAD_4_BYTES(temp0, temp1, temp2, temp3, -1, 0, -1, 1, -1, 2, -1, 3, dst) + "ulw %[temp7], -1-" XSTR(BPS) "(%[dst]) \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "preceu.ph.qbr %[temp5], %[temp7] \n\t" + "ins %[temp2], %[temp1], 16, 16 \n\t" + "preceu.ph.qbl %[temp4], %[temp7] \n\t" + "ins %[temp3], %[temp2], 16, 16 \n\t" + "shll.ph %[temp2], %[temp2], 1 \n\t" + "addq.ph %[temp3], %[temp3], %[temp1] \n\t" + "packrl.ph %[temp6], %[temp5], %[temp1] \n\t" + "addq.ph %[temp3], %[temp3], %[temp2] \n\t" + "addq.ph %[temp1], %[temp1], %[temp5] \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp1], %[temp1], %[temp6] \n\t" + "packrl.ph %[temp0], %[temp4], %[temp5] \n\t" + "addq.ph %[temp8], %[temp5], %[temp4] \n\t" + "shra_r.ph %[temp3], %[temp3], 2 \n\t" + "shll.ph %[temp0], %[temp0], 1 \n\t" + "shra_r.ph %[temp1], %[temp1], 2 \n\t" + "addq.ph %[temp8], %[temp0], %[temp8] \n\t" + "lbu %[temp5], 3-" XSTR(BPS) "(%[dst]) \n\t" + "precrq.ph.w %[temp7], %[temp7], %[temp7] \n\t" + "shra_r.ph %[temp8], %[temp8], 2 \n\t" + "ins %[temp7], %[temp5], 0, 8 \n\t" + "precr.qb.ph %[temp2], %[temp1], %[temp3] \n\t" + "raddu.w.qb %[temp4], %[temp7] \n\t" + "precr.qb.ph %[temp6], %[temp8], %[temp1] \n\t" + "shra_r.w %[temp4], %[temp4], 2 \n\t" + STORE_8_BYTES(temp2, temp6, 3, 0, 1, dst) + "prepend %[temp2], %[temp8], 8 \n\t" + "prepend %[temp6], %[temp4], 8 \n\t" + STORE_8_BYTES(temp2, temp6, 2, 0, 0, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) + : [dst]"r"(dst) + : "memory" + ); +} + +// TEMP0 = SRC[A * BPS] +// TEMP1 = SRC[B + C * BPS] +#define LOAD_8_BYTES(TEMP0, TEMP1, A, B, C, SRC) \ + "ulw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + "ulw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #SRC "]) \n\t" + +static void LD4(uint8_t* dst) { // Down-Left + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) + "preceu.ph.qbl %[temp2], %[temp0] \n\t" + "preceu.ph.qbr %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "preceu.ph.qbl %[temp5], %[temp1] \n\t" + "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" + "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" + "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp9], %[temp2], %[temp6] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "addq.ph %[temp9], %[temp9], %[temp3] \n\t" + "shll.ph %[temp8], %[temp8], 1 \n\t" + "shra_r.ph %[temp9], %[temp9], 2 \n\t" + "addq.ph %[temp3], %[temp4], %[temp7] \n\t" + "addq.ph %[temp0], %[temp5], %[temp8] \n\t" + "addq.ph %[temp3], %[temp3], %[temp2] \n\t" + "addq.ph %[temp0], %[temp0], %[temp4] \n\t" + "shra_r.ph %[temp3], %[temp3], 2 \n\t" + "shra_r.ph %[temp0], %[temp0], 2 \n\t" + "srl %[temp1], %[temp1], 24 \n\t" + "sll %[temp1], %[temp1], 1 \n\t" + "raddu.w.qb %[temp5], %[temp5] \n\t" + "precr.qb.ph %[temp9], %[temp3], %[temp9] \n\t" + "precr.qb.ph %[temp3], %[temp0], %[temp3] \n\t" + "addu %[temp1], %[temp1], %[temp5] \n\t" + "shra_r.w %[temp1], %[temp1], 2 \n\t" + STORE_8_BYTES(temp9, temp3, 0, 0, 2, dst) + "prepend %[temp9], %[temp0], 8 \n\t" + "prepend %[temp3], %[temp1], 8 \n\t" + STORE_8_BYTES(temp9, temp3, 1, 0, 3, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [dst]"r"(dst) + : "memory" + ); +} + +//------------------------------------------------------------------------------ +// Chroma + +static void DC8uv(uint8_t* dst) { // DC + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) + LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst) + LOAD_4_BYTES(temp6, temp7, temp8, temp9, -1, 4, -1, 5, -1, 6, -1, 7, dst) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[temp4], %[temp4], %[temp5] \n\t" + "addu %[temp6], %[temp6], %[temp7] \n\t" + "addu %[temp8], %[temp8], %[temp9] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp4] \n\t" + "addu %[temp6], %[temp6], %[temp8] \n\t" + "addu %[temp0], %[temp0], %[temp2] \n\t" + "addu %[temp0], %[temp0], %[temp6] \n\t" + "shra_r.w %[temp0], %[temp0], 4 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) + STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) + STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) + STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) + STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) + STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) + STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) + STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [dst]"r"(dst) + : "memory" + ); +} + +static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples + int temp0, temp1; + __asm__ volatile ( + LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "shra_r.w %[temp0], %[temp0], 3 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) + STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) + STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) + STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) + STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) + STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) + STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) + STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) + : [dst]"r"(dst) + : "memory" + ); +} + +static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8; + __asm__ volatile ( + LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst) + LOAD_4_BYTES(temp6, temp7, temp8, temp1, -1, 4, -1, 5, -1, 6, -1, 7, dst) + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[temp4], %[temp4], %[temp5] \n\t" + "addu %[temp6], %[temp6], %[temp7] \n\t" + "addu %[temp8], %[temp8], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp4] \n\t" + "addu %[temp6], %[temp6], %[temp8] \n\t" + "addu %[temp0], %[temp6], %[temp2] \n\t" + "shra_r.w %[temp0], %[temp0], 3 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) + STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) + STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) + STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) + STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) + STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) + STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) + STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) + : [dst]"r"(dst) + : "memory" + ); +} + +#undef LOAD_8_BYTES +#undef STORE_8_BYTES +#undef LOAD_4_BYTES + +#define CLIPPING(SIZE) \ + "preceu.ph.qbl %[temp2], %[temp0] \n\t" \ + "preceu.ph.qbr %[temp0], %[temp0] \n\t" \ +".if " #SIZE " == 8 \n\t" \ + "preceu.ph.qbl %[temp3], %[temp1] \n\t" \ + "preceu.ph.qbr %[temp1], %[temp1] \n\t" \ +".endif \n\t" \ + "addu.ph %[temp2], %[temp2], %[dst_1] \n\t" \ + "addu.ph %[temp0], %[temp0], %[dst_1] \n\t" \ +".if " #SIZE " == 8 \n\t" \ + "addu.ph %[temp3], %[temp3], %[dst_1] \n\t" \ + "addu.ph %[temp1], %[temp1], %[dst_1] \n\t" \ +".endif \n\t" \ + "shll_s.ph %[temp2], %[temp2], 7 \n\t" \ + "shll_s.ph %[temp0], %[temp0], 7 \n\t" \ +".if " #SIZE " == 8 \n\t" \ + "shll_s.ph %[temp3], %[temp3], 7 \n\t" \ + "shll_s.ph %[temp1], %[temp1], 7 \n\t" \ +".endif \n\t" \ + "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \ +".if " #SIZE " == 8 \n\t" \ + "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" \ +".endif \n\t" + + +#define CLIP_8B_TO_DST(DST, TOP, SIZE) do { \ + int dst_1 = ((int)(DST)[-1] << 16) + (DST)[-1]; \ + int temp0, temp1, temp2, temp3; \ + __asm__ volatile ( \ + ".if " #SIZE " < 8 \n\t" \ + "ulw %[temp0], 0(%[top]) \n\t" \ + "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \ + CLIPPING(4) \ + "usw %[temp0], 0(%[dst]) \n\t" \ + ".else \n\t" \ + "ulw %[temp0], 0(%[top]) \n\t" \ + "ulw %[temp1], 4(%[top]) \n\t" \ + "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \ + CLIPPING(8) \ + "usw %[temp0], 0(%[dst]) \n\t" \ + "usw %[temp1], 4(%[dst]) \n\t" \ + ".if " #SIZE " == 16 \n\t" \ + "ulw %[temp0], 8(%[top]) \n\t" \ + "ulw %[temp1], 12(%[top]) \n\t" \ + CLIPPING(8) \ + "usw %[temp0], 8(%[dst]) \n\t" \ + "usw %[temp1], 12(%[dst]) \n\t" \ + ".endif \n\t" \ + ".endif \n\t" \ + : [dst_1]"+&r"(dst_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ + : [top_1]"r"(top_1), [top]"r"((TOP)), [dst]"r"((DST)) \ + : "memory" \ + ); \ +} while (0) + +#define CLIP_TO_DST(DST, SIZE) do { \ + int y; \ + const uint8_t* top = (DST) - BPS; \ + const int top_1 = ((int)top[-1] << 16) + top[-1]; \ + for (y = 0; y < (SIZE); ++y) { \ + CLIP_8B_TO_DST((DST), top, (SIZE)); \ + (DST) += BPS; \ + } \ +} while (0) + +#define TRUE_MOTION(DST, SIZE) \ +static void TrueMotion##SIZE(uint8_t* (DST)) { \ + CLIP_TO_DST((DST), (SIZE)); \ +} + +TRUE_MOTION(dst, 4) +TRUE_MOTION(dst, 8) +TRUE_MOTION(dst, 16) + +#undef TRUE_MOTION +#undef CLIP_TO_DST +#undef CLIP_8B_TO_DST +#undef CLIPPING + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPSdspR2(void) { + VP8TransformDC = TransformDC; + VP8TransformAC3 = TransformAC3; + VP8Transform = TransformTwo; + + VP8VFilter16 = VFilter16; + VP8HFilter16 = HFilter16; + VP8VFilter8 = VFilter8; + VP8HFilter8 = HFilter8; + VP8VFilter16i = VFilter16i; + VP8HFilter16i = HFilter16i; + VP8VFilter8i = VFilter8i; + VP8HFilter8i = HFilter8i; + VP8SimpleVFilter16 = SimpleVFilter16; + VP8SimpleHFilter16 = SimpleHFilter16; + VP8SimpleVFilter16i = SimpleVFilter16i; + VP8SimpleHFilter16i = SimpleHFilter16i; + + VP8PredLuma4[0] = DC4; + VP8PredLuma4[1] = TrueMotion4; + VP8PredLuma4[2] = VE4; + VP8PredLuma4[4] = RD4; + VP8PredLuma4[6] = LD4; + + VP8PredChroma8[0] = DC8uv; + VP8PredChroma8[1] = TrueMotion8; + VP8PredChroma8[4] = DC8uvNoTop; + VP8PredChroma8[5] = DC8uvNoLeft; + + VP8PredLuma16[1] = TrueMotion16; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8DspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/dec_msa.c b/libraries/webp/src/dsp/dec_msa.c new file mode 100644 index 0000000000..58d1730192 --- /dev/null +++ b/libraries/webp/src/dsp/dec_msa.c @@ -0,0 +1,1018 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA version of dsp functions +// +// Author(s): Prashant Patil (prashant.patil@imgtec.com) + + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/msa_macro.h" + +//------------------------------------------------------------------------------ +// Transforms + +#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) { \ + v4i32 a1_m, b1_m, c1_m, d1_m; \ + v4i32 c_tmp1_m, c_tmp2_m, d_tmp1_m, d_tmp2_m; \ + const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \ + const v4i32 sinpi8sqrt2 = __msa_fill_w(35468); \ + \ + a1_m = in0 + in2; \ + b1_m = in0 - in2; \ + c_tmp1_m = (in1 * sinpi8sqrt2) >> 16; \ + c_tmp2_m = in3 + ((in3 * cospi8sqrt2minus1) >> 16); \ + c1_m = c_tmp1_m - c_tmp2_m; \ + d_tmp1_m = in1 + ((in1 * cospi8sqrt2minus1) >> 16); \ + d_tmp2_m = (in3 * sinpi8sqrt2) >> 16; \ + d1_m = d_tmp1_m + d_tmp2_m; \ + BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \ +} + +static void TransformOne(const int16_t* in, uint8_t* dst) { + v8i16 input0, input1; + v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3; + v4i32 res0, res1, res2, res3; + const v16i8 zero = { 0 }; + v16i8 dest0, dest1, dest2, dest3; + + LD_SH2(in, 8, input0, input1); + UNPCK_SH_SW(input0, in0, in1); + UNPCK_SH_SW(input1, in2, in3); + IDCT_1D_W(in0, in1, in2, in3, hz0, hz1, hz2, hz3); + TRANSPOSE4x4_SW_SW(hz0, hz1, hz2, hz3, hz0, hz1, hz2, hz3); + IDCT_1D_W(hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3); + SRARI_W4_SW(vt0, vt1, vt2, vt3, 3); + TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3); + LD_SB4(dst, BPS, dest0, dest1, dest2, dest3); + ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, + res0, res1, res2, res3); + ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, + res0, res1, res2, res3); + ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3); + CLIP_SW4_0_255(res0, res1, res2, res3); + PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1); + res0 = (v4i32)__msa_pckev_b((v16i8)vt0, (v16i8)vt1); + ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS); +} + +static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne(in, dst); + if (do_two) { + TransformOne(in + 16, dst + 4); + } +} + +static void TransformWHT(const int16_t* in, int16_t* out) { + v8i16 input0, input1; + const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 }; + const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 }; + const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 }; + const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 }; + v8i16 tmp0, tmp1, tmp2, tmp3; + v8i16 out0, out1; + + LD_SH2(in, 8, input0, input1); + input1 = SLDI_SH(input1, input1, 8); + tmp0 = input0 + input1; + tmp1 = input0 - input1; + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + out0 = tmp2 + tmp3; + out1 = tmp2 - tmp3; + VSHF_H2_SH(out0, out1, out0, out1, mask2, mask3, input0, input1); + tmp0 = input0 + input1; + tmp1 = input0 - input1; + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + tmp0 = tmp2 + tmp3; + tmp1 = tmp2 - tmp3; + ADDVI_H2_SH(tmp0, 3, tmp1, 3, out0, out1); + SRAI_H2_SH(out0, out1, 3); + out[0] = __msa_copy_s_h(out0, 0); + out[16] = __msa_copy_s_h(out0, 4); + out[32] = __msa_copy_s_h(out1, 0); + out[48] = __msa_copy_s_h(out1, 4); + out[64] = __msa_copy_s_h(out0, 1); + out[80] = __msa_copy_s_h(out0, 5); + out[96] = __msa_copy_s_h(out1, 1); + out[112] = __msa_copy_s_h(out1, 5); + out[128] = __msa_copy_s_h(out0, 2); + out[144] = __msa_copy_s_h(out0, 6); + out[160] = __msa_copy_s_h(out1, 2); + out[176] = __msa_copy_s_h(out1, 6); + out[192] = __msa_copy_s_h(out0, 3); + out[208] = __msa_copy_s_h(out0, 7); + out[224] = __msa_copy_s_h(out1, 3); + out[240] = __msa_copy_s_h(out1, 7); +} + +static void TransformDC(const int16_t* in, uint8_t* dst) { + const int DC = (in[0] + 4) >> 3; + const v8i16 tmp0 = __msa_fill_h(DC); + ADDBLK_ST4x4_UB(tmp0, tmp0, tmp0, tmp0, dst, BPS); +} + +static void TransformAC3(const int16_t* in, uint8_t* dst) { + const int a = in[0] + 4; + const int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int in2 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int in3 = WEBP_TRANSFORM_AC3_MUL1(in[1]); + v4i32 tmp0 = { 0 }; + v4i32 out0 = __msa_fill_w(a + d4); + v4i32 out1 = __msa_fill_w(a + c4); + v4i32 out2 = __msa_fill_w(a - c4); + v4i32 out3 = __msa_fill_w(a - d4); + v4i32 res0, res1, res2, res3; + const v4i32 zero = { 0 }; + v16u8 dest0, dest1, dest2, dest3; + + INSERT_W4_SW(in3, in2, -in2, -in3, tmp0); + ADD4(out0, tmp0, out1, tmp0, out2, tmp0, out3, tmp0, + out0, out1, out2, out3); + SRAI_W4_SW(out0, out1, out2, out3, 3); + LD_UB4(dst, BPS, dest0, dest1, dest2, dest3); + ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, + res0, res1, res2, res3); + ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, + res0, res1, res2, res3); + ADD4(res0, out0, res1, out1, res2, out2, res3, out3, res0, res1, res2, res3); + CLIP_SW4_0_255(res0, res1, res2, res3); + PCKEV_B2_SW(res0, res1, res2, res3, out0, out1); + res0 = (v4i32)__msa_pckev_b((v16i8)out0, (v16i8)out1); + ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS); +} + +//------------------------------------------------------------------------------ +// Edge filtering functions + +#define FLIP_SIGN2(in0, in1, out0, out1) { \ + out0 = (v16i8)__msa_xori_b(in0, 0x80); \ + out1 = (v16i8)__msa_xori_b(in1, 0x80); \ +} + +#define FLIP_SIGN4(in0, in1, in2, in3, out0, out1, out2, out3) { \ + FLIP_SIGN2(in0, in1, out0, out1); \ + FLIP_SIGN2(in2, in3, out2, out3); \ +} + +#define FILT_VAL(q0_m, p0_m, mask, filt) do { \ + v16i8 q0_sub_p0; \ + q0_sub_p0 = __msa_subs_s_b(q0_m, p0_m); \ + filt = __msa_adds_s_b(filt, q0_sub_p0); \ + filt = __msa_adds_s_b(filt, q0_sub_p0); \ + filt = __msa_adds_s_b(filt, q0_sub_p0); \ + filt = filt & mask; \ +} while (0) + +#define FILT2(q_m, p_m, q, p) do { \ + u_r = SRAI_H(temp1, 7); \ + u_r = __msa_sat_s_h(u_r, 7); \ + u_l = SRAI_H(temp3, 7); \ + u_l = __msa_sat_s_h(u_l, 7); \ + u = __msa_pckev_b((v16i8)u_l, (v16i8)u_r); \ + q_m = __msa_subs_s_b(q_m, u); \ + p_m = __msa_adds_s_b(p_m, u); \ + q = __msa_xori_b((v16u8)q_m, 0x80); \ + p = __msa_xori_b((v16u8)p_m, 0x80); \ +} while (0) + +#define LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev) do { \ + v16i8 p1_m, p0_m, q0_m, q1_m; \ + v16i8 filt, t1, t2; \ + const v16i8 cnst4b = __msa_ldi_b(4); \ + const v16i8 cnst3b = __msa_ldi_b(3); \ + \ + FLIP_SIGN4(p1, p0, q0, q1, p1_m, p0_m, q0_m, q1_m); \ + filt = __msa_subs_s_b(p1_m, q1_m); \ + filt = filt & hev; \ + FILT_VAL(q0_m, p0_m, mask, filt); \ + t1 = __msa_adds_s_b(filt, cnst4b); \ + t1 = SRAI_B(t1, 3); \ + t2 = __msa_adds_s_b(filt, cnst3b); \ + t2 = SRAI_B(t2, 3); \ + q0_m = __msa_subs_s_b(q0_m, t1); \ + q0 = __msa_xori_b((v16u8)q0_m, 0x80); \ + p0_m = __msa_adds_s_b(p0_m, t2); \ + p0 = __msa_xori_b((v16u8)p0_m, 0x80); \ + filt = __msa_srari_b(t1, 1); \ + hev = __msa_xori_b(hev, 0xff); \ + filt = filt & hev; \ + q1_m = __msa_subs_s_b(q1_m, filt); \ + q1 = __msa_xori_b((v16u8)q1_m, 0x80); \ + p1_m = __msa_adds_s_b(p1_m, filt); \ + p1 = __msa_xori_b((v16u8)p1_m, 0x80); \ +} while (0) + +#define LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev) do { \ + v16i8 p2_m, p1_m, p0_m, q2_m, q1_m, q0_m; \ + v16i8 u, filt, t1, t2, filt_sign; \ + v8i16 filt_r, filt_l, u_r, u_l; \ + v8i16 temp0, temp1, temp2, temp3; \ + const v16i8 cnst4b = __msa_ldi_b(4); \ + const v16i8 cnst3b = __msa_ldi_b(3); \ + const v8i16 cnst9h = __msa_ldi_h(9); \ + const v8i16 cnst63h = __msa_ldi_h(63); \ + \ + FLIP_SIGN4(p1, p0, q0, q1, p1_m, p0_m, q0_m, q1_m); \ + filt = __msa_subs_s_b(p1_m, q1_m); \ + FILT_VAL(q0_m, p0_m, mask, filt); \ + FLIP_SIGN2(p2, q2, p2_m, q2_m); \ + t2 = filt & hev; \ + /* filt_val &= ~hev */ \ + hev = __msa_xori_b(hev, 0xff); \ + filt = filt & hev; \ + t1 = __msa_adds_s_b(t2, cnst4b); \ + t1 = SRAI_B(t1, 3); \ + t2 = __msa_adds_s_b(t2, cnst3b); \ + t2 = SRAI_B(t2, 3); \ + q0_m = __msa_subs_s_b(q0_m, t1); \ + p0_m = __msa_adds_s_b(p0_m, t2); \ + filt_sign = __msa_clti_s_b(filt, 0); \ + ILVRL_B2_SH(filt_sign, filt, filt_r, filt_l); \ + /* update q2/p2 */ \ + temp0 = filt_r * cnst9h; \ + temp1 = temp0 + cnst63h; \ + temp2 = filt_l * cnst9h; \ + temp3 = temp2 + cnst63h; \ + FILT2(q2_m, p2_m, q2, p2); \ + /* update q1/p1 */ \ + temp1 = temp1 + temp0; \ + temp3 = temp3 + temp2; \ + FILT2(q1_m, p1_m, q1, p1); \ + /* update q0/p0 */ \ + temp1 = temp1 + temp0; \ + temp3 = temp3 + temp2; \ + FILT2(q0_m, p0_m, q0, p0); \ +} while (0) + +#define LPF_MASK_HEV(p3_in, p2_in, p1_in, p0_in, \ + q0_in, q1_in, q2_in, q3_in, \ + limit_in, b_limit_in, thresh_in, \ + hev_out, mask_out) do { \ + v16u8 p3_asub_p2_m, p2_asub_p1_m, p1_asub_p0_m, q1_asub_q0_m; \ + v16u8 p1_asub_q1_m, p0_asub_q0_m, q3_asub_q2_m, q2_asub_q1_m; \ + v16u8 flat_out; \ + \ + /* absolute subtraction of pixel values */ \ + p3_asub_p2_m = __msa_asub_u_b(p3_in, p2_in); \ + p2_asub_p1_m = __msa_asub_u_b(p2_in, p1_in); \ + p1_asub_p0_m = __msa_asub_u_b(p1_in, p0_in); \ + q1_asub_q0_m = __msa_asub_u_b(q1_in, q0_in); \ + q2_asub_q1_m = __msa_asub_u_b(q2_in, q1_in); \ + q3_asub_q2_m = __msa_asub_u_b(q3_in, q2_in); \ + p0_asub_q0_m = __msa_asub_u_b(p0_in, q0_in); \ + p1_asub_q1_m = __msa_asub_u_b(p1_in, q1_in); \ + /* calculation of hev */ \ + flat_out = __msa_max_u_b(p1_asub_p0_m, q1_asub_q0_m); \ + hev_out = (thresh_in < flat_out); \ + /* calculation of mask */ \ + p0_asub_q0_m = __msa_adds_u_b(p0_asub_q0_m, p0_asub_q0_m); \ + p1_asub_q1_m = SRAI_B(p1_asub_q1_m, 1); \ + p0_asub_q0_m = __msa_adds_u_b(p0_asub_q0_m, p1_asub_q1_m); \ + mask_out = (b_limit_in < p0_asub_q0_m); \ + mask_out = __msa_max_u_b(flat_out, mask_out); \ + p3_asub_p2_m = __msa_max_u_b(p3_asub_p2_m, p2_asub_p1_m); \ + mask_out = __msa_max_u_b(p3_asub_p2_m, mask_out); \ + q2_asub_q1_m = __msa_max_u_b(q2_asub_q1_m, q3_asub_q2_m); \ + mask_out = __msa_max_u_b(q2_asub_q1_m, mask_out); \ + mask_out = (limit_in < mask_out); \ + mask_out = __msa_xori_b(mask_out, 0xff); \ +} while (0) + +#define ST6x1_UB(in0, in0_idx, in1, in1_idx, pdst, stride) do { \ + const uint16_t tmp0_h = __msa_copy_s_h((v8i16)in1, in1_idx); \ + const uint32_t tmp0_w = __msa_copy_s_w((v4i32)in0, in0_idx); \ + SW(tmp0_w, pdst); \ + SH(tmp0_h, pdst + stride); \ +} while (0) + +#define ST6x4_UB(in0, start_in0_idx, in1, start_in1_idx, pdst, stride) do { \ + uint8_t* ptmp1 = (uint8_t*)pdst; \ + ST6x1_UB(in0, start_in0_idx, in1, start_in1_idx, ptmp1, 4); \ + ptmp1 += stride; \ + ST6x1_UB(in0, start_in0_idx + 1, in1, start_in1_idx + 1, ptmp1, 4); \ + ptmp1 += stride; \ + ST6x1_UB(in0, start_in0_idx + 2, in1, start_in1_idx + 2, ptmp1, 4); \ + ptmp1 += stride; \ + ST6x1_UB(in0, start_in0_idx + 3, in1, start_in1_idx + 3, ptmp1, 4); \ +} while (0) + +#define LPF_SIMPLE_FILT(p1_in, p0_in, q0_in, q1_in, mask) do { \ + v16i8 p1_m, p0_m, q0_m, q1_m, filt, filt1, filt2; \ + const v16i8 cnst4b = __msa_ldi_b(4); \ + const v16i8 cnst3b = __msa_ldi_b(3); \ + \ + FLIP_SIGN4(p1_in, p0_in, q0_in, q1_in, p1_m, p0_m, q0_m, q1_m); \ + filt = __msa_subs_s_b(p1_m, q1_m); \ + FILT_VAL(q0_m, p0_m, mask, filt); \ + filt1 = __msa_adds_s_b(filt, cnst4b); \ + filt1 = SRAI_B(filt1, 3); \ + filt2 = __msa_adds_s_b(filt, cnst3b); \ + filt2 = SRAI_B(filt2, 3); \ + q0_m = __msa_subs_s_b(q0_m, filt1); \ + p0_m = __msa_adds_s_b(p0_m, filt2); \ + q0_in = __msa_xori_b((v16u8)q0_m, 0x80); \ + p0_in = __msa_xori_b((v16u8)p0_m, 0x80); \ +} while (0) + +#define LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask) do { \ + v16u8 p1_a_sub_q1, p0_a_sub_q0; \ + \ + p0_a_sub_q0 = __msa_asub_u_b(p0, q0); \ + p1_a_sub_q1 = __msa_asub_u_b(p1, q1); \ + p1_a_sub_q1 = (v16u8)__msa_srli_b((v16i8)p1_a_sub_q1, 1); \ + p0_a_sub_q0 = __msa_adds_u_b(p0_a_sub_q0, p0_a_sub_q0); \ + mask = __msa_adds_u_b(p0_a_sub_q0, p1_a_sub_q1); \ + mask = (mask <= b_limit); \ +} while (0) + +static void VFilter16(uint8_t* src, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint8_t* ptemp = src - 4 * stride; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0; + v16u8 mask, hev; + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + + LD_UB8(ptemp, stride, p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + ptemp = src - 3 * stride; + ST_UB4(p2, p1, p0, q0, ptemp, stride); + ptemp += (4 * stride); + ST_UB2(q1, q2, ptemp, stride); +} + +static void HFilter16(uint8_t* src, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint8_t* ptmp = src - 4; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0; + v16u8 mask, hev; + v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8; + v16u8 row9, row10, row11, row12, row13, row14, row15; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + + LD_UB8(ptmp, stride, row0, row1, row2, row3, row4, row5, row6, row7); + ptmp += (8 * stride); + LD_UB8(ptmp, stride, row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4); + ILVL_B2_SH(p1, p2, q0, p0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp6, tmp7); + ILVRL_B2_SH(q2, q1, tmp2, tmp5); + ptmp = src - 3; + ST6x1_UB(tmp3, 0, tmp2, 0, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp3, 1, tmp2, 1, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp3, 2, tmp2, 2, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp3, 3, tmp2, 3, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp4, 0, tmp2, 4, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp4, 1, tmp2, 5, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp4, 2, tmp2, 6, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp4, 3, tmp2, 7, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp6, 0, tmp5, 0, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp6, 1, tmp5, 1, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp6, 2, tmp5, 2, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp6, 3, tmp5, 3, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp7, 0, tmp5, 4, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp7, 1, tmp5, 5, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp7, 2, tmp5, 6, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp7, 3, tmp5, 7, ptmp, 4); +} + +// on three inner edges +static void VFilterHorEdge16i(uint8_t* src, int stride, + int b_limit, int limit, int thresh) { + v16u8 mask, hev; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0; + const v16u8 thresh0 = (v16u8)__msa_fill_b(thresh); + const v16u8 b_limit0 = (v16u8)__msa_fill_b(b_limit); + const v16u8 limit0 = (v16u8)__msa_fill_b(limit); + + LD_UB8((src - 4 * stride), stride, p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, + hev, mask); + LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + ST_UB4(p1, p0, q0, q1, (src - 2 * stride), stride); +} + +static void VFilter16i(uint8_t* src_y, int stride, + int b_limit, int limit, int thresh) { + VFilterHorEdge16i(src_y + 4 * stride, stride, b_limit, limit, thresh); + VFilterHorEdge16i(src_y + 8 * stride, stride, b_limit, limit, thresh); + VFilterHorEdge16i(src_y + 12 * stride, stride, b_limit, limit, thresh); +} + +static void HFilterVertEdge16i(uint8_t* src, int stride, + int b_limit, int limit, int thresh) { + v16u8 mask, hev; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0; + v16u8 row0, row1, row2, row3, row4, row5, row6, row7; + v16u8 row8, row9, row10, row11, row12, row13, row14, row15; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + const v16u8 thresh0 = (v16u8)__msa_fill_b(thresh); + const v16u8 b_limit0 = (v16u8)__msa_fill_b(b_limit); + const v16u8 limit0 = (v16u8)__msa_fill_b(limit); + + LD_UB8(src - 4, stride, row0, row1, row2, row3, row4, row5, row6, row7); + LD_UB8(src - 4 + (8 * stride), stride, + row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, + hev, mask); + LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + ILVR_B2_SH(p0, p1, q1, q0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp2, tmp3); + ILVL_B2_SH(p0, p1, q1, q0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp4, tmp5); + src -= 2; + ST4x8_UB(tmp2, tmp3, src, stride); + src += (8 * stride); + ST4x8_UB(tmp4, tmp5, src, stride); +} + +static void HFilter16i(uint8_t* src_y, int stride, + int b_limit, int limit, int thresh) { + HFilterVertEdge16i(src_y + 4, stride, b_limit, limit, thresh); + HFilterVertEdge16i(src_y + 8, stride, b_limit, limit, thresh); + HFilterVertEdge16i(src_y + 12, stride, b_limit, limit, thresh); +} + +// 8-pixels wide variants, for chroma filtering +static void VFilter8(uint8_t* src_u, uint8_t* src_v, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint8_t* ptmp_src_u = src_u - 4 * stride; + uint8_t* ptmp_src_v = src_v - 4 * stride; + uint64_t p2_d, p1_d, p0_d, q0_d, q1_d, q2_d; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev; + v16u8 p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u; + v16u8 p3_v, p2_v, p1_v, p0_v, q3_v, q2_v, q1_v, q0_v; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + + LD_UB8(ptmp_src_u, stride, p3_u, p2_u, p1_u, p0_u, q0_u, q1_u, q2_u, q3_u); + LD_UB8(ptmp_src_v, stride, p3_v, p2_v, p1_v, p0_v, q0_v, q1_v, q2_v, q3_v); + ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0); + ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + p2_d = __msa_copy_s_d((v2i64)p2, 0); + p1_d = __msa_copy_s_d((v2i64)p1, 0); + p0_d = __msa_copy_s_d((v2i64)p0, 0); + q0_d = __msa_copy_s_d((v2i64)q0, 0); + q1_d = __msa_copy_s_d((v2i64)q1, 0); + q2_d = __msa_copy_s_d((v2i64)q2, 0); + ptmp_src_u += stride; + SD4(p2_d, p1_d, p0_d, q0_d, ptmp_src_u, stride); + ptmp_src_u += (4 * stride); + SD(q1_d, ptmp_src_u); + ptmp_src_u += stride; + SD(q2_d, ptmp_src_u); + p2_d = __msa_copy_s_d((v2i64)p2, 1); + p1_d = __msa_copy_s_d((v2i64)p1, 1); + p0_d = __msa_copy_s_d((v2i64)p0, 1); + q0_d = __msa_copy_s_d((v2i64)q0, 1); + q1_d = __msa_copy_s_d((v2i64)q1, 1); + q2_d = __msa_copy_s_d((v2i64)q2, 1); + ptmp_src_v += stride; + SD4(p2_d, p1_d, p0_d, q0_d, ptmp_src_v, stride); + ptmp_src_v += (4 * stride); + SD(q1_d, ptmp_src_v); + ptmp_src_v += stride; + SD(q2_d, ptmp_src_v); +} + +static void HFilter8(uint8_t* src_u, uint8_t* src_v, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint8_t* ptmp_src_u = src_u - 4; + uint8_t* ptmp_src_v = src_v - 4; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev; + v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8; + v16u8 row9, row10, row11, row12, row13, row14, row15; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + + LD_UB8(ptmp_src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7); + LD_UB8(ptmp_src_v, stride, + row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4); + ILVL_B2_SH(p1, p2, q0, p0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp6, tmp7); + ILVRL_B2_SH(q2, q1, tmp2, tmp5); + ptmp_src_u += 1; + ST6x4_UB(tmp3, 0, tmp2, 0, ptmp_src_u, stride); + ptmp_src_u += 4 * stride; + ST6x4_UB(tmp4, 0, tmp2, 4, ptmp_src_u, stride); + ptmp_src_v += 1; + ST6x4_UB(tmp6, 0, tmp5, 0, ptmp_src_v, stride); + ptmp_src_v += 4 * stride; + ST6x4_UB(tmp7, 0, tmp5, 4, ptmp_src_v, stride); +} + +static void VFilter8i(uint8_t* src_u, uint8_t* src_v, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint64_t p1_d, p0_d, q0_d, q1_d; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev; + v16u8 p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u; + v16u8 p3_v, p2_v, p1_v, p0_v, q3_v, q2_v, q1_v, q0_v; + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + + LD_UB8(src_u, stride, p3_u, p2_u, p1_u, p0_u, q0_u, q1_u, q2_u, q3_u); + src_u += (5 * stride); + LD_UB8(src_v, stride, p3_v, p2_v, p1_v, p0_v, q0_v, q1_v, q2_v, q3_v); + src_v += (5 * stride); + ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0); + ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + p1_d = __msa_copy_s_d((v2i64)p1, 0); + p0_d = __msa_copy_s_d((v2i64)p0, 0); + q0_d = __msa_copy_s_d((v2i64)q0, 0); + q1_d = __msa_copy_s_d((v2i64)q1, 0); + SD4(q1_d, q0_d, p0_d, p1_d, src_u, -stride); + p1_d = __msa_copy_s_d((v2i64)p1, 1); + p0_d = __msa_copy_s_d((v2i64)p0, 1); + q0_d = __msa_copy_s_d((v2i64)q0, 1); + q1_d = __msa_copy_s_d((v2i64)q1, 1); + SD4(q1_d, q0_d, p0_d, p1_d, src_v, -stride); +} + +static void HFilter8i(uint8_t* src_u, uint8_t* src_v, int stride, + int b_limit_in, int limit_in, int thresh_in) { + v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev; + v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8; + v16u8 row9, row10, row11, row12, row13, row14, row15; + v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + + LD_UB8(src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7); + LD_UB8(src_v, stride, + row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + ILVR_B2_SW(p0, p1, q1, q0, tmp0, tmp1); + ILVRL_H2_SW(tmp1, tmp0, tmp2, tmp3); + ILVL_B2_SW(p0, p1, q1, q0, tmp0, tmp1); + ILVRL_H2_SW(tmp1, tmp0, tmp4, tmp5); + src_u += 2; + ST4x4_UB(tmp2, tmp2, 0, 1, 2, 3, src_u, stride); + src_u += 4 * stride; + ST4x4_UB(tmp3, tmp3, 0, 1, 2, 3, src_u, stride); + src_v += 2; + ST4x4_UB(tmp4, tmp4, 0, 1, 2, 3, src_v, stride); + src_v += 4 * stride; + ST4x4_UB(tmp5, tmp5, 0, 1, 2, 3, src_v, stride); +} + +static void SimpleVFilter16(uint8_t* src, int stride, int b_limit_in) { + v16u8 p1, p0, q1, q0, mask; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + + LD_UB4(src - 2 * stride, stride, p1, p0, q0, q1); + LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask); + LPF_SIMPLE_FILT(p1, p0, q0, q1, mask); + ST_UB2(p0, q0, src - stride, stride); +} + +static void SimpleHFilter16(uint8_t* src, int stride, int b_limit_in) { + v16u8 p1, p0, q1, q0, mask, row0, row1, row2, row3, row4, row5, row6, row7; + v16u8 row8, row9, row10, row11, row12, row13, row14, row15; + v8i16 tmp0, tmp1; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + uint8_t* ptemp_src = src - 2; + + LD_UB8(ptemp_src, stride, row0, row1, row2, row3, row4, row5, row6, row7); + LD_UB8(ptemp_src + 8 * stride, stride, + row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x4_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p1, p0, q0, q1); + LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask); + LPF_SIMPLE_FILT(p1, p0, q0, q1, mask); + ILVRL_B2_SH(q0, p0, tmp1, tmp0); + ptemp_src += 1; + ST2x4_UB(tmp1, 0, ptemp_src, stride); + ptemp_src += 4 * stride; + ST2x4_UB(tmp1, 4, ptemp_src, stride); + ptemp_src += 4 * stride; + ST2x4_UB(tmp0, 0, ptemp_src, stride); + ptemp_src += 4 * stride; + ST2x4_UB(tmp0, 4, ptemp_src, stride); + ptemp_src += 4 * stride; +} + +static void SimpleVFilter16i(uint8_t* src_y, int stride, int b_limit_in) { + SimpleVFilter16(src_y + 4 * stride, stride, b_limit_in); + SimpleVFilter16(src_y + 8 * stride, stride, b_limit_in); + SimpleVFilter16(src_y + 12 * stride, stride, b_limit_in); +} + +static void SimpleHFilter16i(uint8_t* src_y, int stride, int b_limit_in) { + SimpleHFilter16(src_y + 4, stride, b_limit_in); + SimpleHFilter16(src_y + 8, stride, b_limit_in); + SimpleHFilter16(src_y + 12, stride, b_limit_in); +} + +//------------------------------------------------------------------------------ +// Intra predictions +//------------------------------------------------------------------------------ + +// 4x4 + +static void DC4(uint8_t* dst) { // DC + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS]; + dc >>= 3; + dc = dc | (dc << 8) | (dc << 16) | (dc << 24); + SW4(dc, dc, dc, dc, dst, BPS); +} + +static void TM4(uint8_t* dst) { + const uint8_t* const ptemp = dst - BPS - 1; + v8i16 T, d, r0, r1, r2, r3; + const v16i8 zero = { 0 }; + const v8i16 TL = (v8i16)__msa_fill_h(ptemp[0 * BPS]); + const v8i16 L0 = (v8i16)__msa_fill_h(ptemp[1 * BPS]); + const v8i16 L1 = (v8i16)__msa_fill_h(ptemp[2 * BPS]); + const v8i16 L2 = (v8i16)__msa_fill_h(ptemp[3 * BPS]); + const v8i16 L3 = (v8i16)__msa_fill_h(ptemp[4 * BPS]); + const v16u8 T1 = LD_UB(ptemp + 1); + + T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1); + d = T - TL; + ADD4(d, L0, d, L1, d, L2, d, L3, r0, r1, r2, r3); + CLIP_SH4_0_255(r0, r1, r2, r3); + PCKEV_ST4x4_UB(r0, r1, r2, r3, dst, BPS); +} + +static void VE4(uint8_t* dst) { // vertical + const uint8_t* const ptop = dst - BPS - 1; + const uint32_t val0 = LW(ptop + 0); + const uint32_t val1 = LW(ptop + 4); + uint32_t out; + v16u8 A = { 0 }, B, C, AC, B2, R; + + INSERT_W2_UB(val0, val1, A); + B = SLDI_UB(A, A, 1); + C = SLDI_UB(A, A, 2); + AC = __msa_ave_u_b(A, C); + B2 = __msa_ave_u_b(B, B); + R = __msa_aver_u_b(AC, B2); + out = __msa_copy_s_w((v4i32)R, 0); + SW4(out, out, out, out, dst, BPS); +} + +static void RD4(uint8_t* dst) { // Down-right + const uint8_t* const ptop = dst - 1 - BPS; + uint32_t val0 = LW(ptop + 0); + uint32_t val1 = LW(ptop + 4); + uint32_t val2, val3; + v16u8 A, B, C, AC, B2, R, A1 = { 0 }; + + INSERT_W2_UB(val0, val1, A1); + A = SLDI_UB(A1, A1, 12); + A = (v16u8)__msa_insert_b((v16i8)A, 3, ptop[1 * BPS]); + A = (v16u8)__msa_insert_b((v16i8)A, 2, ptop[2 * BPS]); + A = (v16u8)__msa_insert_b((v16i8)A, 1, ptop[3 * BPS]); + A = (v16u8)__msa_insert_b((v16i8)A, 0, ptop[4 * BPS]); + B = SLDI_UB(A, A, 1); + C = SLDI_UB(A, A, 2); + AC = __msa_ave_u_b(A, C); + B2 = __msa_ave_u_b(B, B); + R = __msa_aver_u_b(AC, B2); + val3 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val2 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val1 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val0 = __msa_copy_s_w((v4i32)R, 0); + SW4(val0, val1, val2, val3, dst, BPS); +} + +static void LD4(uint8_t* dst) { // Down-Left + const uint8_t* const ptop = dst - BPS; + uint32_t val0 = LW(ptop + 0); + uint32_t val1 = LW(ptop + 4); + uint32_t val2, val3; + v16u8 A = { 0 }, B, C, AC, B2, R; + + INSERT_W2_UB(val0, val1, A); + B = SLDI_UB(A, A, 1); + C = SLDI_UB(A, A, 2); + C = (v16u8)__msa_insert_b((v16i8)C, 6, ptop[7]); + AC = __msa_ave_u_b(A, C); + B2 = __msa_ave_u_b(B, B); + R = __msa_aver_u_b(AC, B2); + val0 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val1 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val2 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val3 = __msa_copy_s_w((v4i32)R, 0); + SW4(val0, val1, val2, val3, dst, BPS); +} + +// 16x16 + +static void DC16(uint8_t* dst) { // DC + uint32_t dc = 16; + int i; + const v16u8 rtop = LD_UB(dst - BPS); + const v8u16 dctop = __msa_hadd_u_h(rtop, rtop); + v16u8 out; + + for (i = 0; i < 16; ++i) { + dc += dst[-1 + i * BPS]; + } + dc += HADD_UH_U32(dctop); + out = (v16u8)__msa_fill_b(dc >> 5); + ST_UB8(out, out, out, out, out, out, out, out, dst, BPS); + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); +} + +static void TM16(uint8_t* dst) { + int j; + v8i16 d1, d2; + const v16i8 zero = { 0 }; + const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]); + const v16i8 T = LD_SB(dst - BPS); + + ILVRL_B2_SH(zero, T, d1, d2); + SUB2(d1, TL, d2, TL, d1, d2); + for (j = 0; j < 16; j += 4) { + v16i8 t0, t1, t2, t3; + v8i16 r0, r1, r2, r3, r4, r5, r6, r7; + const v8i16 L0 = (v8i16)__msa_fill_h(dst[-1 + 0 * BPS]); + const v8i16 L1 = (v8i16)__msa_fill_h(dst[-1 + 1 * BPS]); + const v8i16 L2 = (v8i16)__msa_fill_h(dst[-1 + 2 * BPS]); + const v8i16 L3 = (v8i16)__msa_fill_h(dst[-1 + 3 * BPS]); + ADD4(d1, L0, d1, L1, d1, L2, d1, L3, r0, r1, r2, r3); + ADD4(d2, L0, d2, L1, d2, L2, d2, L3, r4, r5, r6, r7); + CLIP_SH4_0_255(r0, r1, r2, r3); + CLIP_SH4_0_255(r4, r5, r6, r7); + PCKEV_B4_SB(r4, r0, r5, r1, r6, r2, r7, r3, t0, t1, t2, t3); + ST_SB4(t0, t1, t2, t3, dst, BPS); + dst += 4 * BPS; + } +} + +static void VE16(uint8_t* dst) { // vertical + const v16u8 rtop = LD_UB(dst - BPS); + ST_UB8(rtop, rtop, rtop, rtop, rtop, rtop, rtop, rtop, dst, BPS); + ST_UB8(rtop, rtop, rtop, rtop, rtop, rtop, rtop, rtop, dst + 8 * BPS, BPS); +} + +static void HE16(uint8_t* dst) { // horizontal + int j; + for (j = 16; j > 0; j -= 4) { + const v16u8 L0 = (v16u8)__msa_fill_b(dst[-1 + 0 * BPS]); + const v16u8 L1 = (v16u8)__msa_fill_b(dst[-1 + 1 * BPS]); + const v16u8 L2 = (v16u8)__msa_fill_b(dst[-1 + 2 * BPS]); + const v16u8 L3 = (v16u8)__msa_fill_b(dst[-1 + 3 * BPS]); + ST_UB4(L0, L1, L2, L3, dst, BPS); + dst += 4 * BPS; + } +} + +static void DC16NoTop(uint8_t* dst) { // DC with top samples not available + int j; + uint32_t dc = 8; + v16u8 out; + + for (j = 0; j < 16; ++j) { + dc += dst[-1 + j * BPS]; + } + out = (v16u8)__msa_fill_b(dc >> 4); + ST_UB8(out, out, out, out, out, out, out, out, dst, BPS); + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); +} + +static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available + uint32_t dc = 8; + const v16u8 rtop = LD_UB(dst - BPS); + const v8u16 dctop = __msa_hadd_u_h(rtop, rtop); + v16u8 out; + + dc += HADD_UH_U32(dctop); + out = (v16u8)__msa_fill_b(dc >> 4); + ST_UB8(out, out, out, out, out, out, out, out, dst, BPS); + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); +} + +static void DC16NoTopLeft(uint8_t* dst) { // DC with nothing + const v16u8 out = (v16u8)__msa_fill_b(0x80); + ST_UB8(out, out, out, out, out, out, out, out, dst, BPS); + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); +} + +// Chroma + +#define STORE8x8(out, dst) do { \ + SD4(out, out, out, out, dst + 0 * BPS, BPS); \ + SD4(out, out, out, out, dst + 4 * BPS, BPS); \ +} while (0) + +static void DC8uv(uint8_t* dst) { // DC + uint32_t dc = 8; + int i; + uint64_t out; + const v16u8 rtop = LD_UB(dst - BPS); + const v8u16 temp0 = __msa_hadd_u_h(rtop, rtop); + const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); + const v2u64 temp2 = __msa_hadd_u_d(temp1, temp1); + v16u8 dctemp; + + for (i = 0; i < 8; ++i) { + dc += dst[-1 + i * BPS]; + } + dc += __msa_copy_s_w((v4i32)temp2, 0); + dctemp = (v16u8)__msa_fill_b(dc >> 4); + out = __msa_copy_s_d((v2i64)dctemp, 0); + STORE8x8(out, dst); +} + +static void TM8uv(uint8_t* dst) { + int j; + const v16i8 T1 = LD_SB(dst - BPS); + const v16i8 zero = { 0 }; + const v8i16 T = (v8i16)__msa_ilvr_b(zero, T1); + const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]); + const v8i16 d = T - TL; + + for (j = 0; j < 8; j += 4) { + v16i8 t0, t1; + v8i16 r0 = (v8i16)__msa_fill_h(dst[-1 + 0 * BPS]); + v8i16 r1 = (v8i16)__msa_fill_h(dst[-1 + 1 * BPS]); + v8i16 r2 = (v8i16)__msa_fill_h(dst[-1 + 2 * BPS]); + v8i16 r3 = (v8i16)__msa_fill_h(dst[-1 + 3 * BPS]); + ADD4(d, r0, d, r1, d, r2, d, r3, r0, r1, r2, r3); + CLIP_SH4_0_255(r0, r1, r2, r3); + PCKEV_B2_SB(r1, r0, r3, r2, t0, t1); + ST4x4_UB(t0, t1, 0, 2, 0, 2, dst, BPS); + ST4x4_UB(t0, t1, 1, 3, 1, 3, dst + 4, BPS); + dst += 4 * BPS; + } +} + +static void VE8uv(uint8_t* dst) { // vertical + const v16u8 rtop = LD_UB(dst - BPS); + const uint64_t out = __msa_copy_s_d((v2i64)rtop, 0); + STORE8x8(out, dst); +} + +static void HE8uv(uint8_t* dst) { // horizontal + int j; + for (j = 0; j < 8; j += 4) { + const v16u8 L0 = (v16u8)__msa_fill_b(dst[-1 + 0 * BPS]); + const v16u8 L1 = (v16u8)__msa_fill_b(dst[-1 + 1 * BPS]); + const v16u8 L2 = (v16u8)__msa_fill_b(dst[-1 + 2 * BPS]); + const v16u8 L3 = (v16u8)__msa_fill_b(dst[-1 + 3 * BPS]); + const uint64_t out0 = __msa_copy_s_d((v2i64)L0, 0); + const uint64_t out1 = __msa_copy_s_d((v2i64)L1, 0); + const uint64_t out2 = __msa_copy_s_d((v2i64)L2, 0); + const uint64_t out3 = __msa_copy_s_d((v2i64)L3, 0); + SD4(out0, out1, out2, out3, dst, BPS); + dst += 4 * BPS; + } +} + +static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples + const uint32_t dc = 4; + const v16u8 rtop = LD_UB(dst - BPS); + const v8u16 temp0 = __msa_hadd_u_h(rtop, rtop); + const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); + const v2u64 temp2 = __msa_hadd_u_d(temp1, temp1); + const uint32_t sum_m = __msa_copy_s_w((v4i32)temp2, 0); + const v16u8 dcval = (v16u8)__msa_fill_b((dc + sum_m) >> 3); + const uint64_t out = __msa_copy_s_d((v2i64)dcval, 0); + STORE8x8(out, dst); +} + +static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples + uint32_t dc = 4; + int i; + uint64_t out; + v16u8 dctemp; + + for (i = 0; i < 8; ++i) { + dc += dst[-1 + i * BPS]; + } + dctemp = (v16u8)__msa_fill_b(dc >> 3); + out = __msa_copy_s_d((v2i64)dctemp, 0); + STORE8x8(out, dst); +} + +static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing + const uint64_t out = 0x8080808080808080ULL; + STORE8x8(out, dst); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMSA(void) { + VP8TransformWHT = TransformWHT; + VP8Transform = TransformTwo; + VP8TransformDC = TransformDC; + VP8TransformAC3 = TransformAC3; + + VP8VFilter16 = VFilter16; + VP8HFilter16 = HFilter16; + VP8VFilter16i = VFilter16i; + VP8HFilter16i = HFilter16i; + VP8VFilter8 = VFilter8; + VP8HFilter8 = HFilter8; + VP8VFilter8i = VFilter8i; + VP8HFilter8i = HFilter8i; + VP8SimpleVFilter16 = SimpleVFilter16; + VP8SimpleHFilter16 = SimpleHFilter16; + VP8SimpleVFilter16i = SimpleVFilter16i; + VP8SimpleHFilter16i = SimpleHFilter16i; + + VP8PredLuma4[0] = DC4; + VP8PredLuma4[1] = TM4; + VP8PredLuma4[2] = VE4; + VP8PredLuma4[4] = RD4; + VP8PredLuma4[6] = LD4; + VP8PredLuma16[0] = DC16; + VP8PredLuma16[1] = TM16; + VP8PredLuma16[2] = VE16; + VP8PredLuma16[3] = HE16; + VP8PredLuma16[4] = DC16NoTop; + VP8PredLuma16[5] = DC16NoLeft; + VP8PredLuma16[6] = DC16NoTopLeft; + VP8PredChroma8[0] = DC8uv; + VP8PredChroma8[1] = TM8uv; + VP8PredChroma8[2] = VE8uv; + VP8PredChroma8[3] = HE8uv; + VP8PredChroma8[4] = DC8uvNoTop; + VP8PredChroma8[5] = DC8uvNoLeft; + VP8PredChroma8[6] = DC8uvNoTopLeft; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8DspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/libraries/webp/src/dsp/dec_neon.c b/libraries/webp/src/dsp/dec_neon.c new file mode 100644 index 0000000000..83b3a1f970 --- /dev/null +++ b/libraries/webp/src/dsp/dec_neon.c @@ -0,0 +1,1660 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// ARM NEON version of dsp functions and loop filtering. +// +// Authors: Somnath Banerjee (somnath@google.com) +// Johann Koenig (johannkoenig@google.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include "src/dsp/neon.h" +#include "src/dec/vp8i_dec.h" + +//------------------------------------------------------------------------------ +// NxM Loading functions + +#if !defined(WORK_AROUND_GCC) + +// This intrinsics version makes gcc-4.6.3 crash during Load4x??() compilation +// (register alloc, probably). The variants somewhat mitigate the problem, but +// not quite. HFilter16i() remains problematic. +static WEBP_INLINE uint8x8x4_t Load4x8_NEON(const uint8_t* const src, + int stride) { + const uint8x8_t zero = vdup_n_u8(0); + uint8x8x4_t out; + INIT_VECTOR4(out, zero, zero, zero, zero); + out = vld4_lane_u8(src + 0 * stride, out, 0); + out = vld4_lane_u8(src + 1 * stride, out, 1); + out = vld4_lane_u8(src + 2 * stride, out, 2); + out = vld4_lane_u8(src + 3 * stride, out, 3); + out = vld4_lane_u8(src + 4 * stride, out, 4); + out = vld4_lane_u8(src + 5 * stride, out, 5); + out = vld4_lane_u8(src + 6 * stride, out, 6); + out = vld4_lane_u8(src + 7 * stride, out, 7); + return out; +} + +static WEBP_INLINE void Load4x16_NEON(const uint8_t* const src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { + // row0 = p1[0..7]|p0[0..7]|q0[0..7]|q1[0..7] + // row8 = p1[8..15]|p0[8..15]|q0[8..15]|q1[8..15] + const uint8x8x4_t row0 = Load4x8_NEON(src - 2 + 0 * stride, stride); + const uint8x8x4_t row8 = Load4x8_NEON(src - 2 + 8 * stride, stride); + *p1 = vcombine_u8(row0.val[0], row8.val[0]); + *p0 = vcombine_u8(row0.val[1], row8.val[1]); + *q0 = vcombine_u8(row0.val[2], row8.val[2]); + *q1 = vcombine_u8(row0.val[3], row8.val[3]); +} + +#else // WORK_AROUND_GCC + +#define LOADQ_LANE_32b(VALUE, LANE) do { \ + (VALUE) = vld1q_lane_u32((const uint32_t*)src, (VALUE), (LANE)); \ + src += stride; \ +} while (0) + +static WEBP_INLINE void Load4x16_NEON(const uint8_t* src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { + const uint32x4_t zero = vdupq_n_u32(0); + uint32x4x4_t in; + INIT_VECTOR4(in, zero, zero, zero, zero); + src -= 2; + LOADQ_LANE_32b(in.val[0], 0); + LOADQ_LANE_32b(in.val[1], 0); + LOADQ_LANE_32b(in.val[2], 0); + LOADQ_LANE_32b(in.val[3], 0); + LOADQ_LANE_32b(in.val[0], 1); + LOADQ_LANE_32b(in.val[1], 1); + LOADQ_LANE_32b(in.val[2], 1); + LOADQ_LANE_32b(in.val[3], 1); + LOADQ_LANE_32b(in.val[0], 2); + LOADQ_LANE_32b(in.val[1], 2); + LOADQ_LANE_32b(in.val[2], 2); + LOADQ_LANE_32b(in.val[3], 2); + LOADQ_LANE_32b(in.val[0], 3); + LOADQ_LANE_32b(in.val[1], 3); + LOADQ_LANE_32b(in.val[2], 3); + LOADQ_LANE_32b(in.val[3], 3); + // Transpose four 4x4 parts: + { + const uint8x16x2_t row01 = vtrnq_u8(vreinterpretq_u8_u32(in.val[0]), + vreinterpretq_u8_u32(in.val[1])); + const uint8x16x2_t row23 = vtrnq_u8(vreinterpretq_u8_u32(in.val[2]), + vreinterpretq_u8_u32(in.val[3])); + const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]), + vreinterpretq_u16_u8(row23.val[0])); + const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]), + vreinterpretq_u16_u8(row23.val[1])); + *p1 = vreinterpretq_u8_u16(row02.val[0]); + *p0 = vreinterpretq_u8_u16(row13.val[0]); + *q0 = vreinterpretq_u8_u16(row02.val[1]); + *q1 = vreinterpretq_u8_u16(row13.val[1]); + } +} +#undef LOADQ_LANE_32b + +#endif // !WORK_AROUND_GCC + +static WEBP_INLINE void Load8x16_NEON( + const uint8_t* const src, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + Load4x16_NEON(src - 2, stride, p3, p2, p1, p0); + Load4x16_NEON(src + 2, stride, q0, q1, q2, q3); +} + +static WEBP_INLINE void Load16x4_NEON(const uint8_t* const src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { + *p1 = vld1q_u8(src - 2 * stride); + *p0 = vld1q_u8(src - 1 * stride); + *q0 = vld1q_u8(src + 0 * stride); + *q1 = vld1q_u8(src + 1 * stride); +} + +static WEBP_INLINE void Load16x8_NEON( + const uint8_t* const src, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + Load16x4_NEON(src - 2 * stride, stride, p3, p2, p1, p0); + Load16x4_NEON(src + 2 * stride, stride, q0, q1, q2, q3); +} + +static WEBP_INLINE void Load8x8x2_NEON( + const uint8_t* const u, const uint8_t* const v, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination + // and the v-samples on the higher half. + *p3 = vcombine_u8(vld1_u8(u - 4 * stride), vld1_u8(v - 4 * stride)); + *p2 = vcombine_u8(vld1_u8(u - 3 * stride), vld1_u8(v - 3 * stride)); + *p1 = vcombine_u8(vld1_u8(u - 2 * stride), vld1_u8(v - 2 * stride)); + *p0 = vcombine_u8(vld1_u8(u - 1 * stride), vld1_u8(v - 1 * stride)); + *q0 = vcombine_u8(vld1_u8(u + 0 * stride), vld1_u8(v + 0 * stride)); + *q1 = vcombine_u8(vld1_u8(u + 1 * stride), vld1_u8(v + 1 * stride)); + *q2 = vcombine_u8(vld1_u8(u + 2 * stride), vld1_u8(v + 2 * stride)); + *q3 = vcombine_u8(vld1_u8(u + 3 * stride), vld1_u8(v + 3 * stride)); +} + +#if !defined(WORK_AROUND_GCC) + +#define LOAD_UV_8(ROW) \ + vcombine_u8(vld1_u8(u - 4 + (ROW) * stride), vld1_u8(v - 4 + (ROW) * stride)) + +static WEBP_INLINE void Load8x8x2T_NEON( + const uint8_t* const u, const uint8_t* const v, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination + // and the v-samples on the higher half. + const uint8x16_t row0 = LOAD_UV_8(0); + const uint8x16_t row1 = LOAD_UV_8(1); + const uint8x16_t row2 = LOAD_UV_8(2); + const uint8x16_t row3 = LOAD_UV_8(3); + const uint8x16_t row4 = LOAD_UV_8(4); + const uint8x16_t row5 = LOAD_UV_8(5); + const uint8x16_t row6 = LOAD_UV_8(6); + const uint8x16_t row7 = LOAD_UV_8(7); + // Perform two side-by-side 8x8 transposes + // u00 u01 u02 u03 u04 u05 u06 u07 | v00 v01 v02 v03 v04 v05 v06 v07 + // u10 u11 u12 u13 u14 u15 u16 u17 | v10 v11 v12 ... + // u20 u21 u22 u23 u24 u25 u26 u27 | v20 v21 ... + // u30 u31 u32 u33 u34 u35 u36 u37 | ... + // u40 u41 u42 u43 u44 u45 u46 u47 | ... + // u50 u51 u52 u53 u54 u55 u56 u57 | ... + // u60 u61 u62 u63 u64 u65 u66 u67 | v60 ... + // u70 u71 u72 u73 u74 u75 u76 u77 | v70 v71 v72 ... + const uint8x16x2_t row01 = vtrnq_u8(row0, row1); // u00 u10 u02 u12 ... + // u01 u11 u03 u13 ... + const uint8x16x2_t row23 = vtrnq_u8(row2, row3); // u20 u30 u22 u32 ... + // u21 u31 u23 u33 ... + const uint8x16x2_t row45 = vtrnq_u8(row4, row5); // ... + const uint8x16x2_t row67 = vtrnq_u8(row6, row7); // ... + const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]), + vreinterpretq_u16_u8(row23.val[0])); + const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]), + vreinterpretq_u16_u8(row23.val[1])); + const uint16x8x2_t row46 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[0]), + vreinterpretq_u16_u8(row67.val[0])); + const uint16x8x2_t row57 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[1]), + vreinterpretq_u16_u8(row67.val[1])); + const uint32x4x2_t row04 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[0]), + vreinterpretq_u32_u16(row46.val[0])); + const uint32x4x2_t row26 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[1]), + vreinterpretq_u32_u16(row46.val[1])); + const uint32x4x2_t row15 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[0]), + vreinterpretq_u32_u16(row57.val[0])); + const uint32x4x2_t row37 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[1]), + vreinterpretq_u32_u16(row57.val[1])); + *p3 = vreinterpretq_u8_u32(row04.val[0]); + *p2 = vreinterpretq_u8_u32(row15.val[0]); + *p1 = vreinterpretq_u8_u32(row26.val[0]); + *p0 = vreinterpretq_u8_u32(row37.val[0]); + *q0 = vreinterpretq_u8_u32(row04.val[1]); + *q1 = vreinterpretq_u8_u32(row15.val[1]); + *q2 = vreinterpretq_u8_u32(row26.val[1]); + *q3 = vreinterpretq_u8_u32(row37.val[1]); +} +#undef LOAD_UV_8 + +#endif // !WORK_AROUND_GCC + +static WEBP_INLINE void Store2x8_NEON(const uint8x8x2_t v, + uint8_t* const dst, int stride) { + vst2_lane_u8(dst + 0 * stride, v, 0); + vst2_lane_u8(dst + 1 * stride, v, 1); + vst2_lane_u8(dst + 2 * stride, v, 2); + vst2_lane_u8(dst + 3 * stride, v, 3); + vst2_lane_u8(dst + 4 * stride, v, 4); + vst2_lane_u8(dst + 5 * stride, v, 5); + vst2_lane_u8(dst + 6 * stride, v, 6); + vst2_lane_u8(dst + 7 * stride, v, 7); +} + +static WEBP_INLINE void Store2x16_NEON(const uint8x16_t p0, const uint8x16_t q0, + uint8_t* const dst, int stride) { + uint8x8x2_t lo, hi; + lo.val[0] = vget_low_u8(p0); + lo.val[1] = vget_low_u8(q0); + hi.val[0] = vget_high_u8(p0); + hi.val[1] = vget_high_u8(q0); + Store2x8_NEON(lo, dst - 1 + 0 * stride, stride); + Store2x8_NEON(hi, dst - 1 + 8 * stride, stride); +} + +#if !defined(WORK_AROUND_GCC) +static WEBP_INLINE void Store4x8_NEON(const uint8x8x4_t v, + uint8_t* const dst, int stride) { + vst4_lane_u8(dst + 0 * stride, v, 0); + vst4_lane_u8(dst + 1 * stride, v, 1); + vst4_lane_u8(dst + 2 * stride, v, 2); + vst4_lane_u8(dst + 3 * stride, v, 3); + vst4_lane_u8(dst + 4 * stride, v, 4); + vst4_lane_u8(dst + 5 * stride, v, 5); + vst4_lane_u8(dst + 6 * stride, v, 6); + vst4_lane_u8(dst + 7 * stride, v, 7); +} + +static WEBP_INLINE void Store4x16_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + uint8_t* const dst, int stride) { + uint8x8x4_t lo, hi; + INIT_VECTOR4(lo, + vget_low_u8(p1), vget_low_u8(p0), + vget_low_u8(q0), vget_low_u8(q1)); + INIT_VECTOR4(hi, + vget_high_u8(p1), vget_high_u8(p0), + vget_high_u8(q0), vget_high_u8(q1)); + Store4x8_NEON(lo, dst - 2 + 0 * stride, stride); + Store4x8_NEON(hi, dst - 2 + 8 * stride, stride); +} +#endif // !WORK_AROUND_GCC + +static WEBP_INLINE void Store16x2_NEON(const uint8x16_t p0, const uint8x16_t q0, + uint8_t* const dst, int stride) { + vst1q_u8(dst - stride, p0); + vst1q_u8(dst, q0); +} + +static WEBP_INLINE void Store16x4_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + uint8_t* const dst, int stride) { + Store16x2_NEON(p1, p0, dst - stride, stride); + Store16x2_NEON(q0, q1, dst + stride, stride); +} + +static WEBP_INLINE void Store8x2x2_NEON(const uint8x16_t p0, + const uint8x16_t q0, + uint8_t* const u, uint8_t* const v, + int stride) { + // p0 and q0 contain the u+v samples packed in low/high halves. + vst1_u8(u - stride, vget_low_u8(p0)); + vst1_u8(u, vget_low_u8(q0)); + vst1_u8(v - stride, vget_high_u8(p0)); + vst1_u8(v, vget_high_u8(q0)); +} + +static WEBP_INLINE void Store8x4x2_NEON(const uint8x16_t p1, + const uint8x16_t p0, + const uint8x16_t q0, + const uint8x16_t q1, + uint8_t* const u, uint8_t* const v, + int stride) { + // The p1...q1 registers contain the u+v samples packed in low/high halves. + Store8x2x2_NEON(p1, p0, u - stride, v - stride, stride); + Store8x2x2_NEON(q0, q1, u + stride, v + stride, stride); +} + +#if !defined(WORK_AROUND_GCC) + +#define STORE6_LANE(DST, VAL0, VAL1, LANE) do { \ + vst3_lane_u8((DST) - 3, (VAL0), (LANE)); \ + vst3_lane_u8((DST) + 0, (VAL1), (LANE)); \ + (DST) += stride; \ +} while (0) + +static WEBP_INLINE void Store6x8x2_NEON( + const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2, + uint8_t* u, uint8_t* v, int stride) { + uint8x8x3_t u0, u1, v0, v1; + INIT_VECTOR3(u0, vget_low_u8(p2), vget_low_u8(p1), vget_low_u8(p0)); + INIT_VECTOR3(u1, vget_low_u8(q0), vget_low_u8(q1), vget_low_u8(q2)); + INIT_VECTOR3(v0, vget_high_u8(p2), vget_high_u8(p1), vget_high_u8(p0)); + INIT_VECTOR3(v1, vget_high_u8(q0), vget_high_u8(q1), vget_high_u8(q2)); + STORE6_LANE(u, u0, u1, 0); + STORE6_LANE(u, u0, u1, 1); + STORE6_LANE(u, u0, u1, 2); + STORE6_LANE(u, u0, u1, 3); + STORE6_LANE(u, u0, u1, 4); + STORE6_LANE(u, u0, u1, 5); + STORE6_LANE(u, u0, u1, 6); + STORE6_LANE(u, u0, u1, 7); + STORE6_LANE(v, v0, v1, 0); + STORE6_LANE(v, v0, v1, 1); + STORE6_LANE(v, v0, v1, 2); + STORE6_LANE(v, v0, v1, 3); + STORE6_LANE(v, v0, v1, 4); + STORE6_LANE(v, v0, v1, 5); + STORE6_LANE(v, v0, v1, 6); + STORE6_LANE(v, v0, v1, 7); +} +#undef STORE6_LANE + +static WEBP_INLINE void Store4x8x2_NEON(const uint8x16_t p1, + const uint8x16_t p0, + const uint8x16_t q0, + const uint8x16_t q1, + uint8_t* const u, uint8_t* const v, + int stride) { + uint8x8x4_t u0, v0; + INIT_VECTOR4(u0, + vget_low_u8(p1), vget_low_u8(p0), + vget_low_u8(q0), vget_low_u8(q1)); + INIT_VECTOR4(v0, + vget_high_u8(p1), vget_high_u8(p0), + vget_high_u8(q0), vget_high_u8(q1)); + vst4_lane_u8(u - 2 + 0 * stride, u0, 0); + vst4_lane_u8(u - 2 + 1 * stride, u0, 1); + vst4_lane_u8(u - 2 + 2 * stride, u0, 2); + vst4_lane_u8(u - 2 + 3 * stride, u0, 3); + vst4_lane_u8(u - 2 + 4 * stride, u0, 4); + vst4_lane_u8(u - 2 + 5 * stride, u0, 5); + vst4_lane_u8(u - 2 + 6 * stride, u0, 6); + vst4_lane_u8(u - 2 + 7 * stride, u0, 7); + vst4_lane_u8(v - 2 + 0 * stride, v0, 0); + vst4_lane_u8(v - 2 + 1 * stride, v0, 1); + vst4_lane_u8(v - 2 + 2 * stride, v0, 2); + vst4_lane_u8(v - 2 + 3 * stride, v0, 3); + vst4_lane_u8(v - 2 + 4 * stride, v0, 4); + vst4_lane_u8(v - 2 + 5 * stride, v0, 5); + vst4_lane_u8(v - 2 + 6 * stride, v0, 6); + vst4_lane_u8(v - 2 + 7 * stride, v0, 7); +} + +#endif // !WORK_AROUND_GCC + +// Zero extend 'v' to an int16x8_t. +static WEBP_INLINE int16x8_t ConvertU8ToS16_NEON(uint8x8_t v) { + return vreinterpretq_s16_u16(vmovl_u8(v)); +} + +// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result +// to the corresponding rows of 'dst'. +static WEBP_INLINE void SaturateAndStore4x4_NEON(uint8_t* const dst, + const int16x8_t dst01, + const int16x8_t dst23) { + // Unsigned saturate to 8b. + const uint8x8_t dst01_u8 = vqmovun_s16(dst01); + const uint8x8_t dst23_u8 = vqmovun_s16(dst23); + + // Store the results. + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); +} + +static WEBP_INLINE void Add4x4_NEON(const int16x8_t row01, + const int16x8_t row23, + uint8_t* const dst) { + uint32x2_t dst01 = vdup_n_u32(0); + uint32x2_t dst23 = vdup_n_u32(0); + + // Load the source pixels. + dst01 = vld1_lane_u32((uint32_t*)(dst + 0 * BPS), dst01, 0); + dst23 = vld1_lane_u32((uint32_t*)(dst + 2 * BPS), dst23, 0); + dst01 = vld1_lane_u32((uint32_t*)(dst + 1 * BPS), dst01, 1); + dst23 = vld1_lane_u32((uint32_t*)(dst + 3 * BPS), dst23, 1); + + { + // Convert to 16b. + const int16x8_t dst01_s16 = ConvertU8ToS16_NEON(vreinterpret_u8_u32(dst01)); + const int16x8_t dst23_s16 = ConvertU8ToS16_NEON(vreinterpret_u8_u32(dst23)); + + // Descale with rounding. + const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); + const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); + // Add the inverse transform. + SaturateAndStore4x4_NEON(dst, out01, out23); + } +} + +//----------------------------------------------------------------------------- +// Simple In-loop filtering (Paragraph 15.2) + +static uint8x16_t NeedsFilter_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + int thresh) { + const uint8x16_t thresh_v = vdupq_n_u8((uint8_t)thresh); + const uint8x16_t a_p0_q0 = vabdq_u8(p0, q0); // abs(p0-q0) + const uint8x16_t a_p1_q1 = vabdq_u8(p1, q1); // abs(p1-q1) + const uint8x16_t a_p0_q0_2 = vqaddq_u8(a_p0_q0, a_p0_q0); // 2 * abs(p0-q0) + const uint8x16_t a_p1_q1_2 = vshrq_n_u8(a_p1_q1, 1); // abs(p1-q1) / 2 + const uint8x16_t sum = vqaddq_u8(a_p0_q0_2, a_p1_q1_2); + const uint8x16_t mask = vcgeq_u8(thresh_v, sum); + return mask; +} + +static int8x16_t FlipSign_NEON(const uint8x16_t v) { + const uint8x16_t sign_bit = vdupq_n_u8(0x80); + return vreinterpretq_s8_u8(veorq_u8(v, sign_bit)); +} + +static uint8x16_t FlipSignBack_NEON(const int8x16_t v) { + const int8x16_t sign_bit = vdupq_n_s8(0x80); + return vreinterpretq_u8_s8(veorq_s8(v, sign_bit)); +} + +static int8x16_t GetBaseDelta_NEON(const int8x16_t p1, const int8x16_t p0, + const int8x16_t q0, const int8x16_t q1) { + const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) + const int8x16_t p1_q1 = vqsubq_s8(p1, q1); // (p1-q1) + const int8x16_t s1 = vqaddq_s8(p1_q1, q0_p0); // (p1-q1) + 1 * (q0 - p0) + const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // (p1-q1) + 2 * (q0 - p0) + const int8x16_t s3 = vqaddq_s8(q0_p0, s2); // (p1-q1) + 3 * (q0 - p0) + return s3; +} + +static int8x16_t GetBaseDelta0_NEON(const int8x16_t p0, const int8x16_t q0) { + const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) + const int8x16_t s1 = vqaddq_s8(q0_p0, q0_p0); // 2 * (q0 - p0) + const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // 3 * (q0 - p0) + return s2; +} + +//------------------------------------------------------------------------------ + +static void ApplyFilter2NoFlip_NEON(const int8x16_t p0s, const int8x16_t q0s, + const int8x16_t delta, + int8x16_t* const op0, + int8x16_t* const oq0) { + const int8x16_t kCst3 = vdupq_n_s8(0x03); + const int8x16_t kCst4 = vdupq_n_s8(0x04); + const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); + const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4); + const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3); + const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); + *op0 = vqaddq_s8(p0s, delta3); + *oq0 = vqsubq_s8(q0s, delta4); +} + +#if defined(WEBP_USE_INTRINSICS) + +static void ApplyFilter2_NEON(const int8x16_t p0s, const int8x16_t q0s, + const int8x16_t delta, + uint8x16_t* const op0, uint8x16_t* const oq0) { + const int8x16_t kCst3 = vdupq_n_s8(0x03); + const int8x16_t kCst4 = vdupq_n_s8(0x04); + const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); + const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4); + const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3); + const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); + const int8x16_t sp0 = vqaddq_s8(p0s, delta3); + const int8x16_t sq0 = vqsubq_s8(q0s, delta4); + *op0 = FlipSignBack_NEON(sp0); + *oq0 = FlipSignBack_NEON(sq0); +} + +static void DoFilter2_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + const uint8x16_t mask, + uint8x16_t* const op0, uint8x16_t* const oq0) { + const int8x16_t p1s = FlipSign_NEON(p1); + const int8x16_t p0s = FlipSign_NEON(p0); + const int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); + const int8x16_t delta0 = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); + const int8x16_t delta1 = vandq_s8(delta0, vreinterpretq_s8_u8(mask)); + ApplyFilter2_NEON(p0s, q0s, delta1, op0, oq0); +} + +static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) { + uint8x16_t p1, p0, q0, q1, op0, oq0; + Load16x4_NEON(p, stride, &p1, &p0, &q0, &q1); + { + const uint8x16_t mask = NeedsFilter_NEON(p1, p0, q0, q1, thresh); + DoFilter2_NEON(p1, p0, q0, q1, mask, &op0, &oq0); + } + Store16x2_NEON(op0, oq0, p, stride); +} + +static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) { + uint8x16_t p1, p0, q0, q1, oq0, op0; + Load4x16_NEON(p, stride, &p1, &p0, &q0, &q1); + { + const uint8x16_t mask = NeedsFilter_NEON(p1, p0, q0, q1, thresh); + DoFilter2_NEON(p1, p0, q0, q1, mask, &op0, &oq0); + } + Store2x16_NEON(op0, oq0, p, stride); +} + +#else + +// Load/Store vertical edge +#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \ + "vld4.8 {" #c1 "[0]," #c2 "[0]," #c3 "[0]," #c4 "[0]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[2]," #c2 "[2]," #c3 "[2]," #c4 "[2]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[3]," #c2 "[3]," #c3 "[3]," #c4 "[3]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[4]," #c2 "[4]," #c3 "[4]," #c4 "[4]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[5]," #c2 "[5]," #c3 "[5]," #c4 "[5]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[6]," #c2 "[6]," #c3 "[6]," #c4 "[6]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[7]," #c2 "[7]," #c3 "[7]," #c4 "[7]}," #b2 "," #stride "\n" + +#define STORE8x2(c1, c2, p, stride) \ + "vst2.8 {" #c1 "[0], " #c2 "[0]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[1], " #c2 "[1]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[2], " #c2 "[2]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[3], " #c2 "[3]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[4], " #c2 "[4]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[5], " #c2 "[5]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[6], " #c2 "[6]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[7], " #c2 "[7]}," #p "," #stride " \n" + +#define QRegs "q0", "q1", "q2", "q3", \ + "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + +#define FLIP_SIGN_BIT2(a, b, s) \ + "veor " #a "," #a "," #s " \n" \ + "veor " #b "," #b "," #s " \n" \ + +#define FLIP_SIGN_BIT4(a, b, c, d, s) \ + FLIP_SIGN_BIT2(a, b, s) \ + FLIP_SIGN_BIT2(c, d, s) \ + +#define NEEDS_FILTER(p1, p0, q0, q1, thresh, mask) \ + "vabd.u8 q15," #p0 "," #q0 " \n" /* abs(p0 - q0) */ \ + "vabd.u8 q14," #p1 "," #q1 " \n" /* abs(p1 - q1) */ \ + "vqadd.u8 q15, q15, q15 \n" /* abs(p0 - q0) * 2 */ \ + "vshr.u8 q14, q14, #1 \n" /* abs(p1 - q1) / 2 */ \ + "vqadd.u8 q15, q15, q14 \n" /* abs(p0 - q0) * 2 + abs(p1 - q1) / 2 */ \ + "vdup.8 q14, " #thresh " \n" \ + "vcge.u8 " #mask ", q14, q15 \n" /* mask <= thresh */ + +#define GET_BASE_DELTA(p1, p0, q0, q1, o) \ + "vqsub.s8 q15," #q0 "," #p0 " \n" /* (q0 - p0) */ \ + "vqsub.s8 " #o "," #p1 "," #q1 " \n" /* (p1 - q1) */ \ + "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 1 * (p0 - q0) */ \ + "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 2 * (p0 - q0) */ \ + "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 3 * (p0 - q0) */ + +#define DO_SIMPLE_FILTER(p0, q0, fl) \ + "vmov.i8 q15, #0x03 \n" \ + "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 3 */ \ + "vshr.s8 q15, q15, #3 \n" /* filter1 >> 3 */ \ + "vqadd.s8 " #p0 "," #p0 ", q15 \n" /* p0 += filter1 */ \ + \ + "vmov.i8 q15, #0x04 \n" \ + "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 4 */ \ + "vshr.s8 q15, q15, #3 \n" /* filter2 >> 3 */ \ + "vqsub.s8 " #q0 "," #q0 ", q15 \n" /* q0 -= filter2 */ + +// Applies filter on 2 pixels (p0 and q0) +#define DO_FILTER2(p1, p0, q0, q1, thresh) \ + NEEDS_FILTER(p1, p0, q0, q1, thresh, q9) /* filter mask in q9 */ \ + "vmov.i8 q10, #0x80 \n" /* sign bit */ \ + FLIP_SIGN_BIT4(p1, p0, q0, q1, q10) /* convert to signed value */ \ + GET_BASE_DELTA(p1, p0, q0, q1, q11) /* get filter level */ \ + "vand q9, q9, q11 \n" /* apply filter mask */ \ + DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \ + FLIP_SIGN_BIT2(p0, q0, q10) + +static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) { + __asm__ volatile ( + "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride + + "vld1.u8 {q1}, [%[p]], %[stride] \n" // p1 + "vld1.u8 {q2}, [%[p]], %[stride] \n" // p0 + "vld1.u8 {q3}, [%[p]], %[stride] \n" // q0 + "vld1.u8 {q12}, [%[p]] \n" // q1 + + DO_FILTER2(q1, q2, q3, q12, %[thresh]) + + "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride + + "vst1.u8 {q2}, [%[p]], %[stride] \n" // store op0 + "vst1.u8 {q3}, [%[p]] \n" // store oq0 + : [p] "+r"(p) + : [stride] "r"(stride), [thresh] "r"(thresh) + : "memory", QRegs + ); +} + +static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) { + __asm__ volatile ( + "sub r4, %[p], #2 \n" // base1 = p - 2 + "lsl r6, %[stride], #1 \n" // r6 = 2 * stride + "add r5, r4, %[stride] \n" // base2 = base1 + stride + + LOAD8x4(d2, d3, d4, d5, [r4], [r5], r6) + LOAD8x4(d24, d25, d26, d27, [r4], [r5], r6) + "vswp d3, d24 \n" // p1:q1 p0:q3 + "vswp d5, d26 \n" // q0:q2 q1:q4 + "vswp q2, q12 \n" // p1:q1 p0:q2 q0:q3 q1:q4 + + DO_FILTER2(q1, q2, q12, q13, %[thresh]) + + "sub %[p], %[p], #1 \n" // p - 1 + + "vswp d5, d24 \n" + STORE8x2(d4, d5, [%[p]], %[stride]) + STORE8x2(d24, d25, [%[p]], %[stride]) + + : [p] "+r"(p) + : [stride] "r"(stride), [thresh] "r"(thresh) + : "memory", "r4", "r5", "r6", QRegs + ); +} + +#undef LOAD8x4 +#undef STORE8x2 + +#endif // WEBP_USE_INTRINSICS + +static void SimpleVFilter16i_NEON(uint8_t* p, int stride, int thresh) { + uint32_t k; + for (k = 3; k != 0; --k) { + p += 4 * stride; + SimpleVFilter16_NEON(p, stride, thresh); + } +} + +static void SimpleHFilter16i_NEON(uint8_t* p, int stride, int thresh) { + uint32_t k; + for (k = 3; k != 0; --k) { + p += 4; + SimpleHFilter16_NEON(p, stride, thresh); + } +} + +//------------------------------------------------------------------------------ +// Complex In-loop filtering (Paragraph 15.3) + +static uint8x16_t NeedsHev_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + int hev_thresh) { + const uint8x16_t hev_thresh_v = vdupq_n_u8((uint8_t)hev_thresh); + const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) + const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) + const uint8x16_t a_max = vmaxq_u8(a_p1_p0, a_q1_q0); + const uint8x16_t mask = vcgtq_u8(a_max, hev_thresh_v); + return mask; +} + +static uint8x16_t NeedsFilter2_NEON(const uint8x16_t p3, const uint8x16_t p2, + const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + const uint8x16_t q2, const uint8x16_t q3, + int ithresh, int thresh) { + const uint8x16_t ithresh_v = vdupq_n_u8((uint8_t)ithresh); + const uint8x16_t a_p3_p2 = vabdq_u8(p3, p2); // abs(p3 - p2) + const uint8x16_t a_p2_p1 = vabdq_u8(p2, p1); // abs(p2 - p1) + const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) + const uint8x16_t a_q3_q2 = vabdq_u8(q3, q2); // abs(q3 - q2) + const uint8x16_t a_q2_q1 = vabdq_u8(q2, q1); // abs(q2 - q1) + const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) + const uint8x16_t max1 = vmaxq_u8(a_p3_p2, a_p2_p1); + const uint8x16_t max2 = vmaxq_u8(a_p1_p0, a_q3_q2); + const uint8x16_t max3 = vmaxq_u8(a_q2_q1, a_q1_q0); + const uint8x16_t max12 = vmaxq_u8(max1, max2); + const uint8x16_t max123 = vmaxq_u8(max12, max3); + const uint8x16_t mask2 = vcgeq_u8(ithresh_v, max123); + const uint8x16_t mask1 = NeedsFilter_NEON(p1, p0, q0, q1, thresh); + const uint8x16_t mask = vandq_u8(mask1, mask2); + return mask; +} + +// 4-points filter + +static void ApplyFilter4_NEON( + const int8x16_t p1, const int8x16_t p0, + const int8x16_t q0, const int8x16_t q1, + const int8x16_t delta0, + uint8x16_t* const op1, uint8x16_t* const op0, + uint8x16_t* const oq0, uint8x16_t* const oq1) { + const int8x16_t kCst3 = vdupq_n_s8(0x03); + const int8x16_t kCst4 = vdupq_n_s8(0x04); + const int8x16_t delta1 = vqaddq_s8(delta0, kCst4); + const int8x16_t delta2 = vqaddq_s8(delta0, kCst3); + const int8x16_t a1 = vshrq_n_s8(delta1, 3); + const int8x16_t a2 = vshrq_n_s8(delta2, 3); + const int8x16_t a3 = vrshrq_n_s8(a1, 1); // a3 = (a1 + 1) >> 1 + *op0 = FlipSignBack_NEON(vqaddq_s8(p0, a2)); // clip(p0 + a2) + *oq0 = FlipSignBack_NEON(vqsubq_s8(q0, a1)); // clip(q0 - a1) + *op1 = FlipSignBack_NEON(vqaddq_s8(p1, a3)); // clip(p1 + a3) + *oq1 = FlipSignBack_NEON(vqsubq_s8(q1, a3)); // clip(q1 - a3) +} + +static void DoFilter4_NEON( + const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + const uint8x16_t mask, const uint8x16_t hev_mask, + uint8x16_t* const op1, uint8x16_t* const op0, + uint8x16_t* const oq0, uint8x16_t* const oq1) { + // This is a fused version of DoFilter2() calling ApplyFilter2 directly + const int8x16_t p1s = FlipSign_NEON(p1); + int8x16_t p0s = FlipSign_NEON(p0); + int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); + const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); + + // do_filter2 part (simple loopfilter on pixels with hev) + { + const int8x16_t delta = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); + const int8x16_t simple_lf_delta = + vandq_s8(delta, vreinterpretq_s8_u8(simple_lf_mask)); + ApplyFilter2NoFlip_NEON(p0s, q0s, simple_lf_delta, &p0s, &q0s); + } + + // do_filter4 part (complex loopfilter on pixels without hev) + { + const int8x16_t delta0 = GetBaseDelta0_NEON(p0s, q0s); + // we use: (mask & hev_mask) ^ mask = mask & !hev_mask + const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); + const int8x16_t complex_lf_delta = + vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); + ApplyFilter4_NEON(p1s, p0s, q0s, q1s, complex_lf_delta, op1, op0, oq0, oq1); + } +} + +// 6-points filter + +static void ApplyFilter6_NEON( + const int8x16_t p2, const int8x16_t p1, const int8x16_t p0, + const int8x16_t q0, const int8x16_t q1, const int8x16_t q2, + const int8x16_t delta, + uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, + uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { + // We have to compute: X = (9*a+63) >> 7, Y = (18*a+63)>>7, Z = (27*a+63) >> 7 + // Turns out, there's a common sub-expression S=9 * a - 1 that can be used + // with the special vqrshrn_n_s16 rounding-shift-and-narrow instruction: + // X = (S + 64) >> 7, Y = (S + 32) >> 6, Z = (18 * a + S + 64) >> 7 + const int8x8_t delta_lo = vget_low_s8(delta); + const int8x8_t delta_hi = vget_high_s8(delta); + const int8x8_t kCst9 = vdup_n_s8(9); + const int16x8_t kCstm1 = vdupq_n_s16(-1); + const int8x8_t kCst18 = vdup_n_s8(18); + const int16x8_t S_lo = vmlal_s8(kCstm1, kCst9, delta_lo); // S = 9 * a - 1 + const int16x8_t S_hi = vmlal_s8(kCstm1, kCst9, delta_hi); + const int16x8_t Z_lo = vmlal_s8(S_lo, kCst18, delta_lo); // S + 18 * a + const int16x8_t Z_hi = vmlal_s8(S_hi, kCst18, delta_hi); + const int8x8_t a3_lo = vqrshrn_n_s16(S_lo, 7); // (9 * a + 63) >> 7 + const int8x8_t a3_hi = vqrshrn_n_s16(S_hi, 7); + const int8x8_t a2_lo = vqrshrn_n_s16(S_lo, 6); // (9 * a + 31) >> 6 + const int8x8_t a2_hi = vqrshrn_n_s16(S_hi, 6); + const int8x8_t a1_lo = vqrshrn_n_s16(Z_lo, 7); // (27 * a + 63) >> 7 + const int8x8_t a1_hi = vqrshrn_n_s16(Z_hi, 7); + const int8x16_t a1 = vcombine_s8(a1_lo, a1_hi); + const int8x16_t a2 = vcombine_s8(a2_lo, a2_hi); + const int8x16_t a3 = vcombine_s8(a3_lo, a3_hi); + + *op0 = FlipSignBack_NEON(vqaddq_s8(p0, a1)); // clip(p0 + a1) + *oq0 = FlipSignBack_NEON(vqsubq_s8(q0, a1)); // clip(q0 - q1) + *oq1 = FlipSignBack_NEON(vqsubq_s8(q1, a2)); // clip(q1 - a2) + *op1 = FlipSignBack_NEON(vqaddq_s8(p1, a2)); // clip(p1 + a2) + *oq2 = FlipSignBack_NEON(vqsubq_s8(q2, a3)); // clip(q2 - a3) + *op2 = FlipSignBack_NEON(vqaddq_s8(p2, a3)); // clip(p2 + a3) +} + +static void DoFilter6_NEON( + const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2, + const uint8x16_t mask, const uint8x16_t hev_mask, + uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, + uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { + // This is a fused version of DoFilter2() calling ApplyFilter2 directly + const int8x16_t p2s = FlipSign_NEON(p2); + const int8x16_t p1s = FlipSign_NEON(p1); + int8x16_t p0s = FlipSign_NEON(p0); + int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); + const int8x16_t q2s = FlipSign_NEON(q2); + const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); + const int8x16_t delta0 = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); + + // do_filter2 part (simple loopfilter on pixels with hev) + { + const int8x16_t simple_lf_delta = + vandq_s8(delta0, vreinterpretq_s8_u8(simple_lf_mask)); + ApplyFilter2NoFlip_NEON(p0s, q0s, simple_lf_delta, &p0s, &q0s); + } + + // do_filter6 part (complex loopfilter on pixels without hev) + { + // we use: (mask & hev_mask) ^ mask = mask & !hev_mask + const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); + const int8x16_t complex_lf_delta = + vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); + ApplyFilter6_NEON(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta, + op2, op1, op0, oq0, oq1, oq2); + } +} + +// on macroblock edges + +static void VFilter16_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + Load16x8_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op2, op1, op0, oq0, oq1, oq2; + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store16x2_NEON(op2, op1, p - 2 * stride, stride); + Store16x2_NEON(op0, oq0, p + 0 * stride, stride); + Store16x2_NEON(oq1, oq2, p + 2 * stride, stride); + } +} + +static void HFilter16_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + Load8x16_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op2, op1, op0, oq0, oq1, oq2; + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store2x16_NEON(op2, op1, p - 2, stride); + Store2x16_NEON(op0, oq0, p + 0, stride); + Store2x16_NEON(oq1, oq2, p + 2, stride); + } +} + +// on three inner edges +static void VFilter16i_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + uint32_t k; + uint8x16_t p3, p2, p1, p0; + Load16x4_NEON(p + 2 * stride, stride, &p3, &p2, &p1, &p0); + for (k = 3; k != 0; --k) { + uint8x16_t q0, q1, q2, q3; + p += 4 * stride; + Load16x4_NEON(p + 2 * stride, stride, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = + NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + // p3 and p2 are not just temporary variables here: they will be + // re-used for next span. And q2/q3 will become p1/p0 accordingly. + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); + Store16x4_NEON(p1, p0, p3, p2, p, stride); + p1 = q2; + p0 = q3; + } + } +} + +#if !defined(WORK_AROUND_GCC) +static void HFilter16i_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + uint32_t k; + uint8x16_t p3, p2, p1, p0; + Load4x16_NEON(p + 2, stride, &p3, &p2, &p1, &p0); + for (k = 3; k != 0; --k) { + uint8x16_t q0, q1, q2, q3; + p += 4; + Load4x16_NEON(p + 2, stride, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = + NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); + Store4x16_NEON(p1, p0, p3, p2, p, stride); + p1 = q2; + p0 = q3; + } + } +} +#endif // !WORK_AROUND_GCC + +// 8-pixels wide variant, for chroma filtering +static void VFilter8_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op2, op1, op0, oq0, oq1, oq2; + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store8x2x2_NEON(op2, op1, u - 2 * stride, v - 2 * stride, stride); + Store8x2x2_NEON(op0, oq0, u + 0 * stride, v + 0 * stride, stride); + Store8x2x2_NEON(oq1, oq2, u + 2 * stride, v + 2 * stride, stride); + } +} +static void VFilter8i_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + u += 4 * stride; + v += 4 * stride; + Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op1, op0, oq0, oq1; + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); + Store8x4x2_NEON(op1, op0, oq0, oq1, u, v, stride); + } +} + +#if !defined(WORK_AROUND_GCC) +static void HFilter8_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op2, op1, op0, oq0, oq1, oq2; + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store6x8x2_NEON(op2, op1, op0, oq0, oq1, oq2, u, v, stride); + } +} + +static void HFilter8i_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + u += 4; + v += 4; + Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op1, op0, oq0, oq1; + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); + Store4x8x2_NEON(op1, op0, oq0, oq1, u, v, stride); + } +} +#endif // !WORK_AROUND_GCC + +//----------------------------------------------------------------------------- +// Inverse transforms (Paragraph 14.4) + +// Technically these are unsigned but vqdmulh is only available in signed. +// vqdmulh returns high half (effectively >> 16) but also doubles the value, +// changing the >> 16 to >> 15 and requiring an additional >> 1. +// We use this to our advantage with kC2. The canonical value is 35468. +// However, the high bit is set so treating it as signed will give incorrect +// results. We avoid this by down shifting by 1 here to clear the highest bit. +// Combined with the doubling effect of vqdmulh we get >> 16. +// This can not be applied to kC1 because the lowest bit is set. Down shifting +// the constant would reduce precision. + +// libwebp uses a trick to avoid some extra addition that libvpx does. +// Instead of: +// temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16); +// libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the +// same issue with kC1 and vqdmulh that we work around by down shifting kC2 + +static const int16_t kC1 = WEBP_TRANSFORM_AC3_C1; +static const int16_t kC2 = + WEBP_TRANSFORM_AC3_C2 / 2; // half of kC2, actually. See comment above. + +#if defined(WEBP_USE_INTRINSICS) +static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0, + const int16x8_t in1, + int16x8x2_t* const out) { + // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 + // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 + const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... + // b0 d0 b1 d1 b2 d2 ... + *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); +} + +static WEBP_INLINE void TransformPass_NEON(int16x8x2_t* const rows) { + // {rows} = in0 | in4 + // in8 | in12 + // B1 = in4 | in12 + const int16x8_t B1 = + vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1])); + // C0 = kC1 * in4 | kC1 * in12 + // C1 = kC2 * in4 | kC2 * in12 + const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1); + const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2); + const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]), + vget_low_s16(rows->val[1])); // in0 + in8 + const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]), + vget_low_s16(rows->val[1])); // in0 - in8 + // c = kC2 * in4 - kC1 * in12 + // d = kC1 * in4 + kC2 * in12 + const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0)); + const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1)); + const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b + const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c + const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c + const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c + const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); + Transpose8x2_NEON(E0, E1, rows); +} + +static void TransformOne_NEON(const int16_t* in, uint8_t* dst) { + int16x8x2_t rows; + INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); + TransformPass_NEON(&rows); + TransformPass_NEON(&rows); + Add4x4_NEON(rows.val[0], rows.val[1], dst); +} + +#else + +static void TransformOne_NEON(const int16_t* in, uint8_t* dst) { + const int kBPS = BPS; + // kC1, kC2. Padded because vld1.16 loads 8 bytes + const int16_t constants[4] = { kC1, kC2, 0, 0 }; + /* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */ + __asm__ volatile ( + "vld1.16 {q1, q2}, [%[in]] \n" + "vld1.16 {d0}, [%[constants]] \n" + + /* d2: in[0] + * d3: in[8] + * d4: in[4] + * d5: in[12] + */ + "vswp d3, d4 \n" + + /* q8 = {in[4], in[12]} * kC1 * 2 >> 16 + * q9 = {in[4], in[12]} * kC2 >> 16 + */ + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + /* d22 = a = in[0] + in[8] + * d23 = b = in[0] - in[8] + */ + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + /* The multiplication should be x * kC1 >> 16 + * However, with vqdmulh we get x * kC1 * 2 >> 16 + * (multiply, double, return high half) + * We avoided this in kC2 by pre-shifting the constant. + * q8 = in[4]/[12] * kC1 >> 16 + */ + "vshr.s16 q8, q8, #1 \n" + + /* Add {in[4], in[12]} back after the multiplication. This is handled by + * adding 1 << 16 to kC1 in the libwebp C code. + */ + "vqadd.s16 q8, q2, q8 \n" + + /* d20 = c = in[4]*kC2 - in[12]*kC1 + * d21 = d = in[4]*kC1 + in[12]*kC2 + */ + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + /* d2 = tmp[0] = a + d + * d3 = tmp[1] = b + c + * d4 = tmp[2] = b - c + * d5 = tmp[3] = a - d + */ + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + "vswp d3, d4 \n" + + /* q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 + * q9 = {tmp[4], tmp[12]} * kC2 >> 16 + */ + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + /* d22 = a = tmp[0] + tmp[8] + * d23 = b = tmp[0] - tmp[8] + */ + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + /* See long winded explanations prior */ + "vshr.s16 q8, q8, #1 \n" + "vqadd.s16 q8, q2, q8 \n" + + /* d20 = c = in[4]*kC2 - in[12]*kC1 + * d21 = d = in[4]*kC1 + in[12]*kC2 + */ + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + /* d2 = tmp[0] = a + d + * d3 = tmp[1] = b + c + * d4 = tmp[2] = b - c + * d5 = tmp[3] = a - d + */ + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vld1.32 d6[0], [%[dst]], %[kBPS] \n" + "vld1.32 d6[1], [%[dst]], %[kBPS] \n" + "vld1.32 d7[0], [%[dst]], %[kBPS] \n" + "vld1.32 d7[1], [%[dst]], %[kBPS] \n" + + "sub %[dst], %[dst], %[kBPS], lsl #2 \n" + + /* (val) + 4 >> 3 */ + "vrshr.s16 d2, d2, #3 \n" + "vrshr.s16 d3, d3, #3 \n" + "vrshr.s16 d4, d4, #3 \n" + "vrshr.s16 d5, d5, #3 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + /* Must accumulate before saturating */ + "vmovl.u8 q8, d6 \n" + "vmovl.u8 q9, d7 \n" + + "vqadd.s16 q1, q1, q8 \n" + "vqadd.s16 q2, q2, q9 \n" + + "vqmovun.s16 d0, q1 \n" + "vqmovun.s16 d1, q2 \n" + + "vst1.32 d0[0], [%[dst]], %[kBPS] \n" + "vst1.32 d0[1], [%[dst]], %[kBPS] \n" + "vst1.32 d1[0], [%[dst]], %[kBPS] \n" + "vst1.32 d1[1], [%[dst]] \n" + + : [in] "+r"(in), [dst] "+r"(dst) /* modified registers */ + : [kBPS] "r"(kBPS), [constants] "r"(constants) /* constants */ + : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" /* clobbered */ + ); +} + +#endif // WEBP_USE_INTRINSICS + +static void TransformTwo_NEON(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne_NEON(in, dst); + if (do_two) { + TransformOne_NEON(in + 16, dst + 4); + } +} + +static void TransformDC_NEON(const int16_t* in, uint8_t* dst) { + const int16x8_t DC = vdupq_n_s16(in[0]); + Add4x4_NEON(DC, DC, dst); +} + +//------------------------------------------------------------------------------ + +#define STORE_WHT(dst, col, rows) do { \ + *dst = vgetq_lane_s32(rows.val[0], col); (dst) += 16; \ + *dst = vgetq_lane_s32(rows.val[1], col); (dst) += 16; \ + *dst = vgetq_lane_s32(rows.val[2], col); (dst) += 16; \ + *dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \ +} while (0) + +static void TransformWHT_NEON(const int16_t* in, int16_t* out) { + int32x4x4_t tmp; + + { + // Load the source. + const int16x4_t in00_03 = vld1_s16(in + 0); + const int16x4_t in04_07 = vld1_s16(in + 4); + const int16x4_t in08_11 = vld1_s16(in + 8); + const int16x4_t in12_15 = vld1_s16(in + 12); + const int32x4_t a0 = vaddl_s16(in00_03, in12_15); // in[0..3] + in[12..15] + const int32x4_t a1 = vaddl_s16(in04_07, in08_11); // in[4..7] + in[8..11] + const int32x4_t a2 = vsubl_s16(in04_07, in08_11); // in[4..7] - in[8..11] + const int32x4_t a3 = vsubl_s16(in00_03, in12_15); // in[0..3] - in[12..15] + tmp.val[0] = vaddq_s32(a0, a1); + tmp.val[1] = vaddq_s32(a3, a2); + tmp.val[2] = vsubq_s32(a0, a1); + tmp.val[3] = vsubq_s32(a3, a2); + // Arrange the temporary results column-wise. + tmp = Transpose4x4_NEON(tmp); + } + + { + const int32x4_t kCst3 = vdupq_n_s32(3); + const int32x4_t dc = vaddq_s32(tmp.val[0], kCst3); // add rounder + const int32x4_t a0 = vaddq_s32(dc, tmp.val[3]); + const int32x4_t a1 = vaddq_s32(tmp.val[1], tmp.val[2]); + const int32x4_t a2 = vsubq_s32(tmp.val[1], tmp.val[2]); + const int32x4_t a3 = vsubq_s32(dc, tmp.val[3]); + + tmp.val[0] = vaddq_s32(a0, a1); + tmp.val[1] = vaddq_s32(a3, a2); + tmp.val[2] = vsubq_s32(a0, a1); + tmp.val[3] = vsubq_s32(a3, a2); + + // right shift the results by 3. + tmp.val[0] = vshrq_n_s32(tmp.val[0], 3); + tmp.val[1] = vshrq_n_s32(tmp.val[1], 3); + tmp.val[2] = vshrq_n_s32(tmp.val[2], 3); + tmp.val[3] = vshrq_n_s32(tmp.val[3], 3); + + STORE_WHT(out, 0, tmp); + STORE_WHT(out, 1, tmp); + STORE_WHT(out, 2, tmp); + STORE_WHT(out, 3, tmp); + } +} + +#undef STORE_WHT + +//------------------------------------------------------------------------------ + +static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) { + const int16x4_t A = vld1_dup_s16(in); + const int16x4_t c4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL2(in[4])); + const int16x4_t d4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL1(in[4])); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); + const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 | + (uint64_t)( c1 & 0xffff) << 16 | + (uint64_t)(-c1 & 0xffff) << 32 | + (uint64_t)(-d1 & 0xffff) << 48; + const int16x4_t CD = vcreate_s16(cd); + const int16x4_t B = vqadd_s16(A, CD); + const int16x8_t m0_m1 = vcombine_s16(vqadd_s16(B, d4), vqadd_s16(B, c4)); + const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4)); + Add4x4_NEON(m0_m1, m2_m3, dst); +} + +//------------------------------------------------------------------------------ +// 4x4 + +static void DC4_NEON(uint8_t* dst) { // DC + const uint8x8_t A = vld1_u8(dst - BPS); // top row + const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top + const uint16x4_t p1 = vpadd_u16(p0, p0); + const uint8x8_t L0 = vld1_u8(dst + 0 * BPS - 1); + const uint8x8_t L1 = vld1_u8(dst + 1 * BPS - 1); + const uint8x8_t L2 = vld1_u8(dst + 2 * BPS - 1); + const uint8x8_t L3 = vld1_u8(dst + 3 * BPS - 1); + const uint16x8_t s0 = vaddl_u8(L0, L1); + const uint16x8_t s1 = vaddl_u8(L2, L3); + const uint16x8_t s01 = vaddq_u16(s0, s1); + const uint16x8_t sum = vaddq_u16(s01, vcombine_u16(p1, p1)); + const uint8x8_t dc0 = vrshrn_n_u16(sum, 3); // (sum + 4) >> 3 + const uint8x8_t dc = vdup_lane_u8(dc0, 0); + int i; + for (i = 0; i < 4; ++i) { + vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc), 0); + } +} + +// TrueMotion (4x4 + 8x8) +static WEBP_INLINE void TrueMotion_NEON(uint8_t* dst, int size) { + const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' + const uint8x8_t T = vld1_u8(dst - BPS); // top row 'A[0..3]' + const int16x8_t d = vreinterpretq_s16_u16(vsubl_u8(T, TL)); // A[c] - A[-1] + int y; + for (y = 0; y < size; y += 4) { + // left edge + const int16x8_t L0 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 0 * BPS - 1)); + const int16x8_t L1 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 1 * BPS - 1)); + const int16x8_t L2 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 2 * BPS - 1)); + const int16x8_t L3 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 3 * BPS - 1)); + const int16x8_t r0 = vaddq_s16(L0, d); // L[r] + A[c] - A[-1] + const int16x8_t r1 = vaddq_s16(L1, d); + const int16x8_t r2 = vaddq_s16(L2, d); + const int16x8_t r3 = vaddq_s16(L3, d); + // Saturate and store the result. + const uint32x2_t r0_u32 = vreinterpret_u32_u8(vqmovun_s16(r0)); + const uint32x2_t r1_u32 = vreinterpret_u32_u8(vqmovun_s16(r1)); + const uint32x2_t r2_u32 = vreinterpret_u32_u8(vqmovun_s16(r2)); + const uint32x2_t r3_u32 = vreinterpret_u32_u8(vqmovun_s16(r3)); + if (size == 4) { + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0_u32, 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1_u32, 0); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2_u32, 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3_u32, 0); + } else { + vst1_u32((uint32_t*)(dst + 0 * BPS), r0_u32); + vst1_u32((uint32_t*)(dst + 1 * BPS), r1_u32); + vst1_u32((uint32_t*)(dst + 2 * BPS), r2_u32); + vst1_u32((uint32_t*)(dst + 3 * BPS), r3_u32); + } + dst += 4 * BPS; + } +} + +static void TM4_NEON(uint8_t* dst) { TrueMotion_NEON(dst, 4); } + +static void VE4_NEON(uint8_t* dst) { // vertical + // NB: avoid vld1_u64 here as an alignment hint may be added -> SIGBUS. + const uint64x1_t A0 = vreinterpret_u64_u8(vld1_u8(dst - BPS - 1)); // top row + const uint64x1_t A1 = vshr_n_u64(A0, 8); + const uint64x1_t A2 = vshr_n_u64(A0, 16); + const uint8x8_t ABCDEFGH = vreinterpret_u8_u64(A0); + const uint8x8_t BCDEFGH0 = vreinterpret_u8_u64(A1); + const uint8x8_t CDEFGH00 = vreinterpret_u8_u64(A2); + const uint8x8_t b = vhadd_u8(ABCDEFGH, CDEFGH00); + const uint8x8_t avg = vrhadd_u8(b, BCDEFGH0); + int i; + for (i = 0; i < 4; ++i) { + vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(avg), 0); + } +} + +static void RD4_NEON(uint8_t* dst) { // Down-right + const uint8x8_t XABCD_u8 = vld1_u8(dst - BPS - 1); + const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8); + const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32); + const uint32_t I = dst[-1 + 0 * BPS]; + const uint32_t J = dst[-1 + 1 * BPS]; + const uint32_t K = dst[-1 + 2 * BPS]; + const uint32_t L = dst[-1 + 3 * BPS]; + const uint64x1_t LKJI____ = + vcreate_u64((uint64_t)L | (K << 8) | (J << 16) | (I << 24)); + const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC); + const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8)); + const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16)); + const uint8_t D = vget_lane_u8(XABCD_u8, 4); + const uint8x8_t JIXABCD_ = vset_lane_u8(D, JIXABC__, 6); + const uint8x8_t LKJIXABC_u8 = vreinterpret_u8_u64(LKJIXABC); + const uint8x8_t avg1 = vhadd_u8(JIXABCD_, LKJIXABC_u8); + const uint8x8_t avg2 = vrhadd_u8(avg1, KJIXABC_); + const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); + const uint32x2_t r3 = vreinterpret_u32_u8(avg2); + const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); + const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); + const uint32x2_t r0 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); +} + +static void LD4_NEON(uint8_t* dst) { // Down-left + // Note using the same shift trick as VE4() is slower here. + const uint8x8_t ABCDEFGH = vld1_u8(dst - BPS + 0); + const uint8x8_t BCDEFGH0 = vld1_u8(dst - BPS + 1); + const uint8x8_t CDEFGH00 = vld1_u8(dst - BPS + 2); + const uint8x8_t CDEFGHH0 = vset_lane_u8(dst[-BPS + 7], CDEFGH00, 6); + const uint8x8_t avg1 = vhadd_u8(ABCDEFGH, CDEFGHH0); + const uint8x8_t avg2 = vrhadd_u8(avg1, BCDEFGH0); + const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); + const uint32x2_t r0 = vreinterpret_u32_u8(avg2); + const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); + const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); + const uint32x2_t r3 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); +} + +//------------------------------------------------------------------------------ +// Chroma + +static void VE8uv_NEON(uint8_t* dst) { // vertical + const uint8x8_t top = vld1_u8(dst - BPS); + int j; + for (j = 0; j < 8; ++j) { + vst1_u8(dst + j * BPS, top); + } +} + +static void HE8uv_NEON(uint8_t* dst) { // horizontal + int j; + for (j = 0; j < 8; ++j) { + const uint8x8_t left = vld1_dup_u8(dst - 1); + vst1_u8(dst, left); + dst += BPS; + } +} + +static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) { + uint16x8_t sum_top; + uint16x8_t sum_left; + uint8x8_t dc0; + + if (do_top) { + const uint8x8_t A = vld1_u8(dst - BPS); // top row +#if WEBP_AARCH64 + const uint16_t p2 = vaddlv_u8(A); + sum_top = vdupq_n_u16(p2); +#else + const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top + const uint16x4_t p1 = vpadd_u16(p0, p0); + const uint16x4_t p2 = vpadd_u16(p1, p1); + sum_top = vcombine_u16(p2, p2); +#endif + } + + if (do_left) { + const uint8x8_t L0 = vld1_u8(dst + 0 * BPS - 1); + const uint8x8_t L1 = vld1_u8(dst + 1 * BPS - 1); + const uint8x8_t L2 = vld1_u8(dst + 2 * BPS - 1); + const uint8x8_t L3 = vld1_u8(dst + 3 * BPS - 1); + const uint8x8_t L4 = vld1_u8(dst + 4 * BPS - 1); + const uint8x8_t L5 = vld1_u8(dst + 5 * BPS - 1); + const uint8x8_t L6 = vld1_u8(dst + 6 * BPS - 1); + const uint8x8_t L7 = vld1_u8(dst + 7 * BPS - 1); + const uint16x8_t s0 = vaddl_u8(L0, L1); + const uint16x8_t s1 = vaddl_u8(L2, L3); + const uint16x8_t s2 = vaddl_u8(L4, L5); + const uint16x8_t s3 = vaddl_u8(L6, L7); + const uint16x8_t s01 = vaddq_u16(s0, s1); + const uint16x8_t s23 = vaddq_u16(s2, s3); + sum_left = vaddq_u16(s01, s23); + } + + if (do_top && do_left) { + const uint16x8_t sum = vaddq_u16(sum_left, sum_top); + dc0 = vrshrn_n_u16(sum, 4); + } else if (do_top) { + dc0 = vrshrn_n_u16(sum_top, 3); + } else if (do_left) { + dc0 = vrshrn_n_u16(sum_left, 3); + } else { + dc0 = vdup_n_u8(0x80); + } + + { + const uint8x8_t dc = vdup_lane_u8(dc0, 0); + int i; + for (i = 0; i < 8; ++i) { + vst1_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc)); + } + } +} + +static void DC8uv_NEON(uint8_t* dst) { DC8_NEON(dst, 1, 1); } +static void DC8uvNoTop_NEON(uint8_t* dst) { DC8_NEON(dst, 0, 1); } +static void DC8uvNoLeft_NEON(uint8_t* dst) { DC8_NEON(dst, 1, 0); } +static void DC8uvNoTopLeft_NEON(uint8_t* dst) { DC8_NEON(dst, 0, 0); } + +static void TM8uv_NEON(uint8_t* dst) { TrueMotion_NEON(dst, 8); } + +//------------------------------------------------------------------------------ +// 16x16 + +static void VE16_NEON(uint8_t* dst) { // vertical + const uint8x16_t top = vld1q_u8(dst - BPS); + int j; + for (j = 0; j < 16; ++j) { + vst1q_u8(dst + j * BPS, top); + } +} + +static void HE16_NEON(uint8_t* dst) { // horizontal + int j; + for (j = 0; j < 16; ++j) { + const uint8x16_t left = vld1q_dup_u8(dst - 1); + vst1q_u8(dst, left); + dst += BPS; + } +} + +static WEBP_INLINE void DC16_NEON(uint8_t* dst, int do_top, int do_left) { + uint16x8_t sum_top; + uint16x8_t sum_left; + uint8x8_t dc0; + + if (do_top) { + const uint8x16_t A = vld1q_u8(dst - BPS); // top row +#if WEBP_AARCH64 + const uint16_t p3 = vaddlvq_u8(A); + sum_top = vdupq_n_u16(p3); +#else + const uint16x8_t p0 = vpaddlq_u8(A); // cascading summation of the top + const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0)); + const uint16x4_t p2 = vpadd_u16(p1, p1); + const uint16x4_t p3 = vpadd_u16(p2, p2); + sum_top = vcombine_u16(p3, p3); +#endif + } + + if (do_left) { + int i; + sum_left = vdupq_n_u16(0); + for (i = 0; i < 16; i += 8) { + const uint8x8_t L0 = vld1_u8(dst + (i + 0) * BPS - 1); + const uint8x8_t L1 = vld1_u8(dst + (i + 1) * BPS - 1); + const uint8x8_t L2 = vld1_u8(dst + (i + 2) * BPS - 1); + const uint8x8_t L3 = vld1_u8(dst + (i + 3) * BPS - 1); + const uint8x8_t L4 = vld1_u8(dst + (i + 4) * BPS - 1); + const uint8x8_t L5 = vld1_u8(dst + (i + 5) * BPS - 1); + const uint8x8_t L6 = vld1_u8(dst + (i + 6) * BPS - 1); + const uint8x8_t L7 = vld1_u8(dst + (i + 7) * BPS - 1); + const uint16x8_t s0 = vaddl_u8(L0, L1); + const uint16x8_t s1 = vaddl_u8(L2, L3); + const uint16x8_t s2 = vaddl_u8(L4, L5); + const uint16x8_t s3 = vaddl_u8(L6, L7); + const uint16x8_t s01 = vaddq_u16(s0, s1); + const uint16x8_t s23 = vaddq_u16(s2, s3); + const uint16x8_t sum = vaddq_u16(s01, s23); + sum_left = vaddq_u16(sum_left, sum); + } + } + + if (do_top && do_left) { + const uint16x8_t sum = vaddq_u16(sum_left, sum_top); + dc0 = vrshrn_n_u16(sum, 5); + } else if (do_top) { + dc0 = vrshrn_n_u16(sum_top, 4); + } else if (do_left) { + dc0 = vrshrn_n_u16(sum_left, 4); + } else { + dc0 = vdup_n_u8(0x80); + } + + { + const uint8x16_t dc = vdupq_lane_u8(dc0, 0); + int i; + for (i = 0; i < 16; ++i) { + vst1q_u8(dst + i * BPS, dc); + } + } +} + +static void DC16TopLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 1, 1); } +static void DC16NoTop_NEON(uint8_t* dst) { DC16_NEON(dst, 0, 1); } +static void DC16NoLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 1, 0); } +static void DC16NoTopLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 0, 0); } + +static void TM16_NEON(uint8_t* dst) { + const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' + const uint8x16_t T = vld1q_u8(dst - BPS); // top row 'A[0..15]' + // A[c] - A[-1] + const int16x8_t d_lo = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), TL)); + const int16x8_t d_hi = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), TL)); + int y; + for (y = 0; y < 16; y += 4) { + // left edge + const int16x8_t L0 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 0 * BPS - 1)); + const int16x8_t L1 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 1 * BPS - 1)); + const int16x8_t L2 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 2 * BPS - 1)); + const int16x8_t L3 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 3 * BPS - 1)); + const int16x8_t r0_lo = vaddq_s16(L0, d_lo); // L[r] + A[c] - A[-1] + const int16x8_t r1_lo = vaddq_s16(L1, d_lo); + const int16x8_t r2_lo = vaddq_s16(L2, d_lo); + const int16x8_t r3_lo = vaddq_s16(L3, d_lo); + const int16x8_t r0_hi = vaddq_s16(L0, d_hi); + const int16x8_t r1_hi = vaddq_s16(L1, d_hi); + const int16x8_t r2_hi = vaddq_s16(L2, d_hi); + const int16x8_t r3_hi = vaddq_s16(L3, d_hi); + // Saturate and store the result. + const uint8x16_t row0 = vcombine_u8(vqmovun_s16(r0_lo), vqmovun_s16(r0_hi)); + const uint8x16_t row1 = vcombine_u8(vqmovun_s16(r1_lo), vqmovun_s16(r1_hi)); + const uint8x16_t row2 = vcombine_u8(vqmovun_s16(r2_lo), vqmovun_s16(r2_hi)); + const uint8x16_t row3 = vcombine_u8(vqmovun_s16(r3_lo), vqmovun_s16(r3_hi)); + vst1q_u8(dst + 0 * BPS, row0); + vst1q_u8(dst + 1 * BPS, row1); + vst1q_u8(dst + 2 * BPS, row2); + vst1q_u8(dst + 3 * BPS, row3); + dst += 4 * BPS; + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitNEON(void) { + VP8Transform = TransformTwo_NEON; + VP8TransformAC3 = TransformAC3_NEON; + VP8TransformDC = TransformDC_NEON; + VP8TransformWHT = TransformWHT_NEON; + + VP8VFilter16 = VFilter16_NEON; + VP8VFilter16i = VFilter16i_NEON; + VP8HFilter16 = HFilter16_NEON; +#if !defined(WORK_AROUND_GCC) + VP8HFilter16i = HFilter16i_NEON; +#endif + VP8VFilter8 = VFilter8_NEON; + VP8VFilter8i = VFilter8i_NEON; +#if !defined(WORK_AROUND_GCC) + VP8HFilter8 = HFilter8_NEON; + VP8HFilter8i = HFilter8i_NEON; +#endif + VP8SimpleVFilter16 = SimpleVFilter16_NEON; + VP8SimpleHFilter16 = SimpleHFilter16_NEON; + VP8SimpleVFilter16i = SimpleVFilter16i_NEON; + VP8SimpleHFilter16i = SimpleHFilter16i_NEON; + + VP8PredLuma4[0] = DC4_NEON; + VP8PredLuma4[1] = TM4_NEON; + VP8PredLuma4[2] = VE4_NEON; + VP8PredLuma4[4] = RD4_NEON; + VP8PredLuma4[6] = LD4_NEON; + + VP8PredLuma16[0] = DC16TopLeft_NEON; + VP8PredLuma16[1] = TM16_NEON; + VP8PredLuma16[2] = VE16_NEON; + VP8PredLuma16[3] = HE16_NEON; + VP8PredLuma16[4] = DC16NoTop_NEON; + VP8PredLuma16[5] = DC16NoLeft_NEON; + VP8PredLuma16[6] = DC16NoTopLeft_NEON; + + VP8PredChroma8[0] = DC8uv_NEON; + VP8PredChroma8[1] = TM8uv_NEON; + VP8PredChroma8[2] = VE8uv_NEON; + VP8PredChroma8[3] = HE8uv_NEON; + VP8PredChroma8[4] = DC8uvNoTop_NEON; + VP8PredChroma8[5] = DC8uvNoLeft_NEON; + VP8PredChroma8[6] = DC8uvNoTopLeft_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8DspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/dec_sse2.c b/libraries/webp/src/dsp/dec_sse2.c new file mode 100644 index 0000000000..ff3a28555b --- /dev/null +++ b/libraries/webp/src/dsp/dec_sse2.c @@ -0,0 +1,1226 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of some decoding functions (idct, loop filtering). +// +// Author: somnath@google.com (Somnath Banerjee) +// cduvivier@google.com (Christian Duvivier) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +// The 3-coeff sparse transform in SSE2 is not really faster than the plain-C +// one it seems => disable it by default. Uncomment the following to enable: +#if !defined(USE_TRANSFORM_AC3) +#define USE_TRANSFORM_AC3 0 // ALTERNATE_CODE +#endif + +#include +#include "src/dsp/common_sse2.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +static void Transform_SSE2(const int16_t* in, uint8_t* dst, int do_two) { + // This implementation makes use of 16-bit fixed point versions of two + // multiply constants: + // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 + // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 + // + // To be able to use signed 16-bit integers, we use the following trick to + // have constants within range: + // - Associated constants are obtained by subtracting the 16-bit fixed point + // version of one: + // k = K - (1 << 16) => K = k + (1 << 16) + // K1 = 85267 => k1 = 20091 + // K2 = 35468 => k2 = -30068 + // - The multiplication of a variable by a constant become the sum of the + // variable and the multiplication of that variable by the associated + // constant: + // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x + const __m128i k1 = _mm_set1_epi16(20091); + const __m128i k2 = _mm_set1_epi16(-30068); + __m128i T0, T1, T2, T3; + + // Load and concatenate the transform coefficients (we'll do two transforms + // in parallel). In the case of only one transform, the second half of the + // vectors will just contain random value we'll never use nor store. + __m128i in0, in1, in2, in3; + { + in0 = _mm_loadl_epi64((const __m128i*)&in[0]); + in1 = _mm_loadl_epi64((const __m128i*)&in[4]); + in2 = _mm_loadl_epi64((const __m128i*)&in[8]); + in3 = _mm_loadl_epi64((const __m128i*)&in[12]); + // a00 a10 a20 a30 x x x x + // a01 a11 a21 a31 x x x x + // a02 a12 a22 a32 x x x x + // a03 a13 a23 a33 x x x x + if (do_two) { + const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]); + const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]); + const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]); + const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]); + in0 = _mm_unpacklo_epi64(in0, inB0); + in1 = _mm_unpacklo_epi64(in1, inB1); + in2 = _mm_unpacklo_epi64(in2, inB2); + in3 = _mm_unpacklo_epi64(in3, inB3); + // a00 a10 a20 a30 b00 b10 b20 b30 + // a01 a11 a21 a31 b01 b11 b21 b31 + // a02 a12 a22 a32 b02 b12 b22 b32 + // a03 a13 a23 a33 b03 b13 b23 b33 + } + } + + // Vertical pass and subsequent transpose. + { + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i a = _mm_add_epi16(in0, in2); + const __m128i b = _mm_sub_epi16(in0, in2); + // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 + const __m128i c1 = _mm_mulhi_epi16(in1, k2); + const __m128i c2 = _mm_mulhi_epi16(in3, k1); + const __m128i c3 = _mm_sub_epi16(in1, in3); + const __m128i c4 = _mm_sub_epi16(c1, c2); + const __m128i c = _mm_add_epi16(c3, c4); + // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 + const __m128i d1 = _mm_mulhi_epi16(in1, k1); + const __m128i d2 = _mm_mulhi_epi16(in3, k2); + const __m128i d3 = _mm_add_epi16(in1, in3); + const __m128i d4 = _mm_add_epi16(d1, d2); + const __m128i d = _mm_add_epi16(d3, d4); + + // Second pass. + const __m128i tmp0 = _mm_add_epi16(a, d); + const __m128i tmp1 = _mm_add_epi16(b, c); + const __m128i tmp2 = _mm_sub_epi16(b, c); + const __m128i tmp3 = _mm_sub_epi16(a, d); + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&tmp0, &tmp1, &tmp2, &tmp3, &T0, &T1, &T2, &T3); + } + + // Horizontal pass and subsequent transpose. + { + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i four = _mm_set1_epi16(4); + const __m128i dc = _mm_add_epi16(T0, four); + const __m128i a = _mm_add_epi16(dc, T2); + const __m128i b = _mm_sub_epi16(dc, T2); + // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 + const __m128i c1 = _mm_mulhi_epi16(T1, k2); + const __m128i c2 = _mm_mulhi_epi16(T3, k1); + const __m128i c3 = _mm_sub_epi16(T1, T3); + const __m128i c4 = _mm_sub_epi16(c1, c2); + const __m128i c = _mm_add_epi16(c3, c4); + // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 + const __m128i d1 = _mm_mulhi_epi16(T1, k1); + const __m128i d2 = _mm_mulhi_epi16(T3, k2); + const __m128i d3 = _mm_add_epi16(T1, T3); + const __m128i d4 = _mm_add_epi16(d1, d2); + const __m128i d = _mm_add_epi16(d3, d4); + + // Second pass. + const __m128i tmp0 = _mm_add_epi16(a, d); + const __m128i tmp1 = _mm_add_epi16(b, c); + const __m128i tmp2 = _mm_sub_epi16(b, c); + const __m128i tmp3 = _mm_sub_epi16(a, d); + const __m128i shifted0 = _mm_srai_epi16(tmp0, 3); + const __m128i shifted1 = _mm_srai_epi16(tmp1, 3); + const __m128i shifted2 = _mm_srai_epi16(tmp2, 3); + const __m128i shifted3 = _mm_srai_epi16(tmp3, 3); + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1, + &T2, &T3); + } + + // Add inverse transform to 'dst' and store. + { + const __m128i zero = _mm_setzero_si128(); + // Load the reference(s). + __m128i dst0, dst1, dst2, dst3; + if (do_two) { + // Load eight bytes/pixels per line. + dst0 = _mm_loadl_epi64((__m128i*)(dst + 0 * BPS)); + dst1 = _mm_loadl_epi64((__m128i*)(dst + 1 * BPS)); + dst2 = _mm_loadl_epi64((__m128i*)(dst + 2 * BPS)); + dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS)); + } else { + // Load four bytes/pixels per line. + dst0 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 0 * BPS)); + dst1 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 1 * BPS)); + dst2 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 2 * BPS)); + dst3 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 3 * BPS)); + } + // Convert to 16b. + dst0 = _mm_unpacklo_epi8(dst0, zero); + dst1 = _mm_unpacklo_epi8(dst1, zero); + dst2 = _mm_unpacklo_epi8(dst2, zero); + dst3 = _mm_unpacklo_epi8(dst3, zero); + // Add the inverse transform(s). + dst0 = _mm_add_epi16(dst0, T0); + dst1 = _mm_add_epi16(dst1, T1); + dst2 = _mm_add_epi16(dst2, T2); + dst3 = _mm_add_epi16(dst3, T3); + // Unsigned saturate to 8b. + dst0 = _mm_packus_epi16(dst0, dst0); + dst1 = _mm_packus_epi16(dst1, dst1); + dst2 = _mm_packus_epi16(dst2, dst2); + dst3 = _mm_packus_epi16(dst3, dst3); + // Store the results. + if (do_two) { + // Store eight bytes/pixels per line. + _mm_storel_epi64((__m128i*)(dst + 0 * BPS), dst0); + _mm_storel_epi64((__m128i*)(dst + 1 * BPS), dst1); + _mm_storel_epi64((__m128i*)(dst + 2 * BPS), dst2); + _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3); + } else { + // Store four bytes/pixels per line. + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); + } + } +} + +#if (USE_TRANSFORM_AC3 == 1) + +static void TransformAC3(const int16_t* in, uint8_t* dst) { + const __m128i A = _mm_set1_epi16(in[0] + 4); + const __m128i c4 = _mm_set1_epi16(WEBP_TRANSFORM_AC3_MUL2(in[4])); + const __m128i d4 = _mm_set1_epi16(WEBP_TRANSFORM_AC3_MUL1(in[4])); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); + const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1); + const __m128i B = _mm_adds_epi16(A, CD); + const __m128i m0 = _mm_adds_epi16(B, d4); + const __m128i m1 = _mm_adds_epi16(B, c4); + const __m128i m2 = _mm_subs_epi16(B, c4); + const __m128i m3 = _mm_subs_epi16(B, d4); + const __m128i zero = _mm_setzero_si128(); + // Load the source pixels. + __m128i dst0 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 0 * BPS)); + __m128i dst1 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 1 * BPS)); + __m128i dst2 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 2 * BPS)); + __m128i dst3 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 3 * BPS)); + // Convert to 16b. + dst0 = _mm_unpacklo_epi8(dst0, zero); + dst1 = _mm_unpacklo_epi8(dst1, zero); + dst2 = _mm_unpacklo_epi8(dst2, zero); + dst3 = _mm_unpacklo_epi8(dst3, zero); + // Add the inverse transform. + dst0 = _mm_adds_epi16(dst0, _mm_srai_epi16(m0, 3)); + dst1 = _mm_adds_epi16(dst1, _mm_srai_epi16(m1, 3)); + dst2 = _mm_adds_epi16(dst2, _mm_srai_epi16(m2, 3)); + dst3 = _mm_adds_epi16(dst3, _mm_srai_epi16(m3, 3)); + // Unsigned saturate to 8b. + dst0 = _mm_packus_epi16(dst0, dst0); + dst1 = _mm_packus_epi16(dst1, dst1); + dst2 = _mm_packus_epi16(dst2, dst2); + dst3 = _mm_packus_epi16(dst3, dst3); + // Store the results. + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); +} + +#endif // USE_TRANSFORM_AC3 + +//------------------------------------------------------------------------------ +// Loop Filter (Paragraph 15) + +// Compute abs(p - q) = subs(p - q) OR subs(q - p) +#define MM_ABS(p, q) _mm_or_si128( \ + _mm_subs_epu8((q), (p)), \ + _mm_subs_epu8((p), (q))) + +// Shift each byte of "x" by 3 bits while preserving by the sign bit. +static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) { + const __m128i zero = _mm_setzero_si128(); + const __m128i lo_0 = _mm_unpacklo_epi8(zero, *x); + const __m128i hi_0 = _mm_unpackhi_epi8(zero, *x); + const __m128i lo_1 = _mm_srai_epi16(lo_0, 3 + 8); + const __m128i hi_1 = _mm_srai_epi16(hi_0, 3 + 8); + *x = _mm_packs_epi16(lo_1, hi_1); +} + +#define FLIP_SIGN_BIT2(a, b) do { \ + (a) = _mm_xor_si128(a, sign_bit); \ + (b) = _mm_xor_si128(b, sign_bit); \ +} while (0) + +#define FLIP_SIGN_BIT4(a, b, c, d) do { \ + FLIP_SIGN_BIT2(a, b); \ + FLIP_SIGN_BIT2(c, d); \ +} while (0) + +// input/output is uint8_t +static WEBP_INLINE void GetNotHEV_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int hev_thresh, __m128i* const not_hev) { + const __m128i zero = _mm_setzero_si128(); + const __m128i t_1 = MM_ABS(*p1, *p0); + const __m128i t_2 = MM_ABS(*q1, *q0); + + const __m128i h = _mm_set1_epi8(hev_thresh); + const __m128i t_max = _mm_max_epu8(t_1, t_2); + + const __m128i t_max_h = _mm_subs_epu8(t_max, h); + *not_hev = _mm_cmpeq_epi8(t_max_h, zero); // not_hev <= t1 && not_hev <= t2 +} + +// input pixels are int8_t +static WEBP_INLINE void GetBaseDelta_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + __m128i* const delta) { + // beware of addition order, for saturation! + const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 + const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0 + const __m128i s1 = _mm_adds_epi8(p1_q1, q0_p0); // p1 - q1 + 1 * (q0 - p0) + const __m128i s2 = _mm_adds_epi8(q0_p0, s1); // p1 - q1 + 2 * (q0 - p0) + const __m128i s3 = _mm_adds_epi8(q0_p0, s2); // p1 - q1 + 3 * (q0 - p0) + *delta = s3; +} + +// input and output are int8_t +static WEBP_INLINE void DoSimpleFilter_SSE2(__m128i* const p0, + __m128i* const q0, + const __m128i* const fl) { + const __m128i k3 = _mm_set1_epi8(3); + const __m128i k4 = _mm_set1_epi8(4); + __m128i v3 = _mm_adds_epi8(*fl, k3); + __m128i v4 = _mm_adds_epi8(*fl, k4); + + SignedShift8b_SSE2(&v4); // v4 >> 3 + SignedShift8b_SSE2(&v3); // v3 >> 3 + *q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4 + *p0 = _mm_adds_epi8(*p0, v3); // p0 += v3 +} + +// Updates values of 2 pixels at MB edge during complex filtering. +// Update operations: +// q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)] +// Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip). +static WEBP_INLINE void Update2Pixels_SSE2(__m128i* const pi, __m128i* const qi, + const __m128i* const a0_lo, + const __m128i* const a0_hi) { + const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7); + const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7); + const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi); + const __m128i sign_bit = _mm_set1_epi8((char)0x80); + *pi = _mm_adds_epi8(*pi, delta); + *qi = _mm_subs_epi8(*qi, delta); + FLIP_SIGN_BIT2(*pi, *qi); +} + +// input pixels are uint8_t +static WEBP_INLINE void NeedsFilter_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int thresh, __m128i* const mask) { + const __m128i m_thresh = _mm_set1_epi8((char)thresh); + const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1) + const __m128i kFE = _mm_set1_epi8((char)0xFE); + const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero + const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2 + + const __m128i t4 = MM_ABS(*p0, *q0); // abs(p0 - q0) + const __m128i t5 = _mm_adds_epu8(t4, t4); // abs(p0 - q0) * 2 + const __m128i t6 = _mm_adds_epu8(t5, t3); // abs(p0-q0)*2 + abs(p1-q1)/2 + + const __m128i t7 = _mm_subs_epu8(t6, m_thresh); // mask <= m_thresh + *mask = _mm_cmpeq_epi8(t7, _mm_setzero_si128()); +} + +//------------------------------------------------------------------------------ +// Edge filtering functions + +// Applies filter on 2 pixels (p0 and q0) +static WEBP_INLINE void DoFilter2_SSE2(__m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1, + int thresh) { + __m128i a, mask; + const __m128i sign_bit = _mm_set1_epi8((char)0x80); + // convert p1/q1 to int8_t (for GetBaseDelta_SSE2) + const __m128i p1s = _mm_xor_si128(*p1, sign_bit); + const __m128i q1s = _mm_xor_si128(*q1, sign_bit); + + NeedsFilter_SSE2(p1, p0, q0, q1, thresh, &mask); + + FLIP_SIGN_BIT2(*p0, *q0); + GetBaseDelta_SSE2(&p1s, p0, q0, &q1s, &a); + a = _mm_and_si128(a, mask); // mask filter values we don't care about + DoSimpleFilter_SSE2(p0, q0, &a); + FLIP_SIGN_BIT2(*p0, *q0); +} + +// Applies filter on 4 pixels (p1, p0, q0 and q1) +static WEBP_INLINE void DoFilter4_SSE2(__m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1, + const __m128i* const mask, + int hev_thresh) { + const __m128i zero = _mm_setzero_si128(); + const __m128i sign_bit = _mm_set1_epi8((char)0x80); + const __m128i k64 = _mm_set1_epi8(64); + const __m128i k3 = _mm_set1_epi8(3); + const __m128i k4 = _mm_set1_epi8(4); + __m128i not_hev; + __m128i t1, t2, t3; + + // compute hev mask + GetNotHEV_SSE2(p1, p0, q0, q1, hev_thresh, ¬_hev); + + // convert to signed values + FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); + + t1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 + t1 = _mm_andnot_si128(not_hev, t1); // hev(p1 - q1) + t2 = _mm_subs_epi8(*q0, *p0); // q0 - p0 + t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 1 * (q0 - p0) + t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 2 * (q0 - p0) + t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0) + t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about + + t2 = _mm_adds_epi8(t1, k3); // 3 * (q0 - p0) + hev(p1 - q1) + 3 + t3 = _mm_adds_epi8(t1, k4); // 3 * (q0 - p0) + hev(p1 - q1) + 4 + SignedShift8b_SSE2(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3 + SignedShift8b_SSE2(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3 + *p0 = _mm_adds_epi8(*p0, t2); // p0 += t2 + *q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3 + FLIP_SIGN_BIT2(*p0, *q0); + + // this is equivalent to signed (a + 1) >> 1 calculation + t2 = _mm_add_epi8(t3, sign_bit); + t3 = _mm_avg_epu8(t2, zero); + t3 = _mm_sub_epi8(t3, k64); + + t3 = _mm_and_si128(not_hev, t3); // if !hev + *q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3 + *p1 = _mm_adds_epi8(*p1, t3); // p1 += t3 + FLIP_SIGN_BIT2(*p1, *q1); +} + +// Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2) +static WEBP_INLINE void DoFilter6_SSE2(__m128i* const p2, __m128i* const p1, + __m128i* const p0, __m128i* const q0, + __m128i* const q1, __m128i* const q2, + const __m128i* const mask, + int hev_thresh) { + const __m128i zero = _mm_setzero_si128(); + const __m128i sign_bit = _mm_set1_epi8((char)0x80); + __m128i a, not_hev; + + // compute hev mask + GetNotHEV_SSE2(p1, p0, q0, q1, hev_thresh, ¬_hev); + + FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); + FLIP_SIGN_BIT2(*p2, *q2); + GetBaseDelta_SSE2(p1, p0, q0, q1, &a); + + { // do simple filter on pixels with hev + const __m128i m = _mm_andnot_si128(not_hev, *mask); + const __m128i f = _mm_and_si128(a, m); + DoSimpleFilter_SSE2(p0, q0, &f); + } + + { // do strong filter on pixels with not hev + const __m128i k9 = _mm_set1_epi16(0x0900); + const __m128i k63 = _mm_set1_epi16(63); + + const __m128i m = _mm_and_si128(not_hev, *mask); + const __m128i f = _mm_and_si128(a, m); + + const __m128i f_lo = _mm_unpacklo_epi8(zero, f); + const __m128i f_hi = _mm_unpackhi_epi8(zero, f); + + const __m128i f9_lo = _mm_mulhi_epi16(f_lo, k9); // Filter (lo) * 9 + const __m128i f9_hi = _mm_mulhi_epi16(f_hi, k9); // Filter (hi) * 9 + + const __m128i a2_lo = _mm_add_epi16(f9_lo, k63); // Filter * 9 + 63 + const __m128i a2_hi = _mm_add_epi16(f9_hi, k63); // Filter * 9 + 63 + + const __m128i a1_lo = _mm_add_epi16(a2_lo, f9_lo); // Filter * 18 + 63 + const __m128i a1_hi = _mm_add_epi16(a2_hi, f9_hi); // Filter * 18 + 63 + + const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63 + const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63 + + Update2Pixels_SSE2(p2, q2, &a2_lo, &a2_hi); + Update2Pixels_SSE2(p1, q1, &a1_lo, &a1_hi); + Update2Pixels_SSE2(p0, q0, &a0_lo, &a0_hi); + } +} + +// reads 8 rows across a vertical edge. +static WEBP_INLINE void Load8x4_SSE2(const uint8_t* const b, int stride, + __m128i* const p, __m128i* const q) { + // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00 + // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10 + const __m128i A0 = _mm_set_epi32( + WebPMemToInt32(&b[6 * stride]), WebPMemToInt32(&b[2 * stride]), + WebPMemToInt32(&b[4 * stride]), WebPMemToInt32(&b[0 * stride])); + const __m128i A1 = _mm_set_epi32( + WebPMemToInt32(&b[7 * stride]), WebPMemToInt32(&b[3 * stride]), + WebPMemToInt32(&b[5 * stride]), WebPMemToInt32(&b[1 * stride])); + + // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00 + // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20 + const __m128i B0 = _mm_unpacklo_epi8(A0, A1); + const __m128i B1 = _mm_unpackhi_epi8(A0, A1); + + // C0 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00 + // C1 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40 + const __m128i C0 = _mm_unpacklo_epi16(B0, B1); + const __m128i C1 = _mm_unpackhi_epi16(B0, B1); + + // *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00 + // *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 + *p = _mm_unpacklo_epi32(C0, C1); + *q = _mm_unpackhi_epi32(C0, C1); +} + +static WEBP_INLINE void Load16x4_SSE2(const uint8_t* const r0, + const uint8_t* const r8, + int stride, + __m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1) { + // Assume the pixels around the edge (|) are numbered as follows + // 00 01 | 02 03 + // 10 11 | 12 13 + // ... | ... + // e0 e1 | e2 e3 + // f0 f1 | f2 f3 + // + // r0 is pointing to the 0th row (00) + // r8 is pointing to the 8th row (80) + + // Load + // p1 = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00 + // q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 + // p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80 + // q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82 + Load8x4_SSE2(r0, stride, p1, q0); + Load8x4_SSE2(r8, stride, p0, q1); + + { + // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00 + // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01 + // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02 + // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03 + const __m128i t1 = *p1; + const __m128i t2 = *q0; + *p1 = _mm_unpacklo_epi64(t1, *p0); + *p0 = _mm_unpackhi_epi64(t1, *p0); + *q0 = _mm_unpacklo_epi64(t2, *q1); + *q1 = _mm_unpackhi_epi64(t2, *q1); + } +} + +static WEBP_INLINE void Store4x4_SSE2(__m128i* const x, + uint8_t* dst, int stride) { + int i; + for (i = 0; i < 4; ++i, dst += stride) { + WebPInt32ToMem(dst, _mm_cvtsi128_si32(*x)); + *x = _mm_srli_si128(*x, 4); + } +} + +// Transpose back and store +static WEBP_INLINE void Store16x4_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + uint8_t* r0, uint8_t* r8, + int stride) { + __m128i t1, p1_s, p0_s, q0_s, q1_s; + + // p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00 + // p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80 + t1 = *p0; + p0_s = _mm_unpacklo_epi8(*p1, t1); + p1_s = _mm_unpackhi_epi8(*p1, t1); + + // q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02 + // q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82 + t1 = *q0; + q0_s = _mm_unpacklo_epi8(t1, *q1); + q1_s = _mm_unpackhi_epi8(t1, *q1); + + // p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00 + // q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40 + t1 = p0_s; + p0_s = _mm_unpacklo_epi16(t1, q0_s); + q0_s = _mm_unpackhi_epi16(t1, q0_s); + + // p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80 + // q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0 + t1 = p1_s; + p1_s = _mm_unpacklo_epi16(t1, q1_s); + q1_s = _mm_unpackhi_epi16(t1, q1_s); + + Store4x4_SSE2(&p0_s, r0, stride); + r0 += 4 * stride; + Store4x4_SSE2(&q0_s, r0, stride); + + Store4x4_SSE2(&p1_s, r8, stride); + r8 += 4 * stride; + Store4x4_SSE2(&q1_s, r8, stride); +} + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +static void SimpleVFilter16_SSE2(uint8_t* p, int stride, int thresh) { + // Load + __m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]); + __m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]); + __m128i q0 = _mm_loadu_si128((__m128i*)&p[0]); + __m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]); + + DoFilter2_SSE2(&p1, &p0, &q0, &q1, thresh); + + // Store + _mm_storeu_si128((__m128i*)&p[-stride], p0); + _mm_storeu_si128((__m128i*)&p[0], q0); +} + +static void SimpleHFilter16_SSE2(uint8_t* p, int stride, int thresh) { + __m128i p1, p0, q0, q1; + + p -= 2; // beginning of p1 + + Load16x4_SSE2(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1); + DoFilter2_SSE2(&p1, &p0, &q0, &q1, thresh); + Store16x4_SSE2(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride); +} + +static void SimpleVFilter16i_SSE2(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + SimpleVFilter16_SSE2(p, stride, thresh); + } +} + +static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + SimpleHFilter16_SSE2(p, stride, thresh); + } +} + +//------------------------------------------------------------------------------ +// Complex In-loop filtering (Paragraph 15.3) + +#define MAX_DIFF1(p3, p2, p1, p0, m) do { \ + (m) = MM_ABS(p1, p0); \ + (m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \ + (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \ +} while (0) + +#define MAX_DIFF2(p3, p2, p1, p0, m) do { \ + (m) = _mm_max_epu8(m, MM_ABS(p1, p0)); \ + (m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \ + (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \ +} while (0) + +#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) do { \ + (e1) = _mm_loadu_si128((__m128i*)&(p)[0 * (stride)]); \ + (e2) = _mm_loadu_si128((__m128i*)&(p)[1 * (stride)]); \ + (e3) = _mm_loadu_si128((__m128i*)&(p)[2 * (stride)]); \ + (e4) = _mm_loadu_si128((__m128i*)&(p)[3 * (stride)]); \ +} while (0) + +#define LOADUV_H_EDGE(p, u, v, stride) do { \ + const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \ + const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \ + (p) = _mm_unpacklo_epi64(U, V); \ +} while (0) + +#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) do { \ + LOADUV_H_EDGE(e1, u, v, 0 * (stride)); \ + LOADUV_H_EDGE(e2, u, v, 1 * (stride)); \ + LOADUV_H_EDGE(e3, u, v, 2 * (stride)); \ + LOADUV_H_EDGE(e4, u, v, 3 * (stride)); \ +} while (0) + +#define STOREUV(p, u, v, stride) do { \ + _mm_storel_epi64((__m128i*)&(u)[(stride)], p); \ + (p) = _mm_srli_si128(p, 8); \ + _mm_storel_epi64((__m128i*)&(v)[(stride)], p); \ +} while (0) + +static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int thresh, int ithresh, + __m128i* const mask) { + const __m128i it = _mm_set1_epi8(ithresh); + const __m128i diff = _mm_subs_epu8(*mask, it); + const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128()); + __m128i filter_mask; + NeedsFilter_SSE2(p1, p0, q0, q1, thresh, &filter_mask); + *mask = _mm_and_si128(thresh_mask, filter_mask); +} + +// on macroblock edges +static void VFilter16_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i t1; + __m128i mask; + __m128i p2, p1, p0, q0, q1, q2; + + // Load p3, p2, p1, p0 + LOAD_H_EDGES4(p - 4 * stride, stride, t1, p2, p1, p0); + MAX_DIFF1(t1, p2, p1, p0, mask); + + // Load q0, q1, q2, q3 + LOAD_H_EDGES4(p, stride, q0, q1, q2, t1); + MAX_DIFF2(t1, q2, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + + // Store + _mm_storeu_si128((__m128i*)&p[-3 * stride], p2); + _mm_storeu_si128((__m128i*)&p[-2 * stride], p1); + _mm_storeu_si128((__m128i*)&p[-1 * stride], p0); + _mm_storeu_si128((__m128i*)&p[+0 * stride], q0); + _mm_storeu_si128((__m128i*)&p[+1 * stride], q1); + _mm_storeu_si128((__m128i*)&p[+2 * stride], q2); +} + +static void HFilter16_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i p3, p2, p1, p0, q0, q1, q2, q3; + + uint8_t* const b = p - 4; + Load16x4_SSE2(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); + MAX_DIFF1(p3, p2, p1, p0, mask); + + Load16x4_SSE2(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); + MAX_DIFF2(q3, q2, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + + Store16x4_SSE2(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride); + Store16x4_SSE2(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride); +} + +// on three inner edges +static void VFilter16i_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + __m128i p3, p2, p1, p0; // loop invariants + + LOAD_H_EDGES4(p, stride, p3, p2, p1, p0); // prologue + + for (k = 3; k > 0; --k) { + __m128i mask, tmp1, tmp2; + uint8_t* const b = p + 2 * stride; // beginning of p1 + p += 4 * stride; + + MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask + LOAD_H_EDGES4(p, stride, p3, p2, tmp1, tmp2); + MAX_DIFF2(p3, p2, tmp1, tmp2, mask); + + // p3 and p2 are not just temporary variables here: they will be + // re-used for next span. And q2/q3 will become p1/p0 accordingly. + ComplexMask_SSE2(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &p3, &p2, &mask, hev_thresh); + + // Store + _mm_storeu_si128((__m128i*)&b[0 * stride], p1); + _mm_storeu_si128((__m128i*)&b[1 * stride], p0); + _mm_storeu_si128((__m128i*)&b[2 * stride], p3); + _mm_storeu_si128((__m128i*)&b[3 * stride], p2); + + // rotate samples + p1 = tmp1; + p0 = tmp2; + } +} + +static void HFilter16i_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + __m128i p3, p2, p1, p0; // loop invariants + + Load16x4_SSE2(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue + + for (k = 3; k > 0; --k) { + __m128i mask, tmp1, tmp2; + uint8_t* const b = p + 2; // beginning of p1 + + p += 4; // beginning of q0 (and next span) + + MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask + Load16x4_SSE2(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2); + MAX_DIFF2(p3, p2, tmp1, tmp2, mask); + + ComplexMask_SSE2(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &p3, &p2, &mask, hev_thresh); + + Store16x4_SSE2(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride); + + // rotate samples + p1 = tmp1; + p0 = tmp2; + } +} + +// 8-pixels wide variant, for chroma filtering +static void VFilter8_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i t1, p2, p1, p0, q0, q1, q2; + + // Load p3, p2, p1, p0 + LOADUV_H_EDGES4(u - 4 * stride, v - 4 * stride, stride, t1, p2, p1, p0); + MAX_DIFF1(t1, p2, p1, p0, mask); + + // Load q0, q1, q2, q3 + LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1); + MAX_DIFF2(t1, q2, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + + // Store + STOREUV(p2, u, v, -3 * stride); + STOREUV(p1, u, v, -2 * stride); + STOREUV(p0, u, v, -1 * stride); + STOREUV(q0, u, v, 0 * stride); + STOREUV(q1, u, v, 1 * stride); + STOREUV(q2, u, v, 2 * stride); +} + +static void HFilter8_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i p3, p2, p1, p0, q0, q1, q2, q3; + + uint8_t* const tu = u - 4; + uint8_t* const tv = v - 4; + Load16x4_SSE2(tu, tv, stride, &p3, &p2, &p1, &p0); + MAX_DIFF1(p3, p2, p1, p0, mask); + + Load16x4_SSE2(u, v, stride, &q0, &q1, &q2, &q3); + MAX_DIFF2(q3, q2, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + + Store16x4_SSE2(&p3, &p2, &p1, &p0, tu, tv, stride); + Store16x4_SSE2(&q0, &q1, &q2, &q3, u, v, stride); +} + +static void VFilter8i_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i t1, t2, p1, p0, q0, q1; + + // Load p3, p2, p1, p0 + LOADUV_H_EDGES4(u, v, stride, t2, t1, p1, p0); + MAX_DIFF1(t2, t1, p1, p0, mask); + + u += 4 * stride; + v += 4 * stride; + + // Load q0, q1, q2, q3 + LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2); + MAX_DIFF2(t2, t1, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &q0, &q1, &mask, hev_thresh); + + // Store + STOREUV(p1, u, v, -2 * stride); + STOREUV(p0, u, v, -1 * stride); + STOREUV(q0, u, v, 0 * stride); + STOREUV(q1, u, v, 1 * stride); +} + +static void HFilter8i_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i t1, t2, p1, p0, q0, q1; + Load16x4_SSE2(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0 + MAX_DIFF1(t2, t1, p1, p0, mask); + + u += 4; // beginning of q0 + v += 4; + Load16x4_SSE2(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3 + MAX_DIFF2(t2, t1, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &q0, &q1, &mask, hev_thresh); + + u -= 2; // beginning of p1 + v -= 2; + Store16x4_SSE2(&p1, &p0, &q0, &q1, u, v, stride); +} + +//------------------------------------------------------------------------------ +// 4x4 predictions + +#define DST(x, y) dst[(x) + (y) * BPS] +#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) + +// We use the following 8b-arithmetic tricks: +// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1 +// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1] +// and: +// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb +// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 +// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 + +static void VE4_SSE2(uint8_t* dst) { // vertical + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); + const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); + const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); + const __m128i b = _mm_subs_epu8(a, lsb); + const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); + const int vals = _mm_cvtsi128_si32(avg); + int i; + for (i = 0; i < 4; ++i) { + WebPInt32ToMem(dst + i * BPS, vals); + } +} + +static void LD4_SSE2(uint8_t* dst) { // Down-Left + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); + const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); + const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, dst[-BPS + 7], 3); + const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); +} + +static void VR4_SSE2(uint8_t* dst) { // Vertical-Right + const __m128i one = _mm_set1_epi8(1); + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int X = dst[-1 - BPS]; + const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); + const __m128i ABCD0 = _mm_srli_si128(XABCD, 1); + const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0); + const __m128i _XABCD = _mm_slli_si128(XABCD, 1); + const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0); + const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i efgh = _mm_avg_epu8(avg2, XABCD); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); + + // these two are hard to implement in SSE2, so we keep the C-version: + DST(0, 2) = AVG3(J, I, X); + DST(0, 3) = AVG3(K, J, I); +} + +static void VL4_SSE2(uint8_t* dst) { // Vertical-Left + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); + const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2); + const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_); + const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_); + const __m128i avg3 = _mm_avg_epu8(avg1, avg2); + const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one); + const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_); + const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_); + const __m128i abbc = _mm_or_si128(ab, bc); + const __m128i lsb2 = _mm_and_si128(abbc, lsb1); + const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); + const uint32_t extra_out = + (uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); + + // these two are hard to get and irregular + DST(3, 2) = (extra_out >> 0) & 0xff; + DST(3, 3) = (extra_out >> 8) & 0xff; +} + +static void RD4_SSE2(uint8_t* dst) { // Down-right + const __m128i one = _mm_set1_epi8(1); + const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); + const __m128i ____XABCD = _mm_slli_si128(XABCD, 4); + const uint32_t I = dst[-1 + 0 * BPS]; + const uint32_t J = dst[-1 + 1 * BPS]; + const uint32_t K = dst[-1 + 2 * BPS]; + const uint32_t L = dst[-1 + 3 * BPS]; + const __m128i LKJI_____ = + _mm_cvtsi32_si128((int)(L | (K << 8) | (J << 16) | (I << 24))); + const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD); + const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); + const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); + const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); +} + +#undef DST +#undef AVG3 + +//------------------------------------------------------------------------------ +// Luma 16x16 + +static WEBP_INLINE void TrueMotion_SSE2(uint8_t* dst, int size) { + const uint8_t* top = dst - BPS; + const __m128i zero = _mm_setzero_si128(); + int y; + if (size == 4) { + const __m128i top_values = _mm_cvtsi32_si128(WebPMemToInt32(top)); + const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); + for (y = 0; y < 4; ++y, dst += BPS) { + const int val = dst[-1] - top[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); + WebPInt32ToMem(dst, _mm_cvtsi128_si32(out)); + } + } else if (size == 8) { + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); + for (y = 0; y < 8; ++y, dst += BPS) { + const int val = dst[-1] - top[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); + _mm_storel_epi64((__m128i*)dst, out); + } + } else { + const __m128i top_values = _mm_loadu_si128((const __m128i*)top); + const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero); + const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero); + for (y = 0; y < 16; ++y, dst += BPS) { + const int val = dst[-1] - top[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out_0 = _mm_add_epi16(base, top_base_0); + const __m128i out_1 = _mm_add_epi16(base, top_base_1); + const __m128i out = _mm_packus_epi16(out_0, out_1); + _mm_storeu_si128((__m128i*)dst, out); + } + } +} + +static void TM4_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 4); } +static void TM8uv_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 8); } +static void TM16_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 16); } + +static void VE16_SSE2(uint8_t* dst) { + const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); + int j; + for (j = 0; j < 16; ++j) { + _mm_storeu_si128((__m128i*)(dst + j * BPS), top); + } +} + +static void HE16_SSE2(uint8_t* dst) { // horizontal + int j; + for (j = 16; j > 0; --j) { + const __m128i values = _mm_set1_epi8((char)dst[-1]); + _mm_storeu_si128((__m128i*)dst, values); + dst += BPS; + } +} + +static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) { + int j; + const __m128i values = _mm_set1_epi8((char)v); + for (j = 0; j < 16; ++j) { + _mm_storeu_si128((__m128i*)(dst + j * BPS), values); + } +} + +static void DC16_SSE2(uint8_t* dst) { // DC + const __m128i zero = _mm_setzero_si128(); + const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); + const __m128i sad8x2 = _mm_sad_epu8(top, zero); + // sum the two sads: sad8x2[0:1] + sad8x2[8:9] + const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); + int left = 0; + int j; + for (j = 0; j < 16; ++j) { + left += dst[-1 + j * BPS]; + } + { + const int DC = _mm_cvtsi128_si32(sum) + left + 16; + Put16_SSE2(DC >> 5, dst); + } +} + +static void DC16NoTop_SSE2(uint8_t* dst) { // DC with top samples unavailable + int DC = 8; + int j; + for (j = 0; j < 16; ++j) { + DC += dst[-1 + j * BPS]; + } + Put16_SSE2(DC >> 4, dst); +} + +static void DC16NoLeft_SSE2(uint8_t* dst) { // DC with left samples unavailable + const __m128i zero = _mm_setzero_si128(); + const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); + const __m128i sad8x2 = _mm_sad_epu8(top, zero); + // sum the two sads: sad8x2[0:1] + sad8x2[8:9] + const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); + const int DC = _mm_cvtsi128_si32(sum) + 8; + Put16_SSE2(DC >> 4, dst); +} + +static void DC16NoTopLeft_SSE2(uint8_t* dst) { // DC with no top & left samples + Put16_SSE2(0x80, dst); +} + +//------------------------------------------------------------------------------ +// Chroma + +static void VE8uv_SSE2(uint8_t* dst) { // vertical + int j; + const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); + for (j = 0; j < 8; ++j) { + _mm_storel_epi64((__m128i*)(dst + j * BPS), top); + } +} + +// helper for chroma-DC predictions +static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) { + int j; + const __m128i values = _mm_set1_epi8((char)v); + for (j = 0; j < 8; ++j) { + _mm_storel_epi64((__m128i*)(dst + j * BPS), values); + } +} + +static void DC8uv_SSE2(uint8_t* dst) { // DC + const __m128i zero = _mm_setzero_si128(); + const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); + const __m128i sum = _mm_sad_epu8(top, zero); + int left = 0; + int j; + for (j = 0; j < 8; ++j) { + left += dst[-1 + j * BPS]; + } + { + const int DC = _mm_cvtsi128_si32(sum) + left + 8; + Put8x8uv_SSE2(DC >> 4, dst); + } +} + +static void DC8uvNoLeft_SSE2(uint8_t* dst) { // DC with no left samples + const __m128i zero = _mm_setzero_si128(); + const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); + const __m128i sum = _mm_sad_epu8(top, zero); + const int DC = _mm_cvtsi128_si32(sum) + 4; + Put8x8uv_SSE2(DC >> 3, dst); +} + +static void DC8uvNoTop_SSE2(uint8_t* dst) { // DC with no top samples + int dc0 = 4; + int i; + for (i = 0; i < 8; ++i) { + dc0 += dst[-1 + i * BPS]; + } + Put8x8uv_SSE2(dc0 >> 3, dst); +} + +static void DC8uvNoTopLeft_SSE2(uint8_t* dst) { // DC with nothing + Put8x8uv_SSE2(0x80, dst); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE2(void) { + VP8Transform = Transform_SSE2; +#if (USE_TRANSFORM_AC3 == 1) + VP8TransformAC3 = TransformAC3_SSE2; +#endif + + VP8VFilter16 = VFilter16_SSE2; + VP8HFilter16 = HFilter16_SSE2; + VP8VFilter8 = VFilter8_SSE2; + VP8HFilter8 = HFilter8_SSE2; + VP8VFilter16i = VFilter16i_SSE2; + VP8HFilter16i = HFilter16i_SSE2; + VP8VFilter8i = VFilter8i_SSE2; + VP8HFilter8i = HFilter8i_SSE2; + + VP8SimpleVFilter16 = SimpleVFilter16_SSE2; + VP8SimpleHFilter16 = SimpleHFilter16_SSE2; + VP8SimpleVFilter16i = SimpleVFilter16i_SSE2; + VP8SimpleHFilter16i = SimpleHFilter16i_SSE2; + + VP8PredLuma4[1] = TM4_SSE2; + VP8PredLuma4[2] = VE4_SSE2; + VP8PredLuma4[4] = RD4_SSE2; + VP8PredLuma4[5] = VR4_SSE2; + VP8PredLuma4[6] = LD4_SSE2; + VP8PredLuma4[7] = VL4_SSE2; + + VP8PredLuma16[0] = DC16_SSE2; + VP8PredLuma16[1] = TM16_SSE2; + VP8PredLuma16[2] = VE16_SSE2; + VP8PredLuma16[3] = HE16_SSE2; + VP8PredLuma16[4] = DC16NoTop_SSE2; + VP8PredLuma16[5] = DC16NoLeft_SSE2; + VP8PredLuma16[6] = DC16NoTopLeft_SSE2; + + VP8PredChroma8[0] = DC8uv_SSE2; + VP8PredChroma8[1] = TM8uv_SSE2; + VP8PredChroma8[2] = VE8uv_SSE2; + VP8PredChroma8[4] = DC8uvNoTop_SSE2; + VP8PredChroma8[5] = DC8uvNoLeft_SSE2; + VP8PredChroma8[6] = DC8uvNoTopLeft_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8DspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/dec_sse41.c b/libraries/webp/src/dsp/dec_sse41.c new file mode 100644 index 0000000000..08a3630272 --- /dev/null +++ b/libraries/webp/src/dsp/dec_sse41.c @@ -0,0 +1,46 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE4 version of some decoding functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) + +#include +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +static void HE16_SSE41(uint8_t* dst) { // horizontal + int j; + const __m128i kShuffle3 = _mm_set1_epi8(3); + for (j = 16; j > 0; --j) { + const __m128i in = _mm_cvtsi32_si128(WebPMemToInt32(dst - 4)); + const __m128i values = _mm_shuffle_epi8(in, kShuffle3); + _mm_storeu_si128((__m128i*)dst, values); + dst += BPS; + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE41(void) { + VP8PredLuma16[3] = HE16_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(VP8DspInitSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/libraries/webp/src/dsp/dsp.h b/libraries/webp/src/dsp/dsp.h new file mode 100644 index 0000000000..b22be1dc5a --- /dev/null +++ b/libraries/webp/src/dsp/dsp.h @@ -0,0 +1,509 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DSP_DSP_H_ +#define WEBP_DSP_DSP_H_ + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include "src/dsp/cpu.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BPS 32 // this is the common stride for enc/dec + +//------------------------------------------------------------------------------ +// WEBP_RESTRICT + +// Declares a pointer with the restrict type qualifier if available. +// This allows code to hint to the compiler that only this pointer references a +// particular object or memory region within the scope of the block in which it +// is declared. This may allow for improved optimizations due to the lack of +// pointer aliasing. See also: +// https://en.cppreference.com/w/c/language/restrict +#if defined(__GNUC__) +#define WEBP_RESTRICT __restrict__ +#elif defined(_MSC_VER) +#define WEBP_RESTRICT __restrict +#else +#define WEBP_RESTRICT +#endif + + +//------------------------------------------------------------------------------ +// Init stub generator + +// Defines an init function stub to ensure each module exposes a symbol, +// avoiding a compiler warning. +#define WEBP_DSP_INIT_STUB(func) \ + extern void func(void); \ + void func(void) {} + +//------------------------------------------------------------------------------ +// Encoding + +// Transforms +// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms +// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4). +typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two); +typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out); +typedef void (*VP8WHT)(const int16_t* in, int16_t* out); +extern VP8Idct VP8ITransform; +extern VP8Fdct VP8FTransform; +extern VP8Fdct VP8FTransform2; // performs two transforms at a time +extern VP8WHT VP8FTransformWHT; +// Predictions +// *dst is the destination block. *top and *left can be NULL. +typedef void (*VP8IntraPreds)(uint8_t* dst, const uint8_t* left, + const uint8_t* top); +typedef void (*VP8Intra4Preds)(uint8_t* dst, const uint8_t* top); +extern VP8Intra4Preds VP8EncPredLuma4; +extern VP8IntraPreds VP8EncPredLuma16; +extern VP8IntraPreds VP8EncPredChroma8; + +typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref); +extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4; +typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref, + const uint16_t* const weights); +// The weights for VP8TDisto4x4 and VP8TDisto16x16 contain a row-major +// 4 by 4 symmetric matrix. +extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16; + +// Compute the average (DC) of four 4x4 blocks. +// Each sub-4x4 block #i sum is stored in dc[i]. +typedef void (*VP8MeanMetric)(const uint8_t* ref, uint32_t dc[4]); +extern VP8MeanMetric VP8Mean16x4; + +typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst); +extern VP8BlockCopy VP8Copy4x4; +extern VP8BlockCopy VP8Copy16x8; +// Quantization +struct VP8Matrix; // forward declaration +typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +// Same as VP8QuantizeBlock, but quantizes two consecutive blocks. +typedef int (*VP8Quantize2Blocks)(int16_t in[32], int16_t out[32], + const struct VP8Matrix* const mtx); + +extern VP8QuantizeBlock VP8EncQuantizeBlock; +extern VP8Quantize2Blocks VP8EncQuantize2Blocks; + +// specific to 2nd transform: +typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; + +extern const int VP8DspScan[16 + 4 + 4]; + +// Collect histogram for susceptibility calculation. +#define MAX_COEFF_THRESH 31 // size of histogram used by CollectHistogram. +typedef struct { + // We only need to store max_value and last_non_zero, not the distribution. + int max_value; + int last_non_zero; +} VP8Histogram; +typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo); +extern VP8CHisto VP8CollectHistogram; +// General-purpose util function to help VP8CollectHistogram(). +void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], + VP8Histogram* const histo); + +// must be called before using any of the above +void VP8EncDspInit(void); + +//------------------------------------------------------------------------------ +// cost functions (encoding) + +extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p) +// approximate cost per level: +extern const uint16_t VP8LevelFixedCosts[2047 /*MAX_LEVEL*/ + 1]; +extern const uint8_t VP8EncBands[16 + 1]; + +struct VP8Residual; +typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs, + struct VP8Residual* const res); +extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; + +// Cost calculation function. +typedef int (*VP8GetResidualCostFunc)(int ctx0, + const struct VP8Residual* const res); +extern VP8GetResidualCostFunc VP8GetResidualCost; + +// must be called before anything using the above +void VP8EncDspCostInit(void); + +//------------------------------------------------------------------------------ +// SSIM / PSNR utils + +// struct for accumulating statistical moments +typedef struct { + uint32_t w; // sum(w_i) : sum of weights + uint32_t xm, ym; // sum(w_i * x_i), sum(w_i * y_i) + uint32_t xxm, xym, yym; // sum(w_i * x_i * x_i), etc. +} VP8DistoStats; + +// Compute the final SSIM value +// The non-clipped version assumes stats->w = (2 * VP8_SSIM_KERNEL + 1)^2. +double VP8SSIMFromStats(const VP8DistoStats* const stats); +double VP8SSIMFromStatsClipped(const VP8DistoStats* const stats); + +#define VP8_SSIM_KERNEL 3 // total size of the kernel: 2 * VP8_SSIM_KERNEL + 1 +typedef double (*VP8SSIMGetClippedFunc)(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int xo, int yo, // center position + int W, int H); // plane dimension + +#if !defined(WEBP_REDUCE_SIZE) +// This version is called with the guarantee that you can load 8 bytes and +// 8 rows at offset src1 and src2 +typedef double (*VP8SSIMGetFunc)(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2); + +extern VP8SSIMGetFunc VP8SSIMGet; // unclipped / unchecked +extern VP8SSIMGetClippedFunc VP8SSIMGetClipped; // with clipping +#endif + +#if !defined(WEBP_DISABLE_STATS) +typedef uint32_t (*VP8AccumulateSSEFunc)(const uint8_t* src1, + const uint8_t* src2, int len); +extern VP8AccumulateSSEFunc VP8AccumulateSSE; +#endif + +// must be called before using any of the above directly +void VP8SSIMDspInit(void); + +//------------------------------------------------------------------------------ +// Decoding + +typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst); +// when doing two transforms, coeffs is actually int16_t[2][16]. +typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two); +extern VP8DecIdct2 VP8Transform; +extern VP8DecIdct VP8TransformAC3; +extern VP8DecIdct VP8TransformUV; +extern VP8DecIdct VP8TransformDC; +extern VP8DecIdct VP8TransformDCUV; +extern VP8WHT VP8TransformWHT; + +#define WEBP_TRANSFORM_AC3_C1 20091 +#define WEBP_TRANSFORM_AC3_C2 35468 +#define WEBP_TRANSFORM_AC3_MUL1(a) ((((a) * WEBP_TRANSFORM_AC3_C1) >> 16) + (a)) +#define WEBP_TRANSFORM_AC3_MUL2(a) (((a) * WEBP_TRANSFORM_AC3_C2) >> 16) + +// *dst is the destination block, with stride BPS. Boundary samples are +// assumed accessible when needed. +typedef void (*VP8PredFunc)(uint8_t* dst); +extern VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */]; +extern VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */]; +extern VP8PredFunc VP8PredLuma4[/* NUM_BMODES */]; + +// clipping tables (for filtering) +extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127] +extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15] +extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255] +extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255] +// must be called first +void VP8InitClipTables(void); + +// simple filter (only for luma) +typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh); +extern VP8SimpleFilterFunc VP8SimpleVFilter16; +extern VP8SimpleFilterFunc VP8SimpleHFilter16; +extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges +extern VP8SimpleFilterFunc VP8SimpleHFilter16i; + +// regular filter (on both macroblock edges and inner edges) +typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride, + int thresh, int ithresh, int hev_t); +typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_t); +// on outer edge +extern VP8LumaFilterFunc VP8VFilter16; +extern VP8LumaFilterFunc VP8HFilter16; +extern VP8ChromaFilterFunc VP8VFilter8; +extern VP8ChromaFilterFunc VP8HFilter8; + +// on inner edge +extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether +extern VP8LumaFilterFunc VP8HFilter16i; +extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether +extern VP8ChromaFilterFunc VP8HFilter8i; + +// Dithering. Combines dithering values (centered around 128) with dst[], +// according to: dst[] = clip(dst[] + (((dither[]-128) + 8) >> 4) +#define VP8_DITHER_DESCALE 4 +#define VP8_DITHER_DESCALE_ROUNDER (1 << (VP8_DITHER_DESCALE - 1)) +#define VP8_DITHER_AMP_BITS 7 +#define VP8_DITHER_AMP_CENTER (1 << VP8_DITHER_AMP_BITS) +extern void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst, + int dst_stride); + +// must be called before anything using the above +void VP8DspInit(void); + +//------------------------------------------------------------------------------ +// WebP I/O + +#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support + +// Convert a pair of y/u/v lines together to the output rgb/a colorspace. +// bottom_y can be NULL if only one line of output is needed (at top/bottom). +typedef void (*WebPUpsampleLinePairFunc)( + const uint8_t* top_y, const uint8_t* bottom_y, + const uint8_t* top_u, const uint8_t* top_v, + const uint8_t* cur_u, const uint8_t* cur_v, + uint8_t* top_dst, uint8_t* bottom_dst, int len); + +#ifdef FANCY_UPSAMPLING + +// Fancy upsampling functions to convert YUV to RGB(A) modes +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +#endif // FANCY_UPSAMPLING + +// Per-row point-sampling methods. +typedef void (*WebPSamplerRowFunc)(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len); +// Generic function to apply 'WebPSamplerRowFunc' to the whole plane: +void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, + const uint8_t* u, const uint8_t* v, int uv_stride, + uint8_t* dst, int dst_stride, + int width, int height, WebPSamplerRowFunc func); + +// Sampling functions to convert rows of YUV to RGB(A) +extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */]; + +// General function for converting two lines of ARGB or RGBA. +// 'alpha_is_last' should be true if 0xff000000 is stored in memory as +// as 0x00, 0x00, 0x00, 0xff (little endian). +WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last); + +// YUV444->RGB converters +typedef void (*WebPYUV444Converter)(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len); + +extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; + +// Must be called before using the WebPUpsamplers[] (and for premultiplied +// colorspaces like rgbA, rgbA4444, etc) +void WebPInitUpsamplers(void); +// Must be called before using WebPSamplers[] +void WebPInitSamplers(void); +// Must be called before using WebPYUV444Converters[] +void WebPInitYUV444Converters(void); + +//------------------------------------------------------------------------------ +// ARGB -> YUV converters + +// Convert ARGB samples to luma Y. +extern void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); +// Convert ARGB samples to U/V with downsampling. do_store should be '1' for +// even lines and '0' for odd ones. 'src_width' is the original width, not +// the U/V one. +extern void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store); + +// Convert a row of accumulated (four-values) of rgba32 toward U/V +extern void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width); + +// Convert RGB or BGR to Y +extern void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); +extern void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); + +// used for plain-C fallback. +extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store); +extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width); + +// Must be called before using the above. +void WebPInitConvertARGBToYUV(void); + +//------------------------------------------------------------------------------ +// Rescaler + +struct WebPRescaler; + +// Import a row of data and save its contribution in the rescaler. +// 'channel' denotes the channel number to be imported. 'Expand' corresponds to +// the wrk->x_expand case. Otherwise, 'Shrink' is to be used. +typedef void (*WebPRescalerImportRowFunc)(struct WebPRescaler* const wrk, + const uint8_t* src); + +extern WebPRescalerImportRowFunc WebPRescalerImportRowExpand; +extern WebPRescalerImportRowFunc WebPRescalerImportRowShrink; + +// Export one row (starting at x_out position) from rescaler. +// 'Expand' corresponds to the wrk->y_expand case. +// Otherwise 'Shrink' is to be used +typedef void (*WebPRescalerExportRowFunc)(struct WebPRescaler* const wrk); +extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand; +extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink; + +// Plain-C implementation, as fall-back. +extern void WebPRescalerImportRowExpand_C(struct WebPRescaler* const wrk, + const uint8_t* src); +extern void WebPRescalerImportRowShrink_C(struct WebPRescaler* const wrk, + const uint8_t* src); +extern void WebPRescalerExportRowExpand_C(struct WebPRescaler* const wrk); +extern void WebPRescalerExportRowShrink_C(struct WebPRescaler* const wrk); + +// Main entry calls: +extern void WebPRescalerImportRow(struct WebPRescaler* const wrk, + const uint8_t* src); +// Export one row (starting at x_out position) from rescaler. +extern void WebPRescalerExportRow(struct WebPRescaler* const wrk); + +// Must be called first before using the above. +void WebPRescalerDspInit(void); + +//------------------------------------------------------------------------------ +// Utilities for processing transparent channel. + +// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h. +// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last). +extern void (*WebPApplyAlphaMultiply)( + uint8_t* rgba, int alpha_first, int w, int h, int stride); + +// Same, buf specifically for RGBA4444 format +extern void (*WebPApplyAlphaMultiply4444)( + uint8_t* rgba4444, int w, int h, int stride); + +// Dispatch the values from alpha[] plane to the ARGB destination 'dst'. +// Returns true if alpha[] plane has non-trivial values different from 0xff. +extern int (*WebPDispatchAlpha)(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint8_t* WEBP_RESTRICT dst, int dst_stride); + +// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the +// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units. +extern void (*WebPDispatchAlphaToGreen)(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint32_t* WEBP_RESTRICT dst, + int dst_stride); + +// Extract the alpha values from 32b values in argb[] and pack them into alpha[] +// (this is the opposite of WebPDispatchAlpha). +// Returns true if there's only trivial 0xff alpha values. +extern int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT argb, + int argb_stride, int width, int height, + uint8_t* WEBP_RESTRICT alpha, + int alpha_stride); + +// Extract the green values from 32b values in argb[] and pack them into alpha[] +// (this is the opposite of WebPDispatchAlphaToGreen). +extern void (*WebPExtractGreen)(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size); + +// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B). +// Un-Multiply operation transforms x into x * 255 / A. + +// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row. +extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); + +// Same a WebPMultARGBRow(), but for several rows. +void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, + int inverse); + +// Same for a row of single values, with side alpha values. +extern void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse); + +// Same a WebPMultRow(), but for several 'num_rows' rows. +void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride, + const uint8_t* WEBP_RESTRICT alpha, int alpha_stride, + int width, int num_rows, int inverse); + +// Plain-C versions, used as fallback by some implementations. +void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse); +void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse); + +#ifdef WORDS_BIGENDIAN +// ARGB packing function: a/r/g/b input is rgba or bgra order. +extern void (*WebPPackARGB)(const uint8_t* WEBP_RESTRICT a, + const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, uint32_t* WEBP_RESTRICT out); +#endif + +// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order. +extern void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, int step, uint32_t* WEBP_RESTRICT out); + +// This function returns true if src[i] contains a value different from 0xff. +extern int (*WebPHasAlpha8b)(const uint8_t* src, int length); +// This function returns true if src[4*i] contains a value different from 0xff. +extern int (*WebPHasAlpha32b)(const uint8_t* src, int length); +// replaces transparent values in src[] by 'color'. +extern void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color); + +// To be called first before using the above. +void WebPInitAlphaProcessing(void); + +//------------------------------------------------------------------------------ +// Filter functions + +typedef enum { // Filter types. + WEBP_FILTER_NONE = 0, + WEBP_FILTER_HORIZONTAL, + WEBP_FILTER_VERTICAL, + WEBP_FILTER_GRADIENT, + WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker + WEBP_FILTER_BEST, // meta-types + WEBP_FILTER_FAST +} WEBP_FILTER_TYPE; + +typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, + int stride, uint8_t* out); +// In-place un-filtering. +// Warning! 'prev_line' pointer can be equal to 'cur_line' or 'preds'. +typedef void (*WebPUnfilterFunc)(const uint8_t* prev_line, const uint8_t* preds, + uint8_t* cur_line, int width); + +// Filter the given data using the given predictor. +// 'in' corresponds to a 2-dimensional pixel array of size (stride * height) +// in raster order. +// 'stride' is number of bytes per scan line (with possible padding). +// 'out' should be pre-allocated. +extern WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; + +// In-place reconstruct the original data from the given filtered data. +// The reconstruction will be done for 'num_rows' rows starting from 'row' +// (assuming rows upto 'row - 1' are already reconstructed). +extern WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; + +// To be called first before using the above. +void VP8FiltersInit(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_DSP_H_ diff --git a/libraries/webp/src/dsp/enc.c b/libraries/webp/src/dsp/enc.c new file mode 100644 index 0000000000..395ad05b0b --- /dev/null +++ b/libraries/webp/src/dsp/enc.c @@ -0,0 +1,830 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical encoding functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include // for abs() + +#include "src/dsp/dsp.h" +#include "src/enc/vp8i_enc.h" + +static WEBP_INLINE uint8_t clip_8b(int v) { + return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; +} + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE int clip_max(int v, int max) { + return (v > max) ? max : v; +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +const int VP8DspScan[16 + 4 + 4] = { + // Luma + 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, + 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, + 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, + 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, + + 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U + 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V +}; + +// general-purpose util function +void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], + VP8Histogram* const histo) { + int max_value = 0, last_non_zero = 1; + int k; + for (k = 0; k <= MAX_COEFF_THRESH; ++k) { + const int value = distribution[k]; + if (value > 0) { + if (value > max_value) max_value = value; + last_non_zero = k; + } + } + histo->max_value = max_value; + histo->last_non_zero = last_non_zero; +} + +#if !WEBP_NEON_OMIT_C_CODE +static void CollectHistogram_C(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int k; + int16_t out[16]; + + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + + // Convert coefficients to bin. + for (k = 0; k < 16; ++k) { + const int v = abs(out[k]) >> 3; + const int clipped_value = clip_max(v, MAX_COEFF_THRESH); + ++distribution[clipped_value]; + } + } + VP8SetHistogramData(distribution, histo); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// run-time tables (~4k) + +static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255] + +// We declare this variable 'volatile' to prevent instruction reordering +// and make sure it's set to true _last_ (so as to be thread-safe) +static volatile int tables_ok = 0; + +static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) { + if (!tables_ok) { + int i; + for (i = -255; i <= 255 + 255; ++i) { + clip1[255 + i] = clip_8b(i); + } + tables_ok = 1; + } +} + + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +#if !WEBP_NEON_OMIT_C_CODE + +#define STORE(x, y, v) \ + dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3)) + +static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + int C[4 * 4], *tmp; + int i; + tmp = C; + for (i = 0; i < 4; ++i) { // vertical pass + const int a = in[0] + in[8]; + const int b = in[0] - in[8]; + const int c = + WEBP_TRANSFORM_AC3_MUL2(in[4]) - WEBP_TRANSFORM_AC3_MUL1(in[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(in[4]) + WEBP_TRANSFORM_AC3_MUL2(in[12]); + tmp[0] = a + d; + tmp[1] = b + c; + tmp[2] = b - c; + tmp[3] = a - d; + tmp += 4; + in++; + } + + tmp = C; + for (i = 0; i < 4; ++i) { // horizontal pass + const int dc = tmp[0] + 4; + const int a = dc + tmp[8]; + const int b = dc - tmp[8]; + const int c = + WEBP_TRANSFORM_AC3_MUL2(tmp[4]) - WEBP_TRANSFORM_AC3_MUL1(tmp[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(tmp[4]) + WEBP_TRANSFORM_AC3_MUL2(tmp[12]); + STORE(0, i, a + d); + STORE(1, i, b + c); + STORE(2, i, b - c); + STORE(3, i, a - d); + tmp++; + } +} + +static void ITransform_C(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { + ITransformOne(ref, in, dst); + if (do_two) { + ITransformOne(ref + 4, in + 16, dst + 4); + } +} + +static void FTransform_C(const uint8_t* src, const uint8_t* ref, int16_t* out) { + int i; + int tmp[16]; + for (i = 0; i < 4; ++i, src += BPS, ref += BPS) { + const int d0 = src[0] - ref[0]; // 9bit dynamic range ([-255,255]) + const int d1 = src[1] - ref[1]; + const int d2 = src[2] - ref[2]; + const int d3 = src[3] - ref[3]; + const int a0 = (d0 + d3); // 10b [-510,510] + const int a1 = (d1 + d2); + const int a2 = (d1 - d2); + const int a3 = (d0 - d3); + tmp[0 + i * 4] = (a0 + a1) * 8; // 14b [-8160,8160] + tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 1812) >> 9; // [-7536,7542] + tmp[2 + i * 4] = (a0 - a1) * 8; + tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9; + } + for (i = 0; i < 4; ++i) { + const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b + const int a1 = (tmp[4 + i] + tmp[ 8 + i]); + const int a2 = (tmp[4 + i] - tmp[ 8 + i]); + const int a3 = (tmp[0 + i] - tmp[12 + i]); + out[0 + i] = (a0 + a1 + 7) >> 4; // 12b + out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0); + out[8 + i] = (a0 - a1 + 7) >> 4; + out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void FTransform2_C(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + VP8FTransform(src, ref, out); + VP8FTransform(src + 4, ref + 4, out + 16); +} + +#if !WEBP_NEON_OMIT_C_CODE +static void FTransformWHT_C(const int16_t* in, int16_t* out) { + // input is 12b signed + int32_t tmp[16]; + int i; + for (i = 0; i < 4; ++i, in += 64) { + const int a0 = (in[0 * 16] + in[2 * 16]); // 13b + const int a1 = (in[1 * 16] + in[3 * 16]); + const int a2 = (in[1 * 16] - in[3 * 16]); + const int a3 = (in[0 * 16] - in[2 * 16]); + tmp[0 + i * 4] = a0 + a1; // 14b + tmp[1 + i * 4] = a3 + a2; + tmp[2 + i * 4] = a3 - a2; + tmp[3 + i * 4] = a0 - a1; + } + for (i = 0; i < 4; ++i) { + const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b + const int a1 = (tmp[4 + i] + tmp[12+ i]); + const int a2 = (tmp[4 + i] - tmp[12+ i]); + const int a3 = (tmp[0 + i] - tmp[8 + i]); + const int b0 = a0 + a1; // 16b + const int b1 = a3 + a2; + const int b2 = a3 - a2; + const int b3 = a0 - a1; + out[ 0 + i] = b0 >> 1; // 15b + out[ 4 + i] = b1 >> 1; + out[ 8 + i] = b2 >> 1; + out[12 + i] = b3 >> 1; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#undef STORE + +//------------------------------------------------------------------------------ +// Intra predictions + +static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) { + int j; + for (j = 0; j < size; ++j) { + memset(dst + j * BPS, value, size); + } +} + +static WEBP_INLINE void VerticalPred(uint8_t* dst, + const uint8_t* top, int size) { + int j; + if (top != NULL) { + for (j = 0; j < size; ++j) memcpy(dst + j * BPS, top, size); + } else { + Fill(dst, 127, size); + } +} + +static WEBP_INLINE void HorizontalPred(uint8_t* dst, + const uint8_t* left, int size) { + if (left != NULL) { + int j; + for (j = 0; j < size; ++j) { + memset(dst + j * BPS, left[j], size); + } + } else { + Fill(dst, 129, size); + } +} + +static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left, + const uint8_t* top, int size) { + int y; + if (left != NULL) { + if (top != NULL) { + const uint8_t* const clip = clip1 + 255 - left[-1]; + for (y = 0; y < size; ++y) { + const uint8_t* const clip_table = clip + left[y]; + int x; + for (x = 0; x < size; ++x) { + dst[x] = clip_table[top[x]]; + } + dst += BPS; + } + } else { + HorizontalPred(dst, left, size); + } + } else { + // true motion without left samples (hence: with default 129 value) + // is equivalent to VE prediction where you just copy the top samples. + // Note that if top samples are not available, the default value is + // then 129, and not 127 as in the VerticalPred case. + if (top != NULL) { + VerticalPred(dst, top, size); + } else { + Fill(dst, 129, size); + } + } +} + +static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left, + const uint8_t* top, + int size, int round, int shift) { + int DC = 0; + int j; + if (top != NULL) { + for (j = 0; j < size; ++j) DC += top[j]; + if (left != NULL) { // top and left present + for (j = 0; j < size; ++j) DC += left[j]; + } else { // top, but no left + DC += DC; + } + DC = (DC + round) >> shift; + } else if (left != NULL) { // left but no top + for (j = 0; j < size; ++j) DC += left[j]; + DC += DC; + DC = (DC + round) >> shift; + } else { // no top, no left, nothing. + DC = 0x80; + } + Fill(dst, DC, size); +} + +//------------------------------------------------------------------------------ +// Chroma 8x8 prediction (paragraph 12.2) + +static void IntraChromaPreds_C(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + // U block + DCMode(C8DC8 + dst, left, top, 8, 8, 4); + VerticalPred(C8VE8 + dst, top, 8); + HorizontalPred(C8HE8 + dst, left, 8); + TrueMotion(C8TM8 + dst, left, top, 8); + // V block + dst += 8; + if (top != NULL) top += 8; + if (left != NULL) left += 16; + DCMode(C8DC8 + dst, left, top, 8, 8, 4); + VerticalPred(C8VE8 + dst, top, 8); + HorizontalPred(C8HE8 + dst, left, 8); + TrueMotion(C8TM8 + dst, left, top, 8); +} + +//------------------------------------------------------------------------------ +// luma 16x16 prediction (paragraph 12.3) + +static void Intra16Preds_C(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DCMode(I16DC16 + dst, left, top, 16, 16, 5); + VerticalPred(I16VE16 + dst, top, 16); + HorizontalPred(I16HE16 + dst, left, 16); + TrueMotion(I16TM16 + dst, left, top, 16); +} + +//------------------------------------------------------------------------------ +// luma 4x4 prediction + +#define DST(x, y) dst[(x) + (y) * BPS] +#define AVG3(a, b, c) ((uint8_t)(((a) + 2 * (b) + (c) + 2) >> 2)) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +static void VE4(uint8_t* dst, const uint8_t* top) { // vertical + const uint8_t vals[4] = { + AVG3(top[-1], top[0], top[1]), + AVG3(top[ 0], top[1], top[2]), + AVG3(top[ 1], top[2], top[3]), + AVG3(top[ 2], top[3], top[4]) + }; + int i; + for (i = 0; i < 4; ++i) { + memcpy(dst + i * BPS, vals, 4); + } +} + +static void HE4(uint8_t* dst, const uint8_t* top) { // horizontal + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); +} + +static void DC4(uint8_t* dst, const uint8_t* top) { + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; + Fill(dst, dc >> 3, 4); +} + +static void RD4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + DST(0, 3) = AVG3(J, K, L); + DST(0, 2) = DST(1, 3) = AVG3(I, J, K); + DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J); + DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I); + DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X); + DST(2, 0) = DST(3, 1) = AVG3(C, B, A); + DST(3, 0) = AVG3(D, C, B); +} + +static void LD4(uint8_t* dst, const uint8_t* top) { + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + const int E = top[4]; + const int F = top[5]; + const int G = top[6]; + const int H = top[7]; + DST(0, 0) = AVG3(A, B, C); + DST(1, 0) = DST(0, 1) = AVG3(B, C, D); + DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E); + DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F); + DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G); + DST(3, 2) = DST(2, 3) = AVG3(F, G, H); + DST(3, 3) = AVG3(G, H, H); +} + +static void VR4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + DST(0, 0) = DST(1, 2) = AVG2(X, A); + DST(1, 0) = DST(2, 2) = AVG2(A, B); + DST(2, 0) = DST(3, 2) = AVG2(B, C); + DST(3, 0) = AVG2(C, D); + + DST(0, 3) = AVG3(K, J, I); + DST(0, 2) = AVG3(J, I, X); + DST(0, 1) = DST(1, 3) = AVG3(I, X, A); + DST(1, 1) = DST(2, 3) = AVG3(X, A, B); + DST(2, 1) = DST(3, 3) = AVG3(A, B, C); + DST(3, 1) = AVG3(B, C, D); +} + +static void VL4(uint8_t* dst, const uint8_t* top) { + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + const int E = top[4]; + const int F = top[5]; + const int G = top[6]; + const int H = top[7]; + DST(0, 0) = AVG2(A, B); + DST(1, 0) = DST(0, 2) = AVG2(B, C); + DST(2, 0) = DST(1, 2) = AVG2(C, D); + DST(3, 0) = DST(2, 2) = AVG2(D, E); + + DST(0, 1) = AVG3(A, B, C); + DST(1, 1) = DST(0, 3) = AVG3(B, C, D); + DST(2, 1) = DST(1, 3) = AVG3(C, D, E); + DST(3, 1) = DST(2, 3) = AVG3(D, E, F); + DST(3, 2) = AVG3(E, F, G); + DST(3, 3) = AVG3(F, G, H); +} + +static void HU4(uint8_t* dst, const uint8_t* top) { + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + DST(0, 0) = AVG2(I, J); + DST(2, 0) = DST(0, 1) = AVG2(J, K); + DST(2, 1) = DST(0, 2) = AVG2(K, L); + DST(1, 0) = AVG3(I, J, K); + DST(3, 0) = DST(1, 1) = AVG3(J, K, L); + DST(3, 1) = DST(1, 2) = AVG3(K, L, L); + DST(3, 2) = DST(2, 2) = + DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; +} + +static void HD4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + + DST(0, 0) = DST(2, 1) = AVG2(I, X); + DST(0, 1) = DST(2, 2) = AVG2(J, I); + DST(0, 2) = DST(2, 3) = AVG2(K, J); + DST(0, 3) = AVG2(L, K); + + DST(3, 0) = AVG3(A, B, C); + DST(2, 0) = AVG3(X, A, B); + DST(1, 0) = DST(3, 1) = AVG3(I, X, A); + DST(1, 1) = DST(3, 2) = AVG3(J, I, X); + DST(1, 2) = DST(3, 3) = AVG3(K, J, I); + DST(1, 3) = AVG3(L, K, J); +} + +static void TM4(uint8_t* dst, const uint8_t* top) { + int x, y; + const uint8_t* const clip = clip1 + 255 - top[-1]; + for (y = 0; y < 4; ++y) { + const uint8_t* const clip_table = clip + top[-2 - y]; + for (x = 0; x < 4; ++x) { + dst[x] = clip_table[top[x]]; + } + dst += BPS; + } +} + +#undef DST +#undef AVG3 +#undef AVG2 + +// Left samples are top[-5 .. -2], top_left is top[-1], top are +// located at top[0..3], and top right is top[4..7] +static void Intra4Preds_C(uint8_t* dst, const uint8_t* top) { + DC4(I4DC4 + dst, top); + TM4(I4TM4 + dst, top); + VE4(I4VE4 + dst, top); + HE4(I4HE4 + dst, top); + RD4(I4RD4 + dst, top); + VR4(I4VR4 + dst, top); + LD4(I4LD4 + dst, top); + VL4(I4VL4 + dst, top); + HD4(I4HD4 + dst, top); + HU4(I4HU4 + dst, top); +} + +//------------------------------------------------------------------------------ +// Metric + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b, + int w, int h) { + int count = 0; + int y, x; + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + const int diff = (int)a[x] - b[x]; + count += diff * diff; + } + a += BPS; + b += BPS; + } + return count; +} + +static int SSE16x16_C(const uint8_t* a, const uint8_t* b) { + return GetSSE(a, b, 16, 16); +} +static int SSE16x8_C(const uint8_t* a, const uint8_t* b) { + return GetSSE(a, b, 16, 8); +} +static int SSE8x8_C(const uint8_t* a, const uint8_t* b) { + return GetSSE(a, b, 8, 8); +} +static int SSE4x4_C(const uint8_t* a, const uint8_t* b) { + return GetSSE(a, b, 4, 4); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void Mean16x4_C(const uint8_t* ref, uint32_t dc[4]) { + int k, x, y; + for (k = 0; k < 4; ++k) { + uint32_t avg = 0; + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + avg += ref[x + y * BPS]; + } + } + dc[k] = avg; + ref += 4; // go to next 4x4 block. + } +} + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +#if !WEBP_NEON_OMIT_C_CODE +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +static int TTransform(const uint8_t* in, const uint16_t* w) { + int sum = 0; + int tmp[16]; + int i; + // horizontal pass + for (i = 0; i < 4; ++i, in += BPS) { + const int a0 = in[0] + in[2]; + const int a1 = in[1] + in[3]; + const int a2 = in[1] - in[3]; + const int a3 = in[0] - in[2]; + tmp[0 + i * 4] = a0 + a1; + tmp[1 + i * 4] = a3 + a2; + tmp[2 + i * 4] = a3 - a2; + tmp[3 + i * 4] = a0 - a1; + } + // vertical pass + for (i = 0; i < 4; ++i, ++w) { + const int a0 = tmp[0 + i] + tmp[8 + i]; + const int a1 = tmp[4 + i] + tmp[12+ i]; + const int a2 = tmp[4 + i] - tmp[12+ i]; + const int a3 = tmp[0 + i] - tmp[8 + i]; + const int b0 = a0 + a1; + const int b1 = a3 + a2; + const int b2 = a3 - a2; + const int b3 = a0 - a1; + + sum += w[ 0] * abs(b0); + sum += w[ 4] * abs(b1); + sum += w[ 8] * abs(b2); + sum += w[12] * abs(b3); + } + return sum; +} + +static int Disto4x4_C(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int sum1 = TTransform(a, w); + const int sum2 = TTransform(b, w); + return abs(sum2 - sum1) >> 5; +} + +static int Disto16x16_C(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_C(a + x + y, b + x + y, w); + } + } + return D; +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// Quantization +// + +static const uint8_t kZigzag[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + +// Simple quantization +static int QuantizeBlock_C(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int last = -1; + int n; + for (n = 0; n < 16; ++n) { + const int j = kZigzag[n]; + const int sign = (in[j] < 0); + const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; + if (coeff > mtx->zthresh_[j]) { + const uint32_t Q = mtx->q_[j]; + const uint32_t iQ = mtx->iq_[j]; + const uint32_t B = mtx->bias_[j]; + int level = QUANTDIV(coeff, iQ, B); + if (level > MAX_LEVEL) level = MAX_LEVEL; + if (sign) level = -level; + in[j] = level * (int)Q; + out[n] = level; + if (level) last = n; + } else { + out[n] = 0; + in[j] = 0; + } + } + return (last >= 0); +} + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static int Quantize2Blocks_C(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Block copy + +static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int w, int h) { + int y; + for (y = 0; y < h; ++y) { + memcpy(dst, src, w); + src += BPS; + dst += BPS; + } +} + +static void Copy4x4_C(const uint8_t* src, uint8_t* dst) { + Copy(src, dst, 4, 4); +} + +static void Copy16x8_C(const uint8_t* src, uint8_t* dst) { + Copy(src, dst, 16, 8); +} + +//------------------------------------------------------------------------------ +// Initialization + +// Speed-critical function pointers. We have to initialize them to the default +// implementations within VP8EncDspInit(). +VP8CHisto VP8CollectHistogram; +VP8Idct VP8ITransform; +VP8Fdct VP8FTransform; +VP8Fdct VP8FTransform2; +VP8WHT VP8FTransformWHT; +VP8Intra4Preds VP8EncPredLuma4; +VP8IntraPreds VP8EncPredLuma16; +VP8IntraPreds VP8EncPredChroma8; +VP8Metric VP8SSE16x16; +VP8Metric VP8SSE8x8; +VP8Metric VP8SSE16x8; +VP8Metric VP8SSE4x4; +VP8WMetric VP8TDisto4x4; +VP8WMetric VP8TDisto16x16; +VP8MeanMetric VP8Mean16x4; +VP8QuantizeBlock VP8EncQuantizeBlock; +VP8Quantize2Blocks VP8EncQuantize2Blocks; +VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; +VP8BlockCopy VP8Copy4x4; +VP8BlockCopy VP8Copy16x8; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8EncDspInitSSE2(void); +extern void VP8EncDspInitSSE41(void); +extern void VP8EncDspInitNEON(void); +extern void VP8EncDspInitMIPS32(void); +extern void VP8EncDspInitMIPSdspR2(void); +extern void VP8EncDspInitMSA(void); + +WEBP_DSP_INIT_FUNC(VP8EncDspInit) { + VP8DspInit(); // common inverse transforms + InitTables(); + + // default C implementations +#if !WEBP_NEON_OMIT_C_CODE + VP8ITransform = ITransform_C; + VP8FTransform = FTransform_C; + VP8FTransformWHT = FTransformWHT_C; + VP8TDisto4x4 = Disto4x4_C; + VP8TDisto16x16 = Disto16x16_C; + VP8CollectHistogram = CollectHistogram_C; + VP8SSE16x16 = SSE16x16_C; + VP8SSE16x8 = SSE16x8_C; + VP8SSE8x8 = SSE8x8_C; + VP8SSE4x4 = SSE4x4_C; +#endif + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + VP8EncQuantizeBlock = QuantizeBlock_C; + VP8EncQuantize2Blocks = Quantize2Blocks_C; +#endif + + VP8FTransform2 = FTransform2_C; + VP8EncPredLuma4 = Intra4Preds_C; + VP8EncPredLuma16 = Intra16Preds_C; + VP8EncPredChroma8 = IntraChromaPreds_C; + VP8Mean16x4 = Mean16x4_C; + VP8EncQuantizeBlockWHT = QuantizeBlock_C; + VP8Copy4x4 = Copy4x4_C; + VP8Copy16x8 = Copy16x8_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8EncDspInitSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + VP8EncDspInitSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8EncDspInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8EncDspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8EncDspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8EncDspInitNEON(); + } +#endif + + assert(VP8ITransform != NULL); + assert(VP8FTransform != NULL); + assert(VP8FTransformWHT != NULL); + assert(VP8TDisto4x4 != NULL); + assert(VP8TDisto16x16 != NULL); + assert(VP8CollectHistogram != NULL); + assert(VP8SSE16x16 != NULL); + assert(VP8SSE16x8 != NULL); + assert(VP8SSE8x8 != NULL); + assert(VP8SSE4x4 != NULL); + assert(VP8EncQuantizeBlock != NULL); + assert(VP8EncQuantize2Blocks != NULL); + assert(VP8FTransform2 != NULL); + assert(VP8EncPredLuma4 != NULL); + assert(VP8EncPredLuma16 != NULL); + assert(VP8EncPredChroma8 != NULL); + assert(VP8Mean16x4 != NULL); + assert(VP8EncQuantizeBlockWHT != NULL); + assert(VP8Copy4x4 != NULL); + assert(VP8Copy16x8 != NULL); +} diff --git a/libraries/webp/src/dsp/enc_mips32.c b/libraries/webp/src/dsp/enc_mips32.c new file mode 100644 index 0000000000..50518a5f1a --- /dev/null +++ b/libraries/webp/src/dsp/enc_mips32.c @@ -0,0 +1,673 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of speed-critical encoding functions. +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) +// Slobodan Prijic (slobodan.prijic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) + +#include "src/dsp/mips_macro.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" + +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; + +// macro for one vertical pass in ITransformOne +// MUL macro inlined +// temp0..temp15 holds tmp[0]..tmp[15] +// A..D - offsets in bytes to load from in buffer +// TEMP0..TEMP3 - registers for corresponding tmp elements +// TEMP4..TEMP5 - temporary registers +#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \ + "lh %[temp16], " #A "(%[temp20]) \n\t" \ + "lh %[temp18], " #B "(%[temp20]) \n\t" \ + "lh %[temp17], " #C "(%[temp20]) \n\t" \ + "lh %[temp19], " #D "(%[temp20]) \n\t" \ + "addu %[" #TEMP4 "], %[temp16], %[temp18] \n\t" \ + "subu %[temp16], %[temp16], %[temp18] \n\t" \ + "mul %[" #TEMP0 "], %[temp17], %[kC2] \n\t" \ + MUL_SHIFT_C1_IO(temp17, temp18) \ + MUL_SHIFT_C1(temp18, temp19) \ + "mul %[temp19], %[temp19], %[kC2] \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\n" \ + "sra %[temp19], %[temp19], 16 \n\n" \ + "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp18] \n\t" \ + "addu %[" #TEMP3 "], %[temp17], %[temp19] \n\t" \ + "addu %[" #TEMP0 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" \ + "addu %[" #TEMP1 "], %[temp16], %[" #TEMP2 "] \n\t" \ + "subu %[" #TEMP2 "], %[temp16], %[" #TEMP2 "] \n\t" \ + "subu %[" #TEMP3 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" + +// macro for one horizontal pass in ITransformOne +// MUL and STORE macros inlined +// a = clip_8b(a) is replaced with: a = max(a, 0); a = min(a, 255) +// temp0..temp15 holds tmp[0]..tmp[15] +// A - offset in bytes to load from ref and store to dst buffer +// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements +#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \ + "addiu %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ + "addu %[temp16], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ + "subu %[temp17], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ + "mul %[" #TEMP0 "], %[" #TEMP4 "], %[kC2] \n\t" \ + MUL_SHIFT_C1_IO(TEMP4, TEMP8) \ + MUL_SHIFT_C1(TEMP8, TEMP12) \ + "mul %[" #TEMP12 "], %[" #TEMP12 "], %[kC2] \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ + "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ + "subu %[temp18], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ + "addu %[temp19], %[" #TEMP4 "], %[" #TEMP12 "] \n\t" \ + "addu %[" #TEMP0 "], %[temp16], %[temp19] \n\t" \ + "addu %[" #TEMP4 "], %[temp17], %[temp18] \n\t" \ + "subu %[" #TEMP8 "], %[temp17], %[temp18] \n\t" \ + "subu %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ + "lw %[temp20], 0(%[args]) \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \ + "sra %[" #TEMP4 "], %[" #TEMP4 "], 3 \n\t" \ + "sra %[" #TEMP8 "], %[" #TEMP8 "], 3 \n\t" \ + "sra %[" #TEMP12 "], %[" #TEMP12 "], 3 \n\t" \ + "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ + "lbu %[temp17], 1+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ + "lbu %[temp18], 2+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ + "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ + "addu %[" #TEMP0 "], %[temp16], %[" #TEMP0 "] \n\t" \ + "addu %[" #TEMP4 "], %[temp17], %[" #TEMP4 "] \n\t" \ + "addu %[" #TEMP8 "], %[temp18], %[" #TEMP8 "] \n\t" \ + "addu %[" #TEMP12 "], %[temp19], %[" #TEMP12 "] \n\t" \ + "slt %[temp16], %[" #TEMP0 "], $zero \n\t" \ + "slt %[temp17], %[" #TEMP4 "], $zero \n\t" \ + "slt %[temp18], %[" #TEMP8 "], $zero \n\t" \ + "slt %[temp19], %[" #TEMP12 "], $zero \n\t" \ + "movn %[" #TEMP0 "], $zero, %[temp16] \n\t" \ + "movn %[" #TEMP4 "], $zero, %[temp17] \n\t" \ + "movn %[" #TEMP8 "], $zero, %[temp18] \n\t" \ + "movn %[" #TEMP12 "], $zero, %[temp19] \n\t" \ + "addiu %[temp20], $zero, 255 \n\t" \ + "slt %[temp16], %[" #TEMP0 "], %[temp20] \n\t" \ + "slt %[temp17], %[" #TEMP4 "], %[temp20] \n\t" \ + "slt %[temp18], %[" #TEMP8 "], %[temp20] \n\t" \ + "slt %[temp19], %[" #TEMP12 "], %[temp20] \n\t" \ + "movz %[" #TEMP0 "], %[temp20], %[temp16] \n\t" \ + "movz %[" #TEMP4 "], %[temp20], %[temp17] \n\t" \ + "lw %[temp16], 8(%[args]) \n\t" \ + "movz %[" #TEMP8 "], %[temp20], %[temp18] \n\t" \ + "movz %[" #TEMP12 "], %[temp20], %[temp19] \n\t" \ + "sb %[" #TEMP0 "], 0+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ + "sb %[" #TEMP4 "], 1+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ + "sb %[" #TEMP8 "], 2+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ + "sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" + +// Does one or two inverse transforms. +static WEBP_INLINE void ITransformOne_MIPS32(const uint8_t* ref, + const int16_t* in, + uint8_t* dst) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + int temp7, temp8, temp9, temp10, temp11, temp12, temp13; + int temp14, temp15, temp16, temp17, temp18, temp19, temp20; + const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst}; + + __asm__ volatile( + "lw %[temp20], 4(%[args]) \n\t" + VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3) + VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7) + VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11) + VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15) + + HORIZONTAL_PASS(0, temp0, temp4, temp8, temp12) + HORIZONTAL_PASS(1, temp1, temp5, temp9, temp13) + HORIZONTAL_PASS(2, temp2, temp6, temp10, temp14) + HORIZONTAL_PASS(3, temp3, temp7, temp11, temp15) + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), + [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), + [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), + [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) + : [args]"r"(args), [kC1]"r"(kC1), [kC2]"r"(kC2) + : "memory", "hi", "lo" + ); +} + +static void ITransform_MIPS32(const uint8_t* ref, const int16_t* in, + uint8_t* dst, int do_two) { + ITransformOne_MIPS32(ref, in, dst); + if (do_two) { + ITransformOne_MIPS32(ref + 4, in + 16, dst + 4); + } +} + +#undef VERTICAL_PASS +#undef HORIZONTAL_PASS + +// macro for one pass through for loop in QuantizeBlock +// QUANTDIV macro inlined +// J - offset in bytes (kZigzag[n] * 2) +// K - offset in bytes (kZigzag[n] * 4) +// N - offset in bytes (n * 2) +#define QUANTIZE_ONE(J, K, N) \ + "lh %[temp0], " #J "(%[ppin]) \n\t" \ + "lhu %[temp1], " #J "(%[ppsharpen]) \n\t" \ + "lw %[temp2], " #K "(%[ppzthresh]) \n\t" \ + "sra %[sign], %[temp0], 15 \n\t" \ + "xor %[coeff], %[temp0], %[sign] \n\t" \ + "subu %[coeff], %[coeff], %[sign] \n\t" \ + "addu %[coeff], %[coeff], %[temp1] \n\t" \ + "slt %[temp4], %[temp2], %[coeff] \n\t" \ + "addiu %[temp5], $zero, 0 \n\t" \ + "addiu %[level], $zero, 0 \n\t" \ + "beqz %[temp4], 2f \n\t" \ + "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ + "lw %[temp2], " #K "(%[ppbias]) \n\t" \ + "lhu %[temp3], " #J "(%[ppq]) \n\t" \ + "mul %[level], %[coeff], %[temp1] \n\t" \ + "addu %[level], %[level], %[temp2] \n\t" \ + "sra %[level], %[level], 17 \n\t" \ + "slt %[temp4], %[max_level], %[level] \n\t" \ + "movn %[level], %[max_level], %[temp4] \n\t" \ + "xor %[level], %[level], %[sign] \n\t" \ + "subu %[level], %[level], %[sign] \n\t" \ + "mul %[temp5], %[level], %[temp3] \n\t" \ +"2: \n\t" \ + "sh %[temp5], " #J "(%[ppin]) \n\t" \ + "sh %[level], " #N "(%[pout]) \n\t" + +static int QuantizeBlock_MIPS32(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int temp0, temp1, temp2, temp3, temp4, temp5; + int sign, coeff, level, i; + int max_level = MAX_LEVEL; + + int16_t* ppin = &in[0]; + int16_t* pout = &out[0]; + const uint16_t* ppsharpen = &mtx->sharpen_[0]; + const uint32_t* ppzthresh = &mtx->zthresh_[0]; + const uint16_t* ppq = &mtx->q_[0]; + const uint16_t* ppiq = &mtx->iq_[0]; + const uint32_t* ppbias = &mtx->bias_[0]; + + __asm__ volatile( + QUANTIZE_ONE( 0, 0, 0) + QUANTIZE_ONE( 2, 4, 2) + QUANTIZE_ONE( 8, 16, 4) + QUANTIZE_ONE(16, 32, 6) + QUANTIZE_ONE(10, 20, 8) + QUANTIZE_ONE( 4, 8, 10) + QUANTIZE_ONE( 6, 12, 12) + QUANTIZE_ONE(12, 24, 14) + QUANTIZE_ONE(18, 36, 16) + QUANTIZE_ONE(24, 48, 18) + QUANTIZE_ONE(26, 52, 20) + QUANTIZE_ONE(20, 40, 22) + QUANTIZE_ONE(14, 28, 24) + QUANTIZE_ONE(22, 44, 26) + QUANTIZE_ONE(28, 56, 28) + QUANTIZE_ONE(30, 60, 30) + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [sign]"=&r"(sign), [coeff]"=&r"(coeff), + [level]"=&r"(level) + : [pout]"r"(pout), [ppin]"r"(ppin), + [ppiq]"r"(ppiq), [max_level]"r"(max_level), + [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh), + [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq) + : "memory", "hi", "lo" + ); + + // moved out from macro to increase possibility for earlier breaking + for (i = 15; i >= 0; i--) { + if (out[i]) return 1; + } + return 0; +} + +static int Quantize2Blocks_MIPS32(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = QuantizeBlock_MIPS32(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_MIPS32(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} + +#undef QUANTIZE_ONE + +// macro for one horizontal pass in Disto4x4 (TTransform) +// two calls of function TTransform are merged into single one +// A - offset in bytes to load from a and b buffers +// E..H - offsets in bytes to store first results to tmp buffer +// E1..H1 - offsets in bytes to store second results to tmp buffer +#define HORIZONTAL_PASS(A, E, F, G, H, E1, F1, G1, H1) \ + "lbu %[temp0], 0+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ + "lbu %[temp1], 1+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ + "lbu %[temp2], 2+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ + "lbu %[temp3], 3+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ + "lbu %[temp4], 0+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ + "lbu %[temp5], 1+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ + "lbu %[temp6], 2+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ + "lbu %[temp7], 3+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ + "addu %[temp8], %[temp0], %[temp2] \n\t" \ + "subu %[temp0], %[temp0], %[temp2] \n\t" \ + "addu %[temp2], %[temp1], %[temp3] \n\t" \ + "subu %[temp1], %[temp1], %[temp3] \n\t" \ + "addu %[temp3], %[temp4], %[temp6] \n\t" \ + "subu %[temp4], %[temp4], %[temp6] \n\t" \ + "addu %[temp6], %[temp5], %[temp7] \n\t" \ + "subu %[temp5], %[temp5], %[temp7] \n\t" \ + "addu %[temp7], %[temp8], %[temp2] \n\t" \ + "subu %[temp2], %[temp8], %[temp2] \n\t" \ + "addu %[temp8], %[temp0], %[temp1] \n\t" \ + "subu %[temp0], %[temp0], %[temp1] \n\t" \ + "addu %[temp1], %[temp3], %[temp6] \n\t" \ + "subu %[temp3], %[temp3], %[temp6] \n\t" \ + "addu %[temp6], %[temp4], %[temp5] \n\t" \ + "subu %[temp4], %[temp4], %[temp5] \n\t" \ + "sw %[temp7], " #E "(%[tmp]) \n\t" \ + "sw %[temp2], " #H "(%[tmp]) \n\t" \ + "sw %[temp8], " #F "(%[tmp]) \n\t" \ + "sw %[temp0], " #G "(%[tmp]) \n\t" \ + "sw %[temp1], " #E1 "(%[tmp]) \n\t" \ + "sw %[temp3], " #H1 "(%[tmp]) \n\t" \ + "sw %[temp6], " #F1 "(%[tmp]) \n\t" \ + "sw %[temp4], " #G1 "(%[tmp]) \n\t" + +// macro for one vertical pass in Disto4x4 (TTransform) +// two calls of function TTransform are merged into single one +// since only one accu is available in mips32r1 instruction set +// first is done second call of function TTransform and after +// that first one. +// const int sum1 = TTransform(a, w); +// const int sum2 = TTransform(b, w); +// return abs(sum2 - sum1) >> 5; +// (sum2 - sum1) is calculated with madds (sub2) and msubs (sub1) +// A..D - offsets in bytes to load first results from tmp buffer +// A1..D1 - offsets in bytes to load second results from tmp buffer +// E..H - offsets in bytes to load from w buffer +#define VERTICAL_PASS(A, B, C, D, A1, B1, C1, D1, E, F, G, H) \ + "lw %[temp0], " #A1 "(%[tmp]) \n\t" \ + "lw %[temp1], " #C1 "(%[tmp]) \n\t" \ + "lw %[temp2], " #B1 "(%[tmp]) \n\t" \ + "lw %[temp3], " #D1 "(%[tmp]) \n\t" \ + "addu %[temp8], %[temp0], %[temp1] \n\t" \ + "subu %[temp0], %[temp0], %[temp1] \n\t" \ + "addu %[temp1], %[temp2], %[temp3] \n\t" \ + "subu %[temp2], %[temp2], %[temp3] \n\t" \ + "addu %[temp3], %[temp8], %[temp1] \n\t" \ + "subu %[temp8], %[temp8], %[temp1] \n\t" \ + "addu %[temp1], %[temp0], %[temp2] \n\t" \ + "subu %[temp0], %[temp0], %[temp2] \n\t" \ + "sra %[temp4], %[temp3], 31 \n\t" \ + "sra %[temp5], %[temp1], 31 \n\t" \ + "sra %[temp6], %[temp0], 31 \n\t" \ + "sra %[temp7], %[temp8], 31 \n\t" \ + "xor %[temp3], %[temp3], %[temp4] \n\t" \ + "xor %[temp1], %[temp1], %[temp5] \n\t" \ + "xor %[temp0], %[temp0], %[temp6] \n\t" \ + "xor %[temp8], %[temp8], %[temp7] \n\t" \ + "subu %[temp3], %[temp3], %[temp4] \n\t" \ + "subu %[temp1], %[temp1], %[temp5] \n\t" \ + "subu %[temp0], %[temp0], %[temp6] \n\t" \ + "subu %[temp8], %[temp8], %[temp7] \n\t" \ + "lhu %[temp4], " #E "(%[w]) \n\t" \ + "lhu %[temp5], " #F "(%[w]) \n\t" \ + "lhu %[temp6], " #G "(%[w]) \n\t" \ + "lhu %[temp7], " #H "(%[w]) \n\t" \ + "madd %[temp4], %[temp3] \n\t" \ + "madd %[temp5], %[temp1] \n\t" \ + "madd %[temp6], %[temp0] \n\t" \ + "madd %[temp7], %[temp8] \n\t" \ + "lw %[temp0], " #A "(%[tmp]) \n\t" \ + "lw %[temp1], " #C "(%[tmp]) \n\t" \ + "lw %[temp2], " #B "(%[tmp]) \n\t" \ + "lw %[temp3], " #D "(%[tmp]) \n\t" \ + "addu %[temp8], %[temp0], %[temp1] \n\t" \ + "subu %[temp0], %[temp0], %[temp1] \n\t" \ + "addu %[temp1], %[temp2], %[temp3] \n\t" \ + "subu %[temp2], %[temp2], %[temp3] \n\t" \ + "addu %[temp3], %[temp8], %[temp1] \n\t" \ + "subu %[temp1], %[temp8], %[temp1] \n\t" \ + "addu %[temp8], %[temp0], %[temp2] \n\t" \ + "subu %[temp0], %[temp0], %[temp2] \n\t" \ + "sra %[temp2], %[temp3], 31 \n\t" \ + "xor %[temp3], %[temp3], %[temp2] \n\t" \ + "subu %[temp3], %[temp3], %[temp2] \n\t" \ + "msub %[temp4], %[temp3] \n\t" \ + "sra %[temp2], %[temp8], 31 \n\t" \ + "sra %[temp3], %[temp0], 31 \n\t" \ + "sra %[temp4], %[temp1], 31 \n\t" \ + "xor %[temp8], %[temp8], %[temp2] \n\t" \ + "xor %[temp0], %[temp0], %[temp3] \n\t" \ + "xor %[temp1], %[temp1], %[temp4] \n\t" \ + "subu %[temp8], %[temp8], %[temp2] \n\t" \ + "subu %[temp0], %[temp0], %[temp3] \n\t" \ + "subu %[temp1], %[temp1], %[temp4] \n\t" \ + "msub %[temp5], %[temp8] \n\t" \ + "msub %[temp6], %[temp0] \n\t" \ + "msub %[temp7], %[temp1] \n\t" + +static int Disto4x4_MIPS32(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int tmp[32]; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + + __asm__ volatile( + HORIZONTAL_PASS(0, 0, 4, 8, 12, 64, 68, 72, 76) + HORIZONTAL_PASS(1, 16, 20, 24, 28, 80, 84, 88, 92) + HORIZONTAL_PASS(2, 32, 36, 40, 44, 96, 100, 104, 108) + HORIZONTAL_PASS(3, 48, 52, 56, 60, 112, 116, 120, 124) + "mthi $zero \n\t" + "mtlo $zero \n\t" + VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24) + VERTICAL_PASS( 4, 20, 36, 52, 68, 84, 100, 116, 2, 10, 18, 26) + VERTICAL_PASS( 8, 24, 40, 56, 72, 88, 104, 120, 4, 12, 20, 28) + VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30) + "mflo %[temp0] \n\t" + "sra %[temp1], %[temp0], 31 \n\t" + "xor %[temp0], %[temp0], %[temp1] \n\t" + "subu %[temp0], %[temp0], %[temp1] \n\t" + "sra %[temp0], %[temp0], 5 \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) + : [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp) + : "memory", "hi", "lo" + ); + + return temp0; +} + +#undef VERTICAL_PASS +#undef HORIZONTAL_PASS + +static int Disto16x16_MIPS32(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_MIPS32(a + x + y, b + x + y, w); + } + } + return D; +} + +// macro for one horizontal pass in FTransform +// temp0..temp15 holds tmp[0]..tmp[15] +// A - offset in bytes to load from src and ref buffers +// TEMP0..TEMP3 - registers for corresponding tmp elements +#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \ + "lw %[" #TEMP1 "], 0(%[args]) \n\t" \ + "lw %[" #TEMP2 "], 4(%[args]) \n\t" \ + "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "lbu %[temp17], 0+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ + "lbu %[temp18], 1+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "lbu %[temp19], 1+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ + "subu %[temp20], %[temp16], %[temp17] \n\t" \ + "lbu %[temp16], 2+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "lbu %[temp17], 2+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ + "subu %[" #TEMP0 "], %[temp18], %[temp19] \n\t" \ + "lbu %[temp18], 3+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ + "subu %[" #TEMP1 "], %[temp16], %[temp17] \n\t" \ + "subu %[" #TEMP2 "], %[temp18], %[temp19] \n\t" \ + "addu %[" #TEMP3 "], %[temp20], %[" #TEMP2 "] \n\t" \ + "subu %[" #TEMP2 "], %[temp20], %[" #TEMP2 "] \n\t" \ + "addu %[temp20], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ + "subu %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ + "mul %[temp16], %[" #TEMP2 "], %[c5352] \n\t" \ + "mul %[temp17], %[" #TEMP2 "], %[c2217] \n\t" \ + "mul %[temp18], %[" #TEMP0 "], %[c5352] \n\t" \ + "mul %[temp19], %[" #TEMP0 "], %[c2217] \n\t" \ + "addu %[" #TEMP1 "], %[" #TEMP3 "], %[temp20] \n\t" \ + "subu %[temp20], %[" #TEMP3 "], %[temp20] \n\t" \ + "sll %[" #TEMP0 "], %[" #TEMP1 "], 3 \n\t" \ + "sll %[" #TEMP2 "], %[temp20], 3 \n\t" \ + "addiu %[temp16], %[temp16], 1812 \n\t" \ + "addiu %[temp17], %[temp17], 937 \n\t" \ + "addu %[temp16], %[temp16], %[temp19] \n\t" \ + "subu %[temp17], %[temp17], %[temp18] \n\t" \ + "sra %[" #TEMP1 "], %[temp16], 9 \n\t" \ + "sra %[" #TEMP3 "], %[temp17], 9 \n\t" + +// macro for one vertical pass in FTransform +// temp0..temp15 holds tmp[0]..tmp[15] +// A..D - offsets in bytes to store to out buffer +// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements +#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \ + "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ + "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ + "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ + "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ + "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \ + "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \ + "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \ + "mul %[temp18], %[temp18], %[c5352] \n\t" \ + "addiu %[temp16], %[temp16], 7 \n\t" \ + "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ + "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \ + "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \ + "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \ + "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \ + "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \ + "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \ + "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \ + "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ + "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ + "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \ + "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ + "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \ + "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \ + "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ + "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" + +static void FTransform_MIPS32(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; + int temp17, temp18, temp19, temp20; + const int c2217 = 2217; + const int c5352 = 5352; + const int* const args[3] = + { (const int*)src, (const int*)ref, (const int*)out }; + + __asm__ volatile( + HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3) + HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7) + HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11) + HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15) + "lw %[temp20], 8(%[args]) \n\t" + VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12) + VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13) + VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14) + VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15) + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), + [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), + [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), + [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) + : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352) + : "memory", "hi", "lo" + ); +} + +#undef VERTICAL_PASS +#undef HORIZONTAL_PASS + +#if !defined(WORK_AROUND_GCC) + +#define GET_SSE_INNER(A, B, C, D) \ + "lbu %[temp0], " #A "(%[a]) \n\t" \ + "lbu %[temp1], " #A "(%[b]) \n\t" \ + "lbu %[temp2], " #B "(%[a]) \n\t" \ + "lbu %[temp3], " #B "(%[b]) \n\t" \ + "lbu %[temp4], " #C "(%[a]) \n\t" \ + "lbu %[temp5], " #C "(%[b]) \n\t" \ + "lbu %[temp6], " #D "(%[a]) \n\t" \ + "lbu %[temp7], " #D "(%[b]) \n\t" \ + "subu %[temp0], %[temp0], %[temp1] \n\t" \ + "subu %[temp2], %[temp2], %[temp3] \n\t" \ + "subu %[temp4], %[temp4], %[temp5] \n\t" \ + "subu %[temp6], %[temp6], %[temp7] \n\t" \ + "madd %[temp0], %[temp0] \n\t" \ + "madd %[temp2], %[temp2] \n\t" \ + "madd %[temp4], %[temp4] \n\t" \ + "madd %[temp6], %[temp6] \n\t" + +#define GET_SSE(A, B, C, D) \ + GET_SSE_INNER(A, A + 1, A + 2, A + 3) \ + GET_SSE_INNER(B, B + 1, B + 2, B + 3) \ + GET_SSE_INNER(C, C + 1, C + 2, C + 3) \ + GET_SSE_INNER(D, D + 1, D + 2, D + 3) + +static int SSE16x16_MIPS32(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile( + "mult $zero, $zero \n\t" + + GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) + GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) + GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) + GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) + GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) + GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) + GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) + GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) + GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) + GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) + GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) + GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) + GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) + GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) + GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) + GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) + + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE16x8_MIPS32(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile( + "mult $zero, $zero \n\t" + + GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) + GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) + GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) + GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) + GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) + GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) + GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) + GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) + + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE8x8_MIPS32(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile( + "mult $zero, $zero \n\t" + + GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) + GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) + GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) + GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) + + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE4x4_MIPS32(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile( + "mult $zero, $zero \n\t" + + GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) + + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +#undef GET_SSE +#undef GET_SSE_INNER + +#endif // !WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPS32(void) { + VP8ITransform = ITransform_MIPS32; + VP8FTransform = FTransform_MIPS32; + + VP8EncQuantizeBlock = QuantizeBlock_MIPS32; + VP8EncQuantize2Blocks = Quantize2Blocks_MIPS32; + + VP8TDisto4x4 = Disto4x4_MIPS32; + VP8TDisto16x16 = Disto16x16_MIPS32; + +#if !defined(WORK_AROUND_GCC) + VP8SSE16x16 = SSE16x16_MIPS32; + VP8SSE8x8 = SSE8x8_MIPS32; + VP8SSE16x8 = SSE16x8_MIPS32; + VP8SSE4x4 = SSE4x4_MIPS32; +#endif +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(VP8EncDspInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/libraries/webp/src/dsp/enc_mips_dsp_r2.c b/libraries/webp/src/dsp/enc_mips_dsp_r2.c new file mode 100644 index 0000000000..e1431f3bef --- /dev/null +++ b/libraries/webp/src/dsp/enc_mips_dsp_r2.c @@ -0,0 +1,1517 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of speed-critical encoding functions. +// +// Author(s): Darko Laus (darko.laus@imgtec.com) +// Mirko Raus (mirko.raus@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/mips_macro.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" + +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; + +// O - output +// I - input (macro doesn't change it) +#define ADD_SUB_HALVES_X4(O0, O1, O2, O3, O4, O5, O6, O7, \ + I0, I1, I2, I3, I4, I5, I6, I7) \ + "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \ + "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" \ + "addq.ph %[" #O2 "], %[" #I2 "], %[" #I3 "] \n\t" \ + "subq.ph %[" #O3 "], %[" #I2 "], %[" #I3 "] \n\t" \ + "addq.ph %[" #O4 "], %[" #I4 "], %[" #I5 "] \n\t" \ + "subq.ph %[" #O5 "], %[" #I4 "], %[" #I5 "] \n\t" \ + "addq.ph %[" #O6 "], %[" #I6 "], %[" #I7 "] \n\t" \ + "subq.ph %[" #O7 "], %[" #I6 "], %[" #I7 "] \n\t" + +// IO - input/output +#define ABS_X8(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7) \ + "absq_s.ph %[" #IO0 "], %[" #IO0 "] \n\t" \ + "absq_s.ph %[" #IO1 "], %[" #IO1 "] \n\t" \ + "absq_s.ph %[" #IO2 "], %[" #IO2 "] \n\t" \ + "absq_s.ph %[" #IO3 "], %[" #IO3 "] \n\t" \ + "absq_s.ph %[" #IO4 "], %[" #IO4 "] \n\t" \ + "absq_s.ph %[" #IO5 "], %[" #IO5 "] \n\t" \ + "absq_s.ph %[" #IO6 "], %[" #IO6 "] \n\t" \ + "absq_s.ph %[" #IO7 "], %[" #IO7 "] \n\t" + +// dpa.w.ph $ac0 temp0 ,temp1 +// $ac += temp0[31..16] * temp1[31..16] + temp0[15..0] * temp1[15..0] +// dpax.w.ph $ac0 temp0 ,temp1 +// $ac += temp0[31..16] * temp1[15..0] + temp0[15..0] * temp1[31..16] +// O - output +// I - input (macro doesn't change it) +#define MUL_HALF(O0, I0, I1, I2, I3, I4, I5, I6, I7, \ + I8, I9, I10, I11, I12, I13, I14, I15) \ + "mult $ac0, $zero, $zero \n\t" \ + "dpa.w.ph $ac0, %[" #I2 "], %[" #I0 "] \n\t" \ + "dpax.w.ph $ac0, %[" #I5 "], %[" #I6 "] \n\t" \ + "dpa.w.ph $ac0, %[" #I8 "], %[" #I9 "] \n\t" \ + "dpax.w.ph $ac0, %[" #I11 "], %[" #I4 "] \n\t" \ + "dpa.w.ph $ac0, %[" #I12 "], %[" #I7 "] \n\t" \ + "dpax.w.ph $ac0, %[" #I13 "], %[" #I1 "] \n\t" \ + "dpa.w.ph $ac0, %[" #I14 "], %[" #I3 "] \n\t" \ + "dpax.w.ph $ac0, %[" #I15 "], %[" #I10 "] \n\t" \ + "mflo %[" #O0 "], $ac0 \n\t" + +#define OUTPUT_EARLY_CLOBBER_REGS_17() \ + OUTPUT_EARLY_CLOBBER_REGS_10(), \ + [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \ + [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \ + [temp17]"=&r"(temp17) + +// macro for one horizontal pass in FTransform +// temp0..temp15 holds tmp[0]..tmp[15] +// A - offset in bytes to load from src and ref buffers +// TEMP0..TEMP3 - registers for corresponding tmp elements +#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \ + "lw %[" #TEMP0 "], 0(%[args]) \n\t" \ + "lw %[" #TEMP1 "], 4(%[args]) \n\t" \ + "lw %[" #TEMP2 "], " XSTR(BPS) "*" #A "(%[" #TEMP0 "]) \n\t" \ + "lw %[" #TEMP3 "], " XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "preceu.ph.qbl %[" #TEMP0 "], %[" #TEMP2 "] \n\t" \ + "preceu.ph.qbl %[" #TEMP1 "], %[" #TEMP3 "] \n\t" \ + "preceu.ph.qbr %[" #TEMP2 "], %[" #TEMP2 "] \n\t" \ + "preceu.ph.qbr %[" #TEMP3 "], %[" #TEMP3 "] \n\t" \ + "subq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ + "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP3 "] \n\t" \ + "rotr %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ + "addq.ph %[" #TEMP1 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \ + "subq.ph %[" #TEMP3 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \ + "seh %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ + "sra %[temp16], %[" #TEMP1 "], 16 \n\t" \ + "seh %[temp19], %[" #TEMP3 "] \n\t" \ + "sra %[" #TEMP3 "], %[" #TEMP3 "], 16 \n\t" \ + "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp16] \n\t" \ + "addu %[" #TEMP0 "], %[" #TEMP0 "], %[temp16] \n\t" \ + "mul %[temp17], %[temp19], %[c2217] \n\t" \ + "mul %[temp18], %[" #TEMP3 "], %[c5352] \n\t" \ + "mul %[" #TEMP1 "], %[temp19], %[c5352] \n\t" \ + "mul %[temp16], %[" #TEMP3 "], %[c2217] \n\t" \ + "sll %[" #TEMP2 "], %[" #TEMP2 "], 3 \n\t" \ + "sll %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \ + "subu %[" #TEMP3 "], %[temp17], %[temp18] \n\t" \ + "addu %[" #TEMP1 "], %[temp16], %[" #TEMP1 "] \n\t" \ + "addiu %[" #TEMP3 "], %[" #TEMP3 "], 937 \n\t" \ + "addiu %[" #TEMP1 "], %[" #TEMP1 "], 1812 \n\t" \ + "sra %[" #TEMP3 "], %[" #TEMP3 "], 9 \n\t" \ + "sra %[" #TEMP1 "], %[" #TEMP1 "], 9 \n\t" + +// macro for one vertical pass in FTransform +// temp0..temp15 holds tmp[0]..tmp[15] +// A..D - offsets in bytes to store to out buffer +// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements +#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \ + "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ + "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ + "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ + "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ + "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \ + "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \ + "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \ + "mul %[temp18], %[temp18], %[c5352] \n\t" \ + "addiu %[temp16], %[temp16], 7 \n\t" \ + "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ + "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \ + "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \ + "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \ + "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \ + "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \ + "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \ + "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \ + "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ + "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ + "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \ + "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ + "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \ + "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \ + "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ + "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" + +static void FTransform_MIPSdspR2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const int c2217 = 2217; + const int c5352 = 5352; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; + int temp17, temp18, temp19, temp20; + const int* const args[3] = + { (const int*)src, (const int*)ref, (const int*)out }; + + __asm__ volatile ( + HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3) + HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7) + HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11) + HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15) + "lw %[temp20], 8(%[args]) \n\t" + VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12) + VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13) + VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14) + VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15) + OUTPUT_EARLY_CLOBBER_REGS_18(), + [temp0]"=&r"(temp0), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) + : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352) + : "memory", "hi", "lo" + ); +} + +#undef VERTICAL_PASS +#undef HORIZONTAL_PASS + +static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; + + __asm__ volatile ( + "ulw %[temp1], 0(%[in]) \n\t" + "ulw %[temp2], 16(%[in]) \n\t" + LOAD_IN_X2(temp5, temp6, 24, 26) + ADD_SUB_HALVES(temp3, temp4, temp1, temp2) + LOAD_IN_X2(temp1, temp2, 8, 10) + MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, + temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6, + temp13, temp11, temp14, temp12) + INSERT_HALF_X2(temp8, temp7, temp10, temp9) + "ulw %[temp17], 4(%[in]) \n\t" + "ulw %[temp18], 20(%[in]) \n\t" + ADD_SUB_HALVES(temp1, temp2, temp3, temp8) + ADD_SUB_HALVES(temp5, temp6, temp4, temp7) + ADD_SUB_HALVES(temp7, temp8, temp17, temp18) + LOAD_IN_X2(temp17, temp18, 12, 14) + LOAD_IN_X2(temp9, temp10, 28, 30) + MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17, + temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10, + temp15, temp4, temp16, temp17) + INSERT_HALF_X2(temp11, temp12, temp13, temp14) + ADD_SUB_HALVES(temp17, temp8, temp8, temp11) + ADD_SUB_HALVES(temp3, temp4, temp7, temp12) + + // horizontal + SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6) + INSERT_HALF_X2(temp1, temp6, temp5, temp2) + SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8) + "repl.ph %[temp2], 0x4 \n\t" + INSERT_HALF_X2(temp3, temp8, temp17, temp4) + "addq.ph %[temp1], %[temp1], %[temp2] \n\t" + "addq.ph %[temp6], %[temp6], %[temp2] \n\t" + ADD_SUB_HALVES(temp2, temp4, temp1, temp3) + ADD_SUB_HALVES(temp5, temp7, temp6, temp8) + MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18, + temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15, + temp6, temp17, temp8, temp18) + MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16, + temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14, + temp18, temp12, temp17, temp16) + INSERT_HALF_X2(temp1, temp3, temp9, temp13) + INSERT_HALF_X2(temp6, temp8, temp11, temp15) + SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15, + temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8, + temp6) + PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13, + temp16, temp11, temp10, temp15, temp14) + LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, ref, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10, + temp11, temp10, temp11, temp14, temp15) + STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11, + temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4, + dst, 0, 1, 2, 3, BPS) + + OUTPUT_EARLY_CLOBBER_REGS_18() + : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2), [ref]"r"(ref) + : "memory", "hi", "lo" + ); +} + +static void ITransform_MIPSdspR2(const uint8_t* ref, const int16_t* in, + uint8_t* dst, int do_two) { + ITransformOne(ref, in, dst); + if (do_two) { + ITransformOne(ref + 4, in + 16, dst + 4); + } +} + +static int Disto4x4_MIPSdspR2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17; + + __asm__ volatile ( + LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, a, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp9,temp10, temp11, + temp12, temp1, temp2, temp3, temp4) + ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12) + PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5, + temp7, temp2, temp4, temp6, temp8) + ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10, + temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12) + ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12, + temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10) + ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2, + temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12) + ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2) + LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w, + 0, 4, 8, 12, + 1, 1, 1, 1, + 16) + MUL_HALF(temp17, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16) + LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, b, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp5,temp6, temp7, temp8, temp9,temp10, temp11, + temp12, temp1, temp2, temp3, temp4) + ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12) + PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5, + temp7, temp2, temp4, temp6, temp8) + ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10, + temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12) + ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12, + temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10) + ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2, + temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12) + ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2) + LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w, + 0, 4, 8, 12, + 1, 1, 1, 1, + 16) + MUL_HALF(temp3, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16) + OUTPUT_EARLY_CLOBBER_REGS_17() + : [a]"r"(a), [b]"r"(b), [w]"r"(w) + : "memory", "hi", "lo" + ); + return abs(temp3 - temp17) >> 5; +} + +static int Disto16x16_MIPSdspR2(const uint8_t* const a, + const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_MIPSdspR2(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ +// Intra predictions + +#define FILL_PART(J, SIZE) \ + "usw %[value], 0+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ + "usw %[value], 4+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ + ".if " #SIZE " == 16 \n\t" \ + "usw %[value], 8+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ + "usw %[value], 12+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ + ".endif \n\t" + +#define FILL_8_OR_16(DST, VALUE, SIZE) do { \ + int value = (VALUE); \ + __asm__ volatile ( \ + "replv.qb %[value], %[value] \n\t" \ + FILL_PART( 0, SIZE) \ + FILL_PART( 1, SIZE) \ + FILL_PART( 2, SIZE) \ + FILL_PART( 3, SIZE) \ + FILL_PART( 4, SIZE) \ + FILL_PART( 5, SIZE) \ + FILL_PART( 6, SIZE) \ + FILL_PART( 7, SIZE) \ + ".if " #SIZE " == 16 \n\t" \ + FILL_PART( 8, 16) \ + FILL_PART( 9, 16) \ + FILL_PART(10, 16) \ + FILL_PART(11, 16) \ + FILL_PART(12, 16) \ + FILL_PART(13, 16) \ + FILL_PART(14, 16) \ + FILL_PART(15, 16) \ + ".endif \n\t" \ + : [value]"+&r"(value) \ + : [dst]"r"((DST)) \ + : "memory" \ + ); \ +} while (0) + +#define VERTICAL_PRED(DST, TOP, SIZE) \ +static WEBP_INLINE void VerticalPred##SIZE(uint8_t* (DST), \ + const uint8_t* (TOP)) { \ + int j; \ + if ((TOP)) { \ + for (j = 0; j < (SIZE); ++j) memcpy((DST) + j * BPS, (TOP), (SIZE)); \ + } else { \ + FILL_8_OR_16((DST), 127, (SIZE)); \ + } \ +} + +VERTICAL_PRED(dst, top, 8) +VERTICAL_PRED(dst, top, 16) + +#undef VERTICAL_PRED + +#define HORIZONTAL_PRED(DST, LEFT, SIZE) \ +static WEBP_INLINE void HorizontalPred##SIZE(uint8_t* (DST), \ + const uint8_t* (LEFT)) { \ + if (LEFT) { \ + int j; \ + for (j = 0; j < (SIZE); ++j) { \ + memset((DST) + j * BPS, (LEFT)[j], (SIZE)); \ + } \ + } else { \ + FILL_8_OR_16((DST), 129, (SIZE)); \ + } \ +} + +HORIZONTAL_PRED(dst, left, 8) +HORIZONTAL_PRED(dst, left, 16) + +#undef HORIZONTAL_PRED + +#define CLIPPING() \ + "preceu.ph.qbl %[temp2], %[temp0] \n\t" \ + "preceu.ph.qbr %[temp0], %[temp0] \n\t" \ + "preceu.ph.qbl %[temp3], %[temp1] \n\t" \ + "preceu.ph.qbr %[temp1], %[temp1] \n\t" \ + "addu.ph %[temp2], %[temp2], %[leftY_1] \n\t" \ + "addu.ph %[temp0], %[temp0], %[leftY_1] \n\t" \ + "addu.ph %[temp3], %[temp3], %[leftY_1] \n\t" \ + "addu.ph %[temp1], %[temp1], %[leftY_1] \n\t" \ + "shll_s.ph %[temp2], %[temp2], 7 \n\t" \ + "shll_s.ph %[temp0], %[temp0], 7 \n\t" \ + "shll_s.ph %[temp3], %[temp3], 7 \n\t" \ + "shll_s.ph %[temp1], %[temp1], 7 \n\t" \ + "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \ + "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" + +#define CLIP_8B_TO_DST(DST, LEFT, TOP, SIZE) do { \ + int leftY_1 = ((int)(LEFT)[y] << 16) + (LEFT)[y]; \ + int temp0, temp1, temp2, temp3; \ + __asm__ volatile ( \ + "replv.ph %[leftY_1], %[leftY_1] \n\t" \ + "ulw %[temp0], 0(%[top]) \n\t" \ + "ulw %[temp1], 4(%[top]) \n\t" \ + "subu.ph %[leftY_1], %[leftY_1], %[left_1] \n\t" \ + CLIPPING() \ + "usw %[temp0], 0(%[dst]) \n\t" \ + "usw %[temp1], 4(%[dst]) \n\t" \ + ".if " #SIZE " == 16 \n\t" \ + "ulw %[temp0], 8(%[top]) \n\t" \ + "ulw %[temp1], 12(%[top]) \n\t" \ + CLIPPING() \ + "usw %[temp0], 8(%[dst]) \n\t" \ + "usw %[temp1], 12(%[dst]) \n\t" \ + ".endif \n\t" \ + : [leftY_1]"+&r"(leftY_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ + : [left_1]"r"(left_1), [top]"r"((TOP)), [dst]"r"((DST)) \ + : "memory" \ + ); \ +} while (0) + +#define CLIP_TO_DST(DST, LEFT, TOP, SIZE) do { \ + int y; \ + const int left_1 = ((int)(LEFT)[-1] << 16) + (LEFT)[-1]; \ + for (y = 0; y < (SIZE); ++y) { \ + CLIP_8B_TO_DST((DST), (LEFT), (TOP), (SIZE)); \ + (DST) += BPS; \ + } \ +} while (0) + +#define TRUE_MOTION(DST, LEFT, TOP, SIZE) \ +static WEBP_INLINE void TrueMotion##SIZE(uint8_t* (DST), const uint8_t* (LEFT),\ + const uint8_t* (TOP)) { \ + if ((LEFT) != NULL) { \ + if ((TOP) != NULL) { \ + CLIP_TO_DST((DST), (LEFT), (TOP), (SIZE)); \ + } else { \ + HorizontalPred##SIZE((DST), (LEFT)); \ + } \ + } else { \ + /* true motion without left samples (hence: with default 129 value) */ \ + /* is equivalent to VE prediction where you just copy the top samples. */ \ + /* Note that if top samples are not available, the default value is */ \ + /* then 129, and not 127 as in the VerticalPred case. */ \ + if ((TOP) != NULL) { \ + VerticalPred##SIZE((DST), (TOP)); \ + } else { \ + FILL_8_OR_16((DST), 129, (SIZE)); \ + } \ + } \ +} + +TRUE_MOTION(dst, left, top, 8) +TRUE_MOTION(dst, left, top, 16) + +#undef TRUE_MOTION +#undef CLIP_TO_DST +#undef CLIP_8B_TO_DST +#undef CLIPPING + +static WEBP_INLINE void DCMode16(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + int DC, DC1; + int temp0, temp1, temp2, temp3; + + __asm__ volatile( + "beqz %[top], 2f \n\t" + LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, top, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[DC], %[temp0], %[temp2] \n\t" + "move %[DC1], %[DC] \n\t" + "beqz %[left], 1f \n\t" + LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[DC1], %[temp0], %[temp2] \n\t" + "1: \n\t" + "addu %[DC], %[DC], %[DC1] \n\t" + "j 3f \n\t" + "2: \n\t" + "beqz %[left], 4f \n\t" + LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[DC], %[temp0], %[temp2] \n\t" + "addu %[DC], %[DC], %[DC] \n\t" + "3: \n\t" + "shra_r.w %[DC], %[DC], 5 \n\t" + "j 5f \n\t" + "4: \n\t" + "li %[DC], 0x80 \n\t" + "5: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1) + : [left]"r"(left), [top]"r"(top) + : "memory" + ); + + FILL_8_OR_16(dst, DC, 16); +} + +static WEBP_INLINE void DCMode8(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + int DC, DC1; + int temp0, temp1, temp2, temp3; + + __asm__ volatile( + "beqz %[top], 2f \n\t" + "ulw %[temp0], 0(%[top]) \n\t" + "ulw %[temp1], 4(%[top]) \n\t" + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[DC], %[temp0], %[temp1] \n\t" + "move %[DC1], %[DC] \n\t" + "beqz %[left], 1f \n\t" + "ulw %[temp2], 0(%[left]) \n\t" + "ulw %[temp3], 4(%[left]) \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[DC1], %[temp2], %[temp3] \n\t" + "1: \n\t" + "addu %[DC], %[DC], %[DC1] \n\t" + "j 3f \n\t" + "2: \n\t" + "beqz %[left], 4f \n\t" + "ulw %[temp2], 0(%[left]) \n\t" + "ulw %[temp3], 4(%[left]) \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[DC], %[temp2], %[temp3] \n\t" + "addu %[DC], %[DC], %[DC] \n\t" + "3: \n\t" + "shra_r.w %[DC], %[DC], 4 \n\t" + "j 5f \n\t" + "4: \n\t" + "li %[DC], 0x80 \n\t" + "5: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1) + : [left]"r"(left), [top]"r"(top) + : "memory" + ); + + FILL_8_OR_16(dst, DC, 8); +} + +static void DC4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1; + __asm__ volatile( + "ulw %[temp0], 0(%[top]) \n\t" + "ulw %[temp1], -5(%[top]) \n\t" + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addiu %[temp0], %[temp0], 4 \n\t" + "srl %[temp0], %[temp0], 3 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + "usw %[temp0], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void TM4(uint8_t* dst, const uint8_t* top) { + int a10, a32, temp0, temp1, temp2, temp3, temp4, temp5; + const int c35 = 0xff00ff; + __asm__ volatile ( + "lbu %[temp1], 0(%[top]) \n\t" + "lbu %[a10], 1(%[top]) \n\t" + "lbu %[temp2], 2(%[top]) \n\t" + "lbu %[a32], 3(%[top]) \n\t" + "ulw %[temp0], -5(%[top]) \n\t" + "lbu %[temp4], -1(%[top]) \n\t" + "append %[a10], %[temp1], 16 \n\t" + "append %[a32], %[temp2], 16 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "shrl.ph %[temp1], %[temp0], 8 \n\t" + "and %[temp0], %[temp0], %[c35] \n\t" + "subu.ph %[temp1], %[temp1], %[temp4] \n\t" + "subu.ph %[temp0], %[temp0], %[temp4] \n\t" + "srl %[temp2], %[temp1], 16 \n\t" + "srl %[temp3], %[temp0], 16 \n\t" + "replv.ph %[temp2], %[temp2] \n\t" + "replv.ph %[temp3], %[temp3] \n\t" + "replv.ph %[temp4], %[temp1] \n\t" + "replv.ph %[temp5], %[temp0] \n\t" + "addu.ph %[temp0], %[temp3], %[a10] \n\t" + "addu.ph %[temp1], %[temp3], %[a32] \n\t" + "addu.ph %[temp3], %[temp2], %[a10] \n\t" + "addu.ph %[temp2], %[temp2], %[a32] \n\t" + "shll_s.ph %[temp0], %[temp0], 7 \n\t" + "shll_s.ph %[temp1], %[temp1], 7 \n\t" + "shll_s.ph %[temp3], %[temp3], 7 \n\t" + "shll_s.ph %[temp2], %[temp2], 7 \n\t" + "precrqu_s.qb.ph %[temp0], %[temp1], %[temp0] \n\t" + "precrqu_s.qb.ph %[temp1], %[temp2], %[temp3] \n\t" + "addu.ph %[temp2], %[temp5], %[a10] \n\t" + "addu.ph %[temp3], %[temp5], %[a32] \n\t" + "addu.ph %[temp5], %[temp4], %[a10] \n\t" + "addu.ph %[temp4], %[temp4], %[a32] \n\t" + "shll_s.ph %[temp2], %[temp2], 7 \n\t" + "shll_s.ph %[temp3], %[temp3], 7 \n\t" + "shll_s.ph %[temp4], %[temp4], 7 \n\t" + "shll_s.ph %[temp5], %[temp5], 7 \n\t" + "precrqu_s.qb.ph %[temp2], %[temp3], %[temp2] \n\t" + "precrqu_s.qb.ph %[temp3], %[temp4], %[temp5] \n\t" + "usw %[temp1], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp3], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp2], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [a10]"=&r"(a10), [a32]"=&r"(a32) + : [c35]"r"(c35), [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void VE4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + __asm__ volatile( + "ulw %[temp0], -1(%[top]) \n\t" + "ulh %[temp1], 3(%[top]) \n\t" + "preceu.ph.qbr %[temp2], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" + "packrl.ph %[temp6], %[temp4], %[temp3] \n\t" + "shll.ph %[temp5], %[temp5], 1 \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp2], %[temp5], %[temp2] \n\t" + "addq.ph %[temp6], %[temp6], %[temp4] \n\t" + "addq.ph %[temp2], %[temp2], %[temp3] \n\t" + "addq.ph %[temp6], %[temp6], %[temp3] \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" + "usw %[temp4], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp4], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp4], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void HE4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + __asm__ volatile( + "ulw %[temp0], -4(%[top]) \n\t" + "lbu %[temp1], -5(%[top]) \n\t" + "preceu.ph.qbr %[temp2], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp0] \n\t" + "replv.ph %[temp4], %[temp1] \n\t" + "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" + "packrl.ph %[temp6], %[temp2], %[temp4] \n\t" + "shll.ph %[temp5], %[temp5], 1 \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp3], %[temp3], %[temp5] \n\t" + "addq.ph %[temp3], %[temp3], %[temp2] \n\t" + "addq.ph %[temp2], %[temp2], %[temp6] \n\t" + "addq.ph %[temp2], %[temp2], %[temp4] \n\t" + "shra_r.ph %[temp3], %[temp3], 2 \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "replv.qb %[temp0], %[temp3] \n\t" + "replv.qb %[temp1], %[temp2] \n\t" + "srl %[temp3], %[temp3], 16 \n\t" + "srl %[temp2], %[temp2], 16 \n\t" + "replv.qb %[temp3], %[temp3] \n\t" + "replv.qb %[temp2], %[temp2] \n\t" + "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp2], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp1], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void RD4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5; + int temp6, temp7, temp8, temp9, temp10, temp11; + __asm__ volatile( + "ulw %[temp0], -5(%[top]) \n\t" + "ulw %[temp1], -1(%[top]) \n\t" + "preceu.ph.qbl %[temp2], %[temp0] \n\t" + "preceu.ph.qbr %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "preceu.ph.qbl %[temp5], %[temp1] \n\t" + "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" + "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" + "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp9], %[temp2], %[temp6] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "addq.ph %[temp9], %[temp9], %[temp3] \n\t" + "shll.ph %[temp8], %[temp8], 1 \n\t" + "shra_r.ph %[temp9], %[temp9], 2 \n\t" + "addq.ph %[temp10], %[temp4], %[temp7] \n\t" + "addq.ph %[temp11], %[temp5], %[temp8] \n\t" + "addq.ph %[temp10], %[temp10], %[temp2] \n\t" + "addq.ph %[temp11], %[temp11], %[temp4] \n\t" + "shra_r.ph %[temp10], %[temp10], 2 \n\t" + "shra_r.ph %[temp11], %[temp11], 2 \n\t" + "lbu %[temp0], 3(%[top]) \n\t" + "lbu %[temp1], 2(%[top]) \n\t" + "lbu %[temp2], 1(%[top]) \n\t" + "sll %[temp1], %[temp1], 1 \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp0], %[temp0], %[temp2] \n\t" + "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t" + "shra_r.w %[temp0], %[temp0], 2 \n\t" + "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t" + "usw %[temp9], 3*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp10], 1*" XSTR(BPS) "(%[dst]) \n\t" + "prepend %[temp9], %[temp11], 8 \n\t" + "prepend %[temp10], %[temp0], 8 \n\t" + "usw %[temp9], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp10], 0*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void VR4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + "ulw %[temp0], -4(%[top]) \n\t" + "ulw %[temp1], 0(%[top]) \n\t" + "preceu.ph.qbl %[temp2], %[temp0] \n\t" + "preceu.ph.qbr %[temp0], %[temp0] \n\t" + "preceu.ph.qbla %[temp3], %[temp1] \n\t" + "preceu.ph.qbra %[temp1], %[temp1] \n\t" + "packrl.ph %[temp7], %[temp3], %[temp2] \n\t" + "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t" + "move %[temp6], %[temp1] \n\t" + "append %[temp1], %[temp2], 16 \n\t" + "shll.ph %[temp9], %[temp6], 1 \n\t" + "addqh_r.ph %[temp5], %[temp7], %[temp6] \n\t" + "shll.ph %[temp8], %[temp7], 1 \n\t" + "addu.ph %[temp3], %[temp7], %[temp3] \n\t" + "addu.ph %[temp1], %[temp1], %[temp6] \n\t" + "packrl.ph %[temp7], %[temp2], %[temp0] \n\t" + "addu.ph %[temp6], %[temp0], %[temp2] \n\t" + "addu.ph %[temp3], %[temp3], %[temp9] \n\t" + "addu.ph %[temp1], %[temp1], %[temp8] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "shra_r.ph %[temp3], %[temp3], 2 \n\t" + "shra_r.ph %[temp1], %[temp1], 2 \n\t" + "addu.ph %[temp6], %[temp6], %[temp7] \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precrq.ph.w %[temp8], %[temp4], %[temp5] \n\t" + "append %[temp4], %[temp5], 16 \n\t" + "precrq.ph.w %[temp2], %[temp3], %[temp1] \n\t" + "append %[temp3], %[temp1], 16 \n\t" + "precr.qb.ph %[temp8], %[temp8], %[temp4] \n\t" + "precr.qb.ph %[temp3], %[temp2], %[temp3] \n\t" + "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t" + "append %[temp3], %[temp6], 8 \n\t" + "srl %[temp6], %[temp6], 16 \n\t" + "append %[temp8], %[temp6], 8 \n\t" + "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void LD4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5; + int temp6, temp7, temp8, temp9, temp10, temp11; + __asm__ volatile( + "ulw %[temp0], 0(%[top]) \n\t" + "ulw %[temp1], 4(%[top]) \n\t" + "preceu.ph.qbl %[temp2], %[temp0] \n\t" + "preceu.ph.qbr %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "preceu.ph.qbl %[temp5], %[temp1] \n\t" + "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" + "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" + "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp9], %[temp2], %[temp6] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "addq.ph %[temp9], %[temp9], %[temp3] \n\t" + "shll.ph %[temp8], %[temp8], 1 \n\t" + "shra_r.ph %[temp9], %[temp9], 2 \n\t" + "addq.ph %[temp10], %[temp4], %[temp7] \n\t" + "addq.ph %[temp11], %[temp5], %[temp8] \n\t" + "addq.ph %[temp10], %[temp10], %[temp2] \n\t" + "addq.ph %[temp11], %[temp11], %[temp4] \n\t" + "shra_r.ph %[temp10], %[temp10], 2 \n\t" + "shra_r.ph %[temp11], %[temp11], 2 \n\t" + "srl %[temp1], %[temp1], 24 \n\t" + "sll %[temp1], %[temp1], 1 \n\t" + "raddu.w.qb %[temp5], %[temp5] \n\t" + "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t" + "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t" + "addu %[temp1], %[temp1], %[temp5] \n\t" + "shra_r.w %[temp1], %[temp1], 2 \n\t" + "usw %[temp9], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp10], 2*" XSTR(BPS) "(%[dst]) \n\t" + "prepend %[temp9], %[temp11], 8 \n\t" + "prepend %[temp10], %[temp1], 8 \n\t" + "usw %[temp9], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp10], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void VL4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + "ulw %[temp0], 0(%[top]) \n\t" + "ulw %[temp1], 4(%[top]) \n\t" + "preceu.ph.qbla %[temp2], %[temp0] \n\t" + "preceu.ph.qbra %[temp0], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp1] \n\t" + "preceu.ph.qbr %[temp1], %[temp1] \n\t" + "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t" + "packrl.ph %[temp7], %[temp1], %[temp0] \n\t" + "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t" + "shll.ph %[temp9], %[temp2], 1 \n\t" + "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t" + "shll.ph %[temp8], %[temp7], 1 \n\t" + "addu.ph %[temp2], %[temp2], %[temp6] \n\t" + "addu.ph %[temp0], %[temp0], %[temp7] \n\t" + "packrl.ph %[temp7], %[temp3], %[temp1] \n\t" + "addu.ph %[temp6], %[temp1], %[temp3] \n\t" + "addu.ph %[temp2], %[temp2], %[temp8] \n\t" + "addu.ph %[temp0], %[temp0], %[temp9] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "shra_r.ph %[temp0], %[temp0], 2 \n\t" + "addu.ph %[temp6], %[temp6], %[temp7] \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precrq.ph.w %[temp8], %[temp5], %[temp4] \n\t" + "append %[temp5], %[temp4], 16 \n\t" + "precrq.ph.w %[temp3], %[temp2], %[temp0] \n\t" + "append %[temp2], %[temp0], 16 \n\t" + "precr.qb.ph %[temp8], %[temp8], %[temp5] \n\t" + "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" + "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t" + "prepend %[temp8], %[temp6], 8 \n\t" + "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t" + "srl %[temp6], %[temp6], 16 \n\t" + "prepend %[temp3], %[temp6], 8 \n\t" + "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void HD4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + "ulw %[temp0], -5(%[top]) \n\t" + "ulw %[temp1], -1(%[top]) \n\t" + "preceu.ph.qbla %[temp2], %[temp0] \n\t" + "preceu.ph.qbra %[temp0], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp1] \n\t" + "preceu.ph.qbr %[temp1], %[temp1] \n\t" + "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t" + "packrl.ph %[temp7], %[temp1], %[temp0] \n\t" + "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t" + "shll.ph %[temp9], %[temp2], 1 \n\t" + "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t" + "shll.ph %[temp8], %[temp7], 1 \n\t" + "addu.ph %[temp2], %[temp2], %[temp6] \n\t" + "addu.ph %[temp0], %[temp0], %[temp7] \n\t" + "packrl.ph %[temp7], %[temp3], %[temp1] \n\t" + "addu.ph %[temp6], %[temp1], %[temp3] \n\t" + "addu.ph %[temp2], %[temp2], %[temp8] \n\t" + "addu.ph %[temp0], %[temp0], %[temp9] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "shra_r.ph %[temp0], %[temp0], 2 \n\t" + "addu.ph %[temp6], %[temp6], %[temp7] \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precrq.ph.w %[temp1], %[temp2], %[temp5] \n\t" + "precrq.ph.w %[temp3], %[temp0], %[temp4] \n\t" + "precr.qb.ph %[temp7], %[temp6], %[temp1] \n\t" + "precr.qb.ph %[temp6], %[temp1], %[temp3] \n\t" + "usw %[temp7], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp6], 1*" XSTR(BPS) "(%[dst]) \n\t" + "append %[temp2], %[temp5], 16 \n\t" + "append %[temp0], %[temp4], 16 \n\t" + "precr.qb.ph %[temp5], %[temp3], %[temp2] \n\t" + "precr.qb.ph %[temp4], %[temp2], %[temp0] \n\t" + "usw %[temp5], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void HU4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + __asm__ volatile ( + "ulw %[temp0], -5(%[top]) \n\t" + "preceu.ph.qbl %[temp1], %[temp0] \n\t" + "preceu.ph.qbr %[temp2], %[temp0] \n\t" + "packrl.ph %[temp3], %[temp1], %[temp2] \n\t" + "replv.qb %[temp7], %[temp2] \n\t" + "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t" + "addqh_r.ph %[temp5], %[temp3], %[temp2] \n\t" + "shll.ph %[temp6], %[temp3], 1 \n\t" + "addu.ph %[temp3], %[temp2], %[temp3] \n\t" + "addu.ph %[temp6], %[temp1], %[temp6] \n\t" + "shll.ph %[temp0], %[temp2], 1 \n\t" + "addu.ph %[temp6], %[temp6], %[temp2] \n\t" + "addu.ph %[temp0], %[temp3], %[temp0] \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "shra_r.ph %[temp0], %[temp0], 2 \n\t" + "packrl.ph %[temp3], %[temp6], %[temp5] \n\t" + "precrq.ph.w %[temp2], %[temp6], %[temp4] \n\t" + "append %[temp0], %[temp5], 16 \n\t" + "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" + "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t" + "precr.qb.ph %[temp1], %[temp7], %[temp0] \n\t" + "usw %[temp7], 3*" XSTR(BPS) "(%[dst]) \n\t" + "packrl.ph %[temp2], %[temp1], %[temp3] \n\t" + "usw %[temp1], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp2], 1*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +//------------------------------------------------------------------------------ +// Chroma 8x8 prediction (paragraph 12.2) + +static void IntraChromaPreds_MIPSdspR2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + // U block + DCMode8(C8DC8 + dst, left, top); + VerticalPred8(C8VE8 + dst, top); + HorizontalPred8(C8HE8 + dst, left); + TrueMotion8(C8TM8 + dst, left, top); + // V block + dst += 8; + if (top) top += 8; + if (left) left += 16; + DCMode8(C8DC8 + dst, left, top); + VerticalPred8(C8VE8 + dst, top); + HorizontalPred8(C8HE8 + dst, left); + TrueMotion8(C8TM8 + dst, left, top); +} + +//------------------------------------------------------------------------------ +// luma 16x16 prediction (paragraph 12.3) + +static void Intra16Preds_MIPSdspR2(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DCMode16(I16DC16 + dst, left, top); + VerticalPred16(I16VE16 + dst, top); + HorizontalPred16(I16HE16 + dst, left); + TrueMotion16(I16TM16 + dst, left, top); +} + +// Left samples are top[-5 .. -2], top_left is top[-1], top are +// located at top[0..3], and top right is top[4..7] +static void Intra4Preds_MIPSdspR2(uint8_t* dst, const uint8_t* top) { + DC4(I4DC4 + dst, top); + TM4(I4TM4 + dst, top); + VE4(I4VE4 + dst, top); + HE4(I4HE4 + dst, top); + RD4(I4RD4 + dst, top); + VR4(I4VR4 + dst, top); + LD4(I4LD4 + dst, top); + VL4(I4VL4 + dst, top); + HD4(I4HD4 + dst, top); + HU4(I4HU4 + dst, top); +} + +//------------------------------------------------------------------------------ +// Metric + +#if !defined(WORK_AROUND_GCC) + +#define GET_SSE_INNER(A) \ + "lw %[temp0], " #A "(%[a]) \n\t" \ + "lw %[temp1], " #A "(%[b]) \n\t" \ + "preceu.ph.qbr %[temp2], %[temp0] \n\t" \ + "preceu.ph.qbl %[temp0], %[temp0] \n\t" \ + "preceu.ph.qbr %[temp3], %[temp1] \n\t" \ + "preceu.ph.qbl %[temp1], %[temp1] \n\t" \ + "subq.ph %[temp2], %[temp2], %[temp3] \n\t" \ + "subq.ph %[temp0], %[temp0], %[temp1] \n\t" \ + "dpa.w.ph $ac0, %[temp2], %[temp2] \n\t" \ + "dpa.w.ph $ac0, %[temp0], %[temp0] \n\t" + +#define GET_SSE(A, B, C, D) \ + GET_SSE_INNER(A) \ + GET_SSE_INNER(B) \ + GET_SSE_INNER(C) \ + GET_SSE_INNER(D) + +static int SSE16x16_MIPSdspR2(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3; + __asm__ volatile ( + "mult $zero, $zero \n\t" + GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) + GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) + GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) + GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) + GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) + GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) + GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) + GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) + GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) + GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) + GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) + GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) + GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) + GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) + GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) + GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE16x8_MIPSdspR2(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3; + __asm__ volatile ( + "mult $zero, $zero \n\t" + GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) + GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) + GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) + GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) + GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) + GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) + GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) + GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE8x8_MIPSdspR2(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3; + __asm__ volatile ( + "mult $zero, $zero \n\t" + GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) + GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) + GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) + GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE4x4_MIPSdspR2(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3; + __asm__ volatile ( + "mult $zero, $zero \n\t" + GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +#undef GET_SSE +#undef GET_SSE_INNER + +#endif // !WORK_AROUND_GCC + +#undef FILL_8_OR_16 +#undef FILL_PART +#undef OUTPUT_EARLY_CLOBBER_REGS_17 +#undef MUL_HALF +#undef ABS_X8 +#undef ADD_SUB_HALVES_X4 + +//------------------------------------------------------------------------------ +// Quantization +// + +// macro for one pass through for loop in QuantizeBlock reading 2 values at time +// QUANTDIV macro inlined +// J - offset in bytes (kZigzag[n] * 2) +// K - offset in bytes (kZigzag[n] * 4) +// N - offset in bytes (n * 2) +// N1 - offset in bytes ((n + 1) * 2) +#define QUANTIZE_ONE(J, K, N, N1) \ + "ulw %[temp1], " #J "(%[ppin]) \n\t" \ + "ulw %[temp2], " #J "(%[ppsharpen]) \n\t" \ + "lhu %[temp3], " #K "(%[ppzthresh]) \n\t" \ + "lhu %[temp6], " #K "+4(%[ppzthresh]) \n\t" \ + "absq_s.ph %[temp4], %[temp1] \n\t" \ + "ins %[temp3], %[temp6], 16, 16 \n\t" \ + "addu.ph %[coeff], %[temp4], %[temp2] \n\t" \ + "shra.ph %[sign], %[temp1], 15 \n\t" \ + "li %[level], 0x10001 \n\t" \ + "cmp.lt.ph %[temp3], %[coeff] \n\t" \ + "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ + "pick.ph %[temp5], %[level], $0 \n\t" \ + "lw %[temp2], " #K "(%[ppbias]) \n\t" \ + "beqz %[temp5], 0f \n\t" \ + "lhu %[temp3], " #J "(%[ppq]) \n\t" \ + "beq %[temp5], %[level], 1f \n\t" \ + "andi %[temp5], %[temp5], 0x1 \n\t" \ + "andi %[temp4], %[coeff], 0xffff \n\t" \ + "beqz %[temp5], 2f \n\t" \ + "mul %[level], %[temp4], %[temp1] \n\t" \ + "sh $0, " #J "+2(%[ppin]) \n\t" \ + "sh $0, " #N1 "(%[pout]) \n\t" \ + "addu %[level], %[level], %[temp2] \n\t" \ + "sra %[level], %[level], 17 \n\t" \ + "slt %[temp4], %[max_level], %[level] \n\t" \ + "movn %[level], %[max_level], %[temp4] \n\t" \ + "andi %[temp6], %[sign], 0xffff \n\t" \ + "xor %[level], %[level], %[temp6] \n\t" \ + "subu %[level], %[level], %[temp6] \n\t" \ + "mul %[temp5], %[level], %[temp3] \n\t" \ + "or %[ret], %[ret], %[level] \n\t" \ + "sh %[level], " #N "(%[pout]) \n\t" \ + "sh %[temp5], " #J "(%[ppin]) \n\t" \ + "j 3f \n\t" \ +"2: \n\t" \ + "lhu %[temp1], " #J "+2(%[ppiq]) \n\t" \ + "srl %[temp5], %[coeff], 16 \n\t" \ + "mul %[level], %[temp5], %[temp1] \n\t" \ + "lw %[temp2], " #K "+4(%[ppbias]) \n\t" \ + "lhu %[temp3], " #J "+2(%[ppq]) \n\t" \ + "addu %[level], %[level], %[temp2] \n\t" \ + "sra %[level], %[level], 17 \n\t" \ + "srl %[temp6], %[sign], 16 \n\t" \ + "slt %[temp4], %[max_level], %[level] \n\t" \ + "movn %[level], %[max_level], %[temp4] \n\t" \ + "xor %[level], %[level], %[temp6] \n\t" \ + "subu %[level], %[level], %[temp6] \n\t" \ + "mul %[temp5], %[level], %[temp3] \n\t" \ + "sh $0, " #J "(%[ppin]) \n\t" \ + "sh $0, " #N "(%[pout]) \n\t" \ + "or %[ret], %[ret], %[level] \n\t" \ + "sh %[temp5], " #J "+2(%[ppin]) \n\t" \ + "sh %[level], " #N1 "(%[pout]) \n\t" \ + "j 3f \n\t" \ +"1: \n\t" \ + "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ + "lw %[temp2], " #K "(%[ppbias]) \n\t" \ + "ulw %[temp3], " #J "(%[ppq]) \n\t" \ + "andi %[temp5], %[coeff], 0xffff \n\t" \ + "srl %[temp0], %[coeff], 16 \n\t" \ + "lhu %[temp6], " #J "+2(%[ppiq]) \n\t" \ + "lw %[coeff], " #K "+4(%[ppbias]) \n\t" \ + "mul %[level], %[temp5], %[temp1] \n\t" \ + "mul %[temp4], %[temp0], %[temp6] \n\t" \ + "addu %[level], %[level], %[temp2] \n\t" \ + "addu %[temp4], %[temp4], %[coeff] \n\t" \ + "precrq.ph.w %[level], %[temp4], %[level] \n\t" \ + "shra.ph %[level], %[level], 1 \n\t" \ + "cmp.lt.ph %[max_level1],%[level] \n\t" \ + "pick.ph %[level], %[max_level], %[level] \n\t" \ + "xor %[level], %[level], %[sign] \n\t" \ + "subu.ph %[level], %[level], %[sign] \n\t" \ + "mul.ph %[temp3], %[level], %[temp3] \n\t" \ + "or %[ret], %[ret], %[level] \n\t" \ + "sh %[level], " #N "(%[pout]) \n\t" \ + "srl %[level], %[level], 16 \n\t" \ + "sh %[level], " #N1 "(%[pout]) \n\t" \ + "usw %[temp3], " #J "(%[ppin]) \n\t" \ + "j 3f \n\t" \ +"0: \n\t" \ + "sh $0, " #N "(%[pout]) \n\t" \ + "sh $0, " #N1 "(%[pout]) \n\t" \ + "usw $0, " #J "(%[ppin]) \n\t" \ +"3: \n\t" + +static int QuantizeBlock_MIPSdspR2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int temp0, temp1, temp2, temp3, temp4, temp5,temp6; + int sign, coeff, level; + int max_level = MAX_LEVEL; + int max_level1 = max_level << 16 | max_level; + int ret = 0; + + int16_t* ppin = &in[0]; + int16_t* pout = &out[0]; + const uint16_t* ppsharpen = &mtx->sharpen_[0]; + const uint32_t* ppzthresh = &mtx->zthresh_[0]; + const uint16_t* ppq = &mtx->q_[0]; + const uint16_t* ppiq = &mtx->iq_[0]; + const uint32_t* ppbias = &mtx->bias_[0]; + + __asm__ volatile ( + QUANTIZE_ONE( 0, 0, 0, 2) + QUANTIZE_ONE( 4, 8, 10, 12) + QUANTIZE_ONE( 8, 16, 4, 8) + QUANTIZE_ONE(12, 24, 14, 24) + QUANTIZE_ONE(16, 32, 6, 16) + QUANTIZE_ONE(20, 40, 22, 26) + QUANTIZE_ONE(24, 48, 18, 20) + QUANTIZE_ONE(28, 56, 28, 30) + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [sign]"=&r"(sign), [coeff]"=&r"(coeff), + [level]"=&r"(level), [temp6]"=&r"(temp6), [ret]"+&r"(ret) + : [ppin]"r"(ppin), [pout]"r"(pout), [max_level1]"r"(max_level1), + [ppiq]"r"(ppiq), [max_level]"r"(max_level), + [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh), + [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq) + : "memory", "hi", "lo" + ); + + return (ret != 0); +} + +static int Quantize2Blocks_MIPSdspR2(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = QuantizeBlock_MIPSdspR2(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_MIPSdspR2(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} + +#undef QUANTIZE_ONE + +// macro for one horizontal pass in FTransformWHT +// temp0..temp7 holds tmp[0]..tmp[15] +// A, B, C, D - offset in bytes to load from in buffer +// TEMP0, TEMP1 - registers for corresponding tmp elements +#define HORIZONTAL_PASS_WHT(A, B, C, D, TEMP0, TEMP1) \ + "lh %[" #TEMP0 "], " #A "(%[in]) \n\t" \ + "lh %[" #TEMP1 "], " #B "(%[in]) \n\t" \ + "lh %[temp8], " #C "(%[in]) \n\t" \ + "lh %[temp9], " #D "(%[in]) \n\t" \ + "ins %[" #TEMP1 "], %[" #TEMP0 "], 16, 16 \n\t" \ + "ins %[temp9], %[temp8], 16, 16 \n\t" \ + "subq.ph %[temp8], %[" #TEMP1 "], %[temp9] \n\t" \ + "addq.ph %[temp9], %[" #TEMP1 "], %[temp9] \n\t" \ + "precrq.ph.w %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \ + "append %[temp8], %[temp9], 16 \n\t" \ + "subq.ph %[" #TEMP1 "], %[" #TEMP0 "], %[temp8] \n\t" \ + "addq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[temp8] \n\t" \ + "rotr %[" #TEMP1 "], %[" #TEMP1 "], 16 \n\t" + +// macro for one vertical pass in FTransformWHT +// temp0..temp7 holds tmp[0]..tmp[15] +// A, B, C, D - offsets in bytes to store to out buffer +// TEMP0, TEMP2, TEMP4 and TEMP6 - registers for corresponding tmp elements +#define VERTICAL_PASS_WHT(A, B, C, D, TEMP0, TEMP2, TEMP4, TEMP6) \ + "addq.ph %[temp8], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \ + "addq.ph %[temp9], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ + "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ + "subq.ph %[" #TEMP6 "], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \ + "addqh.ph %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \ + "subqh.ph %[" #TEMP4 "], %[" #TEMP6 "], %[" #TEMP2 "] \n\t" \ + "addqh.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ + "subqh.ph %[" #TEMP6 "], %[temp8], %[temp9] \n\t" \ + "usw %[" #TEMP0 "], " #A "(%[out]) \n\t" \ + "usw %[" #TEMP2 "], " #B "(%[out]) \n\t" \ + "usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \ + "usw %[" #TEMP6 "], " #D "(%[out]) \n\t" + +static void FTransformWHT_MIPSdspR2(const int16_t* in, int16_t* out) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + + __asm__ volatile ( + HORIZONTAL_PASS_WHT( 0, 32, 64, 96, temp0, temp1) + HORIZONTAL_PASS_WHT(128, 160, 192, 224, temp2, temp3) + HORIZONTAL_PASS_WHT(256, 288, 320, 352, temp4, temp5) + HORIZONTAL_PASS_WHT(384, 416, 448, 480, temp6, temp7) + VERTICAL_PASS_WHT(0, 8, 16, 24, temp0, temp2, temp4, temp6) + VERTICAL_PASS_WHT(4, 12, 20, 28, temp1, temp3, temp5, temp7) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [in]"r"(in), [out]"r"(out) + : "memory" + ); +} + +#undef VERTICAL_PASS_WHT +#undef HORIZONTAL_PASS_WHT + +// macro for converting coefficients to bin +// convert 8 coeffs at time +// A, B, C, D - offsets in bytes to load from out buffer +#define CONVERT_COEFFS_TO_BIN(A, B, C, D) \ + "ulw %[temp0], " #A "(%[out]) \n\t" \ + "ulw %[temp1], " #B "(%[out]) \n\t" \ + "ulw %[temp2], " #C "(%[out]) \n\t" \ + "ulw %[temp3], " #D "(%[out]) \n\t" \ + "absq_s.ph %[temp0], %[temp0] \n\t" \ + "absq_s.ph %[temp1], %[temp1] \n\t" \ + "absq_s.ph %[temp2], %[temp2] \n\t" \ + "absq_s.ph %[temp3], %[temp3] \n\t" \ + "shra.ph %[temp0], %[temp0], 3 \n\t" \ + "shra.ph %[temp1], %[temp1], 3 \n\t" \ + "shra.ph %[temp2], %[temp2], 3 \n\t" \ + "shra.ph %[temp3], %[temp3], 3 \n\t" \ + "shll_s.ph %[temp0], %[temp0], 10 \n\t" \ + "shll_s.ph %[temp1], %[temp1], 10 \n\t" \ + "shll_s.ph %[temp2], %[temp2], 10 \n\t" \ + "shll_s.ph %[temp3], %[temp3], 10 \n\t" \ + "shrl.ph %[temp0], %[temp0], 10 \n\t" \ + "shrl.ph %[temp1], %[temp1], 10 \n\t" \ + "shrl.ph %[temp2], %[temp2], 10 \n\t" \ + "shrl.ph %[temp3], %[temp3], 10 \n\t" \ + "shll.ph %[temp0], %[temp0], 2 \n\t" \ + "shll.ph %[temp1], %[temp1], 2 \n\t" \ + "shll.ph %[temp2], %[temp2], 2 \n\t" \ + "shll.ph %[temp3], %[temp3], 2 \n\t" \ + "ext %[temp4], %[temp0], 0, 16 \n\t" \ + "ext %[temp0], %[temp0], 16, 16 \n\t" \ + "addu %[temp4], %[temp4], %[dist] \n\t" \ + "addu %[temp0], %[temp0], %[dist] \n\t" \ + "ext %[temp5], %[temp1], 0, 16 \n\t" \ + "lw %[temp8], 0(%[temp4]) \n\t" \ + "ext %[temp1], %[temp1], 16, 16 \n\t" \ + "addu %[temp5], %[temp5], %[dist] \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp4]) \n\t" \ + "lw %[temp8], 0(%[temp0]) \n\t" \ + "addu %[temp1], %[temp1], %[dist] \n\t" \ + "ext %[temp6], %[temp2], 0, 16 \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp0]) \n\t" \ + "lw %[temp8], 0(%[temp5]) \n\t" \ + "ext %[temp2], %[temp2], 16, 16 \n\t" \ + "addu %[temp6], %[temp6], %[dist] \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp5]) \n\t" \ + "lw %[temp8], 0(%[temp1]) \n\t" \ + "addu %[temp2], %[temp2], %[dist] \n\t" \ + "ext %[temp7], %[temp3], 0, 16 \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp1]) \n\t" \ + "lw %[temp8], 0(%[temp6]) \n\t" \ + "ext %[temp3], %[temp3], 16, 16 \n\t" \ + "addu %[temp7], %[temp7], %[dist] \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp6]) \n\t" \ + "lw %[temp8], 0(%[temp2]) \n\t" \ + "addu %[temp3], %[temp3], %[dist] \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp2]) \n\t" \ + "lw %[temp8], 0(%[temp7]) \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp7]) \n\t" \ + "lw %[temp8], 0(%[temp3]) \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp3]) \n\t" + +static void CollectHistogram_MIPSdspR2(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + + // Convert coefficients to bin. + __asm__ volatile ( + CONVERT_COEFFS_TO_BIN( 0, 4, 8, 12) + CONVERT_COEFFS_TO_BIN(16, 20, 24, 28) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) + : [dist]"r"(distribution), [out]"r"(out), [max_coeff]"r"(max_coeff) + : "memory" + ); + } + VP8SetHistogramData(distribution, histo); +} + +#undef CONVERT_COEFFS_TO_BIN + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPSdspR2(void) { + VP8FTransform = FTransform_MIPSdspR2; + VP8FTransformWHT = FTransformWHT_MIPSdspR2; + VP8ITransform = ITransform_MIPSdspR2; + + VP8TDisto4x4 = Disto4x4_MIPSdspR2; + VP8TDisto16x16 = Disto16x16_MIPSdspR2; + + VP8EncPredLuma16 = Intra16Preds_MIPSdspR2; + VP8EncPredChroma8 = IntraChromaPreds_MIPSdspR2; + VP8EncPredLuma4 = Intra4Preds_MIPSdspR2; + +#if !defined(WORK_AROUND_GCC) + VP8SSE16x16 = SSE16x16_MIPSdspR2; + VP8SSE8x8 = SSE8x8_MIPSdspR2; + VP8SSE16x8 = SSE16x8_MIPSdspR2; + VP8SSE4x4 = SSE4x4_MIPSdspR2; +#endif + + VP8EncQuantizeBlock = QuantizeBlock_MIPSdspR2; + VP8EncQuantize2Blocks = Quantize2Blocks_MIPSdspR2; + + VP8CollectHistogram = CollectHistogram_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8EncDspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/enc_msa.c b/libraries/webp/src/dsp/enc_msa.c new file mode 100644 index 0000000000..6f85add4bb --- /dev/null +++ b/libraries/webp/src/dsp/enc_msa.c @@ -0,0 +1,896 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA version of encoder dsp functions. +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include +#include "src/dsp/msa_macro.h" +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Transforms + +#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) do { \ + v4i32 a1_m, b1_m, c1_m, d1_m; \ + const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \ + const v4i32 sinpi8sqrt2 = __msa_fill_w(35468); \ + v4i32 c_tmp1_m = in1 * sinpi8sqrt2; \ + v4i32 c_tmp2_m = in3 * cospi8sqrt2minus1; \ + v4i32 d_tmp1_m = in1 * cospi8sqrt2minus1; \ + v4i32 d_tmp2_m = in3 * sinpi8sqrt2; \ + \ + ADDSUB2(in0, in2, a1_m, b1_m); \ + SRAI_W2_SW(c_tmp1_m, c_tmp2_m, 16); \ + c_tmp2_m = c_tmp2_m + in3; \ + c1_m = c_tmp1_m - c_tmp2_m; \ + SRAI_W2_SW(d_tmp1_m, d_tmp2_m, 16); \ + d_tmp1_m = d_tmp1_m + in1; \ + d1_m = d_tmp1_m + d_tmp2_m; \ + BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \ +} while (0) + +static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + v8i16 input0, input1; + v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3; + v4i32 res0, res1, res2, res3; + v16i8 dest0, dest1, dest2, dest3; + const v16i8 zero = { 0 }; + + LD_SH2(in, 8, input0, input1); + UNPCK_SH_SW(input0, in0, in1); + UNPCK_SH_SW(input1, in2, in3); + IDCT_1D_W(in0, in1, in2, in3, hz0, hz1, hz2, hz3); + TRANSPOSE4x4_SW_SW(hz0, hz1, hz2, hz3, hz0, hz1, hz2, hz3); + IDCT_1D_W(hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3); + SRARI_W4_SW(vt0, vt1, vt2, vt3, 3); + TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3); + LD_SB4(ref, BPS, dest0, dest1, dest2, dest3); + ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, + res0, res1, res2, res3); + ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, + res0, res1, res2, res3); + ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3); + CLIP_SW4_0_255(res0, res1, res2, res3); + PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1); + res0 = (v4i32)__msa_pckev_b((v16i8)vt0, (v16i8)vt1); + ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS); +} + +static void ITransform_MSA(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { + ITransformOne(ref, in, dst); + if (do_two) { + ITransformOne(ref + 4, in + 16, dst + 4); + } +} + +static void FTransform_MSA(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + uint64_t out0, out1, out2, out3; + uint32_t in0, in1, in2, in3; + v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + v8i16 t0, t1, t2, t3; + v16u8 srcl0, srcl1, src0 = { 0 }, src1 = { 0 }; + const v8i16 mask0 = { 0, 4, 8, 12, 1, 5, 9, 13 }; + const v8i16 mask1 = { 3, 7, 11, 15, 2, 6, 10, 14 }; + const v8i16 mask2 = { 4, 0, 5, 1, 6, 2, 7, 3 }; + const v8i16 mask3 = { 0, 4, 1, 5, 2, 6, 3, 7 }; + const v8i16 cnst0 = { 2217, -5352, 2217, -5352, 2217, -5352, 2217, -5352 }; + const v8i16 cnst1 = { 5352, 2217, 5352, 2217, 5352, 2217, 5352, 2217 }; + + LW4(src, BPS, in0, in1, in2, in3); + INSERT_W4_UB(in0, in1, in2, in3, src0); + LW4(ref, BPS, in0, in1, in2, in3); + INSERT_W4_UB(in0, in1, in2, in3, src1); + ILVRL_B2_UB(src0, src1, srcl0, srcl1); + HSUB_UB2_SH(srcl0, srcl1, t0, t1); + VSHF_H2_SH(t0, t1, t0, t1, mask0, mask1, t2, t3); + ADDSUB2(t2, t3, t0, t1); + t0 = SRLI_H(t0, 3); + VSHF_H2_SH(t0, t0, t1, t1, mask2, mask3, t3, t2); + tmp0 = __msa_hadd_s_w(t3, t3); + tmp2 = __msa_hsub_s_w(t3, t3); + FILL_W2_SW(1812, 937, tmp1, tmp3); + DPADD_SH2_SW(t2, t2, cnst0, cnst1, tmp3, tmp1); + SRAI_W2_SW(tmp1, tmp3, 9); + PCKEV_H2_SH(tmp1, tmp0, tmp3, tmp2, t0, t1); + VSHF_H2_SH(t0, t1, t0, t1, mask0, mask1, t2, t3); + ADDSUB2(t2, t3, t0, t1); + VSHF_H2_SH(t0, t0, t1, t1, mask2, mask3, t3, t2); + tmp0 = __msa_hadd_s_w(t3, t3); + tmp2 = __msa_hsub_s_w(t3, t3); + ADDVI_W2_SW(tmp0, 7, tmp2, 7, tmp0, tmp2); + SRAI_W2_SW(tmp0, tmp2, 4); + FILL_W2_SW(12000, 51000, tmp1, tmp3); + DPADD_SH2_SW(t2, t2, cnst0, cnst1, tmp3, tmp1); + SRAI_W2_SW(tmp1, tmp3, 16); + UNPCK_R_SH_SW(t1, tmp4); + tmp5 = __msa_ceqi_w(tmp4, 0); + tmp4 = (v4i32)__msa_nor_v((v16u8)tmp5, (v16u8)tmp5); + tmp5 = __msa_fill_w(1); + tmp5 = (v4i32)__msa_and_v((v16u8)tmp5, (v16u8)tmp4); + tmp1 += tmp5; + PCKEV_H2_SH(tmp1, tmp0, tmp3, tmp2, t0, t1); + out0 = __msa_copy_s_d((v2i64)t0, 0); + out1 = __msa_copy_s_d((v2i64)t0, 1); + out2 = __msa_copy_s_d((v2i64)t1, 0); + out3 = __msa_copy_s_d((v2i64)t1, 1); + SD4(out0, out1, out2, out3, out, 8); +} + +static void FTransformWHT_MSA(const int16_t* in, int16_t* out) { + v8i16 in0 = { 0 }; + v8i16 in1 = { 0 }; + v8i16 tmp0, tmp1, tmp2, tmp3; + v8i16 out0, out1; + const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 }; + const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 }; + const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 }; + const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 }; + + in0 = __msa_insert_h(in0, 0, in[ 0]); + in0 = __msa_insert_h(in0, 1, in[ 64]); + in0 = __msa_insert_h(in0, 2, in[128]); + in0 = __msa_insert_h(in0, 3, in[192]); + in0 = __msa_insert_h(in0, 4, in[ 16]); + in0 = __msa_insert_h(in0, 5, in[ 80]); + in0 = __msa_insert_h(in0, 6, in[144]); + in0 = __msa_insert_h(in0, 7, in[208]); + in1 = __msa_insert_h(in1, 0, in[ 48]); + in1 = __msa_insert_h(in1, 1, in[112]); + in1 = __msa_insert_h(in1, 2, in[176]); + in1 = __msa_insert_h(in1, 3, in[240]); + in1 = __msa_insert_h(in1, 4, in[ 32]); + in1 = __msa_insert_h(in1, 5, in[ 96]); + in1 = __msa_insert_h(in1, 6, in[160]); + in1 = __msa_insert_h(in1, 7, in[224]); + ADDSUB2(in0, in1, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + ADDSUB2(tmp2, tmp3, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1); + ADDSUB2(in0, in1, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + ADDSUB2(tmp2, tmp3, out0, out1); + SRAI_H2_SH(out0, out1, 1); + ST_SH2(out0, out1, out, 8); +} + +static int TTransform_MSA(const uint8_t* in, const uint16_t* w) { + int sum; + uint32_t in0_m, in1_m, in2_m, in3_m; + v16i8 src0 = { 0 }; + v8i16 in0, in1, tmp0, tmp1, tmp2, tmp3; + v4i32 dst0, dst1; + const v16i8 zero = { 0 }; + const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 }; + const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 }; + const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 }; + const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 }; + + LW4(in, BPS, in0_m, in1_m, in2_m, in3_m); + INSERT_W4_SB(in0_m, in1_m, in2_m, in3_m, src0); + ILVRL_B2_SH(zero, src0, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1); + ADDSUB2(in0, in1, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + ADDSUB2(tmp2, tmp3, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1); + ADDSUB2(in0, in1, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + ADDSUB2(tmp2, tmp3, tmp0, tmp1); + tmp0 = __msa_add_a_h(tmp0, (v8i16)zero); + tmp1 = __msa_add_a_h(tmp1, (v8i16)zero); + LD_SH2(w, 8, tmp2, tmp3); + DOTP_SH2_SW(tmp0, tmp1, tmp2, tmp3, dst0, dst1); + dst0 = dst0 + dst1; + sum = HADD_SW_S32(dst0); + return sum; +} + +static int Disto4x4_MSA(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int sum1 = TTransform_MSA(a, w); + const int sum2 = TTransform_MSA(b, w); + return abs(sum2 - sum1) >> 5; +} + +static int Disto16x16_MSA(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_MSA(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ +// Histogram + +static void CollectHistogram_MSA(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + { + int k; + v8i16 coeff0, coeff1; + const v8i16 zero = { 0 }; + const v8i16 max_coeff_thr = __msa_ldi_h(MAX_COEFF_THRESH); + LD_SH2(&out[0], 8, coeff0, coeff1); + coeff0 = __msa_add_a_h(coeff0, zero); + coeff1 = __msa_add_a_h(coeff1, zero); + SRAI_H2_SH(coeff0, coeff1, 3); + coeff0 = __msa_min_s_h(coeff0, max_coeff_thr); + coeff1 = __msa_min_s_h(coeff1, max_coeff_thr); + ST_SH2(coeff0, coeff1, &out[0], 8); + for (k = 0; k < 16; ++k) { + ++distribution[out[k]]; + } + } + } + VP8SetHistogramData(distribution, histo); +} + +//------------------------------------------------------------------------------ +// Intra predictions + +// luma 4x4 prediction + +#define DST(x, y) dst[(x) + (y) * BPS] +#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical + const v16u8 A1 = { 0 }; + const uint64_t val_m = LD(top - 1); + const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m); + const v16u8 B = SLDI_UB(A, A, 1); + const v16u8 C = SLDI_UB(A, A, 2); + const v16u8 AC = __msa_ave_u_b(A, C); + const v16u8 B2 = __msa_ave_u_b(B, B); + const v16u8 R = __msa_aver_u_b(AC, B2); + const uint32_t out = __msa_copy_s_w((v4i32)R, 0); + SW4(out, out, out, out, dst, BPS); +} + +static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); +} + +static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) { + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; + dc >>= 3; + dc = dc | (dc << 8) | (dc << 16) | (dc << 24); + SW4(dc, dc, dc, dc, dst, BPS); +} + +static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { + const v16u8 A2 = { 0 }; + const uint64_t val_m = LD(top - 5); + const v16u8 A1 = (v16u8)__msa_insert_d((v2i64)A2, 0, val_m); + const v16u8 A = (v16u8)__msa_insert_b((v16i8)A1, 8, top[3]); + const v16u8 B = SLDI_UB(A, A, 1); + const v16u8 C = SLDI_UB(A, A, 2); + const v16u8 AC = __msa_ave_u_b(A, C); + const v16u8 B2 = __msa_ave_u_b(B, B); + const v16u8 R0 = __msa_aver_u_b(AC, B2); + const v16u8 R1 = SLDI_UB(R0, R0, 1); + const v16u8 R2 = SLDI_UB(R1, R1, 1); + const v16u8 R3 = SLDI_UB(R2, R2, 1); + const uint32_t val0 = __msa_copy_s_w((v4i32)R0, 0); + const uint32_t val1 = __msa_copy_s_w((v4i32)R1, 0); + const uint32_t val2 = __msa_copy_s_w((v4i32)R2, 0); + const uint32_t val3 = __msa_copy_s_w((v4i32)R3, 0); + SW4(val3, val2, val1, val0, dst, BPS); +} + +static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { + const v16u8 A1 = { 0 }; + const uint64_t val_m = LD(top); + const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m); + const v16u8 B = SLDI_UB(A, A, 1); + const v16u8 C1 = SLDI_UB(A, A, 2); + const v16u8 C = (v16u8)__msa_insert_b((v16i8)C1, 6, top[7]); + const v16u8 AC = __msa_ave_u_b(A, C); + const v16u8 B2 = __msa_ave_u_b(B, B); + const v16u8 R0 = __msa_aver_u_b(AC, B2); + const v16u8 R1 = SLDI_UB(R0, R0, 1); + const v16u8 R2 = SLDI_UB(R1, R1, 1); + const v16u8 R3 = SLDI_UB(R2, R2, 1); + const uint32_t val0 = __msa_copy_s_w((v4i32)R0, 0); + const uint32_t val1 = __msa_copy_s_w((v4i32)R1, 0); + const uint32_t val2 = __msa_copy_s_w((v4i32)R2, 0); + const uint32_t val3 = __msa_copy_s_w((v4i32)R3, 0); + SW4(val0, val1, val2, val3, dst, BPS); +} + +static WEBP_INLINE void VR4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + DST(0, 0) = DST(1, 2) = AVG2(X, A); + DST(1, 0) = DST(2, 2) = AVG2(A, B); + DST(2, 0) = DST(3, 2) = AVG2(B, C); + DST(3, 0) = AVG2(C, D); + DST(0, 3) = AVG3(K, J, I); + DST(0, 2) = AVG3(J, I, X); + DST(0, 1) = DST(1, 3) = AVG3(I, X, A); + DST(1, 1) = DST(2, 3) = AVG3(X, A, B); + DST(2, 1) = DST(3, 3) = AVG3(A, B, C); + DST(3, 1) = AVG3(B, C, D); +} + +static WEBP_INLINE void VL4(uint8_t* dst, const uint8_t* top) { + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + const int E = top[4]; + const int F = top[5]; + const int G = top[6]; + const int H = top[7]; + DST(0, 0) = AVG2(A, B); + DST(1, 0) = DST(0, 2) = AVG2(B, C); + DST(2, 0) = DST(1, 2) = AVG2(C, D); + DST(3, 0) = DST(2, 2) = AVG2(D, E); + DST(0, 1) = AVG3(A, B, C); + DST(1, 1) = DST(0, 3) = AVG3(B, C, D); + DST(2, 1) = DST(1, 3) = AVG3(C, D, E); + DST(3, 1) = DST(2, 3) = AVG3(D, E, F); + DST(3, 2) = AVG3(E, F, G); + DST(3, 3) = AVG3(F, G, H); +} + +static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) { + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + DST(0, 0) = AVG2(I, J); + DST(2, 0) = DST(0, 1) = AVG2(J, K); + DST(2, 1) = DST(0, 2) = AVG2(K, L); + DST(1, 0) = AVG3(I, J, K); + DST(3, 0) = DST(1, 1) = AVG3(J, K, L); + DST(3, 1) = DST(1, 2) = AVG3(K, L, L); + DST(3, 2) = DST(2, 2) = + DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; +} + +static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + DST(0, 0) = DST(2, 1) = AVG2(I, X); + DST(0, 1) = DST(2, 2) = AVG2(J, I); + DST(0, 2) = DST(2, 3) = AVG2(K, J); + DST(0, 3) = AVG2(L, K); + DST(3, 0) = AVG3(A, B, C); + DST(2, 0) = AVG3(X, A, B); + DST(1, 0) = DST(3, 1) = AVG3(I, X, A); + DST(1, 1) = DST(3, 2) = AVG3(J, I, X); + DST(1, 2) = DST(3, 3) = AVG3(K, J, I); + DST(1, 3) = AVG3(L, K, J); +} + +static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) { + const v16i8 zero = { 0 }; + const v8i16 TL = (v8i16)__msa_fill_h(top[-1]); + const v8i16 L0 = (v8i16)__msa_fill_h(top[-2]); + const v8i16 L1 = (v8i16)__msa_fill_h(top[-3]); + const v8i16 L2 = (v8i16)__msa_fill_h(top[-4]); + const v8i16 L3 = (v8i16)__msa_fill_h(top[-5]); + const v16u8 T1 = LD_UB(top); + const v8i16 T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1); + const v8i16 d = T - TL; + v8i16 r0, r1, r2, r3; + ADD4(d, L0, d, L1, d, L2, d, L3, r0, r1, r2, r3); + CLIP_SH4_0_255(r0, r1, r2, r3); + PCKEV_ST4x4_UB(r0, r1, r2, r3, dst, BPS); +} + +#undef DST +#undef AVG3 +#undef AVG2 + +static void Intra4Preds_MSA(uint8_t* dst, const uint8_t* top) { + DC4(I4DC4 + dst, top); + TM4(I4TM4 + dst, top); + VE4(I4VE4 + dst, top); + HE4(I4HE4 + dst, top); + RD4(I4RD4 + dst, top); + VR4(I4VR4 + dst, top); + LD4(I4LD4 + dst, top); + VL4(I4VL4 + dst, top); + HD4(I4HD4 + dst, top); + HU4(I4HU4 + dst, top); +} + +// luma 16x16 prediction + +#define STORE16x16(out, dst) do { \ + ST_UB8(out, out, out, out, out, out, out, out, dst + 0 * BPS, BPS); \ + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); \ +} while (0) + +static WEBP_INLINE void VerticalPred16x16(uint8_t* dst, const uint8_t* top) { + if (top != NULL) { + const v16u8 out = LD_UB(top); + STORE16x16(out, dst); + } else { + const v16u8 out = (v16u8)__msa_fill_b(0x7f); + STORE16x16(out, dst); + } +} + +static WEBP_INLINE void HorizontalPred16x16(uint8_t* dst, + const uint8_t* left) { + if (left != NULL) { + int j; + for (j = 0; j < 16; j += 4) { + const v16u8 L0 = (v16u8)__msa_fill_b(left[0]); + const v16u8 L1 = (v16u8)__msa_fill_b(left[1]); + const v16u8 L2 = (v16u8)__msa_fill_b(left[2]); + const v16u8 L3 = (v16u8)__msa_fill_b(left[3]); + ST_UB4(L0, L1, L2, L3, dst, BPS); + dst += 4 * BPS; + left += 4; + } + } else { + const v16u8 out = (v16u8)__msa_fill_b(0x81); + STORE16x16(out, dst); + } +} + +static WEBP_INLINE void TrueMotion16x16(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + if (left != NULL) { + if (top != NULL) { + int j; + v8i16 d1, d2; + const v16i8 zero = { 0 }; + const v8i16 TL = (v8i16)__msa_fill_h(left[-1]); + const v16u8 T = LD_UB(top); + ILVRL_B2_SH(zero, T, d1, d2); + SUB2(d1, TL, d2, TL, d1, d2); + for (j = 0; j < 16; j += 4) { + v16i8 t0, t1, t2, t3; + v8i16 r0, r1, r2, r3, r4, r5, r6, r7; + const v8i16 L0 = (v8i16)__msa_fill_h(left[j + 0]); + const v8i16 L1 = (v8i16)__msa_fill_h(left[j + 1]); + const v8i16 L2 = (v8i16)__msa_fill_h(left[j + 2]); + const v8i16 L3 = (v8i16)__msa_fill_h(left[j + 3]); + ADD4(d1, L0, d1, L1, d1, L2, d1, L3, r0, r1, r2, r3); + ADD4(d2, L0, d2, L1, d2, L2, d2, L3, r4, r5, r6, r7); + CLIP_SH4_0_255(r0, r1, r2, r3); + CLIP_SH4_0_255(r4, r5, r6, r7); + PCKEV_B4_SB(r4, r0, r5, r1, r6, r2, r7, r3, t0, t1, t2, t3); + ST_SB4(t0, t1, t2, t3, dst, BPS); + dst += 4 * BPS; + } + } else { + HorizontalPred16x16(dst, left); + } + } else { + if (top != NULL) { + VerticalPred16x16(dst, top); + } else { + const v16u8 out = (v16u8)__msa_fill_b(0x81); + STORE16x16(out, dst); + } + } +} + +static WEBP_INLINE void DCMode16x16(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + int DC; + v16u8 out; + if (top != NULL && left != NULL) { + const v16u8 rtop = LD_UB(top); + const v8u16 dctop = __msa_hadd_u_h(rtop, rtop); + const v16u8 rleft = LD_UB(left); + const v8u16 dcleft = __msa_hadd_u_h(rleft, rleft); + const v8u16 dctemp = dctop + dcleft; + DC = HADD_UH_U32(dctemp); + DC = (DC + 16) >> 5; + } else if (left != NULL) { // left but no top + const v16u8 rleft = LD_UB(left); + const v8u16 dcleft = __msa_hadd_u_h(rleft, rleft); + DC = HADD_UH_U32(dcleft); + DC = (DC + DC + 16) >> 5; + } else if (top != NULL) { // top but no left + const v16u8 rtop = LD_UB(top); + const v8u16 dctop = __msa_hadd_u_h(rtop, rtop); + DC = HADD_UH_U32(dctop); + DC = (DC + DC + 16) >> 5; + } else { // no top, no left, nothing. + DC = 0x80; + } + out = (v16u8)__msa_fill_b(DC); + STORE16x16(out, dst); +} + +static void Intra16Preds_MSA(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DCMode16x16(I16DC16 + dst, left, top); + VerticalPred16x16(I16VE16 + dst, top); + HorizontalPred16x16(I16HE16 + dst, left); + TrueMotion16x16(I16TM16 + dst, left, top); +} + +// Chroma 8x8 prediction + +#define CALC_DC8(in, out) do { \ + const v8u16 temp0 = __msa_hadd_u_h(in, in); \ + const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); \ + const v2i64 temp2 = (v2i64)__msa_hadd_u_d(temp1, temp1); \ + const v2i64 temp3 = __msa_splati_d(temp2, 1); \ + const v2i64 temp4 = temp3 + temp2; \ + const v16i8 temp5 = (v16i8)__msa_srari_d(temp4, 4); \ + const v2i64 temp6 = (v2i64)__msa_splati_b(temp5, 0); \ + out = __msa_copy_s_d(temp6, 0); \ +} while (0) + +#define STORE8x8(out, dst) do { \ + SD4(out, out, out, out, dst + 0 * BPS, BPS); \ + SD4(out, out, out, out, dst + 4 * BPS, BPS); \ +} while (0) + +static WEBP_INLINE void VerticalPred8x8(uint8_t* dst, const uint8_t* top) { + if (top != NULL) { + const uint64_t out = LD(top); + STORE8x8(out, dst); + } else { + const uint64_t out = 0x7f7f7f7f7f7f7f7fULL; + STORE8x8(out, dst); + } +} + +static WEBP_INLINE void HorizontalPred8x8(uint8_t* dst, const uint8_t* left) { + if (left != NULL) { + int j; + for (j = 0; j < 8; j += 4) { + const v16u8 L0 = (v16u8)__msa_fill_b(left[0]); + const v16u8 L1 = (v16u8)__msa_fill_b(left[1]); + const v16u8 L2 = (v16u8)__msa_fill_b(left[2]); + const v16u8 L3 = (v16u8)__msa_fill_b(left[3]); + const uint64_t out0 = __msa_copy_s_d((v2i64)L0, 0); + const uint64_t out1 = __msa_copy_s_d((v2i64)L1, 0); + const uint64_t out2 = __msa_copy_s_d((v2i64)L2, 0); + const uint64_t out3 = __msa_copy_s_d((v2i64)L3, 0); + SD4(out0, out1, out2, out3, dst, BPS); + dst += 4 * BPS; + left += 4; + } + } else { + const uint64_t out = 0x8181818181818181ULL; + STORE8x8(out, dst); + } +} + +static WEBP_INLINE void TrueMotion8x8(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + if (left != NULL) { + if (top != NULL) { + int j; + const v8i16 TL = (v8i16)__msa_fill_h(left[-1]); + const v16u8 T1 = LD_UB(top); + const v16i8 zero = { 0 }; + const v8i16 T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1); + const v8i16 d = T - TL; + for (j = 0; j < 8; j += 4) { + uint64_t out0, out1, out2, out3; + v16i8 t0, t1; + v8i16 r0 = (v8i16)__msa_fill_h(left[j + 0]); + v8i16 r1 = (v8i16)__msa_fill_h(left[j + 1]); + v8i16 r2 = (v8i16)__msa_fill_h(left[j + 2]); + v8i16 r3 = (v8i16)__msa_fill_h(left[j + 3]); + ADD4(d, r0, d, r1, d, r2, d, r3, r0, r1, r2, r3); + CLIP_SH4_0_255(r0, r1, r2, r3); + PCKEV_B2_SB(r1, r0, r3, r2, t0, t1); + out0 = __msa_copy_s_d((v2i64)t0, 0); + out1 = __msa_copy_s_d((v2i64)t0, 1); + out2 = __msa_copy_s_d((v2i64)t1, 0); + out3 = __msa_copy_s_d((v2i64)t1, 1); + SD4(out0, out1, out2, out3, dst, BPS); + dst += 4 * BPS; + } + } else { + HorizontalPred8x8(dst, left); + } + } else { + if (top != NULL) { + VerticalPred8x8(dst, top); + } else { + const uint64_t out = 0x8181818181818181ULL; + STORE8x8(out, dst); + } + } +} + +static WEBP_INLINE void DCMode8x8(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + uint64_t out; + v16u8 src = { 0 }; + if (top != NULL && left != NULL) { + const uint64_t left_m = LD(left); + const uint64_t top_m = LD(top); + INSERT_D2_UB(left_m, top_m, src); + CALC_DC8(src, out); + } else if (left != NULL) { // left but no top + const uint64_t left_m = LD(left); + INSERT_D2_UB(left_m, left_m, src); + CALC_DC8(src, out); + } else if (top != NULL) { // top but no left + const uint64_t top_m = LD(top); + INSERT_D2_UB(top_m, top_m, src); + CALC_DC8(src, out); + } else { // no top, no left, nothing. + src = (v16u8)__msa_fill_b(0x80); + out = __msa_copy_s_d((v2i64)src, 0); + } + STORE8x8(out, dst); +} + +static void IntraChromaPreds_MSA(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + // U block + DCMode8x8(C8DC8 + dst, left, top); + VerticalPred8x8(C8VE8 + dst, top); + HorizontalPred8x8(C8HE8 + dst, left); + TrueMotion8x8(C8TM8 + dst, left, top); + // V block + dst += 8; + if (top != NULL) top += 8; + if (left != NULL) left += 16; + DCMode8x8(C8DC8 + dst, left, top); + VerticalPred8x8(C8VE8 + dst, top); + HorizontalPred8x8(C8HE8 + dst, left); + TrueMotion8x8(C8TM8 + dst, left, top); +} + +//------------------------------------------------------------------------------ +// Metric + +#define PACK_DOTP_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) do { \ + v16u8 tmp0, tmp1; \ + v8i16 tmp2, tmp3; \ + ILVRL_B2_UB(in0, in1, tmp0, tmp1); \ + HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \ + DOTP_SH2_SW(tmp2, tmp3, tmp2, tmp3, out0, out1); \ + ILVRL_B2_UB(in2, in3, tmp0, tmp1); \ + HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \ + DOTP_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \ +} while (0) + +#define PACK_DPADD_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) do { \ + v16u8 tmp0, tmp1; \ + v8i16 tmp2, tmp3; \ + ILVRL_B2_UB(in0, in1, tmp0, tmp1); \ + HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \ + DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out0, out1); \ + ILVRL_B2_UB(in2, in3, tmp0, tmp1); \ + HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \ + DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \ +} while (0) + +static int SSE16x16_MSA(const uint8_t* a, const uint8_t* b) { + uint32_t sum; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; + v4i32 out0, out1, out2, out3; + + LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7); + LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7); + PACK_DOTP_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3); + a += 8 * BPS; + b += 8 * BPS; + LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7); + LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7); + PACK_DPADD_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3); + out0 += out1; + out2 += out3; + out0 += out2; + sum = HADD_SW_S32(out0); + return sum; +} + +static int SSE16x8_MSA(const uint8_t* a, const uint8_t* b) { + uint32_t sum; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; + v4i32 out0, out1, out2, out3; + + LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7); + LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7); + PACK_DOTP_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3); + out0 += out1; + out2 += out3; + out0 += out2; + sum = HADD_SW_S32(out0); + return sum; +} + +static int SSE8x8_MSA(const uint8_t* a, const uint8_t* b) { + uint32_t sum; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; + v16u8 t0, t1, t2, t3; + v4i32 out0, out1, out2, out3; + + LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7); + LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7); + ILVR_B4_UB(src0, src1, src2, src3, ref0, ref1, ref2, ref3, t0, t1, t2, t3); + PACK_DOTP_UB4_SW(t0, t2, t1, t3, out0, out1, out2, out3); + ILVR_B4_UB(src4, src5, src6, src7, ref4, ref5, ref6, ref7, t0, t1, t2, t3); + PACK_DPADD_UB4_SW(t0, t2, t1, t3, out0, out1, out2, out3); + out0 += out1; + out2 += out3; + out0 += out2; + sum = HADD_SW_S32(out0); + return sum; +} + +static int SSE4x4_MSA(const uint8_t* a, const uint8_t* b) { + uint32_t sum = 0; + uint32_t src0, src1, src2, src3, ref0, ref1, ref2, ref3; + v16u8 src = { 0 }, ref = { 0 }, tmp0, tmp1; + v8i16 diff0, diff1; + v4i32 out0, out1; + + LW4(a, BPS, src0, src1, src2, src3); + LW4(b, BPS, ref0, ref1, ref2, ref3); + INSERT_W4_UB(src0, src1, src2, src3, src); + INSERT_W4_UB(ref0, ref1, ref2, ref3, ref); + ILVRL_B2_UB(src, ref, tmp0, tmp1); + HSUB_UB2_SH(tmp0, tmp1, diff0, diff1); + DOTP_SH2_SW(diff0, diff1, diff0, diff1, out0, out1); + out0 += out1; + sum = HADD_SW_S32(out0); + return sum; +} + +//------------------------------------------------------------------------------ +// Quantization + +static int QuantizeBlock_MSA(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int sum; + v8i16 in0, in1, sh0, sh1, out0, out1; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, sign0, sign1; + v4i32 s0, s1, s2, s3, b0, b1, b2, b3, t0, t1, t2, t3; + const v8i16 zero = { 0 }; + const v8i16 zigzag0 = { 0, 1, 4, 8, 5, 2, 3, 6 }; + const v8i16 zigzag1 = { 9, 12, 13, 10, 7, 11, 14, 15 }; + const v8i16 maxlevel = __msa_fill_h(MAX_LEVEL); + + LD_SH2(&in[0], 8, in0, in1); + LD_SH2(&mtx->sharpen_[0], 8, sh0, sh1); + tmp4 = __msa_add_a_h(in0, zero); + tmp5 = __msa_add_a_h(in1, zero); + ILVRL_H2_SH(sh0, tmp4, tmp0, tmp1); + ILVRL_H2_SH(sh1, tmp5, tmp2, tmp3); + HADD_SH4_SW(tmp0, tmp1, tmp2, tmp3, s0, s1, s2, s3); + sign0 = (in0 < zero); + sign1 = (in1 < zero); // sign + LD_SH2(&mtx->iq_[0], 8, tmp0, tmp1); // iq + ILVRL_H2_SW(zero, tmp0, t0, t1); + ILVRL_H2_SW(zero, tmp1, t2, t3); + LD_SW4(&mtx->bias_[0], 4, b0, b1, b2, b3); // bias + MUL4(t0, s0, t1, s1, t2, s2, t3, s3, t0, t1, t2, t3); + ADD4(b0, t0, b1, t1, b2, t2, b3, t3, b0, b1, b2, b3); + SRAI_W4_SW(b0, b1, b2, b3, 17); + PCKEV_H2_SH(b1, b0, b3, b2, tmp2, tmp3); + tmp0 = (tmp2 > maxlevel); + tmp1 = (tmp3 > maxlevel); + tmp2 = (v8i16)__msa_bmnz_v((v16u8)tmp2, (v16u8)maxlevel, (v16u8)tmp0); + tmp3 = (v8i16)__msa_bmnz_v((v16u8)tmp3, (v16u8)maxlevel, (v16u8)tmp1); + SUB2(zero, tmp2, zero, tmp3, tmp0, tmp1); + tmp2 = (v8i16)__msa_bmnz_v((v16u8)tmp2, (v16u8)tmp0, (v16u8)sign0); + tmp3 = (v8i16)__msa_bmnz_v((v16u8)tmp3, (v16u8)tmp1, (v16u8)sign1); + LD_SW4(&mtx->zthresh_[0], 4, t0, t1, t2, t3); // zthresh + t0 = (s0 > t0); + t1 = (s1 > t1); + t2 = (s2 > t2); + t3 = (s3 > t3); + PCKEV_H2_SH(t1, t0, t3, t2, tmp0, tmp1); + tmp4 = (v8i16)__msa_bmnz_v((v16u8)zero, (v16u8)tmp2, (v16u8)tmp0); + tmp5 = (v8i16)__msa_bmnz_v((v16u8)zero, (v16u8)tmp3, (v16u8)tmp1); + LD_SH2(&mtx->q_[0], 8, tmp0, tmp1); + MUL2(tmp4, tmp0, tmp5, tmp1, in0, in1); + VSHF_H2_SH(tmp4, tmp5, tmp4, tmp5, zigzag0, zigzag1, out0, out1); + ST_SH2(in0, in1, &in[0], 8); + ST_SH2(out0, out1, &out[0], 8); + out0 = __msa_add_a_h(out0, out1); + sum = HADD_SH_S32(out0); + return (sum > 0); +} + +static int Quantize2Blocks_MSA(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMSA(void) { + VP8ITransform = ITransform_MSA; + VP8FTransform = FTransform_MSA; + VP8FTransformWHT = FTransformWHT_MSA; + + VP8TDisto4x4 = Disto4x4_MSA; + VP8TDisto16x16 = Disto16x16_MSA; + VP8CollectHistogram = CollectHistogram_MSA; + + VP8EncPredLuma4 = Intra4Preds_MSA; + VP8EncPredLuma16 = Intra16Preds_MSA; + VP8EncPredChroma8 = IntraChromaPreds_MSA; + + VP8SSE16x16 = SSE16x16_MSA; + VP8SSE16x8 = SSE16x8_MSA; + VP8SSE8x8 = SSE8x8_MSA; + VP8SSE4x4 = SSE4x4_MSA; + + VP8EncQuantizeBlock = QuantizeBlock_MSA; + VP8EncQuantize2Blocks = Quantize2Blocks_MSA; + VP8EncQuantizeBlockWHT = QuantizeBlock_MSA; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8EncDspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/libraries/webp/src/dsp/enc_neon.c b/libraries/webp/src/dsp/enc_neon.c new file mode 100644 index 0000000000..6f641c9a76 --- /dev/null +++ b/libraries/webp/src/dsp/enc_neon.c @@ -0,0 +1,944 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// ARM NEON version of speed-critical encoding functions. +// +// adapted from libvpx (https://www.webmproject.org/code/) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include + +#include "src/dsp/neon.h" +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +// Inverse transform. +// This code is pretty much the same as TransformOne in the dec_neon.c, except +// for subtraction to *ref. See the comments there for algorithmic explanations. + +static const int16_t kC1 = WEBP_TRANSFORM_AC3_C1; +static const int16_t kC2 = + WEBP_TRANSFORM_AC3_C2 / 2; // half of kC2, actually. See comment above. + +// This code works but is *slower* than the inlined-asm version below +// (with gcc-4.6). So we disable it for now. Later, it'll be conditional to +// WEBP_USE_INTRINSICS define. +// With gcc-4.8, it's a little faster speed than inlined-assembly. +#if defined(WEBP_USE_INTRINSICS) + +// Treats 'v' as an uint8x8_t and zero extends to an int16x8_t. +static WEBP_INLINE int16x8_t ConvertU8ToS16_NEON(uint32x2_t v) { + return vreinterpretq_s16_u16(vmovl_u8(vreinterpret_u8_u32(v))); +} + +// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result +// to the corresponding rows of 'dst'. +static WEBP_INLINE void SaturateAndStore4x4_NEON(uint8_t* const dst, + const int16x8_t dst01, + const int16x8_t dst23) { + // Unsigned saturate to 8b. + const uint8x8_t dst01_u8 = vqmovun_s16(dst01); + const uint8x8_t dst23_u8 = vqmovun_s16(dst23); + + // Store the results. + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); +} + +static WEBP_INLINE void Add4x4_NEON(const int16x8_t row01, + const int16x8_t row23, + const uint8_t* const ref, + uint8_t* const dst) { + uint32x2_t dst01 = vdup_n_u32(0); + uint32x2_t dst23 = vdup_n_u32(0); + + // Load the source pixels. + dst01 = vld1_lane_u32((uint32_t*)(ref + 0 * BPS), dst01, 0); + dst23 = vld1_lane_u32((uint32_t*)(ref + 2 * BPS), dst23, 0); + dst01 = vld1_lane_u32((uint32_t*)(ref + 1 * BPS), dst01, 1); + dst23 = vld1_lane_u32((uint32_t*)(ref + 3 * BPS), dst23, 1); + + { + // Convert to 16b. + const int16x8_t dst01_s16 = ConvertU8ToS16_NEON(dst01); + const int16x8_t dst23_s16 = ConvertU8ToS16_NEON(dst23); + + // Descale with rounding. + const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); + const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); + // Add the inverse transform. + SaturateAndStore4x4_NEON(dst, out01, out23); + } +} + +static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0, + const int16x8_t in1, + int16x8x2_t* const out) { + // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 + // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 + const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... + // b0 d0 b1 d1 b2 d2 ... + *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); +} + +static WEBP_INLINE void TransformPass_NEON(int16x8x2_t* const rows) { + // {rows} = in0 | in4 + // in8 | in12 + // B1 = in4 | in12 + const int16x8_t B1 = + vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1])); + // C0 = kC1 * in4 | kC1 * in12 + // C1 = kC2 * in4 | kC2 * in12 + const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1); + const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2); + const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]), + vget_low_s16(rows->val[1])); // in0 + in8 + const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]), + vget_low_s16(rows->val[1])); // in0 - in8 + // c = kC2 * in4 - kC1 * in12 + // d = kC1 * in4 + kC2 * in12 + const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0)); + const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1)); + const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b + const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c + const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c + const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c + const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); + Transpose8x2_NEON(E0, E1, rows); +} + +static void ITransformOne_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst) { + int16x8x2_t rows; + INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); + TransformPass_NEON(&rows); + TransformPass_NEON(&rows); + Add4x4_NEON(rows.val[0], rows.val[1], ref, dst); +} + +#else + +static void ITransformOne_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst) { + const int kBPS = BPS; + const int16_t kC1C2[] = { kC1, kC2, 0, 0 }; + + __asm__ volatile ( + "vld1.16 {q1, q2}, [%[in]] \n" + "vld1.16 {d0}, [%[kC1C2]] \n" + + // d2: in[0] + // d3: in[8] + // d4: in[4] + // d5: in[12] + "vswp d3, d4 \n" + + // q8 = {in[4], in[12]} * kC1 * 2 >> 16 + // q9 = {in[4], in[12]} * kC2 >> 16 + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + // d22 = a = in[0] + in[8] + // d23 = b = in[0] - in[8] + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + // q8 = in[4]/[12] * kC1 >> 16 + "vshr.s16 q8, q8, #1 \n" + + // Add {in[4], in[12]} back after the multiplication. + "vqadd.s16 q8, q2, q8 \n" + + // d20 = c = in[4]*kC2 - in[12]*kC1 + // d21 = d = in[4]*kC1 + in[12]*kC2 + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + // d2 = tmp[0] = a + d + // d3 = tmp[1] = b + c + // d4 = tmp[2] = b - c + // d5 = tmp[3] = a - d + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + "vswp d3, d4 \n" + + // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 + // q9 = {tmp[4], tmp[12]} * kC2 >> 16 + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + // d22 = a = tmp[0] + tmp[8] + // d23 = b = tmp[0] - tmp[8] + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + "vshr.s16 q8, q8, #1 \n" + "vqadd.s16 q8, q2, q8 \n" + + // d20 = c = in[4]*kC2 - in[12]*kC1 + // d21 = d = in[4]*kC1 + in[12]*kC2 + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + // d2 = tmp[0] = a + d + // d3 = tmp[1] = b + c + // d4 = tmp[2] = b - c + // d5 = tmp[3] = a - d + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vld1.32 d6[0], [%[ref]], %[kBPS] \n" + "vld1.32 d6[1], [%[ref]], %[kBPS] \n" + "vld1.32 d7[0], [%[ref]], %[kBPS] \n" + "vld1.32 d7[1], [%[ref]], %[kBPS] \n" + + "sub %[ref], %[ref], %[kBPS], lsl #2 \n" + + // (val) + 4 >> 3 + "vrshr.s16 d2, d2, #3 \n" + "vrshr.s16 d3, d3, #3 \n" + "vrshr.s16 d4, d4, #3 \n" + "vrshr.s16 d5, d5, #3 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + // Must accumulate before saturating + "vmovl.u8 q8, d6 \n" + "vmovl.u8 q9, d7 \n" + + "vqadd.s16 q1, q1, q8 \n" + "vqadd.s16 q2, q2, q9 \n" + + "vqmovun.s16 d0, q1 \n" + "vqmovun.s16 d1, q2 \n" + + "vst1.32 d0[0], [%[dst]], %[kBPS] \n" + "vst1.32 d0[1], [%[dst]], %[kBPS] \n" + "vst1.32 d1[0], [%[dst]], %[kBPS] \n" + "vst1.32 d1[1], [%[dst]] \n" + + : [in] "+r"(in), [dst] "+r"(dst) // modified registers + : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref) // constants + : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" // clobbered + ); +} + +#endif // WEBP_USE_INTRINSICS + +static void ITransform_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst, int do_two) { + ITransformOne_NEON(ref, in, dst); + if (do_two) { + ITransformOne_NEON(ref + 4, in + 16, dst + 4); + } +} + +// Load all 4x4 pixels into a single uint8x16_t variable. +static uint8x16_t Load4x4_NEON(const uint8_t* src) { + uint32x4_t out = vdupq_n_u32(0); + out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0); + out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1); + out = vld1q_lane_u32((const uint32_t*)(src + 2 * BPS), out, 2); + out = vld1q_lane_u32((const uint32_t*)(src + 3 * BPS), out, 3); + return vreinterpretq_u8_u32(out); +} + +// Forward transform. + +#if defined(WEBP_USE_INTRINSICS) + +static WEBP_INLINE void Transpose4x4_S16_NEON(const int16x4_t A, + const int16x4_t B, + const int16x4_t C, + const int16x4_t D, + int16x8_t* const out01, + int16x8_t* const out32) { + const int16x4x2_t AB = vtrn_s16(A, B); + const int16x4x2_t CD = vtrn_s16(C, D); + const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]), + vreinterpret_s32_s16(CD.val[0])); + const int32x2x2_t tmp13 = vtrn_s32(vreinterpret_s32_s16(AB.val[1]), + vreinterpret_s32_s16(CD.val[1])); + *out01 = vreinterpretq_s16_s64( + vcombine_s64(vreinterpret_s64_s32(tmp02.val[0]), + vreinterpret_s64_s32(tmp13.val[0]))); + *out32 = vreinterpretq_s16_s64( + vcombine_s64(vreinterpret_s64_s32(tmp13.val[1]), + vreinterpret_s64_s32(tmp02.val[1]))); +} + +static WEBP_INLINE int16x8_t DiffU8ToS16_NEON(const uint8x8_t a, + const uint8x8_t b) { + return vreinterpretq_s16_u16(vsubl_u8(a, b)); +} + +static void FTransform_NEON(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + int16x8_t d0d1, d3d2; // working 4x4 int16 variables + { + const uint8x16_t S0 = Load4x4_NEON(src); + const uint8x16_t R0 = Load4x4_NEON(ref); + const int16x8_t D0D1 = DiffU8ToS16_NEON(vget_low_u8(S0), vget_low_u8(R0)); + const int16x8_t D2D3 = DiffU8ToS16_NEON(vget_high_u8(S0), vget_high_u8(R0)); + const int16x4_t D0 = vget_low_s16(D0D1); + const int16x4_t D1 = vget_high_s16(D0D1); + const int16x4_t D2 = vget_low_s16(D2D3); + const int16x4_t D3 = vget_high_s16(D2D3); + Transpose4x4_S16_NEON(D0, D1, D2, D3, &d0d1, &d3d2); + } + { // 1rst pass + const int32x4_t kCst937 = vdupq_n_s32(937); + const int32x4_t kCst1812 = vdupq_n_s32(1812); + const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1) + const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2) + const int16x8_t a0a1_2 = vshlq_n_s16(a0a1, 3); + const int16x4_t tmp0 = vadd_s16(vget_low_s16(a0a1_2), + vget_high_s16(a0a1_2)); + const int16x4_t tmp2 = vsub_s16(vget_low_s16(a0a1_2), + vget_high_s16(a0a1_2)); + const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217); + const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217); + const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352); + const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); + const int16x4_t tmp1 = vshrn_n_s32(vaddq_s32(a2_p_a3, kCst1812), 9); + const int16x4_t tmp3 = vshrn_n_s32(vaddq_s32(a3_m_a2, kCst937), 9); + Transpose4x4_S16_NEON(tmp0, tmp1, tmp2, tmp3, &d0d1, &d3d2); + } + { // 2nd pass + // the (1<<16) addition is for the replacement: a3!=0 <-> 1-(a3==0) + const int32x4_t kCst12000 = vdupq_n_s32(12000 + (1 << 16)); + const int32x4_t kCst51000 = vdupq_n_s32(51000); + const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1) + const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2) + const int16x4_t a0_k7 = vadd_s16(vget_low_s16(a0a1), vdup_n_s16(7)); + const int16x4_t out0 = vshr_n_s16(vadd_s16(a0_k7, vget_high_s16(a0a1)), 4); + const int16x4_t out2 = vshr_n_s16(vsub_s16(a0_k7, vget_high_s16(a0a1)), 4); + const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217); + const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217); + const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352); + const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); + const int16x4_t tmp1 = vaddhn_s32(a2_p_a3, kCst12000); + const int16x4_t out3 = vaddhn_s32(a3_m_a2, kCst51000); + const int16x4_t a3_eq_0 = + vreinterpret_s16_u16(vceq_s16(vget_low_s16(a3a2), vdup_n_s16(0))); + const int16x4_t out1 = vadd_s16(tmp1, a3_eq_0); + vst1_s16(out + 0, out0); + vst1_s16(out + 4, out1); + vst1_s16(out + 8, out2); + vst1_s16(out + 12, out3); + } +} + +#else + +// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm +static const int16_t kCoeff16[] = { + 5352, 5352, 5352, 5352, 2217, 2217, 2217, 2217 +}; +static const int32_t kCoeff32[] = { + 1812, 1812, 1812, 1812, + 937, 937, 937, 937, + 12000, 12000, 12000, 12000, + 51000, 51000, 51000, 51000 +}; + +static void FTransform_NEON(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const int kBPS = BPS; + const uint8_t* src_ptr = src; + const uint8_t* ref_ptr = ref; + const int16_t* coeff16 = kCoeff16; + const int32_t* coeff32 = kCoeff32; + + __asm__ volatile ( + // load src into q4, q5 in high half + "vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d9}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d11}, [%[src_ptr]] \n" + + // load ref into q6, q7 in high half + "vld1.8 {d12}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d14}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d13}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d15}, [%[ref_ptr]] \n" + + // Pack the high values in to q4 and q6 + "vtrn.32 q4, q5 \n" + "vtrn.32 q6, q7 \n" + + // d[0-3] = src - ref + "vsubl.u8 q0, d8, d12 \n" + "vsubl.u8 q1, d9, d13 \n" + + // load coeff16 into q8(d16=5352, d17=2217) + "vld1.16 {q8}, [%[coeff16]] \n" + + // load coeff32 high half into q9 = 1812, q10 = 937 + "vld1.32 {q9, q10}, [%[coeff32]]! \n" + + // load coeff32 low half into q11=12000, q12=51000 + "vld1.32 {q11,q12}, [%[coeff32]] \n" + + // part 1 + // Transpose. Register dN is the same as dN in C + "vtrn.32 d0, d2 \n" + "vtrn.32 d1, d3 \n" + "vtrn.16 d0, d1 \n" + "vtrn.16 d2, d3 \n" + + "vadd.s16 d4, d0, d3 \n" // a0 = d0 + d3 + "vadd.s16 d5, d1, d2 \n" // a1 = d1 + d2 + "vsub.s16 d6, d1, d2 \n" // a2 = d1 - d2 + "vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3 + + "vadd.s16 d0, d4, d5 \n" // a0 + a1 + "vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) << 3 + "vsub.s16 d2, d4, d5 \n" // a0 - a1 + "vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1) << 3 + + "vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812 + "vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937 + "vmlal.s16 q9, d6, d17 \n" // a2*2217 + a3*5352 + 1812 + "vmlsl.s16 q10, d6, d16 \n" // a3*2217 + 937 - a2*5352 + + // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9 + // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9 + "vshrn.s32 d1, q9, #9 \n" + "vshrn.s32 d3, q10, #9 \n" + + // part 2 + // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12] + "vtrn.32 d0, d2 \n" + "vtrn.32 d1, d3 \n" + "vtrn.16 d0, d1 \n" + "vtrn.16 d2, d3 \n" + + "vmov.s16 d26, #7 \n" + + "vadd.s16 d4, d0, d3 \n" // a1 = ip[0] + ip[12] + "vadd.s16 d5, d1, d2 \n" // b1 = ip[4] + ip[8] + "vsub.s16 d6, d1, d2 \n" // c1 = ip[4] - ip[8] + "vadd.s16 d4, d4, d26 \n" // a1 + 7 + "vsub.s16 d7, d0, d3 \n" // d1 = ip[0] - ip[12] + + "vadd.s16 d0, d4, d5 \n" // op[0] = a1 + b1 + 7 + "vsub.s16 d2, d4, d5 \n" // op[8] = a1 - b1 + 7 + + "vmlal.s16 q11, d7, d16 \n" // d1*5352 + 12000 + "vmlal.s16 q12, d7, d17 \n" // d1*2217 + 51000 + + "vceq.s16 d4, d7, #0 \n" + + "vshr.s16 d0, d0, #4 \n" + "vshr.s16 d2, d2, #4 \n" + + "vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000 + "vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000 + + "vmvn d4, d4 \n" // !(d1 == 0) + // op[4] = (c1*2217 + d1*5352 + 12000)>>16 + "vshrn.s32 d1, q11, #16 \n" + // op[4] += (d1!=0) + "vsub.s16 d1, d1, d4 \n" + // op[12]= (d1*2217 - c1*5352 + 51000)>>16 + "vshrn.s32 d3, q12, #16 \n" + + // set result to out array + "vst1.16 {q0, q1}, [%[out]] \n" + : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr), + [coeff32] "+r"(coeff32) // modified registers + : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16), + [out] "r"(out) // constants + : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", + "q10", "q11", "q12", "q13" // clobbered + ); +} + +#endif + +#define LOAD_LANE_16b(VALUE, LANE) do { \ + (VALUE) = vld1_lane_s16(src, (VALUE), (LANE)); \ + src += stride; \ +} while (0) + +static void FTransformWHT_NEON(const int16_t* src, int16_t* out) { + const int stride = 16; + const int16x4_t zero = vdup_n_s16(0); + int32x4x4_t tmp0; + int16x4x4_t in; + INIT_VECTOR4(in, zero, zero, zero, zero); + LOAD_LANE_16b(in.val[0], 0); + LOAD_LANE_16b(in.val[1], 0); + LOAD_LANE_16b(in.val[2], 0); + LOAD_LANE_16b(in.val[3], 0); + LOAD_LANE_16b(in.val[0], 1); + LOAD_LANE_16b(in.val[1], 1); + LOAD_LANE_16b(in.val[2], 1); + LOAD_LANE_16b(in.val[3], 1); + LOAD_LANE_16b(in.val[0], 2); + LOAD_LANE_16b(in.val[1], 2); + LOAD_LANE_16b(in.val[2], 2); + LOAD_LANE_16b(in.val[3], 2); + LOAD_LANE_16b(in.val[0], 3); + LOAD_LANE_16b(in.val[1], 3); + LOAD_LANE_16b(in.val[2], 3); + LOAD_LANE_16b(in.val[3], 3); + + { + // a0 = in[0 * 16] + in[2 * 16] + // a1 = in[1 * 16] + in[3 * 16] + // a2 = in[1 * 16] - in[3 * 16] + // a3 = in[0 * 16] - in[2 * 16] + const int32x4_t a0 = vaddl_s16(in.val[0], in.val[2]); + const int32x4_t a1 = vaddl_s16(in.val[1], in.val[3]); + const int32x4_t a2 = vsubl_s16(in.val[1], in.val[3]); + const int32x4_t a3 = vsubl_s16(in.val[0], in.val[2]); + tmp0.val[0] = vaddq_s32(a0, a1); + tmp0.val[1] = vaddq_s32(a3, a2); + tmp0.val[2] = vsubq_s32(a3, a2); + tmp0.val[3] = vsubq_s32(a0, a1); + } + { + const int32x4x4_t tmp1 = Transpose4x4_NEON(tmp0); + // a0 = tmp[0 + i] + tmp[ 8 + i] + // a1 = tmp[4 + i] + tmp[12 + i] + // a2 = tmp[4 + i] - tmp[12 + i] + // a3 = tmp[0 + i] - tmp[ 8 + i] + const int32x4_t a0 = vaddq_s32(tmp1.val[0], tmp1.val[2]); + const int32x4_t a1 = vaddq_s32(tmp1.val[1], tmp1.val[3]); + const int32x4_t a2 = vsubq_s32(tmp1.val[1], tmp1.val[3]); + const int32x4_t a3 = vsubq_s32(tmp1.val[0], tmp1.val[2]); + const int32x4_t b0 = vhaddq_s32(a0, a1); // (a0 + a1) >> 1 + const int32x4_t b1 = vhaddq_s32(a3, a2); // (a3 + a2) >> 1 + const int32x4_t b2 = vhsubq_s32(a3, a2); // (a3 - a2) >> 1 + const int32x4_t b3 = vhsubq_s32(a0, a1); // (a0 - a1) >> 1 + const int16x4_t out0 = vmovn_s32(b0); + const int16x4_t out1 = vmovn_s32(b1); + const int16x4_t out2 = vmovn_s32(b2); + const int16x4_t out3 = vmovn_s32(b3); + + vst1_s16(out + 0, out0); + vst1_s16(out + 4, out1); + vst1_s16(out + 8, out2); + vst1_s16(out + 12, out3); + } +} +#undef LOAD_LANE_16b + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +// a 0123, b 0123 +// a 4567, b 4567 +// a 89ab, b 89ab +// a cdef, b cdef +// +// transpose +// +// a 048c, b 048c +// a 159d, b 159d +// a 26ae, b 26ae +// a 37bf, b 37bf +// +static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16_NEON(int16x8x4_t q4_in) { + const int16x8x2_t q2_tmp0 = vtrnq_s16(q4_in.val[0], q4_in.val[1]); + const int16x8x2_t q2_tmp1 = vtrnq_s16(q4_in.val[2], q4_in.val[3]); + const int32x4x2_t q2_tmp2 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[0]), + vreinterpretq_s32_s16(q2_tmp1.val[0])); + const int32x4x2_t q2_tmp3 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[1]), + vreinterpretq_s32_s16(q2_tmp1.val[1])); + q4_in.val[0] = vreinterpretq_s16_s32(q2_tmp2.val[0]); + q4_in.val[2] = vreinterpretq_s16_s32(q2_tmp2.val[1]); + q4_in.val[1] = vreinterpretq_s16_s32(q2_tmp3.val[0]); + q4_in.val[3] = vreinterpretq_s16_s32(q2_tmp3.val[1]); + return q4_in; +} + +static WEBP_INLINE int16x8x4_t DistoHorizontalPass_NEON( + const int16x8x4_t q4_in) { + // {a0, a1} = {in[0] + in[2], in[1] + in[3]} + // {a3, a2} = {in[0] - in[2], in[1] - in[3]} + const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]); + const int16x8_t q_a1 = vaddq_s16(q4_in.val[1], q4_in.val[3]); + const int16x8_t q_a3 = vsubq_s16(q4_in.val[0], q4_in.val[2]); + const int16x8_t q_a2 = vsubq_s16(q4_in.val[1], q4_in.val[3]); + int16x8x4_t q4_out; + // tmp[0] = a0 + a1 + // tmp[1] = a3 + a2 + // tmp[2] = a3 - a2 + // tmp[3] = a0 - a1 + INIT_VECTOR4(q4_out, + vabsq_s16(vaddq_s16(q_a0, q_a1)), + vabsq_s16(vaddq_s16(q_a3, q_a2)), + vabdq_s16(q_a3, q_a2), vabdq_s16(q_a0, q_a1)); + return q4_out; +} + +static WEBP_INLINE int16x8x4_t DistoVerticalPass_NEON(const uint8x8x4_t q4_in) { + const int16x8_t q_a0 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[0], + q4_in.val[2])); + const int16x8_t q_a1 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[1], + q4_in.val[3])); + const int16x8_t q_a2 = vreinterpretq_s16_u16(vsubl_u8(q4_in.val[1], + q4_in.val[3])); + const int16x8_t q_a3 = vreinterpretq_s16_u16(vsubl_u8(q4_in.val[0], + q4_in.val[2])); + int16x8x4_t q4_out; + + INIT_VECTOR4(q4_out, + vaddq_s16(q_a0, q_a1), vaddq_s16(q_a3, q_a2), + vsubq_s16(q_a3, q_a2), vsubq_s16(q_a0, q_a1)); + return q4_out; +} + +static WEBP_INLINE int16x4x4_t DistoLoadW_NEON(const uint16_t* w) { + const uint16x8_t q_w07 = vld1q_u16(&w[0]); + const uint16x8_t q_w8f = vld1q_u16(&w[8]); + int16x4x4_t d4_w; + INIT_VECTOR4(d4_w, + vget_low_s16(vreinterpretq_s16_u16(q_w07)), + vget_high_s16(vreinterpretq_s16_u16(q_w07)), + vget_low_s16(vreinterpretq_s16_u16(q_w8f)), + vget_high_s16(vreinterpretq_s16_u16(q_w8f))); + return d4_w; +} + +static WEBP_INLINE int32x2_t DistoSum_NEON(const int16x8x4_t q4_in, + const int16x4x4_t d4_w) { + int32x2_t d_sum; + // sum += w[ 0] * abs(b0); + // sum += w[ 4] * abs(b1); + // sum += w[ 8] * abs(b2); + // sum += w[12] * abs(b3); + int32x4_t q_sum0 = vmull_s16(d4_w.val[0], vget_low_s16(q4_in.val[0])); + int32x4_t q_sum1 = vmull_s16(d4_w.val[1], vget_low_s16(q4_in.val[1])); + int32x4_t q_sum2 = vmull_s16(d4_w.val[2], vget_low_s16(q4_in.val[2])); + int32x4_t q_sum3 = vmull_s16(d4_w.val[3], vget_low_s16(q4_in.val[3])); + q_sum0 = vmlsl_s16(q_sum0, d4_w.val[0], vget_high_s16(q4_in.val[0])); + q_sum1 = vmlsl_s16(q_sum1, d4_w.val[1], vget_high_s16(q4_in.val[1])); + q_sum2 = vmlsl_s16(q_sum2, d4_w.val[2], vget_high_s16(q4_in.val[2])); + q_sum3 = vmlsl_s16(q_sum3, d4_w.val[3], vget_high_s16(q4_in.val[3])); + + q_sum0 = vaddq_s32(q_sum0, q_sum1); + q_sum2 = vaddq_s32(q_sum2, q_sum3); + q_sum2 = vaddq_s32(q_sum0, q_sum2); + d_sum = vpadd_s32(vget_low_s32(q_sum2), vget_high_s32(q_sum2)); + d_sum = vpadd_s32(d_sum, d_sum); + return d_sum; +} + +#define LOAD_LANE_32b(src, VALUE, LANE) \ + (VALUE) = vld1_lane_u32((const uint32_t*)(src), (VALUE), (LANE)) + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +static int Disto4x4_NEON(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + uint32x2_t d_in_ab_0123 = vdup_n_u32(0); + uint32x2_t d_in_ab_4567 = vdup_n_u32(0); + uint32x2_t d_in_ab_89ab = vdup_n_u32(0); + uint32x2_t d_in_ab_cdef = vdup_n_u32(0); + uint8x8x4_t d4_in; + + // load data a, b + LOAD_LANE_32b(a + 0 * BPS, d_in_ab_0123, 0); + LOAD_LANE_32b(a + 1 * BPS, d_in_ab_4567, 0); + LOAD_LANE_32b(a + 2 * BPS, d_in_ab_89ab, 0); + LOAD_LANE_32b(a + 3 * BPS, d_in_ab_cdef, 0); + LOAD_LANE_32b(b + 0 * BPS, d_in_ab_0123, 1); + LOAD_LANE_32b(b + 1 * BPS, d_in_ab_4567, 1); + LOAD_LANE_32b(b + 2 * BPS, d_in_ab_89ab, 1); + LOAD_LANE_32b(b + 3 * BPS, d_in_ab_cdef, 1); + INIT_VECTOR4(d4_in, + vreinterpret_u8_u32(d_in_ab_0123), + vreinterpret_u8_u32(d_in_ab_4567), + vreinterpret_u8_u32(d_in_ab_89ab), + vreinterpret_u8_u32(d_in_ab_cdef)); + + { + // Vertical pass first to avoid a transpose (vertical and horizontal passes + // are commutative because w/kWeightY is symmetric) and subsequent + // transpose. + const int16x8x4_t q4_v = DistoVerticalPass_NEON(d4_in); + const int16x4x4_t d4_w = DistoLoadW_NEON(w); + // horizontal pass + const int16x8x4_t q4_t = DistoTranspose4x4S16_NEON(q4_v); + const int16x8x4_t q4_h = DistoHorizontalPass_NEON(q4_t); + int32x2_t d_sum = DistoSum_NEON(q4_h, d4_w); + + // abs(sum2 - sum1) >> 5 + d_sum = vabs_s32(d_sum); + d_sum = vshr_n_s32(d_sum, 5); + return vget_lane_s32(d_sum, 0); + } +} +#undef LOAD_LANE_32b + +static int Disto16x16_NEON(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_NEON(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ + +static void CollectHistogram_NEON(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH); + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + FTransform_NEON(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + { + int k; + const int16x8_t a0 = vld1q_s16(out + 0); + const int16x8_t b0 = vld1q_s16(out + 8); + const uint16x8_t a1 = vreinterpretq_u16_s16(vabsq_s16(a0)); + const uint16x8_t b1 = vreinterpretq_u16_s16(vabsq_s16(b0)); + const uint16x8_t a2 = vshrq_n_u16(a1, 3); + const uint16x8_t b2 = vshrq_n_u16(b1, 3); + const uint16x8_t a3 = vminq_u16(a2, max_coeff_thresh); + const uint16x8_t b3 = vminq_u16(b2, max_coeff_thresh); + vst1q_s16(out + 0, vreinterpretq_s16_u16(a3)); + vst1q_s16(out + 8, vreinterpretq_s16_u16(b3)); + // Convert coefficients to bin. + for (k = 0; k < 16; ++k) { + ++distribution[out[k]]; + } + } + } + VP8SetHistogramData(distribution, histo); +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE void AccumulateSSE16_NEON(const uint8_t* const a, + const uint8_t* const b, + uint32x4_t* const sum) { + const uint8x16_t a0 = vld1q_u8(a); + const uint8x16_t b0 = vld1q_u8(b); + const uint8x16_t abs_diff = vabdq_u8(a0, b0); + const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff), + vget_low_u8(abs_diff)); + const uint16x8_t prod2 = vmull_u8(vget_high_u8(abs_diff), + vget_high_u8(abs_diff)); + /* pair-wise adds and widen */ + const uint32x4_t sum1 = vpaddlq_u16(prod1); + const uint32x4_t sum2 = vpaddlq_u16(prod2); + *sum = vaddq_u32(*sum, vaddq_u32(sum1, sum2)); +} + +// Horizontal sum of all four uint32_t values in 'sum'. +static int SumToInt_NEON(uint32x4_t sum) { +#if WEBP_AARCH64 + return (int)vaddvq_u32(sum); +#else + const uint64x2_t sum2 = vpaddlq_u32(sum); + const uint32x2_t sum3 = vadd_u32(vreinterpret_u32_u64(vget_low_u64(sum2)), + vreinterpret_u32_u64(vget_high_u64(sum2))); + return (int)vget_lane_u32(sum3, 0); +#endif +} + +static int SSE16x16_NEON(const uint8_t* a, const uint8_t* b) { + uint32x4_t sum = vdupq_n_u32(0); + int y; + for (y = 0; y < 16; ++y) { + AccumulateSSE16_NEON(a + y * BPS, b + y * BPS, &sum); + } + return SumToInt_NEON(sum); +} + +static int SSE16x8_NEON(const uint8_t* a, const uint8_t* b) { + uint32x4_t sum = vdupq_n_u32(0); + int y; + for (y = 0; y < 8; ++y) { + AccumulateSSE16_NEON(a + y * BPS, b + y * BPS, &sum); + } + return SumToInt_NEON(sum); +} + +static int SSE8x8_NEON(const uint8_t* a, const uint8_t* b) { + uint32x4_t sum = vdupq_n_u32(0); + int y; + for (y = 0; y < 8; ++y) { + const uint8x8_t a0 = vld1_u8(a + y * BPS); + const uint8x8_t b0 = vld1_u8(b + y * BPS); + const uint8x8_t abs_diff = vabd_u8(a0, b0); + const uint16x8_t prod = vmull_u8(abs_diff, abs_diff); + sum = vpadalq_u16(sum, prod); + } + return SumToInt_NEON(sum); +} + +static int SSE4x4_NEON(const uint8_t* a, const uint8_t* b) { + const uint8x16_t a0 = Load4x4_NEON(a); + const uint8x16_t b0 = Load4x4_NEON(b); + const uint8x16_t abs_diff = vabdq_u8(a0, b0); + const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff), + vget_low_u8(abs_diff)); + const uint16x8_t prod2 = vmull_u8(vget_high_u8(abs_diff), + vget_high_u8(abs_diff)); + /* pair-wise adds and widen */ + const uint32x4_t sum1 = vpaddlq_u16(prod1); + const uint32x4_t sum2 = vpaddlq_u16(prod2); + return SumToInt_NEON(vaddq_u32(sum1, sum2)); +} + +//------------------------------------------------------------------------------ + +// Compilation with gcc-4.6.x is problematic for now. +#if !defined(WORK_AROUND_GCC) + +static int16x8_t Quantize_NEON(int16_t* const in, + const VP8Matrix* const mtx, int offset) { + const uint16x8_t sharp = vld1q_u16(&mtx->sharpen_[offset]); + const uint16x8_t q = vld1q_u16(&mtx->q_[offset]); + const uint16x8_t iq = vld1q_u16(&mtx->iq_[offset]); + const uint32x4_t bias0 = vld1q_u32(&mtx->bias_[offset + 0]); + const uint32x4_t bias1 = vld1q_u32(&mtx->bias_[offset + 4]); + + const int16x8_t a = vld1q_s16(in + offset); // in + const uint16x8_t b = vreinterpretq_u16_s16(vabsq_s16(a)); // coeff = abs(in) + const int16x8_t sign = vshrq_n_s16(a, 15); // sign + const uint16x8_t c = vaddq_u16(b, sharp); // + sharpen + const uint32x4_t m0 = vmull_u16(vget_low_u16(c), vget_low_u16(iq)); + const uint32x4_t m1 = vmull_u16(vget_high_u16(c), vget_high_u16(iq)); + const uint32x4_t m2 = vhaddq_u32(m0, bias0); + const uint32x4_t m3 = vhaddq_u32(m1, bias1); // (coeff * iQ + bias) >> 1 + const uint16x8_t c0 = vcombine_u16(vshrn_n_u32(m2, 16), + vshrn_n_u32(m3, 16)); // QFIX=17 = 16+1 + const uint16x8_t c1 = vminq_u16(c0, vdupq_n_u16(MAX_LEVEL)); + const int16x8_t c2 = veorq_s16(vreinterpretq_s16_u16(c1), sign); + const int16x8_t c3 = vsubq_s16(c2, sign); // restore sign + const int16x8_t c4 = vmulq_s16(c3, vreinterpretq_s16_u16(q)); + vst1q_s16(in + offset, c4); + assert(QFIX == 17); // this function can't work as is if QFIX != 16+1 + return c3; +} + +static const uint8_t kShuffles[4][8] = { + { 0, 1, 2, 3, 8, 9, 16, 17 }, + { 10, 11, 4, 5, 6, 7, 12, 13 }, + { 18, 19, 24, 25, 26, 27, 20, 21 }, + { 14, 15, 22, 23, 28, 29, 30, 31 } +}; + +static int QuantizeBlock_NEON(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + const int16x8_t out0 = Quantize_NEON(in, mtx, 0); + const int16x8_t out1 = Quantize_NEON(in, mtx, 8); + uint8x8x4_t shuffles; + // vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use + // non-standard versions there. +#if defined(__APPLE__) && WEBP_AARCH64 && \ + defined(__apple_build_version__) && (__apple_build_version__< 6020037) + uint8x16x2_t all_out; + INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1)); + INIT_VECTOR4(shuffles, + vtbl2q_u8(all_out, vld1_u8(kShuffles[0])), + vtbl2q_u8(all_out, vld1_u8(kShuffles[1])), + vtbl2q_u8(all_out, vld1_u8(kShuffles[2])), + vtbl2q_u8(all_out, vld1_u8(kShuffles[3]))); +#else + uint8x8x4_t all_out; + INIT_VECTOR4(all_out, + vreinterpret_u8_s16(vget_low_s16(out0)), + vreinterpret_u8_s16(vget_high_s16(out0)), + vreinterpret_u8_s16(vget_low_s16(out1)), + vreinterpret_u8_s16(vget_high_s16(out1))); + INIT_VECTOR4(shuffles, + vtbl4_u8(all_out, vld1_u8(kShuffles[0])), + vtbl4_u8(all_out, vld1_u8(kShuffles[1])), + vtbl4_u8(all_out, vld1_u8(kShuffles[2])), + vtbl4_u8(all_out, vld1_u8(kShuffles[3]))); +#endif + // Zigzag reordering + vst1_u8((uint8_t*)(out + 0), shuffles.val[0]); + vst1_u8((uint8_t*)(out + 4), shuffles.val[1]); + vst1_u8((uint8_t*)(out + 8), shuffles.val[2]); + vst1_u8((uint8_t*)(out + 12), shuffles.val[3]); + // test zeros + if (*(uint64_t*)(out + 0) != 0) return 1; + if (*(uint64_t*)(out + 4) != 0) return 1; + if (*(uint64_t*)(out + 8) != 0) return 1; + if (*(uint64_t*)(out + 12) != 0) return 1; + return 0; +} + +static int Quantize2Blocks_NEON(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = QuantizeBlock_NEON(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_NEON(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} + +#endif // !WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) { + VP8ITransform = ITransform_NEON; + VP8FTransform = FTransform_NEON; + + VP8FTransformWHT = FTransformWHT_NEON; + + VP8TDisto4x4 = Disto4x4_NEON; + VP8TDisto16x16 = Disto16x16_NEON; + VP8CollectHistogram = CollectHistogram_NEON; + + VP8SSE16x16 = SSE16x16_NEON; + VP8SSE16x8 = SSE16x8_NEON; + VP8SSE8x8 = SSE8x8_NEON; + VP8SSE4x4 = SSE4x4_NEON; + +#if !defined(WORK_AROUND_GCC) + VP8EncQuantizeBlock = QuantizeBlock_NEON; + VP8EncQuantize2Blocks = Quantize2Blocks_NEON; +#endif +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8EncDspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/enc_sse2.c b/libraries/webp/src/dsp/enc_sse2.c new file mode 100644 index 0000000000..010624a2f7 --- /dev/null +++ b/libraries/webp/src/dsp/enc_sse2.c @@ -0,0 +1,1514 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of speed-critical encoding functions. +// +// Author: Christian Duvivier (cduvivier@google.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) +#include +#include // for abs() +#include + +#include "src/dsp/common_sse2.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +// Does one inverse transform. +static void ITransform_One_SSE2(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + // This implementation makes use of 16-bit fixed point versions of two + // multiply constants: + // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 + // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 + // + // To be able to use signed 16-bit integers, we use the following trick to + // have constants within range: + // - Associated constants are obtained by subtracting the 16-bit fixed point + // version of one: + // k = K - (1 << 16) => K = k + (1 << 16) + // K1 = 85267 => k1 = 20091 + // K2 = 35468 => k2 = -30068 + // - The multiplication of a variable by a constant become the sum of the + // variable and the multiplication of that variable by the associated + // constant: + // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x + const __m128i k1k2 = _mm_set_epi16(-30068, -30068, -30068, -30068, + 20091, 20091, 20091, 20091); + const __m128i k2k1 = _mm_set_epi16(20091, 20091, 20091, 20091, + -30068, -30068, -30068, -30068); + const __m128i zero = _mm_setzero_si128(); + const __m128i zero_four = _mm_set_epi16(0, 0, 0, 0, 4, 4, 4, 4); + __m128i T01, T23; + + // Load and concatenate the transform coefficients. + const __m128i in01 = _mm_loadu_si128((const __m128i*)&in[0]); + const __m128i in23 = _mm_loadu_si128((const __m128i*)&in[8]); + // a00 a10 a20 a30 a01 a11 a21 a31 + // a02 a12 a22 a32 a03 a13 a23 a33 + + // Vertical pass and subsequent transpose. + { + const __m128i in1 = _mm_unpackhi_epi64(in01, in01); + const __m128i in3 = _mm_unpackhi_epi64(in23, in23); + + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 + // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 + const __m128i a_d3 = _mm_add_epi16(in01, in23); + const __m128i b_c3 = _mm_sub_epi16(in01, in23); + const __m128i c1d1 = _mm_mulhi_epi16(in1, k2k1); + const __m128i c2d2 = _mm_mulhi_epi16(in3, k1k2); + const __m128i c3 = _mm_unpackhi_epi64(b_c3, b_c3); + const __m128i c4 = _mm_sub_epi16(c1d1, c2d2); + const __m128i c = _mm_add_epi16(c3, c4); + const __m128i d4u = _mm_add_epi16(c1d1, c2d2); + const __m128i du = _mm_add_epi16(a_d3, d4u); + const __m128i d = _mm_unpackhi_epi64(du, du); + + // Second pass. + const __m128i comb_ab = _mm_unpacklo_epi64(a_d3, b_c3); + const __m128i comb_dc = _mm_unpacklo_epi64(d, c); + + const __m128i tmp01 = _mm_add_epi16(comb_ab, comb_dc); + const __m128i tmp32 = _mm_sub_epi16(comb_ab, comb_dc); + const __m128i tmp23 = _mm_shuffle_epi32(tmp32, _MM_SHUFFLE(1, 0, 3, 2)); + + const __m128i transpose_0 = _mm_unpacklo_epi16(tmp01, tmp23); + const __m128i transpose_1 = _mm_unpackhi_epi16(tmp01, tmp23); + // a00 a20 a01 a21 a02 a22 a03 a23 + // a10 a30 a11 a31 a12 a32 a13 a33 + + T01 = _mm_unpacklo_epi16(transpose_0, transpose_1); + T23 = _mm_unpackhi_epi16(transpose_0, transpose_1); + // a00 a10 a20 a30 a01 a11 a21 a31 + // a02 a12 a22 a32 a03 a13 a23 a33 + } + + // Horizontal pass and subsequent transpose. + { + const __m128i T1 = _mm_unpackhi_epi64(T01, T01); + const __m128i T3 = _mm_unpackhi_epi64(T23, T23); + + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i dc = _mm_add_epi16(T01, zero_four); + + // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 + // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 + const __m128i a_d3 = _mm_add_epi16(dc, T23); + const __m128i b_c3 = _mm_sub_epi16(dc, T23); + const __m128i c1d1 = _mm_mulhi_epi16(T1, k2k1); + const __m128i c2d2 = _mm_mulhi_epi16(T3, k1k2); + const __m128i c3 = _mm_unpackhi_epi64(b_c3, b_c3); + const __m128i c4 = _mm_sub_epi16(c1d1, c2d2); + const __m128i c = _mm_add_epi16(c3, c4); + const __m128i d4u = _mm_add_epi16(c1d1, c2d2); + const __m128i du = _mm_add_epi16(a_d3, d4u); + const __m128i d = _mm_unpackhi_epi64(du, du); + + // Second pass. + const __m128i comb_ab = _mm_unpacklo_epi64(a_d3, b_c3); + const __m128i comb_dc = _mm_unpacklo_epi64(d, c); + + const __m128i tmp01 = _mm_add_epi16(comb_ab, comb_dc); + const __m128i tmp32 = _mm_sub_epi16(comb_ab, comb_dc); + const __m128i tmp23 = _mm_shuffle_epi32(tmp32, _MM_SHUFFLE(1, 0, 3, 2)); + + const __m128i shifted01 = _mm_srai_epi16(tmp01, 3); + const __m128i shifted23 = _mm_srai_epi16(tmp23, 3); + // a00 a01 a02 a03 a10 a11 a12 a13 + // a20 a21 a22 a23 a30 a31 a32 a33 + + const __m128i transpose_0 = _mm_unpacklo_epi16(shifted01, shifted23); + const __m128i transpose_1 = _mm_unpackhi_epi16(shifted01, shifted23); + // a00 a20 a01 a21 a02 a22 a03 a23 + // a10 a30 a11 a31 a12 a32 a13 a33 + + T01 = _mm_unpacklo_epi16(transpose_0, transpose_1); + T23 = _mm_unpackhi_epi16(transpose_0, transpose_1); + // a00 a10 a20 a30 a01 a11 a21 a31 + // a02 a12 a22 a32 a03 a13 a23 a33 + } + + // Add inverse transform to 'ref' and store. + { + // Load the reference(s). + __m128i ref01, ref23, ref0123; + int32_t buf[4]; + + // Load four bytes/pixels per line. + const __m128i ref0 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[0 * BPS])); + const __m128i ref1 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[1 * BPS])); + const __m128i ref2 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[2 * BPS])); + const __m128i ref3 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[3 * BPS])); + ref01 = _mm_unpacklo_epi32(ref0, ref1); + ref23 = _mm_unpacklo_epi32(ref2, ref3); + + // Convert to 16b. + ref01 = _mm_unpacklo_epi8(ref01, zero); + ref23 = _mm_unpacklo_epi8(ref23, zero); + // Add the inverse transform(s). + ref01 = _mm_add_epi16(ref01, T01); + ref23 = _mm_add_epi16(ref23, T23); + // Unsigned saturate to 8b. + ref0123 = _mm_packus_epi16(ref01, ref23); + + _mm_storeu_si128((__m128i *)buf, ref0123); + + // Store four bytes/pixels per line. + WebPInt32ToMem(&dst[0 * BPS], buf[0]); + WebPInt32ToMem(&dst[1 * BPS], buf[1]); + WebPInt32ToMem(&dst[2 * BPS], buf[2]); + WebPInt32ToMem(&dst[3 * BPS], buf[3]); + } +} + +// Does two inverse transforms. +static void ITransform_Two_SSE2(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + // This implementation makes use of 16-bit fixed point versions of two + // multiply constants: + // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 + // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 + // + // To be able to use signed 16-bit integers, we use the following trick to + // have constants within range: + // - Associated constants are obtained by subtracting the 16-bit fixed point + // version of one: + // k = K - (1 << 16) => K = k + (1 << 16) + // K1 = 85267 => k1 = 20091 + // K2 = 35468 => k2 = -30068 + // - The multiplication of a variable by a constant become the sum of the + // variable and the multiplication of that variable by the associated + // constant: + // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x + const __m128i k1 = _mm_set1_epi16(20091); + const __m128i k2 = _mm_set1_epi16(-30068); + __m128i T0, T1, T2, T3; + + // Load and concatenate the transform coefficients (we'll do two inverse + // transforms in parallel). + __m128i in0, in1, in2, in3; + { + const __m128i tmp0 = _mm_loadu_si128((const __m128i*)&in[0]); + const __m128i tmp1 = _mm_loadu_si128((const __m128i*)&in[8]); + const __m128i tmp2 = _mm_loadu_si128((const __m128i*)&in[16]); + const __m128i tmp3 = _mm_loadu_si128((const __m128i*)&in[24]); + in0 = _mm_unpacklo_epi64(tmp0, tmp2); + in1 = _mm_unpackhi_epi64(tmp0, tmp2); + in2 = _mm_unpacklo_epi64(tmp1, tmp3); + in3 = _mm_unpackhi_epi64(tmp1, tmp3); + // a00 a10 a20 a30 b00 b10 b20 b30 + // a01 a11 a21 a31 b01 b11 b21 b31 + // a02 a12 a22 a32 b02 b12 b22 b32 + // a03 a13 a23 a33 b03 b13 b23 b33 + } + + // Vertical pass and subsequent transpose. + { + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i a = _mm_add_epi16(in0, in2); + const __m128i b = _mm_sub_epi16(in0, in2); + // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 + const __m128i c1 = _mm_mulhi_epi16(in1, k2); + const __m128i c2 = _mm_mulhi_epi16(in3, k1); + const __m128i c3 = _mm_sub_epi16(in1, in3); + const __m128i c4 = _mm_sub_epi16(c1, c2); + const __m128i c = _mm_add_epi16(c3, c4); + // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 + const __m128i d1 = _mm_mulhi_epi16(in1, k1); + const __m128i d2 = _mm_mulhi_epi16(in3, k2); + const __m128i d3 = _mm_add_epi16(in1, in3); + const __m128i d4 = _mm_add_epi16(d1, d2); + const __m128i d = _mm_add_epi16(d3, d4); + + // Second pass. + const __m128i tmp0 = _mm_add_epi16(a, d); + const __m128i tmp1 = _mm_add_epi16(b, c); + const __m128i tmp2 = _mm_sub_epi16(b, c); + const __m128i tmp3 = _mm_sub_epi16(a, d); + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&tmp0, &tmp1, &tmp2, &tmp3, &T0, &T1, &T2, &T3); + } + + // Horizontal pass and subsequent transpose. + { + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i four = _mm_set1_epi16(4); + const __m128i dc = _mm_add_epi16(T0, four); + const __m128i a = _mm_add_epi16(dc, T2); + const __m128i b = _mm_sub_epi16(dc, T2); + // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 + const __m128i c1 = _mm_mulhi_epi16(T1, k2); + const __m128i c2 = _mm_mulhi_epi16(T3, k1); + const __m128i c3 = _mm_sub_epi16(T1, T3); + const __m128i c4 = _mm_sub_epi16(c1, c2); + const __m128i c = _mm_add_epi16(c3, c4); + // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 + const __m128i d1 = _mm_mulhi_epi16(T1, k1); + const __m128i d2 = _mm_mulhi_epi16(T3, k2); + const __m128i d3 = _mm_add_epi16(T1, T3); + const __m128i d4 = _mm_add_epi16(d1, d2); + const __m128i d = _mm_add_epi16(d3, d4); + + // Second pass. + const __m128i tmp0 = _mm_add_epi16(a, d); + const __m128i tmp1 = _mm_add_epi16(b, c); + const __m128i tmp2 = _mm_sub_epi16(b, c); + const __m128i tmp3 = _mm_sub_epi16(a, d); + const __m128i shifted0 = _mm_srai_epi16(tmp0, 3); + const __m128i shifted1 = _mm_srai_epi16(tmp1, 3); + const __m128i shifted2 = _mm_srai_epi16(tmp2, 3); + const __m128i shifted3 = _mm_srai_epi16(tmp3, 3); + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1, + &T2, &T3); + } + + // Add inverse transform to 'ref' and store. + { + const __m128i zero = _mm_setzero_si128(); + // Load the reference(s). + __m128i ref0, ref1, ref2, ref3; + // Load eight bytes/pixels per line. + ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); + ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); + ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); + ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); + // Convert to 16b. + ref0 = _mm_unpacklo_epi8(ref0, zero); + ref1 = _mm_unpacklo_epi8(ref1, zero); + ref2 = _mm_unpacklo_epi8(ref2, zero); + ref3 = _mm_unpacklo_epi8(ref3, zero); + // Add the inverse transform(s). + ref0 = _mm_add_epi16(ref0, T0); + ref1 = _mm_add_epi16(ref1, T1); + ref2 = _mm_add_epi16(ref2, T2); + ref3 = _mm_add_epi16(ref3, T3); + // Unsigned saturate to 8b. + ref0 = _mm_packus_epi16(ref0, ref0); + ref1 = _mm_packus_epi16(ref1, ref1); + ref2 = _mm_packus_epi16(ref2, ref2); + ref3 = _mm_packus_epi16(ref3, ref3); + // Store eight bytes/pixels per line. + _mm_storel_epi64((__m128i*)&dst[0 * BPS], ref0); + _mm_storel_epi64((__m128i*)&dst[1 * BPS], ref1); + _mm_storel_epi64((__m128i*)&dst[2 * BPS], ref2); + _mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3); + } +} + +// Does one or two inverse transforms. +static void ITransform_SSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { + if (do_two) { + ITransform_Two_SSE2(ref, in, dst); + } else { + ITransform_One_SSE2(ref, in, dst); + } +} + +static void FTransformPass1_SSE2(const __m128i* const in01, + const __m128i* const in23, + __m128i* const out01, + __m128i* const out32) { + const __m128i k937 = _mm_set1_epi32(937); + const __m128i k1812 = _mm_set1_epi32(1812); + + const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8); + const __m128i k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8); + const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352, + 2217, 5352, 2217, 5352); + const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217, + -5352, 2217, -5352, 2217); + + // *in01 = 00 01 10 11 02 03 12 13 + // *in23 = 20 21 30 31 22 23 32 33 + const __m128i shuf01_p = _mm_shufflehi_epi16(*in01, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i shuf23_p = _mm_shufflehi_epi16(*in23, _MM_SHUFFLE(2, 3, 0, 1)); + // 00 01 10 11 03 02 13 12 + // 20 21 30 31 23 22 33 32 + const __m128i s01 = _mm_unpacklo_epi64(shuf01_p, shuf23_p); + const __m128i s32 = _mm_unpackhi_epi64(shuf01_p, shuf23_p); + // 00 01 10 11 20 21 30 31 + // 03 02 13 12 23 22 33 32 + const __m128i a01 = _mm_add_epi16(s01, s32); + const __m128i a32 = _mm_sub_epi16(s01, s32); + // [d0 + d3 | d1 + d2 | ...] = [a0 a1 | a0' a1' | ... ] + // [d0 - d3 | d1 - d2 | ...] = [a3 a2 | a3' a2' | ... ] + + const __m128i tmp0 = _mm_madd_epi16(a01, k88p); // [ (a0 + a1) << 3, ... ] + const __m128i tmp2 = _mm_madd_epi16(a01, k88m); // [ (a0 - a1) << 3, ... ] + const __m128i tmp1_1 = _mm_madd_epi16(a32, k5352_2217p); + const __m128i tmp3_1 = _mm_madd_epi16(a32, k5352_2217m); + const __m128i tmp1_2 = _mm_add_epi32(tmp1_1, k1812); + const __m128i tmp3_2 = _mm_add_epi32(tmp3_1, k937); + const __m128i tmp1 = _mm_srai_epi32(tmp1_2, 9); + const __m128i tmp3 = _mm_srai_epi32(tmp3_2, 9); + const __m128i s03 = _mm_packs_epi32(tmp0, tmp2); + const __m128i s12 = _mm_packs_epi32(tmp1, tmp3); + const __m128i s_lo = _mm_unpacklo_epi16(s03, s12); // 0 1 0 1 0 1... + const __m128i s_hi = _mm_unpackhi_epi16(s03, s12); // 2 3 2 3 2 3 + const __m128i v23 = _mm_unpackhi_epi32(s_lo, s_hi); + *out01 = _mm_unpacklo_epi32(s_lo, s_hi); + *out32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2.. +} + +static void FTransformPass2_SSE2(const __m128i* const v01, + const __m128i* const v32, + int16_t* out) { + const __m128i zero = _mm_setzero_si128(); + const __m128i seven = _mm_set1_epi16(7); + const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217, + 5352, 2217, 5352, 2217); + const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352, + 2217, -5352, 2217, -5352); + const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16)); + const __m128i k51000 = _mm_set1_epi32(51000); + + // Same operations are done on the (0,3) and (1,2) pairs. + // a3 = v0 - v3 + // a2 = v1 - v2 + const __m128i a32 = _mm_sub_epi16(*v01, *v32); + const __m128i a22 = _mm_unpackhi_epi64(a32, a32); + + const __m128i b23 = _mm_unpacklo_epi16(a22, a32); + const __m128i c1 = _mm_madd_epi16(b23, k5352_2217); + const __m128i c3 = _mm_madd_epi16(b23, k2217_5352); + const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one); + const __m128i d3 = _mm_add_epi32(c3, k51000); + const __m128i e1 = _mm_srai_epi32(d1, 16); + const __m128i e3 = _mm_srai_epi32(d3, 16); + // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16) + // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16) + const __m128i f1 = _mm_packs_epi32(e1, e1); + const __m128i f3 = _mm_packs_epi32(e3, e3); + // g1 = f1 + (a3 != 0); + // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the + // desired (0, 1), we add one earlier through k12000_plus_one. + // -> g1 = f1 + 1 - (a3 == 0) + const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero)); + + // a0 = v0 + v3 + // a1 = v1 + v2 + const __m128i a01 = _mm_add_epi16(*v01, *v32); + const __m128i a01_plus_7 = _mm_add_epi16(a01, seven); + const __m128i a11 = _mm_unpackhi_epi64(a01, a01); + const __m128i c0 = _mm_add_epi16(a01_plus_7, a11); + const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11); + // d0 = (a0 + a1 + 7) >> 4; + // d2 = (a0 - a1 + 7) >> 4; + const __m128i d0 = _mm_srai_epi16(c0, 4); + const __m128i d2 = _mm_srai_epi16(c2, 4); + + const __m128i d0_g1 = _mm_unpacklo_epi64(d0, g1); + const __m128i d2_f3 = _mm_unpacklo_epi64(d2, f3); + _mm_storeu_si128((__m128i*)&out[0], d0_g1); + _mm_storeu_si128((__m128i*)&out[8], d2_f3); +} + +static void FTransform_SSE2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const __m128i zero = _mm_setzero_si128(); + // Load src. + const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); + const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]); + const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]); + const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]); + // 00 01 02 03 * + // 10 11 12 13 * + // 20 21 22 23 * + // 30 31 32 33 * + // Shuffle. + const __m128i src_0 = _mm_unpacklo_epi16(src0, src1); + const __m128i src_1 = _mm_unpacklo_epi16(src2, src3); + // 00 01 10 11 02 03 12 13 * * ... + // 20 21 30 31 22 22 32 33 * * ... + + // Load ref. + const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); + const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); + const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); + const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); + const __m128i ref_0 = _mm_unpacklo_epi16(ref0, ref1); + const __m128i ref_1 = _mm_unpacklo_epi16(ref2, ref3); + + // Convert both to 16 bit. + const __m128i src_0_16b = _mm_unpacklo_epi8(src_0, zero); + const __m128i src_1_16b = _mm_unpacklo_epi8(src_1, zero); + const __m128i ref_0_16b = _mm_unpacklo_epi8(ref_0, zero); + const __m128i ref_1_16b = _mm_unpacklo_epi8(ref_1, zero); + + // Compute the difference. + const __m128i row01 = _mm_sub_epi16(src_0_16b, ref_0_16b); + const __m128i row23 = _mm_sub_epi16(src_1_16b, ref_1_16b); + __m128i v01, v32; + + // First pass + FTransformPass1_SSE2(&row01, &row23, &v01, &v32); + + // Second pass + FTransformPass2_SSE2(&v01, &v32, out); +} + +static void FTransform2_SSE2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const __m128i zero = _mm_setzero_si128(); + + // Load src and convert to 16b. + const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); + const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]); + const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]); + const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]); + const __m128i src_0 = _mm_unpacklo_epi8(src0, zero); + const __m128i src_1 = _mm_unpacklo_epi8(src1, zero); + const __m128i src_2 = _mm_unpacklo_epi8(src2, zero); + const __m128i src_3 = _mm_unpacklo_epi8(src3, zero); + // Load ref and convert to 16b. + const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); + const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); + const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); + const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); + const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero); + const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero); + const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero); + const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero); + // Compute difference. -> 00 01 02 03 00' 01' 02' 03' + const __m128i diff0 = _mm_sub_epi16(src_0, ref_0); + const __m128i diff1 = _mm_sub_epi16(src_1, ref_1); + const __m128i diff2 = _mm_sub_epi16(src_2, ref_2); + const __m128i diff3 = _mm_sub_epi16(src_3, ref_3); + + // Unpack and shuffle + // 00 01 02 03 0 0 0 0 + // 10 11 12 13 0 0 0 0 + // 20 21 22 23 0 0 0 0 + // 30 31 32 33 0 0 0 0 + const __m128i shuf01l = _mm_unpacklo_epi32(diff0, diff1); + const __m128i shuf23l = _mm_unpacklo_epi32(diff2, diff3); + const __m128i shuf01h = _mm_unpackhi_epi32(diff0, diff1); + const __m128i shuf23h = _mm_unpackhi_epi32(diff2, diff3); + __m128i v01l, v32l; + __m128i v01h, v32h; + + // First pass + FTransformPass1_SSE2(&shuf01l, &shuf23l, &v01l, &v32l); + FTransformPass1_SSE2(&shuf01h, &shuf23h, &v01h, &v32h); + + // Second pass + FTransformPass2_SSE2(&v01l, &v32l, out + 0); + FTransformPass2_SSE2(&v01h, &v32h, out + 16); +} + +static void FTransformWHTRow_SSE2(const int16_t* const in, __m128i* const out) { + const __m128i kMult = _mm_set_epi16(-1, 1, -1, 1, 1, 1, 1, 1); + const __m128i src0 = _mm_loadl_epi64((__m128i*)&in[0 * 16]); + const __m128i src1 = _mm_loadl_epi64((__m128i*)&in[1 * 16]); + const __m128i src2 = _mm_loadl_epi64((__m128i*)&in[2 * 16]); + const __m128i src3 = _mm_loadl_epi64((__m128i*)&in[3 * 16]); + const __m128i A01 = _mm_unpacklo_epi16(src0, src1); // A0 A1 | ... + const __m128i A23 = _mm_unpacklo_epi16(src2, src3); // A2 A3 | ... + const __m128i B0 = _mm_adds_epi16(A01, A23); // a0 | a1 | ... + const __m128i B1 = _mm_subs_epi16(A01, A23); // a3 | a2 | ... + const __m128i C0 = _mm_unpacklo_epi32(B0, B1); // a0 | a1 | a3 | a2 | ... + const __m128i C1 = _mm_unpacklo_epi32(B1, B0); // a3 | a2 | a0 | a1 | ... + const __m128i D = _mm_unpacklo_epi64(C0, C1); // a0 a1 a3 a2 a3 a2 a0 a1 + *out = _mm_madd_epi16(D, kMult); +} + +static void FTransformWHT_SSE2(const int16_t* in, int16_t* out) { + // Input is 12b signed. + __m128i row0, row1, row2, row3; + // Rows are 14b signed. + FTransformWHTRow_SSE2(in + 0 * 64, &row0); + FTransformWHTRow_SSE2(in + 1 * 64, &row1); + FTransformWHTRow_SSE2(in + 2 * 64, &row2); + FTransformWHTRow_SSE2(in + 3 * 64, &row3); + + { + // The a* are 15b signed. + const __m128i a0 = _mm_add_epi32(row0, row2); + const __m128i a1 = _mm_add_epi32(row1, row3); + const __m128i a2 = _mm_sub_epi32(row1, row3); + const __m128i a3 = _mm_sub_epi32(row0, row2); + const __m128i a0a3 = _mm_packs_epi32(a0, a3); + const __m128i a1a2 = _mm_packs_epi32(a1, a2); + + // The b* are 16b signed. + const __m128i b0b1 = _mm_add_epi16(a0a3, a1a2); + const __m128i b3b2 = _mm_sub_epi16(a0a3, a1a2); + const __m128i tmp_b2b3 = _mm_unpackhi_epi64(b3b2, b3b2); + const __m128i b2b3 = _mm_unpacklo_epi64(tmp_b2b3, b3b2); + + _mm_storeu_si128((__m128i*)&out[0], _mm_srai_epi16(b0b1, 1)); + _mm_storeu_si128((__m128i*)&out[8], _mm_srai_epi16(b2b3, 1)); + } +} + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +static void CollectHistogram_SSE2(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + const __m128i zero = _mm_setzero_si128(); + const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + int k; + + FTransform_SSE2(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + + // Convert coefficients to bin (within out[]). + { + // Load. + const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]); + const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]); + const __m128i d0 = _mm_sub_epi16(zero, out0); + const __m128i d1 = _mm_sub_epi16(zero, out1); + const __m128i abs0 = _mm_max_epi16(out0, d0); // abs(v), 16b + const __m128i abs1 = _mm_max_epi16(out1, d1); + // v = abs(out) >> 3 + const __m128i v0 = _mm_srai_epi16(abs0, 3); + const __m128i v1 = _mm_srai_epi16(abs1, 3); + // bin = min(v, MAX_COEFF_THRESH) + const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); + const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); + // Store. + _mm_storeu_si128((__m128i*)&out[0], bin0); + _mm_storeu_si128((__m128i*)&out[8], bin1); + } + + // Convert coefficients to bin. + for (k = 0; k < 16; ++k) { + ++distribution[out[k]]; + } + } + VP8SetHistogramData(distribution, histo); +} + +//------------------------------------------------------------------------------ +// Intra predictions + +// helper for chroma-DC predictions +static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) { + int j; + const __m128i values = _mm_set1_epi8((char)v); + for (j = 0; j < 8; ++j) { + _mm_storel_epi64((__m128i*)(dst + j * BPS), values); + } +} + +static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) { + int j; + const __m128i values = _mm_set1_epi8((char)v); + for (j = 0; j < 16; ++j) { + _mm_store_si128((__m128i*)(dst + j * BPS), values); + } +} + +static WEBP_INLINE void Fill_SSE2(uint8_t* dst, int value, int size) { + if (size == 4) { + int j; + for (j = 0; j < 4; ++j) { + memset(dst + j * BPS, value, 4); + } + } else if (size == 8) { + Put8x8uv_SSE2(value, dst); + } else { + Put16_SSE2(value, dst); + } +} + +static WEBP_INLINE void VE8uv_SSE2(uint8_t* dst, const uint8_t* top) { + int j; + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + for (j = 0; j < 8; ++j) { + _mm_storel_epi64((__m128i*)(dst + j * BPS), top_values); + } +} + +static WEBP_INLINE void VE16_SSE2(uint8_t* dst, const uint8_t* top) { + const __m128i top_values = _mm_load_si128((const __m128i*)top); + int j; + for (j = 0; j < 16; ++j) { + _mm_store_si128((__m128i*)(dst + j * BPS), top_values); + } +} + +static WEBP_INLINE void VerticalPred_SSE2(uint8_t* dst, + const uint8_t* top, int size) { + if (top != NULL) { + if (size == 8) { + VE8uv_SSE2(dst, top); + } else { + VE16_SSE2(dst, top); + } + } else { + Fill_SSE2(dst, 127, size); + } +} + +static WEBP_INLINE void HE8uv_SSE2(uint8_t* dst, const uint8_t* left) { + int j; + for (j = 0; j < 8; ++j) { + const __m128i values = _mm_set1_epi8((char)left[j]); + _mm_storel_epi64((__m128i*)dst, values); + dst += BPS; + } +} + +static WEBP_INLINE void HE16_SSE2(uint8_t* dst, const uint8_t* left) { + int j; + for (j = 0; j < 16; ++j) { + const __m128i values = _mm_set1_epi8((char)left[j]); + _mm_store_si128((__m128i*)dst, values); + dst += BPS; + } +} + +static WEBP_INLINE void HorizontalPred_SSE2(uint8_t* dst, + const uint8_t* left, int size) { + if (left != NULL) { + if (size == 8) { + HE8uv_SSE2(dst, left); + } else { + HE16_SSE2(dst, left); + } + } else { + Fill_SSE2(dst, 129, size); + } +} + +static WEBP_INLINE void TM_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top, int size) { + const __m128i zero = _mm_setzero_si128(); + int y; + if (size == 8) { + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); + for (y = 0; y < 8; ++y, dst += BPS) { + const int val = left[y] - left[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); + _mm_storel_epi64((__m128i*)dst, out); + } + } else { + const __m128i top_values = _mm_load_si128((const __m128i*)top); + const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero); + const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero); + for (y = 0; y < 16; ++y, dst += BPS) { + const int val = left[y] - left[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out_0 = _mm_add_epi16(base, top_base_0); + const __m128i out_1 = _mm_add_epi16(base, top_base_1); + const __m128i out = _mm_packus_epi16(out_0, out_1); + _mm_store_si128((__m128i*)dst, out); + } + } +} + +static WEBP_INLINE void TrueMotion_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top, int size) { + if (left != NULL) { + if (top != NULL) { + TM_SSE2(dst, left, top, size); + } else { + HorizontalPred_SSE2(dst, left, size); + } + } else { + // true motion without left samples (hence: with default 129 value) + // is equivalent to VE prediction where you just copy the top samples. + // Note that if top samples are not available, the default value is + // then 129, and not 127 as in the VerticalPred case. + if (top != NULL) { + VerticalPred_SSE2(dst, top, size); + } else { + Fill_SSE2(dst, 129, size); + } + } +} + +static WEBP_INLINE void DC8uv_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + const __m128i left_values = _mm_loadl_epi64((const __m128i*)left); + const __m128i combined = _mm_unpacklo_epi64(top_values, left_values); + const int DC = VP8HorizontalAdd8b(&combined) + 8; + Put8x8uv_SSE2(DC >> 4, dst); +} + +static WEBP_INLINE void DC8uvNoLeft_SSE2(uint8_t* dst, const uint8_t* top) { + const __m128i zero = _mm_setzero_si128(); + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + const __m128i sum = _mm_sad_epu8(top_values, zero); + const int DC = _mm_cvtsi128_si32(sum) + 4; + Put8x8uv_SSE2(DC >> 3, dst); +} + +static WEBP_INLINE void DC8uvNoTop_SSE2(uint8_t* dst, const uint8_t* left) { + // 'left' is contiguous so we can reuse the top summation. + DC8uvNoLeft_SSE2(dst, left); +} + +static WEBP_INLINE void DC8uvNoTopLeft_SSE2(uint8_t* dst) { + Put8x8uv_SSE2(0x80, dst); +} + +static WEBP_INLINE void DC8uvMode_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + if (top != NULL) { + if (left != NULL) { // top and left present + DC8uv_SSE2(dst, left, top); + } else { // top, but no left + DC8uvNoLeft_SSE2(dst, top); + } + } else if (left != NULL) { // left but no top + DC8uvNoTop_SSE2(dst, left); + } else { // no top, no left, nothing. + DC8uvNoTopLeft_SSE2(dst); + } +} + +static WEBP_INLINE void DC16_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + const __m128i top_row = _mm_load_si128((const __m128i*)top); + const __m128i left_row = _mm_load_si128((const __m128i*)left); + const int DC = + VP8HorizontalAdd8b(&top_row) + VP8HorizontalAdd8b(&left_row) + 16; + Put16_SSE2(DC >> 5, dst); +} + +static WEBP_INLINE void DC16NoLeft_SSE2(uint8_t* dst, const uint8_t* top) { + const __m128i top_row = _mm_load_si128((const __m128i*)top); + const int DC = VP8HorizontalAdd8b(&top_row) + 8; + Put16_SSE2(DC >> 4, dst); +} + +static WEBP_INLINE void DC16NoTop_SSE2(uint8_t* dst, const uint8_t* left) { + // 'left' is contiguous so we can reuse the top summation. + DC16NoLeft_SSE2(dst, left); +} + +static WEBP_INLINE void DC16NoTopLeft_SSE2(uint8_t* dst) { + Put16_SSE2(0x80, dst); +} + +static WEBP_INLINE void DC16Mode_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + if (top != NULL) { + if (left != NULL) { // top and left present + DC16_SSE2(dst, left, top); + } else { // top, but no left + DC16NoLeft_SSE2(dst, top); + } + } else if (left != NULL) { // left but no top + DC16NoTop_SSE2(dst, left); + } else { // no top, no left, nothing. + DC16NoTopLeft_SSE2(dst); + } +} + +//------------------------------------------------------------------------------ +// 4x4 predictions + +#define DST(x, y) dst[(x) + (y) * BPS] +#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +// We use the following 8b-arithmetic tricks: +// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1 +// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1] +// and: +// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb +// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 +// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 + +static WEBP_INLINE void VE4_SSE2(uint8_t* dst, + const uint8_t* top) { // vertical + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(top - 1)); + const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); + const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); + const __m128i b = _mm_subs_epu8(a, lsb); + const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); + const int vals = _mm_cvtsi128_si32(avg); + int i; + for (i = 0; i < 4; ++i) { + WebPInt32ToMem(dst + i * BPS, vals); + } +} + +static WEBP_INLINE void HE4_SSE2(uint8_t* dst, + const uint8_t* top) { // horizontal + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); +} + +static WEBP_INLINE void DC4_SSE2(uint8_t* dst, const uint8_t* top) { + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; + Fill_SSE2(dst, dc >> 3, 4); +} + +static WEBP_INLINE void LD4_SSE2(uint8_t* dst, + const uint8_t* top) { // Down-Left + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); + const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); + const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, top[7], 3); + const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); +} + +static WEBP_INLINE void VR4_SSE2(uint8_t* dst, + const uint8_t* top) { // Vertical-Right + const __m128i one = _mm_set1_epi8(1); + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int X = top[-1]; + const __m128i XABCD = _mm_loadl_epi64((const __m128i*)(top - 1)); + const __m128i ABCD0 = _mm_srli_si128(XABCD, 1); + const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0); + const __m128i _XABCD = _mm_slli_si128(XABCD, 1); + const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0); + const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i efgh = _mm_avg_epu8(avg2, XABCD); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); + + // these two are hard to implement in SSE2, so we keep the C-version: + DST(0, 2) = AVG3(J, I, X); + DST(0, 3) = AVG3(K, J, I); +} + +static WEBP_INLINE void VL4_SSE2(uint8_t* dst, + const uint8_t* top) { // Vertical-Left + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); + const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2); + const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_); + const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_); + const __m128i avg3 = _mm_avg_epu8(avg1, avg2); + const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one); + const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_); + const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_); + const __m128i abbc = _mm_or_si128(ab, bc); + const __m128i lsb2 = _mm_and_si128(abbc, lsb1); + const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); + const uint32_t extra_out = + (uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); + + // these two are hard to get and irregular + DST(3, 2) = (extra_out >> 0) & 0xff; + DST(3, 3) = (extra_out >> 8) & 0xff; +} + +static WEBP_INLINE void RD4_SSE2(uint8_t* dst, + const uint8_t* top) { // Down-right + const __m128i one = _mm_set1_epi8(1); + const __m128i LKJIXABC = _mm_loadl_epi64((const __m128i*)(top - 5)); + const __m128i LKJIXABCD = _mm_insert_epi16(LKJIXABC, top[3], 4); + const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); + const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); + const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); +} + +static WEBP_INLINE void HU4_SSE2(uint8_t* dst, const uint8_t* top) { + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + DST(0, 0) = AVG2(I, J); + DST(2, 0) = DST(0, 1) = AVG2(J, K); + DST(2, 1) = DST(0, 2) = AVG2(K, L); + DST(1, 0) = AVG3(I, J, K); + DST(3, 0) = DST(1, 1) = AVG3(J, K, L); + DST(3, 1) = DST(1, 2) = AVG3(K, L, L); + DST(3, 2) = DST(2, 2) = + DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; +} + +static WEBP_INLINE void HD4_SSE2(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + + DST(0, 0) = DST(2, 1) = AVG2(I, X); + DST(0, 1) = DST(2, 2) = AVG2(J, I); + DST(0, 2) = DST(2, 3) = AVG2(K, J); + DST(0, 3) = AVG2(L, K); + + DST(3, 0) = AVG3(A, B, C); + DST(2, 0) = AVG3(X, A, B); + DST(1, 0) = DST(3, 1) = AVG3(I, X, A); + DST(1, 1) = DST(3, 2) = AVG3(J, I, X); + DST(1, 2) = DST(3, 3) = AVG3(K, J, I); + DST(1, 3) = AVG3(L, K, J); +} + +static WEBP_INLINE void TM4_SSE2(uint8_t* dst, const uint8_t* top) { + const __m128i zero = _mm_setzero_si128(); + const __m128i top_values = _mm_cvtsi32_si128(WebPMemToInt32(top)); + const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); + int y; + for (y = 0; y < 4; ++y, dst += BPS) { + const int val = top[-2 - y] - top[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); + WebPInt32ToMem(dst, _mm_cvtsi128_si32(out)); + } +} + +#undef DST +#undef AVG3 +#undef AVG2 + +//------------------------------------------------------------------------------ +// luma 4x4 prediction + +// Left samples are top[-5 .. -2], top_left is top[-1], top are +// located at top[0..3], and top right is top[4..7] +static void Intra4Preds_SSE2(uint8_t* dst, const uint8_t* top) { + DC4_SSE2(I4DC4 + dst, top); + TM4_SSE2(I4TM4 + dst, top); + VE4_SSE2(I4VE4 + dst, top); + HE4_SSE2(I4HE4 + dst, top); + RD4_SSE2(I4RD4 + dst, top); + VR4_SSE2(I4VR4 + dst, top); + LD4_SSE2(I4LD4 + dst, top); + VL4_SSE2(I4VL4 + dst, top); + HD4_SSE2(I4HD4 + dst, top); + HU4_SSE2(I4HU4 + dst, top); +} + +//------------------------------------------------------------------------------ +// Chroma 8x8 prediction (paragraph 12.2) + +static void IntraChromaPreds_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + // U block + DC8uvMode_SSE2(C8DC8 + dst, left, top); + VerticalPred_SSE2(C8VE8 + dst, top, 8); + HorizontalPred_SSE2(C8HE8 + dst, left, 8); + TrueMotion_SSE2(C8TM8 + dst, left, top, 8); + // V block + dst += 8; + if (top != NULL) top += 8; + if (left != NULL) left += 16; + DC8uvMode_SSE2(C8DC8 + dst, left, top); + VerticalPred_SSE2(C8VE8 + dst, top, 8); + HorizontalPred_SSE2(C8HE8 + dst, left, 8); + TrueMotion_SSE2(C8TM8 + dst, left, top, 8); +} + +//------------------------------------------------------------------------------ +// luma 16x16 prediction (paragraph 12.3) + +static void Intra16Preds_SSE2(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DC16Mode_SSE2(I16DC16 + dst, left, top); + VerticalPred_SSE2(I16VE16 + dst, top, 16); + HorizontalPred_SSE2(I16HE16 + dst, left, 16); + TrueMotion_SSE2(I16TM16 + dst, left, top, 16); +} + +//------------------------------------------------------------------------------ +// Metric + +static WEBP_INLINE void SubtractAndAccumulate_SSE2(const __m128i a, + const __m128i b, + __m128i* const sum) { + // take abs(a-b) in 8b + const __m128i a_b = _mm_subs_epu8(a, b); + const __m128i b_a = _mm_subs_epu8(b, a); + const __m128i abs_a_b = _mm_or_si128(a_b, b_a); + // zero-extend to 16b + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero); + const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero); + // multiply with self + const __m128i sum1 = _mm_madd_epi16(C0, C0); + const __m128i sum2 = _mm_madd_epi16(C1, C1); + *sum = _mm_add_epi32(sum1, sum2); +} + +static WEBP_INLINE int SSE_16xN_SSE2(const uint8_t* a, const uint8_t* b, + int num_pairs) { + __m128i sum = _mm_setzero_si128(); + int32_t tmp[4]; + int i; + + for (i = 0; i < num_pairs; ++i) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[BPS * 0]); + const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[BPS * 0]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[BPS * 1]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[BPS * 1]); + __m128i sum1, sum2; + SubtractAndAccumulate_SSE2(a0, b0, &sum1); + SubtractAndAccumulate_SSE2(a1, b1, &sum2); + sum = _mm_add_epi32(sum, _mm_add_epi32(sum1, sum2)); + a += 2 * BPS; + b += 2 * BPS; + } + _mm_storeu_si128((__m128i*)tmp, sum); + return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); +} + +static int SSE16x16_SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_16xN_SSE2(a, b, 8); +} + +static int SSE16x8_SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_16xN_SSE2(a, b, 4); +} + +#define LOAD_8x16b(ptr) \ + _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr)), zero) + +static int SSE8x8_SSE2(const uint8_t* a, const uint8_t* b) { + const __m128i zero = _mm_setzero_si128(); + int num_pairs = 4; + __m128i sum = zero; + int32_t tmp[4]; + while (num_pairs-- > 0) { + const __m128i a0 = LOAD_8x16b(&a[BPS * 0]); + const __m128i a1 = LOAD_8x16b(&a[BPS * 1]); + const __m128i b0 = LOAD_8x16b(&b[BPS * 0]); + const __m128i b1 = LOAD_8x16b(&b[BPS * 1]); + // subtract + const __m128i c0 = _mm_subs_epi16(a0, b0); + const __m128i c1 = _mm_subs_epi16(a1, b1); + // multiply/accumulate with self + const __m128i d0 = _mm_madd_epi16(c0, c0); + const __m128i d1 = _mm_madd_epi16(c1, c1); + // collect + const __m128i sum01 = _mm_add_epi32(d0, d1); + sum = _mm_add_epi32(sum, sum01); + a += 2 * BPS; + b += 2 * BPS; + } + _mm_storeu_si128((__m128i*)tmp, sum); + return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); +} +#undef LOAD_8x16b + +static int SSE4x4_SSE2(const uint8_t* a, const uint8_t* b) { + const __m128i zero = _mm_setzero_si128(); + + // Load values. Note that we read 8 pixels instead of 4, + // but the a/b buffers are over-allocated to that effect. + const __m128i a0 = _mm_loadl_epi64((const __m128i*)&a[BPS * 0]); + const __m128i a1 = _mm_loadl_epi64((const __m128i*)&a[BPS * 1]); + const __m128i a2 = _mm_loadl_epi64((const __m128i*)&a[BPS * 2]); + const __m128i a3 = _mm_loadl_epi64((const __m128i*)&a[BPS * 3]); + const __m128i b0 = _mm_loadl_epi64((const __m128i*)&b[BPS * 0]); + const __m128i b1 = _mm_loadl_epi64((const __m128i*)&b[BPS * 1]); + const __m128i b2 = _mm_loadl_epi64((const __m128i*)&b[BPS * 2]); + const __m128i b3 = _mm_loadl_epi64((const __m128i*)&b[BPS * 3]); + // Combine pair of lines. + const __m128i a01 = _mm_unpacklo_epi32(a0, a1); + const __m128i a23 = _mm_unpacklo_epi32(a2, a3); + const __m128i b01 = _mm_unpacklo_epi32(b0, b1); + const __m128i b23 = _mm_unpacklo_epi32(b2, b3); + // Convert to 16b. + const __m128i a01s = _mm_unpacklo_epi8(a01, zero); + const __m128i a23s = _mm_unpacklo_epi8(a23, zero); + const __m128i b01s = _mm_unpacklo_epi8(b01, zero); + const __m128i b23s = _mm_unpacklo_epi8(b23, zero); + // subtract, square and accumulate + const __m128i d0 = _mm_subs_epi16(a01s, b01s); + const __m128i d1 = _mm_subs_epi16(a23s, b23s); + const __m128i e0 = _mm_madd_epi16(d0, d0); + const __m128i e1 = _mm_madd_epi16(d1, d1); + const __m128i sum = _mm_add_epi32(e0, e1); + + int32_t tmp[4]; + _mm_storeu_si128((__m128i*)tmp, sum); + return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); +} + +//------------------------------------------------------------------------------ + +static void Mean16x4_SSE2(const uint8_t* ref, uint32_t dc[4]) { + const __m128i mask = _mm_set1_epi16(0x00ff); + const __m128i a0 = _mm_loadu_si128((const __m128i*)&ref[BPS * 0]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&ref[BPS * 1]); + const __m128i a2 = _mm_loadu_si128((const __m128i*)&ref[BPS * 2]); + const __m128i a3 = _mm_loadu_si128((const __m128i*)&ref[BPS * 3]); + const __m128i b0 = _mm_srli_epi16(a0, 8); // hi byte + const __m128i b1 = _mm_srli_epi16(a1, 8); + const __m128i b2 = _mm_srli_epi16(a2, 8); + const __m128i b3 = _mm_srli_epi16(a3, 8); + const __m128i c0 = _mm_and_si128(a0, mask); // lo byte + const __m128i c1 = _mm_and_si128(a1, mask); + const __m128i c2 = _mm_and_si128(a2, mask); + const __m128i c3 = _mm_and_si128(a3, mask); + const __m128i d0 = _mm_add_epi32(b0, c0); + const __m128i d1 = _mm_add_epi32(b1, c1); + const __m128i d2 = _mm_add_epi32(b2, c2); + const __m128i d3 = _mm_add_epi32(b3, c3); + const __m128i e0 = _mm_add_epi32(d0, d1); + const __m128i e1 = _mm_add_epi32(d2, d3); + const __m128i f0 = _mm_add_epi32(e0, e1); + uint16_t tmp[8]; + _mm_storeu_si128((__m128i*)tmp, f0); + dc[0] = tmp[0] + tmp[1]; + dc[1] = tmp[2] + tmp[3]; + dc[2] = tmp[4] + tmp[5]; + dc[3] = tmp[6] + tmp[7]; +} + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +static int TTransform_SSE2(const uint8_t* inA, const uint8_t* inB, + const uint16_t* const w) { + int32_t sum[4]; + __m128i tmp_0, tmp_1, tmp_2, tmp_3; + const __m128i zero = _mm_setzero_si128(); + + // Load and combine inputs. + { + const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]); + const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]); + const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]); + const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]); + const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]); + const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]); + const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]); + const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]); + + // Combine inA and inB (we'll do two transforms in parallel). + const __m128i inAB_0 = _mm_unpacklo_epi32(inA_0, inB_0); + const __m128i inAB_1 = _mm_unpacklo_epi32(inA_1, inB_1); + const __m128i inAB_2 = _mm_unpacklo_epi32(inA_2, inB_2); + const __m128i inAB_3 = _mm_unpacklo_epi32(inA_3, inB_3); + tmp_0 = _mm_unpacklo_epi8(inAB_0, zero); + tmp_1 = _mm_unpacklo_epi8(inAB_1, zero); + tmp_2 = _mm_unpacklo_epi8(inAB_2, zero); + tmp_3 = _mm_unpacklo_epi8(inAB_3, zero); + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + } + + // Vertical pass first to avoid a transpose (vertical and horizontal passes + // are commutative because w/kWeightY is symmetric) and subsequent transpose. + { + // Calculate a and b (two 4x4 at once). + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); + const __m128i b1 = _mm_add_epi16(a3, a2); + const __m128i b2 = _mm_sub_epi16(a3, a2); + const __m128i b3 = _mm_sub_epi16(a0, a1); + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&b0, &b1, &b2, &b3, &tmp_0, &tmp_1, &tmp_2, &tmp_3); + } + + // Horizontal pass and difference of weighted sums. + { + // Load all inputs. + const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]); + const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]); + + // Calculate a and b (two 4x4 at once). + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); + const __m128i b1 = _mm_add_epi16(a3, a2); + const __m128i b2 = _mm_sub_epi16(a3, a2); + const __m128i b3 = _mm_sub_epi16(a0, a1); + + // Separate the transforms of inA and inB. + __m128i A_b0 = _mm_unpacklo_epi64(b0, b1); + __m128i A_b2 = _mm_unpacklo_epi64(b2, b3); + __m128i B_b0 = _mm_unpackhi_epi64(b0, b1); + __m128i B_b2 = _mm_unpackhi_epi64(b2, b3); + + { + const __m128i d0 = _mm_sub_epi16(zero, A_b0); + const __m128i d1 = _mm_sub_epi16(zero, A_b2); + const __m128i d2 = _mm_sub_epi16(zero, B_b0); + const __m128i d3 = _mm_sub_epi16(zero, B_b2); + A_b0 = _mm_max_epi16(A_b0, d0); // abs(v), 16b + A_b2 = _mm_max_epi16(A_b2, d1); + B_b0 = _mm_max_epi16(B_b0, d2); + B_b2 = _mm_max_epi16(B_b2, d3); + } + + // weighted sums + A_b0 = _mm_madd_epi16(A_b0, w_0); + A_b2 = _mm_madd_epi16(A_b2, w_8); + B_b0 = _mm_madd_epi16(B_b0, w_0); + B_b2 = _mm_madd_epi16(B_b2, w_8); + A_b0 = _mm_add_epi32(A_b0, A_b2); + B_b0 = _mm_add_epi32(B_b0, B_b2); + + // difference of weighted sums + A_b0 = _mm_sub_epi32(A_b0, B_b0); + _mm_storeu_si128((__m128i*)&sum[0], A_b0); + } + return sum[0] + sum[1] + sum[2] + sum[3]; +} + +static int Disto4x4_SSE2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int diff_sum = TTransform_SSE2(a, b, w); + return abs(diff_sum) >> 5; +} + +static int Disto16x16_SSE2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_SSE2(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ +// Quantization +// + +static WEBP_INLINE int DoQuantizeBlock_SSE2(int16_t in[16], int16_t out[16], + const uint16_t* const sharpen, + const VP8Matrix* const mtx) { + const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); + const __m128i zero = _mm_setzero_si128(); + __m128i coeff0, coeff8; + __m128i out0, out8; + __m128i packed_out; + + // Load all inputs. + __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); + __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); + const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]); + const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]); + const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]); + const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]); + + // extract sign(in) (0x0000 if positive, 0xffff if negative) + const __m128i sign0 = _mm_cmpgt_epi16(zero, in0); + const __m128i sign8 = _mm_cmpgt_epi16(zero, in8); + + // coeff = abs(in) = (in ^ sign) - sign + coeff0 = _mm_xor_si128(in0, sign0); + coeff8 = _mm_xor_si128(in8, sign8); + coeff0 = _mm_sub_epi16(coeff0, sign0); + coeff8 = _mm_sub_epi16(coeff8, sign8); + + // coeff = abs(in) + sharpen + if (sharpen != NULL) { + const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]); + const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]); + coeff0 = _mm_add_epi16(coeff0, sharpen0); + coeff8 = _mm_add_epi16(coeff8, sharpen8); + } + + // out = (coeff * iQ + B) >> QFIX + { + // doing calculations with 32b precision (QFIX=17) + // out = (coeff * iQ) + const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0); + const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0); + const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8); + const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8); + __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H); + __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H); + __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H); + __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H); + // out = (coeff * iQ + B) + const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]); + const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]); + const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]); + const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]); + out_00 = _mm_add_epi32(out_00, bias_00); + out_04 = _mm_add_epi32(out_04, bias_04); + out_08 = _mm_add_epi32(out_08, bias_08); + out_12 = _mm_add_epi32(out_12, bias_12); + // out = QUANTDIV(coeff, iQ, B, QFIX) + out_00 = _mm_srai_epi32(out_00, QFIX); + out_04 = _mm_srai_epi32(out_04, QFIX); + out_08 = _mm_srai_epi32(out_08, QFIX); + out_12 = _mm_srai_epi32(out_12, QFIX); + + // pack result as 16b + out0 = _mm_packs_epi32(out_00, out_04); + out8 = _mm_packs_epi32(out_08, out_12); + + // if (coeff > 2047) coeff = 2047 + out0 = _mm_min_epi16(out0, max_coeff_2047); + out8 = _mm_min_epi16(out8, max_coeff_2047); + } + + // get sign back (if (sign[j]) out_n = -out_n) + out0 = _mm_xor_si128(out0, sign0); + out8 = _mm_xor_si128(out8, sign8); + out0 = _mm_sub_epi16(out0, sign0); + out8 = _mm_sub_epi16(out8, sign8); + + // in = out * Q + in0 = _mm_mullo_epi16(out0, q0); + in8 = _mm_mullo_epi16(out8, q8); + + _mm_storeu_si128((__m128i*)&in[0], in0); + _mm_storeu_si128((__m128i*)&in[8], in8); + + // zigzag the output before storing it. + // + // The zigzag pattern can almost be reproduced with a small sequence of + // shuffles. After it, we only need to swap the 7th (ending up in third + // position instead of twelfth) and 8th values. + { + __m128i outZ0, outZ8; + outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0)); + outZ0 = _mm_shuffle_epi32 (outZ0, _MM_SHUFFLE(3, 1, 2, 0)); + outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2)); + outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1)); + outZ8 = _mm_shuffle_epi32 (outZ8, _MM_SHUFFLE(3, 1, 2, 0)); + outZ8 = _mm_shufflelo_epi16(outZ8, _MM_SHUFFLE(1, 3, 2, 0)); + _mm_storeu_si128((__m128i*)&out[0], outZ0); + _mm_storeu_si128((__m128i*)&out[8], outZ8); + packed_out = _mm_packs_epi16(outZ0, outZ8); + } + { + const int16_t outZ_12 = out[12]; + const int16_t outZ_3 = out[3]; + out[3] = outZ_12; + out[12] = outZ_3; + } + + // detect if all 'out' values are zeroes or not + return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); +} + +static int QuantizeBlock_SSE2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE2(in, out, &mtx->sharpen_[0], mtx); +} + +static int QuantizeBlockWHT_SSE2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE2(in, out, NULL, mtx); +} + +static int Quantize2Blocks_SSE2(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + const uint16_t* const sharpen = &mtx->sharpen_[0]; + nz = DoQuantizeBlock_SSE2(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; + nz |= DoQuantizeBlock_SSE2(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; + return nz; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE2(void) { + VP8CollectHistogram = CollectHistogram_SSE2; + VP8EncPredLuma16 = Intra16Preds_SSE2; + VP8EncPredChroma8 = IntraChromaPreds_SSE2; + VP8EncPredLuma4 = Intra4Preds_SSE2; + VP8EncQuantizeBlock = QuantizeBlock_SSE2; + VP8EncQuantize2Blocks = Quantize2Blocks_SSE2; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT_SSE2; + VP8ITransform = ITransform_SSE2; + VP8FTransform = FTransform_SSE2; + VP8FTransform2 = FTransform2_SSE2; + VP8FTransformWHT = FTransformWHT_SSE2; + VP8SSE16x16 = SSE16x16_SSE2; + VP8SSE16x8 = SSE16x8_SSE2; + VP8SSE8x8 = SSE8x8_SSE2; + VP8SSE4x4 = SSE4x4_SSE2; + VP8TDisto4x4 = Disto4x4_SSE2; + VP8TDisto16x16 = Disto16x16_SSE2; + VP8Mean16x4 = Mean16x4_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8EncDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/enc_sse41.c b/libraries/webp/src/dsp/enc_sse41.c new file mode 100644 index 0000000000..924035a644 --- /dev/null +++ b/libraries/webp/src/dsp/enc_sse41.c @@ -0,0 +1,339 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE4 version of some encoding functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) +#include +#include // for abs() + +#include "src/dsp/common_sse2.h" +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms. + +static void CollectHistogram_SSE41(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + int k; + + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + + // Convert coefficients to bin (within out[]). + { + // Load. + const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]); + const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]); + // v = abs(out) >> 3 + const __m128i abs0 = _mm_abs_epi16(out0); + const __m128i abs1 = _mm_abs_epi16(out1); + const __m128i v0 = _mm_srai_epi16(abs0, 3); + const __m128i v1 = _mm_srai_epi16(abs1, 3); + // bin = min(v, MAX_COEFF_THRESH) + const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); + const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); + // Store. + _mm_storeu_si128((__m128i*)&out[0], bin0); + _mm_storeu_si128((__m128i*)&out[8], bin1); + } + + // Convert coefficients to bin. + for (k = 0; k < 16; ++k) { + ++distribution[out[k]]; + } + } + VP8SetHistogramData(distribution, histo); +} + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +static int TTransform_SSE41(const uint8_t* inA, const uint8_t* inB, + const uint16_t* const w) { + int32_t sum[4]; + __m128i tmp_0, tmp_1, tmp_2, tmp_3; + + // Load and combine inputs. + { + const __m128i inA_0 = _mm_loadu_si128((const __m128i*)&inA[BPS * 0]); + const __m128i inA_1 = _mm_loadu_si128((const __m128i*)&inA[BPS * 1]); + const __m128i inA_2 = _mm_loadu_si128((const __m128i*)&inA[BPS * 2]); + // In SSE4.1, with gcc 4.8 at least (maybe other versions), + // _mm_loadu_si128 is faster than _mm_loadl_epi64. But for the last lump + // of inA and inB, _mm_loadl_epi64 is still used not to have an out of + // bound read. + const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]); + const __m128i inB_0 = _mm_loadu_si128((const __m128i*)&inB[BPS * 0]); + const __m128i inB_1 = _mm_loadu_si128((const __m128i*)&inB[BPS * 1]); + const __m128i inB_2 = _mm_loadu_si128((const __m128i*)&inB[BPS * 2]); + const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]); + + // Combine inA and inB (we'll do two transforms in parallel). + const __m128i inAB_0 = _mm_unpacklo_epi32(inA_0, inB_0); + const __m128i inAB_1 = _mm_unpacklo_epi32(inA_1, inB_1); + const __m128i inAB_2 = _mm_unpacklo_epi32(inA_2, inB_2); + const __m128i inAB_3 = _mm_unpacklo_epi32(inA_3, inB_3); + tmp_0 = _mm_cvtepu8_epi16(inAB_0); + tmp_1 = _mm_cvtepu8_epi16(inAB_1); + tmp_2 = _mm_cvtepu8_epi16(inAB_2); + tmp_3 = _mm_cvtepu8_epi16(inAB_3); + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + } + + // Vertical pass first to avoid a transpose (vertical and horizontal passes + // are commutative because w/kWeightY is symmetric) and subsequent transpose. + { + // Calculate a and b (two 4x4 at once). + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); + const __m128i b1 = _mm_add_epi16(a3, a2); + const __m128i b2 = _mm_sub_epi16(a3, a2); + const __m128i b3 = _mm_sub_epi16(a0, a1); + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&b0, &b1, &b2, &b3, &tmp_0, &tmp_1, &tmp_2, &tmp_3); + } + + // Horizontal pass and difference of weighted sums. + { + // Load all inputs. + const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]); + const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]); + + // Calculate a and b (two 4x4 at once). + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); + const __m128i b1 = _mm_add_epi16(a3, a2); + const __m128i b2 = _mm_sub_epi16(a3, a2); + const __m128i b3 = _mm_sub_epi16(a0, a1); + + // Separate the transforms of inA and inB. + __m128i A_b0 = _mm_unpacklo_epi64(b0, b1); + __m128i A_b2 = _mm_unpacklo_epi64(b2, b3); + __m128i B_b0 = _mm_unpackhi_epi64(b0, b1); + __m128i B_b2 = _mm_unpackhi_epi64(b2, b3); + + A_b0 = _mm_abs_epi16(A_b0); + A_b2 = _mm_abs_epi16(A_b2); + B_b0 = _mm_abs_epi16(B_b0); + B_b2 = _mm_abs_epi16(B_b2); + + // weighted sums + A_b0 = _mm_madd_epi16(A_b0, w_0); + A_b2 = _mm_madd_epi16(A_b2, w_8); + B_b0 = _mm_madd_epi16(B_b0, w_0); + B_b2 = _mm_madd_epi16(B_b2, w_8); + A_b0 = _mm_add_epi32(A_b0, A_b2); + B_b0 = _mm_add_epi32(B_b0, B_b2); + + // difference of weighted sums + A_b2 = _mm_sub_epi32(A_b0, B_b0); + _mm_storeu_si128((__m128i*)&sum[0], A_b2); + } + return sum[0] + sum[1] + sum[2] + sum[3]; +} + +static int Disto4x4_SSE41(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int diff_sum = TTransform_SSE41(a, b, w); + return abs(diff_sum) >> 5; +} + +static int Disto16x16_SSE41(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_SSE41(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ +// Quantization +// + +// Generates a pshufb constant for shuffling 16b words. +#define PSHUFB_CST(A,B,C,D,E,F,G,H) \ + _mm_set_epi8(2 * (H) + 1, 2 * (H) + 0, 2 * (G) + 1, 2 * (G) + 0, \ + 2 * (F) + 1, 2 * (F) + 0, 2 * (E) + 1, 2 * (E) + 0, \ + 2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \ + 2 * (B) + 1, 2 * (B) + 0, 2 * (A) + 1, 2 * (A) + 0) + +static WEBP_INLINE int DoQuantizeBlock_SSE41(int16_t in[16], int16_t out[16], + const uint16_t* const sharpen, + const VP8Matrix* const mtx) { + const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); + const __m128i zero = _mm_setzero_si128(); + __m128i out0, out8; + __m128i packed_out; + + // Load all inputs. + __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); + __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); + const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]); + const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]); + const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]); + const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]); + + // coeff = abs(in) + __m128i coeff0 = _mm_abs_epi16(in0); + __m128i coeff8 = _mm_abs_epi16(in8); + + // coeff = abs(in) + sharpen + if (sharpen != NULL) { + const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]); + const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]); + coeff0 = _mm_add_epi16(coeff0, sharpen0); + coeff8 = _mm_add_epi16(coeff8, sharpen8); + } + + // out = (coeff * iQ + B) >> QFIX + { + // doing calculations with 32b precision (QFIX=17) + // out = (coeff * iQ) + const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0); + const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0); + const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8); + const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8); + __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H); + __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H); + __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H); + __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H); + // out = (coeff * iQ + B) + const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]); + const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]); + const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]); + const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]); + out_00 = _mm_add_epi32(out_00, bias_00); + out_04 = _mm_add_epi32(out_04, bias_04); + out_08 = _mm_add_epi32(out_08, bias_08); + out_12 = _mm_add_epi32(out_12, bias_12); + // out = QUANTDIV(coeff, iQ, B, QFIX) + out_00 = _mm_srai_epi32(out_00, QFIX); + out_04 = _mm_srai_epi32(out_04, QFIX); + out_08 = _mm_srai_epi32(out_08, QFIX); + out_12 = _mm_srai_epi32(out_12, QFIX); + + // pack result as 16b + out0 = _mm_packs_epi32(out_00, out_04); + out8 = _mm_packs_epi32(out_08, out_12); + + // if (coeff > 2047) coeff = 2047 + out0 = _mm_min_epi16(out0, max_coeff_2047); + out8 = _mm_min_epi16(out8, max_coeff_2047); + } + + // put sign back + out0 = _mm_sign_epi16(out0, in0); + out8 = _mm_sign_epi16(out8, in8); + + // in = out * Q + in0 = _mm_mullo_epi16(out0, q0); + in8 = _mm_mullo_epi16(out8, q8); + + _mm_storeu_si128((__m128i*)&in[0], in0); + _mm_storeu_si128((__m128i*)&in[8], in8); + + // zigzag the output before storing it. The re-ordering is: + // 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 + // -> 0 1 4[8]5 2 3 6 | 9 12 13 10 [7]11 14 15 + // There's only two misplaced entries ([8] and [7]) that are crossing the + // reg's boundaries. + // We use pshufb instead of pshuflo/pshufhi. + { + const __m128i kCst_lo = PSHUFB_CST(0, 1, 4, -1, 5, 2, 3, 6); + const __m128i kCst_7 = PSHUFB_CST(-1, -1, -1, -1, 7, -1, -1, -1); + const __m128i tmp_lo = _mm_shuffle_epi8(out0, kCst_lo); + const __m128i tmp_7 = _mm_shuffle_epi8(out0, kCst_7); // extract #7 + const __m128i kCst_hi = PSHUFB_CST(1, 4, 5, 2, -1, 3, 6, 7); + const __m128i kCst_8 = PSHUFB_CST(-1, -1, -1, 0, -1, -1, -1, -1); + const __m128i tmp_hi = _mm_shuffle_epi8(out8, kCst_hi); + const __m128i tmp_8 = _mm_shuffle_epi8(out8, kCst_8); // extract #8 + const __m128i out_z0 = _mm_or_si128(tmp_lo, tmp_8); + const __m128i out_z8 = _mm_or_si128(tmp_hi, tmp_7); + _mm_storeu_si128((__m128i*)&out[0], out_z0); + _mm_storeu_si128((__m128i*)&out[8], out_z8); + packed_out = _mm_packs_epi16(out_z0, out_z8); + } + + // detect if all 'out' values are zeroes or not + return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); +} + +#undef PSHUFB_CST + +static int QuantizeBlock_SSE41(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE41(in, out, &mtx->sharpen_[0], mtx); +} + +static int QuantizeBlockWHT_SSE41(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE41(in, out, NULL, mtx); +} + +static int Quantize2Blocks_SSE41(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + const uint16_t* const sharpen = &mtx->sharpen_[0]; + nz = DoQuantizeBlock_SSE41(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; + nz |= DoQuantizeBlock_SSE41(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; + return nz; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitSSE41(void); +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE41(void) { + VP8CollectHistogram = CollectHistogram_SSE41; + VP8EncQuantizeBlock = QuantizeBlock_SSE41; + VP8EncQuantize2Blocks = Quantize2Blocks_SSE41; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT_SSE41; + VP8TDisto4x4 = Disto4x4_SSE41; + VP8TDisto16x16 = Disto16x16_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(VP8EncDspInitSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/libraries/webp/src/dsp/filters.c b/libraries/webp/src/dsp/filters.c new file mode 100644 index 0000000000..c9232ff16a --- /dev/null +++ b/libraries/webp/src/dsp/filters.c @@ -0,0 +1,297 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Spatial prediction using various filters +// +// Author: Urvang (urvang@google.com) + +#include "src/dsp/dsp.h" +#include +#include +#include + +//------------------------------------------------------------------------------ +// Helpful macro. + +#define DCHECK(in, out) \ + do { \ + assert((in) != NULL); \ + assert((out) != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE void PredictLine_C(const uint8_t* src, const uint8_t* pred, + uint8_t* dst, int length, int inverse) { + int i; + if (inverse) { + for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] + pred[i]); + } else { + for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] - pred[i]); + } +} + +//------------------------------------------------------------------------------ +// Horizontal filter. + +static WEBP_INLINE void DoHorizontalFilter_C(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + int inverse, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + preds = inverse ? out : in; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + // Leftmost pixel is predicted from above. + PredictLine_C(in, preds - stride, out, 1, inverse); + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +static WEBP_INLINE void DoVerticalFilter_C(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + int inverse, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + preds = inverse ? out : in; + + if (row == 0) { + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + row = 1; + in += stride; + out += stride; + } else { + // We are starting from in-between. Make sure 'preds' points to prev row. + preds -= stride; + } + + // Filter line-by-line. + while (row < last_row) { + PredictLine_C(in, preds, out, width, inverse); + ++row; + preds += stride; + in += stride; + out += stride; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// Gradient filter. + +static WEBP_INLINE int GradientPredictor_C(uint8_t a, uint8_t b, uint8_t c) { + const int g = a + b - c; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit +} + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + int inverse, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + preds = inverse ? out : in; + + // left prediction for top scan-line + if (row == 0) { + out[0] = in[0]; + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + int w; + // leftmost pixel: predict from above. + PredictLine_C(in, preds - stride, out, 1, inverse); + for (w = 1; w < width; ++w) { + const int pred = GradientPredictor_C(preds[w - 1], + preds[w - stride], + preds[w - stride - 1]); + out[w] = (uint8_t)(in[w] + (inverse ? pred : -pred)); + } + ++row; + preds += stride; + in += stride; + out += stride; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#undef DCHECK + +//------------------------------------------------------------------------------ + +#if !WEBP_NEON_OMIT_C_CODE +static void HorizontalFilter_C(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_C(data, width, height, stride, 0, height, 0, + filtered_data); +} + +static void VerticalFilter_C(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_C(data, width, height, stride, 0, height, 0, filtered_data); +} + +static void GradientFilter_C(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_C(data, width, height, stride, 0, height, 0, filtered_data); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ + +static void NoneUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + (void)prev; + if (out != in) memcpy(out, in, width * sizeof(*out)); +} + +static void HorizontalUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + uint8_t pred = (prev == NULL) ? 0 : prev[0]; + int i; + for (i = 0; i < width; ++i) { + out[i] = (uint8_t)(pred + in[i]); + pred = out[i]; + } +} + +#if !WEBP_NEON_OMIT_C_CODE +static void VerticalUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_C(NULL, in, out, width); + } else { + int i; + for (i = 0; i < width; ++i) out[i] = (uint8_t)(prev[i] + in[i]); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void GradientUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_C(NULL, in, out, width); + } else { + uint8_t top = prev[0], top_left = top, left = top; + int i; + for (i = 0; i < width; ++i) { + top = prev[i]; // need to read this first, in case prev==out + left = (uint8_t)(in[i] + GradientPredictor_C(left, top, top_left)); + top_left = top; + out[i] = left; + } + } +} + +//------------------------------------------------------------------------------ +// Init function + +WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; +WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8FiltersInitMIPSdspR2(void); +extern void VP8FiltersInitMSA(void); +extern void VP8FiltersInitNEON(void); +extern void VP8FiltersInitSSE2(void); + +WEBP_DSP_INIT_FUNC(VP8FiltersInit) { + WebPUnfilters[WEBP_FILTER_NONE] = NoneUnfilter_C; +#if !WEBP_NEON_OMIT_C_CODE + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_C; +#endif + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_C; + + WebPFilters[WEBP_FILTER_NONE] = NULL; +#if !WEBP_NEON_OMIT_C_CODE + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_C; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_C; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_C; +#endif + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8FiltersInitSSE2(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8FiltersInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8FiltersInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8FiltersInitNEON(); + } +#endif + + assert(WebPUnfilters[WEBP_FILTER_NONE] != NULL); + assert(WebPUnfilters[WEBP_FILTER_HORIZONTAL] != NULL); + assert(WebPUnfilters[WEBP_FILTER_VERTICAL] != NULL); + assert(WebPUnfilters[WEBP_FILTER_GRADIENT] != NULL); + assert(WebPFilters[WEBP_FILTER_HORIZONTAL] != NULL); + assert(WebPFilters[WEBP_FILTER_VERTICAL] != NULL); + assert(WebPFilters[WEBP_FILTER_GRADIENT] != NULL); +} diff --git a/libraries/webp/src/dsp/filters_mips_dsp_r2.c b/libraries/webp/src/dsp/filters_mips_dsp_r2.c new file mode 100644 index 0000000000..eca866f578 --- /dev/null +++ b/libraries/webp/src/dsp/filters_mips_dsp_r2.c @@ -0,0 +1,404 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Spatial prediction using various filters +// +// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) +// Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/dsp.h" +#include +#include +#include + +//------------------------------------------------------------------------------ +// Helpful macro. + +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) + +#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \ + const uint8_t* psrc = (uint8_t*)(SRC); \ + uint8_t* pdst = (uint8_t*)(DST); \ + const int ilength = (int)(LENGTH); \ + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; \ + __asm__ volatile ( \ + ".set push \n\t" \ + ".set noreorder \n\t" \ + "srl %[temp0], %[length], 2 \n\t" \ + "beqz %[temp0], 4f \n\t" \ + " andi %[temp6], %[length], 3 \n\t" \ + ".if " #INVERSE " \n\t" \ + "1: \n\t" \ + "lbu %[temp1], -1(%[dst]) \n\t" \ + "lbu %[temp2], 0(%[src]) \n\t" \ + "lbu %[temp3], 1(%[src]) \n\t" \ + "lbu %[temp4], 2(%[src]) \n\t" \ + "lbu %[temp5], 3(%[src]) \n\t" \ + "addu %[temp1], %[temp1], %[temp2] \n\t" \ + "addu %[temp2], %[temp1], %[temp3] \n\t" \ + "addu %[temp3], %[temp2], %[temp4] \n\t" \ + "addu %[temp4], %[temp3], %[temp5] \n\t" \ + "sb %[temp1], 0(%[dst]) \n\t" \ + "sb %[temp2], 1(%[dst]) \n\t" \ + "sb %[temp3], 2(%[dst]) \n\t" \ + "sb %[temp4], 3(%[dst]) \n\t" \ + "addiu %[src], %[src], 4 \n\t" \ + "addiu %[temp0], %[temp0], -1 \n\t" \ + "bnez %[temp0], 1b \n\t" \ + " addiu %[dst], %[dst], 4 \n\t" \ + ".else \n\t" \ + "1: \n\t" \ + "ulw %[temp1], -1(%[src]) \n\t" \ + "ulw %[temp2], 0(%[src]) \n\t" \ + "addiu %[src], %[src], 4 \n\t" \ + "addiu %[temp0], %[temp0], -1 \n\t" \ + "subu.qb %[temp3], %[temp2], %[temp1] \n\t" \ + "usw %[temp3], 0(%[dst]) \n\t" \ + "bnez %[temp0], 1b \n\t" \ + " addiu %[dst], %[dst], 4 \n\t" \ + ".endif \n\t" \ + "4: \n\t" \ + "beqz %[temp6], 3f \n\t" \ + " nop \n\t" \ + "2: \n\t" \ + "lbu %[temp2], 0(%[src]) \n\t" \ + ".if " #INVERSE " \n\t" \ + "lbu %[temp1], -1(%[dst]) \n\t" \ + "addu %[temp3], %[temp1], %[temp2] \n\t" \ + ".else \n\t" \ + "lbu %[temp1], -1(%[src]) \n\t" \ + "subu %[temp3], %[temp1], %[temp2] \n\t" \ + ".endif \n\t" \ + "addiu %[src], %[src], 1 \n\t" \ + "sb %[temp3], 0(%[dst]) \n\t" \ + "addiu %[temp6], %[temp6], -1 \n\t" \ + "bnez %[temp6], 2b \n\t" \ + " addiu %[dst], %[dst], 1 \n\t" \ + "3: \n\t" \ + ".set pop \n\t" \ + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ + [temp6]"=&r"(temp6), [dst]"+&r"(pdst), [src]"+&r"(psrc) \ + : [length]"r"(ilength) \ + : "memory" \ + ); \ + } while (0) + +static WEBP_INLINE void PredictLine_MIPSdspR2(const uint8_t* src, uint8_t* dst, + int length) { + DO_PREDICT_LINE(src, dst, length, 0); +} + +#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) do { \ + const uint8_t* psrc = (uint8_t*)(SRC); \ + const uint8_t* ppred = (uint8_t*)(PRED); \ + uint8_t* pdst = (uint8_t*)(DST); \ + const int ilength = (int)(LENGTH); \ + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \ + __asm__ volatile ( \ + ".set push \n\t" \ + ".set noreorder \n\t" \ + "srl %[temp0], %[length], 0x3 \n\t" \ + "beqz %[temp0], 4f \n\t" \ + " andi %[temp7], %[length], 0x7 \n\t" \ + "1: \n\t" \ + "ulw %[temp1], 0(%[src]) \n\t" \ + "ulw %[temp2], 0(%[pred]) \n\t" \ + "ulw %[temp3], 4(%[src]) \n\t" \ + "ulw %[temp4], 4(%[pred]) \n\t" \ + "addiu %[src], %[src], 8 \n\t" \ + ".if " #INVERSE " \n\t" \ + "addu.qb %[temp5], %[temp1], %[temp2] \n\t" \ + "addu.qb %[temp6], %[temp3], %[temp4] \n\t" \ + ".else \n\t" \ + "subu.qb %[temp5], %[temp1], %[temp2] \n\t" \ + "subu.qb %[temp6], %[temp3], %[temp4] \n\t" \ + ".endif \n\t" \ + "addiu %[pred], %[pred], 8 \n\t" \ + "usw %[temp5], 0(%[dst]) \n\t" \ + "usw %[temp6], 4(%[dst]) \n\t" \ + "addiu %[temp0], %[temp0], -1 \n\t" \ + "bnez %[temp0], 1b \n\t" \ + " addiu %[dst], %[dst], 8 \n\t" \ + "4: \n\t" \ + "beqz %[temp7], 3f \n\t" \ + " nop \n\t" \ + "2: \n\t" \ + "lbu %[temp1], 0(%[src]) \n\t" \ + "lbu %[temp2], 0(%[pred]) \n\t" \ + "addiu %[src], %[src], 1 \n\t" \ + "addiu %[pred], %[pred], 1 \n\t" \ + ".if " #INVERSE " \n\t" \ + "addu %[temp3], %[temp1], %[temp2] \n\t" \ + ".else \n\t" \ + "subu %[temp3], %[temp1], %[temp2] \n\t" \ + ".endif \n\t" \ + "sb %[temp3], 0(%[dst]) \n\t" \ + "addiu %[temp7], %[temp7], -1 \n\t" \ + "bnez %[temp7], 2b \n\t" \ + " addiu %[dst], %[dst], 1 \n\t" \ + "3: \n\t" \ + ".set pop \n\t" \ + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [pred]"+&r"(ppred), \ + [dst]"+&r"(pdst), [src]"+&r"(psrc) \ + : [length]"r"(ilength) \ + : "memory" \ + ); \ + } while (0) + +#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST) do { \ + int temp1, temp2, temp3; \ + __asm__ volatile ( \ + "lbu %[temp1], 0(%[src]) \n\t" \ + "lbu %[temp2], 0(%[pred]) \n\t" \ + "subu %[temp3], %[temp1], %[temp2] \n\t" \ + "sb %[temp3], 0(%[dst]) \n\t" \ + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ + : [pred]"r"((PRED)), [dst]"r"((DST)), [src]"r"((SRC)) \ + : "memory" \ + ); \ + } while (0) + +//------------------------------------------------------------------------------ +// Horizontal filter. + +#define FILTER_LINE_BY_LINE do { \ + while (row < last_row) { \ + PREDICT_LINE_ONE_PASS(in, preds - stride, out); \ + DO_PREDICT_LINE(in + 1, out + 1, width - 1, 0); \ + ++row; \ + preds += stride; \ + in += stride; \ + out += stride; \ + } \ + } while (0) + +static WEBP_INLINE void DoHorizontalFilter_MIPSdspR2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + preds = in; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + FILTER_LINE_BY_LINE; +} +#undef FILTER_LINE_BY_LINE + +static void HorizontalFilter_MIPSdspR2(const uint8_t* data, + int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +#define FILTER_LINE_BY_LINE do { \ + while (row < last_row) { \ + DO_PREDICT_LINE_VERTICAL(in, preds, out, width, 0); \ + ++row; \ + preds += stride; \ + in += stride; \ + out += stride; \ + } \ + } while (0) + +static WEBP_INLINE void DoVerticalFilter_MIPSdspR2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + preds = in; + + if (row == 0) { + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } else { + // We are starting from in-between. Make sure 'preds' points to prev row. + preds -= stride; + } + + // Filter line-by-line. + FILTER_LINE_BY_LINE; +} +#undef FILTER_LINE_BY_LINE + +static void VerticalFilter_MIPSdspR2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ +// Gradient filter. + +static int GradientPredictor_MIPSdspR2(uint8_t a, uint8_t b, uint8_t c) { + int temp0; + __asm__ volatile ( + "addu %[temp0], %[a], %[b] \n\t" + "subu %[temp0], %[temp0], %[c] \n\t" + "shll_s.w %[temp0], %[temp0], 23 \n\t" + "precrqu_s.qb.ph %[temp0], %[temp0], $zero \n\t" + "srl %[temp0], %[temp0], 24 \n\t" + : [temp0]"=&r"(temp0) + : [a]"r"(a),[b]"r"(b),[c]"r"(c) + ); + return temp0; +} + +#define FILTER_LINE_BY_LINE(PREDS, OPERATION) do { \ + while (row < last_row) { \ + int w; \ + PREDICT_LINE_ONE_PASS(in, PREDS - stride, out); \ + for (w = 1; w < width; ++w) { \ + const int pred = GradientPredictor_MIPSdspR2(PREDS[w - 1], \ + PREDS[w - stride], \ + PREDS[w - stride - 1]); \ + out[w] = in[w] OPERATION pred; \ + } \ + ++row; \ + in += stride; \ + out += stride; \ + } \ + } while (0) + +static void DoGradientFilter_MIPSdspR2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + preds = in; + + // left prediction for top scan-line + if (row == 0) { + out[0] = in[0]; + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + FILTER_LINE_BY_LINE(in, -); +} +#undef FILTER_LINE_BY_LINE + +static void GradientFilter_MIPSdspR2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ + +static void HorizontalUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + out[0] = in[0] + (prev == NULL ? 0 : prev[0]); + DO_PREDICT_LINE(in + 1, out + 1, width - 1, 1); +} + +static void VerticalUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_MIPSdspR2(NULL, in, out, width); + } else { + DO_PREDICT_LINE_VERTICAL(in, prev, out, width, 1); + } +} + +static void GradientUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_MIPSdspR2(NULL, in, out, width); + } else { + uint8_t top = prev[0], top_left = top, left = top; + int i; + for (i = 0; i < width; ++i) { + top = prev[i]; // need to read this first, in case prev==dst + left = in[i] + GradientPredictor_MIPSdspR2(left, top, top_left); + top_left = top; + out[i] = left; + } + } +} + +#undef DO_PREDICT_LINE_VERTICAL +#undef PREDICT_LINE_ONE_PASS +#undef DO_PREDICT_LINE +#undef DCHECK + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8FiltersInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMIPSdspR2(void) { + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_MIPSdspR2; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_MIPSdspR2; + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_MIPSdspR2; + + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_MIPSdspR2; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_MIPSdspR2; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8FiltersInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/filters_msa.c b/libraries/webp/src/dsp/filters_msa.c new file mode 100644 index 0000000000..33a1b20b70 --- /dev/null +++ b/libraries/webp/src/dsp/filters_msa.c @@ -0,0 +1,204 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA variant of alpha filters +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/msa_macro.h" + +#include + +static WEBP_INLINE void PredictLineInverse0(const uint8_t* src, + const uint8_t* pred, + uint8_t* dst, int length) { + v16u8 src0, pred0, dst0; + assert(length >= 0); + while (length >= 32) { + v16u8 src1, pred1, dst1; + LD_UB2(src, 16, src0, src1); + LD_UB2(pred, 16, pred0, pred1); + SUB2(src0, pred0, src1, pred1, dst0, dst1); + ST_UB2(dst0, dst1, dst, 16); + src += 32; + pred += 32; + dst += 32; + length -= 32; + } + if (length > 0) { + int i; + if (length >= 16) { + src0 = LD_UB(src); + pred0 = LD_UB(pred); + dst0 = src0 - pred0; + ST_UB(dst0, dst); + src += 16; + pred += 16; + dst += 16; + length -= 16; + } + for (i = 0; i < length; i++) { + dst[i] = src[i] - pred[i]; + } + } +} + +//------------------------------------------------------------------------------ +// Helpful macro. + +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + } while (0) + +//------------------------------------------------------------------------------ +// Horrizontal filter + +static void HorizontalFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + const uint8_t* preds = data; + const uint8_t* in = data; + uint8_t* out = filtered_data; + int row = 1; + DCHECK(in, out); + + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLineInverse0(in + 1, preds, out + 1, width - 1); + preds += stride; + in += stride; + out += stride; + // Filter line-by-line. + while (row < height) { + // Leftmost pixel is predicted from above. + PredictLineInverse0(in, preds - stride, out, 1); + PredictLineInverse0(in + 1, preds, out + 1, width - 1); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Gradient filter + +static WEBP_INLINE void PredictLineGradient(const uint8_t* pinput, + const uint8_t* ppred, + uint8_t* poutput, int stride, + int size) { + int w; + const v16i8 zero = { 0 }; + while (size >= 16) { + v16u8 pred0, dst0; + v8i16 a0, a1, b0, b1, c0, c1; + const v16u8 tmp0 = LD_UB(ppred - 1); + const v16u8 tmp1 = LD_UB(ppred - stride); + const v16u8 tmp2 = LD_UB(ppred - stride - 1); + const v16u8 src0 = LD_UB(pinput); + ILVRL_B2_SH(zero, tmp0, a0, a1); + ILVRL_B2_SH(zero, tmp1, b0, b1); + ILVRL_B2_SH(zero, tmp2, c0, c1); + ADD2(a0, b0, a1, b1, a0, a1); + SUB2(a0, c0, a1, c1, a0, a1); + CLIP_SH2_0_255(a0, a1); + pred0 = (v16u8)__msa_pckev_b((v16i8)a1, (v16i8)a0); + dst0 = src0 - pred0; + ST_UB(dst0, poutput); + ppred += 16; + pinput += 16; + poutput += 16; + size -= 16; + } + for (w = 0; w < size; ++w) { + const int pred = ppred[w - 1] + ppred[w - stride] - ppred[w - stride - 1]; + poutput[w] = pinput[w] - (pred < 0 ? 0 : pred > 255 ? 255 : pred); + } +} + + +static void GradientFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + const uint8_t* in = data; + const uint8_t* preds = data; + uint8_t* out = filtered_data; + int row = 1; + DCHECK(in, out); + + // left prediction for top scan-line + out[0] = in[0]; + PredictLineInverse0(in + 1, preds, out + 1, width - 1); + preds += stride; + in += stride; + out += stride; + // Filter line-by-line. + while (row < height) { + out[0] = in[0] - preds[- stride]; + PredictLineGradient(preds + 1, in + 1, out + 1, stride, width - 1); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Vertical filter + +static void VerticalFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + const uint8_t* in = data; + const uint8_t* preds = data; + uint8_t* out = filtered_data; + int row = 1; + DCHECK(in, out); + + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLineInverse0(in + 1, preds, out + 1, width - 1); + in += stride; + out += stride; + + // Filter line-by-line. + while (row < height) { + PredictLineInverse0(in, preds, out, width); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +#undef DCHECK + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8FiltersInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMSA(void) { + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_MSA; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_MSA; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_MSA; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8FiltersInitMSA) + +#endif // WEBP_USE_MSA diff --git a/libraries/webp/src/dsp/filters_neon.c b/libraries/webp/src/dsp/filters_neon.c new file mode 100644 index 0000000000..b49e515af1 --- /dev/null +++ b/libraries/webp/src/dsp/filters_neon.c @@ -0,0 +1,331 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON variant of alpha filters +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include +#include "src/dsp/neon.h" + +//------------------------------------------------------------------------------ +// Helpful macros. + +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) + +// load eight u8 and widen to s16 +#define U8_TO_S16(A) vreinterpretq_s16_u16(vmovl_u8(A)) +#define LOAD_U8_TO_S16(A) U8_TO_S16(vld1_u8(A)) + +// shift left or right by N byte, inserting zeros +#define SHIFT_RIGHT_N_Q(A, N) vextq_u8((A), zero, (N)) +#define SHIFT_LEFT_N_Q(A, N) vextq_u8(zero, (A), (16 - (N)) % 16) + +// rotate left by N bytes +#define ROTATE_LEFT_N(A, N) vext_u8((A), (A), (N)) +// rotate right by N bytes +#define ROTATE_RIGHT_N(A, N) vext_u8((A), (A), (8 - (N)) % 8) + +static void PredictLine_NEON(const uint8_t* src, const uint8_t* pred, + uint8_t* dst, int length) { + int i; + assert(length >= 0); + for (i = 0; i + 16 <= length; i += 16) { + const uint8x16_t A = vld1q_u8(&src[i]); + const uint8x16_t B = vld1q_u8(&pred[i]); + const uint8x16_t C = vsubq_u8(A, B); + vst1q_u8(&dst[i], C); + } + for (; i < length; ++i) dst[i] = src[i] - pred[i]; +} + +// Special case for left-based prediction (when preds==dst-1 or preds==src-1). +static void PredictLineLeft_NEON(const uint8_t* src, uint8_t* dst, int length) { + PredictLine_NEON(src, src - 1, dst, length); +} + +//------------------------------------------------------------------------------ +// Horizontal filter. + +static WEBP_INLINE void DoHorizontalFilter_NEON(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLineLeft_NEON(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + // Leftmost pixel is predicted from above. + out[0] = in[0] - in[-stride]; + PredictLineLeft_NEON(in + 1, out + 1, width - 1); + ++row; + in += stride; + out += stride; + } +} + +static void HorizontalFilter_NEON(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_NEON(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +static WEBP_INLINE void DoVerticalFilter_NEON(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + + if (row == 0) { + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLineLeft_NEON(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + PredictLine_NEON(in, in - stride, out, width); + ++row; + in += stride; + out += stride; + } +} + +static void VerticalFilter_NEON(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_NEON(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ +// Gradient filter. + +static WEBP_INLINE int GradientPredictor_C(uint8_t a, uint8_t b, uint8_t c) { + const int g = a + b - c; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit +} + +static void GradientPredictDirect_NEON(const uint8_t* const row, + const uint8_t* const top, + uint8_t* const out, int length) { + int i; + for (i = 0; i + 8 <= length; i += 8) { + const uint8x8_t A = vld1_u8(&row[i - 1]); + const uint8x8_t B = vld1_u8(&top[i + 0]); + const int16x8_t C = vreinterpretq_s16_u16(vaddl_u8(A, B)); + const int16x8_t D = LOAD_U8_TO_S16(&top[i - 1]); + const uint8x8_t E = vqmovun_s16(vsubq_s16(C, D)); + const uint8x8_t F = vld1_u8(&row[i + 0]); + vst1_u8(&out[i], vsub_u8(F, E)); + } + for (; i < length; ++i) { + out[i] = row[i] - GradientPredictor_C(row[i - 1], top[i], top[i - 1]); + } +} + +static WEBP_INLINE void DoGradientFilter_NEON(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + + // left prediction for top scan-line + if (row == 0) { + out[0] = in[0]; + PredictLineLeft_NEON(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + out[0] = in[0] - in[-stride]; + GradientPredictDirect_NEON(in + 1, in + 1 - stride, out + 1, width - 1); + ++row; + in += stride; + out += stride; + } +} + +static void GradientFilter_NEON(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_NEON(data, width, height, stride, 0, height, + filtered_data); +} + +#undef DCHECK + +//------------------------------------------------------------------------------ +// Inverse transforms + +static void HorizontalUnfilter_NEON(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + int i; + const uint8x16_t zero = vdupq_n_u8(0); + uint8x16_t last; + out[0] = in[0] + (prev == NULL ? 0 : prev[0]); + if (width <= 1) return; + last = vsetq_lane_u8(out[0], zero, 0); + for (i = 1; i + 16 <= width; i += 16) { + const uint8x16_t A0 = vld1q_u8(&in[i]); + const uint8x16_t A1 = vaddq_u8(A0, last); + const uint8x16_t A2 = SHIFT_LEFT_N_Q(A1, 1); + const uint8x16_t A3 = vaddq_u8(A1, A2); + const uint8x16_t A4 = SHIFT_LEFT_N_Q(A3, 2); + const uint8x16_t A5 = vaddq_u8(A3, A4); + const uint8x16_t A6 = SHIFT_LEFT_N_Q(A5, 4); + const uint8x16_t A7 = vaddq_u8(A5, A6); + const uint8x16_t A8 = SHIFT_LEFT_N_Q(A7, 8); + const uint8x16_t A9 = vaddq_u8(A7, A8); + vst1q_u8(&out[i], A9); + last = SHIFT_RIGHT_N_Q(A9, 15); + } + for (; i < width; ++i) out[i] = in[i] + out[i - 1]; +} + +static void VerticalUnfilter_NEON(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_NEON(NULL, in, out, width); + } else { + int i; + assert(width >= 0); + for (i = 0; i + 16 <= width; i += 16) { + const uint8x16_t A = vld1q_u8(&in[i]); + const uint8x16_t B = vld1q_u8(&prev[i]); + const uint8x16_t C = vaddq_u8(A, B); + vst1q_u8(&out[i], C); + } + for (; i < width; ++i) out[i] = in[i] + prev[i]; + } +} + +// GradientUnfilter_NEON is correct but slower than the C-version, +// at least on ARM64. For armv7, it's a wash. +// So best is to disable it for now, but keep the idea around... +#if !defined(USE_GRADIENT_UNFILTER) +#define USE_GRADIENT_UNFILTER 0 // ALTERNATE_CODE +#endif + +#if (USE_GRADIENT_UNFILTER == 1) +#define GRAD_PROCESS_LANE(L) do { \ + const uint8x8_t tmp1 = ROTATE_RIGHT_N(pred, 1); /* rotate predictor in */ \ + const int16x8_t tmp2 = vaddq_s16(BC, U8_TO_S16(tmp1)); \ + const uint8x8_t delta = vqmovun_s16(tmp2); \ + pred = vadd_u8(D, delta); \ + out = vext_u8(out, ROTATE_LEFT_N(pred, (L)), 1); \ +} while (0) + +static void GradientPredictInverse_NEON(const uint8_t* const in, + const uint8_t* const top, + uint8_t* const row, int length) { + if (length > 0) { + int i; + uint8x8_t pred = vdup_n_u8(row[-1]); // left sample + uint8x8_t out = vdup_n_u8(0); + for (i = 0; i + 8 <= length; i += 8) { + const int16x8_t B = LOAD_U8_TO_S16(&top[i + 0]); + const int16x8_t C = LOAD_U8_TO_S16(&top[i - 1]); + const int16x8_t BC = vsubq_s16(B, C); // unclipped gradient basis B - C + const uint8x8_t D = vld1_u8(&in[i]); // base input + GRAD_PROCESS_LANE(0); + GRAD_PROCESS_LANE(1); + GRAD_PROCESS_LANE(2); + GRAD_PROCESS_LANE(3); + GRAD_PROCESS_LANE(4); + GRAD_PROCESS_LANE(5); + GRAD_PROCESS_LANE(6); + GRAD_PROCESS_LANE(7); + vst1_u8(&row[i], out); + } + for (; i < length; ++i) { + row[i] = in[i] + GradientPredictor_C(row[i - 1], top[i], top[i - 1]); + } + } +} +#undef GRAD_PROCESS_LANE + +static void GradientUnfilter_NEON(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_NEON(NULL, in, out, width); + } else { + out[0] = in[0] + prev[0]; // predict from above + GradientPredictInverse_NEON(in + 1, prev + 1, out + 1, width - 1); + } +} + +#endif // USE_GRADIENT_UNFILTER + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8FiltersInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitNEON(void) { + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_NEON; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_NEON; +#if (USE_GRADIENT_UNFILTER == 1) + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_NEON; +#endif + + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_NEON; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_NEON; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8FiltersInitNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/filters_sse2.c b/libraries/webp/src/dsp/filters_sse2.c new file mode 100644 index 0000000000..bb4b5d5874 --- /dev/null +++ b/libraries/webp/src/dsp/filters_sse2.c @@ -0,0 +1,342 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 variant of alpha filters +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Helpful macro. + +#define DCHECK(in, out) \ + do { \ + assert((in) != NULL); \ + assert((out) != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) + +static void PredictLineTop_SSE2(const uint8_t* src, const uint8_t* pred, + uint8_t* dst, int length) { + int i; + const int max_pos = length & ~31; + assert(length >= 0); + for (i = 0; i < max_pos; i += 32) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]); + const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]); + const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]); + const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]); + const __m128i C0 = _mm_sub_epi8(A0, B0); + const __m128i C1 = _mm_sub_epi8(A1, B1); + _mm_storeu_si128((__m128i*)&dst[i + 0], C0); + _mm_storeu_si128((__m128i*)&dst[i + 16], C1); + } + for (; i < length; ++i) dst[i] = src[i] - pred[i]; +} + +// Special case for left-based prediction (when preds==dst-1 or preds==src-1). +static void PredictLineLeft_SSE2(const uint8_t* src, uint8_t* dst, int length) { + int i; + const int max_pos = length & ~31; + assert(length >= 0); + for (i = 0; i < max_pos; i += 32) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + i + 0 )); + const __m128i B0 = _mm_loadu_si128((const __m128i*)(src + i + 0 - 1)); + const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + i + 16 )); + const __m128i B1 = _mm_loadu_si128((const __m128i*)(src + i + 16 - 1)); + const __m128i C0 = _mm_sub_epi8(A0, B0); + const __m128i C1 = _mm_sub_epi8(A1, B1); + _mm_storeu_si128((__m128i*)(dst + i + 0), C0); + _mm_storeu_si128((__m128i*)(dst + i + 16), C1); + } + for (; i < length; ++i) dst[i] = src[i] - src[i - 1]; +} + +//------------------------------------------------------------------------------ +// Horizontal filter. + +static WEBP_INLINE void DoHorizontalFilter_SSE2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + // Leftmost pixel is predicted from above. + out[0] = in[0] - in[-stride]; + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); + ++row; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +static WEBP_INLINE void DoVerticalFilter_SSE2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + + if (row == 0) { + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + PredictLineTop_SSE2(in, in - stride, out, width); + ++row; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Gradient filter. + +static WEBP_INLINE int GradientPredictor_SSE2(uint8_t a, uint8_t b, uint8_t c) { + const int g = a + b - c; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit +} + +static void GradientPredictDirect_SSE2(const uint8_t* const row, + const uint8_t* const top, + uint8_t* const out, int length) { + const int max_pos = length & ~7; + int i; + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i < max_pos; i += 8) { + const __m128i A0 = _mm_loadl_epi64((const __m128i*)&row[i - 1]); + const __m128i B0 = _mm_loadl_epi64((const __m128i*)&top[i]); + const __m128i C0 = _mm_loadl_epi64((const __m128i*)&top[i - 1]); + const __m128i D = _mm_loadl_epi64((const __m128i*)&row[i]); + const __m128i A1 = _mm_unpacklo_epi8(A0, zero); + const __m128i B1 = _mm_unpacklo_epi8(B0, zero); + const __m128i C1 = _mm_unpacklo_epi8(C0, zero); + const __m128i E = _mm_add_epi16(A1, B1); + const __m128i F = _mm_sub_epi16(E, C1); + const __m128i G = _mm_packus_epi16(F, zero); + const __m128i H = _mm_sub_epi8(D, G); + _mm_storel_epi64((__m128i*)(out + i), H); + } + for (; i < length; ++i) { + const int delta = GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]); + out[i] = (uint8_t)(row[i] - delta); + } +} + +static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + DCHECK(in, out); + in += start_offset; + out += start_offset; + + // left prediction for top scan-line + if (row == 0) { + out[0] = in[0]; + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + out[0] = (uint8_t)(in[0] - in[-stride]); + GradientPredictDirect_SSE2(in + 1, in + 1 - stride, out + 1, width - 1); + ++row; + in += stride; + out += stride; + } +} + +#undef DCHECK + +//------------------------------------------------------------------------------ + +static void HorizontalFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_SSE2(data, width, height, stride, 0, height, + filtered_data); +} + +static void VerticalFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_SSE2(data, width, height, stride, 0, height, filtered_data); +} + +static void GradientFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_SSE2(data, width, height, stride, 0, height, filtered_data); +} + +//------------------------------------------------------------------------------ +// Inverse transforms + +static void HorizontalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + int i; + __m128i last; + out[0] = (uint8_t)(in[0] + (prev == NULL ? 0 : prev[0])); + if (width <= 1) return; + last = _mm_set_epi32(0, 0, 0, out[0]); + for (i = 1; i + 8 <= width; i += 8) { + const __m128i A0 = _mm_loadl_epi64((const __m128i*)(in + i)); + const __m128i A1 = _mm_add_epi8(A0, last); + const __m128i A2 = _mm_slli_si128(A1, 1); + const __m128i A3 = _mm_add_epi8(A1, A2); + const __m128i A4 = _mm_slli_si128(A3, 2); + const __m128i A5 = _mm_add_epi8(A3, A4); + const __m128i A6 = _mm_slli_si128(A5, 4); + const __m128i A7 = _mm_add_epi8(A5, A6); + _mm_storel_epi64((__m128i*)(out + i), A7); + last = _mm_srli_epi64(A7, 56); + } + for (; i < width; ++i) out[i] = (uint8_t)(in[i] + out[i - 1]); +} + +static void VerticalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_SSE2(NULL, in, out, width); + } else { + int i; + const int max_pos = width & ~31; + assert(width >= 0); + for (i = 0; i < max_pos; i += 32) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)&in[i + 0]); + const __m128i A1 = _mm_loadu_si128((const __m128i*)&in[i + 16]); + const __m128i B0 = _mm_loadu_si128((const __m128i*)&prev[i + 0]); + const __m128i B1 = _mm_loadu_si128((const __m128i*)&prev[i + 16]); + const __m128i C0 = _mm_add_epi8(A0, B0); + const __m128i C1 = _mm_add_epi8(A1, B1); + _mm_storeu_si128((__m128i*)&out[i + 0], C0); + _mm_storeu_si128((__m128i*)&out[i + 16], C1); + } + for (; i < width; ++i) out[i] = (uint8_t)(in[i] + prev[i]); + } +} + +static void GradientPredictInverse_SSE2(const uint8_t* const in, + const uint8_t* const top, + uint8_t* const row, int length) { + if (length > 0) { + int i; + const int max_pos = length & ~7; + const __m128i zero = _mm_setzero_si128(); + __m128i A = _mm_set_epi32(0, 0, 0, row[-1]); // left sample + for (i = 0; i < max_pos; i += 8) { + const __m128i tmp0 = _mm_loadl_epi64((const __m128i*)&top[i]); + const __m128i tmp1 = _mm_loadl_epi64((const __m128i*)&top[i - 1]); + const __m128i B = _mm_unpacklo_epi8(tmp0, zero); + const __m128i C = _mm_unpacklo_epi8(tmp1, zero); + const __m128i D = _mm_loadl_epi64((const __m128i*)&in[i]); // base input + const __m128i E = _mm_sub_epi16(B, C); // unclipped gradient basis B - C + __m128i out = zero; // accumulator for output + __m128i mask_hi = _mm_set_epi32(0, 0, 0, 0xff); + int k = 8; + while (1) { + const __m128i tmp3 = _mm_add_epi16(A, E); // delta = A + B - C + const __m128i tmp4 = _mm_packus_epi16(tmp3, zero); // saturate delta + const __m128i tmp5 = _mm_add_epi8(tmp4, D); // add to in[] + A = _mm_and_si128(tmp5, mask_hi); // 1-complement clip + out = _mm_or_si128(out, A); // accumulate output + if (--k == 0) break; + A = _mm_slli_si128(A, 1); // rotate left sample + mask_hi = _mm_slli_si128(mask_hi, 1); // rotate mask + A = _mm_unpacklo_epi8(A, zero); // convert 8b->16b + } + A = _mm_srli_si128(A, 7); // prepare left sample for next iteration + _mm_storel_epi64((__m128i*)&row[i], out); + } + for (; i < length; ++i) { + const int delta = GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]); + row[i] = (uint8_t)(in[i] + delta); + } + } +} + +static void GradientUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_SSE2(NULL, in, out, width); + } else { + out[0] = (uint8_t)(in[0] + prev[0]); // predict from above + GradientPredictInverse_SSE2(in + 1, prev + 1, out + 1, width - 1); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8FiltersInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitSSE2(void) { + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_SSE2; +#if defined(CHROMIUM) + // TODO(crbug.com/654974) + (void)VerticalUnfilter_SSE2; +#else + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_SSE2; +#endif + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_SSE2; + + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_SSE2; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_SSE2; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8FiltersInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/lossless.c b/libraries/webp/src/dsp/lossless.c new file mode 100644 index 0000000000..9f81209453 --- /dev/null +++ b/libraries/webp/src/dsp/lossless.c @@ -0,0 +1,681 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) + +#include "src/dsp/dsp.h" + +#include +#include +#include +#include "src/dec/vp8li_dec.h" +#include "src/utils/endian_inl_utils.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" + +//------------------------------------------------------------------------------ +// Image transforms. + +static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { + return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1); +} + +static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { + return Average2(Average2(a0, a2), a1); +} + +static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) { + return Average2(Average2(a0, a1), Average2(a2, a3)); +} + +static WEBP_INLINE uint32_t Clip255(uint32_t a) { + if (a < 256) { + return a; + } + // return 0, when a is a negative integer. + // return 255, when a is positive. + return ~a >> 24; +} + +static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) { + return Clip255((uint32_t)(a + b - c)); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, + uint32_t c2) { + const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24); + const int r = AddSubtractComponentFull((c0 >> 16) & 0xff, + (c1 >> 16) & 0xff, + (c2 >> 16) & 0xff); + const int g = AddSubtractComponentFull((c0 >> 8) & 0xff, + (c1 >> 8) & 0xff, + (c2 >> 8) & 0xff); + const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff); + return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; +} + +static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) { + return Clip255((uint32_t)(a + (a - b) / 2)); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, + uint32_t c2) { + const uint32_t ave = Average2(c0, c1); + const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24); + const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff); + const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff); + const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff); + return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; +} + +// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is +// inlined. +#if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409 +# define LOCAL_INLINE __attribute__ ((noinline)) +#else +# define LOCAL_INLINE WEBP_INLINE +#endif + +static LOCAL_INLINE int Sub3(int a, int b, int c) { + const int pb = b - c; + const int pa = a - c; + return abs(pb) - abs(pa); +} + +#undef LOCAL_INLINE + +static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { + const int pa_minus_pb = + Sub3((a >> 24) , (b >> 24) , (c >> 24) ) + + Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) + + Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) + + Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff); + return (pa_minus_pb <= 0) ? a : b; +} + +//------------------------------------------------------------------------------ +// Predictors + +uint32_t VP8LPredictor0_C(const uint32_t* const left, + const uint32_t* const top) { + (void)top; + (void)left; + return ARGB_BLACK; +} +uint32_t VP8LPredictor1_C(const uint32_t* const left, + const uint32_t* const top) { + (void)top; + return *left; +} +uint32_t VP8LPredictor2_C(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return top[0]; +} +uint32_t VP8LPredictor3_C(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return top[1]; +} +uint32_t VP8LPredictor4_C(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return top[-1]; +} +uint32_t VP8LPredictor5_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average3(*left, top[0], top[1]); + return pred; +} +uint32_t VP8LPredictor6_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(*left, top[-1]); + return pred; +} +uint32_t VP8LPredictor7_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(*left, top[0]); + return pred; +} +uint32_t VP8LPredictor8_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(top[-1], top[0]); + (void)left; + return pred; +} +uint32_t VP8LPredictor9_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(top[0], top[1]); + (void)left; + return pred; +} +uint32_t VP8LPredictor10_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average4(*left, top[-1], top[0], top[1]); + return pred; +} +uint32_t VP8LPredictor11_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Select(top[0], *left, top[-1]); + return pred; +} +uint32_t VP8LPredictor12_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractFull(*left, top[0], top[-1]); + return pred; +} +uint32_t VP8LPredictor13_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractHalf(*left, top[0], top[-1]); + return pred; +} + +static void PredictorAdd0_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int x; + (void)upper; + for (x = 0; x < num_pixels; ++x) out[x] = VP8LAddPixels(in[x], ARGB_BLACK); +} +static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint32_t left = out[-1]; + (void)upper; + for (i = 0; i < num_pixels; ++i) { + out[i] = left = VP8LAddPixels(in[i], left); + } +} +GENERATE_PREDICTOR_ADD(VP8LPredictor2_C, PredictorAdd2_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor3_C, PredictorAdd3_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor4_C, PredictorAdd4_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor5_C, PredictorAdd5_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor6_C, PredictorAdd6_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor7_C, PredictorAdd7_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor8_C, PredictorAdd8_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor9_C, PredictorAdd9_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor10_C, PredictorAdd10_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor11_C, PredictorAdd11_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor12_C, PredictorAdd12_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor13_C, PredictorAdd13_C) + +//------------------------------------------------------------------------------ + +// Inverse prediction. +static void PredictorInverseTransform_C(const VP8LTransform* const transform, + int y_start, int y_end, + const uint32_t* in, uint32_t* out) { + const int width = transform->xsize_; + if (y_start == 0) { // First Row follows the L (mode=1) mode. + PredictorAdd0_C(in, NULL, 1, out); + PredictorAdd1_C(in + 1, NULL, width - 1, out + 1); + in += width; + out += width; + ++y_start; + } + + { + int y = y_start; + const int tile_width = 1 << transform->bits_; + const int mask = tile_width - 1; + const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); + const uint32_t* pred_mode_base = + transform->data_ + (y >> transform->bits_) * tiles_per_row; + + while (y < y_end) { + const uint32_t* pred_mode_src = pred_mode_base; + int x = 1; + // First pixel follows the T (mode=2) mode. + PredictorAdd2_C(in, out - width, 1, out); + // .. the rest: + while (x < width) { + const VP8LPredictorAddSubFunc pred_func = + VP8LPredictorsAdd[((*pred_mode_src++) >> 8) & 0xf]; + int x_end = (x & ~mask) + tile_width; + if (x_end > width) x_end = width; + pred_func(in + x, out + x - width, x_end - x, out + x); + x = x_end; + } + in += width; + out += width; + ++y; + if ((y & mask) == 0) { // Use the same mask, since tiles are squares. + pred_mode_base += tiles_per_row; + } + } + } +} + +// Add green to blue and red channels (i.e. perform the inverse transform of +// 'subtract green'). +void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels, + uint32_t* dst) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint32_t argb = src[i]; + const uint32_t green = ((argb >> 8) & 0xff); + uint32_t red_blue = (argb & 0x00ff00ffu); + red_blue += (green << 16) | green; + red_blue &= 0x00ff00ffu; + dst[i] = (argb & 0xff00ff00u) | red_blue; + } +} + +static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, + int8_t color) { + return ((int)color_pred * color) >> 5; +} + +static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, + VP8LMultipliers* const m) { + m->green_to_red_ = (color_code >> 0) & 0xff; + m->green_to_blue_ = (color_code >> 8) & 0xff; + m->red_to_blue_ = (color_code >> 16) & 0xff; +} + +void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint32_t argb = src[i]; + const int8_t green = (int8_t)(argb >> 8); + const uint32_t red = argb >> 16; + int new_red = red & 0xff; + int new_blue = argb & 0xff; + new_red += ColorTransformDelta((int8_t)m->green_to_red_, green); + new_red &= 0xff; + new_blue += ColorTransformDelta((int8_t)m->green_to_blue_, green); + new_blue += ColorTransformDelta((int8_t)m->red_to_blue_, (int8_t)new_red); + new_blue &= 0xff; + dst[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); + } +} + +// Color space inverse transform. +static void ColorSpaceInverseTransform_C(const VP8LTransform* const transform, + int y_start, int y_end, + const uint32_t* src, uint32_t* dst) { + const int width = transform->xsize_; + const int tile_width = 1 << transform->bits_; + const int mask = tile_width - 1; + const int safe_width = width & ~mask; + const int remaining_width = width - safe_width; + const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); + int y = y_start; + const uint32_t* pred_row = + transform->data_ + (y >> transform->bits_) * tiles_per_row; + + while (y < y_end) { + const uint32_t* pred = pred_row; + VP8LMultipliers m = { 0, 0, 0 }; + const uint32_t* const src_safe_end = src + safe_width; + const uint32_t* const src_end = src + width; + while (src < src_safe_end) { + ColorCodeToMultipliers(*pred++, &m); + VP8LTransformColorInverse(&m, src, tile_width, dst); + src += tile_width; + dst += tile_width; + } + if (src < src_end) { // Left-overs using C-version. + ColorCodeToMultipliers(*pred++, &m); + VP8LTransformColorInverse(&m, src, remaining_width, dst); + src += remaining_width; + dst += remaining_width; + } + ++y; + if ((y & mask) == 0) pred_row += tiles_per_row; + } +} + +// Separate out pixels packed together using pixel-bundling. +// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). +#define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \ + GET_INDEX, GET_VALUE) \ +static void F_NAME(const TYPE* src, const uint32_t* const color_map, \ + TYPE* dst, int y_start, int y_end, int width) { \ + int y; \ + for (y = y_start; y < y_end; ++y) { \ + int x; \ + for (x = 0; x < width; ++x) { \ + *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ + } \ + } \ +} \ +STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \ + int y_start, int y_end, const TYPE* src, \ + TYPE* dst) { \ + int y; \ + const int bits_per_pixel = 8 >> transform->bits_; \ + const int width = transform->xsize_; \ + const uint32_t* const color_map = transform->data_; \ + if (bits_per_pixel < 8) { \ + const int pixels_per_byte = 1 << transform->bits_; \ + const int count_mask = pixels_per_byte - 1; \ + const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \ + for (y = y_start; y < y_end; ++y) { \ + uint32_t packed_pixels = 0; \ + int x; \ + for (x = 0; x < width; ++x) { \ + /* We need to load fresh 'packed_pixels' once every */ \ + /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \ + /* is a power of 2, so can just use a mask for that, instead of */ \ + /* decrementing a counter. */ \ + if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \ + *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \ + packed_pixels >>= bits_per_pixel; \ + } \ + } \ + } else { \ + VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \ + } \ +} + +COLOR_INDEX_INVERSE(ColorIndexInverseTransform_C, MapARGB_C, static, + uint32_t, 32b, VP8GetARGBIndex, VP8GetARGBValue) +COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha_C, , + uint8_t, 8b, VP8GetAlphaIndex, VP8GetAlphaValue) + +#undef COLOR_INDEX_INVERSE + +void VP8LInverseTransform(const VP8LTransform* const transform, + int row_start, int row_end, + const uint32_t* const in, uint32_t* const out) { + const int width = transform->xsize_; + assert(row_start < row_end); + assert(row_end <= transform->ysize_); + switch (transform->type_) { + case SUBTRACT_GREEN_TRANSFORM: + VP8LAddGreenToBlueAndRed(in, (row_end - row_start) * width, out); + break; + case PREDICTOR_TRANSFORM: + PredictorInverseTransform_C(transform, row_start, row_end, in, out); + if (row_end != transform->ysize_) { + // The last predicted row in this iteration will be the top-pred row + // for the first row in next iteration. + memcpy(out - width, out + (row_end - row_start - 1) * width, + width * sizeof(*out)); + } + break; + case CROSS_COLOR_TRANSFORM: + ColorSpaceInverseTransform_C(transform, row_start, row_end, in, out); + break; + case COLOR_INDEXING_TRANSFORM: + if (in == out && transform->bits_ > 0) { + // Move packed pixels to the end of unpacked region, so that unpacking + // can occur seamlessly. + // Also, note that this is the only transform that applies on + // the effective width of VP8LSubSampleSize(xsize_, bits_). All other + // transforms work on effective width of xsize_. + const int out_stride = (row_end - row_start) * width; + const int in_stride = (row_end - row_start) * + VP8LSubSampleSize(transform->xsize_, transform->bits_); + uint32_t* const src = out + out_stride - in_stride; + memmove(src, out, in_stride * sizeof(*src)); + ColorIndexInverseTransform_C(transform, row_start, row_end, src, out); + } else { + ColorIndexInverseTransform_C(transform, row_start, row_end, in, out); + } + break; + } +} + +//------------------------------------------------------------------------------ +// Color space conversion. + +static int is_big_endian(void) { + static const union { + uint16_t w; + uint8_t b[2]; + } tmp = { 1 }; + return (tmp.b[0] != 1); +} + +void VP8LConvertBGRAToRGB_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + *dst++ = (argb >> 16) & 0xff; + *dst++ = (argb >> 8) & 0xff; + *dst++ = (argb >> 0) & 0xff; + } +} + +void VP8LConvertBGRAToRGBA_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + *dst++ = (argb >> 16) & 0xff; + *dst++ = (argb >> 8) & 0xff; + *dst++ = (argb >> 0) & 0xff; + *dst++ = (argb >> 24) & 0xff; + } +} + +void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf); + const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf); +#if (WEBP_SWAP_16BIT_CSP == 1) + *dst++ = ba; + *dst++ = rg; +#else + *dst++ = rg; + *dst++ = ba; +#endif + } +} + +void VP8LConvertBGRAToRGB565_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7); + const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f); +#if (WEBP_SWAP_16BIT_CSP == 1) + *dst++ = gb; + *dst++ = rg; +#else + *dst++ = rg; + *dst++ = gb; +#endif + } +} + +void VP8LConvertBGRAToBGR_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + *dst++ = (argb >> 0) & 0xff; + *dst++ = (argb >> 8) & 0xff; + *dst++ = (argb >> 16) & 0xff; + } +} + +static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, + int swap_on_big_endian) { + if (is_big_endian() == swap_on_big_endian) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + WebPUint32ToMem(dst, BSwap32(argb)); + dst += sizeof(argb); + } + } else { + memcpy(dst, src, num_pixels * sizeof(*src)); + } +} + +void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, + WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) { + switch (out_colorspace) { + case MODE_RGB: + VP8LConvertBGRAToRGB(in_data, num_pixels, rgba); + break; + case MODE_RGBA: + VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); + break; + case MODE_rgbA: + VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); + WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); + break; + case MODE_BGR: + VP8LConvertBGRAToBGR(in_data, num_pixels, rgba); + break; + case MODE_BGRA: + CopyOrSwap(in_data, num_pixels, rgba, 1); + break; + case MODE_bgrA: + CopyOrSwap(in_data, num_pixels, rgba, 1); + WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); + break; + case MODE_ARGB: + CopyOrSwap(in_data, num_pixels, rgba, 0); + break; + case MODE_Argb: + CopyOrSwap(in_data, num_pixels, rgba, 0); + WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0); + break; + case MODE_RGBA_4444: + VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); + break; + case MODE_rgbA_4444: + VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); + WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0); + break; + case MODE_RGB_565: + VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba); + break; + default: + assert(0); // Code flow should not reach here. + } +} + +//------------------------------------------------------------------------------ + +VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed; +VP8LPredictorAddSubFunc VP8LPredictorsAdd[16]; +VP8LPredictorFunc VP8LPredictors[16]; + +// exposed plain-C implementations +VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16]; + +VP8LTransformColorInverseFunc VP8LTransformColorInverse; + +VP8LConvertFunc VP8LConvertBGRAToRGB; +VP8LConvertFunc VP8LConvertBGRAToRGBA; +VP8LConvertFunc VP8LConvertBGRAToRGBA4444; +VP8LConvertFunc VP8LConvertBGRAToRGB565; +VP8LConvertFunc VP8LConvertBGRAToBGR; + +VP8LMapARGBFunc VP8LMapColor32b; +VP8LMapAlphaFunc VP8LMapColor8b; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8LDspInitSSE2(void); +extern void VP8LDspInitSSE41(void); +extern void VP8LDspInitNEON(void); +extern void VP8LDspInitMIPSdspR2(void); +extern void VP8LDspInitMSA(void); + +#define COPY_PREDICTOR_ARRAY(IN, OUT) do { \ + (OUT)[0] = IN##0_C; \ + (OUT)[1] = IN##1_C; \ + (OUT)[2] = IN##2_C; \ + (OUT)[3] = IN##3_C; \ + (OUT)[4] = IN##4_C; \ + (OUT)[5] = IN##5_C; \ + (OUT)[6] = IN##6_C; \ + (OUT)[7] = IN##7_C; \ + (OUT)[8] = IN##8_C; \ + (OUT)[9] = IN##9_C; \ + (OUT)[10] = IN##10_C; \ + (OUT)[11] = IN##11_C; \ + (OUT)[12] = IN##12_C; \ + (OUT)[13] = IN##13_C; \ + (OUT)[14] = IN##0_C; /* <- padding security sentinels*/ \ + (OUT)[15] = IN##0_C; \ +} while (0); + +WEBP_DSP_INIT_FUNC(VP8LDspInit) { + COPY_PREDICTOR_ARRAY(VP8LPredictor, VP8LPredictors) + COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd) + COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd_C) + +#if !WEBP_NEON_OMIT_C_CODE + VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; + + VP8LTransformColorInverse = VP8LTransformColorInverse_C; + + VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; + VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; + VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; +#endif + + VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; + VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; + + VP8LMapColor32b = MapARGB_C; + VP8LMapColor8b = MapAlpha_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8LDspInitSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + VP8LDspInitSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8LDspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8LDspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8LDspInitNEON(); + } +#endif + + assert(VP8LAddGreenToBlueAndRed != NULL); + assert(VP8LTransformColorInverse != NULL); + assert(VP8LConvertBGRAToRGBA != NULL); + assert(VP8LConvertBGRAToRGB != NULL); + assert(VP8LConvertBGRAToBGR != NULL); + assert(VP8LConvertBGRAToRGBA4444 != NULL); + assert(VP8LConvertBGRAToRGB565 != NULL); + assert(VP8LMapColor32b != NULL); + assert(VP8LMapColor8b != NULL); +} +#undef COPY_PREDICTOR_ARRAY + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dsp/lossless.h b/libraries/webp/src/dsp/lossless.h new file mode 100644 index 0000000000..fac0ec6511 --- /dev/null +++ b/libraries/webp/src/dsp/lossless.h @@ -0,0 +1,259 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) + +#ifndef WEBP_DSP_LOSSLESS_H_ +#define WEBP_DSP_LOSSLESS_H_ + +#include "include/webp/types.h" +#include "include/webp/decode.h" + +#include "src/enc/histogram_enc.h" +#include "src/utils/utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Decoding + +typedef uint32_t (*VP8LPredictorFunc)(const uint32_t* const left, + const uint32_t* const top); +extern VP8LPredictorFunc VP8LPredictors[16]; + +uint32_t VP8LPredictor0_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor1_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor2_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor3_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor4_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor5_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor6_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor7_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor8_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor9_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor10_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor11_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor12_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor13_C(const uint32_t* const left, + const uint32_t* const top); + +// These Add/Sub function expects upper[-1] and out[-1] to be readable. +typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in, + const uint32_t* upper, int num_pixels, + uint32_t* out); +extern VP8LPredictorAddSubFunc VP8LPredictorsAdd[16]; +extern VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16]; + +typedef void (*VP8LProcessDecBlueAndRedFunc)(const uint32_t* src, + int num_pixels, uint32_t* dst); +extern VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed; + +typedef struct { + // Note: the members are uint8_t, so that any negative values are + // automatically converted to "mod 256" values. + uint8_t green_to_red_; + uint8_t green_to_blue_; + uint8_t red_to_blue_; +} VP8LMultipliers; +typedef void (*VP8LTransformColorInverseFunc)(const VP8LMultipliers* const m, + const uint32_t* src, + int num_pixels, uint32_t* dst); +extern VP8LTransformColorInverseFunc VP8LTransformColorInverse; + +struct VP8LTransform; // Defined in dec/vp8li.h. + +// Performs inverse transform of data given transform information, start and end +// rows. Transform will be applied to rows [row_start, row_end[. +// The *in and *out pointers refer to source and destination data respectively +// corresponding to the intermediate row (row_start). +void VP8LInverseTransform(const struct VP8LTransform* const transform, + int row_start, int row_end, + const uint32_t* const in, uint32_t* const out); + +// Color space conversion. +typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels, + uint8_t* dst); +extern VP8LConvertFunc VP8LConvertBGRAToRGB; +extern VP8LConvertFunc VP8LConvertBGRAToRGBA; +extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444; +extern VP8LConvertFunc VP8LConvertBGRAToRGB565; +extern VP8LConvertFunc VP8LConvertBGRAToBGR; + +// Converts from BGRA to other color spaces. +void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, + WEBP_CSP_MODE out_colorspace, uint8_t* const rgba); + +typedef void (*VP8LMapARGBFunc)(const uint32_t* src, + const uint32_t* const color_map, + uint32_t* dst, int y_start, + int y_end, int width); +typedef void (*VP8LMapAlphaFunc)(const uint8_t* src, + const uint32_t* const color_map, + uint8_t* dst, int y_start, + int y_end, int width); + +extern VP8LMapARGBFunc VP8LMapColor32b; +extern VP8LMapAlphaFunc VP8LMapColor8b; + +// Similar to the static method ColorIndexInverseTransform() that is part of +// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than +// uint32_t) arguments for 'src' and 'dst'. +void VP8LColorIndexInverseTransformAlpha( + const struct VP8LTransform* const transform, int y_start, int y_end, + const uint8_t* src, uint8_t* dst); + +// Expose some C-only fallback functions +void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst); + +void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, + int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGB565_C(const uint32_t* src, + int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels, + uint32_t* dst); + +// Must be called before calling any of the above methods. +void VP8LDspInit(void); + +//------------------------------------------------------------------------------ +// Encoding + +typedef void (*VP8LProcessEncBlueAndRedFunc)(uint32_t* dst, int num_pixels); +extern VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; +typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m, + uint32_t* dst, int num_pixels); +extern VP8LTransformColorFunc VP8LTransformColor; +typedef void (*VP8LCollectColorBlueTransformsFunc)( + const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, int histo[]); +extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; + +typedef void (*VP8LCollectColorRedTransformsFunc)( + const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]); +extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; + +// Expose some C-only fallback functions +void VP8LTransformColor_C(const VP8LMultipliers* const m, + uint32_t* data, int num_pixels); +void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels); +void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]); +void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]); + +extern VP8LPredictorAddSubFunc VP8LPredictorsSub[16]; +extern VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16]; + +// ----------------------------------------------------------------------------- +// Huffman-cost related functions. + +typedef uint32_t (*VP8LCostFunc)(const uint32_t* population, int length); +typedef uint32_t (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y, + int length); +typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256], + const int Y[256]); + +extern VP8LCostFunc VP8LExtraCost; +extern VP8LCostCombinedFunc VP8LExtraCostCombined; +extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; + +typedef struct { // small struct to hold counters + int counts[2]; // index: 0=zero streak, 1=non-zero streak + int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3] +} VP8LStreaks; + +typedef struct { // small struct to hold bit entropy results + float entropy; // entropy + uint32_t sum; // sum of the population + int nonzeros; // number of non-zero elements in the population + uint32_t max_val; // maximum value in the population + uint32_t nonzero_code; // index of the last non-zero in the population +} VP8LBitEntropy; + +void VP8LBitEntropyInit(VP8LBitEntropy* const entropy); + +// Get the combined symbol bit entropy and Huffman cost stats for the +// distributions 'X' and 'Y'. Those results can then be refined according to +// codec specific heuristics. +typedef void (*VP8LGetCombinedEntropyUnrefinedFunc)( + const uint32_t X[], const uint32_t Y[], int length, + VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats); +extern VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined; + +// Get the entropy for the distribution 'X'. +typedef void (*VP8LGetEntropyUnrefinedFunc)(const uint32_t X[], int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats); +extern VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined; + +void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, + VP8LBitEntropy* const entropy); + +typedef void (*VP8LAddVectorFunc)(const uint32_t* a, const uint32_t* b, + uint32_t* out, int size); +extern VP8LAddVectorFunc VP8LAddVector; +typedef void (*VP8LAddVectorEqFunc)(const uint32_t* a, uint32_t* out, int size); +extern VP8LAddVectorEqFunc VP8LAddVectorEq; +void VP8LHistogramAdd(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out); + +// ----------------------------------------------------------------------------- +// PrefixEncode() + +typedef int (*VP8LVectorMismatchFunc)(const uint32_t* const array1, + const uint32_t* const array2, int length); +// Returns the first index where array1 and array2 are different. +extern VP8LVectorMismatchFunc VP8LVectorMismatch; + +typedef void (*VP8LBundleColorMapFunc)(const uint8_t* const row, int width, + int xbits, uint32_t* dst); +extern VP8LBundleColorMapFunc VP8LBundleColorMap; +void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits, + uint32_t* dst); + +// Must be called before calling any of the above methods. +void VP8LEncDspInit(void); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_LOSSLESS_H_ diff --git a/libraries/webp/src/dsp/lossless_common.h b/libraries/webp/src/dsp/lossless_common.h new file mode 100644 index 0000000000..8f16b5da66 --- /dev/null +++ b/libraries/webp/src/dsp/lossless_common.h @@ -0,0 +1,191 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_DSP_LOSSLESS_COMMON_H_ +#define WEBP_DSP_LOSSLESS_COMMON_H_ + +#include "src/dsp/cpu.h" +#include "src/utils/utils.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Decoding + +// color mapping related functions. +static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) { + return (idx >> 8) & 0xff; +} + +static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) { + return idx; +} + +static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) { + return val; +} + +static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) { + return (val >> 8) & 0xff; +} + +//------------------------------------------------------------------------------ +// Misc methods. + +// Computes sampled size of 'size' when sampling using 'sampling bits'. +static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size, + uint32_t sampling_bits) { + return (size + (1 << sampling_bits) - 1) >> sampling_bits; +} + +// Converts near lossless quality into max number of bits shaved off. +static WEBP_INLINE int VP8LNearLosslessBits(int near_lossless_quality) { + // 100 -> 0 + // 80..99 -> 1 + // 60..79 -> 2 + // 40..59 -> 3 + // 20..39 -> 4 + // 0..19 -> 5 + return 5 - near_lossless_quality / 20; +} + +// ----------------------------------------------------------------------------- +// Faster logarithm for integers. Small values use a look-up table. + +// The threshold till approximate version of log_2 can be used. +// Practically, we can get rid of the call to log() as the two values match to +// very high degree (the ratio of these two is 0.99999x). +// Keeping a high threshold for now. +#define APPROX_LOG_WITH_CORRECTION_MAX 65536 +#define APPROX_LOG_MAX 4096 +#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 +#define LOG_LOOKUP_IDX_MAX 256 +extern const float kLog2Table[LOG_LOOKUP_IDX_MAX]; +extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX]; +typedef float (*VP8LFastLog2SlowFunc)(uint32_t v); + +extern VP8LFastLog2SlowFunc VP8LFastLog2Slow; +extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow; + +static WEBP_INLINE float VP8LFastLog2(uint32_t v) { + return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v); +} +// Fast calculation of v * log2(v) for integer input. +static WEBP_INLINE float VP8LFastSLog2(uint32_t v) { + return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v); +} + +// ----------------------------------------------------------------------------- +// PrefixEncode() + +// Splitting of distance and length codes into prefixes and +// extra bits. The prefixes are encoded with an entropy code +// while the extra bits are stored just as normal bits. +static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code, + int* const extra_bits) { + const int highest_bit = BitsLog2Floor(--distance); + const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; + *extra_bits = highest_bit - 1; + *code = 2 * highest_bit + second_highest_bit; +} + +static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code, + int* const extra_bits, + int* const extra_bits_value) { + const int highest_bit = BitsLog2Floor(--distance); + const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; + *extra_bits = highest_bit - 1; + *extra_bits_value = distance & ((1 << *extra_bits) - 1); + *code = 2 * highest_bit + second_highest_bit; +} + +#define PREFIX_LOOKUP_IDX_MAX 512 +typedef struct { + int8_t code_; + int8_t extra_bits_; +} VP8LPrefixCode; + +// These tables are derived using VP8LPrefixEncodeNoLUT. +extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX]; +extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX]; +static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code, + int* const extra_bits) { + if (distance < PREFIX_LOOKUP_IDX_MAX) { + const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; + *code = prefix_code.code_; + *extra_bits = prefix_code.extra_bits_; + } else { + VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits); + } +} + +static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code, + int* const extra_bits, + int* const extra_bits_value) { + if (distance < PREFIX_LOOKUP_IDX_MAX) { + const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; + *code = prefix_code.code_; + *extra_bits = prefix_code.extra_bits_; + *extra_bits_value = kPrefixEncodeExtraBitsValue[distance]; + } else { + VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value); + } +} + +// Sum of each component, mod 256. +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +uint32_t VP8LAddPixels(uint32_t a, uint32_t b) { + const uint32_t alpha_and_green = (a & 0xff00ff00u) + (b & 0xff00ff00u); + const uint32_t red_and_blue = (a & 0x00ff00ffu) + (b & 0x00ff00ffu); + return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); +} + +// Difference of each component, mod 256. +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { + const uint32_t alpha_and_green = + 0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u); + const uint32_t red_and_blue = + 0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu); + return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); +} + +//------------------------------------------------------------------------------ +// Transform-related functions used in both encoding and decoding. + +// Macros used to create a batch predictor that iteratively uses a +// one-pixel predictor. + +// The predictor is added to the output pixel (which +// is therefore considered as a residual) to get the final prediction. +#define GENERATE_PREDICTOR_ADD(PREDICTOR, PREDICTOR_ADD) \ +static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int x; \ + assert(upper != NULL); \ + for (x = 0; x < num_pixels; ++x) { \ + const uint32_t pred = (PREDICTOR)(&out[x - 1], upper + x); \ + out[x] = VP8LAddPixels(in[x], pred); \ + } \ +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_LOSSLESS_COMMON_H_ diff --git a/libraries/webp/src/dsp/lossless_enc.c b/libraries/webp/src/dsp/lossless_enc.c new file mode 100644 index 0000000000..997d56c2ad --- /dev/null +++ b/libraries/webp/src/dsp/lossless_enc.c @@ -0,0 +1,954 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transform methods for lossless encoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) + +#include "src/dsp/dsp.h" + +#include +#include +#include +#include "src/dec/vp8li_dec.h" +#include "src/utils/endian_inl_utils.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/dsp/yuv.h" + +// lookup table for small values of log2(int) +const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { + 0.0000000000000000f, 0.0000000000000000f, + 1.0000000000000000f, 1.5849625007211560f, + 2.0000000000000000f, 2.3219280948873621f, + 2.5849625007211560f, 2.8073549220576041f, + 3.0000000000000000f, 3.1699250014423121f, + 3.3219280948873621f, 3.4594316186372973f, + 3.5849625007211560f, 3.7004397181410921f, + 3.8073549220576041f, 3.9068905956085187f, + 4.0000000000000000f, 4.0874628412503390f, + 4.1699250014423121f, 4.2479275134435852f, + 4.3219280948873626f, 4.3923174227787606f, + 4.4594316186372973f, 4.5235619560570130f, + 4.5849625007211560f, 4.6438561897747243f, + 4.7004397181410917f, 4.7548875021634682f, + 4.8073549220576037f, 4.8579809951275718f, + 4.9068905956085187f, 4.9541963103868749f, + 5.0000000000000000f, 5.0443941193584533f, + 5.0874628412503390f, 5.1292830169449663f, + 5.1699250014423121f, 5.2094533656289501f, + 5.2479275134435852f, 5.2854022188622487f, + 5.3219280948873626f, 5.3575520046180837f, + 5.3923174227787606f, 5.4262647547020979f, + 5.4594316186372973f, 5.4918530963296747f, + 5.5235619560570130f, 5.5545888516776376f, + 5.5849625007211560f, 5.6147098441152083f, + 5.6438561897747243f, 5.6724253419714951f, + 5.7004397181410917f, 5.7279204545631987f, + 5.7548875021634682f, 5.7813597135246599f, + 5.8073549220576037f, 5.8328900141647412f, + 5.8579809951275718f, 5.8826430493618415f, + 5.9068905956085187f, 5.9307373375628866f, + 5.9541963103868749f, 5.9772799234999167f, + 6.0000000000000000f, 6.0223678130284543f, + 6.0443941193584533f, 6.0660891904577720f, + 6.0874628412503390f, 6.1085244567781691f, + 6.1292830169449663f, 6.1497471195046822f, + 6.1699250014423121f, 6.1898245588800175f, + 6.2094533656289501f, 6.2288186904958804f, + 6.2479275134435852f, 6.2667865406949010f, + 6.2854022188622487f, 6.3037807481771030f, + 6.3219280948873626f, 6.3398500028846243f, + 6.3575520046180837f, 6.3750394313469245f, + 6.3923174227787606f, 6.4093909361377017f, + 6.4262647547020979f, 6.4429434958487279f, + 6.4594316186372973f, 6.4757334309663976f, + 6.4918530963296747f, 6.5077946401986963f, + 6.5235619560570130f, 6.5391588111080309f, + 6.5545888516776376f, 6.5698556083309478f, + 6.5849625007211560f, 6.5999128421871278f, + 6.6147098441152083f, 6.6293566200796094f, + 6.6438561897747243f, 6.6582114827517946f, + 6.6724253419714951f, 6.6865005271832185f, + 6.7004397181410917f, 6.7142455176661224f, + 6.7279204545631987f, 6.7414669864011464f, + 6.7548875021634682f, 6.7681843247769259f, + 6.7813597135246599f, 6.7944158663501061f, + 6.8073549220576037f, 6.8201789624151878f, + 6.8328900141647412f, 6.8454900509443747f, + 6.8579809951275718f, 6.8703647195834047f, + 6.8826430493618415f, 6.8948177633079437f, + 6.9068905956085187f, 6.9188632372745946f, + 6.9307373375628866f, 6.9425145053392398f, + 6.9541963103868749f, 6.9657842846620869f, + 6.9772799234999167f, 6.9886846867721654f, + 7.0000000000000000f, 7.0112272554232539f, + 7.0223678130284543f, 7.0334230015374501f, + 7.0443941193584533f, 7.0552824355011898f, + 7.0660891904577720f, 7.0768155970508308f, + 7.0874628412503390f, 7.0980320829605263f, + 7.1085244567781691f, 7.1189410727235076f, + 7.1292830169449663f, 7.1395513523987936f, + 7.1497471195046822f, 7.1598713367783890f, + 7.1699250014423121f, 7.1799090900149344f, + 7.1898245588800175f, 7.1996723448363644f, + 7.2094533656289501f, 7.2191685204621611f, + 7.2288186904958804f, 7.2384047393250785f, + 7.2479275134435852f, 7.2573878426926521f, + 7.2667865406949010f, 7.2761244052742375f, + 7.2854022188622487f, 7.2946207488916270f, + 7.3037807481771030f, 7.3128829552843557f, + 7.3219280948873626f, 7.3309168781146167f, + 7.3398500028846243f, 7.3487281542310771f, + 7.3575520046180837f, 7.3663222142458160f, + 7.3750394313469245f, 7.3837042924740519f, + 7.3923174227787606f, 7.4008794362821843f, + 7.4093909361377017f, 7.4178525148858982f, + 7.4262647547020979f, 7.4346282276367245f, + 7.4429434958487279f, 7.4512111118323289f, + 7.4594316186372973f, 7.4676055500829976f, + 7.4757334309663976f, 7.4838157772642563f, + 7.4918530963296747f, 7.4998458870832056f, + 7.5077946401986963f, 7.5156998382840427f, + 7.5235619560570130f, 7.5313814605163118f, + 7.5391588111080309f, 7.5468944598876364f, + 7.5545888516776376f, 7.5622424242210728f, + 7.5698556083309478f, 7.5774288280357486f, + 7.5849625007211560f, 7.5924570372680806f, + 7.5999128421871278f, 7.6073303137496104f, + 7.6147098441152083f, 7.6220518194563764f, + 7.6293566200796094f, 7.6366246205436487f, + 7.6438561897747243f, 7.6510516911789281f, + 7.6582114827517946f, 7.6653359171851764f, + 7.6724253419714951f, 7.6794800995054464f, + 7.6865005271832185f, 7.6934869574993252f, + 7.7004397181410917f, 7.7073591320808825f, + 7.7142455176661224f, 7.7210991887071855f, + 7.7279204545631987f, 7.7347096202258383f, + 7.7414669864011464f, 7.7481928495894605f, + 7.7548875021634682f, 7.7615512324444795f, + 7.7681843247769259f, 7.7747870596011736f, + 7.7813597135246599f, 7.7879025593914317f, + 7.7944158663501061f, 7.8008998999203047f, + 7.8073549220576037f, 7.8137811912170374f, + 7.8201789624151878f, 7.8265484872909150f, + 7.8328900141647412f, 7.8392037880969436f, + 7.8454900509443747f, 7.8517490414160571f, + 7.8579809951275718f, 7.8641861446542797f, + 7.8703647195834047f, 7.8765169465649993f, + 7.8826430493618415f, 7.8887432488982591f, + 7.8948177633079437f, 7.9008668079807486f, + 7.9068905956085187f, 7.9128893362299619f, + 7.9188632372745946f, 7.9248125036057812f, + 7.9307373375628866f, 7.9366379390025709f, + 7.9425145053392398f, 7.9483672315846778f, + 7.9541963103868749f, 7.9600019320680805f, + 7.9657842846620869f, 7.9715435539507719f, + 7.9772799234999167f, 7.9829935746943103f, + 7.9886846867721654f, 7.9943534368588577f +}; + +const float kSLog2Table[LOG_LOOKUP_IDX_MAX] = { + 0.00000000f, 0.00000000f, 2.00000000f, 4.75488750f, + 8.00000000f, 11.60964047f, 15.50977500f, 19.65148445f, + 24.00000000f, 28.52932501f, 33.21928095f, 38.05374781f, + 43.01955001f, 48.10571634f, 53.30296891f, 58.60335893f, + 64.00000000f, 69.48686830f, 75.05865003f, 80.71062276f, + 86.43856190f, 92.23866588f, 98.10749561f, 104.04192499f, + 110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f, + 134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f, + 160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f, + 186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f, + 212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f, + 240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f, + 268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f, + 296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f, + 325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f, + 354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f, + 384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f, + 413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f, + 444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f, + 474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f, + 505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f, + 536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f, + 568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f, + 600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f, + 632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f, + 664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f, + 696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f, + 729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f, + 762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f, + 795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f, + 828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f, + 862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f, + 896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f, + 929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f, + 963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f, + 998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f, + 1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f, + 1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f, + 1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f, + 1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f, + 1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f, + 1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f, + 1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f, + 1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f, + 1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f, + 1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f, + 1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f, + 1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f, + 1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f, + 1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f, + 1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f, + 1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f, + 1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f, + 1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f, + 1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f, + 1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f, + 1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f, + 1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f, + 1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f, + 1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f, + 1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f, + 1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f, + 1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f, + 2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f +}; + +const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = { + { 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1}, + { 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2}, + { 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, + { 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, + { 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, + {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, + {10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + {11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, + {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, + {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, + {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, + {12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, + {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, + {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, + {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, + {13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, +}; + +const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = { + 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126 +}; + +static float FastSLog2Slow_C(uint32_t v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_WITH_CORRECTION_MAX) { +#if !defined(WEBP_HAVE_SLOW_CLZ_CTZ) + // use clz if available + const int log_cnt = BitsLog2Floor(v) - 7; + const uint32_t y = 1 << log_cnt; + int correction = 0; + const float v_f = (float)v; + const uint32_t orig_v = v; + v >>= log_cnt; +#else + int log_cnt = 0; + uint32_t y = 1; + int correction = 0; + const float v_f = (float)v; + const uint32_t orig_v = v; + do { + ++log_cnt; + v = v >> 1; + y = y << 1; + } while (v >= LOG_LOOKUP_IDX_MAX); +#endif + // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 + // Xf = floor(Xf) * (1 + (v % y) / v) + // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) + // The correction factor: log(1 + d) ~ d; for very small d values, so + // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v + // LOG_2_RECIPROCAL ~ 23/16 + correction = (23 * (orig_v & (y - 1))) >> 4; + return v_f * (kLog2Table[v] + log_cnt) + correction; + } else { + return (float)(LOG_2_RECIPROCAL * v * log((double)v)); + } +} + +static float FastLog2Slow_C(uint32_t v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_WITH_CORRECTION_MAX) { +#if !defined(WEBP_HAVE_SLOW_CLZ_CTZ) + // use clz if available + const int log_cnt = BitsLog2Floor(v) - 7; + const uint32_t y = 1 << log_cnt; + const uint32_t orig_v = v; + double log_2; + v >>= log_cnt; +#else + int log_cnt = 0; + uint32_t y = 1; + const uint32_t orig_v = v; + double log_2; + do { + ++log_cnt; + v = v >> 1; + y = y << 1; + } while (v >= LOG_LOOKUP_IDX_MAX); +#endif + log_2 = kLog2Table[v] + log_cnt; + if (orig_v >= APPROX_LOG_MAX) { + // Since the division is still expensive, add this correction factor only + // for large values of 'v'. + const int correction = (23 * (orig_v & (y - 1))) >> 4; + log_2 += (double)correction / orig_v; + } + return (float)log_2; + } else { + return (float)(LOG_2_RECIPROCAL * log((double)v)); + } +} + +//------------------------------------------------------------------------------ +// Methods to calculate Entropy (Shannon). + +// Compute the combined Shanon's entropy for distribution {X} and {X+Y} +static float CombinedShannonEntropy_C(const int X[256], const int Y[256]) { + int i; + float retval = 0.f; + int sumX = 0, sumXY = 0; + for (i = 0; i < 256; ++i) { + const int x = X[i]; + if (x != 0) { + const int xy = x + Y[i]; + sumX += x; + retval -= VP8LFastSLog2(x); + sumXY += xy; + retval -= VP8LFastSLog2(xy); + } else if (Y[i] != 0) { + sumXY += Y[i]; + retval -= VP8LFastSLog2(Y[i]); + } + } + retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); + return retval; +} + +void VP8LBitEntropyInit(VP8LBitEntropy* const entropy) { + entropy->entropy = 0.; + entropy->sum = 0; + entropy->nonzeros = 0; + entropy->max_val = 0; + entropy->nonzero_code = VP8L_NON_TRIVIAL_SYM; +} + +void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, + VP8LBitEntropy* const entropy) { + int i; + + VP8LBitEntropyInit(entropy); + + for (i = 0; i < n; ++i) { + if (array[i] != 0) { + entropy->sum += array[i]; + entropy->nonzero_code = i; + ++entropy->nonzeros; + entropy->entropy -= VP8LFastSLog2(array[i]); + if (entropy->max_val < array[i]) { + entropy->max_val = array[i]; + } + } + } + entropy->entropy += VP8LFastSLog2(entropy->sum); +} + +static WEBP_INLINE void GetEntropyUnrefinedHelper( + uint32_t val, int i, uint32_t* const val_prev, int* const i_prev, + VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) { + const int streak = i - *i_prev; + + // Gather info for the bit entropy. + if (*val_prev != 0) { + bit_entropy->sum += (*val_prev) * streak; + bit_entropy->nonzeros += streak; + bit_entropy->nonzero_code = *i_prev; + bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak; + if (bit_entropy->max_val < *val_prev) { + bit_entropy->max_val = *val_prev; + } + } + + // Gather info for the Huffman cost. + stats->counts[*val_prev != 0] += (streak > 3); + stats->streaks[*val_prev != 0][(streak > 3)] += streak; + + *val_prev = val; + *i_prev = i; +} + +static void GetEntropyUnrefined_C(const uint32_t X[], int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { + int i; + int i_prev = 0; + uint32_t x_prev = X[0]; + + memset(stats, 0, sizeof(*stats)); + VP8LBitEntropyInit(bit_entropy); + + for (i = 1; i < length; ++i) { + const uint32_t x = X[i]; + if (x != x_prev) { + GetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats); + } + } + GetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats); + + bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); +} + +static void GetCombinedEntropyUnrefined_C(const uint32_t X[], + const uint32_t Y[], + int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { + int i = 1; + int i_prev = 0; + uint32_t xy_prev = X[0] + Y[0]; + + memset(stats, 0, sizeof(*stats)); + VP8LBitEntropyInit(bit_entropy); + + for (i = 1; i < length; ++i) { + const uint32_t xy = X[i] + Y[i]; + if (xy != xy_prev) { + GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy, stats); + } + } + GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats); + + bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); +} + +//------------------------------------------------------------------------------ + +void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const int argb = (int)argb_data[i]; + const int green = (argb >> 8) & 0xff; + const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff; + const uint32_t new_b = (((argb >> 0) & 0xff) - green) & 0xff; + argb_data[i] = ((uint32_t)argb & 0xff00ff00u) | (new_r << 16) | new_b; + } +} + +static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, int8_t color) { + return ((int)color_pred * color) >> 5; +} + +static WEBP_INLINE int8_t U32ToS8(uint32_t v) { + return (int8_t)(v & 0xff); +} + +void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data, + int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint32_t argb = data[i]; + const int8_t green = U32ToS8(argb >> 8); + const int8_t red = U32ToS8(argb >> 16); + int new_red = red & 0xff; + int new_blue = argb & 0xff; + new_red -= ColorTransformDelta((int8_t)m->green_to_red_, green); + new_red &= 0xff; + new_blue -= ColorTransformDelta((int8_t)m->green_to_blue_, green); + new_blue -= ColorTransformDelta((int8_t)m->red_to_blue_, red); + new_blue &= 0xff; + data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); + } +} + +static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, + uint32_t argb) { + const int8_t green = U32ToS8(argb >> 8); + int new_red = argb >> 16; + new_red -= ColorTransformDelta((int8_t)green_to_red, green); + return (new_red & 0xff); +} + +static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, + uint8_t red_to_blue, + uint32_t argb) { + const int8_t green = U32ToS8(argb >> 8); + const int8_t red = U32ToS8(argb >> 16); + int new_blue = argb & 0xff; + new_blue -= ColorTransformDelta((int8_t)green_to_blue, green); + new_blue -= ColorTransformDelta((int8_t)red_to_blue, red); + return (new_blue & 0xff); +} + +void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]) { + while (tile_height-- > 0) { + int x; + for (x = 0; x < tile_width; ++x) { + ++histo[TransformColorRed((uint8_t)green_to_red, argb[x])]; + } + argb += stride; + } +} + +void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]) { + while (tile_height-- > 0) { + int x; + for (x = 0; x < tile_width; ++x) { + ++histo[TransformColorBlue((uint8_t)green_to_blue, (uint8_t)red_to_blue, + argb[x])]; + } + argb += stride; + } +} + +//------------------------------------------------------------------------------ + +static int VectorMismatch_C(const uint32_t* const array1, + const uint32_t* const array2, int length) { + int match_len = 0; + + while (match_len < length && array1[match_len] == array2[match_len]) { + ++match_len; + } + return match_len; +} + +// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. +void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits, + uint32_t* dst) { + int x; + if (xbits > 0) { + const int bit_depth = 1 << (3 - xbits); + const int mask = (1 << xbits) - 1; + uint32_t code = 0xff000000; + for (x = 0; x < width; ++x) { + const int xsub = x & mask; + if (xsub == 0) { + code = 0xff000000; + } + code |= row[x] << (8 + bit_depth * xsub); + dst[x >> xbits] = code; + } + } else { + for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8); + } +} + +//------------------------------------------------------------------------------ + +static uint32_t ExtraCost_C(const uint32_t* population, int length) { + int i; + uint32_t cost = population[4] + population[5]; + assert(length % 2 == 0); + for (i = 2; i < length / 2 - 1; ++i) { + cost += i * (population[2 * i + 2] + population[2 * i + 3]); + } + return cost; +} + +static uint32_t ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y, + int length) { + int i; + uint32_t cost = X[4] + Y[4] + X[5] + Y[5]; + assert(length % 2 == 0); + for (i = 2; i < length / 2 - 1; ++i) { + const int xy0 = X[2 * i + 2] + Y[2 * i + 2]; + const int xy1 = X[2 * i + 3] + Y[2 * i + 3]; + cost += i * (xy0 + xy1); + } + return cost; +} + +//------------------------------------------------------------------------------ + +static void AddVector_C(const uint32_t* a, const uint32_t* b, uint32_t* out, + int size) { + int i; + for (i = 0; i < size; ++i) out[i] = a[i] + b[i]; +} + +static void AddVectorEq_C(const uint32_t* a, uint32_t* out, int size) { + int i; + for (i = 0; i < size; ++i) out[i] += a[i]; +} + +#define ADD(X, ARG, LEN) do { \ + if (a->is_used_[X]) { \ + if (b->is_used_[X]) { \ + VP8LAddVector(a->ARG, b->ARG, out->ARG, (LEN)); \ + } else { \ + memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \ + } \ + } else if (b->is_used_[X]) { \ + memcpy(&out->ARG[0], &b->ARG[0], (LEN) * sizeof(out->ARG[0])); \ + } else { \ + memset(&out->ARG[0], 0, (LEN) * sizeof(out->ARG[0])); \ + } \ +} while (0) + +#define ADD_EQ(X, ARG, LEN) do { \ + if (a->is_used_[X]) { \ + if (out->is_used_[X]) { \ + VP8LAddVectorEq(a->ARG, out->ARG, (LEN)); \ + } else { \ + memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \ + } \ + } \ +} while (0) + +void VP8LHistogramAdd(const VP8LHistogram* const a, + const VP8LHistogram* const b, VP8LHistogram* const out) { + int i; + const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); + assert(a->palette_code_bits_ == b->palette_code_bits_); + + if (b != out) { + ADD(0, literal_, literal_size); + ADD(1, red_, NUM_LITERAL_CODES); + ADD(2, blue_, NUM_LITERAL_CODES); + ADD(3, alpha_, NUM_LITERAL_CODES); + ADD(4, distance_, NUM_DISTANCE_CODES); + for (i = 0; i < 5; ++i) { + out->is_used_[i] = (a->is_used_[i] | b->is_used_[i]); + } + } else { + ADD_EQ(0, literal_, literal_size); + ADD_EQ(1, red_, NUM_LITERAL_CODES); + ADD_EQ(2, blue_, NUM_LITERAL_CODES); + ADD_EQ(3, alpha_, NUM_LITERAL_CODES); + ADD_EQ(4, distance_, NUM_DISTANCE_CODES); + for (i = 0; i < 5; ++i) out->is_used_[i] |= a->is_used_[i]; + } +} +#undef ADD +#undef ADD_EQ + +//------------------------------------------------------------------------------ +// Image transforms. + +static void PredictorSub0_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i < num_pixels; ++i) out[i] = VP8LSubPixels(in[i], ARGB_BLACK); + (void)upper; +} + +static void PredictorSub1_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i < num_pixels; ++i) out[i] = VP8LSubPixels(in[i], in[i - 1]); + (void)upper; +} + +// It subtracts the prediction from the input pixel and stores the residual +// in the output pixel. +#define GENERATE_PREDICTOR_SUB(PREDICTOR_I) \ +static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \ + const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int x; \ + assert(upper != NULL); \ + for (x = 0; x < num_pixels; ++x) { \ + const uint32_t pred = \ + VP8LPredictor##PREDICTOR_I##_C(&in[x - 1], upper + x); \ + out[x] = VP8LSubPixels(in[x], pred); \ + } \ +} + +GENERATE_PREDICTOR_SUB(2) +GENERATE_PREDICTOR_SUB(3) +GENERATE_PREDICTOR_SUB(4) +GENERATE_PREDICTOR_SUB(5) +GENERATE_PREDICTOR_SUB(6) +GENERATE_PREDICTOR_SUB(7) +GENERATE_PREDICTOR_SUB(8) +GENERATE_PREDICTOR_SUB(9) +GENERATE_PREDICTOR_SUB(10) +GENERATE_PREDICTOR_SUB(11) +GENERATE_PREDICTOR_SUB(12) +GENERATE_PREDICTOR_SUB(13) + +//------------------------------------------------------------------------------ + +VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; + +VP8LTransformColorFunc VP8LTransformColor; + +VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; +VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; + +VP8LFastLog2SlowFunc VP8LFastLog2Slow; +VP8LFastLog2SlowFunc VP8LFastSLog2Slow; + +VP8LCostFunc VP8LExtraCost; +VP8LCostCombinedFunc VP8LExtraCostCombined; +VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; + +VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined; +VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined; + +VP8LAddVectorFunc VP8LAddVector; +VP8LAddVectorEqFunc VP8LAddVectorEq; + +VP8LVectorMismatchFunc VP8LVectorMismatch; +VP8LBundleColorMapFunc VP8LBundleColorMap; + +VP8LPredictorAddSubFunc VP8LPredictorsSub[16]; +VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16]; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8LEncDspInitSSE2(void); +extern void VP8LEncDspInitSSE41(void); +extern void VP8LEncDspInitNEON(void); +extern void VP8LEncDspInitMIPS32(void); +extern void VP8LEncDspInitMIPSdspR2(void); +extern void VP8LEncDspInitMSA(void); + +WEBP_DSP_INIT_FUNC(VP8LEncDspInit) { + VP8LDspInit(); + +#if !WEBP_NEON_OMIT_C_CODE + VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C; + + VP8LTransformColor = VP8LTransformColor_C; +#endif + + VP8LCollectColorBlueTransforms = VP8LCollectColorBlueTransforms_C; + VP8LCollectColorRedTransforms = VP8LCollectColorRedTransforms_C; + + VP8LFastLog2Slow = FastLog2Slow_C; + VP8LFastSLog2Slow = FastSLog2Slow_C; + + VP8LExtraCost = ExtraCost_C; + VP8LExtraCostCombined = ExtraCostCombined_C; + VP8LCombinedShannonEntropy = CombinedShannonEntropy_C; + + VP8LGetEntropyUnrefined = GetEntropyUnrefined_C; + VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_C; + + VP8LAddVector = AddVector_C; + VP8LAddVectorEq = AddVectorEq_C; + + VP8LVectorMismatch = VectorMismatch_C; + VP8LBundleColorMap = VP8LBundleColorMap_C; + + VP8LPredictorsSub[0] = PredictorSub0_C; + VP8LPredictorsSub[1] = PredictorSub1_C; + VP8LPredictorsSub[2] = PredictorSub2_C; + VP8LPredictorsSub[3] = PredictorSub3_C; + VP8LPredictorsSub[4] = PredictorSub4_C; + VP8LPredictorsSub[5] = PredictorSub5_C; + VP8LPredictorsSub[6] = PredictorSub6_C; + VP8LPredictorsSub[7] = PredictorSub7_C; + VP8LPredictorsSub[8] = PredictorSub8_C; + VP8LPredictorsSub[9] = PredictorSub9_C; + VP8LPredictorsSub[10] = PredictorSub10_C; + VP8LPredictorsSub[11] = PredictorSub11_C; + VP8LPredictorsSub[12] = PredictorSub12_C; + VP8LPredictorsSub[13] = PredictorSub13_C; + VP8LPredictorsSub[14] = PredictorSub0_C; // <- padding security sentinels + VP8LPredictorsSub[15] = PredictorSub0_C; + + VP8LPredictorsSub_C[0] = PredictorSub0_C; + VP8LPredictorsSub_C[1] = PredictorSub1_C; + VP8LPredictorsSub_C[2] = PredictorSub2_C; + VP8LPredictorsSub_C[3] = PredictorSub3_C; + VP8LPredictorsSub_C[4] = PredictorSub4_C; + VP8LPredictorsSub_C[5] = PredictorSub5_C; + VP8LPredictorsSub_C[6] = PredictorSub6_C; + VP8LPredictorsSub_C[7] = PredictorSub7_C; + VP8LPredictorsSub_C[8] = PredictorSub8_C; + VP8LPredictorsSub_C[9] = PredictorSub9_C; + VP8LPredictorsSub_C[10] = PredictorSub10_C; + VP8LPredictorsSub_C[11] = PredictorSub11_C; + VP8LPredictorsSub_C[12] = PredictorSub12_C; + VP8LPredictorsSub_C[13] = PredictorSub13_C; + VP8LPredictorsSub_C[14] = PredictorSub0_C; // <- padding security sentinels + VP8LPredictorsSub_C[15] = PredictorSub0_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8LEncDspInitSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + VP8LEncDspInitSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8LEncDspInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8LEncDspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8LEncDspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8LEncDspInitNEON(); + } +#endif + + assert(VP8LSubtractGreenFromBlueAndRed != NULL); + assert(VP8LTransformColor != NULL); + assert(VP8LCollectColorBlueTransforms != NULL); + assert(VP8LCollectColorRedTransforms != NULL); + assert(VP8LFastLog2Slow != NULL); + assert(VP8LFastSLog2Slow != NULL); + assert(VP8LExtraCost != NULL); + assert(VP8LExtraCostCombined != NULL); + assert(VP8LCombinedShannonEntropy != NULL); + assert(VP8LGetEntropyUnrefined != NULL); + assert(VP8LGetCombinedEntropyUnrefined != NULL); + assert(VP8LAddVector != NULL); + assert(VP8LAddVectorEq != NULL); + assert(VP8LVectorMismatch != NULL); + assert(VP8LBundleColorMap != NULL); + assert(VP8LPredictorsSub[0] != NULL); + assert(VP8LPredictorsSub[1] != NULL); + assert(VP8LPredictorsSub[2] != NULL); + assert(VP8LPredictorsSub[3] != NULL); + assert(VP8LPredictorsSub[4] != NULL); + assert(VP8LPredictorsSub[5] != NULL); + assert(VP8LPredictorsSub[6] != NULL); + assert(VP8LPredictorsSub[7] != NULL); + assert(VP8LPredictorsSub[8] != NULL); + assert(VP8LPredictorsSub[9] != NULL); + assert(VP8LPredictorsSub[10] != NULL); + assert(VP8LPredictorsSub[11] != NULL); + assert(VP8LPredictorsSub[12] != NULL); + assert(VP8LPredictorsSub[13] != NULL); + assert(VP8LPredictorsSub[14] != NULL); + assert(VP8LPredictorsSub[15] != NULL); + assert(VP8LPredictorsSub_C[0] != NULL); + assert(VP8LPredictorsSub_C[1] != NULL); + assert(VP8LPredictorsSub_C[2] != NULL); + assert(VP8LPredictorsSub_C[3] != NULL); + assert(VP8LPredictorsSub_C[4] != NULL); + assert(VP8LPredictorsSub_C[5] != NULL); + assert(VP8LPredictorsSub_C[6] != NULL); + assert(VP8LPredictorsSub_C[7] != NULL); + assert(VP8LPredictorsSub_C[8] != NULL); + assert(VP8LPredictorsSub_C[9] != NULL); + assert(VP8LPredictorsSub_C[10] != NULL); + assert(VP8LPredictorsSub_C[11] != NULL); + assert(VP8LPredictorsSub_C[12] != NULL); + assert(VP8LPredictorsSub_C[13] != NULL); + assert(VP8LPredictorsSub_C[14] != NULL); + assert(VP8LPredictorsSub_C[15] != NULL); +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dsp/lossless_enc_mips32.c b/libraries/webp/src/dsp/lossless_enc_mips32.c new file mode 100644 index 0000000000..e10f12da9d --- /dev/null +++ b/libraries/webp/src/dsp/lossless_enc_mips32.c @@ -0,0 +1,397 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of lossless functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" + +#if defined(WEBP_USE_MIPS32) + +#include +#include +#include +#include + +static float FastSLog2Slow_MIPS32(uint32_t v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_WITH_CORRECTION_MAX) { + uint32_t log_cnt, y, correction; + const int c24 = 24; + const float v_f = (float)v; + uint32_t temp; + + // Xf = 256 = 2^8 + // log_cnt is index of leading one in upper 24 bits + __asm__ volatile( + "clz %[log_cnt], %[v] \n\t" + "addiu %[y], $zero, 1 \n\t" + "subu %[log_cnt], %[c24], %[log_cnt] \n\t" + "sllv %[y], %[y], %[log_cnt] \n\t" + "srlv %[temp], %[v], %[log_cnt] \n\t" + : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y), + [temp]"=r"(temp) + : [c24]"r"(c24), [v]"r"(v) + ); + + // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 + // Xf = floor(Xf) * (1 + (v % y) / v) + // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) + // The correction factor: log(1 + d) ~ d; for very small d values, so + // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v + // LOG_2_RECIPROCAL ~ 23/16 + + // (v % y) = (v % 2^log_cnt) = v & (2^log_cnt - 1) + correction = (23 * (v & (y - 1))) >> 4; + return v_f * (kLog2Table[temp] + log_cnt) + correction; + } else { + return (float)(LOG_2_RECIPROCAL * v * log((double)v)); + } +} + +static float FastLog2Slow_MIPS32(uint32_t v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_WITH_CORRECTION_MAX) { + uint32_t log_cnt, y; + const int c24 = 24; + double log_2; + uint32_t temp; + + __asm__ volatile( + "clz %[log_cnt], %[v] \n\t" + "addiu %[y], $zero, 1 \n\t" + "subu %[log_cnt], %[c24], %[log_cnt] \n\t" + "sllv %[y], %[y], %[log_cnt] \n\t" + "srlv %[temp], %[v], %[log_cnt] \n\t" + : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y), + [temp]"=r"(temp) + : [c24]"r"(c24), [v]"r"(v) + ); + + log_2 = kLog2Table[temp] + log_cnt; + if (v >= APPROX_LOG_MAX) { + // Since the division is still expensive, add this correction factor only + // for large values of 'v'. + + const uint32_t correction = (23 * (v & (y - 1))) >> 4; + log_2 += (double)correction / v; + } + return (float)log_2; + } else { + return (float)(LOG_2_RECIPROCAL * log((double)v)); + } +} + +// C version of this function: +// int i = 0; +// int64_t cost = 0; +// const uint32_t* pop = &population[4]; +// const uint32_t* LoopEnd = &population[length]; +// while (pop != LoopEnd) { +// ++i; +// cost += i * *pop; +// cost += i * *(pop + 1); +// pop += 2; +// } +// return cost; +static uint32_t ExtraCost_MIPS32(const uint32_t* const population, int length) { + int i, temp0, temp1; + const uint32_t* pop = &population[4]; + const uint32_t* const LoopEnd = &population[length]; + + __asm__ volatile( + "mult $zero, $zero \n\t" + "xor %[i], %[i], %[i] \n\t" + "beq %[pop], %[LoopEnd], 2f \n\t" + "1: \n\t" + "lw %[temp0], 0(%[pop]) \n\t" + "lw %[temp1], 4(%[pop]) \n\t" + "addiu %[i], %[i], 1 \n\t" + "addiu %[pop], %[pop], 8 \n\t" + "madd %[i], %[temp0] \n\t" + "madd %[i], %[temp1] \n\t" + "bne %[pop], %[LoopEnd], 1b \n\t" + "2: \n\t" + "mfhi %[temp0] \n\t" + "mflo %[temp1] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [i]"=&r"(i), [pop]"+r"(pop) + : [LoopEnd]"r"(LoopEnd) + : "memory", "hi", "lo" + ); + + return ((int64_t)temp0 << 32 | temp1); +} + +// C version of this function: +// int i = 0; +// int64_t cost = 0; +// const uint32_t* pX = &X[4]; +// const uint32_t* pY = &Y[4]; +// const uint32_t* LoopEnd = &X[length]; +// while (pX != LoopEnd) { +// const uint32_t xy0 = *pX + *pY; +// const uint32_t xy1 = *(pX + 1) + *(pY + 1); +// ++i; +// cost += i * xy0; +// cost += i * xy1; +// pX += 2; +// pY += 2; +// } +// return cost; +static uint32_t ExtraCostCombined_MIPS32(const uint32_t* const X, + const uint32_t* const Y, int length) { + int i, temp0, temp1, temp2, temp3; + const uint32_t* pX = &X[4]; + const uint32_t* pY = &Y[4]; + const uint32_t* const LoopEnd = &X[length]; + + __asm__ volatile( + "mult $zero, $zero \n\t" + "xor %[i], %[i], %[i] \n\t" + "beq %[pX], %[LoopEnd], 2f \n\t" + "1: \n\t" + "lw %[temp0], 0(%[pX]) \n\t" + "lw %[temp1], 0(%[pY]) \n\t" + "lw %[temp2], 4(%[pX]) \n\t" + "lw %[temp3], 4(%[pY]) \n\t" + "addiu %[i], %[i], 1 \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addiu %[pX], %[pX], 8 \n\t" + "addiu %[pY], %[pY], 8 \n\t" + "madd %[i], %[temp0] \n\t" + "madd %[i], %[temp2] \n\t" + "bne %[pX], %[LoopEnd], 1b \n\t" + "2: \n\t" + "mfhi %[temp0] \n\t" + "mflo %[temp1] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [i]"=&r"(i), [pX]"+r"(pX), [pY]"+r"(pY) + : [LoopEnd]"r"(LoopEnd) + : "memory", "hi", "lo" + ); + + return ((int64_t)temp0 << 32 | temp1); +} + +#define HUFFMAN_COST_PASS \ + __asm__ volatile( \ + "sll %[temp1], %[temp0], 3 \n\t" \ + "addiu %[temp3], %[streak], -3 \n\t" \ + "addu %[temp2], %[pstreaks], %[temp1] \n\t" \ + "blez %[temp3], 1f \n\t" \ + "srl %[temp1], %[temp1], 1 \n\t" \ + "addu %[temp3], %[pcnts], %[temp1] \n\t" \ + "lw %[temp0], 4(%[temp2]) \n\t" \ + "lw %[temp1], 0(%[temp3]) \n\t" \ + "addu %[temp0], %[temp0], %[streak] \n\t" \ + "addiu %[temp1], %[temp1], 1 \n\t" \ + "sw %[temp0], 4(%[temp2]) \n\t" \ + "sw %[temp1], 0(%[temp3]) \n\t" \ + "b 2f \n\t" \ + "1: \n\t" \ + "lw %[temp0], 0(%[temp2]) \n\t" \ + "addu %[temp0], %[temp0], %[streak] \n\t" \ + "sw %[temp0], 0(%[temp2]) \n\t" \ + "2: \n\t" \ + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ + [temp3]"=&r"(temp3), [temp0]"+r"(temp0) \ + : [pstreaks]"r"(pstreaks), [pcnts]"r"(pcnts), \ + [streak]"r"(streak) \ + : "memory" \ + ); + +// Returns the various RLE counts +static WEBP_INLINE void GetEntropyUnrefinedHelper( + uint32_t val, int i, uint32_t* const val_prev, int* const i_prev, + VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) { + int* const pstreaks = &stats->streaks[0][0]; + int* const pcnts = &stats->counts[0]; + int temp0, temp1, temp2, temp3; + const int streak = i - *i_prev; + + // Gather info for the bit entropy. + if (*val_prev != 0) { + bit_entropy->sum += (*val_prev) * streak; + bit_entropy->nonzeros += streak; + bit_entropy->nonzero_code = *i_prev; + bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak; + if (bit_entropy->max_val < *val_prev) { + bit_entropy->max_val = *val_prev; + } + } + + // Gather info for the Huffman cost. + temp0 = (*val_prev != 0); + HUFFMAN_COST_PASS + + *val_prev = val; + *i_prev = i; +} + +static void GetEntropyUnrefined_MIPS32(const uint32_t X[], int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { + int i; + int i_prev = 0; + uint32_t x_prev = X[0]; + + memset(stats, 0, sizeof(*stats)); + VP8LBitEntropyInit(bit_entropy); + + for (i = 1; i < length; ++i) { + const uint32_t x = X[i]; + if (x != x_prev) { + GetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats); + } + } + GetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats); + + bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); +} + +static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[], + const uint32_t Y[], + int length, + VP8LBitEntropy* const entropy, + VP8LStreaks* const stats) { + int i = 1; + int i_prev = 0; + uint32_t xy_prev = X[0] + Y[0]; + + memset(stats, 0, sizeof(*stats)); + VP8LBitEntropyInit(entropy); + + for (i = 1; i < length; ++i) { + const uint32_t xy = X[i] + Y[i]; + if (xy != xy_prev) { + GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, entropy, stats); + } + } + GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, entropy, stats); + + entropy->entropy += VP8LFastSLog2(entropy->sum); +} + +#define ASM_START \ + __asm__ volatile( \ + ".set push \n\t" \ + ".set at \n\t" \ + ".set macro \n\t" \ + "1: \n\t" + +// P2 = P0 + P1 +// A..D - offsets +// E - temp variable to tell macro +// if pointer should be incremented +// literal_ and successive histograms could be unaligned +// so we must use ulw and usw +#define ADD_TO_OUT(A, B, C, D, E, P0, P1, P2) \ + "ulw %[temp0], " #A "(%[" #P0 "]) \n\t" \ + "ulw %[temp1], " #B "(%[" #P0 "]) \n\t" \ + "ulw %[temp2], " #C "(%[" #P0 "]) \n\t" \ + "ulw %[temp3], " #D "(%[" #P0 "]) \n\t" \ + "ulw %[temp4], " #A "(%[" #P1 "]) \n\t" \ + "ulw %[temp5], " #B "(%[" #P1 "]) \n\t" \ + "ulw %[temp6], " #C "(%[" #P1 "]) \n\t" \ + "ulw %[temp7], " #D "(%[" #P1 "]) \n\t" \ + "addu %[temp4], %[temp4], %[temp0] \n\t" \ + "addu %[temp5], %[temp5], %[temp1] \n\t" \ + "addu %[temp6], %[temp6], %[temp2] \n\t" \ + "addu %[temp7], %[temp7], %[temp3] \n\t" \ + "addiu %[" #P0 "], %[" #P0 "], 16 \n\t" \ + ".if " #E " == 1 \n\t" \ + "addiu %[" #P1 "], %[" #P1 "], 16 \n\t" \ + ".endif \n\t" \ + "usw %[temp4], " #A "(%[" #P2 "]) \n\t" \ + "usw %[temp5], " #B "(%[" #P2 "]) \n\t" \ + "usw %[temp6], " #C "(%[" #P2 "]) \n\t" \ + "usw %[temp7], " #D "(%[" #P2 "]) \n\t" \ + "addiu %[" #P2 "], %[" #P2 "], 16 \n\t" \ + "bne %[" #P0 "], %[LoopEnd], 1b \n\t" \ + ".set pop \n\t" \ + +#define ASM_END_COMMON_0 \ + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \ + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), \ + [pa]"+r"(pa), [pout]"+r"(pout) + +#define ASM_END_COMMON_1 \ + : [LoopEnd]"r"(LoopEnd) \ + : "memory", "at" \ + ); + +#define ASM_END_0 \ + ASM_END_COMMON_0 \ + , [pb]"+r"(pb) \ + ASM_END_COMMON_1 + +#define ASM_END_1 \ + ASM_END_COMMON_0 \ + ASM_END_COMMON_1 + +static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb, + uint32_t* pout, int size) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + const int end = ((size) / 4) * 4; + const uint32_t* const LoopEnd = pa + end; + int i; + ASM_START + ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) + ASM_END_0 + for (i = 0; i < size - end; ++i) pout[i] = pa[i] + pb[i]; +} + +static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + const int end = ((size) / 4) * 4; + const uint32_t* const LoopEnd = pa + end; + int i; + ASM_START + ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) + ASM_END_1 + for (i = 0; i < size - end; ++i) pout[i] += pa[i]; +} + +#undef ASM_END_1 +#undef ASM_END_0 +#undef ASM_END_COMMON_1 +#undef ASM_END_COMMON_0 +#undef ADD_TO_OUT +#undef ASM_START + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) { + VP8LFastSLog2Slow = FastSLog2Slow_MIPS32; + VP8LFastLog2Slow = FastLog2Slow_MIPS32; + VP8LExtraCost = ExtraCost_MIPS32; + VP8LExtraCostCombined = ExtraCostCombined_MIPS32; + VP8LGetEntropyUnrefined = GetEntropyUnrefined_MIPS32; + VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_MIPS32; + VP8LAddVector = AddVector_MIPS32; + VP8LAddVectorEq = AddVectorEq_MIPS32; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/libraries/webp/src/dsp/lossless_enc_mips_dsp_r2.c b/libraries/webp/src/dsp/lossless_enc_mips_dsp_r2.c new file mode 100644 index 0000000000..5855e6ae15 --- /dev/null +++ b/libraries/webp/src/dsp/lossless_enc_mips_dsp_r2.c @@ -0,0 +1,281 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transform methods for lossless encoder. +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/lossless.h" + +static void SubtractGreenFromBlueAndRed_MIPSdspR2(uint32_t* argb_data, + int num_pixels) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + uint32_t* const p_loop1_end = argb_data + (num_pixels & ~3); + uint32_t* const p_loop2_end = p_loop1_end + (num_pixels & 3); + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[argb_data], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[argb_data]) \n\t" + "lw %[temp1], 4(%[argb_data]) \n\t" + "lw %[temp2], 8(%[argb_data]) \n\t" + "lw %[temp3], 12(%[argb_data]) \n\t" + "ext %[temp4], %[temp0], 8, 8 \n\t" + "ext %[temp5], %[temp1], 8, 8 \n\t" + "ext %[temp6], %[temp2], 8, 8 \n\t" + "ext %[temp7], %[temp3], 8, 8 \n\t" + "addiu %[argb_data], %[argb_data], 16 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "replv.ph %[temp5], %[temp5] \n\t" + "replv.ph %[temp6], %[temp6] \n\t" + "replv.ph %[temp7], %[temp7] \n\t" + "subu.qb %[temp0], %[temp0], %[temp4] \n\t" + "subu.qb %[temp1], %[temp1], %[temp5] \n\t" + "subu.qb %[temp2], %[temp2], %[temp6] \n\t" + "subu.qb %[temp3], %[temp3], %[temp7] \n\t" + "sw %[temp0], -16(%[argb_data]) \n\t" + "sw %[temp1], -12(%[argb_data]) \n\t" + "sw %[temp2], -8(%[argb_data]) \n\t" + "bne %[argb_data], %[p_loop1_end], 0b \n\t" + " sw %[temp3], -4(%[argb_data]) \n\t" + "3: \n\t" + "beq %[argb_data], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[argb_data]) \n\t" + "addiu %[argb_data], %[argb_data], 4 \n\t" + "ext %[temp4], %[temp0], 8, 8 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "subu.qb %[temp0], %[temp0], %[temp4] \n\t" + "bne %[argb_data], %[p_loop2_end], 1b \n\t" + " sw %[temp0], -4(%[argb_data]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [argb_data]"+&r"(argb_data), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), + [temp7]"=&r"(temp7) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, + int8_t color) { + return (uint32_t)((int)(color_pred) * color) >> 5; +} + +static void TransformColor_MIPSdspR2(const VP8LMultipliers* const m, + uint32_t* data, int num_pixels) { + int temp0, temp1, temp2, temp3, temp4, temp5; + uint32_t argb, argb1, new_red, new_red1; + const uint32_t G_to_R = m->green_to_red_; + const uint32_t G_to_B = m->green_to_blue_; + const uint32_t R_to_B = m->red_to_blue_; + uint32_t* const p_loop_end = data + (num_pixels & ~1); + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[data], %[p_loop_end], 1f \n\t" + " nop \n\t" + "replv.ph %[temp0], %[G_to_R] \n\t" + "replv.ph %[temp1], %[G_to_B] \n\t" + "replv.ph %[temp2], %[R_to_B] \n\t" + "shll.ph %[temp0], %[temp0], 8 \n\t" + "shll.ph %[temp1], %[temp1], 8 \n\t" + "shll.ph %[temp2], %[temp2], 8 \n\t" + "shra.ph %[temp0], %[temp0], 8 \n\t" + "shra.ph %[temp1], %[temp1], 8 \n\t" + "shra.ph %[temp2], %[temp2], 8 \n\t" + "0: \n\t" + "lw %[argb], 0(%[data]) \n\t" + "lw %[argb1], 4(%[data]) \n\t" + "lhu %[new_red], 2(%[data]) \n\t" + "lhu %[new_red1], 6(%[data]) \n\t" + "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t" + "precr.qb.ph %[temp4], %[argb], %[argb1] \n\t" + "preceu.ph.qbra %[temp3], %[temp3] \n\t" + "preceu.ph.qbla %[temp4], %[temp4] \n\t" + "shll.ph %[temp3], %[temp3], 8 \n\t" + "shll.ph %[temp4], %[temp4], 8 \n\t" + "shra.ph %[temp3], %[temp3], 8 \n\t" + "shra.ph %[temp4], %[temp4], 8 \n\t" + "mul.ph %[temp5], %[temp3], %[temp0] \n\t" + "mul.ph %[temp3], %[temp3], %[temp1] \n\t" + "mul.ph %[temp4], %[temp4], %[temp2] \n\t" + "addiu %[data], %[data], 8 \n\t" + "ins %[new_red1], %[new_red], 16, 16 \n\t" + "ins %[argb1], %[argb], 16, 16 \n\t" + "shra.ph %[temp5], %[temp5], 5 \n\t" + "shra.ph %[temp3], %[temp3], 5 \n\t" + "shra.ph %[temp4], %[temp4], 5 \n\t" + "subu.ph %[new_red1], %[new_red1], %[temp5] \n\t" + "subu.ph %[argb1], %[argb1], %[temp3] \n\t" + "preceu.ph.qbra %[temp5], %[new_red1] \n\t" + "subu.ph %[argb1], %[argb1], %[temp4] \n\t" + "preceu.ph.qbra %[temp3], %[argb1] \n\t" + "sb %[temp5], -2(%[data]) \n\t" + "sb %[temp3], -4(%[data]) \n\t" + "sra %[temp5], %[temp5], 16 \n\t" + "sra %[temp3], %[temp3], 16 \n\t" + "sb %[temp5], -6(%[data]) \n\t" + "bne %[data], %[p_loop_end], 0b \n\t" + " sb %[temp3], -8(%[data]) \n\t" + "1: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [new_red1]"=&r"(new_red1), [new_red]"=&r"(new_red), + [argb]"=&r"(argb), [argb1]"=&r"(argb1), [data]"+&r"(data) + : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B), + [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end) + : "memory", "hi", "lo" + ); + + if (num_pixels & 1) { + const uint32_t argb_ = data[0]; + const uint32_t green = argb_ >> 8; + const uint32_t red = argb_ >> 16; + uint32_t new_blue = argb_; + new_red = red; + new_red -= ColorTransformDelta(m->green_to_red_, green); + new_red &= 0xff; + new_blue -= ColorTransformDelta(m->green_to_blue_, green); + new_blue -= ColorTransformDelta(m->red_to_blue_, red); + new_blue &= 0xff; + data[0] = (argb_ & 0xff00ff00u) | (new_red << 16) | (new_blue); + } +} + +static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, + uint8_t red_to_blue, + uint32_t argb) { + const uint32_t green = argb >> 8; + const uint32_t red = argb >> 16; + uint8_t new_blue = argb; + new_blue -= ColorTransformDelta(green_to_blue, green); + new_blue -= ColorTransformDelta(red_to_blue, red); + return (new_blue & 0xff); +} + +static void CollectColorBlueTransforms_MIPSdspR2(const uint32_t* argb, + int stride, + int tile_width, + int tile_height, + int green_to_blue, + int red_to_blue, + int histo[]) { + const int rtb = (red_to_blue << 16) | (red_to_blue & 0xffff); + const int gtb = (green_to_blue << 16) | (green_to_blue & 0xffff); + const uint32_t mask = 0xff00ffu; + while (tile_height-- > 0) { + int x; + const uint32_t* p_argb = argb; + argb += stride; + for (x = 0; x < (tile_width >> 1); ++x) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + __asm__ volatile ( + "lw %[temp0], 0(%[p_argb]) \n\t" + "lw %[temp1], 4(%[p_argb]) \n\t" + "precr.qb.ph %[temp2], %[temp0], %[temp1] \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "shra.ph %[temp2], %[temp2], 8 \n\t" + "shra.ph %[temp3], %[temp1], 8 \n\t" + "mul.ph %[temp5], %[temp2], %[rtb] \n\t" + "mul.ph %[temp6], %[temp3], %[gtb] \n\t" + "and %[temp4], %[temp1], %[mask] \n\t" + "addiu %[p_argb], %[p_argb], 8 \n\t" + "shra.ph %[temp5], %[temp5], 5 \n\t" + "shra.ph %[temp6], %[temp6], 5 \n\t" + "subu.qb %[temp2], %[temp4], %[temp5] \n\t" + "subu.qb %[temp2], %[temp2], %[temp6] \n\t" + : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), + [temp5]"=&r"(temp5), [temp6]"=&r"(temp6) + : [rtb]"r"(rtb), [gtb]"r"(gtb), [mask]"r"(mask) + : "memory", "hi", "lo" + ); + ++histo[(uint8_t)(temp2 >> 16)]; + ++histo[(uint8_t)temp2]; + } + if (tile_width & 1) { + ++histo[TransformColorBlue(green_to_blue, red_to_blue, *p_argb)]; + } + } +} + +static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, + uint32_t argb) { + const uint32_t green = argb >> 8; + uint32_t new_red = argb >> 16; + new_red -= ColorTransformDelta(green_to_red, green); + return (new_red & 0xff); +} + +static void CollectColorRedTransforms_MIPSdspR2(const uint32_t* argb, + int stride, + int tile_width, + int tile_height, + int green_to_red, + int histo[]) { + const int gtr = (green_to_red << 16) | (green_to_red & 0xffff); + while (tile_height-- > 0) { + int x; + const uint32_t* p_argb = argb; + argb += stride; + for (x = 0; x < (tile_width >> 1); ++x) { + int temp0, temp1, temp2, temp3, temp4; + __asm__ volatile ( + "lw %[temp0], 0(%[p_argb]) \n\t" + "lw %[temp1], 4(%[p_argb]) \n\t" + "precrq.ph.w %[temp4], %[temp0], %[temp1] \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "shra.ph %[temp3], %[temp1], 8 \n\t" + "mul.ph %[temp2], %[temp3], %[gtr] \n\t" + "addiu %[p_argb], %[p_argb], 8 \n\t" + "shra.ph %[temp2], %[temp2], 5 \n\t" + "subu.qb %[temp2], %[temp4], %[temp2] \n\t" + : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4) + : [gtr]"r"(gtr) + : "memory", "hi", "lo" + ); + ++histo[(uint8_t)(temp2 >> 16)]; + ++histo[(uint8_t)temp2]; + } + if (tile_width & 1) { + ++histo[TransformColorRed(green_to_red, *p_argb)]; + } + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPSdspR2(void) { + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_MIPSdspR2; + VP8LTransformColor = TransformColor_MIPSdspR2; + VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_MIPSdspR2; + VP8LCollectColorRedTransforms = CollectColorRedTransforms_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/lossless_enc_msa.c b/libraries/webp/src/dsp/lossless_enc_msa.c new file mode 100644 index 0000000000..600dddfb59 --- /dev/null +++ b/libraries/webp/src/dsp/lossless_enc_msa.c @@ -0,0 +1,148 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA variant of Image transform methods for lossless encoder. +// +// Authors: Prashant Patil (Prashant.Patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/lossless.h" +#include "src/dsp/msa_macro.h" + +#define TRANSFORM_COLOR_8(src0, src1, dst0, dst1, c0, c1, mask0, mask1) do { \ + v8i16 g0, g1, t0, t1, t2, t3; \ + v4i32 t4, t5; \ + VSHF_B2_SH(src0, src0, src1, src1, mask0, mask0, g0, g1); \ + DOTP_SB2_SH(g0, g1, c0, c0, t0, t1); \ + SRAI_H2_SH(t0, t1, 5); \ + t0 = __msa_subv_h((v8i16)src0, t0); \ + t1 = __msa_subv_h((v8i16)src1, t1); \ + t4 = __msa_srli_w((v4i32)src0, 16); \ + t5 = __msa_srli_w((v4i32)src1, 16); \ + DOTP_SB2_SH(t4, t5, c1, c1, t2, t3); \ + SRAI_H2_SH(t2, t3, 5); \ + SUB2(t0, t2, t1, t3, t0, t1); \ + VSHF_B2_UB(src0, t0, src1, t1, mask1, mask1, dst0, dst1); \ +} while (0) + +#define TRANSFORM_COLOR_4(src, dst, c0, c1, mask0, mask1) do { \ + const v16i8 g0 = VSHF_SB(src, src, mask0); \ + v8i16 t0 = __msa_dotp_s_h(c0, g0); \ + v8i16 t1; \ + v4i32 t2; \ + t0 = SRAI_H(t0, 5); \ + t0 = __msa_subv_h((v8i16)src, t0); \ + t2 = __msa_srli_w((v4i32)src, 16); \ + t1 = __msa_dotp_s_h(c1, (v16i8)t2); \ + t1 = SRAI_H(t1, 5); \ + t0 = t0 - t1; \ + dst = VSHF_UB(src, t0, mask1); \ +} while (0) + +static void TransformColor_MSA(const VP8LMultipliers* const m, uint32_t* data, + int num_pixels) { + v16u8 src0, dst0; + const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ | + (m->green_to_red_ << 16)); + const v16i8 r2b = (v16i8)__msa_fill_w(m->red_to_blue_); + const v16u8 mask0 = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, + 13, 255, 13, 255 }; + const v16u8 mask1 = { 16, 1, 18, 3, 20, 5, 22, 7, 24, 9, 26, 11, + 28, 13, 30, 15 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1; + LD_UB2(data, 4, src0, src1); + TRANSFORM_COLOR_8(src0, src1, dst0, dst1, g2br, r2b, mask0, mask1); + ST_UB2(dst0, dst1, data, 4); + data += 8; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(data); + TRANSFORM_COLOR_4(src0, dst0, g2br, r2b, mask0, mask1); + ST_UB(dst0, data); + data += 4; + num_pixels -= 4; + } + if (num_pixels > 0) { + src0 = LD_UB(data); + TRANSFORM_COLOR_4(src0, dst0, g2br, r2b, mask0, mask1); + if (num_pixels == 3) { + const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); + const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2); + SD(pix_d, data + 0); + SW(pix_w, data + 2); + } else if (num_pixels == 2) { + const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); + SD(pix_d, data); + } else { + const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 0); + SW(pix_w, data); + } + } + } +} + +static void SubtractGreenFromBlueAndRed_MSA(uint32_t* argb_data, + int num_pixels) { + int i; + uint8_t* ptemp_data = (uint8_t*)argb_data; + v16u8 src0, dst0, tmp0; + const v16u8 mask = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, + 13, 255, 13, 255 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1, tmp1; + LD_UB2(ptemp_data, 16, src0, src1); + VSHF_B2_UB(src0, src1, src1, src0, mask, mask, tmp0, tmp1); + SUB2(src0, tmp0, src1, tmp1, dst0, dst1); + ST_UB2(dst0, dst1, ptemp_data, 16); + ptemp_data += 8 * 4; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(ptemp_data); + tmp0 = VSHF_UB(src0, src0, mask); + dst0 = src0 - tmp0; + ST_UB(dst0, ptemp_data); + ptemp_data += 4 * 4; + num_pixels -= 4; + } + for (i = 0; i < num_pixels; i++) { + const uint8_t b = ptemp_data[0]; + const uint8_t g = ptemp_data[1]; + const uint8_t r = ptemp_data[2]; + ptemp_data[0] = (b - g) & 0xff; + ptemp_data[2] = (r - g) & 0xff; + ptemp_data += 4; + } + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMSA(void) { + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_MSA; + VP8LTransformColor = TransformColor_MSA; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8LEncDspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/libraries/webp/src/dsp/lossless_enc_neon.c b/libraries/webp/src/dsp/lossless_enc_neon.c new file mode 100644 index 0000000000..e32c7961a2 --- /dev/null +++ b/libraries/webp/src/dsp/lossless_enc_neon.c @@ -0,0 +1,144 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON variant of methods for lossless encoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include + +#include "src/dsp/lossless.h" +#include "src/dsp/neon.h" + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use +// non-standard versions there. +#if defined(__APPLE__) && WEBP_AARCH64 && \ + defined(__apple_build_version__) && (__apple_build_version__< 6020037) +#define USE_VTBLQ +#endif + +#ifdef USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[16] = { + 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 +}; + +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x16_t shuffle) { + return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), + vtbl1q_u8(argb, vget_high_u8(shuffle))); +} +#else // !USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; + +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x8_t shuffle) { + return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), + vtbl1_u8(vget_high_u8(argb), shuffle)); +} +#endif // USE_VTBLQ + +static void SubtractGreenFromBlueAndRed_NEON(uint32_t* argb_data, + int num_pixels) { + const uint32_t* const end = argb_data + (num_pixels & ~3); +#ifdef USE_VTBLQ + const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); +#else + const uint8x8_t shuffle = vld1_u8(kGreenShuffle); +#endif + for (; argb_data < end; argb_data += 4) { + const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); + const uint8x16_t greens = DoGreenShuffle_NEON(argb, shuffle); + vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens)); + } + // fallthrough and finish off with plain-C + VP8LSubtractGreenFromBlueAndRed_C(argb_data, num_pixels & 3); +} + +//------------------------------------------------------------------------------ +// Color Transform + +static void TransformColor_NEON(const VP8LMultipliers* const m, + uint32_t* argb_data, int num_pixels) { + // sign-extended multiplying constants, pre-shifted by 6. +#define CST(X) (((int16_t)(m->X << 8)) >> 6) + const int16_t rb[8] = { + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_) + }; + const int16x8_t mults_rb = vld1q_s16(rb); + const int16_t b2[8] = { + 0, CST(red_to_blue_), 0, CST(red_to_blue_), + 0, CST(red_to_blue_), 0, CST(red_to_blue_), + }; + const int16x8_t mults_b2 = vld1q_s16(b2); +#undef CST +#ifdef USE_VTBLQ + static const uint8_t kg0g0[16] = { + 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13 + }; + const uint8x16_t shuffle = vld1q_u8(kg0g0); +#else + static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 }; + const uint8x8_t shuffle = vld1_u8(k0g0g); +#endif + const uint32x4_t mask_rb = vdupq_n_u32(0x00ff00ffu); // red-blue masks + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i)); + // 0 g 0 g + const uint8x16_t greens = DoGreenShuffle_NEON(in, shuffle); + // x dr x db1 + const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); + // r 0 b 0 + const int16x8_t B = vshlq_n_s16(vreinterpretq_s16_u8(in), 8); + // x db2 0 0 + const int16x8_t C = vqdmulhq_s16(B, mults_b2); + // 0 0 x db2 + const uint32x4_t D = vshrq_n_u32(vreinterpretq_u32_s16(C), 16); + // x dr x db + const int8x16_t E = vaddq_s8(vreinterpretq_s8_u32(D), + vreinterpretq_s8_s16(A)); + // 0 dr 0 db + const uint32x4_t F = vandq_u32(vreinterpretq_u32_s8(E), mask_rb); + const int8x16_t out = vsubq_s8(vreinterpretq_s8_u8(in), + vreinterpretq_s8_u32(F)); + vst1q_s8((int8_t*)(argb_data + i), out); + } + // fallthrough and finish off with plain-C + VP8LTransformColor_C(m, argb_data + i, num_pixels - i); +} + +#undef USE_VTBLQ + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitNEON(void) { + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_NEON; + VP8LTransformColor = TransformColor_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8LEncDspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/lossless_enc_sse2.c b/libraries/webp/src/dsp/lossless_enc_sse2.c new file mode 100644 index 0000000000..66cbaab772 --- /dev/null +++ b/libraries/webp/src/dsp/lossless_enc_sse2.c @@ -0,0 +1,669 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 variant of methods for lossless encoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) +#include +#include +#include "src/dsp/lossless.h" +#include "src/dsp/common_sse2.h" +#include "src/dsp/lossless_common.h" + +// For sign-extended multiplying constants, pre-shifted by 5: +#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5) + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +static void SubtractGreenFromBlueAndRed_SSE2(uint32_t* argb_data, + int num_pixels) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb + const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g + const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); + const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g + const __m128i out = _mm_sub_epi8(in, C); + _mm_storeu_si128((__m128i*)&argb_data[i], out); + } + // fallthrough and finish off with plain-C + if (i != num_pixels) { + VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i); + } +} + +//------------------------------------------------------------------------------ +// Color Transform + +#define MK_CST_16(HI, LO) \ + _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff))) + +static void TransformColor_SSE2(const VP8LMultipliers* const m, + uint32_t* argb_data, int num_pixels) { + const __m128i mults_rb = MK_CST_16(CST_5b(m->green_to_red_), + CST_5b(m->green_to_blue_)); + const __m128i mults_b2 = MK_CST_16(CST_5b(m->red_to_blue_), 0); + const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00); // alpha-green masks + const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb + const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0 + const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); + const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0 + const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1 + const __m128i E = _mm_slli_epi16(in, 8); // r 0 b 0 + const __m128i F = _mm_mulhi_epi16(E, mults_b2); // x db2 0 0 + const __m128i G = _mm_srli_epi32(F, 16); // 0 0 x db2 + const __m128i H = _mm_add_epi8(G, D); // x dr x db + const __m128i I = _mm_and_si128(H, mask_rb); // 0 dr 0 db + const __m128i out = _mm_sub_epi8(in, I); + _mm_storeu_si128((__m128i*)&argb_data[i], out); + } + // fallthrough and finish off with plain-C + if (i != num_pixels) { + VP8LTransformColor_C(m, argb_data + i, num_pixels - i); + } +} + +//------------------------------------------------------------------------------ +#define SPAN 8 +static void CollectColorBlueTransforms_SSE2(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]) { + const __m128i mults_r = MK_CST_16(CST_5b(red_to_blue), 0); + const __m128i mults_g = MK_CST_16(0, CST_5b(green_to_blue)); + const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask + const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask + int y; + for (y = 0; y < tile_height; ++y) { + const uint32_t* const src = argb + y * stride; + int i, x; + for (x = 0; x + SPAN <= tile_width; x += SPAN) { + uint16_t values[SPAN]; + const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]); + const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]); + const __m128i A0 = _mm_slli_epi16(in0, 8); // r 0 | b 0 + const __m128i A1 = _mm_slli_epi16(in1, 8); + const __m128i B0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0 + const __m128i B1 = _mm_and_si128(in1, mask_g); + const __m128i C0 = _mm_mulhi_epi16(A0, mults_r); // x db | 0 0 + const __m128i C1 = _mm_mulhi_epi16(A1, mults_r); + const __m128i D0 = _mm_mulhi_epi16(B0, mults_g); // 0 0 | x db + const __m128i D1 = _mm_mulhi_epi16(B1, mults_g); + const __m128i E0 = _mm_sub_epi8(in0, D0); // x x | x b' + const __m128i E1 = _mm_sub_epi8(in1, D1); + const __m128i F0 = _mm_srli_epi32(C0, 16); // 0 0 | x db + const __m128i F1 = _mm_srli_epi32(C1, 16); + const __m128i G0 = _mm_sub_epi8(E0, F0); // 0 0 | x b' + const __m128i G1 = _mm_sub_epi8(E1, F1); + const __m128i H0 = _mm_and_si128(G0, mask_b); // 0 0 | 0 b + const __m128i H1 = _mm_and_si128(G1, mask_b); + const __m128i I = _mm_packs_epi32(H0, H1); // 0 b' | 0 b' + _mm_storeu_si128((__m128i*)values, I); + for (i = 0; i < SPAN; ++i) ++histo[values[i]]; + } + } + { + const int left_over = tile_width & (SPAN - 1); + if (left_over > 0) { + VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride, + left_over, tile_height, + green_to_blue, red_to_blue, histo); + } + } +} + +static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]) { + const __m128i mults_g = MK_CST_16(0, CST_5b(green_to_red)); + const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask + const __m128i mask = _mm_set1_epi32(0xff); + + int y; + for (y = 0; y < tile_height; ++y) { + const uint32_t* const src = argb + y * stride; + int i, x; + for (x = 0; x + SPAN <= tile_width; x += SPAN) { + uint16_t values[SPAN]; + const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]); + const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]); + const __m128i A0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0 + const __m128i A1 = _mm_and_si128(in1, mask_g); + const __m128i B0 = _mm_srli_epi32(in0, 16); // 0 0 | x r + const __m128i B1 = _mm_srli_epi32(in1, 16); + const __m128i C0 = _mm_mulhi_epi16(A0, mults_g); // 0 0 | x dr + const __m128i C1 = _mm_mulhi_epi16(A1, mults_g); + const __m128i E0 = _mm_sub_epi8(B0, C0); // x x | x r' + const __m128i E1 = _mm_sub_epi8(B1, C1); + const __m128i F0 = _mm_and_si128(E0, mask); // 0 0 | 0 r' + const __m128i F1 = _mm_and_si128(E1, mask); + const __m128i I = _mm_packs_epi32(F0, F1); + _mm_storeu_si128((__m128i*)values, I); + for (i = 0; i < SPAN; ++i) ++histo[values[i]]; + } + } + { + const int left_over = tile_width & (SPAN - 1); + if (left_over > 0) { + VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride, + left_over, tile_height, + green_to_red, histo); + } + } +} +#undef SPAN +#undef MK_CST_16 + +//------------------------------------------------------------------------------ + +// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But +// that's ok since the histogram values are less than 1<<28 (max picture size). +#define LINE_SIZE 16 // 8 or 16 +static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out, + int size) { + int i; + for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); +#if (LINE_SIZE == 16) + const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]); + const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]); +#endif + const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i + 0]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]); +#if (LINE_SIZE == 16) + const __m128i b2 = _mm_loadu_si128((const __m128i*)&b[i + 8]); + const __m128i b3 = _mm_loadu_si128((const __m128i*)&b[i + 12]); +#endif + _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0)); + _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1)); +#if (LINE_SIZE == 16) + _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2)); + _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); +#endif + } + for (; i < size; ++i) { + out[i] = a[i] + b[i]; + } +} + +static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) { + int i; + for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); +#if (LINE_SIZE == 16) + const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]); + const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]); +#endif + const __m128i b0 = _mm_loadu_si128((const __m128i*)&out[i + 0]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&out[i + 4]); +#if (LINE_SIZE == 16) + const __m128i b2 = _mm_loadu_si128((const __m128i*)&out[i + 8]); + const __m128i b3 = _mm_loadu_si128((const __m128i*)&out[i + 12]); +#endif + _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0)); + _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1)); +#if (LINE_SIZE == 16) + _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2)); + _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); +#endif + } + for (; i < size; ++i) { + out[i] += a[i]; + } +} +#undef LINE_SIZE + +//------------------------------------------------------------------------------ +// Entropy + +// TODO(https://crbug.com/webp/499): this function produces different results +// from the C code due to use of double/float resulting in output differences +// when compared to -noasm. +#if !(defined(WEBP_HAVE_SLOW_CLZ_CTZ) || defined(__i386__) || defined(_M_IX86)) + +static float CombinedShannonEntropy_SSE2(const int X[256], const int Y[256]) { + int i; + float retval = 0.f; + int sumX = 0, sumXY = 0; + const __m128i zero = _mm_setzero_si128(); + + for (i = 0; i < 256; i += 16) { + const __m128i x0 = _mm_loadu_si128((const __m128i*)(X + i + 0)); + const __m128i y0 = _mm_loadu_si128((const __m128i*)(Y + i + 0)); + const __m128i x1 = _mm_loadu_si128((const __m128i*)(X + i + 4)); + const __m128i y1 = _mm_loadu_si128((const __m128i*)(Y + i + 4)); + const __m128i x2 = _mm_loadu_si128((const __m128i*)(X + i + 8)); + const __m128i y2 = _mm_loadu_si128((const __m128i*)(Y + i + 8)); + const __m128i x3 = _mm_loadu_si128((const __m128i*)(X + i + 12)); + const __m128i y3 = _mm_loadu_si128((const __m128i*)(Y + i + 12)); + const __m128i x4 = _mm_packs_epi16(_mm_packs_epi32(x0, x1), + _mm_packs_epi32(x2, x3)); + const __m128i y4 = _mm_packs_epi16(_mm_packs_epi32(y0, y1), + _mm_packs_epi32(y2, y3)); + const int32_t mx = _mm_movemask_epi8(_mm_cmpgt_epi8(x4, zero)); + int32_t my = _mm_movemask_epi8(_mm_cmpgt_epi8(y4, zero)) | mx; + while (my) { + const int32_t j = BitsCtz(my); + int xy; + if ((mx >> j) & 1) { + const int x = X[i + j]; + sumXY += x; + retval -= VP8LFastSLog2(x); + } + xy = X[i + j] + Y[i + j]; + sumX += xy; + retval -= VP8LFastSLog2(xy); + my &= my - 1; + } + } + retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); + return retval; +} + +#else + +#define DONT_USE_COMBINED_SHANNON_ENTROPY_SSE2_FUNC // won't be faster + +#endif + +//------------------------------------------------------------------------------ + +static int VectorMismatch_SSE2(const uint32_t* const array1, + const uint32_t* const array2, int length) { + int match_len; + + if (length >= 12) { + __m128i A0 = _mm_loadu_si128((const __m128i*)&array1[0]); + __m128i A1 = _mm_loadu_si128((const __m128i*)&array2[0]); + match_len = 0; + do { + // Loop unrolling and early load both provide a speedup of 10% for the + // current function. Also, max_limit can be MAX_LENGTH=4096 at most. + const __m128i cmpA = _mm_cmpeq_epi32(A0, A1); + const __m128i B0 = + _mm_loadu_si128((const __m128i*)&array1[match_len + 4]); + const __m128i B1 = + _mm_loadu_si128((const __m128i*)&array2[match_len + 4]); + if (_mm_movemask_epi8(cmpA) != 0xffff) break; + match_len += 4; + + { + const __m128i cmpB = _mm_cmpeq_epi32(B0, B1); + A0 = _mm_loadu_si128((const __m128i*)&array1[match_len + 4]); + A1 = _mm_loadu_si128((const __m128i*)&array2[match_len + 4]); + if (_mm_movemask_epi8(cmpB) != 0xffff) break; + match_len += 4; + } + } while (match_len + 12 < length); + } else { + match_len = 0; + // Unroll the potential first two loops. + if (length >= 4 && + _mm_movemask_epi8(_mm_cmpeq_epi32( + _mm_loadu_si128((const __m128i*)&array1[0]), + _mm_loadu_si128((const __m128i*)&array2[0]))) == 0xffff) { + match_len = 4; + if (length >= 8 && + _mm_movemask_epi8(_mm_cmpeq_epi32( + _mm_loadu_si128((const __m128i*)&array1[4]), + _mm_loadu_si128((const __m128i*)&array2[4]))) == 0xffff) { + match_len = 8; + } + } + } + + while (match_len < length && array1[match_len] == array2[match_len]) { + ++match_len; + } + return match_len; +} + +// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. +static void BundleColorMap_SSE2(const uint8_t* const row, int width, int xbits, + uint32_t* dst) { + int x; + assert(xbits >= 0); + assert(xbits <= 3); + switch (xbits) { + case 0: { + const __m128i ff = _mm_set1_epi16((short)0xff00); + const __m128i zero = _mm_setzero_si128(); + // Store 0xff000000 | (row[x] << 8). + for (x = 0; x + 16 <= width; x += 16, dst += 16) { + const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]); + const __m128i in_lo = _mm_unpacklo_epi8(zero, in); + const __m128i dst0 = _mm_unpacklo_epi16(in_lo, ff); + const __m128i dst1 = _mm_unpackhi_epi16(in_lo, ff); + const __m128i in_hi = _mm_unpackhi_epi8(zero, in); + const __m128i dst2 = _mm_unpacklo_epi16(in_hi, ff); + const __m128i dst3 = _mm_unpackhi_epi16(in_hi, ff); + _mm_storeu_si128((__m128i*)&dst[0], dst0); + _mm_storeu_si128((__m128i*)&dst[4], dst1); + _mm_storeu_si128((__m128i*)&dst[8], dst2); + _mm_storeu_si128((__m128i*)&dst[12], dst3); + } + break; + } + case 1: { + const __m128i ff = _mm_set1_epi16((short)0xff00); + const __m128i mul = _mm_set1_epi16(0x110); + for (x = 0; x + 16 <= width; x += 16, dst += 8) { + // 0a0b | (where a/b are 4 bits). + const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]); + const __m128i tmp = _mm_mullo_epi16(in, mul); // aba0 + const __m128i pack = _mm_and_si128(tmp, ff); // ab00 + const __m128i dst0 = _mm_unpacklo_epi16(pack, ff); + const __m128i dst1 = _mm_unpackhi_epi16(pack, ff); + _mm_storeu_si128((__m128i*)&dst[0], dst0); + _mm_storeu_si128((__m128i*)&dst[4], dst1); + } + break; + } + case 2: { + const __m128i mask_or = _mm_set1_epi32((int)0xff000000); + const __m128i mul_cst = _mm_set1_epi16(0x0104); + const __m128i mask_mul = _mm_set1_epi16(0x0f00); + for (x = 0; x + 16 <= width; x += 16, dst += 4) { + // 000a000b000c000d | (where a/b/c/d are 2 bits). + const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]); + const __m128i mul = _mm_mullo_epi16(in, mul_cst); // 00ab00b000cd00d0 + const __m128i tmp = _mm_and_si128(mul, mask_mul); // 00ab000000cd0000 + const __m128i shift = _mm_srli_epi32(tmp, 12); // 00000000ab000000 + const __m128i pack = _mm_or_si128(shift, tmp); // 00000000abcd0000 + // Convert to 0xff00**00. + const __m128i res = _mm_or_si128(pack, mask_or); + _mm_storeu_si128((__m128i*)dst, res); + } + break; + } + default: { + assert(xbits == 3); + for (x = 0; x + 16 <= width; x += 16, dst += 2) { + // 0000000a00000000b... | (where a/b are 1 bit). + const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]); + const __m128i shift = _mm_slli_epi64(in, 7); + const uint32_t move = _mm_movemask_epi8(shift); + dst[0] = 0xff000000 | ((move & 0xff) << 8); + dst[1] = 0xff000000 | (move & 0xff00); + } + break; + } + } + if (x != width) { + VP8LBundleColorMap_C(row + x, width - x, xbits, dst); + } +} + +//------------------------------------------------------------------------------ +// Batch version of Predictor Transform subtraction + +static WEBP_INLINE void Average2_m128i(const __m128i* const a0, + const __m128i* const a1, + __m128i* const avg) { + // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1) + const __m128i ones = _mm_set1_epi8(1); + const __m128i avg1 = _mm_avg_epu8(*a0, *a1); + const __m128i one = _mm_and_si128(_mm_xor_si128(*a0, *a1), ones); + *avg = _mm_sub_epi8(avg1, one); +} + +// Predictor0: ARGB_BLACK. +static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i black = _mm_set1_epi32((int)ARGB_BLACK); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i res = _mm_sub_epi8(src, black); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[0](in + i, NULL, num_pixels - i, out + i); + } + (void)upper; +} + +#define GENERATE_PREDICTOR_1(X, IN) \ + static void PredictorSub##X##_SSE2(const uint32_t* const in, \ + const uint32_t* const upper, \ + int num_pixels, uint32_t* const out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \ + const __m128i pred = _mm_loadu_si128((const __m128i*)&(IN)); \ + const __m128i res = _mm_sub_epi8(src, pred); \ + _mm_storeu_si128((__m128i*)&out[i], res); \ + } \ + if (i != num_pixels) { \ + VP8LPredictorsSub_C[(X)](in + i, WEBP_OFFSET_PTR(upper, i), \ + num_pixels - i, out + i); \ + } \ + } + +GENERATE_PREDICTOR_1(1, in[i - 1]) // Predictor1: L +GENERATE_PREDICTOR_1(2, upper[i]) // Predictor2: T +GENERATE_PREDICTOR_1(3, upper[i + 1]) // Predictor3: TR +GENERATE_PREDICTOR_1(4, upper[i - 1]) // Predictor4: TL +#undef GENERATE_PREDICTOR_1 + +// Predictor5: avg2(avg2(L, TR), T) +static void PredictorSub5_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]); + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + __m128i avg, pred, res; + Average2_m128i(&L, &TR, &avg); + Average2_m128i(&avg, &T, &pred); + res = _mm_sub_epi8(src, pred); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[5](in + i, upper + i, num_pixels - i, out + i); + } +} + +#define GENERATE_PREDICTOR_2(X, A, B) \ +static void PredictorSub##X##_SSE2(const uint32_t* in, const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const __m128i tA = _mm_loadu_si128((const __m128i*)&(A)); \ + const __m128i tB = _mm_loadu_si128((const __m128i*)&(B)); \ + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \ + __m128i pred, res; \ + Average2_m128i(&tA, &tB, &pred); \ + res = _mm_sub_epi8(src, pred); \ + _mm_storeu_si128((__m128i*)&out[i], res); \ + } \ + if (i != num_pixels) { \ + VP8LPredictorsSub_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ + } \ +} + +GENERATE_PREDICTOR_2(6, in[i - 1], upper[i - 1]) // Predictor6: avg(L, TL) +GENERATE_PREDICTOR_2(7, in[i - 1], upper[i]) // Predictor7: avg(L, T) +GENERATE_PREDICTOR_2(8, upper[i - 1], upper[i]) // Predictor8: avg(TL, T) +GENERATE_PREDICTOR_2(9, upper[i], upper[i + 1]) // Predictor9: average(T, TR) +#undef GENERATE_PREDICTOR_2 + +// Predictor10: avg(avg(L,TL), avg(T, TR)). +static void PredictorSub10_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]); + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]); + __m128i avgTTR, avgLTL, avg, res; + Average2_m128i(&T, &TR, &avgTTR); + Average2_m128i(&L, &TL, &avgLTL); + Average2_m128i(&avgTTR, &avgLTL, &avg); + res = _mm_sub_epi8(src, avg); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[10](in + i, upper + i, num_pixels - i, out + i); + } +} + +// Predictor11: select. +static void GetSumAbsDiff32_SSE2(const __m128i* const A, const __m128i* const B, + __m128i* const out) { + // We can unpack with any value on the upper 32 bits, provided it's the same + // on both operands (to that their sum of abs diff is zero). Here we use *A. + const __m128i A_lo = _mm_unpacklo_epi32(*A, *A); + const __m128i B_lo = _mm_unpacklo_epi32(*B, *A); + const __m128i A_hi = _mm_unpackhi_epi32(*A, *A); + const __m128i B_hi = _mm_unpackhi_epi32(*B, *A); + const __m128i s_lo = _mm_sad_epu8(A_lo, B_lo); + const __m128i s_hi = _mm_sad_epu8(A_hi, B_hi); + *out = _mm_packs_epi32(s_lo, s_hi); +} + +static void PredictorSub11_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + __m128i pa, pb; + GetSumAbsDiff32_SSE2(&T, &TL, &pa); // pa = sum |T-TL| + GetSumAbsDiff32_SSE2(&L, &TL, &pb); // pb = sum |L-TL| + { + const __m128i mask = _mm_cmpgt_epi32(pb, pa); + const __m128i A = _mm_and_si128(mask, L); + const __m128i B = _mm_andnot_si128(mask, T); + const __m128i pred = _mm_or_si128(A, B); // pred = (L > T)? L : T + const __m128i res = _mm_sub_epi8(src, pred); + _mm_storeu_si128((__m128i*)&out[i], res); + } + } + if (i != num_pixels) { + VP8LPredictorsSub_C[11](in + i, upper + i, num_pixels - i, out + i); + } +} + +// Predictor12: ClampedSubSubtractFull. +static void PredictorSub12_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]); + const __m128i L_lo = _mm_unpacklo_epi8(L, zero); + const __m128i L_hi = _mm_unpackhi_epi8(L, zero); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i T_lo = _mm_unpacklo_epi8(T, zero); + const __m128i T_hi = _mm_unpackhi_epi8(T, zero); + const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero); + const __m128i TL_hi = _mm_unpackhi_epi8(TL, zero); + const __m128i diff_lo = _mm_sub_epi16(T_lo, TL_lo); + const __m128i diff_hi = _mm_sub_epi16(T_hi, TL_hi); + const __m128i pred_lo = _mm_add_epi16(L_lo, diff_lo); + const __m128i pred_hi = _mm_add_epi16(L_hi, diff_hi); + const __m128i pred = _mm_packus_epi16(pred_lo, pred_hi); + const __m128i res = _mm_sub_epi8(src, pred); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[12](in + i, upper + i, num_pixels - i, out + i); + } +} + +// Predictors13: ClampedAddSubtractHalf +static void PredictorSub13_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i + 2 <= num_pixels; i += 2) { + // we can only process two pixels at a time + const __m128i L = _mm_loadl_epi64((const __m128i*)&in[i - 1]); + const __m128i src = _mm_loadl_epi64((const __m128i*)&in[i]); + const __m128i T = _mm_loadl_epi64((const __m128i*)&upper[i]); + const __m128i TL = _mm_loadl_epi64((const __m128i*)&upper[i - 1]); + const __m128i L_lo = _mm_unpacklo_epi8(L, zero); + const __m128i T_lo = _mm_unpacklo_epi8(T, zero); + const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero); + const __m128i sum = _mm_add_epi16(T_lo, L_lo); + const __m128i avg = _mm_srli_epi16(sum, 1); + const __m128i A1 = _mm_sub_epi16(avg, TL_lo); + const __m128i bit_fix = _mm_cmpgt_epi16(TL_lo, avg); + const __m128i A2 = _mm_sub_epi16(A1, bit_fix); + const __m128i A3 = _mm_srai_epi16(A2, 1); + const __m128i A4 = _mm_add_epi16(avg, A3); + const __m128i pred = _mm_packus_epi16(A4, A4); + const __m128i res = _mm_sub_epi8(src, pred); + _mm_storel_epi64((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[13](in + i, upper + i, num_pixels - i, out + i); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) { + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE2; + VP8LTransformColor = TransformColor_SSE2; + VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE2; + VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2; + VP8LAddVector = AddVector_SSE2; + VP8LAddVectorEq = AddVectorEq_SSE2; +#if !defined(DONT_USE_COMBINED_SHANNON_ENTROPY_SSE2_FUNC) + VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2; +#endif + VP8LVectorMismatch = VectorMismatch_SSE2; + VP8LBundleColorMap = BundleColorMap_SSE2; + + VP8LPredictorsSub[0] = PredictorSub0_SSE2; + VP8LPredictorsSub[1] = PredictorSub1_SSE2; + VP8LPredictorsSub[2] = PredictorSub2_SSE2; + VP8LPredictorsSub[3] = PredictorSub3_SSE2; + VP8LPredictorsSub[4] = PredictorSub4_SSE2; + VP8LPredictorsSub[5] = PredictorSub5_SSE2; + VP8LPredictorsSub[6] = PredictorSub6_SSE2; + VP8LPredictorsSub[7] = PredictorSub7_SSE2; + VP8LPredictorsSub[8] = PredictorSub8_SSE2; + VP8LPredictorsSub[9] = PredictorSub9_SSE2; + VP8LPredictorsSub[10] = PredictorSub10_SSE2; + VP8LPredictorsSub[11] = PredictorSub11_SSE2; + VP8LPredictorsSub[12] = PredictorSub12_SSE2; + VP8LPredictorsSub[13] = PredictorSub13_SSE2; + VP8LPredictorsSub[14] = PredictorSub0_SSE2; // <- padding security sentinels + VP8LPredictorsSub[15] = PredictorSub0_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/lossless_enc_sse41.c b/libraries/webp/src/dsp/lossless_enc_sse41.c new file mode 100644 index 0000000000..7ab83c2604 --- /dev/null +++ b/libraries/webp/src/dsp/lossless_enc_sse41.c @@ -0,0 +1,205 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE4.1 variant of methods for lossless encoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) +#include +#include +#include "src/dsp/lossless.h" + +//------------------------------------------------------------------------------ +// Cost operations. + +static WEBP_INLINE uint32_t HorizontalSum_SSE41(__m128i cost) { + cost = _mm_add_epi32(cost, _mm_srli_si128(cost, 8)); + cost = _mm_add_epi32(cost, _mm_srli_si128(cost, 4)); + return _mm_cvtsi128_si32(cost); +} + +static uint32_t ExtraCost_SSE41(const uint32_t* const a, int length) { + int i; + __m128i cost = _mm_set_epi32(2 * a[7], 2 * a[6], a[5], a[4]); + assert(length % 8 == 0); + + for (i = 8; i + 8 <= length; i += 8) { + const int j = (i - 2) >> 1; + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); + const __m128i w = _mm_set_epi32(j + 3, j + 2, j + 1, j); + const __m128i a2 = _mm_hadd_epi32(a0, a1); + const __m128i mul = _mm_mullo_epi32(a2, w); + cost = _mm_add_epi32(mul, cost); + } + return HorizontalSum_SSE41(cost); +} + +static uint32_t ExtraCostCombined_SSE41(const uint32_t* const a, + const uint32_t* const b, int length) { + int i; + __m128i cost = _mm_add_epi32(_mm_set_epi32(2 * a[7], 2 * a[6], a[5], a[4]), + _mm_set_epi32(2 * b[7], 2 * b[6], b[5], b[4])); + assert(length % 8 == 0); + + for (i = 8; i + 8 <= length; i += 8) { + const int j = (i - 2) >> 1; + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); + const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]); + const __m128i w = _mm_set_epi32(j + 3, j + 2, j + 1, j); + const __m128i a2 = _mm_hadd_epi32(a0, a1); + const __m128i b2 = _mm_hadd_epi32(b0, b1); + const __m128i mul = _mm_mullo_epi32(_mm_add_epi32(a2, b2), w); + cost = _mm_add_epi32(mul, cost); + } + return HorizontalSum_SSE41(cost); +} + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +static void SubtractGreenFromBlueAndRed_SSE41(uint32_t* argb_data, + int num_pixels) { + int i; + const __m128i kCstShuffle = _mm_set_epi8(-1, 13, -1, 13, -1, 9, -1, 9, + -1, 5, -1, 5, -1, 1, -1, 1); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); + const __m128i in_0g0g = _mm_shuffle_epi8(in, kCstShuffle); + const __m128i out = _mm_sub_epi8(in, in_0g0g); + _mm_storeu_si128((__m128i*)&argb_data[i], out); + } + // fallthrough and finish off with plain-C + if (i != num_pixels) { + VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i); + } +} + +//------------------------------------------------------------------------------ +// Color Transform + +// For sign-extended multiplying constants, pre-shifted by 5: +#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5) + +#define MK_CST_16(HI, LO) \ + _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff))) + +static void CollectColorBlueTransforms_SSE41(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]) { + const __m128i mult = + MK_CST_16(CST_5b(red_to_blue) + 256,CST_5b(green_to_blue)); + const __m128i perm = + _mm_setr_epi8(-1, 1, -1, 2, -1, 5, -1, 6, -1, 9, -1, 10, -1, 13, -1, 14); + if (tile_width >= 4) { + int y; + for (y = 0; y < tile_height; ++y) { + const uint32_t* const src = argb + y * stride; + const __m128i A1 = _mm_loadu_si128((const __m128i*)src); + const __m128i B1 = _mm_shuffle_epi8(A1, perm); + const __m128i C1 = _mm_mulhi_epi16(B1, mult); + const __m128i D1 = _mm_sub_epi16(A1, C1); + __m128i E = _mm_add_epi16(_mm_srli_epi32(D1, 16), D1); + int x; + for (x = 4; x + 4 <= tile_width; x += 4) { + const __m128i A2 = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i B2, C2, D2; + ++histo[_mm_extract_epi8(E, 0)]; + B2 = _mm_shuffle_epi8(A2, perm); + ++histo[_mm_extract_epi8(E, 4)]; + C2 = _mm_mulhi_epi16(B2, mult); + ++histo[_mm_extract_epi8(E, 8)]; + D2 = _mm_sub_epi16(A2, C2); + ++histo[_mm_extract_epi8(E, 12)]; + E = _mm_add_epi16(_mm_srli_epi32(D2, 16), D2); + } + ++histo[_mm_extract_epi8(E, 0)]; + ++histo[_mm_extract_epi8(E, 4)]; + ++histo[_mm_extract_epi8(E, 8)]; + ++histo[_mm_extract_epi8(E, 12)]; + } + } + { + const int left_over = tile_width & 3; + if (left_over > 0) { + VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride, + left_over, tile_height, + green_to_blue, red_to_blue, histo); + } + } +} + +static void CollectColorRedTransforms_SSE41(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]) { + + const __m128i mult = MK_CST_16(0, CST_5b(green_to_red)); + const __m128i mask_g = _mm_set1_epi32(0x0000ff00); + if (tile_width >= 4) { + int y; + for (y = 0; y < tile_height; ++y) { + const uint32_t* const src = argb + y * stride; + const __m128i A1 = _mm_loadu_si128((const __m128i*)src); + const __m128i B1 = _mm_and_si128(A1, mask_g); + const __m128i C1 = _mm_madd_epi16(B1, mult); + __m128i D = _mm_sub_epi16(A1, C1); + int x; + for (x = 4; x + 4 <= tile_width; x += 4) { + const __m128i A2 = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i B2, C2; + ++histo[_mm_extract_epi8(D, 2)]; + B2 = _mm_and_si128(A2, mask_g); + ++histo[_mm_extract_epi8(D, 6)]; + C2 = _mm_madd_epi16(B2, mult); + ++histo[_mm_extract_epi8(D, 10)]; + ++histo[_mm_extract_epi8(D, 14)]; + D = _mm_sub_epi16(A2, C2); + } + ++histo[_mm_extract_epi8(D, 2)]; + ++histo[_mm_extract_epi8(D, 6)]; + ++histo[_mm_extract_epi8(D, 10)]; + ++histo[_mm_extract_epi8(D, 14)]; + } + } + { + const int left_over = tile_width & 3; + if (left_over > 0) { + VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride, + left_over, tile_height, green_to_red, + histo); + } + } +} + +#undef MK_CST_16 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) { + VP8LExtraCost = ExtraCost_SSE41; + VP8LExtraCostCombined = ExtraCostCombined_SSE41; + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE41; + VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE41; + VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/libraries/webp/src/dsp/lossless_mips_dsp_r2.c b/libraries/webp/src/dsp/lossless_mips_dsp_r2.c new file mode 100644 index 0000000000..bfe5ea6b38 --- /dev/null +++ b/libraries/webp/src/dsp/lossless_mips_dsp_r2.c @@ -0,0 +1,701 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" + +#define MAP_COLOR_FUNCS(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ +static void FUNC_NAME(const TYPE* src, \ + const uint32_t* const color_map, \ + TYPE* dst, int y_start, int y_end, \ + int width) { \ + int y; \ + for (y = y_start; y < y_end; ++y) { \ + int x; \ + for (x = 0; x < (width >> 2); ++x) { \ + int tmp1, tmp2, tmp3, tmp4; \ + __asm__ volatile ( \ + ".ifc " #TYPE ", uint8_t \n\t" \ + "lbu %[tmp1], 0(%[src]) \n\t" \ + "lbu %[tmp2], 1(%[src]) \n\t" \ + "lbu %[tmp3], 2(%[src]) \n\t" \ + "lbu %[tmp4], 3(%[src]) \n\t" \ + "addiu %[src], %[src], 4 \n\t" \ + ".endif \n\t" \ + ".ifc " #TYPE ", uint32_t \n\t" \ + "lw %[tmp1], 0(%[src]) \n\t" \ + "lw %[tmp2], 4(%[src]) \n\t" \ + "lw %[tmp3], 8(%[src]) \n\t" \ + "lw %[tmp4], 12(%[src]) \n\t" \ + "ext %[tmp1], %[tmp1], 8, 8 \n\t" \ + "ext %[tmp2], %[tmp2], 8, 8 \n\t" \ + "ext %[tmp3], %[tmp3], 8, 8 \n\t" \ + "ext %[tmp4], %[tmp4], 8, 8 \n\t" \ + "addiu %[src], %[src], 16 \n\t" \ + ".endif \n\t" \ + "sll %[tmp1], %[tmp1], 2 \n\t" \ + "sll %[tmp2], %[tmp2], 2 \n\t" \ + "sll %[tmp3], %[tmp3], 2 \n\t" \ + "sll %[tmp4], %[tmp4], 2 \n\t" \ + "lwx %[tmp1], %[tmp1](%[color_map]) \n\t" \ + "lwx %[tmp2], %[tmp2](%[color_map]) \n\t" \ + "lwx %[tmp3], %[tmp3](%[color_map]) \n\t" \ + "lwx %[tmp4], %[tmp4](%[color_map]) \n\t" \ + ".ifc " #TYPE ", uint8_t \n\t" \ + "ext %[tmp1], %[tmp1], 8, 8 \n\t" \ + "ext %[tmp2], %[tmp2], 8, 8 \n\t" \ + "ext %[tmp3], %[tmp3], 8, 8 \n\t" \ + "ext %[tmp4], %[tmp4], 8, 8 \n\t" \ + "sb %[tmp1], 0(%[dst]) \n\t" \ + "sb %[tmp2], 1(%[dst]) \n\t" \ + "sb %[tmp3], 2(%[dst]) \n\t" \ + "sb %[tmp4], 3(%[dst]) \n\t" \ + "addiu %[dst], %[dst], 4 \n\t" \ + ".endif \n\t" \ + ".ifc " #TYPE ", uint32_t \n\t" \ + "sw %[tmp1], 0(%[dst]) \n\t" \ + "sw %[tmp2], 4(%[dst]) \n\t" \ + "sw %[tmp3], 8(%[dst]) \n\t" \ + "sw %[tmp4], 12(%[dst]) \n\t" \ + "addiu %[dst], %[dst], 16 \n\t" \ + ".endif \n\t" \ + : [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [tmp3]"=&r"(tmp3), \ + [tmp4]"=&r"(tmp4), [src]"+&r"(src), [dst]"+r"(dst) \ + : [color_map]"r"(color_map) \ + : "memory" \ + ); \ + } \ + for (x = 0; x < (width & 3); ++x) { \ + *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ + } \ + } \ +} + +MAP_COLOR_FUNCS(MapARGB_MIPSdspR2, uint32_t, VP8GetARGBIndex, VP8GetARGBValue) +MAP_COLOR_FUNCS(MapAlpha_MIPSdspR2, uint8_t, VP8GetAlphaIndex, VP8GetAlphaValue) + +#undef MAP_COLOR_FUNCS + +static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, + uint32_t c2) { + int temp0, temp1, temp2, temp3, temp4, temp5; + __asm__ volatile ( + "preceu.ph.qbr %[temp1], %[c0] \n\t" + "preceu.ph.qbl %[temp2], %[c0] \n\t" + "preceu.ph.qbr %[temp3], %[c1] \n\t" + "preceu.ph.qbl %[temp4], %[c1] \n\t" + "preceu.ph.qbr %[temp5], %[c2] \n\t" + "preceu.ph.qbl %[temp0], %[c2] \n\t" + "subq.ph %[temp3], %[temp3], %[temp5] \n\t" + "subq.ph %[temp4], %[temp4], %[temp0] \n\t" + "addq.ph %[temp1], %[temp1], %[temp3] \n\t" + "addq.ph %[temp2], %[temp2], %[temp4] \n\t" + "shll_s.ph %[temp1], %[temp1], 7 \n\t" + "shll_s.ph %[temp2], %[temp2], 7 \n\t" + "precrqu_s.qb.ph %[temp2], %[temp2], %[temp1] \n\t" + : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5) + : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2) + : "memory" + ); + return temp2; +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, + uint32_t c2) { + int temp0, temp1, temp2, temp3, temp4, temp5; + __asm__ volatile ( + "adduh.qb %[temp5], %[c0], %[c1] \n\t" + "preceu.ph.qbr %[temp3], %[c2] \n\t" + "preceu.ph.qbr %[temp1], %[temp5] \n\t" + "preceu.ph.qbl %[temp2], %[temp5] \n\t" + "preceu.ph.qbl %[temp4], %[c2] \n\t" + "subq.ph %[temp3], %[temp1], %[temp3] \n\t" + "subq.ph %[temp4], %[temp2], %[temp4] \n\t" + "shrl.ph %[temp5], %[temp3], 15 \n\t" + "shrl.ph %[temp0], %[temp4], 15 \n\t" + "addq.ph %[temp3], %[temp3], %[temp5] \n\t" + "addq.ph %[temp4], %[temp0], %[temp4] \n\t" + "shra.ph %[temp3], %[temp3], 1 \n\t" + "shra.ph %[temp4], %[temp4], 1 \n\t" + "addq.ph %[temp1], %[temp1], %[temp3] \n\t" + "addq.ph %[temp2], %[temp2], %[temp4] \n\t" + "shll_s.ph %[temp1], %[temp1], 7 \n\t" + "shll_s.ph %[temp2], %[temp2], 7 \n\t" + "precrqu_s.qb.ph %[temp1], %[temp2], %[temp1] \n\t" + : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=r"(temp4), [temp5]"=&r"(temp5) + : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2) + : "memory" + ); + return temp1; +} + +static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { + int temp0, temp1, temp2, temp3, temp4, temp5; + __asm__ volatile ( + "cmpgdu.lt.qb %[temp1], %[c], %[b] \n\t" + "pick.qb %[temp1], %[b], %[c] \n\t" + "pick.qb %[temp2], %[c], %[b] \n\t" + "cmpgdu.lt.qb %[temp4], %[c], %[a] \n\t" + "pick.qb %[temp4], %[a], %[c] \n\t" + "pick.qb %[temp5], %[c], %[a] \n\t" + "subu.qb %[temp3], %[temp1], %[temp2] \n\t" + "subu.qb %[temp0], %[temp4], %[temp5] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "raddu.w.qb %[temp0], %[temp0] \n\t" + "subu %[temp3], %[temp3], %[temp0] \n\t" + "slti %[temp0], %[temp3], 0x1 \n\t" + "movz %[a], %[b], %[temp0] \n\t" + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp0]"=&r"(temp0), + [a]"+&r"(a) + : [b]"r"(b), [c]"r"(c) + ); + return a; +} + +static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { + __asm__ volatile ( + "adduh.qb %[a0], %[a0], %[a1] \n\t" + : [a0]"+r"(a0) + : [a1]"r"(a1) + ); + return a0; +} + +static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { + return Average2(Average2(a0, a2), a1); +} + +static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) { + return Average2(Average2(a0, a1), Average2(a2, a3)); +} + +static uint32_t Predictor5_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average3(*left, top[0], top[1]); +} + +static uint32_t Predictor6_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average2(*left, top[-1]); +} + +static uint32_t Predictor7_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average2(*left, top[0]); +} + +static uint32_t Predictor8_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return Average2(top[-1], top[0]); +} + +static uint32_t Predictor9_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return Average2(top[0], top[1]); +} + +static uint32_t Predictor10_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average4(*left, top[-1], top[0], top[1]); +} + +static uint32_t Predictor11_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Select(top[0], *left, top[-1]); +} + +static uint32_t Predictor12_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return ClampedAddSubtractFull(*left, top[0], top[-1]); +} + +static uint32_t Predictor13_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return ClampedAddSubtractHalf(*left, top[0], top[-1]); +} + +// Add green to blue and red channels (i.e. perform the inverse transform of +// 'subtract green'). +static void AddGreenToBlueAndRed_MIPSdspR2(const uint32_t* src, int num_pixels, + uint32_t* dst) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "ext %[temp4], %[temp0], 8, 8 \n\t" + "ext %[temp5], %[temp1], 8, 8 \n\t" + "ext %[temp6], %[temp2], 8, 8 \n\t" + "ext %[temp7], %[temp3], 8, 8 \n\t" + "addiu %[src], %[src], 16 \n\t" + "addiu %[dst], %[dst], 16 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "replv.ph %[temp5], %[temp5] \n\t" + "replv.ph %[temp6], %[temp6] \n\t" + "replv.ph %[temp7], %[temp7] \n\t" + "addu.qb %[temp0], %[temp0], %[temp4] \n\t" + "addu.qb %[temp1], %[temp1], %[temp5] \n\t" + "addu.qb %[temp2], %[temp2], %[temp6] \n\t" + "addu.qb %[temp3], %[temp3], %[temp7] \n\t" + "sw %[temp0], -16(%[dst]) \n\t" + "sw %[temp1], -12(%[dst]) \n\t" + "sw %[temp2], -8(%[dst]) \n\t" + "bne %[src], %[p_loop1_end], 0b \n\t" + " sw %[temp3], -4(%[dst]) \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "addiu %[src], %[src], 4 \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "ext %[temp4], %[temp0], 8, 8 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "addu.qb %[temp0], %[temp0], %[temp4] \n\t" + "bne %[src], %[p_loop2_end], 1b \n\t" + " sw %[temp0], -4(%[dst]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [dst]"+&r"(dst), [src]"+&r"(src), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), + [temp7]"=&r"(temp7) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void TransformColorInverse_MIPSdspR2(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst) { + int temp0, temp1, temp2, temp3, temp4, temp5; + uint32_t argb, argb1, new_red; + const uint32_t G_to_R = m->green_to_red_; + const uint32_t G_to_B = m->green_to_blue_; + const uint32_t R_to_B = m->red_to_blue_; + const uint32_t* const p_loop_end = src + (num_pixels & ~1); + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop_end], 1f \n\t" + " nop \n\t" + "replv.ph %[temp0], %[G_to_R] \n\t" + "replv.ph %[temp1], %[G_to_B] \n\t" + "replv.ph %[temp2], %[R_to_B] \n\t" + "shll.ph %[temp0], %[temp0], 8 \n\t" + "shll.ph %[temp1], %[temp1], 8 \n\t" + "shll.ph %[temp2], %[temp2], 8 \n\t" + "shra.ph %[temp0], %[temp0], 8 \n\t" + "shra.ph %[temp1], %[temp1], 8 \n\t" + "shra.ph %[temp2], %[temp2], 8 \n\t" + "0: \n\t" + "lw %[argb], 0(%[src]) \n\t" + "lw %[argb1], 4(%[src]) \n\t" + "sw %[argb], 0(%[dst]) \n\t" + "sw %[argb1], 4(%[dst]) \n\t" + "addiu %[src], %[src], 8 \n\t" + "addiu %[dst], %[dst], 8 \n\t" + "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t" + "preceu.ph.qbra %[temp3], %[temp3] \n\t" + "shll.ph %[temp3], %[temp3], 8 \n\t" + "shra.ph %[temp3], %[temp3], 8 \n\t" + "mul.ph %[temp5], %[temp3], %[temp0] \n\t" + "mul.ph %[temp3], %[temp3], %[temp1] \n\t" + "precrq.ph.w %[new_red], %[argb], %[argb1] \n\t" + "ins %[argb1], %[argb], 16, 16 \n\t" + "shra.ph %[temp5], %[temp5], 5 \n\t" + "shra.ph %[temp3], %[temp3], 5 \n\t" + "addu.ph %[new_red], %[new_red], %[temp5] \n\t" + "addu.ph %[argb1], %[argb1], %[temp3] \n\t" + "preceu.ph.qbra %[temp5], %[new_red] \n\t" + "shll.ph %[temp4], %[temp5], 8 \n\t" + "shra.ph %[temp4], %[temp4], 8 \n\t" + "mul.ph %[temp4], %[temp4], %[temp2] \n\t" + "sb %[temp5], -2(%[dst]) \n\t" + "sra %[temp5], %[temp5], 16 \n\t" + "shra.ph %[temp4], %[temp4], 5 \n\t" + "addu.ph %[argb1], %[argb1], %[temp4] \n\t" + "preceu.ph.qbra %[temp3], %[argb1] \n\t" + "sb %[temp5], -6(%[dst]) \n\t" + "sb %[temp3], -4(%[dst]) \n\t" + "sra %[temp3], %[temp3], 16 \n\t" + "bne %[src], %[p_loop_end], 0b \n\t" + " sb %[temp3], -8(%[dst]) \n\t" + "1: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [new_red]"=&r"(new_red), [argb]"=&r"(argb), + [argb1]"=&r"(argb1), [dst]"+&r"(dst), [src]"+&r"(src) + : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B), + [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end) + : "memory", "hi", "lo" + ); + + // Fall-back to C-version for left-overs. + if (num_pixels & 1) VP8LTransformColorInverse_C(m, src, 1, dst); +} + +static void ConvertBGRAToRGB_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "ins %[temp3], %[temp2], 24, 8 \n\t" + "sll %[temp2], %[temp2], 8 \n\t" + "rotr %[temp3], %[temp3], 16 \n\t" + "ins %[temp2], %[temp1], 0, 16 \n\t" + "sll %[temp1], %[temp1], 8 \n\t" + "wsbh %[temp3], %[temp3] \n\t" + "balign %[temp0], %[temp1], 1 \n\t" + "wsbh %[temp2], %[temp2] \n\t" + "wsbh %[temp0], %[temp0] \n\t" + "usw %[temp3], 8(%[dst]) \n\t" + "rotr %[temp0], %[temp0], 16 \n\t" + "usw %[temp2], 4(%[dst]) \n\t" + "addiu %[src], %[src], 16 \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 12 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "addiu %[src], %[src], 4 \n\t" + "wsbh %[temp1], %[temp0] \n\t" + "addiu %[dst], %[dst], 3 \n\t" + "ush %[temp1], -2(%[dst]) \n\t" + "sra %[temp0], %[temp0], 16 \n\t" + "bne %[src], %[p_loop2_end], 1b \n\t" + " sb %[temp0], -3(%[dst]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void ConvertBGRAToRGBA_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "wsbh %[temp0], %[temp0] \n\t" + "wsbh %[temp1], %[temp1] \n\t" + "wsbh %[temp2], %[temp2] \n\t" + "wsbh %[temp3], %[temp3] \n\t" + "addiu %[src], %[src], 16 \n\t" + "balign %[temp0], %[temp0], 1 \n\t" + "balign %[temp1], %[temp1], 1 \n\t" + "balign %[temp2], %[temp2], 1 \n\t" + "balign %[temp3], %[temp3], 1 \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "usw %[temp1], 4(%[dst]) \n\t" + "usw %[temp2], 8(%[dst]) \n\t" + "usw %[temp3], 12(%[dst]) \n\t" + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 16 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "wsbh %[temp0], %[temp0] \n\t" + "addiu %[src], %[src], 4 \n\t" + "balign %[temp0], %[temp0], 1 \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "bne %[src], %[p_loop2_end], 1b \n\t" + " addiu %[dst], %[dst], 4 \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void ConvertBGRAToRGBA4444_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3, temp4, temp5; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "ext %[temp4], %[temp0], 28, 4 \n\t" + "ext %[temp5], %[temp0], 12, 4 \n\t" + "ins %[temp0], %[temp4], 0, 4 \n\t" + "ext %[temp4], %[temp1], 28, 4 \n\t" + "ins %[temp0], %[temp5], 16, 4 \n\t" + "ext %[temp5], %[temp1], 12, 4 \n\t" + "ins %[temp1], %[temp4], 0, 4 \n\t" + "ext %[temp4], %[temp2], 28, 4 \n\t" + "ins %[temp1], %[temp5], 16, 4 \n\t" + "ext %[temp5], %[temp2], 12, 4 \n\t" + "ins %[temp2], %[temp4], 0, 4 \n\t" + "ext %[temp4], %[temp3], 28, 4 \n\t" + "ins %[temp2], %[temp5], 16, 4 \n\t" + "ext %[temp5], %[temp3], 12, 4 \n\t" + "ins %[temp3], %[temp4], 0, 4 \n\t" + "precr.qb.ph %[temp1], %[temp1], %[temp0] \n\t" + "ins %[temp3], %[temp5], 16, 4 \n\t" + "addiu %[src], %[src], 16 \n\t" + "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" +#if (WEBP_SWAP_16BIT_CSP == 1) + "usw %[temp1], 0(%[dst]) \n\t" + "usw %[temp3], 4(%[dst]) \n\t" +#else + "wsbh %[temp1], %[temp1] \n\t" + "wsbh %[temp3], %[temp3] \n\t" + "usw %[temp1], 0(%[dst]) \n\t" + "usw %[temp3], 4(%[dst]) \n\t" +#endif + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 8 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "ext %[temp4], %[temp0], 28, 4 \n\t" + "ext %[temp5], %[temp0], 12, 4 \n\t" + "ins %[temp0], %[temp4], 0, 4 \n\t" + "ins %[temp0], %[temp5], 16, 4 \n\t" + "addiu %[src], %[src], 4 \n\t" + "precr.qb.ph %[temp0], %[temp0], %[temp0] \n\t" +#if (WEBP_SWAP_16BIT_CSP == 1) + "ush %[temp0], 0(%[dst]) \n\t" +#else + "wsbh %[temp0], %[temp0] \n\t" + "ush %[temp0], 0(%[dst]) \n\t" +#endif + "bne %[src], %[p_loop2_end], 1b \n\t" + " addiu %[dst], %[dst], 2 \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void ConvertBGRAToRGB565_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3, temp4, temp5; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "ext %[temp4], %[temp0], 8, 16 \n\t" + "ext %[temp5], %[temp0], 5, 11 \n\t" + "ext %[temp0], %[temp0], 3, 5 \n\t" + "ins %[temp4], %[temp5], 0, 11 \n\t" + "ext %[temp5], %[temp1], 5, 11 \n\t" + "ins %[temp4], %[temp0], 0, 5 \n\t" + "ext %[temp0], %[temp1], 8, 16 \n\t" + "ext %[temp1], %[temp1], 3, 5 \n\t" + "ins %[temp0], %[temp5], 0, 11 \n\t" + "ext %[temp5], %[temp2], 5, 11 \n\t" + "ins %[temp0], %[temp1], 0, 5 \n\t" + "ext %[temp1], %[temp2], 8, 16 \n\t" + "ext %[temp2], %[temp2], 3, 5 \n\t" + "ins %[temp1], %[temp5], 0, 11 \n\t" + "ext %[temp5], %[temp3], 5, 11 \n\t" + "ins %[temp1], %[temp2], 0, 5 \n\t" + "ext %[temp2], %[temp3], 8, 16 \n\t" + "ext %[temp3], %[temp3], 3, 5 \n\t" + "ins %[temp2], %[temp5], 0, 11 \n\t" + "append %[temp0], %[temp4], 16 \n\t" + "ins %[temp2], %[temp3], 0, 5 \n\t" + "addiu %[src], %[src], 16 \n\t" + "append %[temp2], %[temp1], 16 \n\t" +#if (WEBP_SWAP_16BIT_CSP == 1) + "usw %[temp0], 0(%[dst]) \n\t" + "usw %[temp2], 4(%[dst]) \n\t" +#else + "wsbh %[temp0], %[temp0] \n\t" + "wsbh %[temp2], %[temp2] \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "usw %[temp2], 4(%[dst]) \n\t" +#endif + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 8 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "ext %[temp4], %[temp0], 8, 16 \n\t" + "ext %[temp5], %[temp0], 5, 11 \n\t" + "ext %[temp0], %[temp0], 3, 5 \n\t" + "ins %[temp4], %[temp5], 0, 11 \n\t" + "addiu %[src], %[src], 4 \n\t" + "ins %[temp4], %[temp0], 0, 5 \n\t" +#if (WEBP_SWAP_16BIT_CSP == 1) + "ush %[temp4], 0(%[dst]) \n\t" +#else + "wsbh %[temp4], %[temp4] \n\t" + "ush %[temp4], 0(%[dst]) \n\t" +#endif + "bne %[src], %[p_loop2_end], 1b \n\t" + " addiu %[dst], %[dst], 2 \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void ConvertBGRAToBGR_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "ins %[temp0], %[temp1], 24, 8 \n\t" + "sra %[temp1], %[temp1], 8 \n\t" + "ins %[temp1], %[temp2], 16, 16 \n\t" + "sll %[temp2], %[temp2], 8 \n\t" + "balign %[temp3], %[temp2], 1 \n\t" + "addiu %[src], %[src], 16 \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "usw %[temp1], 4(%[dst]) \n\t" + "usw %[temp3], 8(%[dst]) \n\t" + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 12 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "addiu %[src], %[src], 4 \n\t" + "addiu %[dst], %[dst], 3 \n\t" + "ush %[temp0], -3(%[dst]) \n\t" + "sra %[temp0], %[temp0], 16 \n\t" + "bne %[src], %[p_loop2_end], 1b \n\t" + " sb %[temp0], -1(%[dst]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMIPSdspR2(void) { + VP8LMapColor32b = MapARGB_MIPSdspR2; + VP8LMapColor8b = MapAlpha_MIPSdspR2; + + VP8LPredictors[5] = Predictor5_MIPSdspR2; + VP8LPredictors[6] = Predictor6_MIPSdspR2; + VP8LPredictors[7] = Predictor7_MIPSdspR2; + VP8LPredictors[8] = Predictor8_MIPSdspR2; + VP8LPredictors[9] = Predictor9_MIPSdspR2; + VP8LPredictors[10] = Predictor10_MIPSdspR2; + VP8LPredictors[11] = Predictor11_MIPSdspR2; + VP8LPredictors[12] = Predictor12_MIPSdspR2; + VP8LPredictors[13] = Predictor13_MIPSdspR2; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_MIPSdspR2; + VP8LTransformColorInverse = TransformColorInverse_MIPSdspR2; + + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_MIPSdspR2; + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_MIPSdspR2; + VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444_MIPSdspR2; + VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565_MIPSdspR2; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8LDspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/lossless_msa.c b/libraries/webp/src/dsp/lossless_msa.c new file mode 100644 index 0000000000..9f5472078d --- /dev/null +++ b/libraries/webp/src/dsp/lossless_msa.c @@ -0,0 +1,356 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA variant of methods for lossless decoder +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/lossless.h" +#include "src/dsp/msa_macro.h" + +//------------------------------------------------------------------------------ +// Colorspace conversion functions + +#define CONVERT16_BGRA_XXX(psrc, pdst, m0, m1, m2) do { \ + v16u8 src0, src1, src2, src3, dst0, dst1, dst2; \ + LD_UB4(psrc, 16, src0, src1, src2, src3); \ + VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \ + dst2 = VSHF_UB(src2, src3, m2); \ + ST_UB2(dst0, dst1, pdst, 16); \ + ST_UB(dst2, pdst + 32); \ +} while (0) + +#define CONVERT12_BGRA_XXX(psrc, pdst, m0, m1, m2) do { \ + uint32_t pix_w; \ + v16u8 src0, src1, src2, dst0, dst1, dst2; \ + LD_UB3(psrc, 16, src0, src1, src2); \ + VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \ + dst2 = VSHF_UB(src2, src2, m2); \ + ST_UB2(dst0, dst1, pdst, 16); \ + pix_w = __msa_copy_s_w((v4i32)dst2, 0); \ + SW(pix_w, pdst + 32); \ +} while (0) + +#define CONVERT8_BGRA_XXX(psrc, pdst, m0, m1) do { \ + uint64_t pix_d; \ + v16u8 src0, src1, src2 = { 0 }, dst0, dst1; \ + LD_UB2(psrc, 16, src0, src1); \ + VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \ + ST_UB(dst0, pdst); \ + pix_d = __msa_copy_s_d((v2i64)dst1, 0); \ + SD(pix_d, pdst + 16); \ +} while (0) + +#define CONVERT4_BGRA_XXX(psrc, pdst, m) do { \ + const v16u8 src0 = LD_UB(psrc); \ + const v16u8 dst0 = VSHF_UB(src0, src0, m); \ + uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); \ + uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2); \ + SD(pix_d, pdst + 0); \ + SW(pix_w, pdst + 8); \ +} while (0) + +#define CONVERT1_BGRA_BGR(psrc, pdst) do { \ + const int32_t b = (psrc)[0]; \ + const int32_t g = (psrc)[1]; \ + const int32_t r = (psrc)[2]; \ + (pdst)[0] = b; \ + (pdst)[1] = g; \ + (pdst)[2] = r; \ +} while (0) + +#define CONVERT1_BGRA_RGB(psrc, pdst) do { \ + const int32_t b = (psrc)[0]; \ + const int32_t g = (psrc)[1]; \ + const int32_t r = (psrc)[2]; \ + (pdst)[0] = r; \ + (pdst)[1] = g; \ + (pdst)[2] = b; \ +} while (0) + +#define TRANSFORM_COLOR_INVERSE_8(src0, src1, dst0, dst1, \ + c0, c1, mask0, mask1) do { \ + v8i16 g0, g1, t0, t1, t2, t3; \ + v4i32 t4, t5; \ + VSHF_B2_SH(src0, src0, src1, src1, mask0, mask0, g0, g1); \ + DOTP_SB2_SH(g0, g1, c0, c0, t0, t1); \ + SRAI_H2_SH(t0, t1, 5); \ + t0 = __msa_addv_h(t0, (v8i16)src0); \ + t1 = __msa_addv_h(t1, (v8i16)src1); \ + t4 = __msa_srli_w((v4i32)t0, 16); \ + t5 = __msa_srli_w((v4i32)t1, 16); \ + DOTP_SB2_SH(t4, t5, c1, c1, t2, t3); \ + SRAI_H2_SH(t2, t3, 5); \ + ADD2(t0, t2, t1, t3, t0, t1); \ + VSHF_B2_UB(src0, t0, src1, t1, mask1, mask1, dst0, dst1); \ +} while (0) + +#define TRANSFORM_COLOR_INVERSE_4(src, dst, c0, c1, mask0, mask1) do { \ + const v16i8 g0 = VSHF_SB(src, src, mask0); \ + v8i16 t0 = __msa_dotp_s_h(c0, g0); \ + v8i16 t1; \ + v4i32 t2; \ + t0 = SRAI_H(t0, 5); \ + t0 = __msa_addv_h(t0, (v8i16)src); \ + t2 = __msa_srli_w((v4i32)t0, 16); \ + t1 = __msa_dotp_s_h(c1, (v16i8)t2); \ + t1 = SRAI_H(t1, 5); \ + t0 = t0 + t1; \ + dst = VSHF_UB(src, t0, mask1); \ +} while (0) + +static void ConvertBGRAToRGBA_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int i; + const uint8_t* ptemp_src = (const uint8_t*)src; + uint8_t* ptemp_dst = (uint8_t*)dst; + v16u8 src0, dst0; + const v16u8 mask = { 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1; + LD_UB2(ptemp_src, 16, src0, src1); + VSHF_B2_UB(src0, src0, src1, src1, mask, mask, dst0, dst1); + ST_UB2(dst0, dst1, ptemp_dst, 16); + ptemp_src += 32; + ptemp_dst += 32; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(ptemp_src); + dst0 = VSHF_UB(src0, src0, mask); + ST_UB(dst0, ptemp_dst); + ptemp_src += 16; + ptemp_dst += 16; + num_pixels -= 4; + } + for (i = 0; i < num_pixels; i++) { + const uint8_t b = ptemp_src[2]; + const uint8_t g = ptemp_src[1]; + const uint8_t r = ptemp_src[0]; + const uint8_t a = ptemp_src[3]; + ptemp_dst[0] = b; + ptemp_dst[1] = g; + ptemp_dst[2] = r; + ptemp_dst[3] = a; + ptemp_src += 4; + ptemp_dst += 4; + } + } +} + +static void ConvertBGRAToBGR_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint8_t* ptemp_src = (const uint8_t*)src; + uint8_t* ptemp_dst = (uint8_t*)dst; + const v16u8 mask0 = { 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, + 16, 17, 18, 20 }; + const v16u8 mask1 = { 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, + 21, 22, 24, 25 }; + const v16u8 mask2 = { 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, 24, 25, + 26, 28, 29, 30 }; + + while (num_pixels >= 16) { + CONVERT16_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2); + ptemp_src += 64; + ptemp_dst += 48; + num_pixels -= 16; + } + if (num_pixels > 0) { + if (num_pixels >= 12) { + CONVERT12_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2); + ptemp_src += 48; + ptemp_dst += 36; + num_pixels -= 12; + } else if (num_pixels >= 8) { + CONVERT8_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1); + ptemp_src += 32; + ptemp_dst += 24; + num_pixels -= 8; + } else if (num_pixels >= 4) { + CONVERT4_BGRA_XXX(ptemp_src, ptemp_dst, mask0); + ptemp_src += 16; + ptemp_dst += 12; + num_pixels -= 4; + } + if (num_pixels == 3) { + CONVERT1_BGRA_BGR(ptemp_src + 0, ptemp_dst + 0); + CONVERT1_BGRA_BGR(ptemp_src + 4, ptemp_dst + 3); + CONVERT1_BGRA_BGR(ptemp_src + 8, ptemp_dst + 6); + } else if (num_pixels == 2) { + CONVERT1_BGRA_BGR(ptemp_src + 0, ptemp_dst + 0); + CONVERT1_BGRA_BGR(ptemp_src + 4, ptemp_dst + 3); + } else if (num_pixels == 1) { + CONVERT1_BGRA_BGR(ptemp_src, ptemp_dst); + } + } +} + +static void ConvertBGRAToRGB_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint8_t* ptemp_src = (const uint8_t*)src; + uint8_t* ptemp_dst = (uint8_t*)dst; + const v16u8 mask0 = { 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, + 18, 17, 16, 22 }; + const v16u8 mask1 = { 5, 4, 10, 9, 8, 14, 13, 12, 18, 17, 16, 22, + 21, 20, 26, 25 }; + const v16u8 mask2 = { 8, 14, 13, 12, 18, 17, 16, 22, 21, 20, 26, 25, + 24, 30, 29, 28 }; + + while (num_pixels >= 16) { + CONVERT16_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2); + ptemp_src += 64; + ptemp_dst += 48; + num_pixels -= 16; + } + if (num_pixels) { + if (num_pixels >= 12) { + CONVERT12_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2); + ptemp_src += 48; + ptemp_dst += 36; + num_pixels -= 12; + } else if (num_pixels >= 8) { + CONVERT8_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1); + ptemp_src += 32; + ptemp_dst += 24; + num_pixels -= 8; + } else if (num_pixels >= 4) { + CONVERT4_BGRA_XXX(ptemp_src, ptemp_dst, mask0); + ptemp_src += 16; + ptemp_dst += 12; + num_pixels -= 4; + } + if (num_pixels == 3) { + CONVERT1_BGRA_RGB(ptemp_src + 0, ptemp_dst + 0); + CONVERT1_BGRA_RGB(ptemp_src + 4, ptemp_dst + 3); + CONVERT1_BGRA_RGB(ptemp_src + 8, ptemp_dst + 6); + } else if (num_pixels == 2) { + CONVERT1_BGRA_RGB(ptemp_src + 0, ptemp_dst + 0); + CONVERT1_BGRA_RGB(ptemp_src + 4, ptemp_dst + 3); + } else if (num_pixels == 1) { + CONVERT1_BGRA_RGB(ptemp_src, ptemp_dst); + } + } +} + +static void AddGreenToBlueAndRed_MSA(const uint32_t* const src, int num_pixels, + uint32_t* dst) { + int i; + const uint8_t* in = (const uint8_t*)src; + uint8_t* out = (uint8_t*)dst; + v16u8 src0, dst0, tmp0; + const v16u8 mask = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, + 13, 255, 13, 255 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1, tmp1; + LD_UB2(in, 16, src0, src1); + VSHF_B2_UB(src0, src1, src1, src0, mask, mask, tmp0, tmp1); + ADD2(src0, tmp0, src1, tmp1, dst0, dst1); + ST_UB2(dst0, dst1, out, 16); + in += 32; + out += 32; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(in); + tmp0 = VSHF_UB(src0, src0, mask); + dst0 = src0 + tmp0; + ST_UB(dst0, out); + in += 16; + out += 16; + num_pixels -= 4; + } + for (i = 0; i < num_pixels; i++) { + const uint8_t b = in[0]; + const uint8_t g = in[1]; + const uint8_t r = in[2]; + out[0] = (b + g) & 0xff; + out[1] = g; + out[2] = (r + g) & 0xff; + out[4] = in[4]; + out += 4; + } + } +} + +static void TransformColorInverse_MSA(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst) { + v16u8 src0, dst0; + const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ | + (m->green_to_red_ << 16)); + const v16i8 r2b = (v16i8)__msa_fill_w(m->red_to_blue_); + const v16u8 mask0 = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, + 13, 255, 13, 255 }; + const v16u8 mask1 = { 16, 1, 18, 3, 20, 5, 22, 7, 24, 9, 26, 11, + 28, 13, 30, 15 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1; + LD_UB2(src, 4, src0, src1); + TRANSFORM_COLOR_INVERSE_8(src0, src1, dst0, dst1, g2br, r2b, mask0, mask1); + ST_UB2(dst0, dst1, dst, 4); + src += 8; + dst += 8; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(src); + TRANSFORM_COLOR_INVERSE_4(src0, dst0, g2br, r2b, mask0, mask1); + ST_UB(dst0, dst); + src += 4; + dst += 4; + num_pixels -= 4; + } + if (num_pixels > 0) { + src0 = LD_UB(src); + TRANSFORM_COLOR_INVERSE_4(src0, dst0, g2br, r2b, mask0, mask1); + if (num_pixels == 3) { + const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); + const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2); + SD(pix_d, dst + 0); + SW(pix_w, dst + 2); + } else if (num_pixels == 2) { + const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); + SD(pix_d, dst); + } else { + const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 0); + SW(pix_w, dst); + } + } + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMSA(void) { + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_MSA; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_MSA; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_MSA; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_MSA; + VP8LTransformColorInverse = TransformColorInverse_MSA; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8LDspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/libraries/webp/src/dsp/lossless_neon.c b/libraries/webp/src/dsp/lossless_neon.c new file mode 100644 index 0000000000..e9960db38a --- /dev/null +++ b/libraries/webp/src/dsp/lossless_neon.c @@ -0,0 +1,645 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON variant of methods for lossless decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include + +#include "src/dsp/lossless.h" +#include "src/dsp/neon.h" + +//------------------------------------------------------------------------------ +// Colorspace conversion functions + +#if !defined(WORK_AROUND_GCC) +// gcc 4.6.0 had some trouble (NDK-r9) with this code. We only use it for +// gcc-4.8.x at least. +static void ConvertBGRAToRGBA_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~15); + for (; src < end; src += 16) { + uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); + // swap B and R. (VSWP d0,d2 has no intrinsics equivalent!) + const uint8x16_t tmp = pixel.val[0]; + pixel.val[0] = pixel.val[2]; + pixel.val[2] = tmp; + vst4q_u8(dst, pixel); + dst += 64; + } + VP8LConvertBGRAToRGBA_C(src, num_pixels & 15, dst); // left-overs +} + +static void ConvertBGRAToBGR_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~15); + for (; src < end; src += 16) { + const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); + const uint8x16x3_t tmp = { { pixel.val[0], pixel.val[1], pixel.val[2] } }; + vst3q_u8(dst, tmp); + dst += 48; + } + VP8LConvertBGRAToBGR_C(src, num_pixels & 15, dst); // left-overs +} + +static void ConvertBGRAToRGB_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~15); + for (; src < end; src += 16) { + const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); + const uint8x16x3_t tmp = { { pixel.val[2], pixel.val[1], pixel.val[0] } }; + vst3q_u8(dst, tmp); + dst += 48; + } + VP8LConvertBGRAToRGB_C(src, num_pixels & 15, dst); // left-overs +} + +#else // WORK_AROUND_GCC + +// gcc-4.6.0 fallback + +static const uint8_t kRGBAShuffle[8] = { 2, 1, 0, 3, 6, 5, 4, 7 }; + +static void ConvertBGRAToRGBA_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~1); + const uint8x8_t shuffle = vld1_u8(kRGBAShuffle); + for (; src < end; src += 2) { + const uint8x8_t pixels = vld1_u8((uint8_t*)src); + vst1_u8(dst, vtbl1_u8(pixels, shuffle)); + dst += 8; + } + VP8LConvertBGRAToRGBA_C(src, num_pixels & 1, dst); // left-overs +} + +static const uint8_t kBGRShuffle[3][8] = { + { 0, 1, 2, 4, 5, 6, 8, 9 }, + { 10, 12, 13, 14, 16, 17, 18, 20 }, + { 21, 22, 24, 25, 26, 28, 29, 30 } +}; + +static void ConvertBGRAToBGR_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~7); + const uint8x8_t shuffle0 = vld1_u8(kBGRShuffle[0]); + const uint8x8_t shuffle1 = vld1_u8(kBGRShuffle[1]); + const uint8x8_t shuffle2 = vld1_u8(kBGRShuffle[2]); + for (; src < end; src += 8) { + uint8x8x4_t pixels; + INIT_VECTOR4(pixels, + vld1_u8((const uint8_t*)(src + 0)), + vld1_u8((const uint8_t*)(src + 2)), + vld1_u8((const uint8_t*)(src + 4)), + vld1_u8((const uint8_t*)(src + 6))); + vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0)); + vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1)); + vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2)); + dst += 8 * 3; + } + VP8LConvertBGRAToBGR_C(src, num_pixels & 7, dst); // left-overs +} + +static const uint8_t kRGBShuffle[3][8] = { + { 2, 1, 0, 6, 5, 4, 10, 9 }, + { 8, 14, 13, 12, 18, 17, 16, 22 }, + { 21, 20, 26, 25, 24, 30, 29, 28 } +}; + +static void ConvertBGRAToRGB_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~7); + const uint8x8_t shuffle0 = vld1_u8(kRGBShuffle[0]); + const uint8x8_t shuffle1 = vld1_u8(kRGBShuffle[1]); + const uint8x8_t shuffle2 = vld1_u8(kRGBShuffle[2]); + for (; src < end; src += 8) { + uint8x8x4_t pixels; + INIT_VECTOR4(pixels, + vld1_u8((const uint8_t*)(src + 0)), + vld1_u8((const uint8_t*)(src + 2)), + vld1_u8((const uint8_t*)(src + 4)), + vld1_u8((const uint8_t*)(src + 6))); + vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0)); + vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1)); + vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2)); + dst += 8 * 3; + } + VP8LConvertBGRAToRGB_C(src, num_pixels & 7, dst); // left-overs +} + +#endif // !WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Predictor Transform + +#define LOAD_U32_AS_U8(IN) vreinterpret_u8_u32(vdup_n_u32((IN))) +#define LOAD_U32P_AS_U8(IN) vreinterpret_u8_u32(vld1_u32((IN))) +#define LOADQ_U32_AS_U8(IN) vreinterpretq_u8_u32(vdupq_n_u32((IN))) +#define LOADQ_U32P_AS_U8(IN) vreinterpretq_u8_u32(vld1q_u32((IN))) +#define GET_U8_AS_U32(IN) vget_lane_u32(vreinterpret_u32_u8((IN)), 0) +#define GETQ_U8_AS_U32(IN) vgetq_lane_u32(vreinterpretq_u32_u8((IN)), 0) +#define STOREQ_U8_AS_U32P(OUT, IN) vst1q_u32((OUT), vreinterpretq_u32_u8((IN))) +#define ROTATE32_LEFT(L) vextq_u8((L), (L), 12) // D|C|B|A -> C|B|A|D + +static WEBP_INLINE uint8x8_t Average2_u8_NEON(uint32_t a0, uint32_t a1) { + const uint8x8_t A0 = LOAD_U32_AS_U8(a0); + const uint8x8_t A1 = LOAD_U32_AS_U8(a1); + return vhadd_u8(A0, A1); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf_NEON(uint32_t c0, + uint32_t c1, + uint32_t c2) { + const uint8x8_t avg = Average2_u8_NEON(c0, c1); + // Remove one to c2 when bigger than avg. + const uint8x8_t C2 = LOAD_U32_AS_U8(c2); + const uint8x8_t cmp = vcgt_u8(C2, avg); + const uint8x8_t C2_1 = vadd_u8(C2, cmp); + // Compute half of the difference between avg and c2. + const int8x8_t diff_avg = vreinterpret_s8_u8(vhsub_u8(avg, C2_1)); + // Compute the sum with avg and saturate. + const int16x8_t avg_16 = vreinterpretq_s16_u16(vmovl_u8(avg)); + const uint8x8_t res = vqmovun_s16(vaddw_s8(avg_16, diff_avg)); + const uint32_t output = GET_U8_AS_U32(res); + return output; +} + +static WEBP_INLINE uint32_t Average2_NEON(uint32_t a0, uint32_t a1) { + const uint8x8_t avg_u8x8 = Average2_u8_NEON(a0, a1); + const uint32_t avg = GET_U8_AS_U32(avg_u8x8); + return avg; +} + +static WEBP_INLINE uint32_t Average3_NEON(uint32_t a0, uint32_t a1, + uint32_t a2) { + const uint8x8_t avg0 = Average2_u8_NEON(a0, a2); + const uint8x8_t A1 = LOAD_U32_AS_U8(a1); + const uint32_t avg = GET_U8_AS_U32(vhadd_u8(avg0, A1)); + return avg; +} + +static uint32_t Predictor5_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average3_NEON(*left, top[0], top[1]); +} +static uint32_t Predictor6_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average2_NEON(*left, top[-1]); +} +static uint32_t Predictor7_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average2_NEON(*left, top[0]); +} +static uint32_t Predictor13_NEON(const uint32_t* const left, + const uint32_t* const top) { + return ClampedAddSubtractHalf_NEON(*left, top[0], top[-1]); +} + +// Batch versions of those functions. + +// Predictor0: ARGB_BLACK. +static void PredictorAdd0_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const uint8x16_t black = vreinterpretq_u8_u32(vdupq_n_u32(ARGB_BLACK)); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t res = vaddq_u8(src, black); + STOREQ_U8_AS_U32P(&out[i], res); + } + VP8LPredictorsAdd_C[0](in + i, upper + i, num_pixels - i, out + i); +} + +// Predictor1: left. +static void PredictorAdd1_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const uint8x16_t zero = LOADQ_U32_AS_U8(0); + for (i = 0; i + 4 <= num_pixels; i += 4) { + // a | b | c | d + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + // 0 | a | b | c + const uint8x16_t shift0 = vextq_u8(zero, src, 12); + // a | a + b | b + c | c + d + const uint8x16_t sum0 = vaddq_u8(src, shift0); + // 0 | 0 | a | a + b + const uint8x16_t shift1 = vextq_u8(zero, sum0, 8); + // a | a + b | a + b + c | a + b + c + d + const uint8x16_t sum1 = vaddq_u8(sum0, shift1); + const uint8x16_t prev = LOADQ_U32_AS_U8(out[i - 1]); + const uint8x16_t res = vaddq_u8(sum1, prev); + STOREQ_U8_AS_U32P(&out[i], res); + } + VP8LPredictorsAdd_C[1](in + i, upper + i, num_pixels - i, out + i); +} + +// Macro that adds 32-bit integers from IN using mod 256 arithmetic +// per 8 bit channel. +#define GENERATE_PREDICTOR_1(X, IN) \ +static void PredictorAdd##X##_NEON(const uint32_t* in, \ + const uint32_t* upper, int num_pixels, \ + uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); \ + const uint8x16_t other = LOADQ_U32P_AS_U8(&(IN)); \ + const uint8x16_t res = vaddq_u8(src, other); \ + STOREQ_U8_AS_U32P(&out[i], res); \ + } \ + VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ +} +// Predictor2: Top. +GENERATE_PREDICTOR_1(2, upper[i]) +// Predictor3: Top-right. +GENERATE_PREDICTOR_1(3, upper[i + 1]) +// Predictor4: Top-left. +GENERATE_PREDICTOR_1(4, upper[i - 1]) +#undef GENERATE_PREDICTOR_1 + +// Predictor5: average(average(left, TR), T) +#define DO_PRED5(LANE) do { \ + const uint8x16_t avgLTR = vhaddq_u8(L, TR); \ + const uint8x16_t avg = vhaddq_u8(avgLTR, T); \ + const uint8x16_t res = vaddq_u8(avg, src); \ + vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \ + L = ROTATE32_LEFT(res); \ +} while (0) + +static void PredictorAdd5_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i + 0]); + const uint8x16_t TR = LOADQ_U32P_AS_U8(&upper[i + 1]); + DO_PRED5(0); + DO_PRED5(1); + DO_PRED5(2); + DO_PRED5(3); + } + VP8LPredictorsAdd_C[5](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED5 + +#define DO_PRED67(LANE) do { \ + const uint8x16_t avg = vhaddq_u8(L, top); \ + const uint8x16_t res = vaddq_u8(avg, src); \ + vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \ + L = ROTATE32_LEFT(res); \ +} while (0) + +// Predictor6: average(left, TL) +static void PredictorAdd6_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t top = LOADQ_U32P_AS_U8(&upper[i - 1]); + DO_PRED67(0); + DO_PRED67(1); + DO_PRED67(2); + DO_PRED67(3); + } + VP8LPredictorsAdd_C[6](in + i, upper + i, num_pixels - i, out + i); +} + +// Predictor7: average(left, T) +static void PredictorAdd7_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t top = LOADQ_U32P_AS_U8(&upper[i]); + DO_PRED67(0); + DO_PRED67(1); + DO_PRED67(2); + DO_PRED67(3); + } + VP8LPredictorsAdd_C[7](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED67 + +#define GENERATE_PREDICTOR_2(X, IN) \ +static void PredictorAdd##X##_NEON(const uint32_t* in, \ + const uint32_t* upper, int num_pixels, \ + uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); \ + const uint8x16_t Tother = LOADQ_U32P_AS_U8(&(IN)); \ + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); \ + const uint8x16_t avg = vhaddq_u8(T, Tother); \ + const uint8x16_t res = vaddq_u8(avg, src); \ + STOREQ_U8_AS_U32P(&out[i], res); \ + } \ + VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ +} +// Predictor8: average TL T. +GENERATE_PREDICTOR_2(8, upper[i - 1]) +// Predictor9: average T TR. +GENERATE_PREDICTOR_2(9, upper[i + 1]) +#undef GENERATE_PREDICTOR_2 + +// Predictor10: average of (average of (L,TL), average of (T, TR)). +#define DO_PRED10(LANE) do { \ + const uint8x16_t avgLTL = vhaddq_u8(L, TL); \ + const uint8x16_t avg = vhaddq_u8(avgTTR, avgLTL); \ + const uint8x16_t res = vaddq_u8(avg, src); \ + vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \ + L = ROTATE32_LEFT(res); \ +} while (0) + +static void PredictorAdd10_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]); + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); + const uint8x16_t TR = LOADQ_U32P_AS_U8(&upper[i + 1]); + const uint8x16_t avgTTR = vhaddq_u8(T, TR); + DO_PRED10(0); + DO_PRED10(1); + DO_PRED10(2); + DO_PRED10(3); + } + VP8LPredictorsAdd_C[10](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED10 + +// Predictor11: select. +#define DO_PRED11(LANE) do { \ + const uint8x16_t sumLin = vaddq_u8(L, src); /* in + L */ \ + const uint8x16_t pLTL = vabdq_u8(L, TL); /* |L - TL| */ \ + const uint16x8_t sum_LTL = vpaddlq_u8(pLTL); \ + const uint32x4_t pa = vpaddlq_u16(sum_LTL); \ + const uint32x4_t mask = vcleq_u32(pa, pb); \ + const uint8x16_t res = vbslq_u8(vreinterpretq_u8_u32(mask), sumTin, sumLin); \ + vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \ + L = ROTATE32_LEFT(res); \ +} while (0) + +static void PredictorAdd11_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); + const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]); + const uint8x16_t pTTL = vabdq_u8(T, TL); // |T - TL| + const uint16x8_t sum_TTL = vpaddlq_u8(pTTL); + const uint32x4_t pb = vpaddlq_u16(sum_TTL); + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t sumTin = vaddq_u8(T, src); // in + T + DO_PRED11(0); + DO_PRED11(1); + DO_PRED11(2); + DO_PRED11(3); + } + VP8LPredictorsAdd_C[11](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED11 + +// Predictor12: ClampedAddSubtractFull. +#define DO_PRED12(DIFF, LANE) do { \ + const uint8x8_t pred = \ + vqmovun_s16(vaddq_s16(vreinterpretq_s16_u16(L), (DIFF))); \ + const uint8x8_t res = \ + vadd_u8(pred, (LANE <= 1) ? vget_low_u8(src) : vget_high_u8(src)); \ + const uint16x8_t res16 = vmovl_u8(res); \ + vst1_lane_u32(&out[i + (LANE)], vreinterpret_u32_u8(res), (LANE) & 1); \ + /* rotate in the left predictor for next iteration */ \ + L = vextq_u16(res16, res16, 4); \ +} while (0) + +static void PredictorAdd12_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint16x8_t L = vmovl_u8(LOAD_U32_AS_U8(out[-1])); + for (i = 0; i + 4 <= num_pixels; i += 4) { + // load four pixels of source + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + // precompute the difference T - TL once for all, stored as s16 + const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]); + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); + const int16x8_t diff_lo = + vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), vget_low_u8(TL))); + const int16x8_t diff_hi = + vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), vget_high_u8(TL))); + // loop over the four reconstructed pixels + DO_PRED12(diff_lo, 0); + DO_PRED12(diff_lo, 1); + DO_PRED12(diff_hi, 2); + DO_PRED12(diff_hi, 3); + } + VP8LPredictorsAdd_C[12](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED12 + +// Predictor13: ClampedAddSubtractHalf +#define DO_PRED13(LANE, LOW_OR_HI) do { \ + const uint8x16_t avg = vhaddq_u8(L, T); \ + const uint8x16_t cmp = vcgtq_u8(TL, avg); \ + const uint8x16_t TL_1 = vaddq_u8(TL, cmp); \ + /* Compute half of the difference between avg and TL'. */ \ + const int8x8_t diff_avg = \ + vreinterpret_s8_u8(LOW_OR_HI(vhsubq_u8(avg, TL_1))); \ + /* Compute the sum with avg and saturate. */ \ + const int16x8_t avg_16 = vreinterpretq_s16_u16(vmovl_u8(LOW_OR_HI(avg))); \ + const uint8x8_t delta = vqmovun_s16(vaddw_s8(avg_16, diff_avg)); \ + const uint8x8_t res = vadd_u8(LOW_OR_HI(src), delta); \ + const uint8x16_t res2 = vcombine_u8(res, res); \ + vst1_lane_u32(&out[i + (LANE)], vreinterpret_u32_u8(res), (LANE) & 1); \ + L = ROTATE32_LEFT(res2); \ +} while (0) + +static void PredictorAdd13_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); + const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]); + DO_PRED13(0, vget_low_u8); + DO_PRED13(1, vget_low_u8); + DO_PRED13(2, vget_high_u8); + DO_PRED13(3, vget_high_u8); + } + VP8LPredictorsAdd_C[13](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED13 + +#undef LOAD_U32_AS_U8 +#undef LOAD_U32P_AS_U8 +#undef LOADQ_U32_AS_U8 +#undef LOADQ_U32P_AS_U8 +#undef GET_U8_AS_U32 +#undef GETQ_U8_AS_U32 +#undef STOREQ_U8_AS_U32P +#undef ROTATE32_LEFT + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use +// non-standard versions there. +#if defined(__APPLE__) && WEBP_AARCH64 && \ + defined(__apple_build_version__) && (__apple_build_version__< 6020037) +#define USE_VTBLQ +#endif + +#ifdef USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[16] = { + 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 +}; + +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x16_t shuffle) { + return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), + vtbl1q_u8(argb, vget_high_u8(shuffle))); +} +#else // !USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; + +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x8_t shuffle) { + return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), + vtbl1_u8(vget_high_u8(argb), shuffle)); +} +#endif // USE_VTBLQ + +static void AddGreenToBlueAndRed_NEON(const uint32_t* src, int num_pixels, + uint32_t* dst) { + const uint32_t* const end = src + (num_pixels & ~3); +#ifdef USE_VTBLQ + const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); +#else + const uint8x8_t shuffle = vld1_u8(kGreenShuffle); +#endif + for (; src < end; src += 4, dst += 4) { + const uint8x16_t argb = vld1q_u8((const uint8_t*)src); + const uint8x16_t greens = DoGreenShuffle_NEON(argb, shuffle); + vst1q_u8((uint8_t*)dst, vaddq_u8(argb, greens)); + } + // fallthrough and finish off with plain-C + VP8LAddGreenToBlueAndRed_C(src, num_pixels & 3, dst); +} + +//------------------------------------------------------------------------------ +// Color Transform + +static void TransformColorInverse_NEON(const VP8LMultipliers* const m, + const uint32_t* const src, + int num_pixels, uint32_t* dst) { +// sign-extended multiplying constants, pre-shifted by 6. +#define CST(X) (((int16_t)(m->X << 8)) >> 6) + const int16_t rb[8] = { + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_) + }; + const int16x8_t mults_rb = vld1q_s16(rb); + const int16_t b2[8] = { + 0, CST(red_to_blue_), 0, CST(red_to_blue_), + 0, CST(red_to_blue_), 0, CST(red_to_blue_), + }; + const int16x8_t mults_b2 = vld1q_s16(b2); +#undef CST +#ifdef USE_VTBLQ + static const uint8_t kg0g0[16] = { + 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13 + }; + const uint8x16_t shuffle = vld1q_u8(kg0g0); +#else + static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 }; + const uint8x8_t shuffle = vld1_u8(k0g0g); +#endif + const uint32x4_t mask_ag = vdupq_n_u32(0xff00ff00u); + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t in = vld1q_u8((const uint8_t*)(src + i)); + const uint32x4_t a0g0 = vandq_u32(vreinterpretq_u32_u8(in), mask_ag); + // 0 g 0 g + const uint8x16_t greens = DoGreenShuffle_NEON(in, shuffle); + // x dr x db1 + const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); + // x r' x b' + const int8x16_t B = vaddq_s8(vreinterpretq_s8_u8(in), + vreinterpretq_s8_s16(A)); + // r' 0 b' 0 + const int16x8_t C = vshlq_n_s16(vreinterpretq_s16_s8(B), 8); + // x db2 0 0 + const int16x8_t D = vqdmulhq_s16(C, mults_b2); + // 0 x db2 0 + const uint32x4_t E = vshrq_n_u32(vreinterpretq_u32_s16(D), 8); + // r' x b'' 0 + const int8x16_t F = vaddq_s8(vreinterpretq_s8_u32(E), + vreinterpretq_s8_s16(C)); + // 0 r' 0 b'' + const uint16x8_t G = vshrq_n_u16(vreinterpretq_u16_s8(F), 8); + const uint32x4_t out = vorrq_u32(vreinterpretq_u32_u16(G), a0g0); + vst1q_u32(dst + i, out); + } + // Fall-back to C-version for left-overs. + VP8LTransformColorInverse_C(m, src + i, num_pixels - i, dst + i); +} + +#undef USE_VTBLQ + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitNEON(void) { + VP8LPredictors[5] = Predictor5_NEON; + VP8LPredictors[6] = Predictor6_NEON; + VP8LPredictors[7] = Predictor7_NEON; + VP8LPredictors[13] = Predictor13_NEON; + + VP8LPredictorsAdd[0] = PredictorAdd0_NEON; + VP8LPredictorsAdd[1] = PredictorAdd1_NEON; + VP8LPredictorsAdd[2] = PredictorAdd2_NEON; + VP8LPredictorsAdd[3] = PredictorAdd3_NEON; + VP8LPredictorsAdd[4] = PredictorAdd4_NEON; + VP8LPredictorsAdd[5] = PredictorAdd5_NEON; + VP8LPredictorsAdd[6] = PredictorAdd6_NEON; + VP8LPredictorsAdd[7] = PredictorAdd7_NEON; + VP8LPredictorsAdd[8] = PredictorAdd8_NEON; + VP8LPredictorsAdd[9] = PredictorAdd9_NEON; + VP8LPredictorsAdd[10] = PredictorAdd10_NEON; + VP8LPredictorsAdd[11] = PredictorAdd11_NEON; + VP8LPredictorsAdd[12] = PredictorAdd12_NEON; + VP8LPredictorsAdd[13] = PredictorAdd13_NEON; + + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_NEON; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_NEON; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_NEON; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_NEON; + VP8LTransformColorInverse = TransformColorInverse_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8LDspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/lossless_sse2.c b/libraries/webp/src/dsp/lossless_sse2.c new file mode 100644 index 0000000000..4b6a532c23 --- /dev/null +++ b/libraries/webp/src/dsp/lossless_sse2.c @@ -0,0 +1,712 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 variant of methods for lossless decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include "src/dsp/common_sse2.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include + +//------------------------------------------------------------------------------ +// Predictor Transform + +static WEBP_INLINE uint32_t ClampedAddSubtractFull_SSE2(uint32_t c0, + uint32_t c1, + uint32_t c2) { + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c0), zero); + const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c1), zero); + const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c2), zero); + const __m128i V1 = _mm_add_epi16(C0, C1); + const __m128i V2 = _mm_sub_epi16(V1, C2); + const __m128i b = _mm_packus_epi16(V2, V2); + return (uint32_t)_mm_cvtsi128_si32(b); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf_SSE2(uint32_t c0, + uint32_t c1, + uint32_t c2) { + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c0), zero); + const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c1), zero); + const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c2), zero); + const __m128i avg = _mm_add_epi16(C1, C0); + const __m128i A0 = _mm_srli_epi16(avg, 1); + const __m128i A1 = _mm_sub_epi16(A0, B0); + const __m128i BgtA = _mm_cmpgt_epi16(B0, A0); + const __m128i A2 = _mm_sub_epi16(A1, BgtA); + const __m128i A3 = _mm_srai_epi16(A2, 1); + const __m128i A4 = _mm_add_epi16(A0, A3); + const __m128i A5 = _mm_packus_epi16(A4, A4); + return (uint32_t)_mm_cvtsi128_si32(A5); +} + +static WEBP_INLINE uint32_t Select_SSE2(uint32_t a, uint32_t b, uint32_t c) { + int pa_minus_pb; + const __m128i zero = _mm_setzero_si128(); + const __m128i A0 = _mm_cvtsi32_si128((int)a); + const __m128i B0 = _mm_cvtsi32_si128((int)b); + const __m128i C0 = _mm_cvtsi32_si128((int)c); + const __m128i AC0 = _mm_subs_epu8(A0, C0); + const __m128i CA0 = _mm_subs_epu8(C0, A0); + const __m128i BC0 = _mm_subs_epu8(B0, C0); + const __m128i CB0 = _mm_subs_epu8(C0, B0); + const __m128i AC = _mm_or_si128(AC0, CA0); + const __m128i BC = _mm_or_si128(BC0, CB0); + const __m128i pa = _mm_unpacklo_epi8(AC, zero); // |a - c| + const __m128i pb = _mm_unpacklo_epi8(BC, zero); // |b - c| + const __m128i diff = _mm_sub_epi16(pb, pa); + { + int16_t out[8]; + _mm_storeu_si128((__m128i*)out, diff); + pa_minus_pb = out[0] + out[1] + out[2] + out[3]; + } + return (pa_minus_pb <= 0) ? a : b; +} + +static WEBP_INLINE void Average2_m128i(const __m128i* const a0, + const __m128i* const a1, + __m128i* const avg) { + // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1) + const __m128i ones = _mm_set1_epi8(1); + const __m128i avg1 = _mm_avg_epu8(*a0, *a1); + const __m128i one = _mm_and_si128(_mm_xor_si128(*a0, *a1), ones); + *avg = _mm_sub_epi8(avg1, one); +} + +static WEBP_INLINE void Average2_uint32_SSE2(const uint32_t a0, + const uint32_t a1, + __m128i* const avg) { + // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1) + const __m128i ones = _mm_set1_epi8(1); + const __m128i A0 = _mm_cvtsi32_si128((int)a0); + const __m128i A1 = _mm_cvtsi32_si128((int)a1); + const __m128i avg1 = _mm_avg_epu8(A0, A1); + const __m128i one = _mm_and_si128(_mm_xor_si128(A0, A1), ones); + *avg = _mm_sub_epi8(avg1, one); +} + +static WEBP_INLINE __m128i Average2_uint32_16_SSE2(uint32_t a0, uint32_t a1) { + const __m128i zero = _mm_setzero_si128(); + const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a0), zero); + const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a1), zero); + const __m128i sum = _mm_add_epi16(A1, A0); + return _mm_srli_epi16(sum, 1); +} + +static WEBP_INLINE uint32_t Average2_SSE2(uint32_t a0, uint32_t a1) { + __m128i output; + Average2_uint32_SSE2(a0, a1, &output); + return (uint32_t)_mm_cvtsi128_si32(output); +} + +static WEBP_INLINE uint32_t Average3_SSE2(uint32_t a0, uint32_t a1, + uint32_t a2) { + const __m128i zero = _mm_setzero_si128(); + const __m128i avg1 = Average2_uint32_16_SSE2(a0, a2); + const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a1), zero); + const __m128i sum = _mm_add_epi16(avg1, A1); + const __m128i avg2 = _mm_srli_epi16(sum, 1); + const __m128i A2 = _mm_packus_epi16(avg2, avg2); + return (uint32_t)_mm_cvtsi128_si32(A2); +} + +static WEBP_INLINE uint32_t Average4_SSE2(uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) { + const __m128i avg1 = Average2_uint32_16_SSE2(a0, a1); + const __m128i avg2 = Average2_uint32_16_SSE2(a2, a3); + const __m128i sum = _mm_add_epi16(avg2, avg1); + const __m128i avg3 = _mm_srli_epi16(sum, 1); + const __m128i A0 = _mm_packus_epi16(avg3, avg3); + return (uint32_t)_mm_cvtsi128_si32(A0); +} + +static uint32_t Predictor5_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average3_SSE2(*left, top[0], top[1]); + return pred; +} +static uint32_t Predictor6_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(*left, top[-1]); + return pred; +} +static uint32_t Predictor7_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(*left, top[0]); + return pred; +} +static uint32_t Predictor8_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(top[-1], top[0]); + (void)left; + return pred; +} +static uint32_t Predictor9_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(top[0], top[1]); + (void)left; + return pred; +} +static uint32_t Predictor10_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average4_SSE2(*left, top[-1], top[0], top[1]); + return pred; +} +static uint32_t Predictor11_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Select_SSE2(top[0], *left, top[-1]); + return pred; +} +static uint32_t Predictor12_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractFull_SSE2(*left, top[0], top[-1]); + return pred; +} +static uint32_t Predictor13_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractHalf_SSE2(*left, top[0], top[-1]); + return pred; +} + +// Batch versions of those functions. + +// Predictor0: ARGB_BLACK. +static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i black = _mm_set1_epi32((int)ARGB_BLACK); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i res = _mm_add_epi8(src, black); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[0](in + i, NULL, num_pixels - i, out + i); + } + (void)upper; +} + +// Predictor1: left. +static void PredictorAdd1_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + __m128i prev = _mm_set1_epi32((int)out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + // a | b | c | d + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + // 0 | a | b | c + const __m128i shift0 = _mm_slli_si128(src, 4); + // a | a + b | b + c | c + d + const __m128i sum0 = _mm_add_epi8(src, shift0); + // 0 | 0 | a | a + b + const __m128i shift1 = _mm_slli_si128(sum0, 8); + // a | a + b | a + b + c | a + b + c + d + const __m128i sum1 = _mm_add_epi8(sum0, shift1); + const __m128i res = _mm_add_epi8(sum1, prev); + _mm_storeu_si128((__m128i*)&out[i], res); + // replicate prev output on the four lanes + prev = _mm_shuffle_epi32(res, (3 << 0) | (3 << 2) | (3 << 4) | (3 << 6)); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[1](in + i, upper + i, num_pixels - i, out + i); + } +} + +// Macro that adds 32-bit integers from IN using mod 256 arithmetic +// per 8 bit channel. +#define GENERATE_PREDICTOR_1(X, IN) \ +static void PredictorAdd##X##_SSE2(const uint32_t* in, const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \ + const __m128i other = _mm_loadu_si128((const __m128i*)&(IN)); \ + const __m128i res = _mm_add_epi8(src, other); \ + _mm_storeu_si128((__m128i*)&out[i], res); \ + } \ + if (i != num_pixels) { \ + VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ + } \ +} + +// Predictor2: Top. +GENERATE_PREDICTOR_1(2, upper[i]) +// Predictor3: Top-right. +GENERATE_PREDICTOR_1(3, upper[i + 1]) +// Predictor4: Top-left. +GENERATE_PREDICTOR_1(4, upper[i - 1]) +#undef GENERATE_PREDICTOR_1 + +// Due to averages with integers, values cannot be accumulated in parallel for +// predictors 5 to 7. +GENERATE_PREDICTOR_ADD(Predictor5_SSE2, PredictorAdd5_SSE2) +GENERATE_PREDICTOR_ADD(Predictor6_SSE2, PredictorAdd6_SSE2) +GENERATE_PREDICTOR_ADD(Predictor7_SSE2, PredictorAdd7_SSE2) + +#define GENERATE_PREDICTOR_2(X, IN) \ +static void PredictorAdd##X##_SSE2(const uint32_t* in, const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const __m128i Tother = _mm_loadu_si128((const __m128i*)&(IN)); \ + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); \ + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \ + __m128i avg, res; \ + Average2_m128i(&T, &Tother, &avg); \ + res = _mm_add_epi8(avg, src); \ + _mm_storeu_si128((__m128i*)&out[i], res); \ + } \ + if (i != num_pixels) { \ + VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ + } \ +} +// Predictor8: average TL T. +GENERATE_PREDICTOR_2(8, upper[i - 1]) +// Predictor9: average T TR. +GENERATE_PREDICTOR_2(9, upper[i + 1]) +#undef GENERATE_PREDICTOR_2 + +// Predictor10: average of (average of (L,TL), average of (T, TR)). +#define DO_PRED10(OUT) do { \ + __m128i avgLTL, avg; \ + Average2_m128i(&L, &TL, &avgLTL); \ + Average2_m128i(&avgTTR, &avgLTL, &avg); \ + L = _mm_add_epi8(avg, src); \ + out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(L); \ +} while (0) + +#define DO_PRED10_SHIFT do { \ + /* Rotate the pre-computed values for the next iteration.*/ \ + avgTTR = _mm_srli_si128(avgTTR, 4); \ + TL = _mm_srli_si128(TL, 4); \ + src = _mm_srli_si128(src, 4); \ +} while (0) + +static void PredictorAdd10_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + __m128i L = _mm_cvtsi32_si128((int)out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]); + __m128i avgTTR; + Average2_m128i(&T, &TR, &avgTTR); + DO_PRED10(0); + DO_PRED10_SHIFT; + DO_PRED10(1); + DO_PRED10_SHIFT; + DO_PRED10(2); + DO_PRED10_SHIFT; + DO_PRED10(3); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[10](in + i, upper + i, num_pixels - i, out + i); + } +} +#undef DO_PRED10 +#undef DO_PRED10_SHIFT + +// Predictor11: select. +#define DO_PRED11(OUT) do { \ + const __m128i L_lo = _mm_unpacklo_epi32(L, T); \ + const __m128i TL_lo = _mm_unpacklo_epi32(TL, T); \ + const __m128i pb = _mm_sad_epu8(L_lo, TL_lo); /* pb = sum |L-TL|*/ \ + const __m128i mask = _mm_cmpgt_epi32(pb, pa); \ + const __m128i A = _mm_and_si128(mask, L); \ + const __m128i B = _mm_andnot_si128(mask, T); \ + const __m128i pred = _mm_or_si128(A, B); /* pred = (pa > b)? L : T*/ \ + L = _mm_add_epi8(src, pred); \ + out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(L); \ +} while (0) + +#define DO_PRED11_SHIFT do { \ + /* Shift the pre-computed value for the next iteration.*/ \ + T = _mm_srli_si128(T, 4); \ + TL = _mm_srli_si128(TL, 4); \ + src = _mm_srli_si128(src, 4); \ + pa = _mm_srli_si128(pa, 4); \ +} while (0) + +static void PredictorAdd11_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + __m128i pa; + __m128i L = _mm_cvtsi32_si128((int)out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + { + // We can unpack with any value on the upper 32 bits, provided it's the + // same on both operands (so that their sum of abs diff is zero). Here we + // use T. + const __m128i T_lo = _mm_unpacklo_epi32(T, T); + const __m128i TL_lo = _mm_unpacklo_epi32(TL, T); + const __m128i T_hi = _mm_unpackhi_epi32(T, T); + const __m128i TL_hi = _mm_unpackhi_epi32(TL, T); + const __m128i s_lo = _mm_sad_epu8(T_lo, TL_lo); + const __m128i s_hi = _mm_sad_epu8(T_hi, TL_hi); + pa = _mm_packs_epi32(s_lo, s_hi); // pa = sum |T-TL| + } + DO_PRED11(0); + DO_PRED11_SHIFT; + DO_PRED11(1); + DO_PRED11_SHIFT; + DO_PRED11(2); + DO_PRED11_SHIFT; + DO_PRED11(3); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[11](in + i, upper + i, num_pixels - i, out + i); + } +} +#undef DO_PRED11 +#undef DO_PRED11_SHIFT + +// Predictor12: ClampedAddSubtractFull. +#define DO_PRED12(DIFF, LANE, OUT) do { \ + const __m128i all = _mm_add_epi16(L, (DIFF)); \ + const __m128i alls = _mm_packus_epi16(all, all); \ + const __m128i res = _mm_add_epi8(src, alls); \ + out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(res); \ + L = _mm_unpacklo_epi8(res, zero); \ +} while (0) + +#define DO_PRED12_SHIFT(DIFF, LANE) do { \ + /* Shift the pre-computed value for the next iteration.*/ \ + if ((LANE) == 0) (DIFF) = _mm_srli_si128((DIFF), 8); \ + src = _mm_srli_si128(src, 4); \ +} while (0) + +static void PredictorAdd12_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i zero = _mm_setzero_si128(); + const __m128i L8 = _mm_cvtsi32_si128((int)out[-1]); + __m128i L = _mm_unpacklo_epi8(L8, zero); + for (i = 0; i + 4 <= num_pixels; i += 4) { + // Load 4 pixels at a time. + __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i T_lo = _mm_unpacklo_epi8(T, zero); + const __m128i T_hi = _mm_unpackhi_epi8(T, zero); + const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero); + const __m128i TL_hi = _mm_unpackhi_epi8(TL, zero); + __m128i diff_lo = _mm_sub_epi16(T_lo, TL_lo); + __m128i diff_hi = _mm_sub_epi16(T_hi, TL_hi); + DO_PRED12(diff_lo, 0, 0); + DO_PRED12_SHIFT(diff_lo, 0); + DO_PRED12(diff_lo, 1, 1); + DO_PRED12_SHIFT(diff_lo, 1); + DO_PRED12(diff_hi, 0, 2); + DO_PRED12_SHIFT(diff_hi, 0); + DO_PRED12(diff_hi, 1, 3); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[12](in + i, upper + i, num_pixels - i, out + i); + } +} +#undef DO_PRED12 +#undef DO_PRED12_SHIFT + +// Due to averages with integers, values cannot be accumulated in parallel for +// predictors 13. +GENERATE_PREDICTOR_ADD(Predictor13_SSE2, PredictorAdd13_SSE2) + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +static void AddGreenToBlueAndRed_SSE2(const uint32_t* const src, int num_pixels, + uint32_t* dst) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((const __m128i*)&src[i]); // argb + const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g + const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); + const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g + const __m128i out = _mm_add_epi8(in, C); + _mm_storeu_si128((__m128i*)&dst[i], out); + } + // fallthrough and finish off with plain-C + if (i != num_pixels) { + VP8LAddGreenToBlueAndRed_C(src + i, num_pixels - i, dst + i); + } +} + +//------------------------------------------------------------------------------ +// Color Transform + +static void TransformColorInverse_SSE2(const VP8LMultipliers* const m, + const uint32_t* const src, + int num_pixels, uint32_t* dst) { +// sign-extended multiplying constants, pre-shifted by 5. +#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend +#define MK_CST_16(HI, LO) \ + _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff))) + const __m128i mults_rb = MK_CST_16(CST(green_to_red_), CST(green_to_blue_)); + const __m128i mults_b2 = MK_CST_16(CST(red_to_blue_), 0); +#undef MK_CST_16 +#undef CST + const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00); // alpha-green masks + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((const __m128i*)&src[i]); // argb + const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0 + const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); + const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0 + const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1 + const __m128i E = _mm_add_epi8(in, D); // x r' x b' + const __m128i F = _mm_slli_epi16(E, 8); // r' 0 b' 0 + const __m128i G = _mm_mulhi_epi16(F, mults_b2); // x db2 0 0 + const __m128i H = _mm_srli_epi32(G, 8); // 0 x db2 0 + const __m128i I = _mm_add_epi8(H, F); // r' x b'' 0 + const __m128i J = _mm_srli_epi16(I, 8); // 0 r' 0 b'' + const __m128i out = _mm_or_si128(J, A); + _mm_storeu_si128((__m128i*)&dst[i], out); + } + // Fall-back to C-version for left-overs. + if (i != num_pixels) { + VP8LTransformColorInverse_C(m, src + i, num_pixels - i, dst + i); + } +} + +//------------------------------------------------------------------------------ +// Color-space conversion functions + +static void ConvertBGRAToRGB_SSE2(const uint32_t* src, int num_pixels, + uint8_t* dst) { + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + + while (num_pixels >= 32) { + // Load the BGRA buffers. + __m128i in0 = _mm_loadu_si128(in + 0); + __m128i in1 = _mm_loadu_si128(in + 1); + __m128i in2 = _mm_loadu_si128(in + 2); + __m128i in3 = _mm_loadu_si128(in + 3); + __m128i in4 = _mm_loadu_si128(in + 4); + __m128i in5 = _mm_loadu_si128(in + 5); + __m128i in6 = _mm_loadu_si128(in + 6); + __m128i in7 = _mm_loadu_si128(in + 7); + VP8L32bToPlanar_SSE2(&in0, &in1, &in2, &in3); + VP8L32bToPlanar_SSE2(&in4, &in5, &in6, &in7); + // At this points, in1/in5 contains red only, in2/in6 green only ... + // Pack the colors in 24b RGB. + VP8PlanarTo24b_SSE2(&in1, &in5, &in2, &in6, &in3, &in7); + _mm_storeu_si128(out + 0, in1); + _mm_storeu_si128(out + 1, in5); + _mm_storeu_si128(out + 2, in2); + _mm_storeu_si128(out + 3, in6); + _mm_storeu_si128(out + 4, in3); + _mm_storeu_si128(out + 5, in7); + in += 8; + out += 6; + num_pixels -= 32; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGB_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToRGBA_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ff); + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + while (num_pixels >= 8) { + const __m128i A1 = _mm_loadu_si128(in++); + const __m128i A2 = _mm_loadu_si128(in++); + const __m128i B1 = _mm_and_si128(A1, red_blue_mask); // R 0 B 0 + const __m128i B2 = _mm_and_si128(A2, red_blue_mask); // R 0 B 0 + const __m128i C1 = _mm_andnot_si128(red_blue_mask, A1); // 0 G 0 A + const __m128i C2 = _mm_andnot_si128(red_blue_mask, A2); // 0 G 0 A + const __m128i D1 = _mm_shufflelo_epi16(B1, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i D2 = _mm_shufflelo_epi16(B2, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i E1 = _mm_shufflehi_epi16(D1, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i E2 = _mm_shufflehi_epi16(D2, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i F1 = _mm_or_si128(E1, C1); + const __m128i F2 = _mm_or_si128(E2, C2); + _mm_storeu_si128(out++, F1); + _mm_storeu_si128(out++, F2); + num_pixels -= 8; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToRGBA4444_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i mask_0x0f = _mm_set1_epi8(0x0f); + const __m128i mask_0xf0 = _mm_set1_epi8((char)0xf0); + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + while (num_pixels >= 8) { + const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 + const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 + const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... + const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... + const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... + const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... + const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 + const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 + const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 + const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 + const __m128i ga1 = _mm_srli_epi16(ga0, 4); // g0-|g1-|...|a6-|a7- + const __m128i rb1 = _mm_and_si128(rb0, mask_0xf0); // -r0|-r1|...|-b6|-a7 + const __m128i ga2 = _mm_and_si128(ga1, mask_0x0f); // g0-|g1-|...|a6-|a7- + const __m128i rgba0 = _mm_or_si128(ga2, rb1); // rg0..rg7 | ba0..ba7 + const __m128i rgba1 = _mm_srli_si128(rgba0, 8); // ba0..ba7 | 0 +#if (WEBP_SWAP_16BIT_CSP == 1) + const __m128i rgba = _mm_unpacklo_epi8(rgba1, rgba0); // barg0...barg7 +#else + const __m128i rgba = _mm_unpacklo_epi8(rgba0, rgba1); // rgba0...rgba7 +#endif + _mm_storeu_si128(out++, rgba); + num_pixels -= 8; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToRGB565_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i mask_0xe0 = _mm_set1_epi8((char)0xe0); + const __m128i mask_0xf8 = _mm_set1_epi8((char)0xf8); + const __m128i mask_0x07 = _mm_set1_epi8(0x07); + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + while (num_pixels >= 8) { + const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 + const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 + const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... + const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... + const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... + const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... + const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 + const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 + const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 + const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 + const __m128i rb1 = _mm_and_si128(rb0, mask_0xf8); // -r0..-r7|-b0..-b7 + const __m128i g_lo1 = _mm_srli_epi16(ga0, 5); + const __m128i g_lo2 = _mm_and_si128(g_lo1, mask_0x07); // g0-...g7-|xx (3b) + const __m128i g_hi1 = _mm_slli_epi16(ga0, 3); + const __m128i g_hi2 = _mm_and_si128(g_hi1, mask_0xe0); // -g0...-g7|xx (3b) + const __m128i b0 = _mm_srli_si128(rb1, 8); // -b0...-b7|0 + const __m128i rg1 = _mm_or_si128(rb1, g_lo2); // gr0...gr7|xx + const __m128i b1 = _mm_srli_epi16(b0, 3); + const __m128i gb1 = _mm_or_si128(b1, g_hi2); // bg0...bg7|xx +#if (WEBP_SWAP_16BIT_CSP == 1) + const __m128i rgba = _mm_unpacklo_epi8(gb1, rg1); // rggb0...rggb7 +#else + const __m128i rgba = _mm_unpacklo_epi8(rg1, gb1); // bgrb0...bgrb7 +#endif + _mm_storeu_si128(out++, rgba); + num_pixels -= 8; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToBGR_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i mask_l = _mm_set_epi32(0, 0x00ffffff, 0, 0x00ffffff); + const __m128i mask_h = _mm_set_epi32(0x00ffffff, 0, 0x00ffffff, 0); + const __m128i* in = (const __m128i*)src; + const uint8_t* const end = dst + num_pixels * 3; + // the last storel_epi64 below writes 8 bytes starting at offset 18 + while (dst + 26 <= end) { + const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 + const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 + const __m128i a0l = _mm_and_si128(bgra0, mask_l); // bgr0|0|bgr0|0 + const __m128i a4l = _mm_and_si128(bgra4, mask_l); // bgr0|0|bgr0|0 + const __m128i a0h = _mm_and_si128(bgra0, mask_h); // 0|bgr0|0|bgr0 + const __m128i a4h = _mm_and_si128(bgra4, mask_h); // 0|bgr0|0|bgr0 + const __m128i b0h = _mm_srli_epi64(a0h, 8); // 000b|gr00|000b|gr00 + const __m128i b4h = _mm_srli_epi64(a4h, 8); // 000b|gr00|000b|gr00 + const __m128i c0 = _mm_or_si128(a0l, b0h); // rgbrgb00|rgbrgb00 + const __m128i c4 = _mm_or_si128(a4l, b4h); // rgbrgb00|rgbrgb00 + const __m128i c2 = _mm_srli_si128(c0, 8); + const __m128i c6 = _mm_srli_si128(c4, 8); + _mm_storel_epi64((__m128i*)(dst + 0), c0); + _mm_storel_epi64((__m128i*)(dst + 6), c2); + _mm_storel_epi64((__m128i*)(dst + 12), c4); + _mm_storel_epi64((__m128i*)(dst + 18), c6); + dst += 24; + num_pixels -= 8; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE2(void) { + VP8LPredictors[5] = Predictor5_SSE2; + VP8LPredictors[6] = Predictor6_SSE2; + VP8LPredictors[7] = Predictor7_SSE2; + VP8LPredictors[8] = Predictor8_SSE2; + VP8LPredictors[9] = Predictor9_SSE2; + VP8LPredictors[10] = Predictor10_SSE2; + VP8LPredictors[11] = Predictor11_SSE2; + VP8LPredictors[12] = Predictor12_SSE2; + VP8LPredictors[13] = Predictor13_SSE2; + + VP8LPredictorsAdd[0] = PredictorAdd0_SSE2; + VP8LPredictorsAdd[1] = PredictorAdd1_SSE2; + VP8LPredictorsAdd[2] = PredictorAdd2_SSE2; + VP8LPredictorsAdd[3] = PredictorAdd3_SSE2; + VP8LPredictorsAdd[4] = PredictorAdd4_SSE2; + VP8LPredictorsAdd[5] = PredictorAdd5_SSE2; + VP8LPredictorsAdd[6] = PredictorAdd6_SSE2; + VP8LPredictorsAdd[7] = PredictorAdd7_SSE2; + VP8LPredictorsAdd[8] = PredictorAdd8_SSE2; + VP8LPredictorsAdd[9] = PredictorAdd9_SSE2; + VP8LPredictorsAdd[10] = PredictorAdd10_SSE2; + VP8LPredictorsAdd[11] = PredictorAdd11_SSE2; + VP8LPredictorsAdd[12] = PredictorAdd12_SSE2; + VP8LPredictorsAdd[13] = PredictorAdd13_SSE2; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_SSE2; + VP8LTransformColorInverse = TransformColorInverse_SSE2; + + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_SSE2; + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_SSE2; + VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444_SSE2; + VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565_SSE2; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8LDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/lossless_sse41.c b/libraries/webp/src/dsp/lossless_sse41.c new file mode 100644 index 0000000000..bb7ce7611f --- /dev/null +++ b/libraries/webp/src/dsp/lossless_sse41.c @@ -0,0 +1,133 @@ +// Copyright 2021 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE41 variant of methods for lossless decoder + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) + +#include "src/dsp/common_sse41.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" + +//------------------------------------------------------------------------------ +// Color-space conversion functions + +static void TransformColorInverse_SSE41(const VP8LMultipliers* const m, + const uint32_t* const src, + int num_pixels, uint32_t* dst) { +// sign-extended multiplying constants, pre-shifted by 5. +#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend + const __m128i mults_rb = + _mm_set1_epi32((int)((uint32_t)CST(green_to_red_) << 16 | + (CST(green_to_blue_) & 0xffff))); + const __m128i mults_b2 = _mm_set1_epi32(CST(red_to_blue_)); +#undef CST + const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00); + const __m128i perm1 = _mm_setr_epi8(-1, 1, -1, 1, -1, 5, -1, 5, + -1, 9, -1, 9, -1, 13, -1, 13); + const __m128i perm2 = _mm_setr_epi8(-1, 2, -1, -1, -1, 6, -1, -1, + -1, 10, -1, -1, -1, 14, -1, -1); + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i A = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i B = _mm_shuffle_epi8(A, perm1); // argb -> g0g0 + const __m128i C = _mm_mulhi_epi16(B, mults_rb); + const __m128i D = _mm_add_epi8(A, C); + const __m128i E = _mm_shuffle_epi8(D, perm2); + const __m128i F = _mm_mulhi_epi16(E, mults_b2); + const __m128i G = _mm_add_epi8(D, F); + const __m128i out = _mm_blendv_epi8(G, A, mask_ag); + _mm_storeu_si128((__m128i*)&dst[i], out); + } + // Fall-back to C-version for left-overs. + if (i != num_pixels) { + VP8LTransformColorInverse_C(m, src + i, num_pixels - i, dst + i); + } +} + +//------------------------------------------------------------------------------ + +#define ARGB_TO_RGB_SSE41 do { \ + while (num_pixels >= 16) { \ + const __m128i in0 = _mm_loadu_si128(in + 0); \ + const __m128i in1 = _mm_loadu_si128(in + 1); \ + const __m128i in2 = _mm_loadu_si128(in + 2); \ + const __m128i in3 = _mm_loadu_si128(in + 3); \ + const __m128i a0 = _mm_shuffle_epi8(in0, perm0); \ + const __m128i a1 = _mm_shuffle_epi8(in1, perm1); \ + const __m128i a2 = _mm_shuffle_epi8(in2, perm2); \ + const __m128i a3 = _mm_shuffle_epi8(in3, perm3); \ + const __m128i b0 = _mm_blend_epi16(a0, a1, 0xc0); \ + const __m128i b1 = _mm_blend_epi16(a1, a2, 0xf0); \ + const __m128i b2 = _mm_blend_epi16(a2, a3, 0xfc); \ + _mm_storeu_si128(out + 0, b0); \ + _mm_storeu_si128(out + 1, b1); \ + _mm_storeu_si128(out + 2, b2); \ + in += 4; \ + out += 3; \ + num_pixels -= 16; \ + } \ +} while (0) + +static void ConvertBGRAToRGB_SSE41(const uint32_t* src, int num_pixels, + uint8_t* dst) { + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + const __m128i perm0 = _mm_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, + 8, 14, 13, 12, -1, -1, -1, -1); + const __m128i perm1 = _mm_shuffle_epi32(perm0, 0x39); + const __m128i perm2 = _mm_shuffle_epi32(perm0, 0x4e); + const __m128i perm3 = _mm_shuffle_epi32(perm0, 0x93); + + ARGB_TO_RGB_SSE41; + + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGB_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToBGR_SSE41(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + const __m128i perm0 = _mm_setr_epi8(0, 1, 2, 4, 5, 6, 8, 9, 10, + 12, 13, 14, -1, -1, -1, -1); + const __m128i perm1 = _mm_shuffle_epi32(perm0, 0x39); + const __m128i perm2 = _mm_shuffle_epi32(perm0, 0x4e); + const __m128i perm3 = _mm_shuffle_epi32(perm0, 0x93); + + ARGB_TO_RGB_SSE41; + + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +#undef ARGB_TO_RGB_SSE41 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE41(void) { + VP8LTransformColorInverse = TransformColorInverse_SSE41; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_SSE41; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(VP8LDspInitSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/libraries/webp/src/dsp/mips_macro.h b/libraries/webp/src/dsp/mips_macro.h new file mode 100644 index 0000000000..e810d3d382 --- /dev/null +++ b/libraries/webp/src/dsp/mips_macro.h @@ -0,0 +1,210 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS common macros + +#ifndef WEBP_DSP_MIPS_MACRO_H_ +#define WEBP_DSP_MIPS_MACRO_H_ + +#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409 +#define WORK_AROUND_GCC +#endif + +#define STR(s) #s +#define XSTR(s) STR(s) + +// O0[31..16 | 15..0] = I0[31..16 | 15..0] + I1[31..16 | 15..0] +// O1[31..16 | 15..0] = I0[31..16 | 15..0] - I1[31..16 | 15..0] +// O - output +// I - input (macro doesn't change it) +#define ADD_SUB_HALVES(O0, O1, \ + I0, I1) \ + "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \ + "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" + +// O - output +// I - input (macro doesn't change it) +// I[0/1] - offset in bytes +#define LOAD_IN_X2(O0, O1, \ + I0, I1) \ + "lh %[" #O0 "], " #I0 "(%[in]) \n\t" \ + "lh %[" #O1 "], " #I1 "(%[in]) \n\t" + +// I0 - location +// I1..I9 - offsets in bytes +#define LOAD_WITH_OFFSET_X4(O0, O1, O2, O3, \ + I0, I1, I2, I3, I4, I5, I6, I7, I8, I9) \ + "ulw %[" #O0 "], " #I1 "+" XSTR(I9) "*" #I5 "(%[" #I0 "]) \n\t" \ + "ulw %[" #O1 "], " #I2 "+" XSTR(I9) "*" #I6 "(%[" #I0 "]) \n\t" \ + "ulw %[" #O2 "], " #I3 "+" XSTR(I9) "*" #I7 "(%[" #I0 "]) \n\t" \ + "ulw %[" #O3 "], " #I4 "+" XSTR(I9) "*" #I8 "(%[" #I0 "]) \n\t" + + +// O - output +// I - input (macro doesn't change it so it should be different from I) +#define MUL_SHIFT_C1(O, I) \ + "mul %[" #O "], %[" #I "], %[kC1] \n\t" \ + "sra %[" #O "], %[" #O "], 16 \n\t" \ + "addu %[" #O "], %[" #O "], %[" #I "] \n\t" +#define MUL_SHIFT_C2(O, I) \ + "mul %[" #O "], %[" #I "], %[kC2] \n\t" \ + "sra %[" #O "], %[" #O "], 16 \n\t" + +// Same as #define MUL_SHIFT_C1 but I and O are the same. It stores the +// intermediary result in TMP. +#define MUL_SHIFT_C1_IO(IO, TMP) \ + "mul %[" #TMP "], %[" #IO "], %[kC1] \n\t" \ + "sra %[" #TMP "], %[" #TMP "], 16 \n\t" \ + "addu %[" #IO "], %[" #TMP "], %[" #IO "] \n\t" + +// O - output +// IO - input/output +// I - input (macro doesn't change it) +#define MUL_SHIFT_SUM(O0, O1, O2, O3, O4, O5, O6, O7, \ + IO0, IO1, IO2, IO3, \ + I0, I1, I2, I3, I4, I5, I6, I7) \ + MUL_SHIFT_C2(O0, I0) \ + MUL_SHIFT_C1(O1, I0) \ + MUL_SHIFT_C2(O2, I1) \ + MUL_SHIFT_C1(O3, I1) \ + MUL_SHIFT_C2(O4, I2) \ + MUL_SHIFT_C1(O5, I2) \ + MUL_SHIFT_C2(O6, I3) \ + MUL_SHIFT_C1(O7, I3) \ + "addu %[" #IO0 "], %[" #IO0 "], %[" #I4 "] \n\t" \ + "addu %[" #IO1 "], %[" #IO1 "], %[" #I5 "] \n\t" \ + "subu %[" #IO2 "], %[" #IO2 "], %[" #I6 "] \n\t" \ + "subu %[" #IO3 "], %[" #IO3 "], %[" #I7 "] \n\t" + +// O - output +// I - input (macro doesn't change it) +#define INSERT_HALF_X2(O0, O1, \ + I0, I1) \ + "ins %[" #O0 "], %[" #I0 "], 16, 16 \n\t" \ + "ins %[" #O1 "], %[" #I1 "], 16, 16 \n\t" + +// O - output +// I - input (macro doesn't change it) +#define SRA_16(O0, O1, O2, O3, \ + I0, I1, I2, I3) \ + "sra %[" #O0 "], %[" #I0 "], 16 \n\t" \ + "sra %[" #O1 "], %[" #I1 "], 16 \n\t" \ + "sra %[" #O2 "], %[" #I2 "], 16 \n\t" \ + "sra %[" #O3 "], %[" #I3 "], 16 \n\t" + +// temp0[31..16 | 15..0] = temp8[31..16 | 15..0] + temp12[31..16 | 15..0] +// temp1[31..16 | 15..0] = temp8[31..16 | 15..0] - temp12[31..16 | 15..0] +// temp0[31..16 | 15..0] = temp0[31..16 >> 3 | 15..0 >> 3] +// temp1[31..16 | 15..0] = temp1[31..16 >> 3 | 15..0 >> 3] +// O - output +// I - input (macro doesn't change it) +#define SHIFT_R_SUM_X2(O0, O1, O2, O3, O4, O5, O6, O7, \ + I0, I1, I2, I3, I4, I5, I6, I7) \ + "addq.ph %[" #O0 "], %[" #I0 "], %[" #I4 "] \n\t" \ + "subq.ph %[" #O1 "], %[" #I0 "], %[" #I4 "] \n\t" \ + "addq.ph %[" #O2 "], %[" #I1 "], %[" #I5 "] \n\t" \ + "subq.ph %[" #O3 "], %[" #I1 "], %[" #I5 "] \n\t" \ + "addq.ph %[" #O4 "], %[" #I2 "], %[" #I6 "] \n\t" \ + "subq.ph %[" #O5 "], %[" #I2 "], %[" #I6 "] \n\t" \ + "addq.ph %[" #O6 "], %[" #I3 "], %[" #I7 "] \n\t" \ + "subq.ph %[" #O7 "], %[" #I3 "], %[" #I7 "] \n\t" \ + "shra.ph %[" #O0 "], %[" #O0 "], 3 \n\t" \ + "shra.ph %[" #O1 "], %[" #O1 "], 3 \n\t" \ + "shra.ph %[" #O2 "], %[" #O2 "], 3 \n\t" \ + "shra.ph %[" #O3 "], %[" #O3 "], 3 \n\t" \ + "shra.ph %[" #O4 "], %[" #O4 "], 3 \n\t" \ + "shra.ph %[" #O5 "], %[" #O5 "], 3 \n\t" \ + "shra.ph %[" #O6 "], %[" #O6 "], 3 \n\t" \ + "shra.ph %[" #O7 "], %[" #O7 "], 3 \n\t" + +// precrq.ph.w temp0, temp8, temp2 +// temp0 = temp8[31..16] | temp2[31..16] +// ins temp2, temp8, 16, 16 +// temp2 = temp8[31..16] | temp2[15..0] +// O - output +// IO - input/output +// I - input (macro doesn't change it) +#define PACK_2_HALVES_TO_WORD(O0, O1, O2, O3, \ + IO0, IO1, IO2, IO3, \ + I0, I1, I2, I3) \ + "precrq.ph.w %[" #O0 "], %[" #I0 "], %[" #IO0 "] \n\t" \ + "precrq.ph.w %[" #O1 "], %[" #I1 "], %[" #IO1 "] \n\t" \ + "ins %[" #IO0 "], %[" #I0 "], 16, 16 \n\t" \ + "ins %[" #IO1 "], %[" #I1 "], 16, 16 \n\t" \ + "precrq.ph.w %[" #O2 "], %[" #I2 "], %[" #IO2 "] \n\t" \ + "precrq.ph.w %[" #O3 "], %[" #I3 "], %[" #IO3 "] \n\t" \ + "ins %[" #IO2 "], %[" #I2 "], 16, 16 \n\t" \ + "ins %[" #IO3 "], %[" #I3 "], 16, 16 \n\t" + +// preceu.ph.qbr temp0, temp8 +// temp0 = 0 | 0 | temp8[23..16] | temp8[7..0] +// preceu.ph.qbl temp1, temp8 +// temp1 = temp8[23..16] | temp8[7..0] | 0 | 0 +// O - output +// I - input (macro doesn't change it) +#define CONVERT_2_BYTES_TO_HALF(O0, O1, O2, O3, O4, O5, O6, O7, \ + I0, I1, I2, I3) \ + "preceu.ph.qbr %[" #O0 "], %[" #I0 "] \n\t" \ + "preceu.ph.qbl %[" #O1 "], %[" #I0 "] \n\t" \ + "preceu.ph.qbr %[" #O2 "], %[" #I1 "] \n\t" \ + "preceu.ph.qbl %[" #O3 "], %[" #I1 "] \n\t" \ + "preceu.ph.qbr %[" #O4 "], %[" #I2 "] \n\t" \ + "preceu.ph.qbl %[" #O5 "], %[" #I2 "] \n\t" \ + "preceu.ph.qbr %[" #O6 "], %[" #I3 "] \n\t" \ + "preceu.ph.qbl %[" #O7 "], %[" #I3 "] \n\t" + +// temp0[31..16 | 15..0] = temp0[31..16 | 15..0] + temp8[31..16 | 15..0] +// temp0[31..16 | 15..0] = temp0[31..16 <<(s) 7 | 15..0 <<(s) 7] +// temp1..temp7 same as temp0 +// precrqu_s.qb.ph temp0, temp1, temp0: +// temp0 = temp1[31..24] | temp1[15..8] | temp0[31..24] | temp0[15..8] +// store temp0 to dst +// IO - input/output +// I - input (macro doesn't change it) +#define STORE_SAT_SUM_X2(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7, \ + I0, I1, I2, I3, I4, I5, I6, I7, \ + I8, I9, I10, I11, I12, I13) \ + "addq.ph %[" #IO0 "], %[" #IO0 "], %[" #I0 "] \n\t" \ + "addq.ph %[" #IO1 "], %[" #IO1 "], %[" #I1 "] \n\t" \ + "addq.ph %[" #IO2 "], %[" #IO2 "], %[" #I2 "] \n\t" \ + "addq.ph %[" #IO3 "], %[" #IO3 "], %[" #I3 "] \n\t" \ + "addq.ph %[" #IO4 "], %[" #IO4 "], %[" #I4 "] \n\t" \ + "addq.ph %[" #IO5 "], %[" #IO5 "], %[" #I5 "] \n\t" \ + "addq.ph %[" #IO6 "], %[" #IO6 "], %[" #I6 "] \n\t" \ + "addq.ph %[" #IO7 "], %[" #IO7 "], %[" #I7 "] \n\t" \ + "shll_s.ph %[" #IO0 "], %[" #IO0 "], 7 \n\t" \ + "shll_s.ph %[" #IO1 "], %[" #IO1 "], 7 \n\t" \ + "shll_s.ph %[" #IO2 "], %[" #IO2 "], 7 \n\t" \ + "shll_s.ph %[" #IO3 "], %[" #IO3 "], 7 \n\t" \ + "shll_s.ph %[" #IO4 "], %[" #IO4 "], 7 \n\t" \ + "shll_s.ph %[" #IO5 "], %[" #IO5 "], 7 \n\t" \ + "shll_s.ph %[" #IO6 "], %[" #IO6 "], 7 \n\t" \ + "shll_s.ph %[" #IO7 "], %[" #IO7 "], 7 \n\t" \ + "precrqu_s.qb.ph %[" #IO0 "], %[" #IO1 "], %[" #IO0 "] \n\t" \ + "precrqu_s.qb.ph %[" #IO2 "], %[" #IO3 "], %[" #IO2 "] \n\t" \ + "precrqu_s.qb.ph %[" #IO4 "], %[" #IO5 "], %[" #IO4 "] \n\t" \ + "precrqu_s.qb.ph %[" #IO6 "], %[" #IO7 "], %[" #IO6 "] \n\t" \ + "usw %[" #IO0 "], " XSTR(I13) "*" #I9 "(%[" #I8 "]) \n\t" \ + "usw %[" #IO2 "], " XSTR(I13) "*" #I10 "(%[" #I8 "]) \n\t" \ + "usw %[" #IO4 "], " XSTR(I13) "*" #I11 "(%[" #I8 "]) \n\t" \ + "usw %[" #IO6 "], " XSTR(I13) "*" #I12 "(%[" #I8 "]) \n\t" + +#define OUTPUT_EARLY_CLOBBER_REGS_10() \ + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \ + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), \ + [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), \ + [temp10]"=&r"(temp10) + +#define OUTPUT_EARLY_CLOBBER_REGS_18() \ + OUTPUT_EARLY_CLOBBER_REGS_10(), \ + [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \ + [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \ + [temp17]"=&r"(temp17), [temp18]"=&r"(temp18) + +#endif // WEBP_DSP_MIPS_MACRO_H_ diff --git a/libraries/webp/src/dsp/msa_macro.h b/libraries/webp/src/dsp/msa_macro.h new file mode 100644 index 0000000000..90adbbc319 --- /dev/null +++ b/libraries/webp/src/dsp/msa_macro.h @@ -0,0 +1,1395 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA common macros +// +// Author(s): Prashant Patil (prashant.patil@imgtec.com) + +#ifndef WEBP_DSP_MSA_MACRO_H_ +#define WEBP_DSP_MSA_MACRO_H_ + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include +#include + +#if defined(__clang__) + #define CLANG_BUILD +#endif + +#ifdef CLANG_BUILD + #define ALPHAVAL (-1) + #define ADDVI_H(a, b) __msa_addvi_h((v8i16)a, b) + #define ADDVI_W(a, b) __msa_addvi_w((v4i32)a, b) + #define SRAI_B(a, b) __msa_srai_b((v16i8)a, b) + #define SRAI_H(a, b) __msa_srai_h((v8i16)a, b) + #define SRAI_W(a, b) __msa_srai_w((v4i32)a, b) + #define SRLI_H(a, b) __msa_srli_h((v8i16)a, b) + #define SLLI_B(a, b) __msa_slli_b((v4i32)a, b) + #define ANDI_B(a, b) __msa_andi_b((v16u8)a, b) + #define ORI_B(a, b) __msa_ori_b((v16u8)a, b) +#else + #define ALPHAVAL (0xff) + #define ADDVI_H(a, b) (a + b) + #define ADDVI_W(a, b) (a + b) + #define SRAI_B(a, b) (a >> b) + #define SRAI_H(a, b) (a >> b) + #define SRAI_W(a, b) (a >> b) + #define SRLI_H(a, b) (a << b) + #define SLLI_B(a, b) (a << b) + #define ANDI_B(a, b) (a & b) + #define ORI_B(a, b) (a | b) +#endif + +#define LD_B(RTYPE, psrc) *((RTYPE*)(psrc)) +#define LD_UB(...) LD_B(v16u8, __VA_ARGS__) +#define LD_SB(...) LD_B(v16i8, __VA_ARGS__) + +#define LD_H(RTYPE, psrc) *((RTYPE*)(psrc)) +#define LD_UH(...) LD_H(v8u16, __VA_ARGS__) +#define LD_SH(...) LD_H(v8i16, __VA_ARGS__) + +#define LD_W(RTYPE, psrc) *((RTYPE*)(psrc)) +#define LD_UW(...) LD_W(v4u32, __VA_ARGS__) +#define LD_SW(...) LD_W(v4i32, __VA_ARGS__) + +#define ST_B(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in +#define ST_UB(...) ST_B(v16u8, __VA_ARGS__) +#define ST_SB(...) ST_B(v16i8, __VA_ARGS__) + +#define ST_H(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in +#define ST_UH(...) ST_H(v8u16, __VA_ARGS__) +#define ST_SH(...) ST_H(v8i16, __VA_ARGS__) + +#define ST_W(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in +#define ST_UW(...) ST_W(v4u32, __VA_ARGS__) +#define ST_SW(...) ST_W(v4i32, __VA_ARGS__) + +#define MSA_LOAD_FUNC(TYPE, INSTR, FUNC_NAME) \ + static inline TYPE FUNC_NAME(const void* const psrc) { \ + const uint8_t* const psrc_m = (const uint8_t*)psrc; \ + TYPE val_m; \ + __asm__ volatile("" #INSTR " %[val_m], %[psrc_m] \n\t" \ + : [val_m] "=r"(val_m) \ + : [psrc_m] "m"(*psrc_m)); \ + return val_m; \ + } + +#define MSA_LOAD(psrc, FUNC_NAME) FUNC_NAME(psrc) + +#define MSA_STORE_FUNC(TYPE, INSTR, FUNC_NAME) \ + static inline void FUNC_NAME(TYPE val, void* const pdst) { \ + uint8_t* const pdst_m = (uint8_t*)pdst; \ + TYPE val_m = val; \ + __asm__ volatile(" " #INSTR " %[val_m], %[pdst_m] \n\t" \ + : [pdst_m] "=m"(*pdst_m) \ + : [val_m] "r"(val_m)); \ + } + +#define MSA_STORE(val, pdst, FUNC_NAME) FUNC_NAME(val, pdst) + +#if (__mips_isa_rev >= 6) + MSA_LOAD_FUNC(uint16_t, lh, msa_lh); + #define LH(psrc) MSA_LOAD(psrc, msa_lh) + MSA_LOAD_FUNC(uint32_t, lw, msa_lw); + #define LW(psrc) MSA_LOAD(psrc, msa_lw) + #if (__mips == 64) + MSA_LOAD_FUNC(uint64_t, ld, msa_ld); + #define LD(psrc) MSA_LOAD(psrc, msa_ld) + #else // !(__mips == 64) + #define LD(psrc) ((((uint64_t)MSA_LOAD(psrc + 4, msa_lw)) << 32) | \ + MSA_LOAD(psrc, msa_lw)) + #endif // (__mips == 64) + + MSA_STORE_FUNC(uint16_t, sh, msa_sh); + #define SH(val, pdst) MSA_STORE(val, pdst, msa_sh) + MSA_STORE_FUNC(uint32_t, sw, msa_sw); + #define SW(val, pdst) MSA_STORE(val, pdst, msa_sw) + MSA_STORE_FUNC(uint64_t, sd, msa_sd); + #define SD(val, pdst) MSA_STORE(val, pdst, msa_sd) +#else // !(__mips_isa_rev >= 6) + MSA_LOAD_FUNC(uint16_t, ulh, msa_ulh); + #define LH(psrc) MSA_LOAD(psrc, msa_ulh) + MSA_LOAD_FUNC(uint32_t, ulw, msa_ulw); + #define LW(psrc) MSA_LOAD(psrc, msa_ulw) + #if (__mips == 64) + MSA_LOAD_FUNC(uint64_t, uld, msa_uld); + #define LD(psrc) MSA_LOAD(psrc, msa_uld) + #else // !(__mips == 64) + #define LD(psrc) ((((uint64_t)MSA_LOAD(psrc + 4, msa_ulw)) << 32) | \ + MSA_LOAD(psrc, msa_ulw)) + #endif // (__mips == 64) + + MSA_STORE_FUNC(uint16_t, ush, msa_ush); + #define SH(val, pdst) MSA_STORE(val, pdst, msa_ush) + MSA_STORE_FUNC(uint32_t, usw, msa_usw); + #define SW(val, pdst) MSA_STORE(val, pdst, msa_usw) + #define SD(val, pdst) do { \ + uint8_t* const pdst_sd_m = (uint8_t*)(pdst); \ + const uint32_t val0_m = (uint32_t)(val & 0x00000000FFFFFFFF); \ + const uint32_t val1_m = (uint32_t)((val >> 32) & 0x00000000FFFFFFFF); \ + SW(val0_m, pdst_sd_m); \ + SW(val1_m, pdst_sd_m + 4); \ + } while (0) +#endif // (__mips_isa_rev >= 6) + +/* Description : Load 4 words with stride + * Arguments : Inputs - psrc, stride + * Outputs - out0, out1, out2, out3 + * Details : Load word in 'out0' from (psrc) + * Load word in 'out1' from (psrc + stride) + * Load word in 'out2' from (psrc + 2 * stride) + * Load word in 'out3' from (psrc + 3 * stride) + */ +#define LW4(psrc, stride, out0, out1, out2, out3) do { \ + const uint8_t* ptmp = (const uint8_t*)psrc; \ + out0 = LW(ptmp); \ + ptmp += stride; \ + out1 = LW(ptmp); \ + ptmp += stride; \ + out2 = LW(ptmp); \ + ptmp += stride; \ + out3 = LW(ptmp); \ +} while (0) + +/* Description : Store words with stride + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + * Details : Store word from 'in0' to (pdst) + * Store word from 'in1' to (pdst + stride) + * Store word from 'in2' to (pdst + 2 * stride) + * Store word from 'in3' to (pdst + 3 * stride) + */ +#define SW4(in0, in1, in2, in3, pdst, stride) do { \ + uint8_t* ptmp = (uint8_t*)pdst; \ + SW(in0, ptmp); \ + ptmp += stride; \ + SW(in1, ptmp); \ + ptmp += stride; \ + SW(in2, ptmp); \ + ptmp += stride; \ + SW(in3, ptmp); \ +} while (0) + +#define SW3(in0, in1, in2, pdst, stride) do { \ + uint8_t* ptmp = (uint8_t*)pdst; \ + SW(in0, ptmp); \ + ptmp += stride; \ + SW(in1, ptmp); \ + ptmp += stride; \ + SW(in2, ptmp); \ +} while (0) + +#define SW2(in0, in1, pdst, stride) do { \ + uint8_t* ptmp = (uint8_t*)pdst; \ + SW(in0, ptmp); \ + ptmp += stride; \ + SW(in1, ptmp); \ +} while (0) + +/* Description : Store 4 double words with stride + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + * Details : Store double word from 'in0' to (pdst) + * Store double word from 'in1' to (pdst + stride) + * Store double word from 'in2' to (pdst + 2 * stride) + * Store double word from 'in3' to (pdst + 3 * stride) + */ +#define SD4(in0, in1, in2, in3, pdst, stride) do { \ + uint8_t* ptmp = (uint8_t*)pdst; \ + SD(in0, ptmp); \ + ptmp += stride; \ + SD(in1, ptmp); \ + ptmp += stride; \ + SD(in2, ptmp); \ + ptmp += stride; \ + SD(in3, ptmp); \ +} while (0) + +/* Description : Load vectors with 16 byte elements with stride + * Arguments : Inputs - psrc, stride + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Load 16 byte elements in 'out0' from (psrc) + * Load 16 byte elements in 'out1' from (psrc + stride) + */ +#define LD_B2(RTYPE, psrc, stride, out0, out1) do { \ + out0 = LD_B(RTYPE, psrc); \ + out1 = LD_B(RTYPE, psrc + stride); \ +} while (0) +#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__) +#define LD_SB2(...) LD_B2(v16i8, __VA_ARGS__) + +#define LD_B3(RTYPE, psrc, stride, out0, out1, out2) do { \ + LD_B2(RTYPE, psrc, stride, out0, out1); \ + out2 = LD_B(RTYPE, psrc + 2 * stride); \ +} while (0) +#define LD_UB3(...) LD_B3(v16u8, __VA_ARGS__) +#define LD_SB3(...) LD_B3(v16i8, __VA_ARGS__) + +#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) do { \ + LD_B2(RTYPE, psrc, stride, out0, out1); \ + LD_B2(RTYPE, psrc + 2 * stride , stride, out2, out3); \ +} while (0) +#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__) +#define LD_SB4(...) LD_B4(v16i8, __VA_ARGS__) + +#define LD_B8(RTYPE, psrc, stride, \ + out0, out1, out2, out3, out4, out5, out6, out7) do { \ + LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3); \ + LD_B4(RTYPE, psrc + 4 * stride, stride, out4, out5, out6, out7); \ +} while (0) +#define LD_UB8(...) LD_B8(v16u8, __VA_ARGS__) +#define LD_SB8(...) LD_B8(v16i8, __VA_ARGS__) + +/* Description : Load vectors with 8 halfword elements with stride + * Arguments : Inputs - psrc, stride + * Outputs - out0, out1 + * Details : Load 8 halfword elements in 'out0' from (psrc) + * Load 8 halfword elements in 'out1' from (psrc + stride) + */ +#define LD_H2(RTYPE, psrc, stride, out0, out1) do { \ + out0 = LD_H(RTYPE, psrc); \ + out1 = LD_H(RTYPE, psrc + stride); \ +} while (0) +#define LD_UH2(...) LD_H2(v8u16, __VA_ARGS__) +#define LD_SH2(...) LD_H2(v8i16, __VA_ARGS__) + +/* Description : Load vectors with 4 word elements with stride + * Arguments : Inputs - psrc, stride + * Outputs - out0, out1, out2, out3 + * Details : Load 4 word elements in 'out0' from (psrc + 0 * stride) + * Load 4 word elements in 'out1' from (psrc + 1 * stride) + * Load 4 word elements in 'out2' from (psrc + 2 * stride) + * Load 4 word elements in 'out3' from (psrc + 3 * stride) + */ +#define LD_W2(RTYPE, psrc, stride, out0, out1) do { \ + out0 = LD_W(RTYPE, psrc); \ + out1 = LD_W(RTYPE, psrc + stride); \ +} while (0) +#define LD_UW2(...) LD_W2(v4u32, __VA_ARGS__) +#define LD_SW2(...) LD_W2(v4i32, __VA_ARGS__) + +#define LD_W3(RTYPE, psrc, stride, out0, out1, out2) do { \ + LD_W2(RTYPE, psrc, stride, out0, out1); \ + out2 = LD_W(RTYPE, psrc + 2 * stride); \ +} while (0) +#define LD_UW3(...) LD_W3(v4u32, __VA_ARGS__) +#define LD_SW3(...) LD_W3(v4i32, __VA_ARGS__) + +#define LD_W4(RTYPE, psrc, stride, out0, out1, out2, out3) do { \ + LD_W2(RTYPE, psrc, stride, out0, out1); \ + LD_W2(RTYPE, psrc + 2 * stride, stride, out2, out3); \ +} while (0) +#define LD_UW4(...) LD_W4(v4u32, __VA_ARGS__) +#define LD_SW4(...) LD_W4(v4i32, __VA_ARGS__) + +/* Description : Store vectors of 16 byte elements with stride + * Arguments : Inputs - in0, in1, pdst, stride + * Details : Store 16 byte elements from 'in0' to (pdst) + * Store 16 byte elements from 'in1' to (pdst + stride) + */ +#define ST_B2(RTYPE, in0, in1, pdst, stride) do { \ + ST_B(RTYPE, in0, pdst); \ + ST_B(RTYPE, in1, pdst + stride); \ +} while (0) +#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__) +#define ST_SB2(...) ST_B2(v16i8, __VA_ARGS__) + +#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) do { \ + ST_B2(RTYPE, in0, in1, pdst, stride); \ + ST_B2(RTYPE, in2, in3, pdst + 2 * stride, stride); \ +} while (0) +#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__) +#define ST_SB4(...) ST_B4(v16i8, __VA_ARGS__) + +#define ST_B8(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + pdst, stride) do { \ + ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride); \ + ST_B4(RTYPE, in4, in5, in6, in7, pdst + 4 * stride, stride); \ +} while (0) +#define ST_UB8(...) ST_B8(v16u8, __VA_ARGS__) + +/* Description : Store vectors of 4 word elements with stride + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + * Details : Store 4 word elements from 'in0' to (pdst + 0 * stride) + * Store 4 word elements from 'in1' to (pdst + 1 * stride) + * Store 4 word elements from 'in2' to (pdst + 2 * stride) + * Store 4 word elements from 'in3' to (pdst + 3 * stride) + */ +#define ST_W2(RTYPE, in0, in1, pdst, stride) do { \ + ST_W(RTYPE, in0, pdst); \ + ST_W(RTYPE, in1, pdst + stride); \ +} while (0) +#define ST_UW2(...) ST_W2(v4u32, __VA_ARGS__) +#define ST_SW2(...) ST_W2(v4i32, __VA_ARGS__) + +#define ST_W3(RTYPE, in0, in1, in2, pdst, stride) do { \ + ST_W2(RTYPE, in0, in1, pdst, stride); \ + ST_W(RTYPE, in2, pdst + 2 * stride); \ +} while (0) +#define ST_UW3(...) ST_W3(v4u32, __VA_ARGS__) +#define ST_SW3(...) ST_W3(v4i32, __VA_ARGS__) + +#define ST_W4(RTYPE, in0, in1, in2, in3, pdst, stride) do { \ + ST_W2(RTYPE, in0, in1, pdst, stride); \ + ST_W2(RTYPE, in2, in3, pdst + 2 * stride, stride); \ +} while (0) +#define ST_UW4(...) ST_W4(v4u32, __VA_ARGS__) +#define ST_SW4(...) ST_W4(v4i32, __VA_ARGS__) + +/* Description : Store vectors of 8 halfword elements with stride + * Arguments : Inputs - in0, in1, pdst, stride + * Details : Store 8 halfword elements from 'in0' to (pdst) + * Store 8 halfword elements from 'in1' to (pdst + stride) + */ +#define ST_H2(RTYPE, in0, in1, pdst, stride) do { \ + ST_H(RTYPE, in0, pdst); \ + ST_H(RTYPE, in1, pdst + stride); \ +} while (0) +#define ST_UH2(...) ST_H2(v8u16, __VA_ARGS__) +#define ST_SH2(...) ST_H2(v8i16, __VA_ARGS__) + +/* Description : Store 2x4 byte block to destination memory from input vector + * Arguments : Inputs - in, stidx, pdst, stride + * Details : Index 'stidx' halfword element from 'in' vector is copied to + * the GP register and stored to (pdst) + * Index 'stidx+1' halfword element from 'in' vector is copied to + * the GP register and stored to (pdst + stride) + * Index 'stidx+2' halfword element from 'in' vector is copied to + * the GP register and stored to (pdst + 2 * stride) + * Index 'stidx+3' halfword element from 'in' vector is copied to + * the GP register and stored to (pdst + 3 * stride) + */ +#define ST2x4_UB(in, stidx, pdst, stride) do { \ + uint8_t* pblk_2x4_m = (uint8_t*)pdst; \ + const uint16_t out0_m = __msa_copy_s_h((v8i16)in, stidx); \ + const uint16_t out1_m = __msa_copy_s_h((v8i16)in, stidx + 1); \ + const uint16_t out2_m = __msa_copy_s_h((v8i16)in, stidx + 2); \ + const uint16_t out3_m = __msa_copy_s_h((v8i16)in, stidx + 3); \ + SH(out0_m, pblk_2x4_m); \ + pblk_2x4_m += stride; \ + SH(out1_m, pblk_2x4_m); \ + pblk_2x4_m += stride; \ + SH(out2_m, pblk_2x4_m); \ + pblk_2x4_m += stride; \ + SH(out3_m, pblk_2x4_m); \ +} while (0) + +/* Description : Store 4x4 byte block to destination memory from input vector + * Arguments : Inputs - in0, in1, pdst, stride + * Details : 'Idx0' word element from input vector 'in0' is copied to the + * GP register and stored to (pdst) + * 'Idx1' word element from input vector 'in0' is copied to the + * GP register and stored to (pdst + stride) + * 'Idx2' word element from input vector 'in0' is copied to the + * GP register and stored to (pdst + 2 * stride) + * 'Idx3' word element from input vector 'in0' is copied to the + * GP register and stored to (pdst + 3 * stride) + */ +#define ST4x4_UB(in0, in1, idx0, idx1, idx2, idx3, pdst, stride) do { \ + uint8_t* const pblk_4x4_m = (uint8_t*)pdst; \ + const uint32_t out0_m = __msa_copy_s_w((v4i32)in0, idx0); \ + const uint32_t out1_m = __msa_copy_s_w((v4i32)in0, idx1); \ + const uint32_t out2_m = __msa_copy_s_w((v4i32)in1, idx2); \ + const uint32_t out3_m = __msa_copy_s_w((v4i32)in1, idx3); \ + SW4(out0_m, out1_m, out2_m, out3_m, pblk_4x4_m, stride); \ +} while (0) + +#define ST4x8_UB(in0, in1, pdst, stride) do { \ + uint8_t* const pblk_4x8 = (uint8_t*)pdst; \ + ST4x4_UB(in0, in0, 0, 1, 2, 3, pblk_4x8, stride); \ + ST4x4_UB(in1, in1, 0, 1, 2, 3, pblk_4x8 + 4 * stride, stride); \ +} while (0) + +/* Description : Immediate number of elements to slide + * Arguments : Inputs - in0, in1, slide_val + * Outputs - out + * Return Type - as per RTYPE + * Details : Byte elements from 'in1' vector are slid into 'in0' by + * value specified in the 'slide_val' + */ +#define SLDI_B(RTYPE, in0, in1, slide_val) \ + (RTYPE)__msa_sldi_b((v16i8)in0, (v16i8)in1, slide_val) \ + +#define SLDI_UB(...) SLDI_B(v16u8, __VA_ARGS__) +#define SLDI_SB(...) SLDI_B(v16i8, __VA_ARGS__) +#define SLDI_SH(...) SLDI_B(v8i16, __VA_ARGS__) + +/* Description : Shuffle byte vector elements as per mask vector + * Arguments : Inputs - in0, in1, in2, in3, mask0, mask1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Byte elements from 'in0' & 'in1' are copied selectively to + * 'out0' as per control vector 'mask0' + */ +#define VSHF_B(RTYPE, in0, in1, mask) \ + (RTYPE)__msa_vshf_b((v16i8)mask, (v16i8)in1, (v16i8)in0) + +#define VSHF_UB(...) VSHF_B(v16u8, __VA_ARGS__) +#define VSHF_SB(...) VSHF_B(v16i8, __VA_ARGS__) +#define VSHF_UH(...) VSHF_B(v8u16, __VA_ARGS__) +#define VSHF_SH(...) VSHF_B(v8i16, __VA_ARGS__) + +#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) do { \ + out0 = VSHF_B(RTYPE, in0, in1, mask0); \ + out1 = VSHF_B(RTYPE, in2, in3, mask1); \ +} while (0) +#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__) +#define VSHF_B2_SB(...) VSHF_B2(v16i8, __VA_ARGS__) +#define VSHF_B2_UH(...) VSHF_B2(v8u16, __VA_ARGS__) +#define VSHF_B2_SH(...) VSHF_B2(v8i16, __VA_ARGS__) + +/* Description : Shuffle halfword vector elements as per mask vector + * Arguments : Inputs - in0, in1, in2, in3, mask0, mask1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : halfword elements from 'in0' & 'in1' are copied selectively to + * 'out0' as per control vector 'mask0' + */ +#define VSHF_H2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) do { \ + out0 = (RTYPE)__msa_vshf_h((v8i16)mask0, (v8i16)in1, (v8i16)in0); \ + out1 = (RTYPE)__msa_vshf_h((v8i16)mask1, (v8i16)in3, (v8i16)in2); \ +} while (0) +#define VSHF_H2_UH(...) VSHF_H2(v8u16, __VA_ARGS__) +#define VSHF_H2_SH(...) VSHF_H2(v8i16, __VA_ARGS__) + +/* Description : Dot product of byte vector elements + * Arguments : Inputs - mult0, mult1, cnst0, cnst1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Signed byte elements from 'mult0' are multiplied with + * signed byte elements from 'cnst0' producing a result + * twice the size of input i.e. signed halfword. + * The multiplication result of adjacent odd-even elements + * are added together and written to the 'out0' vector +*/ +#define DOTP_SB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \ + out0 = (RTYPE)__msa_dotp_s_h((v16i8)mult0, (v16i8)cnst0); \ + out1 = (RTYPE)__msa_dotp_s_h((v16i8)mult1, (v16i8)cnst1); \ +} while (0) +#define DOTP_SB2_SH(...) DOTP_SB2(v8i16, __VA_ARGS__) + +/* Description : Dot product of halfword vector elements + * Arguments : Inputs - mult0, mult1, cnst0, cnst1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Signed halfword elements from 'mult0' are multiplied with + * signed halfword elements from 'cnst0' producing a result + * twice the size of input i.e. signed word. + * The multiplication result of adjacent odd-even elements + * are added together and written to the 'out0' vector + */ +#define DOTP_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \ + out0 = (RTYPE)__msa_dotp_s_w((v8i16)mult0, (v8i16)cnst0); \ + out1 = (RTYPE)__msa_dotp_s_w((v8i16)mult1, (v8i16)cnst1); \ +} while (0) +#define DOTP_SH2_SW(...) DOTP_SH2(v4i32, __VA_ARGS__) + +/* Description : Dot product of unsigned word vector elements + * Arguments : Inputs - mult0, mult1, cnst0, cnst1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Unsigned word elements from 'mult0' are multiplied with + * unsigned word elements from 'cnst0' producing a result + * twice the size of input i.e. unsigned double word. + * The multiplication result of adjacent odd-even elements + * are added together and written to the 'out0' vector + */ +#define DOTP_UW2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \ + out0 = (RTYPE)__msa_dotp_u_d((v4u32)mult0, (v4u32)cnst0); \ + out1 = (RTYPE)__msa_dotp_u_d((v4u32)mult1, (v4u32)cnst1); \ +} while (0) +#define DOTP_UW2_UD(...) DOTP_UW2(v2u64, __VA_ARGS__) + +/* Description : Dot product & addition of halfword vector elements + * Arguments : Inputs - mult0, mult1, cnst0, cnst1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Signed halfword elements from 'mult0' are multiplied with + * signed halfword elements from 'cnst0' producing a result + * twice the size of input i.e. signed word. + * The multiplication result of adjacent odd-even elements + * are added to the 'out0' vector + */ +#define DPADD_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \ + out0 = (RTYPE)__msa_dpadd_s_w((v4i32)out0, (v8i16)mult0, (v8i16)cnst0); \ + out1 = (RTYPE)__msa_dpadd_s_w((v4i32)out1, (v8i16)mult1, (v8i16)cnst1); \ +} while (0) +#define DPADD_SH2_SW(...) DPADD_SH2(v4i32, __VA_ARGS__) + +/* Description : Clips all signed halfword elements of input vector + * between 0 & 255 + * Arguments : Input/output - val + * Return Type - signed halfword + */ +#define CLIP_SH_0_255(val) do { \ + const v8i16 max_m = __msa_ldi_h(255); \ + val = __msa_maxi_s_h((v8i16)val, 0); \ + val = __msa_min_s_h(max_m, (v8i16)val); \ +} while (0) + +#define CLIP_SH2_0_255(in0, in1) do { \ + CLIP_SH_0_255(in0); \ + CLIP_SH_0_255(in1); \ +} while (0) + +#define CLIP_SH4_0_255(in0, in1, in2, in3) do { \ + CLIP_SH2_0_255(in0, in1); \ + CLIP_SH2_0_255(in2, in3); \ +} while (0) + +/* Description : Clips all unsigned halfword elements of input vector + * between 0 & 255 + * Arguments : Input - in + * Output - out_m + * Return Type - unsigned halfword + */ +#define CLIP_UH_0_255(in) do { \ + const v8u16 max_m = (v8u16)__msa_ldi_h(255); \ + in = __msa_maxi_u_h((v8u16) in, 0); \ + in = __msa_min_u_h((v8u16) max_m, (v8u16) in); \ +} while (0) + +#define CLIP_UH2_0_255(in0, in1) do { \ + CLIP_UH_0_255(in0); \ + CLIP_UH_0_255(in1); \ +} while (0) + +/* Description : Clips all signed word elements of input vector + * between 0 & 255 + * Arguments : Input/output - val + * Return Type - signed word + */ +#define CLIP_SW_0_255(val) do { \ + const v4i32 max_m = __msa_ldi_w(255); \ + val = __msa_maxi_s_w((v4i32)val, 0); \ + val = __msa_min_s_w(max_m, (v4i32)val); \ +} while (0) + +#define CLIP_SW4_0_255(in0, in1, in2, in3) do { \ + CLIP_SW_0_255(in0); \ + CLIP_SW_0_255(in1); \ + CLIP_SW_0_255(in2); \ + CLIP_SW_0_255(in3); \ +} while (0) + +/* Description : Horizontal addition of 4 signed word elements of input vector + * Arguments : Input - in (signed word vector) + * Output - sum_m (i32 sum) + * Return Type - signed word (GP) + * Details : 4 signed word elements of 'in' vector are added together and + * the resulting integer sum is returned + */ +static WEBP_INLINE int32_t func_hadd_sw_s32(v4i32 in) { + const v2i64 res0_m = __msa_hadd_s_d((v4i32)in, (v4i32)in); + const v2i64 res1_m = __msa_splati_d(res0_m, 1); + const v2i64 out = res0_m + res1_m; + int32_t sum_m = __msa_copy_s_w((v4i32)out, 0); + return sum_m; +} +#define HADD_SW_S32(in) func_hadd_sw_s32(in) + +/* Description : Horizontal addition of 8 signed halfword elements + * Arguments : Input - in (signed halfword vector) + * Output - sum_m (s32 sum) + * Return Type - signed word + * Details : 8 signed halfword elements of input vector are added + * together and the resulting integer sum is returned + */ +static WEBP_INLINE int32_t func_hadd_sh_s32(v8i16 in) { + const v4i32 res = __msa_hadd_s_w(in, in); + const v2i64 res0 = __msa_hadd_s_d(res, res); + const v2i64 res1 = __msa_splati_d(res0, 1); + const v2i64 res2 = res0 + res1; + const int32_t sum_m = __msa_copy_s_w((v4i32)res2, 0); + return sum_m; +} +#define HADD_SH_S32(in) func_hadd_sh_s32(in) + +/* Description : Horizontal addition of 8 unsigned halfword elements + * Arguments : Input - in (unsigned halfword vector) + * Output - sum_m (u32 sum) + * Return Type - unsigned word + * Details : 8 unsigned halfword elements of input vector are added + * together and the resulting integer sum is returned + */ +static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) { + uint32_t sum_m; + const v4u32 res_m = __msa_hadd_u_w(in, in); + v2u64 res0_m = __msa_hadd_u_d(res_m, res_m); + v2u64 res1_m = (v2u64)__msa_splati_d((v2i64)res0_m, 1); + res0_m = res0_m + res1_m; + sum_m = __msa_copy_s_w((v4i32)res0_m, 0); + return sum_m; +} +#define HADD_UH_U32(in) func_hadd_uh_u32(in) + +/* Description : Horizontal addition of signed half word vector elements + Arguments : Inputs - in0, in1 + Outputs - out0, out1 + Return Type - as per RTYPE + Details : Each signed odd half word element from 'in0' is added to + even signed half word element from 'in0' (pairwise) and the + halfword result is written in 'out0' +*/ +#define HADD_SH2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_hadd_s_w((v8i16)in0, (v8i16)in0); \ + out1 = (RTYPE)__msa_hadd_s_w((v8i16)in1, (v8i16)in1); \ +} while (0) +#define HADD_SH2_SW(...) HADD_SH2(v4i32, __VA_ARGS__) + +#define HADD_SH4(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3) do { \ + HADD_SH2(RTYPE, in0, in1, out0, out1); \ + HADD_SH2(RTYPE, in2, in3, out2, out3); \ +} while (0) +#define HADD_SH4_SW(...) HADD_SH4(v4i32, __VA_ARGS__) + +/* Description : Horizontal subtraction of unsigned byte vector elements + * Arguments : Inputs - in0, in1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Each unsigned odd byte element from 'in0' is subtracted from + * even unsigned byte element from 'in0' (pairwise) and the + * halfword result is written to 'out0' + */ +#define HSUB_UB2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_hsub_u_h((v16u8)in0, (v16u8)in0); \ + out1 = (RTYPE)__msa_hsub_u_h((v16u8)in1, (v16u8)in1); \ +} while (0) +#define HSUB_UB2_UH(...) HSUB_UB2(v8u16, __VA_ARGS__) +#define HSUB_UB2_SH(...) HSUB_UB2(v8i16, __VA_ARGS__) +#define HSUB_UB2_SW(...) HSUB_UB2(v4i32, __VA_ARGS__) + +/* Description : Set element n input vector to GPR value + * Arguments : Inputs - in0, in1, in2, in3 + * Output - out + * Return Type - as per RTYPE + * Details : Set element 0 in vector 'out' to value specified in 'in0' + */ +#define INSERT_W2(RTYPE, in0, in1, out) do { \ + out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \ + out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \ +} while (0) +#define INSERT_W2_UB(...) INSERT_W2(v16u8, __VA_ARGS__) +#define INSERT_W2_SB(...) INSERT_W2(v16i8, __VA_ARGS__) + +#define INSERT_W4(RTYPE, in0, in1, in2, in3, out) do { \ + out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \ + out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \ + out = (RTYPE)__msa_insert_w((v4i32)out, 2, in2); \ + out = (RTYPE)__msa_insert_w((v4i32)out, 3, in3); \ +} while (0) +#define INSERT_W4_UB(...) INSERT_W4(v16u8, __VA_ARGS__) +#define INSERT_W4_SB(...) INSERT_W4(v16i8, __VA_ARGS__) +#define INSERT_W4_SW(...) INSERT_W4(v4i32, __VA_ARGS__) + +/* Description : Set element n of double word input vector to GPR value + * Arguments : Inputs - in0, in1 + * Output - out + * Return Type - as per RTYPE + * Details : Set element 0 in vector 'out' to GPR value specified in 'in0' + * Set element 1 in vector 'out' to GPR value specified in 'in1' + */ +#define INSERT_D2(RTYPE, in0, in1, out) do { \ + out = (RTYPE)__msa_insert_d((v2i64)out, 0, in0); \ + out = (RTYPE)__msa_insert_d((v2i64)out, 1, in1); \ +} while (0) +#define INSERT_D2_UB(...) INSERT_D2(v16u8, __VA_ARGS__) +#define INSERT_D2_SB(...) INSERT_D2(v16i8, __VA_ARGS__) + +/* Description : Interleave even byte elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even byte elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVEV_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_b((v16i8)in1, (v16i8)in0); \ + out1 = (RTYPE)__msa_ilvev_b((v16i8)in3, (v16i8)in2); \ +} while (0) +#define ILVEV_B2_UB(...) ILVEV_B2(v16u8, __VA_ARGS__) +#define ILVEV_B2_SB(...) ILVEV_B2(v16i8, __VA_ARGS__) +#define ILVEV_B2_UH(...) ILVEV_B2(v8u16, __VA_ARGS__) +#define ILVEV_B2_SH(...) ILVEV_B2(v8i16, __VA_ARGS__) +#define ILVEV_B2_SD(...) ILVEV_B2(v2i64, __VA_ARGS__) + +/* Description : Interleave odd byte elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Odd byte elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVOD_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvod_b((v16i8)in1, (v16i8)in0); \ + out1 = (RTYPE)__msa_ilvod_b((v16i8)in3, (v16i8)in2); \ +} while (0) +#define ILVOD_B2_UB(...) ILVOD_B2(v16u8, __VA_ARGS__) +#define ILVOD_B2_SB(...) ILVOD_B2(v16i8, __VA_ARGS__) +#define ILVOD_B2_UH(...) ILVOD_B2(v8u16, __VA_ARGS__) +#define ILVOD_B2_SH(...) ILVOD_B2(v8i16, __VA_ARGS__) +#define ILVOD_B2_SD(...) ILVOD_B2(v2i64, __VA_ARGS__) + +/* Description : Interleave even halfword elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even halfword elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVEV_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_h((v8i16)in1, (v8i16)in0); \ + out1 = (RTYPE)__msa_ilvev_h((v8i16)in3, (v8i16)in2); \ +} while (0) +#define ILVEV_H2_UB(...) ILVEV_H2(v16u8, __VA_ARGS__) +#define ILVEV_H2_UH(...) ILVEV_H2(v8u16, __VA_ARGS__) +#define ILVEV_H2_SH(...) ILVEV_H2(v8i16, __VA_ARGS__) +#define ILVEV_H2_SW(...) ILVEV_H2(v4i32, __VA_ARGS__) + +/* Description : Interleave odd halfword elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Odd halfword elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvod_h((v8i16)in1, (v8i16)in0); \ + out1 = (RTYPE)__msa_ilvod_h((v8i16)in3, (v8i16)in2); \ +} while (0) +#define ILVOD_H2_UB(...) ILVOD_H2(v16u8, __VA_ARGS__) +#define ILVOD_H2_UH(...) ILVOD_H2(v8u16, __VA_ARGS__) +#define ILVOD_H2_SH(...) ILVOD_H2(v8i16, __VA_ARGS__) +#define ILVOD_H2_SW(...) ILVOD_H2(v4i32, __VA_ARGS__) + +/* Description : Interleave even word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even word elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_w((v4i32)in1, (v4i32)in0); \ + out1 = (RTYPE)__msa_ilvev_w((v4i32)in3, (v4i32)in2); \ +} while (0) +#define ILVEV_W2_UB(...) ILVEV_W2(v16u8, __VA_ARGS__) +#define ILVEV_W2_SB(...) ILVEV_W2(v16i8, __VA_ARGS__) +#define ILVEV_W2_UH(...) ILVEV_W2(v8u16, __VA_ARGS__) +#define ILVEV_W2_SD(...) ILVEV_W2(v2i64, __VA_ARGS__) + +/* Description : Interleave even-odd word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even word elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + * Odd word elements of 'in2' and 'in3' are interleaved + * and written to 'out1' + */ +#define ILVEVOD_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_w((v4i32)in1, (v4i32)in0); \ + out1 = (RTYPE)__msa_ilvod_w((v4i32)in3, (v4i32)in2); \ +} while (0) +#define ILVEVOD_W2_UB(...) ILVEVOD_W2(v16u8, __VA_ARGS__) +#define ILVEVOD_W2_UH(...) ILVEVOD_W2(v8u16, __VA_ARGS__) +#define ILVEVOD_W2_SH(...) ILVEVOD_W2(v8i16, __VA_ARGS__) +#define ILVEVOD_W2_SW(...) ILVEVOD_W2(v4i32, __VA_ARGS__) + +/* Description : Interleave even-odd half-word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even half-word elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + * Odd half-word elements of 'in2' and 'in3' are interleaved + * and written to 'out1' + */ +#define ILVEVOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_h((v8i16)in1, (v8i16)in0); \ + out1 = (RTYPE)__msa_ilvod_h((v8i16)in3, (v8i16)in2); \ +} while (0) +#define ILVEVOD_H2_UB(...) ILVEVOD_H2(v16u8, __VA_ARGS__) +#define ILVEVOD_H2_UH(...) ILVEVOD_H2(v8u16, __VA_ARGS__) +#define ILVEVOD_H2_SH(...) ILVEVOD_H2(v8i16, __VA_ARGS__) +#define ILVEVOD_H2_SW(...) ILVEVOD_H2(v4i32, __VA_ARGS__) + +/* Description : Interleave even double word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even double word elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVEV_D2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_d((v2i64)in1, (v2i64)in0); \ + out1 = (RTYPE)__msa_ilvev_d((v2i64)in3, (v2i64)in2); \ +} while (0) +#define ILVEV_D2_UB(...) ILVEV_D2(v16u8, __VA_ARGS__) +#define ILVEV_D2_SB(...) ILVEV_D2(v16i8, __VA_ARGS__) +#define ILVEV_D2_SW(...) ILVEV_D2(v4i32, __VA_ARGS__) +#define ILVEV_D2_SD(...) ILVEV_D2(v2i64, __VA_ARGS__) + +/* Description : Interleave left half of byte elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Left half of byte elements of 'in0' and 'in1' are interleaved + * and written to 'out0'. + */ +#define ILVL_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvl_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_ilvl_b((v16i8)in2, (v16i8)in3); \ +} while (0) +#define ILVL_B2_UB(...) ILVL_B2(v16u8, __VA_ARGS__) +#define ILVL_B2_SB(...) ILVL_B2(v16i8, __VA_ARGS__) +#define ILVL_B2_UH(...) ILVL_B2(v8u16, __VA_ARGS__) +#define ILVL_B2_SH(...) ILVL_B2(v8i16, __VA_ARGS__) +#define ILVL_B2_SW(...) ILVL_B2(v4i32, __VA_ARGS__) + +/* Description : Interleave right half of byte elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Right half of byte elements of 'in0' and 'in1' are interleaved + * and written to out0. + */ +#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_ilvr_b((v16i8)in2, (v16i8)in3); \ +} while (0) +#define ILVR_B2_UB(...) ILVR_B2(v16u8, __VA_ARGS__) +#define ILVR_B2_SB(...) ILVR_B2(v16i8, __VA_ARGS__) +#define ILVR_B2_UH(...) ILVR_B2(v8u16, __VA_ARGS__) +#define ILVR_B2_SH(...) ILVR_B2(v8i16, __VA_ARGS__) +#define ILVR_B2_SW(...) ILVR_B2(v4i32, __VA_ARGS__) + +#define ILVR_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1); \ + ILVR_B2(RTYPE, in4, in5, in6, in7, out2, out3); \ +} while (0) +#define ILVR_B4_UB(...) ILVR_B4(v16u8, __VA_ARGS__) +#define ILVR_B4_SB(...) ILVR_B4(v16i8, __VA_ARGS__) +#define ILVR_B4_UH(...) ILVR_B4(v8u16, __VA_ARGS__) +#define ILVR_B4_SH(...) ILVR_B4(v8i16, __VA_ARGS__) +#define ILVR_B4_SW(...) ILVR_B4(v4i32, __VA_ARGS__) + +/* Description : Interleave right half of halfword elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Right half of halfword elements of 'in0' and 'in1' are + * interleaved and written to 'out0'. + */ +#define ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \ + out1 = (RTYPE)__msa_ilvr_h((v8i16)in2, (v8i16)in3); \ +} while (0) +#define ILVR_H2_UB(...) ILVR_H2(v16u8, __VA_ARGS__) +#define ILVR_H2_SH(...) ILVR_H2(v8i16, __VA_ARGS__) +#define ILVR_H2_SW(...) ILVR_H2(v4i32, __VA_ARGS__) + +#define ILVR_H4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1); \ + ILVR_H2(RTYPE, in4, in5, in6, in7, out2, out3); \ +} while (0) +#define ILVR_H4_UB(...) ILVR_H4(v16u8, __VA_ARGS__) +#define ILVR_H4_SH(...) ILVR_H4(v8i16, __VA_ARGS__) +#define ILVR_H4_SW(...) ILVR_H4(v4i32, __VA_ARGS__) + +/* Description : Interleave right half of double word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Right half of double word elements of 'in0' and 'in1' are + * interleaved and written to 'out0'. + */ +#define ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_d((v2i64)in0, (v2i64)in1); \ + out1 = (RTYPE)__msa_ilvr_d((v2i64)in2, (v2i64)in3); \ +} while (0) +#define ILVR_D2_UB(...) ILVR_D2(v16u8, __VA_ARGS__) +#define ILVR_D2_SB(...) ILVR_D2(v16i8, __VA_ARGS__) +#define ILVR_D2_SH(...) ILVR_D2(v8i16, __VA_ARGS__) + +#define ILVR_D4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1); \ + ILVR_D2(RTYPE, in4, in5, in6, in7, out2, out3); \ +} while (0) +#define ILVR_D4_SB(...) ILVR_D4(v16i8, __VA_ARGS__) +#define ILVR_D4_UB(...) ILVR_D4(v16u8, __VA_ARGS__) + +/* Description : Interleave both left and right half of input vectors + * Arguments : Inputs - in0, in1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Right half of byte elements from 'in0' and 'in1' are + * interleaved and written to 'out0' + */ +#define ILVRL_B2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_ilvl_b((v16i8)in0, (v16i8)in1); \ +} while (0) +#define ILVRL_B2_UB(...) ILVRL_B2(v16u8, __VA_ARGS__) +#define ILVRL_B2_SB(...) ILVRL_B2(v16i8, __VA_ARGS__) +#define ILVRL_B2_UH(...) ILVRL_B2(v8u16, __VA_ARGS__) +#define ILVRL_B2_SH(...) ILVRL_B2(v8i16, __VA_ARGS__) +#define ILVRL_B2_SW(...) ILVRL_B2(v4i32, __VA_ARGS__) + +#define ILVRL_H2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \ + out1 = (RTYPE)__msa_ilvl_h((v8i16)in0, (v8i16)in1); \ +} while (0) +#define ILVRL_H2_UB(...) ILVRL_H2(v16u8, __VA_ARGS__) +#define ILVRL_H2_SB(...) ILVRL_H2(v16i8, __VA_ARGS__) +#define ILVRL_H2_SH(...) ILVRL_H2(v8i16, __VA_ARGS__) +#define ILVRL_H2_SW(...) ILVRL_H2(v4i32, __VA_ARGS__) +#define ILVRL_H2_UW(...) ILVRL_H2(v4u32, __VA_ARGS__) + +#define ILVRL_W2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_w((v4i32)in0, (v4i32)in1); \ + out1 = (RTYPE)__msa_ilvl_w((v4i32)in0, (v4i32)in1); \ +} while (0) +#define ILVRL_W2_UB(...) ILVRL_W2(v16u8, __VA_ARGS__) +#define ILVRL_W2_SH(...) ILVRL_W2(v8i16, __VA_ARGS__) +#define ILVRL_W2_SW(...) ILVRL_W2(v4i32, __VA_ARGS__) +#define ILVRL_W2_UW(...) ILVRL_W2(v4u32, __VA_ARGS__) + +/* Description : Pack even byte elements of vector pairs + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even byte elements of 'in0' are copied to the left half of + * 'out0' & even byte elements of 'in1' are copied to the right + * half of 'out0'. + */ +#define PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_pckev_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_pckev_b((v16i8)in2, (v16i8)in3); \ +} while (0) +#define PCKEV_B2_SB(...) PCKEV_B2(v16i8, __VA_ARGS__) +#define PCKEV_B2_UB(...) PCKEV_B2(v16u8, __VA_ARGS__) +#define PCKEV_B2_SH(...) PCKEV_B2(v8i16, __VA_ARGS__) +#define PCKEV_B2_SW(...) PCKEV_B2(v4i32, __VA_ARGS__) + +#define PCKEV_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1); \ + PCKEV_B2(RTYPE, in4, in5, in6, in7, out2, out3); \ +} while (0) +#define PCKEV_B4_SB(...) PCKEV_B4(v16i8, __VA_ARGS__) +#define PCKEV_B4_UB(...) PCKEV_B4(v16u8, __VA_ARGS__) +#define PCKEV_B4_SH(...) PCKEV_B4(v8i16, __VA_ARGS__) +#define PCKEV_B4_SW(...) PCKEV_B4(v4i32, __VA_ARGS__) + +/* Description : Pack even halfword elements of vector pairs + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even halfword elements of 'in0' are copied to the left half of + * 'out0' & even halfword elements of 'in1' are copied to the + * right half of 'out0'. + */ +#define PCKEV_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_pckev_h((v8i16)in0, (v8i16)in1); \ + out1 = (RTYPE)__msa_pckev_h((v8i16)in2, (v8i16)in3); \ +} while (0) +#define PCKEV_H2_UH(...) PCKEV_H2(v8u16, __VA_ARGS__) +#define PCKEV_H2_SH(...) PCKEV_H2(v8i16, __VA_ARGS__) +#define PCKEV_H2_SW(...) PCKEV_H2(v4i32, __VA_ARGS__) +#define PCKEV_H2_UW(...) PCKEV_H2(v4u32, __VA_ARGS__) + +/* Description : Pack even word elements of vector pairs + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even word elements of 'in0' are copied to the left half of + * 'out0' & even word elements of 'in1' are copied to the + * right half of 'out0'. + */ +#define PCKEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_pckev_w((v4i32)in0, (v4i32)in1); \ + out1 = (RTYPE)__msa_pckev_w((v4i32)in2, (v4i32)in3); \ +} while (0) +#define PCKEV_W2_UH(...) PCKEV_W2(v8u16, __VA_ARGS__) +#define PCKEV_W2_SH(...) PCKEV_W2(v8i16, __VA_ARGS__) +#define PCKEV_W2_SW(...) PCKEV_W2(v4i32, __VA_ARGS__) +#define PCKEV_W2_UW(...) PCKEV_W2(v4u32, __VA_ARGS__) + +/* Description : Pack odd halfword elements of vector pairs + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Odd halfword elements of 'in0' are copied to the left half of + * 'out0' & odd halfword elements of 'in1' are copied to the + * right half of 'out0'. + */ +#define PCKOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_pckod_h((v8i16)in0, (v8i16)in1); \ + out1 = (RTYPE)__msa_pckod_h((v8i16)in2, (v8i16)in3); \ +} while (0) +#define PCKOD_H2_UH(...) PCKOD_H2(v8u16, __VA_ARGS__) +#define PCKOD_H2_SH(...) PCKOD_H2(v8i16, __VA_ARGS__) +#define PCKOD_H2_SW(...) PCKOD_H2(v4i32, __VA_ARGS__) +#define PCKOD_H2_UW(...) PCKOD_H2(v4u32, __VA_ARGS__) + +/* Description : Arithmetic immediate shift right all elements of word vector + * Arguments : Inputs - in0, in1, shift + * Outputs - in place operation + * Return Type - as per input vector RTYPE + * Details : Each element of vector 'in0' is right shifted by 'shift' and + * the result is written in-place. 'shift' is a GP variable. + */ +#define SRAI_W2(RTYPE, in0, in1, shift_val) do { \ + in0 = (RTYPE)SRAI_W(in0, shift_val); \ + in1 = (RTYPE)SRAI_W(in1, shift_val); \ +} while (0) +#define SRAI_W2_SW(...) SRAI_W2(v4i32, __VA_ARGS__) +#define SRAI_W2_UW(...) SRAI_W2(v4u32, __VA_ARGS__) + +#define SRAI_W4(RTYPE, in0, in1, in2, in3, shift_val) do { \ + SRAI_W2(RTYPE, in0, in1, shift_val); \ + SRAI_W2(RTYPE, in2, in3, shift_val); \ +} while (0) +#define SRAI_W4_SW(...) SRAI_W4(v4i32, __VA_ARGS__) +#define SRAI_W4_UW(...) SRAI_W4(v4u32, __VA_ARGS__) + +/* Description : Arithmetic shift right all elements of half-word vector + * Arguments : Inputs - in0, in1, shift + * Outputs - in place operation + * Return Type - as per input vector RTYPE + * Details : Each element of vector 'in0' is right shifted by 'shift' and + * the result is written in-place. 'shift' is a GP variable. + */ +#define SRAI_H2(RTYPE, in0, in1, shift_val) do { \ + in0 = (RTYPE)SRAI_H(in0, shift_val); \ + in1 = (RTYPE)SRAI_H(in1, shift_val); \ +} while (0) +#define SRAI_H2_SH(...) SRAI_H2(v8i16, __VA_ARGS__) +#define SRAI_H2_UH(...) SRAI_H2(v8u16, __VA_ARGS__) + +/* Description : Arithmetic rounded shift right all elements of word vector + * Arguments : Inputs - in0, in1, shift + * Outputs - in place operation + * Return Type - as per input vector RTYPE + * Details : Each element of vector 'in0' is right shifted by 'shift' and + * the result is written in-place. 'shift' is a GP variable. + */ +#define SRARI_W2(RTYPE, in0, in1, shift) do { \ + in0 = (RTYPE)__msa_srari_w((v4i32)in0, shift); \ + in1 = (RTYPE)__msa_srari_w((v4i32)in1, shift); \ +} while (0) +#define SRARI_W2_SW(...) SRARI_W2(v4i32, __VA_ARGS__) + +#define SRARI_W4(RTYPE, in0, in1, in2, in3, shift) do { \ + SRARI_W2(RTYPE, in0, in1, shift); \ + SRARI_W2(RTYPE, in2, in3, shift); \ +} while (0) +#define SRARI_W4_SH(...) SRARI_W4(v8i16, __VA_ARGS__) +#define SRARI_W4_UW(...) SRARI_W4(v4u32, __VA_ARGS__) +#define SRARI_W4_SW(...) SRARI_W4(v4i32, __VA_ARGS__) + +/* Description : Shift right arithmetic rounded double words + * Arguments : Inputs - in0, in1, shift + * Outputs - in place operation + * Return Type - as per RTYPE + * Details : Each element of vector 'in0' is shifted right arithmetically by + * the number of bits in the corresponding element in the vector + * 'shift'. The last discarded bit is added to shifted value for + * rounding and the result is written in-place. + * 'shift' is a vector. + */ +#define SRAR_D2(RTYPE, in0, in1, shift) do { \ + in0 = (RTYPE)__msa_srar_d((v2i64)in0, (v2i64)shift); \ + in1 = (RTYPE)__msa_srar_d((v2i64)in1, (v2i64)shift); \ +} while (0) +#define SRAR_D2_SW(...) SRAR_D2(v4i32, __VA_ARGS__) +#define SRAR_D2_SD(...) SRAR_D2(v2i64, __VA_ARGS__) +#define SRAR_D2_UD(...) SRAR_D2(v2u64, __VA_ARGS__) + +#define SRAR_D4(RTYPE, in0, in1, in2, in3, shift) do { \ + SRAR_D2(RTYPE, in0, in1, shift); \ + SRAR_D2(RTYPE, in2, in3, shift); \ +} while (0) +#define SRAR_D4_SD(...) SRAR_D4(v2i64, __VA_ARGS__) +#define SRAR_D4_UD(...) SRAR_D4(v2u64, __VA_ARGS__) + +/* Description : Addition of 2 pairs of half-word vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element in 'in0' is added to 'in1' and result is written + * to 'out0'. + */ +#define ADDVI_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)ADDVI_H(in0, in1); \ + out1 = (RTYPE)ADDVI_H(in2, in3); \ +} while (0) +#define ADDVI_H2_SH(...) ADDVI_H2(v8i16, __VA_ARGS__) +#define ADDVI_H2_UH(...) ADDVI_H2(v8u16, __VA_ARGS__) + +/* Description : Addition of 2 pairs of word vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element in 'in0' is added to 'in1' and result is written + * to 'out0'. + */ +#define ADDVI_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)ADDVI_W(in0, in1); \ + out1 = (RTYPE)ADDVI_W(in2, in3); \ +} while (0) +#define ADDVI_W2_SW(...) ADDVI_W2(v4i32, __VA_ARGS__) + +/* Description : Fill 2 pairs of word vectors with GP registers + * Arguments : Inputs - in0, in1 + * Outputs - out0, out1 + * Details : GP register in0 is replicated in each word element of out0 + * GP register in1 is replicated in each word element of out1 + */ +#define FILL_W2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_fill_w(in0); \ + out1 = (RTYPE)__msa_fill_w(in1); \ +} while (0) +#define FILL_W2_SW(...) FILL_W2(v4i32, __VA_ARGS__) + +/* Description : Addition of 2 pairs of vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element in 'in0' is added to 'in1' and result is written + * to 'out0'. + */ +#define ADD2(in0, in1, in2, in3, out0, out1) do { \ + out0 = in0 + in1; \ + out1 = in2 + in3; \ +} while (0) + +#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + ADD2(in0, in1, in2, in3, out0, out1); \ + ADD2(in4, in5, in6, in7, out2, out3); \ +} while (0) + +/* Description : Subtraction of 2 pairs of vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element in 'in1' is subtracted from 'in0' and result is + * written to 'out0'. + */ +#define SUB2(in0, in1, in2, in3, out0, out1) do { \ + out0 = in0 - in1; \ + out1 = in2 - in3; \ +} while (0) + +#define SUB3(in0, in1, in2, in3, in4, in5, out0, out1, out2) do { \ + out0 = in0 - in1; \ + out1 = in2 - in3; \ + out2 = in4 - in5; \ +} while (0) + +#define SUB4(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + out0 = in0 - in1; \ + out1 = in2 - in3; \ + out2 = in4 - in5; \ + out3 = in6 - in7; \ +} while (0) + +/* Description : Addition - Subtraction of input vectors + * Arguments : Inputs - in0, in1 + * Outputs - out0, out1 + * Details : Each element in 'in1' is added to 'in0' and result is + * written to 'out0'. + * Each element in 'in1' is subtracted from 'in0' and result is + * written to 'out1'. + */ +#define ADDSUB2(in0, in1, out0, out1) do { \ + out0 = in0 + in1; \ + out1 = in0 - in1; \ +} while (0) + +/* Description : Multiplication of pairs of vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element from 'in0' is multiplied with elements from 'in1' + * and the result is written to 'out0' + */ +#define MUL2(in0, in1, in2, in3, out0, out1) do { \ + out0 = in0 * in1; \ + out1 = in2 * in3; \ +} while (0) + +#define MUL4(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + MUL2(in0, in1, in2, in3, out0, out1); \ + MUL2(in4, in5, in6, in7, out2, out3); \ +} while (0) + +/* Description : Sign extend halfword elements from right half of the vector + * Arguments : Input - in (halfword vector) + * Output - out (sign extended word vector) + * Return Type - signed word + * Details : Sign bit of halfword elements from input vector 'in' is + * extracted and interleaved with same vector 'in0' to generate + * 4 word elements keeping sign intact + */ +#define UNPCK_R_SH_SW(in, out) do { \ + const v8i16 sign_m = __msa_clti_s_h((v8i16)in, 0); \ + out = (v4i32)__msa_ilvr_h(sign_m, (v8i16)in); \ +} while (0) + +/* Description : Sign extend halfword elements from input vector and return + * the result in pair of vectors + * Arguments : Input - in (halfword vector) + * Outputs - out0, out1 (sign extended word vectors) + * Return Type - signed word + * Details : Sign bit of halfword elements from input vector 'in' is + * extracted and interleaved right with same vector 'in0' to + * generate 4 signed word elements in 'out0' + * Then interleaved left with same vector 'in0' to + * generate 4 signed word elements in 'out1' + */ +#define UNPCK_SH_SW(in, out0, out1) do { \ + const v8i16 tmp_m = __msa_clti_s_h((v8i16)in, 0); \ + ILVRL_H2_SW(tmp_m, in, out0, out1); \ +} while (0) + +/* Description : Butterfly of 4 input vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + * Details : Butterfly operation + */ +#define BUTTERFLY_4(in0, in1, in2, in3, out0, out1, out2, out3) do { \ + out0 = in0 + in3; \ + out1 = in1 + in2; \ + out2 = in1 - in2; \ + out3 = in0 - in3; \ +} while (0) + +/* Description : Transpose 16x4 block into 4x16 with byte elements in vectors + * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7, + * in8, in9, in10, in11, in12, in13, in14, in15 + * Outputs - out0, out1, out2, out3 + * Return Type - unsigned byte + */ +#define TRANSPOSE16x4_UB_UB(in0, in1, in2, in3, in4, in5, in6, in7, \ + in8, in9, in10, in11, in12, in13, in14, in15, \ + out0, out1, out2, out3) do { \ + v2i64 tmp0_m, tmp1_m, tmp2_m, tmp3_m, tmp4_m, tmp5_m; \ + ILVEV_W2_SD(in0, in4, in8, in12, tmp2_m, tmp3_m); \ + ILVEV_W2_SD(in1, in5, in9, in13, tmp0_m, tmp1_m); \ + ILVEV_D2_UB(tmp2_m, tmp3_m, tmp0_m, tmp1_m, out1, out3); \ + ILVEV_W2_SD(in2, in6, in10, in14, tmp4_m, tmp5_m); \ + ILVEV_W2_SD(in3, in7, in11, in15, tmp0_m, tmp1_m); \ + ILVEV_D2_SD(tmp4_m, tmp5_m, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + ILVEV_B2_SD(out1, out3, tmp2_m, tmp3_m, tmp0_m, tmp1_m); \ + ILVEVOD_H2_UB(tmp0_m, tmp1_m, tmp0_m, tmp1_m, out0, out2); \ + ILVOD_B2_SD(out1, out3, tmp2_m, tmp3_m, tmp0_m, tmp1_m); \ + ILVEVOD_H2_UB(tmp0_m, tmp1_m, tmp0_m, tmp1_m, out1, out3); \ +} while (0) + +/* Description : Transpose 16x8 block into 8x16 with byte elements in vectors + * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7, + * in8, in9, in10, in11, in12, in13, in14, in15 + * Outputs - out0, out1, out2, out3, out4, out5, out6, out7 + * Return Type - unsigned byte + */ +#define TRANSPOSE16x8_UB_UB(in0, in1, in2, in3, in4, in5, in6, in7, \ + in8, in9, in10, in11, in12, in13, in14, in15, \ + out0, out1, out2, out3, out4, out5, \ + out6, out7) do { \ + v8i16 tmp0_m, tmp1_m, tmp4_m, tmp5_m, tmp6_m, tmp7_m; \ + v4i32 tmp2_m, tmp3_m; \ + ILVEV_D2_UB(in0, in8, in1, in9, out7, out6); \ + ILVEV_D2_UB(in2, in10, in3, in11, out5, out4); \ + ILVEV_D2_UB(in4, in12, in5, in13, out3, out2); \ + ILVEV_D2_UB(in6, in14, in7, in15, out1, out0); \ + ILVEV_B2_SH(out7, out6, out5, out4, tmp0_m, tmp1_m); \ + ILVOD_B2_SH(out7, out6, out5, out4, tmp4_m, tmp5_m); \ + ILVEV_B2_UB(out3, out2, out1, out0, out5, out7); \ + ILVOD_B2_SH(out3, out2, out1, out0, tmp6_m, tmp7_m); \ + ILVEV_H2_SW(tmp0_m, tmp1_m, out5, out7, tmp2_m, tmp3_m); \ + ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out0, out4); \ + ILVOD_H2_SW(tmp0_m, tmp1_m, out5, out7, tmp2_m, tmp3_m); \ + ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out2, out6); \ + ILVEV_H2_SW(tmp4_m, tmp5_m, tmp6_m, tmp7_m, tmp2_m, tmp3_m); \ + ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out1, out5); \ + ILVOD_H2_SW(tmp4_m, tmp5_m, tmp6_m, tmp7_m, tmp2_m, tmp3_m); \ + ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out3, out7); \ +} while (0) + +/* Description : Transpose 4x4 block with word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + * Return Type - as per RTYPE + */ +#define TRANSPOSE4x4_W(RTYPE, in0, in1, in2, in3, \ + out0, out1, out2, out3) do { \ + v4i32 s0_m, s1_m, s2_m, s3_m; \ + ILVRL_W2_SW(in1, in0, s0_m, s1_m); \ + ILVRL_W2_SW(in3, in2, s2_m, s3_m); \ + out0 = (RTYPE)__msa_ilvr_d((v2i64)s2_m, (v2i64)s0_m); \ + out1 = (RTYPE)__msa_ilvl_d((v2i64)s2_m, (v2i64)s0_m); \ + out2 = (RTYPE)__msa_ilvr_d((v2i64)s3_m, (v2i64)s1_m); \ + out3 = (RTYPE)__msa_ilvl_d((v2i64)s3_m, (v2i64)s1_m); \ +} while (0) +#define TRANSPOSE4x4_SW_SW(...) TRANSPOSE4x4_W(v4i32, __VA_ARGS__) + +/* Description : Add block 4x4 + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + * Details : Least significant 4 bytes from each input vector are added to + * the destination bytes, clipped between 0-255 and stored. + */ +#define ADDBLK_ST4x4_UB(in0, in1, in2, in3, pdst, stride) do { \ + uint32_t src0_m, src1_m, src2_m, src3_m; \ + v8i16 inp0_m, inp1_m, res0_m, res1_m; \ + v16i8 dst0_m = { 0 }; \ + v16i8 dst1_m = { 0 }; \ + const v16i8 zero_m = { 0 }; \ + ILVR_D2_SH(in1, in0, in3, in2, inp0_m, inp1_m); \ + LW4(pdst, stride, src0_m, src1_m, src2_m, src3_m); \ + INSERT_W2_SB(src0_m, src1_m, dst0_m); \ + INSERT_W2_SB(src2_m, src3_m, dst1_m); \ + ILVR_B2_SH(zero_m, dst0_m, zero_m, dst1_m, res0_m, res1_m); \ + ADD2(res0_m, inp0_m, res1_m, inp1_m, res0_m, res1_m); \ + CLIP_SH2_0_255(res0_m, res1_m); \ + PCKEV_B2_SB(res0_m, res0_m, res1_m, res1_m, dst0_m, dst1_m); \ + ST4x4_UB(dst0_m, dst1_m, 0, 1, 0, 1, pdst, stride); \ +} while (0) + +/* Description : Pack even byte elements, extract 0 & 2 index words from pair + * of results and store 4 words in destination memory as per + * stride + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + */ +#define PCKEV_ST4x4_UB(in0, in1, in2, in3, pdst, stride) do { \ + v16i8 tmp0_m, tmp1_m; \ + PCKEV_B2_SB(in1, in0, in3, in2, tmp0_m, tmp1_m); \ + ST4x4_UB(tmp0_m, tmp1_m, 0, 2, 0, 2, pdst, stride); \ +} while (0) + +/* Description : average with rounding (in0 + in1 + 1) / 2. + * Arguments : Inputs - in0, in1, in2, in3, + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Each unsigned byte element from 'in0' vector is added with + * each unsigned byte element from 'in1' vector. Then the average + * with rounding is calculated and written to 'out0' + */ +#define AVER_UB2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_aver_u_b((v16u8)in0, (v16u8)in1); \ + out1 = (RTYPE)__msa_aver_u_b((v16u8)in2, (v16u8)in3); \ +} while (0) +#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__) + +#endif // WEBP_USE_MSA +#endif // WEBP_DSP_MSA_MACRO_H_ diff --git a/libraries/webp/src/dsp/neon.h b/libraries/webp/src/dsp/neon.h new file mode 100644 index 0000000000..14acb4044b --- /dev/null +++ b/libraries/webp/src/dsp/neon.h @@ -0,0 +1,104 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON common code. + +#ifndef WEBP_DSP_NEON_H_ +#define WEBP_DSP_NEON_H_ + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include + +// Right now, some intrinsics functions seem slower, so we disable them +// everywhere except newer clang/gcc or aarch64 where the inline assembly is +// incompatible. +#if LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 9) || WEBP_AARCH64 +#define WEBP_USE_INTRINSICS // use intrinsics when possible +#endif + +#define INIT_VECTOR2(v, a, b) do { \ + v.val[0] = a; \ + v.val[1] = b; \ +} while (0) + +#define INIT_VECTOR3(v, a, b, c) do { \ + v.val[0] = a; \ + v.val[1] = b; \ + v.val[2] = c; \ +} while (0) + +#define INIT_VECTOR4(v, a, b, c, d) do { \ + v.val[0] = a; \ + v.val[1] = b; \ + v.val[2] = c; \ + v.val[3] = d; \ +} while (0) + +// if using intrinsics, this flag avoids some functions that make gcc-4.6.3 +// crash ("internal compiler error: in immed_double_const, at emit-rtl."). +// (probably similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=48183) +#if !(LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 8) || WEBP_AARCH64) +#define WORK_AROUND_GCC +#endif + +static WEBP_INLINE int32x4x4_t Transpose4x4_NEON(const int32x4x4_t rows) { + uint64x2x2_t row01, row23; + + row01.val[0] = vreinterpretq_u64_s32(rows.val[0]); + row01.val[1] = vreinterpretq_u64_s32(rows.val[1]); + row23.val[0] = vreinterpretq_u64_s32(rows.val[2]); + row23.val[1] = vreinterpretq_u64_s32(rows.val[3]); + // Transpose 64-bit values (there's no vswp equivalent) + { + const uint64x1_t row0h = vget_high_u64(row01.val[0]); + const uint64x1_t row2l = vget_low_u64(row23.val[0]); + const uint64x1_t row1h = vget_high_u64(row01.val[1]); + const uint64x1_t row3l = vget_low_u64(row23.val[1]); + row01.val[0] = vcombine_u64(vget_low_u64(row01.val[0]), row2l); + row23.val[0] = vcombine_u64(row0h, vget_high_u64(row23.val[0])); + row01.val[1] = vcombine_u64(vget_low_u64(row01.val[1]), row3l); + row23.val[1] = vcombine_u64(row1h, vget_high_u64(row23.val[1])); + } + { + const int32x4x2_t out01 = vtrnq_s32(vreinterpretq_s32_u64(row01.val[0]), + vreinterpretq_s32_u64(row01.val[1])); + const int32x4x2_t out23 = vtrnq_s32(vreinterpretq_s32_u64(row23.val[0]), + vreinterpretq_s32_u64(row23.val[1])); + int32x4x4_t out; + out.val[0] = out01.val[0]; + out.val[1] = out01.val[1]; + out.val[2] = out23.val[0]; + out.val[3] = out23.val[1]; + return out; + } +} + +#if 0 // Useful debug macro. +#include +#define PRINT_REG(REG, SIZE) do { \ + int i; \ + printf("%s \t[%d]: 0x", #REG, SIZE); \ + if (SIZE == 8) { \ + uint8_t _tmp[8]; \ + vst1_u8(_tmp, (REG)); \ + for (i = 0; i < 8; ++i) printf("%.2x ", _tmp[i]); \ + } else if (SIZE == 16) { \ + uint16_t _tmp[4]; \ + vst1_u16(_tmp, (REG)); \ + for (i = 0; i < 4; ++i) printf("%.4x ", _tmp[i]); \ + } \ + printf("\n"); \ +} while (0) +#endif + +#endif // WEBP_USE_NEON +#endif // WEBP_DSP_NEON_H_ diff --git a/libraries/webp/src/dsp/quant.h b/libraries/webp/src/dsp/quant.h new file mode 100644 index 0000000000..2830038310 --- /dev/null +++ b/libraries/webp/src/dsp/quant.h @@ -0,0 +1,91 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- + +#ifndef WEBP_DSP_QUANT_H_ +#define WEBP_DSP_QUANT_H_ + +#include + +#include "src/dsp/dsp.h" +#include "include/webp/types.h" + +#if defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && \ + !defined(WEBP_HAVE_NEON_RTCD) +#include + +#define IsFlat IsFlat_NEON + +static uint32_t horizontal_add_uint32x4(const uint32x4_t a) { +#if WEBP_AARCH64 + return vaddvq_u32(a); +#else + const uint64x2_t b = vpaddlq_u32(a); + const uint32x2_t c = vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)), + vreinterpret_u32_u64(vget_high_u64(b))); + return vget_lane_u32(c, 0); +#endif +} + +static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, + int thresh) { + const int16x8_t tst_ones = vdupq_n_s16(-1); + uint32x4_t sum = vdupq_n_u32(0); + int i; + + for (i = 0; i < num_blocks; ++i) { + // Set DC to zero. + const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0); + const int16x8_t a_1 = vld1q_s16(levels + 8); + + const uint16x8_t b_0 = vshrq_n_u16(vtstq_s16(a_0, tst_ones), 15); + const uint16x8_t b_1 = vshrq_n_u16(vtstq_s16(a_1, tst_ones), 15); + + sum = vpadalq_u16(sum, b_0); + sum = vpadalq_u16(sum, b_1); + + levels += 16; + } + return thresh >= (int)horizontal_add_uint32x4(sum); +} + +#else + +#define IsFlat IsFlat_C + +static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, + int thresh) { + int score = 0; + while (num_blocks-- > 0) { // TODO(skal): refine positional scoring? + int i; + for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC + score += (levels[i] != 0); + if (score > thresh) return 0; + } + levels += 16; + } + return 1; +} + +#endif // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && + // !defined(WEBP_HAVE_NEON_RTCD) + +static WEBP_INLINE int IsFlatSource16(const uint8_t* src) { + const uint32_t v = src[0] * 0x01010101u; + int i; + for (i = 0; i < 16; ++i) { + if (memcmp(src + 0, &v, 4) || memcmp(src + 4, &v, 4) || + memcmp(src + 8, &v, 4) || memcmp(src + 12, &v, 4)) { + return 0; + } + src += BPS; + } + return 1; +} + +#endif // WEBP_DSP_QUANT_H_ diff --git a/libraries/webp/src/dsp/rescaler.c b/libraries/webp/src/dsp/rescaler.c new file mode 100644 index 0000000000..325d8be180 --- /dev/null +++ b/libraries/webp/src/dsp/rescaler.c @@ -0,0 +1,252 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dsp/dsp.h" +#include "src/utils/rescaler_utils.h" + +//------------------------------------------------------------------------------ +// Implementations of critical functions ImportRow / ExportRow + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +//------------------------------------------------------------------------------ +// Row import + +void WebPRescalerImportRowExpand_C(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + int channel; + assert(!WebPRescalerInputDone(wrk)); + assert(wrk->x_expand); + for (channel = 0; channel < x_stride; ++channel) { + int x_in = channel; + int x_out = channel; + // simple bilinear interpolation + int accum = wrk->x_add; + rescaler_t left = (rescaler_t)src[x_in]; + rescaler_t right = + (wrk->src_width > 1) ? (rescaler_t)src[x_in + x_stride] : left; + x_in += x_stride; + while (1) { + wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum; + x_out += x_stride; + if (x_out >= x_out_max) break; + accum -= wrk->x_sub; + if (accum < 0) { + left = right; + x_in += x_stride; + assert(x_in < wrk->src_width * x_stride); + right = (rescaler_t)src[x_in]; + accum += wrk->x_add; + } + } + assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0); + } +} + +void WebPRescalerImportRowShrink_C(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + int channel; + assert(!WebPRescalerInputDone(wrk)); + assert(!wrk->x_expand); + for (channel = 0; channel < x_stride; ++channel) { + int x_in = channel; + int x_out = channel; + uint32_t sum = 0; + int accum = 0; + while (x_out < x_out_max) { + uint32_t base = 0; + accum += wrk->x_add; + while (accum > 0) { + accum -= wrk->x_sub; + assert(x_in < wrk->src_width * x_stride); + base = src[x_in]; + sum += base; + x_in += x_stride; + } + { // Emit next horizontal pixel. + const rescaler_t frac = base * (-accum); + wrk->frow[x_out] = sum * wrk->x_sub - frac; + // fresh fractional start for next pixel + sum = (int)MULT_FIX(frac, wrk->fx_scale); + } + x_out += x_stride; + } + assert(accum == 0); + } +} + +//------------------------------------------------------------------------------ +// Row export + +void WebPRescalerExportRowExpand_C(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* const frow = wrk->frow; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + for (x_out = 0; x_out < x_out_max; ++x_out) { + const uint32_t J = frow[x_out]; + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + for (x_out = 0; x_out < x_out_max; ++x_out) { + const uint64_t I = (uint64_t)A * frow[x_out] + + (uint64_t)B * irow[x_out]; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* const frow = wrk->frow; + const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + if (yscale) { + for (x_out = 0; x_out < x_out_max; ++x_out) { + const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale); + const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = frac; // new fractional start + } + } else { + for (x_out = 0; x_out < x_out_max; ++x_out) { + const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = 0; + } + } +} + +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + +//------------------------------------------------------------------------------ +// Main entry calls + +void WebPRescalerImportRow(WebPRescaler* const wrk, const uint8_t* src) { + assert(!WebPRescalerInputDone(wrk)); + if (!wrk->x_expand) { + WebPRescalerImportRowShrink(wrk, src); + } else { + WebPRescalerImportRowExpand(wrk, src); + } +} + +void WebPRescalerExportRow(WebPRescaler* const wrk) { + if (wrk->y_accum <= 0) { + assert(!WebPRescalerOutputDone(wrk)); + if (wrk->y_expand) { + WebPRescalerExportRowExpand(wrk); + } else if (wrk->fxy_scale) { + WebPRescalerExportRowShrink(wrk); + } else { // special case + int i; + assert(wrk->src_height == wrk->dst_height && wrk->x_add == 1); + assert(wrk->src_width == 1 && wrk->dst_width <= 2); + for (i = 0; i < wrk->num_channels * wrk->dst_width; ++i) { + wrk->dst[i] = wrk->irow[i]; + wrk->irow[i] = 0; + } + } + wrk->y_accum += wrk->y_add; + wrk->dst += wrk->dst_stride; + ++wrk->dst_y; + } +} + +//------------------------------------------------------------------------------ + +WebPRescalerImportRowFunc WebPRescalerImportRowExpand; +WebPRescalerImportRowFunc WebPRescalerImportRowShrink; + +WebPRescalerExportRowFunc WebPRescalerExportRowExpand; +WebPRescalerExportRowFunc WebPRescalerExportRowShrink; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void WebPRescalerDspInitSSE2(void); +extern void WebPRescalerDspInitMIPS32(void); +extern void WebPRescalerDspInitMIPSdspR2(void); +extern void WebPRescalerDspInitMSA(void); +extern void WebPRescalerDspInitNEON(void); + +WEBP_DSP_INIT_FUNC(WebPRescalerDspInit) { +#if !defined(WEBP_REDUCE_SIZE) +#if !WEBP_NEON_OMIT_C_CODE + WebPRescalerExportRowExpand = WebPRescalerExportRowExpand_C; + WebPRescalerExportRowShrink = WebPRescalerExportRowShrink_C; +#endif + + WebPRescalerImportRowExpand = WebPRescalerImportRowExpand_C; + WebPRescalerImportRowShrink = WebPRescalerImportRowShrink_C; + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPRescalerDspInitSSE2(); + } +#endif +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + WebPRescalerDspInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPRescalerDspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + WebPRescalerDspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPRescalerDspInitNEON(); + } +#endif + + assert(WebPRescalerExportRowExpand != NULL); + assert(WebPRescalerExportRowShrink != NULL); + assert(WebPRescalerImportRowExpand != NULL); + assert(WebPRescalerImportRowShrink != NULL); +#endif // WEBP_REDUCE_SIZE +} diff --git a/libraries/webp/src/dsp/rescaler_mips32.c b/libraries/webp/src/dsp/rescaler_mips32.c new file mode 100644 index 0000000000..61f63c616c --- /dev/null +++ b/libraries/webp/src/dsp/rescaler_mips32.c @@ -0,0 +1,295 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of rescaling functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) && !defined(WEBP_REDUCE_SIZE) + +#include +#include "src/utils/rescaler_utils.h" + +//------------------------------------------------------------------------------ +// Row import + +static void ImportRowShrink_MIPS32(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const int fx_scale = wrk->fx_scale; + const int x_add = wrk->x_add; + const int x_sub = wrk->x_sub; + const int x_stride1 = x_stride << 2; + int channel; + assert(!wrk->x_expand); + assert(!WebPRescalerInputDone(wrk)); + + for (channel = 0; channel < x_stride; ++channel) { + const uint8_t* src1 = src + channel; + rescaler_t* frow = wrk->frow + channel; + int temp1, temp2, temp3; + int base, frac, sum; + int accum, accum1; + int loop_c = x_out_max - channel; + + __asm__ volatile ( + "li %[temp1], 0x8000 \n\t" + "li %[temp2], 0x10000 \n\t" + "li %[sum], 0 \n\t" + "li %[accum], 0 \n\t" + "1: \n\t" + "addu %[accum], %[accum], %[x_add] \n\t" + "li %[base], 0 \n\t" + "blez %[accum], 3f \n\t" + "2: \n\t" + "lbu %[base], 0(%[src1]) \n\t" + "subu %[accum], %[accum], %[x_sub] \n\t" + "addu %[src1], %[src1], %[x_stride] \n\t" + "addu %[sum], %[sum], %[base] \n\t" + "bgtz %[accum], 2b \n\t" + "3: \n\t" + "negu %[accum1], %[accum] \n\t" + "mul %[frac], %[base], %[accum1] \n\t" + "mul %[temp3], %[sum], %[x_sub] \n\t" + "subu %[loop_c], %[loop_c], %[x_stride] \n\t" + "mult %[temp1], %[temp2] \n\t" + "maddu %[frac], %[fx_scale] \n\t" + "mfhi %[sum] \n\t" + "subu %[temp3], %[temp3], %[frac] \n\t" + "sw %[temp3], 0(%[frow]) \n\t" + "addu %[frow], %[frow], %[x_stride1] \n\t" + "bgtz %[loop_c], 1b \n\t" + : [accum]"=&r"(accum), [src1]"+r"(src1), [temp3]"=&r"(temp3), + [sum]"=&r"(sum), [base]"=&r"(base), [frac]"=&r"(frac), + [frow]"+r"(frow), [accum1]"=&r"(accum1), + [temp2]"=&r"(temp2), [temp1]"=&r"(temp1) + : [x_stride]"r"(x_stride), [fx_scale]"r"(fx_scale), + [x_sub]"r"(x_sub), [x_add]"r"(x_add), + [loop_c]"r"(loop_c), [x_stride1]"r"(x_stride1) + : "memory", "hi", "lo" + ); + assert(accum == 0); + } +} + +static void ImportRowExpand_MIPS32(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const int x_add = wrk->x_add; + const int x_sub = wrk->x_sub; + const int src_width = wrk->src_width; + const int x_stride1 = x_stride << 2; + int channel; + assert(wrk->x_expand); + assert(!WebPRescalerInputDone(wrk)); + + for (channel = 0; channel < x_stride; ++channel) { + const uint8_t* src1 = src + channel; + rescaler_t* frow = wrk->frow + channel; + int temp1, temp2, temp3, temp4; + int frac; + int accum; + int x_out = channel; + + __asm__ volatile ( + "addiu %[temp3], %[src_width], -1 \n\t" + "lbu %[temp2], 0(%[src1]) \n\t" + "addu %[src1], %[src1], %[x_stride] \n\t" + "bgtz %[temp3], 0f \n\t" + "addiu %[temp1], %[temp2], 0 \n\t" + "b 3f \n\t" + "0: \n\t" + "lbu %[temp1], 0(%[src1]) \n\t" + "3: \n\t" + "addiu %[accum], %[x_add], 0 \n\t" + "1: \n\t" + "subu %[temp3], %[temp2], %[temp1] \n\t" + "mul %[temp3], %[temp3], %[accum] \n\t" + "mul %[temp4], %[temp1], %[x_add] \n\t" + "addu %[temp3], %[temp4], %[temp3] \n\t" + "sw %[temp3], 0(%[frow]) \n\t" + "addu %[frow], %[frow], %[x_stride1] \n\t" + "addu %[x_out], %[x_out], %[x_stride] \n\t" + "subu %[temp3], %[x_out], %[x_out_max] \n\t" + "bgez %[temp3], 2f \n\t" + "subu %[accum], %[accum], %[x_sub] \n\t" + "bgez %[accum], 4f \n\t" + "addiu %[temp2], %[temp1], 0 \n\t" + "addu %[src1], %[src1], %[x_stride] \n\t" + "lbu %[temp1], 0(%[src1]) \n\t" + "addu %[accum], %[accum], %[x_add] \n\t" + "4: \n\t" + "b 1b \n\t" + "2: \n\t" + : [src1]"+r"(src1), [accum]"=&r"(accum), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), + [x_out]"+r"(x_out), [frac]"=&r"(frac), [frow]"+r"(frow) + : [x_stride]"r"(x_stride), [x_add]"r"(x_add), [x_sub]"r"(x_sub), + [x_stride1]"r"(x_stride1), [src_width]"r"(src_width), + [x_out_max]"r"(x_out_max) + : "memory", "hi", "lo" + ); + assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0); + } +} + +//------------------------------------------------------------------------------ +// Row export + +static void ExportRowExpand_MIPS32(WebPRescaler* const wrk) { + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* frow = wrk->frow; + int temp0, temp1, temp3, temp4, temp5, loop_end; + const int temp2 = (int)wrk->fy_scale; + const int temp6 = x_out_max << 2; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "addiu %[dst], %[dst], 1 \n\t" + "addiu %[frow], %[frow], 4 \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[temp0], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [dst]"+r"(dst), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [temp6]"r"(temp6) + : "memory", "hi", "lo" + ); + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "lw %[temp1], 0(%[irow]) \n\t" + "addiu %[dst], %[dst], 1 \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[A], %[temp0] \n\t" + "maddu %[B], %[temp1] \n\t" + "addiu %[frow], %[frow], 4 \n\t" + "addiu %[irow], %[irow], 4 \n\t" + "mfhi %[temp5] \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[temp5], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B) + : "memory", "hi", "lo" + ); + } +} + +#if 0 // disabled for now. TODO(skal): make match the C-code +static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) { + const int x_out_max = wrk->dst_width * wrk->num_channels; + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const rescaler_t* frow = wrk->frow; + const int yscale = wrk->fy_scale * (-wrk->y_accum); + int temp0, temp1, temp3, temp4, temp5, loop_end; + const int temp2 = (int)wrk->fxy_scale; + const int temp6 = x_out_max << 2; + + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + assert(wrk->fxy_scale != 0); + if (yscale) { + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "mult %[temp3], %[temp4] \n\t" + "addiu %[frow], %[frow], 4 \n\t" + "maddu %[temp0], %[yscale] \n\t" + "mfhi %[temp1] \n\t" + "lw %[temp0], 0(%[irow]) \n\t" + "addiu %[dst], %[dst], 1 \n\t" + "addiu %[irow], %[irow], 4 \n\t" + "subu %[temp0], %[temp0], %[temp1] \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[temp0], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sw %[temp1], -4(%[irow]) \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [yscale]"r"(yscale), [temp6]"r"(temp6) + : "memory", "hi", "lo" + ); + } else { + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[irow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[irow]) \n\t" + "addiu %[dst], %[dst], 1 \n\t" + "addiu %[irow], %[irow], 4 \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[temp0], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sw $zero, -4(%[irow]) \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[irow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow), + [dst]"+r"(dst), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [temp6]"r"(temp6) + : "memory", "hi", "lo" + ); + } +} +#endif // 0 + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPRescalerDspInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) { + WebPRescalerImportRowExpand = ImportRowExpand_MIPS32; + WebPRescalerImportRowShrink = ImportRowShrink_MIPS32; + WebPRescalerExportRowExpand = ExportRowExpand_MIPS32; +// WebPRescalerExportRowShrink = ExportRowShrink_MIPS32; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/libraries/webp/src/dsp/rescaler_mips_dsp_r2.c b/libraries/webp/src/dsp/rescaler_mips_dsp_r2.c new file mode 100644 index 0000000000..419b741fa5 --- /dev/null +++ b/libraries/webp/src/dsp/rescaler_mips_dsp_r2.c @@ -0,0 +1,314 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of rescaling functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) && !defined(WEBP_REDUCE_SIZE) + +#include +#include "src/utils/rescaler_utils.h" + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +//------------------------------------------------------------------------------ +// Row export + +#if 0 // disabled for now. TODO(skal): make match the C-code +static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) { + int i; + const int x_out_max = wrk->dst_width * wrk->num_channels; + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const rescaler_t* frow = wrk->frow; + const int yscale = wrk->fy_scale * (-wrk->y_accum); + int temp0, temp1, temp2, temp3, temp4, temp5, loop_end; + const int temp7 = (int)wrk->fxy_scale; + const int temp6 = (x_out_max & ~0x3) << 2; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + assert(wrk->fxy_scale != 0); + if (yscale) { + if (x_out_max >= 4) { + int temp8, temp9, temp10, temp11; + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "lw %[temp1], 4(%[frow]) \n\t" + "lw %[temp2], 8(%[frow]) \n\t" + "lw %[temp5], 12(%[frow]) \n\t" + "mult $ac0, %[temp3], %[temp4] \n\t" + "maddu $ac0, %[temp0], %[yscale] \n\t" + "mult $ac1, %[temp3], %[temp4] \n\t" + "maddu $ac1, %[temp1], %[yscale] \n\t" + "mult $ac2, %[temp3], %[temp4] \n\t" + "maddu $ac2, %[temp2], %[yscale] \n\t" + "mult $ac3, %[temp3], %[temp4] \n\t" + "maddu $ac3, %[temp5], %[yscale] \n\t" + "addiu %[frow], %[frow], 16 \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp5], $ac3 \n\t" + "lw %[temp8], 0(%[irow]) \n\t" + "lw %[temp9], 4(%[irow]) \n\t" + "lw %[temp10], 8(%[irow]) \n\t" + "lw %[temp11], 12(%[irow]) \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "addiu %[irow], %[irow], 16 \n\t" + "subu %[temp8], %[temp8], %[temp0] \n\t" + "subu %[temp9], %[temp9], %[temp1] \n\t" + "subu %[temp10], %[temp10], %[temp2] \n\t" + "subu %[temp11], %[temp11], %[temp5] \n\t" + "mult $ac0, %[temp3], %[temp4] \n\t" + "maddu $ac0, %[temp8], %[temp7] \n\t" + "mult $ac1, %[temp3], %[temp4] \n\t" + "maddu $ac1, %[temp9], %[temp7] \n\t" + "mult $ac2, %[temp3], %[temp4] \n\t" + "maddu $ac2, %[temp10], %[temp7] \n\t" + "mult $ac3, %[temp3], %[temp4] \n\t" + "maddu $ac3, %[temp11], %[temp7] \n\t" + "mfhi %[temp8], $ac0 \n\t" + "mfhi %[temp9], $ac1 \n\t" + "mfhi %[temp10], $ac2 \n\t" + "mfhi %[temp11], $ac3 \n\t" + "sw %[temp0], -16(%[irow]) \n\t" + "sw %[temp1], -12(%[irow]) \n\t" + "sw %[temp2], -8(%[irow]) \n\t" + "sw %[temp5], -4(%[irow]) \n\t" + "sb %[temp8], -4(%[dst]) \n\t" + "sb %[temp9], -3(%[dst]) \n\t" + "sb %[temp10], -2(%[dst]) \n\t" + "sb %[temp11], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end), + [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), + [temp11]"=&r"(temp11), [temp2]"=&r"(temp2) + : [temp7]"r"(temp7), [yscale]"r"(yscale), [temp6]"r"(temp6) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", + "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" + ); + } + for (i = 0; i < (x_out_max & 0x3); ++i) { + const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(*frow++, yscale); + const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale); + *dst++ = (v > 255) ? 255u : (uint8_t)v; + *irow++ = frac; // new fractional start + } + } else { + if (x_out_max >= 4) { + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[irow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[irow]) \n\t" + "lw %[temp1], 4(%[irow]) \n\t" + "lw %[temp2], 8(%[irow]) \n\t" + "lw %[temp5], 12(%[irow]) \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "addiu %[irow], %[irow], 16 \n\t" + "mult $ac0, %[temp3], %[temp4] \n\t" + "maddu $ac0, %[temp0], %[temp7] \n\t" + "mult $ac1, %[temp3], %[temp4] \n\t" + "maddu $ac1, %[temp1], %[temp7] \n\t" + "mult $ac2, %[temp3], %[temp4] \n\t" + "maddu $ac2, %[temp2], %[temp7] \n\t" + "mult $ac3, %[temp3], %[temp4] \n\t" + "maddu $ac3, %[temp5], %[temp7] \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp5], $ac3 \n\t" + "sw $zero, -16(%[irow]) \n\t" + "sw $zero, -12(%[irow]) \n\t" + "sw $zero, -8(%[irow]) \n\t" + "sw $zero, -4(%[irow]) \n\t" + "sb %[temp0], -4(%[dst]) \n\t" + "sb %[temp1], -3(%[dst]) \n\t" + "sb %[temp2], -2(%[dst]) \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[irow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow), + [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2) + : [temp7]"r"(temp7), [temp6]"r"(temp6) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", + "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" + ); + } + for (i = 0; i < (x_out_max & 0x3); ++i) { + const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale); + *dst++ = (v > 255) ? 255u : (uint8_t)v; + *irow++ = 0; + } + } +} +#endif // 0 + +static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) { + int i; + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* frow = wrk->frow; + int temp0, temp1, temp2, temp3, temp4, temp5, loop_end; + const int temp6 = (x_out_max & ~0x3) << 2; + const int temp7 = (int)wrk->fy_scale; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + if (x_out_max >= 4) { + __asm__ volatile ( + "li %[temp4], 0x10000 \n\t" + "li %[temp5], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "lw %[temp1], 4(%[frow]) \n\t" + "lw %[temp2], 8(%[frow]) \n\t" + "lw %[temp3], 12(%[frow]) \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "addiu %[frow], %[frow], 16 \n\t" + "mult $ac0, %[temp4], %[temp5] \n\t" + "maddu $ac0, %[temp0], %[temp7] \n\t" + "mult $ac1, %[temp4], %[temp5] \n\t" + "maddu $ac1, %[temp1], %[temp7] \n\t" + "mult $ac2, %[temp4], %[temp5] \n\t" + "maddu $ac2, %[temp2], %[temp7] \n\t" + "mult $ac3, %[temp4], %[temp5] \n\t" + "maddu $ac3, %[temp3], %[temp7] \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp3], $ac3 \n\t" + "sb %[temp0], -4(%[dst]) \n\t" + "sb %[temp1], -3(%[dst]) \n\t" + "sb %[temp2], -2(%[dst]) \n\t" + "sb %[temp3], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2) + : [temp7]"r"(temp7), [temp6]"r"(temp6) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", + "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" + ); + } + for (i = 0; i < (x_out_max & 0x3); ++i) { + const uint32_t J = *frow++; + const int v = (int)MULT_FIX(J, wrk->fy_scale); + *dst++ = (v > 255) ? 255u : (uint8_t)v; + } + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + if (x_out_max >= 4) { + int temp8, temp9, temp10, temp11; + __asm__ volatile ( + "li %[temp8], 0x10000 \n\t" + "li %[temp9], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "lw %[temp1], 4(%[frow]) \n\t" + "lw %[temp2], 8(%[frow]) \n\t" + "lw %[temp3], 12(%[frow]) \n\t" + "lw %[temp4], 0(%[irow]) \n\t" + "lw %[temp5], 4(%[irow]) \n\t" + "lw %[temp10], 8(%[irow]) \n\t" + "lw %[temp11], 12(%[irow]) \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "mult $ac0, %[temp8], %[temp9] \n\t" + "maddu $ac0, %[A], %[temp0] \n\t" + "maddu $ac0, %[B], %[temp4] \n\t" + "mult $ac1, %[temp8], %[temp9] \n\t" + "maddu $ac1, %[A], %[temp1] \n\t" + "maddu $ac1, %[B], %[temp5] \n\t" + "mult $ac2, %[temp8], %[temp9] \n\t" + "maddu $ac2, %[A], %[temp2] \n\t" + "maddu $ac2, %[B], %[temp10] \n\t" + "mult $ac3, %[temp8], %[temp9] \n\t" + "maddu $ac3, %[A], %[temp3] \n\t" + "maddu $ac3, %[B], %[temp11] \n\t" + "addiu %[frow], %[frow], 16 \n\t" + "addiu %[irow], %[irow], 16 \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp3], $ac3 \n\t" + "mult $ac0, %[temp8], %[temp9] \n\t" + "maddu $ac0, %[temp0], %[temp7] \n\t" + "mult $ac1, %[temp8], %[temp9] \n\t" + "maddu $ac1, %[temp1], %[temp7] \n\t" + "mult $ac2, %[temp8], %[temp9] \n\t" + "maddu $ac2, %[temp2], %[temp7] \n\t" + "mult $ac3, %[temp8], %[temp9] \n\t" + "maddu $ac3, %[temp3], %[temp7] \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp3], $ac3 \n\t" + "sb %[temp0], -4(%[dst]) \n\t" + "sb %[temp1], -3(%[dst]) \n\t" + "sb %[temp2], -2(%[dst]) \n\t" + "sb %[temp3], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end), + [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), + [temp11]"=&r"(temp11), [temp2]"=&r"(temp2) + : [temp7]"r"(temp7), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", + "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" + ); + } + for (i = 0; i < (x_out_max & 0x3); ++i) { + const uint64_t I = (uint64_t)A * *frow++ + + (uint64_t)B * *irow++; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX(J, wrk->fy_scale); + *dst++ = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPRescalerDspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) { + WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2; +// WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/rescaler_msa.c b/libraries/webp/src/dsp/rescaler_msa.c new file mode 100644 index 0000000000..256dbdd437 --- /dev/null +++ b/libraries/webp/src/dsp/rescaler_msa.c @@ -0,0 +1,443 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA version of rescaling functions +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) && !defined(WEBP_REDUCE_SIZE) + +#include + +#include "src/utils/rescaler_utils.h" +#include "src/dsp/msa_macro.h" + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \ + v4u32 tmp0, tmp1, tmp2, tmp3; \ + v16u8 t0, t1, t2, t3, t4, t5; \ + v2u64 out0, out1, out2, out3; \ + ILVRL_W2_UW(zero, in0, tmp0, tmp1); \ + ILVRL_W2_UW(zero, in1, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, scale, scale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_B2_UB(out1, out0, out3, out2, t0, t1); \ + ILVRL_W2_UW(zero, in2, tmp0, tmp1); \ + ILVRL_W2_UW(zero, in3, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, scale, scale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_B2_UB(out1, out0, out3, out2, t2, t3); \ + PCKEV_B2_UB(t1, t0, t3, t2, t4, t5); \ + dst = (v16u8)__msa_pckev_b((v16i8)t5, (v16i8)t4); \ +} while (0) + +#define CALC_MULT_FIX_4(in0, scale, shift, dst) do { \ + v4u32 tmp0, tmp1; \ + v16i8 t0, t1; \ + v2u64 out0, out1; \ + ILVRL_W2_UW(zero, in0, tmp0, tmp1); \ + DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \ + SRAR_D2_UD(out0, out1, shift); \ + t0 = __msa_pckev_b((v16i8)out1, (v16i8)out0); \ + t1 = __msa_pckev_b(t0, t0); \ + t0 = __msa_pckev_b(t1, t1); \ + dst = __msa_copy_s_w((v4i32)t0, 0); \ +} while (0) + +#define CALC_MULT_FIX1_16(in0, in1, in2, in3, fyscale, shift, \ + dst0, dst1, dst2, dst3) do { \ + v4u32 tmp0, tmp1, tmp2, tmp3; \ + v2u64 out0, out1, out2, out3; \ + ILVRL_W2_UW(zero, in0, tmp0, tmp1); \ + ILVRL_W2_UW(zero, in1, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, fyscale, fyscale, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, fyscale, fyscale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_W2_UW(out1, out0, out3, out2, dst0, dst1); \ + ILVRL_W2_UW(zero, in2, tmp0, tmp1); \ + ILVRL_W2_UW(zero, in3, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, fyscale, fyscale, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, fyscale, fyscale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_W2_UW(out1, out0, out3, out2, dst2, dst3); \ +} while (0) + +#define CALC_MULT_FIX1_4(in0, scale, shift, dst) do { \ + v4u32 tmp0, tmp1; \ + v2u64 out0, out1; \ + ILVRL_W2_UW(zero, in0, tmp0, tmp1); \ + DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \ + SRAR_D2_UD(out0, out1, shift); \ + dst = (v4u32)__msa_pckev_w((v4i32)out1, (v4i32)out0); \ +} while (0) + +#define CALC_MULT_FIX2_16(in0, in1, in2, in3, mult, scale, shift, \ + dst0, dst1) do { \ + v4u32 tmp0, tmp1, tmp2, tmp3; \ + v2u64 out0, out1, out2, out3; \ + ILVRL_W2_UW(in0, in2, tmp0, tmp1); \ + ILVRL_W2_UW(in1, in3, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, mult, mult, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, mult, mult, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + DOTP_UW2_UD(out0, out1, scale, scale, out0, out1); \ + DOTP_UW2_UD(out2, out3, scale, scale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_B2_UB(out1, out0, out3, out2, dst0, dst1); \ +} while (0) + +#define CALC_MULT_FIX2_4(in0, in1, mult, scale, shift, dst) do { \ + v4u32 tmp0, tmp1; \ + v2u64 out0, out1; \ + v16i8 t0, t1; \ + ILVRL_W2_UW(in0, in1, tmp0, tmp1); \ + DOTP_UW2_UD(tmp0, tmp1, mult, mult, out0, out1); \ + SRAR_D2_UD(out0, out1, shift); \ + DOTP_UW2_UD(out0, out1, scale, scale, out0, out1); \ + SRAR_D2_UD(out0, out1, shift); \ + t0 = __msa_pckev_b((v16i8)out1, (v16i8)out0); \ + t1 = __msa_pckev_b(t0, t0); \ + t0 = __msa_pckev_b(t1, t1); \ + dst = __msa_copy_s_w((v4i32)t0, 0); \ +} while (0) + +static WEBP_INLINE void ExportRowExpand_0(const uint32_t* frow, uint8_t* dst, + int length, + WebPRescaler* const wrk) { + const v4u32 scale = (v4u32)__msa_fill_w(wrk->fy_scale); + const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX); + const v4i32 zero = { 0 }; + + while (length >= 16) { + v4u32 src0, src1, src2, src3; + v16u8 out; + LD_UW4(frow, 4, src0, src1, src2, src3); + CALC_MULT_FIX_16(src0, src1, src2, src3, scale, shift, out); + ST_UB(out, dst); + length -= 16; + frow += 16; + dst += 16; + } + if (length > 0) { + int x_out; + if (length >= 12) { + uint32_t val0_m, val1_m, val2_m; + v4u32 src0, src1, src2; + LD_UW3(frow, 4, src0, src1, src2); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + CALC_MULT_FIX_4(src1, scale, shift, val1_m); + CALC_MULT_FIX_4(src2, scale, shift, val2_m); + SW3(val0_m, val1_m, val2_m, dst, 4); + length -= 12; + frow += 12; + dst += 12; + } else if (length >= 8) { + uint32_t val0_m, val1_m; + v4u32 src0, src1; + LD_UW2(frow, 4, src0, src1); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + CALC_MULT_FIX_4(src1, scale, shift, val1_m); + SW2(val0_m, val1_m, dst, 4); + length -= 8; + frow += 8; + dst += 8; + } else if (length >= 4) { + uint32_t val0_m; + const v4u32 src0 = LD_UW(frow); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + SW(val0_m, dst); + length -= 4; + frow += 4; + dst += 4; + } + for (x_out = 0; x_out < length; ++x_out) { + const uint32_t J = frow[x_out]; + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +static WEBP_INLINE void ExportRowExpand_1(const uint32_t* frow, uint32_t* irow, + uint8_t* dst, int length, + WebPRescaler* const wrk) { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + const v4i32 B1 = __msa_fill_w(B); + const v4i32 A1 = __msa_fill_w(A); + const v4i32 AB = __msa_ilvr_w(A1, B1); + const v4u32 scale = (v4u32)__msa_fill_w(wrk->fy_scale); + const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX); + + while (length >= 16) { + v4u32 frow0, frow1, frow2, frow3, irow0, irow1, irow2, irow3; + v16u8 t0, t1, t2, t3, t4, t5; + LD_UW4(frow, 4, frow0, frow1, frow2, frow3); + LD_UW4(irow, 4, irow0, irow1, irow2, irow3); + CALC_MULT_FIX2_16(frow0, frow1, irow0, irow1, AB, scale, shift, t0, t1); + CALC_MULT_FIX2_16(frow2, frow3, irow2, irow3, AB, scale, shift, t2, t3); + PCKEV_B2_UB(t1, t0, t3, t2, t4, t5); + t0 = (v16u8)__msa_pckev_b((v16i8)t5, (v16i8)t4); + ST_UB(t0, dst); + frow += 16; + irow += 16; + dst += 16; + length -= 16; + } + if (length > 0) { + int x_out; + if (length >= 12) { + uint32_t val0_m, val1_m, val2_m; + v4u32 frow0, frow1, frow2, irow0, irow1, irow2; + LD_UW3(frow, 4, frow0, frow1, frow2); + LD_UW3(irow, 4, irow0, irow1, irow2); + CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m); + CALC_MULT_FIX2_4(frow1, irow1, AB, scale, shift, val1_m); + CALC_MULT_FIX2_4(frow2, irow2, AB, scale, shift, val2_m); + SW3(val0_m, val1_m, val2_m, dst, 4); + frow += 12; + irow += 12; + dst += 12; + length -= 12; + } else if (length >= 8) { + uint32_t val0_m, val1_m; + v4u32 frow0, frow1, irow0, irow1; + LD_UW2(frow, 4, frow0, frow1); + LD_UW2(irow, 4, irow0, irow1); + CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m); + CALC_MULT_FIX2_4(frow1, irow1, AB, scale, shift, val1_m); + SW2(val0_m, val1_m, dst, 4); + frow += 4; + irow += 4; + dst += 4; + length -= 4; + } else if (length >= 4) { + uint32_t val0_m; + const v4u32 frow0 = LD_UW(frow + 0); + const v4u32 irow0 = LD_UW(irow + 0); + CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m); + SW(val0_m, dst); + frow += 4; + irow += 4; + dst += 4; + length -= 4; + } + for (x_out = 0; x_out < length; ++x_out) { + const uint64_t I = (uint64_t)A * frow[x_out] + + (uint64_t)B * irow[x_out]; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) { + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* frow = wrk->frow; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + ExportRowExpand_0(frow, dst, x_out_max, wrk); + } else { + ExportRowExpand_1(frow, irow, dst, x_out_max, wrk); + } +} + +#if 0 // disabled for now. TODO(skal): make match the C-code +static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow, + uint8_t* dst, int length, + const uint32_t yscale, + WebPRescaler* const wrk) { + const v4u32 y_scale = (v4u32)__msa_fill_w(yscale); + const v4u32 fxyscale = (v4u32)__msa_fill_w(wrk->fxy_scale); + const v4u32 shiftval = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX); + const v4i32 zero = { 0 }; + + while (length >= 16) { + v4u32 src0, src1, src2, src3, frac0, frac1, frac2, frac3; + v16u8 out; + LD_UW4(frow, 4, src0, src1, src2, src3); + CALC_MULT_FIX1_16(src0, src1, src2, src3, y_scale, shiftval, + frac0, frac1, frac2, frac3); + LD_UW4(irow, 4, src0, src1, src2, src3); + SUB4(src0, frac0, src1, frac1, src2, frac2, src3, frac3, + src0, src1, src2, src3); + CALC_MULT_FIX_16(src0, src1, src2, src3, fxyscale, shiftval, out); + ST_UB(out, dst); + ST_UW4(frac0, frac1, frac2, frac3, irow, 4); + frow += 16; + irow += 16; + dst += 16; + length -= 16; + } + if (length > 0) { + int x_out; + if (length >= 12) { + uint32_t val0_m, val1_m, val2_m; + v4u32 src0, src1, src2, frac0, frac1, frac2; + LD_UW3(frow, 4, src0, src1, src2); + CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0); + CALC_MULT_FIX1_4(src1, y_scale, shiftval, frac1); + CALC_MULT_FIX1_4(src2, y_scale, shiftval, frac2); + LD_UW3(irow, 4, src0, src1, src2); + SUB3(src0, frac0, src1, frac1, src2, frac2, src0, src1, src2); + CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m); + CALC_MULT_FIX_4(src1, fxyscale, shiftval, val1_m); + CALC_MULT_FIX_4(src2, fxyscale, shiftval, val2_m); + SW3(val0_m, val1_m, val2_m, dst, 4); + ST_UW3(frac0, frac1, frac2, irow, 4); + frow += 12; + irow += 12; + dst += 12; + length -= 12; + } else if (length >= 8) { + uint32_t val0_m, val1_m; + v4u32 src0, src1, frac0, frac1; + LD_UW2(frow, 4, src0, src1); + CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0); + CALC_MULT_FIX1_4(src1, y_scale, shiftval, frac1); + LD_UW2(irow, 4, src0, src1); + SUB2(src0, frac0, src1, frac1, src0, src1); + CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m); + CALC_MULT_FIX_4(src1, fxyscale, shiftval, val1_m); + SW2(val0_m, val1_m, dst, 4); + ST_UW2(frac0, frac1, irow, 4); + frow += 8; + irow += 8; + dst += 8; + length -= 8; + } else if (length >= 4) { + uint32_t val0_m; + v4u32 frac0; + v4u32 src0 = LD_UW(frow); + CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0); + src0 = LD_UW(irow); + src0 = src0 - frac0; + CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m); + SW(val0_m, dst); + ST_UW(frac0, irow); + frow += 4; + irow += 4; + dst += 4; + length -= 4; + } + for (x_out = 0; x_out < length; ++x_out) { + const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale); + const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = frac; + } + } +} + +static WEBP_INLINE void ExportRowShrink_1(uint32_t* irow, uint8_t* dst, + int length, + WebPRescaler* const wrk) { + const v4u32 scale = (v4u32)__msa_fill_w(wrk->fxy_scale); + const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX); + const v4i32 zero = { 0 }; + + while (length >= 16) { + v4u32 src0, src1, src2, src3; + v16u8 dst0; + LD_UW4(irow, 4, src0, src1, src2, src3); + CALC_MULT_FIX_16(src0, src1, src2, src3, scale, shift, dst0); + ST_UB(dst0, dst); + ST_SW4(zero, zero, zero, zero, irow, 4); + length -= 16; + irow += 16; + dst += 16; + } + if (length > 0) { + int x_out; + if (length >= 12) { + uint32_t val0_m, val1_m, val2_m; + v4u32 src0, src1, src2; + LD_UW3(irow, 4, src0, src1, src2); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + CALC_MULT_FIX_4(src1, scale, shift, val1_m); + CALC_MULT_FIX_4(src2, scale, shift, val2_m); + SW3(val0_m, val1_m, val2_m, dst, 4); + ST_SW3(zero, zero, zero, irow, 4); + length -= 12; + irow += 12; + dst += 12; + } else if (length >= 8) { + uint32_t val0_m, val1_m; + v4u32 src0, src1; + LD_UW2(irow, 4, src0, src1); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + CALC_MULT_FIX_4(src1, scale, shift, val1_m); + SW2(val0_m, val1_m, dst, 4); + ST_SW2(zero, zero, irow, 4); + length -= 8; + irow += 8; + dst += 8; + } else if (length >= 4) { + uint32_t val0_m; + const v4u32 src0 = LD_UW(irow + 0); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + SW(val0_m, dst); + ST_SW(zero, irow); + length -= 4; + irow += 4; + dst += 4; + } + for (x_out = 0; x_out < length; ++x_out) { + const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = 0; + } + } +} + +static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) { + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* frow = wrk->frow; + const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + if (yscale) { + ExportRowShrink_0(frow, irow, dst, x_out_max, yscale, wrk); + } else { + ExportRowShrink_1(irow, dst, x_out_max, wrk); + } +} +#endif // 0 + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPRescalerDspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) { + WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2; +// WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/libraries/webp/src/dsp/rescaler_neon.c b/libraries/webp/src/dsp/rescaler_neon.c new file mode 100644 index 0000000000..957a92dbc9 --- /dev/null +++ b/libraries/webp/src/dsp/rescaler_neon.c @@ -0,0 +1,192 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON version of rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) && !defined(WEBP_REDUCE_SIZE) + +#include +#include +#include "src/dsp/neon.h" +#include "src/utils/rescaler_utils.h" + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC)) +#define LOAD_32x8(SRC, DST0, DST1) \ + LOAD_32x4(SRC + 0, DST0); \ + LOAD_32x4(SRC + 4, DST1) + +#define STORE_32x8(SRC0, SRC1, DST) do { \ + vst1q_u32((DST) + 0, SRC0); \ + vst1q_u32((DST) + 4, SRC1); \ +} while (0) + +#if (WEBP_RESCALER_RFIX == 32) +#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1)) +// note: B is actualy scale>>1. See MAKE_HALF_CST +#define MULT_FIX(A, B) \ + vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) +#define MULT_FIX_FLOOR(A, B) \ + vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) +#else +#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work" +#endif + +static uint32x4_t Interpolate_NEON(const rescaler_t* const frow, + const rescaler_t* const irow, + uint32_t A, uint32_t B) { + LOAD_32x4(frow, A0); + LOAD_32x4(irow, B0); + const uint64x2_t C0 = vmull_n_u32(vget_low_u32(A0), A); + const uint64x2_t C1 = vmull_n_u32(vget_high_u32(A0), A); + const uint64x2_t D0 = vmlal_n_u32(C0, vget_low_u32(B0), B); + const uint64x2_t D1 = vmlal_n_u32(C1, vget_high_u32(B0), B); + const uint32x4_t E = vcombine_u32( + vrshrn_n_u64(D0, WEBP_RESCALER_RFIX), + vrshrn_n_u64(D1, WEBP_RESCALER_RFIX)); + return E; +} + +static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const int max_span = x_out_max & ~7; + const rescaler_t* const frow = wrk->frow; + const uint32_t fy_scale = wrk->fy_scale; + const int32x4_t fy_scale_half = MAKE_HALF_CST(fy_scale); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + for (x_out = 0; x_out < max_span; x_out += 8) { + LOAD_32x4(frow + x_out + 0, A0); + LOAD_32x4(frow + x_out + 4, A1); + const uint32x4_t B0 = MULT_FIX(A0, fy_scale_half); + const uint32x4_t B1 = MULT_FIX(A1, fy_scale_half); + const uint16x4_t C0 = vmovn_u32(B0); + const uint16x4_t C1 = vmovn_u32(B1); + const uint8x8_t D = vqmovn_u16(vcombine_u16(C0, C1)); + vst1_u8(dst + x_out, D); + } + for (; x_out < x_out_max; ++x_out) { + const uint32_t J = frow[x_out]; + const int v = (int)MULT_FIX_C(J, fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + for (x_out = 0; x_out < max_span; x_out += 8) { + const uint32x4_t C0 = + Interpolate_NEON(frow + x_out + 0, irow + x_out + 0, A, B); + const uint32x4_t C1 = + Interpolate_NEON(frow + x_out + 4, irow + x_out + 4, A, B); + const uint32x4_t D0 = MULT_FIX(C0, fy_scale_half); + const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half); + const uint16x4_t E0 = vmovn_u32(D0); + const uint16x4_t E1 = vmovn_u32(D1); + const uint8x8_t F = vqmovn_u16(vcombine_u16(E0, E1)); + vst1_u8(dst + x_out, F); + } + for (; x_out < x_out_max; ++x_out) { + const uint64_t I = (uint64_t)A * frow[x_out] + + (uint64_t)B * irow[x_out]; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX_C(J, fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const int max_span = x_out_max & ~7; + const rescaler_t* const frow = wrk->frow; + const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); + const uint32_t fxy_scale = wrk->fxy_scale; + const uint32x4_t zero = vdupq_n_u32(0); + const int32x4_t yscale_half = MAKE_HALF_CST(yscale); + const int32x4_t fxy_scale_half = MAKE_HALF_CST(fxy_scale); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + if (yscale) { + for (x_out = 0; x_out < max_span; x_out += 8) { + LOAD_32x8(frow + x_out, in0, in1); + LOAD_32x8(irow + x_out, in2, in3); + const uint32x4_t A0 = MULT_FIX_FLOOR(in0, yscale_half); + const uint32x4_t A1 = MULT_FIX_FLOOR(in1, yscale_half); + const uint32x4_t B0 = vqsubq_u32(in2, A0); + const uint32x4_t B1 = vqsubq_u32(in3, A1); + const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half); + const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half); + const uint16x4_t D0 = vmovn_u32(C0); + const uint16x4_t D1 = vmovn_u32(C1); + const uint8x8_t E = vqmovn_u16(vcombine_u16(D0, D1)); + vst1_u8(dst + x_out, E); + STORE_32x8(A0, A1, irow + x_out); + } + for (; x_out < x_out_max; ++x_out) { + const uint32_t frac = (uint32_t)MULT_FIX_FLOOR_C(frow[x_out], yscale); + const int v = (int)MULT_FIX_C(irow[x_out] - frac, fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = frac; // new fractional start + } + } else { + for (x_out = 0; x_out < max_span; x_out += 8) { + LOAD_32x8(irow + x_out, in0, in1); + const uint32x4_t A0 = MULT_FIX(in0, fxy_scale_half); + const uint32x4_t A1 = MULT_FIX(in1, fxy_scale_half); + const uint16x4_t B0 = vmovn_u32(A0); + const uint16x4_t B1 = vmovn_u32(A1); + const uint8x8_t C = vqmovn_u16(vcombine_u16(B0, B1)); + vst1_u8(dst + x_out, C); + STORE_32x8(zero, zero, irow + x_out); + } + for (; x_out < x_out_max; ++x_out) { + const int v = (int)MULT_FIX_C(irow[x_out], fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = 0; + } + } +} + +#undef MULT_FIX_FLOOR_C +#undef MULT_FIX_C +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + +//------------------------------------------------------------------------------ + +extern void WebPRescalerDspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitNEON(void) { + WebPRescalerExportRowExpand = RescalerExportRowExpand_NEON; + WebPRescalerExportRowShrink = RescalerExportRowShrink_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/rescaler_sse2.c b/libraries/webp/src/dsp/rescaler_sse2.c new file mode 100644 index 0000000000..3f18e94e93 --- /dev/null +++ b/libraries/webp/src/dsp/rescaler_sse2.c @@ -0,0 +1,366 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) && !defined(WEBP_REDUCE_SIZE) +#include + +#include +#include "src/utils/rescaler_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Implementations of critical functions ImportRow / ExportRow + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0 +static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) { + const __m128i zero = _mm_setzero_si128(); + const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH + const __m128i B = _mm_unpacklo_epi8(A, zero); // A0B0C0D0E0F0G0H0 + const __m128i C = _mm_srli_si128(B, 8); // E0F0G0H0 + *out = _mm_unpacklo_epi16(B, C); +} + +// input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0 +static void LoadEightPixels_SSE2(const uint8_t* const src, __m128i* out) { + const __m128i zero = _mm_setzero_si128(); + const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH + *out = _mm_unpacklo_epi8(A, zero); +} + +static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk, + const uint8_t* src) { + rescaler_t* frow = wrk->frow; + const rescaler_t* const frow_end = frow + wrk->dst_width * wrk->num_channels; + const int x_add = wrk->x_add; + int accum = x_add; + __m128i cur_pixels; + + // SSE2 implementation only works with 16b signed arithmetic at max. + if (wrk->src_width < 8 || accum >= (1 << 15)) { + WebPRescalerImportRowExpand_C(wrk, src); + return; + } + + assert(!WebPRescalerInputDone(wrk)); + assert(wrk->x_expand); + if (wrk->num_channels == 4) { + LoadTwoPixels_SSE2(src, &cur_pixels); + src += 4; + while (1) { + const __m128i mult = _mm_set1_epi32(((x_add - accum) << 16) | accum); + const __m128i out = _mm_madd_epi16(cur_pixels, mult); + _mm_storeu_si128((__m128i*)frow, out); + frow += 4; + if (frow >= frow_end) break; + accum -= wrk->x_sub; + if (accum < 0) { + LoadTwoPixels_SSE2(src, &cur_pixels); + src += 4; + accum += x_add; + } + } + } else { + int left; + const uint8_t* const src_limit = src + wrk->src_width - 8; + LoadEightPixels_SSE2(src, &cur_pixels); + src += 7; + left = 7; + while (1) { + const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum); + const __m128i out = _mm_madd_epi16(cur_pixels, mult); + assert(sizeof(*frow) == sizeof(uint32_t)); + WebPInt32ToMem((uint8_t*)frow, _mm_cvtsi128_si32(out)); + frow += 1; + if (frow >= frow_end) break; + accum -= wrk->x_sub; + if (accum < 0) { + if (--left) { + cur_pixels = _mm_srli_si128(cur_pixels, 2); + } else if (src <= src_limit) { + LoadEightPixels_SSE2(src, &cur_pixels); + src += 7; + left = 7; + } else { // tail + cur_pixels = _mm_srli_si128(cur_pixels, 2); + cur_pixels = _mm_insert_epi16(cur_pixels, src[1], 1); + src += 1; + left = 1; + } + accum += x_add; + } + } + } + assert(accum == 0); +} + +static void RescalerImportRowShrink_SSE2(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_sub = wrk->x_sub; + int accum = 0; + const __m128i zero = _mm_setzero_si128(); + const __m128i mult0 = _mm_set1_epi16(x_sub); + const __m128i mult1 = _mm_set1_epi32(wrk->fx_scale); + const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); + __m128i sum = zero; + rescaler_t* frow = wrk->frow; + const rescaler_t* const frow_end = wrk->frow + 4 * wrk->dst_width; + + if (wrk->num_channels != 4 || wrk->x_add > (x_sub << 7)) { + WebPRescalerImportRowShrink_C(wrk, src); + return; + } + assert(!WebPRescalerInputDone(wrk)); + assert(!wrk->x_expand); + + for (; frow < frow_end; frow += 4) { + __m128i base = zero; + accum += wrk->x_add; + while (accum > 0) { + const __m128i A = _mm_cvtsi32_si128(WebPMemToInt32(src)); + src += 4; + base = _mm_unpacklo_epi8(A, zero); + // To avoid overflow, we need: base * x_add / x_sub < 32768 + // => x_add < x_sub << 7. That's a 1/128 reduction ratio limit. + sum = _mm_add_epi16(sum, base); + accum -= x_sub; + } + { // Emit next horizontal pixel. + const __m128i mult = _mm_set1_epi16(-accum); + const __m128i frac0 = _mm_mullo_epi16(base, mult); // 16b x 16b -> 32b + const __m128i frac1 = _mm_mulhi_epu16(base, mult); + const __m128i frac = _mm_unpacklo_epi16(frac0, frac1); // frac is 32b + const __m128i A0 = _mm_mullo_epi16(sum, mult0); + const __m128i A1 = _mm_mulhi_epu16(sum, mult0); + const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // sum * x_sub + const __m128i frow_out = _mm_sub_epi32(B0, frac); // sum * x_sub - frac + const __m128i D0 = _mm_srli_epi64(frac, 32); + const __m128i D1 = _mm_mul_epu32(frac, mult1); // 32b x 16b -> 64b + const __m128i D2 = _mm_mul_epu32(D0, mult1); + const __m128i E1 = _mm_add_epi64(D1, rounder); + const __m128i E2 = _mm_add_epi64(D2, rounder); + const __m128i F1 = _mm_shuffle_epi32(E1, 1 | (3 << 2)); + const __m128i F2 = _mm_shuffle_epi32(E2, 1 | (3 << 2)); + const __m128i G = _mm_unpacklo_epi32(F1, F2); + sum = _mm_packs_epi32(G, zero); + _mm_storeu_si128((__m128i*)frow, frow_out); + } + } + assert(accum == 0); +} + +//------------------------------------------------------------------------------ +// Row export + +// load *src as epi64, multiply by mult and store result in [out0 ... out3] +static WEBP_INLINE void LoadDispatchAndMult_SSE2(const rescaler_t* const src, + const __m128i* const mult, + __m128i* const out0, + __m128i* const out1, + __m128i* const out2, + __m128i* const out3) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + 0)); + const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + 4)); + const __m128i A2 = _mm_srli_epi64(A0, 32); + const __m128i A3 = _mm_srli_epi64(A1, 32); + if (mult != NULL) { + *out0 = _mm_mul_epu32(A0, *mult); + *out1 = _mm_mul_epu32(A1, *mult); + *out2 = _mm_mul_epu32(A2, *mult); + *out3 = _mm_mul_epu32(A3, *mult); + } else { + *out0 = A0; + *out1 = A1; + *out2 = A2; + *out3 = A3; + } +} + +static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0, + const __m128i* const A1, + const __m128i* const A2, + const __m128i* const A3, + const __m128i* const mult, + uint8_t* const dst) { + const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); + const __m128i mask = _mm_set_epi32(~0, 0, ~0, 0); + const __m128i B0 = _mm_mul_epu32(*A0, *mult); + const __m128i B1 = _mm_mul_epu32(*A1, *mult); + const __m128i B2 = _mm_mul_epu32(*A2, *mult); + const __m128i B3 = _mm_mul_epu32(*A3, *mult); + const __m128i C0 = _mm_add_epi64(B0, rounder); + const __m128i C1 = _mm_add_epi64(B1, rounder); + const __m128i C2 = _mm_add_epi64(B2, rounder); + const __m128i C3 = _mm_add_epi64(B3, rounder); + const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); + const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX); +#if (WEBP_RESCALER_RFIX < 32) + const __m128i D2 = + _mm_and_si128(_mm_slli_epi64(C2, 32 - WEBP_RESCALER_RFIX), mask); + const __m128i D3 = + _mm_and_si128(_mm_slli_epi64(C3, 32 - WEBP_RESCALER_RFIX), mask); +#else + const __m128i D2 = _mm_and_si128(C2, mask); + const __m128i D3 = _mm_and_si128(C3, mask); +#endif + const __m128i E0 = _mm_or_si128(D0, D2); + const __m128i E1 = _mm_or_si128(D1, D3); + const __m128i F = _mm_packs_epi32(E0, E1); + const __m128i G = _mm_packus_epi16(F, F); + _mm_storel_epi64((__m128i*)dst, G); +} + +static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* const frow = wrk->frow; + const __m128i mult = _mm_set_epi32(0, wrk->fy_scale, 0, wrk->fy_scale); + + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0 && wrk->y_sub + wrk->y_accum >= 0); + assert(wrk->y_expand); + if (wrk->y_accum == 0) { + for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { + __m128i A0, A1, A2, A3; + LoadDispatchAndMult_SSE2(frow + x_out, NULL, &A0, &A1, &A2, &A3); + ProcessRow_SSE2(&A0, &A1, &A2, &A3, &mult, dst + x_out); + } + for (; x_out < x_out_max; ++x_out) { + const uint32_t J = frow[x_out]; + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + const __m128i mA = _mm_set_epi32(0, A, 0, A); + const __m128i mB = _mm_set_epi32(0, B, 0, B); + const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); + for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { + __m128i A0, A1, A2, A3, B0, B1, B2, B3; + LoadDispatchAndMult_SSE2(frow + x_out, &mA, &A0, &A1, &A2, &A3); + LoadDispatchAndMult_SSE2(irow + x_out, &mB, &B0, &B1, &B2, &B3); + { + const __m128i C0 = _mm_add_epi64(A0, B0); + const __m128i C1 = _mm_add_epi64(A1, B1); + const __m128i C2 = _mm_add_epi64(A2, B2); + const __m128i C3 = _mm_add_epi64(A3, B3); + const __m128i D0 = _mm_add_epi64(C0, rounder); + const __m128i D1 = _mm_add_epi64(C1, rounder); + const __m128i D2 = _mm_add_epi64(C2, rounder); + const __m128i D3 = _mm_add_epi64(C3, rounder); + const __m128i E0 = _mm_srli_epi64(D0, WEBP_RESCALER_RFIX); + const __m128i E1 = _mm_srli_epi64(D1, WEBP_RESCALER_RFIX); + const __m128i E2 = _mm_srli_epi64(D2, WEBP_RESCALER_RFIX); + const __m128i E3 = _mm_srli_epi64(D3, WEBP_RESCALER_RFIX); + ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult, dst + x_out); + } + } + for (; x_out < x_out_max; ++x_out) { + const uint64_t I = (uint64_t)A * frow[x_out] + + (uint64_t)B * irow[x_out]; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* const frow = wrk->frow; + const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + if (yscale) { + const int scale_xy = wrk->fxy_scale; + const __m128i mult_xy = _mm_set_epi32(0, scale_xy, 0, scale_xy); + const __m128i mult_y = _mm_set_epi32(0, yscale, 0, yscale); + for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { + __m128i A0, A1, A2, A3, B0, B1, B2, B3; + LoadDispatchAndMult_SSE2(irow + x_out, NULL, &A0, &A1, &A2, &A3); + LoadDispatchAndMult_SSE2(frow + x_out, &mult_y, &B0, &B1, &B2, &B3); + { + const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX); // = frac + const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX); + const __m128i D2 = _mm_srli_epi64(B2, WEBP_RESCALER_RFIX); + const __m128i D3 = _mm_srli_epi64(B3, WEBP_RESCALER_RFIX); + const __m128i E0 = _mm_sub_epi64(A0, D0); // irow[x] - frac + const __m128i E1 = _mm_sub_epi64(A1, D1); + const __m128i E2 = _mm_sub_epi64(A2, D2); + const __m128i E3 = _mm_sub_epi64(A3, D3); + const __m128i F2 = _mm_slli_epi64(D2, 32); + const __m128i F3 = _mm_slli_epi64(D3, 32); + const __m128i G0 = _mm_or_si128(D0, F2); + const __m128i G1 = _mm_or_si128(D1, F3); + _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0); + _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1); + ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); + } + } + for (; x_out < x_out_max; ++x_out) { + const uint32_t frac = (int)MULT_FIX_FLOOR(frow[x_out], yscale); + const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = frac; // new fractional start + } + } else { + const uint32_t scale = wrk->fxy_scale; + const __m128i mult = _mm_set_epi32(0, scale, 0, scale); + const __m128i zero = _mm_setzero_si128(); + for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { + __m128i A0, A1, A2, A3; + LoadDispatchAndMult_SSE2(irow + x_out, NULL, &A0, &A1, &A2, &A3); + _mm_storeu_si128((__m128i*)(irow + x_out + 0), zero); + _mm_storeu_si128((__m128i*)(irow + x_out + 4), zero); + ProcessRow_SSE2(&A0, &A1, &A2, &A3, &mult, dst + x_out); + } + for (; x_out < x_out_max; ++x_out) { + const int v = (int)MULT_FIX(irow[x_out], scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = 0; + } + } +} + +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + +//------------------------------------------------------------------------------ + +extern void WebPRescalerDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitSSE2(void) { + WebPRescalerImportRowExpand = RescalerImportRowExpand_SSE2; + WebPRescalerImportRowShrink = RescalerImportRowShrink_SSE2; + WebPRescalerExportRowExpand = RescalerExportRowExpand_SSE2; + WebPRescalerExportRowShrink = RescalerExportRowShrink_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/ssim.c b/libraries/webp/src/dsp/ssim.c new file mode 100644 index 0000000000..9a1341ed95 --- /dev/null +++ b/libraries/webp/src/dsp/ssim.c @@ -0,0 +1,160 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// distortion calculation +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include // for abs() + +#include "src/dsp/dsp.h" + +#if !defined(WEBP_REDUCE_SIZE) + +//------------------------------------------------------------------------------ +// SSIM / PSNR + +// hat-shaped filter. Sum of coefficients is equal to 16. +static const uint32_t kWeight[2 * VP8_SSIM_KERNEL + 1] = { + 1, 2, 3, 4, 3, 2, 1 +}; +static const uint32_t kWeightSum = 16 * 16; // sum{kWeight}^2 + +static WEBP_INLINE double SSIMCalculation( + const VP8DistoStats* const stats, uint32_t N /*num samples*/) { + const uint32_t w2 = N * N; + const uint32_t C1 = 20 * w2; + const uint32_t C2 = 60 * w2; + const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6 + const uint64_t xmxm = (uint64_t)stats->xm * stats->xm; + const uint64_t ymym = (uint64_t)stats->ym * stats->ym; + if (xmxm + ymym >= C3) { + const int64_t xmym = (int64_t)stats->xm * stats->ym; + const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative + const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm; + const uint64_t syy = (uint64_t)stats->yym * N - ymym; + // we descale by 8 to prevent overflow during the fnum/fden multiply. + const uint64_t num_S = (2 * (uint64_t)(sxy < 0 ? 0 : sxy) + C2) >> 8; + const uint64_t den_S = (sxx + syy + C2) >> 8; + const uint64_t fnum = (2 * xmym + C1) * num_S; + const uint64_t fden = (xmxm + ymym + C1) * den_S; + const double r = (double)fnum / fden; + assert(r >= 0. && r <= 1.0); + return r; + } + return 1.; // area is too dark to contribute meaningfully +} + +double VP8SSIMFromStats(const VP8DistoStats* const stats) { + return SSIMCalculation(stats, kWeightSum); +} + +double VP8SSIMFromStatsClipped(const VP8DistoStats* const stats) { + return SSIMCalculation(stats, stats->w); +} + +static double SSIMGetClipped_C(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int xo, int yo, int W, int H) { + VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 }; + const int ymin = (yo - VP8_SSIM_KERNEL < 0) ? 0 : yo - VP8_SSIM_KERNEL; + const int ymax = (yo + VP8_SSIM_KERNEL > H - 1) ? H - 1 + : yo + VP8_SSIM_KERNEL; + const int xmin = (xo - VP8_SSIM_KERNEL < 0) ? 0 : xo - VP8_SSIM_KERNEL; + const int xmax = (xo + VP8_SSIM_KERNEL > W - 1) ? W - 1 + : xo + VP8_SSIM_KERNEL; + int x, y; + src1 += ymin * stride1; + src2 += ymin * stride2; + for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { + for (x = xmin; x <= xmax; ++x) { + const uint32_t w = kWeight[VP8_SSIM_KERNEL + x - xo] + * kWeight[VP8_SSIM_KERNEL + y - yo]; + const uint32_t s1 = src1[x]; + const uint32_t s2 = src2[x]; + stats.w += w; + stats.xm += w * s1; + stats.ym += w * s2; + stats.xxm += w * s1 * s1; + stats.xym += w * s1 * s2; + stats.yym += w * s2 * s2; + } + } + return VP8SSIMFromStatsClipped(&stats); +} + +static double SSIMGet_C(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2) { + VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 }; + int x, y; + for (y = 0; y <= 2 * VP8_SSIM_KERNEL; ++y, src1 += stride1, src2 += stride2) { + for (x = 0; x <= 2 * VP8_SSIM_KERNEL; ++x) { + const uint32_t w = kWeight[x] * kWeight[y]; + const uint32_t s1 = src1[x]; + const uint32_t s2 = src2[x]; + stats.xm += w * s1; + stats.ym += w * s2; + stats.xxm += w * s1 * s1; + stats.xym += w * s1 * s2; + stats.yym += w * s2 * s2; + } + } + return VP8SSIMFromStats(&stats); +} + +#endif // !defined(WEBP_REDUCE_SIZE) + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_DISABLE_STATS) +static uint32_t AccumulateSSE_C(const uint8_t* src1, + const uint8_t* src2, int len) { + int i; + uint32_t sse2 = 0; + assert(len <= 65535); // to ensure that accumulation fits within uint32_t + for (i = 0; i < len; ++i) { + const int32_t diff = src1[i] - src2[i]; + sse2 += diff * diff; + } + return sse2; +} +#endif + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_REDUCE_SIZE) +VP8SSIMGetFunc VP8SSIMGet; +VP8SSIMGetClippedFunc VP8SSIMGetClipped; +#endif +#if !defined(WEBP_DISABLE_STATS) +VP8AccumulateSSEFunc VP8AccumulateSSE; +#endif + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8SSIMDspInitSSE2(void); + +WEBP_DSP_INIT_FUNC(VP8SSIMDspInit) { +#if !defined(WEBP_REDUCE_SIZE) + VP8SSIMGetClipped = SSIMGetClipped_C; + VP8SSIMGet = SSIMGet_C; +#endif + +#if !defined(WEBP_DISABLE_STATS) + VP8AccumulateSSE = AccumulateSSE_C; +#endif + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8SSIMDspInitSSE2(); + } +#endif + } +} diff --git a/libraries/webp/src/dsp/ssim_sse2.c b/libraries/webp/src/dsp/ssim_sse2.c new file mode 100644 index 0000000000..1dcb0eb0ec --- /dev/null +++ b/libraries/webp/src/dsp/ssim_sse2.c @@ -0,0 +1,165 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of distortion calculation +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include + +#include "src/dsp/common_sse2.h" + +#if !defined(WEBP_DISABLE_STATS) + +// Helper function +static WEBP_INLINE void SubtractAndSquare_SSE2(const __m128i a, const __m128i b, + __m128i* const sum) { + // take abs(a-b) in 8b + const __m128i a_b = _mm_subs_epu8(a, b); + const __m128i b_a = _mm_subs_epu8(b, a); + const __m128i abs_a_b = _mm_or_si128(a_b, b_a); + // zero-extend to 16b + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero); + const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero); + // multiply with self + const __m128i sum1 = _mm_madd_epi16(C0, C0); + const __m128i sum2 = _mm_madd_epi16(C1, C1); + *sum = _mm_add_epi32(sum1, sum2); +} + +//------------------------------------------------------------------------------ +// SSIM / PSNR entry point + +static uint32_t AccumulateSSE_SSE2(const uint8_t* src1, + const uint8_t* src2, int len) { + int i = 0; + uint32_t sse2 = 0; + if (len >= 16) { + const int limit = len - 32; + int32_t tmp[4]; + __m128i sum1; + __m128i sum = _mm_setzero_si128(); + __m128i a0 = _mm_loadu_si128((const __m128i*)&src1[i]); + __m128i b0 = _mm_loadu_si128((const __m128i*)&src2[i]); + i += 16; + while (i <= limit) { + const __m128i a1 = _mm_loadu_si128((const __m128i*)&src1[i]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&src2[i]); + __m128i sum2; + i += 16; + SubtractAndSquare_SSE2(a0, b0, &sum1); + sum = _mm_add_epi32(sum, sum1); + a0 = _mm_loadu_si128((const __m128i*)&src1[i]); + b0 = _mm_loadu_si128((const __m128i*)&src2[i]); + i += 16; + SubtractAndSquare_SSE2(a1, b1, &sum2); + sum = _mm_add_epi32(sum, sum2); + } + SubtractAndSquare_SSE2(a0, b0, &sum1); + sum = _mm_add_epi32(sum, sum1); + _mm_storeu_si128((__m128i*)tmp, sum); + sse2 += (tmp[3] + tmp[2] + tmp[1] + tmp[0]); + } + + for (; i < len; ++i) { + const int32_t diff = src1[i] - src2[i]; + sse2 += diff * diff; + } + return sse2; +} +#endif // !defined(WEBP_DISABLE_STATS) + +#if !defined(WEBP_REDUCE_SIZE) + +static uint32_t HorizontalAdd16b_SSE2(const __m128i* const m) { + uint16_t tmp[8]; + const __m128i a = _mm_srli_si128(*m, 8); + const __m128i b = _mm_add_epi16(*m, a); + _mm_storeu_si128((__m128i*)tmp, b); + return (uint32_t)tmp[3] + tmp[2] + tmp[1] + tmp[0]; +} + +static uint32_t HorizontalAdd32b_SSE2(const __m128i* const m) { + const __m128i a = _mm_srli_si128(*m, 8); + const __m128i b = _mm_add_epi32(*m, a); + const __m128i c = _mm_add_epi32(b, _mm_srli_si128(b, 4)); + return (uint32_t)_mm_cvtsi128_si32(c); +} + +static const uint16_t kWeight[] = { 1, 2, 3, 4, 3, 2, 1, 0 }; + +#define ACCUMULATE_ROW(WEIGHT) do { \ + /* compute row weight (Wx * Wy) */ \ + const __m128i Wy = _mm_set1_epi16((WEIGHT)); \ + const __m128i W = _mm_mullo_epi16(Wx, Wy); \ + /* process 8 bytes at a time (7 bytes, actually) */ \ + const __m128i a0 = _mm_loadl_epi64((const __m128i*)src1); \ + const __m128i b0 = _mm_loadl_epi64((const __m128i*)src2); \ + /* convert to 16b and multiply by weight */ \ + const __m128i a1 = _mm_unpacklo_epi8(a0, zero); \ + const __m128i b1 = _mm_unpacklo_epi8(b0, zero); \ + const __m128i wa1 = _mm_mullo_epi16(a1, W); \ + const __m128i wb1 = _mm_mullo_epi16(b1, W); \ + /* accumulate */ \ + xm = _mm_add_epi16(xm, wa1); \ + ym = _mm_add_epi16(ym, wb1); \ + xxm = _mm_add_epi32(xxm, _mm_madd_epi16(a1, wa1)); \ + xym = _mm_add_epi32(xym, _mm_madd_epi16(a1, wb1)); \ + yym = _mm_add_epi32(yym, _mm_madd_epi16(b1, wb1)); \ + src1 += stride1; \ + src2 += stride2; \ +} while (0) + +static double SSIMGet_SSE2(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2) { + VP8DistoStats stats; + const __m128i zero = _mm_setzero_si128(); + __m128i xm = zero, ym = zero; // 16b accums + __m128i xxm = zero, yym = zero, xym = zero; // 32b accum + const __m128i Wx = _mm_loadu_si128((const __m128i*)kWeight); + assert(2 * VP8_SSIM_KERNEL + 1 == 7); + ACCUMULATE_ROW(1); + ACCUMULATE_ROW(2); + ACCUMULATE_ROW(3); + ACCUMULATE_ROW(4); + ACCUMULATE_ROW(3); + ACCUMULATE_ROW(2); + ACCUMULATE_ROW(1); + stats.xm = HorizontalAdd16b_SSE2(&xm); + stats.ym = HorizontalAdd16b_SSE2(&ym); + stats.xxm = HorizontalAdd32b_SSE2(&xxm); + stats.xym = HorizontalAdd32b_SSE2(&xym); + stats.yym = HorizontalAdd32b_SSE2(&yym); + return VP8SSIMFromStats(&stats); +} + +#endif // !defined(WEBP_REDUCE_SIZE) + +extern void VP8SSIMDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInitSSE2(void) { +#if !defined(WEBP_DISABLE_STATS) + VP8AccumulateSSE = AccumulateSSE_SSE2; +#endif +#if !defined(WEBP_REDUCE_SIZE) + VP8SSIMGet = SSIMGet_SSE2; +#endif +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8SSIMDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/upsampling.c b/libraries/webp/src/dsp/upsampling.c new file mode 100644 index 0000000000..983b9c42d3 --- /dev/null +++ b/libraries/webp/src/dsp/upsampling.c @@ -0,0 +1,328 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV to RGB upsampling functions. +// +// Author: somnath@google.com (Somnath Banerjee) + +#include "src/dsp/dsp.h" +#include "src/dsp/yuv.h" + +#include + +//------------------------------------------------------------------------------ +// Fancy upsampler + +#ifdef FANCY_UPSAMPLING + +// Fancy upsampling functions to convert YUV to RGB +WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; + +// Given samples laid out in a square as: +// [a b] +// [c d] +// we interpolate u/v as: +// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 +// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 + +// We process u and v together stashed into 32bit (16bit each). +#define LOAD_UV(u, v) ((u) | ((v) << 16)) + +#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int x; \ + const int last_pixel_pair = (len - 1) >> 1; \ + uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ + uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ + assert(top_y != NULL); \ + { \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ + } \ + for (x = 1; x <= last_pixel_pair; ++x) { \ + const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ + const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ + /* precompute invariant values associated with first and second diagonals*/\ + const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ + const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ + const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ + { \ + const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ + const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ + FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ + top_dst + (2 * x - 1) * (XSTEP)); \ + FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ + top_dst + (2 * x - 0) * (XSTEP)); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ + const uint32_t uv1 = (diag_12 + uv) >> 1; \ + FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ + bottom_dst + (2 * x - 1) * (XSTEP)); \ + FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ + bottom_dst + (2 * x + 0) * (XSTEP)); \ + } \ + tl_uv = t_uv; \ + l_uv = uv; \ + } \ + if (!(len & 1)) { \ + { \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ + top_dst + (len - 1) * (XSTEP)); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ + bottom_dst + (len - 1) * (XSTEP)); \ + } \ + } \ +} + +// All variants implemented. +#if !WEBP_NEON_OMIT_C_CODE +UPSAMPLE_FUNC(UpsampleRgbaLinePair_C, VP8YuvToRgba, 4) +UPSAMPLE_FUNC(UpsampleBgraLinePair_C, VP8YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleArgbLinePair_C, VP8YuvToArgb, 4) +UPSAMPLE_FUNC(UpsampleRgbLinePair_C, VP8YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair_C, VP8YuvToBgr, 3) +UPSAMPLE_FUNC(UpsampleRgba4444LinePair_C, VP8YuvToRgba4444, 2) +UPSAMPLE_FUNC(UpsampleRgb565LinePair_C, VP8YuvToRgb565, 2) +#else +static void EmptyUpsampleFunc(const uint8_t* top_y, const uint8_t* bottom_y, + const uint8_t* top_u, const uint8_t* top_v, + const uint8_t* cur_u, const uint8_t* cur_v, + uint8_t* top_dst, uint8_t* bottom_dst, int len) { + (void)top_y; + (void)bottom_y; + (void)top_u; + (void)top_v; + (void)cur_u; + (void)cur_v; + (void)top_dst; + (void)bottom_dst; + (void)len; + assert(0); // COLORSPACE SUPPORT NOT COMPILED +} +#define UpsampleArgbLinePair_C EmptyUpsampleFunc +#define UpsampleRgbLinePair_C EmptyUpsampleFunc +#define UpsampleBgrLinePair_C EmptyUpsampleFunc +#define UpsampleRgba4444LinePair_C EmptyUpsampleFunc +#define UpsampleRgb565LinePair_C EmptyUpsampleFunc +#endif // WEBP_REDUCE_CSP + +#endif + +#undef LOAD_UV +#undef UPSAMPLE_FUNC + +#endif // FANCY_UPSAMPLING + +//------------------------------------------------------------------------------ + +#if !defined(FANCY_UPSAMPLING) +#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* bot_u, const uint8_t* bot_v, \ + uint8_t* top_dst, uint8_t* bot_dst, int len) { \ + const int half_len = len >> 1; \ + int x; \ + assert(top_dst != NULL); \ + { \ + for (x = 0; x < half_len; ++x) { \ + FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ + FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ + } \ + if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ + } \ + if (bot_dst != NULL) { \ + for (x = 0; x < half_len; ++x) { \ + FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ + FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ + } \ + if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \ + } \ +} + +DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra) +DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb) +#undef DUAL_SAMPLE_FUNC + +#endif // !FANCY_UPSAMPLING + +WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) { + WebPInitUpsamplers(); +#ifdef FANCY_UPSAMPLING + return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB]; +#else + return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB); +#endif +} + +//------------------------------------------------------------------------------ +// YUV444 converter + +#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ +extern void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len); \ +void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * (XSTEP)]); \ +} + +YUV444_FUNC(WebPYuv444ToRgba_C, VP8YuvToRgba, 4) +YUV444_FUNC(WebPYuv444ToBgra_C, VP8YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(WebPYuv444ToRgb_C, VP8YuvToRgb, 3) +YUV444_FUNC(WebPYuv444ToBgr_C, VP8YuvToBgr, 3) +YUV444_FUNC(WebPYuv444ToArgb_C, VP8YuvToArgb, 4) +YUV444_FUNC(WebPYuv444ToRgba4444_C, VP8YuvToRgba4444, 2) +YUV444_FUNC(WebPYuv444ToRgb565_C, VP8YuvToRgb565, 2) +#else +static void EmptyYuv444Func(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + (void)y; + (void)u; + (void)v; + (void)dst; + (void)len; +} +#define WebPYuv444ToRgb_C EmptyYuv444Func +#define WebPYuv444ToBgr_C EmptyYuv444Func +#define WebPYuv444ToArgb_C EmptyYuv444Func +#define WebPYuv444ToRgba4444_C EmptyYuv444Func +#define WebPYuv444ToRgb565_C EmptyYuv444Func +#endif // WEBP_REDUCE_CSP + +#undef YUV444_FUNC + +WebPYUV444Converter WebPYUV444Converters[MODE_LAST]; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void WebPInitYUV444ConvertersMIPSdspR2(void); +extern void WebPInitYUV444ConvertersSSE2(void); +extern void WebPInitYUV444ConvertersSSE41(void); + +WEBP_DSP_INIT_FUNC(WebPInitYUV444Converters) { + WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgba_C; + WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgra_C; + WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgb_C; + WebPYUV444Converters[MODE_BGR] = WebPYuv444ToBgr_C; + WebPYUV444Converters[MODE_ARGB] = WebPYuv444ToArgb_C; + WebPYUV444Converters[MODE_RGBA_4444] = WebPYuv444ToRgba4444_C; + WebPYUV444Converters[MODE_RGB_565] = WebPYuv444ToRgb565_C; + WebPYUV444Converters[MODE_rgbA] = WebPYuv444ToRgba_C; + WebPYUV444Converters[MODE_bgrA] = WebPYuv444ToBgra_C; + WebPYUV444Converters[MODE_Argb] = WebPYuv444ToArgb_C; + WebPYUV444Converters[MODE_rgbA_4444] = WebPYuv444ToRgba4444_C; + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitYUV444ConvertersSSE2(); + } +#endif +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitYUV444ConvertersSSE41(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPInitYUV444ConvertersMIPSdspR2(); + } +#endif + } +} + +//------------------------------------------------------------------------------ +// Main calls + +extern void WebPInitUpsamplersSSE2(void); +extern void WebPInitUpsamplersSSE41(void); +extern void WebPInitUpsamplersNEON(void); +extern void WebPInitUpsamplersMIPSdspR2(void); +extern void WebPInitUpsamplersMSA(void); + +WEBP_DSP_INIT_FUNC(WebPInitUpsamplers) { +#ifdef FANCY_UPSAMPLING +#if !WEBP_NEON_OMIT_C_CODE + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_C; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_C; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_C; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_C; + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_C; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_C; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_C; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_C; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_C; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_C; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_C; +#endif + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitUpsamplersSSE2(); + } +#endif +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitUpsamplersSSE41(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPInitUpsamplersMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + WebPInitUpsamplersMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitUpsamplersNEON(); + } +#endif + + assert(WebPUpsamplers[MODE_RGBA] != NULL); + assert(WebPUpsamplers[MODE_BGRA] != NULL); + assert(WebPUpsamplers[MODE_rgbA] != NULL); + assert(WebPUpsamplers[MODE_bgrA] != NULL); +#if !defined(WEBP_REDUCE_CSP) || !WEBP_NEON_OMIT_C_CODE + assert(WebPUpsamplers[MODE_RGB] != NULL); + assert(WebPUpsamplers[MODE_BGR] != NULL); + assert(WebPUpsamplers[MODE_ARGB] != NULL); + assert(WebPUpsamplers[MODE_RGBA_4444] != NULL); + assert(WebPUpsamplers[MODE_RGB_565] != NULL); + assert(WebPUpsamplers[MODE_Argb] != NULL); + assert(WebPUpsamplers[MODE_rgbA_4444] != NULL); +#endif + +#endif // FANCY_UPSAMPLING +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/dsp/upsampling_mips_dsp_r2.c b/libraries/webp/src/dsp/upsampling_mips_dsp_r2.c new file mode 100644 index 0000000000..10d499d771 --- /dev/null +++ b/libraries/webp/src/dsp/upsampling_mips_dsp_r2.c @@ -0,0 +1,291 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV to RGB upsampling functions. +// +// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) +// Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include +#include "src/dsp/yuv.h" + +#define YUV_TO_RGB(Y, U, V, R, G, B) do { \ + const int t1 = MultHi(Y, 19077); \ + const int t2 = MultHi(V, 13320); \ + R = MultHi(V, 26149); \ + G = MultHi(U, 6419); \ + B = MultHi(U, 33050); \ + R = t1 + R; \ + G = t1 - G; \ + B = t1 + B; \ + R = R - 14234; \ + G = G - t2 + 8708; \ + B = B - 17685; \ + __asm__ volatile ( \ + "shll_s.w %[" #R "], %[" #R "], 17 \n\t" \ + "shll_s.w %[" #G "], %[" #G "], 17 \n\t" \ + "shll_s.w %[" #B "], %[" #B "], 17 \n\t" \ + "precrqu_s.qb.ph %[" #R "], %[" #R "], $zero \n\t" \ + "precrqu_s.qb.ph %[" #G "], %[" #G "], $zero \n\t" \ + "precrqu_s.qb.ph %[" #B "], %[" #B "], $zero \n\t" \ + "srl %[" #R "], %[" #R "], 24 \n\t" \ + "srl %[" #G "], %[" #G "], 24 \n\t" \ + "srl %[" #B "], %[" #B "], 24 \n\t" \ + : [R]"+r"(R), [G]"+r"(G), [B]"+r"(B) \ + : \ + ); \ + } while (0) + +#if !defined(WEBP_REDUCE_CSP) +static WEBP_INLINE void YuvToRgb(int y, int u, int v, uint8_t* const rgb) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + rgb[0] = r; + rgb[1] = g; + rgb[2] = b; +} +static WEBP_INLINE void YuvToBgr(int y, int u, int v, uint8_t* const bgr) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + bgr[0] = b; + bgr[1] = g; + bgr[2] = r; +} +static WEBP_INLINE void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + { + const int rg = (r & 0xf8) | (g >> 5); + const int gb = ((g << 3) & 0xe0) | (b >> 3); +#if (WEBP_SWAP_16BIT_CSP == 1) + rgb[0] = gb; + rgb[1] = rg; +#else + rgb[0] = rg; + rgb[1] = gb; +#endif + } +} +static WEBP_INLINE void YuvToRgba4444(int y, int u, int v, + uint8_t* const argb) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + { + const int rg = (r & 0xf0) | (g >> 4); + const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits +#if (WEBP_SWAP_16BIT_CSP == 1) + argb[0] = ba; + argb[1] = rg; +#else + argb[0] = rg; + argb[1] = ba; +#endif + } +} +#endif // WEBP_REDUCE_CSP + +//----------------------------------------------------------------------------- +// Alpha handling variants + +#if !defined(WEBP_REDUCE_CSP) +static WEBP_INLINE void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const argb) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + argb[0] = 0xff; + argb[1] = r; + argb[2] = g; + argb[3] = b; +} +#endif // WEBP_REDUCE_CSP +static WEBP_INLINE void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const bgra) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + bgra[0] = b; + bgra[1] = g; + bgra[2] = r; + bgra[3] = 0xff; +} +static WEBP_INLINE void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const rgba) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + rgba[0] = r; + rgba[1] = g; + rgba[2] = b; + rgba[3] = 0xff; +} + +//------------------------------------------------------------------------------ +// Fancy upsampler + +#ifdef FANCY_UPSAMPLING + +// Given samples laid out in a square as: +// [a b] +// [c d] +// we interpolate u/v as: +// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 +// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 + +// We process u and v together stashed into 32bit (16bit each). +#define LOAD_UV(u, v) ((u) | ((v) << 16)) + +#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int x; \ + const int last_pixel_pair = (len - 1) >> 1; \ + uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ + uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ + assert(top_y != NULL); \ + { \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ + } \ + for (x = 1; x <= last_pixel_pair; ++x) { \ + const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ + const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ + /* precompute invariant values associated with first and second diagonals*/\ + const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ + const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ + const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ + { \ + const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ + const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ + FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ + top_dst + (2 * x - 1) * XSTEP); \ + FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ + top_dst + (2 * x - 0) * XSTEP); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ + const uint32_t uv1 = (diag_12 + uv) >> 1; \ + FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ + bottom_dst + (2 * x - 1) * XSTEP); \ + FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ + bottom_dst + (2 * x + 0) * XSTEP); \ + } \ + tl_uv = t_uv; \ + l_uv = uv; \ + } \ + if (!(len & 1)) { \ + { \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ + top_dst + (len - 1) * XSTEP); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ + bottom_dst + (len - 1) * XSTEP); \ + } \ + } \ +} + +// All variants implemented. +UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4) +UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) +UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4) +UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2) +UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP + +#undef LOAD_UV +#undef UPSAMPLE_FUNC + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitUpsamplersMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMIPSdspR2(void) { + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +//------------------------------------------------------------------------------ +// YUV444 converter + +#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ +} + +YUV444_FUNC(Yuv444ToRgba, YuvToRgba, 4) +YUV444_FUNC(Yuv444ToBgra, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(Yuv444ToRgb, YuvToRgb, 3) +YUV444_FUNC(Yuv444ToBgr, YuvToBgr, 3) +YUV444_FUNC(Yuv444ToArgb, YuvToArgb, 4) +YUV444_FUNC(Yuv444ToRgba4444, YuvToRgba4444, 2) +YUV444_FUNC(Yuv444ToRgb565, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP + +#undef YUV444_FUNC + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitYUV444ConvertersMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersMIPSdspR2(void) { + WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba; + WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra; + WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba; + WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra; +#if !defined(WEBP_REDUCE_CSP) + WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; + WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; + WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb; + WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444; + WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565; + WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb; + WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444; +#endif // WEBP_REDUCE_CSP +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MIPS_DSP_R2)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersMIPSdspR2) +#endif diff --git a/libraries/webp/src/dsp/upsampling_msa.c b/libraries/webp/src/dsp/upsampling_msa.c new file mode 100644 index 0000000000..f2e03e85e9 --- /dev/null +++ b/libraries/webp/src/dsp/upsampling_msa.c @@ -0,0 +1,688 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA version of YUV to RGB upsampling functions. +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/msa_macro.h" +#include "src/dsp/yuv.h" + +#ifdef FANCY_UPSAMPLING + +#define ILVR_UW2(in, out0, out1) do { \ + const v8i16 t0 = (v8i16)__msa_ilvr_b((v16i8)zero, (v16i8)in); \ + out0 = (v4u32)__msa_ilvr_h((v8i16)zero, t0); \ + out1 = (v4u32)__msa_ilvl_h((v8i16)zero, t0); \ +} while (0) + +#define ILVRL_UW4(in, out0, out1, out2, out3) do { \ + v16u8 t0, t1; \ + ILVRL_B2_UB(zero, in, t0, t1); \ + ILVRL_H2_UW(zero, t0, out0, out1); \ + ILVRL_H2_UW(zero, t1, out2, out3); \ +} while (0) + +#define MULTHI_16(in0, in1, in2, in3, cnst, out0, out1) do { \ + const v4i32 const0 = (v4i32)__msa_fill_w(cnst * 256); \ + v4u32 temp0, temp1, temp2, temp3; \ + MUL4(in0, const0, in1, const0, in2, const0, in3, const0, \ + temp0, temp1, temp2, temp3); \ + PCKOD_H2_UH(temp1, temp0, temp3, temp2, out0, out1); \ +} while (0) + +#define MULTHI_8(in0, in1, cnst, out0) do { \ + const v4i32 const0 = (v4i32)__msa_fill_w(cnst * 256); \ + v4u32 temp0, temp1; \ + MUL2(in0, const0, in1, const0, temp0, temp1); \ + out0 = (v8u16)__msa_pckod_h((v8i16)temp1, (v8i16)temp0); \ +} while (0) + +#define CALC_R16(y0, y1, v0, v1, dst) do { \ + const v8i16 const_a = (v8i16)__msa_fill_h(14234); \ + const v8i16 a0 = __msa_adds_s_h((v8i16)y0, (v8i16)v0); \ + const v8i16 a1 = __msa_adds_s_h((v8i16)y1, (v8i16)v1); \ + v8i16 b0 = __msa_subs_s_h(a0, const_a); \ + v8i16 b1 = __msa_subs_s_h(a1, const_a); \ + SRAI_H2_SH(b0, b1, 6); \ + CLIP_SH2_0_255(b0, b1); \ + dst = (v16u8)__msa_pckev_b((v16i8)b1, (v16i8)b0); \ +} while (0) + +#define CALC_R8(y0, v0, dst) do { \ + const v8i16 const_a = (v8i16)__msa_fill_h(14234); \ + const v8i16 a0 = __msa_adds_s_h((v8i16)y0, (v8i16)v0); \ + v8i16 b0 = __msa_subs_s_h(a0, const_a); \ + b0 = SRAI_H(b0, 6); \ + CLIP_SH_0_255(b0); \ + dst = (v16u8)__msa_pckev_b((v16i8)b0, (v16i8)b0); \ +} while (0) + +#define CALC_G16(y0, y1, u0, u1, v0, v1, dst) do { \ + const v8i16 const_a = (v8i16)__msa_fill_h(8708); \ + v8i16 a0 = __msa_subs_s_h((v8i16)y0, (v8i16)u0); \ + v8i16 a1 = __msa_subs_s_h((v8i16)y1, (v8i16)u1); \ + const v8i16 b0 = __msa_subs_s_h(a0, (v8i16)v0); \ + const v8i16 b1 = __msa_subs_s_h(a1, (v8i16)v1); \ + a0 = __msa_adds_s_h(b0, const_a); \ + a1 = __msa_adds_s_h(b1, const_a); \ + SRAI_H2_SH(a0, a1, 6); \ + CLIP_SH2_0_255(a0, a1); \ + dst = (v16u8)__msa_pckev_b((v16i8)a1, (v16i8)a0); \ +} while (0) + +#define CALC_G8(y0, u0, v0, dst) do { \ + const v8i16 const_a = (v8i16)__msa_fill_h(8708); \ + v8i16 a0 = __msa_subs_s_h((v8i16)y0, (v8i16)u0); \ + const v8i16 b0 = __msa_subs_s_h(a0, (v8i16)v0); \ + a0 = __msa_adds_s_h(b0, const_a); \ + a0 = SRAI_H(a0, 6); \ + CLIP_SH_0_255(a0); \ + dst = (v16u8)__msa_pckev_b((v16i8)a0, (v16i8)a0); \ +} while (0) + +#define CALC_B16(y0, y1, u0, u1, dst) do { \ + const v8u16 const_a = (v8u16)__msa_fill_h(17685); \ + const v8u16 a0 = __msa_adds_u_h((v8u16)y0, u0); \ + const v8u16 a1 = __msa_adds_u_h((v8u16)y1, u1); \ + v8u16 b0 = __msa_subs_u_h(a0, const_a); \ + v8u16 b1 = __msa_subs_u_h(a1, const_a); \ + SRAI_H2_UH(b0, b1, 6); \ + CLIP_UH2_0_255(b0, b1); \ + dst = (v16u8)__msa_pckev_b((v16i8)b1, (v16i8)b0); \ +} while (0) + +#define CALC_B8(y0, u0, dst) do { \ + const v8u16 const_a = (v8u16)__msa_fill_h(17685); \ + const v8u16 a0 = __msa_adds_u_h((v8u16)y0, u0); \ + v8u16 b0 = __msa_subs_u_h(a0, const_a); \ + b0 = SRAI_H(b0, 6); \ + CLIP_UH_0_255(b0); \ + dst = (v16u8)__msa_pckev_b((v16i8)b0, (v16i8)b0); \ +} while (0) + +#define CALC_RGB16(y, u, v, R, G, B) do { \ + const v16u8 zero = { 0 }; \ + v8u16 y0, y1, u0, u1, v0, v1; \ + v4u32 p0, p1, p2, p3; \ + const v16u8 in_y = LD_UB(y); \ + const v16u8 in_u = LD_UB(u); \ + const v16u8 in_v = LD_UB(v); \ + ILVRL_UW4(in_y, p0, p1, p2, p3); \ + MULTHI_16(p0, p1, p2, p3, 19077, y0, y1); \ + ILVRL_UW4(in_v, p0, p1, p2, p3); \ + MULTHI_16(p0, p1, p2, p3, 26149, v0, v1); \ + CALC_R16(y0, y1, v0, v1, R); \ + MULTHI_16(p0, p1, p2, p3, 13320, v0, v1); \ + ILVRL_UW4(in_u, p0, p1, p2, p3); \ + MULTHI_16(p0, p1, p2, p3, 6419, u0, u1); \ + CALC_G16(y0, y1, u0, u1, v0, v1, G); \ + MULTHI_16(p0, p1, p2, p3, 33050, u0, u1); \ + CALC_B16(y0, y1, u0, u1, B); \ +} while (0) + +#define CALC_RGB8(y, u, v, R, G, B) do { \ + const v16u8 zero = { 0 }; \ + v8u16 y0, u0, v0; \ + v4u32 p0, p1; \ + const v16u8 in_y = LD_UB(y); \ + const v16u8 in_u = LD_UB(u); \ + const v16u8 in_v = LD_UB(v); \ + ILVR_UW2(in_y, p0, p1); \ + MULTHI_8(p0, p1, 19077, y0); \ + ILVR_UW2(in_v, p0, p1); \ + MULTHI_8(p0, p1, 26149, v0); \ + CALC_R8(y0, v0, R); \ + MULTHI_8(p0, p1, 13320, v0); \ + ILVR_UW2(in_u, p0, p1); \ + MULTHI_8(p0, p1, 6419, u0); \ + CALC_G8(y0, u0, v0, G); \ + MULTHI_8(p0, p1, 33050, u0); \ + CALC_B8(y0, u0, B); \ +} while (0) + +#define STORE16_3(a0, a1, a2, dst) do { \ + const v16u8 mask0 = { 0, 1, 16, 2, 3, 17, 4, 5, 18, 6, 7, 19, \ + 8, 9, 20, 10 }; \ + const v16u8 mask1 = { 0, 21, 1, 2, 22, 3, 4, 23, 5, 6, 24, 7, \ + 8, 25, 9, 10 }; \ + const v16u8 mask2 = { 26, 0, 1, 27, 2, 3, 28, 4, 5, 29, 6, 7, \ + 30, 8, 9, 31 }; \ + v16u8 out0, out1, out2, tmp0, tmp1, tmp2; \ + ILVRL_B2_UB(a1, a0, tmp0, tmp1); \ + out0 = VSHF_UB(tmp0, a2, mask0); \ + tmp2 = SLDI_UB(tmp1, tmp0, 11); \ + out1 = VSHF_UB(tmp2, a2, mask1); \ + tmp2 = SLDI_UB(tmp1, tmp1, 6); \ + out2 = VSHF_UB(tmp2, a2, mask2); \ + ST_UB(out0, dst + 0); \ + ST_UB(out1, dst + 16); \ + ST_UB(out2, dst + 32); \ +} while (0) + +#define STORE8_3(a0, a1, a2, dst) do { \ + int64_t out_m; \ + const v16u8 mask0 = { 0, 1, 16, 2, 3, 17, 4, 5, 18, 6, 7, 19, \ + 8, 9, 20, 10 }; \ + const v16u8 mask1 = { 11, 21, 12, 13, 22, 14, 15, 23, \ + 255, 255, 255, 255, 255, 255, 255, 255 }; \ + const v16u8 tmp0 = (v16u8)__msa_ilvr_b((v16i8)a1, (v16i8)a0); \ + v16u8 out0, out1; \ + VSHF_B2_UB(tmp0, a2, tmp0, a2, mask0, mask1, out0, out1); \ + ST_UB(out0, dst); \ + out_m = __msa_copy_s_d((v2i64)out1, 0); \ + SD(out_m, dst + 16); \ +} while (0) + +#define STORE16_4(a0, a1, a2, a3, dst) do { \ + v16u8 tmp0, tmp1, tmp2, tmp3; \ + v16u8 out0, out1, out2, out3; \ + ILVRL_B2_UB(a1, a0, tmp0, tmp1); \ + ILVRL_B2_UB(a3, a2, tmp2, tmp3); \ + ILVRL_H2_UB(tmp2, tmp0, out0, out1); \ + ILVRL_H2_UB(tmp3, tmp1, out2, out3); \ + ST_UB(out0, dst + 0); \ + ST_UB(out1, dst + 16); \ + ST_UB(out2, dst + 32); \ + ST_UB(out3, dst + 48); \ +} while (0) + +#define STORE8_4(a0, a1, a2, a3, dst) do { \ + v16u8 tmp0, tmp1, tmp2, tmp3; \ + ILVR_B2_UB(a1, a0, a3, a2, tmp0, tmp1); \ + ILVRL_H2_UB(tmp1, tmp0, tmp2, tmp3); \ + ST_UB(tmp2, dst + 0); \ + ST_UB(tmp3, dst + 16); \ +} while (0) + +#define STORE2_16(a0, a1, dst) do { \ + v16u8 out0, out1; \ + ILVRL_B2_UB(a1, a0, out0, out1); \ + ST_UB(out0, dst + 0); \ + ST_UB(out1, dst + 16); \ +} while (0) + +#define STORE2_8(a0, a1, dst) do { \ + const v16u8 out0 = (v16u8)__msa_ilvr_b((v16i8)a1, (v16i8)a0); \ + ST_UB(out0, dst); \ +} while (0) + +#define CALC_RGBA4444(y, u, v, out0, out1, N, dst) do { \ + CALC_RGB##N(y, u, v, R, G, B); \ + tmp0 = ANDI_B(R, 0xf0); \ + tmp1 = SRAI_B(G, 4); \ + RG = tmp0 | tmp1; \ + tmp0 = ANDI_B(B, 0xf0); \ + BA = ORI_B(tmp0, 0x0f); \ + STORE2_##N(out0, out1, dst); \ +} while (0) + +#define CALC_RGB565(y, u, v, out0, out1, N, dst) do { \ + CALC_RGB##N(y, u, v, R, G, B); \ + tmp0 = ANDI_B(R, 0xf8); \ + tmp1 = SRAI_B(G, 5); \ + RG = tmp0 | tmp1; \ + tmp0 = SLLI_B(G, 3); \ + tmp1 = ANDI_B(tmp0, 0xe0); \ + tmp0 = SRAI_B(B, 3); \ + GB = tmp0 | tmp1; \ + STORE2_##N(out0, out1, dst); \ +} while (0) + +static WEBP_INLINE int Clip8(int v) { + return v < 0 ? 0 : v > 255 ? 255 : v; +} + +static void YuvToRgb(int y, int u, int v, uint8_t* const rgb) { + const int y1 = MultHi(y, 19077); + const int r1 = y1 + MultHi(v, 26149) - 14234; + const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708; + const int b1 = y1 + MultHi(u, 33050) - 17685; + rgb[0] = Clip8(r1 >> 6); + rgb[1] = Clip8(g1 >> 6); + rgb[2] = Clip8(b1 >> 6); +} + +static void YuvToBgr(int y, int u, int v, uint8_t* const bgr) { + const int y1 = MultHi(y, 19077); + const int r1 = y1 + MultHi(v, 26149) - 14234; + const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708; + const int b1 = y1 + MultHi(u, 33050) - 17685; + bgr[0] = Clip8(b1 >> 6); + bgr[1] = Clip8(g1 >> 6); + bgr[2] = Clip8(r1 >> 6); +} + +#if !defined(WEBP_REDUCE_CSP) +static void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { + const int y1 = MultHi(y, 19077); + const int r1 = y1 + MultHi(v, 26149) - 14234; + const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708; + const int b1 = y1 + MultHi(u, 33050) - 17685; + const int r = Clip8(r1 >> 6); + const int g = Clip8(g1 >> 6); + const int b = Clip8(b1 >> 6); + const int rg = (r & 0xf8) | (g >> 5); + const int gb = ((g << 3) & 0xe0) | (b >> 3); +#if (WEBP_SWAP_16BIT_CSP == 1) + rgb[0] = gb; + rgb[1] = rg; +#else + rgb[0] = rg; + rgb[1] = gb; +#endif +} + +static void YuvToRgba4444(int y, int u, int v, uint8_t* const argb) { + const int y1 = MultHi(y, 19077); + const int r1 = y1 + MultHi(v, 26149) - 14234; + const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708; + const int b1 = y1 + MultHi(u, 33050) - 17685; + const int r = Clip8(r1 >> 6); + const int g = Clip8(g1 >> 6); + const int b = Clip8(b1 >> 6); + const int rg = (r & 0xf0) | (g >> 4); + const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits +#if (WEBP_SWAP_16BIT_CSP == 1) + argb[0] = ba; + argb[1] = rg; +#else + argb[0] = rg; + argb[1] = ba; +#endif +} + +static void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, uint8_t* const argb) { + argb[0] = 0xff; + YuvToRgb(y, u, v, argb + 1); +} +#endif // WEBP_REDUCE_CSP + +static void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgra) { + YuvToBgr(y, u, v, bgra); + bgra[3] = 0xff; +} + +static void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, uint8_t* const rgba) { + YuvToRgb(y, u, v, rgba); + rgba[3] = 0xff; +} + +#if !defined(WEBP_REDUCE_CSP) +static void YuvToRgbLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_3(R, G, B, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 3; + length -= 16; + } + if (length > 8) { + uint8_t temp[3 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(temp, u, v, R, G, B); + STORE16_3(R, G, B, temp); + memcpy(dst, temp, length * 3 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[3 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_3(R, G, B, temp); + memcpy(dst, temp, length * 3 * sizeof(*dst)); + } +} + +static void YuvToBgrLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_3(B, G, R, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 3; + length -= 16; + } + if (length > 8) { + uint8_t temp[3 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(temp, u, v, R, G, B); + STORE16_3(B, G, R, temp); + memcpy(dst, temp, length * 3 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[3 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_3(B, G, R, temp); + memcpy(dst, temp, length * 3 * sizeof(*dst)); + } +} +#endif // WEBP_REDUCE_CSP + +static void YuvToRgbaLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_4(R, G, B, A, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 4; + length -= 16; + } + if (length > 8) { + uint8_t temp[4 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(&temp[0], u, v, R, G, B); + STORE16_4(R, G, B, A, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[4 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_4(R, G, B, A, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } +} + +static void YuvToBgraLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_4(B, G, R, A, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 4; + length -= 16; + } + if (length > 8) { + uint8_t temp[4 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(temp, u, v, R, G, B); + STORE16_4(B, G, R, A, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[4 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_4(B, G, R, A, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } +} + +#if !defined(WEBP_REDUCE_CSP) +static void YuvToArgbLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_4(A, R, G, B, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 4; + length -= 16; + } + if (length > 8) { + uint8_t temp[4 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(temp, u, v, R, G, B); + STORE16_4(A, R, G, B, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[4 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_4(A, R, G, B, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } +} + +static void YuvToRgba4444Line(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B, RG, BA, tmp0, tmp1; + while (length >= 16) { +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGBA4444(y, u, v, BA, RG, 16, dst); +#else + CALC_RGBA4444(y, u, v, RG, BA, 16, dst); +#endif + y += 16; + u += 16; + v += 16; + dst += 16 * 2; + length -= 16; + } + if (length > 8) { + uint8_t temp[2 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGBA4444(temp, u, v, BA, RG, 16, temp); +#else + CALC_RGBA4444(temp, u, v, RG, BA, 16, temp); +#endif + memcpy(dst, temp, length * 2 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[2 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGBA4444(temp, u, v, BA, RG, 8, temp); +#else + CALC_RGBA4444(temp, u, v, RG, BA, 8, temp); +#endif + memcpy(dst, temp, length * 2 * sizeof(*dst)); + } +} + +static void YuvToRgb565Line(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B, RG, GB, tmp0, tmp1; + while (length >= 16) { +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGB565(y, u, v, GB, RG, 16, dst); +#else + CALC_RGB565(y, u, v, RG, GB, 16, dst); +#endif + y += 16; + u += 16; + v += 16; + dst += 16 * 2; + length -= 16; + } + if (length > 8) { + uint8_t temp[2 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGB565(temp, u, v, GB, RG, 16, temp); +#else + CALC_RGB565(temp, u, v, RG, GB, 16, temp); +#endif + memcpy(dst, temp, length * 2 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[2 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGB565(temp, u, v, GB, RG, 8, temp); +#else + CALC_RGB565(temp, u, v, RG, GB, 8, temp); +#endif + memcpy(dst, temp, length * 2 * sizeof(*dst)); + } +} +#endif // WEBP_REDUCE_CSP + +#define UPSAMPLE_32PIXELS(a, b, c, d) do { \ + v16u8 s = __msa_aver_u_b(a, d); \ + v16u8 t = __msa_aver_u_b(b, c); \ + const v16u8 st = s ^ t; \ + v16u8 ad = a ^ d; \ + v16u8 bc = b ^ c; \ + v16u8 t0 = ad | bc; \ + v16u8 t1 = t0 | st; \ + v16u8 t2 = ANDI_B(t1, 1); \ + v16u8 t3 = __msa_aver_u_b(s, t); \ + const v16u8 k = t3 - t2; \ + v16u8 diag1, diag2; \ + AVER_UB2_UB(t, k, s, k, t0, t1); \ + bc = bc & st; \ + ad = ad & st; \ + t = t ^ k; \ + s = s ^ k; \ + t2 = bc | t; \ + t3 = ad | s; \ + t2 = ANDI_B(t2, 1); \ + t3 = ANDI_B(t3, 1); \ + SUB2(t0, t2, t1, t3, diag1, diag2); \ + AVER_UB2_UB(a, diag1, b, diag2, t0, t1); \ + ILVRL_B2_UB(t1, t0, a, b); \ + if (pbot_y != NULL) { \ + AVER_UB2_UB(c, diag2, d, diag1, t0, t1); \ + ILVRL_B2_UB(t1, t0, c, d); \ + } \ +} while (0) + +#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bot_dst, int len) \ +{ \ + int size = (len - 1) >> 1; \ + uint8_t temp_u[64]; \ + uint8_t temp_v[64]; \ + const uint32_t tl_uv = ((top_u[0]) | ((top_v[0]) << 16)); \ + const uint32_t l_uv = ((cur_u[0]) | ((cur_v[0]) << 16)); \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + const uint8_t* ptop_y = &top_y[1]; \ + uint8_t* ptop_dst = top_dst + XSTEP; \ + const uint8_t* pbot_y = &bot_y[1]; \ + uint8_t* pbot_dst = bot_dst + XSTEP; \ + \ + FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ + if (bot_y != NULL) { \ + const uint32_t uv1 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bot_y[0], uv1 & 0xff, (uv1 >> 16), bot_dst); \ + } \ + while (size >= 16) { \ + v16u8 tu0, tu1, tv0, tv1, cu0, cu1, cv0, cv1; \ + LD_UB2(top_u, 1, tu0, tu1); \ + LD_UB2(cur_u, 1, cu0, cu1); \ + LD_UB2(top_v, 1, tv0, tv1); \ + LD_UB2(cur_v, 1, cv0, cv1); \ + UPSAMPLE_32PIXELS(tu0, tu1, cu0, cu1); \ + UPSAMPLE_32PIXELS(tv0, tv1, cv0, cv1); \ + ST_UB4(tu0, tu1, cu0, cu1, &temp_u[0], 16); \ + ST_UB4(tv0, tv1, cv0, cv1, &temp_v[0], 16); \ + FUNC##Line(ptop_y, &temp_u[ 0], &temp_v[0], ptop_dst, 32); \ + if (bot_y != NULL) { \ + FUNC##Line(pbot_y, &temp_u[32], &temp_v[32], pbot_dst, 32); \ + } \ + ptop_y += 32; \ + pbot_y += 32; \ + ptop_dst += XSTEP * 32; \ + pbot_dst += XSTEP * 32; \ + top_u += 16; \ + top_v += 16; \ + cur_u += 16; \ + cur_v += 16; \ + size -= 16; \ + } \ + if (size > 0) { \ + v16u8 tu0, tu1, tv0, tv1, cu0, cu1, cv0, cv1; \ + memcpy(&temp_u[ 0], top_u, 17 * sizeof(uint8_t)); \ + memcpy(&temp_u[32], cur_u, 17 * sizeof(uint8_t)); \ + memcpy(&temp_v[ 0], top_v, 17 * sizeof(uint8_t)); \ + memcpy(&temp_v[32], cur_v, 17 * sizeof(uint8_t)); \ + LD_UB2(&temp_u[ 0], 1, tu0, tu1); \ + LD_UB2(&temp_u[32], 1, cu0, cu1); \ + LD_UB2(&temp_v[ 0], 1, tv0, tv1); \ + LD_UB2(&temp_v[32], 1, cv0, cv1); \ + UPSAMPLE_32PIXELS(tu0, tu1, cu0, cu1); \ + UPSAMPLE_32PIXELS(tv0, tv1, cv0, cv1); \ + ST_UB4(tu0, tu1, cu0, cu1, &temp_u[0], 16); \ + ST_UB4(tv0, tv1, cv0, cv1, &temp_v[0], 16); \ + FUNC##Line(ptop_y, &temp_u[ 0], &temp_v[0], ptop_dst, size * 2); \ + if (bot_y != NULL) { \ + FUNC##Line(pbot_y, &temp_u[32], &temp_v[32], pbot_dst, size * 2); \ + } \ + top_u += size; \ + top_v += size; \ + cur_u += size; \ + cur_v += size; \ + } \ + if (!(len & 1)) { \ + const uint32_t t0 = ((top_u[0]) | ((top_v[0]) << 16)); \ + const uint32_t c0 = ((cur_u[0]) | ((cur_v[0]) << 16)); \ + const uint32_t tmp0 = (3 * t0 + c0 + 0x00020002u) >> 2; \ + FUNC(top_y[len - 1], tmp0 & 0xff, (tmp0 >> 16), \ + top_dst + (len - 1) * XSTEP); \ + if (bot_y != NULL) { \ + const uint32_t tmp1 = (3 * c0 + t0 + 0x00020002u) >> 2; \ + FUNC(bot_y[len - 1], tmp1 & 0xff, (tmp1 >> 16), \ + bot_dst + (len - 1) * XSTEP); \ + } \ + } \ +} + +UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4) +UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) +UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4) +UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2) +UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP + +//------------------------------------------------------------------------------ +// Entry point + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +extern void WebPInitUpsamplersMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMSA(void) { + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +#endif // WEBP_USE_MSA + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MSA)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersMSA) +#endif diff --git a/libraries/webp/src/dsp/upsampling_neon.c b/libraries/webp/src/dsp/upsampling_neon.c new file mode 100644 index 0000000000..bbc000ca2d --- /dev/null +++ b/libraries/webp/src/dsp/upsampling_neon.c @@ -0,0 +1,285 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON version of YUV to RGB upsampling functions. +// +// Author: mans@mansr.com (Mans Rullgard) +// Based on SSE code by: somnath@google.com (Somnath Banerjee) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include +#include +#include +#include "src/dsp/neon.h" +#include "src/dsp/yuv.h" + +#ifdef FANCY_UPSAMPLING + +//----------------------------------------------------------------------------- +// U/V upsampling + +// Loads 9 pixels each from rows r1 and r2 and generates 16 pixels. +#define UPSAMPLE_16PIXELS(r1, r2, out) do { \ + const uint8x8_t a = vld1_u8(r1 + 0); \ + const uint8x8_t b = vld1_u8(r1 + 1); \ + const uint8x8_t c = vld1_u8(r2 + 0); \ + const uint8x8_t d = vld1_u8(r2 + 1); \ + /* a + b + c + d */ \ + const uint16x8_t ad = vaddl_u8(a, d); \ + const uint16x8_t bc = vaddl_u8(b, c); \ + const uint16x8_t abcd = vaddq_u16(ad, bc); \ + /* 3a + b + c + 3d */ \ + const uint16x8_t al = vaddq_u16(abcd, vshlq_n_u16(ad, 1)); \ + /* a + 3b + 3c + d */ \ + const uint16x8_t bl = vaddq_u16(abcd, vshlq_n_u16(bc, 1)); \ + \ + const uint8x8_t diag2 = vshrn_n_u16(al, 3); \ + const uint8x8_t diag1 = vshrn_n_u16(bl, 3); \ + \ + const uint8x8_t A = vrhadd_u8(a, diag1); \ + const uint8x8_t B = vrhadd_u8(b, diag2); \ + const uint8x8_t C = vrhadd_u8(c, diag2); \ + const uint8x8_t D = vrhadd_u8(d, diag1); \ + \ + uint8x8x2_t A_B, C_D; \ + INIT_VECTOR2(A_B, A, B); \ + INIT_VECTOR2(C_D, C, D); \ + vst2_u8(out + 0, A_B); \ + vst2_u8(out + 32, C_D); \ +} while (0) + +// Turn the macro into a function for reducing code-size when non-critical +static void Upsample16Pixels_NEON(const uint8_t* r1, const uint8_t* r2, + uint8_t* out) { + UPSAMPLE_16PIXELS(r1, r2, out); +} + +#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ + uint8_t r1[9], r2[9]; \ + memcpy(r1, (tb), (num_pixels)); \ + memcpy(r2, (bb), (num_pixels)); \ + /* replicate last byte */ \ + memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \ + memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \ + Upsample16Pixels_NEON(r1, r2, out); \ +} + +//----------------------------------------------------------------------------- +// YUV->RGB conversion + +// note: we represent the 33050 large constant as 32768 + 282 +static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 }; + +#define v255 vdup_n_u8(255) + +#define STORE_Rgb(out, r, g, b) do { \ + uint8x8x3_t r_g_b; \ + INIT_VECTOR3(r_g_b, r, g, b); \ + vst3_u8(out, r_g_b); \ +} while (0) + +#define STORE_Bgr(out, r, g, b) do { \ + uint8x8x3_t b_g_r; \ + INIT_VECTOR3(b_g_r, b, g, r); \ + vst3_u8(out, b_g_r); \ +} while (0) + +#define STORE_Rgba(out, r, g, b) do { \ + uint8x8x4_t r_g_b_v255; \ + INIT_VECTOR4(r_g_b_v255, r, g, b, v255); \ + vst4_u8(out, r_g_b_v255); \ +} while (0) + +#define STORE_Bgra(out, r, g, b) do { \ + uint8x8x4_t b_g_r_v255; \ + INIT_VECTOR4(b_g_r_v255, b, g, r, v255); \ + vst4_u8(out, b_g_r_v255); \ +} while (0) + +#define STORE_Argb(out, r, g, b) do { \ + uint8x8x4_t v255_r_g_b; \ + INIT_VECTOR4(v255_r_g_b, v255, r, g, b); \ + vst4_u8(out, v255_r_g_b); \ +} while (0) + +#if (WEBP_SWAP_16BIT_CSP == 0) +#define ZIP_U8(lo, hi) vzip_u8((lo), (hi)) +#else +#define ZIP_U8(lo, hi) vzip_u8((hi), (lo)) +#endif + +#define STORE_Rgba4444(out, r, g, b) do { \ + const uint8x8_t rg = vsri_n_u8(r, g, 4); /* shift g, insert r */ \ + const uint8x8_t ba = vsri_n_u8(b, v255, 4); /* shift a, insert b */ \ + const uint8x8x2_t rgba4444 = ZIP_U8(rg, ba); \ + vst1q_u8(out, vcombine_u8(rgba4444.val[0], rgba4444.val[1])); \ +} while (0) + +#define STORE_Rgb565(out, r, g, b) do { \ + const uint8x8_t rg = vsri_n_u8(r, g, 5); /* shift g and insert r */ \ + const uint8x8_t g1 = vshl_n_u8(g, 3); /* pre-shift g: 3bits */ \ + const uint8x8_t gb = vsri_n_u8(g1, b, 3); /* shift b and insert g */ \ + const uint8x8x2_t rgb565 = ZIP_U8(rg, gb); \ + vst1q_u8(out, vcombine_u8(rgb565.val[0], rgb565.val[1])); \ +} while (0) + +#define CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) do { \ + int i; \ + for (i = 0; i < N; i += 8) { \ + const int off = ((cur_x) + i) * XSTEP; \ + const uint8x8_t y = vld1_u8((src_y) + (cur_x) + i); \ + const uint8x8_t u = vld1_u8((src_uv) + i + 0); \ + const uint8x8_t v = vld1_u8((src_uv) + i + 16); \ + const int16x8_t Y0 = vreinterpretq_s16_u16(vshll_n_u8(y, 7)); \ + const int16x8_t U0 = vreinterpretq_s16_u16(vshll_n_u8(u, 7)); \ + const int16x8_t V0 = vreinterpretq_s16_u16(vshll_n_u8(v, 7)); \ + const int16x8_t Y1 = vqdmulhq_lane_s16(Y0, coeff1, 0); \ + const int16x8_t R0 = vqdmulhq_lane_s16(V0, coeff1, 1); \ + const int16x8_t G0 = vqdmulhq_lane_s16(U0, coeff1, 2); \ + const int16x8_t G1 = vqdmulhq_lane_s16(V0, coeff1, 3); \ + const int16x8_t B0 = vqdmulhq_n_s16(U0, 282); \ + const int16x8_t R1 = vqaddq_s16(Y1, R_Rounder); \ + const int16x8_t G2 = vqaddq_s16(Y1, G_Rounder); \ + const int16x8_t B1 = vqaddq_s16(Y1, B_Rounder); \ + const int16x8_t R2 = vqaddq_s16(R0, R1); \ + const int16x8_t G3 = vqaddq_s16(G0, G1); \ + const int16x8_t B2 = vqaddq_s16(B0, B1); \ + const int16x8_t G4 = vqsubq_s16(G2, G3); \ + const int16x8_t B3 = vqaddq_s16(B2, U0); \ + const uint8x8_t R = vqshrun_n_s16(R2, YUV_FIX2); \ + const uint8x8_t G = vqshrun_n_s16(G4, YUV_FIX2); \ + const uint8x8_t B = vqshrun_n_s16(B3, YUV_FIX2); \ + STORE_ ## FMT(out + off, R, G, B); \ + } \ +} while (0) + +#define CONVERT1(FUNC, XSTEP, N, src_y, src_uv, rgb, cur_x) { \ + int i; \ + for (i = 0; i < N; i++) { \ + const int off = ((cur_x) + i) * XSTEP; \ + const int y = src_y[(cur_x) + i]; \ + const int u = (src_uv)[i]; \ + const int v = (src_uv)[i + 16]; \ + FUNC(y, u, v, rgb + off); \ + } \ +} + +#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \ + top_dst, bottom_dst, cur_x, len) { \ + CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x); \ + if (bottom_y != NULL) { \ + CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ + } \ +} + +#define CONVERT2RGB_1(FUNC, XSTEP, top_y, bottom_y, uv, \ + top_dst, bottom_dst, cur_x, len) { \ + CONVERT1(FUNC, XSTEP, len, top_y, uv, top_dst, cur_x); \ + if (bottom_y != NULL) { \ + CONVERT1(FUNC, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ + } \ +} + +#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int block; \ + /* 16 byte aligned array to cache reconstructed u and v */ \ + uint8_t uv_buf[2 * 32 + 15]; \ + uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ + const int uv_len = (len + 1) >> 1; \ + /* 9 pixels must be read-able for each block */ \ + const int num_blocks = (uv_len - 1) >> 3; \ + const int leftover = uv_len - num_blocks * 8; \ + const int last_pos = 1 + 16 * num_blocks; \ + \ + const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ + const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ + \ + const int16x4_t coeff1 = vld1_s16(kCoeffs1); \ + const int16x8_t R_Rounder = vdupq_n_s16(-14234); \ + const int16x8_t G_Rounder = vdupq_n_s16(8708); \ + const int16x8_t B_Rounder = vdupq_n_s16(-17685); \ + \ + /* Treat the first pixel in regular way */ \ + assert(top_y != NULL); \ + { \ + const int u0 = (top_u[0] + u_diag) >> 1; \ + const int v0 = (top_v[0] + v_diag) >> 1; \ + VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \ + } \ + if (bottom_y != NULL) { \ + const int u0 = (cur_u[0] + u_diag) >> 1; \ + const int v0 = (cur_v[0] + v_diag) >> 1; \ + VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \ + } \ + \ + for (block = 0; block < num_blocks; ++block) { \ + UPSAMPLE_16PIXELS(top_u, cur_u, r_uv); \ + UPSAMPLE_16PIXELS(top_v, cur_v, r_uv + 16); \ + CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, r_uv, \ + top_dst, bottom_dst, 16 * block + 1, 16); \ + top_u += 8; \ + cur_u += 8; \ + top_v += 8; \ + cur_v += 8; \ + } \ + \ + UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv); \ + UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 16); \ + CONVERT2RGB_1(VP8YuvTo ## FMT, XSTEP, top_y, bottom_y, r_uv, \ + top_dst, bottom_dst, last_pos, len - last_pos); \ +} + +// NEON variants of the fancy upsampler. +NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair_NEON, Rgba, 4) +NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair_NEON, Bgra, 4) +#if !defined(WEBP_REDUCE_CSP) +NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair_NEON, Rgb, 3) +NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair_NEON, Bgr, 3) +NEON_UPSAMPLE_FUNC(UpsampleArgbLinePair_NEON, Argb, 4) +NEON_UPSAMPLE_FUNC(UpsampleRgba4444LinePair_NEON, Rgba4444, 2) +NEON_UPSAMPLE_FUNC(UpsampleRgb565LinePair_NEON, Rgb565, 2) +#endif // WEBP_REDUCE_CSP + +//------------------------------------------------------------------------------ +// Entry point + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +extern void WebPInitUpsamplersNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersNEON(void) { + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_NEON; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_NEON; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_NEON; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_NEON; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_NEON; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_NEON; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_NEON; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_NEON; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_NEON; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_NEON; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_NEON; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +#endif // WEBP_USE_NEON + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_NEON)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersNEON) +#endif diff --git a/libraries/webp/src/dsp/upsampling_sse2.c b/libraries/webp/src/dsp/upsampling_sse2.c new file mode 100644 index 0000000000..77b4f7221e --- /dev/null +++ b/libraries/webp/src/dsp/upsampling_sse2.c @@ -0,0 +1,267 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of YUV to RGB upsampling functions. +// +// Author: somnath@google.com (Somnath Banerjee) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include +#include +#include "src/dsp/yuv.h" + +#ifdef FANCY_UPSAMPLING + +// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows +// u = (9*a + 3*b + 3*c + d + 8) / 16 +// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2 +// = (a + m + 1) / 2 +// where m = (a + 3*b + 3*c + d) / 8 +// = ((a + b + c + d) / 2 + b + c) / 4 +// +// Let's say k = (a + b + c + d) / 4. +// We can compute k as +// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1 +// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2 +// +// Then m can be written as +// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1 + +// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1 +#define GET_M(ij, in, out) do { \ + const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \ + const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \ + const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \ + const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\ + const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \ + (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \ +} while (0) + +// pack and store two alternating pixel rows +#define PACK_AND_STORE(a, b, da, db, out) do { \ + const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \ + const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \ + const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \ + const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \ + _mm_store_si128(((__m128i*)(out)) + 0, t_1); \ + _mm_store_si128(((__m128i*)(out)) + 1, t_2); \ +} while (0) + +// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. +#define UPSAMPLE_32PIXELS(r1, r2, out) do { \ + const __m128i one = _mm_set1_epi8(1); \ + const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ + const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ + const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \ + const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \ + \ + const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \ + const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \ + const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \ + \ + const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \ + const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \ + \ + const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \ + const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \ + const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \ + const __m128i t4 = _mm_avg_epu8(s, t); \ + const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \ + __m128i diag1, diag2; \ + \ + GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \ + GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \ + \ + /* pack the alternate pixels */ \ + PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ + PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ +} while (0) + +// Turn the macro into a function for reducing code-size when non-critical +static void Upsample32Pixels_SSE2(const uint8_t r1[], const uint8_t r2[], + uint8_t* const out) { + UPSAMPLE_32PIXELS(r1, r2, out); +} + +#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ + uint8_t r1[17], r2[17]; \ + memcpy(r1, (tb), (num_pixels)); \ + memcpy(r2, (bb), (num_pixels)); \ + /* replicate last byte */ \ + memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \ + memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \ + /* using the shared function instead of the macro saves ~3k code size */ \ + Upsample32Pixels_SSE2(r1, r2, out); \ +} + +#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \ + top_dst, bottom_dst, cur_x) do { \ + FUNC##32_SSE2((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \ + if ((bottom_y) != NULL) { \ + FUNC##32_SSE2((bottom_y) + (cur_x), r_u + 64, r_v + 64, \ + (bottom_dst) + (cur_x) * (XSTEP)); \ + } \ +} while (0) + +#define SSE2_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int uv_pos, pos; \ + /* 16byte-aligned array to cache reconstructed u and v */ \ + uint8_t uv_buf[14 * 32 + 15] = { 0 }; \ + uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~(uintptr_t)15); \ + uint8_t* const r_v = r_u + 32; \ + \ + assert(top_y != NULL); \ + { /* Treat the first pixel in regular way */ \ + const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ + const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ + const int u0_t = (top_u[0] + u_diag) >> 1; \ + const int v0_t = (top_v[0] + v_diag) >> 1; \ + FUNC(top_y[0], u0_t, v0_t, top_dst); \ + if (bottom_y != NULL) { \ + const int u0_b = (cur_u[0] + u_diag) >> 1; \ + const int v0_b = (cur_v[0] + v_diag) >> 1; \ + FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \ + } \ + } \ + /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \ + for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \ + UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \ + UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \ + CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \ + } \ + if (len > 1) { \ + const int left_over = ((len + 1) >> 1) - (pos >> 1); \ + uint8_t* const tmp_top_dst = r_u + 4 * 32; \ + uint8_t* const tmp_bottom_dst = tmp_top_dst + 4 * 32; \ + uint8_t* const tmp_top = tmp_bottom_dst + 4 * 32; \ + uint8_t* const tmp_bottom = (bottom_y == NULL) ? NULL : tmp_top + 32; \ + assert(left_over > 0); \ + UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \ + UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \ + memcpy(tmp_top, top_y + pos, len - pos); \ + if (bottom_y != NULL) memcpy(tmp_bottom, bottom_y + pos, len - pos); \ + CONVERT2RGB_32(FUNC, XSTEP, tmp_top, tmp_bottom, tmp_top_dst, \ + tmp_bottom_dst, 0); \ + memcpy(top_dst + pos * (XSTEP), tmp_top_dst, (len - pos) * (XSTEP)); \ + if (bottom_y != NULL) { \ + memcpy(bottom_dst + pos * (XSTEP), tmp_bottom_dst, \ + (len - pos) * (XSTEP)); \ + } \ + } \ +} + +// SSE2 variants of the fancy upsampler. +SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair_SSE2, VP8YuvToRgba, 4) +SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair_SSE2, VP8YuvToBgra, 4) + +#if !defined(WEBP_REDUCE_CSP) +SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair_SSE2, VP8YuvToRgb, 3) +SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair_SSE2, VP8YuvToBgr, 3) +SSE2_UPSAMPLE_FUNC(UpsampleArgbLinePair_SSE2, VP8YuvToArgb, 4) +SSE2_UPSAMPLE_FUNC(UpsampleRgba4444LinePair_SSE2, VP8YuvToRgba4444, 2) +SSE2_UPSAMPLE_FUNC(UpsampleRgb565LinePair_SSE2, VP8YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP + +#undef GET_M +#undef PACK_AND_STORE +#undef UPSAMPLE_32PIXELS +#undef UPSAMPLE_LAST_BLOCK +#undef CONVERT2RGB +#undef CONVERT2RGB_32 +#undef SSE2_UPSAMPLE_FUNC + +//------------------------------------------------------------------------------ +// Entry point + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +extern void WebPInitUpsamplersSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE2(void) { + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_SSE2; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_SSE2; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_SSE2; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_SSE2; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_SSE2; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_SSE2; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_SSE2; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_SSE2; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_SSE2; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_SSE2; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_SSE2; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +//------------------------------------------------------------------------------ + +extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; +extern void WebPInitYUV444ConvertersSSE2(void); + +#define YUV444_FUNC(FUNC_NAME, CALL, CALL_C, XSTEP) \ +extern void CALL_C(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len); \ +static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + const int max_len = len & ~31; \ + for (i = 0; i < max_len; i += 32) { \ + CALL(y + i, u + i, v + i, dst + i * (XSTEP)); \ + } \ + if (i < len) { /* C-fallback */ \ + CALL_C(y + i, u + i, v + i, dst + i * (XSTEP), len - i); \ + } \ +} + +YUV444_FUNC(Yuv444ToRgba_SSE2, VP8YuvToRgba32_SSE2, WebPYuv444ToRgba_C, 4) +YUV444_FUNC(Yuv444ToBgra_SSE2, VP8YuvToBgra32_SSE2, WebPYuv444ToBgra_C, 4) +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(Yuv444ToRgb_SSE2, VP8YuvToRgb32_SSE2, WebPYuv444ToRgb_C, 3) +YUV444_FUNC(Yuv444ToBgr_SSE2, VP8YuvToBgr32_SSE2, WebPYuv444ToBgr_C, 3) +YUV444_FUNC(Yuv444ToArgb_SSE2, VP8YuvToArgb32_SSE2, WebPYuv444ToArgb_C, 4) +YUV444_FUNC(Yuv444ToRgba4444_SSE2, VP8YuvToRgba444432_SSE2, \ + WebPYuv444ToRgba4444_C, 2) +YUV444_FUNC(Yuv444ToRgb565_SSE2, VP8YuvToRgb56532_SSE2, WebPYuv444ToRgb565_C, 2) +#endif // WEBP_REDUCE_CSP + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE2(void) { + WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba_SSE2; + WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra_SSE2; + WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba_SSE2; + WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra_SSE2; +#if !defined(WEBP_REDUCE_CSP) + WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb_SSE2; + WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr_SSE2; + WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb_SSE2; + WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444_SSE2; + WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565_SSE2; + WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb_SSE2; + WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444_SSE2; +#endif // WEBP_REDUCE_CSP +} + +#else + +WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE2) + +#endif // WEBP_USE_SSE2 + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE2)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE2) +#endif diff --git a/libraries/webp/src/dsp/upsampling_sse41.c b/libraries/webp/src/dsp/upsampling_sse41.c new file mode 100644 index 0000000000..e38c88d5e6 --- /dev/null +++ b/libraries/webp/src/dsp/upsampling_sse41.c @@ -0,0 +1,239 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE41 version of YUV to RGB upsampling functions. +// +// Author: somnath@google.com (Somnath Banerjee) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) + +#include +#include +#include +#include "src/dsp/yuv.h" + +#ifdef FANCY_UPSAMPLING + +#if !defined(WEBP_REDUCE_CSP) + +// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows +// u = (9*a + 3*b + 3*c + d + 8) / 16 +// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2 +// = (a + m + 1) / 2 +// where m = (a + 3*b + 3*c + d) / 8 +// = ((a + b + c + d) / 2 + b + c) / 4 +// +// Let's say k = (a + b + c + d) / 4. +// We can compute k as +// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1 +// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2 +// +// Then m can be written as +// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1 + +// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1 +#define GET_M(ij, in, out) do { \ + const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \ + const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \ + const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \ + const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\ + const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \ + (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \ +} while (0) + +// pack and store two alternating pixel rows +#define PACK_AND_STORE(a, b, da, db, out) do { \ + const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \ + const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \ + const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \ + const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \ + _mm_store_si128(((__m128i*)(out)) + 0, t_1); \ + _mm_store_si128(((__m128i*)(out)) + 1, t_2); \ +} while (0) + +// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. +#define UPSAMPLE_32PIXELS(r1, r2, out) do { \ + const __m128i one = _mm_set1_epi8(1); \ + const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ + const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ + const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \ + const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \ + \ + const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \ + const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \ + const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \ + \ + const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \ + const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \ + \ + const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \ + const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \ + const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \ + const __m128i t4 = _mm_avg_epu8(s, t); \ + const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \ + __m128i diag1, diag2; \ + \ + GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \ + GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \ + \ + /* pack the alternate pixels */ \ + PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ + PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ +} while (0) + +// Turn the macro into a function for reducing code-size when non-critical +static void Upsample32Pixels_SSE41(const uint8_t r1[], const uint8_t r2[], + uint8_t* const out) { + UPSAMPLE_32PIXELS(r1, r2, out); +} + +#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ + uint8_t r1[17], r2[17]; \ + memcpy(r1, (tb), (num_pixels)); \ + memcpy(r2, (bb), (num_pixels)); \ + /* replicate last byte */ \ + memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \ + memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \ + /* using the shared function instead of the macro saves ~3k code size */ \ + Upsample32Pixels_SSE41(r1, r2, out); \ +} + +#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \ + top_dst, bottom_dst, cur_x) do { \ + FUNC##32_SSE41((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \ + if ((bottom_y) != NULL) { \ + FUNC##32_SSE41((bottom_y) + (cur_x), r_u + 64, r_v + 64, \ + (bottom_dst) + (cur_x) * (XSTEP)); \ + } \ +} while (0) + +#define SSE4_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int uv_pos, pos; \ + /* 16byte-aligned array to cache reconstructed u and v */ \ + uint8_t uv_buf[14 * 32 + 15] = { 0 }; \ + uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ + uint8_t* const r_v = r_u + 32; \ + \ + assert(top_y != NULL); \ + { /* Treat the first pixel in regular way */ \ + const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ + const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ + const int u0_t = (top_u[0] + u_diag) >> 1; \ + const int v0_t = (top_v[0] + v_diag) >> 1; \ + FUNC(top_y[0], u0_t, v0_t, top_dst); \ + if (bottom_y != NULL) { \ + const int u0_b = (cur_u[0] + u_diag) >> 1; \ + const int v0_b = (cur_v[0] + v_diag) >> 1; \ + FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \ + } \ + } \ + /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \ + for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \ + UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \ + UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \ + CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \ + } \ + if (len > 1) { \ + const int left_over = ((len + 1) >> 1) - (pos >> 1); \ + uint8_t* const tmp_top_dst = r_u + 4 * 32; \ + uint8_t* const tmp_bottom_dst = tmp_top_dst + 4 * 32; \ + uint8_t* const tmp_top = tmp_bottom_dst + 4 * 32; \ + uint8_t* const tmp_bottom = (bottom_y == NULL) ? NULL : tmp_top + 32; \ + assert(left_over > 0); \ + UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \ + UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \ + memcpy(tmp_top, top_y + pos, len - pos); \ + if (bottom_y != NULL) memcpy(tmp_bottom, bottom_y + pos, len - pos); \ + CONVERT2RGB_32(FUNC, XSTEP, tmp_top, tmp_bottom, tmp_top_dst, \ + tmp_bottom_dst, 0); \ + memcpy(top_dst + pos * (XSTEP), tmp_top_dst, (len - pos) * (XSTEP)); \ + if (bottom_y != NULL) { \ + memcpy(bottom_dst + pos * (XSTEP), tmp_bottom_dst, \ + (len - pos) * (XSTEP)); \ + } \ + } \ +} + +// SSE4 variants of the fancy upsampler. +SSE4_UPSAMPLE_FUNC(UpsampleRgbLinePair_SSE41, VP8YuvToRgb, 3) +SSE4_UPSAMPLE_FUNC(UpsampleBgrLinePair_SSE41, VP8YuvToBgr, 3) + +#undef GET_M +#undef PACK_AND_STORE +#undef UPSAMPLE_32PIXELS +#undef UPSAMPLE_LAST_BLOCK +#undef CONVERT2RGB +#undef CONVERT2RGB_32 +#undef SSE4_UPSAMPLE_FUNC + +#endif // WEBP_REDUCE_CSP + +//------------------------------------------------------------------------------ +// Entry point + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +extern void WebPInitUpsamplersSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE41(void) { +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_SSE41; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_SSE41; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +//------------------------------------------------------------------------------ + +extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; +extern void WebPInitYUV444ConvertersSSE41(void); + +#define YUV444_FUNC(FUNC_NAME, CALL, CALL_C, XSTEP) \ +extern void CALL_C(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len); \ +static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + const int max_len = len & ~31; \ + for (i = 0; i < max_len; i += 32) { \ + CALL(y + i, u + i, v + i, dst + i * (XSTEP)); \ + } \ + if (i < len) { /* C-fallback */ \ + CALL_C(y + i, u + i, v + i, dst + i * (XSTEP), len - i); \ + } \ +} + +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(Yuv444ToRgb_SSE41, VP8YuvToRgb32_SSE41, WebPYuv444ToRgb_C, 3) +YUV444_FUNC(Yuv444ToBgr_SSE41, VP8YuvToBgr32_SSE41, WebPYuv444ToBgr_C, 3) +#endif // WEBP_REDUCE_CSP + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE41(void) { +#if !defined(WEBP_REDUCE_CSP) + WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb_SSE41; + WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr_SSE41; +#endif // WEBP_REDUCE_CSP +} + +#else + +WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE41) + +#endif // WEBP_USE_SSE41 + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE41)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE41) +#endif diff --git a/libraries/webp/src/dsp/yuv.c b/libraries/webp/src/dsp/yuv.c new file mode 100644 index 0000000000..8a04b85d82 --- /dev/null +++ b/libraries/webp/src/dsp/yuv.c @@ -0,0 +1,245 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#include +#include + +//----------------------------------------------------------------------------- +// Plain-C version + +#define ROW_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* y, \ + const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + const uint8_t* const end = dst + (len & ~1) * (XSTEP); \ + while (dst != end) { \ + FUNC(y[0], u[0], v[0], dst); \ + FUNC(y[1], u[0], v[0], dst + (XSTEP)); \ + y += 2; \ + ++u; \ + ++v; \ + dst += 2 * (XSTEP); \ + } \ + if (len & 1) { \ + FUNC(y[0], u[0], v[0], dst); \ + } \ +} \ + +// All variants implemented. +ROW_FUNC(YuvToRgbRow, VP8YuvToRgb, 3) +ROW_FUNC(YuvToBgrRow, VP8YuvToBgr, 3) +ROW_FUNC(YuvToRgbaRow, VP8YuvToRgba, 4) +ROW_FUNC(YuvToBgraRow, VP8YuvToBgra, 4) +ROW_FUNC(YuvToArgbRow, VP8YuvToArgb, 4) +ROW_FUNC(YuvToRgba4444Row, VP8YuvToRgba4444, 2) +ROW_FUNC(YuvToRgb565Row, VP8YuvToRgb565, 2) + +#undef ROW_FUNC + +// Main call for processing a plane with a WebPSamplerRowFunc function: +void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, + const uint8_t* u, const uint8_t* v, int uv_stride, + uint8_t* dst, int dst_stride, + int width, int height, WebPSamplerRowFunc func) { + int j; + for (j = 0; j < height; ++j) { + func(y, u, v, dst, width); + y += y_stride; + if (j & 1) { + u += uv_stride; + v += uv_stride; + } + dst += dst_stride; + } +} + +//----------------------------------------------------------------------------- +// Main call + +WebPSamplerRowFunc WebPSamplers[MODE_LAST]; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void WebPInitSamplersSSE2(void); +extern void WebPInitSamplersSSE41(void); +extern void WebPInitSamplersMIPS32(void); +extern void WebPInitSamplersMIPSdspR2(void); + +WEBP_DSP_INIT_FUNC(WebPInitSamplers) { + WebPSamplers[MODE_RGB] = YuvToRgbRow; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow; + WebPSamplers[MODE_BGR] = YuvToBgrRow; + WebPSamplers[MODE_BGRA] = YuvToBgraRow; + WebPSamplers[MODE_ARGB] = YuvToArgbRow; + WebPSamplers[MODE_RGBA_4444] = YuvToRgba4444Row; + WebPSamplers[MODE_RGB_565] = YuvToRgb565Row; + WebPSamplers[MODE_rgbA] = YuvToRgbaRow; + WebPSamplers[MODE_bgrA] = YuvToBgraRow; + WebPSamplers[MODE_Argb] = YuvToArgbRow; + WebPSamplers[MODE_rgbA_4444] = YuvToRgba4444Row; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitSamplersSSE2(); + } +#endif // WEBP_HAVE_SSE2 +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitSamplersSSE41(); + } +#endif // WEBP_HAVE_SSE41 +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + WebPInitSamplersMIPS32(); + } +#endif // WEBP_USE_MIPS32 +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPInitSamplersMIPSdspR2(); + } +#endif // WEBP_USE_MIPS_DSP_R2 + } +} + +//----------------------------------------------------------------------------- +// ARGB -> YUV converters + +static void ConvertARGBToY_C(const uint32_t* argb, uint8_t* y, int width) { + int i; + for (i = 0; i < width; ++i) { + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store) { + // No rounding. Last pixel is dealt with separately. + const int uv_width = src_width >> 1; + int i; + for (i = 0; i < uv_width; ++i) { + const uint32_t v0 = argb[2 * i + 0]; + const uint32_t v1 = argb[2 * i + 1]; + // VP8RGBToU/V expects four accumulated pixels. Hence we need to + // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. + const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe); + const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe); + const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe); + const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); + const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); + if (do_store) { + u[i] = tmp_u; + v[i] = tmp_v; + } else { + // Approximated average-of-four. But it's an acceptable diff. + u[i] = (u[i] + tmp_u + 1) >> 1; + v[i] = (v[i] + tmp_v + 1) >> 1; + } + } + if (src_width & 1) { // last pixel + const uint32_t v0 = argb[2 * i + 0]; + const int r = (v0 >> 14) & 0x3fc; + const int g = (v0 >> 6) & 0x3fc; + const int b = (v0 << 2) & 0x3fc; + const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); + const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); + if (do_store) { + u[i] = tmp_u; + v[i] = tmp_v; + } else { + u[i] = (u[i] + tmp_u + 1) >> 1; + v[i] = (v[i] + tmp_v + 1) >> 1; + } + } +} + +//----------------------------------------------------------------------------- + +static void ConvertRGB24ToY_C(const uint8_t* rgb, uint8_t* y, int width) { + int i; + for (i = 0; i < width; ++i, rgb += 3) { + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_C(const uint8_t* bgr, uint8_t* y, int width) { + int i; + for (i = 0; i < width; ++i, bgr += 3) { + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + int i; + for (i = 0; i < width; i += 1, rgb += 4) { + const int r = rgb[0], g = rgb[1], b = rgb[2]; + u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); + v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); + } +} + +//----------------------------------------------------------------------------- + +void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); +void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); +void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width); + +void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); +void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store); + +extern void WebPInitConvertARGBToYUVSSE2(void); +extern void WebPInitConvertARGBToYUVSSE41(void); +extern void WebPInitConvertARGBToYUVNEON(void); + +WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) { + WebPConvertARGBToY = ConvertARGBToY_C; + WebPConvertARGBToUV = WebPConvertARGBToUV_C; + + WebPConvertRGB24ToY = ConvertRGB24ToY_C; + WebPConvertBGR24ToY = ConvertBGR24ToY_C; + + WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C; + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitConvertARGBToYUVSSE2(); + } +#endif // WEBP_HAVE_SSE2 +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitConvertARGBToYUVSSE41(); + } +#endif // WEBP_HAVE_SSE41 + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitConvertARGBToYUVNEON(); + } +#endif // WEBP_HAVE_NEON + + assert(WebPConvertARGBToY != NULL); + assert(WebPConvertARGBToUV != NULL); + assert(WebPConvertRGB24ToY != NULL); + assert(WebPConvertBGR24ToY != NULL); + assert(WebPConvertRGBA32ToUV != NULL); +} diff --git a/libraries/webp/src/dsp/yuv.h b/libraries/webp/src/dsp/yuv.h new file mode 100644 index 0000000000..66a397d117 --- /dev/null +++ b/libraries/webp/src/dsp/yuv.h @@ -0,0 +1,210 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// inline YUV<->RGB conversion function +// +// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. +// More information at: https://en.wikipedia.org/wiki/YCbCr +// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 +// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 +// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 +// We use 16bit fixed point operations for RGB->YUV conversion (YUV_FIX). +// +// For the Y'CbCr to RGB conversion, the BT.601 specification reads: +// R = 1.164 * (Y-16) + 1.596 * (V-128) +// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) +// B = 1.164 * (Y-16) + 2.018 * (U-128) +// where Y is in the [16,235] range, and U/V in the [16,240] range. +// +// The fixed-point implementation used here is: +// R = (19077 . y + 26149 . v - 14234) >> 6 +// G = (19077 . y - 6419 . u - 13320 . v + 8708) >> 6 +// B = (19077 . y + 33050 . u - 17685) >> 6 +// where the '.' operator is the mulhi_epu16 variant: +// a . b = ((a << 8) * b) >> 16 +// that preserves 8 bits of fractional precision before final descaling. + +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DSP_YUV_H_ +#define WEBP_DSP_YUV_H_ + +#include "src/dsp/dsp.h" +#include "src/dec/vp8_dec.h" + +//------------------------------------------------------------------------------ +// YUV -> RGB conversion + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + YUV_FIX = 16, // fixed-point precision for RGB->YUV + YUV_HALF = 1 << (YUV_FIX - 1), + + YUV_FIX2 = 6, // fixed-point precision for YUV->RGB + YUV_MASK2 = (256 << YUV_FIX2) - 1 +}; + +//------------------------------------------------------------------------------ +// slower on x86 by ~7-8%, but bit-exact with the SSE2/NEON version + +static WEBP_INLINE int MultHi(int v, int coeff) { // _mm_mulhi_epu16 emulation + return (v * coeff) >> 8; +} + +static WEBP_INLINE int VP8Clip8(int v) { + return ((v & ~YUV_MASK2) == 0) ? (v >> YUV_FIX2) : (v < 0) ? 0 : 255; +} + +static WEBP_INLINE int VP8YUVToR(int y, int v) { + return VP8Clip8(MultHi(y, 19077) + MultHi(v, 26149) - 14234); +} + +static WEBP_INLINE int VP8YUVToG(int y, int u, int v) { + return VP8Clip8(MultHi(y, 19077) - MultHi(u, 6419) - MultHi(v, 13320) + 8708); +} + +static WEBP_INLINE int VP8YUVToB(int y, int u) { + return VP8Clip8(MultHi(y, 19077) + MultHi(u, 33050) - 17685); +} + +static WEBP_INLINE void VP8YuvToRgb(int y, int u, int v, + uint8_t* const rgb) { + rgb[0] = VP8YUVToR(y, v); + rgb[1] = VP8YUVToG(y, u, v); + rgb[2] = VP8YUVToB(y, u); +} + +static WEBP_INLINE void VP8YuvToBgr(int y, int u, int v, + uint8_t* const bgr) { + bgr[0] = VP8YUVToB(y, u); + bgr[1] = VP8YUVToG(y, u, v); + bgr[2] = VP8YUVToR(y, v); +} + +static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v, + uint8_t* const rgb) { + const int r = VP8YUVToR(y, v); // 5 usable bits + const int g = VP8YUVToG(y, u, v); // 6 usable bits + const int b = VP8YUVToB(y, u); // 5 usable bits + const int rg = (r & 0xf8) | (g >> 5); + const int gb = ((g << 3) & 0xe0) | (b >> 3); +#if (WEBP_SWAP_16BIT_CSP == 1) + rgb[0] = gb; + rgb[1] = rg; +#else + rgb[0] = rg; + rgb[1] = gb; +#endif +} + +static WEBP_INLINE void VP8YuvToRgba4444(int y, int u, int v, + uint8_t* const argb) { + const int r = VP8YUVToR(y, v); // 4 usable bits + const int g = VP8YUVToG(y, u, v); // 4 usable bits + const int b = VP8YUVToB(y, u); // 4 usable bits + const int rg = (r & 0xf0) | (g >> 4); + const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits +#if (WEBP_SWAP_16BIT_CSP == 1) + argb[0] = ba; + argb[1] = rg; +#else + argb[0] = rg; + argb[1] = ba; +#endif +} + +//----------------------------------------------------------------------------- +// Alpha handling variants + +static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const argb) { + argb[0] = 0xff; + VP8YuvToRgb(y, u, v, argb + 1); +} + +static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const bgra) { + VP8YuvToBgr(y, u, v, bgra); + bgra[3] = 0xff; +} + +static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const rgba) { + VP8YuvToRgb(y, u, v, rgba); + rgba[3] = 0xff; +} + +//----------------------------------------------------------------------------- +// SSE2 extra functions (mostly for upsampling_sse2.c) + +#if defined(WEBP_USE_SSE2) + +// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst. +void VP8YuvToRgba32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToRgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToBgra32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToBgr32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToArgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToRgba444432_SSE2(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst); +void VP8YuvToRgb56532_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); + +#endif // WEBP_USE_SSE2 + +//----------------------------------------------------------------------------- +// SSE41 extra functions (mostly for upsampling_sse41.c) + +#if defined(WEBP_USE_SSE41) + +// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst. +void VP8YuvToRgb32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToBgr32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); + +#endif // WEBP_USE_SSE41 + +//------------------------------------------------------------------------------ +// RGB -> YUV conversion + +// Stub functions that can be called with various rounding values: +static WEBP_INLINE int VP8ClipUV(int uv, int rounding) { + uv = (uv + rounding + (128 << (YUV_FIX + 2))) >> (YUV_FIX + 2); + return ((uv & ~0xff) == 0) ? uv : (uv < 0) ? 0 : 255; +} + +static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) { + const int luma = 16839 * r + 33059 * g + 6420 * b; + return (luma + rounding + (16 << YUV_FIX)) >> YUV_FIX; // no need to clip +} + +static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) { + const int u = -9719 * r - 19081 * g + 28800 * b; + return VP8ClipUV(u, rounding); +} + +static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { + const int v = +28800 * r - 24116 * g - 4684 * b; + return VP8ClipUV(v, rounding); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_YUV_H_ diff --git a/libraries/webp/src/dsp/yuv_mips32.c b/libraries/webp/src/dsp/yuv_mips32.c new file mode 100644 index 0000000000..9d0a887824 --- /dev/null +++ b/libraries/webp/src/dsp/yuv_mips32.c @@ -0,0 +1,103 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of YUV to RGB upsampling functions. +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) + +#include "src/dsp/yuv.h" + +//------------------------------------------------------------------------------ +// simple point-sampling + +#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \ +static void FUNC_NAME(const uint8_t* y, \ + const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i, r, g, b; \ + int temp0, temp1, temp2, temp3, temp4; \ + for (i = 0; i < (len >> 1); i++) { \ + temp1 = MultHi(v[0], 26149); \ + temp3 = MultHi(v[0], 13320); \ + temp2 = MultHi(u[0], 6419); \ + temp4 = MultHi(u[0], 33050); \ + temp0 = MultHi(y[0], 19077); \ + temp1 -= 14234; \ + temp3 -= 8708; \ + temp2 += temp3; \ + temp4 -= 17685; \ + r = VP8Clip8(temp0 + temp1); \ + g = VP8Clip8(temp0 - temp2); \ + b = VP8Clip8(temp0 + temp4); \ + temp0 = MultHi(y[1], 19077); \ + dst[R] = r; \ + dst[G] = g; \ + dst[B] = b; \ + if (A) dst[A] = 0xff; \ + r = VP8Clip8(temp0 + temp1); \ + g = VP8Clip8(temp0 - temp2); \ + b = VP8Clip8(temp0 + temp4); \ + dst[R + XSTEP] = r; \ + dst[G + XSTEP] = g; \ + dst[B + XSTEP] = b; \ + if (A) dst[A + XSTEP] = 0xff; \ + y += 2; \ + ++u; \ + ++v; \ + dst += 2 * XSTEP; \ + } \ + if (len & 1) { \ + temp1 = MultHi(v[0], 26149); \ + temp3 = MultHi(v[0], 13320); \ + temp2 = MultHi(u[0], 6419); \ + temp4 = MultHi(u[0], 33050); \ + temp0 = MultHi(y[0], 19077); \ + temp1 -= 14234; \ + temp3 -= 8708; \ + temp2 += temp3; \ + temp4 -= 17685; \ + r = VP8Clip8(temp0 + temp1); \ + g = VP8Clip8(temp0 - temp2); \ + b = VP8Clip8(temp0 + temp4); \ + dst[R] = r; \ + dst[G] = g; \ + dst[B] = b; \ + if (A) dst[A] = 0xff; \ + } \ +} + +ROW_FUNC(YuvToRgbRow_MIPS32, 3, 0, 1, 2, 0) +ROW_FUNC(YuvToRgbaRow_MIPS32, 4, 0, 1, 2, 3) +ROW_FUNC(YuvToBgrRow_MIPS32, 3, 2, 1, 0, 0) +ROW_FUNC(YuvToBgraRow_MIPS32, 4, 2, 1, 0, 3) + +#undef ROW_FUNC + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPS32(void) { + WebPSamplers[MODE_RGB] = YuvToRgbRow_MIPS32; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_MIPS32; + WebPSamplers[MODE_BGR] = YuvToBgrRow_MIPS32; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_MIPS32; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(WebPInitSamplersMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/libraries/webp/src/dsp/yuv_mips_dsp_r2.c b/libraries/webp/src/dsp/yuv_mips_dsp_r2.c new file mode 100644 index 0000000000..cc8afcc756 --- /dev/null +++ b/libraries/webp/src/dsp/yuv_mips_dsp_r2.c @@ -0,0 +1,134 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS DSPr2 version of YUV to RGB upsampling functions. +// +// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) +// Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/yuv.h" + +//------------------------------------------------------------------------------ +// simple point-sampling + +#define ROW_FUNC_PART_1() \ + "lbu %[temp3], 0(%[v]) \n\t" \ + "lbu %[temp4], 0(%[u]) \n\t" \ + "lbu %[temp0], 0(%[y]) \n\t" \ + "mul %[temp1], %[t_con_1], %[temp3] \n\t" \ + "mul %[temp3], %[t_con_2], %[temp3] \n\t" \ + "mul %[temp2], %[t_con_3], %[temp4] \n\t" \ + "mul %[temp4], %[t_con_4], %[temp4] \n\t" \ + "mul %[temp0], %[t_con_5], %[temp0] \n\t" \ + "subu %[temp1], %[temp1], %[t_con_6] \n\t" \ + "subu %[temp3], %[temp3], %[t_con_7] \n\t" \ + "addu %[temp2], %[temp2], %[temp3] \n\t" \ + "subu %[temp4], %[temp4], %[t_con_8] \n\t" \ + +#define ROW_FUNC_PART_2(R, G, B, K) \ + "addu %[temp5], %[temp0], %[temp1] \n\t" \ + "subu %[temp6], %[temp0], %[temp2] \n\t" \ + "addu %[temp7], %[temp0], %[temp4] \n\t" \ +".if " #K " \n\t" \ + "lbu %[temp0], 1(%[y]) \n\t" \ +".endif \n\t" \ + "shll_s.w %[temp5], %[temp5], 17 \n\t" \ + "shll_s.w %[temp6], %[temp6], 17 \n\t" \ +".if " #K " \n\t" \ + "mul %[temp0], %[t_con_5], %[temp0] \n\t" \ +".endif \n\t" \ + "shll_s.w %[temp7], %[temp7], 17 \n\t" \ + "precrqu_s.qb.ph %[temp5], %[temp5], $zero \n\t" \ + "precrqu_s.qb.ph %[temp6], %[temp6], $zero \n\t" \ + "precrqu_s.qb.ph %[temp7], %[temp7], $zero \n\t" \ + "srl %[temp5], %[temp5], 24 \n\t" \ + "srl %[temp6], %[temp6], 24 \n\t" \ + "srl %[temp7], %[temp7], 24 \n\t" \ + "sb %[temp5], " #R "(%[dst]) \n\t" \ + "sb %[temp6], " #G "(%[dst]) \n\t" \ + "sb %[temp7], " #B "(%[dst]) \n\t" \ + +#define ASM_CLOBBER_LIST() \ + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) \ + : [t_con_1]"r"(t_con_1), [t_con_2]"r"(t_con_2), [t_con_3]"r"(t_con_3), \ + [t_con_4]"r"(t_con_4), [t_con_5]"r"(t_con_5), [t_con_6]"r"(t_con_6), \ + [u]"r"(u), [v]"r"(v), [y]"r"(y), [dst]"r"(dst), \ + [t_con_7]"r"(t_con_7), [t_con_8]"r"(t_con_8) \ + : "memory", "hi", "lo" \ + +#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \ +static void FUNC_NAME(const uint8_t* y, \ + const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \ + const int t_con_1 = 26149; \ + const int t_con_2 = 13320; \ + const int t_con_3 = 6419; \ + const int t_con_4 = 33050; \ + const int t_con_5 = 19077; \ + const int t_con_6 = 14234; \ + const int t_con_7 = 8708; \ + const int t_con_8 = 17685; \ + for (i = 0; i < (len >> 1); i++) { \ + __asm__ volatile ( \ + ROW_FUNC_PART_1() \ + ROW_FUNC_PART_2(R, G, B, 1) \ + ROW_FUNC_PART_2(R + XSTEP, G + XSTEP, B + XSTEP, 0) \ + ASM_CLOBBER_LIST() \ + ); \ + if (A) dst[A] = dst[A + XSTEP] = 0xff; \ + y += 2; \ + ++u; \ + ++v; \ + dst += 2 * XSTEP; \ + } \ + if (len & 1) { \ + __asm__ volatile ( \ + ROW_FUNC_PART_1() \ + ROW_FUNC_PART_2(R, G, B, 0) \ + ASM_CLOBBER_LIST() \ + ); \ + if (A) dst[A] = 0xff; \ + } \ +} + +ROW_FUNC(YuvToRgbRow_MIPSdspR2, 3, 0, 1, 2, 0) +ROW_FUNC(YuvToRgbaRow_MIPSdspR2, 4, 0, 1, 2, 3) +ROW_FUNC(YuvToBgrRow_MIPSdspR2, 3, 2, 1, 0, 0) +ROW_FUNC(YuvToBgraRow_MIPSdspR2, 4, 2, 1, 0, 3) + +#undef ROW_FUNC +#undef ASM_CLOBBER_LIST +#undef ROW_FUNC_PART_2 +#undef ROW_FUNC_PART_1 + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPSdspR2(void) { + WebPSamplers[MODE_RGB] = YuvToRgbRow_MIPSdspR2; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_MIPSdspR2; + WebPSamplers[MODE_BGR] = YuvToBgrRow_MIPSdspR2; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(WebPInitSamplersMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/libraries/webp/src/dsp/yuv_neon.c b/libraries/webp/src/dsp/yuv_neon.c new file mode 100644 index 0000000000..ff77b00980 --- /dev/null +++ b/libraries/webp/src/dsp/yuv_neon.c @@ -0,0 +1,180 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#if defined(WEBP_USE_NEON) + +#include +#include + +#include "src/dsp/neon.h" + +//----------------------------------------------------------------------------- + +static uint8x8_t ConvertRGBToY_NEON(const uint8x8_t R, + const uint8x8_t G, + const uint8x8_t B) { + const uint16x8_t r = vmovl_u8(R); + const uint16x8_t g = vmovl_u8(G); + const uint16x8_t b = vmovl_u8(B); + const uint16x4_t r_lo = vget_low_u16(r); + const uint16x4_t r_hi = vget_high_u16(r); + const uint16x4_t g_lo = vget_low_u16(g); + const uint16x4_t g_hi = vget_high_u16(g); + const uint16x4_t b_lo = vget_low_u16(b); + const uint16x4_t b_hi = vget_high_u16(b); + const uint32x4_t tmp0_lo = vmull_n_u16( r_lo, 16839u); + const uint32x4_t tmp0_hi = vmull_n_u16( r_hi, 16839u); + const uint32x4_t tmp1_lo = vmlal_n_u16(tmp0_lo, g_lo, 33059u); + const uint32x4_t tmp1_hi = vmlal_n_u16(tmp0_hi, g_hi, 33059u); + const uint32x4_t tmp2_lo = vmlal_n_u16(tmp1_lo, b_lo, 6420u); + const uint32x4_t tmp2_hi = vmlal_n_u16(tmp1_hi, b_hi, 6420u); + const uint16x8_t Y1 = vcombine_u16(vrshrn_n_u32(tmp2_lo, 16), + vrshrn_n_u32(tmp2_hi, 16)); + const uint16x8_t Y2 = vaddq_u16(Y1, vdupq_n_u16(16)); + return vqmovn_u16(Y2); +} + +static void ConvertRGB24ToY_NEON(const uint8_t* rgb, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, rgb += 3 * 8) { + const uint8x8x3_t RGB = vld3_u8(rgb); + const uint8x8_t Y = ConvertRGBToY_NEON(RGB.val[0], RGB.val[1], RGB.val[2]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i, rgb += 3) { // left-over + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_NEON(const uint8_t* bgr, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, bgr += 3 * 8) { + const uint8x8x3_t BGR = vld3_u8(bgr); + const uint8x8_t Y = ConvertRGBToY_NEON(BGR.val[2], BGR.val[1], BGR.val[0]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i, bgr += 3) { // left-over + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +static void ConvertARGBToY_NEON(const uint32_t* argb, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8) { + const uint8x8x4_t RGB = vld4_u8((const uint8_t*)&argb[i]); + const uint8x8_t Y = ConvertRGBToY_NEON(RGB.val[2], RGB.val[1], RGB.val[0]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i) { // left-over + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +//----------------------------------------------------------------------------- + +// computes: DST_s16 = [(C0 * r + C1 * g + C2 * b) >> 16] + CST +#define MULTIPLY_16b_PREAMBLE(r, g, b) \ + const int16x4_t r_lo = vreinterpret_s16_u16(vget_low_u16(r)); \ + const int16x4_t r_hi = vreinterpret_s16_u16(vget_high_u16(r)); \ + const int16x4_t g_lo = vreinterpret_s16_u16(vget_low_u16(g)); \ + const int16x4_t g_hi = vreinterpret_s16_u16(vget_high_u16(g)); \ + const int16x4_t b_lo = vreinterpret_s16_u16(vget_low_u16(b)); \ + const int16x4_t b_hi = vreinterpret_s16_u16(vget_high_u16(b)) + +#define MULTIPLY_16b(C0, C1, C2, CST, DST_s16) do { \ + const int32x4_t tmp0_lo = vmull_n_s16( r_lo, C0); \ + const int32x4_t tmp0_hi = vmull_n_s16( r_hi, C0); \ + const int32x4_t tmp1_lo = vmlal_n_s16(tmp0_lo, g_lo, C1); \ + const int32x4_t tmp1_hi = vmlal_n_s16(tmp0_hi, g_hi, C1); \ + const int32x4_t tmp2_lo = vmlal_n_s16(tmp1_lo, b_lo, C2); \ + const int32x4_t tmp2_hi = vmlal_n_s16(tmp1_hi, b_hi, C2); \ + const int16x8_t tmp3 = vcombine_s16(vshrn_n_s32(tmp2_lo, 16), \ + vshrn_n_s32(tmp2_hi, 16)); \ + DST_s16 = vaddq_s16(tmp3, vdupq_n_s16(CST)); \ +} while (0) + +// This needs to be a macro, since (128 << SHIFT) needs to be an immediate. +#define CONVERT_RGB_TO_UV(r, g, b, SHIFT, U_DST, V_DST) do { \ + MULTIPLY_16b_PREAMBLE(r, g, b); \ + MULTIPLY_16b(-9719, -19081, 28800, 128 << SHIFT, U_DST); \ + MULTIPLY_16b(28800, -24116, -4684, 128 << SHIFT, V_DST); \ +} while (0) + +static void ConvertRGBA32ToUV_NEON(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, rgb += 4 * 8) { + const uint16x8x4_t RGB = vld4q_u16((const uint16_t*)rgb); + int16x8_t U, V; + CONVERT_RGB_TO_UV(RGB.val[0], RGB.val[1], RGB.val[2], 2, U, V); + vst1_u8(u + i, vqrshrun_n_s16(U, 2)); + vst1_u8(v + i, vqrshrun_n_s16(V, 2)); + } + for (; i < width; i += 1, rgb += 4) { + const int r = rgb[0], g = rgb[1], b = rgb[2]; + u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); + v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); + } +} + +static void ConvertARGBToUV_NEON(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store) { + int i; + for (i = 0; i + 16 <= src_width; i += 16, u += 8, v += 8) { + const uint8x16x4_t RGB = vld4q_u8((const uint8_t*)&argb[i]); + const uint16x8_t R = vpaddlq_u8(RGB.val[2]); // pair-wise adds + const uint16x8_t G = vpaddlq_u8(RGB.val[1]); + const uint16x8_t B = vpaddlq_u8(RGB.val[0]); + int16x8_t U_tmp, V_tmp; + CONVERT_RGB_TO_UV(R, G, B, 1, U_tmp, V_tmp); + { + const uint8x8_t U = vqrshrun_n_s16(U_tmp, 1); + const uint8x8_t V = vqrshrun_n_s16(V_tmp, 1); + if (do_store) { + vst1_u8(u, U); + vst1_u8(v, V); + } else { + const uint8x8_t prev_u = vld1_u8(u); + const uint8x8_t prev_v = vld1_u8(v); + vst1_u8(u, vrhadd_u8(U, prev_u)); + vst1_u8(v, vrhadd_u8(V, prev_v)); + } + } + } + if (i < src_width) { // left-over + WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); + } +} + + +//------------------------------------------------------------------------------ + +extern void WebPInitConvertARGBToYUVNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVNEON(void) { + WebPConvertRGB24ToY = ConvertRGB24ToY_NEON; + WebPConvertBGR24ToY = ConvertBGR24ToY_NEON; + WebPConvertARGBToY = ConvertARGBToY_NEON; + WebPConvertARGBToUV = ConvertARGBToUV_NEON; + WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVNEON) + +#endif // WEBP_USE_NEON diff --git a/libraries/webp/src/dsp/yuv_sse2.c b/libraries/webp/src/dsp/yuv_sse2.c new file mode 100644 index 0000000000..01a48f9af2 --- /dev/null +++ b/libraries/webp/src/dsp/yuv_sse2.c @@ -0,0 +1,758 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include + +#include "src/dsp/common_sse2.h" +#include "src/utils/utils.h" + +//----------------------------------------------------------------------------- +// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. + +// These constants are 14b fixed-point version of ITU-R BT.601 constants. +// R = (19077 * y + 26149 * v - 14234) >> 6 +// G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 +// B = (19077 * y + 33050 * u - 17685) >> 6 +static void ConvertYUV444ToRGB_SSE2(const __m128i* const Y0, + const __m128i* const U0, + const __m128i* const V0, + __m128i* const R, + __m128i* const G, + __m128i* const B) { + const __m128i k19077 = _mm_set1_epi16(19077); + const __m128i k26149 = _mm_set1_epi16(26149); + const __m128i k14234 = _mm_set1_epi16(14234); + // 33050 doesn't fit in a signed short: only use this with unsigned arithmetic + const __m128i k33050 = _mm_set1_epi16((short)33050); + const __m128i k17685 = _mm_set1_epi16(17685); + const __m128i k6419 = _mm_set1_epi16(6419); + const __m128i k13320 = _mm_set1_epi16(13320); + const __m128i k8708 = _mm_set1_epi16(8708); + + const __m128i Y1 = _mm_mulhi_epu16(*Y0, k19077); + + const __m128i R0 = _mm_mulhi_epu16(*V0, k26149); + const __m128i R1 = _mm_sub_epi16(Y1, k14234); + const __m128i R2 = _mm_add_epi16(R1, R0); + + const __m128i G0 = _mm_mulhi_epu16(*U0, k6419); + const __m128i G1 = _mm_mulhi_epu16(*V0, k13320); + const __m128i G2 = _mm_add_epi16(Y1, k8708); + const __m128i G3 = _mm_add_epi16(G0, G1); + const __m128i G4 = _mm_sub_epi16(G2, G3); + + // be careful with the saturated *unsigned* arithmetic here! + const __m128i B0 = _mm_mulhi_epu16(*U0, k33050); + const __m128i B1 = _mm_adds_epu16(B0, Y1); + const __m128i B2 = _mm_subs_epu16(B1, k17685); + + // use logical shift for B2, which can be larger than 32767 + *R = _mm_srai_epi16(R2, 6); // range: [-14234, 30815] + *G = _mm_srai_epi16(G4, 6); // range: [-10953, 27710] + *B = _mm_srli_epi16(B2, 6); // range: [0, 34238] +} + +// Load the bytes into the *upper* part of 16b words. That's "<< 8", basically. +static WEBP_INLINE __m128i Load_HI_16_SSE2(const uint8_t* src) { + const __m128i zero = _mm_setzero_si128(); + return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src)); +} + +// Load and replicate the U/V samples +static WEBP_INLINE __m128i Load_UV_HI_8_SSE2(const uint8_t* src) { + const __m128i zero = _mm_setzero_si128(); + const __m128i tmp0 = _mm_cvtsi32_si128(WebPMemToInt32(src)); + const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); + return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples +} + +// Convert 32 samples of YUV444 to R/G/B +static void YUV444ToRGB_SSE2(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE2(y), U0 = Load_HI_16_SSE2(u), + V0 = Load_HI_16_SSE2(v); + ConvertYUV444ToRGB_SSE2(&Y0, &U0, &V0, R, G, B); +} + +// Convert 32 samples of YUV420 to R/G/B +static void YUV420ToRGB_SSE2(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE2(y), U0 = Load_UV_HI_8_SSE2(u), + V0 = Load_UV_HI_8_SSE2(v); + ConvertYUV444ToRGB_SSE2(&Y0, &U0, &V0, R, G, B); +} + +// Pack R/G/B/A results into 32b output. +static WEBP_INLINE void PackAndStore4_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + const __m128i* const A, + uint8_t* const dst) { + const __m128i rb = _mm_packus_epi16(*R, *B); + const __m128i ga = _mm_packus_epi16(*G, *A); + const __m128i rg = _mm_unpacklo_epi8(rb, ga); + const __m128i ba = _mm_unpackhi_epi8(rb, ga); + const __m128i RGBA_lo = _mm_unpacklo_epi16(rg, ba); + const __m128i RGBA_hi = _mm_unpackhi_epi16(rg, ba); + _mm_storeu_si128((__m128i*)(dst + 0), RGBA_lo); + _mm_storeu_si128((__m128i*)(dst + 16), RGBA_hi); +} + +// Pack R/G/B/A results into 16b output. +static WEBP_INLINE void PackAndStore4444_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + const __m128i* const A, + uint8_t* const dst) { +#if (WEBP_SWAP_16BIT_CSP == 0) + const __m128i rg0 = _mm_packus_epi16(*R, *G); + const __m128i ba0 = _mm_packus_epi16(*B, *A); +#else + const __m128i rg0 = _mm_packus_epi16(*B, *A); + const __m128i ba0 = _mm_packus_epi16(*R, *G); +#endif + const __m128i mask_0xf0 = _mm_set1_epi8((char)0xf0); + const __m128i rb1 = _mm_unpacklo_epi8(rg0, ba0); // rbrbrbrbrb... + const __m128i ga1 = _mm_unpackhi_epi8(rg0, ba0); // gagagagaga... + const __m128i rb2 = _mm_and_si128(rb1, mask_0xf0); + const __m128i ga2 = _mm_srli_epi16(_mm_and_si128(ga1, mask_0xf0), 4); + const __m128i rgba4444 = _mm_or_si128(rb2, ga2); + _mm_storeu_si128((__m128i*)dst, rgba4444); +} + +// Pack R/G/B results into 16b output. +static WEBP_INLINE void PackAndStore565_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + uint8_t* const dst) { + const __m128i r0 = _mm_packus_epi16(*R, *R); + const __m128i g0 = _mm_packus_epi16(*G, *G); + const __m128i b0 = _mm_packus_epi16(*B, *B); + const __m128i r1 = _mm_and_si128(r0, _mm_set1_epi8((char)0xf8)); + const __m128i b1 = _mm_and_si128(_mm_srli_epi16(b0, 3), _mm_set1_epi8(0x1f)); + const __m128i g1 = + _mm_srli_epi16(_mm_and_si128(g0, _mm_set1_epi8((char)0xe0)), 5); + const __m128i g2 = _mm_slli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0x1c)), 3); + const __m128i rg = _mm_or_si128(r1, g1); + const __m128i gb = _mm_or_si128(g2, b1); +#if (WEBP_SWAP_16BIT_CSP == 0) + const __m128i rgb565 = _mm_unpacklo_epi8(rg, gb); +#else + const __m128i rgb565 = _mm_unpacklo_epi8(gb, rg); +#endif + _mm_storeu_si128((__m128i*)dst, rgb565); +} + +// Pack the planar buffers +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... +static WEBP_INLINE void PlanarTo24b_SSE2(__m128i* const in0, __m128i* const in1, + __m128i* const in2, __m128i* const in3, + __m128i* const in4, __m128i* const in5, + uint8_t* const rgb) { + // The input is 6 registers of sixteen 8b but for the sake of explanation, + // let's take 6 registers of four 8b values. + // To pack, we will keep taking one every two 8b integer and move it + // around as follows: + // Input: + // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 + // Split the 6 registers in two sets of 3 registers: the first set as the even + // 8b bytes, the second the odd ones: + // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 + // Repeat the same permutations twice more: + // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 + // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 + VP8PlanarTo24b_SSE2(in0, in1, in2, in3, in4, in5); + + _mm_storeu_si128((__m128i*)(rgb + 0), *in0); + _mm_storeu_si128((__m128i*)(rgb + 16), *in1); + _mm_storeu_si128((__m128i*)(rgb + 32), *in2); + _mm_storeu_si128((__m128i*)(rgb + 48), *in3); + _mm_storeu_si128((__m128i*)(rgb + 64), *in4); + _mm_storeu_si128((__m128i*)(rgb + 80), *in5); +} + +void VP8YuvToRgba32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 32) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&R, &G, &B, &kAlpha, dst); + } +} + +void VP8YuvToBgra32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 32) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&B, &G, &R, &kAlpha, dst); + } +} + +void VP8YuvToArgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 32) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&kAlpha, &R, &G, &B, dst); + } +} + +void VP8YuvToRgba444432_SSE2(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 16) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4444_SSE2(&R, &G, &B, &kAlpha, dst); + } +} + +void VP8YuvToRgb56532_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + int n; + for (n = 0; n < 32; n += 8, dst += 16) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore565_SSE2(&R, &G, &B, dst); + } +} + +void VP8YuvToRgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; + + YUV444ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE2(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE2(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE2(y + 24, u + 24, v + 24, &R3, &G3, &B3); + + // Cast to 8b and store as RRRRGGGGBBBB. + rgb0 = _mm_packus_epi16(R0, R1); + rgb1 = _mm_packus_epi16(R2, R3); + rgb2 = _mm_packus_epi16(G0, G1); + rgb3 = _mm_packus_epi16(G2, G3); + rgb4 = _mm_packus_epi16(B0, B1); + rgb5 = _mm_packus_epi16(B2, B3); + + // Pack as RGBRGBRGBRGB. + PlanarTo24b_SSE2(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); +} + +void VP8YuvToBgr32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; + + YUV444ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE2(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE2(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE2(y + 24, u + 24, v + 24, &R3, &G3, &B3); + + // Cast to 8b and store as BBBBGGGGRRRR. + bgr0 = _mm_packus_epi16(B0, B1); + bgr1 = _mm_packus_epi16(B2, B3); + bgr2 = _mm_packus_epi16(G0, G1); + bgr3 = _mm_packus_epi16(G2, G3); + bgr4 = _mm_packus_epi16(R0, R1); + bgr5= _mm_packus_epi16(R2, R3); + + // Pack as BGRBGRBGRBGR. + PlanarTo24b_SSE2(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); +} + +//----------------------------------------------------------------------------- +// Arbitrary-length row conversion functions + +static void YuvToRgbaRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n + 8 <= len; n += 8, dst += 32) { + __m128i R, G, B; + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&R, &G, &B, &kAlpha, dst); + y += 8; + u += 4; + v += 4; + } + for (; n < len; ++n) { // Finish off + VP8YuvToRgba(y[0], u[0], v[0], dst); + dst += 4; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToBgraRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n + 8 <= len; n += 8, dst += 32) { + __m128i R, G, B; + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&B, &G, &R, &kAlpha, dst); + y += 8; + u += 4; + v += 4; + } + for (; n < len; ++n) { // Finish off + VP8YuvToBgra(y[0], u[0], v[0], dst); + dst += 4; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToArgbRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n + 8 <= len; n += 8, dst += 32) { + __m128i R, G, B; + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&kAlpha, &R, &G, &B, dst); + y += 8; + u += 4; + v += 4; + } + for (; n < len; ++n) { // Finish off + VP8YuvToArgb(y[0], u[0], v[0], dst); + dst += 4; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToRgbRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; + + YUV420ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE2(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE2(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE2(y + 24, u + 12, v + 12, &R3, &G3, &B3); + + // Cast to 8b and store as RRRRGGGGBBBB. + rgb0 = _mm_packus_epi16(R0, R1); + rgb1 = _mm_packus_epi16(R2, R3); + rgb2 = _mm_packus_epi16(G0, G1); + rgb3 = _mm_packus_epi16(G2, G3); + rgb4 = _mm_packus_epi16(B0, B1); + rgb5 = _mm_packus_epi16(B2, B3); + + // Pack as RGBRGBRGBRGB. + PlanarTo24b_SSE2(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); + + y += 32; + u += 16; + v += 16; + } + for (; n < len; ++n) { // Finish off + VP8YuvToRgb(y[0], u[0], v[0], dst); + dst += 3; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToBgrRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; + + YUV420ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE2(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE2(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE2(y + 24, u + 12, v + 12, &R3, &G3, &B3); + + // Cast to 8b and store as BBBBGGGGRRRR. + bgr0 = _mm_packus_epi16(B0, B1); + bgr1 = _mm_packus_epi16(B2, B3); + bgr2 = _mm_packus_epi16(G0, G1); + bgr3 = _mm_packus_epi16(G2, G3); + bgr4 = _mm_packus_epi16(R0, R1); + bgr5 = _mm_packus_epi16(R2, R3); + + // Pack as BGRBGRBGRBGR. + PlanarTo24b_SSE2(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); + + y += 32; + u += 16; + v += 16; + } + for (; n < len; ++n) { // Finish off + VP8YuvToBgr(y[0], u[0], v[0], dst); + dst += 3; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) { + WebPSamplers[MODE_RGB] = YuvToRgbRow_SSE2; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_SSE2; + WebPSamplers[MODE_BGR] = YuvToBgrRow_SSE2; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_SSE2; + WebPSamplers[MODE_ARGB] = YuvToArgbRow_SSE2; +} + +//------------------------------------------------------------------------------ +// RGB24/32 -> YUV converters + +// Load eight 16b-words from *src. +#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src)) +// Store either 16b-words into *dst +#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V)) + +// Function that inserts a value of the second half of the in buffer in between +// every two char of the first half. +static WEBP_INLINE void RGB24PackedToPlanarHelper_SSE2( + const __m128i* const in /*in[6]*/, __m128i* const out /*out[6]*/) { + out[0] = _mm_unpacklo_epi8(in[0], in[3]); + out[1] = _mm_unpackhi_epi8(in[0], in[3]); + out[2] = _mm_unpacklo_epi8(in[1], in[4]); + out[3] = _mm_unpackhi_epi8(in[1], in[4]); + out[4] = _mm_unpacklo_epi8(in[2], in[5]); + out[5] = _mm_unpackhi_epi8(in[2], in[5]); +} + +// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers: +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// Similar to PlanarTo24bHelper(), but in reverse order. +static WEBP_INLINE void RGB24PackedToPlanar_SSE2( + const uint8_t* const rgb, __m128i* const out /*out[6]*/) { + __m128i tmp[6]; + tmp[0] = _mm_loadu_si128((const __m128i*)(rgb + 0)); + tmp[1] = _mm_loadu_si128((const __m128i*)(rgb + 16)); + tmp[2] = _mm_loadu_si128((const __m128i*)(rgb + 32)); + tmp[3] = _mm_loadu_si128((const __m128i*)(rgb + 48)); + tmp[4] = _mm_loadu_si128((const __m128i*)(rgb + 64)); + tmp[5] = _mm_loadu_si128((const __m128i*)(rgb + 80)); + + RGB24PackedToPlanarHelper_SSE2(tmp, out); + RGB24PackedToPlanarHelper_SSE2(out, tmp); + RGB24PackedToPlanarHelper_SSE2(tmp, out); + RGB24PackedToPlanarHelper_SSE2(out, tmp); + RGB24PackedToPlanarHelper_SSE2(tmp, out); +} + +// Convert 8 packed ARGB to r[], g[], b[] +static WEBP_INLINE void RGB32PackedToPlanar_SSE2(const uint32_t* const argb, + __m128i* const rgb /*in[6]*/) { + const __m128i zero = _mm_setzero_si128(); + __m128i a0 = LOAD_16(argb + 0); + __m128i a1 = LOAD_16(argb + 4); + __m128i a2 = LOAD_16(argb + 8); + __m128i a3 = LOAD_16(argb + 12); + VP8L32bToPlanar_SSE2(&a0, &a1, &a2, &a3); + rgb[0] = _mm_unpacklo_epi8(a1, zero); + rgb[1] = _mm_unpackhi_epi8(a1, zero); + rgb[2] = _mm_unpacklo_epi8(a2, zero); + rgb[3] = _mm_unpackhi_epi8(a2, zero); + rgb[4] = _mm_unpacklo_epi8(a3, zero); + rgb[5] = _mm_unpackhi_epi8(a3, zero); +} + +// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX +// It's a macro and not a function because we need to use immediate values with +// srai_epi32, e.g. +#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \ + ROUNDER, DESCALE_FIX, OUT) do { \ + const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \ + const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \ + const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \ + const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \ + const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \ + const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \ + const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \ + const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \ + const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \ + const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \ + (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \ +} while (0) + +#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A)) +static WEBP_INLINE void ConvertRGBToY_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const Y) { + const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384); + const __m128i kGB_y = MK_CST_16(16384, 6420); + const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF); + + const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); + const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); + const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); + const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y); +} + +static WEBP_INLINE void ConvertRGBToUV_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const U, + __m128i* const V) { + const __m128i kRG_u = MK_CST_16(-9719, -19081); + const __m128i kGB_u = MK_CST_16(0, 28800); + const __m128i kRG_v = MK_CST_16(28800, 0); + const __m128i kGB_v = MK_CST_16(-24116, -4684); + const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2); + + const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); + const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); + const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); + const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u, + kHALF_UV, YUV_FIX + 2, *U); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v, + kHALF_UV, YUV_FIX + 2, *V); +} + +#undef MK_CST_16 +#undef TRANSFORM + +static void ConvertRGB24ToY_SSE2(const uint8_t* rgb, uint8_t* y, int width) { + const int max_width = width & ~31; + int i; + for (i = 0; i < max_width; rgb += 3 * 16 * 2) { + __m128i rgb_plane[6]; + int j; + + RGB24PackedToPlanar_SSE2(rgb, rgb_plane); + + for (j = 0; j < 2; ++j, i += 16) { + const __m128i zero = _mm_setzero_si128(); + __m128i r, g, b, Y0, Y1; + + // Convert to 16-bit Y. + r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero); + g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero); + b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero); + ConvertRGBToY_SSE2(&r, &g, &b, &Y0); + + // Convert to 16-bit Y. + r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero); + g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero); + b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero); + ConvertRGBToY_SSE2(&r, &g, &b, &Y1); + + // Cast to 8-bit and store. + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + } + for (; i < width; ++i, rgb += 3) { // left-over + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_SSE2(const uint8_t* bgr, uint8_t* y, int width) { + const int max_width = width & ~31; + int i; + for (i = 0; i < max_width; bgr += 3 * 16 * 2) { + __m128i bgr_plane[6]; + int j; + + RGB24PackedToPlanar_SSE2(bgr, bgr_plane); + + for (j = 0; j < 2; ++j, i += 16) { + const __m128i zero = _mm_setzero_si128(); + __m128i r, g, b, Y0, Y1; + + // Convert to 16-bit Y. + b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero); + g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero); + r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero); + ConvertRGBToY_SSE2(&r, &g, &b, &Y0); + + // Convert to 16-bit Y. + b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero); + g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero); + r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero); + ConvertRGBToY_SSE2(&r, &g, &b, &Y1); + + // Cast to 8-bit and store. + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + } + for (; i < width; ++i, bgr += 3) { // left-over + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +static void ConvertARGBToY_SSE2(const uint32_t* argb, uint8_t* y, int width) { + const int max_width = width & ~15; + int i; + for (i = 0; i < max_width; i += 16) { + __m128i Y0, Y1, rgb[6]; + RGB32PackedToPlanar_SSE2(&argb[i], rgb); + ConvertRGBToY_SSE2(&rgb[0], &rgb[2], &rgb[4], &Y0); + ConvertRGBToY_SSE2(&rgb[1], &rgb[3], &rgb[5], &Y1); + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + for (; i < width; ++i) { // left-over + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +// Horizontal add (doubled) of two 16b values, result is 16b. +// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ... +static void HorizontalAddPack_SSE2(const __m128i* const A, + const __m128i* const B, + __m128i* const out) { + const __m128i k2 = _mm_set1_epi16(2); + const __m128i C = _mm_madd_epi16(*A, k2); + const __m128i D = _mm_madd_epi16(*B, k2); + *out = _mm_packs_epi32(C, D); +} + +static void ConvertARGBToUV_SSE2(const uint32_t* argb, + uint8_t* u, uint8_t* v, + int src_width, int do_store) { + const int max_width = src_width & ~31; + int i; + for (i = 0; i < max_width; i += 32, u += 16, v += 16) { + __m128i rgb[6], U0, V0, U1, V1; + RGB32PackedToPlanar_SSE2(&argb[i], rgb); + HorizontalAddPack_SSE2(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE2(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE2(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE2(&rgb[0], &rgb[2], &rgb[4], &U0, &V0); + + RGB32PackedToPlanar_SSE2(&argb[i + 16], rgb); + HorizontalAddPack_SSE2(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE2(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE2(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE2(&rgb[0], &rgb[2], &rgb[4], &U1, &V1); + + U0 = _mm_packus_epi16(U0, U1); + V0 = _mm_packus_epi16(V0, V1); + if (!do_store) { + const __m128i prev_u = LOAD_16(u); + const __m128i prev_v = LOAD_16(v); + U0 = _mm_avg_epu8(U0, prev_u); + V0 = _mm_avg_epu8(V0, prev_v); + } + STORE_16(U0, u); + STORE_16(V0, v); + } + if (i < src_width) { // left-over + WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); + } +} + +// Convert 16 packed ARGB 16b-values to r[], g[], b[] +static WEBP_INLINE void RGBA32PackedToPlanar_16b_SSE2( + const uint16_t* const rgbx, + __m128i* const r, __m128i* const g, __m128i* const b) { + const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x + const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x + const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ... + const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ... + // column-wise transpose + const __m128i A0 = _mm_unpacklo_epi16(in0, in1); + const __m128i A1 = _mm_unpackhi_epi16(in0, in1); + const __m128i A2 = _mm_unpacklo_epi16(in2, in3); + const __m128i A3 = _mm_unpackhi_epi16(in2, in3); + const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // r0 r1 r2 r3 | g0 g1 .. + const __m128i B1 = _mm_unpackhi_epi16(A0, A1); // b0 b1 b2 b3 | x x x x + const __m128i B2 = _mm_unpacklo_epi16(A2, A3); // r4 r5 r6 r7 | g4 g5 .. + const __m128i B3 = _mm_unpackhi_epi16(A2, A3); // b4 b5 b6 b7 | x x x x + *r = _mm_unpacklo_epi64(B0, B2); + *g = _mm_unpackhi_epi64(B0, B2); + *b = _mm_unpacklo_epi64(B1, B3); +} + +static void ConvertRGBA32ToUV_SSE2(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + const int max_width = width & ~15; + const uint16_t* const last_rgb = rgb + 4 * max_width; + while (rgb < last_rgb) { + __m128i r, g, b, U0, V0, U1, V1; + RGBA32PackedToPlanar_16b_SSE2(rgb + 0, &r, &g, &b); + ConvertRGBToUV_SSE2(&r, &g, &b, &U0, &V0); + RGBA32PackedToPlanar_16b_SSE2(rgb + 32, &r, &g, &b); + ConvertRGBToUV_SSE2(&r, &g, &b, &U1, &V1); + STORE_16(_mm_packus_epi16(U0, U1), u); + STORE_16(_mm_packus_epi16(V0, V1), v); + u += 16; + v += 16; + rgb += 2 * 32; + } + if (max_width < width) { // left-over + WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width); + } +} + +//------------------------------------------------------------------------------ + +extern void WebPInitConvertARGBToYUVSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE2(void) { + WebPConvertARGBToY = ConvertARGBToY_SSE2; + WebPConvertARGBToUV = ConvertARGBToUV_SSE2; + + WebPConvertRGB24ToY = ConvertRGB24ToY_SSE2; + WebPConvertBGR24ToY = ConvertBGR24ToY_SSE2; + + WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(WebPInitSamplersSSE2) +WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/libraries/webp/src/dsp/yuv_sse41.c b/libraries/webp/src/dsp/yuv_sse41.c new file mode 100644 index 0000000000..f79b802e47 --- /dev/null +++ b/libraries/webp/src/dsp/yuv_sse41.c @@ -0,0 +1,615 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#if defined(WEBP_USE_SSE41) + +#include +#include + +#include "src/dsp/common_sse41.h" +#include "src/utils/utils.h" + +//----------------------------------------------------------------------------- +// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. + +// These constants are 14b fixed-point version of ITU-R BT.601 constants. +// R = (19077 * y + 26149 * v - 14234) >> 6 +// G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 +// B = (19077 * y + 33050 * u - 17685) >> 6 +static void ConvertYUV444ToRGB_SSE41(const __m128i* const Y0, + const __m128i* const U0, + const __m128i* const V0, + __m128i* const R, + __m128i* const G, + __m128i* const B) { + const __m128i k19077 = _mm_set1_epi16(19077); + const __m128i k26149 = _mm_set1_epi16(26149); + const __m128i k14234 = _mm_set1_epi16(14234); + // 33050 doesn't fit in a signed short: only use this with unsigned arithmetic + const __m128i k33050 = _mm_set1_epi16((short)33050); + const __m128i k17685 = _mm_set1_epi16(17685); + const __m128i k6419 = _mm_set1_epi16(6419); + const __m128i k13320 = _mm_set1_epi16(13320); + const __m128i k8708 = _mm_set1_epi16(8708); + + const __m128i Y1 = _mm_mulhi_epu16(*Y0, k19077); + + const __m128i R0 = _mm_mulhi_epu16(*V0, k26149); + const __m128i R1 = _mm_sub_epi16(Y1, k14234); + const __m128i R2 = _mm_add_epi16(R1, R0); + + const __m128i G0 = _mm_mulhi_epu16(*U0, k6419); + const __m128i G1 = _mm_mulhi_epu16(*V0, k13320); + const __m128i G2 = _mm_add_epi16(Y1, k8708); + const __m128i G3 = _mm_add_epi16(G0, G1); + const __m128i G4 = _mm_sub_epi16(G2, G3); + + // be careful with the saturated *unsigned* arithmetic here! + const __m128i B0 = _mm_mulhi_epu16(*U0, k33050); + const __m128i B1 = _mm_adds_epu16(B0, Y1); + const __m128i B2 = _mm_subs_epu16(B1, k17685); + + // use logical shift for B2, which can be larger than 32767 + *R = _mm_srai_epi16(R2, 6); // range: [-14234, 30815] + *G = _mm_srai_epi16(G4, 6); // range: [-10953, 27710] + *B = _mm_srli_epi16(B2, 6); // range: [0, 34238] +} + +// Load the bytes into the *upper* part of 16b words. That's "<< 8", basically. +static WEBP_INLINE __m128i Load_HI_16_SSE41(const uint8_t* src) { + const __m128i zero = _mm_setzero_si128(); + return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src)); +} + +// Load and replicate the U/V samples +static WEBP_INLINE __m128i Load_UV_HI_8_SSE41(const uint8_t* src) { + const __m128i zero = _mm_setzero_si128(); + const __m128i tmp0 = _mm_cvtsi32_si128(WebPMemToInt32(src)); + const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); + return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples +} + +// Convert 32 samples of YUV444 to R/G/B +static void YUV444ToRGB_SSE41(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE41(y), U0 = Load_HI_16_SSE41(u), + V0 = Load_HI_16_SSE41(v); + ConvertYUV444ToRGB_SSE41(&Y0, &U0, &V0, R, G, B); +} + +// Convert 32 samples of YUV420 to R/G/B +static void YUV420ToRGB_SSE41(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE41(y), U0 = Load_UV_HI_8_SSE41(u), + V0 = Load_UV_HI_8_SSE41(v); + ConvertYUV444ToRGB_SSE41(&Y0, &U0, &V0, R, G, B); +} + +// Pack the planar buffers +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... +static WEBP_INLINE void PlanarTo24b_SSE41( + __m128i* const in0, __m128i* const in1, __m128i* const in2, + __m128i* const in3, __m128i* const in4, __m128i* const in5, + uint8_t* const rgb) { + // The input is 6 registers of sixteen 8b but for the sake of explanation, + // let's take 6 registers of four 8b values. + // To pack, we will keep taking one every two 8b integer and move it + // around as follows: + // Input: + // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 + // Split the 6 registers in two sets of 3 registers: the first set as the even + // 8b bytes, the second the odd ones: + // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 + // Repeat the same permutations twice more: + // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 + // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 + VP8PlanarTo24b_SSE41(in0, in1, in2, in3, in4, in5); + + _mm_storeu_si128((__m128i*)(rgb + 0), *in0); + _mm_storeu_si128((__m128i*)(rgb + 16), *in1); + _mm_storeu_si128((__m128i*)(rgb + 32), *in2); + _mm_storeu_si128((__m128i*)(rgb + 48), *in3); + _mm_storeu_si128((__m128i*)(rgb + 64), *in4); + _mm_storeu_si128((__m128i*)(rgb + 80), *in5); +} + +void VP8YuvToRgb32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; + + YUV444ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE41(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE41(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE41(y + 24, u + 24, v + 24, &R3, &G3, &B3); + + // Cast to 8b and store as RRRRGGGGBBBB. + rgb0 = _mm_packus_epi16(R0, R1); + rgb1 = _mm_packus_epi16(R2, R3); + rgb2 = _mm_packus_epi16(G0, G1); + rgb3 = _mm_packus_epi16(G2, G3); + rgb4 = _mm_packus_epi16(B0, B1); + rgb5 = _mm_packus_epi16(B2, B3); + + // Pack as RGBRGBRGBRGB. + PlanarTo24b_SSE41(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); +} + +void VP8YuvToBgr32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; + + YUV444ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE41(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE41(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE41(y + 24, u + 24, v + 24, &R3, &G3, &B3); + + // Cast to 8b and store as BBBBGGGGRRRR. + bgr0 = _mm_packus_epi16(B0, B1); + bgr1 = _mm_packus_epi16(B2, B3); + bgr2 = _mm_packus_epi16(G0, G1); + bgr3 = _mm_packus_epi16(G2, G3); + bgr4 = _mm_packus_epi16(R0, R1); + bgr5= _mm_packus_epi16(R2, R3); + + // Pack as BGRBGRBGRBGR. + PlanarTo24b_SSE41(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); +} + +//----------------------------------------------------------------------------- +// Arbitrary-length row conversion functions + +static void YuvToRgbRow_SSE41(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; + + YUV420ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE41(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE41(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE41(y + 24, u + 12, v + 12, &R3, &G3, &B3); + + // Cast to 8b and store as RRRRGGGGBBBB. + rgb0 = _mm_packus_epi16(R0, R1); + rgb1 = _mm_packus_epi16(R2, R3); + rgb2 = _mm_packus_epi16(G0, G1); + rgb3 = _mm_packus_epi16(G2, G3); + rgb4 = _mm_packus_epi16(B0, B1); + rgb5 = _mm_packus_epi16(B2, B3); + + // Pack as RGBRGBRGBRGB. + PlanarTo24b_SSE41(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); + + y += 32; + u += 16; + v += 16; + } + for (; n < len; ++n) { // Finish off + VP8YuvToRgb(y[0], u[0], v[0], dst); + dst += 3; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToBgrRow_SSE41(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; + + YUV420ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE41(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE41(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE41(y + 24, u + 12, v + 12, &R3, &G3, &B3); + + // Cast to 8b and store as BBBBGGGGRRRR. + bgr0 = _mm_packus_epi16(B0, B1); + bgr1 = _mm_packus_epi16(B2, B3); + bgr2 = _mm_packus_epi16(G0, G1); + bgr3 = _mm_packus_epi16(G2, G3); + bgr4 = _mm_packus_epi16(R0, R1); + bgr5 = _mm_packus_epi16(R2, R3); + + // Pack as BGRBGRBGRBGR. + PlanarTo24b_SSE41(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); + + y += 32; + u += 16; + v += 16; + } + for (; n < len; ++n) { // Finish off + VP8YuvToBgr(y[0], u[0], v[0], dst); + dst += 3; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE41(void) { + WebPSamplers[MODE_RGB] = YuvToRgbRow_SSE41; + WebPSamplers[MODE_BGR] = YuvToBgrRow_SSE41; +} + +//------------------------------------------------------------------------------ +// RGB24/32 -> YUV converters + +// Load eight 16b-words from *src. +#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src)) +// Store either 16b-words into *dst +#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V)) + +#define WEBP_SSE41_SHUFF(OUT) do { \ + const __m128i tmp0 = _mm_shuffle_epi8(A0, shuff0); \ + const __m128i tmp1 = _mm_shuffle_epi8(A1, shuff1); \ + const __m128i tmp2 = _mm_shuffle_epi8(A2, shuff2); \ + const __m128i tmp3 = _mm_shuffle_epi8(A3, shuff0); \ + const __m128i tmp4 = _mm_shuffle_epi8(A4, shuff1); \ + const __m128i tmp5 = _mm_shuffle_epi8(A5, shuff2); \ + \ + /* OR everything to get one channel */ \ + const __m128i tmp6 = _mm_or_si128(tmp0, tmp1); \ + const __m128i tmp7 = _mm_or_si128(tmp3, tmp4); \ + out[OUT + 0] = _mm_or_si128(tmp6, tmp2); \ + out[OUT + 1] = _mm_or_si128(tmp7, tmp5); \ +} while (0); + +// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers: +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// Similar to PlanarTo24bHelper(), but in reverse order. +static WEBP_INLINE void RGB24PackedToPlanar_SSE41( + const uint8_t* const rgb, __m128i* const out /*out[6]*/) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)(rgb + 0)); + const __m128i A1 = _mm_loadu_si128((const __m128i*)(rgb + 16)); + const __m128i A2 = _mm_loadu_si128((const __m128i*)(rgb + 32)); + const __m128i A3 = _mm_loadu_si128((const __m128i*)(rgb + 48)); + const __m128i A4 = _mm_loadu_si128((const __m128i*)(rgb + 64)); + const __m128i A5 = _mm_loadu_si128((const __m128i*)(rgb + 80)); + + // Compute RR. + { + const __m128i shuff0 = _mm_set_epi8( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0); + const __m128i shuff1 = _mm_set_epi8( + -1, -1, -1, -1, -1, 14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1); + const __m128i shuff2 = _mm_set_epi8( + 13, 10, 7, 4, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + WEBP_SSE41_SHUFF(0) + } + // Compute GG. + { + const __m128i shuff0 = _mm_set_epi8( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1); + const __m128i shuff1 = _mm_set_epi8( + -1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1); + const __m128i shuff2 = _mm_set_epi8( + 14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + WEBP_SSE41_SHUFF(2) + } + // Compute BB. + { + const __m128i shuff0 = _mm_set_epi8( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, 11, 8, 5, 2); + const __m128i shuff1 = _mm_set_epi8( + -1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1, -1, -1, -1, -1, -1); + const __m128i shuff2 = _mm_set_epi8( + 15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + WEBP_SSE41_SHUFF(4) + } +} + +#undef WEBP_SSE41_SHUFF + +// Convert 8 packed ARGB to r[], g[], b[] +static WEBP_INLINE void RGB32PackedToPlanar_SSE41( + const uint32_t* const argb, __m128i* const rgb /*in[6]*/) { + const __m128i zero = _mm_setzero_si128(); + __m128i a0 = LOAD_16(argb + 0); + __m128i a1 = LOAD_16(argb + 4); + __m128i a2 = LOAD_16(argb + 8); + __m128i a3 = LOAD_16(argb + 12); + VP8L32bToPlanar_SSE41(&a0, &a1, &a2, &a3); + rgb[0] = _mm_unpacklo_epi8(a1, zero); + rgb[1] = _mm_unpackhi_epi8(a1, zero); + rgb[2] = _mm_unpacklo_epi8(a2, zero); + rgb[3] = _mm_unpackhi_epi8(a2, zero); + rgb[4] = _mm_unpacklo_epi8(a3, zero); + rgb[5] = _mm_unpackhi_epi8(a3, zero); +} + +// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX +// It's a macro and not a function because we need to use immediate values with +// srai_epi32, e.g. +#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \ + ROUNDER, DESCALE_FIX, OUT) do { \ + const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \ + const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \ + const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \ + const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \ + const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \ + const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \ + const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \ + const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \ + const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \ + const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \ + (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \ +} while (0) + +#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A)) +static WEBP_INLINE void ConvertRGBToY_SSE41(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const Y) { + const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384); + const __m128i kGB_y = MK_CST_16(16384, 6420); + const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF); + + const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); + const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); + const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); + const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y); +} + +static WEBP_INLINE void ConvertRGBToUV_SSE41(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const U, + __m128i* const V) { + const __m128i kRG_u = MK_CST_16(-9719, -19081); + const __m128i kGB_u = MK_CST_16(0, 28800); + const __m128i kRG_v = MK_CST_16(28800, 0); + const __m128i kGB_v = MK_CST_16(-24116, -4684); + const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2); + + const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); + const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); + const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); + const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u, + kHALF_UV, YUV_FIX + 2, *U); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v, + kHALF_UV, YUV_FIX + 2, *V); +} + +#undef MK_CST_16 +#undef TRANSFORM + +static void ConvertRGB24ToY_SSE41(const uint8_t* rgb, uint8_t* y, int width) { + const int max_width = width & ~31; + int i; + for (i = 0; i < max_width; rgb += 3 * 16 * 2) { + __m128i rgb_plane[6]; + int j; + + RGB24PackedToPlanar_SSE41(rgb, rgb_plane); + + for (j = 0; j < 2; ++j, i += 16) { + const __m128i zero = _mm_setzero_si128(); + __m128i r, g, b, Y0, Y1; + + // Convert to 16-bit Y. + r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero); + g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero); + b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero); + ConvertRGBToY_SSE41(&r, &g, &b, &Y0); + + // Convert to 16-bit Y. + r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero); + g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero); + b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero); + ConvertRGBToY_SSE41(&r, &g, &b, &Y1); + + // Cast to 8-bit and store. + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + } + for (; i < width; ++i, rgb += 3) { // left-over + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_SSE41(const uint8_t* bgr, uint8_t* y, int width) { + const int max_width = width & ~31; + int i; + for (i = 0; i < max_width; bgr += 3 * 16 * 2) { + __m128i bgr_plane[6]; + int j; + + RGB24PackedToPlanar_SSE41(bgr, bgr_plane); + + for (j = 0; j < 2; ++j, i += 16) { + const __m128i zero = _mm_setzero_si128(); + __m128i r, g, b, Y0, Y1; + + // Convert to 16-bit Y. + b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero); + g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero); + r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero); + ConvertRGBToY_SSE41(&r, &g, &b, &Y0); + + // Convert to 16-bit Y. + b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero); + g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero); + r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero); + ConvertRGBToY_SSE41(&r, &g, &b, &Y1); + + // Cast to 8-bit and store. + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + } + for (; i < width; ++i, bgr += 3) { // left-over + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +static void ConvertARGBToY_SSE41(const uint32_t* argb, uint8_t* y, int width) { + const int max_width = width & ~15; + int i; + for (i = 0; i < max_width; i += 16) { + __m128i Y0, Y1, rgb[6]; + RGB32PackedToPlanar_SSE41(&argb[i], rgb); + ConvertRGBToY_SSE41(&rgb[0], &rgb[2], &rgb[4], &Y0); + ConvertRGBToY_SSE41(&rgb[1], &rgb[3], &rgb[5], &Y1); + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + for (; i < width; ++i) { // left-over + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +// Horizontal add (doubled) of two 16b values, result is 16b. +// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ... +static void HorizontalAddPack_SSE41(const __m128i* const A, + const __m128i* const B, + __m128i* const out) { + const __m128i k2 = _mm_set1_epi16(2); + const __m128i C = _mm_madd_epi16(*A, k2); + const __m128i D = _mm_madd_epi16(*B, k2); + *out = _mm_packs_epi32(C, D); +} + +static void ConvertARGBToUV_SSE41(const uint32_t* argb, + uint8_t* u, uint8_t* v, + int src_width, int do_store) { + const int max_width = src_width & ~31; + int i; + for (i = 0; i < max_width; i += 32, u += 16, v += 16) { + __m128i rgb[6], U0, V0, U1, V1; + RGB32PackedToPlanar_SSE41(&argb[i], rgb); + HorizontalAddPack_SSE41(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE41(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE41(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE41(&rgb[0], &rgb[2], &rgb[4], &U0, &V0); + + RGB32PackedToPlanar_SSE41(&argb[i + 16], rgb); + HorizontalAddPack_SSE41(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE41(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE41(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE41(&rgb[0], &rgb[2], &rgb[4], &U1, &V1); + + U0 = _mm_packus_epi16(U0, U1); + V0 = _mm_packus_epi16(V0, V1); + if (!do_store) { + const __m128i prev_u = LOAD_16(u); + const __m128i prev_v = LOAD_16(v); + U0 = _mm_avg_epu8(U0, prev_u); + V0 = _mm_avg_epu8(V0, prev_v); + } + STORE_16(U0, u); + STORE_16(V0, v); + } + if (i < src_width) { // left-over + WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); + } +} + +// Convert 16 packed ARGB 16b-values to r[], g[], b[] +static WEBP_INLINE void RGBA32PackedToPlanar_16b_SSE41( + const uint16_t* const rgbx, + __m128i* const r, __m128i* const g, __m128i* const b) { + const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x + const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x + const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ... + const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ... + // aarrggbb as 16-bit. + const __m128i shuff0 = + _mm_set_epi8(-1, -1, -1, -1, 13, 12, 5, 4, 11, 10, 3, 2, 9, 8, 1, 0); + const __m128i shuff1 = + _mm_set_epi8(13, 12, 5, 4, -1, -1, -1, -1, 11, 10, 3, 2, 9, 8, 1, 0); + const __m128i A0 = _mm_shuffle_epi8(in0, shuff0); + const __m128i A1 = _mm_shuffle_epi8(in1, shuff1); + const __m128i A2 = _mm_shuffle_epi8(in2, shuff0); + const __m128i A3 = _mm_shuffle_epi8(in3, shuff1); + // R0R1G0G1 + // B0B1**** + // R2R3G2G3 + // B2B3**** + // (OR is used to free port 5 for the unpack) + const __m128i B0 = _mm_unpacklo_epi32(A0, A1); + const __m128i B1 = _mm_or_si128(A0, A1); + const __m128i B2 = _mm_unpacklo_epi32(A2, A3); + const __m128i B3 = _mm_or_si128(A2, A3); + // Gather the channels. + *r = _mm_unpacklo_epi64(B0, B2); + *g = _mm_unpackhi_epi64(B0, B2); + *b = _mm_unpackhi_epi64(B1, B3); +} + +static void ConvertRGBA32ToUV_SSE41(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + const int max_width = width & ~15; + const uint16_t* const last_rgb = rgb + 4 * max_width; + while (rgb < last_rgb) { + __m128i r, g, b, U0, V0, U1, V1; + RGBA32PackedToPlanar_16b_SSE41(rgb + 0, &r, &g, &b); + ConvertRGBToUV_SSE41(&r, &g, &b, &U0, &V0); + RGBA32PackedToPlanar_16b_SSE41(rgb + 32, &r, &g, &b); + ConvertRGBToUV_SSE41(&r, &g, &b, &U1, &V1); + STORE_16(_mm_packus_epi16(U0, U1), u); + STORE_16(_mm_packus_epi16(V0, V1), v); + u += 16; + v += 16; + rgb += 2 * 32; + } + if (max_width < width) { // left-over + WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width); + } +} + +//------------------------------------------------------------------------------ + +extern void WebPInitConvertARGBToYUVSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE41(void) { + WebPConvertARGBToY = ConvertARGBToY_SSE41; + WebPConvertARGBToUV = ConvertARGBToUV_SSE41; + + WebPConvertRGB24ToY = ConvertRGB24ToY_SSE41; + WebPConvertBGR24ToY = ConvertBGR24ToY_SSE41; + + WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_SSE41; +} + +//------------------------------------------------------------------------------ + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(WebPInitSamplersSSE41) +WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/libraries/webp/src/enc/alpha_enc.c b/libraries/webp/src/enc/alpha_enc.c new file mode 100644 index 0000000000..90842330c0 --- /dev/null +++ b/libraries/webp/src/enc/alpha_enc.c @@ -0,0 +1,450 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha-plane compression. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" +#include "src/utils/filters_utils.h" +#include "src/utils/quant_levels_utils.h" +#include "src/utils/utils.h" +#include "include/webp/encode.h" +#include "include/webp/format_constants.h" + +// ----------------------------------------------------------------------------- +// Encodes the given alpha data via specified compression method 'method'. +// The pre-processing (quantization) is performed if 'quality' is less than 100. +// For such cases, the encoding is lossy. The valid range is [0, 100] for +// 'quality' and [0, 1] for 'method': +// 'method = 0' - No compression; +// 'method = 1' - Use lossless coder on the alpha plane only +// 'filter' values [0, 4] correspond to prediction modes none, horizontal, +// vertical & gradient filters. The prediction mode 4 will try all the +// prediction modes 0 to 3 and pick the best one. +// 'effort_level': specifies how much effort must be spent to try and reduce +// the compressed output size. In range 0 (quick) to 6 (slow). +// +// 'output' corresponds to the buffer containing compressed alpha data. +// This buffer is allocated by this method and caller should call +// WebPSafeFree(*output) when done. +// 'output_size' corresponds to size of this compressed alpha buffer. +// +// Returns 1 on successfully encoding the alpha and +// 0 if either: +// invalid quality or method, or +// memory allocation for the compressed data fails. + +#include "src/enc/vp8li_enc.h" + +static int EncodeLossless(const uint8_t* const data, int width, int height, + int effort_level, // in [0..6] range + int use_quality_100, VP8LBitWriter* const bw, + WebPAuxStats* const stats) { + int ok = 0; + WebPConfig config; + WebPPicture picture; + + if (!WebPPictureInit(&picture)) return 0; + picture.width = width; + picture.height = height; + picture.use_argb = 1; + picture.stats = stats; + if (!WebPPictureAlloc(&picture)) return 0; + + // Transfer the alpha values to the green channel. + WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, + picture.argb, picture.argb_stride); + + if (!WebPConfigInit(&config)) return 0; + config.lossless = 1; + // Enable exact, or it would alter RGB values of transparent alpha, which is + // normally OK but not here since we are not encoding the input image but an + // internal encoding-related image containing necessary exact information in + // RGB channels. + config.exact = 1; + config.method = effort_level; // impact is very small + // Set a low default quality for encoding alpha. Ensure that Alpha quality at + // lower methods (3 and below) is less than the threshold for triggering + // costly 'BackwardReferencesTraceBackwards'. + // If the alpha quality is set to 100 and the method to 6, allow for a high + // lossless quality to trigger the cruncher. + config.quality = + (use_quality_100 && effort_level == 6) ? 100 : 8.f * effort_level; + assert(config.quality >= 0 && config.quality <= 100.f); + + ok = VP8LEncodeStream(&config, &picture, bw); + WebPPictureFree(&picture); + ok = ok && !bw->error_; + if (!ok) { + VP8LBitWriterWipeOut(bw); + return 0; + } + return 1; +} + +// ----------------------------------------------------------------------------- + +// Small struct to hold the result of a filter mode compression attempt. +typedef struct { + size_t score; + VP8BitWriter bw; + WebPAuxStats stats; +} FilterTrial; + +// This function always returns an initialized 'bw' object, even upon error. +static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, + int method, int filter, int reduce_levels, + int effort_level, // in [0..6] range + uint8_t* const tmp_alpha, + FilterTrial* result) { + int ok = 0; + const uint8_t* alpha_src; + WebPFilterFunc filter_func; + uint8_t header; + const size_t data_size = width * height; + const uint8_t* output = NULL; + size_t output_size = 0; + VP8LBitWriter tmp_bw; + + assert((uint64_t)data_size == (uint64_t)width * height); // as per spec + assert(filter >= 0 && filter < WEBP_FILTER_LAST); + assert(method >= ALPHA_NO_COMPRESSION); + assert(method <= ALPHA_LOSSLESS_COMPRESSION); + assert(sizeof(header) == ALPHA_HEADER_LEN); + + filter_func = WebPFilters[filter]; + if (filter_func != NULL) { + filter_func(data, width, height, width, tmp_alpha); + alpha_src = tmp_alpha; + } else { + alpha_src = data; + } + + if (method != ALPHA_NO_COMPRESSION) { + ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3); + ok = ok && EncodeLossless(alpha_src, width, height, effort_level, + !reduce_levels, &tmp_bw, &result->stats); + if (ok) { + output = VP8LBitWriterFinish(&tmp_bw); + if (tmp_bw.error_) { + VP8LBitWriterWipeOut(&tmp_bw); + memset(&result->bw, 0, sizeof(result->bw)); + return 0; + } + output_size = VP8LBitWriterNumBytes(&tmp_bw); + if (output_size > data_size) { + // compressed size is larger than source! Revert to uncompressed mode. + method = ALPHA_NO_COMPRESSION; + VP8LBitWriterWipeOut(&tmp_bw); + } + } else { + VP8LBitWriterWipeOut(&tmp_bw); + memset(&result->bw, 0, sizeof(result->bw)); + return 0; + } + } + + if (method == ALPHA_NO_COMPRESSION) { + output = alpha_src; + output_size = data_size; + ok = 1; + } + + // Emit final result. + header = method | (filter << 2); + if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4; + + if (!VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size)) ok = 0; + ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN); + ok = ok && VP8BitWriterAppend(&result->bw, output, output_size); + + if (method != ALPHA_NO_COMPRESSION) { + VP8LBitWriterWipeOut(&tmp_bw); + } + ok = ok && !result->bw.error_; + result->score = VP8BitWriterSize(&result->bw); + return ok; +} + +// ----------------------------------------------------------------------------- + +static int GetNumColors(const uint8_t* data, int width, int height, + int stride) { + int j; + int colors = 0; + uint8_t color[256] = { 0 }; + + for (j = 0; j < height; ++j) { + int i; + const uint8_t* const p = data + j * stride; + for (i = 0; i < width; ++i) { + color[p[i]] = 1; + } + } + for (j = 0; j < 256; ++j) { + if (color[j] > 0) ++colors; + } + return colors; +} + +#define FILTER_TRY_NONE (1 << WEBP_FILTER_NONE) +#define FILTER_TRY_ALL ((1 << WEBP_FILTER_LAST) - 1) + +// Given the input 'filter' option, return an OR'd bit-set of filters to try. +static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height, + int filter, int effort_level) { + uint32_t bit_map = 0U; + if (filter == WEBP_FILTER_FAST) { + // Quick estimate of the best candidate. + int try_filter_none = (effort_level > 3); + const int kMinColorsForFilterNone = 16; + const int kMaxColorsForFilterNone = 192; + const int num_colors = GetNumColors(alpha, width, height, width); + // For low number of colors, NONE yields better compression. + filter = (num_colors <= kMinColorsForFilterNone) + ? WEBP_FILTER_NONE + : WebPEstimateBestFilter(alpha, width, height, width); + bit_map |= 1 << filter; + // For large number of colors, try FILTER_NONE in addition to the best + // filter as well. + if (try_filter_none || num_colors > kMaxColorsForFilterNone) { + bit_map |= FILTER_TRY_NONE; + } + } else if (filter == WEBP_FILTER_NONE) { + bit_map = FILTER_TRY_NONE; + } else { // WEBP_FILTER_BEST -> try all + bit_map = FILTER_TRY_ALL; + } + return bit_map; +} + +static void InitFilterTrial(FilterTrial* const score) { + score->score = (size_t)~0U; + VP8BitWriterInit(&score->bw, 0); +} + +static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, + size_t data_size, int method, int filter, + int reduce_levels, int effort_level, + uint8_t** const output, + size_t* const output_size, + WebPAuxStats* const stats) { + int ok = 1; + FilterTrial best; + uint32_t try_map = + GetFilterMap(alpha, width, height, filter, effort_level); + InitFilterTrial(&best); + + if (try_map != FILTER_TRY_NONE) { + uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); + if (filtered_alpha == NULL) return 0; + + for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) { + if (try_map & 1) { + FilterTrial trial; + ok = EncodeAlphaInternal(alpha, width, height, method, filter, + reduce_levels, effort_level, filtered_alpha, + &trial); + if (ok && trial.score < best.score) { + VP8BitWriterWipeOut(&best.bw); + best = trial; + } else { + VP8BitWriterWipeOut(&trial.bw); + } + } + } + WebPSafeFree(filtered_alpha); + } else { + ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE, + reduce_levels, effort_level, NULL, &best); + } + if (ok) { +#if !defined(WEBP_DISABLE_STATS) + if (stats != NULL) { + stats->lossless_features = best.stats.lossless_features; + stats->histogram_bits = best.stats.histogram_bits; + stats->transform_bits = best.stats.transform_bits; + stats->cache_bits = best.stats.cache_bits; + stats->palette_size = best.stats.palette_size; + stats->lossless_size = best.stats.lossless_size; + stats->lossless_hdr_size = best.stats.lossless_hdr_size; + stats->lossless_data_size = best.stats.lossless_data_size; + } +#else + (void)stats; +#endif + *output_size = VP8BitWriterSize(&best.bw); + *output = VP8BitWriterBuf(&best.bw); + } else { + VP8BitWriterWipeOut(&best.bw); + } + return ok; +} + +static int EncodeAlpha(VP8Encoder* const enc, + int quality, int method, int filter, + int effort_level, + uint8_t** const output, size_t* const output_size) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + + uint8_t* quant_alpha = NULL; + const size_t data_size = width * height; + uint64_t sse = 0; + int ok = 1; + const int reduce_levels = (quality < 100); + + // quick correctness checks + assert((uint64_t)data_size == (uint64_t)width * height); // as per spec + assert(enc != NULL && pic != NULL && pic->a != NULL); + assert(output != NULL && output_size != NULL); + assert(width > 0 && height > 0); + assert(pic->a_stride >= width); + assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST); + + if (quality < 0 || quality > 100) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + + if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + + if (method == ALPHA_NO_COMPRESSION) { + // Don't filter, as filtering will make no impact on compressed size. + filter = WEBP_FILTER_NONE; + } + + quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); + if (quant_alpha == NULL) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + // Extract alpha data (width x height) from raw_data (stride x height). + WebPCopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height); + + if (reduce_levels) { // No Quantization required for 'quality = 100'. + // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence + // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16] + // and Quality:]70, 100] -> Levels:]16, 256]. + const int alpha_levels = (quality <= 70) ? (2 + quality / 5) + : (16 + (quality - 70) * 8); + ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse); + } + + if (ok) { + VP8FiltersInit(); + ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method, + filter, reduce_levels, effort_level, output, + output_size, pic->stats); + if (!ok) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); // imprecise + } +#if !defined(WEBP_DISABLE_STATS) + if (pic->stats != NULL) { // need stats? + pic->stats->coded_size += (int)(*output_size); + enc->sse_[3] = sse; + } +#endif + } + + WebPSafeFree(quant_alpha); + return ok; +} + +//------------------------------------------------------------------------------ +// Main calls + +static int CompressAlphaJob(void* arg1, void* unused) { + VP8Encoder* const enc = (VP8Encoder*)arg1; + const WebPConfig* config = enc->config_; + uint8_t* alpha_data = NULL; + size_t alpha_size = 0; + const int effort_level = config->method; // maps to [0..6] + const WEBP_FILTER_TYPE filter = + (config->alpha_filtering == 0) ? WEBP_FILTER_NONE : + (config->alpha_filtering == 1) ? WEBP_FILTER_FAST : + WEBP_FILTER_BEST; + if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression, + filter, effort_level, &alpha_data, &alpha_size)) { + return 0; + } + if (alpha_size != (uint32_t)alpha_size) { // Soundness check. + WebPSafeFree(alpha_data); + return 0; + } + enc->alpha_data_size_ = (uint32_t)alpha_size; + enc->alpha_data_ = alpha_data; + (void)unused; + return 1; +} + +void VP8EncInitAlpha(VP8Encoder* const enc) { + WebPInitAlphaProcessing(); + enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_); + enc->alpha_data_ = NULL; + enc->alpha_data_size_ = 0; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + WebPGetWorkerInterface()->Init(worker); + worker->data1 = enc; + worker->data2 = NULL; + worker->hook = CompressAlphaJob; + } +} + +int VP8EncStartAlpha(VP8Encoder* const enc) { + if (enc->has_alpha_) { + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + // Makes sure worker is good to go. + if (!WebPGetWorkerInterface()->Reset(worker)) { + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + WebPGetWorkerInterface()->Launch(worker); + return 1; + } else { + return CompressAlphaJob(enc, NULL); // just do the job right away + } + } + return 1; +} + +int VP8EncFinishAlpha(VP8Encoder* const enc) { + if (enc->has_alpha_) { + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error + } + } + return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); +} + +int VP8EncDeleteAlpha(VP8Encoder* const enc) { + int ok = 1; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + // finish anything left in flight + ok = WebPGetWorkerInterface()->Sync(worker); + // still need to end the worker, even if !ok + WebPGetWorkerInterface()->End(worker); + } + WebPSafeFree(enc->alpha_data_); + enc->alpha_data_ = NULL; + enc->alpha_data_size_ = 0; + enc->has_alpha_ = 0; + return ok; +} diff --git a/libraries/webp/src/enc/analysis_enc.c b/libraries/webp/src/enc/analysis_enc.c new file mode 100644 index 0000000000..962eaa998f --- /dev/null +++ b/libraries/webp/src/enc/analysis_enc.c @@ -0,0 +1,483 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Macroblock analysis +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" +#include "src/utils/utils.h" + +#define MAX_ITERS_K_MEANS 6 + +//------------------------------------------------------------------------------ +// Smooth the segment map by replacing isolated block by the majority of its +// neighbours. + +static void SmoothSegmentMap(VP8Encoder* const enc) { + int n, x, y; + const int w = enc->mb_w_; + const int h = enc->mb_h_; + const int majority_cnt_3_x_3_grid = 5; + uint8_t* const tmp = (uint8_t*)WebPSafeMalloc(w * h, sizeof(*tmp)); + assert((uint64_t)(w * h) == (uint64_t)w * h); // no overflow, as per spec + + if (tmp == NULL) return; + for (y = 1; y < h - 1; ++y) { + for (x = 1; x < w - 1; ++x) { + int cnt[NUM_MB_SEGMENTS] = { 0 }; + const VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; + int majority_seg = mb->segment_; + // Check the 8 neighbouring segment values. + cnt[mb[-w - 1].segment_]++; // top-left + cnt[mb[-w + 0].segment_]++; // top + cnt[mb[-w + 1].segment_]++; // top-right + cnt[mb[ - 1].segment_]++; // left + cnt[mb[ + 1].segment_]++; // right + cnt[mb[ w - 1].segment_]++; // bottom-left + cnt[mb[ w + 0].segment_]++; // bottom + cnt[mb[ w + 1].segment_]++; // bottom-right + for (n = 0; n < NUM_MB_SEGMENTS; ++n) { + if (cnt[n] >= majority_cnt_3_x_3_grid) { + majority_seg = n; + break; + } + } + tmp[x + y * w] = majority_seg; + } + } + for (y = 1; y < h - 1; ++y) { + for (x = 1; x < w - 1; ++x) { + VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; + mb->segment_ = tmp[x + y * w]; + } + } + WebPSafeFree(tmp); +} + +//------------------------------------------------------------------------------ +// set segment susceptibility alpha_ / beta_ + +static WEBP_INLINE int clip(int v, int m, int M) { + return (v < m) ? m : (v > M) ? M : v; +} + +static void SetSegmentAlphas(VP8Encoder* const enc, + const int centers[NUM_MB_SEGMENTS], + int mid) { + const int nb = enc->segment_hdr_.num_segments_; + int min = centers[0], max = centers[0]; + int n; + + if (nb > 1) { + for (n = 0; n < nb; ++n) { + if (min > centers[n]) min = centers[n]; + if (max < centers[n]) max = centers[n]; + } + } + if (max == min) max = min + 1; + assert(mid <= max && mid >= min); + for (n = 0; n < nb; ++n) { + const int alpha = 255 * (centers[n] - mid) / (max - min); + const int beta = 255 * (centers[n] - min) / (max - min); + enc->dqm_[n].alpha_ = clip(alpha, -127, 127); + enc->dqm_[n].beta_ = clip(beta, 0, 255); + } +} + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +#define MAX_ALPHA 255 // 8b of precision for susceptibilities. +#define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha. +#define DEFAULT_ALPHA (-1) +#define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha)) + +static int FinalAlphaValue(int alpha) { + alpha = MAX_ALPHA - alpha; + return clip(alpha, 0, MAX_ALPHA); +} + +static int GetAlpha(const VP8Histogram* const histo) { + // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer + // values which happen to be mostly noise. This leaves the maximum precision + // for handling the useful small values which contribute most. + const int max_value = histo->max_value; + const int last_non_zero = histo->last_non_zero; + const int alpha = + (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0; + return alpha; +} + +static void InitHistogram(VP8Histogram* const histo) { + histo->max_value = 0; + histo->last_non_zero = 1; +} + +//------------------------------------------------------------------------------ +// Simplified k-Means, to assign Nb segments based on alpha-histogram + +static void AssignSegments(VP8Encoder* const enc, + const int alphas[MAX_ALPHA + 1]) { + // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an + // explicit check is needed to avoid spurious warning about 'n + 1' exceeding + // array bounds of 'centers' with some compilers (noticed with gcc-4.9). + const int nb = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) ? + enc->segment_hdr_.num_segments_ : NUM_MB_SEGMENTS; + int centers[NUM_MB_SEGMENTS]; + int weighted_average = 0; + int map[MAX_ALPHA + 1]; + int a, n, k; + int min_a = 0, max_a = MAX_ALPHA, range_a; + // 'int' type is ok for histo, and won't overflow + int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS]; + + assert(nb >= 1); + assert(nb <= NUM_MB_SEGMENTS); + + // bracket the input + for (n = 0; n <= MAX_ALPHA && alphas[n] == 0; ++n) {} + min_a = n; + for (n = MAX_ALPHA; n > min_a && alphas[n] == 0; --n) {} + max_a = n; + range_a = max_a - min_a; + + // Spread initial centers evenly + for (k = 0, n = 1; k < nb; ++k, n += 2) { + assert(n < 2 * nb); + centers[k] = min_a + (n * range_a) / (2 * nb); + } + + for (k = 0; k < MAX_ITERS_K_MEANS; ++k) { // few iters are enough + int total_weight; + int displaced; + // Reset stats + for (n = 0; n < nb; ++n) { + accum[n] = 0; + dist_accum[n] = 0; + } + // Assign nearest center for each 'a' + n = 0; // track the nearest center for current 'a' + for (a = min_a; a <= max_a; ++a) { + if (alphas[a]) { + while (n + 1 < nb && abs(a - centers[n + 1]) < abs(a - centers[n])) { + n++; + } + map[a] = n; + // accumulate contribution into best centroid + dist_accum[n] += a * alphas[a]; + accum[n] += alphas[a]; + } + } + // All point are classified. Move the centroids to the + // center of their respective cloud. + displaced = 0; + weighted_average = 0; + total_weight = 0; + for (n = 0; n < nb; ++n) { + if (accum[n]) { + const int new_center = (dist_accum[n] + accum[n] / 2) / accum[n]; + displaced += abs(centers[n] - new_center); + centers[n] = new_center; + weighted_average += new_center * accum[n]; + total_weight += accum[n]; + } + } + weighted_average = (weighted_average + total_weight / 2) / total_weight; + if (displaced < 5) break; // no need to keep on looping... + } + + // Map each original value to the closest centroid + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + VP8MBInfo* const mb = &enc->mb_info_[n]; + const int alpha = mb->alpha_; + mb->segment_ = map[alpha]; + mb->alpha_ = centers[map[alpha]]; // for the record. + } + + if (nb > 1) { + const int smooth = (enc->config_->preprocessing & 1); + if (smooth) SmoothSegmentMap(enc); + } + + SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas. +} + +//------------------------------------------------------------------------------ +// Macroblock analysis: collect histogram for each mode, deduce the maximal +// susceptibility and set best modes for this macroblock. +// Segment assignment is done later. + +// Number of modes to inspect for alpha_ evaluation. We don't need to test all +// the possible modes during the analysis phase: we risk falling into a local +// optimum, or be subject to boundary effect +#define MAX_INTRA16_MODE 2 +#define MAX_INTRA4_MODE 2 +#define MAX_UV_MODE 2 + +static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) { + const int max_mode = MAX_INTRA16_MODE; + int mode; + int best_alpha = DEFAULT_ALPHA; + int best_mode = 0; + + VP8MakeLuma16Preds(it); + for (mode = 0; mode < max_mode; ++mode) { + VP8Histogram histo; + int alpha; + + InitHistogram(&histo); + VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC, + it->yuv_p_ + VP8I16ModeOffsets[mode], + 0, 16, &histo); + alpha = GetAlpha(&histo); + if (IS_BETTER_ALPHA(alpha, best_alpha)) { + best_alpha = alpha; + best_mode = mode; + } + } + VP8SetIntra16Mode(it, best_mode); + return best_alpha; +} + +static int FastMBAnalyze(VP8EncIterator* const it) { + // Empirical cut-off value, should be around 16 (~=block size). We use the + // [8-17] range and favor intra4 at high quality, intra16 for low quality. + const int q = (int)it->enc_->config_->quality; + const uint32_t kThreshold = 8 + (17 - 8) * q / 100; + int k; + uint32_t dc[16], m, m2; + for (k = 0; k < 16; k += 4) { + VP8Mean16x4(it->yuv_in_ + Y_OFF_ENC + k * BPS, &dc[k]); + } + for (m = 0, m2 = 0, k = 0; k < 16; ++k) { + m += dc[k]; + m2 += dc[k] * dc[k]; + } + if (kThreshold * m2 < m * m) { + VP8SetIntra16Mode(it, 0); // DC16 + } else { + const uint8_t modes[16] = { 0 }; // DC4 + VP8SetIntra4Mode(it, modes); + } + return 0; +} + +static int MBAnalyzeBestUVMode(VP8EncIterator* const it) { + int best_alpha = DEFAULT_ALPHA; + int smallest_alpha = 0; + int best_mode = 0; + const int max_mode = MAX_UV_MODE; + int mode; + + VP8MakeChroma8Preds(it); + for (mode = 0; mode < max_mode; ++mode) { + VP8Histogram histo; + int alpha; + InitHistogram(&histo); + VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC, + it->yuv_p_ + VP8UVModeOffsets[mode], + 16, 16 + 4 + 4, &histo); + alpha = GetAlpha(&histo); + if (IS_BETTER_ALPHA(alpha, best_alpha)) { + best_alpha = alpha; + } + // The best prediction mode tends to be the one with the smallest alpha. + if (mode == 0 || alpha < smallest_alpha) { + smallest_alpha = alpha; + best_mode = mode; + } + } + VP8SetIntraUVMode(it, best_mode); + return best_alpha; +} + +static void MBAnalyze(VP8EncIterator* const it, + int alphas[MAX_ALPHA + 1], + int* const alpha, int* const uv_alpha) { + const VP8Encoder* const enc = it->enc_; + int best_alpha, best_uv_alpha; + + VP8SetIntra16Mode(it, 0); // default: Intra16, DC_PRED + VP8SetSkip(it, 0); // not skipped + VP8SetSegment(it, 0); // default segment, spec-wise. + + if (enc->method_ <= 1) { + best_alpha = FastMBAnalyze(it); + } else { + best_alpha = MBAnalyzeBestIntra16Mode(it); + } + best_uv_alpha = MBAnalyzeBestUVMode(it); + + // Final susceptibility mix + best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2; + best_alpha = FinalAlphaValue(best_alpha); + alphas[best_alpha]++; + it->mb_->alpha_ = best_alpha; // for later remapping. + + // Accumulate for later complexity analysis. + *alpha += best_alpha; // mixed susceptibility (not just luma) + *uv_alpha += best_uv_alpha; +} + +static void DefaultMBInfo(VP8MBInfo* const mb) { + mb->type_ = 1; // I16x16 + mb->uv_mode_ = 0; + mb->skip_ = 0; // not skipped + mb->segment_ = 0; // default segment + mb->alpha_ = 0; +} + +//------------------------------------------------------------------------------ +// Main analysis loop: +// Collect all susceptibilities for each macroblock and record their +// distribution in alphas[]. Segments is assigned a-posteriori, based on +// this histogram. +// We also pick an intra16 prediction mode, which shouldn't be considered +// final except for fast-encode settings. We can also pick some intra4 modes +// and decide intra4/intra16, but that's usually almost always a bad choice at +// this stage. + +static void ResetAllMBInfo(VP8Encoder* const enc) { + int n; + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + DefaultMBInfo(&enc->mb_info_[n]); + } + // Default susceptibilities. + enc->dqm_[0].alpha_ = 0; + enc->dqm_[0].beta_ = 0; + // Note: we can't compute this alpha_ / uv_alpha_ -> set to default value. + enc->alpha_ = 0; + enc->uv_alpha_ = 0; + WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); +} + +// struct used to collect job result +typedef struct { + WebPWorker worker; + int alphas[MAX_ALPHA + 1]; + int alpha, uv_alpha; + VP8EncIterator it; + int delta_progress; +} SegmentJob; + +// main work call +static int DoSegmentsJob(void* arg1, void* arg2) { + SegmentJob* const job = (SegmentJob*)arg1; + VP8EncIterator* const it = (VP8EncIterator*)arg2; + int ok = 1; + if (!VP8IteratorIsDone(it)) { + uint8_t tmp[32 + WEBP_ALIGN_CST]; + uint8_t* const scratch = (uint8_t*)WEBP_ALIGN(tmp); + do { + // Let's pretend we have perfect lossless reconstruction. + VP8IteratorImport(it, scratch); + MBAnalyze(it, job->alphas, &job->alpha, &job->uv_alpha); + ok = VP8IteratorProgress(it, job->delta_progress); + } while (ok && VP8IteratorNext(it)); + } + return ok; +} + +#ifdef WEBP_USE_THREAD +static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) { + int i; + for (i = 0; i <= MAX_ALPHA; ++i) dst->alphas[i] += src->alphas[i]; + dst->alpha += src->alpha; + dst->uv_alpha += src->uv_alpha; +} +#endif + +// initialize the job struct with some tasks to perform +static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job, + int start_row, int end_row) { + WebPGetWorkerInterface()->Init(&job->worker); + job->worker.data1 = job; + job->worker.data2 = &job->it; + job->worker.hook = DoSegmentsJob; + VP8IteratorInit(enc, &job->it); + VP8IteratorSetRow(&job->it, start_row); + VP8IteratorSetCountDown(&job->it, (end_row - start_row) * enc->mb_w_); + memset(job->alphas, 0, sizeof(job->alphas)); + job->alpha = 0; + job->uv_alpha = 0; + // only one of both jobs can record the progress, since we don't + // expect the user's hook to be multi-thread safe + job->delta_progress = (start_row == 0) ? 20 : 0; +} + +// main entry point +int VP8EncAnalyze(VP8Encoder* const enc) { + int ok = 1; + const int do_segments = + enc->config_->emulate_jpeg_size || // We need the complexity evaluation. + (enc->segment_hdr_.num_segments_ > 1) || + (enc->method_ <= 1); // for method 0 - 1, we need preds_[] to be filled. + if (do_segments) { + const int last_row = enc->mb_h_; + const int total_mb = last_row * enc->mb_w_; +#ifdef WEBP_USE_THREAD + // We give a little more than a half work to the main thread. + const int split_row = (9 * last_row + 15) >> 4; + const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it + const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow); +#else + const int do_mt = 0; +#endif + const WebPWorkerInterface* const worker_interface = + WebPGetWorkerInterface(); + SegmentJob main_job; + if (do_mt) { +#ifdef WEBP_USE_THREAD + SegmentJob side_job; + // Note the use of '&' instead of '&&' because we must call the functions + // no matter what. + InitSegmentJob(enc, &main_job, 0, split_row); + InitSegmentJob(enc, &side_job, split_row, last_row); + // we don't need to call Reset() on main_job.worker, since we're calling + // WebPWorkerExecute() on it + ok &= worker_interface->Reset(&side_job.worker); + // launch the two jobs in parallel + if (ok) { + worker_interface->Launch(&side_job.worker); + worker_interface->Execute(&main_job.worker); + ok &= worker_interface->Sync(&side_job.worker); + ok &= worker_interface->Sync(&main_job.worker); + } + worker_interface->End(&side_job.worker); + if (ok) MergeJobs(&side_job, &main_job); // merge results together +#endif // WEBP_USE_THREAD + } else { + // Even for single-thread case, we use the generic Worker tools. + InitSegmentJob(enc, &main_job, 0, last_row); + worker_interface->Execute(&main_job.worker); + ok &= worker_interface->Sync(&main_job.worker); + } + worker_interface->End(&main_job.worker); + if (ok) { + enc->alpha_ = main_job.alpha / total_mb; + enc->uv_alpha_ = main_job.uv_alpha / total_mb; + AssignSegments(enc, main_job.alphas); + } + } else { // Use only one default segment. + ResetAllMBInfo(enc); + } + if (!ok) { + return WebPEncodingSetError(enc->pic_, + VP8_ENC_ERROR_OUT_OF_MEMORY); // imprecise + } + return ok; +} + diff --git a/libraries/webp/src/enc/backward_references_cost_enc.c b/libraries/webp/src/enc/backward_references_cost_enc.c new file mode 100644 index 0000000000..6968ef3c9f --- /dev/null +++ b/libraries/webp/src/enc/backward_references_cost_enc.c @@ -0,0 +1,795 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Improves a given set of backward references by analyzing its bit cost. +// The algorithm is similar to the Zopfli compression algorithm but tailored to +// images. +// +// Author: Vincent Rabaud (vrabaud@google.com) +// + +#include +#include + +#include "src/dsp/lossless_common.h" +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" + +#define VALUES_IN_BYTE 256 + +extern void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs); +extern int VP8LDistanceToPlaneCode(int xsize, int dist); +extern void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v); + +typedef struct { + float alpha_[VALUES_IN_BYTE]; + float red_[VALUES_IN_BYTE]; + float blue_[VALUES_IN_BYTE]; + float distance_[NUM_DISTANCE_CODES]; + float* literal_; +} CostModel; + +static void ConvertPopulationCountTableToBitEstimates( + int num_symbols, const uint32_t population_counts[], float output[]) { + uint32_t sum = 0; + int nonzeros = 0; + int i; + for (i = 0; i < num_symbols; ++i) { + sum += population_counts[i]; + if (population_counts[i] > 0) { + ++nonzeros; + } + } + if (nonzeros <= 1) { + memset(output, 0, num_symbols * sizeof(*output)); + } else { + const float logsum = VP8LFastLog2(sum); + for (i = 0; i < num_symbols; ++i) { + output[i] = logsum - VP8LFastLog2(population_counts[i]); + } + } +} + +static int CostModelBuild(CostModel* const m, int xsize, int cache_bits, + const VP8LBackwardRefs* const refs) { + int ok = 0; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits); + if (histo == NULL) goto Error; + + // The following code is similar to VP8LHistogramCreate but converts the + // distance to plane code. + VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 1); + while (VP8LRefsCursorOk(&c)) { + VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, VP8LDistanceToPlaneCode, + xsize); + VP8LRefsCursorNext(&c); + } + + ConvertPopulationCountTableToBitEstimates( + VP8LHistogramNumCodes(histo->palette_code_bits_), histo->literal_, + m->literal_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->red_, m->red_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->blue_, m->blue_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->alpha_, m->alpha_); + ConvertPopulationCountTableToBitEstimates( + NUM_DISTANCE_CODES, histo->distance_, m->distance_); + ok = 1; + + Error: + VP8LFreeHistogram(histo); + return ok; +} + +static WEBP_INLINE float GetLiteralCost(const CostModel* const m, uint32_t v) { + return m->alpha_[v >> 24] + + m->red_[(v >> 16) & 0xff] + + m->literal_[(v >> 8) & 0xff] + + m->blue_[v & 0xff]; +} + +static WEBP_INLINE float GetCacheCost(const CostModel* const m, uint32_t idx) { + const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx; + return m->literal_[literal_idx]; +} + +static WEBP_INLINE float GetLengthCost(const CostModel* const m, + uint32_t length) { + int code, extra_bits; + VP8LPrefixEncodeBits(length, &code, &extra_bits); + return m->literal_[VALUES_IN_BYTE + code] + extra_bits; +} + +static WEBP_INLINE float GetDistanceCost(const CostModel* const m, + uint32_t distance) { + int code, extra_bits; + VP8LPrefixEncodeBits(distance, &code, &extra_bits); + return m->distance_[code] + extra_bits; +} + +static WEBP_INLINE void AddSingleLiteralWithCostModel( + const uint32_t* const argb, VP8LColorCache* const hashers, + const CostModel* const cost_model, int idx, int use_color_cache, + float prev_cost, float* const cost, uint16_t* const dist_array) { + float cost_val = prev_cost; + const uint32_t color = argb[idx]; + const int ix = use_color_cache ? VP8LColorCacheContains(hashers, color) : -1; + if (ix >= 0) { + // use_color_cache is true and hashers contains color + const float mul0 = 0.68f; + cost_val += GetCacheCost(cost_model, ix) * mul0; + } else { + const float mul1 = 0.82f; + if (use_color_cache) VP8LColorCacheInsert(hashers, color); + cost_val += GetLiteralCost(cost_model, color) * mul1; + } + if (cost[idx] > cost_val) { + cost[idx] = cost_val; + dist_array[idx] = 1; // only one is inserted. + } +} + +// ----------------------------------------------------------------------------- +// CostManager and interval handling + +// Empirical value to avoid high memory consumption but good for performance. +#define COST_CACHE_INTERVAL_SIZE_MAX 500 + +// To perform backward reference every pixel at index index_ is considered and +// the cost for the MAX_LENGTH following pixels computed. Those following pixels +// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of: +// cost_ = distance cost at index + GetLengthCost(cost_model, k) +// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an +// array of size MAX_LENGTH. +// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the +// minimal values using intervals of constant cost. +// An interval is defined by the index_ of the pixel that generated it and +// is only useful in a range of indices from start_ to end_ (exclusive), i.e. +// it contains the minimum value for pixels between start_ and end_. +// Intervals are stored in a linked list and ordered by start_. When a new +// interval has a better value, old intervals are split or removed. There are +// therefore no overlapping intervals. +typedef struct CostInterval CostInterval; +struct CostInterval { + float cost_; + int start_; + int end_; + int index_; + CostInterval* previous_; + CostInterval* next_; +}; + +// The GetLengthCost(cost_model, k) are cached in a CostCacheInterval. +typedef struct { + float cost_; + int start_; + int end_; // Exclusive. +} CostCacheInterval; + +// This structure is in charge of managing intervals and costs. +// It caches the different CostCacheInterval, caches the different +// GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose +// count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX). +#define COST_MANAGER_MAX_FREE_LIST 10 +typedef struct { + CostInterval* head_; + int count_; // The number of stored intervals. + CostCacheInterval* cache_intervals_; + size_t cache_intervals_size_; + float cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k). + float* costs_; + uint16_t* dist_array_; + // Most of the time, we only need few intervals -> use a free-list, to avoid + // fragmentation with small allocs in most common cases. + CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST]; + CostInterval* free_intervals_; + // These are regularly malloc'd remains. This list can't grow larger than than + // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note. + CostInterval* recycled_intervals_; +} CostManager; + +static void CostIntervalAddToFreeList(CostManager* const manager, + CostInterval* const interval) { + interval->next_ = manager->free_intervals_; + manager->free_intervals_ = interval; +} + +static int CostIntervalIsInFreeList(const CostManager* const manager, + const CostInterval* const interval) { + return (interval >= &manager->intervals_[0] && + interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]); +} + +static void CostManagerInitFreeList(CostManager* const manager) { + int i; + manager->free_intervals_ = NULL; + for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) { + CostIntervalAddToFreeList(manager, &manager->intervals_[i]); + } +} + +static void DeleteIntervalList(CostManager* const manager, + const CostInterval* interval) { + while (interval != NULL) { + const CostInterval* const next = interval->next_; + if (!CostIntervalIsInFreeList(manager, interval)) { + WebPSafeFree((void*)interval); + } // else: do nothing + interval = next; + } +} + +static void CostManagerClear(CostManager* const manager) { + if (manager == NULL) return; + + WebPSafeFree(manager->costs_); + WebPSafeFree(manager->cache_intervals_); + + // Clear the interval lists. + DeleteIntervalList(manager, manager->head_); + manager->head_ = NULL; + DeleteIntervalList(manager, manager->recycled_intervals_); + manager->recycled_intervals_ = NULL; + + // Reset pointers, count_ and cache_intervals_size_. + memset(manager, 0, sizeof(*manager)); + CostManagerInitFreeList(manager); +} + +static int CostManagerInit(CostManager* const manager, + uint16_t* const dist_array, int pix_count, + const CostModel* const cost_model) { + int i; + const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count; + + manager->costs_ = NULL; + manager->cache_intervals_ = NULL; + manager->head_ = NULL; + manager->recycled_intervals_ = NULL; + manager->count_ = 0; + manager->dist_array_ = dist_array; + CostManagerInitFreeList(manager); + + // Fill in the cost_cache_. + // Has to be done in two passes due to a GCC bug on i686 + // related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 + for (i = 0; i < cost_cache_size; ++i) { + manager->cost_cache_[i] = GetLengthCost(cost_model, i); + } + manager->cache_intervals_size_ = 1; + for (i = 1; i < cost_cache_size; ++i) { + // Get the number of bound intervals. + if (manager->cost_cache_[i] != manager->cost_cache_[i - 1]) { + ++manager->cache_intervals_size_; + } + } + + // With the current cost model, we usually have below 20 intervals. + // The worst case scenario with a cost model would be if every length has a + // different cost, hence MAX_LENGTH but that is impossible with the current + // implementation that spirals around a pixel. + assert(manager->cache_intervals_size_ <= MAX_LENGTH); + manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc( + manager->cache_intervals_size_, sizeof(*manager->cache_intervals_)); + if (manager->cache_intervals_ == NULL) { + CostManagerClear(manager); + return 0; + } + + // Fill in the cache_intervals_. + { + CostCacheInterval* cur = manager->cache_intervals_; + + // Consecutive values in cost_cache_ are compared and if a big enough + // difference is found, a new interval is created and bounded. + cur->start_ = 0; + cur->end_ = 1; + cur->cost_ = manager->cost_cache_[0]; + for (i = 1; i < cost_cache_size; ++i) { + const float cost_val = manager->cost_cache_[i]; + if (cost_val != cur->cost_) { + ++cur; + // Initialize an interval. + cur->start_ = i; + cur->cost_ = cost_val; + } + cur->end_ = i + 1; + } + assert((size_t)(cur - manager->cache_intervals_) + 1 == + manager->cache_intervals_size_); + } + + manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_)); + if (manager->costs_ == NULL) { + CostManagerClear(manager); + return 0; + } + // Set the initial costs_ high for every pixel as we will keep the minimum. + for (i = 0; i < pix_count; ++i) manager->costs_[i] = FLT_MAX; + + return 1; +} + +// Given the cost and the position that define an interval, update the cost at +// pixel 'i' if it is smaller than the previously computed value. +static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, + int position, float cost) { + const int k = i - position; + assert(k >= 0 && k < MAX_LENGTH); + + if (manager->costs_[i] > cost) { + manager->costs_[i] = cost; + manager->dist_array_[i] = k + 1; + } +} + +// Given the cost and the position that define an interval, update the cost for +// all the pixels between 'start' and 'end' excluded. +static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager, + int start, int end, int position, + float cost) { + int i; + for (i = start; i < end; ++i) UpdateCost(manager, i, position, cost); +} + +// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'. +static WEBP_INLINE void ConnectIntervals(CostManager* const manager, + CostInterval* const prev, + CostInterval* const next) { + if (prev != NULL) { + prev->next_ = next; + } else { + manager->head_ = next; + } + + if (next != NULL) next->previous_ = prev; +} + +// Pop an interval in the manager. +static WEBP_INLINE void PopInterval(CostManager* const manager, + CostInterval* const interval) { + if (interval == NULL) return; + + ConnectIntervals(manager, interval->previous_, interval->next_); + if (CostIntervalIsInFreeList(manager, interval)) { + CostIntervalAddToFreeList(manager, interval); + } else { // recycle regularly malloc'd intervals too + interval->next_ = manager->recycled_intervals_; + manager->recycled_intervals_ = interval; + } + --manager->count_; + assert(manager->count_ >= 0); +} + +// Update the cost at index i by going over all the stored intervals that +// overlap with i. +// If 'do_clean_intervals' is set to something different than 0, intervals that +// end before 'i' will be popped. +static WEBP_INLINE void UpdateCostAtIndex(CostManager* const manager, int i, + int do_clean_intervals) { + CostInterval* current = manager->head_; + + while (current != NULL && current->start_ <= i) { + CostInterval* const next = current->next_; + if (current->end_ <= i) { + if (do_clean_intervals) { + // We have an outdated interval, remove it. + PopInterval(manager, current); + } + } else { + UpdateCost(manager, i, current->index_, current->cost_); + } + current = next; + } +} + +// Given a current orphan interval and its previous interval, before +// it was orphaned (which can be NULL), set it at the right place in the list +// of intervals using the start_ ordering and the previous interval as a hint. +static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager, + CostInterval* const current, + CostInterval* previous) { + assert(current != NULL); + + if (previous == NULL) previous = manager->head_; + while (previous != NULL && current->start_ < previous->start_) { + previous = previous->previous_; + } + while (previous != NULL && previous->next_ != NULL && + previous->next_->start_ < current->start_) { + previous = previous->next_; + } + + if (previous != NULL) { + ConnectIntervals(manager, current, previous->next_); + } else { + ConnectIntervals(manager, current, manager->head_); + } + ConnectIntervals(manager, previous, current); +} + +// Insert an interval in the list contained in the manager by starting at +// interval_in as a hint. The intervals are sorted by start_ value. +static WEBP_INLINE void InsertInterval(CostManager* const manager, + CostInterval* const interval_in, + float cost, int position, int start, + int end) { + CostInterval* interval_new; + + if (start >= end) return; + if (manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) { + // Serialize the interval if we cannot store it. + UpdateCostPerInterval(manager, start, end, position, cost); + return; + } + if (manager->free_intervals_ != NULL) { + interval_new = manager->free_intervals_; + manager->free_intervals_ = interval_new->next_; + } else if (manager->recycled_intervals_ != NULL) { + interval_new = manager->recycled_intervals_; + manager->recycled_intervals_ = interval_new->next_; + } else { // malloc for good + interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new)); + if (interval_new == NULL) { + // Write down the interval if we cannot create it. + UpdateCostPerInterval(manager, start, end, position, cost); + return; + } + } + + interval_new->cost_ = cost; + interval_new->index_ = position; + interval_new->start_ = start; + interval_new->end_ = end; + PositionOrphanInterval(manager, interval_new, interval_in); + + ++manager->count_; +} + +// Given a new cost interval defined by its start at position, its length value +// and distance_cost, add its contributions to the previous intervals and costs. +// If handling the interval or one of its subintervals becomes to heavy, its +// contribution is added to the costs right away. +static WEBP_INLINE void PushInterval(CostManager* const manager, + float distance_cost, int position, + int len) { + size_t i; + CostInterval* interval = manager->head_; + CostInterval* interval_next; + const CostCacheInterval* const cost_cache_intervals = + manager->cache_intervals_; + // If the interval is small enough, no need to deal with the heavy + // interval logic, just serialize it right away. This constant is empirical. + const int kSkipDistance = 10; + + if (len < kSkipDistance) { + int j; + for (j = position; j < position + len; ++j) { + const int k = j - position; + float cost_tmp; + assert(k >= 0 && k < MAX_LENGTH); + cost_tmp = distance_cost + manager->cost_cache_[k]; + + if (manager->costs_[j] > cost_tmp) { + manager->costs_[j] = cost_tmp; + manager->dist_array_[j] = k + 1; + } + } + return; + } + + for (i = 0; i < manager->cache_intervals_size_ && + cost_cache_intervals[i].start_ < len; + ++i) { + // Define the intersection of the ith interval with the new one. + int start = position + cost_cache_intervals[i].start_; + const int end = position + (cost_cache_intervals[i].end_ > len + ? len + : cost_cache_intervals[i].end_); + const float cost = distance_cost + cost_cache_intervals[i].cost_; + + for (; interval != NULL && interval->start_ < end; + interval = interval_next) { + interval_next = interval->next_; + + // Make sure we have some overlap + if (start >= interval->end_) continue; + + if (cost >= interval->cost_) { + // When intervals are represented, the lower, the better. + // [**********************************************************[ + // start end + // [----------------------------------[ + // interval->start_ interval->end_ + // If we are worse than what we already have, add whatever we have so + // far up to interval. + const int start_new = interval->end_; + InsertInterval(manager, interval, cost, position, start, + interval->start_); + start = start_new; + if (start >= end) break; + continue; + } + + if (start <= interval->start_) { + if (interval->end_ <= end) { + // [----------------------------------[ + // interval->start_ interval->end_ + // [**************************************************************[ + // start end + // We can safely remove the old interval as it is fully included. + PopInterval(manager, interval); + } else { + // [------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + interval->start_ = end; + break; + } + } else { + if (end < interval->end_) { + // [--------------------------------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + // We have to split the old interval as it fully contains the new one. + const int end_original = interval->end_; + interval->end_ = start; + InsertInterval(manager, interval, interval->cost_, interval->index_, + end, end_original); + interval = interval->next_; + break; + } else { + // [------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + interval->end_ = start; + } + } + } + // Insert the remaining interval from start to end. + InsertInterval(manager, interval, cost, position, start, end); + } +} + +static int BackwardReferencesHashChainDistanceOnly( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, const VP8LBackwardRefs* const refs, + uint16_t* const dist_array) { + int i; + int ok = 0; + int cc_init = 0; + const int pix_count = xsize * ysize; + const int use_color_cache = (cache_bits > 0); + const size_t literal_array_size = + sizeof(float) * (VP8LHistogramNumCodes(cache_bits)); + const size_t cost_model_size = sizeof(CostModel) + literal_array_size; + CostModel* const cost_model = + (CostModel*)WebPSafeCalloc(1ULL, cost_model_size); + VP8LColorCache hashers; + CostManager* cost_manager = + (CostManager*)WebPSafeCalloc(1ULL, sizeof(*cost_manager)); + int offset_prev = -1, len_prev = -1; + float offset_cost = -1.f; + int first_offset_is_constant = -1; // initialized with 'impossible' value + int reach = 0; + + if (cost_model == NULL || cost_manager == NULL) goto Error; + + cost_model->literal_ = (float*)(cost_model + 1); + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + if (!CostModelBuild(cost_model, xsize, cache_bits, refs)) { + goto Error; + } + + if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) { + goto Error; + } + + // We loop one pixel at a time, but store all currently best points to + // non-processed locations from this point. + dist_array[0] = 0; + // Add first pixel as literal. + AddSingleLiteralWithCostModel(argb, &hashers, cost_model, 0, use_color_cache, + 0.f, cost_manager->costs_, dist_array); + + for (i = 1; i < pix_count; ++i) { + const float prev_cost = cost_manager->costs_[i - 1]; + int offset, len; + VP8LHashChainFindCopy(hash_chain, i, &offset, &len); + + // Try adding the pixel as a literal. + AddSingleLiteralWithCostModel(argb, &hashers, cost_model, i, + use_color_cache, prev_cost, + cost_manager->costs_, dist_array); + + // If we are dealing with a non-literal. + if (len >= 2) { + if (offset != offset_prev) { + const int code = VP8LDistanceToPlaneCode(xsize, offset); + offset_cost = GetDistanceCost(cost_model, code); + first_offset_is_constant = 1; + PushInterval(cost_manager, prev_cost + offset_cost, i, len); + } else { + assert(offset_cost >= 0); + assert(len_prev >= 0); + assert(first_offset_is_constant == 0 || first_offset_is_constant == 1); + // Instead of considering all contributions from a pixel i by calling: + // PushInterval(cost_manager, prev_cost + offset_cost, i, len); + // we optimize these contributions in case offset_cost stays the same + // for consecutive pixels. This describes a set of pixels similar to a + // previous set (e.g. constant color regions). + if (first_offset_is_constant) { + reach = i - 1 + len_prev - 1; + first_offset_is_constant = 0; + } + + if (i + len - 1 > reach) { + // We can only be go further with the same offset if the previous + // length was maxed, hence len_prev == len == MAX_LENGTH. + // TODO(vrabaud), bump i to the end right away (insert cache and + // update cost). + // TODO(vrabaud), check if one of the points in between does not have + // a lower cost. + // Already consider the pixel at "reach" to add intervals that are + // better than whatever we add. + int offset_j, len_j = 0; + int j; + assert(len == MAX_LENGTH || len == pix_count - i); + // Figure out the last consecutive pixel within [i, reach + 1] with + // the same offset. + for (j = i; j <= reach; ++j) { + VP8LHashChainFindCopy(hash_chain, j + 1, &offset_j, &len_j); + if (offset_j != offset) { + VP8LHashChainFindCopy(hash_chain, j, &offset_j, &len_j); + break; + } + } + // Update the cost at j - 1 and j. + UpdateCostAtIndex(cost_manager, j - 1, 0); + UpdateCostAtIndex(cost_manager, j, 0); + + PushInterval(cost_manager, cost_manager->costs_[j - 1] + offset_cost, + j, len_j); + reach = j + len_j - 1; + } + } + } + + UpdateCostAtIndex(cost_manager, i, 1); + offset_prev = offset; + len_prev = len; + } + + ok = !refs->error_; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + CostManagerClear(cost_manager); + WebPSafeFree(cost_model); + WebPSafeFree(cost_manager); + return ok; +} + +// We pack the path at the end of *dist_array and return +// a pointer to this part of the array. Example: +// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232] +static void TraceBackwards(uint16_t* const dist_array, + int dist_array_size, + uint16_t** const chosen_path, + int* const chosen_path_size) { + uint16_t* path = dist_array + dist_array_size; + uint16_t* cur = dist_array + dist_array_size - 1; + while (cur >= dist_array) { + const int k = *cur; + --path; + *path = k; + cur -= k; + } + *chosen_path = path; + *chosen_path_size = (int)(dist_array + dist_array_size - path); +} + +static int BackwardReferencesHashChainFollowChosenPath( + const uint32_t* const argb, int cache_bits, + const uint16_t* const chosen_path, int chosen_path_size, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) { + const int use_color_cache = (cache_bits > 0); + int ix; + int i = 0; + int ok = 0; + int cc_init = 0; + VP8LColorCache hashers; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + VP8LClearBackwardRefs(refs); + for (ix = 0; ix < chosen_path_size; ++ix) { + const int len = chosen_path[ix]; + if (len != 1) { + int k; + const int offset = VP8LHashChainFindOffset(hash_chain, i); + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); + if (use_color_cache) { + for (k = 0; k < len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + i += len; + } else { + PixOrCopy v; + const int idx = + use_color_cache ? VP8LColorCacheContains(&hashers, argb[i]) : -1; + if (idx >= 0) { + // use_color_cache is true and hashers contains argb[i] + // push pixel as a color cache index + v = PixOrCopyCreateCacheIdx(idx); + } else { + if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); + v = PixOrCopyCreateLiteral(argb[i]); + } + VP8LBackwardRefsCursorAdd(refs, v); + ++i; + } + } + ok = !refs->error_; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + return ok; +} + +// Returns 1 on success. +extern int VP8LBackwardReferencesTraceBackwards( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, VP8LBackwardRefs* const refs_dst); +int VP8LBackwardReferencesTraceBackwards(int xsize, int ysize, + const uint32_t* const argb, + int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, + VP8LBackwardRefs* const refs_dst) { + int ok = 0; + const int dist_array_size = xsize * ysize; + uint16_t* chosen_path = NULL; + int chosen_path_size = 0; + uint16_t* dist_array = + (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array)); + + if (dist_array == NULL) goto Error; + + if (!BackwardReferencesHashChainDistanceOnly( + xsize, ysize, argb, cache_bits, hash_chain, refs_src, dist_array)) { + goto Error; + } + TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size); + if (!BackwardReferencesHashChainFollowChosenPath( + argb, cache_bits, chosen_path, chosen_path_size, hash_chain, + refs_dst)) { + goto Error; + } + ok = 1; + Error: + WebPSafeFree(dist_array); + return ok; +} diff --git a/libraries/webp/src/enc/backward_references_enc.c b/libraries/webp/src/enc/backward_references_enc.c new file mode 100644 index 0000000000..873aa8f22c --- /dev/null +++ b/libraries/webp/src/enc/backward_references_enc.c @@ -0,0 +1,1065 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +#include "src/enc/backward_references_enc.h" + +#include +#include +#include + +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/histogram_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" +#include "include/webp/encode.h" + +#define MIN_BLOCK_SIZE 256 // minimum block size for backward references + +#define MAX_ENTROPY (1e30f) + +// 1M window (4M bytes) minus 120 special codes for short distances. +#define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120) + +// Minimum number of pixels for which it is cheaper to encode a +// distance + length instead of each pixel as a literal. +#define MIN_LENGTH 4 + +// ----------------------------------------------------------------------------- + +static const uint8_t plane_to_code_lut[128] = { + 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255, + 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79, + 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87, + 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91, + 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100, + 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109, + 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114, + 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117 +}; + +extern int VP8LDistanceToPlaneCode(int xsize, int dist); +int VP8LDistanceToPlaneCode(int xsize, int dist) { + const int yoffset = dist / xsize; + const int xoffset = dist - yoffset * xsize; + if (xoffset <= 8 && yoffset < 8) { + return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1; + } else if (xoffset > xsize - 8 && yoffset < 7) { + return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1; + } + return dist + 120; +} + +// Returns the exact index where array1 and array2 are different. For an index +// inferior or equal to best_len_match, the return value just has to be strictly +// inferior to best_len_match. The current behavior is to return 0 if this index +// is best_len_match, and the index itself otherwise. +// If no two elements are the same, it returns max_limit. +static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, + const uint32_t* const array2, + int best_len_match, int max_limit) { + // Before 'expensive' linear match, check if the two arrays match at the + // current best length index. + if (array1[best_len_match] != array2[best_len_match]) return 0; + + return VP8LVectorMismatch(array1, array2, max_limit); +} + +// ----------------------------------------------------------------------------- +// VP8LBackwardRefs + +struct PixOrCopyBlock { + PixOrCopyBlock* next_; // next block (or NULL) + PixOrCopy* start_; // data start + int size_; // currently used size +}; + +extern void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs); +void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) { + assert(refs != NULL); + if (refs->tail_ != NULL) { + *refs->tail_ = refs->free_blocks_; // recycle all blocks at once + } + refs->free_blocks_ = refs->refs_; + refs->tail_ = &refs->refs_; + refs->last_block_ = NULL; + refs->refs_ = NULL; +} + +void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) { + assert(refs != NULL); + VP8LClearBackwardRefs(refs); + while (refs->free_blocks_ != NULL) { + PixOrCopyBlock* const next = refs->free_blocks_->next_; + WebPSafeFree(refs->free_blocks_); + refs->free_blocks_ = next; + } +} + +// Swaps the content of two VP8LBackwardRefs. +static void BackwardRefsSwap(VP8LBackwardRefs* const refs1, + VP8LBackwardRefs* const refs2) { + const int point_to_refs1 = + (refs1->tail_ != NULL && refs1->tail_ == &refs1->refs_); + const int point_to_refs2 = + (refs2->tail_ != NULL && refs2->tail_ == &refs2->refs_); + const VP8LBackwardRefs tmp = *refs1; + *refs1 = *refs2; + *refs2 = tmp; + if (point_to_refs2) refs1->tail_ = &refs1->refs_; + if (point_to_refs1) refs2->tail_ = &refs2->refs_; +} + +void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) { + assert(refs != NULL); + memset(refs, 0, sizeof(*refs)); + refs->tail_ = &refs->refs_; + refs->block_size_ = + (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size; +} + +VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) { + VP8LRefsCursor c; + c.cur_block_ = refs->refs_; + if (refs->refs_ != NULL) { + c.cur_pos = c.cur_block_->start_; + c.last_pos_ = c.cur_pos + c.cur_block_->size_; + } else { + c.cur_pos = NULL; + c.last_pos_ = NULL; + } + return c; +} + +void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) { + PixOrCopyBlock* const b = c->cur_block_->next_; + c->cur_pos = (b == NULL) ? NULL : b->start_; + c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_; + c->cur_block_ = b; +} + +// Create a new block, either from the free list or allocated +static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) { + PixOrCopyBlock* b = refs->free_blocks_; + if (b == NULL) { // allocate new memory chunk + const size_t total_size = + sizeof(*b) + refs->block_size_ * sizeof(*b->start_); + b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size); + if (b == NULL) { + refs->error_ |= 1; + return NULL; + } + b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned + } else { // recycle from free-list + refs->free_blocks_ = b->next_; + } + *refs->tail_ = b; + refs->tail_ = &b->next_; + refs->last_block_ = b; + b->next_ = NULL; + b->size_ = 0; + return b; +} + +// Return 1 on success, 0 on error. +static int BackwardRefsClone(const VP8LBackwardRefs* const from, + VP8LBackwardRefs* const to) { + const PixOrCopyBlock* block_from = from->refs_; + VP8LClearBackwardRefs(to); + while (block_from != NULL) { + PixOrCopyBlock* const block_to = BackwardRefsNewBlock(to); + if (block_to == NULL) return 0; + memcpy(block_to->start_, block_from->start_, + block_from->size_ * sizeof(PixOrCopy)); + block_to->size_ = block_from->size_; + block_from = block_from->next_; + } + return 1; +} + +extern void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v); +void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v) { + PixOrCopyBlock* b = refs->last_block_; + if (b == NULL || b->size_ == refs->block_size_) { + b = BackwardRefsNewBlock(refs); + if (b == NULL) return; // refs->error_ is set + } + b->start_[b->size_++] = v; +} + +// ----------------------------------------------------------------------------- +// Hash chains + +int VP8LHashChainInit(VP8LHashChain* const p, int size) { + assert(p->size_ == 0); + assert(p->offset_length_ == NULL); + assert(size > 0); + p->offset_length_ = + (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_)); + if (p->offset_length_ == NULL) return 0; + p->size_ = size; + + return 1; +} + +void VP8LHashChainClear(VP8LHashChain* const p) { + assert(p != NULL); + WebPSafeFree(p->offset_length_); + + p->size_ = 0; + p->offset_length_ = NULL; +} + +// ----------------------------------------------------------------------------- + +static const uint32_t kHashMultiplierHi = 0xc6a4a793u; +static const uint32_t kHashMultiplierLo = 0x5bd1e996u; + +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +uint32_t GetPixPairHash64(const uint32_t* const argb) { + uint32_t key; + key = argb[1] * kHashMultiplierHi; + key += argb[0] * kHashMultiplierLo; + key = key >> (32 - HASH_BITS); + return key; +} + +// Returns the maximum number of hash chain lookups to do for a +// given compression quality. Return value in range [8, 86]. +static int GetMaxItersForQuality(int quality) { + return 8 + (quality * quality) / 128; +} + +static int GetWindowSizeForHashChain(int quality, int xsize) { + const int max_window_size = (quality > 75) ? WINDOW_SIZE + : (quality > 50) ? (xsize << 8) + : (quality > 25) ? (xsize << 6) + : (xsize << 4); + assert(xsize > 0); + return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size; +} + +static WEBP_INLINE int MaxFindCopyLength(int len) { + return (len < MAX_LENGTH) ? len : MAX_LENGTH; +} + +int VP8LHashChainFill(VP8LHashChain* const p, int quality, + const uint32_t* const argb, int xsize, int ysize, + int low_effort, const WebPPicture* const pic, + int percent_range, int* const percent) { + const int size = xsize * ysize; + const int iter_max = GetMaxItersForQuality(quality); + const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize); + int remaining_percent = percent_range; + int percent_start = *percent; + int pos; + int argb_comp; + uint32_t base_position; + int32_t* hash_to_first_index; + // Temporarily use the p->offset_length_ as a hash chain. + int32_t* chain = (int32_t*)p->offset_length_; + assert(size > 0); + assert(p->size_ != 0); + assert(p->offset_length_ != NULL); + + if (size <= 2) { + p->offset_length_[0] = p->offset_length_[size - 1] = 0; + return 1; + } + + hash_to_first_index = + (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index)); + if (hash_to_first_index == NULL) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + percent_range = remaining_percent / 2; + remaining_percent -= percent_range; + + // Set the int32_t array to -1. + memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index)); + // Fill the chain linking pixels with the same hash. + argb_comp = (argb[0] == argb[1]); + for (pos = 0; pos < size - 2;) { + uint32_t hash_code; + const int argb_comp_next = (argb[pos + 1] == argb[pos + 2]); + if (argb_comp && argb_comp_next) { + // Consecutive pixels with the same color will share the same hash. + // We therefore use a different hash: the color and its repetition + // length. + uint32_t tmp[2]; + uint32_t len = 1; + tmp[0] = argb[pos]; + // Figure out how far the pixels are the same. + // The last pixel has a different 64 bit hash, as its next pixel does + // not have the same color, so we just need to get to the last pixel equal + // to its follower. + while (pos + (int)len + 2 < size && argb[pos + len + 2] == argb[pos]) { + ++len; + } + if (len > MAX_LENGTH) { + // Skip the pixels that match for distance=1 and length>MAX_LENGTH + // because they are linked to their predecessor and we automatically + // check that in the main for loop below. Skipping means setting no + // predecessor in the chain, hence -1. + memset(chain + pos, 0xff, (len - MAX_LENGTH) * sizeof(*chain)); + pos += len - MAX_LENGTH; + len = MAX_LENGTH; + } + // Process the rest of the hash chain. + while (len) { + tmp[1] = len--; + hash_code = GetPixPairHash64(tmp); + chain[pos] = hash_to_first_index[hash_code]; + hash_to_first_index[hash_code] = pos++; + } + argb_comp = 0; + } else { + // Just move one pixel forward. + hash_code = GetPixPairHash64(argb + pos); + chain[pos] = hash_to_first_index[hash_code]; + hash_to_first_index[hash_code] = pos++; + argb_comp = argb_comp_next; + } + + if (!WebPReportProgress( + pic, percent_start + percent_range * pos / (size - 2), percent)) { + WebPSafeFree(hash_to_first_index); + return 0; + } + } + // Process the penultimate pixel. + chain[pos] = hash_to_first_index[GetPixPairHash64(argb + pos)]; + + WebPSafeFree(hash_to_first_index); + + percent_start += percent_range; + if (!WebPReportProgress(pic, percent_start, percent)) return 0; + percent_range = remaining_percent; + + // Find the best match interval at each pixel, defined by an offset to the + // pixel and a length. The right-most pixel cannot match anything to the right + // (hence a best length of 0) and the left-most pixel nothing to the left + // (hence an offset of 0). + assert(size > 2); + p->offset_length_[0] = p->offset_length_[size - 1] = 0; + for (base_position = size - 2; base_position > 0;) { + const int max_len = MaxFindCopyLength(size - 1 - base_position); + const uint32_t* const argb_start = argb + base_position; + int iter = iter_max; + int best_length = 0; + uint32_t best_distance = 0; + uint32_t best_argb; + const int min_pos = + (base_position > window_size) ? base_position - window_size : 0; + const int length_max = (max_len < 256) ? max_len : 256; + uint32_t max_base_position; + + pos = chain[base_position]; + if (!low_effort) { + int curr_length; + // Heuristic: use the comparison with the above line as an initialization. + if (base_position >= (uint32_t)xsize) { + curr_length = FindMatchLength(argb_start - xsize, argb_start, + best_length, max_len); + if (curr_length > best_length) { + best_length = curr_length; + best_distance = xsize; + } + --iter; + } + // Heuristic: compare to the previous pixel. + curr_length = + FindMatchLength(argb_start - 1, argb_start, best_length, max_len); + if (curr_length > best_length) { + best_length = curr_length; + best_distance = 1; + } + --iter; + // Skip the for loop if we already have the maximum. + if (best_length == MAX_LENGTH) pos = min_pos - 1; + } + best_argb = argb_start[best_length]; + + for (; pos >= min_pos && --iter; pos = chain[pos]) { + int curr_length; + assert(base_position > (uint32_t)pos); + + if (argb[pos + best_length] != best_argb) continue; + + curr_length = VP8LVectorMismatch(argb + pos, argb_start, max_len); + if (best_length < curr_length) { + best_length = curr_length; + best_distance = base_position - pos; + best_argb = argb_start[best_length]; + // Stop if we have reached a good enough length. + if (best_length >= length_max) break; + } + } + // We have the best match but in case the two intervals continue matching + // to the left, we have the best matches for the left-extended pixels. + max_base_position = base_position; + while (1) { + assert(best_length <= MAX_LENGTH); + assert(best_distance <= WINDOW_SIZE); + p->offset_length_[base_position] = + (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length; + --base_position; + // Stop if we don't have a match or if we are out of bounds. + if (best_distance == 0 || base_position == 0) break; + // Stop if we cannot extend the matching intervals to the left. + if (base_position < best_distance || + argb[base_position - best_distance] != argb[base_position]) { + break; + } + // Stop if we are matching at its limit because there could be a closer + // matching interval with the same maximum length. Then again, if the + // matching interval is as close as possible (best_distance == 1), we will + // never find anything better so let's continue. + if (best_length == MAX_LENGTH && best_distance != 1 && + base_position + MAX_LENGTH < max_base_position) { + break; + } + if (best_length < MAX_LENGTH) { + ++best_length; + max_base_position = base_position; + } + } + + if (!WebPReportProgress(pic, + percent_start + percent_range * + (size - 2 - base_position) / + (size - 2), + percent)) { + return 0; + } + } + + return WebPReportProgress(pic, percent_start + percent_range, percent); +} + +static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache, + VP8LColorCache* const hashers, + VP8LBackwardRefs* const refs) { + PixOrCopy v; + if (use_color_cache) { + const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel); + if (VP8LColorCacheLookup(hashers, key) == pixel) { + v = PixOrCopyCreateCacheIdx(key); + } else { + v = PixOrCopyCreateLiteral(pixel); + VP8LColorCacheSet(hashers, key, pixel); + } + } else { + v = PixOrCopyCreateLiteral(pixel); + } + VP8LBackwardRefsCursorAdd(refs, v); +} + +static int BackwardReferencesRle(int xsize, int ysize, + const uint32_t* const argb, + int cache_bits, VP8LBackwardRefs* const refs) { + const int pix_count = xsize * ysize; + int i, k; + const int use_color_cache = (cache_bits > 0); + VP8LColorCache hashers; + + if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) { + return 0; + } + VP8LClearBackwardRefs(refs); + // Add first pixel as literal. + AddSingleLiteral(argb[0], use_color_cache, &hashers, refs); + i = 1; + while (i < pix_count) { + const int max_len = MaxFindCopyLength(pix_count - i); + const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len); + const int prev_row_len = (i < xsize) ? 0 : + FindMatchLength(argb + i, argb + i - xsize, 0, max_len); + if (rle_len >= prev_row_len && rle_len >= MIN_LENGTH) { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len)); + // We don't need to update the color cache here since it is always the + // same pixel being copied, and that does not change the color cache + // state. + i += rle_len; + } else if (prev_row_len >= MIN_LENGTH) { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len)); + if (use_color_cache) { + for (k = 0; k < prev_row_len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + i += prev_row_len; + } else { + AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); + i++; + } + } + if (use_color_cache) VP8LColorCacheClear(&hashers); + return !refs->error_; +} + +static int BackwardReferencesLz77(int xsize, int ysize, + const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs) { + int i; + int i_last_check = -1; + int ok = 0; + int cc_init = 0; + const int use_color_cache = (cache_bits > 0); + const int pix_count = xsize * ysize; + VP8LColorCache hashers; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + VP8LClearBackwardRefs(refs); + for (i = 0; i < pix_count;) { + // Alternative#1: Code the pixels starting at 'i' using backward reference. + int offset = 0; + int len = 0; + int j; + VP8LHashChainFindCopy(hash_chain, i, &offset, &len); + if (len >= MIN_LENGTH) { + const int len_ini = len; + int max_reach = 0; + const int j_max = + (i + len_ini >= pix_count) ? pix_count - 1 : i + len_ini; + // Only start from what we have not checked already. + i_last_check = (i > i_last_check) ? i : i_last_check; + // We know the best match for the current pixel but we try to find the + // best matches for the current pixel AND the next one combined. + // The naive method would use the intervals: + // [i,i+len) + [i+len, length of best match at i+len) + // while we check if we can use: + // [i,j) (where j<=i+len) + [j, length of best match at j) + for (j = i_last_check + 1; j <= j_max; ++j) { + const int len_j = VP8LHashChainFindLength(hash_chain, j); + const int reach = + j + (len_j >= MIN_LENGTH ? len_j : 1); // 1 for single literal. + if (reach > max_reach) { + len = j - i; + max_reach = reach; + if (max_reach >= pix_count) break; + } + } + } else { + len = 1; + } + // Go with literal or backward reference. + assert(len > 0); + if (len == 1) { + AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); + } else { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); + if (use_color_cache) { + for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]); + } + } + i += len; + } + + ok = !refs->error_; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + return ok; +} + +// Compute an LZ77 by forcing matches to happen within a given distance cost. +// We therefore limit the algorithm to the lowest 32 values in the PlaneCode +// definition. +#define WINDOW_OFFSETS_SIZE_MAX 32 +static int BackwardReferencesLz77Box(int xsize, int ysize, + const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain_best, + VP8LHashChain* hash_chain, + VP8LBackwardRefs* const refs) { + int i; + const int pix_count = xsize * ysize; + uint16_t* counts; + int window_offsets[WINDOW_OFFSETS_SIZE_MAX] = {0}; + int window_offsets_new[WINDOW_OFFSETS_SIZE_MAX] = {0}; + int window_offsets_size = 0; + int window_offsets_new_size = 0; + uint16_t* const counts_ini = + (uint16_t*)WebPSafeMalloc(xsize * ysize, sizeof(*counts_ini)); + int best_offset_prev = -1, best_length_prev = -1; + if (counts_ini == NULL) return 0; + + // counts[i] counts how many times a pixel is repeated starting at position i. + i = pix_count - 2; + counts = counts_ini + i; + counts[1] = 1; + for (; i >= 0; --i, --counts) { + if (argb[i] == argb[i + 1]) { + // Max out the counts to MAX_LENGTH. + counts[0] = counts[1] + (counts[1] != MAX_LENGTH); + } else { + counts[0] = 1; + } + } + + // Figure out the window offsets around a pixel. They are stored in a + // spiraling order around the pixel as defined by VP8LDistanceToPlaneCode. + { + int x, y; + for (y = 0; y <= 6; ++y) { + for (x = -6; x <= 6; ++x) { + const int offset = y * xsize + x; + int plane_code; + // Ignore offsets that bring us after the pixel. + if (offset <= 0) continue; + plane_code = VP8LDistanceToPlaneCode(xsize, offset) - 1; + if (plane_code >= WINDOW_OFFSETS_SIZE_MAX) continue; + window_offsets[plane_code] = offset; + } + } + // For narrow images, not all plane codes are reached, so remove those. + for (i = 0; i < WINDOW_OFFSETS_SIZE_MAX; ++i) { + if (window_offsets[i] == 0) continue; + window_offsets[window_offsets_size++] = window_offsets[i]; + } + // Given a pixel P, find the offsets that reach pixels unreachable from P-1 + // with any of the offsets in window_offsets[]. + for (i = 0; i < window_offsets_size; ++i) { + int j; + int is_reachable = 0; + for (j = 0; j < window_offsets_size && !is_reachable; ++j) { + is_reachable |= (window_offsets[i] == window_offsets[j] + 1); + } + if (!is_reachable) { + window_offsets_new[window_offsets_new_size] = window_offsets[i]; + ++window_offsets_new_size; + } + } + } + + hash_chain->offset_length_[0] = 0; + for (i = 1; i < pix_count; ++i) { + int ind; + int best_length = VP8LHashChainFindLength(hash_chain_best, i); + int best_offset; + int do_compute = 1; + + if (best_length >= MAX_LENGTH) { + // Do not recompute the best match if we already have a maximal one in the + // window. + best_offset = VP8LHashChainFindOffset(hash_chain_best, i); + for (ind = 0; ind < window_offsets_size; ++ind) { + if (best_offset == window_offsets[ind]) { + do_compute = 0; + break; + } + } + } + if (do_compute) { + // Figure out if we should use the offset/length from the previous pixel + // as an initial guess and therefore only inspect the offsets in + // window_offsets_new[]. + const int use_prev = + (best_length_prev > 1) && (best_length_prev < MAX_LENGTH); + const int num_ind = + use_prev ? window_offsets_new_size : window_offsets_size; + best_length = use_prev ? best_length_prev - 1 : 0; + best_offset = use_prev ? best_offset_prev : 0; + // Find the longest match in a window around the pixel. + for (ind = 0; ind < num_ind; ++ind) { + int curr_length = 0; + int j = i; + int j_offset = + use_prev ? i - window_offsets_new[ind] : i - window_offsets[ind]; + if (j_offset < 0 || argb[j_offset] != argb[i]) continue; + // The longest match is the sum of how many times each pixel is + // repeated. + do { + const int counts_j_offset = counts_ini[j_offset]; + const int counts_j = counts_ini[j]; + if (counts_j_offset != counts_j) { + curr_length += + (counts_j_offset < counts_j) ? counts_j_offset : counts_j; + break; + } + // The same color is repeated counts_pos times at j_offset and j. + curr_length += counts_j_offset; + j_offset += counts_j_offset; + j += counts_j_offset; + } while (curr_length <= MAX_LENGTH && j < pix_count && + argb[j_offset] == argb[j]); + if (best_length < curr_length) { + best_offset = + use_prev ? window_offsets_new[ind] : window_offsets[ind]; + if (curr_length >= MAX_LENGTH) { + best_length = MAX_LENGTH; + break; + } else { + best_length = curr_length; + } + } + } + } + + assert(i + best_length <= pix_count); + assert(best_length <= MAX_LENGTH); + if (best_length <= MIN_LENGTH) { + hash_chain->offset_length_[i] = 0; + best_offset_prev = 0; + best_length_prev = 0; + } else { + hash_chain->offset_length_[i] = + (best_offset << MAX_LENGTH_BITS) | (uint32_t)best_length; + best_offset_prev = best_offset; + best_length_prev = best_length; + } + } + hash_chain->offset_length_[0] = 0; + WebPSafeFree(counts_ini); + + return BackwardReferencesLz77(xsize, ysize, argb, cache_bits, hash_chain, + refs); +} + +// ----------------------------------------------------------------------------- + +static void BackwardReferences2DLocality(int xsize, + const VP8LBackwardRefs* const refs) { + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + if (PixOrCopyIsCopy(c.cur_pos)) { + const int dist = c.cur_pos->argb_or_distance; + const int transformed_dist = VP8LDistanceToPlaneCode(xsize, dist); + c.cur_pos->argb_or_distance = transformed_dist; + } + VP8LRefsCursorNext(&c); + } +} + +// Evaluate optimal cache bits for the local color cache. +// The input *best_cache_bits sets the maximum cache bits to use (passing 0 +// implies disabling the local color cache). The local color cache is also +// disabled for the lower (<= 25) quality. +// Returns 0 in case of memory error. +static int CalculateBestCacheSize(const uint32_t* argb, int quality, + const VP8LBackwardRefs* const refs, + int* const best_cache_bits) { + int i; + const int cache_bits_max = (quality <= 25) ? 0 : *best_cache_bits; + float entropy_min = MAX_ENTROPY; + int cc_init[MAX_COLOR_CACHE_BITS + 1] = { 0 }; + VP8LColorCache hashers[MAX_COLOR_CACHE_BITS + 1]; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + VP8LHistogram* histos[MAX_COLOR_CACHE_BITS + 1] = { NULL }; + int ok = 0; + + assert(cache_bits_max >= 0 && cache_bits_max <= MAX_COLOR_CACHE_BITS); + + if (cache_bits_max == 0) { + *best_cache_bits = 0; + // Local color cache is disabled. + return 1; + } + + // Allocate data. + for (i = 0; i <= cache_bits_max; ++i) { + histos[i] = VP8LAllocateHistogram(i); + if (histos[i] == NULL) goto Error; + VP8LHistogramInit(histos[i], i, /*init_arrays=*/ 1); + if (i == 0) continue; + cc_init[i] = VP8LColorCacheInit(&hashers[i], i); + if (!cc_init[i]) goto Error; + } + + // Find the cache_bits giving the lowest entropy. The search is done in a + // brute-force way as the function (entropy w.r.t cache_bits) can be + // anything in practice. + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + if (PixOrCopyIsLiteral(v)) { + const uint32_t pix = *argb++; + const uint32_t a = (pix >> 24) & 0xff; + const uint32_t r = (pix >> 16) & 0xff; + const uint32_t g = (pix >> 8) & 0xff; + const uint32_t b = (pix >> 0) & 0xff; + // The keys of the caches can be derived from the longest one. + int key = VP8LHashPix(pix, 32 - cache_bits_max); + // Do not use the color cache for cache_bits = 0. + ++histos[0]->blue_[b]; + ++histos[0]->literal_[g]; + ++histos[0]->red_[r]; + ++histos[0]->alpha_[a]; + // Deal with cache_bits > 0. + for (i = cache_bits_max; i >= 1; --i, key >>= 1) { + if (VP8LColorCacheLookup(&hashers[i], key) == pix) { + ++histos[i]->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key]; + } else { + VP8LColorCacheSet(&hashers[i], key, pix); + ++histos[i]->blue_[b]; + ++histos[i]->literal_[g]; + ++histos[i]->red_[r]; + ++histos[i]->alpha_[a]; + } + } + } else { + int code, extra_bits, extra_bits_value; + // We should compute the contribution of the (distance,length) + // histograms but those are the same independently from the cache size. + // As those constant contributions are in the end added to the other + // histogram contributions, we can ignore them, except for the length + // prefix that is part of the literal_ histogram. + int len = PixOrCopyLength(v); + uint32_t argb_prev = *argb ^ 0xffffffffu; + VP8LPrefixEncode(len, &code, &extra_bits, &extra_bits_value); + for (i = 0; i <= cache_bits_max; ++i) { + ++histos[i]->literal_[NUM_LITERAL_CODES + code]; + } + // Update the color caches. + do { + if (*argb != argb_prev) { + // Efficiency: insert only if the color changes. + int key = VP8LHashPix(*argb, 32 - cache_bits_max); + for (i = cache_bits_max; i >= 1; --i, key >>= 1) { + hashers[i].colors_[key] = *argb; + } + argb_prev = *argb; + } + argb++; + } while (--len != 0); + } + VP8LRefsCursorNext(&c); + } + + for (i = 0; i <= cache_bits_max; ++i) { + const float entropy = VP8LHistogramEstimateBits(histos[i]); + if (i == 0 || entropy < entropy_min) { + entropy_min = entropy; + *best_cache_bits = i; + } + } + ok = 1; + Error: + for (i = 0; i <= cache_bits_max; ++i) { + if (cc_init[i]) VP8LColorCacheClear(&hashers[i]); + VP8LFreeHistogram(histos[i]); + } + return ok; +} + +// Update (in-place) backward references for specified cache_bits. +static int BackwardRefsWithLocalCache(const uint32_t* const argb, + int cache_bits, + VP8LBackwardRefs* const refs) { + int pixel_index = 0; + VP8LColorCache hashers; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0; + + while (VP8LRefsCursorOk(&c)) { + PixOrCopy* const v = c.cur_pos; + if (PixOrCopyIsLiteral(v)) { + const uint32_t argb_literal = v->argb_or_distance; + const int ix = VP8LColorCacheContains(&hashers, argb_literal); + if (ix >= 0) { + // hashers contains argb_literal + *v = PixOrCopyCreateCacheIdx(ix); + } else { + VP8LColorCacheInsert(&hashers, argb_literal); + } + ++pixel_index; + } else { + // refs was created without local cache, so it can not have cache indexes. + int k; + assert(PixOrCopyIsCopy(v)); + for (k = 0; k < v->len; ++k) { + VP8LColorCacheInsert(&hashers, argb[pixel_index++]); + } + } + VP8LRefsCursorNext(&c); + } + VP8LColorCacheClear(&hashers); + return 1; +} + +static VP8LBackwardRefs* GetBackwardReferencesLowEffort( + int width, int height, const uint32_t* const argb, + int* const cache_bits, const VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs_lz77) { + *cache_bits = 0; + if (!BackwardReferencesLz77(width, height, argb, 0, hash_chain, refs_lz77)) { + return NULL; + } + BackwardReferences2DLocality(width, refs_lz77); + return refs_lz77; +} + +extern int VP8LBackwardReferencesTraceBackwards( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, VP8LBackwardRefs* const refs_dst); +static int GetBackwardReferences(int width, int height, + const uint32_t* const argb, int quality, + int lz77_types_to_try, int cache_bits_max, + int do_no_cache, + const VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs, + int* const cache_bits_best) { + VP8LHistogram* histo = NULL; + int i, lz77_type; + // Index 0 is for a color cache, index 1 for no cache (if needed). + int lz77_types_best[2] = {0, 0}; + float bit_costs_best[2] = {FLT_MAX, FLT_MAX}; + VP8LHashChain hash_chain_box; + VP8LBackwardRefs* const refs_tmp = &refs[do_no_cache ? 2 : 1]; + int status = 0; + memset(&hash_chain_box, 0, sizeof(hash_chain_box)); + + histo = VP8LAllocateHistogram(MAX_COLOR_CACHE_BITS); + if (histo == NULL) goto Error; + + for (lz77_type = 1; lz77_types_to_try; + lz77_types_to_try &= ~lz77_type, lz77_type <<= 1) { + int res = 0; + float bit_cost = 0.f; + if ((lz77_types_to_try & lz77_type) == 0) continue; + switch (lz77_type) { + case kLZ77RLE: + res = BackwardReferencesRle(width, height, argb, 0, refs_tmp); + break; + case kLZ77Standard: + // Compute LZ77 with no cache (0 bits), as the ideal LZ77 with a color + // cache is not that different in practice. + res = BackwardReferencesLz77(width, height, argb, 0, hash_chain, + refs_tmp); + break; + case kLZ77Box: + if (!VP8LHashChainInit(&hash_chain_box, width * height)) goto Error; + res = BackwardReferencesLz77Box(width, height, argb, 0, hash_chain, + &hash_chain_box, refs_tmp); + break; + default: + assert(0); + } + if (!res) goto Error; + + // Start with the no color cache case. + for (i = 1; i >= 0; --i) { + int cache_bits = (i == 1) ? 0 : cache_bits_max; + + if (i == 1 && !do_no_cache) continue; + + if (i == 0) { + // Try with a color cache. + if (!CalculateBestCacheSize(argb, quality, refs_tmp, &cache_bits)) { + goto Error; + } + if (cache_bits > 0) { + if (!BackwardRefsWithLocalCache(argb, cache_bits, refs_tmp)) { + goto Error; + } + } + } + + if (i == 0 && do_no_cache && cache_bits == 0) { + // No need to re-compute bit_cost as it was computed at i == 1. + } else { + VP8LHistogramCreate(histo, refs_tmp, cache_bits); + bit_cost = VP8LHistogramEstimateBits(histo); + } + + if (bit_cost < bit_costs_best[i]) { + if (i == 1) { + // Do not swap as the full cache analysis would have the wrong + // VP8LBackwardRefs to start with. + if (!BackwardRefsClone(refs_tmp, &refs[1])) goto Error; + } else { + BackwardRefsSwap(refs_tmp, &refs[0]); + } + bit_costs_best[i] = bit_cost; + lz77_types_best[i] = lz77_type; + if (i == 0) *cache_bits_best = cache_bits; + } + } + } + assert(lz77_types_best[0] > 0); + assert(!do_no_cache || lz77_types_best[1] > 0); + + // Improve on simple LZ77 but only for high quality (TraceBackwards is + // costly). + for (i = 1; i >= 0; --i) { + if (i == 1 && !do_no_cache) continue; + if ((lz77_types_best[i] == kLZ77Standard || + lz77_types_best[i] == kLZ77Box) && + quality >= 25) { + const VP8LHashChain* const hash_chain_tmp = + (lz77_types_best[i] == kLZ77Standard) ? hash_chain : &hash_chain_box; + const int cache_bits = (i == 1) ? 0 : *cache_bits_best; + float bit_cost_trace; + if (!VP8LBackwardReferencesTraceBackwards(width, height, argb, cache_bits, + hash_chain_tmp, &refs[i], + refs_tmp)) { + goto Error; + } + VP8LHistogramCreate(histo, refs_tmp, cache_bits); + bit_cost_trace = VP8LHistogramEstimateBits(histo); + if (bit_cost_trace < bit_costs_best[i]) { + BackwardRefsSwap(refs_tmp, &refs[i]); + } + } + + BackwardReferences2DLocality(width, &refs[i]); + + if (i == 1 && lz77_types_best[0] == lz77_types_best[1] && + *cache_bits_best == 0) { + // If the best cache size is 0 and we have the same best LZ77, just copy + // the data over and stop here. + if (!BackwardRefsClone(&refs[1], &refs[0])) goto Error; + break; + } + } + status = 1; + + Error: + VP8LHashChainClear(&hash_chain_box); + VP8LFreeHistogram(histo); + return status; +} + +int VP8LGetBackwardReferences( + int width, int height, const uint32_t* const argb, int quality, + int low_effort, int lz77_types_to_try, int cache_bits_max, int do_no_cache, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs, + int* const cache_bits_best, const WebPPicture* const pic, int percent_range, + int* const percent) { + if (low_effort) { + VP8LBackwardRefs* refs_best; + *cache_bits_best = cache_bits_max; + refs_best = GetBackwardReferencesLowEffort( + width, height, argb, cache_bits_best, hash_chain, refs); + if (refs_best == NULL) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + // Set it in first position. + BackwardRefsSwap(refs_best, &refs[0]); + } else { + if (!GetBackwardReferences(width, height, argb, quality, lz77_types_to_try, + cache_bits_max, do_no_cache, hash_chain, refs, + cache_bits_best)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + } + + return WebPReportProgress(pic, *percent + percent_range, percent); +} diff --git a/libraries/webp/src/enc/backward_references_enc.h b/libraries/webp/src/enc/backward_references_enc.h new file mode 100644 index 0000000000..26a6e85e2f --- /dev/null +++ b/libraries/webp/src/enc/backward_references_enc.h @@ -0,0 +1,244 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +#ifndef WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ +#define WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ + +#include +#include +#include "include/webp/types.h" +#include "include/webp/encode.h" +#include "include/webp/format_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// The maximum allowed limit is 11. +#define MAX_COLOR_CACHE_BITS 10 + +// ----------------------------------------------------------------------------- +// PixOrCopy + +enum Mode { + kLiteral, + kCacheIdx, + kCopy, + kNone +}; + +typedef struct { + // mode as uint8_t to make the memory layout to be exactly 8 bytes. + uint8_t mode; + uint16_t len; + uint32_t argb_or_distance; +} PixOrCopy; + +static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance, + uint16_t len) { + PixOrCopy retval; + retval.mode = kCopy; + retval.argb_or_distance = distance; + retval.len = len; + return retval; +} + +static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) { + PixOrCopy retval; + assert(idx >= 0); + assert(idx < (1 << MAX_COLOR_CACHE_BITS)); + retval.mode = kCacheIdx; + retval.argb_or_distance = idx; + retval.len = 1; + return retval; +} + +static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) { + PixOrCopy retval; + retval.mode = kLiteral; + retval.argb_or_distance = argb; + retval.len = 1; + return retval; +} + +static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) { + return (p->mode == kLiteral); +} + +static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) { + return (p->mode == kCacheIdx); +} + +static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) { + return (p->mode == kCopy); +} + +static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p, + int component) { + assert(p->mode == kLiteral); + return (p->argb_or_distance >> (component * 8)) & 0xff; +} + +static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) { + return p->len; +} + +static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) { + assert(p->mode == kCacheIdx); + assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS)); + return p->argb_or_distance; +} + +static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) { + assert(p->mode == kCopy); + return p->argb_or_distance; +} + +// ----------------------------------------------------------------------------- +// VP8LHashChain + +#define HASH_BITS 18 +#define HASH_SIZE (1 << HASH_BITS) + +// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it +// is used in VP8LHashChain. +#define MAX_LENGTH_BITS 12 +#define WINDOW_SIZE_BITS 20 +// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits. +#define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1) +#if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32 +#error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32" +#endif + +typedef struct VP8LHashChain VP8LHashChain; +struct VP8LHashChain { + // The 20 most significant bits contain the offset at which the best match + // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain + // (through WINDOW_SIZE = 1<<20). + // The lower 12 bits contain the length of the match. The 12 bit limit is + // defined in MaxFindCopyLength with MAX_LENGTH=4096. + uint32_t* offset_length_; + // This is the maximum size of the hash_chain that can be constructed. + // Typically this is the pixel count (width x height) for a given image. + int size_; +}; + +// Must be called first, to set size. +int VP8LHashChainInit(VP8LHashChain* const p, int size); +// Pre-compute the best matches for argb. pic and percent are for progress. +int VP8LHashChainFill(VP8LHashChain* const p, int quality, + const uint32_t* const argb, int xsize, int ysize, + int low_effort, const WebPPicture* const pic, + int percent_range, int* const percent); +void VP8LHashChainClear(VP8LHashChain* const p); // release memory + +static WEBP_INLINE int VP8LHashChainFindOffset(const VP8LHashChain* const p, + const int base_position) { + return p->offset_length_[base_position] >> MAX_LENGTH_BITS; +} + +static WEBP_INLINE int VP8LHashChainFindLength(const VP8LHashChain* const p, + const int base_position) { + return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1); +} + +static WEBP_INLINE void VP8LHashChainFindCopy(const VP8LHashChain* const p, + int base_position, + int* const offset_ptr, + int* const length_ptr) { + *offset_ptr = VP8LHashChainFindOffset(p, base_position); + *length_ptr = VP8LHashChainFindLength(p, base_position); +} + +// ----------------------------------------------------------------------------- +// VP8LBackwardRefs (block-based backward-references storage) + +// maximum number of reference blocks the image will be segmented into +#define MAX_REFS_BLOCK_PER_IMAGE 16 + +typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration +typedef struct VP8LBackwardRefs VP8LBackwardRefs; + +// Container for blocks chain +struct VP8LBackwardRefs { + int block_size_; // common block-size + int error_; // set to true if some memory error occurred + PixOrCopyBlock* refs_; // list of currently used blocks + PixOrCopyBlock** tail_; // for list recycling + PixOrCopyBlock* free_blocks_; // free-list + PixOrCopyBlock* last_block_; // used for adding new refs (internal) +}; + +// Initialize the object. 'block_size' is the common block size to store +// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE). +void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size); +// Release memory for backward references. +void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs); + +// Cursor for iterating on references content +typedef struct { + // public: + PixOrCopy* cur_pos; // current position + // private: + PixOrCopyBlock* cur_block_; // current block in the refs list + const PixOrCopy* last_pos_; // sentinel for switching to next block +} VP8LRefsCursor; + +// Returns a cursor positioned at the beginning of the references list. +VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs); +// Returns true if cursor is pointing at a valid position. +static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) { + return (c->cur_pos != NULL); +} +// Move to next block of references. Internal, not to be called directly. +void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c); +// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk(). +static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { + assert(c != NULL); + assert(VP8LRefsCursorOk(c)); + if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c); +} + +// ----------------------------------------------------------------------------- +// Main entry points + +enum VP8LLZ77Type { + kLZ77Standard = 1, + kLZ77RLE = 2, + kLZ77Box = 4 +}; + +// Evaluates best possible backward references for specified quality. +// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache +// bits to use (passing 0 implies disabling the local color cache). +// The optimal cache bits is evaluated and set for the *cache_bits_best +// parameter with the matching refs_best. +// If do_no_cache == 0, refs is an array of 2 values and the best +// VP8LBackwardRefs is put in the first element. +// If do_no_cache != 0, refs is an array of 3 values and the best +// VP8LBackwardRefs is put in the first element, the best value with no-cache in +// the second element. +// In both cases, the last element is used as temporary internally. +// pic and percent are for progress. +// Returns false in case of error (stored in pic->error_code). +int VP8LGetBackwardReferences( + int width, int height, const uint32_t* const argb, int quality, + int low_effort, int lz77_types_to_try, int cache_bits_max, int do_no_cache, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs, + int* const cache_bits_best, const WebPPicture* const pic, int percent_range, + int* const percent); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ diff --git a/libraries/webp/src/enc/config_enc.c b/libraries/webp/src/enc/config_enc.c new file mode 100644 index 0000000000..d8a47a5f3a --- /dev/null +++ b/libraries/webp/src/enc/config_enc.c @@ -0,0 +1,157 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Coding tools configuration +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include "include/webp/encode.h" + +//------------------------------------------------------------------------------ +// WebPConfig +//------------------------------------------------------------------------------ + +int WebPConfigInitInternal(WebPConfig* config, + WebPPreset preset, float quality, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { + return 0; // caller/system version mismatch! + } + if (config == NULL) return 0; + + config->quality = quality; + config->target_size = 0; + config->target_PSNR = 0.; + config->method = 4; + config->sns_strength = 50; + config->filter_strength = 60; // mid-filtering + config->filter_sharpness = 0; + config->filter_type = 1; // default: strong (so U/V is filtered too) + config->partitions = 0; + config->segments = 4; + config->pass = 1; + config->qmin = 0; + config->qmax = 100; + config->show_compressed = 0; + config->preprocessing = 0; + config->autofilter = 0; + config->partition_limit = 0; + config->alpha_compression = 1; + config->alpha_filtering = 1; + config->alpha_quality = 100; + config->lossless = 0; + config->exact = 0; + config->image_hint = WEBP_HINT_DEFAULT; + config->emulate_jpeg_size = 0; + config->thread_level = 0; + config->low_memory = 0; + config->near_lossless = 100; + config->use_delta_palette = 0; + config->use_sharp_yuv = 0; + + // TODO(skal): tune. + switch (preset) { + case WEBP_PRESET_PICTURE: + config->sns_strength = 80; + config->filter_sharpness = 4; + config->filter_strength = 35; + config->preprocessing &= ~2; // no dithering + break; + case WEBP_PRESET_PHOTO: + config->sns_strength = 80; + config->filter_sharpness = 3; + config->filter_strength = 30; + config->preprocessing |= 2; + break; + case WEBP_PRESET_DRAWING: + config->sns_strength = 25; + config->filter_sharpness = 6; + config->filter_strength = 10; + break; + case WEBP_PRESET_ICON: + config->sns_strength = 0; + config->filter_strength = 0; // disable filtering to retain sharpness + config->preprocessing &= ~2; // no dithering + break; + case WEBP_PRESET_TEXT: + config->sns_strength = 0; + config->filter_strength = 0; // disable filtering to retain sharpness + config->preprocessing &= ~2; // no dithering + config->segments = 2; + break; + case WEBP_PRESET_DEFAULT: + default: + break; + } + return WebPValidateConfig(config); +} + +int WebPValidateConfig(const WebPConfig* config) { + if (config == NULL) return 0; + if (config->quality < 0 || config->quality > 100) return 0; + if (config->target_size < 0) return 0; + if (config->target_PSNR < 0) return 0; + if (config->method < 0 || config->method > 6) return 0; + if (config->segments < 1 || config->segments > 4) return 0; + if (config->sns_strength < 0 || config->sns_strength > 100) return 0; + if (config->filter_strength < 0 || config->filter_strength > 100) return 0; + if (config->filter_sharpness < 0 || config->filter_sharpness > 7) return 0; + if (config->filter_type < 0 || config->filter_type > 1) return 0; + if (config->autofilter < 0 || config->autofilter > 1) return 0; + if (config->pass < 1 || config->pass > 10) return 0; + if (config->qmin < 0 || config->qmax > 100 || config->qmin > config->qmax) { + return 0; + } + if (config->show_compressed < 0 || config->show_compressed > 1) return 0; + if (config->preprocessing < 0 || config->preprocessing > 7) return 0; + if (config->partitions < 0 || config->partitions > 3) return 0; + if (config->partition_limit < 0 || config->partition_limit > 100) return 0; + if (config->alpha_compression < 0) return 0; + if (config->alpha_filtering < 0) return 0; + if (config->alpha_quality < 0 || config->alpha_quality > 100) return 0; + if (config->lossless < 0 || config->lossless > 1) return 0; + if (config->near_lossless < 0 || config->near_lossless > 100) return 0; + if (config->image_hint >= WEBP_HINT_LAST) return 0; + if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1) return 0; + if (config->thread_level < 0 || config->thread_level > 1) return 0; + if (config->low_memory < 0 || config->low_memory > 1) return 0; + if (config->exact < 0 || config->exact > 1) return 0; + if (config->use_delta_palette < 0 || config->use_delta_palette > 1) { + return 0; + } + if (config->use_sharp_yuv < 0 || config->use_sharp_yuv > 1) return 0; + + return 1; +} + +//------------------------------------------------------------------------------ + +#define MAX_LEVEL 9 + +// Mapping between -z level and -m / -q parameter settings. +static const struct { + uint8_t method_; + uint8_t quality_; +} kLosslessPresets[MAX_LEVEL + 1] = { + { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 }, + { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 } +}; + +int WebPConfigLosslessPreset(WebPConfig* config, int level) { + if (config == NULL || level < 0 || level > MAX_LEVEL) return 0; + config->lossless = 1; + config->method = kLosslessPresets[level].method_; + config->quality = kLosslessPresets[level].quality_; + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/enc/cost_enc.c b/libraries/webp/src/enc/cost_enc.c new file mode 100644 index 0000000000..48fd9bc347 --- /dev/null +++ b/libraries/webp/src/enc/cost_enc.c @@ -0,0 +1,342 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Cost tables for level and modes +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/enc/cost_enc.h" + +//------------------------------------------------------------------------------ +// Level cost tables + +// For each given level, the following table gives the pattern of contexts to +// use for coding it (in [][0]) as well as the bit value to use for each +// context (in [][1]). +const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = { + {0x001, 0x000}, {0x007, 0x001}, {0x00f, 0x005}, + {0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023}, + {0x033, 0x023}, {0x033, 0x023}, {0x033, 0x023}, {0x0d3, 0x013}, + {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, + {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x093}, + {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, + {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, + {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, + {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x153} +}; + +static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) { + int pattern = VP8LevelCodes[level - 1][0]; + int bits = VP8LevelCodes[level - 1][1]; + int cost = 0; + int i; + for (i = 2; pattern; ++i) { + if (pattern & 1) { + cost += VP8BitCost(bits & 1, probas[i]); + } + bits >>= 1; + pattern >>= 1; + } + return cost; +} + +//------------------------------------------------------------------------------ +// Pre-calc level costs once for all + +void VP8CalculateLevelCosts(VP8EncProba* const proba) { + int ctype, band, ctx; + + if (!proba->dirty_) return; // nothing to do. + + for (ctype = 0; ctype < NUM_TYPES; ++ctype) { + int n; + for (band = 0; band < NUM_BANDS; ++band) { + for (ctx = 0; ctx < NUM_CTX; ++ctx) { + const uint8_t* const p = proba->coeffs_[ctype][band][ctx]; + uint16_t* const table = proba->level_cost_[ctype][band][ctx]; + const int cost0 = (ctx > 0) ? VP8BitCost(1, p[0]) : 0; + const int cost_base = VP8BitCost(1, p[1]) + cost0; + int v; + table[0] = VP8BitCost(0, p[1]) + cost0; + for (v = 1; v <= MAX_VARIABLE_LEVEL; ++v) { + table[v] = cost_base + VariableLevelCost(v, p); + } + // Starting at level 67 and up, the variable part of the cost is + // actually constant. + } + } + for (n = 0; n < 16; ++n) { // replicate bands. We don't need to sentinel. + for (ctx = 0; ctx < NUM_CTX; ++ctx) { + proba->remapped_costs_[ctype][n][ctx] = + proba->level_cost_[ctype][VP8EncBands[n]][ctx]; + } + } + } + proba->dirty_ = 0; +} + +//------------------------------------------------------------------------------ +// Mode cost tables. + +// These are the fixed probabilities (in the coding trees) turned into bit-cost +// by calling VP8BitCost(). +const uint16_t VP8FixedCostsUV[4] = { 302, 984, 439, 642 }; +// note: these values include the fixed VP8BitCost(1, 145) mode selection cost. +const uint16_t VP8FixedCostsI16[4] = { 663, 919, 872, 919 }; +const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES] = { + { { 40, 1151, 1723, 1874, 2103, 2019, 1628, 1777, 2226, 2137 }, + { 192, 469, 1296, 1308, 1849, 1794, 1781, 1703, 1713, 1522 }, + { 142, 910, 762, 1684, 1849, 1576, 1460, 1305, 1801, 1657 }, + { 559, 641, 1370, 421, 1182, 1569, 1612, 1725, 863, 1007 }, + { 299, 1059, 1256, 1108, 636, 1068, 1581, 1883, 869, 1142 }, + { 277, 1111, 707, 1362, 1089, 672, 1603, 1541, 1545, 1291 }, + { 214, 781, 1609, 1303, 1632, 2229, 726, 1560, 1713, 918 }, + { 152, 1037, 1046, 1759, 1983, 2174, 1358, 742, 1740, 1390 }, + { 512, 1046, 1420, 753, 752, 1297, 1486, 1613, 460, 1207 }, + { 424, 827, 1362, 719, 1462, 1202, 1199, 1476, 1199, 538 } }, + { { 240, 402, 1134, 1491, 1659, 1505, 1517, 1555, 1979, 2099 }, + { 467, 242, 960, 1232, 1714, 1620, 1834, 1570, 1676, 1391 }, + { 500, 455, 463, 1507, 1699, 1282, 1564, 982, 2114, 2114 }, + { 672, 643, 1372, 331, 1589, 1667, 1453, 1938, 996, 876 }, + { 458, 783, 1037, 911, 738, 968, 1165, 1518, 859, 1033 }, + { 504, 815, 504, 1139, 1219, 719, 1506, 1085, 1268, 1268 }, + { 333, 630, 1445, 1239, 1883, 3672, 799, 1548, 1865, 598 }, + { 399, 644, 746, 1342, 1856, 1350, 1493, 613, 1855, 1015 }, + { 622, 749, 1205, 608, 1066, 1408, 1290, 1406, 546, 971 }, + { 500, 753, 1041, 668, 1230, 1617, 1297, 1425, 1383, 523 } }, + { { 394, 553, 523, 1502, 1536, 981, 1608, 1142, 1666, 2181 }, + { 655, 430, 375, 1411, 1861, 1220, 1677, 1135, 1978, 1553 }, + { 690, 640, 245, 1954, 2070, 1194, 1528, 982, 1972, 2232 }, + { 559, 834, 741, 867, 1131, 980, 1225, 852, 1092, 784 }, + { 690, 875, 516, 959, 673, 894, 1056, 1190, 1528, 1126 }, + { 740, 951, 384, 1277, 1177, 492, 1579, 1155, 1846, 1513 }, + { 323, 775, 1062, 1776, 3062, 1274, 813, 1188, 1372, 655 }, + { 488, 971, 484, 1767, 1515, 1775, 1115, 503, 1539, 1461 }, + { 740, 1006, 998, 709, 851, 1230, 1337, 788, 741, 721 }, + { 522, 1073, 573, 1045, 1346, 887, 1046, 1146, 1203, 697 } }, + { { 105, 864, 1442, 1009, 1934, 1840, 1519, 1920, 1673, 1579 }, + { 534, 305, 1193, 683, 1388, 2164, 1802, 1894, 1264, 1170 }, + { 305, 518, 877, 1108, 1426, 3215, 1425, 1064, 1320, 1242 }, + { 683, 732, 1927, 257, 1493, 2048, 1858, 1552, 1055, 947 }, + { 394, 814, 1024, 660, 959, 1556, 1282, 1289, 893, 1047 }, + { 528, 615, 996, 940, 1201, 635, 1094, 2515, 803, 1358 }, + { 347, 614, 1609, 1187, 3133, 1345, 1007, 1339, 1017, 667 }, + { 218, 740, 878, 1605, 3650, 3650, 1345, 758, 1357, 1617 }, + { 672, 750, 1541, 558, 1257, 1599, 1870, 2135, 402, 1087 }, + { 592, 684, 1161, 430, 1092, 1497, 1475, 1489, 1095, 822 } }, + { { 228, 1056, 1059, 1368, 752, 982, 1512, 1518, 987, 1782 }, + { 494, 514, 818, 942, 965, 892, 1610, 1356, 1048, 1363 }, + { 512, 648, 591, 1042, 761, 991, 1196, 1454, 1309, 1463 }, + { 683, 749, 1043, 676, 841, 1396, 1133, 1138, 654, 939 }, + { 622, 1101, 1126, 994, 361, 1077, 1203, 1318, 877, 1219 }, + { 631, 1068, 857, 1650, 651, 477, 1650, 1419, 828, 1170 }, + { 555, 727, 1068, 1335, 3127, 1339, 820, 1331, 1077, 429 }, + { 504, 879, 624, 1398, 889, 889, 1392, 808, 891, 1406 }, + { 683, 1602, 1289, 977, 578, 983, 1280, 1708, 406, 1122 }, + { 399, 865, 1433, 1070, 1072, 764, 968, 1477, 1223, 678 } }, + { { 333, 760, 935, 1638, 1010, 529, 1646, 1410, 1472, 2219 }, + { 512, 494, 750, 1160, 1215, 610, 1870, 1868, 1628, 1169 }, + { 572, 646, 492, 1934, 1208, 603, 1580, 1099, 1398, 1995 }, + { 786, 789, 942, 581, 1018, 951, 1599, 1207, 731, 768 }, + { 690, 1015, 672, 1078, 582, 504, 1693, 1438, 1108, 2897 }, + { 768, 1267, 571, 2005, 1243, 244, 2881, 1380, 1786, 1453 }, + { 452, 899, 1293, 903, 1311, 3100, 465, 1311, 1319, 813 }, + { 394, 927, 942, 1103, 1358, 1104, 946, 593, 1363, 1109 }, + { 559, 1005, 1007, 1016, 658, 1173, 1021, 1164, 623, 1028 }, + { 564, 796, 632, 1005, 1014, 863, 2316, 1268, 938, 764 } }, + { { 266, 606, 1098, 1228, 1497, 1243, 948, 1030, 1734, 1461 }, + { 366, 585, 901, 1060, 1407, 1247, 876, 1134, 1620, 1054 }, + { 452, 565, 542, 1729, 1479, 1479, 1016, 886, 2938, 1150 }, + { 555, 1088, 1533, 950, 1354, 895, 834, 1019, 1021, 496 }, + { 704, 815, 1193, 971, 973, 640, 1217, 2214, 832, 578 }, + { 672, 1245, 579, 871, 875, 774, 872, 1273, 1027, 949 }, + { 296, 1134, 2050, 1784, 1636, 3425, 442, 1550, 2076, 722 }, + { 342, 982, 1259, 1846, 1848, 1848, 622, 568, 1847, 1052 }, + { 555, 1064, 1304, 828, 746, 1343, 1075, 1329, 1078, 494 }, + { 288, 1167, 1285, 1174, 1639, 1639, 833, 2254, 1304, 509 } }, + { { 342, 719, 767, 1866, 1757, 1270, 1246, 550, 1746, 2151 }, + { 483, 653, 694, 1509, 1459, 1410, 1218, 507, 1914, 1266 }, + { 488, 757, 447, 2979, 1813, 1268, 1654, 539, 1849, 2109 }, + { 522, 1097, 1085, 851, 1365, 1111, 851, 901, 961, 605 }, + { 709, 716, 841, 728, 736, 945, 941, 862, 2845, 1057 }, + { 512, 1323, 500, 1336, 1083, 681, 1342, 717, 1604, 1350 }, + { 452, 1155, 1372, 1900, 1501, 3290, 311, 944, 1919, 922 }, + { 403, 1520, 977, 2132, 1733, 3522, 1076, 276, 3335, 1547 }, + { 559, 1374, 1101, 615, 673, 2462, 974, 795, 984, 984 }, + { 547, 1122, 1062, 812, 1410, 951, 1140, 622, 1268, 651 } }, + { { 165, 982, 1235, 938, 1334, 1366, 1659, 1578, 964, 1612 }, + { 592, 422, 925, 847, 1139, 1112, 1387, 2036, 861, 1041 }, + { 403, 837, 732, 770, 941, 1658, 1250, 809, 1407, 1407 }, + { 896, 874, 1071, 381, 1568, 1722, 1437, 2192, 480, 1035 }, + { 640, 1098, 1012, 1032, 684, 1382, 1581, 2106, 416, 865 }, + { 559, 1005, 819, 914, 710, 770, 1418, 920, 838, 1435 }, + { 415, 1258, 1245, 870, 1278, 3067, 770, 1021, 1287, 522 }, + { 406, 990, 601, 1009, 1265, 1265, 1267, 759, 1017, 1277 }, + { 968, 1182, 1329, 788, 1032, 1292, 1705, 1714, 203, 1403 }, + { 732, 877, 1279, 471, 901, 1161, 1545, 1294, 755, 755 } }, + { { 111, 931, 1378, 1185, 1933, 1648, 1148, 1714, 1873, 1307 }, + { 406, 414, 1030, 1023, 1910, 1404, 1313, 1647, 1509, 793 }, + { 342, 640, 575, 1088, 1241, 1349, 1161, 1350, 1756, 1502 }, + { 559, 766, 1185, 357, 1682, 1428, 1329, 1897, 1219, 802 }, + { 473, 909, 1164, 771, 719, 2508, 1427, 1432, 722, 782 }, + { 342, 892, 785, 1145, 1150, 794, 1296, 1550, 973, 1057 }, + { 208, 1036, 1326, 1343, 1606, 3395, 815, 1455, 1618, 712 }, + { 228, 928, 890, 1046, 3499, 1711, 994, 829, 1720, 1318 }, + { 768, 724, 1058, 636, 991, 1075, 1319, 1324, 616, 825 }, + { 305, 1167, 1358, 899, 1587, 1587, 987, 1988, 1332, 501 } } +}; + +//------------------------------------------------------------------------------ +// helper functions for residuals struct VP8Residual. + +void VP8InitResidual(int first, int coeff_type, + VP8Encoder* const enc, VP8Residual* const res) { + res->coeff_type = coeff_type; + res->prob = enc->proba_.coeffs_[coeff_type]; + res->stats = enc->proba_.stats_[coeff_type]; + res->costs = enc->proba_.remapped_costs_[coeff_type]; + res->first = first; +} + +//------------------------------------------------------------------------------ +// Mode costs + +int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) { + const int x = (it->i4_ & 3), y = (it->i4_ >> 2); + VP8Residual res; + VP8Encoder* const enc = it->enc_; + int R = 0; + int ctx; + + VP8InitResidual(0, 3, enc, &res); + ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(levels, &res); + R += VP8GetResidualCost(ctx, &res); + return R; +} + +int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) { + VP8Residual res; + VP8Encoder* const enc = it->enc_; + int x, y; + int R = 0; + + VP8IteratorNzToBytes(it); // re-import the non-zero context + + // DC + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + R += VP8GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res); + + // AC + VP8InitResidual(1, 0, enc, &res); + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + R += VP8GetResidualCost(ctx, &res); + it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0); + } + } + return R; +} + +int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) { + VP8Residual res; + VP8Encoder* const enc = it->enc_; + int ch, x, y; + int R = 0; + + VP8IteratorNzToBytes(it); // re-import the non-zero context + + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + R += VP8GetResidualCost(ctx, &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0); + } + } + } + return R; +} + + +//------------------------------------------------------------------------------ +// Recording of token probabilities. + +// We keep the table-free variant around for reference, in case. +#define USE_LEVEL_CODE_TABLE + +// Simulate block coding, but only record statistics. +// Note: no need to record the fixed probas. +int VP8RecordCoeffs(int ctx, const VP8Residual* const res) { + int n = res->first; + // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 + proba_t* s = res->stats[n][ctx]; + if (res->last < 0) { + VP8RecordStats(0, s + 0); + return 0; + } + while (n <= res->last) { + int v; + VP8RecordStats(1, s + 0); // order of record doesn't matter + while ((v = res->coeffs[n++]) == 0) { + VP8RecordStats(0, s + 1); + s = res->stats[VP8EncBands[n]][0]; + } + VP8RecordStats(1, s + 1); + if (!VP8RecordStats(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1 + s = res->stats[VP8EncBands[n]][1]; + } else { + v = abs(v); +#if !defined(USE_LEVEL_CODE_TABLE) + if (!VP8RecordStats(v > 4, s + 3)) { + if (VP8RecordStats(v != 2, s + 4)) + VP8RecordStats(v == 4, s + 5); + } else if (!VP8RecordStats(v > 10, s + 6)) { + VP8RecordStats(v > 6, s + 7); + } else if (!VP8RecordStats((v >= 3 + (8 << 2)), s + 8)) { + VP8RecordStats((v >= 3 + (8 << 1)), s + 9); + } else { + VP8RecordStats((v >= 3 + (8 << 3)), s + 10); + } +#else + if (v > MAX_VARIABLE_LEVEL) { + v = MAX_VARIABLE_LEVEL; + } + + { + const int bits = VP8LevelCodes[v - 1][1]; + int pattern = VP8LevelCodes[v - 1][0]; + int i; + for (i = 0; (pattern >>= 1) != 0; ++i) { + const int mask = 2 << i; + if (pattern & 1) VP8RecordStats(!!(bits & mask), s + 3 + i); + } + } +#endif + s = res->stats[VP8EncBands[n]][2]; + } + } + if (n < 16) VP8RecordStats(0, s + 0); + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/enc/cost_enc.h b/libraries/webp/src/enc/cost_enc.h new file mode 100644 index 0000000000..a4b177b342 --- /dev/null +++ b/libraries/webp/src/enc/cost_enc.h @@ -0,0 +1,82 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Cost tables for level and modes. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_ENC_COST_ENC_H_ +#define WEBP_ENC_COST_ENC_H_ + +#include +#include +#include "src/enc/vp8i_enc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// On-the-fly info about the current set of residuals. Handy to avoid +// passing zillions of params. +typedef struct VP8Residual VP8Residual; +struct VP8Residual { + int first; + int last; + const int16_t* coeffs; + + int coeff_type; + ProbaArray* prob; + StatsArray* stats; + CostArrayPtr costs; +}; + +void VP8InitResidual(int first, int coeff_type, + VP8Encoder* const enc, VP8Residual* const res); + +int VP8RecordCoeffs(int ctx, const VP8Residual* const res); + +// Record proba context used. +static WEBP_INLINE int VP8RecordStats(int bit, proba_t* const stats) { + proba_t p = *stats; + // An overflow is inbound. Note we handle this at 0xfffe0000u instead of + // 0xffff0000u to make sure p + 1u does not overflow. + if (p >= 0xfffe0000u) { + p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. + } + // record bit count (lower 16 bits) and increment total count (upper 16 bits). + p += 0x00010000u + bit; + *stats = p; + return bit; +} + +// Cost of coding one event with probability 'proba'. +static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) { + return !bit ? VP8EntropyCost[proba] : VP8EntropyCost[255 - proba]; +} + +// Level cost calculations +extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2]; +void VP8CalculateLevelCosts(VP8EncProba* const proba); +static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) { + return VP8LevelFixedCosts[level] + + table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level]; +} + +// Mode costs +extern const uint16_t VP8FixedCostsUV[4]; +extern const uint16_t VP8FixedCostsI16[4]; +extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES]; + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_ENC_COST_ENC_H_ diff --git a/libraries/webp/src/enc/filter_enc.c b/libraries/webp/src/enc/filter_enc.c new file mode 100644 index 0000000000..580800bfb8 --- /dev/null +++ b/libraries/webp/src/enc/filter_enc.c @@ -0,0 +1,235 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Selecting filter level +// +// Author: somnath@google.com (Somnath Banerjee) + +#include +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" + +// This table gives, for a given sharpness, the filtering strength to be +// used (at least) in order to filter a given edge step delta. +// This is constructed by brute force inspection: for all delta, we iterate +// over all possible filtering strength / thresh until needs_filter() returns +// true. +#define MAX_DELTA_SIZE 64 +static const uint8_t kLevelsFromDelta[8][MAX_DELTA_SIZE] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }, + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 18, + 20, 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, + 44, 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 19, + 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, + 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, + 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, + 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, + 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, + 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20, + 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, + 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 21, + 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, + 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, + 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, + 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 } +}; + +int VP8FilterStrengthFromDelta(int sharpness, int delta) { + const int pos = (delta < MAX_DELTA_SIZE) ? delta : MAX_DELTA_SIZE - 1; + assert(sharpness >= 0 && sharpness <= 7); + return kLevelsFromDelta[sharpness][pos]; +} + +//------------------------------------------------------------------------------ +// Paragraph 15.4: compute the inner-edge filtering strength + +#if !defined(WEBP_REDUCE_SIZE) + +static int GetILevel(int sharpness, int level) { + if (sharpness > 0) { + if (sharpness > 4) { + level >>= 2; + } else { + level >>= 1; + } + if (level > 9 - sharpness) { + level = 9 - sharpness; + } + } + if (level < 1) level = 1; + return level; +} + +static void DoFilter(const VP8EncIterator* const it, int level) { + const VP8Encoder* const enc = it->enc_; + const int ilevel = GetILevel(enc->config_->filter_sharpness, level); + const int limit = 2 * level + ilevel; + + uint8_t* const y_dst = it->yuv_out2_ + Y_OFF_ENC; + uint8_t* const u_dst = it->yuv_out2_ + U_OFF_ENC; + uint8_t* const v_dst = it->yuv_out2_ + V_OFF_ENC; + + // copy current block to yuv_out2_ + memcpy(y_dst, it->yuv_out_, YUV_SIZE_ENC * sizeof(uint8_t)); + + if (enc->filter_hdr_.simple_ == 1) { // simple + VP8SimpleHFilter16i(y_dst, BPS, limit); + VP8SimpleVFilter16i(y_dst, BPS, limit); + } else { // complex + const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0; + VP8HFilter16i(y_dst, BPS, limit, ilevel, hev_thresh); + VP8HFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh); + VP8VFilter16i(y_dst, BPS, limit, ilevel, hev_thresh); + VP8VFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh); + } +} + +//------------------------------------------------------------------------------ +// SSIM metric for one macroblock + +static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) { + int x, y; + double sum = 0.; + + // compute SSIM in a 10 x 10 window + for (y = VP8_SSIM_KERNEL; y < 16 - VP8_SSIM_KERNEL; y++) { + for (x = VP8_SSIM_KERNEL; x < 16 - VP8_SSIM_KERNEL; x++) { + sum += VP8SSIMGetClipped(yuv1 + Y_OFF_ENC, BPS, yuv2 + Y_OFF_ENC, BPS, + x, y, 16, 16); + } + } + for (x = 1; x < 7; x++) { + for (y = 1; y < 7; y++) { + sum += VP8SSIMGetClipped(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS, + x, y, 8, 8); + sum += VP8SSIMGetClipped(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS, + x, y, 8, 8); + } + } + return sum; +} + +#endif // !defined(WEBP_REDUCE_SIZE) + +//------------------------------------------------------------------------------ +// Exposed APIs: Encoder should call the following 3 functions to adjust +// loop filter strength + +void VP8InitFilter(VP8EncIterator* const it) { +#if !defined(WEBP_REDUCE_SIZE) + if (it->lf_stats_ != NULL) { + int s, i; + for (s = 0; s < NUM_MB_SEGMENTS; s++) { + for (i = 0; i < MAX_LF_LEVELS; i++) { + (*it->lf_stats_)[s][i] = 0; + } + } + VP8SSIMDspInit(); + } +#else + (void)it; +#endif +} + +void VP8StoreFilterStats(VP8EncIterator* const it) { +#if !defined(WEBP_REDUCE_SIZE) + int d; + VP8Encoder* const enc = it->enc_; + const int s = it->mb_->segment_; + const int level0 = enc->dqm_[s].fstrength_; + + // explore +/-quant range of values around level0 + const int delta_min = -enc->dqm_[s].quant_; + const int delta_max = enc->dqm_[s].quant_; + const int step_size = (delta_max - delta_min >= 4) ? 4 : 1; + + if (it->lf_stats_ == NULL) return; + + // NOTE: Currently we are applying filter only across the sublock edges + // There are two reasons for that. + // 1. Applying filter on macro block edges will change the pixels in + // the left and top macro blocks. That will be hard to restore + // 2. Macro Blocks on the bottom and right are not yet compressed. So we + // cannot apply filter on the right and bottom macro block edges. + if (it->mb_->type_ == 1 && it->mb_->skip_) return; + + // Always try filter level zero + (*it->lf_stats_)[s][0] += GetMBSSIM(it->yuv_in_, it->yuv_out_); + + for (d = delta_min; d <= delta_max; d += step_size) { + const int level = level0 + d; + if (level <= 0 || level >= MAX_LF_LEVELS) { + continue; + } + DoFilter(it, level); + (*it->lf_stats_)[s][level] += GetMBSSIM(it->yuv_in_, it->yuv_out2_); + } +#else // defined(WEBP_REDUCE_SIZE) + (void)it; +#endif // !defined(WEBP_REDUCE_SIZE) +} + +void VP8AdjustFilterStrength(VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; +#if !defined(WEBP_REDUCE_SIZE) + if (it->lf_stats_ != NULL) { + int s; + for (s = 0; s < NUM_MB_SEGMENTS; s++) { + int i, best_level = 0; + // Improvement over filter level 0 should be at least 1e-5 (relatively) + double best_v = 1.00001 * (*it->lf_stats_)[s][0]; + for (i = 1; i < MAX_LF_LEVELS; i++) { + const double v = (*it->lf_stats_)[s][i]; + if (v > best_v) { + best_v = v; + best_level = i; + } + } + enc->dqm_[s].fstrength_ = best_level; + } + return; + } +#endif // !defined(WEBP_REDUCE_SIZE) + if (enc->config_->filter_strength > 0) { + int max_level = 0; + int s; + for (s = 0; s < NUM_MB_SEGMENTS; s++) { + VP8SegmentInfo* const dqm = &enc->dqm_[s]; + // this '>> 3' accounts for some inverse WHT scaling + const int delta = (dqm->max_edge_ * dqm->y2_.q_[1]) >> 3; + const int level = + VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, delta); + if (level > dqm->fstrength_) { + dqm->fstrength_ = level; + } + if (max_level < dqm->fstrength_) { + max_level = dqm->fstrength_; + } + } + enc->filter_hdr_.level_ = max_level; + } +} + +// ----------------------------------------------------------------------------- diff --git a/libraries/webp/src/enc/frame_enc.c b/libraries/webp/src/enc/frame_enc.c new file mode 100644 index 0000000000..1712310a2b --- /dev/null +++ b/libraries/webp/src/enc/frame_enc.c @@ -0,0 +1,905 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// frame coding and analysis +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include + +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" +#include "include/webp/format_constants.h" // RIFF constants + +#define SEGMENT_VISU 0 +#define DEBUG_SEARCH 0 // useful to track search convergence + +//------------------------------------------------------------------------------ +// multi-pass convergence + +#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \ + VP8_FRAME_HEADER_SIZE) +#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT +// we allow 2k of extra head-room in PARTITION0 limit. +#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11) + +static float Clamp(float v, float min, float max) { + return (v < min) ? min : (v > max) ? max : v; +} + +typedef struct { // struct for organizing convergence in either size or PSNR + int is_first; + float dq; + float q, last_q; + float qmin, qmax; + double value, last_value; // PSNR or size + double target; + int do_size_search; +} PassStats; + +static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) { + const uint64_t target_size = (uint64_t)enc->config_->target_size; + const int do_size_search = (target_size != 0); + const float target_PSNR = enc->config_->target_PSNR; + + s->is_first = 1; + s->dq = 10.f; + s->qmin = 1.f * enc->config_->qmin; + s->qmax = 1.f * enc->config_->qmax; + s->q = s->last_q = Clamp(enc->config_->quality, s->qmin, s->qmax); + s->target = do_size_search ? (double)target_size + : (target_PSNR > 0.) ? target_PSNR + : 40.; // default, just in case + s->value = s->last_value = 0.; + s->do_size_search = do_size_search; + return do_size_search; +} + +static float ComputeNextQ(PassStats* const s) { + float dq; + if (s->is_first) { + dq = (s->value > s->target) ? -s->dq : s->dq; + s->is_first = 0; + } else if (s->value != s->last_value) { + const double slope = (s->target - s->value) / (s->last_value - s->value); + dq = (float)(slope * (s->last_q - s->q)); + } else { + dq = 0.; // we're done?! + } + // Limit variable to avoid large swings. + s->dq = Clamp(dq, -30.f, 30.f); + s->last_q = s->q; + s->last_value = s->value; + s->q = Clamp(s->q + s->dq, s->qmin, s->qmax); + return s->q; +} + +//------------------------------------------------------------------------------ +// Tables for level coding + +const uint8_t VP8Cat3[] = { 173, 148, 140 }; +const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; +const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; +const uint8_t VP8Cat6[] = + { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; + +//------------------------------------------------------------------------------ +// Reset the statistics about: number of skips, token proba, level cost,... + +static void ResetStats(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + VP8CalculateLevelCosts(proba); + proba->nb_skip_ = 0; +} + +//------------------------------------------------------------------------------ +// Skip decision probability + +#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. + +static int CalcSkipProba(uint64_t nb, uint64_t total) { + return (int)(total ? (total - nb) * 255 / total : 255); +} + +// Returns the bit-cost for coding the skip probability. +static int FinalizeSkipProba(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + const int nb_mbs = enc->mb_w_ * enc->mb_h_; + const int nb_events = proba->nb_skip_; + int size; + proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs); + proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD); + size = 256; // 'use_skip_proba' bit + if (proba->use_skip_proba_) { + size += nb_events * VP8BitCost(1, proba->skip_proba_) + + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_); + size += 8 * 256; // cost of signaling the skip_proba_ itself. + } + return size; +} + +// Collect statistics and deduce probabilities for next coding pass. +// Return the total bit-cost for coding the probability updates. +static int CalcTokenProba(int nb, int total) { + assert(nb <= total); + return nb ? (255 - nb * 255 / total) : 255; +} + +// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. +static int BranchCost(int nb, int total, int proba) { + return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); +} + +static void ResetTokenStats(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + memset(proba->stats_, 0, sizeof(proba->stats_)); +} + +static int FinalizeTokenProbas(VP8EncProba* const proba) { + int has_changed = 0; + int size = 0; + int t, b, c, p; + for (t = 0; t < NUM_TYPES; ++t) { + for (b = 0; b < NUM_BANDS; ++b) { + for (c = 0; c < NUM_CTX; ++c) { + for (p = 0; p < NUM_PROBAS; ++p) { + const proba_t stats = proba->stats_[t][b][c][p]; + const int nb = (stats >> 0) & 0xffff; + const int total = (stats >> 16) & 0xffff; + const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; + const int old_p = VP8CoeffsProba0[t][b][c][p]; + const int new_p = CalcTokenProba(nb, total); + const int old_cost = BranchCost(nb, total, old_p) + + VP8BitCost(0, update_proba); + const int new_cost = BranchCost(nb, total, new_p) + + VP8BitCost(1, update_proba) + + 8 * 256; + const int use_new_p = (old_cost > new_cost); + size += VP8BitCost(use_new_p, update_proba); + if (use_new_p) { // only use proba that seem meaningful enough. + proba->coeffs_[t][b][c][p] = new_p; + has_changed |= (new_p != old_p); + size += 8 * 256; + } else { + proba->coeffs_[t][b][c][p] = old_p; + } + } + } + } + } + proba->dirty_ = has_changed; + return size; +} + +//------------------------------------------------------------------------------ +// Finalize Segment probability based on the coding tree + +static int GetProba(int a, int b) { + const int total = a + b; + return (total == 0) ? 255 // that's the default probability. + : (255 * a + total / 2) / total; // rounded proba +} + +static void ResetSegments(VP8Encoder* const enc) { + int n; + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + enc->mb_info_[n].segment_ = 0; + } +} + +static void SetSegmentProbas(VP8Encoder* const enc) { + int p[NUM_MB_SEGMENTS] = { 0 }; + int n; + + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + const VP8MBInfo* const mb = &enc->mb_info_[n]; + ++p[mb->segment_]; + } +#if !defined(WEBP_DISABLE_STATS) + if (enc->pic_->stats != NULL) { + for (n = 0; n < NUM_MB_SEGMENTS; ++n) { + enc->pic_->stats->segment_size[n] = p[n]; + } + } +#endif + if (enc->segment_hdr_.num_segments_ > 1) { + uint8_t* const probas = enc->proba_.segments_; + probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); + probas[1] = GetProba(p[0], p[1]); + probas[2] = GetProba(p[2], p[3]); + + enc->segment_hdr_.update_map_ = + (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); + if (!enc->segment_hdr_.update_map_) ResetSegments(enc); + enc->segment_hdr_.size_ = + p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + + p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + + p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + + p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); + } else { + enc->segment_hdr_.update_map_ = 0; + enc->segment_hdr_.size_ = 0; + } +} + +//------------------------------------------------------------------------------ +// Coefficient coding + +static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const uint8_t* p = res->prob[n][ctx]; + if (!VP8PutBit(bw, res->last >= 0, p[0])) { + return 0; + } + + while (n < 16) { + const int c = res->coeffs[n++]; + const int sign = c < 0; + int v = sign ? -c : c; + if (!VP8PutBit(bw, v != 0, p[1])) { + p = res->prob[VP8EncBands[n]][0]; + continue; + } + if (!VP8PutBit(bw, v > 1, p[2])) { + p = res->prob[VP8EncBands[n]][1]; + } else { + if (!VP8PutBit(bw, v > 4, p[3])) { + if (VP8PutBit(bw, v != 2, p[4])) { + VP8PutBit(bw, v == 4, p[5]); + } + } else if (!VP8PutBit(bw, v > 10, p[6])) { + if (!VP8PutBit(bw, v > 6, p[7])) { + VP8PutBit(bw, v == 6, 159); + } else { + VP8PutBit(bw, v >= 9, 165); + VP8PutBit(bw, !(v & 1), 145); + } + } else { + int mask; + const uint8_t* tab; + if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) + VP8PutBit(bw, 0, p[8]); + VP8PutBit(bw, 0, p[9]); + v -= 3 + (8 << 0); + mask = 1 << 2; + tab = VP8Cat3; + } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) + VP8PutBit(bw, 0, p[8]); + VP8PutBit(bw, 1, p[9]); + v -= 3 + (8 << 1); + mask = 1 << 3; + tab = VP8Cat4; + } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) + VP8PutBit(bw, 1, p[8]); + VP8PutBit(bw, 0, p[10]); + v -= 3 + (8 << 2); + mask = 1 << 4; + tab = VP8Cat5; + } else { // VP8Cat6 (11b) + VP8PutBit(bw, 1, p[8]); + VP8PutBit(bw, 1, p[10]); + v -= 3 + (8 << 3); + mask = 1 << 10; + tab = VP8Cat6; + } + while (mask) { + VP8PutBit(bw, !!(v & mask), *tab++); + mask >>= 1; + } + } + p = res->prob[VP8EncBands[n]][2]; + } + VP8PutBitUniform(bw, sign); + if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { + return 1; // EOB + } + } + return 1; +} + +static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int x, y, ch; + VP8Residual res; + uint64_t pos1, pos2, pos3; + const int i16 = (it->mb_->type_ == 1); + const int segment = it->mb_->segment_; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + + pos1 = VP8BitWriterPos(bw); + if (i16) { + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); + } + } + pos2 = VP8BitWriterPos(bw); + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + PutCoeffs(bw, ctx, &res); + } + } + } + pos3 = VP8BitWriterPos(bw); + it->luma_bits_ = pos2 - pos1; + it->uv_bits_ = pos3 - pos2; + it->bit_count_[segment][i16] += it->luma_bits_; + it->bit_count_[segment][2] += it->uv_bits_; + VP8IteratorBytesToNz(it); +} + +// Same as CodeResiduals, but doesn't actually write anything. +// Instead, it just records the event distribution. +static void RecordResiduals(VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int x, y, ch; + VP8Residual res; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + + if (it->mb_->type_ == 1) { // i16x16 + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res); + } + } + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + VP8RecordCoeffs(ctx, &res); + } + } + } + + VP8IteratorBytesToNz(it); +} + +//------------------------------------------------------------------------------ +// Token buffer + +#if !defined(DISABLE_TOKEN_BUFFER) + +static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, + VP8TBuffer* const tokens) { + int x, y, ch; + VP8Residual res; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + if (it->mb_->type_ == 1) { // i16x16 + const int ctx = it->top_nz_[8] + it->left_nz_[8]; + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + VP8RecordCoeffTokens(ctx, &res, tokens); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = + VP8RecordCoeffTokens(ctx, &res, tokens); + } + } + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + VP8RecordCoeffTokens(ctx, &res, tokens); + } + } + } + VP8IteratorBytesToNz(it); + return !tokens->error_; +} + +#endif // !DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ +// ExtraInfo map / Debug function + +#if !defined(WEBP_DISABLE_STATS) + +#if SEGMENT_VISU +static void SetBlock(uint8_t* p, int value, int size) { + int y; + for (y = 0; y < size; ++y) { + memset(p, value, size); + p += BPS; + } +} +#endif + +static void ResetSSE(VP8Encoder* const enc) { + enc->sse_[0] = 0; + enc->sse_[1] = 0; + enc->sse_[2] = 0; + // Note: enc->sse_[3] is managed by alpha.c + enc->sse_count_ = 0; +} + +static void StoreSSE(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + const uint8_t* const in = it->yuv_in_; + const uint8_t* const out = it->yuv_out_; + // Note: not totally accurate at boundary. And doesn't include in-loop filter. + enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC); + enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC); + enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC); + enc->sse_count_ += 16 * 16; +} + +static void StoreSideInfo(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + const VP8MBInfo* const mb = it->mb_; + WebPPicture* const pic = enc->pic_; + + if (pic->stats != NULL) { + StoreSSE(it); + enc->block_count_[0] += (mb->type_ == 0); + enc->block_count_[1] += (mb->type_ == 1); + enc->block_count_[2] += (mb->skip_ != 0); + } + + if (pic->extra_info != NULL) { + uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_]; + switch (pic->extra_info_type) { + case 1: *info = mb->type_; break; + case 2: *info = mb->segment_; break; + case 3: *info = enc->dqm_[mb->segment_].quant_; break; + case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; + case 5: *info = mb->uv_mode_; break; + case 6: { + const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); + *info = (b > 255) ? 255 : b; break; + } + case 7: *info = mb->alpha_; break; + default: *info = 0; break; + } + } +#if SEGMENT_VISU // visualize segments and prediction modes + SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16); + SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8); + SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8); +#endif +} + +static void ResetSideInfo(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + WebPPicture* const pic = enc->pic_; + if (pic->stats != NULL) { + memset(enc->block_count_, 0, sizeof(enc->block_count_)); + } + ResetSSE(enc); +} +#else // defined(WEBP_DISABLE_STATS) +static void ResetSSE(VP8Encoder* const enc) { + (void)enc; +} +static void StoreSideInfo(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + WebPPicture* const pic = enc->pic_; + if (pic->extra_info != NULL) { + if (it->x_ == 0 && it->y_ == 0) { // only do it once, at start + memset(pic->extra_info, 0, + enc->mb_w_ * enc->mb_h_ * sizeof(*pic->extra_info)); + } + } +} + +static void ResetSideInfo(const VP8EncIterator* const it) { + (void)it; +} +#endif // !defined(WEBP_DISABLE_STATS) + +static double GetPSNR(uint64_t mse, uint64_t size) { + return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; +} + +//------------------------------------------------------------------------------ +// StatLoop(): only collect statistics (number of skips, token usage, ...). +// This is used for deciding optimal probabilities. It also modifies the +// quantizer value if some target (size, PSNR) was specified. + +static void SetLoopParams(VP8Encoder* const enc, float q) { + // Make sure the quality parameter is inside valid bounds + q = Clamp(q, 0.f, 100.f); + + VP8SetSegmentParams(enc, q); // setup segment quantizations and filters + SetSegmentProbas(enc); // compute segment probabilities + + ResetStats(enc); + ResetSSE(enc); +} + +static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, + int nb_mbs, int percent_delta, + PassStats* const s) { + VP8EncIterator it; + uint64_t size = 0; + uint64_t size_p0 = 0; + uint64_t distortion = 0; + const uint64_t pixel_count = (uint64_t)nb_mbs * 384; + + VP8IteratorInit(enc, &it); + SetLoopParams(enc, s->q); + do { + VP8ModeScore info; + VP8IteratorImport(&it, NULL); + if (VP8Decimate(&it, &info, rd_opt)) { + // Just record the number of skips and act like skip_proba is not used. + ++enc->proba_.nb_skip_; + } + RecordResiduals(&it, &info); + size += info.R + info.H; + size_p0 += info.H; + distortion += info.D; + if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) { + return 0; + } + VP8IteratorSaveBoundary(&it); + } while (VP8IteratorNext(&it) && --nb_mbs > 0); + + size_p0 += enc->segment_hdr_.size_; + if (s->do_size_search) { + size += FinalizeSkipProba(enc); + size += FinalizeTokenProbas(&enc->proba_); + size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE; + s->value = (double)size; + } else { + s->value = GetPSNR(distortion, pixel_count); + } + return size_p0; +} + +static int StatLoop(VP8Encoder* const enc) { + const int method = enc->method_; + const int do_search = enc->do_search_; + const int fast_probe = ((method == 0 || method == 3) && !do_search); + int num_pass_left = enc->config_->pass; + const int task_percent = 20; + const int percent_per_pass = + (task_percent + num_pass_left / 2) / num_pass_left; + const int final_percent = enc->percent_ + task_percent; + const VP8RDLevel rd_opt = + (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE; + int nb_mbs = enc->mb_w_ * enc->mb_h_; + PassStats stats; + + InitPassStats(enc, &stats); + ResetTokenStats(enc); + + // Fast mode: quick analysis pass over few mbs. Better than nothing. + if (fast_probe) { + if (method == 3) { // we need more stats for method 3 to be reliable. + nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; + } else { + nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; + } + } + + while (num_pass_left-- > 0) { + const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || + (num_pass_left == 0) || + (enc->max_i4_header_bits_ == 0); + const uint64_t size_p0 = + OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats); + if (size_p0 == 0) return 0; +#if (DEBUG_SEARCH > 0) + printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n", + num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q); +#endif + if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { + ++num_pass_left; + enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... + continue; // ...and start over + } + if (is_last_pass) { + break; + } + // If no target size: just do several pass without changing 'q' + if (do_search) { + ComputeNextQ(&stats); + if (fabs(stats.dq) <= DQ_LIMIT) break; + } + } + if (!do_search || !stats.do_size_search) { + // Need to finalize probas now, since it wasn't done during the search. + FinalizeSkipProba(enc); + FinalizeTokenProbas(&enc->proba_); + } + VP8CalculateLevelCosts(&enc->proba_); // finalize costs + return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); +} + +//------------------------------------------------------------------------------ +// Main loops +// + +static const uint8_t kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; + +static int PreLoopInitialize(VP8Encoder* const enc) { + int p; + int ok = 1; + const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; + const int bytes_per_parts = + enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; + // Initialize the bit-writers + for (p = 0; ok && p < enc->num_parts_; ++p) { + ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); + } + if (!ok) { + VP8EncFreeBitWriters(enc); // malloc error occurred + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return ok; +} + +static int PostLoopFinalize(VP8EncIterator* const it, int ok) { + VP8Encoder* const enc = it->enc_; + if (ok) { // Finalize the partitions, check for extra errors. + int p; + for (p = 0; p < enc->num_parts_; ++p) { + VP8BitWriterFinish(enc->parts_ + p); + ok &= !enc->parts_[p].error_; + } + } + + if (ok) { // All good. Finish up. +#if !defined(WEBP_DISABLE_STATS) + if (enc->pic_->stats != NULL) { // finalize byte counters... + int i, s; + for (i = 0; i <= 2; ++i) { + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); + } + } + } +#endif + VP8AdjustFilterStrength(it); // ...and store filter stats. + } else { + // Something bad happened -> need to do some memory cleanup. + VP8EncFreeBitWriters(enc); + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return ok; +} + +//------------------------------------------------------------------------------ +// VP8EncLoop(): does the final bitstream coding. + +static void ResetAfterSkip(VP8EncIterator* const it) { + if (it->mb_->type_ == 1) { + *it->nz_ = 0; // reset all predictors + it->left_nz_[8] = 0; + } else { + *it->nz_ &= (1 << 24); // preserve the dc_nz bit + } +} + +int VP8EncLoop(VP8Encoder* const enc) { + VP8EncIterator it; + int ok = PreLoopInitialize(enc); + if (!ok) return 0; + + StatLoop(enc); // stats-collection loop + + VP8IteratorInit(enc, &it); + VP8InitFilter(&it); + do { + VP8ModeScore info; + const int dont_use_skip = !enc->proba_.use_skip_proba_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; + + VP8IteratorImport(&it, NULL); + // Warning! order is important: first call VP8Decimate() and + // *then* decide how to code the skip decision if there's one. + if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { + CodeResiduals(it.bw_, &it, &info); + if (it.bw_->error_) { + // enc->pic_->error_code is set in PostLoopFinalize(). + ok = 0; + break; + } + } else { // reset predictors after a skip + ResetAfterSkip(&it); + } + StoreSideInfo(&it); + VP8StoreFilterStats(&it); + VP8IteratorExport(&it); + ok = VP8IteratorProgress(&it, 20); + VP8IteratorSaveBoundary(&it); + } while (ok && VP8IteratorNext(&it)); + + return PostLoopFinalize(&it, ok); +} + +//------------------------------------------------------------------------------ +// Single pass using Token Buffer. + +#if !defined(DISABLE_TOKEN_BUFFER) + +#define MIN_COUNT 96 // minimum number of macroblocks before updating stats + +int VP8EncTokenLoop(VP8Encoder* const enc) { + // Roughly refresh the proba eight times per pass + int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; + int num_pass_left = enc->config_->pass; + int remaining_progress = 40; // percents + const int do_search = enc->do_search_; + VP8EncIterator it; + VP8EncProba* const proba = &enc->proba_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; + const uint64_t pixel_count = (uint64_t)enc->mb_w_ * enc->mb_h_ * 384; + PassStats stats; + int ok; + + InitPassStats(enc, &stats); + ok = PreLoopInitialize(enc); + if (!ok) return 0; + + if (max_count < MIN_COUNT) max_count = MIN_COUNT; + + assert(enc->num_parts_ == 1); + assert(enc->use_tokens_); + assert(proba->use_skip_proba_ == 0); + assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful + assert(num_pass_left > 0); + + while (ok && num_pass_left-- > 0) { + const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || + (num_pass_left == 0) || + (enc->max_i4_header_bits_ == 0); + uint64_t size_p0 = 0; + uint64_t distortion = 0; + int cnt = max_count; + // The final number of passes is not trivial to know in advance. + const int pass_progress = remaining_progress / (2 + num_pass_left); + remaining_progress -= pass_progress; + VP8IteratorInit(enc, &it); + SetLoopParams(enc, stats.q); + if (is_last_pass) { + ResetTokenStats(enc); + VP8InitFilter(&it); // don't collect stats until last pass (too costly) + } + VP8TBufferClear(&enc->tokens_); + do { + VP8ModeScore info; + VP8IteratorImport(&it, NULL); + if (--cnt < 0) { + FinalizeTokenProbas(proba); + VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt + cnt = max_count; + } + VP8Decimate(&it, &info, rd_opt); + ok = RecordTokens(&it, &info, &enc->tokens_); + if (!ok) { + WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + break; + } + size_p0 += info.H; + distortion += info.D; + if (is_last_pass) { + StoreSideInfo(&it); + VP8StoreFilterStats(&it); + VP8IteratorExport(&it); + ok = VP8IteratorProgress(&it, pass_progress); + } + VP8IteratorSaveBoundary(&it); + } while (ok && VP8IteratorNext(&it)); + if (!ok) break; + + size_p0 += enc->segment_hdr_.size_; + if (stats.do_size_search) { + uint64_t size = FinalizeTokenProbas(&enc->proba_); + size += VP8EstimateTokenSize(&enc->tokens_, + (const uint8_t*)proba->coeffs_); + size = (size + size_p0 + 1024) >> 11; // -> size in bytes + size += HEADER_SIZE_ESTIMATE; + stats.value = (double)size; + } else { // compute and store PSNR + stats.value = GetPSNR(distortion, pixel_count); + } + +#if (DEBUG_SEARCH > 0) + printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf " + " range:[%.1f, %.1f]\n", + num_pass_left, stats.last_value, stats.value, + stats.last_q, stats.q, stats.dq, stats.qmin, stats.qmax); +#endif + if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { + ++num_pass_left; + enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... + if (is_last_pass) { + ResetSideInfo(&it); + } + continue; // ...and start over + } + if (is_last_pass) { + break; // done + } + if (do_search) { + ComputeNextQ(&stats); // Adjust q + } + } + if (ok) { + if (!stats.do_size_search) { + FinalizeTokenProbas(&enc->proba_); + } + ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, + (const uint8_t*)proba->coeffs_, 1); + } + ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + remaining_progress, + &enc->percent_); + return PostLoopFinalize(&it, ok); +} + +#else + +int VP8EncTokenLoop(VP8Encoder* const enc) { + (void)enc; + return 0; // we shouldn't be here. +} + +#endif // DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/enc/histogram_enc.c b/libraries/webp/src/enc/histogram_enc.c new file mode 100644 index 0000000000..aa164693e1 --- /dev/null +++ b/libraries/webp/src/enc/histogram_enc.c @@ -0,0 +1,1250 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include +#include + +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +#define MAX_BIT_COST FLT_MAX + +// Number of partitions for the three dominant (literal, red and blue) symbol +// costs. +#define NUM_PARTITIONS 4 +// The size of the bin-hash corresponding to the three dominant costs. +#define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS) +// Maximum number of histograms allowed in greedy combining algorithm. +#define MAX_HISTO_GREEDY 100 + +static void HistogramClear(VP8LHistogram* const p) { + uint32_t* const literal = p->literal_; + const int cache_bits = p->palette_code_bits_; + const int histo_size = VP8LGetHistogramSize(cache_bits); + memset(p, 0, histo_size); + p->palette_code_bits_ = cache_bits; + p->literal_ = literal; +} + +// Swap two histogram pointers. +static void HistogramSwap(VP8LHistogram** const A, VP8LHistogram** const B) { + VP8LHistogram* const tmp = *A; + *A = *B; + *B = tmp; +} + +static void HistogramCopy(const VP8LHistogram* const src, + VP8LHistogram* const dst) { + uint32_t* const dst_literal = dst->literal_; + const int dst_cache_bits = dst->palette_code_bits_; + const int literal_size = VP8LHistogramNumCodes(dst_cache_bits); + const int histo_size = VP8LGetHistogramSize(dst_cache_bits); + assert(src->palette_code_bits_ == dst_cache_bits); + memcpy(dst, src, histo_size); + dst->literal_ = dst_literal; + memcpy(dst->literal_, src->literal_, literal_size * sizeof(*dst->literal_)); +} + +int VP8LGetHistogramSize(int cache_bits) { + const int literal_size = VP8LHistogramNumCodes(cache_bits); + const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size; + assert(total_size <= (size_t)0x7fffffff); + return (int)total_size; +} + +void VP8LFreeHistogram(VP8LHistogram* const histo) { + WebPSafeFree(histo); +} + +void VP8LFreeHistogramSet(VP8LHistogramSet* const histo) { + WebPSafeFree(histo); +} + +void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, + VP8LHistogram* const histo) { + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, NULL, 0); + VP8LRefsCursorNext(&c); + } +} + +void VP8LHistogramCreate(VP8LHistogram* const p, + const VP8LBackwardRefs* const refs, + int palette_code_bits) { + if (palette_code_bits >= 0) { + p->palette_code_bits_ = palette_code_bits; + } + HistogramClear(p); + VP8LHistogramStoreRefs(refs, p); +} + +void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits, + int init_arrays) { + p->palette_code_bits_ = palette_code_bits; + if (init_arrays) { + HistogramClear(p); + } else { + p->trivial_symbol_ = 0; + p->bit_cost_ = 0.; + p->literal_cost_ = 0.; + p->red_cost_ = 0.; + p->blue_cost_ = 0.; + memset(p->is_used_, 0, sizeof(p->is_used_)); + } +} + +VP8LHistogram* VP8LAllocateHistogram(int cache_bits) { + VP8LHistogram* histo = NULL; + const int total_size = VP8LGetHistogramSize(cache_bits); + uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); + if (memory == NULL) return NULL; + histo = (VP8LHistogram*)memory; + // literal_ won't necessary be aligned. + histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); + VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 0); + return histo; +} + +// Resets the pointers of the histograms to point to the bit buffer in the set. +static void HistogramSetResetPointers(VP8LHistogramSet* const set, + int cache_bits) { + int i; + const int histo_size = VP8LGetHistogramSize(cache_bits); + uint8_t* memory = (uint8_t*) (set->histograms); + memory += set->max_size * sizeof(*set->histograms); + for (i = 0; i < set->max_size; ++i) { + memory = (uint8_t*) WEBP_ALIGN(memory); + set->histograms[i] = (VP8LHistogram*) memory; + // literal_ won't necessary be aligned. + set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); + memory += histo_size; + } +} + +// Returns the total size of the VP8LHistogramSet. +static size_t HistogramSetTotalSize(int size, int cache_bits) { + const int histo_size = VP8LGetHistogramSize(cache_bits); + return (sizeof(VP8LHistogramSet) + size * (sizeof(VP8LHistogram*) + + histo_size + WEBP_ALIGN_CST)); +} + +VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) { + int i; + VP8LHistogramSet* set; + const size_t total_size = HistogramSetTotalSize(size, cache_bits); + uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); + if (memory == NULL) return NULL; + + set = (VP8LHistogramSet*)memory; + memory += sizeof(*set); + set->histograms = (VP8LHistogram**)memory; + set->max_size = size; + set->size = size; + HistogramSetResetPointers(set, cache_bits); + for (i = 0; i < size; ++i) { + VP8LHistogramInit(set->histograms[i], cache_bits, /*init_arrays=*/ 0); + } + return set; +} + +void VP8LHistogramSetClear(VP8LHistogramSet* const set) { + int i; + const int cache_bits = set->histograms[0]->palette_code_bits_; + const int size = set->max_size; + const size_t total_size = HistogramSetTotalSize(size, cache_bits); + uint8_t* memory = (uint8_t*)set; + + memset(memory, 0, total_size); + memory += sizeof(*set); + set->histograms = (VP8LHistogram**)memory; + set->max_size = size; + set->size = size; + HistogramSetResetPointers(set, cache_bits); + for (i = 0; i < size; ++i) { + set->histograms[i]->palette_code_bits_ = cache_bits; + } +} + +// Removes the histogram 'i' from 'set' by setting it to NULL. +static void HistogramSetRemoveHistogram(VP8LHistogramSet* const set, int i, + int* const num_used) { + assert(set->histograms[i] != NULL); + set->histograms[i] = NULL; + --*num_used; + // If we remove the last valid one, shrink until the next valid one. + if (i == set->size - 1) { + while (set->size >= 1 && set->histograms[set->size - 1] == NULL) { + --set->size; + } + } +} + +// ----------------------------------------------------------------------------- + +void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, + const PixOrCopy* const v, + int (*const distance_modifier)(int, int), + int distance_modifier_arg0) { + if (PixOrCopyIsLiteral(v)) { + ++histo->alpha_[PixOrCopyLiteral(v, 3)]; + ++histo->red_[PixOrCopyLiteral(v, 2)]; + ++histo->literal_[PixOrCopyLiteral(v, 1)]; + ++histo->blue_[PixOrCopyLiteral(v, 0)]; + } else if (PixOrCopyIsCacheIdx(v)) { + const int literal_ix = + NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v); + assert(histo->palette_code_bits_ != 0); + ++histo->literal_[literal_ix]; + } else { + int code, extra_bits; + VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits); + ++histo->literal_[NUM_LITERAL_CODES + code]; + if (distance_modifier == NULL) { + VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); + } else { + VP8LPrefixEncodeBits( + distance_modifier(distance_modifier_arg0, PixOrCopyDistance(v)), + &code, &extra_bits); + } + ++histo->distance_[code]; + } +} + +// ----------------------------------------------------------------------------- +// Entropy-related functions. + +static WEBP_INLINE float BitsEntropyRefine(const VP8LBitEntropy* entropy) { + float mix; + if (entropy->nonzeros < 5) { + if (entropy->nonzeros <= 1) { + return 0; + } + // Two symbols, they will be 0 and 1 in a Huffman code. + // Let's mix in a bit of entropy to favor good clustering when + // distributions of these are combined. + if (entropy->nonzeros == 2) { + return 0.99f * entropy->sum + 0.01f * entropy->entropy; + } + // No matter what the entropy says, we cannot be better than min_limit + // with Huffman coding. I am mixing a bit of entropy into the + // min_limit since it produces much better (~0.5 %) compression results + // perhaps because of better entropy clustering. + if (entropy->nonzeros == 3) { + mix = 0.95f; + } else { + mix = 0.7f; // nonzeros == 4. + } + } else { + mix = 0.627f; + } + + { + float min_limit = 2.f * entropy->sum - entropy->max_val; + min_limit = mix * min_limit + (1.f - mix) * entropy->entropy; + return (entropy->entropy < min_limit) ? min_limit : entropy->entropy; + } +} + +float VP8LBitsEntropy(const uint32_t* const array, int n) { + VP8LBitEntropy entropy; + VP8LBitsEntropyUnrefined(array, n, &entropy); + + return BitsEntropyRefine(&entropy); +} + +static float InitialHuffmanCost(void) { + // Small bias because Huffman code length is typically not stored in + // full length. + static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3; + static const float kSmallBias = 9.1f; + return kHuffmanCodeOfHuffmanCodeSize - kSmallBias; +} + +// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3) +static float FinalHuffmanCost(const VP8LStreaks* const stats) { + // The constants in this function are experimental and got rounded from + // their original values in 1/8 when switched to 1/1024. + float retval = InitialHuffmanCost(); + // Second coefficient: Many zeros in the histogram are covered efficiently + // by a run-length encode. Originally 2/8. + retval += stats->counts[0] * 1.5625f + 0.234375f * stats->streaks[0][1]; + // Second coefficient: Constant values are encoded less efficiently, but still + // RLE'ed. Originally 6/8. + retval += stats->counts[1] * 2.578125f + 0.703125f * stats->streaks[1][1]; + // 0s are usually encoded more efficiently than non-0s. + // Originally 15/8. + retval += 1.796875f * stats->streaks[0][0]; + // Originally 26/8. + retval += 3.28125f * stats->streaks[1][0]; + return retval; +} + +// Get the symbol entropy for the distribution 'population'. +// Set 'trivial_sym', if there's only one symbol present in the distribution. +static float PopulationCost(const uint32_t* const population, int length, + uint32_t* const trivial_sym, + uint8_t* const is_used) { + VP8LBitEntropy bit_entropy; + VP8LStreaks stats; + VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats); + if (trivial_sym != NULL) { + *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code + : VP8L_NON_TRIVIAL_SYM; + } + // The histogram is used if there is at least one non-zero streak. + *is_used = (stats.streaks[1][0] != 0 || stats.streaks[1][1] != 0); + + return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); +} + +// trivial_at_end is 1 if the two histograms only have one element that is +// non-zero: both the zero-th one, or both the last one. +static WEBP_INLINE float GetCombinedEntropy(const uint32_t* const X, + const uint32_t* const Y, int length, + int is_X_used, int is_Y_used, + int trivial_at_end) { + VP8LStreaks stats; + if (trivial_at_end) { + // This configuration is due to palettization that transforms an indexed + // pixel into 0xff000000 | (pixel << 8) in VP8LBundleColorMap. + // BitsEntropyRefine is 0 for histograms with only one non-zero value. + // Only FinalHuffmanCost needs to be evaluated. + memset(&stats, 0, sizeof(stats)); + // Deal with the non-zero value at index 0 or length-1. + stats.streaks[1][0] = 1; + // Deal with the following/previous zero streak. + stats.counts[0] = 1; + stats.streaks[0][1] = length - 1; + return FinalHuffmanCost(&stats); + } else { + VP8LBitEntropy bit_entropy; + if (is_X_used) { + if (is_Y_used) { + VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats); + } else { + VP8LGetEntropyUnrefined(X, length, &bit_entropy, &stats); + } + } else { + if (is_Y_used) { + VP8LGetEntropyUnrefined(Y, length, &bit_entropy, &stats); + } else { + memset(&stats, 0, sizeof(stats)); + stats.counts[0] = 1; + stats.streaks[0][length > 3] = length; + VP8LBitEntropyInit(&bit_entropy); + } + } + + return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); + } +} + +// Estimates the Entropy + Huffman + other block overhead size cost. +float VP8LHistogramEstimateBits(VP8LHistogram* const p) { + return PopulationCost(p->literal_, + VP8LHistogramNumCodes(p->palette_code_bits_), NULL, + &p->is_used_[0]) + + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL, &p->is_used_[1]) + + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL, &p->is_used_[2]) + + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL, &p->is_used_[3]) + + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL, + &p->is_used_[4]) + + (float)VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES) + + (float)VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); +} + +// ----------------------------------------------------------------------------- +// Various histogram combine/cost-eval functions + +static int GetCombinedHistogramEntropy(const VP8LHistogram* const a, + const VP8LHistogram* const b, + float cost_threshold, float* cost) { + const int palette_code_bits = a->palette_code_bits_; + int trivial_at_end = 0; + assert(a->palette_code_bits_ == b->palette_code_bits_); + *cost += GetCombinedEntropy(a->literal_, b->literal_, + VP8LHistogramNumCodes(palette_code_bits), + a->is_used_[0], b->is_used_[0], 0); + *cost += (float)VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES, + b->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES); + if (*cost > cost_threshold) return 0; + + if (a->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM && + a->trivial_symbol_ == b->trivial_symbol_) { + // A, R and B are all 0 or 0xff. + const uint32_t color_a = (a->trivial_symbol_ >> 24) & 0xff; + const uint32_t color_r = (a->trivial_symbol_ >> 16) & 0xff; + const uint32_t color_b = (a->trivial_symbol_ >> 0) & 0xff; + if ((color_a == 0 || color_a == 0xff) && + (color_r == 0 || color_r == 0xff) && + (color_b == 0 || color_b == 0xff)) { + trivial_at_end = 1; + } + } + + *cost += + GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES, a->is_used_[1], + b->is_used_[1], trivial_at_end); + if (*cost > cost_threshold) return 0; + + *cost += + GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES, a->is_used_[2], + b->is_used_[2], trivial_at_end); + if (*cost > cost_threshold) return 0; + + *cost += + GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES, + a->is_used_[3], b->is_used_[3], trivial_at_end); + if (*cost > cost_threshold) return 0; + + *cost += + GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES, + a->is_used_[4], b->is_used_[4], 0); + *cost += (float)VP8LExtraCostCombined(a->distance_, b->distance_, + NUM_DISTANCE_CODES); + if (*cost > cost_threshold) return 0; + + return 1; +} + +static WEBP_INLINE void HistogramAdd(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out) { + VP8LHistogramAdd(a, b, out); + out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_) + ? a->trivial_symbol_ + : VP8L_NON_TRIVIAL_SYM; +} + +// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing +// to the threshold value 'cost_threshold'. The score returned is +// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed. +// Since the previous score passed is 'cost_threshold', we only need to compare +// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out +// early. +static float HistogramAddEval(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out, float cost_threshold) { + float cost = 0; + const float sum_cost = a->bit_cost_ + b->bit_cost_; + cost_threshold += sum_cost; + + if (GetCombinedHistogramEntropy(a, b, cost_threshold, &cost)) { + HistogramAdd(a, b, out); + out->bit_cost_ = cost; + out->palette_code_bits_ = a->palette_code_bits_; + } + + return cost - sum_cost; +} + +// Same as HistogramAddEval(), except that the resulting histogram +// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit +// the term C(b) which is constant over all the evaluations. +static float HistogramAddThresh(const VP8LHistogram* const a, + const VP8LHistogram* const b, + float cost_threshold) { + float cost; + assert(a != NULL && b != NULL); + cost = -a->bit_cost_; + GetCombinedHistogramEntropy(a, b, cost_threshold, &cost); + return cost; +} + +// ----------------------------------------------------------------------------- + +// The structure to keep track of cost range for the three dominant entropy +// symbols. +typedef struct { + float literal_max_; + float literal_min_; + float red_max_; + float red_min_; + float blue_max_; + float blue_min_; +} DominantCostRange; + +static void DominantCostRangeInit(DominantCostRange* const c) { + c->literal_max_ = 0.; + c->literal_min_ = MAX_BIT_COST; + c->red_max_ = 0.; + c->red_min_ = MAX_BIT_COST; + c->blue_max_ = 0.; + c->blue_min_ = MAX_BIT_COST; +} + +static void UpdateDominantCostRange( + const VP8LHistogram* const h, DominantCostRange* const c) { + if (c->literal_max_ < h->literal_cost_) c->literal_max_ = h->literal_cost_; + if (c->literal_min_ > h->literal_cost_) c->literal_min_ = h->literal_cost_; + if (c->red_max_ < h->red_cost_) c->red_max_ = h->red_cost_; + if (c->red_min_ > h->red_cost_) c->red_min_ = h->red_cost_; + if (c->blue_max_ < h->blue_cost_) c->blue_max_ = h->blue_cost_; + if (c->blue_min_ > h->blue_cost_) c->blue_min_ = h->blue_cost_; +} + +static void UpdateHistogramCost(VP8LHistogram* const h) { + uint32_t alpha_sym, red_sym, blue_sym; + const float alpha_cost = + PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym, &h->is_used_[3]); + const float distance_cost = + PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL, &h->is_used_[4]) + + (float)VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); + const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_); + h->literal_cost_ = + PopulationCost(h->literal_, num_codes, NULL, &h->is_used_[0]) + + (float)VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES); + h->red_cost_ = + PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym, &h->is_used_[1]); + h->blue_cost_ = + PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym, &h->is_used_[2]); + h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ + + alpha_cost + distance_cost; + if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) { + h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM; + } else { + h->trivial_symbol_ = + ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0); + } +} + +static int GetBinIdForEntropy(float min, float max, float val) { + const float range = max - min; + if (range > 0.) { + const float delta = val - min; + return (int)((NUM_PARTITIONS - 1e-6) * delta / range); + } else { + return 0; + } +} + +static int GetHistoBinIndex(const VP8LHistogram* const h, + const DominantCostRange* const c, int low_effort) { + int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_, + h->literal_cost_); + assert(bin_id < NUM_PARTITIONS); + if (!low_effort) { + bin_id = bin_id * NUM_PARTITIONS + + GetBinIdForEntropy(c->red_min_, c->red_max_, h->red_cost_); + bin_id = bin_id * NUM_PARTITIONS + + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_); + assert(bin_id < BIN_SIZE); + } + return bin_id; +} + +// Construct the histograms from backward references. +static void HistogramBuild( + int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, + VP8LHistogramSet* const image_histo) { + int x = 0, y = 0; + const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits); + VP8LHistogram** const histograms = image_histo->histograms; + VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs); + assert(histo_bits > 0); + VP8LHistogramSetClear(image_histo); + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits); + VP8LHistogramAddSinglePixOrCopy(histograms[ix], v, NULL, 0); + x += PixOrCopyLength(v); + while (x >= xsize) { + x -= xsize; + ++y; + } + VP8LRefsCursorNext(&c); + } +} + +// Copies the histograms and computes its bit_cost. +static const uint16_t kInvalidHistogramSymbol = (uint16_t)(-1); +static void HistogramCopyAndAnalyze(VP8LHistogramSet* const orig_histo, + VP8LHistogramSet* const image_histo, + int* const num_used, + uint16_t* const histogram_symbols) { + int i, cluster_id; + int num_used_orig = *num_used; + VP8LHistogram** const orig_histograms = orig_histo->histograms; + VP8LHistogram** const histograms = image_histo->histograms; + assert(image_histo->max_size == orig_histo->max_size); + for (cluster_id = 0, i = 0; i < orig_histo->max_size; ++i) { + VP8LHistogram* const histo = orig_histograms[i]; + UpdateHistogramCost(histo); + + // Skip the histogram if it is completely empty, which can happen for tiles + // with no information (when they are skipped because of LZ77). + if (!histo->is_used_[0] && !histo->is_used_[1] && !histo->is_used_[2] + && !histo->is_used_[3] && !histo->is_used_[4]) { + // The first histogram is always used. If an histogram is empty, we set + // its id to be the same as the previous one: this will improve + // compressibility for later LZ77. + assert(i > 0); + HistogramSetRemoveHistogram(image_histo, i, num_used); + HistogramSetRemoveHistogram(orig_histo, i, &num_used_orig); + histogram_symbols[i] = kInvalidHistogramSymbol; + } else { + // Copy histograms from orig_histo[] to image_histo[]. + HistogramCopy(histo, histograms[i]); + histogram_symbols[i] = cluster_id++; + assert(cluster_id <= image_histo->max_size); + } + } +} + +// Partition histograms to different entropy bins for three dominant (literal, +// red and blue) symbol costs and compute the histogram aggregate bit_cost. +static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo, + uint16_t* const bin_map, + int low_effort) { + int i; + VP8LHistogram** const histograms = image_histo->histograms; + const int histo_size = image_histo->size; + DominantCostRange cost_range; + DominantCostRangeInit(&cost_range); + + // Analyze the dominant (literal, red and blue) entropy costs. + for (i = 0; i < histo_size; ++i) { + if (histograms[i] == NULL) continue; + UpdateDominantCostRange(histograms[i], &cost_range); + } + + // bin-hash histograms on three of the dominant (literal, red and blue) + // symbol costs and store the resulting bin_id for each histogram. + for (i = 0; i < histo_size; ++i) { + // bin_map[i] is not set to a special value as its use will later be guarded + // by another (histograms[i] == NULL). + if (histograms[i] == NULL) continue; + bin_map[i] = GetHistoBinIndex(histograms[i], &cost_range, low_effort); + } +} + +// Merges some histograms with same bin_id together if it's advantageous. +// Sets the remaining histograms to NULL. +static void HistogramCombineEntropyBin( + VP8LHistogramSet* const image_histo, int* num_used, + const uint16_t* const clusters, uint16_t* const cluster_mappings, + VP8LHistogram* cur_combo, const uint16_t* const bin_map, int num_bins, + float combine_cost_factor, int low_effort) { + VP8LHistogram** const histograms = image_histo->histograms; + int idx; + struct { + int16_t first; // position of the histogram that accumulates all + // histograms with the same bin_id + uint16_t num_combine_failures; // number of combine failures per bin_id + } bin_info[BIN_SIZE]; + + assert(num_bins <= BIN_SIZE); + for (idx = 0; idx < num_bins; ++idx) { + bin_info[idx].first = -1; + bin_info[idx].num_combine_failures = 0; + } + + // By default, a cluster matches itself. + for (idx = 0; idx < *num_used; ++idx) cluster_mappings[idx] = idx; + for (idx = 0; idx < image_histo->size; ++idx) { + int bin_id, first; + if (histograms[idx] == NULL) continue; + bin_id = bin_map[idx]; + first = bin_info[bin_id].first; + if (first == -1) { + bin_info[bin_id].first = idx; + } else if (low_effort) { + HistogramAdd(histograms[idx], histograms[first], histograms[first]); + HistogramSetRemoveHistogram(image_histo, idx, num_used); + cluster_mappings[clusters[idx]] = clusters[first]; + } else { + // try to merge #idx into #first (both share the same bin_id) + const float bit_cost = histograms[idx]->bit_cost_; + const float bit_cost_thresh = -bit_cost * combine_cost_factor; + const float curr_cost_diff = HistogramAddEval( + histograms[first], histograms[idx], cur_combo, bit_cost_thresh); + if (curr_cost_diff < bit_cost_thresh) { + // Try to merge two histograms only if the combo is a trivial one or + // the two candidate histograms are already non-trivial. + // For some images, 'try_combine' turns out to be false for a lot of + // histogram pairs. In that case, we fallback to combining + // histograms as usual to avoid increasing the header size. + const int try_combine = + (cur_combo->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM) || + ((histograms[idx]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) && + (histograms[first]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM)); + const int max_combine_failures = 32; + if (try_combine || + bin_info[bin_id].num_combine_failures >= max_combine_failures) { + // move the (better) merged histogram to its final slot + HistogramSwap(&cur_combo, &histograms[first]); + HistogramSetRemoveHistogram(image_histo, idx, num_used); + cluster_mappings[clusters[idx]] = clusters[first]; + } else { + ++bin_info[bin_id].num_combine_failures; + } + } + } + } + if (low_effort) { + // for low_effort case, update the final cost when everything is merged + for (idx = 0; idx < image_histo->size; ++idx) { + if (histograms[idx] == NULL) continue; + UpdateHistogramCost(histograms[idx]); + } + } +} + +// Implement a Lehmer random number generator with a multiplicative constant of +// 48271 and a modulo constant of 2^31 - 1. +static uint32_t MyRand(uint32_t* const seed) { + *seed = (uint32_t)(((uint64_t)(*seed) * 48271u) % 2147483647u); + assert(*seed > 0); + return *seed; +} + +// ----------------------------------------------------------------------------- +// Histogram pairs priority queue + +// Pair of histograms. Negative idx1 value means that pair is out-of-date. +typedef struct { + int idx1; + int idx2; + float cost_diff; + float cost_combo; +} HistogramPair; + +typedef struct { + HistogramPair* queue; + int size; + int max_size; +} HistoQueue; + +static int HistoQueueInit(HistoQueue* const histo_queue, const int max_size) { + histo_queue->size = 0; + histo_queue->max_size = max_size; + // We allocate max_size + 1 because the last element at index "size" is + // used as temporary data (and it could be up to max_size). + histo_queue->queue = (HistogramPair*)WebPSafeMalloc( + histo_queue->max_size + 1, sizeof(*histo_queue->queue)); + return histo_queue->queue != NULL; +} + +static void HistoQueueClear(HistoQueue* const histo_queue) { + assert(histo_queue != NULL); + WebPSafeFree(histo_queue->queue); + histo_queue->size = 0; + histo_queue->max_size = 0; +} + +// Pop a specific pair in the queue by replacing it with the last one +// and shrinking the queue. +static void HistoQueuePopPair(HistoQueue* const histo_queue, + HistogramPair* const pair) { + assert(pair >= histo_queue->queue && + pair < (histo_queue->queue + histo_queue->size)); + assert(histo_queue->size > 0); + *pair = histo_queue->queue[histo_queue->size - 1]; + --histo_queue->size; +} + +// Check whether a pair in the queue should be updated as head or not. +static void HistoQueueUpdateHead(HistoQueue* const histo_queue, + HistogramPair* const pair) { + assert(pair->cost_diff < 0.); + assert(pair >= histo_queue->queue && + pair < (histo_queue->queue + histo_queue->size)); + assert(histo_queue->size > 0); + if (pair->cost_diff < histo_queue->queue[0].cost_diff) { + // Replace the best pair. + const HistogramPair tmp = histo_queue->queue[0]; + histo_queue->queue[0] = *pair; + *pair = tmp; + } +} + +// Update the cost diff and combo of a pair of histograms. This needs to be +// called when the the histograms have been merged with a third one. +static void HistoQueueUpdatePair(const VP8LHistogram* const h1, + const VP8LHistogram* const h2, float threshold, + HistogramPair* const pair) { + const float sum_cost = h1->bit_cost_ + h2->bit_cost_; + pair->cost_combo = 0.; + GetCombinedHistogramEntropy(h1, h2, sum_cost + threshold, &pair->cost_combo); + pair->cost_diff = pair->cost_combo - sum_cost; +} + +// Create a pair from indices "idx1" and "idx2" provided its cost +// is inferior to "threshold", a negative entropy. +// It returns the cost of the pair, or 0. if it superior to threshold. +static float HistoQueuePush(HistoQueue* const histo_queue, + VP8LHistogram** const histograms, int idx1, + int idx2, float threshold) { + const VP8LHistogram* h1; + const VP8LHistogram* h2; + HistogramPair pair; + + // Stop here if the queue is full. + if (histo_queue->size == histo_queue->max_size) return 0.; + assert(threshold <= 0.); + if (idx1 > idx2) { + const int tmp = idx2; + idx2 = idx1; + idx1 = tmp; + } + pair.idx1 = idx1; + pair.idx2 = idx2; + h1 = histograms[idx1]; + h2 = histograms[idx2]; + + HistoQueueUpdatePair(h1, h2, threshold, &pair); + + // Do not even consider the pair if it does not improve the entropy. + if (pair.cost_diff >= threshold) return 0.; + + histo_queue->queue[histo_queue->size++] = pair; + HistoQueueUpdateHead(histo_queue, &histo_queue->queue[histo_queue->size - 1]); + + return pair.cost_diff; +} + +// ----------------------------------------------------------------------------- + +// Combines histograms by continuously choosing the one with the highest cost +// reduction. +static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo, + int* const num_used) { + int ok = 0; + const int image_histo_size = image_histo->size; + int i, j; + VP8LHistogram** const histograms = image_histo->histograms; + // Priority queue of histogram pairs. + HistoQueue histo_queue; + + // image_histo_size^2 for the queue size is safe. If you look at + // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes + // data to the queue, you insert at most: + // - image_histo_size*(image_histo_size-1)/2 (the first two for loops) + // - image_histo_size - 1 in the last for loop at the first iteration of + // the while loop, image_histo_size - 2 at the second iteration ... + // therefore image_histo_size*(image_histo_size-1)/2 overall too + if (!HistoQueueInit(&histo_queue, image_histo_size * image_histo_size)) { + goto End; + } + + for (i = 0; i < image_histo_size; ++i) { + if (image_histo->histograms[i] == NULL) continue; + for (j = i + 1; j < image_histo_size; ++j) { + // Initialize queue. + if (image_histo->histograms[j] == NULL) continue; + HistoQueuePush(&histo_queue, histograms, i, j, 0.); + } + } + + while (histo_queue.size > 0) { + const int idx1 = histo_queue.queue[0].idx1; + const int idx2 = histo_queue.queue[0].idx2; + HistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); + histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; + + // Remove merged histogram. + HistogramSetRemoveHistogram(image_histo, idx2, num_used); + + // Remove pairs intersecting the just combined best pair. + for (i = 0; i < histo_queue.size;) { + HistogramPair* const p = histo_queue.queue + i; + if (p->idx1 == idx1 || p->idx2 == idx1 || + p->idx1 == idx2 || p->idx2 == idx2) { + HistoQueuePopPair(&histo_queue, p); + } else { + HistoQueueUpdateHead(&histo_queue, p); + ++i; + } + } + + // Push new pairs formed with combined histogram to the queue. + for (i = 0; i < image_histo->size; ++i) { + if (i == idx1 || image_histo->histograms[i] == NULL) continue; + HistoQueuePush(&histo_queue, image_histo->histograms, idx1, i, 0.); + } + } + + ok = 1; + + End: + HistoQueueClear(&histo_queue); + return ok; +} + +// Perform histogram aggregation using a stochastic approach. +// 'do_greedy' is set to 1 if a greedy approach needs to be performed +// afterwards, 0 otherwise. +static int PairComparison(const void* idx1, const void* idx2) { + // To be used with bsearch: <0 when *idx1<*idx2, >0 if >, 0 when ==. + return (*(int*) idx1 - *(int*) idx2); +} +static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo, + int* const num_used, int min_cluster_size, + int* const do_greedy) { + int j, iter; + uint32_t seed = 1; + int tries_with_no_success = 0; + const int outer_iters = *num_used; + const int num_tries_no_success = outer_iters / 2; + VP8LHistogram** const histograms = image_histo->histograms; + // Priority queue of histogram pairs. Its size of 'kHistoQueueSize' + // impacts the quality of the compression and the speed: the smaller the + // faster but the worse for the compression. + HistoQueue histo_queue; + const int kHistoQueueSize = 9; + int ok = 0; + // mapping from an index in image_histo with no NULL histogram to the full + // blown image_histo. + int* mappings; + + if (*num_used < min_cluster_size) { + *do_greedy = 1; + return 1; + } + + mappings = (int*) WebPSafeMalloc(*num_used, sizeof(*mappings)); + if (mappings == NULL) return 0; + if (!HistoQueueInit(&histo_queue, kHistoQueueSize)) goto End; + // Fill the initial mapping. + for (j = 0, iter = 0; iter < image_histo->size; ++iter) { + if (histograms[iter] == NULL) continue; + mappings[j++] = iter; + } + assert(j == *num_used); + + // Collapse similar histograms in 'image_histo'. + for (iter = 0; + iter < outer_iters && *num_used >= min_cluster_size && + ++tries_with_no_success < num_tries_no_success; + ++iter) { + int* mapping_index; + float best_cost = + (histo_queue.size == 0) ? 0.f : histo_queue.queue[0].cost_diff; + int best_idx1 = -1, best_idx2 = 1; + const uint32_t rand_range = (*num_used - 1) * (*num_used); + // (*num_used) / 2 was chosen empirically. Less means faster but worse + // compression. + const int num_tries = (*num_used) / 2; + + // Pick random samples. + for (j = 0; *num_used >= 2 && j < num_tries; ++j) { + float curr_cost; + // Choose two different histograms at random and try to combine them. + const uint32_t tmp = MyRand(&seed) % rand_range; + uint32_t idx1 = tmp / (*num_used - 1); + uint32_t idx2 = tmp % (*num_used - 1); + if (idx2 >= idx1) ++idx2; + idx1 = mappings[idx1]; + idx2 = mappings[idx2]; + + // Calculate cost reduction on combination. + curr_cost = + HistoQueuePush(&histo_queue, histograms, idx1, idx2, best_cost); + if (curr_cost < 0) { // found a better pair? + best_cost = curr_cost; + // Empty the queue if we reached full capacity. + if (histo_queue.size == histo_queue.max_size) break; + } + } + if (histo_queue.size == 0) continue; + + // Get the best histograms. + best_idx1 = histo_queue.queue[0].idx1; + best_idx2 = histo_queue.queue[0].idx2; + assert(best_idx1 < best_idx2); + // Pop best_idx2 from mappings. + mapping_index = (int*) bsearch(&best_idx2, mappings, *num_used, + sizeof(best_idx2), &PairComparison); + assert(mapping_index != NULL); + memmove(mapping_index, mapping_index + 1, sizeof(*mapping_index) * + ((*num_used) - (mapping_index - mappings) - 1)); + // Merge the histograms and remove best_idx2 from the queue. + HistogramAdd(histograms[best_idx2], histograms[best_idx1], + histograms[best_idx1]); + histograms[best_idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; + HistogramSetRemoveHistogram(image_histo, best_idx2, num_used); + // Parse the queue and update each pair that deals with best_idx1, + // best_idx2 or image_histo_size. + for (j = 0; j < histo_queue.size;) { + HistogramPair* const p = histo_queue.queue + j; + const int is_idx1_best = p->idx1 == best_idx1 || p->idx1 == best_idx2; + const int is_idx2_best = p->idx2 == best_idx1 || p->idx2 == best_idx2; + int do_eval = 0; + // The front pair could have been duplicated by a random pick so + // check for it all the time nevertheless. + if (is_idx1_best && is_idx2_best) { + HistoQueuePopPair(&histo_queue, p); + continue; + } + // Any pair containing one of the two best indices should only refer to + // best_idx1. Its cost should also be updated. + if (is_idx1_best) { + p->idx1 = best_idx1; + do_eval = 1; + } else if (is_idx2_best) { + p->idx2 = best_idx1; + do_eval = 1; + } + // Make sure the index order is respected. + if (p->idx1 > p->idx2) { + const int tmp = p->idx2; + p->idx2 = p->idx1; + p->idx1 = tmp; + } + if (do_eval) { + // Re-evaluate the cost of an updated pair. + HistoQueueUpdatePair(histograms[p->idx1], histograms[p->idx2], 0., p); + if (p->cost_diff >= 0.) { + HistoQueuePopPair(&histo_queue, p); + continue; + } + } + HistoQueueUpdateHead(&histo_queue, p); + ++j; + } + tries_with_no_success = 0; + } + *do_greedy = (*num_used <= min_cluster_size); + ok = 1; + + End: + HistoQueueClear(&histo_queue); + WebPSafeFree(mappings); + return ok; +} + +// ----------------------------------------------------------------------------- +// Histogram refinement + +// Find the best 'out' histogram for each of the 'in' histograms. +// At call-time, 'out' contains the histograms of the clusters. +// Note: we assume that out[]->bit_cost_ is already up-to-date. +static void HistogramRemap(const VP8LHistogramSet* const in, + VP8LHistogramSet* const out, + uint16_t* const symbols) { + int i; + VP8LHistogram** const in_histo = in->histograms; + VP8LHistogram** const out_histo = out->histograms; + const int in_size = out->max_size; + const int out_size = out->size; + if (out_size > 1) { + for (i = 0; i < in_size; ++i) { + int best_out = 0; + float best_bits = MAX_BIT_COST; + int k; + if (in_histo[i] == NULL) { + // Arbitrarily set to the previous value if unused to help future LZ77. + symbols[i] = symbols[i - 1]; + continue; + } + for (k = 0; k < out_size; ++k) { + float cur_bits; + cur_bits = HistogramAddThresh(out_histo[k], in_histo[i], best_bits); + if (k == 0 || cur_bits < best_bits) { + best_bits = cur_bits; + best_out = k; + } + } + symbols[i] = best_out; + } + } else { + assert(out_size == 1); + for (i = 0; i < in_size; ++i) { + symbols[i] = 0; + } + } + + // Recompute each out based on raw and symbols. + VP8LHistogramSetClear(out); + out->size = out_size; + + for (i = 0; i < in_size; ++i) { + int idx; + if (in_histo[i] == NULL) continue; + idx = symbols[i]; + HistogramAdd(in_histo[i], out_histo[idx], out_histo[idx]); + } +} + +static float GetCombineCostFactor(int histo_size, int quality) { + float combine_cost_factor = 0.16f; + if (quality < 90) { + if (histo_size > 256) combine_cost_factor /= 2.f; + if (histo_size > 512) combine_cost_factor /= 2.f; + if (histo_size > 1024) combine_cost_factor /= 2.f; + if (quality <= 50) combine_cost_factor /= 2.f; + } + return combine_cost_factor; +} + +// Given a HistogramSet 'set', the mapping of clusters 'cluster_mapping' and the +// current assignment of the cells in 'symbols', merge the clusters and +// assign the smallest possible clusters values. +static void OptimizeHistogramSymbols(const VP8LHistogramSet* const set, + uint16_t* const cluster_mappings, + int num_clusters, + uint16_t* const cluster_mappings_tmp, + uint16_t* const symbols) { + int i, cluster_max; + int do_continue = 1; + // First, assign the lowest cluster to each pixel. + while (do_continue) { + do_continue = 0; + for (i = 0; i < num_clusters; ++i) { + int k; + k = cluster_mappings[i]; + while (k != cluster_mappings[k]) { + cluster_mappings[k] = cluster_mappings[cluster_mappings[k]]; + k = cluster_mappings[k]; + } + if (k != cluster_mappings[i]) { + do_continue = 1; + cluster_mappings[i] = k; + } + } + } + // Create a mapping from a cluster id to its minimal version. + cluster_max = 0; + memset(cluster_mappings_tmp, 0, + set->max_size * sizeof(*cluster_mappings_tmp)); + assert(cluster_mappings[0] == 0); + // Re-map the ids. + for (i = 0; i < set->max_size; ++i) { + int cluster; + if (symbols[i] == kInvalidHistogramSymbol) continue; + cluster = cluster_mappings[symbols[i]]; + assert(symbols[i] < num_clusters); + if (cluster > 0 && cluster_mappings_tmp[cluster] == 0) { + ++cluster_max; + cluster_mappings_tmp[cluster] = cluster_max; + } + symbols[i] = cluster_mappings_tmp[cluster]; + } + + // Make sure all cluster values are used. + cluster_max = 0; + for (i = 0; i < set->max_size; ++i) { + if (symbols[i] == kInvalidHistogramSymbol) continue; + if (symbols[i] <= cluster_max) continue; + ++cluster_max; + assert(symbols[i] == cluster_max); + } +} + +static void RemoveEmptyHistograms(VP8LHistogramSet* const image_histo) { + uint32_t size; + int i; + for (i = 0, size = 0; i < image_histo->size; ++i) { + if (image_histo->histograms[i] == NULL) continue; + image_histo->histograms[size++] = image_histo->histograms[i]; + } + image_histo->size = size; +} + +int VP8LGetHistoImageSymbols(int xsize, int ysize, + const VP8LBackwardRefs* const refs, int quality, + int low_effort, int histogram_bits, int cache_bits, + VP8LHistogramSet* const image_histo, + VP8LHistogram* const tmp_histo, + uint16_t* const histogram_symbols, + const WebPPicture* const pic, int percent_range, + int* const percent) { + const int histo_xsize = + histogram_bits ? VP8LSubSampleSize(xsize, histogram_bits) : 1; + const int histo_ysize = + histogram_bits ? VP8LSubSampleSize(ysize, histogram_bits) : 1; + const int image_histo_raw_size = histo_xsize * histo_ysize; + VP8LHistogramSet* const orig_histo = + VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits); + // Don't attempt linear bin-partition heuristic for + // histograms of small sizes (as bin_map will be very sparse) and + // maximum quality q==100 (to preserve the compression gains at that level). + const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE; + int entropy_combine; + uint16_t* const map_tmp = + WebPSafeMalloc(2 * image_histo_raw_size, sizeof(*map_tmp)); + uint16_t* const cluster_mappings = map_tmp + image_histo_raw_size; + int num_used = image_histo_raw_size; + if (orig_histo == NULL || map_tmp == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Construct the histograms from backward references. + HistogramBuild(xsize, histogram_bits, refs, orig_histo); + // Copies the histograms and computes its bit_cost. + // histogram_symbols is optimized + HistogramCopyAndAnalyze(orig_histo, image_histo, &num_used, + histogram_symbols); + + entropy_combine = + (num_used > entropy_combine_num_bins * 2) && (quality < 100); + + if (entropy_combine) { + uint16_t* const bin_map = map_tmp; + const float combine_cost_factor = + GetCombineCostFactor(image_histo_raw_size, quality); + const uint32_t num_clusters = num_used; + + HistogramAnalyzeEntropyBin(image_histo, bin_map, low_effort); + // Collapse histograms with similar entropy. + HistogramCombineEntropyBin( + image_histo, &num_used, histogram_symbols, cluster_mappings, tmp_histo, + bin_map, entropy_combine_num_bins, combine_cost_factor, low_effort); + OptimizeHistogramSymbols(image_histo, cluster_mappings, num_clusters, + map_tmp, histogram_symbols); + } + + // Don't combine the histograms using stochastic and greedy heuristics for + // low-effort compression mode. + if (!low_effort || !entropy_combine) { + const float x = quality / 100.f; + // cubic ramp between 1 and MAX_HISTO_GREEDY: + const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); + int do_greedy; + if (!HistogramCombineStochastic(image_histo, &num_used, threshold_size, + &do_greedy)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + if (do_greedy) { + RemoveEmptyHistograms(image_histo); + if (!HistogramCombineGreedy(image_histo, &num_used)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + } + } + + // Find the optimal map from original histograms to the final ones. + RemoveEmptyHistograms(image_histo); + HistogramRemap(orig_histo, image_histo, histogram_symbols); + + if (!WebPReportProgress(pic, *percent + percent_range, percent)) { + goto Error; + } + + Error: + VP8LFreeHistogramSet(orig_histo); + WebPSafeFree(map_tmp); + return (pic->error_code == VP8_ENC_OK); +} diff --git a/libraries/webp/src/enc/histogram_enc.h b/libraries/webp/src/enc/histogram_enc.h new file mode 100644 index 0000000000..719a31b343 --- /dev/null +++ b/libraries/webp/src/enc/histogram_enc.h @@ -0,0 +1,130 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Models the histograms of literal and distance codes. + +#ifndef WEBP_ENC_HISTOGRAM_ENC_H_ +#define WEBP_ENC_HISTOGRAM_ENC_H_ + +#include + +#include "src/enc/backward_references_enc.h" +#include "include/webp/format_constants.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Not a trivial literal symbol. +#define VP8L_NON_TRIVIAL_SYM (0xffffffff) + +// A simple container for histograms of data. +typedef struct { + // literal_ contains green literal, palette-code and + // copy-length-prefix histogram + uint32_t* literal_; // Pointer to the allocated buffer for literal. + uint32_t red_[NUM_LITERAL_CODES]; + uint32_t blue_[NUM_LITERAL_CODES]; + uint32_t alpha_[NUM_LITERAL_CODES]; + // Backward reference prefix-code histogram. + uint32_t distance_[NUM_DISTANCE_CODES]; + int palette_code_bits_; + uint32_t trivial_symbol_; // True, if histograms for Red, Blue & Alpha + // literal symbols are single valued. + float bit_cost_; // cached value of bit cost. + float literal_cost_; // Cached values of dominant entropy costs: + float red_cost_; // literal, red & blue. + float blue_cost_; + uint8_t is_used_[5]; // 5 for literal, red, blue, alpha, distance +} VP8LHistogram; + +// Collection of histograms with fixed capacity, allocated as one +// big memory chunk. Can be destroyed by calling WebPSafeFree(). +typedef struct { + int size; // number of slots currently in use + int max_size; // maximum capacity + VP8LHistogram** histograms; +} VP8LHistogramSet; + +// Create the histogram. +// +// The input data is the PixOrCopy data, which models the literals, stop +// codes and backward references (both distances and lengths). Also: if +// palette_code_bits is >= 0, initialize the histogram with this value. +void VP8LHistogramCreate(VP8LHistogram* const p, + const VP8LBackwardRefs* const refs, + int palette_code_bits); + +// Return the size of the histogram for a given cache_bits. +int VP8LGetHistogramSize(int cache_bits); + +// Set the palette_code_bits and reset the stats. +// If init_arrays is true, the arrays are also filled with 0's. +void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits, + int init_arrays); + +// Collect all the references into a histogram (without reset) +void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, + VP8LHistogram* const histo); + +// Free the memory allocated for the histogram. +void VP8LFreeHistogram(VP8LHistogram* const histo); + +// Free the memory allocated for the histogram set. +void VP8LFreeHistogramSet(VP8LHistogramSet* const histo); + +// Allocate an array of pointer to histograms, allocated and initialized +// using 'cache_bits'. Return NULL in case of memory error. +VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits); + +// Set the histograms in set to 0. +void VP8LHistogramSetClear(VP8LHistogramSet* const set); + +// Allocate and initialize histogram object with specified 'cache_bits'. +// Returns NULL in case of memory error. +// Special case of VP8LAllocateHistogramSet, with size equals 1. +VP8LHistogram* VP8LAllocateHistogram(int cache_bits); + +// Accumulate a token 'v' into a histogram. +void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, + const PixOrCopy* const v, + int (*const distance_modifier)(int, int), + int distance_modifier_arg0); + +static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) { + return NUM_LITERAL_CODES + NUM_LENGTH_CODES + + ((palette_code_bits > 0) ? (1 << palette_code_bits) : 0); +} + +// Builds the histogram image. pic and percent are for progress. +// Returns false in case of error (stored in pic->error_code). +int VP8LGetHistoImageSymbols(int xsize, int ysize, + const VP8LBackwardRefs* const refs, int quality, + int low_effort, int histogram_bits, int cache_bits, + VP8LHistogramSet* const image_histo, + VP8LHistogram* const tmp_histo, + uint16_t* const histogram_symbols, + const WebPPicture* const pic, int percent_range, + int* const percent); + +// Returns the entropy for the symbols in the input array. +float VP8LBitsEntropy(const uint32_t* const array, int n); + +// Estimate how many bits the combined entropy of literals and distance +// approximately maps to. +float VP8LHistogramEstimateBits(VP8LHistogram* const p); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_ENC_HISTOGRAM_ENC_H_ diff --git a/libraries/webp/src/enc/iterator_enc.c b/libraries/webp/src/enc/iterator_enc.c new file mode 100644 index 0000000000..29f91d8315 --- /dev/null +++ b/libraries/webp/src/enc/iterator_enc.c @@ -0,0 +1,459 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// VP8Iterator: block iterator +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// VP8Iterator +//------------------------------------------------------------------------------ + +static void InitLeft(VP8EncIterator* const it) { + it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = + (it->y_ > 0) ? 129 : 127; + memset(it->y_left_, 129, 16); + memset(it->u_left_, 129, 8); + memset(it->v_left_, 129, 8); + it->left_nz_[8] = 0; + if (it->top_derr_ != NULL) { + memset(&it->left_derr_, 0, sizeof(it->left_derr_)); + } +} + +static void InitTop(VP8EncIterator* const it) { + const VP8Encoder* const enc = it->enc_; + const size_t top_size = enc->mb_w_ * 16; + memset(enc->y_top_, 127, 2 * top_size); + memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_)); + if (enc->top_derr_ != NULL) { + memset(enc->top_derr_, 0, enc->mb_w_ * sizeof(*enc->top_derr_)); + } +} + +void VP8IteratorSetRow(VP8EncIterator* const it, int y) { + VP8Encoder* const enc = it->enc_; + it->x_ = 0; + it->y_ = y; + it->bw_ = &enc->parts_[y & (enc->num_parts_ - 1)]; + it->preds_ = enc->preds_ + y * 4 * enc->preds_w_; + it->nz_ = enc->nz_; + it->mb_ = enc->mb_info_ + y * enc->mb_w_; + it->y_top_ = enc->y_top_; + it->uv_top_ = enc->uv_top_; + InitLeft(it); +} + +void VP8IteratorReset(VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + VP8IteratorSetRow(it, 0); + VP8IteratorSetCountDown(it, enc->mb_w_ * enc->mb_h_); // default + InitTop(it); + memset(it->bit_count_, 0, sizeof(it->bit_count_)); + it->do_trellis_ = 0; +} + +void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down) { + it->count_down_ = it->count_down0_ = count_down; +} + +int VP8IteratorIsDone(const VP8EncIterator* const it) { + return (it->count_down_ <= 0); +} + +void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) { + it->enc_ = enc; + it->yuv_in_ = (uint8_t*)WEBP_ALIGN(it->yuv_mem_); + it->yuv_out_ = it->yuv_in_ + YUV_SIZE_ENC; + it->yuv_out2_ = it->yuv_out_ + YUV_SIZE_ENC; + it->yuv_p_ = it->yuv_out2_ + YUV_SIZE_ENC; + it->lf_stats_ = enc->lf_stats_; + it->percent0_ = enc->percent_; + it->y_left_ = (uint8_t*)WEBP_ALIGN(it->yuv_left_mem_ + 1); + it->u_left_ = it->y_left_ + 16 + 16; + it->v_left_ = it->u_left_ + 16; + it->top_derr_ = enc->top_derr_; + VP8IteratorReset(it); +} + +int VP8IteratorProgress(const VP8EncIterator* const it, int delta) { + VP8Encoder* const enc = it->enc_; + if (delta && enc->pic_->progress_hook != NULL) { + const int done = it->count_down0_ - it->count_down_; + const int percent = (it->count_down0_ <= 0) + ? it->percent0_ + : it->percent0_ + delta * done / it->count_down0_; + return WebPReportProgress(enc->pic_, percent, &enc->percent_); + } + return 1; +} + +//------------------------------------------------------------------------------ +// Import the source samples into the cache. Takes care of replicating +// boundary pixels if necessary. + +static WEBP_INLINE int MinSize(int a, int b) { return (a < b) ? a : b; } + +static void ImportBlock(const uint8_t* src, int src_stride, + uint8_t* dst, int w, int h, int size) { + int i; + for (i = 0; i < h; ++i) { + memcpy(dst, src, w); + if (w < size) { + memset(dst + w, dst[w - 1], size - w); + } + dst += BPS; + src += src_stride; + } + for (i = h; i < size; ++i) { + memcpy(dst, dst - BPS, size); + dst += BPS; + } +} + +static void ImportLine(const uint8_t* src, int src_stride, + uint8_t* dst, int len, int total_len) { + int i; + for (i = 0; i < len; ++i, src += src_stride) dst[i] = *src; + for (; i < total_len; ++i) dst[i] = dst[len - 1]; +} + +void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32) { + const VP8Encoder* const enc = it->enc_; + const int x = it->x_, y = it->y_; + const WebPPicture* const pic = enc->pic_; + const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16; + const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8; + const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8; + const int w = MinSize(pic->width - x * 16, 16); + const int h = MinSize(pic->height - y * 16, 16); + const int uv_w = (w + 1) >> 1; + const int uv_h = (h + 1) >> 1; + + ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF_ENC, w, h, 16); + ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF_ENC, uv_w, uv_h, 8); + ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF_ENC, uv_w, uv_h, 8); + + if (tmp_32 == NULL) return; + + // Import source (uncompressed) samples into boundary. + if (x == 0) { + InitLeft(it); + } else { + if (y == 0) { + it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = 127; + } else { + it->y_left_[-1] = ysrc[- 1 - pic->y_stride]; + it->u_left_[-1] = usrc[- 1 - pic->uv_stride]; + it->v_left_[-1] = vsrc[- 1 - pic->uv_stride]; + } + ImportLine(ysrc - 1, pic->y_stride, it->y_left_, h, 16); + ImportLine(usrc - 1, pic->uv_stride, it->u_left_, uv_h, 8); + ImportLine(vsrc - 1, pic->uv_stride, it->v_left_, uv_h, 8); + } + + it->y_top_ = tmp_32 + 0; + it->uv_top_ = tmp_32 + 16; + if (y == 0) { + memset(tmp_32, 127, 32 * sizeof(*tmp_32)); + } else { + ImportLine(ysrc - pic->y_stride, 1, tmp_32, w, 16); + ImportLine(usrc - pic->uv_stride, 1, tmp_32 + 16, uv_w, 8); + ImportLine(vsrc - pic->uv_stride, 1, tmp_32 + 16 + 8, uv_w, 8); + } +} + +//------------------------------------------------------------------------------ +// Copy back the compressed samples into user space if requested. + +static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride, + int w, int h) { + while (h-- > 0) { + memcpy(dst, src, w); + dst += dst_stride; + src += BPS; + } +} + +void VP8IteratorExport(const VP8EncIterator* const it) { + const VP8Encoder* const enc = it->enc_; + if (enc->config_->show_compressed) { + const int x = it->x_, y = it->y_; + const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC; + const uint8_t* const usrc = it->yuv_out_ + U_OFF_ENC; + const uint8_t* const vsrc = it->yuv_out_ + V_OFF_ENC; + const WebPPicture* const pic = enc->pic_; + uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16; + uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8; + uint8_t* const vdst = pic->v + (y * pic->uv_stride + x) * 8; + int w = (pic->width - x * 16); + int h = (pic->height - y * 16); + + if (w > 16) w = 16; + if (h > 16) h = 16; + + // Luma plane + ExportBlock(ysrc, ydst, pic->y_stride, w, h); + + { // U/V planes + const int uv_w = (w + 1) >> 1; + const int uv_h = (h + 1) >> 1; + ExportBlock(usrc, udst, pic->uv_stride, uv_w, uv_h); + ExportBlock(vsrc, vdst, pic->uv_stride, uv_w, uv_h); + } + } +} + +//------------------------------------------------------------------------------ +// Non-zero contexts setup/teardown + +// Nz bits: +// 0 1 2 3 Y +// 4 5 6 7 +// 8 9 10 11 +// 12 13 14 15 +// 16 17 U +// 18 19 +// 20 21 V +// 22 23 +// 24 DC-intra16 + +// Convert packed context to byte array +#define BIT(nz, n) (!!((nz) & (1 << (n)))) + +void VP8IteratorNzToBytes(VP8EncIterator* const it) { + const int tnz = it->nz_[0], lnz = it->nz_[-1]; + int* const top_nz = it->top_nz_; + int* const left_nz = it->left_nz_; + + // Top-Y + top_nz[0] = BIT(tnz, 12); + top_nz[1] = BIT(tnz, 13); + top_nz[2] = BIT(tnz, 14); + top_nz[3] = BIT(tnz, 15); + // Top-U + top_nz[4] = BIT(tnz, 18); + top_nz[5] = BIT(tnz, 19); + // Top-V + top_nz[6] = BIT(tnz, 22); + top_nz[7] = BIT(tnz, 23); + // DC + top_nz[8] = BIT(tnz, 24); + + // left-Y + left_nz[0] = BIT(lnz, 3); + left_nz[1] = BIT(lnz, 7); + left_nz[2] = BIT(lnz, 11); + left_nz[3] = BIT(lnz, 15); + // left-U + left_nz[4] = BIT(lnz, 17); + left_nz[5] = BIT(lnz, 19); + // left-V + left_nz[6] = BIT(lnz, 21); + left_nz[7] = BIT(lnz, 23); + // left-DC is special, iterated separately +} + +void VP8IteratorBytesToNz(VP8EncIterator* const it) { + uint32_t nz = 0; + const int* const top_nz = it->top_nz_; + const int* const left_nz = it->left_nz_; + // top + nz |= (top_nz[0] << 12) | (top_nz[1] << 13); + nz |= (top_nz[2] << 14) | (top_nz[3] << 15); + nz |= (top_nz[4] << 18) | (top_nz[5] << 19); + nz |= (top_nz[6] << 22) | (top_nz[7] << 23); + nz |= (top_nz[8] << 24); // we propagate the _top_ bit, esp. for intra4 + // left + nz |= (left_nz[0] << 3) | (left_nz[1] << 7); + nz |= (left_nz[2] << 11); + nz |= (left_nz[4] << 17) | (left_nz[6] << 21); + + *it->nz_ = nz; +} + +#undef BIT + +//------------------------------------------------------------------------------ +// Advance to the next position, doing the bookkeeping. + +void VP8IteratorSaveBoundary(VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + const int x = it->x_, y = it->y_; + const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC; + const uint8_t* const uvsrc = it->yuv_out_ + U_OFF_ENC; + if (x < enc->mb_w_ - 1) { // left + int i; + for (i = 0; i < 16; ++i) { + it->y_left_[i] = ysrc[15 + i * BPS]; + } + for (i = 0; i < 8; ++i) { + it->u_left_[i] = uvsrc[7 + i * BPS]; + it->v_left_[i] = uvsrc[15 + i * BPS]; + } + // top-left (before 'top'!) + it->y_left_[-1] = it->y_top_[15]; + it->u_left_[-1] = it->uv_top_[0 + 7]; + it->v_left_[-1] = it->uv_top_[8 + 7]; + } + if (y < enc->mb_h_ - 1) { // top + memcpy(it->y_top_, ysrc + 15 * BPS, 16); + memcpy(it->uv_top_, uvsrc + 7 * BPS, 8 + 8); + } +} + +int VP8IteratorNext(VP8EncIterator* const it) { + if (++it->x_ == it->enc_->mb_w_) { + VP8IteratorSetRow(it, ++it->y_); + } else { + it->preds_ += 4; + it->mb_ += 1; + it->nz_ += 1; + it->y_top_ += 16; + it->uv_top_ += 16; + } + return (0 < --it->count_down_); +} + +//------------------------------------------------------------------------------ +// Helper function to set mode properties + +void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) { + uint8_t* preds = it->preds_; + int y; + for (y = 0; y < 4; ++y) { + memset(preds, mode, 4); + preds += it->enc_->preds_w_; + } + it->mb_->type_ = 1; +} + +void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes) { + uint8_t* preds = it->preds_; + int y; + for (y = 4; y > 0; --y) { + memcpy(preds, modes, 4 * sizeof(*modes)); + preds += it->enc_->preds_w_; + modes += 4; + } + it->mb_->type_ = 0; +} + +void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode) { + it->mb_->uv_mode_ = mode; +} + +void VP8SetSkip(const VP8EncIterator* const it, int skip) { + it->mb_->skip_ = skip; +} + +void VP8SetSegment(const VP8EncIterator* const it, int segment) { + it->mb_->segment_ = segment; +} + +//------------------------------------------------------------------------------ +// Intra4x4 sub-blocks iteration +// +// We store and update the boundary samples into an array of 37 pixels. They +// are updated as we iterate and reconstructs each intra4x4 blocks in turn. +// The position of the samples has the following snake pattern: +// +// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36 <- Top-right +// --+-----------+-----------+-----------+-----------+ +// 15| 19| 23| 27| 31| +// 14| 18| 22| 26| 30| +// 13| 17| 21| 25| 29| +// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28| +// --+-----------+-----------+-----------+-----------+ +// 11| 15| 19| 23| 27| +// 10| 14| 18| 22| 26| +// 9| 13| 17| 21| 25| +// 8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24| +// --+-----------+-----------+-----------+-----------+ +// 7| 11| 15| 19| 23| +// 6| 10| 14| 18| 22| +// 5| 9| 13| 17| 21| +// 4| 5 6 7 8| 9 10 11 12|13 14 15 16|17 18 19 20| +// --+-----------+-----------+-----------+-----------+ +// 3| 7| 11| 15| 19| +// 2| 6| 10| 14| 18| +// 1| 5| 9| 13| 17| +// 0| 1 2 3 4| 5 6 7 8| 9 10 11 12|13 14 15 16| +// --+-----------+-----------+-----------+-----------+ + +// Array to record the position of the top sample to pass to the prediction +// functions in dsp.c. +static const uint8_t VP8TopLeftI4[16] = { + 17, 21, 25, 29, + 13, 17, 21, 25, + 9, 13, 17, 21, + 5, 9, 13, 17 +}; + +void VP8IteratorStartI4(VP8EncIterator* const it) { + const VP8Encoder* const enc = it->enc_; + int i; + + it->i4_ = 0; // first 4x4 sub-block + it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0]; + + // Import the boundary samples + for (i = 0; i < 17; ++i) { // left + it->i4_boundary_[i] = it->y_left_[15 - i]; + } + for (i = 0; i < 16; ++i) { // top + it->i4_boundary_[17 + i] = it->y_top_[i]; + } + // top-right samples have a special case on the far right of the picture + if (it->x_ < enc->mb_w_ - 1) { + for (i = 16; i < 16 + 4; ++i) { + it->i4_boundary_[17 + i] = it->y_top_[i]; + } + } else { // else, replicate the last valid pixel four times + for (i = 16; i < 16 + 4; ++i) { + it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15]; + } + } + VP8IteratorNzToBytes(it); // import the non-zero context +} + +int VP8IteratorRotateI4(VP8EncIterator* const it, + const uint8_t* const yuv_out) { + const uint8_t* const blk = yuv_out + VP8Scan[it->i4_]; + uint8_t* const top = it->i4_top_; + int i; + + // Update the cache with 7 fresh samples + for (i = 0; i <= 3; ++i) { + top[-4 + i] = blk[i + 3 * BPS]; // store future top samples + } + if ((it->i4_ & 3) != 3) { // if not on the right sub-blocks #3, #7, #11, #15 + for (i = 0; i <= 2; ++i) { // store future left samples + top[i] = blk[3 + (2 - i) * BPS]; + } + } else { // else replicate top-right samples, as says the specs. + for (i = 0; i <= 3; ++i) { + top[i] = top[i + 4]; + } + } + // move pointers to next sub-block + ++it->i4_; + if (it->i4_ == 16) { // we're done + return 0; + } + + it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_]; + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/enc/near_lossless_enc.c b/libraries/webp/src/enc/near_lossless_enc.c new file mode 100644 index 0000000000..5517a7e271 --- /dev/null +++ b/libraries/webp/src/enc/near_lossless_enc.c @@ -0,0 +1,151 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Near-lossless image preprocessing adjusts pixel values to help +// compressibility with a guarantee of maximum deviation between original and +// resulting pixel values. +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// Converted to C by Aleksander Kramarz (akramarz@google.com) + +#include +#include + +#include "src/dsp/lossless_common.h" +#include "src/utils/utils.h" +#include "src/enc/vp8li_enc.h" + +#if (WEBP_NEAR_LOSSLESS == 1) + +#define MIN_DIM_FOR_NEAR_LOSSLESS 64 +#define MAX_LIMIT_BITS 5 + +// Quantizes the value up or down to a multiple of 1<> 1) + ((a >> bits) & 1); + assert(bits > 0); + if (biased > 0xff) return 0xff; + return biased & ~mask; +} + +// Applies FindClosestDiscretized to all channels of pixel. +static uint32_t ClosestDiscretizedArgb(uint32_t a, int bits) { + return + (FindClosestDiscretized(a >> 24, bits) << 24) | + (FindClosestDiscretized((a >> 16) & 0xff, bits) << 16) | + (FindClosestDiscretized((a >> 8) & 0xff, bits) << 8) | + (FindClosestDiscretized(a & 0xff, bits)); +} + +// Checks if distance between corresponding channel values of pixels a and b +// is within the given limit. +static int IsNear(uint32_t a, uint32_t b, int limit) { + int k; + for (k = 0; k < 4; ++k) { + const int delta = + (int)((a >> (k * 8)) & 0xff) - (int)((b >> (k * 8)) & 0xff); + if (delta >= limit || delta <= -limit) { + return 0; + } + } + return 1; +} + +static int IsSmooth(const uint32_t* const prev_row, + const uint32_t* const curr_row, + const uint32_t* const next_row, + int ix, int limit) { + // Check that all pixels in 4-connected neighborhood are smooth. + return (IsNear(curr_row[ix], curr_row[ix - 1], limit) && + IsNear(curr_row[ix], curr_row[ix + 1], limit) && + IsNear(curr_row[ix], prev_row[ix], limit) && + IsNear(curr_row[ix], next_row[ix], limit)); +} + +// Adjusts pixel values of image with given maximum error. +static void NearLossless(int xsize, int ysize, const uint32_t* argb_src, + int stride, int limit_bits, uint32_t* copy_buffer, + uint32_t* argb_dst) { + int x, y; + const int limit = 1 << limit_bits; + uint32_t* prev_row = copy_buffer; + uint32_t* curr_row = prev_row + xsize; + uint32_t* next_row = curr_row + xsize; + memcpy(curr_row, argb_src, xsize * sizeof(argb_src[0])); + memcpy(next_row, argb_src + stride, xsize * sizeof(argb_src[0])); + + for (y = 0; y < ysize; ++y, argb_src += stride, argb_dst += xsize) { + if (y == 0 || y == ysize - 1) { + memcpy(argb_dst, argb_src, xsize * sizeof(argb_src[0])); + } else { + memcpy(next_row, argb_src + stride, xsize * sizeof(argb_src[0])); + argb_dst[0] = argb_src[0]; + argb_dst[xsize - 1] = argb_src[xsize - 1]; + for (x = 1; x < xsize - 1; ++x) { + if (IsSmooth(prev_row, curr_row, next_row, x, limit)) { + argb_dst[x] = curr_row[x]; + } else { + argb_dst[x] = ClosestDiscretizedArgb(curr_row[x], limit_bits); + } + } + } + { + // Three-way swap. + uint32_t* const temp = prev_row; + prev_row = curr_row; + curr_row = next_row; + next_row = temp; + } + } +} + +int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, + uint32_t* const argb_dst) { + int i; + const int xsize = picture->width; + const int ysize = picture->height; + const int stride = picture->argb_stride; + uint32_t* const copy_buffer = + (uint32_t*)WebPSafeMalloc(xsize * 3, sizeof(*copy_buffer)); + const int limit_bits = VP8LNearLosslessBits(quality); + assert(argb_dst != NULL); + assert(limit_bits > 0); + assert(limit_bits <= MAX_LIMIT_BITS); + if (copy_buffer == NULL) { + return 0; + } + // For small icon images, don't attempt to apply near-lossless compression. + if ((xsize < MIN_DIM_FOR_NEAR_LOSSLESS && + ysize < MIN_DIM_FOR_NEAR_LOSSLESS) || + ysize < 3) { + for (i = 0; i < ysize; ++i) { + memcpy(argb_dst + i * xsize, picture->argb + i * picture->argb_stride, + xsize * sizeof(*argb_dst)); + } + WebPSafeFree(copy_buffer); + return 1; + } + + NearLossless(xsize, ysize, picture->argb, stride, limit_bits, copy_buffer, + argb_dst); + for (i = limit_bits - 1; i != 0; --i) { + NearLossless(xsize, ysize, argb_dst, xsize, i, copy_buffer, argb_dst); + } + WebPSafeFree(copy_buffer); + return 1; +} +#else // (WEBP_NEAR_LOSSLESS == 1) + +// Define a stub to suppress compiler warnings. +extern void VP8LNearLosslessStub(void); +void VP8LNearLosslessStub(void) {} + +#endif // (WEBP_NEAR_LOSSLESS == 1) diff --git a/libraries/webp/src/enc/picture_csp_enc.c b/libraries/webp/src/enc/picture_csp_enc.c new file mode 100644 index 0000000000..a9280e6c30 --- /dev/null +++ b/libraries/webp/src/enc/picture_csp_enc.c @@ -0,0 +1,846 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture utils for colorspace conversion +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "sharpyuv/sharpyuv.h" +#include "sharpyuv/sharpyuv_csp.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/random_utils.h" +#include "src/utils/utils.h" +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/yuv.h" +#include "src/dsp/cpu.h" + +#if defined(WEBP_USE_THREAD) && !defined(_WIN32) +#include +#endif + +// Uncomment to disable gamma-compression during RGB->U/V averaging +#define USE_GAMMA_COMPRESSION + +// If defined, use table to compute x / alpha. +#define USE_INVERSE_ALPHA_TABLE + +#ifdef WORDS_BIGENDIAN +// uint32_t 0xff000000 is 0xff,00,00,00 in memory +#define CHANNEL_OFFSET(i) (i) +#else +// uint32_t 0xff000000 is 0x00,00,00,ff in memory +#define CHANNEL_OFFSET(i) (3-(i)) +#endif + +#define ALPHA_OFFSET CHANNEL_OFFSET(0) + +//------------------------------------------------------------------------------ +// Detection of non-trivial transparency + +// Returns true if alpha[] has non-0xff values. +static int CheckNonOpaque(const uint8_t* alpha, int width, int height, + int x_step, int y_step) { + if (alpha == NULL) return 0; + WebPInitAlphaProcessing(); + if (x_step == 1) { + for (; height-- > 0; alpha += y_step) { + if (WebPHasAlpha8b(alpha, width)) return 1; + } + } else { + for (; height-- > 0; alpha += y_step) { + if (WebPHasAlpha32b(alpha, width)) return 1; + } + } + return 0; +} + +// Checking for the presence of non-opaque alpha. +int WebPPictureHasTransparency(const WebPPicture* picture) { + if (picture == NULL) return 0; + if (picture->use_argb) { + if (picture->argb != NULL) { + return CheckNonOpaque((const uint8_t*)picture->argb + ALPHA_OFFSET, + picture->width, picture->height, + 4, picture->argb_stride * sizeof(*picture->argb)); + } + return 0; + } + return CheckNonOpaque(picture->a, picture->width, picture->height, + 1, picture->a_stride); +} + +//------------------------------------------------------------------------------ +// Code for gamma correction + +#if defined(USE_GAMMA_COMPRESSION) + +// Gamma correction compensates loss of resolution during chroma subsampling. +#define GAMMA_FIX 12 // fixed-point precision for linear values +#define GAMMA_TAB_FIX 7 // fixed-point fractional bits precision +#define GAMMA_TAB_SIZE (1 << (GAMMA_FIX - GAMMA_TAB_FIX)) +static const double kGamma = 0.80; +static const int kGammaScale = ((1 << GAMMA_FIX) - 1); +static const int kGammaTabScale = (1 << GAMMA_TAB_FIX); +static const int kGammaTabRounder = (1 << GAMMA_TAB_FIX >> 1); + +static int kLinearToGammaTab[GAMMA_TAB_SIZE + 1]; +static uint16_t kGammaToLinearTab[256]; +static volatile int kGammaTablesOk = 0; +static void InitGammaTables(void); +extern VP8CPUInfo VP8GetCPUInfo; + +WEBP_DSP_INIT_FUNC(InitGammaTables) { + if (!kGammaTablesOk) { + int v; + const double scale = (double)(1 << GAMMA_TAB_FIX) / kGammaScale; + const double norm = 1. / 255.; + for (v = 0; v <= 255; ++v) { + kGammaToLinearTab[v] = + (uint16_t)(pow(norm * v, kGamma) * kGammaScale + .5); + } + for (v = 0; v <= GAMMA_TAB_SIZE; ++v) { + kLinearToGammaTab[v] = (int)(255. * pow(scale * v, 1. / kGamma) + .5); + } + kGammaTablesOk = 1; + } +} + +static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { + return kGammaToLinearTab[v]; +} + +static WEBP_INLINE int Interpolate(int v) { + const int tab_pos = v >> (GAMMA_TAB_FIX + 2); // integer part + const int x = v & ((kGammaTabScale << 2) - 1); // fractional part + const int v0 = kLinearToGammaTab[tab_pos]; + const int v1 = kLinearToGammaTab[tab_pos + 1]; + const int y = v1 * x + v0 * ((kGammaTabScale << 2) - x); // interpolate + assert(tab_pos + 1 < GAMMA_TAB_SIZE + 1); + return y; +} + +// Convert a linear value 'v' to YUV_FIX+2 fixed-point precision +// U/V value, suitable for RGBToU/V calls. +static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { + const int y = Interpolate(base_value << shift); // final uplifted value + return (y + kGammaTabRounder) >> GAMMA_TAB_FIX; // descale +} + +#else + +static void InitGammaTables(void) {} +static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; } +static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { + return (int)(base_value << shift); +} + +#endif // USE_GAMMA_COMPRESSION + +//------------------------------------------------------------------------------ +// RGB -> YUV conversion + +static int RGBToY(int r, int g, int b, VP8Random* const rg) { + return (rg == NULL) ? VP8RGBToY(r, g, b, YUV_HALF) + : VP8RGBToY(r, g, b, VP8RandomBits(rg, YUV_FIX)); +} + +static int RGBToU(int r, int g, int b, VP8Random* const rg) { + return (rg == NULL) ? VP8RGBToU(r, g, b, YUV_HALF << 2) + : VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); +} + +static int RGBToV(int r, int g, int b, VP8Random* const rg) { + return (rg == NULL) ? VP8RGBToV(r, g, b, YUV_HALF << 2) + : VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); +} + +//------------------------------------------------------------------------------ +// Sharp RGB->YUV conversion + +static const int kMinDimensionIterativeConversion = 4; + +//------------------------------------------------------------------------------ +// Main function + +static int PreprocessARGB(const uint8_t* r_ptr, + const uint8_t* g_ptr, + const uint8_t* b_ptr, + int step, int rgb_stride, + WebPPicture* const picture) { + const int ok = SharpYuvConvert( + r_ptr, g_ptr, b_ptr, step, rgb_stride, /*rgb_bit_depth=*/8, + picture->y, picture->y_stride, picture->u, picture->uv_stride, picture->v, + picture->uv_stride, /*yuv_bit_depth=*/8, picture->width, + picture->height, SharpYuvGetConversionMatrix(kSharpYuvMatrixWebp)); + if (!ok) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return ok; +} + +//------------------------------------------------------------------------------ +// "Fast" regular RGB->YUV + +#define SUM4(ptr, step) LinearToGamma( \ + GammaToLinear((ptr)[0]) + \ + GammaToLinear((ptr)[(step)]) + \ + GammaToLinear((ptr)[rgb_stride]) + \ + GammaToLinear((ptr)[rgb_stride + (step)]), 0) \ + +#define SUM2(ptr) \ + LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1) + +#define SUM2ALPHA(ptr) ((ptr)[0] + (ptr)[rgb_stride]) +#define SUM4ALPHA(ptr) (SUM2ALPHA(ptr) + SUM2ALPHA((ptr) + 4)) + +#if defined(USE_INVERSE_ALPHA_TABLE) + +static const int kAlphaFix = 19; +// Following table is (1 << kAlphaFix) / a. The (v * kInvAlpha[a]) >> kAlphaFix +// formula is then equal to v / a in most (99.6%) cases. Note that this table +// and constant are adjusted very tightly to fit 32b arithmetic. +// In particular, they use the fact that the operands for 'v / a' are actually +// derived as v = (a0.p0 + a1.p1 + a2.p2 + a3.p3) and a = a0 + a1 + a2 + a3 +// with ai in [0..255] and pi in [0..1<> (kAlphaFix - 2)) + +#else + +#define DIVIDE_BY_ALPHA(sum, a) (4 * (sum) / (a)) + +#endif // USE_INVERSE_ALPHA_TABLE + +static WEBP_INLINE int LinearToGammaWeighted(const uint8_t* src, + const uint8_t* a_ptr, + uint32_t total_a, int step, + int rgb_stride) { + const uint32_t sum = + a_ptr[0] * GammaToLinear(src[0]) + + a_ptr[step] * GammaToLinear(src[step]) + + a_ptr[rgb_stride] * GammaToLinear(src[rgb_stride]) + + a_ptr[rgb_stride + step] * GammaToLinear(src[rgb_stride + step]); + assert(total_a > 0 && total_a <= 4 * 0xff); +#if defined(USE_INVERSE_ALPHA_TABLE) + assert((uint64_t)sum * kInvAlpha[total_a] < ((uint64_t)1 << 32)); +#endif + return LinearToGamma(DIVIDE_BY_ALPHA(sum, total_a), 0); +} + +static WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + int step, + uint8_t* const dst_y, + int width, + VP8Random* const rg) { + int i, j; + for (i = 0, j = 0; i < width; i += 1, j += step) { + dst_y[i] = RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], rg); + } +} + +static WEBP_INLINE void AccumulateRGBA(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + const uint8_t* const a_ptr, + int rgb_stride, + uint16_t* dst, int width) { + int i, j; + // we loop over 2x2 blocks and produce one R/G/B/A value for each. + for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * 4, dst += 4) { + const uint32_t a = SUM4ALPHA(a_ptr + j); + int r, g, b; + if (a == 4 * 0xff || a == 0) { + r = SUM4(r_ptr + j, 4); + g = SUM4(g_ptr + j, 4); + b = SUM4(b_ptr + j, 4); + } else { + r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 4, rgb_stride); + g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 4, rgb_stride); + b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 4, rgb_stride); + } + dst[0] = r; + dst[1] = g; + dst[2] = b; + dst[3] = a; + } + if (width & 1) { + const uint32_t a = 2u * SUM2ALPHA(a_ptr + j); + int r, g, b; + if (a == 4 * 0xff || a == 0) { + r = SUM2(r_ptr + j); + g = SUM2(g_ptr + j); + b = SUM2(b_ptr + j); + } else { + r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 0, rgb_stride); + g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 0, rgb_stride); + b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 0, rgb_stride); + } + dst[0] = r; + dst[1] = g; + dst[2] = b; + dst[3] = a; + } +} + +static WEBP_INLINE void AccumulateRGB(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + int step, int rgb_stride, + uint16_t* dst, int width) { + int i, j; + for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * step, dst += 4) { + dst[0] = SUM4(r_ptr + j, step); + dst[1] = SUM4(g_ptr + j, step); + dst[2] = SUM4(b_ptr + j, step); + // MemorySanitizer may raise false positives with data that passes through + // RGBA32PackedToPlanar_16b_SSE41() due to incorrect modeling of shuffles. + // See https://crbug.com/webp/573. +#ifdef WEBP_MSAN + dst[3] = 0; +#endif + } + if (width & 1) { + dst[0] = SUM2(r_ptr + j); + dst[1] = SUM2(g_ptr + j); + dst[2] = SUM2(b_ptr + j); +#ifdef WEBP_MSAN + dst[3] = 0; +#endif + } +} + +static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb, + uint8_t* const dst_u, + uint8_t* const dst_v, + int width, + VP8Random* const rg) { + int i; + for (i = 0; i < width; i += 1, rgb += 4) { + const int r = rgb[0], g = rgb[1], b = rgb[2]; + dst_u[i] = RGBToU(r, g, b, rg); + dst_v[i] = RGBToV(r, g, b, rg); + } +} + +extern void SharpYuvInit(VP8CPUInfo cpu_info_func); + +static int ImportYUVAFromRGBA(const uint8_t* r_ptr, + const uint8_t* g_ptr, + const uint8_t* b_ptr, + const uint8_t* a_ptr, + int step, // bytes per pixel + int rgb_stride, // bytes per scanline + float dithering, + int use_iterative_conversion, + WebPPicture* const picture) { + int y; + const int width = picture->width; + const int height = picture->height; + const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride); + const int is_rgb = (r_ptr < b_ptr); // otherwise it's bgr + + picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420; + picture->use_argb = 0; + + // disable smart conversion if source is too small (overkill). + if (width < kMinDimensionIterativeConversion || + height < kMinDimensionIterativeConversion) { + use_iterative_conversion = 0; + } + + if (!WebPPictureAllocYUVA(picture)) { + return 0; + } + if (has_alpha) { + assert(step == 4); +#if defined(USE_GAMMA_COMPRESSION) && defined(USE_INVERSE_ALPHA_TABLE) + assert(kAlphaFix + GAMMA_FIX <= 31); +#endif + } + + if (use_iterative_conversion) { + SharpYuvInit(VP8GetCPUInfo); + if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) { + return 0; + } + if (has_alpha) { + WebPExtractAlpha(a_ptr, rgb_stride, width, height, + picture->a, picture->a_stride); + } + } else { + const int uv_width = (width + 1) >> 1; + int use_dsp = (step == 3); // use special function in this case + // temporary storage for accumulated R/G/B values during conversion to U/V + uint16_t* const tmp_rgb = + (uint16_t*)WebPSafeMalloc(4 * uv_width, sizeof(*tmp_rgb)); + uint8_t* dst_y = picture->y; + uint8_t* dst_u = picture->u; + uint8_t* dst_v = picture->v; + uint8_t* dst_a = picture->a; + + VP8Random base_rg; + VP8Random* rg = NULL; + if (dithering > 0.) { + VP8InitRandom(&base_rg, dithering); + rg = &base_rg; + use_dsp = 0; // can't use dsp in this case + } + WebPInitConvertARGBToYUV(); + InitGammaTables(); + + if (tmp_rgb == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + // Downsample Y/U/V planes, two rows at a time + for (y = 0; y < (height >> 1); ++y) { + int rows_have_alpha = has_alpha; + if (use_dsp) { + if (is_rgb) { + WebPConvertRGB24ToY(r_ptr, dst_y, width); + WebPConvertRGB24ToY(r_ptr + rgb_stride, + dst_y + picture->y_stride, width); + } else { + WebPConvertBGR24ToY(b_ptr, dst_y, width); + WebPConvertBGR24ToY(b_ptr + rgb_stride, + dst_y + picture->y_stride, width); + } + } else { + ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg); + ConvertRowToY(r_ptr + rgb_stride, + g_ptr + rgb_stride, + b_ptr + rgb_stride, step, + dst_y + picture->y_stride, width, rg); + } + dst_y += 2 * picture->y_stride; + if (has_alpha) { + rows_have_alpha &= !WebPExtractAlpha(a_ptr, rgb_stride, width, 2, + dst_a, picture->a_stride); + dst_a += 2 * picture->a_stride; + } + // Collect averaged R/G/B(/A) + if (!rows_have_alpha) { + AccumulateRGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, tmp_rgb, width); + } else { + AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, rgb_stride, tmp_rgb, width); + } + // Convert to U/V + if (rg == NULL) { + WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); + } else { + ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); + } + dst_u += picture->uv_stride; + dst_v += picture->uv_stride; + r_ptr += 2 * rgb_stride; + b_ptr += 2 * rgb_stride; + g_ptr += 2 * rgb_stride; + if (has_alpha) a_ptr += 2 * rgb_stride; + } + if (height & 1) { // extra last row + int row_has_alpha = has_alpha; + if (use_dsp) { + if (r_ptr < b_ptr) { + WebPConvertRGB24ToY(r_ptr, dst_y, width); + } else { + WebPConvertBGR24ToY(b_ptr, dst_y, width); + } + } else { + ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg); + } + if (row_has_alpha) { + row_has_alpha &= !WebPExtractAlpha(a_ptr, 0, width, 1, dst_a, 0); + } + // Collect averaged R/G/B(/A) + if (!row_has_alpha) { + // Collect averaged R/G/B + AccumulateRGB(r_ptr, g_ptr, b_ptr, step, /* rgb_stride = */ 0, + tmp_rgb, width); + } else { + AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, /* rgb_stride = */ 0, + tmp_rgb, width); + } + if (rg == NULL) { + WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); + } else { + ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); + } + } + WebPSafeFree(tmp_rgb); + } + return 1; +} + +#undef SUM4 +#undef SUM2 +#undef SUM4ALPHA +#undef SUM2ALPHA + +//------------------------------------------------------------------------------ +// call for ARGB->YUVA conversion + +static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace, + float dithering, int use_iterative_conversion) { + if (picture == NULL) return 0; + if (picture->argb == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); + } else if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } else { + const uint8_t* const argb = (const uint8_t*)picture->argb; + const uint8_t* const a = argb + CHANNEL_OFFSET(0); + const uint8_t* const r = argb + CHANNEL_OFFSET(1); + const uint8_t* const g = argb + CHANNEL_OFFSET(2); + const uint8_t* const b = argb + CHANNEL_OFFSET(3); + + picture->colorspace = WEBP_YUV420; + return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, + dithering, use_iterative_conversion, picture); + } +} + +int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace, + float dithering) { + return PictureARGBToYUVA(picture, colorspace, dithering, 0); +} + +int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) { + return PictureARGBToYUVA(picture, colorspace, 0.f, 0); +} + +int WebPPictureSharpARGBToYUVA(WebPPicture* picture) { + return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1); +} +// for backward compatibility +int WebPPictureSmartARGBToYUVA(WebPPicture* picture) { + return WebPPictureSharpARGBToYUVA(picture); +} + +//------------------------------------------------------------------------------ +// call for YUVA -> ARGB conversion + +int WebPPictureYUVAToARGB(WebPPicture* picture) { + if (picture == NULL) return 0; + if (picture->y == NULL || picture->u == NULL || picture->v == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); + } + if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); + } + if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + // Allocate a new argb buffer (discarding the previous one). + if (!WebPPictureAllocARGB(picture)) return 0; + picture->use_argb = 1; + + // Convert + { + int y; + const int width = picture->width; + const int height = picture->height; + const int argb_stride = 4 * picture->argb_stride; + uint8_t* dst = (uint8_t*)picture->argb; + const uint8_t* cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y; + WebPUpsampleLinePairFunc upsample = + WebPGetLinePairConverter(ALPHA_OFFSET > 0); + + // First row, with replicated top samples. + upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); + cur_y += picture->y_stride; + dst += argb_stride; + // Center rows. + for (y = 1; y + 1 < height; y += 2) { + const uint8_t* const top_u = cur_u; + const uint8_t* const top_v = cur_v; + cur_u += picture->uv_stride; + cur_v += picture->uv_stride; + upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v, + dst, dst + argb_stride, width); + cur_y += 2 * picture->y_stride; + dst += 2 * argb_stride; + } + // Last row (if needed), with replicated bottom samples. + if (height > 1 && !(height & 1)) { + upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); + } + // Insert alpha values if needed, in replacement for the default 0xff ones. + if (picture->colorspace & WEBP_CSP_ALPHA_BIT) { + for (y = 0; y < height; ++y) { + uint32_t* const argb_dst = picture->argb + y * picture->argb_stride; + const uint8_t* const src = picture->a + y * picture->a_stride; + int x; + for (x = 0; x < width; ++x) { + argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24); + } + } + } + } + return 1; +} + +//------------------------------------------------------------------------------ +// automatic import / conversion + +static int Import(WebPPicture* const picture, + const uint8_t* rgb, int rgb_stride, + int step, int swap_rb, int import_alpha) { + int y; + // swap_rb -> b,g,r,a , !swap_rb -> r,g,b,a + const uint8_t* r_ptr = rgb + (swap_rb ? 2 : 0); + const uint8_t* g_ptr = rgb + 1; + const uint8_t* b_ptr = rgb + (swap_rb ? 0 : 2); + const int width = picture->width; + const int height = picture->height; + + if (abs(rgb_stride) < (import_alpha ? 4 : 3) * width) return 0; + + if (!picture->use_argb) { + const uint8_t* a_ptr = import_alpha ? rgb + 3 : NULL; + return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, + 0.f /* no dithering */, 0, picture); + } + if (!WebPPictureAlloc(picture)) return 0; + + VP8LDspInit(); + WebPInitAlphaProcessing(); + + if (import_alpha) { + // dst[] byte order is {a,r,g,b} for big-endian, {b,g,r,a} for little endian + uint32_t* dst = picture->argb; + const int do_copy = (ALPHA_OFFSET == 3) && swap_rb; + assert(step == 4); + if (do_copy) { + for (y = 0; y < height; ++y) { + memcpy(dst, rgb, width * 4); + rgb += rgb_stride; + dst += picture->argb_stride; + } + } else { + for (y = 0; y < height; ++y) { +#ifdef WORDS_BIGENDIAN + // BGRA or RGBA input order. + const uint8_t* a_ptr = rgb + 3; + WebPPackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst); + r_ptr += rgb_stride; + g_ptr += rgb_stride; + b_ptr += rgb_stride; +#else + // RGBA input order. Need to swap R and B. + VP8LConvertBGRAToRGBA((const uint32_t*)rgb, width, (uint8_t*)dst); +#endif + rgb += rgb_stride; + dst += picture->argb_stride; + } + } + } else { + uint32_t* dst = picture->argb; + assert(step >= 3); + for (y = 0; y < height; ++y) { + WebPPackRGB(r_ptr, g_ptr, b_ptr, width, step, dst); + r_ptr += rgb_stride; + g_ptr += rgb_stride; + b_ptr += rgb_stride; + dst += picture->argb_stride; + } + } + return 1; +} + +// Public API + +#if !defined(WEBP_REDUCE_CSP) + +int WebPPictureImportBGR(WebPPicture* picture, + const uint8_t* bgr, int bgr_stride) { + return (picture != NULL && bgr != NULL) + ? Import(picture, bgr, bgr_stride, 3, 1, 0) + : 0; +} + +int WebPPictureImportBGRA(WebPPicture* picture, + const uint8_t* bgra, int bgra_stride) { + return (picture != NULL && bgra != NULL) + ? Import(picture, bgra, bgra_stride, 4, 1, 1) + : 0; +} + + +int WebPPictureImportBGRX(WebPPicture* picture, + const uint8_t* bgrx, int bgrx_stride) { + return (picture != NULL && bgrx != NULL) + ? Import(picture, bgrx, bgrx_stride, 4, 1, 0) + : 0; +} + +#endif // WEBP_REDUCE_CSP + +int WebPPictureImportRGB(WebPPicture* picture, + const uint8_t* rgb, int rgb_stride) { + return (picture != NULL && rgb != NULL) + ? Import(picture, rgb, rgb_stride, 3, 0, 0) + : 0; +} + +int WebPPictureImportRGBA(WebPPicture* picture, + const uint8_t* rgba, int rgba_stride) { + return (picture != NULL && rgba != NULL) + ? Import(picture, rgba, rgba_stride, 4, 0, 1) + : 0; +} + +int WebPPictureImportRGBX(WebPPicture* picture, + const uint8_t* rgbx, int rgbx_stride) { + return (picture != NULL && rgbx != NULL) + ? Import(picture, rgbx, rgbx_stride, 4, 0, 0) + : 0; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/enc/picture_enc.c b/libraries/webp/src/enc/picture_enc.c new file mode 100644 index 0000000000..5a2703541f --- /dev/null +++ b/libraries/webp/src/enc/picture_enc.c @@ -0,0 +1,304 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture class basis +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// WebPPicture +//------------------------------------------------------------------------------ + +static int DummyWriter(const uint8_t* data, size_t data_size, + const WebPPicture* const picture) { + // The following are to prevent 'unused variable' error message. + (void)data; + (void)data_size; + (void)picture; + return 1; +} + +int WebPPictureInitInternal(WebPPicture* picture, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { + return 0; // caller/system version mismatch! + } + if (picture != NULL) { + memset(picture, 0, sizeof(*picture)); + picture->writer = DummyWriter; + WebPEncodingSetError(picture, VP8_ENC_OK); + } + return 1; +} + +//------------------------------------------------------------------------------ + +int WebPValidatePicture(const WebPPicture* const picture) { + if (picture == NULL) return 0; + if (picture->width <= 0 || picture->height <= 0) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + if (picture->width <= 0 || picture->width / 4 > INT_MAX / 4 || + picture->height <= 0 || picture->height / 4 > INT_MAX / 4) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + if (picture->colorspace != WEBP_YUV420 && + picture->colorspace != WEBP_YUV420A) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + return 1; +} + +static void WebPPictureResetBufferARGB(WebPPicture* const picture) { + picture->memory_argb_ = NULL; + picture->argb = NULL; + picture->argb_stride = 0; +} + +static void WebPPictureResetBufferYUVA(WebPPicture* const picture) { + picture->memory_ = NULL; + picture->y = picture->u = picture->v = picture->a = NULL; + picture->y_stride = picture->uv_stride = 0; + picture->a_stride = 0; +} + +void WebPPictureResetBuffers(WebPPicture* const picture) { + WebPPictureResetBufferARGB(picture); + WebPPictureResetBufferYUVA(picture); +} + +int WebPPictureAllocARGB(WebPPicture* const picture) { + void* memory; + const int width = picture->width; + const int height = picture->height; + const uint64_t argb_size = (uint64_t)width * height; + + if (!WebPValidatePicture(picture)) return 0; + + WebPSafeFree(picture->memory_argb_); + WebPPictureResetBufferARGB(picture); + + // allocate a new buffer. + memory = WebPSafeMalloc(argb_size + WEBP_ALIGN_CST, sizeof(*picture->argb)); + if (memory == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + picture->memory_argb_ = memory; + picture->argb = (uint32_t*)WEBP_ALIGN(memory); + picture->argb_stride = width; + return 1; +} + +int WebPPictureAllocYUVA(WebPPicture* const picture) { + const int has_alpha = (int)picture->colorspace & WEBP_CSP_ALPHA_BIT; + const int width = picture->width; + const int height = picture->height; + const int y_stride = width; + const int uv_width = (int)(((int64_t)width + 1) >> 1); + const int uv_height = (int)(((int64_t)height + 1) >> 1); + const int uv_stride = uv_width; + int a_width, a_stride; + uint64_t y_size, uv_size, a_size, total_size; + uint8_t* mem; + + if (!WebPValidatePicture(picture)) return 0; + + WebPSafeFree(picture->memory_); + WebPPictureResetBufferYUVA(picture); + + // alpha + a_width = has_alpha ? width : 0; + a_stride = a_width; + y_size = (uint64_t)y_stride * height; + uv_size = (uint64_t)uv_stride * uv_height; + a_size = (uint64_t)a_stride * height; + + total_size = y_size + a_size + 2 * uv_size; + + // Security and validation checks + if (width <= 0 || height <= 0 || // luma/alpha param error + uv_width <= 0 || uv_height <= 0) { // u/v param error + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + // allocate a new buffer. + mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem)); + if (mem == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + // From now on, we're in the clear, we can no longer fail... + picture->memory_ = (void*)mem; + picture->y_stride = y_stride; + picture->uv_stride = uv_stride; + picture->a_stride = a_stride; + + // TODO(skal): we could align the y/u/v planes and adjust stride. + picture->y = mem; + mem += y_size; + + picture->u = mem; + mem += uv_size; + picture->v = mem; + mem += uv_size; + + if (a_size > 0) { + picture->a = mem; + mem += a_size; + } + (void)mem; // makes the static analyzer happy + return 1; +} + +int WebPPictureAlloc(WebPPicture* picture) { + if (picture != NULL) { + WebPPictureFree(picture); // erase previous buffer + + if (!picture->use_argb) { + return WebPPictureAllocYUVA(picture); + } else { + return WebPPictureAllocARGB(picture); + } + } + return 1; +} + +void WebPPictureFree(WebPPicture* picture) { + if (picture != NULL) { + WebPSafeFree(picture->memory_); + WebPSafeFree(picture->memory_argb_); + WebPPictureResetBuffers(picture); + } +} + +//------------------------------------------------------------------------------ +// WebPMemoryWriter: Write-to-memory + +void WebPMemoryWriterInit(WebPMemoryWriter* writer) { + writer->mem = NULL; + writer->size = 0; + writer->max_size = 0; +} + +int WebPMemoryWrite(const uint8_t* data, size_t data_size, + const WebPPicture* picture) { + WebPMemoryWriter* const w = (WebPMemoryWriter*)picture->custom_ptr; + uint64_t next_size; + if (w == NULL) { + return 1; + } + next_size = (uint64_t)w->size + data_size; + if (next_size > w->max_size) { + uint8_t* new_mem; + uint64_t next_max_size = 2ULL * w->max_size; + if (next_max_size < next_size) next_max_size = next_size; + if (next_max_size < 8192ULL) next_max_size = 8192ULL; + new_mem = (uint8_t*)WebPSafeMalloc(next_max_size, 1); + if (new_mem == NULL) { + return 0; + } + if (w->size > 0) { + memcpy(new_mem, w->mem, w->size); + } + WebPSafeFree(w->mem); + w->mem = new_mem; + // down-cast is ok, thanks to WebPSafeMalloc + w->max_size = (size_t)next_max_size; + } + if (data_size > 0) { + memcpy(w->mem + w->size, data, data_size); + w->size += data_size; + } + return 1; +} + +void WebPMemoryWriterClear(WebPMemoryWriter* writer) { + if (writer != NULL) { + WebPSafeFree(writer->mem); + writer->mem = NULL; + writer->size = 0; + writer->max_size = 0; + } +} + +//------------------------------------------------------------------------------ +// Simplest high-level calls: + +typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int); + +static size_t Encode(const uint8_t* rgba, int width, int height, int stride, + Importer import, float quality_factor, int lossless, + uint8_t** output) { + WebPPicture pic; + WebPConfig config; + WebPMemoryWriter wrt; + int ok; + + if (output == NULL) return 0; + + if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality_factor) || + !WebPPictureInit(&pic)) { + return 0; // shouldn't happen, except if system installation is broken + } + + config.lossless = !!lossless; + pic.use_argb = !!lossless; + pic.width = width; + pic.height = height; + pic.writer = WebPMemoryWrite; + pic.custom_ptr = &wrt; + WebPMemoryWriterInit(&wrt); + + ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic); + WebPPictureFree(&pic); + if (!ok) { + WebPMemoryWriterClear(&wrt); + *output = NULL; + return 0; + } + *output = wrt.mem; + return wrt.size; +} + +#define ENCODE_FUNC(NAME, IMPORTER) \ +size_t NAME(const uint8_t* in, int w, int h, int bps, float q, \ + uint8_t** out) { \ + return Encode(in, w, h, bps, IMPORTER, q, 0, out); \ +} + +ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB) +ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA) +#if !defined(WEBP_REDUCE_CSP) +ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR) +ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA) +#endif // WEBP_REDUCE_CSP + +#undef ENCODE_FUNC + +#define LOSSLESS_DEFAULT_QUALITY 70. +#define LOSSLESS_ENCODE_FUNC(NAME, IMPORTER) \ +size_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) { \ + return Encode(in, w, h, bps, IMPORTER, LOSSLESS_DEFAULT_QUALITY, 1, out); \ +} + +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB) +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA) +#if !defined(WEBP_REDUCE_CSP) +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR) +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA) +#endif // WEBP_REDUCE_CSP + +#undef LOSSLESS_ENCODE_FUNC + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/enc/picture_psnr_enc.c b/libraries/webp/src/enc/picture_psnr_enc.c new file mode 100644 index 0000000000..70d57322ad --- /dev/null +++ b/libraries/webp/src/enc/picture_psnr_enc.c @@ -0,0 +1,258 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture tools for measuring distortion +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "include/webp/encode.h" + +#if !(defined(WEBP_DISABLE_STATS) || defined(WEBP_REDUCE_SIZE)) + +#include +#include + +#include "src/dsp/dsp.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +typedef double (*AccumulateFunc)(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h); + +//------------------------------------------------------------------------------ +// local-min distortion +// +// For every pixel in the *reference* picture, we search for the local best +// match in the compressed image. This is not a symmetrical measure. + +#define RADIUS 2 // search radius. Shouldn't be too large. + +static double AccumulateLSIM(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h) { + int x, y; + double total_sse = 0.; + for (y = 0; y < h; ++y) { + const int y_0 = (y - RADIUS < 0) ? 0 : y - RADIUS; + const int y_1 = (y + RADIUS + 1 >= h) ? h : y + RADIUS + 1; + for (x = 0; x < w; ++x) { + const int x_0 = (x - RADIUS < 0) ? 0 : x - RADIUS; + const int x_1 = (x + RADIUS + 1 >= w) ? w : x + RADIUS + 1; + double best_sse = 255. * 255.; + const double value = (double)ref[y * ref_stride + x]; + int i, j; + for (j = y_0; j < y_1; ++j) { + const uint8_t* const s = src + j * src_stride; + for (i = x_0; i < x_1; ++i) { + const double diff = s[i] - value; + const double sse = diff * diff; + if (sse < best_sse) best_sse = sse; + } + } + total_sse += best_sse; + } + } + return total_sse; +} +#undef RADIUS + +static double AccumulateSSE(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h) { + int y; + double total_sse = 0.; + for (y = 0; y < h; ++y) { + total_sse += VP8AccumulateSSE(src, ref, w); + src += src_stride; + ref += ref_stride; + } + return total_sse; +} + +//------------------------------------------------------------------------------ + +static double AccumulateSSIM(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h) { + const int w0 = (w < VP8_SSIM_KERNEL) ? w : VP8_SSIM_KERNEL; + const int w1 = w - VP8_SSIM_KERNEL - 1; + const int h0 = (h < VP8_SSIM_KERNEL) ? h : VP8_SSIM_KERNEL; + const int h1 = h - VP8_SSIM_KERNEL - 1; + int x, y; + double sum = 0.; + for (y = 0; y < h0; ++y) { + for (x = 0; x < w; ++x) { + sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h); + } + } + for (; y < h1; ++y) { + for (x = 0; x < w0; ++x) { + sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h); + } + for (; x < w1; ++x) { + const int off1 = x - VP8_SSIM_KERNEL + (y - VP8_SSIM_KERNEL) * src_stride; + const int off2 = x - VP8_SSIM_KERNEL + (y - VP8_SSIM_KERNEL) * ref_stride; + sum += VP8SSIMGet(src + off1, src_stride, ref + off2, ref_stride); + } + for (; x < w; ++x) { + sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h); + } + } + for (; y < h; ++y) { + for (x = 0; x < w; ++x) { + sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h); + } + } + return sum; +} + +//------------------------------------------------------------------------------ +// Distortion + +// Max value returned in case of exact similarity. +static const double kMinDistortion_dB = 99.; + +static double GetPSNR(double v, double size) { + return (v > 0. && size > 0.) ? -4.3429448 * log(v / (size * 255 * 255.)) + : kMinDistortion_dB; +} + +static double GetLogSSIM(double v, double size) { + v = (size > 0.) ? v / size : 1.; + return (v < 1.) ? -10.0 * log10(1. - v) : kMinDistortion_dB; +} + +int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, + int width, int height, size_t x_step, + int type, float* distortion, float* result) { + uint8_t* allocated = NULL; + const AccumulateFunc metric = (type == 0) ? AccumulateSSE : + (type == 1) ? AccumulateSSIM : + AccumulateLSIM; + if (src == NULL || ref == NULL || + src_stride < x_step * width || ref_stride < x_step * width || + result == NULL || distortion == NULL) { + return 0; + } + + VP8SSIMDspInit(); + if (x_step != 1) { // extract a packed plane if needed + int x, y; + uint8_t* tmp1; + uint8_t* tmp2; + allocated = + (uint8_t*)WebPSafeMalloc(2ULL * width * height, sizeof(*allocated)); + if (allocated == NULL) return 0; + tmp1 = allocated; + tmp2 = tmp1 + (size_t)width * height; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + tmp1[x + y * width] = src[x * x_step + y * src_stride]; + tmp2[x + y * width] = ref[x * x_step + y * ref_stride]; + } + } + src = tmp1; + ref = tmp2; + } + *distortion = (float)metric(src, width, ref, width, width, height); + WebPSafeFree(allocated); + + *result = (type == 1) ? (float)GetLogSSIM(*distortion, (double)width * height) + : (float)GetPSNR(*distortion, (double)width * height); + return 1; +} + +#ifdef WORDS_BIGENDIAN +#define BLUE_OFFSET 3 // uint32_t 0x000000ff is 0x00,00,00,ff in memory +#else +#define BLUE_OFFSET 0 // uint32_t 0x000000ff is 0xff,00,00,00 in memory +#endif + +int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, + int type, float results[5]) { + int w, h, c; + int ok = 0; + WebPPicture p0, p1; + double total_size = 0., total_distortion = 0.; + if (src == NULL || ref == NULL || + src->width != ref->width || src->height != ref->height || + results == NULL) { + return 0; + } + + VP8SSIMDspInit(); + if (!WebPPictureInit(&p0) || !WebPPictureInit(&p1)) return 0; + w = src->width; + h = src->height; + if (!WebPPictureView(src, 0, 0, w, h, &p0)) goto Error; + if (!WebPPictureView(ref, 0, 0, w, h, &p1)) goto Error; + + // We always measure distortion in ARGB space. + if (p0.use_argb == 0 && !WebPPictureYUVAToARGB(&p0)) goto Error; + if (p1.use_argb == 0 && !WebPPictureYUVAToARGB(&p1)) goto Error; + for (c = 0; c < 4; ++c) { + float distortion; + const size_t stride0 = 4 * (size_t)p0.argb_stride; + const size_t stride1 = 4 * (size_t)p1.argb_stride; + // results are reported as BGRA + const int offset = c ^ BLUE_OFFSET; + if (!WebPPlaneDistortion((const uint8_t*)p0.argb + offset, stride0, + (const uint8_t*)p1.argb + offset, stride1, + w, h, 4, type, &distortion, results + c)) { + goto Error; + } + total_distortion += distortion; + total_size += w * h; + } + + results[4] = (type == 1) ? (float)GetLogSSIM(total_distortion, total_size) + : (float)GetPSNR(total_distortion, total_size); + ok = 1; + + Error: + WebPPictureFree(&p0); + WebPPictureFree(&p1); + return ok; +} + +#undef BLUE_OFFSET + +#else // defined(WEBP_DISABLE_STATS) +int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, + int width, int height, size_t x_step, + int type, float* distortion, float* result) { + (void)src; + (void)src_stride; + (void)ref; + (void)ref_stride; + (void)width; + (void)height; + (void)x_step; + (void)type; + if (distortion == NULL || result == NULL) return 0; + *distortion = 0.f; + *result = 0.f; + return 1; +} + +int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, + int type, float results[5]) { + int i; + (void)src; + (void)ref; + (void)type; + if (results == NULL) return 0; + for (i = 0; i < 5; ++i) results[i] = 0.f; + return 1; +} + +#endif // !defined(WEBP_DISABLE_STATS) diff --git a/libraries/webp/src/enc/picture_rescale_enc.c b/libraries/webp/src/enc/picture_rescale_enc.c new file mode 100644 index 0000000000..b199ea73bb --- /dev/null +++ b/libraries/webp/src/enc/picture_rescale_enc.c @@ -0,0 +1,304 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture tools: copy, crop, rescaling and view. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "include/webp/encode.h" + +#include +#include + +#include "src/enc/vp8i_enc.h" + +#if !defined(WEBP_REDUCE_SIZE) +#include "src/utils/rescaler_utils.h" +#include "src/utils/utils.h" +#endif // !defined(WEBP_REDUCE_SIZE) + +#define HALVE(x) (((x) + 1) >> 1) + +// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them +// into 'dst'. Mark 'dst' as not owning any memory. +static void PictureGrabSpecs(const WebPPicture* const src, + WebPPicture* const dst) { + assert(src != NULL && dst != NULL); + *dst = *src; + WebPPictureResetBuffers(dst); +} + +//------------------------------------------------------------------------------ + +// Adjust top-left corner to chroma sample position. +static void SnapTopLeftPosition(const WebPPicture* const pic, + int* const left, int* const top) { + if (!pic->use_argb) { + *left &= ~1; + *top &= ~1; + } +} + +// Adjust top-left corner and verify that the sub-rectangle is valid. +static int AdjustAndCheckRectangle(const WebPPicture* const pic, + int* const left, int* const top, + int width, int height) { + SnapTopLeftPosition(pic, left, top); + if ((*left) < 0 || (*top) < 0) return 0; + if (width <= 0 || height <= 0) return 0; + if ((*left) + width > pic->width) return 0; + if ((*top) + height > pic->height) return 0; + return 1; +} + +#if !defined(WEBP_REDUCE_SIZE) +int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) { + if (src == NULL || dst == NULL) return 0; + if (src == dst) return 1; + + PictureGrabSpecs(src, dst); + if (!WebPPictureAlloc(dst)) return 0; + + if (!src->use_argb) { + WebPCopyPlane(src->y, src->y_stride, + dst->y, dst->y_stride, dst->width, dst->height); + WebPCopyPlane(src->u, src->uv_stride, dst->u, dst->uv_stride, + HALVE(dst->width), HALVE(dst->height)); + WebPCopyPlane(src->v, src->uv_stride, dst->v, dst->uv_stride, + HALVE(dst->width), HALVE(dst->height)); + if (dst->a != NULL) { + WebPCopyPlane(src->a, src->a_stride, + dst->a, dst->a_stride, dst->width, dst->height); + } + } else { + WebPCopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride, + (uint8_t*)dst->argb, 4 * dst->argb_stride, + 4 * dst->width, dst->height); + } + return 1; +} +#endif // !defined(WEBP_REDUCE_SIZE) + +int WebPPictureIsView(const WebPPicture* picture) { + if (picture == NULL) return 0; + if (picture->use_argb) { + return (picture->memory_argb_ == NULL); + } + return (picture->memory_ == NULL); +} + +int WebPPictureView(const WebPPicture* src, + int left, int top, int width, int height, + WebPPicture* dst) { + if (src == NULL || dst == NULL) return 0; + + // verify rectangle position. + if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0; + + if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'. + PictureGrabSpecs(src, dst); + } + dst->width = width; + dst->height = height; + if (!src->use_argb) { + dst->y = src->y + top * src->y_stride + left; + dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1); + dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1); + dst->y_stride = src->y_stride; + dst->uv_stride = src->uv_stride; + if (src->a != NULL) { + dst->a = src->a + top * src->a_stride + left; + dst->a_stride = src->a_stride; + } + } else { + dst->argb = src->argb + top * src->argb_stride + left; + dst->argb_stride = src->argb_stride; + } + return 1; +} + +#if !defined(WEBP_REDUCE_SIZE) +//------------------------------------------------------------------------------ +// Picture cropping + +int WebPPictureCrop(WebPPicture* pic, + int left, int top, int width, int height) { + WebPPicture tmp; + + if (pic == NULL) return 0; + if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0; + + PictureGrabSpecs(pic, &tmp); + tmp.width = width; + tmp.height = height; + if (!WebPPictureAlloc(&tmp)) { + return WebPEncodingSetError(pic, tmp.error_code); + } + + if (!pic->use_argb) { + const int y_offset = top * pic->y_stride + left; + const int uv_offset = (top / 2) * pic->uv_stride + left / 2; + WebPCopyPlane(pic->y + y_offset, pic->y_stride, + tmp.y, tmp.y_stride, width, height); + WebPCopyPlane(pic->u + uv_offset, pic->uv_stride, + tmp.u, tmp.uv_stride, HALVE(width), HALVE(height)); + WebPCopyPlane(pic->v + uv_offset, pic->uv_stride, + tmp.v, tmp.uv_stride, HALVE(width), HALVE(height)); + + if (tmp.a != NULL) { + const int a_offset = top * pic->a_stride + left; + WebPCopyPlane(pic->a + a_offset, pic->a_stride, + tmp.a, tmp.a_stride, width, height); + } + } else { + const uint8_t* const src = + (const uint8_t*)(pic->argb + top * pic->argb_stride + left); + WebPCopyPlane(src, pic->argb_stride * 4, (uint8_t*)tmp.argb, + tmp.argb_stride * 4, width * 4, height); + } + WebPPictureFree(pic); + *pic = tmp; + return 1; +} + +//------------------------------------------------------------------------------ +// Simple picture rescaler + +static int RescalePlane(const uint8_t* src, + int src_width, int src_height, int src_stride, + uint8_t* dst, + int dst_width, int dst_height, int dst_stride, + rescaler_t* const work, + int num_channels) { + WebPRescaler rescaler; + int y = 0; + if (!WebPRescalerInit(&rescaler, src_width, src_height, + dst, dst_width, dst_height, dst_stride, + num_channels, work)) { + return 0; + } + while (y < src_height) { + y += WebPRescalerImport(&rescaler, src_height - y, + src + y * src_stride, src_stride); + WebPRescalerExport(&rescaler); + } + return 1; +} + +static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) { + assert(pic->argb != NULL); + WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb), + pic->width, pic->height, inverse); +} + +static void AlphaMultiplyY(WebPPicture* const pic, int inverse) { + if (pic->a != NULL) { + WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride, + pic->width, pic->height, inverse); + } +} + +int WebPPictureRescale(WebPPicture* picture, int width, int height) { + WebPPicture tmp; + int prev_width, prev_height; + rescaler_t* work; + + if (picture == NULL) return 0; + prev_width = picture->width; + prev_height = picture->height; + if (!WebPRescalerGetScaledDimensions( + prev_width, prev_height, &width, &height)) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + + PictureGrabSpecs(picture, &tmp); + tmp.width = width; + tmp.height = height; + if (!WebPPictureAlloc(&tmp)) { + return WebPEncodingSetError(picture, tmp.error_code); + } + + if (!picture->use_argb) { + work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work)); + if (work == NULL) { + WebPPictureFree(&tmp); + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + // If present, we need to rescale alpha first (for AlphaMultiplyY). + if (picture->a != NULL) { + WebPInitAlphaProcessing(); + if (!RescalePlane(picture->a, prev_width, prev_height, picture->a_stride, + tmp.a, width, height, tmp.a_stride, work, 1)) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + } + + // We take transparency into account on the luma plane only. That's not + // totally exact blending, but still is a good approximation. + AlphaMultiplyY(picture, 0); + if (!RescalePlane(picture->y, prev_width, prev_height, picture->y_stride, + tmp.y, width, height, tmp.y_stride, work, 1) || + !RescalePlane(picture->u, HALVE(prev_width), HALVE(prev_height), + picture->uv_stride, tmp.u, HALVE(width), HALVE(height), + tmp.uv_stride, work, 1) || + !RescalePlane(picture->v, HALVE(prev_width), HALVE(prev_height), + picture->uv_stride, tmp.v, HALVE(width), HALVE(height), + tmp.uv_stride, work, 1)) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + AlphaMultiplyY(&tmp, 1); + } else { + work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work)); + if (work == NULL) { + WebPPictureFree(&tmp); + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + // In order to correctly interpolate colors, we need to apply the alpha + // weighting first (black-matting), scale the RGB values, and remove + // the premultiplication afterward (while preserving the alpha channel). + WebPInitAlphaProcessing(); + AlphaMultiplyARGB(picture, 0); + if (!RescalePlane((const uint8_t*)picture->argb, prev_width, prev_height, + picture->argb_stride * 4, (uint8_t*)tmp.argb, width, + height, tmp.argb_stride * 4, work, 4)) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + AlphaMultiplyARGB(&tmp, 1); + } + WebPPictureFree(picture); + WebPSafeFree(work); + *picture = tmp; + return 1; +} + +#else // defined(WEBP_REDUCE_SIZE) + +int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) { + (void)src; + (void)dst; + return 0; +} + +int WebPPictureCrop(WebPPicture* pic, + int left, int top, int width, int height) { + (void)pic; + (void)left; + (void)top; + (void)width; + (void)height; + return 0; +} + +int WebPPictureRescale(WebPPicture* pic, int width, int height) { + (void)pic; + (void)width; + (void)height; + return 0; +} +#endif // !defined(WEBP_REDUCE_SIZE) diff --git a/libraries/webp/src/enc/picture_tools_enc.c b/libraries/webp/src/enc/picture_tools_enc.c new file mode 100644 index 0000000000..147cc18608 --- /dev/null +++ b/libraries/webp/src/enc/picture_tools_enc.c @@ -0,0 +1,274 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture tools: alpha handling, etc. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/enc/vp8i_enc.h" +#include "src/dsp/yuv.h" + +//------------------------------------------------------------------------------ +// Helper: clean up fully transparent area to help compressibility. + +#define SIZE 8 +#define SIZE2 (SIZE / 2) +static int IsTransparentARGBArea(const uint32_t* ptr, int stride, int size) { + int y, x; + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) { + if (ptr[x] & 0xff000000u) { + return 0; + } + } + ptr += stride; + } + return 1; +} + +static void Flatten(uint8_t* ptr, int v, int stride, int size) { + int y; + for (y = 0; y < size; ++y) { + memset(ptr, v, size); + ptr += stride; + } +} + +static void FlattenARGB(uint32_t* ptr, uint32_t v, int stride, int size) { + int x, y; + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) ptr[x] = v; + ptr += stride; + } +} + +// Smoothen the luma components of transparent pixels. Return true if the whole +// block is transparent. +static int SmoothenBlock(const uint8_t* a_ptr, int a_stride, uint8_t* y_ptr, + int y_stride, int width, int height) { + int sum = 0, count = 0; + int x, y; + const uint8_t* alpha_ptr = a_ptr; + uint8_t* luma_ptr = y_ptr; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (alpha_ptr[x] != 0) { + ++count; + sum += luma_ptr[x]; + } + } + alpha_ptr += a_stride; + luma_ptr += y_stride; + } + if (count > 0 && count < width * height) { + const uint8_t avg_u8 = (uint8_t)(sum / count); + alpha_ptr = a_ptr; + luma_ptr = y_ptr; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (alpha_ptr[x] == 0) luma_ptr[x] = avg_u8; + } + alpha_ptr += a_stride; + luma_ptr += y_stride; + } + } + return (count == 0); +} + +void WebPReplaceTransparentPixels(WebPPicture* const pic, uint32_t color) { + if (pic != NULL && pic->use_argb) { + int y = pic->height; + uint32_t* argb = pic->argb; + color &= 0xffffffu; // force alpha=0 + WebPInitAlphaProcessing(); + while (y-- > 0) { + WebPAlphaReplace(argb, pic->width, color); + argb += pic->argb_stride; + } + } +} + +void WebPCleanupTransparentArea(WebPPicture* pic) { + int x, y, w, h; + if (pic == NULL) return; + w = pic->width / SIZE; + h = pic->height / SIZE; + + // note: we ignore the left-overs on right/bottom, except for SmoothenBlock(). + if (pic->use_argb) { + uint32_t argb_value = 0; + for (y = 0; y < h; ++y) { + int need_reset = 1; + for (x = 0; x < w; ++x) { + const int off = (y * pic->argb_stride + x) * SIZE; + if (IsTransparentARGBArea(pic->argb + off, pic->argb_stride, SIZE)) { + if (need_reset) { + argb_value = pic->argb[off]; + need_reset = 0; + } + FlattenARGB(pic->argb + off, argb_value, pic->argb_stride, SIZE); + } else { + need_reset = 1; + } + } + } + } else { + const int width = pic->width; + const int height = pic->height; + const int y_stride = pic->y_stride; + const int uv_stride = pic->uv_stride; + const int a_stride = pic->a_stride; + uint8_t* y_ptr = pic->y; + uint8_t* u_ptr = pic->u; + uint8_t* v_ptr = pic->v; + const uint8_t* a_ptr = pic->a; + int values[3] = { 0 }; + if (a_ptr == NULL || y_ptr == NULL || u_ptr == NULL || v_ptr == NULL) { + return; + } + for (y = 0; y + SIZE <= height; y += SIZE) { + int need_reset = 1; + for (x = 0; x + SIZE <= width; x += SIZE) { + if (SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + SIZE, SIZE)) { + if (need_reset) { + values[0] = y_ptr[x]; + values[1] = u_ptr[x >> 1]; + values[2] = v_ptr[x >> 1]; + need_reset = 0; + } + Flatten(y_ptr + x, values[0], y_stride, SIZE); + Flatten(u_ptr + (x >> 1), values[1], uv_stride, SIZE2); + Flatten(v_ptr + (x >> 1), values[2], uv_stride, SIZE2); + } else { + need_reset = 1; + } + } + if (x < width) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + width - x, SIZE); + } + a_ptr += SIZE * a_stride; + y_ptr += SIZE * y_stride; + u_ptr += SIZE2 * uv_stride; + v_ptr += SIZE2 * uv_stride; + } + if (y < height) { + const int sub_height = height - y; + for (x = 0; x + SIZE <= width; x += SIZE) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + SIZE, sub_height); + } + if (x < width) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + width - x, sub_height); + } + } + } +} + +#undef SIZE +#undef SIZE2 + +//------------------------------------------------------------------------------ +// Blend color and remove transparency info + +#define BLEND(V0, V1, ALPHA) \ + ((((V0) * (255 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 256) >> 16) +#define BLEND_10BIT(V0, V1, ALPHA) \ + ((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 1024) >> 18) + +static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) { + return (0xff000000u | (r << 16) | (g << 8) | b); +} + +void WebPBlendAlpha(WebPPicture* picture, uint32_t background_rgb) { + const int red = (background_rgb >> 16) & 0xff; + const int green = (background_rgb >> 8) & 0xff; + const int blue = (background_rgb >> 0) & 0xff; + int x, y; + if (picture == NULL) return; + if (!picture->use_argb) { + // omit last pixel during u/v loop + const int uv_width = (picture->width >> 1); + const int Y0 = VP8RGBToY(red, green, blue, YUV_HALF); + // VP8RGBToU/V expects the u/v values summed over four pixels + const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF); + const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF); + const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT; + uint8_t* y_ptr = picture->y; + uint8_t* u_ptr = picture->u; + uint8_t* v_ptr = picture->v; + uint8_t* a_ptr = picture->a; + if (!has_alpha || a_ptr == NULL) return; // nothing to do + for (y = 0; y < picture->height; ++y) { + // Luma blending + for (x = 0; x < picture->width; ++x) { + const uint8_t alpha = a_ptr[x]; + if (alpha < 0xff) { + y_ptr[x] = BLEND(Y0, y_ptr[x], alpha); + } + } + // Chroma blending every even line + if ((y & 1) == 0) { + uint8_t* const a_ptr2 = + (y + 1 == picture->height) ? a_ptr : a_ptr + picture->a_stride; + for (x = 0; x < uv_width; ++x) { + // Average four alpha values into a single blending weight. + // TODO(skal): might lead to visible contouring. Can we do better? + const uint32_t alpha = + a_ptr[2 * x + 0] + a_ptr[2 * x + 1] + + a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1]; + u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha); + v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha); + } + if (picture->width & 1) { // rightmost pixel + const uint32_t alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]); + u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha); + v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha); + } + } else { + u_ptr += picture->uv_stride; + v_ptr += picture->uv_stride; + } + memset(a_ptr, 0xff, picture->width); // reset alpha value to opaque + a_ptr += picture->a_stride; + y_ptr += picture->y_stride; + } + } else { + uint32_t* argb = picture->argb; + const uint32_t background = MakeARGB32(red, green, blue); + for (y = 0; y < picture->height; ++y) { + for (x = 0; x < picture->width; ++x) { + const int alpha = (argb[x] >> 24) & 0xff; + if (alpha != 0xff) { + if (alpha > 0) { + int r = (argb[x] >> 16) & 0xff; + int g = (argb[x] >> 8) & 0xff; + int b = (argb[x] >> 0) & 0xff; + r = BLEND(red, r, alpha); + g = BLEND(green, g, alpha); + b = BLEND(blue, b, alpha); + argb[x] = MakeARGB32(r, g, b); + } else { + argb[x] = background; + } + } + } + argb += picture->argb_stride; + } + } +} + +#undef BLEND +#undef BLEND_10BIT + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/enc/predictor_enc.c b/libraries/webp/src/enc/predictor_enc.c new file mode 100644 index 0000000000..b3d44b59d5 --- /dev/null +++ b/libraries/webp/src/enc/predictor_enc.c @@ -0,0 +1,792 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transform methods for lossless encoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) +// Vincent Rabaud (vrabaud@google.com) + +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/vp8li_enc.h" + +#define MAX_DIFF_COST (1e30f) + +static const float kSpatialPredictorBias = 15.f; +static const int kPredLowEffort = 11; +static const uint32_t kMaskAlpha = 0xff000000; + +// Mostly used to reduce code size + readability +static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; } + +//------------------------------------------------------------------------------ +// Methods to calculate Entropy (Shannon). + +static float PredictionCostSpatial(const int counts[256], int weight_0, + float exp_val) { + const int significant_symbols = 256 >> 4; + const float exp_decay_factor = 0.6f; + float bits = (float)weight_0 * counts[0]; + int i; + for (i = 1; i < significant_symbols; ++i) { + bits += exp_val * (counts[i] + counts[256 - i]); + exp_val *= exp_decay_factor; + } + return (float)(-0.1 * bits); +} + +static float PredictionCostSpatialHistogram(const int accumulated[4][256], + const int tile[4][256]) { + int i; + float retval = 0.f; + for (i = 0; i < 4; ++i) { + const float kExpValue = 0.94f; + retval += PredictionCostSpatial(tile[i], 1, kExpValue); + retval += VP8LCombinedShannonEntropy(tile[i], accumulated[i]); + } + return (float)retval; +} + +static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) { + ++histo_argb[0][argb >> 24]; + ++histo_argb[1][(argb >> 16) & 0xff]; + ++histo_argb[2][(argb >> 8) & 0xff]; + ++histo_argb[3][argb & 0xff]; +} + +//------------------------------------------------------------------------------ +// Spatial transform functions. + +static WEBP_INLINE void PredictBatch(int mode, int x_start, int y, + int num_pixels, const uint32_t* current, + const uint32_t* upper, uint32_t* out) { + if (x_start == 0) { + if (y == 0) { + // ARGB_BLACK. + VP8LPredictorsSub[0](current, NULL, 1, out); + } else { + // Top one. + VP8LPredictorsSub[2](current, upper, 1, out); + } + ++x_start; + ++out; + --num_pixels; + } + if (y == 0) { + // Left one. + VP8LPredictorsSub[1](current + x_start, NULL, num_pixels, out); + } else { + VP8LPredictorsSub[mode](current + x_start, upper + x_start, num_pixels, + out); + } +} + +#if (WEBP_NEAR_LOSSLESS == 1) +static WEBP_INLINE int GetMax(int a, int b) { return (a < b) ? b : a; } + +static int MaxDiffBetweenPixels(uint32_t p1, uint32_t p2) { + const int diff_a = abs((int)(p1 >> 24) - (int)(p2 >> 24)); + const int diff_r = abs((int)((p1 >> 16) & 0xff) - (int)((p2 >> 16) & 0xff)); + const int diff_g = abs((int)((p1 >> 8) & 0xff) - (int)((p2 >> 8) & 0xff)); + const int diff_b = abs((int)(p1 & 0xff) - (int)(p2 & 0xff)); + return GetMax(GetMax(diff_a, diff_r), GetMax(diff_g, diff_b)); +} + +static int MaxDiffAroundPixel(uint32_t current, uint32_t up, uint32_t down, + uint32_t left, uint32_t right) { + const int diff_up = MaxDiffBetweenPixels(current, up); + const int diff_down = MaxDiffBetweenPixels(current, down); + const int diff_left = MaxDiffBetweenPixels(current, left); + const int diff_right = MaxDiffBetweenPixels(current, right); + return GetMax(GetMax(diff_up, diff_down), GetMax(diff_left, diff_right)); +} + +static uint32_t AddGreenToBlueAndRed(uint32_t argb) { + const uint32_t green = (argb >> 8) & 0xff; + uint32_t red_blue = argb & 0x00ff00ffu; + red_blue += (green << 16) | green; + red_blue &= 0x00ff00ffu; + return (argb & 0xff00ff00u) | red_blue; +} + +static void MaxDiffsForRow(int width, int stride, const uint32_t* const argb, + uint8_t* const max_diffs, int used_subtract_green) { + uint32_t current, up, down, left, right; + int x; + if (width <= 2) return; + current = argb[0]; + right = argb[1]; + if (used_subtract_green) { + current = AddGreenToBlueAndRed(current); + right = AddGreenToBlueAndRed(right); + } + // max_diffs[0] and max_diffs[width - 1] are never used. + for (x = 1; x < width - 1; ++x) { + up = argb[-stride + x]; + down = argb[stride + x]; + left = current; + current = right; + right = argb[x + 1]; + if (used_subtract_green) { + up = AddGreenToBlueAndRed(up); + down = AddGreenToBlueAndRed(down); + right = AddGreenToBlueAndRed(right); + } + max_diffs[x] = MaxDiffAroundPixel(current, up, down, left, right); + } +} + +// Quantize the difference between the actual component value and its prediction +// to a multiple of quantization, working modulo 256, taking care not to cross +// a boundary (inclusive upper limit). +static uint8_t NearLosslessComponent(uint8_t value, uint8_t predict, + uint8_t boundary, int quantization) { + const int residual = (value - predict) & 0xff; + const int boundary_residual = (boundary - predict) & 0xff; + const int lower = residual & ~(quantization - 1); + const int upper = lower + quantization; + // Resolve ties towards a value closer to the prediction (i.e. towards lower + // if value comes after prediction and towards upper otherwise). + const int bias = ((boundary - value) & 0xff) < boundary_residual; + if (residual - lower < upper - residual + bias) { + // lower is closer to residual than upper. + if (residual > boundary_residual && lower <= boundary_residual) { + // Halve quantization step to avoid crossing boundary. This midpoint is + // on the same side of boundary as residual because midpoint >= residual + // (since lower is closer than upper) and residual is above the boundary. + return lower + (quantization >> 1); + } + return lower; + } else { + // upper is closer to residual than lower. + if (residual <= boundary_residual && upper > boundary_residual) { + // Halve quantization step to avoid crossing boundary. This midpoint is + // on the same side of boundary as residual because midpoint <= residual + // (since upper is closer than lower) and residual is below the boundary. + return lower + (quantization >> 1); + } + return upper & 0xff; + } +} + +static WEBP_INLINE uint8_t NearLosslessDiff(uint8_t a, uint8_t b) { + return (uint8_t)((((int)(a) - (int)(b))) & 0xff); +} + +// Quantize every component of the difference between the actual pixel value and +// its prediction to a multiple of a quantization (a power of 2, not larger than +// max_quantization which is a power of 2, smaller than max_diff). Take care if +// value and predict have undergone subtract green, which means that red and +// blue are represented as offsets from green. +static uint32_t NearLossless(uint32_t value, uint32_t predict, + int max_quantization, int max_diff, + int used_subtract_green) { + int quantization; + uint8_t new_green = 0; + uint8_t green_diff = 0; + uint8_t a, r, g, b; + if (max_diff <= 2) { + return VP8LSubPixels(value, predict); + } + quantization = max_quantization; + while (quantization >= max_diff) { + quantization >>= 1; + } + if ((value >> 24) == 0 || (value >> 24) == 0xff) { + // Preserve transparency of fully transparent or fully opaque pixels. + a = NearLosslessDiff((value >> 24) & 0xff, (predict >> 24) & 0xff); + } else { + a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization); + } + g = NearLosslessComponent((value >> 8) & 0xff, (predict >> 8) & 0xff, 0xff, + quantization); + if (used_subtract_green) { + // The green offset will be added to red and blue components during decoding + // to obtain the actual red and blue values. + new_green = ((predict >> 8) + g) & 0xff; + // The amount by which green has been adjusted during quantization. It is + // subtracted from red and blue for compensation, to avoid accumulating two + // quantization errors in them. + green_diff = NearLosslessDiff(new_green, (value >> 8) & 0xff); + } + r = NearLosslessComponent(NearLosslessDiff((value >> 16) & 0xff, green_diff), + (predict >> 16) & 0xff, 0xff - new_green, + quantization); + b = NearLosslessComponent(NearLosslessDiff(value & 0xff, green_diff), + predict & 0xff, 0xff - new_green, quantization); + return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; +} +#endif // (WEBP_NEAR_LOSSLESS == 1) + +// Stores the difference between the pixel and its prediction in "out". +// In case of a lossy encoding, updates the source image to avoid propagating +// the deviation further to pixels which depend on the current pixel for their +// predictions. +static WEBP_INLINE void GetResidual( + int width, int height, uint32_t* const upper_row, + uint32_t* const current_row, const uint8_t* const max_diffs, int mode, + int x_start, int x_end, int y, int max_quantization, int exact, + int used_subtract_green, uint32_t* const out) { + if (exact) { + PredictBatch(mode, x_start, y, x_end - x_start, current_row, upper_row, + out); + } else { + const VP8LPredictorFunc pred_func = VP8LPredictors[mode]; + int x; + for (x = x_start; x < x_end; ++x) { + uint32_t predict; + uint32_t residual; + if (y == 0) { + predict = (x == 0) ? ARGB_BLACK : current_row[x - 1]; // Left. + } else if (x == 0) { + predict = upper_row[x]; // Top. + } else { + predict = pred_func(¤t_row[x - 1], upper_row + x); + } +#if (WEBP_NEAR_LOSSLESS == 1) + if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 || + x == 0 || x == width - 1) { + residual = VP8LSubPixels(current_row[x], predict); + } else { + residual = NearLossless(current_row[x], predict, max_quantization, + max_diffs[x], used_subtract_green); + // Update the source image. + current_row[x] = VP8LAddPixels(predict, residual); + // x is never 0 here so we do not need to update upper_row like below. + } +#else + (void)max_diffs; + (void)height; + (void)max_quantization; + (void)used_subtract_green; + residual = VP8LSubPixels(current_row[x], predict); +#endif + if ((current_row[x] & kMaskAlpha) == 0) { + // If alpha is 0, cleanup RGB. We can choose the RGB values of the + // residual for best compression. The prediction of alpha itself can be + // non-zero and must be kept though. We choose RGB of the residual to be + // 0. + residual &= kMaskAlpha; + // Update the source image. + current_row[x] = predict & ~kMaskAlpha; + // The prediction for the rightmost pixel in a row uses the leftmost + // pixel + // in that row as its top-right context pixel. Hence if we change the + // leftmost pixel of current_row, the corresponding change must be + // applied + // to upper_row as well where top-right context is being read from. + if (x == 0 && y != 0) upper_row[width] = current_row[0]; + } + out[x - x_start] = residual; + } + } +} + +// Returns best predictor and updates the accumulated histogram. +// If max_quantization > 1, assumes that near lossless processing will be +// applied, quantizing residuals to multiples of quantization levels up to +// max_quantization (the actual quantization level depends on smoothness near +// the given pixel). +static int GetBestPredictorForTile(int width, int height, + int tile_x, int tile_y, int bits, + int accumulated[4][256], + uint32_t* const argb_scratch, + const uint32_t* const argb, + int max_quantization, + int exact, int used_subtract_green, + const uint32_t* const modes) { + const int kNumPredModes = 14; + const int start_x = tile_x << bits; + const int start_y = tile_y << bits; + const int tile_size = 1 << bits; + const int max_y = GetMin(tile_size, height - start_y); + const int max_x = GetMin(tile_size, width - start_x); + // Whether there exist columns just outside the tile. + const int have_left = (start_x > 0); + // Position and size of the strip covering the tile and adjacent columns if + // they exist. + const int context_start_x = start_x - have_left; +#if (WEBP_NEAR_LOSSLESS == 1) + const int context_width = max_x + have_left + (max_x < width - start_x); +#endif + const int tiles_per_row = VP8LSubSampleSize(width, bits); + // Prediction modes of the left and above neighbor tiles. + const int left_mode = (tile_x > 0) ? + (modes[tile_y * tiles_per_row + tile_x - 1] >> 8) & 0xff : 0xff; + const int above_mode = (tile_y > 0) ? + (modes[(tile_y - 1) * tiles_per_row + tile_x] >> 8) & 0xff : 0xff; + // The width of upper_row and current_row is one pixel larger than image width + // to allow the top right pixel to point to the leftmost pixel of the next row + // when at the right edge. + uint32_t* upper_row = argb_scratch; + uint32_t* current_row = upper_row + width + 1; + uint8_t* const max_diffs = (uint8_t*)(current_row + width + 1); + float best_diff = MAX_DIFF_COST; + int best_mode = 0; + int mode; + int histo_stack_1[4][256]; + int histo_stack_2[4][256]; + // Need pointers to be able to swap arrays. + int (*histo_argb)[256] = histo_stack_1; + int (*best_histo)[256] = histo_stack_2; + int i, j; + uint32_t residuals[1 << MAX_TRANSFORM_BITS]; + assert(bits <= MAX_TRANSFORM_BITS); + assert(max_x <= (1 << MAX_TRANSFORM_BITS)); + + for (mode = 0; mode < kNumPredModes; ++mode) { + float cur_diff; + int relative_y; + memset(histo_argb, 0, sizeof(histo_stack_1)); + if (start_y > 0) { + // Read the row above the tile which will become the first upper_row. + // Include a pixel to the left if it exists; include a pixel to the right + // in all cases (wrapping to the leftmost pixel of the next row if it does + // not exist). + memcpy(current_row + context_start_x, + argb + (start_y - 1) * width + context_start_x, + sizeof(*argb) * (max_x + have_left + 1)); + } + for (relative_y = 0; relative_y < max_y; ++relative_y) { + const int y = start_y + relative_y; + int relative_x; + uint32_t* tmp = upper_row; + upper_row = current_row; + current_row = tmp; + // Read current_row. Include a pixel to the left if it exists; include a + // pixel to the right in all cases except at the bottom right corner of + // the image (wrapping to the leftmost pixel of the next row if it does + // not exist in the current row). + memcpy(current_row + context_start_x, + argb + y * width + context_start_x, + sizeof(*argb) * (max_x + have_left + (y + 1 < height))); +#if (WEBP_NEAR_LOSSLESS == 1) + if (max_quantization > 1 && y >= 1 && y + 1 < height) { + MaxDiffsForRow(context_width, width, argb + y * width + context_start_x, + max_diffs + context_start_x, used_subtract_green); + } +#endif + + GetResidual(width, height, upper_row, current_row, max_diffs, mode, + start_x, start_x + max_x, y, max_quantization, exact, + used_subtract_green, residuals); + for (relative_x = 0; relative_x < max_x; ++relative_x) { + UpdateHisto(histo_argb, residuals[relative_x]); + } + } + cur_diff = PredictionCostSpatialHistogram( + (const int (*)[256])accumulated, (const int (*)[256])histo_argb); + // Favor keeping the areas locally similar. + if (mode == left_mode) cur_diff -= kSpatialPredictorBias; + if (mode == above_mode) cur_diff -= kSpatialPredictorBias; + + if (cur_diff < best_diff) { + int (*tmp)[256] = histo_argb; + histo_argb = best_histo; + best_histo = tmp; + best_diff = cur_diff; + best_mode = mode; + } + } + + for (i = 0; i < 4; i++) { + for (j = 0; j < 256; j++) { + accumulated[i][j] += best_histo[i][j]; + } + } + + return best_mode; +} + +// Converts pixels of the image to residuals with respect to predictions. +// If max_quantization > 1, applies near lossless processing, quantizing +// residuals to multiples of quantization levels up to max_quantization +// (the actual quantization level depends on smoothness near the given pixel). +static void CopyImageWithPrediction(int width, int height, + int bits, uint32_t* const modes, + uint32_t* const argb_scratch, + uint32_t* const argb, + int low_effort, int max_quantization, + int exact, int used_subtract_green) { + const int tiles_per_row = VP8LSubSampleSize(width, bits); + // The width of upper_row and current_row is one pixel larger than image width + // to allow the top right pixel to point to the leftmost pixel of the next row + // when at the right edge. + uint32_t* upper_row = argb_scratch; + uint32_t* current_row = upper_row + width + 1; + uint8_t* current_max_diffs = (uint8_t*)(current_row + width + 1); +#if (WEBP_NEAR_LOSSLESS == 1) + uint8_t* lower_max_diffs = current_max_diffs + width; +#endif + int y; + + for (y = 0; y < height; ++y) { + int x; + uint32_t* const tmp32 = upper_row; + upper_row = current_row; + current_row = tmp32; + memcpy(current_row, argb + y * width, + sizeof(*argb) * (width + (y + 1 < height))); + + if (low_effort) { + PredictBatch(kPredLowEffort, 0, y, width, current_row, upper_row, + argb + y * width); + } else { +#if (WEBP_NEAR_LOSSLESS == 1) + if (max_quantization > 1) { + // Compute max_diffs for the lower row now, because that needs the + // contents of argb for the current row, which we will overwrite with + // residuals before proceeding with the next row. + uint8_t* const tmp8 = current_max_diffs; + current_max_diffs = lower_max_diffs; + lower_max_diffs = tmp8; + if (y + 2 < height) { + MaxDiffsForRow(width, width, argb + (y + 1) * width, lower_max_diffs, + used_subtract_green); + } + } +#endif + for (x = 0; x < width;) { + const int mode = + (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff; + int x_end = x + (1 << bits); + if (x_end > width) x_end = width; + GetResidual(width, height, upper_row, current_row, current_max_diffs, + mode, x, x_end, y, max_quantization, exact, + used_subtract_green, argb + y * width + x); + x = x_end; + } + } + } +} + +// Finds the best predictor for each tile, and converts the image to residuals +// with respect to predictions. If near_lossless_quality < 100, applies +// near lossless processing, shaving off more bits of residuals for lower +// qualities. +int VP8LResidualImage(int width, int height, int bits, int low_effort, + uint32_t* const argb, uint32_t* const argb_scratch, + uint32_t* const image, int near_lossless_quality, + int exact, int used_subtract_green, + const WebPPicture* const pic, int percent_range, + int* const percent) { + const int tiles_per_row = VP8LSubSampleSize(width, bits); + const int tiles_per_col = VP8LSubSampleSize(height, bits); + int percent_start = *percent; + int tile_y; + int histo[4][256]; + const int max_quantization = 1 << VP8LNearLosslessBits(near_lossless_quality); + if (low_effort) { + int i; + for (i = 0; i < tiles_per_row * tiles_per_col; ++i) { + image[i] = ARGB_BLACK | (kPredLowEffort << 8); + } + } else { + memset(histo, 0, sizeof(histo)); + for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { + int tile_x; + for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { + const int pred = GetBestPredictorForTile( + width, height, tile_x, tile_y, bits, histo, argb_scratch, argb, + max_quantization, exact, used_subtract_green, image); + image[tile_y * tiles_per_row + tile_x] = ARGB_BLACK | (pred << 8); + } + + if (!WebPReportProgress( + pic, percent_start + percent_range * tile_y / tiles_per_col, + percent)) { + return 0; + } + } + } + + CopyImageWithPrediction(width, height, bits, image, argb_scratch, argb, + low_effort, max_quantization, exact, + used_subtract_green); + return WebPReportProgress(pic, percent_start + percent_range, percent); +} + +//------------------------------------------------------------------------------ +// Color transform functions. + +static WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) { + m->green_to_red_ = 0; + m->green_to_blue_ = 0; + m->red_to_blue_ = 0; +} + +static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, + VP8LMultipliers* const m) { + m->green_to_red_ = (color_code >> 0) & 0xff; + m->green_to_blue_ = (color_code >> 8) & 0xff; + m->red_to_blue_ = (color_code >> 16) & 0xff; +} + +static WEBP_INLINE uint32_t MultipliersToColorCode( + const VP8LMultipliers* const m) { + return 0xff000000u | + ((uint32_t)(m->red_to_blue_) << 16) | + ((uint32_t)(m->green_to_blue_) << 8) | + m->green_to_red_; +} + +static float PredictionCostCrossColor(const int accumulated[256], + const int counts[256]) { + // Favor low entropy, locally and globally. + // Favor small absolute values for PredictionCostSpatial + static const float kExpValue = 2.4f; + return VP8LCombinedShannonEntropy(counts, accumulated) + + PredictionCostSpatial(counts, 3, kExpValue); +} + +static float GetPredictionCostCrossColorRed( + const uint32_t* argb, int stride, int tile_width, int tile_height, + VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red, + const int accumulated_red_histo[256]) { + int histo[256] = { 0 }; + float cur_diff; + + VP8LCollectColorRedTransforms(argb, stride, tile_width, tile_height, + green_to_red, histo); + + cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo); + if ((uint8_t)green_to_red == prev_x.green_to_red_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if ((uint8_t)green_to_red == prev_y.green_to_red_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if (green_to_red == 0) { + cur_diff -= 3; + } + return cur_diff; +} + +static void GetBestGreenToRed( + const uint32_t* argb, int stride, int tile_width, int tile_height, + VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, + const int accumulated_red_histo[256], VP8LMultipliers* const best_tx) { + const int kMaxIters = 4 + ((7 * quality) >> 8); // in range [4..6] + int green_to_red_best = 0; + int iter, offset; + float best_diff = GetPredictionCostCrossColorRed( + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_red_best, accumulated_red_histo); + for (iter = 0; iter < kMaxIters; ++iter) { + // ColorTransformDelta is a 3.5 bit fixed point, so 32 is equal to + // one in color computation. Having initial delta here as 1 is sufficient + // to explore the range of (-2, 2). + const int delta = 32 >> iter; + // Try a negative and a positive delta from the best known value. + for (offset = -delta; offset <= delta; offset += 2 * delta) { + const int green_to_red_cur = offset + green_to_red_best; + const float cur_diff = GetPredictionCostCrossColorRed( + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_red_cur, accumulated_red_histo); + if (cur_diff < best_diff) { + best_diff = cur_diff; + green_to_red_best = green_to_red_cur; + } + } + } + best_tx->green_to_red_ = (green_to_red_best & 0xff); +} + +static float GetPredictionCostCrossColorBlue( + const uint32_t* argb, int stride, int tile_width, int tile_height, + VP8LMultipliers prev_x, VP8LMultipliers prev_y, + int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256]) { + int histo[256] = { 0 }; + float cur_diff; + + VP8LCollectColorBlueTransforms(argb, stride, tile_width, tile_height, + green_to_blue, red_to_blue, histo); + + cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo); + if ((uint8_t)green_to_blue == prev_x.green_to_blue_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if ((uint8_t)green_to_blue == prev_y.green_to_blue_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if ((uint8_t)red_to_blue == prev_x.red_to_blue_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if ((uint8_t)red_to_blue == prev_y.red_to_blue_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if (green_to_blue == 0) { + cur_diff -= 3; + } + if (red_to_blue == 0) { + cur_diff -= 3; + } + return cur_diff; +} + +#define kGreenRedToBlueNumAxis 8 +#define kGreenRedToBlueMaxIters 7 +static void GetBestGreenRedToBlue( + const uint32_t* argb, int stride, int tile_width, int tile_height, + VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, + const int accumulated_blue_histo[256], + VP8LMultipliers* const best_tx) { + const int8_t offset[kGreenRedToBlueNumAxis][2] = + {{0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; + const int8_t delta_lut[kGreenRedToBlueMaxIters] = { 16, 16, 8, 4, 2, 2, 2 }; + const int iters = + (quality < 25) ? 1 : (quality > 50) ? kGreenRedToBlueMaxIters : 4; + int green_to_blue_best = 0; + int red_to_blue_best = 0; + int iter; + // Initial value at origin: + float best_diff = GetPredictionCostCrossColorBlue( + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_blue_best, red_to_blue_best, accumulated_blue_histo); + for (iter = 0; iter < iters; ++iter) { + const int delta = delta_lut[iter]; + int axis; + for (axis = 0; axis < kGreenRedToBlueNumAxis; ++axis) { + const int green_to_blue_cur = + offset[axis][0] * delta + green_to_blue_best; + const int red_to_blue_cur = offset[axis][1] * delta + red_to_blue_best; + const float cur_diff = GetPredictionCostCrossColorBlue( + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_blue_cur, red_to_blue_cur, accumulated_blue_histo); + if (cur_diff < best_diff) { + best_diff = cur_diff; + green_to_blue_best = green_to_blue_cur; + red_to_blue_best = red_to_blue_cur; + } + if (quality < 25 && iter == 4) { + // Only axis aligned diffs for lower quality. + break; // next iter. + } + } + if (delta == 2 && green_to_blue_best == 0 && red_to_blue_best == 0) { + // Further iterations would not help. + break; // out of iter-loop. + } + } + best_tx->green_to_blue_ = green_to_blue_best & 0xff; + best_tx->red_to_blue_ = red_to_blue_best & 0xff; +} +#undef kGreenRedToBlueMaxIters +#undef kGreenRedToBlueNumAxis + +static VP8LMultipliers GetBestColorTransformForTile( + int tile_x, int tile_y, int bits, + VP8LMultipliers prev_x, + VP8LMultipliers prev_y, + int quality, int xsize, int ysize, + const int accumulated_red_histo[256], + const int accumulated_blue_histo[256], + const uint32_t* const argb) { + const int max_tile_size = 1 << bits; + const int tile_y_offset = tile_y * max_tile_size; + const int tile_x_offset = tile_x * max_tile_size; + const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize); + const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize); + const int tile_width = all_x_max - tile_x_offset; + const int tile_height = all_y_max - tile_y_offset; + const uint32_t* const tile_argb = argb + tile_y_offset * xsize + + tile_x_offset; + VP8LMultipliers best_tx; + MultipliersClear(&best_tx); + + GetBestGreenToRed(tile_argb, xsize, tile_width, tile_height, + prev_x, prev_y, quality, accumulated_red_histo, &best_tx); + GetBestGreenRedToBlue(tile_argb, xsize, tile_width, tile_height, + prev_x, prev_y, quality, accumulated_blue_histo, + &best_tx); + return best_tx; +} + +static void CopyTileWithColorTransform(int xsize, int ysize, + int tile_x, int tile_y, + int max_tile_size, + VP8LMultipliers color_transform, + uint32_t* argb) { + const int xscan = GetMin(max_tile_size, xsize - tile_x); + int yscan = GetMin(max_tile_size, ysize - tile_y); + argb += tile_y * xsize + tile_x; + while (yscan-- > 0) { + VP8LTransformColor(&color_transform, argb, xscan); + argb += xsize; + } +} + +int VP8LColorSpaceTransform(int width, int height, int bits, int quality, + uint32_t* const argb, uint32_t* image, + const WebPPicture* const pic, int percent_range, + int* const percent) { + const int max_tile_size = 1 << bits; + const int tile_xsize = VP8LSubSampleSize(width, bits); + const int tile_ysize = VP8LSubSampleSize(height, bits); + int percent_start = *percent; + int accumulated_red_histo[256] = { 0 }; + int accumulated_blue_histo[256] = { 0 }; + int tile_x, tile_y; + VP8LMultipliers prev_x, prev_y; + MultipliersClear(&prev_y); + MultipliersClear(&prev_x); + for (tile_y = 0; tile_y < tile_ysize; ++tile_y) { + for (tile_x = 0; tile_x < tile_xsize; ++tile_x) { + int y; + const int tile_x_offset = tile_x * max_tile_size; + const int tile_y_offset = tile_y * max_tile_size; + const int all_x_max = GetMin(tile_x_offset + max_tile_size, width); + const int all_y_max = GetMin(tile_y_offset + max_tile_size, height); + const int offset = tile_y * tile_xsize + tile_x; + if (tile_y != 0) { + ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y); + } + prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits, + prev_x, prev_y, + quality, width, height, + accumulated_red_histo, + accumulated_blue_histo, + argb); + image[offset] = MultipliersToColorCode(&prev_x); + CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset, + max_tile_size, prev_x, argb); + + // Gather accumulated histogram data. + for (y = tile_y_offset; y < all_y_max; ++y) { + int ix = y * width + tile_x_offset; + const int ix_end = ix + all_x_max - tile_x_offset; + for (; ix < ix_end; ++ix) { + const uint32_t pix = argb[ix]; + if (ix >= 2 && + pix == argb[ix - 2] && + pix == argb[ix - 1]) { + continue; // repeated pixels are handled by backward references + } + if (ix >= width + 2 && + argb[ix - 2] == argb[ix - width - 2] && + argb[ix - 1] == argb[ix - width - 1] && + pix == argb[ix - width]) { + continue; // repeated pixels are handled by backward references + } + ++accumulated_red_histo[(pix >> 16) & 0xff]; + ++accumulated_blue_histo[(pix >> 0) & 0xff]; + } + } + } + if (!WebPReportProgress( + pic, percent_start + percent_range * tile_y / tile_ysize, + percent)) { + return 0; + } + } + return 1; +} diff --git a/libraries/webp/src/enc/quant_enc.c b/libraries/webp/src/enc/quant_enc.c new file mode 100644 index 0000000000..6d8202d277 --- /dev/null +++ b/libraries/webp/src/enc/quant_enc.c @@ -0,0 +1,1398 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Quantization +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include // for abs() + +#include "src/dsp/quant.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" + +#define DO_TRELLIS_I4 1 +#define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate. +#define DO_TRELLIS_UV 0 // disable trellis for UV. Risky. Not worth. +#define USE_TDISTO 1 + +#define MID_ALPHA 64 // neutral value for susceptibility +#define MIN_ALPHA 30 // lowest usable value for susceptibility +#define MAX_ALPHA 100 // higher meaningful value for susceptibility + +#define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP + // power-law modulation. Must be strictly less than 1. + +// number of non-zero coeffs below which we consider the block very flat +// (and apply a penalty to complex predictions) +#define FLATNESS_LIMIT_I16 0 // I16 mode (special case) +#define FLATNESS_LIMIT_I4 3 // I4 mode +#define FLATNESS_LIMIT_UV 2 // UV mode +#define FLATNESS_PENALTY 140 // roughly ~1bit per block + +#define MULT_8B(a, b) (((a) * (b) + 128) >> 8) + +#define RD_DISTO_MULT 256 // distortion multiplier (equivalent of lambda) + +// #define DEBUG_BLOCK + +//------------------------------------------------------------------------------ + +#if defined(DEBUG_BLOCK) + +#include +#include + +static void PrintBlockInfo(const VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int i, j; + const int is_i16 = (it->mb_->type_ == 1); + const uint8_t* const y_in = it->yuv_in_ + Y_OFF_ENC; + const uint8_t* const y_out = it->yuv_out_ + Y_OFF_ENC; + const uint8_t* const uv_in = it->yuv_in_ + U_OFF_ENC; + const uint8_t* const uv_out = it->yuv_out_ + U_OFF_ENC; + printf("SOURCE / OUTPUT / ABS DELTA\n"); + for (j = 0; j < 16; ++j) { + for (i = 0; i < 16; ++i) printf("%3d ", y_in[i + j * BPS]); + printf(" "); + for (i = 0; i < 16; ++i) printf("%3d ", y_out[i + j * BPS]); + printf(" "); + for (i = 0; i < 16; ++i) { + printf("%1d ", abs(y_in[i + j * BPS] - y_out[i + j * BPS])); + } + printf("\n"); + } + printf("\n"); // newline before the U/V block + for (j = 0; j < 8; ++j) { + for (i = 0; i < 8; ++i) printf("%3d ", uv_in[i + j * BPS]); + printf(" "); + for (i = 8; i < 16; ++i) printf("%3d ", uv_in[i + j * BPS]); + printf(" "); + for (i = 0; i < 8; ++i) printf("%3d ", uv_out[i + j * BPS]); + printf(" "); + for (i = 8; i < 16; ++i) printf("%3d ", uv_out[i + j * BPS]); + printf(" "); + for (i = 0; i < 8; ++i) { + printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS])); + } + printf(" "); + for (i = 8; i < 16; ++i) { + printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS])); + } + printf("\n"); + } + printf("\nD:%d SD:%d R:%d H:%d nz:0x%x score:%d\n", + (int)rd->D, (int)rd->SD, (int)rd->R, (int)rd->H, (int)rd->nz, + (int)rd->score); + if (is_i16) { + printf("Mode: %d\n", rd->mode_i16); + printf("y_dc_levels:"); + for (i = 0; i < 16; ++i) printf("%3d ", rd->y_dc_levels[i]); + printf("\n"); + } else { + printf("Modes[16]: "); + for (i = 0; i < 16; ++i) printf("%d ", rd->modes_i4[i]); + printf("\n"); + } + printf("y_ac_levels:\n"); + for (j = 0; j < 16; ++j) { + for (i = is_i16 ? 1 : 0; i < 16; ++i) { + printf("%4d ", rd->y_ac_levels[j][i]); + } + printf("\n"); + } + printf("\n"); + printf("uv_levels (mode=%d):\n", rd->mode_uv); + for (j = 0; j < 8; ++j) { + for (i = 0; i < 16; ++i) { + printf("%4d ", rd->uv_levels[j][i]); + } + printf("\n"); + } +} + +#endif // DEBUG_BLOCK + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int clip(int v, int m, int M) { + return v < m ? m : v > M ? M : v; +} + +static const uint8_t kZigzag[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + +static const uint8_t kDcTable[128] = { + 4, 5, 6, 7, 8, 9, 10, 10, + 11, 12, 13, 14, 15, 16, 17, 17, + 18, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 25, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, + 91, 93, 95, 96, 98, 100, 101, 102, + 104, 106, 108, 110, 112, 114, 116, 118, + 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 143, 145, 148, 151, 154, 157 +}; + +static const uint16_t kAcTable[128] = { + 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 60, + 62, 64, 66, 68, 70, 72, 74, 76, + 78, 80, 82, 84, 86, 88, 90, 92, + 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, + 131, 134, 137, 140, 143, 146, 149, 152, + 155, 158, 161, 164, 167, 170, 173, 177, + 181, 185, 189, 193, 197, 201, 205, 209, + 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284 +}; + +static const uint16_t kAcTable2[128] = { + 8, 8, 9, 10, 12, 13, 15, 17, + 18, 20, 21, 23, 24, 26, 27, 29, + 31, 32, 34, 35, 37, 38, 40, 41, + 43, 44, 46, 48, 49, 51, 52, 54, + 55, 57, 58, 60, 62, 63, 65, 66, + 68, 69, 71, 72, 74, 75, 77, 79, + 80, 82, 83, 85, 86, 88, 89, 93, + 96, 99, 102, 105, 108, 111, 114, 117, + 120, 124, 127, 130, 133, 136, 139, 142, + 145, 148, 151, 155, 158, 161, 164, 167, + 170, 173, 176, 179, 184, 189, 193, 198, + 203, 207, 212, 217, 221, 226, 230, 235, + 240, 244, 249, 254, 258, 263, 268, 274, + 280, 286, 292, 299, 305, 311, 317, 323, + 330, 336, 342, 348, 354, 362, 370, 379, + 385, 393, 401, 409, 416, 424, 432, 440 +}; + +static const uint8_t kBiasMatrices[3][2] = { // [luma-ac,luma-dc,chroma][dc,ac] + { 96, 110 }, { 96, 108 }, { 110, 115 } +}; + +// Sharpening by (slightly) raising the hi-frequency coeffs. +// Hack-ish but helpful for mid-bitrate range. Use with care. +#define SHARPEN_BITS 11 // number of descaling bits for sharpening bias +static const uint8_t kFreqSharpening[16] = { + 0, 30, 60, 90, + 30, 60, 90, 90, + 60, 90, 90, 90, + 90, 90, 90, 90 +}; + +//------------------------------------------------------------------------------ +// Initialize quantization parameters in VP8Matrix + +// Returns the average quantizer +static int ExpandMatrix(VP8Matrix* const m, int type) { + int i, sum; + for (i = 0; i < 2; ++i) { + const int is_ac_coeff = (i > 0); + const int bias = kBiasMatrices[type][is_ac_coeff]; + m->iq_[i] = (1 << QFIX) / m->q_[i]; + m->bias_[i] = BIAS(bias); + // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is: + // * zero if coeff <= zthresh + // * non-zero if coeff > zthresh + m->zthresh_[i] = ((1 << QFIX) - 1 - m->bias_[i]) / m->iq_[i]; + } + for (i = 2; i < 16; ++i) { + m->q_[i] = m->q_[1]; + m->iq_[i] = m->iq_[1]; + m->bias_[i] = m->bias_[1]; + m->zthresh_[i] = m->zthresh_[1]; + } + for (sum = 0, i = 0; i < 16; ++i) { + if (type == 0) { // we only use sharpening for AC luma coeffs + m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> SHARPEN_BITS; + } else { + m->sharpen_[i] = 0; + } + sum += m->q_[i]; + } + return (sum + 8) >> 4; +} + +static void CheckLambdaValue(int* const v) { if (*v < 1) *v = 1; } + +static void SetupMatrices(VP8Encoder* enc) { + int i; + const int tlambda_scale = + (enc->method_ >= 4) ? enc->config_->sns_strength + : 0; + const int num_segments = enc->segment_hdr_.num_segments_; + for (i = 0; i < num_segments; ++i) { + VP8SegmentInfo* const m = &enc->dqm_[i]; + const int q = m->quant_; + int q_i4, q_i16, q_uv; + m->y1_.q_[0] = kDcTable[clip(q + enc->dq_y1_dc_, 0, 127)]; + m->y1_.q_[1] = kAcTable[clip(q, 0, 127)]; + + m->y2_.q_[0] = kDcTable[ clip(q + enc->dq_y2_dc_, 0, 127)] * 2; + m->y2_.q_[1] = kAcTable2[clip(q + enc->dq_y2_ac_, 0, 127)]; + + m->uv_.q_[0] = kDcTable[clip(q + enc->dq_uv_dc_, 0, 117)]; + m->uv_.q_[1] = kAcTable[clip(q + enc->dq_uv_ac_, 0, 127)]; + + q_i4 = ExpandMatrix(&m->y1_, 0); + q_i16 = ExpandMatrix(&m->y2_, 1); + q_uv = ExpandMatrix(&m->uv_, 2); + + m->lambda_i4_ = (3 * q_i4 * q_i4) >> 7; + m->lambda_i16_ = (3 * q_i16 * q_i16); + m->lambda_uv_ = (3 * q_uv * q_uv) >> 6; + m->lambda_mode_ = (1 * q_i4 * q_i4) >> 7; + m->lambda_trellis_i4_ = (7 * q_i4 * q_i4) >> 3; + m->lambda_trellis_i16_ = (q_i16 * q_i16) >> 2; + m->lambda_trellis_uv_ = (q_uv * q_uv) << 1; + m->tlambda_ = (tlambda_scale * q_i4) >> 5; + + // none of these constants should be < 1 + CheckLambdaValue(&m->lambda_i4_); + CheckLambdaValue(&m->lambda_i16_); + CheckLambdaValue(&m->lambda_uv_); + CheckLambdaValue(&m->lambda_mode_); + CheckLambdaValue(&m->lambda_trellis_i4_); + CheckLambdaValue(&m->lambda_trellis_i16_); + CheckLambdaValue(&m->lambda_trellis_uv_); + CheckLambdaValue(&m->tlambda_); + + m->min_disto_ = 20 * m->y1_.q_[0]; // quantization-aware min disto + m->max_edge_ = 0; + + m->i4_penalty_ = 1000 * q_i4 * q_i4; + } +} + +//------------------------------------------------------------------------------ +// Initialize filtering parameters + +// Very small filter-strength values have close to no visual effect. So we can +// save a little decoding-CPU by turning filtering off for these. +#define FSTRENGTH_CUTOFF 2 + +static void SetupFilterStrength(VP8Encoder* const enc) { + int i; + // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering. + const int level0 = 5 * enc->config_->filter_strength; + for (i = 0; i < NUM_MB_SEGMENTS; ++i) { + VP8SegmentInfo* const m = &enc->dqm_[i]; + // We focus on the quantization of AC coeffs. + const int qstep = kAcTable[clip(m->quant_, 0, 127)] >> 2; + const int base_strength = + VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, qstep); + // Segments with lower complexity ('beta') will be less filtered. + const int f = base_strength * level0 / (256 + m->beta_); + m->fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f; + } + // We record the initial strength (mainly for the case of 1-segment only). + enc->filter_hdr_.level_ = enc->dqm_[0].fstrength_; + enc->filter_hdr_.simple_ = (enc->config_->filter_type == 0); + enc->filter_hdr_.sharpness_ = enc->config_->filter_sharpness; +} + +//------------------------------------------------------------------------------ + +// Note: if you change the values below, remember that the max range +// allowed by the syntax for DQ_UV is [-16,16]. +#define MAX_DQ_UV (6) +#define MIN_DQ_UV (-4) + +// We want to emulate jpeg-like behaviour where the expected "good" quality +// is around q=75. Internally, our "good" middle is around c=50. So we +// map accordingly using linear piece-wise function +static double QualityToCompression(double c) { + const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.; + // The file size roughly scales as pow(quantizer, 3.). Actually, the + // exponent is somewhere between 2.8 and 3.2, but we're mostly interested + // in the mid-quant range. So we scale the compressibility inversely to + // this power-law: quant ~= compression ^ 1/3. This law holds well for + // low quant. Finer modeling for high-quant would make use of kAcTable[] + // more explicitly. + const double v = pow(linear_c, 1 / 3.); + return v; +} + +static double QualityToJPEGCompression(double c, double alpha) { + // We map the complexity 'alpha' and quality setting 'c' to a compression + // exponent empirically matched to the compression curve of libjpeg6b. + // On average, the WebP output size will be roughly similar to that of a + // JPEG file compressed with same quality factor. + const double amin = 0.30; + const double amax = 0.85; + const double exp_min = 0.4; + const double exp_max = 0.9; + const double slope = (exp_min - exp_max) / (amax - amin); + // Linearly interpolate 'expn' from exp_min to exp_max + // in the [amin, amax] range. + const double expn = (alpha > amax) ? exp_min + : (alpha < amin) ? exp_max + : exp_max + slope * (alpha - amin); + const double v = pow(c, expn); + return v; +} + +static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1, + const VP8SegmentInfo* const S2) { + return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_); +} + +static void SimplifySegments(VP8Encoder* const enc) { + int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 }; + // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an + // explicit check is needed to avoid a spurious warning about 'i' exceeding + // array bounds of 'dqm_' with some compilers (noticed with gcc-4.9). + const int num_segments = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) + ? enc->segment_hdr_.num_segments_ + : NUM_MB_SEGMENTS; + int num_final_segments = 1; + int s1, s2; + for (s1 = 1; s1 < num_segments; ++s1) { // find similar segments + const VP8SegmentInfo* const S1 = &enc->dqm_[s1]; + int found = 0; + // check if we already have similar segment + for (s2 = 0; s2 < num_final_segments; ++s2) { + const VP8SegmentInfo* const S2 = &enc->dqm_[s2]; + if (SegmentsAreEquivalent(S1, S2)) { + found = 1; + break; + } + } + map[s1] = s2; + if (!found) { + if (num_final_segments != s1) { + enc->dqm_[num_final_segments] = enc->dqm_[s1]; + } + ++num_final_segments; + } + } + if (num_final_segments < num_segments) { // Remap + int i = enc->mb_w_ * enc->mb_h_; + while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_]; + enc->segment_hdr_.num_segments_ = num_final_segments; + // Replicate the trailing segment infos (it's mostly cosmetics) + for (i = num_final_segments; i < num_segments; ++i) { + enc->dqm_[i] = enc->dqm_[num_final_segments - 1]; + } + } +} + +void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { + int i; + int dq_uv_ac, dq_uv_dc; + const int num_segments = enc->segment_hdr_.num_segments_; + const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.; + const double Q = quality / 100.; + const double c_base = enc->config_->emulate_jpeg_size ? + QualityToJPEGCompression(Q, enc->alpha_ / 255.) : + QualityToCompression(Q); + for (i = 0; i < num_segments; ++i) { + // We modulate the base coefficient to accommodate for the quantization + // susceptibility and allow denser segments to be quantized more. + const double expn = 1. - amp * enc->dqm_[i].alpha_; + const double c = pow(c_base, expn); + const int q = (int)(127. * (1. - c)); + assert(expn > 0.); + enc->dqm_[i].quant_ = clip(q, 0, 127); + } + + // purely indicative in the bitstream (except for the 1-segment case) + enc->base_quant_ = enc->dqm_[0].quant_; + + // fill-in values for the unused segments (required by the syntax) + for (i = num_segments; i < NUM_MB_SEGMENTS; ++i) { + enc->dqm_[i].quant_ = enc->base_quant_; + } + + // uv_alpha_ is normally spread around ~60. The useful range is + // typically ~30 (quite bad) to ~100 (ok to decimate UV more). + // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv. + dq_uv_ac = (enc->uv_alpha_ - MID_ALPHA) * (MAX_DQ_UV - MIN_DQ_UV) + / (MAX_ALPHA - MIN_ALPHA); + // we rescale by the user-defined strength of adaptation + dq_uv_ac = dq_uv_ac * enc->config_->sns_strength / 100; + // and make it safe. + dq_uv_ac = clip(dq_uv_ac, MIN_DQ_UV, MAX_DQ_UV); + // We also boost the dc-uv-quant a little, based on sns-strength, since + // U/V channels are quite more reactive to high quants (flat DC-blocks + // tend to appear, and are unpleasant). + dq_uv_dc = -4 * enc->config_->sns_strength / 100; + dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed + + enc->dq_y1_dc_ = 0; // TODO(skal): dq-lum + enc->dq_y2_dc_ = 0; + enc->dq_y2_ac_ = 0; + enc->dq_uv_dc_ = dq_uv_dc; + enc->dq_uv_ac_ = dq_uv_ac; + + SetupFilterStrength(enc); // initialize segments' filtering, eventually + + if (num_segments > 1) SimplifySegments(enc); + + SetupMatrices(enc); // finalize quantization matrices +} + +//------------------------------------------------------------------------------ +// Form the predictions in cache + +// Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index +const uint16_t VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; +const uint16_t VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; + +// Must be indexed using {B_DC_PRED -> B_HU_PRED} as index +const uint16_t VP8I4ModeOffsets[NUM_BMODES] = { + I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4 +}; + +void VP8MakeLuma16Preds(const VP8EncIterator* const it) { + const uint8_t* const left = it->x_ ? it->y_left_ : NULL; + const uint8_t* const top = it->y_ ? it->y_top_ : NULL; + VP8EncPredLuma16(it->yuv_p_, left, top); +} + +void VP8MakeChroma8Preds(const VP8EncIterator* const it) { + const uint8_t* const left = it->x_ ? it->u_left_ : NULL; + const uint8_t* const top = it->y_ ? it->uv_top_ : NULL; + VP8EncPredChroma8(it->yuv_p_, left, top); +} + +void VP8MakeIntra4Preds(const VP8EncIterator* const it) { + VP8EncPredLuma4(it->yuv_p_, it->i4_top_); +} + +//------------------------------------------------------------------------------ +// Quantize + +// Layout: +// +----+----+ +// |YYYY|UUVV| 0 +// |YYYY|UUVV| 4 +// |YYYY|....| 8 +// |YYYY|....| 12 +// +----+----+ + +const uint16_t VP8Scan[16] = { // Luma + 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, + 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, + 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, + 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, +}; + +static const uint16_t VP8ScanUV[4 + 4] = { + 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U + 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V +}; + +//------------------------------------------------------------------------------ +// Distortion measurement + +static const uint16_t kWeightY[16] = { + 38, 32, 20, 9, 32, 28, 17, 7, 20, 17, 10, 4, 9, 7, 4, 2 +}; + +static const uint16_t kWeightTrellis[16] = { +#if USE_TDISTO == 0 + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +#else + 30, 27, 19, 11, + 27, 24, 17, 10, + 19, 17, 12, 8, + 11, 10, 8, 6 +#endif +}; + +// Init/Copy the common fields in score. +static void InitScore(VP8ModeScore* const rd) { + rd->D = 0; + rd->SD = 0; + rd->R = 0; + rd->H = 0; + rd->nz = 0; + rd->score = MAX_COST; +} + +static void CopyScore(VP8ModeScore* WEBP_RESTRICT const dst, + const VP8ModeScore* WEBP_RESTRICT const src) { + dst->D = src->D; + dst->SD = src->SD; + dst->R = src->R; + dst->H = src->H; + dst->nz = src->nz; // note that nz is not accumulated, but just copied. + dst->score = src->score; +} + +static void AddScore(VP8ModeScore* WEBP_RESTRICT const dst, + const VP8ModeScore* WEBP_RESTRICT const src) { + dst->D += src->D; + dst->SD += src->SD; + dst->R += src->R; + dst->H += src->H; + dst->nz |= src->nz; // here, new nz bits are accumulated. + dst->score += src->score; +} + +//------------------------------------------------------------------------------ +// Performs trellis-optimized quantization. + +// Trellis node +typedef struct { + int8_t prev; // best previous node + int8_t sign; // sign of coeff_i + int16_t level; // level +} Node; + +// Score state +typedef struct { + score_t score; // partial RD score + const uint16_t* costs; // shortcut to cost tables +} ScoreState; + +// If a coefficient was quantized to a value Q (using a neutral bias), +// we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA] +// We don't test negative values though. +#define MIN_DELTA 0 // how much lower level to try +#define MAX_DELTA 1 // how much higher +#define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA) +#define NODE(n, l) (nodes[(n)][(l) + MIN_DELTA]) +#define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA]) + +static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) { + rd->score = (rd->R + rd->H) * lambda + RD_DISTO_MULT * (rd->D + rd->SD); +} + +static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate, + score_t distortion) { + return rate * lambda + RD_DISTO_MULT * distortion; +} + +// Coefficient type. +enum { TYPE_I16_AC = 0, TYPE_I16_DC = 1, TYPE_CHROMA_A = 2, TYPE_I4_AC = 3 }; + +static int TrellisQuantizeBlock(const VP8Encoder* WEBP_RESTRICT const enc, + int16_t in[16], int16_t out[16], + int ctx0, int coeff_type, + const VP8Matrix* WEBP_RESTRICT const mtx, + int lambda) { + const ProbaArray* const probas = enc->proba_.coeffs_[coeff_type]; + CostArrayPtr const costs = + (CostArrayPtr)enc->proba_.remapped_costs_[coeff_type]; + const int first = (coeff_type == TYPE_I16_AC) ? 1 : 0; + Node nodes[16][NUM_NODES]; + ScoreState score_states[2][NUM_NODES]; + ScoreState* ss_cur = &SCORE_STATE(0, MIN_DELTA); + ScoreState* ss_prev = &SCORE_STATE(1, MIN_DELTA); + int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous + score_t best_score; + int n, m, p, last; + + { + score_t cost; + const int thresh = mtx->q_[1] * mtx->q_[1] / 4; + const int last_proba = probas[VP8EncBands[first]][ctx0][0]; + + // compute the position of the last interesting coefficient + last = first - 1; + for (n = 15; n >= first; --n) { + const int j = kZigzag[n]; + const int err = in[j] * in[j]; + if (err > thresh) { + last = n; + break; + } + } + // we don't need to go inspect up to n = 16 coeffs. We can just go up + // to last + 1 (inclusive) without losing much. + if (last < 15) ++last; + + // compute 'skip' score. This is the max score one can do. + cost = VP8BitCost(0, last_proba); + best_score = RDScoreTrellis(lambda, cost, 0); + + // initialize source node. + for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { + const score_t rate = (ctx0 == 0) ? VP8BitCost(1, last_proba) : 0; + ss_cur[m].score = RDScoreTrellis(lambda, rate, 0); + ss_cur[m].costs = costs[first][ctx0]; + } + } + + // traverse trellis. + for (n = first; n <= last; ++n) { + const int j = kZigzag[n]; + const uint32_t Q = mtx->q_[j]; + const uint32_t iQ = mtx->iq_[j]; + const uint32_t B = BIAS(0x00); // neutral bias + // note: it's important to take sign of the _original_ coeff, + // so we don't have to consider level < 0 afterward. + const int sign = (in[j] < 0); + const uint32_t coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; + int level0 = QUANTDIV(coeff0, iQ, B); + int thresh_level = QUANTDIV(coeff0, iQ, BIAS(0x80)); + if (thresh_level > MAX_LEVEL) thresh_level = MAX_LEVEL; + if (level0 > MAX_LEVEL) level0 = MAX_LEVEL; + + { // Swap current and previous score states + ScoreState* const tmp = ss_cur; + ss_cur = ss_prev; + ss_prev = tmp; + } + + // test all alternate level values around level0. + for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { + Node* const cur = &NODE(n, m); + const int level = level0 + m; + const int ctx = (level > 2) ? 2 : level; + const int band = VP8EncBands[n + 1]; + score_t base_score; + score_t best_cur_score; + int best_prev; + score_t cost, score; + + ss_cur[m].costs = costs[n + 1][ctx]; + if (level < 0 || level > thresh_level) { + ss_cur[m].score = MAX_COST; + // Node is dead. + continue; + } + + { + // Compute delta_error = how much coding this level will + // subtract to max_error as distortion. + // Here, distortion = sum of (|coeff_i| - level_i * Q_i)^2 + const int new_error = coeff0 - level * Q; + const int delta_error = + kWeightTrellis[j] * (new_error * new_error - coeff0 * coeff0); + base_score = RDScoreTrellis(lambda, 0, delta_error); + } + + // Inspect all possible non-dead predecessors. Retain only the best one. + // The base_score is added to all scores so it is only added for the final + // value after the loop. + cost = VP8LevelCost(ss_prev[-MIN_DELTA].costs, level); + best_cur_score = + ss_prev[-MIN_DELTA].score + RDScoreTrellis(lambda, cost, 0); + best_prev = -MIN_DELTA; + for (p = -MIN_DELTA + 1; p <= MAX_DELTA; ++p) { + // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically + // eliminated since their score can't be better than the current best. + cost = VP8LevelCost(ss_prev[p].costs, level); + // Examine node assuming it's a non-terminal one. + score = ss_prev[p].score + RDScoreTrellis(lambda, cost, 0); + if (score < best_cur_score) { + best_cur_score = score; + best_prev = p; + } + } + best_cur_score += base_score; + // Store best finding in current node. + cur->sign = sign; + cur->level = level; + cur->prev = best_prev; + ss_cur[m].score = best_cur_score; + + // Now, record best terminal node (and thus best entry in the graph). + if (level != 0 && best_cur_score < best_score) { + const score_t last_pos_cost = + (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0; + const score_t last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 0); + score = best_cur_score + last_pos_score; + if (score < best_score) { + best_score = score; + best_path[0] = n; // best eob position + best_path[1] = m; // best node index + best_path[2] = best_prev; // best predecessor + } + } + } + } + + // Fresh start + // Beware! We must preserve in[0]/out[0] value for TYPE_I16_AC case. + if (coeff_type == TYPE_I16_AC) { + memset(in + 1, 0, 15 * sizeof(*in)); + memset(out + 1, 0, 15 * sizeof(*out)); + } else { + memset(in, 0, 16 * sizeof(*in)); + memset(out, 0, 16 * sizeof(*out)); + } + if (best_path[0] == -1) { + return 0; // skip! + } + + { + // Unwind the best path. + // Note: best-prev on terminal node is not necessarily equal to the + // best_prev for non-terminal. So we patch best_path[2] in. + int nz = 0; + int best_node = best_path[1]; + n = best_path[0]; + NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal + + for (; n >= first; --n) { + const Node* const node = &NODE(n, best_node); + const int j = kZigzag[n]; + out[n] = node->sign ? -node->level : node->level; + nz |= node->level; + in[j] = out[n] * mtx->q_[j]; + best_node = node->prev; + } + return (nz != 0); + } +} + +#undef NODE + +//------------------------------------------------------------------------------ +// Performs: difference, transform, quantize, back-transform, add +// all at once. Output is the reconstructed block in *yuv_out, and the +// quantized levels in *levels. + +static int ReconstructIntra16(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd, + uint8_t* WEBP_RESTRICT const yuv_out, + int mode) { + const VP8Encoder* const enc = it->enc_; + const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; + const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; + int nz = 0; + int n; + int16_t tmp[16][16], dc_tmp[16]; + + for (n = 0; n < 16; n += 2) { + VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]); + } + VP8FTransformWHT(tmp[0], dc_tmp); + nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &dqm->y2_) << 24; + + if (DO_TRELLIS_I16 && it->do_trellis_) { + int x, y; + VP8IteratorNzToBytes(it); + for (y = 0, n = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x, ++n) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + const int non_zero = TrellisQuantizeBlock( + enc, tmp[n], rd->y_ac_levels[n], ctx, TYPE_I16_AC, &dqm->y1_, + dqm->lambda_trellis_i16_); + it->top_nz_[x] = it->left_nz_[y] = non_zero; + rd->y_ac_levels[n][0] = 0; + nz |= non_zero << n; + } + } + } else { + for (n = 0; n < 16; n += 2) { + // Zero-out the first coeff, so that: a) nz is correct below, and + // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified. + tmp[n][0] = tmp[n + 1][0] = 0; + nz |= VP8EncQuantize2Blocks(tmp[n], rd->y_ac_levels[n], &dqm->y1_) << n; + assert(rd->y_ac_levels[n + 0][0] == 0); + assert(rd->y_ac_levels[n + 1][0] == 0); + } + } + + // Transform back + VP8TransformWHT(dc_tmp, tmp[0]); + for (n = 0; n < 16; n += 2) { + VP8ITransform(ref + VP8Scan[n], tmp[n], yuv_out + VP8Scan[n], 1); + } + + return nz; +} + +static int ReconstructIntra4(VP8EncIterator* WEBP_RESTRICT const it, + int16_t levels[16], + const uint8_t* WEBP_RESTRICT const src, + uint8_t* WEBP_RESTRICT const yuv_out, + int mode) { + const VP8Encoder* const enc = it->enc_; + const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; + const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; + int nz = 0; + int16_t tmp[16]; + + VP8FTransform(src, ref, tmp); + if (DO_TRELLIS_I4 && it->do_trellis_) { + const int x = it->i4_ & 3, y = it->i4_ >> 2; + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, TYPE_I4_AC, &dqm->y1_, + dqm->lambda_trellis_i4_); + } else { + nz = VP8EncQuantizeBlock(tmp, levels, &dqm->y1_); + } + VP8ITransform(ref, tmp, yuv_out, 0); + return nz; +} + +//------------------------------------------------------------------------------ +// DC-error diffusion + +// Diffusion weights. We under-correct a bit (15/16th of the error is actually +// diffused) to avoid 'rainbow' chessboard pattern of blocks at q~=0. +#define C1 7 // fraction of error sent to the 4x4 block below +#define C2 8 // fraction of error sent to the 4x4 block on the right +#define DSHIFT 4 +#define DSCALE 1 // storage descaling, needed to make the error fit int8_t + +// Quantize as usual, but also compute and return the quantization error. +// Error is already divided by DSHIFT. +static int QuantizeSingle(int16_t* WEBP_RESTRICT const v, + const VP8Matrix* WEBP_RESTRICT const mtx) { + int V = *v; + const int sign = (V < 0); + if (sign) V = -V; + if (V > (int)mtx->zthresh_[0]) { + const int qV = QUANTDIV(V, mtx->iq_[0], mtx->bias_[0]) * mtx->q_[0]; + const int err = (V - qV); + *v = sign ? -qV : qV; + return (sign ? -err : err) >> DSCALE; + } + *v = 0; + return (sign ? -V : V) >> DSCALE; +} + +static void CorrectDCValues(const VP8EncIterator* WEBP_RESTRICT const it, + const VP8Matrix* WEBP_RESTRICT const mtx, + int16_t tmp[][16], + VP8ModeScore* WEBP_RESTRICT const rd) { + // | top[0] | top[1] + // --------+--------+--------- + // left[0] | tmp[0] tmp[1] <-> err0 err1 + // left[1] | tmp[2] tmp[3] err2 err3 + // + // Final errors {err1,err2,err3} are preserved and later restored + // as top[]/left[] on the next block. + int ch; + for (ch = 0; ch <= 1; ++ch) { + const int8_t* const top = it->top_derr_[it->x_][ch]; + const int8_t* const left = it->left_derr_[ch]; + int16_t (* const c)[16] = &tmp[ch * 4]; + int err0, err1, err2, err3; + c[0][0] += (C1 * top[0] + C2 * left[0]) >> (DSHIFT - DSCALE); + err0 = QuantizeSingle(&c[0][0], mtx); + c[1][0] += (C1 * top[1] + C2 * err0) >> (DSHIFT - DSCALE); + err1 = QuantizeSingle(&c[1][0], mtx); + c[2][0] += (C1 * err0 + C2 * left[1]) >> (DSHIFT - DSCALE); + err2 = QuantizeSingle(&c[2][0], mtx); + c[3][0] += (C1 * err1 + C2 * err2) >> (DSHIFT - DSCALE); + err3 = QuantizeSingle(&c[3][0], mtx); + // error 'err' is bounded by mtx->q_[0] which is 132 at max. Hence + // err >> DSCALE will fit in an int8_t type if DSCALE>=1. + assert(abs(err1) <= 127 && abs(err2) <= 127 && abs(err3) <= 127); + rd->derr[ch][0] = (int8_t)err1; + rd->derr[ch][1] = (int8_t)err2; + rd->derr[ch][2] = (int8_t)err3; + } +} + +static void StoreDiffusionErrors(VP8EncIterator* WEBP_RESTRICT const it, + const VP8ModeScore* WEBP_RESTRICT const rd) { + int ch; + for (ch = 0; ch <= 1; ++ch) { + int8_t* const top = it->top_derr_[it->x_][ch]; + int8_t* const left = it->left_derr_[ch]; + left[0] = rd->derr[ch][0]; // restore err1 + left[1] = 3 * rd->derr[ch][2] >> 2; // ... 3/4th of err3 + top[0] = rd->derr[ch][1]; // ... err2 + top[1] = rd->derr[ch][2] - left[1]; // ... 1/4th of err3. + } +} + +#undef C1 +#undef C2 +#undef DSHIFT +#undef DSCALE + +//------------------------------------------------------------------------------ + +static int ReconstructUV(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd, + uint8_t* WEBP_RESTRICT const yuv_out, int mode) { + const VP8Encoder* const enc = it->enc_; + const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; + const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; + const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; + int nz = 0; + int n; + int16_t tmp[8][16]; + + for (n = 0; n < 8; n += 2) { + VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[n], tmp[n]); + } + if (it->top_derr_ != NULL) CorrectDCValues(it, &dqm->uv_, tmp, rd); + + if (DO_TRELLIS_UV && it->do_trellis_) { + int ch, x, y; + for (ch = 0, n = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x, ++n) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + const int non_zero = TrellisQuantizeBlock( + enc, tmp[n], rd->uv_levels[n], ctx, TYPE_CHROMA_A, &dqm->uv_, + dqm->lambda_trellis_uv_); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero; + nz |= non_zero << n; + } + } + } + } else { + for (n = 0; n < 8; n += 2) { + nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n; + } + } + + for (n = 0; n < 8; n += 2) { + VP8ITransform(ref + VP8ScanUV[n], tmp[n], yuv_out + VP8ScanUV[n], 1); + } + return (nz << 16); +} + +//------------------------------------------------------------------------------ +// RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost. +// Pick the mode is lower RD-cost = Rate + lambda * Distortion. + +static void StoreMaxDelta(VP8SegmentInfo* const dqm, const int16_t DCs[16]) { + // We look at the first three AC coefficients to determine what is the average + // delta between each sub-4x4 block. + const int v0 = abs(DCs[1]); + const int v1 = abs(DCs[2]); + const int v2 = abs(DCs[4]); + int max_v = (v1 > v0) ? v1 : v0; + max_v = (v2 > max_v) ? v2 : max_v; + if (max_v > dqm->max_edge_) dqm->max_edge_ = max_v; +} + +static void SwapModeScore(VP8ModeScore** a, VP8ModeScore** b) { + VP8ModeScore* const tmp = *a; + *a = *b; + *b = tmp; +} + +static void SwapPtr(uint8_t** a, uint8_t** b) { + uint8_t* const tmp = *a; + *a = *b; + *b = tmp; +} + +static void SwapOut(VP8EncIterator* const it) { + SwapPtr(&it->yuv_out_, &it->yuv_out2_); +} + +static void PickBestIntra16(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT rd) { + const int kNumBlocks = 16; + VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; + const int lambda = dqm->lambda_i16_; + const int tlambda = dqm->tlambda_; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; + VP8ModeScore rd_tmp; + VP8ModeScore* rd_cur = &rd_tmp; + VP8ModeScore* rd_best = rd; + int mode; + int is_flat = IsFlatSource16(it->yuv_in_ + Y_OFF_ENC); + + rd->mode_i16 = -1; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC; // scratch buffer + rd_cur->mode_i16 = mode; + + // Reconstruct + rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode); + + // Measure RD-score + rd_cur->D = VP8SSE16x16(src, tmp_dst); + rd_cur->SD = + tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) : 0; + rd_cur->H = VP8FixedCostsI16[mode]; + rd_cur->R = VP8GetCostLuma16(it, rd_cur); + if (is_flat) { + // refine the first impression (which was in pixel space) + is_flat = IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16); + if (is_flat) { + // Block is very flat. We put emphasis on the distortion being very low! + rd_cur->D *= 2; + rd_cur->SD *= 2; + } + } + + // Since we always examine Intra16 first, we can overwrite *rd directly. + SetRDScore(lambda, rd_cur); + if (mode == 0 || rd_cur->score < rd_best->score) { + SwapModeScore(&rd_cur, &rd_best); + SwapOut(it); + } + } + if (rd_best != rd) { + memcpy(rd, rd_best, sizeof(*rd)); + } + SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision. + VP8SetIntra16Mode(it, rd->mode_i16); + + // we have a blocky macroblock (only DCs are non-zero) with fairly high + // distortion, record max delta so we can later adjust the minimal filtering + // strength needed to smooth these blocks out. + if ((rd->nz & 0x100ffff) == 0x1000000 && rd->D > dqm->min_disto_) { + StoreMaxDelta(dqm, rd->y_dc_levels); + } +} + +//------------------------------------------------------------------------------ + +// return the cost array corresponding to the surrounding prediction modes. +static const uint16_t* GetCostModeI4(VP8EncIterator* WEBP_RESTRICT const it, + const uint8_t modes[16]) { + const int preds_w = it->enc_->preds_w_; + const int x = (it->i4_ & 3), y = it->i4_ >> 2; + const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1]; + const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4]; + return VP8FixedCostsI4[top][left]; +} + +static int PickBestIntra4(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd) { + const VP8Encoder* const enc = it->enc_; + const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; + const int lambda = dqm->lambda_i4_; + const int tlambda = dqm->tlambda_; + const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC; + uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC; + int total_header_bits = 0; + VP8ModeScore rd_best; + + if (enc->max_i4_header_bits_ == 0) { + return 0; + } + + InitScore(&rd_best); + rd_best.H = 211; // '211' is the value of VP8BitCost(0, 145) + SetRDScore(dqm->lambda_mode_, &rd_best); + VP8IteratorStartI4(it); + do { + const int kNumBlocks = 1; + VP8ModeScore rd_i4; + int mode; + int best_mode = -1; + const uint8_t* const src = src0 + VP8Scan[it->i4_]; + const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4); + uint8_t* best_block = best_blocks + VP8Scan[it->i4_]; + uint8_t* tmp_dst = it->yuv_p_ + I4TMP; // scratch buffer. + + InitScore(&rd_i4); + VP8MakeIntra4Preds(it); + for (mode = 0; mode < NUM_BMODES; ++mode) { + VP8ModeScore rd_tmp; + int16_t tmp_levels[16]; + + // Reconstruct + rd_tmp.nz = + ReconstructIntra4(it, tmp_levels, src, tmp_dst, mode) << it->i4_; + + // Compute RD-score + rd_tmp.D = VP8SSE4x4(src, tmp_dst); + rd_tmp.SD = + tlambda ? MULT_8B(tlambda, VP8TDisto4x4(src, tmp_dst, kWeightY)) + : 0; + rd_tmp.H = mode_costs[mode]; + + // Add flatness penalty, to avoid flat area to be mispredicted + // by a complex mode. + if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) { + rd_tmp.R = FLATNESS_PENALTY * kNumBlocks; + } else { + rd_tmp.R = 0; + } + + // early-out check + SetRDScore(lambda, &rd_tmp); + if (best_mode >= 0 && rd_tmp.score >= rd_i4.score) continue; + + // finish computing score + rd_tmp.R += VP8GetCostLuma4(it, tmp_levels); + SetRDScore(lambda, &rd_tmp); + + if (best_mode < 0 || rd_tmp.score < rd_i4.score) { + CopyScore(&rd_i4, &rd_tmp); + best_mode = mode; + SwapPtr(&tmp_dst, &best_block); + memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels, + sizeof(rd_best.y_ac_levels[it->i4_])); + } + } + SetRDScore(dqm->lambda_mode_, &rd_i4); + AddScore(&rd_best, &rd_i4); + if (rd_best.score >= rd->score) { + return 0; + } + total_header_bits += (int)rd_i4.H; // <- equal to mode_costs[best_mode]; + if (total_header_bits > enc->max_i4_header_bits_) { + return 0; + } + // Copy selected samples if not in the right place already. + if (best_block != best_blocks + VP8Scan[it->i4_]) { + VP8Copy4x4(best_block, best_blocks + VP8Scan[it->i4_]); + } + rd->modes_i4[it->i4_] = best_mode; + it->top_nz_[it->i4_ & 3] = it->left_nz_[it->i4_ >> 2] = (rd_i4.nz ? 1 : 0); + } while (VP8IteratorRotateI4(it, best_blocks)); + + // finalize state + CopyScore(rd, &rd_best); + VP8SetIntra4Mode(it, rd->modes_i4); + SwapOut(it); + memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels)); + return 1; // select intra4x4 over intra16x16 +} + +//------------------------------------------------------------------------------ + +static void PickBestUV(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd) { + const int kNumBlocks = 8; + const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; + const int lambda = dqm->lambda_uv_; + const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; + uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC; // scratch buffer + uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC; + uint8_t* dst = dst0; + VP8ModeScore rd_best; + int mode; + + rd->mode_uv = -1; + InitScore(&rd_best); + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + VP8ModeScore rd_uv; + + // Reconstruct + rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode); + + // Compute RD-score + rd_uv.D = VP8SSE16x8(src, tmp_dst); + rd_uv.SD = 0; // not calling TDisto here: it tends to flatten areas. + rd_uv.H = VP8FixedCostsUV[mode]; + rd_uv.R = VP8GetCostUV(it, &rd_uv); + if (mode > 0 && IsFlat(rd_uv.uv_levels[0], kNumBlocks, FLATNESS_LIMIT_UV)) { + rd_uv.R += FLATNESS_PENALTY * kNumBlocks; + } + + SetRDScore(lambda, &rd_uv); + if (mode == 0 || rd_uv.score < rd_best.score) { + CopyScore(&rd_best, &rd_uv); + rd->mode_uv = mode; + memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels)); + if (it->top_derr_ != NULL) { + memcpy(rd->derr, rd_uv.derr, sizeof(rd_uv.derr)); + } + SwapPtr(&dst, &tmp_dst); + } + } + VP8SetIntraUVMode(it, rd->mode_uv); + AddScore(rd, &rd_best); + if (dst != dst0) { // copy 16x8 block if needed + VP8Copy16x8(dst, dst0); + } + if (it->top_derr_ != NULL) { // store diffusion errors for next block + StoreDiffusionErrors(it, rd); + } +} + +//------------------------------------------------------------------------------ +// Final reconstruction and quantization. + +static void SimpleQuantize(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd) { + const VP8Encoder* const enc = it->enc_; + const int is_i16 = (it->mb_->type_ == 1); + int nz = 0; + + if (is_i16) { + nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]); + } else { + VP8IteratorStartI4(it); + do { + const int mode = + it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_]; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; + uint8_t* const dst = it->yuv_out_ + Y_OFF_ENC + VP8Scan[it->i4_]; + VP8MakeIntra4Preds(it); + nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], + src, dst, mode) << it->i4_; + } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF_ENC)); + } + + nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_); + rd->nz = nz; +} + +// Refine intra16/intra4 sub-modes based on distortion only (not rate). +static void RefineUsingDistortion(VP8EncIterator* WEBP_RESTRICT const it, + int try_both_modes, int refine_uv_mode, + VP8ModeScore* WEBP_RESTRICT const rd) { + score_t best_score = MAX_COST; + int nz = 0; + int mode; + int is_i16 = try_both_modes || (it->mb_->type_ == 1); + + const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; + // Some empiric constants, of approximate order of magnitude. + const int lambda_d_i16 = 106; + const int lambda_d_i4 = 11; + const int lambda_d_uv = 120; + score_t score_i4 = dqm->i4_penalty_; + score_t i4_bit_sum = 0; + const score_t bit_limit = try_both_modes ? it->enc_->mb_header_limit_ + : MAX_COST; // no early-out allowed + + if (is_i16) { // First, evaluate Intra16 distortion + int best_mode = -1; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; + const score_t score = (score_t)VP8SSE16x16(src, ref) * RD_DISTO_MULT + + VP8FixedCostsI16[mode] * lambda_d_i16; + if (mode > 0 && VP8FixedCostsI16[mode] > bit_limit) { + continue; + } + + if (score < best_score) { + best_mode = mode; + best_score = score; + } + } + if (it->x_ == 0 || it->y_ == 0) { + // avoid starting a checkerboard resonance from the border. See bug #432. + if (IsFlatSource16(src)) { + best_mode = (it->x_ == 0) ? 0 : 2; + try_both_modes = 0; // stick to i16 + } + } + VP8SetIntra16Mode(it, best_mode); + // we'll reconstruct later, if i16 mode actually gets selected + } + + // Next, evaluate Intra4 + if (try_both_modes || !is_i16) { + // We don't evaluate the rate here, but just account for it through a + // constant penalty (i4 mode usually needs more bits compared to i16). + is_i16 = 0; + VP8IteratorStartI4(it); + do { + int best_i4_mode = -1; + score_t best_i4_score = MAX_COST; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; + const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4); + + VP8MakeIntra4Preds(it); + for (mode = 0; mode < NUM_BMODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; + const score_t score = VP8SSE4x4(src, ref) * RD_DISTO_MULT + + mode_costs[mode] * lambda_d_i4; + if (score < best_i4_score) { + best_i4_mode = mode; + best_i4_score = score; + } + } + i4_bit_sum += mode_costs[best_i4_mode]; + rd->modes_i4[it->i4_] = best_i4_mode; + score_i4 += best_i4_score; + if (score_i4 >= best_score || i4_bit_sum > bit_limit) { + // Intra4 won't be better than Intra16. Bail out and pick Intra16. + is_i16 = 1; + break; + } else { // reconstruct partial block inside yuv_out2_ buffer + uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC + VP8Scan[it->i4_]; + nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], + src, tmp_dst, best_i4_mode) << it->i4_; + } + } while (VP8IteratorRotateI4(it, it->yuv_out2_ + Y_OFF_ENC)); + } + + // Final reconstruction, depending on which mode is selected. + if (!is_i16) { + VP8SetIntra4Mode(it, rd->modes_i4); + SwapOut(it); + best_score = score_i4; + } else { + nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]); + } + + // ... and UV! + if (refine_uv_mode) { + int best_mode = -1; + score_t best_uv_score = MAX_COST; + const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; + const score_t score = VP8SSE16x8(src, ref) * RD_DISTO_MULT + + VP8FixedCostsUV[mode] * lambda_d_uv; + if (score < best_uv_score) { + best_mode = mode; + best_uv_score = score; + } + } + VP8SetIntraUVMode(it, best_mode); + } + nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_); + + rd->nz = nz; + rd->score = best_score; +} + +//------------------------------------------------------------------------------ +// Entry point + +int VP8Decimate(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd, + VP8RDLevel rd_opt) { + int is_skipped; + const int method = it->enc_->method_; + + InitScore(rd); + + // We can perform predictions for Luma16x16 and Chroma8x8 already. + // Luma4x4 predictions needs to be done as-we-go. + VP8MakeLuma16Preds(it); + VP8MakeChroma8Preds(it); + + if (rd_opt > RD_OPT_NONE) { + it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL); + PickBestIntra16(it, rd); + if (method >= 2) { + PickBestIntra4(it, rd); + } + PickBestUV(it, rd); + if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now + it->do_trellis_ = 1; + SimpleQuantize(it, rd); + } + } else { + // At this point we have heuristically decided intra16 / intra4. + // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower). + // For method <= 1, we don't re-examine the decision but just go ahead with + // quantization/reconstruction. + RefineUsingDistortion(it, (method >= 2), (method >= 1), rd); + } + is_skipped = (rd->nz == 0); + VP8SetSkip(it, is_skipped); + return is_skipped; +} diff --git a/libraries/webp/src/enc/syntax_enc.c b/libraries/webp/src/enc/syntax_enc.c new file mode 100644 index 0000000000..0149c85b64 --- /dev/null +++ b/libraries/webp/src/enc/syntax_enc.c @@ -0,0 +1,392 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Header syntax writing +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/utils/utils.h" +#include "include/webp/format_constants.h" // RIFF constants +#include "include/webp/mux_types.h" // ALPHA_FLAG +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Helper functions + +static int IsVP8XNeeded(const VP8Encoder* const enc) { + return !!enc->has_alpha_; // Currently the only case when VP8X is needed. + // This could change in the future. +} + +static int PutPaddingByte(const WebPPicture* const pic) { + const uint8_t pad_byte[1] = { 0 }; + return !!pic->writer(pad_byte, 1, pic); +} + +//------------------------------------------------------------------------------ +// Writers for header's various pieces (in order of appearance) + +static WebPEncodingError PutRIFFHeader(const VP8Encoder* const enc, + size_t riff_size) { + const WebPPicture* const pic = enc->pic_; + uint8_t riff[RIFF_HEADER_SIZE] = { + 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P' + }; + assert(riff_size == (uint32_t)riff_size); + PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); + if (!pic->writer(riff, sizeof(riff), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) { + const WebPPicture* const pic = enc->pic_; + uint8_t vp8x[CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE] = { + 'V', 'P', '8', 'X' + }; + uint32_t flags = 0; + + assert(IsVP8XNeeded(enc)); + assert(pic->width >= 1 && pic->height >= 1); + assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE); + + if (enc->has_alpha_) { + flags |= ALPHA_FLAG; + } + + PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE); + PutLE32(vp8x + CHUNK_HEADER_SIZE, flags); + PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1); + PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1); + if (!pic->writer(vp8x, sizeof(vp8x), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutAlphaChunk(const VP8Encoder* const enc) { + const WebPPicture* const pic = enc->pic_; + uint8_t alpha_chunk_hdr[CHUNK_HEADER_SIZE] = { + 'A', 'L', 'P', 'H' + }; + + assert(enc->has_alpha_); + + // Alpha chunk header. + PutLE32(alpha_chunk_hdr + TAG_SIZE, enc->alpha_data_size_); + if (!pic->writer(alpha_chunk_hdr, sizeof(alpha_chunk_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + + // Alpha chunk data. + if (!pic->writer(enc->alpha_data_, enc->alpha_data_size_, pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + + // Padding. + if ((enc->alpha_data_size_ & 1) && !PutPaddingByte(pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8Header(const WebPPicture* const pic, + size_t vp8_size) { + uint8_t vp8_chunk_hdr[CHUNK_HEADER_SIZE] = { + 'V', 'P', '8', ' ' + }; + assert(vp8_size == (uint32_t)vp8_size); + PutLE32(vp8_chunk_hdr + TAG_SIZE, (uint32_t)vp8_size); + if (!pic->writer(vp8_chunk_hdr, sizeof(vp8_chunk_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8FrameHeader(const WebPPicture* const pic, + int profile, size_t size0) { + uint8_t vp8_frm_hdr[VP8_FRAME_HEADER_SIZE]; + uint32_t bits; + + if (size0 >= VP8_MAX_PARTITION0_SIZE) { // partition #0 is too big to fit + return VP8_ENC_ERROR_PARTITION0_OVERFLOW; + } + + // Paragraph 9.1. + bits = 0 // keyframe (1b) + | (profile << 1) // profile (3b) + | (1 << 4) // visible (1b) + | ((uint32_t)size0 << 5); // partition length (19b) + vp8_frm_hdr[0] = (bits >> 0) & 0xff; + vp8_frm_hdr[1] = (bits >> 8) & 0xff; + vp8_frm_hdr[2] = (bits >> 16) & 0xff; + // signature + vp8_frm_hdr[3] = (VP8_SIGNATURE >> 16) & 0xff; + vp8_frm_hdr[4] = (VP8_SIGNATURE >> 8) & 0xff; + vp8_frm_hdr[5] = (VP8_SIGNATURE >> 0) & 0xff; + // dimensions + vp8_frm_hdr[6] = pic->width & 0xff; + vp8_frm_hdr[7] = pic->width >> 8; + vp8_frm_hdr[8] = pic->height & 0xff; + vp8_frm_hdr[9] = pic->height >> 8; + + if (!pic->writer(vp8_frm_hdr, sizeof(vp8_frm_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +// WebP Headers. +static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0, + size_t vp8_size, size_t riff_size) { + WebPPicture* const pic = enc->pic_; + WebPEncodingError err = VP8_ENC_OK; + + // RIFF header. + err = PutRIFFHeader(enc, riff_size); + if (err != VP8_ENC_OK) goto Error; + + // VP8X. + if (IsVP8XNeeded(enc)) { + err = PutVP8XHeader(enc); + if (err != VP8_ENC_OK) goto Error; + } + + // Alpha. + if (enc->has_alpha_) { + err = PutAlphaChunk(enc); + if (err != VP8_ENC_OK) goto Error; + } + + // VP8 header. + err = PutVP8Header(pic, vp8_size); + if (err != VP8_ENC_OK) goto Error; + + // VP8 frame header. + err = PutVP8FrameHeader(pic, enc->profile_, size0); + if (err != VP8_ENC_OK) goto Error; + + // All OK. + return 1; + + // Error. + Error: + return WebPEncodingSetError(pic, err); +} + +// Segmentation header +static void PutSegmentHeader(VP8BitWriter* const bw, + const VP8Encoder* const enc) { + const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; + const VP8EncProba* const proba = &enc->proba_; + if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) { + // We always 'update' the quant and filter strength values + const int update_data = 1; + int s; + VP8PutBitUniform(bw, hdr->update_map_); + if (VP8PutBitUniform(bw, update_data)) { + // we always use absolute values, not relative ones + VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.) + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7); + } + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6); + } + } + if (hdr->update_map_) { + for (s = 0; s < 3; ++s) { + if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) { + VP8PutBits(bw, proba->segments_[s], 8); + } + } + } + } +} + +// Filtering parameters header +static void PutFilterHeader(VP8BitWriter* const bw, + const VP8EncFilterHeader* const hdr) { + const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0); + VP8PutBitUniform(bw, hdr->simple_); + VP8PutBits(bw, hdr->level_, 6); + VP8PutBits(bw, hdr->sharpness_, 3); + if (VP8PutBitUniform(bw, use_lf_delta)) { + // '0' is the default value for i4x4_lf_delta_ at frame #0. + const int need_update = (hdr->i4x4_lf_delta_ != 0); + if (VP8PutBitUniform(bw, need_update)) { + // we don't use ref_lf_delta => emit four 0 bits + VP8PutBits(bw, 0, 4); + // we use mode_lf_delta for i4x4 + VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6); + VP8PutBits(bw, 0, 3); // all others unused + } + } +} + +// Nominal quantization parameters +static void PutQuant(VP8BitWriter* const bw, + const VP8Encoder* const enc) { + VP8PutBits(bw, enc->base_quant_, 7); + VP8PutSignedBits(bw, enc->dq_y1_dc_, 4); + VP8PutSignedBits(bw, enc->dq_y2_dc_, 4); + VP8PutSignedBits(bw, enc->dq_y2_ac_, 4); + VP8PutSignedBits(bw, enc->dq_uv_dc_, 4); + VP8PutSignedBits(bw, enc->dq_uv_ac_, 4); +} + +// Partition sizes +static int EmitPartitionsSize(const VP8Encoder* const enc, + WebPPicture* const pic) { + uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)]; + int p; + for (p = 0; p < enc->num_parts_ - 1; ++p) { + const size_t part_size = VP8BitWriterSize(enc->parts_ + p); + if (part_size >= VP8_MAX_PARTITION_SIZE) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW); + } + buf[3 * p + 0] = (part_size >> 0) & 0xff; + buf[3 * p + 1] = (part_size >> 8) & 0xff; + buf[3 * p + 2] = (part_size >> 16) & 0xff; + } + if (p && !pic->writer(buf, 3 * p, pic)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE); + } + return 1; +} + +//------------------------------------------------------------------------------ + +static int GeneratePartition0(VP8Encoder* const enc) { + VP8BitWriter* const bw = &enc->bw_; + const int mb_size = enc->mb_w_ * enc->mb_h_; + uint64_t pos1, pos2, pos3; + + pos1 = VP8BitWriterPos(bw); + if (!VP8BitWriterInit(bw, mb_size * 7 / 8)) { // ~7 bits per macroblock + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + VP8PutBitUniform(bw, 0); // colorspace + VP8PutBitUniform(bw, 0); // clamp type + + PutSegmentHeader(bw, enc); + PutFilterHeader(bw, &enc->filter_hdr_); + VP8PutBits(bw, enc->num_parts_ == 8 ? 3 : + enc->num_parts_ == 4 ? 2 : + enc->num_parts_ == 2 ? 1 : 0, 2); + PutQuant(bw, enc); + VP8PutBitUniform(bw, 0); // no proba update + VP8WriteProbas(bw, &enc->proba_); + pos2 = VP8BitWriterPos(bw); + VP8CodeIntraModes(enc); + VP8BitWriterFinish(bw); + + pos3 = VP8BitWriterPos(bw); + +#if !defined(WEBP_DISABLE_STATS) + if (enc->pic_->stats) { + enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3); + enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3); + enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_; + } +#else + (void)pos1; + (void)pos2; + (void)pos3; +#endif + if (bw->error_) { + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return 1; +} + +void VP8EncFreeBitWriters(VP8Encoder* const enc) { + int p; + VP8BitWriterWipeOut(&enc->bw_); + for (p = 0; p < enc->num_parts_; ++p) { + VP8BitWriterWipeOut(enc->parts_ + p); + } +} + +int VP8EncWrite(VP8Encoder* const enc) { + WebPPicture* const pic = enc->pic_; + VP8BitWriter* const bw = &enc->bw_; + const int task_percent = 19; + const int percent_per_part = task_percent / enc->num_parts_; + const int final_percent = enc->percent_ + task_percent; + int ok = 0; + size_t vp8_size, pad, riff_size; + int p; + + // Partition #0 with header and partition sizes + ok = GeneratePartition0(enc); + if (!ok) return 0; + + // Compute VP8 size + vp8_size = VP8_FRAME_HEADER_SIZE + + VP8BitWriterSize(bw) + + 3 * (enc->num_parts_ - 1); + for (p = 0; p < enc->num_parts_; ++p) { + vp8_size += VP8BitWriterSize(enc->parts_ + p); + } + pad = vp8_size & 1; + vp8_size += pad; + + // Compute RIFF size + // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size. + riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8_size; + if (IsVP8XNeeded(enc)) { // Add size for: VP8X header + data. + riff_size += CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + } + if (enc->has_alpha_) { // Add size for: ALPH header + data. + const uint32_t padded_alpha_size = enc->alpha_data_size_ + + (enc->alpha_data_size_ & 1); + riff_size += CHUNK_HEADER_SIZE + padded_alpha_size; + } + // RIFF size should fit in 32-bits. + if (riff_size > 0xfffffffeU) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG); + } + + // Emit headers and partition #0 + { + const uint8_t* const part0 = VP8BitWriterBuf(bw); + const size_t size0 = VP8BitWriterSize(bw); + ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size) + && pic->writer(part0, size0, pic) + && EmitPartitionsSize(enc, pic); + VP8BitWriterWipeOut(bw); // will free the internal buffer. + } + + // Token partitions + for (p = 0; p < enc->num_parts_; ++p) { + const uint8_t* const buf = VP8BitWriterBuf(enc->parts_ + p); + const size_t size = VP8BitWriterSize(enc->parts_ + p); + if (size) ok = ok && pic->writer(buf, size, pic); + VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer. + ok = ok && WebPReportProgress(pic, enc->percent_ + percent_per_part, + &enc->percent_); + } + + // Padding byte + if (ok && pad) { + ok = PutPaddingByte(pic); + } + + enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size); + ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_); + if (!ok) WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE); + return ok; +} + +//------------------------------------------------------------------------------ + diff --git a/libraries/webp/src/enc/token_enc.c b/libraries/webp/src/enc/token_enc.c new file mode 100644 index 0000000000..3a2192acac --- /dev/null +++ b/libraries/webp/src/enc/token_enc.c @@ -0,0 +1,262 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Paginated token buffer +// +// A 'token' is a bit value associated with a probability, either fixed +// or a later-to-be-determined after statistics have been collected. +// For dynamic probability, we just record the slot id (idx) for the probability +// value in the final probability array (uint8_t* probas in VP8EmitTokens). +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +#if !defined(DISABLE_TOKEN_BUFFER) + +// we use pages to reduce the number of memcpy() +#define MIN_PAGE_SIZE 8192 // minimum number of token per page +#define FIXED_PROBA_BIT (1u << 14) + +typedef uint16_t token_t; // bit #15: bit value + // bit #14: flags for constant proba or idx + // bits #0..13: slot or constant proba +struct VP8Tokens { + VP8Tokens* next_; // pointer to next page +}; +// Token data is located in memory just after the next_ field. +// This macro is used to return their address and hide the trick. +#define TOKEN_DATA(p) ((const token_t*)&(p)[1]) + +//------------------------------------------------------------------------------ + +void VP8TBufferInit(VP8TBuffer* const b, int page_size) { + b->tokens_ = NULL; + b->pages_ = NULL; + b->last_page_ = &b->pages_; + b->left_ = 0; + b->page_size_ = (page_size < MIN_PAGE_SIZE) ? MIN_PAGE_SIZE : page_size; + b->error_ = 0; +} + +void VP8TBufferClear(VP8TBuffer* const b) { + if (b != NULL) { + VP8Tokens* p = b->pages_; + while (p != NULL) { + VP8Tokens* const next = p->next_; + WebPSafeFree(p); + p = next; + } + VP8TBufferInit(b, b->page_size_); + } +} + +static int TBufferNewPage(VP8TBuffer* const b) { + VP8Tokens* page = NULL; + if (!b->error_) { + const size_t size = sizeof(*page) + b->page_size_ * sizeof(token_t); + page = (VP8Tokens*)WebPSafeMalloc(1ULL, size); + } + if (page == NULL) { + b->error_ = 1; + return 0; + } + page->next_ = NULL; + + *b->last_page_ = page; + b->last_page_ = &page->next_; + b->left_ = b->page_size_; + b->tokens_ = (token_t*)TOKEN_DATA(page); + return 1; +} + +//------------------------------------------------------------------------------ + +#define TOKEN_ID(t, b, ctx) \ + (NUM_PROBAS * ((ctx) + NUM_CTX * ((b) + NUM_BANDS * (t)))) + +static WEBP_INLINE uint32_t AddToken(VP8TBuffer* const b, uint32_t bit, + uint32_t proba_idx, + proba_t* const stats) { + assert(proba_idx < FIXED_PROBA_BIT); + assert(bit <= 1); + if (b->left_ > 0 || TBufferNewPage(b)) { + const int slot = --b->left_; + b->tokens_[slot] = (bit << 15) | proba_idx; + } + VP8RecordStats(bit, stats); + return bit; +} + +static WEBP_INLINE void AddConstantToken(VP8TBuffer* const b, + uint32_t bit, uint32_t proba) { + assert(proba < 256); + assert(bit <= 1); + if (b->left_ > 0 || TBufferNewPage(b)) { + const int slot = --b->left_; + b->tokens_[slot] = (bit << 15) | FIXED_PROBA_BIT | proba; + } +} + +int VP8RecordCoeffTokens(int ctx, const struct VP8Residual* const res, + VP8TBuffer* const tokens) { + const int16_t* const coeffs = res->coeffs; + const int coeff_type = res->coeff_type; + const int last = res->last; + int n = res->first; + uint32_t base_id = TOKEN_ID(coeff_type, n, ctx); + // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 + proba_t* s = res->stats[n][ctx]; + if (!AddToken(tokens, last >= 0, base_id + 0, s + 0)) { + return 0; + } + + while (n < 16) { + const int c = coeffs[n++]; + const int sign = c < 0; + const uint32_t v = sign ? -c : c; + if (!AddToken(tokens, v != 0, base_id + 1, s + 1)) { + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 0); // ctx=0 + s = res->stats[VP8EncBands[n]][0]; + continue; + } + if (!AddToken(tokens, v > 1, base_id + 2, s + 2)) { + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 1); // ctx=1 + s = res->stats[VP8EncBands[n]][1]; + } else { + if (!AddToken(tokens, v > 4, base_id + 3, s + 3)) { + if (AddToken(tokens, v != 2, base_id + 4, s + 4)) { + AddToken(tokens, v == 4, base_id + 5, s + 5); + } + } else if (!AddToken(tokens, v > 10, base_id + 6, s + 6)) { + if (!AddToken(tokens, v > 6, base_id + 7, s + 7)) { + AddConstantToken(tokens, v == 6, 159); + } else { + AddConstantToken(tokens, v >= 9, 165); + AddConstantToken(tokens, !(v & 1), 145); + } + } else { + int mask; + const uint8_t* tab; + uint32_t residue = v - 3; + if (residue < (8 << 1)) { // VP8Cat3 (3b) + AddToken(tokens, 0, base_id + 8, s + 8); + AddToken(tokens, 0, base_id + 9, s + 9); + residue -= (8 << 0); + mask = 1 << 2; + tab = VP8Cat3; + } else if (residue < (8 << 2)) { // VP8Cat4 (4b) + AddToken(tokens, 0, base_id + 8, s + 8); + AddToken(tokens, 1, base_id + 9, s + 9); + residue -= (8 << 1); + mask = 1 << 3; + tab = VP8Cat4; + } else if (residue < (8 << 3)) { // VP8Cat5 (5b) + AddToken(tokens, 1, base_id + 8, s + 8); + AddToken(tokens, 0, base_id + 10, s + 9); + residue -= (8 << 2); + mask = 1 << 4; + tab = VP8Cat5; + } else { // VP8Cat6 (11b) + AddToken(tokens, 1, base_id + 8, s + 8); + AddToken(tokens, 1, base_id + 10, s + 9); + residue -= (8 << 3); + mask = 1 << 10; + tab = VP8Cat6; + } + while (mask) { + AddConstantToken(tokens, !!(residue & mask), *tab++); + mask >>= 1; + } + } + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 2); // ctx=2 + s = res->stats[VP8EncBands[n]][2]; + } + AddConstantToken(tokens, sign, 128); + if (n == 16 || !AddToken(tokens, n <= last, base_id + 0, s + 0)) { + return 1; // EOB + } + } + return 1; +} + +#undef TOKEN_ID + +//------------------------------------------------------------------------------ +// Final coding pass, with known probabilities + +int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, + const uint8_t* const probas, int final_pass) { + const VP8Tokens* p = b->pages_; + assert(!b->error_); + while (p != NULL) { + const VP8Tokens* const next = p->next_; + const int N = (next == NULL) ? b->left_ : 0; + int n = b->page_size_; + const token_t* const tokens = TOKEN_DATA(p); + while (n-- > N) { + const token_t token = tokens[n]; + const int bit = (token >> 15) & 1; + if (token & FIXED_PROBA_BIT) { + VP8PutBit(bw, bit, token & 0xffu); // constant proba + } else { + VP8PutBit(bw, bit, probas[token & 0x3fffu]); + } + } + if (final_pass) WebPSafeFree((void*)p); + p = next; + } + if (final_pass) b->pages_ = NULL; + return 1; +} + +// Size estimation +size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas) { + size_t size = 0; + const VP8Tokens* p = b->pages_; + assert(!b->error_); + while (p != NULL) { + const VP8Tokens* const next = p->next_; + const int N = (next == NULL) ? b->left_ : 0; + int n = b->page_size_; + const token_t* const tokens = TOKEN_DATA(p); + while (n-- > N) { + const token_t token = tokens[n]; + const int bit = token & (1 << 15); + if (token & FIXED_PROBA_BIT) { + size += VP8BitCost(bit, token & 0xffu); + } else { + size += VP8BitCost(bit, probas[token & 0x3fffu]); + } + } + p = next; + } + return size; +} + +//------------------------------------------------------------------------------ + +#else // DISABLE_TOKEN_BUFFER + +void VP8TBufferInit(VP8TBuffer* const b, int page_size) { + (void)b; + (void)page_size; +} +void VP8TBufferClear(VP8TBuffer* const b) { + (void)b; +} + +#endif // !DISABLE_TOKEN_BUFFER + diff --git a/libraries/webp/src/enc/tree_enc.c b/libraries/webp/src/enc/tree_enc.c new file mode 100644 index 0000000000..64ed28360b --- /dev/null +++ b/libraries/webp/src/enc/tree_enc.c @@ -0,0 +1,504 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Coding of token probabilities, intra modes and segments. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Default probabilities + +// Paragraph 13.5 +const uint8_t + VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { + { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, + { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, + { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } + }, + { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, + { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, + { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, + }, + { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, + { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, + { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, + }, + { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, + { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, + { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } + }, + { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, + { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, + { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } + }, + { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, + { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, + { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } + }, + { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, + { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, + { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } + }, + { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, + { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, + { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } + }, + { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, + { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, + { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } + }, + { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, + { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, + { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } + }, + { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, + { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, + { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } + }, + { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, + { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, + { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } + }, + { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, + { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, + { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } + }, + { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } + } + }, + { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, + { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, + { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } + }, + { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, + { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, + { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } + }, + { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, + { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, + { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } + }, + { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, + { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, + { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, + { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } + }, + { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, + { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, + { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } + }, + { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, + { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, + { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } + }, + { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, + { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, + { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } + }, + { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, + { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, + { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } + }, + { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, + { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, + { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } + }, + { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, + { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, + { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } + }, + { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + } + } +}; + +void VP8DefaultProbas(VP8Encoder* const enc) { + VP8EncProba* const probas = &enc->proba_; + probas->use_skip_proba_ = 0; + memset(probas->segments_, 255u, sizeof(probas->segments_)); + memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0)); + // Note: we could hard-code the level_costs_ corresponding to VP8CoeffsProba0, + // but that's ~11k of static data. Better call VP8CalculateLevelCosts() later. + probas->dirty_ = 1; +} + +// Paragraph 11.5. 900bytes. +static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = { + { { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, + { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, + { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, + { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, + { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, + { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, + { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, + { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, + { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, + { 81, 40, 11, 96, 182, 84, 29, 16, 36 } }, + { { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, + { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, + { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, + { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, + { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, + { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, + { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, + { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, + { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, + { 66, 45, 25, 102, 197, 189, 23, 18, 22 } }, + { { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, + { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, + { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, + { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, + { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, + { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, + { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, + { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, + { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, + { 62, 18, 78, 95, 85, 57, 50, 48, 51 } }, + { { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, + { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, + { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, + { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, + { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, + { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, + { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, + { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, + { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, + { 51, 50, 17, 168, 209, 192, 23, 25, 82 } }, + { { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, + { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, + { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, + { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, + { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, + { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, + { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, + { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, + { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, + { 87, 37, 9, 115, 59, 77, 64, 21, 47 } }, + { { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, + { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, + { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, + { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, + { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, + { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, + { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, + { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, + { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, + { 55, 38, 70, 124, 73, 102, 1, 34, 98 } }, + { { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, + { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, + { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, + { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, + { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, + { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, + { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, + { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, + { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, + { 117, 20, 15, 36, 163, 128, 68, 1, 26 } }, + { { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, + { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, + { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, + { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, + { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, + { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, + { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, + { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, + { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, + { 58, 15, 20, 82, 135, 57, 26, 121, 40 } }, + { { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, + { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, + { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, + { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, + { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, + { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, + { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, + { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, + { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, + { 35, 27, 10, 146, 174, 171, 12, 26, 128 } }, + { { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, + { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, + { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, + { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, + { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, + { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, + { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, + { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, + { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, + { 112, 19, 12, 61, 195, 128, 48, 4, 24 } } +}; + +static int PutI4Mode(VP8BitWriter* const bw, int mode, + const uint8_t* const prob) { + if (VP8PutBit(bw, mode != B_DC_PRED, prob[0])) { + if (VP8PutBit(bw, mode != B_TM_PRED, prob[1])) { + if (VP8PutBit(bw, mode != B_VE_PRED, prob[2])) { + if (!VP8PutBit(bw, mode >= B_LD_PRED, prob[3])) { + if (VP8PutBit(bw, mode != B_HE_PRED, prob[4])) { + VP8PutBit(bw, mode != B_RD_PRED, prob[5]); + } + } else { + if (VP8PutBit(bw, mode != B_LD_PRED, prob[6])) { + if (VP8PutBit(bw, mode != B_VL_PRED, prob[7])) { + VP8PutBit(bw, mode != B_HD_PRED, prob[8]); + } + } + } + } + } + } + return mode; +} + +static void PutI16Mode(VP8BitWriter* const bw, int mode) { + if (VP8PutBit(bw, (mode == TM_PRED || mode == H_PRED), 156)) { + VP8PutBit(bw, mode == TM_PRED, 128); // TM or HE + } else { + VP8PutBit(bw, mode == V_PRED, 163); // VE or DC + } +} + +static void PutUVMode(VP8BitWriter* const bw, int uv_mode) { + if (VP8PutBit(bw, uv_mode != DC_PRED, 142)) { + if (VP8PutBit(bw, uv_mode != V_PRED, 114)) { + VP8PutBit(bw, uv_mode != H_PRED, 183); // else: TM_PRED + } + } +} + +static void PutSegment(VP8BitWriter* const bw, int s, const uint8_t* p) { + if (VP8PutBit(bw, s >= 2, p[0])) p += 1; + VP8PutBit(bw, s & 1, p[1]); +} + +void VP8CodeIntraModes(VP8Encoder* const enc) { + VP8BitWriter* const bw = &enc->bw_; + VP8EncIterator it; + VP8IteratorInit(enc, &it); + do { + const VP8MBInfo* const mb = it.mb_; + const uint8_t* preds = it.preds_; + if (enc->segment_hdr_.update_map_) { + PutSegment(bw, mb->segment_, enc->proba_.segments_); + } + if (enc->proba_.use_skip_proba_) { + VP8PutBit(bw, mb->skip_, enc->proba_.skip_proba_); + } + if (VP8PutBit(bw, (mb->type_ != 0), 145)) { // i16x16 + PutI16Mode(bw, preds[0]); + } else { + const int preds_w = enc->preds_w_; + const uint8_t* top_pred = preds - preds_w; + int x, y; + for (y = 0; y < 4; ++y) { + int left = preds[-1]; + for (x = 0; x < 4; ++x) { + const uint8_t* const probas = kBModesProba[top_pred[x]][left]; + left = PutI4Mode(bw, preds[x], probas); + } + top_pred = preds; + preds += preds_w; + } + } + PutUVMode(bw, mb->uv_mode_); + } while (VP8IteratorNext(&it)); +} + +//------------------------------------------------------------------------------ +// Paragraph 13 + +const uint8_t + VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { + { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, + { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } + }, + { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + } +}; + +void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas) { + int t, b, c, p; + for (t = 0; t < NUM_TYPES; ++t) { + for (b = 0; b < NUM_BANDS; ++b) { + for (c = 0; c < NUM_CTX; ++c) { + for (p = 0; p < NUM_PROBAS; ++p) { + const uint8_t p0 = probas->coeffs_[t][b][c][p]; + const int update = (p0 != VP8CoeffsProba0[t][b][c][p]); + if (VP8PutBit(bw, update, VP8CoeffsUpdateProba[t][b][c][p])) { + VP8PutBits(bw, p0, 8); + } + } + } + } + } + if (VP8PutBitUniform(bw, probas->use_skip_proba_)) { + VP8PutBits(bw, probas->skip_proba_, 8); + } +} + diff --git a/libraries/webp/src/enc/vp8i_enc.h b/libraries/webp/src/enc/vp8i_enc.h new file mode 100644 index 0000000000..553008816f --- /dev/null +++ b/libraries/webp/src/enc/vp8i_enc.h @@ -0,0 +1,523 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_ENC_VP8I_ENC_H_ +#define WEBP_ENC_VP8I_ENC_H_ + +#include // for memcpy() +#include "src/dec/common_dec.h" +#include "src/dsp/dsp.h" +#include "src/utils/bit_writer_utils.h" +#include "src/utils/thread_utils.h" +#include "src/utils/utils.h" +#include "include/webp/encode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Various defines and enums + +// version numbers +#define ENC_MAJ_VERSION 1 +#define ENC_MIN_VERSION 3 +#define ENC_REV_VERSION 2 + +enum { MAX_LF_LEVELS = 64, // Maximum loop filter level + MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost + MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67) + }; + +typedef enum { // Rate-distortion optimization levels + RD_OPT_NONE = 0, // no rd-opt + RD_OPT_BASIC = 1, // basic scoring (no trellis) + RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only + RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower) +} VP8RDLevel; + +// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). +// The original or reconstructed samples can be accessed using VP8Scan[]. +// The predicted blocks can be accessed using offsets to yuv_p_ and +// the arrays VP8*ModeOffsets[]. +// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_) +// (see VP8Scan[] for accessing the blocks, along with +// Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC): +// +----+----+ +// Y_OFF_ENC |YYYY|UUVV| +// U_OFF_ENC |YYYY|UUVV| +// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area +// |YYYY|....| +// +----+----+ +// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC) +// Intra16 predictions (16x16 block each, two per row): +// |I16DC16|I16TM16| +// |I16VE16|I16HE16| +// Chroma U/V predictions (16x8 block each, two per row): +// |C8DC8|C8TM8| +// |C8VE8|C8HE8| +// Intra 4x4 predictions (4x4 block each) +// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4| +// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted +#define YUV_SIZE_ENC (BPS * 16) +#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds +#define Y_OFF_ENC (0) +#define U_OFF_ENC (16) +#define V_OFF_ENC (16 + 8) + +extern const uint16_t VP8Scan[16]; +extern const uint16_t VP8UVModeOffsets[4]; +extern const uint16_t VP8I16ModeOffsets[4]; +extern const uint16_t VP8I4ModeOffsets[NUM_BMODES]; + +// Layout of prediction blocks +// intra 16x16 +#define I16DC16 (0 * 16 * BPS) +#define I16TM16 (I16DC16 + 16) +#define I16VE16 (1 * 16 * BPS) +#define I16HE16 (I16VE16 + 16) +// chroma 8x8, two U/V blocks side by side (hence: 16x8 each) +#define C8DC8 (2 * 16 * BPS) +#define C8TM8 (C8DC8 + 1 * 16) +#define C8VE8 (2 * 16 * BPS + 8 * BPS) +#define C8HE8 (C8VE8 + 1 * 16) +// intra 4x4 +#define I4DC4 (3 * 16 * BPS + 0) +#define I4TM4 (I4DC4 + 4) +#define I4VE4 (I4DC4 + 8) +#define I4HE4 (I4DC4 + 12) +#define I4RD4 (I4DC4 + 16) +#define I4VR4 (I4DC4 + 20) +#define I4LD4 (I4DC4 + 24) +#define I4VL4 (I4DC4 + 28) +#define I4HD4 (3 * 16 * BPS + 4 * BPS) +#define I4HU4 (I4HD4 + 4) +#define I4TMP (I4HD4 + 8) + +typedef int64_t score_t; // type used for scores, rate, distortion +// Note that MAX_COST is not the maximum allowed by sizeof(score_t), +// in order to allow overflowing computations. +#define MAX_COST ((score_t)0x7fffffffffffffLL) + +#define QFIX 17 +#define BIAS(b) ((b) << (QFIX - 8)) +// Fun fact: this is the _only_ line where we're actually being lossy and +// discarding bits. +static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) { + return (int)((n * iQ + B) >> QFIX); +} + +// Uncomment the following to remove token-buffer code: +// #define DISABLE_TOKEN_BUFFER + +// quality below which error-diffusion is enabled +#define ERROR_DIFFUSION_QUALITY 98 + +//------------------------------------------------------------------------------ +// Headers + +typedef uint32_t proba_t; // 16b + 16b +typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS]; +typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS]; +typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1]; +typedef const uint16_t* (*CostArrayPtr)[NUM_CTX]; // for easy casting +typedef const uint16_t* CostArrayMap[16][NUM_CTX]; +typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats + +typedef struct VP8Encoder VP8Encoder; + +// segment features +typedef struct { + int num_segments_; // Actual number of segments. 1 segment only = unused. + int update_map_; // whether to update the segment map or not. + // must be 0 if there's only 1 segment. + int size_; // bit-cost for transmitting the segment map +} VP8EncSegmentHeader; + +// Struct collecting all frame-persistent probabilities. +typedef struct { + uint8_t segments_[3]; // probabilities for segment tree + uint8_t skip_proba_; // final probability of being skipped. + ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 1056 bytes + StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes + CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 13056 bytes + CostArrayMap remapped_costs_[NUM_TYPES]; // 1536 bytes + int dirty_; // if true, need to call VP8CalculateLevelCosts() + int use_skip_proba_; // Note: we always use skip_proba for now. + int nb_skip_; // number of skipped blocks +} VP8EncProba; + +// Filter parameters. Not actually used in the code (we don't perform +// the in-loop filtering), but filled from user's config +typedef struct { + int simple_; // filtering type: 0=complex, 1=simple + int level_; // base filter level [0..63] + int sharpness_; // [0..7] + int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16 +} VP8EncFilterHeader; + +//------------------------------------------------------------------------------ +// Informations about the macroblocks. + +typedef struct { + // block type + unsigned int type_:2; // 0=i4x4, 1=i16x16 + unsigned int uv_mode_:2; + unsigned int skip_:1; + unsigned int segment_:2; + uint8_t alpha_; // quantization-susceptibility +} VP8MBInfo; + +typedef struct VP8Matrix { + uint16_t q_[16]; // quantizer steps + uint16_t iq_[16]; // reciprocals, fixed point. + uint32_t bias_[16]; // rounding bias + uint32_t zthresh_[16]; // value below which a coefficient is zeroed + uint16_t sharpen_[16]; // frequency boosters for slight sharpening +} VP8Matrix; + +typedef struct { + VP8Matrix y1_, y2_, uv_; // quantization matrices + int alpha_; // quant-susceptibility, range [-127,127]. Zero is neutral. + // Lower values indicate a lower risk of blurriness. + int beta_; // filter-susceptibility, range [0,255]. + int quant_; // final segment quantizer. + int fstrength_; // final in-loop filtering strength + int max_edge_; // max edge delta (for filtering strength) + int min_disto_; // minimum distortion required to trigger filtering record + // reactivities + int lambda_i16_, lambda_i4_, lambda_uv_; + int lambda_mode_, lambda_trellis_, tlambda_; + int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_; + + // lambda values for distortion-based evaluation + score_t i4_penalty_; // penalty for using Intra4 +} VP8SegmentInfo; + +typedef int8_t DError[2 /* u/v */][2 /* top or left */]; + +// Handy transient struct to accumulate score and info during RD-optimization +// and mode evaluation. +typedef struct { + score_t D, SD; // Distortion, spectral distortion + score_t H, R, score; // header bits, rate, score. + int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma. + int16_t y_ac_levels[16][16]; + int16_t uv_levels[4 + 4][16]; + int mode_i16; // mode number for intra16 prediction + uint8_t modes_i4[16]; // mode numbers for intra4 predictions + int mode_uv; // mode number of chroma prediction + uint32_t nz; // non-zero blocks + int8_t derr[2][3]; // DC diffusion errors for U/V for blocks #1/2/3 +} VP8ModeScore; + +// Iterator structure to iterate through macroblocks, pointing to the +// right neighbouring data (samples, predictions, contexts, ...) +typedef struct { + int x_, y_; // current macroblock + uint8_t* yuv_in_; // input samples + uint8_t* yuv_out_; // output samples + uint8_t* yuv_out2_; // secondary buffer swapped with yuv_out_. + uint8_t* yuv_p_; // scratch buffer for prediction + VP8Encoder* enc_; // back-pointer + VP8MBInfo* mb_; // current macroblock + VP8BitWriter* bw_; // current bit-writer + uint8_t* preds_; // intra mode predictors (4x4 blocks) + uint32_t* nz_; // non-zero pattern + uint8_t i4_boundary_[37]; // 32+5 boundary samples needed by intra4x4 + uint8_t* i4_top_; // pointer to the current top boundary sample + int i4_; // current intra4x4 mode being tested + int top_nz_[9]; // top-non-zero context. + int left_nz_[9]; // left-non-zero. left_nz[8] is independent. + uint64_t bit_count_[4][3]; // bit counters for coded levels. + uint64_t luma_bits_; // macroblock bit-cost for luma + uint64_t uv_bits_; // macroblock bit-cost for chroma + LFStats* lf_stats_; // filter stats (borrowed from enc_) + int do_trellis_; // if true, perform extra level optimisation + int count_down_; // number of mb still to be processed + int count_down0_; // starting counter value (for progress) + int percent0_; // saved initial progress percent + + DError left_derr_; // left error diffusion (u/v) + DError* top_derr_; // top diffusion error - NULL if disabled + + uint8_t* y_left_; // left luma samples (addressable from index -1 to 15). + uint8_t* u_left_; // left u samples (addressable from index -1 to 7) + uint8_t* v_left_; // left v samples (addressable from index -1 to 7) + + uint8_t* y_top_; // top luma samples at position 'x_' + uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes + + // memory for storing y/u/v_left_ + uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + WEBP_ALIGN_CST]; + // memory for yuv_* + uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + WEBP_ALIGN_CST]; +} VP8EncIterator; + + // in iterator.c +// must be called first +void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it); +// restart a scan +void VP8IteratorReset(VP8EncIterator* const it); +// reset iterator position to row 'y' +void VP8IteratorSetRow(VP8EncIterator* const it, int y); +// set count down (=number of iterations to go) +void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down); +// return true if iteration is finished +int VP8IteratorIsDone(const VP8EncIterator* const it); +// Import uncompressed samples from source. +// If tmp_32 is not NULL, import boundary samples too. +// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory. +void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32); +// export decimated samples +void VP8IteratorExport(const VP8EncIterator* const it); +// go to next macroblock. Returns false if not finished. +int VP8IteratorNext(VP8EncIterator* const it); +// save the yuv_out_ boundary values to top_/left_ arrays for next iterations. +void VP8IteratorSaveBoundary(VP8EncIterator* const it); +// Report progression based on macroblock rows. Return 0 for user-abort request. +int VP8IteratorProgress(const VP8EncIterator* const it, int delta); +// Intra4x4 iterations +void VP8IteratorStartI4(VP8EncIterator* const it); +// returns true if not done. +int VP8IteratorRotateI4(VP8EncIterator* const it, + const uint8_t* const yuv_out); + +// Non-zero context setup/teardown +void VP8IteratorNzToBytes(VP8EncIterator* const it); +void VP8IteratorBytesToNz(VP8EncIterator* const it); + +// Helper functions to set mode properties +void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode); +void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes); +void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode); +void VP8SetSkip(const VP8EncIterator* const it, int skip); +void VP8SetSegment(const VP8EncIterator* const it, int segment); + +//------------------------------------------------------------------------------ +// Paginated token buffer + +typedef struct VP8Tokens VP8Tokens; // struct details in token.c + +typedef struct { +#if !defined(DISABLE_TOKEN_BUFFER) + VP8Tokens* pages_; // first page + VP8Tokens** last_page_; // last page + uint16_t* tokens_; // set to (*last_page_)->tokens_ + int left_; // how many free tokens left before the page is full + int page_size_; // number of tokens per page +#endif + int error_; // true in case of malloc error +} VP8TBuffer; + +// initialize an empty buffer +void VP8TBufferInit(VP8TBuffer* const b, int page_size); +void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory + +#if !defined(DISABLE_TOKEN_BUFFER) + +// Finalizes bitstream when probabilities are known. +// Deletes the allocated token memory if final_pass is true. +int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, + const uint8_t* const probas, int final_pass); + +// record the coding of coefficients without knowing the probabilities yet +int VP8RecordCoeffTokens(int ctx, const struct VP8Residual* const res, + VP8TBuffer* const tokens); + +// Estimate the final coded size given a set of 'probas'. +size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas); + +#endif // !DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ +// VP8Encoder + +struct VP8Encoder { + const WebPConfig* config_; // user configuration and parameters + WebPPicture* pic_; // input / output picture + + // headers + VP8EncFilterHeader filter_hdr_; // filtering information + VP8EncSegmentHeader segment_hdr_; // segment information + + int profile_; // VP8's profile, deduced from Config. + + // dimension, in macroblock units. + int mb_w_, mb_h_; + int preds_w_; // stride of the *preds_ prediction plane (=4*mb_w + 1) + + // number of partitions (1, 2, 4 or 8 = MAX_NUM_PARTITIONS) + int num_parts_; + + // per-partition boolean decoders. + VP8BitWriter bw_; // part0 + VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions + VP8TBuffer tokens_; // token buffer + + int percent_; // for progress + + // transparency blob + int has_alpha_; + uint8_t* alpha_data_; // non-NULL if transparency is present + uint32_t alpha_data_size_; + WebPWorker alpha_worker_; + + // quantization info (one set of DC/AC dequant factor per segment) + VP8SegmentInfo dqm_[NUM_MB_SEGMENTS]; + int base_quant_; // nominal quantizer value. Only used + // for relative coding of segments' quant. + int alpha_; // global susceptibility (<=> complexity) + int uv_alpha_; // U/V quantization susceptibility + // global offset of quantizers, shared by all segments + int dq_y1_dc_; + int dq_y2_dc_, dq_y2_ac_; + int dq_uv_dc_, dq_uv_ac_; + + // probabilities and statistics + VP8EncProba proba_; + uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks + uint64_t sse_count_; // pixel count for the sse_[] stats + int coded_size_; + int residual_bytes_[3][4]; + int block_count_[3]; + + // quality/speed settings + int method_; // 0=fastest, 6=best/slowest. + VP8RDLevel rd_opt_level_; // Deduced from method_. + int max_i4_header_bits_; // partition #0 safeness factor + int mb_header_limit_; // rough limit for header bits per MB + int thread_level_; // derived from config->thread_level + int do_search_; // derived from config->target_XXX + int use_tokens_; // if true, use token buffer + + // Memory + VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1) + uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1) + uint32_t* nz_; // non-zero bit context: mb_w+1 + uint8_t* y_top_; // top luma samples. + uint8_t* uv_top_; // top u/v samples. + // U and V are packed into 16 bytes (8 U + 8 V) + LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off) + DError* top_derr_; // diffusion error (NULL if disabled) +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + + // in tree.c +extern const uint8_t VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; +extern const uint8_t + VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; +// Reset the token probabilities to their initial (default) values +void VP8DefaultProbas(VP8Encoder* const enc); +// Write the token probabilities +void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas); +// Writes the partition #0 modes (that is: all intra modes) +void VP8CodeIntraModes(VP8Encoder* const enc); + + // in syntax.c +// Generates the final bitstream by coding the partition0 and headers, +// and appending an assembly of all the pre-coded token partitions. +// Return true if everything is ok. +int VP8EncWrite(VP8Encoder* const enc); +// Release memory allocated for bit-writing in VP8EncLoop & seq. +void VP8EncFreeBitWriters(VP8Encoder* const enc); + + // in frame.c +extern const uint8_t VP8Cat3[]; +extern const uint8_t VP8Cat4[]; +extern const uint8_t VP8Cat5[]; +extern const uint8_t VP8Cat6[]; + +// Form all the four Intra16x16 predictions in the yuv_p_ cache +void VP8MakeLuma16Preds(const VP8EncIterator* const it); +// Form all the four Chroma8x8 predictions in the yuv_p_ cache +void VP8MakeChroma8Preds(const VP8EncIterator* const it); +// Form all the ten Intra4x4 predictions in the yuv_p_ cache +// for the 4x4 block it->i4_ +void VP8MakeIntra4Preds(const VP8EncIterator* const it); +// Rate calculation +int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd); +int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]); +int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd); +// Main coding calls +int VP8EncLoop(VP8Encoder* const enc); +int VP8EncTokenLoop(VP8Encoder* const enc); + + // in webpenc.c +// Assign an error code to a picture. Return false for convenience. +int WebPEncodingSetError(const WebPPicture* const pic, WebPEncodingError error); +int WebPReportProgress(const WebPPicture* const pic, + int percent, int* const percent_store); + + // in analysis.c +// Main analysis loop. Decides the segmentations and complexity. +// Assigns a first guess for Intra16 and uvmode_ prediction modes. +int VP8EncAnalyze(VP8Encoder* const enc); + + // in quant.c +// Sets up segment's quantization values, base_quant_ and filter strengths. +void VP8SetSegmentParams(VP8Encoder* const enc, float quality); +// Pick best modes and fills the levels. Returns true if skipped. +int VP8Decimate(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd, + VP8RDLevel rd_opt); + + // in alpha.c +void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression +int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process +int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data +int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data + +// autofilter +void VP8InitFilter(VP8EncIterator* const it); +void VP8StoreFilterStats(VP8EncIterator* const it); +void VP8AdjustFilterStrength(VP8EncIterator* const it); + +// returns the approximate filtering strength needed to smooth a edge +// step of 'delta', given a sharpness parameter 'sharpness'. +int VP8FilterStrengthFromDelta(int sharpness, int delta); + + // misc utils for picture_*.c: + +// Returns true if 'picture' is non-NULL and dimensions/colorspace are within +// their valid ranges. If returning false, the 'error_code' in 'picture' is +// updated. +int WebPValidatePicture(const WebPPicture* const picture); + +// Remove reference to the ARGB/YUVA buffer (doesn't free anything). +void WebPPictureResetBuffers(WebPPicture* const picture); + +// Allocates ARGB buffer according to set width/height (previous one is +// always free'd). Preserves the YUV(A) buffer. Returns false in case of error +// (invalid param, out-of-memory). +int WebPPictureAllocARGB(WebPPicture* const picture); + +// Allocates YUVA buffer according to set width/height (previous one is always +// free'd). Uses picture->csp to determine whether an alpha buffer is needed. +// Preserves the ARGB buffer. +// Returns false in case of error (invalid param, out-of-memory). +int WebPPictureAllocYUVA(WebPPicture* const picture); + +// Replace samples that are fully transparent by 'color' to help compressibility +// (no guarantee, though). Assumes pic->use_argb is true. +void WebPReplaceTransparentPixels(WebPPicture* const pic, uint32_t color); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_ENC_VP8I_ENC_H_ diff --git a/libraries/webp/src/enc/vp8l_enc.c b/libraries/webp/src/enc/vp8l_enc.c new file mode 100644 index 0000000000..60427a3b26 --- /dev/null +++ b/libraries/webp/src/enc/vp8l_enc.c @@ -0,0 +1,1893 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// main entry for the lossless encoder. +// +// Author: Vikas Arora (vikaas.arora@gmail.com) +// + +#include +#include + +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/vp8li_enc.h" +#include "src/utils/bit_writer_utils.h" +#include "src/utils/huffman_encode_utils.h" +#include "src/utils/palette.h" +#include "src/utils/utils.h" +#include "include/webp/encode.h" +#include "include/webp/format_constants.h" + +// Maximum number of histogram images (sub-blocks). +#define MAX_HUFF_IMAGE_SIZE 2600 + +// ----------------------------------------------------------------------------- +// Palette + +// These five modes are evaluated and their respective entropy is computed. +typedef enum { + kDirect = 0, + kSpatial = 1, + kSubGreen = 2, + kSpatialSubGreen = 3, + kPalette = 4, + kPaletteAndSpatial = 5, + kNumEntropyIx = 6 +} EntropyIx; + +typedef enum { + kHistoAlpha = 0, + kHistoAlphaPred, + kHistoGreen, + kHistoGreenPred, + kHistoRed, + kHistoRedPred, + kHistoBlue, + kHistoBluePred, + kHistoRedSubGreen, + kHistoRedPredSubGreen, + kHistoBlueSubGreen, + kHistoBluePredSubGreen, + kHistoPalette, + kHistoTotal // Must be last. +} HistoIx; + +static void AddSingleSubGreen(uint32_t p, + uint32_t* const r, uint32_t* const b) { + const int green = (int)p >> 8; // The upper bits are masked away later. + ++r[(((int)p >> 16) - green) & 0xff]; + ++b[(((int)p >> 0) - green) & 0xff]; +} + +static void AddSingle(uint32_t p, + uint32_t* const a, uint32_t* const r, + uint32_t* const g, uint32_t* const b) { + ++a[(p >> 24) & 0xff]; + ++r[(p >> 16) & 0xff]; + ++g[(p >> 8) & 0xff]; + ++b[(p >> 0) & 0xff]; +} + +static WEBP_INLINE uint32_t HashPix(uint32_t pix) { + // Note that masking with 0xffffffffu is for preventing an + // 'unsigned int overflow' warning. Doesn't impact the compiled code. + return ((((uint64_t)pix + (pix >> 19)) * 0x39c5fba7ull) & 0xffffffffu) >> 24; +} + +static int AnalyzeEntropy(const uint32_t* argb, + int width, int height, int argb_stride, + int use_palette, + int palette_size, int transform_bits, + EntropyIx* const min_entropy_ix, + int* const red_and_blue_always_zero) { + // Allocate histogram set with cache_bits = 0. + uint32_t* histo; + + if (use_palette && palette_size <= 16) { + // In the case of small palettes, we pack 2, 4 or 8 pixels together. In + // practice, small palettes are better than any other transform. + *min_entropy_ix = kPalette; + *red_and_blue_always_zero = 1; + return 1; + } + histo = (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); + if (histo != NULL) { + int i, x, y; + const uint32_t* prev_row = NULL; + const uint32_t* curr_row = argb; + uint32_t pix_prev = argb[0]; // Skip the first pixel. + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const uint32_t pix = curr_row[x]; + const uint32_t pix_diff = VP8LSubPixels(pix, pix_prev); + pix_prev = pix; + if ((pix_diff == 0) || (prev_row != NULL && pix == prev_row[x])) { + continue; + } + AddSingle(pix, + &histo[kHistoAlpha * 256], + &histo[kHistoRed * 256], + &histo[kHistoGreen * 256], + &histo[kHistoBlue * 256]); + AddSingle(pix_diff, + &histo[kHistoAlphaPred * 256], + &histo[kHistoRedPred * 256], + &histo[kHistoGreenPred * 256], + &histo[kHistoBluePred * 256]); + AddSingleSubGreen(pix, + &histo[kHistoRedSubGreen * 256], + &histo[kHistoBlueSubGreen * 256]); + AddSingleSubGreen(pix_diff, + &histo[kHistoRedPredSubGreen * 256], + &histo[kHistoBluePredSubGreen * 256]); + { + // Approximate the palette by the entropy of the multiplicative hash. + const uint32_t hash = HashPix(pix); + ++histo[kHistoPalette * 256 + hash]; + } + } + prev_row = curr_row; + curr_row += argb_stride; + } + { + float entropy_comp[kHistoTotal]; + float entropy[kNumEntropyIx]; + int k; + int last_mode_to_analyze = use_palette ? kPalette : kSpatialSubGreen; + int j; + // Let's add one zero to the predicted histograms. The zeros are removed + // too efficiently by the pix_diff == 0 comparison, at least one of the + // zeros is likely to exist. + ++histo[kHistoRedPredSubGreen * 256]; + ++histo[kHistoBluePredSubGreen * 256]; + ++histo[kHistoRedPred * 256]; + ++histo[kHistoGreenPred * 256]; + ++histo[kHistoBluePred * 256]; + ++histo[kHistoAlphaPred * 256]; + + for (j = 0; j < kHistoTotal; ++j) { + entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256); + } + entropy[kDirect] = entropy_comp[kHistoAlpha] + + entropy_comp[kHistoRed] + + entropy_comp[kHistoGreen] + + entropy_comp[kHistoBlue]; + entropy[kSpatial] = entropy_comp[kHistoAlphaPred] + + entropy_comp[kHistoRedPred] + + entropy_comp[kHistoGreenPred] + + entropy_comp[kHistoBluePred]; + entropy[kSubGreen] = entropy_comp[kHistoAlpha] + + entropy_comp[kHistoRedSubGreen] + + entropy_comp[kHistoGreen] + + entropy_comp[kHistoBlueSubGreen]; + entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] + + entropy_comp[kHistoRedPredSubGreen] + + entropy_comp[kHistoGreenPred] + + entropy_comp[kHistoBluePredSubGreen]; + entropy[kPalette] = entropy_comp[kHistoPalette]; + + // When including transforms, there is an overhead in bits from + // storing them. This overhead is small but matters for small images. + // For spatial, there are 14 transformations. + entropy[kSpatial] += VP8LSubSampleSize(width, transform_bits) * + VP8LSubSampleSize(height, transform_bits) * + VP8LFastLog2(14); + // For color transforms: 24 as only 3 channels are considered in a + // ColorTransformElement. + entropy[kSpatialSubGreen] += VP8LSubSampleSize(width, transform_bits) * + VP8LSubSampleSize(height, transform_bits) * + VP8LFastLog2(24); + // For palettes, add the cost of storing the palette. + // We empirically estimate the cost of a compressed entry as 8 bits. + // The palette is differential-coded when compressed hence a much + // lower cost than sizeof(uint32_t)*8. + entropy[kPalette] += palette_size * 8; + + *min_entropy_ix = kDirect; + for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) { + if (entropy[*min_entropy_ix] > entropy[k]) { + *min_entropy_ix = (EntropyIx)k; + } + } + assert((int)*min_entropy_ix <= last_mode_to_analyze); + *red_and_blue_always_zero = 1; + // Let's check if the histogram of the chosen entropy mode has + // non-zero red and blue values. If all are zero, we can later skip + // the cross color optimization. + { + static const uint8_t kHistoPairs[5][2] = { + { kHistoRed, kHistoBlue }, + { kHistoRedPred, kHistoBluePred }, + { kHistoRedSubGreen, kHistoBlueSubGreen }, + { kHistoRedPredSubGreen, kHistoBluePredSubGreen }, + { kHistoRed, kHistoBlue } + }; + const uint32_t* const red_histo = + &histo[256 * kHistoPairs[*min_entropy_ix][0]]; + const uint32_t* const blue_histo = + &histo[256 * kHistoPairs[*min_entropy_ix][1]]; + for (i = 1; i < 256; ++i) { + if ((red_histo[i] | blue_histo[i]) != 0) { + *red_and_blue_always_zero = 0; + break; + } + } + } + } + WebPSafeFree(histo); + return 1; + } else { + return 0; + } +} + +static int GetHistoBits(int method, int use_palette, int width, int height) { + // Make tile size a function of encoding method (Range: 0 to 6). + int histo_bits = (use_palette ? 9 : 7) - method; + while (1) { + const int huff_image_size = VP8LSubSampleSize(width, histo_bits) * + VP8LSubSampleSize(height, histo_bits); + if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; + ++histo_bits; + } + return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS : + (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; +} + +static int GetTransformBits(int method, int histo_bits) { + const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5; + const int res = + (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits; + assert(res <= MAX_TRANSFORM_BITS); + return res; +} + +// Set of parameters to be used in each iteration of the cruncher. +#define CRUNCH_SUBCONFIGS_MAX 2 +typedef struct { + int lz77_; + int do_no_cache_; +} CrunchSubConfig; +typedef struct { + int entropy_idx_; + PaletteSorting palette_sorting_type_; + CrunchSubConfig sub_configs_[CRUNCH_SUBCONFIGS_MAX]; + int sub_configs_size_; +} CrunchConfig; + +// +2 because we add a palette sorting configuration for kPalette and +// kPaletteAndSpatial. +#define CRUNCH_CONFIGS_MAX (kNumEntropyIx + 2 * kPaletteSortingNum) + +static int EncoderAnalyze(VP8LEncoder* const enc, + CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX], + int* const crunch_configs_size, + int* const red_and_blue_always_zero) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const WebPConfig* const config = enc->config_; + const int method = config->method; + const int low_effort = (config->method == 0); + int i; + int use_palette; + int n_lz77s; + // If set to 0, analyze the cache with the computed cache value. If 1, also + // analyze with no-cache. + int do_no_cache = 0; + assert(pic != NULL && pic->argb != NULL); + + // Check whether a palette is possible. + enc->palette_size_ = GetColorPalette(pic, enc->palette_sorted_); + use_palette = (enc->palette_size_ <= MAX_PALETTE_SIZE); + if (!use_palette) { + enc->palette_size_ = 0; + } + + // Empirical bit sizes. + enc->histo_bits_ = GetHistoBits(method, use_palette, + pic->width, pic->height); + enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); + + if (low_effort) { + // AnalyzeEntropy is somewhat slow. + crunch_configs[0].entropy_idx_ = use_palette ? kPalette : kSpatialSubGreen; + crunch_configs[0].palette_sorting_type_ = + use_palette ? kSortedDefault : kUnusedPalette; + n_lz77s = 1; + *crunch_configs_size = 1; + } else { + EntropyIx min_entropy_ix; + // Try out multiple LZ77 on images with few colors. + n_lz77s = (enc->palette_size_ > 0 && enc->palette_size_ <= 16) ? 2 : 1; + if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, use_palette, + enc->palette_size_, enc->transform_bits_, + &min_entropy_ix, red_and_blue_always_zero)) { + return 0; + } + if (method == 6 && config->quality == 100) { + do_no_cache = 1; + // Go brute force on all transforms. + *crunch_configs_size = 0; + for (i = 0; i < kNumEntropyIx; ++i) { + // We can only apply kPalette or kPaletteAndSpatial if we can indeed use + // a palette. + if ((i != kPalette && i != kPaletteAndSpatial) || use_palette) { + assert(*crunch_configs_size < CRUNCH_CONFIGS_MAX); + if (use_palette && (i == kPalette || i == kPaletteAndSpatial)) { + int sorting_method; + for (sorting_method = 0; sorting_method < kPaletteSortingNum; + ++sorting_method) { + const PaletteSorting typed_sorting_method = + (PaletteSorting)sorting_method; + // TODO(vrabaud) kSortedDefault should be tested. It is omitted + // for now for backward compatibility. + if (typed_sorting_method == kUnusedPalette || + typed_sorting_method == kSortedDefault) { + continue; + } + crunch_configs[(*crunch_configs_size)].entropy_idx_ = i; + crunch_configs[(*crunch_configs_size)].palette_sorting_type_ = + typed_sorting_method; + ++*crunch_configs_size; + } + } else { + crunch_configs[(*crunch_configs_size)].entropy_idx_ = i; + crunch_configs[(*crunch_configs_size)].palette_sorting_type_ = + kUnusedPalette; + ++*crunch_configs_size; + } + } + } + } else { + // Only choose the guessed best transform. + *crunch_configs_size = 1; + crunch_configs[0].entropy_idx_ = min_entropy_ix; + crunch_configs[0].palette_sorting_type_ = + use_palette ? kMinimizeDelta : kUnusedPalette; + if (config->quality >= 75 && method == 5) { + // Test with and without color cache. + do_no_cache = 1; + // If we have a palette, also check in combination with spatial. + if (min_entropy_ix == kPalette) { + *crunch_configs_size = 2; + crunch_configs[1].entropy_idx_ = kPaletteAndSpatial; + crunch_configs[1].palette_sorting_type_ = kMinimizeDelta; + } + } + } + } + // Fill in the different LZ77s. + assert(n_lz77s <= CRUNCH_SUBCONFIGS_MAX); + for (i = 0; i < *crunch_configs_size; ++i) { + int j; + for (j = 0; j < n_lz77s; ++j) { + assert(j < CRUNCH_SUBCONFIGS_MAX); + crunch_configs[i].sub_configs_[j].lz77_ = + (j == 0) ? kLZ77Standard | kLZ77RLE : kLZ77Box; + crunch_configs[i].sub_configs_[j].do_no_cache_ = do_no_cache; + } + crunch_configs[i].sub_configs_size_ = n_lz77s; + } + return 1; +} + +static int EncoderInit(VP8LEncoder* const enc) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const int pix_cnt = width * height; + // we round the block size up, so we're guaranteed to have + // at most MAX_REFS_BLOCK_PER_IMAGE blocks used: + const int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; + int i; + if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; + + for (i = 0; i < 4; ++i) VP8LBackwardRefsInit(&enc->refs_[i], refs_block_size); + + return 1; +} + +// Returns false in case of memory error. +static int GetHuffBitLengthsAndCodes( + const VP8LHistogramSet* const histogram_image, + HuffmanTreeCode* const huffman_codes) { + int i, k; + int ok = 0; + uint64_t total_length_size = 0; + uint8_t* mem_buf = NULL; + const int histogram_image_size = histogram_image->size; + int max_num_symbols = 0; + uint8_t* buf_rle = NULL; + HuffmanTree* huff_tree = NULL; + + // Iterate over all histograms and get the aggregate number of codes used. + for (i = 0; i < histogram_image_size; ++i) { + const VP8LHistogram* const histo = histogram_image->histograms[i]; + HuffmanTreeCode* const codes = &huffman_codes[5 * i]; + assert(histo != NULL); + for (k = 0; k < 5; ++k) { + const int num_symbols = + (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) : + (k == 4) ? NUM_DISTANCE_CODES : 256; + codes[k].num_symbols = num_symbols; + total_length_size += num_symbols; + } + } + + // Allocate and Set Huffman codes. + { + uint16_t* codes; + uint8_t* lengths; + mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size, + sizeof(*lengths) + sizeof(*codes)); + if (mem_buf == NULL) goto End; + + codes = (uint16_t*)mem_buf; + lengths = (uint8_t*)&codes[total_length_size]; + for (i = 0; i < 5 * histogram_image_size; ++i) { + const int bit_length = huffman_codes[i].num_symbols; + huffman_codes[i].codes = codes; + huffman_codes[i].code_lengths = lengths; + codes += bit_length; + lengths += bit_length; + if (max_num_symbols < bit_length) { + max_num_symbols = bit_length; + } + } + } + + buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols); + huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols, + sizeof(*huff_tree)); + if (buf_rle == NULL || huff_tree == NULL) goto End; + + // Create Huffman trees. + for (i = 0; i < histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[5 * i]; + VP8LHistogram* const histo = histogram_image->histograms[i]; + VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0); + VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1); + VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2); + VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3); + VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4); + } + ok = 1; + End: + WebPSafeFree(huff_tree); + WebPSafeFree(buf_rle); + if (!ok) { + WebPSafeFree(mem_buf); + memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes)); + } + return ok; +} + +static void StoreHuffmanTreeOfHuffmanTreeToBitMask( + VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) { + // RFC 1951 will calm you down if you are worried about this funny sequence. + // This sequence is tuned from that, but more weighted for lower symbol count, + // and more spiking histograms. + static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = { + 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + }; + int i; + // Throw away trailing zeros: + int codes_to_store = CODE_LENGTH_CODES; + for (; codes_to_store > 4; --codes_to_store) { + if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { + break; + } + } + VP8LPutBits(bw, codes_to_store - 4, 4); + for (i = 0; i < codes_to_store; ++i) { + VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3); + } +} + +static void ClearHuffmanTreeIfOnlyOneSymbol( + HuffmanTreeCode* const huffman_code) { + int k; + int count = 0; + for (k = 0; k < huffman_code->num_symbols; ++k) { + if (huffman_code->code_lengths[k] != 0) { + ++count; + if (count > 1) return; + } + } + for (k = 0; k < huffman_code->num_symbols; ++k) { + huffman_code->code_lengths[k] = 0; + huffman_code->codes[k] = 0; + } +} + +static void StoreHuffmanTreeToBitMask( + VP8LBitWriter* const bw, + const HuffmanTreeToken* const tokens, const int num_tokens, + const HuffmanTreeCode* const huffman_code) { + int i; + for (i = 0; i < num_tokens; ++i) { + const int ix = tokens[i].code; + const int extra_bits = tokens[i].extra_bits; + VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]); + switch (ix) { + case 16: + VP8LPutBits(bw, extra_bits, 2); + break; + case 17: + VP8LPutBits(bw, extra_bits, 3); + break; + case 18: + VP8LPutBits(bw, extra_bits, 7); + break; + } + } +} + +// 'huff_tree' and 'tokens' are pre-alloacted buffers. +static void StoreFullHuffmanCode(VP8LBitWriter* const bw, + HuffmanTree* const huff_tree, + HuffmanTreeToken* const tokens, + const HuffmanTreeCode* const tree) { + uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; + uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; + const int max_tokens = tree->num_symbols; + int num_tokens; + HuffmanTreeCode huffman_code; + huffman_code.num_symbols = CODE_LENGTH_CODES; + huffman_code.code_lengths = code_length_bitdepth; + huffman_code.codes = code_length_bitdepth_symbols; + + VP8LPutBits(bw, 0, 1); + num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens); + { + uint32_t histogram[CODE_LENGTH_CODES] = { 0 }; + uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 }; + int i; + for (i = 0; i < num_tokens; ++i) { + ++histogram[tokens[i].code]; + } + + VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code); + } + + StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); + ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code); + { + int trailing_zero_bits = 0; + int trimmed_length = num_tokens; + int write_trimmed_length; + int length; + int i = num_tokens; + while (i-- > 0) { + const int ix = tokens[i].code; + if (ix == 0 || ix == 17 || ix == 18) { + --trimmed_length; // discount trailing zeros + trailing_zero_bits += code_length_bitdepth[ix]; + if (ix == 17) { + trailing_zero_bits += 3; + } else if (ix == 18) { + trailing_zero_bits += 7; + } + } else { + break; + } + } + write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); + length = write_trimmed_length ? trimmed_length : num_tokens; + VP8LPutBits(bw, write_trimmed_length, 1); + if (write_trimmed_length) { + if (trimmed_length == 2) { + VP8LPutBits(bw, 0, 3 + 2); // nbitpairs=1, trimmed_length=2 + } else { + const int nbits = BitsLog2Floor(trimmed_length - 2); + const int nbitpairs = nbits / 2 + 1; + assert(trimmed_length > 2); + assert(nbitpairs - 1 < 8); + VP8LPutBits(bw, nbitpairs - 1, 3); + VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); + } + } + StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); + } +} + +// 'huff_tree' and 'tokens' are pre-alloacted buffers. +static void StoreHuffmanCode(VP8LBitWriter* const bw, + HuffmanTree* const huff_tree, + HuffmanTreeToken* const tokens, + const HuffmanTreeCode* const huffman_code) { + int i; + int count = 0; + int symbols[2] = { 0, 0 }; + const int kMaxBits = 8; + const int kMaxSymbol = 1 << kMaxBits; + + // Check whether it's a small tree. + for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) { + if (huffman_code->code_lengths[i] != 0) { + if (count < 2) symbols[count] = i; + ++count; + } + } + + if (count == 0) { // emit minimal tree for empty cases + // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 + VP8LPutBits(bw, 0x01, 4); + } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { + VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. + VP8LPutBits(bw, count - 1, 1); + if (symbols[0] <= 1) { + VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value. + VP8LPutBits(bw, symbols[0], 1); + } else { + VP8LPutBits(bw, 1, 1); + VP8LPutBits(bw, symbols[0], 8); + } + if (count == 2) { + VP8LPutBits(bw, symbols[1], 8); + } + } else { + StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code); + } +} + +static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw, + const HuffmanTreeCode* const code, + int code_index) { + const int depth = code->code_lengths[code_index]; + const int symbol = code->codes[code_index]; + VP8LPutBits(bw, symbol, depth); +} + +static WEBP_INLINE void WriteHuffmanCodeWithExtraBits( + VP8LBitWriter* const bw, + const HuffmanTreeCode* const code, + int code_index, + int bits, + int n_bits) { + const int depth = code->code_lengths[code_index]; + const int symbol = code->codes[code_index]; + VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits); +} + +static int StoreImageToBitMask( + VP8LBitWriter* const bw, int width, int histo_bits, + const VP8LBackwardRefs* const refs, + const uint16_t* histogram_symbols, + const HuffmanTreeCode* const huffman_codes, const WebPPicture* const pic) { + const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; + const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits); + // x and y trace the position in the image. + int x = 0; + int y = 0; + int tile_x = x & tile_mask; + int tile_y = y & tile_mask; + int histogram_ix = histogram_symbols[0]; + const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) { + tile_x = x & tile_mask; + tile_y = y & tile_mask; + histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize + + (x >> histo_bits)]; + codes = huffman_codes + 5 * histogram_ix; + } + if (PixOrCopyIsLiteral(v)) { + static const uint8_t order[] = { 1, 2, 0, 3 }; + int k; + for (k = 0; k < 4; ++k) { + const int code = PixOrCopyLiteral(v, order[k]); + WriteHuffmanCode(bw, codes + k, code); + } + } else if (PixOrCopyIsCacheIdx(v)) { + const int code = PixOrCopyCacheIdx(v); + const int literal_ix = 256 + NUM_LENGTH_CODES + code; + WriteHuffmanCode(bw, codes, literal_ix); + } else { + int bits, n_bits; + int code; + + const int distance = PixOrCopyDistance(v); + VP8LPrefixEncode(v->len, &code, &n_bits, &bits); + WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits); + + // Don't write the distance with the extra bits code since + // the distance can be up to 18 bits of extra bits, and the prefix + // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits. + VP8LPrefixEncode(distance, &code, &n_bits, &bits); + WriteHuffmanCode(bw, codes + 4, code); + VP8LPutBits(bw, bits, n_bits); + } + x += PixOrCopyLength(v); + while (x >= width) { + x -= width; + ++y; + } + VP8LRefsCursorNext(&c); + } + if (bw->error_) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return 1; +} + +// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31. +// pic and percent are for progress. +static int EncodeImageNoHuffman(VP8LBitWriter* const bw, + const uint32_t* const argb, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs_array, int width, + int height, int quality, int low_effort, + const WebPPicture* const pic, int percent_range, + int* const percent) { + int i; + int max_tokens = 0; + VP8LBackwardRefs* refs; + HuffmanTreeToken* tokens = NULL; + HuffmanTreeCode huffman_codes[5] = {{0, NULL, NULL}}; + const uint16_t histogram_symbols[1] = {0}; // only one tree, one symbol + int cache_bits = 0; + VP8LHistogramSet* histogram_image = NULL; + HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( + 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); + if (huff_tree == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Calculate backward references from ARGB image. + if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, low_effort, + pic, percent_range / 2, percent)) { + goto Error; + } + if (!VP8LGetBackwardReferences(width, height, argb, quality, /*low_effort=*/0, + kLZ77Standard | kLZ77RLE, cache_bits, + /*do_no_cache=*/0, hash_chain, refs_array, + &cache_bits, pic, + percent_range - percent_range / 2, percent)) { + goto Error; + } + refs = &refs_array[0]; + histogram_image = VP8LAllocateHistogramSet(1, cache_bits); + if (histogram_image == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + VP8LHistogramSetClear(histogram_image); + + // Build histogram image and symbols from backward references. + VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]); + + // Create Huffman bit lengths and codes for each histogram image. + assert(histogram_image->size == 1); + if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // No color cache, no Huffman image. + VP8LPutBits(bw, 0, 1); + + // Find maximum number of symbols for the huffman tree-set. + for (i = 0; i < 5; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + if (max_tokens < codes->num_symbols) { + max_tokens = codes->num_symbols; + } + } + + tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); + if (tokens == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Store Huffman codes. + for (i = 0; i < 5; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + StoreHuffmanCode(bw, huff_tree, tokens, codes); + ClearHuffmanTreeIfOnlyOneSymbol(codes); + } + + // Store actual literals. + if (!StoreImageToBitMask(bw, width, 0, refs, histogram_symbols, huffman_codes, + pic)) { + goto Error; + } + + Error: + WebPSafeFree(tokens); + WebPSafeFree(huff_tree); + VP8LFreeHistogramSet(histogram_image); + WebPSafeFree(huffman_codes[0].codes); + return (pic->error_code == VP8_ENC_OK); +} + +// pic and percent are for progress. +static int EncodeImageInternal( + VP8LBitWriter* const bw, const uint32_t* const argb, + VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[4], int width, + int height, int quality, int low_effort, const CrunchConfig* const config, + int* cache_bits, int histogram_bits, size_t init_byte_position, + int* const hdr_size, int* const data_size, const WebPPicture* const pic, + int percent_range, int* const percent) { + const uint32_t histogram_image_xysize = + VP8LSubSampleSize(width, histogram_bits) * + VP8LSubSampleSize(height, histogram_bits); + int remaining_percent = percent_range; + int percent_start = *percent; + VP8LHistogramSet* histogram_image = NULL; + VP8LHistogram* tmp_histo = NULL; + int histogram_image_size = 0; + size_t bit_array_size = 0; + HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( + 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); + HuffmanTreeToken* tokens = NULL; + HuffmanTreeCode* huffman_codes = NULL; + uint16_t* const histogram_symbols = (uint16_t*)WebPSafeMalloc( + histogram_image_xysize, sizeof(*histogram_symbols)); + int sub_configs_idx; + int cache_bits_init, write_histogram_image; + VP8LBitWriter bw_init = *bw, bw_best; + int hdr_size_tmp; + VP8LHashChain hash_chain_histogram; // histogram image hash chain + size_t bw_size_best = ~(size_t)0; + assert(histogram_bits >= MIN_HUFFMAN_BITS); + assert(histogram_bits <= MAX_HUFFMAN_BITS); + assert(hdr_size != NULL); + assert(data_size != NULL); + + memset(&hash_chain_histogram, 0, sizeof(hash_chain_histogram)); + if (!VP8LBitWriterInit(&bw_best, 0)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Make sure we can allocate the different objects. + if (huff_tree == NULL || histogram_symbols == NULL || + !VP8LHashChainInit(&hash_chain_histogram, histogram_image_xysize)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + percent_range = remaining_percent / 5; + if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, + low_effort, pic, percent_range, percent)) { + goto Error; + } + percent_start += percent_range; + remaining_percent -= percent_range; + + // If the value is different from zero, it has been set during the palette + // analysis. + cache_bits_init = (*cache_bits == 0) ? MAX_COLOR_CACHE_BITS : *cache_bits; + // If several iterations will happen, clone into bw_best. + if ((config->sub_configs_size_ > 1 || config->sub_configs_[0].do_no_cache_) && + !VP8LBitWriterClone(bw, &bw_best)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + for (sub_configs_idx = 0; sub_configs_idx < config->sub_configs_size_; + ++sub_configs_idx) { + const CrunchSubConfig* const sub_config = + &config->sub_configs_[sub_configs_idx]; + int cache_bits_best, i_cache; + int i_remaining_percent = remaining_percent / config->sub_configs_size_; + int i_percent_range = i_remaining_percent / 4; + i_remaining_percent -= i_percent_range; + + if (!VP8LGetBackwardReferences( + width, height, argb, quality, low_effort, sub_config->lz77_, + cache_bits_init, sub_config->do_no_cache_, hash_chain, + &refs_array[0], &cache_bits_best, pic, i_percent_range, percent)) { + goto Error; + } + + for (i_cache = 0; i_cache < (sub_config->do_no_cache_ ? 2 : 1); ++i_cache) { + const int cache_bits_tmp = (i_cache == 0) ? cache_bits_best : 0; + // Speed-up: no need to study the no-cache case if it was already studied + // in i_cache == 0. + if (i_cache == 1 && cache_bits_best == 0) break; + + // Reset the bit writer for this iteration. + VP8LBitWriterReset(&bw_init, bw); + + // Build histogram image and symbols from backward references. + histogram_image = + VP8LAllocateHistogramSet(histogram_image_xysize, cache_bits_tmp); + tmp_histo = VP8LAllocateHistogram(cache_bits_tmp); + if (histogram_image == NULL || tmp_histo == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + i_percent_range = i_remaining_percent / 3; + i_remaining_percent -= i_percent_range; + if (!VP8LGetHistoImageSymbols( + width, height, &refs_array[i_cache], quality, low_effort, + histogram_bits, cache_bits_tmp, histogram_image, tmp_histo, + histogram_symbols, pic, i_percent_range, percent)) { + goto Error; + } + // Create Huffman bit lengths and codes for each histogram image. + histogram_image_size = histogram_image->size; + bit_array_size = 5 * histogram_image_size; + huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, + sizeof(*huffman_codes)); + // Note: some histogram_image entries may point to tmp_histos[], so the + // latter need to outlive the following call to + // GetHuffBitLengthsAndCodes(). + if (huffman_codes == NULL || + !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + // Free combined histograms. + VP8LFreeHistogramSet(histogram_image); + histogram_image = NULL; + + // Free scratch histograms. + VP8LFreeHistogram(tmp_histo); + tmp_histo = NULL; + + // Color Cache parameters. + if (cache_bits_tmp > 0) { + VP8LPutBits(bw, 1, 1); + VP8LPutBits(bw, cache_bits_tmp, 4); + } else { + VP8LPutBits(bw, 0, 1); + } + + // Huffman image + meta huffman. + write_histogram_image = (histogram_image_size > 1); + VP8LPutBits(bw, write_histogram_image, 1); + if (write_histogram_image) { + uint32_t* const histogram_argb = (uint32_t*)WebPSafeMalloc( + histogram_image_xysize, sizeof(*histogram_argb)); + int max_index = 0; + uint32_t i; + if (histogram_argb == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + for (i = 0; i < histogram_image_xysize; ++i) { + const int symbol_index = histogram_symbols[i] & 0xffff; + histogram_argb[i] = (symbol_index << 8); + if (symbol_index >= max_index) { + max_index = symbol_index + 1; + } + } + histogram_image_size = max_index; + + VP8LPutBits(bw, histogram_bits - 2, 3); + i_percent_range = i_remaining_percent / 2; + i_remaining_percent -= i_percent_range; + if (!EncodeImageNoHuffman( + bw, histogram_argb, &hash_chain_histogram, &refs_array[2], + VP8LSubSampleSize(width, histogram_bits), + VP8LSubSampleSize(height, histogram_bits), quality, low_effort, + pic, i_percent_range, percent)) { + WebPSafeFree(histogram_argb); + goto Error; + } + WebPSafeFree(histogram_argb); + } + + // Store Huffman codes. + { + int i; + int max_tokens = 0; + // Find maximum number of symbols for the huffman tree-set. + for (i = 0; i < 5 * histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + if (max_tokens < codes->num_symbols) { + max_tokens = codes->num_symbols; + } + } + tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); + if (tokens == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + for (i = 0; i < 5 * histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + StoreHuffmanCode(bw, huff_tree, tokens, codes); + ClearHuffmanTreeIfOnlyOneSymbol(codes); + } + } + // Store actual literals. + hdr_size_tmp = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); + if (!StoreImageToBitMask(bw, width, histogram_bits, &refs_array[i_cache], + histogram_symbols, huffman_codes, pic)) { + goto Error; + } + // Keep track of the smallest image so far. + if (VP8LBitWriterNumBytes(bw) < bw_size_best) { + bw_size_best = VP8LBitWriterNumBytes(bw); + *cache_bits = cache_bits_tmp; + *hdr_size = hdr_size_tmp; + *data_size = + (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); + VP8LBitWriterSwap(bw, &bw_best); + } + WebPSafeFree(tokens); + tokens = NULL; + if (huffman_codes != NULL) { + WebPSafeFree(huffman_codes->codes); + WebPSafeFree(huffman_codes); + huffman_codes = NULL; + } + } + } + VP8LBitWriterSwap(bw, &bw_best); + + if (!WebPReportProgress(pic, percent_start + remaining_percent, percent)) { + goto Error; + } + + Error: + WebPSafeFree(tokens); + WebPSafeFree(huff_tree); + VP8LFreeHistogramSet(histogram_image); + VP8LFreeHistogram(tmp_histo); + VP8LHashChainClear(&hash_chain_histogram); + if (huffman_codes != NULL) { + WebPSafeFree(huffman_codes->codes); + WebPSafeFree(huffman_codes); + } + WebPSafeFree(histogram_symbols); + VP8LBitWriterWipeOut(&bw_best); + return (pic->error_code == VP8_ENC_OK); +} + +// ----------------------------------------------------------------------------- +// Transforms + +static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height, + VP8LBitWriter* const bw) { + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, SUBTRACT_GREEN_TRANSFORM, 2); + VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); +} + +static int ApplyPredictFilter(const VP8LEncoder* const enc, int width, + int height, int quality, int low_effort, + int used_subtract_green, VP8LBitWriter* const bw, + int percent_range, int* const percent) { + const int pred_bits = enc->transform_bits_; + const int transform_width = VP8LSubSampleSize(width, pred_bits); + const int transform_height = VP8LSubSampleSize(height, pred_bits); + // we disable near-lossless quantization if palette is used. + const int near_lossless_strength = + enc->use_palette_ ? 100 : enc->config_->near_lossless; + + if (!VP8LResidualImage( + width, height, pred_bits, low_effort, enc->argb_, enc->argb_scratch_, + enc->transform_data_, near_lossless_strength, enc->config_->exact, + used_subtract_green, enc->pic_, percent_range / 2, percent)) { + return 0; + } + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); + assert(pred_bits >= 2); + VP8LPutBits(bw, pred_bits - 2, 3); + return EncodeImageNoHuffman( + bw, enc->transform_data_, (VP8LHashChain*)&enc->hash_chain_, + (VP8LBackwardRefs*)&enc->refs_[0], transform_width, transform_height, + quality, low_effort, enc->pic_, percent_range - percent_range / 2, + percent); +} + +static int ApplyCrossColorFilter(const VP8LEncoder* const enc, int width, + int height, int quality, int low_effort, + VP8LBitWriter* const bw, int percent_range, + int* const percent) { + const int ccolor_transform_bits = enc->transform_bits_; + const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); + const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); + + if (!VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality, + enc->argb_, enc->transform_data_, enc->pic_, + percent_range / 2, percent)) { + return 0; + } + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2); + assert(ccolor_transform_bits >= 2); + VP8LPutBits(bw, ccolor_transform_bits - 2, 3); + return EncodeImageNoHuffman( + bw, enc->transform_data_, (VP8LHashChain*)&enc->hash_chain_, + (VP8LBackwardRefs*)&enc->refs_[0], transform_width, transform_height, + quality, low_effort, enc->pic_, percent_range - percent_range / 2, + percent); +} + +// ----------------------------------------------------------------------------- + +static int WriteRiffHeader(const WebPPicture* const pic, size_t riff_size, + size_t vp8l_size) { + uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { + 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', + 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE, + }; + PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); + PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size); + return pic->writer(riff, sizeof(riff), pic); +} + +static int WriteImageSize(const WebPPicture* const pic, + VP8LBitWriter* const bw) { + const int width = pic->width - 1; + const int height = pic->height - 1; + assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION); + + VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS); + VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS); + return !bw->error_; +} + +static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { + VP8LPutBits(bw, has_alpha, 1); + VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS); + return !bw->error_; +} + +static int WriteImage(const WebPPicture* const pic, VP8LBitWriter* const bw, + size_t* const coded_size) { + const uint8_t* const webpll_data = VP8LBitWriterFinish(bw); + const size_t webpll_size = VP8LBitWriterNumBytes(bw); + const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size; + const size_t pad = vp8l_size & 1; + const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad; + *coded_size = 0; + + if (bw->error_) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + if (!WriteRiffHeader(pic, riff_size, vp8l_size) || + !pic->writer(webpll_data, webpll_size, pic)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE); + } + + if (pad) { + const uint8_t pad_byte[1] = { 0 }; + if (!pic->writer(pad_byte, 1, pic)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE); + } + } + *coded_size = CHUNK_HEADER_SIZE + riff_size; + return 1; +} + +// ----------------------------------------------------------------------------- + +static void ClearTransformBuffer(VP8LEncoder* const enc) { + WebPSafeFree(enc->transform_mem_); + enc->transform_mem_ = NULL; + enc->transform_mem_size_ = 0; +} + +// Allocates the memory for argb (W x H) buffer, 2 rows of context for +// prediction and transform data. +// Flags influencing the memory allocated: +// enc->transform_bits_ +// enc->use_predict_, enc->use_cross_color_ +static int AllocateTransformBuffer(VP8LEncoder* const enc, int width, + int height) { + const uint64_t image_size = (uint64_t)width * height; + // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra + // pixel in each, plus 2 regular scanlines of bytes. + // TODO(skal): Clean up by using arithmetic in bytes instead of words. + const uint64_t argb_scratch_size = + enc->use_predict_ ? (width + 1) * 2 + (width * 2 + sizeof(uint32_t) - 1) / + sizeof(uint32_t) + : 0; + const uint64_t transform_data_size = + (enc->use_predict_ || enc->use_cross_color_) + ? (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) * + VP8LSubSampleSize(height, enc->transform_bits_) + : 0; + const uint64_t max_alignment_in_words = + (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t); + const uint64_t mem_size = image_size + max_alignment_in_words + + argb_scratch_size + max_alignment_in_words + + transform_data_size; + uint32_t* mem = enc->transform_mem_; + if (mem == NULL || mem_size > enc->transform_mem_size_) { + ClearTransformBuffer(enc); + mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem)); + if (mem == NULL) { + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + enc->transform_mem_ = mem; + enc->transform_mem_size_ = (size_t)mem_size; + enc->argb_content_ = kEncoderNone; + } + enc->argb_ = mem; + mem = (uint32_t*)WEBP_ALIGN(mem + image_size); + enc->argb_scratch_ = mem; + mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size); + enc->transform_data_ = mem; + + enc->current_width_ = width; + return 1; +} + +static int MakeInputImageCopy(VP8LEncoder* const enc) { + const WebPPicture* const picture = enc->pic_; + const int width = picture->width; + const int height = picture->height; + + if (!AllocateTransformBuffer(enc, width, height)) return 0; + if (enc->argb_content_ == kEncoderARGB) return 1; + + { + uint32_t* dst = enc->argb_; + const uint32_t* src = picture->argb; + int y; + for (y = 0; y < height; ++y) { + memcpy(dst, src, width * sizeof(*dst)); + dst += width; + src += picture->argb_stride; + } + } + enc->argb_content_ = kEncoderARGB; + assert(enc->current_width_ == width); + return 1; +} + +// ----------------------------------------------------------------------------- + +#define APPLY_PALETTE_GREEDY_MAX 4 + +static WEBP_INLINE uint32_t SearchColorGreedy(const uint32_t palette[], + int palette_size, + uint32_t color) { + (void)palette_size; + assert(palette_size < APPLY_PALETTE_GREEDY_MAX); + assert(3 == APPLY_PALETTE_GREEDY_MAX - 1); + if (color == palette[0]) return 0; + if (color == palette[1]) return 1; + if (color == palette[2]) return 2; + return 3; +} + +static WEBP_INLINE uint32_t ApplyPaletteHash0(uint32_t color) { + // Focus on the green color. + return (color >> 8) & 0xff; +} + +#define PALETTE_INV_SIZE_BITS 11 +#define PALETTE_INV_SIZE (1 << PALETTE_INV_SIZE_BITS) + +static WEBP_INLINE uint32_t ApplyPaletteHash1(uint32_t color) { + // Forget about alpha. + return ((uint32_t)((color & 0x00ffffffu) * 4222244071ull)) >> + (32 - PALETTE_INV_SIZE_BITS); +} + +static WEBP_INLINE uint32_t ApplyPaletteHash2(uint32_t color) { + // Forget about alpha. + return ((uint32_t)((color & 0x00ffffffu) * ((1ull << 31) - 1))) >> + (32 - PALETTE_INV_SIZE_BITS); +} + +// Use 1 pixel cache for ARGB pixels. +#define APPLY_PALETTE_FOR(COLOR_INDEX) do { \ + uint32_t prev_pix = palette[0]; \ + uint32_t prev_idx = 0; \ + for (y = 0; y < height; ++y) { \ + for (x = 0; x < width; ++x) { \ + const uint32_t pix = src[x]; \ + if (pix != prev_pix) { \ + prev_idx = COLOR_INDEX; \ + prev_pix = pix; \ + } \ + tmp_row[x] = prev_idx; \ + } \ + VP8LBundleColorMap(tmp_row, width, xbits, dst); \ + src += src_stride; \ + dst += dst_stride; \ + } \ +} while (0) + +// Remap argb values in src[] to packed palettes entries in dst[] +// using 'row' as a temporary buffer of size 'width'. +// We assume that all src[] values have a corresponding entry in the palette. +// Note: src[] can be the same as dst[] +static int ApplyPalette(const uint32_t* src, uint32_t src_stride, uint32_t* dst, + uint32_t dst_stride, const uint32_t* palette, + int palette_size, int width, int height, int xbits, + const WebPPicture* const pic) { + // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be + // made to work in-place. + uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); + int x, y; + + if (tmp_row == NULL) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + if (palette_size < APPLY_PALETTE_GREEDY_MAX) { + APPLY_PALETTE_FOR(SearchColorGreedy(palette, palette_size, pix)); + } else { + int i, j; + uint16_t buffer[PALETTE_INV_SIZE]; + uint32_t (*const hash_functions[])(uint32_t) = { + ApplyPaletteHash0, ApplyPaletteHash1, ApplyPaletteHash2 + }; + + // Try to find a perfect hash function able to go from a color to an index + // within 1 << PALETTE_INV_SIZE_BITS in order to build a hash map to go + // from color to index in palette. + for (i = 0; i < 3; ++i) { + int use_LUT = 1; + // Set each element in buffer to max uint16_t. + memset(buffer, 0xff, sizeof(buffer)); + for (j = 0; j < palette_size; ++j) { + const uint32_t ind = hash_functions[i](palette[j]); + if (buffer[ind] != 0xffffu) { + use_LUT = 0; + break; + } else { + buffer[ind] = j; + } + } + if (use_LUT) break; + } + + if (i == 0) { + APPLY_PALETTE_FOR(buffer[ApplyPaletteHash0(pix)]); + } else if (i == 1) { + APPLY_PALETTE_FOR(buffer[ApplyPaletteHash1(pix)]); + } else if (i == 2) { + APPLY_PALETTE_FOR(buffer[ApplyPaletteHash2(pix)]); + } else { + uint32_t idx_map[MAX_PALETTE_SIZE]; + uint32_t palette_sorted[MAX_PALETTE_SIZE]; + PrepareMapToPalette(palette, palette_size, palette_sorted, idx_map); + APPLY_PALETTE_FOR( + idx_map[SearchColorNoIdx(palette_sorted, pix, palette_size)]); + } + } + WebPSafeFree(tmp_row); + return 1; +} +#undef APPLY_PALETTE_FOR +#undef PALETTE_INV_SIZE_BITS +#undef PALETTE_INV_SIZE +#undef APPLY_PALETTE_GREEDY_MAX + +// Note: Expects "enc->palette_" to be set properly. +static int MapImageFromPalette(VP8LEncoder* const enc, int in_place) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const uint32_t* const palette = enc->palette_; + const uint32_t* src = in_place ? enc->argb_ : pic->argb; + const int src_stride = in_place ? enc->current_width_ : pic->argb_stride; + const int palette_size = enc->palette_size_; + int xbits; + + // Replace each input pixel by corresponding palette index. + // This is done line by line. + if (palette_size <= 4) { + xbits = (palette_size <= 2) ? 3 : 2; + } else { + xbits = (palette_size <= 16) ? 1 : 0; + } + + if (!AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height)) { + return 0; + } + if (!ApplyPalette(src, src_stride, + enc->argb_, enc->current_width_, + palette, palette_size, width, height, xbits, pic)) { + return 0; + } + enc->argb_content_ = kEncoderPalette; + return 1; +} + +// Save palette_[] to bitstream. +static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, int low_effort, + VP8LEncoder* const enc, + int percent_range, int* const percent) { + int i; + uint32_t tmp_palette[MAX_PALETTE_SIZE]; + const int palette_size = enc->palette_size_; + const uint32_t* const palette = enc->palette_; + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2); + assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE); + VP8LPutBits(bw, palette_size - 1, 8); + for (i = palette_size - 1; i >= 1; --i) { + tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); + } + tmp_palette[0] = palette[0]; + return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, + &enc->refs_[0], palette_size, 1, /*quality=*/20, + low_effort, enc->pic_, percent_range, percent); +} + +// ----------------------------------------------------------------------------- +// VP8LEncoder + +static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, + const WebPPicture* const picture) { + VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc)); + if (enc == NULL) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + return NULL; + } + enc->config_ = config; + enc->pic_ = picture; + enc->argb_content_ = kEncoderNone; + + VP8LEncDspInit(); + + return enc; +} + +static void VP8LEncoderDelete(VP8LEncoder* enc) { + if (enc != NULL) { + int i; + VP8LHashChainClear(&enc->hash_chain_); + for (i = 0; i < 4; ++i) VP8LBackwardRefsClear(&enc->refs_[i]); + ClearTransformBuffer(enc); + WebPSafeFree(enc); + } +} + +// ----------------------------------------------------------------------------- +// Main call + +typedef struct { + const WebPConfig* config_; + const WebPPicture* picture_; + VP8LBitWriter* bw_; + VP8LEncoder* enc_; + CrunchConfig crunch_configs_[CRUNCH_CONFIGS_MAX]; + int num_crunch_configs_; + int red_and_blue_always_zero_; + WebPAuxStats* stats_; +} StreamEncodeContext; + +static int EncodeStreamHook(void* input, void* data2) { + StreamEncodeContext* const params = (StreamEncodeContext*)input; + const WebPConfig* const config = params->config_; + const WebPPicture* const picture = params->picture_; + VP8LBitWriter* const bw = params->bw_; + VP8LEncoder* const enc = params->enc_; + const CrunchConfig* const crunch_configs = params->crunch_configs_; + const int num_crunch_configs = params->num_crunch_configs_; + const int red_and_blue_always_zero = params->red_and_blue_always_zero_; +#if !defined(WEBP_DISABLE_STATS) + WebPAuxStats* const stats = params->stats_; +#endif + const int quality = (int)config->quality; + const int low_effort = (config->method == 0); +#if (WEBP_NEAR_LOSSLESS == 1) + const int width = picture->width; +#endif + const int height = picture->height; + const size_t byte_position = VP8LBitWriterNumBytes(bw); + int percent = 2; // for WebPProgressHook +#if (WEBP_NEAR_LOSSLESS == 1) + int use_near_lossless = 0; +#endif + int hdr_size = 0; + int data_size = 0; + int use_delta_palette = 0; + int idx; + size_t best_size = ~(size_t)0; + VP8LBitWriter bw_init = *bw, bw_best; + (void)data2; + + if (!VP8LBitWriterInit(&bw_best, 0) || + (num_crunch_configs > 1 && !VP8LBitWriterClone(bw, &bw_best))) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + for (idx = 0; idx < num_crunch_configs; ++idx) { + const int entropy_idx = crunch_configs[idx].entropy_idx_; + int remaining_percent = 97 / num_crunch_configs, percent_range; + enc->use_palette_ = + (entropy_idx == kPalette) || (entropy_idx == kPaletteAndSpatial); + enc->use_subtract_green_ = + (entropy_idx == kSubGreen) || (entropy_idx == kSpatialSubGreen); + enc->use_predict_ = (entropy_idx == kSpatial) || + (entropy_idx == kSpatialSubGreen) || + (entropy_idx == kPaletteAndSpatial); + // When using a palette, R/B==0, hence no need to test for cross-color. + if (low_effort || enc->use_palette_) { + enc->use_cross_color_ = 0; + } else { + enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; + } + // Reset any parameter in the encoder that is set in the previous iteration. + enc->cache_bits_ = 0; + VP8LBackwardRefsClear(&enc->refs_[0]); + VP8LBackwardRefsClear(&enc->refs_[1]); + +#if (WEBP_NEAR_LOSSLESS == 1) + // Apply near-lossless preprocessing. + use_near_lossless = (config->near_lossless < 100) && !enc->use_palette_ && + !enc->use_predict_; + if (use_near_lossless) { + if (!AllocateTransformBuffer(enc, width, height)) goto Error; + if ((enc->argb_content_ != kEncoderNearLossless) && + !VP8ApplyNearLossless(picture, config->near_lossless, enc->argb_)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + enc->argb_content_ = kEncoderNearLossless; + } else { + enc->argb_content_ = kEncoderNone; + } +#else + enc->argb_content_ = kEncoderNone; +#endif + + // Encode palette + if (enc->use_palette_) { + if (!PaletteSort(crunch_configs[idx].palette_sorting_type_, enc->pic_, + enc->palette_sorted_, enc->palette_size_, + enc->palette_)) { + WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + percent_range = remaining_percent / 4; + if (!EncodePalette(bw, low_effort, enc, percent_range, &percent)) { + goto Error; + } + remaining_percent -= percent_range; + if (!MapImageFromPalette(enc, use_delta_palette)) goto Error; + // If using a color cache, do not have it bigger than the number of + // colors. + if (enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { + enc->cache_bits_ = BitsLog2Floor(enc->palette_size_) + 1; + } + } + if (!use_delta_palette) { + // In case image is not packed. + if (enc->argb_content_ != kEncoderNearLossless && + enc->argb_content_ != kEncoderPalette) { + if (!MakeInputImageCopy(enc)) goto Error; + } + + // ----------------------------------------------------------------------- + // Apply transforms and write transform data. + + if (enc->use_subtract_green_) { + ApplySubtractGreen(enc, enc->current_width_, height, bw); + } + + if (enc->use_predict_) { + percent_range = remaining_percent / 3; + if (!ApplyPredictFilter(enc, enc->current_width_, height, quality, + low_effort, enc->use_subtract_green_, bw, + percent_range, &percent)) { + goto Error; + } + remaining_percent -= percent_range; + } + + if (enc->use_cross_color_) { + percent_range = remaining_percent / 2; + if (!ApplyCrossColorFilter(enc, enc->current_width_, height, quality, + low_effort, bw, percent_range, &percent)) { + goto Error; + } + remaining_percent -= percent_range; + } + } + + VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. + + // ------------------------------------------------------------------------- + // Encode and write the transformed image. + if (!EncodeImageInternal( + bw, enc->argb_, &enc->hash_chain_, enc->refs_, enc->current_width_, + height, quality, low_effort, &crunch_configs[idx], + &enc->cache_bits_, enc->histo_bits_, byte_position, &hdr_size, + &data_size, picture, remaining_percent, &percent)) { + goto Error; + } + + // If we are better than what we already have. + if (VP8LBitWriterNumBytes(bw) < best_size) { + best_size = VP8LBitWriterNumBytes(bw); + // Store the BitWriter. + VP8LBitWriterSwap(bw, &bw_best); +#if !defined(WEBP_DISABLE_STATS) + // Update the stats. + if (stats != NULL) { + stats->lossless_features = 0; + if (enc->use_predict_) stats->lossless_features |= 1; + if (enc->use_cross_color_) stats->lossless_features |= 2; + if (enc->use_subtract_green_) stats->lossless_features |= 4; + if (enc->use_palette_) stats->lossless_features |= 8; + stats->histogram_bits = enc->histo_bits_; + stats->transform_bits = enc->transform_bits_; + stats->cache_bits = enc->cache_bits_; + stats->palette_size = enc->palette_size_; + stats->lossless_size = (int)(best_size - byte_position); + stats->lossless_hdr_size = hdr_size; + stats->lossless_data_size = data_size; + } +#endif + } + // Reset the bit writer for the following iteration if any. + if (num_crunch_configs > 1) VP8LBitWriterReset(&bw_init, bw); + } + VP8LBitWriterSwap(&bw_best, bw); + + Error: + VP8LBitWriterWipeOut(&bw_best); + // The hook should return false in case of error. + return (params->picture_->error_code == VP8_ENC_OK); +} + +int VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, + VP8LBitWriter* const bw_main) { + VP8LEncoder* const enc_main = VP8LEncoderNew(config, picture); + VP8LEncoder* enc_side = NULL; + CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX]; + int num_crunch_configs_main, num_crunch_configs_side = 0; + int idx; + int red_and_blue_always_zero = 0; + WebPWorker worker_main, worker_side; + StreamEncodeContext params_main, params_side; + // The main thread uses picture->stats, the side thread uses stats_side. + WebPAuxStats stats_side; + VP8LBitWriter bw_side; + WebPPicture picture_side; + const WebPWorkerInterface* const worker_interface = WebPGetWorkerInterface(); + int ok_main; + + if (enc_main == NULL || !VP8LBitWriterInit(&bw_side, 0)) { + VP8LEncoderDelete(enc_main); + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + // Avoid "garbage value" error from Clang's static analysis tool. + if (!WebPPictureInit(&picture_side)) { + goto Error; + } + + // Analyze image (entropy, num_palettes etc) + if (!EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main, + &red_and_blue_always_zero) || + !EncoderInit(enc_main)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Split the configs between the main and side threads (if any). + if (config->thread_level > 0) { + num_crunch_configs_side = num_crunch_configs_main / 2; + for (idx = 0; idx < num_crunch_configs_side; ++idx) { + params_side.crunch_configs_[idx] = + crunch_configs[num_crunch_configs_main - num_crunch_configs_side + + idx]; + } + params_side.num_crunch_configs_ = num_crunch_configs_side; + } + num_crunch_configs_main -= num_crunch_configs_side; + for (idx = 0; idx < num_crunch_configs_main; ++idx) { + params_main.crunch_configs_[idx] = crunch_configs[idx]; + } + params_main.num_crunch_configs_ = num_crunch_configs_main; + + // Fill in the parameters for the thread workers. + { + const int params_size = (num_crunch_configs_side > 0) ? 2 : 1; + for (idx = 0; idx < params_size; ++idx) { + // Create the parameters for each worker. + WebPWorker* const worker = (idx == 0) ? &worker_main : &worker_side; + StreamEncodeContext* const param = + (idx == 0) ? ¶ms_main : ¶ms_side; + param->config_ = config; + param->red_and_blue_always_zero_ = red_and_blue_always_zero; + if (idx == 0) { + param->picture_ = picture; + param->stats_ = picture->stats; + param->bw_ = bw_main; + param->enc_ = enc_main; + } else { + // Create a side picture (error_code is not thread-safe). + if (!WebPPictureView(picture, /*left=*/0, /*top=*/0, picture->width, + picture->height, &picture_side)) { + assert(0); + } + picture_side.progress_hook = NULL; // Progress hook is not thread-safe. + param->picture_ = &picture_side; // No need to free a view afterwards. + param->stats_ = (picture->stats == NULL) ? NULL : &stats_side; + // Create a side bit writer. + if (!VP8LBitWriterClone(bw_main, &bw_side)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + param->bw_ = &bw_side; + // Create a side encoder. + enc_side = VP8LEncoderNew(config, &picture_side); + if (enc_side == NULL || !EncoderInit(enc_side)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + // Copy the values that were computed for the main encoder. + enc_side->histo_bits_ = enc_main->histo_bits_; + enc_side->transform_bits_ = enc_main->transform_bits_; + enc_side->palette_size_ = enc_main->palette_size_; + memcpy(enc_side->palette_, enc_main->palette_, + sizeof(enc_main->palette_)); + memcpy(enc_side->palette_sorted_, enc_main->palette_sorted_, + sizeof(enc_main->palette_sorted_)); + param->enc_ = enc_side; + } + // Create the workers. + worker_interface->Init(worker); + worker->data1 = param; + worker->data2 = NULL; + worker->hook = EncodeStreamHook; + } + } + + // Start the second thread if needed. + if (num_crunch_configs_side != 0) { + if (!worker_interface->Reset(&worker_side)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } +#if !defined(WEBP_DISABLE_STATS) + // This line is here and not in the param initialization above to remove a + // Clang static analyzer warning. + if (picture->stats != NULL) { + memcpy(&stats_side, picture->stats, sizeof(stats_side)); + } +#endif + worker_interface->Launch(&worker_side); + } + // Execute the main thread. + worker_interface->Execute(&worker_main); + ok_main = worker_interface->Sync(&worker_main); + worker_interface->End(&worker_main); + if (num_crunch_configs_side != 0) { + // Wait for the second thread. + const int ok_side = worker_interface->Sync(&worker_side); + worker_interface->End(&worker_side); + if (!ok_main || !ok_side) { + if (picture->error_code == VP8_ENC_OK) { + assert(picture_side.error_code != VP8_ENC_OK); + WebPEncodingSetError(picture, picture_side.error_code); + } + goto Error; + } + if (VP8LBitWriterNumBytes(&bw_side) < VP8LBitWriterNumBytes(bw_main)) { + VP8LBitWriterSwap(bw_main, &bw_side); +#if !defined(WEBP_DISABLE_STATS) + if (picture->stats != NULL) { + memcpy(picture->stats, &stats_side, sizeof(*picture->stats)); + } +#endif + } + } + + Error: + VP8LBitWriterWipeOut(&bw_side); + VP8LEncoderDelete(enc_main); + VP8LEncoderDelete(enc_side); + return (picture->error_code == VP8_ENC_OK); +} + +#undef CRUNCH_CONFIGS_MAX +#undef CRUNCH_SUBCONFIGS_MAX + +int VP8LEncodeImage(const WebPConfig* const config, + const WebPPicture* const picture) { + int width, height; + int has_alpha; + size_t coded_size; + int percent = 0; + int initial_size; + VP8LBitWriter bw; + + if (picture == NULL) return 0; + + if (config == NULL || picture->argb == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); + } + + width = picture->width; + height = picture->height; + // Initialize BitWriter with size corresponding to 16 bpp to photo images and + // 8 bpp for graphical images. + initial_size = (config->image_hint == WEBP_HINT_GRAPH) ? + width * height : width * height * 2; + if (!VP8LBitWriterInit(&bw, initial_size)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + if (!WebPReportProgress(picture, 1, &percent)) { + UserAbort: + WebPEncodingSetError(picture, VP8_ENC_ERROR_USER_ABORT); + goto Error; + } + // Reset stats (for pure lossless coding) + if (picture->stats != NULL) { + WebPAuxStats* const stats = picture->stats; + memset(stats, 0, sizeof(*stats)); + stats->PSNR[0] = 99.f; + stats->PSNR[1] = 99.f; + stats->PSNR[2] = 99.f; + stats->PSNR[3] = 99.f; + stats->PSNR[4] = 99.f; + } + + // Write image size. + if (!WriteImageSize(picture, &bw)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + has_alpha = WebPPictureHasTransparency(picture); + // Write the non-trivial Alpha flag and lossless version. + if (!WriteRealAlphaAndVersion(&bw, has_alpha)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + if (!WebPReportProgress(picture, 2, &percent)) goto UserAbort; + + // Encode main image stream. + if (!VP8LEncodeStream(config, picture, &bw)) goto Error; + + if (!WebPReportProgress(picture, 99, &percent)) goto UserAbort; + + // Finish the RIFF chunk. + if (!WriteImage(picture, &bw, &coded_size)) goto Error; + + if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; + +#if !defined(WEBP_DISABLE_STATS) + // Save size. + if (picture->stats != NULL) { + picture->stats->coded_size += (int)coded_size; + picture->stats->lossless_size = (int)coded_size; + } +#endif + + if (picture->extra_info != NULL) { + const int mb_w = (width + 15) >> 4; + const int mb_h = (height + 15) >> 4; + memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info)); + } + + Error: + if (bw.error_) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + VP8LBitWriterWipeOut(&bw); + return (picture->error_code == VP8_ENC_OK); +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/enc/vp8li_enc.h b/libraries/webp/src/enc/vp8li_enc.h new file mode 100644 index 0000000000..09032ecc77 --- /dev/null +++ b/libraries/webp/src/enc/vp8li_enc.h @@ -0,0 +1,124 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Lossless encoder: internal header. +// +// Author: Vikas Arora (vikaas.arora@gmail.com) + +#ifndef WEBP_ENC_VP8LI_ENC_H_ +#define WEBP_ENC_VP8LI_ENC_H_ + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif +// Either WEBP_NEAR_LOSSLESS is defined as 0 in config.h when compiling to +// disable near-lossless, or it is enabled by default. +#ifndef WEBP_NEAR_LOSSLESS +#define WEBP_NEAR_LOSSLESS 1 +#endif + +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/utils/bit_writer_utils.h" +#include "include/webp/encode.h" +#include "include/webp/format_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// maximum value of transform_bits_ in VP8LEncoder. +#define MAX_TRANSFORM_BITS 6 + +typedef enum { + kEncoderNone = 0, + kEncoderARGB, + kEncoderNearLossless, + kEncoderPalette +} VP8LEncoderARGBContent; + +typedef struct { + const WebPConfig* config_; // user configuration and parameters + const WebPPicture* pic_; // input picture. + + uint32_t* argb_; // Transformed argb image data. + VP8LEncoderARGBContent argb_content_; // Content type of the argb buffer. + uint32_t* argb_scratch_; // Scratch memory for argb rows + // (used for prediction). + uint32_t* transform_data_; // Scratch memory for transform data. + uint32_t* transform_mem_; // Currently allocated memory. + size_t transform_mem_size_; // Currently allocated memory size. + + int current_width_; // Corresponds to packed image width. + + // Encoding parameters derived from quality parameter. + int histo_bits_; + int transform_bits_; // <= MAX_TRANSFORM_BITS. + int cache_bits_; // If equal to 0, don't use color cache. + + // Encoding parameters derived from image characteristics. + int use_cross_color_; + int use_subtract_green_; + int use_predict_; + int use_palette_; + int palette_size_; + uint32_t palette_[MAX_PALETTE_SIZE]; + // Sorted version of palette_ for cache purposes. + uint32_t palette_sorted_[MAX_PALETTE_SIZE]; + + // Some 'scratch' (potentially large) objects. + struct VP8LBackwardRefs refs_[4]; // Backward Refs array for temporaries. + VP8LHashChain hash_chain_; // HashChain data for constructing + // backward references. +} VP8LEncoder; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +// Encodes the picture. +// Returns 0 if config or picture is NULL or picture doesn't have valid argb +// input. +int VP8LEncodeImage(const WebPConfig* const config, + const WebPPicture* const picture); + +// Encodes the main image stream using the supplied bit writer. +// Returns false in case of error (stored in picture->error_code). +int VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, VP8LBitWriter* const bw); + +#if (WEBP_NEAR_LOSSLESS == 1) +// in near_lossless.c +// Near lossless preprocessing in RGB color-space. +int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, + uint32_t* const argb_dst); +#endif + +//------------------------------------------------------------------------------ +// Image transforms in predictor.c. + +// pic and percent are for progress. +// Returns false in case of error (stored in pic->error_code). +int VP8LResidualImage(int width, int height, int bits, int low_effort, + uint32_t* const argb, uint32_t* const argb_scratch, + uint32_t* const image, int near_lossless, int exact, + int used_subtract_green, const WebPPicture* const pic, + int percent_range, int* const percent); + +int VP8LColorSpaceTransform(int width, int height, int bits, int quality, + uint32_t* const argb, uint32_t* image, + const WebPPicture* const pic, int percent_range, + int* const percent); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_ENC_VP8LI_ENC_H_ diff --git a/libraries/webp/src/enc/webp_enc.c b/libraries/webp/src/enc/webp_enc.c new file mode 100644 index 0000000000..583fe6a8bb --- /dev/null +++ b/libraries/webp/src/enc/webp_enc.c @@ -0,0 +1,410 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main entry point +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include +#include + +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/vp8li_enc.h" +#include "src/utils/utils.h" + +// #define PRINT_MEMORY_INFO + +#ifdef PRINT_MEMORY_INFO +#include +#endif + +//------------------------------------------------------------------------------ + +int WebPGetEncoderVersion(void) { + return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION; +} + +//------------------------------------------------------------------------------ +// VP8Encoder +//------------------------------------------------------------------------------ + +static void ResetSegmentHeader(VP8Encoder* const enc) { + VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; + hdr->num_segments_ = enc->config_->segments; + hdr->update_map_ = (hdr->num_segments_ > 1); + hdr->size_ = 0; +} + +static void ResetFilterHeader(VP8Encoder* const enc) { + VP8EncFilterHeader* const hdr = &enc->filter_hdr_; + hdr->simple_ = 1; + hdr->level_ = 0; + hdr->sharpness_ = 0; + hdr->i4x4_lf_delta_ = 0; +} + +static void ResetBoundaryPredictions(VP8Encoder* const enc) { + // init boundary values once for all + // Note: actually, initializing the preds_[] is only needed for intra4. + int i; + uint8_t* const top = enc->preds_ - enc->preds_w_; + uint8_t* const left = enc->preds_ - 1; + for (i = -1; i < 4 * enc->mb_w_; ++i) { + top[i] = B_DC_PRED; + } + for (i = 0; i < 4 * enc->mb_h_; ++i) { + left[i * enc->preds_w_] = B_DC_PRED; + } + enc->nz_[-1] = 0; // constant +} + +// Mapping from config->method_ to coding tools used. +//-------------------+---+---+---+---+---+---+---+ +// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | +//-------------------+---+---+---+---+---+---+---+ +// fast probe | x | | | x | | | | +//-------------------+---+---+---+---+---+---+---+ +// dynamic proba | ~ | x | x | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// fast mode analysis|[x]|[x]| | | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// basic rd-opt | | | | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// disto-refine i4/16| x | x | x | | | | | +//-------------------+---+---+---+---+---+---+---+ +// disto-refine uv | | x | x | | | | | +//-------------------+---+---+---+---+---+---+---+ +// rd-opt i4/16 | | | ~ | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// token buffer (opt)| | | | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// Trellis | | | | | | x |Ful| +//-------------------+---+---+---+---+---+---+---+ +// full-SNS | | | | | x | x | x | +//-------------------+---+---+---+---+---+---+---+ + +static void MapConfigToTools(VP8Encoder* const enc) { + const WebPConfig* const config = enc->config_; + const int method = config->method; + const int limit = 100 - config->partition_limit; + enc->method_ = method; + enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL + : (method >= 5) ? RD_OPT_TRELLIS + : (method >= 3) ? RD_OPT_BASIC + : RD_OPT_NONE; + enc->max_i4_header_bits_ = + 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block + (limit * limit) / (100 * 100); // ... modulated with a quadratic curve. + + // partition0 = 512k max. + enc->mb_header_limit_ = + (score_t)256 * 510 * 8 * 1024 / (enc->mb_w_ * enc->mb_h_); + + enc->thread_level_ = config->thread_level; + + enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0); + if (!config->low_memory) { +#if !defined(DISABLE_TOKEN_BUFFER) + enc->use_tokens_ = (enc->rd_opt_level_ >= RD_OPT_BASIC); // need rd stats +#endif + if (enc->use_tokens_) { + enc->num_parts_ = 1; // doesn't work with multi-partition + } + } +} + +// Memory scaling with dimensions: +// memory (bytes) ~= 2.25 * w + 0.0625 * w * h +// +// Typical memory footprint (614x440 picture) +// encoder: 22111 +// info: 4368 +// preds: 17741 +// top samples: 1263 +// non-zero: 175 +// lf-stats: 0 +// total: 45658 +// Transient object sizes: +// VP8EncIterator: 3360 +// VP8ModeScore: 872 +// VP8SegmentInfo: 732 +// VP8EncProba: 18352 +// LFStats: 2048 +// Picture size (yuv): 419328 + +static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, + WebPPicture* const picture) { + VP8Encoder* enc; + const int use_filter = + (config->filter_strength > 0) || (config->autofilter > 0); + const int mb_w = (picture->width + 15) >> 4; + const int mb_h = (picture->height + 15) >> 4; + const int preds_w = 4 * mb_w + 1; + const int preds_h = 4 * mb_h + 1; + const size_t preds_size = preds_w * preds_h * sizeof(*enc->preds_); + const int top_stride = mb_w * 16; + const size_t nz_size = (mb_w + 1) * sizeof(*enc->nz_) + WEBP_ALIGN_CST; + const size_t info_size = mb_w * mb_h * sizeof(*enc->mb_info_); + const size_t samples_size = + 2 * top_stride * sizeof(*enc->y_top_) // top-luma/u/v + + WEBP_ALIGN_CST; // align all + const size_t lf_stats_size = + config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0; + const size_t top_derr_size = + (config->quality <= ERROR_DIFFUSION_QUALITY || config->pass > 1) ? + mb_w * sizeof(*enc->top_derr_) : 0; + uint8_t* mem; + const uint64_t size = (uint64_t)sizeof(*enc) // main struct + + WEBP_ALIGN_CST // cache alignment + + info_size // modes info + + preds_size // prediction modes + + samples_size // top/left samples + + top_derr_size // top diffusion error + + nz_size // coeff context bits + + lf_stats_size; // autofilter stats + +#ifdef PRINT_MEMORY_INFO + printf("===================================\n"); + printf("Memory used:\n" + " encoder: %ld\n" + " info: %ld\n" + " preds: %ld\n" + " top samples: %ld\n" + " top diffusion: %ld\n" + " non-zero: %ld\n" + " lf-stats: %ld\n" + " total: %ld\n", + sizeof(*enc) + WEBP_ALIGN_CST, info_size, + preds_size, samples_size, top_derr_size, nz_size, lf_stats_size, size); + printf("Transient object sizes:\n" + " VP8EncIterator: %ld\n" + " VP8ModeScore: %ld\n" + " VP8SegmentInfo: %ld\n" + " VP8EncProba: %ld\n" + " LFStats: %ld\n", + sizeof(VP8EncIterator), sizeof(VP8ModeScore), + sizeof(VP8SegmentInfo), sizeof(VP8EncProba), + sizeof(LFStats)); + printf("Picture size (yuv): %ld\n", + mb_w * mb_h * 384 * sizeof(uint8_t)); + printf("===================================\n"); +#endif + mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem)); + if (mem == NULL) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + return NULL; + } + enc = (VP8Encoder*)mem; + mem = (uint8_t*)WEBP_ALIGN(mem + sizeof(*enc)); + memset(enc, 0, sizeof(*enc)); + enc->num_parts_ = 1 << config->partitions; + enc->mb_w_ = mb_w; + enc->mb_h_ = mb_h; + enc->preds_w_ = preds_w; + enc->mb_info_ = (VP8MBInfo*)mem; + mem += info_size; + enc->preds_ = mem + 1 + enc->preds_w_; + mem += preds_size; + enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem); + mem += nz_size; + enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL; + mem += lf_stats_size; + + // top samples (all 16-aligned) + mem = (uint8_t*)WEBP_ALIGN(mem); + enc->y_top_ = mem; + enc->uv_top_ = enc->y_top_ + top_stride; + mem += 2 * top_stride; + enc->top_derr_ = top_derr_size ? (DError*)mem : NULL; + mem += top_derr_size; + assert(mem <= (uint8_t*)enc + size); + + enc->config_ = config; + enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2; + enc->pic_ = picture; + enc->percent_ = 0; + + MapConfigToTools(enc); + VP8EncDspInit(); + VP8DefaultProbas(enc); + ResetSegmentHeader(enc); + ResetFilterHeader(enc); + ResetBoundaryPredictions(enc); + VP8EncDspCostInit(); + VP8EncInitAlpha(enc); + + // lower quality means smaller output -> we modulate a little the page + // size based on quality. This is just a crude 1rst-order prediction. + { + const float scale = 1.f + config->quality * 5.f / 100.f; // in [1,6] + VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale)); + } + return enc; +} + +static int DeleteVP8Encoder(VP8Encoder* enc) { + int ok = 1; + if (enc != NULL) { + ok = VP8EncDeleteAlpha(enc); + VP8TBufferClear(&enc->tokens_); + WebPSafeFree(enc); + } + return ok; +} + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_DISABLE_STATS) +static double GetPSNR(uint64_t err, uint64_t size) { + return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.; +} + +static void FinalizePSNR(const VP8Encoder* const enc) { + WebPAuxStats* stats = enc->pic_->stats; + const uint64_t size = enc->sse_count_; + const uint64_t* const sse = enc->sse_; + stats->PSNR[0] = (float)GetPSNR(sse[0], size); + stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4); + stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4); + stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2); + stats->PSNR[4] = (float)GetPSNR(sse[3], size); +} +#endif // !defined(WEBP_DISABLE_STATS) + +static void StoreStats(VP8Encoder* const enc) { +#if !defined(WEBP_DISABLE_STATS) + WebPAuxStats* const stats = enc->pic_->stats; + if (stats != NULL) { + int i, s; + for (i = 0; i < NUM_MB_SEGMENTS; ++i) { + stats->segment_level[i] = enc->dqm_[i].fstrength_; + stats->segment_quant[i] = enc->dqm_[i].quant_; + for (s = 0; s <= 2; ++s) { + stats->residual_bytes[s][i] = enc->residual_bytes_[s][i]; + } + } + FinalizePSNR(enc); + stats->coded_size = enc->coded_size_; + for (i = 0; i < 3; ++i) { + stats->block_count[i] = enc->block_count_[i]; + } + } +#else // defined(WEBP_DISABLE_STATS) + WebPReportProgress(enc->pic_, 100, &enc->percent_); // done! +#endif // !defined(WEBP_DISABLE_STATS) +} + +int WebPEncodingSetError(const WebPPicture* const pic, + WebPEncodingError error) { + assert((int)error < VP8_ENC_ERROR_LAST); + assert((int)error >= VP8_ENC_OK); + // The oldest error reported takes precedence over the new one. + if (pic->error_code == VP8_ENC_OK) { + ((WebPPicture*)pic)->error_code = error; + } + return 0; +} + +int WebPReportProgress(const WebPPicture* const pic, + int percent, int* const percent_store) { + if (percent_store != NULL && percent != *percent_store) { + *percent_store = percent; + if (pic->progress_hook && !pic->progress_hook(percent, pic)) { + // user abort requested + return WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT); + } + } + return 1; // ok +} +//------------------------------------------------------------------------------ + +int WebPEncode(const WebPConfig* config, WebPPicture* pic) { + int ok = 0; + if (pic == NULL) return 0; + + pic->error_code = VP8_ENC_OK; // all ok so far + if (config == NULL) { // bad params + return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); + } + if (!WebPValidateConfig(config)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + if (!WebPValidatePicture(pic)) return 0; + if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); + } + + if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); + + if (!config->lossless) { + VP8Encoder* enc = NULL; + + if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) { + // Make sure we have YUVA samples. + if (config->use_sharp_yuv || (config->preprocessing & 4)) { + if (!WebPPictureSharpARGBToYUVA(pic)) { + return 0; + } + } else { + float dithering = 0.f; + if (config->preprocessing & 2) { + const float x = config->quality / 100.f; + const float x2 = x * x; + // slowly decreasing from max dithering at low quality (q->0) + // to 0.5 dithering amplitude at high quality (q->100) + dithering = 1.0f + (0.5f - 1.0f) * x2 * x2; + } + if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) { + return 0; + } + } + } + + if (!config->exact) { + WebPCleanupTransparentArea(pic); + } + + enc = InitVP8Encoder(config, pic); + if (enc == NULL) return 0; // pic->error is already set. + // Note: each of the tasks below account for 20% in the progress report. + ok = VP8EncAnalyze(enc); + + // Analysis is done, proceed to actual coding. + ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel + if (!enc->use_tokens_) { + ok = ok && VP8EncLoop(enc); + } else { + ok = ok && VP8EncTokenLoop(enc); + } + ok = ok && VP8EncFinishAlpha(enc); + + ok = ok && VP8EncWrite(enc); + StoreStats(enc); + if (!ok) { + VP8EncFreeBitWriters(enc); + } + ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok + } else { + // Make sure we have ARGB samples. + if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { + return 0; + } + + if (!config->exact) { + WebPReplaceTransparentPixels(pic, 0x000000); + } + + ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. + } + + return ok; +} diff --git a/libraries/webp/src/mux/anim_encode.c b/libraries/webp/src/mux/anim_encode.c new file mode 100644 index 0000000000..46d30e4e44 --- /dev/null +++ b/libraries/webp/src/mux/anim_encode.c @@ -0,0 +1,1611 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// AnimEncoder implementation. +// + +#include +#include +#include // for pow() +#include +#include // for abs() + +#include "src/mux/animi.h" +#include "src/utils/utils.h" +#include "include/webp/decode.h" +#include "include/webp/encode.h" +#include "include/webp/format_constants.h" +#include "include/webp/mux.h" +#include "include/webp/types.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +#define ERROR_STR_MAX_LENGTH 100 + +//------------------------------------------------------------------------------ +// Internal structs. + +// Stores frame rectangle dimensions. +typedef struct { + int x_offset_, y_offset_, width_, height_; +} FrameRectangle; + +// Used to store two candidates of encoded data for an animation frame. One of +// the two will be chosen later. +typedef struct { + WebPMuxFrameInfo sub_frame_; // Encoded frame rectangle. + WebPMuxFrameInfo key_frame_; // Encoded frame if it is a key-frame. + int is_key_frame_; // True if 'key_frame' has been chosen. +} EncodedFrame; + +struct WebPAnimEncoder { + const int canvas_width_; // Canvas width. + const int canvas_height_; // Canvas height. + const WebPAnimEncoderOptions options_; // Global encoding options. + + FrameRectangle prev_rect_; // Previous WebP frame rectangle. + WebPConfig last_config_; // Cached in case a re-encode is needed. + WebPConfig last_config_reversed_; // If 'last_config_' uses lossless, then + // this config uses lossy and vice versa; + // only valid if 'options_.allow_mixed' + // is true. + + WebPPicture* curr_canvas_; // Only pointer; we don't own memory. + + // Canvas buffers. + WebPPicture curr_canvas_copy_; // Possibly modified current canvas. + int curr_canvas_copy_modified_; // True if pixels in 'curr_canvas_copy_' + // differ from those in 'curr_canvas_'. + + WebPPicture prev_canvas_; // Previous canvas. + WebPPicture prev_canvas_disposed_; // Previous canvas disposed to background. + + // Encoded data. + EncodedFrame* encoded_frames_; // Array of encoded frames. + size_t size_; // Number of allocated frames. + size_t start_; // Frame start index. + size_t count_; // Number of valid frames. + size_t flush_count_; // If >0, 'flush_count' frames starting from + // 'start' are ready to be added to mux. + + // key-frame related. + int64_t best_delta_; // min(canvas size - frame size) over the frames. + // Can be negative in certain cases due to + // transparent pixels in a frame. + int keyframe_; // Index of selected key-frame relative to 'start_'. + int count_since_key_frame_; // Frames seen since the last key-frame. + + int first_timestamp_; // Timestamp of the first frame. + int prev_timestamp_; // Timestamp of the last added frame. + int prev_candidate_undecided_; // True if it's not yet decided if previous + // frame would be a sub-frame or a key-frame. + + // Misc. + int is_first_frame_; // True if first frame is yet to be added/being added. + int got_null_frame_; // True if WebPAnimEncoderAdd() has already been called + // with a NULL frame. + + size_t in_frame_count_; // Number of input frames processed so far. + size_t out_frame_count_; // Number of frames added to mux so far. This may be + // different from 'in_frame_count_' due to merging. + + WebPMux* mux_; // Muxer to assemble the WebP bitstream. + char error_str_[ERROR_STR_MAX_LENGTH]; // Error string. Empty if no error. +}; + +// ----------------------------------------------------------------------------- +// Life of WebPAnimEncoder object. + +#define DELTA_INFINITY (1ULL << 32) +#define KEYFRAME_NONE (-1) + +// Reset the counters in the WebPAnimEncoder. +static void ResetCounters(WebPAnimEncoder* const enc) { + enc->start_ = 0; + enc->count_ = 0; + enc->flush_count_ = 0; + enc->best_delta_ = DELTA_INFINITY; + enc->keyframe_ = KEYFRAME_NONE; +} + +static void DisableKeyframes(WebPAnimEncoderOptions* const enc_options) { + enc_options->kmax = INT_MAX; + enc_options->kmin = enc_options->kmax - 1; +} + +#define MAX_CACHED_FRAMES 30 + +static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) { + int print_warning = enc_options->verbose; + + if (enc_options->minimize_size) { + DisableKeyframes(enc_options); + } + + if (enc_options->kmax == 1) { // All frames will be key-frames. + enc_options->kmin = 0; + enc_options->kmax = 0; + return; + } else if (enc_options->kmax <= 0) { + DisableKeyframes(enc_options); + print_warning = 0; + } + + if (enc_options->kmin >= enc_options->kmax) { + enc_options->kmin = enc_options->kmax - 1; + if (print_warning) { + fprintf(stderr, "WARNING: Setting kmin = %d, so that kmin < kmax.\n", + enc_options->kmin); + } + } else { + const int kmin_limit = enc_options->kmax / 2 + 1; + if (enc_options->kmin < kmin_limit && kmin_limit < enc_options->kmax) { + // This ensures that enc.keyframe + kmin >= kmax is always true. So, we + // can flush all the frames in the 'count_since_key_frame == kmax' case. + enc_options->kmin = kmin_limit; + if (print_warning) { + fprintf(stderr, + "WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n", + enc_options->kmin); + } + } + } + // Limit the max number of frames that are allocated. + if (enc_options->kmax - enc_options->kmin > MAX_CACHED_FRAMES) { + enc_options->kmin = enc_options->kmax - MAX_CACHED_FRAMES; + if (print_warning) { + fprintf(stderr, + "WARNING: Setting kmin = %d, so that kmax - kmin <= %d.\n", + enc_options->kmin, MAX_CACHED_FRAMES); + } + } + assert(enc_options->kmin < enc_options->kmax); +} + +#undef MAX_CACHED_FRAMES + +static void DefaultEncoderOptions(WebPAnimEncoderOptions* const enc_options) { + enc_options->anim_params.loop_count = 0; + enc_options->anim_params.bgcolor = 0xffffffff; // White. + enc_options->minimize_size = 0; + DisableKeyframes(enc_options); + enc_options->allow_mixed = 0; + enc_options->verbose = 0; +} + +int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options, + int abi_version) { + if (enc_options == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { + return 0; + } + DefaultEncoderOptions(enc_options); + return 1; +} + +// This starting value is more fit to WebPCleanupTransparentAreaLossless(). +#define TRANSPARENT_COLOR 0x00000000 + +static void ClearRectangle(WebPPicture* const picture, + int left, int top, int width, int height) { + int j; + for (j = top; j < top + height; ++j) { + uint32_t* const dst = picture->argb + j * picture->argb_stride; + int i; + for (i = left; i < left + width; ++i) { + dst[i] = TRANSPARENT_COLOR; + } + } +} + +static void WebPUtilClearPic(WebPPicture* const picture, + const FrameRectangle* const rect) { + if (rect != NULL) { + ClearRectangle(picture, rect->x_offset_, rect->y_offset_, + rect->width_, rect->height_); + } else { + ClearRectangle(picture, 0, 0, picture->width, picture->height); + } +} + +static void MarkNoError(WebPAnimEncoder* const enc) { + enc->error_str_[0] = '\0'; // Empty string. +} + +static void MarkError(WebPAnimEncoder* const enc, const char* str) { + if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s.", str) < 0) { + assert(0); // FIX ME! + } +} + +static void MarkError2(WebPAnimEncoder* const enc, + const char* str, int error_code) { + if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s: %d.", str, + error_code) < 0) { + assert(0); // FIX ME! + } +} + +WebPAnimEncoder* WebPAnimEncoderNewInternal( + int width, int height, const WebPAnimEncoderOptions* enc_options, + int abi_version) { + WebPAnimEncoder* enc; + + if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { + return NULL; + } + if (width <= 0 || height <= 0 || + (width * (uint64_t)height) >= MAX_IMAGE_AREA) { + return NULL; + } + + enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc)); + if (enc == NULL) return NULL; + MarkNoError(enc); + + // Dimensions and options. + *(int*)&enc->canvas_width_ = width; + *(int*)&enc->canvas_height_ = height; + if (enc_options != NULL) { + *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options; + SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); + } else { + DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); + } + + // Canvas buffers. + if (!WebPPictureInit(&enc->curr_canvas_copy_) || + !WebPPictureInit(&enc->prev_canvas_) || + !WebPPictureInit(&enc->prev_canvas_disposed_)) { + goto Err; + } + enc->curr_canvas_copy_.width = width; + enc->curr_canvas_copy_.height = height; + enc->curr_canvas_copy_.use_argb = 1; + if (!WebPPictureAlloc(&enc->curr_canvas_copy_) || + !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) || + !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) { + goto Err; + } + WebPUtilClearPic(&enc->prev_canvas_, NULL); + enc->curr_canvas_copy_modified_ = 1; + + // Encoded frames. + ResetCounters(enc); + // Note: one extra storage is for the previous frame. + enc->size_ = enc->options_.kmax - enc->options_.kmin + 1; + // We need space for at least 2 frames. But when kmin, kmax are both zero, + // enc->size_ will be 1. So we handle that special case below. + if (enc->size_ < 2) enc->size_ = 2; + enc->encoded_frames_ = + (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_)); + if (enc->encoded_frames_ == NULL) goto Err; + + enc->mux_ = WebPMuxNew(); + if (enc->mux_ == NULL) goto Err; + + enc->count_since_key_frame_ = 0; + enc->first_timestamp_ = 0; + enc->prev_timestamp_ = 0; + enc->prev_candidate_undecided_ = 0; + enc->is_first_frame_ = 1; + enc->got_null_frame_ = 0; + + return enc; // All OK. + + Err: + WebPAnimEncoderDelete(enc); + return NULL; +} + +// Release the data contained by 'encoded_frame'. +static void FrameRelease(EncodedFrame* const encoded_frame) { + if (encoded_frame != NULL) { + WebPDataClear(&encoded_frame->sub_frame_.bitstream); + WebPDataClear(&encoded_frame->key_frame_.bitstream); + memset(encoded_frame, 0, sizeof(*encoded_frame)); + } +} + +void WebPAnimEncoderDelete(WebPAnimEncoder* enc) { + if (enc != NULL) { + WebPPictureFree(&enc->curr_canvas_copy_); + WebPPictureFree(&enc->prev_canvas_); + WebPPictureFree(&enc->prev_canvas_disposed_); + if (enc->encoded_frames_ != NULL) { + size_t i; + for (i = 0; i < enc->size_; ++i) { + FrameRelease(&enc->encoded_frames_[i]); + } + WebPSafeFree(enc->encoded_frames_); + } + WebPMuxDelete(enc->mux_); + WebPSafeFree(enc); + } +} + +// ----------------------------------------------------------------------------- +// Frame addition. + +// Returns cached frame at the given 'position'. +static EncodedFrame* GetFrame(const WebPAnimEncoder* const enc, + size_t position) { + assert(enc->start_ + position < enc->size_); + return &enc->encoded_frames_[enc->start_ + position]; +} + +typedef int (*ComparePixelsFunc)(const uint32_t*, int, const uint32_t*, int, + int, int); + +// Returns true if 'length' number of pixels in 'src' and 'dst' are equal, +// assuming the given step sizes between pixels. +// 'max_allowed_diff' is unused and only there to allow function pointer use. +static WEBP_INLINE int ComparePixelsLossless(const uint32_t* src, int src_step, + const uint32_t* dst, int dst_step, + int length, int max_allowed_diff) { + (void)max_allowed_diff; + assert(length > 0); + while (length-- > 0) { + if (*src != *dst) { + return 0; + } + src += src_step; + dst += dst_step; + } + return 1; +} + +// Helper to check if each channel in 'src' and 'dst' is at most off by +// 'max_allowed_diff'. +static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst, + int max_allowed_diff) { + const int src_a = (src >> 24) & 0xff; + const int src_r = (src >> 16) & 0xff; + const int src_g = (src >> 8) & 0xff; + const int src_b = (src >> 0) & 0xff; + const int dst_a = (dst >> 24) & 0xff; + const int dst_r = (dst >> 16) & 0xff; + const int dst_g = (dst >> 8) & 0xff; + const int dst_b = (dst >> 0) & 0xff; + + return (src_a == dst_a) && + (abs(src_r - dst_r) * dst_a <= (max_allowed_diff * 255)) && + (abs(src_g - dst_g) * dst_a <= (max_allowed_diff * 255)) && + (abs(src_b - dst_b) * dst_a <= (max_allowed_diff * 255)); +} + +// Returns true if 'length' number of pixels in 'src' and 'dst' are within an +// error bound, assuming the given step sizes between pixels. +static WEBP_INLINE int ComparePixelsLossy(const uint32_t* src, int src_step, + const uint32_t* dst, int dst_step, + int length, int max_allowed_diff) { + assert(length > 0); + while (length-- > 0) { + if (!PixelsAreSimilar(*src, *dst, max_allowed_diff)) { + return 0; + } + src += src_step; + dst += dst_step; + } + return 1; +} + +static int IsEmptyRect(const FrameRectangle* const rect) { + return (rect->width_ == 0) || (rect->height_ == 0); +} + +static int QualityToMaxDiff(float quality) { + const double val = pow(quality / 100., 0.5); + const double max_diff = 31 * (1 - val) + 1 * val; + return (int)(max_diff + 0.5); +} + +// Assumes that an initial valid guess of change rectangle 'rect' is passed. +static void MinimizeChangeRectangle(const WebPPicture* const src, + const WebPPicture* const dst, + FrameRectangle* const rect, + int is_lossless, float quality) { + int i, j; + const ComparePixelsFunc compare_pixels = + is_lossless ? ComparePixelsLossless : ComparePixelsLossy; + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + const int max_allowed_diff = is_lossless ? 0 : max_allowed_diff_lossy; + + // Assumption/correctness checks. + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + + // Left boundary. + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t* const src_argb = + &src->argb[rect->y_offset_ * src->argb_stride + i]; + const uint32_t* const dst_argb = + &dst->argb[rect->y_offset_ * dst->argb_stride + i]; + if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, + rect->height_, max_allowed_diff)) { + --rect->width_; // Redundant column. + ++rect->x_offset_; + } else { + break; + } + } + if (rect->width_ == 0) goto NoChange; + + // Right boundary. + for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) { + const uint32_t* const src_argb = + &src->argb[rect->y_offset_ * src->argb_stride + i]; + const uint32_t* const dst_argb = + &dst->argb[rect->y_offset_ * dst->argb_stride + i]; + if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, + rect->height_, max_allowed_diff)) { + --rect->width_; // Redundant column. + } else { + break; + } + } + if (rect->width_ == 0) goto NoChange; + + // Top boundary. + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + const uint32_t* const src_argb = + &src->argb[j * src->argb_stride + rect->x_offset_]; + const uint32_t* const dst_argb = + &dst->argb[j * dst->argb_stride + rect->x_offset_]; + if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_, + max_allowed_diff)) { + --rect->height_; // Redundant row. + ++rect->y_offset_; + } else { + break; + } + } + if (rect->height_ == 0) goto NoChange; + + // Bottom boundary. + for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) { + const uint32_t* const src_argb = + &src->argb[j * src->argb_stride + rect->x_offset_]; + const uint32_t* const dst_argb = + &dst->argb[j * dst->argb_stride + rect->x_offset_]; + if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_, + max_allowed_diff)) { + --rect->height_; // Redundant row. + } else { + break; + } + } + if (rect->height_ == 0) goto NoChange; + + if (IsEmptyRect(rect)) { + NoChange: + rect->x_offset_ = 0; + rect->y_offset_ = 0; + rect->width_ = 0; + rect->height_ = 0; + } +} + +// Snap rectangle to even offsets (and adjust dimensions if needed). +static WEBP_INLINE void SnapToEvenOffsets(FrameRectangle* const rect) { + rect->width_ += (rect->x_offset_ & 1); + rect->height_ += (rect->y_offset_ & 1); + rect->x_offset_ &= ~1; + rect->y_offset_ &= ~1; +} + +typedef struct { + int should_try_; // Should try this set of parameters. + int empty_rect_allowed_; // Frame with empty rectangle can be skipped. + FrameRectangle rect_ll_; // Frame rectangle for lossless compression. + WebPPicture sub_frame_ll_; // Sub-frame pic for lossless compression. + FrameRectangle rect_lossy_; // Frame rectangle for lossy compression. + // Could be smaller than rect_ll_ as pixels + // with small diffs can be ignored. + WebPPicture sub_frame_lossy_; // Sub-frame pic for lossless compression. +} SubFrameParams; + +static int SubFrameParamsInit(SubFrameParams* const params, + int should_try, int empty_rect_allowed) { + params->should_try_ = should_try; + params->empty_rect_allowed_ = empty_rect_allowed; + if (!WebPPictureInit(¶ms->sub_frame_ll_) || + !WebPPictureInit(¶ms->sub_frame_lossy_)) { + return 0; + } + return 1; +} + +static void SubFrameParamsFree(SubFrameParams* const params) { + WebPPictureFree(¶ms->sub_frame_ll_); + WebPPictureFree(¶ms->sub_frame_lossy_); +} + +// Given previous and current canvas, picks the optimal rectangle for the +// current frame based on 'is_lossless' and other parameters. Assumes that the +// initial guess 'rect' is valid. +static int GetSubRect(const WebPPicture* const prev_canvas, + const WebPPicture* const curr_canvas, int is_key_frame, + int is_first_frame, int empty_rect_allowed, + int is_lossless, float quality, + FrameRectangle* const rect, + WebPPicture* const sub_frame) { + if (!is_key_frame || is_first_frame) { // Optimize frame rectangle. + // Note: This behaves as expected for first frame, as 'prev_canvas' is + // initialized to a fully transparent canvas in the beginning. + MinimizeChangeRectangle(prev_canvas, curr_canvas, rect, + is_lossless, quality); + } + + if (IsEmptyRect(rect)) { + if (empty_rect_allowed) { // No need to get 'sub_frame'. + return 1; + } else { // Force a 1x1 rectangle. + rect->width_ = 1; + rect->height_ = 1; + assert(rect->x_offset_ == 0); + assert(rect->y_offset_ == 0); + } + } + + SnapToEvenOffsets(rect); + return WebPPictureView(curr_canvas, rect->x_offset_, rect->y_offset_, + rect->width_, rect->height_, sub_frame); +} + +// Picks optimal frame rectangle for both lossless and lossy compression. The +// initial guess for frame rectangles will be the full canvas. +static int GetSubRects(const WebPPicture* const prev_canvas, + const WebPPicture* const curr_canvas, int is_key_frame, + int is_first_frame, float quality, + SubFrameParams* const params) { + // Lossless frame rectangle. + params->rect_ll_.x_offset_ = 0; + params->rect_ll_.y_offset_ = 0; + params->rect_ll_.width_ = curr_canvas->width; + params->rect_ll_.height_ = curr_canvas->height; + if (!GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + params->empty_rect_allowed_, 1, quality, + ¶ms->rect_ll_, ¶ms->sub_frame_ll_)) { + return 0; + } + // Lossy frame rectangle. + params->rect_lossy_ = params->rect_ll_; // seed with lossless rect. + return GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + params->empty_rect_allowed_, 0, quality, + ¶ms->rect_lossy_, ¶ms->sub_frame_lossy_); +} + +static WEBP_INLINE int clip(int v, int min_v, int max_v) { + return (v < min_v) ? min_v : (v > max_v) ? max_v : v; +} + +int WebPAnimEncoderRefineRect( + const WebPPicture* const prev_canvas, const WebPPicture* const curr_canvas, + int is_lossless, float quality, int* const x_offset, int* const y_offset, + int* const width, int* const height) { + FrameRectangle rect; + int right, left, bottom, top; + if (prev_canvas == NULL || curr_canvas == NULL || + prev_canvas->width != curr_canvas->width || + prev_canvas->height != curr_canvas->height || + !prev_canvas->use_argb || !curr_canvas->use_argb) { + return 0; + } + right = clip(*x_offset + *width, 0, curr_canvas->width); + left = clip(*x_offset, 0, curr_canvas->width - 1); + bottom = clip(*y_offset + *height, 0, curr_canvas->height); + top = clip(*y_offset, 0, curr_canvas->height - 1); + rect.x_offset_ = left; + rect.y_offset_ = top; + rect.width_ = clip(right - left, 0, curr_canvas->width - rect.x_offset_); + rect.height_ = clip(bottom - top, 0, curr_canvas->height - rect.y_offset_); + MinimizeChangeRectangle(prev_canvas, curr_canvas, &rect, is_lossless, + quality); + SnapToEvenOffsets(&rect); + *x_offset = rect.x_offset_; + *y_offset = rect.y_offset_; + *width = rect.width_; + *height = rect.height_; + return 1; +} + +static void DisposeFrameRectangle(int dispose_method, + const FrameRectangle* const rect, + WebPPicture* const curr_canvas) { + assert(rect != NULL); + if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { + WebPUtilClearPic(curr_canvas, rect); + } +} + +static uint32_t RectArea(const FrameRectangle* const rect) { + return (uint32_t)rect->width_ * rect->height_; +} + +static int IsLosslessBlendingPossible(const WebPPicture* const src, + const WebPPicture* const dst, + const FrameRectangle* const rect) { + int i, j; + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; + const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; + const uint32_t dst_alpha = dst_pixel >> 24; + if (dst_alpha != 0xff && src_pixel != dst_pixel) { + // In this case, if we use blending, we can't attain the desired + // 'dst_pixel' value for this pixel. So, blending is not possible. + return 0; + } + } + } + return 1; +} + +static int IsLossyBlendingPossible(const WebPPicture* const src, + const WebPPicture* const dst, + const FrameRectangle* const rect, + float quality) { + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + int i, j; + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; + const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; + const uint32_t dst_alpha = dst_pixel >> 24; + if (dst_alpha != 0xff && + !PixelsAreSimilar(src_pixel, dst_pixel, max_allowed_diff_lossy)) { + // In this case, if we use blending, we can't attain the desired + // 'dst_pixel' value for this pixel. So, blending is not possible. + return 0; + } + } + } + return 1; +} + +// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by +// transparent pixels. +// Returns true if at least one pixel gets modified. +static int IncreaseTransparency(const WebPPicture* const src, + const FrameRectangle* const rect, + WebPPicture* const dst) { + int i, j; + int modified = 0; + assert(src != NULL && dst != NULL && rect != NULL); + assert(src->width == dst->width && src->height == dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + const uint32_t* const psrc = src->argb + j * src->argb_stride; + uint32_t* const pdst = dst->argb + j * dst->argb_stride; + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + if (psrc[i] == pdst[i] && pdst[i] != TRANSPARENT_COLOR) { + pdst[i] = TRANSPARENT_COLOR; + modified = 1; + } + } + } + return modified; +} + +#undef TRANSPARENT_COLOR + +// Replace similar blocks of pixels by a 'see-through' transparent block +// with uniform average color. +// Assumes lossy compression is being used. +// Returns true if at least one pixel gets modified. +static int FlattenSimilarBlocks(const WebPPicture* const src, + const FrameRectangle* const rect, + WebPPicture* const dst, float quality) { + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + int i, j; + int modified = 0; + const int block_size = 8; + const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1); + const int y_end = (rect->y_offset_ + rect->height_) & ~(block_size - 1); + const int x_start = (rect->x_offset_ + block_size) & ~(block_size - 1); + const int x_end = (rect->x_offset_ + rect->width_) & ~(block_size - 1); + assert(src != NULL && dst != NULL && rect != NULL); + assert(src->width == dst->width && src->height == dst->height); + assert((block_size & (block_size - 1)) == 0); // must be a power of 2 + // Iterate over each block and count similar pixels. + for (j = y_start; j < y_end; j += block_size) { + for (i = x_start; i < x_end; i += block_size) { + int cnt = 0; + int avg_r = 0, avg_g = 0, avg_b = 0; + int x, y; + const uint32_t* const psrc = src->argb + j * src->argb_stride + i; + uint32_t* const pdst = dst->argb + j * dst->argb_stride + i; + for (y = 0; y < block_size; ++y) { + for (x = 0; x < block_size; ++x) { + const uint32_t src_pixel = psrc[x + y * src->argb_stride]; + const int alpha = src_pixel >> 24; + if (alpha == 0xff && + PixelsAreSimilar(src_pixel, pdst[x + y * dst->argb_stride], + max_allowed_diff_lossy)) { + ++cnt; + avg_r += (src_pixel >> 16) & 0xff; + avg_g += (src_pixel >> 8) & 0xff; + avg_b += (src_pixel >> 0) & 0xff; + } + } + } + // If we have a fully similar block, we replace it with an + // average transparent block. This compresses better in lossy mode. + if (cnt == block_size * block_size) { + const uint32_t color = (0x00 << 24) | + ((avg_r / cnt) << 16) | + ((avg_g / cnt) << 8) | + ((avg_b / cnt) << 0); + for (y = 0; y < block_size; ++y) { + for (x = 0; x < block_size; ++x) { + pdst[x + y * dst->argb_stride] = color; + } + } + modified = 1; + } + } + } + return modified; +} + +static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic, + WebPMemoryWriter* const memory) { + pic->use_argb = 1; + pic->writer = WebPMemoryWrite; + pic->custom_ptr = memory; + if (!WebPEncode(config, pic)) { + return 0; + } + return 1; +} + +// Struct representing a candidate encoded frame including its metadata. +typedef struct { + WebPMemoryWriter mem_; + WebPMuxFrameInfo info_; + FrameRectangle rect_; + int evaluate_; // True if this candidate should be evaluated. +} Candidate; + +// Generates a candidate encoded frame given a picture and metadata. +static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame, + const FrameRectangle* const rect, + const WebPConfig* const encoder_config, + int use_blending, + Candidate* const candidate) { + WebPConfig config = *encoder_config; + WebPEncodingError error_code = VP8_ENC_OK; + assert(candidate != NULL); + memset(candidate, 0, sizeof(*candidate)); + + // Set frame rect and info. + candidate->rect_ = *rect; + candidate->info_.id = WEBP_CHUNK_ANMF; + candidate->info_.x_offset = rect->x_offset_; + candidate->info_.y_offset = rect->y_offset_; + candidate->info_.dispose_method = WEBP_MUX_DISPOSE_NONE; // Set later. + candidate->info_.blend_method = + use_blending ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND; + candidate->info_.duration = 0; // Set in next call to WebPAnimEncoderAdd(). + + // Encode picture. + WebPMemoryWriterInit(&candidate->mem_); + + if (!config.lossless && use_blending) { + // Disable filtering to avoid blockiness in reconstructed frames at the + // time of decoding. + config.autofilter = 0; + config.filter_strength = 0; + } + if (!EncodeFrame(&config, sub_frame, &candidate->mem_)) { + error_code = sub_frame->error_code; + goto Err; + } + + candidate->evaluate_ = 1; + return error_code; + + Err: + WebPMemoryWriterClear(&candidate->mem_); + return error_code; +} + +static void CopyCurrentCanvas(WebPAnimEncoder* const enc) { + if (enc->curr_canvas_copy_modified_) { + WebPCopyPixels(enc->curr_canvas_, &enc->curr_canvas_copy_); + enc->curr_canvas_copy_.progress_hook = enc->curr_canvas_->progress_hook; + enc->curr_canvas_copy_.user_data = enc->curr_canvas_->user_data; + enc->curr_canvas_copy_modified_ = 0; + } +} + +enum { + LL_DISP_NONE = 0, + LL_DISP_BG, + LOSSY_DISP_NONE, + LOSSY_DISP_BG, + CANDIDATE_COUNT +}; + +#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold. +#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold. + +// Generates candidates for a given dispose method given pre-filled sub-frame +// 'params'. +static WebPEncodingError GenerateCandidates( + WebPAnimEncoder* const enc, Candidate candidates[CANDIDATE_COUNT], + WebPMuxAnimDispose dispose_method, int is_lossless, int is_key_frame, + SubFrameParams* const params, + const WebPConfig* const config_ll, const WebPConfig* const config_lossy) { + WebPEncodingError error_code = VP8_ENC_OK; + const int is_dispose_none = (dispose_method == WEBP_MUX_DISPOSE_NONE); + Candidate* const candidate_ll = + is_dispose_none ? &candidates[LL_DISP_NONE] : &candidates[LL_DISP_BG]; + Candidate* const candidate_lossy = is_dispose_none + ? &candidates[LOSSY_DISP_NONE] + : &candidates[LOSSY_DISP_BG]; + WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; + const WebPPicture* const prev_canvas = + is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_; + int use_blending_ll, use_blending_lossy; + int evaluate_ll, evaluate_lossy; + + CopyCurrentCanvas(enc); + use_blending_ll = + !is_key_frame && + IsLosslessBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_ll_); + use_blending_lossy = + !is_key_frame && + IsLossyBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_lossy_, + config_lossy->quality); + + // Pick candidates to be tried. + if (!enc->options_.allow_mixed) { + evaluate_ll = is_lossless; + evaluate_lossy = !is_lossless; + } else if (enc->options_.minimize_size) { + evaluate_ll = 1; + evaluate_lossy = 1; + } else { // Use a heuristic for trying lossless and/or lossy compression. + const int num_colors = WebPGetColorPalette(¶ms->sub_frame_ll_, NULL); + evaluate_ll = (num_colors < MAX_COLORS_LOSSLESS); + evaluate_lossy = (num_colors >= MIN_COLORS_LOSSY); + } + + // Generate candidates. + if (evaluate_ll) { + CopyCurrentCanvas(enc); + if (use_blending_ll) { + enc->curr_canvas_copy_modified_ = + IncreaseTransparency(prev_canvas, ¶ms->rect_ll_, curr_canvas); + } + error_code = EncodeCandidate(¶ms->sub_frame_ll_, ¶ms->rect_ll_, + config_ll, use_blending_ll, candidate_ll); + if (error_code != VP8_ENC_OK) return error_code; + } + if (evaluate_lossy) { + CopyCurrentCanvas(enc); + if (use_blending_lossy) { + enc->curr_canvas_copy_modified_ = + FlattenSimilarBlocks(prev_canvas, ¶ms->rect_lossy_, curr_canvas, + config_lossy->quality); + } + error_code = + EncodeCandidate(¶ms->sub_frame_lossy_, ¶ms->rect_lossy_, + config_lossy, use_blending_lossy, candidate_lossy); + if (error_code != VP8_ENC_OK) return error_code; + enc->curr_canvas_copy_modified_ = 1; + } + return error_code; +} + +#undef MIN_COLORS_LOSSY +#undef MAX_COLORS_LOSSLESS + +static void GetEncodedData(const WebPMemoryWriter* const memory, + WebPData* const encoded_data) { + encoded_data->bytes = memory->mem; + encoded_data->size = memory->size; +} + +// Sets dispose method of the previous frame to be 'dispose_method'. +static void SetPreviousDisposeMethod(WebPAnimEncoder* const enc, + WebPMuxAnimDispose dispose_method) { + const size_t position = enc->count_ - 2; + EncodedFrame* const prev_enc_frame = GetFrame(enc, position); + assert(enc->count_ >= 2); // As current and previous frames are in enc. + + if (enc->prev_candidate_undecided_) { + assert(dispose_method == WEBP_MUX_DISPOSE_NONE); + prev_enc_frame->sub_frame_.dispose_method = dispose_method; + prev_enc_frame->key_frame_.dispose_method = dispose_method; + } else { + WebPMuxFrameInfo* const prev_info = prev_enc_frame->is_key_frame_ + ? &prev_enc_frame->key_frame_ + : &prev_enc_frame->sub_frame_; + prev_info->dispose_method = dispose_method; + } +} + +static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) { + const size_t position = enc->count_ - 1; + EncodedFrame* const prev_enc_frame = GetFrame(enc, position); + int new_duration; + + assert(enc->count_ >= 1); + assert(!prev_enc_frame->is_key_frame_ || + prev_enc_frame->sub_frame_.duration == + prev_enc_frame->key_frame_.duration); + assert(prev_enc_frame->sub_frame_.duration == + (prev_enc_frame->sub_frame_.duration & (MAX_DURATION - 1))); + assert(duration == (duration & (MAX_DURATION - 1))); + + new_duration = prev_enc_frame->sub_frame_.duration + duration; + if (new_duration >= MAX_DURATION) { // Special case. + // Separate out previous frame from earlier merged frames to avoid overflow. + // We add a 1x1 transparent frame for the previous frame, with blending on. + const FrameRectangle rect = { 0, 0, 1, 1 }; + const uint8_t lossless_1x1_bytes[] = { + 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, + 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, + 0x10, 0x88, 0x88, 0x08 + }; + const WebPData lossless_1x1 = { + lossless_1x1_bytes, sizeof(lossless_1x1_bytes) + }; + const uint8_t lossy_1x1_bytes[] = { + 0x52, 0x49, 0x46, 0x46, 0x40, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, + 0x56, 0x50, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x50, 0x48, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x34, 0x25, 0xa4, 0x00, 0x03, 0x70, 0x00, 0xfe, 0xfb, 0xfd, 0x50, 0x00 + }; + const WebPData lossy_1x1 = { lossy_1x1_bytes, sizeof(lossy_1x1_bytes) }; + const int can_use_lossless = + (enc->last_config_.lossless || enc->options_.allow_mixed); + EncodedFrame* const curr_enc_frame = GetFrame(enc, enc->count_); + curr_enc_frame->is_key_frame_ = 0; + curr_enc_frame->sub_frame_.id = WEBP_CHUNK_ANMF; + curr_enc_frame->sub_frame_.x_offset = 0; + curr_enc_frame->sub_frame_.y_offset = 0; + curr_enc_frame->sub_frame_.dispose_method = WEBP_MUX_DISPOSE_NONE; + curr_enc_frame->sub_frame_.blend_method = WEBP_MUX_BLEND; + curr_enc_frame->sub_frame_.duration = duration; + if (!WebPDataCopy(can_use_lossless ? &lossless_1x1 : &lossy_1x1, + &curr_enc_frame->sub_frame_.bitstream)) { + return 0; + } + ++enc->count_; + ++enc->count_since_key_frame_; + enc->flush_count_ = enc->count_ - 1; + enc->prev_candidate_undecided_ = 0; + enc->prev_rect_ = rect; + } else { // Regular case. + // Increase duration of the previous frame by 'duration'. + prev_enc_frame->sub_frame_.duration = new_duration; + prev_enc_frame->key_frame_.duration = new_duration; + } + return 1; +} + +// Pick the candidate encoded frame with smallest size and release other +// candidates. +// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should +// also be a criteria, in addition to sizes. +static void PickBestCandidate(WebPAnimEncoder* const enc, + Candidate* const candidates, int is_key_frame, + EncodedFrame* const encoded_frame) { + int i; + int best_idx = -1; + size_t best_size = ~0; + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + const size_t candidate_size = candidates[i].mem_.size; + if (candidate_size < best_size) { + best_idx = i; + best_size = candidate_size; + } + } + } + assert(best_idx != -1); + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + if (i == best_idx) { + WebPMuxFrameInfo* const dst = is_key_frame + ? &encoded_frame->key_frame_ + : &encoded_frame->sub_frame_; + *dst = candidates[i].info_; + GetEncodedData(&candidates[i].mem_, &dst->bitstream); + if (!is_key_frame) { + // Note: Previous dispose method only matters for non-keyframes. + // Also, we don't want to modify previous dispose method that was + // selected when a non key-frame was assumed. + const WebPMuxAnimDispose prev_dispose_method = + (best_idx == LL_DISP_NONE || best_idx == LOSSY_DISP_NONE) + ? WEBP_MUX_DISPOSE_NONE + : WEBP_MUX_DISPOSE_BACKGROUND; + SetPreviousDisposeMethod(enc, prev_dispose_method); + } + enc->prev_rect_ = candidates[i].rect_; // save for next frame. + } else { + WebPMemoryWriterClear(&candidates[i].mem_); + candidates[i].evaluate_ = 0; + } + } + } +} + +// Depending on the configuration, tries different compressions +// (lossy/lossless), dispose methods, blending methods etc to encode the current +// frame and outputs the best one in 'encoded_frame'. +// 'frame_skipped' will be set to true if this frame should actually be skipped. +static WebPEncodingError SetFrame(WebPAnimEncoder* const enc, + const WebPConfig* const config, + int is_key_frame, + EncodedFrame* const encoded_frame, + int* const frame_skipped) { + int i; + WebPEncodingError error_code = VP8_ENC_OK; + const WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; + const WebPPicture* const prev_canvas = &enc->prev_canvas_; + Candidate candidates[CANDIDATE_COUNT]; + const int is_lossless = config->lossless; + const int consider_lossless = is_lossless || enc->options_.allow_mixed; + const int consider_lossy = !is_lossless || enc->options_.allow_mixed; + const int is_first_frame = enc->is_first_frame_; + + // First frame cannot be skipped as there is no 'previous frame' to merge it + // to. So, empty rectangle is not allowed for the first frame. + const int empty_rect_allowed_none = !is_first_frame; + + // Even if there is exact pixel match between 'disposed previous canvas' and + // 'current canvas', we can't skip current frame, as there may not be exact + // pixel match between 'previous canvas' and 'current canvas'. So, we don't + // allow empty rectangle in this case. + const int empty_rect_allowed_bg = 0; + + // If current frame is a key-frame, dispose method of previous frame doesn't + // matter, so we don't try dispose to background. + // Also, if key-frame insertion is on, and previous frame could be picked as + // either a sub-frame or a key-frame, then we can't be sure about what frame + // rectangle would be disposed. In that case too, we don't try dispose to + // background. + const int dispose_bg_possible = + !is_key_frame && !enc->prev_candidate_undecided_; + + SubFrameParams dispose_none_params; + SubFrameParams dispose_bg_params; + + WebPConfig config_ll = *config; + WebPConfig config_lossy = *config; + config_ll.lossless = 1; + config_lossy.lossless = 0; + enc->last_config_ = *config; + enc->last_config_reversed_ = config->lossless ? config_lossy : config_ll; + *frame_skipped = 0; + + if (!SubFrameParamsInit(&dispose_none_params, 1, empty_rect_allowed_none) || + !SubFrameParamsInit(&dispose_bg_params, 0, empty_rect_allowed_bg)) { + return VP8_ENC_ERROR_INVALID_CONFIGURATION; + } + + memset(candidates, 0, sizeof(candidates)); + + // Change-rectangle assuming previous frame was DISPOSE_NONE. + if (!GetSubRects(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + config_lossy.quality, &dispose_none_params)) { + error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + goto Err; + } + + if ((consider_lossless && IsEmptyRect(&dispose_none_params.rect_ll_)) || + (consider_lossy && IsEmptyRect(&dispose_none_params.rect_lossy_))) { + // Don't encode the frame at all. Instead, the duration of the previous + // frame will be increased later. + assert(empty_rect_allowed_none); + *frame_skipped = 1; + goto End; + } + + if (dispose_bg_possible) { + // Change-rectangle assuming previous frame was DISPOSE_BACKGROUND. + WebPPicture* const prev_canvas_disposed = &enc->prev_canvas_disposed_; + WebPCopyPixels(prev_canvas, prev_canvas_disposed); + DisposeFrameRectangle(WEBP_MUX_DISPOSE_BACKGROUND, &enc->prev_rect_, + prev_canvas_disposed); + + if (!GetSubRects(prev_canvas_disposed, curr_canvas, is_key_frame, + is_first_frame, config_lossy.quality, + &dispose_bg_params)) { + error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + goto Err; + } + assert(!IsEmptyRect(&dispose_bg_params.rect_ll_)); + assert(!IsEmptyRect(&dispose_bg_params.rect_lossy_)); + + if (enc->options_.minimize_size) { // Try both dispose methods. + dispose_bg_params.should_try_ = 1; + dispose_none_params.should_try_ = 1; + } else if ((is_lossless && + RectArea(&dispose_bg_params.rect_ll_) < + RectArea(&dispose_none_params.rect_ll_)) || + (!is_lossless && + RectArea(&dispose_bg_params.rect_lossy_) < + RectArea(&dispose_none_params.rect_lossy_))) { + dispose_bg_params.should_try_ = 1; // Pick DISPOSE_BACKGROUND. + dispose_none_params.should_try_ = 0; + } + } + + if (dispose_none_params.should_try_) { + error_code = GenerateCandidates( + enc, candidates, WEBP_MUX_DISPOSE_NONE, is_lossless, is_key_frame, + &dispose_none_params, &config_ll, &config_lossy); + if (error_code != VP8_ENC_OK) goto Err; + } + + if (dispose_bg_params.should_try_) { + assert(!enc->is_first_frame_); + assert(dispose_bg_possible); + error_code = GenerateCandidates( + enc, candidates, WEBP_MUX_DISPOSE_BACKGROUND, is_lossless, is_key_frame, + &dispose_bg_params, &config_ll, &config_lossy); + if (error_code != VP8_ENC_OK) goto Err; + } + + PickBestCandidate(enc, candidates, is_key_frame, encoded_frame); + + goto End; + + Err: + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + WebPMemoryWriterClear(&candidates[i].mem_); + } + } + + End: + SubFrameParamsFree(&dispose_none_params); + SubFrameParamsFree(&dispose_bg_params); + return error_code; +} + +// Calculate the penalty incurred if we encode given frame as a key frame +// instead of a sub-frame. +static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) { + return ((int64_t)encoded_frame->key_frame_.bitstream.size - + encoded_frame->sub_frame_.bitstream.size); +} + +static int CacheFrame(WebPAnimEncoder* const enc, + const WebPConfig* const config) { + int ok = 0; + int frame_skipped = 0; + WebPEncodingError error_code = VP8_ENC_OK; + const size_t position = enc->count_; + EncodedFrame* const encoded_frame = GetFrame(enc, position); + + ++enc->count_; + + if (enc->is_first_frame_) { // Add this as a key-frame. + error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + assert(frame_skipped == 0); // First frame can't be skipped, even if empty. + assert(position == 0 && enc->count_ == 1); + encoded_frame->is_key_frame_ = 1; + enc->flush_count_ = 0; + enc->count_since_key_frame_ = 0; + enc->prev_candidate_undecided_ = 0; + } else { + ++enc->count_since_key_frame_; + if (enc->count_since_key_frame_ <= enc->options_.kmin) { + // Add this as a frame rectangle. + error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + if (frame_skipped) goto Skip; + encoded_frame->is_key_frame_ = 0; + enc->flush_count_ = enc->count_ - 1; + enc->prev_candidate_undecided_ = 0; + } else { + int64_t curr_delta; + FrameRectangle prev_rect_key, prev_rect_sub; + + // Add this as a frame rectangle to enc. + error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + if (frame_skipped) goto Skip; + prev_rect_sub = enc->prev_rect_; + + + // Add this as a key-frame to enc, too. + error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + assert(frame_skipped == 0); // Key-frame cannot be an empty rectangle. + prev_rect_key = enc->prev_rect_; + + // Analyze size difference of the two variants. + curr_delta = KeyFramePenalty(encoded_frame); + if (curr_delta <= enc->best_delta_) { // Pick this as the key-frame. + if (enc->keyframe_ != KEYFRAME_NONE) { + EncodedFrame* const old_keyframe = GetFrame(enc, enc->keyframe_); + assert(old_keyframe->is_key_frame_); + old_keyframe->is_key_frame_ = 0; + } + encoded_frame->is_key_frame_ = 1; + enc->prev_candidate_undecided_ = 1; + enc->keyframe_ = (int)position; + enc->best_delta_ = curr_delta; + enc->flush_count_ = enc->count_ - 1; // We can flush previous frames. + } else { + encoded_frame->is_key_frame_ = 0; + enc->prev_candidate_undecided_ = 0; + } + // Note: We need '>=' below because when kmin and kmax are both zero, + // count_since_key_frame will always be > kmax. + if (enc->count_since_key_frame_ >= enc->options_.kmax) { + enc->flush_count_ = enc->count_ - 1; + enc->count_since_key_frame_ = 0; + enc->keyframe_ = KEYFRAME_NONE; + enc->best_delta_ = DELTA_INFINITY; + } + if (!enc->prev_candidate_undecided_) { + enc->prev_rect_ = + encoded_frame->is_key_frame_ ? prev_rect_key : prev_rect_sub; + } + } + } + + // Update previous to previous and previous canvases for next call. + WebPCopyPixels(enc->curr_canvas_, &enc->prev_canvas_); + enc->is_first_frame_ = 0; + + Skip: + ok = 1; + ++enc->in_frame_count_; + + End: + if (!ok || frame_skipped) { + FrameRelease(encoded_frame); + // We reset some counters, as the frame addition failed/was skipped. + --enc->count_; + if (!enc->is_first_frame_) --enc->count_since_key_frame_; + if (!ok) { + MarkError2(enc, "ERROR adding frame. WebPEncodingError", error_code); + } + } + enc->curr_canvas_->error_code = error_code; // report error_code + assert(ok || error_code != VP8_ENC_OK); + return ok; +} + +static int FlushFrames(WebPAnimEncoder* const enc) { + while (enc->flush_count_ > 0) { + WebPMuxError err; + EncodedFrame* const curr = GetFrame(enc, 0); + const WebPMuxFrameInfo* const info = + curr->is_key_frame_ ? &curr->key_frame_ : &curr->sub_frame_; + assert(enc->mux_ != NULL); + err = WebPMuxPushFrame(enc->mux_, info, 1); + if (err != WEBP_MUX_OK) { + MarkError2(enc, "ERROR adding frame. WebPMuxError", err); + return 0; + } + if (enc->options_.verbose) { + fprintf(stderr, "INFO: Added frame. offset:%d,%d dispose:%d blend:%d\n", + info->x_offset, info->y_offset, info->dispose_method, + info->blend_method); + } + ++enc->out_frame_count_; + FrameRelease(curr); + ++enc->start_; + --enc->flush_count_; + --enc->count_; + if (enc->keyframe_ != KEYFRAME_NONE) --enc->keyframe_; + } + + if (enc->count_ == 1 && enc->start_ != 0) { + // Move enc->start to index 0. + const int enc_start_tmp = (int)enc->start_; + EncodedFrame temp = enc->encoded_frames_[0]; + enc->encoded_frames_[0] = enc->encoded_frames_[enc_start_tmp]; + enc->encoded_frames_[enc_start_tmp] = temp; + FrameRelease(&enc->encoded_frames_[enc_start_tmp]); + enc->start_ = 0; + } + return 1; +} + +#undef DELTA_INFINITY +#undef KEYFRAME_NONE + +int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, + const WebPConfig* encoder_config) { + WebPConfig config; + int ok; + + if (enc == NULL) { + return 0; + } + MarkNoError(enc); + + if (!enc->is_first_frame_) { + // Make sure timestamps are non-decreasing (integer wrap-around is OK). + const uint32_t prev_frame_duration = + (uint32_t)timestamp - enc->prev_timestamp_; + if (prev_frame_duration >= MAX_DURATION) { + if (frame != NULL) { + frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + } + MarkError(enc, "ERROR adding frame: timestamps must be non-decreasing"); + return 0; + } + if (!IncreasePreviousDuration(enc, (int)prev_frame_duration)) { + return 0; + } + // IncreasePreviousDuration() may add a frame to avoid exceeding + // MAX_DURATION which could cause CacheFrame() to over read encoded_frames_ + // before the next flush. + if (enc->count_ == enc->size_ && !FlushFrames(enc)) { + return 0; + } + } else { + enc->first_timestamp_ = timestamp; + } + + if (frame == NULL) { // Special: last call. + enc->got_null_frame_ = 1; + enc->prev_timestamp_ = timestamp; + return 1; + } + + if (frame->width != enc->canvas_width_ || + frame->height != enc->canvas_height_) { + frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + MarkError(enc, "ERROR adding frame: Invalid frame dimensions"); + return 0; + } + + if (!frame->use_argb) { // Convert frame from YUV(A) to ARGB. + if (enc->options_.verbose) { + fprintf(stderr, "WARNING: Converting frame from YUV(A) to ARGB format; " + "this incurs a small loss.\n"); + } + if (!WebPPictureYUVAToARGB(frame)) { + MarkError(enc, "ERROR converting frame from YUV(A) to ARGB"); + return 0; + } + } + + if (encoder_config != NULL) { + if (!WebPValidateConfig(encoder_config)) { + MarkError(enc, "ERROR adding frame: Invalid WebPConfig"); + return 0; + } + config = *encoder_config; + } else { + if (!WebPConfigInit(&config)) { + MarkError(enc, "Cannot Init config"); + return 0; + } + config.lossless = 1; + } + assert(enc->curr_canvas_ == NULL); + enc->curr_canvas_ = frame; // Store reference. + assert(enc->curr_canvas_copy_modified_ == 1); + CopyCurrentCanvas(enc); + + ok = CacheFrame(enc, &config) && FlushFrames(enc); + + enc->curr_canvas_ = NULL; + enc->curr_canvas_copy_modified_ = 1; + if (ok) { + enc->prev_timestamp_ = timestamp; + } + return ok; +} + +// ----------------------------------------------------------------------------- +// Bitstream assembly. + +WEBP_NODISCARD static int DecodeFrameOntoCanvas( + const WebPMuxFrameInfo* const frame, WebPPicture* const canvas) { + const WebPData* const image = &frame->bitstream; + WebPPicture sub_image; + WebPDecoderConfig config; + if (!WebPInitDecoderConfig(&config)) { + return 0; + } + WebPUtilClearPic(canvas, NULL); + if (WebPGetFeatures(image->bytes, image->size, &config.input) != + VP8_STATUS_OK) { + return 0; + } + if (!WebPPictureView(canvas, frame->x_offset, frame->y_offset, + config.input.width, config.input.height, &sub_image)) { + return 0; + } + config.output.is_external_memory = 1; + config.output.colorspace = MODE_BGRA; + config.output.u.RGBA.rgba = (uint8_t*)sub_image.argb; + config.output.u.RGBA.stride = sub_image.argb_stride * 4; + config.output.u.RGBA.size = config.output.u.RGBA.stride * sub_image.height; + + if (WebPDecode(image->bytes, image->size, &config) != VP8_STATUS_OK) { + return 0; + } + return 1; +} + +static int FrameToFullCanvas(WebPAnimEncoder* const enc, + const WebPMuxFrameInfo* const frame, + WebPData* const full_image) { + WebPPicture* const canvas_buf = &enc->curr_canvas_copy_; + WebPMemoryWriter mem1, mem2; + WebPMemoryWriterInit(&mem1); + WebPMemoryWriterInit(&mem2); + + if (!DecodeFrameOntoCanvas(frame, canvas_buf)) goto Err; + if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem1)) goto Err; + GetEncodedData(&mem1, full_image); + + if (enc->options_.allow_mixed) { + if (!EncodeFrame(&enc->last_config_reversed_, canvas_buf, &mem2)) goto Err; + if (mem2.size < mem1.size) { + GetEncodedData(&mem2, full_image); + WebPMemoryWriterClear(&mem1); + } else { + WebPMemoryWriterClear(&mem2); + } + } + return 1; + + Err: + WebPMemoryWriterClear(&mem1); + WebPMemoryWriterClear(&mem2); + return 0; +} + +// Convert a single-frame animation to a non-animated image if appropriate. +// TODO(urvang): Can we pick one of the two heuristically (based on frame +// rectangle and/or presence of alpha)? +static WebPMuxError OptimizeSingleFrame(WebPAnimEncoder* const enc, + WebPData* const webp_data) { + WebPMuxError err = WEBP_MUX_OK; + int canvas_width, canvas_height; + WebPMuxFrameInfo frame; + WebPData full_image; + WebPData webp_data2; + WebPMux* const mux = WebPMuxCreate(webp_data, 0); + if (mux == NULL) return WEBP_MUX_BAD_DATA; + assert(enc->out_frame_count_ == 1); + WebPDataInit(&frame.bitstream); + WebPDataInit(&full_image); + WebPDataInit(&webp_data2); + + err = WebPMuxGetFrame(mux, 1, &frame); + if (err != WEBP_MUX_OK) goto End; + if (frame.id != WEBP_CHUNK_ANMF) goto End; // Non-animation: nothing to do. + err = WebPMuxGetCanvasSize(mux, &canvas_width, &canvas_height); + if (err != WEBP_MUX_OK) goto End; + if (!FrameToFullCanvas(enc, &frame, &full_image)) { + err = WEBP_MUX_BAD_DATA; + goto End; + } + err = WebPMuxSetImage(mux, &full_image, 1); + if (err != WEBP_MUX_OK) goto End; + err = WebPMuxAssemble(mux, &webp_data2); + if (err != WEBP_MUX_OK) goto End; + + if (webp_data2.size < webp_data->size) { // Pick 'webp_data2' if smaller. + WebPDataClear(webp_data); + *webp_data = webp_data2; + WebPDataInit(&webp_data2); + } + + End: + WebPDataClear(&frame.bitstream); + WebPDataClear(&full_image); + WebPMuxDelete(mux); + WebPDataClear(&webp_data2); + return err; +} + +int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) { + WebPMux* mux; + WebPMuxError err; + + if (enc == NULL) { + return 0; + } + MarkNoError(enc); + + if (webp_data == NULL) { + MarkError(enc, "ERROR assembling: NULL input"); + return 0; + } + + if (enc->in_frame_count_ == 0) { + MarkError(enc, "ERROR: No frames to assemble"); + return 0; + } + + if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) { + // set duration of the last frame to be avg of durations of previous frames. + const double delta_time = + (uint32_t)enc->prev_timestamp_ - enc->first_timestamp_; + const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1)); + if (!IncreasePreviousDuration(enc, average_duration)) { + return 0; + } + } + + // Flush any remaining frames. + enc->flush_count_ = enc->count_; + if (!FlushFrames(enc)) { + return 0; + } + + // Set definitive canvas size. + mux = enc->mux_; + err = WebPMuxSetCanvasSize(mux, enc->canvas_width_, enc->canvas_height_); + if (err != WEBP_MUX_OK) goto Err; + + err = WebPMuxSetAnimationParams(mux, &enc->options_.anim_params); + if (err != WEBP_MUX_OK) goto Err; + + // Assemble into a WebP bitstream. + err = WebPMuxAssemble(mux, webp_data); + if (err != WEBP_MUX_OK) goto Err; + + if (enc->out_frame_count_ == 1) { + err = OptimizeSingleFrame(enc, webp_data); + if (err != WEBP_MUX_OK) goto Err; + } + return 1; + + Err: + MarkError2(enc, "ERROR assembling WebP", err); + return 0; +} + +const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) { + if (enc == NULL) return NULL; + return enc->error_str_; +} + +WebPMuxError WebPAnimEncoderSetChunk( + WebPAnimEncoder* enc, const char fourcc[4], const WebPData* chunk_data, + int copy_data) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxSetChunk(enc->mux_, fourcc, chunk_data, copy_data); +} + +WebPMuxError WebPAnimEncoderGetChunk( + const WebPAnimEncoder* enc, const char fourcc[4], WebPData* chunk_data) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxGetChunk(enc->mux_, fourcc, chunk_data); +} + +WebPMuxError WebPAnimEncoderDeleteChunk( + WebPAnimEncoder* enc, const char fourcc[4]) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxDeleteChunk(enc->mux_, fourcc); +} + +// ----------------------------------------------------------------------------- diff --git a/libraries/webp/src/mux/animi.h b/libraries/webp/src/mux/animi.h new file mode 100644 index 0000000000..4fc062508a --- /dev/null +++ b/libraries/webp/src/mux/animi.h @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for animation related functions. +// +// Author: Hui Su (huisu@google.com) + +#ifndef WEBP_MUX_ANIMI_H_ +#define WEBP_MUX_ANIMI_H_ + +#include "include/webp/mux.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Picks the optimal rectangle between two pictures, starting with initial +// values of offsets and dimensions that are passed in. The initial +// values will be clipped, if necessary, to make sure the rectangle is +// within the canvas. "use_argb" must be true for both pictures. +// Parameters: +// prev_canvas, curr_canvas - (in) two input pictures to compare. +// is_lossless, quality - (in) encoding settings. +// x_offset, y_offset, width, height - (in/out) rectangle between the two +// input pictures. +// Returns true on success. +int WebPAnimEncoderRefineRect( + const struct WebPPicture* const prev_canvas, + const struct WebPPicture* const curr_canvas, + int is_lossless, float quality, int* const x_offset, int* const y_offset, + int* const width, int* const height); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_MUX_ANIMI_H_ diff --git a/libraries/webp/src/mux/muxedit.c b/libraries/webp/src/mux/muxedit.c new file mode 100644 index 0000000000..48c6834a4d --- /dev/null +++ b/libraries/webp/src/mux/muxedit.c @@ -0,0 +1,659 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Set and delete APIs for mux. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +#include +#include "src/mux/muxi.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Life of a mux object. + +static void MuxInit(WebPMux* const mux) { + assert(mux != NULL); + memset(mux, 0, sizeof(*mux)); + mux->canvas_width_ = 0; // just to be explicit + mux->canvas_height_ = 0; +} + +WebPMux* WebPNewInternal(int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { + return NULL; + } else { + WebPMux* const mux = (WebPMux*)WebPSafeMalloc(1ULL, sizeof(WebPMux)); + if (mux != NULL) MuxInit(mux); + return mux; + } +} + +// Delete all images in 'wpi_list'. +static void DeleteAllImages(WebPMuxImage** const wpi_list) { + while (*wpi_list != NULL) { + *wpi_list = MuxImageDelete(*wpi_list); + } +} + +static void MuxRelease(WebPMux* const mux) { + assert(mux != NULL); + DeleteAllImages(&mux->images_); + ChunkListDelete(&mux->vp8x_); + ChunkListDelete(&mux->iccp_); + ChunkListDelete(&mux->anim_); + ChunkListDelete(&mux->exif_); + ChunkListDelete(&mux->xmp_); + ChunkListDelete(&mux->unknown_); +} + +void WebPMuxDelete(WebPMux* mux) { + if (mux != NULL) { + MuxRelease(mux); + WebPSafeFree(mux); + } +} + +//------------------------------------------------------------------------------ +// Helper method(s). + +// Handy MACRO, makes MuxSet() very symmetric to MuxGet(). +#define SWITCH_ID_LIST(INDEX, LIST) \ + do { \ + if (idx == (INDEX)) { \ + err = ChunkAssignData(&chunk, data, copy_data, tag); \ + if (err == WEBP_MUX_OK) { \ + err = ChunkSetHead(&chunk, (LIST)); \ + if (err != WEBP_MUX_OK) ChunkRelease(&chunk); \ + } \ + return err; \ + } \ + } while (0) + +static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, + const WebPData* const data, int copy_data) { + WebPChunk chunk; + WebPMuxError err = WEBP_MUX_NOT_FOUND; + const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag); + assert(mux != NULL); + assert(!IsWPI(kChunks[idx].id)); + + ChunkInit(&chunk); + SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_); + SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_); + SWITCH_ID_LIST(IDX_ANIM, &mux->anim_); + SWITCH_ID_LIST(IDX_EXIF, &mux->exif_); + SWITCH_ID_LIST(IDX_XMP, &mux->xmp_); + SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown_); + return err; +} +#undef SWITCH_ID_LIST + +// Create data for frame given image data, offsets and duration. +static WebPMuxError CreateFrameData( + int width, int height, const WebPMuxFrameInfo* const info, + WebPData* const frame) { + uint8_t* frame_bytes; + const size_t frame_size = kChunks[IDX_ANMF].size; + + assert(width > 0 && height > 0 && info->duration >= 0); + assert(info->dispose_method == (info->dispose_method & 1)); + // Note: assertion on upper bounds is done in PutLE24(). + + frame_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_size); + if (frame_bytes == NULL) return WEBP_MUX_MEMORY_ERROR; + + PutLE24(frame_bytes + 0, info->x_offset / 2); + PutLE24(frame_bytes + 3, info->y_offset / 2); + + PutLE24(frame_bytes + 6, width - 1); + PutLE24(frame_bytes + 9, height - 1); + PutLE24(frame_bytes + 12, info->duration); + frame_bytes[15] = + (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) | + (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0); + + frame->bytes = frame_bytes; + frame->size = frame_size; + return WEBP_MUX_OK; +} + +// Outputs image data given a bitstream. The bitstream can either be a +// single-image WebP file or raw VP8/VP8L data. +// Also outputs 'is_lossless' to be true if the given bitstream is lossless. +static WebPMuxError GetImageData(const WebPData* const bitstream, + WebPData* const image, WebPData* const alpha, + int* const is_lossless) { + WebPDataInit(alpha); // Default: no alpha. + if (bitstream->size < TAG_SIZE || + memcmp(bitstream->bytes, "RIFF", TAG_SIZE)) { + // It is NOT webp file data. Return input data as is. + *image = *bitstream; + } else { + // It is webp file data. Extract image data from it. + const WebPMuxImage* wpi; + WebPMux* const mux = WebPMuxCreate(bitstream, 0); + if (mux == NULL) return WEBP_MUX_BAD_DATA; + wpi = mux->images_; + assert(wpi != NULL && wpi->img_ != NULL); + *image = wpi->img_->data_; + if (wpi->alpha_ != NULL) { + *alpha = wpi->alpha_->data_; + } + WebPMuxDelete(mux); + } + *is_lossless = VP8LCheckSignature(image->bytes, image->size); + return WEBP_MUX_OK; +} + +static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) { + WebPMuxError err = WEBP_MUX_NOT_FOUND; + assert(chunk_list); + while (*chunk_list) { + WebPChunk* const chunk = *chunk_list; + if (chunk->tag_ == tag) { + *chunk_list = ChunkDelete(chunk); + err = WEBP_MUX_OK; + } else { + chunk_list = &chunk->next_; + } + } + return err; +} + +static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) { + const WebPChunkId id = ChunkGetIdFromTag(tag); + assert(mux != NULL); + if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT; + return DeleteChunks(MuxGetChunkListFromId(mux, id), tag); +} + +//------------------------------------------------------------------------------ +// Set API(s). + +WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], + const WebPData* chunk_data, int copy_data) { + uint32_t tag; + WebPMuxError err; + if (mux == NULL || fourcc == NULL || chunk_data == NULL || + chunk_data->bytes == NULL || chunk_data->size > MAX_CHUNK_PAYLOAD) { + return WEBP_MUX_INVALID_ARGUMENT; + } + tag = ChunkGetTagFromFourCC(fourcc); + + // Delete existing chunk(s) with the same 'fourcc'. + err = MuxDeleteAllNamedData(mux, tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + // Add the given chunk. + return MuxSet(mux, tag, chunk_data, copy_data); +} + +// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'. +static WebPMuxError AddDataToChunkList( + const WebPData* const data, int copy_data, uint32_t tag, + WebPChunk** chunk_list) { + WebPChunk chunk; + WebPMuxError err; + ChunkInit(&chunk); + err = ChunkAssignData(&chunk, data, copy_data, tag); + if (err != WEBP_MUX_OK) goto Err; + err = ChunkSetHead(&chunk, chunk_list); + if (err != WEBP_MUX_OK) goto Err; + return WEBP_MUX_OK; + Err: + ChunkRelease(&chunk); + return err; +} + +// Extracts image & alpha data from the given bitstream and then sets wpi.alpha_ +// and wpi.img_ appropriately. +static WebPMuxError SetAlphaAndImageChunks( + const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) { + int is_lossless = 0; + WebPData image, alpha; + WebPMuxError err = GetImageData(bitstream, &image, &alpha, &is_lossless); + const int image_tag = + is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; + if (err != WEBP_MUX_OK) return err; + if (alpha.bytes != NULL) { + err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag, + &wpi->alpha_); + if (err != WEBP_MUX_OK) return err; + } + err = AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_); + if (err != WEBP_MUX_OK) return err; + return MuxImageFinalize(wpi) ? WEBP_MUX_OK : WEBP_MUX_INVALID_ARGUMENT; +} + +WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream, + int copy_data) { + WebPMuxImage wpi; + WebPMuxError err; + + if (mux == NULL || bitstream == NULL || bitstream->bytes == NULL || + bitstream->size > MAX_CHUNK_PAYLOAD) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (mux->images_ != NULL) { + // Only one 'simple image' can be added in mux. So, remove present images. + DeleteAllImages(&mux->images_); + } + + MuxImageInit(&wpi); + err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); + if (err != WEBP_MUX_OK) goto Err; + + // Add this WebPMuxImage to mux. + err = MuxImagePush(&wpi, &mux->images_); + if (err != WEBP_MUX_OK) goto Err; + + // All is well. + return WEBP_MUX_OK; + + Err: // Something bad happened. + MuxImageRelease(&wpi); + return err; +} + +WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info, + int copy_data) { + WebPMuxImage wpi; + WebPMuxError err; + + if (mux == NULL || info == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + if (info->id != WEBP_CHUNK_ANMF) return WEBP_MUX_INVALID_ARGUMENT; + + if (info->bitstream.bytes == NULL || + info->bitstream.size > MAX_CHUNK_PAYLOAD) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (mux->images_ != NULL) { + const WebPMuxImage* const image = mux->images_; + const uint32_t image_id = (image->header_ != NULL) ? + ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE; + if (image_id != info->id) { + return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types. + } + } + + MuxImageInit(&wpi); + err = SetAlphaAndImageChunks(&info->bitstream, copy_data, &wpi); + if (err != WEBP_MUX_OK) goto Err; + assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful. + + { + WebPData frame; + const uint32_t tag = kChunks[IDX_ANMF].tag; + WebPMuxFrameInfo tmp = *info; + tmp.x_offset &= ~1; // Snap offsets to even. + tmp.y_offset &= ~1; + if (tmp.x_offset < 0 || tmp.x_offset >= MAX_POSITION_OFFSET || + tmp.y_offset < 0 || tmp.y_offset >= MAX_POSITION_OFFSET || + (tmp.duration < 0 || tmp.duration >= MAX_DURATION) || + tmp.dispose_method != (tmp.dispose_method & 1)) { + err = WEBP_MUX_INVALID_ARGUMENT; + goto Err; + } + err = CreateFrameData(wpi.width_, wpi.height_, &tmp, &frame); + if (err != WEBP_MUX_OK) goto Err; + // Add frame chunk (with copy_data = 1). + err = AddDataToChunkList(&frame, 1, tag, &wpi.header_); + WebPDataClear(&frame); // frame owned by wpi.header_ now. + if (err != WEBP_MUX_OK) goto Err; + } + + // Add this WebPMuxImage to mux. + err = MuxImagePush(&wpi, &mux->images_); + if (err != WEBP_MUX_OK) goto Err; + + // All is well. + return WEBP_MUX_OK; + + Err: // Something bad happened. + MuxImageRelease(&wpi); + return err; +} + +WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux, + const WebPMuxAnimParams* params) { + WebPMuxError err; + uint8_t data[ANIM_CHUNK_SIZE]; + const WebPData anim = { data, ANIM_CHUNK_SIZE }; + + if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; + if (params->loop_count < 0 || params->loop_count >= MAX_LOOP_COUNT) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // Delete any existing ANIM chunk(s). + err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + // Set the animation parameters. + PutLE32(data, params->bgcolor); + PutLE16(data + 4, params->loop_count); + return MuxSet(mux, kChunks[IDX_ANIM].tag, &anim, 1); +} + +WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, + int width, int height) { + WebPMuxError err; + if (mux == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (width < 0 || height < 0 || + width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (width * (uint64_t)height >= MAX_IMAGE_AREA) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if ((width * height) == 0 && (width | height) != 0) { + // one of width / height is zero, but not both -> invalid! + return WEBP_MUX_INVALID_ARGUMENT; + } + // If we already assembled a VP8X chunk, invalidate it. + err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + mux->canvas_width_ = width; + mux->canvas_height_ = height; + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ +// Delete API(s). + +WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) { + if (mux == NULL || fourcc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc)); +} + +WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) { + if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return MuxImageDeleteNth(&mux->images_, nth); +} + +//------------------------------------------------------------------------------ +// Assembly of the WebP RIFF file. + +static WebPMuxError GetFrameInfo( + const WebPChunk* const frame_chunk, + int* const x_offset, int* const y_offset, int* const duration) { + const WebPData* const data = &frame_chunk->data_; + const size_t expected_data_size = ANMF_CHUNK_SIZE; + assert(frame_chunk->tag_ == kChunks[IDX_ANMF].tag); + assert(frame_chunk != NULL); + if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT; + + *x_offset = 2 * GetLE24(data->bytes + 0); + *y_offset = 2 * GetLE24(data->bytes + 3); + *duration = GetLE24(data->bytes + 12); + return WEBP_MUX_OK; +} + +static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi, + int* const x_offset, int* const y_offset, + int* const duration, + int* const width, int* const height) { + const WebPChunk* const frame_chunk = wpi->header_; + WebPMuxError err; + assert(wpi != NULL); + assert(frame_chunk != NULL); + + // Get offsets and duration from ANMF chunk. + err = GetFrameInfo(frame_chunk, x_offset, y_offset, duration); + if (err != WEBP_MUX_OK) return err; + + // Get width and height from VP8/VP8L chunk. + if (width != NULL) *width = wpi->width_; + if (height != NULL) *height = wpi->height_; + return WEBP_MUX_OK; +} + +// Returns the tightest dimension for the canvas considering the image list. +static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux, + int* const width, int* const height) { + WebPMuxImage* wpi = NULL; + assert(mux != NULL); + assert(width != NULL && height != NULL); + + wpi = mux->images_; + assert(wpi != NULL); + assert(wpi->img_ != NULL); + + if (wpi->next_ != NULL) { + int max_x = 0, max_y = 0; + // if we have a chain of wpi's, header_ is necessarily set + assert(wpi->header_ != NULL); + // Aggregate the bounding box for animation frames. + for (; wpi != NULL; wpi = wpi->next_) { + int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0; + const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset, + &duration, &w, &h); + const int max_x_pos = x_offset + w; + const int max_y_pos = y_offset + h; + if (err != WEBP_MUX_OK) return err; + assert(x_offset < MAX_POSITION_OFFSET); + assert(y_offset < MAX_POSITION_OFFSET); + + if (max_x_pos > max_x) max_x = max_x_pos; + if (max_y_pos > max_y) max_y = max_y_pos; + } + *width = max_x; + *height = max_y; + } else { + // For a single image, canvas dimensions are same as image dimensions. + *width = wpi->width_; + *height = wpi->height_; + } + return WEBP_MUX_OK; +} + +// VP8X format: +// Total Size : 10, +// Flags : 4 bytes, +// Width : 3 bytes, +// Height : 3 bytes. +static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { + WebPMuxError err = WEBP_MUX_OK; + uint32_t flags = 0; + int width = 0; + int height = 0; + uint8_t data[VP8X_CHUNK_SIZE]; + const WebPData vp8x = { data, VP8X_CHUNK_SIZE }; + const WebPMuxImage* images = NULL; + + assert(mux != NULL); + images = mux->images_; // First image. + if (images == NULL || images->img_ == NULL || + images->img_->data_.bytes == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // If VP8X chunk(s) is(are) already present, remove them (and later add new + // VP8X chunk with updated flags). + err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + // Set flags. + if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) { + flags |= ICCP_FLAG; + } + if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) { + flags |= EXIF_FLAG; + } + if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) { + flags |= XMP_FLAG; + } + if (images->header_ != NULL) { + if (images->header_->tag_ == kChunks[IDX_ANMF].tag) { + // This is an image with animation. + flags |= ANIMATION_FLAG; + } + } + if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) { + flags |= ALPHA_FLAG; // Some images have an alpha channel. + } + + err = GetAdjustedCanvasSize(mux, &width, &height); + if (err != WEBP_MUX_OK) return err; + + if (width <= 0 || height <= 0) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (mux->canvas_width_ != 0 || mux->canvas_height_ != 0) { + if (width > mux->canvas_width_ || height > mux->canvas_height_) { + return WEBP_MUX_INVALID_ARGUMENT; + } + width = mux->canvas_width_; + height = mux->canvas_height_; + } + + if (flags == 0 && mux->unknown_ == NULL) { + // For simple file format, VP8X chunk should not be added. + return WEBP_MUX_OK; + } + + if (MuxHasAlpha(images)) { + // This means some frames explicitly/implicitly contain alpha. + // Note: This 'flags' update must NOT be done for a lossless image + // without a VP8X chunk! + flags |= ALPHA_FLAG; + } + + PutLE32(data + 0, flags); // VP8X chunk flags. + PutLE24(data + 4, width - 1); // canvas width. + PutLE24(data + 7, height - 1); // canvas height. + + return MuxSet(mux, kChunks[IDX_VP8X].tag, &vp8x, 1); +} + +// Cleans up 'mux' by removing any unnecessary chunks. +static WebPMuxError MuxCleanup(WebPMux* const mux) { + int num_frames; + int num_anim_chunks; + + // If we have an image with a single frame, and its rectangle + // covers the whole canvas, convert it to a non-animated image + // (to avoid writing ANMF chunk unnecessarily). + WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames); + if (err != WEBP_MUX_OK) return err; + if (num_frames == 1) { + WebPMuxImage* frame = NULL; + err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame); + if (err != WEBP_MUX_OK) return err; + // We know that one frame does exist. + assert(frame != NULL); + if (frame->header_ != NULL && + ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) || + (frame->width_ == mux->canvas_width_ && + frame->height_ == mux->canvas_height_))) { + assert(frame->header_->tag_ == kChunks[IDX_ANMF].tag); + ChunkDelete(frame->header_); // Removes ANMF chunk. + frame->header_ = NULL; + num_frames = 0; + } + } + // Remove ANIM chunk if this is a non-animated image. + err = WebPMuxNumChunks(mux, kChunks[IDX_ANIM].id, &num_anim_chunks); + if (err != WEBP_MUX_OK) return err; + if (num_anim_chunks >= 1 && num_frames == 0) { + err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); + if (err != WEBP_MUX_OK) return err; + } + return WEBP_MUX_OK; +} + +// Total size of a list of images. +static size_t ImageListDiskSize(const WebPMuxImage* wpi_list) { + size_t size = 0; + while (wpi_list != NULL) { + size += MuxImageDiskSize(wpi_list); + wpi_list = wpi_list->next_; + } + return size; +} + +// Write out the given list of images into 'dst'. +static uint8_t* ImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) { + while (wpi_list != NULL) { + dst = MuxImageEmit(wpi_list, dst); + wpi_list = wpi_list->next_; + } + return dst; +} + +WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { + size_t size = 0; + uint8_t* data = NULL; + uint8_t* dst = NULL; + WebPMuxError err; + + if (assembled_data == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + // Clean up returned data, in case something goes wrong. + memset(assembled_data, 0, sizeof(*assembled_data)); + + if (mux == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // Finalize mux. + err = MuxCleanup(mux); + if (err != WEBP_MUX_OK) return err; + err = CreateVP8XChunk(mux); + if (err != WEBP_MUX_OK) return err; + + // Allocate data. + size = ChunkListDiskSize(mux->vp8x_) + ChunkListDiskSize(mux->iccp_) + + ChunkListDiskSize(mux->anim_) + ImageListDiskSize(mux->images_) + + ChunkListDiskSize(mux->exif_) + ChunkListDiskSize(mux->xmp_) + + ChunkListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE; + + data = (uint8_t*)WebPSafeMalloc(1ULL, size); + if (data == NULL) return WEBP_MUX_MEMORY_ERROR; + + // Emit header & chunks. + dst = MuxEmitRiffHeader(data, size); + dst = ChunkListEmit(mux->vp8x_, dst); + dst = ChunkListEmit(mux->iccp_, dst); + dst = ChunkListEmit(mux->anim_, dst); + dst = ImageListEmit(mux->images_, dst); + dst = ChunkListEmit(mux->exif_, dst); + dst = ChunkListEmit(mux->xmp_, dst); + dst = ChunkListEmit(mux->unknown_, dst); + assert(dst == data + size); + + // Validate mux. + err = MuxValidate(mux); + if (err != WEBP_MUX_OK) { + WebPSafeFree(data); + data = NULL; + size = 0; + } + + // Finalize data. + assembled_data->bytes = data; + assembled_data->size = size; + + return err; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/mux/muxi.h b/libraries/webp/src/mux/muxi.h new file mode 100644 index 0000000000..c0fb867b94 --- /dev/null +++ b/libraries/webp/src/mux/muxi.h @@ -0,0 +1,234 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for mux library. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_MUX_MUXI_H_ +#define WEBP_MUX_MUXI_H_ + +#include +#include +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "include/webp/mux.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Defines and constants. + +#define MUX_MAJ_VERSION 1 +#define MUX_MIN_VERSION 3 +#define MUX_REV_VERSION 2 + +// Chunk object. +typedef struct WebPChunk WebPChunk; +struct WebPChunk { + uint32_t tag_; + int owner_; // True if *data_ memory is owned internally. + // VP8X, ANIM, and other internally created chunks + // like ANMF are always owned. + WebPData data_; + WebPChunk* next_; +}; + +// MuxImage object. Store a full WebP image (including ANMF chunk, ALPH +// chunk and VP8/VP8L chunk), +typedef struct WebPMuxImage WebPMuxImage; +struct WebPMuxImage { + WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF. + WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA. + WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE. + WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN. + int width_; + int height_; + int has_alpha_; // Through ALPH chunk or as part of VP8L. + int is_partial_; // True if only some of the chunks are filled. + WebPMuxImage* next_; +}; + +// Main mux object. Stores data chunks. +struct WebPMux { + WebPMuxImage* images_; + WebPChunk* iccp_; + WebPChunk* exif_; + WebPChunk* xmp_; + WebPChunk* anim_; + WebPChunk* vp8x_; + + WebPChunk* unknown_; + int canvas_width_; + int canvas_height_; +}; + +// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only. +// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to +// allow two different chunks to have the same id (e.g. WebPChunkId +// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L'). +typedef enum { + IDX_VP8X = 0, + IDX_ICCP, + IDX_ANIM, + IDX_ANMF, + IDX_ALPHA, + IDX_VP8, + IDX_VP8L, + IDX_EXIF, + IDX_XMP, + IDX_UNKNOWN, + + IDX_NIL, + IDX_LAST_CHUNK +} CHUNK_INDEX; + +#define NIL_TAG 0x00000000u // To signal void chunk. + +typedef struct { + uint32_t tag; + WebPChunkId id; + uint32_t size; +} ChunkInfo; + +extern const ChunkInfo kChunks[IDX_LAST_CHUNK]; + +//------------------------------------------------------------------------------ +// Chunk object management. + +// Initialize. +void ChunkInit(WebPChunk* const chunk); + +// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found. +CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); + +// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found. +WebPChunkId ChunkGetIdFromTag(uint32_t tag); + +// Convert a fourcc string to a tag. +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]); + +// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown. +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]); + +// Search for nth chunk with given 'tag' in the chunk list. +// nth = 0 means "last of the list". +WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag); + +// Fill the chunk with the given data. +WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, + int copy_data, uint32_t tag); + +// Sets 'chunk' as the only element in 'chunk_list' if it is empty. +// On success ownership is transferred from 'chunk' to the 'chunk_list'. +WebPMuxError ChunkSetHead(WebPChunk* const chunk, WebPChunk** const chunk_list); +// Sets 'chunk' at last position in the 'chunk_list'. +// On success ownership is transferred from 'chunk' to the 'chunk_list'. +// *chunk_list also points towards the last valid element of the initial +// *chunk_list. +WebPMuxError ChunkAppend(WebPChunk* const chunk, WebPChunk*** const chunk_list); + +// Releases chunk and returns chunk->next_. +WebPChunk* ChunkRelease(WebPChunk* const chunk); + +// Deletes given chunk & returns chunk->next_. +WebPChunk* ChunkDelete(WebPChunk* const chunk); + +// Deletes all chunks in the given chunk list. +void ChunkListDelete(WebPChunk** const chunk_list); + +// Returns size of the chunk including chunk header and padding byte (if any). +static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { + assert(chunk_size <= MAX_CHUNK_PAYLOAD); + return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); +} + +// Size of a chunk including header and padding. +static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { + const size_t data_size = chunk->data_.size; + return SizeWithPadding(data_size); +} + +// Total size of a list of chunks. +size_t ChunkListDiskSize(const WebPChunk* chunk_list); + +// Write out the given list of chunks into 'dst'. +uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst); + +//------------------------------------------------------------------------------ +// MuxImage object management. + +// Initialize. +void MuxImageInit(WebPMuxImage* const wpi); + +// Releases image 'wpi' and returns wpi->next. +WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi); + +// Delete image 'wpi' and return the next image in the list or NULL. +// 'wpi' can be NULL. +WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); + +// Count number of images matching the given tag id in the 'wpi_list'. +// If id == WEBP_CHUNK_NIL, all images will be matched. +int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); + +// Update width/height/has_alpha info from chunks within wpi. +// Also remove ALPH chunk if not needed. +int MuxImageFinalize(WebPMuxImage* const wpi); + +// Check if given ID corresponds to an image related chunk. +static WEBP_INLINE int IsWPI(WebPChunkId id) { + switch (id) { + case WEBP_CHUNK_ANMF: + case WEBP_CHUNK_ALPHA: + case WEBP_CHUNK_IMAGE: return 1; + default: return 0; + } +} + +// Pushes 'wpi' at the end of 'wpi_list'. +WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); + +// Delete nth image in the image list. +WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth); + +// Get nth image in the image list. +WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, + WebPMuxImage** wpi); + +// Total size of the given image. +size_t MuxImageDiskSize(const WebPMuxImage* const wpi); + +// Write out the given image into 'dst'. +uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst); + +//------------------------------------------------------------------------------ +// Helper methods for mux. + +// Checks if the given image list contains at least one image with alpha. +int MuxHasAlpha(const WebPMuxImage* images); + +// Write out RIFF header into 'data', given total data size 'size'. +uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size); + +// Returns the list where chunk with given ID is to be inserted in mux. +WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id); + +// Validates the given mux object. +WebPMuxError MuxValidate(const WebPMux* const mux); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_MUX_MUXI_H_ diff --git a/libraries/webp/src/mux/muxinternal.c b/libraries/webp/src/mux/muxinternal.c new file mode 100644 index 0000000000..75b6b416b9 --- /dev/null +++ b/libraries/webp/src/mux/muxinternal.c @@ -0,0 +1,549 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal objects and utils for mux. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +#include +#include "src/mux/muxi.h" +#include "src/utils/utils.h" + +#define UNDEFINED_CHUNK_SIZE ((uint32_t)(-1)) + +const ChunkInfo kChunks[] = { + { MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE }, + { MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('A', 'N', 'I', 'M'), WEBP_CHUNK_ANIM, ANIM_CHUNK_SIZE }, + { MKFOURCC('A', 'N', 'M', 'F'), WEBP_CHUNK_ANMF, ANMF_CHUNK_SIZE }, + { MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE }, + { NIL_TAG, WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE }, + + { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE } +}; + +//------------------------------------------------------------------------------ + +int WebPGetMuxVersion(void) { + return (MUX_MAJ_VERSION << 16) | (MUX_MIN_VERSION << 8) | MUX_REV_VERSION; +} + +//------------------------------------------------------------------------------ +// Life of a chunk object. + +void ChunkInit(WebPChunk* const chunk) { + assert(chunk); + memset(chunk, 0, sizeof(*chunk)); + chunk->tag_ = NIL_TAG; +} + +WebPChunk* ChunkRelease(WebPChunk* const chunk) { + WebPChunk* next; + if (chunk == NULL) return NULL; + if (chunk->owner_) { + WebPDataClear(&chunk->data_); + } + next = chunk->next_; + ChunkInit(chunk); + return next; +} + +//------------------------------------------------------------------------------ +// Chunk misc methods. + +CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) { + int i; + for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { + if (tag == kChunks[i].tag) return (CHUNK_INDEX)i; + } + return IDX_UNKNOWN; +} + +WebPChunkId ChunkGetIdFromTag(uint32_t tag) { + int i; + for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { + if (tag == kChunks[i].tag) return kChunks[i].id; + } + return WEBP_CHUNK_UNKNOWN; +} + +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) { + return MKFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]); +} + +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) { + const uint32_t tag = ChunkGetTagFromFourCC(fourcc); + return ChunkGetIndexFromTag(tag); +} + +//------------------------------------------------------------------------------ +// Chunk search methods. + +// Returns next chunk in the chunk list with the given tag. +static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) { + while (chunk != NULL && chunk->tag_ != tag) { + chunk = chunk->next_; + } + return chunk; +} + +WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) { + uint32_t iter = nth; + first = ChunkSearchNextInList(first, tag); + if (first == NULL) return NULL; + + while (--iter != 0) { + WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag); + if (next_chunk == NULL) break; + first = next_chunk; + } + return ((nth > 0) && (iter > 0)) ? NULL : first; +} + +//------------------------------------------------------------------------------ +// Chunk writer methods. + +WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, + int copy_data, uint32_t tag) { + // For internally allocated chunks, always copy data & make it owner of data. + if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_ANIM].tag) { + copy_data = 1; + } + + ChunkRelease(chunk); + + if (data != NULL) { + if (copy_data) { // Copy data. + if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR; + chunk->owner_ = 1; // Chunk is owner of data. + } else { // Don't copy data. + chunk->data_ = *data; + } + } + chunk->tag_ = tag; + return WEBP_MUX_OK; +} + +WebPMuxError ChunkSetHead(WebPChunk* const chunk, + WebPChunk** const chunk_list) { + WebPChunk* new_chunk; + + assert(chunk_list != NULL); + if (*chunk_list != NULL) { + return WEBP_MUX_NOT_FOUND; + } + + new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk)); + if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR; + *new_chunk = *chunk; + chunk->owner_ = 0; + new_chunk->next_ = NULL; + *chunk_list = new_chunk; + return WEBP_MUX_OK; +} + +WebPMuxError ChunkAppend(WebPChunk* const chunk, + WebPChunk*** const chunk_list) { + WebPMuxError err; + assert(chunk_list != NULL && *chunk_list != NULL); + + if (**chunk_list == NULL) { + err = ChunkSetHead(chunk, *chunk_list); + } else { + WebPChunk* last_chunk = **chunk_list; + while (last_chunk->next_ != NULL) last_chunk = last_chunk->next_; + err = ChunkSetHead(chunk, &last_chunk->next_); + if (err == WEBP_MUX_OK) *chunk_list = &last_chunk->next_; + } + return err; +} + +//------------------------------------------------------------------------------ +// Chunk deletion method(s). + +WebPChunk* ChunkDelete(WebPChunk* const chunk) { + WebPChunk* const next = ChunkRelease(chunk); + WebPSafeFree(chunk); + return next; +} + +void ChunkListDelete(WebPChunk** const chunk_list) { + while (*chunk_list != NULL) { + *chunk_list = ChunkDelete(*chunk_list); + } +} + +//------------------------------------------------------------------------------ +// Chunk serialization methods. + +static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) { + const size_t chunk_size = chunk->data_.size; + assert(chunk); + assert(chunk->tag_ != NIL_TAG); + PutLE32(dst + 0, chunk->tag_); + PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size); + assert(chunk_size == (uint32_t)chunk_size); + memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes, chunk_size); + if (chunk_size & 1) + dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding. + return dst + ChunkDiskSize(chunk); +} + +uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) { + while (chunk_list != NULL) { + dst = ChunkEmit(chunk_list, dst); + chunk_list = chunk_list->next_; + } + return dst; +} + +size_t ChunkListDiskSize(const WebPChunk* chunk_list) { + size_t size = 0; + while (chunk_list != NULL) { + size += ChunkDiskSize(chunk_list); + chunk_list = chunk_list->next_; + } + return size; +} + +//------------------------------------------------------------------------------ +// Life of a MuxImage object. + +void MuxImageInit(WebPMuxImage* const wpi) { + assert(wpi); + memset(wpi, 0, sizeof(*wpi)); +} + +WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) { + WebPMuxImage* next; + if (wpi == NULL) return NULL; + // There should be at most one chunk of header_, alpha_, img_ but we call + // ChunkListDelete to be safe + ChunkListDelete(&wpi->header_); + ChunkListDelete(&wpi->alpha_); + ChunkListDelete(&wpi->img_); + ChunkListDelete(&wpi->unknown_); + + next = wpi->next_; + MuxImageInit(wpi); + return next; +} + +//------------------------------------------------------------------------------ +// MuxImage search methods. + +// Get a reference to appropriate chunk list within an image given chunk tag. +static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi, + WebPChunkId id) { + assert(wpi != NULL); + switch (id) { + case WEBP_CHUNK_ANMF: return (WebPChunk**)&wpi->header_; + case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_; + case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_; + default: return NULL; + } +} + +int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) { + int count = 0; + const WebPMuxImage* current; + for (current = wpi_list; current != NULL; current = current->next_) { + if (id == WEBP_CHUNK_NIL) { + ++count; // Special case: count all images. + } else { + const WebPChunk* const wpi_chunk = *GetChunkListFromId(current, id); + if (wpi_chunk != NULL) { + const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); + if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'. + } + } + } + return count; +} + +// Outputs a pointer to 'prev_wpi->next_', +// where 'prev_wpi' is the pointer to the image at position (nth - 1). +// Returns true if nth image was found. +static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, + WebPMuxImage*** const location) { + uint32_t count = 0; + assert(wpi_list); + *location = wpi_list; + + if (nth == 0) { + nth = MuxImageCount(*wpi_list, WEBP_CHUNK_NIL); + if (nth == 0) return 0; // Not found. + } + + while (*wpi_list != NULL) { + WebPMuxImage* const cur_wpi = *wpi_list; + ++count; + if (count == nth) return 1; // Found. + wpi_list = &cur_wpi->next_; + *location = wpi_list; + } + return 0; // Not found. +} + +//------------------------------------------------------------------------------ +// MuxImage writer methods. + +WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) { + WebPMuxImage* new_wpi; + + while (*wpi_list != NULL) { + WebPMuxImage* const cur_wpi = *wpi_list; + if (cur_wpi->next_ == NULL) break; + wpi_list = &cur_wpi->next_; + } + + new_wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*new_wpi)); + if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR; + *new_wpi = *wpi; + new_wpi->next_ = NULL; + + if (*wpi_list != NULL) { + (*wpi_list)->next_ = new_wpi; + } else { + *wpi_list = new_wpi; + } + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ +// MuxImage deletion methods. + +WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) { + // Delete the components of wpi. If wpi is NULL this is a noop. + WebPMuxImage* const next = MuxImageRelease(wpi); + WebPSafeFree(wpi); + return next; +} + +WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth) { + assert(wpi_list); + if (!SearchImageToGetOrDelete(wpi_list, nth, &wpi_list)) { + return WEBP_MUX_NOT_FOUND; + } + *wpi_list = MuxImageDelete(*wpi_list); + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ +// MuxImage reader methods. + +WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, + WebPMuxImage** wpi) { + assert(wpi_list); + assert(wpi); + if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, + (WebPMuxImage***)&wpi_list)) { + return WEBP_MUX_NOT_FOUND; + } + *wpi = (WebPMuxImage*)*wpi_list; + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ +// MuxImage serialization methods. + +// Size of an image. +size_t MuxImageDiskSize(const WebPMuxImage* const wpi) { + size_t size = 0; + if (wpi->header_ != NULL) size += ChunkDiskSize(wpi->header_); + if (wpi->alpha_ != NULL) size += ChunkDiskSize(wpi->alpha_); + if (wpi->img_ != NULL) size += ChunkDiskSize(wpi->img_); + if (wpi->unknown_ != NULL) size += ChunkListDiskSize(wpi->unknown_); + return size; +} + +// Special case as ANMF chunk encapsulates other image chunks. +static uint8_t* ChunkEmitSpecial(const WebPChunk* const header, + size_t total_size, uint8_t* dst) { + const size_t header_size = header->data_.size; + const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE; + assert(header->tag_ == kChunks[IDX_ANMF].tag); + PutLE32(dst + 0, header->tag_); + PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next); + assert(header_size == (uint32_t)header_size); + memcpy(dst + CHUNK_HEADER_SIZE, header->data_.bytes, header_size); + if (header_size & 1) { + dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding. + } + return dst + ChunkDiskSize(header); +} + +uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) { + // Ordering of chunks to be emitted is strictly as follows: + // 1. ANMF chunk (if present). + // 2. ALPH chunk (if present). + // 3. VP8/VP8L chunk. + assert(wpi); + if (wpi->header_ != NULL) { + dst = ChunkEmitSpecial(wpi->header_, MuxImageDiskSize(wpi), dst); + } + if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst); + if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst); + if (wpi->unknown_ != NULL) dst = ChunkListEmit(wpi->unknown_, dst); + return dst; +} + +//------------------------------------------------------------------------------ +// Helper methods for mux. + +int MuxHasAlpha(const WebPMuxImage* images) { + while (images != NULL) { + if (images->has_alpha_) return 1; + images = images->next_; + } + return 0; +} + +uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) { + PutLE32(data + 0, MKFOURCC('R', 'I', 'F', 'F')); + PutLE32(data + TAG_SIZE, (uint32_t)size - CHUNK_HEADER_SIZE); + assert(size == (uint32_t)size); + PutLE32(data + TAG_SIZE + CHUNK_SIZE_BYTES, MKFOURCC('W', 'E', 'B', 'P')); + return data + RIFF_HEADER_SIZE; +} + +WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) { + assert(mux != NULL); + switch (id) { + case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_; + case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_; + case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_; + case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_; + case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_; + default: return (WebPChunk**)&mux->unknown_; + } +} + +static int IsNotCompatible(int feature, int num_items) { + return (feature != 0) != (num_items > 0); +} + +#define NO_FLAG ((WebPFeatureFlags)0) + +// Test basic constraints: +// retrieval, maximum number of chunks by index (use -1 to skip) +// and feature incompatibility (use NO_FLAG to skip). +// On success returns WEBP_MUX_OK and stores the chunk count in *num. +static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx, + WebPFeatureFlags feature, + uint32_t vp8x_flags, + int max, int* num) { + const WebPMuxError err = + WebPMuxNumChunks(mux, kChunks[idx].id, num); + if (err != WEBP_MUX_OK) return err; + if (max > -1 && *num > max) return WEBP_MUX_INVALID_ARGUMENT; + if (feature != NO_FLAG && IsNotCompatible(vp8x_flags & feature, *num)) { + return WEBP_MUX_INVALID_ARGUMENT; + } + return WEBP_MUX_OK; +} + +WebPMuxError MuxValidate(const WebPMux* const mux) { + int num_iccp; + int num_exif; + int num_xmp; + int num_anim; + int num_frames; + int num_vp8x; + int num_images; + int num_alpha; + uint32_t flags; + WebPMuxError err; + + // Verify mux is not NULL. + if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + // Verify mux has at least one image. + if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + err = WebPMuxGetFeatures(mux, &flags); + if (err != WEBP_MUX_OK) return err; + + // At most one color profile chunk. + err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp); + if (err != WEBP_MUX_OK) return err; + + // At most one EXIF metadata. + err = ValidateChunk(mux, IDX_EXIF, EXIF_FLAG, flags, 1, &num_exif); + if (err != WEBP_MUX_OK) return err; + + // At most one XMP metadata. + err = ValidateChunk(mux, IDX_XMP, XMP_FLAG, flags, 1, &num_xmp); + if (err != WEBP_MUX_OK) return err; + + // Animation: ANIMATION_FLAG, ANIM chunk and ANMF chunk(s) are consistent. + // At most one ANIM chunk. + err = ValidateChunk(mux, IDX_ANIM, NO_FLAG, flags, 1, &num_anim); + if (err != WEBP_MUX_OK) return err; + err = ValidateChunk(mux, IDX_ANMF, NO_FLAG, flags, -1, &num_frames); + if (err != WEBP_MUX_OK) return err; + + { + const int has_animation = !!(flags & ANIMATION_FLAG); + if (has_animation && (num_anim == 0 || num_frames == 0)) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (!has_animation && (num_anim == 1 || num_frames > 0)) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (!has_animation) { + const WebPMuxImage* images = mux->images_; + // There can be only one image. + if (images == NULL || images->next_ != NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + // Size must match. + if (mux->canvas_width_ > 0) { + if (images->width_ != mux->canvas_width_ || + images->height_ != mux->canvas_height_) { + return WEBP_MUX_INVALID_ARGUMENT; + } + } + } + } + + // Verify either VP8X chunk is present OR there is only one elem in + // mux->images_. + err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x); + if (err != WEBP_MUX_OK) return err; + err = ValidateChunk(mux, IDX_VP8, NO_FLAG, flags, -1, &num_images); + if (err != WEBP_MUX_OK) return err; + if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT; + + // ALPHA_FLAG & alpha chunk(s) are consistent. + // Note: ALPHA_FLAG can be set when there is actually no Alpha data present. + if (MuxHasAlpha(mux->images_)) { + if (num_vp8x > 0) { + // VP8X chunk is present, so it should contain ALPHA_FLAG. + if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT; + } else { + // VP8X chunk is not present, so ALPH chunks should NOT be present either. + err = WebPMuxNumChunks(mux, WEBP_CHUNK_ALPHA, &num_alpha); + if (err != WEBP_MUX_OK) return err; + if (num_alpha > 0) return WEBP_MUX_INVALID_ARGUMENT; + } + } + + return WEBP_MUX_OK; +} + +#undef NO_FLAG + +//------------------------------------------------------------------------------ + diff --git a/libraries/webp/src/mux/muxread.c b/libraries/webp/src/mux/muxread.c new file mode 100644 index 0000000000..afd3542e12 --- /dev/null +++ b/libraries/webp/src/mux/muxread.c @@ -0,0 +1,561 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Read APIs for mux. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +#include +#include "src/mux/muxi.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Helper method(s). + +// Handy MACRO. +#define SWITCH_ID_LIST(INDEX, LIST) \ + do { \ + if (idx == (INDEX)) { \ + const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ + kChunks[(INDEX)].tag); \ + if (chunk) { \ + *data = chunk->data_; \ + return WEBP_MUX_OK; \ + } else { \ + return WEBP_MUX_NOT_FOUND; \ + } \ + } \ + } while (0) + +static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, + uint32_t nth, WebPData* const data) { + assert(mux != NULL); + assert(idx != IDX_LAST_CHUNK); + assert(!IsWPI(kChunks[idx].id)); + WebPDataInit(data); + + SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_); + SWITCH_ID_LIST(IDX_ICCP, mux->iccp_); + SWITCH_ID_LIST(IDX_ANIM, mux->anim_); + SWITCH_ID_LIST(IDX_EXIF, mux->exif_); + SWITCH_ID_LIST(IDX_XMP, mux->xmp_); + assert(idx != IDX_UNKNOWN); + return WEBP_MUX_NOT_FOUND; +} +#undef SWITCH_ID_LIST + +// Fill the chunk with the given data (includes chunk header bytes), after some +// verifications. +static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk, + const uint8_t* data, size_t data_size, + size_t riff_size, int copy_data) { + uint32_t chunk_size; + WebPData chunk_data; + + // Correctness checks. + if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA; + chunk_size = GetLE32(data + TAG_SIZE); + if (chunk_size > MAX_CHUNK_PAYLOAD) return WEBP_MUX_BAD_DATA; + + { + const size_t chunk_disk_size = SizeWithPadding(chunk_size); + if (chunk_disk_size > riff_size) return WEBP_MUX_BAD_DATA; + if (chunk_disk_size > data_size) return WEBP_MUX_NOT_ENOUGH_DATA; + } + + // Data assignment. + chunk_data.bytes = data + CHUNK_HEADER_SIZE; + chunk_data.size = chunk_size; + return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0)); +} + +int MuxImageFinalize(WebPMuxImage* const wpi) { + const WebPChunk* const img = wpi->img_; + const WebPData* const image = &img->data_; + const int is_lossless = (img->tag_ == kChunks[IDX_VP8L].tag); + int w, h; + int vp8l_has_alpha = 0; + const int ok = is_lossless ? + VP8LGetInfo(image->bytes, image->size, &w, &h, &vp8l_has_alpha) : + VP8GetInfo(image->bytes, image->size, image->size, &w, &h); + assert(img != NULL); + if (ok) { + // Ignore ALPH chunk accompanying VP8L. + if (is_lossless && (wpi->alpha_ != NULL)) { + ChunkDelete(wpi->alpha_); + wpi->alpha_ = NULL; + } + wpi->width_ = w; + wpi->height_ = h; + wpi->has_alpha_ = vp8l_has_alpha || (wpi->alpha_ != NULL); + } + return ok; +} + +static int MuxImageParse(const WebPChunk* const chunk, int copy_data, + WebPMuxImage* const wpi) { + const uint8_t* bytes = chunk->data_.bytes; + size_t size = chunk->data_.size; + const uint8_t* const last = (bytes == NULL) ? NULL : bytes + size; + WebPChunk subchunk; + size_t subchunk_size; + WebPChunk** unknown_chunk_list = &wpi->unknown_; + ChunkInit(&subchunk); + + assert(chunk->tag_ == kChunks[IDX_ANMF].tag); + assert(!wpi->is_partial_); + + // ANMF. + { + const size_t hdr_size = ANMF_CHUNK_SIZE; + const WebPData temp = { bytes, hdr_size }; + // Each of ANMF chunk contain a header at the beginning. So, its size should + // be at least 'hdr_size'. + if (size < hdr_size) goto Fail; + if (ChunkAssignData(&subchunk, &temp, copy_data, + chunk->tag_) != WEBP_MUX_OK) { + goto Fail; + } + } + if (ChunkSetHead(&subchunk, &wpi->header_) != WEBP_MUX_OK) goto Fail; + wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks. + + // Rest of the chunks. + subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE; + bytes += subchunk_size; + size -= subchunk_size; + + while (bytes != last) { + ChunkInit(&subchunk); + if (ChunkVerifyAndAssign(&subchunk, bytes, size, size, + copy_data) != WEBP_MUX_OK) { + goto Fail; + } + switch (ChunkGetIdFromTag(subchunk.tag_)) { + case WEBP_CHUNK_ALPHA: + if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks. + if (ChunkSetHead(&subchunk, &wpi->alpha_) != WEBP_MUX_OK) goto Fail; + wpi->is_partial_ = 1; // Waiting for a VP8 chunk. + break; + case WEBP_CHUNK_IMAGE: + if (wpi->img_ != NULL) goto Fail; // Only 1 image chunk allowed. + if (ChunkSetHead(&subchunk, &wpi->img_) != WEBP_MUX_OK) goto Fail; + if (!MuxImageFinalize(wpi)) goto Fail; + wpi->is_partial_ = 0; // wpi is completely filled. + break; + case WEBP_CHUNK_UNKNOWN: + if (wpi->is_partial_) { + goto Fail; // Encountered an unknown chunk + // before some image chunks. + } + if (ChunkAppend(&subchunk, &unknown_chunk_list) != WEBP_MUX_OK) { + goto Fail; + } + break; + default: + goto Fail; + } + subchunk_size = ChunkDiskSize(&subchunk); + bytes += subchunk_size; + size -= subchunk_size; + } + if (wpi->is_partial_) goto Fail; + return 1; + + Fail: + ChunkRelease(&subchunk); + return 0; +} + +//------------------------------------------------------------------------------ +// Create a mux object from WebP-RIFF data. + +WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, + int version) { + size_t riff_size; + uint32_t tag; + const uint8_t* end; + WebPMux* mux = NULL; + WebPMuxImage* wpi = NULL; + const uint8_t* data; + size_t size; + WebPChunk chunk; + // Stores the end of the chunk lists so that it is faster to append data to + // their ends. + WebPChunk** chunk_list_ends[WEBP_CHUNK_NIL + 1] = { NULL }; + ChunkInit(&chunk); + + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { + return NULL; // version mismatch + } + if (bitstream == NULL) return NULL; + + data = bitstream->bytes; + size = bitstream->size; + + if (data == NULL) return NULL; + if (size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) return NULL; + if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') || + GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) { + return NULL; + } + + mux = WebPMuxNew(); + if (mux == NULL) return NULL; + + tag = GetLE32(data + RIFF_HEADER_SIZE); + if (tag != kChunks[IDX_VP8].tag && + tag != kChunks[IDX_VP8L].tag && + tag != kChunks[IDX_VP8X].tag) { + goto Err; // First chunk should be VP8, VP8L or VP8X. + } + + riff_size = GetLE32(data + TAG_SIZE); + if (riff_size > MAX_CHUNK_PAYLOAD) goto Err; + + // Note this padding is historical and differs from demux.c which does not + // pad the file size. + riff_size = SizeWithPadding(riff_size); + if (riff_size < CHUNK_HEADER_SIZE) goto Err; + if (riff_size > size) goto Err; + // There's no point in reading past the end of the RIFF chunk. + if (size > riff_size + CHUNK_HEADER_SIZE) { + size = riff_size + CHUNK_HEADER_SIZE; + } + + end = data + size; + data += RIFF_HEADER_SIZE; + size -= RIFF_HEADER_SIZE; + + wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*wpi)); + if (wpi == NULL) goto Err; + MuxImageInit(wpi); + + // Loop over chunks. + while (data != end) { + size_t data_size; + WebPChunkId id; + if (ChunkVerifyAndAssign(&chunk, data, size, riff_size, + copy_data) != WEBP_MUX_OK) { + goto Err; + } + data_size = ChunkDiskSize(&chunk); + id = ChunkGetIdFromTag(chunk.tag_); + switch (id) { + case WEBP_CHUNK_ALPHA: + if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks. + if (ChunkSetHead(&chunk, &wpi->alpha_) != WEBP_MUX_OK) goto Err; + wpi->is_partial_ = 1; // Waiting for a VP8 chunk. + break; + case WEBP_CHUNK_IMAGE: + if (ChunkSetHead(&chunk, &wpi->img_) != WEBP_MUX_OK) goto Err; + if (!MuxImageFinalize(wpi)) goto Err; + wpi->is_partial_ = 0; // wpi is completely filled. + PushImage: + // Add this to mux->images_ list. + if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err; + MuxImageInit(wpi); // Reset for reading next image. + break; + case WEBP_CHUNK_ANMF: + if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete. + if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err; + ChunkRelease(&chunk); + goto PushImage; + default: // A non-image chunk. + if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before + // getting all chunks of an image. + if (chunk_list_ends[id] == NULL) { + chunk_list_ends[id] = + MuxGetChunkListFromId(mux, id); // List to add this chunk. + } + if (ChunkAppend(&chunk, &chunk_list_ends[id]) != WEBP_MUX_OK) goto Err; + if (id == WEBP_CHUNK_VP8X) { // grab global specs + if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err; + mux->canvas_width_ = GetLE24(data + 12) + 1; + mux->canvas_height_ = GetLE24(data + 15) + 1; + } + break; + } + data += data_size; + size -= data_size; + ChunkInit(&chunk); + } + + // Incomplete image. + if (wpi->is_partial_) goto Err; + + // Validate mux if complete. + if (MuxValidate(mux) != WEBP_MUX_OK) goto Err; + + MuxImageDelete(wpi); + return mux; // All OK; + + Err: // Something bad happened. + ChunkRelease(&chunk); + MuxImageDelete(wpi); + WebPMuxDelete(mux); + return NULL; +} + +//------------------------------------------------------------------------------ +// Get API(s). + +// Validates that the given mux has a single image. +static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) { + const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE); + const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF); + + if (num_images == 0) { + // No images in mux. + return WEBP_MUX_NOT_FOUND; + } else if (num_images == 1 && num_frames == 0) { + // Valid case (single image). + return WEBP_MUX_OK; + } else { + // Frame case OR an invalid mux. + return WEBP_MUX_INVALID_ARGUMENT; + } +} + +// Get the canvas width, height and flags after validating that VP8X/VP8/VP8L +// chunk and canvas size are valid. +static WebPMuxError MuxGetCanvasInfo(const WebPMux* const mux, + int* width, int* height, uint32_t* flags) { + int w, h; + uint32_t f = 0; + WebPData data; + assert(mux != NULL); + + // Check if VP8X chunk is present. + if (MuxGet(mux, IDX_VP8X, 1, &data) == WEBP_MUX_OK) { + if (data.size < VP8X_CHUNK_SIZE) return WEBP_MUX_BAD_DATA; + f = GetLE32(data.bytes + 0); + w = GetLE24(data.bytes + 4) + 1; + h = GetLE24(data.bytes + 7) + 1; + } else { + const WebPMuxImage* const wpi = mux->images_; + // Grab user-forced canvas size as default. + w = mux->canvas_width_; + h = mux->canvas_height_; + if (w == 0 && h == 0 && ValidateForSingleImage(mux) == WEBP_MUX_OK) { + // single image and not forced canvas size => use dimension of first frame + assert(wpi != NULL); + w = wpi->width_; + h = wpi->height_; + } + if (wpi != NULL) { + if (wpi->has_alpha_) f |= ALPHA_FLAG; + } + } + if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA; + + if (width != NULL) *width = w; + if (height != NULL) *height = h; + if (flags != NULL) *flags = f; + return WEBP_MUX_OK; +} + +WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, int* width, int* height) { + if (mux == NULL || width == NULL || height == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + return MuxGetCanvasInfo(mux, width, height, NULL); +} + +WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) { + if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return MuxGetCanvasInfo(mux, NULL, NULL, flags); +} + +static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width, + int height, uint32_t flags) { + const size_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + assert(width >= 1 && height >= 1); + assert(width <= MAX_CANVAS_SIZE && height <= MAX_CANVAS_SIZE); + assert(width * (uint64_t)height < MAX_IMAGE_AREA); + PutLE32(dst, MKFOURCC('V', 'P', '8', 'X')); + PutLE32(dst + TAG_SIZE, VP8X_CHUNK_SIZE); + PutLE32(dst + CHUNK_HEADER_SIZE, flags); + PutLE24(dst + CHUNK_HEADER_SIZE + 4, width - 1); + PutLE24(dst + CHUNK_HEADER_SIZE + 7, height - 1); + return dst + vp8x_size; +} + +// Assemble a single image WebP bitstream from 'wpi'. +static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi, + WebPData* const bitstream) { + uint8_t* dst; + + // Allocate data. + const int need_vp8x = (wpi->alpha_ != NULL); + const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0; + const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0; + // Note: No need to output ANMF chunk for a single image. + const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size + + ChunkDiskSize(wpi->img_); + uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size); + if (data == NULL) return WEBP_MUX_MEMORY_ERROR; + + // There should be at most one alpha_ chunk and exactly one img_ chunk. + assert(wpi->alpha_ == NULL || wpi->alpha_->next_ == NULL); + assert(wpi->img_ != NULL && wpi->img_->next_ == NULL); + + // Main RIFF header. + dst = MuxEmitRiffHeader(data, size); + + if (need_vp8x) { + dst = EmitVP8XChunk(dst, wpi->width_, wpi->height_, ALPHA_FLAG); // VP8X. + dst = ChunkListEmit(wpi->alpha_, dst); // ALPH. + } + + // Bitstream. + dst = ChunkListEmit(wpi->img_, dst); + assert(dst == data + size); + + // Output. + bitstream->bytes = data; + bitstream->size = size; + return WEBP_MUX_OK; +} + +WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], + WebPData* chunk_data) { + CHUNK_INDEX idx; + if (mux == NULL || fourcc == NULL || chunk_data == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + idx = ChunkGetIndexFromFourCC(fourcc); + assert(idx != IDX_LAST_CHUNK); + if (IsWPI(kChunks[idx].id)) { // An image chunk. + return WEBP_MUX_INVALID_ARGUMENT; + } else if (idx != IDX_UNKNOWN) { // A known chunk type. + return MuxGet(mux, idx, 1, chunk_data); + } else { // An unknown chunk type. + const WebPChunk* const chunk = + ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc)); + if (chunk == NULL) return WEBP_MUX_NOT_FOUND; + *chunk_data = chunk->data_; + return WEBP_MUX_OK; + } +} + +static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi, + WebPMuxFrameInfo* const info) { + // Set some defaults for unrelated fields. + info->x_offset = 0; + info->y_offset = 0; + info->duration = 1; + info->dispose_method = WEBP_MUX_DISPOSE_NONE; + info->blend_method = WEBP_MUX_BLEND; + // Extract data for related fields. + info->id = ChunkGetIdFromTag(wpi->img_->tag_); + return SynthesizeBitstream(wpi, &info->bitstream); +} + +static WebPMuxError MuxGetFrameInternal(const WebPMuxImage* const wpi, + WebPMuxFrameInfo* const frame) { + const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag); + const WebPData* frame_data; + if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT; + assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame(). + // Get frame chunk. + frame_data = &wpi->header_->data_; + if (frame_data->size < kChunks[IDX_ANMF].size) return WEBP_MUX_BAD_DATA; + // Extract info. + frame->x_offset = 2 * GetLE24(frame_data->bytes + 0); + frame->y_offset = 2 * GetLE24(frame_data->bytes + 3); + { + const uint8_t bits = frame_data->bytes[15]; + frame->duration = GetLE24(frame_data->bytes + 12); + frame->dispose_method = + (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; + frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; + } + frame->id = ChunkGetIdFromTag(wpi->header_->tag_); + return SynthesizeBitstream(wpi, &frame->bitstream); +} + +WebPMuxError WebPMuxGetFrame( + const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) { + WebPMuxError err; + WebPMuxImage* wpi; + + if (mux == NULL || frame == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // Get the nth WebPMuxImage. + err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi); + if (err != WEBP_MUX_OK) return err; + + // Get frame info. + if (wpi->header_ == NULL) { + return MuxGetImageInternal(wpi, frame); + } else { + return MuxGetFrameInternal(wpi, frame); + } +} + +WebPMuxError WebPMuxGetAnimationParams(const WebPMux* mux, + WebPMuxAnimParams* params) { + WebPData anim; + WebPMuxError err; + + if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + err = MuxGet(mux, IDX_ANIM, 1, &anim); + if (err != WEBP_MUX_OK) return err; + if (anim.size < kChunks[WEBP_CHUNK_ANIM].size) return WEBP_MUX_BAD_DATA; + params->bgcolor = GetLE32(anim.bytes); + params->loop_count = GetLE16(anim.bytes + 4); + + return WEBP_MUX_OK; +} + +// Get chunk index from chunk id. Returns IDX_NIL if not found. +static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) { + int i; + for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) { + if (id == kChunks[i].id) return (CHUNK_INDEX)i; + } + return IDX_NIL; +} + +// Count number of chunks matching 'tag' in the 'chunk_list'. +// If tag == NIL_TAG, any tag will be matched. +static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) { + int count = 0; + const WebPChunk* current; + for (current = chunk_list; current != NULL; current = current->next_) { + if (tag == NIL_TAG || current->tag_ == tag) { + count++; // Count chunks whose tags match. + } + } + return count; +} + +WebPMuxError WebPMuxNumChunks(const WebPMux* mux, + WebPChunkId id, int* num_elements) { + if (mux == NULL || num_elements == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (IsWPI(id)) { + *num_elements = MuxImageCount(mux->images_, id); + } else { + WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id); + const CHUNK_INDEX idx = ChunkGetIndexFromId(id); + *num_elements = CountChunks(*chunk_list, kChunks[idx].tag); + } + + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/utils/bit_reader_inl_utils.h b/libraries/webp/src/utils/bit_reader_inl_utils.h new file mode 100644 index 0000000000..57cc843ff3 --- /dev/null +++ b/libraries/webp/src/utils/bit_reader_inl_utils.h @@ -0,0 +1,196 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Specific inlined methods for boolean decoder [VP8GetBit() ...] +// This file should be included by the .c sources that actually need to call +// these methods. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_BIT_READER_INL_UTILS_H_ +#define WEBP_UTILS_BIT_READER_INL_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include // for memcpy + +#include "src/dsp/dsp.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Derived type lbit_t = natural type for memory I/O + +#if (BITS > 32) +typedef uint64_t lbit_t; +#elif (BITS > 16) +typedef uint32_t lbit_t; +#elif (BITS > 8) +typedef uint16_t lbit_t; +#else +typedef uint8_t lbit_t; +#endif + +extern const uint8_t kVP8Log2Range[128]; +extern const uint8_t kVP8NewRange[128]; + +// special case for the tail byte-reading +void VP8LoadFinalBytes(VP8BitReader* const br); + +//------------------------------------------------------------------------------ +// Inlined critical functions + +// makes sure br->value_ has at least BITS bits worth of data +static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE +void VP8LoadNewBytes(VP8BitReader* WEBP_RESTRICT const br) { + assert(br != NULL && br->buf_ != NULL); + // Read 'BITS' bits at a time if possible. + if (br->buf_ < br->buf_max_) { + // convert memory type to register type (with some zero'ing!) + bit_t bits; +#if defined(WEBP_USE_MIPS32) + // This is needed because of un-aligned read. + lbit_t in_bits; + lbit_t* p_buf_ = (lbit_t*)br->buf_; + __asm__ volatile( + ".set push \n\t" + ".set at \n\t" + ".set macro \n\t" + "ulw %[in_bits], 0(%[p_buf_]) \n\t" + ".set pop \n\t" + : [in_bits]"=r"(in_bits) + : [p_buf_]"r"(p_buf_) + : "memory", "at" + ); +#else + lbit_t in_bits; + memcpy(&in_bits, br->buf_, sizeof(in_bits)); +#endif + br->buf_ += BITS >> 3; +#if !defined(WORDS_BIGENDIAN) +#if (BITS > 32) + bits = BSwap64(in_bits); + bits >>= 64 - BITS; +#elif (BITS >= 24) + bits = BSwap32(in_bits); + bits >>= (32 - BITS); +#elif (BITS == 16) + bits = BSwap16(in_bits); +#else // BITS == 8 + bits = (bit_t)in_bits; +#endif // BITS > 32 +#else // WORDS_BIGENDIAN + bits = (bit_t)in_bits; + if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS); +#endif + br->value_ = bits | (br->value_ << BITS); + br->bits_ += BITS; + } else { + VP8LoadFinalBytes(br); // no need to be inlined + } +} + +// Read a bit with proba 'prob'. Speed-critical function! +static WEBP_INLINE int VP8GetBit(VP8BitReader* WEBP_RESTRICT const br, + int prob, const char label[]) { + // Don't move this declaration! It makes a big speed difference to store + // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't + // alter br->range_ value. + range_t range = br->range_; + if (br->bits_ < 0) { + VP8LoadNewBytes(br); + } + { + const int pos = br->bits_; + const range_t split = (range * prob) >> 8; + const range_t value = (range_t)(br->value_ >> pos); + const int bit = (value > split); + if (bit) { + range -= split; + br->value_ -= (bit_t)(split + 1) << pos; + } else { + range = split + 1; + } + { + const int shift = 7 ^ BitsLog2Floor(range); + range <<= shift; + br->bits_ -= shift; + } + br->range_ = range - 1; + BT_TRACK(br); + return bit; + } +} + +// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here) +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +int VP8GetSigned(VP8BitReader* WEBP_RESTRICT const br, int v, + const char label[]) { + if (br->bits_ < 0) { + VP8LoadNewBytes(br); + } + { + const int pos = br->bits_; + const range_t split = br->range_ >> 1; + const range_t value = (range_t)(br->value_ >> pos); + const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0 + br->bits_ -= 1; + br->range_ += (range_t)mask; + br->range_ |= 1; + br->value_ -= (bit_t)((split + 1) & (uint32_t)mask) << pos; + BT_TRACK(br); + return (v ^ mask) - mask; + } +} + +static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* WEBP_RESTRICT const br, + int prob, const char label[]) { + // Don't move this declaration! It makes a big speed difference to store + // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't + // alter br->range_ value. + range_t range = br->range_; + if (br->bits_ < 0) { + VP8LoadNewBytes(br); + } + { + const int pos = br->bits_; + const range_t split = (range * prob) >> 8; + const range_t value = (range_t)(br->value_ >> pos); + int bit; // Don't use 'const int bit = (value > split);", it's slower. + if (value > split) { + range -= split + 1; + br->value_ -= (bit_t)(split + 1) << pos; + bit = 1; + } else { + range = split; + bit = 0; + } + if (range <= (range_t)0x7e) { + const int shift = kVP8Log2Range[range]; + range = kVP8NewRange[range]; + br->bits_ -= shift; + } + br->range_ = range; + BT_TRACK(br); + return bit; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_ diff --git a/libraries/webp/src/utils/bit_reader_utils.c b/libraries/webp/src/utils/bit_reader_utils.c new file mode 100644 index 0000000000..78aed577fc --- /dev/null +++ b/libraries/webp/src/utils/bit_reader_utils.c @@ -0,0 +1,299 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Boolean decoder non-inlined methods +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include "src/dsp/cpu.h" +#include "src/utils/bit_reader_inl_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// VP8BitReader + +void VP8BitReaderSetBuffer(VP8BitReader* const br, + const uint8_t* const start, + size_t size) { + br->buf_ = start; + br->buf_end_ = start + size; + br->buf_max_ = + (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1 + : start; +} + +void VP8InitBitReader(VP8BitReader* const br, + const uint8_t* const start, size_t size) { + assert(br != NULL); + assert(start != NULL); + assert(size < (1u << 31)); // limit ensured by format and upstream checks + br->range_ = 255 - 1; + br->value_ = 0; + br->bits_ = -8; // to load the very first 8bits + br->eof_ = 0; + VP8BitReaderSetBuffer(br, start, size); + VP8LoadNewBytes(br); +} + +void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { + if (br->buf_ != NULL) { + br->buf_ += offset; + br->buf_end_ += offset; + br->buf_max_ += offset; + } +} + +const uint8_t kVP8Log2Range[128] = { + 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0 +}; + +// range = ((range - 1) << kVP8Log2Range[range]) + 1 +const uint8_t kVP8NewRange[128] = { + 127, 127, 191, 127, 159, 191, 223, 127, + 143, 159, 175, 191, 207, 223, 239, 127, + 135, 143, 151, 159, 167, 175, 183, 191, + 199, 207, 215, 223, 231, 239, 247, 127, + 131, 135, 139, 143, 147, 151, 155, 159, + 163, 167, 171, 175, 179, 183, 187, 191, + 195, 199, 203, 207, 211, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 127, + 129, 131, 133, 135, 137, 139, 141, 143, + 145, 147, 149, 151, 153, 155, 157, 159, + 161, 163, 165, 167, 169, 171, 173, 175, + 177, 179, 181, 183, 185, 187, 189, 191, + 193, 195, 197, 199, 201, 203, 205, 207, + 209, 211, 213, 215, 217, 219, 221, 223, + 225, 227, 229, 231, 233, 235, 237, 239, + 241, 243, 245, 247, 249, 251, 253, 127 +}; + +void VP8LoadFinalBytes(VP8BitReader* const br) { + assert(br != NULL && br->buf_ != NULL); + // Only read 8bits at a time + if (br->buf_ < br->buf_end_) { + br->bits_ += 8; + br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8); + } else if (!br->eof_) { + br->value_ <<= 8; + br->bits_ += 8; + br->eof_ = 1; + } else { + br->bits_ = 0; // This is to avoid undefined behaviour with shifts. + } +} + +//------------------------------------------------------------------------------ +// Higher-level calls + +uint32_t VP8GetValue(VP8BitReader* const br, int bits, const char label[]) { + uint32_t v = 0; + while (bits-- > 0) { + v |= VP8GetBit(br, 0x80, label) << bits; + } + return v; +} + +int32_t VP8GetSignedValue(VP8BitReader* const br, int bits, + const char label[]) { + const int value = VP8GetValue(br, bits, label); + return VP8Get(br, label) ? -value : value; +} + +//------------------------------------------------------------------------------ +// VP8LBitReader + +#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits. + +#if defined(__arm__) || defined(_M_ARM) || WEBP_AARCH64 || \ + defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64) +#define VP8L_USE_FAST_LOAD +#endif + +static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = { + 0, + 0x000001, 0x000003, 0x000007, 0x00000f, + 0x00001f, 0x00003f, 0x00007f, 0x0000ff, + 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff, + 0x001fff, 0x003fff, 0x007fff, 0x00ffff, + 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff, + 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff +}; + +void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start, + size_t length) { + size_t i; + vp8l_val_t value = 0; + assert(br != NULL); + assert(start != NULL); + assert(length < 0xfffffff8u); // can't happen with a RIFF chunk. + + br->len_ = length; + br->val_ = 0; + br->bit_pos_ = 0; + br->eos_ = 0; + + if (length > sizeof(br->val_)) { + length = sizeof(br->val_); + } + for (i = 0; i < length; ++i) { + value |= (vp8l_val_t)start[i] << (8 * i); + } + br->val_ = value; + br->pos_ = length; + br->buf_ = start; +} + +void VP8LBitReaderSetBuffer(VP8LBitReader* const br, + const uint8_t* const buf, size_t len) { + assert(br != NULL); + assert(buf != NULL); + assert(len < 0xfffffff8u); // can't happen with a RIFF chunk. + br->buf_ = buf; + br->len_ = len; + // pos_ > len_ should be considered a param error. + br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br); +} + +static void VP8LSetEndOfStream(VP8LBitReader* const br) { + br->eos_ = 1; + br->bit_pos_ = 0; // To avoid undefined behaviour with shifts. +} + +// If not at EOS, reload up to VP8L_LBITS byte-by-byte +static void ShiftBytes(VP8LBitReader* const br) { + while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { + br->val_ >>= 8; + br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8); + ++br->pos_; + br->bit_pos_ -= 8; + } + if (VP8LIsEndOfStream(br)) { + VP8LSetEndOfStream(br); + } +} + +void VP8LDoFillBitWindow(VP8LBitReader* const br) { + assert(br->bit_pos_ >= VP8L_WBITS); +#if defined(VP8L_USE_FAST_LOAD) + if (br->pos_ + sizeof(br->val_) < br->len_) { + br->val_ >>= VP8L_WBITS; + br->bit_pos_ -= VP8L_WBITS; + br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) << + (VP8L_LBITS - VP8L_WBITS); + br->pos_ += VP8L_LOG8_WBITS; + return; + } +#endif + ShiftBytes(br); // Slow path. +} + +uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) { + assert(n_bits >= 0); + // Flag an error if end_of_stream or n_bits is more than allowed limit. + if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) { + const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits]; + const int new_bits = br->bit_pos_ + n_bits; + br->bit_pos_ = new_bits; + ShiftBytes(br); + return val; + } else { + VP8LSetEndOfStream(br); + return 0; + } +} + +//------------------------------------------------------------------------------ +// Bit-tracing tool + +#if (BITTRACE > 0) + +#include // for atexit() +#include +#include + +#define MAX_NUM_LABELS 32 +static struct { + const char* label; + int size; + int count; +} kLabels[MAX_NUM_LABELS]; + +static int last_label = 0; +static int last_pos = 0; +static const uint8_t* buf_start = NULL; +static int init_done = 0; + +static void PrintBitTraces(void) { + int i; + int scale = 1; + int total = 0; + const char* units = "bits"; +#if (BITTRACE == 2) + scale = 8; + units = "bytes"; +#endif + for (i = 0; i < last_label; ++i) total += kLabels[i].size; + if (total < 1) total = 1; // avoid rounding errors + printf("=== Bit traces ===\n"); + for (i = 0; i < last_label; ++i) { + const int skip = 16 - (int)strlen(kLabels[i].label); + const int value = (kLabels[i].size + scale - 1) / scale; + assert(skip > 0); + printf("%s \%*s: %6d %s \t[%5.2f%%] [count: %7d]\n", + kLabels[i].label, skip, "", value, units, + 100.f * kLabels[i].size / total, + kLabels[i].count); + } + total = (total + scale - 1) / scale; + printf("Total: %d %s\n", total, units); +} + +void BitTrace(const struct VP8BitReader* const br, const char label[]) { + int i, pos; + if (!init_done) { + memset(kLabels, 0, sizeof(kLabels)); + atexit(PrintBitTraces); + buf_start = br->buf_; + init_done = 1; + } + pos = (int)(br->buf_ - buf_start) * 8 - br->bits_; + // if there's a too large jump, we've changed partition -> reset counter + if (abs(pos - last_pos) > 32) { + buf_start = br->buf_; + pos = 0; + last_pos = 0; + } + if (br->range_ >= 0x7f) pos += kVP8Log2Range[br->range_ - 0x7f]; + for (i = 0; i < last_label; ++i) { + if (!strcmp(label, kLabels[i].label)) break; + } + if (i == MAX_NUM_LABELS) abort(); // overflow! + kLabels[i].label = label; + kLabels[i].size += pos - last_pos; + kLabels[i].count += 1; + if (i == last_label) ++last_label; + last_pos = pos; +} + +#endif // BITTRACE > 0 + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/utils/bit_reader_utils.h b/libraries/webp/src/utils/bit_reader_utils.h new file mode 100644 index 0000000000..2307b8b1ae --- /dev/null +++ b/libraries/webp/src/utils/bit_reader_utils.h @@ -0,0 +1,195 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Boolean decoder +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora (vikaas.arora@gmail.com) + +#ifndef WEBP_UTILS_BIT_READER_UTILS_H_ +#define WEBP_UTILS_BIT_READER_UTILS_H_ + +#include +#ifdef _MSC_VER +#include // _byteswap_ulong +#endif +#include "src/dsp/cpu.h" +#include "include/webp/types.h" + +// Warning! This macro triggers quite some MACRO wizardry around func signature! +#if !defined(BITTRACE) +#define BITTRACE 0 // 0 = off, 1 = print bits, 2 = print bytes +#endif + +#if (BITTRACE > 0) +struct VP8BitReader; +extern void BitTrace(const struct VP8BitReader* const br, const char label[]); +#define BT_TRACK(br) BitTrace(br, label) +#define VP8Get(BR, L) VP8GetValue(BR, 1, L) +#else +#define BT_TRACK(br) +// We'll REMOVE the 'const char label[]' from all signatures and calls (!!): +#define VP8GetValue(BR, N, L) VP8GetValue(BR, N) +#define VP8Get(BR, L) VP8GetValue(BR, 1, L) +#define VP8GetSignedValue(BR, N, L) VP8GetSignedValue(BR, N) +#define VP8GetBit(BR, P, L) VP8GetBit(BR, P) +#define VP8GetBitAlt(BR, P, L) VP8GetBitAlt(BR, P) +#define VP8GetSigned(BR, V, L) VP8GetSigned(BR, V) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// The Boolean decoder needs to maintain infinite precision on the value_ field. +// However, since range_ is only 8bit, we only need an active window of 8 bits +// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls +// below 128, range_ is updated, and fresh bits read from the bitstream are +// brought in as LSB. To avoid reading the fresh bits one by one (slow), we +// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a +// natural register (with type bit_t). To fetch BITS bits from bitstream we +// use a type lbit_t. +// +// BITS can be any multiple of 8 from 8 to 56 (inclusive). +// Pick values that fit natural register size. + +#if defined(__i386__) || defined(_M_IX86) // x86 32bit +#define BITS 24 +#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit +#define BITS 56 +#elif defined(__arm__) || defined(_M_ARM) // ARM +#define BITS 24 +#elif WEBP_AARCH64 // ARM 64bit +#define BITS 56 +#elif defined(__mips__) // MIPS +#define BITS 24 +#else // reasonable default +#define BITS 24 +#endif + +//------------------------------------------------------------------------------ +// Derived types and constants: +// bit_t = natural register type for storing 'value_' (which is BITS+8 bits) +// range_t = register for 'range_' (which is 8bits only) + +#if (BITS > 24) +typedef uint64_t bit_t; +#else +typedef uint32_t bit_t; +#endif + +typedef uint32_t range_t; + +//------------------------------------------------------------------------------ +// Bitreader + +typedef struct VP8BitReader VP8BitReader; +struct VP8BitReader { + // boolean decoder (keep the field ordering as is!) + bit_t value_; // current value + range_t range_; // current range minus 1. In [127, 254] interval. + int bits_; // number of valid bits left + // read buffer + const uint8_t* buf_; // next byte to be read + const uint8_t* buf_end_; // end of read buffer + const uint8_t* buf_max_; // max packed-read position on buffer + int eof_; // true if input is exhausted +}; + +// Initialize the bit reader and the boolean decoder. +void VP8InitBitReader(VP8BitReader* const br, + const uint8_t* const start, size_t size); +// Sets the working read buffer. +void VP8BitReaderSetBuffer(VP8BitReader* const br, + const uint8_t* const start, size_t size); + +// Update internal pointers to displace the byte buffer by the +// relative offset 'offset'. +void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset); + +// return the next value made of 'num_bits' bits +uint32_t VP8GetValue(VP8BitReader* const br, int num_bits, const char label[]); + +// return the next value with sign-extension. +int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits, + const char label[]); + +// bit_reader_inl.h will implement the following methods: +// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob, ...) +// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v, ...) +// and should be included by the .c files that actually need them. +// This is to avoid recompiling the whole library whenever this file is touched, +// and also allowing platform-specific ad-hoc hacks. + +// ----------------------------------------------------------------------------- +// Bitreader for lossless format + +// maximum number of bits (inclusive) the bit-reader can handle: +#define VP8L_MAX_NUM_BIT_READ 24 + +#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t). +#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow. + +typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit. + +typedef struct { + vp8l_val_t val_; // pre-fetched bits + const uint8_t* buf_; // input byte buffer + size_t len_; // buffer length + size_t pos_; // byte position in buf_ + int bit_pos_; // current bit-reading position in val_ + int eos_; // true if a bit was read past the end of buffer +} VP8LBitReader; + +void VP8LInitBitReader(VP8LBitReader* const br, + const uint8_t* const start, + size_t length); + +// Sets a new data buffer. +void VP8LBitReaderSetBuffer(VP8LBitReader* const br, + const uint8_t* const buffer, size_t length); + +// Reads the specified number of bits from read buffer. +// Flags an error in case end_of_stream or n_bits is more than the allowed limit +// of VP8L_MAX_NUM_BIT_READ (inclusive). +// Flags eos_ if this read attempt is going to cross the read buffer. +uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits); + +// Return the prefetched bits, so they can be looked up. +static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) { + return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1))); +} + +// Returns true if there was an attempt at reading bit past the end of +// the buffer. Doesn't set br->eos_ flag. +static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) { + assert(br->pos_ <= br->len_); + return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS)); +} + +// For jumping over a number of bits in the bit stream when accessed with +// VP8LPrefetchBits and VP8LFillBitWindow. +// This function does *not* set br->eos_, since it's speed-critical. +// Use with extreme care! +static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) { + br->bit_pos_ = val; +} + +// Advances the read buffer by 4 bytes to make room for reading next 32 bits. +// Speed critical, but infrequent part of the code can be non-inlined. +extern void VP8LDoFillBitWindow(VP8LBitReader* const br); +static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) { + if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_BIT_READER_UTILS_H_ diff --git a/libraries/webp/src/utils/bit_writer_utils.c b/libraries/webp/src/utils/bit_writer_utils.c new file mode 100644 index 0000000000..2f408508f1 --- /dev/null +++ b/libraries/webp/src/utils/bit_writer_utils.c @@ -0,0 +1,347 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora (vikaas.arora@gmail.com) + +#include +#include // for memcpy() +#include + +#include "src/utils/bit_writer_utils.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// VP8BitWriter + +static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) { + uint8_t* new_buf; + size_t new_size; + const uint64_t needed_size_64b = (uint64_t)bw->pos_ + extra_size; + const size_t needed_size = (size_t)needed_size_64b; + if (needed_size_64b != needed_size) { + bw->error_ = 1; + return 0; + } + if (needed_size <= bw->max_pos_) return 1; + // If the following line wraps over 32bit, the test just after will catch it. + new_size = 2 * bw->max_pos_; + if (new_size < needed_size) new_size = needed_size; + if (new_size < 1024) new_size = 1024; + new_buf = (uint8_t*)WebPSafeMalloc(1ULL, new_size); + if (new_buf == NULL) { + bw->error_ = 1; + return 0; + } + if (bw->pos_ > 0) { + assert(bw->buf_ != NULL); + memcpy(new_buf, bw->buf_, bw->pos_); + } + WebPSafeFree(bw->buf_); + bw->buf_ = new_buf; + bw->max_pos_ = new_size; + return 1; +} + +static void Flush(VP8BitWriter* const bw) { + const int s = 8 + bw->nb_bits_; + const int32_t bits = bw->value_ >> s; + assert(bw->nb_bits_ >= 0); + bw->value_ -= bits << s; + bw->nb_bits_ -= 8; + if ((bits & 0xff) != 0xff) { + size_t pos = bw->pos_; + if (!BitWriterResize(bw, bw->run_ + 1)) { + return; + } + if (bits & 0x100) { // overflow -> propagate carry over pending 0xff's + if (pos > 0) bw->buf_[pos - 1]++; + } + if (bw->run_ > 0) { + const int value = (bits & 0x100) ? 0x00 : 0xff; + for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value; + } + bw->buf_[pos++] = bits & 0xff; + bw->pos_ = pos; + } else { + bw->run_++; // delay writing of bytes 0xff, pending eventual carry. + } +} + +//------------------------------------------------------------------------------ +// renormalization + +static const uint8_t kNorm[128] = { // renorm_sizes[i] = 8 - log2(i) + 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0 +}; + +// range = ((range + 1) << kVP8Log2Range[range]) - 1 +static const uint8_t kNewRange[128] = { + 127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239, + 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, + 247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, + 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, + 243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, + 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, + 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, + 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, + 241, 243, 245, 247, 249, 251, 253, 127 +}; + +int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) { + const int split = (bw->range_ * prob) >> 8; + if (bit) { + bw->value_ += split + 1; + bw->range_ -= split + 1; + } else { + bw->range_ = split; + } + if (bw->range_ < 127) { // emit 'shift' bits out and renormalize + const int shift = kNorm[bw->range_]; + bw->range_ = kNewRange[bw->range_]; + bw->value_ <<= shift; + bw->nb_bits_ += shift; + if (bw->nb_bits_ > 0) Flush(bw); + } + return bit; +} + +int VP8PutBitUniform(VP8BitWriter* const bw, int bit) { + const int split = bw->range_ >> 1; + if (bit) { + bw->value_ += split + 1; + bw->range_ -= split + 1; + } else { + bw->range_ = split; + } + if (bw->range_ < 127) { + bw->range_ = kNewRange[bw->range_]; + bw->value_ <<= 1; + bw->nb_bits_ += 1; + if (bw->nb_bits_ > 0) Flush(bw); + } + return bit; +} + +void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) { + uint32_t mask; + assert(nb_bits > 0 && nb_bits < 32); + for (mask = 1u << (nb_bits - 1); mask; mask >>= 1) { + VP8PutBitUniform(bw, value & mask); + } +} + +void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) { + if (!VP8PutBitUniform(bw, value != 0)) return; + if (value < 0) { + VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1); + } else { + VP8PutBits(bw, value << 1, nb_bits + 1); + } +} + +//------------------------------------------------------------------------------ + +int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) { + bw->range_ = 255 - 1; + bw->value_ = 0; + bw->run_ = 0; + bw->nb_bits_ = -8; + bw->pos_ = 0; + bw->max_pos_ = 0; + bw->error_ = 0; + bw->buf_ = NULL; + return (expected_size > 0) ? BitWriterResize(bw, expected_size) : 1; +} + +uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) { + VP8PutBits(bw, 0, 9 - bw->nb_bits_); + bw->nb_bits_ = 0; // pad with zeroes + Flush(bw); + return bw->buf_; +} + +int VP8BitWriterAppend(VP8BitWriter* const bw, + const uint8_t* data, size_t size) { + assert(data != NULL); + if (bw->nb_bits_ != -8) return 0; // Flush() must have been called + if (!BitWriterResize(bw, size)) return 0; + memcpy(bw->buf_ + bw->pos_, data, size); + bw->pos_ += size; + return 1; +} + +void VP8BitWriterWipeOut(VP8BitWriter* const bw) { + if (bw != NULL) { + WebPSafeFree(bw->buf_); + memset(bw, 0, sizeof(*bw)); + } +} + +//------------------------------------------------------------------------------ +// VP8LBitWriter + +// This is the minimum amount of size the memory buffer is guaranteed to grow +// when extra space is needed. +#define MIN_EXTRA_SIZE (32768ULL) + +// Returns 1 on success. +static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) { + uint8_t* allocated_buf; + size_t allocated_size; + const size_t max_bytes = bw->end_ - bw->buf_; + const size_t current_size = bw->cur_ - bw->buf_; + const uint64_t size_required_64b = (uint64_t)current_size + extra_size; + const size_t size_required = (size_t)size_required_64b; + if (size_required != size_required_64b) { + bw->error_ = 1; + return 0; + } + if (max_bytes > 0 && size_required <= max_bytes) return 1; + allocated_size = (3 * max_bytes) >> 1; + if (allocated_size < size_required) allocated_size = size_required; + // make allocated size multiple of 1k + allocated_size = (((allocated_size >> 10) + 1) << 10); + allocated_buf = (uint8_t*)WebPSafeMalloc(1ULL, allocated_size); + if (allocated_buf == NULL) { + bw->error_ = 1; + return 0; + } + if (current_size > 0) { + memcpy(allocated_buf, bw->buf_, current_size); + } + WebPSafeFree(bw->buf_); + bw->buf_ = allocated_buf; + bw->cur_ = bw->buf_ + current_size; + bw->end_ = bw->buf_ + allocated_size; + return 1; +} + +int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) { + memset(bw, 0, sizeof(*bw)); + return VP8LBitWriterResize(bw, expected_size); +} + +int VP8LBitWriterClone(const VP8LBitWriter* const src, + VP8LBitWriter* const dst) { + const size_t current_size = src->cur_ - src->buf_; + assert(src->cur_ >= src->buf_ && src->cur_ <= src->end_); + if (!VP8LBitWriterResize(dst, current_size)) return 0; + memcpy(dst->buf_, src->buf_, current_size); + dst->bits_ = src->bits_; + dst->used_ = src->used_; + dst->error_ = src->error_; + dst->cur_ = dst->buf_ + current_size; + return 1; +} + +void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) { + if (bw != NULL) { + WebPSafeFree(bw->buf_); + memset(bw, 0, sizeof(*bw)); + } +} + +void VP8LBitWriterReset(const VP8LBitWriter* const bw_init, + VP8LBitWriter* const bw) { + bw->bits_ = bw_init->bits_; + bw->used_ = bw_init->used_; + bw->cur_ = bw->buf_ + (bw_init->cur_ - bw_init->buf_); + assert(bw->cur_ <= bw->end_); + bw->error_ = bw_init->error_; +} + +void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst) { + const VP8LBitWriter tmp = *src; + *src = *dst; + *dst = tmp; +} + +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) { + // If needed, make some room by flushing some bits out. + if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { + const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; + if (!CheckSizeOverflow(extra_size) || + !VP8LBitWriterResize(bw, (size_t)extra_size)) { + bw->cur_ = bw->buf_; + bw->error_ = 1; + return; + } + } + *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)bw->bits_); + bw->cur_ += VP8L_WRITER_BYTES; + bw->bits_ >>= VP8L_WRITER_BITS; + bw->used_ -= VP8L_WRITER_BITS; +} + +void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) { + assert(n_bits <= 32); + // That's the max we can handle: + assert(sizeof(vp8l_wtype_t) == 2); + if (n_bits > 0) { + vp8l_atype_t lbits = bw->bits_; + int used = bw->used_; + // Special case of overflow handling for 32bit accumulator (2-steps flush). +#if VP8L_WRITER_BITS == 16 + if (used + n_bits >= VP8L_WRITER_MAX_BITS) { + // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below. + const int shift = VP8L_WRITER_MAX_BITS - used; + lbits |= (vp8l_atype_t)bits << used; + used = VP8L_WRITER_MAX_BITS; + n_bits -= shift; + bits >>= shift; + assert(n_bits <= VP8L_WRITER_MAX_BITS); + } +#endif + // If needed, make some room by flushing some bits out. + while (used >= VP8L_WRITER_BITS) { + if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { + const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; + if (!CheckSizeOverflow(extra_size) || + !VP8LBitWriterResize(bw, (size_t)extra_size)) { + bw->cur_ = bw->buf_; + bw->error_ = 1; + return; + } + } + *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)lbits); + bw->cur_ += VP8L_WRITER_BYTES; + lbits >>= VP8L_WRITER_BITS; + used -= VP8L_WRITER_BITS; + } + bw->bits_ = lbits | ((vp8l_atype_t)bits << used); + bw->used_ = used + n_bits; + } +} + +uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) { + // flush leftover bits + if (VP8LBitWriterResize(bw, (bw->used_ + 7) >> 3)) { + while (bw->used_ > 0) { + *bw->cur_++ = (uint8_t)bw->bits_; + bw->bits_ >>= 8; + bw->used_ -= 8; + } + bw->used_ = 0; + } + return bw->buf_; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/utils/bit_writer_utils.h b/libraries/webp/src/utils/bit_writer_utils.h new file mode 100644 index 0000000000..8ccd554239 --- /dev/null +++ b/libraries/webp/src/utils/bit_writer_utils.h @@ -0,0 +1,154 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_BIT_WRITER_UTILS_H_ +#define WEBP_UTILS_BIT_WRITER_UTILS_H_ + +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Bit-writing + +typedef struct VP8BitWriter VP8BitWriter; +struct VP8BitWriter { + int32_t range_; // range-1 + int32_t value_; + int run_; // number of outstanding bits + int nb_bits_; // number of pending bits + uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned. + size_t pos_; + size_t max_pos_; + int error_; // true in case of error +}; + +// Initialize the object. Allocates some initial memory based on expected_size. +int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size); +// Finalize the bitstream coding. Returns a pointer to the internal buffer. +uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw); +// Release any pending memory and zeroes the object. Not a mandatory call. +// Only useful in case of error, when the internal buffer hasn't been grabbed! +void VP8BitWriterWipeOut(VP8BitWriter* const bw); + +int VP8PutBit(VP8BitWriter* const bw, int bit, int prob); +int VP8PutBitUniform(VP8BitWriter* const bw, int bit); +void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits); +void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits); + +// Appends some bytes to the internal buffer. Data is copied. +int VP8BitWriterAppend(VP8BitWriter* const bw, + const uint8_t* data, size_t size); + +// return approximate write position (in bits) +static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) { + const uint64_t nb_bits = 8 + bw->nb_bits_; // bw->nb_bits_ is <= 0, note + return (bw->pos_ + bw->run_) * 8 + nb_bits; +} + +// Returns a pointer to the internal buffer. +static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) { + return bw->buf_; +} +// Returns the size of the internal buffer. +static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) { + return bw->pos_; +} + +//------------------------------------------------------------------------------ +// VP8LBitWriter + +#if defined(__x86_64__) || defined(_M_X64) // 64bit +typedef uint64_t vp8l_atype_t; // accumulator type +typedef uint32_t vp8l_wtype_t; // writing type +#define WSWAP HToLE32 +#define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t) +#define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t) +#define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t) +#else +typedef uint32_t vp8l_atype_t; +typedef uint16_t vp8l_wtype_t; +#define WSWAP HToLE16 +#define VP8L_WRITER_BYTES 2 +#define VP8L_WRITER_BITS 16 +#define VP8L_WRITER_MAX_BITS 32 +#endif + +typedef struct { + vp8l_atype_t bits_; // bit accumulator + int used_; // number of bits used in accumulator + uint8_t* buf_; // start of buffer + uint8_t* cur_; // current write position + uint8_t* end_; // end of buffer + + // After all bits are written (VP8LBitWriterFinish()), the caller must observe + // the state of error_. A value of 1 indicates that a memory allocation + // failure has happened during bit writing. A value of 0 indicates successful + // writing of bits. + int error_; +} VP8LBitWriter; + +static WEBP_INLINE size_t VP8LBitWriterNumBytes(const VP8LBitWriter* const bw) { + return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3); +} + +// Returns false in case of memory allocation error. +int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); +// Returns false in case of memory allocation error. +int VP8LBitWriterClone(const VP8LBitWriter* const src, + VP8LBitWriter* const dst); +// Finalize the bitstream coding. Returns a pointer to the internal buffer. +uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); +// Release any pending memory and zeroes the object. +void VP8LBitWriterWipeOut(VP8LBitWriter* const bw); +// Resets the cursor of the BitWriter bw to when it was like in bw_init. +void VP8LBitWriterReset(const VP8LBitWriter* const bw_init, + VP8LBitWriter* const bw); +// Swaps the memory held by two BitWriters. +void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst); + +// Internal function for VP8LPutBits flushing 32 bits from the written state. +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); + +// PutBits internal function used in the 16 bit vp8l_wtype_t case. +void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits); + +// This function writes bits into bytes in increasing addresses (little endian), +// and within a byte least-significant-bit first. +// This function can write up to 32 bits in one go, but VP8LBitReader can only +// read 24 bits max (VP8L_MAX_NUM_BIT_READ). +// VP8LBitWriter's error_ flag is set in case of memory allocation error. +static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, + uint32_t bits, int n_bits) { + if (sizeof(vp8l_wtype_t) == 4) { + if (n_bits > 0) { + if (bw->used_ >= 32) { + VP8LPutBitsFlushBits(bw); + } + bw->bits_ |= (vp8l_atype_t)bits << bw->used_; + bw->used_ += n_bits; + } + } else { + VP8LPutBitsInternal(bw, bits, n_bits); + } +} + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_BIT_WRITER_UTILS_H_ diff --git a/libraries/webp/src/utils/color_cache_utils.c b/libraries/webp/src/utils/color_cache_utils.c new file mode 100644 index 0000000000..7b5222b6e5 --- /dev/null +++ b/libraries/webp/src/utils/color_cache_utils.c @@ -0,0 +1,49 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Color Cache for WebP Lossless +// +// Author: Jyrki Alakuijala (jyrki@google.com) + +#include +#include +#include +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// VP8LColorCache. + +int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits) { + const int hash_size = 1 << hash_bits; + assert(color_cache != NULL); + assert(hash_bits > 0); + color_cache->colors_ = (uint32_t*)WebPSafeCalloc( + (uint64_t)hash_size, sizeof(*color_cache->colors_)); + if (color_cache->colors_ == NULL) return 0; + color_cache->hash_shift_ = 32 - hash_bits; + color_cache->hash_bits_ = hash_bits; + return 1; +} + +void VP8LColorCacheClear(VP8LColorCache* const color_cache) { + if (color_cache != NULL) { + WebPSafeFree(color_cache->colors_); + color_cache->colors_ = NULL; + } +} + +void VP8LColorCacheCopy(const VP8LColorCache* const src, + VP8LColorCache* const dst) { + assert(src != NULL); + assert(dst != NULL); + assert(src->hash_bits_ == dst->hash_bits_); + memcpy(dst->colors_, src->colors_, + ((size_t)1u << dst->hash_bits_) * sizeof(*dst->colors_)); +} diff --git a/libraries/webp/src/utils/color_cache_utils.h b/libraries/webp/src/utils/color_cache_utils.h new file mode 100644 index 0000000000..aa18df82e8 --- /dev/null +++ b/libraries/webp/src/utils/color_cache_utils.h @@ -0,0 +1,89 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Color Cache for WebP Lossless +// +// Authors: Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) + +#ifndef WEBP_UTILS_COLOR_CACHE_UTILS_H_ +#define WEBP_UTILS_COLOR_CACHE_UTILS_H_ + +#include + +#include "src/dsp/dsp.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Main color cache struct. +typedef struct { + uint32_t* colors_; // color entries + int hash_shift_; // Hash shift: 32 - hash_bits_. + int hash_bits_; +} VP8LColorCache; + +static const uint32_t kHashMul = 0x1e35a7bdu; + +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +int VP8LHashPix(uint32_t argb, int shift) { + return (int)((argb * kHashMul) >> shift); +} + +static WEBP_INLINE uint32_t VP8LColorCacheLookup( + const VP8LColorCache* const cc, uint32_t key) { + assert((key >> cc->hash_bits_) == 0u); + return cc->colors_[key]; +} + +static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc, + uint32_t key, uint32_t argb) { + assert((key >> cc->hash_bits_) == 0u); + cc->colors_[key] = argb; +} + +static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc, + uint32_t argb) { + const int key = VP8LHashPix(argb, cc->hash_shift_); + cc->colors_[key] = argb; +} + +static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc, + uint32_t argb) { + return VP8LHashPix(argb, cc->hash_shift_); +} + +// Return the key if cc contains argb, and -1 otherwise. +static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc, + uint32_t argb) { + const int key = VP8LHashPix(argb, cc->hash_shift_); + return (cc->colors_[key] == argb) ? key : -1; +} + +//------------------------------------------------------------------------------ + +// Initializes the color cache with 'hash_bits' bits for the keys. +// Returns false in case of memory error. +int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits); + +void VP8LColorCacheCopy(const VP8LColorCache* const src, + VP8LColorCache* const dst); + +// Delete the memory associated to color cache. +void VP8LColorCacheClear(VP8LColorCache* const color_cache); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_UTILS_COLOR_CACHE_UTILS_H_ diff --git a/libraries/webp/src/utils/endian_inl_utils.h b/libraries/webp/src/utils/endian_inl_utils.h new file mode 100644 index 0000000000..44f15b6bd1 --- /dev/null +++ b/libraries/webp/src/utils/endian_inl_utils.h @@ -0,0 +1,93 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Endian related functions. + +#ifndef WEBP_UTILS_ENDIAN_INL_UTILS_H_ +#define WEBP_UTILS_ENDIAN_INL_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include "src/dsp/dsp.h" +#include "include/webp/types.h" + +#if defined(WORDS_BIGENDIAN) +#define HToLE32 BSwap32 +#define HToLE16 BSwap16 +#else +#define HToLE32(x) (x) +#define HToLE16(x) (x) +#endif + +#if !defined(HAVE_CONFIG_H) +#if LOCAL_GCC_PREREQ(4,8) || __has_builtin(__builtin_bswap16) +#define HAVE_BUILTIN_BSWAP16 +#endif +#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap32) +#define HAVE_BUILTIN_BSWAP32 +#endif +#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap64) +#define HAVE_BUILTIN_BSWAP64 +#endif +#endif // !HAVE_CONFIG_H + +static WEBP_INLINE uint16_t BSwap16(uint16_t x) { +#if defined(HAVE_BUILTIN_BSWAP16) + return __builtin_bswap16(x); +#elif defined(_MSC_VER) + return _byteswap_ushort(x); +#else + // gcc will recognize a 'rorw $8, ...' here: + return (x >> 8) | ((x & 0xff) << 8); +#endif // HAVE_BUILTIN_BSWAP16 +} + +static WEBP_INLINE uint32_t BSwap32(uint32_t x) { +#if defined(WEBP_USE_MIPS32_R2) + uint32_t ret; + __asm__ volatile ( + "wsbh %[ret], %[x] \n\t" + "rotr %[ret], %[ret], 16 \n\t" + : [ret]"=r"(ret) + : [x]"r"(x) + ); + return ret; +#elif defined(HAVE_BUILTIN_BSWAP32) + return __builtin_bswap32(x); +#elif defined(__i386__) || defined(__x86_64__) + uint32_t swapped_bytes; + __asm__ volatile("bswap %0" : "=r"(swapped_bytes) : "0"(x)); + return swapped_bytes; +#elif defined(_MSC_VER) + return (uint32_t)_byteswap_ulong(x); +#else + return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24); +#endif // HAVE_BUILTIN_BSWAP32 +} + +static WEBP_INLINE uint64_t BSwap64(uint64_t x) { +#if defined(HAVE_BUILTIN_BSWAP64) + return __builtin_bswap64(x); +#elif defined(__x86_64__) + uint64_t swapped_bytes; + __asm__ volatile("bswapq %0" : "=r"(swapped_bytes) : "0"(x)); + return swapped_bytes; +#elif defined(_MSC_VER) + return (uint64_t)_byteswap_uint64(x); +#else // generic code for swapping 64-bit values (suggested by bdb@) + x = ((x & 0xffffffff00000000ull) >> 32) | ((x & 0x00000000ffffffffull) << 32); + x = ((x & 0xffff0000ffff0000ull) >> 16) | ((x & 0x0000ffff0000ffffull) << 16); + x = ((x & 0xff00ff00ff00ff00ull) >> 8) | ((x & 0x00ff00ff00ff00ffull) << 8); + return x; +#endif // HAVE_BUILTIN_BSWAP64 +} + +#endif // WEBP_UTILS_ENDIAN_INL_UTILS_H_ diff --git a/libraries/webp/src/utils/filters_utils.c b/libraries/webp/src/utils/filters_utils.c new file mode 100644 index 0000000000..bbc2c34d93 --- /dev/null +++ b/libraries/webp/src/utils/filters_utils.c @@ -0,0 +1,76 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// filter estimation +// +// Author: Urvang (urvang@google.com) + +#include "src/utils/filters_utils.h" +#include +#include + +// ----------------------------------------------------------------------------- +// Quick estimate of a potentially interesting filter mode to try. + +#define SMAX 16 +#define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX) + +static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { + const int g = a + b - c; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit +} + +WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, + int width, int height, int stride) { + int i, j; + int bins[WEBP_FILTER_LAST][SMAX]; + memset(bins, 0, sizeof(bins)); + + // We only sample every other pixels. That's enough. + for (j = 2; j < height - 1; j += 2) { + const uint8_t* const p = data + j * stride; + int mean = p[0]; + for (i = 2; i < width - 1; i += 2) { + const int diff0 = SDIFF(p[i], mean); + const int diff1 = SDIFF(p[i], p[i - 1]); + const int diff2 = SDIFF(p[i], p[i - width]); + const int grad_pred = + GradientPredictor(p[i - 1], p[i - width], p[i - width - 1]); + const int diff3 = SDIFF(p[i], grad_pred); + bins[WEBP_FILTER_NONE][diff0] = 1; + bins[WEBP_FILTER_HORIZONTAL][diff1] = 1; + bins[WEBP_FILTER_VERTICAL][diff2] = 1; + bins[WEBP_FILTER_GRADIENT][diff3] = 1; + mean = (3 * mean + p[i] + 2) >> 2; + } + } + { + int filter; + WEBP_FILTER_TYPE best_filter = WEBP_FILTER_NONE; + int best_score = 0x7fffffff; + for (filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; ++filter) { + int score = 0; + for (i = 0; i < SMAX; ++i) { + if (bins[filter][i] > 0) { + score += i; + } + } + if (score < best_score) { + best_score = score; + best_filter = (WEBP_FILTER_TYPE)filter; + } + } + return best_filter; + } +} + +#undef SMAX +#undef SDIFF + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/utils/filters_utils.h b/libraries/webp/src/utils/filters_utils.h new file mode 100644 index 0000000000..e3d8c784c1 --- /dev/null +++ b/libraries/webp/src/utils/filters_utils.h @@ -0,0 +1,32 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Spatial prediction using various filters +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_UTILS_FILTERS_UTILS_H_ +#define WEBP_UTILS_FILTERS_UTILS_H_ + +#include "include/webp/types.h" +#include "src/dsp/dsp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Fast estimate of a potentially good filter. +WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, + int width, int height, int stride); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_FILTERS_UTILS_H_ diff --git a/libraries/webp/src/utils/huffman_encode_utils.c b/libraries/webp/src/utils/huffman_encode_utils.c new file mode 100644 index 0000000000..638d8fb79d --- /dev/null +++ b/libraries/webp/src/utils/huffman_encode_utils.c @@ -0,0 +1,416 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Entropy encoding (Huffman) for webp lossless. + +#include +#include +#include +#include "src/utils/huffman_encode_utils.h" +#include "src/utils/utils.h" +#include "include/webp/format_constants.h" + +// ----------------------------------------------------------------------------- +// Util function to optimize the symbol map for RLE coding + +// Heuristics for selecting the stride ranges to collapse. +static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) { + return abs(a - b) < 4; +} + +// Change the population counts in a way that the consequent +// Huffman tree compression, especially its RLE-part, give smaller output. +static void OptimizeHuffmanForRle(int length, uint8_t* const good_for_rle, + uint32_t* const counts) { + // 1) Let's make the Huffman code more compatible with rle encoding. + int i; + for (; length >= 0; --length) { + if (length == 0) { + return; // All zeros. + } + if (counts[length - 1] != 0) { + // Now counts[0..length - 1] does not have trailing zeros. + break; + } + } + // 2) Let's mark all population counts that already can be encoded + // with an rle code. + { + // Let's not spoil any of the existing good rle codes. + // Mark any seq of 0's that is longer as 5 as a good_for_rle. + // Mark any seq of non-0's that is longer as 7 as a good_for_rle. + uint32_t symbol = counts[0]; + int stride = 0; + for (i = 0; i < length + 1; ++i) { + if (i == length || counts[i] != symbol) { + if ((symbol == 0 && stride >= 5) || + (symbol != 0 && stride >= 7)) { + int k; + for (k = 0; k < stride; ++k) { + good_for_rle[i - k - 1] = 1; + } + } + stride = 1; + if (i != length) { + symbol = counts[i]; + } + } else { + ++stride; + } + } + } + // 3) Let's replace those population counts that lead to more rle codes. + { + uint32_t stride = 0; + uint32_t limit = counts[0]; + uint32_t sum = 0; + for (i = 0; i < length + 1; ++i) { + if (i == length || good_for_rle[i] || + (i != 0 && good_for_rle[i - 1]) || + !ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) { + if (stride >= 4 || (stride >= 3 && sum == 0)) { + uint32_t k; + // The stride must end, collapse what we have, if we have enough (4). + uint32_t count = (sum + stride / 2) / stride; + if (count < 1) { + count = 1; + } + if (sum == 0) { + // Don't make an all zeros stride to be upgraded to ones. + count = 0; + } + for (k = 0; k < stride; ++k) { + // We don't want to change value at counts[i], + // that is already belonging to the next stride. Thus - 1. + counts[i - k - 1] = count; + } + } + stride = 0; + sum = 0; + if (i < length - 3) { + // All interesting strides have a count of at least 4, + // at least when non-zeros. + limit = (counts[i] + counts[i + 1] + + counts[i + 2] + counts[i + 3] + 2) / 4; + } else if (i < length) { + limit = counts[i]; + } else { + limit = 0; + } + } + ++stride; + if (i != length) { + sum += counts[i]; + if (stride >= 4) { + limit = (sum + stride / 2) / stride; + } + } + } + } +} + +// A comparer function for two Huffman trees: sorts first by 'total count' +// (more comes first), and then by 'value' (more comes first). +static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { + const HuffmanTree* const t1 = (const HuffmanTree*)ptr1; + const HuffmanTree* const t2 = (const HuffmanTree*)ptr2; + if (t1->total_count_ > t2->total_count_) { + return -1; + } else if (t1->total_count_ < t2->total_count_) { + return 1; + } else { + assert(t1->value_ != t2->value_); + return (t1->value_ < t2->value_) ? -1 : 1; + } +} + +static void SetBitDepths(const HuffmanTree* const tree, + const HuffmanTree* const pool, + uint8_t* const bit_depths, int level) { + if (tree->pool_index_left_ >= 0) { + SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1); + SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1); + } else { + bit_depths[tree->value_] = level; + } +} + +// Create an optimal Huffman tree. +// +// (data,length): population counts. +// tree_limit: maximum bit depth (inclusive) of the codes. +// bit_depths[]: how many bits are used for the symbol. +// +// Returns 0 when an error has occurred. +// +// The catch here is that the tree cannot be arbitrarily deep +// +// count_limit is the value that is to be faked as the minimum value +// and this minimum value is raised until the tree matches the +// maximum length requirement. +// +// This algorithm is not of excellent performance for very long data blocks, +// especially when population counts are longer than 2**tree_limit, but +// we are not planning to use this with extremely long blocks. +// +// See https://en.wikipedia.org/wiki/Huffman_coding +static void GenerateOptimalTree(const uint32_t* const histogram, + int histogram_size, + HuffmanTree* tree, int tree_depth_limit, + uint8_t* const bit_depths) { + uint32_t count_min; + HuffmanTree* tree_pool; + int tree_size_orig = 0; + int i; + + for (i = 0; i < histogram_size; ++i) { + if (histogram[i] != 0) { + ++tree_size_orig; + } + } + + if (tree_size_orig == 0) { // pretty optimal already! + return; + } + + tree_pool = tree + tree_size_orig; + + // For block sizes with less than 64k symbols we never need to do a + // second iteration of this loop. + // If we actually start running inside this loop a lot, we would perhaps + // be better off with the Katajainen algorithm. + assert(tree_size_orig <= (1 << (tree_depth_limit - 1))); + for (count_min = 1; ; count_min *= 2) { + int tree_size = tree_size_orig; + // We need to pack the Huffman tree in tree_depth_limit bits. + // So, we try by faking histogram entries to be at least 'count_min'. + int idx = 0; + int j; + for (j = 0; j < histogram_size; ++j) { + if (histogram[j] != 0) { + const uint32_t count = + (histogram[j] < count_min) ? count_min : histogram[j]; + tree[idx].total_count_ = count; + tree[idx].value_ = j; + tree[idx].pool_index_left_ = -1; + tree[idx].pool_index_right_ = -1; + ++idx; + } + } + + // Build the Huffman tree. + qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees); + + if (tree_size > 1) { // Normal case. + int tree_pool_size = 0; + while (tree_size > 1) { // Finish when we have only one root. + uint32_t count; + tree_pool[tree_pool_size++] = tree[tree_size - 1]; + tree_pool[tree_pool_size++] = tree[tree_size - 2]; + count = tree_pool[tree_pool_size - 1].total_count_ + + tree_pool[tree_pool_size - 2].total_count_; + tree_size -= 2; + { + // Search for the insertion point. + int k; + for (k = 0; k < tree_size; ++k) { + if (tree[k].total_count_ <= count) { + break; + } + } + memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree)); + tree[k].total_count_ = count; + tree[k].value_ = -1; + + tree[k].pool_index_left_ = tree_pool_size - 1; + tree[k].pool_index_right_ = tree_pool_size - 2; + tree_size = tree_size + 1; + } + } + SetBitDepths(&tree[0], tree_pool, bit_depths, 0); + } else if (tree_size == 1) { // Trivial case: only one element. + bit_depths[tree[0].value_] = 1; + } + + { + // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria. + int max_depth = bit_depths[0]; + for (j = 1; j < histogram_size; ++j) { + if (max_depth < bit_depths[j]) { + max_depth = bit_depths[j]; + } + } + if (max_depth <= tree_depth_limit) { + break; + } + } + } +} + +// ----------------------------------------------------------------------------- +// Coding of the Huffman tree values + +static HuffmanTreeToken* CodeRepeatedValues(int repetitions, + HuffmanTreeToken* tokens, + int value, int prev_value) { + assert(value <= MAX_ALLOWED_CODE_LENGTH); + if (value != prev_value) { + tokens->code = value; + tokens->extra_bits = 0; + ++tokens; + --repetitions; + } + while (repetitions >= 1) { + if (repetitions < 3) { + int i; + for (i = 0; i < repetitions; ++i) { + tokens->code = value; + tokens->extra_bits = 0; + ++tokens; + } + break; + } else if (repetitions < 7) { + tokens->code = 16; + tokens->extra_bits = repetitions - 3; + ++tokens; + break; + } else { + tokens->code = 16; + tokens->extra_bits = 3; + ++tokens; + repetitions -= 6; + } + } + return tokens; +} + +static HuffmanTreeToken* CodeRepeatedZeros(int repetitions, + HuffmanTreeToken* tokens) { + while (repetitions >= 1) { + if (repetitions < 3) { + int i; + for (i = 0; i < repetitions; ++i) { + tokens->code = 0; // 0-value + tokens->extra_bits = 0; + ++tokens; + } + break; + } else if (repetitions < 11) { + tokens->code = 17; + tokens->extra_bits = repetitions - 3; + ++tokens; + break; + } else if (repetitions < 139) { + tokens->code = 18; + tokens->extra_bits = repetitions - 11; + ++tokens; + break; + } else { + tokens->code = 18; + tokens->extra_bits = 0x7f; // 138 repeated 0s + ++tokens; + repetitions -= 138; + } + } + return tokens; +} + +int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, + HuffmanTreeToken* tokens, int max_tokens) { + HuffmanTreeToken* const starting_token = tokens; + HuffmanTreeToken* const ending_token = tokens + max_tokens; + const int depth_size = tree->num_symbols; + int prev_value = 8; // 8 is the initial value for rle. + int i = 0; + assert(tokens != NULL); + while (i < depth_size) { + const int value = tree->code_lengths[i]; + int k = i + 1; + int runs; + while (k < depth_size && tree->code_lengths[k] == value) ++k; + runs = k - i; + if (value == 0) { + tokens = CodeRepeatedZeros(runs, tokens); + } else { + tokens = CodeRepeatedValues(runs, tokens, value, prev_value); + prev_value = value; + } + i += runs; + assert(tokens <= ending_token); + } + (void)ending_token; // suppress 'unused variable' warning + return (int)(tokens - starting_token); +} + +// ----------------------------------------------------------------------------- + +// Pre-reversed 4-bit values. +static const uint8_t kReversedBits[16] = { + 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf +}; + +static uint32_t ReverseBits(int num_bits, uint32_t bits) { + uint32_t retval = 0; + int i = 0; + while (i < num_bits) { + i += 4; + retval |= kReversedBits[bits & 0xf] << (MAX_ALLOWED_CODE_LENGTH + 1 - i); + bits >>= 4; + } + retval >>= (MAX_ALLOWED_CODE_LENGTH + 1 - num_bits); + return retval; +} + +// Get the actual bit values for a tree of bit depths. +static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) { + // 0 bit-depth means that the symbol does not exist. + int i; + int len; + uint32_t next_code[MAX_ALLOWED_CODE_LENGTH + 1]; + int depth_count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; + + assert(tree != NULL); + len = tree->num_symbols; + for (i = 0; i < len; ++i) { + const int code_length = tree->code_lengths[i]; + assert(code_length <= MAX_ALLOWED_CODE_LENGTH); + ++depth_count[code_length]; + } + depth_count[0] = 0; // ignore unused symbol + next_code[0] = 0; + { + uint32_t code = 0; + for (i = 1; i <= MAX_ALLOWED_CODE_LENGTH; ++i) { + code = (code + depth_count[i - 1]) << 1; + next_code[i] = code; + } + } + for (i = 0; i < len; ++i) { + const int code_length = tree->code_lengths[i]; + tree->codes[i] = ReverseBits(code_length, next_code[code_length]++); + } +} + +// ----------------------------------------------------------------------------- +// Main entry point + +void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, + uint8_t* const buf_rle, HuffmanTree* const huff_tree, + HuffmanTreeCode* const huff_code) { + const int num_symbols = huff_code->num_symbols; + memset(buf_rle, 0, num_symbols * sizeof(*buf_rle)); + OptimizeHuffmanForRle(num_symbols, buf_rle, histogram); + GenerateOptimalTree(histogram, num_symbols, huff_tree, tree_depth_limit, + huff_code->code_lengths); + // Create the actual bit codes for the bit lengths. + ConvertBitDepthsToSymbols(huff_code); +} diff --git a/libraries/webp/src/utils/huffman_encode_utils.h b/libraries/webp/src/utils/huffman_encode_utils.h new file mode 100644 index 0000000000..bd59ffa3cc --- /dev/null +++ b/libraries/webp/src/utils/huffman_encode_utils.h @@ -0,0 +1,60 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Entropy encoding (Huffman) for webp lossless + +#ifndef WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ +#define WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ + +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Struct for holding the tree header in coded form. +typedef struct { + uint8_t code; // value (0..15) or escape code (16,17,18) + uint8_t extra_bits; // extra bits for escape codes +} HuffmanTreeToken; + +// Struct to represent the tree codes (depth and bits array). +typedef struct { + int num_symbols; // Number of symbols. + uint8_t* code_lengths; // Code lengths of the symbols. + uint16_t* codes; // Symbol Codes. +} HuffmanTreeCode; + +// Struct to represent the Huffman tree. +typedef struct { + uint32_t total_count_; // Symbol frequency. + int value_; // Symbol value. + int pool_index_left_; // Index for the left sub-tree. + int pool_index_right_; // Index for the right sub-tree. +} HuffmanTree; + +// Turn the Huffman tree into a token sequence. +// Returns the number of tokens used. +int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, + HuffmanTreeToken* tokens, int max_tokens); + +// Create an optimized tree, and tokenize it. +// 'buf_rle' and 'huff_tree' are pre-allocated and the 'tree' is the constructed +// huffman code tree. +void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, + uint8_t* const buf_rle, HuffmanTree* const huff_tree, + HuffmanTreeCode* const huff_code); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ diff --git a/libraries/webp/src/utils/huffman_utils.c b/libraries/webp/src/utils/huffman_utils.c new file mode 100644 index 0000000000..7f54118a04 --- /dev/null +++ b/libraries/webp/src/utils/huffman_utils.c @@ -0,0 +1,299 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +#include +#include +#include +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" +#include "include/webp/format_constants.h" + +// Huffman data read via DecodeImageStream is represented in two (red and green) +// bytes. +#define MAX_HTREE_GROUPS 0x10000 + +HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) { + HTreeGroup* const htree_groups = + (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups)); + if (htree_groups == NULL) { + return NULL; + } + assert(num_htree_groups <= MAX_HTREE_GROUPS); + return htree_groups; +} + +void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) { + if (htree_groups != NULL) { + WebPSafeFree(htree_groups); + } +} + +// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the +// bit-wise reversal of the len least significant bits of key. +static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) { + uint32_t step = 1 << (len - 1); + while (key & step) { + step >>= 1; + } + return step ? (key & (step - 1)) + step : key; +} + +// Stores code in table[0], table[step], table[2*step], ..., table[end]. +// Assumes that end is an integer multiple of step. +static WEBP_INLINE void ReplicateValue(HuffmanCode* table, + int step, int end, + HuffmanCode code) { + assert(end % step == 0); + do { + end -= step; + table[end] = code; + } while (end > 0); +} + +// Returns the table width of the next 2nd level table. count is the histogram +// of bit lengths for the remaining symbols, len is the code length of the next +// processed symbol +static WEBP_INLINE int NextTableBitSize(const int* const count, + int len, int root_bits) { + int left = 1 << (len - root_bits); + while (len < MAX_ALLOWED_CODE_LENGTH) { + left -= count[len]; + if (left <= 0) break; + ++len; + left <<= 1; + } + return len - root_bits; +} + +// sorted[code_lengths_size] is a pre-allocated array for sorting symbols +// by code length. +static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits, + const int code_lengths[], int code_lengths_size, + uint16_t sorted[]) { + HuffmanCode* table = root_table; // next available space in table + int total_size = 1 << root_bits; // total size root table + 2nd level table + int len; // current code length + int symbol; // symbol index in original or sorted table + // number of codes of each length: + int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; + // offsets in sorted table for each length: + int offset[MAX_ALLOWED_CODE_LENGTH + 1]; + + assert(code_lengths_size != 0); + assert(code_lengths != NULL); + assert((root_table != NULL && sorted != NULL) || + (root_table == NULL && sorted == NULL)); + assert(root_bits > 0); + + // Build histogram of code lengths. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) { + return 0; + } + ++count[code_lengths[symbol]]; + } + + // Error, all code lengths are zeros. + if (count[0] == code_lengths_size) { + return 0; + } + + // Generate offsets into sorted symbol table by code length. + offset[1] = 0; + for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) { + if (count[len] > (1 << len)) { + return 0; + } + offset[len + 1] = offset[len] + count[len]; + } + + // Sort symbols by length, by symbol order within each length. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + const int symbol_code_length = code_lengths[symbol]; + if (code_lengths[symbol] > 0) { + if (sorted != NULL) { + if(offset[symbol_code_length] >= code_lengths_size) { + return 0; + } + sorted[offset[symbol_code_length]++] = symbol; + } else { + offset[symbol_code_length]++; + } + } + } + + // Special case code with only one value. + if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) { + if (sorted != NULL) { + HuffmanCode code; + code.bits = 0; + code.value = (uint16_t)sorted[0]; + ReplicateValue(table, 1, total_size, code); + } + return total_size; + } + + { + int step; // step size to replicate values in current table + uint32_t low = 0xffffffffu; // low bits for current root entry + uint32_t mask = total_size - 1; // mask for low bits + uint32_t key = 0; // reversed prefix code + int num_nodes = 1; // number of Huffman tree nodes + int num_open = 1; // number of open branches in current tree level + int table_bits = root_bits; // key length of current table + int table_size = 1 << table_bits; // size of current table + symbol = 0; + // Fill in root table. + for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) { + num_open <<= 1; + num_nodes += num_open; + num_open -= count[len]; + if (num_open < 0) { + return 0; + } + if (root_table == NULL) continue; + for (; count[len] > 0; --count[len]) { + HuffmanCode code; + code.bits = (uint8_t)len; + code.value = (uint16_t)sorted[symbol++]; + ReplicateValue(&table[key], step, table_size, code); + key = GetNextKey(key, len); + } + } + + // Fill in 2nd level tables and add pointers to root table. + for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH; + ++len, step <<= 1) { + num_open <<= 1; + num_nodes += num_open; + num_open -= count[len]; + if (num_open < 0) { + return 0; + } + for (; count[len] > 0; --count[len]) { + HuffmanCode code; + if ((key & mask) != low) { + if (root_table != NULL) table += table_size; + table_bits = NextTableBitSize(count, len, root_bits); + table_size = 1 << table_bits; + total_size += table_size; + low = key & mask; + if (root_table != NULL) { + root_table[low].bits = (uint8_t)(table_bits + root_bits); + root_table[low].value = (uint16_t)((table - root_table) - low); + } + } + if (root_table != NULL) { + code.bits = (uint8_t)(len - root_bits); + code.value = (uint16_t)sorted[symbol++]; + ReplicateValue(&table[key >> root_bits], step, table_size, code); + } + key = GetNextKey(key, len); + } + } + + // Check if tree is full. + if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) { + return 0; + } + } + + return total_size; +} + +// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits). +// More commonly, the value is around ~280. +#define MAX_CODE_LENGTHS_SIZE \ + ((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES) +// Cut-off value for switching between heap and stack allocation. +#define SORTED_SIZE_CUTOFF 512 +int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits, + const int code_lengths[], int code_lengths_size) { + const int total_size = + BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL); + assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE); + if (total_size == 0 || root_table == NULL) return total_size; + + if (root_table->curr_segment->curr_table + total_size >= + root_table->curr_segment->start + root_table->curr_segment->size) { + // If 'root_table' does not have enough memory, allocate a new segment. + // The available part of root_table->curr_segment is left unused because we + // need a contiguous buffer. + const int segment_size = root_table->curr_segment->size; + struct HuffmanTablesSegment* next = + (HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next)); + if (next == NULL) return 0; + // Fill the new segment. + // We need at least 'total_size' but if that value is small, it is better to + // allocate a big chunk to prevent more allocations later. 'segment_size' is + // therefore chosen (any other arbitrary value could be chosen). + next->size = total_size > segment_size ? total_size : segment_size; + next->start = + (HuffmanCode*)WebPSafeMalloc(next->size, sizeof(*next->start)); + if (next->start == NULL) { + WebPSafeFree(next); + return 0; + } + next->curr_table = next->start; + next->next = NULL; + // Point to the new segment. + root_table->curr_segment->next = next; + root_table->curr_segment = next; + } + if (code_lengths_size <= SORTED_SIZE_CUTOFF) { + // use local stack-allocated array. + uint16_t sorted[SORTED_SIZE_CUTOFF]; + BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits, + code_lengths, code_lengths_size, sorted); + } else { // rare case. Use heap allocation. + uint16_t* const sorted = + (uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted)); + if (sorted == NULL) return 0; + BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits, + code_lengths, code_lengths_size, sorted); + WebPSafeFree(sorted); + } + return total_size; +} + +int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) { + // Have 'segment' point to the first segment for now, 'root'. + HuffmanTablesSegment* const root = &huffman_tables->root; + huffman_tables->curr_segment = root; + root->next = NULL; + // Allocate root. + root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start)); + if (root->start == NULL) return 0; + root->curr_table = root->start; + root->size = size; + return 1; +} + +void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) { + HuffmanTablesSegment *current, *next; + if (huffman_tables == NULL) return; + // Free the root node. + current = &huffman_tables->root; + next = current->next; + WebPSafeFree(current->start); + current->start = NULL; + current->next = NULL; + current = next; + // Free the following nodes. + while (current != NULL) { + next = current->next; + WebPSafeFree(current->start); + WebPSafeFree(current); + current = next; + } +} diff --git a/libraries/webp/src/utils/huffman_utils.h b/libraries/webp/src/utils/huffman_utils.h new file mode 100644 index 0000000000..aafa5a4e09 --- /dev/null +++ b/libraries/webp/src/utils/huffman_utils.h @@ -0,0 +1,114 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +#ifndef WEBP_UTILS_HUFFMAN_UTILS_H_ +#define WEBP_UTILS_HUFFMAN_UTILS_H_ + +#include +#include "include/webp/format_constants.h" +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HUFFMAN_TABLE_BITS 8 +#define HUFFMAN_TABLE_MASK ((1 << HUFFMAN_TABLE_BITS) - 1) + +#define LENGTHS_TABLE_BITS 7 +#define LENGTHS_TABLE_MASK ((1 << LENGTHS_TABLE_BITS) - 1) + + +// Huffman lookup table entry +typedef struct { + uint8_t bits; // number of bits used for this symbol + uint16_t value; // symbol value or table offset +} HuffmanCode; + +// long version for holding 32b values +typedef struct { + int bits; // number of bits used for this symbol, + // or an impossible value if not a literal code. + uint32_t value; // 32b packed ARGB value if literal, + // or non-literal symbol otherwise +} HuffmanCode32; + +// Contiguous memory segment of HuffmanCodes. +typedef struct HuffmanTablesSegment { + HuffmanCode* start; + // Pointer to where we are writing into the segment. Starts at 'start' and + // cannot go beyond 'start' + 'size'. + HuffmanCode* curr_table; + // Pointer to the next segment in the chain. + struct HuffmanTablesSegment* next; + int size; +} HuffmanTablesSegment; + +// Chained memory segments of HuffmanCodes. +typedef struct HuffmanTables { + HuffmanTablesSegment root; + // Currently processed segment. At first, this is 'root'. + HuffmanTablesSegment* curr_segment; +} HuffmanTables; + +// Allocates a HuffmanTables with 'size' contiguous HuffmanCodes. Returns 0 on +// memory allocation error, 1 otherwise. +WEBP_NODISCARD int VP8LHuffmanTablesAllocate(int size, + HuffmanTables* huffman_tables); +void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables); + +#define HUFFMAN_PACKED_BITS 6 +#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS) + +// Huffman table group. +// Includes special handling for the following cases: +// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN) +// - is_trivial_code: only 1 code (no bit is read from bitstream) +// - use_packed_table: few enough literal symbols, so all the bit codes +// can fit into a small look-up table packed_table[] +// The common literal base, if applicable, is stored in 'literal_arb'. +typedef struct HTreeGroup HTreeGroup; +struct HTreeGroup { + HuffmanCode* htrees[HUFFMAN_CODES_PER_META_CODE]; + int is_trivial_literal; // True, if huffman trees for Red, Blue & Alpha + // Symbols are trivial (have a single code). + uint32_t literal_arb; // If is_trivial_literal is true, this is the + // ARGB value of the pixel, with Green channel + // being set to zero. + int is_trivial_code; // true if is_trivial_literal with only one code + int use_packed_table; // use packed table below for short literal code + // table mapping input bits to a packed values, or escape case to literal code + HuffmanCode32 packed_table[HUFFMAN_PACKED_TABLE_SIZE]; +}; + +// Creates the instance of HTreeGroup with specified number of tree-groups. +WEBP_NODISCARD HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); + +// Releases the memory allocated for HTreeGroup. +void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); + +// Builds Huffman lookup table assuming code lengths are in symbol order. +// The 'code_lengths' is pre-allocated temporary memory buffer used for creating +// the huffman table. +// Returns built table size or 0 in case of error (invalid tree or +// memory error). +WEBP_NODISCARD int VP8LBuildHuffmanTable(HuffmanTables* const root_table, + int root_bits, + const int code_lengths[], + int code_lengths_size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_HUFFMAN_UTILS_H_ diff --git a/libraries/webp/src/utils/palette.c b/libraries/webp/src/utils/palette.c new file mode 100644 index 0000000000..aa21b14d7d --- /dev/null +++ b/libraries/webp/src/utils/palette.c @@ -0,0 +1,402 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for palette analysis. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#include "src/utils/palette.h" + +#include +#include + +#include "src/dsp/lossless_common.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" +#include "include/webp/encode.h" +#include "include/webp/format_constants.h" + +// ----------------------------------------------------------------------------- + +// Palette reordering for smaller sum of deltas (and for smaller storage). + +static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { + const uint32_t a = WebPMemToUint32((uint8_t*)p1); + const uint32_t b = WebPMemToUint32((uint8_t*)p2); + assert(a != b); + return (a < b) ? -1 : 1; +} + +static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { + return (v <= 128) ? v : (256 - v); +} + +// Computes a value that is related to the entropy created by the +// palette entry diff. +// +// Note that the last & 0xff is a no-operation in the next statement, but +// removed by most compilers and is here only for regularity of the code. +static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { + const uint32_t diff = VP8LSubPixels(col1, col2); + const int kMoreWeightForRGBThanForAlpha = 9; + uint32_t score; + score = PaletteComponentDistance((diff >> 0) & 0xff); + score += PaletteComponentDistance((diff >> 8) & 0xff); + score += PaletteComponentDistance((diff >> 16) & 0xff); + score *= kMoreWeightForRGBThanForAlpha; + score += PaletteComponentDistance((diff >> 24) & 0xff); + return score; +} + +static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { + const uint32_t tmp = *col1; + *col1 = *col2; + *col2 = tmp; +} + +int SearchColorNoIdx(const uint32_t sorted[], uint32_t color, int num_colors) { + int low = 0, hi = num_colors; + if (sorted[low] == color) return low; // loop invariant: sorted[low] != color + while (1) { + const int mid = (low + hi) >> 1; + if (sorted[mid] == color) { + return mid; + } else if (sorted[mid] < color) { + low = mid; + } else { + hi = mid; + } + } + assert(0); + return 0; +} + +void PrepareMapToPalette(const uint32_t palette[], uint32_t num_colors, + uint32_t sorted[], uint32_t idx_map[]) { + uint32_t i; + memcpy(sorted, palette, num_colors * sizeof(*sorted)); + qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort); + for (i = 0; i < num_colors; ++i) { + idx_map[SearchColorNoIdx(sorted, palette[i], num_colors)] = i; + } +} + +//------------------------------------------------------------------------------ + +#define COLOR_HASH_SIZE (MAX_PALETTE_SIZE * 4) +#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). + +int GetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { + int i; + int x, y; + int num_colors = 0; + uint8_t in_use[COLOR_HASH_SIZE] = {0}; + uint32_t colors[COLOR_HASH_SIZE] = {0}; + const uint32_t* argb = pic->argb; + const int width = pic->width; + const int height = pic->height; + uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] + assert(pic != NULL); + assert(pic->use_argb); + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + int key; + if (argb[x] == last_pix) { + continue; + } + last_pix = argb[x]; + key = VP8LHashPix(last_pix, COLOR_HASH_RIGHT_SHIFT); + while (1) { + if (!in_use[key]) { + colors[key] = last_pix; + in_use[key] = 1; + ++num_colors; + if (num_colors > MAX_PALETTE_SIZE) { + return MAX_PALETTE_SIZE + 1; // Exact count not needed. + } + break; + } else if (colors[key] == last_pix) { + break; // The color is already there. + } else { + // Some other color sits here, so do linear conflict resolution. + ++key; + key &= (COLOR_HASH_SIZE - 1); // Key mask. + } + } + } + argb += pic->argb_stride; + } + + if (palette != NULL) { // Fill the colors into palette. + num_colors = 0; + for (i = 0; i < COLOR_HASH_SIZE; ++i) { + if (in_use[i]) { + palette[num_colors] = colors[i]; + ++num_colors; + } + } + qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); + } + return num_colors; +} + +#undef COLOR_HASH_SIZE +#undef COLOR_HASH_RIGHT_SHIFT + +// ----------------------------------------------------------------------------- + +// The palette has been sorted by alpha. This function checks if the other +// components of the palette have a monotonic development with regards to +// position in the palette. If all have monotonic development, there is +// no benefit to re-organize them greedily. A monotonic development +// would be spotted in green-only situations (like lossy alpha) or gray-scale +// images. +static int PaletteHasNonMonotonousDeltas(const uint32_t* const palette, + int num_colors) { + uint32_t predict = 0x000000; + int i; + uint8_t sign_found = 0x00; + for (i = 0; i < num_colors; ++i) { + const uint32_t diff = VP8LSubPixels(palette[i], predict); + const uint8_t rd = (diff >> 16) & 0xff; + const uint8_t gd = (diff >> 8) & 0xff; + const uint8_t bd = (diff >> 0) & 0xff; + if (rd != 0x00) { + sign_found |= (rd < 0x80) ? 1 : 2; + } + if (gd != 0x00) { + sign_found |= (gd < 0x80) ? 8 : 16; + } + if (bd != 0x00) { + sign_found |= (bd < 0x80) ? 64 : 128; + } + predict = palette[i]; + } + return (sign_found & (sign_found << 1)) != 0; // two consequent signs. +} + +static void PaletteSortMinimizeDeltas(const uint32_t* const palette_sorted, + int num_colors, uint32_t* const palette) { + uint32_t predict = 0x00000000; + int i, k; + memcpy(palette, palette_sorted, num_colors * sizeof(*palette)); + if (!PaletteHasNonMonotonousDeltas(palette_sorted, num_colors)) return; + // Find greedily always the closest color of the predicted color to minimize + // deltas in the palette. This reduces storage needs since the + // palette is stored with delta encoding. + for (i = 0; i < num_colors; ++i) { + int best_ix = i; + uint32_t best_score = ~0U; + for (k = i; k < num_colors; ++k) { + const uint32_t cur_score = PaletteColorDistance(palette[k], predict); + if (best_score > cur_score) { + best_score = cur_score; + best_ix = k; + } + } + SwapColor(&palette[best_ix], &palette[i]); + predict = palette[i]; + } +} + +// ----------------------------------------------------------------------------- +// Modified Zeng method from "A Survey on Palette Reordering +// Methods for Improving the Compression of Color-Indexed Images" by Armando J. +// Pinho and Antonio J. R. Neves. + +// Finds the biggest cooccurrence in the matrix. +static void CoOccurrenceFindMax(const uint32_t* const cooccurrence, + uint32_t num_colors, uint8_t* const c1, + uint8_t* const c2) { + // Find the index that is most frequently located adjacent to other + // (different) indexes. + uint32_t best_sum = 0u; + uint32_t i, j, best_cooccurrence; + *c1 = 0u; + for (i = 0; i < num_colors; ++i) { + uint32_t sum = 0; + for (j = 0; j < num_colors; ++j) sum += cooccurrence[i * num_colors + j]; + if (sum > best_sum) { + best_sum = sum; + *c1 = i; + } + } + // Find the index that is most frequently found adjacent to *c1. + *c2 = 0u; + best_cooccurrence = 0u; + for (i = 0; i < num_colors; ++i) { + if (cooccurrence[*c1 * num_colors + i] > best_cooccurrence) { + best_cooccurrence = cooccurrence[*c1 * num_colors + i]; + *c2 = i; + } + } + assert(*c1 != *c2); +} + +// Builds the cooccurrence matrix +static int CoOccurrenceBuild(const WebPPicture* const pic, + const uint32_t* const palette, uint32_t num_colors, + uint32_t* cooccurrence) { + uint32_t *lines, *line_top, *line_current, *line_tmp; + int x, y; + const uint32_t* src = pic->argb; + uint32_t prev_pix = ~src[0]; + uint32_t prev_idx = 0u; + uint32_t idx_map[MAX_PALETTE_SIZE] = {0}; + uint32_t palette_sorted[MAX_PALETTE_SIZE]; + lines = (uint32_t*)WebPSafeMalloc(2 * pic->width, sizeof(*lines)); + if (lines == NULL) { + return 0; + } + line_top = &lines[0]; + line_current = &lines[pic->width]; + PrepareMapToPalette(palette, num_colors, palette_sorted, idx_map); + for (y = 0; y < pic->height; ++y) { + for (x = 0; x < pic->width; ++x) { + const uint32_t pix = src[x]; + if (pix != prev_pix) { + prev_idx = idx_map[SearchColorNoIdx(palette_sorted, pix, num_colors)]; + prev_pix = pix; + } + line_current[x] = prev_idx; + // 4-connectivity is what works best as mentioned in "On the relation + // between Memon's and the modified Zeng's palette reordering methods". + if (x > 0 && prev_idx != line_current[x - 1]) { + const uint32_t left_idx = line_current[x - 1]; + ++cooccurrence[prev_idx * num_colors + left_idx]; + ++cooccurrence[left_idx * num_colors + prev_idx]; + } + if (y > 0 && prev_idx != line_top[x]) { + const uint32_t top_idx = line_top[x]; + ++cooccurrence[prev_idx * num_colors + top_idx]; + ++cooccurrence[top_idx * num_colors + prev_idx]; + } + } + line_tmp = line_top; + line_top = line_current; + line_current = line_tmp; + src += pic->argb_stride; + } + WebPSafeFree(lines); + return 1; +} + +struct Sum { + uint8_t index; + uint32_t sum; +}; + +static int PaletteSortModifiedZeng(const WebPPicture* const pic, + const uint32_t* const palette_in, + uint32_t num_colors, + uint32_t* const palette) { + uint32_t i, j, ind; + uint8_t remapping[MAX_PALETTE_SIZE]; + uint32_t* cooccurrence; + struct Sum sums[MAX_PALETTE_SIZE]; + uint32_t first, last; + uint32_t num_sums; + // TODO(vrabaud) check whether one color images should use palette or not. + if (num_colors <= 1) return 1; + // Build the co-occurrence matrix. + cooccurrence = + (uint32_t*)WebPSafeCalloc(num_colors * num_colors, sizeof(*cooccurrence)); + if (cooccurrence == NULL) { + return 0; + } + if (!CoOccurrenceBuild(pic, palette_in, num_colors, cooccurrence)) { + WebPSafeFree(cooccurrence); + return 0; + } + + // Initialize the mapping list with the two best indices. + CoOccurrenceFindMax(cooccurrence, num_colors, &remapping[0], &remapping[1]); + + // We need to append and prepend to the list of remapping. To this end, we + // actually define the next start/end of the list as indices in a vector (with + // a wrap around when the end is reached). + first = 0; + last = 1; + num_sums = num_colors - 2; // -2 because we know the first two values + if (num_sums > 0) { + // Initialize the sums with the first two remappings and find the best one + struct Sum* best_sum = &sums[0]; + best_sum->index = 0u; + best_sum->sum = 0u; + for (i = 0, j = 0; i < num_colors; ++i) { + if (i == remapping[0] || i == remapping[1]) continue; + sums[j].index = i; + sums[j].sum = cooccurrence[i * num_colors + remapping[0]] + + cooccurrence[i * num_colors + remapping[1]]; + if (sums[j].sum > best_sum->sum) best_sum = &sums[j]; + ++j; + } + + while (num_sums > 0) { + const uint8_t best_index = best_sum->index; + // Compute delta to know if we need to prepend or append the best index. + int32_t delta = 0; + const int32_t n = num_colors - num_sums; + for (ind = first, j = 0; (ind + j) % num_colors != last + 1; ++j) { + const uint16_t l_j = remapping[(ind + j) % num_colors]; + delta += (n - 1 - 2 * (int32_t)j) * + (int32_t)cooccurrence[best_index * num_colors + l_j]; + } + if (delta > 0) { + first = (first == 0) ? num_colors - 1 : first - 1; + remapping[first] = best_index; + } else { + ++last; + remapping[last] = best_index; + } + // Remove best_sum from sums. + *best_sum = sums[num_sums - 1]; + --num_sums; + // Update all the sums and find the best one. + best_sum = &sums[0]; + for (i = 0; i < num_sums; ++i) { + sums[i].sum += cooccurrence[best_index * num_colors + sums[i].index]; + if (sums[i].sum > best_sum->sum) best_sum = &sums[i]; + } + } + } + assert((last + 1) % num_colors == first); + WebPSafeFree(cooccurrence); + + // Re-map the palette. + for (i = 0; i < num_colors; ++i) { + palette[i] = palette_in[remapping[(first + i) % num_colors]]; + } + return 1; +} + +// ----------------------------------------------------------------------------- + +int PaletteSort(PaletteSorting method, const struct WebPPicture* const pic, + const uint32_t* const palette_sorted, uint32_t num_colors, + uint32_t* const palette) { + switch (method) { + case kSortedDefault: + // Nothing to do, we have already sorted the palette. + memcpy(palette, palette_sorted, num_colors * sizeof(*palette)); + return 1; + case kMinimizeDelta: + PaletteSortMinimizeDeltas(palette_sorted, num_colors, palette); + return 1; + case kModifiedZeng: + return PaletteSortModifiedZeng(pic, palette_sorted, num_colors, palette); + case kUnusedPalette: + case kPaletteSortingNum: + break; + } + + assert(0); + return 0; +} diff --git a/libraries/webp/src/utils/palette.h b/libraries/webp/src/utils/palette.h new file mode 100644 index 0000000000..655007ac42 --- /dev/null +++ b/libraries/webp/src/utils/palette.h @@ -0,0 +1,60 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for palette analysis. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_UTILS_PALETTE_H_ +#define WEBP_UTILS_PALETTE_H_ + +#include "include/webp/types.h" + +struct WebPPicture; + +// The different ways a palette can be sorted. +typedef enum PaletteSorting { + kSortedDefault = 0, + // Sorts by minimizing L1 deltas between consecutive colors, giving more + // weight to RGB colors. + kMinimizeDelta = 1, + // Implements the modified Zeng method from "A Survey on Palette Reordering + // Methods for Improving the Compression of Color-Indexed Images" by Armando + // J. Pinho and Antonio J. R. Neves. + kModifiedZeng = 2, + kUnusedPalette = 3, + kPaletteSortingNum = 4 +} PaletteSorting; + +// Returns the index of 'color' in the sorted palette 'sorted' of size +// 'num_colors'. +int SearchColorNoIdx(const uint32_t sorted[], uint32_t color, int num_colors); + +// Sort palette in increasing order and prepare an inverse mapping array. +void PrepareMapToPalette(const uint32_t palette[], uint32_t num_colors, + uint32_t sorted[], uint32_t idx_map[]); + +// Returns count of unique colors in 'pic', assuming pic->use_argb is true. +// If the unique color count is more than MAX_PALETTE_SIZE, returns +// MAX_PALETTE_SIZE+1. +// If 'palette' is not NULL and the number of unique colors is less than or +// equal to MAX_PALETTE_SIZE, also outputs the actual unique colors into +// 'palette' in a sorted order. Note: 'palette' is assumed to be an array +// already allocated with at least MAX_PALETTE_SIZE elements. +int GetColorPalette(const struct WebPPicture* const pic, + uint32_t* const palette); + +// Sorts the palette according to the criterion defined by 'method'. +// 'palette_sorted' is the input palette sorted lexicographically, as done in +// PrepareMapToPalette. Returns 0 on memory allocation error. +int PaletteSort(PaletteSorting method, const struct WebPPicture* const pic, + const uint32_t* const palette_sorted, uint32_t num_colors, + uint32_t* const palette); + +#endif // WEBP_UTILS_PALETTE_H_ diff --git a/libraries/webp/src/utils/quant_levels_dec_utils.c b/libraries/webp/src/utils/quant_levels_dec_utils.c new file mode 100644 index 0000000000..97e7893704 --- /dev/null +++ b/libraries/webp/src/utils/quant_levels_dec_utils.c @@ -0,0 +1,291 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Implement gradient smoothing: we replace a current alpha value by its +// surrounding average if it's close enough (that is: the change will be less +// than the minimum distance between two quantized level). +// We use sliding window for computing the 2d moving average. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/utils/quant_levels_dec_utils.h" + +#include // for memset + +#include "src/utils/utils.h" + +// #define USE_DITHERING // uncomment to enable ordered dithering (not vital) + +#define FIX 16 // fix-point precision for averaging +#define LFIX 2 // extra precision for look-up table +#define LUT_SIZE ((1 << (8 + LFIX)) - 1) // look-up table size + +#if defined(USE_DITHERING) + +#define DFIX 4 // extra precision for ordered dithering +#define DSIZE 4 // dithering size (must be a power of two) +// cf. https://en.wikipedia.org/wiki/Ordered_dithering +static const uint8_t kOrderedDither[DSIZE][DSIZE] = { + { 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision + { 12, 4, 14, 6 }, + { 3, 11, 1, 9 }, + { 15, 7, 13, 5 } +}; + +#else +#define DFIX 0 +#endif + +typedef struct { + int width_, height_; // dimension + int stride_; // stride in bytes + int row_; // current input row being processed + uint8_t* src_; // input pointer + uint8_t* dst_; // output pointer + + int radius_; // filter radius (=delay) + int scale_; // normalization factor, in FIX bits precision + + void* mem_; // all memory + + // various scratch buffers + uint16_t* start_; + uint16_t* cur_; + uint16_t* end_; + uint16_t* top_; + uint16_t* average_; + + // input levels distribution + int num_levels_; // number of quantized levels + int min_, max_; // min and max level values + int min_level_dist_; // smallest distance between two consecutive levels + + int16_t* correction_; // size = 1 + 2*LUT_SIZE -> ~4k memory +} SmoothParams; + +//------------------------------------------------------------------------------ + +#define CLIP_8b_MASK (int)(~0U << (8 + DFIX)) +static WEBP_INLINE uint8_t clip_8b(int v) { + return (!(v & CLIP_8b_MASK)) ? (uint8_t)(v >> DFIX) : (v < 0) ? 0u : 255u; +} +#undef CLIP_8b_MASK + +// vertical accumulation +static void VFilter(SmoothParams* const p) { + const uint8_t* src = p->src_; + const int w = p->width_; + uint16_t* const cur = p->cur_; + const uint16_t* const top = p->top_; + uint16_t* const out = p->end_; + uint16_t sum = 0; // all arithmetic is modulo 16bit + int x; + + for (x = 0; x < w; ++x) { + uint16_t new_value; + sum += src[x]; + new_value = top[x] + sum; + out[x] = new_value - cur[x]; // vertical sum of 'r' pixels. + cur[x] = new_value; + } + // move input pointers one row down + p->top_ = p->cur_; + p->cur_ += w; + if (p->cur_ == p->end_) p->cur_ = p->start_; // roll-over + // We replicate edges, as it's somewhat easier as a boundary condition. + // That's why we don't update the 'src' pointer on top/bottom area: + if (p->row_ >= 0 && p->row_ < p->height_ - 1) { + p->src_ += p->stride_; + } +} + +// horizontal accumulation. We use mirror replication of missing pixels, as it's +// a little easier to implement (surprisingly). +static void HFilter(SmoothParams* const p) { + const uint16_t* const in = p->end_; + uint16_t* const out = p->average_; + const uint32_t scale = p->scale_; + const int w = p->width_; + const int r = p->radius_; + + int x; + for (x = 0; x <= r; ++x) { // left mirroring + const uint16_t delta = in[x + r - 1] + in[r - x]; + out[x] = (delta * scale) >> FIX; + } + for (; x < w - r; ++x) { // bulk middle run + const uint16_t delta = in[x + r] - in[x - r - 1]; + out[x] = (delta * scale) >> FIX; + } + for (; x < w; ++x) { // right mirroring + const uint16_t delta = + 2 * in[w - 1] - in[2 * w - 2 - r - x] - in[x - r - 1]; + out[x] = (delta * scale) >> FIX; + } +} + +// emit one filtered output row +static void ApplyFilter(SmoothParams* const p) { + const uint16_t* const average = p->average_; + const int w = p->width_; + const int16_t* const correction = p->correction_; +#if defined(USE_DITHERING) + const uint8_t* const dither = kOrderedDither[p->row_ % DSIZE]; +#endif + uint8_t* const dst = p->dst_; + int x; + for (x = 0; x < w; ++x) { + const int v = dst[x]; + if (v < p->max_ && v > p->min_) { + const int c = (v << DFIX) + correction[average[x] - (v << LFIX)]; +#if defined(USE_DITHERING) + dst[x] = clip_8b(c + dither[x % DSIZE]); +#else + dst[x] = clip_8b(c); +#endif + } + } + p->dst_ += p->stride_; // advance output pointer +} + +//------------------------------------------------------------------------------ +// Initialize correction table + +static void InitCorrectionLUT(int16_t* const lut, int min_dist) { + // The correction curve is: + // f(x) = x for x <= threshold2 + // f(x) = 0 for x >= threshold1 + // and a linear interpolation for range x=[threshold2, threshold1] + // (along with f(-x) = -f(x) symmetry). + // Note that: threshold2 = 3/4 * threshold1 + const int threshold1 = min_dist << LFIX; + const int threshold2 = (3 * threshold1) >> 2; + const int max_threshold = threshold2 << DFIX; + const int delta = threshold1 - threshold2; + int i; + for (i = 1; i <= LUT_SIZE; ++i) { + int c = (i <= threshold2) ? (i << DFIX) + : (i < threshold1) ? max_threshold * (threshold1 - i) / delta + : 0; + c >>= LFIX; + lut[+i] = +c; + lut[-i] = -c; + } + lut[0] = 0; +} + +static void CountLevels(SmoothParams* const p) { + int i, j, last_level; + uint8_t used_levels[256] = { 0 }; + const uint8_t* data = p->src_; + p->min_ = 255; + p->max_ = 0; + for (j = 0; j < p->height_; ++j) { + for (i = 0; i < p->width_; ++i) { + const int v = data[i]; + if (v < p->min_) p->min_ = v; + if (v > p->max_) p->max_ = v; + used_levels[v] = 1; + } + data += p->stride_; + } + // Compute the mininum distance between two non-zero levels. + p->min_level_dist_ = p->max_ - p->min_; + last_level = -1; + for (i = 0; i < 256; ++i) { + if (used_levels[i]) { + ++p->num_levels_; + if (last_level >= 0) { + const int level_dist = i - last_level; + if (level_dist < p->min_level_dist_) { + p->min_level_dist_ = level_dist; + } + } + last_level = i; + } + } +} + +// Initialize all params. +static int InitParams(uint8_t* const data, int width, int height, int stride, + int radius, SmoothParams* const p) { + const int R = 2 * radius + 1; // total size of the kernel + + const size_t size_scratch_m = (R + 1) * width * sizeof(*p->start_); + const size_t size_m = width * sizeof(*p->average_); + const size_t size_lut = (1 + 2 * LUT_SIZE) * sizeof(*p->correction_); + const size_t total_size = size_scratch_m + size_m + size_lut; + uint8_t* mem = (uint8_t*)WebPSafeMalloc(1U, total_size); + + if (mem == NULL) return 0; + p->mem_ = (void*)mem; + + p->start_ = (uint16_t*)mem; + p->cur_ = p->start_; + p->end_ = p->start_ + R * width; + p->top_ = p->end_ - width; + memset(p->top_, 0, width * sizeof(*p->top_)); + mem += size_scratch_m; + + p->average_ = (uint16_t*)mem; + mem += size_m; + + p->width_ = width; + p->height_ = height; + p->stride_ = stride; + p->src_ = data; + p->dst_ = data; + p->radius_ = radius; + p->scale_ = (1 << (FIX + LFIX)) / (R * R); // normalization constant + p->row_ = -radius; + + // analyze the input distribution so we can best-fit the threshold + CountLevels(p); + + // correction table + p->correction_ = ((int16_t*)mem) + LUT_SIZE; + InitCorrectionLUT(p->correction_, p->min_level_dist_); + + return 1; +} + +static void CleanupParams(SmoothParams* const p) { + WebPSafeFree(p->mem_); +} + +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, + int strength) { + int radius = 4 * strength / 100; + + if (strength < 0 || strength > 100) return 0; + if (data == NULL || width <= 0 || height <= 0) return 0; // bad params + + // limit the filter size to not exceed the image dimensions + if (2 * radius + 1 > width) radius = (width - 1) >> 1; + if (2 * radius + 1 > height) radius = (height - 1) >> 1; + + if (radius > 0) { + SmoothParams p; + memset(&p, 0, sizeof(p)); + if (!InitParams(data, width, height, stride, radius, &p)) return 0; + if (p.num_levels_ > 2) { + for (; p.row_ < p.height_; ++p.row_) { + VFilter(&p); // accumulate average of input + // Need to wait few rows in order to prime the filter, + // before emitting some output. + if (p.row_ >= p.radius_) { + HFilter(&p); + ApplyFilter(&p); + } + } + } + CleanupParams(&p); + } + return 1; +} diff --git a/libraries/webp/src/utils/quant_levels_dec_utils.h b/libraries/webp/src/utils/quant_levels_dec_utils.h new file mode 100644 index 0000000000..9b1e73c776 --- /dev/null +++ b/libraries/webp/src/utils/quant_levels_dec_utils.h @@ -0,0 +1,35 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha plane de-quantization utility +// +// Author: Vikas Arora (vikasa@google.com) + +#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ +#define WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ + +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Apply post-processing to input 'data' of size 'width'x'height' assuming that +// the source was quantized to a reduced number of levels. 'stride' is in bytes. +// Strength is in [0..100] and controls the amount of dithering applied. +// Returns false in case of error (data is NULL, invalid parameters, +// malloc failure, ...). +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, + int strength); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ diff --git a/libraries/webp/src/utils/quant_levels_utils.c b/libraries/webp/src/utils/quant_levels_utils.c new file mode 100644 index 0000000000..d65ad3c29d --- /dev/null +++ b/libraries/webp/src/utils/quant_levels_utils.c @@ -0,0 +1,140 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Quantize levels for specified number of quantization-levels ([2, 256]). +// Min and max values are preserved (usual 0 and 255 for alpha plane). +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/utils/quant_levels_utils.h" + +#define NUM_SYMBOLS 256 + +#define MAX_ITER 6 // Maximum number of convergence steps. +#define ERROR_THRESHOLD 1e-4 // MSE stopping criterion. + +// ----------------------------------------------------------------------------- +// Quantize levels. + +int QuantizeLevels(uint8_t* const data, int width, int height, + int num_levels, uint64_t* const sse) { + int freq[NUM_SYMBOLS] = { 0 }; + int q_level[NUM_SYMBOLS] = { 0 }; + double inv_q_level[NUM_SYMBOLS] = { 0 }; + int min_s = 255, max_s = 0; + const size_t data_size = height * width; + int i, num_levels_in, iter; + double last_err = 1.e38, err = 0.; + const double err_threshold = ERROR_THRESHOLD * data_size; + + if (data == NULL) { + return 0; + } + + if (width <= 0 || height <= 0) { + return 0; + } + + if (num_levels < 2 || num_levels > 256) { + return 0; + } + + { + size_t n; + num_levels_in = 0; + for (n = 0; n < data_size; ++n) { + num_levels_in += (freq[data[n]] == 0); + if (min_s > data[n]) min_s = data[n]; + if (max_s < data[n]) max_s = data[n]; + ++freq[data[n]]; + } + } + + if (num_levels_in <= num_levels) goto End; // nothing to do! + + // Start with uniformly spread centroids. + for (i = 0; i < num_levels; ++i) { + inv_q_level[i] = min_s + (double)(max_s - min_s) * i / (num_levels - 1); + } + + // Fixed values. Won't be changed. + q_level[min_s] = 0; + q_level[max_s] = num_levels - 1; + assert(inv_q_level[0] == min_s); + assert(inv_q_level[num_levels - 1] == max_s); + + // k-Means iterations. + for (iter = 0; iter < MAX_ITER; ++iter) { + double q_sum[NUM_SYMBOLS] = { 0 }; + double q_count[NUM_SYMBOLS] = { 0 }; + int s, slot = 0; + + // Assign classes to representatives. + for (s = min_s; s <= max_s; ++s) { + // Keep track of the nearest neighbour 'slot' + while (slot < num_levels - 1 && + 2 * s > inv_q_level[slot] + inv_q_level[slot + 1]) { + ++slot; + } + if (freq[s] > 0) { + q_sum[slot] += s * freq[s]; + q_count[slot] += freq[s]; + } + q_level[s] = slot; + } + + // Assign new representatives to classes. + if (num_levels > 2) { + for (slot = 1; slot < num_levels - 1; ++slot) { + const double count = q_count[slot]; + if (count > 0.) { + inv_q_level[slot] = q_sum[slot] / count; + } + } + } + + // Compute convergence error. + err = 0.; + for (s = min_s; s <= max_s; ++s) { + const double error = s - inv_q_level[q_level[s]]; + err += freq[s] * error * error; + } + + // Check for convergence: we stop as soon as the error is no + // longer improving. + if (last_err - err < err_threshold) break; + last_err = err; + } + + // Remap the alpha plane to quantized values. + { + // double->int rounding operation can be costly, so we do it + // once for all before remapping. We also perform the data[] -> slot + // mapping, while at it (avoid one indirection in the final loop). + uint8_t map[NUM_SYMBOLS]; + int s; + size_t n; + for (s = min_s; s <= max_s; ++s) { + const int slot = q_level[s]; + map[s] = (uint8_t)(inv_q_level[slot] + .5); + } + // Final pass. + for (n = 0; n < data_size; ++n) { + data[n] = map[data[n]]; + } + } + End: + // Store sum of squared error if needed. + if (sse != NULL) *sse = (uint64_t)err; + + return 1; +} + diff --git a/libraries/webp/src/utils/quant_levels_utils.h b/libraries/webp/src/utils/quant_levels_utils.h new file mode 100644 index 0000000000..8e283ed163 --- /dev/null +++ b/libraries/webp/src/utils/quant_levels_utils.h @@ -0,0 +1,36 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha plane quantization utility +// +// Author: Vikas Arora (vikasa@google.com) + +#ifndef WEBP_UTILS_QUANT_LEVELS_UTILS_H_ +#define WEBP_UTILS_QUANT_LEVELS_UTILS_H_ + +#include + +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Replace the input 'data' of size 'width'x'height' with 'num-levels' +// quantized values. If not NULL, 'sse' will contain the sum of squared error. +// Valid range for 'num_levels' is [2, 256]. +// Returns false in case of error (data is NULL, or parameters are invalid). +int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, + uint64_t* const sse); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_QUANT_LEVELS_UTILS_H_ diff --git a/libraries/webp/src/utils/random_utils.c b/libraries/webp/src/utils/random_utils.c new file mode 100644 index 0000000000..7edb3fefbb --- /dev/null +++ b/libraries/webp/src/utils/random_utils.c @@ -0,0 +1,43 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Pseudo-random utilities +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "src/utils/random_utils.h" + +//------------------------------------------------------------------------------ + +// 31b-range values +static const uint32_t kRandomTable[VP8_RANDOM_TABLE_SIZE] = { + 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828, + 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da, + 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f, + 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2, + 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c, + 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd, + 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3, + 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b, + 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494, + 0x27e5ed3c +}; + +void VP8InitRandom(VP8Random* const rg, float dithering) { + memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_)); + rg->index1_ = 0; + rg->index2_ = 31; + rg->amp_ = (dithering < 0.0) ? 0 + : (dithering > 1.0) ? (1 << VP8_RANDOM_DITHER_FIX) + : (uint32_t)((1 << VP8_RANDOM_DITHER_FIX) * dithering); +} + +//------------------------------------------------------------------------------ + diff --git a/libraries/webp/src/utils/random_utils.h b/libraries/webp/src/utils/random_utils.h new file mode 100644 index 0000000000..700dc4d18a --- /dev/null +++ b/libraries/webp/src/utils/random_utils.h @@ -0,0 +1,63 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Pseudo-random utilities +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_RANDOM_UTILS_H_ +#define WEBP_UTILS_RANDOM_UTILS_H_ + +#include +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering +#define VP8_RANDOM_TABLE_SIZE 55 + +typedef struct { + int index1_, index2_; + uint32_t tab_[VP8_RANDOM_TABLE_SIZE]; + int amp_; +} VP8Random; + +// Initializes random generator with an amplitude 'dithering' in range [0..1]. +void VP8InitRandom(VP8Random* const rg, float dithering); + +// Returns a centered pseudo-random number with 'num_bits' amplitude. +// (uses D.Knuth's Difference-based random generator). +// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision. +static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits, + int amp) { + int diff; + assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31); + diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_]; + if (diff < 0) diff += (1u << 31); + rg->tab_[rg->index1_] = diff; + if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0; + if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0; + // sign-extend, 0-center + diff = (int)((uint32_t)diff << 1) >> (32 - num_bits); + diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX; // restrict range + diff += 1 << (num_bits - 1); // shift back to 0.5-center + return diff; +} + +static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { + return VP8RandomBits2(rg, num_bits, rg->amp_); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_RANDOM_UTILS_H_ diff --git a/libraries/webp/src/utils/rescaler_utils.c b/libraries/webp/src/utils/rescaler_utils.c new file mode 100644 index 0000000000..a0581a14b1 --- /dev/null +++ b/libraries/webp/src/utils/rescaler_utils.c @@ -0,0 +1,160 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include +#include +#include "src/dsp/dsp.h" +#include "src/utils/rescaler_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ + +int WebPRescalerInit(WebPRescaler* const rescaler, + int src_width, int src_height, + uint8_t* const dst, + int dst_width, int dst_height, int dst_stride, + int num_channels, rescaler_t* const work) { + const int x_add = src_width, x_sub = dst_width; + const int y_add = src_height, y_sub = dst_height; + const uint64_t total_size = 2ull * dst_width * num_channels * sizeof(*work); + if (!CheckSizeOverflow(total_size)) return 0; + + rescaler->x_expand = (src_width < dst_width); + rescaler->y_expand = (src_height < dst_height); + rescaler->src_width = src_width; + rescaler->src_height = src_height; + rescaler->dst_width = dst_width; + rescaler->dst_height = dst_height; + rescaler->src_y = 0; + rescaler->dst_y = 0; + rescaler->dst = dst; + rescaler->dst_stride = dst_stride; + rescaler->num_channels = num_channels; + + // for 'x_expand', we use bilinear interpolation + rescaler->x_add = rescaler->x_expand ? (x_sub - 1) : x_add; + rescaler->x_sub = rescaler->x_expand ? (x_add - 1) : x_sub; + if (!rescaler->x_expand) { // fx_scale is not used otherwise + rescaler->fx_scale = WEBP_RESCALER_FRAC(1, rescaler->x_sub); + } + // vertical scaling parameters + rescaler->y_add = rescaler->y_expand ? y_add - 1 : y_add; + rescaler->y_sub = rescaler->y_expand ? y_sub - 1 : y_sub; + rescaler->y_accum = rescaler->y_expand ? rescaler->y_sub : rescaler->y_add; + if (!rescaler->y_expand) { + // This is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast. + // Its value is <= WEBP_RESCALER_ONE, because dst_height <= rescaler->y_add + // and rescaler->x_add >= 1; + const uint64_t num = (uint64_t)dst_height * WEBP_RESCALER_ONE; + const uint64_t den = (uint64_t)rescaler->x_add * rescaler->y_add; + const uint64_t ratio = num / den; + if (ratio != (uint32_t)ratio) { + // When ratio == WEBP_RESCALER_ONE, we can't represent the ratio with the + // current fixed-point precision. This happens when src_height == + // rescaler->y_add (which == src_height), and rescaler->x_add == 1. + // => We special-case fxy_scale = 0, in WebPRescalerExportRow(). + rescaler->fxy_scale = 0; + } else { + rescaler->fxy_scale = (uint32_t)ratio; + } + rescaler->fy_scale = WEBP_RESCALER_FRAC(1, rescaler->y_sub); + } else { + rescaler->fy_scale = WEBP_RESCALER_FRAC(1, rescaler->x_add); + // rescaler->fxy_scale is unused here. + } + rescaler->irow = work; + rescaler->frow = work + num_channels * dst_width; + memset(work, 0, (size_t)total_size); + + WebPRescalerDspInit(); + return 1; +} + +int WebPRescalerGetScaledDimensions(int src_width, int src_height, + int* const scaled_width, + int* const scaled_height) { + assert(scaled_width != NULL); + assert(scaled_height != NULL); + { + int width = *scaled_width; + int height = *scaled_height; + const int max_size = INT_MAX / 2; + + // if width is unspecified, scale original proportionally to height ratio. + if (width == 0 && src_height > 0) { + width = + (int)(((uint64_t)src_width * height + src_height - 1) / src_height); + } + // if height is unspecified, scale original proportionally to width ratio. + if (height == 0 && src_width > 0) { + height = + (int)(((uint64_t)src_height * width + src_width - 1) / src_width); + } + // Check if the overall dimensions still make sense. + if (width <= 0 || height <= 0 || width > max_size || height > max_size) { + return 0; + } + + *scaled_width = width; + *scaled_height = height; + return 1; + } +} + +//------------------------------------------------------------------------------ +// all-in-one calls + +int WebPRescaleNeededLines(const WebPRescaler* const rescaler, + int max_num_lines) { + const int num_lines = + (rescaler->y_accum + rescaler->y_sub - 1) / rescaler->y_sub; + return (num_lines > max_num_lines) ? max_num_lines : num_lines; +} + +int WebPRescalerImport(WebPRescaler* const rescaler, int num_lines, + const uint8_t* src, int src_stride) { + int total_imported = 0; + while (total_imported < num_lines && + !WebPRescalerHasPendingOutput(rescaler)) { + if (rescaler->y_expand) { + rescaler_t* const tmp = rescaler->irow; + rescaler->irow = rescaler->frow; + rescaler->frow = tmp; + } + WebPRescalerImportRow(rescaler, src); + if (!rescaler->y_expand) { // Accumulate the contribution of the new row. + int x; + for (x = 0; x < rescaler->num_channels * rescaler->dst_width; ++x) { + rescaler->irow[x] += rescaler->frow[x]; + } + } + ++rescaler->src_y; + src += src_stride; + ++total_imported; + rescaler->y_accum -= rescaler->y_sub; + } + return total_imported; +} + +int WebPRescalerExport(WebPRescaler* const rescaler) { + int total_exported = 0; + while (WebPRescalerHasPendingOutput(rescaler)) { + WebPRescalerExportRow(rescaler); + ++total_exported; + } + return total_exported; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/utils/rescaler_utils.h b/libraries/webp/src/utils/rescaler_utils.h new file mode 100644 index 0000000000..478b48da73 --- /dev/null +++ b/libraries/webp/src/utils/rescaler_utils.h @@ -0,0 +1,102 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_RESCALER_UTILS_H_ +#define WEBP_UTILS_RESCALER_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "include/webp/types.h" + +#define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies +#define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX) +#define WEBP_RESCALER_FRAC(x, y) \ + ((uint32_t)(((uint64_t)(x) << WEBP_RESCALER_RFIX) / (y))) + +// Structure used for on-the-fly rescaling +typedef uint32_t rescaler_t; // type for side-buffer +typedef struct WebPRescaler WebPRescaler; +struct WebPRescaler { + int x_expand; // true if we're expanding in the x direction + int y_expand; // true if we're expanding in the y direction + int num_channels; // bytes to jump between pixels + uint32_t fx_scale; // fixed-point scaling factors + uint32_t fy_scale; // '' + uint32_t fxy_scale; // '' + int y_accum; // vertical accumulator + int y_add, y_sub; // vertical increments + int x_add, x_sub; // horizontal increments + int src_width, src_height; // source dimensions + int dst_width, dst_height; // destination dimensions + int src_y, dst_y; // row counters for input and output + uint8_t* dst; + int dst_stride; + rescaler_t* irow, *frow; // work buffer +}; + +// Initialize a rescaler given scratch area 'work' and dimensions of src & dst. +// Returns false in case of error. +int WebPRescalerInit(WebPRescaler* const rescaler, + int src_width, int src_height, + uint8_t* const dst, + int dst_width, int dst_height, int dst_stride, + int num_channels, + rescaler_t* const work); + +// If either 'scaled_width' or 'scaled_height' (but not both) is 0 the value +// will be calculated preserving the aspect ratio, otherwise the values are +// left unmodified. Returns true on success, false if either value is 0 after +// performing the scaling calculation. +int WebPRescalerGetScaledDimensions(int src_width, int src_height, + int* const scaled_width, + int* const scaled_height); + +// Returns the number of input lines needed next to produce one output line, +// considering that the maximum available input lines are 'max_num_lines'. +int WebPRescaleNeededLines(const WebPRescaler* const rescaler, + int max_num_lines); + +// Import multiple rows over all channels, until at least one row is ready to +// be exported. Returns the actual number of lines that were imported. +int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows, + const uint8_t* src, int src_stride); + +// Export as many rows as possible. Return the numbers of rows written. +int WebPRescalerExport(WebPRescaler* const rescaler); + +// Return true if input is finished +static WEBP_INLINE +int WebPRescalerInputDone(const WebPRescaler* const rescaler) { + return (rescaler->src_y >= rescaler->src_height); +} +// Return true if output is finished +static WEBP_INLINE +int WebPRescalerOutputDone(const WebPRescaler* const rescaler) { + return (rescaler->dst_y >= rescaler->dst_height); +} + +// Return true if there are pending output rows ready. +static WEBP_INLINE +int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { + return !WebPRescalerOutputDone(rescaler) && (rescaler->y_accum <= 0); +} + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_RESCALER_UTILS_H_ diff --git a/libraries/webp/src/utils/thread_utils.c b/libraries/webp/src/utils/thread_utils.c new file mode 100644 index 0000000000..4e470e17ac --- /dev/null +++ b/libraries/webp/src/utils/thread_utils.c @@ -0,0 +1,369 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Multi-threaded worker +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include // for memset() +#include "src/utils/thread_utils.h" +#include "src/utils/utils.h" + +#ifdef WEBP_USE_THREAD + +#if defined(_WIN32) + +#include +typedef HANDLE pthread_t; +typedef CRITICAL_SECTION pthread_mutex_t; + +#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater +#define USE_WINDOWS_CONDITION_VARIABLE +typedef CONDITION_VARIABLE pthread_cond_t; +#else +typedef struct { + HANDLE waiting_sem_; + HANDLE received_sem_; + HANDLE signal_event_; +} pthread_cond_t; +#endif // _WIN32_WINNT >= 0x600 + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_PARTITION_DESKTOP 1 +#define WINAPI_FAMILY_PARTITION(x) x +#endif + +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#define USE_CREATE_THREAD +#endif + +#else // !_WIN32 + +#include + +#endif // _WIN32 + +typedef struct { + pthread_mutex_t mutex_; + pthread_cond_t condition_; + pthread_t thread_; +} WebPWorkerImpl; + +#if defined(_WIN32) + +//------------------------------------------------------------------------------ +// simplistic pthread emulation layer + +#include + +// _beginthreadex requires __stdcall +#define THREADFN unsigned int __stdcall +#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val) + +#if _WIN32_WINNT >= 0x0501 // Windows XP or greater +#define WaitForSingleObject(obj, timeout) \ + WaitForSingleObjectEx(obj, timeout, FALSE /*bAlertable*/) +#endif + +static int pthread_create(pthread_t* const thread, const void* attr, + unsigned int (__stdcall* start)(void*), void* arg) { + (void)attr; +#ifdef USE_CREATE_THREAD + *thread = CreateThread(NULL, /* lpThreadAttributes */ + 0, /* dwStackSize */ + start, + arg, + 0, /* dwStackSize */ + NULL); /* lpThreadId */ +#else + *thread = (pthread_t)_beginthreadex(NULL, /* void *security */ + 0, /* unsigned stack_size */ + start, + arg, + 0, /* unsigned initflag */ + NULL); /* unsigned *thrdaddr */ +#endif + if (*thread == NULL) return 1; + SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL); + return 0; +} + +static int pthread_join(pthread_t thread, void** value_ptr) { + (void)value_ptr; + return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 || + CloseHandle(thread) == 0); +} + +// Mutex +static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) { + (void)mutexattr; +#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater + InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/); +#else + InitializeCriticalSection(mutex); +#endif + return 0; +} + +static int pthread_mutex_lock(pthread_mutex_t* const mutex) { + EnterCriticalSection(mutex); + return 0; +} + +static int pthread_mutex_unlock(pthread_mutex_t* const mutex) { + LeaveCriticalSection(mutex); + return 0; +} + +static int pthread_mutex_destroy(pthread_mutex_t* const mutex) { + DeleteCriticalSection(mutex); + return 0; +} + +// Condition +static int pthread_cond_destroy(pthread_cond_t* const condition) { + int ok = 1; +#ifdef USE_WINDOWS_CONDITION_VARIABLE + (void)condition; +#else + ok &= (CloseHandle(condition->waiting_sem_) != 0); + ok &= (CloseHandle(condition->received_sem_) != 0); + ok &= (CloseHandle(condition->signal_event_) != 0); +#endif + return !ok; +} + +static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) { + (void)cond_attr; +#ifdef USE_WINDOWS_CONDITION_VARIABLE + InitializeConditionVariable(condition); +#else + condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL); + condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL); + condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); + if (condition->waiting_sem_ == NULL || + condition->received_sem_ == NULL || + condition->signal_event_ == NULL) { + pthread_cond_destroy(condition); + return 1; + } +#endif + return 0; +} + +static int pthread_cond_signal(pthread_cond_t* const condition) { + int ok = 1; +#ifdef USE_WINDOWS_CONDITION_VARIABLE + WakeConditionVariable(condition); +#else + if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) { + // a thread is waiting in pthread_cond_wait: allow it to be notified + ok = SetEvent(condition->signal_event_); + // wait until the event is consumed so the signaler cannot consume + // the event via its own pthread_cond_wait. + ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) != + WAIT_OBJECT_0); + } +#endif + return !ok; +} + +static int pthread_cond_wait(pthread_cond_t* const condition, + pthread_mutex_t* const mutex) { + int ok; +#ifdef USE_WINDOWS_CONDITION_VARIABLE + ok = SleepConditionVariableCS(condition, mutex, INFINITE); +#else + // note that there is a consumer available so the signal isn't dropped in + // pthread_cond_signal + if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) return 1; + // now unlock the mutex so pthread_cond_signal may be issued + pthread_mutex_unlock(mutex); + ok = (WaitForSingleObject(condition->signal_event_, INFINITE) == + WAIT_OBJECT_0); + ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL); + pthread_mutex_lock(mutex); +#endif + return !ok; +} + +#else // !_WIN32 +# define THREADFN void* +# define THREAD_RETURN(val) val +#endif // _WIN32 + +//------------------------------------------------------------------------------ + +static THREADFN ThreadLoop(void* ptr) { + WebPWorker* const worker = (WebPWorker*)ptr; + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; + int done = 0; + while (!done) { + pthread_mutex_lock(&impl->mutex_); + while (worker->status_ == OK) { // wait in idling mode + pthread_cond_wait(&impl->condition_, &impl->mutex_); + } + if (worker->status_ == WORK) { + WebPGetWorkerInterface()->Execute(worker); + worker->status_ = OK; + } else if (worker->status_ == NOT_OK) { // finish the worker + done = 1; + } + // signal to the main thread that we're done (for Sync()) + // Note the associated mutex does not need to be held when signaling the + // condition. Unlocking the mutex first may improve performance in some + // implementations, avoiding the case where the waiting thread can't + // reacquire the mutex when woken. + pthread_mutex_unlock(&impl->mutex_); + pthread_cond_signal(&impl->condition_); + } + return THREAD_RETURN(NULL); // Thread is finished +} + +// main thread state control +static void ChangeState(WebPWorker* const worker, WebPWorkerStatus new_status) { + // No-op when attempting to change state on a thread that didn't come up. + // Checking status_ without acquiring the lock first would result in a data + // race. + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; + if (impl == NULL) return; + + pthread_mutex_lock(&impl->mutex_); + if (worker->status_ >= OK) { + // wait for the worker to finish + while (worker->status_ != OK) { + pthread_cond_wait(&impl->condition_, &impl->mutex_); + } + // assign new status and release the working thread if needed + if (new_status != OK) { + worker->status_ = new_status; + // Note the associated mutex does not need to be held when signaling the + // condition. Unlocking the mutex first may improve performance in some + // implementations, avoiding the case where the waiting thread can't + // reacquire the mutex when woken. + pthread_mutex_unlock(&impl->mutex_); + pthread_cond_signal(&impl->condition_); + return; + } + } + pthread_mutex_unlock(&impl->mutex_); +} + +#endif // WEBP_USE_THREAD + +//------------------------------------------------------------------------------ + +static void Init(WebPWorker* const worker) { + memset(worker, 0, sizeof(*worker)); + worker->status_ = NOT_OK; +} + +static int Sync(WebPWorker* const worker) { +#ifdef WEBP_USE_THREAD + ChangeState(worker, OK); +#endif + assert(worker->status_ <= OK); + return !worker->had_error; +} + +static int Reset(WebPWorker* const worker) { + int ok = 1; + worker->had_error = 0; + if (worker->status_ < OK) { +#ifdef WEBP_USE_THREAD + WebPWorkerImpl* const impl = + (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(WebPWorkerImpl)); + worker->impl_ = (void*)impl; + if (worker->impl_ == NULL) { + return 0; + } + if (pthread_mutex_init(&impl->mutex_, NULL)) { + goto Error; + } + if (pthread_cond_init(&impl->condition_, NULL)) { + pthread_mutex_destroy(&impl->mutex_); + goto Error; + } + pthread_mutex_lock(&impl->mutex_); + ok = !pthread_create(&impl->thread_, NULL, ThreadLoop, worker); + if (ok) worker->status_ = OK; + pthread_mutex_unlock(&impl->mutex_); + if (!ok) { + pthread_mutex_destroy(&impl->mutex_); + pthread_cond_destroy(&impl->condition_); + Error: + WebPSafeFree(impl); + worker->impl_ = NULL; + return 0; + } +#else + worker->status_ = OK; +#endif + } else if (worker->status_ > OK) { + ok = Sync(worker); + } + assert(!ok || (worker->status_ == OK)); + return ok; +} + +static void Execute(WebPWorker* const worker) { + if (worker->hook != NULL) { + worker->had_error |= !worker->hook(worker->data1, worker->data2); + } +} + +static void Launch(WebPWorker* const worker) { +#ifdef WEBP_USE_THREAD + ChangeState(worker, WORK); +#else + Execute(worker); +#endif +} + +static void End(WebPWorker* const worker) { +#ifdef WEBP_USE_THREAD + if (worker->impl_ != NULL) { + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; + ChangeState(worker, NOT_OK); + pthread_join(impl->thread_, NULL); + pthread_mutex_destroy(&impl->mutex_); + pthread_cond_destroy(&impl->condition_); + WebPSafeFree(impl); + worker->impl_ = NULL; + } +#else + worker->status_ = NOT_OK; + assert(worker->impl_ == NULL); +#endif + assert(worker->status_ == NOT_OK); +} + +//------------------------------------------------------------------------------ + +static WebPWorkerInterface g_worker_interface = { + Init, Reset, Sync, Launch, Execute, End +}; + +int WebPSetWorkerInterface(const WebPWorkerInterface* const winterface) { + if (winterface == NULL || + winterface->Init == NULL || winterface->Reset == NULL || + winterface->Sync == NULL || winterface->Launch == NULL || + winterface->Execute == NULL || winterface->End == NULL) { + return 0; + } + g_worker_interface = *winterface; + return 1; +} + +const WebPWorkerInterface* WebPGetWorkerInterface(void) { + return &g_worker_interface; +} + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/utils/thread_utils.h b/libraries/webp/src/utils/thread_utils.h new file mode 100644 index 0000000000..6b8e364c66 --- /dev/null +++ b/libraries/webp/src/utils/thread_utils.h @@ -0,0 +1,90 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Multi-threaded worker +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_THREAD_UTILS_H_ +#define WEBP_UTILS_THREAD_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// State of the worker thread object +typedef enum { + NOT_OK = 0, // object is unusable + OK, // ready to work + WORK // busy finishing the current task +} WebPWorkerStatus; + +// Function to be called by the worker thread. Takes two opaque pointers as +// arguments (data1 and data2), and should return false in case of error. +typedef int (*WebPWorkerHook)(void*, void*); + +// Synchronization object used to launch job in the worker thread +typedef struct { + void* impl_; // platform-dependent implementation worker details + WebPWorkerStatus status_; + WebPWorkerHook hook; // hook to call + void* data1; // first argument passed to 'hook' + void* data2; // second argument passed to 'hook' + int had_error; // return value of the last call to 'hook' +} WebPWorker; + +// The interface for all thread-worker related functions. All these functions +// must be implemented. +typedef struct { + // Must be called first, before any other method. + void (*Init)(WebPWorker* const worker); + // Must be called to initialize the object and spawn the thread. Re-entrant. + // Will potentially launch the thread. Returns false in case of error. + int (*Reset)(WebPWorker* const worker); + // Makes sure the previous work is finished. Returns true if worker->had_error + // was not set and no error condition was triggered by the working thread. + int (*Sync)(WebPWorker* const worker); + // Triggers the thread to call hook() with data1 and data2 arguments. These + // hook/data1/data2 values can be changed at any time before calling this + // function, but not be changed afterward until the next call to Sync(). + void (*Launch)(WebPWorker* const worker); + // This function is similar to Launch() except that it calls the + // hook directly instead of using a thread. Convenient to bypass the thread + // mechanism while still using the WebPWorker structs. Sync() must + // still be called afterward (for error reporting). + void (*Execute)(WebPWorker* const worker); + // Kill the thread and terminate the object. To use the object again, one + // must call Reset() again. + void (*End)(WebPWorker* const worker); +} WebPWorkerInterface; + +// Install a new set of threading functions, overriding the defaults. This +// should be done before any workers are started, i.e., before any encoding or +// decoding takes place. The contents of the interface struct are copied, it +// is safe to free the corresponding memory after this call. This function is +// not thread-safe. Return false in case of invalid pointer or methods. +WEBP_EXTERN int WebPSetWorkerInterface( + const WebPWorkerInterface* const winterface); + +// Retrieve the currently set thread worker interface. +WEBP_EXTERN const WebPWorkerInterface* WebPGetWorkerInterface(void); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_THREAD_UTILS_H_ diff --git a/libraries/webp/src/utils/utils.c b/libraries/webp/src/utils/utils.c new file mode 100644 index 0000000000..fd6b843dab --- /dev/null +++ b/libraries/webp/src/utils/utils.c @@ -0,0 +1,282 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/utils/utils.h" + +#include +#include // for memcpy() + +#include "src/utils/palette.h" +#include "include/webp/encode.h" + +// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of +// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, +// and not multi-thread safe!). +// An interesting alternative is valgrind's 'massif' tool: +// https://valgrind.org/docs/manual/ms-manual.html +// Here is an example command line: +/* valgrind --tool=massif --massif-out-file=massif.out \ + --stacks=yes --alloc-fn=WebPSafeMalloc --alloc-fn=WebPSafeCalloc + ms_print massif.out +*/ +// In addition: +// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles +// are printed. +// * if MALLOC_FAIL_AT is defined, the global environment variable +// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc +// is called for the nth time. Example usage: +// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png +// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT +// sets the maximum amount of memory (in bytes) made available to libwebp. +// This can be used to emulate environment with very limited memory. +// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp + +// #define PRINT_MEM_INFO +// #define PRINT_MEM_TRAFFIC +// #define MALLOC_FAIL_AT +// #define MALLOC_LIMIT + +//------------------------------------------------------------------------------ +// Checked memory allocation + +#if defined(PRINT_MEM_INFO) + +#include + +static int num_malloc_calls = 0; +static int num_calloc_calls = 0; +static int num_free_calls = 0; +static int countdown_to_fail = 0; // 0 = off + +typedef struct MemBlock MemBlock; +struct MemBlock { + void* ptr_; + size_t size_; + MemBlock* next_; +}; + +static MemBlock* all_blocks = NULL; +static size_t total_mem = 0; +static size_t total_mem_allocated = 0; +static size_t high_water_mark = 0; +static size_t mem_limit = 0; + +static int exit_registered = 0; + +static void PrintMemInfo(void) { + fprintf(stderr, "\nMEMORY INFO:\n"); + fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls); + fprintf(stderr, " calloc = %4d\n", num_calloc_calls); + fprintf(stderr, " free = %4d\n", num_free_calls); + fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem); + fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated); + fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark); + while (all_blocks != NULL) { + MemBlock* b = all_blocks; + all_blocks = b->next_; + free(b); + } +} + +static void Increment(int* const v) { + if (!exit_registered) { +#if defined(MALLOC_FAIL_AT) + { + const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT"); + if (malloc_fail_at_str != NULL) { + countdown_to_fail = atoi(malloc_fail_at_str); + } + } +#endif +#if defined(MALLOC_LIMIT) + { + const char* const malloc_limit_str = getenv("MALLOC_LIMIT"); +#if MALLOC_LIMIT > 1 + mem_limit = (size_t)MALLOC_LIMIT; +#endif + if (malloc_limit_str != NULL) { + mem_limit = atoi(malloc_limit_str); + } + } +#endif + (void)countdown_to_fail; + (void)mem_limit; + atexit(PrintMemInfo); + exit_registered = 1; + } + ++*v; +} + +static void AddMem(void* ptr, size_t size) { + if (ptr != NULL) { + MemBlock* const b = (MemBlock*)malloc(sizeof(*b)); + if (b == NULL) abort(); + b->next_ = all_blocks; + all_blocks = b; + b->ptr_ = ptr; + b->size_ = size; + total_mem += size; + total_mem_allocated += size; +#if defined(PRINT_MEM_TRAFFIC) +#if defined(MALLOC_FAIL_AT) + fprintf(stderr, "fail-count: %5d [mem=%u]\n", + num_malloc_calls + num_calloc_calls, (uint32_t)total_mem); +#else + fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size); +#endif +#endif + if (total_mem > high_water_mark) high_water_mark = total_mem; + } +} + +static void SubMem(void* ptr) { + if (ptr != NULL) { + MemBlock** b = &all_blocks; + // Inefficient search, but that's just for debugging. + while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_; + if (*b == NULL) { + fprintf(stderr, "Invalid pointer free! (%p)\n", ptr); + abort(); + } + { + MemBlock* const block = *b; + *b = block->next_; + total_mem -= block->size_; +#if defined(PRINT_MEM_TRAFFIC) + fprintf(stderr, "Mem: %u (-%u)\n", + (uint32_t)total_mem, (uint32_t)block->size_); +#endif + free(block); + } + } +} + +#else +#define Increment(v) do {} while (0) +#define AddMem(p, s) do {} while (0) +#define SubMem(p) do {} while (0) +#endif + +// Returns 0 in case of overflow of nmemb * size. +static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { + const uint64_t total_size = nmemb * size; + if (nmemb == 0) return 1; + if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; + if (!CheckSizeOverflow(total_size)) return 0; +#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT) + if (countdown_to_fail > 0 && --countdown_to_fail == 0) { + return 0; // fake fail! + } +#endif +#if defined(PRINT_MEM_INFO) && defined(MALLOC_LIMIT) + if (mem_limit > 0) { + const uint64_t new_total_mem = (uint64_t)total_mem + total_size; + if (!CheckSizeOverflow(new_total_mem) || + new_total_mem > mem_limit) { + return 0; // fake fail! + } + } +#endif + + return 1; +} + +void* WebPSafeMalloc(uint64_t nmemb, size_t size) { + void* ptr; + Increment(&num_malloc_calls); + if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; + assert(nmemb * size > 0); + ptr = malloc((size_t)(nmemb * size)); + AddMem(ptr, (size_t)(nmemb * size)); + return ptr; +} + +void* WebPSafeCalloc(uint64_t nmemb, size_t size) { + void* ptr; + Increment(&num_calloc_calls); + if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; + assert(nmemb * size > 0); + ptr = calloc((size_t)nmemb, size); + AddMem(ptr, (size_t)(nmemb * size)); + return ptr; +} + +void WebPSafeFree(void* const ptr) { + if (ptr != NULL) { + Increment(&num_free_calls); + SubMem(ptr); + } + free(ptr); +} + +// Public API functions. + +void* WebPMalloc(size_t size) { + return WebPSafeMalloc(1, size); +} + +void WebPFree(void* ptr) { + WebPSafeFree(ptr); +} + +//------------------------------------------------------------------------------ + +void WebPCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height) { + assert(src != NULL && dst != NULL); + assert(abs(src_stride) >= width && abs(dst_stride) >= width); + while (height-- > 0) { + memcpy(dst, src, width); + src += src_stride; + dst += dst_stride; + } +} + +void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { + assert(src != NULL && dst != NULL); + assert(src->width == dst->width && src->height == dst->height); + assert(src->use_argb && dst->use_argb); + WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb, + 4 * dst->argb_stride, 4 * src->width, src->height); +} + +//------------------------------------------------------------------------------ + +int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { + return GetColorPalette(pic, palette); +} + +//------------------------------------------------------------------------------ + +#if defined(WEBP_NEED_LOG_TABLE_8BIT) +const uint8_t WebPLogTable8bit[256] = { // 31 ^ clz(i) + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; +#endif + +//------------------------------------------------------------------------------ diff --git a/libraries/webp/src/utils/utils.h b/libraries/webp/src/utils/utils.h new file mode 100644 index 0000000000..7609f3d433 --- /dev/null +++ b/libraries/webp/src/utils/utils.h @@ -0,0 +1,209 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +#ifndef WEBP_UTILS_UTILS_H_ +#define WEBP_UTILS_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "include/webp/config.h" +#endif + +#include + +#include "include/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Memory allocation + +// This is the maximum memory amount that libwebp will ever try to allocate. +#ifndef WEBP_MAX_ALLOCABLE_MEMORY +#if SIZE_MAX > (1ULL << 34) +#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 34) +#else +// For 32-bit targets keep this below INT_MAX to avoid valgrind warnings. +#define WEBP_MAX_ALLOCABLE_MEMORY ((1ULL << 31) - (1 << 16)) +#endif +#endif // WEBP_MAX_ALLOCABLE_MEMORY + +static WEBP_INLINE int CheckSizeOverflow(uint64_t size) { + return size == (size_t)size; +} + +// size-checking safe malloc/calloc: verify that the requested size is not too +// large, or return NULL. You don't need to call these for constructs like +// malloc(sizeof(foo)), but only if there's picture-dependent size involved +// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this +// safe malloc() borrows the signature from calloc(), pointing at the dangerous +// underlying multiply involved. +WEBP_EXTERN void* WebPSafeMalloc(uint64_t nmemb, size_t size); +// Note that WebPSafeCalloc() expects the second argument type to be 'size_t' +// in order to favor the "calloc(num_foo, sizeof(foo))" pattern. +WEBP_EXTERN void* WebPSafeCalloc(uint64_t nmemb, size_t size); + +// Companion deallocation function to the above allocations. +WEBP_EXTERN void WebPSafeFree(void* const ptr); + +//------------------------------------------------------------------------------ +// Alignment + +#define WEBP_ALIGN_CST 31 +#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & \ + ~(uintptr_t)WEBP_ALIGN_CST) + +#include +// memcpy() is the safe way of moving potentially unaligned 32b memory. +static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { + uint32_t A; + memcpy(&A, ptr, sizeof(A)); + return A; +} + +static WEBP_INLINE int32_t WebPMemToInt32(const uint8_t* const ptr) { + return (int32_t)WebPMemToUint32(ptr); +} + +static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { + memcpy(ptr, &val, sizeof(val)); +} + +static WEBP_INLINE void WebPInt32ToMem(uint8_t* const ptr, int val) { + WebPUint32ToMem(ptr, (uint32_t)val); +} + +//------------------------------------------------------------------------------ +// Reading/writing data. + +// Read 16, 24 or 32 bits stored in little-endian order. +static WEBP_INLINE int GetLE16(const uint8_t* const data) { + return (int)(data[0] << 0) | (data[1] << 8); +} + +static WEBP_INLINE int GetLE24(const uint8_t* const data) { + return GetLE16(data) | (data[2] << 16); +} + +static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { + return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); +} + +// Store 16, 24 or 32 bits in little-endian order. +static WEBP_INLINE void PutLE16(uint8_t* const data, int val) { + assert(val < (1 << 16)); + data[0] = (val >> 0) & 0xff; + data[1] = (val >> 8) & 0xff; +} + +static WEBP_INLINE void PutLE24(uint8_t* const data, int val) { + assert(val < (1 << 24)); + PutLE16(data, val & 0xffff); + data[2] = (val >> 16) & 0xff; +} + +static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { + PutLE16(data, (int)(val & 0xffff)); + PutLE16(data + 2, (int)(val >> 16)); +} + +// use GNU builtins where available. +#if defined(__GNUC__) && \ + ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) +// Returns (int)floor(log2(n)). n must be > 0. +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { + return 31 ^ __builtin_clz(n); +} +// counts the number of trailing zero +static WEBP_INLINE int BitsCtz(uint32_t n) { return __builtin_ctz(n); } +#elif defined(_MSC_VER) && _MSC_VER > 1310 && \ + (defined(_M_X64) || defined(_M_IX86)) +#include +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) + +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { + unsigned long first_set_bit; // NOLINT (runtime/int) + _BitScanReverse(&first_set_bit, n); + return first_set_bit; +} +static WEBP_INLINE int BitsCtz(uint32_t n) { + unsigned long first_set_bit; // NOLINT (runtime/int) + _BitScanForward(&first_set_bit, n); + return first_set_bit; +} +#else // default: use the (slow) C-version. +#define WEBP_HAVE_SLOW_CLZ_CTZ // signal that the Clz/Ctz function are slow +// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either +// based on table or not. Can be used as fallback if clz() is not available. +#define WEBP_NEED_LOG_TABLE_8BIT +extern const uint8_t WebPLogTable8bit[256]; +static WEBP_INLINE int WebPLog2FloorC(uint32_t n) { + int log_value = 0; + while (n >= 256) { + log_value += 8; + n >>= 8; + } + return log_value + WebPLogTable8bit[n]; +} + +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); } + +static WEBP_INLINE int BitsCtz(uint32_t n) { + int i; + for (i = 0; i < 32; ++i, n >>= 1) { + if (n & 1) return i; + } + return 32; +} + +#endif + +//------------------------------------------------------------------------------ +// Pixel copying. + +struct WebPPicture; + +// Copy width x height pixels from 'src' to 'dst' honoring the strides. +WEBP_EXTERN void WebPCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, + int width, int height); + +// Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are +// assumed to be already allocated and using ARGB data. +WEBP_EXTERN void WebPCopyPixels(const struct WebPPicture* const src, + struct WebPPicture* const dst); + +//------------------------------------------------------------------------------ +// Unique colors. + +// Returns count of unique colors in 'pic', assuming pic->use_argb is true. +// If the unique color count is more than MAX_PALETTE_SIZE, returns +// MAX_PALETTE_SIZE+1. +// If 'palette' is not NULL and number of unique colors is less than or equal to +// MAX_PALETTE_SIZE, also outputs the actual unique colors into 'palette'. +// Note: 'palette' is assumed to be an array already allocated with at least +// MAX_PALETTE_SIZE elements. +// TODO(vrabaud) remove whenever we can break the ABI. +WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic, + uint32_t* const palette); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_UTILS_H_ diff --git a/libraries/zlib/CMakeLists.txt b/libraries/zlib/CMakeLists.txt deleted file mode 100644 index 14f0175f65..0000000000 --- a/libraries/zlib/CMakeLists.txt +++ /dev/null @@ -1,197 +0,0 @@ -cmake_minimum_required( VERSION 3.1.0 ) -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) - -make_release_only() - -project(zlib C) - -set(VERSION "1.2.7") - -if(NOT DEFINED BUILD_SHARED_LIBS) - option(BUILD_SHARED_LIBS "Build a shared library form of zlib" OFF) -endif() - -set(ZLIBNAME z) - -include(CheckTypeSize) -include(CheckFunctionExists) -include(CheckIncludeFile) -include(CheckCSourceCompiles) -enable_testing() - -check_include_file(sys/types.h HAVE_SYS_TYPES_H) -check_include_file(stdint.h HAVE_STDINT_H) -check_include_file(stddef.h HAVE_STDDEF_H) - -# -# Check to see if we have large file support -# -set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) -# We add these other definitions here because CheckTypeSize.cmake -# in CMake 2.4.x does not automatically do so and we want -# compatibility with CMake 2.4.x. -if(HAVE_SYS_TYPES_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) -endif() -if(HAVE_STDINT_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) -endif() -if(HAVE_STDDEF_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) -endif() -check_type_size(off64_t OFF64_T) -if(HAVE_OFF64_T) - add_definitions(-D_LARGEFILE64_SOURCE=1) -endif() -set(CMAKE_REQUIRED_DEFINITIONS) # clear variable - -# -# Check for fseeko -# -check_function_exists(fseeko HAVE_FSEEKO) -if(NOT HAVE_FSEEKO) - add_definitions(-DNO_FSEEKO) -endif() - -# -# Check for unistd.h -# -check_include_file(unistd.h Z_HAVE_UNISTD_H) - -if(MSVC) - set(CMAKE_DEBUG_POSTFIX "d") - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) - add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -endif() - -#if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) -# # If we're doing an out of source build and the user has a zconf.h -# # in their source tree... -# if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) -# message(FATAL_ERROR -# "You must remove ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h " -# "from the source tree. This file is included with zlib " -# "but CMake generates this file for you automatically " -# "in the build directory.") -# endif() -#endif() -# -#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein -# ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) -#include_directories(${CMAKE_CURRENT_BINARY_DIR}) - - -#============================================================================ -# zlib -#============================================================================ - -set(ZLIB_PUBLIC_HDRS - zconf.h - zlib.h -) -set(ZLIB_PRIVATE_HDRS - crc32.h - deflate.h - gzguts.h - inffast.h - inffixed.h - inflate.h - inftrees.h - trees.h - zutil.h -) -set(ZLIB_SRCS - adler32.c - compress.c - crc32.c - deflate.c -# gzclose.c -# gzlib.c -# gzread.c -# gzwrite.c - inflate.c - infback.c - inftrees.c - inffast.c - trees.c - uncompr.c - zutil.c -# win32/zlib1.rc -) - -# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) -string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9A-Za-z.]+)\".*" - "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) - -if(MINGW) - # This gets us DLL resource information when compiling on MinGW. - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND windres.exe - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) - set(ZLIB_SRCS ${ZLIB_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) -endif() - -add_library(${ZLIBNAME} STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -set_target_properties(${ZLIBNAME} PROPERTIES DEFINE_SYMBOL ZLIB_DLL) - -set_target_properties(${ZLIBNAME} PROPERTIES SOVERSION 1) - -if(NOT CYGWIN) - # This property causes shared libraries on Linux to have the full version - # encoded into their final filename. We disable this on Cygwin because - # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll - # seems to be the default. - # - # This has no effect with MSVC, on that platform the version info for - # the DLL comes from the resource file win32/zlib1.rc - set_target_properties(${ZLIBNAME} PROPERTIES VERSION ${ZLIB_FULL_VERSION}) -endif() - -if(BUILD_SHARED_LIBS AND WIN32) - # Creates zlib1.dll when building shared library version - set_target_properties(${ZLIBNAME} PROPERTIES SUFFIX "1.dll") -else() - # On unix-like platforms the library is almost always called libz - set_target_properties(${ZLIBNAME} PROPERTIES OUTPUT_NAME z) -endif() - -if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) - install(TARGETS ${ZLIBNAME} - RUNTIME DESTINATION bin - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib ) -endif() -if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) - install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION include) -endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) - install(FILES zlib.3 DESTINATION share/man/man3) -endif() - -#============================================================================ -# Example binaries -#============================================================================ - -#add_executable(example example.c) -#target_link_libraries(example ${ZLIBNAME}) -#add_test(example example) - -#add_executable(minigzip minigzip.c) -#target_link_libraries(minigzip ${ZLIBNAME}) - -#if(HAVE_OFF64_T) -# add_executable(example64 example.c) -# target_link_libraries(example64 ${ZLIBNAME}) -# set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") -# add_test(example64 example64) -# -# add_executable(minigzip64 minigzip.c) -# target_link_libraries(minigzip64 ${ZLIBNAME}) -# set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") -#endif() diff --git a/libraries/zlib/ChangeLog b/libraries/zlib/ChangeLog deleted file mode 100644 index 457526bc6a..0000000000 --- a/libraries/zlib/ChangeLog +++ /dev/null @@ -1,1590 +0,0 @@ - - ChangeLog file for zlib - -Changes in 1.2.13 (13 Oct 2022) -- Fix configure issue that discarded provided CC definition -- Correct incorrect inputs provided to the CRC functions -- Repair prototypes and exporting of new CRC functions -- Fix inflateBack to detect invalid input with distances too far -- Have infback() deliver all of the available output up to any error -- Fix a bug when getting a gzip header extra field with inflate() -- Fix bug in block type selection when Z_FIXED used -- Tighten deflateBound bounds -- Remove deleted assembler code references -- Various portability and appearance improvements - -Changes in 1.2.12 (27 Mar 2022) -- Cygwin does not have _wopen(), so do not create gzopen_w() there -- Permit a deflateParams() parameter change as soon as possible -- Limit hash table inserts after switch from stored deflate -- Fix bug when window full in deflate_stored() -- Fix CLEAR_HASH macro to be usable as a single statement -- Avoid a conversion error in gzseek when off_t type too small -- Have Makefile return non-zero error code on test failure -- Avoid some conversion warnings in gzread.c and gzwrite.c -- Update use of errno for newer Windows CE versions -- Small speedup to inflate [psumbera] -- Return an error if the gzputs string length can't fit in an int -- Add address checking in clang to -w option of configure -- Don't compute check value for raw inflate if asked to validate -- Handle case where inflateSync used when header never processed -- Avoid the use of ptrdiff_t -- Avoid an undefined behavior of memcpy() in gzappend() -- Avoid undefined behaviors of memcpy() in gz*printf() -- Avoid an undefined behavior of memcpy() in _tr_stored_block() -- Make the names in functions declarations identical to definitions -- Remove old assembler code in which bugs have manifested -- Fix deflateEnd() to not report an error at start of raw deflate -- Add legal disclaimer to README -- Emphasize the need to continue decompressing gzip members -- Correct the initialization requirements for deflateInit2() -- Fix a bug that can crash deflate on some input when using Z_FIXED -- Assure that the number of bits for deflatePrime() is valid -- Use a structure to make globals in enough.c evident -- Use a macro for the printf format of big_t in enough.c -- Clean up code style in enough.c, update version -- Use inline function instead of macro for index in enough.c -- Clarify that prefix codes are counted in enough.c -- Show all the codes for the maximum tables size in enough.c -- Add gznorm.c example, which normalizes gzip files -- Fix the zran.c example to work on a multiple-member gzip file -- Add tables for crc32_combine(), to speed it up by a factor of 200 -- Add crc32_combine_gen() and crc32_combine_op() for fast combines -- Speed up software CRC-32 computation by a factor of 1.5 to 3 -- Use atomic test and set, if available, for dynamic CRC tables -- Don't bother computing check value after successful inflateSync() -- Correct comment in crc32.c -- Add use of the ARMv8 crc32 instructions when requested -- Use ARM crc32 instructions if the ARM architecture has them -- Explicitly note that the 32-bit check values are 32 bits -- Avoid adding empty gzip member after gzflush with Z_FINISH -- Fix memory leak on error in gzlog.c -- Fix error in comment on the polynomial representation of a byte -- Clarify gz* function interfaces, referring to parameter names -- Change macro name in inflate.c to avoid collision in VxWorks -- Correct typo in blast.c -- Improve portability of contrib/minizip -- Fix indentation in minizip's zip.c -- Replace black/white with allow/block. (theresa-m) -- minizip warning fix if MAXU32 already defined. (gvollant) -- Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner) -- Clean up minizip to reduce warnings for testing -- Add fallthrough comments for gcc -- Eliminate use of ULL constants -- Separate out address sanitizing from warnings in configure -- Remove destructive aspects of make distclean -- Check for cc masquerading as gcc or clang in configure -- Fix crc32.c to compile local functions only if used - -Changes in 1.2.11 (15 Jan 2017) -- Fix deflate stored bug when pulling last block from window -- Permit immediate deflateParams changes before any deflate input - -Changes in 1.2.10 (2 Jan 2017) -- Avoid warnings on snprintf() return value -- Fix bug in deflate_stored() for zero-length input -- Fix bug in gzwrite.c that produced corrupt gzip files -- Remove files to be installed before copying them in Makefile.in -- Add warnings when compiling with assembler code - -Changes in 1.2.9 (31 Dec 2016) -- Fix contrib/minizip to permit unzipping with desktop API [Zouzou] -- Improve contrib/blast to return unused bytes -- Assure that gzoffset() is correct when appending -- Improve compress() and uncompress() to support large lengths -- Fix bug in test/example.c where error code not saved -- Remedy Coverity warning [Randers-Pehrson] -- Improve speed of gzprintf() in transparent mode -- Fix inflateInit2() bug when windowBits is 16 or 32 -- Change DEBUG macro to ZLIB_DEBUG -- Avoid uninitialized access by gzclose_w() -- Allow building zlib outside of the source directory -- Fix bug that accepted invalid zlib header when windowBits is zero -- Fix gzseek() problem on MinGW due to buggy _lseeki64 there -- Loop on write() calls in gzwrite.c in case of non-blocking I/O -- Add --warn (-w) option to ./configure for more compiler warnings -- Reject a window size of 256 bytes if not using the zlib wrapper -- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE -- Add --debug (-d) option to ./configure to define ZLIB_DEBUG -- Fix bugs in creating a very large gzip header -- Add uncompress2() function, which returns the input size used -- Assure that deflateParams() will not switch functions mid-block -- Dramatically speed up deflation for level 0 (storing) -- Add gzfread(), duplicating the interface of fread() -- Add gzfwrite(), duplicating the interface of fwrite() -- Add deflateGetDictionary() function -- Use snprintf() for later versions of Microsoft C -- Fix *Init macros to use z_ prefix when requested -- Replace as400 with os400 for OS/400 support [Monnerat] -- Add crc32_z() and adler32_z() functions with size_t lengths -- Update Visual Studio project files [AraHaan] - -Changes in 1.2.8 (28 Apr 2013) -- Update contrib/minizip/iowin32.c for Windows RT [Vollant] -- Do not force Z_CONST for C++ -- Clean up contrib/vstudio [Roß] -- Correct spelling error in zlib.h -- Fix mixed line endings in contrib/vstudio - -Changes in 1.2.7.3 (13 Apr 2013) -- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc - -Changes in 1.2.7.2 (13 Apr 2013) -- Change check for a four-byte type back to hexadecimal -- Fix typo in win32/Makefile.msc -- Add casts in gzwrite.c for pointer differences - -Changes in 1.2.7.1 (24 Mar 2013) -- Replace use of unsafe string functions with snprintf if available -- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] -- Fix gzgetc undefine when Z_PREFIX set [Turk] -- Eliminate use of mktemp in Makefile (not always available) -- Fix bug in 'F' mode for gzopen() -- Add inflateGetDictionary() function -- Correct comment in deflate.h -- Use _snprintf for snprintf in Microsoft C -- On Darwin, only use /usr/bin/libtool if libtool is not Apple -- Delete "--version" file if created by "ar --version" [Richard G.] -- Fix configure check for veracity of compiler error return codes -- Fix CMake compilation of static lib for MSVC2010 x64 -- Remove unused variable in infback9.c -- Fix argument checks in gzlog_compress() and gzlog_write() -- Clean up the usage of z_const and respect const usage within zlib -- Clean up examples/gzlog.[ch] comparisons of different types -- Avoid shift equal to bits in type (caused endless loop) -- Fix uninitialized value bug in gzputc() introduced by const patches -- Fix memory allocation error in examples/zran.c [Nor] -- Fix bug where gzopen(), gzclose() would write an empty file -- Fix bug in gzclose() when gzwrite() runs out of memory -- Check for input buffer malloc failure in examples/gzappend.c -- Add note to contrib/blast to use binary mode in stdio -- Fix comparisons of differently signed integers in contrib/blast -- Check for invalid code length codes in contrib/puff -- Fix serious but very rare decompression bug in inftrees.c -- Update inflateBack() comments, since inflate() can be faster -- Use underscored I/O function names for WINAPI_FAMILY -- Add _tr_flush_bits to the external symbols prefixed by --zprefix -- Add contrib/vstudio/vc10 pre-build step for static only -- Quote --version-script argument in CMakeLists.txt -- Don't specify --version-script on Apple platforms in CMakeLists.txt -- Fix casting error in contrib/testzlib/testzlib.c -- Fix types in contrib/minizip to match result of get_crc_table() -- Simplify contrib/vstudio/vc10 with 'd' suffix -- Add TOP support to win32/Makefile.msc -- Support i686 and amd64 assembler builds in CMakeLists.txt -- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h -- Add vc11 and vc12 build files to contrib/vstudio -- Add gzvprintf() as an undocumented function in zlib -- Fix configure for Sun shell -- Remove runtime check in configure for four-byte integer type -- Add casts and consts to ease user conversion to C++ -- Add man pages for minizip and miniunzip -- In Makefile uninstall, don't rm if preceding cd fails -- Do not return Z_BUF_ERROR if deflateParam() has nothing to write - -Changes in 1.2.7 (2 May 2012) -- Replace use of memmove() with a simple copy for portability -- Test for existence of strerror -- Restore gzgetc_ for backward compatibility with 1.2.6 -- Fix build with non-GNU make on Solaris -- Require gcc 4.0 or later on Mac OS X to use the hidden attribute -- Include unistd.h for Watcom C -- Use __WATCOMC__ instead of __WATCOM__ -- Do not use the visibility attribute if NO_VIZ defined -- Improve the detection of no hidden visibility attribute -- Avoid using __int64 for gcc or solo compilation -- Cast to char * in gzprintf to avoid warnings [Zinser] -- Fix make_vms.com for VAX [Zinser] -- Don't use library or built-in byte swaps -- Simplify test and use of gcc hidden attribute -- Fix bug in gzclose_w() when gzwrite() fails to allocate memory -- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() -- Fix bug in test/minigzip.c for configure --solo -- Fix contrib/vstudio project link errors [Mohanathas] -- Add ability to choose the builder in make_vms.com [Schweda] -- Add DESTDIR support to mingw32 win32/Makefile.gcc -- Fix comments in win32/Makefile.gcc for proper usage -- Allow overriding the default install locations for cmake -- Generate and install the pkg-config file with cmake -- Build both a static and a shared version of zlib with cmake -- Include version symbols for cmake builds -- If using cmake with MSVC, add the source directory to the includes -- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] -- Move obsolete emx makefile to old [Truta] -- Allow the use of -Wundef when compiling or using zlib -- Avoid the use of the -u option with mktemp -- Improve inflate() documentation on the use of Z_FINISH -- Recognize clang as gcc -- Add gzopen_w() in Windows for wide character path names -- Rename zconf.h in CMakeLists.txt to move it out of the way -- Add source directory in CMakeLists.txt for building examples -- Look in build directory for zlib.pc in CMakeLists.txt -- Remove gzflags from zlibvc.def in vc9 and vc10 -- Fix contrib/minizip compilation in the MinGW environment -- Update ./configure for Solaris, support --64 [Mooney] -- Remove -R. from Solaris shared build (possible security issue) -- Avoid race condition for parallel make (-j) running example -- Fix type mismatch between get_crc_table() and crc_table -- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] -- Fix the path to zlib.map in CMakeLists.txt -- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] -- Add instructions to win32/Makefile.gcc for shared install [Torri] - -Changes in 1.2.6.1 (12 Feb 2012) -- Avoid the use of the Objective-C reserved name "id" -- Include io.h in gzguts.h for Microsoft compilers -- Fix problem with ./configure --prefix and gzgetc macro -- Include gz_header definition when compiling zlib solo -- Put gzflags() functionality back in zutil.c -- Avoid library header include in crc32.c for Z_SOLO -- Use name in GCC_CLASSIC as C compiler for coverage testing, if set -- Minor cleanup in contrib/minizip/zip.c [Vollant] -- Update make_vms.com [Zinser] -- Remove unnecessary gzgetc_ function -- Use optimized byte swap operations for Microsoft and GNU [Snyder] -- Fix minor typo in zlib.h comments [Rzesniowiecki] - -Changes in 1.2.6 (29 Jan 2012) -- Update the Pascal interface in contrib/pascal -- Fix function numbers for gzgetc_ in zlibvc.def files -- Fix configure.ac for contrib/minizip [Schiffer] -- Fix large-entry detection in minizip on 64-bit systems [Schiffer] -- Have ./configure use the compiler return code for error indication -- Fix CMakeLists.txt for cross compilation [McClure] -- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] -- Fix compilation of contrib/minizip on FreeBSD [Marquez] -- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] -- Include io.h for Turbo C / Borland C on all platforms [Truta] -- Make version explicit in contrib/minizip/configure.ac [Bosmans] -- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] -- Minor cleanup up contrib/minizip/unzip.c [Vollant] -- Fix bug when compiling minizip with C++ [Vollant] -- Protect for long name and extra fields in contrib/minizip [Vollant] -- Avoid some warnings in contrib/minizip [Vollant] -- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip -- Add missing libs to minizip linker command -- Add support for VPATH builds in contrib/minizip -- Add an --enable-demos option to contrib/minizip/configure -- Add the generation of configure.log by ./configure -- Exit when required parameters not provided to win32/Makefile.gcc -- Have gzputc return the character written instead of the argument -- Use the -m option on ldconfig for BSD systems [Tobias] -- Correct in zlib.map when deflateResetKeep was added - -Changes in 1.2.5.3 (15 Jan 2012) -- Restore gzgetc function for binary compatibility -- Do not use _lseeki64 under Borland C++ [Truta] -- Update win32/Makefile.msc to build test/*.c [Truta] -- Remove old/visualc6 given CMakefile and other alternatives -- Update AS400 build files and documentation [Monnerat] -- Update win32/Makefile.gcc to build test/*.c [Truta] -- Permit stronger flushes after Z_BLOCK flushes -- Avoid extraneous empty blocks when doing empty flushes -- Permit Z_NULL arguments to deflatePending -- Allow deflatePrime() to insert bits in the middle of a stream -- Remove second empty static block for Z_PARTIAL_FLUSH -- Write out all of the available bits when using Z_BLOCK -- Insert the first two strings in the hash table after a flush - -Changes in 1.2.5.2 (17 Dec 2011) -- fix ld error: unable to find version dependency 'ZLIB_1.2.5' -- use relative symlinks for shared libs -- Avoid searching past window for Z_RLE strategy -- Assure that high-water mark initialization is always applied in deflate -- Add assertions to fill_window() in deflate.c to match comments -- Update python link in README -- Correct spelling error in gzread.c -- Fix bug in gzgets() for a concatenated empty gzip stream -- Correct error in comment for gz_make() -- Change gzread() and related to ignore junk after gzip streams -- Allow gzread() and related to continue after gzclearerr() -- Allow gzrewind() and gzseek() after a premature end-of-file -- Simplify gzseek() now that raw after gzip is ignored -- Change gzgetc() to a macro for speed (~40% speedup in testing) -- Fix gzclose() to return the actual error last encountered -- Always add large file support for windows -- Include zconf.h for windows large file support -- Include zconf.h.cmakein for windows large file support -- Update zconf.h.cmakein on make distclean -- Merge vestigial vsnprintf determination from zutil.h to gzguts.h -- Clarify how gzopen() appends in zlib.h comments -- Correct documentation of gzdirect() since junk at end now ignored -- Add a transparent write mode to gzopen() when 'T' is in the mode -- Update python link in zlib man page -- Get inffixed.h and MAKEFIXED result to match -- Add a ./config --solo option to make zlib subset with no library use -- Add undocumented inflateResetKeep() function for CAB file decoding -- Add --cover option to ./configure for gcc coverage testing -- Add #define ZLIB_CONST option to use const in the z_stream interface -- Add comment to gzdopen() in zlib.h to use dup() when using fileno() -- Note behavior of uncompress() to provide as much data as it can -- Add files in contrib/minizip to aid in building libminizip -- Split off AR options in Makefile.in and configure -- Change ON macro to Z_ARG to avoid application conflicts -- Facilitate compilation with Borland C++ for pragmas and vsnprintf -- Include io.h for Turbo C / Borland C++ -- Move example.c and minigzip.c to test/ -- Simplify incomplete code table filling in inflate_table() -- Remove code from inflate.c and infback.c that is impossible to execute -- Test the inflate code with full coverage -- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) -- Add deflateResetKeep and fix inflateResetKeep to retain dictionary -- Fix gzwrite.c to accommodate reduced memory zlib compilation -- Have inflate() with Z_FINISH avoid the allocation of a window -- Do not set strm->adler when doing raw inflate -- Fix gzeof() to behave just like feof() when read is not past end of file -- Fix bug in gzread.c when end-of-file is reached -- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF -- Document gzread() capability to read concurrently written files -- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] - -Changes in 1.2.5.1 (10 Sep 2011) -- Update FAQ entry on shared builds (#13) -- Avoid symbolic argument to chmod in Makefile.in -- Fix bug and add consts in contrib/puff [Oberhumer] -- Update contrib/puff/zeros.raw test file to have all block types -- Add full coverage test for puff in contrib/puff/Makefile -- Fix static-only-build install in Makefile.in -- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] -- Add libz.a dependency to shared in Makefile.in for parallel builds -- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out -- Replace $(...) with `...` in configure for non-bash sh [Bowler] -- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] -- Add solaris* to Linux* in configure to allow gcc use [Groffen] -- Add *bsd* to Linux* case in configure [Bar-Lev] -- Add inffast.obj to dependencies in win32/Makefile.msc -- Correct spelling error in deflate.h [Kohler] -- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc -- Add test to configure for GNU C looking for gcc in output of $cc -v -- Add zlib.pc generation to win32/Makefile.gcc [Weigelt] -- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not -- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense -- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) -- Make stronger test in zconf.h to include unistd.h for LFS -- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] -- Fix zlib.h LFS support when Z_PREFIX used -- Add updated as400 support (removed from old) [Monnerat] -- Avoid deflate sensitivity to volatile input data -- Avoid division in adler32_combine for NO_DIVIDE -- Clarify the use of Z_FINISH with deflateBound() amount of space -- Set binary for output file in puff.c -- Use u4 type for crc_table to avoid conversion warnings -- Apply casts in zlib.h to avoid conversion warnings -- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] -- Improve inflateSync() documentation to note indeterminacy -- Add deflatePending() function to return the amount of pending output -- Correct the spelling of "specification" in FAQ [Randers-Pehrson] -- Add a check in configure for stdarg.h, use for gzprintf() -- Check that pointers fit in ints when gzprint() compiled old style -- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] -- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] -- Add debug records in assembler code [Londer] -- Update RFC references to use http://tools.ietf.org/html/... [Li] -- Add --archs option, use of libtool to configure for Mac OS X [Borstel] - -Changes in 1.2.5 (19 Apr 2010) -- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] -- Default to libdir as sharedlibdir in configure [Nieder] -- Update copyright dates on modified source files -- Update trees.c to be able to generate modified trees.h -- Exit configure for MinGW, suggesting win32/Makefile.gcc -- Check for NULL path in gz_open [Homurlu] - -Changes in 1.2.4.5 (18 Apr 2010) -- Set sharedlibdir in configure [Torok] -- Set LDFLAGS in Makefile.in [Bar-Lev] -- Avoid mkdir objs race condition in Makefile.in [Bowler] -- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays -- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C -- Don't use hidden attribute when it is a warning generator (e.g. Solaris) - -Changes in 1.2.4.4 (18 Apr 2010) -- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] -- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty -- Try to use bash or ksh regardless of functionality of /bin/sh -- Fix configure incompatibility with NetBSD sh -- Remove attempt to run under bash or ksh since have better NetBSD fix -- Fix win32/Makefile.gcc for MinGW [Bar-Lev] -- Add diagnostic messages when using CROSS_PREFIX in configure -- Added --sharedlibdir option to configure [Weigelt] -- Use hidden visibility attribute when available [Frysinger] - -Changes in 1.2.4.3 (10 Apr 2010) -- Only use CROSS_PREFIX in configure for ar and ranlib if they exist -- Use CROSS_PREFIX for nm [Bar-Lev] -- Assume _LARGEFILE64_SOURCE defined is equivalent to true -- Avoid use of undefined symbols in #if with && and || -- Make *64 prototypes in gzguts.h consistent with functions -- Add -shared load option for MinGW in configure [Bowler] -- Move z_off64_t to public interface, use instead of off64_t -- Remove ! from shell test in configure (not portable to Solaris) -- Change +0 macro tests to -0 for possibly increased portability - -Changes in 1.2.4.2 (9 Apr 2010) -- Add consistent carriage returns to readme.txt's in masmx86 and masmx64 -- Really provide prototypes for *64 functions when building without LFS -- Only define unlink() in minigzip.c if unistd.h not included -- Update README to point to contrib/vstudio project files -- Move projects/vc6 to old/ and remove projects/ -- Include stdlib.h in minigzip.c for setmode() definition under WinCE -- Clean up assembler builds in win32/Makefile.msc [Rowe] -- Include sys/types.h for Microsoft for off_t definition -- Fix memory leak on error in gz_open() -- Symbolize nm as $NM in configure [Weigelt] -- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] -- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined -- Fix bug in gzeof() to take into account unused input data -- Avoid initialization of structures with variables in puff.c -- Updated win32/README-WIN32.txt [Rowe] - -Changes in 1.2.4.1 (28 Mar 2010) -- Remove the use of [a-z] constructs for sed in configure [gentoo 310225] -- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] -- Restore "for debugging" comment on sprintf() in gzlib.c -- Remove fdopen for MVS from gzguts.h -- Put new README-WIN32.txt in win32 [Rowe] -- Add check for shell to configure and invoke another shell if needed -- Fix big fat stinking bug in gzseek() on uncompressed files -- Remove vestigial F_OPEN64 define in zutil.h -- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE -- Avoid errors on non-LFS systems when applications define LFS macros -- Set EXE to ".exe" in configure for MINGW [Kahle] -- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] -- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] -- Add DLL install in win32/makefile.gcc [Bar-Lev] -- Allow Linux* or linux* from uname in configure [Bar-Lev] -- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] -- Add cross-compilation prefixes to configure [Bar-Lev] -- Match type exactly in gz_load() invocation in gzread.c -- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func -- Provide prototypes for *64 functions when building zlib without LFS -- Don't use -lc when linking shared library on MinGW -- Remove errno.h check in configure and vestigial errno code in zutil.h - -Changes in 1.2.4 (14 Mar 2010) -- Fix VER3 extraction in configure for no fourth subversion -- Update zlib.3, add docs to Makefile.in to make .pdf out of it -- Add zlib.3.pdf to distribution -- Don't set error code in gzerror() if passed pointer is NULL -- Apply destination directory fixes to CMakeLists.txt [Lowman] -- Move #cmakedefine's to a new zconf.in.cmakein -- Restore zconf.h for builds that don't use configure or cmake -- Add distclean to dummy Makefile for convenience -- Update and improve INDEX, README, and FAQ -- Update CMakeLists.txt for the return of zconf.h [Lowman] -- Update contrib/vstudio/vc9 and vc10 [Vollant] -- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc -- Apply license and readme changes to contrib/asm686 [Raiter] -- Check file name lengths and add -c option in minigzip.c [Li] -- Update contrib/amd64 and contrib/masmx86/ [Vollant] -- Avoid use of "eof" parameter in trees.c to not shadow library variable -- Update make_vms.com for removal of zlibdefs.h [Zinser] -- Update assembler code and vstudio projects in contrib [Vollant] -- Remove outdated assembler code contrib/masm686 and contrib/asm586 -- Remove old vc7 and vc8 from contrib/vstudio -- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] -- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() -- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] -- Remove *64 functions from win32/zlib.def (they're not 64-bit yet) -- Fix bug in void-returning vsprintf() case in gzwrite.c -- Fix name change from inflate.h in contrib/inflate86/inffas86.c -- Check if temporary file exists before removing in make_vms.com [Zinser] -- Fix make install and uninstall for --static option -- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] -- Update readme.txt in contrib/masmx64 and masmx86 to assemble - -Changes in 1.2.3.9 (21 Feb 2010) -- Expunge gzio.c -- Move as400 build information to old -- Fix updates in contrib/minizip and contrib/vstudio -- Add const to vsnprintf test in configure to avoid warnings [Weigelt] -- Delete zconf.h (made by configure) [Weigelt] -- Change zconf.in.h to zconf.h.in per convention [Weigelt] -- Check for NULL buf in gzgets() -- Return empty string for gzgets() with len == 1 (like fgets()) -- Fix description of gzgets() in zlib.h for end-of-file, NULL return -- Update minizip to 1.1 [Vollant] -- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c -- Note in zlib.h that gzerror() should be used to distinguish from EOF -- Remove use of snprintf() from gzlib.c -- Fix bug in gzseek() -- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] -- Fix zconf.h generation in CMakeLists.txt [Lowman] -- Improve comments in zconf.h where modified by configure - -Changes in 1.2.3.8 (13 Feb 2010) -- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] -- Use z_off64_t in gz_zero() and gz_skip() to match state->skip -- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) -- Revert to Makefile.in from 1.2.3.6 (live with the clutter) -- Fix missing error return in gzflush(), add zlib.h note -- Add *64 functions to zlib.map [Levin] -- Fix signed/unsigned comparison in gz_comp() -- Use SFLAGS when testing shared linking in configure -- Add --64 option to ./configure to use -m64 with gcc -- Fix ./configure --help to correctly name options -- Have make fail if a test fails [Levin] -- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] -- Remove assembler object files from contrib - -Changes in 1.2.3.7 (24 Jan 2010) -- Always gzopen() with O_LARGEFILE if available -- Fix gzdirect() to work immediately after gzopen() or gzdopen() -- Make gzdirect() more precise when the state changes while reading -- Improve zlib.h documentation in many places -- Catch memory allocation failure in gz_open() -- Complete close operation if seek forward in gzclose_w() fails -- Return Z_ERRNO from gzclose_r() if close() fails -- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL -- Return zero for gzwrite() errors to match zlib.h description -- Return -1 on gzputs() error to match zlib.h description -- Add zconf.in.h to allow recovery from configure modification [Weigelt] -- Fix static library permissions in Makefile.in [Weigelt] -- Avoid warnings in configure tests that hide functionality [Weigelt] -- Add *BSD and DragonFly to Linux case in configure [gentoo 123571] -- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] -- Avoid access of uninitialized data for first inflateReset2 call [Gomes] -- Keep object files in subdirectories to reduce the clutter somewhat -- Remove default Makefile and zlibdefs.h, add dummy Makefile -- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ -- Remove zlibdefs.h completely -- modify zconf.h instead - -Changes in 1.2.3.6 (17 Jan 2010) -- Avoid void * arithmetic in gzread.c and gzwrite.c -- Make compilers happier with const char * for gz_error message -- Avoid unused parameter warning in inflate.c -- Avoid signed-unsigned comparison warning in inflate.c -- Indent #pragma's for traditional C -- Fix usage of strwinerror() in glib.c, change to gz_strwinerror() -- Correct email address in configure for system options -- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] -- Update zlib.map [Brown] -- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] -- Apply various fixes to CMakeLists.txt [Lowman] -- Add checks on len in gzread() and gzwrite() -- Add error message for no more room for gzungetc() -- Remove zlib version check in gzwrite() -- Defer compression of gzprintf() result until need to -- Use snprintf() in gzdopen() if available -- Remove USE_MMAP configuration determination (only used by minigzip) -- Remove examples/pigz.c (available separately) -- Update examples/gun.c to 1.6 - -Changes in 1.2.3.5 (8 Jan 2010) -- Add space after #if in zutil.h for some compilers -- Fix relatively harmless bug in deflate_fast() [Exarevsky] -- Fix same problem in deflate_slow() -- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] -- Add deflate_rle() for faster Z_RLE strategy run-length encoding -- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding -- Change name of "write" variable in inffast.c to avoid library collisions -- Fix premature EOF from gzread() in gzio.c [Brown] -- Use zlib header window size if windowBits is 0 in inflateInit2() -- Remove compressBound() call in deflate.c to avoid linking compress.o -- Replace use of errno in gz* with functions, support WinCE [Alves] -- Provide alternative to perror() in minigzip.c for WinCE [Alves] -- Don't use _vsnprintf on later versions of MSVC [Lowman] -- Add CMake build script and input file [Lowman] -- Update contrib/minizip to 1.1 [Svensson, Vollant] -- Moved nintendods directory from contrib to root -- Replace gzio.c with a new set of routines with the same functionality -- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above -- Update contrib/minizip to 1.1b -- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h - -Changes in 1.2.3.4 (21 Dec 2009) -- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility -- Update comments in configure and Makefile.in for default --shared -- Fix test -z's in configure [Marquess] -- Build examplesh and minigzipsh when not testing -- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h -- Import LDFLAGS from the environment in configure -- Fix configure to populate SFLAGS with discovered CFLAGS options -- Adapt make_vms.com to the new Makefile.in [Zinser] -- Add zlib2ansi script for C++ compilation [Marquess] -- Add _FILE_OFFSET_BITS=64 test to make test (when applicable) -- Add AMD64 assembler code for longest match to contrib [Teterin] -- Include options from $SFLAGS when doing $LDSHARED -- Simplify 64-bit file support by introducing z_off64_t type -- Make shared object files in objs directory to work around old Sun cc -- Use only three-part version number for Darwin shared compiles -- Add rc option to ar in Makefile.in for when ./configure not run -- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* -- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile -- Protect against _FILE_OFFSET_BITS being defined when compiling zlib -- Rename Makefile.in targets allstatic to static and allshared to shared -- Fix static and shared Makefile.in targets to be independent -- Correct error return bug in gz_open() by setting state [Brown] -- Put spaces before ;;'s in configure for better sh compatibility -- Add pigz.c (parallel implementation of gzip) to examples/ -- Correct constant in crc32.c to UL [Leventhal] -- Reject negative lengths in crc32_combine() -- Add inflateReset2() function to work like inflateEnd()/inflateInit2() -- Include sys/types.h for _LARGEFILE64_SOURCE [Brown] -- Correct typo in doc/algorithm.txt [Janik] -- Fix bug in adler32_combine() [Zhu] -- Catch missing-end-of-block-code error in all inflates and in puff - Assures that random input to inflate eventually results in an error -- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ -- Update ENOUGH and its usage to reflect discovered bounds -- Fix gzerror() error report on empty input file [Brown] -- Add ush casts in trees.c to avoid pedantic runtime errors -- Fix typo in zlib.h uncompress() description [Reiss] -- Correct inflate() comments with regard to automatic header detection -- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) -- Put new version of gzlog (2.0) in examples with interruption recovery -- Add puff compile option to permit invalid distance-too-far streams -- Add puff TEST command options, ability to read piped input -- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but - _LARGEFILE64_SOURCE not defined -- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart -- Fix deflateSetDictionary() to use all 32K for output consistency -- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) -- Clear bytes after deflate lookahead to avoid use of uninitialized data -- Change a limit in inftrees.c to be more transparent to Coverity Prevent -- Update win32/zlib.def with exported symbols from zlib.h -- Correct spelling errors in zlib.h [Willem, Sobrado] -- Allow Z_BLOCK for deflate() to force a new block -- Allow negative bits in inflatePrime() to delete existing bit buffer -- Add Z_TREES flush option to inflate() to return at end of trees -- Add inflateMark() to return current state information for random access -- Add Makefile for NintendoDS to contrib [Costa] -- Add -w in configure compile tests to avoid spurious warnings [Beucler] -- Fix typos in zlib.h comments for deflateSetDictionary() -- Fix EOF detection in transparent gzread() [Maier] - -Changes in 1.2.3.3 (2 October 2006) -- Make --shared the default for configure, add a --static option -- Add compile option to permit invalid distance-too-far streams -- Add inflateUndermine() function which is required to enable above -- Remove use of "this" variable name for C++ compatibility [Marquess] -- Add testing of shared library in make test, if shared library built -- Use ftello() and fseeko() if available instead of ftell() and fseek() -- Provide two versions of all functions that use the z_off_t type for - binary compatibility -- a normal version and a 64-bit offset version, - per the Large File Support Extension when _LARGEFILE64_SOURCE is - defined; use the 64-bit versions by default when _FILE_OFFSET_BITS - is defined to be 64 -- Add a --uname= option to configure to perhaps help with cross-compiling - -Changes in 1.2.3.2 (3 September 2006) -- Turn off silly Borland warnings [Hay] -- Use off64_t and define _LARGEFILE64_SOURCE when present -- Fix missing dependency on inffixed.h in Makefile.in -- Rig configure --shared to build both shared and static [Teredesai, Truta] -- Remove zconf.in.h and instead create a new zlibdefs.h file -- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] -- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] - -Changes in 1.2.3.1 (16 August 2006) -- Add watcom directory with OpenWatcom make files [Daniel] -- Remove #undef of FAR in zconf.in.h for MVS [Fedtke] -- Update make_vms.com [Zinser] -- Use -fPIC for shared build in configure [Teredesai, Nicholson] -- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] -- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck] -- Add some FAQ entries about the contrib directory -- Update the MVS question in the FAQ -- Avoid extraneous reads after EOF in gzio.c [Brown] -- Correct spelling of "successfully" in gzio.c [Randers-Pehrson] -- Add comments to zlib.h about gzerror() usage [Brown] -- Set extra flags in gzip header in gzopen() like deflate() does -- Make configure options more compatible with double-dash conventions - [Weigelt] -- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] -- Fix uninstall target in Makefile.in [Truta] -- Add pkgconfig support [Weigelt] -- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] -- Replace set_data_type() with a more accurate detect_data_type() in - trees.c, according to the txtvsbin.txt document [Truta] -- Swap the order of #include and #include "zlib.h" in - gzio.c, example.c and minigzip.c [Truta] -- Shut up annoying VS2005 warnings about standard C deprecation [Rowe, - Truta] (where?) -- Fix target "clean" from win32/Makefile.bor [Truta] -- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] -- Update zlib www home address in win32/DLL_FAQ.txt [Truta] -- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] -- Enable browse info in the "Debug" and "ASM Debug" configurations in - the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] -- Add pkgconfig support [Weigelt] -- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, - for use in win32/zlib1.rc [Polushin, Rowe, Truta] -- Add a document that explains the new text detection scheme to - doc/txtvsbin.txt [Truta] -- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] -- Move algorithm.txt into doc/ [Truta] -- Synchronize FAQ with website -- Fix compressBound(), was low for some pathological cases [Fearnley] -- Take into account wrapper variations in deflateBound() -- Set examples/zpipe.c input and output to binary mode for Windows -- Update examples/zlib_how.html with new zpipe.c (also web site) -- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems - that gcc became pickier in 4.0) -- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain - un-versioned, the patch adds versioning only for symbols introduced in - zlib-1.2.0 or later. It also declares as local those symbols which are - not designed to be exported." [Levin] -- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure -- Do not initialize global static by default in trees.c, add a response - NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] -- Don't use strerror() in gzio.c under WinCE [Yakimov] -- Don't use errno.h in zutil.h under WinCE [Yakimov] -- Move arguments for AR to its usage to allow replacing ar [Marot] -- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] -- Improve inflateInit() and inflateInit2() documentation -- Fix structure size comment in inflate.h -- Change configure help option from --h* to --help [Santos] - -Changes in 1.2.3 (18 July 2005) -- Apply security vulnerability fixes to contrib/infback9 as well -- Clean up some text files (carriage returns, trailing space) -- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] - -Changes in 1.2.2.4 (11 July 2005) -- Add inflatePrime() function for starting inflation at bit boundary -- Avoid some Visual C warnings in deflate.c -- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit - compile -- Fix some spelling errors in comments [Betts] -- Correct inflateInit2() error return documentation in zlib.h -- Add zran.c example of compressed data random access to examples - directory, shows use of inflatePrime() -- Fix cast for assignments to strm->state in inflate.c and infback.c -- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] -- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] -- Add cast in trees.c t avoid a warning [Oberhumer] -- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] -- Update make_vms.com [Zinser] -- Initialize state->write in inflateReset() since copied in inflate_fast() -- Be more strict on incomplete code sets in inflate_table() and increase - ENOUGH and MAXD -- this repairs a possible security vulnerability for - invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for - discovering the vulnerability and providing test cases -- Add ia64 support to configure for HP-UX [Smith] -- Add error return to gzread() for format or i/o error [Levin] -- Use malloc.h for OS/2 [Necasek] - -Changes in 1.2.2.3 (27 May 2005) -- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile -- Typecast fread() return values in gzio.c [Vollant] -- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) -- Fix crc check bug in gzread() after gzungetc() [Heiner] -- Add the deflateTune() function to adjust internal compression parameters -- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) -- Remove an incorrect assertion in examples/zpipe.c -- Add C++ wrapper in infback9.h [Donais] -- Fix bug in inflateCopy() when decoding fixed codes -- Note in zlib.h how much deflateSetDictionary() actually uses -- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) -- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] -- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] -- Add gzdirect() function to indicate transparent reads -- Update contrib/minizip [Vollant] -- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] -- Add casts in crc32.c to avoid warnings [Oberhumer] -- Add contrib/masmx64 [Vollant] -- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] - -Changes in 1.2.2.2 (30 December 2004) -- Replace structure assignments in deflate.c and inflate.c with zmemcpy to - avoid implicit memcpy calls (portability for no-library compilation) -- Increase sprintf() buffer size in gzdopen() to allow for large numbers -- Add INFLATE_STRICT to check distances against zlib header -- Improve WinCE errno handling and comments [Chang] -- Remove comment about no gzip header processing in FAQ -- Add Z_FIXED strategy option to deflateInit2() to force fixed trees -- Add updated make_vms.com [Coghlan], update README -- Create a new "examples" directory, move gzappend.c there, add zpipe.c, - fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html -- Add FAQ entry and comments in deflate.c on uninitialized memory access -- Add Solaris 9 make options in configure [Gilbert] -- Allow strerror() usage in gzio.c for STDC -- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] -- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] -- Use z_off_t for adler32_combine() and crc32_combine() lengths -- Make adler32() much faster for small len -- Use OS_CODE in deflate() default gzip header - -Changes in 1.2.2.1 (31 October 2004) -- Allow inflateSetDictionary() call for raw inflate -- Fix inflate header crc check bug for file names and comments -- Add deflateSetHeader() and gz_header structure for custom gzip headers -- Add inflateGetheader() to retrieve gzip headers -- Add crc32_combine() and adler32_combine() functions -- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list -- Use zstreamp consistently in zlib.h (inflate_back functions) -- Remove GUNZIP condition from definition of inflate_mode in inflate.h - and in contrib/inflate86/inffast.S [Truta, Anderson] -- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] -- Update projects/README.projects and projects/visualc6 [Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] -- Deprecate Z_ASCII; use Z_TEXT instead [Truta] -- Use a new algorithm for setting strm->data_type in trees.c [Truta] -- Do not define an exit() prototype in zutil.c unless DEBUG defined -- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] -- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() -- Fix Darwin build version identification [Peterson] - -Changes in 1.2.2 (3 October 2004) -- Update zlib.h comments on gzip in-memory processing -- Set adler to 1 in inflateReset() to support Java test suite [Walles] -- Add contrib/dotzlib [Ravn] -- Update win32/DLL_FAQ.txt [Truta] -- Update contrib/minizip [Vollant] -- Move contrib/visual-basic.txt to old/ [Truta] -- Fix assembler builds in projects/visualc6/ [Truta] - -Changes in 1.2.1.2 (9 September 2004) -- Update INDEX file -- Fix trees.c to update strm->data_type (no one ever noticed!) -- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] -- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) -- Add limited multitasking protection to DYNAMIC_CRC_TABLE -- Add NO_vsnprintf for VMS in zutil.h [Mozilla] -- Don't declare strerror() under VMS [Mozilla] -- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize -- Update contrib/ada [Anisimkov] -- Update contrib/minizip [Vollant] -- Fix configure to not hardcode directories for Darwin [Peterson] -- Fix gzio.c to not return error on empty files [Brown] -- Fix indentation; update version in contrib/delphi/ZLib.pas and - contrib/pascal/zlibpas.pas [Truta] -- Update mkasm.bat in contrib/masmx86 [Truta] -- Update contrib/untgz [Truta] -- Add projects/README.projects [Truta] -- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] -- Remove an unnecessary assignment to curr in inftrees.c [Truta] -- Add OS/2 to exe builds in configure [Poltorak] -- Remove err dummy parameter in zlib.h [Kientzle] - -Changes in 1.2.1.1 (9 January 2004) -- Update email address in README -- Several FAQ updates -- Fix a big fat bug in inftrees.c that prevented decoding valid - dynamic blocks with only literals and no distance codes -- - Thanks to "Hot Emu" for the bug report and sample file -- Add a note to puff.c on no distance codes case - -Changes in 1.2.1 (17 November 2003) -- Remove a tab in contrib/gzappend/gzappend.c -- Update some interfaces in contrib for new zlib functions -- Update zlib version number in some contrib entries -- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] -- Support shared libraries on Hurd and KFreeBSD [Brown] -- Fix error in NO_DIVIDE option of adler32.c - -Changes in 1.2.0.8 (4 November 2003) -- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas -- Add experimental NO_DIVIDE #define in adler32.c - - Possibly faster on some processors (let me know if it is) -- Correct Z_BLOCK to not return on first inflate call if no wrap -- Fix strm->data_type on inflate() return to correctly indicate EOB -- Add deflatePrime() function for appending in the middle of a byte -- Add contrib/gzappend for an example of appending to a stream -- Update win32/DLL_FAQ.txt [Truta] -- Delete Turbo C comment in README [Truta] -- Improve some indentation in zconf.h [Truta] -- Fix infinite loop on bad input in configure script [Church] -- Fix gzeof() for concatenated gzip files [Johnson] -- Add example to contrib/visual-basic.txt [Michael B.] -- Add -p to mkdir's in Makefile.in [vda] -- Fix configure to properly detect presence or lack of printf functions -- Add AS400 support [Monnerat] -- Add a little Cygwin support [Wilson] - -Changes in 1.2.0.7 (21 September 2003) -- Correct some debug formats in contrib/infback9 -- Cast a type in a debug statement in trees.c -- Change search and replace delimiter in configure from % to # [Beebe] -- Update contrib/untgz to 0.2 with various fixes [Truta] -- Add build support for Amiga [Nikl] -- Remove some directories in old that have been updated to 1.2 -- Add dylib building for Mac OS X in configure and Makefile.in -- Remove old distribution stuff from Makefile -- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X -- Update links in README - -Changes in 1.2.0.6 (13 September 2003) -- Minor FAQ updates -- Update contrib/minizip to 1.00 [Vollant] -- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] -- Update POSTINC comment for 68060 [Nikl] -- Add contrib/infback9 with deflate64 decoding (unsupported) -- For MVS define NO_vsnprintf and undefine FAR [van Burik] -- Add pragma for fdopen on MVS [van Burik] - -Changes in 1.2.0.5 (8 September 2003) -- Add OF to inflateBackEnd() declaration in zlib.h -- Remember start when using gzdopen in the middle of a file -- Use internal off_t counters in gz* functions to properly handle seeks -- Perform more rigorous check for distance-too-far in inffast.c -- Add Z_BLOCK flush option to return from inflate at block boundary -- Set strm->data_type on return from inflate - - Indicate bits unused, if at block boundary, and if in last block -- Replace size_t with ptrdiff_t in crc32.c, and check for correct size -- Add condition so old NO_DEFLATE define still works for compatibility -- FAQ update regarding the Windows DLL [Truta] -- INDEX update: add qnx entry, remove aix entry [Truta] -- Install zlib.3 into mandir [Wilson] -- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] -- Adapt the zlib interface to the new DLL convention guidelines [Truta] -- Introduce ZLIB_WINAPI macro to allow the export of functions using - the WINAPI calling convention, for Visual Basic [Vollant, Truta] -- Update msdos and win32 scripts and makefiles [Truta] -- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] -- Add contrib/ada [Anisimkov] -- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] -- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] -- Add contrib/masm686 [Truta] -- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm - [Truta, Vollant] -- Update contrib/delphi; rename to contrib/pascal; add example [Truta] -- Remove contrib/delphi2; add a new contrib/delphi [Truta] -- Avoid inclusion of the nonstandard in contrib/iostream, - and fix some method prototypes [Truta] -- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip - [Truta] -- Avoid the use of backslash (\) in contrib/minizip [Vollant] -- Fix file time handling in contrib/untgz; update makefiles [Truta] -- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines - [Vollant] -- Remove contrib/vstudio/vc15_16 [Vollant] -- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] -- Update README.contrib [Truta] -- Invert the assignment order of match_head and s->prev[...] in - INSERT_STRING [Truta] -- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings - [Truta] -- Compare function pointers with 0, not with NULL or Z_NULL [Truta] -- Fix prototype of syncsearch in inflate.c [Truta] -- Introduce ASMINF macro to be enabled when using an ASM implementation - of inflate_fast [Truta] -- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] -- Modify test_gzio in example.c to take a single file name as a - parameter [Truta] -- Exit the example.c program if gzopen fails [Truta] -- Add type casts around strlen in example.c [Truta] -- Remove casting to sizeof in minigzip.c; give a proper type - to the variable compared with SUFFIX_LEN [Truta] -- Update definitions of STDC and STDC99 in zconf.h [Truta] -- Synchronize zconf.h with the new Windows DLL interface [Truta] -- Use SYS16BIT instead of __32BIT__ to distinguish between - 16- and 32-bit platforms [Truta] -- Use far memory allocators in small 16-bit memory models for - Turbo C [Truta] -- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in - zlibCompileFlags [Truta] -- Cygwin has vsnprintf [Wilson] -- In Windows16, OS_CODE is 0, as in MSDOS [Truta] -- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] - -Changes in 1.2.0.4 (10 August 2003) -- Minor FAQ updates -- Be more strict when checking inflateInit2's windowBits parameter -- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well -- Add gzip wrapper option to deflateInit2 using windowBits -- Add updated QNX rule in configure and qnx directory [Bonnefoy] -- Make inflate distance-too-far checks more rigorous -- Clean up FAR usage in inflate -- Add casting to sizeof() in gzio.c and minigzip.c - -Changes in 1.2.0.3 (19 July 2003) -- Fix silly error in gzungetc() implementation [Vollant] -- Update contrib/minizip and contrib/vstudio [Vollant] -- Fix printf format in example.c -- Correct cdecl support in zconf.in.h [Anisimkov] -- Minor FAQ updates - -Changes in 1.2.0.2 (13 July 2003) -- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons -- Attempt to avoid warnings in crc32.c for pointer-int conversion -- Add AIX to configure, remove aix directory [Bakker] -- Add some casts to minigzip.c -- Improve checking after insecure sprintf() or vsprintf() calls -- Remove #elif's from crc32.c -- Change leave label to inf_leave in inflate.c and infback.c to avoid - library conflicts -- Remove inflate gzip decoding by default--only enable gzip decoding by - special request for stricter backward compatibility -- Add zlibCompileFlags() function to return compilation information -- More typecasting in deflate.c to avoid warnings -- Remove leading underscore from _Capital #defines [Truta] -- Fix configure to link shared library when testing -- Add some Windows CE target adjustments [Mai] -- Remove #define ZLIB_DLL in zconf.h [Vollant] -- Add zlib.3 [Rodgers] -- Update RFC URL in deflate.c and algorithm.txt [Mai] -- Add zlib_dll_FAQ.txt to contrib [Truta] -- Add UL to some constants [Truta] -- Update minizip and vstudio [Vollant] -- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h -- Expand use of NO_DUMMY_DECL to avoid all dummy structures -- Added iostream3 to contrib [Schwardt] -- Replace rewind() with fseek() for WinCE [Truta] -- Improve setting of zlib format compression level flags - - Report 0 for huffman and rle strategies and for level == 0 or 1 - - Report 2 only for level == 6 -- Only deal with 64K limit when necessary at compile time [Truta] -- Allow TOO_FAR check to be turned off at compile time [Truta] -- Add gzclearerr() function [Souza] -- Add gzungetc() function - -Changes in 1.2.0.1 (17 March 2003) -- Add Z_RLE strategy for run-length encoding [Truta] - - When Z_RLE requested, restrict matches to distance one - - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE -- Correct FASTEST compilation to allow level == 0 -- Clean up what gets compiled for FASTEST -- Incorporate changes to zconf.in.h [Vollant] - - Refine detection of Turbo C need for dummy returns - - Refine ZLIB_DLL compilation - - Include additional header file on VMS for off_t typedef -- Try to use _vsnprintf where it supplants vsprintf [Vollant] -- Add some casts in inffast.c -- Enhance comments in zlib.h on what happens if gzprintf() tries to - write more than 4095 bytes before compression -- Remove unused state from inflateBackEnd() -- Remove exit(0) from minigzip.c, example.c -- Get rid of all those darn tabs -- Add "check" target to Makefile.in that does the same thing as "test" -- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in -- Update contrib/inflate86 [Anderson] -- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] -- Add msdos and win32 directories with makefiles [Truta] -- More additions and improvements to the FAQ - -Changes in 1.2.0 (9 March 2003) -- New and improved inflate code - - About 20% faster - - Does not allocate 32K window unless and until needed - - Automatically detects and decompresses gzip streams - - Raw inflate no longer needs an extra dummy byte at end - - Added inflateBack functions using a callback interface--even faster - than inflate, useful for file utilities (gzip, zip) - - Added inflateCopy() function to record state for random access on - externally generated deflate streams (e.g. in gzip files) - - More readable code (I hope) -- New and improved crc32() - - About 50% faster, thanks to suggestions from Rodney Brown -- Add deflateBound() and compressBound() functions -- Fix memory leak in deflateInit2() -- Permit setting dictionary for raw deflate (for parallel deflate) -- Fix const declaration for gzwrite() -- Check for some malloc() failures in gzio.c -- Fix bug in gzopen() on single-byte file 0x1f -- Fix bug in gzread() on concatenated file with 0x1f at end of buffer - and next buffer doesn't start with 0x8b -- Fix uncompress() to return Z_DATA_ERROR on truncated input -- Free memory at end of example.c -- Remove MAX #define in trees.c (conflicted with some libraries) -- Fix static const's in deflate.c, gzio.c, and zutil.[ch] -- Declare malloc() and free() in gzio.c if STDC not defined -- Use malloc() instead of calloc() in zutil.c if int big enough -- Define STDC for AIX -- Add aix/ with approach for compiling shared library on AIX -- Add HP-UX support for shared libraries in configure -- Add OpenUNIX support for shared libraries in configure -- Use $cc instead of gcc to build shared library -- Make prefix directory if needed when installing -- Correct Macintosh avoidance of typedef Byte in zconf.h -- Correct Turbo C memory allocation when under Linux -- Use libz.a instead of -lz in Makefile (assure use of compiled library) -- Update configure to check for snprintf or vsnprintf functions and their - return value, warn during make if using an insecure function -- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that - is lost when library is used--resolution is to build new zconf.h -- Documentation improvements (in zlib.h): - - Document raw deflate and inflate - - Update RFCs URL - - Point out that zlib and gzip formats are different - - Note that Z_BUF_ERROR is not fatal - - Document string limit for gzprintf() and possible buffer overflow - - Note requirement on avail_out when flushing - - Note permitted values of flush parameter of inflate() -- Add some FAQs (and even answers) to the FAQ -- Add contrib/inflate86/ for x86 faster inflate -- Add contrib/blast/ for PKWare Data Compression Library decompression -- Add contrib/puff/ simple inflate for deflate format description - -Changes in 1.1.4 (11 March 2002) -- ZFREE was repeated on same allocation on some error conditions - This creates a security problem described in - http://www.zlib.org/advisory-2002-03-11.txt -- Returned incorrect error (Z_MEM_ERROR) on some invalid data -- Avoid accesses before window for invalid distances with inflate window - less than 32K -- force windowBits > 8 to avoid a bug in the encoder for a window size - of 256 bytes. (A complete fix will be available in 1.1.5) - -Changes in 1.1.3 (9 July 1998) -- fix "an inflate input buffer bug that shows up on rare but persistent - occasions" (Mark) -- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) -- fix gzseek(..., SEEK_SET) in write mode -- fix crc check after a gzeek (Frank Faubert) -- fix miniunzip when the last entry in a zip file is itself a zip file - (J Lillge) -- add contrib/asm586 and contrib/asm686 (Brian Raiter) - See http://www.muppetlabs.com/~breadbox/software/assembly.html -- add support for Delphi 3 in contrib/delphi (Bob Dellaca) -- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) -- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) -- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) -- added a FAQ file - -- Support gzdopen on Mac with Metrowerks (Jason Linhart) -- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) -- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) -- avoid some warnings with Borland C (Tom Tanner) -- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) -- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) -- allow several arguments to configure (Tim Mooney, Frodo Looijaard) -- use libdir and includedir in Makefile.in (Tim Mooney) -- support shared libraries on OSF1 V4 (Tim Mooney) -- remove so_locations in "make clean" (Tim Mooney) -- fix maketree.c compilation error (Glenn, Mark) -- Python interface to zlib now in Python 1.5 (Jeremy Hylton) -- new Makefile.riscos (Rich Walker) -- initialize static descriptors in trees.c for embedded targets (Nick Smith) -- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) -- add the OS/2 files in Makefile.in too (Andrew Zabolotny) -- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) -- fix maketree.c to allow clean compilation of inffixed.h (Mark) -- fix parameter check in deflateCopy (Gunther Nikl) -- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) -- Many portability patches by Christian Spieler: - . zutil.c, zutil.h: added "const" for zmem* - . Make_vms.com: fixed some typos - . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists - . msdos/Makefile.msc: remove "default rtl link library" info from obj files - . msdos/Makefile.*: use model-dependent name for the built zlib library - . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: - new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) -- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) -- replace __far with _far for better portability (Christian Spieler, Tom Lane) -- fix test for errno.h in configure (Tim Newsham) - -Changes in 1.1.2 (19 March 98) -- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) - See http://www.winimage.com/zLibDll/unzip.html -- preinitialize the inflate tables for fixed codes, to make the code - completely thread safe (Mark) -- some simplifications and slight speed-up to the inflate code (Mark) -- fix gzeof on non-compressed files (Allan Schrum) -- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) -- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) -- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) -- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) -- do not wrap extern "C" around system includes (Tom Lane) -- mention zlib binding for TCL in README (Andreas Kupries) -- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) -- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) -- allow "configure --prefix $HOME" (Tim Mooney) -- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) -- move Makefile.sas to amiga/Makefile.sas - -Changes in 1.1.1 (27 Feb 98) -- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) -- remove block truncation heuristic which had very marginal effect for zlib - (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the - compression ratio on some files. This also allows inlining _tr_tally for - matches in deflate_slow -- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) - -Changes in 1.1.0 (24 Feb 98) -- do not return STREAM_END prematurely in inflate (John Bowler) -- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) -- compile with -DFASTEST to get compression code optimized for speed only -- in minigzip, try mmap'ing the input file first (Miguel Albrecht) -- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain - on Sun but significant on HP) - -- add a pointer to experimental unzip library in README (Gilles Vollant) -- initialize variable gcc in configure (Chris Herborth) - -Changes in 1.0.9 (17 Feb 1998) -- added gzputs and gzgets functions -- do not clear eof flag in gzseek (Mark Diekhans) -- fix gzseek for files in transparent mode (Mark Diekhans) -- do not assume that vsprintf returns the number of bytes written (Jens Krinke) -- replace EXPORT with ZEXPORT to avoid conflict with other programs -- added compress2 in zconf.h, zlib.def, zlib.dnt -- new asm code from Gilles Vollant in contrib/asm386 -- simplify the inflate code (Mark): - . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() - . ZALLOC the length list in inflate_trees_fixed() instead of using stack - . ZALLOC the value area for huft_build() instead of using stack - . Simplify Z_FINISH check in inflate() - -- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 -- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) -- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - the declaration of FAR (Gilles Vollant) -- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) -- read_buf buf parameter of type Bytef* instead of charf* -- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) -- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) -- fix check for presence of directories in "make install" (Ian Willis) - -Changes in 1.0.8 (27 Jan 1998) -- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) -- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) -- added compress2() to allow setting the compression level -- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) -- use constant arrays for the static trees in trees.c instead of computing - them at run time (thanks to Ken Raeburn for this suggestion). To create - trees.h, compile with GEN_TREES_H and run "make test" -- check return code of example in "make test" and display result -- pass minigzip command line options to file_compress -- simplifying code of inflateSync to avoid gcc 2.8 bug - -- support CC="gcc -Wall" in configure -s (QingLong) -- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) -- fix test for shared library support to avoid compiler warnings -- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) -- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) -- do not use fdopen for Metrowerks on Mac (Brad Pettit)) -- add checks for gzputc and gzputc in example.c -- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) -- use const for the CRC table (Ken Raeburn) -- fixed "make uninstall" for shared libraries -- use Tracev instead of Trace in infblock.c -- in example.c use correct compressed length for test_sync -- suppress +vnocompatwarnings in configure for HPUX (not always supported) - -Changes in 1.0.7 (20 Jan 1998) -- fix gzseek which was broken in write mode -- return error for gzseek to negative absolute position -- fix configure for Linux (Chun-Chung Chen) -- increase stack space for MSC (Tim Wegner) -- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) -- define EXPORTVA for gzprintf (Gilles Vollant) -- added man page zlib.3 (Rick Rodgers) -- for contrib/untgz, fix makedir() and improve Makefile - -- check gzseek in write mode in example.c -- allocate extra buffer for seeks only if gzseek is actually called -- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) -- add inflateSyncPoint in zconf.h -- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def - -Changes in 1.0.6 (19 Jan 1998) -- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and - gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) -- Fix a deflate bug occurring only with compression level 0 (thanks to - Andy Buckler for finding this one) -- In minigzip, pass transparently also the first byte for .Z files -- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() -- check Z_FINISH in inflate (thanks to Marc Schluper) -- Implement deflateCopy (thanks to Adam Costello) -- make static libraries by default in configure, add --shared option -- move MSDOS or Windows specific files to directory msdos -- suppress the notion of partial flush to simplify the interface - (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) -- suppress history buffer provided by application to simplify the interface - (this feature was not implemented anyway in 1.0.4) -- next_in and avail_in must be initialized before calling inflateInit or - inflateInit2 -- add EXPORT in all exported functions (for Windows DLL) -- added Makefile.nt (thanks to Stephen Williams) -- added the unsupported "contrib" directory: - contrib/asm386/ by Gilles Vollant - 386 asm code replacing longest_match() - contrib/iostream/ by Kevin Ruland - A C++ I/O streams interface to the zlib gz* functions - contrib/iostream2/ by Tyge Løvset - Another C++ I/O streams interface - contrib/untgz/ by "Pedro A. Aranda Guti\irrez" - A very simple tar.gz file extractor using zlib - contrib/visual-basic.txt by Carlos Rios - How to use compress(), uncompress() and the gz* functions from VB -- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression - level) in minigzip (thanks to Tom Lane) - -- use const for rommable constants in deflate -- added test for gzseek and gztell in example.c -- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) -- add undocumented function zError to convert error code to string - (for Tim Smithers) -- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code -- Use default memcpy for Symantec MSDOS compiler -- Add EXPORT keyword for check_func (needed for Windows DLL) -- add current directory to LD_LIBRARY_PATH for "make test" -- create also a link for libz.so.1 -- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) -- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) -- added -soname for Linux in configure (Chun-Chung Chen, -- assign numbers to the exported functions in zlib.def (for Windows DLL) -- add advice in zlib.h for best usage of deflateSetDictionary -- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) -- allow compilation with ANSI keywords only enabled for TurboC in large model -- avoid "versionString"[0] (Borland bug) -- add NEED_DUMMY_RETURN for Borland -- use variable z_verbose for tracing in debug mode (L. Peter Deutsch) -- allow compilation with CC -- defined STDC for OS/2 (David Charlap) -- limit external names to 8 chars for MVS (Thomas Lund) -- in minigzip.c, use static buffers only for 16-bit systems -- fix suffix check for "minigzip -d foo.gz" -- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) -- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) -- added makelcc.bat for lcc-win32 (Tom St Denis) -- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) -- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion -- check for unistd.h in configure (for off_t) -- remove useless check parameter in inflate_blocks_free -- avoid useless assignment of s->check to itself in inflate_blocks_new -- do not flush twice in gzclose (thanks to Ken Raeburn) -- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h -- use NO_ERRNO_H instead of enumeration of operating systems with errno.h -- work around buggy fclose on pipes for HP/UX -- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) -- fix configure if CC is already equal to gcc - -Changes in 1.0.5 (3 Jan 98) -- Fix inflate to terminate gracefully when fed corrupted or invalid data -- Use const for rommable constants in inflate -- Eliminate memory leaks on error conditions in inflate -- Removed some vestigial code in inflate -- Update web address in README - -Changes in 1.0.4 (24 Jul 96) -- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF - bit, so the decompressor could decompress all the correct data but went - on to attempt decompressing extra garbage data. This affected minigzip too -- zlibVersion and gzerror return const char* (needed for DLL) -- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) -- use z_error only for DEBUG (avoid problem with DLLs) - -Changes in 1.0.3 (2 Jul 96) -- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS - small and medium models; this makes the library incompatible with previous - versions for these models. (No effect in large model or on other systems.) -- return OK instead of BUF_ERROR if previous deflate call returned with - avail_out as zero but there is nothing to do -- added memcmp for non STDC compilers -- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) -- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) -- better check for 16-bit mode MSC (avoids problem with Symantec) - -Changes in 1.0.2 (23 May 96) -- added Windows DLL support -- added a function zlibVersion (for the DLL support) -- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) -- Bytef is define's instead of typedef'd only for Borland C -- avoid reading uninitialized memory in example.c -- mention in README that the zlib format is now RFC1950 -- updated Makefile.dj2 -- added algorithm.doc - -Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] -- fix array overlay in deflate.c which sometimes caused bad compressed data -- fix inflate bug with empty stored block -- fix MSDOS medium model which was broken in 0.99 -- fix deflateParams() which could generate bad compressed data -- Bytef is define'd instead of typedef'ed (work around Borland bug) -- added an INDEX file -- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), - Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) -- speed up adler32 for modern machines without auto-increment -- added -ansi for IRIX in configure -- static_init_done in trees.c is an int -- define unlink as delete for VMS -- fix configure for QNX -- add configure branch for SCO and HPUX -- avoid many warnings (unused variables, dead assignments, etc...) -- no fdopen for BeOS -- fix the Watcom fix for 32 bit mode (define FAR as empty) -- removed redefinition of Byte for MKWERKS -- work around an MWKERKS bug (incorrect merge of all .h files) - -Changes in 0.99 (27 Jan 96) -- allow preset dictionary shared between compressor and decompressor -- allow compression level 0 (no compression) -- add deflateParams in zlib.h: allow dynamic change of compression level - and compression strategy -- test large buffers and deflateParams in example.c -- add optional "configure" to build zlib as a shared library -- suppress Makefile.qnx, use configure instead -- fixed deflate for 64-bit systems (detected on Cray) -- fixed inflate_blocks for 64-bit systems (detected on Alpha) -- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) -- always return Z_BUF_ERROR when deflate() has nothing to do -- deflateInit and inflateInit are now macros to allow version checking -- prefix all global functions and types with z_ with -DZ_PREFIX -- make falloc completely reentrant (inftrees.c) -- fixed very unlikely race condition in ct_static_init -- free in reverse order of allocation to help memory manager -- use zlib-1.0/* instead of zlib/* inside the tar.gz -- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith - -Wconversion -Wstrict-prototypes -Wmissing-prototypes" -- allow gzread on concatenated .gz files -- deflateEnd now returns Z_DATA_ERROR if it was premature -- deflate is finally (?) fully deterministic (no matches beyond end of input) -- Document Z_SYNC_FLUSH -- add uninstall in Makefile -- Check for __cpluplus in zlib.h -- Better test in ct_align for partial flush -- avoid harmless warnings for Borland C++ -- initialize hash_head in deflate.c -- avoid warning on fdopen (gzio.c) for HP cc -Aa -- include stdlib.h for STDC compilers -- include errno.h for Cray -- ignore error if ranlib doesn't exist -- call ranlib twice for NeXTSTEP -- use exec_prefix instead of prefix for libz.a -- renamed ct_* as _tr_* to avoid conflict with applications -- clear z->msg in inflateInit2 before any error return -- initialize opaque in example.c, gzio.c, deflate.c and inflate.c -- fixed typo in zconf.h (_GNUC__ => __GNUC__) -- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) -- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) -- in fcalloc, normalize pointer if size > 65520 bytes -- don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... -- use Z_BINARY instead of BINARY -- document that gzclose after gzdopen will close the file -- allow "a" as mode in gzopen -- fix error checking in gzread -- allow skipping .gz extra-field on pipes -- added reference to Perl interface in README -- put the crc table in FAR data (I dislike more and more the medium model :) -- added get_crc_table -- added a dimension to all arrays (Borland C can't count) -- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast -- guard against multiple inclusion of *.h (for precompiled header on Mac) -- Watcom C pretends to be Microsoft C small model even in 32 bit mode -- don't use unsized arrays to avoid silly warnings by Visual C++: - warning C4746: 'inflate_mask' : unsized array treated as '__far' - (what's wrong with far data in far model?) -- define enum out of inflate_blocks_state to allow compilation with C++ - -Changes in 0.95 (16 Aug 95) -- fix MSDOS small and medium model (now easier to adapt to any compiler) -- inlined send_bits -- fix the final (:-) bug for deflate with flush (output was correct but - not completely flushed in rare occasions) -- default window size is same for compression and decompression - (it's now sufficient to set MAX_WBITS in zconf.h) -- voidp -> voidpf and voidnp -> voidp (for consistency with other - typedefs and because voidnp was not near in large model) - -Changes in 0.94 (13 Aug 95) -- support MSDOS medium model -- fix deflate with flush (could sometimes generate bad output) -- fix deflateReset (zlib header was incorrectly suppressed) -- added support for VMS -- allow a compression level in gzopen() -- gzflush now calls fflush -- For deflate with flush, flush even if no more input is provided -- rename libgz.a as libz.a -- avoid complex expression in infcodes.c triggering Turbo C bug -- work around a problem with gcc on Alpha (in INSERT_STRING) -- don't use inline functions (problem with some gcc versions) -- allow renaming of Byte, uInt, etc... with #define -- avoid warning about (unused) pointer before start of array in deflate.c -- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c -- avoid reserved word 'new' in trees.c - -Changes in 0.93 (25 June 95) -- temporarily disable inline functions -- make deflate deterministic -- give enough lookahead for PARTIAL_FLUSH -- Set binary mode for stdin/stdout in minigzip.c for OS/2 -- don't even use signed char in inflate (not portable enough) -- fix inflate memory leak for segmented architectures - -Changes in 0.92 (3 May 95) -- don't assume that char is signed (problem on SGI) -- Clear bit buffer when starting a stored block -- no memcpy on Pyramid -- suppressed inftest.c -- optimized fill_window, put longest_match inline for gcc -- optimized inflate on stored blocks -- untabify all sources to simplify patches - -Changes in 0.91 (2 May 95) -- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h -- Document the memory requirements in zconf.h -- added "make install" -- fix sync search logic in inflateSync -- deflate(Z_FULL_FLUSH) now works even if output buffer too short -- after inflateSync, don't scare people with just "lo world" -- added support for DJGPP - -Changes in 0.9 (1 May 95) -- don't assume that zalloc clears the allocated memory (the TurboC bug - was Mark's bug after all :) -- let again gzread copy uncompressed data unchanged (was working in 0.71) -- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented -- added a test of inflateSync in example.c -- moved MAX_WBITS to zconf.h because users might want to change that -- document explicitly that zalloc(64K) on MSDOS must return a normalized - pointer (zero offset) -- added Makefiles for Microsoft C, Turbo C, Borland C++ -- faster crc32() - -Changes in 0.8 (29 April 95) -- added fast inflate (inffast.c) -- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this - is incompatible with previous versions of zlib which returned Z_OK -- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) - (actually that was not a compiler bug, see 0.81 above) -- gzread no longer reads one extra byte in certain cases -- In gzio destroy(), don't reference a freed structure -- avoid many warnings for MSDOS -- avoid the ERROR symbol which is used by MS Windows - -Changes in 0.71 (14 April 95) -- Fixed more MSDOS compilation problems :( There is still a bug with - TurboC large model - -Changes in 0.7 (14 April 95) -- Added full inflate support -- Simplified the crc32() interface. The pre- and post-conditioning - (one's complement) is now done inside crc32(). WARNING: this is - incompatible with previous versions; see zlib.h for the new usage - -Changes in 0.61 (12 April 95) -- workaround for a bug in TurboC. example and minigzip now work on MSDOS - -Changes in 0.6 (11 April 95) -- added minigzip.c -- added gzdopen to reopen a file descriptor as gzFile -- added transparent reading of non-gziped files in gzread -- fixed bug in gzread (don't read crc as data) -- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose) -- don't allocate big arrays in the stack (for MSDOS) -- fix some MSDOS compilation problems - -Changes in 0.5: -- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but - not yet Z_FULL_FLUSH -- support decompression but only in a single step (forced Z_FINISH) -- added opaque object for zalloc and zfree -- added deflateReset and inflateReset -- added a variable zlib_version for consistency checking -- renamed the 'filter' parameter of deflateInit2 as 'strategy' - Added Z_FILTERED and Z_HUFFMAN_ONLY constants - -Changes in 0.4: -- avoid "zip" everywhere, use zlib instead of ziplib -- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - if compression method == 8 -- added adler32 and crc32 -- renamed deflateOptions as deflateInit2, call one or the other but not both -- added the method parameter for deflateInit2 -- added inflateInit2 -- simplified considerably deflateInit and inflateInit by not supporting - user-provided history buffer. This is supported only in deflateInit2 - and inflateInit2 - -Changes in 0.3: -- prefix all macro names with Z_ -- use Z_FINISH instead of deflateEnd to finish compression -- added Z_HUFFMAN_ONLY -- added gzerror() diff --git a/libraries/zlib/FAQ b/libraries/zlib/FAQ deleted file mode 100644 index 99b7cf92e4..0000000000 --- a/libraries/zlib/FAQ +++ /dev/null @@ -1,368 +0,0 @@ - - Frequently Asked Questions about zlib - - -If your question is not there, please check the zlib home page -http://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at http://zlib.net/zlib_faq.html - - - 1. Is zlib Y2K-compliant? - - Yes. zlib doesn't handle dates. - - 2. Where can I get a Windows DLL version? - - The zlib sources can be compiled without change to produce a DLL. See the - file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the - precompiled DLL are found in the zlib web site at http://zlib.net/ . - - 3. Where can I get a Visual Basic interface to zlib? - - See - * http://marknelson.us/1997/01/01/zlib-engine/ - * win32/DLL_FAQ.txt in the zlib distribution - - 4. compress() returns Z_BUF_ERROR. - - Make sure that before the call of compress(), the length of the compressed - buffer is equal to the available size of the compressed buffer and not - zero. For Visual Basic, check that this parameter is passed by reference - ("as any"), not by value ("as long"). - - 5. deflate() or inflate() returns Z_BUF_ERROR. - - Before making the call, make sure that avail_in and avail_out are not zero. - When setting the parameter flush equal to Z_FINISH, also make sure that - avail_out is big enough to allow processing all pending input. Note that a - Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be - made with more input or output space. A Z_BUF_ERROR may in fact be - unavoidable depending on how the functions are used, since it is not - possible to tell whether or not there is more output pending when - strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a - heavily annotated example. - - 6. Where's the zlib documentation (man pages, etc.)? - - It's in zlib.h . Examples of zlib usage are in the files test/example.c - and test/minigzip.c, with more in examples/ . - - 7. Why don't you use GNU autoconf or libtool or ...? - - Because we would like to keep zlib as a very small and simple package. - zlib is rather portable and doesn't need much configuration. - - 8. I found a bug in zlib. - - Most of the time, such problems are due to an incorrect usage of zlib. - Please try to reproduce the problem with a small program and send the - corresponding source to us at zlib@gzip.org . Do not send multi-megabyte - data files without prior agreement. - - 9. Why do I get "undefined reference to gzputc"? - - If "make test" produces something like - - example.o(.text+0x154): undefined reference to `gzputc' - - check that you don't have old files libz.* in /usr/lib, /usr/local/lib or - /usr/X11R6/lib. Remove any old versions, then do "make install". - -10. I need a Delphi interface to zlib. - - See the contrib/delphi directory in the zlib distribution. - -11. Can zlib handle .zip archives? - - Not by itself, no. See the directory contrib/minizip in the zlib - distribution. - -12. Can zlib handle .Z files? - - No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt - the code of uncompress on your own. - -13. How can I make a Unix shared library? - - By default a shared (and a static) library is built for Unix. So: - - make distclean - ./configure - make - -14. How do I install a shared zlib library on Unix? - - After the above, then: - - make install - - However, many flavors of Unix come with a shared zlib already installed. - Before going to the trouble of compiling a shared version of zlib and - trying to install it, you may want to check if it's already there! If you - can #include , it's there. The -lz option will probably link to - it. You can check the version at the top of zlib.h or with the - ZLIB_VERSION symbol defined in zlib.h . - -15. I have a question about OttoPDF. - - We are not the authors of OttoPDF. The real author is on the OttoPDF web - site: Joel Hainley, jhainley@myndkryme.com. - -16. Can zlib decode Flate data in an Adobe PDF file? - - Yes. See http://www.pdflib.com/ . To modify PDF forms, see - http://sourceforge.net/projects/acroformtool/ . - -17. Why am I getting this "register_frame_info not found" error on Solaris? - - After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib - generates an error such as: - - ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: - symbol __register_frame_info: referenced symbol not found - - The symbol __register_frame_info is not part of zlib, it is generated by - the C compiler (cc or gcc). You must recompile applications using zlib - which have this problem. This problem is specific to Solaris. See - http://www.sunfreeware.com for Solaris versions of zlib and applications - using zlib. - -18. Why does gzip give an error on a file I make with compress/deflate? - - The compress and deflate functions produce data in the zlib format, which - is different and incompatible with the gzip format. The gz* functions in - zlib on the other hand use the gzip format. Both the zlib and gzip formats - use the same compressed data format internally, but have different headers - and trailers around the compressed data. - -19. Ok, so why are there two different formats? - - The gzip format was designed to retain the directory information about a - single file, such as the name and last modification date. The zlib format - on the other hand was designed for in-memory and communication channel - applications, and has a much more compact header and trailer and uses a - faster integrity check than gzip. - -20. Well that's nice, but how do I make a gzip file in memory? - - You can request that deflate write the gzip format instead of the zlib - format using deflateInit2(). You can also request that inflate decode the - gzip format using inflateInit2(). Read zlib.h for more details. - -21. Is zlib thread-safe? - - Yes. However any library routines that zlib uses and any application- - provided memory allocation routines must also be thread-safe. zlib's gz* - functions use stdio library routines, and most of zlib's functions use the - library memory allocation routines by default. zlib's *Init* functions - allow for the application to provide custom memory allocation routines. - - Of course, you should only operate on any given zlib or gzip stream from a - single thread at a time. - -22. Can I use zlib in my commercial application? - - Yes. Please read the license in zlib.h. - -23. Is zlib under the GNU license? - - No. Please read the license in zlib.h. - -24. The license says that altered source versions must be "plainly marked". So - what exactly do I need to do to meet that requirement? - - You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In - particular, the final version number needs to be changed to "f", and an - identification string should be appended to ZLIB_VERSION. Version numbers - x.x.x.f are reserved for modifications to zlib by others than the zlib - maintainers. For example, if the version of the base zlib you are altering - is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and - ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also - update the version strings in deflate.c and inftrees.c. - - For altered source distributions, you should also note the origin and - nature of the changes in zlib.h, as well as in ChangeLog and README, along - with the dates of the alterations. The origin should include at least your - name (or your company's name), and an email address to contact for help or - issues with the library. - - Note that distributing a compiled zlib library along with zlib.h and - zconf.h is also a source distribution, and so you should change - ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes - in zlib.h as you would for a full source distribution. - -25. Will zlib work on a big-endian or little-endian architecture, and can I - exchange compressed data between them? - - Yes and yes. - -26. Will zlib work on a 64-bit machine? - - Yes. It has been tested on 64-bit machines, and has no dependence on any - data types being limited to 32-bits in length. If you have any - difficulties, please provide a complete problem report to zlib@gzip.org - -27. Will zlib decompress data from the PKWare Data Compression Library? - - No. The PKWare DCL uses a completely different compressed data format than - does PKZIP and zlib. However, you can look in zlib's contrib/blast - directory for a possible solution to your problem. - -28. Can I access data randomly in a compressed stream? - - No, not without some preparation. If when compressing you periodically use - Z_FULL_FLUSH, carefully write all the pending data at those points, and - keep an index of those locations, then you can start decompression at those - points. You have to be careful to not use Z_FULL_FLUSH too often, since it - can significantly degrade compression. Alternatively, you can scan a - deflate stream once to generate an index, and then use that index for - random access. See examples/zran.c . - -29. Does zlib work on MVS, OS/390, CICS, etc.? - - It has in the past, but we have not heard of any recent evidence. There - were working ports of zlib 1.1.4 to MVS, but those links no longer work. - If you know of recent, successful applications of zlib on these operating - systems, please let us know. Thanks. - -30. Is there some simpler, easier to read version of inflate I can look at to - understand the deflate format? - - First off, you should read RFC 1951. Second, yes. Look in zlib's - contrib/puff directory. - -31. Does zlib infringe on any patents? - - As far as we know, no. In fact, that was originally the whole point behind - zlib. Look here for some more information: - - http://www.gzip.org/#faq11 - -32. Can zlib work with greater than 4 GB of data? - - Yes. inflate() and deflate() will process any amount of data correctly. - Each call of inflate() or deflate() is limited to input and output chunks - of the maximum value that can be stored in the compiler's "unsigned int" - type, but there is no limit to the number of chunks. Note however that the - strm.total_in and strm_total_out counters may be limited to 4 GB. These - counters are provided as a convenience and are not used internally by - inflate() or deflate(). The application can easily set up its own counters - updated after each call of inflate() or deflate() to count beyond 4 GB. - compress() and uncompress() may be limited to 4 GB, since they operate in a - single call. gzseek() and gztell() may be limited to 4 GB depending on how - zlib is compiled. See the zlibCompileFlags() function in zlib.h. - - The word "may" appears several times above since there is a 4 GB limit only - if the compiler's "long" type is 32 bits. If the compiler's "long" type is - 64 bits, then the limit is 16 exabytes. - -33. Does zlib have any security vulnerabilities? - - The only one that we are aware of is potentially in gzprintf(). If zlib is - compiled to use sprintf() or vsprintf(), then there is no protection - against a buffer overflow of an 8K string space (or other value as set by - gzbuffer()), other than the caller of gzprintf() assuring that the output - will not exceed 8K. On the other hand, if zlib is compiled to use - snprintf() or vsnprintf(), which should normally be the case, then there is - no vulnerability. The ./configure script will display warnings if an - insecure variation of sprintf() will be used by gzprintf(). Also the - zlibCompileFlags() function will return information on what variant of - sprintf() is used by gzprintf(). - - If you don't have snprintf() or vsnprintf() and would like one, you can - find a portable implementation here: - - http://www.ijs.si/software/snprintf/ - - Note that you should be using the most recent version of zlib. Versions - 1.1.3 and before were subject to a double-free vulnerability, and versions - 1.2.1 and 1.2.2 were subject to an access exception when decompressing - invalid compressed data. - -34. Is there a Java version of zlib? - - Probably what you want is to use zlib in Java. zlib is already included - as part of the Java SDK in the java.util.zip package. If you really want - a version of zlib written in the Java language, look on the zlib home - page for links: http://zlib.net/ . - -35. I get this or that compiler or source-code scanner warning when I crank it - up to maximally-pedantic. Can't you guys write proper code? - - Many years ago, we gave up attempting to avoid warnings on every compiler - in the universe. It just got to be a waste of time, and some compilers - were downright silly as well as contradicted each other. So now, we simply - make sure that the code always works. - -36. Valgrind (or some similar memory access checker) says that deflate is - performing a conditional jump that depends on an uninitialized value. - Isn't that a bug? - - No. That is intentional for performance reasons, and the output of deflate - is not affected. This only started showing up recently since zlib 1.2.x - uses malloc() by default for allocations, whereas earlier versions used - calloc(), which zeros out the allocated memory. Even though the code was - correct, versions 1.2.4 and later was changed to not stimulate these - checkers. - -37. Will zlib read the (insert any ancient or arcane format here) compressed - data format? - - Probably not. Look in the comp.compression FAQ for pointers to various - formats and associated software. - -38. How can I encrypt/decrypt zip files with zlib? - - zlib doesn't support encryption. The original PKZIP encryption is very - weak and can be broken with freely available programs. To get strong - encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib - compression. For PKZIP compatible "encryption", look at - http://www.info-zip.org/ - -39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? - - "gzip" is the gzip format, and "deflate" is the zlib format. They should - probably have called the second one "zlib" instead to avoid confusion with - the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 - correctly points to the zlib specification in RFC 1950 for the "deflate" - transfer encoding, there have been reports of servers and browsers that - incorrectly produce or expect raw deflate data per the deflate - specification in RFC 1951, most notably Microsoft. So even though the - "deflate" transfer encoding using the zlib format would be the more - efficient approach (and in fact exactly what the zlib format was designed - for), using the "gzip" transfer encoding is probably more reliable due to - an unfortunate choice of name on the part of the HTTP 1.1 authors. - - Bottom line: use the gzip format for HTTP 1.1 encoding. - -40. Does zlib support the new "Deflate64" format introduced by PKWare? - - No. PKWare has apparently decided to keep that format proprietary, since - they have not documented it as they have previous compression formats. In - any case, the compression improvements are so modest compared to other more - modern approaches, that it's not worth the effort to implement. - -41. I'm having a problem with the zip functions in zlib, can you help? - - There are no zip functions in zlib. You are probably using minizip by - Giles Vollant, which is found in the contrib directory of zlib. It is not - part of zlib. In fact none of the stuff in contrib is part of zlib. The - files in there are not supported by the zlib authors. You need to contact - the authors of the respective contribution for help. - -42. The match.asm code in contrib is under the GNU General Public License. - Since it's part of zlib, doesn't that mean that all of zlib falls under the - GNU GPL? - - No. The files in contrib are not part of zlib. They were contributed by - other authors and are provided as a convenience to the user within the zlib - distribution. Each item in contrib has its own license. - -43. Is zlib subject to export controls? What is its ECCN? - - zlib is not subject to export controls, and so is classified as EAR99. - -44. Can you please sign these lengthy legal documents and fax them back to us - so that we can use your software in our product? - - No. Go away. Shoo. diff --git a/libraries/zlib/INDEX b/libraries/zlib/INDEX deleted file mode 100644 index 2ba0641204..0000000000 --- a/libraries/zlib/INDEX +++ /dev/null @@ -1,68 +0,0 @@ -CMakeLists.txt cmake build file -ChangeLog history of changes -FAQ Frequently Asked Questions about zlib -INDEX this file -Makefile dummy Makefile that tells you to ./configure -Makefile.in template for Unix Makefile -README guess what -configure configure script for Unix -make_vms.com makefile for VMS -test/example.c zlib usages examples for build testing -test/minigzip.c minimal gzip-like functionality for build testing -test/infcover.c inf*.c code coverage for build coverage testing -treebuild.xml XML description of source file dependencies -zconf.h.cmakein zconf.h template for cmake -zconf.h.in zconf.h template for configure -zlib.3 Man page for zlib -zlib.3.pdf Man page in PDF format -zlib.map Linux symbol information -zlib.pc.in Template for pkg-config descriptor -zlib.pc.cmakein zlib.pc template for cmake -zlib2ansi perl script to convert source files for C++ compilation - -amiga/ makefiles for Amiga SAS C -as400/ makefiles for AS/400 -doc/ documentation for formats and algorithms -msdos/ makefiles for MSDOS -nintendods/ makefile for Nintendo DS -old/ makefiles for various architectures and zlib documentation - files that have not yet been updated for zlib 1.2.x -qnx/ makefiles for QNX -watcom/ makefiles for OpenWatcom -win32/ makefiles for Windows - - zlib public header files (required for library use): -zconf.h -zlib.h - - private source files used to build the zlib library: -adler32.c -compress.c -crc32.c -crc32.h -deflate.c -deflate.h -gzclose.c -gzguts.h -gzlib.c -gzread.c -gzwrite.c -infback.c -inffast.c -inffast.h -inffixed.h -inflate.c -inflate.h -inftrees.c -inftrees.h -trees.c -trees.h -uncompr.c -zutil.c -zutil.h - - source files for sample programs -See examples/README.examples - - unsupported contributions by third parties -See contrib/README.contrib diff --git a/libraries/zlib/README b/libraries/zlib/README deleted file mode 100644 index ba34d1894a..0000000000 --- a/libraries/zlib/README +++ /dev/null @@ -1,118 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.13 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and -rfc1952 (gzip format). - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example -of the library is given in the file test/example.c which also tests that -the library is working correctly. Another example is given in the file -test/minigzip.c. The compression library itself is composed of all source -files in the root directory. - -To compile all files and run the test program, follow the instructions given at -the top of Makefile.in. In short "./configure; make test", and if that goes -well, "make install" should work for most flavors of Unix. For Windows, use -one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use -make_vms.com. - -Questions about zlib should be sent to , or to Gilles Vollant - for the Windows DLL version. The zlib home page is -http://zlib.net/ . Before reporting a problem, please check this site to -verify that you have the latest version of zlib; otherwise get the latest -version and check whether the problem still exists or not. - -PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. - -Mark Nelson wrote an article about zlib for the Jan. 1997 -issue of Dr. Dobb's Journal; a copy of the article is available at -http://marknelson.us/1997/01/01/zlib-engine/ . - -The changes made in version 1.2.13 are documented in the file ChangeLog. - -Unsupported third party contributions are provided in directory contrib/ . - -zlib is available in Java using the java.util.zip package, documented at -http://java.sun.com/developer/technicalArticles/Programming/compression/ . - -A Perl interface to zlib written by Paul Marquess is available -at CPAN (Comprehensive Perl Archive Network) sites, including -http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . - -A Python interface to zlib written by A.M. Kuchling is -available in Python 1.5 and later versions, see -http://docs.python.org/library/zlib.html . - -zlib is built into tcl: http://wiki.tcl.tk/4610 . - -An experimental package to read and write files in .zip format, written on top -of zlib by Gilles Vollant , is available in the -contrib/minizip directory of zlib. - - -Notes for some targets: - -- For Windows DLL versions, please see win32/DLL_FAQ.txt - -- For 64-bit Irix, deflate.c must be compiled without any optimization. With - -O, one libpng test fails. The test works in 32 bit mode (with the -n32 - compiler flag). The compiler bug has been reported to SGI. - -- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works - when compiled with cc. - -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is - necessary to get gzprintf working correctly. This is done by configure. - -- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with - other compilers. Use "make test" to check your compiler. - -- gzdopen is not supported on RISCOS or BEOS. - -- For PalmOs, see http://palmzlib.sourceforge.net/ - - -Acknowledgments: - - The deflate format used by zlib was defined by Phil Katz. The deflate and - zlib specifications were written by L. Peter Deutsch. Thanks to all the - people who reported problems and suggested various improvements in zlib; they - are too numerous to cite here. - -Copyright notice: - - (C) 1995-2022 Jean-loup Gailly and Mark Adler - - 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. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* receiving -lengthy legal documents to sign. The sources are provided for free but without -warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. We make all -contributions to and distributions of this project solely in our personal -capacity, and are not conveying any rights to any intellectual property of -any third parties. - -If you redistribute modified sources, we would appreciate that you include in -the file ChangeLog history information documenting your changes. Please read -the FAQ for more information on the distribution of modified source versions. diff --git a/libraries/zlib/adler32.c b/libraries/zlib/adler32.c deleted file mode 100644 index d0be4380a3..0000000000 --- a/libraries/zlib/adler32.c +++ /dev/null @@ -1,186 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" - -local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); - -#define BASE 65521U /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* use NO_DIVIDE if your processor does not do division in hardware -- - try it both ways to see which is faster */ -#ifdef NO_DIVIDE -/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 - (thank you to John Reiser for pointing this out) */ -# define CHOP(a) \ - do { \ - unsigned long tmp = a >> 16; \ - a &= 0xffffUL; \ - a += (tmp << 4) - tmp; \ - } while (0) -# define MOD28(a) \ - do { \ - CHOP(a); \ - if (a >= BASE) a -= BASE; \ - } while (0) -# define MOD(a) \ - do { \ - CHOP(a); \ - MOD28(a); \ - } while (0) -# define MOD63(a) \ - do { /* this assumes a is not negative */ \ - z_off64_t tmp = a >> 32; \ - a &= 0xffffffffL; \ - a += (tmp << 8) - (tmp << 5) + tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - if (a >= BASE) a -= BASE; \ - } while (0) -#else -# define MOD(a) a %= BASE -# define MOD28(a) a %= BASE -# define MOD63(a) a %= BASE -#endif - -/* ========================================================================= */ -uLong ZEXPORT adler32_z(adler, buf, len) - uLong adler; - const Bytef *buf; - z_size_t len; -{ - unsigned long sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD28(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ - return adler32_z(adler, buf, len); -} - -/* ========================================================================= */ -local uLong adler32_combine_(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off64_t len2; -{ - unsigned long sum1; - unsigned long sum2; - unsigned rem; - - /* for negative len, return invalid adler32 as a clue for debugging */ - if (len2 < 0) - return 0xffffffffUL; - - /* the derivation of this formula is left as an exercise for the reader */ - MOD63(len2); /* assumes len2 >= 0 */ - rem = (unsigned)len2; - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 >= BASE) sum1 -= BASE; - if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); - if (sum2 >= BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32_combine(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off_t len2; -{ - return adler32_combine_(adler1, adler2, len2); -} - -uLong ZEXPORT adler32_combine64(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off64_t len2; -{ - return adler32_combine_(adler1, adler2, len2); -} diff --git a/libraries/zlib/algorithm.txt b/libraries/zlib/algorithm.txt deleted file mode 100644 index c97f495020..0000000000 --- a/libraries/zlib/algorithm.txt +++ /dev/null @@ -1,209 +0,0 @@ -1. Compression algorithm (deflate) - -The deflation algorithm used by gzip (also zip and zlib) is a variation of -LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in -the input data. The second occurrence of a string is replaced by a -pointer to the previous string, in the form of a pair (distance, -length). Distances are limited to 32K bytes, and lengths are limited -to 258 bytes. When a string does not occur anywhere in the previous -32K bytes, it is emitted as a sequence of literal bytes. (In this -description, `string' must be taken as an arbitrary sequence of bytes, -and is not restricted to printable characters.) - -Literals or match lengths are compressed with one Huffman tree, and -match distances are compressed with another tree. The trees are stored -in a compact form at the start of each block. The blocks can have any -size (except that the compressed data for one block must fit in -available memory). A block is terminated when deflate() determines that -it would be useful to start another block with fresh trees. (This is -somewhat similar to the behavior of LZW-based _compress_.) - -Duplicated strings are found using a hash table. All input strings of -length 3 are inserted in the hash table. A hash index is computed for -the next 3 bytes. If the hash chain for this index is not empty, all -strings in the chain are compared with the current input string, and -the longest match is selected. - -The hash chains are searched starting with the most recent strings, to -favor small distances and thus take advantage of the Huffman encoding. -The hash chains are singly linked. There are no deletions from the -hash chains, the algorithm simply discards matches that are too old. - -To avoid a worst-case situation, very long hash chains are arbitrarily -truncated at a certain length, determined by a runtime option (level -parameter of deflateInit). So deflate() does not always find the longest -possible match but generally finds a match which is long enough. - -deflate() also defers the selection of matches with a lazy evaluation -mechanism. After a match of length N has been found, deflate() searches for -a longer match at the next input byte. If a longer match is found, the -previous match is truncated to a length of one (thus producing a single -literal byte) and the process of lazy evaluation begins again. Otherwise, -the original match is kept, and the next match search is attempted only N -steps later. - -The lazy match evaluation is also subject to a runtime parameter. If -the current match is long enough, deflate() reduces the search for a longer -match, thus speeding up the whole process. If compression ratio is more -important than speed, deflate() attempts a complete second search even if -the first match is already long enough. - -The lazy match evaluation is not performed for the fastest compression -modes (level parameter 1 to 3). For these fast modes, new strings -are inserted in the hash table only when no match was found, or -when the match is not too long. This degrades the compression ratio -but saves time since there are both fewer insertions and fewer searches. - - -2. Decompression algorithm (inflate) - -2.1 Introduction - -The key question is how to represent a Huffman code (or any prefix code) so -that you can decode fast. The most important characteristic is that shorter -codes are much more common than longer codes, so pay attention to decoding the -short codes fast, and let the long codes take longer to decode. - -inflate() sets up a first level table that covers some number of bits of -input less than the length of longest code. It gets that many bits from the -stream, and looks it up in the table. The table will tell if the next -code is that many bits or less and how many, and if it is, it will tell -the value, else it will point to the next level table for which inflate() -grabs more bits and tries to decode a longer code. - -How many bits to make the first lookup is a tradeoff between the time it -takes to decode and the time it takes to build the table. If building the -table took no time (and if you had infinite memory), then there would only -be a first level table to cover all the way to the longest code. However, -building the table ends up taking a lot longer for more bits since short -codes are replicated many times in such a table. What inflate() does is -simply to make the number of bits in the first table a variable, and then -to set that variable for the maximum speed. - -For inflate, which has 286 possible codes for the literal/length tree, the size -of the first table is nine bits. Also the distance trees have 30 possible -values, and the size of the first table is six bits. Note that for each of -those cases, the table ended up one bit longer than the ``average'' code -length, i.e. the code length of an approximately flat code which would be a -little more than eight bits for 286 symbols and a little less than five bits -for 30 symbols. - - -2.2 More details on the inflate table lookup - -Ok, you want to know what this cleverly obfuscated inflate tree actually -looks like. You are correct that it's not a Huffman tree. It is simply a -lookup table for the first, let's say, nine bits of a Huffman symbol. The -symbol could be as short as one bit or as long as 15 bits. If a particular -symbol is shorter than nine bits, then that symbol's translation is duplicated -in all those entries that start with that symbol's bits. For example, if the -symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a -symbol is nine bits long, it appears in the table once. - -If the symbol is longer than nine bits, then that entry in the table points -to another similar table for the remaining bits. Again, there are duplicated -entries as needed. The idea is that most of the time the symbol will be short -and there will only be one table look up. (That's whole idea behind data -compression in the first place.) For the less frequent long symbols, there -will be two lookups. If you had a compression method with really long -symbols, you could have as many levels of lookups as is efficient. For -inflate, two is enough. - -So a table entry either points to another table (in which case nine bits in -the above example are gobbled), or it contains the translation for the symbol -and the number of bits to gobble. Then you start again with the next -ungobbled bit. - -You may wonder: why not just have one lookup table for how ever many bits the -longest symbol is? The reason is that if you do that, you end up spending -more time filling in duplicate symbol entries than you do actually decoding. -At least for deflate's output that generates new trees every several 10's of -kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code -would take too long if you're only decoding several thousand symbols. At the -other extreme, you could make a new table for every bit in the code. In fact, -that's essentially a Huffman tree. But then you spend too much time -traversing the tree while decoding, even for short symbols. - -So the number of bits for the first lookup table is a trade of the time to -fill out the table vs. the time spent looking at the second level and above of -the table. - -Here is an example, scaled down: - -The code being decoded, with 10 symbols, from 1 to 6 bits long: - -A: 0 -B: 10 -C: 1100 -D: 11010 -E: 11011 -F: 11100 -G: 11101 -H: 11110 -I: 111110 -J: 111111 - -Let's make the first table three bits long (eight entries): - -000: A,1 -001: A,1 -010: A,1 -011: A,1 -100: B,2 -101: B,2 -110: -> table X (gobble 3 bits) -111: -> table Y (gobble 3 bits) - -Each entry is what the bits decode as and how many bits that is, i.e. how -many bits to gobble. Or the entry points to another table, with the number of -bits to gobble implicit in the size of the table. - -Table X is two bits long since the longest code starting with 110 is five bits -long: - -00: C,1 -01: C,1 -10: D,2 -11: E,2 - -Table Y is three bits long since the longest code starting with 111 is six -bits long: - -000: F,2 -001: F,2 -010: G,2 -011: G,2 -100: H,2 -101: H,2 -110: I,3 -111: J,3 - -So what we have here are three tables with a total of 20 entries that had to -be constructed. That's compared to 64 entries for a single table. Or -compared to 16 entries for a Huffman tree (six two entry tables and one four -entry table). Assuming that the code ideally represents the probability of -the symbols, it takes on the average 1.25 lookups per symbol. That's compared -to one lookup for the single table, or 1.66 lookups per symbol for the -Huffman tree. - -There, I think that gives you a picture of what's going on. For inflate, the -meaning of a particular symbol is often more than just a letter. It can be a -byte (a "literal"), or it can be either a length or a distance which -indicates a base value and a number of bits to fetch after the code that is -added to the base value. Or it might be the special end-of-block code. The -data structures created in inftrees.c try to encode all that information -compactly in the tables. - - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -References: - -[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data -Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, -pp. 337-343. - -``DEFLATE Compressed Data Format Specification'' available in -http://tools.ietf.org/html/rfc1951 diff --git a/libraries/zlib/compress.c b/libraries/zlib/compress.c deleted file mode 100644 index 2ad5326c14..0000000000 --- a/libraries/zlib/compress.c +++ /dev/null @@ -1,86 +0,0 @@ -/* compress.c -- compress a memory buffer - * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ -int ZEXPORT compress2(dest, destLen, source, sourceLen, level) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; - int level; -{ - z_stream stream; - int err; - const uInt max = (uInt)-1; - uLong left; - - left = *destLen; - *destLen = 0; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = deflateInit(&stream, level); - if (err != Z_OK) return err; - - stream.next_out = dest; - stream.avail_out = 0; - stream.next_in = (z_const Bytef *)source; - stream.avail_in = 0; - - do { - if (stream.avail_out == 0) { - stream.avail_out = left > (uLong)max ? max : (uInt)left; - left -= stream.avail_out; - } - if (stream.avail_in == 0) { - stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; - sourceLen -= stream.avail_in; - } - err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); - } while (err == Z_OK); - - *destLen = stream.total_out; - deflateEnd(&stream); - return err == Z_STREAM_END ? Z_OK : err; -} - -/* =========================================================================== - */ -int ZEXPORT compress(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} - -/* =========================================================================== - If the default memLevel or windowBits for deflateInit() is changed, then - this function needs to be updated. - */ -uLong ZEXPORT compressBound(sourceLen) - uLong sourceLen; -{ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13; -} diff --git a/libraries/zlib/crc32.c b/libraries/zlib/crc32.c deleted file mode 100644 index f8357b083f..0000000000 --- a/libraries/zlib/crc32.c +++ /dev/null @@ -1,1125 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2022 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * This interleaved implementation of a CRC makes use of pipelined multiple - * arithmetic-logic units, commonly found in modern CPU cores. It is due to - * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. - */ - -/* @(#) $Id$ */ - -/* - Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore - protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should - first call get_crc_table() to initialize the tables before allowing more than - one thread to use crc32(). - - MAKECRCH can be #defined to write out crc32.h. A main() routine is also - produced, so that this one source file can be compiled to an executable. - */ - -#ifdef MAKECRCH -# include -# ifndef DYNAMIC_CRC_TABLE -# define DYNAMIC_CRC_TABLE -# endif /* !DYNAMIC_CRC_TABLE */ -#endif /* MAKECRCH */ - -#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */ - - /* - A CRC of a message is computed on N braids of words in the message, where - each word consists of W bytes (4 or 8). If N is 3, for example, then three - running sparse CRCs are calculated respectively on each braid, at these - indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... - This is done starting at a word boundary, and continues until as many blocks - of N * W bytes as are available have been processed. The results are combined - into a single CRC at the end. For this code, N must be in the range 1..6 and - W must be 4 or 8. The upper limit on N can be increased if desired by adding - more #if blocks, extending the patterns apparent in the code. In addition, - crc32.h would need to be regenerated, if the maximum N value is increased. - - N and W are chosen empirically by benchmarking the execution time on a given - processor. The choices for N and W below were based on testing on Intel Kaby - Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 - Octeon II processors. The Intel, AMD, and ARM processors were all fastest - with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. - They were all tested with either gcc or clang, all using the -O3 optimization - level. Your mileage may vary. - */ - -/* Define N */ -#ifdef Z_TESTN -# define N Z_TESTN -#else -# define N 5 -#endif -#if N < 1 || N > 6 -# error N must be in 1..6 -#endif - -/* - z_crc_t must be at least 32 bits. z_word_t must be at least as long as - z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and - that bytes are eight bits. - */ - -/* - Define W and the associated z_word_t type. If W is not defined, then a - braided calculation is not used, and the associated tables and code are not - compiled. - */ -#ifdef Z_TESTW -# if Z_TESTW-1 != -1 -# define W Z_TESTW -# endif -#else -# ifdef MAKECRCH -# define W 8 /* required for MAKECRCH */ -# else -# if defined(__x86_64__) || defined(__aarch64__) -# define W 8 -# else -# define W 4 -# endif -# endif -#endif -#ifdef W -# if W == 8 && defined(Z_U8) - typedef Z_U8 z_word_t; -# elif defined(Z_U4) -# undef W -# define W 4 - typedef Z_U4 z_word_t; -# else -# undef W -# endif -#endif - -/* If available, use the ARM processor CRC32 instruction. */ -#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 -# define ARMCRC32 -#endif - -/* Local functions. */ -local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); -local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); - -#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) - local z_word_t byte_swap OF((z_word_t word)); -#endif - -#if defined(W) && !defined(ARMCRC32) - local z_crc_t crc_word OF((z_word_t data)); - local z_word_t crc_word_big OF((z_word_t data)); -#endif - -#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) -/* - Swap the bytes in a z_word_t to convert between little and big endian. Any - self-respecting compiler will optimize this to a single machine byte-swap - instruction, if one is available. This assumes that word_t is either 32 bits - or 64 bits. - */ -local z_word_t byte_swap(word) - z_word_t word; -{ -# if W == 8 - return - (word & 0xff00000000000000) >> 56 | - (word & 0xff000000000000) >> 40 | - (word & 0xff0000000000) >> 24 | - (word & 0xff00000000) >> 8 | - (word & 0xff000000) << 8 | - (word & 0xff0000) << 24 | - (word & 0xff00) << 40 | - (word & 0xff) << 56; -# else /* W == 4 */ - return - (word & 0xff000000) >> 24 | - (word & 0xff0000) >> 8 | - (word & 0xff00) << 8 | - (word & 0xff) << 24; -# endif -} -#endif - -/* CRC polynomial. */ -#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ - -#ifdef DYNAMIC_CRC_TABLE - -local z_crc_t FAR crc_table[256]; -local z_crc_t FAR x2n_table[32]; -local void make_crc_table OF((void)); -#ifdef W - local z_word_t FAR crc_big_table[256]; - local z_crc_t FAR crc_braid_table[W][256]; - local z_word_t FAR crc_braid_big_table[W][256]; - local void braid OF((z_crc_t [][256], z_word_t [][256], int, int)); -#endif -#ifdef MAKECRCH - local void write_table OF((FILE *, const z_crc_t FAR *, int)); - local void write_table32hi OF((FILE *, const z_word_t FAR *, int)); - local void write_table64 OF((FILE *, const z_word_t FAR *, int)); -#endif /* MAKECRCH */ - -/* - Define a once() function depending on the availability of atomics. If this is - compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in - multiple threads, and if atomics are not available, then get_crc_table() must - be called to initialize the tables and must return before any threads are - allowed to compute or combine CRCs. - */ - -/* Definition of once functionality. */ -typedef struct once_s once_t; -local void once OF((once_t *, void (*)(void))); - -/* Check for the availability of atomics. */ -#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ - !defined(__STDC_NO_ATOMICS__) - -#include - -/* Structure for once(), which must be initialized with ONCE_INIT. */ -struct once_s { - atomic_flag begun; - atomic_int done; -}; -#define ONCE_INIT {ATOMIC_FLAG_INIT, 0} - -/* - Run the provided init() function exactly once, even if multiple threads - invoke once() at the same time. The state must be a once_t initialized with - ONCE_INIT. - */ -local void once(state, init) - once_t *state; - void (*init)(void); -{ - if (!atomic_load(&state->done)) { - if (atomic_flag_test_and_set(&state->begun)) - while (!atomic_load(&state->done)) - ; - else { - init(); - atomic_store(&state->done, 1); - } - } -} - -#else /* no atomics */ - -/* Structure for once(), which must be initialized with ONCE_INIT. */ -struct once_s { - volatile int begun; - volatile int done; -}; -#define ONCE_INIT {0, 0} - -/* Test and set. Alas, not atomic, but tries to minimize the period of - vulnerability. */ -local int test_and_set OF((int volatile *)); -local int test_and_set(flag) - int volatile *flag; -{ - int was; - - was = *flag; - *flag = 1; - return was; -} - -/* Run the provided init() function once. This is not thread-safe. */ -local void once(state, init) - once_t *state; - void (*init)(void); -{ - if (!state->done) { - if (test_and_set(&state->begun)) - while (!state->done) - ; - else { - init(); - state->done = 1; - } - } -} - -#endif - -/* State for once(). */ -local once_t made = ONCE_INIT; - -/* - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x - (which is shifting right by one and adding x^32 mod p if the bit shifted out - is a one). We start with the highest power (least significant bit) of q and - repeat for all eight bits of q. - - The table is simply the CRC of all possible eight bit values. This is all the - information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. - */ - -local void make_crc_table() -{ - unsigned i, j, n; - z_crc_t p; - - /* initialize the CRC of bytes tables */ - for (i = 0; i < 256; i++) { - p = i; - for (j = 0; j < 8; j++) - p = p & 1 ? (p >> 1) ^ POLY : p >> 1; - crc_table[i] = p; -#ifdef W - crc_big_table[i] = byte_swap(p); -#endif - } - - /* initialize the x^2^n mod p(x) table */ - p = (z_crc_t)1 << 30; /* x^1 */ - x2n_table[0] = p; - for (n = 1; n < 32; n++) - x2n_table[n] = p = multmodp(p, p); - -#ifdef W - /* initialize the braiding tables -- needs x2n_table[] */ - braid(crc_braid_table, crc_braid_big_table, N, W); -#endif - -#ifdef MAKECRCH - { - /* - The crc32.h header file contains tables for both 32-bit and 64-bit - z_word_t's, and so requires a 64-bit type be available. In that case, - z_word_t must be defined to be 64-bits. This code then also generates - and writes out the tables for the case that z_word_t is 32 bits. - */ -#if !defined(W) || W != 8 -# error Need a 64-bit integer type in order to generate crc32.h. -#endif - FILE *out; - int k, n; - z_crc_t ltl[8][256]; - z_word_t big[8][256]; - - out = fopen("crc32.h", "w"); - if (out == NULL) return; - - /* write out little-endian CRC table to crc32.h */ - fprintf(out, - "/* crc32.h -- tables for rapid CRC calculation\n" - " * Generated automatically by crc32.c\n */\n" - "\n" - "local const z_crc_t FAR crc_table[] = {\n" - " "); - write_table(out, crc_table, 256); - fprintf(out, - "};\n"); - - /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ - fprintf(out, - "\n" - "#ifdef W\n" - "\n" - "#if W == 8\n" - "\n" - "local const z_word_t FAR crc_big_table[] = {\n" - " "); - write_table64(out, crc_big_table, 256); - fprintf(out, - "};\n"); - - /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ - fprintf(out, - "\n" - "#else /* W == 4 */\n" - "\n" - "local const z_word_t FAR crc_big_table[] = {\n" - " "); - write_table32hi(out, crc_big_table, 256); - fprintf(out, - "};\n" - "\n" - "#endif\n"); - - /* write out braid tables for each value of N */ - for (n = 1; n <= 6; n++) { - fprintf(out, - "\n" - "#if N == %d\n", n); - - /* compute braid tables for this N and 64-bit word_t */ - braid(ltl, big, n, 8); - - /* write out braid tables for 64-bit z_word_t to crc32.h */ - fprintf(out, - "\n" - "#if W == 8\n" - "\n" - "local const z_crc_t FAR crc_braid_table[][256] = {\n"); - for (k = 0; k < 8; k++) { - fprintf(out, " {"); - write_table(out, ltl[k], 256); - fprintf(out, "}%s", k < 7 ? ",\n" : ""); - } - fprintf(out, - "};\n" - "\n" - "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); - for (k = 0; k < 8; k++) { - fprintf(out, " {"); - write_table64(out, big[k], 256); - fprintf(out, "}%s", k < 7 ? ",\n" : ""); - } - fprintf(out, - "};\n"); - - /* compute braid tables for this N and 32-bit word_t */ - braid(ltl, big, n, 4); - - /* write out braid tables for 32-bit z_word_t to crc32.h */ - fprintf(out, - "\n" - "#else /* W == 4 */\n" - "\n" - "local const z_crc_t FAR crc_braid_table[][256] = {\n"); - for (k = 0; k < 4; k++) { - fprintf(out, " {"); - write_table(out, ltl[k], 256); - fprintf(out, "}%s", k < 3 ? ",\n" : ""); - } - fprintf(out, - "};\n" - "\n" - "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); - for (k = 0; k < 4; k++) { - fprintf(out, " {"); - write_table32hi(out, big[k], 256); - fprintf(out, "}%s", k < 3 ? ",\n" : ""); - } - fprintf(out, - "};\n" - "\n" - "#endif\n" - "\n" - "#endif\n"); - } - fprintf(out, - "\n" - "#endif\n"); - - /* write out zeros operator table to crc32.h */ - fprintf(out, - "\n" - "local const z_crc_t FAR x2n_table[] = {\n" - " "); - write_table(out, x2n_table, 32); - fprintf(out, - "};\n"); - fclose(out); - } -#endif /* MAKECRCH */ -} - -#ifdef MAKECRCH - -/* - Write the 32-bit values in table[0..k-1] to out, five per line in - hexadecimal separated by commas. - */ -local void write_table(out, table, k) - FILE *out; - const z_crc_t FAR *table; - int k; -{ - int n; - - for (n = 0; n < k; n++) - fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", - (unsigned long)(table[n]), - n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); -} - -/* - Write the high 32-bits of each value in table[0..k-1] to out, five per line - in hexadecimal separated by commas. - */ -local void write_table32hi(out, table, k) -FILE *out; -const z_word_t FAR *table; -int k; -{ - int n; - - for (n = 0; n < k; n++) - fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", - (unsigned long)(table[n] >> 32), - n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); -} - -/* - Write the 64-bit values in table[0..k-1] to out, three per line in - hexadecimal separated by commas. This assumes that if there is a 64-bit - type, then there is also a long long integer type, and it is at least 64 - bits. If not, then the type cast and format string can be adjusted - accordingly. - */ -local void write_table64(out, table, k) - FILE *out; - const z_word_t FAR *table; - int k; -{ - int n; - - for (n = 0; n < k; n++) - fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", - (unsigned long long)(table[n]), - n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); -} - -/* Actually do the deed. */ -int main() -{ - make_crc_table(); - return 0; -} - -#endif /* MAKECRCH */ - -#ifdef W -/* - Generate the little and big-endian braid tables for the given n and z_word_t - size w. Each array must have room for w blocks of 256 elements. - */ -local void braid(ltl, big, n, w) - z_crc_t ltl[][256]; - z_word_t big[][256]; - int n; - int w; -{ - int k; - z_crc_t i, p, q; - for (k = 0; k < w; k++) { - p = x2nmodp((n * w + 3 - k) << 3, 0); - ltl[k][0] = 0; - big[w - 1 - k][0] = 0; - for (i = 1; i < 256; i++) { - ltl[k][i] = q = multmodp(i << 24, p); - big[w - 1 - k][i] = byte_swap(q); - } - } -} -#endif - -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables for byte-wise and braided CRC-32 calculations, and a table of powers - * of x for combining CRC-32s, all made by make_crc_table(). - */ -#include "crc32.h" -#endif /* DYNAMIC_CRC_TABLE */ - -/* ======================================================================== - * Routines used for CRC calculation. Some are also required for the table - * generation above. - */ - -/* - Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, - reflected. For speed, this requires that a not be zero. - */ -local z_crc_t multmodp(a, b) - z_crc_t a; - z_crc_t b; -{ - z_crc_t m, p; - - m = (z_crc_t)1 << 31; - p = 0; - for (;;) { - if (a & m) { - p ^= b; - if ((a & (m - 1)) == 0) - break; - } - m >>= 1; - b = b & 1 ? (b >> 1) ^ POLY : b >> 1; - } - return p; -} - -/* - Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been - initialized. - */ -local z_crc_t x2nmodp(n, k) - z_off64_t n; - unsigned k; -{ - z_crc_t p; - - p = (z_crc_t)1 << 31; /* x^0 == 1 */ - while (n) { - if (n & 1) - p = multmodp(x2n_table[k & 31], p); - n >>= 1; - k++; - } - return p; -} - -/* ========================================================================= - * This function can be used by asm versions of crc32(), and to force the - * generation of the CRC tables in a threaded application. - */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - once(&made, make_crc_table); -#endif /* DYNAMIC_CRC_TABLE */ - return (const z_crc_t FAR *)crc_table; -} - -/* ========================================================================= - * Use ARM machine instructions if available. This will compute the CRC about - * ten times faster than the braided calculation. This code does not check for - * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will - * only be defined if the compilation specifies an ARM processor architecture - * that has the instructions. For example, compiling with -march=armv8.1-a or - * -march=armv8-a+crc, or -march=native if the compile machine has the crc32 - * instructions. - */ -#ifdef ARMCRC32 - -/* - Constants empirically determined to maximize speed. These values are from - measurements on a Cortex-A57. Your mileage may vary. - */ -#define Z_BATCH 3990 /* number of words in a batch */ -#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ -#define Z_BATCH_MIN 800 /* fewest words in a final batch */ - -unsigned long ZEXPORT crc32_z(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - z_crc_t val; - z_word_t crc1, crc2; - const z_word_t *word; - z_word_t val0, val1, val2; - z_size_t last, last2, i; - z_size_t num; - - /* Return initial CRC, if requested. */ - if (buf == Z_NULL) return 0; - -#ifdef DYNAMIC_CRC_TABLE - once(&made, make_crc_table); -#endif /* DYNAMIC_CRC_TABLE */ - - /* Pre-condition the CRC */ - crc = (~crc) & 0xffffffff; - - /* Compute the CRC up to a word boundary. */ - while (len && ((z_size_t)buf & 7) != 0) { - len--; - val = *buf++; - __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); - } - - /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */ - word = (z_word_t const *)buf; - num = len >> 3; - len &= 7; - - /* Do three interleaved CRCs to realize the throughput of one crc32x - instruction per cycle. Each CRC is calculated on Z_BATCH words. The - three CRCs are combined into a single CRC after each set of batches. */ - while (num >= 3 * Z_BATCH) { - crc1 = 0; - crc2 = 0; - for (i = 0; i < Z_BATCH; i++) { - val0 = word[i]; - val1 = word[i + Z_BATCH]; - val2 = word[i + 2 * Z_BATCH]; - __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); - __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); - __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); - } - word += 3 * Z_BATCH; - num -= 3 * Z_BATCH; - crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1; - crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2; - } - - /* Do one last smaller batch with the remaining words, if there are enough - to pay for the combination of CRCs. */ - last = num / 3; - if (last >= Z_BATCH_MIN) { - last2 = last << 1; - crc1 = 0; - crc2 = 0; - for (i = 0; i < last; i++) { - val0 = word[i]; - val1 = word[i + last]; - val2 = word[i + last2]; - __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); - __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); - __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); - } - word += 3 * last; - num -= 3 * last; - val = x2nmodp(last, 6); - crc = multmodp(val, crc) ^ crc1; - crc = multmodp(val, crc) ^ crc2; - } - - /* Compute the CRC on any remaining words. */ - for (i = 0; i < num; i++) { - val0 = word[i]; - __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); - } - word += num; - - /* Complete the CRC on any remaining bytes. */ - buf = (const unsigned char FAR *)word; - while (len) { - len--; - val = *buf++; - __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); - } - - /* Return the CRC, post-conditioned. */ - return crc ^ 0xffffffff; -} - -#else - -#ifdef W - -/* - Return the CRC of the W bytes in the word_t data, taking the - least-significant byte of the word as the first byte of data, without any pre - or post conditioning. This is used to combine the CRCs of each braid. - */ -local z_crc_t crc_word(data) - z_word_t data; -{ - int k; - for (k = 0; k < W; k++) - data = (data >> 8) ^ crc_table[data & 0xff]; - return (z_crc_t)data; -} - -local z_word_t crc_word_big(data) - z_word_t data; -{ - int k; - for (k = 0; k < W; k++) - data = (data << 8) ^ - crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; - return data; -} - -#endif - -/* ========================================================================= */ -unsigned long ZEXPORT crc32_z(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - /* Return initial CRC, if requested. */ - if (buf == Z_NULL) return 0; - -#ifdef DYNAMIC_CRC_TABLE - once(&made, make_crc_table); -#endif /* DYNAMIC_CRC_TABLE */ - - /* Pre-condition the CRC */ - crc = (~crc) & 0xffffffff; - -#ifdef W - - /* If provided enough bytes, do a braided CRC calculation. */ - if (len >= N * W + W - 1) { - z_size_t blks; - z_word_t const *words; - unsigned endian; - int k; - - /* Compute the CRC up to a z_word_t boundary. */ - while (len && ((z_size_t)buf & (W - 1)) != 0) { - len--; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - } - - /* Compute the CRC on as many N z_word_t blocks as are available. */ - blks = len / (N * W); - len -= blks * N * W; - words = (z_word_t const *)buf; - - /* Do endian check at execution time instead of compile time, since ARM - processors can change the endianess at execution time. If the - compiler knows what the endianess will be, it can optimize out the - check and the unused branch. */ - endian = 1; - if (*(unsigned char *)&endian) { - /* Little endian. */ - - z_crc_t crc0; - z_word_t word0; -#if N > 1 - z_crc_t crc1; - z_word_t word1; -#if N > 2 - z_crc_t crc2; - z_word_t word2; -#if N > 3 - z_crc_t crc3; - z_word_t word3; -#if N > 4 - z_crc_t crc4; - z_word_t word4; -#if N > 5 - z_crc_t crc5; - z_word_t word5; -#endif -#endif -#endif -#endif -#endif - - /* Initialize the CRC for each braid. */ - crc0 = crc; -#if N > 1 - crc1 = 0; -#if N > 2 - crc2 = 0; -#if N > 3 - crc3 = 0; -#if N > 4 - crc4 = 0; -#if N > 5 - crc5 = 0; -#endif -#endif -#endif -#endif -#endif - - /* - Process the first blks-1 blocks, computing the CRCs on each braid - independently. - */ - while (--blks) { - /* Load the word for each braid into registers. */ - word0 = crc0 ^ words[0]; -#if N > 1 - word1 = crc1 ^ words[1]; -#if N > 2 - word2 = crc2 ^ words[2]; -#if N > 3 - word3 = crc3 ^ words[3]; -#if N > 4 - word4 = crc4 ^ words[4]; -#if N > 5 - word5 = crc5 ^ words[5]; -#endif -#endif -#endif -#endif -#endif - words += N; - - /* Compute and update the CRC for each word. The loop should - get unrolled. */ - crc0 = crc_braid_table[0][word0 & 0xff]; -#if N > 1 - crc1 = crc_braid_table[0][word1 & 0xff]; -#if N > 2 - crc2 = crc_braid_table[0][word2 & 0xff]; -#if N > 3 - crc3 = crc_braid_table[0][word3 & 0xff]; -#if N > 4 - crc4 = crc_braid_table[0][word4 & 0xff]; -#if N > 5 - crc5 = crc_braid_table[0][word5 & 0xff]; -#endif -#endif -#endif -#endif -#endif - for (k = 1; k < W; k++) { - crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff]; -#if N > 1 - crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff]; -#if N > 2 - crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff]; -#if N > 3 - crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff]; -#if N > 4 - crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff]; -#if N > 5 - crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff]; -#endif -#endif -#endif -#endif -#endif - } - } - - /* - Process the last block, combining the CRCs of the N braids at the - same time. - */ - crc = crc_word(crc0 ^ words[0]); -#if N > 1 - crc = crc_word(crc1 ^ words[1] ^ crc); -#if N > 2 - crc = crc_word(crc2 ^ words[2] ^ crc); -#if N > 3 - crc = crc_word(crc3 ^ words[3] ^ crc); -#if N > 4 - crc = crc_word(crc4 ^ words[4] ^ crc); -#if N > 5 - crc = crc_word(crc5 ^ words[5] ^ crc); -#endif -#endif -#endif -#endif -#endif - words += N; - } - else { - /* Big endian. */ - - z_word_t crc0, word0, comb; -#if N > 1 - z_word_t crc1, word1; -#if N > 2 - z_word_t crc2, word2; -#if N > 3 - z_word_t crc3, word3; -#if N > 4 - z_word_t crc4, word4; -#if N > 5 - z_word_t crc5, word5; -#endif -#endif -#endif -#endif -#endif - - /* Initialize the CRC for each braid. */ - crc0 = byte_swap(crc); -#if N > 1 - crc1 = 0; -#if N > 2 - crc2 = 0; -#if N > 3 - crc3 = 0; -#if N > 4 - crc4 = 0; -#if N > 5 - crc5 = 0; -#endif -#endif -#endif -#endif -#endif - - /* - Process the first blks-1 blocks, computing the CRCs on each braid - independently. - */ - while (--blks) { - /* Load the word for each braid into registers. */ - word0 = crc0 ^ words[0]; -#if N > 1 - word1 = crc1 ^ words[1]; -#if N > 2 - word2 = crc2 ^ words[2]; -#if N > 3 - word3 = crc3 ^ words[3]; -#if N > 4 - word4 = crc4 ^ words[4]; -#if N > 5 - word5 = crc5 ^ words[5]; -#endif -#endif -#endif -#endif -#endif - words += N; - - /* Compute and update the CRC for each word. The loop should - get unrolled. */ - crc0 = crc_braid_big_table[0][word0 & 0xff]; -#if N > 1 - crc1 = crc_braid_big_table[0][word1 & 0xff]; -#if N > 2 - crc2 = crc_braid_big_table[0][word2 & 0xff]; -#if N > 3 - crc3 = crc_braid_big_table[0][word3 & 0xff]; -#if N > 4 - crc4 = crc_braid_big_table[0][word4 & 0xff]; -#if N > 5 - crc5 = crc_braid_big_table[0][word5 & 0xff]; -#endif -#endif -#endif -#endif -#endif - for (k = 1; k < W; k++) { - crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff]; -#if N > 1 - crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff]; -#if N > 2 - crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff]; -#if N > 3 - crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff]; -#if N > 4 - crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff]; -#if N > 5 - crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff]; -#endif -#endif -#endif -#endif -#endif - } - } - - /* - Process the last block, combining the CRCs of the N braids at the - same time. - */ - comb = crc_word_big(crc0 ^ words[0]); -#if N > 1 - comb = crc_word_big(crc1 ^ words[1] ^ comb); -#if N > 2 - comb = crc_word_big(crc2 ^ words[2] ^ comb); -#if N > 3 - comb = crc_word_big(crc3 ^ words[3] ^ comb); -#if N > 4 - comb = crc_word_big(crc4 ^ words[4] ^ comb); -#if N > 5 - comb = crc_word_big(crc5 ^ words[5] ^ comb); -#endif -#endif -#endif -#endif -#endif - words += N; - crc = byte_swap(comb); - } - - /* - Update the pointer to the remaining bytes to process. - */ - buf = (unsigned char const *)words; - } - -#endif /* W */ - - /* Complete the computation of the CRC on any remaining bytes. */ - while (len >= 8) { - len -= 8; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - } - while (len) { - len--; - crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; - } - - /* Return the CRC, post-conditioned. */ - return crc ^ 0xffffffff; -} - -#endif - -/* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - uInt len; -{ - return crc32_z(crc, buf, len); -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine64(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ -#ifdef DYNAMIC_CRC_TABLE - once(&made, make_crc_table); -#endif /* DYNAMIC_CRC_TABLE */ - return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff); -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off_t len2; -{ - return crc32_combine64(crc1, crc2, (z_off64_t)len2); -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine_gen64(len2) - z_off64_t len2; -{ -#ifdef DYNAMIC_CRC_TABLE - once(&made, make_crc_table); -#endif /* DYNAMIC_CRC_TABLE */ - return x2nmodp(len2, 3); -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine_gen(len2) - z_off_t len2; -{ - return crc32_combine_gen64((z_off64_t)len2); -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine_op(crc1, crc2, op) - uLong crc1; - uLong crc2; - uLong op; -{ - return multmodp(op, crc1) ^ (crc2 & 0xffffffff); -} diff --git a/libraries/zlib/crc32.h b/libraries/zlib/crc32.h deleted file mode 100644 index 137df68d61..0000000000 --- a/libraries/zlib/crc32.h +++ /dev/null @@ -1,9446 +0,0 @@ -/* crc32.h -- tables for rapid CRC calculation - * Generated automatically by crc32.c - */ - -local const z_crc_t FAR crc_table[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d}; - -#ifdef W - -#if W == 8 - -local const z_word_t FAR crc_big_table[] = { - 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, - 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, - 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, - 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, - 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, - 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, - 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, - 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, - 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, - 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, - 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, - 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, - 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, - 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, - 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, - 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, - 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, - 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, - 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, - 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, - 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, - 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, - 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, - 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, - 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, - 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, - 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, - 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, - 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, - 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, - 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, - 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, - 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, - 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, - 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, - 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, - 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, - 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, - 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, - 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, - 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, - 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, - 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, - 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, - 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, - 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, - 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, - 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, - 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, - 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, - 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, - 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, - 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, - 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, - 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, - 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, - 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, - 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, - 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, - 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, - 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, - 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, - 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, - 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, - 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, - 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, - 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, - 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, - 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, - 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, - 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, - 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, - 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, - 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, - 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, - 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, - 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, - 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, - 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, - 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, - 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, - 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, - 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, - 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, - 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, - 0x8def022d00000000}; - -#else /* W == 4 */ - -local const z_word_t FAR crc_big_table[] = { - 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, - 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, - 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, - 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, - 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, - 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, - 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, - 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, - 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, - 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, - 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, - 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, - 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, - 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, - 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, - 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, - 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, - 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, - 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, - 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, - 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, - 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, - 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, - 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, - 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, - 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, - 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, - 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, - 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, - 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, - 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, - 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, - 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, - 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, - 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, - 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, - 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, - 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, - 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, - 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, - 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, - 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, - 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, - 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, - 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, - 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, - 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, - 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, - 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, - 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, - 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, - 0x8def022d}; - -#endif - -#if N == 1 - -#if W == 8 - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, - 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, - 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, - 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, - 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, - 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, - 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, - 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, - 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, - 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, - 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, - 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, - 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, - 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, - 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, - 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, - 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, - 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, - 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, - 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, - 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, - 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, - 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, - 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, - 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, - 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, - 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, - 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, - 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, - 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, - 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, - 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, - 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, - 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, - 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, - 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, - 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, - 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, - 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, - 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, - 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, - 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, - 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, - 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, - 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, - 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, - 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, - 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, - 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, - 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, - 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, - 0x264b06e6}, - {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, - 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, - 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, - 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, - 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, - 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, - 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, - 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, - 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, - 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, - 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, - 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, - 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, - 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, - 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, - 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, - 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, - 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, - 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, - 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, - 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, - 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, - 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, - 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, - 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, - 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, - 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, - 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, - 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, - 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, - 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, - 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, - 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, - 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, - 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, - 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, - 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, - 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, - 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, - 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, - 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, - 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, - 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, - 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, - 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, - 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, - 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, - 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, - 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, - 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, - 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, - 0x92364a30}, - {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, - 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, - 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, - 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, - 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, - 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, - 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, - 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, - 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, - 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, - 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, - 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, - 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, - 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, - 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, - 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, - 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, - 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, - 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, - 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, - 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, - 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, - 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, - 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, - 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, - 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, - 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, - 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, - 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, - 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, - 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, - 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, - 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, - 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, - 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, - 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, - 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, - 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, - 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, - 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, - 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, - 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, - 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, - 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, - 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, - 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, - 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, - 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, - 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, - 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, - 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, - 0xe4c4abcc}, - {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, - 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, - 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, - 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, - 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, - 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, - 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, - 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, - 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, - 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, - 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, - 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, - 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, - 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, - 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, - 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, - 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, - 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, - 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, - 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, - 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, - 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, - 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, - 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, - 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, - 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, - 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, - 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, - 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, - 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, - 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, - 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, - 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, - 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, - 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, - 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, - 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, - 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, - 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, - 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, - 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, - 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, - 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, - 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, - 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, - 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, - 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, - 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, - 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, - 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, - 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, - 0xca64c78c}, - {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, - 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, - 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, - 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, - 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, - 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, - 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, - 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, - 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, - 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, - 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, - 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, - 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, - 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, - 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, - 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, - 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, - 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, - 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, - 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, - 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, - 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, - 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, - 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, - 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, - 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, - 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, - 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, - 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, - 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, - 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, - 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, - 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, - 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, - 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, - 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, - 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, - 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, - 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, - 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, - 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, - 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, - 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, - 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, - 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, - 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, - 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, - 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, - 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, - 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, - 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, - 0xde0506f1}, - {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, - 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, - 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, - 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, - 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, - 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, - 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, - 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, - 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, - 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, - 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, - 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, - 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, - 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, - 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, - 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, - 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, - 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, - 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, - 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, - 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, - 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, - 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, - 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, - 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, - 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, - 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, - 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, - 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, - 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, - 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, - 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, - 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, - 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, - 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, - 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, - 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, - 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, - 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, - 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, - 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, - 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, - 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, - 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, - 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, - 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, - 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, - 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, - 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, - 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, - 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, - 0xbe9834ed}, - {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, - 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, - 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, - 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, - 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, - 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, - 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, - 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, - 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, - 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, - 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, - 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, - 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, - 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, - 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, - 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, - 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, - 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, - 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, - 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, - 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, - 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, - 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, - 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, - 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, - 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, - 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, - 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, - 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, - 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, - 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, - 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, - 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, - 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, - 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, - 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, - 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, - 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, - 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, - 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, - 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, - 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, - 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, - 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, - 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, - 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, - 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, - 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, - 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, - 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, - 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, - 0x9324fd72}, - {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, - 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, - 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, - 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, - 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, - 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, - 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, - 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, - 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, - 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, - 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, - 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, - 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, - 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, - 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, - 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, - 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, - 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, - 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, - 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, - 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, - 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, - 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, - 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, - 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, - 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, - 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, - 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, - 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, - 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, - 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, - 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, - 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, - 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, - 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, - 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, - 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, - 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, - 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, - 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, - 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, - 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, - 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, - 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, - 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, - 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, - 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, - 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, - 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, - 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, - 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, - 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, - 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, - 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, - 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, - 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, - 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, - 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, - 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, - 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, - 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, - 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, - 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, - 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, - 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, - 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, - 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, - 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, - 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, - 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, - 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, - 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, - 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, - 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, - 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, - 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, - 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, - 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, - 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, - 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, - 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, - 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, - 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, - 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, - 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, - 0x8def022d00000000}, - {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000, - 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000, - 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000, - 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000, - 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000, - 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000, - 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000, - 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000, - 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000, - 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000, - 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000, - 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000, - 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000, - 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000, - 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000, - 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000, - 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000, - 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000, - 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000, - 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000, - 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000, - 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000, - 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000, - 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000, - 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000, - 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000, - 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000, - 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000, - 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000, - 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000, - 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000, - 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000, - 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000, - 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000, - 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000, - 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000, - 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000, - 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000, - 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000, - 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000, - 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000, - 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000, - 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000, - 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000, - 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000, - 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000, - 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000, - 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000, - 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000, - 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000, - 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000, - 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000, - 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000, - 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000, - 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000, - 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000, - 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000, - 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000, - 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000, - 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000, - 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000, - 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000, - 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000, - 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000, - 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000, - 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000, - 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000, - 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000, - 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000, - 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000, - 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000, - 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000, - 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000, - 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000, - 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000, - 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000, - 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000, - 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000, - 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000, - 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000, - 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000, - 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000, - 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000, - 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000, - 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000, - 0x72fd249300000000}, - {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000, - 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000, - 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000, - 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000, - 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000, - 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000, - 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000, - 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000, - 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000, - 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000, - 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000, - 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000, - 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000, - 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000, - 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000, - 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000, - 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000, - 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000, - 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000, - 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000, - 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000, - 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000, - 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000, - 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000, - 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000, - 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000, - 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000, - 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000, - 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000, - 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000, - 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000, - 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000, - 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000, - 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000, - 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000, - 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000, - 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000, - 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000, - 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000, - 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000, - 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000, - 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000, - 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000, - 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000, - 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000, - 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000, - 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000, - 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000, - 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000, - 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000, - 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000, - 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000, - 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000, - 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000, - 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000, - 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000, - 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000, - 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000, - 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000, - 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000, - 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000, - 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000, - 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000, - 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000, - 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000, - 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000, - 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000, - 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000, - 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000, - 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000, - 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000, - 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000, - 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000, - 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000, - 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000, - 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000, - 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000, - 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000, - 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000, - 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000, - 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000, - 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000, - 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000, - 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000, - 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000, - 0xed3498be00000000}, - {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000, - 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000, - 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000, - 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000, - 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000, - 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000, - 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000, - 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000, - 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000, - 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000, - 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000, - 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000, - 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000, - 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000, - 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000, - 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000, - 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000, - 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000, - 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000, - 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000, - 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000, - 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000, - 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000, - 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000, - 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000, - 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000, - 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000, - 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000, - 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000, - 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000, - 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000, - 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000, - 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000, - 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000, - 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000, - 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000, - 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000, - 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000, - 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000, - 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000, - 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000, - 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000, - 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000, - 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000, - 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000, - 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000, - 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000, - 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000, - 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000, - 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000, - 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000, - 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000, - 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000, - 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000, - 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000, - 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000, - 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000, - 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000, - 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000, - 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000, - 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000, - 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000, - 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000, - 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000, - 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000, - 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000, - 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000, - 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000, - 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000, - 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000, - 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000, - 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000, - 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000, - 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000, - 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000, - 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000, - 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000, - 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000, - 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000, - 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000, - 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000, - 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000, - 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000, - 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000, - 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000, - 0xf10605de00000000}, - {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000, - 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000, - 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000, - 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000, - 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000, - 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000, - 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000, - 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000, - 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000, - 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000, - 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000, - 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000, - 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000, - 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000, - 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000, - 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000, - 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000, - 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000, - 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000, - 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000, - 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000, - 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000, - 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000, - 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000, - 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000, - 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000, - 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000, - 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000, - 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000, - 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000, - 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000, - 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000, - 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000, - 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000, - 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000, - 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000, - 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000, - 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000, - 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000, - 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000, - 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000, - 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000, - 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000, - 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000, - 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000, - 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000, - 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000, - 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000, - 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000, - 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000, - 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000, - 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000, - 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000, - 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000, - 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000, - 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000, - 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000, - 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000, - 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000, - 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000, - 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000, - 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000, - 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000, - 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000, - 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000, - 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000, - 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000, - 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000, - 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000, - 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000, - 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000, - 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000, - 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000, - 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000, - 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000, - 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000, - 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000, - 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000, - 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000, - 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000, - 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000, - 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000, - 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000, - 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000, - 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000, - 0x8cc764ca00000000}, - {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000, - 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000, - 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000, - 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000, - 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000, - 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000, - 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000, - 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000, - 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000, - 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000, - 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000, - 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000, - 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000, - 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000, - 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000, - 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000, - 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000, - 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000, - 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000, - 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000, - 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000, - 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000, - 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000, - 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000, - 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000, - 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000, - 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000, - 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000, - 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000, - 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000, - 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000, - 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000, - 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000, - 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000, - 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000, - 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000, - 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000, - 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000, - 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000, - 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000, - 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000, - 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000, - 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000, - 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000, - 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000, - 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000, - 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000, - 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000, - 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000, - 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000, - 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000, - 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000, - 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000, - 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000, - 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000, - 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000, - 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000, - 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000, - 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000, - 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000, - 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000, - 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000, - 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000, - 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000, - 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000, - 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000, - 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000, - 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000, - 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000, - 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000, - 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000, - 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000, - 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000, - 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000, - 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000, - 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000, - 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000, - 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000, - 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000, - 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000, - 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000, - 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000, - 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000, - 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000, - 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000, - 0xccabc4e400000000}, - {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000, - 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000, - 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000, - 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000, - 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000, - 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000, - 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000, - 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000, - 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000, - 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000, - 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000, - 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000, - 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000, - 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000, - 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000, - 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000, - 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000, - 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000, - 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000, - 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000, - 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000, - 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000, - 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000, - 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000, - 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000, - 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000, - 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000, - 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000, - 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000, - 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000, - 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000, - 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000, - 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000, - 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000, - 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000, - 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000, - 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000, - 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000, - 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000, - 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000, - 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000, - 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000, - 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000, - 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000, - 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000, - 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000, - 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000, - 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000, - 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000, - 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000, - 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000, - 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000, - 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000, - 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000, - 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000, - 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000, - 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000, - 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000, - 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000, - 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000, - 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000, - 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000, - 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000, - 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000, - 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000, - 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000, - 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000, - 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000, - 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000, - 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000, - 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000, - 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000, - 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000, - 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000, - 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000, - 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000, - 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000, - 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000, - 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000, - 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000, - 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000, - 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000, - 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000, - 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000, - 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000, - 0x304a369200000000}, - {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000, - 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000, - 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000, - 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000, - 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000, - 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000, - 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000, - 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000, - 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000, - 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000, - 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000, - 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000, - 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000, - 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000, - 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000, - 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000, - 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000, - 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000, - 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000, - 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000, - 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000, - 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000, - 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000, - 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000, - 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000, - 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000, - 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000, - 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000, - 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000, - 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000, - 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000, - 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000, - 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000, - 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000, - 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000, - 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000, - 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000, - 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000, - 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000, - 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000, - 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000, - 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000, - 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000, - 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000, - 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000, - 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000, - 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000, - 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000, - 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000, - 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000, - 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000, - 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000, - 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000, - 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000, - 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000, - 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000, - 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000, - 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000, - 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000, - 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000, - 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000, - 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000, - 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000, - 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000, - 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000, - 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000, - 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000, - 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000, - 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000, - 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000, - 0x6171384400000000, 0xff71928800000000, 0xe678578200000000, - 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000, - 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000, - 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000, - 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000, - 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000, - 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000, - 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000, - 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000, - 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000, - 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000, - 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000, - 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000, - 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000, - 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000, - 0xe6064b2600000000}}; - -#else /* W == 4 */ - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, - 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, - 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, - 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, - 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, - 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, - 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, - 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, - 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, - 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, - 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, - 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, - 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, - 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, - 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, - 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, - 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, - 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, - 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, - 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, - 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, - 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, - 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, - 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, - 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, - 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, - 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, - 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, - 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, - 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, - 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, - 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, - 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, - 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, - 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, - 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, - 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, - 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, - 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, - 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, - 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, - 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, - 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, - 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, - 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, - 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, - 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, - 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, - 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, - 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, - 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, - 0xde0506f1}, - {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, - 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, - 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, - 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, - 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, - 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, - 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, - 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, - 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, - 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, - 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, - 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, - 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, - 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, - 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, - 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, - 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, - 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, - 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, - 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, - 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, - 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, - 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, - 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, - 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, - 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, - 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, - 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, - 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, - 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, - 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, - 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, - 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, - 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, - 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, - 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, - 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, - 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, - 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, - 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, - 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, - 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, - 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, - 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, - 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, - 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, - 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, - 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, - 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, - 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, - 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, - 0xbe9834ed}, - {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, - 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, - 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, - 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, - 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, - 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, - 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, - 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, - 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, - 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, - 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, - 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, - 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, - 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, - 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, - 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, - 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, - 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, - 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, - 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, - 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, - 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, - 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, - 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, - 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, - 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, - 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, - 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, - 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, - 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, - 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, - 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, - 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, - 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, - 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, - 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, - 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, - 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, - 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, - 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, - 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, - 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, - 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, - 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, - 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, - 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, - 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, - 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, - 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, - 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, - 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, - 0x9324fd72}, - {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, - 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, - 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, - 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, - 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, - 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, - 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, - 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, - 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, - 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, - 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, - 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, - 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, - 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, - 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, - 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, - 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, - 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, - 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, - 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, - 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, - 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, - 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, - 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, - 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, - 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, - 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, - 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, - 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, - 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, - 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, - 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, - 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, - 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, - 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, - 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, - 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, - 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, - 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, - 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, - 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, - 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, - 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, - 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, - 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, - 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, - 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, - 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, - 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, - 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, - 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, - 0x8def022d}, - {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, - 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, - 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, - 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, - 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, - 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, - 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, - 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, - 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, - 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, - 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, - 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, - 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, - 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, - 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, - 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, - 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, - 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, - 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, - 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, - 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, - 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, - 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, - 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, - 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, - 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, - 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, - 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, - 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, - 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, - 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, - 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, - 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, - 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, - 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, - 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, - 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, - 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, - 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, - 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, - 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, - 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, - 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, - 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, - 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, - 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, - 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, - 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, - 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, - 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, - 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, - 0x72fd2493}, - {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, - 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, - 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, - 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, - 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, - 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, - 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, - 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, - 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, - 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, - 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, - 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, - 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, - 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, - 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, - 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, - 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, - 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, - 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, - 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, - 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, - 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, - 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, - 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, - 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, - 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, - 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, - 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, - 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, - 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, - 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, - 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, - 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, - 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, - 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, - 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, - 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, - 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, - 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, - 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, - 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, - 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, - 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, - 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, - 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, - 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, - 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, - 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, - 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, - 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, - 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, - 0xed3498be}, - {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, - 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, - 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, - 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, - 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, - 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, - 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, - 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, - 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, - 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, - 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, - 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, - 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, - 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, - 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, - 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, - 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, - 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, - 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, - 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, - 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, - 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, - 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, - 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, - 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, - 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, - 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, - 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, - 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, - 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, - 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, - 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, - 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, - 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, - 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, - 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, - 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, - 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, - 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, - 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, - 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, - 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, - 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, - 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, - 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, - 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, - 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, - 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, - 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, - 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, - 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, - 0xf10605de}}; - -#endif - -#endif - -#if N == 2 - -#if W == 8 - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, - 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, - 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, - 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, - 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, - 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, - 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, - 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, - 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, - 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, - 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, - 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, - 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, - 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, - 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, - 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, - 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, - 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, - 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, - 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, - 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, - 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, - 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, - 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, - 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, - 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, - 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, - 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, - 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, - 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, - 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, - 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, - 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, - 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, - 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, - 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, - 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, - 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, - 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, - 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, - 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, - 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, - 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, - 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, - 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, - 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, - 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, - 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, - 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, - 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, - 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, - 0x0d7139d7}, - {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, - 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, - 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, - 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, - 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, - 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, - 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, - 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, - 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, - 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, - 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, - 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, - 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, - 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, - 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, - 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, - 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, - 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, - 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, - 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, - 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, - 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, - 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, - 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, - 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, - 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, - 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, - 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, - 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, - 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, - 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, - 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, - 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, - 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, - 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, - 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, - 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, - 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, - 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, - 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, - 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, - 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, - 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, - 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, - 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, - 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, - 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, - 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, - 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, - 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, - 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, - 0x1c53e98a}, - {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, - 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, - 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, - 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, - 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, - 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, - 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, - 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, - 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, - 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, - 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, - 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, - 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, - 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, - 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, - 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, - 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, - 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, - 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, - 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, - 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, - 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, - 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, - 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, - 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, - 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, - 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, - 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, - 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, - 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, - 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, - 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, - 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, - 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, - 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, - 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, - 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, - 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, - 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, - 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, - 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, - 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, - 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, - 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, - 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, - 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, - 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, - 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, - 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, - 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, - 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, - 0x3f88e851}, - {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, - 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, - 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, - 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, - 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, - 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, - 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, - 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, - 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, - 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, - 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, - 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, - 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, - 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, - 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, - 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, - 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, - 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, - 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, - 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, - 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, - 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, - 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, - 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, - 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, - 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, - 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, - 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, - 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, - 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, - 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, - 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, - 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, - 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, - 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, - 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, - 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, - 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, - 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, - 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, - 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, - 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, - 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, - 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, - 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, - 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, - 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, - 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, - 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, - 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, - 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, - 0x3dee8ca6}, - {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, - 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, - 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, - 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, - 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, - 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, - 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, - 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, - 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, - 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, - 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, - 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, - 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, - 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, - 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, - 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, - 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, - 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, - 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, - 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, - 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, - 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, - 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, - 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, - 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, - 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, - 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, - 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, - 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, - 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, - 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, - 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, - 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, - 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, - 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, - 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, - 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, - 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, - 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, - 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, - 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, - 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, - 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, - 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, - 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, - 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, - 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, - 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, - 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, - 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, - 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, - 0x36197165}, - {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, - 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, - 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, - 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, - 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, - 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, - 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, - 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, - 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, - 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, - 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, - 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, - 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, - 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, - 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, - 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, - 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, - 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, - 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, - 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, - 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, - 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, - 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, - 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, - 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, - 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, - 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, - 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, - 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, - 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, - 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, - 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, - 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, - 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, - 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, - 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, - 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, - 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, - 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, - 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, - 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, - 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, - 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, - 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, - 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, - 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, - 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, - 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, - 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, - 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, - 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, - 0x1a3b93aa}, - {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, - 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, - 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, - 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, - 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, - 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, - 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, - 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, - 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, - 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, - 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, - 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, - 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, - 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, - 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, - 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, - 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, - 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, - 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, - 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, - 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, - 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, - 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, - 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, - 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, - 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, - 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, - 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, - 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, - 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, - 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, - 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, - 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, - 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, - 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, - 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, - 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, - 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, - 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, - 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, - 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, - 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, - 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, - 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, - 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, - 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, - 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, - 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, - 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, - 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, - 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, - 0xe147d714}, - {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, - 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, - 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, - 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, - 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, - 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, - 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, - 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, - 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, - 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, - 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, - 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, - 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, - 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, - 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, - 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, - 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, - 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, - 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, - 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, - 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, - 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, - 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, - 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, - 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, - 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, - 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, - 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, - 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, - 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, - 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, - 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, - 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, - 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, - 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, - 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, - 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, - 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, - 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, - 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, - 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, - 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, - 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, - 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, - 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, - 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, - 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, - 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, - 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, - 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, - 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, - 0x494f0c4b}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000, - 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000, - 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000, - 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000, - 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000, - 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000, - 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000, - 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000, - 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000, - 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000, - 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000, - 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000, - 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000, - 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000, - 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000, - 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000, - 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000, - 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000, - 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000, - 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000, - 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000, - 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000, - 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000, - 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000, - 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000, - 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000, - 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000, - 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000, - 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000, - 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000, - 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000, - 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000, - 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000, - 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000, - 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000, - 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000, - 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000, - 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000, - 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000, - 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000, - 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000, - 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000, - 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000, - 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000, - 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000, - 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000, - 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000, - 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000, - 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000, - 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000, - 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000, - 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000, - 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000, - 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000, - 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000, - 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000, - 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000, - 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000, - 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000, - 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000, - 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000, - 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000, - 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000, - 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000, - 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000, - 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000, - 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000, - 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000, - 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000, - 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000, - 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000, - 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000, - 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000, - 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000, - 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000, - 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000, - 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000, - 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000, - 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000, - 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000, - 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000, - 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000, - 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000, - 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000, - 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000, - 0x4b0c4f4900000000}, - {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000, - 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000, - 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000, - 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000, - 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000, - 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000, - 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000, - 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000, - 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000, - 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000, - 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000, - 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000, - 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000, - 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000, - 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000, - 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000, - 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000, - 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000, - 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000, - 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000, - 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000, - 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000, - 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000, - 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000, - 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000, - 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000, - 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000, - 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000, - 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000, - 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000, - 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000, - 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000, - 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000, - 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000, - 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000, - 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000, - 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000, - 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000, - 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000, - 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000, - 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000, - 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000, - 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000, - 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000, - 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000, - 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000, - 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000, - 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000, - 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000, - 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000, - 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000, - 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000, - 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000, - 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000, - 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000, - 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000, - 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000, - 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000, - 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000, - 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000, - 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000, - 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000, - 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000, - 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000, - 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000, - 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000, - 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000, - 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000, - 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000, - 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000, - 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000, - 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000, - 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000, - 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000, - 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000, - 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000, - 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000, - 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000, - 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000, - 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000, - 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000, - 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000, - 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000, - 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000, - 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000, - 0x14d747e100000000}, - {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000, - 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000, - 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000, - 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000, - 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000, - 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000, - 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000, - 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000, - 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000, - 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000, - 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000, - 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000, - 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000, - 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000, - 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000, - 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000, - 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000, - 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000, - 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000, - 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000, - 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000, - 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000, - 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000, - 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000, - 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000, - 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000, - 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000, - 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000, - 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000, - 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000, - 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000, - 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000, - 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000, - 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000, - 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000, - 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000, - 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000, - 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000, - 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000, - 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000, - 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000, - 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000, - 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000, - 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000, - 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000, - 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000, - 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000, - 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000, - 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000, - 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000, - 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000, - 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000, - 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000, - 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000, - 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000, - 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000, - 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000, - 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000, - 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000, - 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000, - 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000, - 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000, - 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000, - 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000, - 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000, - 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000, - 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000, - 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000, - 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000, - 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000, - 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000, - 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000, - 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000, - 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000, - 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000, - 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000, - 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000, - 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000, - 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000, - 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000, - 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000, - 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000, - 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000, - 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000, - 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000, - 0xaa933b1a00000000}, - {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000, - 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000, - 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000, - 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000, - 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000, - 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000, - 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000, - 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000, - 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000, - 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000, - 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000, - 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000, - 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000, - 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000, - 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000, - 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000, - 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000, - 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000, - 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000, - 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000, - 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000, - 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000, - 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000, - 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000, - 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000, - 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000, - 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000, - 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000, - 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000, - 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000, - 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000, - 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000, - 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000, - 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000, - 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000, - 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000, - 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000, - 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000, - 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000, - 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000, - 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000, - 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000, - 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000, - 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000, - 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000, - 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000, - 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000, - 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000, - 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000, - 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000, - 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000, - 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000, - 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000, - 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000, - 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000, - 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000, - 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000, - 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000, - 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000, - 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000, - 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000, - 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000, - 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000, - 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000, - 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000, - 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000, - 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000, - 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000, - 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000, - 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000, - 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000, - 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000, - 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000, - 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000, - 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000, - 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000, - 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000, - 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000, - 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000, - 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000, - 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000, - 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000, - 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000, - 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000, - 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000, - 0x6571193600000000}, - {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000, - 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000, - 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000, - 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000, - 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000, - 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000, - 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000, - 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000, - 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000, - 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000, - 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000, - 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000, - 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000, - 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000, - 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000, - 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000, - 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000, - 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000, - 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000, - 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000, - 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000, - 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000, - 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000, - 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000, - 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000, - 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000, - 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000, - 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000, - 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000, - 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000, - 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000, - 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000, - 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000, - 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000, - 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000, - 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000, - 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000, - 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000, - 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000, - 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000, - 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000, - 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000, - 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000, - 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000, - 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000, - 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000, - 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000, - 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000, - 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000, - 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000, - 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000, - 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000, - 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000, - 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000, - 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000, - 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000, - 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000, - 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000, - 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000, - 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000, - 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000, - 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000, - 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000, - 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000, - 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000, - 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000, - 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000, - 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000, - 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000, - 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000, - 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000, - 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000, - 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000, - 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000, - 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000, - 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000, - 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000, - 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000, - 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000, - 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000, - 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000, - 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000, - 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000, - 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000, - 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000, - 0xa68cee3d00000000}, - {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000, - 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000, - 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000, - 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000, - 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000, - 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000, - 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000, - 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000, - 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000, - 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000, - 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000, - 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000, - 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000, - 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000, - 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000, - 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000, - 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000, - 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000, - 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000, - 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000, - 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000, - 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000, - 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000, - 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000, - 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000, - 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000, - 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000, - 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000, - 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000, - 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000, - 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000, - 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000, - 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000, - 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000, - 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000, - 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000, - 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000, - 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000, - 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000, - 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000, - 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000, - 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000, - 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000, - 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000, - 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000, - 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000, - 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000, - 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000, - 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000, - 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000, - 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000, - 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000, - 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000, - 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000, - 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000, - 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000, - 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000, - 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000, - 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000, - 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000, - 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000, - 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000, - 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000, - 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000, - 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000, - 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000, - 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000, - 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000, - 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000, - 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000, - 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000, - 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000, - 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000, - 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000, - 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000, - 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000, - 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000, - 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000, - 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000, - 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000, - 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000, - 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000, - 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000, - 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000, - 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000, - 0x51e8883f00000000}, - {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000, - 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000, - 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000, - 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000, - 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000, - 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000, - 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000, - 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000, - 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000, - 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000, - 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000, - 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000, - 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000, - 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000, - 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000, - 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000, - 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000, - 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000, - 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000, - 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000, - 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000, - 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000, - 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000, - 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000, - 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000, - 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000, - 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000, - 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000, - 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000, - 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000, - 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000, - 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000, - 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000, - 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000, - 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000, - 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000, - 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000, - 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000, - 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000, - 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000, - 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000, - 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000, - 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000, - 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000, - 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000, - 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000, - 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000, - 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000, - 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000, - 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000, - 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000, - 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000, - 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000, - 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000, - 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000, - 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000, - 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000, - 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000, - 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000, - 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000, - 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000, - 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000, - 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000, - 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000, - 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000, - 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000, - 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000, - 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000, - 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000, - 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000, - 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000, - 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000, - 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000, - 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000, - 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000, - 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000, - 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000, - 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000, - 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000, - 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000, - 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000, - 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000, - 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000, - 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000, - 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000, - 0x8ae9531c00000000}, - {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000, - 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000, - 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000, - 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000, - 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000, - 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000, - 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000, - 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000, - 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000, - 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000, - 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000, - 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000, - 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000, - 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000, - 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000, - 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000, - 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000, - 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000, - 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000, - 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000, - 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000, - 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000, - 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000, - 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000, - 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000, - 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000, - 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000, - 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000, - 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000, - 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000, - 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000, - 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000, - 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000, - 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000, - 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000, - 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000, - 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000, - 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000, - 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000, - 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000, - 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000, - 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000, - 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000, - 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000, - 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000, - 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000, - 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000, - 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000, - 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000, - 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000, - 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000, - 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000, - 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000, - 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000, - 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000, - 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000, - 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000, - 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000, - 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000, - 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000, - 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000, - 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000, - 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000, - 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000, - 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000, - 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000, - 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000, - 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000, - 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000, - 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000, - 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000, - 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000, - 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000, - 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000, - 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000, - 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000, - 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000, - 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000, - 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000, - 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000, - 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000, - 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000, - 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000, - 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000, - 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000, - 0xd739710d00000000}}; - -#else /* W == 4 */ - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, - 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, - 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, - 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, - 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, - 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, - 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, - 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, - 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, - 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, - 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, - 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, - 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, - 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, - 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, - 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, - 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, - 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, - 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, - 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, - 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, - 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, - 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, - 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, - 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, - 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, - 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, - 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, - 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, - 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, - 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, - 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, - 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, - 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, - 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, - 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, - 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, - 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, - 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, - 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, - 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, - 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, - 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, - 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, - 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, - 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, - 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, - 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, - 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, - 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, - 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, - 0x264b06e6}, - {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, - 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, - 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, - 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, - 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, - 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, - 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, - 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, - 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, - 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, - 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, - 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, - 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, - 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, - 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, - 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, - 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, - 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, - 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, - 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, - 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, - 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, - 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, - 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, - 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, - 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, - 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, - 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, - 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, - 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, - 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, - 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, - 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, - 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, - 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, - 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, - 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, - 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, - 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, - 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, - 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, - 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, - 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, - 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, - 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, - 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, - 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, - 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, - 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, - 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, - 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, - 0x92364a30}, - {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, - 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, - 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, - 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, - 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, - 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, - 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, - 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, - 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, - 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, - 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, - 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, - 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, - 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, - 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, - 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, - 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, - 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, - 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, - 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, - 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, - 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, - 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, - 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, - 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, - 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, - 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, - 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, - 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, - 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, - 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, - 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, - 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, - 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, - 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, - 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, - 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, - 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, - 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, - 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, - 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, - 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, - 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, - 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, - 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, - 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, - 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, - 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, - 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, - 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, - 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, - 0xe4c4abcc}, - {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, - 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, - 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, - 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, - 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, - 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, - 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, - 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, - 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, - 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, - 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, - 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, - 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, - 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, - 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, - 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, - 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, - 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, - 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, - 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, - 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, - 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, - 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, - 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, - 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, - 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, - 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, - 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, - 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, - 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, - 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, - 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, - 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, - 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, - 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, - 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, - 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, - 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, - 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, - 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, - 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, - 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, - 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, - 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, - 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, - 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, - 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, - 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, - 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, - 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, - 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, - 0xca64c78c}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5, - 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d, - 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf, - 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027, - 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050, - 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098, - 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb, - 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173, - 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104, - 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c, - 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e, - 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6, - 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358, - 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390, - 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312, - 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da, - 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd, - 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335, - 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387, - 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de, - 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9, - 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261, - 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283, - 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b, - 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c, - 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c, - 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e, - 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6, - 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1, - 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619, - 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b, - 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653, - 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785, - 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d, - 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf, - 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757, - 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720, - 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8, - 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593, - 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b, - 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c, - 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4, - 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506, - 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe, - 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428, - 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0, - 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462, - 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa, - 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd, - 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445, - 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7, - 0x8cc764ca}, - {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b, - 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27, - 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a, - 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285, - 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef, - 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf, - 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a, - 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a, - 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70, - 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf, - 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2, - 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e, - 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f, - 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f, - 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae, - 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe, - 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97, - 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b, - 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436, - 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e, - 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4, - 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4, - 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46, - 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716, - 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c, - 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5, - 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8, - 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774, - 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d, - 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d, - 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc, - 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec, - 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82, - 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e, - 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623, - 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c, - 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6, - 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6, - 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c, - 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c, - 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66, - 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9, - 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4, - 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978, - 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416, - 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946, - 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7, - 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7, - 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e, - 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32, - 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f, - 0xccabc4e4}, - {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4, - 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895, - 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50, - 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656, - 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154, - 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906, - 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258, - 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a, - 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08, - 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e, - 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb, - 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa, - 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44, - 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316, - 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0, - 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2, - 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7, - 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6, - 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73, - 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba, - 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8, - 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea, - 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b, - 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29, - 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b, - 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e, - 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb, - 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a, - 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef, - 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd, - 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b, - 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019, - 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3, - 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2, - 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417, - 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11, - 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13, - 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241, - 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b, - 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09, - 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b, - 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d, - 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8, - 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9, - 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003, - 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851, - 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7, - 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5, - 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190, - 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1, - 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134, - 0x304a3692}, - {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84, - 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f, - 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15, - 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2, - 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf, - 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7, - 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb, - 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3, - 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae, - 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749, - 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243, - 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8, - 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29, - 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61, - 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8, - 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0, - 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1, - 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a, - 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40, - 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e, - 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03, - 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b, - 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee, - 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6, - 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb, - 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f, - 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495, - 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e, - 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f, - 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067, - 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be, - 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6, - 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e, - 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5, - 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf, - 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958, - 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305, - 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d, - 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338, - 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370, - 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d, - 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca, - 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0, - 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b, - 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083, - 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb, - 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012, - 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a, - 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b, - 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0, - 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea, - 0xe6064b26}}; - -#endif - -#endif - -#if N == 3 - -#if W == 8 - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, - 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, - 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, - 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, - 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, - 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, - 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, - 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, - 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, - 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, - 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, - 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, - 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, - 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, - 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, - 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, - 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, - 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, - 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, - 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, - 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, - 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, - 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, - 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, - 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, - 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, - 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, - 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, - 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, - 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, - 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, - 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, - 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, - 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, - 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, - 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, - 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, - 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, - 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, - 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, - 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, - 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, - 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, - 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, - 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, - 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, - 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, - 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, - 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, - 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, - 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, - 0x09cd8551}, - {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, - 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, - 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, - 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, - 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, - 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, - 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, - 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, - 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, - 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, - 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, - 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, - 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, - 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, - 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, - 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, - 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, - 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, - 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, - 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, - 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, - 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, - 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, - 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, - 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, - 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, - 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, - 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, - 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, - 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, - 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, - 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, - 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, - 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, - 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, - 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, - 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, - 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, - 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, - 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, - 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, - 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, - 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, - 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, - 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, - 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, - 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, - 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, - 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, - 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, - 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, - 0x7bc97a0c}, - {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, - 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, - 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, - 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, - 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, - 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, - 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, - 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, - 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, - 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, - 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, - 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, - 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, - 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, - 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, - 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, - 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, - 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, - 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, - 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, - 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, - 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, - 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, - 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, - 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, - 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, - 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, - 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, - 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, - 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, - 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, - 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, - 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, - 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, - 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, - 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, - 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, - 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, - 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, - 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, - 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, - 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, - 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, - 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, - 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, - 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, - 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, - 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, - 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, - 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, - 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, - 0x7851a2ca}, - {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, - 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, - 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, - 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, - 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, - 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, - 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, - 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, - 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, - 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, - 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, - 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, - 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, - 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, - 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, - 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, - 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, - 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, - 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, - 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, - 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, - 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, - 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, - 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, - 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, - 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, - 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, - 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, - 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, - 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, - 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, - 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, - 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, - 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, - 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, - 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, - 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, - 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, - 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, - 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, - 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, - 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, - 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, - 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, - 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, - 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, - 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, - 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, - 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, - 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, - 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, - 0x566b6848}, - {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, - 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, - 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, - 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, - 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, - 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, - 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, - 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, - 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, - 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, - 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, - 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, - 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, - 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, - 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, - 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, - 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, - 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, - 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, - 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, - 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, - 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, - 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, - 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, - 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, - 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, - 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, - 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, - 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, - 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, - 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, - 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, - 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, - 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, - 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, - 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, - 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, - 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, - 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, - 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, - 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, - 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, - 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, - 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, - 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, - 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, - 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, - 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, - 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, - 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, - 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, - 0xd8ac6b35}, - {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, - 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, - 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, - 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, - 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, - 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, - 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, - 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, - 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, - 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, - 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, - 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, - 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, - 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, - 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, - 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, - 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, - 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, - 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, - 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, - 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, - 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, - 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, - 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, - 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, - 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, - 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, - 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, - 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, - 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, - 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, - 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, - 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, - 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, - 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, - 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, - 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, - 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, - 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, - 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, - 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, - 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, - 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, - 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, - 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, - 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, - 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, - 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, - 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, - 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, - 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, - 0xa140efa8}, - {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, - 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, - 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, - 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, - 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, - 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, - 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, - 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, - 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, - 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, - 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, - 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, - 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, - 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, - 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, - 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, - 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, - 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, - 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, - 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, - 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, - 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, - 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, - 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, - 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, - 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, - 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, - 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, - 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, - 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, - 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, - 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, - 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, - 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, - 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, - 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, - 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, - 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, - 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, - 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, - 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, - 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, - 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, - 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, - 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, - 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, - 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, - 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, - 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, - 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, - 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, - 0x917cd6a1}, - {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, - 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, - 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, - 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, - 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, - 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, - 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, - 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, - 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, - 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, - 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, - 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, - 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, - 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, - 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, - 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, - 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, - 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, - 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, - 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, - 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, - 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, - 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, - 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, - 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, - 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, - 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, - 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, - 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, - 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, - 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, - 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, - 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, - 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, - 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, - 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, - 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, - 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, - 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, - 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, - 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, - 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, - 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, - 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, - 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, - 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, - 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, - 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, - 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, - 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, - 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, - 0x18ba364e}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000, - 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000, - 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000, - 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000, - 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000, - 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000, - 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000, - 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000, - 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000, - 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000, - 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000, - 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000, - 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000, - 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000, - 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000, - 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000, - 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000, - 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000, - 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000, - 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000, - 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000, - 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000, - 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000, - 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000, - 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000, - 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000, - 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000, - 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000, - 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000, - 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000, - 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000, - 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000, - 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000, - 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000, - 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000, - 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000, - 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000, - 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000, - 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000, - 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000, - 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000, - 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000, - 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000, - 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000, - 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000, - 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000, - 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000, - 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000, - 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000, - 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000, - 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000, - 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000, - 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000, - 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000, - 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000, - 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000, - 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000, - 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000, - 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000, - 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000, - 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000, - 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000, - 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000, - 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000, - 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000, - 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000, - 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000, - 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000, - 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000, - 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000, - 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000, - 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000, - 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000, - 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000, - 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000, - 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000, - 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000, - 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000, - 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000, - 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000, - 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000, - 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000, - 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000, - 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000, - 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000, - 0x4e36ba1800000000}, - {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000, - 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000, - 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000, - 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000, - 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000, - 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000, - 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000, - 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000, - 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000, - 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000, - 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000, - 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000, - 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000, - 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000, - 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000, - 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000, - 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000, - 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000, - 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000, - 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000, - 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000, - 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000, - 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000, - 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000, - 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000, - 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000, - 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000, - 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000, - 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000, - 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000, - 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000, - 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000, - 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000, - 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000, - 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000, - 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000, - 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000, - 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000, - 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000, - 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000, - 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000, - 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000, - 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000, - 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000, - 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000, - 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000, - 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000, - 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000, - 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000, - 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000, - 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000, - 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000, - 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000, - 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000, - 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000, - 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000, - 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000, - 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000, - 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000, - 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000, - 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000, - 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000, - 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000, - 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000, - 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000, - 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000, - 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000, - 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000, - 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000, - 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000, - 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000, - 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000, - 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000, - 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000, - 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000, - 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000, - 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000, - 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000, - 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000, - 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000, - 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000, - 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000, - 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000, - 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000, - 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000, - 0xa1d67c9100000000}, - {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000, - 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000, - 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000, - 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000, - 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000, - 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000, - 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000, - 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000, - 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000, - 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000, - 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000, - 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000, - 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000, - 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000, - 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000, - 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000, - 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000, - 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000, - 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000, - 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000, - 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000, - 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000, - 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000, - 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000, - 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000, - 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000, - 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000, - 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000, - 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000, - 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000, - 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000, - 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000, - 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000, - 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000, - 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000, - 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000, - 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000, - 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000, - 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000, - 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000, - 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000, - 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000, - 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000, - 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000, - 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000, - 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000, - 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000, - 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000, - 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000, - 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000, - 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000, - 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000, - 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000, - 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000, - 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000, - 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000, - 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000, - 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000, - 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000, - 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000, - 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000, - 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000, - 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000, - 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000, - 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000, - 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000, - 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000, - 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000, - 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000, - 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000, - 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000, - 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000, - 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000, - 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000, - 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000, - 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000, - 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000, - 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000, - 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000, - 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000, - 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000, - 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000, - 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000, - 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000, - 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000, - 0xa8ef40a100000000}, - {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000, - 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000, - 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000, - 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000, - 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000, - 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000, - 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000, - 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000, - 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000, - 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000, - 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000, - 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000, - 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000, - 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000, - 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000, - 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000, - 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000, - 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000, - 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000, - 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000, - 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000, - 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000, - 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000, - 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000, - 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000, - 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000, - 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000, - 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000, - 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000, - 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000, - 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000, - 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000, - 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000, - 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000, - 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000, - 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000, - 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000, - 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000, - 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000, - 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000, - 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000, - 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000, - 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000, - 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000, - 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000, - 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000, - 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000, - 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000, - 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000, - 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000, - 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000, - 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000, - 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000, - 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000, - 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000, - 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000, - 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000, - 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000, - 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000, - 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000, - 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000, - 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000, - 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000, - 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000, - 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000, - 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000, - 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000, - 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000, - 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000, - 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000, - 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000, - 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000, - 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000, - 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000, - 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000, - 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000, - 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000, - 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000, - 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000, - 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000, - 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000, - 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000, - 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000, - 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000, - 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000, - 0x356bacd800000000}, - {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000, - 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000, - 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000, - 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000, - 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000, - 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000, - 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000, - 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000, - 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000, - 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000, - 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000, - 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000, - 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000, - 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000, - 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000, - 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000, - 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000, - 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000, - 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000, - 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000, - 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000, - 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000, - 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000, - 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000, - 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000, - 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000, - 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000, - 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000, - 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000, - 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000, - 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000, - 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000, - 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000, - 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000, - 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000, - 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000, - 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000, - 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000, - 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000, - 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000, - 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000, - 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000, - 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000, - 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000, - 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000, - 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000, - 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000, - 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000, - 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000, - 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000, - 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000, - 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000, - 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000, - 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000, - 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000, - 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000, - 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000, - 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000, - 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000, - 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000, - 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000, - 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000, - 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000, - 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000, - 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000, - 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000, - 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000, - 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000, - 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000, - 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000, - 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000, - 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000, - 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000, - 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000, - 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000, - 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000, - 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000, - 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000, - 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000, - 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000, - 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000, - 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000, - 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000, - 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000, - 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000, - 0x48686b5600000000}, - {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000, - 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000, - 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000, - 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000, - 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000, - 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000, - 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000, - 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000, - 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000, - 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000, - 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000, - 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000, - 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000, - 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000, - 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000, - 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000, - 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000, - 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000, - 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000, - 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000, - 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000, - 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000, - 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000, - 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000, - 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000, - 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000, - 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000, - 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000, - 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000, - 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000, - 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000, - 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000, - 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000, - 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000, - 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000, - 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000, - 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000, - 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000, - 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000, - 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000, - 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000, - 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000, - 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000, - 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000, - 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000, - 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000, - 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000, - 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000, - 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000, - 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000, - 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000, - 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000, - 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000, - 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000, - 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000, - 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000, - 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000, - 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000, - 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000, - 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000, - 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000, - 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000, - 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000, - 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000, - 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000, - 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000, - 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000, - 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000, - 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000, - 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000, - 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000, - 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000, - 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000, - 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000, - 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000, - 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000, - 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000, - 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000, - 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000, - 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000, - 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000, - 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000, - 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000, - 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000, - 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000, - 0xcaa2517800000000}, - {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000, - 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000, - 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000, - 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000, - 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000, - 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000, - 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000, - 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000, - 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000, - 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000, - 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000, - 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000, - 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000, - 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000, - 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000, - 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000, - 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000, - 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000, - 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000, - 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000, - 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000, - 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000, - 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000, - 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000, - 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000, - 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000, - 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000, - 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000, - 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000, - 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000, - 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000, - 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000, - 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000, - 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000, - 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000, - 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000, - 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000, - 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000, - 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000, - 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000, - 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000, - 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000, - 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000, - 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000, - 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000, - 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000, - 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000, - 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000, - 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000, - 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000, - 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000, - 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000, - 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000, - 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000, - 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000, - 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000, - 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000, - 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000, - 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000, - 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000, - 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000, - 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000, - 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000, - 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000, - 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000, - 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000, - 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000, - 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000, - 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000, - 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000, - 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000, - 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000, - 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000, - 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000, - 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000, - 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000, - 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000, - 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000, - 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000, - 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000, - 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000, - 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000, - 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000, - 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000, - 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000, - 0x0c7ac97b00000000}, - {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000, - 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000, - 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000, - 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000, - 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000, - 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000, - 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000, - 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000, - 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000, - 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000, - 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000, - 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000, - 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000, - 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000, - 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000, - 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000, - 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000, - 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000, - 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000, - 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000, - 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000, - 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000, - 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000, - 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000, - 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000, - 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000, - 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000, - 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000, - 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000, - 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000, - 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000, - 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000, - 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000, - 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000, - 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000, - 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000, - 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000, - 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000, - 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000, - 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000, - 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000, - 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000, - 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000, - 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000, - 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000, - 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000, - 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000, - 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000, - 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000, - 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000, - 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000, - 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000, - 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000, - 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000, - 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000, - 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000, - 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000, - 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000, - 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000, - 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000, - 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000, - 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000, - 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000, - 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000, - 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000, - 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000, - 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000, - 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000, - 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000, - 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000, - 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000, - 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000, - 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000, - 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000, - 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000, - 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000, - 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000, - 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000, - 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000, - 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000, - 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000, - 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000, - 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000, - 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000, - 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000, - 0x5185cd0900000000}}; - -#else /* W == 4 */ - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, - 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, - 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, - 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, - 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, - 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, - 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, - 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, - 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, - 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, - 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, - 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, - 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, - 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, - 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, - 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, - 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, - 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, - 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, - 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, - 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, - 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, - 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, - 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, - 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, - 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, - 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, - 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, - 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, - 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, - 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, - 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, - 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, - 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, - 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, - 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, - 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, - 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, - 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, - 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, - 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, - 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, - 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, - 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, - 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, - 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, - 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, - 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, - 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, - 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, - 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, - 0x36197165}, - {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, - 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, - 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, - 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, - 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, - 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, - 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, - 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, - 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, - 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, - 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, - 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, - 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, - 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, - 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, - 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, - 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, - 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, - 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, - 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, - 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, - 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, - 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, - 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, - 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, - 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, - 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, - 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, - 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, - 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, - 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, - 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, - 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, - 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, - 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, - 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, - 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, - 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, - 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, - 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, - 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, - 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, - 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, - 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, - 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, - 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, - 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, - 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, - 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, - 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, - 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, - 0x1a3b93aa}, - {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, - 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, - 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, - 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, - 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, - 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, - 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, - 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, - 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, - 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, - 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, - 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, - 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, - 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, - 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, - 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, - 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, - 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, - 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, - 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, - 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, - 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, - 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, - 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, - 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, - 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, - 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, - 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, - 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, - 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, - 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, - 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, - 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, - 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, - 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, - 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, - 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, - 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, - 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, - 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, - 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, - 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, - 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, - 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, - 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, - 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, - 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, - 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, - 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, - 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, - 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, - 0xe147d714}, - {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, - 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, - 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, - 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, - 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, - 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, - 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, - 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, - 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, - 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, - 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, - 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, - 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, - 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, - 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, - 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, - 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, - 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, - 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, - 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, - 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, - 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, - 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, - 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, - 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, - 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, - 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, - 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, - 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, - 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, - 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, - 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, - 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, - 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, - 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, - 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, - 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, - 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, - 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, - 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, - 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, - 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, - 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, - 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, - 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, - 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, - 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, - 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, - 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, - 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, - 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, - 0x494f0c4b}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d, - 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac, - 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8, - 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95, - 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817, - 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d, - 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac, - 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6, - 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564, - 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39, - 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d, - 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac, - 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de, - 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594, - 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b, - 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01, - 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f, - 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de, - 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba, - 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65, - 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7, - 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad, - 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de, - 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294, - 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716, - 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71, - 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15, - 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4, - 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca, - 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280, - 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f, - 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15, - 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9, - 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748, - 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c, - 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971, - 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3, - 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9, - 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196, - 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc, - 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e, - 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03, - 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67, - 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296, - 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a, - 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170, - 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af, - 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5, - 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb, - 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a, - 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e, - 0x4b0c4f49}, - {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09, - 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc, - 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e, - 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc, - 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934, - 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2, - 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b, - 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad, - 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155, - 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187, - 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65, - 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390, - 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e, - 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378, - 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889, - 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f, - 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0, - 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145, - 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7, - 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a, - 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2, - 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924, - 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2, - 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514, - 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec, - 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709, - 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb, - 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e, - 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1, - 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227, - 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6, - 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030, - 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0, - 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55, - 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7, - 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165, - 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d, - 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b, - 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c, - 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a, - 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362, - 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0, - 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52, - 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7, - 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237, - 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1, - 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020, - 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6, - 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719, - 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec, - 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e, - 0x14d747e1}, - {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0, - 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b, - 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652, - 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437, - 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514, - 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265, - 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de, - 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af, - 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c, - 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9, - 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0, - 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b, - 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6, - 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7, - 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734, - 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045, - 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8, - 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303, - 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a, - 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9, - 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea, - 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b, - 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6, - 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7, - 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4, - 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6, - 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f, - 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054, - 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9, - 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8, - 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b, - 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a, - 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441, - 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a, - 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3, - 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6, - 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5, - 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94, - 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9, - 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288, - 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab, - 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce, - 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7, - 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c, - 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527, - 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256, - 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5, - 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4, - 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39, - 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2, - 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db, - 0xaa933b1a}, - {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603, - 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d, - 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9, - 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b, - 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a, - 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792, - 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4, - 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c, - 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d, - 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f, - 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb, - 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65, - 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330, - 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8, - 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da, - 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742, - 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f, - 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1, - 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5, - 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f, - 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e, - 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6, - 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8, - 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250, - 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021, - 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb, - 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f, - 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511, - 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c, - 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4, - 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886, - 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e, - 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b, - 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5, - 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791, - 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003, - 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272, - 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea, - 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc, - 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24, - 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55, - 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7, - 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3, - 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d, - 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548, - 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0, - 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2, - 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a, - 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47, - 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9, - 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad, - 0x65711936}}; - -#endif - -#endif - -#if N == 4 - -#if W == 8 - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a, - 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe, - 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b, - 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656, - 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd, - 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d, - 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7, - 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47, - 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac, - 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691, - 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404, - 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0, - 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4, - 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424, - 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5, - 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65, - 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67, - 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3, - 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626, - 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9, - 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222, - 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2, - 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a, - 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a, - 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1, - 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2, - 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077, - 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3, - 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1, - 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621, - 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0, - 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60, - 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0, - 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64, - 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1, - 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc, - 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027, - 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7, - 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9, - 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79, - 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292, - 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af, - 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a, - 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee, - 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e, - 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe, - 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f, - 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff, - 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd, - 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29, - 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc, - 0xe3c45916}, - {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344, - 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59, - 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e, - 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463, - 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98, - 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d, - 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3, - 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656, - 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad, - 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0, - 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397, - 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a, - 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2, - 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357, - 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8, - 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d, - 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696, - 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b, - 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc, - 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0, - 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b, - 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be, - 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811, - 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384, - 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f, - 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955, - 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362, - 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f, - 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94, - 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701, - 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe, - 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b, - 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1, - 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc, - 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b, - 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986, - 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d, - 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8, - 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4, - 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371, - 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a, - 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87, - 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0, - 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad, - 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527, - 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2, - 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d, - 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998, - 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73, - 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e, - 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59, - 0xa7520488}, - {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20, - 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09, - 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431, - 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a, - 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203, - 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b, - 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14, - 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c, - 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25, - 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e, - 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36, - 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f, - 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649, - 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961, - 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58, - 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170, - 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b, - 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742, - 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a, - 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55, - 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c, - 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64, - 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f, - 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77, - 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e, - 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a, - 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2, - 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b, - 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090, - 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8, - 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881, - 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9, - 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6, - 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f, - 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7, - 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c, - 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695, - 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd, - 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb, - 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3, - 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa, - 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1, - 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9, - 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0, - 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df, - 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7, - 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace, - 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6, - 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd, - 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4, - 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec, - 0x3522e9e4}, - {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1, - 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86, - 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b, - 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669, - 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7, - 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352, - 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03, - 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6, - 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38, - 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a, - 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7, - 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80, - 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7, - 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522, - 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d, - 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8, - 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103, - 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54, - 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9, - 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0, - 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e, - 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb, - 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1, - 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624, - 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea, - 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a, - 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37, - 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360, - 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab, - 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e, - 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741, - 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4, - 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334, - 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63, - 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de, - 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c, - 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942, - 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7, - 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131, - 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4, - 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a, - 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758, - 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5, - 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2, - 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32, - 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7, - 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8, - 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d, - 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6, - 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1, - 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c, - 0x97411e28}, - {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474, - 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5, - 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6, - 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7, - 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938, - 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051, - 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a, - 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3, - 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c, - 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d, - 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e, - 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf, - 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740, - 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29, - 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592, - 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb, - 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4, - 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365, - 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036, - 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7, - 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08, - 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561, - 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a, - 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663, - 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac, - 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d, - 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce, - 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f, - 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50, - 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639, - 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82, - 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb, - 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954, - 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5, - 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86, - 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7, - 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418, - 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71, - 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa, - 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93, - 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c, - 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d, - 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e, - 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df, - 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60, - 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309, - 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2, - 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db, - 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4, - 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45, - 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16, - 0x93c7a00b}, - {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45, - 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb, - 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d, - 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696, - 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf, - 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb, - 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028, - 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c, - 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65, - 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be, - 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038, - 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6, - 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15, - 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11, - 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d, - 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19, - 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05, - 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b, - 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d, - 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c, - 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35, - 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31, - 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068, - 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c, - 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25, - 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a, - 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac, - 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22, - 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e, - 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a, - 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36, - 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32, - 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84, - 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a, - 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c, - 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057, - 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e, - 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a, - 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc, - 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8, - 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1, - 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a, - 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec, - 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62, - 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4, - 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0, - 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc, - 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8, - 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4, - 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a, - 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc, - 0xce5f968d}, - {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de, - 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b, - 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d, - 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680, - 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4, - 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d, - 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde, - 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97, - 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3, - 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e, - 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678, - 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d, - 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723, - 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a, - 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0, - 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9, - 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85, - 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770, - 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56, - 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a, - 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e, - 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67, - 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785, - 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc, - 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788, - 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90, - 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6, - 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843, - 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f, - 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336, - 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac, - 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5, - 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68, - 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d, - 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb, - 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36, - 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72, - 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b, - 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b, - 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402, - 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446, - 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb, - 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed, - 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418, - 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95, - 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc, - 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946, - 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f, - 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233, - 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6, - 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0, - 0x3e721277}, - {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb, - 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9, - 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11, - 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d, - 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9, - 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c, - 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881, - 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274, - 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790, - 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc, - 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514, - 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56, - 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9, - 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c, - 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13, - 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6, - 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c, - 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e, - 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386, - 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376, - 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692, - 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67, - 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416, - 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3, - 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07, - 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd, - 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15, - 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457, - 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd, - 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28, - 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337, - 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2, - 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594, - 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6, - 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e, - 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52, - 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6, - 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143, - 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17, - 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2, - 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306, - 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a, - 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182, - 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0, - 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496, - 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63, - 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c, - 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89, - 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903, - 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041, - 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9, - 0x1c65ace7}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000, - 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000, - 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000, - 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000, - 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000, - 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000, - 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000, - 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000, - 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000, - 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000, - 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000, - 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000, - 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000, - 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000, - 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000, - 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000, - 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000, - 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000, - 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000, - 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000, - 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000, - 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000, - 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000, - 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000, - 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000, - 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000, - 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000, - 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000, - 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000, - 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000, - 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000, - 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000, - 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000, - 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000, - 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000, - 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000, - 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000, - 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000, - 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000, - 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000, - 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000, - 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000, - 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000, - 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000, - 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000, - 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000, - 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000, - 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000, - 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000, - 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000, - 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000, - 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000, - 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000, - 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000, - 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000, - 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000, - 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000, - 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000, - 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000, - 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000, - 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000, - 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000, - 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000, - 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000, - 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000, - 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000, - 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000, - 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000, - 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000, - 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000, - 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000, - 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000, - 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000, - 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000, - 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000, - 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000, - 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000, - 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000, - 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000, - 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000, - 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000, - 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000, - 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000, - 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000, - 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000, - 0xe7ac651c00000000}, - {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000, - 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000, - 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000, - 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000, - 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000, - 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000, - 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000, - 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000, - 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000, - 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000, - 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000, - 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000, - 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000, - 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000, - 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000, - 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000, - 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000, - 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000, - 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000, - 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000, - 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000, - 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000, - 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000, - 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000, - 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000, - 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000, - 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000, - 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000, - 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000, - 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000, - 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000, - 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000, - 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000, - 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000, - 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000, - 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000, - 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000, - 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000, - 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000, - 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000, - 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000, - 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000, - 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000, - 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000, - 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000, - 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000, - 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000, - 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000, - 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000, - 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000, - 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000, - 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000, - 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000, - 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000, - 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000, - 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000, - 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000, - 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000, - 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000, - 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000, - 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000, - 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000, - 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000, - 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000, - 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000, - 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000, - 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000, - 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000, - 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000, - 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000, - 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000, - 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000, - 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000, - 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000, - 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000, - 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000, - 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000, - 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000, - 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000, - 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000, - 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000, - 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000, - 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000, - 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000, - 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000, - 0x7712723e00000000}, - {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000, - 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000, - 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000, - 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000, - 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000, - 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000, - 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000, - 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000, - 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000, - 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000, - 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000, - 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000, - 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000, - 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000, - 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000, - 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000, - 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000, - 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000, - 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000, - 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000, - 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000, - 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000, - 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000, - 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000, - 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000, - 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000, - 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000, - 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000, - 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000, - 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000, - 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000, - 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000, - 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000, - 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000, - 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000, - 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000, - 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000, - 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000, - 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000, - 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000, - 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000, - 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000, - 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000, - 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000, - 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000, - 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000, - 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000, - 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000, - 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000, - 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000, - 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000, - 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000, - 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000, - 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000, - 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000, - 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000, - 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000, - 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000, - 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000, - 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000, - 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000, - 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000, - 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000, - 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000, - 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000, - 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000, - 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000, - 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000, - 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000, - 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000, - 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000, - 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000, - 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000, - 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000, - 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000, - 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000, - 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000, - 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000, - 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000, - 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000, - 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000, - 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000, - 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000, - 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000, - 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000, - 0x8d965fce00000000}, - {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000, - 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000, - 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000, - 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000, - 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000, - 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000, - 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000, - 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000, - 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000, - 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000, - 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000, - 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000, - 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000, - 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000, - 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000, - 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000, - 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000, - 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000, - 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000, - 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000, - 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000, - 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000, - 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000, - 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000, - 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000, - 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000, - 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000, - 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000, - 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000, - 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000, - 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000, - 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000, - 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000, - 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000, - 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000, - 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000, - 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000, - 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000, - 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000, - 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000, - 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000, - 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000, - 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000, - 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000, - 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000, - 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000, - 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000, - 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000, - 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000, - 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000, - 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000, - 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000, - 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000, - 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000, - 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000, - 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000, - 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000, - 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000, - 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000, - 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000, - 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000, - 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000, - 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000, - 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000, - 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000, - 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000, - 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000, - 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000, - 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000, - 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000, - 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000, - 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000, - 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000, - 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000, - 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000, - 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000, - 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000, - 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000, - 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000, - 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000, - 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000, - 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000, - 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000, - 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000, - 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000, - 0x0ba0c79300000000}, - {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000, - 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000, - 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000, - 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000, - 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000, - 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000, - 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000, - 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000, - 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000, - 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000, - 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000, - 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000, - 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000, - 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000, - 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000, - 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000, - 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000, - 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000, - 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000, - 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000, - 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000, - 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000, - 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000, - 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000, - 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000, - 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000, - 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000, - 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000, - 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000, - 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000, - 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000, - 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000, - 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000, - 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000, - 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000, - 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000, - 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000, - 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000, - 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000, - 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000, - 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000, - 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000, - 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000, - 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000, - 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000, - 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000, - 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000, - 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000, - 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000, - 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000, - 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000, - 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000, - 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000, - 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000, - 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000, - 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000, - 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000, - 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000, - 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000, - 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000, - 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000, - 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000, - 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000, - 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000, - 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000, - 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000, - 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000, - 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000, - 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000, - 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000, - 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000, - 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000, - 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000, - 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000, - 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000, - 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000, - 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000, - 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000, - 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000, - 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000, - 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000, - 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000, - 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000, - 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000, - 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000, - 0x281e419700000000}, - {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000, - 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000, - 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000, - 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000, - 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000, - 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000, - 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000, - 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000, - 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000, - 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000, - 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000, - 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000, - 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000, - 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000, - 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000, - 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000, - 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000, - 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000, - 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000, - 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000, - 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000, - 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000, - 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000, - 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000, - 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000, - 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000, - 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000, - 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000, - 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000, - 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000, - 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000, - 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000, - 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000, - 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000, - 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000, - 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000, - 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000, - 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000, - 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000, - 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000, - 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000, - 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000, - 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000, - 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000, - 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000, - 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000, - 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000, - 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000, - 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000, - 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000, - 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000, - 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000, - 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000, - 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000, - 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000, - 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000, - 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000, - 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000, - 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000, - 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000, - 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000, - 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000, - 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000, - 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000, - 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000, - 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000, - 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000, - 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000, - 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000, - 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000, - 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000, - 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000, - 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000, - 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000, - 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000, - 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000, - 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000, - 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000, - 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000, - 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000, - 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000, - 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000, - 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000, - 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000, - 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000, - 0xe4e9223500000000}, - {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000, - 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000, - 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000, - 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000, - 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000, - 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000, - 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000, - 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000, - 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000, - 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000, - 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000, - 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000, - 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000, - 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000, - 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000, - 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000, - 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000, - 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000, - 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000, - 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000, - 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000, - 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000, - 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000, - 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000, - 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000, - 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000, - 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000, - 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000, - 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000, - 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000, - 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000, - 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000, - 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000, - 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000, - 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000, - 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000, - 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000, - 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000, - 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000, - 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000, - 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000, - 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000, - 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000, - 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000, - 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000, - 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000, - 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000, - 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000, - 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000, - 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000, - 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000, - 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000, - 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000, - 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000, - 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000, - 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000, - 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000, - 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000, - 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000, - 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000, - 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000, - 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000, - 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000, - 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000, - 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000, - 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000, - 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000, - 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000, - 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000, - 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000, - 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000, - 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000, - 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000, - 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000, - 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000, - 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000, - 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000, - 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000, - 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000, - 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000, - 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000, - 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000, - 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000, - 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000, - 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000, - 0x880452a700000000}, - {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000, - 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000, - 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000, - 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000, - 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000, - 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000, - 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000, - 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000, - 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000, - 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000, - 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000, - 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000, - 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000, - 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000, - 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000, - 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000, - 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000, - 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000, - 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000, - 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000, - 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000, - 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000, - 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000, - 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000, - 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000, - 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000, - 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000, - 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000, - 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000, - 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000, - 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000, - 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000, - 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000, - 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000, - 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000, - 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000, - 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000, - 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000, - 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000, - 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000, - 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000, - 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000, - 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000, - 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000, - 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000, - 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000, - 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000, - 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000, - 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000, - 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000, - 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000, - 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000, - 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000, - 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000, - 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000, - 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000, - 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000, - 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000, - 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000, - 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000, - 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000, - 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000, - 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000, - 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000, - 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000, - 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000, - 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000, - 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000, - 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000, - 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000, - 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000, - 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000, - 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000, - 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000, - 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000, - 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000, - 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000, - 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000, - 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000, - 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000, - 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000, - 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000, - 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000, - 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000, - 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000, - 0x1659c4e300000000}}; - -#else /* W == 4 */ - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, - 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, - 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, - 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, - 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, - 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, - 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, - 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, - 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, - 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, - 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, - 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, - 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, - 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, - 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, - 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, - 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, - 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, - 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, - 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, - 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, - 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, - 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, - 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, - 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, - 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, - 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, - 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, - 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, - 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, - 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, - 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, - 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, - 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, - 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, - 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, - 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, - 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, - 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, - 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, - 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, - 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, - 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, - 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, - 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, - 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, - 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, - 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, - 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, - 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, - 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, - 0x0d7139d7}, - {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, - 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, - 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, - 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, - 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, - 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, - 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, - 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, - 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, - 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, - 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, - 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, - 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, - 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, - 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, - 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, - 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, - 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, - 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, - 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, - 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, - 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, - 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, - 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, - 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, - 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, - 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, - 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, - 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, - 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, - 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, - 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, - 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, - 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, - 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, - 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, - 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, - 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, - 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, - 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, - 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, - 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, - 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, - 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, - 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, - 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, - 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, - 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, - 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, - 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, - 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, - 0x1c53e98a}, - {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, - 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, - 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, - 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, - 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, - 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, - 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, - 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, - 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, - 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, - 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, - 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, - 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, - 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, - 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, - 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, - 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, - 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, - 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, - 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, - 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, - 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, - 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, - 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, - 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, - 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, - 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, - 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, - 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, - 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, - 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, - 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, - 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, - 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, - 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, - 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, - 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, - 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, - 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, - 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, - 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, - 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, - 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, - 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, - 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, - 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, - 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, - 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, - 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, - 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, - 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, - 0x3f88e851}, - {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, - 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, - 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, - 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, - 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, - 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, - 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, - 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, - 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, - 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, - 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, - 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, - 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, - 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, - 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, - 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, - 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, - 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, - 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, - 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, - 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, - 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, - 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, - 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, - 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, - 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, - 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, - 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, - 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, - 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, - 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, - 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, - 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, - 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, - 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, - 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, - 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, - 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, - 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, - 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, - 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, - 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, - 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, - 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, - 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, - 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, - 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, - 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, - 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, - 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, - 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, - 0x3dee8ca6}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0, - 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587, - 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa, - 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09, - 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee, - 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3, - 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3, - 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce, - 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429, - 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda, - 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7, - 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0, - 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd, - 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0, - 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287, - 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a, - 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9, - 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e, - 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3, - 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3, - 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054, - 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49, - 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da, - 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7, - 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20, - 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d, - 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00, - 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347, - 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14, - 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209, - 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e, - 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33, - 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3, - 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194, - 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9, - 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a, - 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd, - 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0, - 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d, - 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460, - 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87, - 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674, - 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509, - 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e, - 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae, - 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3, - 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694, - 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989, - 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da, - 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d, - 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0, - 0xa68cee3d}, - {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19, - 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae, - 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb, - 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a, - 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55, - 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1, - 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c, - 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8, - 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7, - 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936, - 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453, - 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4, - 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941, - 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5, - 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93, - 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17, - 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e, - 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89, - 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec, - 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0, - 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf, - 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b, - 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b, - 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f, - 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0, - 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e, - 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b, - 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc, - 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5, - 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261, - 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637, - 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3, - 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57, - 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0, - 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85, - 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454, - 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b, - 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f, - 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423, - 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7, - 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8, - 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739, - 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c, - 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb, - 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f, - 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b, - 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd, - 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59, - 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070, - 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7, - 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2, - 0x51e8883f}, - {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a, - 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276, - 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed, - 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55, - 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b, - 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8, - 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320, - 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413, - 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd, - 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75, - 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee, - 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312, - 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca, - 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9, - 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad, - 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e, - 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504, - 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8, - 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63, - 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353, - 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d, - 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be, - 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae, - 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d, - 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943, - 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7, - 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c, - 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390, - 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a, - 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239, - 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d, - 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e, - 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c, - 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0, - 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b, - 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93, - 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d, - 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e, - 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c, - 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f, - 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1, - 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579, - 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2, - 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e, - 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c, - 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f, - 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b, - 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158, - 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2, - 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e, - 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5, - 0x8ae9531c}, - {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4, - 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd, - 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220, - 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf, - 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495, - 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def, - 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90, - 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea, - 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0, - 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f, - 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2, - 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab, - 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e, - 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754, - 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda, - 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0, - 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c, - 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215, - 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8, - 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910, - 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a, - 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30, - 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658, - 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22, - 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478, - 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2, - 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f, - 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606, - 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba, - 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0, - 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e, - 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034, - 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f, - 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996, - 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b, - 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84, - 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de, - 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4, - 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5, - 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f, - 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5, - 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a, - 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7, - 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce, - 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65, - 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f, - 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91, - 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb, - 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57, - 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e, - 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3, - 0xd739710d}}; - -#endif - -#endif - -#if N == 5 - -#if W == 8 - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df, - 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8, - 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef, - 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376, - 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201, - 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399, - 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372, - 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea, - 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d, - 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004, - 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353, - 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334, - 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a, - 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2, - 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a, - 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2, - 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b, - 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c, - 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b, - 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f, - 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338, - 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0, - 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6, - 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e, - 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319, - 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3, - 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4, - 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783, - 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a, - 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492, - 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a, - 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2, - 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496, - 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1, - 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6, - 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f, - 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548, - 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0, - 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741, - 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9, - 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae, - 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437, - 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760, - 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707, - 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433, - 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab, - 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703, - 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b, - 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412, - 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475, - 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722, - 0xe9947565}, - {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5, - 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22, - 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c, - 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed, - 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d, - 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1, - 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e, - 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32, - 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142, - 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93, - 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d, - 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a, - 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58, - 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14, - 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81, - 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd, - 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab, - 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c, - 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72, - 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f, - 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff, - 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3, - 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30, - 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c, - 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c, - 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558, - 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146, - 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581, - 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7, - 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab, - 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e, - 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272, - 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838, - 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff, - 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1, - 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330, - 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840, - 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c, - 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb, - 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7, - 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7, - 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616, - 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208, - 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf, - 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85, - 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9, - 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c, - 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10, - 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76, - 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1, - 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf, - 0xf7d05006}, - {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b, - 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774, - 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58, - 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a, - 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb, - 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952, - 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e, - 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7, - 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746, - 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14, - 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338, - 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907, - 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777, - 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de, - 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064, - 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd, - 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951, - 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e, - 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42, - 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b, - 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a, - 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3, - 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904, - 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad, - 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c, - 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d, - 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861, - 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e, - 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2, - 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b, - 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1, - 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78, - 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f, - 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40, - 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c, - 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e, - 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf, - 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166, - 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d, - 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4, - 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805, - 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157, - 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b, - 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644, - 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43, - 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea, - 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850, - 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9, - 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165, - 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a, - 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676, - 0xb2075b94}, - {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf, - 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61, - 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be, - 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd, - 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3, - 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063, - 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105, - 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5, - 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb, - 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8, - 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07, - 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9, - 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5, - 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515, - 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4, - 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014, - 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7, - 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269, - 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6, - 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af, - 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1, - 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111, - 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d, - 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad, - 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3, - 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75, - 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa, - 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74, - 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7, - 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477, - 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6, - 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176, - 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af, - 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71, - 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae, - 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd, - 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3, - 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073, - 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0, - 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400, - 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e, - 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d, - 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2, - 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c, - 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5, - 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505, - 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4, - 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004, - 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7, - 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279, - 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6, - 0xba50bcb9}, - {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897, - 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb, - 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2, - 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2, - 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372, - 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70, - 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92, - 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190, - 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40, - 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430, - 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759, - 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75, - 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2, - 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0, - 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7, - 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5, - 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39, - 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215, - 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c, - 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5, - 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625, - 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27, - 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c, - 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e, - 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee, - 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71, - 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18, - 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134, - 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8, - 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba, - 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd, - 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff, - 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a, - 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6, - 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf, - 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf, - 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f, - 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d, - 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d, - 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f, - 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af, - 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df, - 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6, - 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a, - 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef, - 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed, - 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa, - 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8, - 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624, - 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08, - 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861, - 0x808abcf4}, - {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2, - 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd, - 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76, - 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52, - 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e, - 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124, - 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147, - 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d, - 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31, - 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15, - 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae, - 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1, - 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d, - 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307, - 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9, - 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3, - 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084, - 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb, - 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850, - 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2, - 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe, - 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94, - 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261, - 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b, - 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917, - 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53, - 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8, - 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787, - 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0, - 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba, - 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404, - 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e, - 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af, - 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0, - 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b, - 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f, - 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543, - 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129, - 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627, - 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d, - 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51, - 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75, - 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce, - 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1, - 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760, - 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a, - 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4, - 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde, - 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089, - 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6, - 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d, - 0xefdb3f95}, - {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8, - 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7, - 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945, - 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9, - 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652, - 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc, - 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a, - 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4, - 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f, - 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3, - 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51, - 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e, - 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c, - 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362, - 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11, - 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff, - 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7, - 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8, - 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a, - 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690, - 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b, - 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5, - 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05, - 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb, - 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740, - 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f, - 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded, - 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2, - 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa, - 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714, - 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67, - 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89, - 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7, - 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8, - 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a, - 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6, - 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d, - 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3, - 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9, - 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57, - 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc, - 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540, - 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2, - 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd, - 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93, - 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d, - 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e, - 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0, - 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8, - 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7, - 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75, - 0x0e2fbf43}, - {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc, - 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a, - 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3, - 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7, - 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b, - 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154, - 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3, - 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc, - 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330, - 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264, - 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd, - 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b, - 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a, - 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175, - 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275, - 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a, - 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234, - 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2, - 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b, - 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a, - 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6, - 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189, - 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b, - 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204, - 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8, - 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226, - 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff, - 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219, - 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167, - 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258, - 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158, - 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267, - 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c, - 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da, - 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003, - 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157, - 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b, - 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4, - 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179, - 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246, - 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a, - 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de, - 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107, - 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1, - 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba, - 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285, - 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185, - 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba, - 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4, - 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322, - 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb, - 0xf4377108}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000, - 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000, - 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000, - 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000, - 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000, - 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000, - 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000, - 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000, - 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000, - 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000, - 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000, - 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000, - 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000, - 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000, - 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000, - 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000, - 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000, - 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000, - 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000, - 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000, - 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000, - 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000, - 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000, - 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000, - 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000, - 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000, - 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000, - 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000, - 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000, - 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000, - 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000, - 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000, - 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000, - 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000, - 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000, - 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000, - 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000, - 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000, - 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000, - 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000, - 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000, - 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000, - 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000, - 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000, - 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000, - 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000, - 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000, - 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000, - 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000, - 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000, - 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000, - 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000, - 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000, - 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000, - 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000, - 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000, - 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000, - 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000, - 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000, - 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000, - 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000, - 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000, - 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000, - 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000, - 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000, - 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000, - 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000, - 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000, - 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000, - 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000, - 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000, - 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000, - 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000, - 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000, - 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000, - 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000, - 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000, - 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000, - 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000, - 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000, - 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000, - 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000, - 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000, - 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000, - 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000, - 0x087137f400000000}, - {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000, - 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000, - 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000, - 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000, - 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000, - 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000, - 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000, - 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000, - 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000, - 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000, - 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000, - 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000, - 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000, - 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000, - 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000, - 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000, - 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000, - 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000, - 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000, - 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000, - 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000, - 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000, - 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000, - 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000, - 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000, - 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000, - 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000, - 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000, - 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000, - 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000, - 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000, - 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000, - 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000, - 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000, - 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000, - 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000, - 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000, - 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000, - 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000, - 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000, - 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000, - 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000, - 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000, - 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000, - 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000, - 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000, - 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000, - 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000, - 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000, - 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000, - 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000, - 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000, - 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000, - 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000, - 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000, - 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000, - 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000, - 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000, - 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000, - 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000, - 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000, - 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000, - 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000, - 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000, - 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000, - 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000, - 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000, - 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000, - 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000, - 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000, - 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000, - 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000, - 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000, - 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000, - 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000, - 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000, - 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000, - 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000, - 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000, - 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000, - 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000, - 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000, - 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000, - 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000, - 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000, - 0x43bf2f0e00000000}, - {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000, - 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000, - 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000, - 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000, - 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000, - 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000, - 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000, - 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000, - 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000, - 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000, - 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000, - 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000, - 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000, - 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000, - 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000, - 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000, - 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000, - 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000, - 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000, - 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000, - 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000, - 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000, - 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000, - 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000, - 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000, - 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000, - 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000, - 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000, - 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000, - 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000, - 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000, - 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000, - 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000, - 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000, - 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000, - 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000, - 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000, - 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000, - 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000, - 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000, - 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000, - 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000, - 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000, - 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000, - 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000, - 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000, - 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000, - 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000, - 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000, - 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000, - 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000, - 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000, - 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000, - 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000, - 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000, - 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000, - 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000, - 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000, - 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000, - 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000, - 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000, - 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000, - 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000, - 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000, - 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000, - 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000, - 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000, - 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000, - 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000, - 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000, - 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000, - 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000, - 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000, - 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000, - 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000, - 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000, - 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000, - 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000, - 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000, - 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000, - 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000, - 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000, - 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000, - 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000, - 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000, - 0x953fdbef00000000}, - {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000, - 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000, - 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000, - 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000, - 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000, - 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000, - 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000, - 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000, - 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000, - 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000, - 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000, - 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000, - 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000, - 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000, - 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000, - 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000, - 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000, - 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000, - 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000, - 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000, - 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000, - 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000, - 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000, - 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000, - 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000, - 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000, - 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000, - 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000, - 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000, - 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000, - 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000, - 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000, - 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000, - 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000, - 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000, - 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000, - 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000, - 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000, - 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000, - 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000, - 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000, - 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000, - 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000, - 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000, - 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000, - 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000, - 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000, - 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000, - 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000, - 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000, - 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000, - 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000, - 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000, - 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000, - 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000, - 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000, - 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000, - 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000, - 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000, - 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000, - 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000, - 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000, - 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000, - 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000, - 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000, - 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000, - 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000, - 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000, - 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000, - 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000, - 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000, - 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000, - 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000, - 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000, - 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000, - 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000, - 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000, - 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000, - 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000, - 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000, - 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000, - 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000, - 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000, - 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000, - 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000, - 0xf4bc8a8000000000}, - {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000, - 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000, - 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000, - 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000, - 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000, - 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000, - 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000, - 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000, - 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000, - 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000, - 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000, - 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000, - 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000, - 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000, - 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000, - 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000, - 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000, - 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000, - 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000, - 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000, - 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000, - 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000, - 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000, - 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000, - 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000, - 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000, - 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000, - 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000, - 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000, - 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000, - 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000, - 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000, - 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000, - 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000, - 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000, - 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000, - 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000, - 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000, - 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000, - 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000, - 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000, - 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000, - 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000, - 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000, - 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000, - 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000, - 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000, - 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000, - 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000, - 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000, - 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000, - 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000, - 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000, - 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000, - 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000, - 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000, - 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000, - 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000, - 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000, - 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000, - 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000, - 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000, - 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000, - 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000, - 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000, - 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000, - 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000, - 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000, - 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000, - 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000, - 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000, - 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000, - 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000, - 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000, - 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000, - 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000, - 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000, - 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000, - 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000, - 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000, - 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000, - 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000, - 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000, - 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000, - 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000, - 0xb9bc50ba00000000}, - {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000, - 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000, - 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000, - 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000, - 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000, - 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000, - 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000, - 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000, - 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000, - 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000, - 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000, - 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000, - 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000, - 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000, - 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000, - 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000, - 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000, - 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000, - 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000, - 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000, - 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000, - 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000, - 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000, - 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000, - 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000, - 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000, - 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000, - 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000, - 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000, - 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000, - 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000, - 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000, - 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000, - 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000, - 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000, - 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000, - 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000, - 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000, - 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000, - 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000, - 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000, - 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000, - 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000, - 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000, - 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000, - 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000, - 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000, - 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000, - 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000, - 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000, - 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000, - 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000, - 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000, - 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000, - 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000, - 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000, - 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000, - 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000, - 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000, - 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000, - 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000, - 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000, - 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000, - 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000, - 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000, - 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000, - 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000, - 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000, - 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000, - 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000, - 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000, - 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000, - 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000, - 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000, - 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000, - 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000, - 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000, - 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000, - 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000, - 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000, - 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000, - 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000, - 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000, - 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000, - 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000, - 0x945b07b200000000}, - {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000, - 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000, - 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000, - 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000, - 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000, - 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000, - 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000, - 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000, - 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000, - 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000, - 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000, - 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000, - 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000, - 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000, - 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000, - 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000, - 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000, - 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000, - 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000, - 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000, - 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000, - 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000, - 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000, - 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000, - 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000, - 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000, - 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000, - 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000, - 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000, - 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000, - 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000, - 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000, - 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000, - 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000, - 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000, - 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000, - 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000, - 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000, - 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000, - 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000, - 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000, - 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000, - 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000, - 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000, - 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000, - 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000, - 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000, - 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000, - 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000, - 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000, - 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000, - 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000, - 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000, - 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000, - 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000, - 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000, - 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000, - 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000, - 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000, - 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000, - 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000, - 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000, - 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000, - 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000, - 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000, - 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000, - 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000, - 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000, - 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000, - 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000, - 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000, - 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000, - 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000, - 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000, - 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000, - 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000, - 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000, - 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000, - 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000, - 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000, - 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000, - 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000, - 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000, - 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000, - 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000, - 0x0650d0f700000000}, - {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000, - 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000, - 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000, - 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000, - 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000, - 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000, - 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000, - 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000, - 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000, - 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000, - 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000, - 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000, - 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000, - 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000, - 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000, - 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000, - 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000, - 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000, - 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000, - 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000, - 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000, - 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000, - 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000, - 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000, - 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000, - 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000, - 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000, - 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000, - 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000, - 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000, - 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000, - 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000, - 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000, - 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000, - 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000, - 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000, - 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000, - 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000, - 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000, - 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000, - 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000, - 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000, - 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000, - 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000, - 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000, - 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000, - 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000, - 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000, - 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000, - 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000, - 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000, - 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000, - 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000, - 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000, - 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000, - 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000, - 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000, - 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000, - 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000, - 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000, - 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000, - 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000, - 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000, - 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000, - 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000, - 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000, - 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000, - 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000, - 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000, - 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000, - 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000, - 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000, - 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000, - 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000, - 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000, - 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000, - 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000, - 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000, - 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000, - 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000, - 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000, - 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000, - 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000, - 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000, - 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000, - 0x657594e900000000}}; - -#else /* W == 4 */ - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, - 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, - 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, - 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, - 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, - 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, - 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, - 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, - 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, - 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, - 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, - 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, - 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, - 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, - 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, - 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, - 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, - 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, - 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, - 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, - 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, - 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, - 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, - 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, - 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, - 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, - 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, - 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, - 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, - 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, - 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, - 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, - 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, - 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, - 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, - 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, - 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, - 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, - 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, - 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, - 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, - 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, - 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, - 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, - 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, - 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, - 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, - 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, - 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, - 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, - 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, - 0xd8ac6b35}, - {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, - 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, - 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, - 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, - 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, - 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, - 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, - 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, - 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, - 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, - 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, - 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, - 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, - 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, - 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, - 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, - 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, - 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, - 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, - 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, - 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, - 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, - 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, - 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, - 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, - 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, - 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, - 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, - 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, - 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, - 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, - 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, - 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, - 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, - 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, - 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, - 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, - 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, - 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, - 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, - 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, - 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, - 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, - 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, - 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, - 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, - 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, - 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, - 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, - 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, - 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, - 0xa140efa8}, - {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, - 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, - 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, - 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, - 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, - 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, - 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, - 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, - 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, - 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, - 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, - 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, - 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, - 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, - 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, - 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, - 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, - 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, - 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, - 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, - 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, - 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, - 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, - 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, - 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, - 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, - 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, - 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, - 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, - 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, - 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, - 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, - 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, - 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, - 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, - 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, - 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, - 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, - 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, - 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, - 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, - 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, - 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, - 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, - 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, - 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, - 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, - 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, - 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, - 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, - 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, - 0x917cd6a1}, - {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, - 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, - 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, - 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, - 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, - 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, - 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, - 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, - 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, - 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, - 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, - 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, - 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, - 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, - 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, - 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, - 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, - 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, - 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, - 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, - 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, - 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, - 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, - 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, - 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, - 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, - 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, - 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, - 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, - 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, - 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, - 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, - 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, - 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, - 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, - 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, - 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, - 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, - 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, - 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, - 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, - 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, - 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, - 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, - 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, - 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, - 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, - 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, - 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, - 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, - 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, - 0x18ba364e}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873, - 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661, - 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441, - 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44, - 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1, - 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05, - 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa, - 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e, - 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb, - 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be, - 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e, - 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c, - 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d, - 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9, - 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f, - 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b, - 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39, - 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b, - 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b, - 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20, - 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595, - 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61, - 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0, - 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644, - 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1, - 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d, - 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d, - 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f, - 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad, - 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359, - 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f, - 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b, - 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7, - 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5, - 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5, - 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0, - 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65, - 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091, - 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633, - 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7, - 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272, - 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77, - 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57, - 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145, - 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9, - 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d, - 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb, - 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f, - 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad, - 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf, - 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f, - 0x4e36ba18}, - {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b, - 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8, - 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19, - 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4, - 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239, - 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd, - 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258, - 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc, - 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41, - 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c, - 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d, - 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e, - 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba, - 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e, - 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8, - 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c, - 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f, - 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c, - 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d, - 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d, - 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0, - 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014, - 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc, - 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628, - 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5, - 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941, - 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0, - 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53, - 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880, - 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264, - 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92, - 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776, - 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8, - 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b, - 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea, - 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837, - 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca, - 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e, - 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211, - 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5, - 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08, - 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5, - 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934, - 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7, - 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049, - 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad, - 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b, - 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf, - 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c, - 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f, - 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e, - 0xa1d67c91}, - {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9, - 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de, - 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94, - 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0, - 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a, - 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924, - 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052, - 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c, - 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6, - 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2, - 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8, - 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f, - 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d, - 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273, - 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30, - 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e, - 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7, - 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980, - 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca, - 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8, - 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62, - 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c, - 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c, - 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032, - 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798, - 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d, - 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07, - 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630, - 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389, - 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7, - 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4, - 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca, - 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55, - 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662, - 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828, - 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c, - 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6, - 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98, - 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3, - 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d, - 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037, - 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913, - 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759, - 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e, - 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1, - 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf, - 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c, - 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2, - 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b, - 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c, - 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276, - 0xa8ef40a1}, - {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e, - 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8, - 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819, - 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f, - 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d, - 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756, - 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0, - 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb, - 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9, - 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f, - 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e, - 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8, - 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835, - 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e, - 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62, - 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749, - 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b, - 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d, - 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc, - 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80, - 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2, - 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599, - 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05, - 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e, - 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c, - 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e, - 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef, - 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359, - 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b, - 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0, - 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc, - 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7, - 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f, - 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189, - 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568, - 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e, - 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c, - 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27, - 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794, - 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf, - 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d, - 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db, - 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a, - 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c, - 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544, - 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f, - 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013, - 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38, - 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea, - 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c, - 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd, - 0x356bacd8}}; - -#endif - -#endif - -#if N == 6 - -#if W == 8 - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370, - 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d, - 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69, - 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426, - 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3, - 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f, - 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c, - 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490, - 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155, - 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a, - 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e, - 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603, - 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349, - 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5, - 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50, - 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc, - 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b, - 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76, - 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862, - 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9, - 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c, - 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0, - 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937, - 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b, - 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e, - 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e, - 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a, - 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357, - 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0, - 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c, - 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9, - 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165, - 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766, - 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b, - 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f, - 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030, - 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5, - 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59, - 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63, - 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf, - 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a, - 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845, - 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51, - 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c, - 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f, - 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3, - 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46, - 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea, - 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d, - 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60, - 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74, - 0x8568a0a8}, - {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5, - 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf, - 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5, - 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba, - 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf, - 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f, - 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0, - 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450, - 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55, - 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a, - 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620, - 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a, - 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454, - 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4, - 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534, - 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584, - 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694, - 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e, - 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4, - 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1, - 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4, - 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164, - 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1, - 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911, - 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314, - 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c, - 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6, - 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec, - 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc, - 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c, - 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c, - 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c, - 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716, - 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c, - 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676, - 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879, - 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c, - 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc, - 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77, - 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7, - 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2, - 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd, - 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7, - 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad, - 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897, - 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827, - 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7, - 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947, - 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57, - 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d, - 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37, - 0x0d907052}, - {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d, - 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89, - 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31, - 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81, - 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e, - 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0, - 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f, - 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291, - 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e, - 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e, - 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936, - 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2, - 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13, - 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d, - 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f, - 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1, - 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a, - 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae, - 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516, - 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f, - 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20, - 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe, - 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28, - 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6, - 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419, - 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5, - 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d, - 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889, - 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412, - 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c, - 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e, - 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0, - 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02, - 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986, - 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e, - 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e, - 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221, - 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf, - 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913, - 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d, - 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622, - 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592, - 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a, - 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae, - 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c, - 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82, - 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20, - 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe, - 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025, - 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1, - 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719, - 0xfd1a6c8a}, - {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3, - 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb, - 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d, - 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb, - 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9, - 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156, - 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045, - 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa, - 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8, - 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e, - 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8, - 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0, - 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38, - 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87, - 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46, - 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9, - 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585, - 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d, - 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb, - 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531, - 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03, - 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc, - 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33, - 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c, - 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be, - 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d, - 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b, - 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303, - 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f, - 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0, - 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801, - 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe, - 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e, - 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346, - 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620, - 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776, - 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844, - 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb, - 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0, - 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f, - 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d, - 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b, - 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d, - 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75, - 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795, - 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a, - 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb, - 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354, - 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28, - 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30, - 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856, - 0x7895f01a}, - {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188, - 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33, - 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d, - 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445, - 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2, - 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058, - 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43, - 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9, - 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e, - 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06, - 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228, - 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93, - 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e, - 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4, - 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b, - 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371, - 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265, - 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede, - 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0, - 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f, - 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8, - 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32, - 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae, - 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544, - 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3, - 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f, - 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911, - 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa, - 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be, - 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54, - 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b, - 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1, - 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652, - 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9, - 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7, - 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f, - 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68, - 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782, - 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797, - 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d, - 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a, - 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2, - 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc, - 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647, - 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4, - 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e, - 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41, - 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab, - 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf, - 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904, - 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a, - 0x9239b848}, - {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad, - 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0, - 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40, - 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b, - 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d, - 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b, - 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb, - 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d, - 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b, - 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0, - 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840, - 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d, - 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b, - 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d, - 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6, - 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0, - 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580, - 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd, - 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d, - 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b, - 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d, - 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b, - 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6, - 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0, - 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6, - 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c, - 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c, - 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461, - 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841, - 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317, - 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac, - 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa, - 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7, - 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba, - 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a, - 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161, - 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777, - 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21, - 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a, - 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc, - 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da, - 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1, - 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01, - 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c, - 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241, - 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917, - 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac, - 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa, - 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da, - 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397, - 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537, - 0xeb36d3cc}, - {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b, - 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059, - 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251, - 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d, - 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9, - 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c, - 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41, - 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4, - 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10, - 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c, - 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54, - 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476, - 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8, - 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d, - 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92, - 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307, - 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad, - 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f, - 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87, - 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17, - 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3, - 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46, - 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197, - 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02, - 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6, - 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e, - 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96, - 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4, - 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e, - 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b, - 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934, - 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1, - 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7, - 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5, - 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd, - 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1, - 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475, - 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0, - 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155, - 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0, - 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304, - 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348, - 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140, - 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862, - 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14, - 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181, - 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e, - 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab, - 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01, - 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523, - 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b, - 0x38e5f3c5}, - {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06, - 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad, - 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509, - 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba, - 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414, - 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3, - 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733, - 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994, - 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a, - 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889, - 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d, - 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386, - 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621, - 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886, - 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e, - 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389, - 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f, - 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294, - 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30, - 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3, - 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d, - 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba, - 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a, - 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad, - 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03, - 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2, - 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306, - 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad, - 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b, - 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc, - 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914, - 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3, - 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435, - 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e, - 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a, - 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589, - 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27, - 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080, - 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21, - 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586, - 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28, - 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b, - 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f, - 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94, - 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12, - 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5, - 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d, - 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba, - 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c, - 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7, - 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103, - 0x3d3101a2}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000, - 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000, - 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000, - 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000, - 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000, - 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000, - 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000, - 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000, - 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000, - 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000, - 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000, - 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000, - 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000, - 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000, - 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000, - 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000, - 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000, - 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000, - 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000, - 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000, - 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000, - 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000, - 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000, - 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000, - 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000, - 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000, - 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000, - 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000, - 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000, - 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000, - 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000, - 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000, - 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000, - 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000, - 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000, - 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000, - 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000, - 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000, - 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000, - 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000, - 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000, - 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000, - 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000, - 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000, - 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000, - 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000, - 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000, - 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000, - 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000, - 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000, - 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000, - 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000, - 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000, - 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000, - 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000, - 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000, - 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000, - 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000, - 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000, - 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000, - 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000, - 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000, - 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000, - 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000, - 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000, - 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000, - 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000, - 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000, - 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000, - 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000, - 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000, - 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000, - 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000, - 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000, - 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000, - 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000, - 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000, - 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000, - 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000, - 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000, - 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000, - 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000, - 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000, - 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000, - 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000, - 0xa201313d00000000}, - {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000, - 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000, - 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000, - 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000, - 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000, - 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000, - 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000, - 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000, - 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000, - 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000, - 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000, - 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000, - 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000, - 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000, - 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000, - 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000, - 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000, - 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000, - 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000, - 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000, - 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000, - 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000, - 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000, - 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000, - 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000, - 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000, - 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000, - 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000, - 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000, - 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000, - 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000, - 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000, - 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000, - 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000, - 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000, - 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000, - 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000, - 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000, - 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000, - 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000, - 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000, - 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000, - 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000, - 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000, - 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000, - 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000, - 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000, - 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000, - 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000, - 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000, - 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000, - 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000, - 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000, - 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000, - 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000, - 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000, - 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000, - 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000, - 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000, - 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000, - 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000, - 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000, - 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000, - 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000, - 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000, - 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000, - 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000, - 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000, - 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000, - 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000, - 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000, - 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000, - 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000, - 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000, - 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000, - 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000, - 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000, - 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000, - 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000, - 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000, - 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000, - 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000, - 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000, - 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000, - 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000, - 0xc5f3e53800000000}, - {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000, - 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000, - 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000, - 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000, - 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000, - 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000, - 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000, - 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000, - 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000, - 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000, - 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000, - 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000, - 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000, - 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000, - 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000, - 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000, - 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000, - 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000, - 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000, - 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000, - 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000, - 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000, - 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000, - 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000, - 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000, - 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000, - 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000, - 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000, - 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000, - 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000, - 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000, - 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000, - 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000, - 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000, - 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000, - 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000, - 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000, - 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000, - 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000, - 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000, - 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000, - 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000, - 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000, - 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000, - 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000, - 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000, - 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000, - 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000, - 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000, - 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000, - 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000, - 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000, - 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000, - 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000, - 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000, - 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000, - 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000, - 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000, - 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000, - 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000, - 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000, - 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000, - 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000, - 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000, - 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000, - 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000, - 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000, - 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000, - 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000, - 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000, - 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000, - 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000, - 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000, - 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000, - 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000, - 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000, - 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000, - 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000, - 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000, - 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000, - 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000, - 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000, - 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000, - 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000, - 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000, - 0xccd336eb00000000}, - {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000, - 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000, - 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000, - 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000, - 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000, - 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000, - 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000, - 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000, - 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000, - 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000, - 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000, - 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000, - 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000, - 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000, - 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000, - 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000, - 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000, - 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000, - 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000, - 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000, - 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000, - 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000, - 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000, - 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000, - 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000, - 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000, - 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000, - 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000, - 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000, - 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000, - 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000, - 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000, - 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000, - 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000, - 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000, - 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000, - 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000, - 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000, - 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000, - 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000, - 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000, - 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000, - 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000, - 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000, - 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000, - 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000, - 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000, - 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000, - 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000, - 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000, - 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000, - 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000, - 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000, - 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000, - 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000, - 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000, - 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000, - 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000, - 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000, - 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000, - 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000, - 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000, - 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000, - 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000, - 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000, - 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000, - 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000, - 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000, - 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000, - 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000, - 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000, - 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000, - 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000, - 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000, - 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000, - 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000, - 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000, - 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000, - 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000, - 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000, - 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000, - 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000, - 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000, - 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000, - 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000, - 0x48b8399200000000}, - {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000, - 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000, - 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000, - 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000, - 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000, - 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000, - 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000, - 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000, - 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000, - 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000, - 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000, - 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000, - 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000, - 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000, - 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000, - 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000, - 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000, - 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000, - 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000, - 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000, - 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000, - 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000, - 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000, - 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000, - 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000, - 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000, - 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000, - 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000, - 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000, - 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000, - 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000, - 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000, - 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000, - 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000, - 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000, - 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000, - 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000, - 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000, - 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000, - 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000, - 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000, - 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000, - 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000, - 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000, - 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000, - 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000, - 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000, - 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000, - 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000, - 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000, - 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000, - 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000, - 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000, - 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000, - 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000, - 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000, - 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000, - 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000, - 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000, - 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000, - 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000, - 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000, - 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000, - 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000, - 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000, - 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000, - 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000, - 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000, - 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000, - 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000, - 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000, - 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000, - 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000, - 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000, - 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000, - 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000, - 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000, - 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000, - 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000, - 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000, - 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000, - 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000, - 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000, - 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000, - 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000, - 0x1af0957800000000}, - {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000, - 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000, - 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000, - 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000, - 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000, - 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000, - 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000, - 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000, - 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000, - 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000, - 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000, - 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000, - 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000, - 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000, - 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000, - 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000, - 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000, - 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000, - 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000, - 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000, - 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000, - 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000, - 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000, - 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000, - 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000, - 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000, - 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000, - 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000, - 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000, - 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000, - 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000, - 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000, - 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000, - 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000, - 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000, - 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000, - 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000, - 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000, - 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000, - 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000, - 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000, - 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000, - 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000, - 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000, - 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000, - 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000, - 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000, - 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000, - 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000, - 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000, - 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000, - 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000, - 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000, - 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000, - 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000, - 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000, - 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000, - 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000, - 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000, - 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000, - 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000, - 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000, - 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000, - 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000, - 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000, - 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000, - 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000, - 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000, - 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000, - 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000, - 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000, - 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000, - 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000, - 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000, - 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000, - 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000, - 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000, - 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000, - 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000, - 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000, - 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000, - 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000, - 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000, - 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000, - 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000, - 0x8a6c1afd00000000}, - {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000, - 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000, - 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000, - 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000, - 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000, - 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000, - 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000, - 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000, - 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000, - 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000, - 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000, - 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000, - 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000, - 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000, - 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000, - 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000, - 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000, - 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000, - 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000, - 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000, - 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000, - 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000, - 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000, - 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000, - 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000, - 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000, - 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000, - 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000, - 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000, - 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000, - 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000, - 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000, - 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000, - 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000, - 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000, - 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000, - 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000, - 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000, - 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000, - 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000, - 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000, - 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000, - 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000, - 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000, - 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000, - 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000, - 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000, - 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000, - 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000, - 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000, - 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000, - 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000, - 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000, - 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000, - 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000, - 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000, - 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000, - 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000, - 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000, - 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000, - 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000, - 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000, - 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000, - 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000, - 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000, - 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000, - 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000, - 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000, - 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000, - 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000, - 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000, - 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000, - 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000, - 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000, - 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000, - 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000, - 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000, - 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000, - 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000, - 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000, - 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000, - 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000, - 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000, - 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000, - 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000, - 0x5270900d00000000}, - {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000, - 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000, - 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000, - 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000, - 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000, - 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000, - 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000, - 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000, - 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000, - 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000, - 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000, - 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000, - 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000, - 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000, - 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000, - 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000, - 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000, - 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000, - 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000, - 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000, - 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000, - 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000, - 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000, - 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000, - 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000, - 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000, - 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000, - 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000, - 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000, - 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000, - 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000, - 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000, - 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000, - 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000, - 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000, - 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000, - 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000, - 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000, - 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000, - 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000, - 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000, - 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000, - 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000, - 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000, - 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000, - 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000, - 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000, - 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000, - 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000, - 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000, - 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000, - 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000, - 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000, - 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000, - 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000, - 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000, - 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000, - 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000, - 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000, - 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000, - 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000, - 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000, - 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000, - 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000, - 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000, - 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000, - 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000, - 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000, - 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000, - 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000, - 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000, - 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000, - 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000, - 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000, - 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000, - 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000, - 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000, - 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000, - 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000, - 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000, - 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000, - 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000, - 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000, - 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000, - 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000, - 0xa8a0688500000000}}; - -#else /* W == 4 */ - -local const z_crc_t FAR crc_braid_table[][256] = { - {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, - 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, - 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, - 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, - 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, - 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, - 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, - 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, - 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, - 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, - 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, - 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, - 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, - 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, - 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, - 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, - 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, - 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, - 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, - 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, - 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, - 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, - 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, - 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, - 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, - 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, - 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, - 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, - 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, - 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, - 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, - 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, - 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, - 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, - 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, - 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, - 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, - 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, - 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, - 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, - 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, - 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, - 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, - 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, - 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, - 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, - 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, - 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, - 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, - 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, - 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, - 0x09cd8551}, - {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, - 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, - 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, - 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, - 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, - 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, - 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, - 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, - 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, - 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, - 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, - 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, - 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, - 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, - 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, - 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, - 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, - 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, - 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, - 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, - 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, - 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, - 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, - 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, - 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, - 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, - 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, - 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, - 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, - 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, - 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, - 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, - 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, - 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, - 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, - 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, - 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, - 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, - 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, - 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, - 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, - 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, - 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, - 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, - 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, - 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, - 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, - 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, - 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, - 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, - 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, - 0x7bc97a0c}, - {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, - 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, - 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, - 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, - 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, - 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, - 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, - 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, - 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, - 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, - 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, - 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, - 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, - 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, - 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, - 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, - 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, - 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, - 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, - 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, - 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, - 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, - 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, - 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, - 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, - 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, - 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, - 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, - 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, - 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, - 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, - 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, - 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, - 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, - 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, - 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, - 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, - 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, - 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, - 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, - 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, - 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, - 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, - 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, - 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, - 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, - 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, - 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, - 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, - 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, - 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, - 0x7851a2ca}, - {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, - 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, - 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, - 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, - 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, - 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, - 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, - 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, - 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, - 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, - 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, - 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, - 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, - 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, - 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, - 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, - 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, - 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, - 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, - 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, - 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, - 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, - 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, - 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, - 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, - 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, - 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, - 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, - 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, - 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, - 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, - 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, - 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, - 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, - 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, - 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, - 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, - 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, - 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, - 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, - 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, - 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, - 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, - 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, - 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, - 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, - 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, - 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, - 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, - 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, - 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, - 0x566b6848}}; - -local const z_word_t FAR crc_braid_big_table[][256] = { - {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912, - 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba, - 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3, - 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30, - 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e, - 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3, - 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73, - 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe, - 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0, - 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643, - 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a, - 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082, - 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4, - 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279, - 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735, - 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8, - 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad, - 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05, - 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c, - 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718, - 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46, - 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb, - 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc, - 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41, - 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f, - 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad, - 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4, - 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c, - 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779, - 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4, - 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8, - 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235, - 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7, - 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f, - 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476, - 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195, - 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb, - 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46, - 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622, - 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af, - 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1, - 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12, - 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b, - 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3, - 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51, - 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc, - 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90, - 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d, - 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708, - 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0, - 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9, - 0x48686b56}, - {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c, - 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae, - 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb, - 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90, - 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410, - 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b, - 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6, - 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed, - 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d, - 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036, - 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953, - 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1, - 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca, - 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781, - 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d, - 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416, - 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f, - 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd, - 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8, - 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b, - 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb, - 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0, - 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5, - 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e, - 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e, - 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558, - 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d, - 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf, - 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6, - 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad, - 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971, - 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a, - 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b, - 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969, - 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c, - 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57, - 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7, - 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c, - 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab, - 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0, - 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160, - 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b, - 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e, - 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac, - 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d, - 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546, - 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a, - 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1, - 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8, - 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a, - 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f, - 0xcaa25178}, - {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00, - 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b, - 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed, - 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777, - 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01, - 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a, - 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef, - 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74, - 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002, - 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498, - 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee, - 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75, - 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05, - 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e, - 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8, - 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73, - 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404, - 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f, - 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9, - 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71, - 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607, - 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c, - 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb, - 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470, - 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806, - 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790, - 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6, - 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d, - 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a, - 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991, - 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7, - 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c, - 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09, - 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92, - 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4, - 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e, - 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08, - 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593, - 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3, - 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778, - 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e, - 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94, - 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2, - 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079, - 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c, - 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497, - 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1, - 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a, - 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d, - 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396, - 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0, - 0x0c7ac97b}, - {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669, - 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853, - 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062, - 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527, - 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad, - 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545, - 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27, - 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf, - 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45, - 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800, - 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031, - 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b, - 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26, - 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce, - 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d, - 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5, - 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130, - 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a, - 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b, - 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480, - 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a, - 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2, - 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e, - 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996, - 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c, - 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc, - 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd, - 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7, - 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232, - 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da, - 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439, - 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1, - 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da, - 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0, - 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1, - 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94, - 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e, - 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6, - 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2, - 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a, - 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0, - 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95, - 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4, - 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e, - 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395, - 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d, - 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e, - 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676, - 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83, - 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9, - 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888, - 0x5185cd09}}; - -#endif - -#endif - -#endif - -local const z_crc_t FAR x2n_table[] = { - 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, - 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, - 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, - 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, - 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, - 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, - 0xc40ba6d0, 0xc4e22c3c}; diff --git a/libraries/zlib/deflate.c b/libraries/zlib/deflate.c deleted file mode 100644 index 4a689db359..0000000000 --- a/libraries/zlib/deflate.c +++ /dev/null @@ -1,2217 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://tools.ietf.org/html/rfc1951 - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id$ */ - -#include "deflate.h" - -const char deflate_copyright[] = - " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local int deflateStateCheck OF((z_streamp strm)); -local void slide_hash OF((deflate_state *s)); -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -#ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local block_state deflate_rle OF((deflate_state *s, int flush)); -local block_state deflate_huff OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -local uInt longest_match OF((deflate_state *s, IPos cur_match)); - -#ifdef ZLIB_DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -#ifdef FASTEST -local const config configuration_table[2] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ -#else -local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ -#endif - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to UPDATE_HASH are made with consecutive input - * characters, so that a running hash key can be computed from the previous - * key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to INSERT_STRING are made with consecutive input - * characters and the first MIN_MATCH bytes of str are valid (except for - * the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - do { \ - s->head[s->hash_size - 1] = NIL; \ - zmemzero((Bytef *)s->head, \ - (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \ - } while (0) - -/* =========================================================================== - * Slide the hash table when sliding the window down (could be avoided with 32 - * bit values at the expense of memory usage). We slide even when level == 0 to - * keep the hash table consistent if we switch back to level > 0 later. - */ -local void slide_hash(s) - deflate_state *s; -{ - unsigned n, m; - Posf *p; - uInt wsize = s->w_size; - - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m - wsize : NIL); - } while (--n); - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m - wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif -} - -/* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ - deflate_state *s; - int wrap = 1; - static const char my_version[] = ZLIB_VERSION; - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - if (windowBits < -15) - return Z_STREAM_ERROR; - windowBits = -windowBits; - } -#ifdef GZIP - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } -#endif - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - s->status = INIT_STATE; /* to pass state test in deflateReset() */ - - s->wrap = wrap; - s->gzhead = Z_NULL; - s->w_bits = (uInt)windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = (uInt)memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->high_water = 0; /* nothing written to s->window yet */ - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - /* We overlay pending_buf and sym_buf. This works since the average size - * for length/distance pairs over any compressed block is assured to be 31 - * bits or less. - * - * Analysis: The longest fixed codes are a length code of 8 bits plus 5 - * extra bits, for lengths 131 to 257. The longest fixed distance codes are - * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest - * possible fixed-codes length/distance pair is then 31 bits total. - * - * sym_buf starts one-fourth of the way into pending_buf. So there are - * three bytes in sym_buf for every four bytes in pending_buf. Each symbol - * in sym_buf is three bytes -- two for the distance and one for the - * literal/length. As each symbol is consumed, the pointer to the next - * sym_buf value to read moves forward three bytes. From that symbol, up to - * 31 bits are written to pending_buf. The closest the written pending_buf - * bits gets to the next sym_buf symbol to read is just before the last - * code is written. At that time, 31*(n - 2) bits have been written, just - * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at - * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1 - * symbols are written.) The closest the writing gets to what is unread is - * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and - * can range from 128 to 32768. - * - * Therefore, at a minimum, there are 142 bits of space between what is - * written and what is read in the overlain buffers, so the symbols cannot - * be overwritten by the compressed data. That space is actually 139 bits, - * due to the three-bit fixed-code block header. - * - * That covers the case where either Z_FIXED is specified, forcing fixed - * codes, or when the use of fixed codes is chosen, because that choice - * results in a smaller compressed block than dynamic codes. That latter - * condition then assures that the above analysis also covers all dynamic - * blocks. A dynamic-code block will only be chosen to be emitted if it has - * fewer bits than a fixed-code block would for the same set of symbols. - * Therefore its average symbol length is assured to be less than 31. So - * the compressed data for a dynamic block also cannot overwrite the - * symbols from which it is being constructed. - */ - - s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4); - s->pending_buf_size = (ulg)s->lit_bufsize * 4; - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - s->status = FINISH_STATE; - strm->msg = ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->sym_buf = s->pending_buf + s->lit_bufsize; - s->sym_end = (s->lit_bufsize - 1) * 3; - /* We avoid equality with lit_bufsize*3 because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= - * Check for a valid deflate stream state. Return 0 if ok, 1 if not. - */ -local int deflateStateCheck(strm) - z_streamp strm; -{ - deflate_state *s; - if (strm == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) - return 1; - s = strm->state; - if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && -#ifdef GZIP - s->status != GZIP_STATE && -#endif - s->status != EXTRA_STATE && - s->status != NAME_STATE && - s->status != COMMENT_STATE && - s->status != HCRC_STATE && - s->status != BUSY_STATE && - s->status != FINISH_STATE)) - return 1; - return 0; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ - deflate_state *s; - uInt str, n; - int wrap; - unsigned avail; - z_const unsigned char *next; - - if (deflateStateCheck(strm) || dictionary == Z_NULL) - return Z_STREAM_ERROR; - s = strm->state; - wrap = s->wrap; - if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) - return Z_STREAM_ERROR; - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap == 1) - strm->adler = adler32(strm->adler, dictionary, dictLength); - s->wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s->w_size) { - if (wrap == 0) { /* already empty otherwise */ - CLEAR_HASH(s); - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - dictionary += dictLength - s->w_size; /* use the tail */ - dictLength = s->w_size; - } - - /* insert dictionary into window and hash */ - avail = strm->avail_in; - next = strm->next_in; - strm->avail_in = dictLength; - strm->next_in = (z_const Bytef *)dictionary; - fill_window(s); - while (s->lookahead >= MIN_MATCH) { - str = s->strstart; - n = s->lookahead - (MIN_MATCH-1); - do { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - } while (--n); - s->strstart = str; - s->lookahead = MIN_MATCH-1; - fill_window(s); - } - s->strstart += s->lookahead; - s->block_start = (long)s->strstart; - s->insert = s->lookahead; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - strm->next_in = next; - strm->avail_in = avail; - s->wrap = wrap; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength) - z_streamp strm; - Bytef *dictionary; - uInt *dictLength; -{ - deflate_state *s; - uInt len; - - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - s = strm->state; - len = s->strstart + s->lookahead; - if (len > s->w_size) - len = s->w_size; - if (dictionary != Z_NULL && len) - zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); - if (dictLength != Z_NULL) - *dictLength = len; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateResetKeep(strm) - z_streamp strm; -{ - deflate_state *s; - - if (deflateStateCheck(strm)) { - return Z_STREAM_ERROR; - } - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - } - s->status = -#ifdef GZIP - s->wrap == 2 ? GZIP_STATE : -#endif - INIT_STATE; - strm->adler = -#ifdef GZIP - s->wrap == 2 ? crc32(0L, Z_NULL, 0) : -#endif - adler32(0L, Z_NULL, 0); - s->last_flush = -2; - - _tr_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset(strm) - z_streamp strm; -{ - int ret; - - ret = deflateResetKeep(strm); - if (ret == Z_OK) - lm_init(strm->state); - return ret; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetHeader(strm, head) - z_streamp strm; - gz_headerp head; -{ - if (deflateStateCheck(strm) || strm->state->wrap != 2) - return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePending(strm, pending, bits) - unsigned *pending; - int *bits; - z_streamp strm; -{ - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - if (pending != Z_NULL) - *pending = strm->state->pending; - if (bits != Z_NULL) - *bits = strm->state->bi_valid; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePrime(strm, bits, value) - z_streamp strm; - int bits; - int value; -{ - deflate_state *s; - int put; - - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - s = strm->state; - if (bits < 0 || bits > 16 || - s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) - return Z_BUF_ERROR; - do { - put = Buf_size - s->bi_valid; - if (put > bits) - put = bits; - s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); - s->bi_valid += put; - _tr_flush_bits(s); - value >>= put; - bits -= put; - } while (bits); - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ - deflate_state *s; - compress_func func; - - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - s = strm->state; - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if ((strategy != s->strategy || func != configuration_table[level].func) && - s->last_flush != -2) { - /* Flush the last buffer: */ - int err = deflate(strm, Z_BLOCK); - if (err == Z_STREAM_ERROR) - return err; - if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) - return Z_BUF_ERROR; - } - if (s->level != level) { - if (s->level == 0 && s->matches != 0) { - if (s->matches == 1) - slide_hash(s); - else - CLEAR_HASH(s); - s->matches = 0; - } - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) - z_streamp strm; - int good_length; - int max_lazy; - int nice_length; - int max_chain; -{ - deflate_state *s; - - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - s = strm->state; - s->good_match = (uInt)good_length; - s->max_lazy_match = (uInt)max_lazy; - s->nice_match = nice_length; - s->max_chain_length = (uInt)max_chain; - return Z_OK; -} - -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns a - * close to exact, as well as small, upper bound on the compressed size. This - * is an expansion of ~0.03%, plus a small constant. - * - * For any setting other than those defaults for windowBits and memLevel, one - * of two worst case bounds is returned. This is at most an expansion of ~4% or - * ~13%, plus a small constant. - * - * Both the 0.03% and 4% derive from the overhead of stored blocks. The first - * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second - * is for stored blocks of 127 bytes (the worst case memLevel == 1). The - * expansion results from five bytes of header for each stored block. - * - * The larger expansion of 13% results from a window size less than or equal to - * the symbols buffer size (windowBits <= memLevel + 7). In that case some of - * the data being compressed may have slid out of the sliding window, impeding - * a stored block from being emitted. Then the only choice is a fixed or - * dynamic block, where a fixed block limits the maximum expansion to 9 bits - * per 8-bit byte, plus 10 bits for every block. The smallest block size for - * which this can occur is 255 (memLevel == 2). - * - * Shifts are used to approximate divisions, for speed. - */ -uLong ZEXPORT deflateBound(strm, sourceLen) - z_streamp strm; - uLong sourceLen; -{ - deflate_state *s; - uLong fixedlen, storelen, wraplen; - - /* upper bound for fixed blocks with 9-bit literals and length 255 - (memLevel == 2, which is the lowest that may not use stored blocks) -- - ~13% overhead plus a small constant */ - fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) + - (sourceLen >> 9) + 4; - - /* upper bound for stored blocks with length 127 (memLevel == 1) -- - ~4% overhead plus a small constant */ - storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + - (sourceLen >> 11) + 7; - - /* if can't get parameters, return larger bound plus a zlib wrapper */ - if (deflateStateCheck(strm)) - return (fixedlen > storelen ? fixedlen : storelen) + 6; - - /* compute wrapper length */ - s = strm->state; - switch (s->wrap) { - case 0: /* raw deflate */ - wraplen = 0; - break; - case 1: /* zlib wrapper */ - wraplen = 6 + (s->strstart ? 4 : 0); - break; -#ifdef GZIP - case 2: /* gzip wrapper */ - wraplen = 18; - if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ - Bytef *str; - if (s->gzhead->extra != Z_NULL) - wraplen += 2 + s->gzhead->extra_len; - str = s->gzhead->name; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - str = s->gzhead->comment; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - if (s->gzhead->hcrc) - wraplen += 2; - } - break; -#endif - default: /* for compiler happiness */ - wraplen = 6; - } - - /* if not default parameters, return one of the conservative bounds */ - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen; - - /* default settings: return tight bound for that case -- ~0.03% overhead - plus a small constant */ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13 - 6 + wraplen; -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB(s, b) - deflate_state *s; - uInt b; -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output, except for - * some deflate_stored() output, goes through this function so some - * applications may wish to modify it to avoid allocating a large - * strm->next_out buffer and copying into it. (See also read_buf()). - */ -local void flush_pending(strm) - z_streamp strm; -{ - unsigned len; - deflate_state *s = strm->state; - - _tr_flush_bits(s); - len = s->pending; - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, s->pending_out, len); - strm->next_out += len; - s->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; - if (s->pending == 0) { - s->pending_out = s->pending_buf; - } -} - -/* =========================================================================== - * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. - */ -#define HCRC_UPDATE(beg) \ - do { \ - if (s->gzhead->hcrc && s->pending > (beg)) \ - strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ - s->pending - (beg)); \ - } while (0) - -/* ========================================================================= */ -int ZEXPORT deflate(strm, flush) - z_streamp strm; - int flush; -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->avail_in != 0 && strm->next_in == Z_NULL) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - old_flush = s->last_flush; - s->last_flush = flush; - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Write the header */ - if (s->status == INIT_STATE && s->wrap == 0) - s->status = BUSY_STATE; - if (s->status == INIT_STATE) { - /* zlib header */ - uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } -#ifdef GZIP - if (s->status == GZIP_STATE) { - /* gzip header */ - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - ulg beg = s->pending; /* start of bytes to update crc */ - uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; - while (s->pending + left > s->pending_buf_size) { - uInt copy = s->pending_buf_size - s->pending; - zmemcpy(s->pending_buf + s->pending, - s->gzhead->extra + s->gzindex, copy); - s->pending = s->pending_buf_size; - HCRC_UPDATE(beg); - s->gzindex += copy; - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - left -= copy; - } - zmemcpy(s->pending_buf + s->pending, - s->gzhead->extra + s->gzindex, left); - s->pending += left; - HCRC_UPDATE(beg); - s->gzindex = 0; - } - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - ulg beg = s->pending; /* start of bytes to update crc */ - int val; - do { - if (s->pending == s->pending_buf_size) { - HCRC_UPDATE(beg); - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - HCRC_UPDATE(beg); - s->gzindex = 0; - } - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - ulg beg = s->pending; /* start of bytes to update crc */ - int val; - do { - if (s->pending == s->pending_buf_size) { - HCRC_UPDATE(beg); - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - HCRC_UPDATE(beg); - } - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) { - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - } - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } -#endif - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = s->level == 0 ? deflate_stored(s, flush) : - s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - if (s->lookahead == 0) { - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - - if (flush != Z_FINISH) return Z_OK; - if (s->wrap <= 0) return Z_STREAM_END; - - /* Write the trailer */ -#ifdef GZIP - if (s->wrap == 2) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); - put_byte(s, (Byte)(strm->total_in & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); - } - else -#endif - { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd(strm) - z_streamp strm; -{ - int status; - - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - - status = strm->state->status; - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy(dest, source) - z_streamp dest; - z_streamp source; -{ -#ifdef MAXSEG_64K - return Z_STREAM_ERROR; -#else - deflate_state *ds; - deflate_state *ss; - - - if (deflateStateCheck(source) || dest == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4); - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->sym_buf = ds->pending_buf + ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -#endif /* MAXSEG_64K */ -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local unsigned read_buf(strm, buf, size) - z_streamp strm; - Bytef *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - zmemcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, buf, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, buf, len); - } -#endif - strm->next_in += len; - strm->total_in += len; - - return len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init(s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->insert = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -} - -#ifndef FASTEST -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = (int)s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan + best_len - 1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len - 1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match + best_len - 1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart + 3, + 5, up to strstart + 257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) && - *(ushf*)(scan += 2) == *(ushf*)(match += 2) && - *(ushf*)(scan += 2) == *(ushf*)(match += 2) && - *(ushf*)(scan += 2) == *(ushf*)(match += 2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window + strstart + 257 */ - Assert(scan <= s->window + (unsigned)(s->window_size - 1), - "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend - scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len - 1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len - 1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart + 258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window + (unsigned)(s->window_size - 1), - "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan + best_len - 1); -#else - scan_end1 = scan[best_len - 1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; -} - -#else /* FASTEST */ - -/* --------------------------------------------------------------------------- - * Optimized version for FASTEST only - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "need lookahead"); - - Assert(cur_match < s->strstart, "no future"); - - match = s->window + cur_match; - - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - - /* The check at best_len - 1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart + 258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - - if (len < MIN_MATCH) return MIN_MATCH - 1; - - s->match_start = cur_match; - return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; -} - -#endif /* FASTEST */ - -#ifdef ZLIB_DEBUG - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start - match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* ZLIB_DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - unsigned n; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize + MAX_DIST(s)) { - - zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - if (s->insert > s->strstart) - s->insert = s->strstart; - slide_hash(s); - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { - uInt str = s->strstart - s->insert; - s->ins_h = s->window[str]; - UPDATE_HASH(s, s->ins_h, s->window[str + 1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - while (s->insert) { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) - break; - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - ulg curr = s->strstart + (ulg)(s->lookahead); - ulg init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (ulg)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (ulg)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, last) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (last)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, last) { \ - FLUSH_BLOCK_ONLY(s, last); \ - if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ -} - -/* Maximum stored block length in deflate format (not including header). */ -#define MAX_STORED 65535 - -/* Minimum of a and b. */ -#define MIN(a, b) ((a) > (b) ? (b) : (a)) - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * - * In case deflateParams() is used to later switch to a non-zero compression - * level, s->matches (otherwise unused when storing) keeps track of the number - * of hash table slides to perform. If s->matches is 1, then one hash table - * slide will be done when switching. If s->matches is 2, the maximum value - * allowed here, then the hash table will be cleared, since two or more slides - * is the same as a clear. - * - * deflate_stored() is written to minimize the number of times an input byte is - * copied. It is most efficient with large input and output buffers, which - * maximizes the opportunities to have a single copy from next_in to next_out. - */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ - /* Smallest worthy block size when not flushing or finishing. By default - * this is 32K. This can be as small as 507 bytes for memLevel == 1. For - * large input and output buffers, the stored block size will be larger. - */ - unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); - - /* Copy as many min_block or larger stored blocks directly to next_out as - * possible. If flushing, copy the remaining available input to next_out as - * stored blocks, if there is enough space. - */ - unsigned len, left, have, last = 0; - unsigned used = s->strm->avail_in; - do { - /* Set len to the maximum size block that we can copy directly with the - * available input data and output space. Set left to how much of that - * would be copied from what's left in the window. - */ - len = MAX_STORED; /* maximum deflate stored block length */ - have = (s->bi_valid + 42) >> 3; /* number of header bytes */ - if (s->strm->avail_out < have) /* need room for header */ - break; - /* maximum stored block length that will fit in avail_out: */ - have = s->strm->avail_out - have; - left = s->strstart - s->block_start; /* bytes left in window */ - if (len > (ulg)left + s->strm->avail_in) - len = left + s->strm->avail_in; /* limit len to the input */ - if (len > have) - len = have; /* limit len to the output */ - - /* If the stored block would be less than min_block in length, or if - * unable to copy all of the available input when flushing, then try - * copying to the window and the pending buffer instead. Also don't - * write an empty block when flushing -- deflate() does that. - */ - if (len < min_block && ((len == 0 && flush != Z_FINISH) || - flush == Z_NO_FLUSH || - len != left + s->strm->avail_in)) - break; - - /* Make a dummy stored block in pending to get the header bytes, - * including any pending bits. This also updates the debugging counts. - */ - last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; - _tr_stored_block(s, (char *)0, 0L, last); - - /* Replace the lengths in the dummy stored block with len. */ - s->pending_buf[s->pending - 4] = len; - s->pending_buf[s->pending - 3] = len >> 8; - s->pending_buf[s->pending - 2] = ~len; - s->pending_buf[s->pending - 1] = ~len >> 8; - - /* Write the stored block header bytes. */ - flush_pending(s->strm); - -#ifdef ZLIB_DEBUG - /* Update debugging counts for the data about to be copied. */ - s->compressed_len += len << 3; - s->bits_sent += len << 3; -#endif - - /* Copy uncompressed bytes from the window to next_out. */ - if (left) { - if (left > len) - left = len; - zmemcpy(s->strm->next_out, s->window + s->block_start, left); - s->strm->next_out += left; - s->strm->avail_out -= left; - s->strm->total_out += left; - s->block_start += left; - len -= left; - } - - /* Copy uncompressed bytes directly from next_in to next_out, updating - * the check value. - */ - if (len) { - read_buf(s->strm, s->strm->next_out, len); - s->strm->next_out += len; - s->strm->avail_out -= len; - s->strm->total_out += len; - } - } while (last == 0); - - /* Update the sliding window with the last s->w_size bytes of the copied - * data, or append all of the copied data to the existing window if less - * than s->w_size bytes were copied. Also update the number of bytes to - * insert in the hash tables, in the event that deflateParams() switches to - * a non-zero compression level. - */ - used -= s->strm->avail_in; /* number of input bytes directly copied */ - if (used) { - /* If any input was used, then no unused input remains in the window, - * therefore s->block_start == s->strstart. - */ - if (used >= s->w_size) { /* supplant the previous history */ - s->matches = 2; /* clear hash */ - zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); - s->strstart = s->w_size; - s->insert = s->strstart; - } - else { - if (s->window_size - s->strstart <= used) { - /* Slide the window down. */ - s->strstart -= s->w_size; - zmemcpy(s->window, s->window + s->w_size, s->strstart); - if (s->matches < 2) - s->matches++; /* add a pending slide_hash() */ - if (s->insert > s->strstart) - s->insert = s->strstart; - } - zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); - s->strstart += used; - s->insert += MIN(used, s->w_size - s->insert); - } - s->block_start = s->strstart; - } - if (s->high_water < s->strstart) - s->high_water = s->strstart; - - /* If the last block was written to next_out, then done. */ - if (last) - return finish_done; - - /* If flushing and all input has been consumed, then done. */ - if (flush != Z_NO_FLUSH && flush != Z_FINISH && - s->strm->avail_in == 0 && (long)s->strstart == s->block_start) - return block_done; - - /* Fill the window with any remaining input. */ - have = s->window_size - s->strstart; - if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { - /* Slide the window down. */ - s->block_start -= s->w_size; - s->strstart -= s->w_size; - zmemcpy(s->window, s->window + s->w_size, s->strstart); - if (s->matches < 2) - s->matches++; /* add a pending slide_hash() */ - have += s->w_size; /* more space now */ - if (s->insert > s->strstart) - s->insert = s->strstart; - } - if (have > s->strm->avail_in) - have = s->strm->avail_in; - if (have) { - read_buf(s->strm, s->window + s->strstart, have); - s->strstart += have; - s->insert += MIN(have, s->w_size - s->insert); - } - if (s->high_water < s->strstart) - s->high_water = s->strstart; - - /* There was not enough avail_out to write a complete worthy or flushed - * stored block to next_out. Write a stored block to pending instead, if we - * have enough input for a worthy block, or if flushing and there is enough - * room for the remaining input as a stored block in the pending buffer. - */ - have = (s->bi_valid + 42) >> 3; /* number of header bytes */ - /* maximum stored block length that will fit in pending: */ - have = MIN(s->pending_buf_size - have, MAX_STORED); - min_block = MIN(have, s->w_size); - left = s->strstart - s->block_start; - if (left >= min_block || - ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && - s->strm->avail_in == 0 && left <= have)) { - len = MIN(left, have); - last = flush == Z_FINISH && s->strm->avail_in == 0 && - len == left ? 1 : 0; - _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); - s->block_start += len; - flush_pending(s->strm); - } - - /* We've done all we can with the available input and output. */ - return last ? finish_started : need_more; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart + 2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ -#ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else -#endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit(s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->sym_next) - FLUSH_BLOCK(s, 0); - return block_done; -} - -#ifndef FASTEST -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart + 2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED -#if TOO_FAR <= 32767 - || (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR) -#endif - )) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart - 1, s->prev_match, s->prev_length); - - _tr_tally_dist(s, s->strstart - 1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); - - /* Insert in hash table all strings up to the end of the match. - * strstart - 1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length - 1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart - 1])); - _tr_tally_lit(s, s->window[s->strstart - 1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart - 1])); - _tr_tally_lit(s, s->window[s->strstart - 1], bflush); - s->match_available = 0; - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->sym_next) - FLUSH_BLOCK(s, 0); - return block_done; -} -#endif /* FASTEST */ - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -local block_state deflate_rle(s, flush) - deflate_state *s; - int flush; -{ - int bflush; /* set if current block must be flushed */ - uInt prev; /* byte at distance one to match */ - Bytef *scan, *strend; /* scan goes up to strend for length of run */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s->lookahead <= MAX_MATCH) { - fill_window(s); - if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s->match_length = 0; - if (s->lookahead >= MIN_MATCH && s->strstart > 0) { - scan = s->window + s->strstart - 1; - prev = *scan; - if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + MAX_MATCH; - do { - } while (prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - scan < strend); - s->match_length = MAX_MATCH - (uInt)(strend - scan); - if (s->match_length > s->lookahead) - s->match_length = s->lookahead; - } - Assert(scan <= s->window + (uInt)(s->window_size - 1), - "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, s->match_length); - - _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - s->strstart += s->match_length; - s->match_length = 0; - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit(s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->sym_next) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -local block_state deflate_huff(s, flush) - deflate_state *s; - int flush; -{ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s->lookahead == 0) { - fill_window(s); - if (s->lookahead == 0) { - if (flush == Z_NO_FLUSH) - return need_more; - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s->match_length = 0; - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit(s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->sym_next) - FLUSH_BLOCK(s, 0); - return block_done; -} diff --git a/libraries/zlib/deflate.h b/libraries/zlib/deflate.h deleted file mode 100644 index 1a06cd5f25..0000000000 --- a/libraries/zlib/deflate.h +++ /dev/null @@ -1,346 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2018 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef DEFLATE_H -#define DEFLATE_H - -#include "zutil.h" - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer creation by deflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip encoding - should be left enabled. */ -#ifndef NO_GZIP -# define GZIP -#endif - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define Buf_size 16 -/* size of bit buffer in bi_buf */ - -#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ -#ifdef GZIP -# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ -#endif -#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ -#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ -#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ -#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ -#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ -#define FINISH_STATE 666 /* stream complete */ -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - const static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - ulg pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - gz_headerp gzhead; /* gzip header information to write */ - ulg gzindex; /* where in extra, name, or comment */ - Byte method; /* can only be DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to suppress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *sym_buf; /* buffer for distances and literals/lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt sym_next; /* running index in sym_buf */ - uInt sym_end; /* symbol table full when sym_next reaches this */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - uInt insert; /* bytes at end of window left to insert */ - -#ifdef ZLIB_DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - ulg high_water; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - -#define WIN_INIT MAX_MATCH -/* Number of bytes after end of data in window to initialize in order to avoid - memory checker errors from longest match routines */ - - /* in trees.c */ -void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); -int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); -void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -#ifndef ZLIB_DEBUG -/* Inline versions of _tr_tally for speed: */ - -#if defined(GEN_TREES_H) || !defined(STDC) - extern uch ZLIB_INTERNAL _length_code[]; - extern uch ZLIB_INTERNAL _dist_code[]; -#else - extern const uch ZLIB_INTERNAL _length_code[]; - extern const uch ZLIB_INTERNAL _dist_code[]; -#endif - -# define _tr_tally_lit(s, c, flush) \ - { uch cc = (c); \ - s->sym_buf[s->sym_next++] = 0; \ - s->sym_buf[s->sym_next++] = 0; \ - s->sym_buf[s->sym_next++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->sym_next == s->sym_end); \ - } -# define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (uch)(length); \ - ush dist = (ush)(distance); \ - s->sym_buf[s->sym_next++] = (uch)dist; \ - s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \ - s->sym_buf[s->sym_next++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->sym_next == s->sym_end); \ - } -#else -# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -# define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) -#endif - -#endif /* DEFLATE_H */ diff --git a/libraries/zlib/example.c b/libraries/zlib/example.c deleted file mode 100644 index 604736f15f..0000000000 --- a/libraries/zlib/example.c +++ /dev/null @@ -1,565 +0,0 @@ -/* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-2006 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zlib.h" -#include - -#ifdef STDC -# include -# include -#endif - -#if defined(VMS) || defined(RISCOS) -# define TESTFILE "foo-gz" -#else -# define TESTFILE "foo.gz" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -const char hello[] = "hello, hello!"; -/* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - */ - -const char dictionary[] = "hello"; -uLong dictId; /* Adler32 value of the dictionary */ - -void test_compress OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_gzio OF((const char *fname, - Byte *uncompr, uLong uncomprLen)); -void test_deflate OF((Byte *compr, uLong comprLen)); -void test_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_deflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_flush OF((Byte *compr, uLong *comprLen)); -void test_sync OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_dict_deflate OF((Byte *compr, uLong comprLen)); -void test_dict_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -int main OF((int argc, char *argv[])); - -/* =========================================================================== - * Test compress() and uncompress() - */ -void test_compress(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - uLong len = (uLong)strlen(hello)+1; - - err = compress(compr, &comprLen, (const Bytef*)hello, len); - CHECK_ERR(err, "compress"); - - strcpy((char*)uncompr, "garbage"); - - err = uncompress(uncompr, &uncomprLen, compr, comprLen); - CHECK_ERR(err, "uncompress"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad uncompress\n"); - exit(1); - } else { - printf("uncompress(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test read/write of .gz files - */ -void test_gzio(fname, uncompr, uncomprLen) - const char *fname; /* compressed file name */ - Byte *uncompr; - uLong uncomprLen; -{ -#ifdef NO_GZCOMPRESS - fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); -#else - int err; - int len = (int)strlen(hello)+1; - gzFile file; - z_off_t pos; - - file = gzopen(fname, "wb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - gzputc(file, 'h'); - if (gzputs(file, "ello") != 4) { - fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); - exit(1); - } - if (gzprintf(file, ", %s!", "hello") != 8) { - fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); - exit(1); - } - gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ - gzclose(file); - - file = gzopen(fname, "rb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - strcpy((char*)uncompr, "garbage"); - - if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { - fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); - exit(1); - } else { - printf("gzread(): %s\n", (char*)uncompr); - } - - pos = gzseek(file, -8L, SEEK_CUR); - if (pos != 6 || gztell(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)gztell(file)); - exit(1); - } - - if (gzgetc(file) != ' ') { - fprintf(stderr, "gzgetc error\n"); - exit(1); - } - - if (gzungetc(' ', file) != ' ') { - fprintf(stderr, "gzungetc error\n"); - exit(1); - } - - gzgets(file, (char*)uncompr, (int)uncomprLen); - if (strlen((char*)uncompr) != 7) { /* " hello!" */ - fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello + 6)) { - fprintf(stderr, "bad gzgets after gzseek\n"); - exit(1); - } else { - printf("gzgets() after gzseek: %s\n", (char*)uncompr); - } - - gzclose(file); -#endif -} - -/* =========================================================================== - * Test deflate() with small buffers - */ -void test_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uLong len = (uLong)strlen(hello)+1; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (Bytef*)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = deflate(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with small buffers - */ -void test_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 0; - d_stream.next_out = uncompr; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { - d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } else { - printf("inflate(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test deflate() with large buffers and dynamic change of compression level - */ -void test_large_deflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_SPEED); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - /* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - */ - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } - - /* Feed in already compressed data and switch to no compression: */ - deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in = compr; - c_stream.avail_in = (uInt)comprLen/2; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - /* Switch back to compressing mode: */ - deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with large buffers - */ -void test_large_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - for (;;) { - d_stream.next_out = uncompr; /* discard the output */ - d_stream.avail_out = (uInt)uncomprLen; - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "large inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (d_stream.total_out != 2*uncomprLen + comprLen/2) { - fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); - exit(1); - } else { - printf("large_inflate(): OK\n"); - } -} - -/* =========================================================================== - * Test deflate() with full flush - */ -void test_flush(compr, comprLen) - Byte *compr; - uLong *comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uInt len = (uInt)strlen(hello)+1; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (Bytef*)hello; - c_stream.next_out = compr; - c_stream.avail_in = 3; - c_stream.avail_out = (uInt)*comprLen; - err = deflate(&c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, "deflate"); - - compr[3]++; /* force an error in first compressed block */ - c_stream.avail_in = len - 3; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - CHECK_ERR(err, "deflate"); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - *comprLen = c_stream.total_out; -} - -/* =========================================================================== - * Test inflateSync() - */ -void test_sync(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 2; /* just read the zlib header */ - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - inflate(&d_stream, Z_NO_FLUSH); - CHECK_ERR(err, "inflate"); - - d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ - err = inflateSync(&d_stream); /* but skip the damaged part */ - CHECK_ERR(err, "inflateSync"); - - err = inflate(&d_stream, Z_FINISH); - if (err != Z_DATA_ERROR) { - fprintf(stderr, "inflate should report DATA_ERROR\n"); - /* Because of incorrect adler32 */ - exit(1); - } - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - printf("after inflateSync(): hel%s\n", (char *)uncompr); -} - -/* =========================================================================== - * Test deflate() with preset dictionary - */ -void test_dict_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - err = deflateSetDictionary(&c_stream, - (const Bytef*)dictionary, sizeof(dictionary)); - CHECK_ERR(err, "deflateSetDictionary"); - - dictId = c_stream.adler; - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - c_stream.next_in = (Bytef*)hello; - c_stream.avail_in = (uInt)strlen(hello)+1; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with a preset dictionary - */ -void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - for (;;) { - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } - err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, - sizeof(dictionary)); - } - CHECK_ERR(err, "inflate with dict"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } else { - printf("inflate with dictionary: %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Usage: example [output.gz [input.gz]] - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - Byte *compr, *uncompr; - uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - uLong uncomprLen = comprLen; - static const char* myVersion = ZLIB_VERSION; - - if (zlibVersion()[0] != myVersion[0]) { - fprintf(stderr, "incompatible zlib version\n"); - exit(1); - - } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { - fprintf(stderr, "warning: different zlib version\n"); - } - - printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", - ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); - - compr = (Byte*)calloc((uInt)comprLen, 1); - uncompr = (Byte*)calloc((uInt)uncomprLen, 1); - /* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - */ - if (compr == Z_NULL || uncompr == Z_NULL) { - printf("out of memory\n"); - exit(1); - } - test_compress(compr, comprLen, uncompr, uncomprLen); - - test_gzio((argc > 1 ? argv[1] : TESTFILE), - uncompr, uncomprLen); - - test_deflate(compr, comprLen); - test_inflate(compr, comprLen, uncompr, uncomprLen); - - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - - test_flush(compr, &comprLen); - test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; - - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - return 0; -} diff --git a/libraries/zlib/gzguts.h b/libraries/zlib/gzguts.h deleted file mode 100644 index 57faf37165..0000000000 --- a/libraries/zlib/gzguts.h +++ /dev/null @@ -1,219 +0,0 @@ -/* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004-2019 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef _LARGEFILE64_SOURCE -# ifndef _LARGEFILE_SOURCE -# define _LARGEFILE_SOURCE 1 -# endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif -#endif - -#ifdef HAVE_HIDDEN -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include -#include "zlib.h" -#ifdef STDC -# include -# include -# include -#endif - -#ifndef _POSIX_SOURCE -# define _POSIX_SOURCE -#endif -#include - -#ifdef _WIN32 -# include -#endif - -#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) -# include -#endif - -#if defined(_WIN32) -# define WIDECHAR -#endif - -#ifdef WINAPI_FAMILY -# define open _open -# define read _read -# define write _write -# define close _close -#endif - -#ifdef NO_DEFLATE /* for compatibility with old definition */ -# define NO_GZCOMPRESS -#endif - -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS -/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 -/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -# ifdef VMS -# define NO_vsnprintf -# endif -# ifdef __OS400__ -# define NO_vsnprintf -# endif -# ifdef __MVS__ -# define NO_vsnprintf -# endif -#endif - -/* unlike snprintf (which is required in C99), _snprintf does not guarantee - null termination of the result -- however this is only used in gzlib.c where - the result is assured to fit in the space provided */ -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define snprintf _snprintf -#endif - -#ifndef local -# define local static -#endif -/* since "static" is used to mean two completely different things in C, we - define "local" for the non-static meaning of "static", for readability - (compile with -Dlocal if your debugger can't find static symbols) */ - -/* gz* functions always use library allocation functions */ -#ifndef STDC - extern voidp malloc OF((uInt size)); - extern void free OF((voidpf ptr)); -#endif - -/* get errno and strerror definition */ -#if defined UNDER_CE -# include -# define zstrerror() gz_strwinerror((DWORD)GetLastError()) -#else -# ifndef NO_STRERROR -# include -# define zstrerror() strerror(errno) -# else -# define zstrerror() "stdio error (consult errno)" -# endif -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); -#endif - -/* default memLevel */ -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif - -/* default i/o buffer size -- double this for output when reading (this and - twice this must be able to fit in an unsigned type) */ -#define GZBUFSIZE 8192 - -/* gzip modes, also provide a little integrity check on the passed structure */ -#define GZ_NONE 0 -#define GZ_READ 7247 -#define GZ_WRITE 31153 -#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ - -/* values for gz_state how */ -#define LOOK 0 /* look for a gzip header */ -#define COPY 1 /* copy input directly */ -#define GZIP 2 /* decompress a gzip stream */ - -/* internal gzip file state data structure */ -typedef struct { - /* exposed contents for gzgetc() macro */ - struct gzFile_s x; /* "x" for exposed */ - /* x.have: number of bytes available at x.next */ - /* x.next: next output data to deliver or write */ - /* x.pos: current position in uncompressed data */ - /* used for both reading and writing */ - int mode; /* see gzip modes above */ - int fd; /* file descriptor */ - char *path; /* path or fd for error messages */ - unsigned size; /* buffer size, zero if not allocated yet */ - unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer (double-sized when writing) */ - unsigned char *out; /* output buffer (double-sized when reading) */ - int direct; /* 0 if processing gzip, 1 if transparent */ - /* just for reading */ - int how; /* 0: get header, 1: copy, 2: decompress */ - z_off64_t start; /* where the gzip data started, for rewinding */ - int eof; /* true if end of input file reached */ - int past; /* true if read requested past end */ - /* just for writing */ - int level; /* compression level */ - int strategy; /* compression strategy */ - int reset; /* true if a reset is pending after a Z_FINISH */ - /* seek request */ - z_off64_t skip; /* amount to skip (already rewound if backwards) */ - int seek; /* true if seek request pending */ - /* error information */ - int err; /* error code */ - char *msg; /* error message */ - /* zlib inflate or deflate stream */ - z_stream strm; /* stream structure in-place (not a pointer) */ -} gz_state; -typedef gz_state FAR *gz_statep; - -/* shared functions */ -void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); -#if defined UNDER_CE -char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); -#endif - -/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t - value -- needed when comparing unsigned to z_off64_t, which is signed - (possible z_off64_t types off_t, off64_t, and long are all signed) */ -#ifdef INT_MAX -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) -#else -unsigned ZLIB_INTERNAL gz_intmax OF((void)); -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) -#endif diff --git a/libraries/zlib/infback.c b/libraries/zlib/infback.c deleted file mode 100644 index babeaf1806..0000000000 --- a/libraries/zlib/infback.c +++ /dev/null @@ -1,644 +0,0 @@ -/* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2022 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - inflate_fast() can be used with either inflate.c or infback.c. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - windowBits is in the range 8..15, and window is a user-supplied - window and output buffer that is 2**windowBits bytes. - */ -int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) -z_streamp strm; -int windowBits; -unsigned char FAR *window; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL || - windowBits < 8 || windowBits > 15) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->dmax = 32768U; - state->wbits = (uInt)windowBits; - state->wsize = 1U << windowBits; - state->window = window; - state->wnext = 0; - state->whave = 0; - state->sane = 1; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -/* Macros for inflateBack(): */ - -/* Load returned state from inflate_fast() */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Set state from registers for inflate_fast() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = state->window; \ - left = state->wsize; \ - state->whave = left; \ - if (out(out_desc, put, left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) -z_streamp strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - state->mode = TYPE; - state->last = 0; - state->whave = 0; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = state->window; - left = state->wsize; - - /* Inflate until end of block marked as last */ - for (;;) - switch (state->mode) { - case TYPE: - /* determine and dispatch block type */ - if (state->last) { - BYTEBITS(); - state->mode = DONE; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - - /* copy stored block from input to output */ - while (state->length != 0) { - copy = state->length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - /* fallthrough */ - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= 6 && left >= 258) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - inflate_fast(strm, state->wsize); - LOAD(); - break; - } - - /* get a literal, length, or end-of-block code */ - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - state->length = (unsigned)here.val; - - /* process literal */ - if (here.op == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - ROOM(); - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - - /* get distance code */ - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - - /* get distance extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } - if (state->offset > state->wsize - (state->whave < state->wsize ? - left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = state->wsize - state->offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - state->offset; - copy = left; - } - if (copy > state->length) copy = state->length; - state->length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (state->length != 0); - break; - - case DONE: - /* inflate stream terminated properly */ - ret = Z_STREAM_END; - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: - /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Write leftover output and return unused input */ - inf_leave: - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left) && - ret == Z_STREAM_END) - ret = Z_BUF_ERROR; - } - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBackEnd(strm) -z_streamp strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/libraries/zlib/inffast.c b/libraries/zlib/inffast.c deleted file mode 100644 index 1fec7f363f..0000000000 --- a/libraries/zlib/inffast.c +++ /dev/null @@ -1,323 +0,0 @@ -/* inffast.c -- fast decoding - * Copyright (C) 1995-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef ASMINF -# pragma message("Assembler code may have bugs -- use at your own risk") -#else - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void ZLIB_INTERNAL inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *in; /* local strm->next_in */ - z_const unsigned char FAR *last; /* have enough input while in < last */ - unsigned char FAR *out; /* local strm->next_out */ - unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ - unsigned char FAR *end; /* while out < end, enough space available */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ - unsigned long hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const FAR *lcode; /* local strm->lencode */ - code const FAR *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - code const *here; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char FAR *from; /* where to copy match from */ - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - in = strm->next_in; - last = in + (strm->avail_in - 5); - out = strm->next_out; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - wnext = state->wnext; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - here = lcode + (hold & lmask); - dolen: - op = (unsigned)(here->bits); - hold >>= op; - bits -= op; - op = (unsigned)(here->op); - if (op == 0) { /* literal */ - Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here->val)); - *out++ = (unsigned char)(here->val); - } - else if (op & 16) { /* length base */ - len = (unsigned)(here->val); - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - len += (unsigned)hold & ((1U << op) - 1); - hold >>= op; - bits -= op; - } - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - here = dcode + (hold & dmask); - dodist: - op = (unsigned)(here->bits); - hold >>= op; - bits -= op; - op = (unsigned)(here->op); - if (op & 16) { /* distance base */ - dist = (unsigned)(here->val); - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - } - dist += (unsigned)hold & ((1U << op) - 1); -#ifdef INFLATE_STRICT - if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - hold >>= op; - bits -= op; - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state->sane) { - strm->msg = - (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (len <= op - whave) { - do { - *out++ = 0; - } while (--len); - continue; - } - len -= op - whave; - do { - *out++ = 0; - } while (--op > whave); - if (op == 0) { - from = out - dist; - do { - *out++ = *from++; - } while (--len); - continue; - } -#endif - } - from = window; - if (wnext == 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = window; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - while (len > 2) { - *out++ = *from++; - *out++ = *from++; - *out++ = *from++; - len -= 3; - } - if (len) { - *out++ = *from++; - if (len > 1) - *out++ = *from++; - } - } - else { - from = out - dist; /* copy direct from output */ - do { /* minimum length is three */ - *out++ = *from++; - *out++ = *from++; - *out++ = *from++; - len -= 3; - } while (len > 2); - if (len) { - *out++ = *from++; - if (len > 1) - *out++ = *from++; - } - } - } - else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode + here->val + (hold & ((1U << op) - 1)); - goto dodist; - } - else { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - } - else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode + here->val + (hold & ((1U << op) - 1)); - goto dolen; - } - else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - else { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (1U << bits) - 1; - - /* update state and return */ - strm->next_in = in; - strm->next_out = out; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); - strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); - state->hold = hold; - state->bits = bits; - return; -} - -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and wnext == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ - -#endif /* !ASMINF */ diff --git a/libraries/zlib/inffast.h b/libraries/zlib/inffast.h deleted file mode 100644 index e5c1aa4ca8..0000000000 --- a/libraries/zlib/inffast.h +++ /dev/null @@ -1,11 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/libraries/zlib/inffixed.h b/libraries/zlib/inffixed.h deleted file mode 100644 index d628327769..0000000000 --- a/libraries/zlib/inffixed.h +++ /dev/null @@ -1,94 +0,0 @@ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - - /* WARNING: this file should *not* be used by applications. - It is part of the implementation of this library and is - subject to change. Applications should only use zlib.h. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; diff --git a/libraries/zlib/inflate.c b/libraries/zlib/inflate.c deleted file mode 100644 index 8acbef44e9..0000000000 --- a/libraries/zlib/inflate.c +++ /dev/null @@ -1,1595 +0,0 @@ -/* inflate.c -- zlib decompression - * Copyright (C) 1995-2022 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * Change history: - * - * 1.2.beta0 24 Nov 2002 - * - First version -- complete rewrite of inflate to simplify code, avoid - * creation of window when not needed, minimize use of window when it is - * needed, make inffast.c even faster, implement gzip decoding, and to - * improve code readability and style over the previous zlib inflate code - * - * 1.2.beta1 25 Nov 2002 - * - Use pointers for available input and output checking in inffast.c - * - Remove input and output counters in inffast.c - * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 - * - Remove unnecessary second byte pull from length extra in inffast.c - * - Unroll direct copy to three copies per loop in inffast.c - * - * 1.2.beta2 4 Dec 2002 - * - Change external routine names to reduce potential conflicts - * - Correct filename to inffixed.h for fixed tables in inflate.c - * - Make hbuf[] unsigned char to match parameter type in inflate.c - * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) - * to avoid negation problem on Alphas (64 bit) in inflate.c - * - * 1.2.beta3 22 Dec 2002 - * - Add comments on state->bits assertion in inffast.c - * - Add comments on op field in inftrees.h - * - Fix bug in reuse of allocated window after inflateReset() - * - Remove bit fields--back to byte structure for speed - * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths - * - Change post-increments to pre-increments in inflate_fast(), PPC biased? - * - Add compile time option, POSTINC, to use post-increments instead (Intel?) - * - Make MATCH copy in inflate() much faster for when inflate_fast() not used - * - Use local copies of stream next and avail values, as well as local bit - * buffer and bit count in inflate()--for speed when inflate_fast() not used - * - * 1.2.beta4 1 Jan 2003 - * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings - * - Move a comment on output buffer sizes from inffast.c to inflate.c - * - Add comments in inffast.c to introduce the inflate_fast() routine - * - Rearrange window copies in inflate_fast() for speed and simplification - * - Unroll last copy for window match in inflate_fast() - * - Use local copies of window variables in inflate_fast() for speed - * - Pull out common wnext == 0 case for speed in inflate_fast() - * - Make op and len in inflate_fast() unsigned for consistency - * - Add FAR to lcode and dcode declarations in inflate_fast() - * - Simplified bad distance check in inflate_fast() - * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new - * source file infback.c to provide a call-back interface to inflate for - * programs like gzip and unzip -- uses window as output buffer to avoid - * window copying - * - * 1.2.beta5 1 Jan 2003 - * - Improved inflateBack() interface to allow the caller to provide initial - * input in strm. - * - Fixed stored blocks bug in inflateBack() - * - * 1.2.beta6 4 Jan 2003 - * - Added comments in inffast.c on effectiveness of POSTINC - * - Typecasting all around to reduce compiler warnings - * - Changed loops from while (1) or do {} while (1) to for (;;), again to - * make compilers happy - * - Changed type of window in inflateBackInit() to unsigned char * - * - * 1.2.beta7 27 Jan 2003 - * - Changed many types to unsigned or unsigned short to avoid warnings - * - Added inflateCopy() function - * - * 1.2.0 9 Mar 2003 - * - Changed inflateBack() interface to provide separate opaque descriptors - * for the in() and out() functions - * - Changed inflateBack() argument and in_func typedef to swap the length - * and buffer address return values for the input function - * - Check next_in and next_out for Z_NULL on entry to inflate() - * - * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef MAKEFIXED -# ifndef BUILDFIXED -# define BUILDFIXED -# endif -#endif - -/* function prototypes */ -local int inflateStateCheck OF((z_streamp strm)); -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, - unsigned copy)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, - unsigned len)); - -local int inflateStateCheck(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (strm == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) - return 1; - state = (struct inflate_state FAR *)strm->state; - if (state == Z_NULL || state->strm != strm || - state->mode < HEAD || state->mode > SYNC) - return 1; - return 0; -} - -int ZEXPORT inflateResetKeep(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = Z_NULL; - if (state->wrap) /* to support ill-conceived Java test suite */ - strm->adler = state->wrap & 1; - state->mode = HEAD; - state->last = 0; - state->havedict = 0; - state->flags = -1; - state->dmax = 32768U; - state->head = Z_NULL; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - state->sane = 1; - state->back = -1; - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int ZEXPORT inflateReset(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; - return inflateResetKeep(strm); -} - -int ZEXPORT inflateReset2(strm, windowBits) -z_streamp strm; -int windowBits; -{ - int wrap; - struct inflate_state FAR *state; - - /* get the state */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - if (windowBits < -15) - return Z_STREAM_ERROR; - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 5; -#ifdef GUNZIP - if (windowBits < 48) - windowBits &= 15; -#endif - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) - return Z_STREAM_ERROR; - if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { - ZFREE(strm, state->window); - state->window = Z_NULL; - } - - /* update state and reset the rest of it */ - state->wrap = wrap; - state->wbits = (unsigned)windowBits; - return inflateReset(strm); -} - -int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) -z_streamp strm; -int windowBits; -const char *version; -int stream_size; -{ - int ret; - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *) - ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->strm = strm; - state->window = Z_NULL; - state->mode = HEAD; /* to pass state test in inflateReset2() */ - ret = inflateReset2(strm, windowBits); - if (ret != Z_OK) { - ZFREE(strm, state); - strm->state = Z_NULL; - } - return ret; -} - -int ZEXPORT inflateInit_(strm, version, stream_size) -z_streamp strm; -const char *version; -int stream_size; -{ - return inflateInit2_(strm, DEF_WBITS, version, stream_size); -} - -int ZEXPORT inflatePrime(strm, bits, value) -z_streamp strm; -int bits; -int value; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (bits < 0) { - state->hold = 0; - state->bits = 0; - return Z_OK; - } - if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += (unsigned)value << state->bits; - state->bits += (uInt)bits; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -#ifdef MAKEFIXED -#include - -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ -void makefixed() -{ - unsigned low, size; - struct inflate_state state; - - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, - state.lencode[low].bits, state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -local int updatewindow(strm, end, copy) -z_streamp strm; -const Bytef *end; -unsigned copy; -{ - struct inflate_state FAR *state; - unsigned dist; - - state = (struct inflate_state FAR *)strm->state; - - /* if it hasn't been done already, allocate space for the window */ - if (state->window == Z_NULL) { - state->window = (unsigned char FAR *) - ZALLOC(strm, 1U << state->wbits, - sizeof(unsigned char)); - if (state->window == Z_NULL) return 1; - } - - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->wnext = 0; - state->whave = 0; - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state->wsize) { - zmemcpy(state->window, end - state->wsize, state->wsize); - state->wnext = 0; - state->whave = state->wsize; - } - else { - dist = state->wsize - state->wnext; - if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, end - copy, dist); - copy -= dist; - if (copy) { - zmemcpy(state->window, end - copy, copy); - state->wnext = copy; - state->whave = state->wsize; - } - else { - state->wnext += dist; - if (state->wnext == state->wsize) state->wnext = 0; - if (state->whave < state->wsize) state->whave += dist; - } - } - return 0; -} - -/* Macros for inflate(): */ - -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE_CHECK(check, buf, len) \ - (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) -#else -# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) -#endif - -/* check macros for header crc */ -#ifdef GUNZIP -# define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = crc32(check, hbuf, 2); \ - } while (0) - -# define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = crc32(check, hbuf, 4); \ - } while (0) -#endif - -/* Load registers with state in inflate() for speed */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Restore state from registers in inflate() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflate() - if there is no input available. */ -#define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate(). */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ - -int ZEXPORT inflate(strm, flush) -z_streamp strm; -int flush; -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ -#ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ -#endif - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - if (inflateStateCheck(strm) || strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; - - state = (struct inflate_state FAR *)strm->state; - if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); -#ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - if (state->wbits == 0) - state->wbits = 15; - state->check = crc32(0L, Z_NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - if (state->head != Z_NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ -#else - if ( -#endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; - state->mode = BAD; - break; - } - if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (state->wbits == 0) - state->wbits = len; - if (len > 15 || len > state->wbits) { - strm->msg = (char *)"invalid window size"; - state->mode = BAD; - break; - } - state->dmax = 1U << len; - state->flags = 0; /* indicate zlib header */ - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; -#ifdef GUNZIP - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; - state->mode = BAD; - break; - } - if (state->head != Z_NULL) - state->head->text = (int)((hold >> 8) & 1); - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - /* fallthrough */ - case TIME: - NEEDBITS(32); - if (state->head != Z_NULL) - state->head->time = hold; - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - /* fallthrough */ - case OS: - NEEDBITS(16); - if (state->head != Z_NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - /* fallthrough */ - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (unsigned)(hold); - if (state->head != Z_NULL) - state->head->extra_len = (unsigned)hold; - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - } - else if (state->head != Z_NULL) - state->head->extra = Z_NULL; - state->mode = EXTRA; - /* fallthrough */ - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) copy = have; - if (copy) { - if (state->head != Z_NULL && - state->head->extra != Z_NULL && - (len = state->head->extra_len - state->length) < - state->head->extra_max) { - zmemcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) goto inf_leave; - } - state->length = 0; - state->mode = NAME; - /* fallthrough */ - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->name != Z_NULL && - state->length < state->head->name_max) - state->head->name[state->length++] = (Bytef)len; - } while (len && copy < have); - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->name = Z_NULL; - state->length = 0; - state->mode = COMMENT; - /* fallthrough */ - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->comment != Z_NULL && - state->length < state->head->comm_max) - state->head->comment[state->length++] = (Bytef)len; - } while (len && copy < have); - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->comment = Z_NULL; - state->mode = HCRC; - /* fallthrough */ - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if ((state->wrap & 4) && hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; - state->mode = BAD; - break; - } - INITBITS(); - } - if (state->head != Z_NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = crc32(0L, Z_NULL, 0); - state->mode = TYPE; - break; -#endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = ZSWAP32(hold); - INITBITS(); - state->mode = DICT; - /* fallthrough */ - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = TYPE; - /* fallthrough */ - case TYPE: - if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; - /* fallthrough */ - case TYPEDO: - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN_; /* decode codes */ - if (flush == Z_TREES) { - DROPBITS(2); - goto inf_leave; - } - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - case STORED: - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - state->mode = COPY_; - if (flush == Z_TREES) goto inf_leave; - /* fallthrough */ - case COPY_: - state->mode = COPY; - /* fallthrough */ - case COPY: - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - case TABLE: - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - /* fallthrough */ - case LENLENS: - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (const code FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - /* fallthrough */ - case CODELENS: - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (const code FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (const code FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN_; - if (flush == Z_TREES) goto inf_leave; - /* fallthrough */ - case LEN_: - state->mode = LEN; - /* fallthrough */ - case LEN: - if (have >= 6 && left >= 258) { - RESTORE(); - inflate_fast(strm, out); - LOAD(); - if (state->mode == TYPE) - state->back = -1; - break; - } - state->back = 0; - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - state->length = (unsigned)here.val; - if ((int)(here.op) == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - state->mode = LIT; - break; - } - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->back = -1; - state->mode = TYPE; - break; - } - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - state->extra = (unsigned)(here.op) & 15; - state->mode = LENEXT; - /* fallthrough */ - case LENEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->was = state->length; - state->mode = DIST; - /* fallthrough */ - case DIST: - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - state->extra = (unsigned)(here.op) & 15; - state->mode = DISTEXT; - /* fallthrough */ - case DISTEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } -#ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - /* fallthrough */ - case MATCH: - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->whave) { - if (state->sane) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - Trace((stderr, "inflate.c too far\n")); - copy -= state->whave; - if (copy > state->length) copy = state->length; - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = 0; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; -#endif - } - if (copy > state->wnext) { - copy -= state->wnext; - from = state->window + (state->wsize - copy); - } - else - from = state->window + (state->wnext - copy); - if (copy > state->length) copy = state->length; - } - else { /* copy from output */ - from = put - state->offset; - copy = state->length; - } - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = *from++; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; - case LIT: - if (left == 0) goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if ((state->wrap & 4) && out) - strm->adler = state->check = - UPDATE_CHECK(state->check, put - out, out); - out = left; - if ((state->wrap & 4) && ( -#ifdef GUNZIP - state->flags ? hold : -#endif - ZSWAP32(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } -#ifdef GUNZIP - state->mode = LENGTH; - /* fallthrough */ - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { - strm->msg = (char *)"incorrect length check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } -#endif - state->mode = DONE; - /* fallthrough */ - case DONE: - ret = Z_STREAM_END; - goto inf_leave; - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - /* fallthrough */ - default: - return Z_STREAM_ERROR; - } - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - inf_leave: - RESTORE(); - if (state->wsize || (out != strm->avail_out && state->mode < BAD && - (state->mode < CHECK || flush != Z_FINISH))) - if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if ((state->wrap & 4) && out) - strm->adler = state->check = - UPDATE_CHECK(state->check, strm->next_out - out, out); - strm->data_type = (int)state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0) + - (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; -} - -int ZEXPORT inflateEnd(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->window != Z_NULL) ZFREE(strm, state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - -int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) -z_streamp strm; -Bytef *dictionary; -uInt *dictLength; -{ - struct inflate_state FAR *state; - - /* check state */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* copy dictionary */ - if (state->whave && dictionary != Z_NULL) { - zmemcpy(dictionary, state->window + state->wnext, - state->whave - state->wnext); - zmemcpy(dictionary + state->whave - state->wnext, - state->window, state->wnext); - } - if (dictLength != Z_NULL) - *dictLength = state->whave; - return Z_OK; -} - -int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) -z_streamp strm; -const Bytef *dictionary; -uInt dictLength; -{ - struct inflate_state FAR *state; - unsigned long dictid; - int ret; - - /* check state */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; - - /* check for correct dictionary identifier */ - if (state->mode == DICT) { - dictid = adler32(0L, Z_NULL, 0); - dictid = adler32(dictid, dictionary, dictLength); - if (dictid != state->check) - return Z_DATA_ERROR; - } - - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary + dictLength, dictLength); - if (ret) { - state->mode = MEM; - return Z_MEM_ERROR; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -int ZEXPORT inflateGetHeader(strm, head) -z_streamp strm; -gz_headerp head; -{ - struct inflate_state FAR *state; - - /* check state */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; - - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; -} - -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ -local unsigned syncsearch(have, buf, len) -unsigned FAR *have; -const unsigned char FAR *buf; -unsigned len; -{ - unsigned got; - unsigned next; - - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; -} - -int ZEXPORT inflateSync(strm) -z_streamp strm; -{ - unsigned len; /* number of bytes to look at or looked at */ - int flags; /* temporary to save header status */ - unsigned long in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state FAR *state; - - /* check parameters */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; - - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } - - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; - - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) return Z_DATA_ERROR; - if (state->flags == -1) - state->wrap = 0; /* if no header yet, treat as raw */ - else - state->wrap &= ~4; /* no point in computing a check value now */ - flags = state->flags; - in = strm->total_in; out = strm->total_out; - inflateReset(strm); - strm->total_in = in; strm->total_out = out; - state->flags = flags; - state->mode = TYPE; - return Z_OK; -} - -/* - Returns true if inflate is currently at the end of a block generated by - Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - implementation to provide an additional safety check. PPP uses - Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored - block. When decompressing, PPP checks that at the end of input packet, - inflate is waiting for these length bytes. - */ -int ZEXPORT inflateSyncPoint(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - return state->mode == STORED && state->bits == 0; -} - -int ZEXPORT inflateCopy(dest, source) -z_streamp dest; -z_streamp source; -{ - struct inflate_state FAR *state; - struct inflate_state FAR *copy; - unsigned char FAR *window; - unsigned wsize; - - /* check input */ - if (inflateStateCheck(source) || dest == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)source->state; - - /* allocate space */ - copy = (struct inflate_state FAR *) - ZALLOC(source, 1, sizeof(struct inflate_state)); - if (copy == Z_NULL) return Z_MEM_ERROR; - window = Z_NULL; - if (state->window != Z_NULL) { - window = (unsigned char FAR *) - ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == Z_NULL) { - ZFREE(source, copy); - return Z_MEM_ERROR; - } - } - - /* copy state */ - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); - copy->strm = dest; - if (state->lencode >= state->codes && - state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state FAR *)copy; - return Z_OK; -} - -int ZEXPORT inflateUndermine(strm, subvert) -z_streamp strm; -int subvert; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - state->sane = !subvert; - return Z_OK; -#else - (void)subvert; - state->sane = 1; - return Z_DATA_ERROR; -#endif -} - -int ZEXPORT inflateValidate(strm, check) -z_streamp strm; -int check; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (check && state->wrap) - state->wrap |= 4; - else - state->wrap &= ~4; - return Z_OK; -} - -long ZEXPORT inflateMark(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) - return -(1L << 16); - state = (struct inflate_state FAR *)strm->state; - return (long)(((unsigned long)((long)state->back)) << 16) + - (state->mode == COPY ? state->length : - (state->mode == MATCH ? state->was - state->length : 0)); -} - -unsigned long ZEXPORT inflateCodesUsed(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (inflateStateCheck(strm)) return (unsigned long)-1; - state = (struct inflate_state FAR *)strm->state; - return (unsigned long)(state->next - state->codes); -} diff --git a/libraries/zlib/inflate.h b/libraries/zlib/inflate.h deleted file mode 100644 index f127b6b1fa..0000000000 --- a/libraries/zlib/inflate.h +++ /dev/null @@ -1,126 +0,0 @@ -/* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2019 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer decoding by inflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip decoding - should be left enabled. */ -#ifndef NO_GZIP -# define GUNZIP -#endif - -/* Possible inflate modes between inflate() calls */ -typedef enum { - HEAD = 16180, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY_, /* i/o: same as COPY below, but only first time in */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN_, /* i: same as LEN below, but only first time in */ - LEN, /* i: waiting for length/lit/eob code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to BAD or MEM on error -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) or (raw) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> - HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - (raw) -> TYPEDO - Read deflate blocks: - TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK - STORED -> COPY_ -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN_ - LEN_ -> LEN - Read deflate codes in fixed or dynamic block: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* State maintained between inflate() calls -- approximately 7K bytes, not - including the allocated sliding window, which is up to 32K bytes. */ -struct inflate_state { - z_streamp strm; /* pointer back to this zlib stream */ - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip, - bit 2 true to validate check value */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags, 0 if zlib, or - -1 if raw or no header yet */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - gz_headerp head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - unsigned length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ - int sane; /* if false, allow invalid distance too far */ - int back; /* bits back of last unprocessed length/lit */ - unsigned was; /* initial length of match */ -}; diff --git a/libraries/zlib/inftrees.c b/libraries/zlib/inftrees.c deleted file mode 100644 index 57d2793bec..0000000000 --- a/libraries/zlib/inftrees.c +++ /dev/null @@ -1,304 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2022 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char inflate_copyright[] = - " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code here; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - unsigned match; /* use base and extra for symbol >= match */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0}; - static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)1; - here.val = (unsigned short)0; - *(*table)++ = here; /* make a table to force an error */ - *(*table)++ = here; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - match = 20; - break; - case LENS: - base = lbase; - extra = lext; - match = 257; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - match = 0; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here.bits = (unsigned char)(len - drop); - if (work[sym] + 1U < match) { - here.op = (unsigned char)0; - here.val = work[sym]; - } - else if (work[sym] >= match) { - here.op = (unsigned char)(extra[work[sym] - match]); - here.val = base[work[sym] - match]; - } - else { - here.op = (unsigned char)(32 + 64); /* end of block */ - here.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = here; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff != 0) { - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - next[huff] = here; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/libraries/zlib/inftrees.h b/libraries/zlib/inftrees.h deleted file mode 100644 index f53665311c..0000000000 --- a/libraries/zlib/inftrees.h +++ /dev/null @@ -1,62 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of the dynamic table. The maximum number of code structures is - 1444, which is the sum of 852 for literal/length codes and 592 for distance - codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribution. The arguments to that - program are the number of symbols, the initial root table size, and the - maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the - inflate_table() calls in inflate.c and infback.c. If the root table size is - changed, then these maximum sizes would be need to be recalculated and - updated. */ -#define ENOUGH_LENS 852 -#define ENOUGH_DISTS 592 -#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) - -/* Type of code to build for inflate_table() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/libraries/zlib/trees.c b/libraries/zlib/trees.c deleted file mode 100644 index 5f305c4722..0000000000 --- a/libraries/zlib/trees.c +++ /dev/null @@ -1,1181 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2021 Jean-loup Gailly - * detect_data_type() function provided freely by Cosmin Truta, 2006 - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id$ */ - -/* #define GEN_TREES_H */ - -#include "deflate.h" - -#ifdef ZLIB_DEBUG -# include -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local const uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local const static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local const static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local const static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, const ct_data *ltree, - const ct_data *dtree)); -local int detect_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned code, int len)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); - -#ifdef GEN_TREES_H -local void gen_trees_header OF((void)); -#endif - -#ifndef ZLIB_DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* !ZLIB_DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef ZLIB_DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (ush)value << s->bi_valid; - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= (ush)value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !ZLIB_DEBUG */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = (int)value;\ - s->bi_buf |= (ush)val << s->bi_valid;\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (ush)(value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* ZLIB_DEBUG */ - - -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -local void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ -#ifdef NO_INIT_GLOBAL_POINTERS - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; -#endif - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1 << extra_lbits[code]); n++) { - _length_code[length++] = (uch)code; - } - } - Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length - 1] = (uch)code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1 << extra_dbits[code]); n++) { - _dist_code[dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256 + dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Generate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef ZLIB_DEBUG -# include -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width) - 1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, - "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void ZLIB_INTERNAL _tr_init(s) - deflate_state *s; -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef ZLIB_DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->sym_next = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n - base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (unsigned)(bits + xbits); - if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); - } - if (overflow == 0) return; - - Tracev((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if ((unsigned) tree[m].Len != (unsigned) bits) { - Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes(tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - unsigned code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits - 1]) << 1; - next_code[bits] = (ush)code; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, - "inconsistent bit counts"); - Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].Len; - if (len == 0) continue; - /* Now reverse the bits */ - tree[n].Code = (ush)bi_reverse(next_code[len]++, len); - - Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", - n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1)); - } -} - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -local void build_tree(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree(s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code + 1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n + 1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree(s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code + 1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n + 1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except the - * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes - 1, 5); - send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */ - bi_windup(s); /* align on byte boundary */ - put_short(s, (ush)stored_len); - put_short(s, (ush)~stored_len); - if (stored_len) - zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); - s->pending += stored_len; -#ifdef ZLIB_DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; - s->bits_sent += 2*16; - s->bits_sent += stored_len << 3; -#endif -} - -/* =========================================================================== - * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) - */ -void ZLIB_INTERNAL _tr_flush_bits(s) - deflate_state *s; -{ - bi_flush(s); -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -void ZLIB_INTERNAL _tr_align(s) - deflate_state *s; -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef ZLIB_DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and write out the encoded block. - */ -void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is binary or text */ - if (s->strm->data_type == Z_UNKNOWN) - s->strm->data_type = detect_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len + 3 + 7) >> 3; - static_lenb = (s->static_len + 3 + 7) >> 3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->sym_next / 3)); - -#ifndef FORCE_STATIC - if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) -#endif - opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len + 4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - - } else if (static_lenb == opt_lenb) { - send_bits(s, (STATIC_TREES<<1) + last, 3); - compress_block(s, (const ct_data *)static_ltree, - (const ct_data *)static_dtree); -#ifdef ZLIB_DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1) + last, 3); - send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1, - max_blindex + 1); - compress_block(s, (const ct_data *)s->dyn_ltree, - (const ct_data *)s->dyn_dtree); -#ifdef ZLIB_DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); -#ifdef ZLIB_DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3, - s->compressed_len - 7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int ZLIB_INTERNAL _tr_tally(s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length - MIN_MATCH or unmatched char (dist==0) */ -{ - s->sym_buf[s->sym_next++] = (uch)dist; - s->sym_buf[s->sym_next++] = (uch)(dist >> 8); - s->sym_buf[s->sym_next++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - return (s->sym_next == s->sym_end); -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - const ct_data *ltree; /* literal tree */ - const ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned sx = 0; /* running index in sym_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->sym_next != 0) do { - dist = s->sym_buf[sx++] & 0xff; - dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; - lc = s->sym_buf[sx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= (unsigned)base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and sym_buf is ok: */ - Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); - - } while (sx < s->sym_next); - - send_code(s, END_BLOCK, ltree); -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "block list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local int detect_data_type(s) - deflate_state *s; -{ - /* block_mask is the bit mask of block-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long block_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("block-listed") bytes. */ - for (n = 0; n <= 31; n++, block_mask >>= 1) - if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("allow-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 - || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "block-listed" or "allow-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef ZLIB_DEBUG - s->bits_sent = (s->bits_sent + 7) & ~7; -#endif -} diff --git a/libraries/zlib/trees.h b/libraries/zlib/trees.h deleted file mode 100644 index d35639d82a..0000000000 --- a/libraries/zlib/trees.h +++ /dev/null @@ -1,128 +0,0 @@ -/* header created automatically with -DGEN_TREES_H */ - -local const ct_data static_ltree[L_CODES+2] = { -{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -}; - -local const ct_data static_dtree[D_CODES] = { -{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -}; - -const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -local const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - diff --git a/libraries/zlib/uncompr.c b/libraries/zlib/uncompr.c deleted file mode 100644 index f9532f46c1..0000000000 --- a/libraries/zlib/uncompr.c +++ /dev/null @@ -1,93 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. *sourceLen is - the byte length of the source buffer. Upon entry, *destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, - *destLen is the size of the decompressed data and *sourceLen is the number - of source bytes consumed. Upon return, source + *sourceLen points to the - first unused input byte. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, or - Z_DATA_ERROR if the input data was corrupted, including if the input data is - an incomplete zlib stream. -*/ -int ZEXPORT uncompress2(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong *sourceLen; -{ - z_stream stream; - int err; - const uInt max = (uInt)-1; - uLong len, left; - Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ - - len = *sourceLen; - if (*destLen) { - left = *destLen; - *destLen = 0; - } - else { - left = 1; - dest = buf; - } - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = 0; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - stream.next_out = dest; - stream.avail_out = 0; - - do { - if (stream.avail_out == 0) { - stream.avail_out = left > (uLong)max ? max : (uInt)left; - left -= stream.avail_out; - } - if (stream.avail_in == 0) { - stream.avail_in = len > (uLong)max ? max : (uInt)len; - len -= stream.avail_in; - } - err = inflate(&stream, Z_NO_FLUSH); - } while (err == Z_OK); - - *sourceLen -= len + stream.avail_in; - if (dest != buf) - *destLen = stream.total_out; - else if (stream.total_out && err == Z_BUF_ERROR) - left = 1; - - inflateEnd(&stream); - return err == Z_STREAM_END ? Z_OK : - err == Z_NEED_DICT ? Z_DATA_ERROR : - err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : - err; -} - -int ZEXPORT uncompress(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - return uncompress2(dest, destLen, source, &sourceLen); -} diff --git a/libraries/zlib/win32/zlib.def b/libraries/zlib/win32/zlib.def deleted file mode 100644 index 666bc6fbbb..0000000000 --- a/libraries/zlib/win32/zlib.def +++ /dev/null @@ -1,97 +0,0 @@ -; zlib data compression library -EXPORTS -; basic functions - zlibVersion - deflate - deflateEnd - inflate - inflateEnd -; advanced functions - deflateSetDictionary - deflateGetDictionary - deflateCopy - deflateReset - deflateParams - deflateTune - deflateBound - deflatePending - deflatePrime - deflateSetHeader - inflateSetDictionary - inflateGetDictionary - inflateSync - inflateCopy - inflateReset - inflateReset2 - inflatePrime - inflateMark - inflateGetHeader - inflateBack - inflateBackEnd - zlibCompileFlags -; utility functions - compress - compress2 - compressBound - uncompress - uncompress2 - gzopen - gzdopen - gzbuffer - gzsetparams - gzread - gzfread - gzwrite - gzfwrite - gzprintf - gzvprintf - gzputs - gzgets - gzputc - gzgetc - gzungetc - gzflush - gzseek - gzrewind - gztell - gzoffset - gzeof - gzdirect - gzclose - gzclose_r - gzclose_w - gzerror - gzclearerr -; large file functions - gzopen64 - gzseek64 - gztell64 - gzoffset64 - adler32_combine64 - crc32_combine64 - crc32_combine_gen64 -; checksum functions - adler32 - adler32_z - crc32 - crc32_z - adler32_combine - crc32_combine - crc32_combine_gen - crc32_combine_op -; various hacks, don't look :) - deflateInit_ - deflateInit2_ - inflateInit_ - inflateInit2_ - inflateBackInit_ - gzgetc_ - zError - inflateSyncPoint - get_crc_table - inflateUndermine - inflateValidate - inflateCodesUsed - inflateResetKeep - deflateResetKeep - gzopen_w diff --git a/libraries/zlib/win32/zlib1.rc b/libraries/zlib/win32/zlib1.rc deleted file mode 100644 index ceb4ee5c69..0000000000 --- a/libraries/zlib/win32/zlib1.rc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "../zlib.h" - -#ifdef GCC_WINDRES -VS_VERSION_INFO VERSIONINFO -#else -VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE -#endif - FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 - PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS 1 -#else - FILEFLAGS 0 -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - BEGIN - VALUE "FileDescription", "zlib data compression library\0" - VALUE "FileVersion", ZLIB_VERSION "\0" - VALUE "InternalName", "zlib1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2022 Jean-loup Gailly & Mark Adler\0" - VALUE "OriginalFilename", "zlib1.dll\0" - VALUE "ProductName", "zlib\0" - VALUE "ProductVersion", ZLIB_VERSION "\0" - VALUE "Comments", "For more information visit http://www.zlib.net/\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/libraries/zlib/zconf.h b/libraries/zlib/zconf.h deleted file mode 100644 index bf977d3e70..0000000000 --- a/libraries/zlib/zconf.h +++ /dev/null @@ -1,547 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols and init macros */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# define adler32_z z_adler32_z -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define crc32_combine_gen z_crc32_combine_gen -# define crc32_combine_gen64 z_crc32_combine_gen64 -# define crc32_combine_op z_crc32_combine_op -# define crc32_z z_crc32_z -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateGetDictionary z_deflateGetDictionary -# define deflateInit z_deflateInit -# define deflateInit2 z_deflateInit2 -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzfread z_gzfread -# define gzfwrite z_gzfwrite -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzvprintf z_gzvprintf -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit z_inflateBackInit -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCodesUsed z_inflateCodesUsed -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetDictionary z_inflateGetDictionary -# define inflateGetHeader z_inflateGetHeader -# define inflateInit z_inflateInit -# define inflateInit2 z_inflateInit2 -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateResetKeep z_inflateResetKeep -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateValidate z_inflateValidate -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# define uncompress2 z_uncompress2 -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -#ifdef Z_SOLO - typedef unsigned long z_size_t; -#else -# define z_longlong long long -# if defined(NO_SIZE_T) - typedef unsigned NO_SIZE_T z_size_t; -# elif defined(STDC) -# include - typedef size_t z_size_t; -# else - typedef unsigned long z_size_t; -# endif -# undef z_longlong -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus about 7 kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include /* for wchar_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#ifndef Z_HAVE_UNISTD_H -# ifdef __WATCOMC__ -# define Z_HAVE_UNISTD_H -# endif -#endif -#ifndef Z_HAVE_UNISTD_H -# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) -# define Z_HAVE_UNISTD_H -# endif -#endif -#ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/libraries/zlib/zlib.3 b/libraries/zlib/zlib.3 deleted file mode 100644 index 6f6e91404d..0000000000 --- a/libraries/zlib/zlib.3 +++ /dev/null @@ -1,149 +0,0 @@ -.TH ZLIB 3 "13 Oct 2022" -.SH NAME -zlib \- compression/decompression library -.SH SYNOPSIS -[see -.I zlib.h -for full description] -.SH DESCRIPTION -The -.I zlib -library is a general purpose data compression library. -The code is thread safe, assuming that the standard library functions -used are thread safe, such as memory allocation routines. -It provides in-memory compression and decompression functions, -including integrity checks of the uncompressed data. -This version of the library supports only one compression method (deflation) -but other algorithms may be added later -with the same stream interface. -.LP -Compression can be done in a single step if the buffers are large enough -or can be done by repeated calls of the compression function. -In the latter case, -the application must provide more input and/or consume the output -(providing more output space) before each call. -.LP -The library also supports reading and writing files in -.IR gzip (1) -(.gz) format -with an interface similar to that of stdio. -.LP -The library does not install any signal handler. -The decoder checks the consistency of the compressed data, -so the library should never crash even in the case of corrupted input. -.LP -All functions of the compression library are documented in the file -.IR zlib.h . -The distribution source includes examples of use of the library -in the files -.I test/example.c -and -.IR test/minigzip.c, -as well as other examples in the -.IR examples/ -directory. -.LP -Changes to this version are documented in the file -.I ChangeLog -that accompanies the source. -.LP -.I zlib -is built in to many languages and operating systems, including but not limited to -Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. -.LP -An experimental package to read and write files in the .zip format, -written on top of -.I zlib -by Gilles Vollant (info@winimage.com), -is available at: -.IP -http://www.winimage.com/zLibDll/minizip.html -and also in the -.I contrib/minizip -directory of the main -.I zlib -source distribution. -.SH "SEE ALSO" -The -.I zlib -web site can be found at: -.IP -http://zlib.net/ -.LP -The data format used by the -.I zlib -library is described by RFC -(Request for Comments) 1950 to 1952 in the files: -.IP -http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) -.br -http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) -.br -http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) -.LP -Mark Nelson wrote an article about -.I zlib -for the Jan. 1997 issue of Dr. Dobb's Journal; -a copy of the article is available at: -.IP -http://marknelson.us/1997/01/01/zlib-engine/ -.SH "REPORTING PROBLEMS" -Before reporting a problem, -please check the -.I zlib -web site to verify that you have the latest version of -.IR zlib ; -otherwise, -obtain the latest version and see if the problem still exists. -Please read the -.I zlib -FAQ at: -.IP -http://zlib.net/zlib_faq.html -.LP -before asking for help. -Send questions and/or comments to zlib@gzip.org, -or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). -.SH AUTHORS AND LICENSE -Version 1.2.13 -.LP -Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler -.LP -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. -.LP -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: -.LP -.nr step 1 1 -.IP \n[step]. 3 -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. -.IP \n+[step]. -Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -.IP \n+[step]. -This notice may not be removed or altered from any source distribution. -.LP -Jean-loup Gailly Mark Adler -.br -jloup@gzip.org madler@alumni.caltech.edu -.LP -The deflate format used by -.I zlib -was defined by Phil Katz. -The deflate and -.I zlib -specifications were written by L. Peter Deutsch. -Thanks to all the people who reported problems and suggested various -improvements in -.IR zlib ; -who are too numerous to cite here. -.LP -UNIX manual page by R. P. C. Rodgers, -U.S. National Library of Medicine (rodgers@nlm.nih.gov). -.\" end of man page diff --git a/libraries/zlib/zlib.3.pdf b/libraries/zlib/zlib.3.pdf deleted file mode 100644 index 8132d840c8..0000000000 Binary files a/libraries/zlib/zlib.3.pdf and /dev/null differ diff --git a/libraries/zlib/zlib.h b/libraries/zlib/zlib.h deleted file mode 100644 index 953cb5012d..0000000000 --- a/libraries/zlib/zlib.h +++ /dev/null @@ -1,1935 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.13, October 13th, 2022 - - Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler - - 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. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 - (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.13" -#define ZLIB_VERNUM 0x12d0 -#define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 13 -#define ZLIB_VER_SUBREVISION 0 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed data. - This version of the library supports only one compression method (deflation) - but other algorithms will be added later and will have the same stream - interface. - - Compression can be done in a single step if the buffers are large enough, - or can be done by repeated calls of the compression function. In the latter - case, the application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip and raw deflate streams in - memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never crash - even in the case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - z_const Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total number of input bytes read so far */ - - Bytef *next_out; /* next output byte will go here */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total number of bytes output so far */ - - z_const char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text - for deflate, or the decoding state for inflate */ - uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has dropped - to zero. It must update next_out and avail_out when avail_out has dropped - to zero. The application must initialize zalloc, zfree and opaque before - calling the init function. All other fields are set by the compression - library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. In that case, zlib is thread-safe. When zalloc and zfree are - Z_NULL on entry to the initialization function, they are set to internal - routines that use the standard library functions malloc() and free(). - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this if - the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers - returned by zalloc for objects of exactly 65536 bytes *must* have their - offset normalized to zero. The default allocation function provided by this - library ensures this (see zutil.c). To reduce memory requirements and avoid - any allocation of 64K objects, at the expense of compression ratio, compile - the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or progress - reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use by the decompressor (particularly - if the decompressor wants to decompress everything in a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field for deflate() */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is not - compatible with the zlib.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at all - (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION - requests a default compromise between speed and compression (currently - equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Generate more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary. Some output may be provided even if - flush is zero. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating avail_in or avail_out accordingly; avail_out should - never be zero before the call. The application can consume the compressed - output when it wants, for example when the output buffer is full (avail_out - == 0), or after each call of deflate(). If deflate returns Z_OK and with - zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. See deflatePending(), - which can be used if desired to determine whether or not there is more output - in that case. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumulate before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In - particular avail_in is zero after the call if enough output space has been - provided before the call.) Flushing may degrade compression for some - compression algorithms and so it should be used only when necessary. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed - codes block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this - function must be called again with Z_FINISH and more output space (updated - avail_out) but no more input data, until it returns with Z_STREAM_END or an - error. After deflate has returned Z_STREAM_END, the only possible operations - on the stream are deflateReset or deflateEnd. - - Z_FINISH can be used in the first deflate call after deflateInit if all the - compression is to be done in a single step. In order to complete in one - call, avail_out must be at least the value returned by deflateBound (see - below). Then deflate is guaranteed to return Z_STREAM_END. If not enough - output space is provided, deflate will not return Z_STREAM_END, and it must - be called again as described above. - - deflate() sets strm->adler to the Adler-32 checksum of all input read - so far (that is, total_in bytes). If a gzip stream is being generated, then - strm->adler will be the CRC-32 checksum of the input read so far. (See - deflateInit2 below.) - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is - considered binary. This field is only for information purposes and does not - affect the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL or the state was inadvertently written over - by the application), or Z_BUF_ERROR if no progress is possible (for example - avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and - deflate() can be called again with more input and more output space to - continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. In the current version of inflate, the provided input is not - read or consumed. The allocation of a sliding window will be deferred to - the first call of inflate (if the decompression does not complete on the - first call). If zalloc and zfree are set to Z_NULL, inflateInit updates - them to use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression. - Actual decompression will be done by inflate(). So next_in, and avail_in, - next_out, and avail_out are unused and unchanged. The current - implementation of inflateInit() does not process any header information -- - that is deferred until inflate() is called. -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), then next_in and avail_in are updated - accordingly, and processing will resume at this point for the next call of - inflate(). - - - Generate more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. If the - caller of inflate() does not provide both available input and available - output space, it is possible that there will be no progress made. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - To assist in this, on return inflate() always sets strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all of the uncompressed data for the - operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not - required to perform an inflation in one step. However it may be used to - inform inflate that a faster approach can be used for the single inflate() - call. Z_FINISH also informs inflate to not maintain a sliding window if the - stream completes, which reduces inflate's memory footprint. If the stream - does not complete, either because not all of the stream is provided or not - enough output space is provided, then a sliding window will be allocated and - inflate() can be called again to continue the operation as if Z_NO_FLUSH had - been used. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the effects of the flush parameter in this implementation are - on the return value of inflate() as noted below, when inflate() returns early - when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of - memory for a sliding window when Z_FINISH is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the Adler-32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the Adler-32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed Adler-32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained unless inflateGetHeader() is used. When processing - gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - produced so far. The CRC-32 is checked against the gzip trailer, as is the - uncompressed length, modulo 2^32. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value, in which case strm->msg points to a string with a more specific - error), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL, or the state was inadvertently written over - by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR - if no progress was possible or if there was not enough room in the output - buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is to be attempted. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state - was inconsistent. -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields zalloc, zfree and opaque must be initialized before by the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - For the current implementation of deflate(), a windowBits value of 8 (a - window size of 256 bytes) is not supported. As a result, a request for 8 - will result in 9 (a 512-byte window). In that case, providing 8 to - inflateInit2() will result in an error when the zlib header with 9 is - checked against the initialization of inflate(). The remedy is to not use 8 - with deflateInit2() with this initialization, or at least in that case use 9 - with inflateInit2(). - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute a check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to the appropriate value, - if the operating system was determined at compile time. If a gzip stream is - being written, strm->adler is a CRC-32 instead of an Adler-32. - - For raw deflate or gzip encoding, a request for a 256-byte window is - rejected as invalid, since only the zlib header provides a means of - transmitting the window size to the decompressor. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is - incompatible with the version assumed by the caller (ZLIB_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. When using the zlib format, this - function must be called immediately after deflateInit, deflateInit2 or - deflateReset, and before any call of deflate. When doing raw deflate, this - function must be called either before any call of deflate, or immediately - after the completion of a deflate block, i.e. after all input has been - consumed and all output has been delivered when using any of the flush - options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The - compressor and decompressor must use exactly the same dictionary (see - inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the Adler-32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler-32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - Adler-32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if not at a block boundary for raw deflate). deflateSetDictionary does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); -/* - Returns the sliding dictionary being maintained by deflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If deflateGetDictionary() is called with dictionary equal to - Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similarly, if dictLength is Z_NULL, then it is not set. - - deflateGetDictionary() may return a length less than the window size, even - when more than the window size in input has been provided. It may return up - to 258 bytes less in that case, due to how zlib's implementation of deflate - manages the sliding window and lookahead for matches, where matches can be - up to 258 bytes long. If the application needs the last window-size bytes of - input, then that would need to be saved by the application outside of zlib. - - deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, but - does not free and reallocate the internal compression state. The stream - will leave the compression level and any other attributes that may have been - set unchanged. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2(). This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression approach (which is a function of the level) or the - strategy is changed, and if there have been any deflate() calls since the - state was initialized or reset, then the input available so far is - compressed with the old level and strategy using deflate(strm, Z_BLOCK). - There are three approaches for the compression levels 0, 1..3, and 4..9 - respectively. The new level and strategy will take effect at the next call - of deflate(). - - If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does - not have enough output space to complete, then the parameter change will not - take effect. In this case, deflateParams() can be called again with the - same parameters and more output space to try again. - - In order to assure a change in the parameters on the first try, the - deflate stream should be flushed using deflate() with Z_BLOCK or other flush - request until strm.avail_out is not zero, before calling deflateParams(). - Then no more input data should be provided before the deflateParams() call. - If this is done, the old level and strategy will be applied to the data - compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). - - deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream - state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if - there was not enough output space to complete the compression of the - available input data before a change in the strategy or approach. Note that - in the case of a Z_BUF_ERROR, the parameters are not changed. A return - value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be - retried with more output space. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). If that first deflate() call is provided the - sourceLen input bytes, an output buffer allocated to the size returned by - deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed - to return Z_STREAM_END. Note that it is possible for the compressed size to - be larger than the value returned by deflateBound() if flush options other - than Z_FINISH or Z_NO_FLUSH are used. -*/ - -ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, - unsigned *pending, - int *bits)); -/* - deflatePending() returns the number of bytes and bits of output that have - been generated, but not yet provided in the available output. The bytes not - provided would be due to the available output space having being consumed. - The number of bits of output not provided are between 0 and 7, where they - await more bits to join them in order to fill out a full byte. If pending - or bits are Z_NULL, then those values are not set. - - deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. - */ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough - room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an Adler-32 or a CRC-32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see - below), inflate() will *not* automatically decode concatenated gzip members. - inflate() will return Z_STREAM_END at the end of the gzip member. The state - would need to be reset to continue decoding a subsequent gzip member. This - *must* be done if there is more data after a gzip member, in order for the - decompression to be compliant with the gzip standard (RFC 1952). - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler-32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called at any - time to set the dictionary. If the provided dictionary is smaller than the - window and there is already data in the window, then the provided dictionary - will amend what's there. The application must insure that the dictionary - that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler-32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); -/* - Returns the sliding dictionary being maintained by inflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If inflateGetDictionary() is called with dictionary equal to - Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similarly, if dictLength is Z_NULL, then it is not set. - - inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a possible full flush point (see above - for the description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync searches for a 00 00 FF FF pattern in the compressed data. - All full flush points have this pattern, but not all occurrences of this - pattern are full flush points. - - inflateSync returns Z_OK if a possible full flush point has been found, - Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point - has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of - total_in which indicates where valid compressed data was found. In the - error case, the application may repeatedly call inflateSync, providing more - input each time, until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. If the window size is changed, then the - memory allocated for the window is freed, and the window will be reallocated - by inflate() if needed. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL), or if - the windowBits parameter is invalid. -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above, or -65536 if the provided - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not Z_NULL and the respective field is not - present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the parameters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, - z_const unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is potentially more efficient than - inflate() for file i/o applications, in that it avoids copying between the - output and the sliding window by simply making the window itself the output - buffer. inflate() can be faster on modern CPUs when used with large - buffers. inflateBack() trusts the application to not change the output - buffer passed by the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the default - behavior of inflate(), which expects a zlib header and trailer around the - deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero -- buf is ignored in that - case -- and inflateBack() will return a buffer error. inflateBack() will - call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. - out() should return zero on success, or non-zero on failure. If out() - returns non-zero, inflateBack() will return with an error. Neither in() nor - out() are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be Z_NULL only if in() returned an error. If - strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: ZLIB_DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - -#ifndef Z_SOLO - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed data. compress() is equivalent to compress2() with a level - parameter of Z_DEFAULT_COMPRESSION. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed data. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed data. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In - the case where there is not enough room, uncompress() will fill the output - buffer with the uncompressed data up to that point. -*/ - -ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong *sourceLen)); -/* - Same as uncompress, except that sourceLen is a pointer, where the - length of the source is *sourceLen. On return, *sourceLen is the number of - source bytes consumed. -*/ - - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ - -/* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); - - Open the gzip (.gz) file at path for reading and decompressing, or - compressing and writing. The mode parameter is as in fopen ("rb" or "wb") - but can also include a compression level ("wb9") or a strategy: 'f' for - filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", - 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression - as in "wb9F". (See the description of deflateInit2 for more information - about the strategy parameter.) 'T' will request transparent writing or - appending with no compression and not using the gzip format. - - "a" can be used instead of "w" to request that the gzip stream that will - be written be appended to the file. "+" will result in an error, since - reading and writing to the same gzip file is not supported. The addition of - "x" when writing will create the file exclusively, which fails if the file - already exists. On systems that support it, the addition of "e" when - reading or writing will set the flag to close the file on an execve() call. - - These functions, as well as gzip, will read and decode a sequence of gzip - streams in a file. The append function of gzopen() can be used to create - such a file. (Also see gzflush() for another way to do this.) When - appending, gzopen does not test whether the file begins with a gzip stream, - nor does it look for the end of the gzip streams to begin appending. gzopen - will simply append a gzip stream to the existing file. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. When - reading, this will be detected automatically by looking for the magic two- - byte gzip header. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - Associate a gzFile with the file descriptor fd. File descriptors are - obtained from calls like open, dup, creat, pipe or fileno (if the file has - been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. If you are using fileno() to get the - file descriptor from a FILE *, then you will have to use dup() to avoid - double-close()ing the file descriptor. Both gzclose() and fclose() will - close the associated file descriptor, so they need to have different file - descriptors. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); -/* - Set the internal buffer size used by this library's functions for file to - size. The default buffer size is 8192 bytes. This function must be called - after gzopen() or gzdopen(), and before any other calls that read or write - the file. The buffer memory allocation is always deferred to the first read - or write. Three times that size in buffer space is allocated. A larger - buffer size of, for example, 64K or 128K bytes will noticeably increase the - speed of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level and strategy for file. See the - description of deflateInit2 for the meaning of these parameters. Previously - provided data is flushed before applying the parameter changes. - - gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not - opened for writing, Z_ERRNO if there is an error writing the flushed data, - or Z_MEM_ERROR if there is a memory allocation error. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Read and decompress up to len uncompressed bytes from file into buf. If - the input file is not in gzip format, gzread copies the given number of - bytes into the buffer directly from the file. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream. Any number of gzip streams may be - concatenated in the input file, and will all be decompressed by gzread(). - If something other than a gzip stream is encountered after a gzip stream, - that remaining trailing garbage is ignored (and no error is returned). - - gzread can be used to read a gzip file that is being concurrently written. - Upon reaching the end of the input, gzread will return with the available - data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then - gzclearerr can be used to clear the end of file indicator in order to permit - gzread to be tried again. Z_OK indicates that a gzip stream was completed - on the last gzread. Z_BUF_ERROR indicates that the input file ended in the - middle of a gzip stream. Note that gzread does not return -1 in the event - of an incomplete gzip stream. This error is deferred until gzclose(), which - will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip - stream. Alternatively, gzerror can be used before gzclose to detect this - case. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. If len is too large to fit in an int, - then nothing is read, -1 is returned, and the error state is set to - Z_STREAM_ERROR. -*/ - -ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, - gzFile file)); -/* - Read and decompress up to nitems items of size size from file into buf, - otherwise operating as gzread() does. This duplicates the interface of - stdio's fread(), with size_t request and return types. If the library - defines size_t, then z_size_t is identical to size_t. If not, then z_size_t - is an unsigned integer type that can contain a pointer. - - gzfread() returns the number of full items read of size size, or zero if - the end of the file was reached and a full item could not be read, or if - there was an error. gzerror() must be consulted if zero is returned in - order to determine if there was an error. If the multiplication of size and - nitems overflows, i.e. the product does not fit in a z_size_t, then nothing - is read, zero is returned, and the error state is set to Z_STREAM_ERROR. - - In the event that the end of file is reached and only a partial item is - available at the end, i.e. the remaining uncompressed data length is not a - multiple of size, then the final partial item is nevertheless read into buf - and the end-of-file flag is set. The length of the partial item read is not - provided, but could be inferred from the result of gztell(). This behavior - is the same as the behavior of fread() implementations in common libraries, - but it prevents the direct use of gzfread() to read a concurrently written - file, resetting and retrying on end-of-file, when size is not 1. -*/ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); -/* - Compress and write the len uncompressed bytes at buf to file. gzwrite - returns the number of uncompressed bytes written or 0 in case of error. -*/ - -ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, - z_size_t nitems, gzFile file)); -/* - Compress and write nitems items of size size from buf to file, duplicating - the interface of stdio's fwrite(), with size_t request and return types. If - the library defines size_t, then z_size_t is identical to size_t. If not, - then z_size_t is an unsigned integer type that can contain a pointer. - - gzfwrite() returns the number of full items written of size size, or zero - if there was an error. If the multiplication of size and nitems overflows, - i.e. the product does not fit in a z_size_t, then nothing is written, zero - is returned, and the error state is set to Z_STREAM_ERROR. -*/ - -ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); -/* - Convert, format, compress, and write the arguments (...) to file under - control of the string format, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or a negative zlib error code in case - of error. The number of uncompressed bytes written is limited to 8191, or - one less than the buffer size given to gzbuffer(). The caller should assure - that this limit is not exceeded. If it is exceeded, then gzprintf() will - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf(), - because the secure snprintf() or vsnprintf() functions were not available. - This can be determined using zlibCompileFlags(). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Compress and write the given null-terminated string s to file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Read and decompress bytes from file into buf, until len-1 characters are - read, or until a newline character is read and transferred to buf, or an - end-of-file condition is encountered. If any characters are read or if len - is one, the string is terminated with a null character. If no characters - are read due to an end-of-file or len is less than one, then the buffer is - left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Compress and write c, converted to an unsigned char, into file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Read and decompress one byte from file. gzgetc returns this byte or -1 - in case of end of file or error. This is implemented as a macro for speed. - As such, it does not do all of the checking the other functions do. I.e. - it does not check to see if file is NULL, nor whether the structure file - points to has been clobbered or not. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push c back onto the stream for file to be read as the first character on - the next read. At least one character of push-back is always allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flush all pending output to file. The parameter flush is as in the - deflate() function. The return value is the zlib error number (see function - gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatenated gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); - - Set the starting position to offset relative to whence for the next gzread - or gzwrite on file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewind file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). -*/ - -/* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - - Return the starting position for the next gzread or gzwrite on file. - This position represents a number of bytes in the uncompressed data stream, - and is zero when starting, even if appending or reading a gzip stream from - the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - - Return the current compressed (actual) read or write offset of file. This - offset includes the count of bytes that precede the gzip stream, for example - when appending or when using gzdopen() for reading. When reading, the - offset does not include as yet unused buffered input. This information can - be used for a progress indicator. On error, gzoffset() returns -1. -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Return true (1) if the end-of-file indicator for file has been set while - reading, false (0) otherwise. Note that the end-of-file indicator is set - only if the read tried to go past the end of the input, but came up short. - Therefore, just like feof(), gzeof() may return false even if there is no - more data to read, in the event that the last read request was for the exact - number of bytes remaining in the input file. This will happen if the input - file size is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Return true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). - - When writing, gzdirect() returns true (1) if transparent writing was - requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: - gzdirect() is not needed when writing. Transparent writing must be - explicitly requested, so the application already knows the answer. When - linking statically, using gzdirect() will include all of the zlib code for - gzip file reading and decompression, which may not be desired.) -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flush all pending output for file, if necessary, close file and - deallocate the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the - last read ended in the middle of a gzip stream, or Z_OK on success. -*/ - -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Return the error message for the last error which occurred on file. - errnum is set to zlib error number. If an error occurred in the file system - and not in the compression library, errnum is set to Z_ERRNO and the - application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clear the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - -#endif /* !Z_SOLO */ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. An Adler-32 value is in the range of a 32-bit - unsigned integer. If buf is Z_NULL, this function returns the required - initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed - much faster. - - Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, - z_size_t len)); -/* - Same as adler32(), but with a size_t length. -*/ - -/* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); - - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note - that the z_off_t type (like off_t) is a signed integer. If len2 is - negative, the result has no meaning or utility. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. - If buf is Z_NULL, this function returns the required initial value for the - crc. Pre- and post-conditioning (one's complement) is performed within this - function so it shouldn't be done by the application. - - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, - z_size_t len)); -/* - Same as crc32(), but with a size_t length. -*/ - -/* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - -/* -ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); - - Return the operator corresponding to length len2, to be used with - crc32_combine_op(). -*/ - -ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); -/* - Give the same result as crc32_combine(), using op in place of len2. op is - is generated from len2 by crc32_combine_gen(). This will be faster than - crc32_combine() if the generated op is used more than once. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#ifdef Z_PREFIX_SET -# define z_deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -# define z_inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -# define z_inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -# define z_inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) -#else -# define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -# define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -# define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -# define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) -#endif - -#ifndef Z_SOLO - -/* gzgetc() macro and its supporting function and exposed data structure. Note - * that the real internal state is much larger than the exposed structure. - * This abbreviated structure exposes just enough for the gzgetc() macro. The - * user should not mess with these exposed elements, since their names or - * behavior could change in the future, perhaps even capriciously. They can - * only be used by the gzgetc() macro. You have been warned. - */ -struct gzFile_s { - unsigned have; - unsigned char *next; - z_off64_t pos; -}; -ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ -#ifdef Z_PREFIX_SET -# undef z_gzgetc -# define z_gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) -#else -# define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) -#endif - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#ifdef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t)); -#endif - -#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) -# ifdef Z_PREFIX_SET -# define z_gzopen z_gzopen64 -# define z_gzseek z_gzseek64 -# define z_gztell z_gztell64 -# define z_gzoffset z_gzoffset64 -# define z_adler32_combine z_adler32_combine64 -# define z_crc32_combine z_crc32_combine64 -# define z_crc32_combine_gen z_crc32_combine_gen64 -# else -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# define crc32_combine_gen crc32_combine_gen64 -# endif -# ifndef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); -# endif -#else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); -#endif - -#else /* Z_SOLO */ - - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); - -#endif /* !Z_SOLO */ - -/* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); -ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); -ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp)); -ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); -ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#if defined(_WIN32) && !defined(Z_SOLO) -ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, - const char *mode)); -#endif -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, - const char *format, - va_list va)); -# endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/libraries/zlib/zutil.c b/libraries/zlib/zutil.c deleted file mode 100644 index 9543ae825e..0000000000 --- a/libraries/zlib/zutil.c +++ /dev/null @@ -1,327 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2017 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" -#ifndef Z_SOLO -# include "gzguts.h" -#endif - -z_const char * const z_errmsg[10] = { - (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ - (z_const char *)"stream end", /* Z_STREAM_END 1 */ - (z_const char *)"", /* Z_OK 0 */ - (z_const char *)"file error", /* Z_ERRNO (-1) */ - (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ - (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ - (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ - (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ - (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ - (z_const char *)"" -}; - - -const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -uLong ZEXPORT zlibCompileFlags() -{ - uLong flags; - - flags = 0; - switch ((int)(sizeof(uInt))) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch ((int)(sizeof(uLong))) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch ((int)(sizeof(voidpf))) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch ((int)(sizeof(z_off_t))) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef ZLIB_DEBUG - flags += 1 << 8; -#endif - /* -#if defined(ASMV) || defined(ASMINF) - flags += 1 << 9; -#endif - */ -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif -#ifdef BUILDFIXED - flags += 1 << 12; -#endif -#ifdef DYNAMIC_CRC_TABLE - flags += 1 << 13; -#endif -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif -#ifdef FASTEST - flags += 1L << 21; -#endif -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -} - -#ifdef ZLIB_DEBUG -#include -# ifndef verbose -# define verbose 0 -# endif -int ZLIB_INTERNAL z_verbose = verbose; - -void ZLIB_INTERNAL z_error(m) - char *m; -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * ZEXPORT zError(err) - int err; -{ - return ERR_MSG(err); -} - -#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 - /* The older Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. - */ - int errno = 0; -#endif - -#ifndef HAVE_MEMCPY - -void ZLIB_INTERNAL zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int ZLIB_INTERNAL zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void ZLIB_INTERNAL zmemzero(dest, len) - Bytef* dest; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - -#ifndef Z_SOLO - -#ifdef SYS16BIT - -#ifdef __TURBOC__ -/* Turbo C in 16-bit mode */ - -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf; - ulg bsize = (ulg)items*size; - - (void)opaque; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) -{ - int n; - - (void)opaque; - - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - Assert(0, "zcfree: ptr not found"); -} - -#endif /* __TURBOC__ */ - - -#ifdef M_I86 -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) -{ - (void)opaque; - return _halloc((long)items, size); -} - -void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) -{ - (void)opaque; - _hfree(ptr); -} - -#endif /* M_I86 */ - -#endif /* SYS16BIT */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf ZLIB_INTERNAL zcalloc(opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ - (void)opaque; - return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : - (voidpf)calloc(items, size); -} - -void ZLIB_INTERNAL zcfree(opaque, ptr) - voidpf opaque; - voidpf ptr; -{ - (void)opaque; - free(ptr); -} - -#endif /* MY_ZCALLOC */ - -#endif /* !Z_SOLO */ diff --git a/libraries/zlib/zutil.h b/libraries/zlib/zutil.h deleted file mode 100644 index 0bc7f4ecd1..0000000000 --- a/libraries/zlib/zutil.h +++ /dev/null @@ -1,275 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef ZUTIL_H -#define ZUTIL_H - -#ifdef HAVE_HIDDEN -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include "zlib.h" - -#if defined(STDC) && !defined(Z_SOLO) -# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) -# include -# endif -# include -# include -#endif - -#ifndef local -# define local static -#endif -/* since "static" is used to mean two completely different things in C, we - define "local" for the non-static meaning of "static", for readability - (compile with -Dlocal if your debugger can't find static symbols) */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) -# include -# if (ULONG_MAX == 0xffffffffffffffff) -# define Z_U8 unsigned long -# elif (ULLONG_MAX == 0xffffffffffffffff) -# define Z_U8 unsigned long long -# elif (UINT_MAX == 0xffffffffffffffff) -# define Z_U8 unsigned -# endif -#endif - -extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) -# define OS_CODE 0x00 -# ifndef Z_SOLO -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include -# endif -# else /* MSC or DJGPP */ -# include -# endif -# endif -#endif - -#ifdef AMIGA -# define OS_CODE 1 -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 2 -# define F_OPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#ifdef __370__ -# if __TARGET_LIB__ < 0x20000000 -# define OS_CODE 4 -# elif __TARGET_LIB__ < 0x40000000 -# define OS_CODE 11 -# else -# define OS_CODE 8 -# endif -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 5 -#endif - -#ifdef OS2 -# define OS_CODE 6 -# if defined(M_I86) && !defined(Z_SOLO) -# include -# endif -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 7 -# ifndef Z_SOLO -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif -# endif -#endif - -#ifdef __acorn -# define OS_CODE 13 -#endif - -#if defined(WIN32) && !defined(__CYGWIN__) -# define OS_CODE 10 -#endif - -#ifdef _BEOS_ -# define OS_CODE 16 -#endif - -#ifdef __TOS_OS400__ -# define OS_CODE 18 -#endif - -#ifdef __APPLE__ -# define OS_CODE 19 -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX -# if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# else -# define fdopen(fd,type) _fdopen(fd,type) -# endif -#endif - -#if defined(__BORLANDC__) && !defined(MSDOS) - #pragma warn -8004 - #pragma warn -8008 - #pragma warn -8066 -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_WIN32) && \ - (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); -#endif - - /* common defaults */ - -#ifndef OS_CODE -# define OS_CODE 3 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#if defined(pyr) || defined(Z_SOLO) -# define NO_MEMCPY -#endif -#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) -# endif -#else - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef ZLIB_DEBUG -# include - extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) fprintf x ;} -# define Tracev(x) {if (z_verbose>0) fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -#ifndef Z_SOLO - voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); - void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); -#endif - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -/* Reverse the bytes in a 32-bit value */ -#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - -#endif /* ZUTIL_H */ diff --git a/soundfont/vkdoom.sf2 b/soundfont/vkdoom.sf2 index 27cc01c187..702f7ffcdd 100644 Binary files a/soundfont/vkdoom.sf2 and b/soundfont/vkdoom.sf2 differ diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 8218feeb13..10d3577125 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -1,5 +1,5 @@ =============================================================================== -Universal Doom Map Format ZDoom extensions v1.15 - 14.12.2010 +Universal Doom Map Format ZDoom extensions v1.33 15.09.2023 Copyright (c) 2008 Christoph Oelckers. @@ -118,8 +118,11 @@ Note: All fields default to false unless mentioned otherwise. blockuse = ; // Line blocks all use actions blocksight = ; // Line blocks monster line of sight blockhitscan = ; // Line blocks hitscan attacks + blockfloaters = ; // Line blocks floating monsters' movement. + blocklandmonsters = ; // Line blocks walking monsters' movement. locknumber = ; // Line special is locked arg0str = ; // Alternate string-based version of arg0 + arg1str = ; // Alternate string-based version of arg1 moreids = ; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505") transparent = ; // true = line is a Strife transparent line (alpha 0.25) @@ -152,6 +155,11 @@ Note: All fields default to false unless mentioned otherwise. For lines with ACS specials (80-86 and 226), if arg0str is present and non-null, it will be used as the name of the script to execute, and arg0 will be ignored. + + lm_sampledist = ; // ZDRay customizable sampling distance for this line. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_top = ; // ZDRay customizable sampling distance for this line's top part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_mid = ; // ZDRay customizable sampling distance for this line's middle part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_bot = ; // ZDRay customizable sampling distance for this line's bottom part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 } sidedef @@ -221,6 +229,27 @@ Note: All fields default to false unless mentioned otherwise. colorization_top = ; // Sets a colorization record for the upper texture. Colorization records must be defined in TEXTURES. colorization_mid = ; // Sets a colorization record for the middle texture. Colorization records must be defined in TEXTURES. colorization_bottom = ; // Sets a colorization record for the lower texture. Colorization records must be defined in TEXTURES. + + lm_sampledist = ; // ZDRay customizable sampling distance for this sidedef. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_top = ; // ZDRay customizable sampling distance for this sidedef's top part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_mid = ; // ZDRay customizable sampling distance for this sidedef's middle part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_bot = ; // ZDRay customizable sampling distance for this sidedef's bottom part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + + skew_top = ; // enables skewing of wall textures, the skewing angle will be aligned to one of the 4 planes touching the floor. + skew_middle = ; // Vertical texture alignment defines the position at the leftmost point of the wall. + skew_bottom = ; // Possible values: 0 = no skewing, 1 = align to front floor, 2 = align to front ceiling, 3 = align to back floor, 4 = align to back ceiling. + // Front/Back are relative to the sidedef, not the owning linedef. Default = 0. + + xscroll = ; // wall scrolling X speed in map units per tic. + yscroll = ; // wall scrolling Y speed in map units per tic. + xscrolltop = ; // upper wall scrolling X speed in map units per tic. + yscrolltop = ; // upper wall scrolling Y speed in map units per tic. + xscrollmid = ; // mid wall scrolling X speed in map units per tic. + yscrollmid = ; // mid wall scrolling Y speed in map units per tic. + xscrollbottom = ; // lower wall scrolling X speed in map units per tic. + yscrollbottom = ; // lower wall scrolling Y speed in map units per tic. + + } sector @@ -319,6 +348,38 @@ Note: All fields default to false unless mentioned otherwise. healthfloorgroup = ; // ID of destructible object to synchronize hitpoints (optional, default is 0) healthceiling = ; // Amount of hitpoints for this sector (includes ceiling and top-outside linedef sides) healthceilinggroup = ; // ID of destructible object to synchronize hitpoints (optional, default is 0) + health3d = ; // Amount of hitpoints for this sector (includes 3D floors) + health3dgroup = ; // ID of destructible object to synchronize hitpoints (optional, default is 0) + + xscrollfloor = ; // X map units per frame to scroll the floor. + yscrollfloor = ; // Y map units per frame to scroll the floor. + scrollfloormode = ; // Floor scroll mode bit mask (1 = scroll textures, 2 = carry static objects, 4 = carry players, 8 = carry monsters. + xscrollceiling = ; // X map units per frame to scroll the ceiling. + yscrollceiling = ; // Y map units per frame to scroll the ceiling. + scrollceilingmode = ; // ceiling scroll mode bit mask (1 = scroll textures, 2 = carry static objects, 4 = carry players, 8 = carry monsters. + + scroll_ceil_x = ; // deprecated Eternity based alternatives for the above. + scroll_ceil_y = ; // Due to using unintuitive units of measurement and a more limited feature set they should not be used anymore. + scroll_ceil_type = ; + scroll_floor_x = ; + scroll_floor_y = ; + scroll_floor_type = ; + + friction = ; // sets the sector's friction factor. Must be between 0 and 1. + movefactor = // sets the sector's movement acceleration factor. Must be > 0. + + skyfloor = // defines lower sky for this sector. + skyceiling = // defines upper sky for this sector. + skyfloor2 = // defines secondary lower sky for this sector. (for lightning or transparent layers) + skyceiling2 = // defines secondary upper sky for this sector. + + colormap = ; // only provided for backwards compatibility. Do not use in GZDoom projects. + + xthrust = ; // applies thrust to actors - x-magnitude + ythrust = ; // applies thrust to actors - y-magnitude + thrustgroup = ; // specifies which actors get thrusted. Bitfield with (1 = static objects, 2 = player, 4 = monsters, 8 = projectiles, 16 = actors with +WINDTHRUST) + thrustlocation = ; // specifies where in the sector actors get thrusted: (1 = on the ground, 2 = in the air, 4 = on the ceiling) + * Note about dropactors @@ -326,6 +387,9 @@ Note: All fields default to false unless mentioned otherwise. for Doom format maps so any map converter converting to the ZDoomTranslated namespace should set this flag for each tagged sector. + lm_sampledist_floor = ; // ZDRay customizable sampling distance for this sector's floor. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_ceiling = ; // ZDRay customizable sampling distance for this sector's ceiling. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_dynamic = ; // ZDRay marks a sector's lightmaps as dynamic so that they may be updated in realtime (used for flickering lights, changing a lightmap light's position, color etc). Default = false } thing @@ -335,7 +399,9 @@ Note: All fields default to false unless mentioned otherwise. conversation = // Assigns a conversation dialogue to this thing. // Parameter is the conversation ID, 0 meaning none. countsecret = ; // Picking up this actor counts as a secret. + nocount = ; // When true, object does not count toward kills or items. arg0str = ; // Alternate string-based version of arg0 + arg1str = ; // Alternate string-based version of arg1 gravity = ; // Set per-actor gravity. Positive values are multiplied with the class's property, // negative values are used as their absolute. Default = 1.0. @@ -356,6 +422,12 @@ Note: All fields default to false unless mentioned otherwise. scale = ; // Vertical and horizontal scaling on thing. Default = 0 (ignored). floatbobphase = ; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default). + lm_sampledist = ; // ZDRay lightmap sample distance for the entire map. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 8 + lm_suncolor = ; // ZDRay lightmap sun color in hex. Default = "FFFFFF" + SourceRadius = ; // ZDRay lightmap light and raytraced dynamic light soft shadow amount. Higher values produce softer shadows. Default = 5.0 + + friendlyseeblocks = ; // How far (in block units) a friendly monster can see other monsters. Default 10 + * Note about arg0str For things with ACS specials (80-86 and 226), if arg0str is present and non-null, it @@ -519,6 +591,15 @@ Blocklandmonsters MBF21 flag 1.33 06.11.2021 Added separate light levels for sidedef tiers (top/mid/bottom) +1.34 11.09.2023 +Added/updated ZDRay/lightmap-related properties. + +1.35 15.09.2023 +fixed omissions: Blocklandmonsters and Blockfloaters line flags. + +1.36 20.10.2023 +Sidedef skewing properties + =============================================================================== EOF =============================================================================== diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e9f8c2da6..ddc9656625 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 3.1.0 ) +cmake_minimum_required( VERSION 3.16.0 ) include(precompiled_headers) @@ -97,7 +97,7 @@ else() if( NOT DYN_GTK ) set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} ${GTK3_LIBRARIES} ) endif() - include_directories( ${GTK3_INCLUDE_DIRS} ) + include_directories( SYSTEM ${GTK3_INCLUDE_DIRS} ) link_directories( ${GTK3_LIBRARY_DIRS} ) else() pkg_check_modules( GTK2 gtk+-2.0 ) @@ -105,7 +105,7 @@ else() if( NOT DYN_GTK ) set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} ${GTK2_LIBRARIES} ) endif() - include_directories( ${GTK2_INCLUDE_DIRS} ) + include_directories( SYSTEM ${GTK2_INCLUDE_DIRS} ) link_directories( ${GTK2_LIBRARY_DIRS} ) else() set( NO_GTK ON ) @@ -132,18 +132,22 @@ else() # Non-Windows version also needs SDL except native OS X backend if( NOT APPLE OR NOT OSX_COCOA_BACKEND ) find_package( SDL2 REQUIRED ) - include_directories( "${SDL2_INCLUDE_DIR}" ) + include_directories( SYSTEM "${SDL2_INCLUDE_DIR}" ) set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} "${SDL2_LIBRARY}" ) endif() endif() if( NOT NO_OPENAL ) - if ( NOT DYN_OPENAL ) # DYN_OPENAL uses local copies of the headers. + if ( "vcpkg-openal-soft" IN_LIST VCPKG_MANIFEST_FEATURES ) + # Statically link to OpenAL from vcpkg + find_package( OpenAL CONFIG REQUIRED ) + list( APPEND PROJECT_LIBRARIES OpenAL::OpenAL ) + elseif ( NOT DYN_OPENAL ) # DYN_OPENAL uses local copies of the headers. find_package( OpenAL ) mark_as_advanced(CLEAR OPENAL_INCLUDE_DIR) if( OPENAL_INCLUDE_DIR ) - include_directories( ${OPENAL_INCLUDE_DIR} ) + include_directories( SYSTEM ${OPENAL_INCLUDE_DIR} ) mark_as_advanced(CLEAR OPENAL_LIBRARY) if( OPENAL_LIBRARY ) set( PROJECT_LIBRARIES ${OPENAL_LIBRARY} ${PROJECT_LIBRARIES} ) @@ -278,10 +282,7 @@ endif() # Check for thread_local keyword, it's optional at the moment -CHECK_CXX_SOURCE_COMPILES("thread_local int i; int main() { i = 0; }" - HAVE_THREAD_LOCAL) - -if( NOT HAVE_THREAD_LOCAL ) +if ( NOT (cxx_thread_local IN_LIST CMAKE_CXX_COMPILE_FEATURES) ) message( SEND_ERROR "C++ compiler doesn't support thread_local storage duration specifier" ) endif() @@ -303,7 +304,7 @@ if( UNIX ) add_definitions( -DNO_CLOCK_GETTIME ) endif() else() - set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} rt ) + list( APPEND PROJECT_LIBRARIES rt ) endif() endif() @@ -318,11 +319,14 @@ add_custom_target( revision_check ALL # required libraries -set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${CMAKE_DL_LIBS}" "${DRPC_LIBRARIES}") +set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} miniz "${BZIP2_LIBRARIES}" "${CMAKE_DL_LIBS}" "${DRPC_LIBRARIES}") if (HAVE_VULKAN) - set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} "zvulkan") + list( APPEND PROJECT_LIBRARIES "zvulkan" ) endif() +list( APPEND PROJECT_LIBRARIES "zwidget" ) +list( APPEND PROJECT_LIBRARIES "webp" ) + # ZMUSIC if( MSVC ) @@ -373,13 +377,13 @@ endif() if( VPX_FOUND ) add_definitions( "-DUSE_LIBVPX=1" ) - include_directories( "${VPX_INCLUDE_DIR}" ) + include_directories( SYSTEM "${VPX_INCLUDE_DIR}" ) set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} ${VPX_LIBRARIES} ) else() message( SEND_ERROR "Could not find libvpx" ) endif() -include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${DRPC_INCLUDE_DIR}") +include_directories( SYSTEM "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${DRPC_INCLUDE_DIR}") if( ${HAVE_VM_JIT} ) add_definitions( -DHAVE_VM_JIT ) @@ -403,19 +407,14 @@ set( PLAT_WIN32_SOURCES common/platform/win32/st_start.cpp common/platform/win32/base_sysfb.cpp common/platform/win32/win32basevideo.cpp + common/platform/win32/i_crash.cpp ) if (HAVE_VULKAN) - set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} common/platform/win32/win32vulkanvideo.cpp ) + list (APPEND PLAT_WIN32_SOURCES common/platform/win32/win32vulkanvideo.cpp ) endif() -# todo: implement an actual crash catcher for ARM -# for now this is purely experimental -if (NOT ${TARGET_ARCHITECTURE} MATCHES "arm" ) - set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} common/platform/win32/i_crash.cpp ) -endif() if (MSVC AND ${TARGET_ARCHITECTURE} MATCHES "arm") - set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} common/platform/win32/i_crash_arm.cpp ) add_definitions( -DNO_SSE -D__ARM__ -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN) endif() @@ -424,13 +423,13 @@ set( PLAT_POSIX_SOURCES common/platform/posix/i_system_posix.cpp ) set( PLAT_SDL_SOURCES common/platform/posix/sdl/crashcatcher.c + common/platform/posix/sdl/base_sysfb.cpp common/platform/posix/sdl/hardware.cpp common/platform/posix/sdl/i_gui.cpp common/platform/posix/sdl/i_input.cpp common/platform/posix/sdl/i_joystick.cpp common/platform/posix/sdl/i_main.cpp common/platform/posix/sdl/i_system.cpp - common/platform/posix/sdl/sdlglvideo.cpp common/platform/posix/sdl/st_start.cpp ) set( PLAT_UNIX_SOURCES common/platform/posix/unix/i_specialpaths.cpp @@ -570,13 +569,15 @@ file( GLOB HEADER_FILES common/statusbar/*.h common/fonts/*.h common/objects/*.h - common/filesystem/*.h + common/filesystem/include/*.h + common/filesystem/source/*.h common/platform/posix/cocoa/*.h common/platform/posix/sdl/*.h common/platform/win32/*.h common/models/*.h common/textures/*.h common/startscreen/*.h + common/widgets/*.h common/textures/hires/hqnx/*.h common/textures/hires/hqnx_asm/*.h common/textures/hires/xbr/*.h @@ -584,6 +585,7 @@ file( GLOB HEADER_FILES common/thirdparty/rapidjson/*.h common/thirdparty/math/*h common/thirdparty/libsmackerdec/include/*.h + common/thirdparty/utf8proc/*.h common/rendering/*.h common/rendering/hwrenderer/data/*.h common/rendering/vulkan/*.h @@ -595,7 +597,6 @@ file( GLOB HEADER_FILES common/rendering/vulkan/samplers/*.h common/rendering/vulkan/shaders/*.h common/rendering/vulkan/textures/*.h - common/rendering/vulkan/accelstructs/*.h common/scripting/core/*h common/scripting/vm/*h common/scripting/jit/*h @@ -604,6 +605,7 @@ file( GLOB HEADER_FILES common/scripting/frontend/*.h utility/*.h + launcher/*.h scripting/*.h scripting/backend/*.h scripting/decorate/*.h @@ -697,10 +699,6 @@ set( VM_JIT_SOURCES common/scripting/jit/jit_store.cpp ) -# This is disabled for now because I cannot find a way to give the .pch file a different name. -# Visual C++ 2015 seems hell-bent on only allowing one .pch file with the same name as the executable. -#enable_precompiled_headers( g_pch2.h FASTMATH_PCH_SOURCES ) - # Enable fast math for some sources set( FASTMATH_SOURCES rendering/swrenderer/r_all.cpp @@ -715,6 +713,7 @@ set( FASTMATH_SOURCES rendering/hwrenderer/scene/hw_bsp.cpp rendering/hwrenderer/scene/hw_fakeflat.cpp rendering/hwrenderer/scene/hw_decal.cpp + rendering/hwrenderer/scene/hw_drawcontext.cpp rendering/hwrenderer/scene/hw_drawinfo.cpp rendering/hwrenderer/scene/hw_drawlist.cpp rendering/hwrenderer/scene/hw_clipper.cpp @@ -737,6 +736,8 @@ set (VULKAN_SOURCES common/rendering/vulkan/vk_renderstate.cpp common/rendering/vulkan/vk_postprocess.cpp common/rendering/vulkan/vk_pprenderstate.cpp + common/rendering/vulkan/vk_levelmesh.cpp + common/rendering/vulkan/vk_lightmapper.cpp common/rendering/vulkan/commands/vk_commandbuffer.cpp common/rendering/vulkan/buffers/vk_rsbuffers.cpp common/rendering/vulkan/buffers/vk_hwbuffer.cpp @@ -753,11 +754,10 @@ set (VULKAN_SOURCES common/rendering/vulkan/textures/vk_renderbuffers.cpp common/rendering/vulkan/textures/vk_texture.cpp common/rendering/vulkan/framebuffers/vk_framebuffer.cpp - common/rendering/vulkan/accelstructs/vk_raytrace.cpp ) if (HAVE_VULKAN) - set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${VULKAN_SOURCES}) + list (APPEND FASTMATH_SOURCES ${VULKAN_SOURCES}) endif() set (FASTMATH_SOURCES ${FASTMATH_SOURCES}) @@ -847,11 +847,11 @@ set (PCH_SOURCES playsim/mapthinkers/a_pillar.cpp playsim/mapthinkers/a_plats.cpp playsim/mapthinkers/a_pusher.cpp + playsim/mapthinkers/a_thruster.cpp playsim/mapthinkers/a_scroll.cpp playsim/mapthinkers/dsectoreffect.cpp playsim/a_pickups.cpp playsim/a_action.cpp - playsim/a_corona.cpp playsim/a_decals.cpp playsim/a_dynlight.cpp playsim/a_flashfader.cpp @@ -886,7 +886,6 @@ set (PCH_SOURCES rendering/hwrenderer/scene/hw_lighting.cpp rendering/hwrenderer/scene/hw_drawlistadd.cpp rendering/hwrenderer/scene/hw_setcolor.cpp - rendering/hwrenderer/scene/hw_meshcache.cpp maploader/edata.cpp maploader/specials.cpp maploader/maploader.cpp @@ -947,6 +946,12 @@ set (PCH_SOURCES rendering/swrenderer/textures/warptexture.cpp rendering/swrenderer/textures/swcanvastexture.cpp events.cpp + launcher/launcherwindow.cpp + launcher/launcherbanner.cpp + launcher/launcherbuttonbar.cpp + launcher/playgamepage.cpp + launcher/settingspage.cpp + common/audio/sound/i_sound.cpp common/audio/sound/oalsound.cpp common/audio/sound/s_environment.cpp @@ -961,6 +966,7 @@ set (PCH_SOURCES common/2d/v_drawtext.cpp common/2d/v_draw.cpp common/2d/wipe.cpp + common/thirdparty/animlib.cpp common/thirdparty/gain_analysis.cpp common/thirdparty/sfmt/SFMT.cpp common/startscreen/startscreen.cpp @@ -969,11 +975,16 @@ set (PCH_SOURCES common/startscreen/startscreen_strife.cpp common/startscreen/startscreen_generic.cpp common/startscreen/endoom.cpp + common/widgets/errorwindow.cpp + common/widgets/netstartwindow.cpp + common/widgets/widgetresourcedata.cpp common/fonts/singlelumpfont.cpp common/fonts/singlepicfont.cpp common/fonts/specialfont.cpp common/fonts/font.cpp common/fonts/hexfont.cpp + common/fonts/ttffont.cpp + common/fonts/schrift.cpp common/fonts/v_font.cpp common/fonts/v_text.cpp common/textures/hw_ihwtexture.cpp @@ -989,7 +1000,6 @@ set (PCH_SOURCES common/textures/skyboxtexture.cpp common/textures/animtexture.cpp common/textures/v_collection.cpp - common/textures/animlib.cpp common/textures/formats/automaptexture.cpp common/textures/formats/brightmaptexture.cpp common/textures/formats/buildtexture.cpp @@ -997,7 +1007,6 @@ set (PCH_SOURCES common/textures/formats/flattexture.cpp common/textures/formats/fontchars.cpp common/textures/formats/imgztexture.cpp - common/textures/formats/jpegtexture.cpp common/textures/formats/md5check.cpp common/textures/formats/multipatchtexture.cpp common/textures/formats/patchtexture.cpp @@ -1011,6 +1020,8 @@ set (PCH_SOURCES common/textures/formats/stbtexture.cpp common/textures/formats/anmtexture.cpp common/textures/formats/startscreentexture.cpp + common/textures/formats/qoitexture.cpp + common/textures/formats/webptexture.cpp common/textures/hires/hqresize.cpp common/models/models_md3.cpp common/models/models_md2.cpp @@ -1041,17 +1052,16 @@ set (PCH_SOURCES common/utility/m_alloc.cpp common/utility/utf8.cpp common/utility/palette.cpp - common/utility/files.cpp - common/utility/files_decompress.cpp common/utility/memarena.cpp common/utility/cmdlib.cpp common/utility/configfile.cpp common/utility/i_time.cpp common/utility/m_argv.cpp common/utility/s_playlist.cpp - common/utility/zstrformat.cpp common/utility/name.cpp common/utility/r_memory.cpp + common/utility/bounds.cpp + common/utility/writezip.cpp common/thirdparty/base64.cpp common/thirdparty/md5.cpp common/thirdparty/superfasthash.cpp @@ -1060,19 +1070,6 @@ set (PCH_SOURCES common/thirdparty/libsmackerdec/src/HuffmanVLC.cpp common/thirdparty/libsmackerdec/src/LogError.cpp common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp - common/filesystem/filesystem.cpp - common/filesystem/ancientzip.cpp - common/filesystem/file_7z.cpp - common/filesystem/file_grp.cpp - common/filesystem/file_lump.cpp - common/filesystem/file_rff.cpp - common/filesystem/file_wad.cpp - common/filesystem/file_zip.cpp - common/filesystem/file_pak.cpp - common/filesystem/file_whres.cpp - common/filesystem/file_ssi.cpp - common/filesystem/file_directory.cpp - common/filesystem/resourcefile.cpp common/engine/cycler.cpp common/engine/d_event.cpp common/engine/date.cpp @@ -1114,6 +1111,7 @@ set (PCH_SOURCES common/rendering/hwrenderer/data/hw_shadowmap.cpp common/rendering/hwrenderer/data/hw_shaderpatcher.cpp common/rendering/hwrenderer/data/hw_collision.cpp + common/rendering/hwrenderer/data/hw_levelmesh.cpp common/rendering/hwrenderer/data/hw_meshbuilder.cpp common/rendering/hwrenderer/data/hw_mesh.cpp common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp @@ -1152,14 +1150,7 @@ else() set( NOT_COMPILED_SOURCE_FILES ${NOT_COMPILED_SOURCE_FILES} ${VM_JIT_SOURCES} ) endif() -if( MSVC ) - enable_precompiled_headers( g_pch.h PCH_SOURCES ) -else() - # Temporary solution for compilers other than MSVC - set_source_files_properties( ${PCH_SOURCES} PROPERTIES COMPILE_FLAGS "-include g_pch.h" ) -endif() - -add_executable( zdoom WIN32 MACOSX_BUNDLE +set( GAME_SOURCES ${HEADER_FILES} ${NOT_COMPILED_SOURCE_FILES} ${SYSTEM_SOURCES} @@ -1167,8 +1158,11 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE ${PCH_SOURCES} common/utility/x86.cpp common/thirdparty/strnatcmp.c + common/thirdparty/utf8proc/utf8proc.c + common/thirdparty/stb/stb_sprintf.c common/utility/zstring.cpp common/utility/findfile.cpp + common/utility/halffloat.cpp common/thirdparty/math/asin.c common/thirdparty/math/atan.c common/thirdparty/math/const.c @@ -1187,12 +1181,43 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE common/thirdparty/math/tan.c common/thirdparty/math/tanh.c common/thirdparty/math/fastsin.cpp + + common/filesystem/source/filesystem.cpp + common/filesystem/source/ancientzip.cpp + common/filesystem/source/file_7z.cpp + common/filesystem/source/file_grp.cpp + common/filesystem/source/file_lump.cpp + common/filesystem/source/file_rff.cpp + common/filesystem/source/file_wad.cpp + common/filesystem/source/file_zip.cpp + common/filesystem/source/file_pak.cpp + common/filesystem/source/file_whres.cpp + common/filesystem/source/file_ssi.cpp + common/filesystem/source/file_hog.cpp + common/filesystem/source/file_mvl.cpp + common/filesystem/source/file_directory.cpp + common/filesystem/source/resourcefile.cpp + common/filesystem/source/files.cpp + common/filesystem/source/files_decompress.cpp + common/filesystem/source/fs_findfile.cpp + common/filesystem/source/fs_stringpool.cpp + common/filesystem/source/unicode.cpp + common/filesystem/source/critsec.cpp + ) +set( GAME_NONPCH_SOURCES ${GAME_SOURCES} ) +list( REMOVE_ITEM GAME_NONPCH_SOURCES ${PCH_SOURCES} ) + +add_executable( zdoom WIN32 MACOSX_BUNDLE ${GAME_SOURCES} ) + +target_precompile_headers( zdoom PRIVATE g_pch.h ) + set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${ZD_FASTMATH_FLAG} ) set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" ) set_source_files_properties( common/engine/sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" ) set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE ) +set_source_files_properties( ${GAME_NONPCH_SOURCES} common/textures/hires/hqresize.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS TRUE ) if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") @@ -1207,21 +1232,25 @@ if( UNIX ) endif() endif() -target_link_libraries( zdoom ${PROJECT_LIBRARIES} gdtoa lzma ${ZMUSIC_LIBRARIES} ) +target_link_libraries( zdoom ${PROJECT_LIBRARIES} lzma ${ZMUSIC_LIBRARIES} ) -include_directories( . +include_directories( + BEFORE + . common/audio/sound common/audio/music common/2d common/cutscenes common/thirdparty/libsmackerdec/include common/thirdparty + common/thirdparty/stb + common/thirdparty/utf8proc common/textures common/textures/formats common/textures/hires common/textures common/models - common/filesystem + common/filesystem/include common/utility common/console common/engine @@ -1230,6 +1259,7 @@ include_directories( . common/fonts common/objects common/startscreen + common/widgets common/rendering common/rendering/hwrenderer/data common/scripting/vm @@ -1259,8 +1289,11 @@ include_directories( . scripting scripting/zscript rendering - ../libraries/gdtoa + launcher ../libraries/ZVulkan/include + ../libraries/ZWidget/include + ../libraries/webp/include + ../libraries/dp_rect_pack ../libraries/dragonbook/src ${CMAKE_BINARY_DIR}/libraries/gdtoa ${SYSTEM_SOURCES_DIR} @@ -1296,6 +1329,9 @@ if( MSVC ) endif() set_target_properties(zdoom PROPERTIES LINK_FLAGS ${LINKERSTUFF}) + # Create stripped PDBs for nightly builds + set_target_properties(zdoom PROPERTIES LINK_FLAGS_RELWITHDEBINFO /PDBSTRIPPED:${ZDOOM_OUTPUT_DIR}/RelWithDebInfo/${ZDOOM_EXE_NAME}-stripped.pdb) + add_custom_command(TARGET zdoom POST_BUILD COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\common\\platform\\win32\\manifest.xml\" -outputresource:\"$\"\;\#1 COMMENT "Adding manifest..." @@ -1311,7 +1347,7 @@ if( NOT WIN32 AND NOT APPLE ) IF ("${INSTALL_RPATH}" STREQUAL "") set_target_properties(zdoom PROPERTIES #allow libzmusic.so.1 library in same folder as executable at runtime - INSTALL_RPATH "\$ORIGIN" + INSTALL_RPATH "\$ORIGIN:\$ORIGIN/zmusic/build/source" BUILD_WITH_INSTALL_RPATH ON ) endif() @@ -1326,6 +1362,10 @@ add_custom_command(TARGET zdoom POST_BUILD ${CMAKE_SOURCE_DIR}/fm_banks/gs-by-papiezak-and-sneakernets.wopn $/fm_banks/gs-by-papiezak-and-sneakernets.wopn ) +if (VCPKG_TOOLCHAIN) + x_vcpkg_install_local_dependencies(TARGETS zdoom DESTINATION ".") +endif() + if( WIN32 ) set( INSTALL_SOUNDFONT_PATH . CACHE STRING "Directory where soundfonts and WOPL/WOPN banks will be placed during install." ) else() @@ -1363,9 +1403,9 @@ if( APPLE ) endif() if( WIN32 ) - set( INSTALL_PATH . CACHE STRING "Directory where the zdoom executable will be placed during install." ) + set( INSTALL_PATH . CACHE STRING "Directory where the executable will be placed during install." ) else() - set( INSTALL_PATH bin CACHE STRING "Directory where the zdoom executable will be placed during install." ) + set( INSTALL_PATH bin CACHE STRING "Directory where the executable will be placed during install." ) endif() install(TARGETS zdoom DESTINATION ${INSTALL_PATH} @@ -1416,6 +1456,10 @@ source_group("Common\\Objects" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/ source_group("Common\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/menu/.+") source_group("Common\\Fonts" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/fonts/.+") source_group("Common\\File System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/.+") +source_group("Common\\File System\\Include" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/include/.+") +source_group("Common\\File System\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/source/.+") +source_group("Common\\Startscreen" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/startscreen/.+") +source_group("Common\\Widgets" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/widgets/.+") source_group("Common\\Scripting" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/.+") source_group("Common\\Scripting\\Interface" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/interface/.+") source_group("Common\\Scripting\\Frontend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/frontend/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h) @@ -1441,7 +1485,6 @@ source_group("Common\\Rendering\\Vulkan Renderer\\Pipelines" REGULAR_EXPRESSION source_group("Common\\Rendering\\Vulkan Renderer\\Samplers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/samplers/.+") source_group("Common\\Rendering\\Vulkan Renderer\\Shaders" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/shaders/.+") source_group("Common\\Rendering\\Vulkan Renderer\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/textures/.+") -source_group("Common\\Rendering\\Vulkan Renderer\\Accelstructs" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/accelstructs/.+") source_group("Common\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/models/.+") source_group("Common\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/textures/.+") source_group("Common\\Textures\\Hires" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/textures/hires/.+") @@ -1453,12 +1496,15 @@ source_group("Common\\Third Party" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_D source_group("Common\\Third Party\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/thirdparty/math/.+") source_group("Common\\Third Party\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/thirdparty/rapidjson/.+") source_group("Common\\Third Party\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/thirdparty/sfmt/.+") +source_group("Common\\Third Party\\stb" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/thirdparty/stb/.+") +source_group("Common\\Third Party\\utf8proc" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/thirdparty/utf8proc/.+") source_group("Utility" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/utility/.+") source_group("Utility\\Node Builder" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/utility/nodebuilder/.+") source_group("Utility\\Smackerdec" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/smackerdec/.+") source_group("Utility\\Smackerdec\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libsmackerdec/include/.+") source_group("Utility\\Smackerdec\\Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libsmackerdec/src/.+") source_group("Statusbar" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_statusbar/.+") +source_group("Launcher" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/launcher/.+") source_group("Versioning" FILES version.h win32/zdoom.rc) source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h) source_group("Source Files" FILES ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h common/engine/sc_man_scanner.re) diff --git a/src/am_map.cpp b/src/am_map.cpp index 646dc28d52..1b610a52e4 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -156,7 +156,15 @@ CUSTOM_CVAR(Int, am_cheat, 0, 0) CVAR(Int, am_rotate, 0, CVAR_ARCHIVE); -CVAR(Int, am_overlay, 0, CVAR_ARCHIVE); +CUSTOM_CVAR(Int, am_overlay, 0, CVAR_ARCHIVE) +{ + // stop overlay if we're told not to use it anymore. + if (automapactive && viewactive && (self == 0)) + { + automapactive = false; + viewactive = true; + } +} CVAR(Bool, am_showsecrets, true, CVAR_ARCHIVE); CVAR(Bool, am_showmonsters, true, CVAR_ARCHIVE); CVAR(Bool, am_showitems, true, CVAR_ARCHIVE); @@ -208,19 +216,19 @@ CCMD(am_togglefollow) am_followplayer = !am_followplayer; if (primaryLevel && primaryLevel->automap) primaryLevel->automap->ResetFollowLocation(); - Printf("%s\n", GStrings(am_followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF")); + Printf("%s\n", GStrings.GetString(am_followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF")); } CCMD(am_togglegrid) { am_showgrid = !am_showgrid; - Printf("%s\n", GStrings(am_showgrid ? "AMSTR_GRIDON" : "AMSTR_GRIDOFF")); + Printf("%s\n", GStrings.GetString(am_showgrid ? "AMSTR_GRIDON" : "AMSTR_GRIDOFF")); } CCMD(am_toggletexture) { am_textured = !am_textured; - Printf("%s\n", GStrings(am_textured ? "AMSTR_TEXON" : "AMSTR_TEXOFF")); + Printf("%s\n", GStrings.GetString(am_textured ? "AMSTR_TEXON" : "AMSTR_TEXOFF")); } CCMD(am_setmark) @@ -230,7 +238,7 @@ CCMD(am_setmark) int m = primaryLevel->automap->addMark(); if (m >= 0) { - Printf("%s %d\n", GStrings("AMSTR_MARKEDSPOT"), m); + Printf("%s %d\n", GStrings.GetString("AMSTR_MARKEDSPOT"), m); } } } @@ -239,7 +247,7 @@ CCMD(am_clearmarks) { if (primaryLevel && primaryLevel->automap && primaryLevel->automap->clearMarks()) { - Printf("%s\n", GStrings("AMSTR_MARKSCLEARED")); + Printf("%s\n", GStrings.GetString("AMSTR_MARKSCLEARED")); } } @@ -792,9 +800,9 @@ void FMapInfoParser::ParseAMColors(bool overlay) { sc.MustGetToken(TK_StringConst); FString color = sc.String; - FString colorName = V_GetColorStringByName(color); + FString colorName = V_GetColorStringByName(color.GetChars()); if(!colorName.IsEmpty()) color = colorName; - int colorval = V_GetColorFromString(color); + int colorval = V_GetColorFromString(color.GetChars()); cset.c[i].FromRGB(RPART(colorval), GPART(colorval), BPART(colorval)); colorset = true; break; @@ -872,10 +880,10 @@ void AM_StaticInit() CheatKey.Clear(); EasyKey.Clear(); - if (gameinfo.mMapArrow.IsNotEmpty()) AM_ParseArrow(MapArrow, gameinfo.mMapArrow); - if (gameinfo.mCheatMapArrow.IsNotEmpty()) AM_ParseArrow(CheatMapArrow, gameinfo.mCheatMapArrow); - AM_ParseArrow(CheatKey, gameinfo.mCheatKey); - AM_ParseArrow(EasyKey, gameinfo.mEasyKey); + if (gameinfo.mMapArrow.IsNotEmpty()) AM_ParseArrow(MapArrow, gameinfo.mMapArrow.GetChars()); + if (gameinfo.mCheatMapArrow.IsNotEmpty()) AM_ParseArrow(CheatMapArrow, gameinfo.mCheatMapArrow.GetChars()); + AM_ParseArrow(CheatKey, gameinfo.mCheatKey.GetChars()); + AM_ParseArrow(EasyKey, gameinfo.mEasyKey.GetChars()); if (MapArrow.Size() == 0) I_FatalError("No automap arrow defined"); char namebuf[9]; @@ -996,7 +1004,7 @@ class DAutomap :public DAutomapBase void calcMinMaxMtoF(); void DrawMarker(FGameTexture *tex, double x, double y, int yadjust, - INTBOOL flip, double xscale, double yscale, int translation, double alpha, uint32_t fillcolor, FRenderStyle renderstyle); + INTBOOL flip, double xscale, double yscale, FTranslationID translation, double alpha, uint32_t fillcolor, FRenderStyle renderstyle); void rotatePoint(double *x, double *y); void rotate(double *x, double *y, DAngle an); @@ -1360,7 +1368,7 @@ void DAutomap::LevelInit () } else { - mapback = TexMan.CheckForTexture(Level->info->MapBackground, ETextureType::MiscPatch); + mapback = TexMan.CheckForTexture(Level->info->MapBackground.GetChars(), ETextureType::MiscPatch); } clearMarks(); @@ -1547,7 +1555,7 @@ void DAutomap::Ticker () if (!automapactive) return; - if ((primaryLevel->flags9 & LEVEL9_NOAUTOMAP)) + if ((primaryLevel->vkdflags & VKDLEVELFLAG_NOAUTOMAP)) { AM_ToggleMap(); return; @@ -2018,6 +2026,9 @@ void DAutomap::drawSubsectors() PalEntry flatcolor; mpoint_t originpt; + auto lm = getRealLightmode(Level, false); + bool softlightramp = !V_IsHardwareRenderer() || lm == ELightMode::Doom || lm == ELightMode::DoomDark; + auto &subsectors = Level->subsectors; for (unsigned i = 0; i < subsectors.Size(); ++i) { @@ -2192,15 +2203,14 @@ void DAutomap::drawSubsectors() // Why the +12? I wish I knew, but experimentation indicates it // is necessary in order to best reproduce Doom's original lighting. double fadelevel; - - if (!V_IsHardwareRenderer() || primaryLevel->lightMode == ELightMode::DoomDark || primaryLevel->lightMode == ELightMode::Doom || primaryLevel->lightMode == ELightMode::ZDoomSoftware || primaryLevel->lightMode == ELightMode::DoomSoftware) + if (softlightramp) { double map = (NUMCOLORMAPS * 2.) - ((floorlight + 12) * (NUMCOLORMAPS / 128.)); fadelevel = clamp((map - 12) / NUMCOLORMAPS, 0.0, 1.0); } else { - // The hardware renderer's light modes 0, 1 and 4 use a linear light scale which must be used here as well. Otherwise the automap gets too dark. + // for the hardware renderer's light modes that use a linear light scale this must do the same. Otherwise the automap gets too dark. fadelevel = 1. - clamp(floorlight, 0, 255) / 255.f; } @@ -2812,7 +2822,7 @@ void DAutomap::drawPlayers () int numarrowlines; double vh = players[consoleplayer].viewheight; - DVector2 pos = players[consoleplayer].camera->InterpolatedPosition(r_viewpoint.TicFrac); + DVector2 pos = players[consoleplayer].camera->InterpolatedPosition(r_viewpoint.TicFrac).XY(); pt.x = pos.X; pt.y = pos.Y; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) @@ -2956,7 +2966,8 @@ void DAutomap::drawThings () if (am_cheat > 0 || !(t->flags6 & MF6_NOTONAUTOMAP) || (am_thingrenderstyles && !(t->renderflags & RF_INVISIBLE) && !(t->flags6 & MF6_NOTONAUTOMAP))) { - DVector3 pos = t->InterpolatedPosition(r_viewpoint.TicFrac) + t->Level->Displacements.getOffset(sec.PortalGroup, MapPortalGroup); + DVector3 fracPos = t->InterpolatedPosition(r_viewpoint.TicFrac); + FVector2 pos = FVector2(float(fracPos.X),float(fracPos.Y)) + FVector2(t->Level->Displacements.getOffset(sec.PortalGroup, MapPortalGroup)) + FVector2(t->AutomapOffsets); p.x = pos.X; p.y = pos.Y; @@ -2966,14 +2977,14 @@ void DAutomap::drawThings () spriteframe_t *frame; int rotation = 0; - // try all modes backwards until a valid texture has been found. + // try all modes backwards until a valid texture has been found. for(int show = am_showthingsprites; show > 0 && texture == nullptr; show--) { const spritedef_t& sprite = sprites[t->sprite]; const size_t spriteIndex = sprite.spriteframes + (show > 1 ? t->frame : 0); frame = &SpriteFrames[spriteIndex]; - DAngle angle = DAngle::fromDeg(270. + 22.5) - t->InterpolatedAngles(r_viewpoint.TicFrac).Yaw; + DAngle angle = DAngle::fromDeg(270.) - t->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - t->SpriteRotation; if (frame->Texture[0] != frame->Texture[1]) angle += DAngle::fromDeg(180. / 16); if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { @@ -3078,7 +3089,7 @@ void DAutomap::drawThings () //============================================================================= void DAutomap::DrawMarker (FGameTexture *tex, double x, double y, int yadjust, - INTBOOL flip, double xscale, double yscale, int translation, double alpha, uint32_t fillcolor, FRenderStyle renderstyle) + INTBOOL flip, double xscale, double yscale, FTranslationID translation, double alpha, uint32_t fillcolor, FRenderStyle renderstyle) { if (tex == nullptr || !tex->isValid()) { @@ -3101,7 +3112,7 @@ void DAutomap::DrawMarker (FGameTexture *tex, double x, double y, int yadjust, DTA_ClipLeft, f_x, DTA_ClipRight, f_x + f_w, DTA_FlipX, flip, - DTA_TranslationIndex, translation, + DTA_TranslationIndex, translation.index(), DTA_Alpha, alpha, DTA_FillColor, fillcolor, DTA_RenderStyle, renderstyle.AsDWORD, @@ -3132,7 +3143,7 @@ void DAutomap::drawMarks () if (font == nullptr) { DrawMarker(TexMan.GetGameTexture(marknums[i], true), markpoints[i].x, markpoints[i].y, -3, 0, - 1, 1, 0, 1, 0, LegacyRenderStyles[STYLE_Normal]); + 1, 1, NO_TRANSLATION, 1, 0, LegacyRenderStyles[STYLE_Normal]); } else { @@ -3453,7 +3464,7 @@ void AM_ToggleMap() if (!primaryLevel || !primaryLevel->automap) return; - if (!automapactive && (primaryLevel->flags9 & LEVEL9_NOAUTOMAP)) + if (!automapactive && (primaryLevel->vkdflags & VKDLEVELFLAG_NOAUTOMAP)) return; if (!automapactive) diff --git a/src/bbannouncer.cpp b/src/bbannouncer.cpp index 18f85c14e9..07bc2305e7 100644 --- a/src/bbannouncer.cpp +++ b/src/bbannouncer.cpp @@ -261,7 +261,7 @@ bool AnnounceKill (AActor *killer, AActor *killee) playSound |= killer->CheckLocalView(); } - message = GStrings(choice->Message); + message = GStrings.GetString(choice->Message); if (message != NULL) { char assembled[1024]; @@ -293,7 +293,7 @@ bool AnnounceTelefrag (AActor *killer, AActor *killee) if (cl_bbannounce && multiplayer) { - const char *message = GStrings("OB_MPTELEFRAG"); + const char *message = GStrings.GetString("OB_MPTELEFRAG"); if (message != NULL) { char assembled[1024]; diff --git a/src/common/2d/v_2ddrawer.cpp b/src/common/2d/v_2ddrawer.cpp index 375dcc6acb..ffb753491d 100644 --- a/src/common/2d/v_2ddrawer.cpp +++ b/src/common/2d/v_2ddrawer.cpp @@ -68,7 +68,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Clear, Shape2DTransform_Clear) static void Shape2DTransform_Rotate(DShape2DTransform* self, double angle) { - self->transform = DMatrix3x3::Rotate2D(DEG2RAD(angle)) * self->transform; + self->transform = DMatrix3x3::Rotate2D(angle) * self->transform; } DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Rotate, Shape2DTransform_Rotate) @@ -443,7 +443,7 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) if (img->isWarped()) dg.mFlags |= DTF_Wrap; if (parms.indexed) dg.mFlags |= DTF_Indexed; - dg.mTranslationId = 0; + dg.mTranslationId = NO_TRANSLATION; SetStyle(img, parms, vertexcolor, dg); if (parms.indexed) { @@ -451,7 +451,7 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) vertexcolor = 0xffffffff; } - if (!img->isHardwareCanvas() && parms.TranslationId != -1) + if (!img->isHardwareCanvas() && parms.TranslationId != INVALID_TRANSLATION) { dg.mTranslationId = parms.TranslationId; } @@ -607,7 +607,7 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms) dg.mFlags |= DTF_Wrap; dg.mTexture = img; - dg.mTranslationId = 0; + dg.mTranslationId = NO_TRANSLATION; SetStyle(img, parms, vertexcolor, dg); if (shape->lastParms == nullptr) { @@ -624,7 +624,7 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms) shape->lastParms = new DrawParms(parms); } - if (!(img != nullptr && img->isHardwareCanvas()) && parms.TranslationId != -1) + if (!(img != nullptr && img->isHardwareCanvas()) && parms.TranslationId != INVALID_TRANSLATION) dg.mTranslationId = parms.TranslationId; auto osave = offset; @@ -796,7 +796,7 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints, // //========================================================================== -void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const unsigned int* ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, const IntRect* clip) +void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const unsigned int* ind, size_t idxcount, FTranslationID translation, PalEntry color, FRenderStyle style, const IntRect* clip) { RenderCommand dg; @@ -1217,7 +1217,7 @@ void F2DDrawer::OnFrameDone() F2DVertexBuffer::F2DVertexBuffer() { static const FVertexBufferAttribute format[] = { - { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(F2DDrawer::TwoDVertex, x) }, + { 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(F2DDrawer::TwoDVertex, x) }, { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(F2DDrawer::TwoDVertex, u) }, { 0, VATTR_COLOR, VFmt_Byte4, (int)myoffsetof(F2DDrawer::TwoDVertex, color0) } }; @@ -1248,7 +1248,7 @@ class InitTextureCanvasGC FCanvas* GetTextureCanvas(const FString& texturename) { - FTextureID textureid = TexMan.CheckForTexture(texturename, ETextureType::Wall, FTextureManager::TEXMAN_Overridable); + FTextureID textureid = TexMan.CheckForTexture(texturename.GetChars(), ETextureType::Wall, FTextureManager::TEXMAN_Overridable); if (textureid.isValid()) { // Only proceed if the texture is a canvas texture. diff --git a/src/common/2d/v_2ddrawer.h b/src/common/2d/v_2ddrawer.h index 48b18496a2..1445a168f1 100644 --- a/src/common/2d/v_2ddrawer.h +++ b/src/common/2d/v_2ddrawer.h @@ -88,7 +88,7 @@ class F2DDrawer // This vertex type is hardware independent and needs conversion when put into a buffer. struct TwoDVertex { - float x, y, z; + float x, y, z, lindex; float u, v; PalEntry color0; @@ -100,6 +100,7 @@ class F2DDrawer u = 0; v = 0; color0 = 0; + lindex = -1.0f; } void Set(double xx, double yy, double zz, double uu, double vv, PalEntry col) @@ -110,6 +111,7 @@ class F2DDrawer u = (float)uu; v = (float)vv; color0 = col; + lindex = -1.0f; } }; @@ -131,7 +133,7 @@ class F2DDrawer int mIndexCount; FGameTexture *mTexture; - int mTranslationId; + FTranslationID mTranslationId; PalEntry mSpecialColormap[2]; int mScissor[4]; int mDesaturate; @@ -192,7 +194,7 @@ class F2DDrawer TArray mVertices; TArray mData; int Width, Height; - bool isIn2D; + bool isIn2D = false; bool locked = false; // prevents clearing of the data so it can be reused multiple times (useful for screen fades) float screenFade = 1.f; DVector2 offset; @@ -216,8 +218,8 @@ class F2DDrawer void AddPoly(FGameTexture *texture, FVector2 *points, int npoints, double originx, double originy, double scalex, double scaley, DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double lightlevel, uint32_t *indices, size_t indexcount); - void AddPoly(FGameTexture* img, FVector4 *vt, size_t vtcount, const unsigned int *ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, const IntRect* clip); - void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex, + void AddPoly(FGameTexture* img, FVector4 *vt, size_t vtcount, const unsigned int *ind, size_t idxcount, FTranslationID translation, PalEntry color, FRenderStyle style, const IntRect* clip); + void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int pic, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex, int clipx1, int clipy1, int clipx2, int clipy2); void AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, int local_origin = false, double flatscale = 1.0, PalEntry color = 0xffffffff, ERenderStyle rs = STYLE_Normal); @@ -317,7 +319,7 @@ class DShape2D : public DObject RefCountedPtr bufferInfo; - DrawParms* lastParms; + DrawParms* lastParms = nullptr; void OnDestroy() override; }; diff --git a/src/common/2d/v_draw.cpp b/src/common/2d/v_draw.cpp index 7c1beb0c8d..247a2916dc 100644 --- a/src/common/2d/v_draw.cpp +++ b/src/common/2d/v_draw.cpp @@ -831,7 +831,7 @@ static inline FSpecialColormap * ListGetSpecialColormap(VMVa_List &tags) //========================================================================== template -bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, int type, PalEntry fill, double fillalpha) +bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, int type, PalEntry fill, double fillalpha, bool scriptDifferences) { INTBOOL boolval; int intval; @@ -866,7 +866,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double parms->destheight = INT_MAX; parms->Alpha = type == DrawTexture_Fill ? (float)fillalpha : 1.f; parms->fillcolor = type == DrawTexture_Fill ? fill : PalEntry(~0u); - parms->TranslationId = -1; + parms->TranslationId = INVALID_TRANSLATION; parms->colorOverlay = 0; parms->alphaChannel = false; parms->flipX = false; @@ -886,6 +886,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double parms->scalex = parms->scaley = 1; parms->cellx = parms->celly = 0; parms->maxstrlen = INT_MAX; + parms->localize = scriptDifferences; parms->virtBottom = false; parms->srcx = 0.; parms->srcy = 0.; @@ -1089,7 +1090,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_TranslationIndex: - parms->TranslationId = ListGetInt(tags); + parms->TranslationId = FTranslationID::fromInt(ListGetInt(tags)); break; case DTA_ColorOverlay: @@ -1323,6 +1324,10 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double parms->maxstrlen = ListGetInt(tags); break; + case DTA_Localize: + parms->localize = ListGetInt(tags); + break; + case DTA_CellX: parms->cellx = ListGetInt(tags); break; @@ -1434,8 +1439,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double } // explicitly instantiate both versions for v_text.cpp. -template bool ParseDrawTextureTags(F2DDrawer* drawer, FGameTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, int type, PalEntry fill, double fillalpha); -template bool ParseDrawTextureTags(F2DDrawer* drawer, FGameTexture *img, double x, double y, uint32_t tag, VMVa_List& tags, DrawParms *parms, int type, PalEntry fill, double fillalpha); +template bool ParseDrawTextureTags(F2DDrawer* drawer, FGameTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, int type, PalEntry fill, double fillalpha, bool scriptDifferences); +template bool ParseDrawTextureTags(F2DDrawer* drawer, FGameTexture *img, double x, double y, uint32_t tag, VMVa_List& tags, DrawParms *parms, int type, PalEntry fill, double fillalpha, bool scriptDifferences); //========================================================================== // @@ -1786,12 +1791,12 @@ DEFINE_ACTION_FUNCTION(FCanvas, Dim) // //========================================================================== -void DrawBorder (F2DDrawer *drawer, FTextureID picnum, int x1, int y1, int x2, int y2) +void DrawBorder (F2DDrawer *drawer, FTextureID texid, int x1, int y1, int x2, int y2) { int filltype = (ui_screenborder_classic_scaling) ? -1 : 0; - if (picnum.isValid()) + if (texid.isValid()) { - drawer->AddFlatFill (x1, y1, x2, y2, TexMan.GetGameTexture(picnum, false), filltype); + drawer->AddFlatFill (x1, y1, x2, y2, TexMan.GetGameTexture(texid, false), filltype); } else { diff --git a/src/common/2d/v_draw.h b/src/common/2d/v_draw.h index 686e5dc46d..e98ca92456 100644 --- a/src/common/2d/v_draw.h +++ b/src/common/2d/v_draw.h @@ -132,6 +132,7 @@ enum DTA_Indexed, // Use an indexed texture combined with the given translation. DTA_CleanTop, // Like DTA_Clean but aligns to the top of the screen instead of the center. DTA_NoOffset, // Ignore 2D drawer's offset. + DTA_Localize, // localize drawn string, for DrawText only }; @@ -175,7 +176,7 @@ struct DrawParms double left; float Alpha; PalEntry fillcolor; - int TranslationId; + FTranslationID TranslationId; PalEntry colorOverlay; PalEntry color; int alphaChannel; @@ -194,6 +195,7 @@ struct DrawParms int monospace; int spacing; int maxstrlen; + bool localize; bool fortext; bool virtBottom; bool burn; @@ -266,7 +268,7 @@ enum }; template -bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture* img, double x, double y, uint32_t tag, T& tags, DrawParms* parms, int type, PalEntry fill = ~0u, double fillalpha = 0.0); +bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture* img, double x, double y, uint32_t tag, T& tags, DrawParms* parms, int type, PalEntry fill = ~0u, double fillalpha = 0.0, bool scriptDifferences = false); template void DrawTextCommon(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double y, const T* string, DrawParms& parms); diff --git a/src/common/2d/v_drawtext.cpp b/src/common/2d/v_drawtext.cpp index 2bdb64dcad..56415a84fd 100644 --- a/src/common/2d/v_drawtext.cpp +++ b/src/common/2d/v_drawtext.cpp @@ -185,7 +185,7 @@ void DrawChar(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double { return; } - bool palettetrans = (normalcolor == CR_NATIVEPAL && parms.TranslationId != 0); + bool palettetrans = (normalcolor == CR_NATIVEPAL && parms.TranslationId != NO_TRANSLATION); PalEntry color = 0xffffffff; if (!palettetrans) parms.TranslationId = font->GetColorTranslation((EColorRange)normalcolor, &color); parms.color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255); @@ -210,7 +210,7 @@ void DrawChar(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double uint32_t tag = ListGetInt(args); bool res = ParseDrawTextureTags(drawer, pic, x, y, tag, args, &parms, DrawTexture_Normal); if (!res) return; - bool palettetrans = (normalcolor == CR_NATIVEPAL && parms.TranslationId != 0); + bool palettetrans = (normalcolor == CR_NATIVEPAL && parms.TranslationId != NO_TRANSLATION); PalEntry color = 0xffffffff; if (!palettetrans) parms.TranslationId = font->GetColorTranslation((EColorRange)normalcolor, &color); parms.color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255); @@ -272,7 +272,7 @@ void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, d double cx; double cy; int boldcolor; - int trans = -1; + FTranslationID trans = INVALID_TRANSLATION; int kerning; FGameTexture *pic; @@ -282,7 +282,7 @@ void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, d if (parms.celly == 0) parms.celly = font->GetHeight() + 1; parms.celly = int (parms.celly * scaley); - bool palettetrans = (normalcolor == CR_NATIVEPAL && parms.TranslationId != 0); + bool palettetrans = (normalcolor == CR_NATIVEPAL && parms.TranslationId != NO_TRANSLATION); if (normalcolor >= NumTextColors) normalcolor = CR_UNTRANSLATED; @@ -290,7 +290,7 @@ void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, d PalEntry colorparm = parms.color; PalEntry color = 0xffffffff; - trans = palettetrans? -1 : font->GetColorTranslation((EColorRange)normalcolor, &color); + trans = palettetrans? INVALID_TRANSLATION : font->GetColorTranslation((EColorRange)normalcolor, &color); parms.color = PalEntry(colorparm.a, (color.r * colorparm.r) / 255, (color.g * colorparm.g) / 255, (color.b * colorparm.b) / 255); kerning = font->GetDefaultKerning(); @@ -380,6 +380,7 @@ void DrawText(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double { return; } + const char *txt = (parms.localize && string[0] == '$') ? GStrings.GetString(&string[1]) : string; DrawTextCommon(drawer, font, normalcolor, x, y, (const uint8_t*)string, parms); } @@ -399,24 +400,27 @@ void DrawText(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double { return; } + // [Gutawer] right now nothing needs the char32_t version to have localisation support, and i don't know how to do it + assert(parms.localize == false); DrawTextCommon(drawer, font, normalcolor, x, y, string, parms); } -void DrawText(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args) +void DrawText(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double y, const FString& string, VMVa_List &args) { DrawParms parms; - if (font == NULL || string == NULL) + if (font == NULL) return; uint32_t tag = ListGetInt(args); - bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag, args, &parms, DrawTexture_Text); + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag, args, &parms, DrawTexture_Text, ~0u, 0.0, true); if (!res) { return; } - DrawTextCommon(drawer, font, normalcolor, x, y, (const uint8_t*)string, parms); + const char *txt = (parms.localize && string[0] == '$') ? GStrings.GetString(&string[1]) : string.GetChars(); + DrawTextCommon(drawer, font, normalcolor, x, y, (uint8_t*)txt, parms); } DEFINE_ACTION_FUNCTION(_Screen, DrawText) @@ -432,8 +436,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawText) if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); VMVa_List args = { param + 5, 0, numparam - 6, va_reginfo + 5 }; - const char *txt = chr[0] == '$' ? GStrings(&chr[1]) : chr.GetChars(); - DrawText(twod, font, cr, x, y, txt, args); + DrawText(twod, font, cr, x, y, chr, args); return 0; } @@ -450,8 +453,7 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawText) PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array VMVa_List args = { param + 6, 0, numparam - 7, va_reginfo + 6 }; - const char *txt = chr[0] == '$' ? GStrings(&chr[1]) : chr.GetChars(); - DrawText(&self->Drawer, font, cr, x, y, txt, args); + DrawText(&self->Drawer, font, cr, x, y, chr, args); self->Tex->NeedUpdate(); return 0; } diff --git a/src/common/2d/wipe.cpp b/src/common/2d/wipe.cpp index cc57ca29f3..f359e3d189 100644 --- a/src/common/2d/wipe.cpp +++ b/src/common/2d/wipe.cpp @@ -208,6 +208,21 @@ class Wiper_Burn : public Wiper int BurnTime = 8; }; +class Wiper_Fizzlefade : public Wiper +{ +public: + ~Wiper_Fizzlefade(); + bool Run(int ticks) override; + void SetTextures(FGameTexture* startscreen, FGameTexture* endscreen) override; + +private: + static const int WIDTH = 512, HEIGHT = 256; + uint8_t FizzleArray[WIDTH * HEIGHT] = { 0 }; + FBurnTexture* FizzleTexture = nullptr; + + uint32_t rndval = 1; +}; + //=========================================================================== // // Screen wipes @@ -220,13 +235,16 @@ Wiper *Wiper::Create(int type) { case wipe_Burn: return new Wiper_Burn; - + case wipe_Fade: return new Wiper_Crossfade; case wipe_Melt: return new Wiper_Melt; - + + case wipe_Fizzlefade: + return new Wiper_Fizzlefade; + default: return nullptr; } @@ -361,7 +379,7 @@ void Wiper_Burn::SetTextures(FGameTexture *startscreen, FGameTexture *endscreen) BurnTexture = new FBurnTexture(WIDTH, HEIGHT); auto mat = FMaterial::ValidateTexture(endScreen, false); mat->ClearLayers(); - mat->AddTextureLayer(BurnTexture, false); + mat->AddTextureLayer(BurnTexture, false, MaterialLayerSampling::Default); } //========================================================================== @@ -418,6 +436,69 @@ bool Wiper_Burn::Run(int ticks) return done || (BurnTime > 40); } +//========================================================================== + +void Wiper_Fizzlefade::SetTextures(FGameTexture* startscreen, FGameTexture* endscreen) +{ + startScreen = startscreen; + endScreen = endscreen; + FizzleTexture = new FBurnTexture(WIDTH, HEIGHT); + auto mat = FMaterial::ValidateTexture(endScreen, false); + mat->ClearLayers(); + mat->AddTextureLayer(FizzleTexture, false, MaterialLayerSampling::Default); +} + +Wiper_Fizzlefade::~Wiper_Fizzlefade() +{ + delete FizzleTexture; +} + +bool Wiper_Fizzlefade::Run(int ticks) +{ + bool done = false; + + ticks *= 5000; + for (int i = 0; i < ticks; i++) + { + uint32_t y = rndval & 0x000FF; + uint32_t x = (rndval & 0x1FF00) >> 8; + uint32_t lsb = rndval & 1; + rndval >>= 1; + if (lsb) + { + rndval ^= 0x00012000; + } + + FizzleArray[x + (y << 9)] = 255; + + if (rndval == 1) + { + done = true; + break; + } + } + + FizzleTexture->CleanHardwareTextures(); + endScreen->CleanHardwareData(false); // this only cleans the descriptor sets for the Vulkan backend. We do not want to delete the wipe screen's hardware texture here. + + uint8_t* src = FizzleArray; + uint32_t* dest = (uint32_t*)FizzleTexture->GetBuffer(); + for (int y = HEIGHT; y != 0; --y) + { + for (int x = WIDTH; x != 0; --x) + { + uint8_t s = *src++; + *dest++ = MAKEARGB(s, 255, 255, 255); + } + } + + DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); + DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Burn, true, DTA_Masked, false, TAG_DONE); + + return done; +} + +//========================================================================== void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stopsound, std::function overlaydrawer) { diff --git a/src/common/2d/wipe.h b/src/common/2d/wipe.h index 08a7eeb3bd..4113906430 100644 --- a/src/common/2d/wipe.h +++ b/src/common/2d/wipe.h @@ -12,6 +12,7 @@ enum wipe_Melt, // weird screen melt wipe_Burn, // fade in shape of fire wipe_Fade, // crossfade from old to new + wipe_Fizzlefade, // wolf3d fizzle fade from old to new wipe_NUMWIPES }; diff --git a/src/common/audio/music/i_music.cpp b/src/common/audio/music/i_music.cpp index 0bc8582923..b30a27f130 100644 --- a/src/common/audio/music/i_music.cpp +++ b/src/common/audio/music/i_music.cpp @@ -37,10 +37,9 @@ #include #endif -#include +#include #include -#include "m_argv.h" #include "filesystem.h" #include "c_dispatch.h" @@ -54,6 +53,7 @@ #include "s_music.h" #include "filereadermusicinterface.h" +using namespace FileSys; void I_InitSoundFonts(); @@ -70,7 +70,7 @@ int nomusic = 0; // Maximum volume of MOD/stream music. //========================================================================== -CUSTOM_CVARD(Float, snd_musicvolume, 0.5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls music volume") +CUSTOM_CVARD(Float, snd_musicvolume, 1.0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls music volume") { if (self < 0.f) self = 0.f; @@ -82,7 +82,7 @@ CUSTOM_CVARD(Float, snd_musicvolume, 0.5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "contr ChangeMusicSetting(zmusic_snd_musicvolume, nullptr, self); if (GSnd != nullptr) { - GSnd->SetMusicVolume(clamp(self * relative_volume * snd_mastervolume, 0, 1)); + GSnd->SetMusicVolume(clamp(self * relative_volume * snd_mastervolume * 0.75f, 0, 1)); } // For music not implemented through the digital sound system, // let them know about the change. @@ -180,11 +180,10 @@ static void SetupGenMidi() Printf("No GENMIDI lump found. OPL playback not available.\n"); return; } - auto data = fileSystem.OpenFileReader(lump); + auto genmidi = fileSystem.ReadFile(lump); - auto genmidi = data.Read(); - if (genmidi.Size() < 8 + 175 * 36 || memcmp(genmidi.Data(), "#OPL_II#", 8)) return; - ZMusic_SetGenMidi(genmidi.Data()+8); + if (genmidi.size() < 8 + 175 * 36 || memcmp(genmidi.data(), "#OPL_II#", 8)) return; + ZMusic_SetGenMidi(genmidi.bytes() + 8); } static void SetupWgOpn() @@ -194,8 +193,8 @@ static void SetupWgOpn() { return; } - FileData data = fileSystem.ReadFile(lump); - ZMusic_SetWgOpn(data.GetMem(), (uint32_t)data.GetSize()); + auto data = fileSystem.ReadFile(lump); + ZMusic_SetWgOpn(data.data(), (uint32_t)data.size()); } static void SetupDMXGUS() @@ -206,8 +205,8 @@ static void SetupDMXGUS() { return; } - FileData data = fileSystem.ReadFile(lump); - ZMusic_SetDmxGus(data.GetMem(), (uint32_t)data.GetSize()); + auto data = fileSystem.ReadFile(lump); + ZMusic_SetDmxGus(data.data(), (uint32_t)data.size()); } #endif @@ -218,13 +217,13 @@ static void SetupDMXGUS() // //========================================================================== -void I_InitMusic(void) +void I_InitMusic(int musicstate) { I_InitSoundFonts(); snd_musicvolume->Callback (); - nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound"); + nomusic = musicstate; snd_mididevice->Callback(); @@ -313,8 +312,8 @@ static ZMusic_MidiSource GetMIDISource(const char *fn) FString src = fn; if (src.Compare("*") == 0) src = mus_playing.name; - auto lump = fileSystem.CheckNumForName(src, ns_music); - if (lump < 0) lump = fileSystem.CheckNumForFullName(src); + auto lump = fileSystem.CheckNumForName(src.GetChars(), ns_music); + if (lump < 0) lump = fileSystem.CheckNumForFullName(src.GetChars()); if (lump < 0) { Printf("Cannot find MIDI lump %s.\n", src.GetChars()); @@ -338,7 +337,7 @@ static ZMusic_MidiSource GetMIDISource(const char *fn) } auto data = wlump.Read(); - auto source = ZMusic_CreateMIDISource(data.Data(), data.Size(), type); + auto source = ZMusic_CreateMIDISource(data.bytes(), data.size(), type); if (source == nullptr) { @@ -392,7 +391,7 @@ UNSAFE_CCMD (writewave) Printf("MIDI dump of %s failed: %s\n",argv[1], ZMusic_GetLastError()); } - S_ChangeMusic(savedsong.name, savedsong.baseorder, savedsong.loop, true); + S_ChangeMusic(savedsong.name.GetChars(), savedsong.baseorder, savedsong.loop, true); } else { diff --git a/src/common/audio/music/i_music.h b/src/common/audio/music/i_music.h index a6609eadbe..aa2d48e628 100644 --- a/src/common/audio/music/i_music.h +++ b/src/common/audio/music/i_music.h @@ -34,27 +34,16 @@ #ifndef __I_MUSIC_H__ #define __I_MUSIC_H__ -#include "c_cvars.h" - -class FileReader; -struct FOptionValues; - // // MUSIC I/O // -void I_InitMusic (); -void I_BuildMIDIMenuList (FOptionValues *); +void I_InitMusic (int); // Volume. void I_SetRelativeVolume(float); void I_SetMusicVolume (double volume); -extern int nomusic; - -EXTERN_CVAR(Bool, mus_enabled) -EXTERN_CVAR(Float, snd_musicvolume) - inline float AmplitudeTodB(float amplitude) { diff --git a/src/common/audio/music/i_soundfont.cpp b/src/common/audio/music/i_soundfont.cpp index af1c5634c8..9737374fc4 100644 --- a/src/common/audio/music/i_soundfont.cpp +++ b/src/common/audio/music/i_soundfont.cpp @@ -40,9 +40,9 @@ #include "i_system.h" #include "filereadermusicinterface.h" #include -#include "resourcefile.h" +#include "fs_filesystem.h" #include "version.h" -#include "findfile.h" +#include "fs_findfile.h" #include "i_interface.h" #include "configfile.h" #include "printf.h" @@ -68,7 +68,7 @@ std::pair FSoundFontReader::LookupFile(const char *name) for(int i = mPaths.Size()-1; i>=0; i--) { FString fullname = mPaths[i] + name; - auto fr = OpenFile(fullname); + auto fr = OpenFile(fullname.GetChars()); if (fr.isOpen()) return std::make_pair(std::move(fr), fullname); } } @@ -93,7 +93,7 @@ void FSoundFontReader::AddPath(const char *strp) if (str.Back() != '/') str += '/'; // always let it end with a slash. for (auto &s : mPaths) { - if (pathcmp(s.GetChars(), str) == 0) + if (pathcmp(s.GetChars(), str.GetChars()) == 0) { // move string to the back. mPaths.Delete(i); @@ -122,13 +122,13 @@ FileReader FSoundFontReader::Open(const char *name, std::string& filename) if (name == nullptr) { fr = OpenMainConfigFile(); - filename = MainConfigFileName(); + filename = MainConfigFileName().GetChars(); } else { auto res = LookupFile(name); fr = std::move(res.first); - filename = res.second; + filename = res.second.GetChars(); } return fr; } @@ -197,7 +197,7 @@ FileReader FSF2Reader::OpenFile(const char *name) FZipPatReader::FZipPatReader(const char *filename) { mAllowAbsolutePaths = true; - resf = FResourceFile::OpenResourceFile(filename, true); + resf = FResourceFile::OpenResourceFile(filename); } FZipPatReader::~FZipPatReader() @@ -215,10 +215,10 @@ FileReader FZipPatReader::OpenFile(const char *name) FileReader fr; if (resf != nullptr) { - auto lump = resf->FindLump(name); - if (lump != nullptr) + auto lump = resf->FindEntry(name); + if (lump >= 0) { - return lump->NewReader(); + return resf->GetEntryReader(lump, FileSys::READER_NEW, FileSys::READERFLAG_SEEKABLE); } } fr.OpenFile(name); @@ -244,7 +244,7 @@ FPatchSetReader::FPatchSetReader(const char *filename) const char *paths[] = { "C:/TIMIDITY", "/TIMIDITY", - progdir + progdir.GetChars() }; #endif mAllowAbsolutePaths = true; @@ -258,7 +258,7 @@ FPatchSetReader::FPatchSetReader(const char *filename) for(auto c : paths) { FStringf fullname("%s/%s", c, filename); - if (fr.OpenFile(fullname)) + if (fr.OpenFile(fullname.GetChars())) { mFullPathToConfig = fullname; } @@ -267,7 +267,7 @@ FPatchSetReader::FPatchSetReader(const char *filename) if (mFullPathToConfig.Len() > 0) { FixPathSeperator(mFullPathToConfig); - mBasePath = ExtractFilePath(mFullPathToConfig); + mBasePath = ExtractFilePath(mFullPathToConfig.GetChars()); if (mBasePath.Len() > 0 && mBasePath.Back() != '/') mBasePath += '/'; } } @@ -276,7 +276,7 @@ FPatchSetReader::FPatchSetReader(const char *filename) FileReader FPatchSetReader::OpenMainConfigFile() { FileReader fr; - fr.OpenFile(mFullPathToConfig); + fr.OpenFile(mFullPathToConfig.GetChars()); return fr; } @@ -286,7 +286,7 @@ FileReader FPatchSetReader::OpenFile(const char *name) if (IsAbsPath(name)) path = name; else path = mBasePath + name; FileReader fr; - fr.OpenFile(path); + fr.OpenFile(path.GetChars()); return fr; } @@ -302,7 +302,7 @@ FLumpPatchSetReader::FLumpPatchSetReader(const char *filename) mBasePath = filename; FixPathSeperator(mBasePath); - mBasePath = ExtractFilePath(mBasePath); + mBasePath = ExtractFilePath(mBasePath.GetChars()); if (mBasePath.Len() > 0 && mBasePath.Back() != '/') mBasePath += '/'; } @@ -316,7 +316,7 @@ FileReader FLumpPatchSetReader::OpenFile(const char *name) FString path; if (IsAbsPath(name)) return FileReader(); // no absolute paths in the lump directory. path = mBasePath + name; - auto index = fileSystem.CheckNumForFullName(path); + auto index = fileSystem.CheckNumForFullName(path.GetChars()); if (index < 0) return FileReader(); return fileSystem.ReopenFileReader(index); } @@ -331,7 +331,7 @@ FileReader FLumpPatchSetReader::OpenFile(const char *name) // //========================================================================== -void FSoundFontManager::ProcessOneFile(const FString &fn) +void FSoundFontManager::ProcessOneFile(const char* fn) { auto fb = ExtractFileBase(fn, false); auto fbe = ExtractFileBase(fn, true); @@ -367,10 +367,10 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) auto zip = FResourceFile::OpenResourceFile(fn, true); if (zip != nullptr) { - if (zip->LumpCount() > 1) // Anything with just one lump cannot possibly be a packed GUS patch set so skip it right away and simplify the lookup code + if (zip->EntryCount() > 1) // Anything with just one lump cannot possibly be a packed GUS patch set so skip it right away and simplify the lookup code { - auto zipl = zip->FindLump("timidity.cfg"); - if (zipl != nullptr) + auto zipl = zip->FindEntry("timidity.cfg"); + if (zipl >= 0) { // It seems like this is what we are looking for FSoundFontInfo sft = { fb, fbe, fn, SF_GUS }; @@ -391,9 +391,6 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) void FSoundFontManager::CollectSoundfonts() { - findstate_t c_file; - void *file; - FConfigFile* GameConfig = sysCallbacks.GetConfig ? sysCallbacks.GetConfig() : nullptr; if (GameConfig != NULL && GameConfig->SetSection ("SoundfontSearch.Directories")) { @@ -404,25 +401,23 @@ void FSoundFontManager::CollectSoundfonts() { if (stricmp (key, "Path") == 0) { + FileSys::FileList list; + FString dir; dir = NicePath(value); FixPathSeperator(dir); if (dir.IsNotEmpty()) { - if (dir.Back() != '/') dir += '/'; - FString mask = dir + '*'; - if ((file = I_FindFirst(mask, &c_file)) != ((void *)(-1))) + if (FileSys::ScanDirectory(list, dir.GetChars(), "*", true)) { - do + for(auto& entry : list) { - if (!(I_FindAttr(&c_file) & FA_DIREC)) + if (!entry.isDirectory) { - FStringf name("%s%s", dir.GetChars(), I_FindName(&c_file)); - ProcessOneFile(name); + ProcessOneFile(entry.FilePath.c_str()); } - } while (I_FindNext(file, &c_file) == 0); - I_FindClose(file); + } } } } @@ -431,7 +426,7 @@ void FSoundFontManager::CollectSoundfonts() if (soundfonts.Size() == 0) { - ProcessOneFile(NicePath("$PROGDIR/soundfonts/" GAMENAMELOWERCASE ".sf2")); + ProcessOneFile(NicePath("$PROGDIR/soundfonts/" GAMENAMELOWERCASE ".sf2").GetChars()); } } @@ -470,19 +465,16 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all // //========================================================================== -FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed) +FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *const name, int allowed) { - + if (name == nullptr) return nullptr; // First check if the given name is inside the loaded resources. // To avoid clashes this will only be done if the name has the '.cfg' extension. // Sound fonts cannot be loaded this way. - if (name != nullptr) + const char *p = name + strlen(name) - 4; + if (p > name && !stricmp(p, ".cfg") && fileSystem.CheckNumForFullName(name) >= 0) { - const char *p = name + strlen(name) - 4; - if (p > name && !stricmp(p, ".cfg") && fileSystem.CheckNumForFullName(name) >= 0) - { - return new FLumpPatchSetReader(name); - } + return new FLumpPatchSetReader(name); } // Next check if the file is a .sf file @@ -528,8 +520,8 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed auto sfi = FindSoundFont(name, allowed); if (sfi != nullptr) { - if (sfi->type == SF_SF2) return new FSF2Reader(sfi->mFilename); - else return new FZipPatReader(sfi->mFilename); + if (sfi->type == SF_SF2) return new FSF2Reader(sfi->mFilename.GetChars()); + else return new FZipPatReader(sfi->mFilename.GetChars()); } return nullptr; diff --git a/src/common/audio/music/i_soundfont.h b/src/common/audio/music/i_soundfont.h index ef02950710..45e5b0ffa8 100644 --- a/src/common/audio/music/i_soundfont.h +++ b/src/common/audio/music/i_soundfont.h @@ -148,7 +148,7 @@ class FSoundFontManager { TArray soundfonts; - void ProcessOneFile(const FString & fn); + void ProcessOneFile(const char* fn); public: void CollectSoundfonts(); diff --git a/src/common/audio/music/music.cpp b/src/common/audio/music/music.cpp index 610f0368f7..13837e93e7 100644 --- a/src/common/audio/music/music.cpp +++ b/src/common/audio/music/music.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "i_sound.h" #include "i_music.h" @@ -53,9 +54,13 @@ #include "gain_analysis.h" #include "i_specialpaths.h" #include "configfile.h" +#include "c_cvars.h" +#include "md5.h" + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- +extern int nomusic; extern float S_GetMusicVolume (const char *music); static void S_ActivatePlayList(bool goBack); @@ -70,17 +75,17 @@ float saved_relative_volume = 1.0f; // this could be used to implement an ACS Fa MusicVolumeMap MusicVolumes; MidiDeviceMap MidiDevices; -static FileReader DefaultOpenMusic(const char* fn) +static int DefaultFindMusic(const char* fn) { - // This is the minimum needed to make the music system functional. - FileReader fr; - fr.OpenFile(fn); - return fr; + return -1; } -static MusicCallbacks mus_cb = { nullptr, DefaultOpenMusic }; + +MusicCallbacks mus_cb = { nullptr, DefaultFindMusic }; // PUBLIC DATA DEFINITIONS ------------------------------------------------- +EXTERN_CVAR(Bool, mus_enabled) +EXTERN_CVAR(Float, snd_musicvolume) EXTERN_CVAR(Int, snd_mididevice) EXTERN_CVAR(Float, mod_dumb_mastervolume) EXTERN_CVAR(Float, fluid_gain) @@ -88,18 +93,47 @@ EXTERN_CVAR(Float, fluid_gain) CVAR(Bool, mus_calcgain, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song. CVAR(Bool, mus_usereplaygain, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song. -CUSTOM_CVAR(Float, mus_gainoffset, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // for customizing the base volume -{ - if (self > 10.f) self = 10.f; - mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset); -} // CODE -------------------------------------------------------------------- +//========================================================================== +// +// OpenMusic +// +// opens a FileReader for the music - used as a callback to keep +// implementation details out of the core player. +// +//========================================================================== + +static FileReader OpenMusic(const char* musicname) +{ + FileReader reader; + if (!FileExists(musicname)) + { + int lumpnum; + lumpnum = mus_cb.FindMusic(musicname); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, FileSys::ns_music); + if (lumpnum == -1) + { + Printf("Music \"%s\" not found\n", musicname); + } + else if (fileSystem.FileLength(lumpnum) != 0) + { + reader = fileSystem.ReopenFileReader(lumpnum); + } + } + else + { + // Load an external file. + reader.OpenFile(musicname); + } + return reader; +} + void S_SetMusicCallbacks(MusicCallbacks* cb) { mus_cb = *cb; - if (mus_cb.OpenMusic == nullptr) mus_cb.OpenMusic = DefaultOpenMusic; // without this we are dead in the water. + if (mus_cb.FindMusic == nullptr) mus_cb.FindMusic = DefaultFindMusic; // without this we are dead in the water. } int MusicEnabled() // int return is for scripting @@ -161,12 +195,12 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) if (mus_playing.isfloat) { written = ZMusic_FillStream(mus_playing.handle, buff, len); - if (mus_playing.replayGainFactor != 1.f) + if (mus_playing.musicVolume != 1.f) { float* fbuf = (float*)buff; for (int i = 0; i < len / 4; i++) { - fbuf[i] *= mus_playing.replayGainFactor; + fbuf[i] *= mus_playing.musicVolume; } } } @@ -178,7 +212,7 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) float* fbuf = (float*)buff; for (int i = 0; i < len / 4; i++) { - fbuf[i] = convert[i] * mus_playing.replayGainFactor * (1.f/32768.f); + fbuf[i] = convert[i] * mus_playing.musicVolume * (1.f/32768.f); } } @@ -398,14 +432,14 @@ static FString ReplayGainHash(ZMusicCustomReader* reader, int flength, int playe { std::string playparam = _playparam; - uint8_t buffer[50000]; // for performance reasons only hash the start of the file. If we wanted to do this to large waveform songs it'd cause noticable lag. + TArray buffer(50000, true); // for performance reasons only hash the start of the file. If we wanted to do this to large waveform songs it'd cause noticable lag. uint8_t digest[16]; char digestout[33]; - auto length = reader->read(reader, buffer, 50000); + auto length = reader->read(reader, buffer.data(), 50000); reader->seek(reader, 0, SEEK_SET); MD5Context md5; md5.Init(); - md5.Update(buffer, (int)length); + md5.Update(buffer.data(), (int)length); md5.Final(digest); for (size_t j = 0; j < sizeof(digest); ++j) @@ -414,7 +448,7 @@ static FString ReplayGainHash(ZMusicCustomReader* reader, int flength, int playe } digestout[32] = 0; - auto type = ZMusic_IdentifyMIDIType((uint32_t*)buffer, 32); + auto type = ZMusic_IdentifyMIDIType((uint32_t*)buffer.data(), 32); if (type == MIDI_NOTMIDI) return FStringf("%d:%s", flength, digestout); // get the default for MIDI synth @@ -457,7 +491,7 @@ static void SaveGains() { auto path = M_GetAppDataPath(true); path << "/replaygain.ini"; - FConfigFile gains(path); + FConfigFile gains(path.GetChars()); TMap::Iterator it(gainMap); TMap::Pair* pair; @@ -465,7 +499,7 @@ static void SaveGains() { while (it.NextPair(pair)) { - gains.SetValueForKey(pair->Key, std::to_string(pair->Value).c_str()); + gains.SetValueForKey(pair->Key.GetChars(), std::to_string(pair->Value).c_str()); } } gains.WriteConfigFile(); @@ -478,7 +512,7 @@ static void ReadGains() done = true; auto path = M_GetAppDataPath(true); path << "/replaygain.ini"; - FConfigFile gains(path); + FConfigFile gains(path.GetChars()); if (gains.SetSection("Gains")) { const char* key; @@ -502,26 +536,24 @@ CCMD(setreplaygain) if (argv.argc() < 2) { Printf("Usage: setreplaygain {dB}\n"); - Printf("Current replay gain is %f dB\n", mus_playing.replayGain); + Printf("Current replay gain is %f dB\n", AmplitudeTodB(mus_playing.musicVolume)); return; } float dB = (float)strtod(argv[1], nullptr); if (dB > 10) dB = 10; // don't blast the speakers. Values above 2 or 3 are very rare. gainMap.Insert(mus_playing.hash, dB); SaveGains(); - mus_playing.replayGain = dB; - mus_playing.replayGainFactor = (float)dBToAmplitude(mus_playing.replayGain + mus_gainoffset); + mus_playing.musicVolume = (float)dBToAmplitude(dB); } static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const char *playparam) { - mus_playing.replayGain = 0.f; - mus_playing.replayGainFactor = dBToAmplitude(mus_gainoffset); + mus_playing.musicVolume = 1; fluid_gain->Callback(); mod_dumb_mastervolume->Callback(); if (!mus_usereplaygain) return; - FileReader reader = mus_cb.OpenMusic(musicname); + FileReader reader = OpenMusic(musicname); if (!reader.isOpen()) return; int flength = (int)reader.GetLength(); auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper. @@ -533,8 +565,7 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const auto entry = gainMap.CheckKey(hash); if (entry) { - mus_playing.replayGain = *entry; - mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset); + mus_playing.musicVolume = dBToAmplitude(*entry); return; } if (!mus_calcgain) return; @@ -618,19 +649,18 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const } ZMusic_Close(handle); - GainAnalyzer analyzer; - int result = analyzer.InitGainAnalysis(fmt.mSampleRate); + auto analyzer = std::make_unique(); + int result = analyzer->InitGainAnalysis(fmt.mSampleRate); if (result == GAIN_ANALYSIS_OK) { - result = analyzer.AnalyzeSamples(lbuffer.Data(), rbuffer.Size() == 0 ? nullptr : rbuffer.Data(), lbuffer.Size(), rbuffer.Size() == 0 ? 1 : 2); + result = analyzer->AnalyzeSamples(lbuffer.Data(), rbuffer.Size() == 0 ? nullptr : rbuffer.Data(), lbuffer.Size(), rbuffer.Size() == 0 ? 1 : 2); if (result == GAIN_ANALYSIS_OK) { - auto gain = analyzer.GetTitleGain(); - Printf("Calculated replay gain for %s at %f dB\n", hash.GetChars(), gain); + auto gain = analyzer->GetTitleGain(); + Printf("Calculated replay gain for %s (%s) at %f dB\n", musicname, hash.GetChars(), gain); gainMap.Insert(hash, gain); - mus_playing.replayGain = gain; - mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset); + mus_playing.musicVolume = dBToAmplitude(gain); SaveGains(); } } @@ -663,7 +693,7 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) if (!mus_playing.name.IsEmpty() && mus_playing.handle != nullptr && - stricmp(mus_playing.name, musicname) == 0 && + mus_playing.name.CompareNoCase(musicname) == 0 && ZMusic_IsLooping(mus_playing.handle) == zmusic_bool(looping)) { if (order != mus_playing.baseorder) @@ -686,7 +716,6 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) } ZMusic_MusicStream handle = nullptr; - MidiDeviceSetting* devp = MidiDevices.CheckKey(musicname); // Strip off any leading file:// component. if (strncmp(musicname, "file://", 7) == 0) @@ -695,8 +724,10 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) } // opening the music must be done by the game because it's different depending on the game's file system use. - FileReader reader = mus_cb.OpenMusic(musicname); + FileReader reader = OpenMusic(musicname); if (!reader.isOpen()) return false; + auto m = reader.Read(); + reader.Seek(0, FileReader::SeekSet); // shutdown old music S_StopMusic(true); @@ -718,8 +749,19 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) } else { + int lumpnum = mus_cb.FindMusic(musicname); + MidiDeviceSetting* devp = MidiDevices.CheckKey(lumpnum); - CheckReplayGain(musicname, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : ""); + auto volp = MusicVolumes.CheckKey(lumpnum); + if (volp) + { + mus_playing.musicVolume = *volp; + + } + else + { + CheckReplayGain(musicname, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : ""); + } auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper. mus_playing.handle = ZMusic_OpenSong(mreader, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : ""); if (mus_playing.handle == nullptr) @@ -735,13 +777,12 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) if (mus_playing.handle != 0) { // play it - auto volp = MusicVolumes.CheckKey(musicname); - float vol = volp ? *volp : 1.f; - if (!S_StartMusicPlaying(mus_playing.handle, looping, vol, order)) + if (!S_StartMusicPlaying(mus_playing.handle, looping, 1.f, order)) { Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError()); return false; } + S_CreateStream(); mus_playing.baseorder = order; return true; @@ -762,7 +803,7 @@ void S_RestartMusic () { FString song = mus_playing.LastSong; mus_playing.LastSong = ""; - S_ChangeMusic (song, mus_playing.baseorder, mus_playing.loop, true); + S_ChangeMusic (song.GetChars(), mus_playing.baseorder, mus_playing.loop, true); } else { @@ -785,7 +826,7 @@ void S_MIDIDeviceChanged(int newdev) // Reload the song to change the device auto mi = mus_playing; S_StopMusic(true); - S_ChangeMusic(mi.name, mi.baseorder, mi.loop); + S_ChangeMusic(mi.name.GetChars(), mi.baseorder, mi.loop); } } @@ -801,7 +842,7 @@ int S_GetMusic (const char **name) if (mus_playing.name.IsNotEmpty()) { - *name = mus_playing.name; + *name = mus_playing.name.GetChars(); order = mus_playing.baseorder; } else diff --git a/src/common/audio/music/s_music.h b/src/common/audio/music/s_music.h index 1970a57daf..cddfd36d62 100644 --- a/src/common/audio/music/s_music.h +++ b/src/common/audio/music/s_music.h @@ -5,9 +5,9 @@ #include "zstring.h" #include "tarray.h" #include "name.h" +#include "files.h" #include -class FileReader; class SoundStream; @@ -24,7 +24,7 @@ void S_PauseAllCustomStreams(bool on); struct MusicCallbacks { FString(*LookupFileName)(const char* fn, int &order); - FileReader(*OpenMusic)(const char* fn); + int(*FindMusic)(const char* fn); }; void S_SetMusicCallbacks(MusicCallbacks* cb); @@ -68,19 +68,20 @@ struct MidiDeviceSetting FString args; }; -typedef TMap MidiDeviceMap; -typedef TMap MusicVolumeMap; +typedef TMap MidiDeviceMap; +typedef TMap MusicVolumeMap; extern MidiDeviceMap MidiDevices; extern MusicVolumeMap MusicVolumes; +extern MusicCallbacks mus_cb; struct MusPlayingInfo { FString name; ZMusic_MusicStream handle; + int lumpnum; int baseorder; - float replayGain; - float replayGainFactor; + float musicVolume; bool loop; bool isfloat; FString LastSong; // last music that was played diff --git a/src/common/audio/sound/alext.h b/src/common/audio/sound/alext.h deleted file mode 100644 index edfae47353..0000000000 --- a/src/common/audio/sound/alext.h +++ /dev/null @@ -1,643 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 2008 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#ifndef AL_ALEXT_H -#define AL_ALEXT_H - -#include -/* Define int64 and uint64 types */ -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) -#include -typedef int64_t _alsoft_int64_t; -typedef uint64_t _alsoft_uint64_t; -#elif defined(_WIN32) -typedef __int64 _alsoft_int64_t; -typedef unsigned __int64 _alsoft_uint64_t; -#else -/* Fallback if nothing above works */ -#include -typedef int64_t _alsoft_int64_t; -typedef uint64_t _alsoft_uint64_t; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef AL_LOKI_IMA_ADPCM_format -#define AL_LOKI_IMA_ADPCM_format 1 -#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000 -#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001 -#endif - -#ifndef AL_LOKI_WAVE_format -#define AL_LOKI_WAVE_format 1 -#define AL_FORMAT_WAVE_EXT 0x10002 -#endif - -#ifndef AL_EXT_vorbis -#define AL_EXT_vorbis 1 -#define AL_FORMAT_VORBIS_EXT 0x10003 -#endif - -#ifndef AL_LOKI_quadriphonic -#define AL_LOKI_quadriphonic 1 -#define AL_FORMAT_QUAD8_LOKI 0x10004 -#define AL_FORMAT_QUAD16_LOKI 0x10005 -#endif - -#ifndef AL_EXT_float32 -#define AL_EXT_float32 1 -#define AL_FORMAT_MONO_FLOAT32 0x10010 -#define AL_FORMAT_STEREO_FLOAT32 0x10011 -#endif - -#ifndef AL_EXT_double -#define AL_EXT_double 1 -#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012 -#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013 -#endif - -#ifndef AL_EXT_MULAW -#define AL_EXT_MULAW 1 -#define AL_FORMAT_MONO_MULAW_EXT 0x10014 -#define AL_FORMAT_STEREO_MULAW_EXT 0x10015 -#endif - -#ifndef AL_EXT_ALAW -#define AL_EXT_ALAW 1 -#define AL_FORMAT_MONO_ALAW_EXT 0x10016 -#define AL_FORMAT_STEREO_ALAW_EXT 0x10017 -#endif - -#ifndef ALC_LOKI_audio_channel -#define ALC_LOKI_audio_channel 1 -#define ALC_CHAN_MAIN_LOKI 0x500001 -#define ALC_CHAN_PCM_LOKI 0x500002 -#define ALC_CHAN_CD_LOKI 0x500003 -#endif - -#ifndef AL_EXT_MCFORMATS -#define AL_EXT_MCFORMATS 1 -/* Provides support for surround sound buffer formats with 8, 16, and 32-bit - * samples. - * - * QUAD8: Unsigned 8-bit, Quadraphonic (Front Left, Front Right, Rear Left, - * Rear Right). - * QUAD16: Signed 16-bit, Quadraphonic. - * QUAD32: 32-bit float, Quadraphonic. - * REAR8: Unsigned 8-bit, Rear Stereo (Rear Left, Rear Right). - * REAR16: Signed 16-bit, Rear Stereo. - * REAR32: 32-bit float, Rear Stereo. - * 51CHN8: Unsigned 8-bit, 5.1 Surround (Front Left, Front Right, Front Center, - * LFE, Side Left, Side Right). Note that some audio systems may label - * 5.1's Side channels as Rear or Surround; they are equivalent for the - * purposes of this extension. - * 51CHN16: Signed 16-bit, 5.1 Surround. - * 51CHN32: 32-bit float, 5.1 Surround. - * 61CHN8: Unsigned 8-bit, 6.1 Surround (Front Left, Front Right, Front Center, - * LFE, Rear Center, Side Left, Side Right). - * 61CHN16: Signed 16-bit, 6.1 Surround. - * 61CHN32: 32-bit float, 6.1 Surround. - * 71CHN8: Unsigned 8-bit, 7.1 Surround (Front Left, Front Right, Front Center, - * LFE, Rear Left, Rear Right, Side Left, Side Right). - * 71CHN16: Signed 16-bit, 7.1 Surround. - * 71CHN32: 32-bit float, 7.1 Surround. - */ -#define AL_FORMAT_QUAD8 0x1204 -#define AL_FORMAT_QUAD16 0x1205 -#define AL_FORMAT_QUAD32 0x1206 -#define AL_FORMAT_REAR8 0x1207 -#define AL_FORMAT_REAR16 0x1208 -#define AL_FORMAT_REAR32 0x1209 -#define AL_FORMAT_51CHN8 0x120A -#define AL_FORMAT_51CHN16 0x120B -#define AL_FORMAT_51CHN32 0x120C -#define AL_FORMAT_61CHN8 0x120D -#define AL_FORMAT_61CHN16 0x120E -#define AL_FORMAT_61CHN32 0x120F -#define AL_FORMAT_71CHN8 0x1210 -#define AL_FORMAT_71CHN16 0x1211 -#define AL_FORMAT_71CHN32 0x1212 -#endif - -#ifndef AL_EXT_MULAW_MCFORMATS -#define AL_EXT_MULAW_MCFORMATS 1 -#define AL_FORMAT_MONO_MULAW 0x10014 -#define AL_FORMAT_STEREO_MULAW 0x10015 -#define AL_FORMAT_QUAD_MULAW 0x10021 -#define AL_FORMAT_REAR_MULAW 0x10022 -#define AL_FORMAT_51CHN_MULAW 0x10023 -#define AL_FORMAT_61CHN_MULAW 0x10024 -#define AL_FORMAT_71CHN_MULAW 0x10025 -#endif - -#ifndef AL_EXT_IMA4 -#define AL_EXT_IMA4 1 -#define AL_FORMAT_MONO_IMA4 0x1300 -#define AL_FORMAT_STEREO_IMA4 0x1301 -#endif - -#ifndef AL_EXT_STATIC_BUFFER -#define AL_EXT_STATIC_BUFFER 1 -typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq); -#endif -#endif - -#ifndef ALC_EXT_EFX -#define ALC_EXT_EFX 1 -#include "efx.h" -#endif - -#ifndef ALC_EXT_disconnect -#define ALC_EXT_disconnect 1 -#define ALC_CONNECTED 0x313 -#endif - -#ifndef ALC_EXT_thread_local_context -#define ALC_EXT_thread_local_context 1 -typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context); -ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); -#endif -#endif - -#ifndef AL_EXT_source_distance_model -#define AL_EXT_source_distance_model 1 -#define AL_SOURCE_DISTANCE_MODEL 0x200 -#endif - -#ifndef AL_SOFT_buffer_sub_data -#define AL_SOFT_buffer_sub_data 1 -#define AL_BYTE_RW_OFFSETS_SOFT 0x1031 -#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032 -typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); -#endif -#endif - -#ifndef AL_SOFT_loop_points -#define AL_SOFT_loop_points 1 -#define AL_LOOP_POINTS_SOFT 0x2015 -#endif - -#ifndef AL_EXT_FOLDBACK -#define AL_EXT_FOLDBACK 1 -#define AL_EXT_FOLDBACK_NAME "AL_EXT_FOLDBACK" -#define AL_FOLDBACK_EVENT_BLOCK 0x4112 -#define AL_FOLDBACK_EVENT_START 0x4111 -#define AL_FOLDBACK_EVENT_STOP 0x4113 -#define AL_FOLDBACK_MODE_MONO 0x4101 -#define AL_FOLDBACK_MODE_STEREO 0x4102 -typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback); -AL_API void AL_APIENTRY alRequestFoldbackStop(void); -#endif -#endif - -#ifndef ALC_EXT_DEDICATED -#define ALC_EXT_DEDICATED 1 -#define AL_DEDICATED_GAIN 0x0001 -#define AL_EFFECT_DEDICATED_DIALOGUE 0x9001 -#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000 -#endif - -#ifndef AL_SOFT_buffer_samples -#define AL_SOFT_buffer_samples 1 -/* Channel configurations */ -#define AL_MONO_SOFT 0x1500 -#define AL_STEREO_SOFT 0x1501 -#define AL_REAR_SOFT 0x1502 -#define AL_QUAD_SOFT 0x1503 -#define AL_5POINT1_SOFT 0x1504 -#define AL_6POINT1_SOFT 0x1505 -#define AL_7POINT1_SOFT 0x1506 - -/* Sample types */ -#define AL_BYTE_SOFT 0x1400 -#define AL_UNSIGNED_BYTE_SOFT 0x1401 -#define AL_SHORT_SOFT 0x1402 -#define AL_UNSIGNED_SHORT_SOFT 0x1403 -#define AL_INT_SOFT 0x1404 -#define AL_UNSIGNED_INT_SOFT 0x1405 -#define AL_FLOAT_SOFT 0x1406 -#define AL_DOUBLE_SOFT 0x1407 -#define AL_BYTE3_SOFT 0x1408 -#define AL_UNSIGNED_BYTE3_SOFT 0x1409 - -/* Storage formats */ -#define AL_MONO8_SOFT 0x1100 -#define AL_MONO16_SOFT 0x1101 -#define AL_MONO32F_SOFT 0x10010 -#define AL_STEREO8_SOFT 0x1102 -#define AL_STEREO16_SOFT 0x1103 -#define AL_STEREO32F_SOFT 0x10011 -#define AL_QUAD8_SOFT 0x1204 -#define AL_QUAD16_SOFT 0x1205 -#define AL_QUAD32F_SOFT 0x1206 -#define AL_REAR8_SOFT 0x1207 -#define AL_REAR16_SOFT 0x1208 -#define AL_REAR32F_SOFT 0x1209 -#define AL_5POINT1_8_SOFT 0x120A -#define AL_5POINT1_16_SOFT 0x120B -#define AL_5POINT1_32F_SOFT 0x120C -#define AL_6POINT1_8_SOFT 0x120D -#define AL_6POINT1_16_SOFT 0x120E -#define AL_6POINT1_32F_SOFT 0x120F -#define AL_7POINT1_8_SOFT 0x1210 -#define AL_7POINT1_16_SOFT 0x1211 -#define AL_7POINT1_32F_SOFT 0x1212 - -/* Buffer attributes */ -#define AL_INTERNAL_FORMAT_SOFT 0x2008 -#define AL_BYTE_LENGTH_SOFT 0x2009 -#define AL_SAMPLE_LENGTH_SOFT 0x200A -#define AL_SEC_LENGTH_SOFT 0x200B - -typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*); -typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data); -AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); -#endif -#endif - -#ifndef AL_SOFT_direct_channels -#define AL_SOFT_direct_channels 1 -#define AL_DIRECT_CHANNELS_SOFT 0x1033 -#endif - -#ifndef ALC_SOFT_loopback -#define ALC_SOFT_loopback 1 -#define ALC_FORMAT_CHANNELS_SOFT 0x1990 -#define ALC_FORMAT_TYPE_SOFT 0x1991 - -/* Sample types */ -#define ALC_BYTE_SOFT 0x1400 -#define ALC_UNSIGNED_BYTE_SOFT 0x1401 -#define ALC_SHORT_SOFT 0x1402 -#define ALC_UNSIGNED_SHORT_SOFT 0x1403 -#define ALC_INT_SOFT 0x1404 -#define ALC_UNSIGNED_INT_SOFT 0x1405 -#define ALC_FLOAT_SOFT 0x1406 - -/* Channel configurations */ -#define ALC_MONO_SOFT 0x1500 -#define ALC_STEREO_SOFT 0x1501 -#define ALC_QUAD_SOFT 0x1503 -#define ALC_5POINT1_SOFT 0x1504 -#define ALC_6POINT1_SOFT 0x1505 -#define ALC_7POINT1_SOFT 0x1506 - -typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*); -typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum); -typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName); -ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type); -ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); -#endif -#endif - -#ifndef AL_EXT_STEREO_ANGLES -#define AL_EXT_STEREO_ANGLES 1 -#define AL_STEREO_ANGLES 0x1030 -#endif - -#ifndef AL_EXT_SOURCE_RADIUS -#define AL_EXT_SOURCE_RADIUS 1 -#define AL_SOURCE_RADIUS 0x1031 -#endif - -#ifndef AL_SOFT_source_latency -#define AL_SOFT_source_latency 1 -#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200 -#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201 -typedef _alsoft_int64_t ALint64SOFT; -typedef _alsoft_uint64_t ALuint64SOFT; -typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value); -AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3); -AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values); -AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value); -AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3); -AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values); -AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value); -AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3); -AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values); -AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value); -AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3); -AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values); -#endif -#endif - -#ifndef ALC_EXT_DEFAULT_FILTER_ORDER -#define ALC_EXT_DEFAULT_FILTER_ORDER 1 -#define ALC_DEFAULT_FILTER_ORDER 0x1100 -#endif - -#ifndef AL_SOFT_deferred_updates -#define AL_SOFT_deferred_updates 1 -#define AL_DEFERRED_UPDATES_SOFT 0xC002 -typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void); -typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alDeferUpdatesSOFT(void); -AL_API void AL_APIENTRY alProcessUpdatesSOFT(void); -#endif -#endif - -#ifndef AL_SOFT_block_alignment -#define AL_SOFT_block_alignment 1 -#define AL_UNPACK_BLOCK_ALIGNMENT_SOFT 0x200C -#define AL_PACK_BLOCK_ALIGNMENT_SOFT 0x200D -#endif - -#ifndef AL_SOFT_MSADPCM -#define AL_SOFT_MSADPCM 1 -#define AL_FORMAT_MONO_MSADPCM_SOFT 0x1302 -#define AL_FORMAT_STEREO_MSADPCM_SOFT 0x1303 -#endif - -#ifndef AL_SOFT_source_length -#define AL_SOFT_source_length 1 -/*#define AL_BYTE_LENGTH_SOFT 0x2009*/ -/*#define AL_SAMPLE_LENGTH_SOFT 0x200A*/ -/*#define AL_SEC_LENGTH_SOFT 0x200B*/ -#endif - -#ifndef ALC_SOFT_pause_device -#define ALC_SOFT_pause_device 1 -typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device); -typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device); -ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); -#endif -#endif - -#ifndef AL_EXT_BFORMAT -#define AL_EXT_BFORMAT 1 -/* Provides support for B-Format ambisonic buffers (first-order, FuMa scaling - * and layout). - * - * BFORMAT2D_8: Unsigned 8-bit, 3-channel non-periphonic (WXY). - * BFORMAT2D_16: Signed 16-bit, 3-channel non-periphonic (WXY). - * BFORMAT2D_FLOAT32: 32-bit float, 3-channel non-periphonic (WXY). - * BFORMAT3D_8: Unsigned 8-bit, 4-channel periphonic (WXYZ). - * BFORMAT3D_16: Signed 16-bit, 4-channel periphonic (WXYZ). - * BFORMAT3D_FLOAT32: 32-bit float, 4-channel periphonic (WXYZ). - */ -#define AL_FORMAT_BFORMAT2D_8 0x20021 -#define AL_FORMAT_BFORMAT2D_16 0x20022 -#define AL_FORMAT_BFORMAT2D_FLOAT32 0x20023 -#define AL_FORMAT_BFORMAT3D_8 0x20031 -#define AL_FORMAT_BFORMAT3D_16 0x20032 -#define AL_FORMAT_BFORMAT3D_FLOAT32 0x20033 -#endif - -#ifndef AL_EXT_MULAW_BFORMAT -#define AL_EXT_MULAW_BFORMAT 1 -#define AL_FORMAT_BFORMAT2D_MULAW 0x10031 -#define AL_FORMAT_BFORMAT3D_MULAW 0x10032 -#endif - -#ifndef ALC_SOFT_HRTF -#define ALC_SOFT_HRTF 1 -#define ALC_HRTF_SOFT 0x1992 -#define ALC_DONT_CARE_SOFT 0x0002 -#define ALC_HRTF_STATUS_SOFT 0x1993 -#define ALC_HRTF_DISABLED_SOFT 0x0000 -#define ALC_HRTF_ENABLED_SOFT 0x0001 -#define ALC_HRTF_DENIED_SOFT 0x0002 -#define ALC_HRTF_REQUIRED_SOFT 0x0003 -#define ALC_HRTF_HEADPHONES_DETECTED_SOFT 0x0004 -#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT 0x0005 -#define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994 -#define ALC_HRTF_SPECIFIER_SOFT 0x1995 -#define ALC_HRTF_ID_SOFT 0x1996 -typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index); -typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index); -ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs); -#endif -#endif - -#ifndef AL_SOFT_gain_clamp_ex -#define AL_SOFT_gain_clamp_ex 1 -#define AL_GAIN_LIMIT_SOFT 0x200E -#endif - -#ifndef AL_SOFT_source_resampler -#define AL_SOFT_source_resampler -#define AL_NUM_RESAMPLERS_SOFT 0x1210 -#define AL_DEFAULT_RESAMPLER_SOFT 0x1211 -#define AL_SOURCE_RESAMPLER_SOFT 0x1212 -#define AL_RESAMPLER_NAME_SOFT 0x1213 -typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index); -#ifdef AL_ALEXT_PROTOTYPES -AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index); -#endif -#endif - -#ifndef AL_SOFT_source_spatialize -#define AL_SOFT_source_spatialize -#define AL_SOURCE_SPATIALIZE_SOFT 0x1214 -#define AL_AUTO_SOFT 0x0002 -#endif - -#ifndef ALC_SOFT_output_limiter -#define ALC_SOFT_output_limiter -#define ALC_OUTPUT_LIMITER_SOFT 0x199A -#endif - -#ifndef ALC_SOFT_device_clock -#define ALC_SOFT_device_clock 1 -typedef _alsoft_int64_t ALCint64SOFT; -typedef _alsoft_uint64_t ALCuint64SOFT; -#define ALC_DEVICE_CLOCK_SOFT 0x1600 -#define ALC_DEVICE_LATENCY_SOFT 0x1601 -#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602 -#define AL_SAMPLE_OFFSET_CLOCK_SOFT 0x1202 -#define AL_SEC_OFFSET_CLOCK_SOFT 0x1203 -typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); -#endif -#endif - -#ifndef AL_SOFT_direct_channels_remix -#define AL_SOFT_direct_channels_remix 1 -#define AL_DROP_UNMATCHED_SOFT 0x0001 -#define AL_REMIX_UNMATCHED_SOFT 0x0002 -#endif - -#ifndef AL_SOFT_bformat_ex -#define AL_SOFT_bformat_ex 1 -#define AL_AMBISONIC_LAYOUT_SOFT 0x1997 -#define AL_AMBISONIC_SCALING_SOFT 0x1998 - -/* Ambisonic layouts */ -#define AL_FUMA_SOFT 0x0000 -#define AL_ACN_SOFT 0x0001 - -/* Ambisonic scalings (normalization) */ -/*#define AL_FUMA_SOFT*/ -#define AL_SN3D_SOFT 0x0001 -#define AL_N3D_SOFT 0x0002 -#endif - -#ifndef ALC_SOFT_loopback_bformat -#define ALC_SOFT_loopback_bformat 1 -#define ALC_AMBISONIC_LAYOUT_SOFT 0x1997 -#define ALC_AMBISONIC_SCALING_SOFT 0x1998 -#define ALC_AMBISONIC_ORDER_SOFT 0x1999 -#define ALC_MAX_AMBISONIC_ORDER_SOFT 0x199B - -#define ALC_BFORMAT3D_SOFT 0x1507 - -/* Ambisonic layouts */ -#define ALC_FUMA_SOFT 0x0000 -#define ALC_ACN_SOFT 0x0001 - -/* Ambisonic scalings (normalization) */ -/*#define ALC_FUMA_SOFT*/ -#define ALC_SN3D_SOFT 0x0001 -#define ALC_N3D_SOFT 0x0002 -#endif - -#ifndef AL_SOFT_effect_target -#define AL_SOFT_effect_target -#define AL_EFFECTSLOT_TARGET_SOFT 0x199C -#endif - -#ifndef AL_SOFT_events -#define AL_SOFT_events 1 -#define AL_EVENT_CALLBACK_FUNCTION_SOFT 0x19A2 -#define AL_EVENT_CALLBACK_USER_PARAM_SOFT 0x19A3 -#define AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT 0x19A4 -#define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT 0x19A5 -#define AL_EVENT_TYPE_DISCONNECTED_SOFT 0x19A6 -typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param, - ALsizei length, const ALchar *message, - void *userParam); -typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable); -typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam); -typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname); -typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable); -AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam); -AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname); -AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values); -#endif -#endif - -#ifndef ALC_SOFT_reopen_device -#define ALC_SOFT_reopen_device -typedef ALCboolean (ALC_APIENTRY*LPALCREOPENDEVICESOFT)(ALCdevice *device, - const ALCchar *deviceName, const ALCint *attribs); -#ifdef AL_ALEXT_PROTOTYPES -ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *deviceName, - const ALCint *attribs); -#endif -#endif - -#ifndef AL_SOFT_callback_buffer -#define AL_SOFT_callback_buffer -#define AL_BUFFER_CALLBACK_FUNCTION_SOFT 0x19A0 -#define AL_BUFFER_CALLBACK_USER_PARAM_SOFT 0x19A1 -typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes); -typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); -typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value); -typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3); -typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); -AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr); -AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2); -AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr); -#endif -#endif - -#ifndef AL_SOFT_UHJ -#define AL_SOFT_UHJ -#define AL_FORMAT_UHJ2CHN8_SOFT 0x19A2 -#define AL_FORMAT_UHJ2CHN16_SOFT 0x19A3 -#define AL_FORMAT_UHJ2CHN_FLOAT32_SOFT 0x19A4 -#define AL_FORMAT_UHJ3CHN8_SOFT 0x19A5 -#define AL_FORMAT_UHJ3CHN16_SOFT 0x19A6 -#define AL_FORMAT_UHJ3CHN_FLOAT32_SOFT 0x19A7 -#define AL_FORMAT_UHJ4CHN8_SOFT 0x19A8 -#define AL_FORMAT_UHJ4CHN16_SOFT 0x19A9 -#define AL_FORMAT_UHJ4CHN_FLOAT32_SOFT 0x19AA - -#define AL_STEREO_MODE_SOFT 0x19B0 -#define AL_NORMAL_SOFT 0x0000 -#define AL_SUPER_STEREO_SOFT 0x0001 -#define AL_SUPER_STEREO_WIDTH_SOFT 0x19B1 -#endif - -#ifndef ALC_SOFT_output_mode -#define ALC_SOFT_output_mode -#define ALC_OUTPUT_MODE_SOFT 0x19AC -#define ALC_ANY_SOFT 0x19AD -/*#define ALC_MONO_SOFT 0x1500*/ -/*#define ALC_STEREO_SOFT 0x1501*/ -#define ALC_STEREO_BASIC_SOFT 0x19AE -#define ALC_STEREO_UHJ_SOFT 0x19AF -#define ALC_STEREO_HRTF_SOFT 0x19B2 -/*#define ALC_QUAD_SOFT 0x1503*/ -#define ALC_SURROUND_5_1_SOFT 0x1504 -#define ALC_SURROUND_6_1_SOFT 0x1505 -#define ALC_SURROUND_7_1_SOFT 0x1506 -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/common/audio/sound/i_sound.cpp b/src/common/audio/sound/i_sound.cpp index 5f9fdda189..f859ae0a80 100644 --- a/src/common/audio/sound/i_sound.cpp +++ b/src/common/audio/sound/i_sound.cpp @@ -88,14 +88,14 @@ void I_CloseSound (); // Maximum volume of all audio //========================================================================== -CUSTOM_CVAR(Float, snd_mastervolume, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +CUSTOM_CVAR(Float, snd_mastervolume, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { if (self < 0.f) self = 0.f; else if (self > 1.f) self = 1.f; - ChangeMusicSetting(zmusic_snd_mastervolume, nullptr, self); + ChangeMusicSetting(zmusic_snd_mastervolume, nullptr, self * 0.75f); snd_sfxvolume->Callback(); snd_musicvolume->Callback(); } @@ -107,7 +107,7 @@ CUSTOM_CVAR(Float, snd_mastervolume, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVA // Maximum volume of a sound effect. //========================================================================== -CUSTOM_CVAR (Float, snd_sfxvolume, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) +CUSTOM_CVAR (Float, snd_sfxvolume, 1.0f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) { if (self < 0.f) self = 0.f; @@ -115,7 +115,7 @@ CUSTOM_CVAR (Float, snd_sfxvolume, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOIN self = 1.f; else if (GSnd != NULL) { - GSnd->SetSfxVolume (self * snd_mastervolume); + GSnd->SetSfxVolume (self * snd_mastervolume * 0.50f); } } @@ -248,7 +248,7 @@ class NullSoundRenderer : public SoundRenderer void I_InitSound () { - FModule_SetProgDir(progdir); + FModule_SetProgDir(progdir.GetChars()); /* Get command line options: */ nosound = !!Args->CheckParm ("-nosound"); nosfx = !!Args->CheckParm ("-nosfx"); diff --git a/src/common/audio/sound/i_sound.h b/src/common/audio/sound/i_sound.h index 0805154946..e8e5a1a0e9 100644 --- a/src/common/audio/sound/i_sound.h +++ b/src/common/audio/sound/i_sound.h @@ -40,8 +40,8 @@ #include "i_soundinternal.h" #include "zstring.h" #include +#include "files.h" -class FileReader; struct FSoundChan; enum EStartSoundFlags diff --git a/src/common/audio/sound/i_soundinternal.h b/src/common/audio/sound/i_soundinternal.h index 1ef4178d4f..52dabeea3a 100644 --- a/src/common/audio/sound/i_soundinternal.h +++ b/src/common/audio/sound/i_soundinternal.h @@ -5,7 +5,6 @@ #include #include "vectors.h" -#include "tarray.h" #include "tflags.h" enum EChanFlag @@ -32,13 +31,12 @@ enum EChanFlag CHANF_LOCAL = 16384, // only plays locally for the calling actor CHANF_TRANSIENT = 32768, // Do not record in savegames - used for sounds that get restarted outside the sound system (e.g. ambients in SW and Blood) CHANF_FORCE = 65536, // Start, even if sound is paused. + CHANF_SINGULAR = 0x20000, // Only start if no sound of this name is already playing. }; typedef TFlags EChanFlags; DEFINE_TFLAGS_OPERATORS(EChanFlags) -class FileReader; - // For convenience, this structure matches FMOD_REVERB_PROPERTIES. // Since I can't very well #include system-specific stuff in the // main game files, I duplicate it here. @@ -77,14 +75,17 @@ struct REVERB_PROPERTIES unsigned int Flags; }; -#define REVERB_FLAGS_DECAYTIMESCALE 0x00000001 -#define REVERB_FLAGS_REFLECTIONSSCALE 0x00000002 -#define REVERB_FLAGS_REFLECTIONSDELAYSCALE 0x00000004 -#define REVERB_FLAGS_REVERBSCALE 0x00000008 -#define REVERB_FLAGS_REVERBDELAYSCALE 0x00000010 -#define REVERB_FLAGS_DECAYHFLIMIT 0x00000020 -#define REVERB_FLAGS_ECHOTIMESCALE 0x00000040 -#define REVERB_FLAGS_MODULATIONTIMESCALE 0x00000080 +enum EReverbFlags +{ + REVERB_FLAGS_DECAYTIMESCALE = 0x00000001, + REVERB_FLAGS_REFLECTIONSSCALE = 0x00000002, + REVERB_FLAGS_REFLECTIONSDELAYSCALE = 0x00000004, + REVERB_FLAGS_REVERBSCALE = 0x00000008, + REVERB_FLAGS_REVERBDELAYSCALE = 0x00000010, + REVERB_FLAGS_DECAYHFLIMIT = 0x00000020, + REVERB_FLAGS_ECHOTIMESCALE = 0x00000040, + REVERB_FLAGS_MODULATIONTIMESCALE = 0x00000080, +}; struct ReverbContainer { @@ -143,8 +144,6 @@ struct FISoundChannel EChanFlags ChanFlags; }; -class SoundStream; - void S_SetSoundPaused(int state); diff --git a/src/common/audio/sound/oalsound.cpp b/src/common/audio/sound/oalsound.cpp index 6f6e4e3ee0..8b20fb9c10 100644 --- a/src/common/audio/sound/oalsound.cpp +++ b/src/common/audio/sound/oalsound.cpp @@ -75,7 +75,7 @@ CVAR (String, snd_alresampler, "Default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) #define OPENALLIB1 "libopenal.1.dylib" #define OPENALLIB2 "OpenAL.framework/OpenAL" #else // !__APPLE__ -#define OPENALLIB1 NicePath("$PROGDIR/" OPENALLIB) +#define OPENALLIB1 NicePath("$PROGDIR/" OPENALLIB).GetChars() #define OPENALLIB2 OPENALLIB #endif @@ -598,6 +598,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect"); ALC.SOFT_HRTF = !!alcIsExtensionPresent(Device, "ALC_SOFT_HRTF"); ALC.SOFT_pause_device = !!alcIsExtensionPresent(Device, "ALC_SOFT_pause_device"); + ALC.SOFT_output_limiter = !!alcIsExtensionPresent(Device, "ALC_SOFT_output_limiter"); const ALCchar *current = NULL; if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT")) @@ -634,6 +635,11 @@ OpenALSoundRenderer::OpenALSoundRenderer() else attribs.Push(ALC_DONT_CARE_SOFT); } + if(ALC.SOFT_output_limiter) + { + attribs.Push(ALC_OUTPUT_LIMITER_SOFT); + attribs.Push(ALC_TRUE); + } // Other attribs..? attribs.Push(0); @@ -1141,7 +1147,7 @@ SoundHandle OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int length, int def return retval; } - std::vector data; + TArray data; unsigned total = 0; unsigned got; diff --git a/src/common/audio/sound/oalsound.h b/src/common/audio/sound/oalsound.h index 4b277bc25a..6e5c93a87a 100644 --- a/src/common/audio/sound/oalsound.h +++ b/src/common/audio/sound/oalsound.h @@ -21,7 +21,7 @@ #include "alc.h" #endif -#include "alext.h" +#include "thirdparty/alext.h" class OpenALSoundStream; diff --git a/src/common/audio/sound/s_environment.cpp b/src/common/audio/sound/s_environment.cpp index 7a2dbd9a50..5b4ea79f1e 100644 --- a/src/common/audio/sound/s_environment.cpp +++ b/src/common/audio/sound/s_environment.cpp @@ -538,7 +538,7 @@ void S_ReadReverbDef (FScanner &sc) while (sc.GetString ()) { - name = strdup (sc.String); + name = copystring(sc.String); sc.MustGetNumber (); id1 = sc.Number; sc.MustGetNumber (); diff --git a/src/common/audio/sound/s_reverbedit.cpp b/src/common/audio/sound/s_reverbedit.cpp index a8ce5ac0d8..4c01da23a2 100644 --- a/src/common/audio/sound/s_reverbedit.cpp +++ b/src/common/audio/sound/s_reverbedit.cpp @@ -227,7 +227,7 @@ void ExportEnvironments(const char *filename, uint32_t count, const ReverbContai { FString dest = M_GetDocumentsPath() + filename; - FileWriter *f = FileWriter::Open(dest); + FileWriter *f = FileWriter::Open(dest.GetChars()); if (f != nullptr) { @@ -509,13 +509,13 @@ CCMD(createenvironment) { if (S_FindEnvironment(reverbedit_name)) { - M_StartMessage(FStringf("An environment with the name '%s' already exists", *reverbedit_name), 1); + M_StartMessage(FStringf("An environment with the name '%s' already exists", *reverbedit_name).GetChars(), 1); return; } int id = (reverbedit_id1 << 8) + reverbedit_id2; if (S_FindEnvironment(id)) { - M_StartMessage(FStringf("An environment with the ID (%d, %d) already exists", *reverbedit_id1, *reverbedit_id2), 1); + M_StartMessage(FStringf("An environment with the ID (%d, %d) already exists", *reverbedit_id1, *reverbedit_id2).GetChars(), 1); return; } diff --git a/src/common/audio/sound/s_sound.cpp b/src/common/audio/sound/s_sound.cpp index f3b0fb4122..852d389f5a 100644 --- a/src/common/audio/sound/s_sound.cpp +++ b/src/common/audio/sound/s_sound.cpp @@ -488,7 +488,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, } // If this is a singular sound, don't play it if it's already playing. - if (sfx->bSingular && CheckSingular(sound_id)) + if ((sfx->bSingular || (flags & CHANF_SINGULAR)) && CheckSingular(sound_id)) { chanflags |= CHANF_EVICTED; } @@ -744,32 +744,32 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx) DPrintf(DMSG_NOTIFY, "Loading sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); auto sfxdata = ReadSound(sfx->lumpnum); - int size = sfxdata.Size(); + int size = (int)sfxdata.size(); if (size > 8) { - int32_t dmxlen = LittleLong(((int32_t *)sfxdata.Data())[1]); - + auto sfxp = sfxdata.data(); + int32_t dmxlen = LittleLong(((int32_t *)sfxp)[1]); // If the sound is voc, use the custom loader. - if (strncmp ((const char *)sfxdata.Data(), "Creative Voice File", 19) == 0) + if (size > 19 && memcmp (sfxp, "Creative Voice File", 19) == 0) { - sfx->data = GSnd->LoadSoundVoc(sfxdata.Data(), size); + sfx->data = GSnd->LoadSoundVoc(sfxp, size); } // If the sound is raw, just load it as such. else if (sfx->bLoadRAW) { - sfx->data = GSnd->LoadSoundRaw(sfxdata.Data(), size, sfx->RawRate, 1, 8, sfx->LoopStart); + sfx->data = GSnd->LoadSoundRaw(sfxp, size, sfx->RawRate, 1, 8, sfx->LoopStart); } // Otherwise, try the sound as DMX format. - else if (((uint8_t *)sfxdata.Data())[0] == 3 && ((uint8_t *)sfxdata.Data())[1] == 0 && dmxlen <= size - 8) + else if (((uint8_t *)sfxp)[0] == 3 && ((uint8_t *)sfxp)[1] == 0 && dmxlen <= size - 8) { - int frequency = LittleShort(((uint16_t *)sfxdata.Data())[1]); + int frequency = LittleShort(((uint16_t *)sfxp)[1]); if (frequency == 0) frequency = 11025; - sfx->data = GSnd->LoadSoundRaw(sfxdata.Data()+8, dmxlen, frequency, 1, 8, sfx->LoopStart); + sfx->data = GSnd->LoadSoundRaw(sfxp+8, dmxlen, frequency, 1, 8, sfx->LoopStart); } // If that fails, let the sound system try and figure it out. else { - sfx->data = GSnd->LoadSound(sfxdata.Data(), size, sfx->LoopStart, sfx->LoopEnd); + sfx->data = GSnd->LoadSound(sfxp, size, sfx->LoopStart, sfx->LoopEnd); } } @@ -1825,7 +1825,8 @@ void S_SetSoundPaused(int state) if ((state || i_soundinbackground) && !pauseext) { - S_ResumeSound(true); + if (!paused) + S_ResumeSound(true); if (GSnd != nullptr) { GSnd->SetInactive(SoundRenderer::INACTIVE_Active); @@ -1855,6 +1856,21 @@ CCMD(snd_listdrivers) GSnd->PrintDriversList(); } +//========================================================================== +// +// CCMD listsounds +// +//========================================================================== + +CCMD(listsounds) +{ + for (unsigned i = 1; i < soundEngine->GetNumSounds(); i++) + { + auto sfx = soundEngine->GetSfx(FSoundID::fromInt(i)); + Printf("%4d: name = %s, resId = %d, lumpnum = %d\n", i, sfx->name.GetChars(), sfx->ResourceId, sfx->lumpnum); + } +} + ADD_STAT(sound) { return GSnd->GatherStats(); diff --git a/src/common/audio/sound/s_soundinternal.h b/src/common/audio/sound/s_soundinternal.h index dae8a0ee29..1d007faef1 100644 --- a/src/common/audio/sound/s_soundinternal.h +++ b/src/common/audio/sound/s_soundinternal.h @@ -90,6 +90,7 @@ constexpr FSoundID INVALID_SOUND = FSoundID::fromInt(-1); float DefPitchMax = 0.f; // Randomized range with stronger control over pitch itself. int16_t NearLimit = 4; // 0 means unlimited. + int16_t UserVal = 0; // repurpose this gap for something useful uint8_t PitchMask = 0; bool bRandomHeader = false; bool bLoadRAW = false; @@ -99,17 +100,16 @@ constexpr FSoundID INVALID_SOUND = FSoundID::fromInt(-1); bool bTentative = true; bool bExternal = false; - TArray UserData; - int RawRate = 0; // Sample rate to use when bLoadRAW is true int LoopStart = -1; // -1 means no specific loop defined int LoopEnd = -1; // -1 means no specific loop defined + float Attenuation = 1.f; // Multiplies the attenuation passed to S_Sound. FSoundID link = NO_LINK; constexpr static FSoundID NO_LINK = FSoundID::fromInt(-1); + TArray UserData; FRolloffInfo Rolloff{}; - float Attenuation = 1.f; // Multiplies the attenuation passed to S_Sound. }; @@ -402,6 +402,12 @@ class SoundEngine FSoundID PickReplacement(FSoundID refid); void HashSounds(); void AddRandomSound(FSoundID Owner, TArray list); + + TArray& GetSounds() //We still need this for a short time... + { + return S_sfx; + } + }; @@ -426,4 +432,9 @@ inline FSoundID S_FindSound(const char* name) return soundEngine->FindSound(name); } +inline FSoundID S_FindSound(const FString& name) +{ + return soundEngine->FindSound(name.GetChars()); +} + int SoundEnabled(); diff --git a/src/common/audio/sound/thirdparty/alext.h b/src/common/audio/sound/thirdparty/alext.h index 7d2a95274a..edfae47353 100644 --- a/src/common/audio/sound/thirdparty/alext.h +++ b/src/common/audio/sound/thirdparty/alext.h @@ -13,8 +13,8 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * Or go to http://www.gnu.org/copyleft/lgpl.html */ @@ -22,22 +22,22 @@ #define AL_ALEXT_H #include -/* Define int64_t and uint64_t types */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#include -#elif defined(_WIN32) && defined(__GNUC__) +/* Define int64 and uint64 types */ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) #include +typedef int64_t _alsoft_int64_t; +typedef uint64_t _alsoft_uint64_t; #elif defined(_WIN32) -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; +typedef __int64 _alsoft_int64_t; +typedef unsigned __int64 _alsoft_uint64_t; #else /* Fallback if nothing above works */ -#include +#include +typedef int64_t _alsoft_int64_t; +typedef uint64_t _alsoft_uint64_t; #endif -#include "alc.h" -#include "al.h" - #ifdef __cplusplus extern "C" { #endif @@ -97,6 +97,31 @@ extern "C" { #ifndef AL_EXT_MCFORMATS #define AL_EXT_MCFORMATS 1 +/* Provides support for surround sound buffer formats with 8, 16, and 32-bit + * samples. + * + * QUAD8: Unsigned 8-bit, Quadraphonic (Front Left, Front Right, Rear Left, + * Rear Right). + * QUAD16: Signed 16-bit, Quadraphonic. + * QUAD32: 32-bit float, Quadraphonic. + * REAR8: Unsigned 8-bit, Rear Stereo (Rear Left, Rear Right). + * REAR16: Signed 16-bit, Rear Stereo. + * REAR32: 32-bit float, Rear Stereo. + * 51CHN8: Unsigned 8-bit, 5.1 Surround (Front Left, Front Right, Front Center, + * LFE, Side Left, Side Right). Note that some audio systems may label + * 5.1's Side channels as Rear or Surround; they are equivalent for the + * purposes of this extension. + * 51CHN16: Signed 16-bit, 5.1 Surround. + * 51CHN32: 32-bit float, 5.1 Surround. + * 61CHN8: Unsigned 8-bit, 6.1 Surround (Front Left, Front Right, Front Center, + * LFE, Rear Center, Side Left, Side Right). + * 61CHN16: Signed 16-bit, 6.1 Surround. + * 61CHN32: 32-bit float, 6.1 Surround. + * 71CHN8: Unsigned 8-bit, 7.1 Surround (Front Left, Front Right, Front Center, + * LFE, Rear Left, Rear Right, Side Left, Side Right). + * 71CHN16: Signed 16-bit, 7.1 Surround. + * 71CHN32: 32-bit float, 7.1 Surround. + */ #define AL_FORMAT_QUAD8 0x1204 #define AL_FORMAT_QUAD16 0x1205 #define AL_FORMAT_QUAD32 0x1206 @@ -133,9 +158,9 @@ extern "C" { #ifndef AL_EXT_STATIC_BUFFER #define AL_EXT_STATIC_BUFFER 1 -typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei); +typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei); #ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq); +AL_API void AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq); #endif #endif @@ -168,9 +193,9 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); #define AL_SOFT_buffer_sub_data 1 #define AL_BYTE_RW_OFFSETS_SOFT 0x1031 #define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032 -typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); +typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); #ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); +AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); #endif #endif @@ -318,8 +343,8 @@ ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffe #define AL_SOFT_source_latency 1 #define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200 #define AL_SEC_OFFSET_LATENCY_SOFT 0x1201 -typedef int64_t ALint64SOFT; -typedef uint64_t ALuint64SOFT; +typedef _alsoft_int64_t ALint64SOFT; +typedef _alsoft_uint64_t ALuint64SOFT; typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble); typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble); typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*); @@ -356,11 +381,11 @@ AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64 #ifndef AL_SOFT_deferred_updates #define AL_SOFT_deferred_updates 1 #define AL_DEFERRED_UPDATES_SOFT 0xC002 -typedef ALvoid (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void); -typedef ALvoid (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void); +typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void); +typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void); #ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void); -AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void); +AL_API void AL_APIENTRY alDeferUpdatesSOFT(void); +AL_API void AL_APIENTRY alProcessUpdatesSOFT(void); #endif #endif @@ -393,6 +418,224 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); #endif #endif +#ifndef AL_EXT_BFORMAT +#define AL_EXT_BFORMAT 1 +/* Provides support for B-Format ambisonic buffers (first-order, FuMa scaling + * and layout). + * + * BFORMAT2D_8: Unsigned 8-bit, 3-channel non-periphonic (WXY). + * BFORMAT2D_16: Signed 16-bit, 3-channel non-periphonic (WXY). + * BFORMAT2D_FLOAT32: 32-bit float, 3-channel non-periphonic (WXY). + * BFORMAT3D_8: Unsigned 8-bit, 4-channel periphonic (WXYZ). + * BFORMAT3D_16: Signed 16-bit, 4-channel periphonic (WXYZ). + * BFORMAT3D_FLOAT32: 32-bit float, 4-channel periphonic (WXYZ). + */ +#define AL_FORMAT_BFORMAT2D_8 0x20021 +#define AL_FORMAT_BFORMAT2D_16 0x20022 +#define AL_FORMAT_BFORMAT2D_FLOAT32 0x20023 +#define AL_FORMAT_BFORMAT3D_8 0x20031 +#define AL_FORMAT_BFORMAT3D_16 0x20032 +#define AL_FORMAT_BFORMAT3D_FLOAT32 0x20033 +#endif + +#ifndef AL_EXT_MULAW_BFORMAT +#define AL_EXT_MULAW_BFORMAT 1 +#define AL_FORMAT_BFORMAT2D_MULAW 0x10031 +#define AL_FORMAT_BFORMAT3D_MULAW 0x10032 +#endif + +#ifndef ALC_SOFT_HRTF +#define ALC_SOFT_HRTF 1 +#define ALC_HRTF_SOFT 0x1992 +#define ALC_DONT_CARE_SOFT 0x0002 +#define ALC_HRTF_STATUS_SOFT 0x1993 +#define ALC_HRTF_DISABLED_SOFT 0x0000 +#define ALC_HRTF_ENABLED_SOFT 0x0001 +#define ALC_HRTF_DENIED_SOFT 0x0002 +#define ALC_HRTF_REQUIRED_SOFT 0x0003 +#define ALC_HRTF_HEADPHONES_DETECTED_SOFT 0x0004 +#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT 0x0005 +#define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994 +#define ALC_HRTF_SPECIFIER_SOFT 0x1995 +#define ALC_HRTF_ID_SOFT 0x1996 +typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index); +typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs); +#ifdef AL_ALEXT_PROTOTYPES +ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index); +ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs); +#endif +#endif + +#ifndef AL_SOFT_gain_clamp_ex +#define AL_SOFT_gain_clamp_ex 1 +#define AL_GAIN_LIMIT_SOFT 0x200E +#endif + +#ifndef AL_SOFT_source_resampler +#define AL_SOFT_source_resampler +#define AL_NUM_RESAMPLERS_SOFT 0x1210 +#define AL_DEFAULT_RESAMPLER_SOFT 0x1211 +#define AL_SOURCE_RESAMPLER_SOFT 0x1212 +#define AL_RESAMPLER_NAME_SOFT 0x1213 +typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index); +#ifdef AL_ALEXT_PROTOTYPES +AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index); +#endif +#endif + +#ifndef AL_SOFT_source_spatialize +#define AL_SOFT_source_spatialize +#define AL_SOURCE_SPATIALIZE_SOFT 0x1214 +#define AL_AUTO_SOFT 0x0002 +#endif + +#ifndef ALC_SOFT_output_limiter +#define ALC_SOFT_output_limiter +#define ALC_OUTPUT_LIMITER_SOFT 0x199A +#endif + +#ifndef ALC_SOFT_device_clock +#define ALC_SOFT_device_clock 1 +typedef _alsoft_int64_t ALCint64SOFT; +typedef _alsoft_uint64_t ALCuint64SOFT; +#define ALC_DEVICE_CLOCK_SOFT 0x1600 +#define ALC_DEVICE_LATENCY_SOFT 0x1601 +#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602 +#define AL_SAMPLE_OFFSET_CLOCK_SOFT 0x1202 +#define AL_SEC_OFFSET_CLOCK_SOFT 0x1203 +typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); +#ifdef AL_ALEXT_PROTOTYPES +ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); +#endif +#endif + +#ifndef AL_SOFT_direct_channels_remix +#define AL_SOFT_direct_channels_remix 1 +#define AL_DROP_UNMATCHED_SOFT 0x0001 +#define AL_REMIX_UNMATCHED_SOFT 0x0002 +#endif + +#ifndef AL_SOFT_bformat_ex +#define AL_SOFT_bformat_ex 1 +#define AL_AMBISONIC_LAYOUT_SOFT 0x1997 +#define AL_AMBISONIC_SCALING_SOFT 0x1998 + +/* Ambisonic layouts */ +#define AL_FUMA_SOFT 0x0000 +#define AL_ACN_SOFT 0x0001 + +/* Ambisonic scalings (normalization) */ +/*#define AL_FUMA_SOFT*/ +#define AL_SN3D_SOFT 0x0001 +#define AL_N3D_SOFT 0x0002 +#endif + +#ifndef ALC_SOFT_loopback_bformat +#define ALC_SOFT_loopback_bformat 1 +#define ALC_AMBISONIC_LAYOUT_SOFT 0x1997 +#define ALC_AMBISONIC_SCALING_SOFT 0x1998 +#define ALC_AMBISONIC_ORDER_SOFT 0x1999 +#define ALC_MAX_AMBISONIC_ORDER_SOFT 0x199B + +#define ALC_BFORMAT3D_SOFT 0x1507 + +/* Ambisonic layouts */ +#define ALC_FUMA_SOFT 0x0000 +#define ALC_ACN_SOFT 0x0001 + +/* Ambisonic scalings (normalization) */ +/*#define ALC_FUMA_SOFT*/ +#define ALC_SN3D_SOFT 0x0001 +#define ALC_N3D_SOFT 0x0002 +#endif + +#ifndef AL_SOFT_effect_target +#define AL_SOFT_effect_target +#define AL_EFFECTSLOT_TARGET_SOFT 0x199C +#endif + +#ifndef AL_SOFT_events +#define AL_SOFT_events 1 +#define AL_EVENT_CALLBACK_FUNCTION_SOFT 0x19A2 +#define AL_EVENT_CALLBACK_USER_PARAM_SOFT 0x19A3 +#define AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT 0x19A4 +#define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT 0x19A5 +#define AL_EVENT_TYPE_DISCONNECTED_SOFT 0x19A6 +typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param, + ALsizei length, const ALchar *message, + void *userParam); +typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable); +typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam); +typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname); +typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values); +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable); +AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam); +AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname); +AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values); +#endif +#endif + +#ifndef ALC_SOFT_reopen_device +#define ALC_SOFT_reopen_device +typedef ALCboolean (ALC_APIENTRY*LPALCREOPENDEVICESOFT)(ALCdevice *device, + const ALCchar *deviceName, const ALCint *attribs); +#ifdef AL_ALEXT_PROTOTYPES +ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *deviceName, + const ALCint *attribs); +#endif +#endif + +#ifndef AL_SOFT_callback_buffer +#define AL_SOFT_callback_buffer +#define AL_BUFFER_CALLBACK_FUNCTION_SOFT 0x19A0 +#define AL_BUFFER_CALLBACK_USER_PARAM_SOFT 0x19A1 +typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes); +typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); +typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value); +typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3); +typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values); +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); +AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr); +AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2); +AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr); +#endif +#endif + +#ifndef AL_SOFT_UHJ +#define AL_SOFT_UHJ +#define AL_FORMAT_UHJ2CHN8_SOFT 0x19A2 +#define AL_FORMAT_UHJ2CHN16_SOFT 0x19A3 +#define AL_FORMAT_UHJ2CHN_FLOAT32_SOFT 0x19A4 +#define AL_FORMAT_UHJ3CHN8_SOFT 0x19A5 +#define AL_FORMAT_UHJ3CHN16_SOFT 0x19A6 +#define AL_FORMAT_UHJ3CHN_FLOAT32_SOFT 0x19A7 +#define AL_FORMAT_UHJ4CHN8_SOFT 0x19A8 +#define AL_FORMAT_UHJ4CHN16_SOFT 0x19A9 +#define AL_FORMAT_UHJ4CHN_FLOAT32_SOFT 0x19AA + +#define AL_STEREO_MODE_SOFT 0x19B0 +#define AL_NORMAL_SOFT 0x0000 +#define AL_SUPER_STEREO_SOFT 0x0001 +#define AL_SUPER_STEREO_WIDTH_SOFT 0x19B1 +#endif + +#ifndef ALC_SOFT_output_mode +#define ALC_SOFT_output_mode +#define ALC_OUTPUT_MODE_SOFT 0x19AC +#define ALC_ANY_SOFT 0x19AD +/*#define ALC_MONO_SOFT 0x1500*/ +/*#define ALC_STEREO_SOFT 0x1501*/ +#define ALC_STEREO_BASIC_SOFT 0x19AE +#define ALC_STEREO_UHJ_SOFT 0x19AF +#define ALC_STEREO_HRTF_SOFT 0x19B2 +/*#define ALC_QUAD_SOFT 0x1503*/ +#define ALC_SURROUND_5_1_SOFT 0x1504 +#define ALC_SURROUND_6_1_SOFT 0x1505 +#define ALC_SURROUND_7_1_SOFT 0x1506 +#endif + #ifdef __cplusplus } #endif diff --git a/src/common/console/c_bind.cpp b/src/common/console/c_bind.cpp index 90ceaedcef..fe794c736d 100644 --- a/src/common/console/c_bind.cpp +++ b/src/common/console/c_bind.cpp @@ -429,14 +429,14 @@ void FKeyBindings::ArchiveBindings(FConfigFile *f, const char *matchcmd) f->ClearKey(ConfigKeyName(i)); } } - else if (matchcmd == nullptr || stricmp(Binds[i], matchcmd) == 0) + else if (matchcmd == nullptr || Binds[i].CompareNoCase(matchcmd) == 0) { if (Binds[i][0] == '\1') { Binds[i] = ""; continue; } - f->SetValueForKey(ConfigKeyName(i), Binds[i]); + f->SetValueForKey(ConfigKeyName(i), Binds[i].GetChars()); if (matchcmd != nullptr) { // If saving a specific command, set a marker so that // it does not get saved in the general binding list. @@ -465,7 +465,7 @@ int FKeyBindings::GetKeysForCommand (const char *cmd, int *first, int *second) while (i < NUM_KEYS && c < 2) { - if (stricmp (cmd, Binds[i]) == 0) + if (stricmp (cmd, Binds[i].GetChars()) == 0) { if (c++ == 0) *first = i; @@ -490,7 +490,7 @@ TArray FKeyBindings::GetKeysForCommand (const char *cmd) while (i < NUM_KEYS) { - if (stricmp (cmd, Binds[i]) == 0) + if (stricmp (cmd, Binds[i].GetChars()) == 0) { result.Push(i); } @@ -511,7 +511,7 @@ void FKeyBindings::UnbindACommand (const char *str) for (i = 0; i < NUM_KEYS; i++) { - if (!stricmp (str, Binds[i])) + if (!stricmp (str, Binds[i].GetChars())) { Binds[i] = ""; } @@ -538,7 +538,7 @@ void FKeyBindings::DefaultBind(const char *keyname, const char *cmd) } for (int i = 0; i < NUM_KEYS; ++i) { - if (!Binds[i].IsEmpty() && stricmp (Binds[i], cmd) == 0) + if (!Binds[i].IsEmpty() && stricmp (Binds[i].GetChars(), cmd) == 0) { // This command is already bound to a key. return; } @@ -836,7 +836,7 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds) if (ev->type == EV_KeyDown) { // Key pressed for a normal press binding = binds->GetBinding(ev->data1); - DClickTime[ev->data1] = nowtime + 571; + if (doublebinds != nullptr) DClickTime[ev->data1] = nowtime + 571; } else if (doublebinds != nullptr && DClicked[ev->data1]) { // Key released from a double click diff --git a/src/common/console/c_commandbuffer.h b/src/common/console/c_commandbuffer.h index 179651c45b..637027b27c 100644 --- a/src/common/console/c_commandbuffer.h +++ b/src/common/console/c_commandbuffer.h @@ -1,3 +1,4 @@ +#pragma once #include #include "zstring.h" diff --git a/src/common/console/c_console.cpp b/src/common/console/c_console.cpp index f6366d7cd8..44c8ffacf6 100644 --- a/src/common/console/c_console.cpp +++ b/src/common/console/c_console.cpp @@ -295,7 +295,7 @@ void C_DeinitConsole () while (cmd != NULL) { GameAtExit *next = cmd->Next; - AddCommandString (cmd->Command); + AddCommandString (cmd->Command.GetChars()); delete cmd; cmd = next; } @@ -417,7 +417,7 @@ int PrintString (int iprintlevel, const char *outline) if (!conbuffer) return 0; // when called too early int printlevel = iprintlevel & PRINT_TYPES; - if (printlevel < msglevel || *outline == '\0') + if (*outline == '\0') { return 0; } @@ -434,7 +434,10 @@ int PrintString (int iprintlevel, const char *outline) conbuffer->AddText(printlevel, outline); if (vidactive && screen && !(iprintlevel & PRINT_NONOTIFY) && NotifyStrings) { - NotifyStrings->AddString(iprintlevel, outline); + if (printlevel >= msglevel) + { + NotifyStrings->AddString(iprintlevel, outline); + } } } if (Logfile != nullptr && !(iprintlevel & PRINT_NOLOG)) @@ -648,48 +651,51 @@ void C_DrawConsole () conbuffer->FormatText(CurrentConsoleFont, ConWidth / textScale); unsigned int consolelines = conbuffer->GetFormattedLineCount(); FBrokenLines *blines = conbuffer->GetLines(); - FBrokenLines *printline = blines + consolelines - 1 - RowAdjust; - - int bottomline = ConBottom / textScale - CurrentConsoleFont->GetHeight()*2 - 4; - - for(FBrokenLines *p = printline; p >= blines && lines > 0; p--, lines--) + if (blines != nullptr) { - if (textScale == 1) - { - DrawText(twod, CurrentConsoleFont, CR_TAN, LEFTMARGIN, offset + lines * CurrentConsoleFont->GetHeight(), p->Text, TAG_DONE); - } - else - { - DrawText(twod, CurrentConsoleFont, CR_TAN, LEFTMARGIN, offset + lines * CurrentConsoleFont->GetHeight(), p->Text, - DTA_VirtualWidth, twod->GetWidth() / textScale, - DTA_VirtualHeight, twod->GetHeight() / textScale, - DTA_KeepRatio, true, TAG_DONE); - } - } + FBrokenLines* printline = blines + consolelines - 1 - RowAdjust; - if (ConBottom >= 20) - { - if (gamestate != GS_STARTUP) + int bottomline = ConBottom / textScale - CurrentConsoleFont->GetHeight() * 2 - 4; + + for (FBrokenLines* p = printline; p >= blines && lines > 0; p--, lines--) { - auto now = I_msTime(); - if (now > CursorTicker) + if (textScale == 1) { - CursorTicker = now + 500; - cursoron = !cursoron; + DrawText(twod, CurrentConsoleFont, CR_TAN, LEFTMARGIN, offset + lines * CurrentConsoleFont->GetHeight(), p->Text.GetChars(), TAG_DONE); } - CmdLine.Draw(left, bottomline, textScale, cursoron); - } - if (RowAdjust && ConBottom >= CurrentConsoleFont->GetHeight()*7/2) - { - // Indicate that the view has been scrolled up (10) - // and if we can scroll no further (12) - if (textScale == 1) - DrawChar(twod, CurrentConsoleFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE); else - DrawChar(twod, CurrentConsoleFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, + { + DrawText(twod, CurrentConsoleFont, CR_TAN, LEFTMARGIN, offset + lines * CurrentConsoleFont->GetHeight(), p->Text.GetChars(), DTA_VirtualWidth, twod->GetWidth() / textScale, DTA_VirtualHeight, twod->GetHeight() / textScale, DTA_KeepRatio, true, TAG_DONE); + } + } + + if (ConBottom >= 20) + { + if (gamestate != GS_STARTUP) + { + auto now = I_msTime(); + if (now > CursorTicker) + { + CursorTicker = now + 500; + cursoron = !cursoron; + } + CmdLine.Draw(left, bottomline, textScale, cursoron); + } + if (RowAdjust && ConBottom >= CurrentConsoleFont->GetHeight() * 7 / 2) + { + // Indicate that the view has been scrolled up (10) + // and if we can scroll no further (12) + if (textScale == 1) + DrawChar(twod, CurrentConsoleFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE); + else + DrawChar(twod, CurrentConsoleFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, + DTA_VirtualWidth, twod->GetWidth() / textScale, + DTA_VirtualHeight, twod->GetHeight() / textScale, + DTA_KeepRatio, true, TAG_DONE); + } } } } @@ -1006,7 +1012,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) } HistPos = NULL; buffer.SetString(""); - AddCommandString(bufferText); + AddCommandString(bufferText.GetChars()); TabbedLast = false; TabbedList = false; break; @@ -1054,7 +1060,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) { // copy to clipboard if (buffer.TextLength() > 0) { - I_PutInClipboard(buffer.GetText()); + I_PutInClipboard(buffer.GetText().GetChars()); } } else diff --git a/src/common/console/c_consolebuffer.h b/src/common/console/c_consolebuffer.h index 58bc0edea3..8d4e235d58 100644 --- a/src/common/console/c_consolebuffer.h +++ b/src/common/console/c_consolebuffer.h @@ -32,6 +32,7 @@ **--------------------------------------------------------------------------- ** */ +#pragma once #include #include diff --git a/src/common/console/c_cvars.cpp b/src/common/console/c_cvars.cpp index b529e830e9..1cbe6772d0 100644 --- a/src/common/console/c_cvars.cpp +++ b/src/common/console/c_cvars.cpp @@ -44,6 +44,7 @@ #include "printf.h" #include "palutil.h" #include "i_interface.h" +#include "gstrings.h" #include "dobject.h" #include "dobjtype.h" @@ -209,12 +210,12 @@ FBaseCVar::~FBaseCVar () { FBaseCVar *var, *prev; - var = FindCVar (VarName, &prev); + var = FindCVar (VarName.GetChars(), &prev); if (var == this) { cvarMap.Remove(var->VarName); - C_RemoveTabCommand(VarName); + C_RemoveTabCommand(VarName.GetChars()); } } } @@ -397,7 +398,7 @@ const char *FBaseCVar::ToString (UCVarValue value, ECVarType type) case CVAR_Float: IGNORE_FORMAT_PRE - mysnprintf (cstrbuf, countof(cstrbuf), "%H", value.Float); + mysnprintf (cstrbuf, countof(cstrbuf), "%g", value.Float); IGNORE_FORMAT_POST break; @@ -489,7 +490,7 @@ UCVarValue FBaseCVar::FromFloat (float value, ECVarType type) case CVAR_String: IGNORE_FORMAT_PRE - mysnprintf (cstrbuf, countof(cstrbuf), "%H", value); + mysnprintf (cstrbuf, countof(cstrbuf), "%g", value); IGNORE_FORMAT_POST ret.String = cstrbuf; break; @@ -864,27 +865,27 @@ ECVarType FStringCVar::GetRealType () const UCVarValue FStringCVar::GetGenericRep (ECVarType type) const { - return FromString (mValue, type); + return FromString (mValue.GetChars(), type); } UCVarValue FStringCVar::GetFavoriteRep (ECVarType *type) const { UCVarValue ret; *type = CVAR_String; - ret.String = mValue; + ret.String = mValue.GetChars(); return ret; } UCVarValue FStringCVar::GetGenericRepDefault (ECVarType type) const { - return FromString (mDefaultValue, type); + return FromString (mDefaultValue.GetChars(), type); } UCVarValue FStringCVar::GetFavoriteRepDefault (ECVarType *type) const { UCVarValue ret; *type = CVAR_String; - ret.String = mDefaultValue; + ret.String = mDefaultValue.GetChars(); return ret; } @@ -969,7 +970,7 @@ int FColorCVar::ToInt2 (UCVarValue value, ECVarType type) if (string.IsNotEmpty()) { - ret = V_GetColorFromString (string); + ret = V_GetColorFromString (string.GetChars()); } else { @@ -1394,7 +1395,7 @@ void C_RestoreCVars (void) { for (unsigned int i = 0; i < CVarBackups.Size(); ++i) { - cvar_set(CVarBackups[i].Name, CVarBackups[i].String); + cvar_set(CVarBackups[i].Name.GetChars(), CVarBackups[i].String.GetChars()); } C_ForgetCVars(); } @@ -1695,16 +1696,37 @@ CCMD (toggle) } } -void FBaseCVar::ListVars (const char *filter, bool plain) +void FBaseCVar::ListVars (const char *filter, int listtype) { int count = 0; + bool plain = listtype == LCT_Plain; + bool includedesc = listtype == LCT_FullSearch; + decltype(cvarMap)::Iterator it(cvarMap); decltype(cvarMap)::Pair *pair; while (it.NextPair(pair)) { auto var = pair->Value; - if (CheckWildcards (filter, var->GetName())) + + bool ismatch; + + if (filter && includedesc) + { + // search always allow partial matches + // also allow matching to cvar name, localised description, and description language-id + + FString SearchString = FString("*") + filter + "*"; + ismatch = CheckWildcards (SearchString.GetChars(), var->GetName()) || + CheckWildcards (SearchString.GetChars(), var->GetDescription().GetChars()) || + CheckWildcards (SearchString.GetChars(), GStrings.localize(var->GetDescription().GetChars())); + } + else + { + ismatch = CheckWildcards (filter, var->GetName()); + } + + if (ismatch) { uint32_t flags = var->GetFlags(); if (plain) @@ -1718,7 +1740,8 @@ void FBaseCVar::ListVars (const char *filter, bool plain) else { ++count; - Printf ("%c%c%c%c%c %s = %s\n", + + Printf ("%c%c%c%c%c %s = %s", flags & CVAR_ARCHIVE ? 'A' : ' ', flags & CVAR_USERINFO ? 'U' : flags & CVAR_SERVERINFO ? 'S' : @@ -1730,6 +1753,16 @@ void FBaseCVar::ListVars (const char *filter, bool plain) flags & CVAR_IGNORE ? 'X' : ' ', var->GetName(), var->GetHumanString()); + + if (includedesc) + if (var->GetDescription().Len()) + Printf(" // \"%s\"\n", GStrings.localize(var->GetDescription().GetChars())); + else + Printf("\n"); + else + Printf("\n"); + + } } } @@ -1740,17 +1773,29 @@ CCMD (cvarlist) { if (argv.argc() == 1) { - FBaseCVar::ListVars (NULL, false); + FBaseCVar::ListVars (NULL, LCT_Default); } else { - FBaseCVar::ListVars (argv[1], false); + FBaseCVar::ListVars (argv[1], LCT_Default); } } CCMD (cvarlistplain) { - FBaseCVar::ListVars (NULL, true); + FBaseCVar::ListVars (NULL, LCT_Plain); +} + +CCMD (cvarsearch) +{ + if (argv.argc() == 1) + { + FBaseCVar::ListVars (NULL, LCT_FullSearch); + } + else + { + FBaseCVar::ListVars (argv[1], LCT_FullSearch); + } } CCMD (archivecvar) diff --git a/src/common/console/c_cvars.h b/src/common/console/c_cvars.h index 4d2737ab3d..47337523fe 100644 --- a/src/common/console/c_cvars.h +++ b/src/common/console/c_cvars.h @@ -89,6 +89,13 @@ enum ECVarType CVAR_Dummy, // Unknown }; +enum ListCCMDType +{ + LCT_Default, + LCT_Plain, + LCT_FullSearch, +}; + class FIntCVarRef; union UCVarValue @@ -201,7 +208,7 @@ class FBaseCVar static void MarkZSCallbacks (); static void ResetColors (); // recalc color cvars' indices after screen change - static void ListVars (const char *filter, bool plain); + static void ListVars (const char *filter, int listtype); const FString &GetDescription() const { return Description; }; const FString& GetToggleMessage(int which) { return ToggleMessages[which]; } @@ -218,6 +225,9 @@ class FBaseCVar void* GetExtraDataPointer(); + int pnum = -1; + FName userinfoName; + protected: virtual void DoSet (UCVarValue value, ECVarType type) = 0; virtual void InstantiateZSCVar() @@ -412,8 +422,8 @@ class FStringCVar : public FBaseCVar const char *operator= (const char *stringrep) { UCVarValue val; val.String = const_cast(stringrep); SetGenericRep (val, CVAR_String); return stringrep; } - inline operator const char * () const { return mValue; } - inline const char *operator *() const { return mValue; } + inline operator const char * () const { return mValue.GetChars(); } + inline const char *operator *() const { return mValue.GetChars(); } protected: virtual void DoSet (UCVarValue value, ECVarType type); diff --git a/src/common/console/c_dispatch.cpp b/src/common/console/c_dispatch.cpp index 7de13e2ea5..8b6d738a02 100644 --- a/src/common/console/c_dispatch.cpp +++ b/src/common/console/c_dispatch.cpp @@ -79,7 +79,7 @@ class FWaitingCommand : public FDelayedCommand if (--TicsLeft == 0) { UnsafeExecutionScope scope(IsUnsafe); - AddCommandString(Command); + AddCommandString(Command.GetChars()); return true; } return false; @@ -101,7 +101,7 @@ class FStoredCommand : public FDelayedCommand { if (Text.IsNotEmpty() && Command != nullptr) { - FCommandLine args(Text); + FCommandLine args(Text.GetChars()); Command->Run(args, 0); } return true; @@ -301,7 +301,7 @@ void C_DoCommand (const char *cmd, int keynum) } else { // Get the variable's value - if (var->GetDescription().Len()) Printf("%s\n", GStrings.localize(var->GetDescription())); + if (var->GetDescription().Len()) Printf("%s\n", GStrings.localize(var->GetDescription().GetChars())); Printf ("\"%s\" is \"%s\" ", var->GetName(), var->GetHumanString()); Printf ("(default: \"%s\")\n", var->GetHumanStringDefault()); } @@ -400,7 +400,7 @@ static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *na *prev = NULL; while (start) { - comp = strnicmp (start->m_Name, name, namelen); + comp = start->m_Name.CompareNoCase(name, namelen); if (comp > 0) return NULL; else if (comp == 0 && start->m_Name[namelen] == 0) @@ -424,10 +424,10 @@ bool FConsoleCommand::AddToHash (FConsoleCommand **table) unsigned int key; FConsoleCommand *insert, **bucket; - key = MakeKey (m_Name); + key = MakeKey (m_Name.GetChars()); bucket = &table[key % HASH_SIZE]; - if (ScanChainForName (*bucket, m_Name, strlen (m_Name), &insert)) + if (ScanChainForName (*bucket, m_Name.GetChars(), m_Name.Len(), &insert)) { return false; } @@ -477,7 +477,7 @@ FConsoleCommand::~FConsoleCommand () *m_Prev = m_Next; if (m_Next) m_Next->m_Prev = m_Prev; - C_RemoveTabCommand (m_Name); + C_RemoveTabCommand (m_Name.GetChars()); } void FConsoleCommand::Run(FCommandLine &argv, int key) @@ -530,7 +530,7 @@ FString BuildString (int argc, FString *argv) { // It's an empty argument, we need to convert it to '""' buf << "\"\" "; } - else if (strchr(argv[arg], '"')) + else if (strchr(argv[arg].GetChars(), '"')) { // If it contains one or more quotes, we need to escape them. buf << '"'; ptrdiff_t substr_start = 0, quotepos; @@ -545,7 +545,7 @@ FString BuildString (int argc, FString *argv) } buf << argv[arg].Mid(substr_start) << "\" "; } - else if (strchr(argv[arg], ' ')) + else if (strchr(argv[arg].GetChars(), ' ')) { // If it contains a space, it needs to be quoted. buf << '"' << argv[arg] << "\" "; } @@ -674,7 +674,7 @@ static int DumpHash (FConsoleCommand **table, bool aliases, const char *pattern= cmd = table[bucket]; while (cmd) { - if (CheckWildcards (pattern, cmd->m_Name)) + if (CheckWildcards (pattern, cmd->m_Name.GetChars())) { if (cmd->IsAlias()) { @@ -712,8 +712,8 @@ void FConsoleAlias::Archive (FConfigFile *f) { if (f != NULL && !m_Command[0].IsEmpty()) { - f->SetValueForKey ("Name", m_Name, true); - f->SetValueForKey ("Command", m_Command[0], true); + f->SetValueForKey ("Name", m_Name.GetChars(), true); + f->SetValueForKey ("Command", m_Command[0].GetChars(), true); } } @@ -923,7 +923,7 @@ void FConsoleAlias::Run (FCommandLine &args, int key) } bRunning = true; - AddCommandString (mycommand, key); + AddCommandString (mycommand.GetChars(), key); bRunning = false; if (m_Command[index].IsEmpty()) { // The alias is unchanged, so put the command back so it can be used again. @@ -999,15 +999,15 @@ void FExecList::ExecCommands() const { for (unsigned i = 0; i < Commands.Size(); ++i) { - AddCommandString(Commands[i]); + AddCommandString(Commands[i].GetChars()); } } -void FExecList::AddPullins(TArray &wads, FConfigFile *config) const +void FExecList::AddPullins(std::vector& wads, FConfigFile *config) const { for (unsigned i = 0; i < Pullins.Size(); ++i) { - D_AddFile(wads, Pullins[i], true, -1, config); + D_AddFile(wads, Pullins[i].GetChars(), true, -1, config); } } diff --git a/src/common/console/c_dispatch.h b/src/common/console/c_dispatch.h index 532ed9b929..e8b2bfdf0a 100644 --- a/src/common/console/c_dispatch.h +++ b/src/common/console/c_dispatch.h @@ -34,6 +34,8 @@ #ifndef __C_DISPATCH_H__ #define __C_DISPATCH_H__ +#include +#include #include #include #include "c_console.h" @@ -52,7 +54,7 @@ struct FExecList void AddCommand(const char *cmd, const char *file = nullptr); void ExecCommands() const; - void AddPullins(TArray &wads, FConfigFile *config) const; + void AddPullins(std::vector &wads, FConfigFile *config) const; }; extern bool ParsingKeyConf, UnsafeExecutionContext; diff --git a/src/common/console/c_enginecmds.cpp b/src/common/console/c_enginecmds.cpp index 13593cb32d..d6a2e027e2 100644 --- a/src/common/console/c_enginecmds.cpp +++ b/src/common/console/c_enginecmds.cpp @@ -50,10 +50,11 @@ #include "filesystem.h" #include "gstrings.h" #include "version.h" -#include "findfile.h" +#include "fs_findfile.h" #include "md5.h" #include "i_specialpaths.h" #include "i_system.h" +#include "cmdlib.h" extern FILE* Logfile; @@ -79,7 +80,7 @@ CCMD (print) Printf ("print : Print a string from the string table\n"); return; } - const char *str = GStrings[argv[1]]; + const char *str = GStrings.CheckString(argv[1]); if (str == NULL) { Printf ("%s unknown\n", argv[1]); @@ -178,75 +179,44 @@ UNSAFE_CCMD (crashout) UNSAFE_CCMD (dir) { - FString dir, path; - const char *match; - findstate_t c_file; - void *file; - - FString curdir = I_GetCWD(); - if (curdir.IsEmpty()) - { - Printf ("Current path too long\n"); - return; - } + FString path; if (argv.argc() > 1) { path = NicePath(argv[1]); - if (!I_ChDir(path)) - { - match = path; - dir = ExtractFilePath(path); - if (dir[0] != '\0') - { - match += dir.Len(); - } - else - { - dir = "./"; - } - if (match[0] == '\0') - { - match = "*"; - } - if (!I_ChDir(dir)) - { - Printf ("%s not found\n", dir.GetChars()); - return; - } - } - else - { - match = "*"; - dir = path; - } } else { - match = "*"; - dir = curdir; + path = I_GetCWD();; } - if (dir[dir.Len()-1] != '/') + auto base = ExtractFileBase(path.GetChars(), true); + FString bpath; + if (base.IndexOfAny("*?") >= 0) { - dir += '/'; + bpath = ExtractFilePath(path.GetChars()); + } + else + { + base = "*"; + bpath = path; } - if ( (file = I_FindFirst (match, &c_file)) == ((void *)(-1))) - Printf ("Nothing matching %s%s\n", dir.GetChars(), match); + FileSys::FileList list; + if (!FileSys::ScanDirectory(list, bpath.GetChars(), base.GetChars(), true)) + { + Printf ("Nothing matching %s\n", path.GetChars()); + } else { - Printf ("Listing of %s%s:\n", dir.GetChars(), match); - do + Printf ("Listing of %s:\n", path.GetChars()); + for(auto& entry : list) { - if (I_FindAttr (&c_file) & FA_DIREC) - Printf (PRINT_BOLD, "%s \n", I_FindName (&c_file)); + if (entry.isDirectory) + Printf (PRINT_BOLD, "%s \n", entry.FileName.c_str()); else - Printf ("%s\n", I_FindName (&c_file)); - } while (I_FindNext (file, &c_file) == 0); - I_FindClose (file); + Printf ("%s\n", entry.FileName.c_str()); + } } - - I_ChDir(curdir); } //========================================================================== @@ -274,7 +244,7 @@ CCMD (wdir) { if (wadnum == -1 || fileSystem.GetFileContainer(i) == wadnum) { - Printf ("%10d %s\n", fileSystem.FileLength(i), fileSystem.GetFileFullName(i)); + Printf ("%10ld %s\n", fileSystem.FileLength(i), fileSystem.GetFileFullName(i)); } } } @@ -334,7 +304,7 @@ CCMD(printlocalized) return; } } - Printf("%s\n", GStrings(argv[1])); + Printf("%s\n", GStrings.GetString(argv[1])); } } diff --git a/src/common/cutscenes/movieplayer.cpp b/src/common/cutscenes/movieplayer.cpp index 94a7e4c60e..a1b04385f6 100644 --- a/src/common/cutscenes/movieplayer.cpp +++ b/src/common/cutscenes/movieplayer.cpp @@ -153,7 +153,7 @@ class AnmPlayer : public MoviePlayer { // This doesn't need its own class type anim_t anim; - TArray buffer; + FileSys::FileData buffer; int numframes = 0; int curframe = 1; int frametime = 0; @@ -171,9 +171,10 @@ class AnmPlayer : public MoviePlayer memcpy(frameTicks, frameticks, 3 * sizeof(int)); flags = flags_; buffer = fr.ReadPadded(1); + if (buffer.size() < 4) return; fr.Close(); - if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0) + if (ANIM_LoadAnim(&anim, buffer.bytes(), buffer.size() - 1) < 0) { return; } @@ -231,7 +232,6 @@ class AnmPlayer : public MoviePlayer ~AnmPlayer() { - buffer.Reset(); animtex.Clean(); } @@ -322,11 +322,11 @@ class VpxPlayer : public MoviePlayer unsigned width, height; TArray Pic; TArray readBuf; + vpx_codec_iface_t *iface; vpx_codec_ctx_t codec{}; vpx_codec_iter_t iter = nullptr; - uint32_t convnumer; - uint32_t convdenom; + double convrate; uint64_t nsecsperframe; uint64_t nextframetime; @@ -362,10 +362,8 @@ class VpxPlayer : public MoviePlayer Pic.Resize(width * height * 4); - - // Todo: Support VP9 as well? vpx_codec_dec_cfg_t cfg = { 1, width, height }; - if (vpx_codec_dec_init(&codec, &vpx_codec_vp8_dx_algo, &cfg, 0)) + if (vpx_codec_dec_init(&codec, iface, &cfg, 0)) { error.Format("Error initializing VPX codec.\n"); failed = true; @@ -388,7 +386,16 @@ class VpxPlayer : public MoviePlayer uint16_t length = fr.ReadUInt16(); if (length != 32) return false; fr.Read(&magic, 4); - if (magic != MAKE_ID('V', 'P', '8', '0')) return false; + + switch (magic) + { + case MAKE_ID('V', 'P', '8', '0'): + iface = &vpx_codec_vp8_dx_algo; break; + case MAKE_ID('V', 'P', '9', '0'): + iface = &vpx_codec_vp9_dx_algo; break; + default: + return false; + } width = fr.ReadUInt16(); height = fr.ReadUInt16(); @@ -398,15 +405,20 @@ class VpxPlayer : public MoviePlayer if (numframes == 0) return false; fr.Seek(4, FileReader::SeekCur); - if (fpsdenominator > 1000 || fpsnumerator == 0 || fpsdenominator == 0) + if (fpsnumerator == 0 || fpsdenominator == 0) { // default to 30 fps if the header does not provide useful info. fpsdenominator = 30; fpsnumerator = 1; } - convnumer = 120 * fpsnumerator; - convdenom = fpsdenominator * origframedelay; + if (origframedelay < 1) + convrate = 0.0; + else + { + convrate = 120.0 * double(fpsnumerator); + convrate /= double(fpsdenominator) * double(origframedelay); + } nsecsperframe = int64_t(fpsnumerator) * 1'000'000'000 / fpsdenominator; nextframetime = 0; @@ -475,32 +487,6 @@ class VpxPlayer : public MoviePlayer dest[2] = v; } - bool CreateNextFrame() - { - auto img = GetFrameData(); - if (!img) return false; - uint8_t const* const yplane = img->planes[VPX_PLANE_Y]; - uint8_t const* const uplane = img->planes[VPX_PLANE_U]; - uint8_t const* const vplane = img->planes[VPX_PLANE_V]; - - const int ystride = img->stride[VPX_PLANE_Y]; - const int ustride = img->stride[VPX_PLANE_U]; - const int vstride = img->stride[VPX_PLANE_V]; - - for (unsigned int y = 0; y < height; y++) - { - for (unsigned int x = 0; x < width; x++) - { - uint8_t u = uplane[ustride * (y >> 1) + (x >> 1)]; - uint8_t v = vplane[vstride * (y >> 1) + (x >> 1)]; - - SetPixel(&Pic[(x + y * width) << 2], yplane[ystride * y + x], u, v); - } - } - - return true; - } - //--------------------------------------------------------------------------- // // @@ -515,7 +501,7 @@ class VpxPlayer : public MoviePlayer } else if (soundtrack >= 0) { - FileReader reader = fileSystem.OpenFileReader(soundtrack); + FileReader reader = fileSystem.ReopenFileReader(soundtrack); if (reader.isOpen()) { MusicStream = ZMusic_OpenSong(GetMusicReader(reader), MDEV_DEFAULT, nullptr); @@ -525,7 +511,7 @@ class VpxPlayer : public MoviePlayer Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileFullName(soundtrack, false)); } } - animtex.SetSize(AnimTexture::YUV, width, height); + animtex.SetSize(AnimTexture::VPX, width, height); } //--------------------------------------------------------------------------- @@ -534,6 +520,12 @@ class VpxPlayer : public MoviePlayer // //--------------------------------------------------------------------------- + bool FormatSupported(vpx_img_fmt_t fmt) + { + return fmt == VPX_IMG_FMT_I420 || fmt == VPX_IMG_FMT_I444 || fmt == VPX_IMG_FMT_I422 || fmt == VPX_IMG_FMT_I440; + } + + bool Frame(uint64_t clock) override { if (!AudioTrack.GetAudioStream() && MusicStream && clock != 0) @@ -562,22 +554,38 @@ class VpxPlayer : public MoviePlayer bool stop = false; if (clock >= nextframetime) { + + nextframetime += nsecsperframe; - if (!CreateNextFrame()) - { - Printf(PRINT_BOLD, "Failed reading next frame\n"); - stop = true; + while(clock >= nextframetime) + { // frameskipping + auto img = GetFrameData(); + framenum++; + nextframetime += nsecsperframe; + if (framenum >= numframes || !img) break; } - else + + if (framenum < numframes) { - animtex.SetFrame(nullptr, Pic.Data()); + auto img = GetFrameData(); + + if (!img || !FormatSupported(img->fmt)) + { + Printf(PRINT_BOLD, "Failed reading next frame\n"); + stop = true; + } + else + { + animtex.SetFrame(nullptr, img); + } + + framenum++; } - framenum++; if (framenum >= numframes) stop = true; bool nostopsound = (flags & NOSOUNDCUTOFF); - int soundframe = convdenom ? Scale(framenum, convnumer, convdenom) : framenum; + int soundframe = (convrate > 0.0) ? int(convrate * framenum) : framenum; if (soundframe > lastsoundframe) { if (soundtrack == -1) @@ -794,7 +802,7 @@ class SmkPlayer : public MoviePlayer if (sound == INVALID_SOUND) soundEngine->StopAllChannels(); else - soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, nostopsound ? CHANF_UI : CHANF_NONE, sound, 1.f, ATTN_NONE); + soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, nostopsound ? CHANF_UI | CHANF_FORCE : CHANF_FORCE, sound, 1.f, ATTN_NONE); } } } @@ -838,10 +846,10 @@ MoviePlayer* OpenMovie(const char* filename, TArray& ans, const int* framet { auto fn = StripExtension(filename); DefaultExtension(fn, ".ivf"); - fr = fileSystem.OpenFileReader(fn); + fr = fileSystem.ReopenFileReader(fn.GetChars()); } - if (!fr.isOpen()) fr = fileSystem.OpenFileReader(filename); + if (!fr.isOpen()) fr = fileSystem.ReopenFileReader(filename); if (!fr.isOpen()) { size_t nLen = strlen(filename); @@ -849,7 +857,7 @@ MoviePlayer* OpenMovie(const char* filename, TArray& ans, const int* framet if (nLen >= 3 && isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/') { filename += 3; - fr = fileSystem.OpenFileReader(filename); + fr = fileSystem.ReopenFileReader(filename); } if (!fr.isOpen()) { @@ -895,7 +903,7 @@ MoviePlayer* OpenMovie(const char* filename, TArray& ans, const int* framet } return anm; } - else if (!memcmp(id, "DKIF\0\0 \0VP80", 12)) + else if (!memcmp(id, "DKIF\0\0 \0VP80", 12) || !memcmp(id, "DKIF\0\0 \0VP90", 12)) { auto anm = new VpxPlayer(fr, ans, frameticks ? frameticks[1] : 0, flags, error); if (!anm->isvalid()) @@ -906,7 +914,7 @@ MoviePlayer* OpenMovie(const char* filename, TArray& ans, const int* framet // VPX files have no sound track, so look for a same-named sound file with a known extension as the soundtrack to be played. static const char* knownSoundExts[] = { "OGG", "FLAC", "MP3", "OPUS", "WAV" }; FString name = StripExtension(filename); - anm->soundtrack = fileSystem.FindFileWithExtensions(name, knownSoundExts, countof(knownSoundExts)); + anm->soundtrack = fileSystem.FindFileWithExtensions(name.GetChars(), knownSoundExts, countof(knownSoundExts)); return anm; } // add more formats here. @@ -937,7 +945,7 @@ DEFINE_ACTION_FUNCTION(_MoviePlayer, Create) if (firstframetime == -1) firstframetime = frametime; if (lastframetime == -1) lastframetime = frametime; int frametimes[] = { firstframetime, frametime, lastframetime }; - auto movie = OpenMovie(filename, *sndinf, frametime == -1? nullptr : frametimes, flags, error); + auto movie = OpenMovie(filename.GetChars(), *sndinf, frametime == -1? nullptr : frametimes, flags, error); if (!movie) { Printf(TEXTCOLOR_YELLOW "%s", error.GetChars()); diff --git a/src/common/cutscenes/playmve.cpp b/src/common/cutscenes/playmve.cpp index 70b56b43a1..3c49e96105 100644 --- a/src/common/cutscenes/playmve.cpp +++ b/src/common/cutscenes/playmve.cpp @@ -546,7 +546,7 @@ bool InterplayDecoder::Open(FileReader &fr_) int chunkType = LE_16(&chunkPreamble[2]); if (chunkType == CHUNK_VIDEO) bAudioEnabled = false; - else + else if (bAudioEnabled) { if (ProcessNextChunk() != CHUNK_INIT_AUDIO) { diff --git a/src/common/cutscenes/screenjob.cpp b/src/common/cutscenes/screenjob.cpp index dbf86aa461..de1da996f5 100644 --- a/src/common/cutscenes/screenjob.cpp +++ b/src/common/cutscenes/screenjob.cpp @@ -87,8 +87,8 @@ VMFunction* LookupFunction(const char* qname, bool validate) size_t p = strcspn(qname, "."); if (p == 0) I_Error("Call to undefined function %s", qname); - FString clsname(qname, p); - FString funcname = qname + p + 1; + FName clsname(qname, p, true); + FName funcname(qname + p + 1, true); auto func = PClass::FindFunction(clsname, funcname); if (func == nullptr) @@ -154,7 +154,7 @@ void AddGenericVideo(DObject* runner, const FString& fn, int soundid, int fps) int CutsceneDef::GetSound() { FSoundID id = INVALID_SOUND; - if (soundName.IsNotEmpty()) id = soundEngine->FindSound(soundName); + if (soundName.IsNotEmpty()) id = soundEngine->FindSound(soundName.GetChars()); if (id == INVALID_SOUND) id = soundEngine->FindSoundByResID(soundID); return id.index(); } @@ -163,7 +163,7 @@ void CutsceneDef::Create(DObject* runner) { if (function.IsNotEmpty()) { - CallCreateFunction(function, runner); + CallCreateFunction(function.GetChars(), runner); } else if (video.IsNotEmpty()) { diff --git a/src/common/engine/date.cpp b/src/common/engine/date.cpp index c409416f84..63e3776b7b 100644 --- a/src/common/engine/date.cpp +++ b/src/common/engine/date.cpp @@ -224,7 +224,7 @@ static void FormatTime(const FString& timeForm, int timeVal, FString* result) if (timeinfo != nullptr) { char timeString[1024]; - if (strftime(timeString, sizeof(timeString), timeForm, timeinfo)) + if (strftime(timeString, sizeof(timeString), timeForm.GetChars(), timeinfo)) *result = timeString; } } diff --git a/src/common/engine/files.h b/src/common/engine/files.h new file mode 100644 index 0000000000..af6694cf05 --- /dev/null +++ b/src/common/engine/files.h @@ -0,0 +1,6 @@ +#pragma once +#include "fs_files.h" + +using FileSys::FileReader; +using FileSys::FileWriter; +using FileSys::BufferWriter; \ No newline at end of file diff --git a/src/common/engine/filesystem.h b/src/common/engine/filesystem.h new file mode 100644 index 0000000000..53f4916771 --- /dev/null +++ b/src/common/engine/filesystem.h @@ -0,0 +1,7 @@ +#pragma once +#include "fs_filesystem.h" + +using FileSys::FileSystem; +using FileSys::FResourceFile; + +inline FileSys::FileSystem fileSystem; diff --git a/src/common/engine/gamestate.h b/src/common/engine/gamestate.h index 5f674a33b9..aff8da57c8 100644 --- a/src/common/engine/gamestate.h +++ b/src/common/engine/gamestate.h @@ -21,7 +21,8 @@ enum gamestate_t : int GS_FORCEWIPE = -1, GS_FORCEWIPEFADE = -2, GS_FORCEWIPEBURN = -3, - GS_FORCEWIPEMELT = -4 + GS_FORCEWIPEMELT = -4, + GS_FORCEWIPEFIZZLEFADE = -5 }; diff --git a/src/common/engine/i_interface.cpp b/src/common/engine/i_interface.cpp index 580dde407c..c6e8e97eb1 100644 --- a/src/common/engine/i_interface.cpp +++ b/src/common/engine/i_interface.cpp @@ -25,7 +25,7 @@ FStartupInfo GameStartupInfo; CVAR(Bool, queryiwad, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR(String, defaultiwad, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG); -CVAR(Bool, vid_fps, false, 0) +CVAR(Bool, vid_fps, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) EXTERN_CVAR(Bool, ui_generic) diff --git a/src/common/engine/i_interface.h b/src/common/engine/i_interface.h index bdc05198ed..4289bfeab7 100644 --- a/src/common/engine/i_interface.h +++ b/src/common/engine/i_interface.h @@ -10,6 +10,7 @@ class FGameTexture; class FTextureID; enum EUpscaleFlags : int; class FConfigFile; +struct FTranslationID; struct SystemCallbacks { @@ -30,7 +31,6 @@ struct SystemCallbacks FString(*GetPlayerName)(int i); bool (*DispatchEvent)(event_t* ev); bool (*CheckGame)(const char* nm); - int (*GetGender)(); void (*MenuClosed)(); bool (*CheckMenudefOption)(const char* opt); void (*ConsoleToggled)(int state); @@ -47,6 +47,7 @@ struct SystemCallbacks bool (*OkForLocalization)(FTextureID, const char*); FConfigFile* (*GetConfig)(); bool (*WantEscape)(); + FTranslationID(*RemapTranslation)(FTranslationID trans); }; extern SystemCallbacks sysCallbacks; diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index 07dc7fdd9b..65dc60cb1a 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -419,12 +419,12 @@ void BuildAddress (sockaddr_in *address, const char *name) if (!isnamed) { - address->sin_addr.s_addr = inet_addr (target); + address->sin_addr.s_addr = inet_addr (target.GetChars()); Printf ("Node number %d, address %s\n", doomcom.numnodes, target.GetChars()); } else { - hostentry = gethostbyname (target); + hostentry = gethostbyname (target.GetChars()); if (!hostentry) I_FatalError ("gethostbyname: couldn't find %s\n%s", target.GetChars(), neterror()); address->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; diff --git a/src/common/engine/m_joy.cpp b/src/common/engine/m_joy.cpp index dec49377f8..a2ab71103c 100644 --- a/src/common/engine/m_joy.cpp +++ b/src/common/engine/m_joy.cpp @@ -98,7 +98,7 @@ static bool M_SetJoystickConfigSection(IJoystickConfig *joy, bool create, FConfi FString id = "Joy:"; id += joy->GetIdentifier(); if (!GameConfig) return false; - return GameConfig->SetSection(id, create); + return GameConfig->SetSection(id.GetChars(), create); } //========================================================================== @@ -120,6 +120,11 @@ bool M_LoadJoystickConfig(IJoystickConfig *joy) { return false; } + value = GameConfig->GetValueForKey("Enabled"); + if (value != NULL) + { + joy->SetEnabled((bool)atoi(value)); + } value = GameConfig->GetValueForKey("Sensitivity"); if (value != NULL) { @@ -176,6 +181,10 @@ void M_SaveJoystickConfig(IJoystickConfig *joy) if (GameConfig != NULL && M_SetJoystickConfigSection(joy, true, GameConfig)) { GameConfig->ClearCurrentSection(); + if (!joy->GetEnabled()) + { + GameConfig->SetValueForKey("Enabled", "0"); + } if (!joy->IsSensitivityDefault()) { mysnprintf(value, countof(value), "%g", joy->GetSensitivity()); diff --git a/src/common/engine/m_joy.h b/src/common/engine/m_joy.h index fc99379b04..088d5bd6d3 100644 --- a/src/common/engine/m_joy.h +++ b/src/common/engine/m_joy.h @@ -18,7 +18,7 @@ enum EJoyAxis }; // Generic configuration interface for a controller. -struct NOVTABLE IJoystickConfig +struct IJoystickConfig { virtual ~IJoystickConfig() = 0; @@ -36,6 +36,9 @@ struct NOVTABLE IJoystickConfig virtual void SetAxisMap(int axis, EJoyAxis gameaxis) = 0; virtual void SetAxisScale(int axis, float scale) = 0; + virtual bool GetEnabled() = 0; + virtual void SetEnabled(bool enabled) = 0; + // Used by the saver to not save properties that are at their defaults. virtual bool IsSensitivityDefault() = 0; virtual bool IsAxisDeadZoneDefault(int axis) = 0; diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index d11cbffe36..a1f791f9d3 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -10,6 +10,7 @@ xx(Object) xx(Actor) xx(Class) xx(Thinker) +xx(VisualThinker) xx(Crosshairs) xx(Untranslated) @@ -79,7 +80,6 @@ xx(__decorate_internal_float__) // Per-actor sound channels (for deprecated PlaySoundEx function) Do not separate this block!!! xx(Auto) xx(Weapon) -xx(BobPivot3D) xx(Voice) xx(Item) xx(Body) @@ -120,6 +120,7 @@ xx(Vector) xx(Map) xx(MapIterator) xx(Array) +xx(Function) xx(Include) xx(Sound) xx(State) @@ -133,12 +134,17 @@ xx(FVector3) xx(FVector4) xx(FQuat) xx(let) +xx(BlockThingsIterator) +xx(BlockLinesIterator) +xx(ActorIterator) +xx(ThinkerIterator) xx(Min) xx(Max) xx(Min_Normal) xx(Min_Denormal) xx(Epsilon) +xx(Equal_Epsilon) xx(NaN) xx(Infinity) xx(Dig) @@ -180,6 +186,7 @@ xx(Voidptr) xx(StateLabel) xx(SpriteID) xx(TextureID) +xx(TranslationID) xx(Overlay) xx(IsValid) xx(IsNull) @@ -189,6 +196,7 @@ xx(SetNull) xx(Key) xx(Index) xx(Find) +xx(Call) // color channels xx(a) @@ -260,11 +268,16 @@ xx(Mididevices) xx(Aldevices) xx(Alresamplers) +xx(Vkdevices) + // Decorate compatibility functions xx(BuiltinRandom) xx(BuiltinRandom2) xx(BuiltinFRandom) xx(BuiltinNameToClass) xx(BuiltinClassCast) +xx(BuiltinFunctionPtrCast) +xx(BuiltinFindTranslation) xx(ScreenJobRunner) +xx(Action) diff --git a/src/common/engine/palettecontainer.cpp b/src/common/engine/palettecontainer.cpp index 9648f2528c..29ec3599ff 100644 --- a/src/common/engine/palettecontainer.cpp +++ b/src/common/engine/palettecontainer.cpp @@ -32,6 +32,7 @@ ** */ +#include #include "palutil.h" #include "sc_man.h" #include "m_crc32.h" @@ -220,7 +221,7 @@ FRemapTable* PaletteContainer::AddRemap(FRemapTable* remap) // //---------------------------------------------------------------------------- -void PaletteContainer::UpdateTranslation(int trans, FRemapTable* remap) +void PaletteContainer::UpdateTranslation(FTranslationID trans, FRemapTable* remap) { auto newremap = AddRemap(remap); TranslationTables[GetTranslationType(trans)].SetVal(GetTranslationIndex(trans), newremap); @@ -232,7 +233,7 @@ void PaletteContainer::UpdateTranslation(int trans, FRemapTable* remap) // //---------------------------------------------------------------------------- -int PaletteContainer::AddTranslation(int slot, FRemapTable* remap, int count) +FTranslationID PaletteContainer::AddTranslation(int slot, FRemapTable* remap, int count) { uint32_t id = 0; for (int i = 0; i < count; i++) @@ -249,9 +250,9 @@ int PaletteContainer::AddTranslation(int slot, FRemapTable* remap, int count) // //---------------------------------------------------------------------------- -void PaletteContainer::CopyTranslation(int dest, int src) +void PaletteContainer::CopyTranslation(FTranslationID dest, FTranslationID src) { - TranslationTables[GetTranslationType(dest)].SetVal(GetTranslationIndex(dest), TranslationToTable(src)); + TranslationTables[GetTranslationType(dest)].SetVal(GetTranslationIndex(dest), TranslationToTable(src.index())); } //---------------------------------------------------------------------------- @@ -260,8 +261,9 @@ void PaletteContainer::CopyTranslation(int dest, int src) // //---------------------------------------------------------------------------- -FRemapTable *PaletteContainer::TranslationToTable(int translation) +FRemapTable *PaletteContainer::TranslationToTable(int translation) const { + if (IsLuminosityTranslation(translation)) return nullptr; unsigned int type = GetTranslationType(translation); unsigned int index = GetTranslationIndex(translation); @@ -278,14 +280,14 @@ FRemapTable *PaletteContainer::TranslationToTable(int translation) // //---------------------------------------------------------------------------- -int PaletteContainer::StoreTranslation(int slot, FRemapTable *remap) +FTranslationID PaletteContainer::StoreTranslation(int slot, FRemapTable *remap) { unsigned int i; auto size = NumTranslations(slot); for (i = 0; i < size; i++) { - if (*remap == *TranslationToTable(TRANSLATION(slot, i))) + if (*remap == *TranslationToTable(TRANSLATION(slot, i).index())) { // A duplicate of this translation already exists return TRANSLATION(slot, i); @@ -367,7 +369,7 @@ static bool IndexOutOfRange(const int start1, const int end1, const int start2, // //---------------------------------------------------------------------------- -bool FRemapTable::operator==(const FRemapTable& o) +bool FRemapTable::operator==(const FRemapTable& o) const { // Two translations are identical when they have the same amount of colors // and the palette values for both are identical. diff --git a/src/common/engine/palettecontainer.h b/src/common/engine/palettecontainer.h index e1d0befd32..3c6da1a367 100644 --- a/src/common/engine/palettecontainer.h +++ b/src/common/engine/palettecontainer.h @@ -3,8 +3,7 @@ #include #include "memarena.h" #include "palentry.h" - -class FileReader; +#include "files.h" enum { @@ -19,7 +18,7 @@ struct FRemapTable FRemapTable(const FRemapTable& o) = default; FRemapTable& operator=(const FRemapTable& o) = default; - bool operator==(const FRemapTable& o); + bool operator==(const FRemapTable& o) const; void MakeIdentity(); bool IsIdentity() const; bool AddIndexRange(int start, int end, int pal1, int pal2); @@ -43,6 +42,49 @@ struct FRemapTable private: }; + + +// outside facing translation ID +struct FTranslationID +{ +public: + FTranslationID() = default; + +private: + constexpr FTranslationID(int id) : ID(id) + { + } +public: + static constexpr FTranslationID fromInt(int i) + { + return FTranslationID(i); + } + FTranslationID(const FTranslationID& other) = default; + FTranslationID& operator=(const FTranslationID& other) = default; + bool operator !=(FTranslationID other) const + { + return ID != other.ID; + } + bool operator ==(FTranslationID other) const + { + return ID == other.ID; + } + constexpr int index() const + { + return ID; + } + constexpr bool isvalid() const + { + return ID >= 0; + } +private: + + int ID; +}; + +constexpr FTranslationID NO_TRANSLATION = FTranslationID::fromInt(0); +constexpr FTranslationID INVALID_TRANSLATION = FTranslationID::fromInt(-1); + // A class that initializes unusued pointers to NULL. This is used so that when // the TAutoGrowArray below is expanded, the new elements will be NULLed. class FRemapTablePtr @@ -68,14 +110,19 @@ enum TRANSLATIONTYPE_MASK = (255 << TRANSLATION_SHIFT) }; -inline constexpr uint32_t TRANSLATION(uint8_t a, uint32_t b) +inline constexpr FTranslationID TRANSLATION(uint8_t a, uint32_t b) { - return (a << TRANSLATION_SHIFT) | b; + return FTranslationID::fromInt((a << TRANSLATION_SHIFT) | b); } -inline constexpr uint32_t LuminosityTranslation(int range, uint8_t min, uint8_t max) +inline constexpr FTranslationID MakeLuminosityTranslation(int range, uint8_t min, uint8_t max) { // ensure that the value remains positive. - return ( (1 << 30) | ((range&0x3fff) << 16) | (min << 8) | max ); + return FTranslationID::fromInt( (1 << 30) | ((range&0x3fff) << 16) | (min << 8) | max ); +} + +inline constexpr bool IsLuminosityTranslation(FTranslationID trans) +{ + return trans.index() > 0 && (trans.index() & (1 << 30)); } inline constexpr bool IsLuminosityTranslation(int trans) @@ -83,13 +130,25 @@ inline constexpr bool IsLuminosityTranslation(int trans) return trans > 0 && (trans & (1 << 30)); } -inline constexpr int GetTranslationType(uint32_t trans) +inline constexpr int GetTranslationType(FTranslationID trans) +{ + assert(!IsLuminosityTranslation(trans)); + return (trans.index() & TRANSLATIONTYPE_MASK) >> TRANSLATION_SHIFT; +} + +inline constexpr int GetTranslationIndex(FTranslationID trans) +{ + assert(!IsLuminosityTranslation(trans)); + return (trans.index() & TRANSLATION_MASK); +} + +inline constexpr int GetTranslationType(int trans) { assert(!IsLuminosityTranslation(trans)); return (trans & TRANSLATIONTYPE_MASK) >> TRANSLATION_SHIFT; } -inline constexpr int GetTranslationIndex(uint32_t trans) +inline constexpr int GetTranslationIndex(int trans) { assert(!IsLuminosityTranslation(trans)); return (trans & TRANSLATION_MASK); @@ -123,11 +182,16 @@ class PaletteContainer void Clear(); int DetermineTranslucency(FileReader& file); FRemapTable* AddRemap(FRemapTable* remap); - void UpdateTranslation(int trans, FRemapTable* remap); - int AddTranslation(int slot, FRemapTable* remap, int count = 1); - void CopyTranslation(int dest, int src); - int StoreTranslation(int slot, FRemapTable* remap); - FRemapTable* TranslationToTable(int translation); + void UpdateTranslation(FTranslationID trans, FRemapTable* remap); + FTranslationID AddTranslation(int slot, FRemapTable* remap, int count = 1); + void CopyTranslation(FTranslationID dest, FTranslationID src); + FTranslationID StoreTranslation(int slot, FRemapTable* remap); + FRemapTable* TranslationToTable(int translation) const; + FRemapTable* TranslationToTable(FTranslationID translation) const + { + return TranslationToTable(translation.index()); + } + void GenerateGlobalBrightmapFromColormap(const uint8_t* cmapdata, int numlevels); void PushIdentityTable(int slot) @@ -135,7 +199,7 @@ class PaletteContainer AddTranslation(slot, nullptr); } - FRemapTable* GetTranslation(int slot, int index) + FRemapTable* GetTranslation(int slot, int index) const { if (TranslationTables.Size() <= (unsigned)slot) return nullptr; return TranslationTables[slot].GetVal(index); @@ -153,6 +217,28 @@ class PaletteContainer return TranslationTables[slot].Size(); } + +}; + +struct LuminosityTranslationDesc +{ + int colorrange; + int lum_min; + int lum_max; + + static LuminosityTranslationDesc fromInt(int translation) + { + LuminosityTranslationDesc t; + t.colorrange = (translation >> 16) & 0x3fff; + t.lum_min = (translation >> 8) & 0xff; + t.lum_max = translation & 0xff; + return t; + } + + static LuminosityTranslationDesc fromID(FTranslationID translation) + { + return fromInt(translation.index()); + } }; extern PaletteContainer GPalette; diff --git a/src/common/engine/printf.h b/src/common/engine/printf.h index 98af91ff84..990b199b90 100644 --- a/src/common/engine/printf.h +++ b/src/common/engine/printf.h @@ -7,8 +7,9 @@ # define ATTRIBUTE(attrlist) #endif -// This header collects all things printf, so that this doesn't need to pull in other, far more dirty headers, just for outputting some text. +#include "stb_sprintf.h" +// This header collects all things printf, so that this doesn't need to pull in other, far more dirty headers, just for outputting some text. extern "C" int mysnprintf(char* buffer, size_t count, const char* format, ...) ATTRIBUTE((format(printf, 3, 4))); extern "C" int myvsnprintf(char* buffer, size_t count, const char* format, va_list argptr) ATTRIBUTE((format(printf, 3, 0))); diff --git a/src/common/engine/renderstyle.h b/src/common/engine/renderstyle.h index 272f23ba51..19d788e2ce 100644 --- a/src/common/engine/renderstyle.h +++ b/src/common/engine/renderstyle.h @@ -55,7 +55,7 @@ enum ETexMode }; // Legacy render styles -enum ERenderStyle +enum ERenderStyle : int { STYLE_None, // Do not draw STYLE_Normal, // Normal; just copy the image to the screen diff --git a/src/common/engine/sc_man.cpp b/src/common/engine/sc_man.cpp index 1568f677bd..ac7b4799f7 100644 --- a/src/common/engine/sc_man.cpp +++ b/src/common/engine/sc_man.cpp @@ -136,7 +136,7 @@ void FScanner::Open (const char *name) // // FScanner :: OpenFile // -// Loads a script from a file. Uses new/delete for memory allocation. +// Loads a script from a file. // //========================================================================== @@ -148,9 +148,9 @@ bool FScanner::OpenFile (const char *name) if (!fr.OpenFile(name)) return false; auto filesize = fr.GetLength(); auto filebuff = fr.Read(); - if (filebuff.Size() == 0 && filesize > 0) return false; + if (filebuff.size() == 0 && filesize > 0) return false; - ScriptBuffer = FString((const char *)filebuff.Data(), filesize); + ScriptBuffer = FString(filebuff.string(), filesize); ScriptName = name; // This is used for error messages so the full file name is preferable LumpNum = -1; PrepareScript (); @@ -200,10 +200,13 @@ void FScanner :: OpenLumpNum (int lump) { Close (); { - FileData mem = fileSystem.ReadFile(lump); - ScriptBuffer = mem.GetString(); + auto len = fileSystem.FileLength(lump); + auto buff = ScriptBuffer.LockNewBuffer(len); + fileSystem.ReadFile(lump, buff); + buff[len] = 0; + ScriptBuffer.UnlockBuffer(); } - ScriptName = fileSystem.GetFileFullPath(lump); + ScriptName = fileSystem.GetFileFullPath(lump).c_str(); LumpNum = lump; PrepareScript (); } @@ -257,6 +260,7 @@ void FScanner::PrepareScript () StateOptions = false; StringBuffer[0] = '\0'; BigStringBuffer = ""; + ParseError = false; } //========================================================================== @@ -1086,13 +1090,14 @@ void FScanner::ScriptError (const char *message, ...) va_end (arglist); } + ParseError = true; if (NoFatalErrors) { - Printf(TEXTCOLOR_RED "Script error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(), + Printf(TEXTCOLOR_RED "%sScript error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", PrependMessage.GetChars(), ScriptName.GetChars(), AlreadyGot ? AlreadyGotLine : Line, composed.GetChars()); return; } - I_Error ("Script error, \"%s\" line %d:\n%s\n", ScriptName.GetChars(), + I_Error ("%sScript error, \"%s\" line %d:\n%s\n", PrependMessage.GetChars(), ScriptName.GetChars(), AlreadyGot? AlreadyGotLine : Line, composed.GetChars()); } @@ -1118,7 +1123,8 @@ void FScanner::ScriptMessage (const char *message, ...) va_end (arglist); } - Printf (TEXTCOLOR_RED "Script error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(), + ParseError = true; + Printf (TEXTCOLOR_RED "%sScript error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", PrependMessage.GetChars(), ScriptName.GetChars(), AlreadyGot? AlreadyGotLine : Line, composed.GetChars()); } @@ -1380,4 +1386,3 @@ int ParseHex(const char* hex, FScriptPosition* sc) return num; } - diff --git a/src/common/engine/sc_man.h b/src/common/engine/sc_man.h index 4d66b5f215..5873523a12 100644 --- a/src/common/engine/sc_man.h +++ b/src/common/engine/sc_man.h @@ -1,6 +1,7 @@ #ifndef __SC_MAN_H__ #define __SC_MAN_H__ +#include #include "zstring.h" #include "tarray.h" #include "name.h" @@ -70,9 +71,11 @@ class FScanner void Open(const char *lumpname); bool OpenFile(const char *filename); void OpenMem(const char *name, const char *buffer, int size); - void OpenMem(const char *name, const TArray &buffer) + template + void OpenMem(const char* name, const T& buffer) { - OpenMem(name, (const char*)buffer.Data(), buffer.Size()); + static_assert(sizeof(typename T::value_type) == 1); + OpenMem(name, (const char*)buffer.data(), (int)buffer.size()); } void OpenString(const char *name, FString buffer); void OpenLumpNum(int lump); @@ -189,6 +192,7 @@ class FScanner void ScriptError(const char *message, ...) GCCPRINTF(2,3); void ScriptMessage(const char *message, ...) GCCPRINTF(2,3); + void SetPrependMessage(const FString& message) { PrependMessage = message; } bool isText(); @@ -235,6 +239,7 @@ class FScanner bool StateOptions; bool Escape; VersionInfo ParseVersion = { 0, 0, 0 }; // no ZScript extensions by default + FString PrependMessage = ""; bool ScanValue(bool allowfloat, bool evaluate); diff --git a/src/common/engine/sc_man_scanner.re b/src/common/engine/sc_man_scanner.re index 59c3c7712b..5af7e62f93 100644 --- a/src/common/engine/sc_man_scanner.re +++ b/src/common/engine/sc_man_scanner.re @@ -167,8 +167,9 @@ std2: 'vector2' { RET(TK_Vector2); } 'vector3' { RET(TK_Vector3); } 'map' { RET(TK_Map); } - 'mapiterator' { RET(TK_MapIterator); } + 'mapiterator' { RET(ParseVersion >= MakeVersion(4, 10, 0)? TK_MapIterator : TK_Identifier); } 'array' { RET(TK_Array); } + 'function' { RET(ParseVersion >= MakeVersion(4, 12, 0)? TK_FunctionType : TK_Identifier); } 'in' { RET(TK_In); } 'sizeof' { RET(TK_SizeOf); } 'alignof' { RET(TK_AlignOf); } @@ -204,6 +205,7 @@ std2: 'stop' { RET(TK_Stop); } 'null' { RET(TK_Null); } 'nullptr' { RET(ParseVersion >= MakeVersion(4, 9, 0)? TK_Null : TK_Identifier); } + 'sealed' { RET(ParseVersion >= MakeVersion(4, 12, 0)? TK_Sealed : TK_Identifier); } 'is' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Is : TK_Identifier); } 'replaces' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Replaces : TK_Identifier); } @@ -220,6 +222,7 @@ std2: 'bright' { RET(StateOptions ? TK_Bright : TK_Identifier); } 'fast' { RET(StateOptions ? TK_Fast : TK_Identifier); } 'slow' { RET(StateOptions ? TK_Slow : TK_Identifier); } + 'ticadjust' { RET(StateOptions ? TK_NoDelay : TK_Identifier); } 'nodelay' { RET(StateOptions ? TK_NoDelay : TK_Identifier); } 'canraise' { RET(StateOptions ? TK_CanRaise : TK_Identifier); } 'offset' { RET(StateOptions ? TK_Offset : TK_Identifier); } diff --git a/src/common/engine/sc_man_tokens.h b/src/common/engine/sc_man_tokens.h index d93e5be622..4870031251 100644 --- a/src/common/engine/sc_man_tokens.h +++ b/src/common/engine/sc_man_tokens.h @@ -122,6 +122,7 @@ xx(TK_Null, "'null'") xx(TK_Global, "'global'") xx(TK_Stop, "'stop'") xx(TK_Include, "'include'") +xx(TK_Sealed, "'sealed'") xx(TK_Is, "'is'") xx(TK_Replaces, "'replaces'") @@ -130,6 +131,7 @@ xx(TK_Vector3, "'vector3'") xx(TK_Map, "'map'") xx(TK_MapIterator, "'mapiterator'") xx(TK_Array, "'array'") +xx(TK_FunctionType, "'function'") xx(TK_In, "'in'") xx(TK_SizeOf, "'sizeof'") xx(TK_AlignOf, "'alignof'") diff --git a/src/common/engine/serializer.cpp b/src/common/engine/serializer.cpp index 8c68b5a3b7..dcf9308428 100644 --- a/src/common/engine/serializer.cpp +++ b/src/common/engine/serializer.cpp @@ -37,7 +37,7 @@ #define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 #define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag -#include +#include #include "rapidjson/rapidjson.h" #include "rapidjson/writer.h" #include "rapidjson/prettywriter.h" @@ -55,6 +55,10 @@ #include "textures.h" #include "texturemanager.h" #include "base64.h" +#include "vm.h" +#include "i_interface.h" + +using namespace FileSys; extern DObject *WP_NOCHANGE; bool save_full = false; // for testing. Should be removed afterward. @@ -290,6 +294,21 @@ bool FSerializer::BeginObject(const char *name) // //========================================================================== +bool FSerializer::HasKey(const char* name) +{ + if (isReading()) + { + return r->FindKey(name) != nullptr; + } + return false; +} + +//========================================================================== +// +// +// +//========================================================================== + bool FSerializer::HasObject(const char* name) { if (isReading()) @@ -601,6 +620,8 @@ void FSerializer::WriteObjects() { auto obj = w->mDObjects[i]; + if(obj->ObjectFlags & OF_Transient) continue; + BeginObject(nullptr); w->Key("classtype"); w->String(obj->GetClass()->TypeName.GetChars()); @@ -693,7 +714,6 @@ void FSerializer::ReadObjects(bool hubtravel) } EndArray(); - assert(!founderrors); if (founderrors) { Printf(TEXTCOLOR_RED "Failed to restore all objects in savegame\n"); @@ -746,8 +766,8 @@ FCompressedBuffer FSerializer::GetCompressedOutput() FCompressedBuffer buff; WriteObjects(); EndObject(); + buff.filename = nullptr; buff.mSize = (unsigned)w->mOutString.GetSize(); - buff.mZipFlags = 0; buff.mCRC32 = crc32(0, (const Bytef*)w->mOutString.GetString(), buff.mSize); uint8_t *compressbuf = new uint8_t[buff.mSize+1]; @@ -756,9 +776,9 @@ FCompressedBuffer FSerializer::GetCompressedOutput() int err; stream.next_in = (Bytef *)w->mOutString.GetString(); - stream.avail_in = buff.mSize; + stream.avail_in = (unsigned)buff.mSize; stream.next_out = (Bytef*)compressbuf; - stream.avail_out = buff.mSize; + stream.avail_out = (unsigned)buff.mSize; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; @@ -1134,13 +1154,13 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe const char *name; auto lump = pic->GetSourceLump(); - if (fileSystem.GetLinkedTexture(lump) == pic) + if (TexMan.GetLinkedTexture(lump) == pic) { name = fileSystem.GetFileFullName(lump); } else { - name = pic->GetName(); + name = pic->GetName().GetChars(); } arc.WriteKey(key); arc.w->StartArray(); @@ -1191,6 +1211,28 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe return arc; } +//========================================================================== +// +// +// +//========================================================================== + +FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval) +{ + int v = value.index(); + int* defv = (int*)defval; + Serialize(arc, key, v, defv); + + if (arc.isReading()) + { + // allow games to alter the loaded value to handle dynamic lists. + if (sysCallbacks.RemapTranslation) value = sysCallbacks.RemapTranslation(FTranslationID::fromInt(v)); + else value = FTranslationID::fromInt(v); + } + + return arc; +} + //========================================================================== // // This never uses defval and instead uses 'null' as default @@ -1502,8 +1544,8 @@ FString DictionaryToString(const Dictionary &dict) while (i.NextPair(pair)) { - writer.Key(pair->Key); - writer.String(pair->Value); + writer.Key(pair->Key.GetChars()); + writer.String(pair->Value.GetChars()); } writer.EndObject(); @@ -1565,6 +1607,35 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary } } +template<> FSerializer& Serialize(FSerializer& arc, const char* key, VMFunction*& func, VMFunction**) +{ + if (arc.isWriting()) + { + arc.WriteKey(key); + if (func) arc.w->String(func->QualifiedName); + else arc.w->Null(); + } + else + { + func = nullptr; + + auto val = arc.r->FindKey(key); + if (val != nullptr && val->IsString()) + { + auto qname = val->GetString(); + size_t p = strcspn(qname, "."); + if (p != 0) + { + FName clsname(qname, p, true); + FName funcname(qname + p + 1, true); + func = PClass::FindFunction(clsname, funcname); + } + } + + } + return arc; +} + //========================================================================== // // Handler to retrieve a numeric value of any kind. @@ -1622,6 +1693,97 @@ FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &value, N return arc; } +//========================================================================== +// +// PFunctionPointer +// +//========================================================================== + +void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p) +{ + if (arc.isWriting()) + { + if(p) + { + arc.BeginObject(key); + arc("Class",p->ClassName); + arc("Function",p->FunctionName); + arc.EndObject(); + } + else + { + arc.WriteKey(key); + arc.w->Null(); + } + } + else + { + assert(p); + auto v = arc.r->FindKey(key); + if(!v || v->IsNull()) + { + p = nullptr; + } + else if(v->IsObject()) + { + arc.r->mObjects.Push(FJSONObject(v)); // BeginObject + + const char * cstr; + arc.StringPtr("Class", cstr); + + if(!cstr) + { + arc.StringPtr("Function", cstr); + if(!cstr) + { + Printf(TEXTCOLOR_RED "Function Pointer missing Class and Function Fields in Object\n"); + } + else + { + Printf(TEXTCOLOR_RED "Function Pointer missing Class Field in Object\n"); + } + arc.mErrors++; + arc.EndObject(); + p = nullptr; + return; + } + + p->ClassName = FString(cstr); + arc.StringPtr("Function", cstr); + + if(!cstr) + { + Printf(TEXTCOLOR_RED "Function Pointer missing Function Field in Object\n"); + arc.mErrors++; + arc.EndObject(); + p = nullptr; + return; + } + p->FunctionName = FString(cstr); + arc.EndObject(); + } + else + { + Printf(TEXTCOLOR_RED "Function Pointer is not an Object\n"); + arc.mErrors++; + p = nullptr; + } + } +} + +bool FSerializer::ReadOptionalInt(const char * key, int &into) +{ + if(!isReading()) return false; + + auto val = r->FindKey(key); + if(val && val->IsInt()) + { + into = val->GetInt(); + return true; + } + return false; +} + #include "renderstyle.h" FSerializer& Serialize(FSerializer& arc, const char* key, FRenderStyle& style, FRenderStyle* def) { diff --git a/src/common/engine/serializer.h b/src/common/engine/serializer.h index 63bfb35299..ae25853d94 100644 --- a/src/common/engine/serializer.h +++ b/src/common/engine/serializer.h @@ -4,7 +4,6 @@ #include #include #include "tarray.h" -#include "file_zip.h" #include "tflags.h" #include "vectors.h" #include "palentry.h" @@ -21,6 +20,7 @@ class FSoundID; union FRenderStyle; class DObject; class FTextureID; +struct FTranslationID; inline bool nullcmp(const void *buffer, size_t length) { @@ -55,6 +55,12 @@ struct NumericValue } }; +struct FunctionPointerValue +{ + FString ClassName; + FString FunctionName; +}; + class FSerializer { @@ -80,18 +86,19 @@ class FSerializer void SetUniqueSoundNames() { soundNamesAreUnique = true; } bool OpenWriter(bool pretty = true); bool OpenReader(const char *buffer, size_t length); - bool OpenReader(FCompressedBuffer *input); + bool OpenReader(FileSys::FCompressedBuffer *input); void Close(); void ReadObjects(bool hubtravel); bool BeginObject(const char *name); void EndObject(); + bool HasKey(const char* name); bool HasObject(const char* name); bool BeginArray(const char *name); void EndArray(); unsigned GetSize(const char *group); const char *GetKey(); const char *GetOutput(unsigned *len = nullptr); - FCompressedBuffer GetCompressedOutput(); + FileSys::FCompressedBuffer GetCompressedOutput(); // The sprite serializer is a special case because it is needed by the VM to handle its 'spriteid' type. virtual FSerializer &Sprite(const char *key, int32_t &spritenum, int32_t *def); // This is only needed by the type system. @@ -102,6 +109,10 @@ class FSerializer FSerializer &AddString(const char *key, const char *charptr); const char *GetString(const char *key); FSerializer &ScriptNum(const char *key, int &num); + + + bool ReadOptionalInt(const char * key, int &into); + bool isReading() const { return r != nullptr; @@ -234,6 +245,12 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FName &value, FName *d FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundID *def); FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString *def); FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def); +FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride &mo, struct ModelOverride *def); +FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimModelOverride &mo, struct AnimModelOverride *def); +FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &ao, struct AnimOverride *def); +FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval); + +void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p); template >*/> FSerializer &Serialize(FSerializer &arc, const char *key, T *&value, T **) @@ -244,6 +261,15 @@ FSerializer &Serialize(FSerializer &arc, const char *key, T *&value, T **) return arc; } +template +FSerializer &Serialize(FSerializer &arc, const char *key, std::pair &value, std::pair *def) +{ + arc.BeginObject(key); + Serialize(arc, "first", value.first, def ? &def->first : nullptr); + Serialize(arc, "second", value.second, def ? &def->second : nullptr); + arc.EndObject(); + return arc; +} template FSerializer &Serialize(FSerializer &arc, const char *key, TArray &value, TArray *def) @@ -310,6 +336,7 @@ inline FSerializer& Serialize(FSerializer& arc, const char* key, BitArray& value template<> FSerializer& Serialize(FSerializer& arc, const char* key, PClass*& clst, PClass** def); template<> FSerializer& Serialize(FSerializer& arc, const char* key, FFont*& font, FFont** def); template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary *&dict, Dictionary **def); +template<> FSerializer& Serialize(FSerializer& arc, const char* key, VMFunction*& dict, VMFunction** def); inline FSerializer &Serialize(FSerializer &arc, const char *key, DVector3 &p, DVector3 *def) { diff --git a/src/common/engine/serializer_internal.h b/src/common/engine/serializer_internal.h index 31cf76c1ae..05b6dcad0f 100644 --- a/src/common/engine/serializer_internal.h +++ b/src/common/engine/serializer_internal.h @@ -1,3 +1,4 @@ +#pragma once const char* UnicodeToString(const char* cc); const char* StringToUnicode(const char* cc, int size = -1); diff --git a/src/common/engine/st_start.h b/src/common/engine/st_start.h index 8e02987d63..a8b78aaa83 100644 --- a/src/common/engine/st_start.h +++ b/src/common/engine/st_start.h @@ -39,7 +39,7 @@ class FStartupScreen { public: - static FStartupScreen *CreateInstance(int max_progress, bool showprogress); + static FStartupScreen *CreateInstance(int max_progress); FStartupScreen(int max_progress) { @@ -66,7 +66,7 @@ class FStartupScreen class FBasicStartupScreen : public FStartupScreen { public: - FBasicStartupScreen(int max_progress, bool show_bar); + FBasicStartupScreen(int max_progress); ~FBasicStartupScreen(); void Progress(); diff --git a/src/common/engine/stats.cpp b/src/common/engine/stats.cpp index 0a295c8c6b..70ad8e2f16 100644 --- a/src/common/engine/stats.cpp +++ b/src/common/engine/stats.cpp @@ -116,7 +116,7 @@ void FStat::PrintStat (F2DDrawer *drawer) // Count number of linefeeds but ignore terminating ones. if (stattext[i] == '\n') y -= fontheight; } - DrawText(drawer, NewConsoleFont, CR_GREEN, 5 / textScale, y, stattext, + DrawText(drawer, NewConsoleFont, CR_GREEN, 5 / textScale, y, stattext.GetChars(), DTA_VirtualWidth, twod->GetWidth() / textScale, DTA_VirtualHeight, twod->GetHeight() / textScale, DTA_KeepRatio, true, TAG_DONE); diff --git a/src/common/engine/stringtable.cpp b/src/common/engine/stringtable.cpp index 92819c144d..707b59b69e 100644 --- a/src/common/engine/stringtable.cpp +++ b/src/common/engine/stringtable.cpp @@ -47,23 +47,26 @@ // //========================================================================== -void FStringTable::LoadStrings (const char *language) +void FStringTable::LoadStrings (FileSys::FileSystem& fileSystem, const char *language) { int lastlump, lump; + allStrings.Clear(); lastlump = 0; while ((lump = fileSystem.FindLump("LMACROS", &lastlump)) != -1) { - readMacros(lump); + auto lumpdata = fileSystem.ReadFile(lump); + readMacros(lumpdata.string(), lumpdata.size()); } lastlump = 0; while ((lump = fileSystem.FindLump ("LANGUAGE", &lastlump)) != -1) { - auto lumpdata = fileSystem.GetFileData(lump); + auto lumpdata = fileSystem.ReadFile(lump); + auto filenum = fileSystem.GetFileContainer(lump); - if (!ParseLanguageCSV(lump, lumpdata)) - LoadLanguage (lump, lumpdata); + if (!ParseLanguageCSV(filenum, lumpdata.string(), lumpdata.size())) + LoadLanguage (filenum, lumpdata.string(), lumpdata.size()); } UpdateLanguage(language); allMacros.Clear(); @@ -77,9 +80,9 @@ void FStringTable::LoadStrings (const char *language) //========================================================================== -TArray> FStringTable::parseCSV(const TArray &buffer) +TArray> FStringTable::parseCSV(const char* buffer, size_t size) { - const size_t bufLength = buffer.Size(); + const size_t bufLength = size; TArray> data; TArray row; TArray cell; @@ -156,18 +159,15 @@ TArray> FStringTable::parseCSV(const TArray &buffer) // //========================================================================== -bool FStringTable::readMacros(int lumpnum) +bool FStringTable::readMacros(const char* buffer, size_t size) { - auto lumpdata = fileSystem.GetFileData(lumpnum); - auto data = parseCSV(lumpdata); + auto data = parseCSV(buffer, size); + allMacros.Clear(); for (unsigned i = 1; i < data.Size(); i++) { auto macroname = data[i][0]; - auto language = data[i][1]; - if (macroname.IsEmpty() || language.IsEmpty()) continue; - FStringf combined_name("%s/%s", language.GetChars(), macroname.GetChars()); - FName name = combined_name.GetChars(); + FName name = macroname.GetChars(); StringMacro macro; @@ -186,11 +186,11 @@ bool FStringTable::readMacros(int lumpnum) // //========================================================================== -bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray &buffer) +bool FStringTable::ParseLanguageCSV(int filenum, const char* buffer, size_t size) { - if (buffer.Size() < 11) return false; - if (strnicmp((const char*)buffer.Data(), "default,", 8) && strnicmp((const char*)buffer.Data(), "identifier,", 11 )) return false; - auto data = parseCSV(buffer); + if (size < 11) return false; + if (strnicmp(buffer, "default,", 8) && strnicmp(buffer, "identifier,", 11 )) return false; + auto data = parseCSV(buffer, size); int labelcol = -1; int filtercol = -1; @@ -243,7 +243,7 @@ bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray &buffer) auto filter = filterstr.Split(" ", FString::TOK_SKIPEMPTY); for (auto& entry : filter) { - if (sysCallbacks.CheckGame(entry)) + if (sysCallbacks.CheckGame(entry.GetChars())) { ok = true; break; @@ -257,14 +257,14 @@ bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray &buffer) FName strName = row[labelcol].GetChars(); if (hasDefaultEntry) { - DeleteForLabel(lumpnum, strName); + DeleteForLabel(filenum, strName); } for (auto &langentry : langrows) { auto str = row[langentry.first]; if (str.Len() > 0) { - InsertString(lumpnum, langentry.second, strName, str); + InsertString(filenum, langentry.second, strName, str); } else { @@ -282,14 +282,14 @@ bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray &buffer) // //========================================================================== -void FStringTable::LoadLanguage (int lumpnum, const TArray &buffer) +void FStringTable::LoadLanguage (int lumpnum, const char* buffer, size_t size) { bool errordone = false; TArray activeMaps; FScanner sc; bool hasDefaultEntry = false; - sc.OpenMem("LANGUAGE", buffer); + sc.OpenMem("LANGUAGE", buffer, (int)size); sc.SetCMode (true); while (sc.GetString ()) { @@ -323,7 +323,7 @@ void FStringTable::LoadLanguage (int lumpnum, const TArray &buffer) } else { - sc.ScriptError ("The language code must be 2 or 3 characters long.\n'%s' is %lu characters long.", + sc.ScriptError ("The language code must be 2 or 3 characters long.\n'%s' is %zu characters long.", sc.String, len); } } @@ -408,11 +408,10 @@ void FStringTable::DeleteString(int langid, FName label) // //========================================================================== -void FStringTable::DeleteForLabel(int lumpnum, FName label) +void FStringTable::DeleteForLabel(int filenum, FName label) { decltype(allStrings)::Iterator it(allStrings); decltype(allStrings)::Pair *pair; - auto filenum = fileSystem.GetFileContainer(lumpnum); while (it.NextPair(pair)) { @@ -431,10 +430,10 @@ void FStringTable::DeleteForLabel(int lumpnum, FName label) // //========================================================================== -void FStringTable::InsertString(int lumpnum, int langid, FName label, const FString &string) +void FStringTable::InsertString(int filenum, int langid, FName label, const FString &string) { const char *strlangid = (const char *)&langid; - TableElement te = { fileSystem.GetFileContainer(lumpnum), { string, string, string, string } }; + TableElement te = { filenum, { string, string, string, string } }; ptrdiff_t index; while ((index = te.strings[0].IndexOf("@[")) >= 0) { @@ -445,9 +444,8 @@ void FStringTable::InsertString(int lumpnum, int langid, FName label, const FStr break; } FString macroname(te.strings[0].GetChars() + index + 2, endindex - index - 2); - FStringf lookupstr("%s/%s", strlangid, macroname.GetChars()); FStringf replacee("@[%s]", macroname.GetChars()); - FName lookupname(lookupstr.GetChars(), true); + FName lookupname(macroname.GetChars(), true); auto replace = allMacros.CheckKey(lookupname); for (int i = 0; i < 4; i++) { @@ -579,26 +577,33 @@ bool FStringTable::exists(const char *name) // //========================================================================== -const char *FStringTable::GetString(const char *name, uint32_t *langtable, int gender) const +const char *FStringTable::CheckString(const char *name, uint32_t *langtable, int gender) const { if (name == nullptr || *name == 0) { return nullptr; } - if (gender == -1 && sysCallbacks.GetGender) gender = sysCallbacks.GetGender(); + if (gender == -1) gender = defaultgender; if (gender < 0 || gender > 3) gender = 0; FName nm(name, true); if (nm != NAME_None) { + TableElement* bestItem = nullptr; for (auto map : currentLanguageSet) { auto item = map.second->CheckKey(nm); if (item) { + if (bestItem && bestItem->filenum > item->filenum) + { + // prioritize content from later files, even if the language doesn't fully match. + // This is mainly for Dehacked content. + continue; + } if (langtable) *langtable = map.first; auto c = item->strings[gender].GetChars(); if (c && *c == '$' && c[1] == '$') - return GetString(c + 2, langtable, gender); + c = CheckString(c + 2, langtable, gender); return c; } } @@ -608,7 +613,7 @@ const char *FStringTable::GetString(const char *name, uint32_t *langtable, int g //========================================================================== // -// Finds a string by name in a given language +// Finds a string by name in a given language without attempting any substitution // //========================================================================== @@ -618,7 +623,7 @@ const char *FStringTable::GetLanguageString(const char *name, uint32_t langtable { return nullptr; } - if (gender == -1 && sysCallbacks.GetGender) gender = sysCallbacks.GetGender(); + if (gender == -1) gender = defaultgender; if (gender < 0 || gender > 3) gender = 0; FName nm(name, true); if (nm != NAME_None) @@ -642,7 +647,7 @@ bool FStringTable::MatchDefaultString(const char *name, const char *content) con // Check a secondary key, in case the text comparison cannot be done due to needed orthographic fixes (see Harmony's exit text) FStringf checkkey("%s_CHECK", name); - auto cc = GetLanguageString(checkkey, FStringTable::default_table); + auto cc = GetLanguageString(checkkey.GetChars(), FStringTable::default_table); if (cc) c = cc; return (c && !strnicmp(c, content, strcspn(content, "\n\r\t"))); @@ -655,9 +660,9 @@ bool FStringTable::MatchDefaultString(const char *name, const char *content) con // //========================================================================== -const char *FStringTable::operator() (const char *name) const +const char *FStringTable::GetString(const char *name) const { - const char *str = operator[] (name); + const char *str = CheckString(name, nullptr); return str ? str : name; } diff --git a/src/common/engine/stringtable.h b/src/common/engine/stringtable.h index d75864303d..181d8c7f39 100644 --- a/src/common/engine/stringtable.h +++ b/src/common/engine/stringtable.h @@ -44,6 +44,7 @@ #include +#include #include "basics.h" #include "zstring.h" #include "tarray.h" @@ -83,10 +84,10 @@ class FStringTable using LangMap = TMap; using StringMacroMap = TMap; - void LoadStrings(const char *language); + void LoadStrings(FileSys::FileSystem& fileSystem, const char *language); void UpdateLanguage(const char* language); StringMap GetDefaultStrings() { return allStrings[default_table]; } // Dehacked needs these for comparison - void SetOverrideStrings(StringMap && map) + void SetOverrideStrings(StringMap & map) { allStrings.Insert(override_table, map); UpdateLanguage(nullptr); @@ -94,15 +95,13 @@ class FStringTable const char *GetLanguageString(const char *name, uint32_t langtable, int gender = -1) const; bool MatchDefaultString(const char *name, const char *content) const; - const char *GetString(const char *name, uint32_t *langtable, int gender = -1) const; - const char *operator() (const char *name) const; // Never returns NULL - const char *operator[] (const char *name) const - { - return GetString(name, nullptr); - } + const char *CheckString(const char *name, uint32_t *langtable = nullptr, int gender = -1) const; + const char* GetString(const char* name) const; + const char* GetString(const FString& name) const { return GetString(name.GetChars()); } bool exists(const char *name); - void InsertString(int lumpnum, int langid, FName label, const FString& string); + void InsertString(int filenum, int langid, FName label, const FString& string); + void SetDefaultGender(int gender) { defaultgender = gender; } private: @@ -110,15 +109,15 @@ class FStringTable StringMacroMap allMacros; LangMap allStrings; TArray> currentLanguageSet; + int defaultgender = 0; - void LoadLanguage (int lumpnum, const TArray &buffer); - TArray> parseCSV(const TArray &buffer); - bool ParseLanguageCSV(int lumpnum, const TArray &buffer); + void LoadLanguage (int lumpnum, const char* buffer, size_t size); + TArray> parseCSV(const char* buffer, size_t size); + bool ParseLanguageCSV(int filenum, const char* buffer, size_t size); - bool LoadLanguageFromSpreadsheet(int lumpnum, const TArray &buffer); - bool readMacros(int lumpnum); + bool readMacros(const char* buffer, size_t size); void DeleteString(int langid, FName label); - void DeleteForLabel(int lumpnum, FName label); + void DeleteForLabel(int filenum, FName label); static size_t ProcessEscapes (char *str); public: @@ -136,7 +135,7 @@ class FStringTable const char* localize(const char* str) { - return *str == '$' ? operator()(str + 1) : str; + return *str == '$' ? GetString(str + 1) : str; } }; diff --git a/src/common/filesystem/file_directory.cpp b/src/common/filesystem/file_directory.cpp deleted file mode 100644 index 80b9f6e578..0000000000 --- a/src/common/filesystem/file_directory.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* -** file_directory.cpp -** -**--------------------------------------------------------------------------- -** Copyright 2008-2009 Randy Heit -** Copyright 2009 Christoph Oelckers -** 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. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -**--------------------------------------------------------------------------- -** -** -*/ - - -#include - -#include "resourcefile.h" -#include "cmdlib.h" -#include "printf.h" -#include "findfile.h" - -//========================================================================== -// -// Zip Lump -// -//========================================================================== - -struct FDirectoryLump : public FResourceLump -{ - FileReader NewReader() override; - int FillCache() override; - - FString mFullPath; -}; - - -//========================================================================== -// -// Zip file -// -//========================================================================== - -class FDirectory : public FResourceFile -{ - TArray Lumps; - const bool nosubdir; - - int AddDirectory(const char *dirpath); - void AddEntry(const char *fullpath, int size); - -public: - FDirectory(const char * dirname, bool nosubdirflag = false); - bool Open(bool quiet, LumpFilterInfo* filter); - virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } -}; - - - -//========================================================================== -// -// -// -//========================================================================== - -FDirectory::FDirectory(const char * directory, bool nosubdirflag) -: FResourceFile(NULL), nosubdir(nosubdirflag) -{ - FString dirname; - - #ifdef _WIN32 - directory = _fullpath(NULL, directory, _MAX_PATH); - #else - // Todo for Linux: Resolve the path before using it - #endif - dirname = directory; -#ifdef _WIN32 - free((void *)directory); -#endif - dirname.Substitute("\\", "/"); - if (dirname[dirname.Len()-1] != '/') dirname += '/'; - FileName = dirname; -} - - -//========================================================================== -// -// Windows version -// -//========================================================================== - -int FDirectory::AddDirectory(const char *dirpath) -{ - void * handle; - int count = 0; - - FString dirmatch = dirpath; - findstate_t find; - dirmatch += '*'; - - handle = I_FindFirst(dirmatch.GetChars(), &find); - if (handle == ((void *)(-1))) - { - Printf("Could not scan '%s': %s\n", dirpath, strerror(errno)); - } - else - { - do - { - // I_FindName only returns the file's name and not its full path - auto attr = I_FindAttr(&find); - if (attr & FA_HIDDEN) - { - // Skip hidden files and directories. (Prevents SVN bookkeeping - // info from being included.) - continue; - } - FString fi = I_FindName(&find); - if (attr & FA_DIREC) - { - if (nosubdir || (fi[0] == '.' && - (fi[1] == '\0' || - (fi[1] == '.' && fi[2] == '\0')))) - { - // Do not record . and .. directories. - continue; - } - FString newdir = dirpath; - newdir << fi << '/'; - count += AddDirectory(newdir); - } - else - { - if (strstr(fi, ".orig") || strstr(fi, ".bak") || strstr(fi, ".cache")) - { - // We shouldn't add backup files to the file system - continue; - } - size_t size = 0; - FString fn = FString(dirpath) + fi; - - // The next one is courtesy of EDuke32. :( - // Putting cache files in the application directory is very bad style. - // Unfortunately, having a garbage file named "texture" present will cause serious problems down the line. - if (!stricmp(fi, "textures")) - { - FILE* f = fopen(fn, "rb"); - if (f) - { - char check[3]{}; - fread(check, 1, 3, f); - if (!memcmp(check, "LZ4", 3)) continue; - } - } - - if (GetFileInfo(fn, &size, nullptr)) - { - AddEntry(fn, (int)size); - count++; - } - } - - } while (I_FindNext (handle, &find) == 0); - I_FindClose (handle); - } - return count; -} - -//========================================================================== -// -// -// -//========================================================================== - -bool FDirectory::Open(bool quiet, LumpFilterInfo* filter) -{ - NumLumps = AddDirectory(FileName); - PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump), filter); - return true; -} - -//========================================================================== -// -// -// -//========================================================================== - -void FDirectory::AddEntry(const char *fullpath, int size) -{ - FDirectoryLump *lump_p = &Lumps[Lumps.Reserve(1)]; - - // Store the full path here so that we can access the file later, even if it is from a filter directory. - lump_p->mFullPath = fullpath; - - // [mxd] Convert name to lowercase - FString name = fullpath + strlen(FileName); - name.ToLower(); - - // The lump's name is only the part relative to the main directory - lump_p->LumpNameSetup(name); - lump_p->LumpSize = size; - lump_p->Owner = this; - lump_p->Flags = 0; - lump_p->CheckEmbedded(nullptr); -} - - -//========================================================================== -// -// -// -//========================================================================== - -FileReader FDirectoryLump::NewReader() -{ - FileReader fr; - fr.OpenFile(mFullPath); - return fr; -} - -//========================================================================== -// -// -// -//========================================================================== - -int FDirectoryLump::FillCache() -{ - FileReader fr; - Cache = new char[LumpSize]; - if (!fr.OpenFile(mFullPath)) - { - memset(Cache, 0, LumpSize); - return 0; - } - fr.Read(Cache, LumpSize); - RefCount = 1; - return 1; -} - -//========================================================================== -// -// File open -// -//========================================================================== - -FResourceFile *CheckDir(const char *filename, bool quiet, bool nosubdirflag, LumpFilterInfo* filter) -{ - auto rf = new FDirectory(filename, nosubdirflag); - if (rf->Open(quiet, filter)) return rf; - delete rf; - return nullptr; -} - diff --git a/src/common/filesystem/file_zip.cpp b/src/common/filesystem/file_zip.cpp deleted file mode 100644 index e14305b529..0000000000 --- a/src/common/filesystem/file_zip.cpp +++ /dev/null @@ -1,724 +0,0 @@ -/* -** file_zip.cpp -** -**--------------------------------------------------------------------------- -** Copyright 1998-2009 Randy Heit -** Copyright 2005-2009 Christoph Oelckers -** 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. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -**--------------------------------------------------------------------------- -** -** -*/ - -#include -#include "file_zip.h" -#include "cmdlib.h" - -#include "printf.h" -#include "w_zip.h" - -#include "ancientzip.h" - -#define BUFREADCOMMENT (0x400) - -//========================================================================== -// -// Decompression subroutine -// -//========================================================================== - -static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags) -{ - try - { - switch (Method) - { - case METHOD_STORED: - { - Reader.Read(Cache, LumpSize); - break; - } - - case METHOD_DEFLATE: - case METHOD_BZIP2: - case METHOD_LZMA: - { - FileReader frz; - if (frz.OpenDecompressor(Reader, LumpSize, Method, false, [](const char* err) { I_Error("%s", err); })) - { - frz.Read(Cache, LumpSize); - } - break; - } - - // Fixme: These should also use a stream - case METHOD_IMPLODE: - { - FZipExploder exploder; - exploder.Explode((unsigned char *)Cache, LumpSize, Reader, CompressedSize, GPFlags); - break; - } - - case METHOD_SHRINK: - { - ShrinkLoop((unsigned char *)Cache, LumpSize, Reader, CompressedSize); - break; - } - - default: - assert(0); - return false; - } - } - catch (CRecoverableError &err) - { - Printf("%s\n", err.GetMessage()); - return false; - } - return true; -} - -bool FCompressedBuffer::Decompress(char *destbuffer) -{ - FileReader mr; - mr.OpenMemory(mBuffer, mCompressedSize); - return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags); -} - -//----------------------------------------------------------------------- -// -// Finds the central directory end record in the end of the file. -// Taken from Quake3 source but the file in question is not GPL'ed. ;) -// -//----------------------------------------------------------------------- - -static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64) -{ - unsigned char buf[BUFREADCOMMENT + 4]; - uint32_t FileSize; - uint32_t uBackRead; - uint32_t uMaxBack; // maximum size of global comment - uint32_t uPosFound=0; - - FileSize = (uint32_t)fin.GetLength(); - uMaxBack = min(0xffff, FileSize); - - uBackRead = 4; - while (uBackRead < uMaxBack) - { - uint32_t uReadSize, uReadPos; - int i; - if (uBackRead + BUFREADCOMMENT > uMaxBack) - uBackRead = uMaxBack; - else - uBackRead += BUFREADCOMMENT; - uReadPos = FileSize - uBackRead; - - uReadSize = min((BUFREADCOMMENT + 4), (FileSize - uReadPos)); - - if (fin.Seek(uReadPos, FileReader::SeekSet) != 0) break; - - if (fin.Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break; - - for (i = (int)uReadSize - 3; (i--) > 0;) - { - if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6 && !*zip64 && uPosFound == 0) - { - *zip64 = false; - uPosFound = uReadPos + i; - } - if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 6 && buf[i+3] == 6) - { - *zip64 = true; - uPosFound = uReadPos + i; - return uPosFound; - } - } - } - return uPosFound; -} - -//========================================================================== -// -// Zip file -// -//========================================================================== - -FZipFile::FZipFile(const char * filename, FileReader &file) -: FResourceFile(filename, file) -{ - Lumps = NULL; -} - -bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) -{ - bool zip64 = false; - uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64); - int skipped = 0; - - Lumps = NULL; - - if (centraldir == 0) - { - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", FileName.GetChars()); - return false; - } - - uint64_t dirsize, DirectoryOffset; - if (!zip64) - { - FZipEndOfCentralDirectory info; - // Read the central directory info. - Reader.Seek(centraldir, FileReader::SeekSet); - Reader.Read(&info, sizeof(FZipEndOfCentralDirectory)); - - // No multi-disk zips! - if (info.NumEntries != info.NumEntriesOnAllDisks || - info.FirstDisk != 0 || info.DiskNumber != 0) - { - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars()); - return false; - } - - NumLumps = LittleShort(info.NumEntries); - dirsize = LittleLong(info.DirectorySize); - DirectoryOffset = LittleLong(info.DirectoryOffset); - } - else - { - FZipEndOfCentralDirectory64 info; - // Read the central directory info. - Reader.Seek(centraldir, FileReader::SeekSet); - Reader.Read(&info, sizeof(FZipEndOfCentralDirectory64)); - - // No multi-disk zips! - if (info.NumEntries != info.NumEntriesOnAllDisks || - info.FirstDisk != 0 || info.DiskNumber != 0) - { - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars()); - return false; - } - - NumLumps = (uint32_t)info.NumEntries; - dirsize = info.DirectorySize; - DirectoryOffset = info.DirectoryOffset; - } - Lumps = new FZipLump[NumLumps]; - - // Load the entire central directory. Too bad that this contains variable length entries... - void *directory = malloc(dirsize); - Reader.Seek(DirectoryOffset, FileReader::SeekSet); - Reader.Read(directory, dirsize); - - char *dirptr = (char*)directory; - FZipLump *lump_p = Lumps; - - FString name0, name1; - bool foundspeciallump = false; - bool foundprefix = false; - - // Check if all files have the same prefix so that this can be stripped out. - // This will only be done if there is either a MAPINFO, ZMAPINFO or GAMEINFO lump in the subdirectory, denoting a ZDoom mod. - if (NumLumps > 1) for (uint32_t i = 0; i < NumLumps; i++) - { - FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; - - int len = LittleShort(zip_fh->NameLength); - FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); - - dirptr += sizeof(FZipCentralDirectoryInfo) + - LittleShort(zip_fh->NameLength) + - LittleShort(zip_fh->ExtraLength) + - LittleShort(zip_fh->CommentLength); - - if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. - { - free(directory); - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars()); - return false; - } - - name.ToLower(); - if (name.IndexOf("filter/") == 0) - continue; // 'filter' is a reserved name of the file system. - if (name.IndexOf("__macosx") == 0) - continue; // skip Apple garbage. At this stage only the root folder matters. - if (name.IndexOf(".bat") >= 0 || name.IndexOf(".exe") >= 0) - continue; // also ignore executables for this. - if (!foundprefix) - { - // check for special names, if one of these gets found this must be treated as a normal zip. - bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size()); - if (isspecial) break; - name0 = name.Left(name.LastIndexOf("/")+1); - name1 = name.Left(name.IndexOf("/") + 1); - foundprefix = true; - } - - if (name.IndexOf(name0) != 0) - { - if (name1.IsNotEmpty()) - { - name0 = name1; - if (name.IndexOf(name0) != 0) - { - name0 = ""; - } - } - if (name0.IsEmpty()) - break; - } - if (!foundspeciallump && filter) - { - // at least one of the more common definition lumps must be present. - for (auto &p : filter->requiredPrefixes) - { - if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == ptrdiff_t(name.Len() - strlen(p))) - { - foundspeciallump = true; - break; - } - } - } - } - // If it ran through the list without finding anything it should not attempt any path remapping. - if (!foundspeciallump) name0 = ""; - - dirptr = (char*)directory; - lump_p = Lumps; - for (uint32_t i = 0; i < NumLumps; i++) - { - FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; - - int len = LittleShort(zip_fh->NameLength); - FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); - dirptr += sizeof(FZipCentralDirectoryInfo) + - LittleShort(zip_fh->NameLength) + - LittleShort(zip_fh->ExtraLength) + - LittleShort(zip_fh->CommentLength); - - if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. - { - free(directory); - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars()); - return false; - } - - if (name.IndexOf("__macosx") == 0 || name.IndexOf("__MACOSX") == 0) - { - skipped++; - continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation. - } - if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); - - // skip Directories - if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0)) - { - skipped++; - continue; - } - - // Ignore unknown compression formats - zip_fh->Method = LittleShort(zip_fh->Method); - if (zip_fh->Method != METHOD_STORED && - zip_fh->Method != METHOD_DEFLATE && - zip_fh->Method != METHOD_LZMA && - zip_fh->Method != METHOD_BZIP2 && - zip_fh->Method != METHOD_IMPLODE && - zip_fh->Method != METHOD_SHRINK) - { - if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.GetChars(), name.GetChars(), zip_fh->Method); - skipped++; - continue; - } - // Also ignore encrypted entries - zip_fh->Flags = LittleShort(zip_fh->Flags); - if (zip_fh->Flags & ZF_ENCRYPTED) - { - if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", FileName.GetChars(), name.GetChars()); - skipped++; - continue; - } - - FixPathSeperator(name); - name.ToLower(); - - uint32_t UncompressedSize =LittleLong(zip_fh->UncompressedSize32); - uint32_t CompressedSize = LittleLong(zip_fh->CompressedSize32); - uint64_t LocalHeaderOffset = LittleLong(zip_fh->LocalHeaderOffset32); - if (zip_fh->ExtraLength > 0) - { - uint8_t* rawext = (uint8_t*)zip_fh + sizeof(*zip_fh) + zip_fh->NameLength; - uint32_t ExtraLength = LittleLong(zip_fh->ExtraLength); - - while (ExtraLength > 0) - { - auto zip_64 = (FZipCentralDirectoryInfo64BitExt*)rawext; - uint32_t BlockLength = LittleLong(zip_64->Length); - rawext += BlockLength + 4; - ExtraLength -= BlockLength + 4; - if (LittleLong(zip_64->Type) == 1 && BlockLength >= 0x18) - { - if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff) - { - // The file system is limited to 32 bit file sizes; - if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is too large.\n", FileName.GetChars(), name.GetChars()); - skipped++; - continue; - } - UncompressedSize = (uint32_t)zip_64->UncompressedSize; - CompressedSize = (uint32_t)zip_64->CompressedSize; - LocalHeaderOffset = zip_64->LocalHeaderOffset; - } - } - } - - lump_p->LumpNameSetup(name); - lump_p->LumpSize = UncompressedSize; - lump_p->Owner = this; - // The start of the Reader will be determined the first time it is accessed. - lump_p->Flags = LUMPF_FULLPATH; - lump_p->NeedFileStart = true; - lump_p->Method = uint8_t(zip_fh->Method); - if (lump_p->Method != METHOD_STORED) lump_p->Flags |= LUMPF_COMPRESSED; - lump_p->GPFlags = zip_fh->Flags; - lump_p->CRC32 = zip_fh->CRC32; - lump_p->CompressedSize = CompressedSize; - lump_p->Position = LocalHeaderOffset; - lump_p->CheckEmbedded(filter); - - lump_p++; - } - // Resize the lump record array to its actual size - NumLumps -= skipped; - free(directory); - - GenerateHash(); - PostProcessArchive(&Lumps[0], sizeof(FZipLump), filter); - return true; -} - -//========================================================================== -// -// Zip file -// -//========================================================================== - -FZipFile::~FZipFile() -{ - if (Lumps != NULL) delete [] Lumps; -} - -//========================================================================== -// -// -// -//========================================================================== - -FCompressedBuffer FZipLump::GetRawData() -{ - FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)CompressedSize, Method, GPFlags, CRC32, new char[CompressedSize] }; - if (NeedFileStart) SetLumpAddress(); - Owner->Reader.Seek(Position, FileReader::SeekSet); - Owner->Reader.Read(cbuf.mBuffer, CompressedSize); - return cbuf; -} - -//========================================================================== -// -// SetLumpAddress -// -//========================================================================== - -void FZipLump::SetLumpAddress() -{ - // This file is inside a zip and has not been opened before. - // Position points to the start of the local file header, which we must - // read and skip so that we can get to the actual file data. - FZipLocalFileHeader localHeader; - int skiplen; - - Owner->Reader.Seek(Position, FileReader::SeekSet); - Owner->Reader.Read(&localHeader, sizeof(localHeader)); - skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength); - Position += sizeof(localHeader) + skiplen; - NeedFileStart = false; -} - -//========================================================================== -// -// Get reader (only returns non-NULL if not encrypted) -// -//========================================================================== - -FileReader *FZipLump::GetReader() -{ - // Don't return the reader if this lump is encrypted - // In that case always force caching of the lump - if (Method == METHOD_STORED) - { - if (NeedFileStart) SetLumpAddress(); - Owner->Reader.Seek(Position, FileReader::SeekSet); - return &Owner->Reader; - } - else return NULL; -} - -//========================================================================== -// -// Fills the lump cache and performs decompression -// -//========================================================================== - -int FZipLump::FillCache() -{ - if (NeedFileStart) SetLumpAddress(); - const char *buffer; - - if (Method == METHOD_STORED && (buffer = Owner->Reader.GetBuffer()) != NULL) - { - // This is an in-memory file so the cache can point directly to the file's data. - Cache = const_cast(buffer) + Position; - RefCount = -1; - return -1; - } - - Owner->Reader.Seek(Position, FileReader::SeekSet); - Cache = new char[LumpSize]; - UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags); - RefCount = 1; - return 1; -} - -//========================================================================== -// -// -// -//========================================================================== - -int FZipLump::GetFileOffset() -{ - if (Method != METHOD_STORED) return -1; - if (NeedFileStart) SetLumpAddress(); - return (int)Position; -} - -//========================================================================== -// -// File open -// -//========================================================================== - -FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) -{ - char head[4]; - - if (file.GetLength() >= (long)sizeof(FZipLocalFileHeader)) - { - file.Seek(0, FileReader::SeekSet); - file.Read(&head, 4); - file.Seek(0, FileReader::SeekSet); - if (!memcmp(head, "PK\x3\x4", 4)) - { - auto rf = new FZipFile(filename, file); - if (rf->Open(quiet, filter)) return rf; - - file = std::move(rf->Reader); // to avoid destruction of reader - delete rf; - } - } - return NULL; -} - - - -//========================================================================== -// -// time_to_dos -// -// Converts time from struct tm to the DOS format used by zip files. -// -//========================================================================== - -static std::pair time_to_dos(struct tm *time) -{ - std::pair val; - if (time == NULL || time->tm_year < 80) - { - val.first = val.second = 0; - } - else - { - val.first = (time->tm_year - 80) * 512 + (time->tm_mon + 1) * 32 + time->tm_mday; - val.second= time->tm_hour * 2048 + time->tm_min * 32 + time->tm_sec / 2; - } - return val; -} - -//========================================================================== -// -// append_to_zip -// -// Write a given file to the zipFile. -// -// zipfile: zip object to be written to -// -// returns: position = success, -1 = error -// -//========================================================================== - -int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, std::pair &dostime) -{ - FZipLocalFileHeader local; - int position; - - local.Magic = ZIP_LOCALFILE; - local.VersionToExtract[0] = 20; - local.VersionToExtract[1] = 0; - local.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort((uint16_t)2) : LittleShort((uint16_t)content.mZipFlags); - local.Method = LittleShort((uint16_t)content.mMethod); - local.ModDate = LittleShort(dostime.first); - local.ModTime = LittleShort(dostime.second); - local.CRC32 = content.mCRC32; - local.UncompressedSize = LittleLong(content.mSize); - local.CompressedSize = LittleLong(content.mCompressedSize); - local.NameLength = LittleShort((unsigned short)strlen(filename)); - local.ExtraLength = 0; - - // Fill in local directory header. - - position = (int)zip_file->Tell(); - - // Write out the header, file name, and file data. - if (zip_file->Write(&local, sizeof(local)) != sizeof(local) || - zip_file->Write(filename, strlen(filename)) != strlen(filename) || - zip_file->Write(content.mBuffer, content.mCompressedSize) != content.mCompressedSize) - { - return -1; - } - return position; -} - - -//========================================================================== -// -// write_central_dir -// -// Writes the central directory entry for a file. -// -//========================================================================== - -int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, std::pair &dostime, int position) -{ - FZipCentralDirectoryInfo dir; - - dir.Magic = ZIP_CENTRALFILE; - dir.VersionMadeBy[0] = 20; - dir.VersionMadeBy[1] = 0; - dir.VersionToExtract[0] = 20; - dir.VersionToExtract[1] = 0; - dir.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort((uint16_t)2) : LittleShort((uint16_t)content.mZipFlags); - dir.Method = LittleShort((uint16_t)content.mMethod); - dir.ModTime = LittleShort(dostime.first); - dir.ModDate = LittleShort(dostime.second); - dir.CRC32 = content.mCRC32; - dir.CompressedSize32 = LittleLong(content.mCompressedSize); - dir.UncompressedSize32 = LittleLong(content.mSize); - dir.NameLength = LittleShort((unsigned short)strlen(filename)); - dir.ExtraLength = 0; - dir.CommentLength = 0; - dir.StartingDiskNumber = 0; - dir.InternalAttributes = 0; - dir.ExternalAttributes = 0; - dir.LocalHeaderOffset32 = LittleLong(position); - - if (zip_file->Write(&dir, sizeof(dir)) != sizeof(dir) || - zip_file->Write(filename, strlen(filename)) != strlen(filename)) - { - return -1; - } - return 0; -} - -bool WriteZip(const char *filename, TArray &filenames, TArray &content) -{ - // try to determine local time - struct tm *ltime; - time_t ttime; - ttime = time(nullptr); - ltime = localtime(&ttime); - auto dostime = time_to_dos(ltime); - - TArray positions; - - if (filenames.Size() != content.Size()) return false; - - auto f = FileWriter::Open(filename); - if (f != nullptr) - { - for (unsigned i = 0; i < filenames.Size(); i++) - { - int pos = AppendToZip(f, filenames[i], content[i], dostime); - if (pos == -1) - { - delete f; - remove(filename); - return false; - } - positions.Push(pos); - } - - int dirofs = (int)f->Tell(); - for (unsigned i = 0; i < filenames.Size(); i++) - { - if (AppendCentralDirectory(f, filenames[i], content[i], dostime, positions[i]) < 0) - { - delete f; - remove(filename); - return false; - } - } - - // Write the directory terminator. - FZipEndOfCentralDirectory dirend; - dirend.Magic = ZIP_ENDOFDIR; - dirend.DiskNumber = 0; - dirend.FirstDisk = 0; - dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort((uint16_t)filenames.Size()); - dirend.DirectoryOffset = LittleLong(dirofs); - dirend.DirectorySize = LittleLong((uint32_t)(f->Tell() - dirofs)); - dirend.ZipCommentLength = 0; - if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend)) - { - delete f; - remove(filename); - return false; - } - delete f; - return true; - } - return false; -} diff --git a/src/common/filesystem/file_zip.h b/src/common/filesystem/file_zip.h deleted file mode 100644 index c6a42d9a45..0000000000 --- a/src/common/filesystem/file_zip.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __FILE_ZIP_H -#define __FILE_ZIP_H - -#include "resourcefile.h" - -//========================================================================== -// -// Zip Lump -// -//========================================================================== - -struct FZipLump : public FResourceLump -{ - uint16_t GPFlags; - uint8_t Method; - bool NeedFileStart; - int CompressedSize; - int64_t Position; - unsigned CRC32; - - virtual FileReader *GetReader(); - virtual int FillCache(); - -private: - void SetLumpAddress(); - virtual int GetFileOffset(); - FCompressedBuffer GetRawData(); -}; - - -//========================================================================== -// -// Zip file -// -//========================================================================== - -class FZipFile : public FResourceFile -{ - FZipLump *Lumps; - -public: - FZipFile(const char * filename, FileReader &file); - virtual ~FZipFile(); - bool Open(bool quiet, LumpFilterInfo* filter); - virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } -}; - - -#endif \ No newline at end of file diff --git a/src/common/filesystem/filesystem.h b/src/common/filesystem/filesystem.h deleted file mode 100644 index 2dc80f7ffc..0000000000 --- a/src/common/filesystem/filesystem.h +++ /dev/null @@ -1,226 +0,0 @@ -#pragma once -//----------------------------------------------------------------------------- -// -// DESCRIPTION: -// File system I/O functions. -// -//----------------------------------------------------------------------------- - - - -#include "files.h" -#include "tarray.h" -#include "cmdlib.h" -#include "zstring.h" -#include "resourcefile.h" - -class FResourceFile; -struct FResourceLump; -class FGameTexture; - -union LumpShortName -{ - char String[9]; - - uint32_t dword; // These are for accessing the first 4 or 8 chars of - uint64_t qword; // Name as a unit without breaking strict aliasing rules -}; - - -// A lump in memory. -class FileData -{ -public: - FileData (); - - FileData (const FileData ©); - FileData &operator= (const FileData ©); - ~FileData (); - void *GetMem () { return Block.Len() == 0 ? NULL : (void *)Block.GetChars(); } - size_t GetSize () { return Block.Len(); } - const FString &GetString () const { return Block; } - -private: - FileData (const FString &source); - - FString Block; - - friend class FileSystem; -}; - -struct FolderEntry -{ - const char *name; - unsigned lumpnum; -}; - -class FileSystem -{ -public: - FileSystem (); - ~FileSystem (); - - // The wadnum for the IWAD - int GetIwadNum() { return IwadIndex; } - void SetIwadNum(int x) { IwadIndex = x; } - - int GetMaxIwadNum() { return MaxIwadIndex; } - void SetMaxIwadNum(int x) { MaxIwadIndex = x; } - - void InitSingleFile(const char *filename, bool quiet = false); - void InitMultipleFiles (TArray &filenames, bool quiet = false, LumpFilterInfo* filter = nullptr, bool allowduplicates = false, FILE* hashfile = nullptr); - void AddFile (const char *filename, FileReader *wadinfo, bool quiet, LumpFilterInfo* filter, FILE* hashfile); - int CheckIfResourceFileLoaded (const char *name) noexcept; - void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {} - - const char *GetResourceFileName (int filenum) const noexcept; - const char *GetResourceFileFullName (int wadnum) const noexcept; - - int GetFirstEntry(int wadnum) const noexcept; - int GetLastEntry(int wadnum) const noexcept; - int GetEntryCount(int wadnum) const noexcept; - - int CheckNumForName (const char *name, int namespc); - int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true); - int GetNumForName (const char *name, int namespc); - - inline int CheckNumForName (const uint8_t *name) { return CheckNumForName ((const char *)name, ns_global); } - inline int CheckNumForName (const char *name) { return CheckNumForName (name, ns_global); } - inline int CheckNumForName (const FString &name) { return CheckNumForName (name.GetChars()); } - inline int CheckNumForName (const uint8_t *name, int ns) { return CheckNumForName ((const char *)name, ns); } - inline int GetNumForName (const char *name) { return GetNumForName (name, ns_global); } - inline int GetNumForName (const FString &name) { return GetNumForName (name.GetChars(), ns_global); } - inline int GetNumForName (const uint8_t *name) { return GetNumForName ((const char *)name); } - inline int GetNumForName (const uint8_t *name, int ns) { return GetNumForName ((const char *)name, ns); } - - int CheckNumForFullName (const char *name, bool trynormal = false, int namespc = ns_global, bool ignoreext = false); - int CheckNumForFullName (const char *name, int wadfile); - int GetNumForFullName (const char *name); - int FindFile(const char* name) - { - return CheckNumForFullName(name); - } - - bool FileExists(const char* name) - { - return FindFile(name) >= 0; - } - - bool FileExists(const FString& name) - { - return FindFile(name) >= 0; - } - - bool FileExists(const std::string& name) - { - return FindFile(name.c_str()) >= 0; - } - - LumpShortName& GetShortName(int i); // may only be called before the hash chains are set up. - FString& GetLongName(int i); // may only be called before the hash chains are set up. - void RenameFile(int num, const char* fn); - bool CreatePathlessCopy(const char* name, int id, int flags); - - inline int CheckNumForFullName(const FString &name, bool trynormal = false, int namespc = ns_global) { return CheckNumForFullName(name.GetChars(), trynormal, namespc); } - inline int CheckNumForFullName (const FString &name, int wadfile) { return CheckNumForFullName(name.GetChars(), wadfile); } - inline int GetNumForFullName (const FString &name) { return GetNumForFullName(name.GetChars()); } - - void SetLinkedTexture(int lump, FGameTexture *tex); - FGameTexture *GetLinkedTexture(int lump); - - - void ReadFile (int lump, void *dest); - TArray GetFileData(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!) - FileData ReadFile (int lump); - FileData ReadFile (const char *name) { return ReadFile (GetNumForName (name)); } - - inline TArray LoadFile(const char* name, int padding = 0) - { - auto lump = FindFile(name); - if (lump < 0) return TArray(); - return GetFileData(lump, padding); - } - - FileReader OpenFileReader(int lump); // opens a reader that redirects to the containing file's one. - FileReader ReopenFileReader(int lump, bool alwayscache = false); // opens an independent reader. - FileReader OpenFileReader(const char* name); - - int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication - int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names - int FindLumpFullName(const char* name, int* lastlump, bool noext = false); - bool CheckFileName (int lump, const char *name); // [RH] True if lump's name == name - - int FindFileWithExtensions(const char* name, const char* const* exts, int count); - int FindResource(int resid, const char* type, int filenum = -1) const noexcept; - int GetResource(int resid, const char* type, int filenum = -1) const; - - - static uint32_t LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name - - int FileLength (int lump) const; - int GetFileOffset (int lump); // [RH] Returns offset of lump in the wadfile - int GetFileFlags (int lump); // Return the flags for this lump - void GetFileShortName (char *to, int lump) const; // [RH] Copies the lump name to to using uppercopy - void GetFileShortName (FString &to, int lump) const; - const char* GetFileShortName(int lump) const; - const char *GetFileFullName (int lump, bool returnshort = true) const; // [RH] Returns the lump's full name - FString GetFileFullPath (int lump) const; // [RH] Returns wad's name + lump's full name - int GetFileContainer (int lump) const; // [RH] Returns wadnum for a specified lump - int GetFileNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to - void SetFileNamespace(int lump, int ns); - int GetResourceId(int lump) const; // Returns the RFF index number for this lump - const char* GetResourceType(int lump) const; - bool CheckFileName (int lump, const char *name) const; // [RH] Returns true if the names match - unsigned GetFilesInFolder(const char *path, TArray &result, bool atomic) const; - - int GetNumEntries() const - { - return NumEntries; - } - - int GetNumWads() const - { - return Files.Size(); - } - - void AddLump(FResourceLump* lump); - int AddExternalFile(const char *filename); - int AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags); - FileReader* GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD - void InitHashChains(); - FResourceLump* GetFileAt(int no); - -protected: - - struct LumpRecord; - - TArray Files; - TArray FileInfo; - - TArray Hashes; // one allocation for all hash lists. - uint32_t *FirstLumpIndex; // [RH] Hashing stuff moved out of lumpinfo structure - uint32_t *NextLumpIndex; - - uint32_t *FirstLumpIndex_FullName; // The same information for fully qualified paths from .zips - uint32_t *NextLumpIndex_FullName; - - uint32_t *FirstLumpIndex_NoExt; // The same information for fully qualified paths from .zips - uint32_t *NextLumpIndex_NoExt; - - uint32_t* FirstLumpIndex_ResId; // The same information for fully qualified paths from .zips - uint32_t* NextLumpIndex_ResId; - - uint32_t NumEntries = 0; // Not necessarily the same as FileInfo.Size() - uint32_t NumWads; - - int IwadIndex = -1; - int MaxIwadIndex = -1; - -private: - void DeleteAll(); - void MoveLumpsInFolder(const char *); - -}; - -extern FileSystem fileSystem; - diff --git a/src/common/filesystem/include/fs_decompress.h b/src/common/filesystem/include/fs_decompress.h new file mode 100644 index 0000000000..0ea062ddb4 --- /dev/null +++ b/src/common/filesystem/include/fs_decompress.h @@ -0,0 +1,63 @@ +#pragma once +#include "fs_files.h" + +namespace FileSys { + +// Zip compression methods, extended by some internal types to be passed to OpenDecompressor +enum ECompressionMethod +{ + METHOD_STORED = 0, + METHOD_SHRINK = 1, + METHOD_IMPLODE = 6, + METHOD_DEFLATE = 8, + METHOD_BZIP2 = 12, + METHOD_LZMA = 14, + METHOD_XZ = 95, + METHOD_PPMD = 98, + METHOD_LZSS = 1337, // not used in Zips - this is for Console Doom compression + METHOD_ZLIB = 1338, // Zlib stream with header, used by compressed nodes. + METHOD_RFFCRYPT = 1339, // not actual compression but can be put in here to make handling easier. + METHOD_IMPLODE_MIN = 1000, // having discrete types for these avoids keeping around the GPFlags word in Zips. + METHOD_IMPLODE_0 = 1000, + METHOD_IMPLODE_2 = 1002, + METHOD_IMPLODE_4 = 1004, + METHOD_IMPLODE_6 = 1006, + METHOD_IMPLODE_MAX = 1006, + METHOD_INVALID = 0x7fff, + METHOD_TRANSFEROWNER = 0x8000, +}; + +enum EDecompressFlags +{ + DCF_TRANSFEROWNER = 1, + DCF_SEEKABLE = 2, + DCF_EXCEPTIONS = 4, + DCF_CACHED = 8, +}; + +bool OpenDecompressor(FileReader& self, FileReader &parent, FileReader::Size length, int method, int flags = 0); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used. + +// This holds a compresed Zip entry with all needed info to decompress it. +struct FCompressedBuffer +{ + size_t mSize; + size_t mCompressedSize; + int mMethod; + unsigned mCRC32; + char* mBuffer; + const char* filename; + + bool Decompress(char* destbuffer); + void Clean() + { + mSize = mCompressedSize = 0; + if (mBuffer != nullptr) + { + delete[] mBuffer; + mBuffer = nullptr; + } + } +}; + + +} diff --git a/src/common/utility/files.h b/src/common/filesystem/include/fs_files.h similarity index 55% rename from src/common/utility/files.h rename to src/common/filesystem/include/fs_files.h index 66fa9a3540..e0c1362554 100644 --- a/src/common/utility/files.h +++ b/src/common/filesystem/include/fs_files.h @@ -4,7 +4,7 @@ ** **--------------------------------------------------------------------------- ** Copyright 1998-2008 Randy Heit -** Copyright 2005-2008 Christoph Oelckers +** Copyright 2005-2023 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -39,72 +39,151 @@ #include #include #include +#include +#include #include -#include "basics.h" -#include "m_swap.h" -#include "tarray.h" +#include +#include "fs_swap.h" -// Zip compression methods, extended by some internal types to be passed to OpenDecompressor -enum +namespace FileSys { + +class FileSystemException : public std::exception { - METHOD_STORED = 0, - METHOD_SHRINK = 1, - METHOD_IMPLODE = 6, - METHOD_DEFLATE = 8, - METHOD_BZIP2 = 12, - METHOD_LZMA = 14, - METHOD_PPMD = 98, - METHOD_LZSS = 1337, // not used in Zips - this is for Console Doom compression - METHOD_ZLIB = 1338, // Zlib stream with header, used by compressed nodes. - METHOD_TRANSFEROWNER = 0x8000, +protected: + static const int MAX_FSERRORTEXT = 1024; + char m_Message[MAX_FSERRORTEXT]; + +public: + FileSystemException(const char* error, ...) + { + va_list argptr; + va_start(argptr, error); + vsnprintf(m_Message, MAX_FSERRORTEXT, error, argptr); + va_end(argptr); + } + FileSystemException(const char* error, va_list argptr) + { + vsnprintf(m_Message, MAX_FSERRORTEXT, error, argptr); + } + char const* what() const noexcept override + { + return m_Message; + } }; class FileReader; -class FileReaderInterface +// an opaque memory buffer to the file's content. Can either own the memory or just point to an external buffer. +class FileData { + void* memory; + size_t length; + bool owned; + public: - long Length = -1; - virtual ~FileReaderInterface() {} - virtual long Tell () const = 0; - virtual long Seek (long offset, int origin) = 0; - virtual long Read (void *buffer, long len) = 0; - virtual char *Gets(char *strbuf, int len) = 0; - virtual const char *GetBuffer() const { return nullptr; } - long GetLength () const { return Length; } -}; + using value_type = uint8_t; + FileData() { memory = nullptr; length = 0; owned = true; } + FileData(const void* memory_, size_t len, bool own = true) + { + length = len; + if (own) + { + length = len; + memory = malloc(len); + owned = true; + if (memory_) memcpy(memory, memory_, len); + } + else + { + memory = (void*)memory_; + owned = false; + } + } + uint8_t* writable() const { return owned? (uint8_t*)memory : nullptr; } + const void* data() const { return memory; } + size_t size() const { return length; } + const char* string() const { return (const char*)memory; } + const uint8_t* bytes() const { return (const uint8_t*)memory; } + + FileData& operator = (const FileData& copy) + { + if (owned && memory) free(memory); + length = copy.length; + owned = copy.owned; + if (owned) + { + memory = malloc(length); + memcpy(memory, copy.memory, length); + } + else memory = copy.memory; + return *this; + } -class MemoryReader : public FileReaderInterface -{ -protected: - const char * bufptr = nullptr; - long FilePos = 0; + FileData& operator = (FileData&& copy) noexcept + { + if (owned && memory) free(memory); + length = copy.length; + owned = copy.owned; + memory = copy.memory; + copy.memory = nullptr; + copy.length = 0; + copy.owned = true; + return *this; + } + + FileData(const FileData& copy) + { + memory = nullptr; + *this = copy; + } - MemoryReader() - {} + ~FileData() + { + if (owned && memory) free(memory); + } -public: - MemoryReader(const char *buffer, long length) + void* allocate(size_t len) + { + if (!owned) memory = nullptr; + length = len; + owned = true; + memory = realloc(memory, length); + return memory; + } + + void set(const void* mem, size_t len) + { + memory = (void*)mem; + length = len; + owned = false; + } + + void clear() { - bufptr = buffer; - Length = length; - FilePos = 0; + if (owned && memory) free(memory); + memory = nullptr; + length = 0; + owned = true; } - long Tell() const override; - long Seek(long offset, int origin) override; - long Read(void *buffer, long len) override; - char *Gets(char *strbuf, int len) override; - virtual const char *GetBuffer() const override { return bufptr; } }; -struct FResourceLump; +class FileReaderInterface +{ +public: + ptrdiff_t Length = -1; + virtual ~FileReaderInterface() {} + virtual ptrdiff_t Tell () const = 0; + virtual ptrdiff_t Seek (ptrdiff_t offset, int origin) = 0; + virtual ptrdiff_t Read (void *buffer, ptrdiff_t len) = 0; + virtual char *Gets(char *strbuf, ptrdiff_t len) = 0; + virtual const char *GetBuffer() const { return nullptr; } + ptrdiff_t GetLength () const { return Length; } +}; class FileReader { - friend struct FResourceLump; // needs access to the private constructor. - FileReaderInterface *mReader = nullptr; FileReader(const FileReader &r) = delete; @@ -128,13 +207,13 @@ class FileReader FileReader() {} - FileReader(FileReader &&r) + FileReader(FileReader &&r) noexcept { mReader = r.mReader; r.mReader = nullptr; } - FileReader& operator =(FileReader &&r) + FileReader& operator =(FileReader &&r) noexcept { Close(); mReader = r.mReader; @@ -167,12 +246,10 @@ class FileReader mReader = nullptr; } - bool OpenFile(const char *filename, Size start = 0, Size length = -1); + bool OpenFile(const char *filename, Size start = 0, Size length = -1, bool buffered = false); bool OpenFilePart(FileReader &parent, Size start, Size length); bool OpenMemory(const void *mem, Size length); // read directly from the buffer - bool OpenMemoryArray(const void *mem, Size length); // read from a copy of the buffer. - bool OpenMemoryArray(std::function&)> getter); // read contents to a buffer and return a reader to it - bool OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function& cb); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used. + bool OpenMemoryArray(FileData& data); // take the given array Size Tell() const { @@ -181,42 +258,26 @@ class FileReader Size Seek(Size offset, ESeek origin) { - return mReader->Seek((long)offset, origin); + return mReader->Seek(offset, origin); } - Size Read(void *buffer, Size len) + Size Read(void *buffer, Size len) const { - return mReader->Read(buffer, (long)len); + return mReader->Read(buffer, len); } - TArray Read(size_t len) - { - TArray buffer((int)len, true); - Size length = mReader->Read(&buffer[0], (long)len); - buffer.Clamp((int)length); - return buffer; - } + FileData Read(size_t len); + FileData ReadPadded(size_t padding); - TArray Read() + FileData Read() { - TArray buffer(mReader->Length, true); - Size length = mReader->Read(&buffer[0], mReader->Length); - if (length < mReader->Length) buffer.Clear(); - return buffer; + return Read(GetLength()); } - TArray ReadPadded(int padding) - { - TArray buffer(mReader->Length + padding, true); - Size length = mReader->Read(&buffer[0], mReader->Length); - if (length < mReader->Length) buffer.Clear(); - else memset(buffer.Data() + mReader->Length, 0, padding); - return buffer; - } char *Gets(char *strbuf, Size len) { - return mReader->Gets(strbuf, (int)len); + return mReader->Gets(strbuf, len); } const char *GetBuffer() @@ -243,53 +304,53 @@ class FileReader return v; } + uint16_t ReadUInt16() { uint16_t v = 0; Read(&v, 2); - return LittleShort(v); + return byteswap::LittleShort(v); } int16_t ReadInt16() { - int16_t v = 0; + return (int16_t)ReadUInt16(); + } + + int16_t ReadUInt16BE() + { + uint16_t v = 0; Read(&v, 2); - return LittleShort(v); + return byteswap::BigShort(v); } int16_t ReadInt16BE() { - int16_t v = 0; - Read(&v, 2); - return BigShort(v); + return (int16_t)ReadUInt16BE(); } uint32_t ReadUInt32() { uint32_t v = 0; Read(&v, 4); - return LittleLong(v); + return byteswap::LittleLong(v); } int32_t ReadInt32() { - int32_t v = 0; - Read(&v, 4); - return LittleLong(v); + return (int32_t)ReadUInt32(); } uint32_t ReadUInt32BE() { uint32_t v = 0; Read(&v, 4); - return BigLong(v); + return byteswap::BigLong(v); } int32_t ReadInt32BE() { - int32_t v = 0; - Read(&v, 4); - return BigLong(v); + return (int32_t)ReadUInt32BE(); } uint64_t ReadUInt64() @@ -300,29 +361,14 @@ class FileReader return v; } - - friend class FileSystem; -}; - -class DecompressorBase : public FileReaderInterface -{ - std::function ErrorCallback = nullptr; -public: - // These do not work but need to be defined to satisfy the FileReaderInterface. - // They will just error out when called. - long Tell() const override; - long Seek(long offset, int origin) override; - char* Gets(char* strbuf, int len) override; - void DecompressionError(const char* error, ...) const; - void SetErrorCallback(const std::function& cb) + float ReadFloat() { - ErrorCallback = cb; + float v = 0.0f; + Read(&v, 4); + return v; } - void SetOwnsReader(); -protected: - FileReader* File = nullptr; - FileReader OwnedFile; + friend class FileSystem; }; @@ -344,9 +390,10 @@ class FileWriter static FileWriter *Open(const char *filename); virtual size_t Write(const void *buffer, size_t len); - virtual long Tell(); - virtual long Seek(long offset, int mode); - size_t Printf(const char *fmt, ...) GCCPRINTF(2,3); + virtual ptrdiff_t Tell(); + virtual ptrdiff_t Seek(ptrdiff_t offset, int mode); + size_t Printf(const char *fmt, ...); + virtual void Close() { if (File != NULL) fclose(File); @@ -364,14 +411,15 @@ class FileWriter class BufferWriter : public FileWriter { protected: - TArray mBuffer; + std::vector mBuffer; public: BufferWriter() {} virtual size_t Write(const void *buffer, size_t len) override; - TArray *GetBuffer() { return &mBuffer; } - TArray&& TakeBuffer() { return std::move(mBuffer); } + std::vector *GetBuffer() { return &mBuffer; } + std::vector&& TakeBuffer() { return std::move(mBuffer); } }; +} #endif diff --git a/src/common/filesystem/include/fs_filesystem.h b/src/common/filesystem/include/fs_filesystem.h new file mode 100644 index 0000000000..858b748374 --- /dev/null +++ b/src/common/filesystem/include/fs_filesystem.h @@ -0,0 +1,183 @@ +#pragma once +//----------------------------------------------------------------------------- +// +// DESCRIPTION: +// File system I/O functions. +// +//----------------------------------------------------------------------------- + + + +#include "fs_files.h" +#include "resourcefile.h" + +namespace FileSys { + +union LumpShortName +{ + char String[9]; + + uint32_t dword; // These are for accessing the first 4 or 8 chars of + uint64_t qword; // Name as a unit without breaking strict aliasing rules +}; + + +struct FolderEntry +{ + const char *name; + unsigned lumpnum; +}; + +class FileSystem +{ +public: + FileSystem(); + ~FileSystem (); + + // The wadnum for the IWAD + int GetIwadNum() { return IwadIndex; } + void SetIwadNum(int x) { IwadIndex = x; } + + int GetMaxIwadNum() { return MaxIwadIndex; } + void SetMaxIwadNum(int x) { MaxIwadIndex = x; } + + bool InitSingleFile(const char *filename, FileSystemMessageFunc Printf = nullptr); + bool InitMultipleFiles (std::vector& filenames, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false, FILE* hashfile = nullptr); + void AddFile (const char *filename, FileReader *wadinfo, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile); + int CheckIfResourceFileLoaded (const char *name) noexcept; + void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {} + + const char *GetResourceFileName (int filenum) const noexcept; + const char *GetResourceFileFullName (int wadnum) const noexcept; + + int GetFirstEntry(int wadnum) const noexcept; + int GetLastEntry(int wadnum) const noexcept; + int GetEntryCount(int wadnum) const noexcept; + + int CheckNumForName (const char *name, int namespc) const; + int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true) const; + int GetNumForName (const char *name, int namespc) const; + + inline int CheckNumForName (const uint8_t *name) const { return CheckNumForName ((const char *)name, ns_global); } + inline int CheckNumForName (const char *name) const { return CheckNumForName (name, ns_global); } + inline int CheckNumForName (const uint8_t *name, int ns) const { return CheckNumForName ((const char *)name, ns); } + inline int GetNumForName (const char *name) const { return GetNumForName (name, ns_global); } + inline int GetNumForName (const uint8_t *name) const { return GetNumForName ((const char *)name); } + inline int GetNumForName (const uint8_t *name, int ns) const { return GetNumForName ((const char *)name, ns); } + + int CheckNumForFullName (const char *cname, bool trynormal = false, int namespc = ns_global, bool ignoreext = false) const; + int CheckNumForFullName (const char *name, int wadfile) const; + int GetNumForFullName (const char *name) const; + int FindFile(const char* name) const + { + return CheckNumForFullName(name); + } + + bool FileExists(const char* name) const + { + return FindFile(name) >= 0; + } + + bool FileExists(const std::string& name) const + { + return FindFile(name.c_str()) >= 0; + } + + LumpShortName& GetShortName(int i); // may only be called before the hash chains are set up. + void RenameFile(int num, const char* fn); + bool CreatePathlessCopy(const char* name, int id, int flags); + + void ReadFile (int lump, void *dest); + // These should only be used if the file data really needs padding. + FileData ReadFile (int lump); + FileData ReadFile (const char *name) { return ReadFile (GetNumForName (name)); } + FileData ReadFileFullName(const char* name) { return ReadFile(GetNumForFullName(name)); } + + FileReader OpenFileReader(int lump, int readertype, int readerflags); // opens a reader that redirects to the containing file's one. + FileReader OpenFileReader(const char* name); + FileReader ReopenFileReader(const char* name, bool alwayscache = false); + FileReader OpenFileReader(int lump) + { + return OpenFileReader(lump, READER_SHARED, READERFLAG_SEEKABLE); + } + + FileReader ReopenFileReader(int lump, bool alwayscache = false) + { + return OpenFileReader(lump, alwayscache ? READER_CACHED : READER_NEW, READERFLAG_SEEKABLE); + } + + + int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication + int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names + int FindLumpFullName(const char* name, int* lastlump, bool noext = false); + bool CheckFileName (int lump, const char *name); // [RH] True if lump's name == name + + int FindFileWithExtensions(const char* name, const char* const* exts, int count) const; + int FindResource(int resid, const char* type, int filenum = -1) const noexcept; + int GetResource(int resid, const char* type, int filenum = -1) const; + + + static uint32_t LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name + + ptrdiff_t FileLength (int lump) const; + int GetFileFlags (int lump); // Return the flags for this lump + const char* GetFileShortName(int lump) const; + const char *GetFileFullName (int lump, bool returnshort = true) const; // [RH] Returns the lump's full name + std::string GetFileFullPath (int lump) const; // [RH] Returns wad's name + lump's full name + int GetFileContainer (int lump) const; // [RH] Returns wadnum for a specified lump + int GetFileNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to + void SetFileNamespace(int lump, int ns); + int GetResourceId(int lump) const; // Returns the RFF index number for this lump + const char* GetResourceType(int lump) const; + bool CheckFileName (int lump, const char *name) const; // [RH] Returns true if the names match + unsigned GetFilesInFolder(const char *path, std::vector &result, bool atomic) const; + + int GetNumEntries() const + { + return NumEntries; + } + + int GetNumWads() const + { + return (int)Files.size(); + } + + int AddFromBuffer(const char* name, char* data, int size, int id, int flags); + FileReader* GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD + void InitHashChains(); + +protected: + + struct LumpRecord; + + std::vector Files; + std::vector FileInfo; + + std::vector Hashes; // one allocation for all hash lists. + uint32_t *FirstLumpIndex = nullptr; // [RH] Hashing stuff moved out of lumpinfo structure + uint32_t *NextLumpIndex = nullptr; + + uint32_t *FirstLumpIndex_FullName = nullptr; // The same information for fully qualified paths from .zips + uint32_t *NextLumpIndex_FullName = nullptr; + + uint32_t *FirstLumpIndex_NoExt = nullptr; // The same information for fully qualified paths from .zips + uint32_t *NextLumpIndex_NoExt = nullptr; + + uint32_t* FirstLumpIndex_ResId = nullptr; // The same information for fully qualified paths from .zips + uint32_t* NextLumpIndex_ResId = nullptr; + + uint32_t NumEntries = 0; // Not necessarily the same as FileInfo.Size() + uint32_t NumWads = 0; + + int IwadIndex = -1; + int MaxIwadIndex = -1; + + StringPool* stringpool = nullptr; + +private: + void DeleteAll(); + void MoveLumpsInFolder(const char *); + +}; + +} \ No newline at end of file diff --git a/src/common/filesystem/include/fs_findfile.h b/src/common/filesystem/include/fs_findfile.h new file mode 100644 index 0000000000..d8a18c3741 --- /dev/null +++ b/src/common/filesystem/include/fs_findfile.h @@ -0,0 +1,38 @@ +#pragma once +// Directory searching routines + +#include +#include +#include + +namespace FileSys { + +struct FileListEntry +{ + std::string FileName; // file name only + std::string FilePath; // full path to file + std::string FilePathRel; // path relative to the scanned directory. + size_t Length = 0; + bool isDirectory = false; + bool isReadonly = false; + bool isHidden = false; + bool isSystem = false; +}; + +using FileList = std::vector; + +struct FCompressedBuffer; +bool ScanDirectory(std::vector& list, const char* dirpath, const char* match, bool nosubdir = false, bool readhidden = false); +bool FS_DirEntryExists(const char* pathname, bool* isdir); + +inline void FixPathSeparator(char* path) +{ + while (*path) + { + if (*path == '\\') + *path = '/'; + path++; + } +} + +} diff --git a/src/common/filesystem/include/fs_swap.h b/src/common/filesystem/include/fs_swap.h new file mode 100644 index 0000000000..12b988585f --- /dev/null +++ b/src/common/filesystem/include/fs_swap.h @@ -0,0 +1,122 @@ +// +// DESCRIPTION: +// Endianess handling, swapping 16bit and 32bit. +// +//----------------------------------------------------------------------------- + + +#ifndef __FS_SWAP_H__ +#define __FS_SWAP_H__ + +#include + +// Endianess handling. +// WAD files are stored little endian. + +#ifdef __APPLE__ +#include +#endif + +namespace FileSys { +namespace byteswap { + +#ifdef __APPLE__ + +inline unsigned short LittleShort(unsigned short x) +{ + return OSSwapLittleToHostInt16(x); +} + +inline unsigned int LittleLong(unsigned int x) +{ + return OSSwapLittleToHostInt32(x); +} + +inline unsigned short BigShort(unsigned short x) +{ + return OSSwapBigToHostInt16(x); +} + +inline unsigned int BigLong(unsigned int x) +{ + return OSSwapBigToHostInt32(x); +} + + +#elif defined __BIG_ENDIAN__ + +// Swap 16bit, that is, MSB and LSB byte. +// No masking with 0xFF should be necessary. +inline unsigned short LittleShort (unsigned short x) +{ + return (unsigned short)((x>>8) | (x<<8)); +} + +inline unsigned int LittleLong (unsigned int x) +{ + return (unsigned int)( + (x>>24) + | ((x>>8) & 0xff00) + | ((x<<8) & 0xff0000) + | (x<<24)); +} + +inline unsigned short BigShort(unsigned short x) +{ + return x; +} + +inline unsigned int BigLong(unsigned int x) +{ + return x; +} + +#else + +inline unsigned short LittleShort(unsigned short x) +{ + return x; +} + +inline unsigned int LittleLong(unsigned int x) +{ + return x; +} + +#ifdef _MSC_VER + +inline unsigned short BigShort(unsigned short x) +{ + return _byteswap_ushort(x); +} + +inline unsigned int BigLong(unsigned int x) +{ + return (unsigned int)_byteswap_ulong((unsigned long)x); +} + +#pragma warning (default: 4035) + +#else + +inline unsigned short BigShort (unsigned short x) +{ + return (unsigned short)((x>>8) | (x<<8)); +} + +inline unsigned int BigLong (unsigned int x) +{ + return (unsigned int)( + (x>>24) + | ((x>>8) & 0xff00) + | ((x<<8) & 0xff0000) + | (x<<24)); +} + +#endif + +#endif // __BIG_ENDIAN__ +} +} + +#endif // __M_SWAP_H__ diff --git a/src/common/filesystem/include/resourcefile.h b/src/common/filesystem/include/resourcefile.h new file mode 100644 index 0000000000..a23914444e --- /dev/null +++ b/src/common/filesystem/include/resourcefile.h @@ -0,0 +1,210 @@ + + +#ifndef __RESFILE_H +#define __RESFILE_H + +#include +#include +#include +#include "fs_files.h" +#include "fs_decompress.h" + +namespace FileSys { + +class StringPool; +std::string ExtractBaseName(const char* path, bool include_extension = false); +void strReplace(std::string& str, const char* from, const char* to); + +// user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine. +struct LumpFilterInfo +{ + std::vector gameTypeFilter; // this can contain multiple entries + + // The following are for checking if the root directory of a zip can be removed. + std::vector reservedFolders; + std::vector requiredPrefixes; + std::vector embeddings; + std::vector blockednames; // File names that will never be accepted (e.g. dehacked.exe for Doom) + std::function filenamecheck; // for scanning directories, this allows to eliminate unwanted content. + std::function postprocessFunc; +}; + +enum class FSMessageLevel +{ + Error = 1, + Warning = 2, + Attention = 3, + Message = 4, + DebugWarn = 5, + DebugNotify = 6, +}; + +// pass the text output function as parameter to avoid a hard dependency on higher level code. +using FileSystemMessageFunc = int(*)(FSMessageLevel msglevel, const char* format, ...); + + +class FResourceFile; + +// [RH] Namespaces from BOOM. +// These are needed here in the low level part so that WAD files can be properly set up. +typedef enum { + ns_hidden = -1, + + ns_global = 0, + ns_sprites, + ns_flats, + ns_colormaps, + ns_acslibrary, + ns_newtextures, + ns_bloodraw, // no longer used - kept for ZScript. + ns_bloodsfx, // no longer used - kept for ZScript. + ns_bloodmisc, // no longer used - kept for ZScript. + ns_strifevoices, + ns_hires, + ns_voxels, + + // These namespaces are only used to mark lumps in special subdirectories + // so that their contents doesn't interfere with the global namespace. + // searching for data in these namespaces works differently for lumps coming + // from Zips or other files. + ns_specialzipdirectory, + ns_sounds, + ns_patches, + ns_graphics, + ns_music, + + ns_firstskin, +} namespace_t; + +enum ELumpFlags +{ + RESFF_MAYBEFLAT = 1, // might be a flat inside a WAD outside F_START/END + RESFF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names. + RESFF_EMBEDDED = 4, // marks an embedded resource file for later processing. + RESFF_SHORTNAME = 8, // the stored name is a short extension-less name + RESFF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader. + RESFF_NEEDFILESTART = 32, // The real position is not known yet and needs to be calculated on access +}; + +enum EReaderType +{ + READER_SHARED = 0, // returns a view into the parent's reader. + READER_NEW = 1, // opens a new file handle + READER_CACHED = 2, // returns a MemoryArrayReader + READERFLAG_SEEKABLE = 1 // ensure the reader is seekable. +}; + +struct FResourceEntry +{ + size_t Length; + size_t CompressedSize; + const char* FileName; + size_t Position; + int ResourceID; + uint32_t CRC32; + uint16_t Flags; + uint16_t Method; + int16_t Namespace; +}; + +void SetMainThread(); + +class FResourceFile +{ +public: + FResourceFile(const char* filename, StringPool* sp); + FResourceFile(const char* filename, FileReader& r, StringPool* sp); + const char* NormalizeFileName(const char* fn, int fallbackcp = 0); + FResourceEntry* AllocateEntries(int count); + void GenerateHash(); + void PostProcessArchive(LumpFilterInfo* filter); +protected: + FileReader Reader; + const char* FileName; + FResourceEntry* Entries = nullptr; + uint32_t NumLumps; + char Hash[48]; + StringPool* stringpool; + + // for archives that can contain directories + virtual void SetEntryAddress(uint32_t entry) + { + Entries[entry].Flags &= ~RESFF_NEEDFILESTART; + } + bool IsFileInFolder(const char* const resPath); + void CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi); + +private: + uint32_t FirstLump; + + int FilterLumps(const std::string& filtername, uint32_t max); + bool FindPrefixRange(const char* filter, uint32_t max, uint32_t &start, uint32_t &end); + void JunkLeftoverFilters(uint32_t max); + void FindCommonFolder(LumpFilterInfo* filter); + static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); + +public: + static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + virtual ~FResourceFile(); + // If this FResourceFile represents a directory, the Reader object is not usable so don't return it. + FileReader *GetContainerReader() { return Reader.isOpen()? &Reader : nullptr; } + const char* GetFileName() const { return FileName; } + uint32_t GetFirstEntry() const { return FirstLump; } + void SetFirstLump(uint32_t f) { FirstLump = f; } + const char* GetHash() const { return Hash; } + + int EntryCount() const { return NumLumps; } + int FindEntry(const char* name); + + size_t Length(uint32_t entry) + { + return (entry < NumLumps) ? Entries[entry].Length : 0; + } + size_t Offset(uint32_t entry) + { + return (entry < NumLumps) ? Entries[entry].Position : 0; + } + + // default is the safest reader type. + virtual FileReader GetEntryReader(uint32_t entry, int readertype = READER_NEW, int flags = READERFLAG_SEEKABLE); + + int GetEntryFlags(uint32_t entry) + { + return (entry < NumLumps) ? Entries[entry].Flags : 0; + } + + int GetEntryNamespace(uint32_t entry) + { + return (entry < NumLumps) ? Entries[entry].Namespace : (int)ns_hidden; + } + + int GetEntryResourceID(uint32_t entry) + { + return (entry < NumLumps) ? Entries[entry].ResourceID : -1; + } + + const char* getName(uint32_t entry) + { + return (entry < NumLumps) ? Entries[entry].FileName : nullptr; + } + + virtual FileData Read(uint32_t entry); + + virtual FCompressedBuffer GetRawData(uint32_t entry); + + FileReader Destroy() + { + auto fr = std::move(Reader); + delete this; + return fr; + } + + +}; + + +} + +#endif diff --git a/src/common/filesystem/w_zip.h b/src/common/filesystem/include/w_zip.h similarity index 85% rename from src/common/filesystem/w_zip.h rename to src/common/filesystem/include/w_zip.h index ddc065f07d..50c39519f6 100644 --- a/src/common/filesystem/w_zip.h +++ b/src/common/filesystem/include/w_zip.h @@ -1,8 +1,15 @@ #ifndef __W_ZIP #define __W_ZIP -#include "basics.h" +#if defined(__GNUC__) +#define FORCE_PACKED __attribute__((__packed__)) +#else +#define FORCE_PACKED +#endif + +#include + #pragma pack(1) // FZipCentralInfo struct FZipEndOfCentralDirectory @@ -85,6 +92,15 @@ struct FZipLocalFileHeader #pragma pack() +#ifndef MAKE_ID +#ifndef __BIG_ENDIAN__ +#define MAKE_ID(a,b,c,d) ((uint32_t)((a)|((b)<<8)|((c)<<16)|((d)<<24))) +#else +#define MAKE_ID(a,b,c,d) ((uint32_t)((d)|((c)<<8)|((b)<<16)|((a)<<24))) +#endif +#endif + + #define ZIP_LOCALFILE MAKE_ID('P','K',3,4) #define ZIP_CENTRALFILE MAKE_ID('P','K',1,2) #define ZIP_ENDOFDIR MAKE_ID('P','K',5,6) diff --git a/src/common/filesystem/resourcefile.cpp b/src/common/filesystem/resourcefile.cpp deleted file mode 100644 index 3b8e39915d..0000000000 --- a/src/common/filesystem/resourcefile.cpp +++ /dev/null @@ -1,678 +0,0 @@ -/* -** resourcefile.cpp -** -** Base classes for resource file management -** -**--------------------------------------------------------------------------- -** Copyright 2009 Christoph Oelckers -** 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. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -**--------------------------------------------------------------------------- -** -** -*/ - -#include -#include "resourcefile.h" -#include "cmdlib.h" -#include "md5.h" - - -//========================================================================== -// -// File reader that reads from a lump's cache -// -//========================================================================== - -class FLumpReader : public MemoryReader -{ - FResourceLump *source; - -public: - FLumpReader(FResourceLump *src) - : MemoryReader(NULL, src->LumpSize), source(src) - { - src->Lock(); - bufptr = src->Cache; - } - - ~FLumpReader() - { - source->Unlock(); - } -}; - - -//========================================================================== -// -// Base class for resource lumps -// -//========================================================================== - -FResourceLump::~FResourceLump() -{ - if (Cache != NULL && RefCount >= 0) - { - delete [] Cache; - Cache = NULL; - } - Owner = NULL; -} - - -//========================================================================== -// -// Sets up the lump name information for anything not coming from a WAD file. -// -//========================================================================== - -void FResourceLump::LumpNameSetup(FString iname) -{ - // this causes interference with real Dehacked lumps. - if (!iname.CompareNoCase("dehacked.exe")) - { - iname = ""; - } - - FullName = iname; -} - -//========================================================================== -// -// Checks for embedded resource files -// -//========================================================================== - -static bool IsWadInFolder(const FResourceFile* const archive, const char* const resPath) -{ - // Checks a special case when was put in - // directory inside - - if (NULL == archive) - { - return false; - } - - const FString dirName = ExtractFileBase(archive->FileName); - const FString fileName = ExtractFileBase(resPath, true); - const FString filePath = dirName + '/' + fileName; - - return 0 == filePath.CompareNoCase(resPath); -} - -void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi) -{ - // Checks for embedded archives - const char *c = strstr(FullName, ".wad"); - if (c && strlen(c) == 4 && (!strchr(FullName, '/') || IsWadInFolder(Owner, FullName))) - { - Flags |= LUMPF_EMBEDDED; - } - else if (lfi) for (auto& fstr : lfi->embeddings) - { - if (!stricmp(FullName, fstr)) - { - Flags |= LUMPF_EMBEDDED; - } - } -} - - -//========================================================================== -// -// this is just for completeness. For non-Zips only an uncompressed lump can -// be returned. -// -//========================================================================== - -FCompressedBuffer FResourceLump::GetRawData() -{ - FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)LumpSize, METHOD_STORED, 0, 0, new char[LumpSize] }; - memcpy(cbuf.mBuffer, Lock(), LumpSize); - Unlock(); - cbuf.mCRC32 = crc32(0, (uint8_t*)cbuf.mBuffer, LumpSize); - return cbuf; -} - - -//========================================================================== -// -// Returns the owner's FileReader if it can be used to access this lump -// -//========================================================================== - -FileReader *FResourceLump::GetReader() -{ - return NULL; -} - -//========================================================================== -// -// Returns a file reader to the lump's cache -// -//========================================================================== - -FileReader FResourceLump::NewReader() -{ - return FileReader(new FLumpReader(this)); -} - -//========================================================================== -// -// Caches a lump's content and increases the reference counter -// -//========================================================================== - -void *FResourceLump::Lock() -{ - if (Cache != NULL) - { - if (RefCount > 0) RefCount++; - } - else if (LumpSize > 0) - { - FillCache(); - } - return Cache; -} - -//========================================================================== -// -// Decrements reference counter and frees lump if counter reaches 0 -// -//========================================================================== - -int FResourceLump::Unlock() -{ - if (LumpSize > 0 && RefCount > 0) - { - if (--RefCount == 0) - { - delete [] Cache; - Cache = NULL; - } - } - return RefCount; -} - -//========================================================================== -// -// Opens a resource file -// -//========================================================================== - -typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); - -FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckLump(const char *filename,FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckDir(const char *filename, bool quiet, bool nosub, LumpFilterInfo* filter); - -static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckLump }; - -FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter) -{ - for(size_t i = 0; i < countof(funcs) - containeronly; i++) - { - FResourceFile *resfile = funcs[i](filename, file, quiet, filter); - if (resfile != NULL) return resfile; - } - return NULL; -} - -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter) -{ - return DoOpenResourceFile(filename, file, quiet, containeronly, filter); -} - - -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool quiet, bool containeronly, LumpFilterInfo* filter) -{ - FileReader file; - if (!file.OpenFile(filename)) return nullptr; - return DoOpenResourceFile(filename, file, quiet, containeronly, filter); -} - -FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet, LumpFilterInfo* filter) -{ - return CheckDir(filename, quiet, false, filter); -} - -//========================================================================== -// -// Resource file base class -// -//========================================================================== - -FResourceFile::FResourceFile(const char *filename) - : FileName(filename) -{ -} - -FResourceFile::FResourceFile(const char *filename, FileReader &r) - : FResourceFile(filename) -{ - Reader = std::move(r); -} - -FResourceFile::~FResourceFile() -{ -} - -int lumpcmp(const void * a, const void * b) -{ - FResourceLump * rec1 = (FResourceLump *)a; - FResourceLump * rec2 = (FResourceLump *)b; - return stricmp(rec1->getName(), rec2->getName()); -} - -//========================================================================== -// -// FResourceFile :: GenerateHash -// -// Generates a hash identifier for use in file identification. -// Potential uses are mod-wide compatibility settings or localization add-ons. -// This only hashes the lump directory but not the actual content -// -//========================================================================== - -void FResourceFile::GenerateHash() -{ - // hash the lump directory after sorting - - Hash.Format(("%08X-%04X-"), (unsigned)Reader.GetLength(), NumLumps); - - MD5Context md5; - - uint8_t digest[16]; - for(uint32_t i = 0; i < NumLumps; i++) - { - auto lump = GetLump(i); - md5.Update((const uint8_t*)lump->FullName.GetChars(), (unsigned)lump->FullName.Len() + 1); - md5.Update((const uint8_t*)&lump->LumpSize, 4); - } - md5.Final(digest); - for (auto c : digest) - { - Hash.AppendFormat("%02X", c); - } -} - -//========================================================================== -// -// FResourceFile :: PostProcessArchive -// -// Sorts files by name. -// For files named "filter//*": Using the same filter rules as config -// autoloading, move them to the end and rename them without the "filter/" -// prefix. Filtered files that don't match are deleted. -// -//========================================================================== - -void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter) -{ - // Entries in archives are sorted alphabetically - qsort(lumps, NumLumps, lumpsize, lumpcmp); - if (!filter) return; - - // Filter out lumps using the same names as the Autoload.* sections - // in the ini file use. We reduce the maximum lump concidered after - // each one so that we don't risk refiltering already filtered lumps. - uint32_t max = NumLumps; - max -= FilterLumpsByGameType(filter, lumps, lumpsize, max); - - ptrdiff_t len; - ptrdiff_t lastpos = -1; - FString file; - FString LumpFilter = filter->dotFilter; - while ((len = LumpFilter.IndexOf('.', lastpos+1)) > 0) - { - max -= FilterLumps(LumpFilter.Left(len), lumps, lumpsize, max); - lastpos = len; - } - max -= FilterLumps(LumpFilter, lumps, lumpsize, max); - - JunkLeftoverFilters(lumps, lumpsize, max); -} - -//========================================================================== -// -// FResourceFile :: FilterLumps -// -// Finds any lumps between [0,) that match the pattern -// "filter//*" and moves them to the end of the lump list. -// Returns the number of lumps moved. -// -//========================================================================== - -int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max) -{ - FString filter; - uint32_t start, end; - - if (filtername.IsEmpty()) - { - return 0; - } - filter << "filter/" << filtername << '/'; - - bool found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); - - // Workaround for old Doom filter names. - if (!found && filtername.IndexOf("doom.id.doom") == 0) - { - filter.Substitute("doom.id.doom", "doom.doom"); - found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); - } - - if (found) - { - void *from = (uint8_t *)lumps + start * lumpsize; - - // Remove filter prefix from every name - void *lump_p = from; - for (uint32_t i = start; i < end; ++i, lump_p = (uint8_t *)lump_p + lumpsize) - { - FResourceLump *lump = (FResourceLump *)lump_p; - assert(lump->FullName.CompareNoCase(filter, (int)filter.Len()) == 0); - lump->LumpNameSetup(lump->FullName.Mid(filter.Len())); - } - - // Move filtered lumps to the end of the lump list. - size_t count = (end - start) * lumpsize; - void *to = (uint8_t *)lumps + NumLumps * lumpsize - count; - assert (to >= from); - - if (from != to) - { - // Copy filtered lumps to a temporary buffer. - uint8_t *filteredlumps = new uint8_t[count]; - memcpy(filteredlumps, from, count); - - // Shift lumps left to make room for the filtered ones at the end. - memmove(from, (uint8_t *)from + count, (NumLumps - end) * lumpsize); - - // Copy temporary buffer to newly freed space. - memcpy(to, filteredlumps, count); - - delete[] filteredlumps; - } - } - return end - start; -} - -//========================================================================== -// -// FResourceFile :: FilterLumpsByGameType -// -// Matches any lumps that match "filter/game-/*". Includes -// inclusive gametypes like Raven. -// -//========================================================================== - -int FResourceFile::FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max) -{ - if (filter == nullptr) - { - return 0; - } - int count = 0; - for (auto &fstring : filter->gameTypeFilter) - { - count += FilterLumps(fstring, lumps, lumpsize, max); - } - return count; -} - -//========================================================================== -// -// FResourceFile :: JunkLeftoverFilters -// -// Deletes any lumps beginning with "filter/" that were not matched. -// -//========================================================================== - -void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max) -{ - uint32_t start, end; - if (FindPrefixRange("filter/", lumps, lumpsize, max, start, end)) - { - // Since the resource lumps may contain non-POD data besides the - // full name, we "delete" them by erasing their names so they - // can't be found. - void *stop = (uint8_t *)lumps + end * lumpsize; - for (void *p = (uint8_t *)lumps + start * lumpsize; p < stop; p = (uint8_t *)p + lumpsize) - { - FResourceLump *lump = (FResourceLump *)p; - lump->FullName = ""; - } - } -} - -//========================================================================== -// -// FResourceFile :: FindPrefixRange -// -// Finds a range of lumps that start with the prefix string. is left -// indicating the first matching one. is left at one plus the last -// matching one. -// -//========================================================================== - -bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t maxlump, uint32_t &start, uint32_t &end) -{ - uint32_t min, max, mid, inside; - FResourceLump *lump; - int cmp = 0; - - end = start = 0; - - // Pretend that our range starts at 1 instead of 0 so that we can avoid - // unsigned overflow if the range starts at the first lump. - lumps = (uint8_t *)lumps - lumpsize; - - // Binary search to find any match at all. - mid = min = 1, max = maxlump; - while (min <= max) - { - mid = min + (max - min) / 2; - lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); - cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); - if (cmp == 0) - break; - else if (cmp < 0) - min = mid + 1; - else - max = mid - 1; - } - if (max < min) - { // matched nothing - return false; - } - - // Binary search to find first match. - inside = mid; - min = 1, max = mid; - while (min <= max) - { - mid = min + (max - min) / 2; - lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); - cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); - // Go left on matches and right on misses. - if (cmp == 0) - max = mid - 1; - else - min = mid + 1; - } - start = mid + (cmp != 0) - 1; - - // Binary search to find last match. - min = inside, max = maxlump; - while (min <= max) - { - mid = min + (max - min) / 2; - lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); - cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); - // Go right on matches and left on misses. - if (cmp == 0) - min = mid + 1; - else - max = mid - 1; - } - end = mid - (cmp != 0); - return true; -} - -//========================================================================== -// -// Finds a lump by a given name. Used for savegames -// -//========================================================================== - -FResourceLump *FResourceFile::FindLump(const char *name) -{ - for (unsigned i = 0; i < NumLumps; i++) - { - FResourceLump *lump = GetLump(i); - if (!stricmp(name, lump->FullName)) - { - return lump; - } - } - return nullptr; -} - -//========================================================================== -// -// Caches a lump's content and increases the reference counter -// -//========================================================================== - -FileReader *FUncompressedLump::GetReader() -{ - Owner->Reader.Seek(Position, FileReader::SeekSet); - return &Owner->Reader; -} - -//========================================================================== -// -// Caches a lump's content and increases the reference counter -// -//========================================================================== - -int FUncompressedLump::FillCache() -{ - const char * buffer = Owner->Reader.GetBuffer(); - - if (buffer != NULL) - { - // This is an in-memory file so the cache can point directly to the file's data. - Cache = const_cast(buffer) + Position; - RefCount = -1; - return -1; - } - - Owner->Reader.Seek(Position, FileReader::SeekSet); - Cache = new char[LumpSize]; - Owner->Reader.Read(Cache, LumpSize); - RefCount = 1; - return 1; -} - -//========================================================================== -// -// Base class for uncompressed resource files -// -//========================================================================== - -FUncompressedFile::FUncompressedFile(const char *filename) -: FResourceFile(filename) -{} - -FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r) - : FResourceFile(filename, r) -{} - - -//========================================================================== -// -// external lump -// -//========================================================================== - -FExternalLump::FExternalLump(const char *_filename, int filesize) - : Filename(_filename) -{ - if (filesize == -1) - { - FileReader f; - - if (f.OpenFile(_filename)) - { - LumpSize = (int)f.GetLength(); - } - else - { - LumpSize = 0; - } - } - else - { - LumpSize = filesize; - } -} - - -//========================================================================== -// -// Caches a lump's content and increases the reference counter -// For external lumps this reopens the file each time it is accessed -// -//========================================================================== - -int FExternalLump::FillCache() -{ - Cache = new char[LumpSize]; - FileReader f; - - if (f.OpenFile(Filename)) - { - f.Read(Cache, LumpSize); - } - else - { - memset(Cache, 0, LumpSize); - } - RefCount = 1; - return 1; -} - - - diff --git a/src/common/filesystem/resourcefile.h b/src/common/filesystem/resourcefile.h deleted file mode 100644 index d64c278e8e..0000000000 --- a/src/common/filesystem/resourcefile.h +++ /dev/null @@ -1,226 +0,0 @@ - - -#ifndef __RESFILE_H -#define __RESFILE_H - -#include - -#include "files.h" -#include "zstring.h" - -struct LumpFilterInfo -{ - TArray gameTypeFilter; // this can contain multiple entries - FString dotFilter; - - // The following are for checking if the root directory of a zip can be removed. - TArray reservedFolders; - TArray requiredPrefixes; - TArray embeddings; - std::function postprocessFunc; -}; - -class FResourceFile; - -// [RH] Namespaces from BOOM. -// These are needed here in the low level part so that WAD files can be properly set up. -typedef enum { - ns_hidden = -1, - - ns_global = 0, - ns_sprites, - ns_flats, - ns_colormaps, - ns_acslibrary, - ns_newtextures, - ns_bloodraw, // no longer used - kept for ZScript. - ns_bloodsfx, // no longer used - kept for ZScript. - ns_bloodmisc, // no longer used - kept for ZScript. - ns_strifevoices, - ns_hires, - ns_voxels, - - // These namespaces are only used to mark lumps in special subdirectories - // so that their contents doesn't interfere with the global namespace. - // searching for data in these namespaces works differently for lumps coming - // from Zips or other files. - ns_specialzipdirectory, - ns_sounds, - ns_patches, - ns_graphics, - ns_music, - - ns_firstskin, -} namespace_t; - -enum ELumpFlags -{ - LUMPF_MAYBEFLAT = 1, // might be a flat outside F_START/END - LUMPF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names. - LUMPF_EMBEDDED = 4, // marks an embedded resource file for later processing. - LUMPF_SHORTNAME = 8, // the stored name is a short extension-less name - LUMPF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader. -}; - -// This holds a compresed Zip entry with all needed info to decompress it. -struct FCompressedBuffer -{ - unsigned mSize; - unsigned mCompressedSize; - int mMethod; - int mZipFlags; - unsigned mCRC32; - char *mBuffer; - - bool Decompress(char *destbuffer); - void Clean() - { - mSize = mCompressedSize = 0; - if (mBuffer != nullptr) - { - delete[] mBuffer; - mBuffer = nullptr; - } - } -}; - -struct FResourceLump -{ - friend class FResourceFile; - friend class FWadFile; // this still needs direct access. - - int LumpSize; - int RefCount; -protected: - FString FullName; -public: - uint8_t Flags; - char * Cache; - FResourceFile * Owner; - - FResourceLump() - { - Cache = NULL; - Owner = NULL; - Flags = 0; - RefCount = 0; - } - - virtual ~FResourceLump(); - virtual FileReader *GetReader(); - virtual FileReader NewReader(); - virtual int GetFileOffset() { return -1; } - virtual int GetIndexNum() const { return -1; } - virtual int GetNamespace() const { return 0; } - void LumpNameSetup(FString iname); - void CheckEmbedded(LumpFilterInfo* lfi); - virtual FCompressedBuffer GetRawData(); - - void *Lock(); // validates the cache and increases the refcount. - int Unlock(); // decreases the refcount and frees the buffer - - unsigned Size() const{ return LumpSize; } - int LockCount() const { return RefCount; } - const char* getName() { return FullName.GetChars(); } - -protected: - virtual int FillCache() { return -1; } - -}; - -class FResourceFile -{ -public: - FileReader Reader; - FString FileName; -protected: - uint32_t NumLumps; - FString Hash; - - FResourceFile(const char *filename); - FResourceFile(const char *filename, FileReader &r); - - // for archives that can contain directories - void GenerateHash(); - void PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter); - -private: - uint32_t FirstLump; - - int FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max); - int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max); - bool FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end); - void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max); - static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter); - -public: - static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool quiet = false, bool containeronly = false, LumpFilterInfo* filter = nullptr); - static FResourceFile *OpenResourceFile(const char *filename, bool quiet = false, bool containeronly = false, LumpFilterInfo* filter = nullptr); - static FResourceFile *OpenDirectory(const char *filename, bool quiet = false, LumpFilterInfo* filter = nullptr); - virtual ~FResourceFile(); - // If this FResourceFile represents a directory, the Reader object is not usable so don't return it. - FileReader *GetReader() { return Reader.isOpen()? &Reader : nullptr; } - uint32_t LumpCount() const { return NumLumps; } - uint32_t GetFirstEntry() const { return FirstLump; } - void SetFirstLump(uint32_t f) { FirstLump = f; } - const FString &GetHash() const { return Hash; } - - - virtual FResourceLump *GetLump(int no) = 0; - FResourceLump *FindLump(const char *name); -}; - -struct FUncompressedLump : public FResourceLump -{ - int Position; - - virtual FileReader *GetReader(); - virtual int FillCache(); - virtual int GetFileOffset() { return Position; } - -}; - - -// Base class for uncompressed resource files (WAD, GRP, PAK and single lumps) -class FUncompressedFile : public FResourceFile -{ -protected: - TArray Lumps; - - FUncompressedFile(const char *filename); - FUncompressedFile(const char *filename, FileReader &r); - virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } -}; - - -struct FExternalLump : public FResourceLump -{ - FString Filename; - - FExternalLump(const char *_filename, int filesize = -1); - virtual int FillCache(); - -}; - -struct FMemoryLump : public FResourceLump -{ - FMemoryLump(const void* data, int length) - { - RefCount = INT_MAX / 2; - LumpSize = length; - Cache = new char[length]; - memcpy(Cache, data, length); - } - - virtual int FillCache() override - { - RefCount = INT_MAX / 2; // Make sure it never counts down to 0 by resetting it to something high each time it is used. - return 1; - } -}; - - - - - -#endif diff --git a/src/common/filesystem/ancientzip.cpp b/src/common/filesystem/source/ancientzip.cpp similarity index 91% rename from src/common/filesystem/ancientzip.cpp rename to src/common/filesystem/source/ancientzip.cpp index 0088d1f008..9f5ebdfefe 100644 --- a/src/common/filesystem/ancientzip.cpp +++ b/src/common/filesystem/source/ancientzip.cpp @@ -44,8 +44,12 @@ #include +#include +#include #include "ancientzip.h" +namespace FileSys { + /**************************************************************** Bit-I/O variables and routines/macros @@ -123,7 +127,7 @@ static const unsigned char BitReverse4[] = { #define FIRST_BIT_LEN 8 #define REST_BIT_LEN 4 -void FZipExploder::InsertCode(TArray &decoder, unsigned int pos, int bits, unsigned short code, int len, unsigned char value) +void FZipExploder::InsertCode(std::vector &decoder, unsigned int pos, int bits, unsigned short code, int len, unsigned char value) { assert(len > 0); unsigned int node = pos + (code & ((1 << bits) - 1)); @@ -159,12 +163,12 @@ void FZipExploder::InsertCode(TArray &decoder, unsigned int pos, int b } } -unsigned int FZipExploder::InitTable(TArray &decoder, int numspots) +unsigned int FZipExploder::InitTable(std::vector &decoder, int numspots) { - unsigned int start = decoder.Size(); - decoder.Reserve(numspots); + size_t start = decoder.size(); + decoder.resize(decoder.size() + numspots); memset(&decoder[start], 0, sizeof(HuffNode)*numspots); - return start; + return (unsigned)start; } int FZipExploder::buildercmp(const void *a, const void *b) @@ -178,7 +182,7 @@ int FZipExploder::buildercmp(const void *a, const void *b) return d; } -int FZipExploder::BuildDecoder(TArray &decoder, TableBuilder *values, int numvals) +int FZipExploder::BuildDecoder(std::vector &decoder, TableBuilder *values, int numvals) { int i; @@ -216,7 +220,7 @@ int FZipExploder::BuildDecoder(TArray &decoder, TableBuilder *values, } -int FZipExploder::DecodeSFValue(const TArray &decoder) +int FZipExploder::DecodeSFValue(const std::vector &decoder) { unsigned int bits = FIRST_BIT_LEN, table = 0, code; const HuffNode *pos; @@ -234,7 +238,7 @@ int FZipExploder::DecodeSFValue(const TArray &decoder) } -int FZipExploder::DecodeSF(TArray &decoder, int numvals) +int FZipExploder::DecodeSF(std::vector &decoder, int numvals) { TableBuilder builder[256]; unsigned char a, c; @@ -310,7 +314,7 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize, len += minMatchLen; dist++; if (bIdx + len > outsize) { - throw CExplosionError("Not enough output space"); + return -1; } if ((unsigned int)dist > bIdx) { /* Anything before the first input byte is zero. */ @@ -339,10 +343,19 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize, int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &_In, unsigned int InLeft) { + // don't allocate this on the stack, it's a bit on the large side. + struct work + { + unsigned char ReadBuf[256]; + unsigned short Parent[HSIZE]; + unsigned char Value[HSIZE], Stack[HSIZE]; + }; + auto s = std::make_unique(); + unsigned char* ReadBuf = s->ReadBuf; + unsigned short* Parent = s->Parent; + unsigned char* Value = s->Value, * Stack = s->Stack; + FileReader *In = &_In; - unsigned char ReadBuf[256]; - unsigned short Parent[HSIZE]; - unsigned char Value[HSIZE], Stack[HSIZE]; unsigned char *newstr; int len; int KwKwK, codesize = 9; /* start at 9 bits/code */ @@ -433,3 +446,5 @@ int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &_In, unsign } return 0; } + +} diff --git a/src/common/filesystem/ancientzip.h b/src/common/filesystem/source/ancientzip.h similarity index 52% rename from src/common/filesystem/ancientzip.h rename to src/common/filesystem/source/ancientzip.h index 621505504c..1f8d793fd5 100644 --- a/src/common/filesystem/ancientzip.h +++ b/src/common/filesystem/source/ancientzip.h @@ -1,6 +1,8 @@ -#include "files.h" -#include "engineerrors.h" +#pragma once +#include "fs_files.h" +namespace FileSys { + class FZipExploder { unsigned int Hold, Bits; @@ -25,26 +27,21 @@ class FZipExploder unsigned short Code; }; - TArray LiteralDecoder; - TArray DistanceDecoder; - TArray LengthDecoder; + std::vector LiteralDecoder; + std::vector DistanceDecoder; + std::vector LengthDecoder; unsigned char ReadBuf[256]; unsigned int bs, be; static int buildercmp(const void *a, const void *b); - void InsertCode(TArray &decoder, unsigned int pos, int bits, unsigned short code, int len, unsigned char value); - unsigned int InitTable(TArray &decoder, int numspots); - int BuildDecoder(TArray &decoder, TableBuilder *values, int numvals); - int DecodeSFValue(const TArray ¤tTree); - int DecodeSF(TArray &decoder, int numvals); + void InsertCode(std::vector &decoder, unsigned int pos, int bits, unsigned short code, int len, unsigned char value); + unsigned int InitTable(std::vector &decoder, int numspots); + int BuildDecoder(std::vector &decoder, TableBuilder *values, int numvals); + int DecodeSFValue(const std::vector ¤tTree); + int DecodeSF(std::vector &decoder, int numvals); public: int Explode(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize, int flags); }; -class CExplosionError : public CRecoverableError -{ -public: - CExplosionError(const char *message) : CRecoverableError(message) {} -}; - -int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize); \ No newline at end of file +int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize); +} diff --git a/src/common/filesystem/source/critsec.cpp b/src/common/filesystem/source/critsec.cpp new file mode 100644 index 0000000000..874ade79f9 --- /dev/null +++ b/src/common/filesystem/source/critsec.cpp @@ -0,0 +1,150 @@ +/* +** +** +**--------------------------------------------------------------------------- +** Copyright 2005-2016 Randy Heit +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 FileSys { + +#ifdef _WIN32 + +#ifndef _WINNT_ +#define WIN32_LEAN_AND_MEAN +#include +#endif + +class FInternalCriticalSection +{ +public: + void Enter() + { + AcquireSRWLockExclusive(&CritSec); + } + void Leave() + { + ReleaseSRWLockExclusive(&CritSec); + } +private: + SRWLOCK CritSec = SRWLOCK_INIT; +}; + + +FInternalCriticalSection *CreateCriticalSection() +{ + return new FInternalCriticalSection(); +} + +void DeleteCriticalSection(FInternalCriticalSection *c) +{ + delete c; +} + +void EnterCriticalSection(FInternalCriticalSection *c) +{ + c->Enter(); +} + +void LeaveCriticalSection(FInternalCriticalSection *c) +{ + c->Leave(); +} + +#else + +#include "critsec.h" + +#include + +class FInternalCriticalSection +{ +public: + FInternalCriticalSection(); + ~FInternalCriticalSection(); + + void Enter(); + void Leave(); + +private: + pthread_mutex_t m_mutex; + +}; + +// TODO: add error handling + +FInternalCriticalSection::FInternalCriticalSection() +{ + pthread_mutexattr_t attributes; + pthread_mutexattr_init(&attributes); + pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&m_mutex, &attributes); + + pthread_mutexattr_destroy(&attributes); +} + +FInternalCriticalSection::~FInternalCriticalSection() +{ + pthread_mutex_destroy(&m_mutex); +} + +void FInternalCriticalSection::Enter() +{ + pthread_mutex_lock(&m_mutex); +} + +void FInternalCriticalSection::Leave() +{ + pthread_mutex_unlock(&m_mutex); +} + + +FInternalCriticalSection *CreateCriticalSection() +{ + return new FInternalCriticalSection(); +} + +void DeleteCriticalSection(FInternalCriticalSection *c) +{ + delete c; +} + +void EnterCriticalSection(FInternalCriticalSection *c) +{ + c->Enter(); +} + +void LeaveCriticalSection(FInternalCriticalSection *c) +{ + c->Leave(); +} + +#endif + +} \ No newline at end of file diff --git a/src/common/filesystem/source/critsec.h b/src/common/filesystem/source/critsec.h new file mode 100644 index 0000000000..9ea56aab56 --- /dev/null +++ b/src/common/filesystem/source/critsec.h @@ -0,0 +1,39 @@ +#pragma once + +namespace FileSys { +// System independent critical sections without polluting the namespace with the operating system headers. +class FInternalCriticalSection; +FInternalCriticalSection *CreateCriticalSection(); +void DeleteCriticalSection(FInternalCriticalSection *c); +void EnterCriticalSection(FInternalCriticalSection *c); +void LeaveCriticalSection(FInternalCriticalSection *c); + +// This is just a convenience wrapper around the function interface adjusted to use std::lock_guard +class FCriticalSection +{ +public: + FCriticalSection() + { + c = CreateCriticalSection(); + } + + ~FCriticalSection() + { + DeleteCriticalSection(c); + } + + void lock() + { + EnterCriticalSection(c); + } + + void unlock() + { + LeaveCriticalSection(c); + } + +private: + FInternalCriticalSection *c; + +}; +} \ No newline at end of file diff --git a/src/common/filesystem/file_7z.cpp b/src/common/filesystem/source/file_7z.cpp similarity index 67% rename from src/common/filesystem/file_7z.cpp rename to src/common/filesystem/source/file_7z.cpp index f207702d05..21d6049e37 100644 --- a/src/common/filesystem/file_7z.cpp +++ b/src/common/filesystem/source/file_7z.cpp @@ -36,13 +36,15 @@ // Note that 7z made the unwise decision to include windows.h :( #include "7z.h" #include "7zCrc.h" - #include "resourcefile.h" -#include "cmdlib.h" -#include "printf.h" - +#include "fs_findfile.h" +#include "unicode.h" +#include "critsec.h" +#include +namespace FileSys { + //----------------------------------------------------------------------- // // Interface classes to 7z library @@ -66,7 +68,7 @@ struct CZDFileInStream static SRes Read(const ISeekInStream *pp, void *buf, size_t *size) { CZDFileInStream *p = (CZDFileInStream *)pp; - auto numread = p->File.Read(buf, (long)*size); + auto numread = p->File.Read(buf, (ptrdiff_t)*size); if (numread < 0) { *size = 0; @@ -97,7 +99,7 @@ struct CZDFileInStream { return 1; } - res = (int)p->File.Seek((long)*pos, move_method); + res = (int)p->File.Seek((ptrdiff_t)*pos, move_method); *pos = p->File.Tell(); return res; } @@ -122,7 +124,7 @@ struct C7zArchive file.Seek(0, FileReader::SeekSet); LookToRead2_CreateVTable(&LookStream, false); LookStream.realStream = &ArchiveStream.s; - LookToRead2_Init(&LookStream); + LookToRead2_INIT(&LookStream); LookStream.bufSize = sizeof(StreamBuffer); LookStream.buf = StreamBuffer; SzArEx_Init(&DB); @@ -159,20 +161,6 @@ struct C7zArchive return res; } }; -//========================================================================== -// -// Zip Lump -// -//========================================================================== - -struct F7ZLump : public FResourceLump -{ - int Position; - - virtual int FillCache(); - -}; - //========================================================================== // @@ -184,14 +172,15 @@ class F7ZFile : public FResourceFile { friend struct F7ZLump; - F7ZLump *Lumps; C7zArchive *Archive; + FCriticalSection critsec; public: - F7ZFile(const char * filename, FileReader &filer); - bool Open(bool quiet, LumpFilterInfo* filter); + F7ZFile(const char * filename, FileReader &filer, StringPool* sp); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); virtual ~F7ZFile(); - virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } + FileData Read(uint32_t entry) override; + FileReader GetEntryReader(uint32_t entry, int, int) override; }; @@ -202,11 +191,10 @@ class F7ZFile : public FResourceFile // //========================================================================== -F7ZFile::F7ZFile(const char * filename, FileReader &filer) - : FResourceFile(filename, filer) +F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp) + : FResourceFile(filename, filer, sp) { - Lumps = NULL; - Archive = NULL; + Archive = nullptr; } @@ -216,7 +204,7 @@ F7ZFile::F7ZFile(const char * filename, FileReader &filer) // //========================================================================== -bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) +bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf) { Archive = new C7zArchive(Reader); int skipped = 0; @@ -227,44 +215,39 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) { delete Archive; Archive = NULL; - if (!quiet) + if (res == SZ_ERROR_UNSUPPORTED) + { + Printf(FSMessageLevel::Error, "%s: Decoder does not support this archive\n", FileName); + } + else if (res == SZ_ERROR_MEM) + { + Printf(FSMessageLevel::Error, "Cannot allocate memory\n"); + } + else if (res == SZ_ERROR_CRC) + { + Printf(FSMessageLevel::Error, "CRC error\n"); + } + else { - Printf("\n" TEXTCOLOR_RED "%s: ", FileName.GetChars()); - if (res == SZ_ERROR_UNSUPPORTED) - { - Printf("Decoder does not support this archive\n"); - } - else if (res == SZ_ERROR_MEM) - { - Printf("Cannot allocate memory\n"); - } - else if (res == SZ_ERROR_CRC) - { - Printf("CRC error\n"); - } - else - { - Printf("error #%d\n", res); - } + Printf(FSMessageLevel::Error, "error #%d\n", res); } return false; } CSzArEx* const archPtr = &Archive->DB; + AllocateEntries(archPtr->NumFiles); NumLumps = archPtr->NumFiles; - Lumps = new F7ZLump[NumLumps]; - F7ZLump *lump_p = Lumps; - TArray nameUTF16; - TArray nameASCII; + std::u16string nameUTF16; + std::vector nameASCII; + uint32_t j = 0; for (uint32_t i = 0; i < NumLumps; ++i) { // skip Directories if (SzArEx_IsDir(archPtr, i)) { - skipped++; continue; } @@ -272,49 +255,42 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) if (0 == nameLength) { - ++skipped; continue; } - nameUTF16.Resize((unsigned)nameLength); - nameASCII.Resize((unsigned)nameLength); - SzArEx_GetFileNameUtf16(archPtr, i, &nameUTF16[0]); - for (size_t c = 0; c < nameLength; ++c) - { - nameASCII[c] = static_cast(nameUTF16[c]); - } - FixPathSeperator(&nameASCII[0]); - - FString name = &nameASCII[0]; - name.ToLower(); - - lump_p->LumpNameSetup(name); - lump_p->LumpSize = static_cast(SzArEx_GetFileSize(archPtr, i)); - lump_p->Owner = this; - lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED; - lump_p->Position = i; - lump_p->CheckEmbedded(filter); - lump_p++; + nameUTF16.resize((unsigned)nameLength); + nameASCII.resize((unsigned)nameLength); + + SzArEx_GetFileNameUtf16(archPtr, i, (UInt16*)nameUTF16.data()); + utf16_to_utf8((uint16_t*)nameUTF16.data(), nameASCII); + + Entries[j].FileName = NormalizeFileName(nameASCII.data()); + Entries[j].Length = SzArEx_GetFileSize(archPtr, i); + Entries[j].Flags = RESFF_FULLPATH|RESFF_COMPRESSED; + Entries[j].ResourceID = -1; + Entries[j].Namespace = ns_global; + Entries[j].Method = METHOD_INVALID; + Entries[j].Position = i; + j++; } // Resize the lump record array to its actual size - NumLumps -= skipped; + NumLumps = j; if (NumLumps > 0) { // Quick check for unsupported compression method - TArray temp; - temp.Resize(Lumps[0].LumpSize); + FileData temp(nullptr, Entries[0].Length); - if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0])) + if (SZ_OK != Archive->Extract((UInt32)Entries[0].Position, (char*)temp.writable())) { - if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: unsupported 7z/LZMA file!\n", FileName); return false; } } GenerateHash(); - PostProcessArchive(&Lumps[0], sizeof(F7ZLump), filter); + PostProcessArchive(filter); return true; } @@ -326,37 +302,56 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) F7ZFile::~F7ZFile() { - if (Lumps != NULL) + if (Archive != nullptr) { - delete[] Lumps; + delete Archive; } - if (Archive != NULL) +} + +//========================================================================== +// +// Reads data for one entry into a buffer +// +//========================================================================== + +FileData F7ZFile::Read(uint32_t entry) +{ + FileData buffer; + if (entry < NumLumps && Entries[entry].Length > 0) { - delete Archive; + auto p = buffer.allocate(Entries[entry].Length); + // There is no realistic way to keep multiple references to a 7z file open without massive overhead so to make this thread-safe a mutex is the only option. + std::lock_guard lock(critsec); + SRes code = Archive->Extract((UInt32)Entries[entry].Position, (char*)p); + if (code != SZ_OK) buffer.clear(); } + return buffer; } //========================================================================== // -// Fills the lump cache and performs decompression +// This can only return a FileReader to a memory buffer. // //========================================================================== -int F7ZLump::FillCache() +FileReader F7ZFile::GetEntryReader(uint32_t entry, int, int) { - Cache = new char[LumpSize]; - static_cast(Owner)->Archive->Extract(Position, Cache); - RefCount = 1; - return 1; + FileReader fr; + if (entry < 0 || entry >= NumLumps) return fr; + auto buffer = Read(entry); + if (buffer.size() > 0) + fr.OpenMemoryArray(buffer); + return fr; } + //========================================================================== // // File open // //========================================================================== -FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[k7zSignatureSize]; @@ -367,15 +362,14 @@ FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpF file.Seek(0, FileReader::SeekSet); if (!memcmp(head, k7zSignature, k7zSignatureSize)) { - auto rf = new F7ZFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + auto rf = new F7ZFile(filename, file, sp); + if (rf->Open(filter, Printf)) return rf; - file = std::move(rf->Reader); // to avoid destruction of reader - delete rf; + file = rf->Destroy(); } } return NULL; } - +} diff --git a/src/common/filesystem/source/file_directory.cpp b/src/common/filesystem/source/file_directory.cpp new file mode 100644 index 0000000000..3193e00b12 --- /dev/null +++ b/src/common/filesystem/source/file_directory.cpp @@ -0,0 +1,204 @@ +/* +** file_directory.cpp +** +**--------------------------------------------------------------------------- +** Copyright 2008-2009 Randy Heit +** Copyright 2009 Christoph Oelckers +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +** +*/ + + +#include + +#include "resourcefile.h" +#include "fs_findfile.h" +#include "fs_stringpool.h" + +namespace FileSys { + +std::string FS_FullPath(const char* directory); + +//========================================================================== +// +// Zip file +// +//========================================================================== + +class FDirectory : public FResourceFile +{ + const bool nosubdir; + const char* mBasePath; + const char** SystemFilePath; + + + int AddDirectory(const char* dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf); + +public: + FDirectory(const char * dirname, StringPool* sp, bool nosubdirflag = false); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); + FileReader GetEntryReader(uint32_t entry, int, int) override; +}; + + + +//========================================================================== +// +// +// +//========================================================================== + +FDirectory::FDirectory(const char * directory, StringPool* sp, bool nosubdirflag) + : FResourceFile("", sp), nosubdir(nosubdirflag) +{ + auto fn = FS_FullPath(directory); + if (fn.back() != '/') fn += '/'; + FileName = stringpool->Strdup(fn.c_str()); +} + +//========================================================================== +// +// Windows version +// +//========================================================================== + +int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf) +{ + int count = 0; + + FileList list; + if (!ScanDirectory(list, dirpath, "*")) + { + Printf(FSMessageLevel::Error, "Could not scan '%s': %s\n", dirpath, strerror(errno)); + } + else + { + mBasePath = nullptr; + AllocateEntries((int)list.size()); + SystemFilePath = (const char**)stringpool->Alloc(list.size() * sizeof(const char*)); + for(auto& entry : list) + { + if (mBasePath == nullptr) + { + // extract the base path from the first entry to cover changes made in ScanDirectory. + auto full = entry.FilePath.find(entry.FilePathRel); + std::string path(entry.FilePath, 0, full); + mBasePath = stringpool->Strdup(path.c_str()); + } + if (!entry.isDirectory) + { + auto fi = entry.FileName; + for (auto& c : fi) c = tolower(c); + if (strstr(fi.c_str(), ".orig") || strstr(fi.c_str(), ".bak") || strstr(fi.c_str(), ".cache")) + { + // We shouldn't add backup files to the file system + continue; + } + + + if (filter == nullptr || filter->filenamecheck == nullptr || filter->filenamecheck(fi.c_str(), entry.FilePath.c_str())) + { + if (entry.Length > 0x7fffffff) + { + Printf(FSMessageLevel::Warning, "%s is larger than 2GB and will be ignored\n", entry.FilePath.c_str()); + continue; + } + // for accessing the file we need to retain the original unaltered path. + // On Linux this is important because its file system is case sensitive, + // but even on Windows the Unicode normalization is destructive + // for some characters and cannot be used for file names. + // Examples for this are the Turkish 'i's or the German scharfes s. + SystemFilePath[count] = stringpool->Strdup(entry.FilePathRel.c_str()); + // for internal access we use the normalized form of the relative path. + // this is fine because the paths that get compared against this will also be normalized. + Entries[count].FileName = NormalizeFileName(entry.FilePathRel.c_str()); + Entries[count].CompressedSize = Entries[count].Length = entry.Length; + Entries[count].Flags = RESFF_FULLPATH; + Entries[count].ResourceID = -1; + Entries[count].Method = METHOD_STORED; + Entries[count].Namespace = ns_global; + Entries[count].Position = count; + count++; + } + } + } + } + return count; +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) +{ + NumLumps = AddDirectory(FileName, filter, Printf); + PostProcessArchive(filter); + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +FileReader FDirectory::GetEntryReader(uint32_t entry, int readertype, int) +{ + FileReader fr; + if (entry < NumLumps) + { + std::string fn = mBasePath; + fn += SystemFilePath[Entries[entry].Position]; + fr.OpenFile(fn.c_str()); + if (readertype == READER_CACHED) + { + auto data = fr.Read(); + fr.OpenMemoryArray(data); + } + } + return fr; +} + +//========================================================================== +// +// File open +// +//========================================================================== + +FResourceFile *CheckDir(const char *filename, bool nosubdirflag, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + auto rf = new FDirectory(filename, sp, nosubdirflag); + if (rf->Open(filter, Printf)) return rf; + delete rf; + return nullptr; +} + +} diff --git a/src/common/filesystem/file_grp.cpp b/src/common/filesystem/source/file_grp.cpp similarity index 70% rename from src/common/filesystem/file_grp.cpp rename to src/common/filesystem/source/file_grp.cpp index 7128c1307c..57206b4b10 100644 --- a/src/common/filesystem/file_grp.cpp +++ b/src/common/filesystem/source/file_grp.cpp @@ -34,7 +34,10 @@ */ #include "resourcefile.h" -#include "printf.h" +#include "fs_swap.h" + +namespace FileSys { + using namespace byteswap; //========================================================================== // @@ -62,62 +65,39 @@ struct GrpLump }; -//========================================================================== -// -// Build GRP file -// -//========================================================================== - -class FGrpFile : public FUncompressedFile -{ -public: - FGrpFile(const char * filename, FileReader &file); - bool Open(bool quiet, LumpFilterInfo* filter); -}; - - -//========================================================================== -// -// Initializes a Build GRP file -// -//========================================================================== - -FGrpFile::FGrpFile(const char *filename, FileReader &file) -: FUncompressedFile(filename, file) -{ -} - //========================================================================== // // Open it // //========================================================================== -bool FGrpFile::Open(bool quiet, LumpFilterInfo*) +static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter) { GrpHeader header; - Reader.Read(&header, sizeof(header)); - NumLumps = LittleLong(header.NumLumps); + auto Reader = file->GetContainerReader(); + Reader->Read(&header, sizeof(header)); + uint32_t NumLumps = LittleLong(header.NumLumps); + auto Entries = file->AllocateEntries(NumLumps); GrpLump *fileinfo = new GrpLump[NumLumps]; - Reader.Read (fileinfo, NumLumps * sizeof(GrpLump)); - - Lumps.Resize(NumLumps); + Reader->Read (fileinfo, NumLumps * sizeof(GrpLump)); int Position = sizeof(GrpHeader) + NumLumps * sizeof(GrpLump); for(uint32_t i = 0; i < NumLumps; i++) { - Lumps[i].Owner = this; - Lumps[i].Position = Position; - Lumps[i].LumpSize = LittleLong(fileinfo[i].Size); + Entries[i].Position = Position; + Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].Size); Position += fileinfo[i].Size; - Lumps[i].Flags = 0; + Entries[i].Flags = 0; + Entries[i].Namespace = ns_global; fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated - Lumps[i].LumpNameSetup(fileinfo[i].NameWithZero); + Entries[i].ResourceID = -1; + Entries[i].Method = METHOD_STORED; + Entries[i].FileName = file->NormalizeFileName(fileinfo[i].Name); } - GenerateHash(); + file->GenerateHash(); delete[] fileinfo; return true; } @@ -129,7 +109,7 @@ bool FGrpFile::Open(bool quiet, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[12]; @@ -140,13 +120,12 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, Lump file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "KenSilverman", 12)) { - auto rf = new FGrpFile(filename, file); - if (rf->Open(quiet, filter)) return rf; - - file = std::move(rf->Reader); // to avoid destruction of reader - delete rf; + auto rf = new FResourceFile(filename, file, sp); + if (OpenGrp(rf, filter)) return rf; + file = rf->Destroy(); } } - return NULL; + return nullptr; } +} diff --git a/src/common/filesystem/source/file_hog.cpp b/src/common/filesystem/source/file_hog.cpp new file mode 100644 index 0000000000..d12f7e2d86 --- /dev/null +++ b/src/common/filesystem/source/file_hog.cpp @@ -0,0 +1,109 @@ +/* +** file_hog.cpp +** +** reads Descent .hog files +** +**--------------------------------------------------------------------------- +** Copyright 2023 Christoph Oelckers +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +** +*/ + + +#include "resourcefile.h" +#include "fs_swap.h" + +namespace FileSys { + using namespace byteswap; + + + + +static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter) +{ + auto Reader = rf->GetContainerReader(); + FileReader::Size length = Reader->GetLength(); + + std::vector entries; + // Hogs store their data as a list of file records, each containing a name, length and the actual data. + // To read the directory the entire file must be scanned. + while (Reader->Tell() <= length) + { + char name[13]; + + auto r = Reader->Read(&name, 13); + if (r < 13) break; + name[12] = 0; + uint32_t elength = Reader->ReadUInt32(); + + FResourceEntry Entry; + Entry.Position = Reader->Tell(); + Entry.CompressedSize = Entry.Length = elength; + Entry.Flags = 0; + Entry.CRC32 = 0; + Entry.Namespace = ns_global; + Entry.ResourceID = -1; + Entry.Method = METHOD_STORED; + Entry.FileName = rf->NormalizeFileName(name); + entries.push_back(Entry); + Reader->Seek(elength, FileReader::SeekCur); + } + auto Entries = rf->AllocateEntries((int)entries.size()); + memcpy(Entries, entries.data(), entries.size() * sizeof(Entries[0])); + rf->GenerateHash(); + return true; +} + + +//========================================================================== +// +// File open +// +//========================================================================== + +FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + char head[3]; + + if (file.GetLength() >= 20) + { + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 3); + if (!memcmp(head, "DHF", 3)) + { + auto rf = new FResourceFile(filename, file, sp); + if (OpenHog(rf, filter)) return rf; + file = rf->Destroy(); + } + file.Seek(0, FileReader::SeekSet); + } + return nullptr; +} + + +} \ No newline at end of file diff --git a/src/common/filesystem/file_lump.cpp b/src/common/filesystem/source/file_lump.cpp similarity index 64% rename from src/common/filesystem/file_lump.cpp rename to src/common/filesystem/source/file_lump.cpp index abeb9cf71d..b01d46b5d3 100644 --- a/src/common/filesystem/file_lump.cpp +++ b/src/common/filesystem/source/file_lump.cpp @@ -33,55 +33,24 @@ */ #include "resourcefile.h" -#include "cmdlib.h" -#include "printf.h" - -//========================================================================== -// -// Single lump -// -//========================================================================== - -class FLumpFile : public FUncompressedFile -{ -public: - FLumpFile(const char * filename, FileReader &file); - bool Open(bool quiet, LumpFilterInfo* filter); -}; - - -//========================================================================== -// -// FLumpFile::FLumpFile -// -//========================================================================== - -FLumpFile::FLumpFile(const char *filename, FileReader &file) - : FUncompressedFile(filename, file) -{ -} +namespace FileSys { //========================================================================== // // Open it // //========================================================================== -bool FLumpFile::Open(bool quiet, LumpFilterInfo*) +static bool OpenLump(FResourceFile* file, LumpFilterInfo*) { - FString name(ExtractFileBase(FileName, true)); - - Lumps.Resize(1); - Lumps[0].LumpNameSetup(name); - Lumps[0].Owner = this; - Lumps[0].Position = 0; - Lumps[0].LumpSize = (int)Reader.GetLength(); - Lumps[0].Flags = 0; - NumLumps = 1; - if (!quiet) - { - Printf("\n"); - } + auto Entries = file->AllocateEntries(1); + Entries[0].FileName = file->NormalizeFileName(ExtractBaseName(file->GetFileName(), true).c_str()); + Entries[0].Namespace = ns_global; + Entries[0].ResourceID = -1; + Entries[0].Position = 0; + Entries[0].CompressedSize = Entries[0].Length = file->GetContainerReader()->GetLength(); + Entries[0].Method = METHOD_STORED; + Entries[0].Flags = 0; return true; } @@ -91,13 +60,13 @@ bool FLumpFile::Open(bool quiet, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckLump(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { // always succeeds - auto rf = new FLumpFile(filename, file); - if (rf->Open(quiet, filter)) return rf; - file = std::move(rf->Reader); // to avoid destruction of reader - delete rf; + auto rf = new FResourceFile(filename, file, sp); + if (OpenLump(rf, filter)) return rf; + file = rf->Destroy(); return NULL; } +} diff --git a/src/common/filesystem/source/file_mvl.cpp b/src/common/filesystem/source/file_mvl.cpp new file mode 100644 index 0000000000..f08db31618 --- /dev/null +++ b/src/common/filesystem/source/file_mvl.cpp @@ -0,0 +1,98 @@ +/* +** file_mvl.cpp +** +** reads Descent2 .mvl files +** +**--------------------------------------------------------------------------- +** Copyright 2023 Christoph Oelckers +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +** +*/ + + +#include "resourcefile.h" +#include "fs_swap.h" + +namespace FileSys { + using namespace byteswap; + + + +static bool OpenMvl(FResourceFile* rf, LumpFilterInfo* filter) +{ + auto Reader = rf->GetContainerReader(); + auto count = Reader->ReadUInt32(); + auto Entries = rf->AllocateEntries(count); + size_t pos = 8 + (17 * count); // files start after the directory + + for (uint32_t i = 0; i < count; i++) + { + char name[13]; + Reader->Read(&name, 13); + name[12] = 0; + uint32_t elength = Reader->ReadUInt32(); + + Entries[i].Position = pos; + Entries[i].CompressedSize = Entries[i].Length = elength; + Entries[i].ResourceID = -1; + Entries[i].FileName = rf->NormalizeFileName(name); + + pos += elength; + } + + return true; +} + + +//========================================================================== +// +// File open +// +//========================================================================== + +FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + char head[4]; + + if (file.GetLength() >= 20) + { + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 4); + if (!memcmp(head, "DMVL", 4)) + { + auto rf = new FResourceFile(filename, file, sp); + if (OpenMvl(rf, filter)) return rf; + file = rf->Destroy(); + } + file.Seek(0, FileReader::SeekSet); + } + return nullptr; +} + + +} \ No newline at end of file diff --git a/src/common/filesystem/file_pak.cpp b/src/common/filesystem/source/file_pak.cpp similarity index 62% rename from src/common/filesystem/file_pak.cpp rename to src/common/filesystem/source/file_pak.cpp index 3a868766ce..b66a0f3d99 100644 --- a/src/common/filesystem/file_pak.cpp +++ b/src/common/filesystem/source/file_pak.cpp @@ -33,8 +33,10 @@ */ #include "resourcefile.h" -#include "printf.h" +namespace FileSys { + + using namespace byteswap; //========================================================================== // // @@ -44,75 +46,49 @@ struct dpackfile_t { char name[56]; - int filepos, filelen; + uint32_t filepos, filelen; } ; struct dpackheader_t { - int ident; // == IDPAKHEADER - int dirofs; - int dirlen; + uint32_t ident; // == IDPAKHEADER + uint32_t dirofs; + uint32_t dirlen; } ; -//========================================================================== -// -// Wad file -// -//========================================================================== - -class FPakFile : public FUncompressedFile -{ -public: - FPakFile(const char * filename, FileReader &file); - bool Open(bool quiet, LumpFilterInfo* filter); -}; - - -//========================================================================== -// -// FWadFile::FWadFile -// -// Initializes a WAD file -// -//========================================================================== - -FPakFile::FPakFile(const char *filename, FileReader &file) - : FUncompressedFile(filename, file) -{ -} - //========================================================================== // // Open it // //========================================================================== -bool FPakFile::Open(bool quiet, LumpFilterInfo* filter) +static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter) { dpackheader_t header; - Reader.Read(&header, sizeof(header)); - NumLumps = LittleLong(header.dirlen) / sizeof(dpackfile_t); + auto Reader = file->GetContainerReader(); + Reader->Read(&header, sizeof(header)); + uint32_t NumLumps = header.dirlen / sizeof(dpackfile_t); + auto Entries = file->AllocateEntries(NumLumps); header.dirofs = LittleLong(header.dirofs); - TArray fileinfo(NumLumps, true); - Reader.Seek (header.dirofs, FileReader::SeekSet); - Reader.Read (fileinfo.Data(), NumLumps * sizeof(dpackfile_t)); - - Lumps.Resize(NumLumps); + Reader->Seek (header.dirofs, FileReader::SeekSet); + auto fd = Reader->Read (NumLumps * sizeof(dpackfile_t)); + auto fileinfo = (const dpackfile_t*)fd.data(); for(uint32_t i = 0; i < NumLumps; i++) { - Lumps[i].LumpNameSetup(fileinfo[i].name); - Lumps[i].Flags = LUMPF_FULLPATH; - Lumps[i].Owner = this; - Lumps[i].Position = LittleLong(fileinfo[i].filepos); - Lumps[i].LumpSize = LittleLong(fileinfo[i].filelen); - Lumps[i].CheckEmbedded(filter); + Entries[i].Position = LittleLong(fileinfo[i].filepos); + Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].filelen); + Entries[i].Flags = RESFF_FULLPATH; + Entries[i].Namespace = ns_global; + Entries[i].ResourceID = -1; + Entries[i].Method = METHOD_STORED; + Entries[i].FileName = file->NormalizeFileName(fileinfo[i].name); } - GenerateHash(); - PostProcessArchive(&Lumps[0], sizeof(Lumps[0]), filter); + file->GenerateHash(); + file->PostProcessArchive(filter); return true; } @@ -123,7 +99,7 @@ bool FPakFile::Open(bool quiet, LumpFilterInfo* filter) // //========================================================================== -FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -134,13 +110,12 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, Lump file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "PACK", 4)) { - auto rf = new FPakFile(filename, file); - if (rf->Open(quiet, filter)) return rf; - - file = std::move(rf->Reader); // to avoid destruction of reader - delete rf; + auto rf = new FResourceFile(filename, file, sp); + if (OpenPak(rf, filter)) return rf; + file = rf->Destroy(); } } return NULL; } +} diff --git a/src/common/filesystem/file_rff.cpp b/src/common/filesystem/source/file_rff.cpp similarity index 55% rename from src/common/filesystem/file_rff.cpp rename to src/common/filesystem/source/file_rff.cpp index 3e512b62da..673a08ce06 100644 --- a/src/common/filesystem/file_rff.cpp +++ b/src/common/filesystem/source/file_rff.cpp @@ -33,9 +33,12 @@ ** */ +#include #include "resourcefile.h" +#include "fs_swap.h" -#include "printf.h" +namespace FileSys { + using namespace byteswap; //========================================================================== // @@ -65,22 +68,6 @@ struct RFFLump uint32_t IndexNum; // Used by .sfx, possibly others }; -//========================================================================== -// -// Blood RFF lump (uncompressed lump with encryption) -// -//========================================================================== - -struct FRFFLump : public FUncompressedLump -{ - virtual FileReader *GetReader(); - virtual int FillCache(); - - uint32_t IndexNum; - - int GetIndexNum() const { return IndexNum; } -}; - //========================================================================== // // BloodCrypt @@ -98,68 +85,47 @@ void BloodCrypt (void *data, int key, int len) } -//========================================================================== -// -// Blood RFF file -// -//========================================================================== - -class FRFFFile : public FResourceFile -{ - FRFFLump *Lumps; - -public: - FRFFFile(const char * filename, FileReader &file); - virtual ~FRFFFile(); - virtual bool Open(bool quiet, LumpFilterInfo* filter); - virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } -}; - - //========================================================================== // // Initializes a Blood RFF file // //========================================================================== -FRFFFile::FRFFFile(const char *filename, FileReader &file) -: FResourceFile(filename, file) -{ - Lumps = NULL; -} - -//========================================================================== -// -// Initializes a Blood RFF file -// -//========================================================================== - -bool FRFFFile::Open(bool quiet, LumpFilterInfo*) +static bool OpenRFF(FResourceFile* file, LumpFilterInfo*) { RFFLump *lumps; RFFInfo header; - Reader.Read(&header, sizeof(header)); + auto Reader = file->GetContainerReader(); + Reader->Read(&header, sizeof(header)); - NumLumps = LittleLong(header.NumLumps); + uint32_t NumLumps = LittleLong(header.NumLumps); + auto Entries = file->AllocateEntries(NumLumps); header.DirOfs = LittleLong(header.DirOfs); lumps = new RFFLump[header.NumLumps]; - Reader.Seek (header.DirOfs, FileReader::SeekSet); - Reader.Read (lumps, header.NumLumps * sizeof(RFFLump)); - BloodCrypt (lumps, header.DirOfs, header.NumLumps * sizeof(RFFLump)); - - Lumps = new FRFFLump[NumLumps]; + Reader->Seek (LittleLong(header.DirOfs), FileReader::SeekSet); + Reader->Read (lumps, NumLumps * sizeof(RFFLump)); + BloodCrypt (lumps, LittleLong(header.DirOfs), NumLumps * sizeof(RFFLump)); for (uint32_t i = 0; i < NumLumps; ++i) { - Lumps[i].Position = LittleLong(lumps[i].FilePos); - Lumps[i].LumpSize = LittleLong(lumps[i].Size); - Lumps[i].Owner = this; + Entries[i].Position = LittleLong(lumps[i].FilePos); + Entries[i].CompressedSize = Entries[i].Length = LittleLong(lumps[i].Size); + Entries[i].Flags = 0; + Entries[i].Method = METHOD_STORED; if (lumps[i].Flags & 0x10) { - Lumps[i].Flags |= LUMPF_COMPRESSED; // flags the lump as not directly usable + Entries[i].Flags = RESFF_COMPRESSED; // for purposes of decoding, compression and encryption are equivalent. + Entries[i].Method = METHOD_RFFCRYPT; } - Lumps[i].IndexNum = LittleLong(lumps[i].IndexNum); + else + { + Entries[i].Flags = 0; + Entries[i].Method = METHOD_STORED; + } + Entries[i].Namespace = ns_global; + Entries[i].ResourceID = LittleLong(lumps[i].IndexNum); + // Rearrange the name and extension to construct the fullname. char name[13]; strncpy(name, lumps[i].Name, 8); @@ -171,73 +137,20 @@ bool FRFFFile::Open(bool quiet, LumpFilterInfo*) name[len+2] = lumps[i].Extension[1]; name[len+3] = lumps[i].Extension[2]; name[len+4] = 0; - Lumps[i].LumpNameSetup(name); + Entries[i].FileName = file->NormalizeFileName(name); } delete[] lumps; - GenerateHash(); + file->GenerateHash(); return true; } -FRFFFile::~FRFFFile() -{ - if (Lumps != NULL) - { - delete[] Lumps; - } -} - - -//========================================================================== -// -// Get reader (only returns non-NULL if not encrypted) -// -//========================================================================== - -FileReader *FRFFLump::GetReader() -{ - // Don't return the reader if this lump is encrypted - // In that case always force caching of the lump - if (!(Flags & LUMPF_COMPRESSED)) - { - return FUncompressedLump::GetReader(); - } - else - { - return NULL; - } -} - -//========================================================================== -// -// Fills the lump cache and performs decryption -// -//========================================================================== - -int FRFFLump::FillCache() -{ - int res = FUncompressedLump::FillCache(); - - if (Flags & LUMPF_COMPRESSED) - { - int cryptlen = min (LumpSize, 256); - uint8_t *data = (uint8_t *)Cache; - - for (int i = 0; i < cryptlen; ++i) - { - data[i] ^= i >> 1; - } - } - return res; -} - - //========================================================================== // // File open // //========================================================================== -FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -248,15 +161,13 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, Lump file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "RFF\x1a", 4)) { - auto rf = new FRFFFile(filename, file); - if (rf->Open(quiet, filter)) return rf; - - file = std::move(rf->Reader); // to avoid destruction of reader - delete rf; + auto rf = new FResourceFile(filename, file, sp); + if (OpenRFF(rf, filter)) return rf; + file = rf->Destroy(); } } return NULL; } - +} diff --git a/src/common/filesystem/file_ssi.cpp b/src/common/filesystem/source/file_ssi.cpp similarity index 68% rename from src/common/filesystem/file_ssi.cpp rename to src/common/filesystem/source/file_ssi.cpp index 64623e805e..82885c6bb7 100644 --- a/src/common/filesystem/file_ssi.cpp +++ b/src/common/filesystem/source/file_ssi.cpp @@ -34,32 +34,8 @@ */ #include "resourcefile.h" -#include "printf.h" -//========================================================================== -// -// Build GRP file -// -//========================================================================== - -class FSSIFile : public FUncompressedFile -{ -public: - FSSIFile(const char * filename, FileReader &file); - bool Open(bool quiet, int version, int lumpcount, LumpFilterInfo* filter); -}; - - -//========================================================================== -// -// Initializes a Build GRP file -// -//========================================================================== - -FSSIFile::FSSIFile(const char *filename, FileReader &file) -: FUncompressedFile(filename, file) -{ -} +namespace FileSys { //========================================================================== // @@ -68,42 +44,50 @@ FSSIFile::FSSIFile(const char *filename, FileReader &file) // //========================================================================== -bool FSSIFile::Open(bool quiet, int version, int lumpcount, LumpFilterInfo*) +static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilterInfo*) { - NumLumps = lumpcount*2; - Lumps.Resize(lumpcount*2); + uint32_t NumLumps = EntryCount * 2; + auto Entries = file->AllocateEntries(NumLumps); + auto Reader = file->GetContainerReader(); + - - int32_t j = (version == 2 ? 267 : 254) + (lumpcount * 121); + int32_t j = (version == 2 ? 267 : 254) + (EntryCount * 121); for (uint32_t i = 0; i < NumLumps; i+=2) { char fn[13]; - int strlength = Reader.ReadUInt8(); + int strlength = Reader->ReadUInt8(); if (strlength > 12) strlength = 12; - Reader.Read(fn, 12); + Reader->Read(fn, 12); fn[strlength] = 0; - int flength = Reader.ReadInt32(); - + int flength = Reader->ReadInt32(); - Lumps[i].LumpNameSetup(fn); - Lumps[i].Position = j; - Lumps[i].LumpSize = flength; - Lumps[i].Owner = this; - if (strstr(fn, ".GRP")) Lumps[i].Flags |= LUMPF_EMBEDDED; + Entries[i].Position = j; + Entries[i].CompressedSize = Entries[i].Length = flength; + Entries[i].Flags = 0; + Entries[i].Namespace = ns_global; + Entries[i].Method = METHOD_STORED; + Entries[i].ResourceID = -1; + Entries[i].FileName = file->NormalizeFileName(fn); + if (strstr(fn, ".GRP")) Entries[i].Flags |= RESFF_EMBEDDED; // SSI files can swap the order of the extension's characters - but there's no reliable detection for this and it can be mixed inside the same container, // so we have no choice but to create another file record for the altered name. std::swap(fn[strlength - 1], fn[strlength - 3]); - Lumps[i+1].LumpNameSetup(fn); - Lumps[i+1].Position = j; - Lumps[i+1].LumpSize = flength; - Lumps[i+1].Owner = this; - if (strstr(fn, ".GRP")) Lumps[i+1].Flags |= LUMPF_EMBEDDED; + + Entries[i + 1].Position = j; + Entries[i + 1].CompressedSize = Entries[i + 1].Length = flength; + Entries[i + 1].Flags = 0; + Entries[i + 1].Namespace = ns_global; + Entries[i + 1].ResourceID = -1; + Entries[i + 1].FileName = file->NormalizeFileName(fn); + Entries[i + 1].Method = METHOD_STORED; + if (strstr(fn, ".GRP")) Entries[i + 1].Flags |= RESFF_EMBEDDED; j += flength; - Reader.Seek(104, FileReader::SeekCur); + Reader->Seek(104, FileReader::SeekCur); + file->GenerateHash(); } return true; } @@ -115,7 +99,7 @@ bool FSSIFile::Open(bool quiet, int version, int lumpcount, LumpFilterInfo*) // //========================================================================== -FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, LumpFilterInfo* filter) +FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char zerobuf[72]; char buf[72]; @@ -145,11 +129,12 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, Lump { if (!skipstring(70)) return nullptr; } - auto ssi = new FSSIFile(filename, file); - if (ssi->Open(filename, version, numfiles, filter)) return ssi; - file = std::move(ssi->Reader); // to avoid destruction of reader - delete ssi; + auto ssi = new FResourceFile(filename, file, sp); + if (OpenSSI(ssi, version, numfiles, filter)) return ssi; + file = ssi->Destroy(); } } return nullptr; } + +} diff --git a/src/common/filesystem/file_wad.cpp b/src/common/filesystem/source/file_wad.cpp similarity index 54% rename from src/common/filesystem/file_wad.cpp rename to src/common/filesystem/source/file_wad.cpp index 8af39b5f82..4f8574b73d 100644 --- a/src/common/filesystem/file_wad.cpp +++ b/src/common/filesystem/source/file_wad.cpp @@ -35,10 +35,13 @@ #include #include "resourcefile.h" -#include "v_text.h" -#include "filesystem.h" -#include "engineerrors.h" +#include "fs_filesystem.h" +#include "fs_swap.h" +#include "fs_stringpool.h" +#include "resourcefile.h" +namespace FileSys { + using namespace byteswap; struct wadinfo_t { @@ -55,65 +58,6 @@ struct wadlump_t char Name[8]; }; -//========================================================================== -// -// Wad Lump (with console doom LZSS support) -// -//========================================================================== - -class FWadFileLump : public FResourceLump -{ -public: - bool Compressed; - int Position; - int Namespace; - - int GetNamespace() const override { return Namespace; } - - int GetFileOffset() override { return Position; } - FileReader *GetReader() override - { - if(!Compressed) - { - Owner->Reader.Seek(Position, FileReader::SeekSet); - return &Owner->Reader; - } - return NULL; - } - int FillCache() override - { - if(!Compressed) - { - const char * buffer = Owner->Reader.GetBuffer(); - - if (buffer != NULL) - { - // This is an in-memory file so the cache can point directly to the file's data. - Cache = const_cast(buffer) + Position; - RefCount = -1; - return -1; - } - } - - Owner->Reader.Seek(Position, FileReader::SeekSet); - Cache = new char[LumpSize]; - - if(Compressed) - { - FileReader lzss; - if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false, [](const char* err) { I_Error("%s", err); })) - { - lzss.Read(Cache, LumpSize); - } - } - else - Owner->Reader.Read(Cache, LumpSize); - - RefCount = 1; - return 1; - } -}; - //========================================================================== // // Wad file @@ -122,16 +66,13 @@ class FWadFileLump : public FResourceLump class FWadFile : public FResourceFile { - TArray Lumps; - bool IsMarker(int lump, const char *marker); - void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, bool flathack=false); - void SkinHack (); + void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack=false); + void SkinHack (FileSystemMessageFunc Printf); public: - FWadFile(const char * filename, FileReader &file); - FResourceLump *GetLump(int lump) { return &Lumps[lump]; } - bool Open(bool quiet, LumpFilterInfo* filter); + FWadFile(const char * filename, FileReader &file, StringPool* sp); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); }; @@ -143,8 +84,8 @@ class FWadFile : public FResourceFile // //========================================================================== -FWadFile::FWadFile(const char *filename, FileReader &file) - : FResourceFile(filename, file) +FWadFile::FWadFile(const char *filename, FileReader &file, StringPool* sp) + : FResourceFile(filename, file, sp) { } @@ -154,7 +95,7 @@ FWadFile::FWadFile(const char *filename, FileReader &file) // //========================================================================== -bool FWadFile::Open(bool quiet, LumpFilterInfo*) +bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf) { wadinfo_t header; uint32_t InfoTableOfs; @@ -176,63 +117,67 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*) // Check again to detect broken wads if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize) { - I_Error("Cannot load broken WAD file %s\n", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName); + return false; } } - TArray fileinfo(NumLumps, true); - Reader.Seek (InfoTableOfs, FileReader::SeekSet); - Reader.Read (fileinfo.Data(), NumLumps * sizeof(wadlump_t)); + Reader.Seek(InfoTableOfs, FileReader::SeekSet); + auto fd = Reader.Read(NumLumps * sizeof(wadlump_t)); + auto fileinfo = (const wadlump_t*)fd.data(); - Lumps.Resize(NumLumps); + AllocateEntries(NumLumps); for(uint32_t i = 0; i < NumLumps; i++) { + // WAD only supports ASCII. It is also the only format which can use valid backslashes in its names. char n[9]; - uppercopy(n, fileinfo[i].Name); + int ishigh = 0; + for (int j = 0; j < 8; j++) + { + if (fileinfo[i].Name[j] & 0x80) ishigh |= 1 << j; + n[j] = tolower(fileinfo[i].Name[j]); + } n[8] = 0; - // This needs to be done differently. We cannot simply assume that all lumps where the first character's high bit is set are compressed without verification. - // This requires explicit toggling for precisely the files that need it. -#if 0 - Lumps[i].Compressed = !(gameinfo.flags & GI_SHAREWARE) && (n[0] & 0x80) == 0x80; -#else - Lumps[i].Compressed = false; -#endif - n[0] &= ~0x80; - Lumps[i].LumpNameSetup(n); - - Lumps[i].Owner = this; - Lumps[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos); - Lumps[i].LumpSize = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size); - Lumps[i].Namespace = ns_global; - Lumps[i].Flags = Lumps[i].Compressed ? LUMPF_COMPRESSED | LUMPF_SHORTNAME : LUMPF_SHORTNAME; - - // Check if the lump is within the WAD file and print a warning if not. - if (Lumps[i].Position + Lumps[i].LumpSize > wadSize || Lumps[i].Position < 0 || Lumps[i].LumpSize < 0) + if (ishigh == 1) n[0] &= 0x7f; + else if (ishigh > 1) { - if (Lumps[i].LumpSize != 0) - { - Printf(PRINT_HIGH, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.GetChars(), Lumps[i].getName()); - Lumps[i].LumpNameSetup(""); - } - Lumps[i].LumpSize = Lumps[i].Position = 0; + // This may not end up printing something proper because we do not know what encoding might have been used. + Printf(FSMessageLevel::Warning, "%s: Lump name %.8s contains invalid characters\n", FileName, fileinfo[i].Name); } - } - GenerateHash(); // Do this before the lump processing below. + Entries[i].FileName = nullptr; + Entries[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos); + Entries[i].CompressedSize = Entries[i].Length = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size); - if (!quiet) // don't bother with namespaces in quiet mode. We won't need them. + Entries[i].Namespace = ns_global; + Entries[i].Flags = ishigh? RESFF_SHORTNAME | RESFF_COMPRESSED : RESFF_SHORTNAME; + Entries[i].Method = ishigh == 1? METHOD_LZSS : METHOD_STORED; + Entries[i].FileName = stringpool->Strdup(n); + // This doesn't set up the namespace yet. + } + for (uint32_t i = 0; i < NumLumps; i++) { - SetNamespace("S_START", "S_END", ns_sprites); - SetNamespace("F_START", "F_END", ns_flats, true); - SetNamespace("C_START", "C_END", ns_colormaps); - SetNamespace("A_START", "A_END", ns_acslibrary); - SetNamespace("TX_START", "TX_END", ns_newtextures); - SetNamespace("V_START", "V_END", ns_strifevoices); - SetNamespace("HI_START", "HI_END", ns_hires); - SetNamespace("VX_START", "VX_END", ns_voxels); - SkinHack(); + if (Entries[i].Method == METHOD_LZSS) + { + // compressed size is implicit. + Entries[i].CompressedSize = (i == NumLumps - 1 ? Reader.GetLength() : Entries[i + 1].Position) - Entries[i].Position; + } } + + + GenerateHash(); // Do this before the lump processing below. + + SetNamespace("s_start", "s_end", ns_sprites, Printf); + SetNamespace("f_start", "f_end", ns_flats, Printf, true); + SetNamespace("c_start", "c_end", ns_colormaps, Printf); + SetNamespace("a_start", "a_end", ns_acslibrary, Printf); + SetNamespace("tx_start", "tx_end", ns_newtextures, Printf); + SetNamespace("v_start", "v_end", ns_strifevoices, Printf); + SetNamespace("hi_start", "hi_end", ns_hires, Printf); + SetNamespace("vx_start", "vx_end", ns_voxels, Printf); + SkinHack(Printf); + return true; } @@ -246,10 +191,10 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*) inline bool FWadFile::IsMarker(int lump, const char *marker) { - if (Lumps[lump].getName()[0] == marker[0]) + if (Entries[lump].FileName[0] == marker[0]) { - return (!strcmp(Lumps[lump].getName(), marker) || - (marker[1] == '_' && !strcmp(Lumps[lump].getName() +1, marker))); + return (!strcmp(Entries[lump].FileName, marker) || + (marker[1] == '_' && !strcmp(Entries[lump].FileName +1, marker))); } else return false; } @@ -273,25 +218,25 @@ struct Marker unsigned int index; }; -void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, bool flathack) +void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack) { bool warned = false; int numstartmarkers = 0, numendmarkers = 0; unsigned int i; - TArray markers; + std::vector markers; for(i = 0; i < NumLumps; i++) { if (IsMarker(i, startmarker)) { Marker m = { 0, i }; - markers.Push(m); + markers.push_back(m); numstartmarkers++; } else if (IsMarker(i, endmarker)) { Marker m = { 1, i }; - markers.Push(m); + markers.push_back(m); numendmarkers++; } } @@ -300,22 +245,22 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name { if (numendmarkers == 0) return; // no markers found - Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", endmarker, startmarker); + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); if (flathack) { // We have found no F_START but one or more F_END markers. // mark all lumps before the last F_END marker as potential flats. - unsigned int end = markers[markers.Size()-1].index; + unsigned int end = markers[markers.size()-1].index; for(unsigned int ii = 0; ii < end; ii++) { - if (Lumps[ii].LumpSize == 4096) + if (Entries[ii].Length == 4096) { // We can't add this to the flats namespace but // it needs to be flagged for the texture manager. - DPrintf(DMSG_NOTIFY, "Marking %s as potential flat\n", Lumps[ii].getName()); - Lumps[ii].Flags |= LUMPF_MAYBEFLAT; + Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, Entries[ii].FileName); + Entries[ii].Flags |= RESFF_MAYBEFLAT; } } } @@ -323,35 +268,35 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name } i = 0; - while (i < markers.Size()) + while (i < markers.size()) { int start, end; if (markers[i].markertype != 0) { - Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", endmarker, startmarker); + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); i++; continue; } start = i++; // skip over subsequent x_START markers - while (i < markers.Size() && markers[i].markertype == 0) + while (i < markers.size() && markers[i].markertype == 0) { - Printf(TEXTCOLOR_YELLOW"WARNING: duplicate %s marker found.\n", startmarker); + Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker); i++; continue; } // same for x_END markers - while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1)) + while (i < markers.size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1)) { - Printf(TEXTCOLOR_YELLOW"WARNING: duplicate %s marker found.\n", endmarker); + Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker); i++; continue; } // We found a starting marker but no end marker. Ignore this block. - if (i >= markers.Size()) + if (i >= markers.size()) { - Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", startmarker, endmarker); + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker); end = NumLumps; } else @@ -360,28 +305,28 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name } // we found a marked block - DPrintf(DMSG_NOTIFY, "Found %s block at (%d-%d)\n", startmarker, markers[start].index, end); + Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end); for(int j = markers[start].index + 1; j < end; j++) { - if (Lumps[j].Namespace != ns_global) + if (Entries[j].Namespace != ns_global) { if (!warned) { - Printf(TEXTCOLOR_YELLOW"WARNING: Overlapping namespaces found (lump %d)\n", j); + Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName, j); } warned = true; } - else if (space == ns_sprites && Lumps[j].LumpSize < 8) + else if (space == ns_sprites && Entries[j].Length < 8) { // sf 26/10/99: // ignore sprite lumps smaller than 8 bytes (the smallest possible) // in size -- this was used by some dmadds wads // as an 'empty' graphics resource - DPrintf(DMSG_WARNING, " Skipped empty sprite %s (lump %d)\n", Lumps[j].getName(), j); + Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, Entries[j].FileName, j); } else { - Lumps[j].Namespace = space; + Entries[j].Namespace = space; } } } @@ -401,7 +346,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name // //========================================================================== -void FWadFile::SkinHack () +void FWadFile::SkinHack (FileSystemMessageFunc Printf) { // this being static is not a problem. The only relevant thing is that each skin gets a different number. static int namespc = ns_firstskin; @@ -411,11 +356,11 @@ void FWadFile::SkinHack () for (i = 0; i < NumLumps; i++) { - FResourceLump *lump = &Lumps[i]; + auto lump = &Entries[i]; - if (!strnicmp(lump->getName(), "S_SKIN", 6)) + if (!strnicmp(lump->FileName, "S_SKIN", 6)) { // Wad has at least one skin. - lump->LumpNameSetup("S_SKIN"); + lump->FileName = "S_SKIN"; if (!skinned) { skinned = true; @@ -423,35 +368,32 @@ void FWadFile::SkinHack () for (j = 0; j < NumLumps; j++) { - Lumps[j].Namespace = namespc; + Entries[j].Namespace = namespc; } namespc++; } } // needless to say, this check is entirely useless these days as map names can be more diverse.. - if ((lump->getName()[0] == 'M' && - lump->getName()[1] == 'A' && - lump->getName()[2] == 'P' && - lump->getName()[3] >= '0' && lump->getName()[3] <= '9' && - lump->getName()[4] >= '0' && lump->getName()[4] <= '9' && - lump->getName()[5] == '\0') + if ((lump->FileName[0] == 'M' && + lump->FileName[1] == 'A' && + lump->FileName[2] == 'P' && + lump->FileName[3] >= '0' && lump->FileName[3] <= '9' && + lump->FileName[4] >= '0' && lump->FileName[4] <= '9' && + lump->FileName[5] == '\0') || - (lump->getName()[0] == 'E' && - lump->getName()[1] >= '0' && lump->getName()[1] <= '9' && - lump->getName()[2] == 'M' && - lump->getName()[3] >= '0' && lump->getName()[3] <= '9' && - lump->getName()[4] == '\0')) + (lump->FileName[0] == 'E' && + lump->FileName[1] >= '0' && lump->FileName[1] <= '9' && + lump->FileName[2] == 'M' && + lump->FileName[3] >= '0' && lump->FileName[3] <= '9' && + lump->FileName[4] == '\0')) { hasmap = true; } } if (skinned && hasmap) { - Printf (TEXTCOLOR_BLUE - "The maps in %s will not be loaded because it has a skin.\n" - TEXTCOLOR_BLUE - "You should remove the skin from the wad to play these maps.\n", - FileName.GetChars()); + Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName); + Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n"); } } @@ -462,7 +404,7 @@ void FWadFile::SkinHack () // //========================================================================== -FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -473,13 +415,13 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, Lump file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4)) { - auto rf = new FWadFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + auto rf = new FWadFile(filename, file, sp); + if (rf->Open(filter, Printf)) return rf; - file = std::move(rf->Reader); // to avoid destruction of reader - delete rf; + file = rf->Destroy(); } } return NULL; } +} diff --git a/src/common/filesystem/file_whres.cpp b/src/common/filesystem/source/file_whres.cpp similarity index 55% rename from src/common/filesystem/file_whres.cpp rename to src/common/filesystem/source/file_whres.cpp index 969aaafabe..d1d2d1a508 100644 --- a/src/common/filesystem/file_whres.cpp +++ b/src/common/filesystem/source/file_whres.cpp @@ -35,56 +35,11 @@ */ #include "resourcefile.h" -#include "printf.h" -#include "cmdlib.h" +#include "fs_stringpool.h" +#include "fs_swap.h" -//========================================================================== -// -// -// -//========================================================================== - -struct whresentry -{ - int filepospage, filelen, priority; -} ; - -struct dpackheader_t -{ - int ident; // == IDPAKHEADER - int dirofs; - int dirlen; -} ; - - -//========================================================================== -// -// Wad file -// -//========================================================================== - -class FWHResFile : public FUncompressedFile -{ - FString basename; -public: - FWHResFile(const char * filename, FileReader &file); - bool Open(bool quiet, LumpFilterInfo* filter); -}; - - -//========================================================================== -// -// FWadFile::FWadFile -// -// Initializes a WAD file -// -//========================================================================== - -FWHResFile::FWHResFile(const char *filename, FileReader &file) - : FUncompressedFile(filename, file) -{ - basename = ExtractFileBase(filename, false); -} +namespace FileSys { + using namespace byteswap; //========================================================================== // @@ -92,33 +47,48 @@ FWHResFile::FWHResFile(const char *filename, FileReader &file) // //========================================================================== -bool FWHResFile::Open(bool quiet, LumpFilterInfo*) +bool OpenWHRes(FResourceFile* file, LumpFilterInfo*) { - int directory[1024]; + uint32_t directory[1024]; - Reader.Seek(-4096, FileReader::SeekEnd); - Reader.Read(directory, 4096); + auto BaseName = ExtractBaseName(file->GetFileName()); + auto Reader = file->GetContainerReader(); + Reader->Seek(-4096, FileReader::SeekEnd); + Reader->Read(directory, 4096); int nl =1024/3; - Lumps.Resize(nl); - + + int k; + for (k = 0; k < nl; k++) + { + uint32_t offset = LittleLong(directory[k * 3]) * 4096; + uint32_t length = LittleLong(directory[k * 3 + 1]); + if (length == 0) + { + break; + } + } + auto Entries = file->AllocateEntries(k); + auto NumLumps = k; int i = 0; - for(int k = 0; k < nl; k++) + for(k = 0; k < NumLumps; k++) { - int offset = LittleLong(directory[k*3]) * 4096; - int length = LittleLong(directory[k*3+1]); - if (length <= 0) break; - FStringf synthname("%s/%04d", basename.GetChars(), k); - Lumps[i].LumpNameSetup(synthname); - Lumps[i].Owner = this; - Lumps[i].Position = offset; - Lumps[i].LumpSize = length; + uint32_t offset = LittleLong(directory[k*3]) * 4096; + uint32_t length = LittleLong(directory[k*3+1]); + char num[6]; + snprintf(num, 6, "/%04d", k); + std::string synthname = BaseName + num; + + Entries[i].Position = offset; + Entries[i].CompressedSize = Entries[i].Length = length; + Entries[i].Flags = RESFF_FULLPATH; + Entries[i].Namespace = ns_global; + Entries[i].ResourceID = -1; + Entries[i].Method = METHOD_STORED; + Entries[i].FileName = file->NormalizeFileName(synthname.c_str()); i++; } - NumLumps = i; - Lumps.Clamp(NumLumps); - Lumps.ShrinkToFit(); return true; } @@ -129,30 +99,31 @@ bool FWHResFile::Open(bool quiet, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckWHRes(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { if (file.GetLength() >= 8192) // needs to be at least 8192 to contain one file and the directory. { - int directory[1024]; + unsigned directory[1024]; int nl =1024/3; file.Seek(-4096, FileReader::SeekEnd); file.Read(directory, 4096); + auto size = file.GetLength(); - int checkpos = 0; + uint32_t checkpos = 0; for(int k = 0; k < nl; k++) { - int offset = LittleLong(directory[k*3]); - int length = LittleLong(directory[k*3+1]); + unsigned offset = LittleLong(directory[k*3]); + unsigned length = LittleLong(directory[k*3+1]); if (length <= 0 && offset == 0) break; - if (offset != checkpos || length <= 0) return nullptr; + if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr; checkpos += (length+4095) / 4096; } - auto rf = new FWHResFile(filename, file); - if (rf->Open(quiet, filter)) return rf; - file = std::move(rf->Reader); // to avoid destruction of reader - delete rf; + auto rf = new FResourceFile(filename, file, sp); + if (OpenWHRes(rf, filter)) return rf; + file = rf->Destroy(); } return NULL; } - \ No newline at end of file + +} \ No newline at end of file diff --git a/src/common/filesystem/source/file_zip.cpp b/src/common/filesystem/source/file_zip.cpp new file mode 100644 index 0000000000..8351b71464 --- /dev/null +++ b/src/common/filesystem/source/file_zip.cpp @@ -0,0 +1,399 @@ +/* +** file_zip.cpp +** +**--------------------------------------------------------------------------- +** Copyright 1998-2009 Randy Heit +** Copyright 2005-2023 Christoph Oelckers +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +** +*/ + +#include +#include +#include +#include "w_zip.h" +#include "ancientzip.h" +#include "resourcefile.h" +#include "fs_findfile.h" +#include "fs_swap.h" +#include "fs_stringpool.h" + +namespace FileSys { + using namespace byteswap; + +#define BUFREADCOMMENT (0x400) + +//----------------------------------------------------------------------- +// +// Finds the central directory end record in the end of the file. +// Taken from Quake3 source but the file in question is not GPL'ed. ;) +// +//----------------------------------------------------------------------- + +static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64) +{ + unsigned char buf[BUFREADCOMMENT + 4]; + uint32_t FileSize; + uint32_t uBackRead; + uint32_t uMaxBack; // maximum size of global comment + uint32_t uPosFound=0; + + FileSize = (uint32_t)fin.GetLength(); + uMaxBack = std::min(0xffff, FileSize); + + uBackRead = 4; + while (uBackRead < uMaxBack) + { + uint32_t uReadSize, uReadPos; + int i; + if (uBackRead + BUFREADCOMMENT > uMaxBack) + uBackRead = uMaxBack; + else + uBackRead += BUFREADCOMMENT; + uReadPos = FileSize - uBackRead; + + uReadSize = std::min((BUFREADCOMMENT + 4), (FileSize - uReadPos)); + + if (fin.Seek(uReadPos, FileReader::SeekSet) != 0) break; + + if (fin.Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break; + + for (i = (int)uReadSize - 3; (i--) > 0;) + { + if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6 && !*zip64 && uPosFound == 0) + { + *zip64 = false; + uPosFound = uReadPos + i; + } + if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 6 && buf[i+3] == 6) + { + *zip64 = true; + uPosFound = uReadPos + i; + return uPosFound; + } + } + } + return uPosFound; +} + +//========================================================================== +// +// Zip file +// +//========================================================================== + +class FZipFile : public FResourceFile +{ + void SetEntryAddress(uint32_t entry) override; + +public: + FZipFile(const char* filename, FileReader& file, StringPool* sp); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); + FCompressedBuffer GetRawData(uint32_t entry) override; +}; + +//========================================================================== +// +// Zip file +// +//========================================================================== + +FZipFile::FZipFile(const char * filename, FileReader &file, StringPool* sp) +: FResourceFile(filename, file, sp) +{ +} + +bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) +{ + bool zip64 = false; + uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64); + int skipped = 0; + + if (centraldir == 0) + { + Printf(FSMessageLevel::Error, "%s: ZIP file corrupt!\n", FileName); + return false; + } + + uint64_t dirsize, DirectoryOffset; + if (!zip64) + { + FZipEndOfCentralDirectory info; + // Read the central directory info. + Reader.Seek(centraldir, FileReader::SeekSet); + Reader.Read(&info, sizeof(FZipEndOfCentralDirectory)); + + // No multi-disk zips! + if (info.NumEntries != info.NumEntriesOnAllDisks || + info.FirstDisk != 0 || info.DiskNumber != 0) + { + Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName); + return false; + } + + NumLumps = LittleShort(info.NumEntries); + dirsize = LittleLong(info.DirectorySize); + DirectoryOffset = LittleLong(info.DirectoryOffset); + } + else + { + FZipEndOfCentralDirectory64 info; + // Read the central directory info. + Reader.Seek(centraldir, FileReader::SeekSet); + Reader.Read(&info, sizeof(FZipEndOfCentralDirectory64)); + + // No multi-disk zips! + if (info.NumEntries != info.NumEntriesOnAllDisks || + info.FirstDisk != 0 || info.DiskNumber != 0) + { + Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName); + return false; + } + + NumLumps = (uint32_t)info.NumEntries; + dirsize = info.DirectorySize; + DirectoryOffset = info.DirectoryOffset; + } + // Load the entire central directory. Too bad that this contains variable length entries... + void *directory = malloc(dirsize); + Reader.Seek(DirectoryOffset, FileReader::SeekSet); + Reader.Read(directory, dirsize); + + char *dirptr = (char*)directory; + + std::string name0, name1; + bool foundspeciallump = false; + bool foundprefix = false; + + // Check if all files have the same prefix so that this can be stripped out. + // This will only be done if there is either a MAPINFO, ZMAPINFO or GAMEINFO lump in the subdirectory, denoting a ZDoom mod. + if (NumLumps > 1) for (uint32_t i = 0; i < NumLumps; i++) + { + FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; + + int len = LittleShort(zip_fh->NameLength); + std::string name(dirptr + sizeof(FZipCentralDirectoryInfo), len); + + dirptr += sizeof(FZipCentralDirectoryInfo) + + LittleShort(zip_fh->NameLength) + + LittleShort(zip_fh->ExtraLength) + + LittleShort(zip_fh->CommentLength); + + if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. + { + free(directory); + Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName); + return false; + } + } + + dirptr = (char*)directory; + AllocateEntries(NumLumps); + auto Entry = Entries; + for (uint32_t i = 0; i < NumLumps; i++) + { + FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; + + int len = LittleShort(zip_fh->NameLength); + std::string name(dirptr + sizeof(FZipCentralDirectoryInfo), len); + dirptr += sizeof(FZipCentralDirectoryInfo) + + LittleShort(zip_fh->NameLength) + + LittleShort(zip_fh->ExtraLength) + + LittleShort(zip_fh->CommentLength); + + if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. + { + free(directory); + Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName); + return false; + } + + // skip Directories + if (name.empty() || (name.back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0)) + { + skipped++; + continue; + } + + // Ignore unknown compression formats + zip_fh->Method = LittleShort(zip_fh->Method); + if (zip_fh->Method != METHOD_STORED && + zip_fh->Method != METHOD_DEFLATE && + zip_fh->Method != METHOD_LZMA && + zip_fh->Method != METHOD_BZIP2 && + zip_fh->Method != METHOD_IMPLODE && + zip_fh->Method != METHOD_SHRINK && + zip_fh->Method != METHOD_XZ) + { + Printf(FSMessageLevel::Error, "%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName, name.c_str(), zip_fh->Method); + skipped++; + continue; + } + // Also ignore encrypted entries + zip_fh->Flags = LittleShort(zip_fh->Flags); + if (zip_fh->Flags & ZF_ENCRYPTED) + { + Printf(FSMessageLevel::Error, "%s: '%s' is encrypted. Encryption is not supported.\n", FileName, name.c_str()); + skipped++; + continue; + } + + uint32_t UncompressedSize =LittleLong(zip_fh->UncompressedSize32); + uint32_t CompressedSize = LittleLong(zip_fh->CompressedSize32); + uint64_t LocalHeaderOffset = LittleLong(zip_fh->LocalHeaderOffset32); + if (zip_fh->ExtraLength > 0) + { + uint8_t* rawext = (uint8_t*)zip_fh + sizeof(*zip_fh) + zip_fh->NameLength; + uint32_t ExtraLength = LittleLong(zip_fh->ExtraLength); + + while (ExtraLength > 0) + { + auto zip_64 = (FZipCentralDirectoryInfo64BitExt*)rawext; + uint32_t BlockLength = LittleLong(zip_64->Length); + rawext += BlockLength + 4; + ExtraLength -= BlockLength + 4; + if (LittleLong(zip_64->Type) == 1 && BlockLength >= 0x18) + { + if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff) + { + // The file system is limited to 32 bit file sizes; + Printf(FSMessageLevel::Warning, "%s: '%s' is too large.\n", FileName, name.c_str()); + skipped++; + continue; + } + UncompressedSize = (uint32_t)zip_64->UncompressedSize; + CompressedSize = (uint32_t)zip_64->CompressedSize; + LocalHeaderOffset = zip_64->LocalHeaderOffset; + } + } + } + + Entry->FileName = NormalizeFileName(name.c_str()); + Entry->Length = UncompressedSize; + // The start of the Reader will be determined the first time it is accessed. + Entry->Flags = RESFF_FULLPATH | RESFF_NEEDFILESTART; + Entry->Method = uint8_t(zip_fh->Method); + if (Entry->Method != METHOD_STORED) Entry->Flags |= RESFF_COMPRESSED; + if (Entry->Method == METHOD_IMPLODE) + { + // for Implode merge the flags into the compression method to make handling in the file system easier and save one variable. + if ((zip_fh->Flags & 6) == 2) Entry->Method = METHOD_IMPLODE_2; + else if ((zip_fh->Flags & 6) == 4) Entry->Method = METHOD_IMPLODE_4; + else if ((zip_fh->Flags & 6) == 6) Entry->Method = METHOD_IMPLODE_6; + else Entry->Method = METHOD_IMPLODE_0; + } + Entry->CRC32 = zip_fh->CRC32; + Entry->CompressedSize = CompressedSize; + Entry->Position = LocalHeaderOffset; + + Entry++; + + } + // Resize the lump record array to its actual size + NumLumps -= skipped; + free(directory); + + GenerateHash(); + PostProcessArchive(filter); + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +FCompressedBuffer FZipFile::GetRawData(uint32_t entry) +{ + FCompressedBuffer cbuf; + + if (entry >= NumLumps || Entries[entry].Length == 0) + { + cbuf = { 0, 0, METHOD_STORED, 0, 0, nullptr }; + } + else + { + auto& e = Entries[entry]; + cbuf = { e.Length, e.CompressedSize, e.Method, e.CRC32, new char[e.CompressedSize] }; + if (e.Flags & RESFF_NEEDFILESTART) SetEntryAddress(entry); + Reader.Seek(e.Position, FileReader::SeekSet); + Reader.Read(cbuf.mBuffer, e.CompressedSize); + } + + return cbuf; +} + +//========================================================================== +// +// SetLumpAddress +// +//========================================================================== + +void FZipFile::SetEntryAddress(uint32_t entry) +{ + // This file is inside a zip and has not been opened before. + // Position points to the start of the local file header, which we must + // read and skip so that we can get to the actual file data. + FZipLocalFileHeader localHeader; + int skiplen; + + Reader.Seek(Entries[entry].Position, FileReader::SeekSet); + Reader.Read(&localHeader, sizeof(localHeader)); + skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength); + Entries[entry].Position += sizeof(localHeader) + skiplen; + Entries[entry].Flags &= ~RESFF_NEEDFILESTART; +} + +//========================================================================== +// +// File open +// +//========================================================================== + +FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + char head[4]; + + if (file.GetLength() >= (ptrdiff_t)sizeof(FZipLocalFileHeader)) + { + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileReader::SeekSet); + if (!memcmp(head, "PK\x3\x4", 4)) + { + auto rf = new FZipFile(filename, file, sp); + if (rf->Open(filter, Printf)) return rf; + file = rf->Destroy(); + } + } + return NULL; +} + + +} diff --git a/src/common/utility/files.cpp b/src/common/filesystem/source/files.cpp similarity index 63% rename from src/common/utility/files.cpp rename to src/common/filesystem/source/files.cpp index 6f915a2ceb..ac05811198 100644 --- a/src/common/utility/files.cpp +++ b/src/common/filesystem/source/files.cpp @@ -33,22 +33,34 @@ ** */ -#include "files.h" - // just for 'clamp' -#include "zstring.h" - +#include +#include +#include +#include +#include +#include "files_internal.h" + +namespace FileSys { + +#ifdef _WIN32 +std::wstring toWide(const char* str); +#endif FILE *myfopen(const char *filename, const char *flags) { #ifndef _WIN32 return fopen(filename, flags); #else - auto widename = WideString(filename); - auto wideflags = WideString(flags); + auto widename = toWide(filename); + auto wideflags = toWide(flags); return _wfopen(widename.c_str(), wideflags.c_str()); #endif } +#ifdef _WIN32 +#define fseek _fseeki64 +#define ftell _ftelli64 +#endif //========================================================================== // @@ -61,8 +73,8 @@ FILE *myfopen(const char *filename, const char *flags) class StdFileReader : public FileReaderInterface { FILE *File = nullptr; - long StartPos = 0; - long FilePos = 0; + ptrdiff_t StartPos = 0; + ptrdiff_t FilePos = 0; public: StdFileReader() @@ -77,7 +89,7 @@ class StdFileReader : public FileReaderInterface File = nullptr; } - bool Open(const char *filename, long startpos = 0, long len = -1) + bool Open(const char *filename, ptrdiff_t startpos = 0, ptrdiff_t len = -1) { File = myfopen(filename, "rb"); if (File == nullptr) return false; @@ -89,12 +101,12 @@ class StdFileReader : public FileReaderInterface return true; } - long Tell() const override + ptrdiff_t Tell() const override { return FilePos - StartPos; } - long Seek(long offset, int origin) override + ptrdiff_t Seek(ptrdiff_t offset, int origin) override { if (origin == SEEK_SET) { @@ -118,7 +130,7 @@ class StdFileReader : public FileReaderInterface return -1; } - long Read(void *buffer, long len) override + ptrdiff_t Read(void *buffer, ptrdiff_t len) override { assert(len >= 0); if (len <= 0) return 0; @@ -126,18 +138,18 @@ class StdFileReader : public FileReaderInterface { len = Length - FilePos + StartPos; } - len = (long)fread(buffer, 1, len, File); + len = fread(buffer, 1, len, File); FilePos += len; return len; } - char *Gets(char *strbuf, int len) override + char *Gets(char *strbuf, ptrdiff_t len) override { - if (len <= 0 || FilePos >= StartPos + Length) return NULL; - char *p = fgets(strbuf, len, File); - if (p != NULL) + if (len <= 0 || len > 0x7fffffff || FilePos >= StartPos + Length) return nullptr; + char *p = fgets(strbuf, (int)len, File); + if (p != nullptr) { - int old = FilePos; + ptrdiff_t old = FilePos; FilePos = ftell(File); if (FilePos - StartPos > Length) { @@ -148,9 +160,9 @@ class StdFileReader : public FileReaderInterface } private: - long CalcFileLen() const + ptrdiff_t CalcFileLen() const { - long endpos; + ptrdiff_t endpos; fseek(File, 0, SEEK_END); endpos = ftell(File); @@ -170,11 +182,11 @@ class StdFileReader : public FileReaderInterface class FileReaderRedirect : public FileReaderInterface { FileReader *mReader = nullptr; - long StartPos = 0; - long FilePos = 0; + ptrdiff_t StartPos = 0; + ptrdiff_t FilePos = 0; public: - FileReaderRedirect(FileReader &parent, long start, long length) + FileReaderRedirect(FileReader &parent, ptrdiff_t start, ptrdiff_t length) { mReader = &parent; FilePos = start; @@ -183,12 +195,12 @@ class FileReaderRedirect : public FileReaderInterface Seek(0, SEEK_SET); } - virtual long Tell() const override + virtual ptrdiff_t Tell() const override { return FilePos - StartPos; } - virtual long Seek(long offset, int origin) override + virtual ptrdiff_t Seek(ptrdiff_t offset, int origin) override { switch (origin) { @@ -201,7 +213,7 @@ class FileReaderRedirect : public FileReaderInterface break; case SEEK_CUR: - offset += (long)mReader->Tell(); + offset += mReader->Tell(); break; } if (offset < StartPos || offset > StartPos + Length) return -1; // out of scope @@ -213,7 +225,7 @@ class FileReaderRedirect : public FileReaderInterface return -1; } - virtual long Read(void *buffer, long len) override + virtual ptrdiff_t Read(void *buffer, ptrdiff_t len) override { assert(len >= 0); if (len <= 0) return 0; @@ -221,19 +233,19 @@ class FileReaderRedirect : public FileReaderInterface { len = Length - FilePos + StartPos; } - len = (long)mReader->Read(buffer, len); + len = mReader->Read(buffer, len); FilePos += len; return len; } - virtual char *Gets(char *strbuf, int len) override + virtual char *Gets(char *strbuf, ptrdiff_t len) override { - if (len <= 0 || FilePos >= StartPos + Length) return NULL; + if (len <= 0 || FilePos >= StartPos + Length) return nullptr; char *p = mReader->Gets(strbuf, len); - if (p != NULL) + if (p != nullptr) { - int old = FilePos; - FilePos = (long)mReader->Tell(); + ptrdiff_t old = FilePos; + FilePos = mReader->Tell(); if (FilePos - StartPos > Length) { strbuf[Length - old + StartPos] = 0; @@ -252,12 +264,12 @@ class FileReaderRedirect : public FileReaderInterface // //========================================================================== -long MemoryReader::Tell() const +ptrdiff_t MemoryReader::Tell() const { return FilePos; } -long MemoryReader::Seek(long offset, int origin) +ptrdiff_t MemoryReader::Seek(ptrdiff_t offset, int origin) { switch (origin) { @@ -271,23 +283,23 @@ long MemoryReader::Seek(long offset, int origin) } if (offset < 0 || offset > Length) return -1; - FilePos = clamp(offset, 0, Length); + FilePos = std::clamp(offset, 0, Length); return 0; } -long MemoryReader::Read(void *buffer, long len) +ptrdiff_t MemoryReader::Read(void *buffer, ptrdiff_t len) { - if (len>Length - FilePos) len = Length - FilePos; + if (len > Length - FilePos) len = Length - FilePos; if (len<0) len = 0; memcpy(buffer, bufptr + FilePos, len); FilePos += len; return len; } -char *MemoryReader::Gets(char *strbuf, int len) +char *MemoryReader::Gets(char *strbuf, ptrdiff_t len) { if (len>Length - FilePos) len = Length - FilePos; - if (len <= 0) return NULL; + if (len <= 0) return nullptr; char *p = strbuf; while (len > 1) @@ -309,45 +321,42 @@ char *MemoryReader::Gets(char *strbuf, int len) } FilePos++; } - if (p == strbuf) return NULL; + if (p == strbuf) return nullptr; *p++ = 0; return strbuf; } -//========================================================================== -// -// MemoryArrayReader -// -// reads data from an array of memory -// -//========================================================================== - -class MemoryArrayReader : public MemoryReader +int BufferingReader::FillBuffer(ptrdiff_t newpos) { - TArray buf; - -public: - MemoryArrayReader(const char *buffer, long length) + if (newpos > Length) newpos = Length; + if (newpos <= bufferpos) return 0; + auto read = baseReader->Read(&buf.writable()[bufferpos], newpos - bufferpos); + bufferpos += read; + if (bufferpos == Length) { - if (length > 0) - { - buf.Resize(length); - memcpy(&buf[0], buffer, length); - } - UpdateBuffer(); + // we have read the entire file, so delete our data provider. + baseReader.reset(); } + return newpos == bufferpos ? 0 : -1; +} - TArray &GetArray() { return buf; } - - void UpdateBuffer() - { - bufptr = (const char*)&buf[0]; - FilePos = 0; - Length = buf.Size(); - } -}; +ptrdiff_t BufferingReader::Seek(ptrdiff_t offset, int origin) +{ + if (-1 == MemoryReader::Seek(offset, origin)) return -1; + return FillBuffer(FilePos); +} +ptrdiff_t BufferingReader::Read(void* buffer, ptrdiff_t len) +{ + if (FillBuffer(FilePos + len) < 0) return 0; + return MemoryReader::Read(buffer, len); +} +char* BufferingReader::Gets(char* strbuf, ptrdiff_t len) +{ + if (FillBuffer(FilePos + len) < 0) return nullptr; + return MemoryReader::Gets(strbuf, len); +} //========================================================================== // @@ -357,22 +366,23 @@ class MemoryArrayReader : public MemoryReader // //========================================================================== -bool FileReader::OpenFile(const char *filename, FileReader::Size start, FileReader::Size length) +bool FileReader::OpenFile(const char *filename, FileReader::Size start, FileReader::Size length, bool buffered) { auto reader = new StdFileReader; - if (!reader->Open(filename, (long)start, (long)length)) + if (!reader->Open(filename, start, length)) { delete reader; return false; } Close(); - mReader = reader; + if (buffered) mReader = new BufferingReader(reader); + else mReader = reader; return true; } bool FileReader::OpenFilePart(FileReader &parent, FileReader::Size start, FileReader::Size length) { - auto reader = new FileReaderRedirect(parent, (long)start, (long)length); + auto reader = new FileReaderRedirect(parent, start, length); Close(); mReader = reader; return true; @@ -381,36 +391,45 @@ bool FileReader::OpenFilePart(FileReader &parent, FileReader::Size start, FileRe bool FileReader::OpenMemory(const void *mem, FileReader::Size length) { Close(); - mReader = new MemoryReader((const char *)mem, (long)length); + mReader = new MemoryReader((const char *)mem, length); return true; } -bool FileReader::OpenMemoryArray(const void *mem, FileReader::Size length) +bool FileReader::OpenMemoryArray(FileData& data) { Close(); - mReader = new MemoryArrayReader((const char *)mem, (long)length); + if (data.size() > 0) mReader = new MemoryArrayReader(data); return true; } -bool FileReader::OpenMemoryArray(std::function&)> getter) +FileData FileReader::Read(size_t len) { - auto reader = new MemoryArrayReader(nullptr, 0); - if (getter(reader->GetArray())) + FileData buffer; + if (len > 0) { - Close(); - reader->UpdateBuffer(); - mReader = reader; - return true; + Size length = mReader->Read(buffer.allocate(len), len); + if ((size_t)length < len) buffer.allocate(length); } - else + return buffer; +} + +FileData FileReader::ReadPadded(size_t padding) +{ + auto len = GetLength(); + FileData buffer; + + if (len > 0) { - // This will keep the old buffer, if one existed - delete reader; - return false; + auto p = (char*)buffer.allocate(len + padding); + Size length = mReader->Read(p, len); + if (length < len) buffer.clear(); + else memset(p + len, 0, padding); } + return buffer; } + //========================================================================== // // FileWriter (the motivation here is to have a buffer writing subclass) @@ -420,7 +439,7 @@ bool FileReader::OpenMemoryArray(std::function&)> getter) bool FileWriter::OpenDirect(const char *filename) { File = myfopen(filename, "wb"); - return (File != NULL); + return (File != nullptr); } FileWriter *FileWriter::Open(const char *filename) @@ -431,12 +450,12 @@ FileWriter *FileWriter::Open(const char *filename) return fwrit; } delete fwrit; - return NULL; + return nullptr; } size_t FileWriter::Write(const void *buffer, size_t len) { - if (File != NULL) + if (File != nullptr) { return fwrite(buffer, 1, len, File); } @@ -446,9 +465,9 @@ size_t FileWriter::Write(const void *buffer, size_t len) } } -long FileWriter::Tell() +ptrdiff_t FileWriter::Tell() { - if (File != NULL) + if (File != nullptr) { return ftell(File); } @@ -458,9 +477,9 @@ long FileWriter::Tell() } } -long FileWriter::Seek(long offset, int mode) +ptrdiff_t FileWriter::Seek(ptrdiff_t offset, int mode) { - if (File != NULL) + if (File != nullptr) { return fseek(File, offset, mode); } @@ -472,18 +491,24 @@ long FileWriter::Seek(long offset, int mode) size_t FileWriter::Printf(const char *fmt, ...) { - va_list ap; - FString out; - - va_start(ap, fmt); - out.VFormat(fmt, ap); - va_end(ap); - return Write(out.GetChars(), out.Len()); + char c[300]; + va_list arglist; + va_start(arglist, fmt); + auto n = vsnprintf(c, 300, fmt, arglist); + std::string buf; + buf.resize(n + 1); + va_start(arglist, fmt); + vsnprintf(&buf.front(), n + 1, fmt, arglist); + va_end(arglist); + return Write(buf.c_str(), strlen(buf.c_str())); // Make sure we write no nullptr bytes. } size_t BufferWriter::Write(const void *buffer, size_t len) { - unsigned int ofs = mBuffer.Reserve((unsigned)len); + size_t ofs = mBuffer.size(); + mBuffer.resize(ofs + len); memcpy(&mBuffer[ofs], buffer, len); return len; } + +} diff --git a/src/common/utility/files_decompress.cpp b/src/common/filesystem/source/files_decompress.cpp similarity index 53% rename from src/common/utility/files_decompress.cpp rename to src/common/filesystem/source/files_decompress.cpp index cd2e36ed7c..3f7dfb8659 100644 --- a/src/common/utility/files_decompress.cpp +++ b/src/common/filesystem/source/files_decompress.cpp @@ -36,50 +36,78 @@ // Caution: LzmaDec also pulls in windows.h! #define NOMINMAX #include "LzmaDec.h" -#include +#include "Xz.h" +// CRC table needs to be generated prior to reading XZ compressed files. +#include "7zCrc.h" +#include #include #include #include -#include "files.h" +#include "fs_files.h" +#include "files_internal.h" +#include "ancientzip.h" +#include "fs_decompress.h" + +namespace FileSys { + using namespace byteswap; + + +class DecompressorBase : public FileReaderInterface +{ + bool exceptions = false; + +public: + // These do not work but need to be defined to satisfy the FileReaderInterface. + // They will just error out when called. + ptrdiff_t Tell() const override; + ptrdiff_t Seek(ptrdiff_t offset, int origin) override; + char* Gets(char* strbuf, ptrdiff_t len) override; + void DecompressionError(const char* error, ...) const; + void SetOwnsReader(); + void EnableExceptions(bool on) { exceptions = on; } + +protected: + DecompressorBase() + { + //seekable = false; + } + FileReader* File = nullptr; + FileReader OwnedFile; +}; -#include "zstring.h" -#include "cmdlib.h" //========================================================================== // -// I_Error +// DecompressionError // -// Throw an error that will send us to the console if we are far enough -// along in the startup process. +// Allows catching errors from the decompressor. The default is just to +// return failure from the calling function. // //========================================================================== void DecompressorBase::DecompressionError(const char *error, ...) const { - const int MAX_ERRORTEXT = 300; - va_list argptr; - char errortext[MAX_ERRORTEXT]; - - va_start(argptr, error); - vsnprintf(errortext, MAX_ERRORTEXT, error, argptr); - va_end(argptr); - - if (ErrorCallback != nullptr) ErrorCallback(errortext); - else throw std::runtime_error(errortext); + if (exceptions) + { + va_list argptr; + va_start(argptr, error); + throw FileSystemException(error, argptr); + va_end(argptr); + } } -long DecompressorBase::Tell () const +ptrdiff_t DecompressorBase::Tell () const { DecompressionError("Cannot get position of decompressor stream"); return 0; } -long DecompressorBase::Seek (long offset, int origin) +ptrdiff_t DecompressorBase::Seek (ptrdiff_t offset, int origin) { DecompressionError("Cannot seek in decompressor stream"); return 0; } -char *DecompressorBase::Gets(char *strbuf, int len) +char *DecompressorBase::Gets(char *strbuf, ptrdiff_t len) { DecompressionError("Cannot use Gets on decompressor stream"); return nullptr; @@ -91,6 +119,19 @@ void DecompressorBase::SetOwnsReader() File = &OwnedFile; } +//========================================================================== +// +// +// +//========================================================================== + +static const char* ZLibError(int zerr) +{ + static const char* const errs[6] = { "Errno", "Stream Error", "Data Error", "Memory Error", "Buffer Error", "Version Error" }; + if (zerr >= 0 || zerr < -6) return "Unknown"; + else return errs[-zerr - 1]; +} + //========================================================================== // // DecompressorZ @@ -104,18 +145,22 @@ class DecompressorZ : public DecompressorBase { enum { BUFF_SIZE = 4096 }; - bool SawEOF; + bool SawEOF = false; z_stream Stream; uint8_t InBuff[BUFF_SIZE]; public: - DecompressorZ (FileReader *file, bool zip, const std::function& cb) - : SawEOF(false) + bool Open (FileReader *file, bool zip) { + if (File != nullptr) + { + DecompressionError("File already open"); + return false; + } + int err; File = file; - SetErrorCallback(cb); FillBuffer (); Stream.zalloc = Z_NULL; @@ -124,10 +169,12 @@ class DecompressorZ : public DecompressorBase if (!zip) err = inflateInit (&Stream); else err = inflateInit2 (&Stream, -MAX_WBITS); - if (err != Z_OK) + if (err < Z_OK) { - DecompressionError ("DecompressorZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars()); + DecompressionError ("DecompressorZ: inflateInit failed: %s\n", ZLibError(err)); + return false; } + return true; } ~DecompressorZ () @@ -135,33 +182,49 @@ class DecompressorZ : public DecompressorBase inflateEnd (&Stream); } - long Read (void *buffer, long len) override + ptrdiff_t Read (void *buffer, ptrdiff_t olen) override { - int err; + int err = 0; - Stream.next_out = (Bytef *)buffer; - Stream.avail_out = len; + if (File == nullptr) + { + DecompressionError("File not open"); + return 0; + } + auto len = olen; + if (len == 0) return 0; - do + while (len > 0) { - err = inflate (&Stream, Z_SYNC_FLUSH); - if (Stream.avail_in == 0 && !SawEOF) + Stream.next_out = (Bytef*)buffer; + unsigned rlen = (unsigned)std::min(len, 0x40000000); + Stream.avail_out = rlen; + buffer = Stream.next_out + rlen; + len -= rlen; + + do { - FillBuffer (); - } - } while (err == Z_OK && Stream.avail_out != 0); + err = inflate(&Stream, Z_SYNC_FLUSH); + if (Stream.avail_in == 0 && !SawEOF) + { + FillBuffer(); + } + } while (err == Z_OK && Stream.avail_out != 0); + } if (err != Z_OK && err != Z_STREAM_END) { DecompressionError ("Corrupt zlib stream"); + return 0; } if (Stream.avail_out != 0) { DecompressionError ("Ran out of data in zlib stream"); + return 0; } - return len - Stream.avail_out; + return olen - Stream.avail_out; } void FillBuffer () @@ -195,18 +258,22 @@ class DecompressorBZ2 : public DecompressorBase { enum { BUFF_SIZE = 4096 }; - bool SawEOF; + bool SawEOF = false; bz_stream Stream; uint8_t InBuff[BUFF_SIZE]; public: - DecompressorBZ2 (FileReader *file, const std::function& cb) - : SawEOF(false) + bool Open(FileReader *file) { + if (File != nullptr) + { + DecompressionError("File already open"); + return false; + } + int err; File = file; - SetErrorCallback(cb); stupidGlobal = this; FillBuffer (); @@ -219,7 +286,9 @@ class DecompressorBZ2 : public DecompressorBase if (err != BZ_OK) { DecompressionError ("DecompressorBZ2: bzDecompressInit failed: %d\n", err); + return false; } + return true; } ~DecompressorBZ2 () @@ -228,31 +297,47 @@ class DecompressorBZ2 : public DecompressorBase BZ2_bzDecompressEnd (&Stream); } - long Read (void *buffer, long len) override + ptrdiff_t Read (void *buffer, ptrdiff_t len) override { - int err; + if (File == nullptr) + { + DecompressionError("File not open"); + return 0; + } + if (len == 0) return 0; + + int err = BZ_OK; stupidGlobal = this; - Stream.next_out = (char *)buffer; - Stream.avail_out = len; - do + while (len > 0) { - err = BZ2_bzDecompress(&Stream); - if (Stream.avail_in == 0 && !SawEOF) + Stream.next_out = (char*)buffer; + unsigned rlen = (unsigned)std::min(len, 0x40000000); + Stream.avail_out = rlen; + buffer = Stream.next_out + rlen; + len -= rlen; + + do { - FillBuffer (); - } - } while (err == BZ_OK && Stream.avail_out != 0); + err = BZ2_bzDecompress(&Stream); + if (Stream.avail_in == 0 && !SawEOF) + { + FillBuffer(); + } + } while (err == BZ_OK && Stream.avail_out != 0); + } if (err != BZ_OK && err != BZ_STREAM_END) { DecompressionError ("Corrupt bzip2 stream"); + return 0; } if (Stream.avail_out != 0) { DecompressionError ("Ran out of data in bzip2 stream"); + return 0; } return len - Stream.avail_out; @@ -304,7 +389,7 @@ class DecompressorLZMA : public DecompressorBase { enum { BUFF_SIZE = 4096 }; - bool SawEOF; + bool SawEOF = false; CLzmaDec Stream; size_t Size; size_t InPos, InSize; @@ -313,26 +398,32 @@ class DecompressorLZMA : public DecompressorBase public: - DecompressorLZMA (FileReader *file, size_t uncompressed_size, const std::function& cb) - : SawEOF(false) + bool Open(FileReader *file, size_t uncompressed_size) { + if (File != nullptr) + { + DecompressionError("File already open"); + return false; + } + uint8_t header[4 + LZMA_PROPS_SIZE]; int err; File = file; - SetErrorCallback(cb); Size = uncompressed_size; OutProcessed = 0; // Read zip LZMA properties header - if (File->Read(header, sizeof(header)) < (long)sizeof(header)) + if (File->Read(header, sizeof(header)) < (ptrdiff_t)sizeof(header)) { DecompressionError("DecompressorLZMA: File too short\n"); + return false; } if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE) { DecompressionError("DecompressorLZMA: LZMA props size is %d (expected %d)\n", header[2] + header[3] * 256, LZMA_PROPS_SIZE); + return false; } FillBuffer(); @@ -343,9 +434,11 @@ class DecompressorLZMA : public DecompressorBase if (err != SZ_OK) { DecompressionError("DecompressorLZMA: LzmaDec_Allocate failed: %d\n", err); + return false; } LzmaDec_Init(&Stream); + return true; } ~DecompressorLZMA () @@ -353,8 +446,14 @@ class DecompressorLZMA : public DecompressorBase LzmaDec_Free(&Stream, &g_Alloc); } - long Read (void *buffer, long len) override + ptrdiff_t Read (void *buffer, ptrdiff_t len) override { + if (File == nullptr) + { + DecompressionError("File not open"); + return 0; + } + int err; Byte *next_out = (Byte *)buffer; @@ -373,12 +472,14 @@ class DecompressorLZMA : public DecompressorBase if (err != SZ_OK) { DecompressionError ("Corrupt LZMA stream"); + return 0; } if (in_processed == 0 && out_processed == 0) { if (status != LZMA_STATUS_FINISHED_WITH_MARK) { DecompressionError ("Corrupt LZMA stream"); + return 0; } } if (InSize == 0 && !SawEOF) @@ -390,11 +491,148 @@ class DecompressorLZMA : public DecompressorBase if (err != Z_OK && err != Z_STREAM_END) { DecompressionError ("Corrupt LZMA stream"); + return 0; } if (len != 0) { DecompressionError ("Ran out of data in LZMA stream"); + return 0; + } + + return (ptrdiff_t)(next_out - (Byte *)buffer); + } + + void FillBuffer () + { + auto numread = File->Read(InBuff, BUFF_SIZE); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + InPos = 0; + InSize = numread; + } + +}; + +//========================================================================== +// +// DecompressorXZ +// +// The XZ wrapper +// reads data from a XZ compressed stream +// +//========================================================================== + +// Wraps around a Decompressor to decompress a XZ stream +class DecompressorXZ : public DecompressorBase +{ + enum { BUFF_SIZE = 4096 }; + + bool SawEOF = false; + CXzUnpacker Stream; + size_t Size; + size_t InPos, InSize; + size_t OutProcessed; + uint8_t InBuff[BUFF_SIZE]; + +public: + + bool Open(FileReader *file, size_t uncompressed_size) + { + if (File != nullptr) + { + DecompressionError("File already open"); + return false; + } + + uint8_t header[12]; + File = file; + + Size = uncompressed_size; + OutProcessed = 0; + + // Read zip XZ properties header + if (File->Read(header, sizeof(header)) < (long)sizeof(header)) + { + DecompressionError("DecompressorXZ: File too short\n"); + return false; + } + + File->Seek(-(ptrdiff_t)sizeof(header), FileReader::SeekCur); + + FillBuffer(); + + XzUnpacker_Construct(&Stream, &g_Alloc); + XzUnpacker_Init(&Stream); + + return true; + } + + ~DecompressorXZ () + { + XzUnpacker_Free(&Stream); + } + + ptrdiff_t Read (void *buffer, ptrdiff_t len) override + { + if (File == nullptr) + { + DecompressionError("File not open"); + return 0; + } + + if (g_CrcTable[1] == 0) + { + CrcGenerateTable(); + } + + int err; + Byte *next_out = (Byte *)buffer; + + do + { + ECoderFinishMode finish_mode = CODER_FINISH_ANY; + ECoderStatus status; + size_t out_processed = len; + size_t in_processed = InSize; + + err = XzUnpacker_Code(&Stream, next_out, &out_processed, InBuff + InPos, &in_processed, SawEOF, finish_mode, &status); + InPos += in_processed; + InSize -= in_processed; + next_out += out_processed; + len = (long)(len - out_processed); + if (err != SZ_OK) + { + DecompressionError ("Corrupt XZ stream", err); + return 0; + } + if (in_processed == 0 && out_processed == 0) + { + if (status != CODER_STATUS_FINISHED_WITH_MARK) + { + DecompressionError ("Corrupt XZ stream"); + return 0; + } + } + if (InSize == 0 && !SawEOF) + { + FillBuffer (); + } + } while (err == SZ_OK && len != 0); + + if (err != Z_OK && err != Z_STREAM_END) + { + DecompressionError ("Corrupt XZ stream"); + return 0; + } + + if (len != 0) + { + DecompressionError ("Ran out of data in XZ stream"); + return 0; } return (long)(next_out - (Byte *)buffer); @@ -509,7 +747,7 @@ class DecompressorLZSS : public DecompressorBase // Partial overlap: Copy in 2 or 3 chunks. do { - unsigned int copy = min(len, pos+1); + unsigned int copy = std::min(len, pos+1); memcpy(Stream.InternalBuffer, copyStart, copy); Stream.InternalBuffer += copy; Stream.InternalOut += copy; @@ -541,27 +779,34 @@ class DecompressorLZSS : public DecompressorBase } public: - DecompressorLZSS(FileReader *file, const std::function& cb) : SawEOF(false) + bool Open(FileReader *file) { + if (File != nullptr) + { + DecompressionError("File already open"); + return false; + } + File = file; - SetErrorCallback(cb); Stream.State = STREAM_EMPTY; Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE; Stream.InternalOut = 0; Stream.AvailIn = 0; FillBuffer(); + return true; } ~DecompressorLZSS() { } - long Read(void *buffer, long len) override + ptrdiff_t Read(void *buffer, ptrdiff_t len) override { + if (len > 0xffffffff) len = 0xffffffff; // this format cannot be larger than 4GB. uint8_t *Out = (uint8_t*)buffer; - long AvailOut = len; + ptrdiff_t AvailOut = len; do { @@ -575,7 +820,7 @@ class DecompressorLZSS : public DecompressorBase break; } - unsigned int copy = min(Stream.InternalOut, AvailOut); + unsigned int copy = (unsigned)std::min(Stream.InternalOut, AvailOut); if(copy > 0) { memcpy(Out, Stream.WindowData, copy); @@ -600,55 +845,182 @@ class DecompressorLZSS : public DecompressorBase while(AvailOut && Stream.State != STREAM_FINAL); assert(AvailOut == 0); - return (long)(Out - (uint8_t*)buffer); + return (ptrdiff_t)(Out - (uint8_t*)buffer); } }; -bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function& cb) +bool OpenDecompressor(FileReader& self, FileReader &parent, FileReader::Size length, int method, int flags) { - DecompressorBase *dec = nullptr; - FileReader *p = &parent; - switch (method & ~METHOD_TRANSFEROWNER) + FileReaderInterface* fr = nullptr; + DecompressorBase* dec = nullptr; + try { + FileReader* p = &parent; + bool exceptions = !!(flags & DCF_EXCEPTIONS); + + switch (method) + { case METHOD_DEFLATE: case METHOD_ZLIB: - dec = new DecompressorZ(p, method == METHOD_DEFLATE, cb); + { + auto idec = new DecompressorZ; + fr = dec = idec; + idec->EnableExceptions(exceptions); + if (!idec->Open(p, method == METHOD_DEFLATE)) + { + delete idec; + return false; + } break; - + } case METHOD_BZIP2: - dec = new DecompressorBZ2(p, cb); + { + auto idec = new DecompressorBZ2; + fr = dec = idec; + idec->EnableExceptions(exceptions); + if (!idec->Open(p)) + { + delete idec; + return false; + } break; - + } case METHOD_LZMA: - dec = new DecompressorLZMA(p, length, cb); + { + auto idec = new DecompressorLZMA; + fr = dec = idec; + idec->EnableExceptions(exceptions); + if (!idec->Open(p, length)) + { + delete idec; + return false; + } break; - + } + case METHOD_XZ: + { + auto idec = new DecompressorXZ; + fr = dec = idec; + idec->EnableExceptions(exceptions); + if (!idec->Open(p, length)) + { + delete idec; + return false; + } + break; + } case METHOD_LZSS: - dec = new DecompressorLZSS(p, cb); + { + auto idec = new DecompressorLZSS; + fr = dec = idec; + idec->EnableExceptions(exceptions); + if (!idec->Open(p)) + { + delete idec; + return false; + } + break; + } + + // The decoders for these legacy formats can only handle the full data in one go so we have to perform the entire decompression here. + case METHOD_IMPLODE_0: + case METHOD_IMPLODE_2: + case METHOD_IMPLODE_4: + case METHOD_IMPLODE_6: + { + FileData buffer(nullptr, length); + FZipExploder exploder; + if (exploder.Explode(buffer.writable(), (unsigned)length, *p, (unsigned)p->GetLength(), method - METHOD_IMPLODE_MIN) == -1) + { + if (exceptions) + { + throw FileSystemException("DecompressImplode failed"); + } + return false; + } + fr = new MemoryArrayReader(buffer); + flags &= ~(DCF_SEEKABLE | DCF_CACHED); break; + } + + case METHOD_SHRINK: + { + FileData buffer(nullptr, length); + ShrinkLoop(buffer.writable(), (unsigned)length, *p, (unsigned)p->GetLength()); // this never fails. + fr = new MemoryArrayReader(buffer); + flags &= ~(DCF_SEEKABLE | DCF_CACHED); + break; + } + + // While this could be made a buffering reader it isn't worth the effort because only stock RFFs are encrypted and they do not contain large files. + case METHOD_RFFCRYPT: + { + FileData buffer = p->Read(length); + auto bufr = buffer.writable(); + FileReader::Size cryptlen = std::min(length, 256); + + for (FileReader::Size i = 0; i < cryptlen; ++i) + { + bufr[i] ^= i >> 1; + } + fr = new MemoryArrayReader(buffer); + flags &= ~(DCF_SEEKABLE | DCF_CACHED); + break; + } - // todo: METHOD_IMPLODE, METHOD_SHRINK default: return false; - } - if (method & METHOD_TRANSFEROWNER) + } + if (dec) + { + if (flags & DCF_TRANSFEROWNER) + { + dec->SetOwnsReader(); + } + dec->Length = length; + } + if ((flags & (DCF_CACHED| DCF_SEEKABLE))) // the buffering reader does not seem to be stable, so cache it instead until we find out what's wrong. + { + // read everything into a MemoryArrayReader. + FileData data(nullptr, length); + fr->Read(data.writable(), length); + delete fr; + fr = new MemoryArrayReader(data); + } + else if ((flags & DCF_SEEKABLE)) + { + // create a wrapper that can buffer the content so that seeking is possible + fr = new BufferingReader(fr); + } + self = FileReader(fr); + return true; + } + catch (...) { - dec->SetOwnsReader(); + if (fr) delete fr; + throw; } +} - dec->Length = (long)length; - if (!seekable) + +bool FCompressedBuffer::Decompress(char* destbuffer) +{ + if (mMethod == METHOD_STORED) { - Close(); - mReader = dec; + memcpy(destbuffer, mBuffer, mSize); return true; } else { - // todo: create a wrapper. for now this fails - delete dec; - return false; + FileReader mr; + mr.OpenMemory(mBuffer, mCompressedSize); + FileReader frz; + if (OpenDecompressor(frz, mr, mSize, mMethod)) + { + return frz.Read(destbuffer, mSize) != mSize; + } } + return false; } - +} \ No newline at end of file diff --git a/src/common/filesystem/source/files_internal.h b/src/common/filesystem/source/files_internal.h new file mode 100644 index 0000000000..08f4865994 --- /dev/null +++ b/src/common/filesystem/source/files_internal.h @@ -0,0 +1,92 @@ +#pragma once + +#include +#include "fs_files.h" + +namespace FileSys { + +class MemoryReader : public FileReaderInterface +{ +protected: + const char * bufptr = nullptr; + ptrdiff_t FilePos = 0; + + MemoryReader() + {} + +public: + MemoryReader(const char *buffer, ptrdiff_t length) + { + bufptr = buffer; + Length = length; + FilePos = 0; + } + + ptrdiff_t Tell() const override; + ptrdiff_t Seek(ptrdiff_t offset, int origin) override; + ptrdiff_t Read(void *buffer, ptrdiff_t len) override; + char *Gets(char *strbuf, ptrdiff_t len) override; + virtual const char *GetBuffer() const override { return bufptr; } +}; + +class BufferingReader : public MemoryReader +{ + FileData buf; + std::unique_ptr baseReader; + ptrdiff_t bufferpos = 0; + + int FillBuffer(ptrdiff_t newpos); +public: + BufferingReader(FileReaderInterface* base) + : baseReader(base) + { + Length = base->Length; + buf.allocate(Length); + bufptr = (const char*)buf.data(); + } + + ptrdiff_t Seek(ptrdiff_t offset, int origin) override; + ptrdiff_t Read(void* buffer, ptrdiff_t len) override; + char* Gets(char* strbuf, ptrdiff_t len) override; +}; + +//========================================================================== +// +// MemoryArrayReader +// +// reads data from an array of memory +// +//========================================================================== + +class MemoryArrayReader : public MemoryReader +{ + FileData buf; + +public: + MemoryArrayReader() + { + FilePos = 0; + Length = 0; + } + + MemoryArrayReader(size_t len) + { + buf.allocate(len); + UpdateBuffer(); + } + + MemoryArrayReader(FileData& buffer) + { + buf = std::move(buffer); + UpdateBuffer(); + } + + void UpdateBuffer() + { + bufptr = (const char*)buf.data(); + FilePos = 0; + Length = buf.size(); + } +}; + +} diff --git a/src/common/filesystem/filesystem.cpp b/src/common/filesystem/source/filesystem.cpp similarity index 59% rename from src/common/filesystem/filesystem.cpp rename to src/common/filesystem/source/filesystem.cpp index 6b60e8e68d..fee5f10114 100644 --- a/src/common/filesystem/filesystem.cpp +++ b/src/common/filesystem/source/filesystem.cpp @@ -36,112 +36,151 @@ // HEADER FILES ------------------------------------------------------------ +#include #include #include #include +#include -#include "m_argv.h" -#include "cmdlib.h" -#include "filesystem.h" -#include "m_crc32.h" -#include "printf.h" -#include "md5.h" +#include "resourcefile.h" +#include "fs_filesystem.h" +#include "fs_findfile.h" +#include "md5.hpp" +#include "fs_stringpool.h" +namespace FileSys { + // MACROS ------------------------------------------------------------------ #define NULL_INDEX (0xffffffff) +static void UpperCopy(char* to, const char* from) +{ + int i; + + for (i = 0; i < 8 && from[i]; i++) + to[i] = toupper(from[i]); + for (; i < 8; i++) + to[i] = 0; +} + + +//djb2 +static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX) +{ + uint32_t hash = 5381; + uint32_t c; + while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32); + return hash; +} + +static void md5Hash(FileReader& reader, uint8_t* digest) +{ + using namespace md5; + + md5_state_t state; + md5_init(&state); + md5_byte_t buffer[4096]; + while (auto len = reader.Read(buffer, 4096)) + { + md5_append(&state, buffer, len); + } + md5_finish(&state, digest); +} + struct FileSystem::LumpRecord { - FResourceLump *lump; - FGameTexture* linkedTexture; + FResourceFile *resfile; LumpShortName shortName; - FString longName; - int rfnum; - int Namespace; + const char* LongName; + int resindex; + int16_t rfnum; // this is not necessarily the same as resfile's index! + int16_t Namespace; int resourceId; int flags; - void SetFromLump(int filenum, FResourceLump* lmp) + void SetFromLump(FResourceFile* file, int fileindex, int filenum, StringPool* sp, const char* name = nullptr) { - lump = lmp; + resfile = file; + resindex = fileindex; rfnum = filenum; - linkedTexture = nullptr; flags = 0; - if (lump->Flags & LUMPF_SHORTNAME) + auto lflags = file->GetEntryFlags(fileindex); + if (!name) name = file->getName(fileindex); + if (lflags & RESFF_SHORTNAME) { - uppercopy(shortName.String, lump->getName()); + UpperCopy(shortName.String, name); shortName.String[8] = 0; - longName = ""; - Namespace = lump->GetNamespace(); + LongName = ""; + Namespace = file->GetEntryNamespace(fileindex); resourceId = -1; } - else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName()) + else if ((lflags & RESFF_EMBEDDED) || !name || !*name) { shortName.qword = 0; - longName = ""; + LongName = ""; Namespace = ns_hidden; resourceId = -1; } else { - longName = lump->getName(); - resourceId = lump->GetIndexNum(); + LongName = name; + resourceId = file->GetEntryResourceID(fileindex); // Map some directories to WAD namespaces. // Note that some of these namespaces don't exist in WADS. // CheckNumForName will handle any request for these namespaces accordingly. - Namespace = !strncmp(longName.GetChars(), "flats/", 6) ? ns_flats : - !strncmp(longName.GetChars(), "textures/", 9) ? ns_newtextures : - !strncmp(longName.GetChars(), "hires/", 6) ? ns_hires : - !strncmp(longName.GetChars(), "sprites/", 8) ? ns_sprites : - !strncmp(longName.GetChars(), "voxels/", 7) ? ns_voxels : - !strncmp(longName.GetChars(), "colormaps/", 10) ? ns_colormaps : - !strncmp(longName.GetChars(), "acs/", 4) ? ns_acslibrary : - !strncmp(longName.GetChars(), "voices/", 7) ? ns_strifevoices : - !strncmp(longName.GetChars(), "patches/", 8) ? ns_patches : - !strncmp(longName.GetChars(), "graphics/", 9) ? ns_graphics : - !strncmp(longName.GetChars(), "sounds/", 7) ? ns_sounds : - !strncmp(longName.GetChars(), "music/", 6) ? ns_music : - !strchr(longName.GetChars(), '/') ? ns_global : + Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats : + !strncmp(LongName, "textures/", 9) ? ns_newtextures : + !strncmp(LongName, "hires/", 6) ? ns_hires : + !strncmp(LongName, "sprites/", 8) ? ns_sprites : + !strncmp(LongName, "voxels/", 7) ? ns_voxels : + !strncmp(LongName, "colormaps/", 10) ? ns_colormaps : + !strncmp(LongName, "acs/", 4) ? ns_acslibrary : + !strncmp(LongName, "voices/", 7) ? ns_strifevoices : + !strncmp(LongName, "patches/", 8) ? ns_patches : + !strncmp(LongName, "graphics/", 9) ? ns_graphics : + !strncmp(LongName, "sounds/", 7) ? ns_sounds : + !strncmp(LongName, "music/", 6) ? ns_music : + !strchr(LongName, '/') ? ns_global : ns_hidden; if (Namespace == ns_hidden) shortName.qword = 0; - else + else if (strstr(LongName, ".{")) { - ptrdiff_t encodedResID = longName.LastIndexOf(".{"); - if (resourceId == -1 && encodedResID >= 0) + std::string longName = LongName; + ptrdiff_t encodedResID = longName.find_last_of(".{"); + if (resourceId == -1 && (size_t)encodedResID != std::string::npos) { - const char* p = longName.GetChars() + encodedResID; + const char* p = LongName + encodedResID; char* q; - int id = (int)strtoull(p+2, &q, 10); // only decimal numbers allowed here. + int id = (int)strtoull(p + 2, &q, 10); // only decimal numbers allowed here. if (q[0] == '}' && (q[1] == '.' || q[1] == 0)) { - FString toDelete(p, q - p + 1); - longName.Substitute(toDelete, ""); + longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1); resourceId = id; } + LongName = sp->Strdup(longName.c_str()); } - ptrdiff_t slash = longName.LastIndexOf('/'); - FString base = (slash >= 0) ? longName.Mid(slash + 1) : longName; - auto dot = base.LastIndexOf('.'); - if (dot >= 0) base.Truncate(dot); - uppercopy(shortName.String, base); - shortName.String[8] = 0; - - // Since '\' can't be used as a file name's part inside a ZIP - // we have to work around this for sprites because it is a valid - // frame character. - if (Namespace == ns_sprites || Namespace == ns_voxels || Namespace == ns_hires) - { - char* c; + } + auto slash = strrchr(LongName, '/'); + std::string base = slash ? (slash + 1) : LongName; + auto dot = base.find_last_of('.'); + if (dot != std::string::npos) base.resize(dot); + UpperCopy(shortName.String, base.c_str()); + + // Since '\' can't be used as a file name's part inside a ZIP + // we have to work around this for sprites because it is a valid + // frame character. + if (Namespace == ns_sprites || Namespace == ns_voxels || Namespace == ns_hires) + { + char* c; - while ((c = (char*)memchr(shortName.String, '^', 8))) - { - *c = '\\'; - } + while ((c = (char*)memchr(shortName.String, '^', 8))) + { + *c = '\\'; } } } @@ -152,17 +191,14 @@ struct FileSystem::LumpRecord // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- -static void PrintLastError (); +static void PrintLastError (FileSystemMessageFunc Printf); // PUBLIC DATA DEFINITIONS ------------------------------------------------- -FileSystem fileSystem; - // CODE -------------------------------------------------------------------- FileSystem::FileSystem() { - // This is needed to initialize the LumpRecord array, which depends on data only available here. } FileSystem::~FileSystem () @@ -172,20 +208,17 @@ FileSystem::~FileSystem () void FileSystem::DeleteAll () { - Hashes.Clear(); + Hashes.clear(); NumEntries = 0; - // explicitly delete all manually added lumps. - for (auto &frec : FileInfo) - { - if (frec.rfnum == -1) delete frec.lump; - } - FileInfo.Clear(); - for (int i = Files.Size() - 1; i >= 0; --i) + FileInfo.clear(); + for (int i = (int)Files.size() - 1; i >= 0; --i) { delete Files[i]; } - Files.Clear(); + Files.clear(); + if (stringpool != nullptr) delete stringpool; + stringpool = nullptr; } //========================================================================== @@ -199,85 +232,61 @@ void FileSystem::DeleteAll () // //========================================================================== -void FileSystem::InitSingleFile(const char* filename, bool quiet) +bool FileSystem::InitSingleFile(const char* filename, FileSystemMessageFunc Printf) { - TArray filenames; - filenames.Push(filename); - InitMultipleFiles(filenames, true); + std::vector filenames = { filename }; + return InitMultipleFiles(filenames, nullptr, Printf); } -void FileSystem::InitMultipleFiles (TArray &filenames, bool quiet, LumpFilterInfo* filter, bool allowduplicates, FILE* hashfile) +bool FileSystem::InitMultipleFiles (std::vector& filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates, FILE* hashfile) { int numfiles; + // the first call here will designate a main thread which may use shared file readers. All other thewads have to open new file handles. + SetMainThread(); // open all the files, load headers, and count lumps DeleteAll(); numfiles = 0; + stringpool = new StringPool(true); + stringpool->shared = true; // will be used by all owned resource files. + // first, check for duplicates - if (allowduplicates) + if (!allowduplicates) { - for (unsigned i=0;iGetHash().GetChars()); - MoveLumpsInFolder(path); + std::string path = "filter/%s"; + path += Files.back()->GetHash(); + MoveLumpsInFolder(path.c_str()); } - NumEntries = FileInfo.Size(); + NumEntries = (uint32_t)FileInfo.size(); if (NumEntries == 0) { - if (!quiet) I_FatalError("W_InitMultipleFiles: no files found"); - else return; + return false; } if (filter && filter->postprocessFunc) filter->postprocessFunc(); // [RH] Set up hash table InitHashChains (); -} - -//========================================================================== -// -// AddLump -// -// Adds a given lump to the directory. Does not perform rehashing -// -//========================================================================== - -void FileSystem::AddLump(FResourceLump *lump) -{ - FileSystem::LumpRecord *lumprec = &FileInfo[FileInfo.Reserve(1)]; - lumprec->SetFromLump(-1, lump); -} - -//----------------------------------------------------------------------- -// -// Adds an external file to the lump list but not to the hash chains -// It's just a simple means to assign a lump number to some file so that -// the texture manager can read from it. -// -//----------------------------------------------------------------------- - -int FileSystem::AddExternalFile(const char *filename) -{ - FResourceLump *lump = new FExternalLump(filename); - AddLump(lump); - return FileInfo.Size() - 1; // later + return true; } //========================================================================== @@ -288,14 +297,24 @@ int FileSystem::AddExternalFile(const char *filename) // //========================================================================== -int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags) +int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, int flags) { - FStringf fullname("%s.%s", name, type); - auto newlump = new FMemoryLump(data, size); - newlump->LumpNameSetup(fullname); - AddLump(newlump); - FileInfo.Last().resourceId = id; - return FileInfo.Size()-1; + FileReader fr; + FileData blob(data, size); + fr.OpenMemoryArray(blob); + + // wrap this into a single lump resource file (should be done a little better later.) + auto rf = new FResourceFile(name, fr, stringpool); + auto Entries = rf->AllocateEntries(1); + Entries[0].FileName = rf->NormalizeFileName(ExtractBaseName(name, true).c_str()); + Entries[0].ResourceID = -1; + Entries[0].Length = size; + + Files.push_back(rf); + FileInfo.resize(FileInfo.size() + 1); + FileSystem::LumpRecord* lump_p = &FileInfo.back(); + lump_p->SetFromLump(rf, 0, (int)Files.size() - 1, stringpool); + return (int)FileInfo.size() - 1; } //========================================================================== @@ -308,7 +327,7 @@ int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, in // [RH] Removed reload hack //========================================================================== -void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, LumpFilterInfo* filter, FILE* hashfile) +void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile) { int startlump; bool isdir = false; @@ -317,12 +336,12 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L if (filer == nullptr) { // Does this exist? If so, is it a directory? - if (!DirEntryExists(filename, &isdir)) + if (!FS_DirEntryExists(filename, &isdir)) { - if (!quiet) + if (Printf) { - Printf(TEXTCOLOR_RED "%s: File or Directory not found\n", filename); - PrintLastError(); + Printf(FSMessageLevel::Error, "%s: File or Directory not found\n", filename); + PrintLastError(Printf); } return; } @@ -331,10 +350,10 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L { if (!filereader.OpenFile(filename)) { // Didn't find file - if (!quiet) + if (Printf) { - Printf(TEXTCOLOR_RED "%s: File not found\n", filename); - PrintLastError(); + Printf(FSMessageLevel::Error, "%s: File not found\n", filename); + PrintLastError(Printf); } return; } @@ -342,45 +361,46 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L } else filereader = std::move(*filer); - if (!batchrun && !quiet) Printf (" adding %s", filename); startlump = NumEntries; FResourceFile *resfile; + if (!isdir) - resfile = FResourceFile::OpenResourceFile(filename, filereader, quiet, false, filter); + resfile = FResourceFile::OpenResourceFile(filename, filereader, false, filter, Printf, stringpool); else - resfile = FResourceFile::OpenDirectory(filename, quiet, filter); + resfile = FResourceFile::OpenDirectory(filename, filter, Printf, stringpool); if (resfile != NULL) { - if (!quiet && !batchrun) Printf(", %d lumps\n", resfile->LumpCount()); + if (Printf) + Printf(FSMessageLevel::Message, "adding %s, %d lumps\n", filename, resfile->EntryCount()); - uint32_t lumpstart = FileInfo.Size(); + uint32_t lumpstart = (uint32_t)FileInfo.size(); resfile->SetFirstLump(lumpstart); - for (uint32_t i=0; i < resfile->LumpCount(); i++) + Files.push_back(resfile); + for (int i = 0; i < resfile->EntryCount(); i++) { - FResourceLump *lump = resfile->GetLump(i); - FileSystem::LumpRecord *lump_p = &FileInfo[FileInfo.Reserve(1)]; - lump_p->SetFromLump(Files.Size(), lump); + FileInfo.resize(FileInfo.size() + 1); + FileSystem::LumpRecord* lump_p = &FileInfo.back(); + lump_p->SetFromLump(resfile, i, (int)Files.size() - 1, stringpool); } - Files.Push(resfile); - - for (uint32_t i=0; i < resfile->LumpCount(); i++) + for (int i = 0; i < resfile->EntryCount(); i++) { - FResourceLump *lump = resfile->GetLump(i); - if (lump->Flags & LUMPF_EMBEDDED) + int flags = resfile->GetEntryFlags(i); + if (flags & RESFF_EMBEDDED) { - FString path; - path.Format("%s:%s", filename, lump->getName()); - auto embedded = lump->NewReader(); - AddFile(path, &embedded, quiet, filter, hashfile); + std::string path = filename; + path += ':'; + path += resfile->getName(i); + auto embedded = resfile->GetEntryReader(i, READER_CACHED); + AddFile(path.c_str(), &embedded, filter, Printf, hashfile); } } - if (hashfile && !quiet) + if (hashfile) { uint8_t cksum[16]; char cksumout[33]; @@ -388,39 +408,34 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L if (filereader.isOpen()) { - MD5Context md5; filereader.Seek(0, FileReader::SeekSet); - md5Update(filereader, md5, (unsigned)filereader.GetLength()); - md5.Final(cksum); + md5Hash(filereader, cksum); for (size_t j = 0; j < sizeof(cksum); ++j) { snprintf(cksumout + (j * 2), 3, "%02X", cksum[j]); } - fprintf(hashfile, "file: %s, hash: %s, size: %d\n", filename, cksumout, (int)filereader.GetLength()); + fprintf(hashfile, "file: %s, hash: %s, size: %td\n", filename, cksumout, filereader.GetLength()); } else fprintf(hashfile, "file: %s, Directory structure\n", filename); - for (uint32_t i = 0; i < resfile->LumpCount(); i++) + for (int i = 0; i < resfile->EntryCount(); i++) { - FResourceLump *lump = resfile->GetLump(i); - - if (!(lump->Flags & LUMPF_EMBEDDED)) + int flags = resfile->GetEntryFlags(i); + if (!(flags & RESFF_EMBEDDED)) { - MD5Context md5; - auto reader = lump->NewReader(); - md5Update(reader, md5, lump->LumpSize); - md5.Final(cksum); + auto reader = resfile->GetEntryReader(i, READER_SHARED, 0); + md5Hash(filereader, cksum); for (size_t j = 0; j < sizeof(cksum); ++j) { snprintf(cksumout + (j * 2), 3, "%02X", cksum[j]); } - fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %d\n", filename, lump->getName(), cksumout, lump->LumpSize); + fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %zu\n", filename, resfile->getName(i), cksumout, (uint64_t)resfile->Length(i)); } } } @@ -445,7 +460,7 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept if (strrchr (name, '/') != NULL) { - for (i = 0; i < Files.Size(); ++i) + for (i = 0; i < (unsigned)Files.size(); ++i) { if (stricmp (GetResourceFileFullName (i), name) == 0) { @@ -455,10 +470,10 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept } else { - for (i = 0; i < Files.Size(); ++i) + for (i = 0; i < (unsigned)Files.size(); ++i) { - auto pth = ExtractFileBase(GetResourceFileName(i), true); - if (stricmp (pth.GetChars(), name) == 0) + auto pth = ExtractBaseName(GetResourceFileName(i), true); + if (stricmp (pth.c_str(), name) == 0) { return i; } @@ -478,7 +493,7 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept // and namespace parameter //========================================================================== -int FileSystem::CheckNumForName (const char *name, int space) +int FileSystem::CheckNumForName (const char *name, int space) const { union { @@ -499,8 +514,8 @@ int FileSystem::CheckNumForName (const char *name, int space) return -1; } - uppercopy (uname, name); - i = FirstLumpIndex[LumpNameHash (uname) % NumEntries]; + UpperCopy (uname, name); + i = FirstLumpIndex[MakeHash(uname, 8) % NumEntries]; while (i != NULL_INDEX) { @@ -514,8 +529,9 @@ int FileSystem::CheckNumForName (const char *name, int space) // If we find a lump with this name in the global namespace that does not come // from a Zip return that. WADs don't know these namespaces and single lumps must // work as well. + auto lflags = lump.resfile->GetEntryFlags(lump.resindex); if (space > ns_specialzipdirectory && lump.Namespace == ns_global && - !((lump.lump->Flags ^lump.flags) & LUMPF_FULLPATH)) break; + !((lflags ^lump.flags) & RESFF_FULLPATH)) break; } i = NextLumpIndex[i]; } @@ -523,7 +539,7 @@ int FileSystem::CheckNumForName (const char *name, int space) return i != NULL_INDEX ? i : -1; } -int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool exact) +int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool exact) const { union { @@ -537,8 +553,8 @@ int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool ex return CheckNumForName (name, space); } - uppercopy (uname, name); - i = FirstLumpIndex[LumpNameHash (uname) % NumEntries]; + UpperCopy (uname, name); + i = FirstLumpIndex[MakeHash (uname, 8) % NumEntries]; // If exact is true if will only find lumps in the same WAD, otherwise // also those in earlier WADs. @@ -561,14 +577,14 @@ int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool ex // //========================================================================== -int FileSystem::GetNumForName (const char *name, int space) +int FileSystem::GetNumForName (const char *name, int space) const { int i; i = CheckNumForName (name, space); if (i == -1) - I_Error ("GetNumForName: %s not found!", name); + throw FileSystemException("GetNumForName: %s not found!", name); return i; } @@ -584,7 +600,7 @@ int FileSystem::GetNumForName (const char *name, int space) // //========================================================================== -int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int namespc, bool ignoreext) +int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int namespc, bool ignoreext) const { uint32_t i; @@ -597,14 +613,14 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names uint32_t *nli = ignoreext ? NextLumpIndex_NoExt : NextLumpIndex_FullName; auto len = strlen(name); - for (i = fli[MakeKey(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) + for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) { - if (strnicmp(name, FileInfo[i].longName, len)) continue; - if (FileInfo[i].longName[len] == 0) break; // this is a full match - if (ignoreext && FileInfo[i].longName[len] == '.') + if (strnicmp(name, FileInfo[i].LongName, len)) continue; + if (FileInfo[i].LongName[len] == 0) break; // this is a full match + if (ignoreext && FileInfo[i].LongName[len] == '.') { // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? - if (strpbrk(FileInfo[i].longName.GetChars() + len + 1, "./") == nullptr) break; + if (strpbrk(FileInfo[i].LongName + len + 1, "./") == nullptr) break; } } @@ -617,7 +633,7 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names return -1; } -int FileSystem::CheckNumForFullName (const char *name, int rfnum) +int FileSystem::CheckNumForFullName (const char *name, int rfnum) const { uint32_t i; @@ -626,10 +642,10 @@ int FileSystem::CheckNumForFullName (const char *name, int rfnum) return CheckNumForFullName (name); } - i = FirstLumpIndex_FullName[MakeKey (name) % NumEntries]; + i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries]; while (i != NULL_INDEX && - (stricmp(name, FileInfo[i].longName) || FileInfo[i].rfnum != rfnum)) + (stricmp(name, FileInfo[i].LongName) || FileInfo[i].rfnum != rfnum)) { i = NextLumpIndex_FullName[i]; } @@ -645,14 +661,14 @@ int FileSystem::CheckNumForFullName (const char *name, int rfnum) // //========================================================================== -int FileSystem::GetNumForFullName (const char *name) +int FileSystem::GetNumForFullName (const char *name) const { int i; i = CheckNumForFullName (name); if (i == -1) - I_Error ("GetNumForFullName: %s not found!", name); + throw FileSystemException("GetNumForFullName: %s not found!", name); return i; } @@ -665,7 +681,7 @@ int FileSystem::GetNumForFullName (const char *name) // //========================================================================== -int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts, int count) +int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts, int count) const { uint32_t i; @@ -678,12 +694,12 @@ int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts uint32_t* nli = NextLumpIndex_NoExt; auto len = strlen(name); - for (i = fli[MakeKey(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) + for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) { - if (strnicmp(name, FileInfo[i].longName, len)) continue; - if (FileInfo[i].longName[len] != '.') continue; // we are looking for extensions but this file doesn't have one. + if (strnicmp(name, FileInfo[i].LongName, len)) continue; + if (FileInfo[i].LongName[len] != '.') continue; // we are looking for extensions but this file doesn't have one. - auto cp = FileInfo[i].longName.GetChars() + len + 1; + auto cp = FileInfo[i].LongName + len + 1; // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry. @@ -719,7 +735,7 @@ int FileSystem::FindResource (int resid, const char *type, int filenum) const no { if (filenum > 0 && FileInfo[i].rfnum != filenum) continue; if (FileInfo[i].resourceId != resid) continue; - auto extp = strrchr(FileInfo[i].longName, '.'); + auto extp = strrchr(FileInfo[i].LongName, '.'); if (!extp) continue; if (!stricmp(extp + 1, type)) return i; } @@ -742,40 +758,11 @@ int FileSystem::GetResource (int resid, const char *type, int filenum) const if (i == -1) { - I_Error("GetResource: %d of type %s not found!", resid, type); + throw FileSystemException("GetResource: %d of type %s not found!", resid, type); } return i; } -//========================================================================== -// -// link a texture with a given lump -// -//========================================================================== - -void FileSystem::SetLinkedTexture(int lump, FGameTexture *tex) -{ - if ((size_t)lump < NumEntries) - { - FileInfo[lump].linkedTexture = tex; - } -} - -//========================================================================== -// -// retrieve linked texture -// -//========================================================================== - -FGameTexture *FileSystem::GetLinkedTexture(int lump) -{ - if ((size_t)lump < NumEntries) - { - return FileInfo[lump].linkedTexture; - } - return NULL; -} - //========================================================================== // // FileLength @@ -784,31 +771,14 @@ FGameTexture *FileSystem::GetLinkedTexture(int lump) // //========================================================================== -int FileSystem::FileLength (int lump) const +ptrdiff_t FileSystem::FileLength (int lump) const { if ((size_t)lump >= NumEntries) { return -1; } - return FileInfo[lump].lump->LumpSize; -} - -//========================================================================== -// -// GetFileOffset -// -// Returns the offset from the beginning of the file to the lump. -// Returns -1 if the lump is compressed or can't be read directly -// -//========================================================================== - -int FileSystem::GetFileOffset (int lump) -{ - if ((size_t)lump >= NumEntries) - { - return -1; - } - return FileInfo[lump].lump->GetFileOffset(); + const auto &lump_p = FileInfo[lump]; + return (int)lump_p.resfile->Length(lump_p.resindex); } //========================================================================== @@ -824,32 +794,8 @@ int FileSystem::GetFileFlags (int lump) return 0; } - return FileInfo[lump].lump->Flags ^ FileInfo[lump].flags; -} - -//========================================================================== -// -// LumpNameHash -// -// NOTE: s should already be uppercase, in contrast to the BOOM version. -// -// Hash function used for lump names. -// Must be mod'ed with table size. -// Can be used for any 8-character names. -// -//========================================================================== - -uint32_t FileSystem::LumpNameHash (const char *s) -{ - const uint32_t *table = GetCRCTable (); - uint32_t hash = 0xffffffff; - int i; - - for (i = 8; i > 0 && *s; --i, ++s) - { - hash = CRC1 (hash, *s, table); - } - return hash ^ 0xffffffff; + const auto& lump_p = FileInfo[lump]; + return lump_p.resfile->GetEntryFlags(lump_p.resindex) ^ lump_p.flags; } //========================================================================== @@ -865,10 +811,10 @@ void FileSystem::InitHashChains (void) { unsigned int i, j; - NumEntries = FileInfo.Size(); - Hashes.Resize(8 * NumEntries); + NumEntries = (uint32_t)FileInfo.size(); + Hashes.resize(8 * NumEntries); // Mark all buckets as empty - memset(Hashes.Data(), -1, Hashes.Size() * sizeof(Hashes[0])); + memset(Hashes.data(), -1, Hashes.size() * sizeof(Hashes[0])); FirstLumpIndex = &Hashes[0]; NextLumpIndex = &Hashes[NumEntries]; FirstLumpIndex_FullName = &Hashes[NumEntries * 2]; @@ -882,23 +828,23 @@ void FileSystem::InitHashChains (void) // Now set up the chains for (i = 0; i < (unsigned)NumEntries; i++) { - j = LumpNameHash (FileInfo[i].shortName.String) % NumEntries; + j = MakeHash (FileInfo[i].shortName.String, 8) % NumEntries; NextLumpIndex[i] = FirstLumpIndex[j]; FirstLumpIndex[j] = i; // Do the same for the full paths - if (FileInfo[i].longName.IsNotEmpty()) + if (FileInfo[i].LongName[0] != 0) { - j = MakeKey(FileInfo[i].longName) % NumEntries; + j = MakeHash(FileInfo[i].LongName) % NumEntries; NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j]; FirstLumpIndex_FullName[j] = i; - FString nameNoExt = FileInfo[i].longName; - auto dot = nameNoExt.LastIndexOf('.'); - auto slash = nameNoExt.LastIndexOf('/'); - if (dot > slash) nameNoExt.Truncate(dot); + std::string nameNoExt = FileInfo[i].LongName; + auto dot = nameNoExt.find_last_of('.'); + auto slash = nameNoExt.find_last_of('/'); + if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot); - j = MakeKey(nameNoExt) % NumEntries; + j = MakeHash(nameNoExt.c_str()) % NumEntries; NextLumpIndex_NoExt[i] = FirstLumpIndex_NoExt[j]; FirstLumpIndex_NoExt[j] = i; @@ -908,8 +854,8 @@ void FileSystem::InitHashChains (void) } } - FileInfo.ShrinkToFit(); - Files.ShrinkToFit(); + FileInfo.shrink_to_fit(); + Files.shrink_to_fit(); } //========================================================================== @@ -921,20 +867,14 @@ void FileSystem::InitHashChains (void) LumpShortName& FileSystem::GetShortName(int i) { - if ((unsigned)i >= NumEntries) I_Error("GetShortName: Invalid index"); + if ((unsigned)i >= NumEntries) throw FileSystemException("GetShortName: Invalid index"); return FileInfo[i].shortName; } -FString& FileSystem::GetLongName(int i) -{ - if ((unsigned)i >= NumEntries) I_Error("GetLongName: Invalid index"); - return FileInfo[i].longName; -} - void FileSystem::RenameFile(int num, const char* newfn) { - if ((unsigned)num >= NumEntries) I_Error("RenameFile: Invalid index"); - FileInfo[num].longName = newfn; + if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index"); + FileInfo[num].LongName = stringpool->Strdup(newfn); // This does not alter the short name - call GetShortname to do that! } @@ -951,30 +891,29 @@ void FileSystem::RenameFile(int num, const char* newfn) // //========================================================================== -static FResourceLump placeholderLump; - void FileSystem::MoveLumpsInFolder(const char *path) { - if (FileInfo.Size() == 0) + if (FileInfo.size() == 0) { return; } auto len = strlen(path); - auto rfnum = FileInfo.Last().rfnum; + auto rfnum = FileInfo.back().rfnum; - unsigned i; - for (i = 0; i < FileInfo.Size(); i++) + size_t i; + for (i = 0; i < FileInfo.size(); i++) { auto& li = FileInfo[i]; if (li.rfnum >= GetIwadNum()) break; - if (li.longName.Left(len).CompareNoCase(path) == 0) + if (strnicmp(li.LongName, path, len) == 0) { - FileInfo.Push(li); - li.lump = &placeholderLump; // Make the old entry point to something empty. We cannot delete the lump record here because it'd require adjustment of all indices in the list. - auto &ln = FileInfo.Last(); - ln.lump->LumpNameSetup(ln.longName.Mid(len)); - ln.SetFromLump(rfnum, ln.lump); + auto lic = li; // make a copy before pushing. + FileInfo.push_back(lic); + li.LongName = ""; //nuke the name of the old record. + li.shortName.qword = 0; + auto &ln = FileInfo.back(); + ln.SetFromLump(li.resfile, li.resindex, rfnum, stringpool, ln.LongName + len); } } } @@ -990,22 +929,26 @@ void FileSystem::MoveLumpsInFolder(const char *path) int FileSystem::FindLump (const char *name, int *lastlump, bool anyns) { + if ((size_t)*lastlump >= FileInfo.size()) return -1; union { char name8[8]; uint64_t qname; }; - LumpRecord *lump_p; - uppercopy (name8, name); + UpperCopy (name8, name); assert(lastlump != NULL && *lastlump >= 0); - lump_p = &FileInfo[*lastlump]; - while (lump_p < &FileInfo[NumEntries]) + + const LumpRecord * last = FileInfo.data() + FileInfo.size(); + + LumpRecord * lump_p = FileInfo.data() + *lastlump; + + while (lump_p < last) { if ((anyns || lump_p->Namespace == ns_global) && lump_p->shortName.qword == qname) { - int lump = int(lump_p - &FileInfo[0]); + int lump = int(lump_p - FileInfo.data()); *lastlump = lump + 1; return lump; } @@ -1027,11 +970,13 @@ int FileSystem::FindLump (const char *name, int *lastlump, bool anyns) int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, int *nameindex) { - LumpRecord *lump_p; - assert(lastlump != NULL && *lastlump >= 0); - lump_p = &FileInfo[*lastlump]; - while (lump_p < &FileInfo[NumEntries]) + + const LumpRecord * last = FileInfo.data() + FileInfo.size(); + + LumpRecord * lump_p = FileInfo.data() + *lastlump; + + while (lump_p < last) { if (anyns || lump_p->Namespace == ns_global) { @@ -1040,7 +985,7 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in { if (!strnicmp(*name, lump_p->shortName.String, 8)) { - int lump = int(lump_p - &FileInfo[0]); + int lump = int(lump_p - FileInfo.data()); *lastlump = lump + 1; if (nameindex != NULL) *nameindex = int(name - names); return lump; @@ -1066,15 +1011,18 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext) { assert(lastlump != NULL && *lastlump >= 0); - auto lump_p = &FileInfo[*lastlump]; + + const LumpRecord * last = FileInfo.data() + FileInfo.size(); + + LumpRecord * lump_p = FileInfo.data() + *lastlump; if (!noext) { - while (lump_p < &FileInfo[NumEntries]) + while (lump_p < last) { - if (!stricmp(name, lump_p->longName)) + if (!stricmp(name, lump_p->LongName)) { - int lump = int(lump_p - &FileInfo[0]); + int lump = int(lump_p - FileInfo.data()); *lastlump = lump + 1; return lump; } @@ -1084,15 +1032,15 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext) else { auto len = strlen(name); - while (lump_p < &FileInfo[NumEntries]) + while (lump_p <= &FileInfo.back()) { - auto res = strnicmp(name, lump_p->longName, len); + auto res = strnicmp(name, lump_p->LongName, len); if (res == 0) { - auto p = lump_p->longName.GetChars() + len; + auto p = lump_p->LongName + len; if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0)) { - int lump = int(lump_p - &FileInfo[0]); + int lump = int(lump_p - FileInfo.data()); *lastlump = lump + 1; return lump; } @@ -1126,14 +1074,6 @@ bool FileSystem::CheckFileName (int lump, const char *name) // //========================================================================== -void FileSystem::GetFileShortName (char *to, int lump) const -{ - if ((size_t)lump >= NumEntries) - *to = 0; - else - uppercopy (to, FileInfo[lump].shortName.String); -} - const char* FileSystem::GetFileShortName(int lump) const { if ((size_t)lump >= NumEntries) @@ -1142,16 +1082,6 @@ const char* FileSystem::GetFileShortName(int lump) const return FileInfo[lump].shortName.String; } -void FileSystem::GetFileShortName(FString &to, int lump) const -{ - if ((size_t)lump >= NumEntries) - to = FString(); - else { - to = FileInfo[lump].shortName.String; - to.ToUpper(); - } -} - //========================================================================== // // FileSystem :: GetFileFullName @@ -1164,8 +1094,8 @@ const char *FileSystem::GetFileFullName (int lump, bool returnshort) const { if ((size_t)lump >= NumEntries) return NULL; - else if (FileInfo[lump].longName.IsNotEmpty()) - return FileInfo[lump].longName; + else if (FileInfo[lump].LongName[0] != 0) + return FileInfo[lump].LongName; else if (returnshort) return FileInfo[lump].shortName.String; else return nullptr; @@ -1179,13 +1109,15 @@ const char *FileSystem::GetFileFullName (int lump, bool returnshort) const // //========================================================================== -FString FileSystem::GetFileFullPath(int lump) const +std::string FileSystem::GetFileFullPath(int lump) const { - FString foo; + std::string foo; if ((size_t) lump < NumEntries) { - foo << GetResourceFileName(FileInfo[lump].rfnum) << ':' << GetFileFullName(lump); + foo = GetResourceFileName(FileInfo[lump].rfnum); + foo += ':'; + foo += +GetFileFullName(lump); } return foo; } @@ -1241,7 +1173,7 @@ const char *FileSystem::GetResourceType(int lump) const return nullptr; else { - auto p = strrchr(FileInfo[lump].longName.GetChars(), '.'); + auto p = strrchr(FileInfo[lump].LongName, '.'); if (!p) return ""; // has no extension if (strchr(p, '/')) return ""; // the '.' is part of a directory. return p + 1; @@ -1256,7 +1188,7 @@ const char *FileSystem::GetResourceType(int lump) const int FileSystem::GetFileContainer (int lump) const { - if ((size_t)lump >= FileInfo.Size()) + if ((size_t)lump >= FileInfo.size()) return -1; return FileInfo[lump].rfnum; } @@ -1284,25 +1216,26 @@ static int folderentrycmp(const void *a, const void *b) // //========================================================================== -unsigned FileSystem::GetFilesInFolder(const char *inpath, TArray &result, bool atomic) const +unsigned FileSystem::GetFilesInFolder(const char *inpath, std::vector &result, bool atomic) const { - FString path = inpath; - FixPathSeperator(path); - path.ToLower(); - if (path[path.Len() - 1] != '/') path += '/'; - result.Clear(); - for (unsigned i = 0; i < FileInfo.Size(); i++) + std::string path = inpath; + FixPathSeparator(&path.front()); + for (auto& c : path) c = tolower(c); + if (path.back() != '/') path += '/'; + result.clear(); + for (size_t i = 0; i < FileInfo.size(); i++) { - if (FileInfo[i].longName.IndexOf(path) == 0) + if (strncmp(FileInfo[i].LongName, path.c_str(), path.length()) == 0) { // Only if it hasn't been replaced. - if ((unsigned)fileSystem.CheckNumForFullName(FileInfo[i].longName) == i) + if ((unsigned)CheckNumForFullName(FileInfo[i].LongName) == i) { - result.Push({ FileInfo[i].longName.GetChars(), i }); + FolderEntry fe{ FileInfo[i].LongName, (uint32_t)i }; + result.push_back(fe); } } } - if (result.Size()) + if (result.size()) { int maxfile = -1; if (atomic) @@ -1310,46 +1243,20 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, TArray &r // Find the highest resource file having content in the given folder. for (auto & entry : result) { - int thisfile = fileSystem.GetFileContainer(entry.lumpnum); + int thisfile = GetFileContainer(entry.lumpnum); if (thisfile > maxfile) maxfile = thisfile; } // Delete everything from older files. - for (int i = result.Size() - 1; i >= 0; i--) + for (int i = (int)result.size() - 1; i >= 0; i--) { - if (fileSystem.GetFileContainer(result[i].lumpnum) != maxfile) result.Delete(i); + if (GetFileContainer(result[i].lumpnum) != maxfile) result.erase(result.begin() + i); } } - qsort(result.Data(), result.Size(), sizeof(FolderEntry), folderentrycmp); + qsort(result.data(), result.size(), sizeof(FolderEntry), folderentrycmp); } - return result.Size(); + return (unsigned)result.size(); } -//========================================================================== -// -// GetFileData -// -// Loads the lump into a TArray and returns it. -// -//========================================================================== - -TArray FileSystem::GetFileData(int lump, int pad) -{ - if ((size_t)lump >= FileInfo.Size()) - return TArray(); - - auto lumpr = OpenFileReader(lump); - auto size = lumpr.GetLength(); - TArray data(size + pad, true); - auto numread = lumpr.Read(data.Data(), size); - - if (numread != size) - { - I_Error("GetFileData: only read %ld of %ld on lump %i\n", - numread, size, lump); - } - if (pad > 0) memset(&data[size], 0, pad); - return data; -} //========================================================================== // // W_ReadFile @@ -1366,8 +1273,8 @@ void FileSystem::ReadFile (int lump, void *dest) if (numread != size) { - I_Error ("W_ReadFile: only read %ld of %ld on lump %i\n", - numread, size, lump); + throw FileSystemException("W_ReadFile: only read %td of %td on '%s'\n", + numread, size, FileInfo[lump].LongName); } } @@ -1382,7 +1289,11 @@ void FileSystem::ReadFile (int lump, void *dest) FileData FileSystem::ReadFile (int lump) { - return FileData(FString(ELumpNum(lump))); + if ((unsigned)lump >= (unsigned)FileInfo.size()) + { + throw FileSystemException("ReadFile: %u >= NumEntries", lump); + } + return FileInfo[lump].resfile->Read(FileInfo[lump].resindex); } //========================================================================== @@ -1394,53 +1305,31 @@ FileData FileSystem::ReadFile (int lump) //========================================================================== -FileReader FileSystem::OpenFileReader(int lump) +FileReader FileSystem::OpenFileReader(int lump, int readertype, int readerflags) { - if ((unsigned)lump >= (unsigned)FileInfo.Size()) + if ((unsigned)lump >= (unsigned)FileInfo.size()) { - I_Error("OpenFileReader: %u >= NumEntries", lump); + throw FileSystemException("OpenFileReader: %u >= NumEntries", lump); } - auto rl = FileInfo[lump].lump; - auto rd = rl->GetReader(); - - if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !(rl->Flags & LUMPF_COMPRESSED)) - { - FileReader rdr; - rdr.OpenFilePart(*rd, rl->GetFileOffset(), rl->LumpSize); - return rdr; - } - return rl->NewReader(); // This always gets a reader to the cache + auto file = FileInfo[lump].resfile; + return file->GetEntryReader(FileInfo[lump].resindex, readertype, readerflags); } -FileReader FileSystem::ReopenFileReader(int lump, bool alwayscache) +FileReader FileSystem::OpenFileReader(const char* name) { - if ((unsigned)lump >= (unsigned)FileInfo.Size()) - { - I_Error("ReopenFileReader: %u >= NumEntries", lump); - } - - auto rl = FileInfo[lump].lump; - auto rd = rl->GetReader(); - - if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !alwayscache && !(rl->Flags & LUMPF_COMPRESSED)) - { - int fileno = fileSystem.GetFileContainer(lump); - const char *filename = fileSystem.GetResourceFileFullName(fileno); - FileReader fr; - if (fr.OpenFile(filename, rl->GetFileOffset(), rl->LumpSize)) - { - return fr; - } - } - return rl->NewReader(); // This always gets a reader to the cache + FileReader fr; + auto lump = CheckNumForFullName(name); + if (lump >= 0) fr = OpenFileReader(lump); + return fr; } -FileReader FileSystem::OpenFileReader(const char* name) +FileReader FileSystem::ReopenFileReader(const char* name, bool alwayscache) { + FileReader fr; auto lump = CheckNumForFullName(name); - if (lump < 0) return FileReader(); - else return OpenFileReader(lump); + if (lump >= 0) fr = ReopenFileReader(lump, alwayscache); + return fr; } //========================================================================== @@ -1454,12 +1343,12 @@ FileReader FileSystem::OpenFileReader(const char* name) FileReader *FileSystem::GetFileReader(int rfnum) { - if ((uint32_t)rfnum >= Files.Size()) + if ((uint32_t)rfnum >= Files.size()) { return NULL; } - return Files[rfnum]->GetReader(); + return Files[rfnum]->GetContainerReader(); } //========================================================================== @@ -1474,14 +1363,14 @@ const char *FileSystem::GetResourceFileName (int rfnum) const noexcept { const char *name, *slash; - if ((uint32_t)rfnum >= Files.Size()) + if ((uint32_t)rfnum >= Files.size()) { return NULL; } - name = Files[rfnum]->FileName; + name = Files[rfnum]->GetFileName(); slash = strrchr (name, '/'); - return (slash != NULL && slash[1] != 0) ? slash+1 : name; + return (slash != nullptr && slash[1] != 0) ? slash+1 : name; } //========================================================================== @@ -1491,7 +1380,7 @@ const char *FileSystem::GetResourceFileName (int rfnum) const noexcept int FileSystem::GetFirstEntry (int rfnum) const noexcept { - if ((uint32_t)rfnum >= Files.Size()) + if ((uint32_t)rfnum >= Files.size()) { return 0; } @@ -1506,12 +1395,12 @@ int FileSystem::GetFirstEntry (int rfnum) const noexcept int FileSystem::GetLastEntry (int rfnum) const noexcept { - if ((uint32_t)rfnum >= Files.Size()) + if ((uint32_t)rfnum >= Files.size()) { return 0; } - return Files[rfnum]->GetFirstEntry() + Files[rfnum]->LumpCount() - 1; + return Files[rfnum]->GetFirstEntry() + Files[rfnum]->EntryCount() - 1; } //========================================================================== @@ -1521,12 +1410,12 @@ int FileSystem::GetLastEntry (int rfnum) const noexcept int FileSystem::GetEntryCount (int rfnum) const noexcept { - if ((uint32_t)rfnum >= Files.Size()) + if ((uint32_t)rfnum >= Files.size()) { return 0; } - return Files[rfnum]->LumpCount(); + return Files[rfnum]->EntryCount(); } @@ -1540,12 +1429,12 @@ int FileSystem::GetEntryCount (int rfnum) const noexcept const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept { - if ((unsigned int)rfnum >= Files.Size()) + if ((unsigned int)rfnum >= Files.size()) { return nullptr; } - return Files[rfnum]->FileName; + return Files[rfnum]->GetFileName(); } @@ -1557,72 +1446,31 @@ const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/) { - FString name2=name, type2, path; + std::string name2 = name, type2, path; // The old code said 'filename' and ignored the path, this looked like a bug. - FixPathSeperator(name2); - auto lump = FindFile(name2); + FixPathSeparator(&name2.front()); + auto lump = FindFile(name2.c_str()); if (lump < 0) return false; // Does not exist. auto oldlump = FileInfo[lump]; - ptrdiff_t slash = oldlump.longName.LastIndexOf('/'); + auto slash = strrchr(oldlump.LongName, '/'); - if (slash == -1) + if (slash == nullptr) { - FileInfo[lump].flags = LUMPF_FULLPATH; + FileInfo[lump].flags = RESFF_FULLPATH; return true; // already is pathless. } // just create a new reference to the original data with a different name. - oldlump.longName = oldlump.longName.Mid(slash + 1); + oldlump.LongName = slash + 1; oldlump.resourceId = id; - oldlump.flags = LUMPF_FULLPATH; - FileInfo.Push(oldlump); + oldlump.flags = RESFF_FULLPATH; + FileInfo.push_back(oldlump); return true; } -// FileData ----------------------------------------------------------------- - -FileData::FileData () -{ -} - -FileData::FileData (const FileData ©) -{ - Block = copy.Block; -} - -FileData &FileData::operator = (const FileData ©) -{ - Block = copy.Block; - return *this; -} - -FileData::FileData (const FString &source) -: Block (source) -{ -} - -FileData::~FileData () -{ -} - -FString::FString (ELumpNum lumpnum) -{ - auto lumpr = fileSystem.OpenFileReader ((int)lumpnum); - auto size = lumpr.GetLength (); - AllocBuffer (1 + size); - auto numread = lumpr.Read (&Chars[0], size); - Chars[size] = '\0'; - - if (numread != size) - { - I_Error ("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n", - numread, size, lumpnum, fileSystem.GetFileFullName((int)lumpnum)); - } -} - //========================================================================== // // PrintLastError @@ -1647,7 +1495,7 @@ __declspec(dllimport) void * __stdcall LocalFree (void *); __declspec(dllimport) unsigned long __stdcall GetLastError (); } -static void PrintLastError () +static void PrintLastError (FileSystemMessageFunc Printf) { char *lpMsgBuf; FormatMessageA(0x1300 /*FORMAT_MESSAGE_ALLOCATE_BUFFER | @@ -1660,42 +1508,16 @@ static void PrintLastError () 0, NULL ); - Printf (TEXTCOLOR_RED " %s\n", lpMsgBuf); + Printf (FSMessageLevel::Error, " %s\n", lpMsgBuf); // Free the buffer. LocalFree( lpMsgBuf ); } #else -static void PrintLastError () +static void PrintLastError (FileSystemMessageFunc Printf) { - Printf (TEXTCOLOR_RED " %s\n", strerror(errno)); + Printf(FSMessageLevel::Error, " %s\n", strerror(errno)); } #endif -//========================================================================== -// -// NBlood style lookup functions -// -//========================================================================== - -FResourceLump* FileSystem::GetFileAt(int no) -{ - return FileInfo[no].lump; -} -#include "c_dispatch.h" - -CCMD(fs_dir) -{ - int numfiles = fileSystem.GetNumEntries(); - - for (int i = 0; i < numfiles; i++) - { - auto container = fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(i)); - auto fn1 = fileSystem.GetFileFullName(i); - auto fns = fileSystem.GetFileShortName(i); - auto fnid = fileSystem.GetResourceId(i); - auto length = fileSystem.FileLength(i); - bool hidden = fileSystem.FindFile(fn1) != i; - Printf(PRINT_HIGH | PRINT_NONOTIFY, "%s%-64s %-15s (%5d) %10d %s %s\n", hidden ? TEXTCOLOR_RED : TEXTCOLOR_UNTRANSLATED, fn1, fns, fnid, length, container, hidden ? "(h)" : ""); - } } diff --git a/src/common/filesystem/source/fs_findfile.cpp b/src/common/filesystem/source/fs_findfile.cpp new file mode 100644 index 0000000000..9bc32e75e8 --- /dev/null +++ b/src/common/filesystem/source/fs_findfile.cpp @@ -0,0 +1,428 @@ +/* +** findfile.cpp +** Wrapper around the native directory scanning APIs +** +**--------------------------------------------------------------------------- +** Copyright 1998-2016 Randy Heit +** Copyright 2005-2020 Christoph Oelckers +** +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +*/ + +#include "fs_findfile.h" +#include +#include + +#ifndef _WIN32 + +#include +#include +#ifdef __FreeBSD__ +#include +#endif +#include +#include +#include + +#include + +#endif + +namespace FileSys { + +enum +{ + ZPATH_MAX = 260 +}; + +#ifndef _WIN32 + + +#else + + +enum +{ + FA_RDONLY = 1, + FA_HIDDEN = 2, + FA_SYSTEM = 4, + FA_DIREC = 16, + FA_ARCH = 32, +}; + +#endif + + +#ifndef _WIN32 + +struct findstate_t +{ + std::string path; + struct dirent** namelist; + int current; + int count; +}; + +static const char* FS_FindName(findstate_t* fileinfo) +{ + return (fileinfo->namelist[fileinfo->current]->d_name); +} + +enum +{ + FA_RDONLY = 1, + FA_HIDDEN = 2, + FA_SYSTEM = 4, + FA_DIREC = 8, + FA_ARCH = 16, +}; + + +static const char *pattern; + +static int matchfile(const struct dirent *ent) +{ + return fnmatch(pattern, ent->d_name, FNM_NOESCAPE) == 0; +} + +static void *FS_FindFirst(const char *const filespec, findstate_t *const fileinfo) +{ + const char* dir; + + const char *const slash = strrchr(filespec, '/'); + + if (slash) + { + pattern = slash + 1; + fileinfo->path = std::string(filespec, 0, slash - filespec + 1); + dir = fileinfo->path.c_str(); + } + else + { + pattern = filespec; + dir = "."; + } + + fileinfo->current = 0; + fileinfo->count = scandir(dir, &fileinfo->namelist, matchfile, alphasort); + + if (fileinfo->count > 0) + { + return fileinfo; + } + + return (void *)-1; +} + +static int FS_FindNext(void *const handle, findstate_t *const fileinfo) +{ + findstate_t *const state = static_cast(handle); + + if (state->current < fileinfo->count) + { + return ++state->current < fileinfo->count ? 0 : -1; + } + + return -1; +} + +static int FS_FindClose(void *const handle) +{ + findstate_t *const state = static_cast(handle); + + if (handle != (void *)-1 && state->count > 0) + { + for (int i = 0; i < state->count; ++i) + { + free(state->namelist[i]); + } + + free(state->namelist); + state->namelist = nullptr; + state->count = 0; + } + + return 0; +} + +static int FS_FindAttr(findstate_t *const fileinfo) +{ + dirent *const ent = fileinfo->namelist[fileinfo->current]; + const std::string path = fileinfo->path + ent->d_name; + bool isdir; + + if (FS_DirEntryExists(path.c_str(), &isdir)) + { + return isdir ? FA_DIREC : 0; + } + + return 0; +} + +std::string FS_FullPath(const char* directory) +{ + char fullpath[PATH_MAX]; + + if (realpath(directory, fullpath) != nullptr) + return fullpath; + + return directory; +} + +static size_t FS_GetFileSize(findstate_t* handle, const char* pathname) +{ + struct stat info; + bool res = stat(pathname, &info) == 0; + if (!res || (info.st_mode & S_IFDIR)) return 0; + return (size_t)info.st_size; +} + + +#else + +#include +#include + +std::wstring toWide(const char* str) +{ + int len = (int)strlen(str); + std::wstring wide; + if (len > 0) + { + int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, nullptr, 0); + wide.resize(size_needed); + MultiByteToWideChar(CP_UTF8, 0, str, len, &wide.front(), size_needed); + } + return wide; +} + +static std::string toUtf8(const wchar_t* str) +{ + auto len = wcslen(str); + std::string utf8; + if (len > 0) + { + int size_needed = WideCharToMultiByte(CP_UTF8, 0, str, (int)len, nullptr, 0, nullptr, nullptr); + utf8.resize(size_needed); + WideCharToMultiByte(CP_UTF8, 0, str, (int)len, &utf8.front(), size_needed, nullptr, nullptr); + } + return utf8; +} + +struct findstate_t +{ + struct FileTime + { + uint32_t lo, hi; + }; + // Mirror WIN32_FIND_DATAW in . We cannot pull in the Windows header here as it would pollute all consumers' symbol space. + struct WinData + { + uint32_t Attribs; + FileTime Times[3]; + uint32_t Size[2]; + uint32_t Reserved[2]; + wchar_t Name[ZPATH_MAX]; + wchar_t AltName[14]; + }; + WinData FindData; + std::string UTF8Name; +}; + + +static int FS_FindAttr(findstate_t* fileinfo) +{ + return fileinfo->FindData.Attribs; +} + +//========================================================================== +// +// FS_FindFirst +// +// Start a pattern matching sequence. +// +//========================================================================== + + +static void *FS_FindFirst(const char *filespec, findstate_t *fileinfo) +{ + static_assert(sizeof(WIN32_FIND_DATAW) == sizeof(fileinfo->FindData), "FindData size mismatch"); + return FindFirstFileW(toWide(filespec).c_str(), (LPWIN32_FIND_DATAW)&fileinfo->FindData); +} + +//========================================================================== +// +// FS_FindNext +// +// Return the next file in a pattern matching sequence. +// +//========================================================================== + +static int FS_FindNext(void *handle, findstate_t *fileinfo) +{ + return FindNextFileW((HANDLE)handle, (LPWIN32_FIND_DATAW)&fileinfo->FindData) == 0; +} + +//========================================================================== +// +// FS_FindClose +// +// Finish a pattern matching sequence. +// +//========================================================================== + +static int FS_FindClose(void *handle) +{ + return FindClose((HANDLE)handle); +} + +//========================================================================== +// +// FS_FindName +// +// Returns the name for an entry +// +//========================================================================== + +static const char *FS_FindName(findstate_t *fileinfo) +{ + fileinfo->UTF8Name = toUtf8(fileinfo->FindData.Name); + return fileinfo->UTF8Name.c_str(); +} + +std::string FS_FullPath(const char* directory) +{ + auto wdirectory = _wfullpath(nullptr, toWide(directory).c_str(), _MAX_PATH); + std::string sdirectory = toUtf8(wdirectory); + free((void*)wdirectory); + for (auto& c : sdirectory) if (c == '\\') c = '/'; + return sdirectory; +} + +static size_t FS_GetFileSize(findstate_t* handle, const char* pathname) +{ + return handle->FindData.Size[1] + ((uint64_t)handle->FindData.Size[0] << 32); +} + +#endif + + +//========================================================================== +// +// ScanDirectory +// +//========================================================================== + +static bool DoScanDirectory(FileList& list, const char* dirpath, const char* match, const char* relpath, bool nosubdir, bool readhidden) +{ + findstate_t find; + + std::string dirpathn = dirpath; + FixPathSeparator(&dirpathn.front()); + if (dirpathn[dirpathn.length() - 1] != '/') dirpathn += '/'; + + std::string dirmatch = dirpathn; + dirmatch += match; + + auto handle = FS_FindFirst(dirmatch.c_str(), &find); + if (handle == ((void*)(-1))) return false; + FileListEntry fl; + do + { + auto attr = FS_FindAttr(&find); + if (!readhidden && (attr & FA_HIDDEN)) + { + // Skip hidden files and directories. (Prevents SVN/git bookkeeping info from being included.) + continue; + } + auto fn = FS_FindName(&find); + + if (attr & FA_DIREC) + { + if (fn[0] == '.' && + (fn[1] == '\0' || + (fn[1] == '.' && fn[2] == '\0'))) + { + // Do not record . and .. directories. + continue; + } + } + + fl.FileName = fn; + fl.FilePath = dirpathn + fn; + fl.FilePathRel = relpath; + if (fl.FilePathRel.length() > 0) fl.FilePathRel += '/'; + fl.FilePathRel += fn; + fl.isDirectory = !!(attr & FA_DIREC); + fl.isReadonly = !!(attr & FA_RDONLY); + fl.isHidden = !!(attr & FA_HIDDEN); + fl.isSystem = !!(attr & FA_SYSTEM); + fl.Length = FS_GetFileSize(&find, fl.FilePath.c_str()); + list.push_back(fl); + if (!nosubdir && (attr & FA_DIREC)) + { + DoScanDirectory(list, fl.FilePath.c_str(), match, fl.FilePathRel.c_str(), false, readhidden); + fl.Length = 0; + } + } while (FS_FindNext(handle, &find) == 0); + FS_FindClose(handle); + return true; +} + + +bool ScanDirectory(std::vector& list, const char* dirpath, const char* match, bool nosubdir, bool readhidden) +{ + return DoScanDirectory(list, dirpath, match, "", nosubdir, readhidden); +} + +//========================================================================== +// +// DirEntryExists +// +// Returns true if the given path exists, be it a directory or a file. +// +//========================================================================== + +bool FS_DirEntryExists(const char* pathname, bool* isdir) +{ + if (isdir) *isdir = false; + if (pathname == NULL || *pathname == 0) + return false; + +#ifndef _WIN32 + struct stat info; + bool res = stat(pathname, &info) == 0; +#else + // Windows must use the wide version of stat to preserve non-standard paths. + auto wstr = toWide(pathname); + struct _stat64 info; + bool res = _wstat64(wstr.c_str(), &info) == 0; +#endif + if (isdir) *isdir = !!(info.st_mode & S_IFDIR); + return res; +} + +} diff --git a/src/common/filesystem/source/fs_stringpool.cpp b/src/common/filesystem/source/fs_stringpool.cpp new file mode 100644 index 0000000000..316078cae9 --- /dev/null +++ b/src/common/filesystem/source/fs_stringpool.cpp @@ -0,0 +1,131 @@ +/* +** stringpool.cpp +** allocate static strings from larger blocks +** +**--------------------------------------------------------------------------- +** Copyright 2010 Randy Heit +** Copyright 2023 Christoph Oelckers +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include +#include +#include "fs_stringpool.h" + +namespace FileSys { + +struct StringPool::Block +{ + Block *NextBlock; + void *Limit; // End of this block + void *Avail; // Start of free space in this block + void *alignme; // align to 16 bytes. + + void *Alloc(size_t size); +}; + +//========================================================================== +// +// StringPool Destructor +// +//========================================================================== + +StringPool::~StringPool() +{ + for (Block *next, *block = TopBlock; block != nullptr; block = next) + { + next = block->NextBlock; + free(block); + } + TopBlock = nullptr; +} + +//========================================================================== +// +// StringPool :: Alloc +// +//========================================================================== + +void *StringPool::Block::Alloc(size_t size) +{ + if ((char *)Avail + size > Limit) + { + return nullptr; + } + void *res = Avail; + Avail = ((char *)Avail + size); + return res; +} + +StringPool::Block *StringPool::AddBlock(size_t size) +{ + size += sizeof(Block); // Account for header size + + // Allocate a new block + if (size < BlockSize) + { + size = BlockSize; + } + auto mem = (Block *)malloc(size); + if (mem == nullptr) + { + + } + mem->Limit = (uint8_t *)mem + size; + mem->Avail = &mem[1]; + mem->NextBlock = TopBlock; + TopBlock = mem; + return mem; +} + +void *StringPool::Alloc(size_t size) +{ + Block *block; + + size = (size + 7) & ~7; + for (block = TopBlock; block != nullptr; block = block->NextBlock) + { + void *res = block->Alloc(size); + if (res != nullptr) + { + return res; + } + } + block = AddBlock(size); + return block->Alloc(size); +} + +const char* StringPool::Strdup(const char* str) +{ + char* p = (char*)Alloc(strlen(str) + 1); + strcpy(p, str); + return p; +} + +} diff --git a/src/common/filesystem/source/fs_stringpool.h b/src/common/filesystem/source/fs_stringpool.h new file mode 100644 index 0000000000..f327d14a3e --- /dev/null +++ b/src/common/filesystem/source/fs_stringpool.h @@ -0,0 +1,28 @@ +#pragma once + +namespace FileSys { +// Storage for all the static strings the file system must hold. +class StringPool +{ + // do not allow externally defining this. + friend class FileSystem; + friend class FResourceFile; +private: + StringPool(bool _shared, size_t blocksize = 10*1024) : TopBlock(nullptr), BlockSize(blocksize), shared(_shared) {} +public: + ~StringPool(); + const char* Strdup(const char*); + void* Alloc(size_t size); + +protected: + struct Block; + + Block *AddBlock(size_t size); + + Block *TopBlock; + size_t BlockSize; +public: + bool shared; +}; + +} diff --git a/src/common/filesystem/source/md5.hpp b/src/common/filesystem/source/md5.hpp new file mode 100644 index 0000000000..1ecde05d41 --- /dev/null +++ b/src/common/filesystem/source/md5.hpp @@ -0,0 +1,416 @@ +#pragma once +/* + md5.hpp is a reformulation of the md5.h and md5.c code from + http://www.opensource.apple.com/source/cups/cups-59/cups/md5.c to allow it to + function as a component of a header only library. This conversion was done by + Peter Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The + changes are released under the same license as the original (listed below) +*/ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + 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. + + L. Peter Deutsch + ghost@aladdin.com + + */ + /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ + /* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Removed support for non-ANSI compilers; removed + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + + + /* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +#include +#include + +namespace FileSys { + /// Provides MD5 hashing functionality + namespace md5 { + + typedef unsigned char md5_byte_t; /* 8-bit byte */ + typedef unsigned int md5_word_t; /* 32-bit word */ + + /* Define the state of the MD5 Algorithm. */ + typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ + } md5_state_t; + + /* Initialize the algorithm. */ + inline void md5_init(md5_state_t* pms); + + /* Append a string to the message. */ + inline void md5_append(md5_state_t* pms, md5_byte_t const* data, size_t nbytes); + + /* Finish the message and return the digest. */ + inline void md5_finish(md5_state_t* pms, md5_byte_t digest[16]); + +#undef ZSW_MD5_BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define ZSW_MD5_BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define ZSW_MD5_BYTE_ORDER 0 +#endif + +#define ZSW_MD5_T_MASK ((md5_word_t)~0) +#define ZSW_MD5_T1 /* 0xd76aa478 */ (ZSW_MD5_T_MASK ^ 0x28955b87) +#define ZSW_MD5_T2 /* 0xe8c7b756 */ (ZSW_MD5_T_MASK ^ 0x173848a9) +#define ZSW_MD5_T3 0x242070db +#define ZSW_MD5_T4 /* 0xc1bdceee */ (ZSW_MD5_T_MASK ^ 0x3e423111) +#define ZSW_MD5_T5 /* 0xf57c0faf */ (ZSW_MD5_T_MASK ^ 0x0a83f050) +#define ZSW_MD5_T6 0x4787c62a +#define ZSW_MD5_T7 /* 0xa8304613 */ (ZSW_MD5_T_MASK ^ 0x57cfb9ec) +#define ZSW_MD5_T8 /* 0xfd469501 */ (ZSW_MD5_T_MASK ^ 0x02b96afe) +#define ZSW_MD5_T9 0x698098d8 +#define ZSW_MD5_T10 /* 0x8b44f7af */ (ZSW_MD5_T_MASK ^ 0x74bb0850) +#define ZSW_MD5_T11 /* 0xffff5bb1 */ (ZSW_MD5_T_MASK ^ 0x0000a44e) +#define ZSW_MD5_T12 /* 0x895cd7be */ (ZSW_MD5_T_MASK ^ 0x76a32841) +#define ZSW_MD5_T13 0x6b901122 +#define ZSW_MD5_T14 /* 0xfd987193 */ (ZSW_MD5_T_MASK ^ 0x02678e6c) +#define ZSW_MD5_T15 /* 0xa679438e */ (ZSW_MD5_T_MASK ^ 0x5986bc71) +#define ZSW_MD5_T16 0x49b40821 +#define ZSW_MD5_T17 /* 0xf61e2562 */ (ZSW_MD5_T_MASK ^ 0x09e1da9d) +#define ZSW_MD5_T18 /* 0xc040b340 */ (ZSW_MD5_T_MASK ^ 0x3fbf4cbf) +#define ZSW_MD5_T19 0x265e5a51 +#define ZSW_MD5_T20 /* 0xe9b6c7aa */ (ZSW_MD5_T_MASK ^ 0x16493855) +#define ZSW_MD5_T21 /* 0xd62f105d */ (ZSW_MD5_T_MASK ^ 0x29d0efa2) +#define ZSW_MD5_T22 0x02441453 +#define ZSW_MD5_T23 /* 0xd8a1e681 */ (ZSW_MD5_T_MASK ^ 0x275e197e) +#define ZSW_MD5_T24 /* 0xe7d3fbc8 */ (ZSW_MD5_T_MASK ^ 0x182c0437) +#define ZSW_MD5_T25 0x21e1cde6 +#define ZSW_MD5_T26 /* 0xc33707d6 */ (ZSW_MD5_T_MASK ^ 0x3cc8f829) +#define ZSW_MD5_T27 /* 0xf4d50d87 */ (ZSW_MD5_T_MASK ^ 0x0b2af278) +#define ZSW_MD5_T28 0x455a14ed +#define ZSW_MD5_T29 /* 0xa9e3e905 */ (ZSW_MD5_T_MASK ^ 0x561c16fa) +#define ZSW_MD5_T30 /* 0xfcefa3f8 */ (ZSW_MD5_T_MASK ^ 0x03105c07) +#define ZSW_MD5_T31 0x676f02d9 +#define ZSW_MD5_T32 /* 0x8d2a4c8a */ (ZSW_MD5_T_MASK ^ 0x72d5b375) +#define ZSW_MD5_T33 /* 0xfffa3942 */ (ZSW_MD5_T_MASK ^ 0x0005c6bd) +#define ZSW_MD5_T34 /* 0x8771f681 */ (ZSW_MD5_T_MASK ^ 0x788e097e) +#define ZSW_MD5_T35 0x6d9d6122 +#define ZSW_MD5_T36 /* 0xfde5380c */ (ZSW_MD5_T_MASK ^ 0x021ac7f3) +#define ZSW_MD5_T37 /* 0xa4beea44 */ (ZSW_MD5_T_MASK ^ 0x5b4115bb) +#define ZSW_MD5_T38 0x4bdecfa9 +#define ZSW_MD5_T39 /* 0xf6bb4b60 */ (ZSW_MD5_T_MASK ^ 0x0944b49f) +#define ZSW_MD5_T40 /* 0xbebfbc70 */ (ZSW_MD5_T_MASK ^ 0x4140438f) +#define ZSW_MD5_T41 0x289b7ec6 +#define ZSW_MD5_T42 /* 0xeaa127fa */ (ZSW_MD5_T_MASK ^ 0x155ed805) +#define ZSW_MD5_T43 /* 0xd4ef3085 */ (ZSW_MD5_T_MASK ^ 0x2b10cf7a) +#define ZSW_MD5_T44 0x04881d05 +#define ZSW_MD5_T45 /* 0xd9d4d039 */ (ZSW_MD5_T_MASK ^ 0x262b2fc6) +#define ZSW_MD5_T46 /* 0xe6db99e5 */ (ZSW_MD5_T_MASK ^ 0x1924661a) +#define ZSW_MD5_T47 0x1fa27cf8 +#define ZSW_MD5_T48 /* 0xc4ac5665 */ (ZSW_MD5_T_MASK ^ 0x3b53a99a) +#define ZSW_MD5_T49 /* 0xf4292244 */ (ZSW_MD5_T_MASK ^ 0x0bd6ddbb) +#define ZSW_MD5_T50 0x432aff97 +#define ZSW_MD5_T51 /* 0xab9423a7 */ (ZSW_MD5_T_MASK ^ 0x546bdc58) +#define ZSW_MD5_T52 /* 0xfc93a039 */ (ZSW_MD5_T_MASK ^ 0x036c5fc6) +#define ZSW_MD5_T53 0x655b59c3 +#define ZSW_MD5_T54 /* 0x8f0ccc92 */ (ZSW_MD5_T_MASK ^ 0x70f3336d) +#define ZSW_MD5_T55 /* 0xffeff47d */ (ZSW_MD5_T_MASK ^ 0x00100b82) +#define ZSW_MD5_T56 /* 0x85845dd1 */ (ZSW_MD5_T_MASK ^ 0x7a7ba22e) +#define ZSW_MD5_T57 0x6fa87e4f +#define ZSW_MD5_T58 /* 0xfe2ce6e0 */ (ZSW_MD5_T_MASK ^ 0x01d3191f) +#define ZSW_MD5_T59 /* 0xa3014314 */ (ZSW_MD5_T_MASK ^ 0x5cfebceb) +#define ZSW_MD5_T60 0x4e0811a1 +#define ZSW_MD5_T61 /* 0xf7537e82 */ (ZSW_MD5_T_MASK ^ 0x08ac817d) +#define ZSW_MD5_T62 /* 0xbd3af235 */ (ZSW_MD5_T_MASK ^ 0x42c50dca) +#define ZSW_MD5_T63 0x2ad7d2bb +#define ZSW_MD5_T64 /* 0xeb86d391 */ (ZSW_MD5_T_MASK ^ 0x14792c6e) + + static void md5_process(md5_state_t* pms, md5_byte_t const* data /*[64]*/) { + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; +#if ZSW_MD5_BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + md5_word_t const* X; +#endif + + { +#if ZSW_MD5_BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static int const w = 1; + + if (*((md5_byte_t const*)&w)) /* dynamic little-endian */ +#endif +#if ZSW_MD5_BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (md5_byte_t const*)0) & 3)) { + /* data are properly aligned */ + X = (md5_word_t const*)data; + } + else { + /* not aligned */ + std::memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if ZSW_MD5_BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if ZSW_MD5_BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t* xp = data; + int i; + +# if ZSW_MD5_BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ZSW_MD5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define ZSW_MD5_F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + ZSW_MD5_F(b,c,d) + X[k] + Ti;\ + a = ZSW_MD5_ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, ZSW_MD5_T1); + SET(d, a, b, c, 1, 12, ZSW_MD5_T2); + SET(c, d, a, b, 2, 17, ZSW_MD5_T3); + SET(b, c, d, a, 3, 22, ZSW_MD5_T4); + SET(a, b, c, d, 4, 7, ZSW_MD5_T5); + SET(d, a, b, c, 5, 12, ZSW_MD5_T6); + SET(c, d, a, b, 6, 17, ZSW_MD5_T7); + SET(b, c, d, a, 7, 22, ZSW_MD5_T8); + SET(a, b, c, d, 8, 7, ZSW_MD5_T9); + SET(d, a, b, c, 9, 12, ZSW_MD5_T10); + SET(c, d, a, b, 10, 17, ZSW_MD5_T11); + SET(b, c, d, a, 11, 22, ZSW_MD5_T12); + SET(a, b, c, d, 12, 7, ZSW_MD5_T13); + SET(d, a, b, c, 13, 12, ZSW_MD5_T14); + SET(c, d, a, b, 14, 17, ZSW_MD5_T15); + SET(b, c, d, a, 15, 22, ZSW_MD5_T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define ZSW_MD5_G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + ZSW_MD5_G(b,c,d) + X[k] + Ti;\ + a = ZSW_MD5_ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, ZSW_MD5_T17); + SET(d, a, b, c, 6, 9, ZSW_MD5_T18); + SET(c, d, a, b, 11, 14, ZSW_MD5_T19); + SET(b, c, d, a, 0, 20, ZSW_MD5_T20); + SET(a, b, c, d, 5, 5, ZSW_MD5_T21); + SET(d, a, b, c, 10, 9, ZSW_MD5_T22); + SET(c, d, a, b, 15, 14, ZSW_MD5_T23); + SET(b, c, d, a, 4, 20, ZSW_MD5_T24); + SET(a, b, c, d, 9, 5, ZSW_MD5_T25); + SET(d, a, b, c, 14, 9, ZSW_MD5_T26); + SET(c, d, a, b, 3, 14, ZSW_MD5_T27); + SET(b, c, d, a, 8, 20, ZSW_MD5_T28); + SET(a, b, c, d, 13, 5, ZSW_MD5_T29); + SET(d, a, b, c, 2, 9, ZSW_MD5_T30); + SET(c, d, a, b, 7, 14, ZSW_MD5_T31); + SET(b, c, d, a, 12, 20, ZSW_MD5_T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define ZSW_MD5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + ZSW_MD5_H(b,c,d) + X[k] + Ti;\ + a = ZSW_MD5_ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, ZSW_MD5_T33); + SET(d, a, b, c, 8, 11, ZSW_MD5_T34); + SET(c, d, a, b, 11, 16, ZSW_MD5_T35); + SET(b, c, d, a, 14, 23, ZSW_MD5_T36); + SET(a, b, c, d, 1, 4, ZSW_MD5_T37); + SET(d, a, b, c, 4, 11, ZSW_MD5_T38); + SET(c, d, a, b, 7, 16, ZSW_MD5_T39); + SET(b, c, d, a, 10, 23, ZSW_MD5_T40); + SET(a, b, c, d, 13, 4, ZSW_MD5_T41); + SET(d, a, b, c, 0, 11, ZSW_MD5_T42); + SET(c, d, a, b, 3, 16, ZSW_MD5_T43); + SET(b, c, d, a, 6, 23, ZSW_MD5_T44); + SET(a, b, c, d, 9, 4, ZSW_MD5_T45); + SET(d, a, b, c, 12, 11, ZSW_MD5_T46); + SET(c, d, a, b, 15, 16, ZSW_MD5_T47); + SET(b, c, d, a, 2, 23, ZSW_MD5_T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define ZSW_MD5_I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + ZSW_MD5_I(b,c,d) + X[k] + Ti;\ + a = ZSW_MD5_ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, ZSW_MD5_T49); + SET(d, a, b, c, 7, 10, ZSW_MD5_T50); + SET(c, d, a, b, 14, 15, ZSW_MD5_T51); + SET(b, c, d, a, 5, 21, ZSW_MD5_T52); + SET(a, b, c, d, 12, 6, ZSW_MD5_T53); + SET(d, a, b, c, 3, 10, ZSW_MD5_T54); + SET(c, d, a, b, 10, 15, ZSW_MD5_T55); + SET(b, c, d, a, 1, 21, ZSW_MD5_T56); + SET(a, b, c, d, 8, 6, ZSW_MD5_T57); + SET(d, a, b, c, 15, 10, ZSW_MD5_T58); + SET(c, d, a, b, 6, 15, ZSW_MD5_T59); + SET(b, c, d, a, 13, 21, ZSW_MD5_T60); + SET(a, b, c, d, 4, 6, ZSW_MD5_T61); + SET(d, a, b, c, 11, 10, ZSW_MD5_T62); + SET(c, d, a, b, 2, 15, ZSW_MD5_T63); + SET(b, c, d, a, 9, 21, ZSW_MD5_T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; + } + + void md5_init(md5_state_t* pms) { + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ ZSW_MD5_T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ ZSW_MD5_T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; + } + + void md5_append(md5_state_t* pms, md5_byte_t const* data, size_t nbytes) { + md5_byte_t const* p = data; + size_t left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += (md5_word_t)(nbytes >> 29); + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : static_cast(nbytes)); + + std::memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + std::memcpy(pms->buf, p, left); + } + + void md5_finish(md5_state_t* pms, md5_byte_t digest[16]) { + static md5_byte_t const pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); + } + + + } // md5 +} // fs_private + diff --git a/src/common/filesystem/source/resourcefile.cpp b/src/common/filesystem/source/resourcefile.cpp new file mode 100644 index 0000000000..7a6085d2f9 --- /dev/null +++ b/src/common/filesystem/source/resourcefile.cpp @@ -0,0 +1,732 @@ +/* +** resourcefile.cpp +** +** Base classes for resource file management +** +**--------------------------------------------------------------------------- +** Copyright 2009 Christoph Oelckers +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +** +*/ + +#include +#include "resourcefile.h" +#include "md5.hpp" +#include "fs_stringpool.h" +#include "files_internal.h" +#include "unicode.h" +#include "fs_findfile.h" +#include "fs_decompress.h" +#include "wildcards.hpp" + +namespace FileSys { + +// this is for restricting shared file readers to the main thread. +thread_local bool mainThread; +void SetMainThread() +{ + // only set the global flag on the first thread calling this. + static bool done = false; + if (!done) + { + mainThread = done = true; + } +} + +std::string ExtractBaseName(const char* path, bool include_extension) +{ + const char* src, * dot; + + src = path + strlen(path) - 1; + + if (src >= path) + { + // back up until a / or the start + while (src != path && src[-1] != '/' && src[-1] != '\\') // check both on all systems for consistent behavior with archives. + src--; + + if (!include_extension && (dot = strrchr(src, '.'))) + { + return std::string(src, dot - src); + } + else + { + return std::string(src); + } + } + return std::string(); +} + +void strReplace(std::string& str, const char *from, const char* to) +{ + if (*from == 0) + return; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) + { + str.replace(start_pos, strlen(from), to); + start_pos += strlen(to); + } +} + +//========================================================================== +// +// Checks for embedded resource files +// +//========================================================================== + +bool FResourceFile::IsFileInFolder(const char* const resPath) +{ + // Checks a special case when was put in + // directory inside + + const auto dirName = ExtractBaseName(FileName); + const auto fileName = ExtractBaseName(resPath, true); + const std::string filePath = dirName + '/' + fileName; + + return 0 == stricmp(filePath.c_str(), resPath); +} + +void FResourceFile::CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi) +{ + // Checks for embedded archives + auto FullName = Entries[entry].FileName; + const char *c = strstr(FullName, ".wad"); // fixme: Use lfi for this. + if (c && strlen(c) == 4 && (!strchr(FullName, '/') || IsFileInFolder(FullName))) + { + Entries[entry].Flags |= RESFF_EMBEDDED; + } + else if (lfi) for (auto& fstr : lfi->embeddings) + { + if (!stricmp(FullName, fstr.c_str())) + { + Entries[entry].Flags |= RESFF_EMBEDDED; + } + } +} + + +//========================================================================== +// +// Opens a resource file +// +//========================================================================== + +typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); + +FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); + +static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckHog, CheckMvl, CheckWHRes, CheckLump }; + +static int nulPrintf(FSMessageLevel msg, const char* fmt, ...) +{ + return 0; +} + +FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + if (Printf == nullptr) Printf = nulPrintf; + for(auto func : funcs) + { + if (containeronly && func == CheckLump) break; + FResourceFile *resfile = func(filename, file, filter, Printf, sp); + if (resfile != NULL) return resfile; + } + return NULL; +} + +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp); +} + + +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + FileReader file; + if (!file.OpenFile(filename)) return nullptr; + return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp); +} + +FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + if (Printf == nullptr) Printf = nulPrintf; + return CheckDir(filename, false, filter, Printf, sp); +} + +//========================================================================== +// +// Resource file base class +// +//========================================================================== + +FResourceFile::FResourceFile(const char *filename, StringPool* sp) +{ + stringpool = sp ? sp : new StringPool(false); + FileName = stringpool->Strdup(filename); +} + +FResourceFile::FResourceFile(const char *filename, FileReader &r, StringPool* sp) + : FResourceFile(filename,sp) +{ + Reader = std::move(r); +} + +FResourceFile::~FResourceFile() +{ + if (!stringpool->shared) delete stringpool; +} + +//========================================================================== +// +// this is just for completeness. For non-Zips only an uncompressed lump can +// be returned. +// +//========================================================================== + +FCompressedBuffer FResourceFile::GetRawData(uint32_t entry) +{ + size_t LumpSize = entry << NumLumps ? Entries[entry].Length : 0; + FCompressedBuffer cbuf = { LumpSize, LumpSize, METHOD_STORED, 0, 0, LumpSize == 0? nullptr : new char[LumpSize] }; + if (LumpSize > 0) + { + auto fr = GetEntryReader(entry, READER_SHARED, 0); + size_t read = fr.Read(cbuf.mBuffer, LumpSize); + if (read < LumpSize) + { + delete cbuf.mBuffer; + cbuf.mBuffer = nullptr; + LumpSize = cbuf.mCompressedSize = cbuf.mSize = 0; + } + } + if (LumpSize > 0) + cbuf.mCRC32 = crc32(0, (uint8_t*)cbuf.mBuffer, LumpSize); + return cbuf; +} + + +//========================================================================== +// +// normalize the visible file name in the system +// to lowercase canonical precomposed Unicode. +// +//========================================================================== + +const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp) +{ + if (!fn || !*fn) return ""; + auto norm = tolower_normalize(fn); + if (!norm) + { + if (fallbackcp == 437) + { + std::vector buffer; + ibm437_to_utf8(fn, buffer); + norm = tolower_normalize(buffer.data()); + } + // maybe handle other codepages + else + { + // if the filename is not valid UTF-8, nuke all bytes larger than 0x80 so that we still got something semi-usable + std::string ffn = fn; + for (auto& c : ffn) + { + if (c & 0x80) c = '@'; + } + norm = tolower_normalize(&ffn.front()); + } + } + FixPathSeparator(norm); + auto pooled = stringpool->Strdup(norm); + free(norm); + return pooled; + +} + +//========================================================================== +// +// allocate the Entries array +// this also uses the string pool to reduce maintenance +// +//========================================================================== + +FResourceEntry* FResourceFile::AllocateEntries(int count) +{ + NumLumps = count; + Entries = (FResourceEntry*)stringpool->Alloc(count * sizeof(FResourceEntry)); + memset(Entries, 0, count * sizeof(FResourceEntry)); + return Entries; +} + + +//--------------------------------------------------- +int entrycmp(const void* a, const void* b) +{ + FResourceEntry* rec1 = (FResourceEntry*)a; + FResourceEntry* rec2 = (FResourceEntry*)b; + // we are comparing lowercase UTF-8 here + return strcmp(rec1->FileName, rec2->FileName); +} + +//========================================================================== +// +// FResourceFile :: GenerateHash +// +// Generates a hash identifier for use in file identification. +// Potential uses are mod-wide compatibility settings or localization add-ons. +// This only hashes the directory but not the actual content +// +//========================================================================== + +void FResourceFile::GenerateHash() +{ + // hash the directory after sorting + using namespace FileSys::md5; + + auto n = snprintf(Hash, 48, "%08X-%04X-", (unsigned)Reader.GetLength(), NumLumps); + + md5_state_t state; + md5_init(&state); + + uint8_t digest[16]; + for(uint32_t i = 0; i < NumLumps; i++) + { + auto name = getName(i); + auto size = Length(i); + if (name == nullptr) + continue; + md5_append(&state, (const uint8_t*)name, (unsigned)strlen(name) + 1); + md5_append(&state, (const uint8_t*)&size, sizeof(size)); + } + md5_finish(&state, digest); + for (auto c : digest) + { + n += snprintf(Hash + n, 3, "%02X", c); + } +} + +//========================================================================== +// +// FResourceFile :: PostProcessArchive +// +// Sorts files by name. +// For files named "filter//*": Using the same filter rules as config +// autoloading, move them to the end and rename them without the "filter/" +// prefix. Filtered files that don't match are deleted. +// +//========================================================================== + +void FResourceFile::PostProcessArchive(LumpFilterInfo *filter) +{ + // only do this for archive types which contain full file names. All others are assumed to be pre-sorted. + if (NumLumps == 0 || !(Entries[0].Flags & RESFF_FULLPATH)) return; + + // First eliminate all unwanted files + if (filter) + { + for (uint32_t i = 0; i < NumLumps; i++) + { + std::string name = Entries[i].FileName; + for (auto& pattern : filter->blockednames) + { + if (wildcards::match(name, pattern)) + { + Entries[i].FileName = ""; + continue; + } + } + } + } + + // Entries in archives are sorted alphabetically. + qsort(Entries, NumLumps, sizeof(Entries[0]), entrycmp); + if (!filter) return; + FindCommonFolder(filter); + + // Filter out lumps using the same names as the Autoload.* sections + // in the ini file. We reduce the maximum lump concidered after + // each one so that we don't risk refiltering already filtered lumps. + uint32_t max = NumLumps; + + for (auto& LumpFilter : filter->gameTypeFilter) + { + ptrdiff_t len; + ptrdiff_t lastpos = -1; + std::string file; + while (size_t(len = LumpFilter.find_first_of('.', lastpos + 1)) != LumpFilter.npos) + { + max -= FilterLumps(std::string(LumpFilter, 0, len), max); + lastpos = len; + } + max -= FilterLumps(LumpFilter, max); + } + + JunkLeftoverFilters(max); + + for (uint32_t i = 0; i < NumLumps; i++) + { + CheckEmbedded(i, filter); + } + +} + +//========================================================================== +// +// FResourceFile :: FindCommonFolder +// +// Checks if all content is in a common folder that can be stripped out. +// +//========================================================================== + +void FResourceFile::FindCommonFolder(LumpFilterInfo* filter) +{ + std::string name0, name1; + bool foundspeciallump = false; + bool foundprefix = false; + + // try to find a path prefix. + for (uint32_t i = 0; i < NumLumps; i++) + { + if (*Entries[i].FileName == 0) continue; + std::string name = Entries[i].FileName; + + // first eliminate files we do not want to have. + // Some, like MacOS resource forks and executables are eliminated unconditionally, but the calling code can alsp pass a list of invalid content. + if (name.find("filter/") == 0) + return; // 'filter' is a reserved name of the file system. If this appears in the root we got no common folder, and 'filter' cannot be it. + + if (!foundprefix) + { + // check for special names, if one of these gets found this must be treated as a normal zip. + bool isspecial = name.find("/") == std::string::npos || + (filter && std::find(filter->reservedFolders.begin(), filter->reservedFolders.end(), name) != filter->reservedFolders.end()); + if (isspecial) break; + name0 = std::string(name, 0, name.rfind("/") + 1); + name1 = std::string(name, 0, name.find("/") + 1); + foundprefix = true; + } + + if (name.find(name0) != 0) + { + if (!name1.empty()) + { + name0 = name1; + if (name.find(name0) != 0) + { + name0 = ""; + } + } + if (name0.empty()) + break; + } + if (!foundspeciallump && filter) + { + // at least one of the more common definition lumps must be present. + for (auto& p : filter->requiredPrefixes) + { + if (name.find(name0 + p) == 0 || name.rfind(p) == size_t(name.length() - p.length())) + { + foundspeciallump = true; + break; + } + } + } + } + // If it ran through the list without finding anything it should not attempt any path remapping. + if (!foundspeciallump || name0.empty()) return; + + size_t pathlen = name0.length(); + for (uint32_t i = 0; i < NumLumps; i++) + { + if (Entries[i].FileName[0] == 0) continue; + Entries[i].FileName += pathlen; + + } +} + +//========================================================================== +// +// FResourceFile :: FilterLumps +// +// Finds any lumps between [0,) that match the pattern +// "filter//*" and moves them to the end of the lump list. +// Returns the number of lumps moved. +// +//========================================================================== + +int FResourceFile::FilterLumps(const std::string& filtername, uint32_t max) +{ + uint32_t start, end; + + if (filtername.empty()) + { + return 0; + } + std::string filter = "filter/" + filtername + '/'; + + bool found = FindPrefixRange(filter.c_str(), max, start, end); + + if (found) + { + + // Remove filter prefix from every name + for (uint32_t i = start; i < end; ++i) + { + assert(strnicmp(Entries[i].FileName, filter.c_str(), filter.length()) == 0); + Entries[i].FileName += filter.length(); + } + + // Move filtered lumps to the end of the lump list. + size_t count = (end - start); + auto from = Entries + start; + auto to = Entries + NumLumps - count; + assert (to >= from); + + if (from != to) + { + // Copy filtered lumps to a temporary buffer. + auto filteredlumps = new FResourceEntry[count]; + memcpy(filteredlumps, from, count * sizeof(*Entries)); + + // Shift lumps left to make room for the filtered ones at the end. + memmove(from, from + count, (NumLumps - end) * sizeof(*Entries)); + + // Copy temporary buffer to newly freed space. + memcpy(to, filteredlumps, count * sizeof(*Entries)); + + delete[] filteredlumps; + } + } + return end - start; +} + +//========================================================================== +// +// FResourceFile :: JunkLeftoverFilters +// +// Deletes any lumps beginning with "filter/" that were not matched. +// +//========================================================================== + +void FResourceFile::JunkLeftoverFilters(uint32_t max) +{ + uint32_t start, end; + if (FindPrefixRange("filter/", max, start, end)) + { + // Since the resource lumps may contain non-POD data besides the + // full name, we "delete" them by erasing their names so they + // can't be found. + for (uint32_t i = start; i < end; i++) + { + Entries[i].FileName = ""; + } + } +} + +//========================================================================== +// +// FResourceFile :: FindPrefixRange +// +// Finds a range of lumps that start with the prefix string. is left +// indicating the first matching one. is left at one plus the last +// matching one. +// +//========================================================================== + +bool FResourceFile::FindPrefixRange(const char* filter, uint32_t maxlump, uint32_t &start, uint32_t &end) +{ + uint32_t min, max, mid, inside; + int cmp = 0; + + end = start = 0; + + // Pretend that our range starts at 1 instead of 0 so that we can avoid + // unsigned overflow if the range starts at the first lump. + auto lumps = &Entries[-1]; + + // Binary search to find any match at all. + mid = min = 1, max = maxlump; + while (min <= max) + { + mid = min + (max - min) / 2; + auto lump = &lumps[mid]; + cmp = strnicmp(lump->FileName, filter, strlen(filter)); + if (cmp == 0) + break; + else if (cmp < 0) + min = mid + 1; + else + max = mid - 1; + } + if (max < min) + { // matched nothing + return false; + } + + // Binary search to find first match. + inside = mid; + min = 1, max = mid; + while (min <= max) + { + mid = min + (max - min) / 2; + auto lump = &lumps[mid]; + cmp = strnicmp(lump->FileName, filter, strlen(filter)); + // Go left on matches and right on misses. + if (cmp == 0) + max = mid - 1; + else + min = mid + 1; + } + start = mid + (cmp != 0) - 1; + + // Binary search to find last match. + min = inside, max = maxlump; + while (min <= max) + { + mid = min + (max - min) / 2; + auto lump = &lumps[mid]; + cmp = strnicmp(lump->FileName, filter, strlen(filter)); + // Go right on matches and left on misses. + if (cmp == 0) + min = mid + 1; + else + max = mid - 1; + } + end = mid - (cmp != 0); + return true; +} + +//========================================================================== +// +// Finds a lump by a given name. Used for savegames +// +//========================================================================== + +int FResourceFile::FindEntry(const char *name) +{ + auto norm_fn = tolower_normalize(name); + for (unsigned i = 0; i < NumLumps; i++) + { + if (!strcmp(norm_fn, getName(i))) + { + free(norm_fn); + return i; + } + } + free(norm_fn); + return -1; +} + + +//========================================================================== +// +// Caches a lump's content and increases the reference counter +// +//========================================================================== + +FileReader FResourceFile::GetEntryReader(uint32_t entry, int readertype, int readerflags) +{ + FileReader fr; + if (entry < NumLumps) + { + if (Entries[entry].Flags & RESFF_NEEDFILESTART) + { + SetEntryAddress(entry); + } + if (!(Entries[entry].Flags & RESFF_COMPRESSED)) + { + auto buf = Reader.GetBuffer(); + // if this is backed by a memory buffer, create a new reader directly referencing it. + if (buf != nullptr) + { + fr.OpenMemory(buf + Entries[entry].Position, Entries[entry].Length); + } + else + { + if (readertype == READER_SHARED && !mainThread) + readertype = READER_NEW; + if (readertype == READER_SHARED) + { + fr.OpenFilePart(Reader, Entries[entry].Position, Entries[entry].Length); + } + else if (readertype == READER_NEW) + { + fr.OpenFile(FileName, Entries[entry].Position, Entries[entry].Length); + } + else if (readertype == READER_CACHED) + { + Reader.Seek(Entries[entry].Position, FileReader::SeekSet); + auto data = Reader.Read(Entries[entry].Length); + fr.OpenMemoryArray(data); + } + } + } + else + { + FileReader fri; + if (readertype == READER_NEW || !mainThread) fri.OpenFile(FileName, Entries[entry].Position, Entries[entry].CompressedSize); + else fri.OpenFilePart(Reader, Entries[entry].Position, Entries[entry].CompressedSize); + int flags = DCF_TRANSFEROWNER | DCF_EXCEPTIONS; + if (readertype == READER_CACHED) flags |= DCF_CACHED; + else if (readerflags & READERFLAG_SEEKABLE) flags |= DCF_SEEKABLE; + OpenDecompressor(fr, fri, Entries[entry].Length, Entries[entry].Method, flags); + } + } + return fr; +} + +FileData FResourceFile::Read(uint32_t entry) +{ + if (!(Entries[entry].Flags & RESFF_COMPRESSED) && Reader.isOpen()) + { + auto buf = Reader.GetBuffer(); + // if this is backed by a memory buffer, we can just return a reference to the backing store. + if (buf != nullptr) + { + return FileData(buf + Entries[entry].Position, Entries[entry].Length, false); + } + } + + auto fr = GetEntryReader(entry, READER_SHARED, 0); + return fr.Read(entry < NumLumps ? Entries[entry].Length : 0); +} + + + +} diff --git a/src/common/filesystem/source/unicode.cpp b/src/common/filesystem/source/unicode.cpp new file mode 100644 index 0000000000..3d148270ae --- /dev/null +++ b/src/common/filesystem/source/unicode.cpp @@ -0,0 +1,161 @@ +/* +** unicode.cpp +** handling for conversion / comparison of filenames +** +**--------------------------------------------------------------------------- +** Copyright 2019 Christoph Oelckers +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +*/ + +#include "unicode.h" +#include "utf8proc.h" + +namespace FileSys { +//========================================================================== +// +// +// +//========================================================================== + +static void utf8_encode(int32_t codepoint, std::vector& buffer) +{ + if (codepoint < 0 || codepoint > 0x10FFFF || (codepoint >= 0xD800 && codepoint < 0xDFFF)) + { + codepoint = 0xFFFD; + } + uint8_t buf[4]; + auto size = utf8proc_encode_char(codepoint, buf); + for(int i = 0; i < size; i++) + buffer.push_back(buf[i]); +} + + +//========================================================================== +// +// convert UTF16 to UTF8 (needed for 7z) +// +//========================================================================== + +void utf16_to_utf8(const unsigned short* in, std::vector& buffer) +{ + buffer.clear(); + if (!*in) return; + + while (int char1 = *in++) + { + if (char1 >= 0xD800 && char1 <= 0xDBFF) + { + int char2 = *in; + + if (char2 >= 0xDC00 && char2 <= 0xDFFF) + { + in++; + char1 -= 0xD800; + char2 -= 0xDC00; + char1 <<= 10; + char1 += char2; + char1 += 0x010000; + } + else + { + // invalid code point - replace with placeholder + char1 = 0xFFFD; + } + } + else if (char1 >= 0xDC00 && char1 <= 0xDFFF) + { + // invalid code point - replace with placeholder + char1 = 0xFFFD; + } + utf8_encode(char1, buffer); + } + buffer.push_back(0); +} + +//========================================================================== +// +// convert UTF16 to UTF8 (needed for Zip) +// +//========================================================================== + +void ibm437_to_utf8(const char* in, std::vector& buffer) +{ + static const uint16_t ibm437map[] = { + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0, + }; + + buffer.clear(); + if (!*in) return; + + while (int char1 = (uint8_t)*in++) + { + if (char1 >= 0x80) char1 = ibm437map[char1 - 0x80]; + utf8_encode(char1, buffer); + } + buffer.push_back(0); +} + +//========================================================================== +// +// create a normalized lowercase version of a string. +// +//========================================================================== + +char *tolower_normalize(const char *str) +{ + utf8proc_uint8_t *retval; + utf8proc_map((const uint8_t*)str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_COMPOSE | UTF8PROC_CASEFOLD)); + return (char*)retval; +} + +//========================================================================== +// +// validates the string for proper UTF-8 +// +//========================================================================== + +bool unicode_validate(const char* str) +{ + while (*str != 0) + { + int cp; + auto result = utf8proc_iterate((const uint8_t*)str, -1, &cp); + if (result < 0) return false; + } + return true; +} + + +} diff --git a/src/common/filesystem/source/unicode.h b/src/common/filesystem/source/unicode.h new file mode 100644 index 0000000000..8783dbc718 --- /dev/null +++ b/src/common/filesystem/source/unicode.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +namespace FileSys { + +void utf16_to_utf8(const unsigned short* in, std::vector& buffer); +void ibm437_to_utf8(const char* in, std::vector& buffer); +char *tolower_normalize(const char *str); +bool unicode_validate(const char* str); + +} diff --git a/src/common/filesystem/source/wildcards.hpp b/src/common/filesystem/source/wildcards.hpp new file mode 100644 index 0000000000..9b8e4eac6b --- /dev/null +++ b/src/common/filesystem/source/wildcards.hpp @@ -0,0 +1,1833 @@ +// THIS FILE HAS BEEN GENERATED AUTOMATICALLY. DO NOT EDIT DIRECTLY. +// Generated: 2019-03-08 09:59:35.958950200 +// Copyright Tomas Zeman 2018. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef WILDCARDS_HPP +#define WILDCARDS_HPP +#define WILDCARDS_VERSION_MAJOR 1 +#define WILDCARDS_VERSION_MINOR 5 +#define WILDCARDS_VERSION_PATCH 0 +#ifndef WILDCARDS_CARDS_HPP +#define WILDCARDS_CARDS_HPP +#include +namespace wildcards +{ +template +struct cards +{ +constexpr cards(T a, T s, T e) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{false}, +alt_enabled{false} +{ +} +constexpr cards(T a, T s, T e, T so, T sc, T sn, T ao, T ac, T ar) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{true}, +set_open{std::move(so)}, +set_close{std::move(sc)}, +set_not{std::move(sn)}, +alt_enabled{true}, +alt_open{std::move(ao)}, +alt_close{std::move(ac)}, +alt_or{std::move(ar)} +{ +} +T anything; +T single; +T escape; +bool set_enabled; +T set_open; +T set_close; +T set_not; +bool alt_enabled; +T alt_open; +T alt_close; +T alt_or; +}; +enum class cards_type +{ +standard, +extended +}; +template <> +struct cards +{ +constexpr cards(cards_type type = cards_type::extended) +: set_enabled{type == cards_type::extended}, alt_enabled{type == cards_type::extended} +{ +} +constexpr cards(char a, char s, char e) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{false}, +alt_enabled{false} +{ +} +constexpr cards(char a, char s, char e, char so, char sc, char sn, char ao, char ac, char ar) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{true}, +set_open{std::move(so)}, +set_close{std::move(sc)}, +set_not{std::move(sn)}, +alt_enabled{true}, +alt_open{std::move(ao)}, +alt_close{std::move(ac)}, +alt_or{std::move(ar)} +{ +} +char anything{'*'}; +char single{'?'}; +char escape{'\\'}; +bool set_enabled{true}; +char set_open{'['}; +char set_close{']'}; +char set_not{'!'}; +bool alt_enabled{true}; +char alt_open{'('}; +char alt_close{')'}; +char alt_or{'|'}; +}; +template <> +struct cards +{ +constexpr cards(cards_type type = cards_type::extended) +: set_enabled{type == cards_type::extended}, alt_enabled{type == cards_type::extended} +{ +} +constexpr cards(char16_t a, char16_t s, char16_t e) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{false}, +alt_enabled{false} +{ +} +constexpr cards(char16_t a, char16_t s, char16_t e, char16_t so, char16_t sc, char16_t sn, +char16_t ao, char16_t ac, char16_t ar) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{true}, +set_open{std::move(so)}, +set_close{std::move(sc)}, +set_not{std::move(sn)}, +alt_enabled{true}, +alt_open{std::move(ao)}, +alt_close{std::move(ac)}, +alt_or{std::move(ar)} +{ +} +char16_t anything{u'*'}; +char16_t single{u'?'}; +char16_t escape{u'\\'}; +bool set_enabled{true}; +char16_t set_open{u'['}; +char16_t set_close{u']'}; +char16_t set_not{u'!'}; +bool alt_enabled{true}; +char16_t alt_open{u'('}; +char16_t alt_close{u')'}; +char16_t alt_or{u'|'}; +}; +template <> +struct cards +{ +constexpr cards(cards_type type = cards_type::extended) +: set_enabled{type == cards_type::extended}, alt_enabled{type == cards_type::extended} +{ +} +constexpr cards(char32_t a, char32_t s, char32_t e) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{false}, +alt_enabled{false} +{ +} +constexpr cards(char32_t a, char32_t s, char32_t e, char32_t so, char32_t sc, char32_t sn, +char32_t ao, char32_t ac, char32_t ar) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{true}, +set_open{std::move(so)}, +set_close{std::move(sc)}, +set_not{std::move(sn)}, +alt_enabled{true}, +alt_open{std::move(ao)}, +alt_close{std::move(ac)}, +alt_or{std::move(ar)} +{ +} +char32_t anything{U'*'}; +char32_t single{U'?'}; +char32_t escape{U'\\'}; +bool set_enabled{true}; +char32_t set_open{U'['}; +char32_t set_close{U']'}; +char32_t set_not{U'!'}; +bool alt_enabled{true}; +char32_t alt_open{U'('}; +char32_t alt_close{U')'}; +char32_t alt_or{U'|'}; +}; +template <> +struct cards +{ +constexpr cards(cards_type type = cards_type::extended) +: set_enabled{type == cards_type::extended}, alt_enabled{type == cards_type::extended} +{ +} +constexpr cards(wchar_t a, wchar_t s, wchar_t e) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{false}, +alt_enabled{false} +{ +} +constexpr cards(wchar_t a, wchar_t s, wchar_t e, wchar_t so, wchar_t sc, wchar_t sn, wchar_t ao, +wchar_t ac, wchar_t ar) +: anything{std::move(a)}, +single{std::move(s)}, +escape{std::move(e)}, +set_enabled{true}, +set_open{std::move(so)}, +set_close{std::move(sc)}, +set_not{std::move(sn)}, +alt_enabled{true}, +alt_open{std::move(ao)}, +alt_close{std::move(ac)}, +alt_or{std::move(ar)} +{ +} +wchar_t anything{L'*'}; +wchar_t single{L'?'}; +wchar_t escape{L'\\'}; +bool set_enabled{true}; +wchar_t set_open{L'['}; +wchar_t set_close{L']'}; +wchar_t set_not{L'!'}; +bool alt_enabled{true}; +wchar_t alt_open{L'('}; +wchar_t alt_close{L')'}; +wchar_t alt_or{L'|'}; +}; +template +constexpr cards make_cards(T&& a, T&& s, T&& e) +{ +return {std::forward(a), std::forward(s), std::forward(e)}; +} +template +constexpr cards make_cards(T&& a, T&& s, T&& e, T&& so, T&& sc, T&& sn, T&& ao, T&& ac, T&& ar) +{ +return {std::forward(a), std::forward(s), std::forward(e), +std::forward(so), std::forward(sc), std::forward(sn), +std::forward(ao), std::forward(ac), std::forward(ar)}; +} +} +#endif +#ifndef WILDCARDS_MATCH_HPP +#define WILDCARDS_MATCH_HPP +#include +#include +#include +#ifndef CONFIG_HPP +#define CONFIG_HPP +#ifndef QUICKCPPLIB_HAS_FEATURE_H +#define QUICKCPPLIB_HAS_FEATURE_H +#if __cplusplus >= 201103L +#if !defined(__cpp_alias_templates) +#define __cpp_alias_templates 190000 +#endif +#if !defined(__cpp_attributes) +#define __cpp_attributes 190000 +#endif +#if !defined(__cpp_constexpr) +#if __cplusplus >= 201402L +#define __cpp_constexpr 201304 +#else +#define __cpp_constexpr 190000 +#endif +#endif +#if !defined(__cpp_decltype) +#define __cpp_decltype 190000 +#endif +#if !defined(__cpp_delegating_constructors) +#define __cpp_delegating_constructors 190000 +#endif +#if !defined(__cpp_explicit_conversion) +#define __cpp_explicit_conversion 190000 +#endif +#if !defined(__cpp_inheriting_constructors) +#define __cpp_inheriting_constructors 190000 +#endif +#if !defined(__cpp_initializer_lists) +#define __cpp_initializer_lists 190000 +#endif +#if !defined(__cpp_lambdas) +#define __cpp_lambdas 190000 +#endif +#if !defined(__cpp_nsdmi) +#define __cpp_nsdmi 190000 +#endif +#if !defined(__cpp_range_based_for) +#define __cpp_range_based_for 190000 +#endif +#if !defined(__cpp_raw_strings) +#define __cpp_raw_strings 190000 +#endif +#if !defined(__cpp_ref_qualifiers) +#define __cpp_ref_qualifiers 190000 +#endif +#if !defined(__cpp_rvalue_references) +#define __cpp_rvalue_references 190000 +#endif +#if !defined(__cpp_static_assert) +#define __cpp_static_assert 190000 +#endif +#if !defined(__cpp_unicode_characters) +#define __cpp_unicode_characters 190000 +#endif +#if !defined(__cpp_unicode_literals) +#define __cpp_unicode_literals 190000 +#endif +#if !defined(__cpp_user_defined_literals) +#define __cpp_user_defined_literals 190000 +#endif +#if !defined(__cpp_variadic_templates) +#define __cpp_variadic_templates 190000 +#endif +#endif +#if __cplusplus >= 201402L +#if !defined(__cpp_aggregate_nsdmi) +#define __cpp_aggregate_nsdmi 190000 +#endif +#if !defined(__cpp_binary_literals) +#define __cpp_binary_literals 190000 +#endif +#if !defined(__cpp_decltype_auto) +#define __cpp_decltype_auto 190000 +#endif +#if !defined(__cpp_generic_lambdas) +#define __cpp_generic_lambdas 190000 +#endif +#if !defined(__cpp_init_captures) +#define __cpp_init_captures 190000 +#endif +#if !defined(__cpp_return_type_deduction) +#define __cpp_return_type_deduction 190000 +#endif +#if !defined(__cpp_sized_deallocation) +#define __cpp_sized_deallocation 190000 +#endif +#if !defined(__cpp_variable_templates) +#define __cpp_variable_templates 190000 +#endif +#endif +#if defined(_MSC_VER) && !defined(__clang__) +#if !defined(__cpp_exceptions) && defined(_CPPUNWIND) +#define __cpp_exceptions 190000 +#endif +#if !defined(__cpp_rtti) && defined(_CPPRTTI) +#define __cpp_rtti 190000 +#endif +#if !defined(__cpp_alias_templates) && _MSC_VER >= 1800 +#define __cpp_alias_templates 190000 +#endif +#if !defined(__cpp_attributes) +#define __cpp_attributes 190000 +#endif +#if !defined(__cpp_constexpr) && _MSC_FULL_VER >= 190023506 +#define __cpp_constexpr 190000 +#endif +#if !defined(__cpp_decltype) && _MSC_VER >= 1600 +#define __cpp_decltype 190000 +#endif +#if !defined(__cpp_delegating_constructors) && _MSC_VER >= 1800 +#define __cpp_delegating_constructors 190000 +#endif +#if !defined(__cpp_explicit_conversion) && _MSC_VER >= 1800 +#define __cpp_explicit_conversion 190000 +#endif +#if !defined(__cpp_inheriting_constructors) && _MSC_VER >= 1900 +#define __cpp_inheriting_constructors 190000 +#endif +#if !defined(__cpp_initializer_lists) && _MSC_VER >= 1900 +#define __cpp_initializer_lists 190000 +#endif +#if !defined(__cpp_lambdas) && _MSC_VER >= 1600 +#define __cpp_lambdas 190000 +#endif +#if !defined(__cpp_nsdmi) && _MSC_VER >= 1900 +#define __cpp_nsdmi 190000 +#endif +#if !defined(__cpp_range_based_for) && _MSC_VER >= 1700 +#define __cpp_range_based_for 190000 +#endif +#if !defined(__cpp_raw_strings) && _MSC_VER >= 1800 +#define __cpp_raw_strings 190000 +#endif +#if !defined(__cpp_ref_qualifiers) && _MSC_VER >= 1900 +#define __cpp_ref_qualifiers 190000 +#endif +#if !defined(__cpp_rvalue_references) && _MSC_VER >= 1600 +#define __cpp_rvalue_references 190000 +#endif +#if !defined(__cpp_static_assert) && _MSC_VER >= 1600 +#define __cpp_static_assert 190000 +#endif +#if !defined(__cpp_user_defined_literals) && _MSC_VER >= 1900 +#define __cpp_user_defined_literals 190000 +#endif +#if !defined(__cpp_variadic_templates) && _MSC_VER >= 1800 +#define __cpp_variadic_templates 190000 +#endif +#if !defined(__cpp_binary_literals) && _MSC_VER >= 1900 +#define __cpp_binary_literals 190000 +#endif +#if !defined(__cpp_decltype_auto) && _MSC_VER >= 1900 +#define __cpp_decltype_auto 190000 +#endif +#if !defined(__cpp_generic_lambdas) && _MSC_VER >= 1900 +#define __cpp_generic_lambdas 190000 +#endif +#if !defined(__cpp_init_captures) && _MSC_VER >= 1900 +#define __cpp_init_captures 190000 +#endif +#if !defined(__cpp_return_type_deduction) && _MSC_VER >= 1900 +#define __cpp_return_type_deduction 190000 +#endif +#if !defined(__cpp_sized_deallocation) && _MSC_VER >= 1900 +#define __cpp_sized_deallocation 190000 +#endif +#if !defined(__cpp_variable_templates) && _MSC_FULL_VER >= 190023506 +#define __cpp_variable_templates 190000 +#endif +#endif +#if(defined(__GNUC__) && !defined(__clang__)) +#define QUICKCPPLIB_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#if !defined(__cpp_exceptions) && defined(__EXCEPTIONS) +#define __cpp_exceptions 190000 +#endif +#if !defined(__cpp_rtti) && defined(__GXX_RTTI) +#define __cpp_rtti 190000 +#endif +#if defined(__GXX_EXPERIMENTAL_CXX0X__) +#if !defined(__cpp_alias_templates) && (QUICKCPPLIB_GCC >= 40700) +#define __cpp_alias_templates 190000 +#endif +#if !defined(__cpp_attributes) && (QUICKCPPLIB_GCC >= 40800) +#define __cpp_attributes 190000 +#endif +#if !defined(__cpp_constexpr) && (QUICKCPPLIB_GCC >= 40600) +#define __cpp_constexpr 190000 +#endif +#if !defined(__cpp_decltype) && (QUICKCPPLIB_GCC >= 40300) +#define __cpp_decltype 190000 +#endif +#if !defined(__cpp_delegating_constructors) && (QUICKCPPLIB_GCC >= 40700) +#define __cpp_delegating_constructors 190000 +#endif +#if !defined(__cpp_explicit_conversion) && (QUICKCPPLIB_GCC >= 40500) +#define __cpp_explicit_conversion 190000 +#endif +#if !defined(__cpp_inheriting_constructors) && (QUICKCPPLIB_GCC >= 40800) +#define __cpp_inheriting_constructors 190000 +#endif +#if !defined(__cpp_initializer_lists) && (QUICKCPPLIB_GCC >= 40800) +#define __cpp_initializer_lists 190000 +#endif +#if !defined(__cpp_lambdas) && (QUICKCPPLIB_GCC >= 40500) +#define __cpp_lambdas 190000 +#endif +#if !defined(__cpp_nsdmi) && (QUICKCPPLIB_GCC >= 40700) +#define __cpp_nsdmi 190000 +#endif +#if !defined(__cpp_range_based_for) && (QUICKCPPLIB_GCC >= 40600) +#define __cpp_range_based_for 190000 +#endif +#if !defined(__cpp_raw_strings) && (QUICKCPPLIB_GCC >= 40500) +#define __cpp_raw_strings 190000 +#endif +#if !defined(__cpp_ref_qualifiers) && (QUICKCPPLIB_GCC >= 40801) +#define __cpp_ref_qualifiers 190000 +#endif +#if !defined(__cpp_rvalue_references) && defined(__cpp_rvalue_reference) +#define __cpp_rvalue_references __cpp_rvalue_reference +#endif +#if !defined(__cpp_static_assert) && (QUICKCPPLIB_GCC >= 40300) +#define __cpp_static_assert 190000 +#endif +#if !defined(__cpp_unicode_characters) && (QUICKCPPLIB_GCC >= 40500) +#define __cpp_unicode_characters 190000 +#endif +#if !defined(__cpp_unicode_literals) && (QUICKCPPLIB_GCC >= 40500) +#define __cpp_unicode_literals 190000 +#endif +#if !defined(__cpp_user_defined_literals) && (QUICKCPPLIB_GCC >= 40700) +#define __cpp_user_defined_literals 190000 +#endif +#if !defined(__cpp_variadic_templates) && (QUICKCPPLIB_GCC >= 40400) +#define __cpp_variadic_templates 190000 +#endif +#endif +#endif +#if defined(__clang__) +#define QUICKCPPLIB_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#if !defined(__cpp_exceptions) && (defined(__EXCEPTIONS) || defined(_CPPUNWIND)) +#define __cpp_exceptions 190000 +#endif +#if !defined(__cpp_rtti) && (defined(__GXX_RTTI) || defined(_CPPRTTI)) +#define __cpp_rtti 190000 +#endif +#if defined(__GXX_EXPERIMENTAL_CXX0X__) +#if !defined(__cpp_alias_templates) && (QUICKCPPLIB_CLANG >= 30000) +#define __cpp_alias_templates 190000 +#endif +#if !defined(__cpp_attributes) && (QUICKCPPLIB_CLANG >= 30300) +#define __cpp_attributes 190000 +#endif +#if !defined(__cpp_constexpr) && (QUICKCPPLIB_CLANG >= 30100) +#define __cpp_constexpr 190000 +#endif +#if !defined(__cpp_decltype) && (QUICKCPPLIB_CLANG >= 20900) +#define __cpp_decltype 190000 +#endif +#if !defined(__cpp_delegating_constructors) && (QUICKCPPLIB_CLANG >= 30000) +#define __cpp_delegating_constructors 190000 +#endif +#if !defined(__cpp_explicit_conversion) && (QUICKCPPLIB_CLANG >= 30000) +#define __cpp_explicit_conversion 190000 +#endif +#if !defined(__cpp_inheriting_constructors) && (QUICKCPPLIB_CLANG >= 30300) +#define __cpp_inheriting_constructors 190000 +#endif +#if !defined(__cpp_initializer_lists) && (QUICKCPPLIB_CLANG >= 30100) +#define __cpp_initializer_lists 190000 +#endif +#if !defined(__cpp_lambdas) && (QUICKCPPLIB_CLANG >= 30100) +#define __cpp_lambdas 190000 +#endif +#if !defined(__cpp_nsdmi) && (QUICKCPPLIB_CLANG >= 30000) +#define __cpp_nsdmi 190000 +#endif +#if !defined(__cpp_range_based_for) && (QUICKCPPLIB_CLANG >= 30000) +#define __cpp_range_based_for 190000 +#endif +#if !defined(__cpp_raw_strings) && defined(__cpp_raw_string_literals) +#define __cpp_raw_strings __cpp_raw_string_literals +#endif +#if !defined(__cpp_raw_strings) && (QUICKCPPLIB_CLANG >= 30000) +#define __cpp_raw_strings 190000 +#endif +#if !defined(__cpp_ref_qualifiers) && (QUICKCPPLIB_CLANG >= 20900) +#define __cpp_ref_qualifiers 190000 +#endif +#if !defined(__cpp_rvalue_references) && defined(__cpp_rvalue_reference) +#define __cpp_rvalue_references __cpp_rvalue_reference +#endif +#if !defined(__cpp_rvalue_references) && (QUICKCPPLIB_CLANG >= 20900) +#define __cpp_rvalue_references 190000 +#endif +#if !defined(__cpp_static_assert) && (QUICKCPPLIB_CLANG >= 20900) +#define __cpp_static_assert 190000 +#endif +#if !defined(__cpp_unicode_characters) && (QUICKCPPLIB_CLANG >= 30000) +#define __cpp_unicode_characters 190000 +#endif +#if !defined(__cpp_unicode_literals) && (QUICKCPPLIB_CLANG >= 30000) +#define __cpp_unicode_literals 190000 +#endif +#if !defined(__cpp_user_defined_literals) && defined(__cpp_user_literals) +#define __cpp_user_defined_literals __cpp_user_literals +#endif +#if !defined(__cpp_user_defined_literals) && (QUICKCPPLIB_CLANG >= 30100) +#define __cpp_user_defined_literals 190000 +#endif +#if !defined(__cpp_variadic_templates) && (QUICKCPPLIB_CLANG >= 20900) +#define __cpp_variadic_templates 190000 +#endif +#endif +#endif +#endif +#define cfg_HAS_CONSTEXPR14 (__cpp_constexpr >= 201304) +#if cfg_HAS_CONSTEXPR14 +#define cfg_constexpr14 constexpr +#else +#define cfg_constexpr14 +#endif +#if cfg_HAS_CONSTEXPR14 && defined(__clang__) +#define cfg_HAS_FULL_FEATURED_CONSTEXPR14 1 +#else +#define cfg_HAS_FULL_FEATURED_CONSTEXPR14 1 +#endif +#endif +#ifndef CX_FUNCTIONAL_HPP +#define CX_FUNCTIONAL_HPP +#include +namespace cx +{ +template +struct less +{ +constexpr auto operator()(const T& lhs, const T& rhs) const -> decltype(lhs < rhs) +{ +return lhs < rhs; +} +}; +template <> +struct less +{ +template +constexpr auto operator()(T&& lhs, U&& rhs) const +-> decltype(std::forward(lhs) < std::forward(rhs)) +{ +return std::forward(lhs) < std::forward(rhs); +} +}; +template +struct equal_to +{ +constexpr auto operator()(const T& lhs, const T& rhs) const -> decltype(lhs == rhs) +{ +return lhs == rhs; +} +}; +template <> +struct equal_to +{ +template +constexpr auto operator()(T&& lhs, U&& rhs) const +-> decltype(std::forward(lhs) == std::forward(rhs)) +{ +return std::forward(lhs) == std::forward(rhs); +} +}; +} +#endif +#ifndef CX_ITERATOR_HPP +#define CX_ITERATOR_HPP +#include +#include +namespace cx +{ +template +constexpr It next(It it) +{ +return it + 1; +} +template +constexpr It prev(It it) +{ +return it - 1; +} +template +constexpr auto size(const C& c) -> decltype(c.size()) +{ +return c.size(); +} +template +constexpr std::size_t size(const T (&)[N]) +{ +return N; +} +template +constexpr auto empty(const C& c) -> decltype(c.empty()) +{ +return c.empty(); +} +template +constexpr bool empty(const T (&)[N]) +{ +return false; +} +template +constexpr bool empty(std::initializer_list il) +{ +return il.size() == 0; +} +template +constexpr auto begin(const C& c) -> decltype(c.begin()) +{ +return c.begin(); +} +template +constexpr auto begin(C& c) -> decltype(c.begin()) +{ +return c.begin(); +} +template +constexpr T* begin(T (&array)[N]) +{ +return &array[0]; +} +template +constexpr const E* begin(std::initializer_list il) +{ +return il.begin(); +} +template +constexpr auto cbegin(const C& c) -> decltype(cx::begin(c)) +{ +return cx::begin(c); +} +template +constexpr auto end(const C& c) -> decltype(c.end()) +{ +return c.end(); +} +template +constexpr auto end(C& c) -> decltype(c.end()) +{ +return c.end(); +} +template +constexpr T* end(T (&array)[N]) +{ +return &array[N]; +} +template +constexpr const E* end(std::initializer_list il) +{ +return il.end(); +} +template +constexpr auto cend(const C& c) -> decltype(cx::end(c)) +{ +return cx::end(c); +} +} +#endif +#ifndef WILDCARDS_UTILITY_HPP +#define WILDCARDS_UTILITY_HPP +#include +#include +namespace wildcards +{ +template +struct const_iterator +{ +using type = typename std::remove_cv< +typename std::remove_reference()))>::type>::type; +}; +template +using const_iterator_t = typename const_iterator::type; +template +struct iterator +{ +using type = typename std::remove_cv< +typename std::remove_reference()))>::type>::type; +}; +template +using iterator_t = typename iterator::type; +template +struct iterated_item +{ +using type = typename std::remove_cv< +typename std::remove_reference())>::type>::type; +}; +template +using iterated_item_t = typename iterated_item::type; +template +struct container_item +{ +using type = typename std::remove_cv< +typename std::remove_reference()))>::type>::type; +}; +template +using container_item_t = typename container_item::type; +} +#endif +namespace wildcards +{ +template +struct full_match_result +{ +bool res; +SequenceIterator s, send, s1; +PatternIterator p, pend, p1; +constexpr operator bool() const +{ +return res; +} +}; +namespace detail +{ +template +struct match_result +{ +bool res; +SequenceIterator s; +PatternIterator p; +constexpr operator bool() const +{ +return res; +} +}; +template +constexpr match_result make_match_result(bool res, +SequenceIterator s, +PatternIterator p) +{ +return {std::move(res), std::move(s), std::move(p)}; +} +template +constexpr full_match_result make_full_match_result( +SequenceIterator s, SequenceIterator send, PatternIterator p, PatternIterator pend, +match_result mr) +{ +return {std::move(mr.res), std::move(s), std::move(send), std::move(mr.s), +std::move(p), std::move(pend), std::move(mr.p)}; +} +#if !cfg_HAS_FULL_FEATURED_CONSTEXPR14 +constexpr bool throw_invalid_argument(const char* what_arg) +{ +return what_arg == nullptr ? false : throw std::invalid_argument(what_arg); +} +template +constexpr T throw_invalid_argument(T t, const char* what_arg) +{ +return what_arg == nullptr ? t : throw std::invalid_argument(what_arg); +} +constexpr bool throw_logic_error(const char* what_arg) +{ +return what_arg == nullptr ? false : throw std::logic_error(what_arg); +} +template +constexpr T throw_logic_error(T t, const char* what_arg) +{ +return what_arg == nullptr ? t : throw std::logic_error(what_arg); +} +#endif +enum class is_set_state +{ +open, +not_or_first, +first, +next +}; +template +constexpr bool is_set( +PatternIterator p, PatternIterator pend, +const cards>& c = cards>(), +is_set_state state = is_set_state::open) +{ +#if cfg_HAS_CONSTEXPR14 +if (!c.set_enabled) +{ +return false; +} +while (p != pend) +{ +switch (state) +{ +case is_set_state::open: +if (*p != c.set_open) +{ +return false; +} +state = is_set_state::not_or_first; +break; +case is_set_state::not_or_first: +if (*p == c.set_not) +{ +state = is_set_state::first; +} +else +{ +state = is_set_state::next; +} +break; +case is_set_state::first: +state = is_set_state::next; +break; +case is_set_state::next: +if (*p == c.set_close) +{ +return true; +} +break; +default: +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::logic_error( +"The program execution should never end up here throwing this exception"); +#else +return throw_logic_error( +"The program execution should never end up here throwing this exception"); +#endif +} +p = cx::next(p); +} +return false; +#else +return c.set_enabled && p != pend && +(state == is_set_state::open +? *p == c.set_open && is_set(cx::next(p), pend, c, is_set_state::not_or_first) +: +state == is_set_state::not_or_first +? *p == c.set_not ? is_set(cx::next(p), pend, c, is_set_state::first) +: is_set(cx::next(p), pend, c, is_set_state::next) +: state == is_set_state::first +? is_set(cx::next(p), pend, c, is_set_state::next) +: state == is_set_state::next +? *p == c.set_close || +is_set(cx::next(p), pend, c, is_set_state::next) +: throw std::logic_error("The program execution should never end up " +"here throwing this exception")); +#endif +} +enum class set_end_state +{ +open, +not_or_first, +first, +next +}; +template +constexpr PatternIterator set_end( +PatternIterator p, PatternIterator pend, +const cards>& c = cards>(), +set_end_state state = set_end_state::open) +{ +#if cfg_HAS_CONSTEXPR14 +if (!c.set_enabled) +{ +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The use of sets is disabled"); +#else +return throw_invalid_argument(p, "The use of sets is disabled"); +#endif +} +while (p != pend) +{ +switch (state) +{ +case set_end_state::open: +if (*p != c.set_open) +{ +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The given pattern is not a valid set"); +#else +return throw_invalid_argument(p, "The given pattern is not a valid set"); +#endif +} +state = set_end_state::not_or_first; +break; +case set_end_state::not_or_first: +if (*p == c.set_not) +{ +state = set_end_state::first; +} +else +{ +state = set_end_state::next; +} +break; +case set_end_state::first: +state = set_end_state::next; +break; +case set_end_state::next: +if (*p == c.set_close) +{ +return cx::next(p); +} +break; +default: +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::logic_error( +"The program execution should never end up here throwing this exception"); +#else +return throw_logic_error( +p, "The program execution should never end up here throwing this exception"); +#endif +} +p = cx::next(p); +} +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The given pattern is not a valid set"); +#else +return throw_invalid_argument(p, "The given pattern is not a valid set"); +#endif +#else +return !c.set_enabled +? throw std::invalid_argument("The use of sets is disabled") +: p == pend +? throw std::invalid_argument("The given pattern is not a valid set") +: +state == set_end_state::open +? *p == c.set_open +? set_end(cx::next(p), pend, c, set_end_state::not_or_first) +: throw std::invalid_argument("The given pattern is not a valid set") +: +state == set_end_state::not_or_first +? *p == c.set_not ? set_end(cx::next(p), pend, c, set_end_state::first) +: set_end(cx::next(p), pend, c, set_end_state::next) +: state == set_end_state::first +? set_end(cx::next(p), pend, c, set_end_state::next) +: state == set_end_state::next +? *p == c.set_close +? cx::next(p) +: set_end(cx::next(p), pend, c, set_end_state::next) +: throw std::logic_error( +"The program execution should never end up " +"here throwing this exception"); +#endif +} +enum class match_set_state +{ +open, +not_or_first_in, +first_out, +next_in, +next_out +}; +template > +constexpr match_result match_set( +SequenceIterator s, SequenceIterator send, PatternIterator p, PatternIterator pend, +const cards>& c = cards>(), +const EqualTo& equal_to = EqualTo(), match_set_state state = match_set_state::open) +{ +#if cfg_HAS_CONSTEXPR14 +if (!c.set_enabled) +{ +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The use of sets is disabled"); +#else +return throw_invalid_argument(make_match_result(false, s, p), "The use of sets is disabled"); +#endif +} +while (p != pend) +{ +switch (state) +{ +case match_set_state::open: +if (*p != c.set_open) +{ +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The given pattern is not a valid set"); +#else +return throw_invalid_argument(make_match_result(false, s, p), +"The given pattern is not a valid set"); +#endif +} +state = match_set_state::not_or_first_in; +break; +case match_set_state::not_or_first_in: +if (*p == c.set_not) +{ +state = match_set_state::first_out; +} +else +{ +if (s == send) +{ +return make_match_result(false, s, p); +} +if (equal_to(*s, *p)) +{ +return make_match_result(true, s, p); +} +state = match_set_state::next_in; +} +break; +case match_set_state::first_out: +if (s == send || equal_to(*s, *p)) +{ +return make_match_result(false, s, p); +} +state = match_set_state::next_out; +break; +case match_set_state::next_in: +if (*p == c.set_close || s == send) +{ +return make_match_result(false, s, p); +} +if (equal_to(*s, *p)) +{ +return make_match_result(true, s, p); +} +break; +case match_set_state::next_out: +if (*p == c.set_close) +{ +return make_match_result(true, s, p); +} +if (s == send || equal_to(*s, *p)) +{ +return make_match_result(false, s, p); +} +break; +default: +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::logic_error( +"The program execution should never end up here throwing this exception"); +#else +return throw_logic_error( +make_match_result(false, s, p), +"The program execution should never end up here throwing this exception"); +#endif +} +p = cx::next(p); +} +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The given pattern is not a valid set"); +#else +return throw_invalid_argument(make_match_result(false, s, p), +"The given pattern is not a valid set"); +#endif +#else +return !c.set_enabled +? throw std::invalid_argument("The use of sets is disabled") +: p == pend +? throw std::invalid_argument("The given pattern is not a valid set") +: state == match_set_state::open +? *p == c.set_open +? match_set(s, send, cx::next(p), pend, c, equal_to, +match_set_state::not_or_first_in) +: +throw std::invalid_argument("The given pattern is not a valid set") +: +state == match_set_state::not_or_first_in +? *p == c.set_not +? match_set(s, send, cx::next(p), pend, c, equal_to, +match_set_state::first_out) +: +s == send ? make_match_result(false, s, p) +: equal_to(*s, *p) +? make_match_result(true, s, p) +: match_set(s, send, cx::next(p), pend, c, +equal_to, match_set_state::next_in) +: +state == match_set_state::first_out +? s == send || equal_to(*s, *p) +? make_match_result(false, s, p) +: match_set(s, send, cx::next(p), pend, c, equal_to, +match_set_state::next_out) +: +state == match_set_state::next_in +? *p == c.set_close || s == send +? make_match_result(false, s, p) +: equal_to(*s, *p) ? make_match_result(true, s, p) +: match_set(s, send, cx::next(p), +pend, c, equal_to, state) +: +state == match_set_state::next_out +? *p == c.set_close +? make_match_result(true, s, p) +: s == send || equal_to(*s, *p) +? make_match_result(false, s, p) +: match_set(s, send, cx::next(p), pend, c, +equal_to, state) +: throw std::logic_error( +"The program execution should never end up " +"here " +"throwing this exception"); +#endif +} +enum class is_alt_state +{ +open, +next, +escape +}; +template +constexpr bool is_alt( +PatternIterator p, PatternIterator pend, +const cards>& c = cards>(), +is_alt_state state = is_alt_state::open, int depth = 0) +{ +#if cfg_HAS_CONSTEXPR14 +if (!c.alt_enabled) +{ +return false; +} +while (p != pend) +{ +switch (state) +{ +case is_alt_state::open: +if (*p != c.alt_open) +{ +return false; +} +state = is_alt_state::next; +++depth; +break; +case is_alt_state::next: +if (*p == c.escape) +{ +state = is_alt_state::escape; +} +else if (c.set_enabled && *p == c.set_open && +is_set(cx::next(p), pend, c, is_set_state::not_or_first)) +{ +p = cx::prev(set_end(cx::next(p), pend, c, set_end_state::not_or_first)); +} +else if (*p == c.alt_open) +{ +++depth; +} +else if (*p == c.alt_close) +{ +--depth; +if (depth == 0) +{ +return true; +} +} +break; +case is_alt_state::escape: +state = is_alt_state::next; +break; +default: +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::logic_error( +"The program execution should never end up here throwing this exception"); +#else +return throw_logic_error( +p, "The program execution should never end up here throwing this exception"); +#endif +} +p = cx::next(p); +} +return false; +#else +return c.alt_enabled && p != pend && +(state == is_alt_state::open +? *p == c.alt_open && is_alt(cx::next(p), pend, c, is_alt_state::next, depth + 1) +: state == is_alt_state::next +? *p == c.escape +? is_alt(cx::next(p), pend, c, is_alt_state::escape, depth) +: c.set_enabled && *p == c.set_open && +is_set(cx::next(p), pend, c, is_set_state::not_or_first) +? is_alt(set_end(cx::next(p), pend, c, set_end_state::not_or_first), +pend, c, state, depth) +: *p == c.alt_open +? is_alt(cx::next(p), pend, c, state, depth + 1) +: *p == c.alt_close +? depth == 1 || +is_alt(cx::next(p), pend, c, state, depth - 1) +: is_alt(cx::next(p), pend, c, state, depth) +: +state == is_alt_state::escape +? is_alt(cx::next(p), pend, c, is_alt_state::next, depth) +: throw std::logic_error( +"The program execution should never end up here throwing this " +"exception")); +#endif +} +enum class alt_end_state +{ +open, +next, +escape +}; +template +constexpr PatternIterator alt_end( +PatternIterator p, PatternIterator pend, +const cards>& c = cards>(), +alt_end_state state = alt_end_state::open, int depth = 0) +{ +#if cfg_HAS_CONSTEXPR14 +if (!c.alt_enabled) +{ +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The use of alternatives is disabled"); +#else +return throw_invalid_argument(p, "The use of alternatives is disabled"); +#endif +} +while (p != pend) +{ +switch (state) +{ +case alt_end_state::open: +if (*p != c.alt_open) +{ +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The given pattern is not a valid alternative"); +#else +return throw_invalid_argument(p, "The given pattern is not a valid alternative"); +#endif +} +state = alt_end_state::next; +++depth; +break; +case alt_end_state::next: +if (*p == c.escape) +{ +state = alt_end_state::escape; +} +else if (c.set_enabled && *p == c.set_open && +is_set(cx::next(p), pend, c, is_set_state::not_or_first)) +{ +p = cx::prev(set_end(cx::next(p), pend, c, set_end_state::not_or_first)); +} +else if (*p == c.alt_open) +{ +++depth; +} +else if (*p == c.alt_close) +{ +--depth; +if (depth == 0) +{ +return cx::next(p); +} +} +break; +case alt_end_state::escape: +state = alt_end_state::next; +break; +default: +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::logic_error( +"The program execution should never end up here throwing this exception"); +#else +return throw_logic_error( +p, "The program execution should never end up here throwing this exception"); +#endif +} +p = cx::next(p); +} +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The given pattern is not a valid alternative"); +#else +return throw_invalid_argument(p, "The given pattern is not a valid alternative"); +#endif +#else +return !c.alt_enabled +? throw std::invalid_argument("The use of alternatives is disabled") +: p == pend +? throw std::invalid_argument("The given pattern is not a valid alternative") +: state == alt_end_state::open +? *p == c.alt_open +? alt_end(cx::next(p), pend, c, alt_end_state::next, depth + 1) +: throw std::invalid_argument( +"The given pattern is not a valid alternative") +: state == alt_end_state::next +? *p == c.escape +? alt_end(cx::next(p), pend, c, alt_end_state::escape, depth) +: c.set_enabled && *p == c.set_open && +is_set(cx::next(p), pend, c, +is_set_state::not_or_first) +? alt_end(set_end(cx::next(p), pend, c, +set_end_state::not_or_first), +pend, c, state, depth) +: *p == c.alt_open +? alt_end(cx::next(p), pend, c, state, depth + 1) +: *p == c.alt_close +? depth == 1 ? cx::next(p) +: alt_end(cx::next(p), pend, c, +state, depth - 1) +: alt_end(cx::next(p), pend, c, state, depth) +: +state == alt_end_state::escape +? alt_end(cx::next(p), pend, c, alt_end_state::next, depth) +: throw std::logic_error( +"The program execution should never end up here throwing " +"this " +"exception"); +#endif +} +enum class alt_sub_end_state +{ +next, +escape +}; +template +constexpr PatternIterator alt_sub_end( +PatternIterator p, PatternIterator pend, +const cards>& c = cards>(), +alt_sub_end_state state = alt_sub_end_state::next, int depth = 1) +{ +#if cfg_HAS_CONSTEXPR14 +if (!c.alt_enabled) +{ +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The use of alternatives is disabled"); +#else +return throw_invalid_argument(p, "The use of alternatives is disabled"); +#endif +} +while (p != pend) +{ +switch (state) +{ +case alt_sub_end_state::next: +if (*p == c.escape) +{ +state = alt_sub_end_state::escape; +} +else if (c.set_enabled && *p == c.set_open && +is_set(cx::next(p), pend, c, is_set_state::not_or_first)) +{ +p = cx::prev(set_end(cx::next(p), pend, c, set_end_state::not_or_first)); +} +else if (*p == c.alt_open) +{ +++depth; +} +else if (*p == c.alt_close) +{ +--depth; +if (depth == 0) +{ +return p; +} +} +else if (*p == c.alt_or) +{ +if (depth == 1) +{ +return p; +} +} +break; +case alt_sub_end_state::escape: +state = alt_sub_end_state::next; +break; +default: +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::logic_error( +"The program execution should never end up here throwing this exception"); +#else +return throw_logic_error( +p, "The program execution should never end up here throwing this exception"); +#endif +} +p = cx::next(p); +} +#if cfg_HAS_FULL_FEATURED_CONSTEXPR14 +throw std::invalid_argument("The given pattern is not a valid alternative"); +#else +return throw_invalid_argument(p, "The given pattern is not a valid alternative"); +#endif +#else +return !c.alt_enabled +? throw std::invalid_argument("The use of alternatives is disabled") +: p == pend +? throw std::invalid_argument("The given pattern is not a valid alternative") +: state == alt_sub_end_state::next +? *p == c.escape +? alt_sub_end(cx::next(p), pend, c, alt_sub_end_state::escape, depth) +: c.set_enabled && *p == c.set_open && +is_set(cx::next(p), pend, c, is_set_state::not_or_first) +? alt_sub_end(set_end(cx::next(p), pend, c, +set_end_state::not_or_first), +pend, c, state, depth) +: *p == c.alt_open +? alt_sub_end(cx::next(p), pend, c, state, depth + 1) +: *p == c.alt_close +? depth == 1 ? p : alt_sub_end(cx::next(p), pend, +c, state, depth - 1) +: *p == c.alt_or +? depth == 1 ? p +: alt_sub_end(cx::next(p), pend, +c, state, depth) +: alt_sub_end(cx::next(p), pend, c, state, +depth) +: +state == alt_sub_end_state::escape +? alt_sub_end(cx::next(p), pend, c, alt_sub_end_state::next, depth) +: throw std::logic_error( +"The program execution should never end up here throwing " +"this " +"exception"); +#endif +} +template > +constexpr match_result match( +SequenceIterator s, SequenceIterator send, PatternIterator p, PatternIterator pend, +const cards>& c = cards>(), +const EqualTo& equal_to = EqualTo(), bool partial = false, bool escape = false); +template > +constexpr match_result match_alt( +SequenceIterator s, SequenceIterator send, PatternIterator p1, PatternIterator p1end, +PatternIterator p2, PatternIterator p2end, +const cards>& c = cards>(), +const EqualTo& equal_to = EqualTo(), bool partial = false) +{ +#if cfg_HAS_CONSTEXPR14 +auto result1 = match(s, send, p1, p1end, c, equal_to, true); +if (result1) +{ +auto result2 = match(result1.s, send, p2, p2end, c, equal_to, partial); +if (result2) +{ +return result2; +} +} +p1 = cx::next(p1end); +if (p1 == p2) +{ +return make_match_result(false, s, p1end); +} +return match_alt(s, send, p1, alt_sub_end(p1, p2, c), p2, p2end, c, equal_to, partial); +#else +return match(s, send, p1, p1end, c, equal_to, true) && +match(match(s, send, p1, p1end, c, equal_to, true).s, send, p2, p2end, c, equal_to, +partial) +? match(match(s, send, p1, p1end, c, equal_to, true).s, send, p2, p2end, c, equal_to, +partial) +: cx::next(p1end) == p2 +? make_match_result(false, s, p1end) +: match_alt(s, send, cx::next(p1end), alt_sub_end(cx::next(p1end), p2, c), p2, +p2end, c, equal_to, partial); +#endif +} +template +constexpr match_result match( +SequenceIterator s, SequenceIterator send, PatternIterator p, PatternIterator pend, +const cards>& c, const EqualTo& equal_to, bool partial, +bool escape) +{ +#if cfg_HAS_CONSTEXPR14 +if (p == pend) +{ +return make_match_result(partial || s == send, s, p); +} +if (escape) +{ +if (s == send || !equal_to(*s, *p)) +{ +return make_match_result(false, s, p); +} +return match(cx::next(s), send, cx::next(p), pend, c, equal_to, partial); +} +if (*p == c.anything) +{ +auto result = match(s, send, cx::next(p), pend, c, equal_to, partial); +if (result) +{ +return result; +} +if (s == send) +{ +return make_match_result(false, s, p); +} +return match(cx::next(s), send, p, pend, c, equal_to, partial); +} +if (*p == c.single) +{ +if (s == send) +{ +return make_match_result(false, s, p); +} +return match(cx::next(s), send, cx::next(p), pend, c, equal_to, partial); +} +if (*p == c.escape) +{ +return match(s, send, cx::next(p), pend, c, equal_to, partial, true); +} +if (c.set_enabled && *p == c.set_open && is_set(cx::next(p), pend, c, is_set_state::not_or_first)) +{ +auto result = +match_set(s, send, cx::next(p), pend, c, equal_to, match_set_state::not_or_first_in); +if (!result) +{ +return result; +} +return match(cx::next(s), send, set_end(cx::next(p), pend, c, set_end_state::not_or_first), +pend, c, equal_to, partial); +} +if (c.alt_enabled && *p == c.alt_open && is_alt(cx::next(p), pend, c, is_alt_state::next, 1)) +{ +auto p_alt_end = alt_end(cx::next(p), pend, c, alt_end_state::next, 1); +return match_alt(s, send, cx::next(p), alt_sub_end(cx::next(p), p_alt_end, c), p_alt_end, pend, +c, equal_to, partial); +} +if (s == send || !equal_to(*s, *p)) +{ +return make_match_result(false, s, p); +} +return match(cx::next(s), send, cx::next(p), pend, c, equal_to, partial); +#else +return p == pend +? make_match_result(partial || s == send, s, p) +: escape +? s == send || !equal_to(*s, *p) +? make_match_result(false, s, p) +: match(cx::next(s), send, cx::next(p), pend, c, equal_to, partial) +: *p == c.anything +? match(s, send, cx::next(p), pend, c, equal_to, partial) +? match(s, send, cx::next(p), pend, c, equal_to, partial) +: s == send ? make_match_result(false, s, p) +: match(cx::next(s), send, p, pend, c, equal_to, partial) +: *p == c.single +? s == send ? make_match_result(false, s, p) +: match(cx::next(s), send, cx::next(p), pend, c, +equal_to, partial) +: *p == c.escape +? match(s, send, cx::next(p), pend, c, equal_to, partial, true) +: c.set_enabled && *p == c.set_open && +is_set(cx::next(p), pend, c, +is_set_state::not_or_first) +? !match_set(s, send, cx::next(p), pend, c, equal_to, +match_set_state::not_or_first_in) +? match_set(s, send, cx::next(p), pend, c, +equal_to, +match_set_state::not_or_first_in) +: match(cx::next(s), send, +set_end(cx::next(p), pend, c, +set_end_state::not_or_first), +pend, c, equal_to, partial) +: c.alt_enabled && *p == c.alt_open && +is_alt(cx::next(p), pend, c, +is_alt_state::next, 1) +? match_alt( +s, send, cx::next(p), +alt_sub_end(cx::next(p), +alt_end(cx::next(p), pend, c, +alt_end_state::next, 1), +c), +alt_end(cx::next(p), pend, c, +alt_end_state::next, 1), +pend, c, equal_to, partial) +: s == send || !equal_to(*s, *p) +? make_match_result(false, s, p) +: match(cx::next(s), send, cx::next(p), pend, +c, equal_to, partial); +#endif +} +} +template > +constexpr full_match_result, const_iterator_t> match( +Sequence&& sequence, Pattern&& pattern, +const cards>& c = cards>(), +const EqualTo& equal_to = EqualTo()) +{ +return detail::make_full_match_result( +cx::cbegin(sequence), cx::cend(sequence), cx::cbegin(pattern), cx::cend(pattern), +detail::match(cx::cbegin(sequence), cx::cend(std::forward(sequence)), +cx::cbegin(pattern), cx::cend(std::forward(pattern)), c, equal_to)); +} +template , +typename = typename std::enable_if::value>::type> +constexpr full_match_result, const_iterator_t> match( +Sequence&& sequence, Pattern&& pattern, const EqualTo& equal_to) +{ +return match(std::forward(sequence), std::forward(pattern), +cards>(), equal_to); +} +} +#endif +#ifndef WILDCARDS_MATCHER_HPP +#define WILDCARDS_MATCHER_HPP +#include +#include +#include +#ifndef CX_STRING_VIEW_HPP +#define CX_STRING_VIEW_HPP +#include +#include +#ifndef CX_ALGORITHM_HPP +#define CX_ALGORITHM_HPP +namespace cx +{ +template +constexpr bool equal(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) +{ +#if cfg_HAS_CONSTEXPR14 +while (first1 != last1 && first2 != last2 && *first1 == *first2) +{ +++first1, ++first2; +} +return first1 == last1 && first2 == last2; +#else +return first1 != last1 && first2 != last2 && *first1 == *first2 +? equal(first1 + 1, last1, first2 + 1, last2) +: first1 == last1 && first2 == last2; +#endif +} +} +#endif +namespace cx +{ +template +class basic_string_view +{ +public: +using value_type = T; +constexpr basic_string_view() = default; +template +constexpr basic_string_view(const T (&str)[N]) : data_{&str[0]}, size_{N - 1} +{ +} +constexpr basic_string_view(const T* str, std::size_t s) : data_{str}, size_{s} +{ +} +constexpr const T* data() const +{ +return data_; +} +constexpr std::size_t size() const +{ +return size_; +} +constexpr bool empty() const +{ +return size() == 0; +} +constexpr const T* begin() const +{ +return data_; +} +constexpr const T* cbegin() const +{ +return begin(); +} +constexpr const T* end() const +{ +return data_ + size_; +} +constexpr const T* cend() const +{ +return end(); +} +private: +const T* data_{nullptr}; +std::size_t size_{0}; +}; +template +constexpr bool operator==(const basic_string_view& lhs, const basic_string_view& rhs) +{ +return equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} +template +constexpr bool operator!=(const basic_string_view& lhs, const basic_string_view& rhs) +{ +return !(lhs == rhs); +} +template +std::basic_ostream& operator<<(std::basic_ostream& o, const basic_string_view& s) +{ +o << s.data(); +return o; +} +template +constexpr basic_string_view make_string_view(const T (&str)[N]) +{ +return {str, N - 1}; +} +template +constexpr basic_string_view make_string_view(const T* str, std::size_t s) +{ +return {str, s}; +} +using string_view = basic_string_view; +using u16string_view = basic_string_view; +using u32string_view = basic_string_view; +using wstring_view = basic_string_view; +namespace literals +{ +constexpr string_view operator"" _sv(const char* str, std::size_t s) +{ +return {str, s}; +} +constexpr u16string_view operator"" _sv(const char16_t* str, std::size_t s) +{ +return {str, s}; +} +constexpr u32string_view operator"" _sv(const char32_t* str, std::size_t s) +{ +return {str, s}; +} +constexpr wstring_view operator"" _sv(const wchar_t* str, std::size_t s) +{ +return {str, s}; +} +} +} +#endif +namespace wildcards +{ +template > +class matcher +{ +public: +constexpr explicit matcher(Pattern&& pattern, const cards>& c = +cards>(), +const EqualTo& equal_to = EqualTo()) +: p_{cx::cbegin(pattern)}, +pend_{cx::cend(std::forward(pattern))}, +c_{c}, +equal_to_{equal_to} +{ +} +constexpr matcher(Pattern&& pattern, const EqualTo& equal_to) +: p_{cx::cbegin(pattern)}, +pend_{cx::cend(std::forward(pattern))}, +c_{cards>()}, +equal_to_{equal_to} +{ +} +template +constexpr full_match_result, const_iterator_t> matches( +Sequence&& sequence) const +{ +return detail::make_full_match_result( +cx::cbegin(sequence), cx::cend(sequence), p_, pend_, +detail::match(cx::cbegin(sequence), cx::cend(std::forward(sequence)), p_, pend_, +c_, equal_to_)); +} +private: +const_iterator_t p_; +const_iterator_t pend_; +cards> c_; +EqualTo equal_to_; +}; +template > +constexpr matcher make_matcher( +Pattern&& pattern, +const cards>& c = cards>(), +const EqualTo& equal_to = EqualTo()) +{ +return matcher{std::forward(pattern), c, equal_to}; +} +template , +typename = typename std::enable_if::value>::type> +constexpr matcher make_matcher(Pattern&& pattern, const EqualTo& equal_to) +{ +return make_matcher(std::forward(pattern), cards>(), equal_to); +} +namespace literals +{ +constexpr auto operator"" _wc(const char* str, std::size_t s) +-> decltype(make_matcher(cx::make_string_view(str, s + 1))) +{ +return make_matcher(cx::make_string_view(str, s + 1)); +} +constexpr auto operator"" _wc(const char16_t* str, std::size_t s) +-> decltype(make_matcher(cx::make_string_view(str, s + 1))) +{ +return make_matcher(cx::make_string_view(str, s + 1)); +} +constexpr auto operator"" _wc(const char32_t* str, std::size_t s) +-> decltype(make_matcher(cx::make_string_view(str, s + 1))) +{ +return make_matcher(cx::make_string_view(str, s + 1)); +} +constexpr auto operator"" _wc(const wchar_t* str, std::size_t s) +-> decltype(make_matcher(cx::make_string_view(str, s + 1))) +{ +return make_matcher(cx::make_string_view(str, s + 1)); +} +} +} +#endif +#endif diff --git a/src/common/fonts/font.cpp b/src/common/fonts/font.cpp index 3876dd7ea3..c0a9758be9 100644 --- a/src/common/fonts/font.cpp +++ b/src/common/fonts/font.cpp @@ -91,24 +91,25 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla // Read the font's configuration. // This will not be done for the default fonts, because they are not atomic and the default content does not need it. - TArray folderdata; + std::vector folderdata; if (filetemplate != nullptr) { FStringf path("fonts/%s/", filetemplate); // If a name template is given, collect data from all resource files. // For anything else, each folder is being treated as an atomic, self-contained unit and mixing from different glyph sets is blocked. - fileSystem.GetFilesInFolder(path, folderdata, nametemplate == nullptr); + fileSystem.GetFilesInFolder(path.GetChars(), folderdata, nametemplate == nullptr); //if (nametemplate == nullptr) { FStringf infpath("fonts/%s/font.inf", filetemplate); - unsigned index = folderdata.FindEx([=](const FolderEntry &entry) + size_t index; + for(index = 0; index < folderdata.size(); index++) { - return infpath.CompareNoCase(entry.name) == 0; - }); + if (infpath.CompareNoCase(folderdata[index].name) == 0) break; + } - if (index < folderdata.Size()) + if (index < folderdata.size()) { FScanner sc; sc.OpenLumpNum(folderdata[index].lumpnum); @@ -230,8 +231,8 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla // provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load as a 'y'. FStringf c120(nametemplate, 120); FStringf c122(nametemplate, 122); - if (!TexMan.CheckForTexture(c120, ETextureType::MiscPatch).isValid() || - !TexMan.CheckForTexture(c122, ETextureType::MiscPatch).isValid()) + if (!TexMan.CheckForTexture(c120.GetChars(), ETextureType::MiscPatch).isValid() || + !TexMan.CheckForTexture(c122.GetChars(), ETextureType::MiscPatch).isValid()) { // insert the incorrectly named '|' graphic in its correct position. position = 124; @@ -288,7 +289,7 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla } } } - if (folderdata.Size() > 0) + if (folderdata.size() > 0) { // all valid lumps must be named with a hex number that represents its Unicode character index. for (auto &entry : folderdata) @@ -389,7 +390,7 @@ class FSheetTexture : public FImageSource Y = y; } - int CopyPixels(FBitmap* dest, int conversion) + int CopyPixels(FBitmap* dest, int conversion, int frame = 0) override { auto& pic = sheetBitmaps[baseSheet]; dest->CopyPixelDataRGB(0, 0, pic.GetPixels() + 4 * (X + pic.GetWidth() * Y), Width, Height, 4, pic.GetWidth() * 4, 0, CF_BGRA); @@ -397,7 +398,7 @@ class FSheetTexture : public FImageSource } }; -void FFont::ReadSheetFont(TArray &folderdata, int width, int height, const DVector2 &Scale) +void FFont::ReadSheetFont(std::vector &folderdata, int width, int height, const DVector2 &Scale) { TMap charMap; int minchar = INT_MAX; @@ -421,7 +422,7 @@ void FFont::ReadSheetFont(TArray &folderdata, int width, int height FBitmap* sheetimg = &sheetBitmaps[sheetBitmaps.Reserve(1)]; sheetimg->Create(tex->GetTexelWidth(), tex->GetTexelHeight()); - tex->GetTexture()->GetImage()->CopyPixels(sheetimg, FImageSource::normal); + tex->GetTexture()->GetImage()->CopyPixels(sheetimg, FImageSource::normal, 0); for (int y = 0; y < numtex_y; y++) { @@ -710,10 +711,10 @@ int FFont::GetLuminosity (uint32_t *colorsused, TArray &Luminosity, int* // //========================================================================== -int FFont::GetColorTranslation (EColorRange range, PalEntry *color) const +FTranslationID FFont::GetColorTranslation (EColorRange range, PalEntry *color) const { // Single pic fonts do not set up their translation table and must always return 0. - if (Translations.Size() == 0) return 0; + if (Translations.Size() == 0) return NO_TRANSLATION; assert(Translations.Size() == (unsigned)NumTextColors); if (noTranslate) @@ -727,7 +728,7 @@ int FFont::GetColorTranslation (EColorRange range, PalEntry *color) const if (color != nullptr) *color = retcolor; } if (range == CR_UNDEFINED) - return -1; + return INVALID_TRANSLATION; else if (range >= NumTextColors) range = CR_UNTRANSLATED; return Translations[range]; @@ -1058,8 +1059,8 @@ void FFont::LoadTranslations() Translations.Resize(NumTextColors); for (int i = 0; i < NumTextColors; i++) { - if (i == CR_UNTRANSLATED) Translations[i] = 0; - else Translations[i] = LuminosityTranslation(i*2 + TranslationType, minlum, maxlum); + if (i == CR_UNTRANSLATED) Translations[i] = NO_TRANSLATION; + else Translations[i] = MakeLuminosityTranslation(i*2 + TranslationType, minlum, maxlum); } } diff --git a/src/common/fonts/fontinternals.h b/src/common/fonts/fontinternals.h index b74750c57e..149f9ab9f2 100644 --- a/src/common/fonts/fontinternals.h +++ b/src/common/fonts/fontinternals.h @@ -35,5 +35,3 @@ extern TArray TranslationLookup; extern TArray TranslationColors; class FImageSource; - -void RecordTextureColors (FImageSource *pic, uint32_t *usedcolors); diff --git a/src/common/fonts/hexfont.cpp b/src/common/fonts/hexfont.cpp index 643b44d4de..00dbf0830e 100644 --- a/src/common/fonts/hexfont.cpp +++ b/src/common/fonts/hexfont.cpp @@ -58,12 +58,12 @@ struct HexDataSource // //========================================================================== - void ParseDefinition(FResourceLump* font) + void ParseDefinition(FResourceFile* resf, int index) { FScanner sc; - auto data = font->Lock(); - sc.OpenMem("newconsolefont.hex", (const char*)data, font->Size()); + auto data = resf->Read(index); + sc.OpenMem("newconsolefont.hex", data.string(), (int)data.size()); sc.SetCMode(true); glyphdata.Push(0); // ensure that index 0 can be used as 'not present'. while (sc.GetString()) @@ -97,7 +97,6 @@ struct HexDataSource lumb = i * 255 / 17; SmallPal[i] = PalEntry(255, lumb, lumb, lumb); } - font->Unlock(); } }; @@ -109,8 +108,8 @@ class FHexFontChar : public FImageSource public: FHexFontChar(uint8_t *sourcedata, int swidth, int width, int height); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap* bmp, int conversion); + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap* bmp, int conversion, int frame = 0) override; protected: int SourceWidth; @@ -144,7 +143,7 @@ FHexFontChar::FHexFontChar (uint8_t *sourcedata, int swidth, int width, int heig // //========================================================================== -PalettedPixels FHexFontChar::CreatePalettedPixels(int) +PalettedPixels FHexFontChar::CreatePalettedPixels(int, int) { int destSize = Width * Height; PalettedPixels Pixels(destSize); @@ -175,7 +174,7 @@ PalettedPixels FHexFontChar::CreatePalettedPixels(int) return Pixels; } -int FHexFontChar::CopyPixels(FBitmap* bmp, int conversion) +int FHexFontChar::CopyPixels(FBitmap* bmp, int conversion, int frame) { if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. PalEntry* palette = hexdata.ConsolePal; @@ -190,8 +189,8 @@ class FHexFontChar2 : public FHexFontChar public: FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int height); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap* bmp, int conversion); + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap* bmp, int conversion, int frame = 0) override; }; @@ -216,7 +215,7 @@ FHexFontChar2::FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int hei // //========================================================================== -PalettedPixels FHexFontChar2::CreatePalettedPixels(int) +PalettedPixels FHexFontChar2::CreatePalettedPixels(int, int) { int destSize = Width * Height; PalettedPixels Pixels(destSize); @@ -255,7 +254,7 @@ PalettedPixels FHexFontChar2::CreatePalettedPixels(int) return Pixels; } -int FHexFontChar2::CopyPixels(FBitmap* bmp, int conversion) +int FHexFontChar2::CopyPixels(FBitmap* bmp, int conversion, int frame) { if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. PalEntry* palette = hexdata.SmallPal; @@ -323,8 +322,8 @@ class FHexFont : public FFont Translations.Resize(NumTextColors); for (int i = 0; i < NumTextColors; i++) { - if (i == CR_UNTRANSLATED) Translations[i] = 0; - else Translations[i] = LuminosityTranslation(i * 2 + 1, minlum, maxlum); + if (i == CR_UNTRANSLATED) Translations[i] = NO_TRANSLATION; + else Translations[i] = MakeLuminosityTranslation(i * 2 + 1, minlum, maxlum); } } @@ -387,8 +386,8 @@ class FHexFont2 : public FFont Translations.Resize(NumTextColors); for (int i = 0; i < NumTextColors; i++) { - if (i == CR_UNTRANSLATED) Translations[i] = 0; - else Translations[i] = LuminosityTranslation(i * 2, minlum, maxlum); + if (i == CR_UNTRANSLATED) Translations[i] = NO_TRANSLATION; + else Translations[i] = MakeLuminosityTranslation(i * 2, minlum, maxlum); } } }; @@ -440,8 +439,8 @@ void LoadHexFont(const char* filename) { auto resf = FResourceFile::OpenResourceFile(filename); if (resf == nullptr) I_FatalError("Unable to open %s", filename); - auto hexfont = resf->FindLump("newconsolefont.hex"); - if (hexfont == nullptr) I_FatalError("Unable to find newconsolefont.hex in %s", filename); - hexdata.ParseDefinition(hexfont); + auto hexfont = resf->FindEntry("newconsolefont.hex"); + if (hexfont < 0) I_FatalError("Unable to find newconsolefont.hex in %s", filename); + hexdata.ParseDefinition(resf, hexfont); delete resf; } diff --git a/src/common/fonts/schrift.cpp b/src/common/fonts/schrift.cpp new file mode 100644 index 0000000000..dc4958e5ab --- /dev/null +++ b/src/common/fonts/schrift.cpp @@ -0,0 +1,1570 @@ +/* This file is part of libschrift. + * + * © 2019-2022 Thomas Oltmann and contributors + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +# define restrict __restrict +#endif + +#if defined(_WIN32) +# define WIN32_LEAN_AND_MEAN 1 +# include +#else +//# define _POSIX_C_SOURCE 1 +# include +# include +# include +# include +#endif + +#include "schrift.h" + +#define SCHRIFT_VERSION "0.10.2" + +#define FILE_MAGIC_ONE 0x00010000 +#define FILE_MAGIC_TWO 0x74727565 + +#define HORIZONTAL_KERNING 0x01 +#define MINIMUM_KERNING 0x02 +#define CROSS_STREAM_KERNING 0x04 +#define OVERRIDE_KERNING 0x08 + +#define POINT_IS_ON_CURVE 0x01 +#define X_CHANGE_IS_SMALL 0x02 +#define Y_CHANGE_IS_SMALL 0x04 +#define REPEAT_FLAG 0x08 +#define X_CHANGE_IS_ZERO 0x10 +#define X_CHANGE_IS_POSITIVE 0x10 +#define Y_CHANGE_IS_ZERO 0x20 +#define Y_CHANGE_IS_POSITIVE 0x20 + +#define OFFSETS_ARE_LARGE 0x001 +#define ACTUAL_XY_OFFSETS 0x002 +#define GOT_A_SINGLE_SCALE 0x008 +#define THERE_ARE_MORE_COMPONENTS 0x020 +#define GOT_AN_X_AND_Y_SCALE 0x040 +#define GOT_A_SCALE_MATRIX 0x080 + +/* macros */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define SIGN(x) (((x) > 0) - ((x) < 0)) +/* Allocate values on the stack if they are small enough, else spill to heap. */ +#define STACK_ALLOC(var, type, thresh, count) \ + type var##_stack_[thresh]; \ + var = (type*)( (count) <= (thresh) ? var##_stack_ : calloc(sizeof(type), count) ); +#define STACK_FREE(var) \ + if (var != var##_stack_) free(var); + +enum { SrcMapping, SrcUser }; + +/* structs */ +typedef struct Point Point; +typedef struct Line Line; +typedef struct Curve Curve; +typedef struct Cell Cell; +typedef struct Outline Outline; +typedef struct Raster Raster; + +struct Point { double x, y; }; +struct Line { uint_least16_t beg, end; }; +struct Curve { uint_least16_t beg, end, ctrl; }; +struct Cell { double area, cover; }; + +struct Outline +{ + Point *points; + Curve *curves; + Line *lines; + uint_least16_t numPoints; + uint_least16_t capPoints; + uint_least16_t numCurves; + uint_least16_t capCurves; + uint_least16_t numLines; + uint_least16_t capLines; +}; + +struct Raster +{ + Cell *cells; + int width; + int height; +}; + +struct SFT_Font +{ + const uint8_t *memory; + uint_fast32_t size; +#if defined(_WIN32) + HANDLE mapping; +#endif + int source; + + uint_least16_t unitsPerEm; + int_least16_t locaFormat; + uint_least16_t numLongHmtx; +}; + +/* function declarations */ +/* generic utility functions */ +static void *schrift_reallocarray(void *optr, size_t nmemb, size_t size); +static inline int fast_floor(double x); +static inline int fast_ceil (double x); +/* file loading */ +static int map_file (SFT_Font *font, const char *filename); +static void unmap_file(SFT_Font *font); +static int init_font (SFT_Font *font); +/* simple mathematical operations */ +static Point midpoint(Point a, Point b); +static void transform_points(unsigned int numPts, Point *points, double trf[6]); +static void clip_points(unsigned int numPts, Point *points, int width, int height); +/* 'outline' data structure management */ +static int init_outline(Outline *outl); +static void free_outline(Outline *outl); +static int grow_points (Outline *outl); +static int grow_curves (Outline *outl); +static int grow_lines (Outline *outl); +/* TTF parsing utilities */ +static inline int is_safe_offset(SFT_Font *font, uint_fast32_t offset, uint_fast32_t margin); +static void *csearch(const void *key, const void *base, + size_t nmemb, size_t size, int (*compar)(const void *, const void *)); +static int cmpu16(const void *a, const void *b); +static int cmpu32(const void *a, const void *b); +static inline uint_least8_t getu8 (SFT_Font *font, uint_fast32_t offset); +static inline int_least8_t geti8 (SFT_Font *font, uint_fast32_t offset); +static inline uint_least16_t getu16(SFT_Font *font, uint_fast32_t offset); +static inline int_least16_t geti16(SFT_Font *font, uint_fast32_t offset); +static inline uint_least32_t getu32(SFT_Font *font, uint_fast32_t offset); +static int gettable(SFT_Font *font, const char* tag, uint_fast32_t *offset); +/* codepoint to glyph id translation */ +static int cmap_fmt4(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, uint_fast32_t *glyph); +static int cmap_fmt6(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, uint_fast32_t *glyph); +static int glyph_id(SFT_Font *font, SFT_UChar charCode, uint_fast32_t *glyph); +/* glyph metrics lookup */ +static int hor_metrics(SFT_Font *font, uint_fast32_t glyph, int *advanceWidth, int *leftSideBearing); +static int glyph_bbox(const SFT *sft, uint_fast32_t outline, int box[4]); +/* decoding outlines */ +static int outline_offset(SFT_Font *font, uint_fast32_t glyph, uint_fast32_t *offset); +static int simple_flags(SFT_Font *font, uint_fast32_t *offset, uint_fast16_t numPts, uint8_t *flags); +static int simple_points(SFT_Font *font, uint_fast32_t offset, uint_fast16_t numPts, uint8_t *flags, Point *points); +static int decode_contour(uint8_t *flags, uint_fast16_t basePoint, uint_fast16_t count, Outline *outl); +static int simple_outline(SFT_Font *font, uint_fast32_t offset, unsigned int numContours, Outline *outl); +static int compound_outline(SFT_Font *font, uint_fast32_t offset, int recDepth, Outline *outl); +static int decode_outline(SFT_Font *font, uint_fast32_t offset, int recDepth, Outline *outl); +/* tesselation */ +static int is_flat(Outline *outl, Curve curve); +static int tesselate_curve(Curve curve, Outline *outl); +static int tesselate_curves(Outline *outl); +/* silhouette rasterization */ +static void draw_line(Raster buf, Point origin, Point goal); +static void draw_lines(Outline *outl, Raster buf); +/* post-processing */ +static void post_process(Raster buf, uint8_t *image); +/* glyph rendering */ +static int render_outline(Outline *outl, double transform[6], SFT_Image image); + +/* function implementations */ + +const char * +sft_version(void) +{ + return SCHRIFT_VERSION; +} + +/* Loads a font from a user-supplied memory range. */ +SFT_Font * +sft_loadmem(const void *mem, size_t size) +{ + SFT_Font *font; + if (size > UINT32_MAX) { + return NULL; + } + if (!(font = (SFT_Font*)calloc(1, sizeof *font))) { + return NULL; + } + font->memory = (const uint8_t*)mem; + font->size = (uint_fast32_t) size; + font->source = SrcUser; + if (init_font(font) < 0) { + sft_freefont(font); + return NULL; + } + return font; +} + +/* Loads a font from the file system. To do so, it has to map the entire font into memory. */ +SFT_Font * +sft_loadfile(char const *filename) +{ + SFT_Font *font; + if (!(font = (SFT_Font*)calloc(1, sizeof *font))) { + return NULL; + } + if (map_file(font, filename) < 0) { + free(font); + return NULL; + } + if (init_font(font) < 0) { + sft_freefont(font); + return NULL; + } + return font; +} + +void +sft_freefont(SFT_Font *font) +{ + if (!font) return; + /* Only unmap if we mapped it ourselves. */ + if (font->source == SrcMapping) + unmap_file(font); + free(font); +} + +int +sft_lmetrics(const SFT *sft, SFT_LMetrics *metrics) +{ + double factor; + uint_fast32_t hhea; + memset(metrics, 0, sizeof *metrics); + if (gettable(sft->font, "hhea", &hhea) < 0) + return -1; + if (!is_safe_offset(sft->font, hhea, 36)) + return -1; + factor = sft->yScale / sft->font->unitsPerEm; + metrics->ascender = geti16(sft->font, hhea + 4) * factor; + metrics->descender = geti16(sft->font, hhea + 6) * factor; + metrics->lineGap = geti16(sft->font, hhea + 8) * factor; + return 0; +} + +int +sft_lookup(const SFT *sft, SFT_UChar codepoint, SFT_Glyph *glyph) +{ + return glyph_id(sft->font, codepoint, glyph); +} + +int +sft_gmetrics(const SFT *sft, SFT_Glyph glyph, SFT_GMetrics *metrics) +{ + int adv, lsb; + double xScale = sft->xScale / sft->font->unitsPerEm; + uint_fast32_t outline; + int bbox[4]; + + memset(metrics, 0, sizeof *metrics); + + if (hor_metrics(sft->font, glyph, &adv, &lsb) < 0) + return -1; + metrics->advanceWidth = adv * xScale; + metrics->leftSideBearing = lsb * xScale + sft->xOffset; + + if (outline_offset(sft->font, glyph, &outline) < 0) + return -1; + if (!outline) + return 0; + if (glyph_bbox(sft, outline, bbox) < 0) + return -1; + metrics->minWidth = bbox[2] - bbox[0] + 1; + metrics->minHeight = bbox[3] - bbox[1] + 1; + metrics->yOffset = sft->flags & SFT_DOWNWARD_Y ? -bbox[3] : bbox[1]; + + return 0; +} + +int +sft_kerning(const SFT *sft, SFT_Glyph leftGlyph, SFT_Glyph rightGlyph, + SFT_Kerning *kerning) +{ + void *match; + uint_fast32_t offset; + unsigned int numTables, numPairs, length, format, flags; + int value; + uint8_t key[4]; + + memset(kerning, 0, sizeof *kerning); + + if (gettable(sft->font, "kern", &offset) < 0) + return 0; + + /* Read kern table header. */ + if (!is_safe_offset(sft->font, offset, 4)) + return -1; + if (getu16(sft->font, offset) != 0) + return 0; + numTables = getu16(sft->font, offset + 2); + offset += 4; + + while (numTables > 0) { + /* Read subtable header. */ + if (!is_safe_offset(sft->font, offset, 6)) + return -1; + length = getu16(sft->font, offset + 2); + format = getu8 (sft->font, offset + 4); + flags = getu8 (sft->font, offset + 5); + offset += 6; + + if (format == 0 && (flags & HORIZONTAL_KERNING) && !(flags & MINIMUM_KERNING)) { + /* Read format 0 header. */ + if (!is_safe_offset(sft->font, offset, 8)) + return -1; + numPairs = getu16(sft->font, offset); + offset += 8; + /* Look up character code pair via binary search. */ + key[0] = (leftGlyph >> 8) & 0xFF; + key[1] = leftGlyph & 0xFF; + key[2] = (rightGlyph >> 8) & 0xFF; + key[3] = rightGlyph & 0xFF; + if ((match = bsearch(key, sft->font->memory + offset, + numPairs, 6, cmpu32)) != NULL) { + + value = geti16(sft->font, (uint_fast32_t) ((uint8_t *) match - sft->font->memory + 4)); + if (flags & CROSS_STREAM_KERNING) { + kerning->yShift += value; + } else { + kerning->xShift += value; + } + } + + } + + offset += length; + --numTables; + } + + kerning->xShift = kerning->xShift / sft->font->unitsPerEm * sft->xScale; + kerning->yShift = kerning->yShift / sft->font->unitsPerEm * sft->yScale; + + return 0; +} + +int +sft_render(const SFT *sft, SFT_Glyph glyph, SFT_Image image) +{ + uint_fast32_t outline; + double transform[6]; + int bbox[4]; + Outline outl; + + if (outline_offset(sft->font, glyph, &outline) < 0) + return -1; + if (!outline) + return 0; + if (glyph_bbox(sft, outline, bbox) < 0) + return -1; + /* Set up the transformation matrix such that + * the transformed bounding boxes min corner lines + * up with the (0, 0) point. */ + transform[0] = sft->xScale / sft->font->unitsPerEm; + transform[1] = 0.0; + transform[2] = 0.0; + transform[4] = sft->xOffset - bbox[0]; + if (sft->flags & SFT_DOWNWARD_Y) { + transform[3] = -sft->yScale / sft->font->unitsPerEm; + transform[5] = bbox[3] - sft->yOffset; + } else { + transform[3] = +sft->yScale / sft->font->unitsPerEm; + transform[5] = sft->yOffset - bbox[1]; + } + + memset(&outl, 0, sizeof outl); + if (init_outline(&outl) < 0) + goto failure; + + if (decode_outline(sft->font, outline, 0, &outl) < 0) + goto failure; + if (render_outline(&outl, transform, image) < 0) + goto failure; + + free_outline(&outl); + return 0; + +failure: + free_outline(&outl); + return -1; +} + +/* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +/* OpenBSD's schrift_reallocarray() standard libary function. + * A wrapper for realloc() that takes two size args like calloc(). + * Useful because it eliminates common integer overflow bugs. */ +static void * +schrift_reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +} + +/* TODO maybe we should use long here instead of int. */ +static inline int +fast_floor(double x) +{ + int i = (int) x; + return i - (i > x); +} + +static inline int +fast_ceil(double x) +{ + int i = (int) x; + return i + (i < x); +} + +#if defined(_WIN32) + +static int +map_file(SFT_Font *font, const char *filename) +{ + HANDLE file; + DWORD high, low; + + font->mapping = NULL; + font->memory = NULL; + + file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (file == INVALID_HANDLE_VALUE) { + return -1; + } + + low = GetFileSize(file, &high); + if (low == INVALID_FILE_SIZE) { + CloseHandle(file); + return -1; + } + + font->size = (size_t)high << (8 * sizeof(DWORD)) | low; + + font->mapping = CreateFileMapping(file, NULL, PAGE_READONLY, high, low, NULL); + if (!font->mapping) { + CloseHandle(file); + return -1; + } + + CloseHandle(file); + + font->memory = (const uint8_t*)MapViewOfFile(font->mapping, FILE_MAP_READ, 0, 0, 0); + if (!font->memory) { + CloseHandle(font->mapping); + font->mapping = NULL; + return -1; + } + + return 0; +} + +static void +unmap_file(SFT_Font *font) +{ + if (font->memory) { + UnmapViewOfFile(font->memory); + font->memory = NULL; + } + if (font->mapping) { + CloseHandle(font->mapping); + font->mapping = NULL; + } +} + +#else + +static int +map_file(SFT_Font *font, const char *filename) +{ + struct stat info; + int fd; + font->memory = reinterpret_cast(MAP_FAILED); + font->size = 0; + font->source = SrcMapping; + if ((fd = open(filename, O_RDONLY)) < 0) { + return -1; + } + if (fstat(fd, &info) < 0) { + close(fd); + return -1; + } + /* FIXME do some basic validation on info.st_size maybe - it is signed for example, so it *could* be negative .. */ + font->memory = reinterpret_cast(mmap(NULL, (size_t) info.st_size, PROT_READ, MAP_PRIVATE, fd, 0)); + font->size = (uint_fast32_t) info.st_size; + close(fd); + return font->memory == MAP_FAILED ? -1 : 0; +} + +static void +unmap_file(SFT_Font *font) +{ + assert(font->memory != MAP_FAILED); + munmap((void *) font->memory, font->size); +} + +#endif + +static int +init_font(SFT_Font *font) +{ + uint_fast32_t scalerType, head, hhea; + + if (!is_safe_offset(font, 0, 12)) + return -1; + /* Check for a compatible scalerType (magic number). */ + scalerType = getu32(font, 0); + if (scalerType != FILE_MAGIC_ONE && scalerType != FILE_MAGIC_TWO) + return -1; + + if (gettable(font, "head", &head) < 0) + return -1; + if (!is_safe_offset(font, head, 54)) + return -1; + font->unitsPerEm = getu16(font, head + 18); + font->locaFormat = geti16(font, head + 50); + + if (gettable(font, "hhea", &hhea) < 0) + return -1; + if (!is_safe_offset(font, hhea, 36)) + return -1; + font->numLongHmtx = getu16(font, hhea + 34); + + return 0; +} + +static Point +midpoint(Point a, Point b) +{ + return { + 0.5 * (a.x + b.x), + 0.5 * (a.y + b.y) + }; +} + +/* Applies an affine linear transformation matrix to a set of points. */ +static void +transform_points(unsigned int numPts, Point *points, double trf[6]) +{ + Point pt; + unsigned int i; + for (i = 0; i < numPts; ++i) { + pt = points[i]; + points[i] = { + pt.x * trf[0] + pt.y * trf[2] + trf[4], + pt.x * trf[1] + pt.y * trf[3] + trf[5] + }; + } +} + +static void +clip_points(unsigned int numPts, Point *points, int width, int height) +{ + Point pt; + unsigned int i; + + for (i = 0; i < numPts; ++i) { + pt = points[i]; + + if (pt.x < 0.0) { + points[i].x = 0.0; + } + if (pt.x >= width) { + points[i].x = nextafter(width, 0.0); + } + if (pt.y < 0.0) { + points[i].y = 0.0; + } + if (pt.y >= height) { + points[i].y = nextafter(height, 0.0); + } + } +} + +static int +init_outline(Outline *outl) +{ + /* TODO Smaller initial allocations */ + outl->numPoints = 0; + outl->capPoints = 64; + if (!(outl->points = (Point*)malloc(outl->capPoints * sizeof *outl->points))) + return -1; + outl->numCurves = 0; + outl->capCurves = 64; + if (!(outl->curves = (Curve*)malloc(outl->capCurves * sizeof *outl->curves))) + return -1; + outl->numLines = 0; + outl->capLines = 64; + if (!(outl->lines = (Line*)malloc(outl->capLines * sizeof *outl->lines))) + return -1; + return 0; +} + +static void +free_outline(Outline *outl) +{ + free(outl->points); + free(outl->curves); + free(outl->lines); +} + +static int +grow_points(Outline *outl) +{ + void *mem; + uint_fast16_t cap; + assert(outl->capPoints); + /* Since we use uint_fast16_t for capacities, we have to be extra careful not to trigger integer overflow. */ + if (outl->capPoints > UINT16_MAX / 2) + return -1; + cap = (uint_fast16_t) (2U * outl->capPoints); + if (!(mem = schrift_reallocarray(outl->points, cap, sizeof *outl->points))) + return -1; + outl->capPoints = (uint_least16_t) cap; + outl->points = (Point*)mem; + return 0; +} + +static int +grow_curves(Outline *outl) +{ + void *mem; + uint_fast16_t cap; + assert(outl->capCurves); + if (outl->capCurves > UINT16_MAX / 2) + return -1; + cap = (uint_fast16_t) (2U * outl->capCurves); + if (!(mem = schrift_reallocarray(outl->curves, cap, sizeof *outl->curves))) + return -1; + outl->capCurves = (uint_least16_t) cap; + outl->curves = (Curve*)mem; + return 0; +} + +static int +grow_lines(Outline *outl) +{ + void *mem; + uint_fast16_t cap; + assert(outl->capLines); + if (outl->capLines > UINT16_MAX / 2) + return -1; + cap = (uint_fast16_t) (2U * outl->capLines); + if (!(mem = schrift_reallocarray(outl->lines, cap, sizeof *outl->lines))) + return -1; + outl->capLines = (uint_least16_t) cap; + outl->lines = (Line*)mem; + return 0; +} + +static inline int +is_safe_offset(SFT_Font *font, uint_fast32_t offset, uint_fast32_t margin) +{ + if (offset > font->size) return 0; + if (font->size - offset < margin) return 0; + return 1; +} + +/* Like bsearch(), but returns the next highest element if key could not be found. */ +static void * +csearch(const void *key, const void *base, + size_t nmemb, size_t size, + int (*compar)(const void *, const void *)) +{ + const uint8_t *bytes = (const uint8_t*)base, *sample; + size_t low = 0, high = nmemb - 1, mid; + if (!nmemb) return NULL; + while (low != high) { + mid = low + (high - low) / 2; + sample = bytes + mid * size; + if (compar(key, sample) > 0) { + low = mid + 1; + } else { + high = mid; + } + } + return (uint8_t *) bytes + low * size; +} + +/* Used as a comparison function for [bc]search(). */ +static int +cmpu16(const void *a, const void *b) +{ + return memcmp(a, b, 2); +} + +/* Used as a comparison function for [bc]search(). */ +static int +cmpu32(const void *a, const void *b) +{ + return memcmp(a, b, 4); +} + +static inline uint_least8_t +getu8(SFT_Font *font, uint_fast32_t offset) +{ + assert(offset + 1 <= font->size); + return *(font->memory + offset); +} + +static inline int_least8_t +geti8(SFT_Font *font, uint_fast32_t offset) +{ + return (int_least8_t) getu8(font, offset); +} + +static inline uint_least16_t +getu16(SFT_Font *font, uint_fast32_t offset) +{ + assert(offset + 2 <= font->size); + const uint8_t *base = font->memory + offset; + uint_least16_t b1 = base[0], b0 = base[1]; + return (uint_least16_t) (b1 << 8 | b0); +} + +static inline int16_t +geti16(SFT_Font *font, uint_fast32_t offset) +{ + return (int_least16_t) getu16(font, offset); +} + +static inline uint32_t +getu32(SFT_Font *font, uint_fast32_t offset) +{ + assert(offset + 4 <= font->size); + const uint8_t *base = font->memory + offset; + uint_least32_t b3 = base[0], b2 = base[1], b1 = base[2], b0 = base[3]; + return (uint_least32_t) (b3 << 24 | b2 << 16 | b1 << 8 | b0); +} + +static int +gettable(SFT_Font *font, const char* tag, uint_fast32_t *offset) +{ + void *match; + unsigned int numTables; + /* No need to bounds-check access to the first 12 bytes - this gets already checked by init_font(). */ + numTables = getu16(font, 4); + if (!is_safe_offset(font, 12, (uint_fast32_t) numTables * 16)) + return -1; + if (!(match = bsearch(tag, font->memory + 12, numTables, 16, cmpu32))) + return -1; + *offset = getu32(font, (uint_fast32_t) ((uint8_t *) match - font->memory + 8)); + return 0; +} + +static int +cmap_fmt4(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, SFT_Glyph *glyph) +{ + const uint8_t *segPtr; + uint_fast32_t segIdxX2; + uint_fast32_t endCodes, startCodes, idDeltas, idRangeOffsets, idOffset; + uint_fast16_t segCountX2, idRangeOffset, startCode, shortCode, idDelta, id; + uint8_t key[2] = { (uint8_t) (charCode >> 8), (uint8_t) charCode }; + /* cmap format 4 only supports the Unicode BMP. */ + if (charCode > 0xFFFF) { + *glyph = 0; + return 0; + } + shortCode = (uint_fast16_t) charCode; + if (!is_safe_offset(font, table, 8)) + return -1; + segCountX2 = getu16(font, table); + if ((segCountX2 & 1) || !segCountX2) + return -1; + /* Find starting positions of the relevant arrays. */ + endCodes = table + 8; + startCodes = endCodes + segCountX2 + 2; + idDeltas = startCodes + segCountX2; + idRangeOffsets = idDeltas + segCountX2; + if (!is_safe_offset(font, idRangeOffsets, segCountX2)) + return -1; + /* Find the segment that contains shortCode by binary searching over + * the highest codes in the segments. */ + segPtr = (const uint8_t*)csearch(key, font->memory + endCodes, segCountX2 / 2, 2, cmpu16); + segIdxX2 = (uint_fast32_t) (segPtr - (font->memory + endCodes)); + /* Look up segment info from the arrays & short circuit if the spec requires. */ + if ((startCode = getu16(font, startCodes + segIdxX2)) > shortCode) + return 0; + idDelta = getu16(font, idDeltas + segIdxX2); + if (!(idRangeOffset = getu16(font, idRangeOffsets + segIdxX2))) { + /* Intentional integer under- and overflow. */ + *glyph = (shortCode + idDelta) & 0xFFFF; + return 0; + } + /* Calculate offset into glyph array and determine ultimate value. */ + idOffset = idRangeOffsets + segIdxX2 + idRangeOffset + 2U * (unsigned int) (shortCode - startCode); + if (!is_safe_offset(font, idOffset, 2)) + return -1; + id = getu16(font, idOffset); + /* Intentional integer under- and overflow. */ + *glyph = id ? (id + idDelta) & 0xFFFF : 0; + return 0; +} + +static int +cmap_fmt6(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, SFT_Glyph *glyph) +{ + unsigned int firstCode, entryCount; + /* cmap format 6 only supports the Unicode BMP. */ + if (charCode > 0xFFFF) { + *glyph = 0; + return 0; + } + if (!is_safe_offset(font, table, 4)) + return -1; + firstCode = getu16(font, table); + entryCount = getu16(font, table + 2); + if (!is_safe_offset(font, table, 4 + 2 * entryCount)) + return -1; + if (charCode < firstCode) + return -1; + charCode -= firstCode; + if (!(charCode < entryCount)) + return -1; + *glyph = getu16(font, table + 4 + 2 * charCode); + return 0; +} + +static int +cmap_fmt12_13(SFT_Font *font, uint_fast32_t table, SFT_UChar charCode, SFT_Glyph *glyph, int which) +{ + uint32_t len, numEntries; + uint_fast32_t i; + + *glyph = 0; + + /* check that the entire header is present */ + if (!is_safe_offset(font, table, 16)) + return -1; + + len = getu32(font, table + 4); + + /* A minimal header is 16 bytes */ + if (len < 16) + return -1; + + if (!is_safe_offset(font, table, len)) + return -1; + + numEntries = getu32(font, table + 12); + + for (i = 0; i < numEntries; ++i) { + uint32_t firstCode, lastCode, glyphOffset; + firstCode = getu32(font, table + (i * 12) + 16); + lastCode = getu32(font, table + (i * 12) + 16 + 4); + if (charCode < firstCode || charCode > lastCode) + continue; + glyphOffset = getu32(font, table + (i * 12) + 16 + 8); + if (which == 12) + *glyph = (charCode-firstCode) + glyphOffset; + else + *glyph = glyphOffset; + return 0; + } + + return 0; +} + +/* Maps Unicode code points to glyph indices. */ +static int +glyph_id(SFT_Font *font, SFT_UChar charCode, SFT_Glyph *glyph) +{ + uint_fast32_t cmap, entry, table; + unsigned int idx, numEntries; + int type, format; + + *glyph = 0; + + if (gettable(font, "cmap", &cmap) < 0) + return -1; + + if (!is_safe_offset(font, cmap, 4)) + return -1; + numEntries = getu16(font, cmap + 2); + + if (!is_safe_offset(font, cmap, 4 + numEntries * 8)) + return -1; + + /* First look for a 'full repertoire'/non-BMP map. */ + for (idx = 0; idx < numEntries; ++idx) { + entry = cmap + 4 + idx * 8; + type = getu16(font, entry) * 0100 + getu16(font, entry + 2); + /* Complete unicode map */ + if (type == 0004 || type == 0312) { + table = cmap + getu32(font, entry + 4); + if (!is_safe_offset(font, table, 8)) + return -1; + /* Dispatch based on cmap format. */ + format = getu16(font, table); + switch (format) { + case 12: + return cmap_fmt12_13(font, table, charCode, glyph, 12); + default: + return -1; + } + } + } + + /* If no 'full repertoire' cmap was found, try looking for a BMP map. */ + for (idx = 0; idx < numEntries; ++idx) { + entry = cmap + 4 + idx * 8; + type = getu16(font, entry) * 0100 + getu16(font, entry + 2); + /* Unicode BMP */ + if (type == 0003 || type == 0301) { + table = cmap + getu32(font, entry + 4); + if (!is_safe_offset(font, table, 6)) + return -1; + /* Dispatch based on cmap format. */ + switch (getu16(font, table)) { + case 4: + return cmap_fmt4(font, table + 6, charCode, glyph); + case 6: + return cmap_fmt6(font, table + 6, charCode, glyph); + default: + return -1; + } + } + } + + return -1; +} + +static int +hor_metrics(SFT_Font *font, SFT_Glyph glyph, int *advanceWidth, int *leftSideBearing) +{ + uint_fast32_t hmtx, offset, boundary; + if (gettable(font, "hmtx", &hmtx) < 0) + return -1; + if (glyph < font->numLongHmtx) { + /* glyph is inside long metrics segment. */ + offset = hmtx + 4 * glyph; + if (!is_safe_offset(font, offset, 4)) + return -1; + *advanceWidth = getu16(font, offset); + *leftSideBearing = geti16(font, offset + 2); + return 0; + } else { + /* glyph is inside short metrics segment. */ + boundary = hmtx + 4U * (uint_fast32_t) font->numLongHmtx; + if (boundary < 4) + return -1; + + offset = boundary - 4; + if (!is_safe_offset(font, offset, 4)) + return -1; + *advanceWidth = getu16(font, offset); + + offset = boundary + 2 * (glyph - font->numLongHmtx); + if (!is_safe_offset(font, offset, 2)) + return -1; + *leftSideBearing = geti16(font, offset); + return 0; + } +} + +static int +glyph_bbox(const SFT *sft, uint_fast32_t outline, int box[4]) +{ + double xScale, yScale; + /* Read the bounding box from the font file verbatim. */ + if (!is_safe_offset(sft->font, outline, 10)) + return -1; + box[0] = geti16(sft->font, outline + 2); + box[1] = geti16(sft->font, outline + 4); + box[2] = geti16(sft->font, outline + 6); + box[3] = geti16(sft->font, outline + 8); + if (box[2] <= box[0] || box[3] <= box[1]) + return -1; + /* Transform the bounding box into SFT coordinate space. */ + xScale = sft->xScale / sft->font->unitsPerEm; + yScale = sft->yScale / sft->font->unitsPerEm; + box[0] = (int) floor(box[0] * xScale + sft->xOffset); + box[1] = (int) floor(box[1] * yScale + sft->yOffset); + box[2] = (int) ceil (box[2] * xScale + sft->xOffset); + box[3] = (int) ceil (box[3] * yScale + sft->yOffset); + return 0; +} + +/* Returns the offset into the font that the glyph's outline is stored at. */ +static int +outline_offset(SFT_Font *font, SFT_Glyph glyph, uint_fast32_t *offset) +{ + uint_fast32_t loca, glyf; + uint_fast32_t base, this_, next; + + if (gettable(font, "loca", &loca) < 0) + return -1; + if (gettable(font, "glyf", &glyf) < 0) + return -1; + + if (font->locaFormat == 0) { + base = loca + 2 * glyph; + + if (!is_safe_offset(font, base, 4)) + return -1; + + this_ = 2U * (uint_fast32_t) getu16(font, base); + next = 2U * (uint_fast32_t) getu16(font, base + 2); + } else { + base = loca + 4 * glyph; + + if (!is_safe_offset(font, base, 8)) + return -1; + + this_ = getu32(font, base); + next = getu32(font, base + 4); + } + + *offset = this_ == next ? 0 : glyf + this_; + return 0; +} + +/* For a 'simple' outline, determines each point of the outline with a set of flags. */ +static int +simple_flags(SFT_Font *font, uint_fast32_t *offset, uint_fast16_t numPts, uint8_t *flags) +{ + uint_fast32_t off = *offset; + uint_fast16_t i; + uint8_t value = 0, repeat = 0; + for (i = 0; i < numPts; ++i) { + if (repeat) { + --repeat; + } else { + if (!is_safe_offset(font, off, 1)) + return -1; + value = getu8(font, off++); + if (value & REPEAT_FLAG) { + if (!is_safe_offset(font, off, 1)) + return -1; + repeat = getu8(font, off++); + } + } + flags[i] = value; + } + *offset = off; + return 0; +} + +/* For a 'simple' outline, decodes both X and Y coordinates for each point of the outline. */ +static int +simple_points(SFT_Font *font, uint_fast32_t offset, uint_fast16_t numPts, uint8_t *flags, Point *points) +{ + long accum, value, bit; + uint_fast16_t i; + + accum = 0L; + for (i = 0; i < numPts; ++i) { + if (flags[i] & X_CHANGE_IS_SMALL) { + if (!is_safe_offset(font, offset, 1)) + return -1; + value = (long) getu8(font, offset++); + bit = !!(flags[i] & X_CHANGE_IS_POSITIVE); + accum -= (value ^ -bit) + bit; + } else if (!(flags[i] & X_CHANGE_IS_ZERO)) { + if (!is_safe_offset(font, offset, 2)) + return -1; + accum += geti16(font, offset); + offset += 2; + } + points[i].x = (double) accum; + } + + accum = 0L; + for (i = 0; i < numPts; ++i) { + if (flags[i] & Y_CHANGE_IS_SMALL) { + if (!is_safe_offset(font, offset, 1)) + return -1; + value = (long) getu8(font, offset++); + bit = !!(flags[i] & Y_CHANGE_IS_POSITIVE); + accum -= (value ^ -bit) + bit; + } else if (!(flags[i] & Y_CHANGE_IS_ZERO)) { + if (!is_safe_offset(font, offset, 2)) + return -1; + accum += geti16(font, offset); + offset += 2; + } + points[i].y = (double) accum; + } + + return 0; +} + +static int +decode_contour(uint8_t *flags, uint_fast16_t basePoint, uint_fast16_t count, Outline *outl) +{ + uint_fast16_t i; + uint_least16_t looseEnd, beg, ctrl, center, cur; + unsigned int gotCtrl; + + /* Skip contours with less than two points, since the following algorithm can't handle them and + * they should appear invisible either way (because they don't have any area). */ + if (count < 2) return 0; + + assert(basePoint <= UINT16_MAX - count); + + if (flags[0] & POINT_IS_ON_CURVE) { + looseEnd = (uint_least16_t) basePoint++; + ++flags; + --count; + } else if (flags[count - 1] & POINT_IS_ON_CURVE) { + looseEnd = (uint_least16_t) (basePoint + --count); + } else { + if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0) + return -1; + + looseEnd = outl->numPoints; + outl->points[outl->numPoints++] = midpoint( + outl->points[basePoint], + outl->points[basePoint + count - 1]); + } + beg = looseEnd; + gotCtrl = 0; + for (i = 0; i < count; ++i) { + /* cur can't overflow because we ensure that basePoint + count < 0xFFFF before calling decode_contour(). */ + cur = (uint_least16_t) (basePoint + i); + /* NOTE clang-analyzer will often flag this and another piece of code because it thinks that flags and + * outl->points + basePoint don't always get properly initialized -- even when you explicitly loop over both + * and set every element to zero (but not when you use memset). This is a known clang-analyzer bug: + * http://clang-developers.42468.n3.nabble.com/StaticAnalyzer-False-positive-with-loop-handling-td4053875.html */ + if (flags[i] & POINT_IS_ON_CURVE) { + if (gotCtrl) { + if (outl->numCurves >= outl->capCurves && grow_curves(outl) < 0) + return -1; + outl->curves[outl->numCurves++] = { beg, cur, ctrl }; + } else { + if (outl->numLines >= outl->capLines && grow_lines(outl) < 0) + return -1; + outl->lines[outl->numLines++] = { beg, cur }; + } + beg = cur; + gotCtrl = 0; + } else { + if (gotCtrl) { + center = outl->numPoints; + if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0) + return -1; + outl->points[center] = midpoint(outl->points[ctrl], outl->points[cur]); + ++outl->numPoints; + + if (outl->numCurves >= outl->capCurves && grow_curves(outl) < 0) + return -1; + outl->curves[outl->numCurves++] = { beg, center, ctrl }; + + beg = center; + } + ctrl = cur; + gotCtrl = 1; + } + } + if (gotCtrl) { + if (outl->numCurves >= outl->capCurves && grow_curves(outl) < 0) + return -1; + outl->curves[outl->numCurves++] = { beg, looseEnd, ctrl }; + } else { + if (outl->numLines >= outl->capLines && grow_lines(outl) < 0) + return -1; + outl->lines[outl->numLines++] = { beg, looseEnd }; + } + + return 0; +} + +static int +simple_outline(SFT_Font *font, uint_fast32_t offset, unsigned int numContours, Outline *outl) +{ + uint_fast16_t *endPts = NULL; + uint8_t *flags = NULL; + uint_fast16_t numPts; + unsigned int i; + uint_fast16_t beg; + + assert(numContours > 0); + + uint_fast16_t basePoint = outl->numPoints; + + if (!is_safe_offset(font, offset, numContours * 2 + 2)) + goto failure; + numPts = getu16(font, offset + (numContours - 1) * 2); + if (numPts >= UINT16_MAX) + goto failure; + numPts++; + if (outl->numPoints > UINT16_MAX - numPts) + goto failure; + + while (outl->capPoints < basePoint + numPts) { + if (grow_points(outl) < 0) + goto failure; + } + + STACK_ALLOC(endPts, uint_fast16_t, 16, numContours); + if (endPts == NULL) + goto failure; + STACK_ALLOC(flags, uint8_t, 128, numPts); + if (flags == NULL) + goto failure; + + for (i = 0; i < numContours; ++i) { + endPts[i] = getu16(font, offset); + offset += 2; + } + /* Ensure that endPts are never falling. + * Falling endPts have no sensible interpretation and most likely only occur in malicious input. + * Therefore, we bail, should we ever encounter such input. */ + for (i = 0; i < numContours - 1; ++i) { + if (endPts[i + 1] < endPts[i] + 1) + goto failure; + } + offset += 2U + getu16(font, offset); + + if (simple_flags(font, &offset, numPts, flags) < 0) + goto failure; + if (simple_points(font, offset, numPts, flags, outl->points + basePoint) < 0) + goto failure; + outl->numPoints = (uint_least16_t) (outl->numPoints + numPts); + + beg = 0; + for (i = 0; i < numContours; ++i) { + uint_fast16_t count = endPts[i] - beg + 1; + if (decode_contour(flags + beg, basePoint + beg, count, outl) < 0) + goto failure; + beg = endPts[i] + 1; + } + + STACK_FREE(endPts); + STACK_FREE(flags); + return 0; +failure: + STACK_FREE(endPts); + STACK_FREE(flags); + return -1; +} + +static int +compound_outline(SFT_Font *font, uint_fast32_t offset, int recDepth, Outline *outl) +{ + double local[6]; + uint_fast32_t outline; + unsigned int flags, glyph, basePoint; + /* Guard against infinite recursion (compound glyphs that have themselves as component). */ + if (recDepth >= 4) + return -1; + do { + memset(local, 0, sizeof local); + if (!is_safe_offset(font, offset, 4)) + return -1; + flags = getu16(font, offset); + glyph = getu16(font, offset + 2); + offset += 4; + /* We don't implement point matching, and neither does stb_truetype for that matter. */ + if (!(flags & ACTUAL_XY_OFFSETS)) + return -1; + /* Read additional X and Y offsets (in FUnits) of this component. */ + if (flags & OFFSETS_ARE_LARGE) { + if (!is_safe_offset(font, offset, 4)) + return -1; + local[4] = geti16(font, offset); + local[5] = geti16(font, offset + 2); + offset += 4; + } else { + if (!is_safe_offset(font, offset, 2)) + return -1; + local[4] = geti8(font, offset); + local[5] = geti8(font, offset + 1); + offset += 2; + } + if (flags & GOT_A_SINGLE_SCALE) { + if (!is_safe_offset(font, offset, 2)) + return -1; + local[0] = geti16(font, offset) / 16384.0; + local[3] = local[0]; + offset += 2; + } else if (flags & GOT_AN_X_AND_Y_SCALE) { + if (!is_safe_offset(font, offset, 4)) + return -1; + local[0] = geti16(font, offset + 0) / 16384.0; + local[3] = geti16(font, offset + 2) / 16384.0; + offset += 4; + } else if (flags & GOT_A_SCALE_MATRIX) { + if (!is_safe_offset(font, offset, 8)) + return -1; + local[0] = geti16(font, offset + 0) / 16384.0; + local[1] = geti16(font, offset + 2) / 16384.0; + local[2] = geti16(font, offset + 4) / 16384.0; + local[3] = geti16(font, offset + 6) / 16384.0; + offset += 8; + } else { + local[0] = 1.0; + local[3] = 1.0; + } + /* At this point, Apple's spec more or less tells you to scale the matrix by its own L1 norm. + * But stb_truetype scales by the L2 norm. And FreeType2 doesn't scale at all. + * Furthermore, Microsoft's spec doesn't even mention anything like this. + * It's almost as if nobody ever uses this feature anyway. */ + if (outline_offset(font, glyph, &outline) < 0) + return -1; + if (outline) { + basePoint = outl->numPoints; + if (decode_outline(font, outline, recDepth + 1, outl) < 0) + return -1; + transform_points(outl->numPoints - basePoint, outl->points + basePoint, local); + } + } while (flags & THERE_ARE_MORE_COMPONENTS); + + return 0; +} + +static int +decode_outline(SFT_Font *font, uint_fast32_t offset, int recDepth, Outline *outl) +{ + int numContours; + if (!is_safe_offset(font, offset, 10)) + return -1; + numContours = geti16(font, offset); + if (numContours > 0) { + /* Glyph has a 'simple' outline consisting of a number of contours. */ + return simple_outline(font, offset + 10, (unsigned int) numContours, outl); + } else if (numContours < 0) { + /* Glyph has a compound outline combined from mutiple other outlines. */ + return compound_outline(font, offset + 10, recDepth, outl); + } else { + return 0; + } +} + +/* A heuristic to tell whether a given curve can be approximated closely enough by a line. */ +static int +is_flat(Outline *outl, Curve curve) +{ + const double maxArea2 = 2.0; + Point a = outl->points[curve.beg]; + Point b = outl->points[curve.ctrl]; + Point c = outl->points[curve.end]; + Point g = { b.x-a.x, b.y-a.y }; + Point h = { c.x-a.x, c.y-a.y }; + double area2 = fabs(g.x*h.y-h.x*g.y); + return area2 <= maxArea2; +} + +static int +tesselate_curve(Curve curve, Outline *outl) +{ + /* From my tests I can conclude that this stack barely reaches a top height + * of 4 elements even for the largest font sizes I'm willing to support. And + * as space requirements should only grow logarithmically, I think 10 is + * more than enough. */ +#define STACK_SIZE 10 + Curve stack[STACK_SIZE]; + unsigned int top = 0; + for (;;) { + if (is_flat(outl, curve) || top >= STACK_SIZE) { + if (outl->numLines >= outl->capLines && grow_lines(outl) < 0) + return -1; + outl->lines[outl->numLines++] = { curve.beg, curve.end }; + if (top == 0) break; + curve = stack[--top]; + } else { + uint_least16_t ctrl0 = outl->numPoints; + if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0) + return -1; + outl->points[ctrl0] = midpoint(outl->points[curve.beg], outl->points[curve.ctrl]); + ++outl->numPoints; + + uint_least16_t ctrl1 = outl->numPoints; + if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0) + return -1; + outl->points[ctrl1] = midpoint(outl->points[curve.ctrl], outl->points[curve.end]); + ++outl->numPoints; + + uint_least16_t pivot = outl->numPoints; + if (outl->numPoints >= outl->capPoints && grow_points(outl) < 0) + return -1; + outl->points[pivot] = midpoint(outl->points[ctrl0], outl->points[ctrl1]); + ++outl->numPoints; + + stack[top++] = { curve.beg, pivot, ctrl0 }; + curve = { pivot, curve.end, ctrl1 }; + } + } + return 0; +#undef STACK_SIZE +} + +static int +tesselate_curves(Outline *outl) +{ + unsigned int i; + for (i = 0; i < outl->numCurves; ++i) { + if (tesselate_curve(outl->curves[i], outl) < 0) + return -1; + } + return 0; +} + +/* Draws a line into the buffer. Uses a custom 2D raycasting algorithm to do so. */ +static void +draw_line(Raster buf, Point origin, Point goal) +{ + Point delta; + Point nextCrossing; + Point crossingIncr; + double halfDeltaX; + double prevDistance = 0.0, nextDistance; + double xAverage, yDifference; + struct { int x, y; } pixel; + struct { int x, y; } dir; + int step, numSteps = 0; + Cell *cptr = NULL, cell; + + delta.x = goal.x - origin.x; + delta.y = goal.y - origin.y; + dir.x = SIGN(delta.x); + dir.y = SIGN(delta.y); + + if (!dir.y) { + return; + } + + crossingIncr.x = dir.x ? fabs(1.0 / delta.x) : 1.0; + crossingIncr.y = fabs(1.0 / delta.y); + + if (!dir.x) { + pixel.x = fast_floor(origin.x); + nextCrossing.x = 100.0; + } else { + if (dir.x > 0) { + pixel.x = fast_floor(origin.x); + nextCrossing.x = (origin.x - pixel.x) * crossingIncr.x; + nextCrossing.x = crossingIncr.x - nextCrossing.x; + numSteps += fast_ceil(goal.x) - fast_floor(origin.x) - 1; + } else { + pixel.x = fast_ceil(origin.x) - 1; + nextCrossing.x = (origin.x - pixel.x) * crossingIncr.x; + numSteps += fast_ceil(origin.x) - fast_floor(goal.x) - 1; + } + } + + if (dir.y > 0) { + pixel.y = fast_floor(origin.y); + nextCrossing.y = (origin.y - pixel.y) * crossingIncr.y; + nextCrossing.y = crossingIncr.y - nextCrossing.y; + numSteps += fast_ceil(goal.y) - fast_floor(origin.y) - 1; + } else { + pixel.y = fast_ceil(origin.y) - 1; + nextCrossing.y = (origin.y - pixel.y) * crossingIncr.y; + numSteps += fast_ceil(origin.y) - fast_floor(goal.y) - 1; + } + + nextDistance = MIN(nextCrossing.x, nextCrossing.y); + halfDeltaX = 0.5 * delta.x; + + for (step = 0; step < numSteps; ++step) { + xAverage = origin.x + (prevDistance + nextDistance) * halfDeltaX; + yDifference = (nextDistance - prevDistance) * delta.y; + cptr = &buf.cells[pixel.y * buf.width + pixel.x]; + cell = *cptr; + cell.cover += yDifference; + xAverage -= (double) pixel.x; + cell.area += (1.0 - xAverage) * yDifference; + *cptr = cell; + prevDistance = nextDistance; + int alongX = nextCrossing.x < nextCrossing.y; + pixel.x += alongX ? dir.x : 0; + pixel.y += alongX ? 0 : dir.y; + nextCrossing.x += alongX ? crossingIncr.x : 0.0; + nextCrossing.y += alongX ? 0.0 : crossingIncr.y; + nextDistance = MIN(nextCrossing.x, nextCrossing.y); + } + + xAverage = origin.x + (prevDistance + 1.0) * halfDeltaX; + yDifference = (1.0 - prevDistance) * delta.y; + cptr = &buf.cells[pixel.y * buf.width + pixel.x]; + cell = *cptr; + cell.cover += yDifference; + xAverage -= (double) pixel.x; + cell.area += (1.0 - xAverage) * yDifference; + *cptr = cell; +} + +static void +draw_lines(Outline *outl, Raster buf) +{ + unsigned int i; + for (i = 0; i < outl->numLines; ++i) { + Line line = outl->lines[i]; + Point origin = outl->points[line.beg]; + Point goal = outl->points[line.end]; + draw_line(buf, origin, goal); + } +} + +/* Integrate the values in the buffer to arrive at the final grayscale image. */ +static void +post_process(Raster buf, uint8_t *image) +{ + Cell cell; + double accum = 0.0, value; + unsigned int i, num; + num = (unsigned int) buf.width * (unsigned int) buf.height; + for (i = 0; i < num; ++i) { + cell = buf.cells[i]; + value = fabs(accum + cell.area); + value = MIN(value, 1.0); + value = value * 255.0 + 0.5; + image[i] = (uint8_t) value; + accum += cell.cover; + } +} + +static int +render_outline(Outline *outl, double transform[6], SFT_Image image) +{ + Cell *cells = NULL; + Raster buf; + unsigned int numPixels; + + numPixels = (unsigned int) image.width * (unsigned int) image.height; + + STACK_ALLOC(cells, Cell, 128 * 128, numPixels); + if (!cells) { + return -1; + } + memset(cells, 0, numPixels * sizeof *cells); + buf.cells = cells; + buf.width = image.width; + buf.height = image.height; + + transform_points(outl->numPoints, outl->points, transform); + + clip_points(outl->numPoints, outl->points, image.width, image.height); + + if (tesselate_curves(outl) < 0) { + STACK_FREE(cells); + return -1; + } + + draw_lines(outl, buf); + + post_process(buf, (uint8_t*)image.pixels); + + STACK_FREE(cells); + return 0; +} + diff --git a/src/common/fonts/schrift.h b/src/common/fonts/schrift.h new file mode 100644 index 0000000000..93d20516ae --- /dev/null +++ b/src/common/fonts/schrift.h @@ -0,0 +1,95 @@ +/* This file is part of libschrift. + * + * © 2019-2022 Thomas Oltmann and contributors + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef SCHRIFT_H +#define SCHRIFT_H 1 + +#include /* size_t */ +#include /* uint_fast32_t, uint_least32_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SFT_DOWNWARD_Y 0x01 + +typedef struct SFT SFT; +typedef struct SFT_Font SFT_Font; +typedef uint_least32_t SFT_UChar; /* Guaranteed to be compatible with char32_t. */ +typedef uint_fast32_t SFT_Glyph; +typedef struct SFT_LMetrics SFT_LMetrics; +typedef struct SFT_GMetrics SFT_GMetrics; +typedef struct SFT_Kerning SFT_Kerning; +typedef struct SFT_Image SFT_Image; + +struct SFT +{ + SFT_Font *font; + double xScale; + double yScale; + double xOffset; + double yOffset; + int flags; +}; + +struct SFT_LMetrics +{ + double ascender; + double descender; + double lineGap; +}; + +struct SFT_GMetrics +{ + double advanceWidth; + double leftSideBearing; + int yOffset; + int minWidth; + int minHeight; +}; + +struct SFT_Kerning +{ + double xShift; + double yShift; +}; + +struct SFT_Image +{ + void *pixels; + int width; + int height; +}; + +const char *sft_version(void); + +SFT_Font *sft_loadmem (const void *mem, size_t size); +SFT_Font *sft_loadfile(const char *filename); +void sft_freefont(SFT_Font *font); + +int sft_lmetrics(const SFT *sft, SFT_LMetrics *metrics); +int sft_lookup (const SFT *sft, SFT_UChar codepoint, SFT_Glyph *glyph); +int sft_gmetrics(const SFT *sft, SFT_Glyph glyph, SFT_GMetrics *metrics); +int sft_kerning (const SFT *sft, SFT_Glyph leftGlyph, SFT_Glyph rightGlyph, + SFT_Kerning *kerning); +int sft_render (const SFT *sft, SFT_Glyph glyph, SFT_Image image); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/common/fonts/singlelumpfont.cpp b/src/common/fonts/singlelumpfont.cpp index d3bee25a3a..0d58394016 100644 --- a/src/common/fonts/singlelumpfont.cpp +++ b/src/common/fonts/singlelumpfont.cpp @@ -41,6 +41,7 @@ #include "utf8.h" #include "fontchars.h" #include "texturemanager.h" +#include "m_swap.h" #include "fontinternals.h" @@ -123,8 +124,8 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump) FontName = name; - FileData data1 = fileSystem.ReadFile (lump); - const uint8_t *data = (const uint8_t *)data1.GetMem(); + auto data1 = fileSystem.ReadFile (lump); + auto data = data1.bytes(); if (data[0] == 0xE1 && data[1] == 0xE6 && data[2] == 0xD5 && data[3] == 0x1A) { @@ -193,8 +194,8 @@ void FSingleLumpFont::LoadTranslations() Translations.Resize(NumTextColors); for (int i = 0; i < NumTextColors; i++) { - if (i == CR_UNTRANSLATED) Translations[i] = 0; - else Translations[i] = LuminosityTranslation(i * 2 + (FontType == FONT1 ? 1 : 0), minlum, maxlum); + if (i == CR_UNTRANSLATED) Translations[i] = NO_TRANSLATION; + else Translations[i] = MakeLuminosityTranslation(i * 2 + (FontType == FONT1 ? 1 : 0), minlum, maxlum); } } @@ -473,8 +474,8 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data) void FSingleLumpFont::CheckFON1Chars() { - FileData memLump = fileSystem.ReadFile(Lump); - const uint8_t* data = (const uint8_t*)memLump.GetMem(); + auto memLump = fileSystem.ReadFile(Lump); + auto data = memLump.bytes(); const uint8_t* data_p; data_p = data + 8; diff --git a/src/common/fonts/singlepicfont.cpp b/src/common/fonts/singlepicfont.cpp index 687602876a..30fdf87115 100644 --- a/src/common/fonts/singlepicfont.cpp +++ b/src/common/fonts/singlepicfont.cpp @@ -65,21 +65,21 @@ class FSinglePicFont : public FFont FSinglePicFont::FSinglePicFont(const char *picname) : FFont(-1) // Since lump is only needed for priority information we don't need to worry about this here. { - FTextureID picnum = TexMan.CheckForTexture (picname, ETextureType::Any); + FTextureID texid = TexMan.CheckForTexture (picname, ETextureType::Any); - if (!picnum.isValid()) + if (!texid.isValid()) { I_FatalError ("%s is not a font or texture", picname); } - auto pic = TexMan.GetGameTexture(picnum); + auto pic = TexMan.GetGameTexture(texid); FontName = picname; FontHeight = (int)pic->GetDisplayHeight(); SpaceWidth = (int)pic->GetDisplayWidth(); GlobalKerning = 0; FirstChar = LastChar = 'A'; - PicNum = picnum; + PicNum = texid; } //========================================================================== diff --git a/src/common/fonts/specialfont.cpp b/src/common/fonts/specialfont.cpp index 9c35f2a8a0..9ab3d4f388 100644 --- a/src/common/fonts/specialfont.cpp +++ b/src/common/fonts/specialfont.cpp @@ -182,7 +182,7 @@ void FSpecialFont::LoadTranslations() workpal[i * 4 + 2] = GPalette.BaseColors[i].r; workpal[i * 4 + 3] = GPalette.BaseColors[i].a; } - V_ApplyLuminosityTranslation(trans, workpal, 256); + V_ApplyLuminosityTranslation(LuminosityTranslationDesc::fromID(trans), workpal, 256); for (int i = 0; i < 256; i++) { if (!notranslate[i]) diff --git a/src/common/fonts/ttffont.cpp b/src/common/fonts/ttffont.cpp new file mode 100644 index 0000000000..3845855463 --- /dev/null +++ b/src/common/fonts/ttffont.cpp @@ -0,0 +1,146 @@ +#include + +#include "engineerrors.h" +#include "textures.h" +#include "image.h" +#include "v_font.h" +#include "filesystem.h" +#include "utf8.h" +#include "sc_man.h" +#include "texturemanager.h" +#include "fontinternals.h" +#include "schrift.h" + +class FTTFGlyph : public FImageSource +{ +public: + FTTFGlyph(int width, int height, int leftoffset, int topoffset, TArray pixels, PalEntry* palette) + { + Width = width; + Height = height; + LeftOffset = leftoffset; + TopOffset = topoffset; + Pixels = std::move(pixels); + Palette = palette; + } + + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override + { + PalettedPixels OutPixels(Pixels.Size()); + memcpy(OutPixels.Data(), Pixels.Data(), Pixels.Size()); + return OutPixels; + } + + int CopyPixels(FBitmap* bmp, int conversion) + { + if (conversion == luminance) + conversion = normal; // luminance images have no use as an RGB source. + + auto ppix = CreatePalettedPixels(conversion); + bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, 1, Width, 0, Palette); + return 0; + } + +private: + TArray Pixels; + PalEntry* Palette = nullptr; +}; + +class FTTFFont : public FFont +{ +public: + FTTFFont(const char* fontname, int height, int lump) : FFont(lump) + { + auto lumpdata = fileSystem.ReadFile(lump); + + SFT sft = {}; + sft.xScale = height; + sft.yScale = height; + sft.flags = SFT_DOWNWARD_Y; + sft.font = sft_loadmem(lumpdata.data(), lumpdata.size()); + if (!sft.font) + I_FatalError("Could not load truetype font file"); + + SFT_LMetrics lmtx; + if (sft_lmetrics(&sft, &lmtx) < 0) + I_FatalError("Could not get truetype font metrics"); + + FontName = fontname; + FontHeight = (int)std::floor((lmtx.ascender + lmtx.descender + lmtx.lineGap)) + 2; + + { + SFT_Glyph gid; + SFT_GMetrics mtx; + if (sft_lookup(&sft, 32, &gid) < 0) + I_FatalError("Could not find the glyph id for the space character"); + + if (sft_gmetrics(&sft, gid, &mtx) < 0) + I_FatalError("Could not get the glyph metrics for the space character"); + + SpaceWidth = (int)std::round(mtx.advanceWidth); + } + + GlobalKerning = 0; + + FirstChar = 10; + LastChar = 255; + + for (int i = 0; i < 256; i++) + { + palette[i] = PalEntry(i, 255, 255, 255); + } + + Chars.Resize(LastChar - FirstChar + 1); + for (int i = FirstChar; i <= LastChar; i++) + { + SFT_Glyph gid; + if (sft_lookup(&sft, i, &gid) < 0) + continue; + + SFT_GMetrics mtx; + if (sft_gmetrics(&sft, gid, &mtx) < 0) + continue; + + if (mtx.minWidth <= 0 || mtx.minHeight <= 0) + continue; + + SFT_Image img = {}; + img.width = (mtx.minWidth + 3) & ~3; + img.height = mtx.minHeight; + + TArray pixels(img.width * img.height, true); + img.pixels = pixels.Data(); + if (sft_render(&sft, gid, img) < 0) + continue; + + Chars[i - FirstChar].OriginalPic = MakeGameTexture(new FImageTexture(CreateGlyph(lmtx, mtx, img.width, img.height, std::move(pixels))), nullptr, ETextureType::FontChar); + Chars[i - FirstChar].XMove = (int)std::floor(mtx.advanceWidth) + 1; + TexMan.AddGameTexture(Chars[i - FirstChar].OriginalPic); + } + } + + void LoadTranslations() override + { + int minlum = 0; + int maxlum = 255; + + Translations.Resize(NumTextColors); + for (int i = 0; i < NumTextColors; i++) + { + if (i == CR_UNTRANSLATED) Translations[i] = NO_TRANSLATION; + else Translations[i] = MakeLuminosityTranslation(i * 2, minlum, maxlum); + } + } + + virtual FTTFGlyph* CreateGlyph(const SFT_LMetrics& lmtx, const SFT_GMetrics& mtx, int width, int height, TArray pixels) + { + return new FTTFGlyph(width, height, (int)std::round(-mtx.leftSideBearing), -mtx.yOffset - (int)std::round(lmtx.ascender + lmtx.descender + lmtx.lineGap * 0.5), std::move(pixels), palette); + } + + PalEntry palette[256]; +}; + +FFont* CreateTTFFont(const char* fontname, int height, int lump) +{ + return new FTTFFont(fontname, height, lump); +} diff --git a/src/common/fonts/v_font.cpp b/src/common/fonts/v_font.cpp index f51813aeb4..3d63725ccf 100644 --- a/src/common/fonts/v_font.cpp +++ b/src/common/fonts/v_font.cpp @@ -109,11 +109,11 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) int lump = -1; int folderfile = -1; - TArray folderdata; + std::vector folderdata; FStringf path("fonts/%s/", name); // Use a folder-based font only if it comes from a later file than the single lump version. - if (fileSystem.GetFilesInFolder(path, folderdata, true)) + if (fileSystem.GetFilesInFolder(path.GetChars(), folderdata, true)) { // This assumes that any custom font comes in one piece and not distributed across multiple resource files. folderfile = fileSystem.GetFileContainer(folderdata[0].lumpnum); @@ -138,10 +138,10 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) return font; } } - FTextureID picnum = TexMan.CheckForTexture (name, ETextureType::Any); - if (picnum.isValid()) + FTextureID texid = TexMan.CheckForTexture (name, ETextureType::Any); + if (texid.isValid()) { - auto tex = TexMan.GetGameTexture(picnum); + auto tex = TexMan.GetGameTexture(texid); if (tex && tex->GetSourceLump() >= folderfile) { FFont *CreateSinglePicFont(const char *name); @@ -149,7 +149,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) return font; } } - if (folderdata.Size() > 0) + if (folderdata.size() > 0) { font = new FFont(name, nullptr, name, 0, 0, 1, -1); if (translationsLoaded) font->LoadTranslations(); @@ -300,7 +300,7 @@ void V_InitCustomFonts() } if (format == 1) { - FFont *fnt = new FFont (namebuffer, templatebuf, nullptr, first, count, start, llump, spacewidth, donttranslate); + FFont *fnt = new FFont(namebuffer.GetChars(), templatebuf.GetChars(), nullptr, first, count, start, llump, spacewidth, donttranslate); fnt->SetCursor(cursor); fnt->SetKerning(kerning); if (ignoreoffsets) fnt->ClearOffsets(); @@ -326,7 +326,7 @@ void V_InitCustomFonts() if (count > 0) { FFont *CreateSpecialFont (const char *name, int first, int count, FGameTexture **lumplist, const bool *notranslate, int lump, bool donttranslate); - FFont *fnt = CreateSpecialFont (namebuffer, first, count, &lumplist[first], notranslate, llump, donttranslate); + FFont *fnt = CreateSpecialFont(namebuffer.GetChars(), first, count, &lumplist[first], notranslate, llump, donttranslate); fnt->SetCursor(cursor); fnt->SetKerning(kerning); if (spacewidth >= 0) fnt->SpaceWidth = spacewidth; @@ -667,12 +667,12 @@ static void CreateLuminosityTranslationRanges() // //========================================================================== -void V_ApplyLuminosityTranslation(int translation, uint8_t* pixel, int size) +void V_ApplyLuminosityTranslation(const LuminosityTranslationDesc& lum, uint8_t* pixel, int size) { - int colorrange = (translation >> 16) & 0x3fff; + int colorrange = lum.colorrange; if (colorrange >= NumTextColors * 2) return; - int lum_min = (translation >> 8) & 0xff; - int lum_max = translation & 0xff; + int lum_min = lum.lum_min; + int lum_max = lum.lum_max; int lum_range = (lum_max - lum_min + 1); PalEntry* remap = paletteptr + colorrange * 256; @@ -870,11 +870,17 @@ void V_InitFonts() FFont *CreateHexLumpFont(const char *fontname, int lump); FFont *CreateHexLumpFont2(const char *fontname, int lump); + FFont* CreateTTFFont(const char* fontname, int height, int lump); auto lump = fileSystem.CheckNumForFullName("newconsolefont.hex", 0); // This is always loaded from gzdoom.pk3 to prevent overriding it with incomplete replacements. if (lump == -1) I_FatalError("newconsolefont.hex not found"); // This font is needed - do not start up without it. NewConsoleFont = CreateHexLumpFont("NewConsoleFont", lump); NewSmallFont = CreateHexLumpFont2("NewSmallFont", lump); + /* + lump = fileSystem.CheckNumForFullName("newmenufont.ttf", 0); // This is always loaded from gzdoom.pk3 to prevent overriding it with incomplete replacements. + if (lump == -1) I_FatalError("newmenufont.ttf not found"); // This font is needed - do not start up without it. + NewSmallFont = CreateTTFFont("NewSmallFont", 18, lump); + */ CurrentConsoleFont = NewConsoleFont; ConFont = V_GetFont("ConsoleFont", "CONFONT"); V_GetFont("IndexFont", "INDEXFON"); // detect potential replacements for this one. @@ -892,10 +898,11 @@ void V_LoadTranslations() CalcDefaultTranslation(BigFont, CR_UNTRANSLATED * 2 + 1); if (OriginalBigFont != nullptr && OriginalBigFont != BigFont) { - int sometrans = OriginalBigFont->Translations[0]; + assert(IsLuminosityTranslation(OriginalBigFont->Translations[0])); + int sometrans = OriginalBigFont->Translations[0].index(); sometrans &= ~(0x3fff << 16); sometrans |= (CR_UNTRANSLATED * 2 + 1) << 16; - OriginalBigFont->Translations[CR_UNTRANSLATED] = sometrans; + OriginalBigFont->Translations[CR_UNTRANSLATED] = FTranslationID::fromInt(sometrans); OriginalBigFont->forceremap = true; } } @@ -904,18 +911,20 @@ void V_LoadTranslations() CalcDefaultTranslation(SmallFont, CR_UNTRANSLATED * 2); if (OriginalSmallFont != nullptr && OriginalSmallFont != SmallFont) { - int sometrans = OriginalSmallFont->Translations[0]; + assert(IsLuminosityTranslation(OriginalSmallFont->Translations[0])); + int sometrans = OriginalSmallFont->Translations[0].index(); sometrans &= ~(0x3fff << 16); sometrans |= (CR_UNTRANSLATED * 2) << 16; - OriginalSmallFont->Translations[CR_UNTRANSLATED] = sometrans; + OriginalSmallFont->Translations[CR_UNTRANSLATED] = FTranslationID::fromInt(sometrans); OriginalSmallFont->forceremap = true; } if (NewSmallFont != nullptr) { - int sometrans = NewSmallFont->Translations[0]; + assert(IsLuminosityTranslation(NewSmallFont->Translations[0])); + int sometrans = NewSmallFont->Translations[0].index(); sometrans &= ~(0x3fff << 16); sometrans |= (CR_UNTRANSLATED * 2) << 16; - NewSmallFont->Translations[CR_UNTRANSLATED] = sometrans; + NewSmallFont->Translations[CR_UNTRANSLATED] = FTranslationID::fromInt(sometrans); NewSmallFont->forceremap = true; } } diff --git a/src/common/fonts/v_font.h b/src/common/fonts/v_font.h index 407ee0f5ed..4e7596ef83 100644 --- a/src/common/fonts/v_font.h +++ b/src/common/fonts/v_font.h @@ -37,6 +37,7 @@ #include "vectors.h" #include "palentry.h" #include "name.h" +#include "palettecontainer.h" class FGameTexture; struct FRemapTable; @@ -104,7 +105,7 @@ class FFont virtual FGameTexture *GetChar (int code, int translation, int *const width) const; virtual int GetCharWidth (int code) const; - int GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const; + FTranslationID GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const; int GetLump() const { return Lump; } int GetSpaceWidth () const { return SpaceWidth; } int GetHeight () const { return FontHeight; } @@ -175,7 +176,7 @@ class FFont void FixXMoves(); - void ReadSheetFont(TArray &folderdata, int width, int height, const DVector2 &Scale); + void ReadSheetFont(std::vector &folderdata, int width, int height, const DVector2 &Scale); EFontType Type = EFontType::Unknown; FName AltFontName = NAME_None; @@ -197,7 +198,7 @@ class FFont int XMove = INT_MIN; }; TArray Chars; - TArray Translations; + TArray Translations; int Lump; FName FontName = NAME_None; @@ -219,7 +220,7 @@ PalEntry V_LogColorFromColorRange (EColorRange range); EColorRange V_ParseFontColor (const uint8_t *&color_value, int normalcolor, int boldcolor); void V_InitFontColors(); char* CleanseString(char* str); -void V_ApplyLuminosityTranslation(int translation, uint8_t* pixel, int size); +void V_ApplyLuminosityTranslation(const LuminosityTranslationDesc& lum, uint8_t* pixel, int size); void V_LoadTranslations(); class FBitmap; diff --git a/src/common/fonts/v_text.cpp b/src/common/fonts/v_text.cpp index 7fd9bfb535..267b412bdf 100644 --- a/src/common/fonts/v_text.cpp +++ b/src/common/fonts/v_text.cpp @@ -271,12 +271,12 @@ bool CheckFontComplete(FFont* font) { // Also check if the SmallFont contains all characters this language needs. // If not, switch back to the original one. - return font->CanPrint(GStrings["REQUIRED_CHARACTERS"]); + return font->CanPrint(GStrings.CheckString("REQUIRED_CHARACTERS")); } void UpdateGenericUI(bool cvar) { - auto switchstr = GStrings["USE_GENERIC_FONT"]; + auto switchstr = GStrings.CheckString("USE_GENERIC_FONT"); generic_ui = (cvar || (switchstr && strtoll(switchstr, nullptr, 0))); if (!generic_ui) { @@ -311,7 +311,7 @@ void UpdateGenericUI(bool cvar) } } // Turkish i crap. What a mess, just to save two code points... :( - switchstr = GStrings["REQUIRED_CHARACTERS"]; + switchstr = GStrings.CheckString("REQUIRED_CHARACTERS"); special_i = switchstr && strstr(switchstr, "\xc4\xb0") != nullptr; // capital dotted i (İ). if (special_i) { diff --git a/src/common/menu/joystickmenu.cpp b/src/common/menu/joystickmenu.cpp index 21c667d318..ae152b5f0e 100644 --- a/src/common/menu/joystickmenu.cpp +++ b/src/common/menu/joystickmenu.cpp @@ -119,6 +119,20 @@ DEFINE_ACTION_FUNCTION(IJoystickConfig, GetNumAxes) ACTION_RETURN_INT(self->GetNumAxes()); } +DEFINE_ACTION_FUNCTION(IJoystickConfig, GetEnabled) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + ACTION_RETURN_BOOL(self->GetEnabled()); +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, SetEnabled) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + PARAM_BOOL(enabled); + self->SetEnabled(enabled); + return 0; +} + void UpdateJoystickMenu(IJoystickConfig *selected) { @@ -162,7 +176,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected) for (int ii = 0; ii < (int)Joysticks.Size(); ++ii) { - it = CreateOptionMenuItemJoyConfigMenu(Joysticks[ii]->GetName(), Joysticks[ii]); + it = CreateOptionMenuItemJoyConfigMenu(Joysticks[ii]->GetName().GetChars(), Joysticks[ii]); GC::WriteBarrier(opt, it); opt->mItems.Push(it); if (ii == itemnum) opt->mSelectedItem = opt->mItems.Size(); diff --git a/src/common/menu/menu.cpp b/src/common/menu/menu.cpp index a7f560828b..ee9a1277e2 100644 --- a/src/common/menu/menu.cpp +++ b/src/common/menu/menu.cpp @@ -406,7 +406,9 @@ void DMenu::CallDrawer() IFVIRTUAL(DMenu, Drawer) { VMValue params[] = { (DObject*)this }; + InMenu++; VMCall(func, params, 1, nullptr, 0); + InMenu--; twod->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. } } @@ -1039,6 +1041,7 @@ DEFINE_FIELD(DListMenuDescriptor, mFontColor2) DEFINE_FIELD(DListMenuDescriptor, mAnimatedTransition) DEFINE_FIELD(DListMenuDescriptor, mAnimated) DEFINE_FIELD(DListMenuDescriptor, mCenter) +DEFINE_FIELD(DListMenuDescriptor, mCenterText) DEFINE_FIELD(DListMenuDescriptor, mDontDim) DEFINE_FIELD(DListMenuDescriptor, mDontBlur) DEFINE_FIELD(DListMenuDescriptor, mVirtWidth) @@ -1209,7 +1212,7 @@ bool DMenuItemBase::GetString(int i, char *s, int len) FString retstr; VMReturn ret[2]; ret[0].IntAt(&retval); ret[1].StringAt(&retstr); VMCall(func, params, countof(params), ret, 2); - strncpy(s, retstr, len); + strncpy(s, retstr.GetChars(), len); return !!retval; } return false; diff --git a/src/common/menu/menu.h b/src/common/menu/menu.h index 3bd23b3b83..a96e25929c 100644 --- a/src/common/menu/menu.h +++ b/src/common/menu/menu.h @@ -88,6 +88,7 @@ class DListMenuDescriptor : public DMenuDescriptor EColorRange mFontColor; EColorRange mFontColor2; bool mCenter; + bool mCenterText; bool mFromEngine; bool mAnimated; bool mAnimatedTransition; diff --git a/src/common/menu/menudef.cpp b/src/common/menu/menudef.cpp index 4fbeeb0bb6..0a46dfa353 100644 --- a/src/common/menu/menudef.cpp +++ b/src/common/menu/menudef.cpp @@ -66,7 +66,7 @@ PClass *DefaultOptionMenuClass; void I_BuildALDeviceList(FOptionValues *opt); void I_BuildALResamplersList(FOptionValues *opt); - +void I_BuildVKDeviceList(FOptionValues *opt); DEFINE_GLOBAL_NAMED(OptionSettings, OptionMenuSettings) @@ -431,6 +431,10 @@ static void DoParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc, bool &s { desc->mForceList = true; } + else if (sc.Compare("CenterText")) + { + desc->mCenterText = true; + } else { // all item classes from which we know that they support sized scaling. @@ -768,6 +772,7 @@ static void ParseListMenu(FScanner &sc) desc->mWLeft = 0; desc->mWRight = 0; desc->mCenter = false; + desc->mCenterText = false; desc->mFromEngine = fileSystem.GetFileContainer(sc.LumpNum) == 0; // flags menu if the definition is from the IWAD. desc->mVirtWidth = -2; desc->mCustomSizeSet = false; @@ -1519,7 +1524,7 @@ void M_ParseMenuDefs() DefaultOptionMenuSettings->Reset(); OptionSettings.mLinespacing = 17; - int IWADMenu = fileSystem.CheckNumForName("MENUDEF", ns_global, fileSystem.GetIwadNum()); + int IWADMenu = fileSystem.CheckNumForName("MENUDEF", FileSys::ns_global, fileSystem.GetIwadNum()); while ((lump = fileSystem.FindLump ("MENUDEF", &lastlump)) != -1) { @@ -1628,7 +1633,7 @@ static void InitMusicMenus() { FString display = entry.mName; display.ReplaceChars("_", ' '); - auto it = CreateOptionMenuItemCommand(display, FStringf("%s \"%s\"", std::get<2>(p), entry.mName.GetChars()), true); + auto it = CreateOptionMenuItemCommand(display.GetChars(), FStringf("%s \"%s\"", std::get<2>(p), entry.mName.GetChars()), true); static_cast(*menu)->mItems.Push(it); } } @@ -1662,6 +1667,7 @@ static void InitMusicMenus() // Special menus will be created once all engine data is loaded // //============================================================================= +void I_BuildMIDIMenuList(FOptionValues*); void M_CreateMenus() { @@ -1681,6 +1687,11 @@ void M_CreateMenus() { I_BuildALResamplersList(*opt); } + opt = OptionValues.CheckKey(NAME_Vkdevices); + if (opt != nullptr) + { + I_BuildVKDeviceList(*opt); + } } diff --git a/src/common/menu/messagebox.cpp b/src/common/menu/messagebox.cpp index 8b8334b02f..21f22d1905 100644 --- a/src/common/menu/messagebox.cpp +++ b/src/common/menu/messagebox.cpp @@ -99,6 +99,6 @@ DEFINE_ACTION_FUNCTION(DMenu, StartMessage) PARAM_STRING(msg); PARAM_INT(mode); PARAM_NAME(action); - M_StartMessage(msg, mode, action); + M_StartMessage(msg.GetChars(), mode, action); return 0; } diff --git a/src/common/menu/savegamemanager.cpp b/src/common/menu/savegamemanager.cpp index 5dc22ec76b..83865cd1d6 100644 --- a/src/common/menu/savegamemanager.cpp +++ b/src/common/menu/savegamemanager.cpp @@ -252,7 +252,7 @@ void FSavegameManagerBase::DoSave(int Selected, const char *savegamestring) break; } } - PerformSaveGame(filename, savegamestring); + PerformSaveGame(filename.GetChars(), savegamestring); } M_ClearMenus(); } @@ -262,7 +262,7 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, DoSave) PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase); PARAM_INT(sel); PARAM_STRING(name); - self->DoSave(sel, name); + self->DoSave(sel, name.GetChars()); return 0; } @@ -297,37 +297,26 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index) !node->bOldVersion && (resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr) { - FResourceLump *info = resf->FindLump("info.json"); - if (info == nullptr) + auto info = resf->FindEntry("info.json"); + if (info < 0) { // this should not happen because the file has already been verified. return index; } - void* data = info->Lock(); + auto data = resf->Read(info); FSerializer arc; - if (!arc.OpenReader((const char*)data, info->LumpSize)) + if (!arc.OpenReader(data.string(), data.size())) { - info->Unlock(); return index; } - info->Unlock(); SaveCommentString = ExtractSaveComment(arc); - FResourceLump *pic = resf->FindLump("savepic.png"); - if (pic != nullptr) + auto pic = resf->FindEntry("savepic.png"); + if (pic >= 0) { - FileReader picreader; - - picreader.OpenMemoryArray([=](TArray &array) - { - auto cache = pic->Lock(); - array.Resize(pic->LumpSize); - memcpy(&array[0], cache, pic->LumpSize); - pic->Unlock(); - return true; - }); + FileReader picreader = resf->GetEntryReader(pic, FileSys::READER_NEW, FileSys::READERFLAG_SEEKABLE); PNGHandle *png = M_VerifyPNG(picreader); if (png != nullptr) { @@ -481,7 +470,7 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, GetSavegame) void FSavegameManagerBase::InsertNewSaveNode() { - NewSaveNode.SaveTitle = GStrings("NEWSAVE"); + NewSaveNode.SaveTitle = GStrings.GetString("NEWSAVE"); NewSaveNode.bNoDelete = true; SaveGames.Insert(0, &NewSaveNode); } @@ -559,7 +548,7 @@ FString G_GetSavegamesFolder() } else { - name = **save_dir ? save_dir : M_GetSavegamesPath(); + name = **save_dir ? FString(save_dir) : M_GetSavegamesPath(); usefilter = true; } @@ -574,8 +563,8 @@ FString G_GetSavegamesFolder() if (usefilter && SavegameFolder.IsNotEmpty()) name << SavegameFolder << '/'; - name = NicePath(name); - CreatePath(name); + name = NicePath(name.GetChars()); + CreatePath(name.GetChars()); return name; } @@ -589,7 +578,7 @@ FString G_BuildSaveName(const char* prefix) { FString name = G_GetSavegamesFolder() + prefix; DefaultExtension(name, "." SAVEGAME_EXT); // only add an extension if the prefix doesn't have one already. - name = NicePath(name); + name = NicePath(name.GetChars()); name.Substitute("\\", "/"); return name; } diff --git a/src/common/models/model.cpp b/src/common/models/model.cpp index c93fa78767..0f16034158 100644 --- a/src/common/models/model.cpp +++ b/src/common/models/model.cpp @@ -25,6 +25,7 @@ ** General model handling code ** **/ +#include // offsetof() macro. #include "filesystem.h" #include "cmdlib.h" @@ -42,10 +43,9 @@ #include "texturemanager.h" #include "modelrenderer.h" - -TArray savedModelFiles; TDeletingArray Models; TArray SpriteModelFrames; +TMap BaseSpriteModelFrames; ///////////////////////////////////////////////////////////////////////////// @@ -88,7 +88,7 @@ void FModel::DestroyVertexBuffer() static int FindGFXFile(FString & fn) { - int lump = fileSystem.CheckNumForFullName(fn); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. + int lump = fileSystem.CheckNumForFullName(fn.GetChars()); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. if (lump != -1) return lump; int best = -1; @@ -100,7 +100,7 @@ static int FindGFXFile(FString & fn) for (const char ** extp=extensions; *extp; extp++) { - lump = fileSystem.CheckNumForFullName(fn + *extp); + lump = fileSystem.CheckNumForFullName((fn + *extp).GetChars()); if (lump >= best) best = lump; } return best; @@ -132,17 +132,7 @@ FTextureID LoadSkin(const char * path, const char * fn) int ModelFrameHash(FSpriteModelFrame * smf) { - const uint32_t *table = GetCRCTable (); - uint32_t hash = 0xffffffff; - - const char * s = (const char *)(&smf->type); // this uses type, sprite and frame for hashing - const char * se= (const char *)(&smf->hashnext); - - for (; stype), offsetof(FSpriteModelFrame, hashnext) - offsetof(FSpriteModelFrame, type)); } //=========================================================================== @@ -158,7 +148,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) if (path) fullname.Format("%s%s", path, modelfile); else fullname = modelfile; - int lump = fileSystem.CheckNumForFullName(fullname); + int lump = fileSystem.CheckNumForFullName(fullname.GetChars()); if (lump<0) { @@ -168,18 +158,24 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) for(unsigned i = 0; i< Models.Size(); i++) { - if (!Models[i]->mFileName.CompareNoCase(fullname)) return i; + if (Models[i]->mFileName.CompareNoCase(fullname) == 0) return i; + } + + auto len = fileSystem.FileLength(lump); + if (len >= 0x80000000ll) + { + Printf(PRINT_HIGH, "LoadModel: File to large: '%s'\n", fullname.GetChars()); + return -1; } - int len = fileSystem.FileLength(lump); - FileData lumpd = fileSystem.ReadFile(lump); - char * buffer = (char*)lumpd.GetMem(); + auto lumpd = fileSystem.ReadFile(lump); + const char * buffer = lumpd.string(); if ( (size_t)fullname.LastIndexOf("_d.3d") == fullname.Len()-5 ) { FString anivfile = fullname.GetChars(); anivfile.Substitute("_d.3d","_a.3d"); - if ( fileSystem.CheckNumForFullName(anivfile) > 0 ) + if ( fileSystem.CheckNumForFullName(anivfile.GetChars()) > 0 ) { model = new FUE1Model; } @@ -188,7 +184,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) { FString datafile = fullname.GetChars(); datafile.Substitute("_a.3d","_d.3d"); - if ( fileSystem.CheckNumForFullName(datafile) > 0 ) + if ( fileSystem.CheckNumForFullName(datafile.GetChars()) > 0 ) { model = new FUE1Model; } @@ -216,7 +212,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) if (model != nullptr) { - if (!model->Load(path, lump, buffer, len)) + if (!model->Load(path, lump, buffer, (int)len)) { delete model; return -1; @@ -238,6 +234,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) } // The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized model->mFileName = fullname; + model->mFilePath = {path, modelfile}; return Models.Push(model); } diff --git a/src/common/models/model.h b/src/common/models/model.h index dc4d644764..7d5746e331 100644 --- a/src/common/models/model.h +++ b/src/common/models/model.h @@ -4,7 +4,10 @@ #include "textureid.h" #include "i_modelvertexbuffer.h" #include "matrix.h" +#include "palettecontainer.h" #include "TRS.h" +#include "tarray.h" +#include "name.h" class DBoneComponents; class FModelRenderer; @@ -15,9 +18,10 @@ struct FSpriteModelFrame; FTextureID LoadSkin(const char* path, const char* fn); void FlushModels(); -extern TArray savedModelFiles; + extern TDeletingArray Models; extern TArray SpriteModelFrames; +extern TMap BaseSpriteModelFrames; #define MD3_MAX_SURFACES 32 #define MIN_MODELS 4 @@ -37,7 +41,9 @@ struct FSpriteModelFrame float xrotate, yrotate, zrotate; float rotationCenterX, rotationCenterY, rotationCenterZ; float rotationSpeed; +private: unsigned int flags; +public: const void* type; // used for hashing, must point to something usable as identifier for the model's owner. short sprite; short frame; @@ -46,6 +52,9 @@ struct FSpriteModelFrame // added pithoffset, rolloffset. float pitchoffset, rolloffset; // I don't want to bother with type transformations, so I made this variables float. bool isVoxel; + unsigned int getFlags(class DActorModelData * defs) const; + friend void InitModels(); + friend void ParseModelDefLump(int Lump); }; @@ -67,25 +76,36 @@ enum EFrameError class FModel { public: + FModel(); virtual ~FModel(); virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0; + virtual int FindFrame(const char * name, bool nodefault = false) = 0; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) = 0; + + // [RL0] these are used for decoupled iqm animations + virtual int FindFirstFrame(FName name) { return FErr_NotFound; } + virtual int FindLastFrame(FName name) { return FErr_NotFound; } + virtual double FindFramerate(FName name) { return FErr_NotFound; } + + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) = 0; virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0; virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0; virtual float getAspectFactor(float vscale) { return 1.f; } virtual const TArray* AttachAnimationData() { return nullptr; }; - virtual const TArray CalculateBones(int frame1, int frame2, double inter, const TArray* animationData, DBoneComponents* bones, int index) { return {}; }; + virtual const TArray CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray* animationData, DBoneComponents* bones, int index) { return {}; }; void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; } IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; } void DestroyVertexBuffer(); bool hasSurfaces = false; - FString mFileName; + FString mFileName; + std::pair mFilePath; + + FSpriteModelFrame *baseFrame; private: IModelVertexBuffer *mVBuf[NumModelRendererTypes]; }; diff --git a/src/common/models/model_iqm.h b/src/common/models/model_iqm.h index 3ab9566895..464f5c13ad 100644 --- a/src/common/models/model_iqm.h +++ b/src/common/models/model_iqm.h @@ -6,6 +6,7 @@ #include "matrix.h" #include "common/rendering/i_modelvertexbuffer.h" #include "m_swap.h" +#include "name.h" class DBoneComponents; @@ -112,11 +113,14 @@ class IQMModel : public FModel bool Load(const char* fn, int lumpnum, const char* buffer, int length) override; int FindFrame(const char* name, bool nodefault) override; - void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + int FindFirstFrame(FName name) override; + int FindLastFrame(FName name) override; + double FindFramerate(FName name) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer* renderer) override; void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; const TArray* AttachAnimationData() override; - const TArray CalculateBones(int frame1, int frame2, double inter, const TArray* animationData, DBoneComponents* bones, int index) override; + const TArray CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray* animationData, DBoneComponents* bones, int index) override; private: void LoadGeometry(); @@ -129,6 +133,9 @@ class IQMModel : public FModel void LoadBlendWeights(IQMFileReader& reader, const IQMVertexArray& vertexArray); int mLumpNum = -1; + + TMap NamedAnimations; + TArray Meshes; TArray Triangles; TArray Adjacency; diff --git a/src/common/models/model_kvx.h b/src/common/models/model_kvx.h index c801e5c010..2175bcbca7 100644 --- a/src/common/models/model_kvx.h +++ b/src/common/models/model_kvx.h @@ -59,7 +59,7 @@ class FVoxelModel : public FModel bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; void Initialize(); virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; FTextureID GetPaletteTexture() const { return mPalette; } void BuildVertexBuffer(FModelRenderer *renderer) override; diff --git a/src/common/models/model_md2.h b/src/common/models/model_md2.h index 9ead5e60be..fd1646dc9b 100644 --- a/src/common/models/model_md2.h +++ b/src/common/models/model_md2.h @@ -113,7 +113,7 @@ class FDMDModel : public FModel virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; virtual void LoadGeometry(); virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; diff --git a/src/common/models/model_md3.h b/src/common/models/model_md3.h index b53cd3ebb3..045b1cc3b7 100644 --- a/src/common/models/model_md3.h +++ b/src/common/models/model_md3.h @@ -67,7 +67,7 @@ class FMD3Model : public FModel virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; void LoadGeometry(); void BuildVertexBuffer(FModelRenderer *renderer); virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; diff --git a/src/common/models/model_obj.h b/src/common/models/model_obj.h index fa41ec0fc8..4fc977c05f 100644 --- a/src/common/models/model_obj.h +++ b/src/common/models/model_obj.h @@ -98,7 +98,7 @@ class FOBJModel : public FModel ~FOBJModel(); bool Load(const char* fn, int lumpnum, const char* buffer, int length) override; int FindFrame(const char* name, bool nodefault) override; - void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer* renderer) override; void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; }; diff --git a/src/common/models/model_ue1.h b/src/common/models/model_ue1.h index 9b529b44c7..579002f895 100644 --- a/src/common/models/model_ue1.h +++ b/src/common/models/model_ue1.h @@ -26,7 +26,7 @@ class FUE1Model : public FModel bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; int FindFrame(const char* name, bool nodefault) override; - void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer *renderer) override; void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; void LoadGeometry(); @@ -70,15 +70,15 @@ class FUE1Model : public FModel { uint16_t numframes, framesize; }; - d3dhead * dhead; - d3dpoly * dpolys; - a3dhead * ahead; - uint32_t * averts; + const d3dhead * dhead; + const d3dpoly * dpolys; + const a3dhead * ahead; + const uint32_t * averts; struct dxvert { int16_t x, y, z, pad; }; - dxvert * dxverts; + const dxvert * dxverts; // converted data structures struct UE1Vertex diff --git a/src/common/models/modelrenderer.h b/src/common/models/modelrenderer.h index 18c49f641a..d2d774eab9 100644 --- a/src/common/models/modelrenderer.h +++ b/src/common/models/modelrenderer.h @@ -10,18 +10,18 @@ class FModelRenderer virtual ModelRendererType GetType() const = 0; - virtual void BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) = 0; - virtual void EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf) = 0; + virtual void BeginDrawModel(FRenderStyle style, int smf_flags, const VSMatrix &objectToWorldMatrix, bool mirrored) = 0; + virtual void EndDrawModel(FRenderStyle style, int smf_flags) = 0; virtual IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) = 0; virtual VSMatrix GetViewToWorldMatrix() = 0; - virtual void BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored) = 0; - virtual void EndDrawHUDModel(FRenderStyle style) = 0; + virtual void BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, int smf_flags) = 0; + virtual void EndDrawHUDModel(FRenderStyle style, int smf_flags) = 0; virtual void SetInterpolation(double interpolation) = 0; - virtual void SetMaterial(FGameTexture *skin, bool clampNoFilter, int translation) = 0; + virtual void SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation) = 0; virtual void DrawArrays(int start, int count) = 0; virtual void DrawElements(int numIndices, size_t offset) = 0; virtual int SetupFrame(FModel* model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) { return -1; }; diff --git a/src/common/models/models_iqm.cpp b/src/common/models/models_iqm.cpp index a2d72b11ab..891a19647e 100644 --- a/src/common/models/models_iqm.cpp +++ b/src/common/models/models_iqm.cpp @@ -63,12 +63,6 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt uint32_t num_extensions = reader.ReadUInt32(); uint32_t ofs_extensions = reader.ReadUInt32(); - /*if (num_joints <= 0) - { - Printf("Invalid model: \"%s%s\", no joint data is present\n", path, fileSystem.GetLongName(mLumpNum).GetChars()); - return false; - }*/ - if (num_text == 0) return false; @@ -143,9 +137,12 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt } reader.SeekTo(ofs_anims); - for (IQMAnim& anim : Anims) + for(unsigned i = 0; i < Anims.Size(); i++) { + IQMAnim& anim = Anims[i]; anim.Name = reader.ReadName(text); + NamedAnimations.Insert(anim.Name, i); + anim.FirstFrame = reader.ReadUInt32(); anim.NumFrames = reader.ReadUInt32(); anim.Framerate = reader.ReadFloat(); @@ -276,8 +273,8 @@ void IQMModel::LoadGeometry() { try { - FileData lumpdata = fileSystem.ReadFile(mLumpNum); - IQMFileReader reader(lumpdata.GetMem(), (int)lumpdata.GetSize()); + auto lumpdata = fileSystem.ReadFile(mLumpNum); + IQMFileReader reader(lumpdata.data(), (int)lumpdata.size()); Vertices.Resize(NumVertices); for (IQMVertexArray& vertexArray : VertexArrays) @@ -451,7 +448,28 @@ int IQMModel::FindFrame(const char* name, bool nodefault) return FErr_NotFound; } -void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +int IQMModel::FindFirstFrame(FName name) +{ + int * nam = NamedAnimations.CheckKey(name); + if(nam) return Anims[*nam].FirstFrame; + return FErr_NotFound; +} + +int IQMModel::FindLastFrame(FName name) +{ + int * nam = NamedAnimations.CheckKey(name); + if(nam) return Anims[*nam].FirstFrame + Anims[*nam].NumFrames; + return FErr_NotFound; +} + +double IQMModel::FindFramerate(FName name) +{ + int * nam = NamedAnimations.CheckKey(name); + if(nam) return Anims[*nam].Framerate; + return FErr_NotFound; +} + +void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { renderer->SetupFrame(this, 0, 0, NumVertices, boneData, boneStartPosition); @@ -523,7 +541,26 @@ const TArray* IQMModel::AttachAnimationData() return &TRSData; } -const TArray IQMModel::CalculateBones(int frame1, int frame2, double inter, const TArray* animationData, DBoneComponents* boneComponentData, int index) +static TRS InterpolateBone(const TRS &from, const TRS &to, float t, float invt) +{ + TRS bone; + + bone.translation = from.translation * invt + to.translation * t; + bone.rotation = from.rotation * invt; + + if ((bone.rotation | to.rotation * t) < 0) + { + bone.rotation.X *= -1; bone.rotation.Y *= -1; bone.rotation.Z *= -1; bone.rotation.W *= -1; + } + + bone.rotation += to.rotation * t; + bone.rotation.MakeUnit(); + bone.scaling = from.scaling * invt + to.scaling * t; + + return bone; +} + +const TArray IQMModel::CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray* animationData, DBoneComponents* boneComponentData, int index) { const TArray& animationFrames = animationData ? *animationData : TRSData; if (Joints.Size() > 0) @@ -540,8 +577,13 @@ const TArray IQMModel::CalculateBones(int frame1, int frame2, double i int offset1 = frame1 * numbones; int offset2 = frame2 * numbones; - float t = (float)inter; - float invt = 1.0f - t; + + int offset1_1 = frame1_prev * numbones; + int offset2_1 = frame2_prev * numbones; + + float invt = 1.0f - inter; + float invt1 = 1.0f - inter1_prev; + float invt2 = 1.0f - inter2_prev; float swapYZ[16] = { 0.0f }; swapYZ[0 + 0 * 4] = 1.0f; @@ -553,19 +595,26 @@ const TArray IQMModel::CalculateBones(int frame1, int frame2, double i TArray modifiedBone(numbones, true); for (int i = 0; i < numbones; i++) { + TRS prev; + + if(frame1 >= 0 && (frame1_prev >= 0 || inter1_prev < 0)) + { + prev = inter1_prev <= 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1); + } + + TRS next; + + if(frame2 >= 0 && (frame2_prev >= 0 || inter2_prev < 0)) + { + next = inter2_prev <= 0 ? animationFrames[offset2 + i] : InterpolateBone(animationFrames[offset2_1 + i], animationFrames[offset2 + i], inter2_prev, invt2); + } + TRS bone; - TRS from = animationFrames[offset1 + i]; - TRS to = animationFrames[offset2 + i]; - bone.translation = from.translation * invt + to.translation * t; - bone.rotation = from.rotation * invt; - if ((bone.rotation | to.rotation * t) < 0) + if(frame1 >= 0 || inter < 0) { - bone.rotation.X *= -1; bone.rotation.Y *= -1; bone.rotation.Z *= -1; bone.rotation.W *= -1; + bone = inter < 0 ? animationFrames[offset1 + i] : InterpolateBone(prev, next , inter, invt); } - bone.rotation += to.rotation * t; - bone.rotation.MakeUnit(); - bone.scaling = from.scaling * invt + to.scaling * t; if (Joints[i].Parent >= 0 && modifiedBone[Joints[i].Parent]) { diff --git a/src/common/models/models_md2.cpp b/src/common/models/models_md2.cpp index 4f2a12d4e0..280c4d265f 100644 --- a/src/common/models/models_md2.cpp +++ b/src/common/models/models_md2.cpp @@ -31,6 +31,7 @@ #include "texturemanager.h" #include "modelrenderer.h" #include "printf.h" +#include "m_swap.h" #ifdef _MSC_VER #pragma warning(disable:4244) // warning C4244: conversion from 'double' to 'float', possible loss of data @@ -176,8 +177,8 @@ bool FDMDModel::Load(const char * path, int lumpnum, const char * buffer, int le void FDMDModel::LoadGeometry() { static int axis[3] = { VX, VY, VZ }; - FileData lumpdata = fileSystem.ReadFile(mLumpNum); - const char *buffer = (const char *)lumpdata.GetMem(); + auto lumpdata = fileSystem.ReadFile(mLumpNum); + auto buffer = lumpdata.string(); texCoords = new FTexCoord[info.numTexCoords]; memcpy(texCoords, buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord)); @@ -363,7 +364,7 @@ int FDMDModel::FindFrame(const char* name, bool nodefault) // //=========================================================================== -void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID*, const TArray& boneData, int boneStartPosition) +void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID*, const TArray& boneData, int boneStartPosition) { if (frameno >= info.numFrames || frameno2 >= info.numFrames) return; @@ -500,8 +501,8 @@ void FMD2Model::LoadGeometry() { static int axis[3] = { VX, VY, VZ }; uint8_t *md2_frames; - FileData lumpdata = fileSystem.ReadFile(mLumpNum); - const char *buffer = (const char *)lumpdata.GetMem(); + auto lumpdata = fileSystem.ReadFile(mLumpNum); + auto buffer = lumpdata.string(); texCoords = new FTexCoord[info.numTexCoords]; memcpy(texCoords, (uint8_t*)buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord)); diff --git a/src/common/models/models_md3.cpp b/src/common/models/models_md3.cpp index e716a6f260..327cbff88a 100644 --- a/src/common/models/models_md3.cpp +++ b/src/common/models/models_md3.cpp @@ -25,6 +25,7 @@ #include "model_md3.h" #include "texturemanager.h" #include "modelrenderer.h" +#include "m_swap.h" #define MAX_QPATH 64 @@ -188,8 +189,8 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le void FMD3Model::LoadGeometry() { - FileData lumpdata = fileSystem.ReadFile(mLumpNum); - const char *buffer = (const char *)lumpdata.GetMem(); + auto lumpdata = fileSystem.ReadFile(mLumpNum); + auto buffer = lumpdata.string(); md3_header_t * hdr = (md3_header_t *)buffer; md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces)); @@ -344,7 +345,7 @@ int FMD3Model::FindFrame(const char* name, bool nodefault) // //=========================================================================== -void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { if ((unsigned)frameno >= Frames.Size() || (unsigned)frameno2 >= Frames.Size()) return; diff --git a/src/common/models/models_obj.cpp b/src/common/models/models_obj.cpp index e1d777c81d..43e89b1d21 100644 --- a/src/common/models/models_obj.cpp +++ b/src/common/models/models_obj.cpp @@ -37,7 +37,7 @@ */ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length) { - FString objName = fileSystem.GetFileFullPath(lumpnum); + auto objName = fileSystem.GetFileFullPath(lumpnum); FString objBuf(buffer, length); // Do some replacements before we parse the OBJ string @@ -101,7 +101,7 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length wObjBuf = nullptr; objBuf.UnlockBuffer(); } - sc.OpenString(objName, objBuf); + sc.OpenString(objName.c_str(), objBuf); FTextureID curMtl = FNullTextureID(); OBJSurface *curSurface = nullptr; @@ -630,7 +630,7 @@ int FOBJModel::FindFrame(const char* name, bool nodefault) * @param inter The amount to interpolate the two frames. * @param translation The translation for the skin */ -void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { // Prevent the model from rendering if the frame number is < 0 if (frameno < 0 || frameno2 < 0) return; diff --git a/src/common/models/models_ue1.cpp b/src/common/models/models_ue1.cpp index 5db36a672b..8106592617 100644 --- a/src/common/models/models_ue1.cpp +++ b/src/common/models/models_ue1.cpp @@ -53,14 +53,14 @@ bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 ) { realfilename.Substitute("_d.3d","_a.3d"); - lumpnum2 = fileSystem.CheckNumForFullName(realfilename); + lumpnum2 = fileSystem.CheckNumForFullName(realfilename.GetChars()); mDataLump = lumpnum; mAnivLump = lumpnum2; } else { realfilename.Substitute("_a.3d","_d.3d"); - lumpnum2 = fileSystem.CheckNumForFullName(realfilename); + lumpnum2 = fileSystem.CheckNumForFullName(realfilename.GetChars()); mAnivLump = lumpnum; mDataLump = lumpnum2; } @@ -69,26 +69,25 @@ bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int void FUE1Model::LoadGeometry() { - FileData lump, lump2; const char *buffer, *buffer2; - lump = fileSystem.ReadFile(mDataLump); - buffer = (char*)lump.GetMem(); - lump2 = fileSystem.ReadFile(mAnivLump); - buffer2 = (char*)lump2.GetMem(); + auto lump = fileSystem.ReadFile(mDataLump); + buffer = lump.string(); + auto lump2 = fileSystem.ReadFile(mAnivLump); + buffer2 = lump2.string(); // map structures - dhead = (d3dhead*)(buffer); - dpolys = (d3dpoly*)(buffer+sizeof(d3dhead)); - ahead = (a3dhead*)(buffer2); + dhead = (const d3dhead*)(buffer); + dpolys = (const d3dpoly*)(buffer+sizeof(d3dhead)); + ahead = (const a3dhead*)(buffer2); // detect deus ex format if ( (ahead->framesize/dhead->numverts) == 8 ) { - averts = NULL; - dxverts = (dxvert*)(buffer2+sizeof(a3dhead)); + averts = nullptr; + dxverts = (const dxvert*)(buffer2+sizeof(a3dhead)); } else { - averts = (uint32_t*)(buffer2+sizeof(a3dhead)); - dxverts = NULL; + averts = (const uint32_t*)(buffer2+sizeof(a3dhead)); + dxverts = nullptr; } // set counters numVerts = dhead->numverts; @@ -233,7 +232,7 @@ int FUE1Model::FindFrame(const char* name, bool nodefault) return index; } -void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { // the moment of magic if ( (frame < 0) || (frame2 < 0) || (frame >= numFrames) || (frame2 >= numFrames) ) return; diff --git a/src/common/models/models_voxel.cpp b/src/common/models/models_voxel.cpp index f723d1fe4e..e6cd5f8373 100644 --- a/src/common/models/models_voxel.cpp +++ b/src/common/models/models_voxel.cpp @@ -57,8 +57,8 @@ class FVoxelTexture : public FImageSource public: FVoxelTexture(FVoxel *voxel); - int CopyPixels(FBitmap *bmp, int conversion) override; - PalettedPixels CreatePalettedPixels(int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; protected: FVoxel *SourceVox; @@ -84,7 +84,7 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox) // //=========================================================================== -PalettedPixels FVoxelTexture::CreatePalettedPixels(int conversion) +PalettedPixels FVoxelTexture::CreatePalettedPixels(int conversion, int frame) { // GetPixels gets called when a translated palette is used so we still need to implement it here. PalettedPixels Pixels(256); @@ -123,7 +123,7 @@ PalettedPixels FVoxelTexture::CreatePalettedPixels(int conversion) // //=========================================================================== -int FVoxelTexture::CopyPixels(FBitmap *bmp, int conversion) +int FVoxelTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { PalEntry pe[256]; uint8_t bitmap[256]; @@ -400,7 +400,7 @@ float FVoxelModel::getAspectFactor(float stretch) // //=========================================================================== -void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID*, const TArray& boneData, int boneStartPosition) +void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID*, const TArray& boneData, int boneStartPosition) { renderer->SetMaterial(skin, true, translation); renderer->SetupFrame(this, 0, 0, 0, {}, -1); diff --git a/src/common/models/voxels.cpp b/src/common/models/voxels.cpp index d8d2b22454..4d13323530 100644 --- a/src/common/models/voxels.cpp +++ b/src/common/models/voxels.cpp @@ -161,9 +161,10 @@ FVoxel *R_LoadKVX(int lumpnum) int mip, maxmipsize; int i, j, n; - FileData lump = fileSystem.ReadFile(lumpnum); // FileData adds an extra 0 byte to the end. - uint8_t *rawvoxel = (uint8_t *)lump.GetMem(); - int voxelsize = (int)(lump.GetSize()-1); + auto lump = fileSystem.ReadFile(lumpnum); // FileData adds an extra 0 byte to the end. + auto rawvoxel = lump.bytes(); + int voxelsize = (int)(lump.size()); + if (voxelsize <= 768 + 4) return nullptr; // Oh, KVX, why couldn't you have a proper header? We'll just go through // and collect each MIP level, doing lots of range checking, and if the diff --git a/src/common/objects/autosegs.cpp b/src/common/objects/autosegs.cpp index 11fce1005a..e9b3f935ff 100644 --- a/src/common/objects/autosegs.cpp +++ b/src/common/objects/autosegs.cpp @@ -42,6 +42,7 @@ ** compile with something other than Visual C++ or GCC. */ +#include #include "autosegs.h" #ifdef _WIN32 diff --git a/src/common/objects/autosegs.h b/src/common/objects/autosegs.h index 838553dd4b..e015ea9f58 100644 --- a/src/common/objects/autosegs.h +++ b/src/common/objects/autosegs.h @@ -36,6 +36,7 @@ #define AUTOSEGS_H #include +#include #if defined(__clang__) #if defined(__has_feature) && __has_feature(address_sanitizer) diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index ba4f0a0f1a..b66029a535 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -317,6 +317,8 @@ void DObject::Release() void DObject::Destroy () { + RemoveFromNetwork(); + // We cannot call the VM during shutdown because all the needed data has been or is in the process of being deleted. if (PClass::bVMOperational) { @@ -359,54 +361,49 @@ size_t DObject::PropagateMark() const PClass *info = GetClass(); if (!PClass::bShutdown) { - const size_t *offsets = info->FlatPointers; - if (offsets == NULL) + if (info->FlatPointers == nullptr) { - const_cast(info)->BuildFlatPointers(); - offsets = info->FlatPointers; + info->BuildFlatPointers(); + assert(info->FlatPointers); } - while (*offsets != ~(size_t)0) + + for(size_t i = 0; i < info->FlatPointersSize; i++) { - GC::Mark((DObject **)((uint8_t *)this + *offsets)); - offsets++; + GC::Mark((DObject **)((uint8_t *)this + info->FlatPointers[i].first)); } - offsets = info->ArrayPointers; - if (offsets == NULL) + if (info->ArrayPointers == nullptr) { - const_cast(info)->BuildArrayPointers(); - offsets = info->ArrayPointers; + info->BuildArrayPointers(); + assert(info->ArrayPointers); } - while (*offsets != ~(size_t)0) + + for(size_t i = 0; i < info->ArrayPointersSize; i++) { - auto aray = (TArray*)((uint8_t *)this + *offsets); + auto aray = (TArray*)((uint8_t *)this + info->ArrayPointers[i].first); for (auto &p : *aray) { GC::Mark(&p); } - offsets++; } + if (info->MapPointers == nullptr) { - const std::pair *maps = info->MapPointers; - if (maps == NULL) - { - const_cast(info)->BuildMapPointers(); - maps = info->MapPointers; + info->BuildMapPointers(); + assert(info->MapPointers); + } + + for(size_t i = 0; i < info->MapPointersSize; i++) + { + PMap * type = static_cast(info->MapPointers[i].second); + if(type->KeyType->RegType == REGT_STRING) + { // FString,DObject* + PropagateMarkMap((ZSMap*)((uint8_t *)this + info->MapPointers[i].first)); } - while (maps->first != ~(size_t)0) - { - if(maps->second->RegType == REGT_STRING) - { // FString,DObject* - PropagateMarkMap((ZSMap*)((uint8_t *)this + maps->first)); - } - else - { // uint32_t,DObject* - PropagateMarkMap((ZSMap*)((uint8_t *)this + maps->first)); - } - maps++; + else + { // uint32_t,DObject* + PropagateMarkMap((ZSMap*)((uint8_t *)this + info->MapPointers[i].first)); } - } return info->Size; } @@ -419,46 +416,116 @@ size_t DObject::PropagateMark() // //========================================================================== -size_t DObject::PointerSubstitution (DObject *old, DObject *notOld) +template +static void MapPointerSubstitution(M *map, size_t &changed, DObject *old, DObject *notOld, const bool shouldSwap) +{ + TMapIterator it(*map); + typename M::Pair * p; + while(it.NextPair(p)) + { + if (p->Value == old) + { + if (shouldSwap) + { + p->Value = notOld; + changed++; + } + else if (p->Value != nullptr) + { + p->Value = nullptr; + changed++; + } + } + } +} + +size_t DObject::PointerSubstitution (DObject *old, DObject *notOld, bool nullOnFail) { const PClass *info = GetClass(); - const size_t *offsets = info->FlatPointers; size_t changed = 0; - if (offsets == NULL) + if (info->FlatPointers == nullptr) { - const_cast(info)->BuildFlatPointers(); - offsets = info->FlatPointers; + info->BuildFlatPointers(); + assert(info->FlatPointers); } - while (*offsets != ~(size_t)0) + + for(size_t i = 0; i < info->FlatPointersSize; i++) { - if (*(DObject **)((uint8_t *)this + *offsets) == old) + size_t offset = info->FlatPointers[i].first; + auto& obj = *(DObject**)((uint8_t*)this + offset); + + if (obj == old) { - *(DObject **)((uint8_t *)this + *offsets) = notOld; - changed++; + // If a pointer's type is null, that means it's native and anything native is safe to swap + // around due to its inherit type expansiveness. + if (info->FlatPointers[i].second == nullptr || notOld->IsKindOf(info->FlatPointers[i].second->PointedClass())) + { + obj = notOld; + changed++; + } + else if (nullOnFail && obj != nullptr) + { + obj = nullptr; + changed++; + } } - offsets++; } - offsets = info->ArrayPointers; - if (offsets == NULL) + if (info->ArrayPointers == nullptr) { - const_cast(info)->BuildArrayPointers(); - offsets = info->ArrayPointers; + info->BuildArrayPointers(); + assert(info->ArrayPointers); } - while (*offsets != ~(size_t)0) + + for(size_t i = 0; i < info->ArrayPointersSize; i++) { - auto aray = (TArray*)((uint8_t *)this + *offsets); + const bool isType = notOld->IsKindOf(static_cast(info->ArrayPointers[i].second->ElementType)->PointedClass()); + + if (!isType && !nullOnFail) + continue; + + auto aray = (TArray*)((uint8_t*)this + info->ArrayPointers[i].first); for (auto &p : *aray) { if (p == old) { - p = notOld; - changed++; + if (isType) + { + p = notOld; + changed++; + } + else if (p != nullptr) + { + p = nullptr; + changed++; + } } } - offsets++; } + if (info->MapPointers == nullptr) + { + info->BuildMapPointers(); + assert(info->MapPointers); + } + + for(size_t i = 0; i < info->MapPointersSize; i++) + { + PMap * type = static_cast(info->MapPointers[i].second); + + const bool isType = notOld->IsKindOf(static_cast(type->ValueType)->PointedClass()); + if (!isType && !nullOnFail) + continue; + + if(type->KeyType->RegType == REGT_STRING) + { // FString,DObject* + MapPointerSubstitution((ZSMap*)((uint8_t *)this + info->MapPointers[i].first), changed, old, notOld, isType); + } + else + { // uint32_t,DObject* + MapPointerSubstitution((ZSMap*)((uint8_t *)this + info->MapPointers[i].first), changed, old, notOld, isType); + } + } return changed; } @@ -504,8 +571,15 @@ void DObject::Serialize(FSerializer &arc) SerializeFlag("justspawned", OF_JustSpawned); SerializeFlag("spawned", OF_Spawned); - + SerializeFlag("networked", OF_Networked); + ObjectFlags |= OF_SerialSuccess; + + if (arc.isReading() && (ObjectFlags & OF_Networked)) + { + ClearNetworkID(); + EnableNetworking(true); + } } void DObject::CheckIfSerialized () const @@ -520,7 +594,6 @@ void DObject::CheckIfSerialized () const } } - DEFINE_ACTION_FUNCTION(DObject, MSTime) { ACTION_RETURN_INT((uint32_t)I_msTime()); diff --git a/src/common/objects/dobject.h b/src/common/objects/dobject.h index ce591b6d65..f193379c11 100644 --- a/src/common/objects/dobject.h +++ b/src/common/objects/dobject.h @@ -179,8 +179,6 @@ public: \ #include "dobjgc.h" -class AActor; - class DObject { public: @@ -245,9 +243,10 @@ class DObject inline DAngle &AngleVar(FName field); inline FString &StringVar(FName field); template T*& PointerVar(FName field); + inline int* IntArray(FName field); // This is only needed for swapping out PlayerPawns and absolutely nothing else! - virtual size_t PointerSubstitution (DObject *old, DObject *notOld); + virtual size_t PointerSubstitution (DObject *old, DObject *notOld, bool nullOnFail); PClass *GetClass() const { @@ -352,6 +351,18 @@ class DObject friend T* Create(Args&&... args); friend class JitCompiler; + +private: + // This is intentionally left unserialized. + uint32_t _networkID; + +public: + inline bool IsNetworked() const { return (ObjectFlags & OF_Networked); } + inline uint32_t GetNetworkID() const { return _networkID; } + void SetNetworkID(const uint32_t id); + void ClearNetworkID(); + void RemoveFromNetwork(); + virtual void EnableNetworking(const bool enable); }; // This is the only method aside from calling CreateNew that should be used for creating DObjects @@ -435,6 +446,11 @@ inline int &DObject::IntVar(FName field) return *(int*)ScriptVar(field, nullptr); } +inline int* DObject::IntArray(FName field) +{ + return (int*)ScriptVar(field, nullptr); +} + inline FTextureID &DObject::TextureIDVar(FName field) { return *(FTextureID*)ScriptVar(field, nullptr); diff --git a/src/common/objects/dobjgc.cpp b/src/common/objects/dobjgc.cpp index ac75b411a6..d388e4836b 100644 --- a/src/common/objects/dobjgc.cpp +++ b/src/common/objects/dobjgc.cpp @@ -62,6 +62,7 @@ #include "menu.h" #include "stats.h" #include "printf.h" +#include "cmdlib.h" // MACROS ------------------------------------------------------------------ @@ -286,11 +287,22 @@ static size_t DestroyObjects(size_t count) while ((curr = ToDestroy) != nullptr && count-- > 0) { - assert(!(curr->ObjectFlags & OF_EuthanizeMe)); - bytes_destroyed += curr->GetClass()->Size + GCDESTROYCOST; - ToDestroy = curr->GCNext; - curr->GCNext = nullptr; - curr->Destroy(); + // Note that we cannot assume here that the object has not yet been destroyed. + // If destruction happens as the result of another object's destruction we may + // get entries here that have been destroyed already if that owning object was + // first in the list. + if (!(curr->ObjectFlags & OF_EuthanizeMe)) + { + bytes_destroyed += curr->GetClass()->Size + GCDESTROYCOST; + ToDestroy = curr->GCNext; + curr->GCNext = nullptr; + curr->Destroy(); + } + else + { + ToDestroy = curr->GCNext; + curr->GCNext = nullptr; + } } return bytes_destroyed; } diff --git a/src/common/objects/dobjgc.h b/src/common/objects/dobjgc.h index a844a16db4..f5514255db 100644 --- a/src/common/objects/dobjgc.h +++ b/src/common/objects/dobjgc.h @@ -26,6 +26,7 @@ enum EObjectFlags OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk) OF_Spawned = 1 << 12, // Thinker was spawned at all (some thinkers get deleted before spawning) OF_Released = 1 << 13, // Object was released from the GC system and should not be processed by GC function + OF_Networked = 1 << 14, // Object has a unique network identifier that makes it synchronizable between all clients. }; template class TObjPtr; @@ -210,8 +211,8 @@ class TObjPtr { union { - T pp; - DObject *o; + mutable T pp; + mutable DObject *o; }; public: @@ -273,15 +274,26 @@ class TObjPtr { return GC::ReadBarrier(pp); } - constexpr bool operator!=(T u) noexcept + + constexpr const T operator->() const noexcept + { + return GC::ReadBarrier(pp); + } + + constexpr bool operator!=(T u) const noexcept { return GC::ReadBarrier(o) != u; } - constexpr bool operator==(T u) noexcept + constexpr bool operator==(T u) const noexcept { return GC::ReadBarrier(o) == u; } + constexpr bool operator==(TObjPtr u) const noexcept + { + return ForceGet() == u.ForceGet(); + } + template friend inline void GC::Mark(TObjPtr &obj); template friend FSerializer &Serialize(FSerializer &arc, const char *key, TObjPtr &value, TObjPtr *); template friend FSerializer &Serialize(FSerializer &arc, const char *key, TObjPtr &value, U *); diff --git a/src/common/objects/dobjtype.cpp b/src/common/objects/dobjtype.cpp index b39c930f86..0d1bfdf9a8 100644 --- a/src/common/objects/dobjtype.cpp +++ b/src/common/objects/dobjtype.cpp @@ -80,9 +80,7 @@ DEFINE_GLOBAL(WP_NOCHANGE); // PRIVATE DATA DEFINITIONS ------------------------------------------------ // A harmless non-nullptr FlatPointer for classes without pointers. -static const size_t TheEnd = ~(size_t)0; - -static const std::pair TheMapEnd = {~(size_t)0 , nullptr}; +static const std::pair TheEnd = {~(size_t)0 , nullptr}; //========================================================================== // @@ -231,6 +229,8 @@ void PClass::StaticInit () // //========================================================================== +void ClearServices(); + void PClass::StaticShutdown () { if (WP_NOCHANGE != nullptr) @@ -238,6 +238,7 @@ void PClass::StaticShutdown () delete WP_NOCHANGE; } + ClearServices(); // delete all variables containing pointers to script functions. for (auto p : FunctionPtrList) { @@ -437,6 +438,10 @@ DObject *PClass::CreateNew() I_Error("Attempt to instantiate abstract class %s.", TypeName.GetChars()); } ConstructNative (mem); + + if (Defaults != nullptr) + ((DObject *)mem)->ObjectFlags |= ((DObject *)Defaults)->ObjectFlags & OF_Transient; + ((DObject *)mem)->SetClass (const_cast(this)); InitializeSpecials(mem, Defaults, &PClass::SpecialInits); return (DObject *)mem; @@ -662,7 +667,9 @@ PClass *PClass::FindClassTentative(FName name) // //========================================================================== -int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType) +bool ShouldAllowGameSpecificVirtual(FName name, unsigned index, PType* arg, PType* varg); + +int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType, bool ignorePointerReadOnly) { auto proto = variant->Proto; for (unsigned i = 0; i < Virtuals.Size(); i++) @@ -682,8 +689,22 @@ int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction { if (proto->ArgumentTypes[a] != vproto->ArgumentTypes[a]) { - fail = true; - break; + if(ignorePointerReadOnly && proto->ArgumentTypes[a]->isPointer() && vproto->ArgumentTypes[a]->isPointer()) + { + PPointer *ppa = proto->ArgumentTypes[a]->toPointer(); + PPointer *ppb = vproto->ArgumentTypes[a]->toPointer(); + + if(ppa->PointedType != ppb->PointedType) + { + fail = true; + break; + } + } + else if(!ShouldAllowGameSpecificVirtual(name, a, proto->ArgumentTypes[a], vproto->ArgumentTypes[a])) + { + fail = true; + break; + } } } if (fail) continue; @@ -745,75 +766,81 @@ PSymbol *PClass::FindSymbol(FName symname, bool searchparents) const // //========================================================================== -void PClass::BuildFlatPointers () +void PClass::BuildFlatPointers() const { + using pairType = std::pair; + if (FlatPointers != nullptr) { // Already built: Do nothing. return; } - else if (ParentClass == nullptr) - { // No parent (i.e. DObject: FlatPointers is the same as Pointers. - if (Pointers == nullptr) - { // No pointers: Make FlatPointers a harmless non-nullptr. - FlatPointers = &TheEnd; - } - else - { - FlatPointers = Pointers; - } - } else { - ParentClass->BuildFlatPointers (); - - TArray ScriptPointers; - - // Collect all pointers in scripted fields. These are not part of the Pointers list. - for (auto field : Fields) + TArray NativePointers; + if (Pointers != nullptr) { - if (!(field->Flags & VARF_Native)) + for (size_t i = 0; Pointers[i] != ~(size_t)0; i++) { - field->Type->SetPointer(Defaults, unsigned(field->Offset), &ScriptPointers); + NativePointers.Push({Pointers[i], nullptr}); // native pointers have a null type } } - if (Pointers == nullptr && ScriptPointers.Size() == 0) - { // No new pointers: Just use the same FlatPointers as the parent. - FlatPointers = ParentClass->FlatPointers; + if (ParentClass == nullptr) + { // No parent (i.e. DObject): FlatPointers is the same as Pointers. + if (NativePointers.Size() == 0) + { // No pointers: Make FlatPointers a harmless non-nullptr. + FlatPointers = (pairType*)(&TheEnd); + FlatPointersSize = 0; + } + else + { + pairType *flat = (pairType*)ClassDataAllocator.Alloc(sizeof(pairType) * NativePointers.Size()); + memcpy(flat, NativePointers.Data(), sizeof(pairType) * NativePointers.Size()); + + FlatPointers = flat; + FlatPointersSize = NativePointers.Size(); + } } else - { // New pointers: Create a new FlatPointers array and add them. - int numPointers, numSuperPointers; + { + ParentClass->BuildFlatPointers(); - if (Pointers != nullptr) + TArray ScriptPointers; + + // Collect all pointers in scripted fields. These are not part of the Pointers list. + for (auto field : Fields) { - // Count pointers defined by this class. - for (numPointers = 0; Pointers[numPointers] != ~(size_t)0; numPointers++) + if (!(field->Flags & VARF_Native)) { + field->Type->SetPointer(Defaults, unsigned(field->Offset), &ScriptPointers); } } - else numPointers = 0; - - // Count pointers defined by superclasses. - for (numSuperPointers = 0; ParentClass->FlatPointers[numSuperPointers] != ~(size_t)0; numSuperPointers++) - { } - // Concatenate them into a new array - size_t *flat = (size_t*)ClassDataAllocator.Alloc(sizeof(size_t) * (numPointers + numSuperPointers + ScriptPointers.Size() + 1)); - if (numSuperPointers > 0) - { - memcpy (flat, ParentClass->FlatPointers, sizeof(size_t)*numSuperPointers); + if (NativePointers.Size() == 0 && ScriptPointers.Size() == 0) + { // No new pointers: Just use the same FlatPointers as the parent. + FlatPointers = ParentClass->FlatPointers; + FlatPointersSize = ParentClass->FlatPointersSize; } - if (numPointers > 0) - { - memcpy(flat + numSuperPointers, Pointers, sizeof(size_t)*numPointers); - } - if (ScriptPointers.Size() > 0) - { - memcpy(flat + numSuperPointers + numPointers, &ScriptPointers[0], sizeof(size_t) * ScriptPointers.Size()); + else + { // New pointers: Create a new FlatPointers array and add them. + // Concatenate them into a new array + pairType *flat = (pairType*)ClassDataAllocator.Alloc(sizeof(pairType) * (ParentClass->FlatPointersSize + NativePointers.Size() + ScriptPointers.Size())); + + if (ParentClass->FlatPointersSize > 0) + { + memcpy (flat, ParentClass->FlatPointers, sizeof(pairType) * ParentClass->FlatPointersSize); + } + if (NativePointers.Size() > 0) + { + memcpy(flat + ParentClass->FlatPointersSize, NativePointers.Data(), sizeof(pairType) * NativePointers.Size()); + } + if (ScriptPointers.Size() > 0) + { + memcpy(flat + ParentClass->FlatPointersSize + NativePointers.Size(), &ScriptPointers[0], sizeof(pairType) * ScriptPointers.Size()); + } + FlatPointers = flat; + FlatPointersSize = ParentClass->FlatPointersSize + NativePointers.Size() + ScriptPointers.Size(); } - flat[numSuperPointers + numPointers + ScriptPointers.Size()] = ~(size_t)0; - FlatPointers = flat; } } } @@ -826,21 +853,24 @@ void PClass::BuildFlatPointers () // //========================================================================== -void PClass::BuildArrayPointers() +void PClass::BuildArrayPointers() const { + using pairType = std::pair; + if (ArrayPointers != nullptr) { // Already built: Do nothing. return; } else if (ParentClass == nullptr) - { // No parent (i.e. DObject: FlatPointers is the same as Pointers. - ArrayPointers = &TheEnd; + { // No parent (i.e. DObject): Make ArrayPointers a harmless non-nullptr. + ArrayPointers = (pairType*)(&TheEnd); + ArrayPointersSize = 0; } else { ParentClass->BuildArrayPointers(); - TArray ScriptPointers; + TArray ScriptPointers; // Collect all arrays to pointers in scripted fields. for (auto field : Fields) @@ -854,28 +884,24 @@ void PClass::BuildArrayPointers() if (ScriptPointers.Size() == 0) { // No new pointers: Just use the same ArrayPointers as the parent. ArrayPointers = ParentClass->ArrayPointers; + ArrayPointersSize = ParentClass->ArrayPointersSize; } else - { // New pointers: Create a new FlatPointers array and add them. - int numSuperPointers; - - // Count pointers defined by superclasses. - for (numSuperPointers = 0; ParentClass->ArrayPointers[numSuperPointers] != ~(size_t)0; numSuperPointers++) - { - } - + { // New pointers: Create a new ArrayPointers array and add them. // Concatenate them into a new array - size_t *flat = (size_t*)ClassDataAllocator.Alloc(sizeof(size_t) * (numSuperPointers + ScriptPointers.Size() + 1)); - if (numSuperPointers > 0) + pairType *flat = (pairType*)ClassDataAllocator.Alloc(sizeof(pairType) * (ParentClass->ArrayPointersSize + ScriptPointers.Size())); + if (ParentClass->ArrayPointersSize > 0) { - memcpy(flat, ParentClass->ArrayPointers, sizeof(size_t)*numSuperPointers); + memcpy(flat, ParentClass->ArrayPointers, sizeof(pairType) * ParentClass->ArrayPointersSize); } + if (ScriptPointers.Size() > 0) { - memcpy(flat + numSuperPointers, &ScriptPointers[0], sizeof(size_t) * ScriptPointers.Size()); + memcpy(flat + ParentClass->ArrayPointersSize, ScriptPointers.Data(), sizeof(pairType) * ScriptPointers.Size()); } - flat[numSuperPointers + ScriptPointers.Size()] = ~(size_t)0; + ArrayPointers = flat; + ArrayPointersSize = ParentClass->ArrayPointersSize + ScriptPointers.Size(); } } } @@ -888,21 +914,24 @@ void PClass::BuildArrayPointers() // //========================================================================== -void PClass::BuildMapPointers() +void PClass::BuildMapPointers() const { + using pairType = std::pair; + if (MapPointers != nullptr) { // Already built: Do nothing. return; } else if (ParentClass == nullptr) - { // No parent (i.e. DObject: FlatPointers is the same as Pointers. - MapPointers = &TheMapEnd; + { // No parent (i.e. DObject): Make MapPointers a harmless non-nullptr. + MapPointers = (pairType*)(&TheEnd); + MapPointersSize = 0; } else { ParentClass->BuildMapPointers(); - TArray> ScriptPointers; + TArray ScriptPointers; // Collect all arrays to pointers in scripted fields. for (auto field : Fields) @@ -916,28 +945,23 @@ void PClass::BuildMapPointers() if (ScriptPointers.Size() == 0) { // No new pointers: Just use the same ArrayPointers as the parent. MapPointers = ParentClass->MapPointers; + MapPointersSize = ParentClass->MapPointersSize; } else - { // New pointers: Create a new FlatPointers array and add them. - int numSuperPointers; - - // Count pointers defined by superclasses. - for (numSuperPointers = 0; ParentClass->MapPointers[numSuperPointers].first != ~(size_t)0; numSuperPointers++) - { - } - + { // New pointers: Create a new FlatPointers array and add them. // Concatenate them into a new array - std::pair *flat = (std::pair*)ClassDataAllocator.Alloc(sizeof(std::pair) * (numSuperPointers + ScriptPointers.Size() + 1)); - if (numSuperPointers > 0) + pairType *flat = (pairType*)ClassDataAllocator.Alloc(sizeof(pairType) * (ParentClass->MapPointersSize + ScriptPointers.Size())); + if (ParentClass->MapPointersSize > 0) { - memcpy(flat, ParentClass->MapPointers, sizeof(std::pair)*numSuperPointers); + memcpy(flat, ParentClass->MapPointers, sizeof(pairType) * ParentClass->MapPointersSize); } + if (ScriptPointers.Size() > 0) { - memcpy(flat + numSuperPointers, &ScriptPointers[0], sizeof(std::pair) * ScriptPointers.Size()); + memcpy(flat + ParentClass->MapPointersSize, ScriptPointers.Data(), sizeof(pairType) * ScriptPointers.Size()); } - flat[numSuperPointers + ScriptPointers.Size()] = TheMapEnd; MapPointers = flat; + MapPointersSize = ParentClass->MapPointersSize + ScriptPointers.Size(); } } } diff --git a/src/common/objects/dobjtype.h b/src/common/objects/dobjtype.h index c8464a0301..62e6f5ccc5 100644 --- a/src/common/objects/dobjtype.h +++ b/src/common/objects/dobjtype.h @@ -27,6 +27,9 @@ class PClassType; struct FNamespaceManager; class PSymbol; class PField; +class PObjectPointer; +class PDynArray; +class PMap; enum { @@ -43,7 +46,7 @@ class PClass void InitializeSpecials(void* addr, void* defaults, TArray PClass::* Inits); void WriteAllFields(FSerializer &ar, const void *addr) const; bool ReadAllFields(FSerializer &ar, void *addr) const; - int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType); + int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType, bool ignorePointerReadOnly); PSymbol *FindSymbol(FName symname, bool searchparents) const; PField *AddField(FName name, PType *type, uint32_t flags, int fileno = 0); void InitializeDefaults(); @@ -53,10 +56,15 @@ class PClass // Per-class information ------------------------------------- PClass *ParentClass = nullptr; // the class this class derives from - const size_t *Pointers = nullptr; // object pointers defined by this class *only* - const size_t *FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default - const size_t *ArrayPointers = nullptr; // dynamic arrays containing object pointers. - const std::pair *MapPointers = nullptr; // maps containing object pointers. + const size_t * Pointers = nullptr; // native object pointers defined by this class *only* + + mutable size_t FlatPointersSize = 0; + mutable const std::pair * FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default. + mutable size_t ArrayPointersSize = 0; + mutable const std::pair * ArrayPointers = nullptr; // dynamic arrays containing object pointers. + mutable size_t MapPointersSize = 0; + mutable const std::pair * MapPointers = nullptr; // maps containing object pointers. + uint8_t *Defaults = nullptr; uint8_t *Meta = nullptr; // Per-class static script data unsigned Size = sizeof(DObject); @@ -66,11 +74,14 @@ class PClass bool bRuntimeClass = false; // class was defined at run-time, not compile-time bool bDecorateClass = false; // may be subject to some idiosyncracies due to DECORATE backwards compatibility bool bAbstract = false; + bool bSealed = false; + bool bFinal = false; bool bOptional = false; TArray Virtuals; // virtual function table TArray MetaInits; TArray SpecialInits; TArray Fields; + TArray SealedRestriction; PClassType *VMType = nullptr; void (*ConstructNative)(void *); @@ -83,9 +94,11 @@ class PClass PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr, int fileno = 0); void InitializeActorInfo(); - void BuildFlatPointers(); - void BuildArrayPointers(); - void BuildMapPointers(); + + void BuildFlatPointers() const; + void BuildArrayPointers() const; + void BuildMapPointers() const; + void DestroySpecials(void *addr); void DestroyMeta(void *addr); const PClass *NativeClass() const; diff --git a/src/common/platform/posix/cocoa/gl_sysfb.h b/src/common/platform/posix/cocoa/base_sysfb.h similarity index 100% rename from src/common/platform/posix/cocoa/gl_sysfb.h rename to src/common/platform/posix/cocoa/base_sysfb.h diff --git a/src/common/platform/posix/cocoa/i_joystick.cpp b/src/common/platform/posix/cocoa/i_joystick.cpp index 7333803669..a2a27eaff0 100644 --- a/src/common/platform/posix/cocoa/i_joystick.cpp +++ b/src/common/platform/posix/cocoa/i_joystick.cpp @@ -104,6 +104,9 @@ class IOKitJoystick : public IJoystickConfig virtual bool IsAxisMapDefault(int axis); virtual bool IsAxisScaleDefault(int axis); + virtual bool GetEnabled(); + virtual void SetEnabled(bool enabled); + virtual void SetDefaultConfig(); virtual FString GetIdentifier(); @@ -165,6 +168,7 @@ class IOKitJoystick : public IJoystickConfig TArray m_buttons; TArray m_POVs; + bool m_enabled; bool m_useAxesPolling; io_object_t m_notification; @@ -279,6 +283,7 @@ IOKitJoystick::IOKitJoystick(const io_object_t device) : m_interface(CreateDeviceInterface(device)) , m_queue(CreateDeviceQueue(m_interface)) , m_sensitivity(DEFAULT_SENSITIVITY) +, m_enabled(true) , m_useAxesPolling(true) , m_notification(0) { @@ -430,6 +435,17 @@ bool IOKitJoystick::IsAxisScaleDefault(int axis) : true; } + + +bool IOKitJoystick::GetEnabled() +{ + return m_enabled; +} +void IOKitJoystick::SetEnabled(bool enabled) +{ + m_enabled = enabled; +} + #undef IS_AXIS_VALID void IOKitJoystick::SetDefaultConfig() @@ -547,7 +563,7 @@ void IOKitJoystick::Update() if (kIOReturnSuccess == eventResult) { - if (use_joystick) + if (use_joystick && m_enabled) { ProcessAxis(event) || ProcessButton(event) || ProcessPOV(event); } @@ -557,7 +573,7 @@ void IOKitJoystick::Update() Printf(TEXTCOLOR_RED "IOHIDQueueInterface::getNextEvent() failed with code 0x%08X\n", eventResult); } - ProcessAxes(); + if(m_enabled) ProcessAxes(); } diff --git a/src/common/platform/posix/cocoa/i_main.mm b/src/common/platform/posix/cocoa/i_main.mm index 3e257a5ce0..10f3a60ab6 100644 --- a/src/common/platform/posix/cocoa/i_main.mm +++ b/src/common/platform/posix/cocoa/i_main.mm @@ -47,6 +47,7 @@ #include "printf.h" #include "s_music.h" #include "engineerrors.h" +#include "zstring.h" #define ZD_UNUSED(VARIABLE) ((void)(VARIABLE)) @@ -130,6 +131,7 @@ static bool ReadSystemVersionFromPlist(NSOperatingSystemVersion& version) return false; } +FString sys_ostype; void I_DetectOS() { NSOperatingSystemVersion version = {}; @@ -151,21 +153,24 @@ void I_DetectOS() case 10: switch (version.minorVersion) { - case 12: name = "macOS Sierra"; break; - case 13: name = "macOS High Sierra"; break; - case 14: name = "macOS Mojave"; break; - case 15: name = "macOS Catalina"; break; - case 16: name = "macOS Big Sur"; break; + case 12: name = "Sierra"; break; + case 13: name = "High Sierra"; break; + case 14: name = "Mojave"; break; + case 15: name = "Catalina"; break; + case 16: name = "Big Sur"; break; } break; case 11: - name = "macOS Big Sur"; + name = "Big Sur"; break; case 12: - name = "macOS Monterey"; + name = "Monterey"; break; case 13: - name = "macOS Ventura"; + name = "Ventura"; + break; + case 14: + name = "Sonoma"; break; } @@ -186,9 +191,11 @@ void I_DetectOS() "Unknown"; #endif - Printf("%s running %s %d.%d.%d (%s) %s\n", model, name, + Printf("%s running macOS %s %d.%d.%d (%s) %s\n", model, name, int(version.majorVersion), int(version.minorVersion), int(version.patchVersion), release, architecture); + + sys_ostype.Format("macOS %d.%d %s", int(version.majorVersion), int(version.minorVersion), name); } @@ -279,7 +286,8 @@ - (void)applicationDidBecomeActive:(NSNotification*)aNotification { ZD_UNUSED(aNotification); - S_SetSoundPaused(1); + if (GSnd) + S_SetSoundPaused(1); AppActive = true; } @@ -288,7 +296,8 @@ - (void)applicationWillResignActive:(NSNotification*)aNotification { ZD_UNUSED(aNotification); - S_SetSoundPaused(0); + if (GSnd) + S_SetSoundPaused(0); AppActive = false; } @@ -339,7 +348,7 @@ - (BOOL)application:(NSApplication*)theApplication openFile:(NSString*)filename for (size_t i = 0, count = s_argv.Size(); i < count; ++i) { - if (0 == strcmp(s_argv[i], charFileName)) + if (0 == strcmp(s_argv[i].GetChars(), charFileName)) { return FALSE; } diff --git a/src/common/platform/posix/cocoa/i_system.mm b/src/common/platform/posix/cocoa/i_system.mm index 3338f54dba..cef2d177b6 100644 --- a/src/common/platform/posix/cocoa/i_system.mm +++ b/src/common/platform/posix/cocoa/i_system.mm @@ -32,6 +32,7 @@ */ #include "i_common.h" +#include "c_cvars.h" #include #include @@ -40,7 +41,7 @@ #include "st_console.h" #include "v_text.h" - +EXTERN_CVAR(Bool, longsavemessages) double PerfToSec, PerfToMillisec; void CalculateCPUSpeed() @@ -188,7 +189,8 @@ void I_OpenShellFolder(const char* folder) NSString *currentpath = [filemgr currentDirectoryPath]; [filemgr changeCurrentDirectoryPath:[NSString stringWithUTF8String:folder]]; - Printf("Opening folder: %s\n", folder); + if (longsavemessages) + Printf("Opening folder: %s\n", folder); std::system("open ."); [filemgr changeCurrentDirectoryPath:currentpath]; } diff --git a/src/common/platform/posix/cocoa/st_start.mm b/src/common/platform/posix/cocoa/st_start.mm index 8e4ae4bf94..ee6ea26278 100644 --- a/src/common/platform/posix/cocoa/st_start.mm +++ b/src/common/platform/posix/cocoa/st_start.mm @@ -45,7 +45,7 @@ // --------------------------------------------------------------------------- -FBasicStartupScreen::FBasicStartupScreen(int maxProgress, bool showBar) +FBasicStartupScreen::FBasicStartupScreen(int maxProgress) : FStartupScreen(maxProgress) { FConsoleWindow& consoleWindow = FConsoleWindow::GetInstance(); @@ -132,7 +132,7 @@ // --------------------------------------------------------------------------- -FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress, bool showprogress) +FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress) { - return new FBasicStartupScreen(maxProgress, showprogress); + return new FBasicStartupScreen(maxProgress); } diff --git a/src/common/platform/posix/osx/i_specialpaths.mm b/src/common/platform/posix/osx/i_specialpaths.mm index d51bd4ca5a..7d55157efd 100644 --- a/src/common/platform/posix/osx/i_specialpaths.mm +++ b/src/common/platform/posix/osx/i_specialpaths.mm @@ -105,7 +105,7 @@ FString M_GetAppDataPath(bool create) } path += "/" GAMENAMELOWERCASE; - if (create) CreatePath(path); + if (create) CreatePath(path.GetChars()); return path; } @@ -127,7 +127,7 @@ FString M_GetCachePath(bool create) } path += "/zdoom/cache"; - if (create) CreatePath(path); + if (create) CreatePath(path.GetChars()); return path; } @@ -169,9 +169,9 @@ FString M_GetConfigPath(bool for_reading) { // There seems to be no way to get Preferences path via NSFileManager path += "/Preferences/"; - CreatePath(path); + CreatePath(path.GetChars()); - if (!DirExists(path)) + if (!DirExists(path.GetChars())) { path = FString(); } @@ -200,7 +200,7 @@ FString M_GetScreenshotsPath() { path += "/" GAME_DIR "/Screenshots/"; } - CreatePath(path); + CreatePath(path.GetChars()); return path; } @@ -241,7 +241,7 @@ FString M_GetDocumentsPath() path += "/" GAME_DIR "/"; } - CreatePath(path); + CreatePath(path.GetChars()); return path; } diff --git a/src/common/platform/posix/osx/iwadpicker_cocoa.mm b/src/common/platform/posix/osx/iwadpicker_cocoa.mm index e72aa5aad5..f680829bfe 100644 --- a/src/common/platform/posix/osx/iwadpicker_cocoa.mm +++ b/src/common/platform/posix/osx/iwadpicker_cocoa.mm @@ -86,13 +86,13 @@ - (IWADTableData *)init:(WadStuff *) wads num:(int) numwads for(int i = 0;i < numwads;i++) { NSMutableDictionary *record = [[NSMutableDictionary alloc] initWithCapacity:NUM_COLUMNS]; - const char* filename = strrchr(wads[i].Path, '/'); + const char* filename = strrchr(wads[i].Path.GetChars(), '/'); if(filename == NULL) - filename = wads[i].Path; + filename = wads[i].Path.GetChars(); else filename++; [record setObject:[NSString stringWithUTF8String:filename] forKey:[NSString stringWithUTF8String:tableHeaders[COLUMN_IWAD]]]; - [record setObject:[NSString stringWithUTF8String:wads[i].Name] forKey:[NSString stringWithUTF8String:tableHeaders[COLUMN_GAME]]]; + [record setObject:[NSString stringWithUTF8String:wads[i].Name.GetChars()] forKey:[NSString stringWithUTF8String:tableHeaders[COLUMN_GAME]]]; [data addObject:record]; [record release]; } @@ -397,9 +397,9 @@ static void RestartWithParameters(const WadStuff& wad, NSString* parameters) [arguments addObject:GetArchitectureString()]; [arguments addObject:executablePath]; [arguments addObject:@"-iwad"]; - [arguments addObject:[NSString stringWithUTF8String:wad.Path]]; + [arguments addObject:[NSString stringWithUTF8String:wad.Path.GetChars()]]; [arguments addObject:@"+defaultiwad"]; - [arguments addObject:[NSString stringWithUTF8String:wad.Name]]; + [arguments addObject:[NSString stringWithUTF8String:wad.Name.GetChars()]]; [arguments addObject:cvarArgument]; for (int i = 1, count = Args->NumArgs(); i < count; ++i) diff --git a/src/common/platform/posix/sdl/sdlglvideo.cpp b/src/common/platform/posix/sdl/base_sysfb.cpp similarity index 70% rename from src/common/platform/posix/sdl/sdlglvideo.cpp rename to src/common/platform/posix/sdl/base_sysfb.cpp index f1271aac63..e0d70a8475 100644 --- a/src/common/platform/posix/sdl/sdlglvideo.cpp +++ b/src/common/platform/posix/sdl/base_sysfb.cpp @@ -87,8 +87,6 @@ CUSTOM_CVAR(Bool, gl_es, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCA Printf("This won't take effect until " GAMENAME " is restarted.\n"); } -CVAR (Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) - CUSTOM_CVAR(String, vid_sdl_render_driver, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { Printf("This won't take effect until " GAMENAME " is restarted.\n"); @@ -111,29 +109,61 @@ namespace Priv SDL_Window *window; bool softpolyEnabled; bool fullscreenSwitch; + int numberOfDisplays; + SDL_Rect* displayBounds = nullptr; + + void updateDisplayInfo() + { + Priv::numberOfDisplays = SDL_GetNumVideoDisplays(); + if (Priv::numberOfDisplays <= 0) { + Printf("%sWrong number of displays detected.\n", TEXTCOLOR_BOLD); + return; + } + Printf("Number of detected displays %d .\n", Priv::numberOfDisplays); + + if (Priv::displayBounds != nullptr) { + free(Priv::displayBounds); + } + Priv::displayBounds = (SDL_Rect*) calloc(Priv::numberOfDisplays, sizeof(SDL_Rect)); + + for (int i=0; i < Priv::numberOfDisplays; i++) { + if (0 != SDL_GetDisplayBounds(i, &Priv::displayBounds[i])) { + Printf("%sError getting display %d size: %s\n", TEXTCOLOR_BOLD, i, SDL_GetError()); + if (i == 0) { + free(Priv::displayBounds); + displayBounds = nullptr; + } + Priv::numberOfDisplays = i; + return; + } + } + } void CreateWindow(uint32_t extraFlags) { assert(Priv::window == nullptr); - // Set default size - SDL_Rect bounds; - SDL_GetDisplayBounds(vid_adapter, &bounds); + // Get displays and default display size + updateDisplayInfo(); + + // TODO control better when updateDisplayInfo fails + SDL_Rect* bounds = &displayBounds[vid_adapter % numberOfDisplays]; if (win_w <= 0 || win_h <= 0) { - win_w = bounds.w * 8 / 10; - win_h = bounds.h * 8 / 10; + win_w = bounds->w * 8 / 10; + win_h = bounds->h * 8 / 10; } + int xWindowPos = (win_x <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_x; + int yWindowPos = (win_y <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_y; + Printf("Creating window [%dx%d] on adapter %d\n", (*win_w), (*win_h), (*vid_adapter)); + FString caption; caption.Format(GAMENAME " %s (%s)", GetVersionString(), GetGitTime()); const uint32_t windowFlags = (win_maximized ? SDL_WINDOW_MAXIMIZED : 0) | SDL_WINDOW_RESIZABLE | extraFlags; - Priv::window = SDL_CreateWindow(caption, - (win_x <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_x, - (win_y <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_y, - win_w, win_h, windowFlags); + Priv::window = SDL_CreateWindow(caption.GetChars(), xWindowPos, yWindowPos, win_w, win_h, windowFlags); if (Priv::window != nullptr) { @@ -150,15 +180,78 @@ namespace Priv SDL_DestroyWindow(Priv::window); Priv::window = nullptr; + + if (Priv::displayBounds != nullptr) { + free(Priv::displayBounds); + Priv::displayBounds = nullptr; + } } } +CUSTOM_CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + if (Priv::window != nullptr) { + // Get displays and default display size + Priv::updateDisplayInfo(); + + int display = (*self) % Priv::numberOfDisplays; + + // TODO control better when updateDisplayInfo fails + SDL_Rect* bounds = &Priv::displayBounds[vid_adapter % Priv::numberOfDisplays]; + + if (win_w <= 0 || win_h <= 0) + { + win_w = bounds->w * 8 / 10; + win_h = bounds->h * 8 / 10; + } + // Forces to set to the ini this vars to -1, so +vid_adapter keeps working the next time that the game it's launched + win_x = -1; + win_y = -1; + + if ((SDL_GetWindowFlags(Priv::window) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0) { + + // TODO This not works. For some reason keeps stuck on the previus screen + /* + SDL_DisplayMode currentDisplayMode; + SDL_GetWindowDisplayMode(Priv::window, ¤tDisplayMode); + currentDisplayMode.w = win_w; + currentDisplayMode.h = win_h; + if ( 0 != SDL_SetWindowDisplayMode(Priv::window, ¤tDisplayMode)) { + Printf("A problem occured trying to change of display %s\n", SDL_GetError()); + } + */ + + // TODO This workaround also isn't working + /* + SDL_SetWindowFullscreen(Priv::window, 0); + SDL_SetWindowSize(Priv::window, win_w, win_h); + SDL_SetWindowPosition(Priv::window, bounds->x , bounds->y); + SDL_SetWindowFullscreen(Priv::window, SDL_WINDOW_FULLSCREEN_DESKTOP); + */ + Printf("Changing adapter on fullscreen, isn't full supported by SDL. Instead try to switch to windowed mode, change the adapter and then switch again to fullscreen.\n"); + + } else { + SDL_SetWindowSize(Priv::window, win_w, win_h); + SDL_SetWindowPosition(Priv::window, SDL_WINDOWPOS_CENTERED_DISPLAY(display), SDL_WINDOWPOS_CENTERED_DISPLAY(display)); + } + + display = SDL_GetWindowDisplayIndex(Priv::window); + if (display >= 0) { + Printf("New display is %d\n", display ); + } else { + Printf("A problem occured trying to change of display %s\n", SDL_GetError()); + } + } +} + class SDLVideo : public IVideo { public: SDLVideo (); ~SDLVideo (); + void DumpAdapters(); + DFrameBuffer *CreateFrameBuffer (); private: @@ -206,11 +299,6 @@ SDLVideo::SDLVideo () #ifdef HAVE_VULKAN Priv::CreateWindow(SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN | (vid_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); - - if (Priv::window == nullptr) - { - Priv::vulkanEnabled = false; - } #endif } @@ -221,6 +309,22 @@ SDLVideo::~SDLVideo () #endif } +void SDLVideo::DumpAdapters() +{ + Priv::updateDisplayInfo(); + for (int i=0; i < Priv::numberOfDisplays; i++) { + Printf("%s%d. [%dx%d @ (%d,%d)]\n", + vid_adapter == i ? TEXTCOLOR_BOLD : "", + i, + Priv::displayBounds[i].w, + Priv::displayBounds[i].h, + Priv::displayBounds[i].x, + Priv::displayBounds[i].y + ); + } +} + + DFrameBuffer *SDLVideo::CreateFrameBuffer () { SystemBaseFrameBuffer *fb = nullptr; @@ -339,6 +443,7 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h) SDL_GetWindowPosition(Priv::window, &x, &y); win_x = x; win_y = y; + } } @@ -399,7 +504,7 @@ void I_SetWindowTitle(const char* caption) { FString default_caption; default_caption.Format(GAMENAME " %s (%s)", GetVersionString(), GetGitTime()); - SDL_SetWindowTitle(Priv::window, default_caption); + SDL_SetWindowTitle(Priv::window, default_caption.GetChars()); } } diff --git a/src/common/platform/posix/sdl/gl_sysfb.h b/src/common/platform/posix/sdl/base_sysfb.h similarity index 100% rename from src/common/platform/posix/sdl/gl_sysfb.h rename to src/common/platform/posix/sdl/base_sysfb.h diff --git a/src/common/platform/posix/sdl/i_joystick.cpp b/src/common/platform/posix/sdl/i_joystick.cpp index 0fa33ba636..a7eb59568b 100644 --- a/src/common/platform/posix/sdl/i_joystick.cpp +++ b/src/common/platform/posix/sdl/i_joystick.cpp @@ -38,13 +38,15 @@ #include "m_joy.h" #include "keydef.h" +#define DEFAULT_DEADZONE 0.25f; + // Very small deadzone so that floating point magic doesn't happen #define MIN_DEADZONE 0.000001f class SDLInputJoystick: public IJoystickConfig { public: - SDLInputJoystick(int DeviceIndex) : DeviceIndex(DeviceIndex), Multiplier(1.0f) + SDLInputJoystick(int DeviceIndex) : DeviceIndex(DeviceIndex), Multiplier(1.0f) , Enabled(true) { Device = SDL_JoystickOpen(DeviceIndex); if(Device != NULL) @@ -143,7 +145,7 @@ class SDLInputJoystick: public IJoystickConfig info.Name.Format("Axis %d", i+1); else info.Name.Format("Hat %d (%c)", (i-NumAxes)/2 + 1, (i-NumAxes)%2 == 0 ? 'x' : 'y'); - info.DeadZone = MIN_DEADZONE; + info.DeadZone = DEFAULT_DEADZONE; info.Multiplier = 1.0f; info.Value = 0.0; info.ButtonValue = 0; @@ -154,6 +156,17 @@ class SDLInputJoystick: public IJoystickConfig Axes.Push(info); } } + + bool GetEnabled() + { + return Enabled; + } + + void SetEnabled(bool enabled) + { + Enabled = enabled; + } + FString GetIdentifier() { char id[16]; @@ -248,11 +261,16 @@ class SDLInputJoystick: public IJoystickConfig SDL_Joystick *Device; float Multiplier; + bool Enabled; TArray Axes; int NumAxes; int NumHats; + + friend class SDLInputJoystickManager; }; -const EJoyAxis SDLInputJoystick::DefaultAxes[5] = {JOYAXIS_Side, JOYAXIS_Forward, JOYAXIS_Pitch, JOYAXIS_Yaw, JOYAXIS_Up}; + +// [Nash 4 Feb 2024] seems like on Linux, the third axis is actually the Left Trigger, resulting in the player uncontrollably looking upwards. +const EJoyAxis SDLInputJoystick::DefaultAxes[5] = {JOYAXIS_Side, JOYAXIS_Forward, JOYAXIS_None, JOYAXIS_Yaw, JOYAXIS_Pitch}; class SDLInputJoystickManager { @@ -291,7 +309,7 @@ class SDLInputJoystickManager void ProcessInput() const { for(unsigned int i = 0;i < Joysticks.Size();++i) - Joysticks[i]->ProcessInput(); + if(Joysticks[i]->Enabled) Joysticks[i]->ProcessInput(); } protected: TArray Joysticks; diff --git a/src/common/platform/posix/sdl/i_main.cpp b/src/common/platform/posix/sdl/i_main.cpp index 196504b547..4f29bb76ec 100644 --- a/src/common/platform/posix/sdl/i_main.cpp +++ b/src/common/platform/posix/sdl/i_main.cpp @@ -77,6 +77,7 @@ int GameMain(); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- +FString sys_ostype; // The command line arguments. FArgs *Args; @@ -136,6 +137,7 @@ void I_DetectOS() { const char* const separator = operatingSystem.Len() > 0 ? ", " : ""; operatingSystem.AppendFormat("%s%s %s on %s", separator, unameInfo.sysname, unameInfo.release, unameInfo.machine); + sys_ostype.Format("%s %s on %s", unameInfo.sysname, unameInfo.release, unameInfo.machine); } if (operatingSystem.Len() > 0) diff --git a/src/common/platform/posix/sdl/i_system.cpp b/src/common/platform/posix/sdl/i_system.cpp index e81c97f686..7fa41b2bc7 100644 --- a/src/common/platform/posix/sdl/i_system.cpp +++ b/src/common/platform/posix/sdl/i_system.cpp @@ -51,7 +51,6 @@ #include #include #include -#include "printf.h" #endif #include @@ -65,11 +64,11 @@ #include "c_cvars.h" #include "palutil.h" #include "st_start.h" - +#include "printf.h" +#include "launcherwindow.h" #ifndef NO_GTK bool I_GtkAvailable (); -int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags); void I_ShowFatalError_Gtk(const char* errortext); #elif defined(__APPLE__) int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad); @@ -78,6 +77,7 @@ int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad double PerfToSec, PerfToMillisec; CVAR(Bool, con_printansi, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE); CVAR(Bool, con_4bitansi, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE); +EXTERN_CVAR(Bool, longsavemessages) extern FStartupScreen *StartWindow; @@ -118,7 +118,7 @@ void Unix_I_FatalError(const char* errortext) FString cmd; cmd << "kdialog --title \"" GAMENAME " " << GetVersionString() << "\" --msgbox \"" << errortext << "\""; - popen(cmd, "r"); + popen(cmd.GetChars(), "r"); } #ifndef NO_GTK else if (I_GtkAvailable()) @@ -131,7 +131,7 @@ void Unix_I_FatalError(const char* errortext) FString title; title << GAMENAME " " << GetVersionString(); - if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, errortext, NULL) < 0) + if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title.GetChars(), errortext, NULL) < 0) { printf("\n%s\n", errortext); } @@ -218,20 +218,21 @@ void RedrawProgressBar(int CurPos, int MaxPos) CleanProgressBar(); struct winsize sizeOfWindow; ioctl(STDOUT_FILENO, TIOCGWINSZ, &sizeOfWindow); + int windowColClamped = std::min((int)sizeOfWindow.ws_col, 512); double progVal = std::clamp((double)CurPos / (double)MaxPos,0.0,1.0); - int curProgVal = std::clamp(int(sizeOfWindow.ws_col * progVal),0,(int)sizeOfWindow.ws_col); + int curProgVal = std::clamp(int(windowColClamped * progVal),0,windowColClamped); char progressBuffer[512]; memset(progressBuffer,'.',512); - progressBuffer[sizeOfWindow.ws_col - 1] = 0; + progressBuffer[windowColClamped - 1] = 0; int lengthOfStr = 0; while (curProgVal-- > 0) { progressBuffer[lengthOfStr++] = '='; - if (lengthOfStr >= sizeOfWindow.ws_col - 1) break; + if (lengthOfStr >= windowColClamped - 1) break; } - fprintf(stdout, "\0337\033[%d;%dH\033[2K[%s\033[%d;%dH]\0338", sizeOfWindow.ws_row, 0, progressBuffer, sizeOfWindow.ws_row, sizeOfWindow.ws_col); + fprintf(stdout, "\0337\033[%d;%dH\033[2K[%s\033[%d;%dH]\0338", sizeOfWindow.ws_row, 0, progressBuffer, sizeOfWindow.ws_row, windowColClamped); fflush(stdout); ProgressBarCurPos = CurPos; ProgressBarMaxPos = MaxPos; @@ -299,95 +300,16 @@ void I_PrintStr(const char *cp) int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags) { - int i; - if (!showwin) { return defaultiwad; } -#ifndef __APPLE__ - if(I_FileAvailable("kdialog")) - { - FString cmd("kdialog --title \"" GAMENAME " "); - cmd << GetVersionString() << ": Select an IWAD to use\"" - " --menu \"" GAMENAME " found more than one IWAD\n" - "Select from the list below to determine which one to use:\""; - - for(i = 0; i < numwads; ++i) - { - const char *filepart = strrchr(wads[i].Path, '/'); - if(filepart == NULL) - filepart = wads[i].Path; - else - filepart++; - // Menu entries are specified in "tag" "item" pairs, where when a - // particular item is selected (and the Okay button clicked), its - // corresponding tag is printed to stdout for identification. - cmd.AppendFormat(" \"%d\" \"%s (%s)\"", i, wads[i].Name.GetChars(), filepart); - } - - if(defaultiwad >= 0 && defaultiwad < numwads) - { - const char *filepart = strrchr(wads[defaultiwad].Path, '/'); - if(filepart == NULL) - filepart = wads[defaultiwad].Path; - else - filepart++; - cmd.AppendFormat(" --default \"%s (%s)\"", wads[defaultiwad].Name.GetChars(), filepart); - } - - FILE *f = popen(cmd, "r"); - if(f != NULL) - { - char gotstr[16]; - - if(fgets(gotstr, sizeof(gotstr), f) == NULL || - sscanf(gotstr, "%d", &i) != 1) - i = -1; - - // Exit status = 1 means the selection was canceled (either by - // Cancel/Esc or the X button), not that there was an error running - // the program. In that case, nothing was printed so fgets will - // have failed. Other values can indicate an error running the app, - // so fall back to whatever else can be used. - int status = pclose(f); - if(WIFEXITED(status) && (WEXITSTATUS(status) == 0 || WEXITSTATUS(status) == 1)) - return i; - } - } -#endif - -#ifndef NO_GTK - if (I_GtkAvailable()) - { - return I_PickIWad_Gtk (wads, numwads, showwin, defaultiwad, autoloadflags); - } -#endif - #ifdef __APPLE__ return I_PickIWad_Cocoa (wads, numwads, showwin, defaultiwad); +#else + return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags); #endif - - if (!isatty(fileno(stdin))) - { - return defaultiwad; - } - - printf ("Please select a game wad (or 0 to exit):\n"); - for (i = 0; i < numwads; ++i) - { - const char *filepart = strrchr (wads[i].Path, '/'); - if (filepart == NULL) - filepart = wads[i].Path; - else - filepart++; - printf ("%d. %s (%s)\n", i+1, wads[i].Name.GetChars(), filepart); - } - printf ("Which one? "); - if (scanf ("%d", &i) != 1 || i > numwads) - return -1; - return i-1; } void I_PutInClipboard (const char *str) @@ -408,7 +330,7 @@ FString I_GetFromClipboard (bool use_primary_selection) FString I_GetCWD() { - char* curdir = get_current_dir_name(); + char* curdir = getcwd(NULL,0); if (!curdir) { return ""; @@ -447,17 +369,21 @@ unsigned int I_MakeRNGSeed() void I_OpenShellFolder(const char* infolder) { - char* curdir = get_current_dir_name(); + char* curdir = getcwd(NULL,0); if (!chdir(infolder)) { - Printf("Opening folder: %s\n", infolder); + if (longsavemessages) + Printf("Opening folder: %s\n", infolder); std::system("xdg-open ."); chdir(curdir); } else { - Printf("Unable to open directory '%s\n", infolder); + if (longsavemessages) + Printf("Unable to open directory '%s\n", infolder); + else + Printf("Unable to open requested directory\n"); } free(curdir); } diff --git a/src/common/platform/posix/sdl/st_start.cpp b/src/common/platform/posix/sdl/st_start.cpp index d372e79bc0..019a66122b 100644 --- a/src/common/platform/posix/sdl/st_start.cpp +++ b/src/common/platform/posix/sdl/st_start.cpp @@ -85,7 +85,7 @@ static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' }; // //========================================================================== -FStartupScreen *FStartupScreen::CreateInstance(int max_progress, bool) +FStartupScreen *FStartupScreen::CreateInstance(int max_progress) { return new FTTYStartupScreen(max_progress); } @@ -257,6 +257,7 @@ bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata) struct timeval tv; int retval; char k; + bool stdin_eof = false; for (;;) { @@ -265,7 +266,10 @@ bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata) tv.tv_usec = 500000; FD_ZERO (&rfds); - FD_SET (STDIN_FILENO, &rfds); + if (!stdin_eof) + { + FD_SET (STDIN_FILENO, &rfds); + } retval = select (1, &rfds, NULL, NULL, &tv); @@ -281,13 +285,21 @@ bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata) return true; } } - else if (read (STDIN_FILENO, &k, 1) == 1) + else { - // Check input on stdin - if (k == 'q' || k == 'Q') + ssize_t amt = read (STDIN_FILENO, &k, 1); // Check input on stdin + if (amt == 0) + { + // EOF. Stop reading + stdin_eof = true; + } + else if (amt == 1) { - fprintf (stderr, "\nNetwork game synchronization aborted."); - return false; + if (k == 'q' || k == 'Q') + { + fprintf (stderr, "\nNetwork game synchronization aborted."); + return false; + } } } } diff --git a/src/common/platform/posix/unix/gtk_dialogs.cpp b/src/common/platform/posix/unix/gtk_dialogs.cpp index 2c9ad412ab..115e0ceaab 100644 --- a/src/common/platform/posix/unix/gtk_dialogs.cpp +++ b/src/common/platform/posix/unix/gtk_dialogs.cpp @@ -291,9 +291,9 @@ class ZUIListView : public ZUIWidget store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); for (int i = 0; i < numwads; ++i) { - const char *filepart = strrchr (wads[i].Path, '/'); + const char *filepart = strrchr (wads[i].Path.GetChars(), '/'); if (filepart == NULL) - filepart = wads[i].Path; + filepart = wads[i].Path.GetChars(); else filepart++; gtk_list_store_append (store, &iter); @@ -484,106 +484,6 @@ class ZUIButton : public ZUIWidget } }; -static int PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags) -{ - char caption[100]; - mysnprintf(caption, countof(caption), GAMENAME " %s: Select an IWAD to use", GetVersionString()); - - ZUIWindow window(caption); - - ZUIVBox vbox; - - ZUILabel label(GAMENAME " found more than one IWAD\nSelect from the list below to determine which one to use:"); - ZUIListView listview(wads, numwads, defaultiwad); - ZUIScrolledWindow scroll((ZUIWidget*)&listview); - - ZUIHBox hboxOptions; - - ZUIVBox vboxVideo; - ZUILabel videoSettings("Video settings"); - ZUIRadioButton vulkan("Vulkan"); - ZUICheckButton fullscreen("Full screen"); - - ZUIVBox vboxMisc; - ZUICheckButton noautoload("Disable autoload"); - ZUICheckButton dontAskAgain("Don't ask me this again"); - - ZUIVBox vboxExtra; - ZUILabel extraGraphics("Extra graphics"); - ZUICheckButton lights("Lights"); - ZUICheckButton brightmaps("Brightmaps"); - ZUICheckButton widescreen("Widescreen"); - - ZUIHBox hboxButtons; - - ZUIButtonBox bbox; - ZUIButton playButton("Play Game!", true); - ZUIButton exitButton("Exit", false); - - window.AddWidget(&vbox); - vbox.PackStart(&label, false, false, 0); - vbox.PackStart(&scroll, true, true, 0); - vbox.PackEnd(&hboxButtons, false, false, 0); - vbox.PackEnd(&hboxOptions, false, false, 0); - hboxOptions.PackStart(&vboxVideo, false, false, 15); - hboxOptions.PackStart(&vboxMisc, true, false, 15); - hboxOptions.PackStart(&vboxExtra, false, false, 15); - vboxVideo.PackStart(&videoSettings, false, false, 0); - vboxVideo.PackStart(&vulkan, false, false, 0); - vboxVideo.PackStart(&fullscreen, false, false, 15); - vboxMisc.PackStart(&noautoload, false, false, 0); - vboxMisc.PackStart(&dontAskAgain, false, false, 0); - vboxExtra.PackStart(&extraGraphics, false, false, 0); - vboxExtra.PackStart(&lights, false, false, 0); - vboxExtra.PackStart(&brightmaps, false, false, 0); - vboxExtra.PackStart(&widescreen, false, false, 0); - hboxButtons.PackStart(&bbox, true, true, 0); - bbox.PackStart(&playButton, false, false, 0); - bbox.PackEnd(&exitButton, false, false, 0); - - dontAskAgain.SetChecked(!showwin); - - vulkan.SetChecked(true); - - if (vid_fullscreen) fullscreen.SetChecked(true); - - if (autoloadflags & 1) noautoload.SetChecked(true); - if (autoloadflags & 2) lights.SetChecked(true); - if (autoloadflags & 4) brightmaps.SetChecked(true); - if (autoloadflags & 8) widescreen.SetChecked(true); - - int close_style = 0; - listview.ConnectButtonPress(&close_style); - listview.ConnectKeyPress(&window); - playButton.ConnectClickedOK(&close_style); - exitButton.ConnectClickedExit(&window); - - playButton.GrabDefault(); - - window.RunModal(); - - if (close_style == 1) - { - int i = listview.GetSelectedIndex(); - - // Set state of queryiwad based on the checkbox. - queryiwad = !dontAskAgain.GetChecked(); - - vid_fullscreen = fullscreen.GetChecked(); - - autoloadflags = 0; - if (noautoload.GetChecked()) autoloadflags |= 1; - if (lights.GetChecked()) autoloadflags |= 2; - if (brightmaps.GetChecked()) autoloadflags |= 4; - if (widescreen.GetChecked()) autoloadflags |= 8; - - return i; - } - else - { - return -1; - } -} static void ShowError(const char* errortext) { @@ -606,11 +506,6 @@ static void ShowError(const char* errortext) } // namespace Gtk -int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags) -{ - return Gtk::PickIWad (wads, numwads, showwin, defaultiwad, autoloadflags); -} - void I_ShowFatalError_Gtk(const char* errortext) { Gtk::ShowError(errortext); } diff --git a/src/common/platform/posix/unix/i_specialpaths.cpp b/src/common/platform/posix/unix/i_specialpaths.cpp index 524f94c606..112e92ee79 100644 --- a/src/common/platform/posix/unix/i_specialpaths.cpp +++ b/src/common/platform/posix/unix/i_specialpaths.cpp @@ -50,15 +50,15 @@ FString GetUserFile (const char *file) path = NicePath("$HOME/" GAME_DIR "/"); - if (stat (path, &info) == -1) + if (stat (path.GetChars(), &info) == -1) { struct stat extrainfo; // Sanity check for $HOME/.config FString configPath = NicePath("$HOME/.config/"); - if (stat (configPath, &extrainfo) == -1) + if (stat (configPath.GetChars(), &extrainfo) == -1) { - if (mkdir (configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + if (mkdir (configPath.GetChars(), S_IRUSR | S_IWUSR | S_IXUSR) == -1) { I_FatalError ("Failed to create $HOME/.config directory:\n%s", strerror(errno)); } @@ -72,9 +72,9 @@ FString GetUserFile (const char *file) // Transfer the old zdoom directory to the new location bool moved = false; FString oldpath = NicePath("$HOME/." GAMENAMELOWERCASE "/"); - if (stat (oldpath, &extrainfo) != -1) + if (stat (oldpath.GetChars(), &extrainfo) != -1) { - if (rename(oldpath, path) == -1) + if (rename(oldpath.GetChars(), path.GetChars()) == -1) { I_Error ("Failed to move old " GAMENAMELOWERCASE " directory (%s) to new location (%s).", oldpath.GetChars(), path.GetChars()); @@ -83,7 +83,7 @@ FString GetUserFile (const char *file) moved = true; } - if (!moved && mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + if (!moved && mkdir (path.GetChars(), S_IRUSR | S_IWUSR | S_IXUSR) == -1) { I_FatalError ("Failed to create %s directory:\n%s", path.GetChars(), strerror (errno)); @@ -115,7 +115,7 @@ FString M_GetAppDataPath(bool create) FString path = NicePath("$HOME/.config/" GAMENAMELOWERCASE); if (create) { - CreatePath(path); + CreatePath(path.GetChars()); } return path; } @@ -135,7 +135,7 @@ FString M_GetCachePath(bool create) FString path = NicePath("$HOME/.config/zdoom/cache"); if (create) { - CreatePath(path); + CreatePath(path.GetChars()); } return path; } @@ -191,7 +191,7 @@ FString M_GetScreenshotsPath() FString M_GetSavegamesPath() { - return NicePath("$HOME/" GAME_DIR "/"); + return NicePath("$HOME/" GAME_DIR "/savegames/"); } //=========================================================================== diff --git a/src/common/platform/win32/i_crash.cpp b/src/common/platform/win32/i_crash.cpp index 4ba6c0dbf0..e8f77cc766 100644 --- a/src/common/platform/win32/i_crash.cpp +++ b/src/common/platform/win32/i_crash.cpp @@ -1,2289 +1,406 @@ /* -** i_crash.cpp -** Gathers exception information when the program crashes. +** Windows Crash Reporter +** Copyright (c) 2024 Magnus Norddahl ** -**--------------------------------------------------------------------------- -** Copyright 2002-2006 Randy Heit -** All rights reserved. +** 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. ** -** 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. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.s -** IN NO EVENT SHALL THE AUTHOR 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. -**--------------------------------------------------------------------------- +** 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. */ -// HEADER FILES ------------------------------------------------------------ - -#pragma warning(disable:4996) #define WIN32_LEAN_AND_MEAN #include -#include -#include -#ifndef _M_IX86 -#include -#endif -#ifndef __GNUC__ -#if _MSC_VER -#pragma warning(disable:4091) // this silences a warning for a bogus definition in the Windows 8.1 SDK. -#endif -#include -#if _MSC_VER -#pragma warning(default:4091) -#endif -#endif -#include -#include -#include -#include - -#include -#include -#include "resource.h" -#include "version.h" -#include "m_swap.h" -#include "basics.h" -#include "zstring.h" -#include "printf.h" -#include "cmdlib.h" +#include +#include +#include +#include #include "i_mainwindow.h" -#include -#include - -// MACROS ------------------------------------------------------------------ - -// Maximum number of files that might appear in a crash report. -#define MAX_FILES 5 - -#define ZIP_LOCALFILE MAKE_ID('P','K',3,4) -#define ZIP_CENTRALFILE MAKE_ID('P','K',1,2) -#define ZIP_ENDOFDIR MAKE_ID('P','K',5,6) - -// DBGHELP.H --------------------------------------------------------------- - -// w32api does not include dbghelp.h, so if I don't include these here, -// a person using GCC will need to download the Platform SDK, grab dbghelp.h -// from it, and edit it so it works with GCC. -#ifdef __GNUC__ -typedef enum _MINIDUMP_TYPE -{ - MiniDumpNormal - // Other types omitted. -} MINIDUMP_TYPE; - -typedef struct _MINIDUMP_EXCEPTION_INFORMATION { - DWORD ThreadId; - PEXCEPTION_POINTERS ExceptionPointers; - BOOL ClientPointers; -} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; - -typedef struct _MINIDUMP_USER_STREAM_INFORMATION { - ULONG UserStreamCount; - void *UserStreamArray; // Not really void * -} MINIDUMP_USER_STREAM_INFORMATION, *PMINIDUMP_USER_STREAM_INFORMATION; - -typedef BOOL (WINAPI * MINIDUMP_CALLBACK_ROUTINE) ( - IN PVOID CallbackParam, - IN CONST void *CallbackInput, // Not really void * - IN OUT void *CallbackOutput // Not really void * - ); - -typedef struct _MINIDUMP_CALLBACK_INFORMATION { - MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; - PVOID CallbackParam; -} MINIDUMP_CALLBACK_INFORMATION, *PMINIDUMP_CALLBACK_INFORMATION; -#endif - -// Dbghelp.dll is loaded at runtime so we don't create any needless -// dependencies on it. -typedef BOOL (WINAPI *THREADWALK) (HANDLE, LPTHREADENTRY32); -typedef BOOL (WINAPI *MODULEWALK) (HANDLE, LPMODULEENTRY32); -typedef HANDLE (WINAPI *CREATESNAPSHOT) (DWORD, DWORD); -typedef BOOL (WINAPI *WRITEDUMP) (HANDLE, DWORD, HANDLE, int, - PMINIDUMP_EXCEPTION_INFORMATION, - PMINIDUMP_USER_STREAM_INFORMATION, - PMINIDUMP_CALLBACK_INFORMATION); - -// TYPES ------------------------------------------------------------------- - -#ifdef _M_X64 -typedef PRUNTIME_FUNCTION (WINAPI *RTLLOOKUPFUNCTIONENTRY) - (ULONG64 ControlPc, PULONG64 ImageBase, void *HistoryTable); -#endif - -// Damn Microsoft for doing Get/SetWindowLongPtr half-assed. Instead of -// giving them proper prototypes under Win32, they are just macros for -// Get/SetWindowLong, meaning they take LONGs and not LONG_PTRs. -#ifdef _WIN64 -typedef LONG_PTR WLONG_PTR; -#else -typedef LONG WLONG_PTR; -#endif +#ifdef _MSC_VER +#include +#include -namespace zip +class CrashReporter { -#pragma pack(push,1) - struct LocalFileHeader - { - uint32_t Magic; // 0 - uint8_t VersionToExtract[2]; // 4 - uint16_t Flags; // 6 - uint16_t Method; // 8 - uint16_t ModTime; // 10 - uint16_t ModDate; // 12 - uint32_t CRC32; // 14 - uint32_t CompressedSize; // 18 - uint32_t UncompressedSize; // 22 - uint16_t NameLength; // 26 - uint16_t ExtraLength; // 28 - }; +public: + CrashReporter(const std::wstring& reports_directory, const std::wstring& uploader_executable = std::wstring()); + ~CrashReporter(); - struct CentralDirectoryEntry - { - uint32_t Magic; - uint8_t VersionMadeBy[2]; - uint8_t VersionToExtract[2]; - uint16_t Flags; - uint16_t Method; - uint16_t ModTime; - uint16_t ModDate; - uint32_t CRC32; - uint32_t CompressedSize; - uint32_t UncompressedSize; - uint16_t NameLength; - uint16_t ExtraLength; - uint16_t CommentLength; - uint16_t StartingDiskNumber; - uint16_t InternalAttributes; - uint32_t ExternalAttributes; - uint32_t LocalHeaderOffset; - }; + static void hook_thread(); + static void invoke(); + static void generate_report(); - struct EndOfCentralDirectory +private: + struct DumpParams { - uint32_t Magic; - uint16_t DiskNumber; - uint16_t FirstDisk; - uint16_t NumEntries; - uint16_t NumEntriesOnAllDisks; - uint32_t DirectorySize; - uint32_t DirectoryOffset; - uint16_t ZipCommentLength; + HANDLE hprocess; + HANDLE hthread; + int thread_id; + PEXCEPTION_POINTERS exception_pointers; + unsigned int exception_code; }; -#pragma pack(pop) -} -struct TarFile -{ - HANDLE File; - const char *Filename; - int ZipOffset; - uint32_t UncompressedSize; - uint32_t CompressedSize; - uint32_t CRC32; - bool Deflated; -}; - -struct MiniDumpThreadData -{ - HANDLE File; - WRITEDUMP pMiniDumpWriteDump; - MINIDUMP_EXCEPTION_INFORMATION *Exceptor; + void load_dbg_help(); + static void create_dump(DumpParams* params, bool launch_uploader); + static std::wstring reports_directory; + static std::wstring uploader_exe; + + static std::recursive_mutex mutex; + + static DWORD WINAPI create_dump_main(LPVOID thread_parameter); + + static int generate_report_filter(unsigned int code, struct _EXCEPTION_POINTERS* ep); + static void on_terminate(); + static void on_sigabort(int); + static void on_se_unhandled_exception(unsigned int exception_code, PEXCEPTION_POINTERS exception_pointers); + static LONG WINAPI on_win32_unhandled_exception(PEXCEPTION_POINTERS exception_pointers); + + typedef BOOL(WINAPI* MiniDumpWriteDumpPointer)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, CONST PMINIDUMP_EXCEPTION_INFORMATION, CONST PMINIDUMP_USER_STREAM_INFORMATION, CONST PMINIDUMP_CALLBACK_INFORMATION); + HMODULE module_dbghlp; + static MiniDumpWriteDumpPointer func_MiniDumpWriteDump; + + bool enforce_filter(bool enforce); + bool write_memory(BYTE* target, const BYTE* source, DWORD size); +#if defined(_M_X64) + static const BYTE patch_bytes[6]; + BYTE original_bytes[6]; +#elif defined(_M_IX86) + static const BYTE patch_bytes[5]; + BYTE original_bytes[5]; +#endif }; -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void AddFile (HANDLE file, const char *filename); -static void CloseTarFiles (); -static HANDLE MakeZip (); -static void AddZipFile (HANDLE ziphandle, TarFile *whichfile, short dosdate, short dostime); -static HANDLE CreateTempFile (); - -static void DumpBytes (HANDLE file, uint8_t *address); -static void AddStackInfo (HANDLE file, void *dumpaddress, DWORD code, CONTEXT *ctxt); -static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack, DWORD *jump, CONTEXT *ctxt); -static void AddToolHelp (HANDLE file); - -static HANDLE WriteTextReport (); -static DWORD WINAPI WriteMiniDumpInAnotherThread (LPVOID lpParam); - -static INT_PTR CALLBACK DetailsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); -static void SetEditControl (HWND control, HWND sizedisplay, int filenum); - -static BOOL UploadReport (HANDLE report, bool gziped); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -extern HINSTANCE g_hInst; - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -EXCEPTION_POINTERS CrashPointers; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static HRESULT (__stdcall *pEnableThemeDialogTexture) (HWND hwnd, DWORD dwFlags); - -static TarFile TarFiles[MAX_FILES]; - -static int NumFiles; - -static HANDLE DbgProcess; -static DWORD DbgProcessID; -static DWORD DbgThreadID; -static DWORD CrashCode; -static PVOID CrashAddress; -static bool NeedDbgHelp; -static char CrashSummary[256]; - -static WNDPROC StdStaticProc; - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// SafeReadMemory -// -// Returns true if the memory was succussfully read and false if not. -// -//========================================================================== - -static bool SafeReadMemory (const void *base, void *buffer, size_t len) -{ -#ifdef __GNUC__ - // GCC version: Test the memory beforehand and hope it doesn't become - // unreadable while we read it. GCC is the only Windows compiler (that - // I know of) that can't do SEH. - - if (IsBadReadPtr (base, len)) - { - return false; - } - memcpy (buffer, base, len); - return true; #else - // Non-GCC version: Use SEH to catch any bad reads immediately when - // they happen instead of trying to catch them beforehand. - bool success = false; - - __try - { - memcpy (buffer, base, len); - success = true; - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } - return success; -#endif -} - -//========================================================================== -// -// GetTopOfStack -// -// Given a pointer to some address on the stack, returns a pointer to -// the top of the stack. -// -//========================================================================== - -DWORD *GetTopOfStack (void *top) +class CrashReporter { - MEMORY_BASIC_INFORMATION memInfo; +public: + CrashReporter(const std::wstring& reports_directory, const std::wstring& uploader_executable = std::wstring()) { } - if (VirtualQuery (top, &memInfo, sizeof(memInfo))) - { - return (DWORD *)((uint8_t *)memInfo.BaseAddress + memInfo.RegionSize); - } - else - { - return NULL; - } -} + static void hook_thread() {} + static void invoke() { } + static void generate_report() { } +}; -//========================================================================== -// -// WriteMyMiniDump -// -// Writes a minidump if dbghelp.dll is present and adds it to the tarball. -// Otherwise, it just returns INVALID_HANDLE_VALUE. -// -//========================================================================== +#endif -static HANDLE WriteMyMiniDump (void) +void InitCrashReporter(const std::wstring& reports_directory, const std::wstring& uploader_executable) { - MINIDUMP_EXCEPTION_INFORMATION exceptor = { DbgThreadID, &CrashPointers, FALSE }; - WCHAR dbghelpPath[MAX_PATH+12], *bs; - WRITEDUMP pMiniDumpWriteDump; - HANDLE file = INVALID_HANDLE_VALUE; - BOOL good = FALSE; - HMODULE dbghelp = NULL; - - // Make sure dbghelp.dll and MiniDumpWriteDump are available - // Try loading from the application directory first, then from the search path. - GetModuleFileNameW (NULL, dbghelpPath, MAX_PATH); - dbghelpPath[MAX_PATH] = 0; - bs = wcsrchr (dbghelpPath, '\\'); - if (bs != NULL) - { - wcscpy (bs + 1, L"dbghelp.dll"); - dbghelp = LoadLibraryW (dbghelpPath); - } - if (dbghelp == NULL) - { - dbghelp = LoadLibraryA ("dbghelp.dll"); - if (dbghelp == NULL) - { - NeedDbgHelp = true; - return INVALID_HANDLE_VALUE; - } - } - pMiniDumpWriteDump = (WRITEDUMP)GetProcAddress (dbghelp, "MiniDumpWriteDump"); - if (pMiniDumpWriteDump != NULL) - { - file = CreateTempFile (); - if (file != INVALID_HANDLE_VALUE) - { - if (CrashPointers.ExceptionRecord->ExceptionCode != EXCEPTION_STACK_OVERFLOW) - { - good = pMiniDumpWriteDump (DbgProcess, DbgProcessID, file, -#if 1 - MiniDumpNormal -#else - MiniDumpWithDataSegs|MiniDumpWithIndirectlyReferencedMemory|MiniDumpWithPrivateReadWriteMemory -#endif - , &exceptor, NULL, NULL); - } - else - { - MiniDumpThreadData dumpdata = { file, pMiniDumpWriteDump, &exceptor }; - DWORD id; - HANDLE thread = CreateThread (NULL, 0, WriteMiniDumpInAnotherThread, - &dumpdata, 0, &id); - WaitForSingleObject (thread, INFINITE); - if (GetExitCodeThread (thread, &id)) - { - good = id; - } - } - } - } - else - { - NeedDbgHelp = true; - } - return good ? file : INVALID_HANDLE_VALUE; + static CrashReporter reporter(reports_directory, uploader_executable); } -//========================================================================== -// -// WriteMiniDumpInAnotherThread -// -// When a stack overflow occurs, there isn't enough room left on the stack -// for MiniDumpWriteDump to do its thing, so we create a new thread with -// a new stack to do the work. -// -//========================================================================== - -static DWORD WINAPI WriteMiniDumpInAnotherThread (LPVOID lpParam) +void CrashReporterHookThread() { - MiniDumpThreadData *dumpdata = (MiniDumpThreadData *)lpParam; - return dumpdata->pMiniDumpWriteDump (DbgProcess, DbgProcessID, - dumpdata->File, MiniDumpNormal, dumpdata->Exceptor, NULL, NULL); + CrashReporter::hook_thread(); } -//========================================================================== -// -// Writef -// -// Like printf, but for Win32 file HANDLEs. -// -//========================================================================== - -void Writef (HANDLE file, const char *format, ...) +void InvokeCrashReporter() { - char buffer[1024]; - va_list args; - DWORD len; - - va_start (args, format); - len = myvsnprintf (buffer, sizeof buffer, format, args); - va_end (args); - WriteFile (file, buffer, len, &len, NULL); + CrashReporter::invoke(); } -//========================================================================== -// -// WriteLogFileStreamer -// -// The callback function to stream a Rich Edit's contents to a file. -// -//========================================================================== +#ifdef _MSC_VER +#pragma warning(disable: 4535) // warning C4535: calling _set_se_translator() requires /EHa -//========================================================================== -// -// WriteLogFile -// -// Writes the contents of a Rich Edit control to a file. -// -//========================================================================== +std::wstring CrashReporter::reports_directory; +std::wstring CrashReporter::uploader_exe; +CrashReporter::MiniDumpWriteDumpPointer CrashReporter::func_MiniDumpWriteDump = 0; +std::recursive_mutex CrashReporter::mutex; -HANDLE WriteLogFile() +CrashReporter::CrashReporter(const std::wstring& new_reports_directory, const std::wstring& new_uploader_executable) { - HANDLE file; - - file = CreateTempFile(); - if (file != INVALID_HANDLE_VALUE) - { - auto writeFile = [&](const void* data, uint32_t size, uint32_t& written) -> bool - { - DWORD tmp = 0; - BOOL result = WriteFile(file, data, size, &tmp, nullptr); - written = tmp; - return result == TRUE; - }; - mainwindow.GetLog(writeFile); - } - return file; + reports_directory = new_reports_directory; + if (!reports_directory.empty() && (reports_directory.back() != L'/' && reports_directory.back() != L'\\')) + reports_directory.push_back(L'\\'); + uploader_exe = new_uploader_executable; + load_dbg_help(); + SetUnhandledExceptionFilter(&CrashReporter::on_win32_unhandled_exception); + enforce_filter(true); // Prevent anyone else from changing the unhandled exception filter + hook_thread(); } -//========================================================================== -// -// CreateCrashLog -// -// Creates all the files needed for a crash report. -// -//========================================================================== - -void CreateCrashLog (const char *custominfo, DWORD customsize) +CrashReporter::~CrashReporter() { - // Do not collect information more than once. - if (NumFiles != 0) - { - return; - } - - DbgThreadID = GetCurrentThreadId(); - DbgProcessID = GetCurrentProcessId(); - DbgProcess = GetCurrentProcess(); - - CrashCode = CrashPointers.ExceptionRecord->ExceptionCode; - CrashAddress = CrashPointers.ExceptionRecord->ExceptionAddress; - - AddFile (WriteTextReport(), "report.txt"); - AddFile (WriteMyMiniDump(), "minidump.mdmp"); - - // Copy app-specific information out of the crashing process's memory - // and into a new temporary file. - if (customsize != 0) - { - HANDLE file = CreateTempFile(); - DWORD wrote; - - if (file != INVALID_HANDLE_VALUE) - { - uint8_t buffer[512]; - DWORD left; - - for (;; customsize -= left, custominfo += left) - { - left = customsize > 512 ? 512 : customsize; - if (left == 0) - { - break; - } - if (SafeReadMemory (custominfo, buffer, left)) - { - WriteFile (file, buffer, left, &wrote, NULL); - } - else - { - Writef (file, "Failed reading remaining %lu bytes\r\n", customsize); - break; - } - } - AddFile (file, "local.txt"); - } - } - AddFile (WriteLogFile(), "log.rtf"); - CloseHandle (DbgProcess); } -//========================================================================== -// -// WriteTextReport -// -// This is the classic plain-text report ZDoom has generated since it -// added crash gathering abilities in 2002. -// -//========================================================================== - -HANDLE WriteTextReport () +void CrashReporter::invoke() { - HANDLE file; - - static const struct - { - DWORD Code; const char *Text; - } - exceptions[] = - { - { EXCEPTION_ACCESS_VIOLATION, "Access Violation" }, - { EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "Array Bounds Exceeded" }, - { EXCEPTION_BREAKPOINT, "Breakpoint" }, - { EXCEPTION_DATATYPE_MISALIGNMENT, "Data Type Misalignment" }, - { EXCEPTION_FLT_DENORMAL_OPERAND, "Floating Point Denormal Operand." }, - { EXCEPTION_FLT_DIVIDE_BY_ZERO, "Floating Point Divide By Zero" }, - { EXCEPTION_FLT_INEXACT_RESULT, "Floating Point Inexact Result" }, - { EXCEPTION_FLT_INVALID_OPERATION, "Floating Point Invalid Operation" }, - { EXCEPTION_FLT_OVERFLOW, "Floating Point Overflow" }, - { EXCEPTION_FLT_STACK_CHECK, "Floating Point Stack Check" }, - { EXCEPTION_FLT_UNDERFLOW, "Floating Point Underflow" }, - { EXCEPTION_ILLEGAL_INSTRUCTION, "Illegal Instruction" }, - { EXCEPTION_IN_PAGE_ERROR, "In Page Error" }, - { EXCEPTION_INT_DIVIDE_BY_ZERO, "Integer Divide By Zero" }, - { EXCEPTION_INT_OVERFLOW, "Integer Overflow" }, - { EXCEPTION_INVALID_DISPOSITION, "Invalid Disposition" }, - { EXCEPTION_NONCONTINUABLE_EXCEPTION, "Noncontinuable Exception" }, - { EXCEPTION_PRIV_INSTRUCTION, "Priviledged Instruction" }, - { EXCEPTION_SINGLE_STEP, "Single Step" }, - { EXCEPTION_STACK_OVERFLOW, "Stack Overflow" } - }; - static const char eflagsBits[][2] = - { - { 'C','F' }, // Carry Flag - { 'x','1' }, // Always one - { 'P','F' }, // Parity Flag - { 'x','0' }, // Always zero - { 'A','F' }, // Auxilliary Carry Flag - { 'x','0' }, // Always zero - { 'Z','F' }, // Zero Flag - { 'S','F' }, // Sign Flag - { 'T','F' }, // Trap Flag - { 'I','F' }, // Interrupt Enable Flag - { 'D','F' }, // Direction Flag - { 'O','F' }, // Overflow Flag - { 'x','x' }, // IOPL low bit - { 'x','x' }, // IOPL high bit - { 'N','T' }, // Nested Task - { 'x','0' }, // Always zero - { 'R','F' }, // Resume Flag - { 'V','M' }, // Virtual-8086 Mode - { 'A','C' }, // Alignment Check - { 'V','I' }, // Virtual Interrupt Flag - { 'V','P' } // Virtual Interrupt Pending - }; - - - int i, j; - - file = CreateTempFile (); - if (file == INVALID_HANDLE_VALUE) - { - return file; - } - - OSVERSIONINFO verinfo = { sizeof(verinfo) }; - GetVersionEx (&verinfo); - - for (i = 0; (size_t)i < sizeof(exceptions)/sizeof(exceptions[0]); ++i) - { - if (exceptions[i].Code == CrashPointers.ExceptionRecord->ExceptionCode) - { - break; - } - } - j = mysnprintf (CrashSummary, countof(CrashSummary), "Code: %08lX", CrashPointers.ExceptionRecord->ExceptionCode); - if ((size_t)i < sizeof(exceptions)/sizeof(exceptions[0])) - { - j += mysnprintf (CrashSummary + j, countof(CrashSummary) - j, " (%s", exceptions[i].Text); - if (CrashPointers.ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) - { - // Pre-NT kernels do not seem to provide this information. - if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) - { - j += mysnprintf (CrashSummary + j, countof(CrashSummary) - j, - " - tried to %s address %p", - CrashPointers.ExceptionRecord->ExceptionInformation[0] ? "write" : "read", - (void *)CrashPointers.ExceptionRecord->ExceptionInformation[1]); - } - } - CrashSummary[j++] = ')'; - } - j += mysnprintf (CrashSummary + j, countof(CrashSummary) - j, "\r\nAddress: %p", CrashPointers.ExceptionRecord->ExceptionAddress); - Writef (file, "%s\r\nFlags: %08X\r\n\r\n", CrashSummary, CrashPointers.ExceptionRecord->ExceptionFlags); - - Writef (file, "Windows %s %d.%d Build %d %s\r\n\r\n", - verinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ? "9x" : "NT", - verinfo.dwMajorVersion, verinfo.dwMinorVersion, verinfo.dwBuildNumber, verinfo.szCSDVersion); - - CONTEXT *ctxt = CrashPointers.ContextRecord; - - if (ctxt->ContextFlags & CONTEXT_SEGMENTS) - { - Writef (file, "GS=%04x FS=%04x ES=%04x DS=%04x\r\n", - ctxt->SegGs, ctxt->SegFs, ctxt->SegEs, ctxt->SegDs); - } - - if (ctxt->ContextFlags & CONTEXT_INTEGER) - { -#ifndef _M_X64 - Writef (file, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\r\nESI=%08x EDI=%08x\r\n", - ctxt->Eax, ctxt->Ebx, ctxt->Ecx, ctxt->Edx, ctxt->Esi, ctxt->Edi); -#else - Writef (file, "RAX=%016I64x RBX=%016I64x RCX=%016I64x\r\n" - "RDX=%016I64x RSI=%016I64x RDI=%016I64x\r\n" - "RBP=%016I64x R8=%016I64x R9=%016I64x\r\n" - "R10=%016I64x R11=%016I64x R12=%016I64x\r\n" - "R13=%016I64x R14=%016I64x R15=%016I64x\r\n", - ctxt->Rax, ctxt->Rbx, ctxt->Rcx, ctxt->Rdx, ctxt->Rsi, ctxt->Rdi, ctxt->Rbp, - ctxt->R8, ctxt->R9, ctxt->R10, ctxt->R11, ctxt->R12, ctxt->R13, ctxt->R14, ctxt->R15); -#endif - } - - if (ctxt->ContextFlags & CONTEXT_CONTROL) - { -#ifndef _M_X64 - Writef (file, "EBP=%08x EIP=%08x ESP=%08x CS=%04x SS=%04x\r\nEFlags=%08x\r\n", - ctxt->Ebp, ctxt->Eip, ctxt->Esp, ctxt->SegCs, ctxt->SegSs, ctxt->EFlags); -#else - Writef (file, "RIP=%016I64x RSP=%016I64x\r\nCS=%04x SS=%04x EFlags=%08x\r\n", - ctxt->Rip, ctxt->Rsp, ctxt->SegCs, ctxt->SegSs, ctxt->EFlags); -#endif - - DWORD dw; - - for (i = 0, dw = 1; (size_t)i < sizeof(eflagsBits)/sizeof(eflagsBits[0]); dw <<= 1, ++i) - { - if (eflagsBits[i][0] != 'x') - { - Writef (file, " %c%c%c", eflagsBits[i][0], eflagsBits[i][1], - ctxt->EFlags & dw ? '+' : '-'); - } - } - Writef (file, "\r\n"); - } - - if (ctxt->ContextFlags & CONTEXT_FLOATING_POINT) - { -#ifndef _M_X64 - Writef (file, - "\r\nFPU State:\r\n ControlWord=%04x StatusWord=%04x TagWord=%04x\r\n" - " ErrorOffset=%08x\r\n ErrorSelector=%08x\r\n DataOffset=%08x\r\n DataSelector=%08x\r\n" - // Cr0NpxState was renamed in recent Windows headers so better skip it here. Its meaning is unknown anyway. - //" Cr0NpxState=%08x\r\n" - "\r\n" - , - (uint16_t)ctxt->FloatSave.ControlWord, (uint16_t)ctxt->FloatSave.StatusWord, (uint16_t)ctxt->FloatSave.TagWord, - ctxt->FloatSave.ErrorOffset, ctxt->FloatSave.ErrorSelector, ctxt->FloatSave.DataOffset, - ctxt->FloatSave.DataSelector - //, ctxt->FloatSave.Cr0NpxState - ); - - for (i = 0; i < 8; ++i) - { - DWORD d0, d1; - memcpy(&d0, &ctxt->FloatSave.RegisterArea[20*i+4], sizeof(DWORD)); - memcpy(&d1, &ctxt->FloatSave.RegisterArea[20*i], sizeof(DWORD)); - Writef (file, "MM%d=%08x%08x\r\n", i, d0, d1); - } -#else - for (i = 0; i < 8; ++i) - { - Writef (file, "MM%d=%016I64x\r\n", i, ctxt->Legacy[i].Low); - } - for (i = 0; i < 16; ++i) - { - Writef (file, "XMM%d=%016I64x%016I64x\r\n", i, ctxt->FltSave.XmmRegisters[i].High, ctxt->FltSave.XmmRegisters[i].Low); - } -#endif - } - - AddToolHelp (file); - -#ifdef _M_IX86 - Writef (file, "\r\nBytes near EIP:"); -#else - Writef (file, "\r\nBytes near RIP:"); -#endif - DumpBytes (file, (uint8_t *)CrashPointers.ExceptionRecord->ExceptionAddress-16); - - if (ctxt->ContextFlags & CONTEXT_CONTROL) - { -#ifndef _M_X64 - AddStackInfo (file, (void *)(size_t)CrashPointers.ContextRecord->Esp, - CrashPointers.ExceptionRecord->ExceptionCode, ctxt); -#else - AddStackInfo (file, (void *)CrashPointers.ContextRecord->Rsp, - CrashPointers.ExceptionRecord->ExceptionCode, ctxt); +#ifdef _DEBUG + DebugBreak(); // Bring up the debugger if it is running #endif - } - - return file; + Sleep(1000); // Give any possibly logging functionality a little time before we die + RaiseException(EXCEPTION_NONCONTINUABLE_EXCEPTION, EXCEPTION_NONCONTINUABLE_EXCEPTION, 0, 0); } -//========================================================================== -// -// AddToolHelp -// -// Adds the information supplied by the tool help functions to the text -// report. This includes the list of threads for this process and the -// loaded modules. -// -//========================================================================== - -static void AddToolHelp (HANDLE file) +void CrashReporter::generate_report() { - HMODULE kernel = GetModuleHandleA ("kernel32.dll"); - if (kernel == NULL) - return; - - CREATESNAPSHOT pCreateToolhelp32Snapshot; - THREADWALK pThread32First; - THREADWALK pThread32Next; - MODULEWALK pModule32First; - MODULEWALK pModule32Next; - - pCreateToolhelp32Snapshot = (CREATESNAPSHOT)GetProcAddress (kernel, "CreateToolhelp32Snapshot"); - pThread32First = (THREADWALK)GetProcAddress (kernel, "Thread32First"); - pThread32Next = (THREADWALK)GetProcAddress (kernel, "Thread32Next"); - pModule32First = (MODULEWALK)GetProcAddress (kernel, "Module32FirstW"); - pModule32Next = (MODULEWALK)GetProcAddress (kernel, "Module32NextW"); - - if (!(pCreateToolhelp32Snapshot && pThread32First && pThread32Next && - pModule32First && pModule32Next)) - { - Writef (file, "\r\nTool Help unavailable\r\n"); - return; - } - - HANDLE snapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPMODULE|TH32CS_SNAPTHREAD, 0); - if (snapshot == INVALID_HANDLE_VALUE) - { - Writef (file, "\r\nTool Help snapshot unavailable\r\n"); - return; - } - - THREADENTRY32 thread = { sizeof(thread) }; - - Writef (file, "\r\nRunning threads:\r\n"); - - if (pThread32First (snapshot, &thread)) + __try { - do - { - if (thread.th32OwnerProcessID == DbgProcessID) - { - Writef (file, "%08x", thread.th32ThreadID); - - if (thread.th32ThreadID == DbgThreadID) - { - Writef (file, " at %p*", CrashAddress); - } - Writef (file, "\r\n"); - } - } while (pThread32Next (snapshot, &thread)); + RaiseException(EXCEPTION_BREAKPOINT, EXCEPTION_BREAKPOINT, 0, 0); } - - MODULEENTRY32 module = { sizeof(module) }; - - Writef (file, "\r\nLoaded modules:\r\n"); - - if (pModule32First (snapshot, &module)) + __except (generate_report_filter(GetExceptionCode(), GetExceptionInformation())) { - do - { - auto amod = FString(module.szModule); - Writef (file, "%p - %p %c%s\r\n", - module.modBaseAddr, module.modBaseAddr + module.modBaseSize - 1, - module.modBaseAddr <= CrashPointers.ExceptionRecord->ExceptionAddress && - module.modBaseAddr + module.modBaseSize > CrashPointers.ExceptionRecord->ExceptionAddress - ? '*' : ' ', - amod.GetChars()); - } while (pModule32Next (snapshot, &module)); } - - CloseHandle (snapshot); } -//========================================================================== -// -// AddStackInfo -// -// Writes a stack dump to the text report. -// -//========================================================================== - -static void AddStackInfo (HANDLE file, void *dumpaddress, DWORD code, CONTEXT *ctxt) +void CrashReporter::create_dump(DumpParams* dump_params, bool launch_uploader) { - DWORD *addr = (DWORD *)dumpaddress, *jump; - DWORD *topOfStack = GetTopOfStack (dumpaddress); - uint8_t peekb; -#ifdef _M_IX86 - DWORD peekd; -#else - uint64_t peekq; -#endif - - jump = topOfStack; - if (code == EXCEPTION_STACK_OVERFLOW) - { - // If the stack overflowed, only dump the first and last 16KB of it. - if (topOfStack - addr > 32768/4) - { - jump = addr + 16384/4; - } - } - - StackWalk (file, dumpaddress, topOfStack, jump, ctxt); - - Writef (file, "\r\nStack Contents:\r\n"); - DWORD *scan; - for (scan = addr; scan < topOfStack; scan += 4) - { - int i; - ptrdiff_t max; - - if (scan == jump) - { - scan = topOfStack - 16384/4; - Writef (file, "\r\n . . . Snip . . .\r\n\r\n"); - } - - Writef (file, "%p:", scan); -#ifdef _M_IX86 - if (topOfStack - scan < 4) - { - max = topOfStack - scan; - } - else - { - max = 4; - } + SYSTEMTIME systime; + GetLocalTime(&systime); - for (i = 0; i < max; ++i) - { - if (!SafeReadMemory (&scan[i], &peekd, 4)) - { - break; - } - Writef (file, " %08x", peekd); - } - for (; i < 4; ++i) - { - Writef (file, " "); - } -#else - if ((uint64_t *)topOfStack - (uint64_t *)scan < 2) - { - max = (uint64_t *)topOfStack - (uint64_t *)scan; - } - else - { - max = 2; - } - - for (i = 0; i < max; ++i) - { - if (!SafeReadMemory (&scan[i], &peekq, 8)) - { - break; - } - Writef (file, " %016x", peekq); - } - if (i < 2) - { - Writef (file, " "); - } -#endif - Writef (file, " "); - for (i = 0; i < int(max*sizeof(void*)); ++i) - { - if (!SafeReadMemory ((uint8_t *)scan + i, &peekb, 1)) - { - break; - } - Writef (file, "%c", peekb >= 0x20 && peekb <= 0x7f ? peekb : '\xb7'); - } - Writef (file, "\r\n"); - } -} - -#ifdef _M_IX86 - -//========================================================================== -// -// StackWalk -// Win32 version -// -// Lists a possible call trace for the crashing thread to the text report. -// This is not very specific and just lists any pointers into the -// main executable region, whether they are part of the real trace or not. -// -//========================================================================== - -static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack, DWORD *jump, CONTEXT *ctxt) -{ - DWORD *addr = (DWORD *)dumpaddress; - - uint8_t *pBaseOfImage = (uint8_t *)GetModuleHandle (0); - IMAGE_OPTIONAL_HEADER *pHeader = (IMAGE_OPTIONAL_HEADER *)(pBaseOfImage + - ((IMAGE_DOS_HEADER*)pBaseOfImage)->e_lfanew + - sizeof(IMAGE_NT_SIGNATURE) + sizeof(IMAGE_FILE_HEADER)); - - DWORD_PTR codeStart = (DWORD_PTR)pBaseOfImage + pHeader->BaseOfCode; - DWORD_PTR codeEnd = codeStart + pHeader->SizeOfCode; - - Writef (file, "\r\nPossible call trace:\r\n %08x BOOM", CrashAddress); - for (DWORD *scan = addr; scan < topOfStack; ++scan) + HANDLE file = INVALID_HANDLE_VALUE; + WCHAR minidump_filename[1024]; + int counter; + for (counter = 1; counter < 1000; counter++) { - if (scan == jump) - { - scan = topOfStack - 16384/4; - Writef (file, "\r\n\r\n . . . . Snip . . . .\r\n"); - } - - DWORD_PTR code; - - if (SafeReadMemory (scan, &code, sizeof(code)) && - code >= codeStart && code < codeEnd) - { - static const char regNames[][4] = - { - "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" - }; - - // Check if address is after a call statement. Print what was called if it is. - const uint8_t *bytep = (uint8_t *)code; - uint8_t peekb; - -#define chkbyte(x,m,v) (SafeReadMemory(x, &peekb, 1) && ((peekb & m) == v)) - - if (chkbyte(bytep - 5, 0xFF, 0xE8) || chkbyte(bytep - 5, 0xFF, 0xE9)) - { - DWORD peekd; - if (SafeReadMemory (bytep - 4, &peekd, 4)) - { - DWORD_PTR jumpaddr = peekd + code; - Writef (file, "\r\n %p %s %p", code - 5, - peekb == 0xE9 ? "jmp " : "call", jumpaddr); - if (chkbyte((LPCVOID)jumpaddr, 0xFF, 0xE9) && - SafeReadMemory ((LPCVOID)(jumpaddr + 1), &peekd, 4)) - { - Writef (file," => jmp %p", peekd + jumpaddr + 5); - } - } - else - { - Writef (file, "\r\n %p %s ????????", code - 5, - peekb == 0xE9 ? "jmp " : "call"); - } - } - else if (chkbyte(bytep - 2, 0xFF, 0xFF) && chkbyte(bytep - 1, 0xF7, 0xD0)) - { - Writef (file, "\r\n %p call %s", code - 2, regNames[peekb & 7]); - } - else - { - int i; - - for (i = 2; i < 7; ++i) - { - if (chkbyte(bytep - i, 0xFF, 0xFF) && chkbyte(bytep - i + 1, 070, 020)) - { - break; - } - } - if (i >= 7) - { - Writef (file, "\r\n %08x", code); - } - else - { - int mod, rm, basereg = -1, indexreg = -1; - int scale = 1, offset = 0; - - Writef (file, "\r\n %08x", bytep - i); - bytep -= i - 1; - SafeReadMemory (bytep, &peekb, 1); - mod = peekb >> 6; - rm = peekb & 7; - bytep++; - - if (mod == 0 && rm == 5) - { - mod = 2; - } - else if (rm == 4) - { - int index, base; - - SafeReadMemory (bytep, &peekb, 1); - scale = 1 << (peekb >> 6); - index = (peekb >> 3) & 7; - base = peekb & 7; - bytep++; - - if (index != 4) - { - indexreg = index; - } - if (base != 5) - { - basereg = base; - } - else - { - if (mod == 0) - { - mod = 2; - } - else - { - basereg = 5; - } - } - } - else - { - basereg = rm; - } - - if (mod == 1) - { - signed char miniofs; - SafeReadMemory (bytep++, &miniofs, 1); - offset = miniofs; - } - else - { - SafeReadMemory (bytep, &offset, 4); - bytep += 4; - } - if ((DWORD_PTR)bytep == code) - { - Writef (file, " call [", bytep - i + 1); - if (basereg >= 0) - { - Writef (file, "%s", regNames[basereg]); - } - if (indexreg >= 0) - { - Writef (file, "%s%s", basereg >= 0 ? "+" : "", regNames[indexreg]); - if (scale > 1) - { - Writef (file, "*%d", scale); - } - } - if (offset != 0) - { - if (indexreg < 0 && basereg < 0) - { - Writef (file, "%08x", offset); - } - else - { - char sign; - if (offset < 0) - { - sign = '-'; - offset = -offset; - } - else - { - sign = '+'; - } - Writef (file, "%c0x%x", sign, offset); - } - } - Writef (file, "]"); - } - } - } - } + swprintf_s(minidump_filename, L"%s%04d-%02d-%02d %02d.%02d.%02d (%d).dmp", reports_directory.c_str(), systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, counter); + file = CreateFile(minidump_filename, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + if (file != INVALID_HANDLE_VALUE) + break; } - Writef (file, "\r\n"); -} - -#else - -//========================================================================== -// -// StackWalk -// Win64 version -// -// Walks the stack for the crashing thread and dumps the trace to the text -// report. Unlike the Win32 version, Win64 provides facilities for -// doing a 100% exact walk. -// -// See http://www.nynaeve.net/?p=113 for more information, and -// http://www.nynaeve.net/Code/StackWalk64.cpp in particular. -// -//========================================================================== - -static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack, DWORD *jump, CONTEXT *ctxt) -{ - RTLLOOKUPFUNCTIONENTRY RtlLookupFunctionEntry; - HMODULE kernel; - CONTEXT context; - KNONVOLATILE_CONTEXT_POINTERS nv_context; - PRUNTIME_FUNCTION function; - PVOID handler_data; - ULONG64 establisher_frame; - ULONG64 image_base; - - Writef (file, "\r\nCall trace:\r\n rip=%p <- Here it dies.\r\n", CrashAddress); - - kernel = GetModuleHandleA("kernel32.dll"); - if (kernel == NULL || NULL == (RtlLookupFunctionEntry = - (RTLLOOKUPFUNCTIONENTRY)GetProcAddress(kernel, "RtlLookupFunctionEntry"))) - { - Writef (file, " Unavailable: Could not get address of RtlLookupFunctionEntry\r\n"); + if (file == INVALID_HANDLE_VALUE) return; - } - // Get the caller's context - context = *ctxt; - // This unwind loop intentionally skips the first call frame, as it - // shall correspond to the call to StackTrace64, which we aren't - // interested in. - - for (ULONG frame = 0; ; ++frame) - { - // Try to look up unwind metadata for the current function. - function = RtlLookupFunctionEntry(context.Rip, &image_base, NULL); - memset(&nv_context, 0, sizeof(nv_context)); - if (function == NULL) - { - // If we don't have a RUNTIME_FUNCTION, then we've encountered - // a leaf function. Adjust the stack appropriately. - context.Rip = (ULONG64)(*(PULONG64)context.Rsp); - context.Rsp += 8; - Writef(file, " Leaf function\r\n\r\n"); - } - else - { - // Note that there is not a one-to-one correspondance between - // runtime functions and source functions. One source function - // may be broken into multiple runtime functions. This loop walks - // backward from the current runtime function for however many - // consecutive runtime functions precede it. There is a slight - // chance that this will walk across different source functions. - // (Or maybe not, depending on whether or not the compiler - // guarantees that there will be empty space between functions; - // it looks like VC++ might.) In practice, this seems to work - // quite well for identifying the exact address to search for in - // a map file to determine the function name. - - PRUNTIME_FUNCTION function2 = function; - ULONG64 base = image_base; - - while (function2 != NULL) - { - Writef(file, " Function range: %p -> %p\r\n", - (void *)(base + function2->BeginAddress), - (void *)(base + function2->EndAddress)); - function2 = RtlLookupFunctionEntry(base + function2->BeginAddress - 1, &base, NULL); - } - Writef(file, "\r\n"); - - // Use RtlVirtualUnwind to execute the unwind for us. - RtlVirtualUnwind(0/*UNW_FLAG_NHANDLER*/, image_base, context.Rip, - function, &context, &handler_data, &establisher_frame, - &nv_context); - } - // If we reach a RIP of zero, this means we've walked off the end of - // the call stack and are done. - if (context.Rip == 0) - { - break; - } - - // Display the context. Note that we don't bother showing the XMM - // context, although we have the nonvolatile portion of it. - Writef(file, " FRAME %02d:\r\n rip=%p rsp=%p rbp=%p\r\n", - frame, context.Rip, context.Rsp, context.Rbp); - Writef(file, " r12=%p r13=%p r14=%p\r\n" - " rdi=%p rsi=%p rbx=%p\r\n", - context.R12, context.R13, context.R14, - context.Rdi, context.Rsi, context.Rbx); - - static const char reg_names[16][4] = + MINIDUMP_EXCEPTION_INFORMATION info; + info.ThreadId = dump_params->thread_id; + info.ExceptionPointers = dump_params->exception_pointers; + info.ClientPointers = 0; + MINIDUMP_TYPE type = static_cast( + MiniDumpWithHandleData | + MiniDumpWithProcessThreadData | + MiniDumpWithFullMemoryInfo | + MiniDumpWithThreadInfo); + func_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), file, type, &info, 0, 0); + CloseHandle(file); + + WCHAR log_filename[1024]; + swprintf_s(log_filename, L"%s%04d-%02d-%02d %02d.%02d.%02d (%d).log", reports_directory.c_str(), systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, counter); + + file = CreateFile(log_filename, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (file == INVALID_HANDLE_VALUE) + return; + auto writeFile = [&](const void* data, uint32_t size, uint32_t& written) -> bool { - "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + DWORD tmp = 0; + BOOL result = WriteFile(file, data, size, &tmp, nullptr); + written = tmp; + return result == TRUE; }; + mainwindow.GetLog(writeFile); + CloseHandle(file); - // If we have stack-based register stores, then display them here. - for (int i = 0; i < 16; ++i) - { - if (nv_context.IntegerContext[i]) - { - Writef(file, " -> '%s' saved on stack at %p (=> %p)\r\n", - reg_names[i], nv_context.IntegerContext[i], *nv_context.IntegerContext[i]); - } - } - } -} - -#endif + if (launch_uploader && !uploader_exe.empty()) + { + WCHAR commandline[3 * 1024]; + swprintf_s(commandline, L"modulename -showcrashreport \"%s\" \"%s\"", minidump_filename, log_filename); -//========================================================================== -// -// DumpBytes -// -// Writes the bytes around EIP to the text report. -// -//========================================================================== + STARTUPINFO startup_info = {}; + PROCESS_INFORMATION process_info = {}; + startup_info.cb = sizeof(STARTUPINFO); + if (CreateProcess(uploader_exe.c_str(), commandline, 0, 0, FALSE, CREATE_SUSPENDED, 0, 0, &startup_info, &process_info)) + { + // We need to allow the process to become the foreground window. Otherwise the error dialog while show up behind other apps + AllowSetForegroundWindow(process_info.dwProcessId); + ResumeThread(process_info.hThread); -static void DumpBytes (HANDLE file, uint8_t *address) -{ - char line[68*3], *line_p = line; - DWORD len; - uint8_t peek; + CloseHandle(process_info.hThread); + CloseHandle(process_info.hProcess); - for (int i = 0; i < 16*3; ++i) - { - if ((i & 15) == 0) - { - line_p += mysnprintf (line_p, countof(line) - (line_p - line), "\r\n%p:", address); - } - if (SafeReadMemory (address, &peek, 1)) - { - line_p += mysnprintf (line_p, countof(line) - (line_p - line), " %02x", *address); - } - else - { - line_p += mysnprintf (line_p, countof(line) - (line_p - line), " --"); + Sleep(1000); // Give process one second to show the foreground window before we exit } - address++; } - *line_p++ = '\r'; - *line_p++ = '\n'; - WriteFile (file, line, DWORD(line_p - line), &len, NULL); } -//========================================================================== -// -// CreateTempFile -// -// Creates a new temporary with read/write access. The file will be deleted -// automatically when it is closed. -// -//========================================================================== - -static HANDLE CreateTempFile () +int CrashReporter::generate_report_filter(unsigned int code, struct _EXCEPTION_POINTERS* ep) { - WCHAR temppath[MAX_PATH-13]; - WCHAR tempname[MAX_PATH]; - if (!GetTempPathW (countof(temppath), temppath)) - { - temppath[0] = '.'; - temppath[1] = '\0'; - } - if (!GetTempFileNameW (temppath, L"zdo", 0, tempname)) - { - return INVALID_HANDLE_VALUE; - } - return CreateFileW (tempname, GENERIC_WRITE|GENERIC_READ, 0, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE|FILE_FLAG_SEQUENTIAL_SCAN, - NULL); + DumpParams dump_params; + dump_params.hprocess = GetCurrentProcess(); + dump_params.hthread = GetCurrentThread(); + dump_params.thread_id = GetCurrentThreadId(); + dump_params.exception_pointers = ep; + dump_params.exception_code = code; + create_dump(&dump_params, false); + return EXCEPTION_EXECUTE_HANDLER; } -//========================================================================== -// -// AddFile -// -// Add another file to be written to the tar. -// -//========================================================================== - -static void AddFile (HANDLE file, const char *filename) +void CrashReporter::load_dbg_help() { - if (NumFiles == MAX_FILES || file == INVALID_HANDLE_VALUE) - { + module_dbghlp = LoadLibrary(L"dbghelp.dll"); + if (module_dbghlp == 0) return; - } - TarFiles[NumFiles].File = file; - TarFiles[NumFiles].Filename = filename; - NumFiles++; + func_MiniDumpWriteDump = reinterpret_cast(GetProcAddress(module_dbghlp, "MiniDumpWriteDump")); } -//========================================================================== -// -// CloseTarFiles -// -// Close all files that were previously registerd with AddFile(). They -// must still be open. -// -//========================================================================== - -static void CloseTarFiles () +void CrashReporter::hook_thread() { - for (int i = 0; i < NumFiles; ++i) - { - CloseHandle (TarFiles[i].File); - } - NumFiles = 0; + set_terminate(&CrashReporter::on_terminate); + _set_abort_behavior(0, _CALL_REPORTFAULT | _WRITE_ABORT_MSG); + signal(SIGABRT, &CrashReporter::on_sigabort); + _set_se_translator(&CrashReporter::on_se_unhandled_exception); } -//========================================================================== -// -// WriteBlock -// -// This is a wrapper around WriteFile. If stream is non-NULL, then the data -// is compressed before writing it to the file. outbuf must be 1024 bytes. -// -//========================================================================== - -static DWORD WriteBlock (HANDLE file, LPCVOID buffer, DWORD bytes, z_stream *stream, Bytef *outbuf) +void CrashReporter::on_terminate() { - if (stream == NULL) - { - WriteFile (file, buffer, bytes, &bytes, NULL); - return bytes; - } - else - { - DWORD wrote = 0; - - stream->next_in = (Bytef *)buffer; - stream->avail_in = bytes; - - while (stream->avail_in != 0) - { - if (stream->avail_out == 0) - { - stream->next_out = outbuf; - stream->avail_out = 1024; - wrote += 1024; - WriteFile (file, outbuf, 1024, &bytes, NULL); - } - deflate (stream, Z_NO_FLUSH); - } - return wrote; - } + invoke(); } -//========================================================================== -// -// WriteZip -// -// Writes a .zip/pk3 file. A HANDLE to the file is returned. This file is -// delete-on-close. -// -// The archive contains all the files previously passed to AddFile(). They -// must still be open, because MakeZip() does not open them itself. -// -//========================================================================== - -static HANDLE MakeZip () +void CrashReporter::on_sigabort(int) { - zip::CentralDirectoryEntry central = { ZIP_CENTRALFILE, { 20, 0 }, { 20, 0 }, }; - zip::EndOfCentralDirectory dirend = { ZIP_ENDOFDIR, }; - short dosdate, dostime; - time_t now; - struct tm *nowtm; - int i, numfiles; - HANDLE file; - DWORD len; - uint32_t dirsize; - size_t namelen; - - if (NumFiles == 0) - { - return INVALID_HANDLE_VALUE; - } - - // Open the zip file. - file = CreateTempFile (); - if (file == INVALID_HANDLE_VALUE) - { - return file; - } - - time (&now); - nowtm = localtime (&now); - - if (nowtm == NULL || nowtm->tm_year < 80) - { - dosdate = dostime = 0; - } - else - { - dosdate = (nowtm->tm_year - 80) * 512 + (nowtm->tm_mon + 1) * 32 + nowtm->tm_mday; - dostime = nowtm->tm_hour * 2048 + nowtm->tm_min * 32 + nowtm->tm_sec / 2; - dosdate = LittleShort(dosdate); - dostime = LittleShort(dostime); - } - - // Write out the zip archive, one file at a time - for (i = 0; i < NumFiles; ++i) - { - AddZipFile (file, &TarFiles[i], dosdate, dostime); - } - - // Write the central directory - central.ModTime = dostime; - central.ModDate = dosdate; - - dirend.DirectoryOffset = LittleLong((uint32_t)SetFilePointer (file, 0, NULL, FILE_CURRENT)); - - for (i = 0, numfiles = 0, dirsize = 0; i < NumFiles; ++i) - { - // Skip empty files - if (TarFiles[i].UncompressedSize == 0) - { - continue; - } - numfiles++; - if (TarFiles[i].Deflated) - { - central.Flags = LittleShort((uint16_t)2); - central.Method = LittleShort((uint16_t)8); - } - else - { - central.Flags = 0; - central.Method = 0; - } - namelen = strlen(TarFiles[i].Filename); - central.InternalAttributes = 0; - if (namelen > 4 && stricmp(TarFiles[i].Filename - 4, ".txt") == 0) - { // Bit 0 set indicates this is probably a text file. But do any tools use it? - central.InternalAttributes = LittleShort((uint16_t)1); - } - central.CRC32 = LittleLong(TarFiles[i].CRC32); - central.CompressedSize = LittleLong(TarFiles[i].CompressedSize); - central.UncompressedSize = LittleLong(TarFiles[i].UncompressedSize); - central.NameLength = LittleShort((uint16_t)namelen); - central.LocalHeaderOffset = LittleLong(TarFiles[i].ZipOffset); - WriteFile (file, ¢ral, sizeof(central), &len, NULL); - WriteFile (file, TarFiles[i].Filename, (DWORD)namelen, &len, NULL); - dirsize += DWORD(sizeof(central) + namelen); - } - - // Write the directory terminator - dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort((uint16_t)numfiles); - dirend.DirectorySize = LittleLong(dirsize); - WriteFile (file, &dirend, sizeof(dirend), &len, NULL); - - return file; + invoke(); } -//========================================================================== -// -// AddZipFile -// -// Adds a file to the opened zip. -// -//========================================================================== - -static void AddZipFile (HANDLE ziphandle, TarFile *whichfile, short dosdate, short dostime) +void CrashReporter::on_se_unhandled_exception(unsigned int exception_code, PEXCEPTION_POINTERS exception_pointers) { - zip::LocalFileHeader local = { ZIP_LOCALFILE, }; - Bytef outbuf[1024], inbuf[1024]; - z_stream stream; - DWORD wrote, len, k; - int err; - bool gzip; - - whichfile->UncompressedSize = GetFileSize (whichfile->File, NULL); - whichfile->CompressedSize = 0; - whichfile->ZipOffset = 0; - whichfile->Deflated = false; - - // Skip empty files. - if (whichfile->UncompressedSize == 0) - { - return; - } + // Ignore those bloody breakpoints! + if (exception_code == EXCEPTION_BREAKPOINT) return; - stream.next_in = Z_NULL; - stream.avail_in = 0; - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - err = deflateInit2 (&stream, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, - 8, Z_DEFAULT_STRATEGY); - gzip = err == Z_OK; + DumpParams dump_params; + dump_params.hprocess = GetCurrentProcess(); + dump_params.hthread = GetCurrentThread(); + dump_params.thread_id = GetCurrentThreadId(); + dump_params.exception_pointers = exception_pointers; + dump_params.exception_code = exception_code; - if (gzip) - { - local.Method = LittleShort((uint16_t)8); - whichfile->Deflated = true; - stream.next_out = outbuf; - stream.avail_out = sizeof(outbuf); - } - - // Write out the header and filename. - local.VersionToExtract[0] = 20; - local.Flags = gzip ? LittleShort((uint16_t)2) : 0; - local.ModTime = dostime; - local.ModDate = dosdate; - local.UncompressedSize = LittleLong(whichfile->UncompressedSize); - local.NameLength = LittleShort((uint16_t)strlen(whichfile->Filename)); - - whichfile->ZipOffset = SetFilePointer (ziphandle, 0, NULL, FILE_CURRENT); - WriteFile (ziphandle, &local, sizeof(local), &wrote, NULL); - WriteFile (ziphandle, whichfile->Filename, (DWORD)strlen(whichfile->Filename), &wrote, NULL); - - // Write the file itself and calculate its CRC. - SetFilePointer (whichfile->File, 0, NULL, FILE_BEGIN); - for (k = 0; k < whichfile->UncompressedSize; ) - { - len = whichfile->UncompressedSize - k; - if (len > 1024) - { - len = 1024; - } - k += len; - ReadFile (whichfile->File, &inbuf, len, &len, NULL); - whichfile->CRC32 = crc32 (whichfile->CRC32, inbuf, len); - whichfile->CompressedSize += WriteBlock (ziphandle, inbuf, len, gzip ? &stream : NULL, outbuf); - } + // Ensure we only get a dump of the first thread crashing - let other threads block here. + std::unique_lock mutex_lock(mutex); - // Flush the zlib stream buffer. - if (gzip) - { - for (bool done = false;;) - { - len = sizeof(outbuf) - stream.avail_out; - if (len != 0) - { - whichfile->CompressedSize += len; - WriteFile (ziphandle, outbuf, len, &wrote, NULL); - stream.next_out = outbuf; - stream.avail_out = sizeof(outbuf); - } - if (done) - { - break; - } - err = deflate (&stream, Z_FINISH); - done = stream.avail_out != 0 || err == Z_STREAM_END; - if (err != Z_STREAM_END && err != Z_OK) - { - break; - } - } - deflateEnd (&stream); - } - - // Fill in fields we didn't know when we wrote the local header. - SetFilePointer (ziphandle, whichfile->ZipOffset + 14, NULL, FILE_BEGIN); - k = LittleLong(whichfile->CRC32); - WriteFile (ziphandle, &k, 4, &wrote, NULL); - k = LittleLong(whichfile->CompressedSize); - WriteFile (ziphandle, &k, 4, &wrote, NULL); - - SetFilePointer (ziphandle, 0, NULL, FILE_END); + // Create dump in separate thread: + DWORD threadId; + HANDLE hThread = CreateThread(0, 0, &CrashReporter::create_dump_main, &dump_params, 0, &threadId); + if (hThread != 0) + WaitForSingleObject(hThread, INFINITE); + TerminateProcess(GetCurrentProcess(), 255); } -//========================================================================== -// -// DrawTransparentBitmap -// -// The replacement for TransparentBlt that does not leak memory under -// Windows 98/ME. As seen in the MSKB. -// -//========================================================================== - -void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart, - short yStart, COLORREF cTransparentColor) -{ - BITMAP bm; - COLORREF cColor; - HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave; - HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld; - HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave; - POINT ptSize; - - hdcTemp = CreateCompatibleDC(hdc); - SelectObject(hdcTemp, hBitmap); // Select the bitmap - - GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm); - ptSize.x = bm.bmWidth; // Get width of bitmap - ptSize.y = bm.bmHeight; // Get height of bitmap - DPtoLP(hdcTemp, &ptSize, 1); // Convert from device - - // to logical points - - // Create some DCs to hold temporary data. - hdcBack = CreateCompatibleDC(hdc); - hdcObject = CreateCompatibleDC(hdc); - hdcMem = CreateCompatibleDC(hdc); - hdcSave = CreateCompatibleDC(hdc); - - // Create a bitmap for each DC. DCs are required for a number of - // GDI functions. - - // Monochrome DC - bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL); - - // Monochrome DC - bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL); - - bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y); - bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y); - - // Each DC must select a bitmap object to store pixel data. - bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack); - bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject); - bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem); - bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave); - - // Set proper mapping mode. - SetMapMode(hdcTemp, GetMapMode(hdc)); - - // Save the bitmap sent here, because it will be overwritten. - BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY); - - // Set the background color of the source DC to the color. - // contained in the parts of the bitmap that should be transparent - cColor = SetBkColor(hdcTemp, cTransparentColor); - - // Create the object mask for the bitmap by performing a BitBlt - // from the source bitmap to a monochrome bitmap. - BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, - SRCCOPY); - - // Set the background color of the source DC back to the original - // color. - SetBkColor(hdcTemp, cColor); - - // Create the inverse of the object mask. - BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, - NOTSRCCOPY); - - // Copy the background of the main DC to the destination. - BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, - SRCCOPY); - - // Mask out the places where the bitmap will be placed. - BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND); - - // Mask out the transparent colored pixels on the bitmap. - BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND); - - // XOR the bitmap with the background on the destination DC. - BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT); - - // Copy the destination to the screen. - BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, - SRCCOPY); - - // Place the original bitmap back into the bitmap sent here. - BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY); - - // Delete the memory bitmaps. - DeleteObject(SelectObject(hdcBack, bmBackOld)); - DeleteObject(SelectObject(hdcObject, bmObjectOld)); - DeleteObject(SelectObject(hdcMem, bmMemOld)); - DeleteObject(SelectObject(hdcSave, bmSaveOld)); - - // Delete the memory DCs. - DeleteDC(hdcMem); - DeleteDC(hdcBack); - DeleteDC(hdcObject); - DeleteDC(hdcSave); - DeleteDC(hdcTemp); +LONG CrashReporter::on_win32_unhandled_exception(PEXCEPTION_POINTERS exception_pointers) +{ + DumpParams dump_params; + dump_params.hprocess = GetCurrentProcess(); + dump_params.hthread = GetCurrentThread(); + dump_params.thread_id = GetCurrentThreadId(); + dump_params.exception_pointers = exception_pointers; + dump_params.exception_code = 0; + + // Ensure we only get a dump of the first thread crashing - let other threads block here. + std::unique_lock mutex_lock(mutex); + + // Create minidump in seperate thread: + DWORD threadId; + HANDLE hThread = CreateThread(0, 0, &CrashReporter::create_dump_main, &dump_params, 0, &threadId); + if (hThread != 0) + WaitForSingleObject(hThread, INFINITE); + TerminateProcess(GetCurrentProcess(), 255); + return EXCEPTION_EXECUTE_HANDLER; } -//========================================================================== -// -// TransparentStaticProc -// -// A special window procedure for the static control displaying the dying -// Doom Guy. It draws the bitmap with magenta as transparent. I could have -// made it an owner-draw control instead, but then I wouldn't get any of -// the standard bitmap graphic handling (like automatic sizing). -// -//========================================================================== - -static LRESULT CALLBACK TransparentStaticProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +DWORD WINAPI CrashReporter::create_dump_main(LPVOID thread_parameter) { - RECT rect; - PAINTSTRUCT paint; - HDC dc; - - if (uMsg == WM_PAINT) - { - if (GetUpdateRect (hWnd, &rect, FALSE)) - { - dc = BeginPaint (hWnd, &paint); - if (dc != NULL) - { - HBITMAP bitmap = (HBITMAP)SendMessage (hWnd, STM_GETIMAGE, IMAGE_BITMAP, 0); - if (bitmap != NULL) - { - DrawTransparentBitmap (dc, bitmap, 0, 0, RGB(255,0,255)); - } - EndPaint (hWnd, &paint); - } - } - return 0; - } - return CallWindowProc (StdStaticProc, hWnd, uMsg, wParam, lParam); + create_dump(reinterpret_cast(thread_parameter), true); + TerminateProcess(GetCurrentProcess(), 255); + return 0; } -static HMODULE WinHlp32; - -//========================================================================== -// -// OverviewDlgProc -// -// The DialogProc for the crash overview page. -// -//========================================================================== - -static INT_PTR CALLBACK OverviewDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +bool CrashReporter::enforce_filter(bool bEnforce) { - CHARFORMAT charFormat; - HWND edit; - ENLINK *link; +#if defined(_M_X64) || defined(_M_IX86) + DWORD ErrCode = 0; - switch (message) - { - case WM_INITDIALOG: + HMODULE hLib = GetModuleHandle(L"kernel32.dll"); + if (hLib == 0) { - if (pEnableThemeDialogTexture != NULL) - { - pEnableThemeDialogTexture(hDlg, ETDT_ENABLETAB); - } - - // Setup the header at the top of the page. - edit = GetDlgItem(hDlg, IDC_CRASHHEADER); - SetWindowTextW(edit, WGAMENAME" has encountered a problem and needs to close.\n" - "We are sorry for the inconvenience."); - - // Setup a bold version of the standard dialog font and make the header bold. - charFormat.cbSize = sizeof(charFormat); - SendMessageW(edit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&charFormat); - charFormat.dwEffects = CFE_BOLD; - SendMessageW(edit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&charFormat); - - // Setup the drawing routine for the dying guy's bitmap. - edit = GetDlgItem(hDlg, IDC_DEADGUYVIEWER); - StdStaticProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(edit, GWLP_WNDPROC, (WLONG_PTR)(LONG_PTR)TransparentStaticProc); - - // Fill in all the text just below the heading. - edit = GetDlgItem(hDlg, IDC_PLEASETELLUS); - SendMessageW(edit, EM_AUTOURLDETECT, TRUE, 0); - SetWindowTextW(edit, L"Please tell us about this problem.\n" - "The information will NOT be sent to Microsoft.\n\n" - "An error report has been created that you can submit to help improve " GAMENAME ". " - /*"You can either save it to disk and make a report in the bugs forum at " FORUM_URL ", " - "or you can send it directly without letting other people know about it."*/); - SendMessageW(edit, EM_SETSEL, 0, 81); - SendMessageW(edit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFormat); - SendMessageW(edit, EM_SETEVENTMASK, 0, ENM_LINK); - - // Assign a default invalid file handle to the user's edit control. - edit = GetDlgItem(hDlg, IDC_CRASHINFO); - SetWindowLongPtrW(edit, GWLP_USERDATA, (LONG_PTR)INVALID_HANDLE_VALUE); - - // Fill in the summary text at the bottom of the page. - edit = GetDlgItem(hDlg, IDC_CRASHSUMMARY); - auto wsum = WideString(CrashSummary); - SetWindowTextW(edit, wsum.c_str()); - return TRUE; + ErrCode = GetLastError(); + return false; } - case WM_NOTIFY: - // When the link in the "please tell us" edit control is clicked, open - // the bugs forum in a browser window. ShellExecute is used to do this, - // so the default browser, whatever it may be, will open it. - link = (ENLINK *)lParam; - if (link->nmhdr.idFrom == IDC_PLEASETELLUS && link->nmhdr.code == EN_LINK) - { - if (link->msg == WM_LBUTTONDOWN) - { - //ShellExecuteA (NULL, "open", BUGS_FORUM_URL, NULL, NULL, 0); - SetWindowLongPtrW (hDlg, DWLP_MSGRESULT, 1); - return TRUE; - } - } - return FALSE; - break; + BYTE* pTarget = (BYTE*)GetProcAddress(hLib, "SetUnhandledExceptionFilter"); + if (pTarget == 0) + { + ErrCode = GetLastError(); + return false; } - return FALSE; -} -//========================================================================== -// -// CrashDlgProc -// -// The DialogProc for the main crash dialog. -// -//========================================================================== - -static INT_PTR CALLBACK CrashDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - static WCHAR overview[] = L"Overview"; - static WCHAR details[] = L"Details"; - HWND edit; - TCITEM tcitem; - RECT tabrect, tcrect; - LPNMHDR nmhdr; - - switch (message) + if (IsBadReadPtr(pTarget, sizeof(original_bytes))) { - case WM_INITDIALOG: - // Set up the tab control - tcitem.mask = TCIF_TEXT | TCIF_PARAM; - edit = GetDlgItem (hDlg, IDC_CRASHTAB); - - GetWindowRect (edit, &tcrect); - ScreenToClient (hDlg, (LPPOINT)&tcrect.left); - ScreenToClient (hDlg, (LPPOINT)&tcrect.right); - - // There are two tabs: Overview and Details. Each pane is created from a - // dialog template, and the resultant window is stored as the lParam for - // the corresponding tab. - tcitem.pszText = overview; - tcitem.lParam = (LPARAM)CreateDialogParamW (g_hInst, MAKEINTRESOURCE(IDD_CRASHOVERVIEW), hDlg, OverviewDlgProc, (LPARAM)edit); - TabCtrl_InsertItem (edit, 0, &tcitem); - TabCtrl_GetItemRect (edit, 0, &tabrect); - SetWindowPos ((HWND)tcitem.lParam, HWND_TOP, tcrect.left + 3, tcrect.top + tabrect.bottom + 3, - tcrect.right - tcrect.left - 8, tcrect.bottom - tcrect.top - tabrect.bottom - 8, 0); - - tcitem.pszText = details; - tcitem.lParam = (LPARAM)CreateDialogParamW (g_hInst, MAKEINTRESOURCE(IDD_CRASHDETAILS), hDlg, DetailsDlgProc, (LPARAM)edit); - TabCtrl_InsertItem (edit, 1, &tcitem); - SetWindowPos ((HWND)tcitem.lParam, HWND_TOP, tcrect.left + 3, tcrect.top + tabrect.bottom + 3, - tcrect.right - tcrect.left - 8, tcrect.bottom - tcrect.top - tabrect.bottom - 8, 0); - break; - - case WM_NOTIFY: - nmhdr = (LPNMHDR)lParam; - if (nmhdr->idFrom == IDC_CRASHTAB) - { - int i = TabCtrl_GetCurSel (nmhdr->hwndFrom); - tcitem.mask = TCIF_PARAM; - TabCtrl_GetItem (nmhdr->hwndFrom, i, &tcitem); - edit = (HWND)tcitem.lParam; - - // TCN_SELCHANGING is sent just before the selected tab changes. - // TCN_SELCHANGE is sent just after the selected tab changes. - // So, when TCN_SELCHANGING is received hide the pane for the - // selected tab, and when TCN_SELCHANGE is received, show the pane - // for the selected tab. - if (nmhdr->code == TCN_SELCHANGING) - { - ShowWindow (edit, SW_HIDE); - SetWindowLongPtr (hDlg, DWLP_MSGRESULT, FALSE); - return TRUE; - } - else if (nmhdr->code == TCN_SELCHANGE) - { - ShowWindow (edit, SW_SHOW); - return TRUE; - } - else - { - return FALSE; - } - } - break; - - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED) - { - EndDialog (hDlg, LOWORD(wParam)); - } - break; + return false; } - return FALSE; -} - -//========================================================================== -// -// DetailsDlgProc -// -// The dialog procedure for when the user wants to examine the files -// in the report. -// -//========================================================================== -static INT_PTR CALLBACK DetailsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - HWND ctrl; - int i, j; - - switch (message) + if (bEnforce) { - case WM_INITDIALOG: - if (pEnableThemeDialogTexture != NULL) - { - pEnableThemeDialogTexture (hDlg, ETDT_ENABLETAB); - } - - // Set up the file contents display: No undos. The control's - // userdata stores the index of the file currently displayed. - ctrl = GetDlgItem (hDlg, IDC_CRASHFILECONTENTS); - SendMessageW (ctrl, EM_SETUNDOLIMIT, 0, 0); - SetWindowLongPtrW (ctrl, GWLP_USERDATA, -1); - SetEditControl (ctrl, GetDlgItem(hDlg, IDC_CRASHFILESIZE), 0); - SendMessageW (ctrl, LB_SETCURSEL, 0, 0); - break; - - case WM_SHOWWINDOW: - // When showing this pane, refresh the list of packaged files, and - // update the contents display as necessary. - if (wParam == TRUE) - { - ctrl = GetDlgItem (hDlg, IDC_CRASHFILES); - j = (int)SendMessageW (ctrl, LB_GETCURSEL, 0, 0); - SendMessageW (ctrl, LB_RESETCONTENT, 0, 0); - for (i = 0; i < NumFiles; ++i) - { - SendMessageA (ctrl, LB_ADDSTRING, 0, (LPARAM)TarFiles[i].Filename); - } - if (j == LB_ERR || j >= i) j = 0; - SendMessageW (ctrl, LB_SETCURSEL, j, 0); - - ctrl = GetDlgItem (hDlg, IDC_CRASHFILECONTENTS); - if (j > 2) SetWindowLongPtr (ctrl, GWLP_USERDATA, -1); - SetEditControl (ctrl, GetDlgItem(hDlg, IDC_CRASHFILESIZE), j); - } - break; + // Save the original contents of SetUnhandledExceptionFilter + memcpy(original_bytes, pTarget, sizeof(original_bytes)); - case WM_COMMAND: - // Selecting a different file makes the contents display update. - if (HIWORD(wParam) == LBN_SELCHANGE) - { - i = (int)SendMessage ((HWND)lParam, LB_GETCURSEL, 0, 0); - if (i != LB_ERR) - { - // Update the contents control for this file - SetEditControl (GetDlgItem (hDlg, IDC_CRASHFILECONTENTS), - GetDlgItem (hDlg, IDC_CRASHFILESIZE), i); - } - } - break; + // Patch SetUnhandledExceptionFilter + if (!write_memory(pTarget, patch_bytes, sizeof(patch_bytes))) + return false; } - return FALSE; -} - -//========================================================================== -// -// StreamEditText -// -// The callback function to stream a text file into a rich edit control. -// -//========================================================================== - -static DWORD CALLBACK StreamEditText (DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG *pcb) -{ - DWORD wrote; - ReadFile ((HANDLE)cookie, buffer, cb, &wrote, NULL); - *pcb = wrote; - return wrote == 0; -} - -//========================================================================== -// -// StreamEditBinary -// -// The callback function to stream a binary file into a rich edit control. -// The binary file is converted to a RTF hex dump so that the different -// columns can be color-coded. -// -//========================================================================== - -struct BinStreamInfo -{ - int Stage; - HANDLE File; - DWORD Pointer; -}; - -static DWORD CALLBACK StreamEditBinary (DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG *pcb) -{ - BinStreamInfo *info = (BinStreamInfo *)cookie; - uint8_t buf16[16]; - DWORD read, i; - char *buff_p = (char *)buffer; - char *buff_end = (char *)buffer + cb; - -repeat: - switch (info->Stage) + else { - case 0: // Write prologue - buff_p += mysnprintf (buff_p, buff_end - buff_p, "{\\rtf1\\ansi\\deff0" - "{\\colortbl ;\\red0\\green0\\blue80;\\red0\\green0\\blue0;\\red80\\green0\\blue80;}" - "\\viewkind4\\pard"); - info->Stage++; - break; - - case 1: // Write body - while (cb - ((LPBYTE)buff_p - buffer) > 150) - { - ReadFile (info->File, buf16, 16, &read, NULL); - if (read == 0 || info->Pointer >= 65536) - { - info->Stage = read == 0 ? 2 : 3; - goto repeat; - } - char *linestart = buff_p; - buff_p += mysnprintf (buff_p, buff_end - buff_p, "\\cf1 %08lx:\\cf2 ", info->Pointer); - info->Pointer += read; - - for (i = 0; i < read;) - { - if (i <= read - 4) - { - DWORD d; - memcpy(&d, &buf16[i], sizeof(d)); - buff_p += mysnprintf (buff_p, buff_end - buff_p, " %08lx", d); - i += 4; - } - else - { - buff_p += mysnprintf (buff_p, buff_end - buff_p, " %02x", buf16[i]); - i += 1; - } - } - while (buff_p - linestart < 57) - { - *buff_p++ = ' '; - } - buff_p += mysnprintf (buff_p, buff_end - buff_p, "\\cf3 "); - for (i = 0; i < read; ++i) - { - uint8_t code = buf16[i]; - if (code < 0x20 || code > 0x7f) code = 0xB7; - if (code == '\\' || code == '{' || code == '}') *buff_p++ = '\\'; - *buff_p++ = code; - } - buff_p += mysnprintf (buff_p, buff_end - buff_p, "\\par\r\n"); - } - break; - - case 2: // Write epilogue - buff_p += mysnprintf (buff_p, buff_end - buff_p, "\\cf0 }"); - info->Stage = 4; - break; - - case 3: // Write epilogue for truncated file - buff_p += mysnprintf (buff_p, buff_end - buff_p, "--- Rest of file truncated ---\\cf0 }"); - info->Stage = 4; - break; - - case 4: // We're done - return TRUE; + // Restore the original behavior of SetUnhandledExceptionFilter + if (!write_memory(pTarget, original_bytes, sizeof(original_bytes))) + return false; } +#endif - *pcb = (LONG)((LPBYTE)buff_p - buffer); - return FALSE; + return true; } -//========================================================================== -// -// SetEditControl -// -// Fills the edit control with the contents of the chosen file. -// If the filename ends with ".txt" the file is assumed to be text. -// Otherwise it is treated as binary, and you get a hex dump. -// -//========================================================================== - -static void SetEditControl (HWND edit, HWND sizedisplay, int filenum) +bool CrashReporter::write_memory(BYTE* pTarget, const BYTE* pSource, DWORD Size) { - char sizebuf[32]; - EDITSTREAM stream; - DWORD size; - POINT pt = { 0, 0 }; - const char *rtf = NULL; - HGDIOBJ font; - - // Don't refresh the control if it's already showing the file we want. - if (GetWindowLongPtr (edit, GWLP_USERDATA) == filenum) - { - return; - } + DWORD ErrCode = 0; - size = GetFileSize (TarFiles[filenum].File, NULL); - if (size < 1024) - { - mysnprintf (sizebuf, countof(sizebuf), "(%lu bytes)", size); - } - else - { - mysnprintf (sizebuf, countof(sizebuf), "(%lu KB)", size/1024); - } - SetWindowTextA (sizedisplay, sizebuf); + if (pTarget == 0) + return false; + if (pSource == 0) + return false; + if (Size == 0) + return false; + if (IsBadReadPtr(pSource, Size)) + return false; - SetWindowLongPtr (edit, GWLP_USERDATA, filenum); + // Modify protection attributes of the target memory page - SetFilePointer (TarFiles[filenum].File, 0, NULL, FILE_BEGIN); - SendMessage (edit, EM_SETSCROLLPOS, 0, (LPARAM)&pt); + DWORD OldProtect = 0; - // Set the font now, in case log.rtf was previously viewed, because - // that file changes it. - font = GetStockObject (ANSI_FIXED_FONT); - if (font != INVALID_HANDLE_VALUE) + if (!VirtualProtect(pTarget, Size, PAGE_EXECUTE_READWRITE, &OldProtect)) { - SendMessage (edit, WM_SETFONT, (WPARAM)font, FALSE); + ErrCode = GetLastError(); + return false; } - // Text files are streamed in as-is. - // Binary files are streamed in as color-coded hex dumps. - stream.dwError = 0; - if (strstr (TarFiles[filenum].Filename, ".txt") != NULL || - (rtf = strstr (TarFiles[filenum].Filename, ".rtf")) != NULL) - { - CHARFORMAT beBlack; - - beBlack.cbSize = sizeof(beBlack); - beBlack.dwMask = CFM_COLOR; - beBlack.dwEffects = 0; - beBlack.crTextColor = RGB(0,0,0); - SendMessage (edit, EM_SETCHARFORMAT, 0, (LPARAM)&beBlack); - stream.dwCookie = (DWORD_PTR)TarFiles[filenum].File; - stream.pfnCallback = StreamEditText; - SendMessage (edit, EM_STREAMIN, rtf ? SF_RTF : SF_TEXT | SF_USECODEPAGE | (1252 << 16), (LPARAM)&stream); - } - else - { - BinStreamInfo info = { 0, TarFiles[filenum].File, 0 }; - stream.dwCookie = (DWORD_PTR)&info; - stream.pfnCallback = StreamEditBinary; - SendMessage (edit, EM_EXLIMITTEXT, 0, GetFileSize(TarFiles[filenum].File, NULL)*7); - SendMessage (edit, EM_STREAMIN, SF_RTF, (LPARAM)&stream); - } - SendMessage (edit, EM_SETSEL, (WPARAM)-1, 0); -} + // Write memory -//========================================================================== -// -// SaveReport -// -// Makes a permanent copy of the report tarball. -// -//========================================================================== + memcpy(pTarget, pSource, Size); -static void SaveReport (HANDLE file) -{ - OPENFILENAME ofn = { -#ifdef OPENFILENAME_SIZE_VERSION_400 - OPENFILENAME_SIZE_VERSION_400 -#else - sizeof(ofn) -#endif - , }; - WCHAR filename[256]; + // Restore memory protection attributes of the target memory page - ofn.lpstrFilter = L"Zip file (*.zip)\0*.zip\0"; - wcscpy (filename, L"CrashReport.zip"); - ofn.lpstrFile = filename; - ofn.nMaxFile = countof(filename); + DWORD Temp = 0; - while (GetSaveFileNameW (&ofn)) + if (!VirtualProtect(pTarget, Size, OldProtect, &Temp)) { - HANDLE ofile = CreateFileW (ofn.lpstrFile, GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - if (ofile == INVALID_HANDLE_VALUE) - { - if (MessageBoxA (NULL, "Could not open the crash report file", - "Save As failed", MB_RETRYCANCEL) == IDRETRY) - { - continue; - } - return; - } - else - { - DWORD fileLen = GetFileSize (file, NULL), fileLeft; - char xferbuf[1024]; - - SetFilePointer (file, 0, NULL, FILE_BEGIN); - fileLeft = fileLen; - while (fileLeft != 0) - { - DWORD grab = fileLeft > sizeof(xferbuf) ? sizeof(xferbuf) : fileLeft; - DWORD didread; - - ReadFile (file, xferbuf, grab, &didread, NULL); - WriteFile (ofile, xferbuf, didread, &grab, NULL); - fileLeft -= didread; - } - CloseHandle (ofile); - return; - } + ErrCode = GetLastError(); + return false; } -} - -//========================================================================== -// -// DisplayCrashLog -// -// Displays the crash information and possibly submits it. CreateCrashLog() -// must have been called previously. -// -//========================================================================== -void DisplayCrashLog () -{ - HANDLE file; + // Success + return true; +} - if (NumFiles == 0) - { - char ohPoo[] = - GAMENAME" crashed but was unable to produce\n" - "detailed information about the crash.\n" - "\nThis is all that is available:\n\nCode=XXXXXXXX\nAddr=XXXXXXXX"; - mysnprintf (ohPoo + countof(ohPoo) - 23, 23, "%08lX\nAddr=%p", CrashCode, CrashAddress); - MessageBoxA (NULL, ohPoo, GAMENAME" Very Fatal Error", MB_OK|MB_ICONSTOP); - if (WinHlp32 != NULL) - { - FreeLibrary (WinHlp32); - } - } - else - { - HMODULE uxtheme = LoadLibraryA ("uxtheme.dll"); - if (uxtheme != NULL) - { - pEnableThemeDialogTexture = (HRESULT (__stdcall *)(HWND,DWORD))GetProcAddress (uxtheme, "EnableThemeDialogTexture"); - } - INT_PTR result = DialogBox (g_hInst, MAKEINTRESOURCE(IDD_CRASHDIALOG), NULL, (DLGPROC)CrashDlgProc); +#if defined(_M_X64) +const BYTE CrashReporter::patch_bytes[6] = { 0x48, 0x31, 0xC0, 0xC2, 0x00, 0x00 }; +#elif defined(_M_IX86) +const BYTE CrashReporter::patch_bytes[5] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 }; +#endif - if (result == IDC_SAVEREPORT) - { - file = MakeZip (); - SaveReport (file); - CloseHandle (file); - } - if (uxtheme != NULL) - { - FreeLibrary (uxtheme); - } - } - CloseTarFiles (); -} +#endif diff --git a/src/common/platform/win32/i_crash_arm.cpp b/src/common/platform/win32/i_crash_arm.cpp deleted file mode 100644 index 2a61ab42c5..0000000000 --- a/src/common/platform/win32/i_crash_arm.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Licensed to the Public Domain by Rachael Alexandersion (c) 2021 -// This file is nothing more than a stub. Please replace with a proper copyright notice if this function is implemented for ARM. Or just use the regular i_crash.cpp - -void DisplayCrashLog() -{ - // stub -} diff --git a/src/common/platform/win32/i_dijoy.cpp b/src/common/platform/win32/i_dijoy.cpp index 11f60a35f4..492cbda148 100644 --- a/src/common/platform/win32/i_dijoy.cpp +++ b/src/common/platform/win32/i_dijoy.cpp @@ -180,6 +180,9 @@ class FDInputJoystick : public FInputDevice, IJoystickConfig bool IsAxisMapDefault(int axis); bool IsAxisScaleDefault(int axis); + bool GetEnabled(); + void SetEnabled(bool enabled); + void SetDefaultConfig(); FString GetIdentifier(); @@ -219,6 +222,8 @@ class FDInputJoystick : public FInputDevice, IJoystickConfig DIOBJECTDATAFORMAT *Objects; DIDATAFORMAT DataFormat; + bool Enabled; + static BOOL CALLBACK EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef); void OrderAxes(); bool ReorderAxisPair(const GUID &x, const GUID &y, int pos); @@ -297,6 +302,7 @@ FDInputJoystick::FDInputJoystick(const GUID *instance, FString &name) Instance = *instance; Name = name; Marked = false; + Enabled = true; } //=========================================================================== @@ -410,12 +416,13 @@ void FDInputJoystick::ProcessInput() { hr = Device->Acquire(); } - if (FAILED(hr)) + if (FAILED(hr) || !Enabled) { return; } - state = (uint8_t *)alloca(DataFormat.dwDataSize); + TArray statearr(DataFormat.dwDataSize, true); + state = statearr.data(); hr = Device->GetDeviceState(DataFormat.dwDataSize, state); if (FAILED(hr)) return; @@ -892,7 +899,7 @@ const char *FDInputJoystick::GetAxisName(int axis) { if (unsigned(axis) < Axes.Size()) { - return Axes[axis].Name; + return Axes[axis].Name.GetChars(); } return "Invalid"; } @@ -984,6 +991,28 @@ bool FDInputJoystick::IsAxisScaleDefault(int axis) return true; } +//=========================================================================== +// +// FDInputJoystick :: GetEnabled +// +//=========================================================================== + +bool FDInputJoystick::GetEnabled() +{ + return Enabled; +} + +//=========================================================================== +// +// FDInputJoystick :: SetEnabled +// +//=========================================================================== + +void FDInputJoystick::SetEnabled(bool enabled) +{ + Enabled = enabled; +} + //=========================================================================== // // FDInputJoystick :: IsAxisMapDefault diff --git a/src/common/platform/win32/i_input.cpp b/src/common/platform/win32/i_input.cpp index 05988060fd..cb945d61e1 100644 --- a/src/common/platform/win32/i_input.cpp +++ b/src/common/platform/win32/i_input.cpp @@ -110,6 +110,8 @@ EXTERN_CVAR (Bool, use_mouse) static int WheelDelta; extern bool CursorState; +void SetCursorState(bool visible); + extern BOOL paused; static bool noidle = false; @@ -334,7 +336,8 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (!GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)) && size != 0) { - uint8_t *buffer = (uint8_t *)alloca(size); + TArray array(size, true); + uint8_t *buffer = array.data(); if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER)) == size) { int code = GET_RAWINPUT_CODE_WPARAM(wParam); @@ -414,7 +417,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_SETCURSOR: if (!CursorState) { - SetCursor(NULL); // turn off window cursor + SetCursorState(false); // turn off window cursor return TRUE; // Prevent Windows from setting cursor to window class cursor } else @@ -491,7 +494,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_ERASEBKGND: - return true; + return DefWindowProc(hWnd, message, wParam, lParam); case WM_DEVICECHANGE: if (wParam == DBT_DEVNODES_CHANGED || @@ -691,12 +694,15 @@ void I_PutInClipboard (const char *str) auto wstr = WideString(str); HGLOBAL cliphandle = GlobalAlloc (GMEM_DDESHARE, wstr.length() * 2 + 2); - if (cliphandle != NULL) + if (cliphandle != nullptr) { wchar_t *ptr = (wchar_t *)GlobalLock (cliphandle); - wcscpy (ptr, wstr.c_str()); - GlobalUnlock (cliphandle); - SetClipboardData (CF_UNICODETEXT, cliphandle); + if (ptr) + { + wcscpy(ptr, wstr.c_str()); + GlobalUnlock(cliphandle); + SetClipboardData(CF_UNICODETEXT, cliphandle); + } } CloseClipboard (); } diff --git a/src/common/platform/win32/i_input.h b/src/common/platform/win32/i_input.h index 643cc65b3c..16a276ce83 100644 --- a/src/common/platform/win32/i_input.h +++ b/src/common/platform/win32/i_input.h @@ -115,7 +115,7 @@ class FKeyboard : public FInputDevice void PostKeyEvent(int keynum, INTBOOL down, bool foreground); }; -class NOVTABLE FJoystickCollection : public FInputDevice +class FJoystickCollection : public FInputDevice { public: virtual void AddAxes(float axes[NUM_JOYAXIS]) = 0; diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index c28a3ff4bd..200cd541b9 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -32,14 +32,13 @@ ** */ -// HEADER FILES ------------------------------------------------------------ - #define WIN32_LEAN_AND_MEAN #include #include #include #include -#include +#include +#include #include #include @@ -80,8 +79,6 @@ #include "i_mainwindow.h" -// MACROS ------------------------------------------------------------------ - // The main window's title. #ifdef _M_X64 #define X64 " 64-bit" @@ -91,55 +88,25 @@ #define X64 "" #endif -// TYPES ------------------------------------------------------------------- +void InitCrashReporter(const std::wstring& reports_directory, const std::wstring& uploader_executable); +FString GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create); -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); -void CreateCrashLog (const char *custominfo, DWORD customsize); -void DisplayCrashLog (); void DestroyCustomCursor(); int GameMain(); -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -extern EXCEPTION_POINTERS CrashPointers; extern UINT TimerPeriod; -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - // The command line arguments. FArgs *Args; HINSTANCE g_hInst; -HANDLE MainThread; -DWORD MainThreadID; HANDLE StdOut; bool FancyStdOut, AttachedStdOut; -// CODE -------------------------------------------------------------------- - - -//========================================================================== -// -// I_SetIWADInfo -// -//========================================================================== - void I_SetIWADInfo() { - // Make the startup banner show itself - mainwindow.UpdateLayout(); } -//========================================================================== -// -// DoMain -// //========================================================================== int DoMain (HINSTANCE hInstance) @@ -169,7 +136,7 @@ int DoMain (HINSTANCE hInstance) // handle instead of creating a console window. StdOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (StdOut != NULL) + if (StdOut != nullptr) { // It seems that running from a shell always creates a std output // for us, even if it doesn't go anywhere. (Running from Explorer @@ -179,7 +146,7 @@ int DoMain (HINSTANCE hInstance) BY_HANDLE_FILE_INFORMATION info; if (!GetFileInformationByHandle(StdOut, &info)) { - StdOut = NULL; + StdOut = nullptr; } } if (StdOut == nullptr) @@ -187,7 +154,7 @@ int DoMain (HINSTANCE hInstance) if (AttachConsole(ATTACH_PARENT_PROCESS)) { StdOut = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD foo; WriteFile(StdOut, "\n", 1, &foo, NULL); + DWORD foo; WriteFile(StdOut, "\n", 1, &foo, nullptr); AttachedStdOut = true; } if (StdOut == nullptr && AllocConsole()) @@ -219,7 +186,7 @@ int DoMain (HINSTANCE hInstance) // Figure out what directory the program resides in. WCHAR progbuff[1024]; - if (GetModuleFileNameW(nullptr, progbuff, sizeof progbuff) == 0) + if (GetModuleFileNameW(nullptr, progbuff, 1024) == 0) { MessageBoxA(nullptr, "Fatal", "Could not determine program location.", MB_ICONEXCLAMATION|MB_OK); exit(-1); @@ -244,7 +211,7 @@ int DoMain (HINSTANCE hInstance) // element. DEVMODE is not one of those structures. memset (&displaysettings, 0, sizeof(displaysettings)); displaysettings.dmSize = sizeof(displaysettings); - EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings); + EnumDisplaySettings (nullptr, ENUM_CURRENT_SETTINGS, &displaysettings); x = (displaysettings.dmPelsWidth - width) / 2; y = (displaysettings.dmPelsHeight - height) / 2; @@ -262,11 +229,18 @@ int DoMain (HINSTANCE hInstance) WinWidth = cRect.right; WinHeight = cRect.bottom; - CoInitialize (NULL); - atexit ([](){ CoUninitialize(); }); // beware of calling convention. + if (SUCCEEDED(CoInitialize(nullptr))) + atexit ([](){ CoUninitialize(); }); // beware of calling convention. int ret = GameMain (); - mainwindow.CheckForRestart(); + + if (mainwindow.CheckForRestart()) + { + HMODULE hModule = GetModuleHandleW(nullptr); + WCHAR path[MAX_PATH]; + GetModuleFileNameW(hModule, path, MAX_PATH); + ShellExecuteW(nullptr, L"open", path, GetCommandLineW(), nullptr, SW_SHOWNORMAL); + } DestroyCustomCursor(); if (ret == 1337) // special exit code for 'norun'. @@ -279,12 +253,12 @@ int DoMain (HINSTANCE hInstance) HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE); ShowWindow(mainwindow.GetHandle(), SW_HIDE); - WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL); + if (StdOut != nullptr) WriteFile(StdOut, "Press any key to exit...", 24, &bytes, nullptr); FlushConsoleInputBuffer(stdinput); SetConsoleMode(stdinput, 0); - ReadConsole(stdinput, &bytes, 1, &bytes, NULL); + ReadConsole(stdinput, &bytes, 1, &bytes, nullptr); } - else if (StdOut == NULL) + else if (StdOut == nullptr) { mainwindow.ShowErrorPane(nullptr); } @@ -314,231 +288,13 @@ void I_ShowFatalError(const char *msg) } } -// Here is how the error logging system works. -// -// To catch exceptions that occur in secondary threads, CatchAllExceptions is -// set as the UnhandledExceptionFilter for this process. It records the state -// of the thread at the time of the crash using CreateCrashLog and then queues -// an APC on the primary thread. When the APC executes, it raises a software -// exception that gets caught by the __try/__except block in WinMain. -// I_GetEvent calls SleepEx to put the primary thread in a waitable state -// periodically so that the APC has a chance to execute. -// -// Exceptions on the primary thread are caught by the __try/__except block in -// WinMain. Not only does it record the crash information, it also shuts -// everything down and displays a dialog with the information present. If a -// console log is being produced, the information will also be appended to it. -// -// If a debugger is running, CatchAllExceptions never executes, so secondary -// thread exceptions will always be caught by the debugger. For the primary -// thread, IsDebuggerPresent is called to determine if a debugger is present. -// Note that this function is not present on Windows 95, so we cannot -// statically link to it. -// -// To make this work with MinGW, you will need to use inline assembly -// because GCC offers no native support for Windows' SEH. - -//========================================================================== -// -// SleepForever -// -//========================================================================== - -void SleepForever () -{ - Sleep (INFINITE); -} - -//========================================================================== -// -// ExitMessedUp -// -// An exception occurred while exiting, so don't do any standard processing. -// Just die. -// -//========================================================================== - -LONG WINAPI ExitMessedUp (LPEXCEPTION_POINTERS foo) -{ - ExitProcess (1000); -} - -//========================================================================== -// -// ExitFatally -// -//========================================================================== - -void CALLBACK ExitFatally (ULONG_PTR dummy) -{ - SetUnhandledExceptionFilter (ExitMessedUp); - I_ShutdownGraphics (); - mainwindow.RestoreConView (); - DisplayCrashLog (); - exit(-1); -} - -#ifndef _M_ARM64 -//========================================================================== -// -// CatchAllExceptions -// -//========================================================================== - -namespace -{ - CONTEXT MainThreadContext; -} - -LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) -{ -#ifdef _DEBUG - if (info->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) - { - return EXCEPTION_CONTINUE_SEARCH; - } -#endif - - static bool caughtsomething = false; - - if (caughtsomething) return EXCEPTION_EXECUTE_HANDLER; - caughtsomething = true; - - char *custominfo = (char *)HeapAlloc (GetProcessHeap(), 0, 16384); - - CrashPointers = *info; - if (sysCallbacks.CrashInfo && custominfo) sysCallbacks.CrashInfo(custominfo, 16384, "\r\n"); - CreateCrashLog (custominfo, (DWORD)strlen(custominfo)); - - // If the main thread crashed, then make it clean up after itself. - // Otherwise, put the crashing thread to sleep and signal the main thread to clean up. - if (GetCurrentThreadId() == MainThreadID) - { -#ifdef _M_X64 - *info->ContextRecord = MainThreadContext; -#else - info->ContextRecord->Eip = (DWORD_PTR)ExitFatally; -#endif // _M_X64 - } - else - { -#ifndef _M_X64 - info->ContextRecord->Eip = (DWORD_PTR)SleepForever; -#else - info->ContextRecord->Rip = (DWORD_PTR)SleepForever; -#endif - QueueUserAPC (ExitFatally, MainThread, 0); - } - return EXCEPTION_CONTINUE_EXECUTION; -} -#else // !_M_ARM64 -// stub this function for ARM64 -LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) -{ - return EXCEPTION_CONTINUE_EXECUTION; -} -#endif // !_M_ARM64 - -//========================================================================== -// -// infiniterecursion -// -// Debugging routine for testing the crash logger. -// -//========================================================================== - -#ifdef _DEBUG -static void infiniterecursion(int foo) -{ - if (foo) - { - infiniterecursion(foo); - } -} -#endif - -// Setting this to 'true' allows getting the standard notification for a crash -// which offers the very important feature to open a debugger and see the crash in context right away. -CUSTOM_CVAR(Bool, disablecrashlog, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - SetUnhandledExceptionFilter(!*self ? CatchAllExceptions : nullptr); -} - -//========================================================================== -// -// WinMain -// //========================================================================== -int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int nCmdShow) +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int nCmdShow) { g_hInst = hInstance; - InitCommonControls (); // Load some needed controls and be pretty under XP - - // We need to load riched20.dll so that we can create the control. - if (NULL == LoadLibraryA ("riched20.dll")) - { - // This should only happen on basic Windows 95 installations, but since we - // don't support Windows 95, we have no obligation to provide assistance in - // getting it installed. - MessageBoxA(NULL, "Could not load riched20.dll", GAMENAME " Error", MB_OK | MB_ICONSTOP); - return 0; - } - -#if !defined(__GNUC__) && defined(_DEBUG) - if (__argc == 2 && __wargv != nullptr && wcscmp (__wargv[1], L"TestCrash") == 0) - { - __try - { - *(int *)0 = 0; - } - __except(CrashPointers = *GetExceptionInformation(), - CreateCrashLog ("TestCrash", 9), EXCEPTION_EXECUTE_HANDLER) - { - } - DisplayCrashLog (); - return 0; - } - if (__argc == 2 && __wargv != nullptr && wcscmp (__wargv[1], L"TestStackCrash") == 0) - { - __try - { - infiniterecursion(1); - } - __except(CrashPointers = *GetExceptionInformation(), - CreateCrashLog ("TestStackCrash", 14), EXCEPTION_EXECUTE_HANDLER) - { - } - DisplayCrashLog (); - return 0; - } -#endif - - MainThread = INVALID_HANDLE_VALUE; - DuplicateHandle (GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &MainThread, - 0, FALSE, DUPLICATE_SAME_ACCESS); - MainThreadID = GetCurrentThreadId(); - -#ifndef _DEBUG - if (MainThread != INVALID_HANDLE_VALUE) - { -#ifndef _M_ARM64 - SetUnhandledExceptionFilter (CatchAllExceptions); -#endif - -#ifdef _M_X64 - static bool setJumpResult = false; - RtlCaptureContext(&MainThreadContext); - if (setJumpResult) - { - ExitFatally(0); - return 0; - } - setJumpResult = true; -#endif // _M_X64 - } -#endif + InitCommonControls(); #if defined(_DEBUG) && defined(_MSC_VER) // Uncomment this line to make the Visual C++ CRT check the heap before @@ -553,14 +309,24 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int //_crtBreakAlloc = 227524; #endif - int ret = DoMain (hInstance); + // Setup crash reporting, unless it is the crash reporter launching us in response to a crash + if (wcsstr(cmdline, L"-showcrashreport") == nullptr) + { + WCHAR exeFilename[1024] = {}; + if (GetModuleFileName(0, exeFilename, 1023) != 0) + { + FString reportsDirectory = GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, true); + reportsDirectory += "/" GAMENAMELOWERCASE; + reportsDirectory += "/crashreports"; + CreatePath(reportsDirectory.GetChars()); - CloseHandle (MainThread); - MainThread = INVALID_HANDLE_VALUE; - return ret; + InitCrashReporter(reportsDirectory.WideString(), exeFilename); + } + } + + return DoMain(hInstance); } -// each platform has its own specific version of this function. void I_SetWindowTitle(const char* caption) { mainwindow.SetWindowTitle(caption); diff --git a/src/common/platform/win32/i_mainwindow.cpp b/src/common/platform/win32/i_mainwindow.cpp index 5b246e4575..95dda5031f 100644 --- a/src/common/platform/win32/i_mainwindow.cpp +++ b/src/common/platform/win32/i_mainwindow.cpp @@ -11,17 +11,14 @@ #include "v_font.h" #include "i_net.h" #include "engineerrors.h" +#include "common/widgets/errorwindow.h" +#include "common/widgets/netstartwindow.h" #include #include #include +#include -#ifdef _M_X64 -#define X64 " 64-bit" -#elif _M_ARM64 -#define X64 " ARM-64" -#else -#define X64 "" -#endif +#pragma comment(lib, "dwmapi.lib") MainWindow mainwindow; @@ -39,7 +36,7 @@ void MainWindow::Create(const FString& caption, int x, int y, int width, int hei WndClass.hInstance = hInstance; WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); - WndClass.hbrBackground = NULL; + WndClass.hbrBackground = CreateSolidBrush(RGB(0,0,0)); WndClass.lpszMenuName = NULL; WndClass.lpszClassName = WinClassName; @@ -55,7 +52,7 @@ void MainWindow::Create(const FString& caption, int x, int y, int width, int hei WS_EX_APPWINDOW, WinClassName, wcaption.c_str(), - WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, x, y, width, height, (HWND)NULL, (HMENU)NULL, @@ -67,29 +64,15 @@ void MainWindow::Create(const FString& caption, int x, int y, int width, int hei MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION | MB_OK); exit(-1); } -} -void MainWindow::HideGameTitleWindow() -{ - if (GameTitleWindow != 0) - { - DestroyWindow(GameTitleWindow); - GameTitleWindow = 0; - } -} + uint32_t bordercolor = RGB(51, 51, 51); + uint32_t captioncolor = RGB(33, 33, 33); + uint32_t textcolor = RGB(226, 223, 219); -int MainWindow::GetGameTitleWindowHeight() -{ - if (GameTitleWindow != 0) - { - RECT rect; - GetClientRect(GameTitleWindow, &rect); - return rect.bottom; - } - else - { - return 0; - } + // Don't error check these as they only exist on Windows 11, and if they fail then that is OK. + DwmSetWindowAttribute(Window, 34/*DWMWA_BORDER_COLOR*/, &bordercolor, sizeof(uint32_t)); + DwmSetWindowAttribute(Window, 35/*DWMWA_CAPTION_COLOR*/, &captioncolor, sizeof(uint32_t)); + DwmSetWindowAttribute(Window, 36/*DWMWA_TEXT_COLOR*/, &textcolor, sizeof(uint32_t)); } // Sets the main WndProc, hides all the child windows, and starts up in-game input. @@ -99,10 +82,6 @@ void MainWindow::ShowGameView() { SetWindowLongPtr(Window, GWLP_USERDATA, 1); SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)WndProc); - ShowWindow(ConWindow, SW_HIDE); - ShowWindow(ProgressBar, SW_HIDE); - ConWindowHidden = true; - ShowWindow(GameTitleWindow, SW_HIDE); I_InitInput(Window); } } @@ -110,766 +89,88 @@ void MainWindow::ShowGameView() // Returns the main window to its startup state. void MainWindow::RestoreConView() { - HDC screenDC = GetDC(0); - int dpi = GetDeviceCaps(screenDC, LOGPIXELSX); - ReleaseDC(0, screenDC); - int width = (512 * dpi + 96 / 2) / 96; - int height = (384 * dpi + 96 / 2) / 96; - - // Make sure the window has a frame in case it was fullscreened. - SetWindowLongPtr(Window, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW); - if (GetWindowLong(Window, GWL_EXSTYLE) & WS_EX_TOPMOST) - { - SetWindowPos(Window, HWND_BOTTOM, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE); - SetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE); - } - else - { - SetWindowPos(Window, NULL, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER); - } - - SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)LConProc); - ShowWindow(ConWindow, SW_SHOW); - ConWindowHidden = false; - ShowWindow(GameTitleWindow, SW_SHOW); I_ShutdownInput(); // Make sure the mouse pointer is available. + ShowWindow(Window, SW_HIDE); + // Make sure the progress bar isn't visible. DeleteStartupScreen(); - - FlushBufferedConsoleStuff(); } // Shows an error message, preferably in the main window, but it can use a normal message box too. void MainWindow::ShowErrorPane(const char* text) { - auto widetext = WideString(text); - if (Window == nullptr || ConWindow == nullptr) - { - if (text != NULL) - { - FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime()); - MessageBoxW(Window, widetext.c_str(),caption.WideString().c_str(), MB_OK | MB_ICONSTOP | MB_TASKMODAL); - } - return; - } - - if (StartWindow != NULL) // Ensure that the network pane is hidden. + if (StartWindow) // Ensure that the network pane is hidden. { I_NetDone(); } - if (text != NULL) - { - FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime()); - auto wcaption = caption.WideString(); - SetWindowTextW(Window, wcaption.c_str()); - ErrorIcon = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, Window, NULL, GetModuleHandle(0), NULL); - if (ErrorIcon != NULL) - { - SetWindowLong(ErrorIcon, GWL_ID, IDC_ICONPIC); - } - } - ErrorPane = CreateDialogParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_ERRORPANE), Window, ErrorPaneProc, (LONG_PTR)NULL); - - if (text != NULL) - { - CHARRANGE end; - CHARFORMAT2 oldformat, newformat; - PARAFORMAT2 paraformat; - - // Append the error message to the log. - end.cpMax = end.cpMin = GetWindowTextLength(ConWindow); - SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&end); - - // Remember current charformat. - oldformat.cbSize = sizeof(oldformat); - SendMessage(ConWindow, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat); - - // Use bigger font and standout colors. - newformat.cbSize = sizeof(newformat); - newformat.dwMask = CFM_BOLD | CFM_COLOR | CFM_SIZE; - newformat.dwEffects = CFE_BOLD; - newformat.yHeight = oldformat.yHeight * 5 / 4; - newformat.crTextColor = RGB(255, 170, 170); - SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&newformat); - - // Indent the rest of the text to make the error message stand out a little more. - paraformat.cbSize = sizeof(paraformat); - paraformat.dwMask = PFM_STARTINDENT | PFM_OFFSETINDENT | PFM_RIGHTINDENT; - paraformat.dxStartIndent = paraformat.dxOffset = paraformat.dxRightIndent = 120; - SendMessage(ConWindow, EM_SETPARAFORMAT, 0, (LPARAM)¶format); - SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"\n"); - - // Find out where the error lines start for the error icon display control. - SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&end); - ErrorIconChar = end.cpMax; - - // Now start adding the actual error message. - SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"Execution could not continue.\n\n"); - - // Restore old charformat but with light yellow text. - oldformat.crTextColor = RGB(255, 255, 170); - SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat); - - // Add the error text. - SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)widetext.c_str()); - - // Make sure the error text is not scrolled below the window. - SendMessage(ConWindow, EM_LINESCROLL, 0, SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0)); - // The above line scrolled everything off the screen, so pretend to move the scroll - // bar thumb, which clamps to not show any extra lines if it doesn't need to. - SendMessage(ConWindow, EM_SCROLL, SB_PAGEDOWN, 0); - } - - BOOL bRet; - MSG msg; - - while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) - { - if (bRet == -1) - { - MessageBoxW(Window, widetext.c_str(), WGAMENAME " Fatal Error", MB_OK | MB_ICONSTOP | MB_TASKMODAL); - return; - } - else if (!IsDialogMessage(ErrorPane, &msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } -} -void MainWindow::ShowProgressBar(int maxpos) -{ - if (ProgressBar == 0) - ProgressBar = CreateWindowEx(0, PROGRESS_CLASS, 0, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 0, 0, 0, 0, Window, 0, GetModuleHandle(0), 0); - SendMessage(ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, maxpos)); - LayoutMainWindow(Window, 0); -} + // PrintStr(text); -void MainWindow::HideProgressBar() -{ - if (ProgressBar != 0) - { - DestroyWindow(ProgressBar); - ProgressBar = 0; - LayoutMainWindow(Window, 0); - } -} + size_t totalsize = 0; + for (const FString& line : bufferedConsoleStuff) + totalsize += line.Len(); -void MainWindow::SetProgressPos(int pos) -{ - if (ProgressBar != 0) - SendMessage(ProgressBar, PBM_SETPOS, pos, 0); -} + std::string alltext; + alltext.reserve(totalsize); + for (const FString& line : bufferedConsoleStuff) + alltext.append(line.GetChars(), line.Len()); -// DialogProc for the network startup pane. It just waits for somebody to click a button, and the only button available is the abort one. -static INT_PTR CALLBACK NetStartPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) - { - PostMessage(hDlg, WM_COMMAND, 1337, 1337); - return TRUE; - } - return FALSE; + restartrequest = ErrorWindow::ExecModal(text, alltext); } void MainWindow::ShowNetStartPane(const char* message, int maxpos) { - // Create the dialog child window - if (NetStartPane == NULL) - { - NetStartPane = CreateDialogParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_NETSTARTPANE), Window, NetStartPaneProc, 0); - if (ProgressBar != 0) - { - DestroyWindow(ProgressBar); - ProgressBar = 0; - } - RECT winrect; - GetWindowRect(Window, &winrect); - SetWindowPos(Window, NULL, 0, 0, - winrect.right - winrect.left, winrect.bottom - winrect.top + LayoutNetStartPane(NetStartPane, 0), - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); - LayoutMainWindow(Window, NULL); - SetFocus(NetStartPane); - } - - // Set the message text - std::wstring wmessage = WideString(message); - SetDlgItemTextW(NetStartPane, IDC_NETSTARTMESSAGE, wmessage.c_str()); - - // Set the progress bar range - NetStartMaxPos = maxpos; - HWND ctl = GetDlgItem(NetStartPane, IDC_NETSTARTPROGRESS); - if (maxpos == 0) - { - SendMessage(ctl, PBM_SETMARQUEE, TRUE, 100); - SetWindowLong(ctl, GWL_STYLE, GetWindowLong(ctl, GWL_STYLE) | PBS_MARQUEE); - SetDlgItemTextW(NetStartPane, IDC_NETSTARTCOUNT, L""); - } - else - { - SendMessage(ctl, PBM_SETMARQUEE, FALSE, 0); - SetWindowLong(ctl, GWL_STYLE, GetWindowLong(ctl, GWL_STYLE) & (~PBS_MARQUEE)); - - SendMessage(ctl, PBM_SETRANGE, 0, MAKELPARAM(0, maxpos)); - if (maxpos == 1) - { - SendMessage(ctl, PBM_SETPOS, 1, 0); - SetDlgItemTextW(NetStartPane, IDC_NETSTARTCOUNT, L""); - } - } + NetStartWindow::ShowNetStartPane(message, maxpos); } void MainWindow::HideNetStartPane() { - if (NetStartPane != 0) - { - DestroyWindow(NetStartPane); - NetStartPane = 0; - LayoutMainWindow(Window, 0); - } + NetStartWindow::HideNetStartPane(); } void MainWindow::SetNetStartProgress(int pos) { - if (NetStartPane != 0 && NetStartMaxPos > 1) - { - char buf[16]; - mysnprintf(buf, countof(buf), "%d/%d", pos, NetStartMaxPos); - SetDlgItemTextA(NetStartPane, IDC_NETSTARTCOUNT, buf); - SendDlgItemMessage(NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, min(pos, NetStartMaxPos), 0); - } + NetStartWindow::SetNetStartProgress(pos); } bool MainWindow::RunMessageLoop(bool (*timer_callback)(void*), void* userdata) { - BOOL bRet; - MSG msg; - - if (SetTimer(Window, 1337, 500, NULL) == 0) - { - I_FatalError("Could not set network synchronization timer."); - } - - while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) - { - if (bRet == -1) - { - KillTimer(Window, 1337); - return false; - } - else - { - // This must be outside the window function so that the exception does not cross DLL boundaries. - if (msg.message == WM_COMMAND && msg.wParam == 1337 && msg.lParam == 1337) - { - throw CExitEvent(0); - } - if (msg.message == WM_TIMER && msg.hwnd == Window && msg.wParam == 1337) - { - if (timer_callback(userdata)) - { - KillTimer(Window, 1337); - return true; - } - } - if (!IsDialogMessage(NetStartPane, &msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - } - KillTimer(Window, 1337); - return false; -} - -void MainWindow::UpdateLayout() -{ - LayoutMainWindow(Window, 0); -} - -// Lays out the main window with the game title and log controls and possibly the error pane and progress bar. -void MainWindow::LayoutMainWindow(HWND hWnd, HWND pane) -{ - RECT rect; - int errorpaneheight = 0; - int bannerheight = 0; - int progressheight = 0; - int netpaneheight = 0; - int leftside = 0; - int w, h; - - GetClientRect(hWnd, &rect); - w = rect.right; - h = rect.bottom; - - if (GameStartupInfo.Name.IsNotEmpty() && GameTitleWindow != NULL) - { - bannerheight = GameTitleFontHeight + 5; - MoveWindow(GameTitleWindow, 0, 0, w, bannerheight, TRUE); - InvalidateRect(GameTitleWindow, NULL, FALSE); - } - if (ProgressBar != NULL) - { - // Base the height of the progress bar on the height of a scroll bar - // arrow, just as in the progress bar example. - progressheight = GetSystemMetrics(SM_CYVSCROLL); - MoveWindow(ProgressBar, 0, h - progressheight, w, progressheight, TRUE); - } - if (NetStartPane != NULL) - { - netpaneheight = LayoutNetStartPane(NetStartPane, w); - SetWindowPos(NetStartPane, HWND_TOP, 0, h - progressheight - netpaneheight, w, netpaneheight, SWP_SHOWWINDOW); - } - if (pane != NULL) - { - errorpaneheight = LayoutErrorPane(pane, w); - SetWindowPos(pane, HWND_TOP, 0, h - progressheight - netpaneheight - errorpaneheight, w, errorpaneheight, 0); - } - if (ErrorIcon != NULL) - { - leftside = GetSystemMetrics(SM_CXICON) + 6; - MoveWindow(ErrorIcon, 0, bannerheight, leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE); - } - // The log window uses whatever space is left. - MoveWindow(ConWindow, leftside, bannerheight, w - leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE); -} - -// Lays out the error pane to the desired width, returning the required height. -int MainWindow::LayoutErrorPane(HWND pane, int w) -{ - HWND ctl, ctl_two; - RECT rectc, rectc_two; - - // Right-align the Quit button. - ctl = GetDlgItem(pane, IDOK); - GetClientRect(ctl, &rectc); // Find out how big it is. - MoveWindow(ctl, w - rectc.right - 1, 1, rectc.right, rectc.bottom, TRUE); - - // Second-right-align the Restart button - ctl_two = GetDlgItem(pane, IDC_BUTTON1); - GetClientRect(ctl_two, &rectc_two); // Find out how big it is. - MoveWindow(ctl_two, w - rectc.right - rectc_two.right - 2, 1, rectc.right, rectc.bottom, TRUE); - - InvalidateRect(ctl, NULL, TRUE); - InvalidateRect(ctl_two, NULL, TRUE); - - // Return the needed height for this layout - return rectc.bottom + 2; -} - -// Lays out the network startup pane to the specified width, returning its required height. -int MainWindow::LayoutNetStartPane(HWND pane, int w) -{ - HWND ctl; - RECT margin, rectc; - int staticheight, barheight; - - // Determine margin sizes. - SetRect(&margin, 7, 7, 0, 0); - MapDialogRect(pane, &margin); - - // Stick the message text in the upper left corner. - ctl = GetDlgItem(pane, IDC_NETSTARTMESSAGE); - GetClientRect(ctl, &rectc); - MoveWindow(ctl, margin.left, margin.top, rectc.right, rectc.bottom, TRUE); - - // Stick the count text in the upper right corner. - ctl = GetDlgItem(pane, IDC_NETSTARTCOUNT); - GetClientRect(ctl, &rectc); - MoveWindow(ctl, w - rectc.right - margin.left, margin.top, rectc.right, rectc.bottom, TRUE); - staticheight = rectc.bottom; - - // Stretch the progress bar to fill the entire width. - ctl = GetDlgItem(pane, IDC_NETSTARTPROGRESS); - barheight = GetSystemMetrics(SM_CYVSCROLL); - MoveWindow(ctl, margin.left, margin.top * 2 + staticheight, w - margin.left * 2, barheight, TRUE); - - // Center the abort button underneath the progress bar. - ctl = GetDlgItem(pane, IDCANCEL); - GetClientRect(ctl, &rectc); - MoveWindow(ctl, (w - rectc.right) / 2, margin.top * 3 + staticheight + barheight, rectc.right, rectc.bottom, TRUE); - - return margin.top * 4 + staticheight + barheight + rectc.bottom; + return NetStartWindow::RunMessageLoop(timer_callback, userdata); } -void MainWindow::CheckForRestart() +bool MainWindow::CheckForRestart() { - if (restartrequest) - { - HMODULE hModule = GetModuleHandleW(NULL); - WCHAR path[MAX_PATH]; - GetModuleFileNameW(hModule, path, MAX_PATH); - ShellExecuteW(NULL, L"open", path, GetCommandLineW(), NULL, SW_SHOWNORMAL); - } + bool result = restartrequest; restartrequest = false; + return result; } // The main window's WndProc during startup. During gameplay, the WndProc in i_input.cpp is used instead. LRESULT MainWindow::LConProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - return mainwindow.OnMessage(hWnd, msg, wParam, lParam); -} - -INT_PTR MainWindow::ErrorPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_INITDIALOG: - // Appear in the main window. - mainwindow.LayoutMainWindow(GetParent(hDlg), hDlg); - return TRUE; - - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED) - { - if (LOWORD(wParam) == IDC_BUTTON1) // we pressed the restart button, so run GZDoom again - { - mainwindow.restartrequest = true; - } - PostQuitMessage(0); - return TRUE; - } - break; - } - return FALSE; -} - -LRESULT MainWindow::OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_CREATE: return OnCreate(hWnd, msg, wParam, lParam); - case WM_SIZE: return OnSize(hWnd, msg, wParam, lParam); - case WM_DRAWITEM: return OnDrawItem(hWnd, msg, wParam, lParam); - case WM_COMMAND: return OnCommand(hWnd, msg, wParam, lParam); - case WM_CLOSE: return OnClose(hWnd, msg, wParam, lParam); - case WM_DESTROY: return OnDestroy(hWnd, msg, wParam, lParam); - default: return DefWindowProc(hWnd, msg, wParam, lParam); - } -} - -LRESULT MainWindow::OnCreate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND view; - HDC hdc; - HGDIOBJ oldfont; - LOGFONT lf; - TEXTMETRIC tm; - CHARFORMAT2W format; - - HINSTANCE inst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_HINSTANCE); - - // Create game title static control - memset(&lf, 0, sizeof(lf)); - hdc = GetDC(hWnd); - lf.lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72); - lf.lfCharSet = ANSI_CHARSET; - lf.lfWeight = FW_BOLD; - lf.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN; - wcscpy(lf.lfFaceName, L"Trebuchet MS"); - GameTitleFont = CreateFontIndirect(&lf); - - oldfont = SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); - GetTextMetrics(hdc, &tm); - DefaultGUIFontHeight = tm.tmHeight; - if (GameTitleFont == NULL) - { - GameTitleFontHeight = DefaultGUIFontHeight; - } - else - { - SelectObject(hdc, GameTitleFont); - GetTextMetrics(hdc, &tm); - GameTitleFontHeight = tm.tmHeight; - } - SelectObject(hdc, oldfont); - - // Create log read-only edit control - view = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"RichEdit20W", nullptr, - WS_CHILD | WS_VISIBLE | WS_VSCROLL | - ES_LEFT | ES_MULTILINE | WS_CLIPSIBLINGS, - 0, 0, 0, 0, - hWnd, NULL, inst, NULL); - HRESULT hr; - hr = GetLastError(); - if (view == NULL) - { - ReleaseDC(hWnd, hdc); - return -1; - } - SendMessage(view, EM_SETREADONLY, TRUE, 0); - SendMessage(view, EM_EXLIMITTEXT, 0, 0x7FFFFFFE); - SendMessage(view, EM_SETBKGNDCOLOR, 0, RGB(70, 70, 70)); - // Setup default font for the log. - //SendMessage (view, WM_SETFONT, (WPARAM)GetStockObject (DEFAULT_GUI_FONT), FALSE); - format.cbSize = sizeof(format); - format.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_CHARSET; - format.dwEffects = 0; - format.yHeight = 200; - format.crTextColor = RGB(223, 223, 223); - format.bCharSet = ANSI_CHARSET; - format.bPitchAndFamily = FF_SWISS | VARIABLE_PITCH; - wcscpy(format.szFaceName, L"DejaVu Sans"); // At least I have it. :p - SendMessageW(view, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&format); - - ConWindow = view; - ReleaseDC(hWnd, hdc); - - view = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, hWnd, nullptr, inst, nullptr); - if (view == nullptr) - { - return -1; - } - SetWindowLong(view, GWL_ID, IDC_STATIC_TITLE); - GameTitleWindow = view; - - return 0; -} - -LRESULT MainWindow::OnSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW) - { - LayoutMainWindow(hWnd, ErrorPane); - } - return 0; -} - -LRESULT MainWindow::OnDrawItem(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HGDIOBJ oldfont; - HBRUSH hbr; - DRAWITEMSTRUCT* drawitem; - RECT rect; - SIZE size; - - // Draw title banner. - if (wParam == IDC_STATIC_TITLE && GameStartupInfo.Name.IsNotEmpty()) - { - const PalEntry* c; - - // Draw the game title strip at the top of the window. - drawitem = (LPDRAWITEMSTRUCT)lParam; - - // Draw the background. - rect = drawitem->rcItem; - rect.bottom -= 1; - c = (const PalEntry*)&GameStartupInfo.BkColor; - hbr = CreateSolidBrush(RGB(c->r, c->g, c->b)); - FillRect(drawitem->hDC, &drawitem->rcItem, hbr); - DeleteObject(hbr); - - // Calculate width of the title string. - SetTextAlign(drawitem->hDC, TA_TOP); - oldfont = SelectObject(drawitem->hDC, GameTitleFont != NULL ? GameTitleFont : (HFONT)GetStockObject(DEFAULT_GUI_FONT)); - auto widename = GameStartupInfo.Name.WideString(); - GetTextExtentPoint32W(drawitem->hDC, widename.c_str(), (int)widename.length(), &size); - - // Draw the title. - c = (const PalEntry*)&GameStartupInfo.FgColor; - SetTextColor(drawitem->hDC, RGB(c->r, c->g, c->b)); - SetBkMode(drawitem->hDC, TRANSPARENT); - TextOutW(drawitem->hDC, rect.left + (rect.right - rect.left - size.cx) / 2, 2, widename.c_str(), (int)widename.length()); - SelectObject(drawitem->hDC, oldfont); - return TRUE; - } - // Draw stop icon. - else if (wParam == IDC_ICONPIC) - { - HICON icon; - POINTL char_pos; - drawitem = (LPDRAWITEMSTRUCT)lParam; - - // This background color should match the edit control's. - hbr = CreateSolidBrush(RGB(70, 70, 70)); - FillRect(drawitem->hDC, &drawitem->rcItem, hbr); - DeleteObject(hbr); - - // Draw the icon aligned with the first line of error text. - SendMessage(ConWindow, EM_POSFROMCHAR, (WPARAM)&char_pos, ErrorIconChar); - icon = (HICON)LoadImage(0, IDI_ERROR, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); - DrawIcon(drawitem->hDC, 6, char_pos.y, icon); - return TRUE; - } - return FALSE; -} - -LRESULT MainWindow::OnCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (ErrorIcon != NULL && (HWND)lParam == ConWindow && HIWORD(wParam) == EN_UPDATE) - { - // Be sure to redraw the error icon if the edit control changes. - InvalidateRect(ErrorIcon, NULL, TRUE); - return 0; - } - return DefWindowProc(hWnd, msg, wParam, lParam); -} - -LRESULT MainWindow::OnClose(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - PostQuitMessage(0); - return DefWindowProc(hWnd, msg, wParam, lParam); -} - -LRESULT MainWindow::OnDestroy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (GameTitleFont != NULL) - { - DeleteObject(GameTitleFont); - } return DefWindowProc(hWnd, msg, wParam, lParam); } void MainWindow::PrintStr(const char* cp) { - if (ConWindowHidden) - { - bufferedConsoleStuff.Push(cp); - } - else - { - DoPrintStr(cp); - } -} - -void MainWindow::FlushBufferedConsoleStuff() -{ - for (unsigned i = 0; i < bufferedConsoleStuff.Size(); i++) - { - DoPrintStr(bufferedConsoleStuff[i]); - } - bufferedConsoleStuff.Clear(); -} - -void MainWindow::DoPrintStr(const char* cpt) -{ - wchar_t wbuf[256]; - int bpos = 0; - CHARRANGE selection = {}; - CHARRANGE endselection = {}; - LONG lines_before = 0, lines_after = 0; - - // Store the current selection and set it to the end so we can append text. - SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&selection); - endselection.cpMax = endselection.cpMin = GetWindowTextLength(ConWindow); - SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&endselection); - - // GetWindowTextLength and EM_EXSETSEL can disagree on where the end of - // the text is. Find out what EM_EXSETSEL thought it was and use that later. - SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&endselection); - - // Remember how many lines there were before we added text. - lines_before = (LONG)SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0); - - const uint8_t* cptr = (const uint8_t*)cpt; - - auto outputIt = [&]() - { - wbuf[bpos] = 0; - SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)wbuf); - bpos = 0; - }; - - while (int chr = GetCharFromString(cptr)) - { - if ((chr == TEXTCOLOR_ESCAPE && bpos != 0) || bpos == 255) - { - outputIt(); - } - if (chr != TEXTCOLOR_ESCAPE) - { - if (chr >= 0x1D && chr <= 0x1F) - { // The bar characters, most commonly used to indicate map changes - chr = 0x2550; // Box Drawings Double Horizontal - } - wbuf[bpos++] = chr; - } - else - { - EColorRange range = V_ParseFontColor(cptr, CR_UNTRANSLATED, CR_YELLOW); - - if (range != CR_UNDEFINED) - { - // Change the color of future text added to the control. - PalEntry color = V_LogColorFromColorRange(range); - - // Change the color. - CHARFORMAT format; - format.cbSize = sizeof(format); - format.dwMask = CFM_COLOR; - format.dwEffects = 0; - format.crTextColor = RGB(color.r, color.g, color.b); - SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format); - } - } - } - if (bpos != 0) - { - outputIt(); - } - - // If the old selection was at the end of the text, keep it at the end and - // scroll. Don't scroll if the selection is anywhere else. - if (selection.cpMin == endselection.cpMin && selection.cpMax == endselection.cpMax) - { - selection.cpMax = selection.cpMin = GetWindowTextLength(ConWindow); - lines_after = (LONG)SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0); - if (lines_after > lines_before) - { - SendMessage(ConWindow, EM_LINESCROLL, 0, lines_after - lines_before); - } - } - // Restore the previous selection. - SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&selection); - // Give the edit control a chance to redraw itself. - I_GetEvent(); + bufferedConsoleStuff.Push(cp); } -static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG* pcb) +void MainWindow::GetLog(std::function writeData) { - uint32_t didwrite; - LONG p, pp; - - // Replace gray foreground color with black. - static const char* badfg = "\\red223\\green223\\blue223;"; - // 4321098 765432109 876543210 - // 2 1 0 - for (p = pp = 0; p < cb; ++p) + for (const FString& line : bufferedConsoleStuff) { - if (buffer[p] == badfg[pp]) - { - ++pp; - if (pp == 25) - { - buffer[p - 1] = buffer[p - 2] = buffer[p - 3] = - buffer[p - 9] = buffer[p - 10] = buffer[p - 11] = - buffer[p - 18] = buffer[p - 19] = buffer[p - 20] = '0'; - break; - } - } - else + size_t pos = 0; + size_t len = line.Len(); + while (pos < len) { - pp = 0; + uint32_t size = (uint32_t)std::min(len - pos, 0x0fffffffULL); + uint32_t written = 0; + if (!writeData(&line[pos], size, written)) + return; + pos += written; } } - - auto& writeData = *reinterpret_cast*>(cookie); - if (!writeData((const void*)buffer, cb, didwrite)) - { - return 1; - } - *pcb = didwrite; - return 0; -} - -void MainWindow::GetLog(std::function writeData) -{ - FlushBufferedConsoleStuff(); - - EDITSTREAM streamer = { (DWORD_PTR)&writeData, 0, WriteLogFileStreamer }; - SendMessage(ConWindow, EM_STREAMOUT, SF_RTF, (LPARAM)&streamer); } // each platform has its own specific version of this function. @@ -878,7 +179,7 @@ void MainWindow::SetWindowTitle(const char* caption) std::wstring widecaption; if (!caption) { - FStringf default_caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime()); + FStringf default_caption("" GAMENAME " %s (%s)", GetVersionString(), GetGitTime()); widecaption = default_caption.WideString(); } else diff --git a/src/common/platform/win32/i_mainwindow.h b/src/common/platform/win32/i_mainwindow.h index 2adea7bfa2..3c0c7e55df 100644 --- a/src/common/platform/win32/i_mainwindow.h +++ b/src/common/platform/win32/i_mainwindow.h @@ -20,20 +20,11 @@ class MainWindow void RestoreConView(); void ShowErrorPane(const char* text); - void CheckForRestart(); - - void HideGameTitleWindow(); - int GetGameTitleWindowHeight(); + bool CheckForRestart(); void PrintStr(const char* cp); void GetLog(std::function writeFile); - void UpdateLayout(); - - void ShowProgressBar(int maxpos); - void HideProgressBar(); - void SetProgressPos(int pos); - void ShowNetStartPane(const char* message, int maxpos); void SetNetStartProgress(int pos); bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata); @@ -44,47 +35,11 @@ class MainWindow HWND GetHandle() { return Window; } private: - void LayoutMainWindow(HWND hWnd, HWND pane); - int LayoutErrorPane(HWND pane, int w); - int LayoutNetStartPane(HWND pane, int w); - - void DoPrintStr(const char* cpt); - void FlushBufferedConsoleStuff(); - - LRESULT OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - LRESULT OnCreate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - LRESULT OnSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - LRESULT OnDrawItem(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - LRESULT OnCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - LRESULT OnClose(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - LRESULT OnDestroy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK LConProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - static INT_PTR CALLBACK ErrorPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); HWND Window = 0; - - HFONT GameTitleFont = 0; - LONG GameTitleFontHeight = 0; - LONG DefaultGUIFontHeight = 0; - LONG ErrorIconChar = 0; - bool restartrequest = false; - - HWND GameTitleWindow = 0; - HWND ErrorPane = 0; - HWND ErrorIcon = 0; - - bool ConWindowHidden = false; - HWND ConWindow = 0; TArray bufferedConsoleStuff; - - HWND ProgressBar = 0; - - HWND NetStartPane = 0; - int NetStartMaxPos = 0; - - HWND StartupScreen = 0; }; extern MainWindow mainwindow; diff --git a/src/common/platform/win32/i_mouse.cpp b/src/common/platform/win32/i_mouse.cpp index 37ee357098..72dc3f335c 100644 --- a/src/common/platform/win32/i_mouse.cpp +++ b/src/common/platform/win32/i_mouse.cpp @@ -131,7 +131,7 @@ enum EMouseMode // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- -static void SetCursorState(bool visible); +void SetCursorState(bool visible); static FMouse *CreateWin32Mouse(); static FMouse *CreateDInputMouse(); static FMouse *CreateRawMouse(); @@ -191,7 +191,7 @@ CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) static bool mouse_shown = true; -static void SetCursorState(bool visible) +void SetCursorState(bool visible) { CursorState = visible || !m_hidepointer; if (GetForegroundWindow() == mainwindow.GetHandle()) @@ -297,6 +297,12 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult) { BlockMouseMove = 3; Mouse->Ungrab(); + + if(!mouse_shown) + { + ShowCursor(true); + mouse_shown = true; + } } else { diff --git a/src/common/platform/win32/i_rawps2.cpp b/src/common/platform/win32/i_rawps2.cpp index f063788039..d406d61ea8 100644 --- a/src/common/platform/win32/i_rawps2.cpp +++ b/src/common/platform/win32/i_rawps2.cpp @@ -114,6 +114,9 @@ class FRawPS2Controller : public IJoystickConfig bool IsAxisMapDefault(int axis); bool IsAxisScaleDefault(int axis); + bool GetEnabled(); + void SetEnabled(bool enabled); + void SetDefaultConfig(); FString GetIdentifier(); @@ -153,6 +156,7 @@ class FRawPS2Controller : public IJoystickConfig bool Connected; bool Marked; bool Active; + bool Enabled; void Attached(); void Detached(); @@ -376,6 +380,7 @@ FRawPS2Controller::FRawPS2Controller(HANDLE handle, EAdapterType type, int seque ControllerNumber = controller; Sequence = sequence; DeviceID = devid; + Enabled = true; // The EMS USB2 controller provides attachment status. The others do not. Connected = (Descriptors[type].ControllerStatus < 0); @@ -849,6 +854,28 @@ bool FRawPS2Controller::IsAxisScaleDefault(int axis) return true; } +//=========================================================================== +// +// FRawPS2Controller :: GetEnabled +// +//=========================================================================== + +bool FRawPS2Controller::GetEnabled() +{ + return Enabled; +} + +//=========================================================================== +// +// FRawPS2Controller :: SetEnabled +// +//=========================================================================== + +void FRawPS2Controller::SetEnabled(bool enabled) +{ + Enabled = enabled; +} + //=========================================================================== // // FRawPS2Controller :: IsAxisMapDefault @@ -972,7 +999,7 @@ bool FRawPS2Manager::ProcessRawInput(RAWINPUT *raw, int code) { if (Devices[i]->Handle == raw->header.hDevice) { - if (Devices[i]->ProcessInput(&raw->data.hid, code)) + if (Devices[i]->Enabled && Devices[i]->ProcessInput(&raw->data.hid, code)) { return true; } @@ -1215,8 +1242,8 @@ int FRawPS2Manager::DeviceSort(const void *a, const void *b) if (lex == 0) { // Skip device part of the ID and sort the connection part - const char *ca = strchr(ha->DeviceID, '#'); - const char *cb = strchr(hb->DeviceID, '#'); + const char *ca = strchr(ha->DeviceID.GetChars(), '#'); + const char *cb = strchr(hb->DeviceID.GetChars(), '#'); const char *ea, *eb; // The last bit looks like a controller number. Strip it out to be safe // if this is a multi-controller adapter. diff --git a/src/common/platform/win32/i_specialpaths.cpp b/src/common/platform/win32/i_specialpaths.cpp index 3bfee00ea4..8862024b78 100644 --- a/src/common/platform/win32/i_specialpaths.cpp +++ b/src/common/platform/win32/i_specialpaths.cpp @@ -145,7 +145,7 @@ FString M_GetAppDataPath(bool create) path += "/" GAMENAMELOWERCASE; if (create) { - CreatePath(path); + CreatePath(path.GetChars()); } return path; } @@ -167,7 +167,7 @@ FString M_GetCachePath(bool create) path += "/zdoom/cache"; if (create) { - CreatePath(path); + CreatePath(path.GetChars()); } return path; } @@ -283,7 +283,7 @@ FString M_GetConfigPath(bool for_reading) // Construct a user-specific config name FString path = GetKnownFolder(CSIDL_APPDATA, FOLDERID_Documents, true); path += "/My Games/" GAME_DIR; - CreatePath(path); + CreatePath(path.GetChars()); path += "/" GAMENAMELOWERCASE ".ini"; if (!for_reading || FileExists(path)) return path; @@ -305,7 +305,7 @@ FString M_GetConfigPath(bool for_reading) isportable = true; } } - bool res = MoveFileExW(WideString(oldpath).c_str(), WideString(path).c_str(), MOVEFILE_COPY_ALLOWED); + bool res = MoveFileExW(WideString(oldpath.GetChars()).c_str(), WideString(path.GetChars()).c_str(), MOVEFILE_COPY_ALLOWED); if (res) return path; else return oldpath; // if we cannot move, just use the config where it was. It won't be written back, though and never be used again if a new one gets saved. } @@ -351,7 +351,7 @@ FString M_GetScreenshotsPath() path = GetKnownFolder(CSIDL_MYPICTURES, FOLDERID_Pictures, true); path << "/Screenshots/" GAMENAME "/"; } - CreatePath(path); + CreatePath(path.GetChars()); return path; } @@ -402,7 +402,7 @@ FString M_GetDocumentsPath() // I assume since this isn't a standard folder, it doesn't have a localized name either. path = GetKnownFolder(CSIDL_PERSONAL, FOLDERID_Documents, true); path << "/My Games/" GAMENAME "/"; - CreatePath(path); + CreatePath(path.GetChars()); } return path; } diff --git a/src/common/platform/win32/i_system.cpp b/src/common/platform/win32/i_system.cpp index 066e5463c1..0b8ea53ac5 100644 --- a/src/common/platform/win32/i_system.cpp +++ b/src/common/platform/win32/i_system.cpp @@ -87,6 +87,8 @@ #include "i_interface.h" #include "i_mainwindow.h" +#include "launcherwindow.h" + // MACROS ------------------------------------------------------------------ #ifdef _MSC_VER @@ -111,6 +113,7 @@ static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP EXTERN_CVAR (Bool, queryiwad); // Used on welcome/IWAD screen. +EXTERN_CVAR(Bool, longsavemessages) extern HANDLE StdOut; extern bool FancyStdOut; @@ -127,7 +130,7 @@ double PerfToSec, PerfToMillisec; UINT TimerPeriod; -int sys_ostype = 0; +const char* sys_ostype = ""; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -167,12 +170,10 @@ void I_DetectOS(void) if (info.dwMinorVersion == 0) { osname = (info.wProductType == VER_NT_WORKSTATION) ? "Vista" : "Server 2008"; - sys_ostype = 2; // legacy OS } else if (info.dwMinorVersion == 1) { osname = (info.wProductType == VER_NT_WORKSTATION) ? "7" : "Server 2008 R2"; - sys_ostype = 2; // supported OS } else if (info.dwMinorVersion == 2) { @@ -180,12 +181,10 @@ void I_DetectOS(void) // the highest version of Windows you support, which will also be the // highest version of Windows this function returns. osname = (info.wProductType == VER_NT_WORKSTATION) ? "8" : "Server 2012"; - sys_ostype = 2; // supported OS } else if (info.dwMinorVersion == 3) { osname = (info.wProductType == VER_NT_WORKSTATION) ? "8.1" : "Server 2012 R2"; - sys_ostype = 2; // supported OS } else if (info.dwMinorVersion == 4) { @@ -195,7 +194,6 @@ void I_DetectOS(void) else if (info.dwMajorVersion == 10) { osname = (info.wProductType == VER_NT_WORKSTATION) ? (info.dwBuildNumber >= 22000 ? "11 (or higher)" : "10") : "Server 2016 (or higher)"; - sys_ostype = 3; // modern OS } break; @@ -208,6 +206,8 @@ void I_DetectOS(void) osname, info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber, info.szCSDVersion); + + sys_ostype = osname; } //========================================================================== @@ -344,107 +344,6 @@ static void SetQueryIWad(HWND dialog) queryiwad = query; } -//========================================================================== -// -// IWADBoxCallback -// -// Dialog proc for the IWAD selector. -// -//========================================================================== -static int* pAutoloadflags; - -BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - int& flags = *pAutoloadflags;; - - HWND ctrl; - int i; - - switch (message) - { - case WM_INITDIALOG: - // Add our program name to the window title - { - WCHAR label[256]; - FString newlabel; - - GetWindowTextW(hDlg, label, countof(label)); - FString alabel(label); - newlabel.Format(GAMENAME " %s: %s", GetVersionString(), alabel.GetChars()); - auto wlabel = newlabel.WideString(); - SetWindowTextW(hDlg, wlabel.c_str()); - } - - // [SP] Upstreamed from Zandronum - char szString[256]; - - // Check the current video settings. - SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_SETCHECK, vid_fullscreen ? BST_CHECKED : BST_UNCHECKED, 0 ); - SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN2, BM_SETCHECK, BST_CHECKED, 0 ); - - // [SP] This is our's - SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_SETCHECK, (flags & 1) ? BST_CHECKED : BST_UNCHECKED, 0); - SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_SETCHECK, (flags & 2) ? BST_CHECKED : BST_UNCHECKED, 0 ); - SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_SETCHECK, (flags & 4) ? BST_CHECKED : BST_UNCHECKED, 0 ); - SendDlgItemMessage( hDlg, IDC_WELCOME_WIDESCREEN, BM_SETCHECK, (flags & 8) ? BST_CHECKED : BST_UNCHECKED, 0 ); - - // Set up our version string. - snprintf(szString, sizeof(szString), "Version %s.", GetVersionString()); - SetDlgItemTextA (hDlg, IDC_WELCOME_VERSION, szString); - - // Populate the list with all the IWADs found - ctrl = GetDlgItem(hDlg, IDC_IWADLIST); - for (i = 0; i < NumWads; i++) - { - const char *filepart = strrchr(WadList[i].Path, '/'); - if (filepart == NULL) - filepart = WadList[i].Path; - else - filepart++; - - FString work; - if (*filepart) work.Format("%s (%s)", WadList[i].Name.GetChars(), filepart); - else work = WadList[i].Name.GetChars(); - std::wstring wide = work.WideString(); - SendMessage(ctrl, LB_ADDSTRING, 0, (LPARAM)wide.c_str()); - SendMessage(ctrl, LB_SETITEMDATA, i, (LPARAM)i); - } - SendMessage(ctrl, LB_SETCURSEL, DefaultWad, 0); - SetFocus(ctrl); - // Set the state of the "Don't ask me again" checkbox - ctrl = GetDlgItem(hDlg, IDC_DONTASKIWAD); - SendMessage(ctrl, BM_SETCHECK, queryiwad ? BST_UNCHECKED : BST_CHECKED, 0); - // Make sure the dialog is in front. If SHIFT was pressed to force it visible, - // then the other window will normally be on top. - SetForegroundWindow(hDlg); - break; - - case WM_COMMAND: - if (LOWORD(wParam) == IDCANCEL) - { - EndDialog (hDlg, -1); - } - else if (LOWORD(wParam) == IDOK || - (LOWORD(wParam) == IDC_IWADLIST && HIWORD(wParam) == LBN_DBLCLK)) - { - SetQueryIWad(hDlg); - // [SP] Upstreamed from Zandronum - vid_fullscreen = SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_GETCHECK, 0, 0 ) == BST_CHECKED; - - // [SP] This is our's. - flags = 0; - if (SendDlgItemMessage(hDlg, IDC_WELCOME_NOAUTOLOAD, BM_GETCHECK, 0, 0) == BST_CHECKED) flags |= 1; - if (SendDlgItemMessage(hDlg, IDC_WELCOME_LIGHTS, BM_GETCHECK, 0, 0) == BST_CHECKED) flags |= 2; - if (SendDlgItemMessage(hDlg, IDC_WELCOME_BRIGHTMAPS, BM_GETCHECK, 0, 0) == BST_CHECKED) flags |= 4; - if (SendDlgItemMessage(hDlg, IDC_WELCOME_WIDESCREEN, BM_GETCHECK, 0, 0) == BST_CHECKED) flags |= 8; - ctrl = GetDlgItem (hDlg, IDC_IWADLIST); - EndDialog(hDlg, SendMessage (ctrl, LB_GETCURSEL, 0, 0)); - } - break; - } - return FALSE; -} - //========================================================================== // // I_PickIWad @@ -456,7 +355,6 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags) { int vkey; - pAutoloadflags = &autoloadflags; if (stricmp(queryiwad_key, "shift") == 0) { vkey = VK_SHIFT; @@ -471,12 +369,7 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& } if (showwin || (vkey != 0 && GetAsyncKeyState(vkey))) { - WadList = wads; - NumWads = numwads; - DefaultWad = defaultiwad; - - return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG), - (HWND)mainwindow.GetHandle(), (DLGPROC)IWADBoxCallback); + return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags); } return defaultiwad; } @@ -828,37 +721,6 @@ FString I_GetLongPathName(const FString &shortpath) return longpath; } -#ifdef _USING_V110_SDK71_ -//========================================================================== -// -// _stat64i32 -// -// Work around an issue where stat() function doesn't work -// with Windows XP compatible toolset. -// It uses GetFileInformationByHandleEx() which requires Windows Vista. -// -//========================================================================== - -int _wstat64i32(const wchar_t *path, struct _stat64i32 *buffer) -{ - WIN32_FILE_ATTRIBUTE_DATA data; - if(!GetFileAttributesExW(path, GetFileExInfoStandard, &data)) - return -1; - - buffer->st_ino = 0; - buffer->st_mode = ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR : S_IFREG)| - ((data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD|S_IWRITE); - buffer->st_dev = buffer->st_rdev = 0; - buffer->st_nlink = 1; - buffer->st_uid = 0; - buffer->st_gid = 0; - buffer->st_size = data.nFileSizeLow; - buffer->st_atime = (*(uint64_t*)&data.ftLastAccessTime) / 10000000 - 11644473600LL; - buffer->st_mtime = (*(uint64_t*)&data.ftLastWriteTime) / 10000000 - 11644473600LL; - buffer->st_ctime = (*(uint64_t*)&data.ftCreationTime) / 10000000 - 11644473600LL; - return 0; -} -#endif struct NumaNode { @@ -962,13 +824,17 @@ void I_OpenShellFolder(const char* infolder) } else if (SetCurrentDirectoryW(WideString(infolder).c_str())) { - Printf("Opening folder: %s\n", infolder); + if (longsavemessages) + Printf("Opening folder: %s\n", infolder); ShellExecuteW(NULL, L"open", L"explorer.exe", L".", NULL, SW_SHOWNORMAL); SetCurrentDirectoryW(curdir.Data()); } else { - Printf("Unable to open directory '%s\n", infolder); + if (longsavemessages) + Printf("Unable to open directory '%s\n", infolder); + else + Printf("Unable to open requested directory\n"); } } diff --git a/src/common/platform/win32/i_xinput.cpp b/src/common/platform/win32/i_xinput.cpp index ba4605dd0f..d1dc4364d8 100644 --- a/src/common/platform/win32/i_xinput.cpp +++ b/src/common/platform/win32/i_xinput.cpp @@ -102,6 +102,9 @@ class FXInputController : public IJoystickConfig bool IsAxisMapDefault(int axis); bool IsAxisScaleDefault(int axis); + bool GetEnabled(); + void SetEnabled(bool enabled); + void SetDefaultConfig(); FString GetIdentifier(); @@ -138,6 +141,7 @@ class FXInputController : public IJoystickConfig DWORD LastPacketNumber; int LastButtons; bool Connected; + bool Enabled; void Attached(); void Detached(); @@ -221,6 +225,7 @@ FXInputController::FXInputController(int index) { Index = index; Connected = false; + Enabled = true; M_LoadJoystickConfig(this); } @@ -269,7 +274,7 @@ void FXInputController::ProcessInput() { Attached(); } - if (state.dwPacketNumber == LastPacketNumber) + if (state.dwPacketNumber == LastPacketNumber || !Enabled) { // Nothing has changed since last time. return; } @@ -628,6 +633,28 @@ bool FXInputController::IsAxisScaleDefault(int axis) return true; } +//=========================================================================== +// +// FXInputController :: GetEnabled +// +//=========================================================================== + +bool FXInputController::GetEnabled() +{ + return Enabled; +} + +//=========================================================================== +// +// FXInputController :: SetEnabled +// +//=========================================================================== + +void FXInputController::SetEnabled(bool enabled) +{ + Enabled = enabled; +} + //=========================================================================== // // FXInputController :: IsAxisMapDefault diff --git a/src/common/platform/win32/st_start.cpp b/src/common/platform/win32/st_start.cpp index 07039add27..8bc48d26e5 100644 --- a/src/common/platform/win32/st_start.cpp +++ b/src/common/platform/win32/st_start.cpp @@ -76,9 +76,9 @@ extern HINSTANCE g_hInst; // //========================================================================== -FStartupScreen *FStartupScreen::CreateInstance(int max_progress, bool showprogress) +FStartupScreen *FStartupScreen::CreateInstance(int max_progress) { - return new FBasicStartupScreen(max_progress, showprogress); + return new FBasicStartupScreen(max_progress); } //========================================================================== @@ -89,13 +89,9 @@ FStartupScreen *FStartupScreen::CreateInstance(int max_progress, bool showprogre // //========================================================================== -FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar) +FBasicStartupScreen::FBasicStartupScreen(int max_progress) : FStartupScreen(max_progress) { - if (show_bar) - { - mainwindow.ShowProgressBar(MaxPos); - } NetMaxPos = 0; NetCurPos = 0; } @@ -111,8 +107,6 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar) FBasicStartupScreen::~FBasicStartupScreen() { - mainwindow.HideProgressBar(); - KillTimer(mainwindow.GetHandle(), 1337); } //========================================================================== @@ -128,7 +122,6 @@ void FBasicStartupScreen::Progress() if (CurPos < MaxPos) { CurPos++; - mainwindow.SetProgressPos(CurPos); } } diff --git a/src/common/platform/win32/win32glvideo.cpp b/src/common/platform/win32/win32glvideo.cpp index ebeb13cc94..bceb1908e7 100644 --- a/src/common/platform/win32/win32glvideo.cpp +++ b/src/common/platform/win32/win32glvideo.cpp @@ -109,7 +109,7 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer() SystemGLFrameBuffer *fb; #ifdef HAVE_GLES2 - if (V_GetBackend() == 2) + if (V_GetBackend() != 0) fb = new OpenGLESRenderer::OpenGLFrameBuffer(m_hMonitor, vid_fullscreen); else #endif @@ -326,8 +326,7 @@ bool Win32GLVideo::SetupPixelFormat(int multisample) if (!myWglChoosePixelFormatARB(m_hDC, attributes.data(), attribsFloat, 1, &pixelFormat, &numFormats)) { - Printf("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n"); - goto oldmethod; + I_FatalError("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n"); } if (vid_hdr && numFormats == 0) // This card/driver doesn't support the rgb16f pixel format. Fall back to 8bpc @@ -343,8 +342,7 @@ bool Win32GLVideo::SetupPixelFormat(int multisample) if (!myWglChoosePixelFormatARB(m_hDC, attributes.data(), attribsFloat, 1, &pixelFormat, &numFormats)) { - Printf("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n"); - goto oldmethod; + I_FatalError("R_OPENGL: Couldn't choose pixel format."); } } else if (vid_hdr) @@ -360,41 +358,12 @@ bool Win32GLVideo::SetupPixelFormat(int multisample) vr_enable_quadbuffered = false; goto again; } - Printf("R_OPENGL: No valid pixel formats found. Retrying in compatibility mode\n"); - goto oldmethod; + I_FatalError("R_OPENGL: No valid pixel formats found."); } } else { - oldmethod: - // If wglChoosePixelFormatARB is not found we have to do it the old fashioned way. - static PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), - 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - PFD_TYPE_RGBA, - 32, // color depth - 0, 0, 0, 0, 0, 0, - 0, - 0, - 0, - 0, 0, 0, 0, - 32, // z depth - 8, // stencil buffer - 0, - PFD_MAIN_PLANE, - 0, - 0, 0, 0 - }; - - pixelFormat = ChoosePixelFormat(m_hDC, &pfd); - DescribePixelFormat(m_hDC, pixelFormat, sizeof(pfd), &pfd); - - if (pfd.dwFlags & PFD_GENERIC_FORMAT) - { - I_Error("R_OPENGL: OpenGL driver not accelerated!"); - return false; - } + I_FatalError("R_OPENGL: Unable to create an OpenGL render context. Insufficient driver support for context creation\n"); } if (!::SetPixelFormat(m_hDC, pixelFormat, NULL)) @@ -452,8 +421,7 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample) m_hRC = zd_wglCreateContext(m_hDC); if (m_hRC == NULL) { - I_Error("R_OPENGL: Unable to create an OpenGL render context.\n"); - return false; + I_FatalError("R_OPENGL: Unable to create an OpenGL render context.\n"); } } @@ -464,7 +432,7 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample) } } // We get here if the driver doesn't support the modern context creation API which always means an old driver. - I_Error("R_OPENGL: Unable to create an OpenGL render context. Insufficient driver support for context creation\n"); + I_FatalError("R_OPENGL: Unable to create an OpenGL render context. Insufficient driver support for context creation\n"); return false; } diff --git a/src/common/platform/win32/winres.h b/src/common/platform/win32/winres.h index 6d78230d84..a2b8711a6a 100644 --- a/src/common/platform/win32/winres.h +++ b/src/common/platform/win32/winres.h @@ -10,6 +10,7 @@ // winres.h - Windows resource definitions // extracted from WINUSER.H and COMMCTRL.H +#pragma once #ifdef _AFX_MINREBUILD #pragma component(minrebuild, off) diff --git a/src/common/rendering/hwrenderer/data/buffers.h b/src/common/rendering/hwrenderer/data/buffers.h index a195525e7f..aae1415f90 100644 --- a/src/common/rendering/hwrenderer/data/buffers.h +++ b/src/common/rendering/hwrenderer/data/buffers.h @@ -7,7 +7,6 @@ class FRenderState; #ifdef __ANDROID__ #define HW_MAX_PIPELINE_BUFFERS 4 -#define HW_BLOCK_SSBO 1 #else // On desktop this is only useful fpr letting the GPU run in parallel with the playsim and for that 2 buffers are enough. #define HW_MAX_PIPELINE_BUFFERS 2 @@ -27,6 +26,7 @@ enum VATTR_LIGHTMAP, VATTR_BONEWEIGHT, VATTR_BONESELECTOR, + VATTR_UNIFORM_INDEXES, VATTR_MAX }; @@ -38,7 +38,8 @@ enum EVertexAttributeFormat VFmt_Float, VFmt_Byte4, VFmt_Packed_A2R10G10B10, - VFmt_Byte4_UInt + VFmt_Byte4_UInt, + VFmt_Int }; struct FVertexBufferAttribute diff --git a/src/common/rendering/hwrenderer/data/flatvertices.h b/src/common/rendering/hwrenderer/data/flatvertices.h index eac2107e7f..1e13fd5b5a 100644 --- a/src/common/rendering/hwrenderer/data/flatvertices.h +++ b/src/common/rendering/hwrenderer/data/flatvertices.h @@ -1,11 +1,11 @@ #pragma once -struct FFlatVertex +struct FFlatVertex // Note: this must always match the SurfaceVertex struct in shaders (std430 layout rules apply) { float x, z, y; // world position + float lindex; // lightmap texture index float u, v; // texture coordinates float lu, lv; // lightmap texture coordinates - float lindex; // lightmap texture index void Set(float xx, float zz, float yy, float uu, float vv) { @@ -22,11 +22,11 @@ struct FFlatVertex x = xx; z = zz; y = yy; + lindex = llindex; u = uu; v = vv; lu = llu; lv = llv; - lindex = llindex; } void SetVertex(float _x, float _y, float _z = 0) @@ -42,4 +42,5 @@ struct FFlatVertex v = _v; } + FVector3 fPos() const { return FVector3(x, y, z); } }; diff --git a/src/common/rendering/hwrenderer/data/hw_aabbtree.cpp b/src/common/rendering/hwrenderer/data/hw_aabbtree.cpp index 20a1d39a1a..d7d221fe31 100644 --- a/src/common/rendering/hwrenderer/data/hw_aabbtree.cpp +++ b/src/common/rendering/hwrenderer/data/hw_aabbtree.cpp @@ -56,10 +56,10 @@ TArray LevelAABBTree::FindNodePath(unsigned int line, unsigned int node) double LevelAABBTree::RayTest(const DVector3 &ray_start, const DVector3 &ray_end) { // Precalculate some of the variables used by the ray/line intersection test - DVector2 raydelta = ray_end - ray_start; + DVector2 raydelta = (ray_end - ray_start).XY(); double raydist2 = raydelta | raydelta; DVector2 raynormal = DVector2(raydelta.Y, -raydelta.X); - double rayd = raynormal | ray_start; + double rayd = raynormal | ray_start.XY(); if (raydist2 < 1.0) return 1.0f; @@ -73,7 +73,7 @@ double LevelAABBTree::RayTest(const DVector3 &ray_start, const DVector3 &ray_end { int node_index = stack[stack_pos - 1]; - if (!OverlapRayAABB(ray_start, ray_end, nodes[node_index])) + if (!OverlapRayAABB(ray_start.XY(), ray_end.XY(), nodes[node_index])) { // If the ray doesn't overlap this node's AABB we're done for this subtree stack_pos--; @@ -81,7 +81,7 @@ double LevelAABBTree::RayTest(const DVector3 &ray_start, const DVector3 &ray_end else if (nodes[node_index].line_index != -1) // isLeaf(node_index) { // We reached a leaf node. Do a ray/line intersection test to see if we hit the line. - hit_fraction = std::min(IntersectRayLine(ray_start, ray_end, nodes[node_index].line_index, raydelta, rayd, raydist2), hit_fraction); + hit_fraction = std::min(IntersectRayLine(ray_start.XY(), ray_end.XY(), nodes[node_index].line_index, raydelta, rayd, raydist2), hit_fraction); stack_pos--; } else if (stack_pos == 32) diff --git a/src/common/rendering/hwrenderer/data/hw_collision.cpp b/src/common/rendering/hwrenderer/data/hw_collision.cpp index e83afbef6d..eddf6ca37c 100644 --- a/src/common/rendering/hwrenderer/data/hw_collision.cpp +++ b/src/common/rendering/hwrenderer/data/hw_collision.cpp @@ -28,7 +28,7 @@ #include #endif -TriangleMeshShape::TriangleMeshShape(const FVector3 *vertices, int num_vertices, const unsigned int *elements, int num_elements) +TriangleMeshShape::TriangleMeshShape(const FFlatVertex *vertices, int num_vertices, const unsigned int *elements, int num_elements) : vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements) { int num_triangles = num_elements / 3; @@ -44,7 +44,7 @@ TriangleMeshShape::TriangleMeshShape(const FVector3 *vertices, int num_vertices, triangles.push_back(i); int element_index = i * 3; - FVector3 centroid = (vertices[elements[element_index + 0]] + vertices[elements[element_index + 1]] + vertices[elements[element_index + 2]]) * (1.0f / 3.0f); + FVector3 centroid = (vertices[elements[element_index + 0]].fPos() + vertices[elements[element_index + 1]].fPos() + vertices[elements[element_index + 2]].fPos()) * (1.0f / 3.0f); centroids.push_back(centroid); } @@ -55,28 +55,38 @@ TriangleMeshShape::TriangleMeshShape(const FVector3 *vertices, int num_vertices, float TriangleMeshShape::sweep(TriangleMeshShape *shape1, SphereShape *shape2, const FVector3 &target) { + if (shape1->root == -1) + return 1.0f; return sweep(shape1, shape2, shape1->root, target); } bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape1, TriangleMeshShape *shape2) { + if (shape1->root == -1) + return false; return find_any_hit(shape1, shape2, shape1->root, shape2->root); } bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2) { + if (shape1->root == -1) + return false; return find_any_hit(shape1, shape2, shape1->root); } std::vector TriangleMeshShape::find_all_hits(TriangleMeshShape* shape1, SphereShape* shape2) { std::vector hits; - find_all_hits(shape1, shape2, shape1->root, hits); + if (shape1->root != -1) + find_all_hits(shape1, shape2, shape1->root, hits); return hits; } bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape, const FVector3 &ray_start, const FVector3 &ray_end) { + if (shape->root == -1) + return false; + return find_any_hit(shape, RayBBox(ray_start, ray_end), shape->root); } @@ -84,6 +94,9 @@ TraceHit TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const FVect { TraceHit hit; + if (shape->root == -1) + return hit; + // Perform segmented tracing to keep the ray AABB box smaller FVector3 ray_dir = ray_end - ray_start; @@ -267,12 +280,12 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const FVector3 p[3] = { - shape->vertices[shape->elements[start_element]], - shape->vertices[shape->elements[start_element + 1]], - shape->vertices[shape->elements[start_element + 2]] + shape->vertices[shape->elements[start_element]].fPos(), + shape->vertices[shape->elements[start_element + 1]].fPos(), + shape->vertices[shape->elements[start_element + 2]].fPos() }; - // MoellerTrumbore ray-triangle intersection algorithm: + // Moeller-Trumbore ray-triangle intersection algorithm: FVector3 D = ray.end - ray.start; @@ -343,9 +356,9 @@ float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shap FVector3 p[3] = { - shape1->vertices[shape1->elements[start_element]], - shape1->vertices[shape1->elements[start_element + 1]], - shape1->vertices[shape1->elements[start_element + 2]] + shape1->vertices[shape1->elements[start_element]].fPos(), + shape1->vertices[shape1->elements[start_element + 1]].fPos(), + shape1->vertices[shape1->elements[start_element + 2]].fPos() }; FVector3 c = shape2->center; @@ -515,9 +528,9 @@ bool TriangleMeshShape::overlap_triangle_sphere(TriangleMeshShape *shape1, Spher int element_index = shape1->nodes[shape1_node_index].element_index; FVector3 P = shape2->center; - FVector3 A = shape1->vertices[shape1->elements[element_index]] - P; - FVector3 B = shape1->vertices[shape1->elements[element_index + 1]] - P; - FVector3 C = shape1->vertices[shape1->elements[element_index + 2]] - P; + FVector3 A = shape1->vertices[shape1->elements[element_index]].fPos() - P; + FVector3 B = shape1->vertices[shape1->elements[element_index + 1]].fPos() - P; + FVector3 C = shape1->vertices[shape1->elements[element_index + 2]].fPos() - P; float r = shape2->radius; float rr = r * r; @@ -627,14 +640,14 @@ int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const FVecto // Find bounding box and median of the triangle centroids FVector3 median; FVector3 min, max; - min = vertices[elements[triangles[0] * 3]]; + min = vertices[elements[triangles[0] * 3]].fPos(); max = min; for (int i = 0; i < num_triangles; i++) { int element_index = triangles[i] * 3; for (int j = 0; j < 3; j++) { - const FVector3 &vertex = vertices[elements[element_index + j]]; + const FVector3 &vertex = vertices[elements[element_index + j]].fPos(); min.X = std::min(min.X, vertex.X); min.Y = std::min(min.Y, vertex.Y); diff --git a/src/common/rendering/hwrenderer/data/hw_collision.h b/src/common/rendering/hwrenderer/data/hw_collision.h index 756ffc0315..911fe947ea 100644 --- a/src/common/rendering/hwrenderer/data/hw_collision.h +++ b/src/common/rendering/hwrenderer/data/hw_collision.h @@ -23,6 +23,7 @@ #pragma once #include "common/utility/vectors.h" +#include "flatvertices.h" #include #include @@ -86,7 +87,7 @@ class RayBBox class TriangleMeshShape { public: - TriangleMeshShape(const FVector3 *vertices, int num_vertices, const unsigned int *elements, int num_elements); + TriangleMeshShape(const FFlatVertex *vertices, int num_vertices, const unsigned int *elements, int num_elements); int get_min_depth() const; int get_max_depth() const; @@ -121,7 +122,7 @@ class TriangleMeshShape int get_root() const { return root; } private: - const FVector3 *vertices = nullptr; + const FFlatVertex* vertices = nullptr; const int num_vertices = 0; const unsigned int *elements = nullptr; int num_elements = 0; diff --git a/src/common/rendering/hwrenderer/data/hw_cvars.cpp b/src/common/rendering/hwrenderer/data/hw_cvars.cpp index 2476c00247..7d8c4aa3bd 100644 --- a/src/common/rendering/hwrenderer/data/hw_cvars.cpp +++ b/src/common/rendering/hwrenderer/data/hw_cvars.cpp @@ -56,7 +56,7 @@ CUSTOM_CVAR(Int, gl_fogmode, 2, CVAR_ARCHIVE | CVAR_NOINITCALL) CVAR(Bool, gl_portals, true, 0) CVAR(Bool,gl_mirrors,true,0) // This is for debugging only! CVAR(Bool,gl_mirror_envmap, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) -CVAR(Bool, gl_seamless, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR(Bool, gl_seamless, true, 0) // This is for debugging only now! The level mesh requires no holes in the level to properly detect portals. CUSTOM_CVAR(Int, r_mirror_recursions,4,CVAR_GLOBALCONFIG|CVAR_ARCHIVE) { @@ -115,7 +115,7 @@ CVAR(Int, gl_satformula, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); // Texture CVARs // //========================================================================== -CUSTOM_CVARD(Float, gl_texture_filter_anisotropic, 8.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL, "changes the OpenGL texture anisotropy setting") +CUSTOM_CVARD(Float, gl_texture_filter_anisotropic, 0.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL, "changes the texture anisotropy setting") { screen->SetTextureFilterMode(); } @@ -128,8 +128,28 @@ CUSTOM_CVARD(Int, gl_texture_filter, 6, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOIN CVAR(Bool, gl_precache, true, CVAR_ARCHIVE) +CUSTOM_CVAR(Int, gl_light_shadows, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0 || self > 3) + self = 1; +} -CUSTOM_CVAR(Int, gl_shadowmap_filter, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, gl_light_shadow_filter, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (self < 0 || self > 8) self = 1; } + +CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + switch (self) + { + case 128: + case 256: + case 512: + case 1024: + break; + default: + self = 128; + break; + } +} diff --git a/src/common/rendering/hwrenderer/data/hw_cvars.h b/src/common/rendering/hwrenderer/data/hw_cvars.h index eb190d1ae9..b36dda98ad 100644 --- a/src/common/rendering/hwrenderer/data/hw_cvars.h +++ b/src/common/rendering/hwrenderer/data/hw_cvars.h @@ -14,12 +14,11 @@ EXTERN_CVAR(Int, gl_weaponlight) EXTERN_CVAR (Bool, gl_light_sprites); EXTERN_CVAR (Bool, gl_light_particles); -EXTERN_CVAR (Bool, gl_light_shadowmap); -EXTERN_CVAR (Bool, gl_light_raytrace); +EXTERN_CVAR (Int, gl_light_shadows); +EXTERN_CVAR (Int, gl_light_shadow_filter); EXTERN_CVAR (Int, gl_shadowmap_quality); EXTERN_CVAR(Int, gl_fogmode) -EXTERN_CVAR(Int, gl_lightmode) EXTERN_CVAR(Bool,gl_mirror_envmap) EXTERN_CVAR(Bool,gl_mirrors) @@ -44,6 +43,7 @@ EXTERN_CVAR(Int, gl_ssao) EXTERN_CVAR(Int, gl_ssao_portals) EXTERN_CVAR(Float, gl_ssao_strength) EXTERN_CVAR(Int, gl_ssao_debug) +EXTERN_CVAR(Bool, gl_shownormals) EXTERN_CVAR(Float, gl_ssao_bias) EXTERN_CVAR(Float, gl_ssao_radius) EXTERN_CVAR(Float, gl_ssao_blur_amount) @@ -51,8 +51,6 @@ EXTERN_CVAR(Float, gl_ssao_blur_amount) EXTERN_CVAR(Int, gl_debug_level) EXTERN_CVAR(Bool, gl_debug_breakpoint) -EXTERN_CVAR(Int, gl_shadowmap_filter) - EXTERN_CVAR(Bool, gl_brightfog) EXTERN_CVAR(Bool, gl_lightadditivesurfaces) EXTERN_CVAR(Bool, gl_notexturefill) diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp new file mode 100644 index 0000000000..a2998b8aa1 --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp @@ -0,0 +1,286 @@ + +#include "hw_levelmesh.h" +#include "halffloat.h" + +LevelMesh::LevelMesh() +{ + // Default portal + LevelMeshPortal portal; + Portals.Push(portal); + + AddEmptyMesh(); + UpdateCollision(); + + Mesh.MaxVertices = std::max(Mesh.Vertices.Size() * 2, (unsigned int)10000); + Mesh.MaxIndexes = std::max(Mesh.Indexes.Size() * 2, (unsigned int)10000); + Mesh.MaxSurfaces = std::max(Mesh.SurfaceIndexes.Size() * 2, (unsigned int)10000); + Mesh.MaxUniforms = std::max(Mesh.Uniforms.Size() * 2, (unsigned int)10000); + Mesh.MaxSurfaceIndexes = std::max(Mesh.SurfaceIndexes.Size() * 2, (unsigned int)10000); + Mesh.MaxNodes = (int)std::max(Collision->get_nodes().size() * 2, (size_t)10000); + Mesh.MaxLights = 100'000; + Mesh.MaxLightIndexes = 4 * 1024 * 1024; +} + +void LevelMesh::AddEmptyMesh() +{ + // Default empty mesh (we can't make it completely empty since vulkan doesn't like that) + float minval = -100001.0f; + float maxval = -100000.0f; + Mesh.Vertices.Push({ minval, minval, minval }); + Mesh.Vertices.Push({ maxval, minval, minval }); + Mesh.Vertices.Push({ maxval, maxval, minval }); + Mesh.Vertices.Push({ minval, minval, minval }); + Mesh.Vertices.Push({ minval, maxval, minval }); + Mesh.Vertices.Push({ maxval, maxval, minval }); + Mesh.Vertices.Push({ minval, minval, maxval }); + Mesh.Vertices.Push({ maxval, minval, maxval }); + Mesh.Vertices.Push({ maxval, maxval, maxval }); + Mesh.Vertices.Push({ minval, minval, maxval }); + Mesh.Vertices.Push({ minval, maxval, maxval }); + Mesh.Vertices.Push({ maxval, maxval, maxval }); + + for (int i = 0; i < 3 * 4; i++) + Mesh.Indexes.Push(i); +} + +LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, float maxDist) +{ + maxDist = std::max(maxDist - 10.0f, 0.0f); + + FVector3 origin = start; + + LevelMeshSurface* hitSurface = nullptr; + + while (true) + { + FVector3 end = origin + direction * maxDist; + + TraceHit hit = TriangleMeshShape::find_first_hit(Collision.get(), origin, end); + + if (hit.triangle < 0) + { + return nullptr; + } + + hitSurface = GetSurface(Mesh.SurfaceIndexes[hit.triangle]); + + int portal = hitSurface->PortalIndex; + if (!portal) + { + break; + } + + auto& transformation = Portals[portal]; + + auto travelDist = hit.fraction * maxDist + 2.0f; + if (travelDist >= maxDist) + { + break; + } + + origin = transformation.TransformPosition(origin + direction * travelDist); + direction = transformation.TransformRotation(direction); + maxDist -= travelDist; + } + + return hitSurface; // I hit something +} + +LevelMeshTileStats LevelMesh::GatherTilePixelStats() +{ + LevelMeshTileStats stats; + int count = GetSurfaceCount(); + for (const LightmapTile& tile : LightmapTiles) + { + auto area = tile.AtlasLocation.Area(); + + stats.pixels.total += area; + + if (tile.NeedsUpdate) + { + stats.tiles.dirty++; + stats.pixels.dirty += area; + } + } + stats.tiles.total += LightmapTiles.Size(); + return stats; +} + +void LevelMesh::UpdateCollision() +{ + Collision = std::make_unique(Mesh.Vertices.Data(), Mesh.Vertices.Size(), Mesh.Indexes.Data(), Mesh.Indexes.Size()); +} + +struct LevelMeshPlaneGroup +{ + FVector4 plane = FVector4(0, 0, 1, 0); + int sectorGroup = 0; + std::vector surfaces; +}; + +void LevelMesh::BuildTileSurfaceLists() +{ + // Plane group surface is to be rendered with + TArray PlaneGroups; + TArray PlaneGroupIndexes(GetSurfaceCount()); + + for (int i = 0, count = GetSurfaceCount(); i < count; i++) + { + auto surface = GetSurface(i); + + // Is this surface in the same plane as an existing plane group? + int planeGroupIndex = -1; + + for (size_t j = 0; j < PlaneGroups.Size(); j++) + { + if (surface->SectorGroup == PlaneGroups[j].sectorGroup) + { + float direction = PlaneGroups[j].plane.XYZ() | surface->Plane.XYZ(); + if (direction >= 0.999f && direction <= 1.01f) + { + auto point = (surface->Plane.XYZ() * surface->Plane.W); + auto planeDistance = (PlaneGroups[j].plane.XYZ() | point) - PlaneGroups[j].plane.W; + + float dist = std::abs(planeDistance); + if (dist <= 0.1f) + { + planeGroupIndex = (int)j; + break; + } + } + } + } + + // Surface is in a new plane. Create a plane group for it + if (planeGroupIndex == -1) + { + planeGroupIndex = PlaneGroups.Size(); + + LevelMeshPlaneGroup group; + group.plane = surface->Plane; + group.sectorGroup = surface->SectorGroup; + PlaneGroups.Push(group); + } + + PlaneGroups[planeGroupIndex].surfaces.push_back(surface); + PlaneGroupIndexes.Push(planeGroupIndex); + } + + for (auto& tile : LightmapTiles) + tile.Surfaces.Clear(); + + for (int i = 0, count = GetSurfaceCount(); i < count; i++) + { + LevelMeshSurface* targetSurface = GetSurface(i); + if (targetSurface->LightmapTileIndex < 0) + continue; + LightmapTile* tile = &LightmapTiles[targetSurface->LightmapTileIndex]; + for (LevelMeshSurface* surface : PlaneGroups[PlaneGroupIndexes[i]].surfaces) + { + FVector2 minUV = tile->ToUV(surface->Bounds.min); + FVector2 maxUV = tile->ToUV(surface->Bounds.max); + if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f)) + continue; // Bounding box not visible + + tile->Surfaces.Push(GetSurfaceIndex(surface)); + } + } +} + +void LevelMesh::SetupTileTransforms() +{ + for (auto& tile : LightmapTiles) + { + tile.SetupTileTransform(LMTextureSize); + } +} + +void LevelMesh::PackLightmapAtlas(int lightmapStartIndex) +{ + std::vector sortedTiles; + sortedTiles.reserve(LightmapTiles.Size()); + + for (auto& tile : LightmapTiles) + { + sortedTiles.push_back(&tile); + } + + std::sort(sortedTiles.begin(), sortedTiles.end(), [](LightmapTile* a, LightmapTile* b) { return a->AtlasLocation.Height != b->AtlasLocation.Height ? a->AtlasLocation.Height > b->AtlasLocation.Height : a->AtlasLocation.Width > b->AtlasLocation.Width; }); + + // We do not need to add spacing here as this is already built into the tile size itself. + RectPacker packer(LMTextureSize, LMTextureSize, RectPacker::Spacing(0), RectPacker::Padding(0)); + + for (LightmapTile* tile : sortedTiles) + { + auto result = packer.insert(tile->AtlasLocation.Width, tile->AtlasLocation.Height); + tile->AtlasLocation.X = result.pos.x; + tile->AtlasLocation.Y = result.pos.y; + tile->AtlasLocation.ArrayIndex = lightmapStartIndex + (int)result.pageIndex; + } + + LMTextureCount = (int)packer.getNumPages(); + + // Calculate final texture coordinates + for (int i = 0, count = GetSurfaceCount(); i < count; i++) + { + auto surface = GetSurface(i); + if (surface->LightmapTileIndex >= 0) + { + const LightmapTile& tile = LightmapTiles[surface->LightmapTileIndex]; + for (int i = 0; i < surface->MeshLocation.NumVerts; i++) + { + auto& vertex = Mesh.Vertices[surface->MeshLocation.StartVertIndex + i]; + FVector2 uv = tile.ToUV(vertex.fPos(), (float)LMTextureSize); + vertex.lu = uv.X; + vertex.lv = uv.Y; + vertex.lindex = (float)tile.AtlasLocation.ArrayIndex; + } + } + } + +#if 0 // Debug atlas tile locations: + float colors[30] = + { + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 1.0f, + 1.0f, 0.0f, 1.0f, + 0.5f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.0f, + 0.0f, 0.5f, 0.5f, + 0.5f, 0.0f, 0.5f + }; + LMTextureData.Resize(LMTextureSize * LMTextureSize * LMTextureCount * 3); + uint16_t* pixels = LMTextureData.Data(); + for (LightmapTile& tile : LightmapTiles) + { + tile.NeedsUpdate = false; + + int index = tile.Binding.TypeIndex; + float* color = colors + (index % 10) * 3; + + int x = tile.AtlasLocation.X; + int y = tile.AtlasLocation.Y; + int w = tile.AtlasLocation.Width; + int h = tile.AtlasLocation.Height; + for (int yy = y; yy < y + h; yy++) + { + uint16_t* line = pixels + tile.AtlasLocation.ArrayIndex * LMTextureSize * LMTextureSize + yy * LMTextureSize * 3; + for (int xx = x; xx < x + w; xx++) + { + float gray = (yy - y) / (float)h; + line[xx * 3] = floatToHalf(color[0] * gray); + line[xx * 3 + 1] = floatToHalf(color[1] * gray); + line[xx * 3 + 2] = floatToHalf(color[2] * gray); + } + } + } + for (int i = 0, count = GetSurfaceCount(); i < count; i++) + { + auto surface = GetSurface(i); + surface->AlwaysUpdate = false; + } +#endif +} diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index 8a48c99f38..ef3987f094 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -4,27 +4,107 @@ #include "tarray.h" #include "vectors.h" #include "hw_collision.h" +#include "flatvertices.h" +#include "hw_levelmeshlight.h" +#include "hw_levelmeshportal.h" +#include "hw_lightmaptile.h" +#include "hw_levelmeshsurface.h" +#include "hw_materialstate.h" +#include "hw_surfaceuniforms.h" +#include -namespace hwrenderer +#include +typedef dp::rect_pack::RectPacker RectPacker; + +struct LevelMeshTileStats; + +struct LevelSubmeshDrawRange { + int PipelineID; + int Start; + int Count; +}; class LevelMesh { public: + LevelMesh(); virtual ~LevelMesh() = default; - TArray MeshVertices; - TArray MeshUVIndex; - TArray MeshElements; - TArray MeshSurfaces; + virtual LevelMeshSurface* GetSurface(int index) { return nullptr; } + virtual unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const { return 0xffffffff; } + virtual int GetSurfaceCount() { return 0; } - std::unique_ptr Collision; + LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist); + + LevelMeshTileStats GatherTilePixelStats(); + + // Map defaults + FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f); + FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f); - bool Trace(const FVector3& start, FVector3 direction, float maxDist) + TArray Portals; + + struct { - FVector3 end = start + direction * std::max(maxDist - 10.0f, 0.0f); - return !TriangleMeshShape::find_any_hit(Collision.get(), start, end); - } + // Vertex data + TArray Vertices; + TArray UniformIndexes; + + // Surface info + TArray Uniforms; + TArray Materials; + TArray LightIndexes; + + // Lights + TArray Lights; + + // Index data + TArray Indexes; + TArray SurfaceIndexes; + int DynamicIndexStart = 0; + + // Above data must not be resized beyond these limits as that's the size of the GPU buffers) + int MaxVertices = 0; + int MaxIndexes = 0; + int MaxSurfaces = 0; + int MaxUniforms = 0; + int MaxSurfaceIndexes = 0; + int MaxNodes = 0; + int MaxLights = 0; + int MaxLightIndexes = 0; + } Mesh; + + std::unique_ptr Collision; + + TArray DrawList; + TArray PortalList; + + // Lightmap atlas + int LMTextureCount = 0; + int LMTextureSize = 1024; + TArray LMTextureData; + + uint16_t LightmapSampleDistance = 16; + + TArray LightmapTiles; + + uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); } + + void UpdateCollision(); + void BuildTileSurfaceLists(); + void SetupTileTransforms(); + void PackLightmapAtlas(int lightmapStartIndex); + + void AddEmptyMesh(); }; -} // namespace +struct LevelMeshTileStats +{ + struct Stats + { + uint32_t total = 0, dirty = 0; + }; + + Stats tiles, pixels; +}; diff --git a/src/common/rendering/hwrenderer/data/hw_levelmeshlight.h b/src/common/rendering/hwrenderer/data/hw_levelmeshlight.h new file mode 100644 index 0000000000..b18ca38eb2 --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_levelmeshlight.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "vectors.h" + +class LevelMeshLight +{ +public: + FVector3 Origin; + FVector3 RelativeOrigin; + float Radius; + float Intensity; + float InnerAngleCos; + float OuterAngleCos; + FVector3 SpotDir; + FVector3 Color; + int SectorGroup; + float SourceRadius; +}; diff --git a/src/common/rendering/hwrenderer/data/hw_levelmeshportal.h b/src/common/rendering/hwrenderer/data/hw_levelmeshportal.h new file mode 100644 index 0000000000..c7f4c4fc96 --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_levelmeshportal.h @@ -0,0 +1,72 @@ + +#pragma once + +#include +#include "vectors.h" +#include "common/utility/matrix.h" + +struct LevelMeshPortal +{ + LevelMeshPortal() { transformation.loadIdentity(); } + + VSMatrix transformation; + + int sourceSectorGroup = 0; + int targetSectorGroup = 0; + + inline FVector3 TransformPosition(const FVector3& pos) const + { + auto v = transformation * FVector4(pos, 1.0); + return FVector3(v.X, v.Y, v.Z); + } + + inline FVector3 TransformRotation(const FVector3& dir) const + { + auto v = transformation * FVector4(dir, 0.0); + return FVector3(v.X, v.Y, v.Z); + } + + // Checks only transformation + inline bool IsInverseTransformationPortal(const LevelMeshPortal& portal) const + { + auto diff = portal.TransformPosition(TransformPosition(FVector3(0, 0, 0))); + return abs(diff.X) < 0.001 && abs(diff.Y) < 0.001 && abs(diff.Z) < 0.001; + } + + // Checks only transformation + inline bool IsEqualTransformationPortal(const LevelMeshPortal& portal) const + { + auto diff = portal.TransformPosition(FVector3(0, 0, 0)) - TransformPosition(FVector3(0, 0, 0)); + return (abs(diff.X) < 0.001 && abs(diff.Y) < 0.001 && abs(diff.Z) < 0.001); + } + + // Checks transformation, source and destiantion sector groups + inline bool IsEqualPortal(const LevelMeshPortal& portal) const + { + return sourceSectorGroup == portal.sourceSectorGroup && targetSectorGroup == portal.targetSectorGroup && IsEqualTransformationPortal(portal); + } + + // Checks transformation, source and destiantion sector groups + inline bool IsInversePortal(const LevelMeshPortal& portal) const + { + return sourceSectorGroup == portal.targetSectorGroup && targetSectorGroup == portal.sourceSectorGroup && IsInverseTransformationPortal(portal); + } +}; + +// for use with std::set to recursively go through portals and skip returning portals +struct RecursivePortalComparator +{ + bool operator()(const LevelMeshPortal& a, const LevelMeshPortal& b) const + { + return !a.IsInversePortal(b) && std::memcmp(&a.transformation, &b.transformation, sizeof(VSMatrix)) < 0; + } +}; + +// for use with std::map to reject portals which have the same effect for light rays +struct IdenticalPortalComparator +{ + bool operator()(const LevelMeshPortal& a, const LevelMeshPortal& b) const + { + return !a.IsEqualPortal(b) && std::memcmp(&a.transformation, &b.transformation, sizeof(VSMatrix)) < 0; + } +}; diff --git a/src/common/rendering/hwrenderer/data/hw_levelmeshsurface.h b/src/common/rendering/hwrenderer/data/hw_levelmeshsurface.h new file mode 100644 index 0000000000..5dae14107f --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_levelmeshsurface.h @@ -0,0 +1,42 @@ + +#pragma once + +#include "tarray.h" +#include "vectors.h" +#include "bounds.h" +#include "textureid.h" +#include "textures.h" + +class FGameTexture; +struct LevelMeshSurface; + +struct LevelMeshSurface +{ + struct + { + unsigned int StartVertIndex = 0; + int NumVerts = 0; + unsigned int StartElementIndex = 0; + unsigned int NumElements = 0; + } MeshLocation; + + BBox Bounds; + FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f); + int LightmapTileIndex = -1; + + bool AlwaysUpdate = false; + + FGameTexture* Texture = nullptr; + float Alpha = 1.0; + + bool IsSky = false; + int PortalIndex = 0; + int SectorGroup = 0; + + // Light list location in the lightmapper GPU buffers + struct + { + int Pos = 0; + int Count = 0; + } LightList; +}; diff --git a/src/common/rendering/hwrenderer/data/hw_lightmaptile.h b/src/common/rendering/hwrenderer/data/hw_lightmaptile.h new file mode 100644 index 0000000000..dd41928f61 --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_lightmaptile.h @@ -0,0 +1,170 @@ + +#pragma once + +#include "tarray.h" +#include "vectors.h" +#include "bounds.h" + +struct LevelMeshSurface; + +struct LightmapTileBinding +{ + uint32_t Type = 0; + uint32_t TypeIndex = 0; + uint32_t ControlSector = 0xffffffff; + + bool operator<(const LightmapTileBinding& other) const + { + if (TypeIndex != other.TypeIndex) return TypeIndex < other.TypeIndex; + if (ControlSector != other.ControlSector) return ControlSector < other.ControlSector; + return Type < other.Type; + } +}; + +struct LightmapTile +{ + // Surface location in lightmap texture + struct + { + int X = 0; + int Y = 0; + int Width = 0; + int Height = 0; + int ArrayIndex = 0; + uint32_t Area() const { return Width * Height; } + } AtlasLocation; + + // Calculate world coordinates to UV coordinates + struct + { + FVector3 TranslateWorldToLocal = { 0.0f, 0.0f, 0.0f }; + FVector3 ProjLocalToU = { 0.0f, 0.0f, 0.0f }; + FVector3 ProjLocalToV = { 0.0f, 0.0f, 0.0f }; + } Transform; + + LightmapTileBinding Binding; + + // Surfaces that are visible within the lightmap tile + TArray Surfaces; + + BBox Bounds; + uint16_t SampleDimension = 0; + FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f); + + // True if the tile needs to be rendered into the lightmap texture before it can be used + bool NeedsUpdate = true; + + FVector2 ToUV(const FVector3& vert) const + { + FVector3 localPos = vert - Transform.TranslateWorldToLocal; + float u = (localPos | Transform.ProjLocalToU) / AtlasLocation.Width; + float v = (localPos | Transform.ProjLocalToV) / AtlasLocation.Height; + return FVector2(u, v); + } + + FVector2 ToUV(const FVector3& vert, float textureSize) const + { + // Clamp in case the wall moved outside the tile (happens if a lift moves with a static lightmap on it) + FVector3 localPos = vert - Transform.TranslateWorldToLocal; + float u = std::max(std::min(localPos | Transform.ProjLocalToU, (float)AtlasLocation.Width), 0.0f); + float v = std::max(std::min(localPos | Transform.ProjLocalToV, (float)AtlasLocation.Height), 0.0f); + u = (AtlasLocation.X + u) / textureSize; + v = (AtlasLocation.Y + v) / textureSize; + return FVector2(u, v); + } + + enum PlaneAxis + { + AXIS_YZ = 0, + AXIS_XZ, + AXIS_XY + }; + + static PlaneAxis BestAxis(const FVector4& p) + { + float na = fabs(float(p.X)); + float nb = fabs(float(p.Y)); + float nc = fabs(float(p.Z)); + + // figure out what axis the plane lies on + if (na >= nb && na >= nc) + { + return AXIS_YZ; + } + else if (nb >= na && nb >= nc) + { + return AXIS_XZ; + } + + return AXIS_XY; + } + + void SetupTileTransform(int textureSize) + { + // These calculations align the tile so that there's a one texel border around the actual surface in the tile. + // + // This removes sampling artifacts as a linear sampler reads from a 2x2 area. + // The tile is also aligned to the grid to keep aliasing artifacts consistent. + + FVector3 uvMin; + uvMin.X = std::floor(Bounds.min.X / SampleDimension) - 1.0f; + uvMin.Y = std::floor(Bounds.min.Y / SampleDimension) - 1.0f; + uvMin.Z = std::floor(Bounds.min.Z / SampleDimension) - 1.0f; + + FVector3 uvMax; + uvMax.X = std::floor(Bounds.max.X / SampleDimension) + 2.0f; + uvMax.Y = std::floor(Bounds.max.Y / SampleDimension) + 2.0f; + uvMax.Z = std::floor(Bounds.max.Z / SampleDimension) + 2.0f; + + FVector3 tCoords[2] = { FVector3(0.0f, 0.0f, 0.0f), FVector3(0.0f, 0.0f, 0.0f) }; + int width, height; + switch (BestAxis(Plane)) + { + default: + case AXIS_YZ: + width = (int)(uvMax.Y - uvMin.Y); + height = (int)(uvMax.Z - uvMin.Z); + tCoords[0].Y = 1.0f / SampleDimension; + tCoords[1].Z = 1.0f / SampleDimension; + break; + + case AXIS_XZ: + width = (int)(uvMax.X - uvMin.X); + height = (int)(uvMax.Z - uvMin.Z); + tCoords[0].X = 1.0f / SampleDimension; + tCoords[1].Z = 1.0f / SampleDimension; + break; + + case AXIS_XY: + width = (int)(uvMax.X - uvMin.X); + height = (int)(uvMax.Y - uvMin.Y); + tCoords[0].X = 1.0f / SampleDimension; + tCoords[1].Y = 1.0f / SampleDimension; + break; + } + + textureSize -= 6; // Lightmapper needs some padding when baking + + // Tile can never be bigger than the texture. + if (width > textureSize) + { + tCoords[0] *= textureSize / (float)width; + width = textureSize; + } + if (height > textureSize) + { + tCoords[1] *= textureSize / (float)height; + height = textureSize; + } + + Transform.TranslateWorldToLocal.X = uvMin.X * SampleDimension; + Transform.TranslateWorldToLocal.Y = uvMin.Y * SampleDimension; + Transform.TranslateWorldToLocal.Z = uvMin.Z * SampleDimension; + + Transform.ProjLocalToU = tCoords[0]; + Transform.ProjLocalToV = tCoords[1]; + + AtlasLocation.Width = width; + AtlasLocation.Height = height; + } +}; diff --git a/src/common/rendering/hwrenderer/data/hw_materialstate.h b/src/common/rendering/hwrenderer/data/hw_materialstate.h new file mode 100644 index 0000000000..de0d6ada2c --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_materialstate.h @@ -0,0 +1,24 @@ + +#pragma once + +#include "textures.h" + +class FMaterial; + +struct FMaterialState +{ + FMaterial* mMaterial = nullptr; + int mClampMode; + int mTranslation; + int mOverrideShader; + bool mChanged; + + void Reset() + { + mMaterial = nullptr; + mTranslation = 0; + mClampMode = CLAMP_NONE; + mOverrideShader = -1; + mChanged = false; + } +}; diff --git a/src/common/rendering/hwrenderer/data/hw_mesh.cpp b/src/common/rendering/hwrenderer/data/hw_mesh.cpp index 4276200378..46036c8baf 100644 --- a/src/common/rendering/hwrenderer/data/hw_mesh.cpp +++ b/src/common/rendering/hwrenderer/data/hw_mesh.cpp @@ -1,6 +1,7 @@ #include "hw_mesh.h" #include "v_video.h" +#include "cmdlib.h" #define USE_MESH_VERTEX_BUFFER @@ -12,9 +13,9 @@ void Mesh::Draw(FRenderState& renderstate) { static const FVertexBufferAttribute format[] = { - { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) }, + { 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FFlatVertex, x) }, { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }, - { 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FFlatVertex, lu) }, + { 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FFlatVertex, lu) }, }; mVertexBuffer.reset(screen->CreateVertexBuffer(1, 3, sizeof(FFlatVertex), format)); mVertexBuffer->SetData(mVertices.Size() * sizeof(FFlatVertex), mVertices.Data(), BufferUsageType::Static); @@ -34,13 +35,13 @@ void Mesh::Draw(FRenderState& renderstate) origState.applyData.RenderStyle = renderstate.mRenderStyle; origState.applyData.SpecialEffect = renderstate.mSpecialEffect; origState.applyData.TextureEnabled = renderstate.mTextureEnabled; - origState.applyData.AlphaThreshold = renderstate.mStreamData.uAlphaThreshold; + origState.applyData.AlphaThreshold = renderstate.mSurfaceUniforms.uAlphaThreshold; origState.applyData.FogEnabled = renderstate.mFogEnabled; origState.applyData.BrightmapEnabled = renderstate.mBrightmapEnabled; origState.applyData.TextureClamp = renderstate.mTextureClamp; origState.applyData.TextureMode = renderstate.mTextureMode; origState.applyData.TextureModeFlags = renderstate.mTextureModeFlags; - origState.streamData = renderstate.mStreamData; + origState.surfaceUniforms = renderstate.mSurfaceUniforms; origState.material = renderstate.mMaterial; origState.textureMatrix.loadIdentity(); @@ -105,7 +106,7 @@ void Mesh::Apply(FRenderState& renderstate, const MeshApplyState& state) renderstate.mTextureClamp = state.applyData.TextureClamp; renderstate.mTextureMode = state.applyData.TextureMode; renderstate.mTextureModeFlags = state.applyData.TextureModeFlags; - renderstate.mStreamData = state.streamData; + renderstate.mSurfaceUniforms = state.surfaceUniforms; renderstate.mMaterial = state.material; renderstate.SetTextureMatrix(state.textureMatrix); } diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp index 988f087a5b..6df23029e7 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp @@ -63,18 +63,19 @@ void MeshBuilder::Apply() state.applyData.RenderStyle = mRenderStyle; state.applyData.SpecialEffect = mSpecialEffect; state.applyData.TextureEnabled = mTextureEnabled; - state.applyData.AlphaThreshold = mStreamData.uAlphaThreshold; + state.applyData.AlphaThreshold = mSurfaceUniforms.uAlphaThreshold; state.applyData.DepthFunc = mDepthFunc; state.applyData.FogEnabled = mFogEnabled; + state.applyData.FogColor = (mFogColor & 0xffffff) == 0; state.applyData.BrightmapEnabled = mBrightmapEnabled; state.applyData.TextureClamp = mTextureClamp; state.applyData.TextureMode = mTextureMode; state.applyData.TextureModeFlags = mTextureModeFlags; - state.streamData = mStreamData; + state.surfaceUniforms = mSurfaceUniforms; state.material = mMaterial; state.textureMatrix = mTextureMatrix; - state.streamData.uVertexNormal = FVector4(0.0f, 0.0f, 0.0f, 0.0f); // Grr, this should be part of the vertex!! + state.surfaceUniforms.uVertexNormal = FVector4(0.0f, 0.0f, 0.0f, 0.0f); // Grr, this should be part of the vertex!! mDrawLists = &mSortedLists[state]; } diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h index c111caf3e1..dbe095e0f6 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h @@ -7,25 +7,26 @@ class Mesh; +struct MeshApplyData +{ + FRenderStyle RenderStyle; + int SpecialEffect; + int TextureEnabled; + float AlphaThreshold; + int DepthFunc; + int FogEnabled; + int FogColor; + int BrightmapEnabled; + int TextureClamp; + int TextureMode; + int TextureModeFlags; +}; + class MeshApplyState { public: - struct ApplyData - { - FRenderStyle RenderStyle; - int SpecialEffect; - int TextureEnabled; - float AlphaThreshold; - int DepthFunc; - int FogEnabled; - int BrightmapEnabled; - int TextureClamp; - int TextureMode; - int TextureModeFlags; - }; - - ApplyData applyData; - StreamData streamData; + MeshApplyData applyData; + SurfaceUniforms surfaceUniforms; FMaterialState material; VSMatrix textureMatrix; @@ -40,7 +41,7 @@ class MeshApplyState if (material.mOverrideShader != other.material.mOverrideShader) return material.mOverrideShader < other.material.mOverrideShader; - int result = memcmp(&applyData, &other.applyData, sizeof(ApplyData)); + int result = memcmp(&applyData, &other.applyData, sizeof(MeshApplyData)); if (result != 0) return result < 0; @@ -48,7 +49,7 @@ class MeshApplyState if (result != 0) return result < 0; - result = memcmp(&streamData, &other.streamData, sizeof(StreamData)); + result = memcmp(&surfaceUniforms, &other.surfaceUniforms, sizeof(SurfaceUniforms)); return result < 0; } }; @@ -80,6 +81,7 @@ class MeshBuilder : public FRenderState void SetTextureMatrix(const VSMatrix& matrix) override { mTextureMatrix = matrix; } int UploadLights(const FDynLightData& lightdata) override { return -1; } int UploadBones(const TArray& bones) override { return -1; } + int UploadFogballs(const TArray& balls) override { return -1; } // Draw commands void Draw(int dt, int index, int count, bool apply = true) override; @@ -106,20 +108,20 @@ class MeshBuilder : public FRenderState std::unique_ptr Create(); -private: - void Apply(); - struct DrawLists { TArray mDraws; TArray mIndexedDraws; }; std::map mSortedLists; - DrawLists* mDrawLists = nullptr; TArray mVertices; TArray mIndexes; - int mDepthFunc = 0; +private: + void Apply(); + + int mDepthFunc = 0; VSMatrix mTextureMatrix = VSMatrix::identity(); + DrawLists* mDrawLists = nullptr; }; diff --git a/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp index c6e0d97830..6de55d36d8 100644 --- a/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp @@ -41,10 +41,10 @@ FModelVertexBuffer::FModelVertexBuffer(bool needindex, bool singleframe) { static const FVertexBufferAttribute format[] = { - { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FModelVertex, x) }, + { 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FModelVertex, x) }, { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FModelVertex, u) }, { 0, VATTR_NORMAL, VFmt_Packed_A2R10G10B10, (int)myoffsetof(FModelVertex, packedNormal) }, - { 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FModelVertex, lu) }, + { 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FModelVertex, lu) }, { 0, VATTR_BONESELECTOR, VFmt_Byte4_UInt, (int)myoffsetof(FModelVertex, boneselector[0])}, { 0, VATTR_BONEWEIGHT, VFmt_Byte4, (int)myoffsetof(FModelVertex, boneweight[0]) }, { 1, VATTR_VERTEX2, VFmt_Float3, (int)myoffsetof(FModelVertex, x) }, diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index 7ac3662a25..06f79a56a3 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -3,12 +3,15 @@ #include "vectors.h" #include "matrix.h" #include "hw_material.h" +#include "hw_levelmesh.h" #include "texmanip.h" #include "version.h" #include "i_interface.h" #include "hw_viewpointuniforms.h" #include "hw_cvars.h" +#include + struct FColormap; class IBuffer; struct HWViewpointUniforms; @@ -28,6 +31,7 @@ enum ERenderEffect EFF_SPHEREMAP, EFF_BURN, EFF_STENCIL, + EFF_PORTAL, MAX_EFFECTS }; @@ -90,24 +94,6 @@ struct FStateVec4 } }; -struct FMaterialState -{ - FMaterial *mMaterial = nullptr; - int mClampMode; - int mTranslation; - int mOverrideShader; - bool mChanged; - - void Reset() - { - mMaterial = nullptr; - mTranslation = 0; - mClampMode = CLAMP_NONE; - mOverrideShader = -1; - mChanged = false; - } -}; - struct FDepthBiasState { float mFactor; @@ -131,94 +117,14 @@ enum EPassType MAX_PASS_TYPES }; -struct FVector4PalEntry -{ - float r, g, b, a; - - bool operator==(const FVector4PalEntry &other) const - { - return r == other.r && g == other.g && b == other.b && a == other.a; - } - - bool operator!=(const FVector4PalEntry &other) const - { - return r != other.r || g != other.g || b != other.b || a != other.a; - } - - FVector4PalEntry &operator=(PalEntry newvalue) - { - const float normScale = 1.0f / 255.0f; - r = newvalue.r * normScale; - g = newvalue.g * normScale; - b = newvalue.b * normScale; - a = newvalue.a * normScale; - return *this; - } - - FVector4PalEntry& SetIA(PalEntry newvalue) - { - const float normScale = 1.0f / 255.0f; - r = newvalue.r * normScale; - g = newvalue.g * normScale; - b = newvalue.b * normScale; - a = newvalue.a; - return *this; - } - - FVector4PalEntry& SetFlt(float v1, float v2, float v3, float v4) - { - r = v1; - g = v2; - b = v3; - a = v4; - return *this; - } - -}; +inline FVector4 toFVector4(PalEntry pe) { const float normScale = 1.0f / 255.0f; return FVector4(pe.r * normScale, pe.g * normScale, pe.b * normScale, pe.a * normScale); } -struct StreamData +struct Fogball { - FVector4PalEntry uObjectColor; - FVector4PalEntry uObjectColor2; - FVector4 uDynLightColor; - FVector4PalEntry uAddColor; - FVector4PalEntry uTextureAddColor; - FVector4PalEntry uTextureModulateColor; - FVector4PalEntry uTextureBlendColor; - FVector4PalEntry uFogColor; - float uDesaturationFactor; // HWDrawInfo::SetColor - float uInterpolationFactor; - float timer; - int useVertexData; - FVector4 uVertexColor; // HWDrawInfo::SetColor - FVector4 uVertexNormal; - - FVector4 uGlowTopPlane; - FVector4 uGlowTopColor; - FVector4 uGlowBottomPlane; - FVector4 uGlowBottomColor; - - FVector4 uGradientTopPlane; - FVector4 uGradientBottomPlane; - - FVector4 uSplitTopPlane; - FVector4 uSplitBottomPlane; - - FVector4 uDetailParms; - FVector4 uNpotEmulation; - - FVector2 uClipSplit; - FVector2 uSpecularMaterial; - - float uLightLevel; // HWDrawInfo::SetColor - float uFogDensity; - float uLightFactor; - float uLightDist; - - float uAlphaThreshold; - float padding1; - float padding2; - float padding3; + FVector3 Position; + float Radius; + FVector3 Color; + float Fog; }; class FRenderState @@ -233,6 +139,7 @@ class FRenderState int mLightIndex; int mBoneIndexBase; + int mFogballIndex; int mSpecialEffect; int mTextureMode; int mTextureClamp; @@ -243,7 +150,7 @@ class FRenderState int mColorMapSpecial; float mColorMapFlash; - StreamData mStreamData = {}; + SurfaceUniforms mSurfaceUniforms = {}; PalEntry mFogColor; FRenderStyle mRenderStyle; @@ -266,28 +173,29 @@ class FRenderState mTextureEnabled = true; mBrightmapEnabled = mGradientEnabled = mFogEnabled = mGlowEnabled = false; mFogColor = 0xffffffff; - mStreamData.uFogColor = mFogColor; + mSurfaceUniforms.uFogColor = toFVector4(mFogColor); mTextureMode = -1; mTextureClamp = 0; mTextureModeFlags = 0; - mStreamData.uDesaturationFactor = 0.0f; - mStreamData.uAlphaThreshold = 0.5f; + mSurfaceUniforms.uDesaturationFactor = 0.0f; + mSurfaceUniforms.uAlphaThreshold = 0.5f; mSplitEnabled = false; - mStreamData.uAddColor = 0; - mStreamData.uObjectColor = 0xffffffff; - mStreamData.uObjectColor2 = 0; - mStreamData.uTextureBlendColor = 0; - mStreamData.uTextureAddColor = 0; - mStreamData.uTextureModulateColor = 0; + mSurfaceUniforms.uAddColor = toFVector4(PalEntry(0)); + mSurfaceUniforms.uObjectColor = toFVector4(PalEntry(0xffffffff)); + mSurfaceUniforms.uObjectColor2 = toFVector4(PalEntry(0)); + mSurfaceUniforms.uTextureBlendColor = toFVector4(PalEntry(0)); + mSurfaceUniforms.uTextureAddColor = toFVector4(PalEntry(0)); + mSurfaceUniforms.uTextureModulateColor = toFVector4(PalEntry(0)); mSoftLight = 0; - mStreamData.uLightDist = 0.0f; - mStreamData.uLightFactor = 0.0f; - mStreamData.uFogDensity = 0.0f; - mStreamData.uLightLevel = -1.0f; + mSurfaceUniforms.uLightDist = 0.0f; + mSurfaceUniforms.uLightFactor = 0.0f; + mSurfaceUniforms.uFogDensity = 0.0f; + mSurfaceUniforms.uLightLevel = -1.0f; mSpecialEffect = EFF_NONE; mLightIndex = -1; mBoneIndexBase = -1; - mStreamData.uInterpolationFactor = 0; + mFogballIndex = -1; + mSurfaceUniforms.uInterpolationFactor = 0; mRenderStyle = DefaultRenderStyle(); mMaterial.Reset(); mBias.Reset(); @@ -300,57 +208,57 @@ class FRenderState mVertexOffsets[0] = mVertexOffsets[1] = 0; mIndexBuffer = nullptr; - mStreamData.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f }; - mStreamData.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGlowTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGlowBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGradientTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGradientBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f }; - mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f }; + mSurfaceUniforms.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uGlowTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uGlowBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uGradientTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uGradientBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f }; + mSurfaceUniforms.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f }; #ifdef NPOT_EMULATION - mStreamData.uNpotEmulation = { 0,0,0,0 }; + mSurfaceUniforms.uNpotEmulation = { 0,0,0,0 }; #endif ClearClipSplit(); } void SetNormal(FVector3 norm) { - mStreamData.uVertexNormal = { norm.X, norm.Y, norm.Z, 0.f }; + mSurfaceUniforms.uVertexNormal = { norm.X, norm.Y, norm.Z, 0.f }; } void SetNormal(float x, float y, float z) { - mStreamData.uVertexNormal = { x, y, z, 0.f }; + mSurfaceUniforms.uVertexNormal = { x, y, z, 0.f }; } void SetColor(float r, float g, float b, float a = 1.f, int desat = 0) { - mStreamData.uVertexColor = { r, g, b, a }; - mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + mSurfaceUniforms.uVertexColor = { r, g, b, a }; + mSurfaceUniforms.uDesaturationFactor = desat * (1.0f / 255.0f); } void SetColor(PalEntry pe, int desat = 0) { const float scale = 1.0f / 255.0f; - mStreamData.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, pe.a * scale }; - mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + mSurfaceUniforms.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, pe.a * scale }; + mSurfaceUniforms.uDesaturationFactor = desat * (1.0f / 255.0f); } void SetColorAlpha(PalEntry pe, float alpha = 1.f, int desat = 0) { const float scale = 1.0f / 255.0f; - mStreamData.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, alpha }; - mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + mSurfaceUniforms.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, alpha }; + mSurfaceUniforms.uDesaturationFactor = desat * (1.0f / 255.0f); } void ResetColor() { - mStreamData.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f }; - mStreamData.uDesaturationFactor = 0.0f; + mSurfaceUniforms.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f }; + mSurfaceUniforms.uDesaturationFactor = 0.0f; } void SetTextureClamp(bool on) @@ -412,8 +320,8 @@ class FRenderState { if (mGlowEnabled && !on) { - mStreamData.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f }; } mGlowEnabled = on; } @@ -432,27 +340,27 @@ class FRenderState { if (mSplitEnabled && !on) { - mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mSurfaceUniforms.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; } mSplitEnabled = on; } void SetGlowParams(float *t, float *b) { - mStreamData.uGlowTopColor = { t[0], t[1], t[2], t[3] }; - mStreamData.uGlowBottomColor = { b[0], b[1], b[2], b[3] }; + mSurfaceUniforms.uGlowTopColor = { t[0], t[1], t[2], t[3] }; + mSurfaceUniforms.uGlowBottomColor = { b[0], b[1], b[2], b[3] }; } void SetSoftLightLevel(int llevel, int blendfactor = 0) { - if (blendfactor == 0) mStreamData.uLightLevel = llevel / 255.f; - else mStreamData.uLightLevel = -1.f; + if (blendfactor == 0) mSurfaceUniforms.uLightLevel = llevel / 255.f; + else mSurfaceUniforms.uLightLevel = -1.f; } void SetNoSoftLightLevel() { - mStreamData.uLightLevel = -1.f; + mSurfaceUniforms.uLightLevel = -1.f; } void SetLightMode(int lightmode) @@ -462,59 +370,59 @@ class FRenderState void SetGlowPlanes(const FVector4 &tp, const FVector4& bp) { - mStreamData.uGlowTopPlane = tp; - mStreamData.uGlowBottomPlane = bp; + mSurfaceUniforms.uGlowTopPlane = tp; + mSurfaceUniforms.uGlowBottomPlane = bp; } void SetGradientPlanes(const FVector4& tp, const FVector4& bp) { - mStreamData.uGradientTopPlane = tp; - mStreamData.uGradientBottomPlane = bp; + mSurfaceUniforms.uGradientTopPlane = tp; + mSurfaceUniforms.uGradientBottomPlane = bp; } void SetSplitPlanes(const FVector4& tp, const FVector4& bp) { - mStreamData.uSplitTopPlane = tp; - mStreamData.uSplitBottomPlane = bp; + mSurfaceUniforms.uSplitTopPlane = tp; + mSurfaceUniforms.uSplitBottomPlane = bp; } void SetDetailParms(float xscale, float yscale, float bias) { - mStreamData.uDetailParms = { xscale, yscale, bias, 0 }; + mSurfaceUniforms.uDetailParms = { xscale, yscale, bias, 0 }; } void SetDynLight(float r, float g, float b) { - mStreamData.uDynLightColor.X = r; - mStreamData.uDynLightColor.Y = g; - mStreamData.uDynLightColor.Z = b; + mSurfaceUniforms.uDynLightColor.X = r; + mSurfaceUniforms.uDynLightColor.Y = g; + mSurfaceUniforms.uDynLightColor.Z = b; } void SetScreenFade(float f) { // This component is otherwise unused. - mStreamData.uDynLightColor.W = f; + mSurfaceUniforms.uDynLightColor.W = f; } void SetObjectColor(PalEntry pe) { - mStreamData.uObjectColor = pe; + mSurfaceUniforms.uObjectColor = toFVector4(pe); } void SetObjectColor2(PalEntry pe) { - mStreamData.uObjectColor2 = pe; + mSurfaceUniforms.uObjectColor2 = toFVector4(pe); } void SetAddColor(PalEntry pe) { - mStreamData.uAddColor = pe; + mSurfaceUniforms.uAddColor = toFVector4(pe); } void SetNpotEmulation(float factor, float offset) { #ifdef NPOT_EMULATION - mStreamData.uNpotEmulation = { offset, factor, 0, 0 }; + mSurfaceUniforms.uNpotEmulation = { offset, factor, 0, 0 }; #endif } @@ -522,36 +430,37 @@ class FRenderState { if (!texfx || texfx->AddColor.a == 0) { - mStreamData.uTextureAddColor.a = 0; // we only need to set the flags to 0 + mSurfaceUniforms.uTextureAddColor.W = 0.0f; // we only need to set the flags to 0 } else { // set up the whole thing - mStreamData.uTextureAddColor.SetIA(texfx->AddColor); + const float normScale = 1.0f / 255.0f; + mSurfaceUniforms.uTextureAddColor = FVector4(texfx->AddColor.r * normScale, texfx->AddColor.g * normScale, texfx->AddColor.b * normScale, texfx->AddColor.a); auto pe = texfx->ModulateColor; - mStreamData.uTextureModulateColor.SetFlt(pe.r * pe.a / 255.f, pe.g * pe.a / 255.f, pe.b * pe.a / 255.f, texfx->DesaturationFactor); - mStreamData.uTextureBlendColor = texfx->BlendColor; + mSurfaceUniforms.uTextureModulateColor = FVector4(pe.r * pe.a / 255.f, pe.g * pe.a / 255.f, pe.b * pe.a / 255.f, texfx->DesaturationFactor); + mSurfaceUniforms.uTextureBlendColor = toFVector4(texfx->BlendColor); } } void SetTextureColors(float* modColor, float* addColor, float* blendColor) { - mStreamData.uTextureAddColor.SetFlt(addColor[0], addColor[1], addColor[2], addColor[3]); - mStreamData.uTextureModulateColor.SetFlt(modColor[0], modColor[1], modColor[2], modColor[3]); - mStreamData.uTextureBlendColor.SetFlt(blendColor[0], blendColor[1], blendColor[2], blendColor[3]); + mSurfaceUniforms.uTextureAddColor = FVector4(addColor[0], addColor[1], addColor[2], addColor[3]); + mSurfaceUniforms.uTextureModulateColor = FVector4(modColor[0], modColor[1], modColor[2], modColor[3]); + mSurfaceUniforms.uTextureBlendColor = FVector4(blendColor[0], blendColor[1], blendColor[2], blendColor[3]); } void SetFog(PalEntry c, float d) { const float LOG2E = 1.442692f; // = 1/log(2) mFogColor = c; - mStreamData.uFogColor = mFogColor; - if (d >= 0.0f) mStreamData.uFogDensity = d * (-LOG2E / 64000.f); + mSurfaceUniforms.uFogColor = toFVector4(mFogColor); + if (d >= 0.0f) mSurfaceUniforms.uFogDensity = d * (-LOG2E / 64000.f); } void SetLightParms(float f, float d) { - mStreamData.uLightFactor = f; - mStreamData.uLightDist = d; + mSurfaceUniforms.uLightFactor = f; + mSurfaceUniforms.uLightDist = d; } PalEntry GetFogColor() const @@ -561,8 +470,8 @@ class FRenderState void AlphaFunc(int func, float thresh) { - if (func == Alpha_Greater) mStreamData.uAlphaThreshold = thresh; - else mStreamData.uAlphaThreshold = thresh - 0.001f; + if (func == Alpha_Greater) mSurfaceUniforms.uAlphaThreshold = thresh; + else mSurfaceUniforms.uAlphaThreshold = thresh - 0.001f; } void SetLightIndex(int index) @@ -575,6 +484,11 @@ class FRenderState mBoneIndexBase = index; } + void SetFogballIndex(int index) + { + mFogballIndex = index; + } + void SetRenderStyle(FRenderStyle rs) { mRenderStyle = rs; @@ -619,7 +533,7 @@ class FRenderState mMaterial.mChanged = true; mTextureModeFlags = mat->GetLayerFlags(); auto scale = mat->GetDetailScale(); - mStreamData.uDetailParms = { scale.X, scale.Y, 2, 0 }; + mSurfaceUniforms.uDetailParms = { scale.X, scale.Y, 2, 0 }; } public: @@ -635,28 +549,34 @@ class FRenderState SetMaterial(mat, clampmode, translation, overrideshader); } + void SetMaterial(FGameTexture* tex, EUpscaleFlags upscalemask, int scaleflags, int clampmode, FTranslationID translation, int overrideshader) + { + SetMaterial(tex, upscalemask, scaleflags, clampmode, translation.index(), overrideshader); + } + + void SetClipSplit(float bottom, float top) { - mStreamData.uClipSplit.X = bottom; - mStreamData.uClipSplit.Y = top; + mSurfaceUniforms.uClipSplit.X = bottom; + mSurfaceUniforms.uClipSplit.Y = top; } void SetClipSplit(float *vals) { - mStreamData.uClipSplit.X = vals[0]; - mStreamData.uClipSplit.Y = vals[1]; + mSurfaceUniforms.uClipSplit.X = vals[0]; + mSurfaceUniforms.uClipSplit.Y = vals[1]; } void GetClipSplit(float *out) { - out[0] = mStreamData.uClipSplit.X; - out[1] = mStreamData.uClipSplit.Y; + out[0] = mSurfaceUniforms.uClipSplit.X; + out[1] = mSurfaceUniforms.uClipSplit.Y; } void ClearClipSplit() { - mStreamData.uClipSplit.X = -1000000.f; - mStreamData.uClipSplit.Y = 1000000.f; + mSurfaceUniforms.uClipSplit.X = -1000000.f; + mSurfaceUniforms.uClipSplit.Y = 1000000.f; } void SetVertexBuffer(IBuffer* vb, int offset0 = 0, int offset1 = 0) @@ -679,12 +599,12 @@ class FRenderState void SetInterpolationFactor(float fac) { - mStreamData.uInterpolationFactor = fac; + mSurfaceUniforms.uInterpolationFactor = fac; } float GetInterpolationFactor() { - return mStreamData.uInterpolationFactor; + return mSurfaceUniforms.uInterpolationFactor; } void EnableDrawBufferAttachments(bool on) // Used by fog boundary drawer @@ -722,7 +642,7 @@ class FRenderState matrices.mGlobVis = 1.f; matrices.mPalLightLevels = palLightLevels; matrices.mClipLine.X = -10000000.0f; - matrices.mShadowmapFilter = gl_shadowmap_filter; + matrices.mShadowFilter = gl_light_shadow_filter; matrices.mLightBlendMode = 0; matrices.mProjectionMatrix.ortho(0, (float)width, (float)height, 0, -1.0f, 1.0f); matrices.CalcDependencies(); @@ -747,6 +667,7 @@ class FRenderState virtual void SetTextureMatrix(const VSMatrix& matrix) = 0; virtual int UploadLights(const FDynLightData& lightdata) = 0; virtual int UploadBones(const TArray& bones) = 0; + virtual int UploadFogballs(const TArray& balls) = 0; // Draw commands virtual void ClearScreen() = 0; @@ -774,6 +695,14 @@ class FRenderState SetColorMask(on, on, on, on); } + // Draw level mesh + virtual void DrawLevelMeshSurfaces(bool noFragmentShader) { } + virtual void DrawLevelMeshPortals(bool noFragmentShader) { } + virtual int GetNextQueryIndex() { return 0; } + virtual void BeginQuery() { } + virtual void EndQuery() { } + virtual void GetQueryResults(int start, int count, TArray& results) { } + friend class Mesh; }; diff --git a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp index fc66d63def..aaa32749a1 100644 --- a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp +++ b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp @@ -188,7 +188,7 @@ FString RemoveSamplerBindings(FString code, TArray> &sam FString type = NextGlslToken(chars, len, pos); FString identifier = NextGlslToken(chars, len, pos); - isSamplerUniformName = uniform.Compare("uniform") == 0 && isShaderType(type); + isSamplerUniformName = uniform.Compare("uniform") == 0 && isShaderType(type.GetChars()); if (isSamplerUniformName) { samplerstobind.Push(std::make_pair(identifier, val)); @@ -246,7 +246,7 @@ FString RemoveLayoutLocationDecl(FString code, const char *inoutkeyword) // keyword following the declaration? bool keywordFound = true; - long i; + ptrdiff_t i; for (i = 0; inoutkeyword[i] != 0; i++) { if (chars[endIndex + i] != inoutkeyword[i]) diff --git a/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp b/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp index 70eb42208b..bfb25e5137 100644 --- a/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp +++ b/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp @@ -59,9 +59,6 @@ cycle_t ShadowMap::UpdateCycles; int ShadowMap::LightsProcessed; int ShadowMap::LightsShadowmapped; -CVAR(Bool, gl_light_shadowmap, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -CVAR(Bool, gl_light_raytrace, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) - ADD_STAT(shadowmap) { FString out; @@ -69,24 +66,9 @@ ADD_STAT(shadowmap) return out; } -CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - switch (self) - { - case 128: - case 256: - case 512: - case 1024: - break; - default: - self = 128; - break; - } -} - bool ShadowMap::ShadowTest(const DVector3 &lpos, const DVector3 &pos) { - if (mAABBTree && gl_light_shadowmap) + if (mAABBTree && gl_light_shadows > 0) return mAABBTree->RayTest(lpos, pos) >= 1.0f; else return true; diff --git a/src/common/rendering/hwrenderer/data/hw_skydome.cpp b/src/common/rendering/hwrenderer/data/hw_skydome.cpp index cd8807b134..26aa292551 100644 --- a/src/common/rendering/hwrenderer/data/hw_skydome.cpp +++ b/src/common/rendering/hwrenderer/data/hw_skydome.cpp @@ -66,7 +66,7 @@ //----------------------------------------------------------------------------- // -// Shamelessly lifted from Doomsday (written by Jaakko Kernen) +// Shamelessly lifted from Doomsday (written by Jaakko Keränen) // also shamelessly lifted from ZDoomGL! ;) // //----------------------------------------------------------------------------- @@ -124,10 +124,10 @@ FSkyVertexBuffer::FSkyVertexBuffer(DFrameBuffer* fb) : fb(fb) CreateDome(); static const FVertexBufferAttribute format[] = { - { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FSkyVertex, x) }, + { 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FSkyVertex, x) }, { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FSkyVertex, u) }, { 0, VATTR_COLOR, VFmt_Byte4, (int)myoffsetof(FSkyVertex, color) }, - { 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FSkyVertex, lu) }, + { 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FSkyVertex, lu) }, }; mVertexBuffer = fb->CreateVertexBuffer(1, 4, sizeof(FSkyVertex), format); mVertexBuffer->SetData(mVertices.Size() * sizeof(FSkyVertex), &mVertices[0], BufferUsageType::Static); @@ -178,6 +178,8 @@ void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip) vert.y = z - 1.f; vert.z = pos.Y; + vert.lindex = -1; + mVertices.Push(vert); } @@ -210,6 +212,8 @@ void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip) vert.y = z - 1.f; vert.z = pos.Y; + vert.lindex = -1; + mVertices.Push(vert); } diff --git a/src/common/rendering/hwrenderer/data/hw_skydome.h b/src/common/rendering/hwrenderer/data/hw_skydome.h index 7bd4022895..400c9f0611 100644 --- a/src/common/rendering/hwrenderer/data/hw_skydome.h +++ b/src/common/rendering/hwrenderer/data/hw_skydome.h @@ -17,7 +17,7 @@ const int skyoffsetfactor = 57; struct FSkyVertex { - float x, y, z, u, v, lu, lv, lindex; + float x, y, z, lindex, u, v, lu, lv; PalEntry color; void Set(float xx, float zz, float yy, float uu=0, float vv=0, PalEntry col=0xffffffff) diff --git a/src/common/rendering/hwrenderer/data/hw_surfaceuniforms.h b/src/common/rendering/hwrenderer/data/hw_surfaceuniforms.h new file mode 100644 index 0000000000..5705c9a8d4 --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_surfaceuniforms.h @@ -0,0 +1,49 @@ + +#pragma once + +#include "vectors.h" + +struct SurfaceUniforms +{ + FVector4 uObjectColor; + FVector4 uObjectColor2; + FVector4 uDynLightColor; + FVector4 uAddColor; + FVector4 uTextureAddColor; + FVector4 uTextureModulateColor; + FVector4 uTextureBlendColor; + FVector4 uFogColor; + float uDesaturationFactor; // HWDrawInfo::SetColor + float uInterpolationFactor; + float timer; + int useVertexData; + FVector4 uVertexColor; // HWDrawInfo::SetColor + FVector4 uVertexNormal; + + FVector4 uGlowTopPlane; + FVector4 uGlowTopColor; + FVector4 uGlowBottomPlane; + FVector4 uGlowBottomColor; + + FVector4 uGradientTopPlane; + FVector4 uGradientBottomPlane; + + FVector4 uSplitTopPlane; + FVector4 uSplitBottomPlane; + + FVector4 uDetailParms; + FVector4 uNpotEmulation; + + FVector2 uClipSplit; + FVector2 uSpecularMaterial; + + float uLightLevel; // HWDrawInfo::SetColor + float uFogDensity; + float uLightFactor; + float uLightDist; + + float uAlphaThreshold; + int uTextureIndex; + float padding2; + float padding3; +}; diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h b/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h index def3b48089..bdbc917074 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h +++ b/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h @@ -26,7 +26,7 @@ struct HWViewpointUniforms int mViewHeight = 0; float mClipHeight = 0.f; float mClipHeightDirection = 0.f; - int mShadowmapFilter = 1; + int mShadowFilter = 1; int mLightBlendMode = 0; diff --git a/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp b/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp index ac80eec545..c51ce2ee90 100644 --- a/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp +++ b/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp @@ -34,7 +34,7 @@ ** */ -#include "vectors.h" // RAD2DEG +#include "vectors.h" #include "hw_cvars.h" #include "hw_vrmodes.h" #include "v_video.h" @@ -67,6 +67,16 @@ static VRMode vrmi_righteye = { 1, 1.f, 1.f, 1.f,{ { .5f, 1.f },{ 0.f, 0.f } } } static VRMode vrmi_topbottom = { 2, 1.f, .5f, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } }; static VRMode vrmi_checker = { 2, isqrt2, isqrt2, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } }; +static float DEG2RAD(float deg) +{ + return deg * float(M_PI / 180.0); +} + +static float RAD2DEG(float rad) +{ + return rad * float(180. / M_PI); +} + const VRMode *VRMode::GetVRMode(bool toscreen) { int mode = !toscreen || (sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter()) ? 0 : vr_mode; diff --git a/src/common/rendering/hwrenderer/hw_draw2d.cpp b/src/common/rendering/hwrenderer/hw_draw2d.cpp index 6300d6d025..4f556e77dc 100644 --- a/src/common/rendering/hwrenderer/hw_draw2d.cpp +++ b/src/common/rendering/hwrenderer/hw_draw2d.cpp @@ -213,7 +213,7 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int state.SetIndexBuffer(buffers.GetBufferObjects().second); state.DrawIndexed(DT_Triangles, 0, cmd.shape2DIndexCount); state.SetVertexBuffer(vb.GetBufferObjects().first); - state.SetVertexBuffer(vb.GetBufferObjects().second); + state.SetIndexBuffer(vb.GetBufferObjects().second); if (cmd.shape2DCommandCounter == cmd.shape2DBufInfo->lastCommand) { cmd.shape2DBufInfo->lastCommand = -1; diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp index fab2db9646..784a1aefc2 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp @@ -389,7 +389,7 @@ void PPFXAA::Render(PPRenderState *renderstate) int PPFXAA::GetMaxVersion() { - return screen->glslversion >= 4.f ? 400 : 330; + return 460; } void PPFXAA::CreateShaders() @@ -722,7 +722,7 @@ void PPAmbientOcclusion::UpdateTextures(int width, int height) void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneWidth, int sceneHeight) { - if (gl_ssao == 0 || sceneWidth == 0 || sceneHeight == 0) + if ((gl_ssao == 0 && !gl_shownormals) || sceneWidth == 0 || sceneHeight == 0) { return; } @@ -813,7 +813,7 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW renderstate->Draw(); // Blur SSAO texture - if (gl_ssao_debug < 2) + if (gl_ssao_debug < 2 && !gl_shownormals) { renderstate->Clear(); renderstate->Shader = &BlurHorizontal; @@ -839,13 +839,13 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW renderstate->Shader = gl_multisample > 1 ? &CombineMS : &Combine; renderstate->Uniforms.Set(combineUniforms); renderstate->Viewport = screen->mSceneViewport; - if (gl_ssao_debug < 4) - renderstate->SetInputTexture(0, &Ambient0, PPFilterMode::Linear); + renderstate->SetInputTexture(0, &Ambient0, PPFilterMode::Linear); + if (gl_ssao_debug < 4 && !gl_shownormals) + renderstate->SetInputSceneFog(1); else - renderstate->SetInputSceneNormal(0, PPFilterMode::Linear); - renderstate->SetInputSceneFog(1); + renderstate->SetInputSceneNormal(1, PPFilterMode::Linear); renderstate->SetOutputSceneColor(); - if (gl_ssao_debug != 0) + if (gl_ssao_debug != 0 || gl_shownormals) renderstate->SetNoBlend(); else renderstate->SetAlphaBlend(); @@ -1016,7 +1016,7 @@ void PPCustomShaderInstance::SetTextures(PPRenderState *renderstate) while (it.NextPair(pair)) { FString name = pair->Value; - auto gtex = TexMan.GetGameTexture(TexMan.CheckForTexture(name, ETextureType::Any), true); + auto gtex = TexMan.GetGameTexture(TexMan.CheckForTexture(name.GetChars(), ETextureType::Any), true); if (gtex && gtex->isValid()) { // Why does this completely circumvent the normal way of handling textures? diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp index 4f6334a12e..d2dec62a5c 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp @@ -72,6 +72,7 @@ CUSTOM_CVAR(Int, gl_ssao_portals, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Float, gl_ssao_strength, 0.7f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Int, gl_ssao_debug, 0, 0) +CVAR(Bool, gl_shownormals, false, 0) CVAR(Float, gl_ssao_bias, 0.2f, 0) CVAR(Float, gl_ssao_radius, 80.0f, 0) CUSTOM_CVAR(Float, gl_ssao_blur, 16.0f, 0) diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h index 523b8d8d02..7ecbd4f84c 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h @@ -1,5 +1,8 @@ #pragma once +#include "zstring.h" +#include "tarray.h" + enum class PostProcessUniformType { Undefined, diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp index 4608b9ce96..7ab93b3ec5 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp @@ -39,7 +39,7 @@ CCMD (shaderenable) for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) { PostProcessShader &shader = PostProcessShaders[i]; - if (strcmp(shader.Name, shaderName) == 0) + if (shader.Name.Compare(shaderName) == 0) { if (value != -1) shader.Enabled = value; @@ -70,7 +70,7 @@ CCMD (shaderuniform) for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) { PostProcessShader &shader = PostProcessShaders[i]; - if (strcmp(shader.Name, shaderName) == 0) + if (shader.Name.Compare(shaderName) == 0) { if (argv.argc() > 3) { @@ -116,7 +116,7 @@ CCMD(listuniforms) for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) { PostProcessShader &shader = PostProcessShaders[i]; - if (strcmp(shader.Name, shaderName) == 0) + if (shader.Name.Compare(shaderName) == 0) { Printf("Shader '%s' uniforms:\n", shaderName); diff --git a/src/common/rendering/i_modelvertexbuffer.h b/src/common/rendering/i_modelvertexbuffer.h index f68d4e1179..1d1bed9c42 100644 --- a/src/common/rendering/i_modelvertexbuffer.h +++ b/src/common/rendering/i_modelvertexbuffer.h @@ -1,14 +1,15 @@ #pragma once +#include "basics.h" struct FModelVertex { float x, y, z; // world position + float lindex; // lightmap texture index float u, v; // texture coordinates unsigned packedNormal; // normal vector as GL_INT_2_10_10_10_REV. float lu, lv; // lightmap texture coordinates - float lindex; // lightmap texture index uint8_t boneselector[4]; uint8_t boneweight[4]; diff --git a/src/common/rendering/v_video.cpp b/src/common/rendering/v_video.cpp index ba04006a10..35a54e107e 100644 --- a/src/common/rendering/v_video.cpp +++ b/src/common/rendering/v_video.cpp @@ -81,7 +81,7 @@ CUSTOM_CVAR(Int, gl_pipeline_depth, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_N Printf("Changing the pipeline depth requires a restart for " GAMENAME ".\n"); } -CUSTOM_CVAR(Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, vid_maxfps, 500, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (self < GameTicRate && self != 0) { @@ -93,7 +93,6 @@ CUSTOM_CVAR(Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) } } - CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL) { if (self < 0) diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index a4e75ecfd3..721347e873 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -45,6 +45,7 @@ #include "hw_shadowmap.h" #include "hw_levelmesh.h" #include "buffers.h" +#include "files.h" struct FPortalSceneState; @@ -55,22 +56,6 @@ class FMaterial; class FGameTexture; class FRenderState; -enum EHWCaps -{ - // [BB] Added texture compression flags. - RFL_TEXTURE_COMPRESSION = 1, - RFL_TEXTURE_COMPRESSION_S3TC = 2, - - RFL_SHADER_STORAGE_BUFFER = 4, - RFL_BUFFER_STORAGE = 8, - - RFL_NO_CLIP_PLANES = 32, - - RFL_INVALIDATE_BUFFER = 64, - RFL_DEBUG = 128, -}; - - extern int DisplayWidth, DisplayHeight; void V_UpdateModeSize (int width, int height); @@ -84,11 +69,11 @@ EXTERN_CVAR(Int, win_h) EXTERN_CVAR(Bool, win_maximized) struct FColormap; -class FileWriter; enum FTextureFormat : uint32_t; class FModelRenderer; struct SamplerUniform; struct FVertexBufferAttribute; +struct MeshApplyData; // // VIDEO @@ -128,8 +113,6 @@ class DFrameBuffer public: // Hardware render state that needs to be exposed to the API independent part of the renderer. For ease of access this is stored in the base class. - int hwcaps = 0; // Capability flags - float glslversion = 0; // This is here so that the differences between old OpenGL and new OpenGL/Vulkan can be handled by platform independent code. int instack[2] = { 0,0 }; // this is globally maintained state for portal recursion avoidance. int stencilValue = 0; // Global stencil test value unsigned int uniformblockalignment = 256; // Hardware dependent uniform buffer alignment. @@ -155,21 +138,8 @@ class DFrameBuffer virtual bool IsVulkan() { return false; } virtual bool IsPoly() { return false; } virtual bool CompileNextShader() { return true; } - virtual void SetLevelMesh(hwrenderer::LevelMesh *mesh) { } - bool allowSSBO() const - { -#ifndef HW_BLOCK_SSBO - return true; -#else - return mPipelineType == 0; -#endif - } - - // SSBOs have quite worse performance for read only data, so keep this around only as long as Vulkan has not been adapted yet. - bool useSSBO() - { - return IsVulkan(); - } + virtual void SetLevelMesh(LevelMesh *mesh) { } + virtual void UpdateLightmaps(const TArray& tiles) {} virtual DCanvas* GetCanvas() { return nullptr; } @@ -214,18 +184,15 @@ class DFrameBuffer virtual void BeginFrame() {} virtual void SetWindowSize(int w, int h) {} virtual void StartPrecaching() {} - virtual FRenderState* RenderState(int threadIndex) { return nullptr; } + virtual FRenderState* RenderState() { return nullptr; } virtual int GetClientWidth() = 0; virtual int GetClientHeight() = 0; virtual void BlurScene(float amount) {} - virtual void InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData) {} - // Interface to hardware rendering resources virtual IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs) { return nullptr; } virtual IBuffer* CreateIndexBuffer() { return nullptr; } - bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); } // This is overridable in case Vulkan does it differently. virtual bool RenderTextureIsFlipped() const @@ -250,12 +217,17 @@ class DFrameBuffer virtual void RenderTextureView(FCanvasTexture* tex, std::function renderFunc) {} virtual void SetActiveRenderTarget() {} + // Get the array index for the material in the textures array accessible from shaders + virtual int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation) { return -1; } + // Screen wiping virtual FTexture *WipeStartScreen(); virtual FTexture *WipeEndScreen(); virtual void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) { if (afterBloomDrawEndScene2D) afterBloomDrawEndScene2D(); } + virtual int GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material) { return 0; } + void ScaleCoordsFromWindow(int16_t &x, int16_t &y); virtual void Draw2D() {} @@ -277,8 +249,6 @@ class DFrameBuffer uint64_t FrameTime = 0; uint64_t FrameTimeNS = 0; - int MaxThreads = 8; // To do: this may need to be limited by how much memory is available for dedicated buffer mapping (i.e. is resizeable bar available or not) - private: uint64_t fpsLimitTime = 0; diff --git a/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp b/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp deleted file mode 100644 index 06fa0e2a8a..0000000000 --- a/src/common/rendering/vulkan/accelstructs/vk_raytrace.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* -** Vulkan backend -** Copyright (c) 2016-2020 Magnus Norddahl -** -** 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. -** -*/ - -#include "vk_raytrace.h" -#include "zvulkan/vulkanbuilders.h" -#include "vulkan/vk_renderdevice.h" -#include "vulkan/commands/vk_commandbuffer.h" -#include "hw_levelmesh.h" - -VkRaytrace::VkRaytrace(VulkanRenderDevice* fb) : fb(fb) -{ - useRayQuery = fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME); - - NullMesh.MeshVertices.Push({ -1.0f, -1.0f, -1.0f }); - NullMesh.MeshVertices.Push({ 1.0f, -1.0f, -1.0f }); - NullMesh.MeshVertices.Push({ 1.0f, 1.0f, -1.0f }); - NullMesh.MeshVertices.Push({ -1.0f, -1.0f, -1.0f }); - NullMesh.MeshVertices.Push({ -1.0f, 1.0f, -1.0f }); - NullMesh.MeshVertices.Push({ 1.0f, 1.0f, -1.0f }); - NullMesh.MeshVertices.Push({ -1.0f, -1.0f, 1.0f }); - NullMesh.MeshVertices.Push({ 1.0f, -1.0f, 1.0f }); - NullMesh.MeshVertices.Push({ 1.0f, 1.0f, 1.0f }); - NullMesh.MeshVertices.Push({ -1.0f, -1.0f, 1.0f }); - NullMesh.MeshVertices.Push({ -1.0f, 1.0f, 1.0f }); - NullMesh.MeshVertices.Push({ 1.0f, 1.0f, 1.0f }); - for (int i = 0; i < 3 * 4; i++) - NullMesh.MeshElements.Push(i); - - NullMesh.Collision = std::make_unique(NullMesh.MeshVertices.Data(), NullMesh.MeshVertices.Size(), NullMesh.MeshElements.Data(), NullMesh.MeshElements.Size()); - - SetLevelMesh(nullptr); -} - -void VkRaytrace::SetLevelMesh(hwrenderer::LevelMesh* mesh) -{ - if (!mesh) - mesh = &NullMesh; - - if (mesh != Mesh) - { - Reset(); - Mesh = mesh; - CreateVulkanObjects(); - } -} - -void VkRaytrace::Reset() -{ - auto deletelist = fb->GetCommands()->DrawDeleteList.get(); - deletelist->Add(std::move(vertexBuffer)); - deletelist->Add(std::move(indexBuffer)); - deletelist->Add(std::move(transferBuffer)); - deletelist->Add(std::move(nodesBuffer)); - deletelist->Add(std::move(blScratchBuffer)); - deletelist->Add(std::move(blAccelStructBuffer)); - deletelist->Add(std::move(blAccelStruct)); - deletelist->Add(std::move(tlTransferBuffer)); - deletelist->Add(std::move(tlScratchBuffer)); - deletelist->Add(std::move(tlInstanceBuffer)); - deletelist->Add(std::move(tlAccelStructBuffer)); - deletelist->Add(std::move(tlAccelStruct)); -} - -void VkRaytrace::CreateVulkanObjects() -{ - CreateVertexAndIndexBuffers(); - if (useRayQuery) - { - CreateBottomLevelAccelerationStructure(); - CreateTopLevelAccelerationStructure(); - } -} - -void VkRaytrace::CreateVertexAndIndexBuffers() -{ - std::vector nodes = CreateCollisionNodes(); - - // std430 alignment rules forces us to convert the vec3 to a vec4 - std::vector vertices; - vertices.reserve(Mesh->MeshVertices.Size()); - for (const FVector3& v : Mesh->MeshVertices) - vertices.push_back({ v, 1.0f }); - - CollisionNodeBufferHeader nodesHeader; - nodesHeader.root = Mesh->Collision->get_root(); - - vertexBuffer = BufferBuilder() - .Usage( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT | - (useRayQuery ? - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | - VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) | - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) - .Size(vertices.size() * sizeof(FVector4)) - .DebugName("vertexBuffer") - .Create(fb->GetDevice()); - - indexBuffer = BufferBuilder() - .Usage( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT | - (useRayQuery ? - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | - VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) | - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) - .Size((size_t)Mesh->MeshElements.Size() * sizeof(uint32_t)) - .DebugName("indexBuffer") - .Create(fb->GetDevice()); - - nodesBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) - .Size(sizeof(CollisionNodeBufferHeader) + nodes.size() * sizeof(CollisionNode)) - .DebugName("nodesBuffer") - .Create(fb->GetDevice()); - - transferBuffer = BufferTransfer() - .AddBuffer(vertexBuffer.get(), vertices.data(), vertices.size() * sizeof(FVector4)) - .AddBuffer(indexBuffer.get(), Mesh->MeshElements.Data(), (size_t)Mesh->MeshElements.Size() * sizeof(uint32_t)) - .AddBuffer(nodesBuffer.get(), &nodesHeader, sizeof(CollisionNodeBufferHeader), nodes.data(), nodes.size() * sizeof(CollisionNode)) - .Execute(fb->GetDevice(), fb->GetCommands()->GetTransferCommands()); - - PipelineBarrier() - .AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) - .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, useRayQuery ? VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); -} - -void VkRaytrace::CreateBottomLevelAccelerationStructure() -{ - VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; - VkAccelerationStructureGeometryKHR accelStructBLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; - VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructBLDesc }; - VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {}; - VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo }; - - accelStructBLDesc.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelStructBLDesc.geometry.triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR }; - accelStructBLDesc.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32A32_SFLOAT; - accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = vertexBuffer->GetDeviceAddress(); - accelStructBLDesc.geometry.triangles.vertexStride = sizeof(FVector4); - accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelStructBLDesc.geometry.triangles.indexData.deviceAddress = indexBuffer->GetDeviceAddress(); - accelStructBLDesc.geometry.triangles.maxVertex = Mesh->MeshVertices.Size() - 1; - - buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - buildInfo.geometryCount = 1; - buildInfo.ppGeometries = geometries; - - uint32_t maxPrimitiveCount = Mesh->MeshElements.Size() / 3; - - VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; - vkGetAccelerationStructureBuildSizesKHR(fb->GetDevice()->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo); - - blAccelStructBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) - .Size(sizeInfo.accelerationStructureSize) - .DebugName("blAccelStructBuffer") - .Create(fb->GetDevice()); - - blAccelStruct = AccelerationStructureBuilder() - .Type(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) - .Buffer(blAccelStructBuffer.get(), sizeInfo.accelerationStructureSize) - .DebugName("blAccelStruct") - .Create(fb->GetDevice()); - - blScratchBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) - .Size(sizeInfo.buildScratchSize) - .MinAlignment(fb->GetDevice()->PhysicalDevice.Properties.AccelerationStructure.minAccelerationStructureScratchOffsetAlignment) - .DebugName("blScratchBuffer") - .Create(fb->GetDevice()); - - buildInfo.dstAccelerationStructure = blAccelStruct->accelstruct; - buildInfo.scratchData.deviceAddress = blScratchBuffer->GetDeviceAddress(); - rangeInfo.primitiveCount = maxPrimitiveCount; - - fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos); - - // Finish building before using it as input to a toplevel accel structure - PipelineBarrier() - .AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR) - .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); -} - -void VkRaytrace::CreateTopLevelAccelerationStructure() -{ - VkAccelerationStructureInstanceKHR instance = {}; - instance.transform.matrix[0][0] = 1.0f; - instance.transform.matrix[1][1] = 1.0f; - instance.transform.matrix[2][2] = 1.0f; - instance.mask = 0xff; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = blAccelStruct->GetDeviceAddress(); - - tlTransferBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) - .Size(sizeof(VkAccelerationStructureInstanceKHR)) - .DebugName("tlTransferBuffer") - .Create(fb->GetDevice()); - - auto data = (uint8_t*)tlTransferBuffer->Map(0, sizeof(VkAccelerationStructureInstanceKHR)); - memcpy(data, &instance, sizeof(VkAccelerationStructureInstanceKHR)); - tlTransferBuffer->Unmap(); - - tlInstanceBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT) - .Size(sizeof(VkAccelerationStructureInstanceKHR)) - .DebugName("tlInstanceBuffer") - .Create(fb->GetDevice()); - - fb->GetCommands()->GetTransferCommands()->copyBuffer(tlTransferBuffer.get(), tlInstanceBuffer.get()); - - // Finish transfering before using it as input - PipelineBarrier() - .AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) - .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); - - VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; - VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; - VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructTLDesc }; - VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {}; - VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo }; - - buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - buildInfo.geometryCount = 1; - buildInfo.ppGeometries = geometries; - - accelStructTLDesc.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelStructTLDesc.geometry.instances = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR }; - accelStructTLDesc.geometry.instances.data.deviceAddress = tlInstanceBuffer->GetDeviceAddress(); - - uint32_t maxInstanceCount = 1; - - VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; - vkGetAccelerationStructureBuildSizesKHR(fb->GetDevice()->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxInstanceCount, &sizeInfo); - - tlAccelStructBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) - .Size(sizeInfo.accelerationStructureSize) - .DebugName("tlAccelStructBuffer") - .Create(fb->GetDevice()); - - tlAccelStruct = AccelerationStructureBuilder() - .Type(VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) - .Buffer(tlAccelStructBuffer.get(), sizeInfo.accelerationStructureSize) - .DebugName("tlAccelStruct") - .Create(fb->GetDevice()); - - tlScratchBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) - .Size(sizeInfo.buildScratchSize) - .MinAlignment(fb->GetDevice()->PhysicalDevice.Properties.AccelerationStructure.minAccelerationStructureScratchOffsetAlignment) - .DebugName("tlScratchBuffer") - .Create(fb->GetDevice()); - - buildInfo.dstAccelerationStructure = tlAccelStruct->accelstruct; - buildInfo.scratchData.deviceAddress = tlScratchBuffer->GetDeviceAddress(); - rangeInfo.primitiveCount = 1; - - fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos); - - // Finish building the accel struct before using as input in a fragment shader - PipelineBarrier() - .AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT) - .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); -} - -std::vector VkRaytrace::CreateCollisionNodes() -{ - std::vector nodes; - nodes.reserve(Mesh->Collision->get_nodes().size()); - for (const auto& node : Mesh->Collision->get_nodes()) - { - CollisionNode info; - info.center = node.aabb.Center; - info.extents = node.aabb.Extents; - info.left = node.left; - info.right = node.right; - info.element_index = node.element_index; - nodes.push_back(info); - } - if (nodes.empty()) // vulkan doesn't support zero byte buffers - nodes.push_back(CollisionNode()); - return nodes; -} - - -///////////////////////////////////////////////////////////////////////////// - -BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, const void* data, size_t size) -{ - bufferCopies.push_back({ buffer, data, size, nullptr, 0 }); - return *this; -} - -BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, const void* data0, size_t size0, const void* data1, size_t size1) -{ - bufferCopies.push_back({ buffer, data0, size0, data1, size1 }); - return *this; -} - -std::unique_ptr BufferTransfer::Execute(VulkanDevice* device, VulkanCommandBuffer* cmdbuffer) -{ - size_t transferbuffersize = 0; - for (const auto& copy : bufferCopies) - transferbuffersize += copy.size0 + copy.size1; - - if (transferbuffersize == 0) - return nullptr; - - auto transferBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) - .Size(transferbuffersize) - .DebugName("BufferTransfer.transferBuffer") - .Create(device); - - uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize); - size_t pos = 0; - for (const auto& copy : bufferCopies) - { - memcpy(data + pos, copy.data0, copy.size0); - pos += copy.size0; - memcpy(data + pos, copy.data1, copy.size1); - pos += copy.size1; - } - transferBuffer->Unmap(); - - pos = 0; - for (const auto& copy : bufferCopies) - { - if (copy.size0 > 0) - cmdbuffer->copyBuffer(transferBuffer.get(), copy.buffer, pos, 0, copy.size0); - pos += copy.size0; - - if (copy.size1 > 0) - cmdbuffer->copyBuffer(transferBuffer.get(), copy.buffer, pos, copy.size0, copy.size1); - pos += copy.size1; - } - - return transferBuffer; -} diff --git a/src/common/rendering/vulkan/accelstructs/vk_raytrace.h b/src/common/rendering/vulkan/accelstructs/vk_raytrace.h deleted file mode 100644 index d914f6efeb..0000000000 --- a/src/common/rendering/vulkan/accelstructs/vk_raytrace.h +++ /dev/null @@ -1,90 +0,0 @@ - -#pragma once - -#include "zvulkan/vulkanobjects.h" -#include "hw_levelmesh.h" - -class VulkanRenderDevice; - -struct CollisionNodeBufferHeader -{ - int root; - int padding1; - int padding2; - int padding3; -}; - -struct CollisionNode -{ - FVector3 center; - float padding1; - FVector3 extents; - float padding2; - int left; - int right; - int element_index; - int padding3; -}; - -class VkRaytrace -{ -public: - VkRaytrace(VulkanRenderDevice* fb); - - void SetLevelMesh(hwrenderer::LevelMesh* mesh); - - VulkanAccelerationStructure* GetAccelStruct() { return tlAccelStruct.get(); } - VulkanBuffer* GetVertexBuffer() { return vertexBuffer.get(); } - VulkanBuffer* GetIndexBuffer() { return indexBuffer.get(); } - VulkanBuffer* GetNodeBuffer() { return nodesBuffer.get(); } - -private: - void Reset(); - void CreateVulkanObjects(); - void CreateVertexAndIndexBuffers(); - void CreateBottomLevelAccelerationStructure(); - void CreateTopLevelAccelerationStructure(); - - std::vector CreateCollisionNodes(); - - VulkanRenderDevice* fb = nullptr; - - bool useRayQuery = true; - - hwrenderer::LevelMesh NullMesh; - hwrenderer::LevelMesh* Mesh = nullptr; - - std::unique_ptr vertexBuffer; - std::unique_ptr indexBuffer; - std::unique_ptr transferBuffer; - std::unique_ptr nodesBuffer; - - std::unique_ptr blScratchBuffer; - std::unique_ptr blAccelStructBuffer; - std::unique_ptr blAccelStruct; - - std::unique_ptr tlTransferBuffer; - std::unique_ptr tlScratchBuffer; - std::unique_ptr tlInstanceBuffer; - std::unique_ptr tlAccelStructBuffer; - std::unique_ptr tlAccelStruct; -}; - -class BufferTransfer -{ -public: - BufferTransfer& AddBuffer(VulkanBuffer* buffer, const void* data, size_t size); - BufferTransfer& AddBuffer(VulkanBuffer* buffer, const void* data0, size_t size0, const void* data1, size_t size1); - std::unique_ptr Execute(VulkanDevice* device, VulkanCommandBuffer* cmdbuffer); - -private: - struct BufferCopy - { - VulkanBuffer* buffer; - const void* data0; - size_t size0; - const void* data1; - size_t size1; - }; - std::vector bufferCopies; -}; diff --git a/src/common/rendering/vulkan/buffers/vk_buffer.cpp b/src/common/rendering/vulkan/buffers/vk_buffer.cpp index 993e730978..23b6f4d37a 100644 --- a/src/common/rendering/vulkan/buffers/vk_buffer.cpp +++ b/src/common/rendering/vulkan/buffers/vk_buffer.cpp @@ -38,10 +38,7 @@ VkBufferManager::~VkBufferManager() void VkBufferManager::Init() { - for (int threadIndex = 0; threadIndex < fb->MaxThreads; threadIndex++) - { - RSBuffers.push_back(std::make_unique(fb)); - } + RSBuffers = std::make_unique(fb); Shadowmap.Nodes.reset(new VkHardwareDataBuffer(fb, true, false)); Shadowmap.Lines.reset(new VkHardwareDataBuffer(fb, true, false)); @@ -52,7 +49,7 @@ void VkBufferManager::Init() void VkBufferManager::Deinit() { - RSBuffers.clear(); + RSBuffers.reset(); Shadowmap.Nodes.reset(); Shadowmap.Lines.reset(); @@ -76,7 +73,9 @@ void VkBufferManager::RemoveBuffer(VkHardwareBuffer* buffer) IBuffer* VkBufferManager::CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs) { - return new VkHardwareVertexBuffer(fb, fb->GetRenderPassManager()->GetVertexFormat(numBindingPoints, numAttributes, stride, attrs)); + std::vector bufferStrides; + bufferStrides.resize(numBindingPoints, stride); + return new VkHardwareVertexBuffer(fb, fb->GetRenderPassManager()->GetVertexFormat(bufferStrides, std::vector(attrs, attrs + numAttributes))); } IBuffer* VkBufferManager::CreateIndexBuffer() diff --git a/src/common/rendering/vulkan/buffers/vk_buffer.h b/src/common/rendering/vulkan/buffers/vk_buffer.h index e4de97f3dc..984af74822 100644 --- a/src/common/rendering/vulkan/buffers/vk_buffer.h +++ b/src/common/rendering/vulkan/buffers/vk_buffer.h @@ -26,7 +26,7 @@ class VkBufferManager void AddBuffer(VkHardwareBuffer* buffer); void RemoveBuffer(VkHardwareBuffer* buffer); - VkRSBuffers* GetRSBuffers(int threadIndex) { return RSBuffers[threadIndex].get(); } + VkRSBuffers* GetRSBuffers() { return RSBuffers.get(); } struct { @@ -43,5 +43,5 @@ class VkBufferManager VulkanRenderDevice* fb = nullptr; std::list Buffers; - std::vector> RSBuffers; + std::unique_ptr RSBuffers; }; diff --git a/src/common/rendering/vulkan/buffers/vk_rsbuffers.cpp b/src/common/rendering/vulkan/buffers/vk_rsbuffers.cpp index b24d18c7fe..08a3854f41 100644 --- a/src/common/rendering/vulkan/buffers/vk_rsbuffers.cpp +++ b/src/common/rendering/vulkan/buffers/vk_rsbuffers.cpp @@ -26,17 +26,19 @@ #include "vulkan/buffers/vk_buffer.h" #include #include "flatvertices.h" +#include "cmdlib.h" VkRSBuffers::VkRSBuffers(VulkanRenderDevice* fb) { - static const FVertexBufferAttribute format[] = + static std::vector format = { - { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) }, + { 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FFlatVertex, x) }, { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }, - { 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FFlatVertex, lu) }, + { 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FFlatVertex, lu) }, }; + static std::vector bufferStrides = { sizeof(FFlatVertex), sizeof(FFlatVertex) }; - Flatbuffer.VertexFormat = fb->GetRenderPassManager()->GetVertexFormat(1, 3, sizeof(FFlatVertex), format); + Flatbuffer.VertexFormat = fb->GetRenderPassManager()->GetVertexFormat(bufferStrides, format); Flatbuffer.VertexBuffer = BufferBuilder() .Usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT) @@ -55,8 +57,8 @@ VkRSBuffers::VkRSBuffers(VulkanRenderDevice* fb) .DebugName("Flatbuffer.IndexBuffer") .Create(fb->GetDevice()); - MatrixBuffer = std::make_unique(fb, sizeof(MatricesUBO), 50000); - StreamBuffer = std::make_unique(fb, sizeof(StreamUBO), 300); + MatrixBuffer = std::make_unique(fb); + SurfaceUniformsBuffer = std::make_unique(fb); Viewpoint.BlockAlign = (sizeof(HWViewpointUniforms) + fb->uniformblockalignment - 1) / fb->uniformblockalignment * fb->uniformblockalignment; @@ -92,6 +94,21 @@ VkRSBuffers::VkRSBuffers(VulkanRenderDevice* fb) .Create(fb->GetDevice()); Bonebuffer.Data = Bonebuffer.SSO->Map(0, Bonebuffer.SSO->size); + + Fogballbuffer.UBO = BufferBuilder() + .Usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT) + .MemoryType( + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + .Size(Fogballbuffer.Count * sizeof(Fogball)) + .DebugName("Fogballbuffer.UBO") + .Create(fb->GetDevice()); + + Fogballbuffer.Data = Fogballbuffer.UBO->Map(0, Fogballbuffer.UBO->size); + + OcclusionQuery.QueryPool = QueryPoolBuilder() + .QueryType(VK_QUERY_TYPE_OCCLUSION, OcclusionQuery.MaxQueries) + .Create(fb->GetDevice()); } VkRSBuffers::~VkRSBuffers() @@ -112,6 +129,10 @@ VkRSBuffers::~VkRSBuffers() if (Bonebuffer.SSO) Bonebuffer.SSO->Unmap(); Bonebuffer.SSO.reset(); + + if (Fogballbuffer.UBO) + Fogballbuffer.UBO->Unmap(); + Fogballbuffer.UBO.reset(); } ///////////////////////////////////////////////////////////////////////////// @@ -148,38 +169,40 @@ uint32_t VkStreamBuffer::NextStreamDataBlock() return mStreamDataOffset; } -VkStreamBufferWriter::VkStreamBufferWriter(VkRSBuffers* rsbuffers) +///////////////////////////////////////////////////////////////////////////// + +VkSurfaceUniformsBufferWriter::VkSurfaceUniformsBufferWriter(VulkanRenderDevice* fb) { - mBuffer = rsbuffers->StreamBuffer.get(); + mBuffer = std::make_unique(fb, sizeof(SurfaceUniformsUBO), 300); } -bool VkStreamBufferWriter::Write(const StreamData& data) +bool VkSurfaceUniformsBufferWriter::Write(const SurfaceUniforms& data) { mDataIndex++; - if (mDataIndex == MAX_STREAM_DATA) + if (mDataIndex == MAX_SURFACE_UNIFORMS) { mDataIndex = 0; - mStreamDataOffset = mBuffer->NextStreamDataBlock(); - if (mStreamDataOffset == 0xffffffff) + mOffset = mBuffer->NextStreamDataBlock(); + if (mOffset == 0xffffffff) return false; } uint8_t* ptr = (uint8_t*)mBuffer->Data; - memcpy(ptr + mStreamDataOffset + sizeof(StreamData) * mDataIndex, &data, sizeof(StreamData)); + memcpy(ptr + mOffset + sizeof(SurfaceUniforms) * mDataIndex, &data, sizeof(SurfaceUniforms)); return true; } -void VkStreamBufferWriter::Reset() +void VkSurfaceUniformsBufferWriter::Reset() { - mDataIndex = MAX_STREAM_DATA - 1; - mStreamDataOffset = 0; + mDataIndex = MAX_SURFACE_UNIFORMS - 1; + mOffset = 0; mBuffer->Reset(); } ///////////////////////////////////////////////////////////////////////////// -VkMatrixBufferWriter::VkMatrixBufferWriter(VkRSBuffers* rsbuffers) +VkMatrixBufferWriter::VkMatrixBufferWriter(VulkanRenderDevice* fb) { - mBuffer = rsbuffers->MatrixBuffer.get(); + mBuffer = std::make_unique(fb, sizeof(MatricesUBO), 50000); } bool VkMatrixBufferWriter::Write(const MatricesUBO& matrices) diff --git a/src/common/rendering/vulkan/buffers/vk_rsbuffers.h b/src/common/rendering/vulkan/buffers/vk_rsbuffers.h index d08802d24e..1eaddf6766 100644 --- a/src/common/rendering/vulkan/buffers/vk_rsbuffers.h +++ b/src/common/rendering/vulkan/buffers/vk_rsbuffers.h @@ -4,7 +4,8 @@ #include "vulkan/buffers/vk_hwbuffer.h" #include "vulkan/shaders/vk_shader.h" -class VkStreamBuffer; +class VkMatrixBufferWriter; +class VkSurfaceUniformsBufferWriter; struct FFlatVertex; class VkRSBuffers @@ -20,8 +21,8 @@ class VkRSBuffers FFlatVertex* Vertices = nullptr; unsigned int ShadowDataSize = 0; unsigned int CurIndex = 0; - static const unsigned int BUFFER_SIZE = 2000000; - static const unsigned int BUFFER_SIZE_TO_USE = BUFFER_SIZE - 500; + const unsigned int BUFFER_SIZE = 2000000; + const unsigned int BUFFER_SIZE_TO_USE = BUFFER_SIZE - 500; std::unique_ptr IndexBuffer; } Flatbuffer; @@ -50,8 +51,23 @@ class VkRSBuffers void* Data = nullptr; } Bonebuffer; - std::unique_ptr MatrixBuffer; - std::unique_ptr StreamBuffer; + struct + { + int UploadIndex = 0; + int Count = 10000; + std::unique_ptr UBO; + void* Data = nullptr; + } Fogballbuffer; + + std::unique_ptr MatrixBuffer; + std::unique_ptr SurfaceUniformsBuffer; + + struct + { + const int MaxQueries = 64000; + std::unique_ptr QueryPool; + int NextIndex = 0; + } OcclusionQuery; }; class VkStreamBuffer @@ -71,34 +87,38 @@ class VkStreamBuffer uint32_t mStreamDataOffset = 0; }; -class VkStreamBufferWriter +class VkSurfaceUniformsBufferWriter { public: - VkStreamBufferWriter(VkRSBuffers* rsbuffers); + VkSurfaceUniformsBufferWriter(VulkanRenderDevice* fb); - bool Write(const StreamData& data); + bool Write(const SurfaceUniforms& data); void Reset(); uint32_t DataIndex() const { return mDataIndex; } - uint32_t StreamDataOffset() const { return mStreamDataOffset; } + uint32_t Offset() const { return mOffset; } + + VulkanBuffer* UBO() const { return mBuffer->UBO.get(); } private: - VkStreamBuffer* mBuffer; - uint32_t mDataIndex = MAX_STREAM_DATA - 1; - uint32_t mStreamDataOffset = 0; + std::unique_ptr mBuffer; + uint32_t mDataIndex = MAX_SURFACE_UNIFORMS - 1; + uint32_t mOffset = 0; }; class VkMatrixBufferWriter { public: - VkMatrixBufferWriter(VkRSBuffers* rsbuffers); + VkMatrixBufferWriter(VulkanRenderDevice* fb); bool Write(const MatricesUBO& matrices); void Reset(); uint32_t Offset() const { return mOffset; } + VulkanBuffer* UBO() const { return mBuffer->UBO.get(); } + private: - VkStreamBuffer* mBuffer; + std::unique_ptr mBuffer; uint32_t mOffset = 0; }; diff --git a/src/common/rendering/vulkan/commands/vk_commandbuffer.cpp b/src/common/rendering/vulkan/commands/vk_commandbuffer.cpp index 5fc5275705..a1657fc47b 100644 --- a/src/common/rendering/vulkan/commands/vk_commandbuffer.cpp +++ b/src/common/rendering/vulkan/commands/vk_commandbuffer.cpp @@ -25,6 +25,7 @@ #include "vulkan/vk_renderstate.h" #include "vulkan/vk_postprocess.h" #include "vulkan/framebuffers/vk_framebuffer.h" +#include "vulkan/descriptorsets/vk_descriptorset.h" #include #include #include "hw_clock.h" @@ -112,7 +113,7 @@ void VkCommandBufferManager::BeginFrame() { if (mNextTimestampQuery > 0) { - GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, mNextTimestampQuery); + GetTransferCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, mNextTimestampQuery); mNextTimestampQuery = 0; } } @@ -150,8 +151,10 @@ void VkCommandBufferManager::FlushCommands(VulkanCommandBuffer** commands, size_ void VkCommandBufferManager::FlushCommands(bool finish, bool lastsubmit, bool uploadOnly) { + fb->GetDescriptorSetManager()->UpdateBindlessDescriptorSet(); + if (!uploadOnly) - fb->GetRenderState(0)->EndRenderPass(); + fb->GetRenderState()->EndRenderPass(); std::unique_lock lock(mMutex); @@ -201,7 +204,8 @@ void VkCommandBufferManager::WaitForCommands(bool finish, bool uploadOnly) if (finish) { - fb->FPSLimit(); + if (!fb->GetVSync()) + fb->FPSLimit(); fb->GetFramebufferManager()->QueuePresent(); } @@ -231,7 +235,7 @@ void VkCommandBufferManager::DeleteFrameObjects(bool uploadOnly) DrawDeleteList = std::make_unique(); } -void VkCommandBufferManager::PushGroup(const FString& name) +void VkCommandBufferManager::PushGroup(VulkanCommandBuffer* cmdbuffer, const FString& name) { if (!gpuStatActive) return; @@ -242,13 +246,13 @@ void VkCommandBufferManager::PushGroup(const FString& name) q.name = name; q.startIndex = mNextTimestampQuery++; q.endIndex = 0; - GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.startIndex); + cmdbuffer->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.startIndex); mGroupStack.push_back(timeElapsedQueries.size()); timeElapsedQueries.push_back(q); } } -void VkCommandBufferManager::PopGroup() +void VkCommandBufferManager::PopGroup(VulkanCommandBuffer* cmdbuffer) { if (!gpuStatActive || mGroupStack.empty()) return; @@ -259,7 +263,7 @@ void VkCommandBufferManager::PopGroup() if (mNextTimestampQuery < MaxTimestampQueries && fb->GetDevice()->GraphicsTimeQueries) { q.endIndex = mNextTimestampQuery++; - GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.endIndex); + cmdbuffer->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.endIndex); } } diff --git a/src/common/rendering/vulkan/commands/vk_commandbuffer.h b/src/common/rendering/vulkan/commands/vk_commandbuffer.h index 561b5eb8c6..e3c5cb3b63 100644 --- a/src/common/rendering/vulkan/commands/vk_commandbuffer.h +++ b/src/common/rendering/vulkan/commands/vk_commandbuffer.h @@ -25,8 +25,8 @@ class VkCommandBufferManager void WaitForCommands(bool finish) { WaitForCommands(finish, false); } void WaitForCommands(bool finish, bool uploadOnly); - void PushGroup(const FString& name); - void PopGroup(); + void PushGroup(VulkanCommandBuffer* cmdbuffer, const FString& name); + void PopGroup(VulkanCommandBuffer* cmdbuffer); void UpdateGpuStats(); class DeleteList diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp index f38559075c..00343c9d54 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp @@ -22,7 +22,7 @@ #include "vk_descriptorset.h" #include "vulkan/vk_renderdevice.h" -#include "vulkan/accelstructs/vk_raytrace.h" +#include "vulkan/vk_levelmesh.h" #include "vulkan/shaders/vk_shader.h" #include "vulkan/samplers/vk_samplers.h" #include "vulkan/textures/vk_renderbuffers.h" @@ -40,10 +40,13 @@ VkDescriptorSetManager::VkDescriptorSetManager(VulkanRenderDevice* fb) : fb(fb) { - CreateRSBufferSetLayout(); - CreateFixedSetLayout(); + CreateLevelMeshLayout(); + CreateRSBufferLayout(); + CreateFixedLayout(); + CreateLevelMeshPool(); CreateRSBufferPool(); - CreateFixedSetPool(); + CreateFixedPool(); + CreateBindlessSet(); } VkDescriptorSetManager::~VkDescriptorSetManager() @@ -56,21 +59,18 @@ void VkDescriptorSetManager::Init() { UpdateFixedSet(); - for (int threadIndex = 0; threadIndex < fb->MaxThreads; threadIndex++) - { - auto rsbuffers = fb->GetBufferManager()->GetRSBuffers(threadIndex); - auto rsbufferset = RSBufferDescriptorPool->allocate(RSBufferSetLayout.get()); - - WriteDescriptors() - .AddBuffer(rsbufferset.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Viewpoint.UBO.get(), 0, sizeof(HWViewpointUniforms)) - .AddBuffer(rsbufferset.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->MatrixBuffer->UBO.get(), 0, sizeof(MatricesUBO)) - .AddBuffer(rsbufferset.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->StreamBuffer->UBO.get(), 0, sizeof(StreamUBO)) - .AddBuffer(rsbufferset.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Lightbuffer.UBO.get(), 0, sizeof(LightBufferUBO)) - .AddBuffer(rsbufferset.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, rsbuffers->Bonebuffer.SSO.get()) - .Execute(fb->GetDevice()); - - RSBufferSets.push_back(std::move(rsbufferset)); - } + RSBuffer.Set = RSBuffer.Pool->allocate(RSBuffer.Layout.get()); + LevelMesh.Set = LevelMesh.Pool->allocate(LevelMesh.Layout.get()); + + auto rsbuffers = fb->GetBufferManager()->GetRSBuffers(); + WriteDescriptors() + .AddBuffer(RSBuffer.Set.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Viewpoint.UBO.get(), 0, sizeof(HWViewpointUniforms)) + .AddBuffer(RSBuffer.Set.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->MatrixBuffer->UBO(), 0, sizeof(MatricesUBO)) + .AddBuffer(RSBuffer.Set.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->SurfaceUniformsBuffer->UBO(), 0, sizeof(SurfaceUniformsUBO)) + .AddBuffer(RSBuffer.Set.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Lightbuffer.UBO.get(), 0, sizeof(LightBufferUBO)) + .AddBuffer(RSBuffer.Set.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Fogballbuffer.UBO.get(), 0, sizeof(FogballBufferUBO)) + .AddBuffer(RSBuffer.Set.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, rsbuffers->Bonebuffer.SSO.get()) + .Execute(fb->GetDevice()); } void VkDescriptorSetManager::Deinit() @@ -82,31 +82,45 @@ void VkDescriptorSetManager::Deinit() void VkDescriptorSetManager::BeginFrame() { UpdateFixedSet(); + UpdateLevelMeshSet(); +} + +void VkDescriptorSetManager::UpdateLevelMeshSet() +{ + auto rsbuffers = fb->GetBufferManager()->GetRSBuffers(); + WriteDescriptors() + .AddBuffer(LevelMesh.Set.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Viewpoint.UBO.get(), 0, sizeof(HWViewpointUniforms)) + .AddBuffer(LevelMesh.Set.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->MatrixBuffer->UBO(), 0, sizeof(MatricesUBO)) + .AddBuffer(LevelMesh.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetUniformsBuffer()) + .AddBuffer(LevelMesh.Set.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Lightbuffer.UBO.get(), 0, sizeof(LightBufferUBO)) + .AddBuffer(LevelMesh.Set.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Fogballbuffer.UBO.get(), 0, sizeof(FogballBufferUBO)) + .AddBuffer(LevelMesh.Set.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, rsbuffers->Bonebuffer.SSO.get()) + .Execute(fb->GetDevice()); } void VkDescriptorSetManager::UpdateFixedSet() { - fb->GetCommands()->DrawDeleteList->Add(std::move(FixedSet)); + fb->GetCommands()->DrawDeleteList->Add(std::move(Fixed.Set)); - FixedSet = FixedDescriptorPool->tryAllocate(FixedSetLayout.get()); - if (!FixedSet) + Fixed.Set = Fixed.Pool->tryAllocate(Fixed.Layout.get()); + if (!Fixed.Set) { fb->GetCommands()->WaitForCommands(false); - FixedSet = FixedDescriptorPool->allocate(FixedSetLayout.get()); + Fixed.Set = Fixed.Pool->allocate(Fixed.Layout.get()); } WriteDescriptors update; - update.AddCombinedImageSampler(FixedSet.get(), 0, fb->GetTextureManager()->Shadowmap.View.get(), fb->GetSamplerManager()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - update.AddCombinedImageSampler(FixedSet.get(), 1, fb->GetTextureManager()->Lightmap.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + update.AddCombinedImageSampler(Fixed.Set.get(), 0, fb->GetTextureManager()->Shadowmap.View.get(), fb->GetSamplerManager()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + update.AddCombinedImageSampler(Fixed.Set.get(), 1, fb->GetTextureManager()->Lightmap.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + if (fb->IsRayQueryEnabled()) { - update.AddAccelerationStructure(FixedSet.get(), 2, fb->GetRaytrace()->GetAccelStruct()); + update.AddAccelerationStructure(Fixed.Set.get(), 2, fb->GetLevelMesh()->GetAccelStruct()); } else { - update.AddBuffer(FixedSet.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetNodeBuffer()); - update.AddBuffer(FixedSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetVertexBuffer()); - update.AddBuffer(FixedSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetIndexBuffer()); + update.AddBuffer(Fixed.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetNodeBuffer()); + update.AddBuffer(Fixed.Set.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer()); + update.AddBuffer(Fixed.Set.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer()); } update.Execute(fb->GetDevice()); } @@ -116,71 +130,11 @@ void VkDescriptorSetManager::ResetHWTextureSets() for (auto mat : Materials) mat->DeleteDescriptors(); - auto deleteList = fb->GetCommands()->DrawDeleteList.get(); - for (auto& desc : TextureDescriptorPools) - { - deleteList->Add(std::move(desc)); - } - deleteList->Add(std::move(NullTextureDescriptorSet)); - - TextureDescriptorPools.clear(); - TextureDescriptorSetsLeft = 0; - TextureDescriptorsLeft = 0; -} - -VulkanDescriptorSet* VkDescriptorSetManager::GetNullTextureDescriptorSet() -{ - if (!NullTextureDescriptorSet) - { - NullTextureDescriptorSet = AllocateTextureDescriptorSet(SHADER_MIN_REQUIRED_TEXTURE_LAYERS); - - WriteDescriptors update; - for (int i = 0; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++) - { - update.AddCombinedImageSampler(NullTextureDescriptorSet.get(), i, fb->GetTextureManager()->GetNullTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - } - update.Execute(fb->GetDevice()); - } - - return NullTextureDescriptorSet.get(); -} + Bindless.Writer = WriteDescriptors(); + Bindless.NextIndex = 0; -std::unique_ptr VkDescriptorSetManager::AllocateTextureDescriptorSet(int numLayers) -{ - if (TextureDescriptorSetsLeft == 0 || TextureDescriptorsLeft < numLayers) - { - TextureDescriptorSetsLeft = 1000; - TextureDescriptorsLeft = 2000; - - TextureDescriptorPools.push_back(DescriptorPoolBuilder() - .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TextureDescriptorsLeft) - .MaxSets(TextureDescriptorSetsLeft) - .DebugName("VkDescriptorSetManager.TextureDescriptorPool") - .Create(fb->GetDevice())); - } - - TextureDescriptorSetsLeft--; - TextureDescriptorsLeft -= numLayers; - return TextureDescriptorPools.back()->allocate(GetTextureSetLayout(numLayers)); -} - -VulkanDescriptorSetLayout* VkDescriptorSetManager::GetTextureSetLayout(int numLayers) -{ - if (TextureSetLayouts.size() < (size_t)numLayers) - TextureSetLayouts.resize(numLayers); - - auto& layout = TextureSetLayouts[numLayers - 1]; - if (layout) - return layout.get(); - - DescriptorSetLayoutBuilder builder; - for (int i = 0; i < numLayers; i++) - { - builder.AddBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - } - builder.DebugName("VkDescriptorSetManager.TextureSetLayout"); - layout = builder.Create(fb->GetDevice()); - return layout.get(); + // Slot zero always needs to be the null texture + AddBindlessTextureIndex(fb->GetTextureManager()->GetNullTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP)); } void VkDescriptorSetManager::AddMaterial(VkMaterial* texture) @@ -197,7 +151,7 @@ void VkDescriptorSetManager::RemoveMaterial(VkMaterial* texture) VulkanDescriptorSet* VkDescriptorSetManager::GetInput(VkPPRenderPassSetup* passSetup, const TArray& textures, bool bindShadowMapBuffers) { - auto descriptors = AllocatePPDescriptorSet(passSetup->DescriptorLayout.get()); + auto descriptors = AllocatePPSet(passSetup->DescriptorLayout.get()); descriptors->SetDebugName("VkPostprocess.descriptors"); WriteDescriptors write; @@ -228,45 +182,59 @@ VulkanDescriptorSet* VkDescriptorSetManager::GetInput(VkPPRenderPassSetup* passS return set; } -std::unique_ptr VkDescriptorSetManager::AllocatePPDescriptorSet(VulkanDescriptorSetLayout* layout) +std::unique_ptr VkDescriptorSetManager::AllocatePPSet(VulkanDescriptorSetLayout* layout) { - if (PPDescriptorPool) + if (Postprocess.Pool) { - auto descriptors = PPDescriptorPool->tryAllocate(layout); + auto descriptors = Postprocess.Pool->tryAllocate(layout); if (descriptors) return descriptors; - fb->GetCommands()->DrawDeleteList->Add(std::move(PPDescriptorPool)); + fb->GetCommands()->DrawDeleteList->Add(std::move(Postprocess.Pool)); } - PPDescriptorPool = DescriptorPoolBuilder() + Postprocess.Pool = DescriptorPoolBuilder() .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 200) .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4) .MaxSets(100) .DebugName("PPDescriptorPool") .Create(fb->GetDevice()); - return PPDescriptorPool->allocate(layout); + return Postprocess.Pool->allocate(layout); } -void VkDescriptorSetManager::CreateRSBufferSetLayout() +void VkDescriptorSetManager::CreateLevelMeshLayout() { - RSBufferSetLayout = DescriptorSetLayoutBuilder() + LevelMesh.Layout = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT) + .DebugName("VkDescriptorSetManager.LevelMesh.Layout") + .Create(fb->GetDevice()); +} + +void VkDescriptorSetManager::CreateRSBufferLayout() +{ + RSBuffer.Layout = DescriptorSetLayoutBuilder() .AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) .AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) .AddBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) .AddBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) - .AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT) - .DebugName("VkDescriptorSetManager.RSBufferSetLayout") + .AddBinding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT) + .DebugName("VkDescriptorSetManager.RSBuffer.Layout") .Create(fb->GetDevice()); } -void VkDescriptorSetManager::CreateFixedSetLayout() +void VkDescriptorSetManager::CreateFixedLayout() { DescriptorSetLayoutBuilder builder; builder.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); builder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + if (fb->IsRayQueryEnabled()) { builder.AddBinding(2, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT); } @@ -276,33 +244,78 @@ void VkDescriptorSetManager::CreateFixedSetLayout() builder.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); builder.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); } - builder.DebugName("VkDescriptorSetManager.FixedSetLayout"); - FixedSetLayout = builder.Create(fb->GetDevice()); + builder.DebugName("VkDescriptorSetManager.Fixed.SetLayout"); + Fixed.Layout = builder.Create(fb->GetDevice()); +} + +void VkDescriptorSetManager::CreateLevelMeshPool() +{ + LevelMesh.Pool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 4) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2) + .MaxSets(1) + .DebugName("VkDescriptorSetManager.LevelMesh.Pool") + .Create(fb->GetDevice()); } void VkDescriptorSetManager::CreateRSBufferPool() { - RSBufferDescriptorPool = DescriptorPoolBuilder() - .AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 4 * fb->MaxThreads) - .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 * fb->MaxThreads) - .MaxSets(fb->MaxThreads) - .DebugName("VkDescriptorSetManager.RSBufferDescriptorPool") + RSBuffer.Pool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 5) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1) + .MaxSets(1) + .DebugName("VkDescriptorSetManager.RSBuffer.Pool") .Create(fb->GetDevice()); } -void VkDescriptorSetManager::CreateFixedSetPool() +void VkDescriptorSetManager::CreateFixedPool() { DescriptorPoolBuilder poolbuilder; - poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * maxSets); - if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * MaxFixedSets); + if (fb->IsRayQueryEnabled()) { - poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * maxSets); + poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * MaxFixedSets); } else { - poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3 * maxSets); + poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3 * MaxFixedSets); } - poolbuilder.MaxSets(maxSets); - poolbuilder.DebugName("VkDescriptorSetManager.FixedDescriptorPool"); - FixedDescriptorPool = poolbuilder.Create(fb->GetDevice()); + poolbuilder.MaxSets(MaxFixedSets); + poolbuilder.DebugName("VkDescriptorSetManager.Fixed.Pool"); + Fixed.Pool = poolbuilder.Create(fb->GetDevice()); +} + +void VkDescriptorSetManager::CreateBindlessSet() +{ + Bindless.Pool = DescriptorPoolBuilder() + .Flags(VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) + .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MaxBindlessTextures) + .MaxSets(MaxBindlessTextures) + .DebugName("Bindless.Pool") + .Create(fb->GetDevice()); + + Bindless.Layout = DescriptorSetLayoutBuilder() + .Flags(VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) + .AddBinding( + 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + MaxBindlessTextures, + VK_SHADER_STAGE_FRAGMENT_BIT, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT) + .DebugName("Bindless.Layout") + .Create(fb->GetDevice()); + + Bindless.Set = Bindless.Pool->allocate(Bindless.Layout.get(), MaxBindlessTextures); +} + +void VkDescriptorSetManager::UpdateBindlessDescriptorSet() +{ + Bindless.Writer.Execute(fb->GetDevice()); + Bindless.Writer = WriteDescriptors(); +} + +int VkDescriptorSetManager::AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler) +{ + int index = Bindless.NextIndex++; + Bindless.Writer.AddCombinedImageSampler(Bindless.Set.get(), 0, index, imageview, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + return index; } diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h index 04babd639c..90ccbb4581 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h @@ -2,6 +2,7 @@ #pragma once #include "zvulkan/vulkanobjects.h" +#include "zvulkan/vulkanbuilders.h" #include #include "tarray.h" @@ -20,51 +21,77 @@ class VkDescriptorSetManager void Deinit(); void BeginFrame(); void ResetHWTextureSets(); + void UpdateLevelMeshSet(); - VulkanDescriptorSetLayout* GetRSBufferSetLayout() { return RSBufferSetLayout.get(); } - VulkanDescriptorSetLayout* GetFixedSetLayout() { return FixedSetLayout.get(); } - VulkanDescriptorSetLayout* GetTextureSetLayout(int numLayers); + VulkanDescriptorSetLayout* GetLevelMeshLayout() { return LevelMesh.Layout.get(); } + VulkanDescriptorSetLayout* GetRSBufferLayout() { return RSBuffer.Layout.get(); } + VulkanDescriptorSetLayout* GetFixedLayout() { return Fixed.Layout.get(); } + VulkanDescriptorSetLayout* GetBindlessLayout() { return Bindless.Layout.get(); } - VulkanDescriptorSet* GetRSBufferDescriptorSet(int threadIndex) { return RSBufferSets[threadIndex].get(); } - VulkanDescriptorSet* GetFixedDescriptorSet() { return FixedSet.get(); } - VulkanDescriptorSet* GetNullTextureDescriptorSet(); - - std::unique_ptr AllocateTextureDescriptorSet(int numLayers); + VulkanDescriptorSet* GetLevelMeshSet() { return LevelMesh.Set.get(); } + VulkanDescriptorSet* GetRSBufferSet() { return RSBuffer.Set.get(); } + VulkanDescriptorSet* GetFixedSet() { return Fixed.Set.get(); } + VulkanDescriptorSet* GetBindlessSet() { return Bindless.Set.get(); } VulkanDescriptorSet* GetInput(VkPPRenderPassSetup* passSetup, const TArray& textures, bool bindShadowMapBuffers); void AddMaterial(VkMaterial* texture); void RemoveMaterial(VkMaterial* texture); + void UpdateBindlessDescriptorSet(); + int AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler); + private: - void CreateRSBufferSetLayout(); - void CreateFixedSetLayout(); + void CreateLevelMeshLayout(); + void CreateRSBufferLayout(); + void CreateFixedLayout(); + void CreateLevelMeshPool(); void CreateRSBufferPool(); - void CreateFixedSetPool(); + void CreateFixedPool(); + void CreateBindlessSet(); void UpdateFixedSet(); - std::unique_ptr AllocatePPDescriptorSet(VulkanDescriptorSetLayout* layout); + std::unique_ptr AllocatePPSet(VulkanDescriptorSetLayout* layout); VulkanRenderDevice* fb = nullptr; - std::unique_ptr RSBufferSetLayout; - std::unique_ptr FixedSetLayout; - std::vector> TextureSetLayouts; - - std::unique_ptr RSBufferDescriptorPool; - std::unique_ptr FixedDescriptorPool; - - std::unique_ptr PPDescriptorPool; - - int TextureDescriptorSetsLeft = 0; - int TextureDescriptorsLeft = 0; - std::vector> TextureDescriptorPools; - - std::vector> RSBufferSets; - std::unique_ptr FixedSet; - std::unique_ptr NullTextureDescriptorSet; + struct + { + std::unique_ptr Layout; + std::unique_ptr Pool; + std::unique_ptr Set; + } LevelMesh; + + struct + { + std::unique_ptr Layout; + std::unique_ptr Pool; + std::unique_ptr Set; + } RSBuffer; + + struct + { + std::unique_ptr Layout; + std::unique_ptr Pool; + std::unique_ptr Set; + } Fixed; + + struct + { + std::unique_ptr Pool; + std::unique_ptr Set; + std::unique_ptr Layout; + WriteDescriptors Writer; + int NextIndex = 0; + } Bindless; + + struct + { + std::unique_ptr Pool; + } Postprocess; std::list Materials; - static const int maxSets = 100; + static const int MaxFixedSets = 100; + static const int MaxBindlessTextures = 16536; }; diff --git a/src/common/rendering/vulkan/pipelines/vk_pprenderpass.cpp b/src/common/rendering/vulkan/pipelines/vk_pprenderpass.cpp index d6773ccf76..7da074e237 100644 --- a/src/common/rendering/vulkan/pipelines/vk_pprenderpass.cpp +++ b/src/common/rendering/vulkan/pipelines/vk_pprenderpass.cpp @@ -79,7 +79,11 @@ void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey& key) builder.Stencil(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0); } builder.Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); - BlendMode(builder, key.BlendMode); + + ColorBlendAttachmentBuilder blendbuilder; + BlendMode(blendbuilder, key.BlendMode); + builder.AddColorBlendAttachment(blendbuilder.Create()); + builder.RasterizationSamples(key.Samples); builder.Layout(PipelineLayout.get()); builder.RenderPass(RenderPass.get()); diff --git a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp index 095dc3393e..c5c6017610 100644 --- a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp +++ b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp @@ -24,7 +24,7 @@ #include "vk_pprenderpass.h" #include "vulkan/vk_renderstate.h" #include "vulkan/vk_renderdevice.h" -#include "vulkan/accelstructs/vk_raytrace.h" +#include "vulkan/vk_levelmesh.h" #include "vulkan/descriptorsets/vk_descriptorset.h" #include "vulkan/textures/vk_renderbuffers.h" #include "vulkan/samplers/vk_samplers.h" @@ -35,11 +35,12 @@ #include "hw_viewpointuniforms.h" #include "v_2ddrawer.h" #include "i_specialpaths.h" +#include "cmdlib.h" VkRenderPassManager::VkRenderPassManager(VulkanRenderDevice* fb) : fb(fb) { FString path = M_GetCachePath(true); - CreatePath(path); + CreatePath(path.GetChars()); CacheFilename = path + "/pipelinecache.zdpc"; PipelineCacheBuilder builder; @@ -48,7 +49,7 @@ VkRenderPassManager::VkRenderPassManager(VulkanRenderDevice* fb) : fb(fb) try { FileReader fr; - if (fr.OpenFile(CacheFilename)) + if (fr.OpenFile(CacheFilename.GetChars())) { std::vector data; data.resize(fr.GetLength()); @@ -70,7 +71,7 @@ VkRenderPassManager::~VkRenderPassManager() try { auto data = PipelineCache->GetCacheData(); - std::unique_ptr fw(FileWriter::Open(CacheFilename)); + std::unique_ptr fw(FileWriter::Open(CacheFilename.GetChars())); if (fw) fw->Write(data.data(), data.size()); } @@ -93,39 +94,30 @@ VkRenderPassSetup *VkRenderPassManager::GetRenderPass(const VkRenderPassKey &key return item.get(); } -int VkRenderPassManager::GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) +int VkRenderPassManager::GetVertexFormat(const std::vector& bufferStrides, const std::vector& attrs) { for (size_t i = 0; i < VertexFormats.size(); i++) { const auto &f = VertexFormats[i]; - if (f.Attrs.size() == (size_t)numAttributes && f.NumBindingPoints == numBindingPoints && f.Stride == stride) + if (f.BufferStrides.size() == bufferStrides.size() && + f.Attrs.size() == attrs.size() && + memcmp(f.BufferStrides.data(), bufferStrides.data(), bufferStrides.size() * sizeof(size_t)) == 0 && + memcmp(f.Attrs.data(), attrs.data(), attrs.size() * sizeof(FVertexBufferAttribute)) == 0) { - bool matches = true; - for (int j = 0; j < numAttributes; j++) - { - if (memcmp(&f.Attrs[j], &attrs[j], sizeof(FVertexBufferAttribute)) != 0) - { - matches = false; - break; - } - } - - if (matches) - return (int)i; + return (int)i; } } VkVertexFormat fmt; - fmt.NumBindingPoints = numBindingPoints; - fmt.Stride = stride; + fmt.BufferStrides = bufferStrides; + fmt.Attrs = attrs; fmt.UseVertexData = 0; - for (int j = 0; j < numAttributes; j++) + for (const FVertexBufferAttribute& attr : fmt.Attrs) { - if (attrs[j].location == VATTR_COLOR) + if (attr.location == VATTR_COLOR) fmt.UseVertexData |= 1; - else if (attrs[j].location == VATTR_NORMAL) + else if (attr.location == VATTR_NORMAL) fmt.UseVertexData |= 2; - fmt.Attrs.push_back(attrs[j]); } VertexFormats.push_back(fmt); return (int)VertexFormats.size() - 1; @@ -136,22 +128,18 @@ VkVertexFormat *VkRenderPassManager::GetVertexFormat(int index) return &VertexFormats[index]; } -VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers) +VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(bool levelmesh) { - if (PipelineLayouts.size() <= (size_t)numLayers) - PipelineLayouts.resize(numLayers + 1); - - auto &layout = PipelineLayouts[numLayers]; + auto &layout = PipelineLayouts[levelmesh]; if (layout) return layout.get(); auto descriptors = fb->GetDescriptorSetManager(); PipelineLayoutBuilder builder; - builder.AddSetLayout(descriptors->GetFixedSetLayout()); - builder.AddSetLayout(descriptors->GetRSBufferSetLayout()); - if (numLayers != 0) - builder.AddSetLayout(descriptors->GetTextureSetLayout(numLayers)); + builder.AddSetLayout(descriptors->GetFixedLayout()); + builder.AddSetLayout(levelmesh ? descriptors->GetLevelMeshLayout() : descriptors->GetRSBufferLayout()); + builder.AddSetLayout(descriptors->GetBindlessLayout()); builder.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants)); builder.DebugName("VkRenderPassManager.PipelineLayout"); layout = builder.Create(fb->GetDevice()); @@ -246,12 +234,13 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli VkShaderProgram *program = fb->GetShaderManager()->Get(key.ShaderKey); builder.AddVertexShader(program->vert.get()); - builder.AddFragmentShader(program->frag.get()); + if (program->frag) + builder.AddFragmentShader(program->frag.get()); const VkVertexFormat &vfmt = *fb->GetRenderPassManager()->GetVertexFormat(key.VertexFormat); - for (int i = 0; i < vfmt.NumBindingPoints; i++) - builder.AddVertexBufferBinding(i, vfmt.Stride); + for (int i = 0; i < vfmt.BufferStrides.size(); i++) + builder.AddVertexBufferBinding(i, vfmt.BufferStrides[i]); const static VkFormat vkfmts[] = { VK_FORMAT_R32G32B32A32_SFLOAT, @@ -260,7 +249,8 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli VK_FORMAT_R32_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_A2B10G10R10_SNORM_PACK32, - VK_FORMAT_R8G8B8A8_UINT + VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_R32_SINT }; bool inputLocations[VATTR_MAX] = {}; @@ -310,13 +300,18 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli // main.vp addresses this by patching up gl_Position.z, which has the side effect of flipping the sign of the front face calculations. builder.Cull(key.CullMode == Cull_None ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT, key.CullMode == Cull_CW ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE); - builder.ColorWriteMask((VkColorComponentFlags)key.ColorMask); builder.Stencil(VK_STENCIL_OP_KEEP, op2vk[key.StencilPassOp], VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0); - BlendMode(builder, key.RenderStyle); - builder.SubpassColorAttachmentCount(PassKey.DrawBuffers); + + ColorBlendAttachmentBuilder blendbuilder; + blendbuilder.ColorWriteMask((VkColorComponentFlags)key.ColorMask); + BlendMode(blendbuilder, key.RenderStyle); + + for (int i = 0; i < PassKey.DrawBuffers; i++) + builder.AddColorBlendAttachment(blendbuilder.Create()); + builder.RasterizationSamples((VkSampleCountFlagBits)PassKey.Samples); - builder.Layout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers)); + builder.Layout(fb->GetRenderPassManager()->GetPipelineLayout(key.ShaderKey.UseLevelMesh)); builder.RenderPass(GetRenderPass(0)); builder.DebugName("VkRenderPassSetup.Pipeline"); @@ -325,7 +320,7 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli ///////////////////////////////////////////////////////////////////////////// -GraphicsPipelineBuilder& BlendMode(GraphicsPipelineBuilder& builder, const FRenderStyle& style) +ColorBlendAttachmentBuilder& BlendMode(ColorBlendAttachmentBuilder& builder, const FRenderStyle& style) { // Just in case Vulkan doesn't do this optimization itself if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero && style.Flags == 0) diff --git a/src/common/rendering/vulkan/pipelines/vk_renderpass.h b/src/common/rendering/vulkan/pipelines/vk_renderpass.h index ef4d1408e8..aeba5adb75 100644 --- a/src/common/rendering/vulkan/pipelines/vk_renderpass.h +++ b/src/common/rendering/vulkan/pipelines/vk_renderpass.h @@ -11,10 +11,11 @@ #include class VulkanRenderDevice; -class GraphicsPipelineBuilder; +class ColorBlendAttachmentBuilder; class VkPPShader; class VkPPRenderPassKey; class VkPPRenderPassSetup; +class ColorBlendAttachmentBuilder; class VkPipelineKey { @@ -39,12 +40,12 @@ class VkPipelineKey }; int VertexFormat = 0; - int NumTextureLayers = 0; + int Padding0 = 0; VkShaderKey ShaderKey; FRenderStyle RenderStyle; - int Padding = 0; // for 64 bit alignment + int Padding1 = 0; // for 64 bit alignment bool operator<(const VkPipelineKey &other) const { return memcmp(this, &other, sizeof(VkPipelineKey)) < 0; } bool operator==(const VkPipelineKey &other) const { return memcmp(this, &other, sizeof(VkPipelineKey)) == 0; } @@ -90,13 +91,12 @@ class VkRenderPassSetup class VkVertexFormat { public: - int NumBindingPoints; - size_t Stride; + std::vector BufferStrides; std::vector Attrs; int UseVertexData; }; -GraphicsPipelineBuilder& BlendMode(GraphicsPipelineBuilder& builder, const FRenderStyle& style); +ColorBlendAttachmentBuilder& BlendMode(ColorBlendAttachmentBuilder& builder, const FRenderStyle& style); class VkRenderPassManager { @@ -107,9 +107,9 @@ class VkRenderPassManager void RenderBuffersReset(); VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key); - int GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs); + int GetVertexFormat(const std::vector& bufferStrides, const std::vector& attrs); VkVertexFormat *GetVertexFormat(int index); - VulkanPipelineLayout* GetPipelineLayout(int numLayers); + VulkanPipelineLayout* GetPipelineLayout(bool levelmesh); VkPPRenderPassSetup* GetPPRenderPass(const VkPPRenderPassKey& key); @@ -119,7 +119,7 @@ class VkRenderPassManager VulkanRenderDevice* fb = nullptr; std::map> RenderPassSetup; - std::vector> PipelineLayouts; + std::unique_ptr PipelineLayouts[2]; std::vector VertexFormats; std::map> PPRenderPassSetup; diff --git a/src/common/rendering/vulkan/samplers/vk_samplers.cpp b/src/common/rendering/vulkan/samplers/vk_samplers.cpp index 7d6b061de8..b35c69f755 100644 --- a/src/common/rendering/vulkan/samplers/vk_samplers.cpp +++ b/src/common/rendering/vulkan/samplers/vk_samplers.cpp @@ -32,6 +32,7 @@ #include "hw_material.h" #include "i_interface.h" #include "hwrenderer/postprocessing/hw_postprocess.h" +#include struct VkTexFilter { @@ -66,6 +67,63 @@ static VkTexClamp TexClamp[] = { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE }, }; +std::unordered_set CurrentDriverIntelDeviceIDs = +{ + // Devices out now that may have an older driver still + 0x0BDA, 0x0BD9, 0x0BDB, 0x0BD7, 0x0BD6, 0x0BD0, 0x0BD5, 0x56C0, + 0x56C1, 0x56B3, 0x56B2, 0x56A4, 0x56A3, 0x5697, 0x5696, 0x5695, + 0x56B1, 0x56B0, 0x56A6, 0x56A5, 0x56A1, 0x56A0, 0x5694, 0x5693, + 0x5692, 0x5691, 0x5690, 0xA7A9, 0xA7A8, 0xA7A1, 0xA7A0, 0xA721, + 0xA720, 0xA78B, 0xA78A, 0xA789, 0xA788, 0xA783, 0xA782, 0xA781, + 0xA780, 0x4907, 0x4905, 0x4680, 0x4682, 0x4688, 0x468A, 0x468B, + 0x4690, 0x4692, 0x4693, 0x46D0, 0x46D1, 0x46D2, 0x4626, 0x4628, + 0x462A, 0x46A0, 0x46A1, 0x46A2, 0x46A3, 0x46A6, 0x46A8, 0x46AA, + 0x46B0, 0x46B1, 0x46B2, 0x46B3, 0x46C0, 0x46C1, 0x46C2, 0x46C3, + 0x4C8A, 0x4C8B, 0x4C90, 0x4C9A, 0x4C8C, 0x4C80, 0x4E71, 0x4E61, + 0x4E57, 0x4E55, 0x4E51, 0x4571, 0x4557, 0x4555, 0x4551, 0x4541, + 0x9A59, 0x9A60, 0x9A68, 0x9A70, 0x9A40, 0x9A49, 0x9A78, 0x9AC0, + 0x9AC9, 0x9AD9, 0x9AF8 +}; + +std::unordered_set LegacyIntelDeviceIDs = +{ + // Not under active development as of 2024 + 0x8A70, 0x8A71, 0x8A56, 0x8A58, 0x8A5B, 0x8A5D, 0x8A54, 0x8A5A, + 0x8A5C, 0x8A57, 0x8A59, 0x8A50, 0x8A51, 0x8A52, 0x8A53, 0x3EA5, + 0x3EA8, 0x3EA6, 0x3EA7, 0x3EA2, 0x3E90, 0x3E93, 0x3E99, 0x3E9C, + 0x3EA1, 0x9BA5, 0x9BA8, 0x3EA4, 0x9B21, 0x9BA0, 0x9BA2, 0x9BA4, + 0x9BAA, 0x9BAB, 0x9BAC, 0x87CA, 0x3EA3, 0x9B41, 0x9BC0, 0x9BC2, + 0x9BC4, 0x9BCA, 0x9BCB, 0x9BCC, 0x3E91, 0x3E92, 0x3E98, 0x3E9B, + 0x9BC5, 0x9BC8, 0x3E96, 0x3E9A, 0x3E94, 0x9BC6, 0x9BE6, 0x9BF6, + 0x3EA9, 0x3EA0, 0x593B, 0x5923, 0x5926, 0x5927, 0x5917, 0x5912, + 0x591B, 0x5916, 0x5921, 0x591A, 0x591D, 0x591E, 0x591C, 0x87C0, + 0x5913, 0x5915, 0x5902, 0x5906, 0x590B, 0x590A, 0x5908, 0x590E, + 0x3185, 0x3184, 0x1A85, 0x5A85, 0x0A84, 0x1A84, 0x5A84, 0x192A, + 0x1932, 0x193B, 0x193A, 0x193D, 0x1923, 0x1926, 0x1927, 0x192B, + 0x192D, 0x1912, 0x191B, 0x1913, 0x1915, 0x1917, 0x191A, 0x1916, + 0x1921, 0x191D, 0x191E, 0x1902, 0x1906, 0x190B, 0x190A, 0x190E, + + // Hardware completely out of support. Generally only seen in Linux now: + 0x163D, 0x163A, 0x1632, 0x163E, 0x163B, 0x1636, 0x1622, 0x1626, + 0x162A, 0x162B, 0x162D, 0x162E, 0x1612, 0x1616, 0x161A, 0x161B, + 0x161D, 0x161E, 0x1602, 0x1606, 0x160A, 0x160B, 0x160D, 0x160E, + 0x22B0, 0x22B2, 0x22B3, 0x22B1, 0x0F30, 0x0F31, 0x0F32, 0x0F33, + 0x0157, 0x0155, 0x0422, 0x0426, 0x042A, 0x042B, 0x042E, 0x0C22, + 0x0C26, 0x0C2A, 0x0C2B, 0x0C2E, 0x0A22, 0x0A2A, 0x0A2B, 0x0D2A, + 0x0D2B, 0x0D2E, 0x0A26, 0x0A2E, 0x0D22, 0x0D26, 0x0412, 0x0416, + 0x0D12, 0x041A, 0x041B, 0x0C12, 0x0C16, 0x0C1A, 0x0C1B, 0x0C1E, + 0x0A12, 0x0A1A, 0x0A1B, 0x0D16, 0x0D1A, 0x0D1B, 0x0D1E, 0x041E, + 0x0A16, 0x0A1E, 0x0402, 0x0406, 0x040A, 0x040B, 0x040E, 0x0C02, + 0x0C06, 0x0C0A, 0x0C0B, 0x0C0E, 0x0A02, 0x0A06, 0x0A0A, 0x0A0B, + 0x0A0E, 0x0D02, 0x0D06, 0x0D0A, 0x0D0B, 0x0D0E, 0x0162, 0x0166, + 0x016A, 0x0152, 0x0156, 0x015A, 0x0112, 0x0122, 0x0116, 0x0126, + 0x0102, 0x0106, 0x010A, 0x0042, 0x0046, 0x2A42, 0x2E02, 0x2E12, + 0x2E22, 0x2E32, 0x2E42, 0x2E92, 0x29A2, 0x2982, 0x2992, 0x2972, + 0x2A02, 0x2A12, 0xA001, 0xA011, 0x29D2, 0x29C2, 0x29B2, 0x27AE, + 0x27A2, 0x2772, 0x2592, 0x258A, 0x2582, 0x2572, 0x3582, 0x358E, + 0x2562, 0x3577 +}; + VkSamplerManager::VkSamplerManager(VulkanRenderDevice* fb) : fb(fb) { CreateHWSamplers(); @@ -85,7 +143,47 @@ void VkSamplerManager::ResetHWSamplers() void VkSamplerManager::CreateHWSamplers() { - int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter()? 0 : gl_texture_filter; + int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter() ? 0 : gl_texture_filter; + + const auto& properties = fb->GetDevice()->PhysicalDevice.Properties.Properties; + + // Anisotropy puts extra load on the memory architecture. + // Unless the user explicitly chose their own filter value, default to lower filtering for integrated GPUs as they are generally slow. + float maxAnisotropy = gl_texture_filter_anisotropic; + if (maxAnisotropy < 1.0f) + { + if (properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) + maxAnisotropy = 4.0f; + else + maxAnisotropy = 8.0f; + } + + // Intel devices handles anisotropic filtering differently than what we want. + bool brokenNearestMipLinear = false; + if (properties.vendorID == 0x8086) + { + bool isLegacyDevice = LegacyIntelDeviceIDs.find(properties.deviceID) != LegacyIntelDeviceIDs.end(); + bool isCurrentDriverDevice = CurrentDriverIntelDeviceIDs.find(properties.deviceID) != CurrentDriverIntelDeviceIDs.end(); + if (isLegacyDevice || + (isCurrentDriverDevice && VK_VERSION_MAJOR(properties.driverVersion) == 0 && VK_VERSION_MINOR(properties.driverVersion) < 405) || + (isCurrentDriverDevice && VK_VERSION_MAJOR(properties.driverVersion) == 0 && VK_VERSION_MINOR(properties.driverVersion) == 405 && VK_VERSION_PATCH(properties.driverVersion) < 1286)) + { + // Old hardware and old drivers have to turn AF off if we want any nearest filtering. + if (TexFilter[filter].magFilter != VK_FILTER_LINEAR || TexFilter[filter].minFilter != VK_FILTER_LINEAR) + { + maxAnisotropy = 1.0f; + } + } + else + { + // None (trilinear) still doesn't work. Use None (linear mipmap) instead + if (filter == 6) + { + filter = 5; + } + brokenNearestMipLinear = true; + } + } for (int i = CLAMP_NONE; i <= CLAMP_XY; i++) { @@ -96,7 +194,8 @@ void VkSamplerManager::CreateHWSamplers() builder.MipmapMode(TexFilter[filter].mipfilter); if (TexFilter[filter].mipmapping) { - builder.Anisotropy(gl_texture_filter_anisotropic); + if (maxAnisotropy > 1.0f) + builder.Anisotropy(maxAnisotropy); builder.MaxLod(100.0f); // According to the spec this value is clamped so something high makes it usable for all textures. } else @@ -137,15 +236,45 @@ void VkSamplerManager::CreateHWSamplers() .MaxLod(0.25f) .DebugName("VkSamplerManager.mSamplers") .Create(fb->GetDevice()); + + { + SamplerBuilder builder; + builder.MagFilter(VK_FILTER_NEAREST); + builder.MinFilter(!brokenNearestMipLinear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST); + builder.AddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT); + builder.MipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR); + builder.MaxLod(100.0f); + if (maxAnisotropy > 1.0f) + builder.Anisotropy(maxAnisotropy); + mOverrideSamplers[int(MaterialLayerSampling::NearestMipLinear)] = builder.Create(fb->GetDevice()); + } + + { + SamplerBuilder builder; + builder.MagFilter(VK_FILTER_LINEAR); + builder.MinFilter(VK_FILTER_LINEAR); + builder.AddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT); + builder.MipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR); + builder.MaxLod(100.0f); + if (maxAnisotropy > 1.0f) + builder.Anisotropy(maxAnisotropy); + mOverrideSamplers[int(MaterialLayerSampling::LinearMipLinear)] = builder.Create(fb->GetDevice()); + } } void VkSamplerManager::DeleteHWSamplers() { - for (auto& sampler : mSamplers) + auto deleteSamplers = [&](auto& samplers) { - if (sampler) - fb->GetCommands()->DrawDeleteList->Add(std::move(sampler)); - } + for (auto& sampler : samplers) + { + if (sampler) + fb->GetCommands()->DrawDeleteList->Add(std::move(sampler)); + } + }; + + deleteSamplers(mSamplers); + deleteSamplers(mOverrideSamplers); } VulkanSampler* VkSamplerManager::Get(PPFilterMode filter, PPWrapMode wrap) diff --git a/src/common/rendering/vulkan/samplers/vk_samplers.h b/src/common/rendering/vulkan/samplers/vk_samplers.h index a7f9ac68fa..1b2eba3489 100644 --- a/src/common/rendering/vulkan/samplers/vk_samplers.h +++ b/src/common/rendering/vulkan/samplers/vk_samplers.h @@ -16,9 +16,16 @@ class VkSamplerManager void ResetHWSamplers(); - VulkanSampler *Get(int no) const { return mSamplers[no].get(); } VulkanSampler* Get(PPFilterMode filter, PPWrapMode wrap); + inline VulkanSampler* Get(int no) const { return mSamplers[no].get(); } + inline VulkanSampler* Get(MaterialLayerSampling filterOverride, int no) const + { + if (filterOverride == MaterialLayerSampling::Default) + return Get(no); + return mOverrideSamplers[int(filterOverride)].get(); + } + std::unique_ptr ShadowmapSampler; std::unique_ptr LightmapSampler; @@ -30,5 +37,6 @@ class VkSamplerManager VulkanRenderDevice* fb = nullptr; std::array, NUMSAMPLERS> mSamplers; + std::array, 2> mOverrideSamplers; std::array, 4> mPPSamplers; }; diff --git a/src/common/rendering/vulkan/shaders/vk_ppshader.cpp b/src/common/rendering/vulkan/shaders/vk_ppshader.cpp index a84470cce4..25a9030914 100644 --- a/src/common/rendering/vulkan/shaders/vk_ppshader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_ppshader.cpp @@ -26,6 +26,7 @@ #include "vulkan/commands/vk_commandbuffer.h" #include #include "filesystem.h" +#include "cmdlib.h" VkPPShader::VkPPShader(VulkanRenderDevice* fb, PPShader *shader) : fb(fb) { @@ -37,12 +38,16 @@ VkPPShader::VkPPShader(VulkanRenderDevice* fb, PPShader *shader) : fb(fb) VertexShader = ShaderBuilder() .Type(ShaderType::Vertex) .AddSource(shader->VertexShader.GetChars(), LoadShaderCode(shader->VertexShader, "", shader->Version).GetChars()) + .OnIncludeLocal([=](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, false); }) + .OnIncludeSystem([=](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, true); }) .DebugName(shader->VertexShader.GetChars()) .Create(shader->VertexShader.GetChars(), fb->GetDevice()); FragmentShader = ShaderBuilder() .Type(ShaderType::Fragment) .AddSource(shader->FragmentShader.GetChars(), LoadShaderCode(shader->FragmentShader, prolog, shader->Version).GetChars()) + .OnIncludeLocal([=](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, false); }) + .OnIncludeSystem([=](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, true); }) .DebugName(shader->FragmentShader.GetChars()) .Create(shader->FragmentShader.GetChars(), fb->GetDevice()); @@ -64,14 +69,54 @@ void VkPPShader::Reset() } } +ShaderIncludeResult VkPPShader::OnInclude(FString headerName, FString includerName, size_t depth, bool system) +{ + if (depth > 8) + I_Error("Too much include recursion!"); + + FString includeguardname; + includeguardname << "_HEADERGUARD_" << headerName.GetChars(); + includeguardname.ReplaceChars("/\\.", '_'); + + FString code; + code << "#ifndef " << includeguardname.GetChars() << "\n"; + code << "#define " << includeguardname.GetChars() << "\n"; + code << "#line 1\n"; + + if (system) + code << LoadPrivateShaderLump(headerName.GetChars()).GetChars() << "\n"; + else + code << LoadPublicShaderLump(headerName.GetChars()).GetChars() << "\n"; + + code << "#endif\n"; + + return ShaderIncludeResult(headerName.GetChars(), code.GetChars()); +} + +FString VkPPShader::LoadPublicShaderLump(const char* lumpname) +{ + int lump = fileSystem.CheckNumForFullName(lumpname, 0); + if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname); + if (lump == -1) I_Error("Unable to load '%s'", lumpname); + return GetStringFromLump(lump); +} + +FString VkPPShader::LoadPrivateShaderLump(const char* lumpname) +{ + int lump = fileSystem.CheckNumForFullName(lumpname, 0); + if (lump == -1) I_Error("Unable to load '%s'", lumpname); + return GetStringFromLump(lump); +} + FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version) { - int lump = fileSystem.CheckNumForFullName(lumpName); + int lump = fileSystem.CheckNumForFullName(lumpName.GetChars()); if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars()); - FString code = fileSystem.ReadFile(lump).GetString().GetChars(); + FString code = GetStringFromLump(lump); FString patchedCode; - patchedCode.AppendFormat("#version %d\n", 450); + patchedCode.AppendFormat("#version %d core\n", fb->GetDevice()->Instance->ApiVersion >= VK_API_VERSION_1_2 ? 460 : 450); + patchedCode << "#extension GL_GOOGLE_include_directive : enable\n"; patchedCode << defines; patchedCode << "#line 1\n"; patchedCode << code; @@ -86,10 +131,6 @@ FString VkPPShader::CreateUniformBlockDecl(const char* name, const std::vectorglslversion < 4.20) - { - layout = "std140"; - } else { layout.Format("std140, binding = %d", bindingpoint); diff --git a/src/common/rendering/vulkan/shaders/vk_ppshader.h b/src/common/rendering/vulkan/shaders/vk_ppshader.h index a8820c1f06..c5d02bcc42 100644 --- a/src/common/rendering/vulkan/shaders/vk_ppshader.h +++ b/src/common/rendering/vulkan/shaders/vk_ppshader.h @@ -6,6 +6,7 @@ #include class VulkanRenderDevice; +class ShaderIncludeResult; class VkPPShader : public PPShaderBackend { @@ -25,4 +26,8 @@ class VkPPShader : public PPShaderBackend FString LoadShaderCode(const FString &lumpname, const FString &defines, int version); static FString CreateUniformBlockDecl(const char* name, const std::vector& fields, int bindingpoint); static const char* GetTypeStr(UniformType type); + + ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system); + FString LoadPublicShaderLump(const char* lumpname); + FString LoadPrivateShaderLump(const char* lumpname); }; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 52f6803819..78dd192379 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -28,6 +28,7 @@ #include "filesystem.h" #include "engineerrors.h" #include "version.h" +#include "cmdlib.h" VkShaderManager::VkShaderManager(VulkanRenderDevice* fb) : fb(fb) { @@ -70,11 +71,13 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key) { "spheremap", "shaders/scene/frag_main.glsl", "shaders/scene/material_default.glsl", "shaders/scene/mateffect_default.glsl", "shaders/scene/lightmodel_normal.glsl", "#define SPHEREMAP\n#define NO_ALPHATEST\n" }, { "burn", "shaders/scene/frag_burn.glsl", nullptr, nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, { "stencil", "shaders/scene/frag_stencil.glsl", nullptr, nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, + { "portal", "shaders/scene/frag_portal.glsl", nullptr, nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, }; const auto& desc = effectshaders[key.SpecialEffect]; - program.vert = LoadVertShader(desc.ShaderName, mainvp, desc.defines); - program.frag = LoadFragShader(desc.ShaderName, desc.fp1, desc.fp2, desc.fp3, desc.fp4, desc.defines, key); + program.vert = LoadVertShader(desc.ShaderName, mainvp, desc.defines, key.UseLevelMesh); + if (!key.NoFragmentShader) + program.frag = LoadFragShader(desc.ShaderName, desc.fp1, desc.fp2, desc.fp3, desc.fp4, desc.defines, key); } else { @@ -111,28 +114,31 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key) if (key.EffectState < FIRST_USER_SHADER) { const auto& desc = defaultshaders[key.EffectState]; - program.vert = LoadVertShader(desc.ShaderName, mainvp, desc.Defines); - program.frag = LoadFragShader(desc.ShaderName, mainfp, desc.material_lump, desc.mateffect_lump, desc.lightmodel_lump, desc.Defines, key); + program.vert = LoadVertShader(desc.ShaderName, mainvp, desc.Defines, key.UseLevelMesh); + if (!key.NoFragmentShader) + program.frag = LoadFragShader(desc.ShaderName, mainfp, desc.material_lump, desc.mateffect_lump, desc.lightmodel_lump, desc.Defines, key); } else { const auto& desc = usershaders[key.EffectState - FIRST_USER_SHADER]; - const FString& name = ExtractFileBase(desc.shader); + const FString& name = ExtractFileBase(desc.shader.GetChars()); FString defines = defaultshaders[desc.shaderType].Defines + desc.defines; - program.vert = LoadVertShader(name, mainvp, defines); - program.frag = LoadFragShader(name, mainfp, desc.shader, defaultshaders[desc.shaderType].mateffect_lump, defaultshaders[desc.shaderType].lightmodel_lump, defines, key); + program.vert = LoadVertShader(name, mainvp, defines.GetChars(), key.UseLevelMesh); + if (!key.NoFragmentShader) + program.frag = LoadFragShader(name, mainfp, desc.shader.GetChars(), defaultshaders[desc.shaderType].mateffect_lump, defaultshaders[desc.shaderType].lightmodel_lump, defines.GetChars(), key); } } return &program; } -std::unique_ptr VkShaderManager::LoadVertShader(FString shadername, const char *vert_lump, const char *defines) +std::unique_ptr VkShaderManager::LoadVertShader(FString shadername, const char *vert_lump, const char *defines, bool levelmesh) { FString definesBlock; definesBlock << defines; - definesBlock << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; + definesBlock << "\n#define MAX_SURFACE_UNIFORMS " << std::to_string(MAX_SURFACE_UNIFORMS).c_str() << "\n"; definesBlock << "#define MAX_LIGHT_DATA " << std::to_string(MAX_LIGHT_DATA).c_str() << "\n"; + definesBlock << "#define MAX_FOGBALL_DATA " << std::to_string(MAX_FOGBALL_DATA).c_str() << "\n"; #ifdef NPOT_EMULATION definesBlock << "#define NPOT_EMULATION\n"; #endif @@ -141,6 +147,9 @@ std::unique_ptr VkShaderManager::LoadVertShader(FString shadername definesBlock << "#define NO_CLIPDISTANCE_SUPPORT\n"; } + if (levelmesh) + definesBlock << "#define USE_LEVELMESH\n"; + FString layoutBlock; layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_shared.glsl").GetChars() << "\n"; layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_vert.glsl").GetChars() << "\n"; @@ -163,10 +172,11 @@ std::unique_ptr VkShaderManager::LoadVertShader(FString shadername std::unique_ptr VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *light_lump, const char *defines, const VkShaderKey& key) { FString definesBlock; - if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) definesBlock << "\n#define SUPPORTS_RAYQUERY\n"; + if (fb->IsRayQueryEnabled()) definesBlock << "\n#define SUPPORTS_RAYQUERY\n"; definesBlock << defines; - definesBlock << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; + definesBlock << "\n#define MAX_SURFACE_UNIFORMS " << std::to_string(MAX_SURFACE_UNIFORMS).c_str() << "\n"; definesBlock << "#define MAX_LIGHT_DATA " << std::to_string(MAX_LIGHT_DATA).c_str() << "\n"; + definesBlock << "#define MAX_FOGBALL_DATA " << std::to_string(MAX_FOGBALL_DATA).c_str() << "\n"; #ifdef NPOT_EMULATION definesBlock << "#define NPOT_EMULATION\n"; #endif @@ -182,6 +192,7 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername if (key.UseRaytrace) definesBlock << "#define USE_RAYTRACE\n"; if (key.UseShadowmap) definesBlock << "#define USE_SHADOWMAP\n"; + if (key.UseLevelMesh) definesBlock << "#define USE_LEVELMESH\n"; switch (key.TextureMode) { @@ -207,6 +218,11 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername if (key.FogRadial) definesBlock << "#define FOG_RADIAL\n"; if (key.SWLightRadial) definesBlock << "#define SWLIGHT_RADIAL\n"; if (key.SWLightBanded) definesBlock << "#define SWLIGHT_BANDED\n"; + if (key.FogBalls) definesBlock << "#define FOGBALLS\n"; + + // Backwards compatibility with shaders that rape and pillage... uhm, I mean abused uFogEnabled to detect 2D rendering! + if (key.Simple2D) definesBlock << "#define uFogEnabled -3\n"; + else definesBlock << "#define uFogEnabled 0\n"; FString layoutBlock; layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_shared.glsl").GetChars() << "\n"; @@ -217,23 +233,67 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername FString materialname = "MaterialBlock"; FString materialBlock; + FString lightname = "LightBlock"; + FString lightBlock; + FString mateffectname = "MaterialEffectBlock"; + FString mateffectBlock; + if (material_lump) { materialname = material_lump; materialBlock = LoadPublicShaderLump(material_lump); + + // Attempt to fix old custom shaders: + + materialBlock = RemoveLegacyUserUniforms(materialBlock); + materialBlock.Substitute("gl_TexCoord[0]", "vTexCoord"); + + if (materialBlock.IndexOf("ProcessMaterial") < 0 && materialBlock.IndexOf("SetupMaterial") < 0) + { + // Old hardware shaders that implements GetTexCoord, ProcessTexel or Process + + if (materialBlock.IndexOf("GetTexCoord") >= 0) + { + mateffectBlock = "vec2 GetTexCoord();"; + } + + FString code; + if (materialBlock.IndexOf("ProcessTexel") >= 0) + { + code = LoadPrivateShaderLump("shaders/scene/material_legacy_ptexel.glsl"); + } + else if (materialBlock.IndexOf("Process") >= 0) + { + code = LoadPrivateShaderLump("shaders/scene/material_legacy_process.glsl"); + } + else + { + code = LoadPrivateShaderLump("shaders/scene/material_default.glsl"); + } + code << "\n#line 1\n"; + + materialBlock = code + materialBlock; + } + else if (materialBlock.IndexOf("SetupMaterial") < 0) + { + // Old hardware shader implementing SetupMaterial + + definesBlock << "#define LEGACY_USER_SHADER\n"; + + FString code = LoadPrivateShaderLump("shaders/scene/material_legacy_pmaterial.glsl"); + code << "\n#line 1\n"; + + materialBlock = code + materialBlock; + } } - FString lightname = "LightBlock"; - FString lightBlock; - if (light_lump) + if (light_lump && lightBlock.IsEmpty()) { lightname = light_lump; lightBlock << LoadPrivateShaderLump(light_lump).GetChars(); } - FString mateffectname = "MaterialEffectBlock"; - FString mateffectBlock; - if (mateffect_lump) + if (mateffect_lump && mateffectBlock.IsEmpty()) { mateffectname = mateffect_lump; mateffectBlock << LoadPrivateShaderLump(mateffect_lump).GetChars(); @@ -269,8 +329,9 @@ FString VkShaderManager::GetVersionBlock() } versionBlock << "#extension GL_GOOGLE_include_directive : enable\n"; + versionBlock << "#extension GL_EXT_nonuniform_qualifier : enable\r\n"; - if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + if (fb->IsRayQueryEnabled()) { versionBlock << "#extension GL_EXT_ray_query : enable\n"; } @@ -307,16 +368,14 @@ FString VkShaderManager::LoadPublicShaderLump(const char *lumpname) int lump = fileSystem.CheckNumForFullName(lumpname, 0); if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname); if (lump == -1) I_Error("Unable to load '%s'", lumpname); - FileData data = fileSystem.ReadFile(lump); - return data.GetString(); + return GetStringFromLump(lump); } FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname) { int lump = fileSystem.CheckNumForFullName(lumpname, 0); if (lump == -1) I_Error("Unable to load '%s'", lumpname); - FileData data = fileSystem.ReadFile(lump); - return data.GetString(); + return GetStringFromLump(lump); } VkPPShader* VkShaderManager::GetVkShader(PPShader* shader) diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index 84b52e0531..595a90299e 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -10,8 +10,6 @@ #include #include -#define SHADER_MIN_REQUIRED_TEXTURE_LAYERS 11 - class ShaderIncludeResult; class VulkanRenderDevice; class VulkanDevice; @@ -26,11 +24,11 @@ struct MatricesUBO VSMatrix TextureMatrix; }; -#define MAX_STREAM_DATA ((int)(65536 / sizeof(StreamData))) +#define MAX_SURFACE_UNIFORMS ((int)(65536 / sizeof(SurfaceUniforms))) -struct StreamUBO +struct SurfaceUniformsUBO { - StreamData data[MAX_STREAM_DATA]; + SurfaceUniforms data[MAX_SURFACE_UNIFORMS]; }; #define MAX_LIGHT_DATA ((int)(65536 / sizeof(FVector4))) @@ -40,12 +38,19 @@ struct LightBufferUBO FVector4 lights[MAX_LIGHT_DATA]; }; +#define MAX_FOGBALL_DATA ((int)(65536 / sizeof(Fogball))) + +struct FogballBufferUBO +{ + Fogball fogballs[MAX_FOGBALL_DATA]; +}; + struct PushConstants { int uDataIndex; // streamdata index int uLightIndex; // dynamic lights int uBoneIndexBase; // bone animation - int padding; + int uFogballIndex; // fog balls }; class VkShaderKey @@ -63,7 +68,7 @@ class VkShaderKey uint64_t Detailmap : 1; // uTextureMode & TEXF_Detailmap uint64_t Glowmap : 1; // uTextureMode & TEXF_Glowmap uint64_t GBufferPass : 1; // GBUFFER_PASS - uint64_t UseShadowmap : 1; // USE_SHADOWMAPS + uint64_t UseShadowmap : 1; // USE_SHADOWMAP uint64_t UseRaytrace : 1; // USE_RAYTRACE uint64_t FogBeforeLights : 1; // FOG_BEFORE_LIGHTS uint64_t FogAfterLights : 1; // FOG_AFTER_LIGHTS @@ -71,7 +76,10 @@ class VkShaderKey uint64_t SWLightRadial : 1; // SWLIGHT_RADIAL uint64_t SWLightBanded : 1; // SWLIGHT_BANDED uint64_t LightMode : 2; // LIGHTMODE_DEFAULT, LIGHTMODE_SOFTWARE, LIGHTMODE_VANILLA, LIGHTMODE_BUILD - uint64_t Unused : 45; + uint64_t UseLevelMesh : 1; // USE_LEVELMESH + uint64_t FogBalls : 1; // FOGBALLS + uint64_t NoFragmentShader : 1; + uint64_t Unused : 42; }; uint64_t AsQWORD = 0; }; @@ -111,7 +119,7 @@ class VkShaderManager void RemoveVkPPShader(VkPPShader* shader); private: - std::unique_ptr LoadVertShader(FString shadername, const char *vert_lump, const char *defines); + std::unique_ptr LoadVertShader(FString shadername, const char *vert_lump, const char *defines, bool levelmesh); std::unique_ptr LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *lightmodel_lump, const char *defines, const VkShaderKey& key); ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system); diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp index ffb9da351a..d09fc61857 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp @@ -113,7 +113,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) } else { - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; + VkFormat format = tex->IsHDR() ? VK_FORMAT_R32G32B32A32_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM; int w = tex->GetWidth(); int h = tex->GetHeight(); @@ -304,7 +304,6 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) VkMaterial::VkMaterial(VulkanRenderDevice* fb, FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags), fb(fb) { - mThreadDescriptorSets.resize(fb->MaxThreads); fb->GetDescriptorSetManager()->AddMaterial(this); } @@ -316,21 +315,15 @@ VkMaterial::~VkMaterial() void VkMaterial::DeleteDescriptors() { - if (fb) - { - auto deleteList = fb->GetCommands()->DrawDeleteList.get(); - for (auto& it : mDescriptorSets) - { - deleteList->Add(std::move(it.descriptor)); - } - mDescriptorSets.clear(); + mDescriptorSets.clear(); +} - for (auto& list : mThreadDescriptorSets) - list.clear(); - } +int VkMaterial::GetBindlessIndex(const FMaterialState& state) +{ + return GetDescriptorEntry(state).bindlessIndex; } -VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) +VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState& state) { auto base = Source(); int clampmode = state.mClampMode; @@ -341,22 +334,17 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) for (auto& set : mDescriptorSets) { - if (set.descriptor && set.clampmode == clampmode && set.remap == translationp) return set.descriptor.get(); + if (set.clampmode == clampmode && set.remap == translationp) return set; } int numLayers = NumLayers(); + auto descriptors = fb->GetDescriptorSetManager(); + auto* sampler = fb->GetSamplerManager()->Get(clampmode); - auto descriptor = fb->GetDescriptorSetManager()->AllocateTextureDescriptorSet(max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS)); - - descriptor->SetDebugName("VkHardwareTexture.mDescriptorSets"); - - VulkanSampler* sampler = fb->GetSamplerManager()->Get(clampmode); - - WriteDescriptors update; MaterialLayerInfo *layer; auto systex = static_cast(GetLayer(0, state.mTranslation, &layer)); auto systeximage = systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags); - update.AddCombinedImageSampler(descriptor.get(), 0, systeximage->View.get(), sampler, systeximage->Layout); + int bindlessIndex = descriptors->AddBindlessTextureIndex(systeximage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(0), clampmode)); if (!(layer->scaleFlags & CTF_Indexed)) { @@ -364,7 +352,7 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) { auto syslayer = static_cast(GetLayer(i, 0, &layer)); auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags); - update.AddCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout); + descriptors->AddBindlessTextureIndex(syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode)); } } else @@ -373,35 +361,11 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) { auto syslayer = static_cast(GetLayer(i, translation, &layer)); auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags); - update.AddCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout); + descriptors->AddBindlessTextureIndex(syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode)); } numLayers = 3; } - auto dummyImage = fb->GetTextureManager()->GetNullTextureView(); - for (int i = numLayers; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++) - { - update.AddCombinedImageSampler(descriptor.get(), i, dummyImage, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - } - - update.Execute(fb->GetDevice()); - mDescriptorSets.emplace_back(clampmode, translationp, std::move(descriptor)); - return mDescriptorSets.back().descriptor.get(); -} - -VulkanDescriptorSet* VkMaterial::GetDescriptorSet(int threadIndex, const FMaterialState& state) -{ - int clampmode = Source()->GetClampMode(state.mClampMode); - int translation = state.mTranslation; - auto translationp = IsLuminosityTranslation(translation) ? translation : intptr_t(GPalette.GetTranslation(GetTranslationType(translation), GetTranslationIndex(translation))); - for (auto& set : mThreadDescriptorSets[threadIndex]) - { - if (set.descriptor && set.clampmode == clampmode && set.remap == translationp) - return set.descriptor; - } - - std::unique_lock lock(fb->ThreadMutex); - VulkanDescriptorSet* descriptorset = GetDescriptorSet(state); - mThreadDescriptorSets[threadIndex].push_back(ThreadDescriptorEntry(clampmode, translationp, descriptorset)); - return descriptorset; + mDescriptorSets.emplace_back(clampmode, translationp, bindlessIndex); + return mDescriptorSets.back(); } diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.h b/src/common/rendering/vulkan/textures/vk_hwtexture.h index 99bcaa6a38..19dd71dc5f 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.h @@ -70,34 +70,24 @@ class VkMaterial : public FMaterial VulkanRenderDevice* fb = nullptr; std::list::iterator it; - VulkanDescriptorSet* GetDescriptorSet(int threadIndex, const FMaterialState& state); + int GetBindlessIndex(const FMaterialState& state); private: - VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state); - struct DescriptorEntry { int clampmode; intptr_t remap; - std::unique_ptr descriptor; + int bindlessIndex; - DescriptorEntry(int cm, intptr_t f, std::unique_ptr&& d) + DescriptorEntry(int cm, intptr_t f, int index) { clampmode = cm; remap = f; - descriptor = std::move(d); + bindlessIndex = index; } }; - struct ThreadDescriptorEntry - { - int clampmode; - intptr_t remap; - VulkanDescriptorSet* descriptor; - - ThreadDescriptorEntry(int cm, intptr_t f, VulkanDescriptorSet* d) : clampmode(cm), remap(f), descriptor(d) { } - }; + DescriptorEntry& GetDescriptorEntry(const FMaterialState& state); std::vector mDescriptorSets; - std::vector> mThreadDescriptorSets; }; diff --git a/src/common/rendering/vulkan/textures/vk_imagetransition.cpp b/src/common/rendering/vulkan/textures/vk_imagetransition.cpp index dd281e7bda..5701a18717 100644 --- a/src/common/rendering/vulkan/textures/vk_imagetransition.cpp +++ b/src/common/rendering/vulkan/textures/vk_imagetransition.cpp @@ -22,7 +22,7 @@ #include "vk_imagetransition.h" -VkImageTransition& VkImageTransition::AddImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel, int levelCount) +VkImageTransition& VkImageTransition::AddImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel, int levelCount, int baseArrayLayer, int layerCount) { if (image->Layout == targetLayout) return *this; @@ -91,7 +91,7 @@ VkImageTransition& VkImageTransition::AddImage(VkTextureImage *image, VkImageLay I_FatalError("Unimplemented dst image layout transition\n"); } - barrier.AddImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask, baseMipLevel, levelCount); + barrier.AddImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask, baseMipLevel, levelCount, baseArrayLayer, layerCount); needbarrier = true; image->Layout = targetLayout; return *this; diff --git a/src/common/rendering/vulkan/textures/vk_imagetransition.h b/src/common/rendering/vulkan/textures/vk_imagetransition.h index 3dd78a48b4..a7c179e012 100644 --- a/src/common/rendering/vulkan/textures/vk_imagetransition.h +++ b/src/common/rendering/vulkan/textures/vk_imagetransition.h @@ -19,6 +19,12 @@ class VkTextureImage for (auto &it : RSFramebuffers) deletelist->Add(std::move(it.second)); RSFramebuffers.clear(); + for (auto& framebuffer : LMFramebuffers) + deletelist->Add(std::move(framebuffer)); + LMFramebuffers.clear(); + for (auto& view : LMViews) + deletelist->Add(std::move(view)); + LMViews.clear(); deletelist->Add(std::move(DepthOnlyView)); deletelist->Add(std::move(View)); deletelist->Add(std::move(Image)); @@ -33,12 +39,14 @@ class VkTextureImage VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; std::unique_ptr PPFramebuffer; std::map> RSFramebuffers; + std::vector> LMViews; + std::vector> LMFramebuffers; }; class VkImageTransition { public: - VkImageTransition& AddImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel = 0, int levelCount = 1); + VkImageTransition& AddImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel = 0, int levelCount = 1, int baseArrayLayer = 0, int layerCount = 1); void Execute(VulkanCommandBuffer *cmdbuffer); private: diff --git a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp index 145a2ed8ed..9794228500 100644 --- a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp @@ -85,6 +85,27 @@ void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int scen mSceneHeight = sceneHeight; } +VulkanFramebuffer* VkRenderBuffers::GetFramebuffer(const VkRenderPassKey& key) +{ + auto& framebuffer = SceneColor.RSFramebuffers[key]; + if (framebuffer) + return framebuffer.get(); + + FramebufferBuilder builder; + builder.RenderPass(fb->GetRenderPassManager()->GetRenderPass(key)->GetRenderPass(0)); + builder.Size(GetWidth(), GetHeight()); + builder.AddAttachment(SceneColor.View.get()); + if (key.DrawBuffers > 1) + builder.AddAttachment(SceneFog.View.get()); + if (key.DrawBuffers > 2) + builder.AddAttachment(SceneNormal.View.get()); + if (key.DepthStencil) + builder.AddAttachment(SceneDepthStencil.View.get()); + builder.DebugName("VkRenderPassSetup.Framebuffer"); + framebuffer = builder.Create(fb->GetDevice()); + return framebuffer.get(); +} + void VkRenderBuffers::CreatePipelineDepthStencil(int width, int height) { ImageBuilder builder; diff --git a/src/common/rendering/vulkan/textures/vk_renderbuffers.h b/src/common/rendering/vulkan/textures/vk_renderbuffers.h index 360b366abc..4e9cab4da0 100644 --- a/src/common/rendering/vulkan/textures/vk_renderbuffers.h +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.h @@ -28,6 +28,8 @@ class VkRenderBuffers int GetSceneHeight() const { return mSceneHeight; } VkSampleCountFlagBits GetSceneSamples() const { return mSamples; } + VulkanFramebuffer* GetFramebuffer(const VkRenderPassKey& key); + VkTextureImage SceneColor; VkTextureImage SceneDepthStencil; VkTextureImage SceneNormal; diff --git a/src/common/rendering/vulkan/textures/vk_texture.cpp b/src/common/rendering/vulkan/textures/vk_texture.cpp index ce2edc9284..b75158f978 100644 --- a/src/common/rendering/vulkan/textures/vk_texture.cpp +++ b/src/common/rendering/vulkan/textures/vk_texture.cpp @@ -185,23 +185,28 @@ void VkTextureManager::CreateLightmap() data.Push(0); data.Push(0); data.Push(0); - data.Push(0x3c00); // half-float 1.0 - SetLightmap(1, 1, data); + CreateLightmap(1, 1, std::move(data)); } -void VkTextureManager::SetLightmap(int LMTextureSize, int LMTextureCount, const TArray& LMTextureData) +void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray&& newPixelData) { - int w = LMTextureSize; - int h = LMTextureSize; - int count = LMTextureCount; + if (LMTextureSize == newLMTextureSize && LMTextureCount == newLMTextureCount + 1 && newPixelData.Size() == 0) + return; + + LMTextureSize = newLMTextureSize; + LMTextureCount = newLMTextureCount + 1; // the extra texture is for the dynamic lightmap + + int w = newLMTextureSize; + int h = newLMTextureSize; + int count = newLMTextureCount; int pixelsize = 8; Lightmap.Reset(fb); Lightmap.Image = ImageBuilder() - .Size(w, h, 1, count) + .Size(w, h, 1, LMTextureCount) .Format(VK_FORMAT_R16G16B16A16_SFLOAT) - .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) .DebugName("VkRenderBuffers.Lightmap") .Create(fb->GetDevice()); @@ -213,41 +218,48 @@ void VkTextureManager::SetLightmap(int LMTextureSize, int LMTextureCount, const auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); - int totalSize = w * h * count * pixelsize; - - auto stagingBuffer = BufferBuilder() - .Size(totalSize) - .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) - .DebugName("VkHardwareTexture.mStagingBuffer") - .Create(fb->GetDevice()); - - uint16_t one = 0x3c00; // half-float 1.0 - const uint16_t* src = LMTextureData.Data(); - uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize); - for (int i = w * h * count; i > 0; i--) + if (count > 0 && newPixelData.Size() >= (size_t)w * h * count * 3) { - *(data++) = *(src++); - *(data++) = *(src++); - *(data++) = *(src++); - *(data++) = one; + assert(newPixelData.Size() == (size_t)w * h * count * 3); + + int totalSize = w * h * count * pixelsize; + + auto stagingBuffer = BufferBuilder() + .Size(totalSize) + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .DebugName("VkHardwareTexture.mStagingBuffer") + .Create(fb->GetDevice()); + + uint16_t one = 0x3c00; // half-float 1.0 + const uint16_t* src = newPixelData.Data(); + uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize); + for (int i = w * h * count; i > 0; i--) + { + *(data++) = *(src++); + *(data++) = *(src++); + *(data++) = *(src++); + *(data++) = one; + } + stagingBuffer->Unmap(); + + VkImageTransition() + .AddImage(&Lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, LMTextureCount) + .Execute(cmdbuffer); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = count; + region.imageExtent.depth = 1; + region.imageExtent.width = w; + region.imageExtent.height = h; + cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer)); + + newPixelData.Clear(); } - stagingBuffer->Unmap(); - - VkImageTransition() - .AddImage(&Lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, count) - .Execute(cmdbuffer); - - VkBufferImageCopy region = {}; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = count; - region.imageExtent.depth = 1; - region.imageExtent.width = w; - region.imageExtent.height = h; - cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); VkImageTransition() - .AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, count) + .AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, LMTextureCount) .Execute(cmdbuffer); - - fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer)); } diff --git a/src/common/rendering/vulkan/textures/vk_texture.h b/src/common/rendering/vulkan/textures/vk_texture.h index 16b49001ac..f829503d92 100644 --- a/src/common/rendering/vulkan/textures/vk_texture.h +++ b/src/common/rendering/vulkan/textures/vk_texture.h @@ -23,7 +23,7 @@ class VkTextureManager void BeginFrame(); - void SetLightmap(int LMTextureSize, int LMTextureCount, const TArray& LMTextureData); + void CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray&& newPixelData); VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex); VkFormat GetTextureFormat(PPTexture* texture); @@ -37,8 +37,12 @@ class VkTextureManager VulkanImage* GetNullTexture() { return NullTexture.get(); } VulkanImageView* GetNullTextureView() { return NullTextureView.get(); } + int GetHWTextureCount() { return (int)Textures.size(); } + VkTextureImage Shadowmap; VkTextureImage Lightmap; + int LMTextureSize = 0; + int LMTextureCount = 0; private: void CreateNullTexture(); diff --git a/src/common/rendering/vulkan/vk_levelmesh.cpp b/src/common/rendering/vulkan/vk_levelmesh.cpp new file mode 100644 index 0000000000..171d3c3a5e --- /dev/null +++ b/src/common/rendering/vulkan/vk_levelmesh.cpp @@ -0,0 +1,704 @@ +/* +** Vulkan backend +** Copyright (c) 2016-2020 Magnus Norddahl +** +** 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. +** +*/ + +#include "vk_levelmesh.h" +#include "zvulkan/vulkanbuilders.h" +#include "vulkan/vk_renderdevice.h" +#include "vulkan/commands/vk_commandbuffer.h" +#include "hw_levelmesh.h" +#include "hw_material.h" +#include "texturemanager.h" + +VkLevelMesh::VkLevelMesh(VulkanRenderDevice* fb) : fb(fb) +{ + useRayQuery = fb->IsRayQueryEnabled(); + + SetLevelMesh(nullptr); +} + +void VkLevelMesh::SetLevelMesh(LevelMesh* mesh) +{ + if (!mesh) + mesh = &NullMesh; + + Mesh = mesh; + CreateVulkanObjects(); +} + +void VkLevelMesh::Reset() +{ + auto deletelist = fb->GetCommands()->DrawDeleteList.get(); + deletelist->Add(std::move(VertexBuffer)); + deletelist->Add(std::move(UniformIndexBuffer)); + deletelist->Add(std::move(IndexBuffer)); + deletelist->Add(std::move(NodeBuffer)); + deletelist->Add(std::move(SurfaceBuffer)); + deletelist->Add(std::move(UniformsBuffer)); + deletelist->Add(std::move(SurfaceIndexBuffer)); + deletelist->Add(std::move(PortalBuffer)); + deletelist->Add(std::move(LightBuffer)); + deletelist->Add(std::move(LightIndexBuffer)); + deletelist->Add(std::move(StaticBLAS.ScratchBuffer)); + deletelist->Add(std::move(StaticBLAS.AccelStructBuffer)); + deletelist->Add(std::move(StaticBLAS.AccelStruct)); + deletelist->Add(std::move(DynamicBLAS.ScratchBuffer)); + deletelist->Add(std::move(DynamicBLAS.AccelStructBuffer)); + deletelist->Add(std::move(DynamicBLAS.AccelStruct)); + deletelist->Add(std::move(TopLevelAS.TransferBuffer)); + deletelist->Add(std::move(TopLevelAS.InstanceBuffer)); + deletelist->Add(std::move(TopLevelAS.ScratchBuffer)); + deletelist->Add(std::move(TopLevelAS.AccelStructBuffer)); + deletelist->Add(std::move(TopLevelAS.AccelStruct)); +} + +void VkLevelMesh::CreateVulkanObjects() +{ + Reset(); + CreateBuffers(); + UploadMeshes(false); + + if (useRayQuery) + { + // Wait for uploads to finish + PipelineBarrier() + .AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + CreateStaticBLAS(); + CreateDynamicBLAS(); + CreateTLASInstanceBuffer(); + + UploadTLASInstanceBuffer(); + + // Wait for bottom level builds to finish before using it as input to a toplevel accel structure. Also wait for the instance buffer upload to complete. + PipelineBarrier() + .AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); + + CreateTopLevelAS(DynamicBLAS.AccelStruct ? 2 : 1); + + // Finish building the accel struct before using it from the shaders + PipelineBarrier() + .AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + } + else + { + // Uploads must finish before we can read from the shaders + PipelineBarrier() + .AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + } +} + +void VkLevelMesh::BeginFrame() +{ + UploadMeshes(true); + + if (useRayQuery) + { + // Wait for uploads to finish + PipelineBarrier() + .AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + // Create a new dynamic BLAS + + // To do: we should reuse the buffers. However this requires we know when the command buffers are completely done with them first. + auto deletelist = fb->GetCommands()->DrawDeleteList.get(); + deletelist->Add(std::move(DynamicBLAS.ScratchBuffer)); + deletelist->Add(std::move(DynamicBLAS.AccelStructBuffer)); + deletelist->Add(std::move(DynamicBLAS.AccelStruct)); + deletelist->Add(std::move(TopLevelAS.TransferBuffer)); + deletelist->Add(std::move(TopLevelAS.InstanceBuffer)); + + if (Mesh->Mesh.DynamicIndexStart < (int)Mesh->Mesh.Indexes.Size()) + DynamicBLAS = CreateBLAS(true, Mesh->Mesh.DynamicIndexStart, Mesh->Mesh.Indexes.Size() - Mesh->Mesh.DynamicIndexStart); + + CreateTLASInstanceBuffer(); + UploadTLASInstanceBuffer(); + + // Wait for bottom level builds to finish before using it as input to a toplevel accel structure. Also wait for the instance buffer upload to complete. + PipelineBarrier() + .AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); + + UpdateTopLevelAS(DynamicBLAS.AccelStruct ? 2 : 1); + + // Finish building the accel struct before using it from the shaders + PipelineBarrier() + .AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + } + else + { + // Uploads must finish before we can read from the shaders + PipelineBarrier() + .AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + } +} + +void VkLevelMesh::UploadMeshes(bool dynamicOnly) +{ + if (dynamicOnly) + { + Locations.Index.Push({ Mesh->Mesh.DynamicIndexStart, (int)(Mesh->Mesh.Indexes.Size() - Mesh->Mesh.DynamicIndexStart) }); + } + else + { + if (!useRayQuery) + Locations.Node.Push({ 0, (int)Mesh->Collision->get_nodes().size() }); + Locations.Vertex.Push({ 0, (int)Mesh->Mesh.Vertices.Size() }); + Locations.Index.Push({ 0, (int)Mesh->Mesh.Indexes.Size() }); + Locations.SurfaceIndex.Push({ 0, (int)Mesh->Mesh.SurfaceIndexes.Size() }); + Locations.Surface.Push({ 0, Mesh->GetSurfaceCount() }); + Locations.UniformIndexes.Push({ 0, (int)Mesh->Mesh.UniformIndexes.Size() }); + Locations.Uniforms.Push({ 0, (int)Mesh->Mesh.Uniforms.Size() }); + Locations.Portals.Push({ 0, (int)Mesh->Portals.Size() }); + Locations.Light.Push({ 0, (int)Mesh->Mesh.Lights.Size() }); + Locations.LightIndex.Push({ 0, (int)Mesh->Mesh.LightIndexes.Size() }); + } + + VkLevelMeshUploader uploader(this); + uploader.Upload(); +} + +void VkLevelMesh::CreateBuffers() +{ + VertexBuffer = BufferBuilder() + .Usage( + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + (useRayQuery ? + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(Mesh->Mesh.MaxVertices * sizeof(FFlatVertex)) + .DebugName("VertexBuffer") + .Create(fb->GetDevice()); + + UniformIndexBuffer = BufferBuilder() + .Usage( + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->Mesh.MaxVertices * sizeof(int)) + .DebugName("UniformIndexes") + .Create(fb->GetDevice()); + + IndexBuffer = BufferBuilder() + .Usage( + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + (useRayQuery ? + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size((size_t)Mesh->Mesh.MaxIndexes * sizeof(uint32_t)) + .DebugName("IndexBuffer") + .Create(fb->GetDevice()); + + NodeBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(sizeof(CollisionNodeBufferHeader) + Mesh->Mesh.MaxNodes * sizeof(CollisionNode)) + .DebugName("NodeBuffer") + .Create(fb->GetDevice()); + + SurfaceIndexBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->Mesh.MaxSurfaceIndexes * sizeof(int)) + .DebugName("SurfaceBuffer") + .Create(fb->GetDevice()); + + SurfaceBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->Mesh.MaxSurfaces * sizeof(SurfaceInfo)) + .DebugName("SurfaceBuffer") + .Create(fb->GetDevice()); + + UniformsBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->Mesh.MaxUniforms * sizeof(SurfaceUniforms)) + .DebugName("SurfaceUniformsBuffer") + .Create(fb->GetDevice()); + + PortalBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->Portals.Size() * sizeof(PortalInfo)) + .DebugName("PortalBuffer") + .Create(fb->GetDevice()); + + LightBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->Mesh.MaxLights * sizeof(LightInfo)) + .DebugName("LightBuffer") + .Create(fb->GetDevice()); + + LightIndexBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(Mesh->Mesh.MaxLightIndexes * sizeof(int32_t)) + .DebugName("LightIndexBuffer") + .Create(fb->GetDevice()); +} + +VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(bool preferFastBuild, int indexOffset, int indexCount) +{ + BLAS blas; + + VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; + VkAccelerationStructureGeometryKHR accelStructBLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; + VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructBLDesc }; + + accelStructBLDesc.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; + accelStructBLDesc.geometry.triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR }; + accelStructBLDesc.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32A32_SFLOAT; + accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = VertexBuffer->GetDeviceAddress(); + accelStructBLDesc.geometry.triangles.vertexStride = sizeof(FFlatVertex); + accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; + accelStructBLDesc.geometry.triangles.indexData.deviceAddress = IndexBuffer->GetDeviceAddress() + indexOffset * sizeof(uint32_t); + accelStructBLDesc.geometry.triangles.maxVertex = Mesh->Mesh.Vertices.Size() - 1; + + buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + buildInfo.flags = preferFastBuild ? VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR : VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + buildInfo.geometryCount = 1; + buildInfo.ppGeometries = geometries; + + uint32_t maxPrimitiveCount = indexCount / 3; + + VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; + vkGetAccelerationStructureBuildSizesKHR(fb->GetDevice()->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo); + + blas.AccelStructBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) + .Size(sizeInfo.accelerationStructureSize) + .DebugName("BLAS.AccelStructBuffer") + .Create(fb->GetDevice()); + + blas.AccelStruct = AccelerationStructureBuilder() + .Type(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) + .Buffer(blas.AccelStructBuffer.get(), sizeInfo.accelerationStructureSize) + .DebugName("BLAS.AccelStruct") + .Create(fb->GetDevice()); + + blas.ScratchBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(sizeInfo.buildScratchSize) + .MinAlignment(fb->GetDevice()->PhysicalDevice.Properties.AccelerationStructure.minAccelerationStructureScratchOffsetAlignment) + .DebugName("BLAS.ScratchBuffer") + .Create(fb->GetDevice()); + + buildInfo.dstAccelerationStructure = blas.AccelStruct->accelstruct; + buildInfo.scratchData.deviceAddress = blas.ScratchBuffer->GetDeviceAddress(); + + VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {}; + VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo }; + rangeInfo.primitiveCount = maxPrimitiveCount; + + fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos); + + return blas; +} + +void VkLevelMesh::CreateStaticBLAS() +{ + StaticBLAS = CreateBLAS(false, 0, Mesh->Mesh.DynamicIndexStart); +} + +void VkLevelMesh::CreateDynamicBLAS() +{ + if (Mesh->Mesh.DynamicIndexStart < (int)Mesh->Mesh.Indexes.Size()) + DynamicBLAS = CreateBLAS(true, Mesh->Mesh.DynamicIndexStart, Mesh->Mesh.Indexes.Size() - Mesh->Mesh.DynamicIndexStart); +} + +void VkLevelMesh::CreateTLASInstanceBuffer() +{ + TopLevelAS.TransferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(sizeof(VkAccelerationStructureInstanceKHR) * 2) + .DebugName("TopLevelAS.TransferBuffer") + .Create(fb->GetDevice()); + + TopLevelAS.InstanceBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(sizeof(VkAccelerationStructureInstanceKHR) * 2) + .DebugName("TopLevelAS.InstanceBuffer") + .Create(fb->GetDevice()); +} + +void VkLevelMesh::CreateTopLevelAS(int instanceCount) +{ + VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; + VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; + VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructTLDesc }; + + buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + buildInfo.geometryCount = 1; + buildInfo.ppGeometries = geometries; + + accelStructTLDesc.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + accelStructTLDesc.geometry.instances = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR }; + accelStructTLDesc.geometry.instances.data.deviceAddress = TopLevelAS.InstanceBuffer->GetDeviceAddress(); + + uint32_t maxInstanceCount = 2; + + VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; + vkGetAccelerationStructureBuildSizesKHR(fb->GetDevice()->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxInstanceCount, &sizeInfo); + + TopLevelAS.AccelStructBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) + .Size(sizeInfo.accelerationStructureSize) + .DebugName("TopLevelAS.AccelStructBuffer") + .Create(fb->GetDevice()); + + TopLevelAS.AccelStruct = AccelerationStructureBuilder() + .Type(VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) + .Buffer(TopLevelAS.AccelStructBuffer.get(), sizeInfo.accelerationStructureSize) + .DebugName("TopLevelAS.AccelStruct") + .Create(fb->GetDevice()); + + TopLevelAS.ScratchBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(sizeInfo.buildScratchSize) + .MinAlignment(fb->GetDevice()->PhysicalDevice.Properties.AccelerationStructure.minAccelerationStructureScratchOffsetAlignment) + .DebugName("TopLevelAS.ScratchBuffer") + .Create(fb->GetDevice()); + + buildInfo.dstAccelerationStructure = TopLevelAS.AccelStruct->accelstruct; + buildInfo.scratchData.deviceAddress = TopLevelAS.ScratchBuffer->GetDeviceAddress(); + + VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {}; + VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo }; + rangeInfo.primitiveCount = instanceCount; + + fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos); +} + +void VkLevelMesh::UpdateTopLevelAS(int instanceCount) +{ + VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; + VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; + VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructTLDesc }; + + buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + buildInfo.geometryCount = 1; + buildInfo.ppGeometries = geometries; + + accelStructTLDesc.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + accelStructTLDesc.geometry.instances = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR }; + accelStructTLDesc.geometry.instances.data.deviceAddress = TopLevelAS.InstanceBuffer->GetDeviceAddress(); + + buildInfo.dstAccelerationStructure = TopLevelAS.AccelStruct->accelstruct; + buildInfo.scratchData.deviceAddress = TopLevelAS.ScratchBuffer->GetDeviceAddress(); + + VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {}; + VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo }; + rangeInfo.primitiveCount = instanceCount; + + fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos); +} + +void VkLevelMesh::UploadTLASInstanceBuffer() +{ + VkAccelerationStructureInstanceKHR instances[2] = {}; + instances[0].transform.matrix[0][0] = 1.0f; + instances[0].transform.matrix[1][1] = 1.0f; + instances[0].transform.matrix[2][2] = 1.0f; + instances[0].mask = 0xff; + instances[0].flags = 0; + instances[0].accelerationStructureReference = StaticBLAS.AccelStruct->GetDeviceAddress(); + + if (DynamicBLAS.AccelStruct) + { + instances[1].transform.matrix[0][0] = 1.0f; + instances[1].transform.matrix[1][1] = 1.0f; + instances[1].transform.matrix[2][2] = 1.0f; + instances[1].mask = 0xff; + instances[1].flags = 0; + instances[1].accelerationStructureReference = DynamicBLAS.AccelStruct->GetDeviceAddress(); + } + + auto data = (uint8_t*)TopLevelAS.TransferBuffer->Map(0, sizeof(VkAccelerationStructureInstanceKHR) * 2); + memcpy(data, instances, sizeof(VkAccelerationStructureInstanceKHR) * 2); + TopLevelAS.TransferBuffer->Unmap(); + + fb->GetCommands()->GetTransferCommands()->copyBuffer(TopLevelAS.TransferBuffer.get(), TopLevelAS.InstanceBuffer.get()); +} + +///////////////////////////////////////////////////////////////////////////// + +VkLevelMeshUploader::VkLevelMeshUploader(VkLevelMesh* mesh) : Mesh(mesh) +{ +} + +void VkLevelMeshUploader::Upload() +{ + size_t transferBufferSize = GetTransferSize(); + if (transferBufferSize == 0) + { + ClearRanges(); + return; + } + + BeginTransfer(transferBufferSize); + + UploadNodes(); + UploadRanges(Mesh->Locations.Vertex, Mesh->Mesh->Mesh.Vertices.Data(), Mesh->VertexBuffer.get()); + UploadRanges(Mesh->Locations.UniformIndexes, Mesh->Mesh->Mesh.UniformIndexes.Data(), Mesh->UniformIndexBuffer.get()); + UploadRanges(Mesh->Locations.Index, Mesh->Mesh->Mesh.Indexes.Data(), Mesh->IndexBuffer.get()); + UploadRanges(Mesh->Locations.SurfaceIndex, Mesh->Mesh->Mesh.SurfaceIndexes.Data(), Mesh->SurfaceIndexBuffer.get()); + UploadRanges(Mesh->Locations.LightIndex, Mesh->Mesh->Mesh.LightIndexes.Data(), Mesh->LightIndexBuffer.get()); + UploadSurfaces(); + UploadUniforms(); + UploadPortals(); + UploadLights(); + + EndTransfer(transferBufferSize); + ClearRanges(); +} + +void VkLevelMeshUploader::ClearRanges() +{ + Mesh->Locations.Vertex.clear(); + Mesh->Locations.Index.clear(); + Mesh->Locations.Node.clear(); + Mesh->Locations.SurfaceIndex.clear(); + Mesh->Locations.Surface.clear(); + Mesh->Locations.UniformIndexes.clear(); + Mesh->Locations.Uniforms.clear(); + Mesh->Locations.Portals.clear(); + Mesh->Locations.Light.clear(); + Mesh->Locations.LightIndex.clear(); +} + +void VkLevelMeshUploader::BeginTransfer(size_t transferBufferSize) +{ + cmdbuffer = Mesh->fb->GetCommands()->GetTransferCommands(); + transferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(transferBufferSize) + .DebugName("UploadMeshes") + .Create(Mesh->fb->GetDevice()); + + data = (uint8_t*)transferBuffer->Map(0, transferBufferSize); + datapos = 0; +} + +void VkLevelMeshUploader::EndTransfer(size_t transferBufferSize) +{ + assert(datapos == transferBufferSize); + + transferBuffer->Unmap(); + Mesh->fb->GetCommands()->TransferDeleteList->Add(std::move(transferBuffer)); +} + +static FVector3 SwapYZ(const FVector3& v) +{ + return FVector3(v.X, v.Z, v.Y); +} + +void VkLevelMeshUploader::UploadNodes() +{ + // Always update the header struct of the collision storage buffer block if something changed + if (Mesh->Locations.Node.Size() > 0) + { + CollisionNodeBufferHeader nodesHeader; + nodesHeader.root = Mesh->Mesh->Collision->get_root(); + + *((CollisionNodeBufferHeader*)(data + datapos)) = nodesHeader; + cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos, 0, sizeof(CollisionNodeBufferHeader)); + + datapos += sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode); + } + + // Copy collision nodes + for (const MeshBufferRange& range : Mesh->Locations.Node) + { + const auto& srcnodes = Mesh->Mesh->Collision->get_nodes(); + CollisionNode* nodes = (CollisionNode*)(data + datapos); + for (int i = 0, count = range.Size; i < count; i++) + { + const auto& node = srcnodes[range.Offset + i]; + CollisionNode info; + info.center = SwapYZ(node.aabb.Center); + info.extents = SwapYZ(node.aabb.Extents); + info.left = node.left; + info.right = node.right; + info.element_index = node.element_index; + *(nodes++) = info; + } + + size_t copysize = range.Size * sizeof(CollisionNode); + if (copysize > 0) + cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos, sizeof(CollisionNodeBufferHeader) + range.Offset * sizeof(CollisionNode), copysize); + datapos += copysize; + } +} + +template +void VkLevelMeshUploader::UploadRanges(const TArray& ranges, const T* srcbuffer, VulkanBuffer* destbuffer) +{ + for (const MeshBufferRange& range : ranges) + { + size_t copysize = range.Size * sizeof(T); + memcpy(data + datapos, srcbuffer + range.Offset, copysize); + if (copysize > 0) + cmdbuffer->copyBuffer(transferBuffer.get(), destbuffer, datapos, range.Offset * sizeof(T), copysize); + datapos += copysize; + } +} + +void VkLevelMeshUploader::UploadSurfaces() +{ + for (const MeshBufferRange& range : Mesh->Locations.Surface) + { + SurfaceInfo* surfaces = (SurfaceInfo*)(data + datapos); + for (int j = 0, count = range.Size; j < count; j++) + { + LevelMeshSurface* surface = Mesh->Mesh->GetSurface(range.Offset + j); + + SurfaceInfo info; + info.Normal = FVector3(surface->Plane.X, surface->Plane.Z, surface->Plane.Y); + info.PortalIndex = surface->PortalIndex; + info.Sky = surface->IsSky; + info.Alpha = surface->Alpha; + if (surface->Texture) + { + auto mat = FMaterial::ValidateTexture(surface->Texture, 0); + info.TextureIndex = Mesh->fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0); + } + else + { + info.TextureIndex = 0; + } + info.LightStart = surface->LightList.Pos; + info.LightEnd = surface->LightList.Pos + surface->LightList.Count; + + *(surfaces++) = info; + } + + size_t copysize = range.Size * sizeof(SurfaceInfo); + if (copysize > 0) + cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->SurfaceBuffer.get(), datapos, range.Offset * sizeof(SurfaceInfo), copysize); + datapos += copysize; + } +} + +void VkLevelMeshUploader::UploadUniforms() +{ + for (const MeshBufferRange& range : Mesh->Locations.Uniforms) + { + for (int j = 0, count = range.Size; j < count; j++) + { + auto& surfaceUniforms = Mesh->Mesh->Mesh.Uniforms[range.Offset + j]; + auto& material = Mesh->Mesh->Mesh.Materials[range.Offset + j]; + if (material.mMaterial) + { + auto source = material.mMaterial->Source(); + surfaceUniforms.uSpecularMaterial = { source->GetGlossiness(), source->GetSpecularLevel() }; + surfaceUniforms.uTextureIndex = Mesh->fb->GetBindlessTextureIndex(material.mMaterial, material.mClampMode, material.mTranslation); + } + else + { + surfaceUniforms.uTextureIndex = 0; + } + } + + SurfaceUniforms* uniforms = (SurfaceUniforms*)(data + datapos); + size_t copysize = range.Size * sizeof(SurfaceUniforms); + memcpy(uniforms, Mesh->Mesh->Mesh.Uniforms.Data(), copysize); + if (copysize > 0) + cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->UniformsBuffer.get(), datapos, range.Offset * sizeof(SurfaceUniforms), copysize); + datapos += copysize; + } +} + +void VkLevelMeshUploader::UploadPortals() +{ + for (const MeshBufferRange& range : Mesh->Locations.Portals) + { + PortalInfo* portals = (PortalInfo*)(data + datapos); + for (int i = 0, count = range.Size; i < count; i++) + { + const auto& portal = Mesh->Mesh->Portals[range.Offset + i]; + PortalInfo info; + info.transformation = portal.transformation; + *(portals++) = info; + } + + size_t copysize = range.Size * sizeof(PortalInfo); + if (copysize > 0) + cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->PortalBuffer.get(), datapos, range.Offset * sizeof(PortalInfo), copysize); + datapos += copysize; + } +} + +void VkLevelMeshUploader::UploadLights() +{ + for (const MeshBufferRange& range : Mesh->Locations.Light) + { + LightInfo* lights = (LightInfo*)(data + datapos); + for (int i = 0, count = range.Size; i < count; i++) + { + const auto& light = Mesh->Mesh->Mesh.Lights[range.Offset + i]; + LightInfo info; + info.Origin = SwapYZ(light.Origin); + info.RelativeOrigin = SwapYZ(light.RelativeOrigin); + info.Radius = light.Radius; + info.Intensity = light.Intensity; + info.InnerAngleCos = light.InnerAngleCos; + info.OuterAngleCos = light.OuterAngleCos; + info.SpotDir = SwapYZ(light.SpotDir); + info.Color = light.Color; + info.SourceRadius = light.SourceRadius; + *(lights++) = info; + } + + size_t copysize = range.Size * sizeof(LightInfo); + if (copysize > 0) + cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->LightBuffer.get(), datapos, range.Offset * sizeof(LightInfo), copysize); + datapos += copysize; + } +} + +size_t VkLevelMeshUploader::GetTransferSize() +{ + // Figure out how much memory we need to transfer it to the GPU + size_t transferBufferSize = 0; + if (Mesh->Locations.Node.Size() > 0) transferBufferSize += sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode); + for (const MeshBufferRange& range : Mesh->Locations.Node) transferBufferSize += range.Size * sizeof(CollisionNode); + for (const MeshBufferRange& range : Mesh->Locations.Vertex) transferBufferSize += range.Size * sizeof(FFlatVertex); + for (const MeshBufferRange& range : Mesh->Locations.UniformIndexes) transferBufferSize += range.Size * sizeof(int); + for (const MeshBufferRange& range : Mesh->Locations.Index) transferBufferSize += range.Size * sizeof(uint32_t); + for (const MeshBufferRange& range : Mesh->Locations.SurfaceIndex) transferBufferSize += range.Size * sizeof(int); + for (const MeshBufferRange& range : Mesh->Locations.Surface) transferBufferSize += range.Size * sizeof(SurfaceInfo); + for (const MeshBufferRange& range : Mesh->Locations.Uniforms) transferBufferSize += range.Size * sizeof(SurfaceUniforms); + for (const MeshBufferRange& range : Mesh->Locations.Portals) transferBufferSize += range.Size * sizeof(PortalInfo); + for (const MeshBufferRange& range : Mesh->Locations.LightIndex) transferBufferSize += range.Size * sizeof(int32_t); + for (const MeshBufferRange& range : Mesh->Locations.Light) transferBufferSize += range.Size * sizeof(LightInfo); + return transferBufferSize; +} diff --git a/src/common/rendering/vulkan/vk_levelmesh.h b/src/common/rendering/vulkan/vk_levelmesh.h new file mode 100644 index 0000000000..6b6eec003a --- /dev/null +++ b/src/common/rendering/vulkan/vk_levelmesh.h @@ -0,0 +1,192 @@ + +#pragma once + +#include "zvulkan/vulkanobjects.h" +#include "hw_levelmesh.h" +#include "common/utility/matrix.h" + +class VulkanRenderDevice; + +struct CollisionNodeBufferHeader +{ + int root; + int padding1; + int padding2; + int padding3; +}; + +struct CollisionNode +{ + FVector3 center; + float padding1; + FVector3 extents; + float padding2; + int left; + int right; + int element_index; + int padding3; +}; + +struct SurfaceInfo +{ + FVector3 Normal; + float Sky; + uint32_t PortalIndex; + int32_t TextureIndex; + float Alpha; + float Padding0; + uint32_t LightStart; + uint32_t LightEnd; + uint32_t Padding1; + uint32_t Padding2; +}; + +struct PortalInfo +{ + VSMatrix transformation; +}; + +struct LightInfo +{ + FVector3 Origin; + float Padding0; + FVector3 RelativeOrigin; + float Padding1; + float Radius; + float Intensity; + float InnerAngleCos; + float OuterAngleCos; + FVector3 SpotDir; + float SourceRadius; + FVector3 Color; + float Padding3; +}; + +static_assert(sizeof(LightInfo) == sizeof(float) * 20); + +struct MeshBufferRange +{ + int Offset = 0; + int Size = 0; +}; + +class VkLevelMesh +{ +public: + VkLevelMesh(VulkanRenderDevice* fb); + + void SetLevelMesh(LevelMesh* mesh); + void BeginFrame(); + + VulkanAccelerationStructure* GetAccelStruct() { return TopLevelAS.AccelStruct.get(); } + VulkanBuffer* GetVertexBuffer() { return VertexBuffer.get(); } + VulkanBuffer* GetUniformIndexBuffer() { return UniformIndexBuffer.get(); } + VulkanBuffer* GetIndexBuffer() { return IndexBuffer.get(); } + VulkanBuffer* GetNodeBuffer() { return NodeBuffer.get(); } + VulkanBuffer* GetSurfaceIndexBuffer() { return SurfaceIndexBuffer.get(); } + VulkanBuffer* GetSurfaceBuffer() { return SurfaceBuffer.get(); } + VulkanBuffer* GetUniformsBuffer() { return UniformsBuffer.get(); } + VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); } + VulkanBuffer* GetLightBuffer() { return LightBuffer.get(); } + VulkanBuffer* GetLightIndexBuffer() { return LightIndexBuffer.get(); } + + LevelMesh* GetMesh() { return Mesh; } + +private: + struct BLAS + { + std::unique_ptr ScratchBuffer; + std::unique_ptr AccelStructBuffer; + std::unique_ptr AccelStruct; + }; + + void Reset(); + void CreateVulkanObjects(); + void CreateBuffers(); + void CreateStaticBLAS(); + void CreateDynamicBLAS(); + void CreateTLASInstanceBuffer(); + void CreateTopLevelAS(int instanceCount); + + void UploadMeshes(bool dynamicOnly); + void UploadTLASInstanceBuffer(); + void UpdateTopLevelAS(int instanceCount); + + BLAS CreateBLAS(bool preferFastBuild, int indexOffset, int indexCount); + + VulkanRenderDevice* fb = nullptr; + + bool useRayQuery = true; + + LevelMesh NullMesh; + LevelMesh* Mesh = nullptr; + + struct + { + TArray Vertex; + TArray Index; + TArray Node; + TArray SurfaceIndex; + TArray Surface; + TArray UniformIndexes; + TArray Uniforms; + TArray Portals; + TArray Light; + TArray LightIndex; + } Locations; + + std::unique_ptr VertexBuffer; + std::unique_ptr UniformIndexBuffer; + std::unique_ptr IndexBuffer; + std::unique_ptr SurfaceIndexBuffer; + std::unique_ptr SurfaceBuffer; + std::unique_ptr UniformsBuffer; + std::unique_ptr PortalBuffer; + std::unique_ptr LightBuffer; + std::unique_ptr LightIndexBuffer; + + std::unique_ptr NodeBuffer; + + BLAS StaticBLAS; + BLAS DynamicBLAS; + + struct + { + std::unique_ptr TransferBuffer; + std::unique_ptr ScratchBuffer; + std::unique_ptr InstanceBuffer; + std::unique_ptr AccelStructBuffer; + std::unique_ptr AccelStruct; + } TopLevelAS; + + friend class VkLevelMeshUploader; +}; + +class VkLevelMeshUploader +{ +public: + VkLevelMeshUploader(VkLevelMesh* mesh); + + void Upload(); + +private: + void BeginTransfer(size_t transferBufferSize); + void EndTransfer(size_t transferBufferSize); + size_t GetTransferSize(); + void ClearRanges(); + + void UploadNodes(); + void UploadSurfaces(); + void UploadUniforms(); + void UploadPortals(); + void UploadLights(); + + template + void UploadRanges(const TArray& ranges, const T* srcbuffer, VulkanBuffer* destbuffer); + + VkLevelMesh* Mesh = nullptr; + uint8_t* data = nullptr; + size_t datapos = 0; + VulkanCommandBuffer* cmdbuffer = nullptr; + std::unique_ptr transferBuffer; +}; diff --git a/src/common/rendering/vulkan/vk_lightmapper.cpp b/src/common/rendering/vulkan/vk_lightmapper.cpp new file mode 100644 index 0000000000..83bac594d1 --- /dev/null +++ b/src/common/rendering/vulkan/vk_lightmapper.cpp @@ -0,0 +1,1096 @@ + +#include "vk_lightmapper.h" +#include "vulkan/vk_renderdevice.h" +#include "vulkan/textures/vk_texture.h" +#include "vulkan/commands/vk_commandbuffer.h" +#include "vulkan/descriptorsets/vk_descriptorset.h" +#include "vk_levelmesh.h" +#include "zvulkan/vulkanbuilders.h" +#include "filesystem.h" +#include "cmdlib.h" + +static int lastSurfaceCount; +static glcycle_t lightmapRaytraceLast; + +static uint32_t lastPixelCount; + +ADD_STAT(lightmapper) +{ + FString out; + out.Format("CPU time: %.3fms\nSurface count: %d\nPixel count: %u K", lightmapRaytraceLast.TimeMS(), lastSurfaceCount, lastPixelCount / 1024); + return out; +} + +CVAR(Int, lm_background_updates, 8, CVAR_NOSAVE); +CVAR(Int, lm_max_updates, 128, CVAR_NOSAVE); +CVAR(Float, lm_scale, 1.0, CVAR_NOSAVE); +CVAR(Bool, lm_sunlight, true, CVAR_ARCHIVE); +CVAR(Bool, lm_blur, true, CVAR_ARCHIVE); +CVAR(Bool, lm_ao, false, CVAR_ARCHIVE); +CVAR(Bool, lm_softshadows, true, CVAR_ARCHIVE); +CVAR(Bool, lm_bounce, false, CVAR_ARCHIVE); + +VkLightmapper::VkLightmapper(VulkanRenderDevice* fb) : fb(fb) +{ + useRayQuery = fb->IsRayQueryEnabled(); + + try + { + CreateUniformBuffer(); + CreateTileBuffer(); + CreateDrawIndexedBuffer(); + + CreateShaders(); + CreateRaytracePipeline(); + CreateResolvePipeline(); + CreateBlurPipeline(); + CreateCopyPipeline(); + CreateBakeImage(); + } + catch (...) + { + ReleaseResources(); + throw; + } +} + +VkLightmapper::~VkLightmapper() +{ + ReleaseResources(); +} + +void VkLightmapper::ReleaseResources() +{ + if (copytiles.Buffer) + copytiles.Buffer->Unmap(); + if (drawindexed.CommandsBuffer) + drawindexed.CommandsBuffer->Unmap(); + if (drawindexed.ConstantsBuffer) + drawindexed.ConstantsBuffer->Unmap(); +} + +void VkLightmapper::SetLevelMesh(LevelMesh* level) +{ + mesh = level; + UpdateAccelStructDescriptors(); + + lightmapRaytraceLast.Reset(); + lastPixelCount = 0; + lastSurfaceCount = 0; +} + +void VkLightmapper::BeginFrame() +{ + drawindexed.Pos = 0; +} + +void VkLightmapper::Raytrace(const TArray& tiles) +{ + if (mesh && tiles.Size() > 0) + { + lightmapRaytraceLast.active = true; + + lightmapRaytraceLast.ResetAndClock(); + + SelectTiles(tiles); + if (selectedTiles.Size() > 0) + { + fb->GetCommands()->PushGroup(fb->GetCommands()->GetTransferCommands(), "lightmap.total"); + + UploadUniforms(); + Render(); + Resolve(); + if (lm_blur) + Blur(); + CopyResult(); + + fb->GetCommands()->PopGroup(fb->GetCommands()->GetTransferCommands()); + } + + lightmapRaytraceLast.Unclock(); + } +} + +void VkLightmapper::SelectTiles(const TArray& tiles) +{ + bakeImage.maxX = 0; + bakeImage.maxY = 0; + selectedTiles.Clear(); + + // We use a 3 texel spacing between rectangles so that the blur pass will not pick up anything from a neighbour tile. + RectPacker packer(bakeImageSize, bakeImageSize, RectPacker::Spacing(3), RectPacker::Padding(3)); + + for (int i = 0, count = tiles.Size(); i < count; i++) + { + LightmapTile* tile = tiles[i]; + + if (!tile->NeedsUpdate) + continue; + + // Only grab surfaces until our bake texture is full + auto result = packer.insert(tile->AtlasLocation.Width, tile->AtlasLocation.Height); + if (result.pageIndex == 0) + { + SelectedTile selected; + selected.Tile = tile; + selected.X = result.pos.x; + selected.Y = result.pos.y; + selectedTiles.Push(selected); + + bakeImage.maxX = std::max(bakeImage.maxX, uint16_t(result.pos.x + tile->AtlasLocation.Width)); + bakeImage.maxY = std::max(bakeImage.maxY, uint16_t(result.pos.y + tile->AtlasLocation.Height)); + + tile->NeedsUpdate = false; + } + } + + // Include the padding + bakeImage.maxX += 3; + bakeImage.maxY += 3; +} + +void VkLightmapper::Render() +{ + auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); + + fb->GetCommands()->PushGroup(cmdbuffer, "lightmap.raytrace"); + + RenderPassBegin() + .RenderPass(raytrace.renderPass.get()) + .RenderArea(0, 0, bakeImage.maxX, bakeImage.maxY) + .Framebuffer(bakeImage.raytrace.Framebuffer.get()) + .AddClearColor(0.0f, 0.0f, 0.0f, 0.0f) + .Execute(cmdbuffer); + + VkDeviceSize offset = 0; + cmdbuffer->bindVertexBuffers(0, 1, &fb->GetLevelMesh()->GetVertexBuffer()->buffer, &offset); + cmdbuffer->bindIndexBuffer(fb->GetLevelMesh()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32); + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipeline[GetRaytracePipelineIndex()].get()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 0, raytrace.descriptorSet0.get()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 1, raytrace.descriptorSet1.get()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 2, fb->GetDescriptorSetManager()->GetBindlessSet()); + + VkViewport viewport = {}; + viewport.maxDepth = 1; + viewport.width = (float)bakeImageSize; + viewport.height = (float)bakeImageSize; + cmdbuffer->setViewport(0, 1, &viewport); + + for (int i = 0, count = selectedTiles.Size(); i < count; i++) + { + auto& selectedTile = selectedTiles[i]; + LightmapTile* targetTile = selectedTile.Tile; + + LightmapRaytracePC pc; + pc.TileX = (float)selectedTile.X; + pc.TileY = (float)selectedTile.Y; + pc.TextureSize = (float)bakeImageSize; + pc.TileWidth = (float)targetTile->AtlasLocation.Width; + pc.TileHeight = (float)targetTile->AtlasLocation.Height; + pc.WorldToLocal = SwapYZ(targetTile->Transform.TranslateWorldToLocal); + pc.ProjLocalToU = SwapYZ(targetTile->Transform.ProjLocalToU); + pc.ProjLocalToV = SwapYZ(targetTile->Transform.ProjLocalToV); + + bool buffersFull = false; + + // Paint all surfaces visible in the tile + for (int surfaceIndex : targetTile->Surfaces) + { + LevelMeshSurface* surface = mesh->GetSurface(surfaceIndex); + pc.SurfaceIndex = surfaceIndex; + + VkDrawIndexedIndirectCommand cmd; + cmd.indexCount = surface->MeshLocation.NumElements; + cmd.instanceCount = 1; + cmd.firstIndex = surface->MeshLocation.StartElementIndex; + cmd.vertexOffset = 0; + cmd.firstInstance = drawindexed.Pos; + drawindexed.Constants[drawindexed.Pos] = pc; + drawindexed.Commands[drawindexed.Pos] = cmd; + drawindexed.Pos++; + + if (drawindexed.Pos == drawindexed.BufferSize) + { + // Our indirect draw buffer is full. Postpone the rest. + buffersFull = true; + break; + } + } + + if (buffersFull) + { + while (i < count) + { + selectedTiles[i].Tile->NeedsUpdate = true; + i++; + } + break; + } + + selectedTile.Rendered = true; + } + + cmdbuffer->drawIndexedIndirect(drawindexed.CommandsBuffer->buffer, 0, drawindexed.Pos, sizeof(VkDrawIndexedIndirectCommand)); + + cmdbuffer->endRenderPass(); + + fb->GetCommands()->PopGroup(cmdbuffer); +} + +void VkLightmapper::UploadUniforms() +{ + Uniforms values = {}; + values.SunDir = SwapYZ(mesh->SunDirection); + values.SunColor = mesh->SunColor; + values.SunIntensity = 1.0f; + + uniforms.Uniforms = (uint8_t*)uniforms.TransferBuffer->Map(0, uniforms.NumStructs * uniforms.StructStride); + *reinterpret_cast(uniforms.Uniforms + uniforms.StructStride * uniforms.Index) = values; + uniforms.TransferBuffer->Unmap(); + + auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); + cmdbuffer->copyBuffer(uniforms.TransferBuffer.get(), uniforms.Buffer.get()); + PipelineBarrier() + .AddBuffer(uniforms.Buffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); +} + +void VkLightmapper::Resolve() +{ + auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); + + fb->GetCommands()->PushGroup(cmdbuffer, "lightmap.resolve"); + + PipelineBarrier() + .AddImage(bakeImage.raytrace.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + RenderPassBegin() + .RenderPass(resolve.renderPass.get()) + .RenderArea(0, 0, bakeImage.maxX, bakeImage.maxY) + .Framebuffer(bakeImage.resolve.Framebuffer.get()) + .Execute(cmdbuffer); + + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, resolve.pipeline.get()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, resolve.pipelineLayout.get(), 0, bakeImage.resolve.DescriptorSet.get()); + + VkViewport viewport = {}; + viewport.maxDepth = 1; + viewport.width = (float)bakeImage.maxX; + viewport.height = (float)bakeImage.maxY; + cmdbuffer->setViewport(0, 1, &viewport); + + cmdbuffer->draw(3, 1, 0, 0); + + cmdbuffer->endRenderPass(); + + fb->GetCommands()->PopGroup(cmdbuffer); +} + +void VkLightmapper::Blur() +{ + auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); + + fb->GetCommands()->PushGroup(cmdbuffer, "lightmap.blur"); + + PipelineBarrier() + .AddImage(bakeImage.resolve.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + // Pass 0 + { + RenderPassBegin() + .RenderPass(blur.renderPass.get()) + .RenderArea(0, 0, bakeImage.maxX, bakeImage.maxY) + .Framebuffer(bakeImage.blur.Framebuffer.get()) + .Execute(cmdbuffer); + + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, blur.pipeline[0].get()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, blur.pipelineLayout.get(), 0, bakeImage.blur.DescriptorSet[0].get()); + + VkViewport viewport = {}; + viewport.maxDepth = 1; + viewport.width = (float)bakeImage.maxX; + viewport.height = (float)bakeImage.maxY; + cmdbuffer->setViewport(0, 1, &viewport); + + cmdbuffer->draw(3, 1, 0, 0); + + cmdbuffer->endRenderPass(); + } + + PipelineBarrier() + .AddImage(bakeImage.blur.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + // Pass 1 (outputs back into resolve fb) + { + RenderPassBegin() + .RenderPass(blur.renderPass.get()) + .RenderArea(0, 0, bakeImage.maxX, bakeImage.maxY) + .Framebuffer(bakeImage.resolve.Framebuffer.get()) + .Execute(cmdbuffer); + + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, blur.pipeline[1].get()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, blur.pipelineLayout.get(), 0, bakeImage.blur.DescriptorSet[1].get()); + + VkViewport viewport = {}; + viewport.maxDepth = 1; + viewport.width = (float)bakeImage.maxX; + viewport.height = (float)bakeImage.maxY; + cmdbuffer->setViewport(0, 1, &viewport); + + cmdbuffer->draw(3, 1, 0, 0); + + cmdbuffer->endRenderPass(); + } + + fb->GetCommands()->PopGroup(cmdbuffer); +} + +void VkLightmapper::CopyResult() +{ + // Sort by destination + uint32_t pixels = 0; + lastSurfaceCount = 0; + for (auto& list : copylists) list.Clear(); + for (int i = 0, count = selectedTiles.Size(); i < count; i++) + { + auto& selected = selectedTiles[i]; + if (selected.Rendered) + { + unsigned int pageIndex = (unsigned int)selected.Tile->AtlasLocation.ArrayIndex; + if (pageIndex >= copylists.Size()) + { + copylists.Resize(pageIndex + 1); + } + copylists[pageIndex].Push(&selected); + + pixels += selected.Tile->AtlasLocation.Area(); + lastSurfaceCount++; + } + } + lastPixelCount = pixels; + + if (pixels == 0) + return; + + VkTextureImage* destTexture = &fb->GetTextureManager()->Lightmap; + int destSize = fb->GetTextureManager()->LMTextureSize; + + auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); + + fb->GetCommands()->PushGroup(cmdbuffer, "lightmap.copy"); + + // Transition lightmap destination images to be used as framebuffers and the resolve image as sampling source + PipelineBarrier barrier0; + barrier0.AddImage(bakeImage.resolve.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); + for (unsigned int i = 0, count = copylists.Size(); i < count; i++) + { + if (copylists[i].Size() > 0) + barrier0.AddImage(destTexture->Image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, i, 1); + } + barrier0.Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + // Copy into the lightmap images + int start = 0; + int pos = 0; + for (unsigned int i = 0, count = copylists.Size(); i < count; i++) + { + auto& list = copylists[i]; + if (list.Size() == 0) + continue; + + // Create framebuffer object if it doesn't exist + if (i >= destTexture->LMFramebuffers.size()) + { + destTexture->LMViews.resize(i + 1); + destTexture->LMFramebuffers.resize(i + 1); + } + + auto& framebuffer = destTexture->LMFramebuffers[i]; + if (!framebuffer) + { + auto& view = destTexture->LMViews[i]; + if (!view) + { + view = ImageViewBuilder() + .Type(VK_IMAGE_VIEW_TYPE_2D) + .Image(destTexture->Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT, 0, i, 1, 1) + .DebugName("LMView") + .Create(fb->GetDevice()); + } + + framebuffer = FramebufferBuilder() + .RenderPass(copy.renderPass.get()) + .Size(destSize, destSize) + .AddAttachment(view.get()) + .DebugName("LMFramebuffer") + .Create(fb->GetDevice()); + } + + // Copy the tile positions into a storage buffer for the vertex shader to read + start = pos; + for (SelectedTile* selected : list) + { + LightmapTile* tile = selected->Tile; + + CopyTileInfo* copyinfo = ©tiles.Tiles[pos++]; + copyinfo->SrcPosX = selected->X; + copyinfo->SrcPosY = selected->Y; + copyinfo->DestPosX = tile->AtlasLocation.X; + copyinfo->DestPosY = tile->AtlasLocation.Y; + copyinfo->TileWidth = tile->AtlasLocation.Width; + copyinfo->TileHeight = tile->AtlasLocation.Height; + } + + // Draw the tiles. One instance per tile. + RenderPassBegin() + .RenderPass(copy.renderPass.get()) + .RenderArea(0, 0, destSize, destSize) + .Framebuffer(framebuffer.get()) + .Execute(cmdbuffer); + + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, copy.pipeline.get()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, copy.pipelineLayout.get(), 0, bakeImage.copy.DescriptorSet.get()); + + VkViewport viewport = {}; + viewport.maxDepth = 1; + viewport.width = (float)destSize; + viewport.height = (float)destSize; + cmdbuffer->setViewport(0, 1, &viewport); + + LightmapCopyPC pc; + pc.SrcTexSize = bakeImageSize; + pc.DestTexSize = destSize; + cmdbuffer->pushConstants(copy.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(LightmapCopyPC), &pc); + + cmdbuffer->draw(4, pos - start, 0, start); + + cmdbuffer->endRenderPass(); + } + + // Transition lightmap destination images back to be used for fragment shader sampling + PipelineBarrier barrier1; + for (unsigned int i = 0, count = copylists.Size(); i < count; i++) + { + if (copylists[i].Size() > 0) + barrier1.AddImage(destTexture->Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, i, 1); + } + barrier1.Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + fb->GetCommands()->PopGroup(cmdbuffer); +} + +void VkLightmapper::CreateShaders() +{ + std::string prefix = "#version 460\r\n"; + std::string traceprefix = "#version 460\r\n"; + prefix += "#extension GL_GOOGLE_include_directive : enable\n"; + + traceprefix += "#extension GL_GOOGLE_include_directive : enable\n"; + traceprefix += "#extension GL_EXT_nonuniform_qualifier : enable\r\n"; + if (useRayQuery) + { + traceprefix += "#extension GL_EXT_ray_query : require\r\n"; + traceprefix += "#define USE_RAYQUERY\r\n"; + } + + auto onIncludeLocal = [](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, false); }; + auto onIncludeSystem = [](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, true); }; + + shaders.vertRaytrace = ShaderBuilder() + .Type(ShaderType::Vertex) + .AddSource("VersionBlock", prefix) + .AddSource("vert_raytrace.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_raytrace.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmapper.VertRaytrace") + .Create("VkLightmapper.VertRaytrace", fb->GetDevice()); + + shaders.vertScreenquad = ShaderBuilder() + .Type(ShaderType::Vertex) + .AddSource("VersionBlock", prefix) + .AddSource("vert_screenquad.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_screenquad.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmapper.VertScreenquad") + .Create("VkLightmapper.VertScreenquad", fb->GetDevice()); + + shaders.vertCopy = ShaderBuilder() + .Type(ShaderType::Vertex) + .AddSource("VersionBlock", prefix) + .AddSource("vert_copy.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_copy.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmapper.VertCopy") + .Create("VkLightmapper.VertCopy", fb->GetDevice()); + + for (int i = 0; i < 16; i++) + { + std::string defines = traceprefix; + if (i & 1) + defines += "#define USE_SOFTSHADOWS\n"; + if (i & 2) + defines += "#define USE_AO\n"; + if (i & 4) + defines += "#define USE_SUNLIGHT\n"; + if (i & 8) + defines += "#define USE_BOUNCE\n"; + + shaders.fragRaytrace[i] = ShaderBuilder() + .Type(ShaderType::Fragment) + .AddSource("VersionBlock", defines) + .AddSource("frag_raytrace.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_raytrace.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmapper.FragRaytrace") + .Create("VkLightmapper.FragRaytrace", fb->GetDevice()); + } + + shaders.fragResolve = ShaderBuilder() + .Type(ShaderType::Fragment) + .AddSource("VersionBlock", prefix) + .AddSource("frag_resolve.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_resolve.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmapper.FragResolve") + .Create("VkLightmapper.FragResolve", fb->GetDevice()); + + shaders.fragBlur[0] = ShaderBuilder() + .Type(ShaderType::Fragment) + .AddSource("VersionBlock", prefix + "#define BLUR_HORIZONTAL\r\n") + .AddSource("frag_blur.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_blur.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmapper.FragBlur") + .Create("VkLightmapper.FragBlur", fb->GetDevice()); + + shaders.fragBlur[1] = ShaderBuilder() + .Type(ShaderType::Fragment) + .AddSource("VersionBlock", prefix + "#define BLUR_VERTICAL\r\n") + .AddSource("frag_blur.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_blur.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmapper.FragBlur") + .Create("VkLightmapper.FragBlur", fb->GetDevice()); + + shaders.fragCopy = ShaderBuilder() + .Type(ShaderType::Fragment) + .AddSource("VersionBlock", prefix) + .AddSource("frag_copy.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_copy.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmapper.FragCopy") + .Create("VkLightmapper.FragCopy", fb->GetDevice()); +} + +int VkLightmapper::GetRaytracePipelineIndex() +{ + int index = 0; + if (lm_softshadows && useRayQuery) + index |= 1; + if (lm_ao && useRayQuery) + index |= 2; + if (lm_sunlight && mesh->SunColor != FVector3(0.0f, 0.0f, 0.0f)) + index |= 4; + if (lm_bounce) + index |= 8; + return index; +} + +FString VkLightmapper::LoadPrivateShaderLump(const char* lumpname) +{ + int lump = fileSystem.CheckNumForFullName(lumpname, 0); + if (lump == -1) I_Error("Unable to load '%s'", lumpname); + return GetStringFromLump(lump); +} + +FString VkLightmapper::LoadPublicShaderLump(const char* lumpname) +{ + int lump = fileSystem.CheckNumForFullName(lumpname, 0); + if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname); + if (lump == -1) I_Error("Unable to load '%s'", lumpname); + return GetStringFromLump(lump); +} + +ShaderIncludeResult VkLightmapper::OnInclude(FString headerName, FString includerName, size_t depth, bool system) +{ + if (depth > 8) + I_Error("Too much include recursion!"); + + FString includeguardname; + includeguardname << "_HEADERGUARD_" << headerName.GetChars(); + includeguardname.ReplaceChars("/\\.", '_'); + + FString code; + code << "#ifndef " << includeguardname.GetChars() << "\n"; + code << "#define " << includeguardname.GetChars() << "\n"; + code << "#line 1\n"; + + if (system) + code << LoadPrivateShaderLump(headerName.GetChars()).GetChars() << "\n"; + else + code << LoadPublicShaderLump(headerName.GetChars()).GetChars() << "\n"; + + code << "#endif\n"; + + return ShaderIncludeResult(headerName.GetChars(), code.GetChars()); +} + +void VkLightmapper::CreateRaytracePipeline() +{ + raytrace.descriptorSetLayout0 = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) + .DebugName("raytrace.descriptorSetLayout0") + .Create(fb->GetDevice()); + + if (useRayQuery) + { + raytrace.descriptorSetLayout1 = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .DebugName("raytrace.descriptorSetLayout1") + .Create(fb->GetDevice()); + } + else + { + raytrace.descriptorSetLayout1 = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .DebugName("raytrace.descriptorSetLayout1") + .Create(fb->GetDevice()); + } + + raytrace.pipelineLayout = PipelineLayoutBuilder() + .AddSetLayout(raytrace.descriptorSetLayout0.get()) + .AddSetLayout(raytrace.descriptorSetLayout1.get()) + .AddSetLayout(fb->GetDescriptorSetManager()->GetBindlessLayout()) + .DebugName("raytrace.pipelineLayout") + .Create(fb->GetDevice()); + + raytrace.renderPass = RenderPassBuilder() + .AddAttachment( + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_SAMPLE_COUNT_4_BIT, + VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddSubpass() + .AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddExternalSubpassDependency( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) + .DebugName("raytrace.renderPass") + .Create(fb->GetDevice()); + + for (int i = 0; i < 16; i++) + { + raytrace.pipeline[i] = GraphicsPipelineBuilder() + .Layout(raytrace.pipelineLayout.get()) + .RenderPass(raytrace.renderPass.get()) + .AddVertexShader(shaders.vertRaytrace.get()) + .AddFragmentShader(shaders.fragRaytrace[i].get()) + .AddVertexBufferBinding(0, sizeof(FFlatVertex)) + .AddVertexAttribute(0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0) + .Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) + .AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT) + .RasterizationSamples(VK_SAMPLE_COUNT_4_BIT) + .Viewport(0.0f, 0.0f, 0.0f, 0.0f) + .Scissor(0, 0, 4096, 4096) + .DebugName("raytrace.pipeline") + .Create(fb->GetDevice()); + } + + raytrace.descriptorPool0 = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 6) + .MaxSets(1) + .DebugName("raytrace.descriptorPool0") + .Create(fb->GetDevice()); + + if (useRayQuery) + { + raytrace.descriptorPool1 = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2) + .MaxSets(1) + .DebugName("raytrace.descriptorPool1") + .Create(fb->GetDevice()); + } + else + { + raytrace.descriptorPool1 = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3) + .MaxSets(1) + .DebugName("raytrace.descriptorPool1") + .Create(fb->GetDevice()); + } + + raytrace.descriptorSet0 = raytrace.descriptorPool0->allocate(raytrace.descriptorSetLayout0.get()); + raytrace.descriptorSet0->SetDebugName("raytrace.descriptorSet1"); + + raytrace.descriptorSet1 = raytrace.descriptorPool1->allocate(raytrace.descriptorSetLayout1.get()); + raytrace.descriptorSet1->SetDebugName("raytrace.descriptorSet1"); +} + +void VkLightmapper::UpdateAccelStructDescriptors() +{ + if (useRayQuery) + { + WriteDescriptors() + .AddAccelerationStructure(raytrace.descriptorSet1.get(), 0, fb->GetLevelMesh()->GetAccelStruct()) + .AddBuffer(raytrace.descriptorSet1.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer()) + .AddBuffer(raytrace.descriptorSet1.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer()) + .Execute(fb->GetDevice()); + } + else + { + WriteDescriptors() + .AddBuffer(raytrace.descriptorSet1.get(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetNodeBuffer()) + .AddBuffer(raytrace.descriptorSet1.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer()) + .AddBuffer(raytrace.descriptorSet1.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer()) + .Execute(fb->GetDevice()); + } + + WriteDescriptors() + .AddBuffer(raytrace.descriptorSet0.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniforms.Buffer.get(), 0, sizeof(Uniforms)) + .AddBuffer(raytrace.descriptorSet0.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceIndexBuffer()) + .AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceBuffer()) + .AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetLightBuffer()) + .AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetLightIndexBuffer()) + .AddBuffer(raytrace.descriptorSet0.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer()) + .AddBuffer(raytrace.descriptorSet0.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, drawindexed.ConstantsBuffer.get(), 0, drawindexed.BufferSize * sizeof(LightmapRaytracePC)) + .Execute(fb->GetDevice()); +} + +void VkLightmapper::CreateResolvePipeline() +{ + resolve.descriptorSetLayout = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .DebugName("resolve.descriptorSetLayout") + .Create(fb->GetDevice()); + + resolve.pipelineLayout = PipelineLayoutBuilder() + .AddSetLayout(resolve.descriptorSetLayout.get()) + .DebugName("resolve.pipelineLayout") + .Create(fb->GetDevice()); + + resolve.renderPass = RenderPassBuilder() + .AddAttachment( + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_SAMPLE_COUNT_1_BIT, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddSubpass() + .AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddExternalSubpassDependency( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) + .DebugName("resolve.renderpass") + .Create(fb->GetDevice()); + + resolve.pipeline = GraphicsPipelineBuilder() + .Layout(resolve.pipelineLayout.get()) + .RenderPass(resolve.renderPass.get()) + .AddVertexShader(shaders.vertScreenquad.get()) + .AddFragmentShader(shaders.fragResolve.get()) + .Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) + .AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT) + .Viewport(0.0f, 0.0f, 0.0f, 0.0f) + .Scissor(0, 0, 4096, 4096) + .DebugName("resolve.pipeline") + .Create(fb->GetDevice()); + + resolve.descriptorPool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) + .MaxSets(1) + .DebugName("resolve.descriptorPool") + .Create(fb->GetDevice()); + + resolve.sampler = SamplerBuilder() + .DebugName("resolve.Sampler") + .Create(fb->GetDevice()); +} + +void VkLightmapper::CreateBlurPipeline() +{ + blur.descriptorSetLayout = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .DebugName("blur.descriptorSetLayout") + .Create(fb->GetDevice()); + + blur.pipelineLayout = PipelineLayoutBuilder() + .AddSetLayout(blur.descriptorSetLayout.get()) + .DebugName("blur.pipelineLayout") + .Create(fb->GetDevice()); + + blur.renderPass = RenderPassBuilder() + .AddAttachment( + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_SAMPLE_COUNT_1_BIT, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddSubpass() + .AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddExternalSubpassDependency( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) + .DebugName("blur.renderpass") + .Create(fb->GetDevice()); + + for (int i = 0; i < 2; i++) + { + blur.pipeline[i] = GraphicsPipelineBuilder() + .Layout(blur.pipelineLayout.get()) + .RenderPass(blur.renderPass.get()) + .AddVertexShader(shaders.vertScreenquad.get()) + .AddFragmentShader(shaders.fragBlur[i].get()) + .Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) + .AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT) + .Viewport(0.0f, 0.0f, 0.0f, 0.0f) + .Scissor(0, 0, 4096, 4096) + .DebugName("blur.pipeline") + .Create(fb->GetDevice()); + } + + blur.descriptorPool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) + .MaxSets(2) + .DebugName("blur.descriptorPool") + .Create(fb->GetDevice()); + + blur.sampler = SamplerBuilder() + .MinFilter(VK_FILTER_NEAREST) + .MagFilter(VK_FILTER_NEAREST) + .MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) + .DebugName("blur.Sampler") + .Create(fb->GetDevice()); +} + +void VkLightmapper::CreateCopyPipeline() +{ + copy.descriptorSetLayout = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT) + .DebugName("copy.descriptorSetLayout") + .Create(fb->GetDevice()); + + copy.pipelineLayout = PipelineLayoutBuilder() + .AddSetLayout(copy.descriptorSetLayout.get()) + .AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(LightmapCopyPC)) + .DebugName("copy.pipelineLayout") + .Create(fb->GetDevice()); + + copy.renderPass = RenderPassBuilder() + .AddAttachment( + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_SAMPLE_COUNT_1_BIT, + VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddSubpass() + .AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .AddExternalSubpassDependency( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) + .DebugName("copy.renderpass") + .Create(fb->GetDevice()); + + copy.pipeline = GraphicsPipelineBuilder() + .Layout(copy.pipelineLayout.get()) + .RenderPass(copy.renderPass.get()) + .AddVertexShader(shaders.vertCopy.get()) + .AddFragmentShader(shaders.fragCopy.get()) + .Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) + .AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT) + .Viewport(0.0f, 0.0f, 0.0f, 0.0f) + .Scissor(0, 0, 4096, 4096) + .DebugName("copy.pipeline") + .Create(fb->GetDevice()); + + copy.descriptorPool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1) + .MaxSets(1) + .DebugName("copy.descriptorPool") + .Create(fb->GetDevice()); + + copy.sampler = SamplerBuilder() + .DebugName("copy.Sampler") + .Create(fb->GetDevice()); +} + +void VkLightmapper::CreateBakeImage() +{ + int width = bakeImageSize; + int height = bakeImageSize; + + bakeImage.raytrace.Image = ImageBuilder() + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Size(width, height) + .Samples(VK_SAMPLE_COUNT_4_BIT) + .DebugName("LightmapImage.raytrace.Image") + .Create(fb->GetDevice()); + + bakeImage.raytrace.View = ImageViewBuilder() + .Image(bakeImage.raytrace.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("LightmapImage.raytrace.View") + .Create(fb->GetDevice()); + + bakeImage.raytrace.Framebuffer = FramebufferBuilder() + .RenderPass(raytrace.renderPass.get()) + .Size(width, height) + .AddAttachment(bakeImage.raytrace.View.get()) + .DebugName("LightmapImage.raytrace.Framebuffer") + .Create(fb->GetDevice()); + + bakeImage.resolve.Image = ImageBuilder() + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Size(width, height) + .DebugName("LightmapImage.resolve.Image") + .Create(fb->GetDevice()); + + bakeImage.resolve.View = ImageViewBuilder() + .Image(bakeImage.resolve.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("LightmapImage.resolve.View") + .Create(fb->GetDevice()); + + bakeImage.resolve.Framebuffer = FramebufferBuilder() + .RenderPass(resolve.renderPass.get()) + .Size(width, height) + .AddAttachment(bakeImage.resolve.View.get()) + .DebugName("LightmapImage.resolve.Framebuffer") + .Create(fb->GetDevice()); + + bakeImage.resolve.DescriptorSet = resolve.descriptorPool->allocate(resolve.descriptorSetLayout.get()); + bakeImage.resolve.DescriptorSet->SetDebugName("resolve.descriptorSet"); + + + bakeImage.blur.Image = ImageBuilder() + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Size(width, height) + .DebugName("LightmapImage.blur.Image") + .Create(fb->GetDevice()); + + bakeImage.blur.View = ImageViewBuilder() + .Image(bakeImage.blur.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("LightmapImage.blur.View") + .Create(fb->GetDevice()); + + bakeImage.blur.Framebuffer = FramebufferBuilder() + .RenderPass(blur.renderPass.get()) + .Size(width, height) + .AddAttachment(bakeImage.blur.View.get()) + .DebugName("LightmapImage.blur.Framebuffer") + .Create(fb->GetDevice()); + + bakeImage.blur.DescriptorSet[0] = blur.descriptorPool->allocate(blur.descriptorSetLayout.get()); + bakeImage.blur.DescriptorSet[0]->SetDebugName("blur.descriptorSet"); + + bakeImage.blur.DescriptorSet[1] = blur.descriptorPool->allocate(blur.descriptorSetLayout.get()); + bakeImage.blur.DescriptorSet[1]->SetDebugName("blur.descriptorSet"); + + bakeImage.copy.DescriptorSet = copy.descriptorPool->allocate(copy.descriptorSetLayout.get()); + bakeImage.copy.DescriptorSet->SetDebugName("copy.descriptorSet"); + + WriteDescriptors() + .AddCombinedImageSampler(bakeImage.resolve.DescriptorSet.get(), 0, bakeImage.raytrace.View.get(), resolve.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + .AddCombinedImageSampler(bakeImage.blur.DescriptorSet[0].get(), 0, bakeImage.resolve.View.get(), blur.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + .AddCombinedImageSampler(bakeImage.blur.DescriptorSet[1].get(), 0, bakeImage.blur.View.get(), blur.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + .AddCombinedImageSampler(bakeImage.copy.DescriptorSet.get(), 0, bakeImage.resolve.View.get(), blur.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + .AddBuffer(bakeImage.copy.DescriptorSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, copytiles.Buffer.get()) + .Execute(fb->GetDevice()); +} + +void VkLightmapper::CreateUniformBuffer() +{ + VkDeviceSize align = fb->GetDevice()->PhysicalDevice.Properties.Properties.limits.minUniformBufferOffsetAlignment; + uniforms.StructStride = (sizeof(Uniforms) + align - 1) / align * align; + + uniforms.Buffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(uniforms.NumStructs * uniforms.StructStride) + .DebugName("LightmapUniformBuffer") + .Create(fb->GetDevice()); + + uniforms.TransferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU) + .Size(uniforms.NumStructs * uniforms.StructStride) + .DebugName("LightmapUniformTransferBuffer") + .Create(fb->GetDevice()); +} + +void VkLightmapper::CreateTileBuffer() +{ + size_t size = sizeof(CopyTileInfo) * copytiles.BufferSize; + + copytiles.Buffer = BufferBuilder() + .Usage( + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT) + .MemoryType( + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + .Size(size) + .DebugName("CopyTileBuffer") + .Create(fb->GetDevice()); + + copytiles.Tiles = (CopyTileInfo*)copytiles.Buffer->Map(0, size); +} + +void VkLightmapper::CreateDrawIndexedBuffer() +{ + size_t size1 = sizeof(VkDrawIndexedIndirectCommand) * drawindexed.BufferSize; + size_t size2 = sizeof(LightmapRaytracePC) * drawindexed.BufferSize; + + drawindexed.CommandsBuffer = BufferBuilder() + .Usage( + VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, + VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT) + .MemoryType( + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + .Size(size1) + .DebugName("DrawIndexed.CommandsBuffer") + .Create(fb->GetDevice()); + + drawindexed.ConstantsBuffer = BufferBuilder() + .Usage( + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT) + .MemoryType( + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + .Size(size2) + .DebugName("DrawIndexed.ConstantsBuffer") + .Create(fb->GetDevice()); + + drawindexed.Commands = (VkDrawIndexedIndirectCommand*)drawindexed.CommandsBuffer->Map(0, size1); + drawindexed.Constants = (LightmapRaytracePC*)drawindexed.ConstantsBuffer->Map(0, size2); +} diff --git a/src/common/rendering/vulkan/vk_lightmapper.h b/src/common/rendering/vulkan/vk_lightmapper.h new file mode 100644 index 0000000000..ac2944cf85 --- /dev/null +++ b/src/common/rendering/vulkan/vk_lightmapper.h @@ -0,0 +1,236 @@ +#pragma once + +#include "common/rendering/hwrenderer/data/hw_levelmesh.h" +#include "zvulkan/vulkanobjects.h" +#include + +typedef dp::rect_pack::RectPacker RectPacker; + +class VulkanRenderDevice; +class FString; +class ShaderIncludeResult; + +struct Uniforms +{ + FVector3 SunDir; + float Padding1; + FVector3 SunColor; + float SunIntensity; +}; + +struct LightmapRaytracePC +{ + int32_t SurfaceIndex; + int32_t Padding0; + int32_t Padding1; + int32_t Padding2; + FVector3 WorldToLocal; + float TextureSize; + FVector3 ProjLocalToU; + float Padding3; + FVector3 ProjLocalToV; + float Padding4; + float TileX; + float TileY; + float TileWidth; + float TileHeight; +}; + +struct LightmapCopyPC +{ + int SrcTexSize; + int DestTexSize; + int Padding1; + int Padding2; +}; + +struct LightmapBakeImage +{ + struct + { + std::unique_ptr Image; + std::unique_ptr View; + std::unique_ptr Framebuffer; + } raytrace; + + struct + { + std::unique_ptr Image; + std::unique_ptr View; + std::unique_ptr Framebuffer; + std::unique_ptr DescriptorSet; + } resolve; + + struct + { + std::unique_ptr Image; + std::unique_ptr View; + std::unique_ptr Framebuffer; + std::unique_ptr DescriptorSet[2]; + } blur; + + struct + { + std::unique_ptr DescriptorSet; + } copy; + + // how much of the image is used for the baking + uint16_t maxX = 0; + uint16_t maxY = 0; +}; + +struct SelectedTile +{ + LightmapTile* Tile = nullptr; + int X = -1; + int Y = -1; + bool Rendered = false; +}; + +struct CopyTileInfo +{ + int SrcPosX; + int SrcPosY; + int DestPosX; + int DestPosY; + int TileWidth; + int TileHeight; + int Padding1; + int Padding2; +}; + +static_assert(sizeof(CopyTileInfo) == sizeof(int32_t) * 8); + +class VkLightmapper +{ +public: + VkLightmapper(VulkanRenderDevice* fb); + ~VkLightmapper(); + + void BeginFrame(); + void Raytrace(const TArray& surfaces); + void SetLevelMesh(LevelMesh* level); + +private: + void ReleaseResources(); + + void SelectTiles(const TArray& surfaces); + void UploadUniforms(); + void Render(); + void Resolve(); + void Blur(); + void CopyResult(); + + void UpdateAccelStructDescriptors(); + + void CreateShaders(); + void CreateRaytracePipeline(); + void CreateResolvePipeline(); + void CreateBlurPipeline(); + void CreateCopyPipeline(); + void CreateUniformBuffer(); + void CreateTileBuffer(); + void CreateDrawIndexedBuffer(); + void CreateBakeImage(); + + int GetRaytracePipelineIndex(); + + static FString LoadPrivateShaderLump(const char* lumpname); + static FString LoadPublicShaderLump(const char* lumpname); + static ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system); + + FVector3 SwapYZ(const FVector3& v) { return FVector3(v.X, v.Z, v.Y); } + + VulkanRenderDevice* fb = nullptr; + LevelMesh* mesh = nullptr; + + bool useRayQuery = true; + + TArray selectedTiles; + TArray> copylists; + + struct + { + std::unique_ptr Buffer; + std::unique_ptr TransferBuffer; + + uint8_t* Uniforms = nullptr; + int Index = 0; + int NumStructs = 256; + VkDeviceSize StructStride = sizeof(Uniforms); + } uniforms; + + struct + { + const int BufferSize = 100'000; + std::unique_ptr Buffer; + CopyTileInfo* Tiles = nullptr; + } copytiles; + + struct + { + const int BufferSize = 100'000; + std::unique_ptr CommandsBuffer; + std::unique_ptr ConstantsBuffer; + VkDrawIndexedIndirectCommand* Commands = nullptr; + LightmapRaytracePC* Constants = nullptr; + int Pos = 0; + } drawindexed; + + struct + { + std::unique_ptr vertRaytrace; + std::unique_ptr vertScreenquad; + std::unique_ptr vertCopy; + std::unique_ptr fragRaytrace[16]; + std::unique_ptr fragResolve; + std::unique_ptr fragBlur[2]; + std::unique_ptr fragCopy; + } shaders; + + struct + { + std::unique_ptr descriptorSetLayout0; + std::unique_ptr descriptorSetLayout1; + std::unique_ptr pipelineLayout; + std::unique_ptr pipeline[16]; + std::unique_ptr renderPass; + std::unique_ptr descriptorPool0; + std::unique_ptr descriptorPool1; + std::unique_ptr descriptorSet0; + std::unique_ptr descriptorSet1; + } raytrace; + + struct + { + std::unique_ptr descriptorSetLayout; + std::unique_ptr pipelineLayout; + std::unique_ptr pipeline; + std::unique_ptr renderPass; + std::unique_ptr descriptorPool; + std::unique_ptr sampler; + } resolve; + + struct + { + std::unique_ptr descriptorSetLayout; + std::unique_ptr pipelineLayout; + std::unique_ptr pipeline[2]; + std::unique_ptr renderPass; + std::unique_ptr descriptorPool; + std::unique_ptr sampler; + } blur; + + struct + { + std::unique_ptr descriptorSetLayout; + std::unique_ptr pipelineLayout; + std::unique_ptr pipeline; + std::unique_ptr renderPass; + std::unique_ptr descriptorPool; + std::unique_ptr sampler; + } copy; + + LightmapBakeImage bakeImage; + static const int bakeImageSize = 2048; +}; diff --git a/src/common/rendering/vulkan/vk_postprocess.cpp b/src/common/rendering/vulkan/vk_postprocess.cpp index 41b80239f1..ae4b93c4cc 100644 --- a/src/common/rendering/vulkan/vk_postprocess.cpp +++ b/src/common/rendering/vulkan/vk_postprocess.cpp @@ -61,14 +61,12 @@ void VkPostprocess::SetActiveRenderTarget() .AddImage(&buffers->PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false) .Execute(fb->GetCommands()->GetDrawCommands()); - for (int i = 0; i < fb->MaxThreads; i++) - fb->GetRenderState(i)->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], buffers->PipelineDepthStencil.View.get(), buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT); + fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], buffers->PipelineDepthStencil.View.get(), buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT); } void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) { - for (int i = 0; i < fb->MaxThreads; i++) - fb->GetRenderState(i)->EndRenderPass(); + fb->GetRenderState()->EndRenderPass(); fb->GetCommands()->FlushCommands(false); int sceneWidth = fb->GetBuffers()->GetSceneWidth(); @@ -84,8 +82,7 @@ void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::functi void VkPostprocess::BlitSceneToPostprocess() { - for (int i = 0; i < fb->MaxThreads; i++) - fb->GetRenderState(i)->EndRenderPass(); + fb->GetRenderState()->EndRenderPass(); auto buffers = fb->GetBuffers(); auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); @@ -154,8 +151,7 @@ void VkPostprocess::ImageTransitionScene(bool undefinedSrcLayout) void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout finallayout) { - for (int i = 0; i < fb->MaxThreads; i++) - fb->GetRenderState(i)->EndRenderPass(); + fb->GetRenderState()->EndRenderPass(); auto srcimage = &fb->GetBuffers()->PipelineImage[mCurrentPipelineImage]; auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); diff --git a/src/common/rendering/vulkan/vk_pprenderstate.cpp b/src/common/rendering/vulkan/vk_pprenderstate.cpp index 231cb5e551..6d2cbe372b 100644 --- a/src/common/rendering/vulkan/vk_pprenderstate.cpp +++ b/src/common/rendering/vulkan/vk_pprenderstate.cpp @@ -43,17 +43,17 @@ VkPPRenderState::VkPPRenderState(VulkanRenderDevice* fb) : fb(fb) void VkPPRenderState::PushGroup(const FString &name) { - fb->GetCommands()->PushGroup(name); + fb->GetCommands()->PushGroup(fb->GetCommands()->GetDrawCommands(), name); } void VkPPRenderState::PopGroup() { - fb->GetCommands()->PopGroup(); + fb->GetCommands()->PopGroup(fb->GetCommands()->GetDrawCommands()); } void VkPPRenderState::Draw() { - fb->GetRenderState(0)->EndRenderPass(); + fb->GetRenderState()->EndRenderPass(); VkPPRenderPassKey key; key.BlendMode = BlendMode; diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index 0fb2974580..9898b2a9b1 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -38,11 +38,13 @@ #include "hw_cvars.h" #include "hw_skydome.h" #include "flatvertices.h" +#include "hw_meshbuilder.h" #include "vk_renderdevice.h" #include "vulkan/vk_renderstate.h" #include "vulkan/vk_postprocess.h" -#include "vulkan/accelstructs/vk_raytrace.h" +#include "vulkan/vk_levelmesh.h" +#include "vulkan/vk_lightmapper.h" #include "vulkan/pipelines/vk_renderpass.h" #include "vulkan/descriptorsets/vk_descriptorset.h" #include "vulkan/shaders/vk_shader.h" @@ -61,16 +63,22 @@ #include #include "engineerrors.h" #include "c_dispatch.h" +#include "menu.h" +#include "cmdlib.h" FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames = -1); -EXTERN_CVAR(Bool, r_drawvoxels) EXTERN_CVAR(Int, gl_tonemap) EXTERN_CVAR(Int, screenblocks) EXTERN_CVAR(Bool, cl_capfps) +EXTERN_CVAR(Bool, r_skipmats) // Physical device info static std::vector SupportedDevices; +int vkversion; +static TArray memheapnames; +static TArray membudgets; +static int hwtexturecount; CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { @@ -84,6 +92,11 @@ CUSTOM_CVAR(Int, vk_device, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCAL Printf("This won't take effect until " GAMENAME " is restarted.\n"); } +CUSTOM_CVAR(Bool, vk_rayquery, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + Printf("This won't take effect until " GAMENAME " is restarted.\n"); +} + CCMD(vk_listdevices) { for (size_t i = 0; i < SupportedDevices.size(); i++) @@ -92,6 +105,38 @@ CCMD(vk_listdevices) } } +CCMD(vk_membudget) +{ + for (size_t i = 0; i < membudgets.size(); i++) + { + if (membudgets[i].budget != 0) + { + Printf("#%d%s - %d MB used out of %d MB estimated budget (%d%%)\n", + i, memheapnames[i].GetChars(), + (int)(membudgets[i].usage / (1024 * 1024)), + (int)(membudgets[i].budget / (1024 * 1024)), + (int)(membudgets[i].usage * 100 / membudgets[i].budget)); + } + else + { + Printf("#%d %s - %d MB used\n", + i, memheapnames[i].GetChars(), + (int)(membudgets[i].usage / (1024 * 1024))); + } + } + Printf("%d total hardware textures\n", hwtexturecount); +} + +void I_BuildVKDeviceList(FOptionValues* opt) +{ + for (size_t i = 0; i < SupportedDevices.size(); i++) + { + unsigned int idx = opt->mValues.Reserve(1); + opt->mValues[idx].Value = (double)i; + opt->mValues[idx].Text = SupportedDevices[i].Device->Properties.Properties.deviceName; + } +} + void VulkanError(const char* text) { throw CVulkanError(text); @@ -119,10 +164,22 @@ VulkanRenderDevice::VulkanRenderDevice(void *hMonitor, bool fullscreen, std::sha { VulkanDeviceBuilder builder; builder.OptionalRayQuery(); + builder.RequireExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); builder.Surface(surface); builder.SelectDevice(vk_device); SupportedDevices = builder.FindDevices(surface->Instance); mDevice = builder.Create(surface->Instance); + + bool supportsBindless = + mDevice->EnabledFeatures.DescriptorIndexing.descriptorBindingPartiallyBound && + mDevice->EnabledFeatures.DescriptorIndexing.runtimeDescriptorArray && + mDevice->EnabledFeatures.DescriptorIndexing.shaderSampledImageArrayNonUniformIndexing; + if (!supportsBindless) + { + I_FatalError("This GPU does not support the minimum requirements of this application"); + } + + mUseRayQuery = vk_rayquery && mDevice->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && mDevice->PhysicalDevice.Features.RayQuery.rayQuery; } VulkanRenderDevice::~VulkanRenderDevice() @@ -134,6 +191,7 @@ VulkanRenderDevice::~VulkanRenderDevice() if (mDescriptorSetManager) mDescriptorSetManager->Deinit(); + mCommands->DeleteFrameObjects(); if (mTextureManager) mTextureManager->Deinit(); if (mBufferManager) @@ -162,10 +220,8 @@ void VulkanRenderDevice::InitializeState() default: vendorstring = "Unknown"; break; } - hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE; - glslversion = 4.50f; uniformblockalignment = (unsigned int)mDevice->PhysicalDevice.Properties.Properties.limits.minUniformBufferOffsetAlignment; - maxuniformblock = mDevice->PhysicalDevice.Properties.Properties.limits.maxUniformBufferRange; + maxuniformblock = std::min(mDevice->PhysicalDevice.Properties.Properties.limits.maxUniformBufferRange, (uint32_t)1024 * 1024); mCommands.reset(new VkCommandBufferManager(this)); @@ -181,7 +237,8 @@ void VulkanRenderDevice::InitializeState() mPostprocess.reset(new VkPostprocess(this)); mDescriptorSetManager.reset(new VkDescriptorSetManager(this)); mRenderPassManager.reset(new VkRenderPassManager(this)); - mRaytrace.reset(new VkRaytrace(this)); + mLevelMesh.reset(new VkLevelMesh(this)); + mLightmapper.reset(new VkLightmapper(this)); mBufferManager->Init(); @@ -191,14 +248,11 @@ void VulkanRenderDevice::InitializeState() mShaderManager.reset(new VkShaderManager(this)); mDescriptorSetManager->Init(); - for (int threadIndex = 0; threadIndex < MaxThreads; threadIndex++) - { #ifdef __APPLE__ - mRenderState.push_back(std::make_unique(this)); + mRenderState = std::make_unique(this); #else - mRenderState.push_back(std::make_unique(this, 0)); + mRenderState = std::make_unique(this); #endif - } } void VulkanRenderDevice::Update() @@ -213,11 +267,8 @@ void VulkanRenderDevice::Update() Draw2D(); twod->Clear(); - for (auto& renderstate : mRenderState) - { - renderstate->EndRenderPass(); - renderstate->EndFrame(); - } + mRenderState->EndRenderPass(); + mRenderState->EndFrame(); Flush3D.Unclock(); @@ -239,19 +290,13 @@ void VulkanRenderDevice::RenderTextureView(FCanvasTexture* tex, std::functionGetImage(tex, 0, 0); VkTextureImage *depthStencil = BaseLayer->GetDepthStencil(tex); - for (auto& renderstate : mRenderState) - { - renderstate->EndRenderPass(); - } + mRenderState->EndRenderPass(); VkImageTransition() .AddImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false) .Execute(mCommands->GetDrawCommands()); - for (auto& renderstate : mRenderState) - { - renderstate->SetRenderTarget(image, depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT); - } + mRenderState->SetRenderTarget(image, depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT); IntRect bounds; bounds.left = bounds.top = 0; @@ -260,19 +305,13 @@ void VulkanRenderDevice::RenderTextureView(FCanvasTexture* tex, std::functionEndRenderPass(); - } + mRenderState->EndRenderPass(); VkImageTransition() .AddImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) .Execute(mCommands->GetDrawCommands()); - for (auto& renderstate : mRenderState) - { - renderstate->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); - } + mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); tex->SetUpdated(true); } @@ -464,28 +503,46 @@ TArray VulkanRenderDevice::GetScreenshotBuffer(int &pitch, ESSType &col void VulkanRenderDevice::BeginFrame() { + vmaSetCurrentFrameIndex(mDevice->allocator, 0); + membudgets.Resize(mDevice->PhysicalDevice.Properties.Memory.memoryHeapCount); + vmaGetHeapBudgets(mDevice->allocator, membudgets.data()); + if (memheapnames.size() == 0) + { + memheapnames.Resize(mDevice->PhysicalDevice.Properties.Memory.memoryHeapCount); + for (unsigned int i = 0; i < memheapnames.Size(); i++) + { + bool deviceLocal = !!(mDevice->PhysicalDevice.Properties.Memory.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT); + memheapnames[i] = deviceLocal ? " (device local)" : ""; + } + } + hwtexturecount = mTextureManager->GetHWTextureCount(); + + if (levelMeshChanged) + { + levelMeshChanged = false; + mLevelMesh->SetLevelMesh(levelMesh); + + if (levelMesh && levelMesh->LMTextureCount > 0) + { + GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData)); + GetLightmapper()->SetLevelMesh(levelMesh); + } + } + SetViewportRects(nullptr); mCommands->BeginFrame(); + mLevelMesh->BeginFrame(); mTextureManager->BeginFrame(); mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); mSaveBuffers->BeginFrame(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT); - for (auto& renderstate : mRenderState) - renderstate->BeginFrame(); + mRenderState->BeginFrame(); mDescriptorSetManager->BeginFrame(); -} - -void VulkanRenderDevice::InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData) -{ - if (LMTextureData.Size() > 0) - { - GetTextureManager()->SetLightmap(LMTextureSize, LMTextureCount, LMTextureData); - LMTextureData.Reset(); // We no longer need this, release the memory - } + mLightmapper->BeginFrame(); } void VulkanRenderDevice::Draw2D() { - ::Draw2D(twod, *RenderState(0)); + ::Draw2D(twod, *RenderState()); } void VulkanRenderDevice::WaitForCommands(bool finish) @@ -511,6 +568,7 @@ void VulkanRenderDevice::PrintStartupLog() FString apiVersion, driverVersion; apiVersion.Format("%d.%d.%d", VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion), VK_VERSION_PATCH(props.apiVersion)); driverVersion.Format("%d.%d.%d", VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion), VK_VERSION_PATCH(props.driverVersion)); + vkversion = VK_API_VERSION_MAJOR(props.apiVersion) * 100 + VK_API_VERSION_MINOR(props.apiVersion); Printf("Vulkan device: " TEXTCOLOR_ORANGE "%s\n", props.deviceName); Printf("Vulkan device type: %s\n", deviceType.GetChars()); @@ -529,9 +587,15 @@ void VulkanRenderDevice::PrintStartupLog() Printf("Min. uniform buffer offset alignment: %" PRIu64 "\n", limits.minUniformBufferOffsetAlignment); } -void VulkanRenderDevice::SetLevelMesh(hwrenderer::LevelMesh* mesh) +void VulkanRenderDevice::SetLevelMesh(LevelMesh* mesh) { - mRaytrace->SetLevelMesh(mesh); + levelMesh = mesh; + levelMeshChanged = true; +} + +void VulkanRenderDevice::UpdateLightmaps(const TArray& tiles) +{ + GetLightmapper()->Raytrace(tiles); } void VulkanRenderDevice::SetShadowMaps(const TArray& lights, hwrenderer::LevelAABBTree* tree, bool newTree) @@ -565,9 +629,9 @@ void VulkanRenderDevice::ImageTransitionScene(bool unknown) mPostprocess->ImageTransitionScene(unknown); } -FRenderState* VulkanRenderDevice::RenderState(int threadIndex) +FRenderState* VulkanRenderDevice::RenderState() { - return mRenderState[threadIndex].get(); + return mRenderState.get(); } void VulkanRenderDevice::AmbientOccludeScene(float m5) @@ -577,8 +641,123 @@ void VulkanRenderDevice::AmbientOccludeScene(float m5) void VulkanRenderDevice::SetSceneRenderTarget(bool useSSAO) { - for (auto& renderstate : mRenderState) + mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); +} + +int VulkanRenderDevice::GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation) +{ + FMaterialState materialState; + materialState.mMaterial = material; + materialState.mClampMode = clampmode; + materialState.mTranslation = translation; + return static_cast(material)->GetBindlessIndex(materialState); +} + +int VulkanRenderDevice::GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material) +{ + if (levelVertexFormatIndex == -1) { - renderstate->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); + static const std::vector format = + { + { 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FFlatVertex, x) }, + { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }, + { 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FFlatVertex, lu) }, + { 1, VATTR_UNIFORM_INDEXES, VFmt_Int, 0 } + }; + levelVertexFormatIndex = GetRenderPassManager()->GetVertexFormat({ sizeof(FFlatVertex), sizeof(int32_t) }, format); } + + VkPipelineKey pipelineKey; + pipelineKey.DrawType = DT_Triangles; + pipelineKey.VertexFormat = levelVertexFormatIndex; + pipelineKey.RenderStyle = applyData.RenderStyle; + pipelineKey.DepthFunc = applyData.DepthFunc; + if (applyData.SpecialEffect > EFF_NONE) + { + pipelineKey.ShaderKey.SpecialEffect = applyData.SpecialEffect; + pipelineKey.ShaderKey.EffectState = 0; + pipelineKey.ShaderKey.AlphaTest = false; + } + else + { + int effectState = material.mOverrideShader >= 0 ? material.mOverrideShader : (material.mMaterial ? material.mMaterial->GetShaderIndex() : 0); + pipelineKey.ShaderKey.SpecialEffect = EFF_NONE; + pipelineKey.ShaderKey.EffectState = applyData.TextureEnabled ? effectState : SHADER_NoTexture; + if (r_skipmats && pipelineKey.ShaderKey.EffectState >= 3 && pipelineKey.ShaderKey.EffectState <= 4) + pipelineKey.ShaderKey.EffectState = 0; + pipelineKey.ShaderKey.AlphaTest = surfaceUniforms.uAlphaThreshold >= 0.f; + } + + int tempTM = (material.mMaterial && material.mMaterial->Source()->isHardwareCanvas()) ? TM_OPAQUE : TM_NORMAL; + int f = applyData.TextureModeFlags; + if (!applyData.BrightmapEnabled) f &= ~(TEXF_Brightmap | TEXF_Glowmap); + if (applyData.TextureClamp) f |= TEXF_ClampY; + int uTextureMode = (applyData.TextureMode == TM_NORMAL && tempTM == TM_OPAQUE ? TM_OPAQUE : applyData.TextureMode) | f; + + pipelineKey.ShaderKey.TextureMode = uTextureMode & 0xffff; + pipelineKey.ShaderKey.ClampY = (uTextureMode & TEXF_ClampY) != 0; + pipelineKey.ShaderKey.Brightmap = (uTextureMode & TEXF_Brightmap) != 0; + pipelineKey.ShaderKey.Detailmap = (uTextureMode & TEXF_Detailmap) != 0; + pipelineKey.ShaderKey.Glowmap = (uTextureMode & TEXF_Glowmap) != 0; + + // The way GZDoom handles state is just plain insanity! + int fogset = 0; + if (applyData.FogEnabled) + { + if (applyData.FogEnabled == 2) + { + fogset = -3; // 2D rendering with 'foggy' overlay. + } + else if (applyData.FogColor) + { + fogset = gl_fogmode; + } + else + { + fogset = -gl_fogmode; + } + } + pipelineKey.ShaderKey.Simple2D = (fogset == -3); + pipelineKey.ShaderKey.FogBeforeLights = (fogset > 0); + pipelineKey.ShaderKey.FogAfterLights = (fogset < 0); + pipelineKey.ShaderKey.FogRadial = (fogset < -1 || fogset > 1); + pipelineKey.ShaderKey.SWLightRadial = (gl_fogmode == 2); + pipelineKey.ShaderKey.SWLightBanded = false; // gl_bandedswlight; + + float lightlevel = surfaceUniforms.uLightLevel; + if (lightlevel < 0.0) + { + pipelineKey.ShaderKey.LightMode = 0; // Default + } + else + { + /*if (mLightMode == 5) + pipelineKey.ShaderKey.LightMode = 3; // Build + else if (mLightMode == 16) + pipelineKey.ShaderKey.LightMode = 2; // Vanilla + else*/ + pipelineKey.ShaderKey.LightMode = 1; // Software + } + + pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1; + pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows == 2; + + pipelineKey.ShaderKey.GBufferPass = false; + pipelineKey.ShaderKey.UseLevelMesh = true; + + for (unsigned int i = 0, count = levelMeshPipelineKeys.Size(); i < count; i++) + { + if (levelMeshPipelineKeys[i] == pipelineKey) + { + return i; + } + } + + levelMeshPipelineKeys.Push(pipelineKey); + return levelMeshPipelineKeys.Size() - 1; +} + +const VkPipelineKey& VulkanRenderDevice::GetLevelMeshPipelineKey(int id) const +{ + return levelMeshPipelineKeys[id]; } diff --git a/src/common/rendering/vulkan/vk_renderdevice.h b/src/common/rendering/vulkan/vk_renderdevice.h index 1701cb3710..106e36d858 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.h +++ b/src/common/rendering/vulkan/vk_renderdevice.h @@ -14,13 +14,16 @@ class VkCommandBufferManager; class VkDescriptorSetManager; class VkRenderPassManager; class VkFramebufferManager; -class VkRaytrace; +class VkLevelMesh; +class VkLightmapper; class VkRenderState; class VkStreamBuffer; class VkHardwareDataBuffer; class VkHardwareTexture; class VkRenderBuffers; class VkPostprocess; +class VkPipelineKey; +class VkRenderPassSetup; class VulkanRenderDevice : public SystemBaseFrameBuffer { @@ -37,12 +40,14 @@ class VulkanRenderDevice : public SystemBaseFrameBuffer VkFramebufferManager* GetFramebufferManager() { return mFramebufferManager.get(); } VkDescriptorSetManager* GetDescriptorSetManager() { return mDescriptorSetManager.get(); } VkRenderPassManager *GetRenderPassManager() { return mRenderPassManager.get(); } - VkRaytrace* GetRaytrace() { return mRaytrace.get(); } - VkRenderState *GetRenderState(int threadIndex) { return mRenderState[threadIndex].get(); } + VkLevelMesh* GetLevelMesh() { return mLevelMesh.get(); } + VkLightmapper* GetLightmapper() { return mLightmapper.get(); } + VkRenderState *GetRenderState() { return mRenderState.get(); } VkPostprocess *GetPostprocess() { return mPostprocess.get(); } VkRenderBuffers *GetBuffers() { return mActiveRenderBuffers; } - FRenderState* RenderState(int threadIndex) override; + FRenderState* RenderState() override; + bool IsRayQueryEnabled() const { return mUseRayQuery; } bool IsVulkan() override { return true; } void Update() override; @@ -56,12 +61,12 @@ class VulkanRenderDevice : public SystemBaseFrameBuffer void SetTextureFilterMode() override; void StartPrecaching() override; void BeginFrame() override; - void InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData) override; void BlurScene(float amount) override; void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) override; void AmbientOccludeScene(float m5) override; void SetSceneRenderTarget(bool useSSAO) override; - void SetLevelMesh(hwrenderer::LevelMesh* mesh) override; + void SetLevelMesh(LevelMesh* mesh) override; + void UpdateLightmaps(const TArray& tiles) override; void SetShadowMaps(const TArray& lights, hwrenderer::LevelAABBTree* tree, bool newTree) override; void SetSaveBuffers(bool yes) override; void ImageTransitionScene(bool unknown) override; @@ -85,7 +90,11 @@ class VulkanRenderDevice : public SystemBaseFrameBuffer void WaitForCommands(bool finish) override; - std::mutex ThreadMutex; + int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation) override; + + int GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material) override; + + const VkPipelineKey& GetLevelMeshPipelineKey(int id) const; private: void RenderTextureView(FCanvasTexture* tex, std::function renderFunc) override; @@ -104,12 +113,20 @@ class VulkanRenderDevice : public SystemBaseFrameBuffer std::unique_ptr mPostprocess; std::unique_ptr mDescriptorSetManager; std::unique_ptr mRenderPassManager; - std::unique_ptr mRaytrace; - std::vector> mRenderState; + std::unique_ptr mLevelMesh; + std::unique_ptr mLightmapper; + std::unique_ptr mRenderState; VkRenderBuffers *mActiveRenderBuffers = nullptr; bool mVSync = false; + bool mUseRayQuery = false; + + LevelMesh* levelMesh = nullptr; + bool levelMeshChanged = true; + + int levelVertexFormatIndex = -1; + TArray levelMeshPipelineKeys; }; class CVulkanError : public CEngineError diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 9acfb57181..3d75d32055 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -22,6 +22,7 @@ #include "vk_renderstate.h" #include "vulkan/vk_renderdevice.h" +#include "vulkan/vk_levelmesh.h" #include "vulkan/commands/vk_commandbuffer.h" #include "vulkan/buffers/vk_buffer.h" #include "vulkan/pipelines/vk_renderpass.h" @@ -40,7 +41,7 @@ CVAR(Int, vk_submit_size, 1000, 0); EXTERN_CVAR(Bool, r_skipmats) -VkRenderState::VkRenderState(VulkanRenderDevice* fb, int threadIndex) : fb(fb), threadIndex(threadIndex), mRSBuffers(fb->GetBufferManager()->GetRSBuffers(threadIndex)), mStreamBufferWriter(mRSBuffers), mMatrixBufferWriter(mRSBuffers) +VkRenderState::VkRenderState(VulkanRenderDevice* fb) : fb(fb), mRSBuffers(fb->GetBufferManager()->GetRSBuffers()) { mMatrices.ModelMatrix.loadIdentity(); mMatrices.NormalModelMatrix.loadIdentity(); @@ -188,13 +189,13 @@ void VkRenderState::Apply(int dt) drawcalls.Clock(); mApplyCount++; - if (threadIndex == 0 && mApplyCount >= vk_submit_size) + if (mApplyCount >= vk_submit_size) { fb->GetCommands()->FlushCommands(false); mApplyCount = 0; } - ApplyStreamData(); + ApplySurfaceUniforms(); ApplyMatrices(); ApplyRenderPass(dt); ApplyScissor(); @@ -204,7 +205,6 @@ void VkRenderState::Apply(int dt) ApplyPushConstants(); ApplyVertexBuffers(); ApplyBufferSets(); - ApplyMaterial(); mNeedApply = false; drawcalls.Unclock(); @@ -235,8 +235,6 @@ void VkRenderState::ApplyRenderPass(int dt) pipelineKey.StencilPassOp = mStencilOp; pipelineKey.ColorMask = mColorMask; pipelineKey.CullMode = mCullMode; - pipelineKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->NumLayers() : 0; - pipelineKey.NumTextureLayers = max(pipelineKey.NumTextureLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS);// Always force minimum 8 textures as the shader requires it if (mSpecialEffect > EFF_NONE) { pipelineKey.ShaderKey.SpecialEffect = mSpecialEffect; @@ -250,7 +248,7 @@ void VkRenderState::ApplyRenderPass(int dt) pipelineKey.ShaderKey.EffectState = mTextureEnabled ? effectState : SHADER_NoTexture; if (r_skipmats && pipelineKey.ShaderKey.EffectState >= 3 && pipelineKey.ShaderKey.EffectState <= 4) pipelineKey.ShaderKey.EffectState = 0; - pipelineKey.ShaderKey.AlphaTest = mStreamData.uAlphaThreshold >= 0.f; + pipelineKey.ShaderKey.AlphaTest = mSurfaceUniforms.uAlphaThreshold >= 0.f; } int uTextureMode = GetTextureModeAndFlags((mMaterial.mMaterial && mMaterial.mMaterial->Source()->isHardwareCanvas()) ? TM_OPAQUE : TM_NORMAL); @@ -283,8 +281,9 @@ void VkRenderState::ApplyRenderPass(int dt) pipelineKey.ShaderKey.FogRadial = (fogset < -1 || fogset > 1); pipelineKey.ShaderKey.SWLightRadial = (gl_fogmode == 2); pipelineKey.ShaderKey.SWLightBanded = false; // gl_bandedswlight; + pipelineKey.ShaderKey.FogBalls = mFogballIndex >= 0; - float lightlevel = mStreamData.uLightLevel; + float lightlevel = mSurfaceUniforms.uLightLevel; if (lightlevel < 0.0) { pipelineKey.ShaderKey.LightMode = 0; // Default @@ -299,8 +298,8 @@ void VkRenderState::ApplyRenderPass(int dt) pipelineKey.ShaderKey.LightMode = 1; // Software } - pipelineKey.ShaderKey.UseShadowmap = gl_light_shadowmap; - pipelineKey.ShaderKey.UseRaytrace = gl_light_raytrace; + pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1; + pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows == 2; pipelineKey.ShaderKey.GBufferPass = mRenderTarget.DrawBuffers > 1; @@ -310,15 +309,7 @@ void VkRenderState::ApplyRenderPass(int dt) if (!inRenderPass) { - if (threadIndex == 0) - { - mCommandBuffer = fb->GetCommands()->GetDrawCommands(); - } - else - { - mThreadCommandBuffer = fb->GetCommands()->BeginThreadCommands(); - mCommandBuffer = mThreadCommandBuffer.get(); - } + mCommandBuffer = fb->GetCommands()->GetDrawCommands(); mScissorChanged = true; mViewportChanged = true; @@ -399,47 +390,60 @@ void VkRenderState::ApplyViewport() } } -void VkRenderState::ApplyStreamData() +void VkRenderState::ApplySurfaceUniforms() { auto passManager = fb->GetRenderPassManager(); - mStreamData.useVertexData = mVertexBuffer ? passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData : 0; + mSurfaceUniforms.useVertexData = mVertexBuffer ? passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData : 0; if (mMaterial.mMaterial && mMaterial.mMaterial->Source()) - mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->GetShaderSpeed() / 1000.); + mSurfaceUniforms.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->GetShaderSpeed() / 1000.); else - mStreamData.timer = 0.0f; + mSurfaceUniforms.timer = 0.0f; - if (mMaterial.mMaterial) + if (mMaterial.mChanged) { - auto source = mMaterial.mMaterial->Source(); - mStreamData.uSpecularMaterial = { source->GetGlossiness(), source->GetSpecularLevel() }; + if (mMaterial.mMaterial) + { + auto source = mMaterial.mMaterial->Source(); + if (source->isHardwareCanvas()) + static_cast(source->GetTexture())->NeedUpdate(); + + mSurfaceUniforms.uTextureIndex = static_cast(mMaterial.mMaterial)->GetBindlessIndex(mMaterial); + mSurfaceUniforms.uSpecularMaterial = { source->GetGlossiness(), source->GetSpecularLevel() }; + } + else + { + mSurfaceUniforms.uTextureIndex = 0; + } + mMaterial.mChanged = false; } - if (!mStreamBufferWriter.Write(mStreamData)) + if (!mRSBuffers->SurfaceUniformsBuffer->Write(mSurfaceUniforms)) { WaitForStreamBuffers(); - mStreamBufferWriter.Write(mStreamData); + mRSBuffers->SurfaceUniformsBuffer->Write(mSurfaceUniforms); } } void VkRenderState::ApplyPushConstants() { - mPushConstants.uDataIndex = mStreamBufferWriter.DataIndex(); + mPushConstants.uDataIndex = mRSBuffers->SurfaceUniformsBuffer->DataIndex(); mPushConstants.uLightIndex = mLightIndex >= 0 ? (mLightIndex % MAX_LIGHT_DATA) : -1; mPushConstants.uBoneIndexBase = mBoneIndexBase; + mPushConstants.uFogballIndex = mFogballIndex >= 0 ? (mFogballIndex % MAX_FOGBALL_DATA) : -1; - mCommandBuffer->pushConstants(GetPipelineLayout(mPipelineKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants); + mCommandBuffer->pushConstants(fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.ShaderKey.UseLevelMesh), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants); } void VkRenderState::ApplyMatrices() { if (mMatricesChanged) { - if (!mMatrixBufferWriter.Write(mMatrices)) + if (!mRSBuffers->MatrixBuffer->Write(mMatrices)) { WaitForStreamBuffers(); - mMatrixBufferWriter.Write(mMatrices); + mRSBuffers->MatrixBuffer->Write(mMatrices); } mMatricesChanged = false; } @@ -449,19 +453,20 @@ void VkRenderState::ApplyVertexBuffers() { if ((mVertexBuffer != mLastVertexBuffer || mVertexOffsets[0] != mLastVertexOffsets[0] || mVertexOffsets[1] != mLastVertexOffsets[1])) { + // Note: second [0] for BufferStrides is not a typo. Not all the vertex formats have a second buffer and the entire thing assumes they have the same stride anyway. if (mVertexBuffer) { auto vkbuf = static_cast(mVertexBuffer); const VkVertexFormat* format = fb->GetRenderPassManager()->GetVertexFormat(vkbuf->VertexFormat); VkBuffer vertexBuffers[2] = { vkbuf->mBuffer->buffer, vkbuf->mBuffer->buffer }; - VkDeviceSize offsets[] = { mVertexOffsets[0] * format->Stride, mVertexOffsets[1] * format->Stride }; + VkDeviceSize offsets[] = { mVertexOffsets[0] * format->BufferStrides[0], mVertexOffsets[1] * format->BufferStrides[0]}; mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, offsets); } else { const VkVertexFormat* format = fb->GetRenderPassManager()->GetVertexFormat(mRSBuffers->Flatbuffer.VertexFormat); VkBuffer vertexBuffers[2] = { mRSBuffers->Flatbuffer.VertexBuffer->buffer, mRSBuffers->Flatbuffer.VertexBuffer->buffer }; - VkDeviceSize offsets[] = { mVertexOffsets[0] * format->Stride, mVertexOffsets[1] * format->Stride }; + VkDeviceSize offsets[] = { mVertexOffsets[0] * format->BufferStrides[0], mVertexOffsets[1] * format->BufferStrides[0]}; mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, offsets); } @@ -485,42 +490,27 @@ void VkRenderState::ApplyVertexBuffers() } } -void VkRenderState::ApplyMaterial() -{ - if (mMaterial.mChanged) - { - auto descriptors = fb->GetDescriptorSetManager(); - VulkanPipelineLayout* layout = GetPipelineLayout(mPipelineKey.NumTextureLayers); - - if (mMaterial.mMaterial && mMaterial.mMaterial->Source()->isHardwareCanvas()) - static_cast(mMaterial.mMaterial->Source()->GetTexture())->NeedUpdate(); - - VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast(mMaterial.mMaterial)->GetDescriptorSet(threadIndex, mMaterial) : descriptors->GetNullTextureDescriptorSet(); - - mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedDescriptorSet()); - mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptorset); - mMaterial.mChanged = false; - } -} - void VkRenderState::ApplyBufferSets() { - uint32_t matrixOffset = mMatrixBufferWriter.Offset(); - uint32_t streamDataOffset = mStreamBufferWriter.StreamDataOffset(); + uint32_t matrixOffset = mRSBuffers->MatrixBuffer->Offset(); + uint32_t surfaceUniformsOffset = mRSBuffers->SurfaceUniformsBuffer->Offset(); uint32_t lightsOffset = mLightIndex >= 0 ? (uint32_t)(mLightIndex / MAX_LIGHT_DATA) * sizeof(LightBufferUBO) : mLastLightsOffset; - if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || streamDataOffset != mLastStreamDataOffset || lightsOffset != mLastLightsOffset) + uint32_t fogballsOffset = mFogballIndex >= 0 ? (uint32_t)(mFogballIndex / MAX_FOGBALL_DATA) * sizeof(FogballBufferUBO) : mLastFogballsOffset; + if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || surfaceUniformsOffset != mLastSurfaceUniformsOffset || lightsOffset != mLastLightsOffset || fogballsOffset != mLastFogballsOffset) { auto descriptors = fb->GetDescriptorSetManager(); - VulkanPipelineLayout* layout = GetPipelineLayout(mPipelineKey.NumTextureLayers); + VulkanPipelineLayout* layout = fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.ShaderKey.UseLevelMesh); - uint32_t offsets[4] = { mViewpointOffset, matrixOffset, streamDataOffset, lightsOffset }; - mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedDescriptorSet()); - mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetRSBufferDescriptorSet(threadIndex), 4, offsets); + uint32_t offsets[5] = { mViewpointOffset, matrixOffset, surfaceUniformsOffset, lightsOffset, fogballsOffset }; + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet()); + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetRSBufferSet(), 5, offsets); + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet()); mLastViewpointOffset = mViewpointOffset; mLastMatricesOffset = matrixOffset; - mLastStreamDataOffset = streamDataOffset; + mLastSurfaceUniformsOffset = surfaceUniformsOffset; mLastLightsOffset = lightsOffset; + mLastFogballsOffset = fogballsOffset; } } @@ -528,8 +518,9 @@ void VkRenderState::WaitForStreamBuffers() { fb->WaitForCommands(false); mApplyCount = 0; - mStreamBufferWriter.Reset(); - mMatrixBufferWriter.Reset(); + mRSBuffers->SurfaceUniformsBuffer->Reset(); + mRSBuffers->MatrixBuffer->Reset(); + mMatricesChanged = true; } int VkRenderState::SetViewpoint(const HWViewpointUniforms& vp) @@ -643,6 +634,35 @@ int VkRenderState::UploadBones(const TArray& bones) } } +int VkRenderState::UploadFogballs(const TArray& balls) +{ + int totalsize = balls.Size() + 1; + if (balls.Size() == 0) + { + return -1; + } + + // Make sure the fogball list doesn't cross a page boundary + if (mRSBuffers->Fogballbuffer.UploadIndex % MAX_FOGBALL_DATA + totalsize > MAX_FOGBALL_DATA) + mRSBuffers->Fogballbuffer.UploadIndex = (mRSBuffers->Fogballbuffer.UploadIndex / MAX_FOGBALL_DATA + 1) * MAX_FOGBALL_DATA; + + int thisindex = mRSBuffers->Fogballbuffer.UploadIndex; + mRSBuffers->Fogballbuffer.UploadIndex += totalsize; + + if (thisindex + totalsize <= mRSBuffers->Fogballbuffer.Count) + { + Fogball sizeinfo; // First entry is actually not a fogball. It is the size of the array. + sizeinfo.Position.X = (float)balls.Size(); + memcpy((Fogball*)mRSBuffers->Fogballbuffer.Data + thisindex, &sizeinfo, sizeof(Fogball)); + memcpy((Fogball*)mRSBuffers->Fogballbuffer.Data + thisindex + 1, balls.Data(), balls.Size() * sizeof(Fogball)); + return thisindex; + } + else + { + return -1; + } +} + std::pair VkRenderState::AllocVertices(unsigned int count) { unsigned int index = mRSBuffers->Flatbuffer.CurIndex; @@ -712,6 +732,10 @@ void VkRenderState::BeginFrame() mRSBuffers->Viewpoint.UploadIndex = 0; mRSBuffers->Lightbuffer.UploadIndex = 0; mRSBuffers->Bonebuffer.UploadIndex = 0; + mRSBuffers->Fogballbuffer.UploadIndex = 0; + mRSBuffers->OcclusionQuery.NextIndex = 0; + + fb->GetCommands()->GetDrawCommands()->resetQueryPool(mRSBuffers->OcclusionQuery.QueryPool.get(), 0, mRSBuffers->OcclusionQuery.MaxQueries); } void VkRenderState::EndRenderPass() @@ -722,11 +746,6 @@ void VkRenderState::EndRenderPass() mCommandBuffer = nullptr; } - if (mThreadCommandBuffer) - { - fb->GetCommands()->EndThreadCommands(std::move(mThreadCommandBuffer)); - } - // Force rebind of everything on next draw mPipelineKey = {}; mLastViewpointOffset = 0xffffffff; @@ -736,8 +755,9 @@ void VkRenderState::EndRenderPass() void VkRenderState::EndFrame() { - mMatrixBufferWriter.Reset(); - mStreamBufferWriter.Reset(); + mRSBuffers->MatrixBuffer->Reset(); + mRSBuffers->SurfaceUniformsBuffer->Reset(); + mMatricesChanged = true; } void VkRenderState::EnableDrawBuffers(int count, bool apply) @@ -769,7 +789,7 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer) key.DrawBuffers = mRenderTarget.DrawBuffers; key.DepthStencil = !!mRenderTarget.DepthStencil; - mPassSetup = GetRenderPass(key); + mPassSetup = fb->GetRenderPassManager()->GetRenderPass(key); auto &framebuffer = mRenderTarget.Image->RSFramebuffers[key]; if (!framebuffer) @@ -809,53 +829,113 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer) mClearTargets = 0; } -VkThreadRenderPassSetup* VkRenderState::GetRenderPass(const VkRenderPassKey& key) +void VkRenderState::ApplyLevelMesh() { - auto& item = mRenderPassSetups[key]; - if (!item) - item.reset(new VkThreadRenderPassSetup(fb, key)); - return item.get(); + ApplyMatrices(); + ApplyRenderPass(DT_Triangles); + ApplyScissor(); + ApplyViewport(); + ApplyStencilRef(); + ApplyDepthBias(); + mNeedApply = true; + + VkBuffer vertexBuffers[2] = { fb->GetLevelMesh()->GetVertexBuffer()->buffer, fb->GetLevelMesh()->GetUniformIndexBuffer()->buffer }; + VkDeviceSize vertexBufferOffsets[] = { 0, 0 }; + mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, vertexBufferOffsets); + mCommandBuffer->bindIndexBuffer(fb->GetLevelMesh()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32); +} + +void VkRenderState::DrawLevelMeshSurfaces(bool noFragmentShader) +{ + ApplyLevelMesh(); + + auto mesh = fb->GetLevelMesh()->GetMesh(); + for (LevelSubmeshDrawRange& range : mesh->DrawList) + { + DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, noFragmentShader); + } } -VulkanPipelineLayout* VkRenderState::GetPipelineLayout(int numLayers) +void VkRenderState::DrawLevelMeshPortals(bool noFragmentShader) { - if (mPipelineLayouts.size() <= (size_t)numLayers) - mPipelineLayouts.resize(numLayers + 1); + ApplyLevelMesh(); - auto& layout = mPipelineLayouts[numLayers]; - if (layout) - return layout; + auto mesh = fb->GetLevelMesh()->GetMesh(); + for (LevelSubmeshDrawRange& range : mesh->PortalList) + { + DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, noFragmentShader); + } +} - std::unique_lock lock(fb->ThreadMutex); - layout = fb->GetRenderPassManager()->GetPipelineLayout(numLayers); - return layout; +void VkRenderState::BeginQuery() +{ + mCommandBuffer->beginQuery(mRSBuffers->OcclusionQuery.QueryPool.get(), mRSBuffers->OcclusionQuery.NextIndex++, 0); } -///////////////////////////////////////////////////////////////////////////// +void VkRenderState::EndQuery() +{ + mCommandBuffer->endQuery(mRSBuffers->OcclusionQuery.QueryPool.get(), mRSBuffers->OcclusionQuery.NextIndex - 1); +} -VkThreadRenderPassSetup::VkThreadRenderPassSetup(VulkanRenderDevice* fb, const VkRenderPassKey& key) : PassKey(key), fb(fb) +int VkRenderState::GetNextQueryIndex() { + return mRSBuffers->OcclusionQuery.NextIndex; } -VulkanRenderPass* VkThreadRenderPassSetup::GetRenderPass(int clearTargets) +void VkRenderState::GetQueryResults(int queryStart, int queryCount, TArray& results) { - if (RenderPasses[clearTargets]) - return RenderPasses[clearTargets]; + fb->GetCommands()->FlushCommands(false); - std::unique_lock lock(fb->ThreadMutex); - RenderPasses[clearTargets] = fb->GetRenderPassManager()->GetRenderPass(PassKey)->GetRenderPass(clearTargets); - return RenderPasses[clearTargets]; + mQueryResultsBuffer.Resize(queryCount); + VkResult result = vkGetQueryPoolResults(fb->GetDevice()->device, mRSBuffers->OcclusionQuery.QueryPool->pool, queryStart, queryCount, mQueryResultsBuffer.Size() * sizeof(uint32_t), mQueryResultsBuffer.Data(), sizeof(uint32_t), VK_QUERY_RESULT_WAIT_BIT); + CheckVulkanError(result, "Could not query occlusion query results"); + if (result == VK_NOT_READY) + VulkanError("Occlusion query results returned VK_NOT_READY!"); + + results.Resize(queryCount); + for (int i = 0; i < queryCount; i++) + { + results[i] = mQueryResultsBuffer[i] != 0; + } } -VulkanPipeline* VkThreadRenderPassSetup::GetPipeline(const VkPipelineKey& key) +void VkRenderState::DrawLevelMeshRange(VulkanCommandBuffer* cmdbuffer, VkPipelineKey pipelineKey, int start, int count, bool noFragmentShader) { - auto& item = Pipelines[key]; - if (item) - return item; + if (noFragmentShader && pipelineKey.ShaderKey.AlphaTest) + return; - std::unique_lock lock(fb->ThreadMutex); - item = fb->GetRenderPassManager()->GetRenderPass(PassKey)->GetPipeline(key); - return item; + pipelineKey.ShaderKey.NoFragmentShader = noFragmentShader; + pipelineKey.DepthTest = mDepthTest; + pipelineKey.DepthWrite = mDepthTest && mDepthWrite; + pipelineKey.DepthClamp = mDepthClamp; + pipelineKey.DepthBias = !(mBias.mFactor == 0 && mBias.mUnits == 0); + pipelineKey.StencilTest = mStencilTest; + pipelineKey.StencilPassOp = mStencilOp; + pipelineKey.ColorMask = mColorMask; + pipelineKey.CullMode = mCullMode; + if (!mTextureEnabled) + pipelineKey.ShaderKey.EffectState = SHADER_NoTexture; + mPipelineKey = pipelineKey; + + PushConstants pushConstants = {}; + pushConstants.uDataIndex = 0; + pushConstants.uLightIndex = -1; + pushConstants.uBoneIndexBase = -1; + + VulkanPipelineLayout* layout = fb->GetRenderPassManager()->GetPipelineLayout(pipelineKey.ShaderKey.UseLevelMesh); + uint32_t viewpointOffset = mViewpointOffset; + uint32_t matrixOffset = mRSBuffers->MatrixBuffer->Offset(); + uint32_t lightsOffset = 0; + uint32_t fogballsOffset = 0; + uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset, fogballsOffset }; + + auto descriptors = fb->GetDescriptorSetManager(); + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mPassSetup->GetPipeline(pipelineKey)); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 4, offsets); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet()); + cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants); + cmdbuffer->drawIndexed(count, 1, start, 0, 0); } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/common/rendering/vulkan/vk_renderstate.h b/src/common/rendering/vulkan/vk_renderstate.h index a239bda6d1..e3bd077546 100644 --- a/src/common/rendering/vulkan/vk_renderstate.h +++ b/src/common/rendering/vulkan/vk_renderstate.h @@ -12,13 +12,12 @@ #include "hw_material.h" class VulkanRenderDevice; -class VkThreadRenderPassSetup; class VkTextureImage; class VkRenderState : public FRenderState { public: - VkRenderState(VulkanRenderDevice* fb, int threadIndex); + VkRenderState(VulkanRenderDevice* fb); virtual ~VkRenderState() = default; // Draw commands @@ -49,6 +48,7 @@ class VkRenderState : public FRenderState void SetTextureMatrix(const VSMatrix& matrix) override; int UploadLights(const FDynLightData& lightdata) override; int UploadBones(const TArray& bones) override; + int UploadFogballs(const TArray& balls) override; // Vertices std::pair AllocVertices(unsigned int count) override; @@ -56,6 +56,14 @@ class VkRenderState : public FRenderState void UpdateShadowData(unsigned int index, const FFlatVertex* vertices, unsigned int count) override; void ResetVertices() override; + // Draw level mesh + void DrawLevelMeshSurfaces(bool noFragmentShader) override; + void DrawLevelMeshPortals(bool noFragmentShader) override; + int GetNextQueryIndex() override; + void BeginQuery() override; + void EndQuery() override; + void GetQueryResults(int start, int count, TArray& results) override; + // Worker threads void FlushCommands() override { EndRenderPass(); } @@ -71,28 +79,26 @@ class VkRenderState : public FRenderState void ApplyDepthBias(); void ApplyScissor(); void ApplyViewport(); - void ApplyStreamData(); + void ApplySurfaceUniforms(); void ApplyMatrices(); void ApplyPushConstants(); void ApplyBufferSets(); void ApplyVertexBuffers(); - void ApplyMaterial(); void BeginRenderPass(VulkanCommandBuffer *cmdbuffer); void WaitForStreamBuffers(); - VkThreadRenderPassSetup* GetRenderPass(const VkRenderPassKey& key); - VulkanPipelineLayout* GetPipelineLayout(int numLayers); + void ApplyLevelMesh(); + void DrawLevelMeshRange(VulkanCommandBuffer* cmdbuffer, VkPipelineKey pipelineKey, int start, int count, bool noFragmentShader); VulkanRenderDevice* fb = nullptr; - int threadIndex = 0; VkRSBuffers* mRSBuffers = nullptr; bool mDepthClamp = true; VulkanCommandBuffer *mCommandBuffer = nullptr; VkPipelineKey mPipelineKey = {}; - VkThreadRenderPassSetup* mPassSetup = nullptr; + VkRenderPassSetup* mPassSetup = nullptr; int mClearTargets = 0; bool mNeedApply = true; @@ -117,13 +123,11 @@ class VkRenderState : public FRenderState uint32_t mLastViewpointOffset = 0xffffffff; uint32_t mLastMatricesOffset = 0xffffffff; - uint32_t mLastStreamDataOffset = 0xffffffff; + uint32_t mLastSurfaceUniformsOffset = 0xffffffff; uint32_t mLastLightsOffset = 0; + uint32_t mLastFogballsOffset = 0; uint32_t mViewpointOffset = 0; - VkStreamBufferWriter mStreamBufferWriter; - VkMatrixBufferWriter mMatrixBufferWriter; - int mLastVertexOffsets[2] = { 0, 0 }; IBuffer* mLastVertexBuffer = nullptr; IBuffer* mLastIndexBuffer = nullptr; @@ -145,24 +149,7 @@ class VkRenderState : public FRenderState int DrawBuffers = 1; } mRenderTarget; - std::map> mRenderPassSetups; - std::vector mPipelineLayouts; - std::unique_ptr mThreadCommandBuffer; -}; - -class VkThreadRenderPassSetup -{ -public: - VkThreadRenderPassSetup(VulkanRenderDevice* fb, const VkRenderPassKey& key); - - VulkanRenderPass* GetRenderPass(int clearTargets); - VulkanPipeline* GetPipeline(const VkPipelineKey& key); - -private: - VkRenderPassKey PassKey; - VulkanRenderDevice* fb; - VulkanRenderPass* RenderPasses[8] = {}; - std::map Pipelines; + TArray mQueryResultsBuffer; }; class VkRenderStateMolten : public VkRenderState diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 2659eda268..8b3ee306a6 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -43,11 +43,13 @@ #include "texturemanager.h" #include "m_random.h" #include "v_font.h" +#include "palettecontainer.h" extern FRandom pr_exrandom; FMemArena FxAlloc(65536); CompileEnvironment compileEnvironment; +FTranslationID R_FindCustomTranslation(FName name); struct FLOP { @@ -161,6 +163,12 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) PType* expected = ReturnProto->ReturnTypes[i]; PType* actual = proto->ReturnTypes[i]; if (swapped) std::swap(expected, actual); + // this must pass for older ZScripts. + if (Version < MakeVersion(4, 12, 0)) + { + if (expected == TypeTranslationID) expected = TypeSInt32; + if (actual == TypeTranslationID) actual = TypeSInt32; + } if (expected != actual && !AreCompatiblePointerTypes(expected, actual)) { // Incompatible @@ -268,6 +276,8 @@ PFunction *FindBuiltinFunction(FName funcname) // //========================================================================== +static bool AreCompatibleFnPtrTypes(PPrototype *to, PPrototype *from); + bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare) { if (dest->isPointer() && source->isPointer()) @@ -277,25 +287,36 @@ bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare) // null pointers can be assigned to everything, everything can be assigned to void pointers. if (fromtype == nullptr || totype == TypeVoidPtr) return true; // when comparing const-ness does not matter. - if (!forcompare && totype->IsConst != fromtype->IsConst) return false; + // If not comparing, then we should not allow const to be cast away. + if (!forcompare && fromtype->IsConst && !totype->IsConst) return false; // A type is always compatible to itself. if (fromtype == totype) return true; - // Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type. if (source->isObjectPointer() && dest->isObjectPointer()) - { + { // Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type. auto fromcls = static_cast(source)->PointedClass(); auto tocls = static_cast(dest)->PointedClass(); if (forcompare && tocls->IsDescendantOf(fromcls)) return true; return (fromcls->IsDescendantOf(tocls)); } - // The same rules apply to class pointers. A child type can be assigned to a variable of a parent type. - if (source->isClassPointer() && dest->isClassPointer()) - { + else if (source->isClassPointer() && dest->isClassPointer()) + { // The same rules apply to class pointers. A child type can be assigned to a variable of a parent type. auto fromcls = static_cast(source)->ClassRestriction; auto tocls = static_cast(dest)->ClassRestriction; if (forcompare && tocls->IsDescendantOf(fromcls)) return true; return (fromcls->IsDescendantOf(tocls)); } + else if(source->isFunctionPointer() && dest->isFunctionPointer()) + { + auto from = static_cast(source); + auto to = static_cast(dest); + if(from->PointedType == TypeVoid) return false; + + return to->PointedType == TypeVoid || (AreCompatibleFnPtrTypes((PPrototype *)to->PointedType, (PPrototype *)from->PointedType) && from->ArgFlags == to->ArgFlags && FScopeBarrier::CheckSidesForFunctionPointer(from->Scope, to->Scope)); + } + else if(source->isRealPointer() && dest->isRealPointer()) + { + return fromtype->PointedType == totype->PointedType; + } } return false; } @@ -905,6 +926,17 @@ FxExpression *FxBoolCast::Resolve(FCompileContext &ctx) ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) { ExpEmit from = basex->Emit(build); + + if(from.Konst && from.RegType == REGT_INT) + { // this is needed here because the int const assign optimization returns a constant + ExpEmit to; + to.Konst = true; + to.RegType = REGT_INT; + to.RegNum = build->GetConstantInt(!!build->FindConstantInt(from.RegNum)); + return to; + } + + assert(!from.Konst); assert(basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER); @@ -971,6 +1003,19 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) if (basex->ValueType->GetRegType() == REGT_INT) { + if (basex->ValueType == TypeTranslationID) + { + // translation IDs must be entirely incompatible with ints, not even allowing an explicit conversion, + // but since the type was only introduced in version 4.12, older ZScript versions must allow this conversion. + if (ctx.Version < MakeVersion(4, 12, 0)) + { + FxExpression* x = basex; + x->ValueType = ValueType; + basex = nullptr; + delete this; + return x; + } + } if (basex->ValueType->isNumeric() || Explicit) // names can be converted to int, but only with an explicit type cast. { FxExpression *x = basex; @@ -984,7 +1029,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this serious error needs to be reduced to a warning. :( // At least in ZScript, MSG_OPTERROR always means to report an error, not a warning so the problem only exists in DECORATE. if (!basex->isConstant()) - ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a %s", basex->ValueType->DescriptiveName()); else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); FxExpression * x = new FxConstant(0, ScriptPosition); delete this; @@ -1105,7 +1150,8 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) { // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( // At least in ZScript, MSG_OPTERROR always means to report an error, not a warning so the problem only exists in DECORATE. - if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + if (!basex->isConstant()) + ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a %s", basex->ValueType->DescriptiveName()); else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); FxExpression *x = new FxConstant(0.0, ScriptPosition); delete this; @@ -1129,7 +1175,15 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build) { ExpEmit from = basex->Emit(build); - //assert(!from.Konst); + if(from.Konst && from.RegType == REGT_INT) + { // this is needed here because the int const assign optimization returns a constant + ExpEmit to; + to.Konst = true; + to.RegType = REGT_FLOAT; + to.RegNum = build->GetConstantFloat(build->FindConstantInt(from.RegNum)); + return to; + } + assert(basex->ValueType->GetRegType() == REGT_INT); from.Free(build); ExpEmit to(build, REGT_FLOAT); @@ -1393,7 +1447,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx) } else { - FxExpression *x = new FxConstant(V_GetColor(constval.GetString(), &ScriptPosition), ScriptPosition); + FxExpression *x = new FxConstant(V_GetColor(constval.GetString().GetChars(), &ScriptPosition), ScriptPosition); delete this; return x; } @@ -1473,7 +1527,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx) if (basex->isConstant()) { ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(S_FindSound(constval.GetString()), ScriptPosition); + FxExpression *x = new FxConstant(S_FindSound(constval.GetString().GetChars()), ScriptPosition); delete this; return x; } @@ -1504,6 +1558,107 @@ ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build) return to; } +//========================================================================== +// +// +// +//========================================================================== + +FxTranslationCast::FxTranslationCast(FxExpression* x) + : FxExpression(EFX_TranslationCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeTranslationID; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxTranslationCast::~FxTranslationCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression* FxTranslationCast::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType->isInt()) + { + // 0 is a valid constant for translations, meaning 'no translation at all'. note that this conversion ONLY allows a constant! + if (basex->isConstant() && static_cast(basex)->GetValue().GetInt() == 0) + { + FxExpression* x = basex; + x->ValueType = TypeTranslationID; + basex = nullptr; + delete this; + return x; + } + if (ctx.Version < MakeVersion(4, 12, 0)) + { + // only allow this conversion as a fallback + FxExpression* x = basex; + x->ValueType = TypeTranslationID; + basex = nullptr; + delete this; + return x; + } + } + else if (basex->ValueType == TypeString || basex->ValueType == TypeName) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression* x = new FxConstant(R_FindCustomTranslation(constval.GetName()), ScriptPosition); + x->ValueType = TypeTranslationID; + delete this; + return x; + } + else if (basex->ValueType == TypeString) + { + basex = new FxNameCast(basex, true); + basex = basex->Resolve(ctx); + } + return this; + } + ScriptPosition.Message(MSG_ERROR, "Cannot convert to translation ID"); + delete this; + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxTranslationCast::Emit(VMFunctionBuilder* build) +{ + ExpEmit to(build, REGT_POINTER); + + VMFunction* callfunc; + auto sym = FindBuiltinFunction(NAME_BuiltinFindTranslation); + + assert(sym); + callfunc = sym->Variants[0].Implementation; + + FunctionCallEmitter emitters(callfunc); + emitters.AddParameter(build, basex); + emitters.AddReturn(REGT_INT); + return emitters.EmitCall(build); +} + + //========================================================================== // // @@ -1551,7 +1706,7 @@ FxExpression *FxFontCast::Resolve(FCompileContext &ctx) else if ((basex->ValueType == TypeString || basex->ValueType == TypeName) && basex->isConstant()) { ExpVal constval = static_cast(basex)->GetValue(); - FFont *font = V_GetFont(constval.GetString()); + FFont *font = V_GetFont(constval.GetString().GetChars()); // Font must exist. Most internal functions working with fonts do not like null pointers. // If checking is needed scripts will have to call Font.GetFont themselves. if (font == nullptr) @@ -1607,6 +1762,35 @@ FxTypeCast::~FxTypeCast() // //========================================================================== +FxConstant * FxTypeCast::convertRawFunctionToFunctionPointer(FxExpression * in, FScriptPosition &ScriptPosition) +{ + assert(in->isConstant() && in->ValueType == TypeRawFunction); + FxConstant *val = static_cast(in); + PFunction * fn = static_cast(val->value.pointer); + if(fn && (fn->Variants[0].Flags & (VARF_Virtual | VARF_Action | VARF_Method)) == 0) + { + val->ValueType = val->value.Type = NewFunctionPointer(fn->Variants[0].Proto, TArray(fn->Variants[0].ArgFlags), FScopeBarrier::SideFromFlags(fn->Variants[0].Flags)); + return val; + } + else if(fn && (fn->Variants[0].Flags & (VARF_Virtual | VARF_Action | VARF_Method)) == VARF_Method) + { + TArray flags(fn->Variants[0].ArgFlags); + flags[0] = 0; + val->ValueType = val->value.Type = NewFunctionPointer(fn->Variants[0].Proto, std::move(flags), FScopeBarrier::SideFromFlags(fn->Variants[0].Flags)); + return val; + } + else if(!fn) + { + val->ValueType = val->value.Type = NewFunctionPointer(nullptr, {}, -1); // Function + return val; + } + else + { + ScriptPosition.Message(MSG_ERROR, "virtual/action function pointers are not allowed"); + return nullptr; + } +} + FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); @@ -1618,6 +1802,22 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) if (result != this) return result; } + if (basex->isConstant() && basex->ValueType == TypeRawFunction && ValueType->isFunctionPointer()) + { + FxConstant *val = convertRawFunctionToFunctionPointer(basex, ScriptPosition); + if(!val) + { + delete this; + return nullptr; + } + } + else if (basex->isConstant() && basex->ValueType == TypeRawFunction && ValueType == TypeVMFunction) + { + FxConstant *val = static_cast(basex); + val->ValueType = val->value.Type = TypeVMFunction; + val->value.pointer = static_cast(val->value.pointer)->Variants[0].Implementation; + } + // first deal with the simple types if (ValueType == TypeError || basex->ValueType == TypeError || basex->ValueType == nullptr) { @@ -1691,6 +1891,14 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + else if (ValueType == TypeTranslationID) + { + FxExpression* x = new FxTranslationCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } else if (ValueType == TypeColor) { FxExpression *x = new FxColorCast(basex); @@ -1734,6 +1942,12 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) { bool writable; basex->RequestAddress(ctx, &writable); + + if(!writable && !ValueType->toPointer()->IsConst && ctx.Version >= MakeVersion(4, 12)) + { + ScriptPosition.Message(MSG_ERROR, "Trying to assign readonly value to writable type."); + } + basex->ValueType = ValueType; auto x = basex; basex = nullptr; @@ -1917,7 +2131,17 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) { //assert(ValueType == Operand->ValueType); ExpEmit from = Operand->Emit(build); + if(from.Konst && from.RegType == REGT_INT) + { // this is needed here because the int const assign optimization returns a constant + ExpEmit to; + to.Konst = true; + to.RegType = REGT_INT; + to.RegNum = build->GetConstantInt(-build->FindConstantInt(from.RegNum)); + return to; + } + ExpEmit to; + assert(from.Konst == 0); assert(ValueType->GetRegCount() == from.RegCount); // Do it in-place, unless a local variable @@ -2037,6 +2261,16 @@ ExpEmit FxUnaryNotBitwise::Emit(VMFunctionBuilder *build) { assert(Operand->ValueType->GetRegType() == REGT_INT); ExpEmit from = Operand->Emit(build); + + if(from.Konst && from.RegType == REGT_INT) + { // this is needed here because the int const assign optimization returns a constant + ExpEmit to; + to.Konst = true; + to.RegType = REGT_INT; + to.RegNum = build->GetConstantInt(~build->FindConstantInt(from.RegNum)); + return to; + } + from.Free(build); ExpEmit to(build, REGT_INT); assert(!from.Konst); @@ -2108,6 +2342,16 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) assert(Operand->ValueType == TypeBool); assert(ValueType == TypeBool || IsInteger()); // this may have been changed by an int cast. ExpEmit from = Operand->Emit(build); + + if(from.Konst && from.RegType == REGT_INT) + { // this is needed here because the int const assign optimization returns a constant + ExpEmit to; + to.Konst = true; + to.RegType = REGT_INT; + to.RegNum = build->GetConstantInt(!build->FindConstantInt(from.RegNum)); + return to; + } + from.Free(build); ExpEmit to(build, REGT_INT); assert(!from.Konst); @@ -2453,7 +2697,17 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) SAFE_RESOLVE(Right, ctx); } } - else if (Base->ValueType == Right->ValueType) + else if (Right->IsNativeStruct() && Base->ValueType->isRealPointer() && Base->ValueType->toPointer()->PointedType == Right->ValueType) + { + // allow conversion of native structs to pointers of the same type. This is necessary to assign elements from global arrays like players, sectors, etc. to local pointers. + // For all other types this is not needed. Structs are not assignable and classes can only exist as references. + Right->RequestAddress(ctx, nullptr); + Right->ValueType = Base->ValueType; + } + else if ( Base->ValueType == Right->ValueType + || (Base->ValueType->isRealPointer() && Base->ValueType->toPointer()->PointedType == Right->ValueType) + || (Right->ValueType->isRealPointer() && Right->ValueType->toPointer()->PointedType == Base->ValueType) + ) { if (Base->ValueType->isArray()) { @@ -2461,28 +2715,103 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) delete this; return nullptr; } - else if (Base->IsDynamicArray()) - { - ScriptPosition.Message(MSG_ERROR, "Cannot assign dynamic arrays, use Copy() or Move() function instead"); - delete this; - return nullptr; - } - if (!Base->IsVector() && !Base->IsQuaternion() && Base->ValueType->isStruct()) + else if(!Base->IsVector() && !Base->IsQuaternion()) { - ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet"); - delete this; - return nullptr; + PType * btype = Base->ValueType; + + if(btype->isRealPointer()) + { + PType * p = static_cast(btype)->PointedType; + if( p->isDynArray() || p->isMap() + || (p->isStruct() && !static_cast(p)->isNative) + ) + { //un-pointer dynarrays, maps and non-native structs for assignment checking + btype = p; + } + } + + if (btype->isDynArray()) + { + if(ctx.Version >= MakeVersion(4, 11, 1)) + { + FArgumentList args; + args.Push(Right); + auto call = new FxMemberFunctionCall(Base, NAME_Copy, std::move(args), ScriptPosition); + Right = Base = nullptr; + delete this; + return call->Resolve(ctx); + } + else + { + if(Base->ValueType->isRealPointer() && Right->ValueType->isRealPointer()) + { + ScriptPosition.Message(MSG_WARNING, "Dynamic Array assignments not allowed in ZScript versions below 4.11.1, use the Copy() or Move() functions instead\n" + TEXTCOLOR_RED " Assigning an out array pointer to another out array pointer\n" + " does not alter either of the underlying arrays' values\n" + " it only swaps the pointers below ZScript version 4.11.1!!"); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Dynamic Array assignments not allowed in ZScript versions below 4.11.1, use the Copy() or Move() functions instead"); + delete this; + return nullptr; + } + } + } + else if (btype->isMap()) + { + if(ctx.Version >= MakeVersion(4, 11, 1)) + { + FArgumentList args; + args.Push(Right); + auto call = new FxMemberFunctionCall(Base, NAME_Copy, std::move(args), ScriptPosition); + Right = Base = nullptr; + delete this; + return call->Resolve(ctx); + } + else + { + if(Base->ValueType->isRealPointer() && Right->ValueType->isRealPointer()) + { // don't break existing code, but warn that it's a no-op + ScriptPosition.Message(MSG_WARNING, "Map assignments not allowed in ZScript versions below 4.11.1, use the Copy() or Move() functions instead\n" + TEXTCOLOR_RED " Assigning an out map pointer to another out map pointer\n" + " does not alter either of the underlying maps' values\n" + " it only swaps the pointers below ZScript version 4.11.1!!"); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Map assignments not allowed in ZScript versions below 4.11.1, use the Copy() or Move() functions instead"); + delete this; + return nullptr; + } + } + } + else if (btype->isMapIterator()) + { + ScriptPosition.Message(MSG_ERROR, "Cannot assign map iterators"); + delete this; + return nullptr; + } + else if (btype->isStruct()) + { + if(Base->ValueType->isRealPointer() && Right->ValueType->isRealPointer()) + { // don't break existing code, but warn that it's a no-op + ScriptPosition.Message(MSG_WARNING, "Struct assignment not implemented yet\n" + TEXTCOLOR_RED " Assigning an out struct pointer to another out struct pointer\n" + " does not alter either of the underlying structs' values\n" + " it only swaps the pointers!!"); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet"); + delete this; + return nullptr; + } + } } + // Both types are the same so this is ok. } - else if (Right->IsNativeStruct() && Base->ValueType->isRealPointer() && Base->ValueType->toPointer()->PointedType == Right->ValueType) - { - // allow conversion of native structs to pointers of the same type. This is necessary to assign elements from global arrays like players, sectors, etc. to local pointers. - // For all other types this is not needed. Structs are not assignable and classes can only exist as references. - bool writable; - Right->RequestAddress(ctx, &writable); - Right->ValueType = Base->ValueType; - } else { // pass it to FxTypeCast for complete handling. @@ -2605,7 +2934,6 @@ FxExpression *FxAssignSelf::Resolve(FCompileContext &ctx) ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) { - assert(ValueType == Assignment->ValueType); ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it if (!pointer.Target) { @@ -3506,6 +3834,16 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) delete left; left = x; } + else if (left->IsNumeric() && right->ValueType == TypeTranslationID && ctx.Version < MakeVersion(4, 12)) + { + right = new FxTypeCast(right, TypeSInt32, true); + SAFE_RESOLVE(right, ctx); + } + else if (right->IsNumeric() && left->ValueType == TypeTranslationID && ctx.Version < MakeVersion(4, 12)) + { + left = new FxTypeCast(left, TypeSInt32, true); + SAFE_RESOLVE(left, ctx); + } if (left->ValueType == TypeString || right->ValueType == TypeString) { @@ -3798,6 +4136,17 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) delete left; left = x; } + else if (left->IsNumeric() && right->ValueType == TypeTranslationID && ctx.Version < MakeVersion(4, 12)) + { + right = new FxIntCast(right, true, true); + SAFE_RESOLVE(right, ctx); + } + else if (right->IsNumeric() && left->ValueType == TypeTranslationID && ctx.Version < MakeVersion(4, 12)) + { + left = new FxTypeCast(left, TypeSInt32, true); + SAFE_RESOLVE(left, ctx); + } + // Special cases: Compare strings and names with names, sounds, colors, state labels and class types. // These are all types a string can be implicitly cast into, so for convenience, so they should when doing a comparison. if ((left->ValueType == TypeString || left->ValueType == TypeName) && @@ -4450,6 +4799,7 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) else if (left->ValueType == TypeColor) cast = CAST_Co2S; else if (left->ValueType == TypeSpriteID) cast = CAST_SID2S; else if (left->ValueType == TypeTextureID) cast = CAST_TID2S; + else if (left->ValueType == TypeTranslationID) cast = CAST_U2S; else if (op1.RegType == REGT_POINTER) cast = CAST_P2S; else if (op1.RegType == REGT_INT) cast = CAST_I2S; else assert(false && "Bad type for string concatenation"); @@ -4483,6 +4833,7 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) else if (right->ValueType == TypeColor) cast = CAST_Co2S; else if (right->ValueType == TypeSpriteID) cast = CAST_SID2S; else if (right->ValueType == TypeTextureID) cast = CAST_TID2S; + else if (right->ValueType == TypeTranslationID) cast = CAST_U2S; else if (op2.RegType == REGT_POINTER) cast = CAST_P2S; else if (op2.RegType == REGT_INT) cast = CAST_I2S; else assert(false && "Bad type for string concatenation"); @@ -4793,7 +5144,7 @@ FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx) } else { - left = new FxTypeCast(left, NewPointer(RUNTIME_CLASS(DObject)), false); + left = new FxTypeCast(left, NewPointer(RUNTIME_CLASS(DObject), true), false); ClassCheck = false; } right = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), right, false); @@ -4954,11 +5305,24 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) ValueType = truex->ValueType; else if (falsex->IsPointer() && truex->ValueType == TypeNullPtr) ValueType = falsex->ValueType; + // translation IDs need a bit of glue for compatibility and the 0 literal. + else if (truex->IsInteger() && falsex->ValueType == TypeTranslationID) + { + truex = new FxTranslationCast(truex); + truex = truex->Resolve(ctx); + ValueType = ctx.Version < MakeVersion(4, 12, 0)? TypeSInt32 : TypeTranslationID; + } + else if (falsex->IsInteger() && truex->ValueType == TypeTranslationID) + { + falsex = new FxTranslationCast(falsex); + falsex = falsex->Resolve(ctx); + ValueType = ctx.Version < MakeVersion(4, 12, 0) ? TypeSInt32 : TypeTranslationID; + } + else ValueType = TypeVoid; - //else if (truex->ValueType != falsex->ValueType) - if (ValueType->GetRegType() == REGT_NIL) + if (truex == nullptr || falsex == nullptr || ValueType->GetRegType() == REGT_NIL) { ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator"); delete this; @@ -6273,6 +6637,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) ABORT(newex); goto foundit; } + else if (sym->IsKindOf(RUNTIME_CLASS(PFunction))) + { + if (ctx.Version >= MakeVersion(4, 11, 100)) + { + // VMFunction is only supported since 4.12 and Raze 1.8. + newex = new FxConstant(static_cast(sym), ScriptPosition); + goto foundit; + } + } } // now check in the owning class. @@ -6284,6 +6657,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) newex = FxConstant::MakeConstant(sym, ScriptPosition); goto foundit; } + else if (sym->IsKindOf(RUNTIME_CLASS(PFunction))) + { + if (ctx.Version >= MakeVersion(4, 11, 100)) + { + // VMFunction is only supported since 4.12 and Raze 1.8. + newex = new FxConstant(static_cast(sym), ScriptPosition); + goto foundit; + } + } else if (ctx.Function == nullptr) { ScriptPosition.Message(MSG_ERROR, "Unable to access class member %s from constant declaration", sym->SymbolName.GetChars()); @@ -6428,7 +6810,6 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType * if (result != this) return result; } - if (objtype != nullptr && (sym = objtype->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr) { if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) @@ -6644,7 +7025,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) SAFE_RESOLVE(Object, ctx); - // check for class or struct constants if the left side is a type name. + // check for class or struct constants/functions if the left side is a type name. if (Object->ValueType == TypeError) { if (ccls != nullptr) @@ -6658,6 +7039,16 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) delete this; return FxConstant::MakeConstant(sym, ScriptPosition); } + else if(sym->IsKindOf(RUNTIME_CLASS(PFunction))) + { + if (ctx.Version >= MakeVersion(4, 11, 100)) + { + // VMFunction is only supported since 4.12 and Raze 1.8. + auto x = new FxConstant(static_cast(sym), ScriptPosition); + delete this; + return x->Resolve(ctx); + } + } else { auto f = dyn_cast(sym); @@ -7180,7 +7571,7 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable) if (membervar->Flags & VARF_Meta) { // Meta variables are read only. - *writable = false; + if(writable != nullptr) *writable = false; } else if (writable != nullptr) { @@ -7819,7 +8210,7 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction // //========================================================================== -FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos) +FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &&args, const FScriptPosition &pos) : FxExpression(EFX_FunctionCall, pos) { MethodName = methodname; @@ -8063,6 +8454,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) MethodName == NAME_Name ? TypeName : MethodName == NAME_SpriteID ? TypeSpriteID : MethodName == NAME_TextureID ? TypeTextureID : + MethodName == NAME_TranslationID ? TypeTranslationID : MethodName == NAME_State ? TypeState : MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; @@ -8245,7 +8637,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) // //========================================================================== -FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &args, const FScriptPosition &pos) +FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &&args, const FScriptPosition &pos) : FxExpression(EFX_MemberFunctionCall, pos) { Self = self; @@ -8275,6 +8667,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) PContainerType *cls = nullptr; bool staticonly = false; bool novirtual = false; + bool fnptr = false; bool isreadonly = false; PContainerType *ccls = nullptr; @@ -8354,6 +8747,12 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (Self->ValueType->isRealPointer()) { auto pointedType = Self->ValueType->toPointer()->PointedType; + + if(pointedType && pointedType->isStruct() && Self->ValueType->toPointer()->IsConst && ctx.Version >= MakeVersion(4, 12)) + { + isreadonly = true; + } + if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator())) { Self = new FxOutVarDereference(Self, Self->ScriptPosition); @@ -8789,7 +9188,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (a->IsMap()) { // Copy and Move must turn their parameter into a pointer to the backing struct type. - auto o = static_cast(a->ValueType); + auto o = static_cast(a->ValueType); auto backingtype = o->BackingType; if (mapKeyType != o->KeyType || mapValueType != o->ValueType) { @@ -8858,7 +9257,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } } - if (Self->ValueType->isRealPointer()) + if (Self->ValueType->isRealPointer() && Self->ValueType->toPointer()->PointedType) { auto ptype = Self->ValueType->toPointer()->PointedType; cls = ptype->toContainer(); @@ -8883,7 +9282,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } } - else if (Self->ValueType->isStruct()) + else if (Self->ValueType->isStruct() && !isreadonly) { bool writable; @@ -8892,14 +9291,30 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) cls = static_cast(Self->ValueType); Self->ValueType = NewPointer(Self->ValueType); } - else + else if (Self->ValueType->isFunctionPointer()) { - ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s", MethodName.GetChars()); - delete this; - return nullptr; - } - - // Todo: handle member calls from instantiated structs. + auto fn = static_cast(Self->ValueType); + + if(MethodName == NAME_Call && fn->PointedType != TypeVoid) + { // calling a Function pointer isn't allowed + fnptr = true; + afd_override = fn->FakeFunction; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Unknown function %s", MethodName.GetChars()); + delete this; + return nullptr; + } + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s", MethodName.GetChars()); + delete this; + return nullptr; + } + + // Todo: handle member calls from instantiated structs. isresolved: bool error = false; @@ -9011,8 +9426,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } // do not pass the self pointer to static functions. - auto self = (afd->Variants[0].Flags & VARF_Method) ? Self : nullptr; - auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly|novirtual); + auto self = ( fnptr || (afd->Variants[0].Flags & VARF_Method)) ? Self : nullptr; + auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, (staticonly || novirtual) && !fnptr); if (Self == self) Self = nullptr; delete this; return x->Resolve(ctx); @@ -9026,7 +9441,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) //========================================================================== FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual) -: FxExpression(EFX_VMFunctionCall, pos) +: FxExpression(EFX_VMFunctionCall, pos) , FnPtrCall((self && self->ValueType) ? self->ValueType->isFunctionPointer() : false) { Self = self; Function = func; @@ -9100,7 +9515,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction(PFunction *callingfunc, const Ve // definition can call that function directly without wrapping // it inside VM code. - if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual) && CheckAccessibility(ver) && CheckFunctionCompatiblity(ScriptPosition, callingfunc, Function)) + if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual) && !FnPtrCall && CheckAccessibility(ver) && CheckFunctionCompatiblity(ScriptPosition, callingfunc, Function)) { unsigned imp = Function->GetImplicitArgs(); if (Function->Variants[0].ArgFlags.Size() > imp && !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr; @@ -9125,7 +9540,9 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) auto &argtypes = proto->ArgumentTypes; auto &argnames = Function->Variants[0].ArgNames; auto &argflags = Function->Variants[0].ArgFlags; - auto &defaults = Function->Variants[0].Implementation->DefaultArgs; + auto *defaults = FnPtrCall ? nullptr : &Function->Variants[0].Implementation->DefaultArgs; + + if(FnPtrCall) static_cast(ctx.Function->Variants[0].Implementation)->blockJit = true; int implicit = Function->GetImplicitArgs(); @@ -9151,7 +9568,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) // [Player701] Catch attempts to call abstract functions directly at compile time if (NoVirtual && Function->Variants[0].Implementation->VarFlags & VARF_Abstract) { - ScriptPosition.Message(MSG_ERROR, "Cannot call abstract function %s", Function->Variants[0].Implementation->PrintableName.GetChars()); + ScriptPosition.Message(MSG_ERROR, "Cannot call abstract function %s", Function->Variants[0].Implementation->PrintableName); delete this; return nullptr; } @@ -9193,6 +9610,12 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) if (ArgList[i]->ExprType == EFX_NamedNode) { + if(FnPtrCall) + { + ScriptPosition.Message(MSG_ERROR, "Named arguments not supported in function pointer calls"); + delete this; + return nullptr; + } if (!(flag & VARF_Optional)) { ScriptPosition.Message(MSG_ERROR, "Cannot use a named argument here - not all required arguments have been passed."); @@ -9242,7 +9665,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } if (ntype->GetRegCount() == 1) { - auto x = new FxConstant(ntype, defaults[i + k + skipdefs + implicit], ScriptPosition); + auto x = new FxConstant(ntype, (*defaults)[i + k + skipdefs + implicit], ScriptPosition); ArgList.Insert(i + k, x); } else @@ -9251,7 +9674,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) FxConstant *cs[4] = { nullptr }; for (int l = 0; l < ntype->GetRegCount(); l++) { - cs[l] = new FxConstant(TypeFloat64, defaults[l + i + k + skipdefs + implicit], ScriptPosition); + cs[l] = new FxConstant(TypeFloat64, (*defaults)[l + i + k + skipdefs + implicit], ScriptPosition); } FxExpression *x = new FxVectorValue(cs[0], cs[1], cs[2], cs[3], ScriptPosition); ArgList.Insert(i + k, x); @@ -9388,6 +9811,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { ValueType = TypeVoid; } + return this; } @@ -9413,11 +9837,14 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } } - VMFunction *vmfunc = Function->Variants[0].Implementation; - bool staticcall = ((vmfunc->VarFlags & VARF_Final) || vmfunc->VirtualIndex == ~0u || NoVirtual); + VMFunction *vmfunc = FnPtrCall ? nullptr : Function->Variants[0].Implementation; + bool staticcall = (FnPtrCall || (vmfunc->VarFlags & VARF_Final) || vmfunc->VirtualIndex == ~0u || NoVirtual); count = 0; - FunctionCallEmitter emitters(vmfunc); + + assert(!FnPtrCall || (FnPtrCall && Self && Self->ValueType && Self->ValueType->isFunctionPointer())); + + FunctionCallEmitter emitters(FnPtrCall ? FunctionCallEmitter(PType::toFunctionPointer(Self->ValueType)) : FunctionCallEmitter(vmfunc)); // Emit code to pass implied parameters ExpEmit selfemit; if (Function->Variants[0].Flags & VARF_Method) @@ -9461,43 +9888,57 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } } } + else if (FnPtrCall) + { + assert(Self != nullptr); + selfemit = Self->Emit(build); + assert(selfemit.RegType == REGT_POINTER); + build->Emit(OP_NULLCHECK, selfemit.RegNum, 0, 0); + staticcall = false; + } else staticcall = true; // Emit code to pass explicit parameters for (unsigned i = 0; i < ArgList.Size(); ++i) { emitters.AddParameter(build, ArgList[i]); } - // Complete the parameter list from the defaults. - auto &defaults = Function->Variants[0].Implementation->DefaultArgs; - for (unsigned i = emitters.Count(); i < defaults.Size(); i++) + if(!FnPtrCall) { - switch (defaults[i].Type) + // Complete the parameter list from the defaults. + auto &defaults = Function->Variants[0].Implementation->DefaultArgs; + for (unsigned i = emitters.Count(); i < defaults.Size(); i++) { - default: - case REGT_INT: - emitters.AddParameterIntConst(defaults[i].i); - break; - case REGT_FLOAT: - emitters.AddParameterFloatConst(defaults[i].f); - break; - case REGT_POINTER: - emitters.AddParameterPointerConst(defaults[i].a); - break; - case REGT_STRING: - emitters.AddParameterStringConst(defaults[i].s()); - break; + switch (defaults[i].Type) + { + default: + case REGT_INT: + emitters.AddParameterIntConst(defaults[i].i); + break; + case REGT_FLOAT: + emitters.AddParameterFloatConst(defaults[i].f); + break; + case REGT_POINTER: + emitters.AddParameterPointerConst(defaults[i].a); + break; + case REGT_STRING: + emitters.AddParameterStringConst(defaults[i].s()); + break; + } } } ArgList.DeleteAndClear(); ArgList.ShrinkToFit(); if (!staticcall) emitters.SetVirtualReg(selfemit.RegNum); - int resultcount = vmfunc->Proto->ReturnTypes.Size() == 0 ? 0 : max(AssignCount, 1); - assert((unsigned)resultcount <= vmfunc->Proto->ReturnTypes.Size()); + PPrototype * proto = FnPtrCall ? static_cast(static_cast(Self->ValueType)->PointedType) : vmfunc->Proto; + + int resultcount = proto->ReturnTypes.Size() == 0 ? 0 : max(AssignCount, 1); + + assert((unsigned)resultcount <= proto->ReturnTypes.Size()); for (int i = 0; i < resultcount; i++) { - emitters.AddReturn(vmfunc->Proto->ReturnTypes[i]->GetRegType(), vmfunc->Proto->ReturnTypes[i]->GetRegCount()); + emitters.AddReturn(proto->ReturnTypes[i]->GetRegType(), proto->ReturnTypes[i]->GetRegCount()); } return emitters.EmitCall(build, resultcount > 1? &ReturnRegs : nullptr); } @@ -10957,12 +11398,14 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) // //========================================================================== -FxForEachLoop::FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* code, const FScriptPosition& pos) - : FxLoopStatement(EFX_ForEachLoop, pos), loopVarName(vn), Array(arrayvar), Array2(arrayvar2), Code(code) +FxForEachLoop::FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* arrayvar3, FxExpression* arrayvar4, FxExpression* code, const FScriptPosition& pos) + : FxLoopStatement(EFX_ForEachLoop, pos), loopVarName(vn), Array(arrayvar), Array2(arrayvar2), Array3(arrayvar3), Array4(arrayvar4), Code(code) { ValueType = TypeVoid; if (Array != nullptr) Array->NeedResult = false; if (Array2 != nullptr) Array2->NeedResult = false; + if (Array3 != nullptr) Array3->NeedResult = false; + if (Array4 != nullptr) Array4->NeedResult = false; if (Code != nullptr) Code->NeedResult = false; } @@ -10970,57 +11413,347 @@ FxForEachLoop::~FxForEachLoop() { SAFE_DELETE(Array); SAFE_DELETE(Array2); + SAFE_DELETE(Array3); + SAFE_DELETE(Array4); SAFE_DELETE(Code); } +extern bool IsGameSpecificForEachLoop(FxForEachLoop *); +extern FxExpression * ResolveGameSpecificForEachLoop(FxForEachLoop *); + FxExpression* FxForEachLoop::DoResolve(FCompileContext& ctx) { CHECKRESOLVED(); SAFE_RESOLVE(Array, ctx); SAFE_RESOLVE(Array2, ctx); + SAFE_RESOLVE(Array3, ctx); + SAFE_RESOLVE(Array4, ctx); + + + if(Array->ValueType->isMap() || Array->ValueType->isMapIterator()) + { + auto mapLoop = new FxTwoArgForEachLoop(NAME_None, loopVarName, Array, Array2, Array3, Array4, Code, ScriptPosition); + Array = Array2 = Array3 = Array4 = Code = nullptr; + delete this; + return mapLoop->Resolve(ctx); + } + else if(IsGameSpecificForEachLoop(this)) + { + return ResolveGameSpecificForEachLoop(this)->Resolve(ctx); + } + else + { + // Instead of writing a new code generator for this, convert this into + // + // int @size = array.Size(); + // for(int @i = 0; @i < @size; @i++) + // { + // let var = array[i]; + // body + // } + // and let the existing 'for' loop code sort out the rest. + + FName sizevar = "@size"; + FName itvar = "@i"; + + auto block = new FxCompoundStatement(ScriptPosition); + auto arraysize = new FxMemberFunctionCall(Array, NAME_Size, {}, ScriptPosition); + auto size = new FxLocalVariableDeclaration(TypeSInt32, sizevar, arraysize, 0, ScriptPosition); + auto it = new FxLocalVariableDeclaration(TypeSInt32, itvar, new FxConstant(0, ScriptPosition), 0, ScriptPosition); + block->Add(size); + block->Add(it); + + auto cit = new FxLocalVariable(it, ScriptPosition); + auto csiz = new FxLocalVariable(size, ScriptPosition); + auto comp = new FxCompareRel('<', cit, csiz); // new FxIdentifier(itvar, ScriptPosition), new FxIdentifier(sizevar, ScriptPosition)); + + auto iit = new FxLocalVariable(it, ScriptPosition); + auto bump = new FxPreIncrDecr(iit, TK_Incr); + + auto ait = new FxLocalVariable(it, ScriptPosition); + auto access = new FxArrayElement(Array2, ait, true); // Note: Array must be a separate copy because these nodes cannot share the same element. + + auto assign = new FxLocalVariableDeclaration(TypeAuto, loopVarName, access, 0, ScriptPosition); + auto body = new FxCompoundStatement(ScriptPosition); + body->Add(assign); + body->Add(Code); + auto forloop = new FxForLoop(nullptr, comp, bump, body, ScriptPosition); + block->Add(forloop); + Array2 = Array = nullptr; + Code = nullptr; + delete this; + return block->Resolve(ctx); + } +} + +//========================================================================== +// +// FxMapForEachLoop +// +//========================================================================== + +FxTwoArgForEachLoop::FxTwoArgForEachLoop(FName kv, FName vv, FxExpression* mapexpr, FxExpression* mapexpr2, FxExpression* mapexpr3, FxExpression* mapexpr4, FxExpression* code, const FScriptPosition& pos) + : FxExpression(EFX_TwoArgForEachLoop,pos), keyVarName(kv), valueVarName(vv), MapExpr(mapexpr), MapExpr2(mapexpr2), MapExpr3(mapexpr3), MapExpr4(mapexpr4), Code(code) +{ + ValueType = TypeVoid; + if (MapExpr != nullptr) MapExpr->NeedResult = false; + if (MapExpr2 != nullptr) MapExpr2->NeedResult = false; + if (MapExpr3 != nullptr) MapExpr3->NeedResult = false; + if (MapExpr4 != nullptr) MapExpr4->NeedResult = false; + if (Code != nullptr) Code->NeedResult = false; +} + +FxTwoArgForEachLoop::~FxTwoArgForEachLoop() +{ + SAFE_DELETE(MapExpr); + SAFE_DELETE(MapExpr2); + SAFE_DELETE(MapExpr3); + SAFE_DELETE(MapExpr4); + SAFE_DELETE(Code); +} + +extern bool HasGameSpecificTwoArgForEachLoopTypeNames(); +extern const char * GetGameSpecificTwoArgForEachLoopTypeNames(); +extern bool IsGameSpecificTwoArgForEachLoop(FxTwoArgForEachLoop *); +extern FxExpression * ResolveGameSpecificTwoArgForEachLoop(FxTwoArgForEachLoop *); + +FxExpression *FxTwoArgForEachLoop::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(MapExpr, ctx); + SAFE_RESOLVE(MapExpr2, ctx); + SAFE_RESOLVE(MapExpr3, ctx); + SAFE_RESOLVE(MapExpr4, ctx); + + bool is_iterator = false; + + if(IsGameSpecificTwoArgForEachLoop(this)) + { + return ResolveGameSpecificTwoArgForEachLoop(this)->Resolve(ctx); + } + else if(!(MapExpr->ValueType->isMap() || (is_iterator = MapExpr->ValueType->isMapIterator()))) + { + if(HasGameSpecificTwoArgForEachLoopTypeNames()) + { + ScriptPosition.Message(MSG_ERROR, "foreach( k, v : m ) - 'm' must be %s a map, or a map iterator, but is a %s", GetGameSpecificTwoArgForEachLoopTypeNames(), MapExpr->ValueType->DescriptiveName()); + delete this; + return nullptr; + } + else + { + ScriptPosition.Message(MSG_ERROR, "foreach( k, v : m ) - 'm' must be a map or a map iterator, but is a %s", MapExpr->ValueType->DescriptiveName()); + delete this; + return nullptr; + } + } + else if(valueVarName == NAME_None) + { + ScriptPosition.Message(MSG_ERROR, "missing value for foreach( k, v : m )"); + delete this; + return nullptr; + } + - // Instead of writing a new code generator for this, convert this into - // - // int @size = array.Size(); - // for(int @i = 0; @i < @size; @i++) - // { - // let var = array[i]; - // body - // } - // and let the existing 'for' loop code sort out the rest. - - FName sizevar = "@size"; - FName itvar = "@i"; - FArgumentList al; auto block = new FxCompoundStatement(ScriptPosition); - auto arraysize = new FxMemberFunctionCall(Array, NAME_Size, al, ScriptPosition); - auto size = new FxLocalVariableDeclaration(TypeSInt32, sizevar, arraysize, 0, ScriptPosition); - auto it = new FxLocalVariableDeclaration(TypeSInt32, itvar, new FxConstant(0, ScriptPosition), 0, ScriptPosition); - block->Add(size); - block->Add(it); - - auto cit = new FxLocalVariable(it, ScriptPosition); - auto csiz = new FxLocalVariable(size, ScriptPosition); - auto comp = new FxCompareRel('<', cit, csiz); // new FxIdentifier(itvar, ScriptPosition), new FxIdentifier(sizevar, ScriptPosition)); - - auto iit = new FxLocalVariable(it, ScriptPosition); - auto bump = new FxPreIncrDecr(iit, TK_Incr); - - auto ait = new FxLocalVariable(it, ScriptPosition); - auto access = new FxArrayElement(Array2, ait, true); // Note: Array must be a separate copy because these nodes cannot share the same element. - - auto assign = new FxLocalVariableDeclaration(TypeAuto, loopVarName, access, 0, ScriptPosition); - auto body = new FxCompoundStatement(ScriptPosition); - body->Add(assign); - body->Add(Code); - auto forloop = new FxForLoop(nullptr, comp, bump, body, ScriptPosition); - block->Add(forloop); - Array2 = Array = nullptr; - Code = nullptr; - delete this; - return block->Resolve(ctx); + + auto valType = is_iterator ? static_cast(MapExpr->ValueType)->ValueType : static_cast(MapExpr->ValueType)->ValueType; + auto keyType = is_iterator ? static_cast(MapExpr->ValueType)->KeyType : static_cast(MapExpr->ValueType)->KeyType; + + auto v = new FxLocalVariableDeclaration(valType, valueVarName, nullptr, 0, ScriptPosition); + block->Add(v); + + if(keyVarName != NAME_None) + { + auto k = new FxLocalVariableDeclaration(keyType, keyVarName, nullptr, 0, ScriptPosition); + block->Add(k); + } + + + if(MapExpr->ValueType->isMapIterator()) + { + /* + { + KeyType k; + ValueType v; + if(it.ReInit()) while(it.Next()) + { + k = it.GetKey(); + v = it.GetValue(); + body + } + } + */ + + auto inner_block = new FxCompoundStatement(ScriptPosition); + + if(keyVarName != NAME_None) + { + inner_block->Add(new FxAssign(new FxIdentifier(keyVarName, ScriptPosition), new FxMemberFunctionCall(MapExpr, "GetKey", {}, ScriptPosition), true)); + } + + inner_block->Add(new FxAssign(new FxIdentifier(valueVarName, ScriptPosition), new FxMemberFunctionCall(MapExpr2, "GetValue", {}, ScriptPosition), true)); + inner_block->Add(Code); + + auto reInit = new FxMemberFunctionCall(MapExpr3, "ReInit", {}, ScriptPosition); + block->Add(new FxIfStatement(reInit, new FxWhileLoop(new FxMemberFunctionCall(MapExpr4, "Next", {}, ScriptPosition), inner_block, ScriptPosition), nullptr, ScriptPosition)); + + MapExpr = MapExpr2 = MapExpr3 = MapExpr4 = Code = nullptr; + delete this; + return block->Resolve(ctx); + } + else + { + /* + { + KeyType k; + ValueType v; + MapIterator @it; + @it.Init(map); + while(@it.Next()) + { + k = @it.GetKey(); + v = @it.GetValue(); + body + } + } + */ + + PType * itType = NewMapIterator(keyType, valType); + auto it = new FxLocalVariableDeclaration(itType, "@it", nullptr, 0, ScriptPosition); + block->Add(it); + + FArgumentList al_map; + al_map.Push(MapExpr); + + block->Add(new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "Init", std::move(al_map), ScriptPosition)); + + auto inner_block = new FxCompoundStatement(ScriptPosition); + + if(keyVarName != NAME_None) + { + inner_block->Add(new FxAssign(new FxIdentifier(keyVarName, ScriptPosition), new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "GetKey", {}, ScriptPosition), true)); + } + inner_block->Add(new FxAssign(new FxIdentifier(valueVarName, ScriptPosition), new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "GetValue", {}, ScriptPosition), true)); + inner_block->Add(Code); + + block->Add(new FxWhileLoop(new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "Next", {}, ScriptPosition), inner_block, ScriptPosition)); + + delete MapExpr2; + delete MapExpr3; + delete MapExpr4; + MapExpr = MapExpr2 = MapExpr3 = MapExpr4 = Code = nullptr; + delete this; + return block->Resolve(ctx); + } +} + + +//========================================================================== +// +// FxThreeArgForEachLoop +// +//========================================================================== + +FxThreeArgForEachLoop::FxThreeArgForEachLoop(FName vv, FName pv, FName fv, FxExpression* blockiteartorexpr, FxExpression* code, const FScriptPosition& pos) + : FxExpression(EFX_ThreeArgForEachLoop, pos), varVarName(vv), posVarName(pv), flagsVarName(fv), BlockIteratorExpr(blockiteartorexpr), Code(code) +{ + ValueType = TypeVoid; + if (BlockIteratorExpr != nullptr) BlockIteratorExpr->NeedResult = false; + if (Code != nullptr) Code->NeedResult = false; +} + +FxThreeArgForEachLoop::~FxThreeArgForEachLoop() +{ + SAFE_DELETE(BlockIteratorExpr); + SAFE_DELETE(Code); +} + +extern bool HasGameSpecificThreeArgForEachLoopTypeNames(); +extern const char * GetGameSpecificThreeArgForEachLoopTypeNames(); +extern bool IsGameSpecificThreeArgForEachLoop(FxThreeArgForEachLoop *); +extern FxExpression * ResolveGameSpecificThreeArgForEachLoop(FxThreeArgForEachLoop *); + +FxExpression *FxThreeArgForEachLoop::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(BlockIteratorExpr, ctx); + + + if(IsGameSpecificThreeArgForEachLoop(this)) + { + return ResolveGameSpecificThreeArgForEachLoop(this)->Resolve(ctx); + } + else + { + //put any non-game-specific typed for-each loops here + } + + if(HasGameSpecificThreeArgForEachLoopTypeNames()) + { + ScriptPosition.Message(MSG_ERROR, "foreach( a, b, c : it ) - 'it' must be %s but is a %s", GetGameSpecificThreeArgForEachLoopTypeNames(), BlockIteratorExpr->ValueType->DescriptiveName()); + delete this; + return nullptr; + } + else + { + ScriptPosition.Message(MSG_ERROR, "foreach( a, b, c : it ) - three-arg foreach loops not supported"); + delete this; + return nullptr; + } } +//========================================================================== +// +// FxCastForEachLoop +// +//========================================================================== + +FxTypedForEachLoop::FxTypedForEachLoop(FName cv, FName vv, FxExpression* castiteartorexpr, FxExpression* code, const FScriptPosition& pos) + : FxExpression(EFX_TypedForEachLoop, pos), className(cv), varName(vv), Expr(castiteartorexpr), Code(code) +{ + ValueType = TypeVoid; + if (Expr != nullptr) Expr->NeedResult = false; + if (Code != nullptr) Code->NeedResult = false; +} + +FxTypedForEachLoop::~FxTypedForEachLoop() +{ + SAFE_DELETE(Expr); + SAFE_DELETE(Code); +} + +extern bool HasGameSpecificTypedForEachLoopTypeNames(); +extern const char * GetGameSpecificTypedForEachLoopTypeNames(); +extern bool IsGameSpecificTypedForEachLoop(FxTypedForEachLoop *); +extern FxExpression * ResolveGameSpecificTypedForEachLoop(FxTypedForEachLoop *); + +FxExpression *FxTypedForEachLoop::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Expr, ctx); + + if(IsGameSpecificTypedForEachLoop(this)) + { + return ResolveGameSpecificTypedForEachLoop(this)->Resolve(ctx); + } + else + { + //put any non-game-specific typed for-each loops here + } + + if(HasGameSpecificTypedForEachLoopTypeNames()) + { + ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - 'it' must be %s but is a %s",GetGameSpecificTypedForEachLoopTypeNames(), Expr->ValueType->DescriptiveName()); + delete this; + return nullptr; + } + else + { + ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - typed foreach loops not supported"); + delete this; + return nullptr; + } +} //========================================================================== // @@ -11122,6 +11855,10 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx) { mismatchSeverity = MSG_ERROR; } + else if (protoRetCount > retCount) + { // also warn when returning less values then the return count + mismatchSeverity = ctx.Version >= MakeVersion(4, 12) ? MSG_ERROR : MSG_WARNING; + } } if (mismatchSeverity != -1) @@ -11525,6 +12262,228 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build) return emitters.EmitCall(build); } +//========================================================================== +// +//========================================================================== + +FxFunctionPtrCast::FxFunctionPtrCast(PFunctionPointer *ftype, FxExpression *x) + : FxExpression(EFX_FunctionPtrCast, x->ScriptPosition) +{ + ValueType = ftype; + basex = x; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFunctionPtrCast::~FxFunctionPtrCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +static bool AreCompatibleFnPtrs(PFunctionPointer * to, PFunctionPointer * from); + +bool CanNarrowTo(PClass * from, PClass * to) +{ + return from->IsAncestorOf(to); +} + +bool CanWidenTo(PClass * from, PClass * to) +{ + return to->IsAncestorOf(from); +} + +static bool AreCompatibleFnPtrTypes(PPrototype *to, PPrototype *from) +{ + if(to->ArgumentTypes.Size() != from->ArgumentTypes.Size() + || to->ReturnTypes.Size() != from->ReturnTypes.Size()) return false; + int n = to->ArgumentTypes.Size(); + + //allow narrowing of arguments + for(int i = 0; i < n; i++) + { + PType * fromType = from->ArgumentTypes[i]; + PType * toType = to->ArgumentTypes[i]; + if(fromType->isFunctionPointer() && toType->isFunctionPointer()) + { + if(!AreCompatibleFnPtrs(static_cast(toType), static_cast(fromType))) return false; + } + else if(fromType->isClassPointer() && toType->isClassPointer()) + { + PClassPointer * fromClass = static_cast(fromType); + PClassPointer * toClass = static_cast(toType); + //allow narrowing parameters + if(!CanNarrowTo(fromClass->ClassRestriction, toClass->ClassRestriction)) return false; + } + else if(fromType->isObjectPointer() && toType->isObjectPointer()) + { + PObjectPointer * fromObj = static_cast(fromType); + PObjectPointer * toObj = static_cast(toType); + //allow narrowing parameters + if(!CanNarrowTo(fromObj->PointedClass(), toObj->PointedClass())) return false; + } + else if(fromType != toType) + { + return false; + } + } + + n = to->ReturnTypes.Size(); + + for(int i = 0; i < n; i++) + { + PType * fromType = from->ReturnTypes[i]; + PType * toType = to->ReturnTypes[i]; + if(fromType->isFunctionPointer() && toType->isFunctionPointer()) + { + if(!AreCompatibleFnPtrs(static_cast(toType), static_cast(fromType))) return false; + } + else if(fromType->isClassPointer() && toType->isClassPointer()) + { + PClassPointer * fromClass = static_cast(fromType); + PClassPointer * toClass = static_cast(toType); + //allow widening returns + if(!CanWidenTo(fromClass->ClassRestriction, toClass->ClassRestriction)) return false; + } + else if(fromType->isObjectPointer() && toType->isObjectPointer()) + { + PObjectPointer * fromObj = static_cast(fromType); + PObjectPointer * toObj = static_cast(toType); + //allow widening returns + if(!CanWidenTo(fromObj->PointedClass(), toObj->PointedClass())) return false; + } + else if(fromType != toType) + { + return false; + } + } + return true; +} + +static bool AreCompatibleFnPtrs(PFunctionPointer * to, PFunctionPointer * from) +{ + if(to->PointedType == TypeVoid) return true; + else if(from->PointedType == TypeVoid) return false; + + PPrototype * toProto = (PPrototype *)to->PointedType; + PPrototype * fromProto = (PPrototype *)from->PointedType; + return + ( FScopeBarrier::CheckSidesForFunctionPointer(from->Scope, to->Scope) + /* + && toProto->ArgumentTypes == fromProto->ArgumentTypes + && toProto->ReturnTypes == fromProto->ReturnTypes + */ + && AreCompatibleFnPtrTypes(toProto, fromProto) + && to->ArgFlags == from->ArgFlags + ); +} + +FxExpression *FxFunctionPtrCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->isConstant() && basex->ValueType == TypeRawFunction) + { + FxConstant *val = FxTypeCast::convertRawFunctionToFunctionPointer(basex, ScriptPosition); + if(!val) + { + delete this; + return nullptr; + } + } + + if (!(basex->ValueType && basex->ValueType->isFunctionPointer())) + { + delete this; + return nullptr; + } + auto to = static_cast(ValueType); + auto from = static_cast(basex->ValueType); + + if(from->PointedType == TypeVoid) + { // nothing to check at compile-time for casts from Function + return this; + } + else if(AreCompatibleFnPtrs(to, from)) + { // no need to do anything for (Function)(...) or compatible casts + basex->ValueType = ValueType; + auto x = basex; + basex = nullptr; + delete this; + return x; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Cannot cast %s to %s. The types are incompatible.", basex->ValueType->DescriptiveName(), to->DescriptiveName()); + delete this; + return nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +PFunction *NativeFunctionPointerCast(PFunction *from, const PFunctionPointer *to) +{ + if(to->PointedType == TypeVoid) + { + return from; + } + else if(from && ((from->Variants[0].Flags & (VARF_Virtual | VARF_Action)) == 0) && FScopeBarrier::CheckSidesForFunctionPointer(FScopeBarrier::SideFromFlags(from->Variants[0].Flags), to->Scope)) + { + if(to->ArgFlags.Size() != from->Variants[0].ArgFlags.Size()) return nullptr; + int n = to->ArgFlags.Size(); + for(int i = from->GetImplicitArgs(); i < n; i++) // skip checking flags for implicit self + { + if(from->Variants[0].ArgFlags[i] != to->ArgFlags[i]) + { + return nullptr; + } + } + return AreCompatibleFnPtrTypes(static_cast(to->PointedType), from->Variants[0].Proto) ? from : nullptr; + } + else + { // cannot cast virtual/action functions to anything + return nullptr; + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinFunctionPtrCast, NativeFunctionPointerCast) +{ + PARAM_PROLOGUE; + PARAM_POINTER(from, PFunction); + PARAM_POINTER(to, PFunctionPointer); + ACTION_RETURN_POINTER(NativeFunctionPointerCast(from, to)); +} + +ExpEmit FxFunctionPtrCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit funcptr = basex->Emit(build); + + auto sym = FindBuiltinFunction(NAME_BuiltinFunctionPtrCast); + assert(sym); + + FunctionCallEmitter emitters(sym->Variants[0].Implementation); + emitters.AddParameter(funcptr, false); + emitters.AddParameterPointerConst(ValueType); + + emitters.AddReturn(REGT_POINTER); + return emitters.EmitCall(build); +} + //========================================================================== // // declares a single local variable (no arrays) @@ -11589,12 +12548,30 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) return nullptr; } SAFE_RESOLVE(Init, ctx); + + if(Init->isConstant() && Init->ValueType == TypeRawFunction) + { + FxConstant *val = FxTypeCast::convertRawFunctionToFunctionPointer(Init, ScriptPosition); + if(!val) + { + delete this; + return nullptr; + } + } + ValueType = Init->ValueType; if (ValueType->RegType == REGT_NIL) { if (Init->IsStruct()) { - ValueType = NewPointer(ValueType); + bool writable = true; + + if(ctx.Version >= MakeVersion(4, 12, 0)) + { + Init->RequestAddress(ctx, &writable); + } + + ValueType = NewPointer(ValueType, !writable); Init = new FxTypeCast(Init, ValueType, false); SAFE_RESOLVE(Init, ctx); } @@ -11626,8 +12603,7 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) if (IsDynamicArray()) { auto stackVar = new FxStackVariable(ValueType, StackOffset, ScriptPosition); - FArgumentList argsList; - clearExpr = new FxMemberFunctionCall(stackVar, "Clear", argsList, ScriptPosition); + clearExpr = new FxMemberFunctionCall(stackVar, "Clear", {}, ScriptPosition); SAFE_RESOLVE(clearExpr, ctx); } @@ -11945,10 +12921,9 @@ FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx) else { FArgumentList argsList; - argsList.Clear(); argsList.Push(v); - FxExpression *funcCall = new FxMemberFunctionCall(stackVar, NAME_Push, argsList, (const FScriptPosition) v->ScriptPosition); + FxExpression *funcCall = new FxMemberFunctionCall(stackVar, NAME_Push, std::move(argsList), (const FScriptPosition) v->ScriptPosition); SAFE_RESOLVE(funcCall, ctx); v = funcCall; diff --git a/src/common/scripting/backend/codegen.h b/src/common/scripting/backend/codegen.h index c12e33d3f3..cd37a7102b 100644 --- a/src/common/scripting/backend/codegen.h +++ b/src/common/scripting/backend/codegen.h @@ -48,6 +48,7 @@ #include "types.h" #include "vmintern.h" #include "c_cvars.h" +#include "palettecontainer.h" struct FState; // needed for FxConstant. Maybe move the state constructor to a subclass later? @@ -232,6 +233,7 @@ enum EFxType EFX_StringCast, EFX_ColorCast, EFX_SoundCast, + EFX_TranslationCast, EFX_TypeCast, EFX_PlusSign, EFX_MinusSign, @@ -273,10 +275,14 @@ enum EFxType EFX_DoWhileLoop, EFX_ForLoop, EFX_ForEachLoop, + EFX_TwoArgForEachLoop, + EFX_ThreeArgForEachLoop, + EFX_TypedForEachLoop, EFX_JumpStatement, EFX_ReturnStatement, EFX_ClassTypeCast, EFX_ClassPtrCast, + EFX_FunctionPtrCast, EFX_StateByIndex, EFX_RuntimeStateIndex, EFX_MultiNameState, @@ -348,8 +354,8 @@ class FxExpression bool IsQuaternion() const { return ValueType == TypeQuaternion || ValueType == TypeFQuaternion || ValueType == TypeQuaternionStruct; }; bool IsBoolCompat() const { return ValueType->isScalar(); } bool IsObject() const { return ValueType->isObjectPointer(); } - bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); } - bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form. + bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType && ValueType->toPointer()->PointedType->isArray()); } + bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form. bool IsDynamicArray() const { return (ValueType->isDynArray()); } bool IsMap() const { return ValueType->isMap(); } bool IsMapIterator() const { return ValueType->isMapIterator(); } @@ -506,6 +512,27 @@ class FxConstant : public FxExpression isresolved = true; } + FxConstant(FTranslationID state, const FScriptPosition& pos) : FxExpression(EFX_Constant, pos) + { + value.Int = state.index(); + ValueType = value.Type = TypeTranslationID; + isresolved = true; + } + + FxConstant(VMFunction* state, const FScriptPosition& pos) : FxExpression(EFX_Constant, pos) + { + value.pointer = state; + ValueType = value.Type = TypeVMFunction; + isresolved = true; + } + + FxConstant(PFunction* rawptr, const FScriptPosition& pos) : FxExpression(EFX_Constant, pos) + { + value.pointer = rawptr; + ValueType = value.Type = TypeRawFunction; + isresolved = true; + } + FxConstant(const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { value.pointer = nullptr; @@ -550,6 +577,8 @@ class FxConstant : public FxExpression return value; } ExpEmit Emit(VMFunctionBuilder *build); + + friend class FxTypeCast; }; //========================================================================== @@ -698,6 +727,19 @@ class FxSoundCast : public FxExpression ExpEmit Emit(VMFunctionBuilder *build); }; +class FxTranslationCast : public FxExpression +{ + FxExpression* basex; + +public: + + FxTranslationCast(FxExpression* x); + ~FxTranslationCast(); + FxExpression* Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder* build); +}; + class FxFontCast : public FxExpression { FxExpression *basex; @@ -728,6 +770,8 @@ class FxTypeCast : public FxExpression FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); + + static FxConstant * convertRawFunctionToFunctionPointer(FxExpression * in, FScriptPosition &ScriptPosition); }; //========================================================================== @@ -1397,7 +1441,7 @@ class FxMemberBase : public FxExpression //========================================================================== // -// FxGlobalVariabe +// FxGlobalVariable // //========================================================================== @@ -1580,7 +1624,7 @@ class FxFunctionCall : public FxExpression FName MethodName; FArgumentList ArgList; - FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos); + FxFunctionCall(FName methodname, FName rngname, FArgumentList &&args, const FScriptPosition &pos); ~FxFunctionCall(); FxExpression *Resolve(FCompileContext&); }; @@ -1597,10 +1641,11 @@ class FxMemberFunctionCall : public FxExpression FxExpression *Self; FName MethodName; FArgumentList ArgList; + bool ResolveSelf; public: - FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &args, const FScriptPosition &pos); + FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &&args, const FScriptPosition &pos); ~FxMemberFunctionCall(); FxExpression *Resolve(FCompileContext&); }; @@ -1811,6 +1856,7 @@ class FxVMFunctionCall : public FxExpression bool CheckAccessibility(const VersionInfo &ver); public: + const bool FnPtrCall; FArgumentList ArgList; PFunction* Function; @@ -2027,17 +2073,83 @@ class FxForLoop : public FxLoopStatement class FxForEachLoop : public FxLoopStatement { +public: FName loopVarName; FxExpression* Array; FxExpression* Array2; + FxExpression* Array3; + FxExpression* Array4; FxExpression* Code; -public: - FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* code, const FScriptPosition& pos); + FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* arrayvar3, FxExpression* arrayvar4, FxExpression* code, const FScriptPosition& pos); ~FxForEachLoop(); FxExpression* DoResolve(FCompileContext&); }; +//========================================================================== +// +// FxTwoArgForEachLoop +// +//========================================================================== + +class FxTwoArgForEachLoop : public FxExpression +{ +public: + FName keyVarName; + FName valueVarName; + FxExpression* MapExpr; + FxExpression* MapExpr2; + FxExpression* MapExpr3; + FxExpression* MapExpr4; + FxExpression* Code; + + FxTwoArgForEachLoop(FName kv, FName vv, FxExpression* mapexpr, FxExpression* mapexpr2, FxExpression* mapexpr3, FxExpression* mapexpr4, FxExpression* code, const FScriptPosition& pos); + ~FxTwoArgForEachLoop(); + FxExpression *Resolve(FCompileContext&); + //ExpEmit Emit(VMFunctionBuilder *build); This node is transformed, so it won't ever be emitted itself +}; + +//========================================================================== +// +// FxThreeArgForEachLoop +// +//========================================================================== + +class FxThreeArgForEachLoop : public FxExpression +{ +public: + FName varVarName; + FName posVarName; + FName flagsVarName; + FxExpression* BlockIteratorExpr; + FxExpression* Code; + + FxThreeArgForEachLoop(FName vv, FName pv, FName fv, FxExpression* blockiteartorexpr, FxExpression* code, const FScriptPosition& pos); + ~FxThreeArgForEachLoop(); + FxExpression *Resolve(FCompileContext&); + //ExpEmit Emit(VMFunctionBuilder *build); This node is transformed, so it won't ever be emitted itself +}; + +//========================================================================== +// +// FxTypedForEachLoop +// +//========================================================================== + +class FxTypedForEachLoop : public FxExpression +{ +public: + FName className; + FName varName; + FxExpression* Expr; + FxExpression* Code; + + FxTypedForEachLoop(FName cv, FName vv, FxExpression* castiteartorexpr, FxExpression* code, const FScriptPosition& pos); + ~FxTypedForEachLoop(); + FxExpression *Resolve(FCompileContext&); + //ExpEmit Emit(VMFunctionBuilder *build); This node is transformed, so it won't ever be emitted itself +}; + //========================================================================== // // FxJumpStatement @@ -2120,6 +2232,24 @@ class FxClassPtrCast : public FxExpression // //========================================================================== +class FxFunctionPtrCast : public FxExpression +{ + FxExpression *basex; + +public: + + FxFunctionPtrCast (PFunctionPointer *ftype, FxExpression *x); + ~FxFunctionPtrCast(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// +// +//========================================================================== + class FxNop : public FxExpression { public: diff --git a/src/common/scripting/backend/vmbuilder.cpp b/src/common/scripting/backend/vmbuilder.cpp index 7d270af61e..71a766d9a7 100644 --- a/src/common/scripting/backend/vmbuilder.cpp +++ b/src/common/scripting/backend/vmbuilder.cpp @@ -37,9 +37,13 @@ #include "m_argv.h" #include "c_cvars.h" #include "jit.h" +#include "filesystem.h" CVAR(Bool, strictdecorate, false, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) +EXTERN_CVAR(Bool, vm_jit) +EXTERN_CVAR(Bool, vm_jit_aot) + struct VMRemap { uint8_t altOp, kReg, kType; @@ -289,6 +293,24 @@ unsigned VMFunctionBuilder::GetConstantAddress(void *ptr) } } + +//========================================================================== +// +// VMFunctionBuilder :: FindConstantInt +// +// Returns a constant register initialized with the given value. +// +//========================================================================== + +int VMFunctionBuilder::FindConstantInt(unsigned index) +{ + if(IntConstantList.Size() < index) + { + return IntConstantList[index]; + } + return 0; +} + //========================================================================== // // VMFunctionBuilder :: AllocConstants* @@ -297,7 +319,7 @@ unsigned VMFunctionBuilder::GetConstantAddress(void *ptr) // //========================================================================== -unsigned VMFunctionBuilder::AllocConstantsInt(unsigned count, int *values) +unsigned VMFunctionBuilder::AllocConstantsInt(unsigned int count, int *values) { unsigned addr = IntConstantList.Reserve(count); memcpy(&IntConstantList[addr], values, count * sizeof(int)); @@ -308,7 +330,7 @@ unsigned VMFunctionBuilder::AllocConstantsInt(unsigned count, int *values) return addr; } -unsigned VMFunctionBuilder::AllocConstantsFloat(unsigned count, double *values) +unsigned VMFunctionBuilder::AllocConstantsFloat(unsigned int count, double *values) { unsigned addr = FloatConstantList.Reserve(count); memcpy(&FloatConstantList[addr], values, count * sizeof(double)); @@ -319,7 +341,7 @@ unsigned VMFunctionBuilder::AllocConstantsFloat(unsigned count, double *values) return addr; } -unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs) +unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned int count, void **ptrs) { unsigned addr = AddressConstantList.Reserve(count); memcpy(&AddressConstantList[addr], ptrs, count * sizeof(void *)); @@ -330,7 +352,7 @@ unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs) return addr; } -unsigned VMFunctionBuilder::AllocConstantsString(unsigned count, FString *ptrs) +unsigned VMFunctionBuilder::AllocConstantsString(unsigned int count, FString *ptrs) { unsigned addr = StringConstantList.Reserve(count); for (unsigned i = 0; i < count; i++) @@ -790,7 +812,7 @@ VMFunction *FFunctionBuildList::AddFunction(PNamespace *gnspc, const VersionInfo it.PrintableName = name; it.Function = new VMScriptFunction; it.Function->Name = functype->SymbolName; - it.Function->PrintableName = name; + it.Function->QualifiedName = it.Function->PrintableName = ClassDataAllocator.Strdup(name.GetChars()); it.Function->ImplicitArgs = functype->GetImplicitArgs(); it.Proto = nullptr; it.FromDecorate = fromdecorate; @@ -909,6 +931,13 @@ void FFunctionBuildList::Build() disasmdump.Write(sfunc, item.PrintableName); sfunc->Unsafe = ctx.Unsafe; + + #if HAVE_VM_JIT + if(vm_jit && vm_jit_aot) + { + sfunc->JitCompile(); + } + #endif } catch (CRecoverableError &err) { @@ -922,13 +951,17 @@ void FFunctionBuildList::Build() VMFunction::CreateRegUseInfo(); FScriptPosition::StrictErrors = strictdecorate; - if (FScriptPosition::ErrorCounter == 0 && Args->CheckParm("-dumpjit")) DumpJit(); + if (FScriptPosition::ErrorCounter == 0) + { + if (Args->CheckParm("-dumpjit")) DumpJit(true); + else if (Args->CheckParm("-dumpjitmod")) DumpJit(false); + } mItems.Clear(); mItems.ShrinkToFit(); FxAlloc.FreeAllBlocks(); } -void FFunctionBuildList::DumpJit() +void FFunctionBuildList::DumpJit(bool include_gzdoom_pk3) { #ifdef HAVE_VM_JIT FILE *dump = fopen("dumpjit.txt", "w"); @@ -937,13 +970,25 @@ void FFunctionBuildList::DumpJit() for (auto &item : mItems) { - JitDumpLog(dump, item.Function); + if(include_gzdoom_pk3 || fileSystem.GetFileContainer(item.Lump)) JitDumpLog(dump, item.Function); } fclose(dump); #endif // HAVE_VM_JIT } +FunctionCallEmitter::FunctionCallEmitter(VMFunction *func) +{ + target = func; + is_vararg = target->VarFlags & VARF_VarArg; +} + +FunctionCallEmitter::FunctionCallEmitter(class PFunctionPointer *func) +{ + fnptr = func; + is_vararg = false; // function pointers cannot point to vararg functions +} + void FunctionCallEmitter::AddParameter(VMFunctionBuilder *build, FxExpression *operand) { @@ -954,7 +999,7 @@ void FunctionCallEmitter::AddParameter(VMFunctionBuilder *build, FxExpression *o operand->ScriptPosition.Message(MSG_ERROR, "Attempted to pass a non-value"); } numparams += where.RegCount; - if (target->VarFlags & VARF_VarArg) + if (is_vararg) for (unsigned i = 0; i < where.RegCount; i++) reginfo.Push(where.RegType & REGT_TYPE); emitters.push_back([=](VMFunctionBuilder *build) -> int @@ -977,7 +1022,7 @@ void FunctionCallEmitter::AddParameter(VMFunctionBuilder *build, FxExpression *o void FunctionCallEmitter::AddParameter(ExpEmit &emit, bool reference) { numparams += emit.RegCount; - if (target->VarFlags & VARF_VarArg) + if (is_vararg) { if (reference) reginfo.Push(REGT_POINTER); else for (unsigned i = 0; i < emit.RegCount; i++) reginfo.Push(emit.RegType & REGT_TYPE); @@ -994,7 +1039,7 @@ void FunctionCallEmitter::AddParameter(ExpEmit &emit, bool reference) void FunctionCallEmitter::AddParameterPointerConst(void *konst) { numparams++; - if (target->VarFlags & VARF_VarArg) + if (is_vararg) reginfo.Push(REGT_POINTER); emitters.push_back([=](VMFunctionBuilder *build) ->int { @@ -1006,7 +1051,7 @@ void FunctionCallEmitter::AddParameterPointerConst(void *konst) void FunctionCallEmitter::AddParameterPointer(int index, bool konst) { numparams++; - if (target->VarFlags & VARF_VarArg) + if (is_vararg) reginfo.Push(REGT_POINTER); emitters.push_back([=](VMFunctionBuilder *build) ->int { @@ -1018,7 +1063,7 @@ void FunctionCallEmitter::AddParameterPointer(int index, bool konst) void FunctionCallEmitter::AddParameterFloatConst(double konst) { numparams++; - if (target->VarFlags & VARF_VarArg) + if (is_vararg) reginfo.Push(REGT_FLOAT); emitters.push_back([=](VMFunctionBuilder *build) ->int { @@ -1030,7 +1075,7 @@ void FunctionCallEmitter::AddParameterFloatConst(double konst) void FunctionCallEmitter::AddParameterIntConst(int konst) { numparams++; - if (target->VarFlags & VARF_VarArg) + if (is_vararg) reginfo.Push(REGT_INT); emitters.push_back([=](VMFunctionBuilder *build) ->int { @@ -1050,7 +1095,7 @@ void FunctionCallEmitter::AddParameterIntConst(int konst) void FunctionCallEmitter::AddParameterStringConst(const FString &konst) { numparams++; - if (target->VarFlags & VARF_VarArg) + if (is_vararg) reginfo.Push(REGT_STRING); emitters.push_back([=](VMFunctionBuilder *build) ->int { @@ -1059,8 +1104,6 @@ void FunctionCallEmitter::AddParameterStringConst(const FString &konst) }); } -EXTERN_CVAR(Bool, vm_jit) - ExpEmit FunctionCallEmitter::EmitCall(VMFunctionBuilder *build, TArray *ReturnRegs) { unsigned paramcount = 0; @@ -1069,7 +1112,7 @@ ExpEmit FunctionCallEmitter::EmitCall(VMFunctionBuilder *build, TArray paramcount += func(build); } assert(paramcount == numparams); - if (target->VarFlags & VARF_VarArg) + if (is_vararg) { // Pass a hidden type information parameter to vararg functions. // It would really be nicer to actually pass real types but that'd require a far more complex interface on the compiler side than what we have. @@ -1079,9 +1122,24 @@ ExpEmit FunctionCallEmitter::EmitCall(VMFunctionBuilder *build, TArray paramcount++; } + if(fnptr) + { + ExpEmit reg(build, REGT_POINTER); + + assert(fnptr->Scope != -1); + assert(fnptr->PointedType != TypeVoid); + + // OP_LP , Load from memory. rA = *(rB + rkC) + // reg = &PFunction->Variants[0] -- PFunction::Variant* + build->Emit(OP_LP, reg.RegNum, virtualselfreg, build->GetConstantInt(offsetof(PFunction, Variants) + offsetof(FArray, Array))); + // reg = (&PFunction->Variants[0])->Implementation -- VMFunction* + build->Emit(OP_LP, reg.RegNum, reg.RegNum, build->GetConstantInt(offsetof(PFunction::Variant, Implementation))); + build->Emit(OP_CALL, reg.RegNum, paramcount, vm_jit? static_cast(fnptr->PointedType)->ReturnTypes.Size() : returns.Size()); - if (virtualselfreg == -1) + reg.Free(build); + } + else if (virtualselfreg == -1) { build->Emit(OP_CALL_K, build->GetConstantAddress(target), paramcount, vm_jit ? target->Proto->ReturnTypes.Size() : returns.Size()); } @@ -1105,9 +1163,13 @@ ExpEmit FunctionCallEmitter::EmitCall(VMFunctionBuilder *build, TArray } if (vm_jit) // The JIT compiler needs this, but the VM interpreter does not. { - for (unsigned i = returns.Size(); i < target->Proto->ReturnTypes.Size(); i++) + assert(!fnptr || fnptr->PointedType != TypeVoid); + + PPrototype * proto = fnptr ? static_cast(fnptr->PointedType) : target->Proto; + + for (unsigned i = returns.Size(); i < proto->ReturnTypes.Size(); i++) { - ExpEmit reg(build, target->Proto->ReturnTypes[i]->RegType, target->Proto->ReturnTypes[i]->RegCount); + ExpEmit reg(build, proto->ReturnTypes[i]->RegType, proto->ReturnTypes[i]->RegCount); build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum); reg.Free(build); } @@ -1148,7 +1210,7 @@ void VMDisassemblyDumper::Write(VMScriptFunction *sfunc, const FString &fname) assert(sfunc != nullptr); - DumpFunction(dump, sfunc, fname, (int)fname.Len()); + DumpFunction(dump, sfunc, fname.GetChars(), (int)fname.Len()); codesize += sfunc->CodeSize; datasize += sfunc->LineInfoCount * sizeof(FStatementInfo) + sfunc->ExtraSpace + sfunc->NumKonstD * sizeof(int) + sfunc->NumKonstA * sizeof(void*) + sfunc->NumKonstF * sizeof(double) + sfunc->NumKonstS * sizeof(FString); diff --git a/src/common/scripting/backend/vmbuilder.h b/src/common/scripting/backend/vmbuilder.h index 8bb43565e6..2ead8f9069 100644 --- a/src/common/scripting/backend/vmbuilder.h +++ b/src/common/scripting/backend/vmbuilder.h @@ -65,6 +65,11 @@ class VMFunctionBuilder unsigned GetConstantAddress(void *ptr); unsigned GetConstantString(FString str); + int FindConstantInt(unsigned index); + //double FindConstantFloat(unsigned index); + //void * FindConstantAddress(unsigned index); + //const FString& FindConstantString(unsigned index); + unsigned AllocConstantsInt(unsigned int count, int *values); unsigned AllocConstantsFloat(unsigned int count, double *values); unsigned AllocConstantsAddress(unsigned int count, void **ptrs); @@ -155,7 +160,7 @@ class FFunctionBuildList TArray mItems; - void DumpJit(); + void DumpJit(bool include_gzdoom_pk3); public: VMFunction *AddFunction(PNamespace *curglobals, const VersionInfo &ver, PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate, int statecnt, int lumpnum); @@ -180,13 +185,12 @@ class FunctionCallEmitter TArray reginfo; unsigned numparams = 0; // This counts the number of pushed elements, which can differ from the number of emitters with vectors. VMFunction *target = nullptr; + class PFunctionPointer *fnptr = nullptr; int virtualselfreg = -1; - + bool is_vararg; public: - FunctionCallEmitter(VMFunction *func) - { - target = func; - } + FunctionCallEmitter(VMFunction *func); + FunctionCallEmitter(class PFunctionPointer *func); void SetVirtualReg(int virtreg) { diff --git a/src/common/scripting/core/imports.cpp b/src/common/scripting/core/imports.cpp index c5a8cf9c5e..ff6d7ceba7 100644 --- a/src/common/scripting/core/imports.cpp +++ b/src/common/scripting/core/imports.cpp @@ -147,6 +147,24 @@ VMFunction *FindVMFunction(PClass *cls, const char *name) } +//========================================================================== +// +// Find an action function in AActor's table from a qualified name +// This cannot search in structs. sorry. :( +// +//========================================================================== + +VMFunction* FindVMFunction( const char* name) +{ + auto p = strchr(name, '.'); + if (p == nullptr) return nullptr; + std::string clsname(name, p - name); + auto cls = PClass::FindClass(clsname.c_str()); + if (cls == nullptr) return nullptr; + return FindVMFunction(cls, p + 1); +} + + //========================================================================== // // Sorting helpers @@ -198,7 +216,8 @@ void InitImports() { assert(afunc->VMPointer != NULL); *(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->FuncName); - (*(afunc->VMPointer))->PrintableName.Format("%s.%s [Native]", afunc->ClassName+1, afunc->FuncName); + (*(afunc->VMPointer))->QualifiedName = ClassDataAllocator.Strdup(FStringf("%s.%s", afunc->ClassName + 1, afunc->FuncName).GetChars()); + (*(afunc->VMPointer))->PrintableName = ClassDataAllocator.Strdup(FStringf("%s.%s [Native]", afunc->ClassName+1, afunc->FuncName).GetChars()); (*(afunc->VMPointer))->DirectNativeCall = afunc->DirectNative; AFTable.Push(*afunc); }); diff --git a/src/common/scripting/core/scopebarrier.cpp b/src/common/scripting/core/scopebarrier.cpp index a6c5a23705..b274435707 100644 --- a/src/common/scripting/core/scopebarrier.cpp +++ b/src/common/scripting/core/scopebarrier.cpp @@ -208,6 +208,14 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name) } } +bool FScopeBarrier::CheckSidesForFunctionPointer(int from, int to) +{ + if(to == -1) return true; + + if(from == Side_Clear) from = Side_PlainData; + return ((from == to) || (from == Side_PlainData)); +} + // these are for vmexec.h void FScopeBarrier::ValidateNew(PClass* cls, int outerside) { @@ -221,5 +229,5 @@ void FScopeBarrier::ValidateCall(PClass* selftype, VMFunction *calledfunc, int o { int innerside = FScopeBarrier::SideFromObjectFlags(selftype->VMType->ScopeFlags); if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) - ThrowAbortException(X_OTHER, "Cannot call %s function %s from %s context", FScopeBarrier::StringFromSide(innerside), calledfunc->PrintableName.GetChars(), FScopeBarrier::StringFromSide(outerside)); + ThrowAbortException(X_OTHER, "Cannot call %s function %s from %s context", FScopeBarrier::StringFromSide(innerside), calledfunc->PrintableName, FScopeBarrier::StringFromSide(outerside)); } \ No newline at end of file diff --git a/src/common/scripting/core/scopebarrier.h b/src/common/scripting/core/scopebarrier.h index b5eeae78fc..08fc0a195a 100644 --- a/src/common/scripting/core/scopebarrier.h +++ b/src/common/scripting/core/scopebarrier.h @@ -62,6 +62,9 @@ struct FScopeBarrier // This struct is used so that the logic is in a single place. void AddFlags(int flags1, int flags2, const char* name); + + static bool CheckSidesForFunctionPointer(int from, int to); + // this is called from vmexec.h static void ValidateNew(PClass* cls, int scope); static void ValidateCall(PClass* selftype, VMFunction *calledfunc, int outerside); diff --git a/src/common/scripting/core/symbols.h b/src/common/scripting/core/symbols.h index de5caaae99..b75d3a2ea2 100644 --- a/src/common/scripting/core/symbols.h +++ b/src/common/scripting/core/symbols.h @@ -9,6 +9,16 @@ class PPrototype; struct ZCC_TreeNode; class PContainerType; +// This is needed in common code, despite being Doom specific. +enum EStateUseFlags +{ + SUF_ACTOR = 1, + SUF_OVERLAY = 2, + SUF_WEAPON = 4, + SUF_ITEM = 8, +}; + + // Symbol information ------------------------------------------------------- class PTypeBase @@ -44,7 +54,7 @@ class PSymbolType : public PSymbol { DECLARE_CLASS(PSymbolType, PSymbol); public: - PType *Type; + PType *Type = nullptr; PSymbolType(FName name, class PType *ty) : PSymbol(name), Type(ty) {} PSymbolType() : PSymbol(NAME_None) {} @@ -56,7 +66,7 @@ class PSymbolTreeNode : public PSymbol { DECLARE_CLASS(PSymbolTreeNode, PSymbol); public: - struct ZCC_TreeNode *Node; + struct ZCC_TreeNode *Node = nullptr; PSymbolTreeNode(FName name, struct ZCC_TreeNode *node) : PSymbol(name), Node(node) {} PSymbolTreeNode() : PSymbol(NAME_None) {} @@ -137,11 +147,11 @@ class PSymbolConstNumeric : public PSymbolConst void *Pad; }; - PSymbolConstNumeric(FName name, PType *type=NULL) : PSymbolConst(name, type) {} + PSymbolConstNumeric(FName name, PType *type=nullptr) : PSymbolConst(name, type), Float(0) {} PSymbolConstNumeric(FName name, PType *type, int val) : PSymbolConst(name, type), Value(val) {} PSymbolConstNumeric(FName name, PType *type, unsigned int val) : PSymbolConst(name, type), Value((int)val) {} PSymbolConstNumeric(FName name, PType *type, double val) : PSymbolConst(name, type), Float(val) {} - PSymbolConstNumeric() {} + PSymbolConstNumeric() : Float(0) {} }; // A constant string value -------------------------------------------------- diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index 693e84e2e8..8e13dcc521 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -41,6 +41,9 @@ #include "printf.h" #include "textureid.h" #include "maps.h" +#include "palettecontainer.h" +#include "texturemanager.h" +#include "i_interface.h" FTypeTable TypeTable; @@ -58,6 +61,7 @@ PName *TypeName; PSound *TypeSound; PColor *TypeColor; PTextureID *TypeTextureID; +PTranslationID* TypeTranslationID; PSpriteID *TypeSpriteID; PStatePointer *TypeState; PPointer *TypeFont; @@ -75,6 +79,8 @@ PStruct *TypeStringStruct; PStruct* TypeQuaternionStruct; PPointer *TypeNullPtr; PPointer *TypeVoidPtr; +PPointer *TypeRawFunction; +PPointer* TypeVMFunction; // CODE -------------------------------------------------------------------- @@ -110,7 +116,7 @@ void DumpTypeTable() } Printf("\n"); } - Printf("Used buckets: %d/%lu (%.2f%%) for %d entries\n", used, countof(TypeTable.TypeHash), double(used)/countof(TypeTable.TypeHash)*100, all); + Printf("Used buckets: %d/%zu (%.2f%%) for %d entries\n", used, countof(TypeTable.TypeHash), double(used)/countof(TypeTable.TypeHash)*100, all); Printf("Min bucket size: %d\n", min); Printf("Max bucket size: %d\n", max); Printf("Avg bucket size: %.2f\n", double(all) / used); @@ -190,15 +196,15 @@ void PType::SetDefaultValue(void *base, unsigned offset, TArray // //========================================================================== -void PType::SetPointer(void *base, unsigned offset, TArray *stroffs) +void PType::SetPointer(void *base, unsigned offset, TArray> *stroffs) { } -void PType::SetPointerArray(void *base, unsigned offset, TArray *stroffs) +void PType::SetPointerArray(void *base, unsigned offset, TArray> *stroffs) { } -void PType::SetPointerMap(void *base, unsigned offset, TArray> *ptrofs) +void PType::SetPointerMap(void *base, unsigned offset, TArray> *ptrofs) { } @@ -320,8 +326,12 @@ void PType::StaticInit() TypeTable.AddType(TypeNullPtr = new PPointer, NAME_Pointer); TypeTable.AddType(TypeSpriteID = new PSpriteID, NAME_SpriteID); TypeTable.AddType(TypeTextureID = new PTextureID, NAME_TextureID); + TypeTable.AddType(TypeTranslationID = new PTranslationID, NAME_TranslationID); TypeVoidPtr = NewPointer(TypeVoid, false); + TypeRawFunction = new PPointer; + TypeRawFunction->mDescriptiveName = "Raw Function Pointer"; + TypeVMFunction = NewPointer(NewStruct("VMFunction", nullptr, true)); TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. TypeStringStruct = NewStruct("Stringstruct", nullptr, true); TypeQuaternionStruct = NewStruct("QuatStruct", nullptr, true); @@ -853,6 +863,7 @@ void PFloat::SetDoubleSymbols() { NAME_Min_Normal, DBL_MIN }, { NAME_Max, DBL_MAX }, { NAME_Epsilon, DBL_EPSILON }, + { NAME_Equal_Epsilon, EQUAL_EPSILON }, { NAME_NaN, std::numeric_limits::quiet_NaN() }, { NAME_Infinity, std::numeric_limits::infinity() }, { NAME_Min_Denormal, std::numeric_limits::denorm_min() } @@ -885,6 +896,7 @@ void PFloat::SetSingleSymbols() { NAME_Min_Normal, FLT_MIN }, { NAME_Max, FLT_MAX }, { NAME_Epsilon, FLT_EPSILON }, + { NAME_Equal_Epsilon, (float)EQUAL_EPSILON }, { NAME_NaN, std::numeric_limits::quiet_NaN() }, { NAME_Infinity, std::numeric_limits::infinity() }, { NAME_Min_Denormal, std::numeric_limits::denorm_min() } @@ -1314,6 +1326,48 @@ bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const return true; } +/* PTranslationID ******************************************************************/ + +//========================================================================== +// +// PTranslationID Default Constructor +// +//========================================================================== + +PTranslationID::PTranslationID() + : PInt(sizeof(FTranslationID), true, false) +{ + mDescriptiveName = "TranslationID"; + Flags |= TYPE_IntNotInt; + static_assert(sizeof(FTranslationID) == alignof(FTranslationID), "TranslationID not properly aligned"); +} + +//========================================================================== +// +// PTranslationID :: WriteValue +// +//========================================================================== + +void PTranslationID::WriteValue(FSerializer& ar, const char* key, const void* addr) const +{ + FTranslationID val = *(FTranslationID*)addr; + ar(key, val); +} + +//========================================================================== +// +// PTranslationID :: ReadValue +// +//========================================================================== + +bool PTranslationID::ReadValue(FSerializer& ar, const char* key, void* addr) const +{ + FTranslationID val; + ar(key, val); + *(FTranslationID*)addr = val; + return true; +} + /* PSound *****************************************************************/ //========================================================================== @@ -1521,10 +1575,10 @@ PObjectPointer::PObjectPointer(PClass *cls, bool isconst) // //========================================================================== -void PObjectPointer::SetPointer(void *base, unsigned offset, TArray *special) +void PObjectPointer::SetPointer(void *base, unsigned offset, TArray> *special) { // Add to the list of pointers for this class. - special->Push(offset); + special->Push({offset, this}); } //========================================================================== @@ -1607,7 +1661,8 @@ PClassPointer::PClassPointer(PClass *restrict) loadOp = OP_LP; storeOp = OP_SP; Flags |= TYPE_ClassPointer; - mVersion = restrict->VMType->mVersion; + if (restrict) mVersion = restrict->VMType->mVersion; + else mVersion = 0; } //========================================================================== @@ -1651,7 +1706,7 @@ bool PClassPointer::isCompatible(PType *type) // //========================================================================== -void PClassPointer::SetPointer(void *base, unsigned offset, TArray *special) +void PClassPointer::SetPointer(void *base, unsigned offset, TArray> *special) { } @@ -1853,7 +1908,7 @@ void PArray::SetDefaultValue(void *base, unsigned offset, TArray // //========================================================================== -void PArray::SetPointer(void *base, unsigned offset, TArray *special) +void PArray::SetPointer(void *base, unsigned offset, TArray> *special) { for (unsigned i = 0; i < ElementCount; ++i) { @@ -1867,7 +1922,7 @@ void PArray::SetPointer(void *base, unsigned offset, TArray *special) // //========================================================================== -void PArray::SetPointerArray(void *base, unsigned offset, TArray *special) +void PArray::SetPointerArray(void *base, unsigned offset, TArray> *special) { if (ElementType->isStruct() || ElementType->isDynArray()) { @@ -1884,7 +1939,7 @@ void PArray::SetPointerArray(void *base, unsigned offset, TArray *specia // //========================================================================== -void PArray::SetPointerMap(void *base, unsigned offset, TArray> *special) +void PArray::SetPointerMap(void *base, unsigned offset, TArray> *special) { if(ElementType->isStruct() || ElementType->isMap()) { @@ -2199,12 +2254,12 @@ void PDynArray::SetDefaultValue(void *base, unsigned offset, TArray *special) +void PDynArray::SetPointerArray(void *base, unsigned offset, TArray> *special) { if (ElementType->isObjectPointer()) { // Add to the list of pointer arrays for this class. - special->Push(offset); + special->Push({offset, this}); } } @@ -2375,60 +2430,50 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const // //========================================================================== +#define FOR_EACH_MAP_TYPE(FN) \ + case PMap::MAP_I32_I8: \ + FN( uint32_t , uint8_t ) \ + case PMap::MAP_I32_I16: \ + FN( uint32_t , uint16_t ) \ + case PMap::MAP_I32_I32: \ + FN( uint32_t , uint32_t ) \ + case PMap::MAP_I32_F32: \ + FN( uint32_t , float ) \ + case PMap::MAP_I32_F64: \ + FN( uint32_t , double ) \ + case PMap::MAP_I32_OBJ: \ + FN( uint32_t , DObject* ) \ + case PMap::MAP_I32_PTR: \ + FN( uint32_t , void* ) \ + case PMap::MAP_I32_STR: \ + FN( uint32_t , FString ) \ + case PMap::MAP_STR_I8: \ + FN( FString , uint8_t ) \ + case PMap::MAP_STR_I16: \ + FN( FString , uint16_t ) \ + case PMap::MAP_STR_I32: \ + FN( FString , uint32_t ) \ + case PMap::MAP_STR_F32: \ + FN( FString , float ) \ + case PMap::MAP_STR_F64: \ + FN( FString , double ) \ + case PMap::MAP_STR_OBJ: \ + FN( FString , DObject* ) \ + case PMap::MAP_STR_PTR: \ + FN( FString , void* ) \ + case PMap::MAP_STR_STR: \ + FN( FString , FString ) + void PMap::Construct(void * addr) const { switch(BackingClass) { - case MAP_I32_I8: - new(addr) ZSMap(); - break; - case MAP_I32_I16: - new(addr) ZSMap(); - break; - case MAP_I32_I32: - new(addr) ZSMap(); - break; - case MAP_I32_F32: - new(addr) ZSMap(); - break; - case MAP_I32_F64: - new(addr) ZSMap(); - break; - case MAP_I32_OBJ: - new(addr) ZSMap(); - break; - case MAP_I32_PTR: - new(addr) ZSMap(); - break; - case MAP_I32_STR: - new(addr) ZSMap(); - break; - case MAP_STR_I8: - new(addr) ZSMap(); - break; - case MAP_STR_I16: - new(addr) ZSMap(); - break; - case MAP_STR_I32: - new(addr) ZSMap(); - break; - case MAP_STR_F32: - new(addr) ZSMap(); - break; - case MAP_STR_F64: - new(addr) ZSMap(); - break; - case MAP_STR_OBJ: - new(addr) ZSMap(); - break; - case MAP_STR_PTR: - new(addr) ZSMap(); - break; - case MAP_STR_STR: - new(addr) ZSMap(); - break; + #define MAP_CONSTRUCT(KT, VT) new(addr) ZSMap< KT, VT >(); break; + FOR_EACH_MAP_TYPE(MAP_CONSTRUCT) + #undef MAP_CONSTRUCT }; } + void PMap::InitializeValue(void *addr, const void *def) const { Construct(addr); @@ -2444,54 +2489,9 @@ void PMap::DestroyValue(void *addr) const { switch(BackingClass) { - case MAP_I32_I8: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_I32_I16: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_I32_I32: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_I32_F32: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_I32_F64: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_I32_OBJ: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_I32_PTR: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_I32_STR: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_STR_I8: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_STR_I16: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_STR_I32: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_STR_F32: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_STR_F64: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_STR_OBJ: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_STR_PTR: - static_cast*>(addr)->~ZSMap(); - break; - case MAP_STR_STR: - static_cast*>(addr)->~ZSMap(); - break; + #define MAP_DESTRUCT(KT, VT) static_cast*>(addr)->~ZSMap(); break; + FOR_EACH_MAP_TYPE(MAP_DESTRUCT) + #undef MAP_DESTRUCT } } @@ -2524,12 +2524,12 @@ void PMap::SetDefaultValue(void *base, unsigned offset, TArray * // //========================================================================== -void PMap::SetPointerMap(void *base, unsigned offset, TArray> *special) +void PMap::SetPointerMap(void *base, unsigned offset, TArray> *special) { if (ValueType->isObjectPointer()) { // Add to the list of pointer arrays for this class. - special->Push(std::make_pair(offset,KeyType)); + special->Push(std::make_pair(offset, this)); } } @@ -2552,9 +2552,63 @@ static void PMapValueWriter(FSerializer &ar, const M *map, const PMap *m) } else if constexpr(std::is_same_v) { - FString key; - key.Format("%u",p->Key); - m->ValueType->WriteValue(ar,key.GetChars(),static_cast(&p->Value)); + if(m->KeyType->Flags & 8 /*TYPE_IntNotInt*/) + { + if(m->KeyType == TypeName) + { + m->ValueType->WriteValue(ar,FName(ENamedName(p->Key)).GetChars(),static_cast(&p->Value)); + } + else if(m->KeyType == TypeSound) + { + m->ValueType->WriteValue(ar,soundEngine->GetSoundName(FSoundID::fromInt(p->Key)),static_cast(&p->Value)); + } + else if(m->KeyType == TypeTextureID) + { + if(!!(p->Key & 0x8000000)) + { // invalid + m->ValueType->WriteValue(ar,"invalid",static_cast(&p->Value)); + } + else if(p->Key == 0 || p->Key >= (unsigned)TexMan.NumTextures()) + { // null + m->ValueType->WriteValue(ar,"null",static_cast(&p->Value)); + } + else + { + FTextureID tid; + tid.SetIndex(p->Key); + FGameTexture *tex = TexMan.GetGameTexture(tid); + int lump = tex->GetSourceLump(); + unsigned useType = static_cast(tex->GetUseType()); + + FString name; + + if (TexMan.GetLinkedTexture(lump) == tex) + { + name = fileSystem.GetFileFullName(lump); + } + else + { + name = tex->GetName().GetChars(); + } + + name.AppendFormat(":%u",useType); + + m->ValueType->WriteValue(ar,name.GetChars(),static_cast(&p->Value)); + } + } + else + { // bool/color/enum/sprite/translationID + FString key; + key.Format("%u",p->Key); + m->ValueType->WriteValue(ar,key.GetChars(),static_cast(&p->Value)); + } + } + else + { + FString key; + key.Format("%u",p->Key); + m->ValueType->WriteValue(ar,key.GetChars(),static_cast(&p->Value)); + } } //else unknown key type } @@ -2566,54 +2620,9 @@ void PMap::WriteValue(FSerializer &ar, const char *key, const void *addr) const { switch(BackingClass) { - case MAP_I32_I8: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_I32_I16: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_I32_I32: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_I32_F32: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_I32_F64: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_I32_OBJ: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_I32_PTR: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_I32_STR: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_STR_I8: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_STR_I16: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_STR_I32: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_STR_F32: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_STR_F64: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_STR_OBJ: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_STR_PTR: - PMapValueWriter(ar, static_cast*>(addr), this); - break; - case MAP_STR_STR: - PMapValueWriter(ar, static_cast*>(addr), this); - break; + #define MAP_WRITE(KT, VT) PMapValueWriter(ar, static_cast*>(addr), this); break; + FOR_EACH_MAP_TYPE(MAP_WRITE) + #undef MAP_WRITE } ar.EndObject(); } @@ -2632,20 +2641,85 @@ static bool PMapValueReader(FSerializer &ar, M *map, const PMap *m) const char * k; while((k = ar.GetKey())) { - typename M::ValueType * val; + typename M::ValueType * val = nullptr; if constexpr(std::is_same_v) { val = &map->InsertNew(k); } else if constexpr(std::is_same_v) { - FString s(k); - if(!s.IsInt()) + if(m->KeyType->Flags & 8 /*TYPE_IntNotInt*/) + { + if(m->KeyType == TypeName) + { + val = &map->InsertNew(FName(k).GetIndex()); + } + else if(m->KeyType == TypeSound) + { + val = &map->InsertNew(S_FindSound(k).index()); + } + else if(m->KeyType == TypeTextureID) + { + FString s(k); + FTextureID tex; + if(s.Compare("invalid") == 0) + { + tex.SetInvalid(); + } + else if(s.Compare("null") == 0) + { + tex.SetNull(); + } + else + { + ptrdiff_t sep = s.LastIndexOf(":"); + if(sep < 0) + { + ar.EndObject(); + return false; + } + FString texName = s.Left(sep); + FString useType = s.Mid(sep + 1); + + tex = TexMan.GetTextureID(texName.GetChars(), (ETextureType) useType.ToULong()); + } + val = &map->InsertNew(tex.GetIndex()); + } + else if(m->KeyType == TypeTranslationID) + { + FString s(k); + if(!s.IsInt()) + { + ar.EndObject(); + return false; + } + int v = (int)s.ToULong(); + + if (sysCallbacks.RemapTranslation) v = sysCallbacks.RemapTranslation(FTranslationID::fromInt(v)).index(); + + val = &map->InsertNew(v); + } + else + { // bool/color/enum/sprite + FString s(k); + if(!s.IsInt()) + { + ar.EndObject(); + return false; + } + val = &map->InsertNew(static_cast(s.ToULong())); + } + } + else { - ar.EndObject(); - return false; + FString s(k); + if(!s.IsInt()) + { + ar.EndObject(); + return false; + } + val = &map->InsertNew(static_cast(s.ToULong())); } - val = &map->InsertNew(static_cast(s.ToULong())); } if (!m->ValueType->ReadValue(ar,nullptr,static_cast(val))) { @@ -2666,38 +2740,9 @@ bool PMap::ReadValue(FSerializer &ar, const char *key, void *addr) const { switch(BackingClass) { - case MAP_I32_I8: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_I32_I16: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_I32_I32: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_I32_F32: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_I32_F64: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_I32_OBJ: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_I32_PTR: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_I32_STR: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_STR_I8: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_STR_I16: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_STR_I32: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_STR_F32: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_STR_F64: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_STR_OBJ: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_STR_PTR: - return PMapValueReader(ar, static_cast*>(addr), this); - case MAP_STR_STR: - return PMapValueReader(ar, static_cast*>(addr), this); + #define MAP_READ(KT, VT) return PMapValueReader(ar, static_cast*>(addr), this); + FOR_EACH_MAP_TYPE(MAP_READ) + #undef MAP_READ } } return false; @@ -2788,11 +2833,11 @@ PMap *NewMap(PType *keyType, PType *valueType) return (PMap *)mapType; } -/* PMap *******************************************************************/ +/* PMapIterator ***********************************************************/ //========================================================================== // -// PMap - Parameterized Constructor +// PMapIterator - Parameterized Constructor // //========================================================================== @@ -2842,54 +2887,9 @@ void PMapIterator::GetTypeIDs(intptr_t &id1, intptr_t &id2) const void PMapIterator::Construct(void * addr) const { switch(BackingClass) { - case PMap::MAP_I32_I8: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_I32_I16: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_I32_I32: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_I32_F32: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_I32_F64: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_I32_OBJ: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_I32_PTR: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_I32_STR: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_STR_I8: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_STR_I16: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_STR_I32: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_STR_F32: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_STR_F64: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_STR_OBJ: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_STR_PTR: - new(addr) ZSMapIterator(); - break; - case PMap::MAP_STR_STR: - new(addr) ZSMapIterator(); - break; + #define MAP_IT_CONSTRUCT(KT, VT) new(addr) ZSMapIterator< KT, VT >(); break; + FOR_EACH_MAP_TYPE(MAP_IT_CONSTRUCT) + #undef MAP_IT_CONSTRUCT }; } @@ -2908,54 +2908,9 @@ void PMapIterator::DestroyValue(void *addr) const { switch(BackingClass) { - case PMap::MAP_I32_I8: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_I32_I16: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_I32_I32: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_I32_F32: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_I32_F64: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_I32_OBJ: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_I32_PTR: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_I32_STR: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_STR_I8: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_STR_I16: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_STR_I32: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_STR_F32: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_STR_F64: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_STR_OBJ: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_STR_PTR: - static_cast*>(addr)->~ZSMapIterator(); - break; - case PMap::MAP_STR_STR: - static_cast*>(addr)->~ZSMapIterator(); - break; + #define MAP_IT_DESTROY(KT, VT) static_cast*>(addr)->~ZSMapIterator(); break; + FOR_EACH_MAP_TYPE(MAP_IT_DESTROY) + #undef MAP_IT_DESTROY } } @@ -3033,6 +2988,239 @@ PMapIterator *NewMapIterator(PType *keyType, PType *valueType) return (PMapIterator *)mapIteratorType; } +/* PFunctionPointer *******************************************************/ + +//========================================================================== +// +// PFunctionPointer - Parameterized Constructor +// +//========================================================================== + +static FString MakeFunctionPointerDescriptiveName(PPrototype * proto,const TArray &ArgFlags, int scope) +{ + FString mDescriptiveName; + + mDescriptiveName = "Function<"; + switch(scope) + { + case FScopeBarrier::Side_PlainData: + mDescriptiveName += "clearscope "; + break; + case FScopeBarrier::Side_Play: + mDescriptiveName += "play "; + break; + case FScopeBarrier::Side_UI: + mDescriptiveName += "ui "; + break; + } + if(proto->ReturnTypes.Size() > 0) + { + mDescriptiveName += proto->ReturnTypes[0]->DescriptiveName(); + + const unsigned n = proto->ReturnTypes.Size(); + for(unsigned i = 1; i < n; i++) + { + mDescriptiveName += ", "; + mDescriptiveName += proto->ReturnTypes[i]->DescriptiveName(); + } + mDescriptiveName += " ("; + } + else + { + mDescriptiveName += "void ("; + } + if(proto->ArgumentTypes.Size() > 0) + { + if(ArgFlags[0] == VARF_Out) mDescriptiveName += "out "; + mDescriptiveName += proto->ArgumentTypes[0]->DescriptiveName(); + const unsigned n = proto->ArgumentTypes.Size(); + for(unsigned i = 1; i < n; i++) + { + mDescriptiveName += ", "; + if(ArgFlags[i] == VARF_Out) mDescriptiveName += "out "; + mDescriptiveName += proto->ArgumentTypes[i]->DescriptiveName(); + } + mDescriptiveName += ")>"; + } + else + { + mDescriptiveName += "void)>"; + } + + return mDescriptiveName; +} + + +FString PFunctionPointer::GenerateNameForError(const PFunction * from) +{ + return MakeFunctionPointerDescriptiveName(from->Variants[0].Proto, from->Variants[0].ArgFlags, FScopeBarrier::SideFromFlags(from->Variants[0].Flags)); +} + +PFunctionPointer::PFunctionPointer(PPrototype * proto, TArray && argflags, int scope) + : PPointer(proto ? (PType*) proto : TypeVoid, false), ArgFlags(std::move(argflags)), Scope(scope) +{ + if(!proto) + { + mDescriptiveName = "Function"; + } + else + { + mDescriptiveName = MakeFunctionPointerDescriptiveName(proto, ArgFlags, scope); + } + + Flags |= TYPE_FunctionPointer; + + if(proto) + { + assert(Scope != -1); // for now, a scope is always required + + TArray ArgNames; + TArray ArgFlags2(ArgFlags); // AddVariant calls std::move on this, so it needs to be a copy, + // but it takes it as a regular reference, so it needs to be a full variable instead of a temporary + ArgNames.Resize(ArgFlags.Size()); + FakeFunction = Create(); + FakeFunction->AddVariant(proto, ArgFlags2, ArgNames, nullptr, FScopeBarrier::FlagsFromSide(Scope), 0); + } + else + { + FakeFunction = nullptr; + } +} + +void PFunctionPointer::WriteValue(FSerializer &ar, const char *key, const void *addr) const +{ + auto p = *(const PFunction**)(addr); + if(p) + { + FunctionPointerValue val; + FunctionPointerValue *fpv = &val; + val.ClassName = FString((p->OwningClass ? p->OwningClass->TypeName : NAME_None).GetChars()); + val.FunctionName = FString(p->SymbolName.GetChars()); + SerializeFunctionPointer(ar, key, fpv); + } + else + { + FunctionPointerValue *fpv = nullptr; + SerializeFunctionPointer(ar, key, fpv); + } +} + +PFunction *NativeFunctionPointerCast(PFunction *from, const PFunctionPointer *to); + +bool PFunctionPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const +{ + FunctionPointerValue val; + FunctionPointerValue *fpv = &val; + SerializeFunctionPointer(ar, key, fpv); + + PFunction ** fn = (PFunction**)(addr); + + if(fpv) + { + auto cls = PClass::FindClass(val.ClassName); + if(!cls) + { + *fn = nullptr; + Printf(TEXTCOLOR_RED "Function Pointer ('%s::%s'): '%s' is not a valid class\n", + val.ClassName.GetChars(), + val.FunctionName.GetChars(), + val.ClassName.GetChars() + ); + ar.mErrors++; + return false; + } + auto sym = cls->FindSymbol(FName(val.FunctionName), true); + if(!sym) + { + *fn = nullptr; + Printf(TEXTCOLOR_RED "Function Pointer ('%s::%s'): symbol '%s' does not exist in class '%s'\n", + val.ClassName.GetChars(), + val.FunctionName.GetChars(), + val.FunctionName.GetChars(), + val.ClassName.GetChars() + ); + ar.mErrors++; + return false; + } + PFunction* p = dyn_cast(sym); + if(!p) + { + *fn = nullptr; + Printf(TEXTCOLOR_RED "Function Pointer (%s::%s): '%s' in class '%s' is a variable, not a function\n", + val.ClassName.GetChars(), + val.FunctionName.GetChars(), + val.FunctionName.GetChars(), + val.ClassName.GetChars() + ); + ar.mErrors++; + return false; + } + *fn = NativeFunctionPointerCast(p, this); + if(!*fn) + { + if((p->Variants[0].Flags & (VARF_Action | VARF_Virtual)) != 0) + { + *fn = nullptr; + Printf(TEXTCOLOR_RED "Function Pointer (%s::%s): function '%s' in class '%s' is %s, not a static function\n", + val.ClassName.GetChars(), + val.FunctionName.GetChars(), + val.FunctionName.GetChars(), + val.ClassName.GetChars(), + (p->GetImplicitArgs() == 1 ? "a virtual function" : "an action function") + ); + } + else + { + FString fn_name = MakeFunctionPointerDescriptiveName(p->Variants[0].Proto,p->Variants[0].ArgFlags, FScopeBarrier::SideFromFlags(p->Variants[0].Flags)); + Printf(TEXTCOLOR_RED "Function Pointer (%s::%s) has incompatible type (Pointer is '%s', Function is '%s')\n", + val.ClassName.GetChars(), + val.FunctionName.GetChars(), + fn_name.GetChars(), + mDescriptiveName.GetChars() + ); + } + ar.mErrors++; + return false; + } + return true; + } + else + { + *fn = nullptr; + } + return true; +} + +bool PFunctionPointer::IsMatch(intptr_t id1, intptr_t id2) const +{ + const PPrototype * proto = (const PPrototype*) id1; + const PFunctionPointer::FlagsAndScope * flags_and_scope = (const PFunctionPointer::FlagsAndScope *) id2; + return (proto == (PointedType == TypeVoid ? nullptr : PointedType)) + && (Scope == flags_and_scope->Scope) + && (ArgFlags == *flags_and_scope->ArgFlags); +} + +void PFunctionPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const +{ //NOT SUPPORTED + assert(0 && "GetTypeIDs not supported for PFunctionPointer"); +} + +PFunctionPointer * NewFunctionPointer(PPrototype * proto, TArray && argflags, int scope) +{ + size_t bucket; + + PFunctionPointer::FlagsAndScope flags_and_scope { &argflags, scope }; + + PType *fn = TypeTable.FindType(NAME_Function, (intptr_t)proto, (intptr_t)&flags_and_scope, &bucket); + if (fn == nullptr) + { + fn = new PFunctionPointer(proto, std::move(argflags), scope); + flags_and_scope.ArgFlags = &static_cast(fn)->ArgFlags; + TypeTable.AddType(fn, NAME_Function, (intptr_t)proto, (intptr_t)&flags_and_scope, bucket); + } + return (PFunctionPointer *)fn; +} + /* PStruct ****************************************************************/ //========================================================================== @@ -3076,7 +3264,7 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArray *special) +void PStruct::SetPointer(void *base, unsigned offset, TArray> *special) { auto it = Symbols.GetIterator(); PSymbolTable::MapType::Pair *pair; @@ -3096,7 +3284,7 @@ void PStruct::SetPointer(void *base, unsigned offset, TArray *special) // //========================================================================== -void PStruct::SetPointerArray(void *base, unsigned offset, TArray *special) +void PStruct::SetPointerArray(void *base, unsigned offset, TArray> *special) { auto it = Symbols.GetIterator(); PSymbolTable::MapType::Pair *pair; @@ -3116,7 +3304,7 @@ void PStruct::SetPointerArray(void *base, unsigned offset, TArray *speci // //========================================================================== -void PStruct::SetPointerMap(void *base, unsigned offset, TArray> *special) +void PStruct::SetPointerMap(void *base, unsigned offset, TArray> *special) { auto it = Symbols.GetIterator(); PSymbolTable::MapType::Pair *pair; @@ -3174,7 +3362,7 @@ bool PStruct::ReadValue(FSerializer &ar, const char *key, void *addr) const PField *PStruct::AddField(FName name, PType *type, uint32_t flags) { assert(type->Size > 0); - return Symbols.AddField(name, type, flags, Size, &Align); + return Symbols.AddField(name, type, flags, Size, &Align, mDefFileNo); } //========================================================================== @@ -3442,13 +3630,13 @@ size_t FTypeTable::Hash(FName p1, intptr_t p2, intptr_t p3) // to transform this into a ROR or ROL. i1 = (i1 >> (sizeof(size_t)*4)) | (i1 << (sizeof(size_t)*4)); - if (p1 != NAME_Prototype) + if (p1 != NAME_Prototype && p1 != NAME_Function) { size_t i2 = (size_t)p2; size_t i3 = (size_t)p3; return (~i1 ^ i2) + i3 * 961748927; // i3 is multiplied by a prime } - else + else if(p1 == NAME_Prototype) { // Prototypes need to hash the TArrays at p2 and p3 const TArray *a2 = (const TArray *)p2; const TArray *a3 = (const TArray *)p3; @@ -3462,6 +3650,18 @@ size_t FTypeTable::Hash(FName p1, intptr_t p2, intptr_t p3) } return i1; } + else // if(p1 == NAME_Function) + { // functions need custom hashing as well + size_t i2 = (size_t)p2; + const PFunctionPointer::FlagsAndScope * flags_and_scope = (const PFunctionPointer::FlagsAndScope *) p3; + const TArray * a3 = flags_and_scope->ArgFlags; + i1 = (~i1 ^ i2); + for (unsigned i = 0; i < a3->Size(); ++i) + { + i1 = (i1 * 961748927) + (size_t)((*a3)[i]); + } + return (i1 * 961748927) + (size_t)flags_and_scope->Scope; + } } //========================================================================== diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index 789cc7d3e4..a092247dea 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -66,9 +66,13 @@ enum class PContainerType; class PPointer; class PClassPointer; +class PFunctionPointer; class PArray; +class PDynArray; +class PMap; class PStruct; class PClassType; +class PObjectPointer; struct ZCC_ExprConstant; class PType : public PTypeBase @@ -86,6 +90,7 @@ class PType : public PTypeBase TYPE_ObjectPointer = 64, TYPE_ClassPointer = 128, TYPE_Array = 256, + TYPE_FunctionPointer = 512, TYPE_IntCompatible = TYPE_Int | TYPE_IntNotInt, // must be the combination of all flags that are subtypes of int and can be cast to an int. }; @@ -127,9 +132,9 @@ class PType : public PTypeBase // initialization when the object is created and destruction when the // object is destroyed. virtual void SetDefaultValue(void *base, unsigned offset, TArray *special=NULL); - virtual void SetPointer(void *base, unsigned offset, TArray *ptrofs = NULL); - virtual void SetPointerArray(void *base, unsigned offset, TArray *ptrofs = NULL); - virtual void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs = NULL); + virtual void SetPointer(void *base, unsigned offset, TArray> *ptrofs = NULL); + virtual void SetPointerArray(void *base, unsigned offset, TArray> *ptrofs = NULL); + virtual void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs = NULL); // Initialize the value, if needed (e.g. strings) virtual void InitializeValue(void *addr, const void *def) const; @@ -194,9 +199,10 @@ class PType : public PTypeBase bool isIntCompatible() const { return !!(Flags & TYPE_IntCompatible); } bool isFloat() const { return !!(Flags & TYPE_Float); } bool isPointer() const { return !!(Flags & TYPE_Pointer); } - bool isRealPointer() const { return (Flags & (TYPE_Pointer|TYPE_ClassPointer)) == TYPE_Pointer; } // This excludes class pointers which use their PointedType differently + bool isRealPointer() const { return (Flags & (TYPE_Pointer | TYPE_ClassPointer | TYPE_FunctionPointer)) == TYPE_Pointer; } // This excludes class and function pointers which use their PointedType differently bool isObjectPointer() const { return !!(Flags & TYPE_ObjectPointer); } bool isClassPointer() const { return !!(Flags & TYPE_ClassPointer); } + bool isFunctionPointer() const { return !!(Flags & TYPE_FunctionPointer); } bool isEnum() const { return TypeTableType == NAME_Enum; } bool isArray() const { return !!(Flags & TYPE_Array); } bool isStaticArray() const { return TypeTableType == NAME_StaticArray; } @@ -210,6 +216,7 @@ class PType : public PTypeBase PContainerType *toContainer() { return isContainer() ? (PContainerType*)this : nullptr; } PPointer *toPointer() { return isPointer() ? (PPointer*)this : nullptr; } static PClassPointer *toClassPointer(PType *t) { return t && t->isClassPointer() ? (PClassPointer*)t : nullptr; } + static PFunctionPointer *toFunctionPointer(PType *t) { return t && t->isFunctionPointer() ? (PFunctionPointer*)t : nullptr; } static PClassType *toClass(PType *t) { return t && t->isClass() ? (PClassType*)t : nullptr; } }; @@ -379,6 +386,15 @@ class PTextureID : public PInt bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; }; +class PTranslationID : public PInt +{ +public: + PTranslationID(); + + void WriteValue(FSerializer& ar, const char* key, const void* addr) const override; + bool ReadValue(FSerializer& ar, const char* key, void* addr) const override; +}; + class PColor : public PInt { public: @@ -442,7 +458,7 @@ class PObjectPointer : public PPointer void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; - void SetPointer(void *base, unsigned offset, TArray *special = NULL) override; + void SetPointer(void *base, unsigned offset, TArray> *special = NULL) override; PClass *PointedClass() const; }; @@ -458,7 +474,7 @@ class PClassPointer : public PPointer void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; - void SetPointer(void *base, unsigned offset, TArray *special = NULL) override; + void SetPointer(void *base, unsigned offset, TArray> *special = NULL) override; bool IsMatch(intptr_t id1, intptr_t id2) const override; void GetTypeIDs(intptr_t &id1, intptr_t &id2) const override; }; @@ -490,9 +506,9 @@ class PArray : public PCompoundType bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *special) override; - void SetPointer(void *base, unsigned offset, TArray *special) override; - void SetPointerArray(void *base, unsigned offset, TArray *ptrofs = NULL) override; - void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs = NULL) override; + void SetPointer(void *base, unsigned offset, TArray> *special) override; + void SetPointerArray(void *base, unsigned offset, TArray> *ptrofs = NULL) override; + void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs = NULL) override; }; class PStaticArray : public PArray @@ -522,7 +538,7 @@ class PDynArray : public PCompoundType void SetDefaultValue(void *base, unsigned offset, TArray *specials) override; void InitializeValue(void *addr, const void *def) const override; void DestroyValue(void *addr) const override; - void SetPointerArray(void *base, unsigned offset, TArray *ptrofs = NULL) override; + void SetPointerArray(void *base, unsigned offset, TArray> *ptrofs = NULL) override; }; class PMap : public PCompoundType @@ -566,7 +582,7 @@ class PMap : public PCompoundType void SetDefaultValue(void *base, unsigned offset, TArray *specials) override; void InitializeValue(void *addr, const void *def) const override; void DestroyValue(void *addr) const override; - void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs) override; + void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs) override; }; @@ -595,6 +611,33 @@ class PMapIterator : public PCompoundType void DestroyValue(void *addr) const override; }; +class PFunctionPointer : public PPointer +{ +public: + //PointedType = PPrototype or TypeVoid + PFunctionPointer(PPrototype * proto, TArray &&argflags, int scope); + + static FString GenerateNameForError(const PFunction * from); + + TArray ArgFlags; + int Scope; + + PFunction *FakeFunction; // used for type checking in FxFunctionCall + + void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; + bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; + + + struct FlagsAndScope + { // used for IsMatch's id2 + TArray * ArgFlags; + int Scope; + }; + + bool IsMatch(intptr_t id1, intptr_t id2) const override; + void GetTypeIDs(intptr_t &id1, intptr_t &id2) const override; //NOT SUPPORTED +}; + class PStruct : public PContainerType { public: @@ -613,9 +656,9 @@ class PStruct : public PContainerType void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *specials) override; - void SetPointer(void *base, unsigned offset, TArray *specials) override; - void SetPointerArray(void *base, unsigned offset, TArray *special) override; - void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs) override; + void SetPointer(void *base, unsigned offset, TArray> *specials) override; + void SetPointerArray(void *base, unsigned offset, TArray> *special) override; + void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs) override; }; class PPrototype : public PCompoundType @@ -657,6 +700,7 @@ PMapIterator *NewMapIterator(PType *keytype, PType *valuetype); PArray *NewArray(PType *type, unsigned int count); PStaticArray *NewStaticArray(PType *type); PDynArray *NewDynArray(PType *type); +PFunctionPointer *NewFunctionPointer(PPrototype * proto, TArray && argflags, int scope); PPointer *NewPointer(PType *type, bool isconst = false); PPointer *NewPointer(PClass *type, bool isconst = false); PClassPointer *NewClassPointer(PClass *restrict); @@ -680,6 +724,7 @@ extern PName *TypeName; extern PSound *TypeSound; extern PColor *TypeColor; extern PTextureID *TypeTextureID; +extern PTranslationID* TypeTranslationID; extern PSpriteID *TypeSpriteID; extern PStruct* TypeVector2; extern PStruct* TypeVector3; @@ -697,6 +742,9 @@ extern PPointer *TypeFont; extern PStateLabel *TypeStateLabel; extern PPointer *TypeNullPtr; extern PPointer *TypeVoidPtr; +extern PPointer* TypeRawFunction; +extern PPointer* TypeVMFunction; + inline FString &DObject::StringVar(FName field) { diff --git a/src/common/scripting/core/vmdisasm.cpp b/src/common/scripting/core/vmdisasm.cpp index 433a2fd1ab..09524d3b58 100644 --- a/src/common/scripting/core/vmdisasm.cpp +++ b/src/common/scripting/core/vmdisasm.cpp @@ -46,6 +46,9 @@ #define LKP MODE_AP | MODE_BCJOINT | MODE_BCKP #define LFP MODE_AP | MODE_BUNUSED | MODE_CUNUSED + +#define RP MODE_AP | MODE_BUNUSED | MODE_CUNUSED + #define RIRPKI MODE_AI | MODE_BP | MODE_CKI #define RIRPRI MODE_AI | MODE_BP | MODE_CI #define RFRPKI MODE_AF | MODE_BP | MODE_CKI @@ -528,7 +531,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction } else if (code[i].op == OP_CALL_K && callfunc) { - printf_wrapper(out, " [%s]\n", callfunc->PrintableName.GetChars()); + printf_wrapper(out, " [%s]\n", callfunc->PrintableName); } else { diff --git a/src/common/scripting/frontend/ast.cpp b/src/common/scripting/frontend/ast.cpp index 50e1c2e9f1..ba91077af0 100644 --- a/src/common/scripting/frontend/ast.cpp +++ b/src/common/scripting/frontend/ast.cpp @@ -521,6 +521,26 @@ static void PrintDynArrayType(FLispString &out, const ZCC_TreeNode *node) out.Close(); } +static void PrintFuncPtrParamDecl(FLispString &out, const ZCC_TreeNode *node) +{ + ZCC_FuncPtrParamDecl *dnode = (ZCC_FuncPtrParamDecl *)node; + out.Break(); + out.Open("func-ptr-param-decl"); + PrintNodes(out, dnode->Type); + out.AddHex(dnode->Flags); + out.Close(); +} + +static void PrintFuncPtrType(FLispString &out, const ZCC_TreeNode *node){ + ZCC_FuncPtrType *dnode = (ZCC_FuncPtrType *)node; + out.Break(); + out.Open("func-ptr-type"); + PrintNodes(out, dnode->RetType); + PrintNodes(out, dnode->Params); + out.AddHex(dnode->Scope); + out.Close(); +} + static void PrintClassType(FLispString &out, const ZCC_TreeNode *node) { ZCC_ClassType *tnode = (ZCC_ClassType *)node; @@ -628,6 +648,16 @@ static void PrintExprClassCast(FLispString &out, const ZCC_TreeNode *node) out.Close(); } +static void PrintExprFunctionPtrCast(FLispString &out, const ZCC_TreeNode *node) +{ + ZCC_FunctionPtrCast *enode = (ZCC_FunctionPtrCast *)node; + assert(enode->Operation == PEX_FunctionPtrCast); + out.Open("expr-func-ptr-cast"); + PrintNodes(out, enode->PtrType, false); + PrintNodes(out, enode->Expr, false); + out.Close(); +} + static void PrintStaticArray(FLispString &out, const ZCC_TreeNode *node) { ZCC_StaticArrayStatement *enode = (ZCC_StaticArrayStatement *)node; @@ -953,6 +983,53 @@ static void PrintArrayIterationStmt(FLispString &out, const ZCC_TreeNode *node) out.Close(); } +static void PrintTwoArgIterationStmt(FLispString &out, const ZCC_TreeNode *node) +{ + auto inode = (ZCC_TwoArgIterationStmt *)node; + out.Break(); + out.Open("map-iteration-stmt"); + PrintVarName(out, inode->ItKey); + out.Break(); + PrintVarName(out, inode->ItValue); + out.Break(); + PrintNodes(out, inode->ItMap); + out.Break(); + PrintNodes(out, inode->LoopStatement); + out.Close(); +} + +static void PrintThreeArgIterationStmt(FLispString &out, const ZCC_TreeNode *node) +{ + auto inode = (ZCC_ThreeArgIterationStmt *)node; + out.Break(); + out.Open("block-iteration-stmt"); + PrintVarName(out, inode->ItVar); + out.Break(); + PrintVarName(out, inode->ItPos); + out.Break(); + PrintVarName(out, inode->ItFlags); + out.Break(); + PrintNodes(out, inode->ItBlock); + out.Break(); + PrintNodes(out, inode->LoopStatement); + out.Close(); +} + +static void PrintTypedIterationStmt(FLispString &out, const ZCC_TreeNode *node) +{ + auto inode = (ZCC_TypedIterationStmt *)node; + out.Break(); + out.Open("cast-iteration-stmt"); + PrintVarName(out, inode->ItType); + out.Break(); + PrintVarName(out, inode->ItVar); + out.Break(); + PrintNodes(out, inode->ItExpr); + out.Break(); + PrintNodes(out, inode->LoopStatement); + out.Close(); +} + static const NodePrinterFunc TreeNodePrinter[] = { PrintIdentifier, @@ -976,6 +1053,8 @@ static const NodePrinterFunc TreeNodePrinter[] = PrintMapType, PrintMapIteratorType, PrintDynArrayType, + PrintFuncPtrParamDecl, + PrintFuncPtrType, PrintClassType, PrintExpression, PrintExprID, @@ -1011,12 +1090,16 @@ static const NodePrinterFunc TreeNodePrinter[] = PrintVectorInitializer, PrintDeclFlags, PrintExprClassCast, + PrintExprFunctionPtrCast, PrintStaticArrayState, PrintProperty, PrintFlagDef, PrintMixinDef, PrintMixinStmt, PrintArrayIterationStmt, + PrintTwoArgIterationStmt, + PrintThreeArgIterationStmt, + PrintTypedIterationStmt, }; FString ZCC_PrintAST(const ZCC_TreeNode *root) diff --git a/src/common/scripting/frontend/zcc-parse.lemon b/src/common/scripting/frontend/zcc-parse.lemon index 1a9146f372..199771949d 100644 --- a/src/common/scripting/frontend/zcc-parse.lemon +++ b/src/common/scripting/frontend/zcc-parse.lemon @@ -78,6 +78,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) struct ClassFlagsBlock { VM_UWORD Flags; ZCC_Identifier *Replaces; + ZCC_Identifier *Sealed; VersionInfo Version; }; @@ -242,6 +243,7 @@ class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C). head->ParentName = B; head->Flags = C.Flags; head->Replaces = C.Replaces; + head->Sealed = C.Sealed; head->Version = C.Version; head->Type = nullptr; head->Symbol = nullptr; @@ -253,13 +255,15 @@ class_ancestry(X) ::= . { X = NULL; } class_ancestry(X) ::= COLON dottable_id(A). { X = A; /*X-overwrites-A*/ } %type class_flags{ClassFlagsBlock} -class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; X.Version = {0,0}; } -class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | ZCC_Abstract; X.Replaces = A.Replaces; } -class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Replaces = A.Replaces; } -class_flags(X) ::= class_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; X.Replaces = A.Replaces; } -class_flags(X) ::= class_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; X.Replaces = A.Replaces; } -class_flags(X) ::= class_flags(A) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; } -class_flags(X) ::= class_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Replaces = A.Replaces; X.Version = C.String->GetChars(); } +class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; X.Version = {0,0}; X.Sealed = NULL; } +class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | ZCC_Abstract; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed; } +class_flags(X) ::= class_flags(A) FINAL. { X.Flags = A.Flags | ZCC_Final; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed;} +class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed; } +class_flags(X) ::= class_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed; } +class_flags(X) ::= class_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed; } +class_flags(X) ::= class_flags(A) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; X.Version = A.Version; X.Sealed = A.Sealed; } +class_flags(X) ::= class_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Replaces = A.Replaces; X.Version = C.String->GetChars(); X.Sealed = A.Sealed; } +class_flags(X) ::= class_flags(A) SEALED LPAREN states_opt(B) RPAREN. { X.Flags = A.Flags | ZCC_Sealed; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = B; } /*----- Dottable Identifier -----*/ // This can be either a single identifier or two identifiers connected by a . @@ -272,6 +276,13 @@ dottable_id(X) ::= IDENTIFIER(A). id->Id = A.Name(); X = id; } +// this is needed for defining properties named 'action'. +dottable_id(X) ::= ACTION(A). +{ + NEW_AST_NODE(Identifier,id,A); + id->Id = NAME_Action; + X = id; +} dottable_id(X) ::= dottable_id(A) DOT IDENTIFIER(B). { NEW_AST_NODE(Identifier,id2,A); @@ -367,6 +378,15 @@ flag_def(X) ::= FLAGDEF(T) IDENTIFIER(A) COLON IDENTIFIER(B) COMMA INTCONST(C) S X = def; } +flag_def(X) ::= FLAGDEF(T) INTERNAL IDENTIFIER(A) COLON IDENTIFIER(B) COMMA INTCONST(C) SEMICOLON. +{ + NEW_AST_NODE(FlagDef,def,T); + def->NodeName = A.Name(); + def->RefName = B.Name(); + def->BitValue = C.Int | 0x10000; + X = def; +} + identifier_list(X) ::= IDENTIFIER(A). { @@ -426,6 +446,7 @@ struct_member(X) ::= declarator(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= staticarray_statement(A). { X = A; /*X-overwrites-A*/ } +struct_member(X) ::= flag_def(A). { X = A; /*X-overwrites-A*/ } /*----- Constant Definition ------*/ /* Like UnrealScript, a constant's type is implied by its value's type. */ @@ -967,6 +988,71 @@ aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray */ X = arr; } +aggregate_type(X) ::= func_ptr_type(A). { X = A; /*X-overwrites-A*/ } + +%type func_ptr_type {ZCC_FuncPtrType *} +%type func_ptr_params {ZCC_FuncPtrParamDecl *} +%type func_ptr_param_list {ZCC_FuncPtrParamDecl *} +%type func_ptr_param {ZCC_FuncPtrParamDecl *} + +//fn_ptr_flag(X) ::= . { X.Int = 0; } //implicit scope not allowed +fn_ptr_flag(X) ::= UI. { X.Int = ZCC_UIFlag; } +fn_ptr_flag(X) ::= PLAY. { X.Int = ZCC_Play; } +fn_ptr_flag(X) ::= CLEARSCOPE. { X.Int = ZCC_ClearScope; } +//fn_ptr_flag(X) ::= VIRTUALSCOPE. { X.Int = ZCC_VirtualScope; } //virtual scope not allowed + + +func_ptr_type(X) ::= FNTYPE(T) LT fn_ptr_flag(F) type_list_or_void(A) LPAREN func_ptr_params(B) RPAREN GT. /* Function<...(...)> */ +{ + NEW_AST_NODE(FuncPtrType,fn_ptr,T); + fn_ptr->RetType = A; + fn_ptr->Params = B; + fn_ptr->Scope = F.Int; + X = fn_ptr; +} + +func_ptr_type(X) ::= FNTYPE(T) LT VOID GT. /* Function */ +{ + NEW_AST_NODE(FuncPtrType,fn_ptr,T); + fn_ptr->RetType = nullptr; + fn_ptr->Params = nullptr; + fn_ptr->Scope = -1; + X = fn_ptr; +} + +func_ptr_params(X) ::= . /* empty */ { X = NULL; } +func_ptr_params(X) ::= VOID. { X = NULL; } +func_ptr_params(X) ::= func_ptr_param_list(X). + +// varargs function pointers not currently supported +//func_ptr_params(X) ::= func_ptr_param_list(A) COMMA ELLIPSIS. +//{ +// NEW_AST_NODE(FuncPtrParamDecl,parm,stat->sc->GetMessageLine()); +// parm->Type = nullptr; +// parm->Flags = 0; +// X = A; /*X-overwrites-A*/ +// AppendTreeNodeSibling(X, parm); +//} + +func_ptr_param_list(X) ::= func_ptr_param(X). +func_ptr_param_list(X) ::= func_ptr_param_list(A) COMMA func_ptr_param(B). { X = A; /*X-overwrites-A*/ AppendTreeNodeSibling(X, B); } + +func_ptr_param(X) ::= func_param_flags(A) type(B). +{ + NEW_AST_NODE(FuncPtrParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc); + parm->Type = B; + parm->Flags = A.Int; + X = parm; +} + +func_ptr_param(X) ::= func_param_flags(A) type(B) AND. +{ + NEW_AST_NODE(FuncPtrParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc); + parm->Type = B; + parm->Flags = A.Int | ZCC_Out; + X = parm; +} + aggregate_type(X) ::= CLASS(T) class_restrictor(A). /* class */ { NEW_AST_NODE(ClassType,cls,T); @@ -1278,6 +1364,26 @@ func_param(X) ::= func_param_flags(A) type(B) IDENTIFIER(C) EQ expr(D). X = parm; } +func_param(X) ::= func_param_flags(A) type(B) AND IDENTIFIER(C). +{ + NEW_AST_NODE(FuncParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc); + parm->Type = B; + parm->Name = C.Name(); + parm->Flags = A.Int | ZCC_Out; + parm->Default = nullptr; + X = parm; +} + +func_param(X) ::= func_param_flags(A) type(B) AND IDENTIFIER(C) EQ expr(D). +{ + NEW_AST_NODE(FuncParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc); + parm->Type = B; + parm->Name = C.Name(); + parm->Flags = A.Int | ZCC_Out; + parm->Default = D; + X = parm; +} + func_param_flags(X) ::= . { X.Int = 0; X.SourceLoc = 0; } func_param_flags(X) ::= func_param_flags(A) IN(T). { X.Int = A.Int | ZCC_In; X.SourceLoc = T.SourceLoc; } func_param_flags(X) ::= func_param_flags(A) OUT(T). { X.Int = A.Int | ZCC_Out; X.SourceLoc = T.SourceLoc; } @@ -1367,6 +1473,17 @@ primary(X) ::= LPAREN CLASS LT IDENTIFIER(A) GT RPAREN LPAREN func_expr_list(B) expr->Parameters = B; X = expr; } + +primary(X) ::= LPAREN func_ptr_type(A) RPAREN LPAREN expr(B) RPAREN. [DOT] // function pointer type cast +{ + NEW_AST_NODE(FunctionPtrCast, expr, A); + expr->Operation = PEX_FunctionPtrCast; + A->ArraySize = NULL; + expr->PtrType = A; + expr->Expr = B; + X = expr; +} + primary(X) ::= primary(A) LBRACKET expr(B) RBRACKET. [DOT] // Array access { NEW_AST_NODE(ExprBinary, expr, B); @@ -1376,6 +1493,7 @@ primary(X) ::= primary(A) LBRACKET expr(B) RBRACKET. [DOT] // Array access expr->Right = B; X = expr; } + primary(X) ::= primary(A) DOT IDENTIFIER(B). // Member access { NEW_AST_NODE(ExprMemberAccess, expr, B); @@ -1838,6 +1956,9 @@ statement(X) ::= expression_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ statement(X) ::= selection_statement(X). statement(X) ::= iteration_statement(X). statement(X) ::= array_iteration_statement(X). +statement(X) ::= two_arg_iteration_statement(X). +statement(X) ::= three_arg_iteration_statement(X). +statement(X) ::= typed_iteration_statement(X). statement(X) ::= jump_statement(X). statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } statement(X) ::= assign_decl_statement(A) SEMICOLON.{ X = A; /*X-overwrites-A*/ } @@ -2007,6 +2128,43 @@ array_iteration_statement(X) ::= FOREACH(T) LPAREN variable_name(IN) COLON expr( X = iter; } +%type two_arg_iteration_statement{ZCC_Statement *} + +two_arg_iteration_statement(X) ::= FOREACH(T) LPAREN variable_name(KEY) COMMA variable_name(VAL) COLON expr(EX) RPAREN statement(ST). +{ + NEW_AST_NODE(TwoArgIterationStmt, iter, T); + iter->ItKey = KEY; + iter->ItValue = VAL; + iter->ItMap = EX; + iter->LoopStatement = ST; + X = iter; +} + +%type three_arg_iteration_statement{ZCC_Statement *} + +three_arg_iteration_statement(X) ::= FOREACH(T) LPAREN variable_name(VAR) COMMA variable_name(POS) COMMA variable_name(FLAGS) COLON expr(EX) RPAREN statement(ST). +{ + NEW_AST_NODE(ThreeArgIterationStmt, iter, T); + iter->ItVar = VAR; + iter->ItPos = POS; + iter->ItFlags = FLAGS; + iter->ItBlock = EX; + iter->LoopStatement = ST; + X = iter; +} + +%type typed_iteration_statement{ZCC_Statement *} + +typed_iteration_statement(X) ::= FOREACH(T) LPAREN variable_name(TYPE) variable_name(VAR) COLON expr(EX) RPAREN statement(ST). +{ + NEW_AST_NODE(TypedIterationStmt, iter, T); + iter->ItType = TYPE; + iter->ItVar = VAR; + iter->ItExpr = EX; + iter->LoopStatement = ST; + X = iter; +} + while_or_until(X) ::= WHILE(T). { X.Int = ZCC_WHILE; diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index ffba4c301d..d109717a32 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -43,6 +43,11 @@ FSharedStringArena VMStringConstants; +static bool ShouldWrapPointer(PType * type) +{ + return ((type->isStruct() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) || type->isDynArray() || type->isMap() || type->isMapIterator()); +} + int GetIntConst(FxExpression *ex, FCompileContext &ctx) { ex = new FxIntCast(ex, false); @@ -57,6 +62,13 @@ double GetFloatConst(FxExpression *ex, FCompileContext &ctx) return ex ? static_cast(ex)->GetValue().GetFloat() : 0; } +VMFunction* GetFuncConst(FxExpression* ex, FCompileContext& ctx) +{ + ex = new FxTypeCast(ex, TypeVMFunction, false); + ex = ex->Resolve(ctx); + return static_cast(ex ? static_cast(ex)->GetValue().GetPointer() : nullptr); +} + const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx) { ex = new FxStringCast(ex); @@ -452,6 +464,11 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC } break; + case AST_FlagDef: + cls->FlagDefs.Push(static_cast(node)); + break; + + default: assert(0 && "Unhandled AST node type"); break; @@ -662,7 +679,7 @@ void ZCCCompiler::MessageV(ZCC_TreeNode *node, const char *txtcolor, const char composed.Format("%s%s, line %d: ", txtcolor, node->SourceName->GetChars(), node->SourceLoc); composed.VAppendFormat(msg, argptr); composed += '\n'; - PrintString(PRINT_HIGH, composed); + PrintString(PRINT_HIGH, composed.GetChars()); } //========================================================================== @@ -792,8 +809,14 @@ void ZCCCompiler::CreateClassTypes() PClass *parent; auto ParentName = c->cls->ParentName; - if (ParentName != nullptr && ParentName->SiblingNext == ParentName) parent = PClass::FindClass(ParentName->Id); - else if (ParentName == nullptr) parent = RUNTIME_CLASS(DObject); + if (ParentName != nullptr && ParentName->SiblingNext == ParentName) + { + parent = PClass::FindClass(ParentName->Id); + } + else if (ParentName == nullptr) + { + parent = RUNTIME_CLASS(DObject); + } else { // The parent is a dotted name which the type system currently does not handle. @@ -813,6 +836,15 @@ void ZCCCompiler::CreateClassTypes() if (parent != nullptr && (parent->VMType != nullptr || c->NodeName() == NAME_Object)) { + if(parent->bFinal) + { + Error(c->cls, "Class '%s' cannot extend final class '%s'", FName(c->NodeName()).GetChars(), parent->TypeName.GetChars()); + } + else if(parent->bSealed && !parent->SealedRestriction.Contains(c->NodeName())) + { + Error(c->cls, "Class '%s' cannot extend sealed class '%s'", FName(c->NodeName()).GetChars(), parent->TypeName.GetChars()); + } + // The parent exists, we may create a type for this class if (c->cls->Flags & ZCC_Native) { @@ -874,6 +906,25 @@ void ZCCCompiler::CreateClassTypes() { c->Type()->mVersion = c->cls->Version; } + + + if (c->cls->Flags & ZCC_Final) + { + c->ClassType()->bFinal = true; + } + + if (c->cls->Flags & ZCC_Sealed) + { + PClass * ccls = c->ClassType(); + ccls->bSealed = true; + ZCC_Identifier * it = c->cls->Sealed; + if(it) do + { + ccls->SealedRestriction.Push(FName(it->Id)); + it = (ZCC_Identifier*) it->SiblingNext; + } + while(it != c->cls->Sealed); + } // if (mVersion >= MakeVersion(2, 4, 0)) { @@ -1840,6 +1891,12 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n retval = TypeTextureID; break; + case NAME_TranslationID: + retval = TypeTranslationID; + break; + + + default: retval = ResolveUserType(btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false); break; @@ -1866,19 +1923,17 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n auto keytype = DetermineType(outertype, field, name, mtype->KeyType, false, false); auto valuetype = DetermineType(outertype, field, name, mtype->ValueType, false, false); - if (keytype->GetRegType() == REGT_INT) + if (keytype->GetRegType() != REGT_STRING && !(keytype->GetRegType() == REGT_INT && keytype->Size == 4)) { - if (keytype->Size != 4) + if(name != NAME_None) + { + Error(field, "%s : Map<%s , ...> not implemented yet", name.GetChars(), keytype->DescriptiveName()); + } + else { Error(field, "Map<%s , ...> not implemented yet", keytype->DescriptiveName()); - break; } } - else if (keytype->GetRegType() != REGT_STRING) - { - Error(field, "Map<%s , ...> not implemented yet", keytype->DescriptiveName()); - break; - } switch(valuetype->GetRegType()) { @@ -1888,14 +1943,20 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n case REGT_POINTER: if (valuetype->GetRegCount() > 1) { - Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName()); + default: + if(name != NAME_None) + { + Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName()); + } + else + { + Error(field, "Base type for map value types must be integral, but got %s", valuetype->DescriptiveName()); + } break; } retval = NewMap(keytype, valuetype); break; - default: - Error(field, "%s: Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName()); } break; @@ -1913,17 +1974,17 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n auto keytype = DetermineType(outertype, field, name, mtype->KeyType, false, false); auto valuetype = DetermineType(outertype, field, name, mtype->ValueType, false, false); - if (keytype->GetRegType() == REGT_INT) + if (keytype->GetRegType() != REGT_STRING && !(keytype->GetRegType() == REGT_INT && keytype->Size == 4)) { - if (keytype->Size != 4) + if(name != NAME_None) + { + Error(field, "%s : MapIterator<%s , ...> not implemented yet", name.GetChars(), keytype->DescriptiveName()); + } + else { Error(field, "MapIterator<%s , ...> not implemented yet", keytype->DescriptiveName()); } } - else if (keytype->GetRegType() != REGT_STRING) - { - Error(field, "MapIterator<%s , ...> not implemented yet", keytype->DescriptiveName()); - } switch(valuetype->GetRegType()) { @@ -1933,13 +1994,19 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n case REGT_POINTER: if (valuetype->GetRegCount() > 1) { - Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName()); + default: + if(name != NAME_None) + { + Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName()); + } + else + { + Error(field, "Base type for map value types must be integral, but got %s", valuetype->DescriptiveName()); + } break; } retval = NewMapIterator(keytype, valuetype); break; - default: - Error(field, "%s: Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName()); } break; } @@ -1968,6 +2035,61 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n } break; } + case AST_FuncPtrType: + { + auto fn = static_cast(ztype); + + if(fn->Scope == -1) + { // Function + retval = NewFunctionPointer(nullptr, {}, -1); + } + else + { + TArray returns; + TArray args; + TArray argflags; + + if(auto *t = fn->RetType; t != nullptr) do { + returns.Push(DetermineType(outertype, field, name, t, false, false)); + } while( (t = (ZCC_Type *)t->SiblingNext) != fn->RetType); + + if(auto *t = fn->Params; t != nullptr) do { + PType * tt = DetermineType(outertype, field, name, t->Type, false, false); + int flags = 0; + + if (ShouldWrapPointer(tt)) + { + tt = NewPointer(tt); + flags = VARF_Ref; + } + + args.Push(tt); + argflags.Push(t->Flags == ZCC_Out ? VARF_Out|flags : flags); + } while( (t = (ZCC_FuncPtrParamDecl *) t->SiblingNext) != fn->Params); + + auto proto = NewPrototype(returns,args); + switch(fn->Scope) + { // only play/ui/clearscope functions are allowed, no data or virtual scope functions + case ZCC_Play: + fn->Scope = FScopeBarrier::Side_Play; + break; + case ZCC_UIFlag: + fn->Scope = FScopeBarrier::Side_UI; + break; + case ZCC_ClearScope: + fn->Scope = FScopeBarrier::Side_PlainData; + break; + case 0: + fn->Scope = -1; + break; + default: + Error(field, "Invalid Scope for Function Pointer"); + break; + } + retval = NewFunctionPointer(proto, std::move(argflags), fn->Scope); + } + break; + } case AST_ClassType: { auto ctype = static_cast(ztype); @@ -2244,6 +2366,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool Error(f, "The return type of a function cannot be a dynamic array"); break; } + else if (type->isMap()) + { + Error(f, "The return type of a function cannot be a map"); + break; + } else if (type == TypeFVector2) { type = TypeVector2; @@ -2437,7 +2564,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); int flags = 0; - if ((type->isStruct() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) || type->isDynArray() || type->isMap() || type->isMapIterator()) + if (ShouldWrapPointer(type)) { // Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly. type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/); @@ -2651,7 +2778,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool // [ZZ] unspecified virtual function inherits old scope. virtual function scope can't be changed. sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; } - + bool exactReturnType = mVersion < MakeVersion(4, 4); PClass *clstype = forclass? static_cast(c->Type())->Descriptor : nullptr; if (varflags & VARF_Virtual) @@ -2672,7 +2799,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool auto parentfunc = clstype->ParentClass? dyn_cast(clstype->ParentClass->VMType->Symbols.FindSymbol(sym->SymbolName, true)) : nullptr; - int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType); + int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType, sym->SymbolName == FName("SpecialBounceHit") && mVersion < MakeVersion(4, 12)); // specifying 'override' is necessary to prevent one of the biggest problem spots with virtual inheritance: Mismatching argument types. if (varflags & VARF_Override) { @@ -2754,7 +2881,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool } else if (forclass) { - int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType); + int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType, sym->SymbolName == FName("SpecialBounceHit") && mVersion < MakeVersion(4, 12)); if (virtindex != -1) { Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); @@ -2798,7 +2925,7 @@ void ZCCCompiler::InitFunctions() { if (v->VarFlags & VARF_Abstract) { - Error(c->cls, "Non-abstract class %s must override abstract function %s", c->Type()->TypeName.GetChars(), v->PrintableName.GetChars()); + Error(c->cls, "Non-abstract class %s must override abstract function %s", c->Type()->TypeName.GetChars(), v->PrintableName); } } } @@ -2886,12 +3013,12 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) { case AST_ExprID: // The function name is a simple identifier. - return new FxFunctionCall(static_cast(fcall->Function)->Identifier, NAME_None, ConvertNodeList(args, fcall->Parameters), *ast); + return new FxFunctionCall(static_cast(fcall->Function)->Identifier, NAME_None, std::move(ConvertNodeList(args, fcall->Parameters)), *ast); case AST_ExprMemberAccess: { auto ema = static_cast(fcall->Function); - return new FxMemberFunctionCall(ConvertNode(ema->Left, true), ema->Right, ConvertNodeList(args, fcall->Parameters), *ast); + return new FxMemberFunctionCall(ConvertNode(ema->Left, true), ema->Right, std::move(ConvertNodeList(args, fcall->Parameters)), *ast); } case AST_ExprBinary: @@ -2901,7 +3028,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) auto binary = static_cast(fcall->Function); if (binary->Left->NodeType == AST_ExprID && binary->Right->NodeType == AST_ExprID) { - return new FxFunctionCall(static_cast(binary->Left)->Identifier, static_cast(binary->Right)->Identifier, ConvertNodeList(args, fcall->Parameters), *ast); + return new FxFunctionCall(static_cast(binary->Left)->Identifier, static_cast(binary->Right)->Identifier, std::move(ConvertNodeList(args, fcall->Parameters)), *ast); } } // fall through if this isn't an array access node. @@ -2931,6 +3058,17 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) return new FxClassPtrCast(cls, ConvertNode(cc->Parameters)); } + case AST_FunctionPtrCast: + { + auto cast = static_cast(ast); + + auto type = DetermineType(ConvertClass, cast, NAME_None, cast->PtrType, false, false); + assert(type->isFunctionPointer()); + auto ptrType = static_cast(type); + + return new FxFunctionPtrCast(ptrType, ConvertNode(cast->Expr)); + } + case AST_StaticArrayStatement: { auto sas = static_cast(ast); @@ -3264,10 +3402,45 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) auto iter = static_cast(ast); auto var = iter->ItName->Name; FxExpression* const itArray = ConvertNode(iter->ItArray); - FxExpression* const itArray2 = ConvertNode(iter->ItArray); // the handler needs two copies of this - here's the easiest place to create them. + FxExpression* const itArray2 = ConvertNode(iter->ItArray); + FxExpression* const itArray3 = ConvertNode(iter->ItArray); + FxExpression* const itArray4 = ConvertNode(iter->ItArray); // the handler needs copies of this - here's the easiest place to create them. + FxExpression* const body = ConvertImplicitScopeNode(ast, iter->LoopStatement); + return new FxForEachLoop(iter->ItName->Name, itArray, itArray2, itArray3, itArray4, body, *ast); + } + + case AST_TwoArgIterationStmt: + { + auto iter = static_cast(ast); + auto key = iter->ItKey->Name; + auto var = iter->ItValue->Name; + FxExpression* const itMap = ConvertNode(iter->ItMap); + FxExpression* const itMap2 = ConvertNode(iter->ItMap); + FxExpression* const itMap3 = ConvertNode(iter->ItMap); + FxExpression* const itMap4 = ConvertNode(iter->ItMap); + FxExpression* const body = ConvertImplicitScopeNode(ast, iter->LoopStatement); + return new FxTwoArgForEachLoop(key, var, itMap, itMap2, itMap3, itMap4, body, *ast); + } + + case AST_ThreeArgIterationStmt: + { + auto iter = static_cast(ast); + auto var = iter->ItVar->Name; + auto pos = iter->ItPos->Name; + auto flags = iter->ItFlags->Name; + FxExpression* const itBlock = ConvertNode(iter->ItBlock); FxExpression* const body = ConvertImplicitScopeNode(ast, iter->LoopStatement); - return new FxForEachLoop(iter->ItName->Name, itArray, itArray2, body, *ast); + return new FxThreeArgForEachLoop(var, pos, flags, itBlock, body, *ast); + } + case AST_TypedIterationStmt: + { + auto iter = static_cast(ast); + auto cls = iter->ItType->Name; + auto var = iter->ItVar->Name; + FxExpression* const itExpr = ConvertNode(iter->ItExpr); + FxExpression* const body = ConvertImplicitScopeNode(ast, iter->LoopStatement); + return new FxTypedForEachLoop(cls, var, itExpr, body, *ast); } case AST_IterationStmt: diff --git a/src/common/scripting/frontend/zcc_compile.h b/src/common/scripting/frontend/zcc_compile.h index b6f32018d2..19e9f8ff07 100644 --- a/src/common/scripting/frontend/zcc_compile.h +++ b/src/common/scripting/frontend/zcc_compile.h @@ -6,7 +6,6 @@ struct Baggage; struct FPropertyInfo; -class AActor; class FxExpression; typedef TDeletingArray FArgumentList; @@ -23,6 +22,7 @@ struct ZCC_StructWork TArray Fields; TArray Functions; TArray Arrays; + TArray FlagDefs; ZCC_StructWork() { diff --git a/src/common/scripting/frontend/zcc_exprlist.h b/src/common/scripting/frontend/zcc_exprlist.h index faf6af6a43..f05758379a 100644 --- a/src/common/scripting/frontend/zcc_exprlist.h +++ b/src/common/scripting/frontend/zcc_exprlist.h @@ -9,6 +9,7 @@ xx(FuncCall, '(') xx(ArrayAccess, TK_Array) xx(MemberAccess, '.') xx(ClassCast, TK_Class) +xx(FunctionPtrCast, TK_FunctionType) xx(TypeRef, TK_Class) xx(Vector, TK_Vector2) diff --git a/src/common/scripting/frontend/zcc_parser.cpp b/src/common/scripting/frontend/zcc_parser.cpp index 3fc8db10df..a713f20524 100644 --- a/src/common/scripting/frontend/zcc_parser.cpp +++ b/src/common/scripting/frontend/zcc_parser.cpp @@ -52,7 +52,7 @@ static FString ResolveIncludePath(const FString &path,const FString &lumpname){ auto end = lumpname.LastIndexOf("/"); // find last '/' - // it's a top-level file, if it's a folder being loaded ( /xxx/yyy/:whatever.zs ) end is before than start, or if it's a zip ( xxx.zip/whatever.zs ) end would be -1 + // it's a top-level file, if it's a folder being loaded ( /xxx/yyy/:whatever.zs ) end is before than start, or if it's a zip ( xxx.zip:whatever.zs ) end would be -1 bool topLevelFile = start > end ; FString fullPath = topLevelFile ? FString {} : lumpname.Mid(start + 1, end - start - 1); // get path from lumpname (format 'wad:filepath/filename') @@ -71,9 +71,16 @@ static FString ResolveIncludePath(const FString &path,const FString &lumpname){ { relativePath = relativePath.Mid(3); auto slash_index = fullPath.LastIndexOf("/"); - if (slash_index != -1) { + if (slash_index != -1) + { fullPath = fullPath.Mid(0, slash_index); - } else { + } + else if (fullPath.IsNotEmpty()) + { + fullPath = ""; + } + else + { pathOk = false; break; } @@ -222,6 +229,7 @@ static void InitTokenMap() TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map); TOKENDEF2(TK_MapIterator, ZCC_MAPITERATOR,NAME_MapIterator); TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array); + TOKENDEF2(TK_FunctionType, ZCC_FNTYPE, NAME_Function); TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include); TOKENDEF (TK_Void, ZCC_VOID); TOKENDEF (TK_True, ZCC_TRUE); @@ -232,6 +240,7 @@ static void InitTokenMap() TOKENDEF (TK_Out, ZCC_OUT); TOKENDEF (TK_Super, ZCC_SUPER); TOKENDEF (TK_Null, ZCC_NULLPTR); + TOKENDEF (TK_Sealed, ZCC_SEALED); TOKENDEF ('~', ZCC_TILDE); TOKENDEF ('!', ZCC_BANG); TOKENDEF (TK_SizeOf, ZCC_SIZEOF); @@ -407,8 +416,6 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state) int lumpnum = baselump; auto fileno = fileSystem.GetFileContainer(lumpnum); - FString file = fileSystem.GetFileFullPath(lumpnum); - state.FileNo = fileno; if (TokenMap.CountUsed() == 0) @@ -473,7 +480,7 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state) ParseSingleFile(&sc, nullptr, lumpnum, parser, state); for (unsigned i = 0; i < Includes.Size(); i++) { - lumpnum = fileSystem.CheckNumForFullName(Includes[i], true); + lumpnum = fileSystem.CheckNumForFullName(Includes[i].GetChars(), true); if (lumpnum == -1) { IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars()); @@ -503,7 +510,7 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state) // If the parser fails, there is no point starting the compiler, because it'd only flood the output with endless errors. if (FScriptPosition::ErrorCounter > 0) { - I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, fileSystem.GetFileFullPath(baselump).GetChars()); + I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, fileSystem.GetFileFullPath(baselump).c_str()); } #ifndef NDEBUG @@ -517,10 +524,10 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state) if (Args->CheckParm("-dumpast")) { FString ast = ZCC_PrintAST(state.TopNode); - FString filename = fileSystem.GetFileFullPath(baselump); + FString filename = fileSystem.GetFileFullPath(baselump).c_str(); filename.ReplaceChars(":\\/?|", '.'); filename << ".ast"; - FileWriter *ff = FileWriter::Open(filename); + FileWriter *ff = FileWriter::Open(filename.GetChars()); if (ff != NULL) { ff->Write(ast.GetChars(), ast.Len()); @@ -926,6 +933,29 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c break; } + case AST_FuncPtrParamDecl: + { + TreeNodeDeepCopy_Start(FuncPtrParamDecl); + + // ZCC_FuncPtrParamDecl + copy->Type = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList)); + copy->Flags = origCasted->Flags; + + break; + } + + case AST_FuncPtrType: + { + TreeNodeDeepCopy_Start(FuncPtrType); + + // ZCC_FuncPtrType + copy->RetType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->RetType, true, copiedNodesList)); + copy->Params = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Params, true, copiedNodesList)); + copy->Scope = origCasted->Scope; + + break; + } + case AST_ClassType: { TreeNodeDeepCopy_Start(ClassType); @@ -1154,6 +1184,46 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c break; } + case AST_TwoArgIterationStmt: + { + TreeNodeDeepCopy_Start(TwoArgIterationStmt); + + // ZCC_TwoArgIterationStmt + copy->ItKey = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItKey, true, copiedNodesList)); + copy->ItValue = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItValue, true, copiedNodesList)); + copy->LoopStatement = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList)); + copy->ItMap = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItMap, true, copiedNodesList)); + + break; + } + + case AST_ThreeArgIterationStmt: + { + TreeNodeDeepCopy_Start(ThreeArgIterationStmt); + + // ZCC_TwoArgIterationStmt + copy->ItVar = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItVar, true, copiedNodesList)); + copy->ItPos = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItPos, true, copiedNodesList)); + copy->ItFlags = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItFlags, true, copiedNodesList)); + copy->LoopStatement = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList)); + copy->ItBlock = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItBlock, true, copiedNodesList)); + + break; + } + + case AST_TypedIterationStmt: + { + TreeNodeDeepCopy_Start(TypedIterationStmt); + + // ZCC_TwoArgIterationStmt + copy->ItType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItType, true, copiedNodesList)); + copy->ItVar = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItVar, true, copiedNodesList)); + copy->LoopStatement = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList)); + copy->ItExpr = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItExpr, true, copiedNodesList)); + + break; + } + case AST_IfStmt: { TreeNodeDeepCopy_Start(IfStmt); @@ -1372,7 +1442,21 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c break; } + + case AST_FunctionPtrCast: + { + TreeNodeDeepCopy_Start(FunctionPtrCast); + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_FunctionPtrCast + copy->PtrType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->PtrType, true, copiedNodesList)); + copy->Expr = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Expr, true, copiedNodesList)); + + break; + } + case AST_StaticArrayStatement: { TreeNodeDeepCopy_Start(StaticArrayStatement); diff --git a/src/common/scripting/frontend/zcc_parser.h b/src/common/scripting/frontend/zcc_parser.h index 25a60d9ad2..d0b6264da5 100644 --- a/src/common/scripting/frontend/zcc_parser.h +++ b/src/common/scripting/frontend/zcc_parser.h @@ -64,6 +64,7 @@ enum ZCC_VirtualScope = 1 << 20, ZCC_Version = 1 << 21, ZCC_Internal = 1 << 22, + ZCC_Sealed = 1 << 23, }; // Function parameter modifiers @@ -100,6 +101,8 @@ enum EZCCTreeNodeType AST_MapType, AST_MapIteratorType, AST_DynArrayType, + AST_FuncPtrParamDecl, + AST_FuncPtrType, AST_ClassType, AST_Expression, AST_ExprID, @@ -135,12 +138,16 @@ enum EZCCTreeNodeType AST_VectorValue, AST_DeclFlags, AST_ClassCast, + AST_FunctionPtrCast, AST_StaticArrayStatement, AST_Property, AST_FlagDef, AST_MixinDef, AST_MixinStmt, AST_ArrayIterationStmt, + AST_TwoArgIterationStmt, + AST_ThreeArgIterationStmt, + AST_TypedIterationStmt, NUM_AST_NODE_TYPES }; @@ -251,6 +258,7 @@ struct ZCC_Class : ZCC_Struct { ZCC_Identifier *ParentName; ZCC_Identifier *Replaces; + ZCC_Identifier *Sealed; PClass *CType() { return static_cast(Type)->Descriptor; } }; @@ -380,6 +388,19 @@ struct ZCC_DynArrayType : ZCC_Type ZCC_Type *ElementType; }; +struct ZCC_FuncPtrParamDecl : ZCC_TreeNode +{ + ZCC_Type *Type; + int Flags; +}; + +struct ZCC_FuncPtrType : ZCC_Type +{ + ZCC_Type *RetType; + ZCC_FuncPtrParamDecl *Params; + int Scope; +}; + struct ZCC_ClassType : ZCC_Type { ZCC_Identifier *Restriction; @@ -426,6 +447,12 @@ struct ZCC_ClassCast : ZCC_Expression ZCC_FuncParm *Parameters; }; +struct ZCC_FunctionPtrCast : ZCC_Expression +{ + ZCC_FuncPtrType *PtrType; + ZCC_Expression *Expr; +}; + struct ZCC_ExprMemberAccess : ZCC_Expression { ZCC_Expression *Left; @@ -508,6 +535,31 @@ struct ZCC_ArrayIterationStmt : ZCC_Statement ZCC_Statement* LoopStatement; }; +struct ZCC_TwoArgIterationStmt : ZCC_Statement +{ + ZCC_VarName* ItKey; + ZCC_VarName* ItValue; + ZCC_Expression* ItMap; + ZCC_Statement* LoopStatement; +}; + +struct ZCC_ThreeArgIterationStmt : ZCC_Statement +{ + ZCC_VarName* ItVar; + ZCC_VarName* ItPos; + ZCC_VarName* ItFlags; + ZCC_Expression* ItBlock; + ZCC_Statement* LoopStatement; +}; + +struct ZCC_TypedIterationStmt : ZCC_Statement +{ + ZCC_VarName* ItType; + ZCC_VarName* ItVar; + ZCC_Expression* ItExpr; + ZCC_Statement* LoopStatement; +}; + struct ZCC_IfStmt : ZCC_Statement { ZCC_Expression *Condition; diff --git a/src/common/scripting/interface/stringformat.cpp b/src/common/scripting/interface/stringformat.cpp index 77ce54ed68..3d7a3c428e 100644 --- a/src/common/scripting/interface/stringformat.cpp +++ b/src/common/scripting/interface/stringformat.cpp @@ -282,9 +282,9 @@ DEFINE_ACTION_FUNCTION(FStringStruct, DeleteLastCharacter) static void LocalizeString(const FString &label, bool prefixed, FString *result) { - if (!prefixed) *result = GStrings(label); + if (!prefixed) *result = GStrings.GetString(label); else if (label[0] != '$') *result = label; - else *result = GStrings(&label[1]); + else *result = GStrings.GetString(&label[1]); } DEFINE_ACTION_FUNCTION_NATIVE(FStringTable, Localize, LocalizeString) @@ -408,13 +408,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, ByteAt, StringByteAt) static void StringFilter(FString *self, FString *result) { - *result = strbin1(*self); + *result = strbin1(self->GetChars()); } DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, Filter, StringFilter) { PARAM_SELF_STRUCT_PROLOGUE(FString); - ACTION_RETURN_STRING(strbin1(*self)); + ACTION_RETURN_STRING(strbin1(self->GetChars())); } static int StringIndexOf(FString *self, const FString &substr, int startIndex) diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index 2c7df6fb7a..730465a34e 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -54,11 +54,12 @@ #include "i_time.h" #include "maps.h" +#include "types.h" static ZSMap AllServices; -static void MarkServices() { - +static void MarkServices() +{ ZSMap::Iterator it(AllServices); ZSMap::Pair* pair; while (it.NextPair(pair)) @@ -82,6 +83,11 @@ void InitServices() GC::AddMarkerFunc(&MarkServices); } +void ClearServices() +{ + AllServices.Clear(); +} + //========================================================================== @@ -143,7 +149,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DStatusBarCore, DrawTexture, SBar_DrawTexture) void SBar_DrawImage(DStatusBarCore* self, const FString& texid, double x, double y, int flags, double alpha, double w, double h, double scaleX, double scaleY, int style, int color, int translation, double clipwidth) { if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); - self->DrawGraphic(TexMan.CheckForTexture(texid, ETextureType::Any), x, y, flags, alpha, w, h, scaleX, scaleY, ERenderStyle(style), color, translation, clipwidth); + self->DrawGraphic(TexMan.CheckForTexture(texid.GetChars(), ETextureType::Any), x, y, flags, alpha, w, h, scaleX, scaleY, ERenderStyle(style), color, translation, clipwidth); } DEFINE_ACTION_FUNCTION_NATIVE(DStatusBarCore, DrawImage, SBar_DrawImage) @@ -169,7 +175,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DStatusBarCore, DrawImage, SBar_DrawImage) void SBar_DrawImageRotated(DStatusBarCore* self, const FString& texid, double x, double y, int flags, double angle, double alpha, double scaleX, double scaleY, int style, int color, int translation) { if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); - self->DrawRotated(TexMan.CheckForTexture(texid, ETextureType::Any), x, y, flags, angle, alpha, scaleX, scaleY, color, translation, (ERenderStyle)style); + self->DrawRotated(TexMan.CheckForTexture(texid.GetChars(), ETextureType::Any), x, y, flags, angle, alpha, scaleX, scaleY, color, translation, (ERenderStyle)style); } DEFINE_ACTION_FUNCTION_NATIVE(DStatusBarCore, DrawImageRotated, SBar_DrawImageRotated) @@ -419,7 +425,7 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetName) { // Textures for full path names do not have their own name, they merely link to the source lump. auto lump = tex->GetSourceLump(); - if (fileSystem.GetLinkedTexture(lump) == tex) + if (TexMan.GetLinkedTexture(lump) == tex) retval = fileSystem.GetFileFullName(lump); } } @@ -428,7 +434,7 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetName) static int CheckForTexture(const FString& name, int type, int flags) { - return TexMan.CheckForTexture(name, static_cast(type), flags).GetIndex(); + return TexMan.CheckForTexture(name.GetChars(), static_cast(type), flags).GetIndex(); } DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, CheckForTexture, CheckForTexture) @@ -555,7 +561,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, CheckRealHeight, CheckRealHeight) static int OkForLocalization_(int index, const FString& substitute) { - return sysCallbacks.OkForLocalization? sysCallbacks.OkForLocalization(FSetTextureID(index), substitute) : false; + return sysCallbacks.OkForLocalization? sysCallbacks.OkForLocalization(FSetTextureID(index), substitute.GetChars()) : false; } DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, OkForLocalization, OkForLocalization_) @@ -662,9 +668,9 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetBottomAlignOffset, GetBottomAlignOffset) ACTION_RETURN_FLOAT(GetBottomAlignOffset(self, code)); } -static int StringWidth(FFont *font, const FString &str) +static int StringWidth(FFont *font, const FString &str, int localize) { - const char *txt = str[0] == '$' ? GStrings(&str[1]) : str.GetChars(); + const char *txt = (localize && str[0] == '$') ? GStrings.GetString(&str[1]) : str.GetChars(); return font->StringWidth(txt); } @@ -672,12 +678,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, StringWidth, StringWidth) { PARAM_SELF_STRUCT_PROLOGUE(FFont); PARAM_STRING(str); - ACTION_RETURN_INT(StringWidth(self, str)); + PARAM_BOOL(localize); + ACTION_RETURN_INT(StringWidth(self, str, localize)); } -static int GetMaxAscender(FFont* font, const FString& str) +static int GetMaxAscender(FFont* font, const FString& str, int localize) { - const char* txt = str[0] == '$' ? GStrings(&str[1]) : str.GetChars(); + const char* txt = (localize && str[0] == '$') ? GStrings.GetString(&str[1]) : str.GetChars(); return font->GetMaxAscender(txt); } @@ -685,12 +692,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetMaxAscender, GetMaxAscender) { PARAM_SELF_STRUCT_PROLOGUE(FFont); PARAM_STRING(str); - ACTION_RETURN_INT(GetMaxAscender(self, str)); + PARAM_BOOL(localize); + ACTION_RETURN_INT(GetMaxAscender(self, str, localize)); } -static int CanPrint(FFont *font, const FString &str) +static int CanPrint(FFont *font, const FString &str, int localize) { - const char *txt = str[0] == '$' ? GStrings(&str[1]) : str.GetChars(); + const char *txt = (localize && str[0] == '$') ? GStrings.GetString(&str[1]) : str.GetChars(); return font->CanPrint(txt); } @@ -698,7 +706,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, CanPrint, CanPrint) { PARAM_SELF_STRUCT_PROLOGUE(FFont); PARAM_STRING(str); - ACTION_RETURN_INT(CanPrint(self, str)); + PARAM_BOOL(localize); + ACTION_RETURN_INT(CanPrint(self, str, localize)); } static int FindFontColor(int name) @@ -780,14 +789,14 @@ DEFINE_ACTION_FUNCTION(_Wads, CheckNumForName) PARAM_INT(ns); PARAM_INT(wadnum); PARAM_BOOL(exact); - ACTION_RETURN_INT(fileSystem.CheckNumForName(name, ns, wadnum, exact)); + ACTION_RETURN_INT(fileSystem.CheckNumForName(name.GetChars(), ns, wadnum, exact)); } DEFINE_ACTION_FUNCTION(_Wads, CheckNumForFullName) { PARAM_PROLOGUE; PARAM_STRING(name); - ACTION_RETURN_INT(fileSystem.CheckNumForFullName(name)); + ACTION_RETURN_INT(fileSystem.CheckNumForFullName(name.GetChars())); } DEFINE_ACTION_FUNCTION(_Wads, FindLump) @@ -797,7 +806,7 @@ DEFINE_ACTION_FUNCTION(_Wads, FindLump) PARAM_INT(startlump); PARAM_INT(ns); const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumEntries(); - ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLump(name, &startlump, 0 != ns) : -1); + ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLump(name.GetChars(), &startlump, 0 != ns) : -1); } DEFINE_ACTION_FUNCTION(_Wads, FindLumpFullName) @@ -807,16 +816,14 @@ DEFINE_ACTION_FUNCTION(_Wads, FindLumpFullName) PARAM_INT(startlump); PARAM_BOOL(noext); const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumEntries(); - ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLumpFullName(name, &startlump, noext) : -1); + ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLumpFullName(name.GetChars(), &startlump, noext) : -1); } DEFINE_ACTION_FUNCTION(_Wads, GetLumpName) { PARAM_PROLOGUE; PARAM_INT(lump); - FString lumpname; - fileSystem.GetFileShortName(lumpname, lump); - ACTION_RETURN_STRING(lumpname); + ACTION_RETURN_STRING(fileSystem.GetFileShortName(lump)); } DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullName) @@ -838,7 +845,14 @@ DEFINE_ACTION_FUNCTION(_Wads, ReadLump) PARAM_PROLOGUE; PARAM_INT(lump); const bool isLumpValid = lump >= 0 && lump < fileSystem.GetNumEntries(); - ACTION_RETURN_STRING(isLumpValid ? fileSystem.ReadFile(lump).GetString() : FString()); + ACTION_RETURN_STRING(isLumpValid ? GetStringFromLump(lump, false) : FString()); +} + +DEFINE_ACTION_FUNCTION(_Wads, GetLumpLength) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_INT((int)fileSystem.FileLength(lump)); } //========================================================================== @@ -1017,7 +1031,7 @@ DEFINE_ACTION_FUNCTION(FKeyBindings, SetBind) } - self->SetBind(k, cmd); + self->SetBind(k, cmd.GetChars()); return 0; } @@ -1035,7 +1049,8 @@ DEFINE_ACTION_FUNCTION(FKeyBindings, NameAllKeys) { PARAM_PROLOGUE; PARAM_POINTER(array, TArray); - auto buffer = C_NameKeys(array->Data(), array->Size(), true); + PARAM_BOOL(color); + auto buffer = C_NameKeys(array->Data(), array->Size(), color); ACTION_RETURN_STRING(buffer); } @@ -1055,7 +1070,7 @@ DEFINE_ACTION_FUNCTION(FKeyBindings, GetAllKeysForCommand) PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings); PARAM_POINTER(array, TArray); PARAM_STRING(cmd); - *array = self->GetKeysForCommand(cmd); + *array = self->GetKeysForCommand(cmd.GetChars()); return 0; } @@ -1077,7 +1092,7 @@ DEFINE_ACTION_FUNCTION(FKeyBindings, UnbindACommand) I_FatalError("Attempt to unbind key bindings for '%s' outside of menu code", cmd.GetChars()); } - self->UnbindACommand(cmd); + self->UnbindACommand(cmd.GetChars()); return 0; } @@ -1095,7 +1110,7 @@ DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand) } UnsafeExecutionScope scope(unsafe); - AddCommandString(cmd); + AddCommandString(cmd.GetChars()); return 0; } @@ -1140,7 +1155,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_System, StopAllSounds, StopAllSounds) static int PlayMusic(const FString& musname, int order, int looped) { - return S_ChangeMusic(musname, order, !!looped, true); + return S_ChangeMusic(musname.GetChars(), order, !!looped, true); } DEFINE_ACTION_FUNCTION_NATIVE(_System, PlayMusic, PlayMusic) @@ -1341,3 +1356,412 @@ DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, Inverse, QuatInverse) QuatInverse(self->X, self->Y, self->Z, self->W, &quat); ACTION_RETURN_QUAT(quat); } + +PFunction * FindFunctionPointer(PClass * cls, int fn_name) +{ + auto fn = dyn_cast(cls->FindSymbol(ENamedName(fn_name), true)); + return (fn && (fn->Variants[0].Flags & (VARF_Action | VARF_Virtual)) == 0 ) ? fn : nullptr; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, FindFunction, FindFunctionPointer) +{ + PARAM_PROLOGUE; + PARAM_CLASS(cls, DObject); + PARAM_NAME(fn); + + ACTION_RETURN_POINTER(FindFunctionPointer(cls, fn.GetIndex())); +} + +FTranslationID R_FindCustomTranslation(FName name); + +static int ZFindTranslation(int intname) +{ + return R_FindCustomTranslation(ENamedName(intname)).index(); +} + +static int MakeTransID(int g, int s) +{ + return TRANSLATION(g, s).index(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Translation, GetID, ZFindTranslation) +{ + PARAM_PROLOGUE; + PARAM_INT(t); + ACTION_RETURN_INT(ZFindTranslation(t)); +} + +// same as above for the compiler which needs a class to look this up. +DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinFindTranslation, ZFindTranslation) +{ + PARAM_PROLOGUE; + PARAM_INT(t); + ACTION_RETURN_INT(ZFindTranslation(t)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Translation, MakeID, MakeTransID) +{ + PARAM_PROLOGUE; + PARAM_INT(g); + PARAM_INT(t); + ACTION_RETURN_INT(MakeTransID(g, t)); +} + +// DObject-based wrapper around FScanner, for ZScript. +class DScriptScanner : public DObject +{ + DECLARE_CLASS(DScriptScanner, DObject) +public: + FScanner wrapped; + +}; + +IMPLEMENT_CLASS(DScriptScanner, false, false); + +static void OpenLumpNum(DScriptScanner* self, int lump) { return self->wrapped.OpenLumpNum(lump); } +static void OpenString(DScriptScanner* self, const FString* name, FString* script) { return self->wrapped.OpenString(name->GetChars(), *script); } +static void SavePos(DScriptScanner* self, FScanner::SavedPos *pos) { *pos = self->wrapped.SavePos(); } +static void RestorePos(DScriptScanner* self, const FScanner::SavedPos* pos) { return self->wrapped.RestorePos(*pos); } +static void GetStringContents(DScriptScanner* self, FString* str) { *str = self->wrapped.String; } +static void UnGet(DScriptScanner* self) { return self->wrapped.UnGet(); } +static int isText(DScriptScanner* self) { return self->wrapped.isText(); } +static int GetMessageLine(DScriptScanner* self) { return self->wrapped.GetMessageLine(); } +static void Close(DScriptScanner* self) { return self->wrapped.Close(); } +static void SetCMode(DScriptScanner* self, int cmode) { return self->wrapped.SetCMode(cmode); } +static void SetNoOctals(DScriptScanner* self, int cmode) { return self->wrapped.SetNoOctals(cmode); } +static void SetEscape(DScriptScanner* self, int esc) { return self->wrapped.SetNoOctals(esc); } +static void SetNoFatalErrors(DScriptScanner* self, int cmode) { return self->wrapped.SetNoFatalErrors(cmode); } +static void AddSymbolUint(DScriptScanner* self, const FString* name, uint32_t value) { return self->wrapped.AddSymbol(name->GetChars(), value); } +static void AddSymbolInt(DScriptScanner* self, const FString* name, int32_t value) { return self->wrapped.AddSymbol(name->GetChars(), value); } +static void AddSymbolDouble(DScriptScanner* self, const FString* name, double value) { return self->wrapped.AddSymbol(name->GetChars(), value); } +static int GetString(DScriptScanner* self) { return self->wrapped.GetString(); } +static int GetNumber(DScriptScanner* self, int evaluate) { return self->wrapped.GetNumber(evaluate); } +static int GetFloat(DScriptScanner* self, int evaluate) { return self->wrapped.GetFloat(evaluate); } +static int CheckValue(DScriptScanner* self, int allowfloat, int evaluate) { return self->wrapped.CheckValue(allowfloat, evaluate); } +static int CheckNumber(DScriptScanner* self, int evaluate) { return self->wrapped.CheckNumber(evaluate); } +static int CheckBoolToken(DScriptScanner* self) { return self->wrapped.CheckBoolToken(); } +static int CheckString(DScriptScanner* self, const FString* name) { return self->wrapped.CheckString(name->GetChars()); } +static int CheckFloat(DScriptScanner* self, int evaluate) { return self->wrapped.CheckFloat(evaluate); } +static void SetPrependMessage(DScriptScanner* self, const FString* message) { return self->wrapped.SetPrependMessage(*message); } +static void SkipToEndOfBlock(DScriptScanner* self) { return self->wrapped.SkipToEndOfBlock(); } +static int StartBraces(DScriptScanner* self, FScanner::SavedPos* braceend) { return self->wrapped.StartBraces(braceend); } +static int FoundEndBrace(DScriptScanner* self, FScanner::SavedPos* braceend) { return self->wrapped.FoundEndBrace(*braceend); } +static void MustGetValue(DScriptScanner* self, int allowfloat, int evaluate) { return self->wrapped.MustGetValue(allowfloat, evaluate); } +static void MustGetFloat(DScriptScanner* self, int evaluate) { return self->wrapped.MustGetFloat(evaluate); } +static void MustGetNumber(DScriptScanner* self, int evaluate) { return self->wrapped.MustGetNumber(evaluate); } +static void MustGetString(DScriptScanner* self) { return self->wrapped.MustGetString(); } +static void MustGetStringName(DScriptScanner* self, const FString* name) { return self->wrapped.MustGetStringName(name->GetChars()); } +static void MustGetBoolToken(DScriptScanner* self) { return self->wrapped.MustGetBoolToken(); } + + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, OpenLumpNum, OpenLumpNum) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_INT(lump); + + OpenLumpNum(self, lump); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, OpenString, OpenString) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_STRING(name); + PARAM_STRING_VAL(script); + + OpenString(self, &name, &script); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SavePos, SavePos) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_POINTER(pos, FScanner::SavedPos); + + SavePos(self, pos); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, RestorePos, RestorePos) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_POINTER(pos, FScanner::SavedPos); + + RestorePos(self, pos); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetStringContents, GetStringContents) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + ACTION_RETURN_STRING(self->wrapped.String); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, UnGet, UnGet) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + UnGet(self); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, isText, isText) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + ACTION_RETURN_BOOL(isText(self)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetMessageLine, GetMessageLine) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + ACTION_RETURN_INT(GetMessageLine(self)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, AddSymbol, AddSymbolInt) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_STRING(name); + PARAM_INT(value); + + AddSymbolInt(self, &name, value); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, AddSymbolUnsigned, AddSymbolUint) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_STRING(name); + PARAM_UINT(value); + + AddSymbolUint(self, &name, value); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, AddSymbolFloat, AddSymbolDouble) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_STRING(name); + PARAM_FLOAT(value); + + AddSymbolDouble(self, &name, value); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetString, GetString) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + ACTION_RETURN_BOOL(GetString(self)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetNumber, GetNumber) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(evaluate); + + ACTION_RETURN_BOOL(GetNumber(self, evaluate)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetFloat, GetFloat) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(evaluate); + + ACTION_RETURN_BOOL(GetFloat(self, evaluate)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckValue, CheckValue) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(allowfloat); + PARAM_BOOL(evaluate); + + ACTION_RETURN_BOOL(CheckValue(self, allowfloat, evaluate)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckBoolToken, CheckBoolToken) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + ACTION_RETURN_BOOL(CheckBoolToken(self)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckNumber, CheckNumber) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(evaluate); + + ACTION_RETURN_BOOL(CheckNumber(self, evaluate)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckString, CheckString) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_STRING(name); + + ACTION_RETURN_BOOL(CheckString(self, &name)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckFloat, CheckFloat) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(evaluate); + + ACTION_RETURN_BOOL(CheckFloat(self, evaluate)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetPrependMessage, SetPrependMessage) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_STRING(message); + + SetPrependMessage(self, &message); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetCMode, SetCMode) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(cmode); + + SetCMode(self, cmode); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetNoOctals, SetNoOctals) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(cmode); + + SetNoOctals(self, cmode); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetEscape, SetEscape) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(esc); + + SetEscape(self, esc); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SkipToEndOfBlock, SkipToEndOfBlock) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + SkipToEndOfBlock(self); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, StartBraces, StartBraces) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_POINTER(braceend, FScanner::SavedPos); + + StartBraces(self, braceend); // the return value of this is useless. + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, FoundEndBrace, FoundEndBrace) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_POINTER(braceend, FScanner::SavedPos); + + ACTION_RETURN_BOOL(FoundEndBrace(self, braceend)); +} + +DEFINE_ACTION_FUNCTION(DScriptScanner, ScriptError) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + FString s = FStringFormat(VM_ARGS_NAMES); + self->wrapped.ScriptError("%s", s.GetChars()); + return 0; +} + +DEFINE_ACTION_FUNCTION(DScriptScanner, ScriptMessage) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + FString s = FStringFormat(VM_ARGS_NAMES); + self->wrapped.ScriptMessage("%s", s.GetChars()); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetValue, MustGetValue) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(allowfloat); + PARAM_BOOL(evaluate); + + MustGetValue(self, allowfloat, evaluate); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetNumber, MustGetNumber) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(evaluate); + + MustGetNumber(self, evaluate); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetFloat, MustGetFloat) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(evaluate); + + MustGetFloat(self, evaluate); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetString, MustGetString) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + MustGetString(self); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetStringName, MustGetStringName) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_STRING(name); + + MustGetStringName(self, &name); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetBoolToken, MustGetBoolToken) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + MustGetBoolToken(self); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, Close, Close) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + + Close(self); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetNoFatalErrors, SetNoFatalErrors) +{ + PARAM_SELF_PROLOGUE(DScriptScanner); + PARAM_BOOL(cmode); + + SetNoFatalErrors(self, cmode); + return 0; +} + +DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Line, Line); +DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Float, Float); +DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Number, Number); +DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.End, End); +DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Crossed, Crossed); +DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.ParseError, ParseError); diff --git a/src/common/scripting/jit/jit.cpp b/src/common/scripting/jit/jit.cpp index 100dcc4cc0..1092d8f3d1 100644 --- a/src/common/scripting/jit/jit.cpp +++ b/src/common/scripting/jit/jit.cpp @@ -35,13 +35,19 @@ JitFuncPtr JitCompile(VMScriptFunction* sfunc) } catch (...) { - Printf("%s: Unexpected JIT error encountered\n", sfunc->PrintableName.GetChars()); + Printf("%s: Unexpected JIT error encountered\n", sfunc->PrintableName); throw; } } void JitDumpLog(FILE* file, VMScriptFunction* sfunc) { + if(sfunc->VarFlags & VARF_Abstract) + { + // Printf(TEXTCOLOR_ORANGE "Skipping abstract function during JIT dump: %s\n", sfunc->PrintableName.GetChars()); + return; + } + try { if (sfunc->VarFlags & VARF_Abstract) @@ -241,8 +247,8 @@ void JitCompiler::Setup() //cc.comment("", 0); IRFunctionType* functype = ircontext->getFunctionType(int32Ty, { int8PtrTy, int8PtrTy, int32Ty, int8PtrTy, int32Ty }); - irfunc = ircontext->createFunction(functype, sfunc->PrintableName.GetChars()); - irfunc->fileInfo.push_back({ sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars() }); + irfunc = ircontext->createFunction(functype, sfunc->PrintableName); + irfunc->fileInfo.push_back({ sfunc->PrintableName, sfunc->SourceFileName.GetChars() }); args = irfunc->args[1]; numargs = irfunc->args[2]; @@ -353,7 +359,7 @@ void JitCompiler::SetupSimpleFrame() if (errorDetails) { - I_FatalError("JIT: inconsistent number of %s for function %s", errorDetails, sfunc->PrintableName.GetChars()); + I_FatalError("JIT: inconsistent number of %s for function %s", errorDetails, sfunc->PrintableName); } for (int i = regd; i < sfunc->NumRegD; i++) @@ -553,7 +559,7 @@ static int CastS2I(FString* b) { return (int)b->ToLong(); } static double CastS2F(FString* b) { return b->ToDouble(); } static int CastS2N(FString* b) { return b->Len() == 0 ? NAME_None : FName(*b).GetIndex(); } static void CastN2S(FString* a, int b) { FName name = FName(ENamedName(b)); *a = name.IsValidName() ? name.GetChars() : ""; } -static int CastS2Co(FString* b) { return V_GetColor(*b); } +static int CastS2Co(FString* b) { return V_GetColor(b->GetChars()); } static void CastCo2S(FString* a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); } static int CastS2So(FString* b) { return S_FindSound(*b).index(); } static void CastSo2S(FString* a, int b) { *a = soundEngine->GetSoundName(FSoundID::fromInt(b)); } diff --git a/src/common/scripting/jit/jit_call.cpp b/src/common/scripting/jit/jit_call.cpp index 60d408dfc8..e4bff19a18 100644 --- a/src/common/scripting/jit/jit_call.cpp +++ b/src/common/scripting/jit/jit_call.cpp @@ -90,7 +90,7 @@ void JitCompiler::EmitVMCall(IRValue* vmfunc, VMFunction* target) IRFunctionType* functype = ircontext->getFunctionType(int32Ty, { int8PtrTy, int8PtrTy, int32Ty, int8PtrTy, int32Ty }); IRInst* call = cc.CreateCall(cc.CreateBitCast(scriptcall, functype), { vmfunc, paramsptr, ConstValueD(B), GetCallReturns(), ConstValueD(C) }); - call->comment = std::string("call ") + (target ? target->PrintableName.GetChars() : "VMCall"); + call->comment = std::string("call ") + (target ? target->PrintableName : "VMCall"); LoadInOuts(); LoadReturns(pc + 1, C); @@ -337,6 +337,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) } std::vector args; + for (unsigned int i = 0; i < ParamOpcodes.Size(); i++) { if (ParamOpcodes[i]->op == OP_PARAMI) @@ -472,7 +473,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) } IRInst* result = cc.CreateCall(cc.CreateBitCast(ConstValueA(target->DirectNativeCall), GetFuncSignature()), args); - result->comment = std::string("call ") + target->PrintableName.GetChars(); + result->comment = std::string("call ") + target->PrintableName; if (startret == 1 && numret > 0) { @@ -645,3 +646,8 @@ IRFunctionType* JitCompiler::GetFuncSignature() return ircontext->getFunctionType(rettype, args); } + +void JitCompiler::EmitNULLCHECK() +{ + EmitNullPointerThrow(A, X_READ_NIL); +} \ No newline at end of file diff --git a/src/common/scripting/jit/jitintern.h b/src/common/scripting/jit/jitintern.h index 8a08f034ec..b803b5375a 100644 --- a/src/common/scripting/jit/jitintern.h +++ b/src/common/scripting/jit/jitintern.h @@ -1,4 +1,4 @@ - +#pragma once #include "jit.h" #include "types.h" diff --git a/src/common/scripting/vm/vm.h b/src/common/scripting/vm/vm.h index 3766e9d318..2b7344d5dc 100644 --- a/src/common/scripting/vm/vm.h +++ b/src/common/scripting/vm/vm.h @@ -45,6 +45,7 @@ #include "memarena.h" #include "name.h" #include "scopebarrier.h" +#include class DObject; union VMOP; @@ -194,6 +195,12 @@ struct VMReturn *(void **)Location = val; } + void SetConstPointer(const void *val) + { + assert(RegType == REGT_POINTER); + *(const void **)Location = val; + } + void SetObject(DObject *val) { assert(RegType == REGT_POINTER); @@ -444,7 +451,8 @@ class VMFunction FName Name; const uint8_t *RegTypes = nullptr; TArray DefaultArgs; - FString PrintableName; // so that the VM can print meaningful info if something in this function goes wrong. + const char* QualifiedName = nullptr; + const char* PrintableName = nullptr; // same as QualifiedName, but can have additional annotations. class PPrototype *Proto; TArray ArgFlags; // Should be the same length as Proto->ArgumentTypes @@ -611,6 +619,8 @@ namespace template struct native_is_valid { static const bool value = true; static const bool retval = true; }; template<> struct native_is_valid { static const bool value = true; static const bool retval = true; }; template<> struct native_is_valid { static const bool value = true; static const bool retval = true; }; + // [RL0] this is disabled for now due to graf's concerns + // template<> struct native_is_valid { static const bool value = true; static const bool retval = true; static_assert(sizeof(FName) == sizeof(int)); static_assert(std::is_pod_v);}; template<> struct native_is_valid { static const bool value = true; static const bool retval = true; }; template<> struct native_is_valid { static const bool value = true; static const bool retval = true; }; template<> struct native_is_valid { static const bool value = true; static const bool retval = false;}; // Bool as return does not work! @@ -621,26 +631,7 @@ struct DirectNativeDesc { DirectNativeDesc() = default; - #define TP(n) typename P##n - #define VP(n) ValidateType() - template DirectNativeDesc(Ret(*func)()) : Ptr(reinterpret_cast(func)) { ValidateRet(); } - template DirectNativeDesc(Ret(*func)(P1)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); } - template DirectNativeDesc(Ret(*func)(P1,P2)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); } - template DirectNativeDesc(Ret(*func)(P1,P2,P3)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13), VP(14); } - template DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)) : Ptr(reinterpret_cast(func)) { ValidateRet(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13), VP(14), VP(15); } -#undef TP - #undef VP + template DirectNativeDesc(Ret(*func)(Params...)) : Ptr(reinterpret_cast(func)) { ValidateRet(); (ValidateType(), ...); } template void ValidateType() { static_assert(native_is_valid::value, "Argument type is not valid as a direct native parameter or return type"); } template void ValidateRet() { static_assert(native_is_valid::retval, "Return type is not valid as a direct native parameter or return type"); } @@ -733,6 +724,11 @@ struct AFuncDesc extern FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr; \ MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname; +#define DEFINE_FIELD_NAMED_UNSIZED(cls, name, scriptname) \ + static const FieldDesc VMField_##cls##_##scriptname = { #cls, #scriptname, (unsigned)myoffsetof(cls, name), ~0u, 0 }; \ + extern FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr; \ + MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname; + #define DEFINE_FIELD_BIT(cls, name, scriptname, bitval) \ static const FieldDesc VMField_##cls##_##scriptname = { #cls, #scriptname, (unsigned)myoffsetof(cls, name), (unsigned)sizeof(cls::name), bitval }; \ extern FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr; \ @@ -759,6 +755,7 @@ struct AFuncDesc class AActor; #define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0) +#define ACTION_RETURN_CONST_POINTER(v) do { const void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetConstPointer(state); return 1; } return 0; } while(0) #define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0) #define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetObject(state); return 1; } return 0; } while(0) #define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0) @@ -800,6 +797,7 @@ class AActor; class PFunction; VMFunction *FindVMFunction(PClass *cls, const char *name); +VMFunction* FindVMFunction(const char* name); #define DECLARE_VMFUNC(cls, name) static VMFunction *name; if (name == nullptr) name = FindVMFunction(RUNTIME_CLASS(cls), #name); FString FStringFormat(VM_ARGS, int offset = 0); @@ -838,4 +836,16 @@ unsigned GetVirtualIndex(PClass *cls, const char *funcname); VMFunction *func = clss->Virtuals.Size() > VIndex? clss->Virtuals[VIndex] : nullptr; \ if (func != nullptr) +#define IFOVERRIDENVIRTUALPTRNAME(self, clsname, funcname) \ + static VMFunction *orig_func = nullptr; \ + static unsigned VIndex = ~0u; \ + if (VIndex == ~0u) { \ + PClass *cls = PClass::FindClass(clsname); \ + VIndex = GetVirtualIndex(cls, #funcname); \ + orig_func = cls->Virtuals.Size() > VIndex? cls->Virtuals[VIndex] : nullptr; \ + assert(VIndex != ~0u); \ + } \ + auto *clss = self->GetClass(); \ + VMFunction *func = clss->Virtuals.Size() > VIndex? clss->Virtuals[VIndex] : nullptr; \ + if (func && func != orig_func ) #endif diff --git a/src/common/scripting/vm/vmexec.h b/src/common/scripting/vm/vmexec.h index f303304b81..0d5737d256 100644 --- a/src/common/scripting/vm/vmexec.h +++ b/src/common/scripting/vm/vmexec.h @@ -895,7 +895,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) catch (CVMAbortException &err) { err.MaybePrintMessage(); - err.stacktrace.AppendFormat("Called from %s\n", call->PrintableName.GetChars()); + err.stacktrace.AppendFormat("Called from %s\n", call->PrintableName); // PrintParameters(reg.param + f->NumParam - B, B); throw; } @@ -1937,6 +1937,15 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) CMPJMP(reg.a[B] == konsta[C].v); NEXTOP; + OP(NULLCHECK): + ASSERTA(a); + if (PA == nullptr) + { + ThrowAbortException(X_WRITE_NIL, nullptr); + return 0; + } + NEXTOP; + OP(NOP): NEXTOP; } @@ -2000,7 +2009,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) catch (CVMAbortException &err) { err.MaybePrintMessage(); - err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars(), sfunc->PCToLine(pc)); + err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName, sfunc->SourceFileName.GetChars(), sfunc->PCToLine(pc)); // PrintParameters(reg.param + f->NumParam - B, B); throw; } @@ -2117,7 +2126,7 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c case CAST_S2Co: ASSERTD(a); ASSERTS(b); - reg.d[a] = V_GetColor(reg.s[b]); + reg.d[a] = V_GetColor(reg.s[b].GetChars()); break; case CAST_Co2S: diff --git a/src/common/scripting/vm/vmframe.cpp b/src/common/scripting/vm/vmframe.cpp index 7cab879d4e..0f29a7bfb5 100644 --- a/src/common/scripting/vm/vmframe.cpp +++ b/src/common/scripting/vm/vmframe.cpp @@ -54,8 +54,14 @@ CUSTOM_CVAR(Bool, vm_jit, true, CVAR_NOINITCALL) Printf("You must restart " GAMENAME " for this change to take effect.\n"); Printf("This cvar is currently not saved. You must specify it on the command line."); } +CUSTOM_CVAR(Bool, vm_jit_aot, true, CVAR_NOINITCALL) +{ + Printf("You must restart " GAMENAME " for this change to take effect.\n"); + Printf("This cvar is currently not saved. You must specify it on the command line."); +} #else CVAR(Bool, vm_jit, false, CVAR_NOINITCALL|CVAR_NOSET) +CVAR(Bool, vm_jit_aot, false, CVAR_NOINITCALL|CVAR_NOSET) FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames) { return FString(); } void JitRelease() {} #endif @@ -80,7 +86,7 @@ void VMFunction::CreateRegUse() if (!Proto) { //if (RegTypes) return; - //Printf(TEXTCOLOR_ORANGE "Function without prototype needs register info manually set: %s\n", PrintableName.GetChars()); + //Printf(TEXTCOLOR_ORANGE "Function without prototype needs register info manually set: %s\n", PrintableName); return; } assert(Proto->isPrototype()); @@ -268,6 +274,41 @@ int VMScriptFunction::PCToLine(const VMOP *pc) return -1; } +static bool CanJit(VMScriptFunction* func) +{ + // Asmjit has a 256 register limit. Stay safely away from it as the jit compiler uses a few for temporaries as well. + // Any function exceeding the limit will use the VM - a fair punishment to someone for writing a function so bloated ;) + + if (func->blockJit) return false; + + int maxregs = 200; + if (func->NumRegA + func->NumRegD + func->NumRegF + func->NumRegS < maxregs) + return true; + + Printf(TEXTCOLOR_ORANGE "%s is using too many registers (%d of max %d)! Function will not use native code.\n", func->PrintableName, func->NumRegA + func->NumRegD + func->NumRegF + func->NumRegS, maxregs); + + return false; +} + +void VMScriptFunction::JitCompile() +{ + if (!(VarFlags & VARF_Abstract)) + { +#ifdef HAVE_VM_JIT + if (vm_jit && CanJit(this)) + { + ScriptCall = ::JitCompile(this); + if (!ScriptCall) + ScriptCall = VMExec; + } + else +#endif // HAVE_VM_JIT + { + ScriptCall = VMExec; + } + } +} + int VMScriptFunction::FirstScriptCall(VMFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret) { // [Player701] Check that we aren't trying to call an abstract function. @@ -275,21 +316,10 @@ int VMScriptFunction::FirstScriptCall(VMFunction *func, VMValue *params, int num // rather than let GZDoom crash. if (func->VarFlags & VARF_Abstract) { - ThrowAbortException(X_OTHER, "attempt to call abstract function %s.", func->PrintableName.GetChars()); - } -#ifdef HAVE_VM_JIT - if (vm_jit) - { - func->ScriptCall = JitCompile(static_cast(func)); - if (!func->ScriptCall) - func->ScriptCall = VMExec; - } - else -#endif // HAVE_VM_JIT - { - func->ScriptCall = VMExec; + ThrowAbortException(X_OTHER, "attempt to call abstract function %s.", func->PrintableName); } + static_cast(func)->JitCompile(); return func->ScriptCall(func, params, numparams, ret, numret); } @@ -306,7 +336,7 @@ int VMNativeFunction::NativeScriptCall(VMFunction *func, VMValue *params, int nu catch (CVMAbortException &err) { err.MaybePrintMessage(); - err.stacktrace.AppendFormat("Called from %s\n", func->PrintableName.GetChars()); + err.stacktrace.AppendFormat("Called from %s\n", func->PrintableName); throw; } } @@ -688,7 +718,7 @@ void CVMAbortException::MaybePrintMessage() CVMAbortException err(reason, moreinfo, ap); - err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars(), sfunc->PCToLine(line)); + err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName, sfunc->SourceFileName.GetChars(), sfunc->PCToLine(line)); throw err; } diff --git a/src/common/scripting/vm/vmintern.h b/src/common/scripting/vm/vmintern.h index 9a3e2d4010..b35eefc1e3 100644 --- a/src/common/scripting/vm/vmintern.h +++ b/src/common/scripting/vm/vmintern.h @@ -474,6 +474,8 @@ class VMScriptFunction : public VMFunction VM_UBYTE NumArgs; // Number of arguments this function takes TArray SpecialInits; // list of all contents on the extra stack which require construction and destruction + bool blockJit = false; // function triggers Jit bugs, block compilation until bugs are fixed + void InitExtra(void *addr); void DestroyExtra(void *addr); int AllocExtraStack(PType *type); @@ -481,4 +483,6 @@ class VMScriptFunction : public VMFunction private: static int FirstScriptCall(VMFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret); + void JitCompile(); + friend class FFunctionBuildList; }; diff --git a/src/common/scripting/vm/vmops.h b/src/common/scripting/vm/vmops.h index 1782e78b70..9280b746c5 100644 --- a/src/common/scripting/vm/vmops.h +++ b/src/common/scripting/vm/vmops.h @@ -289,4 +289,7 @@ xx(SUBA, sub, RIRPRP, NOP, 0, 0) // dA = pB - pC xx(EQA_R, beq, CPRR, NOP, 0, 0) // if ((pB == pkC) != A) then pc++ xx(EQA_K, beq, CPRK, EQA_R, 4, REGT_POINTER) +// Null check +xx(NULLCHECK, nullcheck, RP, NOP, 0, 0) // EmitNullPointerThrow(pA) + #undef xx diff --git a/src/common/startscreen/endoom.cpp b/src/common/startscreen/endoom.cpp index c0b5fee023..649c1362dc 100644 --- a/src/common/startscreen/endoom.cpp +++ b/src/common/startscreen/endoom.cpp @@ -111,7 +111,7 @@ FEndoomScreen::FEndoomScreen(int loading_lump) StartupBitmap.Create(80 * 8, 26 * 16); // line 26 is for our own 'press any key to quit' message. DrawTextScreen(StartupBitmap, endoom_screen); ClearBlock(StartupBitmap, {0, 0, 0, 255}, 0, 25*16, 640, 16); - DrawString(StartupBitmap, 0, 25, GStrings("TXT_QUITENDOOM"), { 128, 128, 128 ,255}, { 0, 0, 0, 255}); + DrawString(StartupBitmap, 0, 25, GStrings.GetString("TXT_QUITENDOOM"), { 128, 128, 128 ,255}, { 0, 0, 0, 255}); lastUpdateTime = I_msTime(); // Does this screen need blinking? @@ -153,7 +153,7 @@ int RunEndoom() return 0; } - int endoom_lump = fileSystem.CheckNumForFullName (endoomName, true); + int endoom_lump = fileSystem.CheckNumForFullName (endoomName.GetChars(), true); if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000) { diff --git a/src/common/startscreen/startscreen.cpp b/src/common/startscreen/startscreen.cpp index 2d682f0c04..82fa28f021 100644 --- a/src/common/startscreen/startscreen.cpp +++ b/src/common/startscreen/startscreen.cpp @@ -367,7 +367,7 @@ FStartScreen* GetGameStartScreen(int max_progress) Printf("Error creating start screen: %s\n", err.what()); // fall through to the generic startup screen } - //return CreateGenericStartScreen(max_progress); + return CreateGenericStartScreen(max_progress); } return nullptr; } @@ -570,8 +570,8 @@ void FStartScreen::CreateHeader() fcolor.rgbBlue = BPART(GameStartupInfo.FgColor); fcolor.rgbReserved = 255; ClearBlock(HeaderBitmap, bcolor, 0, 0, HeaderBitmap.GetWidth(), HeaderBitmap.GetHeight()); - int textlen = SizeOfText(GameStartupInfo.Name); - DrawString(HeaderBitmap, (HeaderBitmap.GetWidth() >> 4) - (textlen >> 1), 0.5, GameStartupInfo.Name, fcolor, bcolor); + int textlen = SizeOfText(GameStartupInfo.Name.GetChars()); + DrawString(HeaderBitmap, (HeaderBitmap.GetWidth() >> 4) - (textlen >> 1), 0.5, GameStartupInfo.Name.GetChars(), fcolor, bcolor); NetBitmap.Create(StartupBitmap.GetWidth() * Scale, 16); } @@ -588,7 +588,7 @@ void FStartScreen::DrawNetStatus(int found, int total) RgbQuad black = { 0, 0, 0, 255 }; RgbQuad gray = { 100, 100, 100, 255 }; ClearBlock(NetBitmap, black, 0, NetBitmap.GetHeight() - 16, NetBitmap.GetWidth(), 16); - DrawString(NetBitmap, 0, 0, NetMessageString, gray, black); + DrawString(NetBitmap, 0, 0, NetMessageString.GetChars(), gray, black); char of[10]; mysnprintf(of, 10, "%d/%d", found, total); int siz = SizeOfText(of); @@ -607,7 +607,7 @@ bool FStartScreen::NetInit(const char* message, int numplayers) { NetMaxPos = numplayers; NetCurPos = 0; - NetMessageString.Format("%s %s", message, GStrings("TXT_NET_PRESSESC")); + NetMessageString.Format("%s %s", message, GStrings.GetString("TXT_NET_PRESSESC")); NetProgress(1); // You always know about yourself return true; } @@ -654,9 +654,11 @@ void FStartScreen::NetProgress(int count) void FStartScreen::Render(bool force) { + static uint64_t minwaittime = 30; + auto nowtime = I_msTime(); // Do not refresh too often. This function gets called a lot more frequently than the screen can update. - if (nowtime - screen->FrameTime > 30 || force) + if (nowtime - screen->FrameTime > minwaittime || force) { screen->FrameTime = nowtime; screen->FrameTimeNS = I_nsTime(); @@ -690,6 +692,9 @@ void FStartScreen::Render(bool force) screen->Update(); twod->OnFrameDone(); } + auto newtime = I_msTime(); + if ((newtime - nowtime) * 2.0 > minwaittime) // slow down drawing the start screen if we're on a slow GPU! + minwaittime = (newtime - nowtime) * 2.0; } FImageSource* CreateStartScreenTexture(FBitmap& srcdata); diff --git a/src/common/startscreen/startscreen_generic.cpp b/src/common/startscreen/startscreen_generic.cpp index c2af0bd505..b76cbd3e25 100644 --- a/src/common/startscreen/startscreen_generic.cpp +++ b/src/common/startscreen/startscreen_generic.cpp @@ -72,10 +72,10 @@ FGenericStartScreen::FGenericStartScreen(int max_progress) : FStartScreen(max_progress) { // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system - int startup_lump = fileSystem.CheckNumForName("GZDOOM", ns_graphics); + int startup_lump = fileSystem.CheckNumForName("BOOTLOGO", FileSys::ns_graphics); - StartupBitmap.Create(640, 480); - ClearBlock(StartupBitmap, { 0, 0, 0, 255 }, 0, 0, 640, 480); + StartupBitmap.Create(640 * 2, 480 * 2); + ClearBlock(StartupBitmap, { 0, 0, 0, 255 }, 0, 0, 640 * 2, 480 * 2); // This also needs to work if the lump turns out to be unusable. if (startup_lump != -1) { @@ -83,14 +83,13 @@ FGenericStartScreen::FGenericStartScreen(int max_progress) if (iBackground) { Background = iBackground->GetCachedBitmap(nullptr, FImageSource::normal); - if (Background.GetWidth() < 640 || Background.GetHeight() < 480) - StartupBitmap.Blit(320 - Background.GetWidth()/2, 220 - Background.GetHeight() /2, Background); + if (Background.GetWidth() < 640 * 2 || Background.GetHeight() < 480 * 2) + StartupBitmap.Blit(320 * 2 - Background.GetWidth()/2, 220 * 2 - Background.GetHeight() / 2, Background); else - StartupBitmap.Blit(0, 0, Background, 640, 480); + StartupBitmap.Blit(0, 0, Background, 640 * 2, 480 * 2); } } - CreateHeader(); } //========================================================================== @@ -107,14 +106,15 @@ bool FGenericStartScreen::DoProgress(int advance) if (CurPos < MaxPos) { - RgbQuad bcolor = { 128, 0, 0, 255 }; // todo: make configurable - int numnotches = 512; - notch_pos = ((CurPos + 1) * 512) / MaxPos; + RgbQuad bcolor = { 2, 25, 87, 255 }; // todo: make configurable + int numnotches = 200 * 2; + notch_pos = ((CurPos + 1) * numnotches) / MaxPos; if (notch_pos != NotchPos) { // Time to draw another notch. - ClearBlock(StartupBitmap, bcolor, ST_PROGRESS_X, ST_PROGRESS_Y, notch_pos, 16); + ClearBlock(StartupBitmap, bcolor, (320 - 100) * 2, 480 * 2 - 30, notch_pos, 4 * 2); NotchPos = notch_pos; - StartupTexture->CleanHardwareData(true); + if (StartupTexture) + StartupTexture->CleanHardwareData(true); } } return FStartScreen::DoProgress(advance); diff --git a/src/common/startscreen/startscreen_hexen.cpp b/src/common/startscreen/startscreen_hexen.cpp index 6eef735994..a82e21b351 100644 --- a/src/common/startscreen/startscreen_hexen.cpp +++ b/src/common/startscreen/startscreen_hexen.cpp @@ -81,9 +81,9 @@ FHexenStartScreen::FHexenStartScreen(int max_progress) : FStartScreen(max_progress) { // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system - int startup_lump = fileSystem.CheckNumForName("STARTUP", ns_graphics); - int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", ns_graphics); - int notch_lump = fileSystem.CheckNumForName("NOTCH", ns_graphics); + int startup_lump = fileSystem.CheckNumForName("STARTUP", FileSys::ns_graphics); + int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", FileSys::ns_graphics); + int notch_lump = fileSystem.CheckNumForName("NOTCH", FileSys::ns_graphics); // For backwards compatibility we also need to look in the default namespace, because these were previously not handled as graphics. if (startup_lump == -1) startup_lump = fileSystem.CheckNumForName("STARTUP"); diff --git a/src/common/startscreen/startscreen_strife.cpp b/src/common/startscreen/startscreen_strife.cpp index 6587443b83..df5467f966 100644 --- a/src/common/startscreen/startscreen_strife.cpp +++ b/src/common/startscreen/startscreen_strife.cpp @@ -39,6 +39,7 @@ #include "image.h" #include "textures.h" #include "palettecontainer.h" +#include "cmdlib.h" // Strife startup screen #define PEASANT_INDEX 0 @@ -104,21 +105,13 @@ class FStrifeStartScreen : public FStartScreen FStrifeStartScreen::FStrifeStartScreen(int max_progress) : FStartScreen(max_progress) { - // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system - - int startup_lump = fileSystem.CheckNumForName("STARTUP0"); - - if (startup_lump < 0) - { - I_Error("bad startscreen assets"); - } - StartupBitmap.Create(320, 200); - // Load the animated overlays. + // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system + // Load the background and animated overlays. for (size_t i = 0; i < countof(StrifeStartupPicNames); ++i) { - int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], ns_graphics); + int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], FileSys::ns_graphics); if (lumpnum < 0) lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]); if (lumpnum >= 0) diff --git a/src/common/statusbar/base_sbar.cpp b/src/common/statusbar/base_sbar.cpp index 3b1029c651..e890c04115 100644 --- a/src/common/statusbar/base_sbar.cpp +++ b/src/common/statusbar/base_sbar.cpp @@ -601,7 +601,7 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag DTA_ClipBottom, twod->GetHeight(), DTA_ClipRight, clipwidth < 0? twod->GetWidth() : int(x + boxwidth * clipwidth), DTA_Color, color, - DTA_TranslationIndex, translation? translation : (flags & DI_TRANSLATABLE) ? GetTranslation() : 0, + DTA_TranslationIndex, translation? translation : (flags & DI_TRANSLATABLE) ? GetTranslation().index() : 0, DTA_ColorOverlay, (flags & DI_DIM) ? MAKEARGB(170, 0, 0, 0) : 0, DTA_Alpha, Alpha, DTA_AlphaChannel, !!(flags & DI_ALPHAMAPPED), @@ -686,7 +686,7 @@ void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flag DTA_Color, color, DTA_CenterOffsetRel, !!(flags & DI_ITEM_RELCENTER), DTA_Rotate, angle, - DTA_TranslationIndex, translation ? translation : (flags & DI_TRANSLATABLE) ? GetTranslation() : 0, + DTA_TranslationIndex, translation ? translation : (flags & DI_TRANSLATABLE) ? GetTranslation().index() : 0, DTA_ColorOverlay, (flags & DI_DIM) ? MAKEARGB(170, 0, 0, 0) : 0, DTA_Alpha, Alpha, DTA_AlphaChannel, !!(flags & DI_ALPHAMAPPED), @@ -704,7 +704,7 @@ void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flag // //============================================================================ -void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY, int pt, int style) +void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY, FTranslationID pt, int style) { bool monospaced = monospacing != EMonospacing::Off; double dx = 0; @@ -823,11 +823,11 @@ void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, d DTA_FillColor, 0, TAG_DONE); } - DrawChar(twod, font, pt == 0? fontcolor : CR_NATIVEPAL, rx, ry, ch, + DrawChar(twod, font, pt == NO_TRANSLATION? fontcolor : CR_NATIVEPAL, rx, ry, ch, DTA_DestWidthF, rw, DTA_DestHeightF, rh, DTA_Alpha, Alpha, - DTA_TranslationIndex, pt, + DTA_TranslationIndex, pt.index(), DTA_LegacyRenderStyle, ERenderStyle(style), TAG_DONE); @@ -840,10 +840,11 @@ void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, d } } -void SBar_DrawString(DStatusBarCore* self, DHUDFont* font, const FString& string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY, int pt, int style) +void SBar_DrawString(DStatusBarCore* self, DHUDFont* font, const FString& string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY, int pt_, int style) { if (font == nullptr || font->mFont == nullptr) ThrowAbortException(X_READ_NIL, nullptr); if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + auto pt = FTranslationID::fromInt(pt_); // resolve auto-alignment before making any adjustments to the position values. if (!(flags & DI_SCREEN_MANUAL_ALIGN)) diff --git a/src/common/statusbar/base_sbar.h b/src/common/statusbar/base_sbar.h index f095ab80d2..444e5257a1 100644 --- a/src/common/statusbar/base_sbar.h +++ b/src/common/statusbar/base_sbar.h @@ -179,7 +179,7 @@ class DStatusBarCore : public DObject void BeginHUD(int resW, int resH, double Alpha, bool forceScaled = false); void SetSize(int reltop = 32, int hres = 320, int vres = 200, int hhres = -1, int hvres = -1); virtual DVector2 GetHUDScale() const; - virtual uint32_t GetTranslation() const { return 0; } + virtual FTranslationID GetTranslation() const { return NO_TRANSLATION; } void SetDrawSize(int reltop, int hres, int vres); virtual void SetScale(); void ValidateResolution(int& hres, int& vres) const; @@ -188,7 +188,7 @@ class DStatusBarCore : public DObject void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, ERenderStyle style = STYLE_Translucent, PalEntry color = 0xffffffff, int translation = 0, double clipwidth = -1.0); void DrawRotated(FTextureID texture, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent); void DrawRotated(FGameTexture* tex, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent); - void DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY, int pt, int style); + void DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY, FTranslationID pt, int style); void TransformRect(double& x, double& y, double& w, double& h, int flags = 0); void Fill(PalEntry color, double x, double y, double w, double h, int flags = 0); void SetClipRect(double x, double y, double w, double h, int flags = 0); diff --git a/src/common/textures/animtexture.cpp b/src/common/textures/animtexture.cpp index a3be030794..1e9ee6d809 100644 --- a/src/common/textures/animtexture.cpp +++ b/src/common/textures/animtexture.cpp @@ -35,6 +35,8 @@ #include "bitmap.h" #include "texturemanager.h" +#include "vpx/vpx_image.h" + //========================================================================== // @@ -46,39 +48,152 @@ void AnimTexture::SetFrameSize(int format, int width, int height) { pixelformat = format; FTexture::SetSize(width, height); - Image.Resize(width * height * (format == Paletted ? 1 : 3)); + Image.Resize(width * height * 4); memset(Image.Data(), 0, Image.Size()); } -void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) +//TODO optimize +static inline void YUVtoRGB(uint8_t yi, uint8_t ui, uint8_t vi, uint8_t * rgb) +{ + float Y = yi * (1 / 255.f); + float U = ui * (1 / 255.f) - 0.5f; + float V = vi * (1 / 255.f) - 0.5f; + Y = 1.1643f * (Y - 0.0625f); + float r = Y + 1.5958f * V; + float g = Y - 0.39173f * U - 0.81290f * V; + float b = Y + 2.017f * U; + (rgb)[2] = (uint8_t)(clamp(r, 0.f, 1.f) * 255); + (rgb)[1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255); + (rgb)[0] = (uint8_t)(clamp(b, 0.f, 1.f) * 255); + (rgb)[3] = 255; +} + +void AnimTexture::SetFrame(const uint8_t* Palette, const void* data_) { - if (palette) memcpy(Palette, palette, 768); if (data_) { + auto dpix = Image.Data(); + if (pixelformat == YUV) { - auto spix = (const uint8_t*)data_; - auto dpix = Image.Data(); + const uint8_t * spix = reinterpret_cast(data_); + + for (int i = 0; i < Width * Height; i++) + { + YUVtoRGB(spix[0], spix[1], spix[2], dpix); + + spix += 4; + dpix += 4; + } + } + else if(pixelformat == VPX) + { + const vpx_image_t *img = reinterpret_cast(data_); + + uint8_t const* const yplane = img->planes[VPX_PLANE_Y]; + uint8_t const* const uplane = img->planes[VPX_PLANE_U]; + uint8_t const* const vplane = img->planes[VPX_PLANE_V]; + + const int ystride = img->stride[VPX_PLANE_Y]; + const int ustride = img->stride[VPX_PLANE_U]; + const int vstride = img->stride[VPX_PLANE_V]; + + if(img->fmt == VPX_IMG_FMT_I420) + { + for (unsigned int y = 0; y < Height; y++) + { + for (unsigned int x = 0; x < Width; x++) + { + YUVtoRGB( + yplane[ystride * y + x], + uplane[ustride * (y >> 1) + (x >> 1)], + vplane[vstride * (y >> 1) + (x >> 1)], + dpix + ); + + dpix += 4; + } + } + } + else if(img->fmt == VPX_IMG_FMT_I444) + { + for (unsigned int y = 0; y < Height; y++) + { + for (unsigned int x = 0; x < Width; x++) + { + YUVtoRGB( + yplane[ystride * y + x], + uplane[ustride * y + x], + vplane[vstride * y + x], + dpix + ); + dpix += 4; + } + } + } + else if(img->fmt == VPX_IMG_FMT_I422) + { // 422 and 440 untested + for (unsigned int y = 0; y < Height; y++) + { + for (unsigned int x = 0; x < Width; x++) + { + YUVtoRGB( + yplane[ystride * y + x], + uplane[ustride * y + (x >> 1)], + vplane[vstride * y + (x >> 1)], + dpix + ); + dpix += 4; + } + } + } + else if(img->fmt == VPX_IMG_FMT_I440) + { + for (unsigned int y = 0; y < Height; y++) + { + for (unsigned int x = 0; x < Width; x++) + { + YUVtoRGB( + yplane[ystride * y + x], + uplane[ustride * (y >> 1) + x], + vplane[vstride * (y >> 1) + x], + dpix + ); + dpix += 4; + } + } + } + } + else if(pixelformat == RGB) + { + const uint8_t *img = reinterpret_cast(data_); + for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int q = i * 3; - float y = spix[p] * (1 / 255.f); - float u = spix[p + 1] * (1 / 255.f) - 0.5f; - float v = spix[p + 2] * (1 / 255.f) - 0.5f; - - y = 1.1643f * (y - 0.0625f); - - float r = y + 1.5958f * v; - float g = y - 0.39173f * u - 0.81290f * v; - float b = y + 2.017f * u; - - dpix[q + 0] = (uint8_t)(clamp(r, 0.f, 1.f) * 255); - dpix[q + 1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255); - dpix[q + 2] = (uint8_t)(clamp(b, 0.f, 1.f) * 255); + { + dpix[0] = img[2]; + dpix[1] = img[1]; + dpix[2] = img[0]; + dpix[3] = 255; + + dpix += 4; + } + } + else if (pixelformat == Paletted) + { + assert(Palette); + const uint8_t *img = reinterpret_cast(data_); + + for (int i = 0; i < Width * Height; i++) + { + int index = img[i]; + dpix[0] = Palette[index * 3 + 2]; + dpix[1] = Palette[index * 3 + 1]; + dpix[2] = Palette[index * 3]; + dpix[3] = 255; + + dpix += 4; } } - else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); } } @@ -90,37 +205,7 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans) { - FBitmap bmp; - - bmp.Create(Width, Height); - - auto spix = Image.Data(); - auto dpix = bmp.GetPixels(); - if (pixelformat == Paletted) - { - for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int index = spix[i]; - dpix[p + 0] = Palette[index * 3 + 2]; - dpix[p + 1] = Palette[index * 3 + 1]; - dpix[p + 2] = Palette[index * 3]; - dpix[p + 3] = 255; - } - } - else if (pixelformat == RGB || pixelformat == YUV) - { - for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int q = i * 3; - dpix[p + 0] = spix[q + 2]; - dpix[p + 1] = spix[q + 1]; - dpix[p + 2] = spix[q]; - dpix[p + 3] = 255; - } - } - return bmp; + return FBitmap(Image.Data(), Width * 4, Width, Height); } //========================================================================== diff --git a/src/common/textures/animtexture.h b/src/common/textures/animtexture.h index 1f79d0af1c..dafa5e6334 100644 --- a/src/common/textures/animtexture.h +++ b/src/common/textures/animtexture.h @@ -5,7 +5,6 @@ class AnimTexture : public FTexture { - uint8_t Palette[768]; TArray Image; int pixelformat; public: @@ -13,7 +12,8 @@ class AnimTexture : public FTexture { Paletted = 0, RGB = 1, - YUV = 2 + YUV = 2, + VPX = 3 }; AnimTexture() = default; void SetFrameSize(int format, int width, int height); diff --git a/src/common/textures/bitmap.cpp b/src/common/textures/bitmap.cpp index b685b03252..b97b969d70 100644 --- a/src/common/textures/bitmap.cpp +++ b/src/common/textures/bitmap.cpp @@ -118,7 +118,7 @@ void iCopyColors(uint8_t *pout, const uint8_t *pin, int count, int step, FCopyIn a = TSrc::A(pin, tr, tg, tb); if (TBlend::ProcessAlpha0() || a) { - int gray = clamp(TSrc::Gray(pin),0,255); + int gray = std::clamp(TSrc::Gray(pin),0,255); PalEntry pe = cm->GrayscaleToColor[gray]; TBlend::OpC(pout[TDest::RED], pe.r , a, inf); @@ -257,21 +257,21 @@ bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy, step_y = pstep_y; break; - case 1: // rotate 90 right + case 1: // rotate 90° right pixxoffset = 0; pixyoffset = srcheight - 1; step_x = -pstep_y; step_y = pstep_x; break; - case 2: // rotate 180 + case 2: // rotate 180° pixxoffset = srcwidth - 1; pixyoffset = srcheight - 1; step_x = -pstep_x; step_y = -pstep_y; break; - case 3: // rotate 90 left + case 3: // rotate 90° left pixxoffset = srcwidth - 1; pixyoffset = 0; step_x = pstep_y; @@ -285,7 +285,7 @@ bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy, step_y = pstep_y; break; - case 5: // flip horizontally and rotate 90 right + case 5: // flip horizontally and rotate 90° right pixxoffset = srcwidth - 1; pixyoffset = srcheight - 1; step_x = -pstep_y; @@ -299,7 +299,7 @@ bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy, step_y = -pstep_y; break; - case 7: // flip horizontally and rotate 90 left + case 7: // flip horizontally and rotate 90° left pixxoffset = 0; pixyoffset = 0; step_x = pstep_y; diff --git a/src/common/textures/bitmap.h b/src/common/textures/bitmap.h index ae5ede88f0..7f52bc5c02 100644 --- a/src/common/textures/bitmap.h +++ b/src/common/textures/bitmap.h @@ -36,8 +36,7 @@ #ifndef __BITMAP_H__ #define __BITMAP_H__ -#include "basics.h" - +#include #include "palentry.h" struct FCopyInfo; @@ -110,7 +109,7 @@ class FBitmap FBitmap(const FBitmap &other) = delete; // disallow because in nearly all cases this creates an unwanted copy. - FBitmap(FBitmap &&other) + FBitmap(FBitmap &&other) noexcept { data = other.data; Pitch = other.Pitch; @@ -124,7 +123,7 @@ class FBitmap FBitmap &operator=(const FBitmap &other) = delete; // disallow because in nearly all cases this creates an unwanted copy. Use Copy instead. - FBitmap &operator=(FBitmap &&other) + FBitmap &operator=(FBitmap &&other) noexcept { if (data != nullptr && FreeBuffer) delete[] data; data = other.data; @@ -254,6 +253,8 @@ class FBitmap CopyPixelDataRGB(originx, originy, src.GetPixels(), src.GetWidth(), src.GetHeight(), 4, src.GetWidth()*4, 0, CF_BGRA, inf); } + + friend class FTexture; }; bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy, @@ -320,9 +321,9 @@ struct cCMYK struct cYCbCr { - static __forceinline unsigned char R(const unsigned char * p) { return clamp((int)(p[0] + 1.40200 * (int(p[2]) - 0x80)), 0, 255); } - static __forceinline unsigned char G(const unsigned char * p) { return clamp((int)(p[0] - 0.34414 * (int(p[1] - 0x80)) - 0.71414 * (int(p[2]) - 0x80)), 0, 255); } - static __forceinline unsigned char B(const unsigned char * p) { return clamp((int)(p[0] + 1.77200 * (int(p[1]) - 0x80)), 0, 255); } + static __forceinline unsigned char R(const unsigned char * p) { return std::clamp((int)(p[0] + 1.40200 * (int(p[2]) - 0x80)), 0, 255); } + static __forceinline unsigned char G(const unsigned char * p) { return std::clamp((int)(p[0] - 0.34414 * (int(p[1] - 0x80)) - 0.71414 * (int(p[2]) - 0x80)), 0, 255); } + static __forceinline unsigned char B(const unsigned char * p) { return std::clamp((int)(p[0] + 1.77200 * (int(p[1]) - 0x80)), 0, 255); } static __forceinline unsigned char A(const unsigned char * p, uint8_t x, uint8_t y, uint8_t z) { return 255; } static __forceinline int Gray(const unsigned char * p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; } }; @@ -470,7 +471,7 @@ struct bCopyAlpha struct bOverlay { static __forceinline void OpC(uint8_t &d, uint8_t s, uint8_t a, FCopyInfo *i) { d = (s*a + d*(255-a))/255; } - static __forceinline void OpA(uint8_t &d, uint8_t s, FCopyInfo *i) { d = max(s,d); } + static __forceinline void OpA(uint8_t &d, uint8_t s, FCopyInfo *i) { d = std::max(s,d); } static __forceinline bool ProcessAlpha0() { return false; } }; @@ -483,21 +484,21 @@ struct bBlend struct bAdd { - static __forceinline void OpC(uint8_t &d, uint8_t s, uint8_t a, FCopyInfo *i) { d = min((d*BLENDUNIT + s*i->alpha) >> BLENDBITS, 255); } + static __forceinline void OpC(uint8_t &d, uint8_t s, uint8_t a, FCopyInfo *i) { d = std::min((d*BLENDUNIT + s*i->alpha) >> BLENDBITS, 255); } static __forceinline void OpA(uint8_t &d, uint8_t s, FCopyInfo *i) { d = s; } static __forceinline bool ProcessAlpha0() { return false; } }; struct bSubtract { - static __forceinline void OpC(uint8_t &d, uint8_t s, uint8_t a, FCopyInfo *i) { d = max((d*BLENDUNIT - s*i->alpha) >> BLENDBITS, 0); } + static __forceinline void OpC(uint8_t &d, uint8_t s, uint8_t a, FCopyInfo *i) { d = std::max((d*BLENDUNIT - s*i->alpha) >> BLENDBITS, 0); } static __forceinline void OpA(uint8_t &d, uint8_t s, FCopyInfo *i) { d = s; } static __forceinline bool ProcessAlpha0() { return false; } }; struct bReverseSubtract { - static __forceinline void OpC(uint8_t &d, uint8_t s, uint8_t a, FCopyInfo *i) { d = max((-d*BLENDUNIT + s*i->alpha) >> BLENDBITS, 0); } + static __forceinline void OpC(uint8_t &d, uint8_t s, uint8_t a, FCopyInfo *i) { d = std::max((-d*BLENDUNIT + s*i->alpha) >> BLENDBITS, 0); } static __forceinline void OpA(uint8_t &d, uint8_t s, FCopyInfo *i) { d = s; } static __forceinline bool ProcessAlpha0() { return false; } }; diff --git a/src/common/textures/formats/anmtexture.cpp b/src/common/textures/formats/anmtexture.cpp index eeea41a898..1eb7f49492 100644 --- a/src/common/textures/formats/anmtexture.cpp +++ b/src/common/textures/formats/anmtexture.cpp @@ -33,6 +33,7 @@ ** */ +#include #include "files.h" #include "filesystem.h" #include "bitmap.h" @@ -51,8 +52,8 @@ class FAnmTexture : public FImageSource public: FAnmTexture (int lumpnum, int w, int h); void ReadFrame(uint8_t *buffer, uint8_t *palette); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap *bmp, int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; }; @@ -71,13 +72,14 @@ FImageSource *AnmImage_TryCreate(FileReader & file, int lumpnum) if (memcmp(check, "LPF ", 4)) return nullptr; file.Seek(0, FileReader::SeekSet); auto buffer = file.ReadPadded(1); + if (buffer.size() < 4) return nullptr; - anim_t anim; - if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0) + std::unique_ptr anim = std::make_unique(); // note that this struct is very large and should not go onto the stack! + if (ANIM_LoadAnim(anim.get(), buffer.bytes(), buffer.size() - 1) < 0) { return nullptr; } - int numframes = ANIM_NumFrames(&anim); + int numframes = ANIM_NumFrames(anim.get()); if (numframes >= 1) { return new FAnmTexture(lumpnum, 320, 200); @@ -103,17 +105,17 @@ FAnmTexture::FAnmTexture (int lumpnum, int w, int h) void FAnmTexture::ReadFrame(uint8_t *pixels, uint8_t *palette) { - FileData lump = fileSystem.ReadFile (SourceLump); - uint8_t *source = (uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto source = lump.bytes(); - anim_t anim; - if (ANIM_LoadAnim(&anim, source, (int)lump.GetSize()) >= 0) + std::unique_ptr anim = std::make_unique(); // note that this struct is very large and should not go onto the stack! + if (ANIM_LoadAnim(anim.get(), source, (int)lump.size()) >= 0) { - int numframes = ANIM_NumFrames(&anim); + int numframes = ANIM_NumFrames(anim.get()); if (numframes >= 1) { - memcpy(palette, ANIM_GetPalette(&anim), 768); - memcpy(pixels, ANIM_DrawFrame(&anim, 1), Width*Height); + memcpy(palette, ANIM_GetPalette(anim.get()), 768); + memcpy(pixels, ANIM_DrawFrame(anim.get(), 1), Width * Height); return; } } @@ -121,25 +123,30 @@ void FAnmTexture::ReadFrame(uint8_t *pixels, uint8_t *palette) memset(palette, 0, 768); } +struct workbuf +{ + uint8_t buffer[64000]; + uint8_t palette[768]; +}; + //========================================================================== // // // //========================================================================== -PalettedPixels FAnmTexture::CreatePalettedPixels(int conversion) +PalettedPixels FAnmTexture::CreatePalettedPixels(int conversion, int frame) { PalettedPixels pixels(Width*Height); - uint8_t buffer[64000]; - uint8_t palette[768]; uint8_t remap[256]; + std::unique_ptr w = std::make_unique(); - ReadFrame(buffer, palette); + ReadFrame(w->buffer, w->palette); for(int i=0;i<256;i++) { - remap[i] = ColorMatcher.Pick(palette[i*3], palette[i*3+1], palette[i*3+2]); + remap[i] = ColorMatcher.Pick(w->palette[i*3], w->palette[i*3+1], w->palette[i*3+2]); } - ImageHelpers::FlipNonSquareBlockRemap (pixels.Data(), buffer, Width, Height, Width, remap); + ImageHelpers::FlipNonSquareBlockRemap (pixels.Data(), w->buffer, Width, Height, Width, remap); return pixels; } @@ -149,20 +156,19 @@ PalettedPixels FAnmTexture::CreatePalettedPixels(int conversion) // //========================================================================== -int FAnmTexture::CopyPixels(FBitmap *bmp, int conversion) +int FAnmTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { - uint8_t buffer[64000]; - uint8_t palette[768]; - ReadFrame(buffer, palette); + std::unique_ptr w = std::make_unique(); + ReadFrame(w->buffer, w->palette); auto dpix = bmp->GetPixels(); for (int i = 0; i < Width * Height; i++) { int p = i * 4; - int index = buffer[i]; - dpix[p + 0] = palette[index * 3 + 2]; - dpix[p + 1] = palette[index * 3 + 1]; - dpix[p + 2] = palette[index * 3]; + int index = w->buffer[i]; + dpix[p + 0] = w->palette[index * 3 + 2]; + dpix[p + 1] = w->palette[index * 3 + 1]; + dpix[p + 2] = w->palette[index * 3]; dpix[p + 3] = 255; } diff --git a/src/common/textures/formats/automaptexture.cpp b/src/common/textures/formats/automaptexture.cpp index c253650fda..2ebdc4d536 100644 --- a/src/common/textures/formats/automaptexture.cpp +++ b/src/common/textures/formats/automaptexture.cpp @@ -50,7 +50,7 @@ class FAutomapTexture : public FImageSource { public: FAutomapTexture(int lumpnum); - PalettedPixels CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; }; @@ -89,11 +89,11 @@ FAutomapTexture::FAutomapTexture (int lumpnum) // //========================================================================== -PalettedPixels FAutomapTexture::CreatePalettedPixels(int conversion) +PalettedPixels FAutomapTexture::CreatePalettedPixels(int conversion, int frame) { int x, y; - FileData data = fileSystem.ReadFile (SourceLump); - const uint8_t *indata = (const uint8_t *)data.GetMem(); + auto data = fileSystem.ReadFile (SourceLump); + auto indata = data.bytes(); PalettedPixels Pixels(Width * Height); diff --git a/src/common/textures/formats/brightmaptexture.cpp b/src/common/textures/formats/brightmaptexture.cpp index f7e36d6285..262a520f6f 100644 --- a/src/common/textures/formats/brightmaptexture.cpp +++ b/src/common/textures/formats/brightmaptexture.cpp @@ -43,7 +43,7 @@ class FBrightmapTexture : public FImageSource public: FBrightmapTexture (FImageSource *source); - int CopyPixels(FBitmap *bmp, int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; protected: FImageSource *SourcePic; @@ -65,9 +65,9 @@ FBrightmapTexture::FBrightmapTexture (FImageSource *source) bMasked = false; } -int FBrightmapTexture::CopyPixels(FBitmap *bmp, int conversion) +int FBrightmapTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { - SourcePic->CopyTranslatedPixels(bmp, GPalette.GlobalBrightmap.Palette); + SourcePic->CopyTranslatedPixels(bmp, GPalette.GlobalBrightmap.Palette, frame); return 0; } diff --git a/src/common/textures/formats/buildtexture.cpp b/src/common/textures/formats/buildtexture.cpp index f8d8a7b6ab..fec41227bf 100644 --- a/src/common/textures/formats/buildtexture.cpp +++ b/src/common/textures/formats/buildtexture.cpp @@ -55,7 +55,7 @@ FBuildTexture::FBuildTexture(const FString &pathprefix, int tilenum, const uint8 TopOffset = top; } -PalettedPixels FBuildTexture::CreatePalettedPixels(int conversion) +PalettedPixels FBuildTexture::CreatePalettedPixels(int conversion, int frame) { PalettedPixels Pixels(Width * Height); FRemapTable *Remap = Translation; @@ -67,7 +67,7 @@ PalettedPixels FBuildTexture::CreatePalettedPixels(int conversion) return Pixels; } -int FBuildTexture::CopyPixels(FBitmap *bmp, int conversion) +int FBuildTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { PalEntry *Remap = Translation->Palette; bmp->CopyPixelData(0, 0, RawPixels, Width, Height, Height, 1, 0, Remap); diff --git a/src/common/textures/formats/ddstexture.cpp b/src/common/textures/formats/ddstexture.cpp index 8a3d0ba74f..6105ea99be 100644 --- a/src/common/textures/formats/ddstexture.cpp +++ b/src/common/textures/formats/ddstexture.cpp @@ -54,6 +54,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" // Since we want this to compile under Linux too, we need to define this // stuff ourselves instead of including a DirectX header. @@ -163,7 +164,7 @@ class FDDSTexture : public FImageSource public: FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc); - PalettedPixels CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; protected: uint32_t Format; @@ -182,7 +183,7 @@ class FDDSTexture : public FImageSource void DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode); void DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode); - int CopyPixels(FBitmap *bmp, int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; friend class FTexture; }; @@ -371,7 +372,7 @@ void FDDSTexture::CalcBitShift (uint32_t mask, uint8_t *lshiftp, uint8_t *rshift // //========================================================================== -PalettedPixels FDDSTexture::CreatePalettedPixels(int conversion) +PalettedPixels FDDSTexture::CreatePalettedPixels(int conversion, int frame) { auto lump = fileSystem.OpenFileReader (SourceLump); @@ -664,7 +665,7 @@ void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode) { - const long blocklinelen = ((Width + 3) >> 2) << 4; + const size_t blocklinelen = ((Width + 3) >> 2) << 4; uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *block; PalEntry color[4]; @@ -780,7 +781,7 @@ void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t // //=========================================================================== -int FDDSTexture::CopyPixels(FBitmap *bmp, int conversion) +int FDDSTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { auto lump = fileSystem.OpenFileReader (SourceLump); diff --git a/src/common/textures/formats/emptytexture.cpp b/src/common/textures/formats/emptytexture.cpp index 74e8fe1cba..cd53b996a3 100644 --- a/src/common/textures/formats/emptytexture.cpp +++ b/src/common/textures/formats/emptytexture.cpp @@ -49,7 +49,7 @@ class FEmptyTexture : public FImageSource { public: FEmptyTexture (int lumpnum); - PalettedPixels CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; }; //========================================================================== @@ -94,7 +94,7 @@ FEmptyTexture::FEmptyTexture (int lumpnum) // //========================================================================== -PalettedPixels FEmptyTexture::CreatePalettedPixels(int conversion) +PalettedPixels FEmptyTexture::CreatePalettedPixels(int conversion, int frame) { static uint8_t p; PalettedPixels Pixel(&p, 1); diff --git a/src/common/textures/formats/flattexture.cpp b/src/common/textures/formats/flattexture.cpp index a01016a366..533b484b36 100644 --- a/src/common/textures/formats/flattexture.cpp +++ b/src/common/textures/formats/flattexture.cpp @@ -48,7 +48,7 @@ class FFlatTexture : public FImageSource { public: FFlatTexture (int lumpnum); - PalettedPixels CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; }; @@ -74,10 +74,9 @@ FImageSource *FlatImage_TryCreate(FileReader & file, int lumpnum) FFlatTexture::FFlatTexture (int lumpnum) : FImageSource(lumpnum) { - int area; int bits; - area = fileSystem.FileLength (lumpnum); + auto area = fileSystem.FileLength (lumpnum); switch (area) { @@ -102,7 +101,7 @@ FFlatTexture::FFlatTexture (int lumpnum) // //========================================================================== -PalettedPixels FFlatTexture::CreatePalettedPixels(int conversion) +PalettedPixels FFlatTexture::CreatePalettedPixels(int conversion, int frame) { auto lump = fileSystem.OpenFileReader (SourceLump); PalettedPixels Pixels(Width*Height); diff --git a/src/common/textures/formats/fontchars.cpp b/src/common/textures/formats/fontchars.cpp index add4f1f742..2d09cf58de 100644 --- a/src/common/textures/formats/fontchars.cpp +++ b/src/common/textures/formats/fontchars.cpp @@ -66,7 +66,7 @@ FFontChar2::FFontChar2(int sourcelump, int sourcepos, int width, int height, int // //========================================================================== -PalettedPixels FFontChar2::CreatePalettedPixels(int) +PalettedPixels FFontChar2::CreatePalettedPixels(int, int) { auto lump = fileSystem.OpenFileReader(SourceLump); int destSize = Width * Height; @@ -164,15 +164,13 @@ PalettedPixels FFontChar2::CreatePalettedPixels(int) if (destSize < 0) { - char name[9]; - fileSystem.GetFileShortName(name, SourceLump); - name[8] = 0; + auto name = fileSystem.GetFileShortName(SourceLump); I_FatalError("The font %s is corrupt", name); } return Pixels; } -int FFontChar2::CopyPixels(FBitmap* bmp, int conversion) +int FFontChar2::CopyPixels(FBitmap* bmp, int conversion, int frame) { if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. auto ppix = CreatePalettedPixels(conversion); diff --git a/src/common/textures/formats/fontchars.h b/src/common/textures/formats/fontchars.h index 45c6785661..089043969e 100644 --- a/src/common/textures/formats/fontchars.h +++ b/src/common/textures/formats/fontchars.h @@ -6,8 +6,8 @@ class FFontChar2 : public FImageSource public: FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap* bmp, int conversion); + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap* bmp, int conversion, int frame = 0); void SetSourceRemap(const PalEntry* sourceremap) { diff --git a/src/common/textures/formats/imgztexture.cpp b/src/common/textures/formats/imgztexture.cpp index 733d20f844..9419c64a66 100644 --- a/src/common/textures/formats/imgztexture.cpp +++ b/src/common/textures/formats/imgztexture.cpp @@ -66,8 +66,8 @@ class FIMGZTexture : public FImageSource public: FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t, bool isalpha); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap *bmp, int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; }; @@ -118,10 +118,10 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1 // //========================================================================== -PalettedPixels FIMGZTexture::CreatePalettedPixels(int conversion) +PalettedPixels FIMGZTexture::CreatePalettedPixels(int conversion, int frame) { - FileData lump = fileSystem.ReadFile (SourceLump); - const ImageHeader *imgz = (const ImageHeader *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto imgz = (const ImageHeader *)lump.data(); const uint8_t *data = (const uint8_t *)&imgz[1]; uint8_t *dest_p; @@ -198,9 +198,9 @@ PalettedPixels FIMGZTexture::CreatePalettedPixels(int conversion) // //========================================================================== -int FIMGZTexture::CopyPixels(FBitmap *bmp, int conversion) +int FIMGZTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { - if (!isalpha) return FImageSource::CopyPixels(bmp, conversion); - else return CopyTranslatedPixels(bmp, GPalette.GrayscaleMap.Palette); + if (!isalpha) return FImageSource::CopyPixels(bmp, conversion, frame); + else return CopyTranslatedPixels(bmp, GPalette.GrayscaleMap.Palette, frame); } diff --git a/src/common/textures/formats/jpegtexture.cpp b/src/common/textures/formats/jpegtexture.cpp deleted file mode 100644 index b1e5163b3f..0000000000 --- a/src/common/textures/formats/jpegtexture.cpp +++ /dev/null @@ -1,486 +0,0 @@ -/* -** jpegtexture.cpp -** Texture class for JPEG images -** -**--------------------------------------------------------------------------- -** Copyright 2005-2016 Randy Heit -** Copyright 2005-2019 Christoph Oelckers -** 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. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -**--------------------------------------------------------------------------- -** -** -*/ - -#include -extern "C" -{ -#include -} - -#include "files.h" -#include "filesystem.h" -#include "printf.h" -#include "bitmap.h" -#include "imagehelpers.h" -#include "image.h" - - -struct FLumpSourceMgr : public jpeg_source_mgr -{ - FileReader *Lump; - JOCTET Buffer[4096]; - bool StartOfFile; - - FLumpSourceMgr (FileReader *lump, j_decompress_ptr cinfo); - static void InitSource (j_decompress_ptr cinfo); - static boolean FillInputBuffer (j_decompress_ptr cinfo); - static void SkipInputData (j_decompress_ptr cinfo, long num_bytes); - static void TermSource (j_decompress_ptr cinfo); -}; - - -//========================================================================== -// -// -// -//========================================================================== - -void FLumpSourceMgr::InitSource (j_decompress_ptr cinfo) -{ - ((FLumpSourceMgr *)(cinfo->src))->StartOfFile = true; -} - -//========================================================================== -// -// -// -//========================================================================== - -boolean FLumpSourceMgr::FillInputBuffer (j_decompress_ptr cinfo) -{ - FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src); - auto nbytes = me->Lump->Read (me->Buffer, sizeof(me->Buffer)); - - if (nbytes <= 0) - { - me->Buffer[0] = (JOCTET)0xFF; - me->Buffer[1] = (JOCTET)JPEG_EOI; - nbytes = 2; - } - me->next_input_byte = me->Buffer; - me->bytes_in_buffer = nbytes; - me->StartOfFile = false; - return TRUE; -} - -//========================================================================== -// -// -// -//========================================================================== - -void FLumpSourceMgr::SkipInputData (j_decompress_ptr cinfo, long num_bytes) -{ - FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src); - if (num_bytes <= (long)me->bytes_in_buffer) - { - me->bytes_in_buffer -= num_bytes; - me->next_input_byte += num_bytes; - } - else - { - num_bytes -= (long)me->bytes_in_buffer; - me->Lump->Seek (num_bytes, FileReader::SeekCur); - FillInputBuffer (cinfo); - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FLumpSourceMgr::TermSource (j_decompress_ptr cinfo) -{ -} - -//========================================================================== -// -// -// -//========================================================================== - -FLumpSourceMgr::FLumpSourceMgr (FileReader *lump, j_decompress_ptr cinfo) -: Lump (lump) -{ - cinfo->src = this; - init_source = InitSource; - fill_input_buffer = FillInputBuffer; - skip_input_data = SkipInputData; - resync_to_restart = jpeg_resync_to_restart; - term_source = TermSource; - bytes_in_buffer = 0; - next_input_byte = NULL; -} - -//========================================================================== -// -// -// -//========================================================================== - -void JPEG_ErrorExit (j_common_ptr cinfo) -{ - (*cinfo->err->output_message) (cinfo); - throw -1; -} - -//========================================================================== -// -// -// -//========================================================================== - -void JPEG_OutputMessage (j_common_ptr cinfo) -{ - char buffer[JMSG_LENGTH_MAX]; - - (*cinfo->err->format_message) (cinfo, buffer); - Printf (TEXTCOLOR_ORANGE "JPEG failure: %s\n", buffer); -} - -//========================================================================== -// -// A JPEG texture -// -//========================================================================== - -class FJPEGTexture : public FImageSource -{ -public: - FJPEGTexture (int lumpnum, int width, int height); - - int CopyPixels(FBitmap *bmp, int conversion) override; - PalettedPixels CreatePalettedPixels(int conversion) override; -}; - -//========================================================================== -// -// -// -//========================================================================== - -FImageSource *JPEGImage_TryCreate(FileReader & data, int lumpnum) -{ - union - { - uint32_t dw; - uint16_t w[2]; - uint8_t b[4]; - } first4bytes; - - data.Seek(0, FileReader::SeekSet); - if (data.Read(&first4bytes, 4) < 4) return NULL; - - if (first4bytes.b[0] != 0xFF || first4bytes.b[1] != 0xD8 || first4bytes.b[2] != 0xFF) - return NULL; - - // Find the SOFn marker to extract the image dimensions, - // where n is 0, 1, or 2 (other types are unsupported). - while ((unsigned)first4bytes.b[3] - 0xC0 >= 3) - { - if (data.Read (first4bytes.w, 2) != 2) - { - return NULL; - } - data.Seek (BigShort(first4bytes.w[0]) - 2, FileReader::SeekCur); - if (data.Read (first4bytes.b + 2, 2) != 2 || first4bytes.b[2] != 0xFF) - { - return NULL; - } - } - if (data.Read (first4bytes.b, 3) != 3) - { - return NULL; - } - if (BigShort (first4bytes.w[0]) < 5) - { - return NULL; - } - if (data.Read (first4bytes.b, 4) != 4) - { - return NULL; - } - return new FJPEGTexture (lumpnum, BigShort(first4bytes.w[1]), BigShort(first4bytes.w[0])); -} - -//========================================================================== -// -// -// -//========================================================================== - -FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height) -: FImageSource(lumpnum) -{ - bMasked = false; - - Width = width; - Height = height; -} - -//========================================================================== -// -// -// -//========================================================================== - -PalettedPixels FJPEGTexture::CreatePalettedPixels(int conversion) -{ - auto lump = fileSystem.OpenFileReader (SourceLump); - JSAMPLE *buff = NULL; - - jpeg_decompress_struct cinfo; - jpeg_error_mgr jerr; - - PalettedPixels Pixels(Width * Height); - memset (Pixels.Data(), 0xBA, Width * Height); - - cinfo.err = jpeg_std_error(&jerr); - cinfo.err->output_message = JPEG_OutputMessage; - cinfo.err->error_exit = JPEG_ErrorExit; - jpeg_create_decompress(&cinfo); - - FLumpSourceMgr sourcemgr(&lump, &cinfo); - try - { - bool doalpha = conversion == luminance; - jpeg_read_header(&cinfo, TRUE); - if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || - (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || - (cinfo.out_color_space == JCS_YCCK && cinfo.num_components == 4) || - (cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) || - (cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) - { - Printf(TEXTCOLOR_ORANGE "Unsupported color format in %s\n", fileSystem.GetFileFullPath(SourceLump).GetChars()); - } - else - { - jpeg_start_decompress(&cinfo); - - int y = 0; - buff = new uint8_t[cinfo.output_width * cinfo.output_components]; - - while (cinfo.output_scanline < cinfo.output_height) - { - jpeg_read_scanlines(&cinfo, &buff, 1); - uint8_t *in = buff; - uint8_t *out = Pixels.Data() + y; - switch (cinfo.out_color_space) - { - case JCS_RGB: - for (int x = Width; x > 0; --x) - { - *out = ImageHelpers::RGBToPalette(doalpha, in[0], in[1], in[2]); - out += Height; - in += 3; - } - break; - - case JCS_GRAYSCALE: - { - auto remap = ImageHelpers::GetRemap(doalpha, true); - for (int x = Width; x > 0; --x) - { - *out = remap[in[0]]; - out += Height; - in += 1; - } - break; - } - case JCS_CMYK: - // What are you doing using a CMYK image? :) - for (int x = Width; x > 0; --x) - { - // To be precise, these calculations should use 255, but - // 256 is much faster and virtually indistinguishable. - int r = in[3] - (((256 - in[0])*in[3]) >> 8); - int g = in[3] - (((256 - in[1])*in[3]) >> 8); - int b = in[3] - (((256 - in[2])*in[3]) >> 8); - *out = ImageHelpers::RGBToPalette(doalpha, r, g, b); - out += Height; - in += 4; - } - break; - - case JCS_YCbCr: - // Probably useless but since I had the formula available... - for (int x = Width; x > 0; --x) - { - double Y = in[0], Cb = in[1], Cr = in[2]; - int r = clamp((int)(Y + 1.40200 * (Cr - 0x80)), 0, 255); - int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255); - int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255); - *out = ImageHelpers::RGBToPalette(doalpha, r, g, b); - out += Height; - in += 4; - } - break; - - case JCS_YCCK: - // Probably useless but since I had the formula available... - for (int x = Width; x > 0; --x) - { - double Y = in[0], Cb = in[1], Cr = in[2]; - int K = in[3]; - int r = clamp((int)(Y + 1.40200 * (Cr - 0x80)), 0, 255); - int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255); - int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255); - r = r - ((r * K) >> 8); - g = g - ((g * K) >> 8); - b = b - ((b * K) >> 8); - *out = ImageHelpers::RGBToPalette(doalpha, r, g, b); - out += Height; - in += 4; - } - break; - - default: - // The other colorspaces were considered above and discarded, - // but GCC will complain without a default for them here. - break; - } - y++; - } - jpeg_finish_decompress(&cinfo); - } - } - catch (int) - { - Printf(TEXTCOLOR_ORANGE "JPEG error in %s\n", fileSystem.GetFileFullPath(SourceLump).GetChars()); - } - jpeg_destroy_decompress(&cinfo); - if (buff != NULL) - { - delete[] buff; - } - return Pixels; -} - - -//=========================================================================== -// -// FJPEGTexture::CopyPixels -// -// Preserves the full color information (unlike software mode) -// -//=========================================================================== - -int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion) -{ - PalEntry pe[256]; - - auto lump = fileSystem.OpenFileReader (SourceLump); - - jpeg_decompress_struct cinfo; - jpeg_error_mgr jerr; - - cinfo.err = jpeg_std_error(&jerr); - cinfo.err->output_message = JPEG_OutputMessage; - cinfo.err->error_exit = JPEG_ErrorExit; - jpeg_create_decompress(&cinfo); - - FLumpSourceMgr sourcemgr(&lump, &cinfo); - try - { - jpeg_read_header(&cinfo, TRUE); - - if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || - (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || - (cinfo.out_color_space == JCS_YCCK && cinfo.num_components == 4) || - (cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) || - (cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) - { - Printf(TEXTCOLOR_ORANGE "Unsupported color format in %s\n", fileSystem.GetFileFullPath(SourceLump).GetChars()); - } - else - { - jpeg_start_decompress(&cinfo); - - int yc = 0; - TArray buff(cinfo.output_height * cinfo.output_width * cinfo.output_components, true); - - while (cinfo.output_scanline < cinfo.output_height) - { - uint8_t * ptr = buff.Data() + cinfo.output_width * cinfo.output_components * yc; - jpeg_read_scanlines(&cinfo, &ptr, 1); - yc++; - } - - switch (cinfo.out_color_space) - { - case JCS_RGB: - bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height, - 3, cinfo.output_width * cinfo.output_components, 0, CF_RGB); - break; - - case JCS_GRAYSCALE: - for (int i = 0; i < 256; i++) pe[i] = PalEntry(255, i, i, i); // default to a gray map - bmp->CopyPixelData(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height, - 1, cinfo.output_width, 0, pe); - break; - - case JCS_CMYK: - bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height, - 4, cinfo.output_width * cinfo.output_components, 0, CF_CMYK); - break; - - case JCS_YCCK: - bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height, - 4, cinfo.output_width * cinfo.output_components, 0, CF_YCCK); - break; - - case JCS_YCbCr: - bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height, - 4, cinfo.output_width * cinfo.output_components, 0, CF_YCbCr); - break; - - default: - assert(0); - break; - } - jpeg_finish_decompress(&cinfo); - } - } - catch (int) - { - Printf(TEXTCOLOR_ORANGE "JPEG error in %s\n", fileSystem.GetFileFullPath(SourceLump).GetChars()); - } - jpeg_destroy_decompress(&cinfo); - return 0; -} - diff --git a/src/common/textures/formats/multipatchtexture.cpp b/src/common/textures/formats/multipatchtexture.cpp index 17c0a7b28d..3a8e8ae7b0 100644 --- a/src/common/textures/formats/multipatchtexture.cpp +++ b/src/common/textures/formats/multipatchtexture.cpp @@ -201,7 +201,7 @@ void FMultiPatchTexture::CopyToBlock(uint8_t *dest, int dwidth, int dheight, FIm // //========================================================================== -PalettedPixels FMultiPatchTexture::CreatePalettedPixels(int conversion) +PalettedPixels FMultiPatchTexture::CreatePalettedPixels(int conversion, int frame) { int numpix = Width * Height; uint8_t blendwork[256]; @@ -278,7 +278,7 @@ PalettedPixels FMultiPatchTexture::CreatePalettedPixels(int conversion) // //=========================================================================== -int FMultiPatchTexture::CopyPixels(FBitmap *bmp, int conversion) +int FMultiPatchTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { int retv = -1; diff --git a/src/common/textures/formats/multipatchtexture.h b/src/common/textures/formats/multipatchtexture.h index 4b92aad4f6..ce1f5d932f 100644 --- a/src/common/textures/formats/multipatchtexture.h +++ b/src/common/textures/formats/multipatchtexture.h @@ -74,8 +74,8 @@ class FMultiPatchTexture : public FImageSource TexPart *Parts; // The getters must optionally redirect if it's a simple one-patch texture. - int CopyPixels(FBitmap *bmp, int conversion) override; - PalettedPixels CreatePalettedPixels(int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; void CopyToBlock(uint8_t *dest, int dwidth, int dheight, FImageSource *source, int xpos, int ypos, int rotate, const uint8_t *translation, int style); void CollectForPrecache(PrecacheInfo &info, bool requiretruecolor) override; diff --git a/src/common/textures/formats/patchtexture.cpp b/src/common/textures/formats/patchtexture.cpp index 2fe36efe72..d7e8f3fca6 100644 --- a/src/common/textures/formats/patchtexture.cpp +++ b/src/common/textures/formats/patchtexture.cpp @@ -38,6 +38,18 @@ #include "bitmap.h" #include "image.h" #include "imagehelpers.h" +#include "m_swap.h" + + +// Doom patch format header +struct patch_t +{ + int16_t width; // bounding box size + int16_t height; + int16_t leftoffset; // pixels to the left of origin + int16_t topoffset; // pixels below the origin + uint32_t columnofs[1]; // only [width] used +}; // posts are runs of non masked source pixels @@ -61,8 +73,8 @@ class FPatchTexture : public FImageSource bool isalpha = false; public: FPatchTexture (int lumpnum, int w, int h, int lo, int to, bool isalphatex); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap *bmp, int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; bool SupportRemap0() override { return !badflag; } void DetectBadPatches(); }; @@ -80,7 +92,7 @@ static bool CheckIfPatch(FileReader & file, bool &isalpha) file.Seek(0, FileReader::SeekSet); auto data = file.Read(file.GetLength()); - const patch_t *foo = (const patch_t *)data.Data(); + const patch_t *foo = (const patch_t *)data.data(); int height = LittleShort(foo->height); int width = LittleShort(foo->width); @@ -110,7 +122,7 @@ static bool CheckIfPatch(FileReader & file, bool &isalpha) { // only check this if the texture passed validation. // Here is a good point because we already have a valid buffer of the lump's data. - isalpha = checkPatchForAlpha(data.Data(), (uint32_t)file.GetLength()); + isalpha = checkPatchForAlpha(data.data(), (uint32_t)file.GetLength()); } return !gapAtStart; } @@ -166,15 +178,15 @@ FPatchTexture::FPatchTexture (int lumpnum, int w, int h, int lo, int to, bool is // //========================================================================== -PalettedPixels FPatchTexture::CreatePalettedPixels(int conversion) +PalettedPixels FPatchTexture::CreatePalettedPixels(int conversion, int frame) { uint8_t *remap, remaptable[256]; int numspans; const column_t *maxcol; int x; - FileData lump = fileSystem.ReadFile (SourceLump); - const patch_t *patch = (const patch_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + const patch_t *patch = (const patch_t *)lump.data(); maxcol = (const column_t *)((const uint8_t *)patch + fileSystem.FileLength (SourceLump) - 3); @@ -263,10 +275,10 @@ PalettedPixels FPatchTexture::CreatePalettedPixels(int conversion) // //========================================================================== -int FPatchTexture::CopyPixels(FBitmap *bmp, int conversion) +int FPatchTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { - if (!isalpha) return FImageSource::CopyPixels(bmp, conversion); - else return CopyTranslatedPixels(bmp, GPalette.GrayscaleMap.Palette); + if (!isalpha) return FImageSource::CopyPixels(bmp, conversion, frame); + else return CopyTranslatedPixels(bmp, GPalette.GrayscaleMap.Palette, frame); } //========================================================================== @@ -283,8 +295,8 @@ void FPatchTexture::DetectBadPatches () // Check if this patch is likely to be a problem. // It must be 256 pixels tall, and all its columns must have exactly // one post, where each post has a supposed length of 0. - FileData lump = fileSystem.ReadFile (SourceLump); - const patch_t *realpatch = (patch_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + const patch_t *realpatch = (patch_t *)lump.data(); const uint32_t *cofs = realpatch->columnofs; int x, x2 = LittleShort(realpatch->width); diff --git a/src/common/textures/formats/pcxtexture.cpp b/src/common/textures/formats/pcxtexture.cpp index 60e2f4aba6..6981f91e03 100644 --- a/src/common/textures/formats/pcxtexture.cpp +++ b/src/common/textures/formats/pcxtexture.cpp @@ -39,6 +39,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" //========================================================================== // @@ -83,7 +84,7 @@ class FPCXTexture : public FImageSource public: FPCXTexture (int lumpnum, PCXHeader &); - int CopyPixels(FBitmap *bmp, int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; protected: void ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr); @@ -91,7 +92,7 @@ class FPCXTexture : public FImageSource void ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes); - PalettedPixels CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; }; @@ -159,8 +160,8 @@ void FPCXTexture::ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr) int rle_count = 0; uint8_t rle_value = 0; - TArray srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); - uint8_t * src = srcp.Data(); + auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); + const uint8_t * src = srcp.bytes(); for (y = 0; y < Height; ++y) { @@ -209,8 +210,8 @@ void FPCXTexture::ReadPCX4bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr) TArray line(hdr->bytesPerScanLine, true); TArray colorIndex(Width, true); - TArray srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); - uint8_t * src = srcp.Data(); + auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); + const uint8_t * src = srcp.bytes(); for (y = 0; y < Height; ++y) { @@ -264,7 +265,7 @@ void FPCXTexture::ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr) int y, bytes; auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); - uint8_t * src = srcp.Data(); + const uint8_t * src = srcp.bytes(); for (y = 0; y < Height; ++y) { @@ -305,7 +306,7 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr int bytes; auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); - uint8_t * src = srcp.Data(); + const uint8_t * src = srcp.bytes(); for (y = 0; y < Height; ++y) { @@ -344,7 +345,7 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr // //========================================================================== -PalettedPixels FPCXTexture::CreatePalettedPixels(int conversion) +PalettedPixels FPCXTexture::CreatePalettedPixels(int conversion, int frame) { uint8_t PaletteMap[256]; PCXHeader header; @@ -432,7 +433,7 @@ PalettedPixels FPCXTexture::CreatePalettedPixels(int conversion) // //=========================================================================== -int FPCXTexture::CopyPixels(FBitmap *bmp, int conversion) +int FPCXTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { PalEntry pe[256]; PCXHeader header; diff --git a/src/common/textures/formats/pngtexture.cpp b/src/common/textures/formats/pngtexture.cpp index f9e39fc8c7..01f210a1c5 100644 --- a/src/common/textures/formats/pngtexture.cpp +++ b/src/common/textures/formats/pngtexture.cpp @@ -43,6 +43,7 @@ #include "printf.h" #include "texturemanager.h" #include "filesystem.h" +#include "m_swap.h" //========================================================================== // @@ -55,8 +56,8 @@ class FPNGTexture : public FImageSource public: FPNGTexture (FileReader &lump, int lumpnum, int width, int height, uint8_t bitdepth, uint8_t colortype, uint8_t interlace); - int CopyPixels(FBitmap *bmp, int conversion) override; - PalettedPixels CreatePalettedPixels(int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; protected: void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap); @@ -411,7 +412,7 @@ void FPNGTexture::ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap) // //========================================================================== -PalettedPixels FPNGTexture::CreatePalettedPixels(int conversion) +PalettedPixels FPNGTexture::CreatePalettedPixels(int conversion, int frame) { FileReader *lump; FileReader lfr; @@ -552,7 +553,7 @@ PalettedPixels FPNGTexture::CreatePalettedPixels(int conversion) // //=========================================================================== -int FPNGTexture::CopyPixels(FBitmap *bmp, int conversion) +int FPNGTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { // Parse pre-IDAT chunks. I skip the CRCs. Is that bad? PalEntry pe[256]; diff --git a/src/common/textures/formats/qoitexture.cpp b/src/common/textures/formats/qoitexture.cpp new file mode 100644 index 0000000000..07511aaf9a --- /dev/null +++ b/src/common/textures/formats/qoitexture.cpp @@ -0,0 +1,213 @@ +/* +** qoitexture.cpp +** Texture class for QOI (Quite OK Image Format) images +** +**--------------------------------------------------------------------------- +** Copyright 2023 Cacodemon345 +** Copyright 2022 Dominic Szablewski +** All rights reserved. +** +** 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. +**--------------------------------------------------------------------------- +** +** +*/ + +#include "files.h" +#include "filesystem.h" +#include "bitmap.h" +#include "imagehelpers.h" +#include "image.h" + +#pragma pack(1) + +struct QOIHeader +{ + char magic[4]; + uint32_t width; + uint32_t height; + uint8_t channels; + uint8_t colorspace; +}; +#pragma pack() + +class FQOITexture : public FImageSource +{ +public: + FQOITexture(int lumpnum, QOIHeader& header); + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; +}; + +FImageSource *QOIImage_TryCreate(FileReader &file, int lumpnum) +{ + QOIHeader header; + + if ((size_t)file.GetLength() < (sizeof(header) + 8)) + { + return nullptr; + } + + file.Seek(0, FileReader::SeekSet); + file.Read((void *)&header, sizeof(header)); + + if (header.magic[0] != 'q' || header.magic[1] != 'o' || header.magic[2] != 'i' || header.magic[3] != 'f') + { + return nullptr; + } + + if (header.width == 0 || header.height == 0 || header.channels < 3 || header.channels > 4 || header.colorspace > 1) + { + return nullptr; + } + + return new FQOITexture(lumpnum, header); +} + +FQOITexture::FQOITexture(int lumpnum, QOIHeader& header) + : FImageSource(lumpnum) +{ + LeftOffset = TopOffset = 0; + Width = header.width; + Height = header.height; + if (header.channels == 3) bMasked = (bTranslucent = false); +} + +PalettedPixels FQOITexture::CreatePalettedPixels(int conversion, int frame) +{ + FBitmap bitmap; + bitmap.Create(Width, Height); + CopyPixels(&bitmap, conversion); + const uint8_t *data = bitmap.GetPixels(); + + uint8_t *dest_p; + int dest_adv = Height; + int dest_rew = Width * Height - 1; + + PalettedPixels Pixels(Width * Height); + dest_p = Pixels.Data(); + + bool doalpha = conversion == luminance; + // Convert the source image from row-major to column-major format and remap it + for (int y = Height; y != 0; --y) + { + for (int x = Width; x != 0; --x) + { + int b = *data++; + int g = *data++; + int r = *data++; + int a = *data++; + if (a < 128) + *dest_p = 0; + else + *dest_p = ImageHelpers::RGBToPalette(doalpha, r, g, b); + dest_p += dest_adv; + } + dest_p -= dest_rew; + } + return Pixels; +} + +int FQOITexture::CopyPixels(FBitmap *bmp, int conversion, int frame) +{ + enum + { + QOI_OP_INDEX = 0x00, /* 00xxxxxx */ + QOI_OP_DIFF = 0x40, /* 01xxxxxx */ + QOI_OP_LUMA = 0x80, /* 10xxxxxx */ + QOI_OP_RUN = 0xc0, /* 11xxxxxx */ + QOI_OP_RGB = 0xfe, /* 11111110 */ + QOI_OP_RGBA = 0xff, /* 11111111 */ + + QOI_MASK_2 = 0xc0, /* 11000000 */ + }; + + constexpr auto QOI_COLOR_HASH = [](PalEntry C) { return (C.r * 3 + C.g * 5 + C.b * 7 + C.a * 11); }; + + auto lump = fileSystem.ReadFile(SourceLump); + if (lump.size() < 22) return 0; // error + PalEntry index[64] = {}; + PalEntry pe = 0xff000000; + + size_t p = 14, run = 0; + + size_t chunks_len = lump.size() - 8; + auto bytes = lump.bytes(); + + for (int h = 0; h < Height; h++) + { + auto pixels = bmp->GetPixels() + h * bmp->GetPitch(); + for (int w = 0; w < Width; w++) + { + if (run > 0) + { + run--; + } + else if (p < chunks_len) + { + int b1 = bytes[p++]; + + if (b1 == QOI_OP_RGB) + { + pe.r = bytes[p++]; + pe.g = bytes[p++]; + pe.b = bytes[p++]; + } + else if (b1 == QOI_OP_RGBA) + { + pe.r = bytes[p++]; + pe.g = bytes[p++]; + pe.b = bytes[p++]; + pe.a = bytes[p++]; + } + else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) + { + pe = index[b1]; + } + else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) + { + pe.r += ((b1 >> 4) & 0x03) - 2; + pe.g += ((b1 >> 2) & 0x03) - 2; + pe.b += (b1 & 0x03) - 2; + } + else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) + { + int b2 = bytes[p++]; + int vg = (b1 & 0x3f) - 32; + pe.r += vg - 8 + ((b2 >> 4) & 0x0f); + pe.g += vg; + pe.b += vg - 8 + (b2 & 0x0f); + } + else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) + { + run = (b1 & 0x3f); + } + + index[QOI_COLOR_HASH(pe) % 64] = pe; + } + } + + pixels[0] = pe.b; + pixels[1] = pe.g; + pixels[2] = pe.r; + pixels[3] = pe.a; + pixels += 4; + } + return bMasked? -1 : 0; +} diff --git a/src/common/textures/formats/rawpagetexture.cpp b/src/common/textures/formats/rawpagetexture.cpp index 19d3f45878..52b3f3c535 100644 --- a/src/common/textures/formats/rawpagetexture.cpp +++ b/src/common/textures/formats/rawpagetexture.cpp @@ -38,6 +38,17 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" + +// Doom patch format header +struct patch_t +{ + int16_t width; // bounding box size + int16_t height; + int16_t leftoffset; // pixels to the left of origin + int16_t topoffset; // pixels below the origin + uint32_t columnofs[1]; // only [width] used +}; //========================================================================== @@ -51,8 +62,8 @@ class FRawPageTexture : public FImageSource int mPaletteLump = -1; public: FRawPageTexture (int lumpnum); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap *bmp, int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; }; //========================================================================== @@ -73,7 +84,7 @@ bool CheckIfRaw(FileReader & data, unsigned desiredsize) data.Seek(0, FileReader::SeekSet); auto bits = data.Read(data.GetLength()); - foo = (patch_t *)bits.Data(); + foo = (patch_t *)bits.data(); height = LittleShort(foo->height); width = LittleShort(foo->width); @@ -154,9 +165,8 @@ FRawPageTexture::FRawPageTexture (int lumpnum) Height = 200; // Special case hack for Heretic's E2 end pic. This is not going to be exposed as an editing feature because the implications would be horrible. - FString Name; - fileSystem.GetFileShortName(Name, lumpnum); - if (Name.CompareNoCase("E2END") == 0) + auto Name = fileSystem.GetFileShortName(lumpnum); + if (stricmp(Name, "E2END") == 0) { mPaletteLump = fileSystem.CheckNumForName("E2PAL"); if (fileSystem.FileLength(mPaletteLump) < 768) mPaletteLump = -1; @@ -170,10 +180,10 @@ FRawPageTexture::FRawPageTexture (int lumpnum) // //========================================================================== -PalettedPixels FRawPageTexture::CreatePalettedPixels(int conversion) +PalettedPixels FRawPageTexture::CreatePalettedPixels(int conversion, int frame) { - FileData lump = fileSystem.ReadFile (SourceLump); - const uint8_t *source = (const uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto source = lump.bytes(); const uint8_t *source_p = source; uint8_t *dest_p; @@ -199,15 +209,15 @@ PalettedPixels FRawPageTexture::CreatePalettedPixels(int conversion) return Pixels; } -int FRawPageTexture::CopyPixels(FBitmap *bmp, int conversion) +int FRawPageTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { - if (mPaletteLump < 0) return FImageSource::CopyPixels(bmp, conversion); + if (mPaletteLump < 0) return FImageSource::CopyPixels(bmp, conversion, frame); else { - FileData lump = fileSystem.ReadFile(SourceLump); - FileData plump = fileSystem.ReadFile(mPaletteLump); - const uint8_t *source = (const uint8_t *)lump.GetMem(); - const uint8_t *psource = (const uint8_t *)plump.GetMem(); + auto lump = fileSystem.ReadFile(SourceLump); + auto plump = fileSystem.ReadFile(mPaletteLump); + auto source = lump.bytes(); + auto psource = plump.bytes(); PalEntry paldata[256]; for (auto & pe : paldata) { diff --git a/src/common/textures/formats/shadertexture.cpp b/src/common/textures/formats/shadertexture.cpp index ce5952fc26..0b69e8acb2 100644 --- a/src/common/textures/formats/shadertexture.cpp +++ b/src/common/textures/formats/shadertexture.cpp @@ -98,7 +98,7 @@ class FBarShader : public FImageSource } } - PalettedPixels CreatePalettedPixels(int conversion) override + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override { PalettedPixels Pix(512); if (conversion == luminance) @@ -118,7 +118,7 @@ class FBarShader : public FImageSource return Pix; } - int CopyPixels(FBitmap *bmp, int conversion) override + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override { bmp->CopyPixelData(0, 0, Pixels, Width, Height, Height, 1, 0, GPalette.GrayRamp.Palette); return 0; diff --git a/src/common/textures/formats/startscreentexture.cpp b/src/common/textures/formats/startscreentexture.cpp index 85710d42f2..155bae19b1 100644 --- a/src/common/textures/formats/startscreentexture.cpp +++ b/src/common/textures/formats/startscreentexture.cpp @@ -60,7 +60,7 @@ class FStartScreenTexture : public FImageSource Height = srcdata.GetHeight(); bUseGamePalette = false; } - int CopyPixels(FBitmap* bmp, int conversion) + int CopyPixels(FBitmap* bmp, int conversion, int frame = 0) override { bmp->Blit(0, 0, info); return 0; diff --git a/src/common/textures/formats/startuptexture.cpp b/src/common/textures/formats/startuptexture.cpp index 8a2a1e602f..c062251d8c 100644 --- a/src/common/textures/formats/startuptexture.cpp +++ b/src/common/textures/formats/startuptexture.cpp @@ -77,30 +77,30 @@ class FStartupTexture : public FImageSource { public: FStartupTexture (int lumpnum); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap *bmp, int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame) override; }; class FNotchTexture : public FImageSource { public: FNotchTexture (int lumpnum, int width, int height); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap *bmp, int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame) override; }; class FStrifeStartupTexture : public FImageSource { public: FStrifeStartupTexture (int lumpnum, int w, int h); - PalettedPixels CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; }; class FStrifeStartupBackground : public FImageSource { public: FStrifeStartupBackground (int lumpnum); - PalettedPixels CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; }; //========================================================================== @@ -164,8 +164,8 @@ FStartupTexture::FStartupTexture (int lumpnum) Height = 480; bUseGamePalette = false; - FileData lump = fileSystem.ReadFile (SourceLump); - const uint8_t *source = (const uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto source = lump.bytes(); // Initialize the bitmap palette. // the palette is static so that the notches can share it. @@ -231,10 +231,10 @@ void PlanarToChunky(T* dest, const uint8_t* src, const T* remap, int width, int // //========================================================================== -PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion) +PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion, int frame) { - FileData lump = fileSystem.ReadFile (SourceLump); - const uint8_t *source = (const uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto source = lump.bytes(); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); @@ -251,10 +251,10 @@ PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion) // //========================================================================== -int FStartupTexture::CopyPixels(FBitmap *bmp, int conversion) +int FStartupTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { - FileData lump = fileSystem.ReadFile (SourceLump); - const uint8_t *source = (const uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto source = lump.bytes(); PlanarToChunky((uint32_t*)bmp->GetPixels(), source + 48, startuppalette32, Width, Height); return 0; } @@ -279,10 +279,10 @@ FNotchTexture::FNotchTexture (int lumpnum, int width, int height) // //========================================================================== -PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion) +PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion, int frame) { - FileData lump = fileSystem.ReadFile (SourceLump); - const uint8_t *source = (const uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto source = lump.bytes(); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); TArray Work(Width*Height, true); @@ -302,10 +302,10 @@ PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion) // //========================================================================== -int FNotchTexture::CopyPixels(FBitmap *bmp, int conversion) +int FNotchTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { - FileData lump = fileSystem.ReadFile (SourceLump); - const uint8_t *source = (const uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto source = lump.bytes(); auto Work = (uint32_t*)bmp->GetPixels(); for(int i = 0; i < Width * Height / 2; i++) @@ -336,10 +336,10 @@ FStrifeStartupTexture::FStrifeStartupTexture (int lumpnum, int w, int h) // //========================================================================== -PalettedPixels FStrifeStartupTexture::CreatePalettedPixels(int conversion) +PalettedPixels FStrifeStartupTexture::CreatePalettedPixels(int conversion, int frame) { - FileData lump = fileSystem.ReadFile (SourceLump); - const uint8_t *source = (const uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (SourceLump); + auto source = lump.bytes(); PalettedPixels Pixels(Width*Height); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), source, Width, Height, Width, remap); @@ -366,7 +366,7 @@ FStrifeStartupBackground::FStrifeStartupBackground (int lumpnum) // //========================================================================== -PalettedPixels FStrifeStartupBackground::CreatePalettedPixels(int conversion) +PalettedPixels FStrifeStartupBackground::CreatePalettedPixels(int conversion, int frame) { TArray source(64000, true); memset(source.Data(), 0xF0, 64000); diff --git a/src/common/textures/formats/stbtexture.cpp b/src/common/textures/formats/stbtexture.cpp index e8d9fe2a0a..827013a583 100644 --- a/src/common/textures/formats/stbtexture.cpp +++ b/src/common/textures/formats/stbtexture.cpp @@ -36,9 +36,8 @@ #define STB_IMAGE_IMPLEMENTATION #define STBI_NO_STDIO // Undefine formats we do not want to support here. -#define STBI_NO_JPEG //#define STBI_NO_PNG we need PNG for 16 bit channel images. Regular ones still use our own, more flexible decoder. -#define STBI_NO_TGA +#define STBI_NO_TGA // we could use that but our own loader has better palette support. #define STBI_NO_PSD #define STBI_NO_HDR #define STBI_NO_PNM @@ -67,8 +66,8 @@ class FStbTexture : public FImageSource public: FStbTexture (int lumpnum, int w, int h); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap *bmp, int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; }; @@ -117,7 +116,7 @@ FStbTexture::FStbTexture (int lumpnum, int w, int h) // //========================================================================== -PalettedPixels FStbTexture::CreatePalettedPixels(int conversion) +PalettedPixels FStbTexture::CreatePalettedPixels(int conversion, int frame) { FBitmap bitmap; bitmap.Create(Width, Height); @@ -156,7 +155,7 @@ PalettedPixels FStbTexture::CreatePalettedPixels(int conversion) // //========================================================================== -int FStbTexture::CopyPixels(FBitmap *bmp, int conversion) +int FStbTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { auto lump = fileSystem.OpenFileReader (SourceLump); int x, y, chan; diff --git a/src/common/textures/formats/tgatexture.cpp b/src/common/textures/formats/tgatexture.cpp index 932eeeaf1d..7577f79ff4 100644 --- a/src/common/textures/formats/tgatexture.cpp +++ b/src/common/textures/formats/tgatexture.cpp @@ -39,6 +39,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" //========================================================================== @@ -79,11 +80,11 @@ class FTGATexture : public FImageSource public: FTGATexture (int lumpnum, TGAHeader *); - int CopyPixels(FBitmap *bmp, int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; protected: void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel); - PalettedPixels CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; }; //========================================================================== @@ -96,7 +97,7 @@ FImageSource *TGAImage_TryCreate(FileReader & file, int lumpnum) { TGAHeader hdr; - if (file.GetLength() < (long)sizeof(hdr)) return NULL; + if (file.GetLength() < (ptrdiff_t)sizeof(hdr)) return NULL; file.Seek(0, FileReader::SeekSet); file.Read(&hdr, sizeof(hdr)); @@ -177,7 +178,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe // //========================================================================== -PalettedPixels FTGATexture::CreatePalettedPixels(int conversion) +PalettedPixels FTGATexture::CreatePalettedPixels(int conversion, int frame) { uint8_t PaletteMap[256]; auto lump = fileSystem.OpenFileReader (SourceLump); @@ -384,7 +385,7 @@ PalettedPixels FTGATexture::CreatePalettedPixels(int conversion) // //=========================================================================== -int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) +int FTGATexture::CopyPixels(FBitmap *bmp, int conversion, int frame) { PalEntry pe[256]; auto lump = fileSystem.OpenFileReader (SourceLump); diff --git a/src/common/textures/formats/webptexture.cpp b/src/common/textures/formats/webptexture.cpp new file mode 100644 index 0000000000..2df7596451 --- /dev/null +++ b/src/common/textures/formats/webptexture.cpp @@ -0,0 +1,148 @@ +/* +** webptexture.cpp +** Texture class for WebP images. +** +**--------------------------------------------------------------------------- +** Copyright 2023 Cacodemon345 +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +** +*/ +#include "webp/decode.h" +#include "webp/mux.h" + +#include "files.h" +#include "filesystem.h" +#include "bitmap.h" +#include "imagehelpers.h" +#include "image.h" +#include "printf.h" + +class FWebPTexture : public FImageSource +{ + +public: + FWebPTexture(int lumpnum, int w, int h, int xoff, int yoff); + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override; +}; + + +FImageSource *WebPImage_TryCreate(FileReader &file, int lumpnum) +{ + int width = 0, height = 0; + int xoff = 0, yoff = 0; + file.Seek(0, FileReader::SeekSet); + + uint8_t header[12]; + if (file.Read(header, 12) != 12) return nullptr; + if (memcmp(header, "RIFF", 4) || memcmp(header + 8, "WEBP", 4)) return nullptr; + + file.Seek(0, FileReader::SeekSet); + auto bytes = file.Read(); + + if (WebPGetInfo(bytes.bytes(), bytes.size(), &width, &height)) + { + WebPData data{ bytes.bytes(), bytes.size() }; + WebPData chunk_data; + auto mux = WebPMuxCreate(&data, 0); + if (mux) + { + const char fourcc[4] = { 'g', 'r', 'A', 'b' }; + if (WebPMuxGetChunk(mux, fourcc, &chunk_data) == WEBP_MUX_OK && chunk_data.size >= 4) + { + xoff = chunk_data.bytes[0] | (chunk_data.bytes[1] << 8); + yoff = chunk_data.bytes[2] | (chunk_data.bytes[3] << 8); + } + WebPMuxDelete(mux); + } + return new FWebPTexture(lumpnum, width, height, xoff, yoff); + } + return nullptr; +} + +FWebPTexture::FWebPTexture(int lumpnum, int w, int h, int xoff, int yoff) + : FImageSource(lumpnum) +{ + Width = w; + Height = h; + LeftOffset = xoff; + TopOffset = yoff; +} + +PalettedPixels FWebPTexture::CreatePalettedPixels(int conversion, int frame) +{ + FBitmap bitmap; + bitmap.Create(Width, Height); + CopyPixels(&bitmap, conversion); + const uint8_t *data = bitmap.GetPixels(); + + uint8_t *dest_p; + int dest_adv = Height; + int dest_rew = Width * Height - 1; + + PalettedPixels Pixels(Width*Height); + dest_p = Pixels.Data(); + + bool doalpha = conversion == luminance; + // Convert the source image from row-major to column-major format and remap it + for (int y = Height; y != 0; --y) + { + for (int x = Width; x != 0; --x) + { + int b = *data++; + int g = *data++; + int r = *data++; + int a = *data++; + if (a < 128) *dest_p = 0; + else *dest_p = ImageHelpers::RGBToPalette(doalpha, r, g, b); + dest_p += dest_adv; + } + dest_p -= dest_rew; + } + return Pixels; +} + +int FWebPTexture::CopyPixels(FBitmap *bmp, int conversion, int frame) +{ + WebPDecoderConfig config; + auto bytes = fileSystem.ReadFile(SourceLump); + + if (WebPInitDecoderConfig(&config) == false) + return 0; + + config.options.no_fancy_upsampling = 0; + config.output.colorspace = MODE_BGRA; + config.output.u.RGBA.rgba = (uint8_t*)bmp->GetPixels(); + config.output.u.RGBA.size = bmp->GetBufferSize(); + config.output.u.RGBA.stride = bmp->GetPitch(); + config.output.is_external_memory = 1; + + (void)WebPDecode(bytes.bytes(), bytes.size(), &config); + + return 0; +} diff --git a/src/common/textures/gametexture.cpp b/src/common/textures/gametexture.cpp index be40632136..755f48b49e 100644 --- a/src/common/textures/gametexture.cpp +++ b/src/common/textures/gametexture.cpp @@ -49,6 +49,7 @@ #include "texturemanager.h" #include "c_cvars.h" #include "hw_material.h" +#include "cmdlib.h" FTexture *CreateBrightmapTexture(FImageSource*); @@ -98,8 +99,8 @@ FGameTexture::~FGameTexture() { if (Base != nullptr) { - FGameTexture* link = fileSystem.GetLinkedTexture(GetSourceLump()); - if (link == this) fileSystem.SetLinkedTexture(GetSourceLump(), nullptr); + FGameTexture* link = TexMan.GetLinkedTexture(GetSourceLump()); + if (link == this) TexMan.SetLinkedTexture(GetSourceLump(), nullptr); } if (SoftwareTexture != nullptr) { @@ -181,7 +182,7 @@ void FGameTexture::AddAutoMaterials() if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done. { FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars()); - auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true); + auto lump = fileSystem.CheckNumForFullName(lookup.GetChars(), false, FileSys::ns_global, true); if (lump != -1) { auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); @@ -198,7 +199,7 @@ void FGameTexture::AddAutoMaterials() if (!this->Layers || this->Layers.get()->*(layer.pointer) == nullptr) // only if no explicit assignment had been done. { FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars()); - auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true); + auto lump = fileSystem.CheckNumForFullName(lookup.GetChars(), false, FileSys::ns_global, true); if (lump != -1) { auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); diff --git a/src/common/textures/gametexture.h b/src/common/textures/gametexture.h index 3eb3740a95..a63dc1b37d 100644 --- a/src/common/textures/gametexture.h +++ b/src/common/textures/gametexture.h @@ -35,6 +35,14 @@ struct SpritePositioningInfo }; +enum class MaterialLayerSampling +{ + Default = -1, + + NearestMipLinear, + LinearMipLinear, +}; + struct MaterialLayers { float Glossiness; @@ -46,6 +54,8 @@ struct MaterialLayers FGameTexture* Roughness; FGameTexture* AmbientOcclusion; FGameTexture* CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES]; + + MaterialLayerSampling CustomShaderTextureSampling[MAX_CUSTOM_HW_SHADER_TEXTURES]; }; enum EGameTexFlags @@ -74,6 +84,8 @@ struct FMaterialLayers RefCountedPtr Roughness; // Roughness texture for PBR RefCountedPtr AmbientOcclusion; // Ambient occlusion texture for PBR RefCountedPtr CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES]; // Custom texture maps for custom hardware shaders + + MaterialLayerSampling CustomShaderTextureSampling[MAX_CUSTOM_HW_SHADER_TEXTURES]; }; // Refactoring helper to allow piece by piece adjustment of the API @@ -235,7 +247,11 @@ class FGameTexture if (lay.AmbientOcclusion) Layers->AmbientOcclusion = lay.AmbientOcclusion->GetTexture(); for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++) { - if (lay.CustomShaderTextures[i]) Layers->CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture(); + if (lay.CustomShaderTextures[i]) + { + Layers->CustomShaderTextureSampling[i] = lay.CustomShaderTextureSampling[i]; + Layers->CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture(); + } } } } diff --git a/src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h b/src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h index 918b904fe2..6e2a931081 100644 --- a/src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h +++ b/src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h @@ -19,6 +19,7 @@ //#ifdef WIN32 //#define DLL __declspec(dllexport) //#else +#pragma once #define DLL //#endif diff --git a/src/common/textures/hires/hqresize.cpp b/src/common/textures/hires/hqresize.cpp index 9a6c42aa25..fc3f13a162 100644 --- a/src/common/textures/hires/hqresize.cpp +++ b/src/common/textures/hires/hqresize.cpp @@ -39,6 +39,7 @@ #ifdef HAVE_MMX #include "hqnx_asm/hqnx_asm.h" #endif +#include #include "xbr/xbrz.h" #include "xbr/xbrz_old.h" #include "parallel_for.h" @@ -304,7 +305,8 @@ static unsigned char *hqNxAsmHelper( void (*hqNxFunction) ( int*, unsigned char* initdone = true; } - HQnX_asm::CImage cImageIn; + auto pImageIn = std::make_unique(); + auto& cImageIn = *pImageIn; cImageIn.SetImage(inputBuffer, inWidth, inHeight, 32); cImageIn.Convert32To17(); diff --git a/src/common/textures/hires/xbr/xbrz.cpp b/src/common/textures/hires/xbr/xbrz.cpp index cd0b7b030d..855205af25 100644 --- a/src/common/textures/hires/xbr/xbrz.cpp +++ b/src/common/textures/hires/xbr/xbrz.cpp @@ -420,7 +420,7 @@ void blendPixel(const Kernel_3x3& ker, return true; //make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes - if (getTopR(blend) != BLEND_NONE && !eq(e, g)) //but support double-blending for 90 corners + if (getTopR(blend) != BLEND_NONE && !eq(e, g)) //but support double-blending for 90° corners return false; if (getBottomL(blend) != BLEND_NONE && !eq(e, c)) return false; diff --git a/src/common/textures/hw_material.cpp b/src/common/textures/hw_material.cpp index 2517c098ed..bbfe61e169 100644 --- a/src/common/textures/hw_material.cpp +++ b/src/common/textures/hw_material.cpp @@ -52,7 +52,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) mShaderIndex = SHADER_Default; sourcetex = tx; auto imgtex = tx->GetTexture(); - mTextureLayers.Push({ imgtex, scaleflags, -1 }); + mTextureLayers.Push({ imgtex, scaleflags, -1, MaterialLayerSampling::Default }); if (tx->GetUseType() == ETextureType::SWCanvas && static_cast(imgtex)->GetColorFormat() == 0) { @@ -83,7 +83,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) { for (auto &texture : { tx->Layers->Normal.get(), tx->Layers->Specular.get() }) { - mTextureLayers.Push({ texture, 0, -1 }); + mTextureLayers.Push({ texture, 0, -1, MaterialLayerSampling::Default }); } mShaderIndex = SHADER_Specular; } @@ -91,7 +91,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) { for (auto &texture : { tx->Layers->Normal.get(), tx->Layers->Metallic.get(), tx->Layers->Roughness.get(), tx->Layers->AmbientOcclusion.get() }) { - mTextureLayers.Push({ texture, 0, -1 }); + mTextureLayers.Push({ texture, 0, -1, MaterialLayerSampling::Default }); } mShaderIndex = SHADER_PBR; } @@ -101,30 +101,30 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) auto placeholder = TexMan.GameByIndex(1); if (tx->Brightmap.get()) { - mTextureLayers.Push({ tx->Brightmap.get(), scaleflags, -1 }); + mTextureLayers.Push({ tx->Brightmap.get(), scaleflags, -1, MaterialLayerSampling::Default }); mLayerFlags |= TEXF_Brightmap; } else { - mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); + mTextureLayers.Push({ placeholder->GetTexture(), 0, -1, MaterialLayerSampling::Default }); } if (tx->Layers && tx->Layers->Detailmap.get()) { - mTextureLayers.Push({ tx->Layers->Detailmap.get(), 0, CLAMP_NONE }); + mTextureLayers.Push({ tx->Layers->Detailmap.get(), 0, CLAMP_NONE, MaterialLayerSampling::Default }); mLayerFlags |= TEXF_Detailmap; } else { - mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); + mTextureLayers.Push({ placeholder->GetTexture(), 0, -1, MaterialLayerSampling::Default }); } if (tx->Layers && tx->Layers->Glowmap.get()) { - mTextureLayers.Push({ tx->Layers->Glowmap.get(), scaleflags, -1 }); + mTextureLayers.Push({ tx->Layers->Glowmap.get(), scaleflags, -1, MaterialLayerSampling::Default}); mLayerFlags |= TEXF_Glowmap; } else { - mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); + mTextureLayers.Push({ placeholder->GetTexture(), 0, -1, MaterialLayerSampling::Default }); } auto index = tx->GetShaderIndex(); @@ -137,10 +137,13 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) { if (tx->Layers) { + size_t index = 0; for (auto& texture : tx->Layers->CustomShaderTextures) { - if (texture == nullptr) continue; - mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable. + if (texture != nullptr) + { + mTextureLayers.Push({ texture.get(), 0, -1, tx->Layers->CustomShaderTextureSampling[index++]}); // scalability should be user-definable. + } } } mShaderIndex = index; diff --git a/src/common/textures/hw_material.h b/src/common/textures/hw_material.h index 20c38b3326..e7509bca20 100644 --- a/src/common/textures/hw_material.h +++ b/src/common/textures/hw_material.h @@ -13,6 +13,7 @@ struct MaterialLayerInfo FTexture* layerTexture; int scaleFlags; int clampflags; + MaterialLayerSampling layerFiltering; }; //=========================================================================== @@ -55,9 +56,9 @@ class FMaterial mTextureLayers.Resize(1); } - void AddTextureLayer(FTexture *tex, bool allowscale) + void AddTextureLayer(FTexture *tex, bool allowscale, MaterialLayerSampling filter) { - mTextureLayers.Push({ tex, allowscale }); + mTextureLayers.Push({ tex, allowscale, -1, filter }); } int NumLayers() const @@ -66,7 +67,11 @@ class FMaterial } IHardwareTexture *GetLayer(int i, int translation, MaterialLayerInfo **pLayer = nullptr) const; - + + MaterialLayerSampling GetLayerFilter(int index) const + { + return mTextureLayers[index].layerFiltering; + } static FMaterial *ValidateTexture(FGameTexture * tex, int scaleflags, bool create = true); const TArray &GetLayerArray() const diff --git a/src/common/textures/hw_texcontainer.h b/src/common/textures/hw_texcontainer.h index a4ff33f93f..e8777b00e1 100644 --- a/src/common/textures/hw_texcontainer.h +++ b/src/common/textures/hw_texcontainer.h @@ -3,9 +3,9 @@ #include "tarray.h" #include "hw_ihwtexture.h" #include "palettecontainer.h" +#include "hw_ihwtexture.h" // Note: this cannot be a forward declaration due to the inlined delete statement below. struct FTextureBuffer; -class IHardwareTexture; enum ECreateTexBufferFlags { @@ -34,7 +34,7 @@ class FHardwareTextureContainer void Delete() { - if (hwTexture) delete hwTexture; + delete hwTexture; hwTexture = nullptr; } @@ -137,7 +137,7 @@ class FHardwareTextureContainer for (int i = hwTex_Translated.Size()-1; i>= 0; i--) { auto& tt = hwTex_Translated[i]; - if (!tt.isMarkedForPreache()) + if (!tt.isMarkedForPreache()) { hwTex_Translated.Delete(i); } @@ -148,11 +148,11 @@ class FHardwareTextureContainer { for (auto& tt : hwDefTex) { - if (!tt.isMarkedForPreache()) tt.MarkForPrecache(false); + tt.MarkForPrecache(false); } for (auto& tt : hwTex_Translated) { - if (!tt.isMarkedForPreache()) tt.MarkForPrecache(false); + tt.MarkForPrecache(false); } } diff --git a/src/common/textures/image.cpp b/src/common/textures/image.cpp index b32634948b..83f7450ebe 100644 --- a/src/common/textures/image.cpp +++ b/src/common/textures/image.cpp @@ -51,6 +51,7 @@ struct PrecacheDataPaletted PalettedPixels Pixels; int RefCount; int ImageID; + int Frame; }; struct PrecacheDataRgba @@ -59,6 +60,7 @@ struct PrecacheDataRgba int TransInfo; int RefCount; int ImageID; + int Frame; }; // TMap doesn't handle this kind of data well. std::map neither. The linear search is still faster, even for a few 100 entries because it doesn't have to access the heap as often.. @@ -71,21 +73,21 @@ TArray precacheDataRgba; // //=========================================================================== -PalettedPixels FImageSource::CreatePalettedPixels(int conversion) +PalettedPixels FImageSource::CreatePalettedPixels(int conversion, int frame) { PalettedPixels Pixels(Width * Height); memset(Pixels.Data(), 0, Width * Height); return Pixels; } -PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion) +PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion, int frame) { PalettedPixels ret; auto imageID = ImageID; // Do we have this image in the cache? - unsigned index = conversion != normal? UINT_MAX : precacheDataPaletted.FindEx([=](PrecacheDataPaletted &entry) { return entry.ImageID == imageID; }); + unsigned index = conversion != normal? UINT_MAX : precacheDataPaletted.FindEx([=](PrecacheDataPaletted &entry) { return entry.ImageID == imageID && entry.Frame == frame; }); if (index < precacheDataPaletted.Size()) { auto cache = &precacheDataPaletted[index]; @@ -115,7 +117,7 @@ PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion) { // This is either the only copy needed or some access outside the caching block. In these cases create a new one and directly return it. //Printf("returning fresh copy of %s\n", name.GetChars()); - return CreatePalettedPixels(conversion); + return CreatePalettedPixels(conversion, frame); } else { @@ -126,16 +128,16 @@ PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion) pdp->ImageID = imageID; pdp->RefCount = info->second - 1; info->second = 0; - pdp->Pixels = CreatePalettedPixels(normal); + pdp->Pixels = CreatePalettedPixels(normal, frame); ret.Pixels.Set(pdp->Pixels.Data(), pdp->Pixels.Size()); } } return ret; } -TArray FImageSource::GetPalettedPixels(int conversion) +TArray FImageSource::GetPalettedPixels(int conversion, int frame) { - auto pix = GetCachedPalettedPixels(conversion); + auto pix = GetCachedPalettedPixels(conversion, frame); if (pix.ownsPixels()) { // return the pixel store of the returned data directly if this was the last reference. @@ -165,19 +167,19 @@ TArray FImageSource::GetPalettedPixels(int conversion) // //=========================================================================== -int FImageSource::CopyPixels(FBitmap *bmp, int conversion) +int FImageSource::CopyPixels(FBitmap *bmp, int conversion, int frame) { if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. PalEntry *palette = GPalette.BaseColors; - auto ppix = CreatePalettedPixels(conversion); + auto ppix = CreatePalettedPixels(conversion, frame); bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, palette, nullptr); return 0; } -int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap) +int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap, int frame) { - auto ppix = CreatePalettedPixels(normal); + auto ppix = CreatePalettedPixels(normal, frame); bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, remap, nullptr); return 0; } @@ -188,26 +190,31 @@ int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap) // //========================================================================== -FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int *ptrans) +FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int *ptrans, int frame) { FBitmap ret; int trans = -1; auto imageID = ImageID; + if (NumOfFrames == 1 && frame == 1) + { + frame = 0; + } + if (remap != nullptr) { // Remapped images are never run through the cache because they would complicate matters too much for very little gain. // Translated images are normally sprites which normally just consist of a single image and use no composition. // Additionally, since translation requires the base palette, the really time consuming stuff will never be subjected to it. ret.Create(Width, Height); - trans = CopyTranslatedPixels(&ret, remap); + trans = CopyTranslatedPixels(&ret, remap, frame); } else { if (conversion == luminance) conversion = normal; // luminance has no meaning for true color. // Do we have this image in the cache? - unsigned index = conversion != normal? UINT_MAX : precacheDataRgba.FindEx([=](PrecacheDataRgba &entry) { return entry.ImageID == imageID; }); + unsigned index = conversion != normal? UINT_MAX : precacheDataRgba.FindEx([=](PrecacheDataRgba &entry) { return entry.ImageID == imageID && entry.Frame == frame; }); if (index < precacheDataRgba.Size()) { auto cache = &precacheDataRgba[index]; @@ -230,7 +237,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int // This should never happen if the function is implemented correctly //Printf("something bad happened for %s, refcount = %d\n", name.GetChars(), cache->RefCount); ret.Create(Width, Height); - trans = CopyPixels(&ret, normal); + trans = CopyPixels(&ret, normal, frame); } } else @@ -242,7 +249,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int // This is either the only copy needed or some access outside the caching block. In these cases create a new one and directly return it. //Printf("returning fresh copy of %s\n", name.GetChars()); ret.Create(Width, Height); - trans = CopyPixels(&ret, conversion); + trans = CopyPixels(&ret, conversion, frame); } else { @@ -251,10 +258,11 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int PrecacheDataRgba *pdr = &precacheDataRgba[precacheDataRgba.Reserve(1)]; pdr->ImageID = imageID; + pdr->Frame = frame; pdr->RefCount = info->first - 1; info->first = 0; pdr->Pixels.Create(Width, Height); - trans = pdr->TransInfo = CopyPixels(&pdr->Pixels, normal); + trans = pdr->TransInfo = CopyPixels(&pdr->Pixels, normal, frame); ret.Copy(pdr->Pixels, false); } } @@ -317,11 +325,12 @@ struct TexCreateInfo FImageSource *IMGZImage_TryCreate(FileReader &, int lumpnum); FImageSource *PNGImage_TryCreate(FileReader &, int lumpnum); -FImageSource *JPEGImage_TryCreate(FileReader &, int lumpnum); FImageSource *DDSImage_TryCreate(FileReader &, int lumpnum); FImageSource *PCXImage_TryCreate(FileReader &, int lumpnum); FImageSource *TGAImage_TryCreate(FileReader &, int lumpnum); FImageSource *StbImage_TryCreate(FileReader &, int lumpnum); +FImageSource *QOIImage_TryCreate(FileReader &, int lumpnum); +FImageSource *WebPImage_TryCreate(FileReader &, int lumpnum); FImageSource *AnmImage_TryCreate(FileReader &, int lumpnum); FImageSource *RawPageImage_TryCreate(FileReader &, int lumpnum); FImageSource *FlatImage_TryCreate(FileReader &, int lumpnum); @@ -338,10 +347,11 @@ FImageSource * FImageSource::GetImage(int lumpnum, bool isflat) static TexCreateInfo CreateInfo[] = { { IMGZImage_TryCreate, false }, { PNGImage_TryCreate, false }, - { JPEGImage_TryCreate, false }, { DDSImage_TryCreate, false }, { PCXImage_TryCreate, false }, { StbImage_TryCreate, false }, + { QOIImage_TryCreate, false }, + { WebPImage_TryCreate, false }, { TGAImage_TryCreate, false }, { AnmImage_TryCreate, false }, { StartupPageImage_TryCreate, false }, diff --git a/src/common/textures/image.h b/src/common/textures/image.h index 5be8525497..72b5ca9df5 100644 --- a/src/common/textures/image.h +++ b/src/common/textures/image.h @@ -5,20 +5,24 @@ #include "bitmap.h" #include "memarena.h" +#ifndef MAKE_ID +#ifndef __BIG_ENDIAN__ +#define MAKE_ID(a,b,c,d) ((uint32_t)((a)|((b)<<8)|((c)<<16)|((d)<<24))) +#else +#define MAKE_ID(a,b,c,d) ((uint32_t)((d)|((c)<<8)|((b)<<16)|((a)<<24))) +#endif +#endif + +using std::min; +using std::max; +using std::clamp; + + class FImageSource; using PrecacheInfo = TMap>; extern FMemArena ImageArena; -// Doom patch format header -struct patch_t -{ - int16_t width; // bounding box size - int16_t height; - int16_t leftoffset; // pixels to the left of origin - int16_t topoffset; // pixels below the origin - uint32_t columnofs[1]; // only [width] used -}; - +// Pixel store wrapper that can either own the pixels itself or refer to an external store. struct PalettedPixels { friend class FImageSource; @@ -67,12 +71,13 @@ class FImageSource int LeftOffset = 0, TopOffset = 0; // Offsets stored in the image. bool bUseGamePalette = false; // true if this is an image without its own color set. int ImageID = -1; + int NumOfFrames = 1; // Internal image creation functions. All external access should go through the cache interface, // so that all code can benefit from future improvements to that. - virtual PalettedPixels CreatePalettedPixels(int conversion); - int CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap); + virtual PalettedPixels CreatePalettedPixels(int conversion, int frame = 0); + int CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap, int frame = 0); public: @@ -101,19 +106,25 @@ class FImageSource // 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture. // Either returns a reference to the cache, or a newly created item. The return of this has to be considered transient. If you need to store the result, use GetPalettedPixels - PalettedPixels GetCachedPalettedPixels(int conversion); + PalettedPixels GetCachedPalettedPixels(int conversion, int frame = 0); // tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy. - TArray GetPalettedPixels(int conversion); + TArray GetPalettedPixels(int conversion, int frame = 0); - virtual int CopyPixels(FBitmap* bmp, int conversion); + virtual int CopyPixels(FBitmap* bmp, int conversion, int frame = 0); - FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr); + FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr, int frame = 0); static void ClearImages() { ImageArena.FreeAll(); ImageForLump.Clear(); NextID = 0; } static FImageSource * GetImage(int lumpnum, bool checkflat); + // Frame functions + + // Gets number of frames. + int GetNumOfFrames() { return NumOfFrames; } + // Gets duration of frame in miliseconds. + virtual int GetDurationOfFrame(int frame) { return 1000; } // Conversion option enum EType @@ -180,8 +191,8 @@ class FBuildTexture : public FImageSource { public: FBuildTexture(const FString& pathprefix, int tilenum, const uint8_t* pixels, FRemapTable* translation, int width, int height, int left, int top); - PalettedPixels CreatePalettedPixels(int conversion) override; - int CopyPixels(FBitmap* bmp, int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override; + int CopyPixels(FBitmap* bmp, int conversion, int frame = 0) override; protected: const uint8_t* RawPixels; @@ -191,4 +202,4 @@ class FBuildTexture : public FImageSource class FTexture; -FTexture* CreateImageTexture(FImageSource* img) noexcept; +FTexture* CreateImageTexture(FImageSource* img, int frame = 0) noexcept; diff --git a/src/common/textures/imagetexture.cpp b/src/common/textures/imagetexture.cpp index d94ff80029..233cf4b098 100644 --- a/src/common/textures/imagetexture.cpp +++ b/src/common/textures/imagetexture.cpp @@ -47,10 +47,11 @@ // //========================================================================== -FImageTexture::FImageTexture(FImageSource *img) noexcept +FImageTexture::FImageTexture(FImageSource *img, int frame) noexcept : FTexture(img? img->LumpNum() : 0) { mImage = img; + TexFrame = frame; if (img != nullptr) { SetFromImage(); @@ -79,7 +80,7 @@ void FImageTexture::SetFromImage() FBitmap FImageTexture::GetBgraBitmap(const PalEntry *p, int *trans) { - return mImage->GetCachedBitmap(p, bNoRemap0? FImageSource::noremap0 : FImageSource::normal, trans); + return mImage->GetCachedBitmap(p, bNoRemap0? FImageSource::noremap0 : FImageSource::normal, trans, TexFrame); } //=========================================================================== @@ -90,7 +91,7 @@ FBitmap FImageTexture::GetBgraBitmap(const PalEntry *p, int *trans) TArray FImageTexture::Get8BitPixels(bool alpha) { - return mImage->GetPalettedPixels(alpha? FImageSource::luminance : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal); + return mImage->GetPalettedPixels(alpha? FImageSource::luminance : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal, TexFrame); } //=========================================================================== @@ -113,8 +114,8 @@ bool FImageTexture::DetermineTranslucency() } -FTexture* CreateImageTexture(FImageSource* img) noexcept +FTexture* CreateImageTexture(FImageSource* img, int frame) noexcept { - return new FImageTexture(img); + return new FImageTexture(img, frame); } diff --git a/src/common/textures/m_png.cpp b/src/common/textures/m_png.cpp index 8467a5d424..331b35e200 100644 --- a/src/common/textures/m_png.cpp +++ b/src/common/textures/m_png.cpp @@ -36,17 +36,19 @@ #include #include -#include +#include #include #ifdef _MSC_VER #include // for alloca() #endif -#include "basics.h" #include "m_crc32.h" #include "m_swap.h" +#if __has_include("c_cvars.h") #include "c_cvars.h" +#endif #include "m_png.h" +#include "basics.h" // MACROS ------------------------------------------------------------------ @@ -103,6 +105,8 @@ static void UnpackPixels (int width, int bytesPerRow, int bitdepth, const uint8_ // PUBLIC DATA DEFINITIONS ------------------------------------------------- +// allow this to compile without CVARs. +#if __has_include("c_cvars.h") CUSTOM_CVAR(Int, png_level, 5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (self < 0) @@ -111,6 +115,10 @@ CUSTOM_CVAR(Int, png_level, 5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) self = 9; } CVAR(Float, png_gamma, 0.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +#else +const int png_level = 5; +const float png_gamma = 0; +#endif // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -502,7 +510,8 @@ bool M_ReadIDAT (FileReader &file, uint8_t *buffer, int width, int height, int p { i += bytesPerRowOut * 2; } - inputLine = (Byte *)alloca (i); + TArray inputArray(i, true); + inputLine = inputArray.data(); adam7buff[0] = inputLine + 4 + bytesPerRowOut; adam7buff[1] = adam7buff[0] + bytesPerRowOut; adam7buff[2] = adam7buff[1] + bytesPerRowOut; @@ -917,7 +926,8 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height temprow[i] = &temprow_storage[temprow_size * i]; } - Byte buffer[PNG_WRITE_SIZE]; + TArray array(PNG_WRITE_SIZE, true); + auto buffer = array.data(); z_stream stream; int err; int y; diff --git a/src/common/textures/m_png.h b/src/common/textures/m_png.h index 2f52a1fcf5..426e4d9828 100644 --- a/src/common/textures/m_png.h +++ b/src/common/textures/m_png.h @@ -37,7 +37,6 @@ #include "zstring.h" #include "files.h" #include "palentry.h" -#include "basics.h" // Screenshot buffer image data types enum ESSType @@ -47,7 +46,6 @@ enum ESSType SS_BGRA }; -class FileWriter; // PNG Writing -------------------------------------------------------------- // Start writing an 8-bit palettized PNG file. @@ -82,13 +80,13 @@ struct PNGHandle uint32_t Size; }; - FileReader File; + FileSys::FileReader File; bool bDeleteFilePtr; TArray Chunks; TArray TextChunks; unsigned int ChunkPt; - PNGHandle(FileReader &file); + PNGHandle(FileSys::FileReader &file); ~PNGHandle(); }; @@ -96,7 +94,7 @@ struct PNGHandle // the signature, but also checking for the IEND chunk. CRC checking of // each chunk is not done. If it is valid, you get a PNGHandle to pass to // the following functions. -PNGHandle *M_VerifyPNG (FileReader &file); +PNGHandle *M_VerifyPNG (FileSys::FileReader &file); // Finds a chunk in a PNG file. The file pointer will be positioned at the // beginning of the chunk data, and its length will be returned. A return @@ -115,7 +113,7 @@ bool M_GetPNGText (PNGHandle *png, const char *keyword, char *buffer, size_t buf // The file must be positioned at the start of the first IDAT. It reads // image data into the provided buffer. Returns true on success. -bool M_ReadIDAT (FileReader &file, uint8_t *buffer, int width, int height, int pitch, +bool M_ReadIDAT (FileSys::FileReader &file, uint8_t *buffer, int width, int height, int pitch, uint8_t bitdepth, uint8_t colortype, uint8_t interlace, unsigned int idatlen); diff --git a/src/common/textures/multipatchtexturebuilder.cpp b/src/common/textures/multipatchtexturebuilder.cpp index 2a8b77feaf..25ea5bbefa 100644 --- a/src/common/textures/multipatchtexturebuilder.cpp +++ b/src/common/textures/multipatchtexturebuilder.cpp @@ -44,6 +44,7 @@ #include "image.h" #include "formats/multipatchtexture.h" #include "texturemanager.h" +#include "m_swap.h" // On the Alpha, accessing the shorts directly if they aren't aligned on a @@ -136,7 +137,7 @@ struct FPatchLookup void FMultipatchTextureBuilder::MakeTexture(BuildInfo &buildinfo, ETextureType usetype) { - buildinfo.texture = new FGameTexture(nullptr, buildinfo.Name); + buildinfo.texture = new FGameTexture(nullptr, buildinfo.Name.GetChars()); buildinfo.texture->SetUseType(usetype); buildinfo.texture->SetSize(buildinfo.Width, buildinfo.Height); buildinfo.texture->SetOffsets(0, buildinfo.LeftOffset[0], buildinfo.TopOffset[0]); // These are needed for construction of other multipatch textures. @@ -284,7 +285,7 @@ void FMultipatchTextureBuilder::AddTexturesLump(const void *lumpdata, int lumpsi } // Check whether the amount of names reported is correct. - int lumplength = fileSystem.FileLength(patcheslump); + uint32_t lumplength = (uint32_t)fileSystem.FileLength(patcheslump); if (numpatches > uint32_t((lumplength - 4) / 8)) { Printf("PNAMES lump is shorter than required (%u entries reported but only %d bytes (%d entries) long\n", @@ -372,7 +373,7 @@ void FMultipatchTextureBuilder::AddTexturesLump(const void *lumpdata, int lumpsi int j; for (j = (int)TexMan.NumTextures() - 1; j >= firstdup; --j) { - if (strnicmp(TexMan.GameByIndex(j)->GetName(), (const char *)maptex + offset, 8) == 0) + if (strnicmp(TexMan.GameByIndex(j)->GetName().GetChars(), (const char *)maptex + offset, 8) == 0) break; } if (j + 1 == firstdup) @@ -396,13 +397,13 @@ void FMultipatchTextureBuilder::AddTexturesLumps(int lump1, int lump2, int patch if (lump1 >= 0) { - FileData texdir = fileSystem.ReadFile(lump1); - AddTexturesLump(texdir.GetMem(), fileSystem.FileLength(lump1), lump1, patcheslump, firstdup, true); + auto texdir = fileSystem.ReadFile(lump1); + AddTexturesLump(texdir.data(), (int)fileSystem.FileLength(lump1), lump1, patcheslump, firstdup, true); } if (lump2 >= 0) { - FileData texdir = fileSystem.ReadFile(lump2); - AddTexturesLump(texdir.GetMem(), fileSystem.FileLength(lump2), lump2, patcheslump, firstdup, false); + auto texdir = fileSystem.ReadFile(lump2); + AddTexturesLump(texdir.data(), (int)fileSystem.FileLength(lump2), lump2, patcheslump, firstdup, false); } } @@ -777,11 +778,11 @@ void FMultipatchTextureBuilder::ResolvePatches(BuildInfo &buildinfo) { for (unsigned i = 0; i < buildinfo.Inits.Size(); i++) { - FTextureID texno = TexMan.CheckForTexture(buildinfo.Inits[i].TexName, buildinfo.Inits[i].UseType); + FTextureID texno = TexMan.CheckForTexture(buildinfo.Inits[i].TexName.GetChars(), buildinfo.Inits[i].UseType); if (texno == buildinfo.texture->GetID()) // we found ourselves. Try looking for another one with the same name which is not a multipatch texture itself. { TArray list; - TexMan.ListTextures(buildinfo.Inits[i].TexName, list, true); + TexMan.ListTextures(buildinfo.Inits[i].TexName.GetChars(), list, true); for (int ii = list.Size() - 1; ii >= 0; ii--) { auto gtex = TexMan.GetGameTexture(list[ii]); diff --git a/src/common/textures/texture.cpp b/src/common/textures/texture.cpp index db922a7b51..af335ca31e 100644 --- a/src/common/textures/texture.cpp +++ b/src/common/textures/texture.cpp @@ -50,6 +50,7 @@ #include "c_cvars.h" #include "imagehelpers.h" #include "v_video.h" +#include "v_font.h" // Wrappers to keep the definitions of these classes out of here. IHardwareTexture* CreateHardwareTexture(int numchannels); @@ -321,7 +322,6 @@ bool FTexture::ProcessData(unsigned char* buffer, int w, int h, bool ispatch) // Initializes the buffer for the texture data // //=========================================================================== -void V_ApplyLuminosityTranslation(int translation, uint8_t *buffer, int size); FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags) { @@ -354,20 +354,32 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags) if (!checkonly) { - buffer = new unsigned char[W * (H + 1) * 4]; - memset(buffer, 0, W * (H + 1) * 4); - auto remap = translation <= 0 || IsLuminosityTranslation(translation) ? nullptr : GPalette.TranslationToTable(translation); if (remap && remap->Inactive) remap = nullptr; if (remap) translation = remap->Index; - FBitmap bmp(buffer, W * 4, W, H); int trans; auto Pixels = GetBgraBitmap(remap ? remap->Palette : nullptr, &trans); - bmp.Blit(exx, exx, Pixels); + + if(!exx && Pixels.ClipRect.x == 0 && Pixels.ClipRect.y == 0 && Pixels.ClipRect.width == Pixels.Width && Pixels.ClipRect.height == Pixels.Height && (Pixels.FreeBuffer || !IsLuminosityTranslation(translation))) + { + buffer = Pixels.data; + result.mFreeBuffer = Pixels.FreeBuffer; + Pixels.FreeBuffer = false; + } + else + { + buffer = new unsigned char[W * (H + 1) * 4]; + memset(buffer, 0, W * (H + 1) * 4); + + FBitmap bmp(buffer, W * 4, W, H); + + bmp.Blit(exx, exx, Pixels); + } + if (IsLuminosityTranslation(translation)) { - V_ApplyLuminosityTranslation(translation, buffer, W * H); + V_ApplyLuminosityTranslation(LuminosityTranslationDesc::fromInt(translation), buffer, W * H); } if (remap == nullptr) diff --git a/src/common/textures/textureid.h b/src/common/textures/textureid.h index e30b4e86ad..2d3a226f52 100644 --- a/src/common/textures/textureid.h +++ b/src/common/textures/textureid.h @@ -1,5 +1,8 @@ #pragma once +#include +#include "tarray.h" + enum class ETextureType : uint8_t { Any, @@ -28,6 +31,7 @@ class FTextureID public: FTextureID() = default; + FTextureID(std::nullptr_t) : texnum(0) {} bool isNull() const { return texnum == 0; } bool isValid() const { return texnum > 0; } bool Exists() const { return texnum >= 0; } @@ -45,7 +49,7 @@ class FTextureID bool operator > (FTextureID other) const { return texnum > other.texnum; } protected: - FTextureID(int num) { texnum = num; } + constexpr FTextureID(int num) : texnum(num) { } private: int texnum; }; @@ -53,13 +57,21 @@ class FTextureID class FNullTextureID : public FTextureID { public: - FNullTextureID() : FTextureID(0) {} + constexpr FNullTextureID() : FTextureID(0) {} }; // This is for the script interface which needs to do casts from int to texture. class FSetTextureID : public FTextureID { public: - FSetTextureID(int v) : FTextureID(v) {} + constexpr FSetTextureID(int v) : FTextureID(v) {} }; +template<> struct THashTraits +{ + + hash_t Hash(const FTextureID key) { return (hash_t)key.GetIndex(); } + + // Compares two keys, returning zero if they are the same. + int Compare(const FTextureID left, const FTextureID right) { return left != right; } +}; diff --git a/src/common/textures/texturemanager.cpp b/src/common/textures/texturemanager.cpp index 94aa40de1d..1173f61be0 100644 --- a/src/common/textures/texturemanager.cpp +++ b/src/common/textures/texturemanager.cpp @@ -47,7 +47,10 @@ #include "vectors.h" #include "animtexture.h" #include "formats/multipatchtexture.h" +#include "basics.h" +#include "cmdlib.h" +using namespace FileSys; FTextureManager TexMan; @@ -175,7 +178,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset auto tex = Textures[i].Texture; - if (stricmp (tex->GetName(), name) == 0 ) + if (tex->GetName().CompareNoCase(name) == 0 ) { // If we look for short names, we must ignore any long name texture. if ((flags & TEXMAN_ShortNameOnly) && tex->isFullNameTexture()) @@ -244,11 +247,11 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset // Any graphic being placed in the zip's root directory can not be found by this. if (strchr(name, '/') || (flags & TEXMAN_ForceLookup)) { - FGameTexture *const NO_TEXTURE = (FGameTexture*)-1; + FGameTexture *const NO_TEXTURE = (FGameTexture*)-1; // marker for lumps we already checked that do not map to a texture. int lump = fileSystem.CheckNumForFullName(name); if (lump >= 0) { - FGameTexture *tex = fileSystem.GetLinkedTexture(lump); + FGameTexture *tex = GetLinkedTexture(lump); if (tex == NO_TEXTURE) return FTextureID(-1); if (tex != NULL) return tex->GetID(); if (flags & TEXMAN_DontCreate) return FTextureID(-1); // we only want to check, there's no need to create a texture if we don't have one yet. @@ -256,13 +259,13 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset if (tex != NULL) { tex->AddAutoMaterials(); - fileSystem.SetLinkedTexture(lump, tex); + SetLinkedTexture(lump, tex); return AddGameTexture(tex); } else { // mark this lump as having no valid texture so that we don't have to retry creating one later. - fileSystem.SetLinkedTexture(lump, NO_TEXTURE); + SetLinkedTexture(lump, NO_TEXTURE); } } } @@ -303,7 +306,7 @@ int FTextureManager::ListTextures (const char *name, TArray &list, b { auto tex = Textures[i].Texture; - if (stricmp (tex->GetName(), name) == 0) + if (tex->GetName().CompareNoCase(name) == 0) { auto texUseType = tex->GetUseType(); // NULL textures must be ignored. @@ -375,7 +378,7 @@ FGameTexture *FTextureManager::FindGameTexture(const char *texname, ETextureType bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitute, int locmode) { uint32_t langtable = 0; - if (*substitute == '$') substitute = GStrings.GetString(substitute+1, &langtable); + if (*substitute == '$') substitute = GStrings.CheckString(substitute+1, &langtable); else return true; // String literals from the source data should never override graphics from the same definition. if (substitute == nullptr) return true; // The text does not exist. @@ -419,7 +422,7 @@ FTextureID FTextureManager::AddGameTexture (FGameTexture *texture, bool addtohas // Textures without name can't be looked for if (addtohash && texture->GetName().IsNotEmpty()) { - bucket = int(MakeKey (texture->GetName()) % HASH_SIZE); + bucket = int(MakeKey (texture->GetName().GetChars()) % HASH_SIZE); hash = HashFirst[bucket]; } else @@ -451,13 +454,13 @@ FTextureID FTextureManager::CreateTexture (int lumpnum, ETextureType usetype) { FString str; if (!usefullnames) - fileSystem.GetFileShortName(str, lumpnum); + str = fileSystem.GetFileShortName(lumpnum); else { auto fn = fileSystem.GetFileFullName(lumpnum); str = ExtractFileBase(fn); } - auto out = MakeGameTexture(CreateTextureFromLump(lumpnum, usetype == ETextureType::Flat), str, usetype); + auto out = MakeGameTexture(CreateTextureFromLump(lumpnum, usetype == ETextureType::Flat), str.GetChars(), usetype); if (out != NULL) { @@ -485,7 +488,7 @@ FTextureID FTextureManager::CreateTexture (int lumpnum, ETextureType usetype) } else { - Printf (TEXTCOLOR_ORANGE "Invalid data encountered for texture %s\n", fileSystem.GetFileFullPath(lumpnum).GetChars()); + Printf (TEXTCOLOR_ORANGE "Invalid data encountered for texture %s\n", fileSystem.GetFileFullPath(lumpnum).c_str()); return FTextureID(-1); } } @@ -498,9 +501,9 @@ FTextureID FTextureManager::CreateTexture (int lumpnum, ETextureType usetype) // //========================================================================== -void FTextureManager::ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free) +void FTextureManager::ReplaceTexture (FTextureID texid, FGameTexture *newtexture, bool free) { - int index = picnum.GetIndex(); + int index = texid.GetIndex(); if (unsigned(index) >= Textures.Size()) return; @@ -511,7 +514,7 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FGameTexture *newtextur auto oldtexture = Textures[index].Texture; - newtexture->SetName(oldtexture->GetName()); + newtexture->SetName(oldtexture->GetName().GetChars()); newtexture->SetUseType(oldtexture->GetUseType()); Textures[index].Texture = newtexture; newtexture->SetID(oldtexture->GetID()); @@ -563,7 +566,6 @@ void FTextureManager::AddGroup(int wadnum, int ns, ETextureType usetype) { int firsttx = fileSystem.GetFirstEntry(wadnum); int lasttx = fileSystem.GetLastEntry(wadnum); - FString Name; if (!usefullnames) { @@ -574,17 +576,16 @@ void FTextureManager::AddGroup(int wadnum, int ns, ETextureType usetype) for (; firsttx <= lasttx; ++firsttx) { + auto Name = fileSystem.GetFileShortName(firsttx); if (fileSystem.GetFileNamespace(firsttx) == ns) { - fileSystem.GetFileShortName(Name, firsttx); - if (fileSystem.CheckNumForName(Name, ns) == firsttx) { CreateTexture(firsttx, usetype); } progressFunc(); } - else if (ns == ns_flats && fileSystem.GetFileFlags(firsttx) & LUMPF_MAYBEFLAT) + else if (ns == ns_flats && fileSystem.GetFileFlags(firsttx) & RESFF_MAYBEFLAT) { if (fileSystem.CheckNumForName(Name, ns) < firsttx) { @@ -618,7 +619,6 @@ void FTextureManager::AddHiresTextures (int wadnum) int firsttx = fileSystem.GetFirstEntry(wadnum); int lasttx = fileSystem.GetLastEntry(wadnum); - FString Name; TArray tlist; if (firsttx == -1 || lasttx == -1) @@ -630,7 +630,7 @@ void FTextureManager::AddHiresTextures (int wadnum) { if (fileSystem.GetFileNamespace(firsttx) == ns_hires) { - fileSystem.GetFileShortName (Name, firsttx); + auto Name = fileSystem.GetFileShortName(firsttx); if (fileSystem.CheckNumForName (Name, ns_hires) == firsttx) { @@ -682,15 +682,15 @@ void FTextureManager::AddHiresTextures (int wadnum) void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build) { - int remapLump, lastLump; + int texLump, lastLump; lastLump = 0; - while ((remapLump = fileSystem.FindLump(lumpname, &lastLump)) != -1) + while ((texLump = fileSystem.FindLump(lumpname, &lastLump)) != -1) { - if (fileSystem.GetFileContainer(remapLump) == wadnum) + if (fileSystem.GetFileContainer(texLump) == wadnum) { - ParseTextureDef(remapLump, build); + ParseTextureDef(texLump, build); } } } @@ -793,7 +793,7 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build if (lumpnum>=0) { - auto newtex = MakeGameTexture(CreateTextureFromLump(lumpnum), src, ETextureType::Override); + auto newtex = MakeGameTexture(CreateTextureFromLump(lumpnum), src.GetChars(), ETextureType::Override); if (newtex != NULL) { @@ -801,7 +801,7 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build newtex->SetWorldPanning(true); newtex->SetDisplaySize((float)width, (float)height); - FTextureID oldtex = TexMan.CheckForTexture(src, ETextureType::MiscPatch); + FTextureID oldtex = TexMan.CheckForTexture(src.GetChars(), ETextureType::MiscPatch); if (oldtex.isValid()) { ReplaceTexture(oldtex, newtex, true); @@ -964,15 +964,14 @@ void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &b for (int i= firsttx; i <= lasttx; i++) { bool skin = false; - FString Name; - fileSystem.GetFileShortName(Name, i); + auto Name = fileSystem.GetFileShortName(i); // Ignore anything not in the global namespace int ns = fileSystem.GetFileNamespace(i); if (ns == ns_global) { // In Zips all graphics must be in a separate namespace. - if (fileSystem.GetFileFlags(i) & LUMPF_FULLPATH) continue; + if (fileSystem.GetFileFlags(i) & RESFF_FULLPATH) continue; // Ignore lumps with empty names. if (fileSystem.CheckFileName(i, "")) continue; @@ -997,7 +996,7 @@ void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &b if (iwad) { // We need to make an exception for font characters of the SmallFont coming from the IWAD to be able to construct the original font. - if (Name.IndexOf("STCFN") != 0 && Name.IndexOf("FONTA") != 0) continue; + if (strncmp(Name, "STCFN", 5) != 0 && strncmp(Name, "FONTA", 5) != 0) continue; force = true; } else continue; @@ -1013,7 +1012,7 @@ void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &b if (iwad) { // We need to make an exception for font characters of the SmallFont coming from the IWAD to be able to construct the original font. - if (Name.IndexOf("STCFN") != 0 && Name.IndexOf("FONTA") != 0) continue; + if (strncmp(Name, "STCFN", 5) != 0 && strncmp(Name, "FONTA", 5) != 0) continue; } else continue; } @@ -1110,7 +1109,7 @@ void FTextureManager::SortTexturesByType(int start, int end) void FTextureManager::AddLocalizedVariants() { - TArray content; + std::vector content; fileSystem.GetFilesInFolder("localized/textures/", content, false); for (auto &entry : content) { @@ -1128,8 +1127,8 @@ void FTextureManager::AddLocalizedVariants() } if (tokens.Size() >= 2) { - FString base = ExtractFileBase(tokens[0]); - FTextureID origTex = CheckForTexture(base, ETextureType::MiscPatch); + FString base = ExtractFileBase(tokens[0].GetChars()); + FTextureID origTex = CheckForTexture(base.GetChars(), ETextureType::MiscPatch); if (origTex.isValid()) { FTextureID tex = CheckForTexture(entry.name, ETextureType::MiscPatch); @@ -1368,7 +1367,7 @@ FTextureID FTextureManager::GetFrontSkyLayer(FTextureID texid) // But do not link the new texture into the hash chain! auto itex = new FImageTexture(image); itex->SetNoRemap0(); - auto FrontSkyLayer = MakeGameTexture(itex, tex->GetName(), ETextureType::Wall); + auto FrontSkyLayer = MakeGameTexture(itex, tex->GetName().GetChars(), ETextureType::Wall); FrontSkyLayer->SetUseType(tex->GetUseType()); texid = TexMan.AddGameTexture(FrontSkyLayer, false); Textures[texidx].FrontSkyLayer = texid.GetIndex(); @@ -1426,7 +1425,7 @@ int FTextureManager::GuesstimateNumTextures () break; default: - if (fileSystem.GetFileFlags(i) & LUMPF_MAYBEFLAT) numtex++; + if (fileSystem.GetFileFlags(i) & RESFF_MAYBEFLAT) numtex++; break; } @@ -1513,9 +1512,7 @@ void FTextureManager::AdjustSpriteOffsets() if (fileSystem.GetFileContainer(i) > fileSystem.GetMaxIwadNum()) break; // we are past the IWAD if (fileSystem.GetFileNamespace(i) == ns_sprites && fileSystem.GetFileContainer(i) >= fileSystem.GetIwadNum() && fileSystem.GetFileContainer(i) <= fileSystem.GetMaxIwadNum()) { - char str[9]; - fileSystem.GetFileShortName(str, i); - str[8] = 0; + const char *str = fileSystem.GetFileShortName(i); FTextureID texid = TexMan.CheckForTexture(str, ETextureType::Sprite, 0); if (texid.isValid() && fileSystem.GetFileContainer(GetGameTexture(texid)->GetSourceLump()) > fileSystem.GetMaxIwadNum()) { @@ -1627,6 +1624,37 @@ void FTextureManager::Listaliases() } } +//========================================================================== +// +// link a texture with a given lump +// +//========================================================================== + +void FTextureManager::SetLinkedTexture(int lump, FGameTexture* tex) +{ + if (lump < fileSystem.GetNumEntries()) + { + linkedMap.Insert(lump, tex); + } +} + +//========================================================================== +// +// retrieve linked texture +// +//========================================================================== + +FGameTexture* FTextureManager::GetLinkedTexture(int lump) +{ + if (lump < fileSystem.GetNumEntries()) + { + auto check = linkedMap.CheckKey(lump); + if (check) return *check; + } + return nullptr; +} + + //========================================================================== // // FTextureID::operator+ diff --git a/src/common/textures/texturemanager.h b/src/common/textures/texturemanager.h index 575e838ea0..cf799153f6 100644 --- a/src/common/textures/texturemanager.h +++ b/src/common/textures/texturemanager.h @@ -88,6 +88,15 @@ class FTextureManager } } + //========================================================================== + // + // link a texture with a given lump + // + //========================================================================== + + TMap linkedMap; + void SetLinkedTexture(int lump, FGameTexture* tex); + FGameTexture* GetLinkedTexture(int lump); enum { @@ -137,7 +146,7 @@ class FTextureManager void AddTextures(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&), void (*customtexturehandler)() = nullptr); void DeleteAll(); - void ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free); + void ReplaceTexture (FTextureID texid, FGameTexture *newtexture, bool free); int NumTextures () const { return (int)Textures.Size(); } diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index da2c7a167a..8fcdd3b239 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -45,7 +45,6 @@ #include "floatrect.h" #include "refcounted.h" -typedef TMap SpriteHits; class FImageSource; class FGameTexture; class IHardwareTexture; @@ -170,6 +169,7 @@ union FContentIdBuilder struct FTextureBuffer { uint8_t *mBuffer = nullptr; + bool mFreeBuffer = true; int mWidth = 0; int mHeight = 0; uint64_t mContentId = 0; // unique content identifier. (Two images created from the same image source with the same settings will return the same value.) @@ -178,25 +178,27 @@ struct FTextureBuffer ~FTextureBuffer() { - if (mBuffer) delete[] mBuffer; + if (mBuffer && mFreeBuffer) delete[] mBuffer; } FTextureBuffer(const FTextureBuffer &other) = delete; - FTextureBuffer(FTextureBuffer &&other) + FTextureBuffer(FTextureBuffer &&other) noexcept { mBuffer = other.mBuffer; mWidth = other.mWidth; mHeight = other.mHeight; mContentId = other.mContentId; + mFreeBuffer = other.mFreeBuffer; other.mBuffer = nullptr; } - FTextureBuffer& operator=(FTextureBuffer &&other) + FTextureBuffer& operator=(FTextureBuffer &&other) noexcept { mBuffer = other.mBuffer; mWidth = other.mWidth; mHeight = other.mHeight; mContentId = other.mContentId; + mFreeBuffer = other.mFreeBuffer; other.mBuffer = nullptr; return *this; } @@ -217,6 +219,7 @@ class FTexture : public RefCountedBase bool Masked = false; // Texture (might) have holes bool bHasCanvas = false; + bool bHdr = false; // only canvas textures for now. int8_t bTranslucent = -1; int8_t areacount = 0; // this is capped at 4 sections. @@ -253,6 +256,8 @@ class FTexture : public RefCountedBase bool isHardwareCanvas() const { return bHasCanvas; } // There's two here so that this can deal with software canvases in the hardware renderer later. bool isCanvas() const { return bHasCanvas; } + bool IsHDR() const { return bHdr; } + int GetSourceLump() { return SourceLump; } // needed by the scripted GetName method. void SetSourceLump(int sl) { SourceLump = sl; } bool FindHoles(const unsigned char * buffer, int w, int h); @@ -345,6 +350,12 @@ class FCanvasTexture : public FTexture float aspectRatio; friend struct FCanvasTextureInfo; + friend class FTextureAnimator; + +private: + void SetHDR(bool hdr) { + bHdr = hdr; + } }; @@ -370,10 +381,11 @@ class FImageTexture : public FTexture { FImageSource* mImage; bool bNoRemap0 = false; + int TexFrame = 0; protected: void SetFromImage(); public: - FImageTexture(FImageSource* image) noexcept; + FImageTexture(FImageSource* image, int frame = 0) noexcept; ~FImageTexture(); TArray Get8BitPixels(bool alphatex) override; diff --git a/src/common/textures/v_collection.cpp b/src/common/textures/v_collection.cpp index 2b51885bf0..975287680a 100644 --- a/src/common/textures/v_collection.cpp +++ b/src/common/textures/v_collection.cpp @@ -62,8 +62,8 @@ void FImageCollection::Add (const char **patchNames, int numPatches, ETextureTyp for (int i = 0; i < numPatches; ++i) { - FTextureID picnum = TexMan.CheckForTexture(patchNames[i], namespc); - ImageMap[OldCount + i] = picnum; + FTextureID texid = TexMan.CheckForTexture(patchNames[i], namespc); + ImageMap[OldCount + i] = texid; } } diff --git a/src/common/textures/animlib.cpp b/src/common/thirdparty/animlib.cpp similarity index 98% rename from src/common/textures/animlib.cpp rename to src/common/thirdparty/animlib.cpp index e42386bd99..4791a13132 100644 --- a/src/common/textures/animlib.cpp +++ b/src/common/thirdparty/animlib.cpp @@ -25,9 +25,9 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) */ //------------------------------------------------------------------------- +#include #include "animlib.h" #include "m_swap.h" -#include "m_alloc.h" //**************************************************************************** // @@ -217,12 +217,12 @@ static inline void drawframe(anim_t *anim, uint16_t framenumber) } // is the file size, for consistency checking. -int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length) +int32_t ANIM_LoadAnim(anim_t *anim, const uint8_t *buffer, size_t length) { if (memcmp(buffer, "LPF ", 4)) return -1; length -= sizeof(lpfileheader)+128+768; - if (length < 0) + if ((signed)length < 0) return -1; anim->curlpnum = 0xffff; @@ -244,7 +244,7 @@ int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length) lpheader.framesPerSecond = LittleShort(lpheader.framesPerSecond); length -= lpheader.nLps * sizeof(lp_descriptor); - if (length < 0) + if ((signed)length < 0) return -2; buffer += sizeof(lpfileheader)+128; diff --git a/src/common/textures/animlib.h b/src/common/thirdparty/animlib.h similarity index 97% rename from src/common/textures/animlib.h rename to src/common/thirdparty/animlib.h index 23d0d89da7..26fa124f40 100644 --- a/src/common/textures/animlib.h +++ b/src/common/thirdparty/animlib.h @@ -24,6 +24,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) */ //------------------------------------------------------------------------- +#pragma once #include ///////////////////////////////////////////////////////////////////////////// @@ -91,7 +92,7 @@ struct anim_t lp_descriptor * curlp; // header of large page currently in memory uint16_t * thepage; // buffer where current large page is loaded uint8_t imagebuffer[IMAGEBUFFERSIZE]; // buffer where anim frame is decoded - uint8_t * buffer; + const uint8_t * buffer; uint8_t pal[768]; int32_t currentframe; }; @@ -104,7 +105,7 @@ struct anim_t // //**************************************************************************** -int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length); +int32_t ANIM_LoadAnim(anim_t *anim, const uint8_t *buffer, size_t length); //**************************************************************************** // diff --git a/src/common/thirdparty/gain_analysis.cpp b/src/common/thirdparty/gain_analysis.cpp index 2f92e2128c..a31538f40a 100644 --- a/src/common/thirdparty/gain_analysis.cpp +++ b/src/common/thirdparty/gain_analysis.cpp @@ -282,7 +282,7 @@ GainAnalyzer::ResetSampleFrequency(int samplefreq) { int GainAnalyzer::InitGainAnalysis(int samplefreq) { - *this = {}; + memset(this, 0, sizeof(*this)); if (ResetSampleFrequency(samplefreq) != INIT_GAIN_ANALYSIS_OK) { return INIT_GAIN_ANALYSIS_ERROR; } diff --git a/src/common/thirdparty/libsmackerdec/src/FileStream.cpp b/src/common/thirdparty/libsmackerdec/src/FileStream.cpp index 454143ff10..f7845136b5 100644 --- a/src/common/thirdparty/libsmackerdec/src/FileStream.cpp +++ b/src/common/thirdparty/libsmackerdec/src/FileStream.cpp @@ -28,7 +28,7 @@ bool FileStream::Open(const char *fileName) { FString fixedname = fileName; FixPathSeperator(fixedname); - file = fileSystem.OpenFileReader(fixedname); + file = fileSystem.OpenFileReader(fixedname.GetChars()); if (!file.isOpen()) { // log error diff --git a/src/common/thirdparty/m_crc32.h b/src/common/thirdparty/m_crc32.h index 2930b8cbdf..d2de074fc0 100644 --- a/src/common/thirdparty/m_crc32.h +++ b/src/common/thirdparty/m_crc32.h @@ -32,12 +32,11 @@ ** */ #pragma once -#include +#include #include -// zlib includes some CRC32 stuff, so just use that +// miniz includes some CRC32 stuff, so just use that -inline const uint32_t *GetCRCTable () { return (const uint32_t *)get_crc_table(); } inline uint32_t CalcCRC32 (const uint8_t *buf, unsigned int len) { return crc32 (0, buf, len); diff --git a/src/common/thirdparty/math/asin.c b/src/common/thirdparty/math/asin.c index 8bc342dd12..72dc9b3e95 100644 --- a/src/common/thirdparty/math/asin.c +++ b/src/common/thirdparty/math/asin.c @@ -276,8 +276,7 @@ double c_asin(); #endif extern double PIO2, PIO4, NAN; -double c_asin(x) -double x; +double c_asin(double x) { double a, p, z, zz; short sign; @@ -327,8 +326,7 @@ return(z); -double c_acos(x) -double x; +double c_acos(double x) { if( (x < -1.0) || (x > 1.0) ) { diff --git a/src/common/thirdparty/math/atan.c b/src/common/thirdparty/math/atan.c index d73ed1ee44..68e10310af 100644 --- a/src/common/thirdparty/math/atan.c +++ b/src/common/thirdparty/math/atan.c @@ -212,8 +212,7 @@ extern double PI, PIO2, PIO4, INFINITY, NEGZERO, MAXNUM; #endif -double c_atan(x) -double x; +double c_atan(double x) { double y, z; short sign, flag; @@ -269,11 +268,10 @@ return(y); /* atan2 */ #ifdef ANSIC -double c_atan2( y, x ) +double c_atan2(double y, double x) #else -double c_atan2( x, y ) +double c_atan2(double x, double y) #endif -double x, y; { double z, w; short code; diff --git a/src/common/thirdparty/math/cosh.c b/src/common/thirdparty/math/cosh.c index 778ccd9514..bd4df2f391 100644 --- a/src/common/thirdparty/math/cosh.c +++ b/src/common/thirdparty/math/cosh.c @@ -79,8 +79,7 @@ int isnan(), isfinite(); #endif extern double MAXLOG, INFINITY, LOGE2; -double c_cosh(x) -double x; +double c_cosh(double x) { double y; diff --git a/src/common/thirdparty/math/exp.c b/src/common/thirdparty/math/exp.c index 29ec8d5da8..46cd0f5596 100644 --- a/src/common/thirdparty/math/exp.c +++ b/src/common/thirdparty/math/exp.c @@ -164,12 +164,11 @@ static short sc2[] = {0x3eb7,0xf7d1,0xcf79,0xabca}; extern double LOGE2, LOG2E, MAXLOG, MINLOG, MAXNUM; -double c_exp(x) -double x; +double c_exp(double x) { double px, xx; int n; -double polevl(), floor(), ldexp(); +double polevl(double, void *, int), floor(double), ldexp(double, int); if( x > MAXLOG) { diff --git a/src/common/thirdparty/math/fastsin.cpp b/src/common/thirdparty/math/fastsin.cpp index 36f59dbb44..41bc473ca8 100644 --- a/src/common/thirdparty/math/fastsin.cpp +++ b/src/common/thirdparty/math/fastsin.cpp @@ -57,7 +57,7 @@ __forceinline double FFastTrig::sinq1(unsigned bangle) { unsigned int index = bangle >> BITSHIFT; - if ((bangle &= (REMAINDER)) == 0) // This is to avoid precision problems at 180 + if ((bangle &= (REMAINDER)) == 0) // This is to avoid precision problems at 180° { return double(sinetable[index]); } diff --git a/src/common/thirdparty/math/isnan.c b/src/common/thirdparty/math/isnan.c index 6c421441f5..b09ce01a35 100644 --- a/src/common/thirdparty/math/isnan.c +++ b/src/common/thirdparty/math/isnan.c @@ -99,8 +99,7 @@ POSSIBILITY OF SUCH DAMAGE. /* Return 1 if the sign bit of x is 1, else 0. */ -int signbit(x) -double x; +int signbit(double x) { union { @@ -140,8 +139,7 @@ else /* Return 1 if x is a number that is Not a Number, else return 0. */ -int isnan(x) -double x; +int isnan(double x) { #ifdef NANS union @@ -209,8 +207,7 @@ return(0); /* Return 1 if x is not infinite and is not a NaN. */ -int isfinite(x) -double x; +int isfinite(double x) { #ifdef INFINITIES union diff --git a/src/common/thirdparty/math/log.c b/src/common/thirdparty/math/log.c index 81595120cc..8ad060c7ee 100644 --- a/src/common/thirdparty/math/log.c +++ b/src/common/thirdparty/math/log.c @@ -230,8 +230,7 @@ int isnan(), isfinite(); #define SQRTH 0.70710678118654752440 extern double INFINITY, NAN; -double c_log(x) -double x; +double c_log(double x) { int e; #ifdef DEC diff --git a/src/common/thirdparty/math/log10.c b/src/common/thirdparty/math/log10.c index 037741c60e..b7662dc0ec 100644 --- a/src/common/thirdparty/math/log10.c +++ b/src/common/thirdparty/math/log10.c @@ -178,8 +178,7 @@ int isnan(), isfinite(); #endif extern double LOGE2, SQRT2, INFINITY, NAN; -double c_log10(x) -double x; +double c_log10(double x) { VOLATILE double z; double y; diff --git a/src/common/thirdparty/math/mtherr.c b/src/common/thirdparty/math/mtherr.c index 5650e07ed6..3f24da2b7c 100644 --- a/src/common/thirdparty/math/mtherr.c +++ b/src/common/thirdparty/math/mtherr.c @@ -99,9 +99,7 @@ static char *ermsg[7] = { }; -int mtherr( name, code ) -char *name; -int code; +int mtherr(char* name, int code) { /* Display string passed by calling program, diff --git a/src/common/thirdparty/math/polevl.c b/src/common/thirdparty/math/polevl.c index bc17a1210c..dde27daff6 100644 --- a/src/common/thirdparty/math/polevl.c +++ b/src/common/thirdparty/math/polevl.c @@ -75,10 +75,7 @@ Direct inquiries to 30 Frost Street, Cambridge, MA 02140 */ -double polevl( x, coef, N ) -double x; -double coef[]; -int N; +double polevl(double x, double coef[], int N) { double ans; int i; @@ -101,10 +98,7 @@ return( ans ); * Otherwise same as polevl. */ -double p1evl( x, coef, N ) -double x; -double coef[]; -int N; +double p1evl(double x, double coef[], int N) { double ans; double *p; diff --git a/src/common/thirdparty/math/pow.c b/src/common/thirdparty/math/pow.c index 49d0914458..3631c4c78c 100644 --- a/src/common/thirdparty/math/pow.c +++ b/src/common/thirdparty/math/pow.c @@ -387,8 +387,7 @@ extern double NAN; extern double NEGZERO; #endif -double c_pow( x, y ) -double x, y; +double c_pow(double x, double y) { double w, z, W, Wa, Wb, ya, yb, u; /* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */ @@ -768,8 +767,7 @@ return( z ); /* Find a multiple of 1/16 that is within 1/16 of x. */ -static double reduc(x) -double x; +static double reduc(double x) { double t; diff --git a/src/common/thirdparty/math/powi.c b/src/common/thirdparty/math/powi.c index d4d5a07f69..75a22f8f1a 100644 --- a/src/common/thirdparty/math/powi.c +++ b/src/common/thirdparty/math/powi.c @@ -78,9 +78,7 @@ int signbit(); #endif extern double NEGZERO, INFINITY, MAXNUM, MAXLOG, MINLOG, LOGE2; -double c_powi( x, nn ) -double x; -int nn; +double c_powi(double x, int nn) { int n, e, sign, asign, lx; double w, y, s; diff --git a/src/common/thirdparty/math/sin.c b/src/common/thirdparty/math/sin.c index 76c6a1938a..4b4275f2ed 100644 --- a/src/common/thirdparty/math/sin.c +++ b/src/common/thirdparty/math/sin.c @@ -238,8 +238,7 @@ extern double INFINITY; #endif -double c_sin(x) -double x; +double c_sin(double x) { double y, z, zz; int j, sign; @@ -318,8 +317,7 @@ return(y); -double c_cos(x) -double x; +double c_cos(double x) { double y, z, zz; int i; @@ -403,8 +401,7 @@ static unsigned short P648[] = {034513,054170,0176773,0116043,}; static double P64800 = 4.8481368110953599358991410e-5; #endif -double radian(d,m,s) -double d,m,s; +double radian(double d, double m, double s) { return( ((d*60.0 + m)*60.0 + s)*P64800 ); diff --git a/src/common/thirdparty/math/sinh.c b/src/common/thirdparty/math/sinh.c index eb868b7650..3b54760c46 100644 --- a/src/common/thirdparty/math/sinh.c +++ b/src/common/thirdparty/math/sinh.c @@ -132,8 +132,7 @@ double fabs(), c_exp(), polevl(), p1evl(); #endif extern double INFINITY, MINLOG, MAXLOG, LOGE2; -double c_sinh(x) -double x; +double c_sinh(double x) { double a; diff --git a/src/common/thirdparty/math/sqrt.c b/src/common/thirdparty/math/sqrt.c index de214aff04..67f7376f17 100644 --- a/src/common/thirdparty/math/sqrt.c +++ b/src/common/thirdparty/math/sqrt.c @@ -78,8 +78,7 @@ double frexp(), ldexp(); #endif extern double SQRT2; /* _sqrt2 = 1.41421356237309504880 */ -double c_sqrt(x) -double x; +double c_sqrt(double x) { int e; #ifndef UNK diff --git a/src/common/thirdparty/math/tan.c b/src/common/thirdparty/math/tan.c index 0b5fecc9c6..adeade460e 100644 --- a/src/common/thirdparty/math/tan.c +++ b/src/common/thirdparty/math/tan.c @@ -220,8 +220,7 @@ extern double PIO4; extern double INFINITY; extern double NAN; -double c_tan(x) -double x; +double c_tan(double x) { #ifdef MINUSZERO if( x == 0.0 ) @@ -240,8 +239,7 @@ return( tancot(x,0) ); } -double c_cot(x) -double x; +double c_cot(double x) { if( x == 0.0 ) @@ -253,9 +251,7 @@ return( tancot(x,1) ); } -static double tancot( xx, cotflg ) -double xx; -int cotflg; +static double tancot(double xx, int cotflg) { double x, y, z, zz; int j, sign; diff --git a/src/common/thirdparty/math/tanh.c b/src/common/thirdparty/math/tanh.c index 1836d35cce..92452c10fb 100644 --- a/src/common/thirdparty/math/tanh.c +++ b/src/common/thirdparty/math/tanh.c @@ -128,8 +128,7 @@ double fabs(), c_exp(), polevl(), p1evl(); #endif extern double MAXLOG; -double c_tanh(x) -double x; +double c_tanh(double x) { double s, z; diff --git a/src/common/thirdparty/md5.h b/src/common/thirdparty/md5.h index f3aab94d96..95ac9a50d8 100644 --- a/src/common/thirdparty/md5.h +++ b/src/common/thirdparty/md5.h @@ -18,6 +18,8 @@ #ifndef MD5_H #define MD5_H +#include + struct MD5Context { MD5Context() { Init(); } diff --git a/src/common/thirdparty/richpresence.cpp b/src/common/thirdparty/richpresence.cpp index 7a081adac8..a8d8e81158 100644 --- a/src/common/thirdparty/richpresence.cpp +++ b/src/common/thirdparty/richpresence.cpp @@ -36,6 +36,7 @@ */ #include +#include #include "common/engine/printf.h" #include "discord_rpc.h" diff --git a/src/common/textures/formats/stb_image.h b/src/common/thirdparty/stb/stb_image.h similarity index 89% rename from src/common/textures/formats/stb_image.h rename to src/common/thirdparty/stb/stb_image.h index 44117802ac..5e807a0a6e 100644 --- a/src/common/textures/formats/stb_image.h +++ b/src/common/thirdparty/stb/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.23 - public domain image loader - http://nothings.org/stb +/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: @@ -48,10 +48,15 @@ LICENSE RECENT REVISION HISTORY: + 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff + 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes + 2.26 (2020-07-13) many minor fixes + 2.25 (2020-02-02) fix warnings + 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically 2.23 (2019-08-11) fix clang static analysis warning 2.22 (2019-03-04) gif fixes, fix warnings 2.21 (2019-02-25) fix typo in comment - 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 2.19 (2018-02-11) fix warning 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings @@ -86,26 +91,37 @@ RECENT REVISION HISTORY: Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Mikhail Morozov (1-bit BMP) Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) - Arseny Kapoulkine + Arseny Kapoulkine Simon Breuss (16-bit PNM) John-Mark Allen Carmelo J Fdez-Aguera Bug & warning fixes - Marc LeBlanc David Woo Guillaume George Martins Mozeiko - Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan - Dave Moore Roy Eltham Hayaki Saito Nathan Reed - Won Chun Luke Graham Johan Duparc Nick Verigakis - the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh - Janez Zemva John Bartholomew Michal Cichon github:romigrou - Jonathan Blow Ken Hamada Tero Hanninen github:svdijk - Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar - Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex - Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 - Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw - Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus - Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo - Christian Floisand Kevin Schmidt JR Smith github:darealshinji - Blazej Dariusz Roszkowski github:Michaelangel007 + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski + Phil Jordan Dave Moore Roy Eltham + Hayaki Saito Nathan Reed Won Chun + Luke Graham Johan Duparc Nick Verigakis the Horde3D community + Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Eugene Golushkov Laurent Gomila Cort Stratton github:snagar + Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex + Cass Everitt Ryamond Barbiero github:grim210 + Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw + Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus + Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo + Julian Raschke Gregory Mullen Christian Floisand github:darealshinji + Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 + Brad Weinberger Matvey Cherevko github:mosra + Luca Sas Alexander Veselov Zack Middleton [reserved] + Ryan C. Gordon [reserved] [reserved] + DO NOT ADD YOUR NAME HERE + + Jacko Dirks + + To add your name to the credits, pick a random blank space in the middle and fill it. + 80% of merge conflicts on stb PRs are due to people adding their name at the end + of the credits. */ #ifndef STBI_INCLUDE_STB_IMAGE_H @@ -125,7 +141,7 @@ RECENT REVISION HISTORY: // // ... x = width, y = height, n = # 8-bit components per pixel ... // // ... replace '0' with '1'..'4' to force that many components per pixel // // ... but 'n' will always be the number that it would have been if you said 0 -// stbi_image_free(data) +// stbi_image_free(data); // // Standard parameters: // int *x -- outputs image width in pixels @@ -164,6 +180,32 @@ RECENT REVISION HISTORY: // // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. // +// To query the width, height and component count of an image without having to +// decode the full file, you can use the stbi_info family of functions: +// +// int x,y,n,ok; +// ok = stbi_info(filename, &x, &y, &n); +// // returns ok=1 and sets x, y, n if image is a supported format, +// // 0 otherwise. +// +// Note that stb_image pervasively uses ints in its public API for sizes, +// including sizes of memory buffers. This is now part of the API and thus +// hard to change without causing breakage. As a result, the various image +// loaders all have certain limits on image size; these differ somewhat +// by format but generally boil down to either just under 2GB or just under +// 1GB. When the decoded image would be larger than this, stb_image decoding +// will fail. +// +// Additionally, stb_image will reject image files that have any of their +// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, +// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, +// the only way to have an image with such dimensions load correctly +// is for it to have a rather extreme aspect ratio. Either way, the +// assumption here is that such larger images are likely to be malformed +// or malicious. If you do need to load an image with individual dimensions +// larger than that, and it still fits in the overall size limit, you can +// #define STBI_MAX_DIMENSIONS on your own to be something larger. +// // =========================================================================== // // UNICODE: @@ -269,11 +311,10 @@ RECENT REVISION HISTORY: // // iPhone PNG support: // -// By default we convert iphone-formatted PNGs back to RGB, even though -// they are internally encoded differently. You can disable this conversion -// by calling stbi_convert_iphone_png_to_rgb(0), in which case -// you will always just get the native iphone "format" through (which -// is BGR stored in RGB). +// We optionally support converting iPhone-formatted PNGs (which store +// premultiplied BGRA) back to RGB, even though they're internally encoded +// differently. To enable this conversion, call +// stbi_convert_iphone_png_to_rgb(1). // // Call stbi_set_unpremultiply_on_load(1) as well to force a divide per // pixel to remove any premultiplied alpha *only* if the image file explicitly @@ -315,7 +356,14 @@ RECENT REVISION HISTORY: // - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still // want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB // - +// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater +// than that size (in either width or height) without further processing. +// This is to let programs in the wild set an upper bound to prevent +// denial-of-service attacks on untrusted data, as one could generate a +// valid image of gigantic dimensions and force stb_image to allocate a +// huge block of memory and spend disproportionate time decoding it. By +// default this is set to (1 << 24), which is 16777216, but that's still +// very big. #ifndef STBI_NO_STDIO #include @@ -434,7 +482,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f); // get a VERY brief reason for failure -// NOT THREADSAFE +// on most compilers (and ALL modern mainstream compilers) this is threadsafe STBIDEF const char *stbi_failure_reason (void); // free the loaded image -- this is just free() @@ -467,6 +515,13 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); // flip the image vertically, so the first pixel in the output array is the bottom left STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); +// as above, but only applies to images loaded on the thread that calls the function +// this function is only available if your compiler supports thread-local variables; +// calling it will fail to link if your compiler doesn't +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); + // ZLIB client - used by PNG, available for other purposes STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); @@ -563,8 +618,25 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch #define stbi_inline __forceinline #endif +#ifndef STBI_NO_THREAD_LOCALS + #if defined(__cplusplus) && __cplusplus >= 201103L + #define STBI_THREAD_LOCAL thread_local + #elif defined(__GNUC__) && __GNUC__ < 5 + #define STBI_THREAD_LOCAL __thread + #elif defined(_MSC_VER) + #define STBI_THREAD_LOCAL __declspec(thread) + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) + #define STBI_THREAD_LOCAL _Thread_local + #endif -#ifdef _MSC_VER + #ifndef STBI_THREAD_LOCAL + #if defined(__GNUC__) + #define STBI_THREAD_LOCAL __thread + #endif + #endif +#endif + +#if defined(_MSC_VER) || defined(__SYMBIAN32__) typedef unsigned short stbi__uint16; typedef signed short stbi__int16; typedef unsigned int stbi__uint32; @@ -593,7 +665,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #ifdef STBI_HAS_LROTL #define stbi_lrot(x,y) _lrotl(x,y) #else - #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) #endif #if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) @@ -707,14 +779,21 @@ static int stbi__sse2_available(void) #ifdef STBI_NEON #include -// assume GCC or Clang on ARM targets +#ifdef _MSC_VER +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #endif +#endif #ifndef STBI_SIMD_ALIGN #define STBI_SIMD_ALIGN(type, name) type name #endif +#ifndef STBI_MAX_DIMENSIONS +#define STBI_MAX_DIMENSIONS (1 << 24) +#endif + /////////////////////////////////////////////// // // stbi__context struct and start_xxx functions @@ -732,6 +811,7 @@ typedef struct int read_from_callbacks; int buflen; stbi_uc buffer_start[128]; + int callback_already_read; stbi_uc *img_buffer, *img_buffer_end; stbi_uc *img_buffer_original, *img_buffer_original_end; @@ -745,6 +825,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) { s->io.read = NULL; s->read_from_callbacks = 0; + s->callback_already_read = 0; s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; } @@ -756,7 +837,8 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void * s->io_user_data = user; s->buflen = sizeof(s->buffer_start); s->read_from_callbacks = 1; - s->img_buffer_original = s->buffer_start; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = s->buffer_start; stbi__refill_buffer(s); s->img_buffer_original_end = s->img_buffer_end; } @@ -770,12 +852,17 @@ static int stbi__stdio_read(void *user, char *data, int size) static void stbi__stdio_skip(void *user, int n) { + int ch; fseek((FILE*) user, n, SEEK_CUR); + ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ + if (ch != EOF) { + ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ + } } static int stbi__stdio_eof(void *user) { - return feof((FILE*) user); + return feof((FILE*) user) || ferror((FILE *) user); } static stbi_io_callbacks stbi__stdio_callbacks = @@ -871,21 +958,27 @@ static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__pnm_test(stbi__context *s); static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__pnm_is16(stbi__context *s); #endif -// this is not threadsafe -static const char *stbi__g_failure_reason; +static +#ifdef STBI_THREAD_LOCAL +STBI_THREAD_LOCAL +#endif +const char *stbi__g_failure_reason; STBIDEF const char *stbi_failure_reason(void) { return stbi__g_failure_reason; } +#ifndef STBI_NO_FAILURE_STRINGS static int stbi__err(const char *str) { stbi__g_failure_reason = str; return 0; } +#endif static void *stbi__malloc(size_t size) { @@ -924,11 +1017,13 @@ static int stbi__mul2sizes_valid(int a, int b) return a <= INT_MAX/b; } +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) // returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow static int stbi__mad2sizes_valid(int a, int b, int add) { return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); } +#endif // returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow static int stbi__mad3sizes_valid(int a, int b, int c, int add) @@ -938,7 +1033,7 @@ static int stbi__mad3sizes_valid(int a, int b, int c, int add) } // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) { return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && @@ -946,12 +1041,14 @@ static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) } #endif +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) // mallocs with size overflow checking static void *stbi__malloc_mad2(int a, int b, int add) { if (!stbi__mad2sizes_valid(a, b, add)) return NULL; return stbi__malloc(a*b + add); } +#endif static void *stbi__malloc_mad3(int a, int b, int c, int add) { @@ -959,7 +1056,7 @@ static void *stbi__malloc_mad3(int a, int b, int c, int add) return stbi__malloc(a*b*c + add); } -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) { if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; @@ -967,6 +1064,23 @@ static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) } #endif +// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. +static int stbi__addints_valid(int a, int b) +{ + if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow + if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. + return a <= INT_MAX - b; +} + +// returns 1 if the product of two signed shorts is valid, 0 on overflow. +static int stbi__mul2shorts_valid(short a, short b) +{ + if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow + if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid + if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN + return a >= SHRT_MIN / b; +} + // stbi__err - error // stbi__errpf - error returning pointer to float // stbi__errpuc - error returning pointer to unsigned char @@ -995,13 +1109,29 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); #endif -static int stbi__vertically_flip_on_load = 0; +static int stbi__vertically_flip_on_load_global = 0; STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) { - stbi__vertically_flip_on_load = flag_true_if_should_flip; + stbi__vertically_flip_on_load_global = flag_true_if_should_flip; } +#ifndef STBI_THREAD_LOCAL +#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global +#else +static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; + +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_local = flag_true_if_should_flip; + stbi__vertically_flip_on_load_set = 1; +} + +#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ + ? stbi__vertically_flip_on_load_local \ + : stbi__vertically_flip_on_load_global) +#endif // STBI_THREAD_LOCAL + static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields @@ -1009,9 +1139,8 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order ri->num_channels = 0; - #ifndef STBI_NO_JPEG - if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); - #endif + // test the formats with a very explicit header first (at least a FOURCC + // or distinctive magic number first) #ifndef STBI_NO_PNG if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); #endif @@ -1023,10 +1152,19 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re #endif #ifndef STBI_NO_PSD if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #else + STBI_NOTUSED(bpc); #endif #ifndef STBI_NO_PIC if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); #endif + + // then the formats that can end up attempting to load with just 1 or 2 + // bytes matching expectations; these are prone to false positives, so + // try them later + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif #ifndef STBI_NO_PNM if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); #endif @@ -1111,8 +1249,8 @@ static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int byt stbi_uc *bytes = (stbi_uc *)image; for (slice = 0; slice < z; ++slice) { - stbi__vertical_flip(bytes, w, h, bytes_per_pixel); - bytes += slice_size; + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; } } #endif @@ -1125,8 +1263,10 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, if (result == NULL) return NULL; + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + if (ri.bits_per_channel != 8) { - STBI_ASSERT(ri.bits_per_channel == 16); result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); ri.bits_per_channel = 8; } @@ -1149,8 +1289,10 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, if (result == NULL) return NULL; + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + if (ri.bits_per_channel != 16) { - STBI_ASSERT(ri.bits_per_channel == 8); result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); ri.bits_per_channel = 16; } @@ -1178,12 +1320,12 @@ static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, in #ifndef STBI_NO_STDIO -#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); #endif -#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); @@ -1193,16 +1335,16 @@ STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wch static FILE *stbi__fopen(char const *filename, char const *mode) { FILE *f; -#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) return 0; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; -#if _MSC_VER >= 1400 +#if defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != _wfopen_s(&f, wFilename, wMode)) f = 0; #else @@ -1300,15 +1442,15 @@ STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *u STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) { unsigned char *result; - stbi__context s; - stbi__start_mem(&s,buffer,len); + stbi__context s; + stbi__start_mem(&s,buffer,len); result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); if (stbi__vertically_flip_on_load) { - stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); } - return result; + return result; } #endif @@ -1453,6 +1595,7 @@ enum static void stbi__refill_buffer(stbi__context *s) { int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); if (n == 0) { // at end of file, treat same as if from memory, but need to handle case // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file @@ -1477,6 +1620,9 @@ stbi_inline static stbi_uc stbi__get8(stbi__context *s) return 0; } +#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else stbi_inline static int stbi__at_eof(stbi__context *s) { if (s->io.read) { @@ -1488,9 +1634,14 @@ stbi_inline static int stbi__at_eof(stbi__context *s) return s->img_buffer >= s->img_buffer_end; } +#endif +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) +// nothing +#else static void stbi__skip(stbi__context *s, int n) { + if (n == 0) return; // already there! if (n < 0) { s->img_buffer = s->img_buffer_end; return; @@ -1505,7 +1656,11 @@ static void stbi__skip(stbi__context *s, int n) } s->img_buffer += n; } +#endif +#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) +// nothing +#else static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) { if (s->io.read) { @@ -1529,18 +1684,27 @@ static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) } else return 0; } +#endif +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else static int stbi__get16be(stbi__context *s) { int z = stbi__get8(s); return (z << 8) + stbi__get8(s); } +#endif +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else static stbi__uint32 stbi__get32be(stbi__context *s) { stbi__uint32 z = stbi__get16be(s); return (z << 16) + stbi__get16be(s); } +#endif #if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) // nothing @@ -1556,13 +1720,16 @@ static int stbi__get16le(stbi__context *s) static stbi__uint32 stbi__get32le(stbi__context *s) { stbi__uint32 z = stbi__get16le(s); - return z + (stbi__get16le(s) << 16); + z += (stbi__uint32)stbi__get16le(s) << 16; + return z; } #endif #define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings - +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else ////////////////////////////////////////////////////////////////////////////// // // generic converter from built-in img_n to req_comp @@ -1578,7 +1745,11 @@ static stbi_uc stbi__compute_y(int r, int g, int b) { return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); } +#endif +#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; @@ -1614,7 +1785,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; - default: STBI_ASSERT(0); + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); } #undef STBI__CASE } @@ -1622,12 +1793,20 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r STBI_FREE(data); return good; } +#endif +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else static stbi__uint16 stbi__compute_y_16(int r, int g, int b) { return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); } +#endif +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; @@ -1663,7 +1842,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; - default: STBI_ASSERT(0); + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); } #undef STBI__CASE } @@ -1671,6 +1850,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r STBI_FREE(data); return good; } +#endif #ifndef STBI_NO_LINEAR static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) @@ -1823,9 +2003,12 @@ static int stbi__build_huffman(stbi__huffman *h, int *count) int i,j,k=0; unsigned int code; // build size list for each symbol (from JPEG spec) - for (i=0; i < 16; ++i) - for (j=0; j < count[i]; ++j) + for (i=0; i < 16; ++i) { + for (j=0; j < count[i]; ++j) { h->size[k++] = (stbi_uc) (i+1); + if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); + } + } h->size[k] = 0; // compute actual symbols (from jpeg spec) @@ -1950,6 +2133,8 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) // convert the huffman code to the symbol id c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + if(c < 0 || c >= 256) // symbol id out of bounds! + return -1; STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); // convert the id to a symbol @@ -1968,14 +2153,14 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n) unsigned int k; int sgn; if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing - sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) k = stbi_lrot(j->code_buffer, n); - STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; j->code_bits -= n; - return k + (stbi__jbias[n] & ~sgn); + return k + (stbi__jbias[n] & (sgn - 1)); } // get some unsigned bits @@ -1983,6 +2168,7 @@ stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) { unsigned int k; if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing k = stbi_lrot(j->code_buffer, n); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; @@ -1994,6 +2180,7 @@ stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) { unsigned int k; if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing k = j->code_buffer; j->code_buffer <<= 1; --j->code_bits; @@ -2025,14 +2212,16 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); t = stbi__jpeg_huff_decode(j, hdc); - if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); // 0 all the ac values now so we can do it 32-bits at a time memset(data,0,64*sizeof(data[0])); diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); data[0] = (short) (dc * dequant[0]); // decode AC components, see JPEG spec @@ -2046,6 +2235,7 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman if (r) { // fast-AC path k += (r >> 4) & 15; // run s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); j->code_buffer <<= s; j->code_bits -= s; // decode into unzigzag'd location @@ -2082,11 +2272,14 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__ // first scan for DC coefficient, must be first memset(data,0,64*sizeof(data[0])); // 0 all the ac values now t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; - data[0] = (short) (dc << j->succ_low); + if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * (1 << j->succ_low)); } else { // refinement scan for DC coefficient if (stbi__jpeg_get_bit(j)) @@ -2120,10 +2313,11 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__ if (r) { // fast-AC path k += (r >> 4) & 15; // run s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); j->code_buffer <<= s; j->code_bits -= s; zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) ((r >> 8) << shift); + data[zig] = (short) ((r >> 8) * (1 << shift)); } else { int rs = stbi__jpeg_huff_decode(j, hac); if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); @@ -2141,7 +2335,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__ } else { k += r; zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) (stbi__extend_receive(j,s) << shift); + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); } } } while (k <= j->spec_end); @@ -2940,6 +3134,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m) sizes[i] = stbi__get8(z->s); n += sizes[i]; } + if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! L -= 17; if (tc == 0) { if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; @@ -3072,6 +3267,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); c = stbi__get8(s); if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); s->img_n = c; @@ -3103,6 +3300,13 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; } + // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios + // and I've never seen a non-corrupted JPEG file actually use them + for (i=0; i < s->img_n; ++i) { + if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); + if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); + } + // compute interleaved mcu info z->img_h_max = h_max; z->img_v_max = v_max; @@ -3180,6 +3384,28 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) return 1; } +static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +{ + // some JPEGs have junk at end, skip over it but if we find what looks + // like a valid marker, resume there + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + while (x == 255) { // might be a marker + if (stbi__at_eof(j->s)) return STBI__MARKER_none; + x = stbi__get8(j->s); + if (x != 0x00 && x != 0xff) { + // not a stuffed zero or lead-in to another marker, looks + // like an actual marker, return it + return x; + } + // stuffed zero has x=0 now which ends the loop, meaning we go + // back to regular scan loop. + // repeated 0xff keeps trying to read the next byte of the marker. + } + } + return STBI__MARKER_none; +} + // decode image to YCbCr format static int stbi__decode_jpeg_image(stbi__jpeg *j) { @@ -3196,25 +3422,22 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) if (!stbi__process_scan_header(j)) return 0; if (!stbi__parse_entropy_coded_data(j)) return 0; if (j->marker == STBI__MARKER_none ) { - // handle 0s at the end of image data from IP Kamera 9060 - while (!stbi__at_eof(j->s)) { - int x = stbi__get8(j->s); - if (x == 255) { - j->marker = stbi__get8(j->s); - break; - } - } + j->marker = stbi__skip_jpeg_junk_at_end(j); // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 } + m = stbi__get_marker(j); + if (STBI__RESTART(m)) + m = stbi__get_marker(j); } else if (stbi__DNL(m)) { int Ld = stbi__get16be(j->s); stbi__uint32 NL = stbi__get16be(j->s); if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + m = stbi__get_marker(j); } else { - if (!stbi__process_marker(j, m)) return 0; + if (!stbi__process_marker(j, m)) return 1; + m = stbi__get_marker(j); } - m = stbi__get_marker(j); } if (j->progressive) stbi__jpeg_finish(j); @@ -3658,6 +3881,10 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp else decode_n = z->s->img_n; + // nothing to do if no components requested; check this now to avoid + // accessing uninitialized coutput[0] later + if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } + // resample and color-convert { int k; @@ -3800,6 +4027,8 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re { unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); STBI_NOTUSED(ri); j->s = s; stbi__setup_jpeg(j); @@ -3812,6 +4041,8 @@ static int stbi__jpeg_test(stbi__context *s) { int r; stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); j->s = s; stbi__setup_jpeg(j); r = stbi__decode_jpeg_header(j, STBI__SCAN_type); @@ -3836,6 +4067,8 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) { int result; stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); j->s = s; result = stbi__jpeg_info_raw(j, x, y, comp); STBI_FREE(j); @@ -3855,6 +4088,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) // fast-way is faster to check than jpeg huffman, but slow way is slower #define STBI__ZFAST_BITS 9 // accelerate all cases in default tables #define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) +#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet // zlib-style huffman encoding // (jpegs packs from left, zlib from right, so can't share code) @@ -3864,8 +4098,8 @@ typedef struct stbi__uint16 firstcode[16]; int maxcode[17]; stbi__uint16 firstsymbol[16]; - stbi_uc size[288]; - stbi__uint16 value[288]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; } stbi__zhuffman; stbi_inline static int stbi__bitreverse16(int n) @@ -3952,16 +4186,23 @@ typedef struct stbi__zhuffman z_length, z_distance; } stbi__zbuf; +stbi_inline static int stbi__zeof(stbi__zbuf *z) +{ + return (z->zbuffer >= z->zbuffer_end); +} + stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) { - if (z->zbuffer >= z->zbuffer_end) return 0; - return *z->zbuffer++; + return stbi__zeof(z) ? 0 : *z->zbuffer++; } static void stbi__fill_bits(stbi__zbuf *z) { do { - STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + if (z->code_buffer >= (1U << z->num_bits)) { + z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ + return; + } z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; z->num_bits += 8; } while (z->num_bits <= 24); @@ -3986,10 +4227,11 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) for (s=STBI__ZFAST_BITS+1; ; ++s) if (k < z->maxcode[s]) break; - if (s == 16) return -1; // invalid code! + if (s >= 16) return -1; // invalid code! // code size is s, so: b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; - STBI_ASSERT(z->size[b] == s); + if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! + if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. a->code_buffer >>= s; a->num_bits -= s; return z->value[b]; @@ -3998,7 +4240,12 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) { int b,s; - if (a->num_bits < 16) stbi__fill_bits(a); + if (a->num_bits < 16) { + if (stbi__zeof(a)) { + return -1; /* report error for unexpected end of data. */ + } + stbi__fill_bits(a); + } b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; if (b) { s = b >> 9; @@ -4012,13 +4259,16 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes { char *q; - int cur, limit, old_limit; + unsigned int cur, limit, old_limit; z->zout = zout; if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); - cur = (int) (z->zout - z->zout_start); - limit = old_limit = (int) (z->zout_end - z->zout_start); - while (cur + n > limit) + cur = (unsigned int) (z->zout - z->zout_start); + limit = old_limit = (unsigned) (z->zout_end - z->zout_start); + if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); + while (cur + n > limit) { + if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); limit *= 2; + } q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); STBI_NOTUSED(old_limit); if (q == NULL) return stbi__err("outofmem", "Out of memory"); @@ -4061,11 +4311,12 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) a->zout = zout; return 1; } + if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data z -= 257; len = stbi__zlength_base[z]; if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); z = stbi__zhuffman_decode(a, &a->z_distance); - if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); @@ -4116,11 +4367,12 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) c = stbi__zreceive(a,2)+3; if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); fill = lencodes[n-1]; - } else if (c == 17) + } else if (c == 17) { c = stbi__zreceive(a,3)+3; - else { - STBI_ASSERT(c == 18); + } else if (c == 18) { c = stbi__zreceive(a,7)+11; + } else { + return stbi__err("bad codelengths", "Corrupt PNG"); } if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); memset(lencodes+n, fill, c); @@ -4146,7 +4398,7 @@ static int stbi__parse_uncompressed_block(stbi__zbuf *a) a->code_buffer >>= 8; a->num_bits -= 8; } - STBI_ASSERT(a->num_bits == 0); + if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); // now fill header the normal way while (k < 4) header[k++] = stbi__zget8(a); @@ -4168,6 +4420,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) int cm = cmf & 15; /* int cinfo = cmf >> 4; */ int flg = stbi__zget8(a); + if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png @@ -4175,7 +4428,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) return 1; } -static const stbi_uc stbi__zdefault_length[288] = +static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, @@ -4221,7 +4474,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) } else { if (type == 1) { // use fixed code lengths - if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; } else { if (!stbi__compute_huffman_codes(a)) return 0; @@ -4429,7 +4682,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r return stbi__err("invalid filter","Corrupt PNG"); if (depth < 8) { - STBI_ASSERT(img_width_bytes <= x); + if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG"); cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place filter_bytes = 1; width = img_width_bytes; @@ -4617,6 +4870,7 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3 // de-interlacing final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + if (!final) return stbi__err("outofmem", "Out of memory"); for (p=0; p < 7; ++p) { int xorig[] = { 0,4,0,2,0,1,0 }; int yorig[] = { 0,0,4,0,2,0,1 }; @@ -4737,19 +4991,46 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int return 1; } -static int stbi__unpremultiply_on_load = 0; -static int stbi__de_iphone_flag = 0; +static int stbi__unpremultiply_on_load_global = 0; +static int stbi__de_iphone_flag_global = 0; STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) { - stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; } STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) { - stbi__de_iphone_flag = flag_true_if_should_convert; + stbi__de_iphone_flag_global = flag_true_if_should_convert; } +#ifndef STBI_THREAD_LOCAL +#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global +#define stbi__de_iphone_flag stbi__de_iphone_flag_global +#else +static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; +static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; + +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_set = 1; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_local = flag_true_if_should_convert; + stbi__de_iphone_flag_set = 1; +} + +#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ + ? stbi__unpremultiply_on_load_local \ + : stbi__unpremultiply_on_load_global) +#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ + ? stbi__de_iphone_flag_local \ + : stbi__de_iphone_flag_global) +#endif // STBI_THREAD_LOCAL + static void stbi__de_iphone(stbi__png *z) { stbi__context *s = z->s; @@ -4824,8 +5105,10 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); first = 0; if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); - s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); - s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_x = stbi__get32be(s); + s->img_y = stbi__get32be(s); + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); @@ -4837,14 +5120,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (!pal_img_n) { s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); - if (scan == STBI__SCAN_header) return 1; } else { // if paletted, then pal_n is our final components, and // img_n is # components to decompress/filter. s->img_n = 1; if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); - // if SCAN_header, have to scan to see if we have a tRNS } + // even with SCAN_header, have to scan to see if we have a tRNS break; } @@ -4876,6 +5158,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; + // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. + if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } if (z->depth == 16) { for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is } else { @@ -4888,7 +5172,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) case STBI__PNG_TYPE('I','D','A','T'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); - if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if (scan == STBI__SCAN_header) { + // header scan definitely stops at first IDAT + if (pal_img_n) + s->img_n = pal_img_n; + return 1; + } + if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); if ((int)(ioff + c.length) < (int)ioff) return 0; if (ioff + c.length > idata_limit) { stbi__uint32 idata_limit_old = idata_limit; @@ -4942,6 +5232,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) ++s->img_n; } STBI_FREE(z->expanded); z->expanded = NULL; + // end of PNG chunk, read and skip CRC + stbi__get32be(s); return 1; } @@ -4972,10 +5264,12 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st void *result=NULL; if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { - if (p->depth < 8) + if (p->depth <= 8) ri->bits_per_channel = 8; + else if (p->depth == 16) + ri->bits_per_channel = 16; else - ri->bits_per_channel = p->depth; + return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { @@ -5111,7 +5405,7 @@ static int stbi__shiftsigned(unsigned int v, int shift, int bits) v <<= -shift; else v >>= shift; - STBI_ASSERT(v >= 0 && v < 256); + STBI_ASSERT(v < 256); v >>= (8-bits); STBI_ASSERT(bits >= 0 && bits <= 8); return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; @@ -5121,8 +5415,35 @@ typedef struct { int bpp, offset, hsz; unsigned int mr,mg,mb,ma, all_a; + int extra_read; } stbi__bmp_data; +static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) +{ + // BI_BITFIELDS specifies masks explicitly, don't override + if (compress == 3) + return 1; + + if (compress == 0) { + if (info->bpp == 16) { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } else if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + // otherwise, use defaults, which is all-0 + info->mr = info->mg = info->mb = info->ma = 0; + } + return 1; + } + return 0; // error +} + static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) { int hsz; @@ -5133,6 +5454,9 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) info->offset = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s); info->mr = info->mg = info->mb = info->ma = 0; + info->extra_read = 14; + + if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { @@ -5147,6 +5471,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) if (hsz != 12) { int compress = stbi__get32le(s); if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes + if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel stbi__get32le(s); // discard sizeof stbi__get32le(s); // discard hres stbi__get32le(s); // discard vres @@ -5161,21 +5487,12 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) } if (info->bpp == 16 || info->bpp == 32) { if (compress == 0) { - if (info->bpp == 32) { - info->mr = 0xffu << 16; - info->mg = 0xffu << 8; - info->mb = 0xffu << 0; - info->ma = 0xffu << 24; - info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 - } else { - info->mr = 31u << 10; - info->mg = 31u << 5; - info->mb = 31u << 0; - } + stbi__bmp_set_mask_defaults(info, compress); } else if (compress == 3) { info->mr = stbi__get32le(s); info->mg = stbi__get32le(s); info->mb = stbi__get32le(s); + info->extra_read += 12; // not documented, but generated by photoshop and handled by mspaint if (info->mr == info->mg && info->mg == info->mb) { // ?!?!? @@ -5185,6 +5502,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) return stbi__errpuc("bad BMP", "bad BMP"); } } else { + // V4/V5 header int i; if (hsz != 108 && hsz != 124) return stbi__errpuc("bad BMP", "bad BMP"); @@ -5192,6 +5510,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) info->mg = stbi__get32le(s); info->mb = stbi__get32le(s); info->ma = stbi__get32le(s); + if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs + stbi__bmp_set_mask_defaults(info, compress); stbi__get32le(s); // discard color space for (i=0; i < 12; ++i) stbi__get32le(s); // discard color space parameters @@ -5224,6 +5544,9 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req flip_vertically = ((int) s->img_y) > 0; s->img_y = abs((int) s->img_y); + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + mr = info.mr; mg = info.mg; mb = info.mb; @@ -5232,10 +5555,29 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req if (info.hsz == 12) { if (info.bpp < 24) - psize = (info.offset - 14 - 24) / 3; + psize = (info.offset - info.extra_read - 24) / 3; } else { if (info.bpp < 16) - psize = (info.offset - 14 - info.hsz) >> 2; + psize = (info.offset - info.extra_read - info.hsz) >> 2; + } + if (psize == 0) { + // accept some number of extra bytes after the header, but if the offset points either to before + // the header ends or implies a large amount of extra data, reject the file as malformed + int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); + int header_limit = 1024; // max we actually read is below 256 bytes currently. + int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. + if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { + return stbi__errpuc("bad header", "Corrupt BMP"); + } + // we established that bytes_read_so_far is positive and sensible. + // the first half of this test rejects offsets that are either too small positives, or + // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn + // ensures the number computed in the second half of the test can't overflow. + if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } else { + stbi__skip(s, info.offset - bytes_read_so_far); + } } if (info.bpp == 24 && ma == 0xff000000) @@ -5263,7 +5605,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req if (info.hsz != 12) stbi__get8(s); pal[i][3] = 255; } - stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); if (info.bpp == 1) width = (s->img_x + 7) >> 3; else if (info.bpp == 4) width = (s->img_x + 1) >> 1; else if (info.bpp == 8) width = s->img_x; @@ -5312,7 +5654,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; int z = 0; int easy=0; - stbi__skip(s, info.offset - 14 - info.hsz); + stbi__skip(s, info.offset - info.extra_read - info.hsz); if (info.bpp == 24) width = 3 * s->img_x; else if (info.bpp == 16) width = 2*s->img_x; else /* bpp = 32 and pad = 0 */ width=0; @@ -5330,6 +5672,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } } for (j=0; j < (int) s->img_y; ++j) { if (easy) { @@ -5554,6 +5897,9 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req STBI_NOTUSED(tga_x_origin); // @TODO STBI_NOTUSED(tga_y_origin); // @TODO + if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + // do a tiny bit of precessing if ( tga_image_type >= 8 ) { @@ -5593,6 +5939,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req // do I need to load a palette? if ( tga_indexed) { + if (tga_palette_len == 0) { /* you have to have at least one entry! */ + STBI_FREE(tga_data); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + // any data to skip? (offset usually = 0) stbi__skip(s, tga_palette_start ); // load the palette @@ -5801,6 +6152,9 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req h = stbi__get32be(s); w = stbi__get32be(s); + if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + // Make sure the depth is 8 bits. bitdepth = stbi__get16be(s); if (bitdepth != 8 && bitdepth != 16) @@ -6155,6 +6509,10 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c x = stbi__get16be(s); y = stbi__get16be(s); + + if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); @@ -6164,6 +6522,7 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c // intermediate buffer is RGBA result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + if (!result) return stbi__errpuc("outofmem", "Out of memory"); memset(result, 0xff, x*y*4); if (!stbi__pic_load_core(s,x,y,comp, result)) { @@ -6202,7 +6561,7 @@ typedef struct int w,h; stbi_uc *out; // output buffer (always 4 components) stbi_uc *background; // The current "background" as far as a gif is concerned - stbi_uc *history; + stbi_uc *history; int flags, bgindex, ratio, transparent, eflags; stbi_uc pal[256][4]; stbi_uc lpal[256][4]; @@ -6263,6 +6622,9 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in g->ratio = stbi__get8(s); g->transparent = -1; + if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments if (is_info) return 1; @@ -6276,6 +6638,7 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) { stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!g) return stbi__err("outofmem", "Out of memory"); if (!stbi__gif_header(s, g, comp, 1)) { STBI_FREE(g); stbi__rewind( s ); @@ -6290,7 +6653,7 @@ static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) { stbi_uc *p, *c; - int idx; + int idx; // recurse to decode the prefixes, since the linked-list is backwards, // and working backwards through an interleaved image would be nasty @@ -6299,12 +6662,12 @@ static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) if (g->cur_y >= g->max_y) return; - idx = g->cur_x + g->cur_y; + idx = g->cur_x + g->cur_y; p = &g->out[idx]; - g->history[idx / 4] = 1; + g->history[idx / 4] = 1; c = &g->color_table[g->codes[code].suffix * 4]; - if (c[3] > 128) { // don't render transparent pixels; + if (c[3] > 128) { // don't render transparent pixels; p[0] = c[2]; p[1] = c[1]; p[2] = c[0]; @@ -6413,14 +6776,14 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) // two back is the image from two frames ago, used for a very specific disposal format static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) { - int dispose; - int first_frame; - int pi; - int pcount; + int dispose; + int first_frame; + int pi; + int pcount; STBI_NOTUSED(req_comp); // on first frame, any non-written pixels get the background colour (non-transparent) - first_frame = 0; + first_frame = 0; if (g->out == 0) { if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) @@ -6432,17 +6795,17 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i if (!g->out || !g->background || !g->history) return stbi__errpuc("outofmem", "Out of memory"); - // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; // background colour is only used for pixels that are not rendered first frame, after that "background" - // color refers to the color that was there the previous frame. + // color refers to the color that was there the previous frame. memset(g->out, 0x00, 4 * pcount); memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) memset(g->history, 0x00, pcount); // pixels that were affected previous frame - first_frame = 1; + first_frame = 1; } else { - // second frame - how do we dispoase of the previous one? - dispose = (g->eflags & 0x1C) >> 2; - pcount = g->w * g->h; + // second frame - how do we dispose of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; if ((dispose == 3) && (two_back == 0)) { dispose = 2; // if I don't have an image to revert back to, default to the old background @@ -6451,32 +6814,32 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i if (dispose == 3) { // use previous graphic for (pi = 0; pi < pcount; ++pi) { if (g->history[pi]) { - memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); } } - } else if (dispose == 2) { - // restore what was changed last frame to background before that frame; + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; for (pi = 0; pi < pcount; ++pi) { if (g->history[pi]) { - memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); } } } else { - // This is a non-disposal case eithe way, so just + // This is a non-disposal case eithe way, so just // leave the pixels as is, and they will become the new background // 1: do not dispose // 0: not specified. } - // background is what out is after the undoing of the previou frame; - memcpy( g->background, g->out, 4 * g->w * g->h ); + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); } - // clear my history; + // clear my history; memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame for (;;) { - int tag = stbi__get8(s); + int tag = stbi__get8(s); switch (tag) { case 0x2C: /* Image Descriptor */ { @@ -6521,19 +6884,19 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i } else if (g->flags & 0x80) { g->color_table = (stbi_uc *) g->pal; } else - return stbi__errpuc("missing color table", "Corrupt GIF"); + return stbi__errpuc("missing color table", "Corrupt GIF"); o = stbi__process_gif_raster(s, g); if (!o) return NULL; - // if this was the first frame, - pcount = g->w * g->h; + // if this was the first frame, + pcount = g->w * g->h; if (first_frame && (g->bgindex > 0)) { // if first frame, any pixel not drawn to gets the background color for (pi = 0; pi < pcount; ++pi) { if (g->history[pi] == 0) { - g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; - memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); } } } @@ -6544,7 +6907,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i case 0x21: // Comment Extension. { int len; - int ext = stbi__get8(s); + int ext = stbi__get8(s); if (ext == 0xF9) { // Graphic Control Extension. len = stbi__get8(s); if (len == 4) { @@ -6553,23 +6916,23 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i // unset old transparent if (g->transparent >= 0) { - g->pal[g->transparent][3] = 255; - } + g->pal[g->transparent][3] = 255; + } if (g->eflags & 0x01) { g->transparent = stbi__get8(s); if (g->transparent >= 0) { - g->pal[g->transparent][3] = 0; + g->pal[g->transparent][3] = 0; } } else { // don't need transparent - stbi__skip(s, 1); - g->transparent = -1; + stbi__skip(s, 1); + g->transparent = -1; } } else { stbi__skip(s, len); break; } - } + } while ((len = stbi__get8(s)) != 0) { stbi__skip(s, len); } @@ -6585,18 +6948,35 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i } } +static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) +{ + STBI_FREE(g->out); + STBI_FREE(g->history); + STBI_FREE(g->background); + + if (out) STBI_FREE(out); + if (delays && *delays) STBI_FREE(*delays); + return stbi__errpuc("outofmem", "Out of memory"); +} + static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) { if (stbi__gif_test(s)) { - int layers = 0; + int layers = 0; stbi_uc *u = 0; stbi_uc *out = 0; - stbi_uc *two_back = 0; + stbi_uc *two_back = 0; stbi__gif g; - int stride; + int stride; + int out_size = 0; + int delays_size = 0; + + STBI_NOTUSED(out_size); + STBI_NOTUSED(delays_size); + memset(&g, 0, sizeof(g)); if (delays) { - *delays = 0; + *delays = 0; } do { @@ -6606,44 +6986,61 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, if (u) { *x = g.w; *y = g.h; - ++layers; - stride = g.w * g.h * 4; + ++layers; + stride = g.w * g.h * 4; if (out) { - out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); + if (!tmp) + return stbi__load_gif_main_outofmem(&g, out, delays); + else { + out = (stbi_uc*) tmp; + out_size = layers * stride; + } + if (delays) { - *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!new_delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + *delays = new_delays; + delays_size = layers * sizeof(int); } } else { - out = (stbi_uc*)stbi__malloc( layers * stride ); + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); + out_size = layers * stride; if (delays) { - *delays = (int*) stbi__malloc( layers * sizeof(int) ); + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + delays_size = layers * sizeof(int); } } - memcpy( out + ((layers - 1) * stride), u, stride ); + memcpy( out + ((layers - 1) * stride), u, stride ); if (layers >= 2) { - two_back = out - 2 * stride; + two_back = out - 2 * stride; } if (delays) { - (*delays)[layers - 1U] = g.delay; + (*delays)[layers - 1U] = g.delay; } } - } while (u != 0); + } while (u != 0); - // free temp buffer; - STBI_FREE(g.out); - STBI_FREE(g.history); - STBI_FREE(g.background); + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); - // do the final conversion after loading everything; + // do the final conversion after loading everything; if (req_comp && req_comp != 4) out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); - *z = layers; + *z = layers; return out; } else { - return stbi__errpuc("not GIF", "Image was not as a gif type."); + return stbi__errpuc("not GIF", "Image was not as a gif type."); } } @@ -6661,7 +7058,7 @@ static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req *y = g.h; // moved conversion to after successful load so that the same - // can be done for multiple frames. + // can be done for multiple frames. if (req_comp && req_comp != 4) u = stbi__convert_format(u, 4, req_comp, g.w, g.h); } else if (g.out) { @@ -6669,9 +7066,9 @@ static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req STBI_FREE(g.out); } - // free buffers needed for multiple frame loading; + // free buffers needed for multiple frame loading; STBI_FREE(g.history); - STBI_FREE(g.background); + STBI_FREE(g.background); return u; } @@ -6796,6 +7193,9 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re token += 3; width = (int) strtol(token, NULL, 10); + if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + *x = width; *y = height; @@ -6864,12 +7264,12 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re // Run value = stbi__get8(s); count -= 128; - if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = value; } else { // Dump - if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = stbi__get8(s); } @@ -6938,9 +7338,10 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) info.all_a = 255; p = stbi__bmp_parse_header(s, &info); - stbi__rewind( s ); - if (p == NULL) + if (p == NULL) { + stbi__rewind( s ); return 0; + } if (x) *x = s->img_x; if (y) *y = s->img_y; if (comp) { @@ -7006,8 +7407,8 @@ static int stbi__psd_is16(stbi__context *s) stbi__rewind( s ); return 0; } - (void) stbi__get32be(s); - (void) stbi__get32be(s); + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); depth = stbi__get16be(s); if (depth != 16) { stbi__rewind( s ); @@ -7086,7 +7487,6 @@ static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) // Known limitations: // Does not support comments in the header section // Does not support ASCII image data (formats P2 and P3) -// Does not support 16-bit-per-channel #ifndef STBI_NO_PNM @@ -7107,22 +7507,33 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req stbi_uc *out; STBI_NOTUSED(ri); - if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); + if (ri->bits_per_channel == 0) return 0; + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + *x = s->img_x; *y = s->img_y; if (comp) *comp = s->img_n; - if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) return stbi__errpuc("too large", "PNM too large"); - out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); + out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); - stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { + STBI_FREE(out); + return stbi__errpuc("bad PNM", "PNM file truncated"); + } if (req_comp && req_comp != s->img_n) { - out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (ri->bits_per_channel == 16) { + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); + } else { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + } if (out == NULL) return out; // stbi__convert_format frees input on failure } return out; @@ -7159,6 +7570,8 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c) while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { value = value*10 + (*c - '0'); *c = (char) stbi__get8(s); + if((value > 214748364) || (value == 214748364 && *c > '7')) + return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); } return value; @@ -7189,17 +7602,29 @@ static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) stbi__pnm_skip_whitespace(s, &c); *x = stbi__pnm_getinteger(s, &c); // read width + if(*x == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); stbi__pnm_skip_whitespace(s, &c); *y = stbi__pnm_getinteger(s, &c); // read height + if (*y == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); stbi__pnm_skip_whitespace(s, &c); maxv = stbi__pnm_getinteger(s, &c); // read max value - - if (maxv > 255) - return stbi__err("max value > 255", "PPM image not 8-bit"); + if (maxv > 65535) + return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); + else if (maxv > 255) + return 16; else - return 1; + return 8; +} + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; } #endif @@ -7255,6 +7680,9 @@ static int stbi__is_16_main(stbi__context *s) if (stbi__psd_is16(s)) return 1; #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif return 0; } @@ -7334,7 +7762,7 @@ STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user /* revision history: - 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 2.19 (2018-02-11) fix warning 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug diff --git a/src/common/thirdparty/stb/stb_sprintf.c b/src/common/thirdparty/stb/stb_sprintf.c new file mode 100644 index 0000000000..948362c3b8 --- /dev/null +++ b/src/common/thirdparty/stb/stb_sprintf.c @@ -0,0 +1,21 @@ +#define STB_SPRINTF_IMPLEMENTATION +#define STB_SPRINTF_UTF8_CHARS +#include "stb_sprintf.h" + +// We still need our own wrappers because they use a size_t for count, not an int. +int mysnprintf(char* buf, size_t count, char const* fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + + result = stbsp_vsnprintf(buf, (int)count, fmt, va); + va_end(va); + + return result; +} + +int myvsnprintf(char* buf, size_t count, const char* fmt, va_list va) +{ + return stbsp_vsnprintf(buf, (int)count, fmt, va); +} diff --git a/src/common/thirdparty/stb/stb_sprintf.h b/src/common/thirdparty/stb/stb_sprintf.h new file mode 100644 index 0000000000..ee4a601f88 --- /dev/null +++ b/src/common/thirdparty/stb/stb_sprintf.h @@ -0,0 +1,1947 @@ +// stb_sprintf - v1.10 - public domain snprintf() implementation +// originally by Jeff Roberts / RAD Game Tools, 2015/10/20 +// http://github.com/nothings/stb +// +// allowed types: sc uidBboXx p AaGgEef n +// lengths : hh h ll j z t I64 I32 I +// +// Contributors: +// Fabian "ryg" Giesen (reformatting) +// github:aganm (attribute format) +// +// Contributors (bugfixes): +// github:d26435 +// github:trex78 +// github:account-login +// Jari Komppa (SI suffixes) +// Rohit Nirmal +// Marcin Wojdyr +// Leonard Ritter +// Stefano Zanotti +// Adam Allison +// Arvid Gerstmann +// Markus Kolb +// +// LICENSE: +// +// See end of file for license information. + +#ifndef STB_SPRINTF_H_INCLUDE +#define STB_SPRINTF_H_INCLUDE + +/* +Single file sprintf replacement. + +Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. +Hereby placed in public domain. + +This is a full sprintf replacement that supports everything that +the C runtime sprintfs support, including float/double, 64-bit integers, +hex floats, field parameters (%*.*d stuff), length reads backs, etc. + +Why would you need this if sprintf already exists? Well, first off, +it's *much* faster (see below). It's also much smaller than the CRT +versions code-space-wise. We've also added some simple improvements +that are super handy (commas in thousands, callbacks at buffer full, +for example). Finally, the format strings for MSVC and GCC differ +for 64-bit integers (among other small things), so this lets you use +the same format strings in cross platform code. + +It uses the standard single file trick of being both the header file +and the source itself. If you just include it normally, you just get +the header file function definitions. To get the code, you include +it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first. + +It only uses va_args macros from the C runtime to do it's work. It +does cast doubles to S64s and shifts and divides U64s, which does +drag in CRT code on most platforms. + +It compiles to roughly 8K with float support, and 4K without. +As a comparison, when using MSVC static libs, calling sprintf drags +in 16K. + +API: +==== +int stbsp_sprintf( char * buf, char const * fmt, ... ) +int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) + Convert an arg list into a buffer. stbsp_snprintf always returns + a zero-terminated string (unlike regular snprintf). + +int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) +int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) + Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns + a zero-terminated string (unlike regular snprintf). + +int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) + typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len ); + Convert into a buffer, calling back every STB_SPRINTF_MIN chars. + Your callback can then copy the chars out, print them or whatever. + This function is actually the workhorse for everything else. + The buffer you pass in must hold at least STB_SPRINTF_MIN characters. + // you return the next buffer to use or 0 to stop converting + +void stbsp_set_separators( char comma, char period ) + Set the comma and period characters to use. + +FLOATS/DOUBLES: +=============== +This code uses a internal float->ascii conversion method that uses +doubles with error correction (double-doubles, for ~105 bits of +precision). This conversion is round-trip perfect - that is, an atof +of the values output here will give you the bit-exact double back. + +One difference is that our insignificant digits will be different than +with MSVC or GCC (but they don't match each other either). We also +don't attempt to find the minimum length matching float (pre-MSVC15 +doesn't either). + +If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT +and you'll save 4K of code space. + +64-BIT INTS: +============ +This library also supports 64-bit integers and you can use MSVC style or +GCC style indicators (%I64d or %lld). It supports the C99 specifiers +for size_t and ptr_diff_t (%jd %zd) as well. + +EXTRAS: +======= +Like some GCCs, for integers and floats, you can use a ' (single quote) +specifier and commas will be inserted on the thousands: "%'d" on 12345 +would print 12,345. + +For integers and floats, you can use a "$" specifier and the number +will be converted to float and then divided to get kilo, mega, giga or +tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is +"2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn +2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three +$:s: "%$$$d" -> "2.42 M". To remove the space between the number and the +suffix, add "_" specifier: "%_$d" -> "2.53M". + +In addition to octal and hexadecimal conversions, you can print +integers in binary: "%b" for 256 would print 100. + +PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): +=================================================================== +"%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) +"%24d" across all 32-bit ints (4.5x/4.2x faster) +"%x" across all 32-bit ints (4.5x/3.8x faster) +"%08x" across all 32-bit ints (4.3x/3.8x faster) +"%f" across e-10 to e+10 floats (7.3x/6.0x faster) +"%e" across e-10 to e+10 floats (8.1x/6.0x faster) +"%g" across e-10 to e+10 floats (10.0x/7.1x faster) +"%f" for values near e-300 (7.9x/6.5x faster) +"%f" for values near e+300 (10.0x/9.1x faster) +"%e" for values near e-300 (10.1x/7.0x faster) +"%e" for values near e+300 (9.2x/6.0x faster) +"%.320f" for values near e-300 (12.6x/11.2x faster) +"%a" for random values (8.6x/4.3x faster) +"%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) +"%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) +"%s%s%s" for 64 char strings (7.1x/7.3x faster) +"...512 char string..." ( 35.0x/32.5x faster!) +*/ + +#if defined(__clang__) + #if defined(__has_feature) && defined(__has_attribute) + #if __has_feature(address_sanitizer) + #if __has_attribute(__no_sanitize__) + #define STBSP__ASAN __attribute__((__no_sanitize__("address"))) + #elif __has_attribute(__no_sanitize_address__) + #define STBSP__ASAN __attribute__((__no_sanitize_address__)) + #elif __has_attribute(__no_address_safety_analysis__) + #define STBSP__ASAN __attribute__((__no_address_safety_analysis__)) + #endif + #endif + #endif +#elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) + #if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ + #define STBSP__ASAN __attribute__((__no_sanitize_address__)) + #endif +#endif + +#ifndef STBSP__ASAN +#define STBSP__ASAN +#endif + +#ifdef STB_SPRINTF_STATIC +#define STBSP__PUBLICDEC static +#define STBSP__PUBLICDEF static STBSP__ASAN +#else +#ifdef __cplusplus +#define STBSP__PUBLICDEC extern "C" +#define STBSP__PUBLICDEF extern "C" STBSP__ASAN +#else +#define STBSP__PUBLICDEC extern +#define STBSP__PUBLICDEF STBSP__ASAN +#endif +#endif + +#if defined(__has_attribute) + #if __has_attribute(format) + #define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va))) + #endif +#endif + +#ifndef STBSP__ATTRIBUTE_FORMAT +#define STBSP__ATTRIBUTE_FORMAT(fmt,va) +#endif + +#ifdef _MSC_VER +#define STBSP__NOTUSED(v) (void)(v) +#else +#define STBSP__NOTUSED(v) (void)sizeof(v) +#endif + +#include // for va_arg(), va_list() +#include // size_t, ptrdiff_t + +#ifndef STB_SPRINTF_MIN +#define STB_SPRINTF_MIN 512 // how many characters per callback +#endif +typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); + +#ifndef STB_SPRINTF_DECORATE +#define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names +#endif + +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4); + +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); +STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); + +#endif // STB_SPRINTF_H_INCLUDE + +#ifdef STB_SPRINTF_IMPLEMENTATION + +#define stbsp__uint32 unsigned int +#define stbsp__int32 signed int + +#ifdef _MSC_VER +#define stbsp__uint64 unsigned __int64 +#define stbsp__int64 signed __int64 +#else +#define stbsp__uint64 unsigned long long +#define stbsp__int64 signed long long +#endif +#define stbsp__uint16 unsigned short + +#ifndef stbsp__uintptr +#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) +#define stbsp__uintptr stbsp__uint64 +#else +#define stbsp__uintptr stbsp__uint32 +#endif +#endif + +#ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define STB_SPRINTF_MSVC_MODE +#endif +#endif + +#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses +#define STBSP__UNALIGNED(code) +#else +#define STBSP__UNALIGNED(code) code +#endif + +#ifndef STB_SPRINTF_NOFLOAT +// internal float utility functions +static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits); +static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value); +#define STBSP__SPECIAL 0x7000 +#endif + +static char stbsp__period = '.'; +static char stbsp__comma = ','; +static struct +{ + short temp; // force next field to be 2-byte aligned + char pair[201]; +} stbsp__digitpair = +{ + 0, + "00010203040506070809101112131415161718192021222324" + "25262728293031323334353637383940414243444546474849" + "50515253545556575859606162636465666768697071727374" + "75767778798081828384858687888990919293949596979899" +}; + +#ifdef STB_SPRINTF_UTF8_CHARS +static int stbsp_utf8_encode(int codepoint, char* buffer) +{ + if (codepoint < -0x80 || codepoint > 0x10FFFF) + { + codepoint = 0xfffd; + } + if (codepoint < 0x80) + { + buffer[0] = (char)codepoint; + return 1; + } + else if (codepoint < 0x800) + { + buffer[0] = 0xC0 + ((codepoint & 0x7C0) >> 6); + buffer[1] = 0x80 + ((codepoint & 0x03F)); + return 2; + } + else if (codepoint < 0x10000) + { + buffer[0] = 0xE0 + ((codepoint & 0xF000) >> 12); + buffer[1] = 0x80 + ((codepoint & 0x0FC0) >> 6); + buffer[2] = 0x80 + ((codepoint & 0x003F)); + return 3; + } + else + { + buffer[0] = 0xF0 + ((codepoint & 0x1C0000) >> 18); + buffer[1] = 0x80 + ((codepoint & 0x03F000) >> 12); + buffer[2] = 0x80 + ((codepoint & 0x000FC0) >> 6); + buffer[3] = 0x80 + ((codepoint & 0x00003F)); + return 4; + } +} +#endif + +STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod) +{ + stbsp__period = pperiod; + stbsp__comma = pcomma; +} + +#define STBSP__LEFTJUST 1 +#define STBSP__LEADINGPLUS 2 +#define STBSP__LEADINGSPACE 4 +#define STBSP__LEADING_0X 8 +#define STBSP__LEADINGZERO 16 +#define STBSP__INTMAX 32 +#define STBSP__TRIPLET_COMMA 64 +#define STBSP__NEGATIVE 128 +#define STBSP__METRIC_SUFFIX 256 +#define STBSP__HALFWIDTH 512 +#define STBSP__METRIC_NOSPACE 1024 +#define STBSP__METRIC_1024 2048 +#define STBSP__METRIC_JEDEC 4096 + +static void stbsp__lead_sign(stbsp__uint32 fl, char *sign) +{ + sign[0] = 0; + if (fl & STBSP__NEGATIVE) { + sign[0] = 1; + sign[1] = '-'; + } else if (fl & STBSP__LEADINGSPACE) { + sign[0] = 1; + sign[1] = ' '; + } else if (fl & STBSP__LEADINGPLUS) { + sign[0] = 1; + sign[1] = '+'; + } +} + +static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit) +{ + char const * sn = s; + + // get up to 4-byte alignment + for (;;) { + if (((stbsp__uintptr)sn & 3) == 0) + break; + + if (!limit || *sn == 0) + return (stbsp__uint32)(sn - s); + + ++sn; + --limit; + } + + // scan over 4 bytes at a time to find terminating 0 + // this will intentionally scan up to 3 bytes past the end of buffers, + // but becase it works 4B aligned, it will never cross page boundaries + // (hence the STBSP__ASAN markup; the over-read here is intentional + // and harmless) + while (limit >= 4) { + stbsp__uint32 v = *(stbsp__uint32 *)sn; + // bit hack to find if there's a 0 byte in there + if ((v - 0x01010101) & (~v) & 0x80808080UL) + break; + + sn += 4; + limit -= 4; + } + + // handle the last few characters to find actual size + while (limit && *sn) { + ++sn; + --limit; + } + + return (stbsp__uint32)(sn - s); +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va) +{ + static char hex[] = "0123456789abcdefxp"; + static char hexu[] = "0123456789ABCDEFXP"; + char *bf; + char const *f; + int tlen = 0; + + bf = buf; + f = fmt; + for (;;) { + stbsp__int32 fw, pr, tz; + stbsp__uint32 fl; + + // macros for the callback buffer stuff + #define stbsp__chk_cb_bufL(bytes) \ + { \ + int len = (int)(bf - buf); \ + if ((len + (bytes)) >= STB_SPRINTF_MIN) { \ + tlen += len; \ + if (0 == (bf = buf = callback(buf, user, len))) \ + goto done; \ + } \ + } + #define stbsp__chk_cb_buf(bytes) \ + { \ + if (callback) { \ + stbsp__chk_cb_bufL(bytes); \ + } \ + } + #define stbsp__flush_cb() \ + { \ + stbsp__chk_cb_bufL(STB_SPRINTF_MIN - 1); \ + } // flush if there is even one byte in the buffer + #define stbsp__cb_buf_clamp(cl, v) \ + cl = v; \ + if (callback) { \ + int lg = STB_SPRINTF_MIN - (int)(bf - buf); \ + if (cl > lg) \ + cl = lg; \ + } + + // fast copy everything up to the next % (or end of string) + for (;;) { + while (((stbsp__uintptr)f) & 3) { + schk1: + if (f[0] == '%') + goto scandd; + schk2: + if (f[0] == 0) + goto endfmt; + stbsp__chk_cb_buf(1); + *bf++ = f[0]; + ++f; + } + for (;;) { + // Check if the next 4 bytes contain %(0x25) or end of string. + // Using the 'hasless' trick: + // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord + stbsp__uint32 v, c; + v = *(stbsp__uint32 *)f; + c = (~v) & 0x80808080; + if (((v ^ 0x25252525) - 0x01010101) & c) + goto schk1; + if ((v - 0x01010101) & c) + goto schk2; + if (callback) + if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4) + goto schk1; + #ifdef STB_SPRINTF_NOUNALIGNED + if(((stbsp__uintptr)bf) & 3) { + bf[0] = f[0]; + bf[1] = f[1]; + bf[2] = f[2]; + bf[3] = f[3]; + } else + #endif + { + *(stbsp__uint32 *)bf = v; + } + bf += 4; + f += 4; + } + } + scandd: + + ++f; + + // ok, we have a percent, read the modifiers first + fw = 0; + pr = -1; + fl = 0; + tz = 0; + + // flags + for (;;) { + switch (f[0]) { + // if we have left justify + case '-': + fl |= STBSP__LEFTJUST; + ++f; + continue; + // if we have leading plus + case '+': + fl |= STBSP__LEADINGPLUS; + ++f; + continue; + // if we have leading space + case ' ': + fl |= STBSP__LEADINGSPACE; + ++f; + continue; + // if we have leading 0x + case '#': + fl |= STBSP__LEADING_0X; + ++f; + continue; + // if we have thousand commas + case '\'': + fl |= STBSP__TRIPLET_COMMA; + ++f; + continue; + // if we have kilo marker (none->kilo->kibi->jedec) + case '$': + if (fl & STBSP__METRIC_SUFFIX) { + if (fl & STBSP__METRIC_1024) { + fl |= STBSP__METRIC_JEDEC; + } else { + fl |= STBSP__METRIC_1024; + } + } else { + fl |= STBSP__METRIC_SUFFIX; + } + ++f; + continue; + // if we don't want space between metric suffix and number + case '_': + fl |= STBSP__METRIC_NOSPACE; + ++f; + continue; + // if we have leading zero + case '0': + fl |= STBSP__LEADINGZERO; + ++f; + goto flags_done; + default: goto flags_done; + } + } + flags_done: + + // get the field width + if (f[0] == '*') { + fw = va_arg(va, stbsp__uint32); + ++f; + } else { + while ((f[0] >= '0') && (f[0] <= '9')) { + fw = fw * 10 + f[0] - '0'; + f++; + } + } + // get the precision + if (f[0] == '.') { + ++f; + if (f[0] == '*') { + pr = va_arg(va, stbsp__uint32); + ++f; + } else { + pr = 0; + while ((f[0] >= '0') && (f[0] <= '9')) { + pr = pr * 10 + f[0] - '0'; + f++; + } + } + } + + // handle integer size overrides + switch (f[0]) { + // are we halfwidth? + case 'h': + fl |= STBSP__HALFWIDTH; + ++f; + if (f[0] == 'h') + ++f; // QUARTERWIDTH + break; + // are we 64-bit (unix style) + case 'l': + fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0); + ++f; + if (f[0] == 'l') { + fl |= STBSP__INTMAX; + ++f; + } + break; + // are we 64-bit on intmax? (c99) + case 'j': + fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + // are we 64-bit on size_t or ptrdiff_t? (c99) + case 'z': + fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + case 't': + fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + // are we 64-bit (msft style) + case 'I': + if ((f[1] == '6') && (f[2] == '4')) { + fl |= STBSP__INTMAX; + f += 3; + } else if ((f[1] == '3') && (f[2] == '2')) { + f += 3; + } else { + fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0); + ++f; + } + break; + default: break; + } + + // handle each replacement + switch (f[0]) { + #define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307 + char num[STBSP__NUMSZ]; + char lead[8]; + char tail[8]; + char *s; + char const *h; + stbsp__uint32 l, n, cs; + stbsp__uint64 n64; +#ifndef STB_SPRINTF_NOFLOAT + double fv; +#endif + stbsp__int32 dp; + char const *sn; + + case 's': + // get the string + s = va_arg(va, char *); + if (s == 0) + s = (char *)"null"; + // get the length, limited to desired precision + // always limit to ~0u chars since our counts are 32b + l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + // copy the string in + goto scopy; + + case 'c': // char + // get the character +#ifndef STB_SPRINTF_UTF8_CHARS + s = num + STBSP__NUMSZ - 1; + *s = (char)va_arg(va, int); + l = 1; +#else + s = num + STBSP__NUMSZ - 4; // UTF-8 needs 4 bytes at most. + l = stbsp_utf8_encode(va_arg(va, int), s); +#endif + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + goto scopy; + + case 'n': // weird write-bytes specifier + { + int *d = va_arg(va, int *); + *d = tlen + (int)(bf - buf); + } break; + +#ifdef STB_SPRINTF_NOFLOAT + case 'A': // float + case 'a': // hex float + case 'G': // float + case 'g': // float + case 'E': // float + case 'e': // float + case 'f': // float + va_arg(va, double); // eat it + s = (char *)"No float"; + l = 8; + lead[0] = 0; + tail[0] = 0; + pr = 0; + cs = 0; + STBSP__NOTUSED(dp); + goto scopy; +#else + case 'A': // hex float + case 'a': // hex float + h = (f[0] == 'A') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv)) + fl |= STBSP__NEGATIVE; + + s = num + 64; + + stbsp__lead_sign(fl, lead); + + if (dp == -1023) + dp = (n64) ? -1022 : 0; + else + n64 |= (((stbsp__uint64)1) << 52); + n64 <<= (64 - 56); + if (pr < 15) + n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4)); +// add leading chars + +#ifdef STB_SPRINTF_MSVC_MODE + *s++ = '0'; + *s++ = 'x'; +#else + lead[1 + lead[0]] = '0'; + lead[2 + lead[0]] = 'x'; + lead[0] += 2; +#endif + *s++ = h[(n64 >> 60) & 15]; + n64 <<= 4; + if (pr) + *s++ = stbsp__period; + sn = s; + + // print the bits + n = pr; + if (n > 13) + n = 13; + if (pr > (stbsp__int32)n) + tz = pr - n; + pr = 0; + while (n--) { + *s++ = h[(n64 >> 60) & 15]; + n64 <<= 4; + } + + // print the expo + tail[1] = h[17]; + if (dp < 0) { + tail[2] = '-'; + dp = -dp; + } else + tail[2] = '+'; + n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3)); + tail[0] = (char)n; + for (;;) { + tail[n] = '0' + dp % 10; + if (n <= 3) + break; + --n; + dp /= 10; + } + + dp = (int)(s - sn); + l = (int)(s - (num + 64)); + s = num + 64; + cs = 1 + (3 << 24); + goto scopy; + + case 'G': // float + case 'g': // float + h = (f[0] == 'G') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; + else if (pr == 0) + pr = 1; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000)) + fl |= STBSP__NEGATIVE; + + // clamp the precision and delete extra zeros after clamp + n = pr; + if (l > (stbsp__uint32)pr) + l = pr; + while ((l > 1) && (pr) && (sn[l - 1] == '0')) { + --pr; + --l; + } + + // should we use %e + if ((dp <= -4) || (dp > (stbsp__int32)n)) { + if (pr > (stbsp__int32)l) + pr = l - 1; + else if (pr) + --pr; // when using %e, there is one digit before the decimal + goto doexpfromg; + } + // this is the insane action to get the pr to match %g semantics for %f + if (dp > 0) { + pr = (dp < (stbsp__int32)l) ? l - dp : 0; + } else { + pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32) l : pr); + } + goto dofloatfromg; + + case 'E': // float + case 'e': // float + h = (f[0] == 'E') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000)) + fl |= STBSP__NEGATIVE; + doexpfromg: + tail[0] = 0; + stbsp__lead_sign(fl, lead); + if (dp == STBSP__SPECIAL) { + s = (char *)sn; + cs = 0; + pr = 0; + goto scopy; + } + s = num + 64; + // handle leading chars + *s++ = sn[0]; + + if (pr) + *s++ = stbsp__period; + + // handle after decimal + if ((l - 1) > (stbsp__uint32)pr) + l = pr + 1; + for (n = 1; n < l; n++) + *s++ = sn[n]; + // trailing zeros + tz = pr - (l - 1); + pr = 0; + // dump expo + tail[1] = h[0xe]; + dp -= 1; + if (dp < 0) { + tail[2] = '-'; + dp = -dp; + } else + tail[2] = '+'; +#ifdef STB_SPRINTF_MSVC_MODE + n = 5; +#else + n = (dp >= 100) ? 5 : 4; +#endif + tail[0] = (char)n; + for (;;) { + tail[n] = '0' + dp % 10; + if (n <= 3) + break; + --n; + dp /= 10; + } + cs = 1 + (3 << 24); // how many tens + goto flt_lead; + + case 'f': // float + fv = va_arg(va, double); + doafloat: + // do kilos + if (fl & STBSP__METRIC_SUFFIX) { + double divisor; + divisor = 1000.0f; + if (fl & STBSP__METRIC_1024) + divisor = 1024.0; + while (fl < 0x4000000) { + if ((fv < divisor) && (fv > -divisor)) + break; + fv /= divisor; + fl += 0x1000000; + } + } + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr)) + fl |= STBSP__NEGATIVE; + dofloatfromg: + tail[0] = 0; + stbsp__lead_sign(fl, lead); + if (dp == STBSP__SPECIAL) { + s = (char *)sn; + cs = 0; + pr = 0; + goto scopy; + } + s = num + 64; + + // handle the three decimal varieties + if (dp <= 0) { + stbsp__int32 i; + // handle 0.000*000xxxx + *s++ = '0'; + if (pr) + *s++ = stbsp__period; + n = -dp; + if ((stbsp__int32)n > pr) + n = pr; + i = n; + while (i) { + if ((((stbsp__uintptr)s) & 3) == 0) + break; + *s++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)s = 0x30303030; + s += 4; + i -= 4; + } + while (i) { + *s++ = '0'; + --i; + } + if ((stbsp__int32)(l + n) > pr) + l = pr - n; + i = l; + while (i) { + *s++ = *sn++; + --i; + } + tz = pr - (n + l); + cs = 1 + (3 << 24); // how many tens did we write (for commas below) + } else { + cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0; + if ((stbsp__uint32)dp >= l) { + // handle xxxx000*000.0 + n = 0; + for (;;) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = sn[n]; + ++n; + if (n >= l) + break; + } + } + if (n < (stbsp__uint32)dp) { + n = dp - n; + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + while (n) { + if ((((stbsp__uintptr)s) & 3) == 0) + break; + *s++ = '0'; + --n; + } + while (n >= 4) { + *(stbsp__uint32 *)s = 0x30303030; + s += 4; + n -= 4; + } + } + while (n) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = '0'; + --n; + } + } + } + cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens + if (pr) { + *s++ = stbsp__period; + tz = pr; + } + } else { + // handle xxxxx.xxxx000*000 + n = 0; + for (;;) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = sn[n]; + ++n; + if (n >= (stbsp__uint32)dp) + break; + } + } + cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens + if (pr) + *s++ = stbsp__period; + if ((l - dp) > (stbsp__uint32)pr) + l = pr + dp; + while (n < l) { + *s++ = sn[n]; + ++n; + } + tz = pr - (l - dp); + } + } + pr = 0; + + // handle k,m,g,t + if (fl & STBSP__METRIC_SUFFIX) { + char idx; + idx = 1; + if (fl & STBSP__METRIC_NOSPACE) + idx = 0; + tail[0] = idx; + tail[1] = ' '; + { + if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'. + if (fl & STBSP__METRIC_1024) + tail[idx + 1] = "_KMGT"[fl >> 24]; + else + tail[idx + 1] = "_kMGT"[fl >> 24]; + idx++; + // If printing kibits and not in jedec, add the 'i'. + if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) { + tail[idx + 1] = 'i'; + idx++; + } + tail[0] = idx; + } + } + }; + + flt_lead: + // get the length that we copied + l = (stbsp__uint32)(s - (num + 64)); + s = num + 64; + goto scopy; +#endif + + case 'B': // upper binary + case 'b': // lower binary + h = (f[0] == 'B') ? hexu : hex; + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 2; + lead[1] = '0'; + lead[2] = h[0xb]; + } + l = (8 << 4) | (1 << 8); + goto radixnum; + + case 'o': // octal + h = hexu; + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 1; + lead[1] = '0'; + } + l = (3 << 4) | (3 << 8); + goto radixnum; + + case 'p': // pointer + fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0; + pr = sizeof(void *) * 2; + fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros + // fall through - to X + + case 'X': // upper hex + case 'x': // lower hex + h = (f[0] == 'X') ? hexu : hex; + l = (4 << 4) | (4 << 8); + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 2; + lead[1] = '0'; + lead[2] = h[16]; + } + radixnum: + // get the number + if (fl & STBSP__INTMAX) + n64 = va_arg(va, stbsp__uint64); + else + n64 = va_arg(va, stbsp__uint32); + + s = num + STBSP__NUMSZ; + dp = 0; + // clear tail, and clear leading if value is zero + tail[0] = 0; + if (n64 == 0) { + lead[0] = 0; + if (pr == 0) { + l = 0; + cs = 0; + goto scopy; + } + } + // convert to string + for (;;) { + *--s = h[n64 & ((1 << (l >> 8)) - 1)]; + n64 >>= (l >> 8); + if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr))) + break; + if (fl & STBSP__TRIPLET_COMMA) { + ++l; + if ((l & 15) == ((l >> 4) & 15)) { + l &= ~15; + *--s = stbsp__comma; + } + } + }; + // get the tens and the comma pos + cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24); + // get the length that we copied + l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); + // copy it + goto scopy; + + case 'u': // unsigned + case 'i': + case 'd': // integer + // get the integer and abs it + if (fl & STBSP__INTMAX) { + stbsp__int64 i64 = va_arg(va, stbsp__int64); + n64 = (stbsp__uint64)i64; + if ((f[0] != 'u') && (i64 < 0)) { + n64 = (stbsp__uint64)-i64; + fl |= STBSP__NEGATIVE; + } + } else { + stbsp__int32 i = va_arg(va, stbsp__int32); + n64 = (stbsp__uint32)i; + if ((f[0] != 'u') && (i < 0)) { + n64 = (stbsp__uint32)-i; + fl |= STBSP__NEGATIVE; + } + } + +#ifndef STB_SPRINTF_NOFLOAT + if (fl & STBSP__METRIC_SUFFIX) { + if (n64 < 1024) + pr = 0; + else if (pr == -1) + pr = 1; + fv = (double)(stbsp__int64)n64; + goto doafloat; + } +#endif + + // convert to string + s = num + STBSP__NUMSZ; + l = 0; + + for (;;) { + // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) + char *o = s - 8; + if (n64 >= 100000000) { + n = (stbsp__uint32)(n64 % 100000000); + n64 /= 100000000; + } else { + n = (stbsp__uint32)n64; + n64 = 0; + } + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + do { + s -= 2; + *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; + n /= 100; + } while (n); + } + while (n) { + if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { + l = 0; + *--s = stbsp__comma; + --o; + } else { + *--s = (char)(n % 10) + '0'; + n /= 10; + } + } + if (n64 == 0) { + if ((s[0] == '0') && (s != (num + STBSP__NUMSZ))) + ++s; + break; + } + while (s != o) + if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { + l = 0; + *--s = stbsp__comma; + --o; + } else { + *--s = '0'; + } + } + + tail[0] = 0; + stbsp__lead_sign(fl, lead); + + // get the length that we copied + l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); + if (l == 0) { + *--s = '0'; + l = 1; + } + cs = l + (3 << 24); + if (pr < 0) + pr = 0; + + scopy: + // get fw=leading/trailing space, pr=leading zeros + if (pr < (stbsp__int32)l) + pr = l; + n = pr + lead[0] + tail[0] + tz; + if (fw < (stbsp__int32)n) + fw = n; + fw -= n; + pr -= l; + + // handle right justify and leading zeros + if ((fl & STBSP__LEFTJUST) == 0) { + if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr + { + pr = (fw > pr) ? fw : pr; + fw = 0; + } else { + fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas + } + } + + // copy the spaces and/or zeros + if (fw + pr) { + stbsp__int32 i; + stbsp__uint32 c; + + // copy leading spaces (or when doing %8.4d stuff) + if ((fl & STBSP__LEFTJUST) == 0) + while (fw > 0) { + stbsp__cb_buf_clamp(i, fw); + fw -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = ' '; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x20202020; + bf += 4; + i -= 4; + } + while (i) { + *bf++ = ' '; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy leader + sn = lead + 1; + while (lead[0]) { + stbsp__cb_buf_clamp(i, lead[0]); + lead[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy leading zeros + c = cs >> 24; + cs &= 0xffffff; + cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0; + while (pr > 0) { + stbsp__cb_buf_clamp(i, pr); + pr -= i; + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x30303030; + bf += 4; + i -= 4; + } + } + while (i) { + if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) { + cs = 0; + *bf++ = stbsp__comma; + } else + *bf++ = '0'; + --i; + } + stbsp__chk_cb_buf(1); + } + } + + // copy leader if there is still one + sn = lead + 1; + while (lead[0]) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, lead[0]); + lead[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy the string + n = l; + while (n) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, n); + n -= i; + STBSP__UNALIGNED(while (i >= 4) { + *(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s; + bf += 4; + s += 4; + i -= 4; + }) + while (i) { + *bf++ = *s++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy trailing zeros + while (tz) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, tz); + tz -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x30303030; + bf += 4; + i -= 4; + } + while (i) { + *bf++ = '0'; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy tail if there is one + sn = tail + 1; + while (tail[0]) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, tail[0]); + tail[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // handle the left justify + if (fl & STBSP__LEFTJUST) + if (fw > 0) { + while (fw) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, fw); + fw -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = ' '; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x20202020; + bf += 4; + i -= 4; + } + while (i--) + *bf++ = ' '; + stbsp__chk_cb_buf(1); + } + } + break; + + default: // unknown, just copy code + s = num + STBSP__NUMSZ - 1; + *s = f[0]; + l = 1; + fw = fl = 0; + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + goto scopy; + } + ++f; + } +endfmt: + + if (!callback) + *bf = 0; + else + stbsp__flush_cb(); + +done: + return tlen + (int)(bf - buf); +} + +// cleanup +#undef STBSP__LEFTJUST +#undef STBSP__LEADINGPLUS +#undef STBSP__LEADINGSPACE +#undef STBSP__LEADING_0X +#undef STBSP__LEADINGZERO +#undef STBSP__INTMAX +#undef STBSP__TRIPLET_COMMA +#undef STBSP__NEGATIVE +#undef STBSP__METRIC_SUFFIX +#undef STBSP__NUMSZ +#undef stbsp__chk_cb_bufL +#undef stbsp__chk_cb_buf +#undef stbsp__flush_cb +#undef stbsp__cb_buf_clamp + +// ============================================================================ +// wrapper functions + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); + va_end(va); + return result; +} + +typedef struct stbsp__context { + char *buf; + int count; + int length; + char tmp[STB_SPRINTF_MIN]; +} stbsp__context; + +static char *stbsp__clamp_callback(const char *buf, void *user, int len) +{ + stbsp__context *c = (stbsp__context *)user; + c->length += len; + + if (len > c->count) + len = c->count; + + if (len) { + if (buf != c->buf) { + const char *s, *se; + char *d; + d = c->buf; + s = buf; + se = buf + len; + do { + *d++ = *s++; + } while (s < se); + } + c->buf += len; + c->count -= len; + } + + if (c->count <= 0) + return c->tmp; + return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can +} + +static char * stbsp__count_clamp_callback( const char * buf, void * user, int len ) +{ + stbsp__context * c = (stbsp__context*)user; + (void) sizeof(buf); + + c->length += len; + return c->tmp; // go direct into buffer if you can +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) +{ + stbsp__context c; + + if ( (count == 0) && !buf ) + { + c.length = 0; + + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va ); + } + else + { + int l; + + c.buf = buf; + c.count = count; + c.length = 0; + + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va ); + + // zero-terminate + l = (int)( c.buf - buf ); + if ( l >= count ) // should never be greater, only equal (or less) than count + l = count - 1; + buf[l] = 0; + } + + return c.length; +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + + result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va); + va_end(va); + + return result; +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va) +{ + return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); +} + +// ======================================================================= +// low level float utility functions + +#ifndef STB_SPRINTF_NOFLOAT + +// copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) +#define STBSP__COPYFP(dest, src) \ + { \ + int cn; \ + for (cn = 0; cn < 8; cn++) \ + ((char *)&dest)[cn] = ((char *)&src)[cn]; \ + } + +// get float info +static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value) +{ + double d; + stbsp__int64 b = 0; + + // load value and round at the frac_digits + d = value; + + STBSP__COPYFP(b, d); + + *bits = b & ((((stbsp__uint64)1) << 52) - 1); + *expo = (stbsp__int32)(((b >> 52) & 2047) - 1023); + + return (stbsp__int32)((stbsp__uint64) b >> 63); +} + +static double const stbsp__bot[23] = { + 1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011, + 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022 +}; +static double const stbsp__negbot[22] = { + 1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011, + 1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022 +}; +static double const stbsp__negboterr[22] = { + -5.551115123125783e-018, -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023, + 4.5251888174113739e-024, -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028, 2.0113352370744385e-029, + -3.0373745563400371e-030, 1.1806906454401013e-032, -7.7705399876661076e-032, 2.0902213275965398e-033, -7.1542424054621921e-034, -7.1542424054621926e-035, + 2.4754073164739869e-036, 5.4846728545790429e-037, 9.2462547772103625e-038, -4.8596774326570872e-039 +}; +static double const stbsp__top[13] = { + 1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207, 1e+230, 1e+253, 1e+276, 1e+299 +}; +static double const stbsp__negtop[13] = { + 1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207, 1e-230, 1e-253, 1e-276, 1e-299 +}; +static double const stbsp__toperr[13] = { + 8388608, + 6.8601809640529717e+028, + -7.253143638152921e+052, + -4.3377296974619174e+075, + -1.5559416129466825e+098, + -3.2841562489204913e+121, + -3.7745893248228135e+144, + -1.7356668416969134e+167, + -3.8893577551088374e+190, + -9.9566444326005119e+213, + 6.3641293062232429e+236, + -5.2069140800249813e+259, + -5.2504760255204387e+282 +}; +static double const stbsp__negtoperr[13] = { + 3.9565301985100693e-040, -2.299904345391321e-063, 3.6506201437945798e-086, 1.1875228833981544e-109, + -5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178, -5.7778912386589953e-201, + 7.4997100559334532e-224, -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293, + 8.0970921678014997e-317 +}; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +static stbsp__uint64 const stbsp__powten[20] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, + 10000000000000000000U +}; +#define stbsp__tento19th ((stbsp__uint64)1000000000000000000) +#else +static stbsp__uint64 const stbsp__powten[20] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000ULL, + 100000000000ULL, + 1000000000000ULL, + 10000000000000ULL, + 100000000000000ULL, + 1000000000000000ULL, + 10000000000000000ULL, + 100000000000000000ULL, + 1000000000000000000ULL, + 10000000000000000000ULL +}; +#define stbsp__tento19th (1000000000000000000ULL) +#endif + +#define stbsp__ddmulthi(oh, ol, xh, yh) \ + { \ + double ahi = 0, alo, bhi = 0, blo; \ + stbsp__int64 bt; \ + oh = xh * yh; \ + STBSP__COPYFP(bt, xh); \ + bt &= ((~(stbsp__uint64)0) << 27); \ + STBSP__COPYFP(ahi, bt); \ + alo = xh - ahi; \ + STBSP__COPYFP(bt, yh); \ + bt &= ((~(stbsp__uint64)0) << 27); \ + STBSP__COPYFP(bhi, bt); \ + blo = yh - bhi; \ + ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \ + } + +#define stbsp__ddtoS64(ob, xh, xl) \ + { \ + double ahi = 0, alo, vh, t; \ + ob = (stbsp__int64)xh; \ + vh = (double)ob; \ + ahi = (xh - vh); \ + t = (ahi - xh); \ + alo = (xh - (ahi - t)) - (vh + t); \ + ob += (stbsp__int64)(ahi + alo + xl); \ + } + +#define stbsp__ddrenorm(oh, ol) \ + { \ + double s; \ + s = oh + ol; \ + ol = ol - (s - oh); \ + oh = s; \ + } + +#define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh); + +#define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl); + +static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350 +{ + double ph, pl; + if ((power >= 0) && (power <= 22)) { + stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]); + } else { + stbsp__int32 e, et, eb; + double p2h, p2l; + + e = power; + if (power < 0) + e = -e; + et = (e * 0x2c9) >> 14; /* %23 */ + if (et > 13) + et = 13; + eb = e - (et * 23); + + ph = d; + pl = 0.0; + if (power < 0) { + if (eb) { + --eb; + stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]); + stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]); + } + if (et) { + stbsp__ddrenorm(ph, pl); + --et; + stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]); + stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]); + ph = p2h; + pl = p2l; + } + } else { + if (eb) { + e = eb; + if (eb > 22) + eb = 22; + e -= eb; + stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]); + if (e) { + stbsp__ddrenorm(ph, pl); + stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]); + stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl); + ph = p2h; + pl = p2l; + } + } + if (et) { + stbsp__ddrenorm(ph, pl); + --et; + stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]); + stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]); + ph = p2h; + pl = p2l; + } + } + } + stbsp__ddrenorm(ph, pl); + *ohi = ph; + *olo = pl; +} + +// given a float value, returns the significant bits in bits, and the position of the +// decimal point in decimal_pos. +/-INF and NAN are specified by special values +// returned in the decimal_pos parameter. +// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 +static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits) +{ + double d; + stbsp__int64 bits = 0; + stbsp__int32 expo, e, ng, tens; + + d = value; + STBSP__COPYFP(bits, d); + expo = (stbsp__int32)((bits >> 52) & 2047); + ng = (stbsp__int32)((stbsp__uint64) bits >> 63); + if (ng) + d = -d; + + if (expo == 2047) // is nan or inf? + { + *start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf"; + *decimal_pos = STBSP__SPECIAL; + *len = 3; + return ng; + } + + if (expo == 0) // is zero or denormal + { + if (((stbsp__uint64) bits << 1) == 0) // do zero + { + *decimal_pos = 1; + *start = out; + out[0] = '0'; + *len = 1; + return ng; + } + // find the right expo for denormals + { + stbsp__int64 v = ((stbsp__uint64)1) << 51; + while ((bits & v) == 0) { + --expo; + v >>= 1; + } + } + } + + // find the decimal exponent as well as the decimal bits of the value + { + double ph, pl; + + // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046 + tens = expo - 1023; + tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1); + + // move the significant bits into position and stick them into an int + stbsp__raise_to_power10(&ph, &pl, d, 18 - tens); + + // get full as much precision from double-double as possible + stbsp__ddtoS64(bits, ph, pl); + + // check if we undershot + if (((stbsp__uint64)bits) >= stbsp__tento19th) + ++tens; + } + + // now do the rounding in integer land + frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits); + if ((frac_digits < 24)) { + stbsp__uint32 dg = 1; + if ((stbsp__uint64)bits >= stbsp__powten[9]) + dg = 10; + while ((stbsp__uint64)bits >= stbsp__powten[dg]) { + ++dg; + if (dg == 20) + goto noround; + } + if (frac_digits < dg) { + stbsp__uint64 r; + // add 0.5 at the right position and round + e = dg - frac_digits; + if ((stbsp__uint32)e >= 24) + goto noround; + r = stbsp__powten[e]; + bits = bits + (r / 2); + if ((stbsp__uint64)bits >= stbsp__powten[dg]) + ++tens; + bits /= r; + } + noround:; + } + + // kill long trailing runs of zeros + if (bits) { + stbsp__uint32 n; + for (;;) { + if (bits <= 0xffffffff) + break; + if (bits % 1000) + goto donez; + bits /= 1000; + } + n = (stbsp__uint32)bits; + while ((n % 1000) == 0) + n /= 1000; + bits = n; + donez:; + } + + // convert to string + out += 64; + e = 0; + for (;;) { + stbsp__uint32 n; + char *o = out - 8; + // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) + if (bits >= 100000000) { + n = (stbsp__uint32)(bits % 100000000); + bits /= 100000000; + } else { + n = (stbsp__uint32)bits; + bits = 0; + } + while (n) { + out -= 2; + *(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; + n /= 100; + e += 2; + } + if (bits == 0) { + if ((e) && (out[0] == '0')) { + ++out; + --e; + } + break; + } + while (out != o) { + *--out = '0'; + ++e; + } + } + + *decimal_pos = tens; + *start = out; + *len = e; + return ng; +} + +#undef stbsp__ddmulthi +#undef stbsp__ddrenorm +#undef stbsp__ddmultlo +#undef stbsp__ddmultlos +#undef STBSP__SPECIAL +#undef STBSP__COPYFP + +#endif // STB_SPRINTF_NOFLOAT + +// clean up +#undef stbsp__uint16 +#undef stbsp__uint32 +#undef stbsp__int32 +#undef stbsp__uint64 +#undef stbsp__int64 +#undef STBSP__UNALIGNED + +#endif // STB_SPRINTF_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/src/common/thirdparty/utf8proc/LICENSE.md b/src/common/thirdparty/utf8proc/LICENSE.md new file mode 100644 index 0000000000..f18b1f3abd --- /dev/null +++ b/src/common/thirdparty/utf8proc/LICENSE.md @@ -0,0 +1,93 @@ +## utf8proc license ## + +**utf8proc** is a software package originally developed +by Jan Behrens and the rest of the Public Software Group, who +deserve nearly all of the credit for this library, that is now maintained by the Julia-language developers. Like the original utf8proc, +whose copyright and license statements are reproduced below, all new +work on the utf8proc library is licensed under the [MIT "expat" +license](http://opensource.org/licenses/MIT): + +*Copyright © 2014-2021 by Steven G. Johnson, Jiahao Chen, Tony Kelman, Jonas Fonseca, and other contributors listed in the git history.* + +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. + +## Original utf8proc license ## + +*Copyright (c) 2009, 2013 Public Software Group e. V., Berlin, Germany* + +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. + +## Unicode data license ## + +This software contains data (`utf8proc_data.c`) derived from processing +the Unicode data files. The following license applies to that data: + +**COPYRIGHT AND PERMISSION NOTICE** + +*Copyright (c) 1991-2007 Unicode, Inc. All rights reserved. Distributed +under the Terms of Use in http://www.unicode.org/copyright.html.* + +Permission is hereby granted, free of charge, to any person obtaining a +copy of the Unicode data files and any associated documentation (the "Data +Files") or Unicode software and any associated documentation (the +"Software") to deal in the Data Files or Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, and/or sell copies of the Data Files or Software, and +to permit persons to whom the Data Files or Software are furnished to do +so, provided that (a) the above copyright notice(s) and this permission +notice appear with all copies of the Data Files or Software, (b) both the +above copyright notice(s) and this permission notice appear in associated +documentation, and (c) there is clear notice in each modified Data File or +in the Software as well as in the documentation associated with the Data +File(s) or Software that the data or software has been modified. + +THE DATA FILES AND SOFTWARE ARE 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 OF +THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS +INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. + +Unicode and the Unicode logo are trademarks of Unicode, Inc., and may be +registered in some jurisdictions. All other trademarks and registered +trademarks mentioned herein are the property of their respective owners. diff --git a/src/common/thirdparty/utf8proc/utf8proc.c b/src/common/thirdparty/utf8proc/utf8proc.c new file mode 100644 index 0000000000..a7644247b4 --- /dev/null +++ b/src/common/thirdparty/utf8proc/utf8proc.c @@ -0,0 +1,815 @@ +/* -*- mode: c; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 2014-2021 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors. + * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany + * + * 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. + */ + +/* + * This library contains derived data from a modified version of the + * Unicode data files. + * + * The original data files are available at + * https://www.unicode.org/Public/UNIDATA/ + * + * Please notice the copyright statement in the file "utf8proc_data.c". + */ + + +/* + * File name: utf8proc.c + * + * Description: + * Implementation of libutf8proc. + */ + + +#include "utf8proc.h" + +#ifndef SSIZE_MAX +#define SSIZE_MAX ((size_t)SIZE_MAX/2) +#endif +#ifndef UINT16_MAX +# define UINT16_MAX 65535U +#endif + +#include "utf8proc_data.c" + + +UTF8PROC_DLLEXPORT const utf8proc_int8_t utf8proc_utf8class[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 }; + +#define UTF8PROC_HANGUL_SBASE 0xAC00 +#define UTF8PROC_HANGUL_LBASE 0x1100 +#define UTF8PROC_HANGUL_VBASE 0x1161 +#define UTF8PROC_HANGUL_TBASE 0x11A7 +#define UTF8PROC_HANGUL_LCOUNT 19 +#define UTF8PROC_HANGUL_VCOUNT 21 +#define UTF8PROC_HANGUL_TCOUNT 28 +#define UTF8PROC_HANGUL_NCOUNT 588 +#define UTF8PROC_HANGUL_SCOUNT 11172 +/* END is exclusive */ +#define UTF8PROC_HANGUL_L_START 0x1100 +#define UTF8PROC_HANGUL_L_END 0x115A +#define UTF8PROC_HANGUL_L_FILLER 0x115F +#define UTF8PROC_HANGUL_V_START 0x1160 +#define UTF8PROC_HANGUL_V_END 0x11A3 +#define UTF8PROC_HANGUL_T_START 0x11A8 +#define UTF8PROC_HANGUL_T_END 0x11FA +#define UTF8PROC_HANGUL_S_START 0xAC00 +#define UTF8PROC_HANGUL_S_END 0xD7A4 + +/* Should follow semantic-versioning rules (semver.org) based on API + compatibility. (Note that the shared-library version number will + be different, being based on ABI compatibility.): */ +#define STRINGIZEx(x) #x +#define STRINGIZE(x) STRINGIZEx(x) +UTF8PROC_DLLEXPORT const char *utf8proc_version(void) { + return STRINGIZE(UTF8PROC_VERSION_MAJOR) "." STRINGIZE(UTF8PROC_VERSION_MINOR) "." STRINGIZE(UTF8PROC_VERSION_PATCH) ""; +} + +UTF8PROC_DLLEXPORT const char *utf8proc_unicode_version(void) { + return "15.1.0"; +} + +UTF8PROC_DLLEXPORT const char *utf8proc_errmsg(utf8proc_ssize_t errcode) { + switch (errcode) { + case UTF8PROC_ERROR_NOMEM: + return "Memory for processing UTF-8 data could not be allocated."; + case UTF8PROC_ERROR_OVERFLOW: + return "UTF-8 string is too long to be processed."; + case UTF8PROC_ERROR_INVALIDUTF8: + return "Invalid UTF-8 string"; + case UTF8PROC_ERROR_NOTASSIGNED: + return "Unassigned Unicode code point found in UTF-8 string."; + case UTF8PROC_ERROR_INVALIDOPTS: + return "Invalid options for UTF-8 processing chosen."; + default: + return "An unknown error occurred while processing UTF-8 data."; + } +} + +#define utf_cont(ch) (((ch) & 0xc0) == 0x80) +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_iterate( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_int32_t *dst +) { + utf8proc_int32_t uc; + const utf8proc_uint8_t *end; + + *dst = -1; + if (!strlen) return 0; + end = str + ((strlen < 0) ? 4 : strlen); + uc = *str++; + if (uc < 0x80) { + *dst = uc; + return 1; + } + // Must be between 0xc2 and 0xf4 inclusive to be valid + if ((utf8proc_uint32_t)(uc - 0xc2) > (0xf4-0xc2)) return UTF8PROC_ERROR_INVALIDUTF8; + if (uc < 0xe0) { // 2-byte sequence + // Must have valid continuation character + if (str >= end || !utf_cont(*str)) return UTF8PROC_ERROR_INVALIDUTF8; + *dst = ((uc & 0x1f)<<6) | (*str & 0x3f); + return 2; + } + if (uc < 0xf0) { // 3-byte sequence + if ((str + 1 >= end) || !utf_cont(*str) || !utf_cont(str[1])) + return UTF8PROC_ERROR_INVALIDUTF8; + // Check for surrogate chars + if (uc == 0xed && *str > 0x9f) + return UTF8PROC_ERROR_INVALIDUTF8; + uc = ((uc & 0xf)<<12) | ((*str & 0x3f)<<6) | (str[1] & 0x3f); + if (uc < 0x800) + return UTF8PROC_ERROR_INVALIDUTF8; + *dst = uc; + return 3; + } + // 4-byte sequence + // Must have 3 valid continuation characters + if ((str + 2 >= end) || !utf_cont(*str) || !utf_cont(str[1]) || !utf_cont(str[2])) + return UTF8PROC_ERROR_INVALIDUTF8; + // Make sure in correct range (0x10000 - 0x10ffff) + if (uc == 0xf0) { + if (*str < 0x90) return UTF8PROC_ERROR_INVALIDUTF8; + } else if (uc == 0xf4) { + if (*str > 0x8f) return UTF8PROC_ERROR_INVALIDUTF8; + } + *dst = ((uc & 7)<<18) | ((*str & 0x3f)<<12) | ((str[1] & 0x3f)<<6) | (str[2] & 0x3f); + return 4; +} + +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_codepoint_valid(utf8proc_int32_t uc) { + return (((utf8proc_uint32_t)uc)-0xd800 > 0x07ff) && ((utf8proc_uint32_t)uc < 0x110000); +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t *dst) { + if (uc < 0x00) { + return 0; + } else if (uc < 0x80) { + dst[0] = (utf8proc_uint8_t) uc; + return 1; + } else if (uc < 0x800) { + dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6)); + dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 2; + // Note: we allow encoding 0xd800-0xdfff here, so as not to change + // the API, however, these are actually invalid in UTF-8 + } else if (uc < 0x10000) { + dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 3; + } else if (uc < 0x110000) { + dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 4; + } else return 0; +} + +/* internal version used for inserting 0xff bytes between graphemes */ +static utf8proc_ssize_t charbound_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t *dst) { + if (uc < 0x00) { + if (uc == -1) { /* internal value used for grapheme breaks */ + dst[0] = (utf8proc_uint8_t)0xFF; + return 1; + } + return 0; + } else if (uc < 0x80) { + dst[0] = (utf8proc_uint8_t)uc; + return 1; + } else if (uc < 0x800) { + dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6)); + dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 2; + } else if (uc < 0x10000) { + dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 3; + } else if (uc < 0x110000) { + dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 4; + } else return 0; +} + +/* internal "unsafe" version that does not check whether uc is in range */ +static const utf8proc_property_t *unsafe_get_property(utf8proc_int32_t uc) { + /* ASSERT: uc >= 0 && uc < 0x110000 */ + return utf8proc_properties + ( + utf8proc_stage2table[ + utf8proc_stage1table[uc >> 8] + (uc & 0xFF) + ] + ); +} + +UTF8PROC_DLLEXPORT const utf8proc_property_t *utf8proc_get_property(utf8proc_int32_t uc) { + return uc < 0 || uc >= 0x110000 ? utf8proc_properties : unsafe_get_property(uc); +} + +/* return whether there is a grapheme break between boundclasses lbc and tbc + (according to the definition of extended grapheme clusters) + + Rule numbering refers to TR29 Version 29 (Unicode 9.0.0): + http://www.unicode.org/reports/tr29/tr29-29.html + + CAVEATS: + Please note that evaluation of GB10 (grapheme breaks between emoji zwj sequences) + and GB 12/13 (regional indicator code points) require knowledge of previous characters + and are thus not handled by this function. This may result in an incorrect break before + an E_Modifier class codepoint and an incorrectly missing break between two + REGIONAL_INDICATOR class code points if such support does not exist in the caller. + + See the special support in grapheme_break_extended, for required bookkeeping by the caller. +*/ +static utf8proc_bool grapheme_break_simple(int lbc, int tbc) { + return + (lbc == UTF8PROC_BOUNDCLASS_START) ? true : // GB1 + (lbc == UTF8PROC_BOUNDCLASS_CR && // GB3 + tbc == UTF8PROC_BOUNDCLASS_LF) ? false : // --- + (lbc >= UTF8PROC_BOUNDCLASS_CR && lbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true : // GB4 + (tbc >= UTF8PROC_BOUNDCLASS_CR && tbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true : // GB5 + (lbc == UTF8PROC_BOUNDCLASS_L && // GB6 + (tbc == UTF8PROC_BOUNDCLASS_L || // --- + tbc == UTF8PROC_BOUNDCLASS_V || // --- + tbc == UTF8PROC_BOUNDCLASS_LV || // --- + tbc == UTF8PROC_BOUNDCLASS_LVT)) ? false : // --- + ((lbc == UTF8PROC_BOUNDCLASS_LV || // GB7 + lbc == UTF8PROC_BOUNDCLASS_V) && // --- + (tbc == UTF8PROC_BOUNDCLASS_V || // --- + tbc == UTF8PROC_BOUNDCLASS_T)) ? false : // --- + ((lbc == UTF8PROC_BOUNDCLASS_LVT || // GB8 + lbc == UTF8PROC_BOUNDCLASS_T) && // --- + tbc == UTF8PROC_BOUNDCLASS_T) ? false : // --- + (tbc == UTF8PROC_BOUNDCLASS_EXTEND || // GB9 + tbc == UTF8PROC_BOUNDCLASS_ZWJ || // --- + tbc == UTF8PROC_BOUNDCLASS_SPACINGMARK || // GB9a + lbc == UTF8PROC_BOUNDCLASS_PREPEND) ? false : // GB9b + (lbc == UTF8PROC_BOUNDCLASS_E_ZWG && // GB11 (requires additional handling below) + tbc == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC) ? false : // ---- + (lbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR && // GB12/13 (requires additional handling below) + tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) ? false : // ---- + true; // GB999 +} + +static utf8proc_bool grapheme_break_extended(int lbc, int tbc, int licb, int ticb, utf8proc_int32_t *state) +{ + if (state) { + int state_bc, state_icb; /* boundclass and indic_conjunct_break state */ + if (*state == 0) { /* state initialization */ + state_bc = lbc; + state_icb = licb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT ? licb : UTF8PROC_INDIC_CONJUNCT_BREAK_NONE; + } + else { /* lbc and licb are already encoded in *state */ + state_bc = *state & 0xff; // 1st byte of state is bound class + state_icb = *state >> 8; // 2nd byte of state is indic conjunct break + } + + utf8proc_bool break_permitted = grapheme_break_simple(state_bc, tbc) && + !(state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER + && ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT); // GB9c + + // Special support for GB9c. Don't break between two consonants + // separated 1+ linker characters and 0+ extend characters in any order. + // After a consonant, we enter LINKER state after at least one linker. + if (ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT + || state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT + || state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND) + state_icb = ticb; + else if (state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER) + state_icb = ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND ? + UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER : ticb; + + // Special support for GB 12/13 made possible by GB999. After two RI + // class codepoints we want to force a break. Do this by resetting the + // second RI's bound class to UTF8PROC_BOUNDCLASS_OTHER, to force a break + // after that character according to GB999 (unless of course such a break is + // forbidden by a different rule such as GB9). + if (state_bc == tbc && tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) + state_bc = UTF8PROC_BOUNDCLASS_OTHER; + // Special support for GB11 (emoji extend* zwj / emoji) + else if (state_bc == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC) { + if (tbc == UTF8PROC_BOUNDCLASS_EXTEND) // fold EXTEND codepoints into emoji + state_bc = UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC; + else if (tbc == UTF8PROC_BOUNDCLASS_ZWJ) + state_bc = UTF8PROC_BOUNDCLASS_E_ZWG; // state to record emoji+zwg combo + else + state_bc = tbc; + } + else + state_bc = tbc; + + *state = state_bc + (state_icb << 8); + return break_permitted; + } + else + return grapheme_break_simple(lbc, tbc); +} + +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break_stateful( + utf8proc_int32_t c1, utf8proc_int32_t c2, utf8proc_int32_t *state) { + + const utf8proc_property_t *p1 = utf8proc_get_property(c1); + const utf8proc_property_t *p2 = utf8proc_get_property(c2); + return grapheme_break_extended(p1->boundclass, + p2->boundclass, + p1->indic_conjunct_break, + p2->indic_conjunct_break, + state); +} + + +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break( + utf8proc_int32_t c1, utf8proc_int32_t c2) { + return utf8proc_grapheme_break_stateful(c1, c2, NULL); +} + +static utf8proc_int32_t seqindex_decode_entry(const utf8proc_uint16_t **entry) +{ + utf8proc_int32_t entry_cp = **entry; + if ((entry_cp & 0xF800) == 0xD800) { + *entry = *entry + 1; + entry_cp = ((entry_cp & 0x03FF) << 10) | (**entry & 0x03FF); + entry_cp += 0x10000; + } + return entry_cp; +} + +static utf8proc_int32_t seqindex_decode_index(const utf8proc_uint32_t seqindex) +{ + const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex]; + return seqindex_decode_entry(&entry); +} + +static utf8proc_ssize_t seqindex_write_char_decomposed(utf8proc_uint16_t seqindex, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) { + utf8proc_ssize_t written = 0; + const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex & 0x3FFF]; + int len = seqindex >> 14; + if (len >= 3) { + len = *entry; + entry++; + } + for (; len >= 0; entry++, len--) { + utf8proc_int32_t entry_cp = seqindex_decode_entry(&entry); + + written += utf8proc_decompose_char(entry_cp, dst+written, + (bufsize > written) ? (bufsize - written) : 0, options, + last_boundclass); + if (written < 0) return UTF8PROC_ERROR_OVERFLOW; + } + return written; +} + +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_tolower(utf8proc_int32_t c) +{ + utf8proc_int32_t cl = utf8proc_get_property(c)->lowercase_seqindex; + return cl != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cl) : c; +} + +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_toupper(utf8proc_int32_t c) +{ + utf8proc_int32_t cu = utf8proc_get_property(c)->uppercase_seqindex; + return cu != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cu) : c; +} + +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c) +{ + utf8proc_int32_t cu = utf8proc_get_property(c)->titlecase_seqindex; + return cu != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cu) : c; +} + +UTF8PROC_DLLEXPORT int utf8proc_islower(utf8proc_int32_t c) +{ + const utf8proc_property_t *p = utf8proc_get_property(c); + return p->lowercase_seqindex != p->uppercase_seqindex && p->lowercase_seqindex == UINT16_MAX; +} + +UTF8PROC_DLLEXPORT int utf8proc_isupper(utf8proc_int32_t c) +{ + const utf8proc_property_t *p = utf8proc_get_property(c); + return p->lowercase_seqindex != p->uppercase_seqindex && p->uppercase_seqindex == UINT16_MAX && p->category != UTF8PROC_CATEGORY_LT; +} + +/* return a character width analogous to wcwidth (except portable and + hopefully less buggy than most system wcwidth functions). */ +UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) { + return utf8proc_get_property(c)->charwidth; +} + +UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t c) { + return (utf8proc_category_t) utf8proc_get_property(c)->category; +} + +UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) { + static const char s[][3] = {"Cn","Lu","Ll","Lt","Lm","Lo","Mn","Mc","Me","Nd","Nl","No","Pc","Pd","Ps","Pe","Pi","Pf","Po","Sm","Sc","Sk","So","Zs","Zl","Zp","Cc","Cf","Cs","Co"}; + return s[utf8proc_category(c)]; +} + +#define utf8proc_decompose_lump(replacement_uc) \ + return utf8proc_decompose_char((replacement_uc), dst, bufsize, \ + options & ~(unsigned int)UTF8PROC_LUMP, last_boundclass) + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) { + const utf8proc_property_t *property; + utf8proc_propval_t category; + utf8proc_int32_t hangul_sindex; + if (uc < 0 || uc >= 0x110000) return UTF8PROC_ERROR_NOTASSIGNED; + property = unsafe_get_property(uc); + category = property->category; + hangul_sindex = uc - UTF8PROC_HANGUL_SBASE; + if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) { + if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) { + utf8proc_int32_t hangul_tindex; + if (bufsize >= 1) { + dst[0] = UTF8PROC_HANGUL_LBASE + + hangul_sindex / UTF8PROC_HANGUL_NCOUNT; + if (bufsize >= 2) dst[1] = UTF8PROC_HANGUL_VBASE + + (hangul_sindex % UTF8PROC_HANGUL_NCOUNT) / UTF8PROC_HANGUL_TCOUNT; + } + hangul_tindex = hangul_sindex % UTF8PROC_HANGUL_TCOUNT; + if (!hangul_tindex) return 2; + if (bufsize >= 3) dst[2] = UTF8PROC_HANGUL_TBASE + hangul_tindex; + return 3; + } + } + if (options & UTF8PROC_REJECTNA) { + if (!category) return UTF8PROC_ERROR_NOTASSIGNED; + } + if (options & UTF8PROC_IGNORE) { + if (property->ignorable) return 0; + } + if (options & UTF8PROC_STRIPNA) { + if (!category) return 0; + } + if (options & UTF8PROC_LUMP) { + if (category == UTF8PROC_CATEGORY_ZS) utf8proc_decompose_lump(0x0020); + if (uc == 0x2018 || uc == 0x2019 || uc == 0x02BC || uc == 0x02C8) + utf8proc_decompose_lump(0x0027); + if (category == UTF8PROC_CATEGORY_PD || uc == 0x2212) + utf8proc_decompose_lump(0x002D); + if (uc == 0x2044 || uc == 0x2215) utf8proc_decompose_lump(0x002F); + if (uc == 0x2236) utf8proc_decompose_lump(0x003A); + if (uc == 0x2039 || uc == 0x2329 || uc == 0x3008) + utf8proc_decompose_lump(0x003C); + if (uc == 0x203A || uc == 0x232A || uc == 0x3009) + utf8proc_decompose_lump(0x003E); + if (uc == 0x2216) utf8proc_decompose_lump(0x005C); + if (uc == 0x02C4 || uc == 0x02C6 || uc == 0x2038 || uc == 0x2303) + utf8proc_decompose_lump(0x005E); + if (category == UTF8PROC_CATEGORY_PC || uc == 0x02CD) + utf8proc_decompose_lump(0x005F); + if (uc == 0x02CB) utf8proc_decompose_lump(0x0060); + if (uc == 0x2223) utf8proc_decompose_lump(0x007C); + if (uc == 0x223C) utf8proc_decompose_lump(0x007E); + if ((options & UTF8PROC_NLF2LS) && (options & UTF8PROC_NLF2PS)) { + if (category == UTF8PROC_CATEGORY_ZL || + category == UTF8PROC_CATEGORY_ZP) + utf8proc_decompose_lump(0x000A); + } + } + if (options & UTF8PROC_STRIPMARK) { + if (category == UTF8PROC_CATEGORY_MN || + category == UTF8PROC_CATEGORY_MC || + category == UTF8PROC_CATEGORY_ME) return 0; + } + if (options & UTF8PROC_CASEFOLD) { + if (property->casefold_seqindex != UINT16_MAX) { + return seqindex_write_char_decomposed(property->casefold_seqindex, dst, bufsize, options, last_boundclass); + } + } + if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) { + if (property->decomp_seqindex != UINT16_MAX && + (!property->decomp_type || (options & UTF8PROC_COMPAT))) { + return seqindex_write_char_decomposed(property->decomp_seqindex, dst, bufsize, options, last_boundclass); + } + } + if (options & UTF8PROC_CHARBOUND) { + utf8proc_bool boundary; + boundary = grapheme_break_extended(0, property->boundclass, 0, property->indic_conjunct_break, + last_boundclass); + if (boundary) { + if (bufsize >= 1) dst[0] = -1; /* sentinel value for grapheme break */ + if (bufsize >= 2) dst[1] = uc; + return 2; + } + } + if (bufsize >= 1) *dst = uc; + return 1; +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options +) { + return utf8proc_decompose_custom(str, strlen, buffer, bufsize, options, NULL, NULL); +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data +) { + /* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */ + utf8proc_ssize_t wpos = 0; + if ((options & UTF8PROC_COMPOSE) && (options & UTF8PROC_DECOMPOSE)) + return UTF8PROC_ERROR_INVALIDOPTS; + if ((options & UTF8PROC_STRIPMARK) && + !(options & UTF8PROC_COMPOSE) && !(options & UTF8PROC_DECOMPOSE)) + return UTF8PROC_ERROR_INVALIDOPTS; + { + utf8proc_int32_t uc; + utf8proc_ssize_t rpos = 0; + utf8proc_ssize_t decomp_result; + int boundclass = UTF8PROC_BOUNDCLASS_START; + while (1) { + if (options & UTF8PROC_NULLTERM) { + rpos += utf8proc_iterate(str + rpos, -1, &uc); + /* checking of return value is not necessary, + as 'uc' is < 0 in case of error */ + if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; + if (rpos < 0) return UTF8PROC_ERROR_OVERFLOW; + if (uc == 0) break; + } else { + if (rpos >= strlen) break; + rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc); + if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; + } + if (custom_func != NULL) { + uc = custom_func(uc, custom_data); /* user-specified custom mapping */ + } + decomp_result = utf8proc_decompose_char( + uc, buffer + wpos, (bufsize > wpos) ? (bufsize - wpos) : 0, options, + &boundclass + ); + if (decomp_result < 0) return decomp_result; + wpos += decomp_result; + /* prohibiting integer overflows due to too long strings: */ + if (wpos < 0 || + wpos > (utf8proc_ssize_t)(SSIZE_MAX/sizeof(utf8proc_int32_t)/2)) + return UTF8PROC_ERROR_OVERFLOW; + } + } + if ((options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) && bufsize >= wpos) { + utf8proc_ssize_t pos = 0; + while (pos < wpos-1) { + utf8proc_int32_t uc1, uc2; + const utf8proc_property_t *property1, *property2; + uc1 = buffer[pos]; + uc2 = buffer[pos+1]; + property1 = unsafe_get_property(uc1); + property2 = unsafe_get_property(uc2); + if (property1->combining_class > property2->combining_class && + property2->combining_class > 0) { + buffer[pos] = uc2; + buffer[pos+1] = uc1; + if (pos > 0) pos--; else pos++; + } else { + pos++; + } + } + } + return wpos; +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) { + /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored */ + if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) { + utf8proc_ssize_t rpos; + utf8proc_ssize_t wpos = 0; + utf8proc_int32_t uc; + for (rpos = 0; rpos < length; rpos++) { + uc = buffer[rpos]; + if (uc == 0x000D && rpos < length-1 && buffer[rpos+1] == 0x000A) rpos++; + if (uc == 0x000A || uc == 0x000D || uc == 0x0085 || + ((options & UTF8PROC_STRIPCC) && (uc == 0x000B || uc == 0x000C))) { + if (options & UTF8PROC_NLF2LS) { + if (options & UTF8PROC_NLF2PS) { + buffer[wpos++] = 0x000A; + } else { + buffer[wpos++] = 0x2028; + } + } else { + if (options & UTF8PROC_NLF2PS) { + buffer[wpos++] = 0x2029; + } else { + buffer[wpos++] = 0x0020; + } + } + } else if ((options & UTF8PROC_STRIPCC) && + (uc < 0x0020 || (uc >= 0x007F && uc < 0x00A0))) { + if (uc == 0x0009) buffer[wpos++] = 0x0020; + } else { + buffer[wpos++] = uc; + } + } + length = wpos; + } + if (options & UTF8PROC_COMPOSE) { + utf8proc_int32_t *starter = NULL; + utf8proc_int32_t current_char; + const utf8proc_property_t *starter_property = NULL, *current_property; + utf8proc_propval_t max_combining_class = -1; + utf8proc_ssize_t rpos; + utf8proc_ssize_t wpos = 0; + utf8proc_int32_t composition; + for (rpos = 0; rpos < length; rpos++) { + current_char = buffer[rpos]; + current_property = unsafe_get_property(current_char); + if (starter && current_property->combining_class > max_combining_class) { + /* combination perhaps possible */ + utf8proc_int32_t hangul_lindex; + utf8proc_int32_t hangul_sindex; + hangul_lindex = *starter - UTF8PROC_HANGUL_LBASE; + if (hangul_lindex >= 0 && hangul_lindex < UTF8PROC_HANGUL_LCOUNT) { + utf8proc_int32_t hangul_vindex; + hangul_vindex = current_char - UTF8PROC_HANGUL_VBASE; + if (hangul_vindex >= 0 && hangul_vindex < UTF8PROC_HANGUL_VCOUNT) { + *starter = UTF8PROC_HANGUL_SBASE + + (hangul_lindex * UTF8PROC_HANGUL_VCOUNT + hangul_vindex) * + UTF8PROC_HANGUL_TCOUNT; + starter_property = NULL; + continue; + } + } + hangul_sindex = *starter - UTF8PROC_HANGUL_SBASE; + if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT && + (hangul_sindex % UTF8PROC_HANGUL_TCOUNT) == 0) { + utf8proc_int32_t hangul_tindex; + hangul_tindex = current_char - UTF8PROC_HANGUL_TBASE; + if (hangul_tindex >= 0 && hangul_tindex < UTF8PROC_HANGUL_TCOUNT) { + *starter += hangul_tindex; + starter_property = NULL; + continue; + } + } + if (!starter_property) { + starter_property = unsafe_get_property(*starter); + } + if (starter_property->comb_index < 0x8000 && + current_property->comb_index != UINT16_MAX && + current_property->comb_index >= 0x8000) { + int sidx = starter_property->comb_index; + int idx = current_property->comb_index & 0x3FFF; + if (idx >= utf8proc_combinations[sidx] && idx <= utf8proc_combinations[sidx + 1] ) { + idx += sidx + 2 - utf8proc_combinations[sidx]; + if (current_property->comb_index & 0x4000) { + composition = (utf8proc_combinations[idx] << 16) | utf8proc_combinations[idx+1]; + } else + composition = utf8proc_combinations[idx]; + + if (composition > 0 && (!(options & UTF8PROC_STABLE) || + !(unsafe_get_property(composition)->comp_exclusion))) { + *starter = composition; + starter_property = NULL; + continue; + } + } + } + } + buffer[wpos] = current_char; + if (current_property->combining_class) { + if (current_property->combining_class > max_combining_class) { + max_combining_class = current_property->combining_class; + } + } else { + starter = buffer + wpos; + starter_property = NULL; + max_combining_class = -1; + } + wpos++; + } + length = wpos; + } + return length; +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) { + /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored + ASSERT: 'buffer' has one spare byte of free space at the end! */ + length = utf8proc_normalize_utf32(buffer, length, options); + if (length < 0) return length; + { + utf8proc_ssize_t rpos, wpos = 0; + utf8proc_int32_t uc; + if (options & UTF8PROC_CHARBOUND) { + for (rpos = 0; rpos < length; rpos++) { + uc = buffer[rpos]; + wpos += charbound_encode_char(uc, ((utf8proc_uint8_t *)buffer) + wpos); + } + } else { + for (rpos = 0; rpos < length; rpos++) { + uc = buffer[rpos]; + wpos += utf8proc_encode_char(uc, ((utf8proc_uint8_t *)buffer) + wpos); + } + } + ((utf8proc_uint8_t *)buffer)[wpos] = 0; + return wpos; + } +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options +) { + return utf8proc_map_custom(str, strlen, dstptr, options, NULL, NULL); +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data +) { + utf8proc_int32_t *buffer; + utf8proc_ssize_t result; + *dstptr = NULL; + result = utf8proc_decompose_custom(str, strlen, NULL, 0, options, custom_func, custom_data); + if (result < 0) return result; + buffer = (utf8proc_int32_t *) malloc(((utf8proc_size_t)result) * sizeof(utf8proc_int32_t) + 1); + if (!buffer) return UTF8PROC_ERROR_NOMEM; + result = utf8proc_decompose_custom(str, strlen, buffer, result, options, custom_func, custom_data); + if (result < 0) { + free(buffer); + return result; + } + result = utf8proc_reencode(buffer, result, options); + if (result < 0) { + free(buffer); + return result; + } + { + utf8proc_int32_t *newptr; + newptr = (utf8proc_int32_t *) realloc(buffer, (size_t)result+1); + if (newptr) buffer = newptr; + } + *dstptr = (utf8proc_uint8_t *)buffer; + return result; +} + +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; + utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | + UTF8PROC_DECOMPOSE); + return retval; +} + +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; + utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | + UTF8PROC_COMPOSE); + return retval; +} + +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; + utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | + UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT); + return retval; +} + +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; + utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | + UTF8PROC_COMPOSE | UTF8PROC_COMPAT); + return retval; +} + +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; + utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | + UTF8PROC_COMPOSE | UTF8PROC_COMPAT | UTF8PROC_CASEFOLD | UTF8PROC_IGNORE); + return retval; +} diff --git a/src/common/thirdparty/utf8proc/utf8proc.h b/src/common/thirdparty/utf8proc/utf8proc.h new file mode 100644 index 0000000000..0bd4452482 --- /dev/null +++ b/src/common/thirdparty/utf8proc/utf8proc.h @@ -0,0 +1,745 @@ +/* + * Copyright (c) 2014-2021 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors. + * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany + * + * 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. + */ + + +/** + * @mainpage + * + * utf8proc is a free/open-source (MIT/expat licensed) C library + * providing Unicode normalization, case-folding, and other operations + * for strings in the UTF-8 encoding, supporting up-to-date Unicode versions. + * See the utf8proc home page (http://julialang.org/utf8proc/) + * for downloads and other information, or the source code on github + * (https://github.com/JuliaLang/utf8proc). + * + * For the utf8proc API documentation, see: @ref utf8proc.h + * + * The features of utf8proc include: + * + * - Transformation of strings (utf8proc_map()) to: + * - decompose (@ref UTF8PROC_DECOMPOSE) or compose (@ref UTF8PROC_COMPOSE) Unicode combining characters (http://en.wikipedia.org/wiki/Combining_character) + * - canonicalize Unicode compatibility characters (@ref UTF8PROC_COMPAT) + * - strip "ignorable" (@ref UTF8PROC_IGNORE) characters, control characters (@ref UTF8PROC_STRIPCC), or combining characters such as accents (@ref UTF8PROC_STRIPMARK) + * - case-folding (@ref UTF8PROC_CASEFOLD) + * - Unicode normalization: utf8proc_NFD(), utf8proc_NFC(), utf8proc_NFKD(), utf8proc_NFKC() + * - Detecting grapheme boundaries (utf8proc_grapheme_break() and @ref UTF8PROC_CHARBOUND) + * - Character-width computation: utf8proc_charwidth() + * - Classification of characters by Unicode category: utf8proc_category() and utf8proc_category_string() + * - Encode (utf8proc_encode_char()) and decode (utf8proc_iterate()) Unicode codepoints to/from UTF-8. + */ + +/** @file */ + +#ifndef UTF8PROC_H +#define UTF8PROC_H + +#define UTF8PROC_STATIC + +/** @name API version + * + * The utf8proc API version MAJOR.MINOR.PATCH, following + * semantic-versioning rules (http://semver.org) based on API + * compatibility. + * + * This is also returned at runtime by utf8proc_version(); however, the + * runtime version may append a string like "-dev" to the version number + * for prerelease versions. + * + * @note The shared-library version number in the Makefile + * (and CMakeLists.txt, and MANIFEST) may be different, + * being based on ABI compatibility rather than API compatibility. + */ +/** @{ */ +/** The MAJOR version number (increased when backwards API compatibility is broken). */ +#define UTF8PROC_VERSION_MAJOR 2 +/** The MINOR version number (increased when new functionality is added in a backwards-compatible manner). */ +#define UTF8PROC_VERSION_MINOR 9 +/** The PATCH version (increased for fixes that do not change the API). */ +#define UTF8PROC_VERSION_PATCH 0 +/** @} */ + +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +// MSVC prior to 2013 lacked stdbool.h and inttypes.h +typedef signed char utf8proc_int8_t; +typedef unsigned char utf8proc_uint8_t; +typedef short utf8proc_int16_t; +typedef unsigned short utf8proc_uint16_t; +typedef int utf8proc_int32_t; +typedef unsigned int utf8proc_uint32_t; +# ifdef _WIN64 +typedef __int64 utf8proc_ssize_t; +typedef unsigned __int64 utf8proc_size_t; +# else +typedef int utf8proc_ssize_t; +typedef unsigned int utf8proc_size_t; +# endif +# ifndef __cplusplus +// emulate C99 bool +typedef unsigned char utf8proc_bool; +# ifndef __bool_true_false_are_defined +# define false 0 +# define true 1 +# define __bool_true_false_are_defined 1 +# endif +# else +typedef bool utf8proc_bool; +# endif +#else +# include +# include +# include +typedef int8_t utf8proc_int8_t; +typedef uint8_t utf8proc_uint8_t; +typedef int16_t utf8proc_int16_t; +typedef uint16_t utf8proc_uint16_t; +typedef int32_t utf8proc_int32_t; +typedef uint32_t utf8proc_uint32_t; +typedef size_t utf8proc_size_t; +typedef ptrdiff_t utf8proc_ssize_t; +typedef bool utf8proc_bool; +#endif +#include + +#ifdef UTF8PROC_STATIC +# define UTF8PROC_DLLEXPORT +#else +# ifdef _WIN32 +# ifdef UTF8PROC_EXPORTS +# define UTF8PROC_DLLEXPORT __declspec(dllexport) +# else +# define UTF8PROC_DLLEXPORT __declspec(dllimport) +# endif +# elif __GNUC__ >= 4 +# define UTF8PROC_DLLEXPORT __attribute__ ((visibility("default"))) +# else +# define UTF8PROC_DLLEXPORT +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Option flags used by several functions in the library. + */ +typedef enum { + /** The given UTF-8 input is NULL terminated. */ + UTF8PROC_NULLTERM = (1<<0), + /** Unicode Versioning Stability has to be respected. */ + UTF8PROC_STABLE = (1<<1), + /** Compatibility decomposition (i.e. formatting information is lost). */ + UTF8PROC_COMPAT = (1<<2), + /** Return a result with decomposed characters. */ + UTF8PROC_COMPOSE = (1<<3), + /** Return a result with decomposed characters. */ + UTF8PROC_DECOMPOSE = (1<<4), + /** Strip "default ignorable characters" such as SOFT-HYPHEN or ZERO-WIDTH-SPACE. */ + UTF8PROC_IGNORE = (1<<5), + /** Return an error, if the input contains unassigned codepoints. */ + UTF8PROC_REJECTNA = (1<<6), + /** + * Indicating that NLF-sequences (LF, CRLF, CR, NEL) are representing a + * line break, and should be converted to the codepoint for line + * separation (LS). + */ + UTF8PROC_NLF2LS = (1<<7), + /** + * Indicating that NLF-sequences are representing a paragraph break, and + * should be converted to the codepoint for paragraph separation + * (PS). + */ + UTF8PROC_NLF2PS = (1<<8), + /** Indicating that the meaning of NLF-sequences is unknown. */ + UTF8PROC_NLF2LF = (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS), + /** Strips and/or convers control characters. + * + * NLF-sequences are transformed into space, except if one of the + * NLF2LS/PS/LF options is given. HorizontalTab (HT) and FormFeed (FF) + * are treated as a NLF-sequence in this case. All other control + * characters are simply removed. + */ + UTF8PROC_STRIPCC = (1<<9), + /** + * Performs unicode case folding, to be able to do a case-insensitive + * string comparison. + */ + UTF8PROC_CASEFOLD = (1<<10), + /** + * Inserts 0xFF bytes at the beginning of each sequence which is + * representing a single grapheme cluster (see UAX#29). + */ + UTF8PROC_CHARBOUND = (1<<11), + /** Lumps certain characters together. + * + * E.g. HYPHEN U+2010 and MINUS U+2212 to ASCII "-". See lump.md for details. + * + * If NLF2LF is set, this includes a transformation of paragraph and + * line separators to ASCII line-feed (LF). + */ + UTF8PROC_LUMP = (1<<12), + /** Strips all character markings. + * + * This includes non-spacing, spacing and enclosing (i.e. accents). + * @note This option works only with @ref UTF8PROC_COMPOSE or + * @ref UTF8PROC_DECOMPOSE + */ + UTF8PROC_STRIPMARK = (1<<13), + /** + * Strip unassigned codepoints. + */ + UTF8PROC_STRIPNA = (1<<14), +} utf8proc_option_t; + +/** @name Error codes + * Error codes being returned by almost all functions. + */ +/** @{ */ +/** Memory could not be allocated. */ +#define UTF8PROC_ERROR_NOMEM -1 +/** The given string is too long to be processed. */ +#define UTF8PROC_ERROR_OVERFLOW -2 +/** The given string is not a legal UTF-8 string. */ +#define UTF8PROC_ERROR_INVALIDUTF8 -3 +/** The @ref UTF8PROC_REJECTNA flag was set and an unassigned codepoint was found. */ +#define UTF8PROC_ERROR_NOTASSIGNED -4 +/** Invalid options have been used. */ +#define UTF8PROC_ERROR_INVALIDOPTS -5 +/** @} */ + +/* @name Types */ + +/** Holds the value of a property. */ +typedef utf8proc_int16_t utf8proc_propval_t; + +/** Struct containing information about a codepoint. */ +typedef struct utf8proc_property_struct { + /** + * Unicode category. + * @see utf8proc_category_t. + */ + utf8proc_propval_t category; + utf8proc_propval_t combining_class; + /** + * Bidirectional class. + * @see utf8proc_bidi_class_t. + */ + utf8proc_propval_t bidi_class; + /** + * @anchor Decomposition type. + * @see utf8proc_decomp_type_t. + */ + utf8proc_propval_t decomp_type; + utf8proc_uint16_t decomp_seqindex; + utf8proc_uint16_t casefold_seqindex; + utf8proc_uint16_t uppercase_seqindex; + utf8proc_uint16_t lowercase_seqindex; + utf8proc_uint16_t titlecase_seqindex; + utf8proc_uint16_t comb_index; + unsigned bidi_mirrored:1; + unsigned comp_exclusion:1; + /** + * Can this codepoint be ignored? + * + * Used by utf8proc_decompose_char() when @ref UTF8PROC_IGNORE is + * passed as an option. + */ + unsigned ignorable:1; + unsigned control_boundary:1; + /** The width of the codepoint. */ + unsigned charwidth:2; + unsigned pad:2; + /** + * Boundclass. + * @see utf8proc_boundclass_t. + */ + unsigned boundclass:6; + unsigned indic_conjunct_break:2; +} utf8proc_property_t; + +/** Unicode categories. */ +typedef enum { + UTF8PROC_CATEGORY_CN = 0, /**< Other, not assigned */ + UTF8PROC_CATEGORY_LU = 1, /**< Letter, uppercase */ + UTF8PROC_CATEGORY_LL = 2, /**< Letter, lowercase */ + UTF8PROC_CATEGORY_LT = 3, /**< Letter, titlecase */ + UTF8PROC_CATEGORY_LM = 4, /**< Letter, modifier */ + UTF8PROC_CATEGORY_LO = 5, /**< Letter, other */ + UTF8PROC_CATEGORY_MN = 6, /**< Mark, nonspacing */ + UTF8PROC_CATEGORY_MC = 7, /**< Mark, spacing combining */ + UTF8PROC_CATEGORY_ME = 8, /**< Mark, enclosing */ + UTF8PROC_CATEGORY_ND = 9, /**< Number, decimal digit */ + UTF8PROC_CATEGORY_NL = 10, /**< Number, letter */ + UTF8PROC_CATEGORY_NO = 11, /**< Number, other */ + UTF8PROC_CATEGORY_PC = 12, /**< Punctuation, connector */ + UTF8PROC_CATEGORY_PD = 13, /**< Punctuation, dash */ + UTF8PROC_CATEGORY_PS = 14, /**< Punctuation, open */ + UTF8PROC_CATEGORY_PE = 15, /**< Punctuation, close */ + UTF8PROC_CATEGORY_PI = 16, /**< Punctuation, initial quote */ + UTF8PROC_CATEGORY_PF = 17, /**< Punctuation, final quote */ + UTF8PROC_CATEGORY_PO = 18, /**< Punctuation, other */ + UTF8PROC_CATEGORY_SM = 19, /**< Symbol, math */ + UTF8PROC_CATEGORY_SC = 20, /**< Symbol, currency */ + UTF8PROC_CATEGORY_SK = 21, /**< Symbol, modifier */ + UTF8PROC_CATEGORY_SO = 22, /**< Symbol, other */ + UTF8PROC_CATEGORY_ZS = 23, /**< Separator, space */ + UTF8PROC_CATEGORY_ZL = 24, /**< Separator, line */ + UTF8PROC_CATEGORY_ZP = 25, /**< Separator, paragraph */ + UTF8PROC_CATEGORY_CC = 26, /**< Other, control */ + UTF8PROC_CATEGORY_CF = 27, /**< Other, format */ + UTF8PROC_CATEGORY_CS = 28, /**< Other, surrogate */ + UTF8PROC_CATEGORY_CO = 29, /**< Other, private use */ +} utf8proc_category_t; + +/** Bidirectional character classes. */ +typedef enum { + UTF8PROC_BIDI_CLASS_L = 1, /**< Left-to-Right */ + UTF8PROC_BIDI_CLASS_LRE = 2, /**< Left-to-Right Embedding */ + UTF8PROC_BIDI_CLASS_LRO = 3, /**< Left-to-Right Override */ + UTF8PROC_BIDI_CLASS_R = 4, /**< Right-to-Left */ + UTF8PROC_BIDI_CLASS_AL = 5, /**< Right-to-Left Arabic */ + UTF8PROC_BIDI_CLASS_RLE = 6, /**< Right-to-Left Embedding */ + UTF8PROC_BIDI_CLASS_RLO = 7, /**< Right-to-Left Override */ + UTF8PROC_BIDI_CLASS_PDF = 8, /**< Pop Directional Format */ + UTF8PROC_BIDI_CLASS_EN = 9, /**< European Number */ + UTF8PROC_BIDI_CLASS_ES = 10, /**< European Separator */ + UTF8PROC_BIDI_CLASS_ET = 11, /**< European Number Terminator */ + UTF8PROC_BIDI_CLASS_AN = 12, /**< Arabic Number */ + UTF8PROC_BIDI_CLASS_CS = 13, /**< Common Number Separator */ + UTF8PROC_BIDI_CLASS_NSM = 14, /**< Nonspacing Mark */ + UTF8PROC_BIDI_CLASS_BN = 15, /**< Boundary Neutral */ + UTF8PROC_BIDI_CLASS_B = 16, /**< Paragraph Separator */ + UTF8PROC_BIDI_CLASS_S = 17, /**< Segment Separator */ + UTF8PROC_BIDI_CLASS_WS = 18, /**< Whitespace */ + UTF8PROC_BIDI_CLASS_ON = 19, /**< Other Neutrals */ + UTF8PROC_BIDI_CLASS_LRI = 20, /**< Left-to-Right Isolate */ + UTF8PROC_BIDI_CLASS_RLI = 21, /**< Right-to-Left Isolate */ + UTF8PROC_BIDI_CLASS_FSI = 22, /**< First Strong Isolate */ + UTF8PROC_BIDI_CLASS_PDI = 23, /**< Pop Directional Isolate */ +} utf8proc_bidi_class_t; + +/** Decomposition type. */ +typedef enum { + UTF8PROC_DECOMP_TYPE_FONT = 1, /**< Font */ + UTF8PROC_DECOMP_TYPE_NOBREAK = 2, /**< Nobreak */ + UTF8PROC_DECOMP_TYPE_INITIAL = 3, /**< Initial */ + UTF8PROC_DECOMP_TYPE_MEDIAL = 4, /**< Medial */ + UTF8PROC_DECOMP_TYPE_FINAL = 5, /**< Final */ + UTF8PROC_DECOMP_TYPE_ISOLATED = 6, /**< Isolated */ + UTF8PROC_DECOMP_TYPE_CIRCLE = 7, /**< Circle */ + UTF8PROC_DECOMP_TYPE_SUPER = 8, /**< Super */ + UTF8PROC_DECOMP_TYPE_SUB = 9, /**< Sub */ + UTF8PROC_DECOMP_TYPE_VERTICAL = 10, /**< Vertical */ + UTF8PROC_DECOMP_TYPE_WIDE = 11, /**< Wide */ + UTF8PROC_DECOMP_TYPE_NARROW = 12, /**< Narrow */ + UTF8PROC_DECOMP_TYPE_SMALL = 13, /**< Small */ + UTF8PROC_DECOMP_TYPE_SQUARE = 14, /**< Square */ + UTF8PROC_DECOMP_TYPE_FRACTION = 15, /**< Fraction */ + UTF8PROC_DECOMP_TYPE_COMPAT = 16, /**< Compat */ +} utf8proc_decomp_type_t; + +/** Boundclass property. (TR29) */ +typedef enum { + UTF8PROC_BOUNDCLASS_START = 0, /**< Start */ + UTF8PROC_BOUNDCLASS_OTHER = 1, /**< Other */ + UTF8PROC_BOUNDCLASS_CR = 2, /**< Cr */ + UTF8PROC_BOUNDCLASS_LF = 3, /**< Lf */ + UTF8PROC_BOUNDCLASS_CONTROL = 4, /**< Control */ + UTF8PROC_BOUNDCLASS_EXTEND = 5, /**< Extend */ + UTF8PROC_BOUNDCLASS_L = 6, /**< L */ + UTF8PROC_BOUNDCLASS_V = 7, /**< V */ + UTF8PROC_BOUNDCLASS_T = 8, /**< T */ + UTF8PROC_BOUNDCLASS_LV = 9, /**< Lv */ + UTF8PROC_BOUNDCLASS_LVT = 10, /**< Lvt */ + UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR = 11, /**< Regional indicator */ + UTF8PROC_BOUNDCLASS_SPACINGMARK = 12, /**< Spacingmark */ + UTF8PROC_BOUNDCLASS_PREPEND = 13, /**< Prepend */ + UTF8PROC_BOUNDCLASS_ZWJ = 14, /**< Zero Width Joiner */ + + /* the following are no longer used in Unicode 11, but we keep + the constants here for backward compatibility */ + UTF8PROC_BOUNDCLASS_E_BASE = 15, /**< Emoji Base */ + UTF8PROC_BOUNDCLASS_E_MODIFIER = 16, /**< Emoji Modifier */ + UTF8PROC_BOUNDCLASS_GLUE_AFTER_ZWJ = 17, /**< Glue_After_ZWJ */ + UTF8PROC_BOUNDCLASS_E_BASE_GAZ = 18, /**< E_BASE + GLUE_AFTER_ZJW */ + + /* the Extended_Pictographic property is used in the Unicode 11 + grapheme-boundary rules, so we store it in the boundclass field */ + UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC = 19, + UTF8PROC_BOUNDCLASS_E_ZWG = 20, /* UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC + ZWJ */ +} utf8proc_boundclass_t; + +/** Indic_Conjunct_Break property. (TR44) */ +typedef enum { + UTF8PROC_INDIC_CONJUNCT_BREAK_NONE = 0, + UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER = 1, + UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT = 2, + UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND = 3, +} utf8proc_indic_conjunct_break_t; + +/** + * Function pointer type passed to utf8proc_map_custom() and + * utf8proc_decompose_custom(), which is used to specify a user-defined + * mapping of codepoints to be applied in conjunction with other mappings. + */ +typedef utf8proc_int32_t (*utf8proc_custom_func)(utf8proc_int32_t codepoint, void *data); + +/** + * Array containing the byte lengths of a UTF-8 encoded codepoint based + * on the first byte. + */ +UTF8PROC_DLLEXPORT extern const utf8proc_int8_t utf8proc_utf8class[256]; + +/** + * Returns the utf8proc API version as a string MAJOR.MINOR.PATCH + * (http://semver.org format), possibly with a "-dev" suffix for + * development versions. + */ +UTF8PROC_DLLEXPORT const char *utf8proc_version(void); + +/** + * Returns the utf8proc supported Unicode version as a string MAJOR.MINOR.PATCH. + */ +UTF8PROC_DLLEXPORT const char *utf8proc_unicode_version(void); + +/** + * Returns an informative error string for the given utf8proc error code + * (e.g. the error codes returned by utf8proc_map()). + */ +UTF8PROC_DLLEXPORT const char *utf8proc_errmsg(utf8proc_ssize_t errcode); + +/** + * Reads a single codepoint from the UTF-8 sequence being pointed to by `str`. + * The maximum number of bytes read is `strlen`, unless `strlen` is + * negative (in which case up to 4 bytes are read). + * + * If a valid codepoint could be read, it is stored in the variable + * pointed to by `codepoint_ref`, otherwise that variable will be set to -1. + * In case of success, the number of bytes read is returned; otherwise, a + * negative error code is returned. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_iterate(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_int32_t *codepoint_ref); + +/** + * Check if a codepoint is valid (regardless of whether it has been + * assigned a value by the current Unicode standard). + * + * @return 1 if the given `codepoint` is valid and otherwise return 0. + */ +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_codepoint_valid(utf8proc_int32_t codepoint); + +/** + * Encodes the codepoint as an UTF-8 string in the byte array pointed + * to by `dst`. This array must be at least 4 bytes long. + * + * In case of success the number of bytes written is returned, and + * otherwise 0 is returned. + * + * This function does not check whether `codepoint` is valid Unicode. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_t codepoint, utf8proc_uint8_t *dst); + +/** + * Look up the properties for a given codepoint. + * + * @param codepoint The Unicode codepoint. + * + * @returns + * A pointer to a (constant) struct containing information about + * the codepoint. + * @par + * If the codepoint is unassigned or invalid, a pointer to a special struct is + * returned in which `category` is 0 (@ref UTF8PROC_CATEGORY_CN). + */ +UTF8PROC_DLLEXPORT const utf8proc_property_t *utf8proc_get_property(utf8proc_int32_t codepoint); + +/** Decompose a codepoint into an array of codepoints. + * + * @param codepoint the codepoint. + * @param dst the destination buffer. + * @param bufsize the size of the destination buffer. + * @param options one or more of the following flags: + * - @ref UTF8PROC_REJECTNA - return an error `codepoint` is unassigned + * - @ref UTF8PROC_IGNORE - strip "default ignorable" codepoints + * - @ref UTF8PROC_CASEFOLD - apply Unicode casefolding + * - @ref UTF8PROC_COMPAT - replace certain codepoints with their + * compatibility decomposition + * - @ref UTF8PROC_CHARBOUND - insert 0xFF bytes before each grapheme cluster + * - @ref UTF8PROC_LUMP - lump certain different codepoints together + * - @ref UTF8PROC_STRIPMARK - remove all character marks + * - @ref UTF8PROC_STRIPNA - remove unassigned codepoints + * @param last_boundclass + * Pointer to an integer variable containing + * the previous codepoint's (boundclass + indic_conjunct_break << 1) if the @ref UTF8PROC_CHARBOUND + * option is used. If the string is being processed in order, this can be initialized to 0 for + * the beginning of the string, and is thereafter updated automatically. Otherwise, this parameter is ignored. + * + * @return + * In case of success, the number of codepoints written is returned; in case + * of an error, a negative error code is returned (utf8proc_errmsg()). + * @par + * If the number of written codepoints would be bigger than `bufsize`, the + * required buffer size is returned, while the buffer will be overwritten with + * undefined data. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char( + utf8proc_int32_t codepoint, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, + utf8proc_option_t options, int *last_boundclass +); + +/** + * The same as utf8proc_decompose_char(), but acts on a whole UTF-8 + * string and orders the decomposed sequences correctly. + * + * If the @ref UTF8PROC_NULLTERM flag in `options` is set, processing + * will be stopped, when a NULL byte is encountered, otherwise `strlen` + * bytes are processed. The result (in the form of 32-bit unicode + * codepoints) is written into the buffer being pointed to by + * `buffer` (which must contain at least `bufsize` entries). In case of + * success, the number of codepoints written is returned; in case of an + * error, a negative error code is returned (utf8proc_errmsg()). + * See utf8proc_decompose_custom() to supply additional transformations. + * + * If the number of written codepoints would be bigger than `bufsize`, the + * required buffer size is returned, while the buffer will be overwritten with + * undefined data. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options +); + +/** + * The same as utf8proc_decompose(), but also takes a `custom_func` mapping function + * that is called on each codepoint in `str` before any other transformations + * (along with a `custom_data` pointer that is passed through to `custom_func`). + * The `custom_func` argument is ignored if it is `NULL`. See also utf8proc_map_custom(). + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data +); + +/** + * Normalizes the sequence of `length` codepoints pointed to by `buffer` + * in-place (i.e., the result is also stored in `buffer`). + * + * @param buffer the (native-endian UTF-32) unicode codepoints to re-encode. + * @param length the length (in codepoints) of the buffer. + * @param options a bitwise or (`|`) of one or more of the following flags: + * - @ref UTF8PROC_NLF2LS - convert LF, CRLF, CR and NEL into LS + * - @ref UTF8PROC_NLF2PS - convert LF, CRLF, CR and NEL into PS + * - @ref UTF8PROC_NLF2LF - convert LF, CRLF, CR and NEL into LF + * - @ref UTF8PROC_STRIPCC - strip or convert all non-affected control characters + * - @ref UTF8PROC_COMPOSE - try to combine decomposed codepoints into composite + * codepoints + * - @ref UTF8PROC_STABLE - prohibit combining characters that would violate + * the unicode versioning stability + * + * @return + * In case of success, the length (in codepoints) of the normalized UTF-32 string is + * returned; otherwise, a negative error code is returned (utf8proc_errmsg()). + * + * @warning The entries of the array pointed to by `str` have to be in the + * range `0x0000` to `0x10FFFF`. Otherwise, the program might crash! + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options); + +/** + * Reencodes the sequence of `length` codepoints pointed to by `buffer` + * UTF-8 data in-place (i.e., the result is also stored in `buffer`). + * Can optionally normalize the UTF-32 sequence prior to UTF-8 conversion. + * + * @param buffer the (native-endian UTF-32) unicode codepoints to re-encode. + * @param length the length (in codepoints) of the buffer. + * @param options a bitwise or (`|`) of one or more of the following flags: + * - @ref UTF8PROC_NLF2LS - convert LF, CRLF, CR and NEL into LS + * - @ref UTF8PROC_NLF2PS - convert LF, CRLF, CR and NEL into PS + * - @ref UTF8PROC_NLF2LF - convert LF, CRLF, CR and NEL into LF + * - @ref UTF8PROC_STRIPCC - strip or convert all non-affected control characters + * - @ref UTF8PROC_COMPOSE - try to combine decomposed codepoints into composite + * codepoints + * - @ref UTF8PROC_STABLE - prohibit combining characters that would violate + * the unicode versioning stability + * - @ref UTF8PROC_CHARBOUND - insert 0xFF bytes before each grapheme cluster + * + * @return + * In case of success, the length (in bytes) of the resulting nul-terminated + * UTF-8 string is returned; otherwise, a negative error code is returned + * (utf8proc_errmsg()). + * + * @warning The amount of free space pointed to by `buffer` must + * exceed the amount of the input data by one byte, and the + * entries of the array pointed to by `str` have to be in the + * range `0x0000` to `0x10FFFF`. Otherwise, the program might crash! + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options); + +/** + * Given a pair of consecutive codepoints, return whether a grapheme break is + * permitted between them (as defined by the extended grapheme clusters in UAX#29). + * + * @param codepoint1 The first codepoint. + * @param codepoint2 The second codepoint, occurring consecutively after `codepoint1`. + * @param state Beginning with Version 29 (Unicode 9.0.0), this algorithm requires + * state to break graphemes. This state can be passed in as a pointer + * in the `state` argument and should initially be set to 0. If the + * state is not passed in (i.e. a null pointer is passed), UAX#29 rules + * GB10/12/13 which require this state will not be applied, essentially + * matching the rules in Unicode 8.0.0. + * + * @warning If the state parameter is used, `utf8proc_grapheme_break_stateful` must + * be called IN ORDER on ALL potential breaks in a string. However, it + * is safe to reset the state to zero after a grapheme break. + */ +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break_stateful( + utf8proc_int32_t codepoint1, utf8proc_int32_t codepoint2, utf8proc_int32_t *state); + +/** + * Same as utf8proc_grapheme_break_stateful(), except without support for the + * Unicode 9 additions to the algorithm. Supported for legacy reasons. + */ +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break( + utf8proc_int32_t codepoint1, utf8proc_int32_t codepoint2); + + +/** + * Given a codepoint `c`, return the codepoint of the corresponding + * lower-case character, if any; otherwise (if there is no lower-case + * variant, or if `c` is not a valid codepoint) return `c`. + */ +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_tolower(utf8proc_int32_t c); + +/** + * Given a codepoint `c`, return the codepoint of the corresponding + * upper-case character, if any; otherwise (if there is no upper-case + * variant, or if `c` is not a valid codepoint) return `c`. + */ +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_toupper(utf8proc_int32_t c); + +/** + * Given a codepoint `c`, return the codepoint of the corresponding + * title-case character, if any; otherwise (if there is no title-case + * variant, or if `c` is not a valid codepoint) return `c`. + */ +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c); + +/** + * Given a codepoint `c`, return `1` if the codepoint corresponds to a lower-case character + * and `0` otherwise. + */ +UTF8PROC_DLLEXPORT int utf8proc_islower(utf8proc_int32_t c); + +/** + * Given a codepoint `c`, return `1` if the codepoint corresponds to an upper-case character + * and `0` otherwise. + */ +UTF8PROC_DLLEXPORT int utf8proc_isupper(utf8proc_int32_t c); + +/** + * Given a codepoint, return a character width analogous to `wcwidth(codepoint)`, + * except that a width of 0 is returned for non-printable codepoints + * instead of -1 as in `wcwidth`. + * + * @note + * If you want to check for particular types of non-printable characters, + * (analogous to `isprint` or `iscntrl`), use utf8proc_category(). */ +UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t codepoint); + +/** + * Return the Unicode category for the codepoint (one of the + * @ref utf8proc_category_t constants.) + */ +UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t codepoint); + +/** + * Return the two-letter (nul-terminated) Unicode category string for + * the codepoint (e.g. `"Lu"` or `"Co"`). + */ +UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t codepoint); + +/** + * Maps the given UTF-8 string pointed to by `str` to a new UTF-8 + * string, allocated dynamically by `malloc` and returned via `dstptr`. + * + * If the @ref UTF8PROC_NULLTERM flag in the `options` field is set, + * the length is determined by a NULL terminator, otherwise the + * parameter `strlen` is evaluated to determine the string length, but + * in any case the result will be NULL terminated (though it might + * contain NULL characters with the string if `str` contained NULL + * characters). Other flags in the `options` field are passed to the + * functions defined above, and regarded as described. See also + * utf8proc_map_custom() to supply a custom codepoint transformation. + * + * In case of success the length of the new string is returned, + * otherwise a negative error code is returned. + * + * @note The memory of the new UTF-8 string will have been allocated + * with `malloc`, and should therefore be deallocated with `free`. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options +); + +/** + * Like utf8proc_map(), but also takes a `custom_func` mapping function + * that is called on each codepoint in `str` before any other transformations + * (along with a `custom_data` pointer that is passed through to `custom_func`). + * The `custom_func` argument is ignored if it is `NULL`. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data +); + +/** @name Unicode normalization + * + * Returns a pointer to newly allocated memory of a NFD, NFC, NFKD, NFKC or + * NFKC_Casefold normalized version of the null-terminated string `str`. These + * are shortcuts to calling utf8proc_map() with @ref UTF8PROC_NULLTERM + * combined with @ref UTF8PROC_STABLE and flags indicating the normalization. + */ +/** @{ */ +/** NFD normalization (@ref UTF8PROC_DECOMPOSE). */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str); +/** NFC normalization (@ref UTF8PROC_COMPOSE). */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str); +/** NFKD normalization (@ref UTF8PROC_DECOMPOSE and @ref UTF8PROC_COMPAT). */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str); +/** NFKC normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT). */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str); +/** + * NFKC_Casefold normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT + * and @ref UTF8PROC_CASEFOLD and @ref UTF8PROC_IGNORE). + **/ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8proc_uint8_t *str); +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/common/thirdparty/utf8proc/utf8proc_data.c b/src/common/thirdparty/utf8proc/utf8proc_data.c new file mode 100644 index 0000000000..b26bcb3b6f --- /dev/null +++ b/src/common/thirdparty/utf8proc/utf8proc_data.c @@ -0,0 +1,16960 @@ +static const utf8proc_uint16_t utf8proc_sequences[] = { + 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 32, 32, 776, 32, 772, + 50, 51, 32, 769, 956, 32, 807, 49, + 49, 8260, 52, 49, 8260, 50, 51, 8260, + 52, 65, 768, 224, 65, 769, 225, 65, + 770, 226, 65, 771, 227, 65, 776, 228, + 65, 778, 229, 230, 67, 807, 231, 69, + 768, 232, 69, 769, 233, 69, 770, 234, + 69, 776, 235, 73, 768, 236, 73, 769, + 237, 73, 770, 238, 73, 776, 239, 240, + 78, 771, 241, 79, 768, 242, 79, 769, + 243, 79, 770, 244, 79, 771, 245, 79, + 776, 246, 248, 85, 768, 249, 85, 769, + 250, 85, 770, 251, 85, 776, 252, 89, + 769, 253, 254, 115, 115, 97, 768, 97, + 769, 97, 770, 97, 771, 97, 776, 97, + 778, 99, 807, 101, 768, 101, 769, 101, + 770, 101, 776, 105, 768, 105, 769, 105, + 770, 105, 776, 110, 771, 111, 768, 111, + 769, 111, 770, 111, 771, 111, 776, 117, + 768, 117, 769, 117, 770, 117, 776, 121, + 769, 121, 776, 65, 772, 257, 97, 772, + 65, 774, 259, 97, 774, 65, 808, 261, + 97, 808, 67, 769, 263, 99, 769, 67, + 770, 265, 99, 770, 67, 775, 267, 99, + 775, 67, 780, 269, 99, 780, 68, 780, + 271, 100, 780, 273, 69, 772, 275, 101, + 772, 69, 774, 277, 101, 774, 69, 775, + 279, 101, 775, 69, 808, 281, 101, 808, + 69, 780, 283, 101, 780, 71, 770, 285, + 103, 770, 71, 774, 287, 103, 774, 71, + 775, 289, 103, 775, 71, 807, 291, 103, + 807, 72, 770, 293, 104, 770, 295, 73, + 771, 297, 105, 771, 73, 772, 299, 105, + 772, 73, 774, 301, 105, 774, 73, 808, + 303, 105, 808, 73, 775, 105, 775, 73, + 74, 307, 105, 106, 74, 770, 309, 106, + 770, 75, 807, 311, 107, 807, 76, 769, + 314, 108, 769, 76, 807, 316, 108, 807, + 76, 780, 318, 108, 780, 76, 183, 320, + 108, 183, 322, 78, 769, 324, 110, 769, + 78, 807, 326, 110, 807, 78, 780, 328, + 110, 780, 700, 110, 331, 79, 772, 333, + 111, 772, 79, 774, 335, 111, 774, 79, + 779, 337, 111, 779, 339, 82, 769, 341, + 114, 769, 82, 807, 343, 114, 807, 82, + 780, 345, 114, 780, 83, 769, 347, 115, + 769, 83, 770, 349, 115, 770, 83, 807, + 351, 115, 807, 83, 780, 353, 115, 780, + 84, 807, 355, 116, 807, 84, 780, 357, + 116, 780, 359, 85, 771, 361, 117, 771, + 85, 772, 363, 117, 772, 85, 774, 365, + 117, 774, 85, 778, 367, 117, 778, 85, + 779, 369, 117, 779, 85, 808, 371, 117, + 808, 87, 770, 373, 119, 770, 89, 770, + 375, 121, 770, 89, 776, 255, 90, 769, + 378, 122, 769, 90, 775, 380, 122, 775, + 90, 780, 382, 122, 780, 595, 387, 389, + 596, 392, 598, 599, 396, 477, 601, 603, + 402, 608, 611, 617, 616, 409, 623, 626, + 629, 79, 795, 417, 111, 795, 419, 421, + 640, 424, 643, 429, 648, 85, 795, 432, + 117, 795, 650, 651, 436, 438, 658, 441, + 445, 68, 381, 454, 68, 382, 100, 382, + 76, 74, 457, 76, 106, 108, 106, 78, + 74, 460, 78, 106, 110, 106, 65, 780, + 462, 97, 780, 73, 780, 464, 105, 780, + 79, 780, 466, 111, 780, 85, 780, 468, + 117, 780, 220, 772, 470, 252, 772, 220, + 769, 472, 252, 769, 220, 780, 474, 252, + 780, 220, 768, 476, 252, 768, 196, 772, + 479, 228, 772, 550, 772, 481, 551, 772, + 198, 772, 483, 230, 772, 485, 71, 780, + 487, 103, 780, 75, 780, 489, 107, 780, + 79, 808, 491, 111, 808, 490, 772, 493, + 491, 772, 439, 780, 495, 658, 780, 106, + 780, 68, 90, 499, 68, 122, 100, 122, + 71, 769, 501, 103, 769, 405, 447, 78, + 768, 505, 110, 768, 197, 769, 507, 229, + 769, 198, 769, 509, 230, 769, 216, 769, + 511, 248, 769, 65, 783, 513, 97, 783, + 65, 785, 515, 97, 785, 69, 783, 517, + 101, 783, 69, 785, 519, 101, 785, 73, + 783, 521, 105, 783, 73, 785, 523, 105, + 785, 79, 783, 525, 111, 783, 79, 785, + 527, 111, 785, 82, 783, 529, 114, 783, + 82, 785, 531, 114, 785, 85, 783, 533, + 117, 783, 85, 785, 535, 117, 785, 83, + 806, 537, 115, 806, 84, 806, 539, 116, + 806, 541, 72, 780, 543, 104, 780, 414, + 547, 549, 65, 775, 551, 97, 775, 69, + 807, 553, 101, 807, 214, 772, 555, 246, + 772, 213, 772, 557, 245, 772, 79, 775, + 559, 111, 775, 558, 772, 561, 559, 772, + 89, 772, 563, 121, 772, 11365, 572, 410, + 11366, 578, 384, 649, 652, 583, 585, 587, + 589, 591, 614, 633, 635, 641, 32, 774, + 32, 775, 32, 778, 32, 808, 32, 771, + 32, 779, 661, 768, 769, 787, 776, 769, + 953, 881, 883, 697, 887, 32, 837, 59, + 1011, 168, 769, 913, 769, 940, 183, 917, + 769, 941, 919, 769, 942, 921, 769, 943, + 927, 769, 972, 933, 769, 973, 937, 769, + 974, 970, 769, 953, 776, 769, 945, 946, + 947, 948, 949, 950, 951, 952, 954, 955, + 957, 958, 959, 960, 961, 963, 964, 965, + 966, 967, 968, 969, 921, 776, 970, 933, + 776, 971, 945, 769, 949, 769, 951, 769, + 953, 769, 971, 769, 965, 776, 769, 953, + 776, 965, 776, 959, 769, 965, 769, 969, + 769, 983, 933, 978, 769, 978, 776, 985, + 987, 989, 991, 993, 995, 997, 999, 1001, + 1003, 1005, 1007, 962, 920, 1016, 931, 1010, + 1019, 891, 892, 893, 1045, 768, 1104, 1045, + 776, 1105, 1106, 1043, 769, 1107, 1108, 1109, + 1110, 1030, 776, 1111, 1112, 1113, 1114, 1115, + 1050, 769, 1116, 1048, 768, 1117, 1059, 774, + 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077, + 1078, 1079, 1080, 1048, 774, 1081, 1082, 1083, + 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, + 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, + 1100, 1101, 1102, 1103, 1080, 774, 1077, 768, + 1077, 776, 1075, 769, 1110, 776, 1082, 769, + 1080, 768, 1091, 774, 1121, 1123, 1125, 1127, + 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1140, + 783, 1143, 1141, 783, 1145, 1147, 1149, 1151, + 1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, + 1177, 1179, 1181, 1183, 1185, 1187, 1189, 1191, + 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, + 1209, 1211, 1213, 1215, 1231, 1046, 774, 1218, + 1078, 774, 1220, 1222, 1224, 1226, 1228, 1230, + 1040, 774, 1233, 1072, 774, 1040, 776, 1235, + 1072, 776, 1237, 1045, 774, 1239, 1077, 774, + 1241, 1240, 776, 1243, 1241, 776, 1046, 776, + 1245, 1078, 776, 1047, 776, 1247, 1079, 776, + 1249, 1048, 772, 1251, 1080, 772, 1048, 776, + 1253, 1080, 776, 1054, 776, 1255, 1086, 776, + 1257, 1256, 776, 1259, 1257, 776, 1069, 776, + 1261, 1101, 776, 1059, 772, 1263, 1091, 772, + 1059, 776, 1265, 1091, 776, 1059, 779, 1267, + 1091, 779, 1063, 776, 1269, 1095, 776, 1271, + 1067, 776, 1273, 1099, 776, 1275, 1277, 1279, + 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, + 1297, 1299, 1301, 1303, 1305, 1307, 1309, 1311, + 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, + 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, + 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, + 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, + 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, + 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, + 1575, 1619, 1575, 1620, 1608, 1620, 1575, 1621, + 1610, 1620, 1575, 1652, 1608, 1652, 1735, 1652, + 1610, 1652, 1749, 1620, 1729, 1620, 1746, 1620, + 2344, 2364, 2352, 2364, 2355, 2364, 2325, 2364, + 2326, 2364, 2327, 2364, 2332, 2364, 2337, 2364, + 2338, 2364, 2347, 2364, 2351, 2364, 2503, 2494, + 2503, 2519, 2465, 2492, 2466, 2492, 2479, 2492, + 2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, + 2588, 2620, 2603, 2620, 2887, 2902, 2887, 2878, + 2887, 2903, 2849, 2876, 2850, 2876, 2962, 3031, + 3014, 3006, 3015, 3006, 3014, 3031, 3142, 3158, + 3263, 3285, 3270, 3285, 3270, 3286, 3270, 3266, + 3274, 3285, 3398, 3390, 3399, 3390, 3398, 3415, + 3545, 3530, 3545, 3535, 3548, 3530, 3545, 3551, + 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, + 3851, 3906, 4023, 3916, 4023, 3921, 4023, 3926, + 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, + 3956, 4018, 3968, 4018, 3969, 4019, 3968, 4019, + 3969, 3953, 3968, 3986, 4023, 3996, 4023, 4001, + 4023, 4006, 4023, 4011, 4023, 3984, 4021, 4133, + 4142, 11520, 11521, 11522, 11523, 11524, 11525, 11526, + 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, + 11535, 11536, 11537, 11538, 11539, 11540, 11541, 11542, + 11543, 11544, 11545, 11546, 11547, 11548, 11549, 11550, + 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, + 11565, 4316, 5104, 5105, 5106, 5107, 5108, 5109, + 6917, 6965, 6919, 6965, 6921, 6965, 6923, 6965, + 6925, 6965, 6929, 6965, 6970, 6965, 6972, 6965, + 6974, 6965, 6975, 6965, 6978, 6965, 42571, 4304, + 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, + 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, + 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, + 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, + 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, + 4346, 4349, 4350, 4351, 65, 198, 66, 68, + 69, 398, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 546, 80, 82, 84, 85, + 87, 592, 593, 7426, 604, 7446, 7447, 7453, + 7461, 594, 597, 607, 609, 613, 618, 7547, + 669, 621, 7557, 671, 625, 624, 627, 628, + 632, 642, 427, 7452, 656, 657, 65, 805, + 7681, 97, 805, 66, 775, 7683, 98, 775, + 66, 803, 7685, 98, 803, 66, 817, 7687, + 98, 817, 199, 769, 7689, 231, 769, 68, + 775, 7691, 100, 775, 68, 803, 7693, 100, + 803, 68, 817, 7695, 100, 817, 68, 807, + 7697, 100, 807, 68, 813, 7699, 100, 813, + 274, 768, 7701, 275, 768, 274, 769, 7703, + 275, 769, 69, 813, 7705, 101, 813, 69, + 816, 7707, 101, 816, 552, 774, 7709, 553, + 774, 70, 775, 7711, 102, 775, 71, 772, + 7713, 103, 772, 72, 775, 7715, 104, 775, + 72, 803, 7717, 104, 803, 72, 776, 7719, + 104, 776, 72, 807, 7721, 104, 807, 72, + 814, 7723, 104, 814, 73, 816, 7725, 105, + 816, 207, 769, 7727, 239, 769, 75, 769, + 7729, 107, 769, 75, 803, 7731, 107, 803, + 75, 817, 7733, 107, 817, 76, 803, 7735, + 108, 803, 7734, 772, 7737, 7735, 772, 76, + 817, 7739, 108, 817, 76, 813, 7741, 108, + 813, 77, 769, 7743, 109, 769, 77, 775, + 7745, 109, 775, 77, 803, 7747, 109, 803, + 78, 775, 7749, 110, 775, 78, 803, 7751, + 110, 803, 78, 817, 7753, 110, 817, 78, + 813, 7755, 110, 813, 213, 769, 7757, 245, + 769, 213, 776, 7759, 245, 776, 332, 768, + 7761, 333, 768, 332, 769, 7763, 333, 769, + 80, 769, 7765, 112, 769, 80, 775, 7767, + 112, 775, 82, 775, 7769, 114, 775, 82, + 803, 7771, 114, 803, 7770, 772, 7773, 7771, + 772, 82, 817, 7775, 114, 817, 83, 775, + 7777, 115, 775, 83, 803, 7779, 115, 803, + 346, 775, 7781, 347, 775, 352, 775, 7783, + 353, 775, 7778, 775, 7785, 7779, 775, 84, + 775, 7787, 116, 775, 84, 803, 7789, 116, + 803, 84, 817, 7791, 116, 817, 84, 813, + 7793, 116, 813, 85, 804, 7795, 117, 804, + 85, 816, 7797, 117, 816, 85, 813, 7799, + 117, 813, 360, 769, 7801, 361, 769, 362, + 776, 7803, 363, 776, 86, 771, 7805, 118, + 771, 86, 803, 7807, 118, 803, 87, 768, + 7809, 119, 768, 87, 769, 7811, 119, 769, + 87, 776, 7813, 119, 776, 87, 775, 7815, + 119, 775, 87, 803, 7817, 119, 803, 88, + 775, 7819, 120, 775, 88, 776, 7821, 120, + 776, 89, 775, 7823, 121, 775, 90, 770, + 7825, 122, 770, 90, 803, 7827, 122, 803, + 90, 817, 7829, 122, 817, 104, 817, 116, + 776, 119, 778, 121, 778, 97, 702, 383, + 775, 65, 803, 7841, 97, 803, 65, 777, + 7843, 97, 777, 194, 769, 7845, 226, 769, + 194, 768, 7847, 226, 768, 194, 777, 7849, + 226, 777, 194, 771, 7851, 226, 771, 7840, + 770, 7853, 7841, 770, 258, 769, 7855, 259, + 769, 258, 768, 7857, 259, 768, 258, 777, + 7859, 259, 777, 258, 771, 7861, 259, 771, + 7840, 774, 7863, 7841, 774, 69, 803, 7865, + 101, 803, 69, 777, 7867, 101, 777, 69, + 771, 7869, 101, 771, 202, 769, 7871, 234, + 769, 202, 768, 7873, 234, 768, 202, 777, + 7875, 234, 777, 202, 771, 7877, 234, 771, + 7864, 770, 7879, 7865, 770, 73, 777, 7881, + 105, 777, 73, 803, 7883, 105, 803, 79, + 803, 7885, 111, 803, 79, 777, 7887, 111, + 777, 212, 769, 7889, 244, 769, 212, 768, + 7891, 244, 768, 212, 777, 7893, 244, 777, + 212, 771, 7895, 244, 771, 7884, 770, 7897, + 7885, 770, 416, 769, 7899, 417, 769, 416, + 768, 7901, 417, 768, 416, 777, 7903, 417, + 777, 416, 771, 7905, 417, 771, 416, 803, + 7907, 417, 803, 85, 803, 7909, 117, 803, + 85, 777, 7911, 117, 777, 431, 769, 7913, + 432, 769, 431, 768, 7915, 432, 768, 431, + 777, 7917, 432, 777, 431, 771, 7919, 432, + 771, 431, 803, 7921, 432, 803, 89, 768, + 7923, 121, 768, 89, 803, 7925, 121, 803, + 89, 777, 7927, 121, 777, 89, 771, 7929, + 121, 771, 7931, 7933, 7935, 945, 787, 945, + 788, 7936, 768, 7937, 768, 7936, 769, 7937, + 769, 7936, 834, 7937, 834, 913, 787, 7936, + 913, 788, 7937, 7944, 768, 7938, 7945, 768, + 7939, 7944, 769, 7940, 7945, 769, 7941, 7944, + 834, 7942, 7945, 834, 7943, 949, 787, 949, + 788, 7952, 768, 7953, 768, 7952, 769, 7953, + 769, 917, 787, 7952, 917, 788, 7953, 7960, + 768, 7954, 7961, 768, 7955, 7960, 769, 7956, + 7961, 769, 7957, 951, 787, 951, 788, 7968, + 768, 7969, 768, 7968, 769, 7969, 769, 7968, + 834, 7969, 834, 919, 787, 7968, 919, 788, + 7969, 7976, 768, 7970, 7977, 768, 7971, 7976, + 769, 7972, 7977, 769, 7973, 7976, 834, 7974, + 7977, 834, 7975, 953, 787, 953, 788, 7984, + 768, 7985, 768, 7984, 769, 7985, 769, 7984, + 834, 7985, 834, 921, 787, 7984, 921, 788, + 7985, 7992, 768, 7986, 7993, 768, 7987, 7992, + 769, 7988, 7993, 769, 7989, 7992, 834, 7990, + 7993, 834, 7991, 959, 787, 959, 788, 8000, + 768, 8001, 768, 8000, 769, 8001, 769, 927, + 787, 8000, 927, 788, 8001, 8008, 768, 8002, + 8009, 768, 8003, 8008, 769, 8004, 8009, 769, + 8005, 965, 787, 965, 788, 8016, 768, 965, + 787, 768, 8017, 768, 8016, 769, 965, 787, + 769, 8017, 769, 8016, 834, 965, 787, 834, + 8017, 834, 933, 788, 8017, 8025, 768, 8019, + 8025, 769, 8021, 8025, 834, 8023, 969, 787, + 969, 788, 8032, 768, 8033, 768, 8032, 769, + 8033, 769, 8032, 834, 8033, 834, 937, 787, + 8032, 937, 788, 8033, 8040, 768, 8034, 8041, + 768, 8035, 8040, 769, 8036, 8041, 769, 8037, + 8040, 834, 8038, 8041, 834, 8039, 945, 768, + 949, 768, 951, 768, 953, 768, 959, 768, + 965, 768, 969, 768, 7936, 837, 7936, 953, + 7937, 837, 7937, 953, 7938, 837, 7938, 953, + 7939, 837, 7939, 953, 7940, 837, 7940, 953, + 7941, 837, 7941, 953, 7942, 837, 7942, 953, + 7943, 837, 7943, 953, 7944, 837, 7945, 837, + 7946, 837, 7947, 837, 7948, 837, 7949, 837, + 7950, 837, 7951, 837, 7968, 837, 7968, 953, + 7969, 837, 7969, 953, 7970, 837, 7970, 953, + 7971, 837, 7971, 953, 7972, 837, 7972, 953, + 7973, 837, 7973, 953, 7974, 837, 7974, 953, + 7975, 837, 7975, 953, 7976, 837, 7977, 837, + 7978, 837, 7979, 837, 7980, 837, 7981, 837, + 7982, 837, 7983, 837, 8032, 837, 8032, 953, + 8033, 837, 8033, 953, 8034, 837, 8034, 953, + 8035, 837, 8035, 953, 8036, 837, 8036, 953, + 8037, 837, 8037, 953, 8038, 837, 8038, 953, + 8039, 837, 8039, 953, 8040, 837, 8041, 837, + 8042, 837, 8043, 837, 8044, 837, 8045, 837, + 8046, 837, 8047, 837, 945, 774, 945, 772, + 8048, 837, 8048, 953, 945, 837, 945, 953, + 940, 837, 940, 953, 945, 834, 8118, 837, + 945, 834, 953, 913, 774, 8112, 913, 772, + 8113, 913, 768, 8048, 902, 8049, 913, 837, + 32, 787, 32, 834, 168, 834, 8052, 837, + 8052, 953, 951, 837, 951, 953, 942, 837, + 942, 953, 951, 834, 8134, 837, 951, 834, + 953, 917, 768, 8050, 904, 8051, 919, 768, + 8052, 905, 8053, 919, 837, 8127, 768, 8127, + 769, 8127, 834, 953, 774, 953, 772, 970, + 768, 953, 776, 768, 912, 953, 834, 970, + 834, 953, 776, 834, 921, 774, 8144, 921, + 772, 8145, 921, 768, 8054, 906, 8055, 8190, + 768, 8190, 769, 8190, 834, 965, 774, 965, + 772, 971, 768, 965, 776, 768, 944, 961, + 787, 961, 788, 965, 834, 971, 834, 965, + 776, 834, 933, 774, 8160, 933, 772, 8161, + 933, 768, 8058, 910, 8059, 929, 788, 8165, + 168, 768, 901, 96, 8060, 837, 8060, 953, + 969, 837, 969, 953, 974, 837, 974, 953, + 969, 834, 8182, 837, 969, 834, 953, 927, + 768, 8056, 908, 8057, 937, 768, 8060, 911, + 8061, 937, 837, 180, 32, 788, 8194, 8195, + 8208, 32, 819, 46, 46, 46, 46, 46, + 46, 8242, 8242, 8242, 8242, 8242, 8245, 8245, + 8245, 8245, 8245, 33, 33, 32, 773, 63, + 63, 63, 33, 33, 63, 3, 8242, 8242, + 8242, 8242, 48, 52, 53, 54, 55, 56, + 57, 43, 8722, 61, 40, 41, 82, 115, + 97, 47, 99, 97, 47, 115, 67, 176, + 67, 99, 47, 111, 99, 47, 117, 400, + 176, 70, 78, 111, 81, 83, 77, 84, + 69, 76, 84, 77, 90, 937, 197, 70, + 8526, 1488, 1489, 1490, 1491, 70, 65, 88, + 915, 928, 8721, 49, 8260, 55, 49, 8260, + 57, 3, 49, 8260, 49, 48, 49, 8260, + 51, 50, 8260, 51, 49, 8260, 53, 50, + 8260, 53, 51, 8260, 53, 52, 8260, 53, + 49, 8260, 54, 53, 8260, 54, 49, 8260, + 56, 51, 8260, 56, 53, 8260, 56, 55, + 8260, 56, 49, 8260, 8560, 73, 73, 8561, + 73, 73, 73, 8562, 73, 86, 8563, 86, + 8564, 86, 73, 8565, 86, 73, 73, 8566, + 3, 86, 73, 73, 73, 8567, 73, 88, + 8568, 88, 8569, 88, 73, 8570, 88, 73, + 73, 8571, 8572, 8573, 8574, 8575, 105, 105, + 105, 105, 105, 105, 118, 118, 105, 118, + 105, 105, 3, 118, 105, 105, 105, 105, + 120, 120, 105, 120, 105, 105, 8580, 48, + 8260, 51, 8592, 824, 8594, 824, 8596, 824, + 8656, 824, 8660, 824, 8658, 824, 8707, 824, + 8712, 824, 8715, 824, 8739, 824, 8741, 824, + 8747, 8747, 8747, 8747, 8747, 8750, 8750, 8750, + 8750, 8750, 8764, 824, 8771, 824, 8773, 824, + 8776, 824, 61, 824, 8801, 824, 8781, 824, + 60, 824, 62, 824, 8804, 824, 8805, 824, + 8818, 824, 8819, 824, 8822, 824, 8823, 824, + 8826, 824, 8827, 824, 8834, 824, 8835, 824, + 8838, 824, 8839, 824, 8866, 824, 8872, 824, + 8873, 824, 8875, 824, 8828, 824, 8829, 824, + 8849, 824, 8850, 824, 8882, 824, 8883, 824, + 8884, 824, 8885, 824, 12296, 12297, 49, 48, + 49, 49, 49, 50, 49, 51, 49, 52, + 49, 53, 49, 54, 49, 55, 49, 56, + 49, 57, 50, 48, 40, 49, 41, 40, + 50, 41, 40, 51, 41, 40, 52, 41, + 40, 53, 41, 40, 54, 41, 40, 55, + 41, 40, 56, 41, 40, 57, 41, 3, + 40, 49, 48, 41, 3, 40, 49, 49, + 41, 3, 40, 49, 50, 41, 3, 40, + 49, 51, 41, 3, 40, 49, 52, 41, + 3, 40, 49, 53, 41, 3, 40, 49, + 54, 41, 3, 40, 49, 55, 41, 3, + 40, 49, 56, 41, 3, 40, 49, 57, + 41, 3, 40, 50, 48, 41, 49, 46, + 50, 46, 51, 46, 52, 46, 53, 46, + 54, 46, 55, 46, 56, 46, 57, 46, + 49, 48, 46, 49, 49, 46, 49, 50, + 46, 49, 51, 46, 49, 52, 46, 49, + 53, 46, 49, 54, 46, 49, 55, 46, + 49, 56, 46, 49, 57, 46, 50, 48, + 46, 40, 97, 41, 40, 98, 41, 40, + 99, 41, 40, 100, 41, 40, 101, 41, + 40, 102, 41, 40, 103, 41, 40, 104, + 41, 40, 105, 41, 40, 106, 41, 40, + 107, 41, 40, 108, 41, 40, 109, 41, + 40, 110, 41, 40, 111, 41, 40, 112, + 41, 40, 113, 41, 40, 114, 41, 40, + 115, 41, 40, 116, 41, 40, 117, 41, + 40, 118, 41, 40, 119, 41, 40, 120, + 41, 40, 121, 41, 40, 122, 41, 9424, + 9425, 9426, 9427, 9428, 9429, 9430, 9431, 9432, + 9433, 9434, 9435, 9436, 9437, 9438, 9439, 9440, + 9441, 83, 9442, 9443, 9444, 9445, 9446, 9447, + 89, 9448, 9449, 3, 8747, 8747, 8747, 8747, + 58, 58, 61, 61, 61, 61, 61, 61, + 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, + 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, + 11326, 11327, 11328, 11329, 11330, 11331, 11332, 11333, + 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, + 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, + 11350, 11351, 11352, 11353, 11354, 11355, 11356, 11357, + 11358, 11359, 11361, 619, 7549, 637, 11368, 11370, + 11372, 11379, 11382, 575, 576, 11393, 11395, 11397, + 11399, 11401, 11403, 11405, 11407, 11409, 11411, 11413, + 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, + 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, + 11447, 11449, 11451, 11453, 11455, 11457, 11459, 11461, + 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, + 11479, 11481, 11483, 11485, 11487, 11489, 11491, 11500, + 11502, 11507, 11617, 27597, 40863, 19968, 20008, 20022, + 20031, 20057, 20101, 20108, 20128, 20154, 20799, 20837, + 20843, 20866, 20886, 20907, 20960, 20981, 20992, 21147, + 21241, 21269, 21274, 21304, 21313, 21340, 21353, 21378, + 21430, 21448, 21475, 22231, 22303, 22763, 22786, 22794, + 22805, 22823, 22899, 23376, 23424, 23544, 23567, 23586, + 23608, 23662, 23665, 24027, 24037, 24049, 24062, 24178, + 24186, 24191, 24308, 24318, 24331, 24339, 24400, 24417, + 24435, 24515, 25096, 25142, 25163, 25903, 25908, 25991, + 26007, 26020, 26041, 26080, 26085, 26352, 26376, 26408, + 27424, 27490, 27513, 27571, 27595, 27604, 27611, 27663, + 27668, 27700, 28779, 29226, 29238, 29243, 29247, 29255, + 29273, 29275, 29356, 29572, 29577, 29916, 29926, 29976, + 29983, 29992, 30000, 30091, 30098, 30326, 30333, 30382, + 30399, 30446, 30683, 30690, 30707, 31034, 31160, 31166, + 31348, 31435, 31481, 31859, 31992, 32566, 32593, 32650, + 32701, 32769, 32780, 32786, 32819, 32895, 32905, 33251, + 33258, 33267, 33276, 33292, 33307, 33311, 33390, 33394, + 33400, 34381, 34411, 34880, 34892, 34915, 35198, 35211, + 35282, 35328, 35895, 35910, 35925, 35960, 35997, 36196, + 36208, 36275, 36523, 36554, 36763, 36784, 36789, 37009, + 37193, 37318, 37324, 37329, 38263, 38272, 38428, 38582, + 38585, 38632, 38737, 38750, 38754, 38761, 38859, 38893, + 38899, 38913, 39080, 39131, 39135, 39318, 39321, 39340, + 39592, 39640, 39647, 39717, 39727, 39730, 39740, 39770, + 40165, 40565, 40575, 40613, 40635, 40643, 40653, 40657, + 40697, 40701, 40718, 40723, 40736, 40763, 40778, 40786, + 40845, 40860, 40864, 12306, 21316, 21317, 12363, 12441, + 12365, 12441, 12367, 12441, 12369, 12441, 12371, 12441, + 12373, 12441, 12375, 12441, 12377, 12441, 12379, 12441, + 12381, 12441, 12383, 12441, 12385, 12441, 12388, 12441, + 12390, 12441, 12392, 12441, 12399, 12441, 12399, 12442, + 12402, 12441, 12402, 12442, 12405, 12441, 12405, 12442, + 12408, 12441, 12408, 12442, 12411, 12441, 12411, 12442, + 12358, 12441, 32, 12441, 32, 12442, 12445, 12441, + 12424, 12426, 12459, 12441, 12461, 12441, 12463, 12441, + 12465, 12441, 12467, 12441, 12469, 12441, 12471, 12441, + 12473, 12441, 12475, 12441, 12477, 12441, 12479, 12441, + 12481, 12441, 12484, 12441, 12486, 12441, 12488, 12441, + 12495, 12441, 12495, 12442, 12498, 12441, 12498, 12442, + 12501, 12441, 12501, 12442, 12504, 12441, 12504, 12442, + 12507, 12441, 12507, 12442, 12454, 12441, 12527, 12441, + 12528, 12441, 12529, 12441, 12530, 12441, 12541, 12441, + 12467, 12488, 4352, 4353, 4522, 4354, 4524, 4525, + 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, + 4533, 4378, 4358, 4359, 4360, 4385, 4361, 4362, + 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, + 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, + 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, + 4465, 4466, 4467, 4468, 4469, 4448, 4372, 4373, + 4551, 4552, 4556, 4558, 4563, 4567, 4569, 4380, + 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, + 4393, 4395, 4396, 4397, 4398, 4399, 4402, 4406, + 4416, 4423, 4428, 4593, 4594, 4439, 4440, 4441, + 4484, 4485, 4488, 4497, 4498, 4500, 4510, 4513, + 19977, 22235, 19978, 20013, 19979, 30002, 19993, 19969, + 22825, 22320, 40, 4352, 41, 40, 4354, 41, + 40, 4355, 41, 40, 4357, 41, 40, 4358, + 41, 40, 4359, 41, 40, 4361, 41, 40, + 4363, 41, 40, 4364, 41, 40, 4366, 41, + 40, 4367, 41, 40, 4368, 41, 40, 4369, + 41, 40, 4370, 41, 3, 40, 4352, 4449, + 41, 3, 40, 4354, 4449, 41, 3, 40, + 4355, 4449, 41, 3, 40, 4357, 4449, 41, + 3, 40, 4358, 4449, 41, 3, 40, 4359, + 4449, 41, 3, 40, 4361, 4449, 41, 3, + 40, 4363, 4449, 41, 3, 40, 4364, 4449, + 41, 3, 40, 4366, 4449, 41, 3, 40, + 4367, 4449, 41, 3, 40, 4368, 4449, 41, + 3, 40, 4369, 4449, 41, 3, 40, 4370, + 4449, 41, 3, 40, 4364, 4462, 41, 6, + 40, 4363, 4457, 4364, 4453, 4523, 41, 5, + 40, 4363, 4457, 4370, 4462, 41, 40, 19968, + 41, 40, 20108, 41, 40, 19977, 41, 40, + 22235, 41, 40, 20116, 41, 40, 20845, 41, + 40, 19971, 41, 40, 20843, 41, 40, 20061, + 41, 40, 21313, 41, 40, 26376, 41, 40, + 28779, 41, 40, 27700, 41, 40, 26408, 41, + 40, 37329, 41, 40, 22303, 41, 40, 26085, + 41, 40, 26666, 41, 40, 26377, 41, 40, + 31038, 41, 40, 21517, 41, 40, 29305, 41, + 40, 36001, 41, 40, 31069, 41, 40, 21172, + 41, 40, 20195, 41, 40, 21628, 41, 40, + 23398, 41, 40, 30435, 41, 40, 20225, 41, + 40, 36039, 41, 40, 21332, 41, 40, 31085, + 41, 40, 20241, 41, 40, 33258, 41, 40, + 33267, 41, 21839, 24188, 31631, 80, 84, 69, + 50, 49, 50, 50, 50, 51, 50, 52, + 50, 53, 50, 54, 50, 55, 50, 56, + 50, 57, 51, 48, 51, 49, 51, 50, + 51, 51, 51, 52, 51, 53, 4352, 4449, + 4354, 4449, 4355, 4449, 4357, 4449, 4358, 4449, + 4359, 4449, 4361, 4449, 4363, 4449, 4364, 4449, + 4366, 4449, 4367, 4449, 4368, 4449, 4369, 4449, + 4370, 4449, 4, 4366, 4449, 4535, 4352, 4457, + 3, 4364, 4462, 4363, 4468, 4363, 4462, 20116, + 20845, 19971, 20061, 26666, 26377, 31038, 21517, 29305, + 36001, 31069, 21172, 31192, 30007, 36969, 20778, 21360, + 27880, 38917, 20241, 20889, 27491, 24038, 21491, 21307, + 23447, 23398, 30435, 20225, 36039, 21332, 22812, 51, + 54, 51, 55, 51, 56, 51, 57, 52, + 48, 52, 49, 52, 50, 52, 51, 52, + 52, 52, 53, 52, 54, 52, 55, 52, + 56, 52, 57, 53, 48, 49, 26376, 50, + 26376, 51, 26376, 52, 26376, 53, 26376, 54, + 26376, 55, 26376, 56, 26376, 57, 26376, 49, + 48, 26376, 49, 49, 26376, 49, 50, 26376, + 72, 103, 101, 114, 103, 101, 86, 76, + 84, 68, 12450, 12452, 12454, 12456, 12458, 12459, + 12461, 12463, 12465, 12467, 12469, 12471, 12473, 12475, + 12477, 12479, 12481, 12484, 12486, 12488, 12490, 12491, + 12492, 12493, 12494, 12495, 12498, 12501, 12504, 12507, + 12510, 12511, 12512, 12513, 12514, 12516, 12518, 12520, + 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, + 12530, 20196, 21644, 3, 12450, 12497, 12540, 12488, + 3, 12450, 12523, 12501, 12449, 3, 12450, 12531, + 12506, 12450, 12450, 12540, 12523, 3, 12452, 12491, + 12531, 12464, 12452, 12531, 12481, 12454, 12457, 12531, + 4, 12456, 12473, 12463, 12540, 12489, 3, 12456, + 12540, 12459, 12540, 12458, 12531, 12473, 12458, 12540, + 12512, 12459, 12452, 12522, 3, 12459, 12521, 12483, + 12488, 3, 12459, 12525, 12522, 12540, 12460, 12525, + 12531, 12460, 12531, 12510, 12462, 12460, 12462, 12491, + 12540, 3, 12461, 12517, 12522, 12540, 3, 12462, + 12523, 12480, 12540, 12461, 12525, 4, 12461, 12525, + 12464, 12521, 12512, 5, 12461, 12525, 12513, 12540, + 12488, 12523, 4, 12461, 12525, 12527, 12483, 12488, + 12464, 12521, 12512, 4, 12464, 12521, 12512, 12488, + 12531, 4, 12463, 12523, 12476, 12452, 12525, 3, + 12463, 12525, 12540, 12493, 12465, 12540, 12473, 12467, + 12523, 12490, 12467, 12540, 12509, 3, 12469, 12452, + 12463, 12523, 4, 12469, 12531, 12481, 12540, 12512, + 3, 12471, 12522, 12531, 12464, 12475, 12531, 12481, + 12475, 12531, 12488, 12480, 12540, 12473, 12487, 12471, + 12489, 12523, 12488, 12531, 12490, 12494, 12494, 12483, + 12488, 12495, 12452, 12484, 4, 12497, 12540, 12475, + 12531, 12488, 12497, 12540, 12484, 3, 12496, 12540, + 12524, 12523, 4, 12500, 12450, 12473, 12488, 12523, + 12500, 12463, 12523, 12500, 12467, 12499, 12523, 4, + 12501, 12449, 12521, 12483, 12489, 3, 12501, 12451, + 12540, 12488, 4, 12502, 12483, 12471, 12455, 12523, + 12501, 12521, 12531, 4, 12504, 12463, 12479, 12540, + 12523, 12506, 12477, 12506, 12491, 12498, 12504, 12523, + 12484, 12506, 12531, 12473, 12506, 12540, 12472, 12505, + 12540, 12479, 3, 12509, 12452, 12531, 12488, 12508, + 12523, 12488, 12507, 12531, 12509, 12531, 12489, 12507, + 12540, 12523, 12507, 12540, 12531, 3, 12510, 12452, + 12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, + 12510, 12523, 12463, 4, 12510, 12531, 12471, 12519, + 12531, 3, 12511, 12463, 12525, 12531, 12511, 12522, + 4, 12511, 12522, 12496, 12540, 12523, 12513, 12460, + 3, 12513, 12460, 12488, 12531, 3, 12513, 12540, + 12488, 12523, 12516, 12540, 12489, 12516, 12540, 12523, + 12518, 12450, 12531, 3, 12522, 12483, 12488, 12523, + 12522, 12521, 12523, 12500, 12540, 3, 12523, 12540, + 12502, 12523, 12524, 12512, 4, 12524, 12531, 12488, + 12466, 12531, 12527, 12483, 12488, 48, 28857, 49, + 28857, 50, 28857, 51, 28857, 52, 28857, 53, + 28857, 54, 28857, 55, 28857, 56, 28857, 57, + 28857, 49, 48, 28857, 49, 49, 28857, 49, + 50, 28857, 49, 51, 28857, 49, 52, 28857, + 49, 53, 28857, 49, 54, 28857, 49, 55, + 28857, 49, 56, 28857, 49, 57, 28857, 50, + 48, 28857, 50, 49, 28857, 50, 50, 28857, + 50, 51, 28857, 50, 52, 28857, 104, 80, + 97, 100, 97, 65, 85, 98, 97, 114, + 111, 86, 112, 99, 100, 109, 100, 109, + 178, 100, 109, 179, 73, 85, 24179, 25104, + 26157, 21644, 22823, 27491, 26126, 27835, 3, 26666, + 24335, 20250, 31038, 112, 65, 110, 65, 956, + 65, 109, 65, 107, 65, 75, 66, 77, + 66, 71, 66, 99, 97, 108, 3, 107, + 99, 97, 108, 112, 70, 110, 70, 956, + 70, 956, 103, 109, 103, 107, 103, 72, + 122, 107, 72, 122, 77, 72, 122, 71, + 72, 122, 84, 72, 122, 956, 8467, 109, + 8467, 100, 8467, 107, 8467, 102, 109, 110, + 109, 956, 109, 109, 109, 99, 109, 107, + 109, 109, 109, 178, 99, 109, 178, 109, + 178, 107, 109, 178, 109, 109, 179, 99, + 109, 179, 109, 179, 107, 109, 179, 109, + 8725, 115, 3, 109, 8725, 115, 178, 80, + 97, 107, 80, 97, 77, 80, 97, 71, + 80, 97, 114, 97, 100, 4, 114, 97, + 100, 8725, 115, 5, 114, 97, 100, 8725, + 115, 178, 112, 115, 110, 115, 956, 115, + 109, 115, 112, 86, 110, 86, 956, 86, + 109, 86, 107, 86, 77, 86, 112, 87, + 110, 87, 956, 87, 109, 87, 107, 87, + 77, 87, 107, 937, 77, 937, 3, 97, + 46, 109, 46, 66, 113, 99, 99, 99, + 100, 3, 67, 8725, 107, 103, 67, 111, + 46, 100, 66, 71, 121, 104, 97, 72, + 80, 105, 110, 75, 75, 75, 77, 107, + 116, 108, 109, 108, 110, 108, 111, 103, + 108, 120, 109, 98, 109, 105, 108, 109, + 111, 108, 80, 72, 3, 112, 46, 109, + 46, 80, 80, 77, 80, 82, 115, 114, + 83, 118, 87, 98, 86, 8725, 109, 65, + 8725, 109, 49, 26085, 50, 26085, 51, 26085, + 52, 26085, 53, 26085, 54, 26085, 55, 26085, + 56, 26085, 57, 26085, 49, 48, 26085, 49, + 49, 26085, 49, 50, 26085, 49, 51, 26085, + 49, 52, 26085, 49, 53, 26085, 49, 54, + 26085, 49, 55, 26085, 49, 56, 26085, 49, + 57, 26085, 50, 48, 26085, 50, 49, 26085, + 50, 50, 26085, 50, 51, 26085, 50, 52, + 26085, 50, 53, 26085, 50, 54, 26085, 50, + 55, 26085, 50, 56, 26085, 50, 57, 26085, + 51, 48, 26085, 51, 49, 26085, 103, 97, + 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575, + 42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, + 42593, 42595, 42597, 42599, 42601, 42603, 42605, 42625, + 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641, + 42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, + 42793, 42795, 42797, 42799, 42803, 42805, 42807, 42809, + 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825, + 42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, + 42843, 42845, 42847, 42849, 42851, 42853, 42855, 42857, + 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881, + 42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, + 42907, 42909, 42911, 42913, 42915, 42917, 42919, 42921, + 620, 670, 647, 43859, 42933, 42935, 42937, 42939, + 42941, 42943, 42945, 42947, 42900, 7566, 42952, 42954, + 42961, 42967, 42969, 42998, 294, 43831, 43858, 653, + 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, + 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, + 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, + 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, + 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, + 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, + 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, + 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, + 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, + 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, + 35912, 26356, 36040, 28369, 20018, 21477, 22865, 21895, + 22856, 25078, 30313, 32645, 34367, 34746, 35064, 37007, + 27138, 27931, 28889, 29662, 33853, 37226, 39409, 20098, + 21365, 27396, 29211, 34349, 40478, 23888, 28651, 34253, + 35172, 25289, 33240, 34847, 24266, 26391, 28010, 29436, + 37070, 20358, 20919, 21214, 25796, 27347, 29200, 30439, + 34310, 34396, 36335, 38706, 39791, 40442, 30860, 31103, + 32160, 33737, 37636, 35542, 22751, 24324, 31840, 32894, + 29282, 30922, 36034, 38647, 22744, 23650, 27155, 28122, + 28431, 32047, 32311, 38475, 21202, 32907, 20956, 20940, + 31260, 32190, 33777, 38517, 35712, 25295, 35582, 20025, + 23527, 24594, 29575, 30064, 21271, 30971, 20415, 24489, + 19981, 27852, 25976, 32034, 21443, 22622, 30465, 33865, + 35498, 27578, 27784, 25342, 33509, 25504, 30053, 20142, + 20841, 20937, 26753, 31975, 33391, 35538, 37327, 21237, + 21570, 24300, 26053, 28670, 31018, 38317, 39530, 40599, + 40654, 26310, 27511, 36706, 24180, 24976, 25088, 25754, + 28451, 29001, 29833, 31178, 32244, 32879, 36646, 34030, + 36899, 37706, 21015, 21155, 21693, 28872, 35010, 24265, + 24565, 25467, 27566, 31806, 29557, 20196, 22265, 23994, + 24604, 29618, 29801, 32666, 32838, 37428, 38646, 38728, + 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698, + 23534, 23615, 26009, 29134, 30274, 34044, 36988, 26248, + 38446, 21129, 26491, 26611, 27969, 28316, 29705, 30041, + 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138, + 36650, 24459, 24900, 26647, 38534, 21033, 21519, 23653, + 26131, 26446, 26792, 27877, 29702, 30178, 32633, 35023, + 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298, + 38563, 40023, 40607, 26519, 28107, 33256, 31520, 31890, + 29376, 28825, 35672, 20160, 33590, 21050, 20999, 24230, + 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275, + 20800, 21952, 22618, 26228, 20958, 29482, 30410, 31036, + 31070, 31077, 31119, 38742, 31934, 34322, 35576, 36920, + 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398, + 20711, 20813, 21193, 21220, 21329, 21917, 22022, 22120, + 22592, 22696, 23652, 24724, 24936, 24974, 25074, 25935, + 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227, + 29730, 30865, 31049, 31048, 31056, 31062, 31117, 31118, + 31296, 31361, 31680, 32265, 32321, 32626, 32773, 33261, + 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104, + 36790, 38627, 38911, 38971, 24693, 55376, 57070, 33304, + 20006, 20917, 20840, 20352, 20805, 20864, 21191, 21242, + 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, + 24274, 24281, 24425, 24493, 24792, 24910, 24840, 24928, + 25140, 25540, 25628, 25682, 25942, 26395, 26454, 28379, + 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, + 30237, 30239, 30427, 30452, 30538, 30528, 30924, 31409, + 31867, 32091, 32574, 33618, 33775, 34681, 35137, 35206, + 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, + 38524, 38875, 38923, 39698, 55370, 56394, 55370, 56388, + 55372, 57301, 15261, 16408, 16441, 55380, 56905, 55383, + 56528, 55391, 57043, 40771, 40846, 102, 102, 102, + 105, 102, 108, 102, 102, 105, 102, 102, + 108, 383, 116, 115, 116, 1396, 1398, 1396, + 1381, 1396, 1387, 1406, 1398, 1396, 1389, 1497, + 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501, + 1512, 1514, 1513, 1473, 1513, 1474, 64329, 1473, + 64329, 1474, 1488, 1463, 1488, 1464, 1488, 1468, + 1489, 1468, 1490, 1468, 1491, 1468, 1492, 1468, + 1493, 1468, 1494, 1468, 1496, 1468, 1497, 1468, + 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468, + 1504, 1468, 1505, 1468, 1507, 1468, 1508, 1468, + 1510, 1468, 1511, 1468, 1512, 1468, 1513, 1468, + 1514, 1468, 1493, 1465, 1489, 1471, 1499, 1471, + 1508, 1471, 1488, 1500, 1649, 1659, 1662, 1664, + 1658, 1663, 1657, 1700, 1702, 1668, 1667, 1670, + 1671, 1677, 1676, 1678, 1672, 1688, 1681, 1705, + 1711, 1715, 1713, 1722, 1723, 1728, 1729, 1726, + 1746, 1747, 1709, 1735, 1734, 1736, 1655, 1739, + 1733, 1737, 1744, 1609, 1574, 1575, 1574, 1749, + 1574, 1608, 1574, 1735, 1574, 1734, 1574, 1736, + 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574, + 1581, 1574, 1605, 1574, 1610, 1576, 1580, 1576, + 1581, 1576, 1582, 1576, 1605, 1576, 1609, 1576, + 1610, 1578, 1580, 1578, 1581, 1578, 1582, 1578, + 1605, 1578, 1609, 1578, 1610, 1579, 1580, 1579, + 1605, 1579, 1609, 1579, 1610, 1580, 1581, 1580, + 1605, 1581, 1580, 1581, 1605, 1582, 1580, 1582, + 1581, 1582, 1605, 1587, 1580, 1587, 1581, 1587, + 1582, 1587, 1605, 1589, 1581, 1589, 1605, 1590, + 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591, + 1581, 1591, 1605, 1592, 1605, 1593, 1580, 1593, + 1605, 1594, 1580, 1594, 1605, 1601, 1580, 1601, + 1581, 1601, 1582, 1601, 1605, 1601, 1609, 1601, + 1610, 1602, 1581, 1602, 1605, 1602, 1609, 1602, + 1610, 1603, 1575, 1603, 1580, 1603, 1581, 1603, + 1582, 1603, 1604, 1603, 1605, 1603, 1609, 1603, + 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604, + 1605, 1604, 1609, 1604, 1610, 1605, 1580, 1605, + 1581, 1605, 1582, 1605, 1605, 1605, 1609, 1605, + 1610, 1606, 1580, 1606, 1581, 1606, 1582, 1606, + 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607, + 1605, 1607, 1609, 1607, 1610, 1610, 1580, 1610, + 1581, 1610, 1582, 1610, 1605, 1610, 1609, 1610, + 1610, 1584, 1648, 1585, 1648, 1609, 1648, 32, + 1612, 1617, 32, 1613, 1617, 32, 1614, 1617, + 32, 1615, 1617, 32, 1616, 1617, 32, 1617, + 1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, + 1585, 1576, 1586, 1576, 1606, 1578, 1585, 1578, + 1586, 1578, 1606, 1579, 1585, 1579, 1586, 1579, + 1606, 1605, 1575, 1606, 1585, 1606, 1586, 1606, + 1606, 1610, 1585, 1610, 1586, 1610, 1606, 1574, + 1582, 1574, 1607, 1576, 1607, 1578, 1607, 1589, + 1582, 1604, 1607, 1606, 1607, 1607, 1648, 1610, + 1607, 1579, 1607, 1587, 1607, 1588, 1605, 1588, + 1607, 1600, 1614, 1617, 1600, 1615, 1617, 1600, + 1616, 1617, 1591, 1609, 1591, 1610, 1593, 1609, + 1593, 1610, 1594, 1609, 1594, 1610, 1587, 1609, + 1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, + 1581, 1610, 1580, 1609, 1580, 1610, 1582, 1609, + 1582, 1610, 1589, 1609, 1589, 1610, 1590, 1609, + 1590, 1610, 1588, 1580, 1588, 1581, 1588, 1582, + 1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, + 1575, 1611, 1578, 1580, 1605, 1578, 1581, 1580, + 1578, 1581, 1605, 1578, 1582, 1605, 1578, 1605, + 1580, 1578, 1605, 1581, 1578, 1605, 1582, 1580, + 1605, 1581, 1581, 1605, 1610, 1581, 1605, 1609, + 1587, 1581, 1580, 1587, 1580, 1581, 1587, 1580, + 1609, 1587, 1605, 1581, 1587, 1605, 1580, 1587, + 1605, 1605, 1589, 1581, 1581, 1589, 1605, 1605, + 1588, 1581, 1605, 1588, 1580, 1610, 1588, 1605, + 1582, 1588, 1605, 1605, 1590, 1581, 1609, 1590, + 1582, 1605, 1591, 1605, 1581, 1591, 1605, 1605, + 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605, + 1605, 1593, 1605, 1609, 1594, 1605, 1605, 1594, + 1605, 1610, 1594, 1605, 1609, 1601, 1582, 1605, + 1602, 1605, 1581, 1602, 1605, 1605, 1604, 1581, + 1605, 1604, 1581, 1610, 1604, 1581, 1609, 1604, + 1580, 1580, 1604, 1582, 1605, 1604, 1605, 1581, + 1605, 1581, 1580, 1605, 1581, 1605, 1605, 1581, + 1610, 1605, 1580, 1581, 1605, 1580, 1605, 1605, + 1582, 1580, 1605, 1582, 1605, 1605, 1580, 1582, + 1607, 1605, 1580, 1607, 1605, 1605, 1606, 1581, + 1605, 1606, 1581, 1609, 1606, 1580, 1605, 1606, + 1580, 1609, 1606, 1605, 1610, 1606, 1605, 1609, + 1610, 1605, 1605, 1576, 1582, 1610, 1578, 1580, + 1610, 1578, 1580, 1609, 1578, 1582, 1610, 1578, + 1582, 1609, 1578, 1605, 1610, 1578, 1605, 1609, + 1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, + 1609, 1587, 1582, 1609, 1589, 1581, 1610, 1588, + 1581, 1610, 1590, 1581, 1610, 1604, 1580, 1610, + 1604, 1605, 1610, 1610, 1581, 1610, 1610, 1580, + 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602, + 1605, 1610, 1606, 1581, 1610, 1593, 1605, 1610, + 1603, 1605, 1610, 1606, 1580, 1581, 1605, 1582, + 1610, 1604, 1580, 1605, 1603, 1605, 1605, 1580, + 1581, 1610, 1581, 1580, 1610, 1605, 1580, 1610, + 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582, + 1610, 1606, 1580, 1610, 1589, 1604, 1746, 1602, + 1604, 1746, 3, 1575, 1604, 1604, 1607, 3, + 1575, 1603, 1576, 1585, 3, 1605, 1581, 1605, + 1583, 3, 1589, 1604, 1593, 1605, 3, 1585, + 1587, 1608, 1604, 3, 1593, 1604, 1610, 1607, + 3, 1608, 1587, 1604, 1605, 1589, 1604, 1609, + 17, 1589, 1604, 1609, 32, 1575, 1604, 1604, + 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, + 1587, 1604, 1605, 7, 1580, 1604, 32, 1580, + 1604, 1575, 1604, 1607, 3, 1585, 1740, 1575, + 1604, 44, 12289, 12290, 58, 33, 63, 12310, + 12311, 8230, 8229, 8212, 8211, 95, 123, 125, + 12308, 12309, 12304, 12305, 12298, 12299, 12300, 12301, + 12302, 12303, 91, 93, 8254, 35, 38, 42, + 45, 60, 62, 92, 36, 37, 64, 32, + 1611, 1600, 1611, 32, 1612, 32, 1613, 32, + 1614, 1600, 1614, 32, 1615, 1600, 1615, 32, + 1616, 1600, 1616, 32, 1617, 1600, 1617, 32, + 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573, + 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, + 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, + 1590, 1591, 1592, 1593, 1594, 1601, 1602, 1603, + 1604, 1605, 1606, 1607, 1608, 1610, 1604, 1570, + 1604, 1571, 1604, 1573, 1604, 1575, 34, 39, + 47, 65345, 65346, 65347, 65348, 65349, 65350, 65351, + 65352, 65353, 65354, 65355, 65356, 65357, 65358, 65359, + 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, + 65368, 65369, 65370, 94, 124, 126, 10629, 10630, + 12539, 12449, 12451, 12453, 12455, 12457, 12515, 12517, + 12519, 12483, 12540, 12531, 12441, 12442, 12644, 12593, + 12594, 12595, 12596, 12597, 12598, 12599, 12600, 12601, + 12602, 12603, 12604, 12605, 12606, 12607, 12608, 12609, + 12610, 12611, 12612, 12613, 12614, 12615, 12616, 12617, + 12618, 12619, 12620, 12621, 12622, 12623, 12624, 12625, + 12626, 12627, 12628, 12629, 12630, 12631, 12632, 12633, + 12634, 12635, 12636, 12637, 12638, 12639, 12640, 12641, + 12642, 12643, 162, 163, 172, 175, 166, 165, + 8361, 9474, 8592, 8593, 8594, 8595, 9632, 9675, + 55297, 56360, 55297, 56361, 55297, 56362, 55297, 56363, + 55297, 56364, 55297, 56365, 55297, 56366, 55297, 56367, + 55297, 56368, 55297, 56369, 55297, 56370, 55297, 56371, + 55297, 56372, 55297, 56373, 55297, 56374, 55297, 56375, + 55297, 56376, 55297, 56377, 55297, 56378, 55297, 56379, + 55297, 56380, 55297, 56381, 55297, 56382, 55297, 56383, + 55297, 56384, 55297, 56385, 55297, 56386, 55297, 56387, + 55297, 56388, 55297, 56389, 55297, 56390, 55297, 56391, + 55297, 56392, 55297, 56393, 55297, 56394, 55297, 56395, + 55297, 56396, 55297, 56397, 55297, 56398, 55297, 56399, + 55297, 56536, 55297, 56537, 55297, 56538, 55297, 56539, + 55297, 56540, 55297, 56541, 55297, 56542, 55297, 56543, + 55297, 56544, 55297, 56545, 55297, 56546, 55297, 56547, + 55297, 56548, 55297, 56549, 55297, 56550, 55297, 56551, + 55297, 56552, 55297, 56553, 55297, 56554, 55297, 56555, + 55297, 56556, 55297, 56557, 55297, 56558, 55297, 56559, + 55297, 56560, 55297, 56561, 55297, 56562, 55297, 56563, + 55297, 56564, 55297, 56565, 55297, 56566, 55297, 56567, + 55297, 56568, 55297, 56569, 55297, 56570, 55297, 56571, + 55297, 56727, 55297, 56728, 55297, 56729, 55297, 56730, + 55297, 56731, 55297, 56732, 55297, 56733, 55297, 56734, + 55297, 56735, 55297, 56736, 55297, 56737, 55297, 56739, + 55297, 56740, 55297, 56741, 55297, 56742, 55297, 56743, + 55297, 56744, 55297, 56745, 55297, 56746, 55297, 56747, + 55297, 56748, 55297, 56749, 55297, 56750, 55297, 56751, + 55297, 56752, 55297, 56753, 55297, 56755, 55297, 56756, + 55297, 56757, 55297, 56758, 55297, 56759, 55297, 56760, + 55297, 56761, 55297, 56763, 55297, 56764, 720, 721, + 665, 675, 43878, 677, 676, 7569, 600, 606, + 681, 612, 610, 667, 668, 615, 644, 682, + 683, 55351, 57092, 42894, 622, 55351, 57093, 654, + 55351, 57094, 630, 631, 634, 55351, 57096, 638, + 680, 678, 43879, 679, 11377, 655, 673, 674, + 664, 448, 449, 450, 55351, 57098, 55351, 57118, + 55299, 56512, 55299, 56513, 55299, 56514, 55299, 56515, + 55299, 56516, 55299, 56517, 55299, 56518, 55299, 56519, + 55299, 56520, 55299, 56521, 55299, 56522, 55299, 56523, + 55299, 56524, 55299, 56525, 55299, 56526, 55299, 56527, + 55299, 56528, 55299, 56529, 55299, 56530, 55299, 56531, + 55299, 56532, 55299, 56533, 55299, 56534, 55299, 56535, + 55299, 56536, 55299, 56537, 55299, 56538, 55299, 56539, + 55299, 56540, 55299, 56541, 55299, 56542, 55299, 56543, + 55299, 56544, 55299, 56545, 55299, 56546, 55299, 56547, + 55299, 56548, 55299, 56549, 55299, 56550, 55299, 56551, + 55299, 56552, 55299, 56553, 55299, 56554, 55299, 56555, + 55299, 56556, 55299, 56557, 55299, 56558, 55299, 56559, + 55299, 56560, 55299, 56561, 55299, 56562, 55300, 56473, + 55300, 56506, 55300, 56475, 55300, 56506, 55300, 56485, + 55300, 56506, 55300, 56625, 55300, 56615, 55300, 56626, + 55300, 56615, 55300, 57159, 55300, 57150, 55300, 57159, + 55300, 57175, 55301, 56505, 55301, 56506, 55301, 56505, + 55301, 56496, 55301, 56505, 55301, 56509, 55301, 56760, + 55301, 56751, 55301, 56761, 55301, 56751, 55302, 56512, + 55302, 56513, 55302, 56514, 55302, 56515, 55302, 56516, + 55302, 56517, 55302, 56518, 55302, 56519, 55302, 56520, + 55302, 56521, 55302, 56522, 55302, 56523, 55302, 56524, + 55302, 56525, 55302, 56526, 55302, 56527, 55302, 56528, + 55302, 56529, 55302, 56530, 55302, 56531, 55302, 56532, + 55302, 56533, 55302, 56534, 55302, 56535, 55302, 56536, + 55302, 56537, 55302, 56538, 55302, 56539, 55302, 56540, + 55302, 56541, 55302, 56542, 55302, 56543, 55302, 56629, + 55302, 56624, 55323, 56928, 55323, 56929, 55323, 56930, + 55323, 56931, 55323, 56932, 55323, 56933, 55323, 56934, + 55323, 56935, 55323, 56936, 55323, 56937, 55323, 56938, + 55323, 56939, 55323, 56940, 55323, 56941, 55323, 56942, + 55323, 56943, 55323, 56944, 55323, 56945, 55323, 56946, + 55323, 56947, 55323, 56948, 55323, 56949, 55323, 56950, + 55323, 56951, 55323, 56952, 55323, 56953, 55323, 56954, + 55323, 56955, 55323, 56956, 55323, 56957, 55323, 56958, + 55323, 56959, 55348, 56663, 55348, 56677, 55348, 56664, + 55348, 56677, 55348, 56671, 55348, 56686, 55348, 56671, + 55348, 56687, 55348, 56671, 55348, 56688, 55348, 56671, + 55348, 56689, 55348, 56671, 55348, 56690, 55348, 56761, + 55348, 56677, 55348, 56762, 55348, 56677, 55348, 56763, + 55348, 56686, 55348, 56764, 55348, 56686, 55348, 56763, + 55348, 56687, 55348, 56764, 55348, 56687, 305, 567, + 913, 914, 916, 917, 918, 919, 921, 922, + 923, 924, 925, 926, 927, 929, 1012, 932, + 934, 935, 936, 8711, 8706, 1013, 977, 1008, + 981, 1009, 982, 988, 55354, 56610, 55354, 56611, + 55354, 56612, 55354, 56613, 55354, 56614, 55354, 56615, + 55354, 56616, 55354, 56617, 55354, 56618, 55354, 56619, + 55354, 56620, 55354, 56621, 55354, 56622, 55354, 56623, + 55354, 56624, 55354, 56625, 55354, 56626, 55354, 56627, + 55354, 56628, 55354, 56629, 55354, 56630, 55354, 56631, + 55354, 56632, 55354, 56633, 55354, 56634, 55354, 56635, + 55354, 56636, 55354, 56637, 55354, 56638, 55354, 56639, + 55354, 56640, 55354, 56641, 55354, 56642, 55354, 56643, + 1646, 1697, 1647, 48, 46, 48, 44, 49, + 44, 50, 44, 51, 44, 52, 44, 53, + 44, 54, 44, 55, 44, 56, 44, 57, + 44, 40, 65, 41, 40, 66, 41, 40, + 67, 41, 40, 68, 41, 40, 69, 41, + 40, 70, 41, 40, 71, 41, 40, 72, + 41, 40, 73, 41, 40, 74, 41, 40, + 75, 41, 40, 76, 41, 40, 77, 41, + 40, 78, 41, 40, 79, 41, 40, 80, + 41, 40, 81, 41, 40, 82, 41, 40, + 83, 41, 40, 84, 41, 40, 85, 41, + 40, 86, 41, 40, 87, 41, 40, 88, + 41, 40, 89, 41, 40, 90, 41, 12308, + 83, 12309, 67, 68, 87, 90, 72, 86, + 83, 68, 83, 83, 80, 80, 86, 87, + 67, 77, 67, 77, 68, 77, 82, 68, + 74, 12411, 12363, 12467, 12467, 23383, 21452, 12487, + 22810, 35299, 20132, 26144, 28961, 21069, 24460, 20877, + 26032, 21021, 32066, 36009, 22768, 21561, 28436, 25237, + 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, + 30003, 21106, 21942, 37197, 12308, 26412, 12309, 12308, + 19977, 12309, 12308, 20108, 12309, 12308, 23433, 12309, + 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, + 12309, 12308, 21213, 12309, 12308, 25943, 12309, 24471, + 21487, 20029, 20024, 20033, 55360, 56610, 20320, 20411, + 20482, 20602, 20633, 20687, 13470, 55361, 56890, 20820, + 20836, 20855, 55361, 56604, 13497, 20839, 55361, 56651, + 20887, 20900, 20172, 20908, 55396, 56799, 20995, 13535, + 21051, 21062, 21111, 13589, 21253, 21254, 21321, 21338, + 21363, 21373, 21375, 55362, 56876, 28784, 21450, 21471, + 55362, 57187, 21483, 21489, 21510, 21662, 21560, 21576, + 21608, 21666, 21750, 21776, 21843, 21859, 21892, 21931, + 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, + 22516, 22541, 22411, 22578, 22577, 22700, 55365, 56548, + 22770, 22775, 22790, 22818, 22882, 55365, 57000, 55365, + 57066, 23020, 23067, 23079, 23000, 23142, 14062, 14076, + 23304, 23358, 55366, 56776, 23491, 23512, 23539, 55366, + 57112, 23551, 23558, 24403, 14209, 23648, 23744, 23693, + 55367, 56804, 23875, 55367, 56806, 23918, 23915, 23932, + 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, + 55368, 56707, 14460, 24240, 24243, 24246, 55400, 57234, + 55368, 57137, 33281, 24354, 14535, 55372, 57016, 55384, + 56794, 24418, 24427, 14563, 24474, 24525, 24535, 24569, + 24705, 14650, 14620, 55369, 57044, 24775, 24904, 24908, + 24954, 25010, 24996, 25007, 25054, 25104, 25115, 25181, + 25265, 25300, 25424, 55370, 57100, 25405, 25340, 25448, + 25475, 25572, 55370, 57329, 25634, 25541, 25513, 14894, + 25705, 25726, 25757, 25719, 14956, 25964, 55372, 56330, + 26083, 26360, 26185, 15129, 15112, 15076, 20882, 20885, + 26368, 26268, 32941, 17369, 26401, 26462, 26451, 55372, + 57283, 15177, 26618, 26501, 26706, 55373, 56429, 26766, + 26655, 26900, 26946, 27043, 27114, 27304, 55373, 56995, + 27355, 15384, 27425, 55374, 56487, 27476, 15438, 27506, + 27551, 27579, 55374, 56973, 55367, 56587, 55374, 57082, + 27726, 55375, 56508, 27839, 27853, 27751, 27926, 27966, + 28009, 28024, 28037, 55375, 56606, 27956, 28207, 28270, + 15667, 28359, 55375, 57041, 28153, 28526, 55375, 57182, + 55375, 57230, 28614, 28729, 28699, 15766, 28746, 28797, + 28791, 28845, 55361, 56613, 28997, 55376, 56931, 29084, + 55376, 57259, 29224, 29264, 55377, 56840, 29312, 29333, + 55377, 57141, 55378, 56340, 29562, 29579, 16044, 29605, + 16056, 29767, 29788, 29829, 29898, 16155, 29988, 55379, + 56374, 30014, 55379, 56466, 55368, 56735, 30224, 55379, + 57249, 55379, 57272, 55380, 56388, 16380, 16392, 55380, + 56563, 55380, 56562, 55380, 56601, 55380, 56627, 30494, + 30495, 30603, 16454, 16534, 55381, 56349, 30798, 16611, + 55381, 56870, 55381, 56986, 55381, 57029, 31211, 16687, + 31306, 31311, 55382, 56700, 55382, 56999, 31470, 16898, + 55382, 57259, 31686, 31689, 16935, 55383, 56448, 31954, + 17056, 31976, 31971, 32000, 55383, 57222, 32099, 17153, + 32199, 32258, 32325, 17204, 55384, 56872, 55384, 56903, + 17241, 55384, 57049, 32634, 55384, 57150, 32661, 32762, + 55385, 56538, 55385, 56611, 32864, 55385, 56744, 32880, + 55372, 57183, 17365, 32946, 33027, 17419, 33086, 23221, + 55385, 57255, 55385, 57269, 55372, 57235, 55372, 57244, + 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457, + 33459, 33469, 33510, 55386, 57148, 33565, 33635, 33709, + 33571, 33725, 33767, 33619, 33738, 33740, 33756, 55387, + 56374, 55387, 56683, 55387, 56533, 17707, 34033, 34035, + 34070, 55388, 57290, 34148, 55387, 57132, 17757, 17761, + 55387, 57265, 55388, 56530, 17771, 34384, 34407, 34409, + 34473, 34440, 34574, 34530, 34600, 34667, 34694, 17879, + 34785, 34817, 17913, 34912, 55389, 56935, 35031, 35038, + 17973, 35066, 13499, 55390, 56494, 55390, 56678, 18110, + 18119, 35488, 55391, 56488, 36011, 36033, 36123, 36215, + 55391, 57135, 55362, 56324, 36299, 36284, 36336, 55362, + 56542, 36564, 55393, 56786, 55393, 56813, 37012, 37105, + 37137, 55393, 57134, 37147, 37432, 37591, 37592, 37500, + 37881, 37909, 55394, 57338, 38283, 18837, 38327, 55395, + 56695, 18918, 38595, 23986, 38691, 55396, 56645, 55396, + 56858, 19054, 19062, 38880, 55397, 56330, 19122, 55397, + 56470, 38953, 55397, 56758, 39138, 19251, 39209, 39335, + 39362, 39422, 19406, 55398, 57136, 40000, 40189, 19662, + 19693, 40295, 55400, 56526, 19704, 55400, 56581, 55400, + 56846, 55400, 56977, 19798, 40702, 40709, 40719, 40726, + 55401, 56832, 170, 186, 7838, 192, 193, 194, + 195, 196, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 216, 217, 218, 219, 220, 221, + 222, 376, 256, 258, 260, 262, 264, 266, + 268, 270, 272, 274, 276, 278, 280, 282, + 284, 286, 288, 290, 292, 296, 298, 300, + 302, 306, 308, 310, 312, 313, 315, 317, + 319, 321, 323, 325, 327, 329, 330, 332, + 334, 336, 338, 340, 342, 344, 346, 348, + 350, 352, 354, 356, 358, 360, 362, 364, + 366, 368, 370, 372, 374, 377, 379, 381, + 579, 386, 388, 391, 395, 397, 401, 502, + 408, 573, 411, 544, 416, 418, 420, 423, + 426, 428, 431, 435, 437, 440, 442, 444, + 446, 503, 453, 452, 456, 455, 459, 458, + 461, 463, 465, 467, 469, 471, 473, 475, + 478, 480, 482, 484, 486, 488, 490, 492, + 494, 496, 498, 497, 500, 504, 506, 508, + 510, 512, 514, 516, 518, 520, 522, 524, + 526, 528, 530, 532, 534, 536, 538, 540, + 542, 545, 548, 550, 552, 554, 556, 558, + 560, 562, 564, 565, 566, 568, 569, 571, + 11390, 11391, 577, 582, 584, 586, 588, 590, + 11375, 11373, 11376, 385, 390, 393, 394, 399, + 602, 42923, 605, 403, 42924, 404, 42893, 42922, + 407, 406, 42926, 11362, 42925, 412, 11374, 413, + 415, 636, 11364, 639, 422, 42949, 425, 645, + 646, 42929, 430, 580, 433, 434, 581, 439, + 659, 662, 663, 666, 42930, 42928, 672, 684, + 685, 686, 687, 688, 689, 690, 691, 692, + 693, 694, 695, 696, 704, 705, 736, 737, + 738, 739, 740, 880, 882, 886, 890, 1021, + 1022, 1023, 938, 939, 978, 979, 980, 975, + 984, 986, 990, 992, 994, 996, 998, 1000, + 1002, 1004, 1006, 1017, 895, 1015, 1018, 1020, + 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, + 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, + 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, + 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, + 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, + 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, + 1120, 1122, 1124, 1126, 1128, 1130, 1132, 1134, + 1136, 1138, 1140, 1142, 1144, 1146, 1148, 1150, + 1152, 1162, 1164, 1166, 1168, 1170, 1172, 1174, + 1176, 1178, 1180, 1182, 1184, 1186, 1188, 1190, + 1192, 1194, 1196, 1198, 1200, 1202, 1204, 1206, + 1208, 1210, 1212, 1214, 1217, 1219, 1221, 1223, + 1225, 1227, 1229, 1216, 1232, 1234, 1236, 1238, + 1240, 1242, 1244, 1246, 1248, 1250, 1252, 1254, + 1256, 1258, 1260, 1262, 1264, 1266, 1268, 1270, + 1272, 1274, 1276, 1278, 1280, 1282, 1284, 1286, + 1288, 1290, 1292, 1294, 1296, 1298, 1300, 1302, + 1304, 1306, 1308, 1310, 1312, 1314, 1316, 1318, + 1320, 1322, 1324, 1326, 1376, 1329, 1330, 1331, + 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, + 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, + 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, + 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, + 1364, 1365, 1366, 1415, 1416, 7312, 7313, 7314, + 7315, 7316, 7317, 7318, 7319, 7320, 7321, 7322, + 7323, 7324, 7325, 7326, 7327, 7328, 7329, 7330, + 7331, 7332, 7333, 7334, 7335, 7336, 7337, 7338, + 7339, 7340, 7341, 7342, 7343, 7344, 7345, 7346, + 7347, 7348, 7349, 7350, 7351, 7352, 7353, 7354, + 4348, 7357, 7358, 7359, 43888, 43889, 43890, 43891, + 43892, 43893, 43894, 43895, 43896, 43897, 43898, 43899, + 43900, 43901, 43902, 43903, 43904, 43905, 43906, 43907, + 43908, 43909, 43910, 43911, 43912, 43913, 43914, 43915, + 43916, 43917, 43918, 43919, 43920, 43921, 43922, 43923, + 43924, 43925, 43926, 43927, 43928, 43929, 43930, 43931, + 43932, 43933, 43934, 43935, 43936, 43937, 43938, 43939, + 43940, 43941, 43942, 43943, 43944, 43945, 43946, 43947, + 43948, 43949, 43950, 43951, 43952, 43953, 43954, 43955, + 43956, 43957, 43958, 43959, 43960, 43961, 43962, 43963, + 43964, 43965, 43966, 43967, 5112, 5113, 5114, 5115, + 5116, 5117, 42570, 7424, 7425, 7427, 7428, 7429, + 7430, 7431, 7432, 7433, 7434, 7435, 7436, 7437, + 7438, 7439, 7440, 7441, 7442, 7443, 7444, 7445, + 7448, 7449, 7450, 7451, 7454, 7455, 7456, 7457, + 7458, 7459, 7460, 7462, 7463, 7464, 7465, 7466, + 7467, 7468, 7469, 7470, 7471, 7472, 7473, 7474, + 7475, 7476, 7477, 7478, 7479, 7480, 7481, 7482, + 7483, 7484, 7485, 7486, 7487, 7488, 7489, 7490, + 7491, 7492, 7493, 7494, 7495, 7496, 7497, 7498, + 7499, 7500, 7501, 7502, 7503, 7504, 7505, 7506, + 7507, 7508, 7509, 7510, 7511, 7512, 7513, 7514, + 7515, 7516, 7517, 7518, 7519, 7520, 7521, 7522, + 7523, 7524, 7525, 7526, 7527, 7528, 7529, 7530, + 7531, 7532, 7533, 7534, 7535, 7536, 7537, 7538, + 7539, 7540, 7541, 7542, 7543, 7544, 42877, 7546, + 7548, 11363, 7550, 7551, 7552, 7553, 7554, 7555, + 7556, 7558, 7559, 7560, 7561, 7562, 7563, 7564, + 7565, 42950, 7567, 7568, 7570, 7571, 7572, 7573, + 7574, 7575, 7576, 7577, 7578, 7579, 7580, 7581, + 7582, 7583, 7584, 7585, 7586, 7587, 7588, 7589, + 7590, 7591, 7592, 7593, 7594, 7595, 7596, 7597, + 7598, 7599, 7600, 7601, 7602, 7603, 7604, 7605, + 7606, 7607, 7608, 7609, 7610, 7611, 7612, 7613, + 7614, 7615, 7680, 7682, 7684, 7686, 7688, 7690, + 7692, 7694, 7696, 7698, 7700, 7702, 7704, 7706, + 7708, 7710, 7712, 7714, 7716, 7718, 7720, 7722, + 7724, 7726, 7728, 7730, 7732, 7734, 7736, 7738, + 7740, 7742, 7744, 7746, 7748, 7750, 7752, 7754, + 7756, 7758, 7760, 7762, 7764, 7766, 7768, 7770, + 7772, 7774, 7776, 7778, 7780, 7782, 7784, 7786, + 7788, 7790, 7792, 7794, 7796, 7798, 7800, 7802, + 7804, 7806, 7808, 7810, 7812, 7814, 7816, 7818, + 7820, 7822, 7824, 7826, 7828, 7830, 7831, 7832, + 7833, 7834, 7836, 7837, 223, 7839, 7840, 7842, + 7844, 7846, 7848, 7850, 7852, 7854, 7856, 7858, + 7860, 7862, 7864, 7866, 7868, 7870, 7872, 7874, + 7876, 7878, 7880, 7882, 7884, 7886, 7888, 7890, + 7892, 7894, 7896, 7898, 7900, 7902, 7904, 7906, + 7908, 7910, 7912, 7914, 7916, 7918, 7920, 7922, + 7924, 7926, 7928, 7930, 7932, 7934, 7944, 7945, + 7946, 7947, 7948, 7949, 7950, 7951, 7960, 7961, + 7962, 7963, 7964, 7965, 7976, 7977, 7978, 7979, + 7980, 7981, 7982, 7983, 7992, 7993, 7994, 7995, + 7996, 7997, 7998, 7999, 8008, 8009, 8010, 8011, + 8012, 8013, 8016, 8025, 8018, 8027, 8020, 8029, + 8022, 8031, 8040, 8041, 8042, 8043, 8044, 8045, + 8046, 8047, 8122, 8123, 8136, 8137, 8138, 8139, + 8154, 8155, 8184, 8185, 8170, 8171, 8186, 8187, + 8072, 8073, 8074, 8075, 8076, 8077, 8078, 8079, + 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071, + 8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, + 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, + 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, + 8096, 8097, 8098, 8099, 8100, 8101, 8102, 8103, + 8120, 8121, 8114, 8124, 8116, 8118, 8119, 8115, + 8130, 8140, 8132, 8134, 8135, 8131, 8152, 8153, + 8146, 8147, 8150, 8151, 8168, 8169, 8162, 8163, + 8164, 8172, 8166, 8167, 8178, 8188, 8180, 8182, + 8183, 8179, 8305, 8319, 8336, 8337, 8338, 8339, + 8340, 8341, 8342, 8343, 8344, 8345, 8346, 8347, + 8348, 8450, 8455, 8458, 8459, 8460, 8461, 8462, + 8463, 8464, 8465, 8466, 8467, 8469, 8473, 8474, + 8475, 8476, 8477, 8484, 8488, 8492, 8493, 8495, + 8496, 8497, 8499, 8500, 8505, 8508, 8509, 8510, + 8511, 8517, 8518, 8519, 8520, 8521, 8498, 8544, + 8545, 8546, 8547, 8548, 8549, 8550, 8551, 8552, + 8553, 8554, 8555, 8556, 8557, 8558, 8559, 8579, + 9398, 9399, 9400, 9401, 9402, 9403, 9404, 9405, + 9406, 9407, 9408, 9409, 9410, 9411, 9412, 9413, + 9414, 9415, 9416, 9417, 9418, 9419, 9420, 9421, + 9422, 9423, 11264, 11265, 11266, 11267, 11268, 11269, + 11270, 11271, 11272, 11273, 11274, 11275, 11276, 11277, + 11278, 11279, 11280, 11281, 11282, 11283, 11284, 11285, + 11286, 11287, 11288, 11289, 11290, 11291, 11292, 11293, + 11294, 11295, 11296, 11297, 11298, 11299, 11300, 11301, + 11302, 11303, 11304, 11305, 11306, 11307, 11308, 11309, + 11310, 11311, 11360, 570, 574, 11367, 11369, 11371, + 11378, 11380, 11381, 11383, 11384, 11385, 11386, 11387, + 11388, 11389, 11392, 11394, 11396, 11398, 11400, 11402, + 11404, 11406, 11408, 11410, 11412, 11414, 11416, 11418, + 11420, 11422, 11424, 11426, 11428, 11430, 11432, 11434, + 11436, 11438, 11440, 11442, 11444, 11446, 11448, 11450, + 11452, 11454, 11456, 11458, 11460, 11462, 11464, 11466, + 11468, 11470, 11472, 11474, 11476, 11478, 11480, 11482, + 11484, 11486, 11488, 11490, 11492, 11499, 11501, 11506, + 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, + 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, + 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, + 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, + 4288, 4289, 4290, 4291, 4292, 4293, 4295, 4301, + 42560, 42562, 42564, 42566, 42568, 42572, 42574, 42576, + 42578, 42580, 42582, 42584, 42586, 42588, 42590, 42592, + 42594, 42596, 42598, 42600, 42602, 42604, 42624, 42626, + 42628, 42630, 42632, 42634, 42636, 42638, 42640, 42642, + 42644, 42646, 42648, 42650, 42652, 42653, 42786, 42788, + 42790, 42792, 42794, 42796, 42798, 42800, 42801, 42802, + 42804, 42806, 42808, 42810, 42812, 42814, 42816, 42818, + 42820, 42822, 42824, 42826, 42828, 42830, 42832, 42834, + 42836, 42838, 42840, 42842, 42844, 42846, 42848, 42850, + 42852, 42854, 42856, 42858, 42860, 42862, 42864, 42865, + 42866, 42867, 42868, 42869, 42870, 42871, 42872, 42873, + 42875, 42878, 42880, 42882, 42884, 42886, 42891, 42896, + 42898, 42948, 42901, 42902, 42904, 42906, 42908, 42910, + 42912, 42914, 42916, 42918, 42920, 42927, 42932, 42934, + 42936, 42938, 42940, 42942, 42944, 42946, 42951, 42953, + 42960, 42963, 42965, 42966, 42968, 42994, 42995, 42996, + 42997, 43000, 43001, 43002, 43824, 43825, 43826, 43827, + 43828, 43829, 43830, 43832, 43833, 43834, 43835, 43836, + 43837, 43838, 43839, 43840, 43841, 43842, 43843, 43844, + 43845, 43846, 43847, 43848, 43849, 43850, 43851, 43852, + 43853, 43854, 43855, 43856, 43857, 42931, 43860, 43861, + 43862, 43863, 43864, 43865, 43866, 43868, 43869, 43870, + 43871, 43872, 43873, 43874, 43875, 43876, 43877, 43880, + 43881, 64256, 64257, 64258, 64259, 64260, 64261, 64262, + 64275, 64276, 64277, 64278, 64279, 65313, 65314, 65315, + 65316, 65317, 65318, 65319, 65320, 65321, 65322, 65323, + 65324, 65325, 65326, 65327, 65328, 65329, 65330, 65331, + 65332, 65333, 65334, 65335, 65336, 65337, 65338, 55297, + 56320, 55297, 56321, 55297, 56322, 55297, 56323, 55297, + 56324, 55297, 56325, 55297, 56326, 55297, 56327, 55297, + 56328, 55297, 56329, 55297, 56330, 55297, 56331, 55297, + 56332, 55297, 56333, 55297, 56334, 55297, 56335, 55297, + 56336, 55297, 56337, 55297, 56338, 55297, 56339, 55297, + 56340, 55297, 56341, 55297, 56342, 55297, 56343, 55297, + 56344, 55297, 56345, 55297, 56346, 55297, 56347, 55297, + 56348, 55297, 56349, 55297, 56350, 55297, 56351, 55297, + 56352, 55297, 56353, 55297, 56354, 55297, 56355, 55297, + 56356, 55297, 56357, 55297, 56358, 55297, 56359, 55297, + 56496, 55297, 56497, 55297, 56498, 55297, 56499, 55297, + 56500, 55297, 56501, 55297, 56502, 55297, 56503, 55297, + 56504, 55297, 56505, 55297, 56506, 55297, 56507, 55297, + 56508, 55297, 56509, 55297, 56510, 55297, 56511, 55297, + 56512, 55297, 56513, 55297, 56514, 55297, 56515, 55297, + 56516, 55297, 56517, 55297, 56518, 55297, 56519, 55297, + 56520, 55297, 56521, 55297, 56522, 55297, 56523, 55297, + 56524, 55297, 56525, 55297, 56526, 55297, 56527, 55297, + 56528, 55297, 56529, 55297, 56530, 55297, 56531, 55297, + 56688, 55297, 56689, 55297, 56690, 55297, 56691, 55297, + 56692, 55297, 56693, 55297, 56694, 55297, 56695, 55297, + 56696, 55297, 56697, 55297, 56698, 55297, 56700, 55297, + 56701, 55297, 56702, 55297, 56703, 55297, 56704, 55297, + 56705, 55297, 56706, 55297, 56707, 55297, 56708, 55297, + 56709, 55297, 56710, 55297, 56711, 55297, 56712, 55297, + 56713, 55297, 56714, 55297, 56716, 55297, 56717, 55297, + 56718, 55297, 56719, 55297, 56720, 55297, 56721, 55297, + 56722, 55297, 56724, 55297, 56725, 55297, 57216, 55297, + 57219, 55297, 57220, 55297, 57221, 55297, 57223, 55297, + 57224, 55297, 57225, 55297, 57226, 55297, 57227, 55297, + 57228, 55297, 57229, 55297, 57230, 55297, 57231, 55297, + 57232, 55297, 57233, 55297, 57234, 55297, 57235, 55297, + 57236, 55297, 57237, 55297, 57238, 55297, 57239, 55297, + 57240, 55297, 57241, 55297, 57242, 55297, 57243, 55297, + 57244, 55297, 57245, 55297, 57246, 55297, 57247, 55297, + 57248, 55297, 57249, 55297, 57250, 55297, 57251, 55297, + 57252, 55297, 57253, 55297, 57254, 55297, 57255, 55297, + 57256, 55297, 57257, 55297, 57258, 55297, 57259, 55297, + 57260, 55297, 57261, 55297, 57262, 55297, 57263, 55297, + 57264, 55297, 57266, 55297, 57267, 55297, 57268, 55297, + 57269, 55297, 57270, 55297, 57271, 55297, 57272, 55297, + 57273, 55297, 57274, 55299, 56448, 55299, 56449, 55299, + 56450, 55299, 56451, 55299, 56452, 55299, 56453, 55299, + 56454, 55299, 56455, 55299, 56456, 55299, 56457, 55299, + 56458, 55299, 56459, 55299, 56460, 55299, 56461, 55299, + 56462, 55299, 56463, 55299, 56464, 55299, 56465, 55299, + 56466, 55299, 56467, 55299, 56468, 55299, 56469, 55299, + 56470, 55299, 56471, 55299, 56472, 55299, 56473, 55299, + 56474, 55299, 56475, 55299, 56476, 55299, 56477, 55299, + 56478, 55299, 56479, 55299, 56480, 55299, 56481, 55299, + 56482, 55299, 56483, 55299, 56484, 55299, 56485, 55299, + 56486, 55299, 56487, 55299, 56488, 55299, 56489, 55299, + 56490, 55299, 56491, 55299, 56492, 55299, 56493, 55299, + 56494, 55299, 56495, 55299, 56496, 55299, 56497, 55299, + 56498, 55302, 56480, 55302, 56481, 55302, 56482, 55302, + 56483, 55302, 56484, 55302, 56485, 55302, 56486, 55302, + 56487, 55302, 56488, 55302, 56489, 55302, 56490, 55302, + 56491, 55302, 56492, 55302, 56493, 55302, 56494, 55302, + 56495, 55302, 56496, 55302, 56497, 55302, 56498, 55302, + 56499, 55302, 56500, 55302, 56501, 55302, 56502, 55302, + 56503, 55302, 56504, 55302, 56505, 55302, 56506, 55302, + 56507, 55302, 56508, 55302, 56509, 55302, 56510, 55302, + 56511, 55323, 56896, 55323, 56897, 55323, 56898, 55323, + 56899, 55323, 56900, 55323, 56901, 55323, 56902, 55323, + 56903, 55323, 56904, 55323, 56905, 55323, 56906, 55323, + 56907, 55323, 56908, 55323, 56909, 55323, 56910, 55323, + 56911, 55323, 56912, 55323, 56913, 55323, 56914, 55323, + 56915, 55323, 56916, 55323, 56917, 55323, 56918, 55323, + 56919, 55323, 56920, 55323, 56921, 55323, 56922, 55323, + 56923, 55323, 56924, 55323, 56925, 55323, 56926, 55323, + 56927, 55349, 56320, 55349, 56321, 55349, 56322, 55349, + 56323, 55349, 56324, 55349, 56325, 55349, 56326, 55349, + 56327, 55349, 56328, 55349, 56329, 55349, 56330, 55349, + 56331, 55349, 56332, 55349, 56333, 55349, 56334, 55349, + 56335, 55349, 56336, 55349, 56337, 55349, 56338, 55349, + 56339, 55349, 56340, 55349, 56341, 55349, 56342, 55349, + 56343, 55349, 56344, 55349, 56345, 55349, 56346, 55349, + 56347, 55349, 56348, 55349, 56349, 55349, 56350, 55349, + 56351, 55349, 56352, 55349, 56353, 55349, 56354, 55349, + 56355, 55349, 56356, 55349, 56357, 55349, 56358, 55349, + 56359, 55349, 56360, 55349, 56361, 55349, 56362, 55349, + 56363, 55349, 56364, 55349, 56365, 55349, 56366, 55349, + 56367, 55349, 56368, 55349, 56369, 55349, 56370, 55349, + 56371, 55349, 56372, 55349, 56373, 55349, 56374, 55349, + 56375, 55349, 56376, 55349, 56377, 55349, 56378, 55349, + 56379, 55349, 56380, 55349, 56381, 55349, 56382, 55349, + 56383, 55349, 56384, 55349, 56385, 55349, 56386, 55349, + 56387, 55349, 56388, 55349, 56389, 55349, 56390, 55349, + 56391, 55349, 56392, 55349, 56393, 55349, 56394, 55349, + 56395, 55349, 56396, 55349, 56397, 55349, 56398, 55349, + 56399, 55349, 56400, 55349, 56401, 55349, 56402, 55349, + 56403, 55349, 56404, 55349, 56406, 55349, 56407, 55349, + 56408, 55349, 56409, 55349, 56410, 55349, 56411, 55349, + 56412, 55349, 56413, 55349, 56414, 55349, 56415, 55349, + 56416, 55349, 56417, 55349, 56418, 55349, 56419, 55349, + 56420, 55349, 56421, 55349, 56422, 55349, 56423, 55349, + 56424, 55349, 56425, 55349, 56426, 55349, 56427, 55349, + 56428, 55349, 56429, 55349, 56430, 55349, 56431, 55349, + 56432, 55349, 56433, 55349, 56434, 55349, 56435, 55349, + 56436, 55349, 56437, 55349, 56438, 55349, 56439, 55349, + 56440, 55349, 56441, 55349, 56442, 55349, 56443, 55349, + 56444, 55349, 56445, 55349, 56446, 55349, 56447, 55349, + 56448, 55349, 56449, 55349, 56450, 55349, 56451, 55349, + 56452, 55349, 56453, 55349, 56454, 55349, 56455, 55349, + 56456, 55349, 56457, 55349, 56458, 55349, 56459, 55349, + 56460, 55349, 56461, 55349, 56462, 55349, 56463, 55349, + 56464, 55349, 56465, 55349, 56466, 55349, 56467, 55349, + 56468, 55349, 56469, 55349, 56470, 55349, 56471, 55349, + 56472, 55349, 56473, 55349, 56474, 55349, 56475, 55349, + 56476, 55349, 56478, 55349, 56479, 55349, 56482, 55349, + 56485, 55349, 56486, 55349, 56489, 55349, 56490, 55349, + 56491, 55349, 56492, 55349, 56494, 55349, 56495, 55349, + 56496, 55349, 56497, 55349, 56498, 55349, 56499, 55349, + 56500, 55349, 56501, 55349, 56502, 55349, 56503, 55349, + 56504, 55349, 56505, 55349, 56507, 55349, 56509, 55349, + 56510, 55349, 56511, 55349, 56512, 55349, 56513, 55349, + 56514, 55349, 56515, 55349, 56517, 55349, 56518, 55349, + 56519, 55349, 56520, 55349, 56521, 55349, 56522, 55349, + 56523, 55349, 56524, 55349, 56525, 55349, 56526, 55349, + 56527, 55349, 56528, 55349, 56529, 55349, 56530, 55349, + 56531, 55349, 56532, 55349, 56533, 55349, 56534, 55349, + 56535, 55349, 56536, 55349, 56537, 55349, 56538, 55349, + 56539, 55349, 56540, 55349, 56541, 55349, 56542, 55349, + 56543, 55349, 56544, 55349, 56545, 55349, 56546, 55349, + 56547, 55349, 56548, 55349, 56549, 55349, 56550, 55349, + 56551, 55349, 56552, 55349, 56553, 55349, 56554, 55349, + 56555, 55349, 56556, 55349, 56557, 55349, 56558, 55349, + 56559, 55349, 56560, 55349, 56561, 55349, 56562, 55349, + 56563, 55349, 56564, 55349, 56565, 55349, 56566, 55349, + 56567, 55349, 56568, 55349, 56569, 55349, 56570, 55349, + 56571, 55349, 56572, 55349, 56573, 55349, 56574, 55349, + 56575, 55349, 56576, 55349, 56577, 55349, 56578, 55349, + 56579, 55349, 56580, 55349, 56581, 55349, 56583, 55349, + 56584, 55349, 56585, 55349, 56586, 55349, 56589, 55349, + 56590, 55349, 56591, 55349, 56592, 55349, 56593, 55349, + 56594, 55349, 56595, 55349, 56596, 55349, 56598, 55349, + 56599, 55349, 56600, 55349, 56601, 55349, 56602, 55349, + 56603, 55349, 56604, 55349, 56606, 55349, 56607, 55349, + 56608, 55349, 56609, 55349, 56610, 55349, 56611, 55349, + 56612, 55349, 56613, 55349, 56614, 55349, 56615, 55349, + 56616, 55349, 56617, 55349, 56618, 55349, 56619, 55349, + 56620, 55349, 56621, 55349, 56622, 55349, 56623, 55349, + 56624, 55349, 56625, 55349, 56626, 55349, 56627, 55349, + 56628, 55349, 56629, 55349, 56630, 55349, 56631, 55349, + 56632, 55349, 56633, 55349, 56635, 55349, 56636, 55349, + 56637, 55349, 56638, 55349, 56640, 55349, 56641, 55349, + 56642, 55349, 56643, 55349, 56644, 55349, 56646, 55349, + 56650, 55349, 56651, 55349, 56652, 55349, 56653, 55349, + 56654, 55349, 56655, 55349, 56656, 55349, 56658, 55349, + 56659, 55349, 56660, 55349, 56661, 55349, 56662, 55349, + 56663, 55349, 56664, 55349, 56665, 55349, 56666, 55349, + 56667, 55349, 56668, 55349, 56669, 55349, 56670, 55349, + 56671, 55349, 56672, 55349, 56673, 55349, 56674, 55349, + 56675, 55349, 56676, 55349, 56677, 55349, 56678, 55349, + 56679, 55349, 56680, 55349, 56681, 55349, 56682, 55349, + 56683, 55349, 56684, 55349, 56685, 55349, 56686, 55349, + 56687, 55349, 56688, 55349, 56689, 55349, 56690, 55349, + 56691, 55349, 56692, 55349, 56693, 55349, 56694, 55349, + 56695, 55349, 56696, 55349, 56697, 55349, 56698, 55349, + 56699, 55349, 56700, 55349, 56701, 55349, 56702, 55349, + 56703, 55349, 56704, 55349, 56705, 55349, 56706, 55349, + 56707, 55349, 56708, 55349, 56709, 55349, 56710, 55349, + 56711, 55349, 56712, 55349, 56713, 55349, 56714, 55349, + 56715, 55349, 56716, 55349, 56717, 55349, 56718, 55349, + 56719, 55349, 56720, 55349, 56721, 55349, 56722, 55349, + 56723, 55349, 56724, 55349, 56725, 55349, 56726, 55349, + 56727, 55349, 56728, 55349, 56729, 55349, 56730, 55349, + 56731, 55349, 56732, 55349, 56733, 55349, 56734, 55349, + 56735, 55349, 56736, 55349, 56737, 55349, 56738, 55349, + 56739, 55349, 56740, 55349, 56741, 55349, 56742, 55349, + 56743, 55349, 56744, 55349, 56745, 55349, 56746, 55349, + 56747, 55349, 56748, 55349, 56749, 55349, 56750, 55349, + 56751, 55349, 56752, 55349, 56753, 55349, 56754, 55349, + 56755, 55349, 56756, 55349, 56757, 55349, 56758, 55349, + 56759, 55349, 56760, 55349, 56761, 55349, 56762, 55349, + 56763, 55349, 56764, 55349, 56765, 55349, 56766, 55349, + 56767, 55349, 56768, 55349, 56769, 55349, 56770, 55349, + 56771, 55349, 56772, 55349, 56773, 55349, 56774, 55349, + 56775, 55349, 56776, 55349, 56777, 55349, 56778, 55349, + 56779, 55349, 56780, 55349, 56781, 55349, 56782, 55349, + 56783, 55349, 56784, 55349, 56785, 55349, 56786, 55349, + 56787, 55349, 56788, 55349, 56789, 55349, 56790, 55349, + 56791, 55349, 56792, 55349, 56793, 55349, 56794, 55349, + 56795, 55349, 56796, 55349, 56797, 55349, 56798, 55349, + 56799, 55349, 56800, 55349, 56801, 55349, 56802, 55349, + 56803, 55349, 56804, 55349, 56805, 55349, 56806, 55349, + 56807, 55349, 56808, 55349, 56809, 55349, 56810, 55349, + 56811, 55349, 56812, 55349, 56813, 55349, 56814, 55349, + 56815, 55349, 56816, 55349, 56817, 55349, 56818, 55349, + 56819, 55349, 56820, 55349, 56821, 55349, 56822, 55349, + 56823, 55349, 56824, 55349, 56825, 55349, 56826, 55349, + 56827, 55349, 56828, 55349, 56829, 55349, 56830, 55349, + 56831, 55349, 56832, 55349, 56833, 55349, 56834, 55349, + 56835, 55349, 56836, 55349, 56837, 55349, 56838, 55349, + 56839, 55349, 56840, 55349, 56841, 55349, 56842, 55349, + 56843, 55349, 56844, 55349, 56845, 55349, 56846, 55349, + 56847, 55349, 56848, 55349, 56849, 55349, 56850, 55349, + 56851, 55349, 56852, 55349, 56853, 55349, 56854, 55349, + 56855, 55349, 56856, 55349, 56857, 55349, 56858, 55349, + 56859, 55349, 56860, 55349, 56861, 55349, 56862, 55349, + 56863, 55349, 56864, 55349, 56865, 55349, 56866, 55349, + 56867, 55349, 56868, 55349, 56869, 55349, 56870, 55349, + 56871, 55349, 56872, 55349, 56873, 55349, 56874, 55349, + 56875, 55349, 56876, 55349, 56877, 55349, 56878, 55349, + 56879, 55349, 56880, 55349, 56881, 55349, 56882, 55349, + 56883, 55349, 56884, 55349, 56885, 55349, 56886, 55349, + 56887, 55349, 56888, 55349, 56889, 55349, 56890, 55349, + 56891, 55349, 56892, 55349, 56893, 55349, 56894, 55349, + 56895, 55349, 56896, 55349, 56897, 55349, 56898, 55349, + 56899, 55349, 56900, 55349, 56901, 55349, 56902, 55349, + 56903, 55349, 56904, 55349, 56905, 55349, 56906, 55349, + 56907, 55349, 56908, 55349, 56909, 55349, 56910, 55349, + 56911, 55349, 56912, 55349, 56913, 55349, 56914, 55349, + 56915, 55349, 56916, 55349, 56917, 55349, 56918, 55349, + 56919, 55349, 56920, 55349, 56921, 55349, 56922, 55349, + 56923, 55349, 56924, 55349, 56925, 55349, 56926, 55349, + 56927, 55349, 56928, 55349, 56929, 55349, 56930, 55349, + 56931, 55349, 56932, 55349, 56933, 55349, 56934, 55349, + 56935, 55349, 56936, 55349, 56937, 55349, 56938, 55349, + 56939, 55349, 56940, 55349, 56941, 55349, 56942, 55349, + 56943, 55349, 56944, 55349, 56945, 55349, 56946, 55349, + 56947, 55349, 56948, 55349, 56949, 55349, 56950, 55349, + 56951, 55349, 56952, 55349, 56953, 55349, 56954, 55349, + 56955, 55349, 56956, 55349, 56957, 55349, 56958, 55349, + 56959, 55349, 56960, 55349, 56961, 55349, 56962, 55349, + 56963, 55349, 56964, 55349, 56965, 55349, 56966, 55349, + 56967, 55349, 56968, 55349, 56969, 55349, 56970, 55349, + 56971, 55349, 56972, 55349, 56973, 55349, 56974, 55349, + 56975, 55349, 56976, 55349, 56977, 55349, 56978, 55349, + 56979, 55349, 56980, 55349, 56981, 55349, 56982, 55349, + 56983, 55349, 56984, 55349, 56985, 55349, 56986, 55349, + 56987, 55349, 56988, 55349, 56989, 55349, 56990, 55349, + 56991, 55349, 56992, 55349, 56993, 55349, 56994, 55349, + 56995, 55349, 56996, 55349, 56997, 55349, 57000, 55349, + 57001, 55349, 57002, 55349, 57003, 55349, 57004, 55349, + 57005, 55349, 57006, 55349, 57007, 55349, 57008, 55349, + 57009, 55349, 57010, 55349, 57011, 55349, 57012, 55349, + 57013, 55349, 57014, 55349, 57015, 55349, 57016, 55349, + 57017, 55349, 57018, 55349, 57019, 55349, 57020, 55349, + 57021, 55349, 57022, 55349, 57023, 55349, 57024, 55349, + 57026, 55349, 57027, 55349, 57028, 55349, 57029, 55349, + 57030, 55349, 57031, 55349, 57032, 55349, 57033, 55349, + 57034, 55349, 57035, 55349, 57036, 55349, 57037, 55349, + 57038, 55349, 57039, 55349, 57040, 55349, 57041, 55349, + 57042, 55349, 57043, 55349, 57044, 55349, 57045, 55349, + 57046, 55349, 57047, 55349, 57048, 55349, 57049, 55349, + 57050, 55349, 57052, 55349, 57053, 55349, 57054, 55349, + 57055, 55349, 57056, 55349, 57057, 55349, 57058, 55349, + 57059, 55349, 57060, 55349, 57061, 55349, 57062, 55349, + 57063, 55349, 57064, 55349, 57065, 55349, 57066, 55349, + 57067, 55349, 57068, 55349, 57069, 55349, 57070, 55349, + 57071, 55349, 57072, 55349, 57073, 55349, 57074, 55349, + 57075, 55349, 57076, 55349, 57077, 55349, 57078, 55349, + 57079, 55349, 57080, 55349, 57081, 55349, 57082, 55349, + 57084, 55349, 57085, 55349, 57086, 55349, 57087, 55349, + 57088, 55349, 57089, 55349, 57090, 55349, 57091, 55349, + 57092, 55349, 57093, 55349, 57094, 55349, 57095, 55349, + 57096, 55349, 57097, 55349, 57098, 55349, 57099, 55349, + 57100, 55349, 57101, 55349, 57102, 55349, 57103, 55349, + 57104, 55349, 57105, 55349, 57106, 55349, 57107, 55349, + 57108, 55349, 57110, 55349, 57111, 55349, 57112, 55349, + 57113, 55349, 57114, 55349, 57115, 55349, 57116, 55349, + 57117, 55349, 57118, 55349, 57119, 55349, 57120, 55349, + 57121, 55349, 57122, 55349, 57123, 55349, 57124, 55349, + 57125, 55349, 57126, 55349, 57127, 55349, 57128, 55349, + 57129, 55349, 57130, 55349, 57131, 55349, 57132, 55349, + 57133, 55349, 57134, 55349, 57135, 55349, 57136, 55349, + 57137, 55349, 57138, 55349, 57139, 55349, 57140, 55349, + 57142, 55349, 57143, 55349, 57144, 55349, 57145, 55349, + 57146, 55349, 57147, 55349, 57148, 55349, 57149, 55349, + 57150, 55349, 57151, 55349, 57152, 55349, 57153, 55349, + 57154, 55349, 57155, 55349, 57156, 55349, 57157, 55349, + 57158, 55349, 57159, 55349, 57160, 55349, 57161, 55349, + 57162, 55349, 57163, 55349, 57164, 55349, 57165, 55349, + 57166, 55349, 57168, 55349, 57169, 55349, 57170, 55349, + 57171, 55349, 57172, 55349, 57173, 55349, 57174, 55349, + 57175, 55349, 57176, 55349, 57177, 55349, 57178, 55349, + 57179, 55349, 57180, 55349, 57181, 55349, 57182, 55349, + 57183, 55349, 57184, 55349, 57185, 55349, 57186, 55349, + 57187, 55349, 57188, 55349, 57189, 55349, 57190, 55349, + 57191, 55349, 57192, 55349, 57193, 55349, 57194, 55349, + 57195, 55349, 57196, 55349, 57197, 55349, 57198, 55349, + 57200, 55349, 57201, 55349, 57202, 55349, 57203, 55349, + 57204, 55349, 57205, 55349, 57206, 55349, 57207, 55349, + 57208, 55349, 57209, 55349, 57210, 55349, 57211, 55349, + 57212, 55349, 57213, 55349, 57214, 55349, 57215, 55349, + 57216, 55349, 57217, 55349, 57218, 55349, 57219, 55349, + 57220, 55349, 57221, 55349, 57222, 55349, 57223, 55349, + 57224, 55349, 57226, 55349, 57227, 55349, 57228, 55349, + 57229, 55349, 57230, 55349, 57231, 55349, 57232, 55349, + 57233, 55349, 57234, 55349, 57235, 55349, 57236, 55349, + 57237, 55349, 57238, 55349, 57239, 55349, 57240, 55349, + 57241, 55349, 57242, 55349, 57243, 55349, 57244, 55349, + 57245, 55349, 57246, 55349, 57247, 55349, 57248, 55349, + 57249, 55349, 57250, 55349, 57251, 55349, 57252, 55349, + 57253, 55349, 57254, 55349, 57255, 55349, 57256, 55349, + 57258, 55349, 57259, 55349, 57260, 55349, 57261, 55349, + 57262, 55349, 57263, 55349, 57264, 55349, 57265, 55349, + 57266, 55349, 57267, 55349, 57268, 55349, 57269, 55349, + 57270, 55349, 57271, 55349, 57272, 55349, 57273, 55349, + 57274, 55349, 57275, 55349, 57276, 55349, 57277, 55349, + 57278, 55349, 57279, 55349, 57280, 55349, 57281, 55349, + 57282, 55349, 57284, 55349, 57285, 55349, 57286, 55349, + 57287, 55349, 57288, 55349, 57289, 55349, 57290, 55349, + 57291, 55351, 57088, 55351, 57089, 55351, 57090, 55351, + 57091, 55351, 57095, 55351, 57097, 55351, 57099, 55351, + 57100, 55351, 57101, 55351, 57102, 55351, 57103, 55351, + 57104, 55351, 57105, 55351, 57106, 55351, 57107, 55351, + 57108, 55351, 57109, 55351, 57110, 55351, 57111, 55351, + 57112, 55351, 57113, 55351, 57114, 55351, 57115, 55351, + 57116, 55351, 57117, 55351, 57125, 55351, 57126, 55351, + 57127, 55351, 57128, 55351, 57129, 55351, 57130, 55352, + 56368, 55352, 56369, 55352, 56370, 55352, 56371, 55352, + 56372, 55352, 56373, 55352, 56374, 55352, 56375, 55352, + 56376, 55352, 56377, 55352, 56378, 55352, 56379, 55352, + 56380, 55352, 56381, 55352, 56382, 55352, 56383, 55352, + 56384, 55352, 56385, 55352, 56386, 55352, 56387, 55352, + 56388, 55352, 56389, 55352, 56390, 55352, 56391, 55352, + 56392, 55352, 56393, 55352, 56394, 55352, 56395, 55352, + 56396, 55352, 56397, 55352, 56398, 55352, 56399, 55352, + 56400, 55352, 56401, 55352, 56402, 55352, 56403, 55352, + 56404, 55352, 56405, 55352, 56406, 55352, 56407, 55352, + 56408, 55352, 56409, 55352, 56410, 55352, 56411, 55352, + 56412, 55352, 56413, 55352, 56414, 55352, 56415, 55352, + 56416, 55352, 56417, 55352, 56418, 55352, 56419, 55352, + 56420, 55352, 56421, 55352, 56422, 55352, 56423, 55352, + 56424, 55352, 56425, 55352, 56426, 55352, 56427, 55352, + 56428, 55352, 56429, 55354, 56576, 55354, 56577, 55354, + 56578, 55354, 56579, 55354, 56580, 55354, 56581, 55354, + 56582, 55354, 56583, 55354, 56584, 55354, 56585, 55354, + 56586, 55354, 56587, 55354, 56588, 55354, 56589, 55354, + 56590, 55354, 56591, 55354, 56592, 55354, 56593, 55354, + 56594, 55354, 56595, 55354, 56596, 55354, 56597, 55354, + 56598, 55354, 56599, 55354, 56600, 55354, 56601, 55354, + 56602, 55354, 56603, 55354, 56604, 55354, 56605, 55354, + 56606, 55354, 56607, 55354, 56608, 55354, 56609, 55356, + 56624, 55356, 56625, 55356, 56626, 55356, 56627, 55356, + 56628, 55356, 56629, 55356, 56630, 55356, 56631, 55356, + 56632, 55356, 56633, 55356, 56634, 55356, 56635, 55356, + 56636, 55356, 56637, 55356, 56638, 55356, 56639, 55356, + 56640, 55356, 56641, 55356, 56642, 55356, 56643, 55356, + 56644, 55356, 56645, 55356, 56646, 55356, 56647, 55356, + 56648, 55356, 56649, 55356, 56656, 55356, 56657, 55356, + 56658, 55356, 56659, 55356, 56660, 55356, 56661, 55356, + 56662, 55356, 56663, 55356, 56664, 55356, 56665, 55356, + 56666, 55356, 56667, 55356, 56668, 55356, 56669, 55356, + 56670, 55356, 56671, 55356, 56672, 55356, 56673, 55356, + 56674, 55356, 56675, 55356, 56676, 55356, 56677, 55356, + 56678, 55356, 56679, 55356, 56680, 55356, 56681, 55356, + 56688, 55356, 56689, 55356, 56690, 55356, 56691, 55356, + 56692, 55356, 56693, 55356, 56694, 55356, 56695, 55356, + 56696, 55356, 56697, 55356, 56698, 55356, 56699, 55356, + 56700, 55356, 56701, 55356, 56702, 55356, 56703, 55356, + 56704, 55356, 56705, 55356, 56706, 55356, 56707, 55356, + 56708, 55356, 56709, 55356, 56710, 55356, 56711, 55356, + 56712, 55356, 56713, }; + +static const utf8proc_uint16_t utf8proc_stage1table[] = { + 0, 256, 512, 768, 1024, 1280, 1536, + 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, + 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, + 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680, + 7936, 8192, 8448, 8704, 8960, 9216, 9472, 9728, + 9984, 10240, 10496, 10752, 11008, 11264, 11520, 11776, + 12032, 12288, 12544, 12800, 13056, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13568, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13824, 13312, 13312, 13312, 14080, 5376, 14336, + 14592, 14848, 15104, 15360, 15616, 15872, 16128, 16384, + 16640, 16896, 17152, 17408, 15872, 16128, 16384, 16640, + 16896, 17152, 17408, 15872, 16128, 16384, 16640, 16896, + 17152, 17408, 15872, 16128, 16384, 16640, 16896, 17152, + 17408, 15872, 16128, 16384, 16640, 16896, 17152, 17408, + 15872, 16128, 16384, 16640, 16896, 17152, 17408, 15872, + 17664, 17920, 17920, 17920, 17920, 17920, 17920, 17920, + 17920, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18432, 18688, 18944, 19200, 19456, 19712, + 19968, 20224, 20480, 20736, 20992, 21248, 21504, 5376, + 21760, 22016, 22272, 22528, 22784, 23040, 23296, 23552, + 23808, 24064, 24320, 24576, 24832, 25088, 25344, 25600, + 25856, 26112, 26368, 26624, 26880, 27136, 27392, 27648, + 27904, 5376, 5376, 5376, 28160, 28416, 28672, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 29184, 5376, 5376, 5376, 5376, 29440, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 5376, 5376, 29696, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 5376, 5376, 29952, 30208, 28928, 28928, 30464, + 30720, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 30976, 13312, 13312, 13312, 13312, 31232, 31488, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 31744, 13312, 32000, 32256, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 32512, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 32768, 33024, 33280, 33536, 33792, 34048, 34304, 34560, + 34816, 10240, 10240, 35072, 28928, 28928, 28928, 28928, + 35328, 35584, 35840, 36096, 28928, 36352, 28928, 28928, + 36608, 36864, 37120, 28928, 28928, 37376, 37632, 37888, + 28928, 38144, 38400, 38656, 38912, 39168, 39424, 39680, + 39936, 40192, 40448, 40704, 40960, 28928, 28928, 28928, + 28928, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 41216, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 41472, 41728, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 41984, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 42240, 13312, 13312, 42496, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 42752, 43008, 43264, 28928, 28928, 28928, 28928, + 28928, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 43520, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 43776, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 44032, 44288, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 44544, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 44544, }; + +static const utf8proc_uint16_t utf8proc_stage2table[] = { + 1, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 4, 3, 5, 6, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 7, 7, 7, + 3, 8, 9, 9, 10, 11, 10, 9, + 9, 12, 13, 9, 14, 15, 16, 15, + 15, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 15, 9, 18, 19, 20, + 9, 9, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 12, 9, 13, 47, + 48, 47, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 12, 75, 13, 75, + 2, 2, 2, 2, 2, 2, 7, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 76, 9, 11, 11, 11, 11, 77, + 9, 78, 79, 80, 81, 75, 82, 79, + 83, 84, 85, 86, 87, 88, 89, 9, + 9, 90, 91, 92, 93, 94, 95, 96, + 9, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 75, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, + 75, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, + 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, + 350, 346, 346, 346, 346, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, + 386, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 425, + 426, 427, 428, 429, 430, 431, 432, 433, + 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 447, 448, 449, + 450, 451, 452, 453, 454, 455, 456, 457, + 458, 459, 460, 461, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 501, 502, 503, 504, 505, + 506, 507, 508, 509, 510, 511, 512, 513, + 514, 515, 516, 517, 518, 519, 520, 521, + 522, 523, 524, 525, 526, 527, 528, 529, + 530, 531, 532, 533, 534, 535, 536, 537, + 538, 539, 540, 541, 542, 543, 544, 545, + 546, 547, 548, 549, 550, 551, 552, 553, + 554, 555, 556, 557, 558, 346, 559, 560, + 561, 562, 563, 564, 565, 566, 567, 568, + 569, 570, 571, 572, 573, 574, 575, 576, + 577, 578, 579, 580, 581, 582, 583, 584, + 585, 586, 587, 588, 589, 590, 591, 592, + 593, 594, 595, 595, 596, 596, 596, 596, + 596, 597, 598, 47, 47, 47, 47, 595, + 595, 595, 595, 595, 595, 595, 595, 595, + 595, 596, 596, 47, 47, 47, 47, 47, + 47, 599, 600, 601, 602, 603, 604, 47, + 47, 605, 606, 607, 608, 609, 47, 47, + 47, 47, 47, 47, 47, 595, 47, 596, + 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, + 47, 610, 611, 612, 613, 614, 615, 616, + 617, 618, 619, 620, 621, 622, 615, 615, + 623, 615, 624, 615, 625, 626, 627, 628, + 628, 628, 628, 627, 629, 628, 628, 628, + 628, 628, 630, 630, 631, 632, 633, 634, + 635, 636, 628, 628, 628, 628, 637, 638, + 628, 639, 640, 628, 628, 641, 641, 641, + 641, 642, 628, 628, 628, 628, 615, 615, + 615, 643, 644, 645, 646, 647, 648, 615, + 628, 628, 628, 615, 615, 615, 628, 628, + 649, 615, 615, 615, 628, 628, 628, 628, + 615, 627, 628, 628, 615, 650, 651, 651, + 650, 651, 651, 650, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 652, 653, 654, 655, 656, 47, 657, + 658, 0, 0, 659, 660, 661, 662, 663, + 664, 0, 0, 0, 0, 88, 665, 666, + 667, 668, 669, 670, 0, 671, 0, 672, + 673, 674, 675, 676, 677, 678, 679, 680, + 681, 682, 683, 684, 685, 686, 687, 688, + 689, 690, 691, 0, 692, 693, 694, 695, + 696, 697, 698, 699, 700, 701, 702, 703, + 704, 705, 706, 707, 708, 709, 710, 711, + 712, 713, 714, 715, 716, 717, 718, 719, + 720, 721, 722, 723, 724, 725, 726, 727, + 728, 729, 730, 731, 732, 733, 734, 735, + 736, 737, 738, 739, 740, 741, 742, 743, + 744, 745, 746, 747, 748, 749, 750, 751, + 752, 753, 754, 755, 756, 757, 758, 759, + 760, 761, 762, 763, 764, 765, 766, 767, + 768, 769, 770, 771, 772, 773, 774, 75, + 775, 776, 777, 778, 779, 780, 781, 782, + 783, 784, 785, 786, 787, 788, 789, 790, + 791, 792, 793, 794, 795, 796, 797, 798, + 799, 800, 801, 802, 803, 804, 805, 806, + 807, 808, 809, 810, 811, 812, 813, 814, + 815, 816, 817, 818, 819, 820, 821, 822, + 823, 824, 825, 826, 827, 828, 829, 830, + 831, 832, 833, 834, 835, 836, 837, 838, + 839, 840, 841, 842, 843, 844, 845, 846, + 847, 848, 849, 850, 851, 852, 853, 854, + 855, 856, 857, 858, 859, 860, 861, 862, + 863, 864, 865, 866, 867, 868, 869, 870, + 871, 872, 873, 874, 875, 876, 877, 878, + 879, 880, 881, 882, 883, 884, 885, 886, + 887, 888, 889, 890, 891, 892, 893, 894, + 895, 896, 897, 898, 899, 900, 901, 902, + 903, 904, 905, 906, 907, 908, 909, 910, + 911, 912, 913, 914, 615, 615, 615, 615, + 615, 915, 915, 916, 917, 918, 919, 920, + 921, 922, 923, 924, 925, 926, 927, 928, + 929, 930, 931, 932, 933, 934, 935, 936, + 937, 938, 939, 940, 941, 942, 943, 944, + 945, 946, 947, 948, 949, 950, 951, 952, + 953, 954, 955, 956, 957, 958, 959, 960, + 961, 962, 963, 964, 965, 966, 967, 968, + 969, 970, 971, 972, 973, 974, 975, 976, + 977, 978, 979, 980, 981, 982, 983, 984, + 985, 986, 987, 988, 989, 990, 991, 992, + 993, 994, 995, 996, 997, 998, 999, 1000, + 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, + 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, + 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, + 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, + 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, + 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, + 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, + 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, + 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, + 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, + 1081, 0, 1082, 1083, 1084, 1085, 1086, 1087, + 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, + 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, + 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, + 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, + 0, 0, 596, 1120, 1120, 1120, 1120, 1120, + 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, + 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, + 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, + 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, + 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, + 1160, 1161, 1120, 1162, 0, 0, 77, 77, + 11, 0, 628, 615, 615, 615, 615, 628, + 615, 615, 615, 1163, 628, 615, 615, 615, + 615, 615, 615, 628, 628, 628, 628, 628, + 628, 615, 615, 628, 615, 615, 1163, 1164, + 615, 1165, 1166, 1167, 1168, 1169, 1170, 1171, + 1172, 1173, 1174, 1174, 1175, 1176, 1177, 1178, + 1179, 1180, 1181, 1182, 1180, 615, 628, 1180, + 1173, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 0, 0, 0, 0, + 1183, 1183, 1183, 1183, 1180, 1180, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1184, 1184, 1184, 1184, 1184, 1184, 75, + 75, 1185, 10, 10, 1186, 15, 1187, 77, + 77, 615, 615, 615, 615, 615, 615, 615, + 615, 1188, 1189, 1190, 1187, 1191, 1187, 1187, + 1187, 1192, 1192, 1193, 1194, 1195, 1196, 1197, + 1198, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1199, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1200, 1192, 1201, 1202, 1203, 1204, 1188, + 1189, 1190, 1205, 1206, 1207, 1208, 1209, 628, + 615, 615, 615, 615, 615, 628, 615, 615, + 628, 1210, 1210, 1210, 1210, 1210, 1210, 1210, + 1210, 1210, 1210, 10, 1211, 1211, 1187, 1192, + 1192, 1212, 1192, 1192, 1192, 1192, 1213, 1214, + 1215, 1216, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1217, 1218, 1219, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1220, 1221, 1187, 1222, 615, + 615, 615, 615, 615, 615, 615, 1184, 77, + 615, 615, 615, 615, 628, 615, 1199, 1199, + 615, 615, 77, 628, 615, 615, 628, 1192, + 1192, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 1192, 1192, 1192, 1223, 1223, + 1192, 1187, 1187, 1187, 1187, 1187, 1187, 1187, + 1187, 1187, 1187, 1187, 1187, 1187, 1187, 0, + 1224, 1192, 1225, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 615, 628, 615, 615, 628, 615, 615, + 628, 628, 628, 615, 628, 628, 615, 628, + 615, 615, 615, 628, 615, 628, 615, 628, + 615, 628, 615, 615, 0, 0, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1192, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1227, 1227, 1227, 1227, 1227, 1227, 1227, + 1227, 1227, 1227, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 615, 615, 615, 615, + 615, 615, 615, 628, 615, 1228, 1228, 77, + 9, 9, 9, 1228, 0, 0, 628, 1229, + 1229, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 615, + 615, 615, 615, 1228, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 1228, 615, 615, + 615, 1228, 615, 615, 615, 615, 615, 0, + 0, 1180, 1180, 1180, 1180, 1180, 1180, 1180, + 1180, 1180, 1180, 1180, 1180, 1180, 1180, 1180, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 628, 628, 628, 0, 0, 1180, + 0, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 0, 0, 0, 0, + 0, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1230, 1192, 1192, 1192, 1192, 1192, 1192, + 0, 1184, 1184, 0, 0, 0, 0, 0, + 0, 615, 628, 628, 628, 615, 615, 615, + 615, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1199, 615, 615, 615, 615, 615, + 628, 628, 628, 628, 628, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 1184, 628, 615, 615, 628, + 615, 615, 628, 615, 615, 615, 628, 628, + 628, 1202, 1203, 1204, 615, 615, 615, 628, + 615, 615, 628, 628, 615, 615, 615, 615, + 615, 1226, 1226, 1226, 1231, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1233, 1234, 1232, 1232, 1232, 1232, 1232, + 1232, 1235, 1236, 1232, 1237, 1238, 1232, 1232, + 1232, 1232, 1232, 1226, 1231, 1239, 346, 1231, + 1231, 1231, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1231, 1231, 1231, 1231, 1240, 1231, + 1231, 346, 615, 628, 615, 615, 1226, 1226, + 1226, 1241, 1242, 1243, 1244, 1245, 1246, 1247, + 1248, 346, 346, 1226, 1226, 1120, 1120, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1120, 596, 346, 346, 346, 346, 346, + 346, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 346, 1226, 1231, 1231, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 0, + 346, 346, 0, 0, 346, 346, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 0, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 0, 1232, 0, 0, 0, 1232, + 1232, 1232, 1232, 0, 0, 1250, 346, 1251, + 1231, 1231, 1226, 1226, 1226, 1226, 0, 0, + 1252, 1231, 0, 0, 1253, 1254, 1240, 346, + 0, 0, 0, 0, 0, 0, 0, 0, + 1255, 0, 0, 0, 0, 1256, 1257, 0, + 1258, 346, 346, 1226, 1226, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1232, 1232, 11, 11, 1259, 1259, 1259, + 1259, 1259, 1259, 914, 11, 346, 1120, 615, + 0, 0, 1226, 1226, 1231, 0, 346, 346, + 346, 346, 346, 346, 0, 0, 0, 0, + 346, 346, 0, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 1260, 0, 346, 1261, + 0, 346, 346, 0, 0, 1250, 0, 1231, + 1231, 1231, 1226, 1226, 0, 0, 0, 0, + 1226, 1226, 0, 0, 1226, 1226, 1262, 0, + 0, 0, 1226, 0, 0, 0, 0, 0, + 0, 0, 1263, 1264, 1265, 346, 0, 1266, + 0, 0, 0, 0, 0, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1226, 1226, 346, 346, 346, 1226, 1120, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1226, 1226, 1231, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 346, 346, 346, 0, 346, 346, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 0, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 0, 1232, 1232, 0, 1232, 1232, + 1232, 1232, 1232, 0, 0, 1250, 346, 1231, + 1231, 1231, 1226, 1226, 1226, 1226, 1226, 0, + 1226, 1226, 1231, 0, 1231, 1231, 1240, 0, + 0, 346, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 1226, 1226, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1120, 11, 0, 0, 0, 0, 0, + 0, 0, 1232, 1226, 1226, 1226, 1226, 1226, + 1226, 0, 1226, 1231, 1231, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 0, + 346, 346, 0, 0, 346, 346, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 0, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 0, 1232, 1232, 0, 1232, 1232, + 1232, 1232, 1232, 0, 0, 1250, 346, 1267, + 1226, 1231, 1226, 1226, 1226, 1226, 0, 0, + 1268, 1269, 0, 0, 1270, 1271, 1240, 0, + 0, 0, 0, 0, 0, 0, 1226, 1272, + 1273, 0, 0, 0, 0, 1274, 1275, 0, + 1232, 346, 346, 1226, 1226, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 914, 1232, 1259, 1259, 1259, 1259, 1259, + 1259, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1226, 346, 0, 346, 346, + 346, 346, 346, 346, 0, 0, 0, 346, + 346, 346, 0, 1276, 346, 1277, 346, 0, + 0, 0, 346, 346, 0, 346, 0, 346, + 346, 0, 0, 0, 346, 346, 0, 0, + 0, 346, 346, 346, 0, 0, 0, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 0, 0, 0, 1278, + 1231, 1226, 1231, 1231, 0, 0, 0, 1279, + 1280, 1231, 0, 1281, 1282, 1283, 1262, 0, + 0, 346, 0, 0, 0, 0, 0, 0, + 1284, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1259, 1259, 1259, 77, 77, 77, 77, + 77, 77, 11, 77, 0, 0, 0, 0, + 0, 1226, 1231, 1231, 1231, 1226, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 346, + 346, 346, 0, 346, 346, 346, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 0, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 0, 0, 1250, 346, 1226, + 1226, 1226, 1231, 1231, 1231, 1231, 0, 1285, + 1226, 1286, 0, 1226, 1226, 1226, 1240, 0, + 0, 0, 0, 0, 0, 0, 1287, 1288, + 0, 1232, 1232, 1232, 0, 0, 346, 0, + 0, 346, 346, 1226, 1226, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 0, 0, 0, 0, 0, 0, 0, + 1120, 1289, 1289, 1289, 1289, 1289, 1289, 1289, + 914, 346, 1226, 1231, 1231, 1120, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 346, + 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 346, 346, + 346, 346, 346, 0, 0, 1250, 346, 1231, + 1290, 1291, 1231, 1292, 1231, 1231, 0, 1293, + 1294, 1295, 0, 1296, 1297, 1226, 1262, 0, + 0, 0, 0, 0, 0, 0, 1298, 1299, + 0, 0, 0, 0, 0, 0, 346, 346, + 0, 346, 346, 1226, 1226, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 0, 346, 346, 1231, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1226, 1226, 1231, 1231, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 346, + 346, 346, 0, 346, 346, 346, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1300, 1300, 346, 1301, + 1231, 1231, 1226, 1226, 1226, 1226, 0, 1302, + 1303, 1231, 0, 1304, 1305, 1306, 1240, 1307, + 914, 0, 0, 0, 0, 346, 346, 346, + 1308, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 346, 346, 346, 1226, 1226, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 914, 346, 346, 346, 346, 346, + 346, 0, 1226, 1231, 1231, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 0, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 346, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 0, 0, 1309, 0, 0, 0, 0, + 1310, 1231, 1231, 1226, 1226, 1226, 0, 1226, + 0, 1231, 1311, 1312, 1231, 1313, 1314, 1315, + 1316, 0, 0, 0, 0, 0, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 0, 0, 1231, 1231, 1120, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1226, 346, 1317, 1226, 1226, 1226, + 1226, 1318, 1318, 1300, 0, 0, 0, 0, + 11, 346, 346, 346, 346, 346, 346, 596, + 1226, 1319, 1319, 1319, 1319, 1226, 1226, 1226, + 1120, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1120, 1120, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 346, 346, 0, 346, 0, 346, + 346, 346, 346, 346, 0, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1226, 346, 1320, 1226, 1226, 1226, + 1226, 1321, 1321, 1300, 1226, 1226, 346, 0, + 0, 346, 346, 346, 346, 346, 0, 596, + 0, 1322, 1322, 1322, 1322, 1226, 1226, 1226, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 1323, 1324, 346, + 346, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 914, 914, 914, 1120, 1120, 1120, + 1120, 1120, 1120, 1120, 1120, 1325, 1120, 1120, + 1120, 1120, 1120, 1120, 914, 1120, 914, 914, + 914, 628, 628, 914, 914, 914, 914, 914, + 914, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 914, 628, 914, + 628, 914, 1326, 12, 13, 12, 13, 1231, + 1231, 346, 346, 346, 1327, 346, 346, 346, + 346, 0, 346, 346, 346, 346, 1328, 346, + 346, 346, 346, 1329, 346, 346, 346, 346, + 1330, 346, 346, 346, 346, 1331, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1332, 346, 346, 346, 0, 0, + 0, 0, 1333, 1334, 1335, 1336, 1337, 1338, + 1339, 1340, 1341, 1334, 1334, 1334, 1334, 1226, + 1231, 1334, 1342, 615, 615, 1300, 1120, 615, + 615, 346, 346, 346, 346, 346, 1226, 1226, + 1226, 1226, 1226, 1226, 1343, 1226, 1226, 1226, + 1226, 0, 1226, 1226, 1226, 1226, 1344, 1226, + 1226, 1226, 1226, 1345, 1226, 1226, 1226, 1226, + 1346, 1226, 1226, 1226, 1226, 1347, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1348, 1226, 1226, 1226, 0, 914, + 914, 914, 914, 914, 914, 914, 914, 628, + 914, 914, 914, 914, 914, 914, 0, 914, + 914, 1120, 1120, 1120, 1120, 1120, 914, 914, + 914, 914, 1120, 1120, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 1349, 1350, + 346, 346, 346, 346, 1351, 1351, 1226, 1352, + 1226, 1226, 1231, 1226, 1226, 1226, 1226, 1226, + 1250, 1351, 1300, 1300, 1231, 1231, 1226, 1226, + 346, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1120, 1120, 1120, 1120, 1120, + 1120, 346, 346, 346, 346, 346, 346, 1231, + 1231, 1226, 1226, 346, 346, 346, 346, 1226, + 1226, 1226, 346, 1351, 1351, 1351, 346, 346, + 1351, 1351, 1351, 1351, 1351, 1351, 1351, 346, + 346, 346, 1226, 1226, 1226, 1226, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 1226, 1351, 1231, 1226, 1226, + 1351, 1351, 1351, 1351, 1351, 1351, 628, 346, + 1351, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1351, 1351, 1351, 1226, 914, + 914, 1353, 1354, 1355, 1356, 1357, 1358, 1359, + 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, + 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, + 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, + 1384, 1385, 1386, 1387, 1388, 1389, 1390, 0, + 1391, 0, 0, 0, 0, 0, 1392, 0, + 0, 1393, 1394, 1395, 1396, 1397, 1398, 1399, + 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, + 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, + 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, + 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, + 1432, 1433, 1434, 1435, 1120, 1436, 1437, 1438, + 1439, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1441, 1442, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 0, 346, 346, 346, 346, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 0, 346, 346, 346, 346, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 0, 615, 615, + 615, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 1120, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 0, 0, 0, 0, 0, + 0, 1445, 1446, 1447, 1448, 1449, 1450, 1451, + 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, + 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, + 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, + 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, + 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, + 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, + 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, + 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, + 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, + 1524, 1525, 1526, 1527, 1528, 1529, 1530, 0, + 0, 1531, 1532, 1533, 1534, 1535, 1536, 0, + 0, 1162, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 914, 1120, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 8, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 12, 13, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1120, 1120, 1120, 1537, + 1537, 1537, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 1226, 1226, 1300, 1538, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 1226, 1226, 1538, 1120, 1120, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 1226, 1226, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 346, + 346, 346, 0, 1226, 1226, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 649, 649, 1231, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1226, + 1231, 1231, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1300, 1226, 1120, 1120, 1120, + 596, 1120, 1120, 1120, 11, 346, 615, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 1289, 1289, 1289, 1289, 1289, 1289, 1289, + 1289, 1289, 1289, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 1162, + 9, 9, 9, 9, 649, 649, 649, 1539, + 649, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 596, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 1226, 1226, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1164, 346, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 1226, 1226, 1226, 1231, 1231, 1231, 1231, + 1226, 1226, 1231, 1231, 1231, 0, 0, 0, + 0, 1231, 1231, 1226, 1231, 1231, 1231, 1231, + 1231, 1231, 1163, 615, 628, 0, 0, 0, + 0, 77, 0, 0, 0, 9, 9, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 0, 346, 346, 346, 346, 346, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1259, 0, 0, 0, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 615, 628, 1231, 1231, 1226, 0, 0, 1120, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 1231, 1226, + 1231, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 0, 1300, 1351, 1226, 1351, 1351, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1231, 1231, + 1231, 1231, 1231, 1231, 1226, 1226, 615, 615, + 615, 615, 615, 615, 615, 615, 0, 0, + 628, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 596, 1120, 1120, 1120, 1120, 1120, 1120, 0, + 0, 615, 615, 615, 615, 615, 628, 628, + 628, 628, 628, 628, 615, 615, 628, 915, + 628, 628, 615, 615, 628, 628, 615, 615, + 615, 615, 615, 628, 615, 615, 615, 615, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1226, 1226, 1226, 1226, 1231, 1540, 1541, + 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, + 346, 346, 1550, 1551, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 1250, 1552, 1226, + 1226, 1226, 1226, 1553, 1554, 1555, 1556, 1557, + 1558, 1559, 1560, 1561, 1562, 1538, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1120, 1120, 1120, 1120, 1120, + 1120, 1120, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 615, 628, 615, 615, + 615, 615, 615, 615, 615, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 1120, 1120, + 0, 1226, 1226, 1231, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1231, 1226, 1226, 1226, 1226, 1231, + 1231, 1226, 1226, 1538, 1300, 1226, 1226, 346, + 346, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 1250, + 1231, 1226, 1226, 1231, 1231, 1231, 1226, 1231, + 1226, 1226, 1226, 1538, 1538, 0, 0, 0, + 0, 0, 0, 0, 0, 1120, 1120, 1120, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1231, 1231, 1226, + 1250, 0, 0, 0, 1120, 1120, 1120, 1120, + 1120, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 346, 346, + 346, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 596, 596, 596, 596, 596, 596, 1120, + 1120, 1563, 1564, 1565, 1566, 1567, 1567, 1568, + 1569, 1570, 0, 0, 0, 0, 0, 0, + 0, 1571, 1572, 1573, 1574, 1575, 1576, 1577, + 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, + 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, + 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, + 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, + 1610, 1611, 1612, 1613, 0, 0, 1614, 1615, + 1616, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 0, 0, 0, 0, 0, 0, 0, + 0, 615, 615, 615, 1120, 641, 628, 628, + 628, 628, 628, 615, 615, 628, 628, 628, + 628, 615, 1231, 641, 641, 641, 641, 641, + 641, 641, 346, 346, 346, 346, 628, 346, + 346, 346, 346, 346, 346, 615, 346, 346, + 1231, 615, 615, 346, 0, 0, 0, 0, + 0, 1617, 1618, 1619, 1620, 1621, 1622, 1623, + 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, + 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, + 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, + 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, + 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, + 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, + 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, + 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, + 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, + 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, + 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, + 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, + 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, + 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, + 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, + 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, + 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, + 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, + 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, + 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, + 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, + 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, + 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, + 1808, 615, 615, 628, 615, 615, 615, 615, + 615, 615, 615, 628, 615, 615, 651, 1809, + 628, 630, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 627, + 1164, 1164, 628, 1810, 615, 650, 628, 615, + 628, 1811, 1812, 1813, 1814, 1815, 1816, 1817, + 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, + 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, + 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, + 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, + 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, + 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, + 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, + 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, + 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, + 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, + 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, + 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, + 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, + 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, + 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, + 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, + 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, + 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, + 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, + 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, + 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, + 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, + 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, + 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, + 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, + 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, + 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, + 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, + 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, + 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, + 2082, 2083, 2084, 2085, 2086, 2087, 2088, 0, + 0, 2089, 2090, 2091, 2092, 2093, 2094, 0, + 0, 2095, 2096, 2097, 2098, 2099, 2100, 2101, + 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, + 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, + 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, + 2126, 2127, 2128, 2129, 2130, 2131, 2132, 0, + 0, 2133, 2134, 2135, 2136, 2137, 2138, 0, + 0, 2139, 2140, 2141, 2142, 2143, 2144, 2145, + 2146, 0, 2147, 0, 2148, 0, 2149, 0, + 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, + 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, + 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, + 2174, 2175, 2176, 2177, 2178, 2179, 2180, 0, + 0, 2181, 2182, 2183, 2184, 2185, 2186, 2187, + 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, + 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, + 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, + 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, + 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, + 2228, 2229, 2230, 2231, 2232, 2233, 0, 2234, + 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, + 2243, 2244, 2245, 2246, 2247, 2248, 0, 2249, + 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, + 2258, 2259, 2260, 2261, 2262, 0, 0, 2263, + 2264, 2265, 2266, 2267, 2268, 0, 2269, 2270, + 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, + 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, + 2287, 0, 0, 2288, 2289, 2290, 0, 2291, + 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, + 0, 2300, 2301, 2302, 2302, 2302, 2302, 2302, + 2303, 2302, 2302, 2302, 1539, 2304, 2305, 2306, + 2307, 1162, 2308, 1162, 1162, 1162, 1162, 9, + 2309, 2310, 2311, 2312, 2310, 2310, 2311, 2312, + 2310, 9, 9, 9, 9, 2313, 2314, 2315, + 9, 2316, 2317, 2318, 2319, 2320, 2321, 2322, + 76, 10, 10, 10, 2323, 2324, 9, 2325, + 2326, 9, 81, 93, 9, 2327, 9, 2328, + 48, 48, 9, 9, 9, 2329, 12, 13, + 2330, 2331, 2332, 9, 9, 9, 9, 9, + 9, 9, 9, 75, 9, 48, 9, 9, + 2333, 9, 9, 9, 9, 9, 9, 9, + 2302, 1539, 1539, 1539, 1539, 1539, 0, 2334, + 2335, 2336, 2337, 1539, 1539, 1539, 1539, 1539, + 1539, 2338, 2339, 0, 0, 2340, 2341, 2342, + 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, + 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, + 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, + 0, 2367, 2368, 2369, 2370, 2371, 2372, 2373, + 2374, 2375, 2376, 2377, 2378, 2379, 0, 0, + 0, 11, 11, 11, 11, 11, 11, 11, + 11, 2380, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 615, 615, 641, 641, 615, 615, 615, + 615, 641, 641, 641, 615, 615, 915, 915, + 915, 915, 615, 915, 915, 915, 641, 641, + 615, 628, 615, 641, 641, 628, 628, 628, + 628, 615, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2381, 2382, 2383, 2384, 77, 2385, 2386, + 2387, 77, 2388, 2389, 2390, 2391, 2392, 2393, + 2394, 2395, 2396, 2397, 2398, 77, 2399, 2400, + 77, 75, 2401, 2402, 2403, 2404, 2405, 77, + 77, 2406, 2407, 2408, 77, 2409, 77, 2410, + 77, 2411, 77, 2412, 2413, 2414, 2415, 84, + 2416, 2417, 2418, 2419, 2420, 2421, 2422, 2423, + 2424, 2425, 2426, 77, 2427, 2428, 2429, 2430, + 2431, 2432, 75, 75, 75, 75, 2433, 2434, + 2435, 2436, 2437, 77, 75, 77, 77, 2438, + 914, 2439, 2440, 2441, 2442, 2443, 2444, 2445, + 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, + 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, + 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, + 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, + 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, + 2486, 1537, 1537, 1537, 2487, 2488, 1537, 1537, + 1537, 1537, 2489, 77, 77, 0, 0, 0, + 0, 2490, 75, 2491, 75, 2492, 79, 79, + 79, 79, 79, 2493, 2494, 77, 77, 77, + 77, 75, 77, 77, 75, 77, 77, 75, + 77, 77, 79, 79, 77, 77, 77, 2495, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 2496, 2497, + 2498, 2499, 77, 2500, 77, 2501, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 2502, 2502, 2503, 2504, 75, 75, + 75, 2505, 2506, 2502, 2507, 2508, 2502, 75, + 75, 75, 2502, 14, 85, 75, 2502, 2502, + 75, 75, 75, 2502, 2502, 2502, 2502, 75, + 2502, 2502, 2502, 2502, 2509, 2510, 2511, 2512, + 75, 75, 75, 75, 2502, 2513, 2514, 2502, + 2515, 2516, 2502, 2502, 2502, 75, 75, 75, + 75, 75, 2502, 75, 2502, 2517, 2502, 2502, + 2502, 2502, 2518, 2502, 2519, 2520, 2521, 2502, + 2522, 2523, 2524, 2502, 2502, 2502, 2525, 75, + 75, 75, 75, 2502, 2502, 2502, 2502, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 2502, 2526, 2527, 2528, 75, 2529, 2530, 2502, + 2502, 2502, 2502, 2502, 2502, 75, 2531, 2532, + 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, + 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2502, + 2502, 2548, 2549, 2550, 2551, 2552, 2553, 2554, + 2555, 2556, 2557, 2502, 2502, 2502, 75, 75, + 2502, 2502, 2558, 2559, 75, 75, 75, 75, + 75, 2502, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 2560, 2502, 75, 75, 2502, + 2502, 2561, 2562, 2502, 2563, 2564, 2565, 2566, + 2567, 2502, 2502, 2568, 2569, 2570, 2571, 2502, + 2502, 2502, 75, 75, 75, 75, 75, 2502, + 2502, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 2502, 2502, 2502, 2502, 2502, 75, + 75, 2502, 2502, 75, 75, 75, 75, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2572, 2573, 2574, 2575, 2502, 2502, 2502, + 2502, 2502, 2502, 2576, 2577, 2578, 2579, 75, + 75, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 77, 77, 77, 77, 77, 77, 77, + 77, 12, 13, 12, 13, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 2580, 2580, 77, 77, 77, + 77, 2502, 2502, 77, 77, 77, 77, 77, + 77, 79, 2581, 2582, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 77, 75, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 79, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 914, 77, + 77, 77, 77, 77, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 79, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 75, 75, 75, + 75, 75, 75, 77, 77, 77, 77, 77, + 77, 77, 2580, 2580, 2580, 2580, 79, 79, + 79, 2580, 79, 79, 2580, 77, 77, 77, + 77, 79, 79, 79, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2583, 2584, 2585, 2586, 2587, 2588, 2589, + 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, + 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, + 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, + 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, + 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, + 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, + 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, + 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, + 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, + 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, + 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, + 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, + 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, + 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, + 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, + 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, + 2718, 2719, 2720, 2721, 1289, 1289, 1289, 1289, + 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, + 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, + 1289, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 79, 79, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 79, + 75, 77, 77, 77, 77, 77, 77, 77, + 77, 79, 75, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 75, 75, 75, 2722, 2722, 2723, 2723, + 75, 79, 79, 79, 79, 79, 79, 77, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 77, 2580, 2580, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 2722, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 2580, 79, 79, 79, 79, 79, 79, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 79, 79, 79, 2580, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 2580, 79, 79, 79, 79, 79, + 79, 79, 79, 2580, 2580, 2724, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 2580, 2580, + 79, 79, 79, 79, 79, 2580, 2580, 79, + 79, 79, 79, 79, 79, 79, 79, 2580, + 79, 79, 79, 79, 79, 2580, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 2580, 79, 79, 79, 79, + 79, 79, 79, 2580, 2580, 79, 2580, 79, + 79, 79, 79, 2580, 79, 79, 2580, 79, + 79, 79, 79, 79, 79, 79, 2580, 77, + 77, 79, 79, 2580, 2580, 79, 79, 79, + 79, 79, 79, 79, 77, 79, 77, 79, + 77, 77, 77, 77, 77, 77, 79, 77, + 77, 77, 79, 77, 77, 77, 77, 77, + 77, 2580, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 79, 79, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 79, 77, 77, + 79, 77, 77, 77, 77, 2580, 77, 2580, + 77, 77, 77, 77, 2580, 2580, 2580, 77, + 2580, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 79, 79, 79, 79, + 79, 12, 13, 12, 13, 12, 13, 12, + 13, 12, 13, 12, 13, 12, 13, 1289, + 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, + 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, + 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, + 1289, 1289, 1289, 1289, 1289, 77, 2580, 2580, + 2580, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 79, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 2580, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 2580, 2502, 75, 75, 2502, 2502, 12, 13, + 75, 2502, 2502, 75, 2502, 2502, 2502, 75, + 75, 75, 75, 75, 2502, 2502, 2502, 2502, + 75, 75, 75, 75, 75, 2502, 2502, 2502, + 75, 75, 75, 2502, 2502, 2502, 2502, 12, + 13, 12, 13, 12, 13, 12, 13, 12, + 13, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 2722, 2722, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 12, 13, 12, 13, + 12, 13, 12, 13, 12, 13, 12, 13, + 12, 13, 12, 13, 12, 13, 12, 13, + 12, 13, 75, 75, 2502, 2502, 2502, 2502, + 2502, 2502, 75, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 75, 75, 75, 75, 75, 75, 75, + 75, 2502, 75, 75, 75, 75, 75, 75, + 75, 2502, 2502, 2502, 2502, 2502, 2502, 75, + 75, 75, 2502, 75, 75, 75, 75, 2502, + 2502, 2502, 2502, 2502, 75, 2502, 2502, 75, + 75, 12, 13, 12, 13, 2502, 75, 75, + 75, 75, 2502, 75, 2502, 2502, 2502, 75, + 75, 2502, 2502, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 2502, 2502, 2502, + 2502, 2502, 2502, 75, 75, 12, 13, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 2502, 2502, 2725, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 75, 2502, + 2502, 2502, 2502, 75, 75, 2502, 75, 2502, + 75, 75, 2502, 75, 2502, 2502, 2502, 2502, + 75, 75, 75, 75, 75, 2502, 2502, 75, + 75, 75, 75, 75, 75, 2502, 2502, 2502, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 2502, 2502, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 2502, 2502, 75, + 75, 75, 75, 2502, 2502, 2502, 2502, 75, + 2502, 2502, 75, 75, 2502, 2726, 2727, 2728, + 75, 75, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 75, 75, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 75, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 2502, 2502, 2502, 2502, 2502, 2502, 2502, 2502, + 75, 75, 75, 75, 75, 2729, 2730, 2502, + 75, 75, 75, 2502, 2502, 2502, 2502, 2502, + 75, 75, 75, 75, 75, 2502, 2502, 2502, + 75, 75, 75, 75, 2502, 75, 75, 75, + 2502, 2502, 2502, 2502, 2502, 75, 2502, 75, + 75, 77, 77, 77, 77, 77, 79, 79, + 79, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 2580, 2580, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 77, 77, + 75, 75, 75, 75, 75, 75, 77, 77, + 77, 2580, 77, 77, 77, 77, 2580, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 0, 0, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 0, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 2731, + 77, 2732, 2733, 2734, 2735, 2736, 2737, 2738, + 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, + 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, + 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, + 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, + 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, + 2779, 2780, 2781, 2782, 2783, 2784, 2785, 2786, + 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, + 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, + 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, + 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, + 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, + 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, + 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, + 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, + 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, + 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, + 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, + 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, + 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, + 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, + 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, + 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, + 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, + 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, + 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, + 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, + 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, + 2955, 2956, 2957, 2958, 2959, 2960, 77, 77, + 77, 77, 77, 77, 2961, 2962, 2963, 2964, + 615, 615, 615, 2965, 2966, 0, 0, 0, + 0, 0, 9, 9, 9, 9, 1289, 9, + 9, 2967, 2968, 2969, 2970, 2971, 2972, 2973, + 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, + 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, + 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, + 2998, 2999, 3000, 3001, 3002, 3003, 3004, 0, + 3005, 0, 0, 0, 0, 0, 3006, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 0, 0, 0, 0, 0, + 3007, 1120, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1300, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 9, 9, 81, 93, 81, 93, 9, + 9, 9, 81, 93, 9, 81, 93, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 1162, 9, 9, 1162, 9, 81, 93, 9, + 9, 81, 93, 12, 13, 12, 13, 12, + 13, 12, 13, 9, 9, 9, 9, 9, + 595, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 1162, 1162, 9, 9, 9, + 9, 1162, 9, 2312, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 77, 77, 9, 9, 9, 12, 13, + 12, 13, 12, 13, 12, 13, 1162, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 0, 3008, 3008, 3008, 3008, + 3009, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3010, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3011, 3012, 3013, 3014, 3015, 3016, 3017, + 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, + 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, + 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, + 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, + 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, + 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, + 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, + 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, + 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, + 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, + 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, + 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, + 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, + 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, + 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, + 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, + 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, + 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, + 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, + 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, + 3178, 3179, 3180, 3181, 3182, 3183, 3184, 3185, + 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, + 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, + 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, + 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, + 3218, 3219, 3220, 3221, 3222, 3223, 3224, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3225, 3226, 3226, 3226, 3008, 3227, 3228, + 3229, 3230, 3231, 3230, 3231, 3230, 3231, 3230, + 3231, 3230, 3231, 3008, 3008, 3230, 3231, 3230, + 3231, 3230, 3231, 3230, 3231, 3232, 3233, 3234, + 3234, 3008, 3229, 3229, 3229, 3229, 3229, 3229, + 3229, 3229, 3229, 1810, 1164, 627, 1163, 3235, + 3235, 3236, 3227, 3227, 3227, 3227, 3227, 3237, + 3008, 3238, 3239, 3240, 3227, 3228, 3241, 3008, + 77, 0, 3228, 3228, 3228, 3228, 3228, 3242, + 3228, 3228, 3228, 3228, 3243, 3244, 3245, 3246, + 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, + 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, + 3263, 3264, 3265, 3266, 3228, 3267, 3268, 3269, + 3270, 3271, 3272, 3228, 3228, 3228, 3228, 3228, + 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, + 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3288, 3228, 3228, + 0, 0, 3289, 3290, 3291, 3292, 3293, 3294, + 3295, 3232, 3228, 3228, 3228, 3228, 3228, 3296, + 3228, 3228, 3228, 3228, 3297, 3298, 3299, 3300, + 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, + 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, + 3317, 3318, 3319, 3320, 3228, 3321, 3322, 3323, + 3324, 3325, 3326, 3228, 3228, 3228, 3228, 3228, + 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, + 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3342, 3343, 3344, 3345, 3228, 3346, 3228, 3228, + 3347, 3348, 3349, 3350, 3226, 3227, 3351, 3352, + 3353, 0, 0, 0, 0, 0, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 0, 3354, 3355, 3356, 3357, 3358, 3359, + 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, + 3368, 3369, 3370, 3371, 3372, 3373, 3374, 3375, + 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, + 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, + 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, + 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, + 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, + 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, + 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, + 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, + 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, + 0, 3448, 3448, 3449, 3450, 3451, 3452, 3453, + 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, + 3462, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3008, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3463, 3464, 3465, 3466, 3467, 3468, 3469, + 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, + 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, + 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, + 0, 3494, 3495, 3496, 3497, 3498, 3499, 3500, + 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, + 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, + 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, + 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, + 3533, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 3534, 3535, 3536, 3537, 3538, 3539, 3540, + 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, + 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, + 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, + 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, + 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, + 3448, 3581, 3582, 3583, 3584, 3585, 3586, 3587, + 3588, 3589, 3590, 3591, 3592, 3593, 3594, 3595, + 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, + 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, + 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, + 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, + 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, + 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, + 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, + 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, + 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, + 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, + 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, + 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, + 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, + 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, + 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, + 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, + 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, + 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, + 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, + 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, + 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, + 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, + 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, + 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, + 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, + 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, + 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, + 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, + 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, + 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, + 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, + 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, + 3852, 3853, 3854, 3855, 3856, 3857, 3858, 3859, + 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, + 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, + 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, + 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, + 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, + 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, + 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, + 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, + 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, + 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, + 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, + 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, + 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, + 3964, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3227, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 0, 0, + 0, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 3008, 3008, 3008, 3008, 3008, 3008, 3008, 3008, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 596, 596, 596, 596, 596, 596, 1120, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 596, 9, 9, + 9, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 346, 346, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3965, 3966, 3967, 3968, 3969, 3970, 3971, + 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, + 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, + 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, + 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, + 4004, 4005, 4006, 4007, 4008, 4009, 4010, 346, + 615, 915, 915, 915, 9, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 9, + 595, 4011, 4012, 4013, 4014, 4015, 4016, 4017, + 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, + 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, + 4034, 4035, 4036, 4037, 4038, 4039, 4040, 615, + 615, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 615, 615, 1120, 1120, 1120, 1120, 1120, + 1120, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, + 595, 595, 595, 595, 595, 595, 595, 595, + 595, 47, 47, 4041, 4042, 4043, 4044, 4045, + 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, + 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, + 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, + 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, + 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, + 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, + 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, + 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, + 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, + 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, + 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, + 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, + 4142, 595, 4143, 4143, 4144, 4145, 4146, 4147, + 346, 4148, 4149, 4150, 4151, 4152, 4153, 4154, + 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, + 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, + 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, + 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, + 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, + 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, + 4203, 4204, 4205, 4206, 0, 0, 0, 0, + 0, 4207, 4208, 0, 4209, 0, 4210, 4211, + 4212, 4213, 4214, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4215, 4216, 4217, 4218, 4219, + 346, 4220, 4221, 4222, 346, 346, 346, 346, + 346, 346, 346, 1226, 346, 346, 346, 1262, + 346, 346, 346, 346, 1226, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1231, 1231, 1226, 1226, + 1231, 77, 77, 77, 77, 1300, 0, 0, + 0, 1259, 1259, 1259, 1259, 1259, 1259, 914, + 914, 11, 84, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 1231, 1231, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1262, 1226, 0, + 0, 0, 0, 0, 0, 0, 0, 1120, + 1120, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 346, 346, 346, 346, 346, + 346, 1120, 1120, 1120, 346, 1120, 346, 346, + 1226, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 1226, + 1226, 1226, 1226, 1226, 628, 628, 628, 1120, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1231, 1538, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1120, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, + 1440, 1440, 1440, 1440, 1440, 1440, 0, 0, + 0, 1226, 1226, 1226, 1231, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1250, 1231, 1231, 1226, + 1226, 1226, 1226, 1231, 1231, 1226, 1226, 1231, + 1231, 1538, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 1120, 1120, 1120, 1120, 1120, 1120, 0, + 596, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 1120, + 1120, 346, 346, 346, 346, 346, 1226, 596, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1226, 1226, 1226, 1226, 1226, 1226, + 1231, 1231, 1226, 1226, 1231, 1231, 1226, 1226, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 1226, 346, 346, 346, + 346, 346, 346, 346, 346, 1226, 1231, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 1120, 1120, 1120, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 596, 346, 346, 346, 346, 346, 346, + 914, 914, 914, 346, 1351, 1226, 1351, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 615, 346, 615, 615, 628, 346, 346, + 615, 615, 346, 346, 346, 346, 346, 615, + 615, 346, 615, 346, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 346, 346, 596, 1120, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1231, 1226, 1226, 1231, + 1231, 1120, 1120, 346, 596, 596, 1231, 1300, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 346, 346, 346, 346, 346, 346, + 0, 0, 346, 346, 346, 346, 346, 346, + 0, 0, 346, 346, 346, 346, 346, 346, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 4223, 4224, 4225, 4226, 4227, 4228, 4229, + 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, + 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, + 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, + 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, + 4262, 4263, 4264, 4265, 4143, 4266, 4267, 4268, + 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, + 4277, 4278, 4279, 47, 47, 0, 0, 0, + 0, 4280, 4281, 4282, 4283, 4284, 4285, 4286, + 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, + 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, + 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, + 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, + 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, + 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, + 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, + 4343, 4344, 4345, 4346, 4347, 4348, 4349, 4350, + 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, + 4359, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1231, 1231, 1226, 1231, + 1231, 1226, 1231, 1231, 1120, 1231, 1300, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4360, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4360, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 0, 0, 0, 0, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, + 1444, 1444, 1444, 1444, 1444, 0, 0, 0, + 0, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, + 4371, 4371, 4372, 4373, 4374, 4375, 4376, 4377, + 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, + 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, + 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401, + 4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, + 4410, 4411, 4412, 4413, 4414, 4415, 4416, 4417, + 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, + 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, + 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, + 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, + 4450, 4451, 4452, 4453, 4454, 4383, 4455, 4456, + 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, + 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, + 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, + 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, + 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, + 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, + 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, + 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, + 4521, 4522, 4473, 4523, 4524, 4525, 4526, 4527, + 4528, 4529, 4530, 4457, 4531, 4532, 4533, 4534, + 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, + 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, + 4383, 4551, 4552, 4553, 4554, 4555, 4556, 4557, + 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, + 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, + 4574, 4575, 4576, 4577, 4459, 4578, 4579, 4580, + 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, + 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, + 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, + 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, + 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, + 4621, 4622, 4623, 4624, 4625, 4626, 4627, 3228, + 3228, 4628, 3228, 4629, 3228, 3228, 4630, 4631, + 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, + 3228, 4640, 3228, 4641, 3228, 3228, 4642, 4643, + 3228, 3228, 3228, 4644, 4645, 4646, 4647, 4648, + 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, + 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, + 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, + 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, + 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, + 4512, 4689, 4690, 4691, 4692, 4693, 4694, 4694, + 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, + 4642, 4703, 4704, 4705, 4706, 4707, 4708, 0, + 0, 4709, 4710, 4711, 4712, 4713, 4714, 4715, + 4716, 4656, 4717, 4718, 4719, 4628, 4720, 4721, + 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, + 4730, 4731, 4665, 4732, 4666, 4733, 4734, 4735, + 4736, 4737, 4629, 4404, 4738, 4739, 4740, 4474, + 4561, 4741, 4742, 4673, 4743, 4674, 4744, 4745, + 4746, 4631, 4747, 4748, 4749, 4750, 4751, 4632, + 4752, 4753, 4754, 4755, 4756, 4757, 4688, 4758, + 4759, 4512, 4760, 4692, 4761, 4762, 4763, 4764, + 4765, 4697, 4766, 4641, 4767, 4698, 4455, 4768, + 4699, 4769, 4701, 4770, 4771, 4772, 4773, 4774, + 4703, 4637, 4775, 4704, 4776, 4705, 4777, 4371, + 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, + 4786, 4787, 4788, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4789, 4790, 4791, 4792, 4793, 4794, 4795, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4796, 4797, 4798, 4799, + 4800, 0, 0, 0, 0, 0, 4801, 4802, + 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, + 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, + 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, + 0, 4827, 4828, 4829, 4830, 4831, 0, 4832, + 0, 4833, 4834, 0, 4835, 4836, 0, 4837, + 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, + 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, + 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, + 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, + 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, + 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, + 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, + 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, + 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, + 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, + 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, + 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, + 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, + 4942, 4943, 4944, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4945, 4946, 4947, 4948, + 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, + 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, + 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, + 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, + 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, + 4989, 4990, 4991, 4992, 4983, 4993, 4994, 4995, + 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, + 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, + 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, + 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, + 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, + 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, + 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, + 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, + 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, + 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, + 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, + 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, + 5092, 4984, 5093, 5094, 5095, 5096, 5097, 5098, + 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, + 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, + 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, + 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, + 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, + 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, + 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, + 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, + 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, + 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, + 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, + 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, + 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, + 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, + 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, + 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, + 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, + 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, + 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, + 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, + 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, + 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, + 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, + 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, + 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, + 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, + 2312, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 5307, 5308, 5309, 5310, 5311, 5312, 5313, + 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, + 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, + 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, + 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, + 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, + 5354, 5355, 5356, 5357, 5358, 5359, 5360, 5361, + 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, + 5370, 0, 0, 5371, 5372, 5373, 5374, 5375, + 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, + 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, + 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, + 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, + 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, + 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, + 5424, 0, 0, 0, 0, 0, 0, 0, + 77, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5425, 5426, 5427, 5428, 5429, 5430, 5431, + 5432, 5433, 5434, 5435, 5436, 5437, 77, 77, + 77, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 5438, 5439, 5440, 5441, 5442, 5443, 5444, + 5445, 5446, 5447, 0, 0, 0, 0, 0, + 0, 615, 615, 615, 615, 615, 615, 615, + 628, 628, 628, 628, 628, 628, 628, 615, + 615, 5448, 5449, 5450, 5451, 5451, 5452, 5453, + 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, + 5462, 5463, 5464, 5465, 5466, 5467, 3226, 3226, + 5468, 5469, 5470, 5470, 5470, 5470, 5471, 5471, + 5471, 5472, 5473, 5474, 0, 5475, 5476, 5477, + 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, + 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, + 0, 5494, 5495, 5496, 5497, 0, 0, 0, + 0, 5498, 5499, 5500, 1192, 5501, 0, 5502, + 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, + 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, + 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, + 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, + 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, + 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, + 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, + 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, + 5567, 5568, 5569, 5570, 5571, 5572, 5573, 5574, + 5575, 5576, 5577, 5578, 5579, 5580, 5581, 5582, + 5583, 5584, 5585, 5586, 5587, 5588, 5589, 5590, + 5591, 5592, 5593, 5594, 5595, 5596, 5597, 5598, + 5599, 5600, 5601, 5602, 5603, 5604, 5605, 5606, + 5607, 5608, 5609, 5610, 5611, 5612, 5613, 5614, + 5615, 5616, 5617, 5618, 5619, 5620, 5621, 5622, + 5623, 5624, 5625, 5626, 5627, 5628, 5629, 5630, + 5631, 5632, 5633, 5634, 5635, 5636, 0, 0, + 1539, 0, 5637, 5638, 5639, 5640, 5641, 5642, + 5643, 5644, 5645, 5646, 5647, 5648, 5649, 5650, + 5651, 5652, 5653, 5654, 5655, 5656, 5657, 5658, + 5659, 5660, 5661, 5662, 5663, 5664, 5665, 5666, + 5667, 5668, 5669, 5670, 5671, 5672, 5673, 5674, + 5675, 5676, 5677, 5678, 5679, 5680, 5681, 5682, + 5683, 5684, 5685, 5686, 5687, 5688, 5689, 5690, + 5691, 5692, 5693, 5694, 5695, 5696, 5697, 5698, + 5699, 5700, 5701, 5702, 5703, 5704, 5705, 5706, + 5707, 5708, 5709, 5710, 5711, 5712, 5713, 5714, + 5715, 5716, 5717, 5718, 5719, 5720, 5721, 5722, + 5723, 5724, 5725, 5726, 5727, 5728, 5729, 5730, + 5731, 5732, 5733, 5734, 5735, 5736, 5737, 5738, + 5739, 5740, 5741, 5742, 5743, 5744, 5745, 5746, + 5747, 5748, 5749, 5750, 5751, 5752, 5753, 5754, + 5755, 5756, 5757, 5758, 5759, 5760, 5761, 5762, + 5763, 5764, 5765, 5766, 5767, 5768, 5769, 5770, + 5771, 5772, 5773, 5774, 5775, 5776, 5777, 5778, + 5779, 5780, 5781, 5782, 5783, 5784, 5785, 5786, + 5787, 5788, 5789, 5790, 5791, 5792, 5793, 5794, + 5795, 5796, 5797, 5798, 5799, 5800, 5801, 5802, + 5803, 5804, 5805, 5806, 5807, 5808, 5809, 5810, + 5811, 5812, 5813, 5814, 5815, 5816, 5817, 5818, + 5819, 5820, 5821, 5822, 5823, 5824, 5825, 5826, + 0, 0, 0, 5827, 5828, 5829, 5830, 5831, + 5832, 0, 0, 5833, 5834, 5835, 5836, 5837, + 5838, 0, 0, 5839, 5840, 5841, 5842, 5843, + 5844, 0, 0, 5845, 5846, 5847, 0, 0, + 0, 5848, 5849, 5850, 5851, 5852, 5853, 5854, + 0, 5855, 5856, 5857, 5858, 5859, 5860, 5861, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5862, 5862, 5862, 77, 77, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 346, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 0, 0, 0, + 0, 1120, 9, 1120, 0, 0, 0, 0, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 0, 0, 0, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 5863, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 5863, 1289, 1289, + 1289, 1289, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 1289, 1289, 77, 914, 914, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 0, 0, + 0, 77, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 628, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 628, 5864, 5864, 5864, 5864, 5864, 5864, + 5864, 5864, 5864, 5864, 5864, 5864, 5864, 5864, + 5864, 5864, 5864, 5864, 5864, 5864, 5864, 5864, + 5864, 5864, 5864, 5864, 5864, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 1259, 1259, 1259, 1259, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1537, 346, 346, 346, 346, 346, + 346, 346, 346, 1537, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 615, + 615, 615, 615, 615, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 1120, 1537, 1537, 1537, 1537, 1537, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5865, 5866, 5867, 5868, 5869, 5870, 5871, + 5872, 5873, 5874, 5875, 5876, 5877, 5878, 5879, + 5880, 5881, 5882, 5883, 5884, 5885, 5886, 5887, + 5888, 5889, 5890, 5891, 5892, 5893, 5894, 5895, + 5896, 5897, 5898, 5899, 5900, 5901, 5902, 5903, + 5904, 5905, 5906, 5907, 5908, 5909, 5910, 5911, + 5912, 5913, 5914, 5915, 5916, 5917, 5918, 5919, + 5920, 5921, 5922, 5923, 5924, 5925, 5926, 5927, + 5928, 5929, 5930, 5931, 5932, 5933, 5934, 5935, + 5936, 5937, 5938, 5939, 5940, 5941, 5942, 5943, + 5944, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 5945, 5946, 5947, 5948, 5949, 5950, 5951, + 5952, 5953, 5954, 5955, 5956, 5957, 5958, 5959, + 5960, 5961, 5962, 5963, 5964, 5965, 5966, 5967, + 5968, 5969, 5970, 5971, 5972, 5973, 5974, 5975, + 5976, 5977, 5978, 5979, 5980, 0, 0, 0, + 0, 5981, 5982, 5983, 5984, 5985, 5986, 5987, + 5988, 5989, 5990, 5991, 5992, 5993, 5994, 5995, + 5996, 5997, 5998, 5999, 6000, 6001, 6002, 6003, + 6004, 6005, 6006, 6007, 6008, 6009, 6010, 6011, + 6012, 6013, 6014, 6015, 6016, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1120, 6017, 6018, 6019, 6020, 6021, 6022, 6023, + 6024, 6025, 6026, 6027, 0, 6028, 6029, 6030, + 6031, 6032, 6033, 6034, 6035, 6036, 6037, 6038, + 6039, 6040, 6041, 6042, 0, 6043, 6044, 6045, + 6046, 6047, 6048, 6049, 0, 6050, 6051, 0, + 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, + 6060, 6061, 6062, 0, 6063, 6064, 6065, 6066, + 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6074, + 6075, 6076, 6077, 0, 6078, 6079, 6080, 6081, + 6082, 6083, 6084, 0, 6085, 6086, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6087, 6088, 6089, 6090, 6091, 6092, 0, + 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6100, + 6101, 6102, 6103, 6104, 6105, 6106, 6107, 6108, + 6109, 6110, 6111, 6112, 6113, 6114, 6115, 6116, + 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, + 6125, 6126, 6127, 6128, 6129, 6130, 6131, 6132, + 6133, 6134, 0, 6135, 6136, 6137, 6138, 6139, + 6140, 6141, 6142, 6143, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 0, + 0, 1183, 0, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 0, + 1183, 1183, 0, 0, 0, 1183, 0, 0, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 0, + 1180, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 6145, 6145, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 0, 0, 0, 0, 0, 0, 0, 0, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 0, 1183, 1183, 0, + 0, 0, 0, 0, 6144, 6144, 6144, 6144, + 6144, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 6144, + 6144, 6144, 6144, 6144, 6144, 0, 0, 0, + 9, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 0, 0, 0, 0, 0, + 1180, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 0, 0, 0, 0, 6144, 6144, 1183, + 1183, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 0, 0, 6144, 6144, 6144, 6144, 6144, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 1183, 1226, 1226, 1226, 0, 1226, 1226, + 0, 0, 0, 0, 0, 1226, 628, 1226, + 615, 1183, 1183, 1183, 1183, 0, 1183, 1183, + 1183, 0, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 0, + 0, 615, 641, 628, 0, 0, 0, 0, + 1300, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 6144, 0, 0, 0, 0, 0, 0, + 0, 1180, 1180, 1180, 1180, 1180, 1180, 1180, + 1180, 1180, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 6144, 6144, + 1180, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 6144, 6144, + 6144, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 6145, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 615, 628, + 0, 0, 0, 0, 6144, 6144, 6144, 6144, + 6144, 1180, 1180, 1180, 1180, 1180, 1180, 1180, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 0, + 0, 0, 9, 9, 9, 9, 9, 9, + 9, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 0, + 0, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 0, 0, 0, 0, + 0, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 0, 0, 0, 0, 0, + 0, 0, 1180, 1180, 1180, 1180, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6146, 6147, 6148, 6149, 6150, 6151, 6152, + 6153, 6154, 6155, 6156, 6157, 6158, 6159, 6160, + 6161, 6162, 6163, 6164, 6165, 6166, 6167, 6168, + 6169, 6170, 6171, 6172, 6173, 6174, 6175, 6176, + 6177, 6178, 6179, 6180, 6181, 6182, 6183, 6184, + 6185, 6186, 6187, 6188, 6189, 6190, 6191, 6192, + 6193, 6194, 6195, 6196, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6197, 6198, 6199, 6200, 6201, 6202, 6203, + 6204, 6205, 6206, 6207, 6208, 6209, 6210, 6211, + 6212, 6213, 6214, 6215, 6216, 6217, 6218, 6219, + 6220, 6221, 6222, 6223, 6224, 6225, 6226, 6227, + 6228, 6229, 6230, 6231, 6232, 6233, 6234, 6235, + 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, + 6244, 6245, 6246, 6247, 0, 0, 0, 0, + 0, 0, 0, 6144, 6144, 6144, 6144, 6144, + 6144, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 615, 615, 615, + 615, 0, 0, 0, 0, 0, 0, 0, + 0, 1210, 1210, 1210, 1210, 1210, 1210, 1210, + 1210, 1210, 1210, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 0, 615, 615, 1178, 0, + 0, 1183, 1183, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 628, 628, + 628, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 6144, 6144, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 1183, 0, 0, 0, 0, 0, 0, 0, + 0, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 628, + 628, 615, 615, 615, 628, 615, 628, 628, + 628, 628, 6249, 6249, 6249, 6249, 1187, 1187, + 1187, 1187, 1187, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 615, 628, 615, 628, 1180, + 1180, 1180, 1180, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 6144, 6144, + 6144, 6144, 6144, 6144, 6144, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1231, 1226, 1231, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1262, + 1120, 1120, 1120, 1120, 1120, 1120, 1120, 0, + 0, 0, 0, 1289, 1289, 1289, 1289, 1289, + 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, + 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1300, 346, 346, 1226, 1226, 346, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1300, 1226, 1226, 1231, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 6250, 6251, 6252, 6253, 346, 346, + 346, 346, 346, 346, 346, 346, 6254, 346, + 346, 346, 346, 346, 6255, 346, 346, 346, + 346, 1231, 1231, 1231, 1226, 1226, 1226, 1226, + 1231, 1231, 1262, 6256, 1120, 1120, 6257, 1120, + 1120, 1120, 1120, 1226, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6257, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 615, 615, 615, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 6258, 1226, 1226, 1226, 1226, 1231, 1226, 6259, + 6260, 1226, 6261, 6262, 1300, 1300, 0, 1249, + 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1120, 1120, 1120, 1120, 346, 1231, 1231, + 346, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1250, 1120, 1120, 346, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1226, 1226, 1231, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1231, 1231, 1231, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1231, 1538, 346, 1307, 1307, 346, 1120, 1120, + 1120, 1120, 1226, 1250, 1226, 1226, 1120, 1231, + 1226, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 346, 1120, 346, 1120, 1120, + 1120, 0, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 1231, 1231, 1231, + 1226, 1226, 1226, 1231, 1231, 1226, 1538, 1250, + 1226, 1120, 1120, 1120, 1120, 1120, 1120, 1226, + 346, 346, 1226, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 0, 346, 346, 346, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1120, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 1226, 1231, 1231, 1231, 1226, 1226, 1226, 1226, + 1226, 1226, 1250, 1300, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 1226, 1226, 1231, 1231, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 0, + 346, 346, 0, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 0, 346, 346, + 346, 346, 346, 0, 1250, 1250, 346, 6263, + 1231, 1226, 1231, 1231, 1231, 1231, 0, 0, + 6264, 1231, 0, 0, 6265, 6266, 1538, 0, + 0, 346, 0, 0, 0, 0, 0, 0, + 6267, 0, 0, 0, 0, 0, 346, 346, + 346, 346, 346, 1231, 1231, 0, 0, 615, + 615, 615, 615, 615, 615, 615, 0, 0, + 0, 615, 615, 615, 615, 615, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 1231, 1231, + 1231, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1231, 1231, 1262, 1226, 1226, 1231, 1250, + 346, 346, 346, 346, 1120, 1120, 1120, 1120, + 1120, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1120, 1120, 0, 1120, 615, + 346, 346, 346, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 6268, 1231, 1231, 1226, 1226, 1226, 1226, + 1226, 1226, 6269, 6270, 6271, 6272, 6273, 6274, + 1226, 1226, 1231, 1262, 1250, 346, 346, 1120, + 346, 0, 0, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 6275, 1231, 1231, 1226, 1226, 1226, 1226, 0, + 0, 6276, 6277, 6278, 6279, 1226, 1226, 1231, + 1262, 1250, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 346, 346, 346, 346, 1226, 1226, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 1231, 1231, 1231, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1231, 1231, 1226, 1231, + 1262, 1226, 1120, 1120, 1120, 346, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1226, 1231, 1226, 1231, + 1231, 1226, 1226, 1226, 1226, 1226, 1226, 1538, + 1250, 346, 1120, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 0, 1226, 1226, + 1226, 1351, 1351, 1226, 1226, 1226, 1226, 1231, + 1226, 1226, 1226, 1226, 1300, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1259, 1259, 1120, 1120, 1120, + 914, 346, 346, 346, 346, 346, 346, 346, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 1231, 1231, 1231, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1231, 1262, 1250, 1120, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6280, 6281, 6282, 6283, 6284, 6285, 6286, + 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, + 6295, 6296, 6297, 6298, 6299, 6300, 6301, 6302, + 6303, 6304, 6305, 6306, 6307, 6308, 6309, 6310, + 6311, 6312, 6313, 6314, 6315, 6316, 6317, 6318, + 6319, 6320, 6321, 6322, 6323, 6324, 6325, 6326, + 6327, 6328, 6329, 6330, 6331, 6332, 6333, 6334, + 6335, 6336, 6337, 6338, 6339, 6340, 6341, 6342, + 6343, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 0, 346, 0, 0, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 6344, 1231, 1231, 1231, 1231, 6345, 0, + 1231, 6346, 0, 0, 1226, 1226, 1538, 1300, + 1307, 1231, 1307, 1231, 1250, 1120, 1120, 1120, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1231, 1231, 1231, 1226, 1226, 1226, + 1226, 0, 0, 1226, 1226, 1231, 1231, 1231, + 1231, 1262, 346, 1120, 346, 1231, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 1226, 1226, 1226, 1226, 1226, 1226, + 6347, 6347, 1226, 1226, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1226, 1300, 1226, 1226, + 1226, 1226, 1231, 1307, 1226, 1226, 1226, 1226, + 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 1300, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 1226, 1226, 1226, 1226, 1226, 1226, + 1231, 1231, 1226, 1226, 1226, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 1307, 1307, 1307, + 1307, 1307, 1307, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1231, 1226, 1300, 1120, 1120, 1120, 346, 1120, + 1120, 1120, 1120, 1120, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, + 0, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 1120, 1120, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 1231, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 0, 1226, 1226, 1226, 1226, 1226, 1226, 1231, + 6348, 346, 1120, 1120, 1120, 1120, 1120, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 0, 0, + 0, 1120, 1120, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 0, 1231, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1231, 1226, 1226, 1231, 1226, 1226, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1226, 1226, 1226, 1226, 1226, 1226, + 0, 0, 0, 1226, 0, 1226, 1226, 0, + 1226, 1226, 1226, 1250, 1226, 1300, 1300, 1307, + 1226, 0, 0, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 0, + 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 1231, 1231, 1231, 1231, 1231, + 0, 1226, 1226, 0, 1231, 1231, 1226, 1231, + 1300, 346, 0, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 1226, 1226, 1231, 1231, + 1120, 1120, 0, 0, 0, 0, 0, 0, + 0, 1226, 1226, 1307, 1231, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 1231, 1231, 1226, + 1226, 1226, 1226, 1226, 0, 0, 0, 1231, + 1231, 1226, 1538, 1300, 1120, 1120, 1120, 1120, + 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, + 1120, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 77, 77, + 77, 77, 77, 77, 77, 77, 11, 11, + 11, 11, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, + 0, 1120, 1120, 1120, 1120, 1120, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 1120, 1120, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 6349, 6349, 6349, 6349, 6349, 6349, 6349, + 6349, 6349, 6349, 6349, 6349, 6349, 6349, 6349, + 6349, 1226, 346, 346, 346, 346, 346, 346, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 1120, + 1120, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, + 0, 641, 641, 641, 641, 641, 1120, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 615, 615, 615, 615, 615, 615, 615, + 1120, 1120, 1120, 1120, 1120, 914, 914, 914, + 914, 596, 596, 596, 596, 1120, 914, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 0, 0, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6350, 6351, 6352, 6353, 6354, 6355, 6356, + 6357, 6358, 6359, 6360, 6361, 6362, 6363, 6364, + 6365, 6366, 6367, 6368, 6369, 6370, 6371, 6372, + 6373, 6374, 6375, 6376, 6377, 6378, 6379, 6380, + 6381, 6382, 6383, 6384, 6385, 6386, 6387, 6388, + 6389, 6390, 6391, 6392, 6393, 6394, 6395, 6396, + 6397, 6398, 6399, 6400, 6401, 6402, 6403, 6404, + 6405, 6406, 6407, 6408, 6409, 6410, 6411, 6412, + 6413, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1120, 1120, 1120, 1120, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 0, 0, 0, + 1226, 346, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 0, 0, 0, 0, 0, 0, 0, + 1226, 1226, 1226, 1226, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, + 596, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3226, 3227, 1226, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6414, 6414, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 0, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 0, 3227, 3227, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3228, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 0, 0, 3228, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3228, 3228, 3228, + 3228, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 0, 914, 1226, 641, + 1120, 1539, 1539, 1539, 1539, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 0, + 0, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 0, 0, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 6415, 6416, 914, 914, 914, 914, 914, 6417, + 6418, 6419, 6420, 6421, 6422, 6423, 6424, 6425, + 641, 641, 641, 914, 914, 914, 6426, 6427, + 6428, 6429, 6430, 6431, 1539, 1539, 1539, 1539, + 1539, 1539, 1539, 1539, 628, 628, 628, 628, + 628, 628, 628, 628, 914, 914, 615, 615, + 615, 615, 615, 628, 628, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 615, 615, 615, 615, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 6432, 6433, 6434, 6435, 6436, 6437, + 6438, 6439, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 77, 77, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 615, 615, 615, 77, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, + 1259, 1259, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6440, 6441, 6442, 6443, 6444, 6445, 6446, + 6447, 6448, 6449, 6450, 6451, 6452, 6453, 6454, + 6455, 6456, 6457, 6458, 6459, 6460, 6461, 6462, + 6463, 6464, 6465, 6466, 6467, 6468, 6469, 6470, + 6471, 6472, 6473, 6474, 6475, 6476, 6477, 6478, + 6479, 6480, 6481, 6482, 6483, 6484, 6485, 6486, + 6487, 6488, 6489, 6490, 6491, 6492, 6493, 6494, + 6495, 6496, 6497, 6498, 6499, 6500, 6501, 6502, + 6503, 6504, 6505, 6506, 6507, 6508, 6509, 6510, + 6511, 6512, 6513, 6514, 6515, 6516, 6517, 6518, + 6519, 6520, 6521, 6522, 6523, 6524, 0, 6525, + 6526, 6527, 6528, 6529, 6530, 6531, 6532, 6533, + 6534, 6535, 6536, 6537, 6538, 6539, 6540, 6541, + 6542, 6543, 6544, 6545, 6546, 6547, 6548, 6549, + 6550, 6551, 6552, 6553, 6554, 6555, 6556, 6557, + 6558, 6559, 6560, 6561, 6562, 6563, 6564, 6565, + 6566, 6567, 6568, 6569, 6570, 6571, 6572, 6573, + 6574, 6575, 6576, 6577, 6578, 6579, 6580, 6581, + 6582, 6583, 6584, 6585, 6586, 6587, 6588, 6589, + 6590, 6591, 6592, 6593, 6594, 6595, 0, 6596, + 6597, 0, 0, 6598, 0, 0, 6599, 6600, + 0, 0, 6601, 6602, 6603, 6604, 0, 6605, + 6606, 6607, 6608, 6609, 6610, 6611, 6612, 6613, + 6614, 6615, 6616, 0, 6617, 0, 6618, 6619, + 6620, 6621, 6622, 6623, 6624, 0, 6625, 6626, + 6627, 6628, 6629, 6630, 6631, 6632, 6633, 6634, + 6635, 6636, 6637, 6638, 6639, 6640, 6641, 6642, + 6643, 6644, 6645, 6646, 6647, 6648, 6649, 6650, + 6651, 6652, 6653, 6654, 6655, 6656, 6657, 6658, + 6659, 6660, 6661, 6662, 6663, 6664, 6665, 6666, + 6667, 6668, 6669, 6670, 6671, 6672, 6673, 6674, + 6675, 6676, 6677, 6678, 6679, 6680, 6681, 6682, + 6683, 6684, 6685, 6686, 6687, 6688, 6689, 0, + 6690, 6691, 6692, 6693, 0, 0, 6694, 6695, + 6696, 6697, 6698, 6699, 6700, 6701, 0, 6702, + 6703, 6704, 6705, 6706, 6707, 6708, 0, 6709, + 6710, 6711, 6712, 6713, 6714, 6715, 6716, 6717, + 6718, 6719, 6720, 6721, 6722, 6723, 6724, 6725, + 6726, 6727, 6728, 6729, 6730, 6731, 6732, 6733, + 6734, 6735, 6736, 0, 6737, 6738, 6739, 6740, + 0, 6741, 6742, 6743, 6744, 6745, 0, 6746, + 0, 0, 0, 6747, 6748, 6749, 6750, 6751, + 6752, 6753, 0, 6754, 6755, 6756, 6757, 6758, + 6759, 6760, 6761, 6762, 6763, 6764, 6765, 6766, + 6767, 6768, 6769, 6770, 6771, 6772, 6773, 6774, + 6775, 6776, 6777, 6778, 6779, 6780, 6781, 6782, + 6783, 6784, 6785, 6786, 6787, 6788, 6789, 6790, + 6791, 6792, 6793, 6794, 6795, 6796, 6797, 6798, + 6799, 6800, 6801, 6802, 6803, 6804, 6805, 6806, + 6807, 6808, 6809, 6810, 6811, 6812, 6813, 6814, + 6815, 6816, 6817, 6818, 6819, 6820, 6821, 6822, + 6823, 6824, 6825, 6826, 6827, 6828, 6829, 6830, + 6831, 6832, 6833, 6834, 6835, 6836, 6837, 6838, + 6839, 6840, 6841, 6842, 6843, 6844, 6845, 6846, + 6847, 6848, 6849, 6850, 6851, 6852, 6853, 6854, + 6855, 6856, 6857, 6858, 6859, 6860, 6861, 6862, + 6863, 6864, 6865, 6866, 6867, 6868, 6869, 6870, + 6871, 6872, 6873, 6874, 6875, 6876, 6877, 6878, + 6879, 6880, 6881, 6882, 6883, 6884, 6885, 6886, + 6887, 6888, 6889, 6890, 6891, 6892, 6893, 6894, + 6895, 6896, 6897, 6898, 6899, 6900, 6901, 6902, + 6903, 6904, 6905, 6906, 6907, 6908, 6909, 6910, + 6911, 6912, 6913, 6914, 6915, 6916, 6917, 6918, + 6919, 6920, 6921, 6922, 6923, 6924, 6925, 6926, + 6927, 6928, 6929, 6930, 6931, 6932, 6933, 6934, + 6935, 6936, 6937, 6938, 6939, 6940, 6941, 6942, + 6943, 6944, 6945, 6946, 6947, 6948, 6949, 6950, + 6951, 6952, 6953, 6954, 6955, 6956, 6957, 6958, + 6959, 6960, 6961, 6962, 6963, 6964, 6965, 6966, + 6967, 6968, 6969, 6970, 6971, 6972, 6973, 6974, + 6975, 6976, 6977, 6978, 6979, 6980, 6981, 6982, + 6983, 6984, 6985, 6986, 6987, 6988, 6989, 6990, + 6991, 6992, 6993, 6994, 6995, 6996, 6997, 6998, + 6999, 7000, 7001, 7002, 7003, 7004, 7005, 7006, + 7007, 7008, 7009, 7010, 7011, 7012, 7013, 7014, + 7015, 7016, 7017, 7018, 7019, 7020, 7021, 7022, + 7023, 7024, 7025, 7026, 7027, 7028, 7029, 7030, + 7031, 7032, 7033, 7034, 7035, 7036, 7037, 7038, + 7039, 7040, 7041, 7042, 7043, 7044, 7045, 7046, + 7047, 7048, 7049, 7050, 7051, 7052, 7053, 7054, + 7055, 7056, 7057, 7058, 7059, 7060, 7061, 7062, + 7063, 7064, 7065, 7066, 7067, 7068, 7069, 7070, + 7071, 7072, 7073, 7074, 7075, 7076, 7077, 7078, + 7079, 7080, 7081, 7082, 7083, 7084, 7085, 7086, + 7087, 7088, 7089, 7090, 7091, 7092, 7093, 0, + 0, 7094, 7095, 7096, 7097, 7098, 7099, 7100, + 7101, 7102, 7103, 7104, 7105, 7106, 7107, 7108, + 7109, 7110, 7111, 7112, 7113, 7114, 7115, 7116, + 7117, 7118, 7119, 7120, 7121, 7122, 7123, 7124, + 7125, 7126, 7127, 7128, 7129, 7130, 7131, 7132, + 7133, 7134, 7135, 7136, 7137, 7138, 7139, 7140, + 7141, 7142, 7143, 7144, 7145, 7146, 7147, 7148, + 7149, 7150, 7151, 7152, 7153, 7154, 7155, 7156, + 7157, 7158, 7159, 7160, 7161, 7162, 7163, 7164, + 7165, 7166, 7167, 7168, 7169, 7170, 7171, 7172, + 7173, 7174, 7175, 7176, 7119, 7177, 7178, 7179, + 7180, 7181, 7182, 7183, 7184, 7185, 7186, 7187, + 7188, 7189, 7190, 7191, 7192, 7193, 7194, 7195, + 7196, 7197, 7198, 7199, 7200, 7201, 7145, 7202, + 7203, 7204, 7205, 7206, 7207, 7208, 7209, 7210, + 7211, 7212, 7213, 7214, 7215, 7216, 7217, 7218, + 7219, 7220, 7221, 7222, 7223, 7224, 7225, 7226, + 7227, 7228, 7229, 7230, 7231, 7232, 7119, 7233, + 7234, 7235, 7236, 7237, 7238, 7239, 7240, 7241, + 7242, 7243, 7244, 7245, 7246, 7247, 7248, 7249, + 7250, 7251, 7252, 7253, 7254, 7255, 7256, 7257, + 7145, 7258, 7259, 7260, 7261, 7262, 7263, 7264, + 7265, 7266, 7267, 7268, 7269, 7270, 7271, 7272, + 7273, 7274, 7275, 7276, 7277, 7278, 7279, 7280, + 7281, 7282, 7283, 7284, 7285, 7286, 7287, 7288, + 7119, 7289, 7290, 7291, 7292, 7293, 7294, 7295, + 7296, 7297, 7298, 7299, 7300, 7301, 7302, 7303, + 7304, 7305, 7306, 7307, 7308, 7309, 7310, 7311, + 7312, 7313, 7145, 7314, 7315, 7316, 7317, 7318, + 7319, 7320, 7321, 7322, 7323, 7324, 7325, 7326, + 7327, 7328, 7329, 7330, 7331, 7332, 7333, 7334, + 7335, 7336, 7337, 7338, 7339, 7340, 7341, 7342, + 7343, 7344, 7119, 7345, 7346, 7347, 7348, 7349, + 7350, 7351, 7352, 7353, 7354, 7355, 7356, 7357, + 7358, 7359, 7360, 7361, 7362, 7363, 7364, 7365, + 7366, 7367, 7368, 7369, 7145, 7370, 7371, 7372, + 7373, 7374, 7375, 7376, 7377, 0, 0, 7378, + 7379, 7380, 7381, 7382, 7383, 7384, 7385, 7386, + 7387, 7378, 7379, 7380, 7381, 7382, 7383, 7384, + 7385, 7386, 7387, 7378, 7379, 7380, 7381, 7382, + 7383, 7384, 7385, 7386, 7387, 7378, 7379, 7380, + 7381, 7382, 7383, 7384, 7385, 7386, 7387, 7378, + 7379, 7380, 7381, 7382, 7383, 7384, 7385, 7386, + 7387, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 914, 914, 914, 914, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 914, 914, + 914, 914, 914, 914, 914, 914, 1226, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 1226, 914, 914, + 1120, 1120, 1120, 1120, 1120, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1226, 1226, 1226, 1226, + 1226, 0, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7388, 7389, 7390, 7391, 7392, 7393, 7394, + 7395, 7396, 7397, 346, 7398, 7399, 7400, 7401, + 7402, 7403, 7404, 7405, 7406, 7407, 7408, 7409, + 7410, 7411, 7412, 7413, 7414, 7415, 7416, 7417, + 0, 0, 0, 0, 0, 0, 7418, 7419, + 7420, 7421, 7422, 7423, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 615, 615, 615, 615, 615, 615, 615, + 0, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 0, 0, 615, 615, 615, 615, + 615, 615, 615, 0, 615, 615, 0, 615, + 615, 615, 615, 615, 0, 0, 0, 0, + 0, 7424, 7425, 7426, 7427, 7428, 7429, 7430, + 7431, 7432, 7433, 7434, 7435, 7436, 7437, 7438, + 7439, 7440, 7441, 7442, 7443, 7444, 7445, 7446, + 7447, 7448, 7449, 7450, 7451, 7452, 7453, 7454, + 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, + 7463, 7464, 7465, 7466, 7467, 7468, 7469, 7470, + 7471, 7472, 7473, 7474, 7475, 7476, 7477, 7478, + 7479, 7480, 7481, 7482, 7483, 7484, 7485, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 615, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 0, 0, + 0, 615, 615, 615, 615, 615, 615, 615, + 596, 596, 596, 596, 596, 596, 596, 0, + 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 346, + 914, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 615, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 615, 615, 615, + 615, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 596, 627, 627, 628, + 615, 1249, 1249, 1249, 1249, 1249, 1249, 1249, + 1249, 1249, 1249, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 346, 346, 346, 346, 346, 346, 346, + 0, 346, 346, 346, 346, 0, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1183, 1183, 1183, 1183, 1183, 0, 0, + 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, + 6144, 628, 628, 628, 628, 628, 628, 628, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7486, 7487, 7488, 7489, 7490, 7491, 7492, + 7493, 7494, 7495, 7496, 7497, 7498, 7499, 7500, + 7501, 7502, 7503, 7504, 7505, 7506, 7507, 7508, + 7509, 7510, 7511, 7512, 7513, 7514, 7515, 7516, + 7517, 7518, 7519, 7520, 7521, 7522, 7523, 7524, + 7525, 7526, 7527, 7528, 7529, 7530, 7531, 7532, + 7533, 7534, 7535, 7536, 7537, 7538, 7539, 7540, + 7541, 7542, 7543, 7544, 7545, 7546, 7547, 7548, + 7549, 7550, 7551, 7552, 7553, 615, 615, 615, + 615, 615, 615, 1250, 1228, 0, 0, 0, + 0, 1227, 1227, 1227, 1227, 1227, 1227, 1227, + 1227, 1227, 1227, 0, 0, 0, 0, 1180, + 1180, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 1223, 6249, 6249, + 6249, 1186, 6249, 6249, 6249, 6249, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 1223, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 6249, + 6249, 6249, 6249, 6249, 6249, 6249, 6249, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7554, 7555, 7556, 7557, 0, 7558, 7559, + 7560, 7561, 7562, 7563, 7564, 7565, 7566, 7567, + 7568, 7569, 7570, 7571, 7572, 7573, 7574, 7575, + 7576, 7577, 7578, 7579, 7580, 7581, 7582, 7583, + 7584, 0, 7555, 7556, 0, 7585, 0, 0, + 7560, 0, 7562, 7563, 7564, 7565, 7566, 7567, + 7568, 7569, 7570, 7571, 0, 7573, 7574, 7575, + 7576, 0, 7578, 0, 7580, 0, 0, 0, + 0, 0, 0, 7556, 0, 0, 0, 0, + 7560, 0, 7562, 0, 7564, 0, 7566, 7567, + 7568, 0, 7570, 7571, 0, 7573, 0, 0, + 7576, 0, 7578, 0, 7580, 0, 7582, 0, + 7584, 0, 7555, 7556, 0, 7585, 0, 0, + 7560, 7561, 7562, 7563, 0, 7565, 7566, 7567, + 7568, 7569, 7570, 7571, 0, 7573, 7574, 7575, + 7576, 0, 7578, 7579, 7580, 7581, 0, 7583, + 0, 7554, 7555, 7556, 7557, 7585, 7558, 7559, + 7560, 7561, 7562, 0, 7564, 7565, 7566, 7567, + 7568, 7569, 7570, 7571, 7572, 7573, 7574, 7575, + 7576, 7577, 7578, 7579, 7580, 0, 0, 0, + 0, 0, 7555, 7556, 7557, 0, 7558, 7559, + 7560, 7561, 7562, 0, 7564, 7565, 7566, 7567, + 7568, 7569, 7570, 7571, 7572, 7573, 7574, 7575, + 7576, 7577, 7578, 7579, 7580, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 75, 75, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 79, 79, 79, 79, 2580, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 0, 0, 0, + 0, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 0, 0, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 0, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 2580, 0, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7586, 7587, 7588, 7589, 7590, 7591, 7592, + 7593, 7594, 7595, 7596, 1289, 1289, 79, 79, + 79, 7597, 7598, 7599, 7600, 7601, 7602, 7603, + 7604, 7605, 7606, 7607, 7608, 7609, 7610, 7611, + 7612, 7613, 7614, 7615, 7616, 7617, 7618, 7619, + 7620, 7621, 7622, 7623, 7624, 7625, 7626, 7627, + 79, 7628, 7629, 7630, 7631, 7632, 7633, 7634, + 7635, 7636, 7637, 7638, 7639, 7640, 7641, 7642, + 7643, 7644, 7645, 7646, 7647, 7648, 7649, 7650, + 7651, 7652, 7653, 7654, 7655, 7656, 7657, 7658, + 7659, 7660, 7661, 7662, 7663, 7664, 7665, 7666, + 7667, 7668, 7669, 7670, 7671, 7672, 7673, 7674, + 7675, 7676, 7677, 7678, 7679, 7680, 7681, 7682, + 7683, 7684, 7685, 7686, 7687, 7688, 79, 79, + 79, 7689, 7690, 7691, 7692, 7693, 7694, 7695, + 7696, 7697, 7698, 7699, 7700, 7701, 7702, 7703, + 7704, 7705, 7706, 7707, 7708, 7709, 7710, 7711, + 7712, 7713, 7714, 914, 914, 914, 914, 7715, + 914, 7716, 7715, 7715, 7715, 7715, 7715, 7715, + 7715, 7715, 7715, 7715, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 914, 914, + 914, 914, 914, 914, 914, 914, 79, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7717, + 7717, 7717, 7717, 7717, 7717, 7717, 7717, 7717, + 7717, 7717, 7717, 7717, 7717, 7717, 7717, 7717, + 7717, 7717, 7717, 7717, 7717, 7717, 7717, 7717, + 7717, 7718, 7719, 7720, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7721, 7722, 7723, 7724, 7725, 7726, 7727, + 7728, 7729, 7730, 7731, 7732, 7733, 7734, 7735, + 7736, 7737, 7738, 7739, 7740, 7741, 7742, 7743, + 7744, 7745, 7746, 7747, 7748, 7749, 7750, 7751, + 7752, 7753, 7754, 7755, 7756, 7757, 7758, 7759, + 7760, 7761, 7762, 7763, 7764, 0, 0, 0, + 0, 7765, 7766, 7767, 7768, 7769, 7770, 7771, + 7772, 7773, 0, 0, 0, 0, 0, 0, + 0, 7774, 7775, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2580, 2580, 2580, 2580, 2580, 2580, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 79, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 79, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 79, 79, 79, 79, + 2580, 2580, 2580, 2580, 2580, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 79, 79, 79, 2580, 79, 79, + 79, 2580, 2580, 2580, 7776, 7776, 7776, 7776, + 7776, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 79, 2580, 79, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 79, 79, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 77, + 77, 77, 77, 77, 77, 77, 77, 79, + 79, 79, 79, 79, 2580, 2580, 2580, 2580, + 79, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 2580, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 2580, 2580, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 2580, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 79, + 79, 79, 79, 79, 79, 2580, 79, 79, + 79, 2580, 2580, 2580, 79, 79, 2580, 2580, + 2580, 0, 0, 0, 0, 2580, 2580, 2580, + 2580, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 2580, 2580, 0, 0, + 0, 79, 79, 79, 79, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 79, 79, 79, + 0, 0, 0, 0, 79, 79, 79, 79, + 79, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 79, 79, + 79, 79, 79, 0, 0, 0, 0, 0, + 0, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 0, 0, 0, + 0, 2580, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 0, + 0, 79, 79, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 77, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 77, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 0, + 0, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 0, 0, + 0, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 0, 0, 0, 0, 0, 0, + 0, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 0, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 0, + 0, 0, 0, 0, 0, 0, 0, 2580, + 2580, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 2580, 2580, 2580, 0, 0, 0, + 0, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 0, 0, 0, 0, 0, 0, + 0, 2580, 2580, 2580, 2580, 2580, 2580, 2580, + 2580, 2580, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 0, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7378, 7379, 7380, 7381, 7382, 7383, 7384, + 7385, 7386, 7387, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7777, 7778, 7779, 7780, 7781, 4650, 7782, + 7783, 7784, 7785, 4651, 7786, 7787, 7788, 4652, + 7789, 7790, 7791, 7792, 7793, 7794, 7795, 7796, + 7797, 7798, 7799, 7800, 4710, 7801, 7802, 7803, + 7804, 7805, 7806, 7807, 7808, 7809, 4715, 4653, + 4654, 4716, 7810, 7811, 4461, 7812, 4655, 7813, + 7814, 7815, 7816, 7816, 7816, 7817, 7818, 7819, + 7820, 7821, 7822, 7823, 7824, 7825, 7826, 7827, + 7828, 7829, 7830, 7831, 7832, 7833, 7834, 7834, + 4718, 7835, 7836, 7837, 7838, 4657, 7839, 7840, + 7841, 4614, 7842, 7843, 7844, 7845, 7846, 7847, + 7848, 7849, 7850, 7851, 7852, 7853, 7854, 7855, + 7856, 7857, 7858, 7859, 7860, 7861, 7862, 7863, + 7864, 7865, 7866, 7867, 7867, 7868, 7869, 7870, + 4457, 7871, 7872, 7873, 7874, 7875, 7876, 7877, + 7878, 4662, 7879, 7880, 7881, 7882, 7883, 7884, + 7885, 7886, 7887, 7888, 7889, 7890, 7891, 7892, + 7893, 7894, 7895, 7896, 7897, 7898, 7899, 4403, + 7900, 7901, 7902, 7902, 7903, 7904, 7904, 7905, + 7906, 7907, 7908, 7909, 7910, 7911, 7912, 7913, + 7914, 7915, 7916, 7917, 4663, 7918, 7919, 7920, + 7921, 4730, 7921, 7922, 4665, 7923, 7924, 7925, + 7926, 4666, 4376, 7927, 7928, 7929, 7930, 7931, + 7932, 7933, 7934, 7935, 7936, 7937, 7938, 7939, + 7940, 7941, 7942, 7943, 7944, 7945, 7946, 7947, + 7948, 4667, 7949, 7950, 7951, 7952, 7953, 7954, + 4669, 7955, 7956, 7957, 7958, 7959, 7960, 7961, + 7962, 4404, 4738, 7963, 7964, 7965, 7966, 7967, + 7968, 7969, 7970, 4670, 7971, 7972, 7973, 7974, + 4781, 7975, 7976, 7977, 7978, 7979, 7980, 7981, + 7982, 7983, 7984, 7985, 7986, 7987, 4474, 7988, + 7989, 7990, 7991, 7992, 7993, 7994, 7995, 7996, + 7997, 7998, 4671, 4561, 7999, 8000, 8001, 8002, + 8003, 8004, 8005, 8006, 4742, 8007, 8008, 8009, + 8010, 8011, 8012, 8013, 8014, 4743, 8015, 8016, + 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8024, + 8025, 8026, 4745, 8027, 8028, 8029, 8030, 8031, + 8032, 8033, 8034, 8035, 8036, 8037, 8037, 8038, + 8039, 4747, 8040, 8041, 8042, 8043, 8044, 8045, + 8046, 4460, 8047, 8048, 8049, 8050, 8051, 8052, + 8053, 4753, 8054, 8055, 8056, 8057, 8058, 8059, + 8059, 4754, 4783, 8060, 8061, 8062, 8063, 8064, + 4422, 4756, 8065, 8066, 4682, 8067, 8068, 4636, + 8069, 8070, 4686, 8071, 8072, 8073, 8074, 8074, + 8075, 8076, 8077, 8078, 8079, 8080, 8081, 8082, + 8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090, + 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, + 8099, 8100, 8101, 4692, 8102, 8103, 8104, 8105, + 8106, 8107, 8108, 8109, 8110, 8111, 8112, 8113, + 8114, 8115, 8116, 8117, 7903, 8118, 8119, 8120, + 8121, 8122, 8123, 8124, 8125, 8126, 8127, 8128, + 8129, 4478, 8130, 8131, 8132, 8133, 8134, 8135, + 4695, 8136, 8137, 8138, 8139, 8140, 8141, 8142, + 8143, 8144, 8145, 8146, 8147, 8148, 8149, 8150, + 8151, 8152, 8153, 8154, 8155, 4417, 8156, 8157, + 8158, 8159, 8160, 8161, 4763, 8162, 8163, 8164, + 8165, 8166, 8167, 8168, 8169, 8170, 8171, 8172, + 8173, 8174, 8175, 8176, 8177, 8178, 8179, 8180, + 8181, 4768, 4769, 8182, 8183, 8184, 8185, 8186, + 8187, 8188, 8189, 8190, 8191, 8192, 8193, 8194, + 4770, 8195, 8196, 8197, 8198, 8199, 8200, 8201, + 8202, 8203, 8204, 8205, 8206, 8207, 8208, 8209, + 8210, 8211, 8212, 8213, 8214, 8215, 8216, 8217, + 8218, 8219, 8220, 8221, 8222, 8223, 8224, 4776, + 4776, 8225, 8226, 8227, 8228, 8229, 8230, 8231, + 8232, 8233, 8234, 4777, 8235, 8236, 8237, 8238, + 8239, 8240, 8241, 8242, 8243, 8244, 8245, 8246, + 8247, 8248, 8249, 8250, 8251, 8252, 8253, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 0, 0, 0, 0, + 0, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1539, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 649, + 649, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 4363, + 4363, 4363, 4363, 4363, 4363, 4363, 4363, 0, + 0, }; + +static const utf8proc_property_t utf8proc_properties[] = { + {0, 0, 0, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false,false,false,false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_S, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_LF, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CR, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5093, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5084, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5096, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 0, UINT16_MAX, 0, UINT16_MAX, 0, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1, UINT16_MAX, 1, UINT16_MAX, 2784, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2, UINT16_MAX, 2, UINT16_MAX, 49, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3, UINT16_MAX, 3, UINT16_MAX, 704, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4, UINT16_MAX, 4, UINT16_MAX, 62, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5, UINT16_MAX, 5, UINT16_MAX, 2872, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6, UINT16_MAX, 6, UINT16_MAX, 782, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7, UINT16_MAX, 7, UINT16_MAX, 808, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8, UINT16_MAX, 8, UINT16_MAX, 111, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9, UINT16_MAX, 9, UINT16_MAX, 898, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 10, UINT16_MAX, 10, UINT16_MAX, 913, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 11, UINT16_MAX, 11, UINT16_MAX, 999, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 12, UINT16_MAX, 12, UINT16_MAX, 2890, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 13, UINT16_MAX, 13, UINT16_MAX, 160, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 14, UINT16_MAX, 14, UINT16_MAX, 205, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 15, UINT16_MAX, 15, UINT16_MAX, 2982, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 16, UINT16_MAX, 16, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 17, UINT16_MAX, 17, UINT16_MAX, 1087, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 18, UINT16_MAX, 18, UINT16_MAX, 1173, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 19, UINT16_MAX, 19, UINT16_MAX, 1257, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 20, UINT16_MAX, 20, UINT16_MAX, 254, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 21, UINT16_MAX, 21, UINT16_MAX, 3042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 22, UINT16_MAX, 22, UINT16_MAX, 1337, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 23, UINT16_MAX, 23, UINT16_MAX, 3122, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 24, UINT16_MAX, 24, UINT16_MAX, 303, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 25, UINT16_MAX, 25, UINT16_MAX, 1423, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1491, UINT16_MAX, 1491, 352, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1493, UINT16_MAX, 1493, 2818, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2813, UINT16_MAX, 2813, 401, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1494, UINT16_MAX, 1494, 743, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1495, UINT16_MAX, 1495, 414, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2838, UINT16_MAX, 2838, 2875, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1497, UINT16_MAX, 1497, 795, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1498, UINT16_MAX, 1498, 853, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1499, UINT16_MAX, 1499, 463, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1500, UINT16_MAX, 1500, 901, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1501, UINT16_MAX, 1501, 956, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1502, UINT16_MAX, 1502, 1043, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1503, UINT16_MAX, 1503, 2932, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1504, UINT16_MAX, 1504, 512, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1505, UINT16_MAX, 1505, 557, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1507, UINT16_MAX, 1507, 2994, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2827, UINT16_MAX, 2827, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1508, UINT16_MAX, 1508, 1130, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3320, UINT16_MAX, 3320, 1215, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1509, UINT16_MAX, 1509, 1296, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1510, UINT16_MAX, 1510, 606, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2910, UINT16_MAX, 2910, 3082, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1511, UINT16_MAX, 1511, 1380, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2928, UINT16_MAX, 2928, 3131, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3327, UINT16_MAX, 3327, 655, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2835, UINT16_MAX, 2835, 1466, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_NOBREAK, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 16411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 1621, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 0, UINT16_MAX, 8289, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 1, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 16413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 16417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35, 35, 7440, UINT16_MAX, 7440, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 16420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 14, UINT16_MAX, 8290, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 32807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 32810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 32813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16432, 50, UINT16_MAX, 50, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16435, 53, UINT16_MAX, 53, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16438, 56, UINT16_MAX, 56, UINT16_MAX, 3143, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16441, 59, UINT16_MAX, 59, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16444, 62, UINT16_MAX, 62, UINT16_MAX, 1537, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16447, 65, UINT16_MAX, 65, UINT16_MAX, 1579, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 66, UINT16_MAX, 66, UINT16_MAX, 1549, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16451, 69, UINT16_MAX, 69, UINT16_MAX, 2852, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16454, 72, UINT16_MAX, 72, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16457, 75, UINT16_MAX, 75, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16460, 78, UINT16_MAX, 78, UINT16_MAX, 3357, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16463, 81, UINT16_MAX, 81, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16466, 84, UINT16_MAX, 84, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16469, 87, UINT16_MAX, 87, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16472, 90, UINT16_MAX, 90, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16475, 93, UINT16_MAX, 93, UINT16_MAX, 2878, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 94, UINT16_MAX, 94, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16479, 97, UINT16_MAX, 97, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16482, 100, UINT16_MAX, 100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16485, 103, UINT16_MAX, 103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16488, 106, UINT16_MAX, 106, UINT16_MAX, 3461, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16491, 109, UINT16_MAX, 109, UINT16_MAX, 1597, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16494, 112, UINT16_MAX, 112, UINT16_MAX, 1591, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 113, UINT16_MAX, 113, UINT16_MAX, 1585, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16498, 116, UINT16_MAX, 116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16501, 119, UINT16_MAX, 119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16504, 122, UINT16_MAX, 122, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16507, 125, UINT16_MAX, 125, UINT16_MAX, 1509, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16510, 128, UINT16_MAX, 128, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 129, UINT16_MAX, 129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 16514, 8291, UINT16_MAX, 8291, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16516, UINT16_MAX, 8292, UINT16_MAX, 8292, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16518, UINT16_MAX, 8293, UINT16_MAX, 8293, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16520, UINT16_MAX, 8294, UINT16_MAX, 8294, 3192, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16522, UINT16_MAX, 8295, UINT16_MAX, 8295, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16524, UINT16_MAX, 8296, UINT16_MAX, 8296, 1540, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16526, UINT16_MAX, 2837, UINT16_MAX, 2837, 1582, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1492, UINT16_MAX, 1492, 1558, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16528, UINT16_MAX, 8297, UINT16_MAX, 8297, 2855, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16530, UINT16_MAX, 8298, UINT16_MAX, 8298, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16532, UINT16_MAX, 8299, UINT16_MAX, 8299, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16534, UINT16_MAX, 8300, UINT16_MAX, 8300, 3406, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16536, UINT16_MAX, 8301, UINT16_MAX, 8301, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16538, UINT16_MAX, 8302, UINT16_MAX, 8302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16540, UINT16_MAX, 8303, UINT16_MAX, 8303, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16542, UINT16_MAX, 8304, UINT16_MAX, 8304, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16544, UINT16_MAX, 8305, UINT16_MAX, 8305, 2881, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8306, UINT16_MAX, 8306, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16546, UINT16_MAX, 8307, UINT16_MAX, 8307, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16548, UINT16_MAX, 8308, UINT16_MAX, 8308, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16550, UINT16_MAX, 8309, UINT16_MAX, 8309, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16552, UINT16_MAX, 8310, UINT16_MAX, 8310, 3510, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16554, UINT16_MAX, 8311, UINT16_MAX, 8311, 1606, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16556, UINT16_MAX, 8312, UINT16_MAX, 8312, 1594, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8313, UINT16_MAX, 8313, 1588, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16558, UINT16_MAX, 8314, UINT16_MAX, 8314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16560, UINT16_MAX, 8315, UINT16_MAX, 8315, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16562, UINT16_MAX, 8316, UINT16_MAX, 8316, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16564, UINT16_MAX, 8317, UINT16_MAX, 8317, 1523, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16566, UINT16_MAX, 8318, UINT16_MAX, 8318, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8319, UINT16_MAX, 8319, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16568, UINT16_MAX, 8320, UINT16_MAX, 8320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16570, 188, UINT16_MAX, 188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16573, UINT16_MAX, 8321, UINT16_MAX, 8321, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16575, 193, UINT16_MAX, 193, UINT16_MAX, 3259, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16578, UINT16_MAX, 8322, UINT16_MAX, 8322, 3308, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16580, 198, UINT16_MAX, 198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16583, UINT16_MAX, 8323, UINT16_MAX, 8323, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16585, 203, UINT16_MAX, 203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16588, UINT16_MAX, 8324, UINT16_MAX, 8324, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16590, 208, UINT16_MAX, 208, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16593, UINT16_MAX, 8325, UINT16_MAX, 8325, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16595, 213, UINT16_MAX, 213, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16598, UINT16_MAX, 8326, UINT16_MAX, 8326, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16600, 218, UINT16_MAX, 218, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16603, UINT16_MAX, 8327, UINT16_MAX, 8327, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16605, 223, UINT16_MAX, 223, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16608, UINT16_MAX, 8328, UINT16_MAX, 8328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 226, UINT16_MAX, 226, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8329, UINT16_MAX, 8329, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16611, 229, UINT16_MAX, 229, UINT16_MAX, 2858, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16614, UINT16_MAX, 8330, UINT16_MAX, 8330, 2862, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16616, 234, UINT16_MAX, 234, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16619, UINT16_MAX, 8331, UINT16_MAX, 8331, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16621, 239, UINT16_MAX, 239, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16624, UINT16_MAX, 8332, UINT16_MAX, 8332, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16626, 244, UINT16_MAX, 244, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16629, UINT16_MAX, 8333, UINT16_MAX, 8333, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16631, 249, UINT16_MAX, 249, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16634, UINT16_MAX, 8334, UINT16_MAX, 8334, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16636, 254, UINT16_MAX, 254, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16639, UINT16_MAX, 8335, UINT16_MAX, 8335, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16641, 259, UINT16_MAX, 259, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16644, UINT16_MAX, 8336, UINT16_MAX, 8336, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16646, 264, UINT16_MAX, 264, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16649, UINT16_MAX, 8337, UINT16_MAX, 8337, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16651, 269, UINT16_MAX, 269, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16654, UINT16_MAX, 8338, UINT16_MAX, 8338, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16656, 274, UINT16_MAX, 274, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16659, UINT16_MAX, 8339, UINT16_MAX, 8339, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 277, UINT16_MAX, 277, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 5251, UINT16_MAX, 5251, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16662, 280, UINT16_MAX, 280, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16665, UINT16_MAX, 8340, UINT16_MAX, 8340, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16667, 285, UINT16_MAX, 285, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16670, UINT16_MAX, 8341, UINT16_MAX, 8341, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16672, 290, UINT16_MAX, 290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16675, UINT16_MAX, 8342, UINT16_MAX, 8342, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16677, 295, UINT16_MAX, 295, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16680, UINT16_MAX, 8343, UINT16_MAX, 8343, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16682, 16684, UINT16_MAX, 8, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1499, UINT16_MAX, 1499, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16686, 304, UINT16_MAX, 304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16689, UINT16_MAX, 8344, UINT16_MAX, 8344, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16691, 309, UINT16_MAX, 309, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16694, UINT16_MAX, 8345, UINT16_MAX, 8345, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16696, 314, UINT16_MAX, 314, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16699, UINT16_MAX, 8346, UINT16_MAX, 8346, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8347, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16701, 319, UINT16_MAX, 319, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16704, UINT16_MAX, 8348, UINT16_MAX, 8348, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16706, 324, UINT16_MAX, 324, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16709, UINT16_MAX, 8349, UINT16_MAX, 8349, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16711, 329, UINT16_MAX, 329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16714, UINT16_MAX, 8350, UINT16_MAX, 8350, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16716, 334, UINT16_MAX, 334, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16719, UINT16_MAX, 8351, UINT16_MAX, 8351, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 337, UINT16_MAX, 337, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8352, UINT16_MAX, 8352, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16722, 340, UINT16_MAX, 340, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16725, UINT16_MAX, 8353, UINT16_MAX, 8353, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16727, 345, UINT16_MAX, 345, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16730, UINT16_MAX, 8354, UINT16_MAX, 8354, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16732, 350, UINT16_MAX, 350, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16735, UINT16_MAX, 8355, UINT16_MAX, 8355, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16737, 16737, 8356, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 355, UINT16_MAX, 355, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8357, UINT16_MAX, 8357, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16740, 358, UINT16_MAX, 358, UINT16_MAX, 2974, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16743, UINT16_MAX, 8358, UINT16_MAX, 8358, 2978, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16745, 363, UINT16_MAX, 363, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16748, UINT16_MAX, 8359, UINT16_MAX, 8359, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16750, 368, UINT16_MAX, 368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16753, UINT16_MAX, 8360, UINT16_MAX, 8360, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 371, UINT16_MAX, 371, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8361, UINT16_MAX, 8361, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16756, 374, UINT16_MAX, 374, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16759, UINT16_MAX, 8362, UINT16_MAX, 8362, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16761, 379, UINT16_MAX, 379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16764, UINT16_MAX, 8363, UINT16_MAX, 8363, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16766, 384, UINT16_MAX, 384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16769, UINT16_MAX, 8364, UINT16_MAX, 8364, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16771, 389, UINT16_MAX, 389, UINT16_MAX, 3012, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16774, UINT16_MAX, 8365, UINT16_MAX, 8365, 3015, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16776, 394, UINT16_MAX, 394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16779, UINT16_MAX, 8366, UINT16_MAX, 8366, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16781, 399, UINT16_MAX, 399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16784, UINT16_MAX, 8367, UINT16_MAX, 8367, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16786, 404, UINT16_MAX, 404, UINT16_MAX, 3018, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16789, UINT16_MAX, 8368, UINT16_MAX, 8368, 3021, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16791, 409, UINT16_MAX, 409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16794, UINT16_MAX, 8369, UINT16_MAX, 8369, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16796, 414, UINT16_MAX, 414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16799, UINT16_MAX, 8370, UINT16_MAX, 8370, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 417, UINT16_MAX, 417, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8371, UINT16_MAX, 8371, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16802, 420, UINT16_MAX, 420, UINT16_MAX, 3030, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16805, UINT16_MAX, 8372, UINT16_MAX, 8372, 3033, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16807, 425, UINT16_MAX, 425, UINT16_MAX, 3036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16810, UINT16_MAX, 8373, UINT16_MAX, 8373, 3039, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16812, 430, UINT16_MAX, 430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16815, UINT16_MAX, 8374, UINT16_MAX, 8374, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16817, 435, UINT16_MAX, 435, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16820, UINT16_MAX, 8375, UINT16_MAX, 8375, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16822, 440, UINT16_MAX, 440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16825, UINT16_MAX, 8376, UINT16_MAX, 8376, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16827, 445, UINT16_MAX, 445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16830, UINT16_MAX, 8377, UINT16_MAX, 8377, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16832, 450, UINT16_MAX, 450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16835, UINT16_MAX, 8378, UINT16_MAX, 8378, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16837, 455, UINT16_MAX, 455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16840, UINT16_MAX, 8379, UINT16_MAX, 8379, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16842, 460, UINT16_MAX, 460, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16845, 463, UINT16_MAX, 463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16848, UINT16_MAX, 8380, UINT16_MAX, 8380, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16850, 468, UINT16_MAX, 468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16853, UINT16_MAX, 8381, UINT16_MAX, 8381, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16855, 473, UINT16_MAX, 473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16858, UINT16_MAX, 8382, UINT16_MAX, 8382, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18, 18, 3320, UINT16_MAX, 3320, 3140, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8383, UINT16_MAX, 8383, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 476, UINT16_MAX, 476, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 477, UINT16_MAX, 477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8384, UINT16_MAX, 8384, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 478, UINT16_MAX, 478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8385, UINT16_MAX, 8385, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 479, UINT16_MAX, 479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 480, UINT16_MAX, 480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8386, UINT16_MAX, 8386, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 481, UINT16_MAX, 481, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 482, UINT16_MAX, 482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 483, UINT16_MAX, 483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8387, UINT16_MAX, 8387, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8388, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 484, UINT16_MAX, 484, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 485, UINT16_MAX, 485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 486, UINT16_MAX, 486, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 487, UINT16_MAX, 487, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8389, UINT16_MAX, 8389, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 488, UINT16_MAX, 488, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 489, UINT16_MAX, 489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8390, UINT16_MAX, 8390, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 490, UINT16_MAX, 490, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 491, UINT16_MAX, 491, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 492, UINT16_MAX, 492, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8391, UINT16_MAX, 8391, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8392, UINT16_MAX, 8392, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8393, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 493, UINT16_MAX, 493, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 494, UINT16_MAX, 494, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8394, UINT16_MAX, 8394, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 495, UINT16_MAX, 495, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16880, 498, UINT16_MAX, 498, UINT16_MAX, 3565, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16883, UINT16_MAX, 8395, UINT16_MAX, 8395, 3614, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 501, UINT16_MAX, 501, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8396, UINT16_MAX, 8396, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 502, UINT16_MAX, 502, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8397, UINT16_MAX, 8397, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 503, UINT16_MAX, 503, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 504, UINT16_MAX, 504, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8398, UINT16_MAX, 8398, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 505, UINT16_MAX, 505, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8399, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1537, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 506, UINT16_MAX, 506, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8400, UINT16_MAX, 8400, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 507, UINT16_MAX, 507, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16892, 510, UINT16_MAX, 510, UINT16_MAX, 3663, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16895, UINT16_MAX, 8401, UINT16_MAX, 8401, 3712, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 513, UINT16_MAX, 513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 514, UINT16_MAX, 514, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 515, UINT16_MAX, 515, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8402, UINT16_MAX, 8402, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 516, UINT16_MAX, 516, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8403, UINT16_MAX, 8403, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 517, UINT16_MAX, 517, UINT16_MAX, 1573, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 518, UINT16_MAX, 518, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8404, UINT16_MAX, 8404, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8405, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 519, UINT16_MAX, 519, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8406, UINT16_MAX, 8406, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8407, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8408, UINT16_MAX, 8408, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16904, 522, UINT16_MAX, 522, 8409, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16907, 522, 8410, 522, 8409, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16909, UINT16_MAX, 8410, UINT16_MAX, 8409, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16911, 529, UINT16_MAX, 529, 8411, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16914, 529, 8412, 529, 8411, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16916, UINT16_MAX, 8412, UINT16_MAX, 8411, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16918, 536, UINT16_MAX, 536, 8413, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16921, 536, 8414, 536, 8413, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16923, UINT16_MAX, 8414, UINT16_MAX, 8413, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16925, 543, UINT16_MAX, 543, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16928, UINT16_MAX, 8415, UINT16_MAX, 8415, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16930, 548, UINT16_MAX, 548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16933, UINT16_MAX, 8416, UINT16_MAX, 8416, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16935, 553, UINT16_MAX, 553, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16938, UINT16_MAX, 8417, UINT16_MAX, 8417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16940, 558, UINT16_MAX, 558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16943, UINT16_MAX, 8418, UINT16_MAX, 8418, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16945, 563, UINT16_MAX, 563, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16948, UINT16_MAX, 8419, UINT16_MAX, 8419, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16950, 568, UINT16_MAX, 568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16953, UINT16_MAX, 8420, UINT16_MAX, 8420, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16955, 573, UINT16_MAX, 573, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16958, UINT16_MAX, 8421, UINT16_MAX, 8421, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16960, 578, UINT16_MAX, 578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16963, UINT16_MAX, 8422, UINT16_MAX, 8422, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1496, UINT16_MAX, 1496, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16965, 583, UINT16_MAX, 583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16968, UINT16_MAX, 8423, UINT16_MAX, 8423, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16970, 588, UINT16_MAX, 588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16973, UINT16_MAX, 8424, UINT16_MAX, 8424, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16975, 593, UINT16_MAX, 593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16978, UINT16_MAX, 8425, UINT16_MAX, 8425, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 596, UINT16_MAX, 596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8426, UINT16_MAX, 8426, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16981, 599, UINT16_MAX, 599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16984, UINT16_MAX, 8427, UINT16_MAX, 8427, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16986, 604, UINT16_MAX, 604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16989, UINT16_MAX, 8428, UINT16_MAX, 8428, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16991, 609, UINT16_MAX, 609, UINT16_MAX, 1567, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16994, UINT16_MAX, 8429, UINT16_MAX, 8429, 1570, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16996, 614, UINT16_MAX, 614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16999, UINT16_MAX, 8430, UINT16_MAX, 8430, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17001, 619, UINT16_MAX, 619, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17004, UINT16_MAX, 8431, UINT16_MAX, 8431, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17006, 17006, 8432, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17008, 626, UINT16_MAX, 626, 8433, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17011, 626, 8434, 626, 8433, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17013, UINT16_MAX, 8434, UINT16_MAX, 8433, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17015, 633, UINT16_MAX, 633, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17018, UINT16_MAX, 8435, UINT16_MAX, 8435, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 636, UINT16_MAX, 636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 637, UINT16_MAX, 637, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17022, 640, UINT16_MAX, 640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17025, UINT16_MAX, 8436, UINT16_MAX, 8436, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17027, 645, UINT16_MAX, 645, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17030, UINT16_MAX, 8437, UINT16_MAX, 8437, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17032, 650, UINT16_MAX, 650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17035, UINT16_MAX, 8438, UINT16_MAX, 8438, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17037, 655, UINT16_MAX, 655, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17040, UINT16_MAX, 8439, UINT16_MAX, 8439, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17042, 660, UINT16_MAX, 660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17045, UINT16_MAX, 8440, UINT16_MAX, 8440, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17047, 665, UINT16_MAX, 665, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17050, UINT16_MAX, 8441, UINT16_MAX, 8441, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17052, 670, UINT16_MAX, 670, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17055, UINT16_MAX, 8442, UINT16_MAX, 8442, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17057, 675, UINT16_MAX, 675, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17060, UINT16_MAX, 8443, UINT16_MAX, 8443, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17062, 680, UINT16_MAX, 680, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17065, UINT16_MAX, 8444, UINT16_MAX, 8444, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17067, 685, UINT16_MAX, 685, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17070, UINT16_MAX, 8445, UINT16_MAX, 8445, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17072, 690, UINT16_MAX, 690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17075, UINT16_MAX, 8446, UINT16_MAX, 8446, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17077, 695, UINT16_MAX, 695, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17080, UINT16_MAX, 8447, UINT16_MAX, 8447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17082, 700, UINT16_MAX, 700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17085, UINT16_MAX, 8448, UINT16_MAX, 8448, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17087, 705, UINT16_MAX, 705, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17090, UINT16_MAX, 8449, UINT16_MAX, 8449, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17092, 710, UINT16_MAX, 710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17095, UINT16_MAX, 8450, UINT16_MAX, 8450, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17097, 715, UINT16_MAX, 715, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17100, UINT16_MAX, 8451, UINT16_MAX, 8451, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17102, 720, UINT16_MAX, 720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17105, UINT16_MAX, 8452, UINT16_MAX, 8452, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17107, 725, UINT16_MAX, 725, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17110, UINT16_MAX, 8453, UINT16_MAX, 8453, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 728, UINT16_MAX, 728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8454, UINT16_MAX, 8454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17113, 731, UINT16_MAX, 731, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17116, UINT16_MAX, 8455, UINT16_MAX, 8455, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 734, UINT16_MAX, 734, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8456, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 735, UINT16_MAX, 735, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1506, UINT16_MAX, 1506, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 736, UINT16_MAX, 736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8457, UINT16_MAX, 8457, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17121, 739, UINT16_MAX, 739, UINT16_MAX, 1543, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17124, UINT16_MAX, 8458, UINT16_MAX, 8458, 1546, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17126, 744, UINT16_MAX, 744, UINT16_MAX, 2866, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17129, UINT16_MAX, 8459, UINT16_MAX, 8459, 2869, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17131, 749, UINT16_MAX, 749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17134, UINT16_MAX, 8460, UINT16_MAX, 8460, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17136, 754, UINT16_MAX, 754, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17139, UINT16_MAX, 8461, UINT16_MAX, 8461, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17141, 759, UINT16_MAX, 759, UINT16_MAX, 1615, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17144, UINT16_MAX, 8462, UINT16_MAX, 8462, 1618, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17146, 764, UINT16_MAX, 764, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17149, UINT16_MAX, 8463, UINT16_MAX, 8463, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17151, 769, UINT16_MAX, 769, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17154, UINT16_MAX, 8464, UINT16_MAX, 8464, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8465, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8466, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8467, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7430, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8468, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8469, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 772, UINT16_MAX, 772, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 773, UINT16_MAX, 773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8470, UINT16_MAX, 8470, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 774, UINT16_MAX, 774, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 775, UINT16_MAX, 775, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8471, UINT16_MAX, 8471, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8472, UINT16_MAX, 8472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 776, UINT16_MAX, 776, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8473, UINT16_MAX, 8473, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 777, UINT16_MAX, 777, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 778, UINT16_MAX, 778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 779, UINT16_MAX, 779, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 780, UINT16_MAX, 780, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8474, UINT16_MAX, 8474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 781, UINT16_MAX, 781, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8475, UINT16_MAX, 8475, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 782, UINT16_MAX, 782, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8476, UINT16_MAX, 8476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 783, UINT16_MAX, 783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8477, UINT16_MAX, 8477, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 784, UINT16_MAX, 784, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8478, UINT16_MAX, 8478, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8479, UINT16_MAX, 8479, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8480, UINT16_MAX, 8480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8481, UINT16_MAX, 8481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8482, UINT16_MAX, 8482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8483, UINT16_MAX, 8483, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1521, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8484, UINT16_MAX, 8484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8485, UINT16_MAX, 8485, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7053, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8486, UINT16_MAX, 8486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8487, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2822, UINT16_MAX, 2822, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8488, UINT16_MAX, 8488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8489, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7054, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1522, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8490, UINT16_MAX, 8490, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8491, UINT16_MAX, 8491, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7057, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8492, UINT16_MAX, 8492, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7056, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8493, UINT16_MAX, 8493, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8494, UINT16_MAX, 8494, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7060, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8495, UINT16_MAX, 8495, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8496, UINT16_MAX, 8496, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8497, UINT16_MAX, 8497, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8498, UINT16_MAX, 8498, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8499, UINT16_MAX, 8499, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1528, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7067, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8500, UINT16_MAX, 8500, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1532, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8501, UINT16_MAX, 8501, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8502, UINT16_MAX, 8502, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1533, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1534, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8503, UINT16_MAX, 8503, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7073, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7074, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1535, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 786, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7075, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 787, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8504, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8505, UINT16_MAX, 8505, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7078, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8506, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8507, UINT16_MAX, 8507, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 788, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8508, UINT16_MAX, 8508, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8509, UINT16_MAX, 8509, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7061, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8510, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8511, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8512, UINT16_MAX, 8512, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8513, UINT16_MAX, 8513, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8514, UINT16_MAX, 8514, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8515, UINT16_MAX, 8515, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8516, UINT16_MAX, 8516, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8517, UINT16_MAX, 8517, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 5254, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7070, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7084, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1539, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1540, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8518, UINT16_MAX, 8518, 1576, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8519, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 801, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8520, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8521, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7087, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7047, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8522, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7058, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7059, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8523, UINT16_MAX, 8523, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8524, UINT16_MAX, 8524, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1530, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8525, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7085, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7086, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7048, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7051, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7050, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7080, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7082, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7079, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7055, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7062, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7063, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8526, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8527, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8528, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8529, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7, UINT16_MAX, 8530, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 785, UINT16_MAX, 8531, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 9, UINT16_MAX, 8532, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 17, UINT16_MAX, 8533, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 786, UINT16_MAX, 8534, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 787, UINT16_MAX, 8535, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 788, UINT16_MAX, 8536, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 22, UINT16_MAX, 8537, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 24, UINT16_MAX, 8538, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8539, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8540, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 489, UINT16_MAX, 8541, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 11, UINT16_MAX, 8542, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 18, UINT16_MAX, 8543, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 23, UINT16_MAX, 8544, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 801, UINT16_MAX, 8545, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32768, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32769, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32770, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32771, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32775, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32776, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32778, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32772, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32814, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32773, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32780, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32779, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32782, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32783, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32815, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32816, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 232, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32781, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32808, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32813, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32807, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32784, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32774, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32777, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32810, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32812, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32811, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32809, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32819, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32817, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 17189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 240, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, 807, 7437, UINT16_MAX, 7437, 32818, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 233, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 234, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 808, UINT16_MAX, 808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8546, UINT16_MAX, 8546, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 809, UINT16_MAX, 809, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8547, UINT16_MAX, 8547, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 811, UINT16_MAX, 811, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8548, UINT16_MAX, 8548, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17196, UINT16_MAX, 8549, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8550, UINT16_MAX, 8550, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8551, UINT16_MAX, 8551, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8552, UINT16_MAX, 8552, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 815, UINT16_MAX, 815, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 17200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17202, 820, UINT16_MAX, 820, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17206, 824, UINT16_MAX, 824, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17209, 827, UINT16_MAX, 827, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17212, 830, UINT16_MAX, 830, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17215, 833, UINT16_MAX, 833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17218, 836, UINT16_MAX, 836, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17221, 839, UINT16_MAX, 839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17224, 33610, 2659, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 845, UINT16_MAX, 845, UINT16_MAX, 1673, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 846, UINT16_MAX, 846, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 847, UINT16_MAX, 847, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 848, UINT16_MAX, 848, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 849, UINT16_MAX, 849, UINT16_MAX, 1726, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 850, UINT16_MAX, 850, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 851, UINT16_MAX, 851, UINT16_MAX, 1777, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 852, UINT16_MAX, 852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 807, UINT16_MAX, 807, UINT16_MAX, 1830, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 853, UINT16_MAX, 853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 854, UINT16_MAX, 854, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 35, UINT16_MAX, 35, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 855, UINT16_MAX, 855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 856, UINT16_MAX, 856, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 857, UINT16_MAX, 857, UINT16_MAX, 1881, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 858, UINT16_MAX, 858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 859, UINT16_MAX, 859, UINT16_MAX, 5027, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 860, UINT16_MAX, 860, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 861, UINT16_MAX, 861, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 862, UINT16_MAX, 862, UINT16_MAX, 1932, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 863, UINT16_MAX, 863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 864, UINT16_MAX, 864, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 865, UINT16_MAX, 865, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 866, UINT16_MAX, 866, UINT16_MAX, 1983, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17251, 869, UINT16_MAX, 869, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17254, 872, UINT16_MAX, 872, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17257, UINT16_MAX, 2603, UINT16_MAX, 2603, 4904, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17259, UINT16_MAX, 2635, UINT16_MAX, 2635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17261, UINT16_MAX, 2640, UINT16_MAX, 2640, 4913, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17263, UINT16_MAX, 2676, UINT16_MAX, 2676, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17265, 33651, 2693, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7431, UINT16_MAX, 7431, 2088, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7432, UINT16_MAX, 7432, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2847, UINT16_MAX, 2847, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7433, UINT16_MAX, 7433, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7434, UINT16_MAX, 7434, 2141, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7435, UINT16_MAX, 7435, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7436, UINT16_MAX, 7436, 2192, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 915, UINT16_MAX, 915, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7437, UINT16_MAX, 7437, 2245, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7438, UINT16_MAX, 7438, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7439, UINT16_MAX, 7439, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7440, UINT16_MAX, 7440, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7441, UINT16_MAX, 7441, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7442, UINT16_MAX, 7442, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7443, UINT16_MAX, 7443, 2401, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2848, UINT16_MAX, 2848, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7444, UINT16_MAX, 7444, 5023, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 860, 917, UINT16_MAX, 917, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 917, UINT16_MAX, 917, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7446, UINT16_MAX, 7446, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 897, UINT16_MAX, 897, 2349, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7447, UINT16_MAX, 7447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7448, UINT16_MAX, 7448, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7449, UINT16_MAX, 7449, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2836, UINT16_MAX, 2836, 2452, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17270, UINT16_MAX, 8553, UINT16_MAX, 8553, 2036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17272, UINT16_MAX, 8554, UINT16_MAX, 8554, 2297, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17274, UINT16_MAX, 2745, UINT16_MAX, 2745, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17276, UINT16_MAX, 2714, UINT16_MAX, 2714, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17278, UINT16_MAX, 2750, UINT16_MAX, 2750, 5033, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 896, UINT16_MAX, 896, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 846, 846, 7432, UINT16_MAX, 7432, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 852, 852, 915, UINT16_MAX, 915, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 897, UINT16_MAX, UINT16_MAX, 8555, UINT16_MAX, 2505, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17282, UINT16_MAX, UINT16_MAX, 8556, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17284, UINT16_MAX, UINT16_MAX, 8557, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 863, 863, 7447, UINT16_MAX, 7447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 858, 858, 2848, UINT16_MAX, 2848, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8558, UINT16_MAX, 8558, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 902, UINT16_MAX, 902, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8559, UINT16_MAX, 8559, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 903, UINT16_MAX, 903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8560, UINT16_MAX, 8560, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 904, UINT16_MAX, 904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7458, UINT16_MAX, 7458, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 905, UINT16_MAX, 905, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8561, UINT16_MAX, 8561, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 906, UINT16_MAX, 906, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8562, UINT16_MAX, 8562, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 907, UINT16_MAX, 907, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8563, UINT16_MAX, 8563, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 908, UINT16_MAX, 908, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8564, UINT16_MAX, 8564, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 909, UINT16_MAX, 909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8565, UINT16_MAX, 8565, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 910, UINT16_MAX, 910, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8566, UINT16_MAX, 8566, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 911, UINT16_MAX, 911, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8567, UINT16_MAX, 8567, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 912, UINT16_MAX, 912, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8568, UINT16_MAX, 8568, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 913, UINT16_MAX, 913, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8569, UINT16_MAX, 8569, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 853, 853, 7438, UINT16_MAX, 7438, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 859, 859, 7444, UINT16_MAX, 7444, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 914, UINT16_MAX, 8570, UINT16_MAX, 8570, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8571, UINT16_MAX, 8571, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 915, 852, UINT16_MAX, 852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 849, 849, 7434, UINT16_MAX, 7434, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 916, UINT16_MAX, 916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8572, UINT16_MAX, 8572, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 917, 918, UINT16_MAX, 918, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 919, UINT16_MAX, 919, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8573, UINT16_MAX, 8573, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8574, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 920, UINT16_MAX, 920, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 921, UINT16_MAX, 921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 922, UINT16_MAX, 922, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17307, 925, UINT16_MAX, 925, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17310, 928, UINT16_MAX, 928, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 929, UINT16_MAX, 929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17314, 932, UINT16_MAX, 932, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 933, UINT16_MAX, 933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 934, UINT16_MAX, 934, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 935, UINT16_MAX, 935, UINT16_MAX, 2525, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17320, 938, UINT16_MAX, 938, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 939, UINT16_MAX, 939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 940, UINT16_MAX, 940, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 941, UINT16_MAX, 941, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 942, UINT16_MAX, 942, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17327, 945, UINT16_MAX, 945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17330, 948, UINT16_MAX, 948, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17333, 951, UINT16_MAX, 951, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 952, UINT16_MAX, 952, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 953, UINT16_MAX, 953, UINT16_MAX, 2615, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 954, UINT16_MAX, 954, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 955, UINT16_MAX, 955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 956, UINT16_MAX, 956, UINT16_MAX, 2522, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 957, UINT16_MAX, 957, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 958, UINT16_MAX, 958, UINT16_MAX, 2511, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 959, UINT16_MAX, 959, UINT16_MAX, 2601, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 960, UINT16_MAX, 960, UINT16_MAX, 2635, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 961, UINT16_MAX, 961, UINT16_MAX, 2531, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17346, 964, UINT16_MAX, 964, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 965, UINT16_MAX, 965, UINT16_MAX, 2528, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 966, UINT16_MAX, 966, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 967, UINT16_MAX, 967, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 968, UINT16_MAX, 968, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 969, UINT16_MAX, 969, UINT16_MAX, 2641, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 970, UINT16_MAX, 970, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 971, UINT16_MAX, 971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 972, UINT16_MAX, 972, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 973, UINT16_MAX, 973, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 974, UINT16_MAX, 974, UINT16_MAX, 2542, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 975, UINT16_MAX, 975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 976, UINT16_MAX, 976, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 977, UINT16_MAX, 977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 978, UINT16_MAX, 978, UINT16_MAX, 2659, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 979, UINT16_MAX, 979, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 980, UINT16_MAX, 980, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 981, UINT16_MAX, 981, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 982, UINT16_MAX, 982, UINT16_MAX, 2665, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 983, UINT16_MAX, 983, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 984, UINT16_MAX, 984, UINT16_MAX, 2653, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 985, UINT16_MAX, 985, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 986, UINT16_MAX, 986, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8575, UINT16_MAX, 8575, 2622, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8576, UINT16_MAX, 8576, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8577, UINT16_MAX, 8577, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8578, UINT16_MAX, 8578, 2575, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8579, UINT16_MAX, 8579, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8580, UINT16_MAX, 8580, 2564, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8581, UINT16_MAX, 8581, 2608, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8582, UINT16_MAX, 8582, 2638, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8583, UINT16_MAX, 8583, 2553, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17371, UINT16_MAX, 8584, UINT16_MAX, 8584, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8585, UINT16_MAX, 8585, 2581, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8586, UINT16_MAX, 8586, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8587, UINT16_MAX, 8587, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8588, UINT16_MAX, 8588, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8589, UINT16_MAX, 8589, 2644, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8590, UINT16_MAX, 8590, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8591, UINT16_MAX, 8591, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8592, UINT16_MAX, 8592, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8593, UINT16_MAX, 8593, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8594, UINT16_MAX, 8594, 2584, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8595, UINT16_MAX, 8595, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8596, UINT16_MAX, 8596, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8597, UINT16_MAX, 8597, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8598, UINT16_MAX, 8598, 2662, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8599, UINT16_MAX, 8599, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8600, UINT16_MAX, 8600, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8601, UINT16_MAX, 8601, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8602, UINT16_MAX, 8602, 2668, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8603, UINT16_MAX, 8603, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8604, UINT16_MAX, 8604, 2656, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8605, UINT16_MAX, 8605, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8606, UINT16_MAX, 8606, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17373, UINT16_MAX, 8607, UINT16_MAX, 8607, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17375, UINT16_MAX, 8608, UINT16_MAX, 8608, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8609, UINT16_MAX, 8609, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17377, UINT16_MAX, 8610, UINT16_MAX, 8610, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8611, UINT16_MAX, 8611, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8612, UINT16_MAX, 8612, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8613, UINT16_MAX, 8613, 2578, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17379, UINT16_MAX, 8614, UINT16_MAX, 8614, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8615, UINT16_MAX, 8615, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8616, UINT16_MAX, 8616, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8617, UINT16_MAX, 8617, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8618, UINT16_MAX, 8618, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17381, UINT16_MAX, 8619, UINT16_MAX, 8619, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17383, UINT16_MAX, 8620, UINT16_MAX, 8620, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17385, UINT16_MAX, 8621, UINT16_MAX, 8621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8622, UINT16_MAX, 8622, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1003, UINT16_MAX, 1003, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8623, UINT16_MAX, 8623, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1004, UINT16_MAX, 1004, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8624, UINT16_MAX, 8624, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1005, UINT16_MAX, 1005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8625, UINT16_MAX, 8625, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1006, UINT16_MAX, 1006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8626, UINT16_MAX, 8626, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1007, UINT16_MAX, 1007, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8627, UINT16_MAX, 8627, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1008, UINT16_MAX, 1008, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8628, UINT16_MAX, 8628, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1009, UINT16_MAX, 1009, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8629, UINT16_MAX, 8629, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1010, UINT16_MAX, 1010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8630, UINT16_MAX, 8630, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1011, UINT16_MAX, 1011, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8631, UINT16_MAX, 8631, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1012, UINT16_MAX, 1012, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8632, UINT16_MAX, 8632, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1013, UINT16_MAX, 1013, UINT16_MAX, 2595, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8633, UINT16_MAX, 8633, 2598, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17398, 1016, UINT16_MAX, 1016, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17401, UINT16_MAX, 8634, UINT16_MAX, 8634, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1019, UINT16_MAX, 1019, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8635, UINT16_MAX, 8635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1020, UINT16_MAX, 1020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8636, UINT16_MAX, 8636, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1021, UINT16_MAX, 1021, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8637, UINT16_MAX, 8637, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1022, UINT16_MAX, 1022, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8638, UINT16_MAX, 8638, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1023, UINT16_MAX, 1023, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8639, UINT16_MAX, 8639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ME, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1024, UINT16_MAX, 1024, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8640, UINT16_MAX, 8640, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1025, UINT16_MAX, 1025, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8641, UINT16_MAX, 8641, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1026, UINT16_MAX, 1026, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8642, UINT16_MAX, 8642, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1027, UINT16_MAX, 1027, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8643, UINT16_MAX, 8643, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1028, UINT16_MAX, 1028, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8644, UINT16_MAX, 8644, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1029, UINT16_MAX, 1029, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8645, UINT16_MAX, 8645, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1030, UINT16_MAX, 1030, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8646, UINT16_MAX, 8646, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1031, UINT16_MAX, 1031, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8647, UINT16_MAX, 8647, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1032, UINT16_MAX, 1032, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8648, UINT16_MAX, 8648, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1033, UINT16_MAX, 1033, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8649, UINT16_MAX, 8649, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1034, UINT16_MAX, 1034, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8650, UINT16_MAX, 8650, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1035, UINT16_MAX, 1035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8651, UINT16_MAX, 8651, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1036, UINT16_MAX, 1036, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8652, UINT16_MAX, 8652, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1037, UINT16_MAX, 1037, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8653, UINT16_MAX, 8653, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1038, UINT16_MAX, 1038, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8654, UINT16_MAX, 8654, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1039, UINT16_MAX, 1039, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8655, UINT16_MAX, 8655, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1040, UINT16_MAX, 1040, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8656, UINT16_MAX, 8656, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1041, UINT16_MAX, 1041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8657, UINT16_MAX, 8657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1042, UINT16_MAX, 1042, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8658, UINT16_MAX, 8658, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1043, UINT16_MAX, 1043, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8659, UINT16_MAX, 8659, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1044, UINT16_MAX, 1044, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8660, UINT16_MAX, 8660, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1045, UINT16_MAX, 1045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8661, UINT16_MAX, 8661, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1046, UINT16_MAX, 1046, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8662, UINT16_MAX, 8662, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1047, UINT16_MAX, 1047, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8663, UINT16_MAX, 8663, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1048, UINT16_MAX, 1048, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8664, UINT16_MAX, 8664, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1049, UINT16_MAX, 1049, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8665, UINT16_MAX, 8665, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1050, UINT16_MAX, 1050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8666, UINT16_MAX, 8666, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1051, UINT16_MAX, 1051, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17436, 1054, UINT16_MAX, 1054, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17439, UINT16_MAX, 8667, UINT16_MAX, 8667, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1057, UINT16_MAX, 1057, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8668, UINT16_MAX, 8668, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1058, UINT16_MAX, 1058, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8669, UINT16_MAX, 8669, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1059, UINT16_MAX, 1059, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8670, UINT16_MAX, 8670, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1060, UINT16_MAX, 1060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8671, UINT16_MAX, 8671, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1061, UINT16_MAX, 1061, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8672, UINT16_MAX, 8672, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1062, UINT16_MAX, 1062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8673, UINT16_MAX, 8673, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8674, UINT16_MAX, 8674, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17447, 1065, UINT16_MAX, 1065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17450, UINT16_MAX, 8675, UINT16_MAX, 8675, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17452, 1070, UINT16_MAX, 1070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17455, UINT16_MAX, 8676, UINT16_MAX, 8676, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1073, UINT16_MAX, 1073, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8677, UINT16_MAX, 8677, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17458, 1076, UINT16_MAX, 1076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17461, UINT16_MAX, 8678, UINT16_MAX, 8678, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1079, UINT16_MAX, 1079, UINT16_MAX, 2629, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8679, UINT16_MAX, 8679, 2632, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17464, 1082, UINT16_MAX, 1082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17467, UINT16_MAX, 8680, UINT16_MAX, 8680, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17469, 1087, UINT16_MAX, 1087, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17472, UINT16_MAX, 8681, UINT16_MAX, 8681, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17474, 1092, UINT16_MAX, 1092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17477, UINT16_MAX, 8682, UINT16_MAX, 8682, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1095, UINT16_MAX, 1095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8683, UINT16_MAX, 8683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17480, 1098, UINT16_MAX, 1098, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17483, UINT16_MAX, 8684, UINT16_MAX, 8684, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17485, 1103, UINT16_MAX, 1103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17488, UINT16_MAX, 8685, UINT16_MAX, 8685, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17490, 1108, UINT16_MAX, 1108, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17493, UINT16_MAX, 8686, UINT16_MAX, 8686, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1111, UINT16_MAX, 1111, UINT16_MAX, 2647, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8687, UINT16_MAX, 8687, 2650, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17496, 1114, UINT16_MAX, 1114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17499, UINT16_MAX, 8688, UINT16_MAX, 8688, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17501, 1119, UINT16_MAX, 1119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17504, UINT16_MAX, 8689, UINT16_MAX, 8689, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17506, 1124, UINT16_MAX, 1124, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17509, UINT16_MAX, 8690, UINT16_MAX, 8690, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17511, 1129, UINT16_MAX, 1129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17514, UINT16_MAX, 8691, UINT16_MAX, 8691, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17516, 1134, UINT16_MAX, 1134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17519, UINT16_MAX, 8692, UINT16_MAX, 8692, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17521, 1139, UINT16_MAX, 1139, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17524, UINT16_MAX, 8693, UINT16_MAX, 8693, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1142, UINT16_MAX, 1142, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8694, UINT16_MAX, 8694, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17527, 1145, UINT16_MAX, 1145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17530, UINT16_MAX, 8695, UINT16_MAX, 8695, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1148, UINT16_MAX, 1148, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8696, UINT16_MAX, 8696, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1149, UINT16_MAX, 1149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8697, UINT16_MAX, 8697, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1150, UINT16_MAX, 1150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8698, UINT16_MAX, 8698, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1151, UINT16_MAX, 1151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8699, UINT16_MAX, 8699, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1152, UINT16_MAX, 1152, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8700, UINT16_MAX, 8700, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1153, UINT16_MAX, 1153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8701, UINT16_MAX, 8701, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1154, UINT16_MAX, 1154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8702, UINT16_MAX, 8702, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1155, UINT16_MAX, 1155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8703, UINT16_MAX, 8703, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1156, UINT16_MAX, 1156, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8704, UINT16_MAX, 8704, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1157, UINT16_MAX, 1157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8705, UINT16_MAX, 8705, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1158, UINT16_MAX, 1158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8706, UINT16_MAX, 8706, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1159, UINT16_MAX, 1159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8707, UINT16_MAX, 8707, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1160, UINT16_MAX, 1160, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8708, UINT16_MAX, 8708, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1161, UINT16_MAX, 1161, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8709, UINT16_MAX, 8709, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1162, UINT16_MAX, 1162, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8710, UINT16_MAX, 8710, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1163, UINT16_MAX, 1163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8711, UINT16_MAX, 8711, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1164, UINT16_MAX, 1164, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8712, UINT16_MAX, 8712, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1165, UINT16_MAX, 1165, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8713, UINT16_MAX, 8713, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1166, UINT16_MAX, 1166, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8714, UINT16_MAX, 8714, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1167, UINT16_MAX, 1167, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8715, UINT16_MAX, 8715, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1168, UINT16_MAX, 1168, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8716, UINT16_MAX, 8716, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1169, UINT16_MAX, 1169, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8717, UINT16_MAX, 8717, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1170, UINT16_MAX, 1170, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8718, UINT16_MAX, 8718, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1171, UINT16_MAX, 1171, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8719, UINT16_MAX, 8719, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1172, UINT16_MAX, 1172, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8720, UINT16_MAX, 8720, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1173, UINT16_MAX, 1173, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8721, UINT16_MAX, 8721, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1174, UINT16_MAX, 1174, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8722, UINT16_MAX, 8722, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1175, UINT16_MAX, 1175, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1176, UINT16_MAX, 1176, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1177, UINT16_MAX, 1177, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1178, UINT16_MAX, 1178, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1179, UINT16_MAX, 1179, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1180, UINT16_MAX, 1180, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1181, UINT16_MAX, 1181, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1182, UINT16_MAX, 1182, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1183, UINT16_MAX, 1183, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1184, UINT16_MAX, 1184, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1185, UINT16_MAX, 1185, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1186, UINT16_MAX, 1186, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1187, UINT16_MAX, 1187, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1188, UINT16_MAX, 1188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1189, UINT16_MAX, 1189, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1190, UINT16_MAX, 1190, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1191, UINT16_MAX, 1191, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1192, UINT16_MAX, 1192, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1193, UINT16_MAX, 1193, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1194, UINT16_MAX, 1194, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1195, UINT16_MAX, 1195, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1196, UINT16_MAX, 1196, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1197, UINT16_MAX, 1197, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1198, UINT16_MAX, 1198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1199, UINT16_MAX, 1199, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1200, UINT16_MAX, 1200, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1201, UINT16_MAX, 1201, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1202, UINT16_MAX, 1202, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1203, UINT16_MAX, 1203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1204, UINT16_MAX, 1204, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1205, UINT16_MAX, 1205, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1206, UINT16_MAX, 1206, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1207, UINT16_MAX, 1207, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1208, UINT16_MAX, 1208, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1209, UINT16_MAX, 1209, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1210, UINT16_MAX, 1210, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1211, UINT16_MAX, 1211, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1212, UINT16_MAX, 1212, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8723, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8724, UINT16_MAX, 8724, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8725, UINT16_MAX, 8725, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8726, UINT16_MAX, 8726, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8727, UINT16_MAX, 8727, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8728, UINT16_MAX, 8728, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8729, UINT16_MAX, 8729, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8730, UINT16_MAX, 8730, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8731, UINT16_MAX, 8731, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8732, UINT16_MAX, 8732, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8733, UINT16_MAX, 8733, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8734, UINT16_MAX, 8734, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8735, UINT16_MAX, 8735, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8736, UINT16_MAX, 8736, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8737, UINT16_MAX, 8737, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8738, UINT16_MAX, 8738, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8739, UINT16_MAX, 8739, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8740, UINT16_MAX, 8740, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8741, UINT16_MAX, 8741, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8742, UINT16_MAX, 8742, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8743, UINT16_MAX, 8743, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8744, UINT16_MAX, 8744, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8745, UINT16_MAX, 8745, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8746, UINT16_MAX, 8746, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8747, UINT16_MAX, 8747, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8748, UINT16_MAX, 8748, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8749, UINT16_MAX, 8749, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8750, UINT16_MAX, 8750, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8751, UINT16_MAX, 8751, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8752, UINT16_MAX, 8752, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8753, UINT16_MAX, 8753, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8754, UINT16_MAX, 8754, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8755, UINT16_MAX, 8755, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8756, UINT16_MAX, 8756, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8757, UINT16_MAX, 8757, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8758, UINT16_MAX, 8758, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8759, UINT16_MAX, 8759, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8760, UINT16_MAX, 8760, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8761, UINT16_MAX, 8761, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17597, 17597, 8762, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8763, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 222, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 228, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 10, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 11, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 12, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 13, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 14, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 15, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 16, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 17, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 18, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 19, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 20, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 21, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 22, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 23, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 24, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 25, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 30, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 31, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 32, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 17599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 17601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 17603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 17605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 17607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2671, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2676, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2679, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 27, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 28, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 29, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 33, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 34, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32785, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32786, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32787, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 35, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 17609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 17611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 17613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 17615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 17617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2685, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 17619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2688, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 17621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2682, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 36, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2691, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2694, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2697, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32788, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32789, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2700, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32790, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32792, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2704, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32791, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32793, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2709, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32795, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2712, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2716, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32794, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2719, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 84, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 91, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32796, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2722, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32799, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2725, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2730, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32797, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32798, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32800, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2733, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2737, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_PREPEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32801, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32802, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32803, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2740, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2745, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17707, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32804, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 103, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 107, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17713, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 118, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 122, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, 1335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 129, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 130, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 132, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, 17738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, 17742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 17756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2748, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32805, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1376, UINT16_MAX, 1376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1377, UINT16_MAX, 1377, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1378, UINT16_MAX, 1378, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1379, UINT16_MAX, 1379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1380, UINT16_MAX, 1380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1381, UINT16_MAX, 1381, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1382, UINT16_MAX, 1382, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1383, UINT16_MAX, 1383, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1384, UINT16_MAX, 1384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1385, UINT16_MAX, 1385, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1386, UINT16_MAX, 1386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1387, UINT16_MAX, 1387, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1388, UINT16_MAX, 1388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1389, UINT16_MAX, 1389, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1390, UINT16_MAX, 1390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1391, UINT16_MAX, 1391, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1392, UINT16_MAX, 1392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1393, UINT16_MAX, 1393, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1394, UINT16_MAX, 1394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1395, UINT16_MAX, 1395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1396, UINT16_MAX, 1396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1397, UINT16_MAX, 1397, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1398, UINT16_MAX, 1398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1399, UINT16_MAX, 1399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1400, UINT16_MAX, 1400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1401, UINT16_MAX, 1401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1402, UINT16_MAX, 1402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1403, UINT16_MAX, 1403, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1404, UINT16_MAX, 1404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1405, UINT16_MAX, 1405, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1406, UINT16_MAX, 1406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1407, UINT16_MAX, 1407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1408, UINT16_MAX, 1408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1409, UINT16_MAX, 1409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1410, UINT16_MAX, 1410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1411, UINT16_MAX, 1411, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1412, UINT16_MAX, 1412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1413, UINT16_MAX, 1413, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1414, UINT16_MAX, 1414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1415, UINT16_MAX, 1415, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8764, UINT16_MAX, 1446, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8765, UINT16_MAX, 1447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8766, UINT16_MAX, 1448, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8767, UINT16_MAX, 1449, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8768, UINT16_MAX, 1450, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8769, UINT16_MAX, 1451, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8770, UINT16_MAX, 1452, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8771, UINT16_MAX, 1453, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8772, UINT16_MAX, 1454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8773, UINT16_MAX, 1455, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8774, UINT16_MAX, 1456, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8775, UINT16_MAX, 1457, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8776, UINT16_MAX, 1416, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8777, UINT16_MAX, 1458, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8778, UINT16_MAX, 1459, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8779, UINT16_MAX, 1460, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8780, UINT16_MAX, 1461, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8781, UINT16_MAX, 1462, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8782, UINT16_MAX, 1463, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8783, UINT16_MAX, 1464, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8784, UINT16_MAX, 1465, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8785, UINT16_MAX, 1466, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8786, UINT16_MAX, 1467, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8787, UINT16_MAX, 1468, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8788, UINT16_MAX, 1469, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8789, UINT16_MAX, 1470, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8790, UINT16_MAX, 1471, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8791, UINT16_MAX, 1472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8792, UINT16_MAX, 1473, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8793, UINT16_MAX, 1474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8794, UINT16_MAX, 1475, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8795, UINT16_MAX, 1476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8796, UINT16_MAX, 1477, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8797, UINT16_MAX, 1478, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8798, UINT16_MAX, 1479, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8799, UINT16_MAX, 1480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8800, UINT16_MAX, 1481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8801, UINT16_MAX, 1482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8802, UINT16_MAX, 1483, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8803, UINT16_MAX, 1484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8804, UINT16_MAX, 1485, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8805, UINT16_MAX, 1486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8806, UINT16_MAX, 1487, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1416, UINT16_MAX, 8807, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8808, UINT16_MAX, 1488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8809, UINT16_MAX, 1489, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8810, UINT16_MAX, 1490, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_L, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_L, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 1, 0, UTF8PROC_BOUNDCLASS_V, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_V, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_T, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8811, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8812, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8813, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8814, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8815, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8816, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8817, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8818, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8819, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8820, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8821, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8822, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8823, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8824, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8825, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8826, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8827, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8828, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8829, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8830, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8831, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8832, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8834, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8835, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8836, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8837, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8838, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8840, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8841, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8842, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8844, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8845, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8846, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8847, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8848, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8849, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8850, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8851, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8854, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8856, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8857, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8859, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8860, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8861, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8862, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8864, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8865, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8866, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8867, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8868, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8869, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8870, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8871, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8872, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8873, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8874, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8875, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8876, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8877, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8878, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8879, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8880, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8881, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8882, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8884, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8885, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8886, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8887, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8888, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8889, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8890, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8891, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8892, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8893, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8894, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8895, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8896, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1417, 1417, UINT16_MAX, 1417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1418, 1418, UINT16_MAX, 1418, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1419, 1419, UINT16_MAX, 1419, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1420, 1420, UINT16_MAX, 1420, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1421, 1421, UINT16_MAX, 1421, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1422, 1422, UINT16_MAX, 1422, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 9, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2751, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2754, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2757, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2760, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2763, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2766, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 17817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32806, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2769, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2772, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2775, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2778, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2781, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 17827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 955, 8577, UINT16_MAX, 8577, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 957, 8579, UINT16_MAX, 8579, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 969, 8589, UINT16_MAX, 8589, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 972, 8592, UINT16_MAX, 8592, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 973, 8593, UINT16_MAX, 8593, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 981, 8601, UINT16_MAX, 8601, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1004, 8624, UINT16_MAX, 8624, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1445, 8897, UINT16_MAX, 8897, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1446, UINT16_MAX, 1446, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1447, UINT16_MAX, 1447, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1448, UINT16_MAX, 1448, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1449, UINT16_MAX, 1449, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1450, UINT16_MAX, 1450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1451, UINT16_MAX, 1451, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1452, UINT16_MAX, 1452, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1453, UINT16_MAX, 1453, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1454, UINT16_MAX, 1454, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1455, UINT16_MAX, 1455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1456, UINT16_MAX, 1456, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1457, UINT16_MAX, 1457, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1416, UINT16_MAX, 1416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1458, UINT16_MAX, 1458, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1459, UINT16_MAX, 1459, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1460, UINT16_MAX, 1460, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1461, UINT16_MAX, 1461, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1462, UINT16_MAX, 1462, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1463, UINT16_MAX, 1463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1464, UINT16_MAX, 1464, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1465, UINT16_MAX, 1465, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1466, UINT16_MAX, 1466, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1467, UINT16_MAX, 1467, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1468, UINT16_MAX, 1468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1469, UINT16_MAX, 1469, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1470, UINT16_MAX, 1470, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1471, UINT16_MAX, 1471, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1472, UINT16_MAX, 1472, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1473, UINT16_MAX, 1473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1474, UINT16_MAX, 1474, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1475, UINT16_MAX, 1475, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1476, UINT16_MAX, 1476, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1477, UINT16_MAX, 1477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1478, UINT16_MAX, 1478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1479, UINT16_MAX, 1479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1480, UINT16_MAX, 1480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1481, UINT16_MAX, 1481, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1482, UINT16_MAX, 1482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1483, UINT16_MAX, 1483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1484, UINT16_MAX, 1484, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1485, UINT16_MAX, 1485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1486, UINT16_MAX, 1486, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1487, UINT16_MAX, 1487, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1488, UINT16_MAX, 1488, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1489, UINT16_MAX, 1489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1490, UINT16_MAX, 1490, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8898, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8899, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1514, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8900, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8901, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8902, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8903, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8904, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8905, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8906, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8907, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8908, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8909, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8910, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8911, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8912, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8913, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8914, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8915, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8916, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8917, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8918, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1516, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1517, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8919, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8920, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8921, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8922, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1538, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1518, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8923, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8924, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8925, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8926, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8927, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8928, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8929, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1519, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8930, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8931, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8932, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8933, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8934, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8935, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1491, UINT16_MAX, 8936, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1492, UINT16_MAX, 8937, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1493, UINT16_MAX, 8938, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8939, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1494, UINT16_MAX, 8940, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1495, UINT16_MAX, 8941, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1496, UINT16_MAX, 8942, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1497, UINT16_MAX, 8943, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1498, UINT16_MAX, 8944, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1499, UINT16_MAX, 8945, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1500, UINT16_MAX, 8946, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1501, UINT16_MAX, 8947, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1502, UINT16_MAX, 8948, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1503, UINT16_MAX, 8949, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1504, UINT16_MAX, 8950, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8951, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1505, UINT16_MAX, 8952, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1506, UINT16_MAX, 8953, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1507, UINT16_MAX, 8954, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1508, UINT16_MAX, 8955, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1509, UINT16_MAX, 8956, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1510, UINT16_MAX, 8957, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1511, UINT16_MAX, 8958, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 0, UINT16_MAX, 8959, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1512, UINT16_MAX, 8960, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1513, UINT16_MAX, 8961, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1514, UINT16_MAX, 8962, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1, UINT16_MAX, 8963, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3, UINT16_MAX, 8964, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4, UINT16_MAX, 8965, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 485, UINT16_MAX, 8966, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 486, UINT16_MAX, 8967, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1515, UINT16_MAX, 8968, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6, UINT16_MAX, 8969, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8970, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 10, UINT16_MAX, 8971, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 12, UINT16_MAX, 8972, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 355, UINT16_MAX, 8973, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 14, UINT16_MAX, 8974, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 479, UINT16_MAX, 8975, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1516, UINT16_MAX, 8976, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1517, UINT16_MAX, 8977, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 15, UINT16_MAX, 8978, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 19, UINT16_MAX, 8979, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 20, UINT16_MAX, 8980, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1518, UINT16_MAX, 8981, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 493, UINT16_MAX, 8982, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 21, UINT16_MAX, 8983, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1519, UINT16_MAX, 8984, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 846, UINT16_MAX, 8985, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 847, UINT16_MAX, 8986, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 848, UINT16_MAX, 8987, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 863, UINT16_MAX, 8988, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 864, UINT16_MAX, 8989, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 8, UINT16_MAX, 8990, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 17, UINT16_MAX, 8991, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 20, UINT16_MAX, 8992, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 21, UINT16_MAX, 8993, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 846, UINT16_MAX, 8994, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 847, UINT16_MAX, 8995, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 859, UINT16_MAX, 8996, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 863, UINT16_MAX, 8997, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 864, UINT16_MAX, 8998, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8999, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9000, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9001, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9002, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9003, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9004, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9005, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9006, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9007, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9008, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9009, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9010, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9011, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 968, UINT16_MAX, 9012, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9013, UINT16_MAX, 9013, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9014, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1526, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9015, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9016, UINT16_MAX, 9016, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9017, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9018, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9019, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9020, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9021, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9022, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9023, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1529, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9024, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9025, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9026, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9027, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9028, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9029, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9030, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9031, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9032, UINT16_MAX, 9032, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9033, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9034, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7052, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9035, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9036, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9037, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9038, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9039, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9040, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9041, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9042, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9043, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1520, UINT16_MAX, 9044, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2, UINT16_MAX, 9045, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1521, UINT16_MAX, 9046, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 94, UINT16_MAX, 9047, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1515, UINT16_MAX, 9048, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5, UINT16_MAX, 9049, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1522, UINT16_MAX, 9050, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1523, UINT16_MAX, 9051, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1524, UINT16_MAX, 9052, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 491, UINT16_MAX, 9053, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 490, UINT16_MAX, 9054, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1525, UINT16_MAX, 9055, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1526, UINT16_MAX, 9056, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1527, UINT16_MAX, 9057, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1528, UINT16_MAX, 9058, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1529, UINT16_MAX, 9059, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1530, UINT16_MAX, 9060, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1531, UINT16_MAX, 9061, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1532, UINT16_MAX, 9062, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 494, UINT16_MAX, 9063, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1533, UINT16_MAX, 9064, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1534, UINT16_MAX, 9065, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 495, UINT16_MAX, 9066, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1535, UINT16_MAX, 9067, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1536, UINT16_MAX, 9068, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 505, UINT16_MAX, 9069, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1537, UINT16_MAX, 9070, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 778, UINT16_MAX, 9071, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 513, UINT16_MAX, 9072, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1538, UINT16_MAX, 9073, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 514, UINT16_MAX, 9074, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 779, UINT16_MAX, 9075, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 25, UINT16_MAX, 9076, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1539, UINT16_MAX, 9077, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1540, UINT16_MAX, 9078, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 517, UINT16_MAX, 9079, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 852, UINT16_MAX, 9080, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 214, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 218, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17925, 1543, UINT16_MAX, 1543, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17928, UINT16_MAX, 9081, UINT16_MAX, 9081, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17930, 1548, UINT16_MAX, 1548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17933, UINT16_MAX, 9082, UINT16_MAX, 9082, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17935, 1553, UINT16_MAX, 1553, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17938, UINT16_MAX, 9083, UINT16_MAX, 9083, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17940, 1558, UINT16_MAX, 1558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17943, UINT16_MAX, 9084, UINT16_MAX, 9084, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17945, 1563, UINT16_MAX, 1563, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17948, UINT16_MAX, 9085, UINT16_MAX, 9085, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17950, 1568, UINT16_MAX, 1568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17953, UINT16_MAX, 9086, UINT16_MAX, 9086, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17955, 1573, UINT16_MAX, 1573, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17958, UINT16_MAX, 9087, UINT16_MAX, 9087, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17960, 1578, UINT16_MAX, 1578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17963, UINT16_MAX, 9088, UINT16_MAX, 9088, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17965, 1583, UINT16_MAX, 1583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17968, UINT16_MAX, 9089, UINT16_MAX, 9089, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17970, 1588, UINT16_MAX, 1588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17973, UINT16_MAX, 9090, UINT16_MAX, 9090, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17975, 1593, UINT16_MAX, 1593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17978, UINT16_MAX, 9091, UINT16_MAX, 9091, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17980, 1598, UINT16_MAX, 1598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17983, UINT16_MAX, 9092, UINT16_MAX, 9092, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17985, 1603, UINT16_MAX, 1603, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17988, UINT16_MAX, 9093, UINT16_MAX, 9093, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17990, 1608, UINT16_MAX, 1608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17993, UINT16_MAX, 9094, UINT16_MAX, 9094, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17995, 1613, UINT16_MAX, 1613, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17998, UINT16_MAX, 9095, UINT16_MAX, 9095, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18000, 1618, UINT16_MAX, 1618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18003, UINT16_MAX, 9096, UINT16_MAX, 9096, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18005, 1623, UINT16_MAX, 1623, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18008, UINT16_MAX, 9097, UINT16_MAX, 9097, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18010, 1628, UINT16_MAX, 1628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18013, UINT16_MAX, 9098, UINT16_MAX, 9098, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18015, 1633, UINT16_MAX, 1633, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18018, UINT16_MAX, 9099, UINT16_MAX, 9099, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18020, 1638, UINT16_MAX, 1638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18023, UINT16_MAX, 9100, UINT16_MAX, 9100, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18025, 1643, UINT16_MAX, 1643, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18028, UINT16_MAX, 9101, UINT16_MAX, 9101, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18030, 1648, UINT16_MAX, 1648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18033, UINT16_MAX, 9102, UINT16_MAX, 9102, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18035, 1653, UINT16_MAX, 1653, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18038, UINT16_MAX, 9103, UINT16_MAX, 9103, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18040, 1658, UINT16_MAX, 1658, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18043, UINT16_MAX, 9104, UINT16_MAX, 9104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18045, 1663, UINT16_MAX, 1663, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18048, UINT16_MAX, 9105, UINT16_MAX, 9105, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18050, 1668, UINT16_MAX, 1668, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18053, UINT16_MAX, 9106, UINT16_MAX, 9106, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18055, 1673, UINT16_MAX, 1673, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18058, UINT16_MAX, 9107, UINT16_MAX, 9107, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18060, 1678, UINT16_MAX, 1678, UINT16_MAX, 2884, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18063, UINT16_MAX, 9108, UINT16_MAX, 9108, 2887, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18065, 1683, UINT16_MAX, 1683, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18068, UINT16_MAX, 9109, UINT16_MAX, 9109, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18070, 1688, UINT16_MAX, 1688, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18073, UINT16_MAX, 9110, UINT16_MAX, 9110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18075, 1693, UINT16_MAX, 1693, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18078, UINT16_MAX, 9111, UINT16_MAX, 9111, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18080, 1698, UINT16_MAX, 1698, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18083, UINT16_MAX, 9112, UINT16_MAX, 9112, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18085, 1703, UINT16_MAX, 1703, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18088, UINT16_MAX, 9113, UINT16_MAX, 9113, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18090, 1708, UINT16_MAX, 1708, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18093, UINT16_MAX, 9114, UINT16_MAX, 9114, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18095, 1713, UINT16_MAX, 1713, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18098, UINT16_MAX, 9115, UINT16_MAX, 9115, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18100, 1718, UINT16_MAX, 1718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18103, UINT16_MAX, 9116, UINT16_MAX, 9116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18105, 1723, UINT16_MAX, 1723, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18108, UINT16_MAX, 9117, UINT16_MAX, 9117, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18110, 1728, UINT16_MAX, 1728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18113, UINT16_MAX, 9118, UINT16_MAX, 9118, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18115, 1733, UINT16_MAX, 1733, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18118, UINT16_MAX, 9119, UINT16_MAX, 9119, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18120, 1738, UINT16_MAX, 1738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18123, UINT16_MAX, 9120, UINT16_MAX, 9120, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18125, 1743, UINT16_MAX, 1743, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18128, UINT16_MAX, 9121, UINT16_MAX, 9121, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18130, 1748, UINT16_MAX, 1748, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18133, UINT16_MAX, 9122, UINT16_MAX, 9122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18135, 1753, UINT16_MAX, 1753, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18138, UINT16_MAX, 9123, UINT16_MAX, 9123, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18140, 1758, UINT16_MAX, 1758, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18143, UINT16_MAX, 9124, UINT16_MAX, 9124, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18145, 1763, UINT16_MAX, 1763, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18148, UINT16_MAX, 9125, UINT16_MAX, 9125, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18150, 1768, UINT16_MAX, 1768, UINT16_MAX, 3006, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18153, UINT16_MAX, 9126, UINT16_MAX, 9126, 3009, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18155, 1773, UINT16_MAX, 1773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18158, UINT16_MAX, 9127, UINT16_MAX, 9127, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18160, 1778, UINT16_MAX, 1778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18163, UINT16_MAX, 9128, UINT16_MAX, 9128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18165, 1783, UINT16_MAX, 1783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18168, UINT16_MAX, 9129, UINT16_MAX, 9129, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18170, 1788, UINT16_MAX, 1788, UINT16_MAX, 3024, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18173, UINT16_MAX, 9130, UINT16_MAX, 9130, 3027, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18175, 1793, UINT16_MAX, 1793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18178, UINT16_MAX, 9131, UINT16_MAX, 9131, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18180, 1798, UINT16_MAX, 1798, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18183, UINT16_MAX, 9132, UINT16_MAX, 9132, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18185, 1803, UINT16_MAX, 1803, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18188, UINT16_MAX, 9133, UINT16_MAX, 9133, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18190, 1808, UINT16_MAX, 1808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18193, UINT16_MAX, 9134, UINT16_MAX, 9134, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18195, 1813, UINT16_MAX, 1813, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18198, UINT16_MAX, 9135, UINT16_MAX, 9135, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18200, 1818, UINT16_MAX, 1818, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18203, UINT16_MAX, 9136, UINT16_MAX, 9136, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18205, 1823, UINT16_MAX, 1823, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18208, UINT16_MAX, 9137, UINT16_MAX, 9137, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18210, 1828, UINT16_MAX, 1828, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18213, UINT16_MAX, 9138, UINT16_MAX, 9138, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18215, 1833, UINT16_MAX, 1833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18218, UINT16_MAX, 9139, UINT16_MAX, 9139, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18220, 1838, UINT16_MAX, 1838, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18223, UINT16_MAX, 9140, UINT16_MAX, 9140, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18225, 1843, UINT16_MAX, 1843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18228, UINT16_MAX, 9141, UINT16_MAX, 9141, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18230, 1848, UINT16_MAX, 1848, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18233, UINT16_MAX, 9142, UINT16_MAX, 9142, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18235, 1853, UINT16_MAX, 1853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18238, UINT16_MAX, 9143, UINT16_MAX, 9143, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18240, 1858, UINT16_MAX, 1858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18243, UINT16_MAX, 9144, UINT16_MAX, 9144, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18245, 1863, UINT16_MAX, 1863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18248, UINT16_MAX, 9145, UINT16_MAX, 9145, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18250, 1868, UINT16_MAX, 1868, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18253, UINT16_MAX, 9146, UINT16_MAX, 9146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18255, 1873, UINT16_MAX, 1873, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18258, UINT16_MAX, 9147, UINT16_MAX, 9147, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18260, 1878, UINT16_MAX, 1878, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18263, UINT16_MAX, 9148, UINT16_MAX, 9148, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18265, 1883, UINT16_MAX, 1883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18268, UINT16_MAX, 9149, UINT16_MAX, 9149, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18270, 1888, UINT16_MAX, 1888, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18273, UINT16_MAX, 9150, UINT16_MAX, 9150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18275, 1893, UINT16_MAX, 1893, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18278, UINT16_MAX, 9151, UINT16_MAX, 9151, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18280, 1898, UINT16_MAX, 1898, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18283, UINT16_MAX, 9152, UINT16_MAX, 9152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18285, 1903, UINT16_MAX, 1903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18288, UINT16_MAX, 9153, UINT16_MAX, 9153, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18290, 1908, UINT16_MAX, 1908, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18293, UINT16_MAX, 9154, UINT16_MAX, 9154, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18295, 1913, UINT16_MAX, 1913, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18298, UINT16_MAX, 9155, UINT16_MAX, 9155, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18300, 18300, 9156, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18302, 18302, 9157, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18304, 18304, 9158, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18306, 18306, 9159, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18308, 18308, 9160, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18310, 1783, 9129, UINT16_MAX, 9129, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9161, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9162, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 16514, UINT16_MAX, 9163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9164, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18312, 1930, UINT16_MAX, 1930, UINT16_MAX, 3241, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18315, UINT16_MAX, 9165, UINT16_MAX, 9165, 3250, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18317, 1935, UINT16_MAX, 1935, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18320, UINT16_MAX, 9166, UINT16_MAX, 9166, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18322, 1940, UINT16_MAX, 1940, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18325, UINT16_MAX, 9167, UINT16_MAX, 9167, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18327, 1945, UINT16_MAX, 1945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18330, UINT16_MAX, 9168, UINT16_MAX, 9168, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18332, 1950, UINT16_MAX, 1950, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18335, UINT16_MAX, 9169, UINT16_MAX, 9169, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18337, 1955, UINT16_MAX, 1955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18340, UINT16_MAX, 9170, UINT16_MAX, 9170, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18342, 1960, UINT16_MAX, 1960, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18345, UINT16_MAX, 9171, UINT16_MAX, 9171, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18347, 1965, UINT16_MAX, 1965, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18350, UINT16_MAX, 9172, UINT16_MAX, 9172, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18352, 1970, UINT16_MAX, 1970, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18355, UINT16_MAX, 9173, UINT16_MAX, 9173, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18357, 1975, UINT16_MAX, 1975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18360, UINT16_MAX, 9174, UINT16_MAX, 9174, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18362, 1980, UINT16_MAX, 1980, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18365, UINT16_MAX, 9175, UINT16_MAX, 9175, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18367, 1985, UINT16_MAX, 1985, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18370, UINT16_MAX, 9176, UINT16_MAX, 9176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18372, 1990, UINT16_MAX, 1990, UINT16_MAX, 3455, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18375, UINT16_MAX, 9177, UINT16_MAX, 9177, 3458, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18377, 1995, UINT16_MAX, 1995, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18380, UINT16_MAX, 9178, UINT16_MAX, 9178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18382, 2000, UINT16_MAX, 2000, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18385, UINT16_MAX, 9179, UINT16_MAX, 9179, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18387, 2005, UINT16_MAX, 2005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18390, UINT16_MAX, 9180, UINT16_MAX, 9180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18392, 2010, UINT16_MAX, 2010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18395, UINT16_MAX, 9181, UINT16_MAX, 9181, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18397, 2015, UINT16_MAX, 2015, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18400, UINT16_MAX, 9182, UINT16_MAX, 9182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18402, 2020, UINT16_MAX, 2020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18405, UINT16_MAX, 9183, UINT16_MAX, 9183, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18407, 2025, UINT16_MAX, 2025, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18410, UINT16_MAX, 9184, UINT16_MAX, 9184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18412, 2030, UINT16_MAX, 2030, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18415, UINT16_MAX, 9185, UINT16_MAX, 9185, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18417, 2035, UINT16_MAX, 2035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18420, UINT16_MAX, 9186, UINT16_MAX, 9186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18422, 2040, UINT16_MAX, 2040, UINT16_MAX, 3559, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18425, UINT16_MAX, 9187, UINT16_MAX, 9187, 3562, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18427, 2045, UINT16_MAX, 2045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18430, UINT16_MAX, 9188, UINT16_MAX, 9188, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18432, 2050, UINT16_MAX, 2050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18435, UINT16_MAX, 9189, UINT16_MAX, 9189, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18437, 2055, UINT16_MAX, 2055, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18440, UINT16_MAX, 9190, UINT16_MAX, 9190, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18442, 2060, UINT16_MAX, 2060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18445, UINT16_MAX, 9191, UINT16_MAX, 9191, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18447, 2065, UINT16_MAX, 2065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18450, UINT16_MAX, 9192, UINT16_MAX, 9192, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18452, 2070, UINT16_MAX, 2070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18455, UINT16_MAX, 9193, UINT16_MAX, 9193, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18457, 2075, UINT16_MAX, 2075, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18460, UINT16_MAX, 9194, UINT16_MAX, 9194, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18462, 2080, UINT16_MAX, 2080, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18465, UINT16_MAX, 9195, UINT16_MAX, 9195, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18467, 2085, UINT16_MAX, 2085, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18470, UINT16_MAX, 9196, UINT16_MAX, 9196, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18472, 2090, UINT16_MAX, 2090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18475, UINT16_MAX, 9197, UINT16_MAX, 9197, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18477, 2095, UINT16_MAX, 2095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18480, UINT16_MAX, 9198, UINT16_MAX, 9198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18482, 2100, UINT16_MAX, 2100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18485, UINT16_MAX, 9199, UINT16_MAX, 9199, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18487, 2105, UINT16_MAX, 2105, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18490, UINT16_MAX, 9200, UINT16_MAX, 9200, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18492, 2110, UINT16_MAX, 2110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18495, UINT16_MAX, 9201, UINT16_MAX, 9201, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18497, 2115, UINT16_MAX, 2115, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18500, UINT16_MAX, 9202, UINT16_MAX, 9202, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18502, 2120, UINT16_MAX, 2120, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18505, UINT16_MAX, 9203, UINT16_MAX, 9203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18507, 2125, UINT16_MAX, 2125, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18510, UINT16_MAX, 9204, UINT16_MAX, 9204, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18512, 2130, UINT16_MAX, 2130, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18515, UINT16_MAX, 9205, UINT16_MAX, 9205, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18517, 2135, UINT16_MAX, 2135, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18520, UINT16_MAX, 9206, UINT16_MAX, 9206, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18522, 2140, UINT16_MAX, 2140, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18525, UINT16_MAX, 9207, UINT16_MAX, 9207, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18527, 2145, UINT16_MAX, 2145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18530, UINT16_MAX, 9208, UINT16_MAX, 9208, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18532, 2150, UINT16_MAX, 2150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18535, UINT16_MAX, 9209, UINT16_MAX, 9209, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2153, UINT16_MAX, 2153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9210, UINT16_MAX, 9210, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2154, UINT16_MAX, 2154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9211, UINT16_MAX, 9211, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2155, UINT16_MAX, 2155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9212, UINT16_MAX, 9212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18540, UINT16_MAX, 9213, UINT16_MAX, 9213, 3761, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18542, UINT16_MAX, 9214, UINT16_MAX, 9214, 3814, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18544, UINT16_MAX, 9215, UINT16_MAX, 9215, 4793, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18546, UINT16_MAX, 9216, UINT16_MAX, 9216, 4796, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18548, UINT16_MAX, 9217, UINT16_MAX, 9217, 4799, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18550, UINT16_MAX, 9218, UINT16_MAX, 9218, 4802, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18552, UINT16_MAX, 9219, UINT16_MAX, 9219, 4805, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18554, UINT16_MAX, 9220, UINT16_MAX, 9220, 4808, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18556, 2174, UINT16_MAX, 2174, UINT16_MAX, 3867, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18559, 2177, UINT16_MAX, 2177, UINT16_MAX, 3920, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18562, 2180, UINT16_MAX, 2180, UINT16_MAX, 4811, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18565, 2183, UINT16_MAX, 2183, UINT16_MAX, 4814, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18568, 2186, UINT16_MAX, 2186, UINT16_MAX, 4817, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18571, 2189, UINT16_MAX, 2189, UINT16_MAX, 4820, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18574, 2192, UINT16_MAX, 2192, UINT16_MAX, 4823, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18577, 2195, UINT16_MAX, 2195, UINT16_MAX, 4826, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18580, UINT16_MAX, 9221, UINT16_MAX, 9221, 3973, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18582, UINT16_MAX, 9222, UINT16_MAX, 9222, 3977, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18584, UINT16_MAX, 9223, UINT16_MAX, 9223, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18586, UINT16_MAX, 9224, UINT16_MAX, 9224, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18588, UINT16_MAX, 9225, UINT16_MAX, 9225, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18590, UINT16_MAX, 9226, UINT16_MAX, 9226, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18592, 2210, UINT16_MAX, 2210, UINT16_MAX, 3981, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18595, 2213, UINT16_MAX, 2213, UINT16_MAX, 3985, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18598, 2216, UINT16_MAX, 2216, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18601, 2219, UINT16_MAX, 2219, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18604, 2222, UINT16_MAX, 2222, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18607, 2225, UINT16_MAX, 2225, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18610, UINT16_MAX, 9227, UINT16_MAX, 9227, 3989, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18612, UINT16_MAX, 9228, UINT16_MAX, 9228, 4042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18614, UINT16_MAX, 9229, UINT16_MAX, 9229, 4829, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18616, UINT16_MAX, 9230, UINT16_MAX, 9230, 4832, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18618, UINT16_MAX, 9231, UINT16_MAX, 9231, 4835, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18620, UINT16_MAX, 9232, UINT16_MAX, 9232, 4838, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18622, UINT16_MAX, 9233, UINT16_MAX, 9233, 4841, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18624, UINT16_MAX, 9234, UINT16_MAX, 9234, 4844, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18626, 2244, UINT16_MAX, 2244, UINT16_MAX, 4095, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18629, 2247, UINT16_MAX, 2247, UINT16_MAX, 4148, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18632, 2250, UINT16_MAX, 2250, UINT16_MAX, 4847, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18635, 2253, UINT16_MAX, 2253, UINT16_MAX, 4850, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18638, 2256, UINT16_MAX, 2256, UINT16_MAX, 4853, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18641, 2259, UINT16_MAX, 2259, UINT16_MAX, 4856, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18644, 2262, UINT16_MAX, 2262, UINT16_MAX, 4859, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18647, 2265, UINT16_MAX, 2265, UINT16_MAX, 4862, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18650, UINT16_MAX, 9235, UINT16_MAX, 9235, 4201, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18652, UINT16_MAX, 9236, UINT16_MAX, 9236, 4253, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18654, UINT16_MAX, 9237, UINT16_MAX, 9237, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18656, UINT16_MAX, 9238, UINT16_MAX, 9238, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18658, UINT16_MAX, 9239, UINT16_MAX, 9239, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18660, UINT16_MAX, 9240, UINT16_MAX, 9240, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18662, UINT16_MAX, 9241, UINT16_MAX, 9241, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18664, UINT16_MAX, 9242, UINT16_MAX, 9242, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18666, 2284, UINT16_MAX, 2284, UINT16_MAX, 4305, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18669, 2287, UINT16_MAX, 2287, UINT16_MAX, 4357, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18672, 2290, UINT16_MAX, 2290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18675, 2293, UINT16_MAX, 2293, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18678, 2296, UINT16_MAX, 2296, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18681, 2299, UINT16_MAX, 2299, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18684, 2302, UINT16_MAX, 2302, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18687, 2305, UINT16_MAX, 2305, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18690, UINT16_MAX, 9243, UINT16_MAX, 9243, 4409, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18692, UINT16_MAX, 9244, UINT16_MAX, 9244, 4413, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18694, UINT16_MAX, 9245, UINT16_MAX, 9245, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18696, UINT16_MAX, 9246, UINT16_MAX, 9246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18698, UINT16_MAX, 9247, UINT16_MAX, 9247, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18700, UINT16_MAX, 9248, UINT16_MAX, 9248, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18702, 2320, UINT16_MAX, 2320, UINT16_MAX, 4417, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18705, 2323, UINT16_MAX, 2323, UINT16_MAX, 4421, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18708, 2326, UINT16_MAX, 2326, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18711, 2329, UINT16_MAX, 2329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18714, 2332, UINT16_MAX, 2332, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18717, 2335, UINT16_MAX, 2335, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18720, 18720, 9249, UINT16_MAX, UINT16_MAX, 4425, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18722, UINT16_MAX, 9250, UINT16_MAX, 9250, 4477, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18724, 35110, 9251, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18729, UINT16_MAX, 9252, UINT16_MAX, 9252, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18731, 35117, 9253, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18736, UINT16_MAX, 9254, UINT16_MAX, 9254, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18738, 35124, 9255, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18743, UINT16_MAX, 9256, UINT16_MAX, 9256, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18745, 2363, UINT16_MAX, 2363, UINT16_MAX, 4529, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18748, 2366, UINT16_MAX, 2366, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18751, 2369, UINT16_MAX, 2369, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18754, 2372, UINT16_MAX, 2372, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18757, UINT16_MAX, 9257, UINT16_MAX, 9257, 4581, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18759, UINT16_MAX, 9258, UINT16_MAX, 9258, 4634, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18761, UINT16_MAX, 9259, UINT16_MAX, 9259, 4865, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18763, UINT16_MAX, 9260, UINT16_MAX, 9260, 4868, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18765, UINT16_MAX, 9261, UINT16_MAX, 9261, 4871, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18767, UINT16_MAX, 9262, UINT16_MAX, 9262, 4874, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18769, UINT16_MAX, 9263, UINT16_MAX, 9263, 4877, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18771, UINT16_MAX, 9264, UINT16_MAX, 9264, 4880, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18773, 2391, UINT16_MAX, 2391, UINT16_MAX, 4687, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18776, 2394, UINT16_MAX, 2394, UINT16_MAX, 4740, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18779, 2397, UINT16_MAX, 2397, UINT16_MAX, 4883, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18782, 2400, UINT16_MAX, 2400, UINT16_MAX, 4886, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18785, 2403, UINT16_MAX, 2403, UINT16_MAX, 4889, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18788, 2406, UINT16_MAX, 2406, UINT16_MAX, 4892, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18791, 2409, UINT16_MAX, 2409, UINT16_MAX, 4895, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18794, 2412, UINT16_MAX, 2412, UINT16_MAX, 4898, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18797, UINT16_MAX, 9265, UINT16_MAX, 9265, 4901, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 820, UINT16_MAX, 9266, UINT16_MAX, 9266, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18799, UINT16_MAX, 9267, UINT16_MAX, 9267, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 824, UINT16_MAX, 9268, UINT16_MAX, 9268, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18801, UINT16_MAX, 9269, UINT16_MAX, 9269, 4910, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 827, UINT16_MAX, 9270, UINT16_MAX, 9270, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18803, UINT16_MAX, 9271, UINT16_MAX, 9271, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 830, UINT16_MAX, 9272, UINT16_MAX, 9272, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18805, UINT16_MAX, 9273, UINT16_MAX, 9273, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 833, UINT16_MAX, 9274, UINT16_MAX, 9274, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18807, UINT16_MAX, 9275, UINT16_MAX, 9275, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 836, UINT16_MAX, 9276, UINT16_MAX, 9276, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18809, UINT16_MAX, 9277, UINT16_MAX, 9277, 5030, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 839, UINT16_MAX, 9278, UINT16_MAX, 9278, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18811, 18813, 9279, UINT16_MAX, 9279, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18815, 18817, 9280, UINT16_MAX, 9280, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18819, 18821, 9281, UINT16_MAX, 9281, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18823, 18825, 9282, UINT16_MAX, 9282, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18827, 18829, 9283, UINT16_MAX, 9283, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18831, 18833, 9284, UINT16_MAX, 9284, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18835, 18837, 9285, UINT16_MAX, 9285, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18839, 18841, 9286, UINT16_MAX, 9286, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18843, 18813, UINT16_MAX, 9287, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18845, 18817, UINT16_MAX, 9288, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18847, 18821, UINT16_MAX, 9289, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18849, 18825, UINT16_MAX, 9290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18851, 18829, UINT16_MAX, 9291, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18853, 18833, UINT16_MAX, 9292, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18855, 18837, UINT16_MAX, 9293, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18857, 18841, UINT16_MAX, 9294, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18859, 18861, 9295, UINT16_MAX, 9295, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18863, 18865, 9296, UINT16_MAX, 9296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18867, 18869, 9297, UINT16_MAX, 9297, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18871, 18873, 9298, UINT16_MAX, 9298, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18875, 18877, 9299, UINT16_MAX, 9299, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18879, 18881, 9300, UINT16_MAX, 9300, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18883, 18885, 9301, UINT16_MAX, 9301, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18887, 18889, 9302, UINT16_MAX, 9302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18891, 18861, UINT16_MAX, 9303, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18893, 18865, UINT16_MAX, 9304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18895, 18869, UINT16_MAX, 9305, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18897, 18873, UINT16_MAX, 9306, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18899, 18877, UINT16_MAX, 9307, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18901, 18881, UINT16_MAX, 9308, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18903, 18885, UINT16_MAX, 9309, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18905, 18889, UINT16_MAX, 9310, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18907, 18909, 9311, UINT16_MAX, 9311, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18911, 18913, 9312, UINT16_MAX, 9312, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18915, 18917, 9313, UINT16_MAX, 9313, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18919, 18921, 9314, UINT16_MAX, 9314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18923, 18925, 9315, UINT16_MAX, 9315, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18927, 18929, 9316, UINT16_MAX, 9316, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18931, 18933, 9317, UINT16_MAX, 9317, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18935, 18937, 9318, UINT16_MAX, 9318, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18939, 18909, UINT16_MAX, 9319, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18941, 18913, UINT16_MAX, 9320, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18943, 18917, UINT16_MAX, 9321, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18945, 18921, UINT16_MAX, 9322, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18947, 18925, UINT16_MAX, 9323, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18949, 18929, UINT16_MAX, 9324, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18951, 18933, UINT16_MAX, 9325, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18953, 18937, UINT16_MAX, 9326, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18955, UINT16_MAX, 9327, UINT16_MAX, 9327, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18957, UINT16_MAX, 9328, UINT16_MAX, 9328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18959, 18961, 9329, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18963, 18965, 9330, UINT16_MAX, 9330, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18967, 18969, 9331, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18971, 18971, 9332, UINT16_MAX, UINT16_MAX, 4907, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18973, 35359, 9333, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18978, 2596, UINT16_MAX, 2596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18981, 2599, UINT16_MAX, 2599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18984, 2602, UINT16_MAX, 2602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2603, 2604, UINT16_MAX, 2604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 18989, 18965, UINT16_MAX, 9334, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 18991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 807, 807, 7437, UINT16_MAX, 7437, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 18991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4919, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 18993, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 18995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18997, 18999, 9335, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19001, 19003, 9336, UINT16_MAX, 9336, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19005, 19007, 9337, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19009, 19009, 9338, UINT16_MAX, UINT16_MAX, 4916, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19011, 35397, 9339, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19016, 2634, UINT16_MAX, 2634, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2635, 2636, UINT16_MAX, 2636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19021, 2639, UINT16_MAX, 2639, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2640, 2641, UINT16_MAX, 2641, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19026, 19003, UINT16_MAX, 9340, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19034, UINT16_MAX, 9341, UINT16_MAX, 9341, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19036, UINT16_MAX, 9342, UINT16_MAX, 9342, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19038, 35424, 9343, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 2659, 33610, 9344, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19044, 19044, 9345, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19046, 35432, 9346, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19051, 2669, UINT16_MAX, 2669, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19054, 2672, UINT16_MAX, 2672, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19057, 2675, UINT16_MAX, 2675, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2676, 2677, UINT16_MAX, 2677, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19068, UINT16_MAX, 9347, UINT16_MAX, 9347, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19070, UINT16_MAX, 9348, UINT16_MAX, 9348, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19072, 35458, 9349, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 2693, 33651, 9350, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19078, 19078, 9351, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19080, UINT16_MAX, 9352, UINT16_MAX, 9352, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19082, 19082, 9353, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19084, 35470, 9354, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19089, 2707, UINT16_MAX, 2707, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19092, 2710, UINT16_MAX, 2710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19095, 2713, UINT16_MAX, 2713, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2714, 2715, UINT16_MAX, 2715, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19100, 2718, UINT16_MAX, 2718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19103, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19107, 19109, 9355, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19111, 19113, 9356, UINT16_MAX, 9356, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19115, 19117, 9357, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19119, 19119, 9358, UINT16_MAX, UINT16_MAX, 5036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19121, 35507, 9359, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19126, 2744, UINT16_MAX, 2744, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2745, 2746, UINT16_MAX, 2746, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19131, 2749, UINT16_MAX, 2749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2750, 2751, UINT16_MAX, 2751, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19136, 19113, UINT16_MAX, 9360, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4971, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, 2757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, 2758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_COMPAT, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_NOBREAK, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_ZWJ, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NOBREAK, 2759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 2762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZL, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZP, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRE, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLE, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDF, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRO, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLO, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 19152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 35538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_CS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19168, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 51940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_FSI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8, UINT16_MAX, 9361, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, 2800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, 2801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 13, UINT16_MAX, 9362, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, 2800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, 2801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 0, UINT16_MAX, 9363, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 4, UINT16_MAX, 9364, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 14, UINT16_MAX, 9365, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 23, UINT16_MAX, 9366, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 485, UINT16_MAX, 9367, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 7, UINT16_MAX, 9368, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 10, UINT16_MAX, 9369, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 11, UINT16_MAX, 9370, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 12, UINT16_MAX, 9371, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 13, UINT16_MAX, 9372, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 15, UINT16_MAX, 9373, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 18, UINT16_MAX, 9374, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 19, UINT16_MAX, 9375, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 19189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 9376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2822, UINT16_MAX, UINT16_MAX, 9377, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 9378, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 9379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 9380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 9381, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 9382, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 277, UINT16_MAX, 9383, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 9384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 9385, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 9386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 9387, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 9388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 9389, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 9390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 9391, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 9392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 9393, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 19212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 19217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 9394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2836, 866, UINT16_MAX, 866, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 9395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1501, 10, UINT16_MAX, 10, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2837, 65, UINT16_MAX, 65, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 9396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 9397, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 9398, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 9399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 9400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2839, UINT16_MAX, 2839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 9401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 9402, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 9403, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, 9404, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, 9405, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2847, UINT16_MAX, UINT16_MAX, 9406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2848, UINT16_MAX, UINT16_MAX, 9407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 2849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 9408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 9409, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 9410, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 9411, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 9412, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9413, UINT16_MAX, 9413, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 52008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1499, 2899, UINT16_MAX, 2899, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19284, 2902, UINT16_MAX, 2902, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35671, 2906, UINT16_MAX, 2906, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19291, 2909, UINT16_MAX, 2909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2910, 2911, UINT16_MAX, 2911, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19296, 2914, UINT16_MAX, 2914, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35683, 2918, UINT16_MAX, 2918, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 52071, 2924, UINT16_MAX, 2924, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19309, 2927, UINT16_MAX, 2927, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2928, 2929, UINT16_MAX, 2929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19314, 2932, UINT16_MAX, 2932, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35701, 2936, UINT16_MAX, 2936, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1502, 2937, UINT16_MAX, 2937, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2813, 2938, UINT16_MAX, 2938, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1494, 2939, UINT16_MAX, 2939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1503, 2940, UINT16_MAX, 2940, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8, UINT16_MAX, 9414, UINT16_MAX, 9414, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19325, UINT16_MAX, 9415, UINT16_MAX, 9415, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35711, UINT16_MAX, 9416, UINT16_MAX, 9416, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19330, UINT16_MAX, 9417, UINT16_MAX, 9417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21, UINT16_MAX, 9418, UINT16_MAX, 9418, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19332, UINT16_MAX, 9419, UINT16_MAX, 9419, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35718, UINT16_MAX, 9420, UINT16_MAX, 9420, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 52105, UINT16_MAX, 9421, UINT16_MAX, 9421, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19342, UINT16_MAX, 9422, UINT16_MAX, 9422, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23, UINT16_MAX, 9423, UINT16_MAX, 9423, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19344, UINT16_MAX, 9424, UINT16_MAX, 9424, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35730, UINT16_MAX, 9425, UINT16_MAX, 9425, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11, UINT16_MAX, 9426, UINT16_MAX, 9426, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2, UINT16_MAX, 9427, UINT16_MAX, 9427, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3, UINT16_MAX, 9428, UINT16_MAX, 9428, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12, UINT16_MAX, 9429, UINT16_MAX, 9429, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2965, UINT16_MAX, 2965, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9430, UINT16_MAX, 9430, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 35734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5039, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5045, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5048, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5054, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5051, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5057, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5060, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5063, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19369, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5066, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5069, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19375, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5072, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5075, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19387, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5078, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5081, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19391, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5090, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5087, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5099, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5102, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19403, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5105, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5108, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5111, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5114, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5117, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5120, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5147, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5150, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5123, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5126, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5129, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5132, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5153, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5156, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5135, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5138, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5141, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5144, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5159, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5162, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5165, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5168, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 19473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 35883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35965, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35977, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35980, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 35989, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36001, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36013, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36019, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36025, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36031, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36043, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36055, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36061, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1491, 3302, UINT16_MAX, 3302, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1493, 3303, UINT16_MAX, 3303, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2813, 3304, UINT16_MAX, 3304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1494, 3305, UINT16_MAX, 3305, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1495, 3306, UINT16_MAX, 3306, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2838, 3307, UINT16_MAX, 3307, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1497, 3308, UINT16_MAX, 3308, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1498, 3309, UINT16_MAX, 3309, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1499, 3310, UINT16_MAX, 3310, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1500, 3311, UINT16_MAX, 3311, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1501, 3312, UINT16_MAX, 3312, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1502, 3313, UINT16_MAX, 3313, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1503, 3314, UINT16_MAX, 3314, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1504, 3315, UINT16_MAX, 3315, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1505, 3316, UINT16_MAX, 3316, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1507, 3317, UINT16_MAX, 3317, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2827, 3318, UINT16_MAX, 3318, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1508, 3319, UINT16_MAX, 3319, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3320, 3321, UINT16_MAX, 3321, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1509, 3322, UINT16_MAX, 3322, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1510, 3323, UINT16_MAX, 3323, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2910, 3324, UINT16_MAX, 3324, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1511, 3325, UINT16_MAX, 3325, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2928, 3326, UINT16_MAX, 3326, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3327, 3328, UINT16_MAX, 3328, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2835, 3329, UINT16_MAX, 3329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 0, UINT16_MAX, 9431, UINT16_MAX, 9431, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1, UINT16_MAX, 9432, UINT16_MAX, 9432, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2, UINT16_MAX, 9433, UINT16_MAX, 9433, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3, UINT16_MAX, 9434, UINT16_MAX, 9434, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4, UINT16_MAX, 9435, UINT16_MAX, 9435, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5, UINT16_MAX, 9436, UINT16_MAX, 9436, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 6, UINT16_MAX, 9437, UINT16_MAX, 9437, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7, UINT16_MAX, 9438, UINT16_MAX, 9438, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 8, UINT16_MAX, 9439, UINT16_MAX, 9439, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 9, UINT16_MAX, 9440, UINT16_MAX, 9440, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 10, UINT16_MAX, 9441, UINT16_MAX, 9441, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 11, UINT16_MAX, 9442, UINT16_MAX, 9442, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12, UINT16_MAX, 9443, UINT16_MAX, 9443, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 13, UINT16_MAX, 9444, UINT16_MAX, 9444, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 14, UINT16_MAX, 9445, UINT16_MAX, 9445, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 15, UINT16_MAX, 9446, UINT16_MAX, 9446, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 16, UINT16_MAX, 9447, UINT16_MAX, 9447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 17, UINT16_MAX, 9448, UINT16_MAX, 9448, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 18, UINT16_MAX, 9449, UINT16_MAX, 9449, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 19, UINT16_MAX, 9450, UINT16_MAX, 9450, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20, UINT16_MAX, 9451, UINT16_MAX, 9451, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21, UINT16_MAX, 9452, UINT16_MAX, 9452, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 22, UINT16_MAX, 9453, UINT16_MAX, 9453, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 23, UINT16_MAX, 9454, UINT16_MAX, 9454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 24, UINT16_MAX, 9455, UINT16_MAX, 9455, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 25, UINT16_MAX, 9456, UINT16_MAX, 9456, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 52482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36103, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 19727, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5171, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3345, UINT16_MAX, 3345, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3346, UINT16_MAX, 3346, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3347, UINT16_MAX, 3347, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3348, UINT16_MAX, 3348, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3349, UINT16_MAX, 3349, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3350, UINT16_MAX, 3350, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3351, UINT16_MAX, 3351, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3352, UINT16_MAX, 3352, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3353, UINT16_MAX, 3353, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3354, UINT16_MAX, 3354, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3355, UINT16_MAX, 3355, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3356, UINT16_MAX, 3356, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3357, UINT16_MAX, 3357, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3358, UINT16_MAX, 3358, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3359, UINT16_MAX, 3359, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3360, UINT16_MAX, 3360, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3361, UINT16_MAX, 3361, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3362, UINT16_MAX, 3362, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3363, UINT16_MAX, 3363, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3364, UINT16_MAX, 3364, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3365, UINT16_MAX, 3365, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3366, UINT16_MAX, 3366, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3367, UINT16_MAX, 3367, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3368, UINT16_MAX, 3368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3369, UINT16_MAX, 3369, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3370, UINT16_MAX, 3370, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3371, UINT16_MAX, 3371, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3372, UINT16_MAX, 3372, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3373, UINT16_MAX, 3373, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3374, UINT16_MAX, 3374, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3375, UINT16_MAX, 3375, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3376, UINT16_MAX, 3376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3377, UINT16_MAX, 3377, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3378, UINT16_MAX, 3378, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3379, UINT16_MAX, 3379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3380, UINT16_MAX, 3380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3381, UINT16_MAX, 3381, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3382, UINT16_MAX, 3382, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3383, UINT16_MAX, 3383, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3384, UINT16_MAX, 3384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3385, UINT16_MAX, 3385, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3386, UINT16_MAX, 3386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3387, UINT16_MAX, 3387, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3388, UINT16_MAX, 3388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3389, UINT16_MAX, 3389, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3390, UINT16_MAX, 3390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3391, UINT16_MAX, 3391, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3392, UINT16_MAX, 3392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9457, UINT16_MAX, 9457, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9458, UINT16_MAX, 9458, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9459, UINT16_MAX, 9459, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9460, UINT16_MAX, 9460, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9461, UINT16_MAX, 9461, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9462, UINT16_MAX, 9462, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9463, UINT16_MAX, 9463, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9464, UINT16_MAX, 9464, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9465, UINT16_MAX, 9465, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9466, UINT16_MAX, 9466, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9467, UINT16_MAX, 9467, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9468, UINT16_MAX, 9468, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9469, UINT16_MAX, 9469, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9470, UINT16_MAX, 9470, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9471, UINT16_MAX, 9471, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9472, UINT16_MAX, 9472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9473, UINT16_MAX, 9473, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9474, UINT16_MAX, 9474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9475, UINT16_MAX, 9475, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9476, UINT16_MAX, 9476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9477, UINT16_MAX, 9477, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9478, UINT16_MAX, 9478, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9479, UINT16_MAX, 9479, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9480, UINT16_MAX, 9480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9481, UINT16_MAX, 9481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9482, UINT16_MAX, 9482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9483, UINT16_MAX, 9483, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9484, UINT16_MAX, 9484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9485, UINT16_MAX, 9485, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9486, UINT16_MAX, 9486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9487, UINT16_MAX, 9487, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9488, UINT16_MAX, 9488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9489, UINT16_MAX, 9489, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9490, UINT16_MAX, 9490, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9491, UINT16_MAX, 9491, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9492, UINT16_MAX, 9492, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9493, UINT16_MAX, 9493, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9494, UINT16_MAX, 9494, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9495, UINT16_MAX, 9495, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9496, UINT16_MAX, 9496, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9497, UINT16_MAX, 9497, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9498, UINT16_MAX, 9498, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9499, UINT16_MAX, 9499, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9500, UINT16_MAX, 9500, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9501, UINT16_MAX, 9501, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9502, UINT16_MAX, 9502, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9503, UINT16_MAX, 9503, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9504, UINT16_MAX, 9504, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3393, UINT16_MAX, 3393, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9505, UINT16_MAX, 9505, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3394, UINT16_MAX, 3394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3395, UINT16_MAX, 3395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3396, UINT16_MAX, 3396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9506, UINT16_MAX, 9506, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9507, UINT16_MAX, 9507, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3397, UINT16_MAX, 3397, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9508, UINT16_MAX, 9508, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3398, UINT16_MAX, 3398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9509, UINT16_MAX, 9509, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3399, UINT16_MAX, 3399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9510, UINT16_MAX, 9510, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1513, UINT16_MAX, 1513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1531, UINT16_MAX, 1531, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1512, UINT16_MAX, 1512, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1520, UINT16_MAX, 1520, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7083, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3400, UINT16_MAX, 3400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9511, UINT16_MAX, 9511, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9512, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3401, UINT16_MAX, 3401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9513, UINT16_MAX, 9513, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9514, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9515, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9516, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9517, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9518, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 9, UINT16_MAX, 9519, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2910, UINT16_MAX, 9520, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3402, UINT16_MAX, 3402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3403, UINT16_MAX, 3403, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3404, UINT16_MAX, 3404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9521, UINT16_MAX, 9521, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3405, UINT16_MAX, 3405, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9522, UINT16_MAX, 9522, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3406, UINT16_MAX, 3406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9523, UINT16_MAX, 9523, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3407, UINT16_MAX, 3407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9524, UINT16_MAX, 9524, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3408, UINT16_MAX, 3408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9525, UINT16_MAX, 9525, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3409, UINT16_MAX, 3409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9526, UINT16_MAX, 9526, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3410, UINT16_MAX, 3410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9527, UINT16_MAX, 9527, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3411, UINT16_MAX, 3411, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9528, UINT16_MAX, 9528, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3412, UINT16_MAX, 3412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9529, UINT16_MAX, 9529, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3413, UINT16_MAX, 3413, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9530, UINT16_MAX, 9530, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3414, UINT16_MAX, 3414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9531, UINT16_MAX, 9531, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3415, UINT16_MAX, 3415, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9532, UINT16_MAX, 9532, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3416, UINT16_MAX, 3416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9533, UINT16_MAX, 9533, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3417, UINT16_MAX, 3417, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9534, UINT16_MAX, 9534, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3418, UINT16_MAX, 3418, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9535, UINT16_MAX, 9535, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3419, UINT16_MAX, 3419, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9536, UINT16_MAX, 9536, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3420, UINT16_MAX, 3420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9537, UINT16_MAX, 9537, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3421, UINT16_MAX, 3421, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9538, UINT16_MAX, 9538, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3422, UINT16_MAX, 3422, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9539, UINT16_MAX, 9539, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3423, UINT16_MAX, 3423, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9540, UINT16_MAX, 9540, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3424, UINT16_MAX, 3424, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9541, UINT16_MAX, 9541, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3425, UINT16_MAX, 3425, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9542, UINT16_MAX, 9542, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3426, UINT16_MAX, 3426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9543, UINT16_MAX, 9543, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3427, UINT16_MAX, 3427, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9544, UINT16_MAX, 9544, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3428, UINT16_MAX, 3428, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9545, UINT16_MAX, 9545, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3429, UINT16_MAX, 3429, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9546, UINT16_MAX, 9546, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3430, UINT16_MAX, 3430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9547, UINT16_MAX, 9547, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3431, UINT16_MAX, 3431, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9548, UINT16_MAX, 9548, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3432, UINT16_MAX, 3432, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9549, UINT16_MAX, 9549, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3433, UINT16_MAX, 3433, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9550, UINT16_MAX, 9550, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3434, UINT16_MAX, 3434, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9551, UINT16_MAX, 9551, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3435, UINT16_MAX, 3435, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9552, UINT16_MAX, 9552, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3436, UINT16_MAX, 3436, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9553, UINT16_MAX, 9553, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3437, UINT16_MAX, 3437, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9554, UINT16_MAX, 9554, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3438, UINT16_MAX, 3438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9555, UINT16_MAX, 9555, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3439, UINT16_MAX, 3439, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9556, UINT16_MAX, 9556, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3440, UINT16_MAX, 3440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9557, UINT16_MAX, 9557, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3441, UINT16_MAX, 3441, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9558, UINT16_MAX, 9558, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3442, UINT16_MAX, 3442, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9559, UINT16_MAX, 9559, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3443, UINT16_MAX, 3443, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9560, UINT16_MAX, 9560, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3444, UINT16_MAX, 3444, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9561, UINT16_MAX, 9561, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3445, UINT16_MAX, 3445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9562, UINT16_MAX, 9562, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3446, UINT16_MAX, 3446, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9563, UINT16_MAX, 9563, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3447, UINT16_MAX, 3447, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9564, UINT16_MAX, 9564, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3448, UINT16_MAX, 3448, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9565, UINT16_MAX, 9565, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3449, UINT16_MAX, 3449, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9566, UINT16_MAX, 9566, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3450, UINT16_MAX, 3450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9567, UINT16_MAX, 9567, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3451, UINT16_MAX, 3451, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9568, UINT16_MAX, 9568, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3452, UINT16_MAX, 3452, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9569, UINT16_MAX, 9569, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3453, UINT16_MAX, 3453, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9570, UINT16_MAX, 9570, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9571, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3454, UINT16_MAX, 3454, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9572, UINT16_MAX, 9572, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3455, UINT16_MAX, 3455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9573, UINT16_MAX, 9573, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3456, UINT16_MAX, 3456, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9574, UINT16_MAX, 9574, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9575, UINT16_MAX, 9575, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9576, UINT16_MAX, 9576, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9577, UINT16_MAX, 9577, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9578, UINT16_MAX, 9578, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9579, UINT16_MAX, 9579, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9580, UINT16_MAX, 9580, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9581, UINT16_MAX, 9581, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9582, UINT16_MAX, 9582, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9583, UINT16_MAX, 9583, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9584, UINT16_MAX, 9584, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9585, UINT16_MAX, 9585, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9586, UINT16_MAX, 9586, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9587, UINT16_MAX, 9587, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9588, UINT16_MAX, 9588, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9589, UINT16_MAX, 9589, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9590, UINT16_MAX, 9590, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9591, UINT16_MAX, 9591, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9592, UINT16_MAX, 9592, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9593, UINT16_MAX, 9593, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9594, UINT16_MAX, 9594, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9595, UINT16_MAX, 9595, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9596, UINT16_MAX, 9596, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9597, UINT16_MAX, 9597, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9598, UINT16_MAX, 9598, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9599, UINT16_MAX, 9599, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9600, UINT16_MAX, 9600, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9601, UINT16_MAX, 9601, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9602, UINT16_MAX, 9602, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9603, UINT16_MAX, 9603, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9604, UINT16_MAX, 9604, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9605, UINT16_MAX, 9605, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9606, UINT16_MAX, 9606, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9607, UINT16_MAX, 9607, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9608, UINT16_MAX, 9608, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9609, UINT16_MAX, 9609, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9610, UINT16_MAX, 9610, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9611, UINT16_MAX, 9611, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9612, UINT16_MAX, 9612, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9613, UINT16_MAX, 9613, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9614, UINT16_MAX, 9614, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_WIDE, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 224, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5239, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5174, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20061, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5177, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5180, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20065, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5183, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5186, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5189, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20071, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5192, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5195, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5198, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20077, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5201, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20079, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5204, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5207, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20083, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5210, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20085, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5213, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20087, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5216, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20089, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5219, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20091, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20093, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5223, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20095, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20097, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5227, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20099, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20101, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5231, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20103, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20105, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5235, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20107, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20109, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32820, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32821, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20113, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20115, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5242, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, 20117, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, 20119, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5310, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5245, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20121, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5248, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5251, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20125, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5254, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20127, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5257, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5260, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20131, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5263, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20133, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5266, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20135, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5269, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20137, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5272, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5275, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20141, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5278, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20143, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5281, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5284, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5287, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5290, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20151, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5294, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20155, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5298, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5302, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5306, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5313, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5316, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5319, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5322, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 20179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5325, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, 20181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, 20183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3806, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3808, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3831, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3832, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3833, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53099, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53109, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53119, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36808, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36832, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 36916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 53361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 53367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4239, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4241, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 20695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 37081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 20700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 37086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4334, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37239, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21001, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37387, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21071, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21100, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21106, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 37557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 37560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 53981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54125, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21384, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 37811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 37814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 37901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5136, UINT16_MAX, 5136, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9615, UINT16_MAX, 9615, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5137, UINT16_MAX, 5137, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9616, UINT16_MAX, 9616, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5138, UINT16_MAX, 5138, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9617, UINT16_MAX, 9617, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5139, UINT16_MAX, 5139, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9618, UINT16_MAX, 9618, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5140, UINT16_MAX, 5140, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9619, UINT16_MAX, 9619, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1445, UINT16_MAX, 1445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8897, UINT16_MAX, 8897, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5141, UINT16_MAX, 5141, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9620, UINT16_MAX, 9620, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5142, UINT16_MAX, 5142, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9621, UINT16_MAX, 9621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5143, UINT16_MAX, 5143, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9622, UINT16_MAX, 9622, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5144, UINT16_MAX, 5144, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9623, UINT16_MAX, 9623, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5145, UINT16_MAX, 5145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9624, UINT16_MAX, 9624, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5146, UINT16_MAX, 5146, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9625, UINT16_MAX, 9625, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5147, UINT16_MAX, 5147, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9626, UINT16_MAX, 9626, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5148, UINT16_MAX, 5148, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9627, UINT16_MAX, 9627, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5149, UINT16_MAX, 5149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9628, UINT16_MAX, 9628, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5150, UINT16_MAX, 5150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9629, UINT16_MAX, 9629, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5151, UINT16_MAX, 5151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9630, UINT16_MAX, 9630, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5152, UINT16_MAX, 5152, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9631, UINT16_MAX, 9631, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5153, UINT16_MAX, 5153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9632, UINT16_MAX, 9632, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5154, UINT16_MAX, 5154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9633, UINT16_MAX, 9633, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5155, UINT16_MAX, 5155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9634, UINT16_MAX, 9634, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5156, UINT16_MAX, 5156, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9635, UINT16_MAX, 9635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5157, UINT16_MAX, 5157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9636, UINT16_MAX, 9636, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5158, UINT16_MAX, 5158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9637, UINT16_MAX, 9637, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5159, UINT16_MAX, 5159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9638, UINT16_MAX, 9638, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5160, UINT16_MAX, 5160, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9639, UINT16_MAX, 9639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5161, UINT16_MAX, 5161, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9640, UINT16_MAX, 9640, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5162, UINT16_MAX, 5162, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9641, UINT16_MAX, 9641, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5163, UINT16_MAX, 5163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9642, UINT16_MAX, 9642, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5164, UINT16_MAX, 5164, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9643, UINT16_MAX, 9643, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5165, UINT16_MAX, 5165, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9644, UINT16_MAX, 9644, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5166, UINT16_MAX, 5166, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9645, UINT16_MAX, 9645, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5167, UINT16_MAX, 5167, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9646, UINT16_MAX, 9646, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5168, UINT16_MAX, 5168, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9647, UINT16_MAX, 9647, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5169, UINT16_MAX, 5169, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9648, UINT16_MAX, 9648, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5170, UINT16_MAX, 5170, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9649, UINT16_MAX, 9649, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5171, UINT16_MAX, 5171, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9650, UINT16_MAX, 9650, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 981, UINT16_MAX, 9651, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 983, UINT16_MAX, 9652, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5172, UINT16_MAX, 5172, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9653, UINT16_MAX, 9653, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5173, UINT16_MAX, 5173, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9654, UINT16_MAX, 9654, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5174, UINT16_MAX, 5174, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9655, UINT16_MAX, 9655, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5175, UINT16_MAX, 5175, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9656, UINT16_MAX, 9656, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5176, UINT16_MAX, 5176, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9657, UINT16_MAX, 9657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5177, UINT16_MAX, 5177, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9658, UINT16_MAX, 9658, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5178, UINT16_MAX, 5178, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9659, UINT16_MAX, 9659, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9660, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9661, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5179, UINT16_MAX, 5179, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9662, UINT16_MAX, 9662, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5180, UINT16_MAX, 5180, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9663, UINT16_MAX, 9663, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5181, UINT16_MAX, 5181, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9664, UINT16_MAX, 9664, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5182, UINT16_MAX, 5182, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9665, UINT16_MAX, 9665, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5183, UINT16_MAX, 5183, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9666, UINT16_MAX, 9666, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5184, UINT16_MAX, 5184, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9667, UINT16_MAX, 9667, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5185, UINT16_MAX, 5185, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9668, UINT16_MAX, 9668, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5186, UINT16_MAX, 5186, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9669, UINT16_MAX, 9669, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5187, UINT16_MAX, 5187, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9670, UINT16_MAX, 9670, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5188, UINT16_MAX, 5188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9671, UINT16_MAX, 9671, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5189, UINT16_MAX, 5189, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9672, UINT16_MAX, 9672, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5190, UINT16_MAX, 5190, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9673, UINT16_MAX, 9673, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5191, UINT16_MAX, 5191, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9674, UINT16_MAX, 9674, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5192, UINT16_MAX, 5192, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9675, UINT16_MAX, 9675, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5193, UINT16_MAX, 5193, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9676, UINT16_MAX, 9676, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5194, UINT16_MAX, 5194, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9677, UINT16_MAX, 9677, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5195, UINT16_MAX, 5195, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9678, UINT16_MAX, 9678, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5196, UINT16_MAX, 5196, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9679, UINT16_MAX, 9679, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5197, UINT16_MAX, 5197, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9680, UINT16_MAX, 9680, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5198, UINT16_MAX, 5198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9681, UINT16_MAX, 9681, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5199, UINT16_MAX, 5199, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9682, UINT16_MAX, 9682, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5200, UINT16_MAX, 5200, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9683, UINT16_MAX, 9683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5201, UINT16_MAX, 5201, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9684, UINT16_MAX, 9684, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5202, UINT16_MAX, 5202, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9685, UINT16_MAX, 9685, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5203, UINT16_MAX, 5203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9686, UINT16_MAX, 9686, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5204, UINT16_MAX, 5204, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9687, UINT16_MAX, 9687, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5205, UINT16_MAX, 5205, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9688, UINT16_MAX, 9688, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5206, UINT16_MAX, 5206, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9689, UINT16_MAX, 9689, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5207, UINT16_MAX, 5207, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9690, UINT16_MAX, 9690, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5208, UINT16_MAX, 5208, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9691, UINT16_MAX, 9691, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5209, UINT16_MAX, 5209, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9692, UINT16_MAX, 9692, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5209, UINT16_MAX, 9693, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9694, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9695, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9696, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9697, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9698, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9699, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9700, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9701, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5210, UINT16_MAX, 5210, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9702, UINT16_MAX, 9702, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5211, UINT16_MAX, 5211, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9703, UINT16_MAX, 9703, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5212, UINT16_MAX, 5212, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5213, UINT16_MAX, 5213, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9704, UINT16_MAX, 9704, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5214, UINT16_MAX, 5214, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9705, UINT16_MAX, 9705, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5215, UINT16_MAX, 5215, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9706, UINT16_MAX, 9706, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5216, UINT16_MAX, 5216, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9707, UINT16_MAX, 9707, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5217, UINT16_MAX, 5217, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9708, UINT16_MAX, 9708, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5218, UINT16_MAX, 5218, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9709, UINT16_MAX, 9709, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1524, UINT16_MAX, 1524, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7066, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5219, UINT16_MAX, 5219, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9710, UINT16_MAX, 9710, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5220, UINT16_MAX, 5220, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9711, UINT16_MAX, 9711, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9712, UINT16_MAX, 9712, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9713, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5221, UINT16_MAX, 5221, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9714, UINT16_MAX, 9714, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5222, UINT16_MAX, 5222, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9715, UINT16_MAX, 9715, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5223, UINT16_MAX, 5223, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9716, UINT16_MAX, 9716, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5224, UINT16_MAX, 5224, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9717, UINT16_MAX, 9717, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5225, UINT16_MAX, 5225, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9718, UINT16_MAX, 9718, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5226, UINT16_MAX, 5226, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9719, UINT16_MAX, 9719, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5227, UINT16_MAX, 5227, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9720, UINT16_MAX, 9720, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5228, UINT16_MAX, 5228, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9721, UINT16_MAX, 9721, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5229, UINT16_MAX, 5229, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9722, UINT16_MAX, 9722, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5230, UINT16_MAX, 5230, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9723, UINT16_MAX, 9723, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 785, UINT16_MAX, 785, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1515, UINT16_MAX, 1515, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1523, UINT16_MAX, 1523, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5231, UINT16_MAX, 5231, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1525, UINT16_MAX, 1525, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9724, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5232, UINT16_MAX, 5232, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5233, UINT16_MAX, 5233, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1527, UINT16_MAX, 1527, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5234, UINT16_MAX, 5234, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5235, UINT16_MAX, 5235, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9725, UINT16_MAX, 9725, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5236, UINT16_MAX, 5236, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9726, UINT16_MAX, 9726, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5237, UINT16_MAX, 5237, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9727, UINT16_MAX, 9727, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5238, UINT16_MAX, 5238, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9728, UINT16_MAX, 9728, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5239, UINT16_MAX, 5239, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9729, UINT16_MAX, 9729, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5240, UINT16_MAX, 5240, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9730, UINT16_MAX, 9730, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5241, UINT16_MAX, 5241, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9731, UINT16_MAX, 9731, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5242, UINT16_MAX, 5242, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9732, UINT16_MAX, 9732, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5243, UINT16_MAX, 5243, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1536, UINT16_MAX, 1536, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5244, UINT16_MAX, 5244, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5245, UINT16_MAX, 5245, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9733, UINT16_MAX, 9733, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5246, UINT16_MAX, 5246, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9734, UINT16_MAX, 9734, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5247, UINT16_MAX, 5247, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9735, UINT16_MAX, 9735, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9736, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9737, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5248, UINT16_MAX, 5248, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9738, UINT16_MAX, 9738, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5249, UINT16_MAX, 5249, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9739, UINT16_MAX, 9739, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2813, UINT16_MAX, 9740, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2838, UINT16_MAX, 9741, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2827, UINT16_MAX, 9742, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5250, UINT16_MAX, 5250, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9743, UINT16_MAX, 9743, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5251, UINT16_MAX, 9744, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 371, UINT16_MAX, 9745, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9746, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9747, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9748, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9749, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9750, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9751, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9752, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9753, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 5252, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9754, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9755, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9756, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9757, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9758, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9759, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9760, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9761, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9762, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9763, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9764, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9765, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9766, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9767, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9768, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9769, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9770, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9771, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9772, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9773, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9774, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9775, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9776, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9777, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9778, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9779, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 5253, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9780, UINT16_MAX, 9780, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9781, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9782, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9783, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9784, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9785, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9786, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9787, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5174, UINT16_MAX, 9788, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5252, UINT16_MAX, 9789, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3394, UINT16_MAX, 9790, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5253, UINT16_MAX, 9791, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9792, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9793, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9794, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9795, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9796, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9797, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7049, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7081, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9798, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5254, UINT16_MAX, 9799, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5255, 5255, UINT16_MAX, 5255, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5256, 5256, UINT16_MAX, 5256, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5257, 5257, UINT16_MAX, 5257, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5258, 5258, UINT16_MAX, 5258, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5259, 5259, UINT16_MAX, 5259, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5260, 5260, UINT16_MAX, 5260, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5261, 5261, UINT16_MAX, 5261, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5262, 5262, UINT16_MAX, 5262, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5263, 5263, UINT16_MAX, 5263, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5264, 5264, UINT16_MAX, 5264, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5265, 5265, UINT16_MAX, 5265, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5266, 5266, UINT16_MAX, 5266, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5267, 5267, UINT16_MAX, 5267, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5268, 5268, UINT16_MAX, 5268, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5269, 5269, UINT16_MAX, 5269, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5270, 5270, UINT16_MAX, 5270, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5271, 5271, UINT16_MAX, 5271, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5272, 5272, UINT16_MAX, 5272, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5273, 5273, UINT16_MAX, 5273, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5274, 5274, UINT16_MAX, 5274, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5275, 5275, UINT16_MAX, 5275, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5276, 5276, UINT16_MAX, 5276, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5277, 5277, UINT16_MAX, 5277, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5278, 5278, UINT16_MAX, 5278, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5279, 5279, UINT16_MAX, 5279, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5280, 5280, UINT16_MAX, 5280, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5281, 5281, UINT16_MAX, 5281, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5282, 5282, UINT16_MAX, 5282, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5283, 5283, UINT16_MAX, 5283, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5284, 5284, UINT16_MAX, 5284, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5285, 5285, UINT16_MAX, 5285, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5286, 5286, UINT16_MAX, 5286, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5287, 5287, UINT16_MAX, 5287, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5288, 5288, UINT16_MAX, 5288, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5289, 5289, UINT16_MAX, 5289, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5290, 5290, UINT16_MAX, 5290, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5291, 5291, UINT16_MAX, 5291, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5292, 5292, UINT16_MAX, 5292, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5293, 5293, UINT16_MAX, 5293, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5294, 5294, UINT16_MAX, 5294, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5295, 5295, UINT16_MAX, 5295, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5296, 5296, UINT16_MAX, 5296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5297, 5297, UINT16_MAX, 5297, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5298, 5298, UINT16_MAX, 5298, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5299, 5299, UINT16_MAX, 5299, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5300, 5300, UINT16_MAX, 5300, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5301, 5301, UINT16_MAX, 5301, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5302, 5302, UINT16_MAX, 5302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5303, 5303, UINT16_MAX, 5303, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5304, 5304, UINT16_MAX, 5304, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5305, 5305, UINT16_MAX, 5305, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5306, 5306, UINT16_MAX, 5306, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5307, 5307, UINT16_MAX, 5307, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5308, 5308, UINT16_MAX, 5308, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5309, 5309, UINT16_MAX, 5309, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5310, 5310, UINT16_MAX, 5310, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5311, 5311, UINT16_MAX, 5311, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5312, 5312, UINT16_MAX, 5312, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5313, 5313, UINT16_MAX, 5313, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5314, 5314, UINT16_MAX, 5314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5315, 5315, UINT16_MAX, 5315, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5316, 5316, UINT16_MAX, 5316, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5317, 5317, UINT16_MAX, 5317, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5318, 5318, UINT16_MAX, 5318, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5319, 5319, UINT16_MAX, 5319, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5320, 5320, UINT16_MAX, 5320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5321, 5321, UINT16_MAX, 5321, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5322, 5322, UINT16_MAX, 5322, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5323, 5323, UINT16_MAX, 5323, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5324, 5324, UINT16_MAX, 5324, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5325, 5325, UINT16_MAX, 5325, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5326, 5326, UINT16_MAX, 5326, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5327, 5327, UINT16_MAX, 5327, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5328, 5328, UINT16_MAX, 5328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5329, 5329, UINT16_MAX, 5329, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5330, 5330, UINT16_MAX, 5330, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5331, 5331, UINT16_MAX, 5331, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5332, 5332, UINT16_MAX, 5332, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5333, 5333, UINT16_MAX, 5333, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5334, 5334, UINT16_MAX, 5334, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_LV, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_LVT, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CS, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5369, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5372, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5375, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5381, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5383, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5384, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5387, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5391, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5403, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5707, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5713, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5716, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5727, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5731, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5733, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22132, 22132, 9800, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22134, 22134, 9801, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22136, 22136, 9802, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38522, 38522, 9803, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38525, 38525, 9804, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22144, 22146, 9805, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22146, 22146, 9806, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22148, 22148, 9807, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22150, 22150, 9808, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22152, 22152, 9809, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22154, 22154, 9810, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22156, 22156, 9811, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 26, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 2840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 2843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_FONT, 2800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22203, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22215, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 22231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_COMPAT, 22233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22316, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22334, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22372, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22384, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 38862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 38865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 38868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 38871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 38874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 38877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22316, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22334, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22372, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22384, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 38944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 38947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 38950, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39009, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39015, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39021, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39027, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39033, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39039, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39051, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39087, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39093, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39093, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39099, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39105, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39117, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39135, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39141, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39156, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39168, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39117, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 39060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 39288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 39291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 39294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 39332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 55747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 2804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 3067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 3068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 6627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 6612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 6600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 2762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 6603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, 2800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, 6631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23085, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23085, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23087, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23087, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23089, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23089, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23091, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23091, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, 2800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, 6631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 2762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1491, 6712, UINT16_MAX, 6712, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1493, 6713, UINT16_MAX, 6713, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2813, 6714, UINT16_MAX, 6714, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1494, 6715, UINT16_MAX, 6715, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1495, 6716, UINT16_MAX, 6716, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2838, 6717, UINT16_MAX, 6717, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1497, 6718, UINT16_MAX, 6718, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1498, 6719, UINT16_MAX, 6719, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1499, 6720, UINT16_MAX, 6720, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1500, 6721, UINT16_MAX, 6721, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1501, 6722, UINT16_MAX, 6722, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1502, 6723, UINT16_MAX, 6723, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1503, 6724, UINT16_MAX, 6724, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1504, 6725, UINT16_MAX, 6725, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1505, 6726, UINT16_MAX, 6726, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1507, 6727, UINT16_MAX, 6727, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2827, 6728, UINT16_MAX, 6728, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1508, 6729, UINT16_MAX, 6729, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3320, 6730, UINT16_MAX, 6730, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1509, 6731, UINT16_MAX, 6731, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1510, 6732, UINT16_MAX, 6732, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2910, 6733, UINT16_MAX, 6733, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1511, 6734, UINT16_MAX, 6734, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2928, 6735, UINT16_MAX, 6735, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3327, 6736, UINT16_MAX, 6736, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2835, 6737, UINT16_MAX, 6737, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 0, UINT16_MAX, 9812, UINT16_MAX, 9812, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1, UINT16_MAX, 9813, UINT16_MAX, 9813, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2, UINT16_MAX, 9814, UINT16_MAX, 9814, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3, UINT16_MAX, 9815, UINT16_MAX, 9815, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 4, UINT16_MAX, 9816, UINT16_MAX, 9816, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 5, UINT16_MAX, 9817, UINT16_MAX, 9817, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 6, UINT16_MAX, 9818, UINT16_MAX, 9818, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 7, UINT16_MAX, 9819, UINT16_MAX, 9819, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 8, UINT16_MAX, 9820, UINT16_MAX, 9820, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 9, UINT16_MAX, 9821, UINT16_MAX, 9821, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 10, UINT16_MAX, 9822, UINT16_MAX, 9822, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 11, UINT16_MAX, 9823, UINT16_MAX, 9823, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 12, UINT16_MAX, 9824, UINT16_MAX, 9824, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 13, UINT16_MAX, 9825, UINT16_MAX, 9825, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 14, UINT16_MAX, 9826, UINT16_MAX, 9826, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 15, UINT16_MAX, 9827, UINT16_MAX, 9827, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 16, UINT16_MAX, 9828, UINT16_MAX, 9828, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 17, UINT16_MAX, 9829, UINT16_MAX, 9829, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 18, UINT16_MAX, 9830, UINT16_MAX, 9830, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 19, UINT16_MAX, 9831, UINT16_MAX, 9831, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 20, UINT16_MAX, 9832, UINT16_MAX, 9832, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 21, UINT16_MAX, 9833, UINT16_MAX, 9833, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 22, UINT16_MAX, 9834, UINT16_MAX, 9834, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 23, UINT16_MAX, 9835, UINT16_MAX, 9835, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 24, UINT16_MAX, 9836, UINT16_MAX, 9836, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 25, UINT16_MAX, 9837, UINT16_MAX, 9837, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6751, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4334, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6806, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6808, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6823, UINT16_MAX, 6823, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6825, UINT16_MAX, 6825, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6827, UINT16_MAX, 6827, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6829, UINT16_MAX, 6829, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6831, UINT16_MAX, 6831, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6833, UINT16_MAX, 6833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6835, UINT16_MAX, 6835, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6837, UINT16_MAX, 6837, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6839, UINT16_MAX, 6839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6841, UINT16_MAX, 6841, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6843, UINT16_MAX, 6843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6845, UINT16_MAX, 6845, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6847, UINT16_MAX, 6847, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6849, UINT16_MAX, 6849, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6851, UINT16_MAX, 6851, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6853, UINT16_MAX, 6853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6855, UINT16_MAX, 6855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6857, UINT16_MAX, 6857, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6859, UINT16_MAX, 6859, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6861, UINT16_MAX, 6861, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6863, UINT16_MAX, 6863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6865, UINT16_MAX, 6865, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6867, UINT16_MAX, 6867, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6869, UINT16_MAX, 6869, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6871, UINT16_MAX, 6871, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6873, UINT16_MAX, 6873, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6875, UINT16_MAX, 6875, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6877, UINT16_MAX, 6877, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6879, UINT16_MAX, 6879, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6881, UINT16_MAX, 6881, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6883, UINT16_MAX, 6883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6885, UINT16_MAX, 6885, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6887, UINT16_MAX, 6887, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6889, UINT16_MAX, 6889, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6891, UINT16_MAX, 6891, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6893, UINT16_MAX, 6893, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6895, UINT16_MAX, 6895, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6897, UINT16_MAX, 6897, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6899, UINT16_MAX, 6899, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6901, UINT16_MAX, 6901, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9838, UINT16_MAX, 9838, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9840, UINT16_MAX, 9840, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9842, UINT16_MAX, 9842, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9844, UINT16_MAX, 9844, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9846, UINT16_MAX, 9846, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9848, UINT16_MAX, 9848, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9850, UINT16_MAX, 9850, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9852, UINT16_MAX, 9852, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9854, UINT16_MAX, 9854, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9856, UINT16_MAX, 9856, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9858, UINT16_MAX, 9858, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9860, UINT16_MAX, 9860, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9862, UINT16_MAX, 9862, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9864, UINT16_MAX, 9864, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9866, UINT16_MAX, 9866, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9868, UINT16_MAX, 9868, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9870, UINT16_MAX, 9870, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9872, UINT16_MAX, 9872, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9874, UINT16_MAX, 9874, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9876, UINT16_MAX, 9876, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9878, UINT16_MAX, 9878, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9880, UINT16_MAX, 9880, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9882, UINT16_MAX, 9882, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9884, UINT16_MAX, 9884, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9886, UINT16_MAX, 9886, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9888, UINT16_MAX, 9888, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9890, UINT16_MAX, 9890, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9892, UINT16_MAX, 9892, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9894, UINT16_MAX, 9894, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9896, UINT16_MAX, 9896, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9898, UINT16_MAX, 9898, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9900, UINT16_MAX, 9900, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9902, UINT16_MAX, 9902, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9904, UINT16_MAX, 9904, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9906, UINT16_MAX, 9906, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9908, UINT16_MAX, 9908, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9910, UINT16_MAX, 9910, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9912, UINT16_MAX, 9912, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9914, UINT16_MAX, 9914, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9916, UINT16_MAX, 9916, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6903, UINT16_MAX, 6903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6905, UINT16_MAX, 6905, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6907, UINT16_MAX, 6907, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6909, UINT16_MAX, 6909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6911, UINT16_MAX, 6911, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6913, UINT16_MAX, 6913, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6915, UINT16_MAX, 6915, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6917, UINT16_MAX, 6917, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6919, UINT16_MAX, 6919, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6921, UINT16_MAX, 6921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6923, UINT16_MAX, 6923, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6925, UINT16_MAX, 6925, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6927, UINT16_MAX, 6927, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6929, UINT16_MAX, 6929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6931, UINT16_MAX, 6931, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6933, UINT16_MAX, 6933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6935, UINT16_MAX, 6935, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6937, UINT16_MAX, 6937, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6939, UINT16_MAX, 6939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6941, UINT16_MAX, 6941, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6943, UINT16_MAX, 6943, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6945, UINT16_MAX, 6945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6947, UINT16_MAX, 6947, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6949, UINT16_MAX, 6949, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6951, UINT16_MAX, 6951, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6953, UINT16_MAX, 6953, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6955, UINT16_MAX, 6955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6957, UINT16_MAX, 6957, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6959, UINT16_MAX, 6959, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6961, UINT16_MAX, 6961, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6963, UINT16_MAX, 6963, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6965, UINT16_MAX, 6965, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6967, UINT16_MAX, 6967, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6969, UINT16_MAX, 6969, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6971, UINT16_MAX, 6971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6973, UINT16_MAX, 6973, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9918, UINT16_MAX, 9918, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9920, UINT16_MAX, 9920, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9922, UINT16_MAX, 9922, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9924, UINT16_MAX, 9924, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9926, UINT16_MAX, 9926, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9928, UINT16_MAX, 9928, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9930, UINT16_MAX, 9930, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9932, UINT16_MAX, 9932, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9934, UINT16_MAX, 9934, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9936, UINT16_MAX, 9936, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9938, UINT16_MAX, 9938, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9940, UINT16_MAX, 9940, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9942, UINT16_MAX, 9942, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9944, UINT16_MAX, 9944, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9946, UINT16_MAX, 9946, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9948, UINT16_MAX, 9948, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9950, UINT16_MAX, 9950, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9952, UINT16_MAX, 9952, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9954, UINT16_MAX, 9954, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9956, UINT16_MAX, 9956, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9958, UINT16_MAX, 9958, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9960, UINT16_MAX, 9960, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9962, UINT16_MAX, 9962, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9964, UINT16_MAX, 9964, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9966, UINT16_MAX, 9966, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9968, UINT16_MAX, 9968, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9970, UINT16_MAX, 9970, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9972, UINT16_MAX, 9972, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9974, UINT16_MAX, 9974, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9976, UINT16_MAX, 9976, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9978, UINT16_MAX, 9978, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9980, UINT16_MAX, 9980, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9982, UINT16_MAX, 9982, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9984, UINT16_MAX, 9984, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9986, UINT16_MAX, 9986, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9988, UINT16_MAX, 9988, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6975, UINT16_MAX, 6975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6977, UINT16_MAX, 6977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6979, UINT16_MAX, 6979, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6981, UINT16_MAX, 6981, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6983, UINT16_MAX, 6983, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6985, UINT16_MAX, 6985, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6987, UINT16_MAX, 6987, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6989, UINT16_MAX, 6989, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6991, UINT16_MAX, 6991, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6993, UINT16_MAX, 6993, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6995, UINT16_MAX, 6995, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6997, UINT16_MAX, 6997, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6999, UINT16_MAX, 6999, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7001, UINT16_MAX, 7001, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7003, UINT16_MAX, 7003, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7005, UINT16_MAX, 7005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7007, UINT16_MAX, 7007, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7009, UINT16_MAX, 7009, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7011, UINT16_MAX, 7011, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7013, UINT16_MAX, 7013, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7015, UINT16_MAX, 7015, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7017, UINT16_MAX, 7017, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7019, UINT16_MAX, 7019, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7021, UINT16_MAX, 7021, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7023, UINT16_MAX, 7023, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7025, UINT16_MAX, 7025, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7027, UINT16_MAX, 7027, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7029, UINT16_MAX, 7029, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7031, UINT16_MAX, 7031, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7033, UINT16_MAX, 7033, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7035, UINT16_MAX, 7035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7037, UINT16_MAX, 7037, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7039, UINT16_MAX, 7039, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7041, UINT16_MAX, 7041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7043, UINT16_MAX, 7043, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9990, UINT16_MAX, 9990, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9992, UINT16_MAX, 9992, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9994, UINT16_MAX, 9994, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9996, UINT16_MAX, 9996, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9998, UINT16_MAX, 9998, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10000, UINT16_MAX, 10000, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10002, UINT16_MAX, 10002, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10004, UINT16_MAX, 10004, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10006, UINT16_MAX, 10006, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10008, UINT16_MAX, 10008, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10010, UINT16_MAX, 10010, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10012, UINT16_MAX, 10012, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10014, UINT16_MAX, 10014, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10016, UINT16_MAX, 10016, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10018, UINT16_MAX, 10018, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10020, UINT16_MAX, 10020, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10022, UINT16_MAX, 10022, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10024, UINT16_MAX, 10024, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10026, UINT16_MAX, 10026, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10028, UINT16_MAX, 10028, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10030, UINT16_MAX, 10030, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10032, UINT16_MAX, 10032, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10034, UINT16_MAX, 10034, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10036, UINT16_MAX, 10036, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10038, UINT16_MAX, 10038, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10040, UINT16_MAX, 10040, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10042, UINT16_MAX, 10042, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10044, UINT16_MAX, 10044, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10046, UINT16_MAX, 10046, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10048, UINT16_MAX, 10048, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10050, UINT16_MAX, 10050, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10052, UINT16_MAX, 10052, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10054, UINT16_MAX, 10054, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10056, UINT16_MAX, 10056, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10058, UINT16_MAX, 10058, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10060, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 66, UINT16_MAX, 10062, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7047, UINT16_MAX, 10064, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 476, UINT16_MAX, 10066, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7048, UINT16_MAX, 10068, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7049, UINT16_MAX, 10070, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7050, UINT16_MAX, 10072, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7051, UINT16_MAX, 10074, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 481, UINT16_MAX, 10076, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 482, UINT16_MAX, 10078, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7052, UINT16_MAX, 10080, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7053, UINT16_MAX, 10082, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7054, UINT16_MAX, 10084, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7055, UINT16_MAX, 10086, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7056, UINT16_MAX, 10088, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7057, UINT16_MAX, 10090, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 488, UINT16_MAX, 10092, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7058, UINT16_MAX, 10094, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 277, UINT16_MAX, 10096, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7059, UINT16_MAX, 10098, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7060, UINT16_MAX, 10100, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7061, UINT16_MAX, 10102, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7062, UINT16_MAX, 10104, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7063, UINT16_MAX, 10106, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5231, UINT16_MAX, 10108, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7064, UINT16_MAX, 10110, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7066, UINT16_MAX, 10112, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7067, UINT16_MAX, 10114, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7068, UINT16_MAX, 10116, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7070, UINT16_MAX, 10118, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7071, UINT16_MAX, 10120, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 113, UINT16_MAX, 10122, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7073, UINT16_MAX, 10124, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7074, UINT16_MAX, 10126, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 16, UINT16_MAX, 10128, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7075, UINT16_MAX, 10130, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7076, UINT16_MAX, 10132, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3396, UINT16_MAX, 10134, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7078, UINT16_MAX, 10136, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 503, UINT16_MAX, 10138, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7079, UINT16_MAX, 10140, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7080, UINT16_MAX, 10142, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7081, UINT16_MAX, 10144, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7082, UINT16_MAX, 10146, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 507, UINT16_MAX, 10148, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7083, UINT16_MAX, 10150, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7084, UINT16_MAX, 10152, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7085, UINT16_MAX, 10154, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7086, UINT16_MAX, 10156, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7087, UINT16_MAX, 10158, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7088, UINT16_MAX, 10160, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7089, UINT16_MAX, 10162, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7090, UINT16_MAX, 10164, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7091, UINT16_MAX, 10166, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7093, UINT16_MAX, 10168, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7095, UINT16_MAX, 7095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7097, UINT16_MAX, 7097, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7099, UINT16_MAX, 7099, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7101, UINT16_MAX, 7101, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7103, UINT16_MAX, 7103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7105, UINT16_MAX, 7105, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7107, UINT16_MAX, 7107, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7109, UINT16_MAX, 7109, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7111, UINT16_MAX, 7111, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7113, UINT16_MAX, 7113, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7115, UINT16_MAX, 7115, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7117, UINT16_MAX, 7117, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7119, UINT16_MAX, 7119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7121, UINT16_MAX, 7121, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7123, UINT16_MAX, 7123, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7125, UINT16_MAX, 7125, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7127, UINT16_MAX, 7127, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7129, UINT16_MAX, 7129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7131, UINT16_MAX, 7131, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7133, UINT16_MAX, 7133, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7135, UINT16_MAX, 7135, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7137, UINT16_MAX, 7137, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7139, UINT16_MAX, 7139, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7141, UINT16_MAX, 7141, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7143, UINT16_MAX, 7143, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7145, UINT16_MAX, 7145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7147, UINT16_MAX, 7147, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7149, UINT16_MAX, 7149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7151, UINT16_MAX, 7151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7153, UINT16_MAX, 7153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7155, UINT16_MAX, 7155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7157, UINT16_MAX, 7157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7159, UINT16_MAX, 7159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7161, UINT16_MAX, 7161, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7163, UINT16_MAX, 7163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7165, UINT16_MAX, 7165, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7167, UINT16_MAX, 7167, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7169, UINT16_MAX, 7169, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7171, UINT16_MAX, 7171, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7173, UINT16_MAX, 7173, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7175, UINT16_MAX, 7175, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7177, UINT16_MAX, 7177, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7179, UINT16_MAX, 7179, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7181, UINT16_MAX, 7181, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7183, UINT16_MAX, 7183, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7185, UINT16_MAX, 7185, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7187, UINT16_MAX, 7187, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7189, UINT16_MAX, 7189, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7191, UINT16_MAX, 7191, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7193, UINT16_MAX, 7193, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7195, UINT16_MAX, 7195, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10170, UINT16_MAX, 10170, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10172, UINT16_MAX, 10172, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10174, UINT16_MAX, 10174, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10176, UINT16_MAX, 10176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10178, UINT16_MAX, 10178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10180, UINT16_MAX, 10180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10182, UINT16_MAX, 10182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10184, UINT16_MAX, 10184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10186, UINT16_MAX, 10186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10188, UINT16_MAX, 10188, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10190, UINT16_MAX, 10190, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10192, UINT16_MAX, 10192, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10194, UINT16_MAX, 10194, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10196, UINT16_MAX, 10196, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10198, UINT16_MAX, 10198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10200, UINT16_MAX, 10200, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10202, UINT16_MAX, 10202, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10204, UINT16_MAX, 10204, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10206, UINT16_MAX, 10206, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10208, UINT16_MAX, 10208, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10210, UINT16_MAX, 10210, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10212, UINT16_MAX, 10212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10214, UINT16_MAX, 10214, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10216, UINT16_MAX, 10216, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10218, UINT16_MAX, 10218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10220, UINT16_MAX, 10220, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10222, UINT16_MAX, 10222, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10224, UINT16_MAX, 10224, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10226, UINT16_MAX, 10226, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10228, UINT16_MAX, 10228, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10230, UINT16_MAX, 10230, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10232, UINT16_MAX, 10232, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10234, UINT16_MAX, 10234, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10236, UINT16_MAX, 10236, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10238, UINT16_MAX, 10238, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10240, UINT16_MAX, 10240, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10242, UINT16_MAX, 10242, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10244, UINT16_MAX, 10244, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10246, UINT16_MAX, 10246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10248, UINT16_MAX, 10248, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10250, UINT16_MAX, 10250, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10252, UINT16_MAX, 10252, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10254, UINT16_MAX, 10254, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10256, UINT16_MAX, 10256, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10258, UINT16_MAX, 10258, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10260, UINT16_MAX, 10260, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10262, UINT16_MAX, 10262, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10264, UINT16_MAX, 10264, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10266, UINT16_MAX, 10266, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10268, UINT16_MAX, 10268, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 10270, UINT16_MAX, 10270, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5328, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5332, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5336, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49206, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49208, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 23593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 23597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5340, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5344, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49210, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5348, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 23601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 23605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49212, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49216, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5354, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49214, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 23609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 23613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49218, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 23617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49220, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5362, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5366, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 23621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 23625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7245, UINT16_MAX, 7245, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7247, UINT16_MAX, 7247, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7249, UINT16_MAX, 7249, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7251, UINT16_MAX, 7251, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7253, UINT16_MAX, 7253, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7255, UINT16_MAX, 7255, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7257, UINT16_MAX, 7257, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7259, UINT16_MAX, 7259, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7261, UINT16_MAX, 7261, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7263, UINT16_MAX, 7263, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7265, UINT16_MAX, 7265, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7267, UINT16_MAX, 7267, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7269, UINT16_MAX, 7269, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7271, UINT16_MAX, 7271, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7273, UINT16_MAX, 7273, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7275, UINT16_MAX, 7275, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7277, UINT16_MAX, 7277, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7279, UINT16_MAX, 7279, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7281, UINT16_MAX, 7281, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7283, UINT16_MAX, 7283, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7285, UINT16_MAX, 7285, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7287, UINT16_MAX, 7287, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7289, UINT16_MAX, 7289, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7291, UINT16_MAX, 7291, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7293, UINT16_MAX, 7293, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7295, UINT16_MAX, 7295, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7297, UINT16_MAX, 7297, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7299, UINT16_MAX, 7299, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7301, UINT16_MAX, 7301, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7303, UINT16_MAX, 7303, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7305, UINT16_MAX, 7305, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7307, UINT16_MAX, 7307, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10272, UINT16_MAX, 10272, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10274, UINT16_MAX, 10274, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10276, UINT16_MAX, 10276, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10278, UINT16_MAX, 10278, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10280, UINT16_MAX, 10280, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10282, UINT16_MAX, 10282, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10284, UINT16_MAX, 10284, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10286, UINT16_MAX, 10286, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10288, UINT16_MAX, 10288, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10290, UINT16_MAX, 10290, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10292, UINT16_MAX, 10292, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10294, UINT16_MAX, 10294, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10296, UINT16_MAX, 10296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10298, UINT16_MAX, 10298, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10300, UINT16_MAX, 10300, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10302, UINT16_MAX, 10302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10304, UINT16_MAX, 10304, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10306, UINT16_MAX, 10306, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10308, UINT16_MAX, 10308, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10310, UINT16_MAX, 10310, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10312, UINT16_MAX, 10312, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10314, UINT16_MAX, 10314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10316, UINT16_MAX, 10316, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10318, UINT16_MAX, 10318, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10320, UINT16_MAX, 10320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10322, UINT16_MAX, 10322, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10324, UINT16_MAX, 10324, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10326, UINT16_MAX, 10326, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10328, UINT16_MAX, 10328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10330, UINT16_MAX, 10330, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10332, UINT16_MAX, 10332, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10334, UINT16_MAX, 10334, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49222, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5370, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 23693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7313, UINT16_MAX, 7313, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7315, UINT16_MAX, 7315, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7317, UINT16_MAX, 7317, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7319, UINT16_MAX, 7319, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7321, UINT16_MAX, 7321, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7323, UINT16_MAX, 7323, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7325, UINT16_MAX, 7325, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7327, UINT16_MAX, 7327, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7329, UINT16_MAX, 7329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7331, UINT16_MAX, 7331, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7333, UINT16_MAX, 7333, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7335, UINT16_MAX, 7335, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7337, UINT16_MAX, 7337, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7339, UINT16_MAX, 7339, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7341, UINT16_MAX, 7341, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7343, UINT16_MAX, 7343, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7345, UINT16_MAX, 7345, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7347, UINT16_MAX, 7347, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7349, UINT16_MAX, 7349, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7351, UINT16_MAX, 7351, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7353, UINT16_MAX, 7353, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7355, UINT16_MAX, 7355, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7357, UINT16_MAX, 7357, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7359, UINT16_MAX, 7359, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7361, UINT16_MAX, 7361, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7363, UINT16_MAX, 7363, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7365, UINT16_MAX, 7365, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7367, UINT16_MAX, 7367, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7369, UINT16_MAX, 7369, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7371, UINT16_MAX, 7371, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7373, UINT16_MAX, 7373, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7375, UINT16_MAX, 7375, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10336, UINT16_MAX, 10336, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10338, UINT16_MAX, 10338, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10340, UINT16_MAX, 10340, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10342, UINT16_MAX, 10342, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10344, UINT16_MAX, 10344, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10346, UINT16_MAX, 10346, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10348, UINT16_MAX, 10348, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10350, UINT16_MAX, 10350, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10352, UINT16_MAX, 10352, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10354, UINT16_MAX, 10354, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10356, UINT16_MAX, 10356, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10358, UINT16_MAX, 10358, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10360, UINT16_MAX, 10360, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10362, UINT16_MAX, 10362, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10364, UINT16_MAX, 10364, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10366, UINT16_MAX, 10366, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10368, UINT16_MAX, 10368, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10370, UINT16_MAX, 10370, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10372, UINT16_MAX, 10372, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10374, UINT16_MAX, 10374, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10376, UINT16_MAX, 10376, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10378, UINT16_MAX, 10378, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10380, UINT16_MAX, 10380, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10382, UINT16_MAX, 10382, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10384, UINT16_MAX, 10384, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10386, UINT16_MAX, 10386, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10388, UINT16_MAX, 10388, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10390, UINT16_MAX, 10390, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10392, UINT16_MAX, 10392, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10394, UINT16_MAX, 10394, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10396, UINT16_MAX, 10396, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 10398, UINT16_MAX, 10398, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 6, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5374, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5378, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5382, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49224, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 226, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49226, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49228, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49230, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49232, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49234, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5394, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5398, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5402, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5408, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 23809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 10400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 10402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 10404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 10406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 10408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 10410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 10412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 10414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 10416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 10418, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 10420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 10422, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 10424, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 10426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 10428, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 10430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 10432, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 10434, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 10436, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 10438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 10440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 10442, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 10444, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 10446, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 10448, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 10450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10452, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10454, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10456, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10458, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10460, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10462, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10464, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10466, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10468, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10470, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10472, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10474, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10476, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10478, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10480, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10482, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10484, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10486, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10488, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10490, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10492, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10494, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10496, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10498, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10500, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10502, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 10504, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 10506, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 10508, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 10510, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 10512, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 10514, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 10516, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 10518, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 10520, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 10522, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 10524, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 10526, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 10528, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 10530, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 10532, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 10534, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 10536, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 10538, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 10540, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 10542, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 10544, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 10546, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 10548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 10550, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 10552, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 10554, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10556, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10558, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10560, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10562, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10564, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10566, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10568, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10570, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10572, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10574, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10576, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10578, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10580, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10582, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10584, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10586, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10588, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10590, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10592, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10594, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10596, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10598, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10600, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10602, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10604, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 10606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 10608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 10610, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 10612, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 10614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 10616, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 10618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 10620, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 10622, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 10624, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 10626, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 10628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 10630, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 10632, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 10634, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 10636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 10638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 10640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 10642, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 10644, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 10646, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 10648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 10650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 10652, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 10654, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 10656, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10658, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10660, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10662, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10664, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10666, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10668, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10670, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10672, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10674, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10676, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10678, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10680, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10682, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10684, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10686, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10688, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10690, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10692, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10694, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10696, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10698, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10700, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10702, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10704, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10706, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10708, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 10710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 10712, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 10714, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 10716, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 10718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 10720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 10722, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 10724, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 10726, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 10728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 10730, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 10732, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 10734, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 10736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 10738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 10740, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 10742, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 10744, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10746, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10748, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10750, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10752, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10754, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10756, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10758, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10760, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10762, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10764, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10766, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10768, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10770, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10772, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10774, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10776, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10778, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10780, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10782, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10784, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10786, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10788, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10790, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 10792, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 10794, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 10796, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 10798, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 10800, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 10802, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 10804, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 10806, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 10808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 10810, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 10812, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 10814, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 10816, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 10818, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 10820, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 10822, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 10824, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 10826, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 10828, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 10830, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 10832, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 10834, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 10836, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 10838, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 10840, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 10842, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10844, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10846, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10848, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10850, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10852, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10854, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10856, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10858, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10860, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10862, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10864, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10866, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10868, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10870, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10872, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10874, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10876, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10878, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10880, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10882, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10884, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10886, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10888, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10890, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10892, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10894, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 10896, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 10898, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 10900, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 10902, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 10904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 10906, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 10908, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 10910, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 10912, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 10914, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 10916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 10918, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 10920, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 10922, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 10924, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 10926, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 10928, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 10930, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 10932, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 10934, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 10936, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10938, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10940, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10942, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10944, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10946, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10948, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10950, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10952, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10954, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10956, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10958, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10960, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10962, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10964, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10966, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10968, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10970, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10972, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10974, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10976, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10978, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10980, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10982, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10984, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10986, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10988, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 10990, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 10992, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 10994, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 10996, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 10998, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 11000, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 11002, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 11004, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 11006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 11008, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 11010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 11012, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 11014, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 11016, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 11018, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 11020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 11022, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 11024, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 11026, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 11028, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 11030, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 11032, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 11034, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 11036, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 11038, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 11040, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 11042, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 11044, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 11046, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 11048, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 11050, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 11052, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 11054, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 11056, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 11058, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 11060, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 11062, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 11064, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 11066, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 11068, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 11070, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 11072, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 11074, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 11076, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 11078, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 11080, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 11082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 11084, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 11086, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 11088, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 11090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 11092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 11094, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 11096, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 11098, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 11100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 11102, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 11104, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 11106, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 11108, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 11110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 11112, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 11114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 11116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 11118, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 11120, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 11122, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 11124, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 11126, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 11128, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 11130, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 11132, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 11134, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 11136, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 11138, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 11140, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 11142, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 11144, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 11146, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 11148, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 11150, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 11152, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 11154, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 11156, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 11158, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 11160, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 11162, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 11164, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 11166, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 11168, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 11170, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 11172, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 11174, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 11176, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 11178, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 11180, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 11182, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 11184, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 11186, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 11188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 11190, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 11192, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 11194, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 11196, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 11198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 11200, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 11202, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 11204, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 11206, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 11208, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 11210, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 11212, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 11214, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 11216, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 11218, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 11220, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 11222, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 11224, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 11226, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 11228, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 11230, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 11232, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 11234, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 11236, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 11238, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 11240, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 11242, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 11244, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 11246, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 11248, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 11250, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 11252, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 11254, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 11256, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 11258, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 11260, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 11262, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 11264, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 11266, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 11268, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 11270, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 11272, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 11274, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 11276, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 11278, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 11280, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 11282, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 11284, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 11286, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 11288, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 11290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 11292, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 11294, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 11296, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 11298, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 11300, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 11302, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 11304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 11306, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 11308, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 11310, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 11312, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 11314, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 11316, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 11318, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 11320, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 11322, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 11324, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 11326, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 11328, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 11330, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 11332, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 11334, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 11336, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 11338, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 11340, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 11342, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 11344, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 11346, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 11348, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 11350, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 11352, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 11354, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 11356, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 11358, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 11360, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 11362, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 11364, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 11366, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 11368, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 11370, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 11372, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 11374, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 11376, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 11378, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 11380, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 11382, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 11384, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 11386, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 11388, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 11390, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 11392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 11394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 11396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 11398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 11400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 11402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 11404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 11406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 11408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 11410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 11412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 11414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 11416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 11418, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 11420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 11422, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 11424, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 11426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 11428, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 11430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 11432, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 11434, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 11436, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 11438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 11440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 11442, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 11444, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 11446, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 11448, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 11450, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 11452, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 11454, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 11456, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 11458, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 11460, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 11462, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 11464, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 11466, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 11468, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 11470, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 11472, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 11474, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 11476, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 11478, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 11480, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 11482, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 11484, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 11486, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 11488, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 11490, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 11492, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 11494, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 11496, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 11498, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 11500, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 11502, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 11504, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 11506, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 11508, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 11510, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 11512, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 11514, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 11516, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 11518, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 11520, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 11522, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 11524, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 11526, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 11528, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 11530, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 11532, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 11534, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 11536, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 11538, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 11540, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 11542, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 11544, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 11546, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 11548, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 11550, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 11552, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 11554, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 11556, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 11558, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 11560, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 11562, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 11564, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 11566, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 11568, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 11570, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 11572, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 11574, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 11576, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 11578, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 11580, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 11582, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 11584, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 11586, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 11588, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 11590, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 11592, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 11594, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 11596, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 11598, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, 11600, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, 11602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2813, UINT16_MAX, UINT16_MAX, 11604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, 11606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, 11608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2838, UINT16_MAX, UINT16_MAX, 11610, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, 11612, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, 11614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, 11616, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, 11618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, 11620, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, 11622, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, 11624, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, 11626, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, 11628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, 11630, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2827, UINT16_MAX, UINT16_MAX, 11632, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, 11634, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3320, UINT16_MAX, UINT16_MAX, 11636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, 11638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, 11640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2910, UINT16_MAX, UINT16_MAX, 11642, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, 11644, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2928, UINT16_MAX, UINT16_MAX, 11646, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3327, UINT16_MAX, UINT16_MAX, 11648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, 11650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 11652, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 11654, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 11656, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 11658, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 11660, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 11662, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 11664, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 11666, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 11668, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 11670, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 11672, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 11674, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 11676, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 11678, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 11680, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 11682, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 11684, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 11686, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 11688, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 11690, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 11692, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 11694, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 11696, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 11698, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 11700, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 11702, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7429, UINT16_MAX, 11704, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7430, UINT16_MAX, 11706, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7431, UINT16_MAX, UINT16_MAX, 11708, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7432, UINT16_MAX, UINT16_MAX, 11710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2847, UINT16_MAX, UINT16_MAX, 11712, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7433, UINT16_MAX, UINT16_MAX, 11714, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7434, UINT16_MAX, UINT16_MAX, 11716, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7435, UINT16_MAX, UINT16_MAX, 11718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7436, UINT16_MAX, UINT16_MAX, 11720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 915, UINT16_MAX, UINT16_MAX, 11722, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7437, UINT16_MAX, UINT16_MAX, 11724, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7438, UINT16_MAX, UINT16_MAX, 11726, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7439, UINT16_MAX, UINT16_MAX, 11728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7440, UINT16_MAX, UINT16_MAX, 11730, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7441, UINT16_MAX, UINT16_MAX, 11732, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7442, UINT16_MAX, UINT16_MAX, 11734, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7443, UINT16_MAX, UINT16_MAX, 11736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2848, UINT16_MAX, UINT16_MAX, 11738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7444, UINT16_MAX, UINT16_MAX, 11740, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7445, UINT16_MAX, UINT16_MAX, 11742, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 917, UINT16_MAX, UINT16_MAX, 11744, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7446, UINT16_MAX, UINT16_MAX, 11746, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 897, UINT16_MAX, UINT16_MAX, 11748, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7447, UINT16_MAX, UINT16_MAX, 11750, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7448, UINT16_MAX, UINT16_MAX, 11752, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7449, UINT16_MAX, UINT16_MAX, 11754, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2836, UINT16_MAX, UINT16_MAX, 11756, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 845, UINT16_MAX, 11758, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 846, UINT16_MAX, 11760, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, 11762, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 848, UINT16_MAX, 11764, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 849, UINT16_MAX, 11766, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 850, UINT16_MAX, 11768, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 851, UINT16_MAX, 11770, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 852, UINT16_MAX, 11772, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 807, UINT16_MAX, 11774, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 853, UINT16_MAX, 11776, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 854, UINT16_MAX, 11778, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, 11780, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 855, UINT16_MAX, 11782, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 856, UINT16_MAX, 11784, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 857, UINT16_MAX, 11786, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, 11788, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 859, UINT16_MAX, 11790, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 914, UINT16_MAX, 11792, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 860, UINT16_MAX, 11794, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 861, UINT16_MAX, 11796, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 862, UINT16_MAX, 11798, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 863, UINT16_MAX, 11800, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 864, UINT16_MAX, 11802, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 865, UINT16_MAX, 11804, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 866, UINT16_MAX, 11806, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 7451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7452, UINT16_MAX, 11808, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7453, UINT16_MAX, 11810, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7454, UINT16_MAX, 11812, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7455, UINT16_MAX, 11814, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7456, UINT16_MAX, 11816, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7457, UINT16_MAX, 11818, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7431, UINT16_MAX, UINT16_MAX, 11820, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7432, UINT16_MAX, UINT16_MAX, 11822, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2847, UINT16_MAX, UINT16_MAX, 11824, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7433, UINT16_MAX, UINT16_MAX, 11826, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7434, UINT16_MAX, UINT16_MAX, 11828, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7435, UINT16_MAX, UINT16_MAX, 11830, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7436, UINT16_MAX, UINT16_MAX, 11832, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 915, UINT16_MAX, UINT16_MAX, 11834, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7437, UINT16_MAX, UINT16_MAX, 11836, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7438, UINT16_MAX, UINT16_MAX, 11838, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7439, UINT16_MAX, UINT16_MAX, 11840, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7440, UINT16_MAX, UINT16_MAX, 11842, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7441, UINT16_MAX, UINT16_MAX, 11844, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7442, UINT16_MAX, UINT16_MAX, 11846, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7443, UINT16_MAX, UINT16_MAX, 11848, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2848, UINT16_MAX, UINT16_MAX, 11850, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7444, UINT16_MAX, UINT16_MAX, 11852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7445, UINT16_MAX, UINT16_MAX, 11854, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 917, UINT16_MAX, UINT16_MAX, 11856, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7446, UINT16_MAX, UINT16_MAX, 11858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 897, UINT16_MAX, UINT16_MAX, 11860, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7447, UINT16_MAX, UINT16_MAX, 11862, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7448, UINT16_MAX, UINT16_MAX, 11864, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7449, UINT16_MAX, UINT16_MAX, 11866, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2836, UINT16_MAX, UINT16_MAX, 11868, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 845, UINT16_MAX, 11870, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 846, UINT16_MAX, 11872, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, 11874, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 848, UINT16_MAX, 11876, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 849, UINT16_MAX, 11878, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 850, UINT16_MAX, 11880, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 851, UINT16_MAX, 11882, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 852, UINT16_MAX, 11884, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 807, UINT16_MAX, 11886, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 853, UINT16_MAX, 11888, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 854, UINT16_MAX, 11890, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, 11892, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 855, UINT16_MAX, 11894, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 856, UINT16_MAX, 11896, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 857, UINT16_MAX, 11898, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, 11900, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 859, UINT16_MAX, 11902, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 914, UINT16_MAX, 11904, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 860, UINT16_MAX, 11906, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 861, UINT16_MAX, 11908, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 862, UINT16_MAX, 11910, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 863, UINT16_MAX, 11912, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 864, UINT16_MAX, 11914, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 865, UINT16_MAX, 11916, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 866, UINT16_MAX, 11918, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7452, UINT16_MAX, 11920, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7453, UINT16_MAX, 11922, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7454, UINT16_MAX, 11924, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7455, UINT16_MAX, 11926, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7456, UINT16_MAX, 11928, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7457, UINT16_MAX, 11930, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7431, UINT16_MAX, UINT16_MAX, 11932, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7432, UINT16_MAX, UINT16_MAX, 11934, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2847, UINT16_MAX, UINT16_MAX, 11936, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7433, UINT16_MAX, UINT16_MAX, 11938, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7434, UINT16_MAX, UINT16_MAX, 11940, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7435, UINT16_MAX, UINT16_MAX, 11942, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7436, UINT16_MAX, UINT16_MAX, 11944, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 915, UINT16_MAX, UINT16_MAX, 11946, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7437, UINT16_MAX, UINT16_MAX, 11948, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7438, UINT16_MAX, UINT16_MAX, 11950, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7439, UINT16_MAX, UINT16_MAX, 11952, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7440, UINT16_MAX, UINT16_MAX, 11954, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7441, UINT16_MAX, UINT16_MAX, 11956, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7442, UINT16_MAX, UINT16_MAX, 11958, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7443, UINT16_MAX, UINT16_MAX, 11960, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2848, UINT16_MAX, UINT16_MAX, 11962, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7444, UINT16_MAX, UINT16_MAX, 11964, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7445, UINT16_MAX, UINT16_MAX, 11966, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 917, UINT16_MAX, UINT16_MAX, 11968, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7446, UINT16_MAX, UINT16_MAX, 11970, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 897, UINT16_MAX, UINT16_MAX, 11972, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7447, UINT16_MAX, UINT16_MAX, 11974, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7448, UINT16_MAX, UINT16_MAX, 11976, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7449, UINT16_MAX, UINT16_MAX, 11978, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2836, UINT16_MAX, UINT16_MAX, 11980, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 845, UINT16_MAX, 11982, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 846, UINT16_MAX, 11984, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, 11986, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 848, UINT16_MAX, 11988, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 849, UINT16_MAX, 11990, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 850, UINT16_MAX, 11992, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 851, UINT16_MAX, 11994, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 852, UINT16_MAX, 11996, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 807, UINT16_MAX, 11998, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 853, UINT16_MAX, 12000, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 854, UINT16_MAX, 12002, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, 12004, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 855, UINT16_MAX, 12006, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 856, UINT16_MAX, 12008, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 857, UINT16_MAX, 12010, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, 12012, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 859, UINT16_MAX, 12014, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 914, UINT16_MAX, 12016, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 860, UINT16_MAX, 12018, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 861, UINT16_MAX, 12020, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 862, UINT16_MAX, 12022, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 863, UINT16_MAX, 12024, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 864, UINT16_MAX, 12026, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 865, UINT16_MAX, 12028, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 866, UINT16_MAX, 12030, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7452, UINT16_MAX, 12032, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7453, UINT16_MAX, 12034, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7454, UINT16_MAX, 12036, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7455, UINT16_MAX, 12038, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7456, UINT16_MAX, 12040, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7457, UINT16_MAX, 12042, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7431, UINT16_MAX, UINT16_MAX, 12044, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7432, UINT16_MAX, UINT16_MAX, 12046, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2847, UINT16_MAX, UINT16_MAX, 12048, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7433, UINT16_MAX, UINT16_MAX, 12050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7434, UINT16_MAX, UINT16_MAX, 12052, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7435, UINT16_MAX, UINT16_MAX, 12054, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7436, UINT16_MAX, UINT16_MAX, 12056, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 915, UINT16_MAX, UINT16_MAX, 12058, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7437, UINT16_MAX, UINT16_MAX, 12060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7438, UINT16_MAX, UINT16_MAX, 12062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7439, UINT16_MAX, UINT16_MAX, 12064, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7440, UINT16_MAX, UINT16_MAX, 12066, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7441, UINT16_MAX, UINT16_MAX, 12068, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7442, UINT16_MAX, UINT16_MAX, 12070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7443, UINT16_MAX, UINT16_MAX, 12072, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2848, UINT16_MAX, UINT16_MAX, 12074, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7444, UINT16_MAX, UINT16_MAX, 12076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7445, UINT16_MAX, UINT16_MAX, 12078, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 917, UINT16_MAX, UINT16_MAX, 12080, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7446, UINT16_MAX, UINT16_MAX, 12082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 897, UINT16_MAX, UINT16_MAX, 12084, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7447, UINT16_MAX, UINT16_MAX, 12086, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7448, UINT16_MAX, UINT16_MAX, 12088, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7449, UINT16_MAX, UINT16_MAX, 12090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2836, UINT16_MAX, UINT16_MAX, 12092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 845, UINT16_MAX, 12094, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 846, UINT16_MAX, 12096, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, 12098, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 848, UINT16_MAX, 12100, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 849, UINT16_MAX, 12102, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 850, UINT16_MAX, 12104, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 851, UINT16_MAX, 12106, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 852, UINT16_MAX, 12108, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 807, UINT16_MAX, 12110, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 853, UINT16_MAX, 12112, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 854, UINT16_MAX, 12114, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, 12116, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 855, UINT16_MAX, 12118, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 856, UINT16_MAX, 12120, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 857, UINT16_MAX, 12122, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, 12124, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 859, UINT16_MAX, 12126, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 914, UINT16_MAX, 12128, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 860, UINT16_MAX, 12130, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 861, UINT16_MAX, 12132, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 862, UINT16_MAX, 12134, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 863, UINT16_MAX, 12136, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 864, UINT16_MAX, 12138, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 865, UINT16_MAX, 12140, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 866, UINT16_MAX, 12142, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7452, UINT16_MAX, 12144, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7453, UINT16_MAX, 12146, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7454, UINT16_MAX, 12148, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7455, UINT16_MAX, 12150, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7456, UINT16_MAX, 12152, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7457, UINT16_MAX, 12154, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7431, UINT16_MAX, UINT16_MAX, 12156, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7432, UINT16_MAX, UINT16_MAX, 12158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2847, UINT16_MAX, UINT16_MAX, 12160, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7433, UINT16_MAX, UINT16_MAX, 12162, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7434, UINT16_MAX, UINT16_MAX, 12164, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7435, UINT16_MAX, UINT16_MAX, 12166, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7436, UINT16_MAX, UINT16_MAX, 12168, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 915, UINT16_MAX, UINT16_MAX, 12170, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7437, UINT16_MAX, UINT16_MAX, 12172, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7438, UINT16_MAX, UINT16_MAX, 12174, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7439, UINT16_MAX, UINT16_MAX, 12176, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7440, UINT16_MAX, UINT16_MAX, 12178, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7441, UINT16_MAX, UINT16_MAX, 12180, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7442, UINT16_MAX, UINT16_MAX, 12182, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7443, UINT16_MAX, UINT16_MAX, 12184, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2848, UINT16_MAX, UINT16_MAX, 12186, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7444, UINT16_MAX, UINT16_MAX, 12188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7445, UINT16_MAX, UINT16_MAX, 12190, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 917, UINT16_MAX, UINT16_MAX, 12192, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7446, UINT16_MAX, UINT16_MAX, 12194, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 897, UINT16_MAX, UINT16_MAX, 12196, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7447, UINT16_MAX, UINT16_MAX, 12198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7448, UINT16_MAX, UINT16_MAX, 12200, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7449, UINT16_MAX, UINT16_MAX, 12202, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2836, UINT16_MAX, UINT16_MAX, 12204, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 845, UINT16_MAX, 12206, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 846, UINT16_MAX, 12208, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, 12210, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 848, UINT16_MAX, 12212, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 849, UINT16_MAX, 12214, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 850, UINT16_MAX, 12216, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 851, UINT16_MAX, 12218, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 852, UINT16_MAX, 12220, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 807, UINT16_MAX, 12222, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 853, UINT16_MAX, 12224, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 854, UINT16_MAX, 12226, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, 12228, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 855, UINT16_MAX, 12230, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 856, UINT16_MAX, 12232, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 857, UINT16_MAX, 12234, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, 12236, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 859, UINT16_MAX, 12238, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 914, UINT16_MAX, 12240, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 860, UINT16_MAX, 12242, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 861, UINT16_MAX, 12244, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 862, UINT16_MAX, 12246, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 863, UINT16_MAX, 12248, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 864, UINT16_MAX, 12250, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 865, UINT16_MAX, 12252, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 866, UINT16_MAX, 12254, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7452, UINT16_MAX, 12256, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7453, UINT16_MAX, 12258, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7454, UINT16_MAX, 12260, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7455, UINT16_MAX, 12262, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7456, UINT16_MAX, 12264, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7457, UINT16_MAX, 12266, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7458, UINT16_MAX, UINT16_MAX, 12268, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 904, UINT16_MAX, 12270, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12272, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12274, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12276, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12278, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7064, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7068, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7071, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12280, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7076, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12282, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12284, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12286, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12288, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12290, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12292, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12294, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12296, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12298, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12300, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12302, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12304, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12306, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12308, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12310, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12312, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12314, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12316, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12318, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12320, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7093, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12322, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12324, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12326, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12328, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12330, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 12332, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 953, UINT16_MAX, 12334, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 954, UINT16_MAX, 12336, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 955, UINT16_MAX, 12338, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 956, UINT16_MAX, 12340, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 957, UINT16_MAX, 12342, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 958, UINT16_MAX, 12344, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 959, UINT16_MAX, 12346, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 960, UINT16_MAX, 12348, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 961, UINT16_MAX, 12350, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 965, UINT16_MAX, 12352, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 966, UINT16_MAX, 12354, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 967, UINT16_MAX, 12356, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 969, UINT16_MAX, 12358, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 970, UINT16_MAX, 12360, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 971, UINT16_MAX, 12362, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 972, UINT16_MAX, 12364, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 973, UINT16_MAX, 12366, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 974, UINT16_MAX, 12368, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 975, UINT16_MAX, 12370, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 976, UINT16_MAX, 12372, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 977, UINT16_MAX, 12374, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 978, UINT16_MAX, 12376, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 979, UINT16_MAX, 12378, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 982, UINT16_MAX, 12380, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 984, UINT16_MAX, 12382, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 985, UINT16_MAX, 12384, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5162, UINT16_MAX, 12386, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1079, UINT16_MAX, 12388, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 935, UINT16_MAX, 12390, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 939, UINT16_MAX, 12392, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1111, UINT16_MAX, 12394, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1042, UINT16_MAX, 12396, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1051, UINT16_MAX, 12398, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 953, UINT16_MAX, 12400, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 954, UINT16_MAX, 12402, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 955, UINT16_MAX, 12404, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 956, UINT16_MAX, 12406, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 957, UINT16_MAX, 12408, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 958, UINT16_MAX, 12410, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 959, UINT16_MAX, 12412, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 960, UINT16_MAX, 12414, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 961, UINT16_MAX, 12416, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 965, UINT16_MAX, 12418, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 966, UINT16_MAX, 12420, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 969, UINT16_MAX, 12422, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 970, UINT16_MAX, 12424, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 972, UINT16_MAX, 12426, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 974, UINT16_MAX, 12428, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 975, UINT16_MAX, 12430, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 976, UINT16_MAX, 12432, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 977, UINT16_MAX, 12434, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 978, UINT16_MAX, 12436, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 979, UINT16_MAX, 12438, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 981, UINT16_MAX, 12440, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 982, UINT16_MAX, 12442, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1027, UINT16_MAX, 12444, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 935, UINT16_MAX, 12446, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 934, UINT16_MAX, 12448, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 952, UINT16_MAX, 12450, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1040, UINT16_MAX, 12452, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5143, UINT16_MAX, 12454, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1043, UINT16_MAX, 12456, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7459, UINT16_MAX, 7459, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7461, UINT16_MAX, 7461, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7463, UINT16_MAX, 7463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7465, UINT16_MAX, 7465, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7467, UINT16_MAX, 7467, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7469, UINT16_MAX, 7469, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7471, UINT16_MAX, 7471, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7473, UINT16_MAX, 7473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7475, UINT16_MAX, 7475, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7477, UINT16_MAX, 7477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7479, UINT16_MAX, 7479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7481, UINT16_MAX, 7481, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7483, UINT16_MAX, 7483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7485, UINT16_MAX, 7485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7487, UINT16_MAX, 7487, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7489, UINT16_MAX, 7489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7491, UINT16_MAX, 7491, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7493, UINT16_MAX, 7493, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7495, UINT16_MAX, 7495, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7497, UINT16_MAX, 7497, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7499, UINT16_MAX, 7499, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7501, UINT16_MAX, 7501, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7503, UINT16_MAX, 7503, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7505, UINT16_MAX, 7505, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7507, UINT16_MAX, 7507, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7509, UINT16_MAX, 7509, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7511, UINT16_MAX, 7511, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7513, UINT16_MAX, 7513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7515, UINT16_MAX, 7515, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7517, UINT16_MAX, 7517, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7519, UINT16_MAX, 7519, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7521, UINT16_MAX, 7521, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7523, UINT16_MAX, 7523, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7525, UINT16_MAX, 7525, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12458, UINT16_MAX, 12458, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12460, UINT16_MAX, 12460, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12462, UINT16_MAX, 12462, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12464, UINT16_MAX, 12464, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12466, UINT16_MAX, 12466, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12468, UINT16_MAX, 12468, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12470, UINT16_MAX, 12470, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12472, UINT16_MAX, 12472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12474, UINT16_MAX, 12474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12476, UINT16_MAX, 12476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12478, UINT16_MAX, 12478, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12480, UINT16_MAX, 12480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12482, UINT16_MAX, 12482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12484, UINT16_MAX, 12484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12486, UINT16_MAX, 12486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12488, UINT16_MAX, 12488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12490, UINT16_MAX, 12490, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12492, UINT16_MAX, 12492, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12494, UINT16_MAX, 12494, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12496, UINT16_MAX, 12496, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12498, UINT16_MAX, 12498, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12500, UINT16_MAX, 12500, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12502, UINT16_MAX, 12502, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12504, UINT16_MAX, 12504, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12506, UINT16_MAX, 12506, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12508, UINT16_MAX, 12508, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12510, UINT16_MAX, 12510, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12512, UINT16_MAX, 12512, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12514, UINT16_MAX, 12514, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12516, UINT16_MAX, 12516, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12518, UINT16_MAX, 12518, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12520, UINT16_MAX, 12520, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12522, UINT16_MAX, 12522, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 12524, UINT16_MAX, 12524, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 5874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 23934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40383, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 24017, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 24019, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1491, UINT16_MAX, UINT16_MAX, 12526, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1493, UINT16_MAX, UINT16_MAX, 12528, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2813, UINT16_MAX, UINT16_MAX, 12530, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1494, UINT16_MAX, UINT16_MAX, 12532, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1495, UINT16_MAX, UINT16_MAX, 12534, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2838, UINT16_MAX, UINT16_MAX, 12536, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1497, UINT16_MAX, UINT16_MAX, 12538, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1498, UINT16_MAX, UINT16_MAX, 12540, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1499, UINT16_MAX, UINT16_MAX, 12542, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1500, UINT16_MAX, UINT16_MAX, 12544, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1501, UINT16_MAX, UINT16_MAX, 12546, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1502, UINT16_MAX, UINT16_MAX, 12548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1503, UINT16_MAX, UINT16_MAX, 12550, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1504, UINT16_MAX, UINT16_MAX, 12552, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1505, UINT16_MAX, UINT16_MAX, 12554, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1507, UINT16_MAX, UINT16_MAX, 12556, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2827, UINT16_MAX, UINT16_MAX, 12558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1508, UINT16_MAX, UINT16_MAX, 12560, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3320, UINT16_MAX, UINT16_MAX, 12562, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1509, UINT16_MAX, UINT16_MAX, 12564, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1510, UINT16_MAX, UINT16_MAX, 12566, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2910, UINT16_MAX, UINT16_MAX, 12568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1511, UINT16_MAX, UINT16_MAX, 12570, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2928, UINT16_MAX, UINT16_MAX, 12572, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3327, UINT16_MAX, UINT16_MAX, 12574, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2835, UINT16_MAX, UINT16_MAX, 12576, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 24021, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 24023, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 24025, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 40411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 24030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12580, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12582, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12584, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12586, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12590, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12592, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12594, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12600, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12610, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12612, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12616, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12620, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12622, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12624, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12626, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 24032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 24034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 24036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12630, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12632, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12634, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12642, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12644, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12646, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12652, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12654, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12656, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12658, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12662, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12664, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12666, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12668, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12670, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12672, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12674, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12676, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12678, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12680, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 24038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 24040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 24042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7727, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7731, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7751, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7806, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7808, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7831, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7833, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7950, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7951, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7963, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7965, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7966, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7967, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7973, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7977, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7979, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7980, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7985, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7987, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7989, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7993, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7999, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8001, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8005, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8006, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8009, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8011, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8013, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8015, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8017, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8019, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8021, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8025, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8027, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8029, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8047, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8051, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8053, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8055, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8059, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8061, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8065, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8071, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8079, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8083, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8085, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8087, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8089, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8091, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8093, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8095, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8099, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8101, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8103, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8105, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8107, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8113, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8115, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8117, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8119, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8121, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8125, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8127, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8131, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8133, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8135, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8137, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8141, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8143, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8156, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8203, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8241, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, +}; + +static const utf8proc_uint16_t utf8proc_combinations[] = { + 0, 46, 192, 193, 194, 195, 196, 197, 0, + 256, 258, 260, 550, 461, 0, 0, 512, + 514, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7680, 7840, 0, 0, 0, 0, 0, 7842, +1, 11, + 262, 264, 0, 0, 0, 199, 0, 0, + 0, 266, 268, +0, 46, 200, 201, 202, 7868, 203, + 0, 552, 274, 276, 280, 278, 282, 0, + 0, 516, 518, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7864, 0, 7704, 7706, 0, + 0, 7866, +0, 46, 204, 205, 206, 296, 207, 0, + 0, 298, 300, 302, 304, 463, 0, 0, + 520, 522, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7882, 0, 0, 7724, 0, 0, + 7880, +0, 42, 504, 323, 0, 209, 0, 0, 325, + 0, 0, 0, 7748, 327, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7750, 7752, 7754, +0, 46, 210, 211, 212, 213, + 214, 0, 0, 332, 334, 490, 558, 465, + 336, 416, 524, 526, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7884, 0, 0, 0, + 0, 0, 7886, +0, 46, 217, 218, 219, 360, 220, + 366, 0, 362, 364, 370, 0, 467, 368, + 431, 532, 534, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7908, 0, 7798, 7796, 0, + 7794, 7910, +0, 46, 7922, 221, 374, 7928, 376, 0, + 0, 562, 0, 0, 7822, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7924, 0, 0, 0, 0, 0, + 7926, +0, 46, 224, 225, 226, 227, 228, 229, 0, + 257, 259, 261, 551, 462, 0, 0, 513, + 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7681, 7841, 0, 0, 0, 0, 0, 7843, +1, 11, + 263, 265, 0, 0, 0, 231, 0, 0, + 0, 267, 269, +0, 46, 232, 233, 234, 7869, 235, + 0, 553, 275, 277, 281, 279, 283, 0, + 0, 517, 519, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7865, 0, 7705, 7707, 0, + 0, 7867, +0, 46, 236, 237, 238, 297, 239, 0, + 0, 299, 301, 303, 0, 464, 0, 0, + 521, 523, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7883, 0, 0, 7725, 0, 0, + 7881, +0, 42, 505, 324, 0, 241, 0, 0, 326, + 0, 0, 0, 7749, 328, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7751, 7753, 7755, +0, 46, 242, 243, 244, 245, + 246, 0, 0, 333, 335, 491, 559, 466, + 337, 417, 525, 527, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7885, 0, 0, 0, + 0, 0, 7887, +0, 46, 249, 250, 251, 361, 252, + 367, 0, 363, 365, 371, 0, 468, 369, + 432, 533, 535, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7909, 0, 7799, 7797, 0, + 7795, 7911, +0, 46, 7923, 253, 375, 7929, 255, 7833, + 0, 563, 0, 0, 7823, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7925, 0, 0, 0, 0, 0, + 7927, +6, 42, 7696, 0, 0, 0, 7690, 270, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7692, 7694, 7698, +6, 42, 7697, 0, + 0, 0, 7691, 271, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7693, 7695, 7699, +1, 11, 500, 284, 0, 0, 0, + 290, 7712, 286, 0, 288, 486, +1, 11, 501, 285, + 0, 0, 0, 291, 7713, 287, 0, 289, + 487, +2, 44, 292, 0, 7718, 0, 7720, 0, 0, + 0, 7714, 542, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7716, + 0, 0, 0, 7722, +2, 44, 293, 0, 7719, 0, + 7721, 0, 0, 0, 7715, 543, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7717, 7830, 0, 0, 7723, +2, 2, 308, +2, 11, + 309, 0, 0, 0, 0, 0, 0, 0, + 0, 496, +1, 41, 7728, 0, 0, 0, 0, 310, + 0, 0, 0, 0, 488, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7730, 7732, +1, 41, 7729, 0, 0, 0, 0, + 311, 0, 0, 0, 0, 489, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7731, 7733, +1, 42, 313, 0, 0, 0, + 0, 315, 0, 0, 0, 0, 317, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7734, 7738, 7740, +1, 42, 314, 0, + 0, 0, 0, 316, 0, 0, 0, 0, + 318, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7735, 7739, 7741, +1, 41, + 340, 0, 0, 0, 0, 342, 0, 0, + 0, 7768, 344, 0, 0, 528, 530, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7770, + 7774, +1, 41, 341, 0, 0, 0, 0, 343, 0, + 0, 0, 7769, 345, 0, 0, 529, 531, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7771, 7775, +1, 40, 346, 348, 0, 0, 0, 350, + 0, 0, 0, 7776, 352, 0, 0, 0, + 0, 536, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7778, +1, 40, 347, 349, 0, 0, 0, 351, + 0, 0, 0, 7777, 353, 0, 0, 0, + 0, 537, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7779, +6, 42, 354, 0, 0, 0, 7786, 356, + 0, 0, 0, 0, 538, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7788, 7790, 7792, +4, 42, 7831, + 0, 355, 0, 0, 0, 7787, 357, 0, + 0, 0, 0, 539, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7789, 7791, 7793, +0, 40, 7808, 7810, + 372, 0, 7812, 0, 0, 0, 0, 0, + 7814, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7816, +0, 40, 7809, + 7811, 373, 0, 7813, 7832, 0, 0, 0, + 0, 7815, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7817, +1, 41, + 377, 7824, 0, 0, 0, 0, 0, 0, + 0, 379, 381, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7826, + 7828, +1, 41, 378, 7825, 0, 0, 0, 0, 0, + 0, 0, 380, 382, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7827, 7829, +0, 11, 475, 471, 0, 0, 0, 0, + 0, 469, 0, 0, 0, 473, +0, 11, 476, 472, + 0, 0, 0, 0, 0, 470, 0, 0, + 0, 474, +7, 7, 478, +7, 7, 479, +7, 7, 480, +7, 7, 481, +1, 7, 508, 0, + 0, 0, 0, 0, 482, +1, 7, 509, 0, 0, + 0, 0, 0, 483, +7, 7, 492, +7, 7, 493, +11, 11, 494, +11, 11, 495, +1, 1, + 506, +1, 1, 507, +1, 1, 510, +1, 1, 511, +7, 7, 554, +7, 7, 555, +1, 7, 7756, 0, + 0, 7758, 0, 0, 556, +1, 7, 7757, 0, 0, + 7759, 0, 0, 557, +7, 7, 560, +7, 7, 561, +0, 49, 8173, 901, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8129, +0, 50, + 8122, 902, 0, 0, 0, 0, 0, 8121, + 8120, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7944, + 7945, 0, 8124, +0, 48, 8136, 904, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7960, 7961, +0, 50, 8138, 905, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7976, 7977, 0, 8140, +0, 48, 8154, + 906, 0, 0, 938, 0, 0, 8153, 8152, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7992, 7993, +0, 48, + 8184, 908, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8008, + 8009, +0, 48, 8170, 910, 0, 0, 939, 0, 0, + 8169, 8168, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8025, +0, 50, 8186, 911, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8040, 8041, 0, 8188, +0, 49, 8146, 912, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8151, +0, 50, 8048, + 940, 0, 0, 0, 0, 0, 8113, 8112, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7936, 7937, + 8118, 8115, +0, 48, 8050, 941, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7952, 7953, +0, 50, 8052, 942, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7968, 7969, 8134, 8131, +0, 49, 8054, 943, + 0, 0, 970, 0, 0, 8145, 8144, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7984, 7985, 8150, +0, 49, + 8162, 944, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8167, +0, 49, 8058, 973, 0, 0, 971, 0, + 0, 8161, 8160, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8016, 8017, 8166, +0, 48, 8056, 972, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8000, 8001, +0, 50, 8060, 974, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8032, 8033, 8182, 8179, +1, 4, + 979, 0, 0, 980, +0, 8, 1024, 0, 0, 0, + 1025, 0, 0, 0, 1238, +1, 1, 1027, +4, 4, 1031, +1, 1, 1036, +0, 8, + 1037, 0, 0, 0, 1252, 0, 0, 1250, + 1049, +4, 12, 1264, 0, 0, 1262, 1038, 0, 0, + 0, 1266, +0, 8, 1117, 0, 0, 0, 1253, 0, + 0, 1251, 1081, +0, 8, 1104, 0, 0, 0, 1105, + 0, 0, 0, 1239, +1, 1, 1107, +4, 4, 1111, +1, 1, 1116, +4, 12, 1265, + 0, 0, 1263, 1118, 0, 0, 0, 1267, +14, 14, + 1142, +14, 14, 1143, +4, 8, 1244, 0, 0, 0, 1217, +4, 8, 1245, + 0, 0, 0, 1218, +4, 8, 1234, 0, 0, 0, + 1232, +4, 8, 1235, 0, 0, 0, 1233, +4, 4, 1242, +4, 4, 1243, +4, 4, + 1246, +4, 4, 1247, +4, 4, 1254, +4, 4, 1255, +4, 4, 1258, +4, 4, 1259, +4, 4, 1260, +4, 4, 1261, +4, 4, + 1268, +4, 4, 1269, +4, 4, 1272, +4, 4, 1273, +17, 19, 1570, 1571, 1573, +18, 18, 1572, +18, 18, + 1574, +18, 18, 1728, +18, 18, 1730, +18, 18, 1747, +20, 20, 2345, +20, 20, 2353, +20, 20, 2356, +21, 22, 2507, + 2508, +23, 25, 2888, 2891, 2892, +26, 26, 2964, +26, 27, 3020, 3018, +27, 27, 3019, +28, 28, + 3144, +29, 29, 3264, +29, 31, 3271, 3272, 3274, +29, 29, 3275, +32, 33, 3402, 3404, +32, 32, + 3403, +34, 36, 3546, 3548, 3550, +34, 34, 3549, +37, 37, 4134, +38, 38, 6918, +38, 38, 6920, +38, 38, + 6922, +38, 38, 6924, +38, 38, 6926, +38, 38, 6930, +38, 38, 6971, +38, 38, 6973, +38, 38, 6976, +38, 38, 6977, +38, 38, + 6979, +10, 41, 7682, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7684, + 7686, +10, 41, 7683, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7685, + 7687, +1, 1, 7688, +1, 1, 7689, +0, 1, 7700, 7702, +0, 1, 7701, 7703, +8, 8, 7708, +8, 8, + 7709, +10, 10, 7710, +10, 10, 7711, +1, 1, 7726, +1, 1, 7727, +7, 7, 7736, +7, 7, 7737, +1, 40, 7742, + 0, 0, 0, 0, 0, 0, 0, 0, + 7744, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7746, +1, 40, 7743, + 0, 0, 0, 0, 0, 0, 0, 0, + 7745, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7747, +0, 1, 7760, + 7762, +0, 1, 7761, 7763, +1, 10, 7764, 0, 0, 0, 0, + 0, 0, 0, 0, 7766, +1, 10, 7765, 0, 0, + 0, 0, 0, 0, 0, 0, 7767, +7, 7, 7772, +7, 7, + 7773, +10, 10, 7780, +10, 10, 7781, +10, 10, 7782, +10, 10, 7783, +10, 10, 7784, +10, 10, 7785, +1, 1, 7800, +1, 1, + 7801, +4, 4, 7802, +4, 4, 7803, +3, 40, 7804, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7806, +3, 40, 7805, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7807, +4, 10, 7820, + 0, 0, 0, 0, 0, 7818, +4, 10, 7821, 0, + 0, 0, 0, 0, 7819, +10, 10, 7835, +0, 46, 7846, 7844, + 0, 7850, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7848, +0, 46, 7847, 7845, 0, + 7851, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7849, +2, 8, 7852, 0, 0, 0, + 0, 0, 7862, +2, 8, 7853, 0, 0, 0, 0, + 0, 7863, +0, 46, 7856, 7854, 0, 7860, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7858, +0, 46, 7857, 7855, 0, 7861, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7859, +0, 46, + 7872, 7870, 0, 7876, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7874, +0, 46, 7873, + 7871, 0, 7877, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7875, +2, 2, 7878, +2, 2, 7879, +0, 46, + 7890, 7888, 0, 7894, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7892, +0, 46, 7891, + 7889, 0, 7895, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7893, +2, 2, 7896, +2, 2, 7897, +0, 46, + 7900, 7898, 0, 7904, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7906, 0, 0, 0, 0, 0, 7902, +0, 46, 7901, + 7899, 0, 7905, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7907, + 0, 0, 0, 0, 0, 7903, +0, 46, 7914, 7912, + 0, 7918, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7920, 0, + 0, 0, 0, 0, 7916, +0, 46, 7915, 7913, 0, + 7919, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7921, 0, 0, + 0, 0, 0, 7917, +0, 50, 7938, 7940, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7942, 8064, +0, 50, 7939, + 7941, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7943, 8065, +0, 50, 7946, 7948, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7950, 8072, +0, 50, 7947, 7949, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7951, 8073, +0, 1, + 7954, 7956, +0, 1, 7955, 7957, +0, 1, 7962, 7964, +0, 1, 7963, 7965, +0, 50, + 7970, 7972, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7974, 8080, +0, 50, 7971, 7973, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7975, 8081, +0, 50, 7978, 7980, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7982, + 8088, +0, 50, 7979, 7981, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7983, 8089, +0, 49, 7986, 7988, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7990, +0, 49, 7987, 7989, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7991, +0, 49, + 7994, 7996, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7998, +0, 49, 7995, 7997, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7999, +0, 1, 8002, 8004, +0, 1, 8003, 8005, +0, 1, + 8010, 8012, +0, 1, 8011, 8013, +0, 49, 8018, 8020, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8022, +0, 49, 8019, 8021, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8023, +0, 49, + 8027, 8029, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8031, +0, 50, 8034, 8036, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8038, 8096, +0, 50, 8035, 8037, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8039, 8097, +0, 50, + 8042, 8044, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8046, 8104, +0, 50, 8043, 8045, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8047, 8105, +50, 50, 8066, +50, 50, 8067, +50, 50, + 8068, +50, 50, 8069, +50, 50, 8070, +50, 50, 8071, +50, 50, 8074, +50, 50, 8075, +50, 50, 8076, +50, 50, 8077, +50, 50, + 8078, +50, 50, 8079, +50, 50, 8082, +50, 50, 8083, +50, 50, 8084, +50, 50, 8085, +50, 50, 8086, +50, 50, 8087, +50, 50, + 8090, +50, 50, 8091, +50, 50, 8092, +50, 50, 8093, +50, 50, 8094, +50, 50, 8095, +50, 50, 8098, +50, 50, 8099, +50, 50, + 8100, +50, 50, 8101, +50, 50, 8102, +50, 50, 8103, +50, 50, 8106, +50, 50, 8107, +50, 50, 8108, +50, 50, 8109, +50, 50, + 8110, +50, 50, 8111, +50, 50, 8114, +50, 50, 8116, +50, 50, 8119, +50, 50, 8130, +50, 50, 8132, +50, 50, 8135, +0, 49, + 8141, 8142, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8143, +0, 49, 8157, 8158, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8159, +47, 48, 8164, 8165, +48, 48, 8172, +50, 50, 8178, +50, 50, + 8180, +50, 50, 8183, +51, 51, 8602, +51, 51, 8603, +51, 51, 8622, +51, 51, 8653, +51, 51, 8654, +51, 51, 8655, +51, 51, + 8708, +51, 51, 8713, +51, 51, 8716, +51, 51, 8740, +51, 51, 8742, +51, 51, 8769, +51, 51, 8772, +51, 51, 8775, +51, 51, + 8777, +51, 51, 8800, +51, 51, 8802, +51, 51, 8813, +51, 51, 8814, +51, 51, 8815, +51, 51, 8816, +51, 51, 8817, +51, 51, + 8820, +51, 51, 8821, +51, 51, 8824, +51, 51, 8825, +51, 51, 8832, +51, 51, 8833, +51, 51, 8836, +51, 51, 8837, +51, 51, + 8840, +51, 51, 8841, +51, 51, 8876, +51, 51, 8877, +51, 51, 8878, +51, 51, 8879, +51, 51, 8928, +51, 51, 8929, +51, 51, + 8930, +51, 51, 8931, +51, 51, 8938, +51, 51, 8939, +51, 51, 8940, +51, 51, 8941, +51, 51, 10972, +52, 52, 12364, +52, 52, + 12366, +52, 52, 12368, +52, 52, 12370, +52, 52, 12372, +52, 52, 12374, +52, 52, 12376, +52, 52, 12378, +52, 52, 12380, +52, 52, + 12382, +52, 52, 12384, +52, 52, 12386, +52, 52, 12389, +52, 52, 12391, +52, 52, 12393, +52, 53, 12400, 12401, +52, 53, + 12403, 12404, +52, 53, 12406, 12407, +52, 53, 12409, 12410, +52, 53, 12412, 12413, +52, 52, + 12436, +52, 52, 12446, +52, 52, 12460, +52, 52, 12462, +52, 52, 12464, +52, 52, 12466, +52, 52, 12468, +52, 52, 12470, +52, 52, + 12472, +52, 52, 12474, +52, 52, 12476, +52, 52, 12478, +52, 52, 12480, +52, 52, 12482, +52, 52, 12485, +52, 52, 12487, +52, 52, + 12489, +52, 53, 12496, 12497, +52, 53, 12499, 12500, +52, 53, 12502, 12503, +52, 53, 12505, + 12506, +52, 53, 12508, 12509, +52, 52, 12532, +52, 52, 12535, +52, 52, 12536, +52, 52, 12537, +52, 52, 12538, +52, 52, + 12542, +54, 55, 1, 4250, +54, 55, 1, 4252, +54, 55, 1, 4267, +56, 57, 1, 4398, +56, 57, 1, 4399, +58, 61, 1, 4939, 1, 4940, +62, 67, + 1, 5307, 1, 5308, 1, 5310, +68, 69, 1, 5562, +68, 69, 1, 5563, +70, 71, 1, 6456, +72, 73, 1, 53598, +72, 73, 1, 53599, +74, 83, + 1, 53600, 1, 53601, 1, 53602, 1, 53603, 1, 53604, +72, 73, 1, 53691, +72, 73, 1, 53692, +74, 77, 1, 53693, + 1, 53695, +74, 77, 1, 53694, 1, 53696, +}; + diff --git a/src/common/utility/basics.h b/src/common/utility/basics.h index 6655ede2c8..0dbb47c67b 100644 --- a/src/common/utility/basics.h +++ b/src/common/utility/basics.h @@ -3,7 +3,6 @@ #include #include #include -#include "xs_Float.h" #define MAXWIDTH 12000 #define MAXHEIGHT 5000 @@ -22,7 +21,6 @@ typedef int32_t fixed_t; // the last remnants of tables.h #define ANGLE_90 (0x40000000) #define ANGLE_180 (0x80000000) -#define ANGLE_270 (0xc0000000) #define ANGLE_MAX (0xffffffff) typedef uint32_t angle_t; @@ -39,14 +37,6 @@ typedef uint32_t angle_t; #define FORCE_PACKED #endif -// Todo: get rid of this. Static file name buffers suck. -#ifndef PATH_MAX -#define BMAX_PATH 256 -#else -#define BMAX_PATH PATH_MAX -#endif - - #ifdef __GNUC__ #define GCCPRINTF(stri,firstargi) __attribute__((format(printf,stri,firstargi))) #define GCCFORMAT(stri) __attribute__((format(printf,stri,0))) @@ -69,12 +59,6 @@ using INTBOOL = int; using BITFIELD = uint32_t; -#if defined(_MSC_VER) -#define NOVTABLE __declspec(novtable) -#else -#define NOVTABLE -#endif - // always use our own definition for consistency. #ifdef M_PI #undef M_PI @@ -82,46 +66,6 @@ using BITFIELD = uint32_t; const double M_PI = 3.14159265358979323846; // matches value in gcc v2 math.h -inline float DEG2RAD(float deg) -{ - return deg * float(M_PI / 180.0); -} - -inline double DEG2RAD(double deg) -{ - return deg * (M_PI / 180.0); -} - -inline float RAD2DEG(float rad) -{ - return rad * float(180. / M_PI); -} - -inline double RAD2DEG(double rad) -{ - return rad * (180. / M_PI); -} - -inline angle_t RAD2BAM(float rad) -{ - return angle_t(xs_RoundToUInt(rad * float(0x80000000u / M_PI))); -} - -inline angle_t RAD2BAM(double rad) -{ - return angle_t(xs_RoundToUInt(rad * (0x80000000u / M_PI))); -} - - -// This is needed in common code, despite being Doom specific. -enum EStateUseFlags -{ - SUF_ACTOR = 1, - SUF_OVERLAY = 2, - SUF_WEAPON = 4, - SUF_ITEM = 8, -}; - using std::min; using std::max; using std::clamp; diff --git a/src/common/utility/bounds.cpp b/src/common/utility/bounds.cpp new file mode 100644 index 0000000000..8b1b30b8d9 --- /dev/null +++ b/src/common/utility/bounds.cpp @@ -0,0 +1,379 @@ +//----------------------------------------------------------------------------- +// Note: this is a modified version of dlight. It is not the original software. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2013-2014 Samuel Villarreal +// svkaiser@gmail.com +// +// 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. +// + +#include +#include + +#include "bounds.h" + +#define M_INFINITY 1e30f + +BBox::BBox() +{ + Clear(); +} + +BBox::BBox(const FVector3 &vMin, const FVector3 &vMax) +{ + this->min = vMin; + this->max = vMax; +} + +void BBox::Clear() +{ + min = FVector3(M_INFINITY, M_INFINITY, M_INFINITY); + max = FVector3(-M_INFINITY, -M_INFINITY, -M_INFINITY); +} + +void BBox::AddPoint(const FVector3 &vec) +{ + float lowx = min.X; + float lowy = min.Y; + float lowz = min.Z; + float hix = max.X; + float hiy = max.Y; + float hiz = max.Z; + + if (vec.X < lowx) { lowx = vec.X; } + if (vec.Y < lowy) { lowy = vec.Y; } + if (vec.Z < lowz) { lowz = vec.Z; } + if (vec.X > hix) { hix = vec.X; } + if (vec.Y > hiy) { hiy = vec.Y; } + if (vec.Z > hiz) { hiz = vec.Z; } + + min = FVector3(lowx, lowy, lowz); + max = FVector3(hix, hiy, hiz); +} + +float BBox::Radius() const +{ + int i; + float r = 0; + float r1; + float r2; + + for (i = 0; i < 3; i++) + { + r1 = fabsf(min[i]); + r2 = fabsf(max[i]); + + if (r1 > r2) + { + r += r1 * r1; + } + else + { + r += r2 * r2; + } + } + + return sqrtf(r); +} + +bool BBox::PointInside(const FVector3 &vec) const +{ + return !(vec[0] < min[0] || vec[1] < min[1] || vec[2] < min[2] || + vec[0] > max[0] || vec[1] > max[1] || vec[2] > max[2]); +} + +bool BBox::IntersectingBox(const BBox &box) const +{ + return !(box.max[0] < min[0] || box.max[1] < min[1] || box.max[2] < min[2] || + box.min[0] > max[0] || box.min[1] > max[1] || box.min[2] > max[2]); +} + +bool BBox::IntersectingBox2D(const BBox &box) const +{ + return !(box.max[0] < min[0] || box.max[2] < min[2] || + box.min[0] > max[0] || box.min[2] > max[2]); +} + +float BBox::DistanceToPlane(Plane &plane) +{ + throw "unimplemented"; + return 0; + /*FVector3 c; + float distStart; + float distEnd; + float dist = 0; + + c = Center(); + + distStart = plane.Distance(c); + distEnd = fabs((max.X - c.X) * plane.a) + + fabs((max.Y - c.Y) * plane.b) + + fabs((max.Z - c.Z) * plane.c); + + dist = distStart - distEnd; + + if (dist > 0) + { + // in front + return dist; + } + + dist = distStart + distEnd; + + if (dist < 0) + { + // behind + return dist; + } + + return 0;*/ +} + +BBox BBox::operator+(const float radius) const +{ + FVector3 vmin = min; + FVector3 vmax = max; + + vmin.X -= radius; + vmin.Y -= radius; + vmin.Z -= radius; + + vmax.X += radius; + vmax.Y += radius; + vmax.Z += radius; + + return BBox(vmin, vmax); +} + +BBox &BBox::operator+=(const float radius) +{ + min.X -= radius; + min.Y -= radius; + min.Z -= radius; + max.X += radius; + max.Y += radius; + max.Z += radius; + return *this; +} + +BBox BBox::operator+(const FVector3 &vec) const +{ + FVector3 vmin = min; + FVector3 vmax = max; + + vmin.X += vec.X; + vmin.Y += vec.Y; + vmin.Z += vec.Z; + + vmax.X += vec.X; + vmax.Y += vec.Y; + vmax.Z += vec.Z; + + return BBox(vmin, vmax); +} + +BBox BBox::operator-(const float radius) const +{ + FVector3 vmin = min; + FVector3 vmax = max; + + vmin.X += radius; + vmin.Y += radius; + vmin.Z += radius; + + vmax.X -= radius; + vmax.Y -= radius; + vmax.Z -= radius; + + return BBox(vmin, vmax); +} + +BBox BBox::operator-(const FVector3 &vec) const +{ + FVector3 vmin = min; + FVector3 vmax = max; + + vmin.X -= vec.X; + vmin.Y -= vec.Y; + vmin.Z -= vec.Z; + + vmax.X -= vec.X; + vmax.Y -= vec.Y; + vmax.Z -= vec.Z; + + return BBox(vmin, vmax); +} + +BBox &BBox::operator-=(const float radius) +{ + min.X += radius; + min.Y += radius; + min.Z += radius; + max.X -= radius; + max.Y -= radius; + max.Z -= radius; + return *this; +} + +BBox BBox::operator*(const FVector3 &vec) const +{ + BBox box = *this; + + if (vec.X < 0) { box.min.X += (vec.X - 1); } + else { box.max.X += (vec.X + 1); } + if (vec.Y < 0) { box.min.Y += (vec.Y - 1); } + else { box.max.Y += (vec.Y + 1); } + if (vec.Z < 0) { box.min.Z += (vec.Z - 1); } + else { box.max.Z += (vec.Z + 1); } + + return box; +} + +BBox &BBox::operator*=(const FVector3 &vec) +{ + if (vec.X < 0) { min.X += (vec.X - 1); } + else { max.X += (vec.X + 1); } + if (vec.Y < 0) { min.Y += (vec.Y - 1); } + else { max.Y += (vec.Y + 1); } + if (vec.Z < 0) { min.Z += (vec.Z - 1); } + else { max.Z += (vec.Z + 1); } + + return *this; +} + +BBox &BBox::operator=(const BBox &bbox) +{ + min = bbox.min; + max = bbox.max; + + return *this; +} + +FVector3 BBox::operator[](int index) const +{ + assert(index >= 0 && index < 2); + return index == 0 ? min : max; +} + +FVector3 &BBox::operator[](int index) +{ + assert(index >= 0 && index < 2); + return index == 0 ? min : max; +} + +bool BBox::LineIntersect(const FVector3 &start, const FVector3 &end) +{ + float ld[3]; + FVector3 center = Center(); + FVector3 extents = max - center; + FVector3 lineDir = (end - start) * 0.5f; + FVector3 lineCenter = lineDir + start; + FVector3 dir = lineCenter - center; + + ld[0] = fabs(lineDir.X); + if (fabs(dir.X) > extents.X + ld[0]) { return false; } + ld[1] = fabs(lineDir.Y); + if (fabs(dir.Y) > extents.Y + ld[1]) { return false; } + ld[2] = fabs(lineDir.Z); + if (fabs(dir.Z) > extents.Z + ld[2]) { return false; } + + FVector3 crossprod = lineDir ^ dir; + + if (fabs(crossprod.X) > extents.Y * ld[2] + extents.Z * ld[1]) { return false; } + if (fabs(crossprod.Y) > extents.X * ld[2] + extents.Z * ld[0]) { return false; } + if (fabs(crossprod.Z) > extents.X * ld[1] + extents.Y * ld[0]) { return false; } + + return true; +} + +// Assumes points is an array of 24 +void BBox::ToPoints(float *points) const +{ + points[0 * 3 + 0] = max[0]; + points[0 * 3 + 1] = min[1]; + points[0 * 3 + 2] = min[2]; + points[1 * 3 + 0] = max[0]; + points[1 * 3 + 1] = min[1]; + points[1 * 3 + 2] = max[2]; + points[2 * 3 + 0] = min[0]; + points[2 * 3 + 1] = min[1]; + points[2 * 3 + 2] = max[2]; + points[3 * 3 + 0] = min[0]; + points[3 * 3 + 1] = min[1]; + points[3 * 3 + 2] = min[2]; + points[4 * 3 + 0] = max[0]; + points[4 * 3 + 1] = max[1]; + points[4 * 3 + 2] = min[2]; + points[5 * 3 + 0] = max[0]; + points[5 * 3 + 1] = max[1]; + points[5 * 3 + 2] = max[2]; + points[6 * 3 + 0] = min[0]; + points[6 * 3 + 1] = max[1]; + points[6 * 3 + 2] = max[2]; + points[7 * 3 + 0] = min[0]; + points[7 * 3 + 1] = max[1]; + points[7 * 3 + 2] = min[2]; +} + +// Assumes vectors is an array of 8 +void BBox::ToVectors(FVector3 *vectors) const +{ + vectors[0][0] = max[0]; + vectors[0][1] = min[1]; + vectors[0][2] = min[2]; + vectors[1][0] = max[0]; + vectors[1][1] = min[1]; + vectors[1][2] = max[2]; + vectors[2][0] = min[0]; + vectors[2][1] = min[1]; + vectors[2][2] = max[2]; + vectors[3][0] = min[0]; + vectors[3][1] = min[1]; + vectors[3][2] = min[2]; + vectors[4][0] = max[0]; + vectors[4][1] = max[1]; + vectors[4][2] = min[2]; + vectors[5][0] = max[0]; + vectors[5][1] = max[1]; + vectors[5][2] = max[2]; + vectors[6][0] = min[0]; + vectors[6][1] = max[1]; + vectors[6][2] = max[2]; + vectors[7][0] = min[0]; + vectors[7][1] = max[1]; + vectors[7][2] = min[2]; +} + +inline FVector3 BBox::Center() const +{ + return FVector3( + (max.X + min.X) * 0.5f, + (max.Y + min.Y) * 0.5f, + (max.Z + min.Z) * 0.5f); +} + +inline FVector3 BBox::Extents() const +{ + return FVector3( + (max.X - min.X) * 0.5f, + (max.Y - min.Y) * 0.5f, + (max.Z - min.Z) * 0.5f); +} diff --git a/src/common/utility/bounds.h b/src/common/utility/bounds.h new file mode 100644 index 0000000000..29a86ce795 --- /dev/null +++ b/src/common/utility/bounds.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Note: this is from ZDRay +//----------------------------------------------------------------------------- +// +// Copyright (c) 2013-2014 Samuel Villarreal +// svkaiser@gmail.com +// +// 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. +// + +#pragma once + +#include "vectors.h" + +class BBox +{ +public: + BBox(); + BBox(const FVector3& vMin, const FVector3& vMax); + + void Clear(); + FVector3 Center() const; + FVector3 Extents() const; + float Radius() const; + void AddPoint(const FVector3& vec); + bool PointInside(const FVector3& vec) const; + bool IntersectingBox(const BBox& box) const; + bool IntersectingBox2D(const BBox& box) const; + float DistanceToPlane(Plane& plane); + bool LineIntersect(const FVector3& start, const FVector3& end); + void ToPoints(float* points) const; + void ToVectors(FVector3* vectors) const; + + BBox operator+(const float radius) const; + BBox& operator+=(const float radius); + BBox operator+(const FVector3& vec) const; + BBox operator-(const float radius) const; + BBox operator-(const FVector3& vec) const; + BBox& operator-=(const float radius); + BBox operator*(const FVector3& vec) const; + BBox& operator*=(const FVector3& vec); + BBox& operator=(const BBox& bbox); + FVector3 operator[](int index) const; + FVector3& operator[](int index); + + FVector3 min; + FVector3 max; +}; \ No newline at end of file diff --git a/src/common/utility/cmdlib.cpp b/src/common/utility/cmdlib.cpp index 02ab189591..5933a91d55 100644 --- a/src/common/utility/cmdlib.cpp +++ b/src/common/utility/cmdlib.cpp @@ -35,7 +35,8 @@ #include "cmdlib.h" -#include "findfile.h" +#include "fs_findfile.h" +#include "filesystem.h" #include "files.h" #include "md5.h" @@ -68,13 +69,16 @@ FString progdir; // //========================================================================== -static inline bool IsSeperator (int c) +static inline bool IsSeperator (int c, bool forcebackslash = false) { if (c == '/') return true; #ifdef _WIN32 if (c == '\\') return true; +#else + if (forcebackslash && c == '\\') + return true; #endif return false; } @@ -122,25 +126,6 @@ char *copystring (const char *s) return b; } -//========================================================================== -// -// ReplaceString -// -// Do not use in new code. -// -//========================================================================== - -void ReplaceString (char **ptr, const char *str) -{ - if (*ptr) - { - if (*ptr == str) - return; - delete[] *ptr; - } - *ptr = copystring (str); -} - /* ============================================================================= @@ -261,11 +246,11 @@ bool GetFileInfo(const char* pathname, size_t *size, time_t *time) // //========================================================================== -void DefaultExtension (FString &path, const char *extension) +void DefaultExtension (FString &path, const char *extension, bool forcebackslash) { const char *src = &path[int(path.Len())-1]; - while (src != &path[0] && !IsSeperator(*src)) + while (src != &path[0] && !IsSeperator(*src, forcebackslash)) { if (*src == '.') return; // it has an extension @@ -287,7 +272,7 @@ void DefaultExtension (FString &path, const char *extension) // //========================================================================== -FString ExtractFilePath (const char *path) +FString ExtractFilePath (const char *path, bool forcebackslash) { const char *src; @@ -296,7 +281,7 @@ FString ExtractFilePath (const char *path) // // back up until a \ or the start // - while (src != path && !IsSeperator(*(src-1))) + while (src != path && !IsSeperator(*(src-1), forcebackslash)) src--; return FString(path, src - path); @@ -310,7 +295,7 @@ FString ExtractFilePath (const char *path) // //========================================================================== -FString ExtractFileBase (const char *path, bool include_extension) +FString ExtractFileBase (const char *path, bool include_extension, bool forcebackslash) { const char *src, *dot; @@ -319,7 +304,7 @@ FString ExtractFileBase (const char *path, bool include_extension) if (src >= path) { // back up until a / or the start - while (src != path && !IsSeperator(*(src-1))) + while (src != path && !IsSeperator(*(src-1), forcebackslash)) src--; // Check for files with drive specification but no path @@ -343,6 +328,29 @@ FString ExtractFileBase (const char *path, bool include_extension) return FString(); } +//========================================================================== +// +// SplitPath +// +// splits a path into directory, base name and extension +// +//========================================================================== + + void SplitPath(const char* path, FString& directory, FString& base, FString& ext, bool forcebackslash) +{ + directory = ExtractFilePath(path, forcebackslash); + base = ExtractFileBase(path, forcebackslash); + auto dot = base.LastIndexOf('.'); + if (dot > -1) + { + ext = base.Mid(dot + 1); + base.Truncate(dot); + } + else + ext = ""; +} + + //========================================================================== // // StripExtension @@ -546,7 +554,7 @@ void CreatePath(const char *fn) { FString name(fn); name += '/'; - DoCreatePath(name); + DoCreatePath(name.GetChars()); } else { @@ -823,13 +831,13 @@ FString ExpandEnvVars(const char *searchpathstring) if (length != 0) { FString varname = FString(dollar + 1, length); - if (stricmp(varname, "progdir") == 0) + if (varname.CompareNoCase("progdir") == 0) { out += progdir; } else { - char *varvalue = getenv(varname); + char *varvalue = getenv(varname.GetChars()); if ( (varvalue != NULL) && (strlen(varvalue) != 0) ) { out += varvalue; @@ -897,7 +905,7 @@ FString NicePath(const char *path) slash = path + strlen(path); } FString who(path, slash - path); - pwstruct = getpwnam(who); + pwstruct = getpwnam(who.GetChars()); } if (pwstruct == NULL) { @@ -913,68 +921,6 @@ FString NicePath(const char *path) } -//========================================================================== -// -// ScanDirectory -// -//========================================================================== - -bool ScanDirectory(TArray &list, const char *dirpath) -{ - findstate_t find; - FString dirmatch; - - dirmatch << dirpath << "*"; - - auto handle = I_FindFirst(dirmatch.GetChars(), &find); - if (handle == ((void*)(-1))) - { - return false; - } - else - { - do - { - auto attr = I_FindAttr(&find); - if (attr & FA_HIDDEN) - { - // Skip hidden files and directories. (Prevents SVN bookkeeping - // info from being included.) - continue; - } - auto fn = I_FindName(&find); - - if (attr & FA_DIREC) - { - if (fn[0] == '.' && - (fn[1] == '\0' || - (fn[1] == '.' && fn[2] == '\0'))) - { - // Do not record . and .. directories. - continue; - } - - FFileList* fl = &list[list.Reserve(1)]; - fl->Filename << dirpath << fn; - fl->isDirectory = true; - FString newdir = fl->Filename; - newdir << "/"; - ScanDirectory(list, newdir); - } - else - { - FFileList* fl = &list[list.Reserve(1)]; - fl->Filename << dirpath << fn; - fl->isDirectory = false; - } - } - while (I_FindNext(handle, &find) == 0); - I_FindClose(handle); - } - return true; -} - - //========================================================================== // // @@ -1064,9 +1010,9 @@ void md5Update(FileReader& file, MD5Context& md5, unsigned len) while (len > 0) { - t = min(len, sizeof(readbuf)); + t = std::min(len, sizeof(readbuf)); len -= t; - t = (long)file.Read(readbuf, t); + t = (unsigned)file.Read(readbuf, t); md5.Update(readbuf, t); } } @@ -1089,3 +1035,17 @@ void uppercopy(char* to, const char* from) to[i] = 0; } +//========================================================================== +// +// GetStringFromLump +// +// Loads a zero terminated string from a lump in the file system +//========================================================================== + +FString GetStringFromLump(int lump, bool zerotruncate) +{ + auto fd = fileSystem.ReadFile(lump); + FString ScriptBuffer(fd.string(), fd.size()); + if (zerotruncate) ScriptBuffer.Truncate(strlen(ScriptBuffer.GetChars())); // this is necessary to properly truncate the generated string to not contain 0 bytes. + return ScriptBuffer; +} diff --git a/src/common/utility/cmdlib.h b/src/common/utility/cmdlib.h index 392d0f46db..df779a975a 100644 --- a/src/common/utility/cmdlib.h +++ b/src/common/utility/cmdlib.h @@ -12,6 +12,7 @@ #include #include #include "zstring.h" +#include "files.h" #if !defined(GUID_DEFINED) #define GUID_DEFINED @@ -33,6 +34,10 @@ char(&_ArraySizeHelper(T(&array)[N]))[N]; #define myoffsetof(type,identifier) ((size_t)&((type *)alignof(type))->identifier - alignof(type)) bool FileExists (const char *filename); +inline bool FileExists(const FString& filename) +{ + return FileExists(filename.GetChars()); +} bool FileReadable (const char *filename); bool DirExists(const char *filename); bool DirEntryExists (const char *pathname, bool *isdir = nullptr); @@ -43,18 +48,18 @@ extern FString progdir; void FixPathSeperator (char *path); static void inline FixPathSeperator (FString &path) { path.ReplaceChars('\\', '/'); } -void DefaultExtension (FString &path, const char *extension); +void DefaultExtension (FString &path, const char *extension, bool forcebackslash = false); void NormalizeFileName(FString &str); -FString ExtractFilePath (const char *path); -FString ExtractFileBase (const char *path, bool keep_extension=false); +FString ExtractFilePath (const char *path, bool forcebackslash = false); +FString ExtractFileBase (const char *path, bool keep_extension=false, bool forcebackslash = false); FString StripExtension(const char* path); +void SplitPath(const char* path, FString& directory, FString& base, FString& ext, bool forcebackslash = false); struct FScriptPosition; bool IsNum (const char *str); // [RH] added char *copystring(const char *s); -void ReplaceString (char **ptr, const char *str); bool CheckWildcards (const char *pattern, const char *text); @@ -70,13 +75,6 @@ void CreatePath(const char * fn); FString ExpandEnvVars(const char *searchpathstring); FString NicePath(const char *path); -struct FFileList -{ - FString Filename; - bool isDirectory; -}; - -bool ScanDirectory(TArray &list, const char *dirpath); bool IsAbsPath(const char*); FString M_ZLibError(int zerrnum); @@ -90,11 +88,11 @@ inline constexpr double Scale(double a, double b, double c) return (a * b) / c; } -class FileReader; struct MD5Context; void md5Update(FileReader& file, MD5Context& md5, unsigned len); void uppercopy(char* to, const char* from); +FString GetStringFromLump(int lump, bool zerotruncate = true); inline void fillshort(void* buff, size_t count, uint16_t clear) { diff --git a/src/common/utility/configfile.cpp b/src/common/utility/configfile.cpp index 52bb4bcae0..cdd4e95197 100644 --- a/src/common/utility/configfile.cpp +++ b/src/common/utility/configfile.cpp @@ -85,7 +85,7 @@ FConfigFile::FConfigFile (const FConfigFile &other) Sections = CurrentSection = NULL; LastSectionPtr = &Sections; CurrentEntry = NULL; - ChangePathName (other.PathName); + ChangePathName (other.PathName.GetChars()); *this = other; OkayToWrite = other.OkayToWrite; FileExisted = other.FileExisted; @@ -134,7 +134,7 @@ FConfigFile &FConfigFile::operator = (const FConfigFile &other) while (fromsection != NULL) { fromentry = fromsection->RootEntry; - tosection = NewConfigSection (fromsection->SectionName); + tosection = NewConfigSection (fromsection->SectionName.GetChars()); while (fromentry != NULL) { NewConfigEntry (tosection, fromentry->Key, fromentry->Value); @@ -602,7 +602,7 @@ void FConfigFile::LoadConfigFile () bool succ; FileExisted = false; - if (!file.OpenFile (PathName)) + if (!file.OpenFile (PathName.GetChars())) { return; } @@ -739,7 +739,7 @@ FConfigFile::FConfigEntry *FConfigFile::ReadMultiLineValue(FileReader *file, FCo // Append this line to the value. value << readbuf; } - return NewConfigEntry(section, key, value); + return NewConfigEntry(section, key, value.GetChars()); } //==================================================================== @@ -787,7 +787,7 @@ bool FConfigFile::WriteConfigFile () const return true; } - FileWriter *file = FileWriter::Open (PathName); + FileWriter *file = FileWriter::Open (PathName.GetChars()); FConfigSection *section; FConfigEntry *entry; diff --git a/src/common/utility/configfile.h b/src/common/utility/configfile.h index cc484a3c24..f1a5ab87d6 100644 --- a/src/common/utility/configfile.h +++ b/src/common/utility/configfile.h @@ -66,6 +66,10 @@ class FConfigFile bool NextInSection (const char *&key, const char *&value); const char *GetValueForKey (const char *key) const; void SetValueForKey (const char *key, const char *value, bool duplicates=false); + void SetValueForKey(const char* key, const FString& value, bool duplicates = false) + { + SetValueForKey(key, value.GetChars(), duplicates); + } const char *GetPathName () const { return PathName.GetChars(); } void ChangePathName (const char *path); diff --git a/src/common/utility/engineerrors.cpp b/src/common/utility/engineerrors.cpp index 4d01258192..05897b7862 100644 --- a/src/common/utility/engineerrors.cpp +++ b/src/common/utility/engineerrors.cpp @@ -35,8 +35,9 @@ bool gameisdead; -#ifdef _WIN32 #include + +#ifdef _WIN32 #include #include "zstring.h" void I_DebugPrint(const char *cp) @@ -60,7 +61,7 @@ void I_DebugPrintf(const char *fmt,...) va_end(args); - auto wstr = WideString(s); + auto wstr = WideString(s.GetChars()); OutputDebugStringW(wstr.c_str()); } } diff --git a/src/common/utility/engineerrors.h b/src/common/utility/engineerrors.h index 18fe849bc3..a8d439f7a7 100644 --- a/src/common/utility/engineerrors.h +++ b/src/common/utility/engineerrors.h @@ -59,13 +59,13 @@ class CEngineError : public std::exception strncpy (m_Message, message, MAX_ERRORTEXT-1); m_Message[MAX_ERRORTEXT-1] = '\0'; } - void AppendMessage(const char *message) + void AppendMessage(const char *message) noexcept { size_t len = strlen(m_Message); strncpy(m_Message + len, message, MAX_ERRORTEXT - 1 - len); m_Message[MAX_ERRORTEXT - 1] = '\0'; } - const char *GetMessage (void) const + const char *GetMessage (void) const noexcept { if (m_Message[0] != '\0') return (const char *)m_Message; diff --git a/src/common/utility/filereadermusicinterface.h b/src/common/utility/filereadermusicinterface.h index f261f9dd03..c30ac6c55e 100644 --- a/src/common/utility/filereadermusicinterface.h +++ b/src/common/utility/filereadermusicinterface.h @@ -6,13 +6,14 @@ inline ZMusicCustomReader *GetMusicReader(FileReader& fr) { + using FileSys::FileReaderInterface; auto zcr = new ZMusicCustomReader; zcr->handle = fr.GetInterface(); zcr->gets = [](ZMusicCustomReader* zr, char* buff, int n) { return reinterpret_cast(zr->handle)->Gets(buff, n); }; - zcr->read = [](ZMusicCustomReader* zr, void* buff, int32_t size) { return reinterpret_cast(zr->handle)->Read(buff, (long)size); }; - zcr->seek = [](ZMusicCustomReader* zr, long offset, int whence) { return reinterpret_cast(zr->handle)->Seek(offset, whence); }; - zcr->tell = [](ZMusicCustomReader* zr) { return reinterpret_cast(zr->handle)->Tell(); }; + zcr->read = [](ZMusicCustomReader* zr, void* buff, int32_t size) -> long { return (long)reinterpret_cast(zr->handle)->Read(buff, size); }; + zcr->seek = [](ZMusicCustomReader* zr, long offset, int whence) -> long { return (long)reinterpret_cast(zr->handle)->Seek(offset, whence); }; + zcr->tell = [](ZMusicCustomReader* zr) -> long { return (long)reinterpret_cast(zr->handle)->Tell(); }; zcr->close = [](ZMusicCustomReader* zr) { delete reinterpret_cast(zr->handle); diff --git a/src/common/utility/findfile.cpp b/src/common/utility/findfile.cpp index 0da6a97fff..65090cc903 100644 --- a/src/common/utility/findfile.cpp +++ b/src/common/utility/findfile.cpp @@ -38,160 +38,11 @@ #include "printf.h" #include "configfile.h" #include "i_system.h" +#include "fs_findfile.h" -#ifndef _WIN32 - -#include -#include +#ifdef __unix__ #include - -#include "cmdlib.h" - -static const char *pattern; - -static int matchfile(const struct dirent *ent) -{ - return fnmatch(pattern, ent->d_name, FNM_NOESCAPE) == 0; -} - -void *I_FindFirst(const char *const filespec, findstate_t *const fileinfo) -{ - FString dir; - - const char *const slash = strrchr(filespec, '/'); - - if (slash) - { - pattern = slash + 1; - dir = FString(filespec, slash - filespec + 1); - fileinfo->path = dir; - } - else - { - pattern = filespec; - dir = "."; - } - - fileinfo->current = 0; - fileinfo->count = scandir(dir.GetChars(), &fileinfo->namelist, matchfile, alphasort); - - if (fileinfo->count > 0) - { - return fileinfo; - } - - return (void *)-1; -} - -int I_FindNext(void *const handle, findstate_t *const fileinfo) -{ - findstate_t *const state = static_cast(handle); - - if (state->current < fileinfo->count) - { - return ++state->current < fileinfo->count ? 0 : -1; - } - - return -1; -} - -int I_FindClose(void *const handle) -{ - findstate_t *const state = static_cast(handle); - - if (handle != (void *)-1 && state->count > 0) - { - for (int i = 0; i < state->count; ++i) - { - free(state->namelist[i]); - } - - free(state->namelist); - state->namelist = nullptr; - state->count = 0; - } - - return 0; -} - -int I_FindAttr(findstate_t *const fileinfo) -{ - dirent *const ent = fileinfo->namelist[fileinfo->current]; - const FString path = fileinfo->path + ent->d_name; - bool isdir; - - if (DirEntryExists(path, &isdir)) - { - return isdir ? FA_DIREC : 0; - } - - return 0; -} - -#else - -#include -#include - -//========================================================================== -// -// I_FindFirst -// -// Start a pattern matching sequence. -// -//========================================================================== - - -void *I_FindFirst(const char *filespec, findstate_t *fileinfo) -{ - static_assert(sizeof(WIN32_FIND_DATAW) == sizeof(fileinfo->FindData), "FindData size mismatch"); - auto widespec = WideString(filespec); - fileinfo->UTF8Name = ""; - return FindFirstFileW(widespec.c_str(), (LPWIN32_FIND_DATAW)&fileinfo->FindData); -} - -//========================================================================== -// -// I_FindNext -// -// Return the next file in a pattern matching sequence. -// -//========================================================================== - -int I_FindNext(void *handle, findstate_t *fileinfo) -{ - fileinfo->UTF8Name = ""; - return !FindNextFileW((HANDLE)handle, (LPWIN32_FIND_DATAW)&fileinfo->FindData); -} - -//========================================================================== -// -// I_FindClose -// -// Finish a pattern matching sequence. -// -//========================================================================== - -int I_FindClose(void *handle) -{ - return FindClose((HANDLE)handle); -} - -//========================================================================== -// -// I_FindName -// -// Returns the name for an entry -// -//========================================================================== - -const char *I_FindName(findstate_t *fileinfo) -{ - if (fileinfo->UTF8Name.IsEmpty()) fileinfo->UTF8Name = fileinfo->FindData.Name; - return fileinfo->UTF8Name.GetChars(); -} - -#endif +#endif // __unix__ //========================================================================== // @@ -199,7 +50,7 @@ const char *I_FindName(findstate_t *fileinfo) // //========================================================================== -bool D_AddFile(TArray& wadfiles, const char* file, bool check, int position, FConfigFile* config) +bool D_AddFile(std::vector& wadfiles, const char* file, bool check, int position, FConfigFile* config) { if (file == nullptr || *file == '\0') { @@ -239,7 +90,7 @@ bool D_AddFile(TArray& wadfiles, const char* file, bool check, int posi closedir(d); if (!found) { - Printf("Can't find file '%s' in '%s'\n", filename.GetChars(), basepath.GetChars()); + //Printf("Can't find file '%s' in '%s'\n", filename.GetChars(), basepath.GetChars()); return false; } } @@ -263,10 +114,10 @@ bool D_AddFile(TArray& wadfiles, const char* file, bool check, int posi file = f; } - FString f = file; - FixPathSeperator(f); - if (position == -1) wadfiles.Push(f); - else wadfiles.Insert(position, f); + std::string f = file; + for (auto& c : f) if (c == '\\') c = '/'; + if (position == -1) wadfiles.push_back(f); + else wadfiles.insert(wadfiles.begin() + position, f); return true; } @@ -276,7 +127,7 @@ bool D_AddFile(TArray& wadfiles, const char* file, bool check, int posi // //========================================================================== -void D_AddWildFile(TArray& wadfiles, const char* value, const char *extension, FConfigFile* config) +void D_AddWildFile(std::vector& wadfiles, const char* value, const char *extension, FConfigFile* config) { if (value == nullptr || *value == '\0') { @@ -288,45 +139,20 @@ void D_AddWildFile(TArray& wadfiles, const char* value, const char *ext { D_AddFile(wadfiles, wadfile, true, -1, config); } - else - { // Try pattern matching - findstate_t findstate; - char path[ZPATH_MAX]; - char* sep; - void* handle = I_FindFirst(value, &findstate); - - strcpy(path, value); - sep = strrchr(path, '/'); - if (sep == nullptr) - { - sep = strrchr(path, '\\'); -#ifdef _WIN32 - if (sep == nullptr && path[1] == ':') + else + { + // Try pattern matching + FileSys::FileList list; + auto path = ExtractFilePath(value); + auto name = ExtractFileBase(value, true); + if (path.IsEmpty()) path = "."; + if (FileSys::ScanDirectory(list, path.GetChars(), name.GetChars(), true)) + { + for(auto& entry : list) { - sep = path + 1; + D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config); } -#endif } - - if (handle != ((void*)-1)) - { - do - { - if (!(I_FindAttr(&findstate) & FA_DIREC)) - { - if (sep == nullptr) - { - D_AddFile(wadfiles, I_FindName(&findstate), true, -1, config); - } - else - { - strcpy(sep + 1, I_FindName(&findstate)); - D_AddFile(wadfiles, path, true, -1, config); - } - } - } while (I_FindNext(handle, &findstate) == 0); - } - I_FindClose(handle); } } @@ -338,7 +164,7 @@ void D_AddWildFile(TArray& wadfiles, const char* value, const char *ext // //========================================================================== -void D_AddConfigFiles(TArray& wadfiles, const char* section, const char* extension, FConfigFile *config) +void D_AddConfigFiles(std::vector& wadfiles, const char* section, const char* extension, FConfigFile *config) { if (config && config->SetSection(section)) { @@ -352,7 +178,7 @@ void D_AddConfigFiles(TArray& wadfiles, const char* section, const char { // D_AddWildFile resets config's position, so remember it config->GetPosition(pos); - D_AddWildFile(wadfiles, ExpandEnvVars(value), extension, config); + D_AddWildFile(wadfiles, ExpandEnvVars(value).GetChars(), extension, config); // Reset config's position to get next wad config->SetPosition(pos); } @@ -368,42 +194,18 @@ void D_AddConfigFiles(TArray& wadfiles, const char* section, const char // //========================================================================== -void D_AddDirectory(TArray& wadfiles, const char* dir, const char *filespec, FConfigFile* config) +void D_AddDirectory(std::vector& wadfiles, const char* dir, const char *filespec, FConfigFile* config) { - FString curdir = I_GetCWD(); - if (curdir.IsNotEmpty()) + FileSys::FileList list; + if (FileSys::ScanDirectory(list, dir, "*.wad", true)) { - char skindir[ZPATH_MAX]; - findstate_t findstate; - void* handle; - size_t stuffstart; - - stuffstart = strlen(dir); - memcpy(skindir, dir, stuffstart * sizeof(*dir)); - skindir[stuffstart] = 0; - - if (skindir[stuffstart - 1] == '/') + for (auto& entry : list) { - skindir[--stuffstart] = 0; - } - - if (I_ChDir(skindir)) - { - skindir[stuffstart++] = '/'; - if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1) + if (!entry.isDirectory) { - do - { - if (!(I_FindAttr(&findstate) & FA_DIREC)) - { - strcpy(skindir + stuffstart, I_FindName(&findstate)); - D_AddFile(wadfiles, skindir, true, -1, config); - } - } while (I_FindNext(handle, &findstate) == 0); - I_FindClose(handle); + D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config); } } - I_ChDir(curdir); } } @@ -428,7 +230,7 @@ const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinpr if (lookfirstinprogdir) { BFSwad.Format("%s%s%s", progdir.GetChars(), progdir.Back() == '/' ? "" : "/", file); - if (DirEntryExists(BFSwad)) + if (DirEntryExists(BFSwad.GetChars())) { return BFSwad.GetChars(); } @@ -455,7 +257,7 @@ const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinpr if (dir.IsNotEmpty()) { BFSwad.Format("%s%s%s", dir.GetChars(), dir.Back() == '/' ? "" : "/", file); - if (DirEntryExists(BFSwad)) + if (DirEntryExists(BFSwad.GetChars())) { return BFSwad.GetChars(); } @@ -469,7 +271,7 @@ const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinpr { FString tmp = file; DefaultExtension(tmp, ext); - return BaseFileSearch(tmp, nullptr, lookfirstinprogdir, config); + return BaseFileSearch(tmp.GetChars(), nullptr, lookfirstinprogdir, config); } return nullptr; } diff --git a/src/common/utility/findfile.h b/src/common/utility/findfile.h index 44bee1a35a..fd58ecde5e 100644 --- a/src/common/utility/findfile.h +++ b/src/common/utility/findfile.h @@ -2,98 +2,13 @@ // Directory searching routines #include -#include "zstring.h" - -enum -{ - ZPATH_MAX = 260 -}; - -#ifndef _WIN32 - -#include - -struct findstate_t -{ -private: - FString path; - struct dirent **namelist; - int current; - int count; - - friend void *I_FindFirst(const char *filespec, findstate_t *fileinfo); - friend int I_FindNext(void *handle, findstate_t *fileinfo); - friend const char *I_FindName(findstate_t *fileinfo); - friend int I_FindAttr(findstate_t *fileinfo); - friend int I_FindClose(void *handle); -}; - -int I_FindAttr (findstate_t *fileinfo); - -inline const char *I_FindName(findstate_t *fileinfo) -{ - return (fileinfo->namelist[fileinfo->current]->d_name); -} - -#define FA_RDONLY 1 -#define FA_HIDDEN 2 -#define FA_SYSTEM 4 -#define FA_DIREC 8 -#define FA_ARCH 16 - - -#else - -// Mirror WIN32_FIND_DATAW in - -struct findstate_t -{ -private: - struct FileTime - { - uint32_t lo, hi; - }; - struct WinData - { - uint32_t Attribs; - FileTime Times[3]; - uint32_t Size[2]; - uint32_t Reserved[2]; - wchar_t Name[ZPATH_MAX]; - wchar_t AltName[14]; - }; - WinData FindData; - FString UTF8Name; - - friend void *I_FindFirst(const char *filespec, findstate_t *fileinfo); - friend int I_FindNext(void *handle, findstate_t *fileinfo); - friend const char *I_FindName(findstate_t *fileinfo); - friend int I_FindAttr(findstate_t *fileinfo); -}; - - -const char *I_FindName(findstate_t *fileinfo); -inline int I_FindAttr(findstate_t *fileinfo) -{ - return fileinfo->FindData.Attribs; -} - -#define FA_RDONLY 0x00000001 -#define FA_HIDDEN 0x00000002 -#define FA_SYSTEM 0x00000004 -#define FA_DIREC 0x00000010 -#define FA_ARCH 0x00000020 - -#endif - -void *I_FindFirst (const char *filespec, findstate_t *fileinfo); -int I_FindNext (void *handle, findstate_t *fileinfo); -int I_FindClose (void *handle); +#include +#include class FConfigFile; -bool D_AddFile(TArray& wadfiles, const char* file, bool check, int position, FConfigFile* config); -void D_AddWildFile(TArray& wadfiles, const char* value, const char *extension, FConfigFile* config); -void D_AddConfigFiles(TArray& wadfiles, const char* section, const char* extension, FConfigFile* config); -void D_AddDirectory(TArray& wadfiles, const char* dir, const char *filespec, FConfigFile* config); +bool D_AddFile(std::vector& wadfiles, const char* file, bool check, int position, FConfigFile* config); +void D_AddWildFile(std::vector& wadfiles, const char* value, const char *extension, FConfigFile* config); +void D_AddConfigFiles(std::vector& wadfiles, const char* section, const char* extension, FConfigFile* config); +void D_AddDirectory(std::vector& wadfiles, const char* dir, const char *filespec, FConfigFile* config); const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinprogdir, FConfigFile* config); diff --git a/src/common/utility/geometry.h b/src/common/utility/geometry.h index cbe0fc72d4..3a7bb8d9c8 100644 --- a/src/common/utility/geometry.h +++ b/src/common/utility/geometry.h @@ -150,7 +150,7 @@ inline double InterceptLineSegments(double v2x, double v2y, double v2dx, double den = 1 / den; double factor1 = ((v2x - v1x) * v2dy + (v1y - v2y) * v2dx) * -den; - if (factor1 < 0 || factor1 > 1) return -FLT_MAX; // no intersection + if (factor1 < 0 || factor1 >= 1) return -FLT_MAX; // no intersection if (pfactor1) *pfactor1 = factor1; return ((v1x - v2x) * v1dy + (v2y - v1y) * v1dx) * den; // this one's for the line segment where we want to get the intercept factor for so it needs to be last. diff --git a/src/common/utility/halffloat.cpp b/src/common/utility/halffloat.cpp new file mode 100644 index 0000000000..4d738aa23b --- /dev/null +++ b/src/common/utility/halffloat.cpp @@ -0,0 +1,3378 @@ +/* +** Based on the paper "Fast Half Float Conversions" by Jeroen van der Zijp. +** +** 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. +** +*/ + +#include "halffloat.h" + +namespace HalfFloatTables +{ + unsigned int mantissa_table[2048] = + { + 0, + 864026624, + 872415232, + 876609536, + 880803840, + 882900992, + 884998144, + 887095296, + 889192448, + 890241024, + 891289600, + 892338176, + 893386752, + 894435328, + 895483904, + 896532480, + 897581056, + 898105344, + 898629632, + 899153920, + 899678208, + 900202496, + 900726784, + 901251072, + 901775360, + 902299648, + 902823936, + 903348224, + 903872512, + 904396800, + 904921088, + 905445376, + 905969664, + 906231808, + 906493952, + 906756096, + 907018240, + 907280384, + 907542528, + 907804672, + 908066816, + 908328960, + 908591104, + 908853248, + 909115392, + 909377536, + 909639680, + 909901824, + 910163968, + 910426112, + 910688256, + 910950400, + 911212544, + 911474688, + 911736832, + 911998976, + 912261120, + 912523264, + 912785408, + 913047552, + 913309696, + 913571840, + 913833984, + 914096128, + 914358272, + 914489344, + 914620416, + 914751488, + 914882560, + 915013632, + 915144704, + 915275776, + 915406848, + 915537920, + 915668992, + 915800064, + 915931136, + 916062208, + 916193280, + 916324352, + 916455424, + 916586496, + 916717568, + 916848640, + 916979712, + 917110784, + 917241856, + 917372928, + 917504000, + 917635072, + 917766144, + 917897216, + 918028288, + 918159360, + 918290432, + 918421504, + 918552576, + 918683648, + 918814720, + 918945792, + 919076864, + 919207936, + 919339008, + 919470080, + 919601152, + 919732224, + 919863296, + 919994368, + 920125440, + 920256512, + 920387584, + 920518656, + 920649728, + 920780800, + 920911872, + 921042944, + 921174016, + 921305088, + 921436160, + 921567232, + 921698304, + 921829376, + 921960448, + 922091520, + 922222592, + 922353664, + 922484736, + 922615808, + 922746880, + 922812416, + 922877952, + 922943488, + 923009024, + 923074560, + 923140096, + 923205632, + 923271168, + 923336704, + 923402240, + 923467776, + 923533312, + 923598848, + 923664384, + 923729920, + 923795456, + 923860992, + 923926528, + 923992064, + 924057600, + 924123136, + 924188672, + 924254208, + 924319744, + 924385280, + 924450816, + 924516352, + 924581888, + 924647424, + 924712960, + 924778496, + 924844032, + 924909568, + 924975104, + 925040640, + 925106176, + 925171712, + 925237248, + 925302784, + 925368320, + 925433856, + 925499392, + 925564928, + 925630464, + 925696000, + 925761536, + 925827072, + 925892608, + 925958144, + 926023680, + 926089216, + 926154752, + 926220288, + 926285824, + 926351360, + 926416896, + 926482432, + 926547968, + 926613504, + 926679040, + 926744576, + 926810112, + 926875648, + 926941184, + 927006720, + 927072256, + 927137792, + 927203328, + 927268864, + 927334400, + 927399936, + 927465472, + 927531008, + 927596544, + 927662080, + 927727616, + 927793152, + 927858688, + 927924224, + 927989760, + 928055296, + 928120832, + 928186368, + 928251904, + 928317440, + 928382976, + 928448512, + 928514048, + 928579584, + 928645120, + 928710656, + 928776192, + 928841728, + 928907264, + 928972800, + 929038336, + 929103872, + 929169408, + 929234944, + 929300480, + 929366016, + 929431552, + 929497088, + 929562624, + 929628160, + 929693696, + 929759232, + 929824768, + 929890304, + 929955840, + 930021376, + 930086912, + 930152448, + 930217984, + 930283520, + 930349056, + 930414592, + 930480128, + 930545664, + 930611200, + 930676736, + 930742272, + 930807808, + 930873344, + 930938880, + 931004416, + 931069952, + 931135488, + 931168256, + 931201024, + 931233792, + 931266560, + 931299328, + 931332096, + 931364864, + 931397632, + 931430400, + 931463168, + 931495936, + 931528704, + 931561472, + 931594240, + 931627008, + 931659776, + 931692544, + 931725312, + 931758080, + 931790848, + 931823616, + 931856384, + 931889152, + 931921920, + 931954688, + 931987456, + 932020224, + 932052992, + 932085760, + 932118528, + 932151296, + 932184064, + 932216832, + 932249600, + 932282368, + 932315136, + 932347904, + 932380672, + 932413440, + 932446208, + 932478976, + 932511744, + 932544512, + 932577280, + 932610048, + 932642816, + 932675584, + 932708352, + 932741120, + 932773888, + 932806656, + 932839424, + 932872192, + 932904960, + 932937728, + 932970496, + 933003264, + 933036032, + 933068800, + 933101568, + 933134336, + 933167104, + 933199872, + 933232640, + 933265408, + 933298176, + 933330944, + 933363712, + 933396480, + 933429248, + 933462016, + 933494784, + 933527552, + 933560320, + 933593088, + 933625856, + 933658624, + 933691392, + 933724160, + 933756928, + 933789696, + 933822464, + 933855232, + 933888000, + 933920768, + 933953536, + 933986304, + 934019072, + 934051840, + 934084608, + 934117376, + 934150144, + 934182912, + 934215680, + 934248448, + 934281216, + 934313984, + 934346752, + 934379520, + 934412288, + 934445056, + 934477824, + 934510592, + 934543360, + 934576128, + 934608896, + 934641664, + 934674432, + 934707200, + 934739968, + 934772736, + 934805504, + 934838272, + 934871040, + 934903808, + 934936576, + 934969344, + 935002112, + 935034880, + 935067648, + 935100416, + 935133184, + 935165952, + 935198720, + 935231488, + 935264256, + 935297024, + 935329792, + 935362560, + 935395328, + 935428096, + 935460864, + 935493632, + 935526400, + 935559168, + 935591936, + 935624704, + 935657472, + 935690240, + 935723008, + 935755776, + 935788544, + 935821312, + 935854080, + 935886848, + 935919616, + 935952384, + 935985152, + 936017920, + 936050688, + 936083456, + 936116224, + 936148992, + 936181760, + 936214528, + 936247296, + 936280064, + 936312832, + 936345600, + 936378368, + 936411136, + 936443904, + 936476672, + 936509440, + 936542208, + 936574976, + 936607744, + 936640512, + 936673280, + 936706048, + 936738816, + 936771584, + 936804352, + 936837120, + 936869888, + 936902656, + 936935424, + 936968192, + 937000960, + 937033728, + 937066496, + 937099264, + 937132032, + 937164800, + 937197568, + 937230336, + 937263104, + 937295872, + 937328640, + 937361408, + 937394176, + 937426944, + 937459712, + 937492480, + 937525248, + 937558016, + 937590784, + 937623552, + 937656320, + 937689088, + 937721856, + 937754624, + 937787392, + 937820160, + 937852928, + 937885696, + 937918464, + 937951232, + 937984000, + 938016768, + 938049536, + 938082304, + 938115072, + 938147840, + 938180608, + 938213376, + 938246144, + 938278912, + 938311680, + 938344448, + 938377216, + 938409984, + 938442752, + 938475520, + 938508288, + 938541056, + 938573824, + 938606592, + 938639360, + 938672128, + 938704896, + 938737664, + 938770432, + 938803200, + 938835968, + 938868736, + 938901504, + 938934272, + 938967040, + 938999808, + 939032576, + 939065344, + 939098112, + 939130880, + 939163648, + 939196416, + 939229184, + 939261952, + 939294720, + 939327488, + 939360256, + 939393024, + 939425792, + 939458560, + 939491328, + 939524096, + 939540480, + 939556864, + 939573248, + 939589632, + 939606016, + 939622400, + 939638784, + 939655168, + 939671552, + 939687936, + 939704320, + 939720704, + 939737088, + 939753472, + 939769856, + 939786240, + 939802624, + 939819008, + 939835392, + 939851776, + 939868160, + 939884544, + 939900928, + 939917312, + 939933696, + 939950080, + 939966464, + 939982848, + 939999232, + 940015616, + 940032000, + 940048384, + 940064768, + 940081152, + 940097536, + 940113920, + 940130304, + 940146688, + 940163072, + 940179456, + 940195840, + 940212224, + 940228608, + 940244992, + 940261376, + 940277760, + 940294144, + 940310528, + 940326912, + 940343296, + 940359680, + 940376064, + 940392448, + 940408832, + 940425216, + 940441600, + 940457984, + 940474368, + 940490752, + 940507136, + 940523520, + 940539904, + 940556288, + 940572672, + 940589056, + 940605440, + 940621824, + 940638208, + 940654592, + 940670976, + 940687360, + 940703744, + 940720128, + 940736512, + 940752896, + 940769280, + 940785664, + 940802048, + 940818432, + 940834816, + 940851200, + 940867584, + 940883968, + 940900352, + 940916736, + 940933120, + 940949504, + 940965888, + 940982272, + 940998656, + 941015040, + 941031424, + 941047808, + 941064192, + 941080576, + 941096960, + 941113344, + 941129728, + 941146112, + 941162496, + 941178880, + 941195264, + 941211648, + 941228032, + 941244416, + 941260800, + 941277184, + 941293568, + 941309952, + 941326336, + 941342720, + 941359104, + 941375488, + 941391872, + 941408256, + 941424640, + 941441024, + 941457408, + 941473792, + 941490176, + 941506560, + 941522944, + 941539328, + 941555712, + 941572096, + 941588480, + 941604864, + 941621248, + 941637632, + 941654016, + 941670400, + 941686784, + 941703168, + 941719552, + 941735936, + 941752320, + 941768704, + 941785088, + 941801472, + 941817856, + 941834240, + 941850624, + 941867008, + 941883392, + 941899776, + 941916160, + 941932544, + 941948928, + 941965312, + 941981696, + 941998080, + 942014464, + 942030848, + 942047232, + 942063616, + 942080000, + 942096384, + 942112768, + 942129152, + 942145536, + 942161920, + 942178304, + 942194688, + 942211072, + 942227456, + 942243840, + 942260224, + 942276608, + 942292992, + 942309376, + 942325760, + 942342144, + 942358528, + 942374912, + 942391296, + 942407680, + 942424064, + 942440448, + 942456832, + 942473216, + 942489600, + 942505984, + 942522368, + 942538752, + 942555136, + 942571520, + 942587904, + 942604288, + 942620672, + 942637056, + 942653440, + 942669824, + 942686208, + 942702592, + 942718976, + 942735360, + 942751744, + 942768128, + 942784512, + 942800896, + 942817280, + 942833664, + 942850048, + 942866432, + 942882816, + 942899200, + 942915584, + 942931968, + 942948352, + 942964736, + 942981120, + 942997504, + 943013888, + 943030272, + 943046656, + 943063040, + 943079424, + 943095808, + 943112192, + 943128576, + 943144960, + 943161344, + 943177728, + 943194112, + 943210496, + 943226880, + 943243264, + 943259648, + 943276032, + 943292416, + 943308800, + 943325184, + 943341568, + 943357952, + 943374336, + 943390720, + 943407104, + 943423488, + 943439872, + 943456256, + 943472640, + 943489024, + 943505408, + 943521792, + 943538176, + 943554560, + 943570944, + 943587328, + 943603712, + 943620096, + 943636480, + 943652864, + 943669248, + 943685632, + 943702016, + 943718400, + 943734784, + 943751168, + 943767552, + 943783936, + 943800320, + 943816704, + 943833088, + 943849472, + 943865856, + 943882240, + 943898624, + 943915008, + 943931392, + 943947776, + 943964160, + 943980544, + 943996928, + 944013312, + 944029696, + 944046080, + 944062464, + 944078848, + 944095232, + 944111616, + 944128000, + 944144384, + 944160768, + 944177152, + 944193536, + 944209920, + 944226304, + 944242688, + 944259072, + 944275456, + 944291840, + 944308224, + 944324608, + 944340992, + 944357376, + 944373760, + 944390144, + 944406528, + 944422912, + 944439296, + 944455680, + 944472064, + 944488448, + 944504832, + 944521216, + 944537600, + 944553984, + 944570368, + 944586752, + 944603136, + 944619520, + 944635904, + 944652288, + 944668672, + 944685056, + 944701440, + 944717824, + 944734208, + 944750592, + 944766976, + 944783360, + 944799744, + 944816128, + 944832512, + 944848896, + 944865280, + 944881664, + 944898048, + 944914432, + 944930816, + 944947200, + 944963584, + 944979968, + 944996352, + 945012736, + 945029120, + 945045504, + 945061888, + 945078272, + 945094656, + 945111040, + 945127424, + 945143808, + 945160192, + 945176576, + 945192960, + 945209344, + 945225728, + 945242112, + 945258496, + 945274880, + 945291264, + 945307648, + 945324032, + 945340416, + 945356800, + 945373184, + 945389568, + 945405952, + 945422336, + 945438720, + 945455104, + 945471488, + 945487872, + 945504256, + 945520640, + 945537024, + 945553408, + 945569792, + 945586176, + 945602560, + 945618944, + 945635328, + 945651712, + 945668096, + 945684480, + 945700864, + 945717248, + 945733632, + 945750016, + 945766400, + 945782784, + 945799168, + 945815552, + 945831936, + 945848320, + 945864704, + 945881088, + 945897472, + 945913856, + 945930240, + 945946624, + 945963008, + 945979392, + 945995776, + 946012160, + 946028544, + 946044928, + 946061312, + 946077696, + 946094080, + 946110464, + 946126848, + 946143232, + 946159616, + 946176000, + 946192384, + 946208768, + 946225152, + 946241536, + 946257920, + 946274304, + 946290688, + 946307072, + 946323456, + 946339840, + 946356224, + 946372608, + 946388992, + 946405376, + 946421760, + 946438144, + 946454528, + 946470912, + 946487296, + 946503680, + 946520064, + 946536448, + 946552832, + 946569216, + 946585600, + 946601984, + 946618368, + 946634752, + 946651136, + 946667520, + 946683904, + 946700288, + 946716672, + 946733056, + 946749440, + 946765824, + 946782208, + 946798592, + 946814976, + 946831360, + 946847744, + 946864128, + 946880512, + 946896896, + 946913280, + 946929664, + 946946048, + 946962432, + 946978816, + 946995200, + 947011584, + 947027968, + 947044352, + 947060736, + 947077120, + 947093504, + 947109888, + 947126272, + 947142656, + 947159040, + 947175424, + 947191808, + 947208192, + 947224576, + 947240960, + 947257344, + 947273728, + 947290112, + 947306496, + 947322880, + 947339264, + 947355648, + 947372032, + 947388416, + 947404800, + 947421184, + 947437568, + 947453952, + 947470336, + 947486720, + 947503104, + 947519488, + 947535872, + 947552256, + 947568640, + 947585024, + 947601408, + 947617792, + 947634176, + 947650560, + 947666944, + 947683328, + 947699712, + 947716096, + 947732480, + 947748864, + 947765248, + 947781632, + 947798016, + 947814400, + 947830784, + 947847168, + 947863552, + 947879936, + 947896320, + 939524096, + 939532288, + 939540480, + 939548672, + 939556864, + 939565056, + 939573248, + 939581440, + 939589632, + 939597824, + 939606016, + 939614208, + 939622400, + 939630592, + 939638784, + 939646976, + 939655168, + 939663360, + 939671552, + 939679744, + 939687936, + 939696128, + 939704320, + 939712512, + 939720704, + 939728896, + 939737088, + 939745280, + 939753472, + 939761664, + 939769856, + 939778048, + 939786240, + 939794432, + 939802624, + 939810816, + 939819008, + 939827200, + 939835392, + 939843584, + 939851776, + 939859968, + 939868160, + 939876352, + 939884544, + 939892736, + 939900928, + 939909120, + 939917312, + 939925504, + 939933696, + 939941888, + 939950080, + 939958272, + 939966464, + 939974656, + 939982848, + 939991040, + 939999232, + 940007424, + 940015616, + 940023808, + 940032000, + 940040192, + 940048384, + 940056576, + 940064768, + 940072960, + 940081152, + 940089344, + 940097536, + 940105728, + 940113920, + 940122112, + 940130304, + 940138496, + 940146688, + 940154880, + 940163072, + 940171264, + 940179456, + 940187648, + 940195840, + 940204032, + 940212224, + 940220416, + 940228608, + 940236800, + 940244992, + 940253184, + 940261376, + 940269568, + 940277760, + 940285952, + 940294144, + 940302336, + 940310528, + 940318720, + 940326912, + 940335104, + 940343296, + 940351488, + 940359680, + 940367872, + 940376064, + 940384256, + 940392448, + 940400640, + 940408832, + 940417024, + 940425216, + 940433408, + 940441600, + 940449792, + 940457984, + 940466176, + 940474368, + 940482560, + 940490752, + 940498944, + 940507136, + 940515328, + 940523520, + 940531712, + 940539904, + 940548096, + 940556288, + 940564480, + 940572672, + 940580864, + 940589056, + 940597248, + 940605440, + 940613632, + 940621824, + 940630016, + 940638208, + 940646400, + 940654592, + 940662784, + 940670976, + 940679168, + 940687360, + 940695552, + 940703744, + 940711936, + 940720128, + 940728320, + 940736512, + 940744704, + 940752896, + 940761088, + 940769280, + 940777472, + 940785664, + 940793856, + 940802048, + 940810240, + 940818432, + 940826624, + 940834816, + 940843008, + 940851200, + 940859392, + 940867584, + 940875776, + 940883968, + 940892160, + 940900352, + 940908544, + 940916736, + 940924928, + 940933120, + 940941312, + 940949504, + 940957696, + 940965888, + 940974080, + 940982272, + 940990464, + 940998656, + 941006848, + 941015040, + 941023232, + 941031424, + 941039616, + 941047808, + 941056000, + 941064192, + 941072384, + 941080576, + 941088768, + 941096960, + 941105152, + 941113344, + 941121536, + 941129728, + 941137920, + 941146112, + 941154304, + 941162496, + 941170688, + 941178880, + 941187072, + 941195264, + 941203456, + 941211648, + 941219840, + 941228032, + 941236224, + 941244416, + 941252608, + 941260800, + 941268992, + 941277184, + 941285376, + 941293568, + 941301760, + 941309952, + 941318144, + 941326336, + 941334528, + 941342720, + 941350912, + 941359104, + 941367296, + 941375488, + 941383680, + 941391872, + 941400064, + 941408256, + 941416448, + 941424640, + 941432832, + 941441024, + 941449216, + 941457408, + 941465600, + 941473792, + 941481984, + 941490176, + 941498368, + 941506560, + 941514752, + 941522944, + 941531136, + 941539328, + 941547520, + 941555712, + 941563904, + 941572096, + 941580288, + 941588480, + 941596672, + 941604864, + 941613056, + 941621248, + 941629440, + 941637632, + 941645824, + 941654016, + 941662208, + 941670400, + 941678592, + 941686784, + 941694976, + 941703168, + 941711360, + 941719552, + 941727744, + 941735936, + 941744128, + 941752320, + 941760512, + 941768704, + 941776896, + 941785088, + 941793280, + 941801472, + 941809664, + 941817856, + 941826048, + 941834240, + 941842432, + 941850624, + 941858816, + 941867008, + 941875200, + 941883392, + 941891584, + 941899776, + 941907968, + 941916160, + 941924352, + 941932544, + 941940736, + 941948928, + 941957120, + 941965312, + 941973504, + 941981696, + 941989888, + 941998080, + 942006272, + 942014464, + 942022656, + 942030848, + 942039040, + 942047232, + 942055424, + 942063616, + 942071808, + 942080000, + 942088192, + 942096384, + 942104576, + 942112768, + 942120960, + 942129152, + 942137344, + 942145536, + 942153728, + 942161920, + 942170112, + 942178304, + 942186496, + 942194688, + 942202880, + 942211072, + 942219264, + 942227456, + 942235648, + 942243840, + 942252032, + 942260224, + 942268416, + 942276608, + 942284800, + 942292992, + 942301184, + 942309376, + 942317568, + 942325760, + 942333952, + 942342144, + 942350336, + 942358528, + 942366720, + 942374912, + 942383104, + 942391296, + 942399488, + 942407680, + 942415872, + 942424064, + 942432256, + 942440448, + 942448640, + 942456832, + 942465024, + 942473216, + 942481408, + 942489600, + 942497792, + 942505984, + 942514176, + 942522368, + 942530560, + 942538752, + 942546944, + 942555136, + 942563328, + 942571520, + 942579712, + 942587904, + 942596096, + 942604288, + 942612480, + 942620672, + 942628864, + 942637056, + 942645248, + 942653440, + 942661632, + 942669824, + 942678016, + 942686208, + 942694400, + 942702592, + 942710784, + 942718976, + 942727168, + 942735360, + 942743552, + 942751744, + 942759936, + 942768128, + 942776320, + 942784512, + 942792704, + 942800896, + 942809088, + 942817280, + 942825472, + 942833664, + 942841856, + 942850048, + 942858240, + 942866432, + 942874624, + 942882816, + 942891008, + 942899200, + 942907392, + 942915584, + 942923776, + 942931968, + 942940160, + 942948352, + 942956544, + 942964736, + 942972928, + 942981120, + 942989312, + 942997504, + 943005696, + 943013888, + 943022080, + 943030272, + 943038464, + 943046656, + 943054848, + 943063040, + 943071232, + 943079424, + 943087616, + 943095808, + 943104000, + 943112192, + 943120384, + 943128576, + 943136768, + 943144960, + 943153152, + 943161344, + 943169536, + 943177728, + 943185920, + 943194112, + 943202304, + 943210496, + 943218688, + 943226880, + 943235072, + 943243264, + 943251456, + 943259648, + 943267840, + 943276032, + 943284224, + 943292416, + 943300608, + 943308800, + 943316992, + 943325184, + 943333376, + 943341568, + 943349760, + 943357952, + 943366144, + 943374336, + 943382528, + 943390720, + 943398912, + 943407104, + 943415296, + 943423488, + 943431680, + 943439872, + 943448064, + 943456256, + 943464448, + 943472640, + 943480832, + 943489024, + 943497216, + 943505408, + 943513600, + 943521792, + 943529984, + 943538176, + 943546368, + 943554560, + 943562752, + 943570944, + 943579136, + 943587328, + 943595520, + 943603712, + 943611904, + 943620096, + 943628288, + 943636480, + 943644672, + 943652864, + 943661056, + 943669248, + 943677440, + 943685632, + 943693824, + 943702016, + 943710208, + 943718400, + 943726592, + 943734784, + 943742976, + 943751168, + 943759360, + 943767552, + 943775744, + 943783936, + 943792128, + 943800320, + 943808512, + 943816704, + 943824896, + 943833088, + 943841280, + 943849472, + 943857664, + 943865856, + 943874048, + 943882240, + 943890432, + 943898624, + 943906816, + 943915008, + 943923200, + 943931392, + 943939584, + 943947776, + 943955968, + 943964160, + 943972352, + 943980544, + 943988736, + 943996928, + 944005120, + 944013312, + 944021504, + 944029696, + 944037888, + 944046080, + 944054272, + 944062464, + 944070656, + 944078848, + 944087040, + 944095232, + 944103424, + 944111616, + 944119808, + 944128000, + 944136192, + 944144384, + 944152576, + 944160768, + 944168960, + 944177152, + 944185344, + 944193536, + 944201728, + 944209920, + 944218112, + 944226304, + 944234496, + 944242688, + 944250880, + 944259072, + 944267264, + 944275456, + 944283648, + 944291840, + 944300032, + 944308224, + 944316416, + 944324608, + 944332800, + 944340992, + 944349184, + 944357376, + 944365568, + 944373760, + 944381952, + 944390144, + 944398336, + 944406528, + 944414720, + 944422912, + 944431104, + 944439296, + 944447488, + 944455680, + 944463872, + 944472064, + 944480256, + 944488448, + 944496640, + 944504832, + 944513024, + 944521216, + 944529408, + 944537600, + 944545792, + 944553984, + 944562176, + 944570368, + 944578560, + 944586752, + 944594944, + 944603136, + 944611328, + 944619520, + 944627712, + 944635904, + 944644096, + 944652288, + 944660480, + 944668672, + 944676864, + 944685056, + 944693248, + 944701440, + 944709632, + 944717824, + 944726016, + 944734208, + 944742400, + 944750592, + 944758784, + 944766976, + 944775168, + 944783360, + 944791552, + 944799744, + 944807936, + 944816128, + 944824320, + 944832512, + 944840704, + 944848896, + 944857088, + 944865280, + 944873472, + 944881664, + 944889856, + 944898048, + 944906240, + 944914432, + 944922624, + 944930816, + 944939008, + 944947200, + 944955392, + 944963584, + 944971776, + 944979968, + 944988160, + 944996352, + 945004544, + 945012736, + 945020928, + 945029120, + 945037312, + 945045504, + 945053696, + 945061888, + 945070080, + 945078272, + 945086464, + 945094656, + 945102848, + 945111040, + 945119232, + 945127424, + 945135616, + 945143808, + 945152000, + 945160192, + 945168384, + 945176576, + 945184768, + 945192960, + 945201152, + 945209344, + 945217536, + 945225728, + 945233920, + 945242112, + 945250304, + 945258496, + 945266688, + 945274880, + 945283072, + 945291264, + 945299456, + 945307648, + 945315840, + 945324032, + 945332224, + 945340416, + 945348608, + 945356800, + 945364992, + 945373184, + 945381376, + 945389568, + 945397760, + 945405952, + 945414144, + 945422336, + 945430528, + 945438720, + 945446912, + 945455104, + 945463296, + 945471488, + 945479680, + 945487872, + 945496064, + 945504256, + 945512448, + 945520640, + 945528832, + 945537024, + 945545216, + 945553408, + 945561600, + 945569792, + 945577984, + 945586176, + 945594368, + 945602560, + 945610752, + 945618944, + 945627136, + 945635328, + 945643520, + 945651712, + 945659904, + 945668096, + 945676288, + 945684480, + 945692672, + 945700864, + 945709056, + 945717248, + 945725440, + 945733632, + 945741824, + 945750016, + 945758208, + 945766400, + 945774592, + 945782784, + 945790976, + 945799168, + 945807360, + 945815552, + 945823744, + 945831936, + 945840128, + 945848320, + 945856512, + 945864704, + 945872896, + 945881088, + 945889280, + 945897472, + 945905664, + 945913856, + 945922048, + 945930240, + 945938432, + 945946624, + 945954816, + 945963008, + 945971200, + 945979392, + 945987584, + 945995776, + 946003968, + 946012160, + 946020352, + 946028544, + 946036736, + 946044928, + 946053120, + 946061312, + 946069504, + 946077696, + 946085888, + 946094080, + 946102272, + 946110464, + 946118656, + 946126848, + 946135040, + 946143232, + 946151424, + 946159616, + 946167808, + 946176000, + 946184192, + 946192384, + 946200576, + 946208768, + 946216960, + 946225152, + 946233344, + 946241536, + 946249728, + 946257920, + 946266112, + 946274304, + 946282496, + 946290688, + 946298880, + 946307072, + 946315264, + 946323456, + 946331648, + 946339840, + 946348032, + 946356224, + 946364416, + 946372608, + 946380800, + 946388992, + 946397184, + 946405376, + 946413568, + 946421760, + 946429952, + 946438144, + 946446336, + 946454528, + 946462720, + 946470912, + 946479104, + 946487296, + 946495488, + 946503680, + 946511872, + 946520064, + 946528256, + 946536448, + 946544640, + 946552832, + 946561024, + 946569216, + 946577408, + 946585600, + 946593792, + 946601984, + 946610176, + 946618368, + 946626560, + 946634752, + 946642944, + 946651136, + 946659328, + 946667520, + 946675712, + 946683904, + 946692096, + 946700288, + 946708480, + 946716672, + 946724864, + 946733056, + 946741248, + 946749440, + 946757632, + 946765824, + 946774016, + 946782208, + 946790400, + 946798592, + 946806784, + 946814976, + 946823168, + 946831360, + 946839552, + 946847744, + 946855936, + 946864128, + 946872320, + 946880512, + 946888704, + 946896896, + 946905088, + 946913280, + 946921472, + 946929664, + 946937856, + 946946048, + 946954240, + 946962432, + 946970624, + 946978816, + 946987008, + 946995200, + 947003392, + 947011584, + 947019776, + 947027968, + 947036160, + 947044352, + 947052544, + 947060736, + 947068928, + 947077120, + 947085312, + 947093504, + 947101696, + 947109888, + 947118080, + 947126272, + 947134464, + 947142656, + 947150848, + 947159040, + 947167232, + 947175424, + 947183616, + 947191808, + 947200000, + 947208192, + 947216384, + 947224576, + 947232768, + 947240960, + 947249152, + 947257344, + 947265536, + 947273728, + 947281920, + 947290112, + 947298304, + 947306496, + 947314688, + 947322880, + 947331072, + 947339264, + 947347456, + 947355648, + 947363840, + 947372032, + 947380224, + 947388416, + 947396608, + 947404800, + 947412992, + 947421184, + 947429376, + 947437568, + 947445760, + 947453952, + 947462144, + 947470336, + 947478528, + 947486720, + 947494912, + 947503104, + 947511296, + 947519488, + 947527680, + 947535872, + 947544064, + 947552256, + 947560448, + 947568640, + 947576832, + 947585024, + 947593216, + 947601408, + 947609600, + 947617792, + 947625984, + 947634176, + 947642368, + 947650560, + 947658752, + 947666944, + 947675136, + 947683328, + 947691520, + 947699712, + 947707904, + 947716096, + 947724288, + 947732480, + 947740672, + 947748864, + 947757056, + 947765248, + 947773440, + 947781632, + 947789824, + 947798016, + 947806208, + 947814400, + 947822592, + 947830784, + 947838976, + 947847168, + 947855360, + 947863552, + 947871744, + 947879936, + 947888128, + 947896320, + 947904512, + }; + + unsigned int exponent_table[64] = + { + 0, + 8388608, + 16777216, + 25165824, + 33554432, + 41943040, + 50331648, + 58720256, + 67108864, + 75497472, + 83886080, + 92274688, + 100663296, + 109051904, + 117440512, + 125829120, + 134217728, + 142606336, + 150994944, + 159383552, + 167772160, + 176160768, + 184549376, + 192937984, + 201326592, + 209715200, + 218103808, + 226492416, + 234881024, + 243269632, + 251658240, + 1199570944, + 2147483648, + 2155872256, + 2164260864, + 2172649472, + 2181038080, + 2189426688, + 2197815296, + 2206203904, + 2214592512, + 2222981120, + 2231369728, + 2239758336, + 2248146944, + 2256535552, + 2264924160, + 2273312768, + 2281701376, + 2290089984, + 2298478592, + 2306867200, + 2315255808, + 2323644416, + 2332033024, + 2340421632, + 2348810240, + 2357198848, + 2365587456, + 2373976064, + 2382364672, + 2390753280, + 2399141888, + 3347054592, + }; + + unsigned short offset_table[64] = + { + 0, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }; + + unsigned short base_table[512] = + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 512, + 1024, + 2048, + 3072, + 4096, + 5120, + 6144, + 7168, + 8192, + 9216, + 10240, + 11264, + 12288, + 13312, + 14336, + 15360, + 16384, + 17408, + 18432, + 19456, + 20480, + 21504, + 22528, + 23552, + 24576, + 25600, + 26624, + 27648, + 28672, + 29696, + 30720, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32769, + 32770, + 32772, + 32776, + 32784, + 32800, + 32832, + 32896, + 33024, + 33280, + 33792, + 34816, + 35840, + 36864, + 37888, + 38912, + 39936, + 40960, + 41984, + 43008, + 44032, + 45056, + 46080, + 47104, + 48128, + 49152, + 50176, + 51200, + 52224, + 53248, + 54272, + 55296, + 56320, + 57344, + 58368, + 59392, + 60416, + 61440, + 62464, + 63488, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + }; + + unsigned char shift_table[512] = + { + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 23, + 22, + 21, + 20, + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 13, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 23, + 22, + 21, + 20, + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 13, + }; + + /* + + void generate_tables() + { + unsigned int mantissa_table[2048]; + unsigned int exponent_table[64]; + unsigned short offset_table[64]; + unsigned short base_table[512]; + unsigned char shift_table[512]; + + mantissa_table[0] = 0; + for (int i = 1; i < 1024; i++) + { + unsigned int m=i<<13; // Zero pad mantissa bits + unsigned int e=0; // Zero exponent + while(!(m&0x00800000)) // While not normalized + { + e-=0x00800000; // Decrement exponent (1<<23) + m<<=1; // Shift mantissa + } + m&=~0x00800000; // Clear leading 1 bit + e+=0x38800000; // Adjust bias ((127-14)<<23) + mantissa_table[i] = m | e; + } + for (int i = 1024; i < 2048; i++) + { + mantissa_table[i] = 0x38000000 + ((i - 1024) << 13); + } + + exponent_table[0] = 0; + exponent_table[32] = 0x80000000; + + for (int i = 1; i < 31; i++) + exponent_table[i] = i<<23; + for (int i = 33; i < 63; i++) + exponent_table[i] = 0x80000000 + ((i-32)<<23); + + exponent_table[31] = 0x47800000; + exponent_table[63] = 0xC7800000; + + offset_table[0] = 0; + offset_table[32] = 0; + for (int i = 1; i < 32; i++) + offset_table[i] = 1024; + + for(unsigned int i=0; i<256; ++i) + { + int e=i-127; + if (e<-24) // Very small numbers map to zero + { + base_table[i|0x000]=0x0000; + base_table[i|0x100]=0x8000; + shift_table[i|0x000]=24; + shift_table[i|0x100]=24; + } + else if (e<-14) // Small numbers map to denorms + { + base_table[i|0x000]=(0x0400>>(-e-14)); + base_table[i|0x100]=(0x0400>>(-e-14)) | 0x8000; + shift_table[i|0x000]=-e-1; + shift_table[i|0x100]=-e-1; + } + else if (e<=15) // Normal numbers just lose precision + { + base_table[i|0x000]=((e+15)<<10); + base_table[i|0x100]=((e+15)<<10) | 0x8000; + shift_table[i|0x000]=13; + shift_table[i|0x100]=13; + } + else if (e<128) // Large numbers map to Infinity + { + base_table[i|0x000]=0x7C00; + base_table[i|0x100]=0xFC00; + shift_table[i|0x000]=24; + shift_table[i|0x100]=24; + } + else // Infinity and NaN's stay Infinity and NaN's + { + base_table[i|0x000]=0x7C00; + base_table[i|0x100]=0xFC00; + shift_table[i|0x000]=13; + shift_table[i|0x100]=13; + } + } + + File file("tables.txt", File::create_always, File::access_read_write); + file.write_string_text("unsigned int mantissa_table[2048] ="); + file.write_string_text("{"); + for (int i = 0; i < 2048; i++) + { + file.write_string_text("\t" + Text::to_string(mantissa_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + + file.write_string_text("unsigned int exponent_table[64] ="); + file.write_string_text("{"); + for (int i = 0; i < 64; i++) + { + file.write_string_text("\t" + Text::to_string(exponent_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + + file.write_string_text("unsigned short offset_table[64] ="); + file.write_string_text("{"); + for (int i = 0; i < 64; i++) + { + file.write_string_text("\t" + Text::to_string(offset_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + + file.write_string_text("unsigned short base_table[512] ="); + file.write_string_text("{"); + for (int i = 0; i < 512; i++) + { + file.write_string_text("\t" + Text::to_string(base_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + + file.write_string_text("unsigned char shift_table[512] ="); + file.write_string_text("{"); + for (int i = 0; i < 512; i++) + { + file.write_string_text("\t" + Text::to_string(shift_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + } + */ +} diff --git a/src/common/utility/halffloat.h b/src/common/utility/halffloat.h new file mode 100644 index 0000000000..0ec2c4bbdb --- /dev/null +++ b/src/common/utility/halffloat.h @@ -0,0 +1,65 @@ +/* +** Based on the paper "Fast Half Float Conversions" by Jeroen van der Zijp. +** +** 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. +** +*/ + +#pragma once + +namespace HalfFloatTables +{ + extern unsigned int mantissa_table[2048]; + extern unsigned int exponent_table[64]; + extern unsigned short offset_table[64]; + extern unsigned short base_table[512]; + extern unsigned char shift_table[512]; +}; + +/// Convert half-float to float. Only works for 'normal' half-float values +inline float halfToFloatSimple(unsigned short hf) +{ + unsigned int float_value = ((hf & 0x8000) << 16) | (((hf & 0x7c00) + 0x1C000) << 13) | ((hf & 0x03FF) << 13); + void *ptr = static_cast(&float_value); + return *static_cast(ptr); +} + +/// Convert float to half-float. Only works for 'normal' half-float values +inline unsigned short floatToHalfSimple(float float_value) +{ + void *ptr = static_cast(&float_value); + unsigned int f = *static_cast(ptr); + return ((f >> 16) & 0x8000) | ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | ((f >> 13) & 0x03ff); +} + +/// Convert half-float to float +inline float halfToFloat(unsigned short hf) +{ + using namespace HalfFloatTables; + unsigned int float_value = mantissa_table[offset_table[hf >> 10] + (hf & 0x3ff)] + exponent_table[hf >> 10]; + void *ptr = static_cast(&float_value); + return *static_cast(ptr); +} + +/// Convert float to half-float +inline unsigned short floatToHalf(float float_value) +{ + using namespace HalfFloatTables; + void *ptr = static_cast(&float_value); + unsigned int f = *static_cast(ptr); + return base_table[(f >> 23) & 0x1ff] + ((f & 0x007fffff) >> shift_table[(f >> 23) & 0x1ff]); +} diff --git a/src/common/utility/m_alloc.cpp b/src/common/utility/m_alloc.cpp index 3b7e12f434..5884b48e81 100644 --- a/src/common/utility/m_alloc.cpp +++ b/src/common/utility/m_alloc.cpp @@ -77,6 +77,7 @@ void *M_Realloc(void *memblock, size_t size) GC::ReportRealloc(oldsize, _msize(block)); return block; } + #else void *M_Malloc(size_t size) { @@ -113,6 +114,14 @@ void *M_Realloc(void *memblock, size_t size) return block; } #endif + +void* M_Calloc(size_t v1, size_t v2) +{ + auto p = M_Malloc(v1 * v2); + memset(p, 0, v1 * v2); + return p; +} + #else #ifdef _MSC_VER #include diff --git a/src/common/utility/m_alloc.h b/src/common/utility/m_alloc.h index 471d42fae9..5f80584d6d 100644 --- a/src/common/utility/m_alloc.h +++ b/src/common/utility/m_alloc.h @@ -72,12 +72,7 @@ inline void* M_Calloc_Dbg(size_t v1, size_t v2, const char* file, int lineno) #else void *M_Malloc (size_t size); void *M_Realloc (void *memblock, size_t size); -inline void* M_Calloc(size_t v1, size_t v2) -{ - auto p = M_Malloc(v1 * v2); - memset(p, 0, v1 * v2); - return p; -} +void* M_Calloc(size_t v1, size_t v2); #endif diff --git a/src/common/utility/m_argv.cpp b/src/common/utility/m_argv.cpp index d6f834d88c..b9b05c3e9b 100644 --- a/src/common/utility/m_argv.cpp +++ b/src/common/utility/m_argv.cpp @@ -158,7 +158,7 @@ int FArgs::CheckParm(const char** check, int start) const { for (unsigned i = start; i < Argv.Size(); ++i) { - if (0 == stricmp(check, Argv[i])) + if (0 == stricmp(check, Argv[i].GetChars())) { return i; } diff --git a/src/common/utility/matrix.h b/src/common/utility/matrix.h index 0ed4f7bfd8..bafef419ba 100644 --- a/src/common/utility/matrix.h +++ b/src/common/utility/matrix.h @@ -29,6 +29,10 @@ typedef double FLOATTYPE; typedef float FLOATTYPE; #endif +#ifndef NO_SSE +#include +#endif + class VSMatrix { public: @@ -102,6 +106,32 @@ class VSMatrix { bool inverseMatrix(VSMatrix &result); void transpose(); + FVector4 operator *(const FVector4& v) const + { + #ifdef NO_SSE + FVector4 result; + result.X = mMatrix[0 * 4 + 0] * v.X + mMatrix[1 * 4 + 0] * v.Y + mMatrix[2 * 4 + 0] * v.Z + mMatrix[3 * 4 + 0] * v.W; + result.Y = mMatrix[0 * 4 + 1] * v.X + mMatrix[1 * 4 + 1] * v.Y + mMatrix[2 * 4 + 1] * v.Z + mMatrix[3 * 4 + 1] * v.W; + result.Z = mMatrix[0 * 4 + 2] * v.X + mMatrix[1 * 4 + 2] * v.Y + mMatrix[2 * 4 + 2] * v.Z + mMatrix[3 * 4 + 2] * v.W; + result.W = mMatrix[0 * 4 + 3] * v.X + mMatrix[1 * 4 + 3] * v.Y + mMatrix[2 * 4 + 3] * v.Z + mMatrix[3 * 4 + 3] * v.W; + return result; + #else + __m128 m0 = _mm_loadu_ps(mMatrix); + __m128 m1 = _mm_loadu_ps(mMatrix + 4); + __m128 m2 = _mm_loadu_ps(mMatrix + 8); + __m128 m3 = _mm_loadu_ps(mMatrix + 12); + __m128 mv = _mm_loadu_ps(&v.X); + m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0))); + m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1))); + m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2))); + m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3))); + mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3); + FVector4 result; + _mm_storeu_ps(&result.X, mv); + return result; + #endif + } + protected: static void crossProduct(const FLOATTYPE *a, const FLOATTYPE *b, FLOATTYPE *res); static FLOATTYPE dotProduct(const FLOATTYPE *a, const FLOATTYPE * b); @@ -184,7 +214,7 @@ class Matrix3x4 // used like a 4x4 matrix with the last row always being (0,0,0, *this = (*this) * m1; } - Matrix3x4 operator *(const Matrix3x4 &other) + Matrix3x4 operator *(const Matrix3x4 &other) const { Matrix3x4 result; @@ -206,7 +236,7 @@ class Matrix3x4 // used like a 4x4 matrix with the last row always being (0,0,0, return result; } - FVector3 operator *(const FVector3 &vec) + FVector3 operator *(const FVector3 &vec) const { FVector3 result; diff --git a/src/common/utility/memarena.cpp b/src/common/utility/memarena.cpp index 2a9467dc21..83621df47a 100644 --- a/src/common/utility/memarena.cpp +++ b/src/common/utility/memarena.cpp @@ -132,6 +132,13 @@ void* FMemArena::Calloc(size_t size) return mem; } +const char* FMemArena::Strdup(const char* str) +{ + char* p = (char*)Alloc(strlen(str) + 1); + strcpy(p, str); + return p; +} + //========================================================================== // // FMemArena :: FreeAll @@ -335,7 +342,7 @@ FString *FSharedStringArena::Alloc(const FString &source) unsigned int hash; Node *strnode; - strnode = FindString(source, source.Len(), hash); + strnode = FindString(source.GetChars(), source.Len(), hash); if (strnode == NULL) { strnode = (Node *)iAlloc(sizeof(Node)); diff --git a/src/common/utility/memarena.h b/src/common/utility/memarena.h index bb7f60b9a5..8c1def64dc 100644 --- a/src/common/utility/memarena.h +++ b/src/common/utility/memarena.h @@ -45,6 +45,7 @@ class FMemArena void *Alloc(size_t size); void* Calloc(size_t size); + const char* Strdup(const char*); void FreeAll(); void FreeAllBlocks(); FString DumpInfo(); diff --git a/src/common/utility/palette.cpp b/src/common/utility/palette.cpp index e7bc61f098..03517c1ba5 100644 --- a/src/common/utility/palette.cpp +++ b/src/common/utility/palette.cpp @@ -33,12 +33,16 @@ */ #include +#include +#include #include "palutil.h" #include "palentry.h" #include "sc_man.h" #include "files.h" #include "filesystem.h" #include "printf.h" +#include "m_swap.h" +#include "cmdlib.h" #include "m_png.h" @@ -662,9 +666,8 @@ int V_GetColorFromString(const char* cstr, FScriptPosition* sc) FString V_GetColorStringByName(const char* name, FScriptPosition* sc) { - FileData rgbNames; - char* rgbEnd; - char* rgb, * endp; + const char* rgbEnd; + const char* rgb, * endp; int rgblump; int c[3], step; size_t namelen; @@ -679,9 +682,9 @@ FString V_GetColorStringByName(const char* name, FScriptPosition* sc) return FString(); } - rgbNames = fileSystem.ReadFile(rgblump); - rgb = (char*)rgbNames.GetMem(); - rgbEnd = rgb + fileSystem.FileLength(rgblump); + auto rgbNames = fileSystem.ReadFile(rgblump); + rgb = rgbNames.string(); + rgbEnd = rgb + rgbNames.size(); step = 0; namelen = strlen(name); @@ -704,7 +707,7 @@ FString V_GetColorStringByName(const char* name, FScriptPosition* sc) } else if (step < 3) { // collect RGB values - c[step++] = strtoul(rgb, &endp, 10); + c[step++] = strtoul(rgb, (char**)&endp, 10); if (endp == rgb) { break; @@ -758,7 +761,7 @@ int V_GetColor(const char* str, FScriptPosition* sc) if (!string.IsEmpty()) { - res = V_GetColorFromString(string, sc); + res = V_GetColorFromString(string.GetChars(), sc); } else { @@ -928,12 +931,12 @@ int ReadPalette(int lumpnum, uint8_t* buffer) { return 0; } - FileData lump = fileSystem.ReadFile(lumpnum); - uint8_t* lumpmem = (uint8_t*)lump.GetMem(); + auto lump = fileSystem.ReadFile(lumpnum); + auto lumpmem = lump.bytes(); memset(buffer, 0, 768); FileReader fr; - fr.OpenMemory(lumpmem, lump.GetSize()); + fr.OpenMemory(lumpmem, lump.size()); auto png = M_VerifyPNG(fr); if (png) { @@ -963,7 +966,7 @@ int ReadPalette(int lumpnum, uint8_t* buffer) { FScanner sc; - sc.OpenMem(fileSystem.GetFileFullName(lumpnum), (char*)lumpmem, int(lump.GetSize())); + sc.OpenMem(fileSystem.GetFileFullName(lumpnum), (char*)lumpmem, int(lump.size())); sc.MustGetString(); sc.MustGetNumber(); // version - ignore sc.MustGetNumber(); @@ -981,7 +984,7 @@ int ReadPalette(int lumpnum, uint8_t* buffer) } else { - memcpy(buffer, lumpmem, min(768, lump.GetSize())); + memcpy(buffer, lumpmem, min(768, lump.size())); return 256; } } diff --git a/src/common/utility/s_playlist.cpp b/src/common/utility/s_playlist.cpp index d457d01376..694329b58b 100644 --- a/src/common/utility/s_playlist.cpp +++ b/src/common/utility/s_playlist.cpp @@ -80,7 +80,7 @@ bool FPlayList::ChangeList (const char *path) // For a .PLS file, skip anything that doesn't start with File[0-9]+= if (pls) { - if (strncmp(song, "File", 4) != 0) + if (strncmp(song.GetChars(), "File", 4) != 0) { continue; } @@ -205,5 +205,5 @@ const char *FPlayList::GetSong (int position) const if ((unsigned)position >= Songs.Size()) return NULL; - return Songs[position]; + return Songs[position].GetChars(); } diff --git a/src/common/utility/s_playlist.h b/src/common/utility/s_playlist.h index 5bd5fd55ef..84d2040b03 100644 --- a/src/common/utility/s_playlist.h +++ b/src/common/utility/s_playlist.h @@ -34,7 +34,7 @@ #ifndef __S_PLAYLIST_H__ #define __S_PLAYLIST_H__ -class FileReader; +#include "files.h" class FPlayList { diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h index 29d62289ce..bce3ba3ea1 100644 --- a/src/common/utility/tarray.h +++ b/src/common/utility/tarray.h @@ -54,6 +54,8 @@ #include #include #include +#include +#include #if !defined(_WIN32) #include // for intptr_t @@ -233,7 +235,7 @@ class TArray { DoCopy (other); } - TArray (TArray &&other) + TArray (TArray &&other) noexcept { Array = other.Array; other.Array = NULL; Most = other.Most; other.Most = 0; @@ -255,7 +257,7 @@ class TArray } return *this; } - TArray &operator= (TArray &&other) + TArray &operator= (TArray &&other) noexcept { if (Array) { @@ -327,9 +329,10 @@ class TArray } // returns address of first element - T *Data() const + T *Data(size_t index = 0) const { - return &Array[0]; + assert(index <= Count); + return &Array[index]; } unsigned IndexOf(const T& elem) const @@ -353,6 +356,105 @@ class TArray return i; } + // !!! THIS REQUIRES AN ELEMENT TYPE THAT'S COMPARABLE WITH THE LT OPERATOR !!! + bool IsSorted() + { + for(unsigned i = 1; i < Count; i++) + { + if(Array[i] < Array[i-1]) return false; + } + return true; + } + + template + bool IsSorted(Func &<) + { + for(unsigned i = 1; i < Count; i++) + { + if(std::invoke(lt, Array[i], Array[i-1])) return false; + } + return true; + } + + // !!! THIS REQUIRES A SORTED OR EMPTY ARRAY !!! + // !!! AND AN ELEMENT TYPE THAT'S COMPARABLE WITH THE LT OPERATOR !!! + // + // exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does + unsigned int SortedFind(const T& item, bool exact = true) const + { + if(Count == 0) return 0; + if(Count == 1) return (item < Array[0]) ? 0 : 1; + + unsigned int lo = 0; + unsigned int hi = Count - 1; + + while(lo <= hi) + { + int mid = lo + ((hi - lo) / 2); + + if(Array[mid] < item) + { + lo = mid + 1; + } + else if(item < Array[mid]) + { + hi = mid - 1; + } + else + { + return mid; + } + } + if(exact) + { + return Count; + } + else + { + return (lo == Count || (item < Array[lo])) ? lo : lo + 1; + } + } + + // !!! THIS REQUIRES A SORTED OR EMPTY ARRAY !!! + // + // exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does + template + unsigned int SortedFind(const T& item, Func &<, bool exact = true) const + { + if(Count == 0) return 0; + if(Count == 1) return lt(item, Array[0]) ? 0 : 1; + + unsigned int lo = 0; + unsigned int hi = Count - 1; + + while(lo <= hi) + { + int mid = lo + ((hi - lo) / 2); + + if(std::invoke(lt, Array[mid], item)) + { + lo = mid + 1; + } + else if(std::invoke(lt, item, Array[mid])) + { + if(mid == 0) break; // prevent negative overflow due to unsigned numbers + hi = mid - 1; + } + else + { + return mid; + } + } + if(exact) + { + return Count; + } + else + { + return (lo == Count || std::invoke(lt, item, Array[lo])) ? lo : lo + 1; + } + } + bool Contains(const T& item) const { unsigned int i; @@ -365,12 +467,24 @@ class TArray } template - unsigned int FindEx(Func compare) const + bool Contains(const T& item, Func &&compare) const + { + unsigned int i; + for(i = 0;i < Count;++i) + { + if(std::invoke(compare, Array[i], item)) + return true; + } + return false; + } + + template + unsigned int FindEx(Func &&compare) const { unsigned int i; for (i = 0; i < Count; ++i) { - if (compare(Array[i])) + if (std::invoke(compare, Array[i])) break; } return i; @@ -397,9 +511,16 @@ class TArray Grow(item.Size()); Count += item.Size(); - for (unsigned i = 0; i < item.Size(); i++) + if constexpr (std::is_trivially_copyable::value) { - new(&Array[start + i]) T(item[i]); + memcpy(Array + start,item.Array,item.Size() * sizeof(T)); + } + else + { + for (unsigned i = 0; i < item.Size(); i++) + { + new(&Array[start + i]) T(item[i]); + } } return start; } @@ -411,14 +532,92 @@ class TArray Grow(item.Size()); Count += item.Size(); - for (unsigned i = 0; i < item.Size(); i++) + if constexpr (std::is_trivially_copyable::value) { - new(&Array[start + i]) T(std::move(item[i])); + memcpy(Array + start,item.Array,item.Size() * sizeof(T)); + } + else + { + for (unsigned i = 0; i < item.Size(); i++) + { + new(&Array[start + i]) T(std::move(item[i])); + } } item.Clear(); return start; } + unsigned AppendFill(const T& val, unsigned append_count) + { + unsigned start = Count; + + Grow(append_count); + Count += append_count; + if constexpr (std::is_trivially_copyable::value) + { + std::fill(Array + start, Array + Count, val); + } + else + { + for (unsigned i = 0; i < append_count; i++) + { + new(&Array[start + i]) T(val); + } + } + return start; + } + + unsigned AddUnique(const T& obj) + { + auto f = Find(obj); + if (f == Size()) Push(obj); + return f; + } + + unsigned SortedAddUnique(const T& obj) + { + auto f = SortedFind(obj, true); + if (f == Size()) Push(obj); + return f; + } + + template + unsigned SortedAddUnique(const T& obj, Func &<) + { + auto f = SortedFind(obj, std::forward(lt), true); + if (f == Size()) Push(obj); + return f; + } + + bool SortedDelete(const T& obj) + { + auto f = SortedFind(obj, true); + if (f == Size()) + { + Delete(f); + return true; + } + else + { + return false; + } + } + + template + bool SortedDelete(const T& obj, Func &<) + { + auto f = SortedFind(obj, std::forward(lt), true); + if (f == Size()) + { + Delete(f); + return true; + } + else + { + return false; + } + } + bool Pop () { if (Count > 0) @@ -499,6 +698,17 @@ class TArray } } + void SortedInsert (const T &item) + { + Insert (SortedFind (item, false), item); + } + + template + void SortedInsert (const T &item, Func &<) + { + Insert (SortedFind (item, std::forward(lt), false), item); + } + void ShrinkToFit () { if (Most > Count) @@ -614,6 +824,44 @@ class TArray std::swap(Most, other.Most); } + // aliases with STL compliant names to allow using TArrays with templates designed for STL containers + + size_t size() const + { + return Count; + } + + T* data() const + { + return Data(); + } + + T& front() const + { + return *Data(); + } + + T& back() const + { + return Last(); + } + + void resize(size_t i) + { + Resize(i); + } + + void push_back(const T& elem) + { + Push(elem); + } + + void clear() + { + Clear(); + } + + private: T *Array; unsigned int Count; @@ -1696,14 +1944,14 @@ class BitArray return *this; } - BitArray(BitArray && arr) + BitArray(BitArray && arr) noexcept : bytes(std::move(arr.bytes)) { size = arr.size; arr.size = 0; } - BitArray &operator=(BitArray && arr) + BitArray &operator=(BitArray && arr) noexcept { bytes = std::move(arr.bytes); size = arr.size; diff --git a/src/common/utility/utf8.cpp b/src/common/utility/utf8.cpp index 100c06a136..5ac7fc9f15 100644 --- a/src/common/utility/utf8.cpp +++ b/src/common/utility/utf8.cpp @@ -413,7 +413,7 @@ int getAlternative(int code) case 0x41e: return 'O'; case 0x420: return 'P'; case 0x421: return 'C'; - case 0x423: return 'T'; + case 0x422: return 'T'; case 0x425: return 'X'; case 0x430: return 'a'; case 0x435: return 'e'; @@ -823,44 +823,52 @@ static const uint16_t loweruppercase[] = { 0x0584,0x0554, 0x0585,0x0555, 0x0586,0x0556, -0x10D0,0x10A0, -0x10D1,0x10A1, -0x10D2,0x10A2, -0x10D3,0x10A3, -0x10D4,0x10A4, -0x10D5,0x10A5, -0x10D6,0x10A6, -0x10D7,0x10A7, -0x10D8,0x10A8, -0x10D9,0x10A9, -0x10DA,0x10AA, -0x10DB,0x10AB, -0x10DC,0x10AC, -0x10DD,0x10AD, -0x10DE,0x10AE, -0x10DF,0x10AF, -0x10E0,0x10B0, -0x10E1,0x10B1, -0x10E2,0x10B2, -0x10E3,0x10B3, -0x10E4,0x10B4, -0x10E5,0x10B5, -0x10E6,0x10B6, -0x10E7,0x10B7, -0x10E8,0x10B8, -0x10E9,0x10B9, -0x10EA,0x10BA, -0x10EB,0x10BB, -0x10EC,0x10BC, -0x10ED,0x10BD, -0x10EE,0x10BE, -0x10EF,0x10BF, -0x10F0,0x10C0, -0x10F1,0x10C1, -0x10F2,0x10C2, -0x10F3,0x10C3, -0x10F4,0x10C4, -0x10F5,0x10C5, +0x10D0,0x1C90, +0x10D1,0x1C91, +0x10D2,0x1C92, +0x10D3,0x1C93, +0x10D4,0x1C94, +0x10D5,0x1C95, +0x10D6,0x1C96, +0x10D7,0x1C97, +0x10D8,0x1C98, +0x10D9,0x1C99, +0x10DA,0x1C9A, +0x10DB,0x1C9B, +0x10DC,0x1C9C, +0x10DD,0x1C9D, +0x10DE,0x1C9E, +0x10DF,0x1C9F, +0x10E0,0x1CA0, +0x10E1,0x1CA1, +0x10E2,0x1CA2, +0x10E3,0x1CA3, +0x10E4,0x1CA4, +0x10E5,0x1CA5, +0x10E6,0x1CA6, +0x10E7,0x1CA7, +0x10E8,0x1CA8, +0x10E9,0x1CA9, +0x10EA,0x1CAA, +0x10EB,0x1CAB, +0x10EC,0x1CAC, +0x10ED,0x1CAD, +0x10EE,0x1CAE, +0x10EF,0x1CAF, +0x10F0,0x1CB0, +0x10F1,0x1CB1, +0x10F2,0x1CB2, +0x10F3,0x1CB3, +0x10F4,0x1CB4, +0x10F5,0x1CB5, +0x10F6,0x1CB6, +0x10F7,0x1CB7, +0x10F8,0x1CB8, +0x10F9,0x1CB9, +0x10FA,0x1CBA, +0x10FD,0x1CBD, +0x10FE,0x1CBE, +0x10FF,0x1CBF, 0x1E01,0x1E00, 0x1E03,0x1E02, 0x1E05,0x1E04, @@ -1085,6 +1093,46 @@ static const uint16_t loweruppercase[] = { 0x24E7, 0x24CD, 0x24E8, 0x24CE, 0x24E9, 0x24CF, +0x2D00, 0x10A0, +0x2D01, 0x10A1, +0x2D02, 0x10A2, +0x2D03, 0x10A3, +0x2D04, 0x10A4, +0x2D05, 0x10A5, +0x2D06, 0x10A6, +0x2D07, 0x10A7, +0x2D08, 0x10A8, +0x2D09, 0x10A9, +0x2D0A, 0x10AA, +0x2D0B, 0x10AB, +0x2D0C, 0x10AC, +0x2D0D, 0x10AD, +0x2D0E, 0x10AE, +0x2D0F, 0x10AF, +0x2D10, 0x10B0, +0x2D11, 0x10B1, +0x2D12, 0x10B2, +0x2D13, 0x10B3, +0x2D14, 0x10B4, +0x2D15, 0x10B5, +0x2D16, 0x10B6, +0x2D17, 0x10B7, +0x2D18, 0x10B8, +0x2D19, 0x10B9, +0x2D1A, 0x10BA, +0x2D1B, 0x10BB, +0x2D1C, 0x10BC, +0x2D1D, 0x10BD, +0x2D1E, 0x10BE, +0x2D1F, 0x10BF, +0x2D20, 0x10C0, +0x2D21, 0x10C1, +0x2D22, 0x10C2, +0x2D23, 0x10C3, +0x2D24, 0x10C4, +0x2D25, 0x10C5, +0x2D27, 0x10C7, +0x2D2D, 0x10CD, 0xFF41, 0xFF21, 0xFF42, 0xFF22, 0xFF43, 0xFF23, @@ -1157,3 +1205,17 @@ bool myisupper(int code) return false; } +std::wstring WideString(const char* cin) +{ + std::wstring buildbuffer; + if (cin) + { + // This is a bit tricky because we need to support both UTF-8 and legacy content in ISO-8859-1 / Windows 1252 + // and thanks to user-side string manipulation it can be that a text mixes both. + // To convert the string this uses the same function as all text printing in the engine. + const uint8_t* in = (const uint8_t*)cin; + while (*in) buildbuffer.push_back((wchar_t)GetCharFromString(in)); + } + return buildbuffer; +} + diff --git a/src/common/utility/utf8.h b/src/common/utility/utf8.h index 7ca8a5f324..0b5e4ae0ac 100644 --- a/src/common/utility/utf8.h +++ b/src/common/utility/utf8.h @@ -1,5 +1,7 @@ #pragma once +#include + int utf8_encode(int32_t codepoint, uint8_t *buffer, int *size); int utf8_decode(const uint8_t *src, int *size); int GetCharFromString(const uint8_t *&string); @@ -18,3 +20,8 @@ int getAlternative(int code); extern uint16_t win1252map[]; extern uint16_t lowerforupper[65536]; extern uint16_t upperforlower[65536]; + +// make this only visible on Windows, on other platforms this should not be called. +#ifdef _WIN32 +std::wstring WideString(const char*); +#endif diff --git a/src/common/utility/vectors.h b/src/common/utility/vectors.h index 140c310f08..77e41d2a9e 100644 --- a/src/common/utility/vectors.h +++ b/src/common/utility/vectors.h @@ -44,23 +44,33 @@ #include #include #include -#include "xs_Float.h" -#include "math/cmath.h" -#include "basics.h" -#include "cmdlib.h" +#include - -#define EQUAL_EPSILON (1/65536.) +// this is needed to properly normalize angles. We cannot do that with compiler provided conversions because they differ too much +#include "xs_Float.h" // make this a local inline function to avoid any dependencies on other headers and not pollute the global namespace namespace pi { inline constexpr double pi() { return 3.14159265358979323846; } - inline constexpr double pif() { return 3.14159265358979323846f; } + inline constexpr float pif() { return 3.14159265358979323846f; } } +// optionally use reliable math routines if reproducability across hardware is important, but let this still compile without them. +#if __has_include("math/cmath.h") +#include "math/cmath.h" +#else +inline double g_cosdeg(double v) { return cos(v * (pi::pi() / 180.)); } +inline double g_sindeg(double v) { return sin(v * (pi::pi() / 180.)); } +inline double g_cos(double v) { return cos(v); } +inline double g_sin(double v) { return sin(v); } +inline double g_sqrt(double v) { return sqrt(v); } +inline double g_atan2(double v, double w) { return atan2(v, w); } +#endif +#define EQUAL_EPSILON (1/65536.) + template struct TVector3; template struct TRotator; template struct TAngle; @@ -70,56 +80,56 @@ struct TVector2 { vec_t X, Y; - TVector2() = default; + constexpr TVector2() = default; - TVector2 (vec_t a, vec_t b) + constexpr TVector2 (vec_t a, vec_t b) : X(a), Y(b) { } - TVector2(const TVector2 &other) = default; + constexpr TVector2(const TVector2 &other) = default; - TVector2 (const TVector3 &other) // Copy the X and Y from the 3D vector and discard the Z - : X(other.X), Y(other.Y) + constexpr TVector2(vec_t *o) + : X(o[0]), Y(o[1]) { } - TVector2(vec_t *o) - : X(o[0]), Y(o[1]) - { + template + constexpr explicit operator TVector2 () const noexcept { + return TVector2(static_cast(X), static_cast(Y)); } - void Zero() + constexpr void Zero() { Y = X = 0; } - bool isZero() const + constexpr bool isZero() const { return X == 0 && Y == 0; } - TVector2 &operator= (const TVector2 &other) = default; + constexpr TVector2 &operator= (const TVector2 &other) = default; // Access X and Y as an array - vec_t &operator[] (int index) + constexpr vec_t &operator[] (int index) { return index == 0 ? X : Y; } - const vec_t &operator[] (int index) const + constexpr const vec_t &operator[] (int index) const { return index == 0 ? X : Y; } // Test for equality - bool operator== (const TVector2 &other) const + constexpr bool operator== (const TVector2 &other) const { return X == other.X && Y == other.Y; } // Test for inequality - bool operator!= (const TVector2 &other) const + constexpr bool operator!= (const TVector2 &other) const { return X != other.X || Y != other.Y; } @@ -137,92 +147,92 @@ struct TVector2 } // Unary negation - TVector2 operator- () const + constexpr TVector2 operator- () const { return TVector2(-X, -Y); } // Scalar addition #if 0 - TVector2 &operator+= (double scalar) + constexpr TVector2 &operator+= (double scalar) { X += scalar, Y += scalar; return *this; } #endif - friend TVector2 operator+ (const TVector2 &v, vec_t scalar) + constexpr friend TVector2 operator+ (const TVector2 &v, vec_t scalar) { return TVector2(v.X + scalar, v.Y + scalar); } - friend TVector2 operator+ (vec_t scalar, const TVector2 &v) + constexpr friend TVector2 operator+ (vec_t scalar, const TVector2 &v) { return TVector2(v.X + scalar, v.Y + scalar); } // Scalar subtraction - TVector2 &operator-= (vec_t scalar) + constexpr TVector2 &operator-= (vec_t scalar) { X -= scalar, Y -= scalar; return *this; } - TVector2 operator- (vec_t scalar) const + constexpr TVector2 operator- (vec_t scalar) const { return TVector2(X - scalar, Y - scalar); } // Scalar multiplication - TVector2 &operator*= (vec_t scalar) + constexpr TVector2 &operator*= (vec_t scalar) { X *= scalar, Y *= scalar; return *this; } - friend TVector2 operator* (const TVector2 &v, vec_t scalar) + constexpr friend TVector2 operator* (const TVector2 &v, vec_t scalar) { return TVector2(v.X * scalar, v.Y * scalar); } - friend TVector2 operator* (vec_t scalar, const TVector2 &v) + constexpr friend TVector2 operator* (vec_t scalar, const TVector2 &v) { return TVector2(v.X * scalar, v.Y * scalar); } // Scalar division - TVector2 &operator/= (vec_t scalar) + constexpr TVector2 &operator/= (vec_t scalar) { scalar = 1 / scalar, X *= scalar, Y *= scalar; return *this; } - TVector2 operator/ (vec_t scalar) const + constexpr TVector2 operator/ (vec_t scalar) const { scalar = 1 / scalar; return TVector2(X * scalar, Y * scalar); } // Vector addition - TVector2 &operator+= (const TVector2 &other) + constexpr TVector2 &operator+= (const TVector2 &other) { X += other.X, Y += other.Y; return *this; } - TVector2 operator+ (const TVector2 &other) const + constexpr TVector2 operator+ (const TVector2 &other) const { return TVector2(X + other.X, Y + other.Y); } // Vector subtraction - TVector2 &operator-= (const TVector2 &other) + constexpr TVector2 &operator-= (const TVector2 &other) { X -= other.X, Y -= other.Y; return *this; } - TVector2 operator- (const TVector2 &other) const + constexpr TVector2 operator- (const TVector2 &other) const { return TVector2(X - other.X, Y - other.Y); } @@ -233,7 +243,7 @@ struct TVector2 return (vec_t)g_sqrt (LengthSquared()); } - vec_t LengthSquared() const + constexpr vec_t LengthSquared() const { return X*X + Y*Y; } @@ -286,12 +296,12 @@ struct TVector2 } // Dot product - vec_t operator | (const TVector2 &other) const + constexpr vec_t operator | (const TVector2 &other) const { return X*other.X + Y*other.Y; } - vec_t dot(const TVector2 &other) const + constexpr vec_t dot(const TVector2 &other) const { return X*other.X + Y*other.Y; } @@ -317,19 +327,19 @@ struct TVector2 } // Returns a rotated vector. angle is in degrees. - TVector2 Rotated(const double cosval, const double sinval) const + constexpr TVector2 Rotated(const double cosval, const double sinval) const { return TVector2(X*cosval - Y*sinval, Y*cosval + X*sinval); } // Returns a vector rotated 90 degrees clockwise. - TVector2 Rotated90CW() const + constexpr TVector2 Rotated90CW() const { return TVector2(Y, -X); } // Returns a vector rotated 90 degrees counterclockwise. - TVector2 Rotated90CCW() const + constexpr TVector2 Rotated90CCW() const { return TVector2(-Y, X); } @@ -344,65 +354,70 @@ struct TVector3 vec_t X, Y, Z; - TVector3() = default; + constexpr TVector3() = default; - TVector3 (vec_t a, vec_t b, vec_t c) + constexpr TVector3 (vec_t a, vec_t b, vec_t c) : X(a), Y(b), Z(c) { } - TVector3(vec_t *o) + constexpr TVector3(vec_t *o) : X(o[0]), Y(o[1]), Z(o[2]) { } - TVector3(std::nullptr_t nul) = delete; + constexpr TVector3(std::nullptr_t nul) = delete; - TVector3(const TVector3 &other) = default; + constexpr TVector3(const TVector3 &other) = default; - TVector3 (const Vector2 &xy, vec_t z) + constexpr TVector3 (const Vector2 &xy, vec_t z) : X(xy.X), Y(xy.Y), Z(z) { } TVector3 (const TRotator &rot); + + template + constexpr explicit operator TVector3 () const noexcept { + return TVector3(static_cast(X), static_cast(Y), static_cast(Z)); + } - void Zero() + constexpr void Zero() { Z = Y = X = 0; } - bool isZero() const + constexpr bool isZero() const { return X == 0 && Y == 0 && Z == 0; } - TVector3 plusZ(double z) const + constexpr TVector3 plusZ(double z) const { return { X, Y, Z + z }; } - TVector3 &operator= (const TVector3 &other) = default; + constexpr TVector3 &operator= (const TVector3 &other) = default; // Access X and Y and Z as an array - vec_t &operator[] (int index) + constexpr vec_t &operator[] (int index) { return index == 0 ? X : index == 1 ? Y : Z; } - const vec_t &operator[] (int index) const + constexpr const vec_t &operator[] (int index) const { return index == 0 ? X : index == 1 ? Y : Z; } // Test for equality - bool operator== (const TVector3 &other) const + constexpr bool operator== (const TVector3 &other) const { return X == other.X && Y == other.Y && Z == other.Z; } // Test for inequality - bool operator!= (const TVector3 &other) const + constexpr bool operator!= (const TVector3 &other) const { return X != other.X || Y != other.Y || Z != other.Z; } @@ -420,140 +435,140 @@ struct TVector3 } // Unary negation - TVector3 operator- () const + constexpr TVector3 operator- () const { return TVector3(-X, -Y, -Z); } // Scalar addition #if 0 - TVector3 &operator+= (vec_t scalar) + constexpr TVector3 &operator+= (vec_t scalar) { X += scalar, Y += scalar, Z += scalar; return *this; } #endif - friend TVector3 operator+ (const TVector3 &v, vec_t scalar) + constexpr friend TVector3 operator+ (const TVector3 &v, vec_t scalar) { return TVector3(v.X + scalar, v.Y + scalar, v.Z + scalar); } - friend TVector3 operator+ (vec_t scalar, const TVector3 &v) + constexpr friend TVector3 operator+ (vec_t scalar, const TVector3 &v) { return TVector3(v.X + scalar, v.Y + scalar, v.Z + scalar); } // Scalar subtraction - TVector3 &operator-= (vec_t scalar) + constexpr TVector3 &operator-= (vec_t scalar) { X -= scalar, Y -= scalar, Z -= scalar; return *this; } - TVector3 operator- (vec_t scalar) const + constexpr TVector3 operator- (vec_t scalar) const { return TVector3(X - scalar, Y - scalar, Z - scalar); } // Scalar multiplication - TVector3 &operator*= (vec_t scalar) + constexpr TVector3 &operator*= (vec_t scalar) { X = vec_t(X *scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar); return *this; } - friend TVector3 operator* (const TVector3 &v, vec_t scalar) + constexpr friend TVector3 operator* (const TVector3 &v, vec_t scalar) { return TVector3(v.X * scalar, v.Y * scalar, v.Z * scalar); } - friend TVector3 operator* (vec_t scalar, const TVector3 &v) + constexpr friend TVector3 operator* (vec_t scalar, const TVector3 &v) { return TVector3(v.X * scalar, v.Y * scalar, v.Z * scalar); } // Scalar division - TVector3 &operator/= (vec_t scalar) + constexpr TVector3 &operator/= (vec_t scalar) { scalar = 1 / scalar, X = vec_t(X * scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar); return *this; } - TVector3 operator/ (vec_t scalar) const + constexpr TVector3 operator/ (vec_t scalar) const { scalar = 1 / scalar; return TVector3(X * scalar, Y * scalar, Z * scalar); } // Vector addition - TVector3 &operator+= (const TVector3 &other) + constexpr TVector3 &operator+= (const TVector3 &other) { X += other.X, Y += other.Y, Z += other.Z; return *this; } - TVector3 operator+ (const TVector3 &other) const + constexpr TVector3 operator+ (const TVector3 &other) const { return TVector3(X + other.X, Y + other.Y, Z + other.Z); } // Vector subtraction - TVector3 &operator-= (const TVector3 &other) + constexpr TVector3 &operator-= (const TVector3 &other) { X -= other.X, Y -= other.Y, Z -= other.Z; return *this; } - TVector3 operator- (const TVector3 &other) const + constexpr TVector3 operator- (const TVector3 &other) const { return TVector3(X - other.X, Y - other.Y, Z - other.Z); } // Add a 2D vector to this 3D vector, leaving Z unchanged. - TVector3 &operator+= (const Vector2 &other) + constexpr TVector3 &operator+= (const Vector2 &other) { X += other.X, Y += other.Y; return *this; } // Subtract a 2D vector from this 3D vector, leaving Z unchanged. - TVector3 &operator-= (const Vector2 &other) + constexpr TVector3 &operator-= (const Vector2 &other) { X -= other.X, Y -= other.Y; return *this; } // returns the XY fields as a 2D-vector. - const Vector2& XY() const + constexpr const Vector2& XY() const { return *reinterpret_cast(this); } - Vector2& XY() + constexpr Vector2& XY() { return *reinterpret_cast(this); } // Add a 3D vector and a 2D vector. - friend TVector3 operator+ (const TVector3 &v3, const Vector2 &v2) + constexpr friend TVector3 operator+ (const TVector3 &v3, const Vector2 &v2) { return TVector3(v3.X + v2.X, v3.Y + v2.Y, v3.Z); } - friend TVector3 operator- (const TVector3 &v3, const Vector2 &v2) + constexpr friend TVector3 operator- (const TVector3 &v3, const Vector2 &v2) { return TVector3(v3.X - v2.X, v3.Y - v2.Y, v3.Z); } - friend Vector2 operator+ (const Vector2 &v2, const TVector3 &v3) + constexpr friend Vector2 operator+ (const Vector2 &v2, const TVector3 &v3) { return Vector2(v2.X + v3.X, v2.Y + v3.Y); } // Subtract a 3D vector and a 2D vector. // Discards the Z component of the 3D vector and returns a 2D vector. - friend Vector2 operator- (const TVector2 &v2, const TVector3 &v3) + constexpr friend Vector2 operator- (const TVector2 &v2, const TVector3 &v3) { return Vector2(v2.X - v3.X, v2.Y - v3.Y); } @@ -561,7 +576,7 @@ struct TVector3 void GetRightUp(TVector3 &right, TVector3 &up) { TVector3 n(X, Y, Z); - TVector3 fn(fabs(n.X), fabs(n.Y), fabs(n.Z)); + TVector3 fn((vec_t)fabs(n.X), (vec_t)fabs(n.Y), (vec_t)fabs(n.Z)); int major = 0; if (fn[1] > fn[major]) major = 1; @@ -616,7 +631,7 @@ struct TVector3 return g_sqrt (LengthSquared()); } - double LengthSquared() const + constexpr double LengthSquared() const { return X*X + Y*Y + Z*Z; } @@ -672,25 +687,25 @@ struct TVector3 } // Dot product - vec_t operator | (const TVector3 &other) const + constexpr vec_t operator | (const TVector3 &other) const { return X*other.X + Y*other.Y + Z*other.Z; } - vec_t dot (const TVector3& other) const + constexpr vec_t dot (const TVector3& other) const { return X * other.X + Y * other.Y + Z * other.Z; } // Cross product - TVector3 operator ^ (const TVector3 &other) const + constexpr TVector3 operator ^ (const TVector3 &other) const { return TVector3(Y*other.Z - Z*other.Y, Z*other.X - X*other.Z, X*other.Y - Y*other.X); } - TVector3 &operator ^= (const TVector3 &other) + constexpr TVector3 &operator ^= (const TVector3 &other) { *this = *this ^ other; return *this; @@ -705,83 +720,88 @@ struct TVector4 vec_t X, Y, Z, W; - TVector4() = default; + constexpr TVector4() = default; - TVector4(vec_t a, vec_t b, vec_t c, vec_t d) + constexpr TVector4(vec_t a, vec_t b, vec_t c, vec_t d) : X(a), Y(b), Z(c), W(d) { } - TVector4(vec_t *o) + constexpr TVector4(vec_t *o) : X(o[0]), Y(o[1]), Z(o[2]), W(o[3]) { } - TVector4(const TVector4 &other) = default; + constexpr TVector4(const TVector4 &other) = default; - TVector4(const Vector3 &xyz, vec_t w) + constexpr TVector4(const Vector3 &xyz, vec_t w) : X(xyz.X), Y(xyz.Y), Z(xyz.Z), W(w) { } - TVector4(const vec_t v[4]) + constexpr TVector4(const vec_t v[4]) : TVector4(v[0], v[1], v[2], v[3]) { } - void Zero() + template + constexpr explicit operator TVector4 () const noexcept { + return TVector4(static_cast(X), static_cast(Y), static_cast(Z), static_cast(W)); + } + + constexpr void Zero() { Z = Y = X = W = 0; } - bool isZero() const + constexpr bool isZero() const { return X == 0 && Y == 0 && Z == 0 && W == 0; } - TVector4 &operator= (const TVector4 &other) = default; + constexpr TVector4 &operator= (const TVector4 &other) = default; // Access X and Y and Z as an array - vec_t &operator[] (int index) + constexpr vec_t &operator[] (int index) { return (&X)[index]; } - const vec_t &operator[] (int index) const + constexpr const vec_t &operator[] (int index) const { return (&X)[index]; } // Test for equality - bool operator== (const TVector4 &other) const + constexpr bool operator== (const TVector4 &other) const { return X == other.X && Y == other.Y && Z == other.Z && W == other.W; } // Test for inequality - bool operator!= (const TVector4 &other) const + constexpr bool operator!= (const TVector4 &other) const { return X != other.X || Y != other.Y || Z != other.Z || W != other.W; } // returns the XY fields as a 2D-vector. - const Vector2& XY() const + constexpr const Vector2& XY() const { return *reinterpret_cast(this); } - Vector2& XY() + constexpr Vector2& XY() { return *reinterpret_cast(this); } // returns the XY fields as a 2D-vector. - const Vector3& XYZ() const + constexpr const Vector3& XYZ() const { return *reinterpret_cast(this); } - Vector3& XYZ() + constexpr Vector3& XYZ() { return *reinterpret_cast(this); } @@ -800,127 +820,127 @@ struct TVector4 } // Unary negation - TVector4 operator- () const + constexpr TVector4 operator- () const { return TVector4(-X, -Y, -Z, -W); } // Scalar addition - TVector4 &operator+= (vec_t scalar) + constexpr TVector4 &operator+= (vec_t scalar) { X += scalar, Y += scalar, Z += scalar; W += scalar; return *this; } - friend TVector4 operator+ (const TVector4 &v, vec_t scalar) + constexpr friend TVector4 operator+ (const TVector4 &v, vec_t scalar) { return TVector4(v.X + scalar, v.Y + scalar, v.Z + scalar, v.W + scalar); } - friend TVector4 operator+ (vec_t scalar, const TVector4 &v) + constexpr friend TVector4 operator+ (vec_t scalar, const TVector4 &v) { return TVector4(v.X + scalar, v.Y + scalar, v.Z + scalar, v.W + scalar); } // Scalar subtraction - TVector4 &operator-= (vec_t scalar) + constexpr TVector4 &operator-= (vec_t scalar) { X -= scalar, Y -= scalar, Z -= scalar, W -= scalar; return *this; } - TVector4 operator- (vec_t scalar) const + constexpr TVector4 operator- (vec_t scalar) const { return TVector4(X - scalar, Y - scalar, Z - scalar, W - scalar); } // Scalar multiplication - TVector4 &operator*= (vec_t scalar) + constexpr TVector4 &operator*= (vec_t scalar) { X = vec_t(X *scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar), W = vec_t(W * scalar); return *this; } - friend TVector4 operator* (const TVector4 &v, vec_t scalar) + constexpr friend TVector4 operator* (const TVector4 &v, vec_t scalar) { return TVector4(v.X * scalar, v.Y * scalar, v.Z * scalar, v.W * scalar); } - friend TVector4 operator* (vec_t scalar, const TVector4 &v) + constexpr friend TVector4 operator* (vec_t scalar, const TVector4 &v) { return TVector4(v.X * scalar, v.Y * scalar, v.Z * scalar, v.W * scalar); } // Scalar division - TVector4 &operator/= (vec_t scalar) + constexpr TVector4 &operator/= (vec_t scalar) { scalar = 1 / scalar, X = vec_t(X * scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar), W = vec_t(W * scalar); return *this; } - TVector4 operator/ (vec_t scalar) const + constexpr TVector4 operator/ (vec_t scalar) const { scalar = 1 / scalar; return TVector4(X * scalar, Y * scalar, Z * scalar, W * scalar); } // Vector addition - TVector4 &operator+= (const TVector4 &other) + constexpr TVector4 &operator+= (const TVector4 &other) { X += other.X, Y += other.Y, Z += other.Z, W += other.W; return *this; } - TVector4 operator+ (const TVector4 &other) const + constexpr TVector4 operator+ (const TVector4 &other) const { return TVector4(X + other.X, Y + other.Y, Z + other.Z, W + other.W); } // Vector subtraction - TVector4 &operator-= (const TVector4 &other) + constexpr TVector4 &operator-= (const TVector4 &other) { X -= other.X, Y -= other.Y, Z -= other.Z, W -= other.W; return *this; } - TVector4 operator- (const TVector4 &other) const + constexpr TVector4 operator- (const TVector4 &other) const { return TVector4(X - other.X, Y - other.Y, Z - other.Z, W - other.W); } // Add a 3D vector to this 4D vector, leaving W unchanged. - TVector4 &operator+= (const Vector3 &other) + constexpr TVector4 &operator+= (const Vector3 &other) { X += other.X, Y += other.Y, Z += other.Z; return *this; } // Subtract a 3D vector from this 4D vector, leaving W unchanged. - TVector4 &operator-= (const Vector3 &other) + constexpr TVector4 &operator-= (const Vector3 &other) { X -= other.X, Y -= other.Y, Z -= other.Z; return *this; } // Add a 4D vector and a 3D vector. - friend TVector4 operator+ (const TVector4 &v4, const Vector3 &v3) + constexpr friend TVector4 operator+ (const TVector4 &v4, const Vector3 &v3) { return TVector4(v4.X + v3.X, v4.Y + v3.Y, v4.Z + v3.Z, v4.W); } - friend TVector4 operator- (const TVector4 &v4, const Vector3 &v3) + constexpr friend TVector4 operator- (const TVector4 &v4, const Vector3 &v3) { return TVector4(v4.X - v3.X, v4.Y - v3.Y, v4.Z - v3.Z, v4.W); } - friend Vector3 operator+ (const Vector3 &v3, const TVector4 &v4) + constexpr friend Vector3 operator+ (const Vector3 &v3, const TVector4 &v4) { return Vector3(v3.X + v4.X, v3.Y + v4.Y, v3.Z + v4.Z); } // Subtract a 4D vector and a 3D vector. // Discards the W component of the 4D vector and returns a 3D vector. - friend Vector3 operator- (const TVector3 &v3, const TVector4 &v4) + constexpr friend Vector3 operator- (const TVector3 &v3, const TVector4 &v4) { return Vector3(v3.X - v4.X, v3.Y - v4.Y, v3.Z - v4.Z); } @@ -931,7 +951,7 @@ struct TVector4 return g_sqrt(LengthSquared()); } - double LengthSquared() const + constexpr double LengthSquared() const { return X*X + Y*Y + Z*Z + W*W; } @@ -988,12 +1008,12 @@ struct TVector4 } // Dot product - vec_t operator | (const TVector4 &other) const + constexpr vec_t operator | (const TVector4 &other) const { return X*other.X + Y*other.Y + Z*other.Z + W*other.W; } - vec_t dot(const TVector4 &other) const + constexpr vec_t dot(const TVector4 &other) const { return X*other.X + Y*other.Y + Z*other.Z + W*other.W; } @@ -1006,11 +1026,11 @@ struct TMatrix3x3 vec_t Cells[3][3]; - TMatrix3x3() = default; - TMatrix3x3(const TMatrix3x3 &other) = default; - TMatrix3x3& operator=(const TMatrix3x3& other) = default; + constexpr TMatrix3x3() = default; + constexpr TMatrix3x3(const TMatrix3x3 &other) = default; + constexpr TMatrix3x3& operator=(const TMatrix3x3& other) = default; - TMatrix3x3(const Vector3 &row1, const Vector3 &row2, const Vector3 &row3) + constexpr TMatrix3x3(const Vector3 &row1, const Vector3 &row2, const Vector3 &row3) { (*this)[0] = row1; (*this)[1] = row2; @@ -1019,51 +1039,16 @@ struct TMatrix3x3 // Construct a rotation matrix about an arbitrary axis. // (The axis vector must be normalized.) - TMatrix3x3(const Vector3 &axis, double radians) + constexpr TMatrix3x3(const Vector3 &axis, double degrees) + : TMatrix3x3(axis, g_sindeg(degrees), g_cosdeg(degrees)) { - double c = g_cos(radians), s = g_sin(radians), t = 1 - c; -/* In comments: A more readable version of the matrix setup. -This was found in Diana Gruber's article "The Mathematics of the -3D Rotation Matrix" at and is -attributed to Graphics Gems (Glassner, Academic Press, 1990). - - Cells[0][0] = t*axis.X*axis.X + c; - Cells[0][1] = t*axis.X*axis.Y - s*axis.Z; - Cells[0][2] = t*axis.X*axis.Z + s*axis.Y; - - Cells[1][0] = t*axis.Y*axis.X + s*axis.Z; - Cells[1][1] = t*axis.Y*axis.Y + c; - Cells[1][2] = t*axis.Y*axis.Z - s*axis.X; - - Cells[2][0] = t*axis.Z*axis.X - s*axis.Y; - Cells[2][1] = t*axis.Z*axis.Y + s*axis.X; - Cells[2][2] = t*axis.Z*axis.Z + c; - -Outside comments: A faster version with only 10 (not 24) multiplies. -*/ - double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z; - double tx, ty, txx, tyy, u, v; - - tx = t*axis.X; - Cells[0][0] = vec_t( (txx=tx*axis.X) + c ); - Cells[0][1] = vec_t( (u=tx*axis.Y) - sz); - Cells[0][2] = vec_t( (v=tx*axis.Z) + sy); - - ty = t*axis.Y; - Cells[1][0] = vec_t( u + sz); - Cells[1][1] = vec_t( (tyy=ty*axis.Y) + c ); - Cells[1][2] = vec_t( (u=ty*axis.Z) - sx); - - Cells[2][0] = vec_t( v - sy); - Cells[2][1] = vec_t( u + sx); - Cells[2][2] = vec_t( (t-txx-tyy) + c ); } - TMatrix3x3(const Vector3 &axis, double c/*cosine*/, double s/*sine*/) + constexpr TMatrix3x3(const Vector3 &axis, double c/*cosine*/, double s/*sine*/) { double t = 1 - c; double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z; - double tx, ty, txx, tyy, u, v; + double tx = 0, ty = 0, txx = 0, tyy = 0, u = 0, v = 0; tx = t*axis.X; Cells[0][0] = vec_t( (txx=tx*axis.X) + c ); @@ -1082,10 +1067,10 @@ Outside comments: A faster version with only 10 (not 24) multiplies. TMatrix3x3(const Vector3 &axis, TAngle degrees); - static TMatrix3x3 Rotate2D(double radians) + static TMatrix3x3 Rotate2D(double degrees) { - double c = g_cos(radians); - double s = g_sin(radians); + double c = g_cosdeg(degrees); + double s = g_sindeg(degrees); TMatrix3x3 ret; ret.Cells[0][0] = c; ret.Cells[0][1] = -s; ret.Cells[0][2] = 0; ret.Cells[1][0] = s; ret.Cells[1][1] = c; ret.Cells[1][2] = 0; @@ -1093,7 +1078,7 @@ Outside comments: A faster version with only 10 (not 24) multiplies. return ret; } - static TMatrix3x3 Scale2D(TVector2 scaleVec) + constexpr static TMatrix3x3 Scale2D(TVector2 scaleVec) { TMatrix3x3 ret; ret.Cells[0][0] = scaleVec.X; ret.Cells[0][1] = 0; ret.Cells[0][2] = 0; @@ -1102,7 +1087,7 @@ Outside comments: A faster version with only 10 (not 24) multiplies. return ret; } - static TMatrix3x3 Translate2D(TVector2 translateVec) + constexpr static TMatrix3x3 Translate2D(TVector2 translateVec) { TMatrix3x3 ret; ret.Cells[0][0] = 1; ret.Cells[0][1] = 0; ret.Cells[0][2] = translateVec.X; @@ -1111,30 +1096,30 @@ Outside comments: A faster version with only 10 (not 24) multiplies. return ret; } - void Zero() + constexpr void Zero() { memset (this, 0, sizeof *this); } - void Identity() + constexpr void Identity() { Cells[0][0] = 1; Cells[0][1] = 0; Cells[0][2] = 0; Cells[1][0] = 0; Cells[1][1] = 1; Cells[1][2] = 0; Cells[2][0] = 0; Cells[2][1] = 0; Cells[2][2] = 1; } - Vector3 &operator[] (int index) + constexpr Vector3 &operator[] (int index) { return *((Vector3 *)&Cells[index]); } - const Vector3 &operator[] (int index) const + constexpr const Vector3 &operator[] (int index) const { return *((Vector3 *)&Cells[index]); } // Multiply a scalar - TMatrix3x3 &operator*= (double scalar) + constexpr TMatrix3x3 &operator*= (double scalar) { (*this)[0] *= scalar; (*this)[1] *= scalar; @@ -1142,29 +1127,29 @@ Outside comments: A faster version with only 10 (not 24) multiplies. return *this; } - friend TMatrix3x3 operator* (double s, const TMatrix3x3 &m) + constexpr friend TMatrix3x3 operator* (double s, const TMatrix3x3 &m) { return TMatrix3x3(m[0]*s, m[1]*s, m[2]*s); } - TMatrix3x3 operator* (double s) const + constexpr TMatrix3x3 operator* (double s) const { return TMatrix3x3((*this)[0]*s, (*this)[1]*s, (*this)[2]*s); } // Divide a scalar - TMatrix3x3 &operator/= (double scalar) + constexpr TMatrix3x3 &operator/= (double scalar) { return *this *= 1 / scalar; } - TMatrix3x3 operator/ (double s) const + constexpr TMatrix3x3 operator/ (double s) const { return *this * (1 / s); } // Add two 3x3 matrices together - TMatrix3x3 &operator+= (const TMatrix3x3 &o) + constexpr TMatrix3x3 &operator+= (const TMatrix3x3 &o) { (*this)[0] += o[0]; (*this)[1] += o[1]; @@ -1172,13 +1157,13 @@ Outside comments: A faster version with only 10 (not 24) multiplies. return *this; } - TMatrix3x3 operator+ (const TMatrix3x3 &o) const + constexpr TMatrix3x3 operator+ (const TMatrix3x3 &o) const { return TMatrix3x3((*this)[0] + o[0], (*this)[1] + o[1], (*this)[2] + o[2]); } // Subtract two 3x3 matrices - TMatrix3x3 &operator-= (const TMatrix3x3 &o) + constexpr TMatrix3x3 &operator-= (const TMatrix3x3 &o) { (*this)[0] -= o[0]; (*this)[1] -= o[1]; @@ -1186,18 +1171,18 @@ Outside comments: A faster version with only 10 (not 24) multiplies. return *this; } - TMatrix3x3 operator- (const TMatrix3x3 &o) const + constexpr TMatrix3x3 operator- (const TMatrix3x3 &o) const { return TMatrix3x3((*this)[0] - o[0], (*this)[1] - o[1], (*this)[2] - o[2]); } // Concatenate two 3x3 matrices - TMatrix3x3 &operator*= (const TMatrix3x3 &o) + constexpr TMatrix3x3 &operator*= (const TMatrix3x3 &o) { return *this = *this * o; } - TMatrix3x3 operator* (const TMatrix3x3 &o) const + constexpr TMatrix3x3 operator* (const TMatrix3x3 &o) const { return TMatrix3x3( Vector3(Cells[0][0]*o[0][0] + Cells[0][1]*o[1][0] + Cells[0][2]*o[2][0], @@ -1212,12 +1197,12 @@ Outside comments: A faster version with only 10 (not 24) multiplies. } // Multiply a 3D vector by a rotation matrix - friend Vector3 operator* (const Vector3 &v, const TMatrix3x3 &m) + constexpr friend Vector3 operator* (const Vector3 &v, const TMatrix3x3 &m) { return Vector3(m[0] | v, m[1] | v, m[2] | v); } - friend Vector3 operator* (const TMatrix3x3 &m, const Vector3 &v) + constexpr friend Vector3 operator* (const TMatrix3x3 &m, const Vector3 &v) { return Vector3(m[0] | v, m[1] | v, m[2] | v); } @@ -1254,7 +1239,7 @@ struct TAngle } public: - vec_t& Degrees__() { return Degrees_; } + constexpr vec_t& Degrees__() { return Degrees_; } static constexpr TAngle fromDeg(float deg) { @@ -1301,8 +1286,8 @@ struct TAngle return TAngle(bang * (90. / 16384)); } - TAngle(const TAngle &other) = default; - TAngle &operator= (const TAngle &other) = default; + constexpr TAngle(const TAngle &other) = default; + constexpr TAngle &operator= (const TAngle &other) = default; constexpr TAngle operator- () const { @@ -1450,8 +1435,13 @@ struct TAngle double Tan() const { + // use an optimized approach if we have a sine table. If not just call the CRT's tan function. +#if __has_include("math/cmath.h") const auto bam = BAMs(); return g_sinbam(bam) / g_cosbam(bam); +#else + return vec_t(tan(Radians())); +#endif } // This is for calculating vertical velocity. For high pitches the tangent will become too large to be useful. @@ -1460,12 +1450,32 @@ struct TAngle return clamp(Tan(), -max, max); } + // returns sign of the NORMALIZED angle. int Sgn() const { - return ::Sgn(int(BAMs())); + auto val = int(BAMs()); + return (val > 0) - (val < 0); } }; +typedef TAngle FAngle; +typedef TAngle DAngle; + +constexpr DAngle nullAngle = DAngle::fromDeg(0.); +constexpr FAngle nullFAngle = FAngle::fromDeg(0.); +constexpr DAngle minAngle = DAngle::fromDeg(1. / 65536.); +constexpr FAngle minFAngle = FAngle::fromDeg(1. / 65536.); + +constexpr DAngle DAngle1 = DAngle::fromDeg(1); +constexpr DAngle DAngle15 = DAngle::fromDeg(15); +constexpr DAngle DAngle22_5 = DAngle::fromDeg(22.5); +constexpr DAngle DAngle45 = DAngle::fromDeg(45); +constexpr DAngle DAngle60 = DAngle::fromDeg(60); +constexpr DAngle DAngle90 = DAngle::fromDeg(90); +constexpr DAngle DAngle180 = DAngle::fromDeg(180); +constexpr DAngle DAngle270 = DAngle::fromDeg(270); +constexpr DAngle DAngle360 = DAngle::fromDeg(360); + template inline TAngle fabs (const TAngle °) { @@ -1490,12 +1500,6 @@ inline TAngle absangle(const TAngle &a1, const TAngle &a2) return fabs(deltaangle(a2, a1)); } -template -inline TAngle clamp(const TAngle &angle, const TAngle &min, const TAngle &max) -{ - return TAngle::fromDeg(clamp(angle.Degrees(), min.Degrees(), max.Degrees())); -} - inline TAngle VecToAngle(double x, double y) { return TAngle::fromRad(g_atan2(y, x)); @@ -1532,11 +1536,23 @@ TAngle TVector3::Pitch() const } template -inline TVector2 clamp(const TVector2 &vec, const TVector2 &min, const TVector2 &max) +constexpr inline TVector2 clamp(const TVector2 &vec, const TVector2 &min, const TVector2 &max) { return TVector2(clamp(vec.X, min.X, max.X), clamp(vec.Y, min.Y, max.Y)); } +template +constexpr inline TVector3 clamp(const TVector3 &vec, const TVector3 &min, const TVector3 &max) +{ + return TVector3(std::clamp(vec.X, min.X, max.X), std::clamp(vec.Y, min.Y, max.Y), std::clamp(vec.Z, min.Z, max.Z)); +} + +template +constexpr inline TRotator clamp(const TRotator &rot, const TRotator &min, const TRotator &max) +{ + return TRotator(clamp(rot.Pitch, min.Pitch, max.Pitch), clamp(rot.Yaw, min.Yaw, max.Yaw), clamp(rot.Roll, min.Roll, max.Roll)); +} + template inline TAngle interpolatedvalue(const TAngle &oang, const TAngle &ang, const double interpfrac) { @@ -1554,7 +1570,7 @@ inline TRotator interpolatedvalue(const TRotator &oang, const TRotator } template -inline T interpolatedvalue(const T& oval, const T& val, const double interpfrac) +constexpr inline T interpolatedvalue(const T& oval, const T& val, const double interpfrac) { return T(oval + (val - oval) * interpfrac); } @@ -1569,125 +1585,162 @@ struct TRotator Angle Yaw; // left/right Angle Roll; // rotation about the forward axis. - TRotator() = default; + constexpr TRotator() = default; - TRotator (const Angle &p, const Angle &y, const Angle &r) + constexpr TRotator (const Angle &p, const Angle &y, const Angle &r) : Pitch(p), Yaw(y), Roll(r) { } - TRotator(const TRotator &other) = default; - TRotator &operator= (const TRotator &other) = default; + constexpr TRotator(const TRotator &other) = default; + constexpr TRotator &operator= (const TRotator &other) = default; + + constexpr void Zero() + { + Roll = Yaw = Pitch = nullAngle; + } + + constexpr bool isZero() const + { + return Pitch == nullAngle && Yaw == nullAngle && Roll == nullAngle; + } // Access angles as an array - Angle &operator[] (int index) + constexpr Angle &operator[] (int index) { return *(&Pitch + index); } - const Angle &operator[] (int index) const + constexpr const Angle &operator[] (int index) const { return *(&Pitch + index); } // Test for equality - bool operator== (const TRotator &other) const + constexpr bool operator== (const TRotator &other) const { - return fabs(Pitch - other.Pitch) < Angle(EQUAL_EPSILON) && fabs(Yaw - other.Yaw) < Angle(EQUAL_EPSILON) && fabs(Roll - other.Roll) < Angle(EQUAL_EPSILON); + return Pitch == other.Pitch && Yaw == other.Yaw && Roll == other.Roll; } // Test for inequality - bool operator!= (const TRotator &other) const + constexpr bool operator!= (const TRotator &other) const { - return fabs(Pitch - other.Pitch) >= Angle(EQUAL_EPSILON) && fabs(Yaw - other.Yaw) >= Angle(EQUAL_EPSILON) && fabs(Roll - other.Roll) >= Angle(EQUAL_EPSILON); + return Pitch != other.Pitch || Yaw != other.Yaw || Roll != other.Roll; + } + + // Test for approximate equality + bool ApproximatelyEquals (const TRotator &other) const + { + constexpr auto epsilon = Angle(EQUAL_EPSILON); + return fabs(Pitch - other.Pitch) < epsilon && fabs(Yaw - other.Yaw) < epsilon && fabs(Roll - other.Roll) < epsilon; + } + + // Test for approximate inequality + bool DoesNotApproximatelyEqual (const TRotator &other) const + { + constexpr auto epsilon = Angle(EQUAL_EPSILON); + return fabs(Pitch - other.Pitch) >= epsilon && fabs(Yaw - other.Yaw) >= epsilon && fabs(Roll - other.Roll) >= epsilon; } // Unary negation - TRotator operator- () const + constexpr TRotator operator- () const { return TRotator(-Pitch, -Yaw, -Roll); } // Scalar addition - TRotator &operator+= (const Angle &scalar) + constexpr TRotator &operator+= (const Angle &scalar) { Pitch += scalar, Yaw += scalar, Roll += scalar; return *this; } - friend TRotator operator+ (const TRotator &v, const Angle &scalar) + constexpr friend TRotator operator+ (const TRotator &v, const Angle &scalar) { return TRotator(v.Pitch + scalar, v.Yaw + scalar, v.Roll + scalar); } - friend TRotator operator+ (const Angle &scalar, const TRotator &v) + constexpr friend TRotator operator+ (const Angle &scalar, const TRotator &v) { return TRotator(v.Pitch + scalar, v.Yaw + scalar, v.Roll + scalar); } // Scalar subtraction - TRotator &operator-= (const Angle &scalar) + constexpr TRotator &operator-= (const Angle &scalar) { Pitch -= scalar, Yaw -= scalar, Roll -= scalar; return *this; } - TRotator operator- (const Angle &scalar) const + constexpr TRotator operator- (const Angle &scalar) const { return TRotator(Pitch - scalar, Yaw - scalar, Roll - scalar); } // Scalar multiplication - TRotator &operator*= (const Angle &scalar) + constexpr TRotator &operator*= (const Angle &scalar) { Pitch *= scalar, Yaw *= scalar, Roll *= scalar; return *this; } - friend TRotator operator* (const TRotator &v, const Angle &scalar) + constexpr friend TRotator operator* (const TRotator &v, const Angle &scalar) { return TRotator(v.Pitch * scalar, v.Yaw * scalar, v.Roll * scalar); } - friend TRotator operator* (const Angle &scalar, const TRotator &v) + constexpr friend TRotator operator* (const Angle &scalar, const TRotator &v) { return TRotator(v.Pitch * scalar, v.Yaw * scalar, v.Roll * scalar); } // Scalar division - TRotator &operator/= (const Angle &scalar) + constexpr TRotator &operator/= (const Angle &scalar) { Angle mul(1 / scalar.Degrees_); Pitch *= mul, Yaw *= mul, Roll *= mul; return *this; } - TRotator operator/ (const Angle &scalar) const + constexpr TRotator &operator/= (const vec_t &scalar) + { + const auto mul = 1. / scalar; + Pitch *= mul, Yaw *= mul, Roll *= mul; + return *this; + } + + constexpr TRotator operator/ (const Angle &scalar) const { Angle mul(1 / scalar.Degrees_); return TRotator(Pitch * mul, Yaw * mul, Roll * mul); } + constexpr TRotator operator/ (const vec_t &scalar) const + { + const auto mul = 1. / scalar; + return TRotator(Pitch * mul, Yaw * mul, Roll * mul); + } + // Vector addition - TRotator &operator+= (const TRotator &other) + constexpr TRotator &operator+= (const TRotator &other) { Pitch += other.Pitch, Yaw += other.Yaw, Roll += other.Roll; return *this; } - TRotator operator+ (const TRotator &other) const + constexpr TRotator operator+ (const TRotator &other) const { return TRotator(Pitch + other.Pitch, Yaw + other.Yaw, Roll + other.Roll); } // Vector subtraction - TRotator &operator-= (const TRotator &other) + constexpr TRotator &operator-= (const TRotator &other) { Pitch -= other.Pitch, Yaw -= other.Yaw, Roll -= other.Roll; return *this; } - TRotator operator- (const TRotator &other) const + constexpr TRotator operator- (const TRotator &other) const { return TRotator(Pitch - other.Pitch, Yaw - other.Yaw, Roll - other.Roll); } @@ -1728,28 +1781,12 @@ typedef TVector3 FVector3; typedef TVector4 FVector4; typedef TRotator FRotator; typedef TMatrix3x3 FMatrix3x3; -typedef TAngle FAngle; typedef TVector2 DVector2; typedef TVector3 DVector3; typedef TVector4 DVector4; typedef TRotator DRotator; typedef TMatrix3x3 DMatrix3x3; -typedef TAngle DAngle; - -constexpr DAngle nullAngle = DAngle::fromDeg(0.); -constexpr DAngle minAngle = DAngle::fromDeg(1. / 65536.); -constexpr FAngle nullFAngle = FAngle::fromDeg(0.); - -constexpr DAngle DAngle1 = DAngle::fromDeg(1); -constexpr DAngle DAngle15 = DAngle::fromDeg(15); -constexpr DAngle DAngle22_5 = DAngle::fromDeg(22.5); -constexpr DAngle DAngle45 = DAngle::fromDeg(45); -constexpr DAngle DAngle60 = DAngle::fromDeg(60); -constexpr DAngle DAngle90 = DAngle::fromDeg(90); -constexpr DAngle DAngle180 = DAngle::fromDeg(180); -constexpr DAngle DAngle270 = DAngle::fromDeg(270); -constexpr DAngle DAngle360 = DAngle::fromDeg(360); class Plane { diff --git a/src/common/utility/weightedlist.h b/src/common/utility/weightedlist.h index cd6a4ba0ed..fb956a4625 100644 --- a/src/common/utility/weightedlist.h +++ b/src/common/utility/weightedlist.h @@ -31,6 +31,7 @@ **--------------------------------------------------------------------------- ** */ +#pragma once #include #include diff --git a/src/common/utility/writezip.cpp b/src/common/utility/writezip.cpp new file mode 100644 index 0000000000..2f3507e6f0 --- /dev/null +++ b/src/common/utility/writezip.cpp @@ -0,0 +1,240 @@ +/* +** writezip.cpp +** +**--------------------------------------------------------------------------- +** Copyright 1998-2009 Randy Heit +** Copyright 2005-2023 Christoph Oelckers +** 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. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +** +*/ + +#include +#include +#include "tarray.h" +#include "files.h" +#include "m_swap.h" +#include "w_zip.h" +#include "fs_decompress.h" + +using FileSys::FCompressedBuffer; + + + +//========================================================================== +// +// time_to_dos +// +// Converts time from struct tm to the DOS format used by zip files. +// +//========================================================================== + +static std::pair time_to_dos(struct tm *time) +{ + std::pair val; + if (time == NULL || time->tm_year < 80) + { + val.first = val.second = 0; + } + else + { + val.first = time->tm_hour * 2048 + time->tm_min * 32 + time->tm_sec / 2; + val.second = (time->tm_year - 80) * 512 + (time->tm_mon + 1) * 32 + time->tm_mday; + } + return val; +} + +//========================================================================== +// +// append_to_zip +// +// Write a given file to the zipFile. +// +// zipfile: zip object to be written to +// +// returns: position = success, -1 = error +// +//========================================================================== + +static int AppendToZip(FileWriter *zip_file, const FCompressedBuffer &content, std::pair &dostime) +{ + FZipLocalFileHeader local; + int position; + + int flags = 0; + int method = content.mMethod; + if (method >= FileSys::METHOD_IMPLODE_MIN && method <= FileSys::METHOD_IMPLODE_MAX) + { + flags = method - FileSys::METHOD_IMPLODE_MIN; + method = FileSys::METHOD_IMPLODE; + } + else if (method == FileSys::METHOD_DEFLATE) + { + flags = 2; + } + else if (method >= 1337) + return -1; + + local.Magic = ZIP_LOCALFILE; + local.VersionToExtract[0] = 20; + local.VersionToExtract[1] = 0; + local.Flags = LittleShort((uint16_t)flags); + local.Method = LittleShort((uint16_t)method); + local.ModDate = LittleShort(dostime.first); + local.ModTime = LittleShort(dostime.second); + local.CRC32 = content.mCRC32; + local.UncompressedSize = LittleLong((unsigned)content.mSize); + local.CompressedSize = LittleLong((unsigned)content.mCompressedSize); + local.NameLength = LittleShort((unsigned short)strlen(content.filename)); + local.ExtraLength = 0; + + // Fill in local directory header. + + position = (int)zip_file->Tell(); + + // Write out the header, file name, and file data. + if (zip_file->Write(&local, sizeof(local)) != sizeof(local) || + zip_file->Write(content.filename, strlen(content.filename)) != strlen(content.filename) || + zip_file->Write(content.mBuffer, content.mCompressedSize) != content.mCompressedSize) + { + return -1; + } + return position; +} + + +//========================================================================== +// +// write_central_dir +// +// Writes the central directory entry for a file. +// +//========================================================================== + +int AppendCentralDirectory(FileWriter *zip_file, const FCompressedBuffer &content, std::pair &dostime, int position) +{ + FZipCentralDirectoryInfo dir; + + int flags = 0; + int method = content.mMethod; + if (method >= FileSys::METHOD_IMPLODE_MIN && method <= FileSys::METHOD_IMPLODE_MAX) + { + flags = method - FileSys::METHOD_IMPLODE_MIN; + method = FileSys::METHOD_IMPLODE; + } + else if (method == FileSys::METHOD_DEFLATE) + { + flags = 2; + } + else if (method >= 1337) + return -1; + + dir.Magic = ZIP_CENTRALFILE; + dir.VersionMadeBy[0] = 20; + dir.VersionMadeBy[1] = 0; + dir.VersionToExtract[0] = 20; + dir.VersionToExtract[1] = 0; + dir.Flags = LittleShort((uint16_t)flags); + dir.Method = LittleShort((uint16_t)method); + dir.ModTime = LittleShort(dostime.first); + dir.ModDate = LittleShort(dostime.second); + dir.CRC32 = content.mCRC32; + dir.CompressedSize32 = LittleLong((unsigned)content.mCompressedSize); + dir.UncompressedSize32 = LittleLong((unsigned)content.mSize); + dir.NameLength = LittleShort((unsigned short)strlen(content.filename)); + dir.ExtraLength = 0; + dir.CommentLength = 0; + dir.StartingDiskNumber = 0; + dir.InternalAttributes = 0; + dir.ExternalAttributes = 0; + dir.LocalHeaderOffset32 = LittleLong((unsigned)position); + + if (zip_file->Write(&dir, sizeof(dir)) != sizeof(dir) || + zip_file->Write(content.filename, strlen(content.filename)) != strlen(content.filename)) + { + return -1; + } + return 0; +} + +bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t contentcount) +{ + // try to determine local time + struct tm *ltime; + time_t ttime; + ttime = time(nullptr); + ltime = localtime(&ttime); + auto dostime = time_to_dos(ltime); + + TArray positions; + + auto f = FileWriter::Open(filename); + if (f != nullptr) + { + for (size_t i = 0; i < contentcount; i++) + { + int pos = AppendToZip(f, content[i], dostime); + if (pos == -1) + { + delete f; + remove(filename); + return false; + } + positions.Push(pos); + } + + int dirofs = (int)f->Tell(); + for (size_t i = 0; i < contentcount; i++) + { + if (AppendCentralDirectory(f, content[i], dostime, positions[i]) < 0) + { + delete f; + remove(filename); + return false; + } + } + + // Write the directory terminator. + FZipEndOfCentralDirectory dirend; + dirend.Magic = ZIP_ENDOFDIR; + dirend.DiskNumber = 0; + dirend.FirstDisk = 0; + dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort((uint16_t)contentcount); + dirend.DirectoryOffset = LittleLong((unsigned)dirofs); + dirend.DirectorySize = LittleLong((uint32_t)(f->Tell() - dirofs)); + dirend.ZipCommentLength = 0; + if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend)) + { + delete f; + remove(filename); + return false; + } + delete f; + return true; + } + return false; +} diff --git a/src/common/utility/x86.cpp b/src/common/utility/x86.cpp index 76e8808340..5707c6572c 100644 --- a/src/common/utility/x86.cpp +++ b/src/common/utility/x86.cpp @@ -45,7 +45,7 @@ void CheckCPUID(CPUInfo *cpu) cpu->DataL1LineSize = 32; // Assume a 32-byte cache line } -FString DumpCPUInfo(const CPUInfo *cpu) +FString DumpCPUInfo(const CPUInfo *cpu, bool brief) { return FString(); } @@ -161,7 +161,7 @@ void CheckCPUID(CPUInfo *cpu) } } -FString DumpCPUInfo(const CPUInfo *cpu) +FString DumpCPUInfo(const CPUInfo *cpu, bool brief) { char cpustring[4*4*3+1]; diff --git a/src/common/utility/x86.h b/src/common/utility/x86.h index 25e698d813..8a009efa0e 100644 --- a/src/common/utility/x86.h +++ b/src/common/utility/x86.h @@ -229,7 +229,7 @@ struct CPUInfo // 92 bytes extern CPUInfo CPU; void CheckCPUID (CPUInfo *cpu); -FString DumpCPUInfo (const CPUInfo *cpu); +FString DumpCPUInfo (const CPUInfo *cpu, bool brief = false); #endif diff --git a/src/common/utility/zstrformat.cpp b/src/common/utility/zstrformat.cpp deleted file mode 100644 index 0d8bcfbc2f..0000000000 --- a/src/common/utility/zstrformat.cpp +++ /dev/null @@ -1,1061 +0,0 @@ -/* -** zstrformat.cpp -** Routines for generic printf-style formatting. -** -**--------------------------------------------------------------------------- -** Copyright 2005-2008 Randy Heit -** 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. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 file relating to printing floating point numbers -** are covered by the following copyright: -** -**--------------------------------------------------------------------------- -** Copyright (c) 1990, 1993 -** The Regents of the University of California. All rights reserved. -** -** This code is derived from software contributed to Berkeley by -** Chris Torek. -** -** 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. -** 4. Neither the name of the University 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 REGENTS 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. -** -**--------------------------------------------------------------------------- -** -** Even though the standard C library has a function to do printf-style -** formatting in a generic way, there is no standard interface to this -** function. So if you want to do some printf formatting that doesn't fit in -** the context of the provided functions, you need to roll your own. Why is -** that? -** -** Maybe Microsoft wants you to write a better one yourself? When used as -** part of a sprintf replacement, this function is significantly faster than -** Microsoft's offering. When used as part of a fprintf replacement, this -** function turns out to be slower, but that's probably because the CRT's -** fprintf can interact with the FILE object on a low level for better -** perfomance. If you sprintf into a buffer and then fwrite that buffer, this -** routine wins again, though the difference isn't great. -*/ - -#include -#include -#include -#include -#include - -#include "zstring.h" -#include "gdtoa.h" -#include "utf8.h" - - -/* - * MAXEXPDIG is the maximum number of decimal digits needed to store a - * floating point exponent in the largest supported format. It should - * be ceil(log10(LDBL_MAX_10_EXP)) or, if hexadecimal floating point - * conversions are supported, ceil(log10(LDBL_MAX_EXP)). But since it - * is presently never greater than 5 in practice, we fudge it. - */ -#define MAXEXPDIG 6 -#if LDBL_MAX_EXP > 999999 -#error "floating point buffers too small" -#endif - -#define DEFPREC 6 - -static const char hexits[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; -static const char HEXits[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; -static const char spaces[16] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; -static const char zeroes[17] = {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','.'}; - -namespace StringFormat -{ - static int writepad (OutputFunc output, void *outputData, const char *pad, int padsize, int spaceToFill); - static int printandpad (OutputFunc output, void *outputData, const char *p, const char *ep, int len, const char *with, int padsize); - static int exponent (char *p0, int exp, int fmtch); - - int Worker (OutputFunc output, void *outputData, const char *fmt, ...) - { - va_list arglist; - int len; - - va_start (arglist, fmt); - len = VWorker (output, outputData, fmt, arglist); - va_end (arglist); - return len; - } - - int VWorker (OutputFunc output, void *outputData, const char *fmt, va_list arglist) - { - const char *c; - const char *base; - int len = 0; - int width; - int precision; - int flags; - - base = c = fmt; - for (;;) - { - while (*c && *c != '%') - { - ++c; - } - if (*c == '\0') - { - return len + output (outputData, base, int(c - base)); - } - - if (c - base > 0) - { - len += output (outputData, base, int(c - base)); - } - c++; - - // Gather the flags, if any - for (flags = 0;; ++c) - { - if (*c == '-') - { - flags |= F_MINUS; // bit 0 - } - else if (*c == '+') - { - flags |= F_PLUS; // bit 1 - } - else if (*c == '0') - { - flags |= F_ZERO; // bit 2 - } - else if (*c == ' ') - { - flags |= F_BLANK; // bit 3 - } - else if (*c == '#') - { - flags |= F_HASH; // bit 4 - } - else - { - break; - } - } - - width = precision = -1; - - // Read the width, if any - if (*c == '*') - { - ++c; - width = va_arg (arglist, int); - if (width < 0) - { // Negative width means minus flag and positive width - flags |= F_MINUS; - width = -width; - } - } - else if (*c >= '0' && *c <= '9') - { - width = *c++ - '0'; - while (*c >= '0' && *c <= '9') - { - width = width * 10 + *c++ - '0'; - } - } - - // If 0 and - both appear, 0 is ignored. - // If the blank and + both appear, the blank is ignored. - flags &= ~((flags & 3) << 2); - - // Read the precision, if any - if (*c == '.') - { - precision = 0; - if (*++c == '*') - { - ++c; - precision = va_arg (arglist, int); - } - else if (*c >= '0' && *c <= '9') - { - precision = *c++ - '0'; - while (*c >= '0' && *c <= '9') - { - precision = precision * 10 + *c++ - '0'; - } - } - } - - // Read the size prefix, if any - if (*c == 'h') - { - if (*++c == 'h') - { - flags |= F_HALFHALF; - ++c; - } - else - { - flags |= F_HALF; - } - } - else if (*c == 'l') - { - if (*++c == 'l') - { - flags |= F_LONGLONG; - ++c; - } - else - { - flags |= F_LONG; - } - } - else if (*c == 'I') - { - if (*++c == '6') - { - if (*++c == '4') - { - flags |= F_LONGLONG; - ++c; - } - } - else - { - flags |= F_BIGI; - } - } - else if (*c == 't') - { - flags |= F_PTRDIFF; - ++c; - } - else if (*c == 'z') - { - flags |= F_SIZE; - ++c; - } - - base = c+1; - - // Now that that's all out of the way, we should be pointing at the type specifier - { - char prefix[3]; - int prefixlen; - char hexprefix = '\0'; - char sign = '\0'; - int postprefixzeros = 0; - int size = flags & 0xF000; - char buffer[80], *ibuff; - const char *obuff = 0; - char type = *c++; - int bufflen = 0; - int outlen = 0; - unsigned int intarg = 0; - uint64_t int64arg = 0; - const void *voidparg; - const char *charparg; - double dblarg; - const char *xits = hexits; - int inlen = len; - /* - * We can decompose the printed representation of floating - * point numbers into several parts, some of which may be empty: - * - * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ - * A B ---C--- D E F - * - * A: 'sign' holds this value if present; '\0' otherwise - * B: hexprefix holds the 'x' or 'X'; '\0' if not hexadecimal - * C: obuff points to the string MMMNNN. Leading and trailing - * zeros are not in the string and must be added. - * D: expchar holds this character; '\0' if no exponent, e.g. %f - * F: at least two digits for decimal, at least one digit for hex - */ - const char *decimal_point = ".";/* locale specific decimal point */ - int signflag; /* true if float is negative */ - int expt = 0; /* integer value of exponent */ - char expchar = 'e'; /* exponent character: [eEpP\0] */ - char* dtoaend = nullptr; /* pointer to end of converted digits */ - int expsize = 0; /* character count for expstr */ - int ndig = 0; /* actual number of digits returned by dtoa */ - char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ - char *dtoaresult = NULL; /* buffer allocated by dtoa */ - - // Using a bunch of if/else if statements is faster than a switch, because a switch generates - // a jump table. A jump table means a possible data cache miss and a hefty penalty while the - // cache line is loaded. - - if (type == 'x' || type == 'X' || - type == 'p' || - type == 'd' || type == 'u' || type == 'i' || - type == 'o' || - type == 'B') - { - if (type == 'X' || type == 'p') - { - xits = HEXits; - } - if (type == 'p') - { - type = 'X'; - voidparg = va_arg (arglist, void *); - if (sizeof(void*) == sizeof(int)) - { - intarg = (unsigned int)(size_t)voidparg; - precision = 8; - size = 0; - } - else - { - int64arg = (uint64_t)(size_t)voidparg; - precision = 16; - size = F_LONGLONG; - } - } - else - { - if (size == 0) - { - intarg = va_arg (arglist, int); - } - else if (size == F_HALFHALF) - { - intarg = va_arg (arglist, int); - intarg = (signed char)intarg; - } - else if (size == F_HALF) - { - intarg = va_arg (arglist, int); - intarg = (short)intarg; - } - else if (size == F_LONG) - { - if (sizeof(long) == sizeof(int)) intarg = va_arg (arglist, int); - else { int64arg = va_arg (arglist, int64_t); size = F_LONGLONG; } - } - else if (size == F_BIGI) - { - if (sizeof(void*) == sizeof(int)) intarg = va_arg (arglist, int); - else { int64arg = va_arg (arglist, int64_t); size = F_LONGLONG; } - } - else if (size == F_LONGLONG) - { - int64arg = va_arg (arglist, int64_t); - } - else if (size == F_PTRDIFF) - { - if (sizeof(ptrdiff_t) == sizeof(int)) intarg = va_arg (arglist, int); - else { int64arg = va_arg (arglist, int64_t); size = F_LONGLONG; } - } - else if (size == F_SIZE) - { - if (sizeof(size_t) == sizeof(int)) intarg = va_arg (arglist, int); - else { int64arg = va_arg (arglist, int64_t); size = F_LONGLONG; } - } - else - { - intarg = va_arg (arglist, int); - } - } - - if (precision < 0) precision = 1; - - ibuff = &buffer[sizeof(buffer)]; - - if (size == F_LONGLONG) - { - if (int64arg == 0) - { - flags |= F_ZEROVALUE; - } - else - { - if (type == 'o') - { // Octal: Dump digits until it fits in an unsigned int - while (int64arg > UINT_MAX) - { - *--ibuff = char(int64arg & 7) + '0'; int64arg >>= 3; - } - intarg = int(int64arg); - } - else if (type == 'x' || type == 'X') - { // Hexadecimal: Dump digits until it fits in an unsigned int - while (int64arg > UINT_MAX) - { - *--ibuff = xits[int64arg & 15]; int64arg >>= 4; - } - intarg = int(int64arg); - } - else if (type == 'B') - { // Binary: Dump digits until it fits in an unsigned int - while (int64arg > UINT_MAX) - { - *--ibuff = char(int64arg & 1) + '0'; int64arg >>= 1; - } - intarg = int(int64arg); - } - else - { - if (type != 'u') - { - // If a signed number is negative, set the negative flag and make it positive. - int64_t sint64arg = (int64_t)int64arg; - if (sint64arg < 0) - { - flags |= F_NEGATIVE; - sint64arg = -sint64arg; - int64arg = sint64arg; - } - flags |= F_SIGNED; - type = 'u'; - } - // If an unsigned int64 is too big to fit in an unsigned int, dump out - // digits until it is sufficiently small. - while (int64arg > INT_MAX) - { - *--ibuff = char(int64arg % 10) + '0'; int64arg /= 10; - } - intarg = (unsigned int)(int64arg); - } - } - } - else - { - if (intarg == 0) - { - flags |= F_ZEROVALUE; - } - else if (type == 'i' || type == 'd') - { // If a signed int is negative, set the negative flag and make it positive. - signed int sintarg = (signed int)intarg; - if (sintarg < 0) - { - flags |= F_NEGATIVE; - sintarg = -sintarg; - intarg = sintarg; - } - flags |= F_SIGNED; - type = 'u'; - } - } - if (flags & F_ZEROVALUE) - { - if (precision != 0) - { - *--ibuff = '0'; - } - } - else if (type == 'u') - { // Decimal - int i; - - // Unsigned division is typically slower than signed division. - // Do it at most once. - if (intarg > INT_MAX) - { - *--ibuff = char(intarg % 10) + '0'; intarg /= 10; - } - i = (int)intarg; - while (i != 0) - { - *--ibuff = char(i % 10) + '0'; i /= 10; - } - } - else if (type == 'o') - { // Octal - while (intarg != 0) - { - *--ibuff = char(intarg & 7) + '0'; intarg >>= 3; - } - } - else if (type == 'B') - { // Binary - while (intarg != 0) - { - *--ibuff = char(intarg & 1) + '0'; intarg >>= 1; - } - } - else - { // Hexadecimal - while (intarg != 0) - { - *--ibuff = xits[intarg & 15]; intarg >>= 4; - } - } - // Check for prefix (only for non-decimal, which are always unsigned) - if ((flags & (F_HASH|F_ZEROVALUE)) == F_HASH) - { - if (type == 'o') - { - if (bufflen >= precision) - { - sign = '0'; - } - } - else if (type == 'x' || type == 'X') - { - hexprefix = type; - } - else if (type == 'B') - { - hexprefix = '!'; - } - } - bufflen = (int)(ptrdiff_t)(&buffer[sizeof(buffer)] - ibuff); - obuff = ibuff; - if (precision >= 0) - { - postprefixzeros = precision - bufflen; - if (postprefixzeros < 0) postprefixzeros = 0; -// flags &= ~F_ZERO; - } - } - else if (type == 'c') - { - intarg = va_arg (arglist, int); - if (utf8_encode(intarg, (uint8_t*)buffer, &bufflen) != 0) - { - buffer[0] = '?'; - bufflen = 1; - } - obuff = buffer; - } - else if (type == 's') - { - charparg = va_arg (arglist, const char *); - if (charparg == NULL) - { - obuff = "(null)"; - bufflen = 6; - } - else - { - obuff = charparg; - if (precision < 0) - { - bufflen = (int)strlen (charparg); - } - else - { - for (bufflen = 0; bufflen < precision && charparg[bufflen] != '\0'; ++bufflen) - { /* empty */ } - } - } - } - else if (type == '%') - { // Just print a '%': Output it with the next stage. - base--; - continue; - } - else if (type == 'n') - { - if (size == F_HALFHALF) - { - *va_arg (arglist, char *) = (char)inlen; - } - else if (size == F_HALF) - { - *va_arg (arglist, short *) = (short)inlen; - } - else if (size == F_LONG) - { - *va_arg (arglist, long *) = inlen; - } - else if (size == F_LONGLONG) - { - *va_arg (arglist, int64_t *) = inlen; - } - else if (size == F_BIGI) - { - *va_arg (arglist, ptrdiff_t *) = inlen; - } - else - { - *va_arg (arglist, int *) = inlen; - } - } - else if (type == 'f' || type == 'F') - { - expchar = '\0'; - goto fp_begin; - } - else if (type == 'g' || type == 'G') - { - expchar = type - ('g' - 'e'); - if (precision == 0) - { - precision = 1; - } - goto fp_begin; - } - else if (type == 'H') - { // %H is an extension that behaves similarly to %g, except it automatically - // selects precision based on whatever will produce the smallest string. - expchar = 'e'; - goto fp_begin; - } -#if 0 - // The hdtoa function provided with FreeBSD uses a hexadecimal FP constant. - // Microsoft's compiler does not support these, so I would need to hack it - // together with ints instead. It's very do-able, but until I actually have - // some reason to print hex FP numbers, I won't bother. - else if (type == 'a' || type == 'A') - { - if (type == 'A') - { - xits = HEXits; - hexprefix = 'X'; - expchar = 'P'; - } - else - { - hexprefix = 'x'; - expchar = 'p'; - } - if (precision >= 0) - { - precision++; - } - dblarg = va_arg(arglist, double); - dtoaresult = obuff = hdtoa(dblarg, xits, precision, &expt, &signflag, &dtoaend); - if (precision < 0) - { - precision = (int)(dtoaend - obuff); - } - if (expt == INT_MAX) - { - hexprefix = '\0'; - } - goto fp_common; - } -#endif - else if (type == 'e' || type == 'E') - { - expchar = type; - if (precision < 0) // account for digit before decpt - { - precision = DEFPREC + 1; - } - else - { - precision++; - } -fp_begin: - if (precision < 0) - { - precision = DEFPREC; - } - dblarg = va_arg(arglist, double); - obuff = dtoaresult = dtoa(dblarg, type != 'H' ? (expchar ? 2 : 3) : 0, precision, &expt, &signflag, &dtoaend); -//fp_common: - decimal_point = localeconv()->decimal_point; - flags |= F_SIGNED; - if (signflag) - { - flags |= F_NEGATIVE; - } - if (expt == 9999) // inf or nan - { - if (*obuff == 'N') - { - obuff = (type >= 'a') ? "nan" : "NAN"; - flags &= ~F_SIGNED; - } - else - { - obuff = (type >= 'a') ? "inf" : "INF"; - } - bufflen = 3; - flags &= ~F_ZERO; - } - else - { - flags |= F_FPT; - ndig = (int)(dtoaend - obuff); - if (type == 'g' || type == 'G') - { - if (expt > -4 && expt <= precision) - { // Make %[gG] smell like %[fF]. - expchar = '\0'; - if (flags & F_HASH) - { - precision -= expt; - } - else - { - precision = ndig - expt; - } - if (precision < 0) - { - precision = 0; - } - } - else - { // Make %[gG] smell like %[eE], but trim trailing zeroes if no # flag. - if (!(flags & F_HASH)) - { - precision = ndig; - } - } - } - else if (type == 'H') - { - if (expt > -(ndig + 2) && expt <= (ndig + 4)) - { // Make %H smell like %f - expchar = '\0'; - precision = ndig - expt; - if (precision < 0) - { - precision = 0; - } - } - else - {// Make %H smell like %e - precision = ndig; - } - } - if (expchar) - { - expsize = exponent(expstr, expt - 1, expchar); - bufflen = expsize + precision; - if (precision > 1 || (flags & F_HASH)) - { - ++bufflen; - } - } - else - { // space for digits before decimal point - if (expt > 0) - { - bufflen = expt; - } - else // "0" - { - bufflen = 1; - } - // space for decimal pt and following digits - if (precision != 0 || (flags & F_HASH)) - { - bufflen += precision + 1; - } - } - } - } - - // Check for sign prefix (only for signed numbers) - if (flags & F_SIGNED) - { - if (flags & F_NEGATIVE) - { - sign = '-'; - } - else if (flags & F_PLUS) - { - sign = '+'; - } - else if (flags & F_BLANK) - { - sign = ' '; - } - } - - // Construct complete prefix from sign and hex prefix character - prefixlen = 0; - if (sign != '\0') - { - prefix[0] = sign; - prefixlen = 1; - } - if (hexprefix != '\0') - { - prefix[prefixlen] = '0'; - prefix[prefixlen + 1] = hexprefix; - prefixlen += 2; - } - - // Pad the output to the field width, if needed - int fieldlen = prefixlen + postprefixzeros + bufflen; - const char *pad = (flags & F_ZERO) ? zeroes : spaces; - - // If the output is right aligned and zero-padded, then the prefix must come before the padding. - if ((flags & (F_ZERO|F_MINUS)) == F_ZERO && prefixlen > 0) - { - outlen += output (outputData, prefix, prefixlen); - prefixlen = 0; - } - if (!(flags & F_MINUS) && fieldlen < width) - { // Field is right-justified, so padding comes first - outlen += writepad (output, outputData, pad, sizeof(spaces), width - fieldlen); - width = -1; - } - - // Output field: Prefix, post-prefix zeros, buffer text - if (prefixlen > 0) - { - outlen += output (outputData, prefix, prefixlen); - } - outlen += writepad (output, outputData, zeroes, sizeof(spaces), postprefixzeros); - if (!(flags & F_FPT)) - { - if (bufflen > 0) - { - outlen += output (outputData, obuff, bufflen); - } - } - else - { - if (expchar == '\0') // %[fF] or sufficiently short %[gG] - { - if (expt <= 0) - { - outlen += output (outputData, zeroes, 1); - if (precision != 0 || (flags & F_HASH)) - { - outlen += output (outputData, decimal_point, 1); - } - outlen += writepad (output, outputData, zeroes, sizeof(zeroes), -expt); - // already handled initial 0's - precision += expt; - } - else - { - outlen += printandpad (output, outputData, obuff, dtoaend, expt, zeroes, sizeof(zeroes)); - obuff += expt; - if (precision || (flags & F_HASH)) - { - outlen += output (outputData, decimal_point, 1); - } - } - outlen += printandpad (output, outputData, obuff, dtoaend, precision, zeroes, sizeof(zeroes)); - } - else // %[eE] or sufficiently long %[gG] - { - if (precision > 1 || (flags & F_HASH)) - { - buffer[0] = *obuff++; - buffer[1] = *decimal_point; - outlen += output (outputData, buffer, 2); - outlen += output (outputData, obuff, ndig - 1); - outlen += writepad (output, outputData, zeroes, sizeof(zeroes), precision - ndig); - } - else // XeYY - { - outlen += output (outputData, obuff, 1); - } - outlen += output (outputData, expstr, expsize); - } - } - - if ((flags & F_MINUS) && fieldlen < width) - { // Field is left-justified, so padding comes last - outlen += writepad (output, outputData, pad, sizeof(spaces), width - fieldlen); - } - len += outlen; - if (dtoaresult != NULL) - { - freedtoa(dtoaresult); - dtoaresult = NULL; - } - } - } - } - - static int writepad (OutputFunc output, void *outputData, const char *pad, int padsize, int spaceToFill) - { - int outlen = 0; - while (spaceToFill > 0) - { - int count = spaceToFill > padsize ? padsize : spaceToFill; - outlen += output (outputData, pad, count); - spaceToFill -= count; - } - return outlen; - } - - static int printandpad (OutputFunc output, void *outputData, const char *p, const char *ep, int len, const char *with, int padsize) - { - int outlen = 0; - int n2 = (int)(ep - p); - if (n2 > len) - { - n2 = len; - } - if (n2 > 0) - { - outlen = output (outputData, p, n2); - } - return outlen + writepad (output, outputData, with, padsize, len - (n2 > 0 ? n2 : 0)); - } - - static int exponent (char *p0, int exp, int fmtch) - { - char *p, *t; - char expbuf[MAXEXPDIG]; - - p = p0; - *p++ = fmtch; - if (exp < 0) - { - exp = -exp; - *p++ = '-'; - } - else - { - *p++ = '+'; - } - t = expbuf + MAXEXPDIG; - if (exp > 9) - { - do - { - *--t = '0' + (exp % 10); - } - while ((exp /= 10) > 9); - *--t = '0' + exp; - for(; t < expbuf + MAXEXPDIG; *p++ = *t++) - { } - } - else - { - // Exponents for decimal floating point conversions - // (%[eEgG]) must be at least two characters long, - // whereas exponents for hexadecimal conversions can - // be only one character long. - if (fmtch == 'e' || fmtch == 'E') - { - *p++ = '0'; - } - *p++ = '0' + exp; - } - return (int)(p - p0); - } -}; - -//========================================================================// -// snprintf / vsnprintf imitations - -#ifdef __GNUC__ -#define GCCPRINTF(stri,firstargi) __attribute__((format(printf,stri,firstargi))) -#define GCCFORMAT(stri) __attribute__((format(printf,stri,0))) -#define GCCNOWARN __attribute__((unused)) -#else -#define GCCPRINTF(a,b) -#define GCCFORMAT(a) -#define GCCNOWARN -#endif - -struct snprintf_state -{ - char *buffer; - size_t maxlen; - size_t curlen; - int ideallen; -}; - -static int myvsnprintf_helper(void *data, const char *cstr, int cstr_len) -{ - snprintf_state *state = (snprintf_state *)data; - - if (INT_MAX - cstr_len < state->ideallen) - { - state->ideallen = INT_MAX; - } - else - { - state->ideallen += cstr_len; - } - if (state->curlen + cstr_len > state->maxlen) - { - cstr_len = (int)(state->maxlen - state->curlen); - } - if (cstr_len > 0) - { - memcpy(state->buffer + state->curlen, cstr, cstr_len); - state->curlen += cstr_len; - } - return cstr_len; -} - -extern "C" -{ - -// Unlike the MS CRT function snprintf, this one always writes a terminating -// null character to the buffer. It also returns the full length of the string -// that would have been output if the buffer had been large enough. In other -// words, it follows BSD/Linux rules and not MS rules. -int myvsnprintf(char *buffer, size_t count, const char *format, va_list argptr) -{ - size_t originalcount = count; - if (count != 0) - { - count--; - } - if (count > INT_MAX) - { // This is probably an error. Output nothing. - originalcount = 0; - count = 0; - } - snprintf_state state = { buffer, count, 0, 0 }; - StringFormat::VWorker(myvsnprintf_helper, &state, format, argptr); - if (originalcount > 0) - { - buffer[state.curlen] = '\0'; - } - return state.ideallen; -} - -int mysnprintf(char *buffer, size_t count, const char *format, ...) -{ - va_list argptr; - va_start(argptr, format); - int len = myvsnprintf(buffer, count, format, argptr); - va_end(argptr); - return len; -} - -} diff --git a/src/common/utility/zstring.cpp b/src/common/utility/zstring.cpp index 2b3c4f1fe1..ecd0dc7e63 100644 --- a/src/common/utility/zstring.cpp +++ b/src/common/utility/zstring.cpp @@ -39,6 +39,7 @@ #include "zstring.h" #include "utf8.h" +#include "stb_sprintf.h" extern uint16_t lowerforupper[65536]; extern uint16_t upperforlower[65536]; @@ -216,7 +217,7 @@ FString &FString::operator = (const FString &other) return *this; } -FString &FString::operator = (FString &&other) +FString &FString::operator = (FString &&other) noexcept { assert (Chars != NULL); @@ -274,25 +275,28 @@ void FString::Format (const char *fmt, ...) void FString::AppendFormat (const char *fmt, ...) { + char workbuf[STB_SPRINTF_MIN]; va_list arglist; va_start (arglist, fmt); - StringFormat::VWorker (FormatHelper, this, fmt, arglist); + stbsp_vsprintfcb(FormatHelper, this, workbuf, fmt, arglist); va_end (arglist); } void FString::VFormat (const char *fmt, va_list arglist) { + char workbuf[STB_SPRINTF_MIN]; Data()->Release(); Chars = (char *)(FStringData::Alloc(128) + 1); - StringFormat::VWorker (FormatHelper, this, fmt, arglist); + stbsp_vsprintfcb(FormatHelper, this, workbuf, fmt, arglist); } void FString::VAppendFormat (const char *fmt, va_list arglist) { - StringFormat::VWorker (FormatHelper, this, fmt, arglist); + char workbuf[STB_SPRINTF_MIN]; + stbsp_vsprintfcb(FormatHelper, this, workbuf, fmt, arglist); } -int FString::FormatHelper (void *data, const char *cstr, int len) +char* FString::FormatHelper (const char *cstr, void* data, int len) { FString *str = (FString *)data; size_t len1 = str->Len(); @@ -302,7 +306,7 @@ int FString::FormatHelper (void *data, const char *cstr, int len) } StrCopy (str->Chars + len1, cstr, len); str->Data()->Len = (unsigned int)(len1 + len); - return len; + return (char*)cstr; } FString FString::operator + (const FString &tail) const @@ -599,7 +603,7 @@ ptrdiff_t FString::LastIndexOfAny (const FString &charset) const ptrdiff_t FString::LastIndexOfAny (const char *charset) const { - return LastIndexOfAny (charset, long(Len())); + return LastIndexOfAny (charset, ptrdiff_t(Len())); } ptrdiff_t FString::LastIndexOfAny (const FString &charset, ptrdiff_t endIndex) const @@ -838,12 +842,12 @@ void FString::StripLeftRight () if (max == 0) return; for (i = 0; i < max; ++i) { - if (Chars[i] < 0 || !isspace((unsigned char)Chars[i])) + if ((signed char)Chars[i] < 0 || !isspace((unsigned char)Chars[i])) break; } for (j = max - 1; j >= i; --j) { - if (Chars[j] < 0 || !isspace((unsigned char)Chars[j])) + if ((signed char)Chars[j] < 0 || !isspace((unsigned char)Chars[j])) break; } if (i == 0 && j == max - 1) @@ -1322,19 +1326,6 @@ FString &FString::operator=(const wchar_t *copyStr) return *this; } -std::wstring WideString(const char *cin) -{ - if (!cin) return L""; - const uint8_t *in = (const uint8_t*)cin; - // This is a bit tricky because we need to support both UTF-8 and legacy content in ISO-8859-1 - // and thanks to user-side string manipulation it can be that a text mixes both. - // To convert the string this uses the same function as all text printing in the engine. - TArray buildbuffer; - while (*in) buildbuffer.Push((wchar_t)GetCharFromString(in)); - buildbuffer.Push(0); - return std::wstring(buildbuffer.Data()); -} - static HANDLE StringHeap; const SIZE_T STRING_HEAP_SIZE = 64*1024; #endif diff --git a/src/common/utility/zstring.h b/src/common/utility/zstring.h index 4640d5c287..93d6790215 100644 --- a/src/common/utility/zstring.h +++ b/src/common/utility/zstring.h @@ -39,6 +39,8 @@ #include #include #include "tarray.h" +#include "utf8.h" +#include "filesystem.h" #ifdef __GNUC__ #define PRINTFISH(x) __attribute__((format(printf, 2, x))) @@ -57,10 +59,6 @@ #define IGNORE_FORMAT_POST #endif -#ifdef _WIN32 -std::wstring WideString(const char *); -#endif - struct FStringData { unsigned int Len; // Length of string, excluding terminating null @@ -127,7 +125,7 @@ class FString // Copy constructors FString (const FString &other) { AttachToOther (other); } - FString (FString &&other) : Chars(other.Chars) { other.ResetToNull(); } + FString (FString &&other) noexcept : Chars(other.Chars) { other.ResetToNull(); } FString (const char *copyStr); FString (const char *copyStr, size_t copyLen); FString (char oneChar); @@ -148,9 +146,6 @@ class FString FString (const char *head, const char *tail); FString (char head, const FString &tail); - // Other constructors - FString (ELumpNum); // Create from a lump - ~FString (); // Discard string's contents, create a new buffer, and lock it. @@ -168,8 +163,6 @@ class FString explicit operator bool() = delete; // this is needed to render the operator const char * ineffective when used in boolean constructs. bool operator !() = delete; - operator const char *() const { return Chars; } - const char *GetChars() const { return Chars; } const char &operator[] (int index) const { return Chars[index]; } @@ -186,7 +179,7 @@ class FString const char &operator[] (unsigned long long index) const { return Chars[index]; } FString &operator = (const FString &other); - FString &operator = (FString &&other); + FString &operator = (FString &&other) noexcept; FString &operator = (const char *copyStr); FString operator + (const FString &tail) const; @@ -331,13 +324,13 @@ class FString int Compare (const FString &other) const { return strcmp (Chars, other.Chars); } int Compare (const char *other) const { return strcmp (Chars, other); } - int Compare(const FString &other, int len) const { return strncmp(Chars, other.Chars, len); } - int Compare(const char *other, int len) const { return strncmp(Chars, other, len); } + int Compare(const FString &other, size_t len) const { return strncmp(Chars, other.Chars, len); } + int Compare(const char *other, size_t len) const { return strncmp(Chars, other, len); } int CompareNoCase (const FString &other) const { return stricmp (Chars, other.Chars); } int CompareNoCase (const char *other) const { return stricmp (Chars, other); } - int CompareNoCase(const FString &other, int len) const { return strnicmp(Chars, other.Chars, len); } - int CompareNoCase(const char *other, int len) const { return strnicmp(Chars, other, len); } + int CompareNoCase(const FString &other, size_t len) const { return strnicmp(Chars, other.Chars, len); } + int CompareNoCase(const char *other, size_t len) const { return strnicmp(Chars, other, len); } enum EmptyTokenType { @@ -364,7 +357,7 @@ class FString void AllocBuffer (size_t len); void ReallocBuffer (size_t newlen); - static int FormatHelper (void *data, const char *str, int len); + static char* FormatHelper (const char *str, void* data, int len); static void StrCopy (char *to, const char *from, size_t len); static void StrCopy (char *to, const FString &from); @@ -431,6 +424,7 @@ class FStringf : public FString }; +/* namespace StringFormat { enum @@ -461,6 +455,7 @@ namespace StringFormat int VWorker (OutputFunc output, void *outputData, const char *fmt, va_list arglist); int Worker (OutputFunc output, void *outputData, const char *fmt, ...); }; +*/ #undef PRINTFISH diff --git a/src/common/widgets/errorwindow.cpp b/src/common/widgets/errorwindow.cpp new file mode 100644 index 0000000000..d74864bb67 --- /dev/null +++ b/src/common/widgets/errorwindow.cpp @@ -0,0 +1,325 @@ + +#include "errorwindow.h" +#include "version.h" +#include "v_font.h" +#include "printf.h" +#include +#include +#include +#include +#include + +bool ErrorWindow::ExecModal(const std::string& text, const std::string& log, std::vector minidump) +{ + Size screenSize = GetScreenSize(); + double windowWidth = 1200.0; + double windowHeight = 700.0; + + auto window = std::make_unique(std::move(minidump)); + window->SetText(text, log); + window->SetFrameGeometry((screenSize.width - windowWidth) * 0.5, (screenSize.height - windowHeight) * 0.5, windowWidth, windowHeight); + window->Show(); + + DisplayWindow::RunLoop(); + + return window->Restart; +} + +ErrorWindow::ErrorWindow(std::vector initminidump) : Widget(nullptr, WidgetType::Window), minidump(std::move(initminidump)) +{ + FStringf caption("Fatal Error - " GAMENAME " %s (%s)", GetVersionString(), GetGitTime()); + SetWindowTitle(caption.GetChars()); + SetWindowBackground(Colorf::fromRgba8(51, 51, 51)); + SetWindowBorderColor(Colorf::fromRgba8(51, 51, 51)); + SetWindowCaptionColor(Colorf::fromRgba8(33, 33, 33)); + SetWindowCaptionTextColor(Colorf::fromRgba8(226, 223, 219)); + + LogView = new LogViewer(this); + ClipboardButton = new PushButton(this); + ClipboardButton->OnClick = [=]() { OnClipboardButtonClicked(); }; + ClipboardButton->SetText("Copy to clipboard"); + + if (minidump.empty()) + { + RestartButton = new PushButton(this); + RestartButton->OnClick = [=]() { OnRestartButtonClicked(); }; + RestartButton->SetText("Restart"); + } + else + { + SaveReportButton = new PushButton(this); + SaveReportButton->OnClick = [=]() { OnSaveReportButtonClicked(); }; + SaveReportButton->SetText("Save Report"); + } + + LogView->SetFocus(); +} + +void ErrorWindow::SetText(const std::string& text, const std::string& log) +{ + LogView->SetText(text, log); + + clipboardtext.clear(); + clipboardtext.reserve(log.size() + text.size() + 100); + + // Strip the color escapes from the log + const uint8_t* cptr = (const uint8_t*)log.data(); + while (int chr = GetCharFromString(cptr)) + { + if (chr != TEXTCOLOR_ESCAPE) + { + // The bar characters, most commonly used to indicate map changes + if (chr >= 0x1D && chr <= 0x1F) + { + chr = 0x2550; // Box Drawings Double Horizontal + } + clipboardtext += MakeUTF8(chr); + } + } + + clipboardtext += "\nExecution could not continue.\n"; + clipboardtext += text; + clipboardtext += "\n"; +} + +void ErrorWindow::OnClipboardButtonClicked() +{ + SetClipboardText(clipboardtext); +} + +void ErrorWindow::OnRestartButtonClicked() +{ + Restart = true; + DisplayWindow::ExitLoop(); +} + +void ErrorWindow::OnSaveReportButtonClicked() +{ + auto dialog = SaveFileDialog::Create(this); + dialog->AddFilter("Crash Report Zip Files", "*.zip"); + dialog->AddFilter("All Files", "*.*"); + dialog->SetFilename("CrashReport.zip"); + dialog->SetDefaultExtension("zip"); + if (dialog->Show()) + { + std::string filename = dialog->Filename(); + + mz_zip_archive zip = {}; + if (mz_zip_writer_init_heap(&zip, 0, 16 * 1024 * 1024)) + { + mz_zip_writer_add_mem(&zip, "minidump.dmp", minidump.data(), minidump.size(), MZ_DEFAULT_COMPRESSION); + mz_zip_writer_add_mem(&zip, "log.txt", clipboardtext.data(), clipboardtext.size(), MZ_DEFAULT_COMPRESSION); + } + void* buffer = nullptr; + size_t buffersize = 0; + mz_zip_writer_finalize_heap_archive(&zip, &buffer, &buffersize); + mz_zip_writer_end(&zip); + + std::unique_ptr f(FileWriter::Open(filename.c_str())); + if (f) + { + f->Write(buffer, buffersize); + f->Close(); + } + } +} + +void ErrorWindow::OnClose() +{ + Restart = false; + DisplayWindow::ExitLoop(); +} + +void ErrorWindow::OnGeometryChanged() +{ + double w = GetWidth(); + double h = GetHeight(); + + double y = GetHeight() - 15.0 - ClipboardButton->GetPreferredHeight(); + ClipboardButton->SetFrameGeometry(20.0, y, 170.0, ClipboardButton->GetPreferredHeight()); + if (RestartButton) + RestartButton->SetFrameGeometry(GetWidth() - 20.0 - 100.0, y, 100.0, RestartButton->GetPreferredHeight()); + else if (SaveReportButton) + SaveReportButton->SetFrameGeometry(GetWidth() - 20.0 - 100.0, y, 100.0, SaveReportButton->GetPreferredHeight()); + y -= 20.0; + + LogView->SetFrameGeometry(Rect::xywh(0.0, 0.0, w, y)); +} + +///////////////////////////////////////////////////////////////////////////// + +LogViewer::LogViewer(Widget* parent) : Widget(parent) +{ + SetNoncontentSizes(8.0, 8.0, 3.0, 8.0); + + scrollbar = new Scrollbar(this); + scrollbar->FuncScroll = [=]() { OnScrollbarScroll(); }; +} + +void LogViewer::SetText(const std::string& text, const std::string& log) +{ + lines.clear(); + + std::string::size_type start = 0; + std::string::size_type end = log.find('\n'); + while (end != std::string::npos) + { + lines.push_back(CreateLineLayout(log.substr(start, end - start))); + start = end + 1; + end = log.find('\n', start); + } + + lines.push_back(CreateLineLayout(log.substr(start))); + + // Add an empty line as a bit of spacing + lines.push_back(CreateLineLayout({})); + + SpanLayout layout; + //layout.AddImage(Image::LoadResource("widgets/erroricon.svg"), -8.0); + layout.AddText("Execution could not continue.", largefont, Colorf::fromRgba8(255, 170, 170)); + lines.push_back(layout); + + layout.Clear(); + layout.AddText(text, largefont, Colorf::fromRgba8(255, 255, 170)); + lines.push_back(layout); + + scrollbar->SetRanges(0.0, (double)lines.size(), 1.0, 100.0); + scrollbar->SetPosition((double)lines.size() - 1.0); + + Update(); +} + +SpanLayout LogViewer::CreateLineLayout(const std::string& text) +{ + SpanLayout layout; + + Colorf curcolor = Colorf::fromRgba8(255, 255, 255); + std::string curtext; + + const uint8_t* cptr = (const uint8_t*)text.data(); + while (int chr = GetCharFromString(cptr)) + { + if (chr != TEXTCOLOR_ESCAPE) + { + // The bar characters, most commonly used to indicate map changes + if (chr >= 0x1D && chr <= 0x1F) + { + chr = 0x2550; // Box Drawings Double Horizontal + } + curtext += MakeUTF8(chr); + } + else + { + EColorRange range = V_ParseFontColor(cptr, CR_UNTRANSLATED, CR_YELLOW); + if (range != CR_UNDEFINED) + { + if (!curtext.empty()) + layout.AddText(curtext, font, curcolor); + curtext.clear(); + + PalEntry color = V_LogColorFromColorRange(range); + curcolor = Colorf::fromRgba8(color.r, color.g, color.b); + } + } + } + + curtext.push_back(' '); + layout.AddText(curtext, font, curcolor); + + return layout; +} + +void LogViewer::OnPaintFrame(Canvas* canvas) +{ + double w = GetFrameGeometry().width; + double h = GetFrameGeometry().height; + Colorf bordercolor = Colorf::fromRgba8(100, 100, 100); + canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(38, 38, 38)); + //canvas->fillRect(Rect::xywh(0.0, 0.0, w, 1.0), bordercolor); + //canvas->fillRect(Rect::xywh(0.0, h - 1.0, w, 1.0), bordercolor); + //canvas->fillRect(Rect::xywh(0.0, 0.0, 1.0, h - 0.0), bordercolor); + //canvas->fillRect(Rect::xywh(w - 1.0, 0.0, 1.0, h - 0.0), bordercolor); +} + +void LogViewer::OnPaint(Canvas* canvas) +{ + double width = GetWidth() - scrollbar->GetFrameGeometry().width; + double y = GetHeight(); + size_t start = std::min((size_t)std::round(scrollbar->GetPosition() + 1.0), lines.size()); + for (size_t i = start; i > 0 && y > 0.0; i--) + { + SpanLayout& layout = lines[i - 1]; + layout.Layout(canvas, width); + layout.SetPosition(Point(0.0, y - layout.GetSize().height)); + layout.DrawLayout(canvas); + y -= layout.GetSize().height; + } +} + +bool LogViewer::OnMouseWheel(const Point& pos, InputKey key) +{ + if (key == InputKey::MouseWheelUp) + { + ScrollUp(4); + } + else if (key == InputKey::MouseWheelDown) + { + ScrollDown(4); + } + return true; +} + +void LogViewer::OnKeyDown(InputKey key) +{ + if (key == InputKey::Home) + { + scrollbar->SetPosition(0.0f); + Update(); + } + if (key == InputKey::End) + { + scrollbar->SetPosition(scrollbar->GetMax()); + Update(); + } + else if (key == InputKey::PageUp) + { + ScrollUp(20); + } + else if (key == InputKey::PageDown) + { + ScrollDown(20); + } + else if (key == InputKey::Up) + { + ScrollUp(4); + } + else if (key == InputKey::Down) + { + ScrollDown(4); + } +} + +void LogViewer::OnScrollbarScroll() +{ + Update(); +} + +void LogViewer::OnGeometryChanged() +{ + double w = GetWidth(); + double h = GetHeight(); + double sw = scrollbar->GetPreferredWidth(); + scrollbar->SetFrameGeometry(Rect::xywh(w - sw, 0.0, sw, h)); +} + +void LogViewer::ScrollUp(int lines) +{ + scrollbar->SetPosition(std::max(scrollbar->GetPosition() - (double)lines, 0.0)); + Update(); +} + +void LogViewer::ScrollDown(int lines) +{ + scrollbar->SetPosition(std::min(scrollbar->GetPosition() + (double)lines, scrollbar->GetMax())); + Update(); +} diff --git a/src/common/widgets/errorwindow.h b/src/common/widgets/errorwindow.h new file mode 100644 index 0000000000..1cb9b236d1 --- /dev/null +++ b/src/common/widgets/errorwindow.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include + +class LogViewer; +class PushButton; +class Scrollbar; + +class ErrorWindow : public Widget +{ +public: + static bool ExecModal(const std::string& text, const std::string& log, std::vector minidump = {}); + + ErrorWindow(std::vector minidump); + + bool Restart = false; + +protected: + void OnClose() override; + void OnGeometryChanged() override; + +private: + void SetText(const std::string& text, const std::string& log); + + void OnClipboardButtonClicked(); + void OnRestartButtonClicked(); + void OnSaveReportButtonClicked(); + + LogViewer* LogView = nullptr; + PushButton* ClipboardButton = nullptr; + PushButton* RestartButton = nullptr; + PushButton* SaveReportButton = nullptr; + + std::vector minidump; + std::string clipboardtext; +}; + +class LogViewer : public Widget +{ +public: + LogViewer(Widget* parent); + + void SetText(const std::string& text, const std::string& log); + +protected: + void OnPaintFrame(Canvas* canvas) override; + void OnPaint(Canvas* canvas) override; + bool OnMouseWheel(const Point& pos, InputKey key) override; + void OnKeyDown(InputKey key) override; + void OnGeometryChanged() override; + +private: + void OnScrollbarScroll(); + void ScrollUp(int lines); + void ScrollDown(int lines); + + SpanLayout CreateLineLayout(const std::string& text); + + Scrollbar* scrollbar = nullptr; + + std::shared_ptr largefont = Font::Create("Poppins", 16.0); + std::shared_ptr font = Font::Create("Poppins", 12.0); + std::vector lines; +}; diff --git a/src/common/widgets/netstartwindow.cpp b/src/common/widgets/netstartwindow.cpp new file mode 100644 index 0000000000..69c83e5654 --- /dev/null +++ b/src/common/widgets/netstartwindow.cpp @@ -0,0 +1,152 @@ + +#include "netstartwindow.h" +#include "version.h" +#include "engineerrors.h" +#include "gstrings.h" +#include +#include +#include + +NetStartWindow* NetStartWindow::Instance = nullptr; + +void NetStartWindow::ShowNetStartPane(const char* message, int maxpos) +{ + Size screenSize = GetScreenSize(); + double windowWidth = 300.0; + double windowHeight = 150.0; + + if (!Instance) + { + Instance = new NetStartWindow(); + Instance->SetFrameGeometry((screenSize.width - windowWidth) * 0.5, (screenSize.height - windowHeight) * 0.5, windowWidth, windowHeight); + Instance->Show(); + } + + Instance->SetMessage(message, maxpos); +} + +void NetStartWindow::HideNetStartPane() +{ + delete Instance; + Instance = nullptr; +} + +void NetStartWindow::SetNetStartProgress(int pos) +{ + if (Instance) + Instance->SetProgress(pos); +} + +bool NetStartWindow::RunMessageLoop(bool (*newtimer_callback)(void*), void* newuserdata) +{ + if (!Instance) + return false; + + Instance->timer_callback = newtimer_callback; + Instance->userdata = newuserdata; + Instance->CallbackException = {}; + + DisplayWindow::RunLoop(); + + Instance->timer_callback = nullptr; + Instance->userdata = nullptr; + + if (Instance->CallbackException) + std::rethrow_exception(Instance->CallbackException); + + // Even though the comment in FBasicStartupScreen::NetLoop says we should return false, the old code actually throws an exception! + // This effectively also means the function always returns true... + if (!Instance->exitreason) + { + throw CExitEvent(0); + } + + return Instance->exitreason; +} + +NetStartWindow::NetStartWindow() : Widget(nullptr, WidgetType::Window) +{ + SetWindowBackground(Colorf::fromRgba8(51, 51, 51)); + SetWindowBorderColor(Colorf::fromRgba8(51, 51, 51)); + SetWindowCaptionColor(Colorf::fromRgba8(33, 33, 33)); + SetWindowCaptionTextColor(Colorf::fromRgba8(226, 223, 219)); + SetWindowTitle(GAMENAME); + + MessageLabel = new TextLabel(this); + ProgressLabel = new TextLabel(this); + AbortButton = new PushButton(this); + + MessageLabel->SetTextAlignment(TextLabelAlignment::Center); + ProgressLabel->SetTextAlignment(TextLabelAlignment::Center); + + AbortButton->OnClick = [=]() { OnClose(); }; + + AbortButton->SetText("Abort Network Game"); + + CallbackTimer = new Timer(this); + CallbackTimer->FuncExpired = [=]() { OnCallbackTimerExpired(); }; + CallbackTimer->Start(500); +} + +void NetStartWindow::SetMessage(const std::string& message, int newmaxpos) +{ + MessageLabel->SetText(message); + maxpos = newmaxpos; +} + +void NetStartWindow::SetProgress(int newpos) +{ + if (pos != newpos && maxpos > 1) + { + pos = newpos; + FString message; + message.Format("%d/%d", pos, maxpos); + ProgressLabel->SetText(message.GetChars()); + } +} + +void NetStartWindow::OnClose() +{ + exitreason = false; + DisplayWindow::ExitLoop(); +} + +void NetStartWindow::OnGeometryChanged() +{ + double w = GetWidth(); + double h = GetHeight(); + + double y = 15.0; + double labelheight = MessageLabel->GetPreferredHeight(); + MessageLabel->SetFrameGeometry(Rect::xywh(5.0, y, w - 10.0, labelheight)); + y += labelheight; + + labelheight = ProgressLabel->GetPreferredHeight(); + ProgressLabel->SetFrameGeometry(Rect::xywh(5.0, y, w - 10.0, labelheight)); + y += labelheight; + + y = GetHeight() - 15.0 - AbortButton->GetPreferredHeight(); + AbortButton->SetFrameGeometry((w - 200.0) * 0.5, y, 200.0, AbortButton->GetPreferredHeight()); +} + +void NetStartWindow::OnCallbackTimerExpired() +{ + if (timer_callback) + { + bool result = false; + try + { + result = timer_callback(userdata); + } + catch (...) + { + CallbackException = std::current_exception(); + } + + if (result) + { + exitreason = true; + DisplayWindow::ExitLoop(); + } + } +} diff --git a/src/common/widgets/netstartwindow.h b/src/common/widgets/netstartwindow.h new file mode 100644 index 0000000000..5d27b8ebfc --- /dev/null +++ b/src/common/widgets/netstartwindow.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +class TextLabel; +class PushButton; +class Timer; + +class NetStartWindow : public Widget +{ +public: + static void ShowNetStartPane(const char* message, int maxpos); + static void HideNetStartPane(); + static void SetNetStartProgress(int pos); + static bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata); + +private: + NetStartWindow(); + + void SetMessage(const std::string& message, int maxpos); + void SetProgress(int pos); + +protected: + void OnClose() override; + void OnGeometryChanged() override; + +private: + void OnCallbackTimerExpired(); + + TextLabel* MessageLabel = nullptr; + TextLabel* ProgressLabel = nullptr; + PushButton* AbortButton = nullptr; + + Timer* CallbackTimer = nullptr; + + int pos = 0; + int maxpos = 1; + bool (*timer_callback)(void*) = nullptr; + void* userdata = nullptr; + + bool exitreason = false; + + std::exception_ptr CallbackException; + + static NetStartWindow* Instance; +}; diff --git a/src/common/widgets/widgetresourcedata.cpp b/src/common/widgets/widgetresourcedata.cpp new file mode 100644 index 0000000000..522f4ff1ee --- /dev/null +++ b/src/common/widgets/widgetresourcedata.cpp @@ -0,0 +1,91 @@ + +#include +#include +#include "filesystem.h" +#include "printf.h" +#include "zstring.h" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +FResourceFile* WidgetResources; + +void InitWidgetResources(const char* filename) +{ + WidgetResources = FResourceFile::OpenResourceFile(filename); + if (!WidgetResources) + I_FatalError("Unable to open %s", filename); + + WidgetTheme::SetTheme(std::make_unique()); +} + +void CloseWidgetResources() +{ + if (WidgetResources) delete WidgetResources; +} + +static std::vector LoadFile(const char* name) +{ + auto lump = WidgetResources->FindEntry(name); + if (lump == -1) + I_FatalError("Unable to find %s", name); + + auto reader = WidgetResources->GetEntryReader(lump, FileSys::READER_SHARED); + std::vector buffer(reader.GetLength()); + reader.Read(buffer.data(), buffer.size()); + return buffer; +} + +// this must be allowed to fail without throwing. +static std::vector LoadDiskFile(const char* name) +{ + std::vector buffer; + FileSys::FileReader lump; + if (lump.OpenFile(name)) + { + buffer.resize(lump.GetLength()); + lump.Read(buffer.data(), buffer.size()); + } + return buffer; +} + +// This interface will later require some significant redesign. +std::vector LoadWidgetFontData(const std::string& name) +{ + std::vector returnv; + if (!stricmp(name.c_str(), "notosans")) + { + returnv.resize(3); + returnv[0].fontdata = LoadFile("widgets/noto/notosans-regular.ttf"); + returnv[1].fontdata = LoadFile("widgets/noto/notosansarmenian-regular.ttf"); + returnv[2].fontdata = LoadFile("widgets/noto/notosansgeorgian-regular.ttf"); +#ifdef _WIN32 + wchar_t wbuffer[256]; + if (GetWindowsDirectoryW(wbuffer, 256)) + { + returnv.resize(5); + FString windir(wbuffer); + returnv[3].fontdata = LoadDiskFile((windir + "/fonts/yugothm.ttc").GetChars()); + returnv[3].language = "ja"; + returnv[4].fontdata = LoadDiskFile((windir + "/fonts/malgun.ttf").GetChars()); + returnv[4].language = "ko"; + // Don't fail if these cannot be found + if (returnv[4].fontdata.size() == 0) returnv.erase(returnv.begin() + 4); + if (returnv[3].fontdata.size() == 0) returnv.erase(returnv.begin() + 3); + } +#endif + return returnv; + + } + returnv.resize(1); + std::string fn = "widgets/font/" +name + ".ttf"; + returnv[0].fontdata = LoadFile(fn.c_str()); + return returnv; +} + +std::vector LoadWidgetData(const std::string& name) +{ + return LoadFile(name.c_str()); +} diff --git a/src/console/c_cmds.cpp b/src/console/c_cmds.cpp index f9dc42f39c..1ea9fe771a 100644 --- a/src/console/c_cmds.cpp +++ b/src/console/c_cmds.cpp @@ -120,8 +120,8 @@ CCMD (god) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_GOD); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_GOD); } CCMD(god2) @@ -129,8 +129,8 @@ CCMD(god2) if (CheckCheatmode()) return; - Net_WriteByte(DEM_GENERICCHEAT); - Net_WriteByte(CHT_GOD2); + Net_WriteInt8(DEM_GENERICCHEAT); + Net_WriteInt8(CHT_GOD2); } CCMD (iddqd) @@ -138,8 +138,8 @@ CCMD (iddqd) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_IDDQD); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_IDDQD); } CCMD (buddha) @@ -147,8 +147,8 @@ CCMD (buddha) if (CheckCheatmode()) return; - Net_WriteByte(DEM_GENERICCHEAT); - Net_WriteByte(CHT_BUDDHA); + Net_WriteInt8(DEM_GENERICCHEAT); + Net_WriteInt8(CHT_BUDDHA); } CCMD(buddha2) @@ -156,8 +156,8 @@ CCMD(buddha2) if (CheckCheatmode()) return; - Net_WriteByte(DEM_GENERICCHEAT); - Net_WriteByte(CHT_BUDDHA2); + Net_WriteInt8(DEM_GENERICCHEAT); + Net_WriteInt8(CHT_BUDDHA2); } CCMD (notarget) @@ -165,8 +165,8 @@ CCMD (notarget) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_NOTARGET); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_NOTARGET); } CCMD (fly) @@ -174,8 +174,8 @@ CCMD (fly) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_FLY); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_FLY); } /* @@ -190,8 +190,8 @@ CCMD (noclip) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_NOCLIP); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_NOCLIP); } CCMD (noclip2) @@ -199,8 +199,8 @@ CCMD (noclip2) if (CheckCheatmode()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_NOCLIP2); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_NOCLIP2); } CCMD (powerup) @@ -208,8 +208,8 @@ CCMD (powerup) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_POWER); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_POWER); } CCMD (morphme) @@ -219,12 +219,12 @@ CCMD (morphme) if (argv.argc() == 1) { - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_MORPH); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_MORPH); } else { - Net_WriteByte (DEM_MORPHEX); + Net_WriteInt8 (DEM_MORPHEX); Net_WriteString (argv[1]); } } @@ -234,8 +234,8 @@ CCMD (anubis) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_ANUBIS); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_ANUBIS); } // [GRB] @@ -244,8 +244,8 @@ CCMD (resurrect) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_RESSURECT); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_RESSURECT); } EXTERN_CVAR (Bool, chasedemo) @@ -276,8 +276,8 @@ CCMD (chase) if (gamestate != GS_LEVEL || (!(dmflags2 & DF2_CHASECAM) && deathmatch && CheckCheatmode ())) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_CHASECAM); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_CHASECAM); } } @@ -309,12 +309,12 @@ CCMD (idclev) // Catch invalid maps. mapname = CalcMapName (epsd, map); - if (!P_CheckMapData(mapname)) + if (!P_CheckMapData(mapname.GetChars())) return; // So be it. - Printf ("%s\n", GStrings("STSTR_CLEV")); - G_DeferedInitNew (mapname); + Printf ("%s\n", GStrings.GetString("STSTR_CLEV")); + G_DeferedInitNew (mapname.GetChars()); //players[0].health = 0; // Force reset } } @@ -334,11 +334,11 @@ CCMD (hxvisit) { // Just because it's in MAPINFO doesn't mean it's in the wad. - if (P_CheckMapData(mapname)) + if (P_CheckMapData(mapname.GetChars())) { // So be it. - Printf ("%s\n", GStrings("STSTR_CLEV")); - G_DeferedInitNew (mapname); + Printf ("%s\n", GStrings.GetString("STSTR_CLEV")); + G_DeferedInitNew (mapname.GetChars()); return; } } @@ -386,12 +386,12 @@ CCMD (changemap) { if (argv.argc() > 2) { - Net_WriteByte (DEM_CHANGEMAP2); - Net_WriteByte (atoi(argv[2])); + Net_WriteInt8 (DEM_CHANGEMAP2); + Net_WriteInt8 (atoi(argv[2])); } else { - Net_WriteByte (DEM_CHANGEMAP); + Net_WriteInt8 (DEM_CHANGEMAP); } Net_WriteString (mapname); } @@ -425,7 +425,7 @@ CCMD (changeskill) if (argv.argc() == 2) { int skill = atoi(argv[1]); - if (skill < 0 || skill >= AllSkills.Size()) + if ((unsigned)skill >= AllSkills.Size()) { Printf ("Skill %d is out of range.\n", skill); } @@ -446,12 +446,12 @@ CCMD (give) if (CheckCheatmode () || argv.argc() < 2) return; - Net_WriteByte (DEM_GIVECHEAT); + Net_WriteInt8 (DEM_GIVECHEAT); Net_WriteString (argv[1]); if (argv.argc() > 2) - Net_WriteLong(atoi(argv[2])); + Net_WriteInt32(atoi(argv[2])); else - Net_WriteLong(0); + Net_WriteInt32(0); } CCMD (take) @@ -459,12 +459,12 @@ CCMD (take) if (CheckCheatmode () || argv.argc() < 2) return; - Net_WriteByte (DEM_TAKECHEAT); + Net_WriteInt8 (DEM_TAKECHEAT); Net_WriteString (argv[1]); if (argv.argc() > 2) - Net_WriteLong(atoi (argv[2])); + Net_WriteInt32(atoi (argv[2])); else - Net_WriteLong (0); + Net_WriteInt32 (0); } CCMD(setinv) @@ -472,17 +472,17 @@ CCMD(setinv) if (CheckCheatmode() || argv.argc() < 2) return; - Net_WriteByte(DEM_SETINV); + Net_WriteInt8(DEM_SETINV); Net_WriteString(argv[1]); if (argv.argc() > 2) - Net_WriteLong(atoi(argv[2])); + Net_WriteInt32(atoi(argv[2])); else - Net_WriteLong(0); + Net_WriteInt32(0); if (argv.argc() > 3) - Net_WriteByte(!!atoi(argv[3])); + Net_WriteInt8(!!atoi(argv[3])); else - Net_WriteByte(0); + Net_WriteInt8(0); } @@ -513,18 +513,18 @@ CCMD (puke) if (script > 0) { - Net_WriteByte (DEM_RUNSCRIPT); - Net_WriteWord (script); + Net_WriteInt8 (DEM_RUNSCRIPT); + Net_WriteInt16 (script); } else { - Net_WriteByte (DEM_RUNSCRIPT2); - Net_WriteWord (-script); + Net_WriteInt8 (DEM_RUNSCRIPT2); + Net_WriteInt16 (-script); } - Net_WriteByte (argn); + Net_WriteInt8 (argn); for (i = 0; i < argn; ++i) { - Net_WriteLong (arg[i]); + Net_WriteInt32 (arg[i]); } } } @@ -557,12 +557,12 @@ CCMD (pukename) arg[i] = atoi(argv[argstart + i]); } } - Net_WriteByte(DEM_RUNNAMEDSCRIPT); + Net_WriteInt8(DEM_RUNNAMEDSCRIPT); Net_WriteString(argv[1]); - Net_WriteByte(argn | (always << 7)); + Net_WriteInt8(argn | (always << 7)); for (i = 0; i < argn; ++i) { - Net_WriteLong(arg[i]); + Net_WriteInt32(arg[i]); } } } @@ -603,12 +603,12 @@ CCMD (special) return; } } - Net_WriteByte(DEM_RUNSPECIAL); - Net_WriteWord(specnum); - Net_WriteByte(argc - 2); + Net_WriteInt8(DEM_RUNSPECIAL); + Net_WriteInt16(specnum); + Net_WriteInt8(argc - 2); for (int i = 2; i < argc; ++i) { - Net_WriteLong(atoi(argv[i])); + Net_WriteInt32(atoi(argv[i])); } } } @@ -639,10 +639,10 @@ CCMD (warp) } else { - Net_WriteByte (DEM_WARPCHEAT); - Net_WriteWord (atoi (argv[1])); - Net_WriteWord (atoi (argv[2])); - Net_WriteWord (argv.argc() == 3 ? ONFLOORZ/65536 : atoi (argv[3])); + Net_WriteInt8 (DEM_WARPCHEAT); + Net_WriteInt16 (atoi (argv[1])); + Net_WriteInt16 (atoi (argv[2])); + Net_WriteInt16 (argv.argc() == 3 ? ONFLOORZ/65536 : atoi (argv[3])); } } @@ -686,8 +686,8 @@ UNSAFE_CCMD (load) return; } #endif - fname = G_BuildSaveName(fname); - G_LoadGame (fname); + fname = G_BuildSaveName(fname.GetChars()); + G_LoadGame (fname.GetChars()); } //========================================================================== @@ -700,9 +700,9 @@ UNSAFE_CCMD (load) UNSAFE_CCMD(save) { - if ((primaryLevel->flags9 & LEVEL9_NOUSERSAVE)) + if ((primaryLevel->vkdflags & VKDLEVELFLAG_NOUSERSAVE)) { - Printf("%s\n", GStrings("SAVEDEAD")); + Printf("%s\n", GStrings.GetString("SAVEDEAD")); return; } @@ -731,8 +731,8 @@ UNSAFE_CCMD(save) return; } #endif - fname = G_BuildSaveName(fname); - G_SaveGame (fname, argv.argc() > 2 ? argv[2] : argv[1]); + fname = G_BuildSaveName(fname.GetChars()); + G_SaveGame (fname.GetChars(), argv.argc() > 2 ? argv[2] : argv[1]); } @@ -957,8 +957,8 @@ CCMD(thaw) if (CheckCheatmode()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_CLEARFROZENPROPS); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_CLEARFROZENPROPS); } //----------------------------------------------------------------------------- @@ -977,7 +977,7 @@ CCMD(nextmap) if (primaryLevel->NextMap.Len() > 0 && primaryLevel->NextMap.Compare("enDSeQ", 6)) { - G_DeferedInitNew(primaryLevel->NextMap); + G_DeferedInitNew(primaryLevel->NextMap.GetChars()); } else { @@ -1001,7 +1001,7 @@ CCMD(nextsecret) if (primaryLevel->NextSecretMap.Len() > 0 && primaryLevel->NextSecretMap.Compare("enDSeQ", 6)) { - G_DeferedInitNew(primaryLevel->NextSecretMap); + G_DeferedInitNew(primaryLevel->NextSecretMap.GetChars()); } else { @@ -1055,7 +1055,7 @@ static void PrintSecretString(const char *string, bool thislevel) } else if (string[1] == 'T' || string[1] == 't') { - long tid = (long)strtoll(string+2, (char**)&string, 10); + int tid = (int)strtoll(string+2, (char**)&string, 10); if (*string == ';') string++; auto it = primaryLevel->GetActorIterator(tid); AActor *actor; @@ -1073,7 +1073,7 @@ static void PrintSecretString(const char *string, bool thislevel) else colstr = TEXTCOLOR_GREEN; } } - auto brok = V_BreakLines(CurrentConsoleFont, twod->GetWidth()*95/100, *string == '$' ? GStrings(++string) : string); + auto brok = V_BreakLines(CurrentConsoleFont, twod->GetWidth()*95/100, *string == '$' ? GStrings.GetString(++string) : string); for (auto &line : brok) { @@ -1091,7 +1091,7 @@ static void PrintSecretString(const char *string, bool thislevel) CCMD(secret) { const char *mapname = argv.argc() < 2? primaryLevel->MapName.GetChars() : argv[1]; - bool thislevel = !stricmp(mapname, primaryLevel->MapName); + bool thislevel = !stricmp(mapname, primaryLevel->MapName.GetChars()); bool foundsome = false; int lumpno=fileSystem.CheckNumForName("SECRETS"); @@ -1111,13 +1111,13 @@ CCMD(secret) { if (readbuffer[0] == '[') { - inlevel = !strnicmp(readbuffer, maphdr, maphdr.Len()); + inlevel = !strnicmp(readbuffer, maphdr.GetChars(), maphdr.Len()); if (!foundsome) { FString levelname; level_info_t *info = FindLevelInfo(mapname); - const char *ln = !(info->flags & LEVEL_LOOKUPLEVELNAME)? info->LevelName.GetChars() : GStrings[info->LevelName.GetChars()]; - levelname.Format("%s - %s", mapname, ln); + FString ln = info->LookupLevelName(); + levelname.Format("%s - %s", mapname, ln.GetChars()); Printf(TEXTCOLOR_YELLOW "%s\n", levelname.GetChars()); size_t llen = levelname.Len(); levelname = ""; @@ -1138,7 +1138,7 @@ CCMD(secret) // line complete so print it. linebuild.Substitute("\r", ""); linebuild.StripRight(" \t\n"); - PrintSecretString(linebuild, thislevel); + PrintSecretString(linebuild.GetChars(), thislevel); linebuild = ""; } } @@ -1206,7 +1206,7 @@ CCMD(idmus) } else { - Printf("%s\n", GStrings("STSTR_NOMUS")); + Printf("%s\n", GStrings.GetString("STSTR_NOMUS")); return; } } @@ -1215,17 +1215,17 @@ CCMD(idmus) map = CalcMapName(argv[1][0] - '0', argv[1][1] - '0'); } - if ((info = FindLevelInfo(map))) + if ((info = FindLevelInfo(map.GetChars()))) { if (info->Music.IsNotEmpty()) { - S_ChangeMusic(info->Music, info->musicorder); - Printf("%s\n", GStrings("STSTR_MUS")); + S_ChangeMusic(info->Music.GetChars(), info->musicorder); + Printf("%s\n", GStrings.GetString("STSTR_MUS")); } } else { - Printf("%s\n", GStrings("STSTR_NOMUS")); + Printf("%s\n", GStrings.GetString("STSTR_NOMUS")); } } } @@ -1276,3 +1276,85 @@ CCMD(dumpactors) } } } + +const char* testlocalised(const char* in) +{ + const char *out = GStrings.GetLanguageString(in, FStringTable::default_table); + if (in[0] == '$') + out = GStrings.GetLanguageString(in + 1, FStringTable::default_table); + if (out) + return out; + return in; +} + +CCMD (mapinfo) +{ + level_info_t *myLevel = nullptr; + if (players[consoleplayer].mo && players[consoleplayer].mo->Level) + myLevel = players[consoleplayer].mo->Level->info; + + if (argv.argc() > 1) + { + if (P_CheckMapData(argv[1])) + myLevel = FindLevelInfo(argv[1]); + else + { + Printf("Mapname '%s' not found\n", argv[1]); + return; + } + } + + if (!myLevel) + { + Printf("Not in a level\n"); + return; + } + + Printf("[ Map Info For: '%s' ]\n\n", myLevel->MapName.GetChars()); + + if (myLevel->LevelName.IsNotEmpty()) + Printf(" LevelName: %s\n", myLevel->LookupLevelName().GetChars()); + + if (myLevel->AuthorName.IsNotEmpty()) + Printf(" AuthorName: %s\n", testlocalised(myLevel->AuthorName.GetChars())); + + if (myLevel->levelnum) + Printf(" LevelNum: %i\n", myLevel->levelnum); + + if (myLevel->NextMap.IsNotEmpty()) + Printf(" Next: %s\n", myLevel->NextMap.GetChars()); + + if (myLevel->NextSecretMap.IsNotEmpty()) + Printf(" SecretNext: %s\n", myLevel->NextSecretMap.GetChars()); + + if (myLevel->Music.IsNotEmpty()) + Printf(" Music: %s%s\n", myLevel->Music[0] == '$'? "D_" : "", testlocalised(myLevel->Music.GetChars())); + + Printf(" PixelStretch: %f\n", myLevel->pixelstretch); + + if (myLevel->RedirectType != NAME_None) + Printf(" Redirect (Item): %s\n", myLevel->RedirectType.GetChars()); + + if (myLevel->RedirectMapName.IsNotEmpty()) + Printf(" Redirect (Map): %s\n", myLevel->RedirectMapName.GetChars()); + + if (myLevel->RedirectCVAR != NAME_None) + Printf("CVAR_Redirect (CVAR): %s\n", myLevel->RedirectCVAR.GetChars()); + + if (myLevel->RedirectCVARMapName.IsNotEmpty()) + Printf(" CVAR_Redirect (Map): %s\n", myLevel->RedirectCVARMapName.GetChars()); + + Printf(" LightMode: %i\n", (int8_t)myLevel->lightmode); + + if (players[consoleplayer].mo && players[consoleplayer].mo->Level) + { + level_info_t *check = myLevel->CheckLevelRedirect(); + if (check) + Printf("Level IS currently being redirected to '%s'!\n", check->MapName.GetChars()); + else + Printf("Level is currently NOT being redirected!\n"); + } + else + Printf("Level redirection is currently not being tested - not in game!\n"); +} + diff --git a/src/console/c_notifybuffer.cpp b/src/console/c_notifybuffer.cpp index d25b320e43..4c394c376a 100644 --- a/src/console/c_notifybuffer.cpp +++ b/src/console/c_notifybuffer.cpp @@ -146,7 +146,7 @@ void FNotifyBuffer::Draw() int scale = active_con_scaletext(twod, generic_ui); if (!center) - DrawText(twod, font, color, 0, line, notify.Text, + DrawText(twod, font, color, 0, line, notify.Text.GetChars(), DTA_VirtualWidth, twod->GetWidth() / scale, DTA_VirtualHeight, twod->GetHeight() / scale, DTA_KeepRatio, true, @@ -154,7 +154,7 @@ void FNotifyBuffer::Draw() else DrawText(twod, font, color, (twod->GetWidth() - font->StringWidth (notify.Text) * scale) / 2 / scale, - line, notify.Text, + line, notify.Text.GetChars(), DTA_VirtualWidth, twod->GetWidth() / scale, DTA_VirtualHeight, twod->GetHeight() / scale, DTA_KeepRatio, true, diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index 5f16a872a0..e5368f83e1 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -173,7 +173,7 @@ bool CT_Responder (event_t *ev) else if (ev->data1 == 'V' && (ev->data3 & GKM_CTRL)) #endif // __APPLE__ { - CT_PasteChat(I_GetFromClipboard(false)); + CT_PasteChat(I_GetFromClipboard(false).GetChars()); } } else if (ev->subtype == EV_GUI_Char) @@ -193,7 +193,7 @@ bool CT_Responder (event_t *ev) #ifdef __unix__ else if (ev->subtype == EV_GUI_MButtonDown) { - CT_PasteChat(I_GetFromClipboard(true)); + CT_PasteChat(I_GetFromClipboard(true).GetChars()); } #endif } @@ -261,7 +261,7 @@ void CT_Drawer (void) if (!!rv) return; } - FStringf prompt("%s ", GStrings("TXT_SAY")); + FStringf prompt("%s ", GStrings.GetString("TXT_SAY")); int x, scalex, y, promptwidth; y = (viewactive || gamestate != GS_LEVEL) ? -displayfont->GetHeight()-2 : -displayfont->GetHeight() - 22; @@ -291,7 +291,7 @@ void CT_Drawer (void) DrawText(drawer, displayfont, CR_GREEN, 0, y, prompt.GetChars(), DTA_VirtualWidth, screen_width, DTA_VirtualHeight, screen_height, DTA_KeepRatio, true, TAG_DONE); - DrawText(drawer, displayfont, CR_GREY, promptwidth, y, printstr, + DrawText(drawer, displayfont, CR_GREY, promptwidth, y, printstr.GetChars(), DTA_VirtualWidth, screen_width, DTA_VirtualHeight, screen_height, DTA_KeepRatio, true, TAG_DONE); } } @@ -371,17 +371,16 @@ static void ShoveChatStr (const char *str, uint8_t who) who |= 2; } - Net_WriteByte (DEM_SAY); - Net_WriteByte (who); + Net_WriteInt8 (DEM_SAY); + Net_WriteInt8 (who); - if (!chat_substitution || !DoSubstitution (substBuff, str)) + if (chat_substitution && DoSubstitution (substBuff, str)) { - Net_WriteString(MakeUTF8(str)); - } - else - { - Net_WriteString(MakeUTF8(substBuff)); + str = substBuff.GetChars(); } + + Net_WriteString(CleanseString(const_cast(MakeUTF8(str)))); + } //=========================================================================== diff --git a/src/d_anonstats.cpp b/src/d_anonstats.cpp index 48762bd6d6..b302ad189f 100644 --- a/src/d_anonstats.cpp +++ b/src/d_anonstats.cpp @@ -16,8 +16,9 @@ void D_ConfirmSendStats() #define WIN32_LEAN_AND_MEAN #include #include -extern int sys_ostype; +extern const char* sys_ostype; #else +extern FString sys_ostype; #ifdef __APPLE__ #include #else // !__APPLE__ @@ -38,15 +39,16 @@ extern int sys_ostype; #include "gl_interface.h" #include "printf.h" -CVAR(Int, sys_statsenabled49, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) -CVAR(String, sys_statshost, "gzstats.drdteam.org", CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) -CVAR(Int, sys_statsport, 80, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) +CVAR(Int, anonstats_enabled411, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) +CVAR(String, anonstats_host, "gzstats.drdteam.org", CVAR_NOSET) +CVAR(Int, anonstats_port, 80, CVAR_NOSET) #define CHECKVERSION 490 #define CHECKVERSIONSTR "490" CVAR(Int, sentstats_hwr_done, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) std::pair gl_getInfo(); +extern int vkversion; @@ -69,13 +71,16 @@ FString URLencode(const char *s) return out; } +// accept FString inputs too +FString URLencode(FString s) +{ + return URLencode(s.GetChars()); +} + #ifdef _WIN32 bool I_HTTPRequest(const char* request) { - if ((*sys_statshost)[0] == 0) - return false; // no host, disable - WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { @@ -84,20 +89,20 @@ bool I_HTTPRequest(const char* request) } SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct hostent *host; - host = gethostbyname(sys_statshost); + host = gethostbyname(anonstats_host); if (host == nullptr) { DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); return false; } SOCKADDR_IN SockAddr; - SockAddr.sin_port = htons(sys_statsport); + SockAddr.sin_port = htons(anonstats_port); SockAddr.sin_family = AF_INET; SockAddr.sin_addr.s_addr = *((uint32_t*)host->h_addr); - DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", *sys_statshost); + DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", *anonstats_host); if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0) { - DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", *sys_statshost); + DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", *anonstats_host); return false; } send(Socket, request, (int)strlen(request), 0); @@ -119,14 +124,14 @@ bool I_HTTPRequest(const char* request) #else bool I_HTTPRequest(const char* request) { - if ((*sys_statshost)[0] == 0) + if ((*anonstats_host)[0] == 0) return false; // no host, disable int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; - portno = sys_statsport; + portno = anonstats_port; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) @@ -135,7 +140,7 @@ bool I_HTTPRequest(const char* request) return false; } - server = gethostbyname(sys_statshost); + server = gethostbyname(anonstats_host); if (server == NULL) { DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); @@ -148,10 +153,10 @@ bool I_HTTPRequest(const char* request) server->h_length); serv_addr.sin_port = htons(portno); - DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", *sys_statshost); + DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", *anonstats_host); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", *sys_statshost); + DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", *anonstats_host); return false; } @@ -171,48 +176,28 @@ bool I_HTTPRequest(const char* request) } #endif -static int GetOSVersion() +static FString GetOSVersion() { #ifdef _WIN32 #ifndef _M_ARM64 - if (sizeof(void*) == 4) // 32 bit - { - BOOL res; - if (IsWow64Process(GetCurrentProcess(), &res) && res) - { - return 1; - } - return 0; - } - else - { - if (sys_ostype == 2) return 2; - else return 3; - } + return FStringf("Windows %s", sys_ostype); #else - return 4; + return FStringf("Windows %s ARM", sys_ostype); #endif #elif defined __APPLE__ #if defined(__aarch64__) - return 6; + return sys_ostype + " ARM"; #else - return 5; + return sys_ostype + " x64"; #endif #else // fall-through linux stuff here #ifdef __arm__ - return 9; + return sys_ostype + " ARM"; #else - if (sizeof(void*) == 4) // 32 bit - { - return 7; - } - else - { - return 8; - } + return sys_ostype; #endif @@ -265,7 +250,7 @@ static int GetCoreInfo() static int GetRenderInfo() { - if (screen->Backend() == 0) return 1; + if (screen->Backend() == 2) return 1; if (screen->Backend() == 1) return 4; auto info = gl_getInfo(); if (!info.second) @@ -277,7 +262,7 @@ static int GetRenderInfo() static int GetGLVersion() { - if (screen->Backend() == 1) return 50; + if (screen->Backend() == 1) return vkversion; auto info = gl_getInfo(); return int(info.first * 10); } @@ -290,11 +275,57 @@ static void D_DoHTTPRequest(const char *request) } } + +static FString GetDeviceName() +{ + FString device = screen->DeviceName(); + if (device.Compare("AMD Radeon(TM) Graphics") == 0 || + device.Compare("Intel(R) UHD Graphics") == 0 || + //device.Compare("Intel(R) HD Graphics") == 0 || these are not that interesting so leave them alone + device.Compare("Intel(R) Iris(R) Plus Graphics") == 0 || + device.Compare("Intel(R) Iris(R) Xe Graphics") == 0 || + device.Compare("Radeon RX Vega") == 0 || + device.Compare("AMD Radeon Series") == 0) + { + // for these anonymous series names add the CPU name to get an idea what GPU we really have + auto ci = DumpCPUInfo(&CPU, true); + device.AppendFormat(" * %s", ci.GetChars()); + } + // cleanse the GPU info string to allow better searches on the database. + device.Substitute("/SSE2", ""); + device.Substitute("/PCIe", ""); + device.Substitute("/PCI", ""); + device.Substitute("(TM) ", ""); + device.Substitute("Mesa ", ""); + device.Substitute("DRI ", ""); + auto pos = device.IndexOf("Intel(R)"); + if (pos >= 0) + { + device.Substitute("(R) ", ""); + auto pos = device.IndexOf("("); + if (pos >= 0) device.Truncate(pos); + } + + pos = device.IndexOf("(LLVM"); + if (pos >= 0) device.Truncate(pos); + pos = device.IndexOf("(DRM"); + if (pos >= 0) device.Truncate(pos); + pos = device.IndexOf("(RADV"); + if (pos >= 0) device.Truncate(pos); + pos = device.IndexOf(", LLVM"); + if (pos >= 0) + { + device.Truncate(pos); + device << ')'; + } + device.StripLeftRight(); + return device; +} void D_DoAnonStats() { #ifndef _DEBUG // Do not repeat if already sent. - if (sys_statsenabled49 != 1 || sentstats_hwr_done >= CHECKVERSION) + if (anonstats_enabled411 != 1 || sentstats_hwr_done >= CHECKVERSION) { return; } @@ -306,8 +337,8 @@ void D_DoAnonStats() static char requeststring[1024]; - mysnprintf(requeststring, sizeof requeststring, "GET /stats_202109.py?render=%i&cores=%i&os=%i&glversion=%i&vendor=%s&model=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nUser-Agent: %s %s\r\n\r\n", - GetRenderInfo(), GetCoreInfo(), GetOSVersion(), GetGLVersion(), URLencode(screen->vendorstring).GetChars(), URLencode(screen->DeviceName()).GetChars(), *sys_statshost, GAMENAME, VERSIONSTR); + mysnprintf(requeststring, sizeof requeststring, "GET /stats_202309.py?render=%i&cores=%i&os=%s&glversion=%i&vendor=%s&model=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nUser-Agent: %s %s\r\n\r\n", + GetRenderInfo(), GetCoreInfo(), URLencode(GetOSVersion()).GetChars(), GetGLVersion(), URLencode(screen->vendorstring).GetChars(), URLencode(GetDeviceName()).GetChars(), *anonstats_host, GAMENAME, VERSIONSTR); DPrintf(DMSG_NOTIFY, "Sending %s", requeststring); #if 1//ndef _DEBUG // Don't send info in debug builds @@ -320,7 +351,7 @@ void D_DoAnonStats() void D_ConfirmSendStats() { - if (sys_statsenabled49 >= 0) + if (anonstats_enabled411 >= 0) { return; } @@ -376,7 +407,7 @@ void D_ConfirmSendStats() enabled.Int = SDL_ShowMessageBox(&messageboxdata, &buttonid) == 0 && buttonid == 0; #endif // _WIN32 - sys_statsenabled49->ForceSet(enabled, CVAR_Int); + anonstats_enabled411->ForceSet(enabled, CVAR_Int); } #endif // NO_SEND_STATS diff --git a/src/d_defcvars.cpp b/src/d_defcvars.cpp index 7e12e01506..3a1985070b 100644 --- a/src/d_defcvars.cpp +++ b/src/d_defcvars.cpp @@ -81,17 +81,17 @@ void D_GrabCVarDefaults() CurrentFindCVar.ToLower(); // these two got renamed - if (strcmp(CurrentFindCVar, "gamma") == 0) + if (CurrentFindCVar.Compare("gamma") == 0) { CurrentFindCVar = "vid_gamma"; } - if (strcmp(CurrentFindCVar, "fullscreen") == 0) + if (CurrentFindCVar.Compare("fullscreen") == 0) { CurrentFindCVar = "vid_fullscreen"; } // this was removed - if (strcmp(CurrentFindCVar, "cd_drive") == 0) + if (CurrentFindCVar.Compare("cd_drive") == 0) break; } if (lumpversion < 221) @@ -100,9 +100,9 @@ void D_GrabCVarDefaults() // this one doesn't matter as much, since it depended on platform-specific values, // and is something the user should change anyhow, so, let's just throw this value // out. - if (strcmp(CurrentFindCVar, "mouse_sensitivity") == 0) + if (CurrentFindCVar.Compare("mouse_sensitivity") == 0) break; - if (strcmp(CurrentFindCVar, "m_noprescale") == 0) + if (CurrentFindCVar.Compare("m_noprescale") == 0) break; } @@ -123,12 +123,15 @@ void D_GrabCVarDefaults() SHOULD_BLACKLIST(vid_adapter) SHOULD_BLACKLIST(sys_statsenabled47) SHOULD_BLACKLIST(sys_statsenabled49) + SHOULD_BLACKLIST(anonstats_statsenabled411) SHOULD_BLACKLIST(save_dir) SHOULD_BLACKLIST(sys_statsport) SHOULD_BLACKLIST(sys_statshost) + SHOULD_BLACKLIST(anonstats_port) + SHOULD_BLACKLIST(anonstats_host) SHOULD_BLACKLIST(sentstats_hwr_done) - var = FindCVar(CurrentFindCVar, NULL); + var = FindCVar(CurrentFindCVar.GetChars(), NULL); if (blacklisted) { diff --git a/src/d_defcvars.h b/src/d_defcvars.h index 73f110c707..caaca508ba 100644 --- a/src/d_defcvars.h +++ b/src/d_defcvars.h @@ -19,9 +19,10 @@ // defcvars loader split from d_main.cpp // //----------------------------------------------------------------------------- +#pragma once #define SHOULD_BLACKLIST(name) \ if (#name[0]==CurrentFindCVar[0]) \ - if (strcmp(CurrentFindCVar, #name) == 0) \ + if (CurrentFindCVar.Compare(#name) == 0) \ blacklisted = true; diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 431c37813c..f1495febcd 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -46,8 +46,10 @@ #include "version.h" #include "engineerrors.h" #include "v_text.h" +#include "fs_findfile.h" #include "findfile.h" #include "i_interface.h" +#include "gstrings.h" EXTERN_CVAR(Bool, queryiwad); EXTERN_CVAR(String, defaultiwad); @@ -55,6 +57,7 @@ EXTERN_CVAR(Bool, disableautoload) EXTERN_CVAR(Bool, autoloadlights) EXTERN_CVAR(Bool, autoloadbrightmaps) EXTERN_CVAR(Bool, autoloadwidescreen) +EXTERN_CVAR(String, language) //========================================================================== // @@ -148,6 +151,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, else if(sc.Compare("Extended")) iwad->flags |= GI_MENUHACK_EXTENDED; else if(sc.Compare("Shorttex")) iwad->flags |= GI_COMPATSHORTTEX; else if(sc.Compare("Stairs")) iwad->flags |= GI_COMPATSTAIRS; + else if (sc.Compare("nosectionmerge")) iwad->flags |= GI_NOSECTIONMERGE; else sc.ScriptError(NULL); } while (sc.CheckString(",")); @@ -298,24 +302,28 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, // Look for IWAD definition lump // //========================================================================== -void GetReserved(LumpFilterInfo& lfi); +void GetReserved(FileSys::LumpFilterInfo& lfi); FIWadManager::FIWadManager(const char *firstfn, const char *optfn) { FileSystem check; - TArray fns; - fns.Push(firstfn); - if (optfn) fns.Push(optfn); + std::vector fns; + fns.push_back(firstfn); + if (optfn) fns.push_back(optfn); + FileSys::LumpFilterInfo lfi; + GetReserved(lfi); - check.InitMultipleFiles(fns, true); - if (check.GetNumEntries() > 0) + if (check.InitMultipleFiles(fns, &lfi, nullptr)) { + // this is for the IWAD picker. As we have a filesystem open here that contains the base files, it is the easiest place to load the strings early. + GStrings.LoadStrings(check, language); int num = check.CheckNumForName("IWADINFO"); if (num >= 0) { - auto data = check.GetFileData(num); - ParseIWadInfo("IWADINFO", (const char*)data.Data(), data.Size()); + auto data = check.ReadFile(num); + ParseIWadInfo("IWADINFO", data.string(), (int)data.size()); } + } } @@ -330,7 +338,7 @@ FIWadManager::FIWadManager(const char *firstfn, const char *optfn) int FIWadManager::ScanIWAD (const char *iwad) { FileSystem check; - check.InitSingleFile(iwad, true); + check.InitSingleFile(iwad, nullptr); mLumpsFound.Resize(mIWadInfos.Size()); @@ -359,7 +367,7 @@ int FIWadManager::ScanIWAD (const char *iwad) if (full && strnicmp(full, "maps/", 5) == 0) { FString mapname(&full[5], strcspn(&full[5], ".")); - CheckFileName(mapname); + CheckFileName(mapname.GetChars()); } } } @@ -384,13 +392,11 @@ int FIWadManager::CheckIWADInfo(const char* fn) { FileSystem check; - LumpFilterInfo lfi; + FileSys::LumpFilterInfo lfi; GetReserved(lfi); - TArray filenames; - filenames.Push(fn); - check.InitMultipleFiles(filenames, true, &lfi); - if (check.GetNumEntries() > 0) + std::vector filenames = { fn }; + if (check.InitMultipleFiles(filenames, &lfi, nullptr)) { int num = check.CheckNumForName("IWADINFO"); if (num >= 0) @@ -399,8 +405,8 @@ int FIWadManager::CheckIWADInfo(const char* fn) { FIWADInfo result; - auto data = check.GetFileData(num); - ParseIWadInfo(fn, (const char*)data.Data(), data.Size(), &result); + auto data = check.ReadFile(num); + ParseIWadInfo(fn, data.string(), (int)data.size(), &result); for (unsigned i = 0, count = mIWadInfos.Size(); i < count; ++i) { @@ -472,36 +478,32 @@ void FIWadManager::CollectSearchPaths() void FIWadManager::AddIWADCandidates(const char *dir) { - void *handle; - findstate_t findstate; - FStringf slasheddir("%s/", dir); - FString findmask = slasheddir + "*.*"; - if ((handle = I_FindFirst(findmask, &findstate)) != (void *)-1) + FileSys::FileList list; + + if (FileSys::ScanDirectory(list, dir, "*", true)) { - do + for(auto& entry : list) { - if (!(I_FindAttr(&findstate) & FA_DIREC)) + if (!entry.isDirectory) { - auto FindName = I_FindName(&findstate); - auto p = strrchr(FindName, '.'); + auto p = strrchr(entry.FileName.c_str(), '.'); if (p != nullptr) { // special IWAD extension. if (!stricmp(p, ".iwad") || !stricmp(p, ".ipk3") || !stricmp(p, ".ipk7")) { - mFoundWads.Push(FFoundWadInfo{ slasheddir + FindName, "", -1 }); + mFoundWads.Push(FFoundWadInfo{ entry.FilePath.c_str(), "", -1 }); } } for (auto &name : mIWadNames) { - if (!stricmp(name, FindName)) + if (!name.CompareNoCase(entry.FileName.c_str())) { - mFoundWads.Push(FFoundWadInfo{ slasheddir + FindName, "", -1 }); + mFoundWads.Push(FFoundWadInfo{ entry.FilePath.c_str(), "", -1 }); } } } - } while (I_FindNext(handle, &findstate) == 0); - I_FindClose(handle); + } } } @@ -520,14 +522,14 @@ void FIWadManager::ValidateIWADs() for (auto &p : mFoundWads) { int index; - auto x = strrchr(p.mFullPath, '.'); + auto x = strrchr(p.mFullPath.GetChars(), '.'); if (x != nullptr && (!stricmp(x, ".iwad") || !stricmp(x, ".ipk3") || !stricmp(x, ".ipk7"))) { - index = CheckIWADInfo(p.mFullPath); + index = CheckIWADInfo(p.mFullPath.GetChars()); } else { - index = ScanIWAD(p.mFullPath); + index = ScanIWAD(p.mFullPath.GetChars()); } p.mInfoIndex = index; } @@ -556,7 +558,7 @@ void FIWadManager::ValidateIWADs() static bool havepicked = false; -int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, const char *zdoom_wad, const char *optional_wad) +int FIWadManager::IdentifyVersion (std::vector&wadfiles, const char *iwad, const char *zdoom_wad, const char *optional_wad) { const char *iwadparm = Args->CheckValue ("-iwad"); FString custwad; @@ -566,7 +568,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, // Collect all IWADs in the search path for (auto &dir : mSearchPaths) { - AddIWADCandidates(dir); + AddIWADCandidates(dir.GetChars()); } unsigned numFoundWads = mFoundWads.Size(); @@ -613,7 +615,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, // Check for symbolic links leading to non-existent files and for files that are unreadable. for (unsigned int i = 0; i < mFoundWads.Size(); i++) { - if (!FileExists(mFoundWads[i].mFullPath) || !FileReadable(mFoundWads[i].mFullPath)) mFoundWads.Delete(i); + if (!FileExists(mFoundWads[i].mFullPath) || !FileReadable(mFoundWads[i].mFullPath.GetChars())) mFoundWads.Delete(i--); } // Now check if what got collected actually is an IWAD. @@ -734,7 +736,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, for (unsigned i = 0; i < picks.Size(); ++i) { FString &basename = mIWadInfos[picks[i].mInfoIndex].Name; - if (stricmp(basename, defaultiwad) == 0) + if (basename.CompareNoCase(defaultiwad) == 0) { pick = i; break; @@ -750,7 +752,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, { WadStuff stuff; stuff.Name = mIWadInfos[found.mInfoIndex].Name; - stuff.Path = ExtractFileBase(found.mFullPath); + stuff.Path = ExtractFileBase(found.mFullPath.GetChars()); wads.Push(stuff); } int flags = 0;; @@ -769,7 +771,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, autoloadwidescreen = !!(flags & 8); // The newly selected IWAD becomes the new default - defaultiwad = mIWadInfos[picks[pick].mInfoIndex].Name; + defaultiwad = mIWadInfos[picks[pick].mInfoIndex].Name.GetChars(); } else { @@ -781,7 +783,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, } // zdoom.pk3 must always be the first file loaded and the IWAD second. - wadfiles.Clear(); + wadfiles.clear(); D_AddFile (wadfiles, zdoom_wad, true, -1, GameConfig); // [SP] Load non-free assets if available. This must be done before the IWAD. @@ -794,10 +796,10 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, fileSystem.SetIwadNum(iwadnum); if (picks[pick].mRequiredPath.IsNotEmpty()) { - D_AddFile (wadfiles, picks[pick].mRequiredPath, true, -1, GameConfig); + D_AddFile (wadfiles, picks[pick].mRequiredPath.GetChars(), true, -1, GameConfig); iwadnum++; } - D_AddFile (wadfiles, picks[pick].mFullPath, true, -1, GameConfig); + D_AddFile (wadfiles, picks[pick].mFullPath.GetChars(), true, -1, GameConfig); fileSystem.SetMaxIwadNum(iwadnum); auto info = mIWadInfos[picks[pick].mInfoIndex]; @@ -818,7 +820,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, path = FString(picks[pick].mFullPath.GetChars(), lastslash + 1); } path += info.Load[i]; - D_AddFile(wadfiles, path, true, -1, GameConfig); + D_AddFile(wadfiles, path.GetChars(), true, -1, GameConfig); } else { @@ -837,7 +839,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, // //========================================================================== -const FIWADInfo *FIWadManager::FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad, const char *optionalwad) +const FIWADInfo *FIWadManager::FindIWAD(std::vector& wadfiles, const char *iwad, const char *basewad, const char *optionalwad) { int iwadType = IdentifyVersion(wadfiles, iwad, basewad, optionalwad); if (iwadType == -1) return nullptr; diff --git a/src/d_main.cpp b/src/d_main.cpp index 77cfa7d3d3..df6770fe37 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -29,6 +29,8 @@ #ifdef _WIN32 #include +#define WIN32_MEAN_AND_LEAN +#include #endif #if defined(__unix__) || defined(__APPLE__) @@ -117,11 +119,14 @@ #include "screenjob.h" #include "startscreen.h" #include "shiftstate.h" +#include "common/widgets/errorwindow.h" #ifdef __unix__ #include "i_system.h" // for SHARE_DIR #endif // __unix__ +using namespace FileSys; + EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Int, vr_mode) EXTERN_CVAR(Bool, cl_customizeinvulmap) @@ -157,6 +162,7 @@ void I_UpdateDiscordPresence(bool SendPresence, const char* curstatus, const cha bool M_SetSpecialMenu(FName& menu, int param); // game specific checks const FIWADInfo *D_FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad); +void InitWidgetResources(const char* basewad); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -202,11 +208,6 @@ extern bool insave; extern TDeletingArray LightDefaults; extern FName MessageBoxClass; -static const char* iwad_folders[] = { "flats/", "textures/", "hires/", "sprites/", "voxels/", "colormaps/", "acs/", "maps/", "voices/", "patches/", "graphics/", "sounds/", "music/", - "materials/", "models/", "fonts/", "brightmaps/"}; -static const char* iwad_reserved[] = { "mapinfo", "zmapinfo", "umapinfo", "gameinfo", "sndinfo", "sndseq", "sbarinfo", "menudef", "gldefs", "animdefs", "decorate", "zscript", "iwadinfo", "maps/" }; - - CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL | CVAR_VIRTUAL) { if (netgame) @@ -262,7 +263,7 @@ CUSTOM_CVAR (Int, fraglimit, 0, CVAR_SERVERINFO) { if (playeringame[i] && self <= D_GetFragCount(&players[i])) { - Printf ("%s\n", GStrings("TXT_FRAGLIMIT")); + Printf ("%s\n", GStrings.GetString("TXT_FRAGLIMIT")); primaryLevel->ExitLevel (0, false); break; } @@ -280,7 +281,7 @@ CUSTOM_CVAR (String, vid_cursor, "None", CVAR_ARCHIVE | CVAR_NOINITCALL) if (!stricmp(self, "None" ) && gameinfo.CursorPic.IsNotEmpty()) { - res = I_SetCursor(TexMan.GetGameTextureByName(gameinfo.CursorPic)); + res = I_SetCursor(TexMan.GetGameTextureByName(gameinfo.CursorPic.GetChars())); } else { @@ -399,9 +400,9 @@ void D_Render(std::function action, bool interpolate) for (auto Level : AllLevels()) { // Check for the presence of dynamic lights at the start of the frame once. - if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->LMTextureCount > 0) + if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->lightmaps) { - Level->HasDynamicLights = Level->lights || Level->LMTextureCount > 0; + Level->HasDynamicLights = Level->lights || Level->lightmaps; } else Level->HasDynamicLights = false; // lights are off so effectively we have none. if (interpolate) Level->interpolator.DoInterpolations(I_GetTimeFrac()); @@ -430,14 +431,14 @@ CUSTOM_CVAR (Int, dmflags, 0, CVAR_SERVERINFO | CVAR_NOINITCALL) if (self & DF_NO_FREELOOK) { - Net_WriteByte (DEM_CENTERVIEW); + Net_WriteInt8 (DEM_CENTERVIEW); } // If nofov is set, force everybody to the arbitrator's FOV. if ((self & DF_NO_FOV) && consoleplayer == Net_Arbitrator) { float fov; - Net_WriteByte (DEM_FOV); + Net_WriteInt8 (DEM_FOV); // If the game is started with DF_NO_FOV set, the arbitrator's // DesiredFOV will not be set when this callback is run, so @@ -576,6 +577,13 @@ CUSTOM_CVAR(Int, dmflags3, 0, CVAR_SERVERINFO | CVAR_NOINITCALL) } CVAR(Flag, sv_noplayerclip, dmflags3, DF3_NO_PLAYER_CLIP); +CVAR(Flag, sv_coopsharekeys, dmflags3, DF3_COOP_SHARE_KEYS); +CVAR(Flag, sv_localitems, dmflags3, DF3_LOCAL_ITEMS); +CVAR(Flag, sv_nolocaldrops, dmflags3, DF3_NO_LOCAL_DROPS); +CVAR(Flag, sv_nocoopitems, dmflags3, DF3_NO_COOP_ONLY_ITEMS); +CVAR(Flag, sv_nocoopthings, dmflags3, DF3_NO_COOP_ONLY_THINGS); +CVAR(Flag, sv_rememberlastweapon, dmflags3, DF3_REMEMBER_LAST_WEAP); +CVAR(Flag, sv_pistolstart, dmflags3, DF3_PISTOL_START); //========================================================================== // @@ -981,6 +989,10 @@ void D_Display () case GS_FORCEWIPEMELT: wipe_type = wipe_Melt; break; + + case GS_FORCEWIPEFIZZLEFADE: + wipe_type = wipe_Fizzlefade; + break; } } @@ -995,6 +1007,7 @@ void D_Display () screen->FrameTimeNS = I_nsTime(); TexAnim.UpdateAnimations(screen->FrameTime); R_UpdateSky(screen->FrameTime); + if (level.levelMesh) level.levelMesh->BeginFrame(level); screen->BeginFrame(); twod->ClearClipRect(); if ((gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL) && gametic != 0) @@ -1098,18 +1111,18 @@ void D_Display () } if ( !skip ) { - auto tex = TexMan.GetGameTextureByName(gameinfo.PauseSign, true); + auto tex = TexMan.GetGameTextureByName(gameinfo.PauseSign.GetChars(), true); double x = (SCREENWIDTH - tex->GetDisplayWidth() * CleanXfac)/2 + tex->GetDisplayLeftOffset() * CleanXfac; DrawTexture(twod, tex, x, 4, DTA_CleanNoMove, true, TAG_DONE); if (paused && multiplayer) { FFont *font = generic_ui? NewSmallFont : SmallFont; - FString pstring = GStrings("TXT_BY"); + FString pstring = GStrings.GetString("TXT_BY"); pstring.Substitute("%s", players[paused - 1].userinfo.GetName()); DrawText(twod, font, CR_RED, (twod->GetWidth() - font->StringWidth(pstring)*CleanXfac) / 2, - (tex->GetDisplayHeight() * CleanYfac) + 4, pstring, DTA_CleanNoMove, true, TAG_DONE); + (tex->GetDisplayHeight() * CleanYfac) + 4, pstring.GetChars(), DTA_CleanNoMove, true, TAG_DONE); } } } @@ -1205,6 +1218,8 @@ void D_DoomLoop () { try { + GStrings.SetDefaultGender(players[consoleplayer].userinfo.GetGender()); // cannot be done when the CVAR changes because we don't know if it's for the consoleplayer. + // frame syncronous IO operations if (gametic > lasttic) { @@ -1246,7 +1261,7 @@ void D_DoomLoop () return; } } - catch (CRecoverableError &error) + catch (const CRecoverableError &error) { if (error.GetMessage ()) { @@ -1254,6 +1269,14 @@ void D_DoomLoop () } D_ErrorCleanup (); } + catch (const FileSystemException& error) // in case this propagates up to here it should be treated as a recoverable error. + { + if (error.what()) + { + Printf(PRINT_NONOTIFY | PRINT_BOLD, "\n%s\n", error.what()); + } + D_ErrorCleanup(); + } catch (CVMAbortException &error) { error.MaybePrintMessage(); @@ -1295,7 +1318,7 @@ void D_PageDrawer (void) if (Subtitle != nullptr) { FFont* font = generic_ui ? NewSmallFont : SmallFont; - DrawFullscreenSubtitle(font, GStrings[Subtitle]); + DrawFullscreenSubtitle(font, GStrings.CheckString(Subtitle)); } if (Advisory.isValid()) { @@ -1523,7 +1546,7 @@ void D_DoAdvanceDemo (void) gamestate = GS_DEMOSCREEN; pagename = gameinfo.TitlePage; pagetic = (int)(gameinfo.titleTime * TICRATE); - if (!playedtitlemusic) S_ChangeMusic (gameinfo.titleMusic, gameinfo.titleOrder, false); + if (!playedtitlemusic) S_ChangeMusic (gameinfo.titleMusic.GetChars(), gameinfo.titleOrder, false); playedtitlemusic = true; demosequence = 3; pagecount = 0; @@ -1545,7 +1568,7 @@ void D_DoAdvanceDemo (void) if (pagename.IsNotEmpty()) { - Page = TexMan.CheckForTexture(pagename, ETextureType::MiscPatch); + Page = TexMan.CheckForTexture(pagename.GetChars(), ETextureType::MiscPatch); } } @@ -1724,7 +1747,7 @@ void ParseCVarInfo() } } // Now create the cvar. - cvar = customCVar ? C_CreateZSCustomCVar(cvarname, cvartype, cvarflags, customCVarClassName) : C_CreateCVar(cvarname, cvartype, cvarflags); + cvar = customCVar ? C_CreateZSCustomCVar(cvarname.GetChars(), cvartype, cvarflags, customCVarClassName) : C_CreateCVar(cvarname.GetChars(), cvartype, cvarflags); if (cvardefault != NULL) { UCVarValue val; @@ -1740,7 +1763,7 @@ void ParseCVarInfo() // clutter up the cvar space when not playing mods with custom cvars. if (addedcvars) { - GameConfig->DoModSetup (gameinfo.ConfigName); + GameConfig->DoModSetup (gameinfo.ConfigName.GetChars()); } } @@ -1761,8 +1784,8 @@ bool ConsiderPatches (const char *arg) argc = Args->CheckParmList(arg, &args); for (i = 0; i < argc; ++i) { - if ( (f = BaseFileSearch(args[i], ".deh", false, GameConfig)) || - (f = BaseFileSearch(args[i], ".bex", false, GameConfig)) ) + if ( (f = BaseFileSearch(args[i].GetChars(), ".deh", false, GameConfig)) || + (f = BaseFileSearch(args[i].GetChars(), ".bex", false, GameConfig)) ) { D_LoadDehFile(f); } @@ -1785,7 +1808,7 @@ FExecList *D_MultiExec (FArgs *list, FExecList *exec) return exec; } -static void GetCmdLineFiles(TArray &wadfiles) +static void GetCmdLineFiles(std::vector& wadfiles) { FString *args; int i, argc; @@ -1793,12 +1816,12 @@ static void GetCmdLineFiles(TArray &wadfiles) argc = Args->CheckParmList("-file", &args); for (i = 0; i < argc; ++i) { - D_AddWildFile(wadfiles, args[i], ".wad", GameConfig); + D_AddWildFile(wadfiles, args[i].GetChars(), ".wad", GameConfig); } } -static FString ParseGameInfo(TArray &pwads, const char *fn, const char *data, int size) +static FString ParseGameInfo(std::vector &pwads, const char *fn, const char *data, int size) { FScanner sc; FString iwad; @@ -1806,6 +1829,8 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char bool isDir; const char *lastSlash = strrchr (fn, '/'); + if (lastSlash == NULL) + lastSlash = strrchr (fn, ':'); sc.OpenMem("GAMEINFO", data, size); while(sc.GetToken()) @@ -1830,20 +1855,19 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char FString checkpath; if (lastSlash != NULL) { - checkpath = FString(fn, (lastSlash - fn) + 1); - checkpath += sc.String; + checkpath = FString(fn, lastSlash - fn) + '/' + sc.String; } else { checkpath = sc.String; } - if (!DirEntryExists(checkpath, &isDir)) + if (!DirEntryExists(checkpath.GetChars(), &isDir)) { pos += D_AddFile(pwads, sc.String, true, pos, GameConfig); } else { - pos += D_AddFile(pwads, checkpath, true, pos, GameConfig); + pos += D_AddFile(pwads, checkpath.GetChars(), true, pos, GameConfig); } } while (sc.CheckToken(',')); @@ -1925,11 +1949,13 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char void GetReserved(LumpFilterInfo& lfi) { - for (auto p : iwad_folders) lfi.reservedFolders.Push(p); - for (auto p : iwad_reserved) lfi.requiredPrefixes.Push(p); + lfi.reservedFolders = { "flats/", "textures/", "hires/", "sprites/", "voxels/", "colormaps/", "acs/", "maps/", "voices/", "patches/", "graphics/", "sounds/", "music/", + "materials/", "models/", "fonts/", "brightmaps/" }; + lfi.requiredPrefixes = { "mapinfo", "zmapinfo", "umapinfo", "gameinfo", "sndinfo", "sndseq", "sbarinfo", "menudef", "gldefs", "animdefs", "decorate", "zscript", "iwadinfo", "complvl", "terrain", "maps/" }; + lfi.blockednames = { "*.bat", "*.exe", "__macosx/*", "*/__macosx/*" }; } -static FString CheckGameInfo(TArray & pwads) +static FString CheckGameInfo(std::vector & pwads) { FileSystem check; @@ -1937,16 +1963,15 @@ static FString CheckGameInfo(TArray & pwads) GetReserved(lfi); // Open the entire list as a temporary file system and look for a GAMEINFO lump. The last one will automatically win. - check.InitMultipleFiles(pwads, true, &lfi); - if (check.GetNumEntries() > 0) + if (check.InitMultipleFiles(pwads, &lfi, nullptr)) { int num = check.CheckNumForName("GAMEINFO"); if (num >= 0) { // Found one! - auto data = check.GetFileData(num); + auto data = check.ReadFile(num); auto wadname = check.GetResourceFileName(check.GetFileContainer(num)); - return ParseGameInfo(pwads, wadname, (const char*)data.Data(), data.Size()); + return ParseGameInfo(pwads, wadname, data.string(), (int)data.size()); } } return ""; @@ -1997,7 +2022,7 @@ static void D_DoomInit() // //========================================================================== -static void AddAutoloadFiles(const char *autoname, TArray& allwads) +static void AddAutoloadFiles(const char *autoname, std::vector& allwads) { LumpFilterIWAD.Format("%s.", autoname); // The '.' is appened to simplify parsing the string @@ -2044,11 +2069,11 @@ static void AddAutoloadFiles(const char *autoname, TArray& allwads) file = progdir; #endif file += "skins"; - D_AddDirectory (allwads, file, "*.wad", GameConfig); + D_AddDirectory (allwads, file.GetChars(), "*.wad", GameConfig); #ifdef __unix__ file = NicePath("$HOME/" GAME_DIR "/skins"); - D_AddDirectory (allwads, file, "*.wad", GameConfig); + D_AddDirectory (allwads, file.GetChars(), "*.wad", GameConfig); #endif // Add common (global) wads @@ -2060,7 +2085,7 @@ static void AddAutoloadFiles(const char *autoname, TArray& allwads) while ((len = LumpFilterIWAD.IndexOf('.', lastpos+1)) > 0) { file = LumpFilterIWAD.Left(len) + ".Autoload"; - D_AddConfigFiles(allwads, file, "*.wad", GameConfig); + D_AddConfigFiles(allwads, file.GetChars(), "*.wad", GameConfig); lastpos = len; } } @@ -2147,7 +2172,7 @@ static void CheckCmdLine() FString mapvalue = Args->TakeValue("+map"); if (mapvalue.IsNotEmpty()) { - if (!P_CheckMapData(mapvalue)) + if (!P_CheckMapData(mapvalue.GetChars())) { Printf ("Can't find map %s\n", mapvalue.GetChars()); } @@ -2160,7 +2185,7 @@ static void CheckCmdLine() if (devparm) { - Printf ("%s", GStrings("D_DEVSTR")); + Printf ("%s", GStrings.GetString("D_DEVSTR")); } // turbo option // [RH] (now a cvar) @@ -2199,9 +2224,8 @@ static void CheckCmdLine() StartScreen->AppendStatusLine("Respawning..."); if (autostart) { - FString temp; - temp.Format ("Warp to map %s, Skill %d ", startmap.GetChars(), gameskill + 1); - StartScreen->AppendStatusLine(temp); + FStringf temp("Warp to map %s, Skill %d ", startmap.GetChars(), gameskill + 1); + StartScreen->AppendStatusLine(temp.GetChars()); } } @@ -2421,7 +2445,7 @@ void RenameNerve(FileSystem& fileSystem) continue; } for (int icheck = 0; icheck < numnerveversions; icheck++) - if (fr->GetLength() == (long)nervesize[icheck]) + if (fr->GetLength() == (ptrdiff_t)nervesize[icheck]) isizecheck = icheck; if (isizecheck == -1) { @@ -2482,9 +2506,9 @@ void FixMacHexen(FileSystem& fileSystem) FileReader* reader = fileSystem.GetFileReader(fileSystem.GetIwadNum()); auto iwadSize = reader->GetLength(); - static const long DEMO_SIZE = 13596228; - static const long BETA_SIZE = 13749984; - static const long FULL_SIZE = 21078584; + static const ptrdiff_t DEMO_SIZE = 13596228; + static const ptrdiff_t BETA_SIZE = 13749984; + static const ptrdiff_t FULL_SIZE = 21078584; if (DEMO_SIZE != iwadSize && BETA_SIZE != iwadSize @@ -2634,19 +2658,14 @@ void Mlook_ReleaseHandler() { if (lookspring) { - Net_WriteByte(DEM_CENTERVIEW); + Net_WriteInt8(DEM_CENTERVIEW); } } -int StrTable_GetGender() -{ - return players[consoleplayer].userinfo.GetGender(); -} - bool StrTable_ValidFilter(const char* str) { if (gameinfo.gametype == GAME_Strife && (gameinfo.flags & GI_SHAREWARE) && !stricmp(str, "strifeteaser")) return true; - return stricmp(str, GameNames[gameinfo.gametype]) == 0; + return gameinfo.gametype == 0 || stricmp(str, GameNames[gameinfo.gametype]) == 0; } bool System_WantGuiCapture() @@ -2997,7 +3016,25 @@ static void System_StartCutscene(bool blockui) static void System_SetTransition(int type) { - if (type != wipe_None) wipegamestate = type == wipe_Burn? GS_FORCEWIPEBURN : type == wipe_Fade? GS_FORCEWIPEFADE : GS_FORCEWIPEMELT; + if (type != wipe_None) + { + switch (type) + { + case wipe_Burn: + wipegamestate = GS_FORCEWIPEBURN; + break; + case wipe_Fizzlefade: + wipegamestate = GS_FORCEWIPEFIZZLEFADE; + break; + case wipe_Fade: + wipegamestate = GS_FORCEWIPEFADE; + break; + default: + case wipe_Melt: + wipegamestate = GS_FORCEWIPEMELT; + break; + } + } } static void System_HudScaleChanged() @@ -3044,14 +3081,71 @@ static FILE* D_GetHashFile() return hashfile; } +// checks if a file within a directory is allowed to be added to the file system. +static bool FileNameCheck(const char* base, const char* path) +{ + // This one is courtesy of EDuke32. :( + // Putting cache files in the application directory is very bad style. + // Unfortunately, having a garbage file named "textures" present will cause serious problems down the line. + if (!strnicmp(base, "textures", 8)) + { + // do not use fopen. The path may contain non-ASCII characters. + FileReader f; + if (f.OpenFile(path)) + { + char check[3]{}; + f.Read(check, 3); + if (!memcmp(check, "LZ4", 3)) return false; + } + } + return true; +} + +static int FileSystemPrintf(FSMessageLevel level, const char* fmt, ...) +{ + va_list arg; + va_start(arg, fmt); + FString text; + text.VFormat(fmt, arg); + switch (level) + { + case FSMessageLevel::Error: + return Printf(TEXTCOLOR_RED "%s", text.GetChars()); + break; + case FSMessageLevel::Warning: + Printf(TEXTCOLOR_YELLOW "%s", text.GetChars()); + break; + case FSMessageLevel::Attention: + Printf(TEXTCOLOR_BLUE "%s", text.GetChars()); + break; + case FSMessageLevel::Message: + Printf("%s", text.GetChars()); + break; + case FSMessageLevel::DebugWarn: + DPrintf(DMSG_WARNING, "%s", text.GetChars()); + break; + case FSMessageLevel::DebugNotify: + DPrintf(DMSG_NOTIFY, "%s", text.GetChars()); + break; + } + return (int)text.Len(); +} //========================================================================== // // D_InitGame // //========================================================================== -static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArray& pwads) +static int D_InitGame(const FIWADInfo* iwad_info, std::vector& allwads, std::vector& pwads) { + NetworkEntityManager::InitializeNetworkEntities(); + + if (!restart) + { + V_InitScreenSize(); + // This allocates a dummy framebuffer as a stand-in until V_Init2 is called. + V_InitScreen(); + } SavegameFolder = iwad_info->Autoname; gameinfo.gametype = iwad_info->gametype; gameinfo.flags = iwad_info->flags; @@ -3075,15 +3169,15 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr FRandom::StaticClearRandom (); FBaseCVar::DisableCallbacks(); - GameConfig->DoGameSetup (gameinfo.ConfigName); + GameConfig->DoGameSetup (gameinfo.ConfigName.GetChars()); - AddAutoloadFiles(iwad_info->Autoname, allwads); + AddAutoloadFiles(iwad_info->Autoname.GetChars(), allwads); // Process automatically executed files FExecList *exec; FArgs *execFiles = new FArgs; if (!(Args->CheckParm("-noautoexec"))) - GameConfig->AddAutoexec(execFiles, gameinfo.ConfigName); + GameConfig->AddAutoexec(execFiles, gameinfo.ConfigName.GetChars()); exec = D_MultiExec(execFiles, NULL); delete execFiles; @@ -3103,7 +3197,6 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr if (!batchrun) Printf ("W_Init: Init WADfiles.\n"); LumpFilterInfo lfi; - lfi.dotFilter = LumpFilterIWAD; static const struct { int match; const char* name; } blanket[] = { @@ -3115,9 +3208,18 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr for (auto& inf : blanket) { - if (gameinfo.gametype & inf.match) lfi.gameTypeFilter.Push(inf.name); + if (gameinfo.gametype & inf.match) lfi.gameTypeFilter.push_back(inf.name); + } + lfi.gameTypeFilter.push_back(FStringf("game-%s", GameTypeName()).GetChars()); + + lfi.gameTypeFilter.push_back(LumpFilterIWAD.GetChars()); + // Workaround for old Doom filter names. + if (LumpFilterIWAD.Compare("doom.id.doom") == 0) + { + lfi.gameTypeFilter.push_back("doom.doom"); } - lfi.gameTypeFilter.Push(FStringf("game-%s", GameTypeName())); + + GetReserved(lfi); @@ -3128,15 +3230,28 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr FixMacHexen(fileSystem); FindStrifeTeaserVoices(fileSystem); }; - allwads.Append(std::move(pwads)); + allwads.insert( + allwads.end(), + std::make_move_iterator(pwads.begin()), + std::make_move_iterator(pwads.end()) + ); bool allowduplicates = Args->CheckParm("-allowduplicates"); auto hashfile = D_GetHashFile(); - fileSystem.InitMultipleFiles (allwads, false, &lfi, allowduplicates, hashfile); - allwads.Clear(); - allwads.ShrinkToFit(); + if (!fileSystem.InitMultipleFiles(allwads, &lfi, FileSystemPrintf, allowduplicates, hashfile)) + { + I_FatalError("FileSystem: no files found"); + } + allwads.clear(); + allwads.shrink_to_fit(); SetMapxxFlag(); + if (!restart) + { + // Note: this has to happen after the file system has been initialized (backends may load shaders during initialization) + V_Init2(); + } + D_GrabCVarDefaults(); //parse DEFCVARS InitPalette(); @@ -3159,7 +3274,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr StartScreen = nostartscreen? nullptr : GetGameStartScreen(per_shader_progress > 0 ? max_progress * 10 / 9 : max_progress + 3); - GameConfig->DoKeySetup(gameinfo.ConfigName); + GameConfig->DoKeySetup(gameinfo.ConfigName.GetChars()); // Now that wads are loaded, define mod-specific cvars. ParseCVarInfo(); @@ -3172,8 +3287,8 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr exec = NULL; } - // [RH] Initialize localizable strings. - GStrings.LoadStrings (language); + // [RH] Initialize localizable strings. + GStrings.LoadStrings(fileSystem, language); V_InitFontColors (); @@ -3196,16 +3311,8 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr if (!batchrun) Printf ("V_Init: allocate screen.\n"); if (!restart) { - V_InitScreenSize(); - // This allocates a dummy framebuffer as a stand-in until V_Init2 is called. - V_InitScreen (); - - if (StartScreen != nullptr) - { - V_Init2(); - StartScreen->Render(); - } - + screen->CompileNextShader(); + if (StartScreen != nullptr) StartScreen->Render(); } else { @@ -3226,7 +3333,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr if (!batchrun) Printf ("ST_Init: Init startup screen.\n"); if (!restart) { - StartWindow = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5, StartScreen == nullptr); + StartWindow = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5); } else { @@ -3263,7 +3370,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr }, CheckForHacks, InitBuildTiles); PatchTextures(); TexAnim.Init(); - C_InitConback(TexMan.CheckForTexture(gameinfo.BorderFlat, ETextureType::Flat), true, 0.25); + C_InitConback(TexMan.CheckForTexture(gameinfo.BorderFlat.GetChars(), ETextureType::Flat), true, 0.25); FixWideStatusBar(); @@ -3310,6 +3417,8 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr if (!batchrun) Printf ("DecalLibrary: Load decals.\n"); DecalLibrary.ReadAllDecals (); + auto numbasesounds = soundEngine->GetNumSounds(); + // Load embedded Dehacked patches D_LoadDehLumps(FromIWAD); @@ -3339,6 +3448,9 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr // Create replacements for dehacked pickups FinishDehPatch(); + auto numdehsounds = soundEngine->GetNumSounds(); + if (numbasesounds < numdehsounds) S_LockLocalSndinfo(); // DSDHacked sounds are not compatible with map-local SNDINFOs. + if (!batchrun) Printf("M_Init: Init menus.\n"); SetDefaultMenuColors(); M_Init(); @@ -3383,7 +3495,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr for (int p = 0; p < 5; ++p) { // At this point we cannot use the player's gender info yet so force 'male' here. - const char *str = GStrings.GetString(startupString[p], nullptr, 0); + const char *str = GStrings.CheckString(startupString[p], nullptr, 0); if (str != NULL && str[0] != '\0') { Printf("%s\n", str); @@ -3436,7 +3548,6 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr return 1337; // special exit } - if (StartScreen == nullptr) V_Init2(); if (StartScreen) { StartScreen->Progress(max_progress); // advance progress bar to the end. @@ -3456,7 +3567,6 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr twod->Begin(screen->GetWidth(), screen->GetHeight()); twod->End(); UpdateJoystickMenu(NULL); - UpdateVRModes(); Local_Job_Init(); v = Args->CheckValue ("-loadgame"); @@ -3467,7 +3577,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr { I_FatalError("Cannot find savegame %s", file.GetChars()); } - G_LoadGame(file); + G_LoadGame(file.GetChars()); } v = Args->CheckValue("-playdemo"); @@ -3496,11 +3606,11 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr } CheckWarpTransMap(startmap, true); if (demorecording) - G_BeginRecording(startmap); - G_InitNew(startmap, false); + G_BeginRecording(startmap.GetChars()); + G_InitNew(startmap.GetChars(), false); if (StoredWarp.IsNotEmpty()) { - AddCommandString(StoredWarp); + AddCommandString(StoredWarp.GetChars()); StoredWarp = ""; } } @@ -3575,7 +3685,6 @@ static int D_DoomMain_Internal (void) System_GetPlayerName, System_DispatchEvent, StrTable_ValidFilter, - StrTable_GetGender, nullptr, CheckSkipGameOptionBlock, System_ConsoleToggled, @@ -3590,8 +3699,9 @@ static int D_DoomMain_Internal (void) OnMenuOpen, System_LanguageChanged, OkForLocalization, - []() ->FConfigFile* { return GameConfig; } - + []() ->FConfigFile* { return GameConfig; }, + nullptr, + RemapUserTranslation }; @@ -3608,6 +3718,50 @@ static int D_DoomMain_Internal (void) I_FatalError("Cannot find " BASEWAD); } LoadHexFont(wad); // load hex font early so we have it during startup. + InitWidgetResources(wad); + + if (Args->CheckParm("-showcrashreport")) + { + FString minidumpFilename = Args->GetArg(2); + FString logFilename = Args->GetArg(3); + + FString logText; + { + FileReader fr; + if (fr.OpenFile(logFilename.GetChars())) + { + std::vector data(fr.GetLength() + 1); + if (fr.Read(data.data(), data.size() - 1) == (FileReader::Size)data.size() - 1) + { + logText = data.data(); + } + } + } + std::vector minidump; + { + FileReader fr; + if (fr.OpenFile(minidumpFilename.GetChars())) + { + minidump.resize(fr.GetLength()); + if (fr.Read(minidump.data(), minidump.size()) != (FileReader::Size)minidump.size()) + { + minidump.clear(); + } + } + } + + FString text; + text.Format("%s fatally crashed!", GAMENAME); + ErrorWindow::ExecModal(text.GetChars(), logText.GetChars(), std::move(minidump)); + + // Crash reporter only uses -showcrashreport on Windows at the moment and there seems to be no abstraction available + #ifdef WIN32 + DeleteFile(logFilename.WideString().c_str()); + DeleteFile(minidumpFilename.WideString().c_str()); + #endif + + return 0; + } C_InitConsole(80*8, 25*8, false); I_DetectOS(); @@ -3616,7 +3770,7 @@ static int D_DoomMain_Internal (void) FString logfile = Args->TakeValue("+logfile"); if (logfile.IsNotEmpty()) { - execLogfile(logfile); + execLogfile(logfile.GetChars()); } else if (batchout != NULL && *batchout != 0) { @@ -3640,7 +3794,7 @@ static int D_DoomMain_Internal (void) FString optionalwad = BaseFileSearch(OPTIONALWAD, NULL, true, GameConfig); - iwad_man = new FIWadManager(basewad, optionalwad); + iwad_man = new FIWadManager(basewad.GetChars(), optionalwad.GetChars()); // Now that we have the IWADINFO, initialize the autoload ini sections. GameConfig->DoAutoloadSetup(iwad_man); @@ -3660,13 +3814,13 @@ static int D_DoomMain_Internal (void) if (iwad_man == NULL) { - iwad_man = new FIWadManager(basewad, optionalwad); + iwad_man = new FIWadManager(basewad.GetChars(), optionalwad.GetChars()); } // Load zdoom.pk3 alone so that we can get access to the internal gameinfos before // the IWAD is known. - TArray pwads; + std::vector pwads; GetCmdLineFiles(pwads); FString iwad = CheckGameInfo(pwads); @@ -3674,18 +3828,21 @@ static int D_DoomMain_Internal (void) // restart is initiated without a defined IWAD assume for now that it's not going to change. if (iwad.IsEmpty()) iwad = lastIWAD; - TArray allwads; + std::vector allwads; - const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad, optionalwad); + const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad.GetChars(), basewad.GetChars(), optionalwad.GetChars()); if (!iwad_info) return 0; // user exited the selection popup via cancel button. - if ((iwad_info->flags & GI_SHAREWARE) && pwads.Size() > 0) + if ((iwad_info->flags & GI_SHAREWARE) && pwads.size() > 0) { I_FatalError ("You cannot -file with the shareware version. Register!"); } lastIWAD = iwad; int ret = D_InitGame(iwad_info, allwads, pwads); - allwads.Reset(); + pwads.clear(); + pwads.shrink_to_fit(); + allwads.clear(); + allwads.shrink_to_fit(); delete iwad_man; // now we won't need this anymore iwad_man = NULL; if (ret != 0) return ret; @@ -3898,7 +4055,7 @@ void I_UpdateWindowTitle() // Strip out any color escape sequences before setting a window title TArray copy(titlestr.Len() + 1); - const char* srcp = titlestr; + const char* srcp = titlestr.GetChars(); char* dstp = copy.Data(); while (*srcp != 0) @@ -3928,35 +4085,29 @@ void I_UpdateWindowTitle() I_SetWindowTitle(copy.Data()); } -#ifdef _WIN32 -// For broadest GL compatibility, require user to explicitly enable quad-buffered stereo mode. -// Setting vr_enable_quadbuffered_stereo does not automatically invoke quad-buffered stereo, -// but makes it possible for subsequent "vr_mode 7" to invoke quad-buffered stereo -CUSTOM_CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +CCMD(fs_dir) { - Printf("You must restart " GAMENAME " to switch quad stereo mode\n"); + int numfiles = fileSystem.GetNumEntries(); + + for (int i = 0; i < numfiles; i++) + { + auto container = fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(i)); + auto fn1 = fileSystem.GetFileFullName(i); + auto fns = fileSystem.GetFileShortName(i); + auto fnid = fileSystem.GetResourceId(i); + auto length = fileSystem.FileLength(i); + bool hidden = fileSystem.FindFile(fn1) != i; + Printf(PRINT_HIGH | PRINT_NONOTIFY, "%s%-64s %-15s (%5d) %10d %s %s\n", hidden ? TEXTCOLOR_RED : TEXTCOLOR_UNTRANSLATED, fn1, fns, fnid, length, container, hidden ? "(h)" : ""); + } } -#endif -void UpdateVRModes(bool considerQuadBuffered) +CCMD(type) { - FOptionValues** pVRModes = OptionValues.CheckKey("VRMode"); - if (pVRModes == nullptr) return; - - TArray& vals = (*pVRModes)->mValues; - TArray filteredValues; - int cnt = vals.Size(); - for (int i = 0; i < cnt; ++i) { - auto const& mode = vals[i]; - if (mode.Value == 7) { // Quad-buffered stereo -#ifdef _WIN32 - if (!vr_enable_quadbuffered) continue; -#else - continue; // Remove quad-buffered option on Mac and Linux -#endif - if (!considerQuadBuffered) continue; // Probably no compatible screen mode was found - } - filteredValues.Push(mode); + if (argv.argc() < 2) return; + int lump = fileSystem.CheckNumForFullName(argv[1]); + if (lump >= 0) + { + auto data = fileSystem.ReadFile(lump); + Printf("%.*s\n", data.size(), data.string()); } - vals = filteredValues; } diff --git a/src/d_main.h b/src/d_main.h index a6f76a8d89..6f6c374581 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -128,13 +128,13 @@ class FIWadManager void ParseIWadInfo(const char *fn, const char *data, int datasize, FIWADInfo *result = nullptr); int ScanIWAD (const char *iwad); int CheckIWADInfo(const char *iwad); - int IdentifyVersion (TArray &wadfiles, const char *iwad, const char *zdoom_wad, const char *optional_wad); + int IdentifyVersion (std::vector& wadfiles, const char *iwad, const char *zdoom_wad, const char *optional_wad); void CollectSearchPaths(); void AddIWADCandidates(const char *dir); void ValidateIWADs(); public: FIWadManager(const char *fn, const char *fnopt); - const FIWADInfo *FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad, const char *optionalwad); + const FIWADInfo *FindIWAD(std::vector& wadfiles, const char *iwad, const char *basewad, const char *optionalwad); const FString *GetAutoname(unsigned int num) const { if (num < mIWadInfos.Size()) return &mIWadInfos[num].Autoname; diff --git a/src/d_net.cpp b/src/d_net.cpp index 80f43e1a27..656b07e0b7 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -264,27 +264,37 @@ static struct TicSpecial if (streamptr) { CheckSpace (1); - WriteByte (it, &streamptr); + WriteInt8 (it, &streamptr); } return *this; } - TicSpecial &operator << (short it) + TicSpecial &operator << (int16_t it) { if (streamptr) { CheckSpace (2); - WriteWord (it, &streamptr); + WriteInt16 (it, &streamptr); } return *this; } - TicSpecial &operator << (int it) + TicSpecial &operator << (int32_t it) { if (streamptr) { CheckSpace (4); - WriteLong (it, &streamptr); + WriteInt32 (it, &streamptr); + } + return *this; + } + + TicSpecial& operator << (int64_t it) + { + if (streamptr) + { + CheckSpace(8); + WriteInt64(it, &streamptr); } return *this; } @@ -299,6 +309,16 @@ static struct TicSpecial return *this; } + TicSpecial& operator << (double it) + { + if (streamptr) + { + CheckSpace(8); + WriteDouble(it, &streamptr); + } + return *this; + } + TicSpecial &operator << (const char *it) { if (streamptr) @@ -791,7 +811,7 @@ void GetPackets (void) { if (playeringame[i]) { - int resend = ReadLong (&foo); + int resend = ReadInt32 (&foo); if (i != consoleplayer) { resendto[nodeforplayer[i]] = resend; @@ -1246,7 +1266,7 @@ void NetUpdate (void) // the other players. if (l == 0) { - WriteWord (localcmds[localstart].consistancy, &cmddata); + WriteInt16 (localcmds[localstart].consistancy, &cmddata); // [RH] Write out special "ticcmds" before real ticcmd if (specials.used[start]) { @@ -1261,7 +1281,7 @@ void NetUpdate (void) int len; uint8_t *spec; - WriteWord (netcmds[playerbytes[l]][start].consistancy, &cmddata); + WriteInt16 (netcmds[playerbytes[l]][start].consistancy, &cmddata); spec = NetSpecs[playerbytes[l]][start].GetData (&len); if (spec != NULL) { @@ -1406,7 +1426,6 @@ struct ArbitrateData bool DoArbitrate (void *userdata) { ArbitrateData *data = (ArbitrateData *)userdata; - char *s; uint8_t *stream; int version; int node; @@ -1468,10 +1487,8 @@ bool DoArbitrate (void *userdata) NetMode = netbuffer[2]; stream = &netbuffer[3]; - s = ReadString (&stream); - startmap = s; - delete[] s; - rngseed = ReadLong (&stream); + startmap = ReadStringConst(&stream); + rngseed = ReadInt32 (&stream); C_ReadCVars (&stream); } else if (netbuffer[0] == NCMD_SETUP+3) @@ -1538,8 +1555,8 @@ bool DoArbitrate (void *userdata) netbuffer[1] = (uint8_t)doomcom.ticdup; netbuffer[2] = NetMode; stream = &netbuffer[3]; - WriteString (startmap, &stream); - WriteLong (rngseed, &stream); + WriteString (startmap.GetChars(), &stream); + WriteInt32 (rngseed, &stream); C_WriteCVars (&stream, CVAR_SERVERINFO, true); SendSetup (data->playersdetected, data->gotsetup, int(stream - netbuffer)); @@ -1782,7 +1799,7 @@ void D_QuitNetGame (void) for (i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i] && i != consoleplayer) - WriteLong (resendto[nodeforplayer[i]], &foo); + WriteInt32 (resendto[nodeforplayer[i]], &foo); } k = int(foo - netbuffer); } @@ -2050,17 +2067,22 @@ void Net_NewMakeTic (void) specials.NewMakeTic (); } -void Net_WriteByte (uint8_t it) +void Net_WriteInt8 (uint8_t it) +{ + specials << it; +} + +void Net_WriteInt16 (int16_t it) { specials << it; } -void Net_WriteWord (short it) +void Net_WriteInt32 (int32_t it) { specials << it; } -void Net_WriteLong (int it) +void Net_WriteInt64(int64_t it) { specials << it; } @@ -2070,6 +2092,11 @@ void Net_WriteFloat (float it) specials << it; } +void Net_WriteDouble(double it) +{ + specials << it; +} + void Net_WriteString (const char *it) { specials << it; @@ -2166,7 +2193,7 @@ static int RemoveClass(FLevelLocals *Level, const PClass *cls) void Net_DoCommand (int type, uint8_t **stream, int player) { uint8_t pos = 0; - char *s = NULL; + const char* s = nullptr; int i; switch (type) @@ -2174,10 +2201,9 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_SAY: { const char *name = players[player].userinfo.GetName(); - uint8_t who = ReadByte (stream); + uint8_t who = ReadInt8 (stream); - s = ReadString (stream); - CleanseString (s); + s = ReadStringConst(stream); if (((who & 1) == 0) || players[player].userinfo.GetTeam() == TEAM_NONE) { // Said to everyone if (who & 2) @@ -2206,18 +2232,15 @@ void Net_DoCommand (int type, uint8_t **stream, int player) break; case DEM_MUSICCHANGE: - s = ReadString (stream); - S_ChangeMusic (s); + S_ChangeMusic(ReadStringConst(stream)); break; case DEM_PRINT: - s = ReadString (stream); - Printf ("%s", s); + Printf("%s", ReadStringConst(stream)); break; case DEM_CENTERPRINT: - s = ReadString (stream); - C_MidPrint (nullptr, s); + C_MidPrint(nullptr, ReadStringConst(stream)); break; case DEM_UINFCHANGED: @@ -2233,11 +2256,11 @@ void Net_DoCommand (int type, uint8_t **stream, int player) break; case DEM_GIVECHEAT: - s = ReadString (stream); - cht_Give (&players[player], s, ReadLong (stream)); + s = ReadStringConst(stream); + cht_Give (&players[player], s, ReadInt32 (stream)); if (player != consoleplayer) { - FString message = GStrings("TXT_X_CHEATS"); + FString message = GStrings.GetString("TXT_X_CHEATS"); message.Substitute("%s", players[player].userinfo.GetName()); Printf("%s: give %s\n", message.GetChars(), s); } @@ -2245,36 +2268,36 @@ void Net_DoCommand (int type, uint8_t **stream, int player) break; case DEM_TAKECHEAT: - s = ReadString (stream); - cht_Take (&players[player], s, ReadLong (stream)); + s = ReadStringConst(stream); + cht_Take (&players[player], s, ReadInt32 (stream)); break; case DEM_SETINV: - s = ReadString(stream); - i = ReadLong(stream); - cht_SetInv(&players[player], s, i, !!ReadByte(stream)); + s = ReadStringConst(stream); + i = ReadInt32(stream); + cht_SetInv(&players[player], s, i, !!ReadInt8(stream)); break; case DEM_WARPCHEAT: { int x, y, z; - x = ReadWord (stream); - y = ReadWord (stream); - z = ReadWord (stream); + x = ReadInt16 (stream); + y = ReadInt16 (stream); + z = ReadInt16 (stream); P_TeleportMove (players[player].mo, DVector3(x, y, z), true); } break; case DEM_GENERICCHEAT: - cht_DoCheat (&players[player], ReadByte (stream)); + cht_DoCheat (&players[player], ReadInt8 (stream)); break; case DEM_CHANGEMAP2: - pos = ReadByte (stream); + pos = ReadInt8 (stream); /* intentional fall-through */ case DEM_CHANGEMAP: // Change to another map without disconnecting other players - s = ReadString (stream); + s = ReadStringConst(stream); // Using LEVEL_NOINTERMISSION tends to throw the game out of sync. // That was a long time ago. Maybe it works now? primaryLevel->flags |= LEVEL_CHANGEMAPCHEAT; @@ -2319,10 +2342,10 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_INVUSE: case DEM_INVDROP: { - uint32_t which = ReadLong (stream); + uint32_t which = ReadInt32 (stream); int amt = -1; - if (type == DEM_INVDROP) amt = ReadLong(stream); + if (type == DEM_INVDROP) amt = ReadInt32(stream); if (gamestate == GS_LEVEL && !paused && players[player].playerstate != PST_DEAD) @@ -2361,13 +2384,13 @@ void Net_DoCommand (int type, uint8_t **stream, int player) uint8_t special = 0; int args[5]; - s = ReadString (stream); + s = ReadStringConst(stream); if (type >= DEM_SUMMON2 && type <= DEM_SUMMONFOE2) { - angle = ReadWord(stream); - tid = ReadWord(stream); - special = ReadByte(stream); - for(i = 0; i < 5; i++) args[i] = ReadLong(stream); + angle = ReadInt16(stream); + tid = ReadInt16(stream); + special = ReadInt8(stream); + for(i = 0; i < 5; i++) args[i] = ReadInt32(stream); } typeinfo = PClass::FindActor(s); @@ -2425,12 +2448,12 @@ void Net_DoCommand (int type, uint8_t **stream, int player) break; case DEM_SPRAY: - s = ReadString(stream); + s = ReadStringConst(stream); SprayDecal(players[player].mo, s); break; case DEM_MDK: - s = ReadString(stream); + s = ReadStringConst(stream); cht_DoMDK(&players[player], s); break; @@ -2453,17 +2476,14 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_SAVEGAME: if (gamestate == GS_LEVEL) { - s = ReadString (stream); - savegamefile = s; - delete[] s; - s = ReadString (stream); - savedescription = s; + savegamefile = ReadStringConst(stream); + savedescription = ReadStringConst(stream); if (player != consoleplayer) { // Paths sent over the network will be valid for the system that sent // the save command. For other systems, the path needs to be changed. - FString basename = ExtractFileBase(savegamefile, true); - savegamefile = G_BuildSaveName (basename); + FString basename = ExtractFileBase(savegamefile.GetChars(), true); + savegamefile = G_BuildSaveName (basename.GetChars()); } } gameaction = ga_savegame; @@ -2481,7 +2501,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player) { break; } - Net_WriteByte (DEM_DOAUTOSAVE); + Net_WriteInt8 (DEM_DOAUTOSAVE); break; case DEM_DOAUTOSAVE: @@ -2516,8 +2536,8 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_RUNSCRIPT: case DEM_RUNSCRIPT2: { - int snum = ReadWord (stream); - int argn = ReadByte (stream); + int snum = ReadInt16 (stream); + int argn = ReadInt8 (stream); RunScript(stream, players[player].mo, snum, argn, (type == DEM_RUNSCRIPT2) ? ACS_ALWAYS : 0); } @@ -2525,8 +2545,8 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_RUNNAMEDSCRIPT: { - s = ReadString(stream); - int argn = ReadByte(stream); + s = ReadStringConst(stream); + int argn = ReadInt8(stream); RunScript(stream, players[player].mo, -FName(s).GetIndex(), argn & 127, (argn & 128) ? ACS_ALWAYS : 0); } @@ -2534,13 +2554,13 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_RUNSPECIAL: { - int snum = ReadWord(stream); - int argn = ReadByte(stream); + int snum = ReadInt16(stream); + int argn = ReadInt8(stream); int arg[5] = { 0, 0, 0, 0, 0 }; for (i = 0; i < argn; ++i) { - int argval = ReadLong(stream); + int argval = ReadInt32(stream); if ((unsigned)i < countof(arg)) { arg[i] = argval; @@ -2564,8 +2584,8 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_MORPHEX: { - s = ReadString (stream); - FString msg = cht_Morph (players + player, PClass::FindActor (s), false); + s = ReadStringConst(stream); + FString msg = cht_Morph (players + player, PClass::FindActor(s), false); if (player == consoleplayer) { Printf ("%s\n", msg[0] != '\0' ? msg.GetChars() : "Morph failed."); @@ -2575,7 +2595,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_ADDCONTROLLER: { - uint8_t playernum = ReadByte (stream); + uint8_t playernum = ReadInt8 (stream); players[playernum].settings_controller = true; if (consoleplayer == playernum || consoleplayer == Net_Arbitrator) @@ -2585,7 +2605,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_DELCONTROLLER: { - uint8_t playernum = ReadByte (stream); + uint8_t playernum = ReadInt8 (stream); players[playernum].settings_controller = false; if (consoleplayer == playernum || consoleplayer == Net_Arbitrator) @@ -2595,7 +2615,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_KILLCLASSCHEAT: { - s = ReadString (stream); + s = ReadStringConst(stream); int killcount = 0; PClassActor *cls = PClass::FindActor(s); @@ -2618,7 +2638,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player) break; case DEM_REMOVE: { - s = ReadString(stream); + s = ReadStringConst(stream); int removecount = 0; PClassActor *cls = PClass::FindActor(s); if (cls != NULL && cls->IsDescendantOf(RUNTIME_CLASS(AActor))) @@ -2650,14 +2670,14 @@ void Net_DoCommand (int type, uint8_t **stream, int player) int pnum; if (type == DEM_SETSLOTPNUM) { - pnum = ReadByte(stream); + pnum = ReadInt8(stream); } else { pnum = player; } - unsigned int slot = ReadByte(stream); - int count = ReadByte(stream); + unsigned int slot = ReadInt8(stream); + int count = ReadInt8(stream); if (slot < NUM_WEAPON_SLOTS) { players[pnum].weapons.ClearSlot(slot); @@ -2672,7 +2692,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_ADDSLOT: { - int slot = ReadByte(stream); + int slot = ReadInt8(stream); PClassActor *wpn = Net_ReadWeapon(stream); players[player].weapons.AddSlot(slot, wpn, player == consoleplayer); } @@ -2680,15 +2700,15 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_ADDSLOTDEFAULT: { - int slot = ReadByte(stream); + int slot = ReadInt8(stream); PClassActor *wpn = Net_ReadWeapon(stream); players[player].weapons.AddSlotDefault(slot, wpn, player == consoleplayer); } break; case DEM_SETPITCHLIMIT: - players[player].MinPitch = DAngle::fromDeg(-ReadByte(stream)); // up - players[player].MaxPitch = DAngle::fromDeg(ReadByte(stream)); // down + players[player].MinPitch = DAngle::fromDeg(-ReadInt8(stream)); // up + players[player].MaxPitch = DAngle::fromDeg(ReadInt8(stream)); // down break; case DEM_REVERTCAMERA: @@ -2702,12 +2722,12 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_NETEVENT: { - s = ReadString(stream); - int argn = ReadByte(stream); + s = ReadStringConst(stream); + int argn = ReadInt8(stream); int arg[3] = { 0, 0, 0 }; for (int i = 0; i < 3; i++) - arg[i] = ReadLong(stream); - bool manual = !!ReadByte(stream); + arg[i] = ReadInt32(stream); + bool manual = !!ReadInt8(stream); primaryLevel->localEventManager->Console(player, s, arg[0], arg[1], arg[2], manual, false); } break; @@ -2715,14 +2735,29 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_ENDSCREENJOB: EndScreenJob(); break; + + case DEM_ZSC_CMD: + { + FName cmd = ReadStringConst(stream); + unsigned int size = ReadInt16(stream); + + TArray buffer = {}; + if (size) + { + buffer.Grow(size); + for (unsigned int i = 0u; i < size; ++i) + buffer.Push(ReadInt8(stream)); + } + + FNetworkCommand netCmd = { player, cmd, buffer }; + primaryLevel->localEventManager->NetCommand(netCmd); + } + break; default: I_Error ("Unknown net command: %d", type); break; } - - if (s) - delete[] s; } // Used by DEM_RUNSCRIPT, DEM_RUNSCRIPT2, and DEM_RUNNAMEDSCRIPT @@ -2739,13 +2774,13 @@ static void RunScript(uint8_t **stream, AActor *pawn, int snum, int argn, int al for (i = 0; i < argn; ++i) { - int argval = ReadLong(stream); + int argval = ReadInt32(stream); if ((unsigned)i < countof(arg)) { arg[i] = argval; } } - P_StartScript(pawn->Level, pawn, NULL, snum, primaryLevel->MapName, arg, min(countof(arg), argn), ACS_NET | always); + P_StartScript(pawn->Level, pawn, NULL, snum, primaryLevel->MapName.GetChars(), arg, min(countof(arg), argn), ACS_NET | always); } void Net_SkipCommand (int type, uint8_t **stream) @@ -2776,6 +2811,11 @@ void Net_SkipCommand (int type, uint8_t **stream) skip = strlen((char *)(*stream)) + 15; break; + case DEM_ZSC_CMD: + skip = strlen((char*)(*stream)) + 1; + skip += (((*stream)[skip] << 8) | (*stream)[skip + 1]) + 2; + break; + case DEM_SUMMON2: case DEM_SUMMONFRIEND2: case DEM_SUMMONFOE2: @@ -2925,6 +2965,174 @@ int Net_GetLatency(int *ld, int *ad) return severity; } +//========================================================================== +// +// +// +//========================================================================== + +void NetworkEntityManager::InitializeNetworkEntities() +{ + if (!s_netEntities.Size()) + s_netEntities.AppendFill(nullptr, NetIDStart); // Allocate the first 0-8 slots for the world and clients. +} + +// Clients need special handling since they always go in slots 1 - MAXPLAYERS. +void NetworkEntityManager::SetClientNetworkEntity(player_t* const client) +{ + AActor* const mo = client->mo; + const uint32_t id = ClientNetIDStart + mo->Level->PlayerNum(client); + + // If resurrecting, we need to swap the corpse's position with the new pawn's + // position so it's no longer considered the client's body. + DObject* const oldBody = s_netEntities[id]; + if (oldBody != nullptr) + { + if (oldBody == mo) + return; + + const uint32_t curID = mo->GetNetworkID(); + + s_netEntities[curID] = oldBody; + oldBody->ClearNetworkID(); + oldBody->SetNetworkID(curID); + + mo->ClearNetworkID(); + } + else + { + RemoveNetworkEntity(mo); // Free up its current id. + } + + s_netEntities[id] = mo; + mo->SetNetworkID(id); +} + +void NetworkEntityManager::AddNetworkEntity(DObject* const ent) +{ + if (ent->IsNetworked()) + return; + + // Slot 0 is reserved for the world. + // Clients go in the first 1 - MAXPLAYERS slots + // Everything else is first come first serve. + uint32_t id = WorldNetID; + if (s_openNetIDs.Size()) + { + s_openNetIDs.Pop(id); + s_netEntities[id] = ent; + } + else + { + id = s_netEntities.Push(ent); + } + + ent->SetNetworkID(id); +} + +void NetworkEntityManager::RemoveNetworkEntity(DObject* const ent) +{ + if (!ent->IsNetworked()) + return; + + const uint32_t id = ent->GetNetworkID(); + if (id == WorldNetID) + return; + + assert(s_netEntities[id] == ent); + if (id >= NetIDStart) + s_openNetIDs.Push(id); + s_netEntities[id] = nullptr; + ent->ClearNetworkID(); +} + +DObject* NetworkEntityManager::GetNetworkEntity(const uint32_t id) +{ + if (id == WorldNetID || id >= s_netEntities.Size()) + return nullptr; + + return s_netEntities[id]; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DObject::SetNetworkID(const uint32_t id) +{ + if (!IsNetworked()) + { + ObjectFlags |= OF_Networked; + _networkID = id; + } +} + +void DObject::ClearNetworkID() +{ + ObjectFlags &= ~OF_Networked; + _networkID = NetworkEntityManager::WorldNetID; +} + +void DObject::EnableNetworking(const bool enable) +{ + if (enable) + NetworkEntityManager::AddNetworkEntity(this); + else + NetworkEntityManager::RemoveNetworkEntity(this); +} + +void DObject::RemoveFromNetwork() +{ + NetworkEntityManager::RemoveNetworkEntity(this); +} + +static unsigned int GetNetworkID(DObject* const self) +{ + return self->GetNetworkID(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkID, GetNetworkID) +{ + PARAM_SELF_PROLOGUE(DObject); + + ACTION_RETURN_INT(self->GetNetworkID()); +} + +static void EnableNetworking(DObject* const self, const bool enable) +{ + self->EnableNetworking(enable); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, EnableNetworking, EnableNetworking) +{ + PARAM_SELF_PROLOGUE(DObject); + PARAM_BOOL(enable); + + self->EnableNetworking(enable); + return 0; +} + +static DObject* GetNetworkEntity(const unsigned int id) +{ + return NetworkEntityManager::GetNetworkEntity(id); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkEntity, GetNetworkEntity) +{ + PARAM_PROLOGUE; + PARAM_UINT(id); + + ACTION_RETURN_OBJECT(NetworkEntityManager::GetNetworkEntity(id)); +} + +//========================================================================== +// +// +// +//========================================================================== + // [RH] List "ping" times CCMD (pings) { @@ -2983,11 +3191,11 @@ static void Network_Controller (int playernum, bool add) } if (add) - Net_WriteByte (DEM_ADDCONTROLLER); + Net_WriteInt8 (DEM_ADDCONTROLLER); else - Net_WriteByte (DEM_DELCONTROLLER); + Net_WriteInt8 (DEM_DELCONTROLLER); - Net_WriteByte (playernum); + Net_WriteInt8 (playernum); } //========================================================================== diff --git a/src/d_net.h b/src/d_net.h index 309ea4d349..e4029bd660 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -64,10 +64,12 @@ void Net_CheckLastReceived(int); // [RH] Functions for making and using special "ticcmds" void Net_NewMakeTic (); -void Net_WriteByte (uint8_t); -void Net_WriteWord (short); -void Net_WriteLong (int); +void Net_WriteInt8 (uint8_t); +void Net_WriteInt16 (int16_t); +void Net_WriteInt32 (int32_t); +void Net_WriteInt64(int64_t); void Net_WriteFloat (float); +void Net_WriteDouble(double); void Net_WriteString (const char *); void Net_WriteBytes (const uint8_t *, int len); @@ -93,6 +95,29 @@ extern int nodeforplayer[MAXPLAYERS]; extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS]; extern int ticdup; +class player_t; +class DObject; + +class NetworkEntityManager +{ +private: + inline static TArray s_netEntities = {}; + inline static TArray s_openNetIDs = {}; + +public: + NetworkEntityManager() = delete; + + inline static uint32_t WorldNetID = 0u; + inline static uint32_t ClientNetIDStart = 1u; + inline static uint32_t NetIDStart = MAXPLAYERS + 1u; + + static void InitializeNetworkEntities(); + static void SetClientNetworkEntity(player_t* const client); + static void AddNetworkEntity(DObject* const ent); + static void RemoveNetworkEntity(DObject* const ent); + static DObject* GetNetworkEntity(const uint32_t id); +}; + // [RH] // New generic packet structure: // diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index f276233631..3d35e50296 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -161,7 +161,7 @@ int D_PlayerClassToInt (const char *classname) { auto type = PlayerClasses[i].Type; - if (type->GetDisplayName().IsNotEmpty() && stricmp(type->GetDisplayName(), classname) == 0) + if (type->GetDisplayName().IsNotEmpty() && type->GetDisplayName().CompareNoCase(classname) == 0) { return i; } @@ -321,7 +321,7 @@ static void UpdateTeam (int pnum, int team, bool update) if ((dmflags2 & DF2_NO_TEAM_SWITCH) && (alwaysapplydmflags || deathmatch) && TeamLibrary.IsValidTeam (info->GetTeam())) { - Printf ("%s\n", GStrings("TXT_NO_TEAM_CHANGE")); + Printf ("%s\n", GStrings.GetString("TXT_NO_TEAM_CHANGE")); return; } @@ -339,12 +339,12 @@ static void UpdateTeam (int pnum, int team, bool update) FString message; if (TeamLibrary.IsValidTeam (team)) { - message = GStrings("TXT_JOINED_TEAM"); + message = GStrings.GetString("TXT_JOINED_TEAM"); message.Substitute("%t", Teams[team].GetName()); } else { - message = GStrings("TXT_LONER"); + message = GStrings.GetString("TXT_LONER"); } message.Substitute("%s", info->GetName()); Printf("%s\n", message.GetChars()); @@ -393,7 +393,7 @@ void D_SetupUserInfo () // Reset everybody's userinfo to a default state. for (i = 0; i < MAXPLAYERS; i++) { - players[i].userinfo.Reset(); + players[i].userinfo.Reset(i); } // Initialize the console player's user info coninfo = &players[consoleplayer].userinfo; @@ -426,7 +426,7 @@ void D_SetupUserInfo () R_BuildPlayerTranslation(consoleplayer); } -void userinfo_t::Reset() +void userinfo_t::Reset(int pnum) { // Clear this player's userinfo. TMapIterator it(*this); @@ -469,6 +469,9 @@ void userinfo_t::Reset() newcvar->SetExtraDataPointer(cvar); // store backing cvar } + newcvar->pnum = pnum; + newcvar->userinfoName = cvarname; + Insert(cvarname, newcvar); } } @@ -568,7 +571,7 @@ void D_UserInfoChanged (FBaseCVar *cvar) mysnprintf (foo, countof(foo), "\\%s\\%s", cvar->GetName(), escaped_val.GetChars()); - Net_WriteByte (DEM_UINFCHANGED); + Net_WriteInt8 (DEM_UINFCHANGED); Net_WriteString (foo); } @@ -589,7 +592,7 @@ static const char *SetServerVar (char *name, ECVarType type, uint8_t **stream, b { return NULL; } - bitdata = ReadByte (stream); + bitdata = ReadInt8 (stream); mask = 1 << (bitdata & 31); if (bitdata & 32) { @@ -605,8 +608,8 @@ static const char *SetServerVar (char *name, ECVarType type, uint8_t **stream, b { switch (type) { - case CVAR_Bool: value.Bool = ReadByte (stream) ? 1 : 0; break; - case CVAR_Int: value.Int = ReadLong (stream); break; + case CVAR_Bool: value.Bool = ReadInt8 (stream) ? 1 : 0; break; + case CVAR_Int: value.Int = ReadInt32 (stream); break; case CVAR_Float: value.Float = ReadFloat (stream); break; case CVAR_String: value.String = ReadString (stream); break; default: break; // Silence GCC @@ -662,13 +665,13 @@ bool D_SendServerInfoChange (FBaseCVar *cvar, UCVarValue value, ECVarType type) namelen = strlen(cvar->GetName()); - Net_WriteByte(DEM_SINFCHANGED); - Net_WriteByte((uint8_t)(namelen | (type << 6))); + Net_WriteInt8(DEM_SINFCHANGED); + Net_WriteInt8((uint8_t)(namelen | (type << 6))); Net_WriteBytes((uint8_t*)cvar->GetName(), (int)namelen); switch (type) { - case CVAR_Bool: Net_WriteByte(value.Bool); break; - case CVAR_Int: Net_WriteLong(value.Int); break; + case CVAR_Bool: Net_WriteInt8(value.Bool); break; + case CVAR_Int: Net_WriteInt32(value.Int); break; case CVAR_Float: Net_WriteFloat(value.Float); break; case CVAR_String: Net_WriteString(value.String); break; default: break; // Silence GCC @@ -693,10 +696,10 @@ bool D_SendServerFlagChange (FBaseCVar *cvar, int bitnum, bool set, bool silent) int namelen = (int)strlen(cvar->GetName()); - Net_WriteByte(DEM_SINFCHANGEDXOR); - Net_WriteByte((uint8_t)namelen); + Net_WriteInt8(DEM_SINFCHANGEDXOR); + Net_WriteInt8((uint8_t)namelen); Net_WriteBytes((uint8_t*)cvar->GetName(), namelen); - Net_WriteByte(uint8_t(bitnum | (set << 5))); + Net_WriteInt8(uint8_t(bitnum | (set << 5))); return true; } return false; @@ -709,7 +712,7 @@ void D_DoServerInfoChange (uint8_t **stream, bool singlebit) int len; int type; - len = ReadByte (stream); + len = ReadInt8 (stream); type = len >> 6; len &= 0x3f; if (len == 0) @@ -786,7 +789,7 @@ FString D_GetUserInfoStrings(int pnum, bool compact) break; case NAME_Skin: - result.AppendFormat("\\%s", D_EscapeUserInfo(Skins[info->GetSkin()].Name).GetChars()); + result.AppendFormat("\\%s", D_EscapeUserInfo(Skins[info->GetSkin()].Name.GetChars()).GetChars()); break; default: @@ -870,15 +873,15 @@ void D_ReadUserInfoStrings (int pnum, uint8_t **stream, bool update) switch (keyname.GetIndex()) { case NAME_Gender: - info->GenderChanged(value); + info->GenderChanged(value.GetChars()); break; case NAME_PlayerClass: - info->PlayerClassChanged(value); + info->PlayerClassChanged(value.GetChars()); break; case NAME_Skin: - info->SkinChanged(value, players[pnum].CurrentPlayerClass); + info->SkinChanged(value.GetChars(), players[pnum].CurrentPlayerClass); if (players[pnum].mo != NULL) { if (players[pnum].cls != NULL && @@ -895,11 +898,11 @@ void D_ReadUserInfoStrings (int pnum, uint8_t **stream, bool update) break; case NAME_Team: - UpdateTeam(pnum, atoi(value), update); + UpdateTeam(pnum, atoi(value.GetChars()), update); break; case NAME_Color: - info->ColorChanged(value); + info->ColorChanged(value.GetChars()); break; default: @@ -956,7 +959,7 @@ void WriteUserInfo(FSerializer &arc, userinfo_t &info) switch (pair->Key.GetIndex()) { case NAME_Skin: - string = Skins[info.GetSkin()].Name; + string = Skins[info.GetSkin()].Name.GetChars(); break; case NAME_PlayerClass: @@ -969,7 +972,7 @@ void WriteUserInfo(FSerializer &arc, userinfo_t &info) string = val.String; break; } - arc.StringPtr(name, string); + arc.StringPtr(name.GetChars(), string); } arc.EndObject(); } @@ -981,7 +984,6 @@ void ReadUserInfo(FSerializer &arc, userinfo_t &info, FString &skin) const char *key; const char *str; - info.Reset(); skin = ""; if (arc.BeginObject("userinfo")) { diff --git a/src/d_protocol.cpp b/src/d_protocol.cpp index 1079419768..ec1750a12e 100644 --- a/src/d_protocol.cpp +++ b/src/d_protocol.cpp @@ -55,35 +55,54 @@ const char *ReadStringConst(uint8_t **stream) return string; } -int ReadByte (uint8_t **stream) +uint8_t ReadInt8 (uint8_t **stream) { uint8_t v = **stream; *stream += 1; return v; } -int ReadWord (uint8_t **stream) +int16_t ReadInt16 (uint8_t **stream) { - short v = (((*stream)[0]) << 8) | (((*stream)[1])); + int16_t v = (((*stream)[0]) << 8) | (((*stream)[1])); *stream += 2; return v; } -int ReadLong (uint8_t **stream) +int32_t ReadInt32 (uint8_t **stream) { - int v = (((*stream)[0]) << 24) | (((*stream)[1]) << 16) | (((*stream)[2]) << 8) | (((*stream)[3])); + int32_t v = (((*stream)[0]) << 24) | (((*stream)[1]) << 16) | (((*stream)[2]) << 8) | (((*stream)[3])); *stream += 4; return v; } +int64_t ReadInt64(uint8_t** stream) +{ + int64_t v = (int64_t((*stream)[0]) << 56) | (int64_t((*stream)[1]) << 48) | (int64_t((*stream)[2]) << 40) | (int64_t((*stream)[3]) << 32) + | (int64_t((*stream)[4]) << 24) | (int64_t((*stream)[5]) << 16) | (int64_t((*stream)[6]) << 8) | (int64_t((*stream)[7])); + *stream += 8; + return v; +} + float ReadFloat (uint8_t **stream) { union { - int i; + int32_t i; float f; } fakeint; - fakeint.i = ReadLong (stream); + fakeint.i = ReadInt32 (stream); + return fakeint.f; +} + +double ReadDouble(uint8_t** stream) +{ + union + { + int64_t i; + double f; + } fakeint; + fakeint.i = ReadInt64(stream); return fakeint.f; } @@ -100,20 +119,20 @@ void WriteString (const char *string, uint8_t **stream) } -void WriteByte (uint8_t v, uint8_t **stream) +void WriteInt8 (uint8_t v, uint8_t **stream) { **stream = v; *stream += 1; } -void WriteWord (short v, uint8_t **stream) +void WriteInt16 (int16_t v, uint8_t **stream) { (*stream)[0] = v >> 8; (*stream)[1] = v & 255; *stream += 2; } -void WriteLong (int v, uint8_t **stream) +void WriteInt32 (int32_t v, uint8_t **stream) { (*stream)[0] = v >> 24; (*stream)[1] = (v >> 16) & 255; @@ -122,15 +141,39 @@ void WriteLong (int v, uint8_t **stream) *stream += 4; } +void WriteInt64(int64_t v, uint8_t** stream) +{ + (*stream)[0] = v >> 56; + (*stream)[1] = (v >> 48) & 255; + (*stream)[2] = (v >> 40) & 255; + (*stream)[3] = (v >> 32) & 255; + (*stream)[4] = (v >> 24) & 255; + (*stream)[5] = (v >> 16) & 255; + (*stream)[6] = (v >> 8) & 255; + (*stream)[7] = v & 255; + *stream += 8; +} + void WriteFloat (float v, uint8_t **stream) { union { - int i; + int32_t i; float f; } fakeint; fakeint.f = v; - WriteLong (fakeint.i, stream); + WriteInt32 (fakeint.i, stream); +} + +void WriteDouble(double v, uint8_t** stream) +{ + union + { + int64_t i; + double f; + } fakeint; + fakeint.f = v; + WriteInt64(fakeint.i, stream); } // Returns the number of bytes read @@ -151,7 +194,7 @@ int UnpackUserCmd (usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stream) memset (ucmd, 0, sizeof(usercmd_t)); } - flags = ReadByte (stream); + flags = ReadInt8 (stream); if (flags) { @@ -159,20 +202,20 @@ int UnpackUserCmd (usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stream) if (flags & UCMDF_BUTTONS) { uint32_t buttons = ucmd->buttons; - uint8_t in = ReadByte(stream); + uint8_t in = ReadInt8(stream); buttons = (buttons & ~0x7F) | (in & 0x7F); if (in & 0x80) { - in = ReadByte(stream); + in = ReadInt8(stream); buttons = (buttons & ~(0x7F << 7)) | ((in & 0x7F) << 7); if (in & 0x80) { - in = ReadByte(stream); + in = ReadInt8(stream); buttons = (buttons & ~(0x7F << 14)) | ((in & 0x7F) << 14); if (in & 0x80) { - in = ReadByte(stream); + in = ReadInt8(stream); buttons = (buttons & ~(0xFF << 21)) | (in << 21); } } @@ -180,17 +223,17 @@ int UnpackUserCmd (usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stream) ucmd->buttons = buttons; } if (flags & UCMDF_PITCH) - ucmd->pitch = ReadWord (stream); + ucmd->pitch = ReadInt16 (stream); if (flags & UCMDF_YAW) - ucmd->yaw = ReadWord (stream); + ucmd->yaw = ReadInt16 (stream); if (flags & UCMDF_FORWARDMOVE) - ucmd->forwardmove = ReadWord (stream); + ucmd->forwardmove = ReadInt16 (stream); if (flags & UCMDF_SIDEMOVE) - ucmd->sidemove = ReadWord (stream); + ucmd->sidemove = ReadInt16 (stream); if (flags & UCMDF_UPMOVE) - ucmd->upmove = ReadWord (stream); + ucmd->upmove = ReadInt16 (stream); if (flags & UCMDF_ROLL) - ucmd->roll = ReadWord (stream); + ucmd->roll = ReadInt16 (stream); } return int(*stream - start); @@ -211,7 +254,7 @@ int PackUserCmd (const usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stream basis = ␣ } - WriteByte (0, stream); // Make room for the packing bits + WriteInt8 (0, stream); // Make room for the packing bits buttons_changed = ucmd->buttons ^ basis->buttons; if (buttons_changed != 0) @@ -235,16 +278,16 @@ int PackUserCmd (const usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stream } } } - WriteByte (bytes[0], stream); + WriteInt8 (bytes[0], stream); if (bytes[0] & 0x80) { - WriteByte (bytes[1], stream); + WriteInt8 (bytes[1], stream); if (bytes[1] & 0x80) { - WriteByte (bytes[2], stream); + WriteInt8 (bytes[2], stream); if (bytes[2] & 0x80) { - WriteByte (bytes[3], stream); + WriteInt8 (bytes[3], stream); } } } @@ -252,36 +295,36 @@ int PackUserCmd (const usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stream if (ucmd->pitch != basis->pitch) { flags |= UCMDF_PITCH; - WriteWord (ucmd->pitch, stream); + WriteInt16 (ucmd->pitch, stream); } if (ucmd->yaw != basis->yaw) { flags |= UCMDF_YAW; - WriteWord (ucmd->yaw, stream); + WriteInt16 (ucmd->yaw, stream); } if (ucmd->forwardmove != basis->forwardmove) { flags |= UCMDF_FORWARDMOVE; - WriteWord (ucmd->forwardmove, stream); + WriteInt16 (ucmd->forwardmove, stream); } if (ucmd->sidemove != basis->sidemove) { flags |= UCMDF_SIDEMOVE; - WriteWord (ucmd->sidemove, stream); + WriteInt16 (ucmd->sidemove, stream); } if (ucmd->upmove != basis->upmove) { flags |= UCMDF_UPMOVE; - WriteWord (ucmd->upmove, stream); + WriteInt16 (ucmd->upmove, stream); } if (ucmd->roll != basis->roll) { flags |= UCMDF_ROLL; - WriteWord (ucmd->roll, stream); + WriteInt16 (ucmd->roll, stream); } // Write the packing bits - WriteByte (flags, &temp); + WriteInt8 (flags, &temp); return int(*stream - start); } @@ -329,7 +372,7 @@ int WriteUserCmdMessage (usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stre ucmd->upmove != 0 || ucmd->roll != 0) { - WriteByte (DEM_USERCMD, stream); + WriteInt8 (DEM_USERCMD, stream); return PackUserCmd (ucmd, basis, stream) + 1; } } @@ -342,11 +385,11 @@ int WriteUserCmdMessage (usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stre ucmd->upmove != basis->upmove || ucmd->roll != basis->roll) { - WriteByte (DEM_USERCMD, stream); + WriteInt8 (DEM_USERCMD, stream); return PackUserCmd (ucmd, basis, stream) + 1; } - WriteByte (DEM_EMPTYUSERCMD, stream); + WriteInt8 (DEM_EMPTYUSERCMD, stream); return 1; } @@ -417,11 +460,11 @@ void ReadTicCmd (uint8_t **stream, int player, int tic) int ticmod = tic % BACKUPTICS; tcmd = &netcmds[player][ticmod]; - tcmd->consistancy = ReadWord (stream); + tcmd->consistancy = ReadInt16 (stream); start = *stream; - while ((type = ReadByte (stream)) != DEM_USERCMD && type != DEM_EMPTYUSERCMD) + while ((type = ReadInt8 (stream)) != DEM_USERCMD && type != DEM_EMPTYUSERCMD) Net_SkipCommand (type, stream); NetSpecs[player][ticmod].SetData (start, int(*stream - start - 1)); @@ -460,7 +503,7 @@ void RunNetSpecs (int player, int buf) uint8_t *end = stream + len; while (stream < end) { - int type = ReadByte (&stream); + int type = ReadInt8 (&stream); Net_DoCommand (type, &stream, player); } if (!demorecording) @@ -475,7 +518,7 @@ uint8_t *lenspot; // for the length field. void StartChunk (int id, uint8_t **stream) { - WriteLong (id, stream); + WriteInt32 (id, stream); lenspot = *stream; *stream += 4; } @@ -490,9 +533,9 @@ void FinishChunk (uint8_t **stream) return; len = int(*stream - lenspot - 4); - WriteLong (len, &lenspot); + WriteInt32 (len, &lenspot); if (len & 1) - WriteByte (0, stream); + WriteInt8 (0, stream); lenspot = NULL; } @@ -503,6 +546,6 @@ void SkipChunk (uint8_t **stream) { int len; - len = ReadLong (stream); + len = ReadInt32 (stream); *stream += len + (len & 1); } diff --git a/src/d_protocol.h b/src/d_protocol.h index 2c36a1874f..33fa109660 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -163,6 +163,7 @@ enum EDemoCommand DEM_MDK, // 71 String: Damage type DEM_SETINV, // 72 SetInventory DEM_ENDSCREENJOB, + DEM_ZSC_CMD, // 74 String: Command, Word: Byte size of command }; // The following are implemented by cht_DoCheat in m_cheat.cpp @@ -246,16 +247,20 @@ int SkipTicCmd (uint8_t **stream, int count); void ReadTicCmd (uint8_t **stream, int player, int tic); void RunNetSpecs (int player, int buf); -int ReadByte (uint8_t **stream); -int ReadWord (uint8_t **stream); -int ReadLong (uint8_t **stream); +uint8_t ReadInt8 (uint8_t **stream); +int16_t ReadInt16 (uint8_t **stream); +int32_t ReadInt32 (uint8_t **stream); +int64_t ReadInt64(uint8_t** stream); float ReadFloat (uint8_t **stream); +double ReadDouble(uint8_t** stream); char *ReadString (uint8_t **stream); const char *ReadStringConst(uint8_t **stream); -void WriteByte (uint8_t val, uint8_t **stream); -void WriteWord (short val, uint8_t **stream); -void WriteLong (int val, uint8_t **stream); +void WriteInt8 (uint8_t val, uint8_t **stream); +void WriteInt16 (int16_t val, uint8_t **stream); +void WriteInt32 (int32_t val, uint8_t **stream); +void WriteInt64(int64_t val, uint8_t** stream); void WriteFloat (float val, uint8_t **stream); +void WriteDouble(double val, uint8_t** stream); void WriteString (const char *string, uint8_t **stream); #endif //__D_PROTOCOL_H__ diff --git a/src/doomdata.h b/src/doomdata.h index 12a2869219..40d3b6862b 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -382,6 +382,7 @@ struct FMapThing int FloatbobPhase; int friendlyseeblocks; FName arg0str; + double SourceRadius; }; diff --git a/src/doomdef.h b/src/doomdef.h index bdeb81611f..98fa88d939 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -180,6 +180,13 @@ enum : unsigned enum : unsigned { DF3_NO_PLAYER_CLIP = 1 << 0, // Players can walk through and shoot through each other + DF3_COOP_SHARE_KEYS = 1 << 1, // Keys and other core items will be given to all players in coop + DF3_LOCAL_ITEMS = 1 << 2, // Items are picked up client-side rather than fully taken by the client who picked it up + DF3_NO_LOCAL_DROPS = 1 << 3, // Drops from Actors aren't picked up locally + DF3_NO_COOP_ONLY_ITEMS = 1 << 4, // Items that only appear in co-op are disabled + DF3_NO_COOP_ONLY_THINGS = 1 << 5, // Any Actor that only appears in co-op is disabled + DF3_REMEMBER_LAST_WEAP = 1 << 6, // When respawning in co-op, keep the last used weapon out instead of switching to the best new one. + DF3_PISTOL_START = 1 << 7, // Take player inventory when exiting to the next level. }; // [RH] Compatibility flags. @@ -213,7 +220,7 @@ enum : unsigned int COMPATF_VILEGHOSTS = 1 << 25, // Crushed monsters are resurrected as ghosts. COMPATF_NOBLOCKFRIENDS = 1 << 26, // Friendly monsters aren't blocked by monster-blocking lines. COMPATF_SPRITESORT = 1 << 27, // Invert sprite sorting order for sprites of equal distance - COMPATF_HITSCAN = 1 << 28, // Hitscans use original blockmap anf hit check code. + COMPATF_HITSCAN = 1 << 28, // Hitscans use original blockmap and hit check code. COMPATF_LIGHT = 1 << 29, // Find neighboring light level like Doom COMPATF_POLYOBJ = 1 << 30, // Draw polyobjects the old fashioned way COMPATF_MASKEDMIDTEX = 1u << 31, // Ignore compositing when drawing masked midtextures @@ -251,6 +258,7 @@ enum BCOMPATF_NOSLOPEID = 1 << 9, // disable line IDs on slopes. BCOMPATF_CLIPMIDTEX = 1 << 10, // Always Clip midtex's in the software renderer (required to run certain GZDoom maps, has no effect in the hardware renderer) BCOMPATF_NOSECTIONMERGE = 1 << 11, // (for IWAD maps) keep separate sections for sectors with intra-sector linedefs. + BCOMPATF_NOMIRRORS = 1 << 12, // disable mirrors, for maps that have broken setups. }; // phares 3/20/98: diff --git a/src/events.cpp b/src/events.cpp index d179ac50af..a4773d1332 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -31,7 +31,6 @@ ** */ #include "events.h" -#include "vm.h" #include "vmintern.h" #include "r_utility.h" #include "g_levellocals.h" @@ -45,6 +44,225 @@ EventManager staticEventManager; +static int ListGetInt(VMVa_List& tags) +{ + if (tags.curindex < tags.numargs) + { + if (tags.reginfo[tags.curindex] == REGT_FLOAT) + return static_cast(tags.args[tags.curindex++].f); + + if (tags.reginfo[tags.curindex] == REGT_INT) + return tags.args[tags.curindex++].i; + + ThrowAbortException(X_OTHER, "Invalid parameter in network command function, int expected"); + } + + return TAG_DONE; +} + +static double ListGetDouble(VMVa_List& tags) +{ + if (tags.curindex < tags.numargs) + { + if (tags.reginfo[tags.curindex] == REGT_FLOAT) + return tags.args[tags.curindex++].f; + + if (tags.reginfo[tags.curindex] == REGT_INT) + return tags.args[tags.curindex++].i; + + ThrowAbortException(X_OTHER, "Invalid parameter in network command function, float expected"); + } + + return TAG_DONE; +} + +static const FString* ListGetString(VMVa_List& tags) +{ + if (tags.curindex < tags.numargs) + { + if (tags.reginfo[tags.curindex] == REGT_STRING) + return &tags.args[tags.curindex++].s(); + + ThrowAbortException(X_OTHER, "Invalid parameter in network command function, string expected"); + } + + return nullptr; +} + +IMPLEMENT_CLASS(DNetworkBuffer, false, false); + +void DNetworkBuffer::AddInt8(int byte) +{ + ++_size; + _buffer.Push({ NET_INT8, byte }); +} + +void DNetworkBuffer::AddInt16(int word) +{ + _size += 2u; + _buffer.Push({ NET_INT16, word }); +} + +void DNetworkBuffer::AddInt(int msg) +{ + _size += 4u; + _buffer.Push({ NET_INT, msg }); +} + +void DNetworkBuffer::AddFloat(double msg) +{ + _size += 4u; + _buffer.Push({ NET_FLOAT, msg }); +} + +void DNetworkBuffer::AddDouble(double msg) +{ + _size += 8u; + _buffer.Push({ NET_DOUBLE, msg }); +} + +void DNetworkBuffer::AddString(const FString& msg) +{ + _size += msg.Len() + 1u; + _buffer.Push({ NET_STRING, msg }); +} + +void DNetworkBuffer::OnDestroy() +{ + Super::OnDestroy(); + + _buffer.Reset(); +} + +void DNetworkBuffer::Serialize(FSerializer& arc) +{ + Super::Serialize(arc); + + if (arc.isWriting()) + { + if (!_buffer.Size()) + return; + + if (arc.BeginArray("types")) + { + for (const auto& value : _buffer) + { + int i = value.GetType(); + arc(nullptr, i); + } + + arc.EndArray(); + } + + if (arc.BeginArray("values")) + { + for (const auto& value : _buffer) + { + switch (value.GetType()) + { + case NET_DOUBLE: + case NET_FLOAT: + { + double f = value.GetDouble(); + arc(nullptr, f); + break; + } + + case NET_STRING: + { + FString s = value.GetString(); + arc(nullptr, s); + break; + } + + default: + { + int i = value.GetInt(); + arc(nullptr, i); + break; + } + } + } + + arc.EndArray(); + } + } + else + { + TArray types = {}; + arc("types", types); + + if (!types.Size()) + return; + + if (arc.BeginArray("values")) + { + // Something got corrupted, don't repopulate the buffer. + if (arc.ArraySize() != types.Size()) + { + arc.EndArray(); + return; + } + + for (int type : types) + { + switch (type) + { + case NET_INT8: + { + int i = 0; + arc(nullptr, i); + AddInt8(i); + break; + } + + case NET_INT16: + { + int i = 0; + arc(nullptr, i); + AddInt16(i); + break; + } + + case NET_INT: + { + int i = 0; + arc(nullptr, i); + AddInt(i); + break; + } + + case NET_FLOAT: + { + double f = 0.0; + arc(nullptr, f); + AddFloat(f); + break; + } + + case NET_DOUBLE: + { + double f = 0.0; + arc(nullptr, f); + AddDouble(f); + break; + } + + case NET_STRING: + { + FString s = {}; + arc(nullptr, s); + AddString(s); + break; + } + } + } + + arc.EndArray(); + } + } +} + void EventManager::CallOnRegister() { for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next) @@ -165,13 +383,157 @@ bool EventManager::SendNetworkEvent(FString name, int arg1, int arg2, int arg3, if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) return false; - Net_WriteByte(DEM_NETEVENT); - Net_WriteString(name); - Net_WriteByte(3); - Net_WriteLong(arg1); - Net_WriteLong(arg2); - Net_WriteLong(arg3); - Net_WriteByte(manual); + Net_WriteInt8(DEM_NETEVENT); + Net_WriteString(name.GetChars()); + Net_WriteInt8(3); + Net_WriteInt32(arg1); + Net_WriteInt32(arg2); + Net_WriteInt32(arg3); + Net_WriteInt8(manual); + + return true; +} + +bool EventManager::SendNetworkCommand(const FName& cmd, VMVa_List& args) +{ + if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) + return false; + + // Calculate the size of the message so we know where it ends. + unsigned int bytes = 0u; + int tag = ListGetInt(args); + while (tag != TAG_DONE) + { + switch (tag) + { + case NET_INT8: + ++bytes; + break; + + case NET_INT16: + bytes += 2u; + break; + + case NET_INT: + case NET_FLOAT: + bytes += 4u; + break; + + case NET_DOUBLE: + bytes += 8u; + break; + + case NET_STRING: + { + ++bytes; // Strings will always consume at least one byte. + const FString* str = ListGetString(args); + if (str != nullptr) + bytes += str->Len(); + break; + } + } + + if (tag != NET_STRING) + ++args.curindex; + + tag = ListGetInt(args); + } + + Net_WriteInt8(DEM_ZSC_CMD); + Net_WriteString(cmd.GetChars()); + Net_WriteInt16(bytes); + + constexpr char Default[] = ""; + + args.curindex = 0; + tag = ListGetInt(args); + while (tag != TAG_DONE) + { + switch (tag) + { + default: + ++args.curindex; + break; + + case NET_INT8: + Net_WriteInt8(ListGetInt(args)); + break; + + case NET_INT16: + Net_WriteInt16(ListGetInt(args)); + break; + + case NET_INT: + Net_WriteInt32(ListGetInt(args)); + break; + + case NET_FLOAT: + Net_WriteFloat(ListGetDouble(args)); + break; + + case NET_DOUBLE: + Net_WriteDouble(ListGetDouble(args)); + break; + + case NET_STRING: + { + const FString* str = ListGetString(args); + if (str != nullptr) + Net_WriteString(str->GetChars()); + else + Net_WriteString(Default); // Still have to send something here to be read correctly. + break; + } + } + + tag = ListGetInt(args); + } + + return true; +} + +bool EventManager::SendNetworkBuffer(const FName& cmd, const DNetworkBuffer* buffer) +{ + if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) + return false; + + Net_WriteInt8(DEM_ZSC_CMD); + Net_WriteString(cmd.GetChars()); + Net_WriteInt16(buffer != nullptr ? buffer->GetBytes() : 0); + + if (buffer != nullptr) + { + for (unsigned int i = 0u; i < buffer->GetBufferSize(); ++i) + { + const auto& value = buffer->GetValue(i); + switch (value.GetType()) + { + case NET_INT8: + Net_WriteInt8(value.GetInt()); + break; + + case NET_INT16: + Net_WriteInt16(value.GetInt()); + break; + + case NET_INT: + Net_WriteInt32(value.GetInt()); + break; + + case NET_FLOAT: + Net_WriteFloat(value.GetDouble()); + break; + + case NET_DOUBLE: + Net_WriteDouble(value.GetDouble()); + break; + + case NET_STRING: + Net_WriteString(value.GetString()); + break; + } + } + } return true; } @@ -524,6 +886,14 @@ bool EventManager::Responder(const event_t* ev) return false; } +void EventManager::NetCommand(FNetworkCommand& cmd) +{ + if (ShouldCallStatic(false)) staticEventManager.NetCommand(cmd); + + for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next) + handler->NetCommandProcess(cmd); +} + void EventManager::Console(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui) { if (ShouldCallStatic(false)) staticEventManager.Console(player, name, arg1, arg2, arg3, manual, ui); @@ -673,6 +1043,501 @@ DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, Replacee) DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, Replacement) DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, IsFinal) +DEFINE_FIELD(FNetworkCommand, Player) +DEFINE_FIELD(FNetworkCommand, Command) + +static int NativeReadInt8(FNetworkCommand* const self) { return self->ReadInt8(); } + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadInt8, NativeReadInt8) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_INT(self->ReadInt8()); +} + +static int NativeReadInt16(FNetworkCommand* const self) { return self->ReadInt16(); } + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadInt16, NativeReadInt16) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_INT(self->ReadInt16()); +} + +static int NativeReadInt(FNetworkCommand* const self) { return self->ReadInt(); } + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadInt, NativeReadInt) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_INT(self->ReadInt()); +} + +static double NativeReadFloat(FNetworkCommand* const self) { return self->ReadFloat(); } + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadFloat, NativeReadFloat) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_FLOAT(self->ReadFloat()); +} + +static double NativeReadDouble(FNetworkCommand* const self) { return self->ReadDouble(); } + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadDouble, NativeReadDouble) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_FLOAT(self->ReadDouble()); +} + +static void NativeReadString(FNetworkCommand* const self, FString* const result) +{ + const auto str = self->ReadString(); + if (str != nullptr) + *result = str; +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadString, NativeReadString) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + FString res = {}; + NativeReadString(self, &res); + ACTION_RETURN_STRING(res); +} + +static int NativeReadName(FNetworkCommand* const self) +{ + FName res = NAME_None; + const auto str = self->ReadString(); + if (str != nullptr) + res = str; + + return res.GetIndex(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadName, NativeReadName) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_INT(NativeReadName(self)); +} + +static double NativeReadMapUnit(FNetworkCommand* const self) +{ + constexpr double FixedToFloat = 1.0 / (1 << 16); + return self->ReadInt() * FixedToFloat; +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadMapUnit, NativeReadMapUnit) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_FLOAT(NativeReadMapUnit(self)); +} + +static double NativeReadAngle(FNetworkCommand* const self) { return DAngle::fromBam(self->ReadInt()).Degrees(); } + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadAngle, NativeReadAngle) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_FLOAT(DAngle::fromBam(self->ReadInt()).Degrees()); +} + +static void NativeReadVector2(FNetworkCommand* const self, DVector2* const result) +{ + result->X = self->ReadDouble(); + result->Y = self->ReadDouble(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadVector2, NativeReadVector2) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_VEC2(DVector2(self->ReadDouble(), self->ReadDouble())); +} + +static void NativeReadVector3(FNetworkCommand* const self, DVector3* const result) +{ + result->X = self->ReadDouble(); + result->Y = self->ReadDouble(); + result->Z = self->ReadDouble(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadVector3, NativeReadVector3) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_VEC3(DVector3(self->ReadDouble(), self->ReadDouble(), self->ReadDouble())); +} + +static void NativeReadVector4(FNetworkCommand* const self, DVector4* const result) +{ + result->X = self->ReadDouble(); + result->Y = self->ReadDouble(); + result->Z = self->ReadDouble(); + result->W = self->ReadDouble(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadVector4, NativeReadVector4) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_VEC4(DVector4(self->ReadDouble(), self->ReadDouble(), self->ReadDouble(), self->ReadDouble())); +} + +static void NativeReadQuat(FNetworkCommand* const self, DQuaternion* const result) +{ + result->X = self->ReadDouble(); + result->Y = self->ReadDouble(); + result->Z = self->ReadDouble(); + result->W = self->ReadDouble(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadQuat, NativeReadQuat) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_QUAT(DQuaternion(self->ReadDouble(), self->ReadDouble(), self->ReadDouble(), self->ReadDouble())); +} + +static void NativeReadIntArray(FNetworkCommand* const self, TArray* const values, const int type) +{ + const unsigned int size = self->ReadInt(); + for (unsigned int i = 0u; i < size; ++i) + { + switch (type) + { + case NET_INT8: + values->Push(self->ReadInt8()); + break; + + case NET_INT16: + values->Push(self->ReadInt16()); + break; + + default: + values->Push(self->ReadInt()); + break; + } + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadIntArray, NativeReadIntArray) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + PARAM_OUTPOINTER(values, TArray); + PARAM_INT(type); + + NativeReadIntArray(self, values, type); + return 0; +} + +static void NativeReadDoubleArray(FNetworkCommand* const self, TArray* const values, const bool doublePrecision) +{ + const unsigned int size = self->ReadInt(); + for (unsigned int i = 0u; i < size; ++i) + { + if (doublePrecision) + values->Push(self->ReadDouble()); + else + values->Push(self->ReadFloat()); + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadDoubleArray, NativeReadDoubleArray) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + PARAM_OUTPOINTER(values, TArray); + PARAM_BOOL(doublePrecision); + + NativeReadDoubleArray(self, values, doublePrecision); + return 0; +} + +static void NativeReadStringArray(FNetworkCommand* const self, TArray* const values, const bool skipEmpty) +{ + const unsigned int size = self->ReadInt(); + for (unsigned int i = 0u; i < size; ++i) + { + FString res = {}; + const auto str = self->ReadString(); + if (str != nullptr) + res = str; + + if (!skipEmpty || !res.IsEmpty()) + values->Push(res); + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, ReadStringArray, NativeReadStringArray) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + PARAM_OUTPOINTER(values, TArray); + PARAM_BOOL(skipEmpty); + + NativeReadStringArray(self, values, skipEmpty); + return 0; +} + +static int EndOfStream(FNetworkCommand* const self) { return self->EndOfStream(); } + +DEFINE_ACTION_FUNCTION_NATIVE(FNetworkCommand, EndOfStream, EndOfStream) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + ACTION_RETURN_BOOL(self->EndOfStream()); +} + +static void AddInt8(DNetworkBuffer* const self, const int value) { self->AddInt8(value); } + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddInt8, AddInt8) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_INT(value); + self->AddInt8(value); + return 0; +} + +static void AddInt16(DNetworkBuffer* const self, const int value) { self->AddInt16(value); } + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddInt16, AddInt16) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_INT(value); + self->AddInt16(value); + return 0; +} + +static void AddInt(DNetworkBuffer* const self, const int value) { self->AddInt(value); } + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddInt, AddInt) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_INT(value); + self->AddInt(value); + return 0; +} + +static void AddFloat(DNetworkBuffer* const self, const double value) { self->AddFloat(value); } + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddFloat, AddFloat) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(value); + self->AddFloat(value); + return 0; +} + +static void AddDouble(DNetworkBuffer* const self, const double value) { self->AddDouble(value); } + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddDouble, AddDouble) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(value); + self->AddDouble(value); + return 0; +} + +static void AddString(DNetworkBuffer* const self, const FString& value) { self->AddString(value); } + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddString, AddString) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_STRING(value); + self->AddString(value); + return 0; +} + +static void AddName(DNetworkBuffer* const self, const int value) { FName x = ENamedName(value); self->AddString(x.GetChars()); } + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddName, AddName) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_NAME(value); + self->AddString(value.GetChars()); + return 0; +} + +static void AddMapUnit(DNetworkBuffer* const self, const double value) +{ + constexpr int FloatToFixed = 1 << 16; + self->AddInt(static_cast(value * FloatToFixed)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddMapUnit, AddMapUnit) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(value); + + AddMapUnit(self, value); + return 0; +} + +static void AddAngle(DNetworkBuffer* const self, const double value) { self->AddInt(DAngle::fromDeg(value).BAMs()); } + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddAngle, AddAngle) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_ANGLE(value); + self->AddInt(value.BAMs()); + return 0; +} + +static void AddVector2(DNetworkBuffer* const self, const double x, const double y) +{ + self->AddDouble(x); + self->AddDouble(y); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddVector2, AddVector2) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + self->AddDouble(x); + self->AddDouble(y); + return 0; +} + +static void AddVector3(DNetworkBuffer* const self, const double x, const double y, const double z) +{ + self->AddDouble(x); + self->AddDouble(y); + self->AddDouble(z); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddVector3, AddVector3) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + self->AddDouble(x); + self->AddDouble(y); + self->AddDouble(z); + return 0; +} + +static void AddVector4(DNetworkBuffer* const self, const double x, const double y, const double z, const double w) +{ + self->AddDouble(x); + self->AddDouble(y); + self->AddDouble(z); + self->AddDouble(w); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddVector4, AddVector4) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_FLOAT(w); + self->AddDouble(x); + self->AddDouble(y); + self->AddDouble(z); + self->AddDouble(w); + return 0; +} + +static void AddQuat(DNetworkBuffer* const self, const double x, const double y, const double z, const double w) +{ + self->AddDouble(x); + self->AddDouble(y); + self->AddDouble(z); + self->AddDouble(w); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddQuat, AddQuat) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_FLOAT(w); + self->AddDouble(x); + self->AddDouble(y); + self->AddDouble(z); + self->AddDouble(w); + return 0; +} + +static void AddIntArray(DNetworkBuffer* const self, TArray* const values, const int type) +{ + const unsigned int size = values->Size(); + self->AddInt(size); + for (unsigned int i = 0u; i < size; ++i) + { + switch (type) + { + case NET_INT8: + self->AddInt8((*values)[i]); + break; + + case NET_INT16: + self->AddInt16((*values)[i]); + break; + + default: + self->AddInt((*values)[i]); + break; + } + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddIntArray, AddIntArray) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_POINTER(values, TArray); + PARAM_INT(type); + + AddIntArray(self, values, type); + return 0; +} + +static void AddDoubleArray(DNetworkBuffer* const self, TArray* const values, const bool doublePrecision) +{ + const unsigned int size = values->Size(); + self->AddInt(size); + for (unsigned int i = 0u; i < size; ++i) + { + if (doublePrecision) + self->AddDouble((*values)[i]); + else + self->AddFloat((*values)[i]); + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddDoubleArray, AddDoubleArray) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_POINTER(values, TArray); + PARAM_BOOL(doublePrecision); + + AddDoubleArray(self, values, doublePrecision); + return 0; +} + +static void AddStringArray(DNetworkBuffer* const self, TArray* const values) +{ + const unsigned int size = values->Size(); + self->AddInt(size); + for (unsigned int i = 0u; i < size; ++i) + self->AddString((*values)[i]); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DNetworkBuffer, AddStringArray, AddStringArray) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_POINTER(values, TArray); + + AddStringArray(self, values); + return 0; +} + DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder) { PARAM_SELF_PROLOGUE(DStaticEventHandler); @@ -682,6 +1547,25 @@ DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder) return 0; } +DEFINE_ACTION_FUNCTION(DEventHandler, SendNetworkCommand) +{ + PARAM_PROLOGUE; + PARAM_NAME(cmd); + PARAM_VA_POINTER(va_reginfo); + + VMVa_List args = { param + 1, 0, numparam - 2, va_reginfo + 1 }; + ACTION_RETURN_BOOL(currentVMLevel->localEventManager->SendNetworkCommand(cmd, args)); +} + +DEFINE_ACTION_FUNCTION(DEventHandler, SendNetworkBuffer) +{ + PARAM_PROLOGUE; + PARAM_NAME(cmd); + PARAM_OBJECT(buffer, DNetworkBuffer); + + ACTION_RETURN_BOOL(currentVMLevel->localEventManager->SendNetworkBuffer(cmd, buffer)); +} + DEFINE_ACTION_FUNCTION(DEventHandler, SendNetworkEvent) { PARAM_PROLOGUE; @@ -1178,6 +2062,20 @@ void DStaticEventHandler::PostUiTick() } } +void DStaticEventHandler::NetCommandProcess(FNetworkCommand& cmd) +{ + IFVIRTUAL(DStaticEventHandler, NetworkCommandProcess) + { + if (isEmpty(func)) + return; + + VMValue params[] = { this, &cmd }; + VMCall(func, params, 2, nullptr, 0); + + cmd.Reset(); + } +} + void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui) { if (player < 0) diff --git a/src/events.h b/src/events.h index c97908b377..d71922b9a8 100755 --- a/src/events.h +++ b/src/events.h @@ -1,10 +1,12 @@ #pragma once +#include #include "dobject.h" #include "serializer.h" #include "d_event.h" #include "sbar.h" #include "info.h" +#include "vm.h" class DStaticEventHandler; struct EventManager; @@ -18,6 +20,229 @@ enum class EventHandlerType PerMap }; +enum ENetCmd +{ + NET_INT8 = 1, + NET_INT16, + NET_INT, + NET_FLOAT, + NET_DOUBLE, + NET_STRING, +}; + +struct FNetworkCommand +{ +private: + size_t _index = 0; + TArray _stream; + +public: + int Player; + FName Command; + + FNetworkCommand(const int player, const FName& command, TArray& stream) : Player(player), Command(command) + { + _stream.Swap(stream); + } + + inline bool EndOfStream() const + { + return _index >= _stream.Size(); + } + + inline void Reset() + { + _index = 0; + } + + int ReadInt8() + { + if (EndOfStream()) + return 0; + + return _stream[_index++]; + } + + // If a value has to cut off early, just treat the previous value as the full one. + int ReadInt16() + { + if (EndOfStream()) + return 0; + + int value = _stream[_index++]; + if (!EndOfStream()) + value = (value << 8) | _stream[_index++]; + + return value; + } + + int ReadInt() + { + if (EndOfStream()) + return 0; + + int value = _stream[_index++]; + if (!EndOfStream()) + { + value = (value << 8) | _stream[_index++]; + if (!EndOfStream()) + { + value = (value << 8) | _stream[_index++]; + if (!EndOfStream()) + value = (value << 8) | _stream[_index++]; + } + } + + return value; + } + + // Floats without their first bits are pretty meaningless so those are done first. + double ReadFloat() + { + if (EndOfStream()) + return 0.0; + + int value = _stream[_index++] << 24; + if (!EndOfStream()) + { + value |= _stream[_index++] << 16; + if (!EndOfStream()) + { + value |= _stream[_index++] << 8; + if (!EndOfStream()) + value |= _stream[_index++]; + } + } + + union + { + int32_t i; + float f; + } floatCaster; + floatCaster.i = value; + return floatCaster.f; + } + + double ReadDouble() + { + if (EndOfStream()) + return 0.0; + + int64_t value = int64_t(_stream[_index++]) << 56; + if (!EndOfStream()) + { + value |= int64_t(_stream[_index++]) << 48; + if (!EndOfStream()) + { + value |= int64_t(_stream[_index++]) << 40; + if (!EndOfStream()) + { + value |= int64_t(_stream[_index++]) << 32; + if (!EndOfStream()) + { + value |= int64_t(_stream[_index++]) << 24; + if (!EndOfStream()) + { + value |= int64_t(_stream[_index++]) << 16; + if (!EndOfStream()) + { + value |= int64_t(_stream[_index++]) << 8; + if (!EndOfStream()) + value |= int64_t(_stream[_index++]); + } + } + } + } + } + } + + union + { + int64_t i; + double f; + } floatCaster; + floatCaster.i = value; + return floatCaster.f; + } + + const char* ReadString() + { + if (EndOfStream()) + return nullptr; + + const char* str = reinterpret_cast(&_stream[_index]); + _index += strlen(str) + 1; + return str; + } +}; + +class DNetworkBuffer final : public DObject +{ + DECLARE_CLASS(DNetworkBuffer, DObject) + +public: + struct BufferValue + { + private: + ENetCmd _type; + std::variant _message; + + public: + BufferValue(const ENetCmd type, const int message) : _type(type), _message(message) {} + BufferValue(const ENetCmd type, const double message) : _type(type), _message(message) {} + BufferValue(const ENetCmd type, const FString& message) : _type(type), _message(message) {} + + inline ENetCmd GetType() const + { + return _type; + } + + inline int GetInt() const + { + return std::get(_message); + } + + inline double GetDouble() const + { + return std::get(_message); + } + + inline const char* GetString() const + { + return std::get(_message).GetChars(); + } + }; + +private: + unsigned int _size = 0u; + TArray _buffer = {}; + +public: + inline unsigned int GetBytes() const + { + return _size; + } + + inline unsigned int GetBufferSize() const + { + return _buffer.Size(); + } + + inline const BufferValue& GetValue(unsigned int i) const + { + return _buffer[i]; + } + + void AddInt8(int byte); + void AddInt16(int word); + void AddInt(int msg); + void AddFloat(double msg); + void AddDouble(double msg); + void AddString(const FString& msg); + void OnDestroy() override; + void Serialize(FSerializer& arc) override; +}; + // ============================================== // // EventHandler - base class @@ -113,6 +338,7 @@ class DStaticEventHandler : public DObject // make it a part of normal GC proces // void ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui); + void NetCommandProcess(FNetworkCommand& cmd); // void CheckReplacement(PClassActor* replacee, PClassActor** replacement, bool* final); @@ -285,6 +511,8 @@ struct EventManager bool Responder(const event_t* ev); // splits events into InputProcess and UiProcess // this executes on console/net events. void Console(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui); + // This reads from ZScript network commands. + void NetCommand(FNetworkCommand& cmd); // called when looking up the replacement for an actor class bool CheckReplacement(PClassActor* replacee, PClassActor** replacement); @@ -296,6 +524,10 @@ struct EventManager // send networked event. unified function. bool SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual); + // Send a custom network command from ZScript. + bool SendNetworkCommand(const FName& cmd, VMVa_List& args); + // Send a pre-built command buffer over. + bool SendNetworkBuffer(const FName& cmd, const DNetworkBuffer* buffer); // check if there is anything that should receive GUI events bool CheckUiProcessors(); diff --git a/src/g_dumpinfo.cpp b/src/g_dumpinfo.cpp index 96951df6fb..227b98f501 100644 --- a/src/g_dumpinfo.cpp +++ b/src/g_dumpinfo.cpp @@ -129,7 +129,7 @@ CCMD (spray) return; } - Net_WriteByte (DEM_SPRAY); + Net_WriteInt8 (DEM_SPRAY); Net_WriteString (argv[1]); } @@ -366,7 +366,7 @@ CCMD(listmaps) for (unsigned i = 0; i < wadlevelinfos.Size(); i++) { level_info_t *info = &wadlevelinfos[i]; - MapData *map = P_OpenMapData(info->MapName, true); + MapData *map = P_OpenMapData(info->MapName.GetChars(), true); if (map != NULL) { diff --git a/src/g_game.cpp b/src/g_game.cpp index a24f90f1bf..7ef0277258 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -90,11 +90,13 @@ #include "doommenu.h" #include "screenjob.h" #include "i_interface.h" +#include "fs_findfile.h" static FRandom pr_dmspawn ("DMSpawn"); static FRandom pr_pspawn ("PlayerSpawn"); +bool WriteZip(const char* filename, const FileSys::FCompressedBuffer* content, size_t contentcount); bool G_CheckDemoStatus (void); void G_ReadDemoTiccmd (ticcmd_t *cmd, int player); void G_WriteDemoTiccmd (ticcmd_t *cmd, int player, int buf); @@ -111,7 +113,6 @@ void G_DoAutoSave (); void G_DoQuickSave (); void STAT_Serialize(FSerializer &file); -bool WriteZip(const char *filename, TArray &filenames, TArray &content); CVARD_NAMED(Int, gameskill, skill, 2, CVAR_SERVERINFO|CVAR_LATCH, "sets the skill for the next newly started game") CVAR(Bool, save_formatted, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // use formatted JSON for saves (more readable but a larger files and a bit slower. @@ -121,6 +122,7 @@ CVAR (Bool, storesavepic, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, longsavemessages, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, cl_waitforsave, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR (Bool, enablescriptscreenshot, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR (Bool, cl_restartondeath, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); EXTERN_CVAR (Float, con_midtime); //========================================================================== @@ -208,7 +210,10 @@ CVAR (Float, m_forward, 1.f, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) CVAR (Float, m_side, 2.f, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) int turnheld; // for accelerative turning - + +EXTERN_CVAR (Bool, invertmouse) +EXTERN_CVAR (Bool, invertmousex) + // mouse values are used once float mousex; float mousey; @@ -317,7 +322,8 @@ CCMD (slot) } // [Nash] Option to display the name of the weapon being switched to. - if ((paused || pauseext) || players[consoleplayer].playerstate != PST_LIVE) return; + if ((paused || pauseext) || players[consoleplayer].playerstate != PST_LIVE) + return; if (SendItemUse != players[consoleplayer].ReadyWeapon && (displaynametags & 2) && StatusBar && SmallFont && SendItemUse) { StatusBar->AttachMessage(Create(nullptr, SendItemUse->GetTag(), @@ -328,12 +334,14 @@ CCMD (slot) CCMD (centerview) { - Net_WriteByte (DEM_CENTERVIEW); + if ((players[consoleplayer].cheats & CF_TOTALLYFROZEN)) + return; + Net_WriteInt8 (DEM_CENTERVIEW); } CCMD(crouch) { - Net_WriteByte(DEM_CROUCH); + Net_WriteInt8(DEM_CROUCH); } CCMD (land) @@ -761,32 +769,32 @@ void G_BuildTiccmd (ticcmd_t *cmd) if (sendpause) { sendpause = false; - Net_WriteByte (DEM_PAUSE); + Net_WriteInt8 (DEM_PAUSE); } if (sendsave) { sendsave = false; - Net_WriteByte (DEM_SAVEGAME); - Net_WriteString (savegamefile); - Net_WriteString (savedescription); + Net_WriteInt8 (DEM_SAVEGAME); + Net_WriteString (savegamefile.GetChars()); + Net_WriteString (savedescription.GetChars()); savegamefile = ""; } if (SendItemUse == (const AActor *)1) { - Net_WriteByte (DEM_INVUSEALL); + Net_WriteInt8 (DEM_INVUSEALL); SendItemUse = NULL; } else if (SendItemUse != NULL) { - Net_WriteByte (DEM_INVUSE); - Net_WriteLong (SendItemUse->InventoryID); + Net_WriteInt8 (DEM_INVUSE); + Net_WriteInt32 (SendItemUse->InventoryID); SendItemUse = NULL; } if (SendItemDrop != NULL) { - Net_WriteByte (DEM_INVDROP); - Net_WriteLong (SendItemDrop->InventoryID); - Net_WriteLong(SendItemDropAmount); + Net_WriteInt8 (DEM_INVDROP); + Net_WriteInt32 (SendItemDrop->InventoryID); + Net_WriteInt32(SendItemDropAmount); SendItemDrop = NULL; } @@ -896,7 +904,7 @@ static void ChangeSpy (int changespy) // has done this for you, since it could desync otherwise. if (!demoplayback) { - Net_WriteByte(DEM_REVERTCAMERA); + Net_WriteInt8(DEM_REVERTCAMERA); } return; } @@ -1032,9 +1040,23 @@ bool G_Responder (event_t *ev) break; // [RH] mouse buttons are sent as key up/down events - case EV_Mouse: - mousex = ev->x; - mousey = ev->y; + case EV_Mouse: + if(invertmousex) + { + mousex = -ev->x; + } + else + { + mousex = ev->x; + } + if(invertmouse) + { + mousey = -ev->y; + } + else + { + mousey = ev->y; + } break; } @@ -1139,8 +1161,8 @@ void G_Ticker () { case ga_recordgame: G_CheckDemoStatus(); - G_RecordDemo(newdemoname); - G_BeginRecording(newdemomap); + G_RecordDemo(newdemoname.GetChars()); + G_BeginRecording(newdemomap.GetChars()); [[fallthrough]]; case ga_newgame2: // Silence GCC (see above) case ga_newgame: @@ -1152,7 +1174,7 @@ void G_Ticker () G_DoLoadGame (); break; case ga_savegame: - G_DoSaveGame (true, false, savegamefile, savedescription); + G_DoSaveGame (true, false, savegamefile, savedescription.GetChars()); gameaction = ga_nothing; savegamefile = ""; savedescription = ""; @@ -1174,7 +1196,7 @@ void G_Ticker () G_DoWorldDone (); break; case ga_screenshot: - M_ScreenShot (shotfile); + M_ScreenShot (shotfile.GetChars()); shotfile = ""; gameaction = ga_nothing; break; @@ -1310,7 +1332,7 @@ void G_Ticker () if (ScreenJobTick()) { // synchronize termination with the playsim. - Net_WriteByte(DEM_ENDSCREENJOB); + Net_WriteInt8(DEM_ENDSCREENJOB); } break; @@ -1403,6 +1425,7 @@ void FLevelLocals::PlayerReborn (int player) p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately p->original_oldbuttons = ~0; p->playerstate = PST_LIVE; + NetworkEntityManager::SetClientNetworkEntity(p); if (gamestate != GS_TITLELEVEL) { @@ -1468,7 +1491,7 @@ bool FLevelLocals::CheckSpot (int playernum, FPlayerStart *mthing) // return false; players[playernum].mo->flags |= MF_SOLID; - i = P_CheckPosition(players[playernum].mo, spot); + i = P_CheckPosition(players[playernum].mo, spot.XY()); players[playernum].mo->flags &= ~MF_SOLID; players[playernum].mo->SetZ(oldz); // [RH] Restore corpse's height if (!i) @@ -1584,10 +1607,20 @@ void FLevelLocals::DeathMatchSpawnPlayer (int playernum) if (selections < 1) I_Error ("No deathmatch starts"); + bool hasSpawned = false; + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (PlayerInGame(i) && Players[i]->mo != nullptr && Players[i]->health > 0) + { + hasSpawned = true; + break; + } + } + // At level start, none of the players have mobjs attached to them, // so we always use the random deathmatch spawn. During the game, // though, we use whatever dmflags specifies. - if ((dmflags & DF_SPAWN_FARTHEST) && players[playernum].mo) + if ((dmflags & DF_SPAWN_FARTHEST) && hasSpawned) spot = SelectFarthestDeathmatchSpot (selections); else spot = SelectRandomDeathmatchSpot (playernum, selections); @@ -1720,7 +1753,7 @@ void FLevelLocals::DoReborn (int playernum, bool freshbot) if (!multiplayer && !(flags2 & LEVEL2_ALLOWRESPAWN) && !sv_singleplayerrespawn && !G_SkillProperty(SKILLP_PlayerRespawn)) { - if (BackupSaveName.Len() > 0 && FileExists (BackupSaveName.GetChars())) + if (!(cl_restartondeath) && (BackupSaveName.Len() > 0 && FileExists (BackupSaveName))) { // Load game from the last point it was saved savename = BackupSaveName; gameaction = ga_autoloadgame; @@ -1729,7 +1762,7 @@ void FLevelLocals::DoReborn (int playernum, bool freshbot) { // Reload the level from scratch bool indemo = demoplayback; BackupSaveName = ""; - G_InitNew (MapName, false); + G_InitNew (MapName.GetChars(), false); demoplayback = indemo; } } @@ -1792,7 +1825,7 @@ void G_DoPlayerPop(int playernum) { playeringame[playernum] = false; - FString message = GStrings(deathmatch? "TXT_LEFTWITHFRAGS" : "TXT_LEFTTHEGAME"); + FString message = GStrings.GetString(deathmatch? "TXT_LEFTWITHFRAGS" : "TXT_LEFTTHEGAME"); message.Substitute("%s", players[playernum].userinfo.GetName()); message.Substitute("%d", FStringf("%d", players[playernum].fragcount)); Printf("%s\n", message.GetChars()); @@ -1870,7 +1903,7 @@ static bool CheckSingleWad (const char *name, bool &printRequires, bool printwar { if (!printRequires) { - Printf ("%s:\n%s", GStrings("TXT_SAVEGAMENEEDS"), name); + Printf ("%s:\n%s", GStrings.GetString("TXT_SAVEGAMENEEDS"), name); } else { @@ -1887,12 +1920,12 @@ static bool CheckSingleWad (const char *name, bool &printRequires, bool printwar bool G_CheckSaveGameWads (FSerializer &arc, bool printwarn) { bool printRequires = false; - FString text; - arc("Game WAD", text); - CheckSingleWad (text, printRequires, printwarn); - arc("Map WAD", text); + const char *text = arc.GetString("Game WAD"); CheckSingleWad (text, printRequires, printwarn); + const char *text2 = arc.GetString("Map WAD"); + // do not validate the same file twice. + if (text != nullptr && text2 != nullptr && stricmp(text, text2) != 0) CheckSingleWad (text2, printRequires, printwarn); if (printRequires) { @@ -1908,7 +1941,7 @@ bool G_CheckSaveGameWads (FSerializer &arc, bool printwarn) static void LoadGameError(const char *label, const char *append = "") { - FString message = GStrings(label); + FString message = GStrings.GetString(label); message.Substitute("%s", savename); Printf ("%s %s\n", message.GetChars(), append); } @@ -1961,8 +1994,12 @@ void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter) } +void SetupLoadingCVars(); +void FinishLoadingCVars(); + void G_DoLoadGame () { + SetupLoadingCVars(); bool hidecon; if (gameaction != ga_autoloadgame) @@ -1972,14 +2009,14 @@ void G_DoLoadGame () hidecon = gameaction == ga_loadgamehidecon; gameaction = ga_nothing; - std::unique_ptr resfile(FResourceFile::OpenResourceFile(savename.GetChars(), true, true)); + std::unique_ptr resfile(FResourceFile::OpenResourceFile(savename.GetChars(), true)); if (resfile == nullptr) { LoadGameError("TXT_COULDNOTREAD"); return; } - FResourceLump *info = resfile->FindLump("info.json"); - if (info == nullptr) + auto info = resfile->FindEntry("info.json"); + if (info < 0) { LoadGameError("TXT_NOINFOJSON"); return; @@ -1987,9 +2024,9 @@ void G_DoLoadGame () SaveVersion = 0; - void *data = info->Lock(); + auto data = resfile->Read(info); FSerializer arc; - if (!arc.OpenReader((const char *)data, info->LumpSize)) + if (!arc.OpenReader(data.string(), data.size())) { LoadGameError("TXT_FAILEDTOREADSG"); return; @@ -2023,16 +2060,16 @@ void G_DoLoadGame () FString message; if (SaveVersion < MINSAVEVER) { - message = GStrings("TXT_TOOOLDSG"); + message = GStrings.GetString("TXT_TOOOLDSG"); message.Substitute("%e", FStringf("%d", MINSAVEVER)); } else { - message = GStrings("TXT_TOONEWSG"); + message = GStrings.GetString("TXT_TOONEWSG"); message.Substitute("%e", FStringf("%d", SAVEVER)); } message.Substitute("%d", FStringf("%d", SaveVersion)); - LoadGameError(message); + LoadGameError(message.GetChars()); return; } @@ -2056,15 +2093,15 @@ void G_DoLoadGame () // we are done with info.json. arc.Close(); - info = resfile->FindLump("globals.json"); - if (info == nullptr) + info = resfile->FindEntry("globals.json"); + if (info < 0) { LoadGameError("TXT_NOGLOBALSJSON"); return; } - data = info->Lock(); - if (!arc.OpenReader((const char *)data, info->LumpSize)) + data = resfile->Read(info); + if (!arc.OpenReader(data.string(), data.size())) { LoadGameError("TXT_SGINFOERR"); return; @@ -2104,7 +2141,8 @@ void G_DoLoadGame () // load a base level bool demoplaybacksave = demoplayback; - G_InitNew(map, false); + G_InitNew(map.GetChars(), false); + FinishLoadingCVars(); demoplayback = demoplaybacksave; savegamerestore = false; @@ -2121,14 +2159,6 @@ void G_DoLoadGame () BackupSaveName = savename; - //Push any added models from A_ChangeModel - for (auto& smf : savedModelFiles) - { - FString modelFilePath = smf.Left(smf.LastIndexOf("/")+1); - FString modelFileName = smf.Right(smf.Len() - smf.Left(smf.LastIndexOf("/") + 1).Len()); - FindModel(modelFilePath, modelFileName); - } - // At this point, the GC threshold is likely a lot higher than the // amount of memory in use, so bring it down now by starting a // collection. @@ -2145,19 +2175,19 @@ void G_SaveGame (const char *filename, const char *description) { if (sendsave || gameaction == ga_savegame) { - Printf ("%s\n", GStrings("TXT_SAVEPENDING")); + Printf ("%s\n", GStrings.GetString("TXT_SAVEPENDING")); } else if (!usergame) { - Printf ("%s\n", GStrings("TXT_NOTSAVEABLE")); + Printf ("%s\n", GStrings.GetString("TXT_NOTSAVEABLE")); } else if (gamestate != GS_LEVEL) { - Printf ("%s\n", GStrings("TXT_NOTINLEVEL")); + Printf ("%s\n", GStrings.GetString("TXT_NOTINLEVEL")); } else if (players[consoleplayer].health <= 0 && !multiplayer) { - Printf ("%s\n", GStrings("TXT_SPPLAYERDEAD")); + Printf ("%s\n", GStrings.GetString("TXT_SPPLAYERDEAD")); } else { @@ -2170,8 +2200,8 @@ void G_SaveGame (const char *filename, const char *description) CCMD(opensaves) { FString name = G_GetSavegamesFolder(); - CreatePath(name); - I_OpenShellFolder(name); + CreatePath(name.GetChars()); + I_OpenShellFolder(name.GetChars()); } CVAR (Int, autosavenum, 0, CVAR_NOSET|CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -2194,7 +2224,7 @@ CUSTOM_CVAR (Int, quicksaverotationcount, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) void G_DoAutoSave () { - if ((primaryLevel->flags9 & LEVEL9_NOUSERSAVE)) + if ((primaryLevel->vkdflags & VKDLEVELFLAG_NOUSERSAVE)) return; FString description; @@ -2212,7 +2242,7 @@ void G_DoAutoSave () num.Int = nextautosave; autosavenum->ForceSet (num, CVAR_Int); - file = G_BuildSaveName(FStringf("auto%02d", nextautosave)); + file = G_BuildSaveName(FStringf("auto%02d", nextautosave).GetChars()); // The hint flag is only relevant on the primary level. if (!(primaryLevel->flags2 & LEVEL2_NOAUTOSAVEHINT)) @@ -2227,7 +2257,7 @@ void G_DoAutoSave () readableTime = myasctime (); description.Format("Autosave %s", readableTime); - G_DoSaveGame (false, false, file, description); + G_DoSaveGame (false, false, file, description.GetChars()); } void G_DoQuickSave () @@ -2251,11 +2281,11 @@ void G_DoQuickSave () num.Int = lastquicksave; quicksavenum->ForceSet (num, CVAR_Int); - file = G_BuildSaveName(FStringf("quick%02d", lastquicksave)); + file = G_BuildSaveName(FStringf("quick%02d", lastquicksave).GetChars()); readableTime = myasctime (); description.Format("Quicksave %s", readableTime); - G_DoSaveGame (true, true, file, description); + G_DoSaveGame (true, true, file, description.GetChars()); } @@ -2268,11 +2298,8 @@ static void PutSaveWads (FSerializer &arc) arc.AddString("Game WAD", name); // Name of wad the map resides in - if (fileSystem.GetFileContainer (primaryLevel->lumpnum) > fileSystem.GetIwadNum()) - { - name = fileSystem.GetResourceFileName (fileSystem.GetFileContainer (primaryLevel->lumpnum)); - arc.AddString("Map WAD", name); - } + name = fileSystem.GetResourceFileName (fileSystem.GetFileContainer (primaryLevel->lumpnum)); + arc.AddString("Map WAD", name); } static void PutSaveComment (FSerializer &arc) @@ -2281,18 +2308,18 @@ static void PutSaveComment (FSerializer &arc) FString comment = myasctime(); - arc.AddString("Creation Time", comment); + arc.AddString("Creation Time", comment.GetChars()); // Get level name comment.Format("%s - %s\n", primaryLevel->MapName.GetChars(), primaryLevel->LevelName.GetChars()); // Append elapsed time - const char *const time = GStrings("SAVECOMMENT_TIME"); + const char *const time = GStrings.GetString("SAVECOMMENT_TIME"); levelTime = primaryLevel->time / TICRATE; comment.AppendFormat("%s: %02d:%02d:%02d", time, levelTime/3600, (levelTime%3600)/60, levelTime%60); // Write out the comment - arc.AddString("Comment", comment); + arc.AddString("Comment", comment.GetChars()); } static void PutSavePic (FileWriter *file, int width, int height) @@ -2370,7 +2397,7 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c // put some basic info into the PNG so that this isn't lost when the image gets extracted. M_AppendPNGText(&savepic, "Software", buf); M_AppendPNGText(&savepic, "Title", description); - M_AppendPNGText(&savepic, "Current Map", primaryLevel->MapName); + M_AppendPNGText(&savepic, "Current Map", primaryLevel->MapName.GetChars()); M_FinishPNG(&savepic); int ver = SAVEVER; @@ -2378,7 +2405,7 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c .AddString("Engine", GAMESIG) ("Save Version", ver) .AddString("Title", description) - .AddString("Current Map", primaryLevel->MapName); + .AddString("Current Map", primaryLevel->MapName.GetChars()); PutSaveWads (savegameinfo); @@ -2408,7 +2435,7 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c } auto picdata = savepic.GetBuffer(); - FCompressedBuffer bufpng = { picdata->Size(), picdata->Size(), METHOD_STORED, 0, static_cast(crc32(0, &(*picdata)[0], picdata->Size())), (char*)&(*picdata)[0] }; + FCompressedBuffer bufpng = { picdata->size(), picdata->size(), FileSys::METHOD_STORED, static_cast(crc32(0, &(*picdata)[0], picdata->size())), (char*)&(*picdata)[0] }; savegame_content.Push(bufpng); savegame_filenames.Push("savepic.png"); @@ -2416,16 +2443,17 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c savegame_filenames.Push("info.json"); savegame_content.Push(savegameglobals.GetCompressedOutput()); savegame_filenames.Push("globals.json"); - G_WriteSnapshots (savegame_filenames, savegame_content); + for (unsigned i = 0; i < savegame_content.Size(); i++) + savegame_content[i].filename = savegame_filenames[i].GetChars(); bool succeeded = false; - if (WriteZip(filename, savegame_filenames, savegame_content)) + if (WriteZip(filename.GetChars(), savegame_content.Data(), savegame_content.Size())) { // Check whether the file is ok by trying to open it. - FResourceFile *test = FResourceFile::OpenResourceFile(filename, true); + FResourceFile *test = FResourceFile::OpenResourceFile(filename.GetChars(), true); if (test != nullptr) { delete test; @@ -2438,12 +2466,12 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c savegameManager.NotifyNewSave(filename, description, okForQuicksave, forceQuicksave); BackupSaveName = filename; - if (longsavemessages) Printf("%s (%s)\n", GStrings("GGSAVED"), filename.GetChars()); - else Printf("%s\n", GStrings("GGSAVED")); + if (longsavemessages) Printf("%s (%s)\n", GStrings.GetString("GGSAVED"), filename.GetChars()); + else Printf("%s\n", GStrings.GetString("GGSAVED")); } else { - Printf(PRINT_HIGH, "%s\n", GStrings("TXT_SAVEFAILED")); + Printf(PRINT_HIGH, "%s\n", GStrings.GetString("TXT_SAVEFAILED")); } @@ -2481,7 +2509,7 @@ void G_ReadDemoTiccmd (ticcmd_t *cmd, int player) break; } - id = ReadByte (&demo_p); + id = ReadInt8 (&demo_p); switch (id) { @@ -2500,7 +2528,7 @@ void G_ReadDemoTiccmd (ticcmd_t *cmd, int player) case DEM_DROPPLAYER: { - uint8_t i = ReadByte (&demo_p); + uint8_t i = ReadInt8 (&demo_p); if (i < MAXPLAYERS) { playeringame[i] = false; @@ -2594,23 +2622,23 @@ void G_BeginRecording (const char *startmap) if (startmap == NULL) { - startmap = primaryLevel->MapName; + startmap = primaryLevel->MapName.GetChars(); } demo_p = demobuffer; - WriteLong (FORM_ID, &demo_p); // Write FORM ID + WriteInt32 (FORM_ID, &demo_p); // Write FORM ID demo_p += 4; // Leave space for len - WriteLong (ZDEM_ID, &demo_p); // Write ZDEM ID + WriteInt32 (ZDEM_ID, &demo_p); // Write ZDEM ID // Write header chunk StartChunk (ZDHD_ID, &demo_p); - WriteWord (DEMOGAMEVERSION, &demo_p); // Write ZDoom version + WriteInt16 (DEMOGAMEVERSION, &demo_p); // Write ZDoom version *demo_p++ = 2; // Write minimum version needed to use this demo. *demo_p++ = 3; // (Useful?) strcpy((char*)demo_p, startmap); // Write name of map demo was recorded on. demo_p += strlen(startmap) + 1; - WriteLong(rngseed, &demo_p); // Write RNG seed + WriteInt32(rngseed, &demo_p); // Write RNG seed *demo_p++ = consoleplayer; FinishChunk (&demo_p); @@ -2620,7 +2648,7 @@ void G_BeginRecording (const char *startmap) if (playeringame[i]) { StartChunk(UINF_ID, &demo_p); - WriteByte((uint8_t)i, &demo_p); + WriteInt8((uint8_t)i, &demo_p); auto str = D_GetUserInfoStrings(i); memcpy(demo_p, str.GetChars(), str.Len() + 1); demo_p += str.Len(); @@ -2650,7 +2678,7 @@ void G_BeginRecording (const char *startmap) // Indicate body is compressed StartChunk (COMP_ID, &demo_p); democompspot = demo_p; - WriteLong (0, &demo_p); + WriteInt32 (0, &demo_p); FinishChunk (&demo_p); // Begin BODY chunk @@ -2715,13 +2743,13 @@ bool G_ProcessIFFDemo (FString &mapname) for (i = 0; i < MAXPLAYERS; i++) playeringame[i] = 0; - len = ReadLong (&demo_p); + len = ReadInt32 (&demo_p); zdemformend = demo_p + len + (len & 1); // Check to make sure this is a ZDEM chunk file. // TODO: Support multiple FORM ZDEMs in a CAT. Might be useful. - id = ReadLong (&demo_p); + id = ReadInt32 (&demo_p); if (id != ZDEM_ID) { Printf ("Not a " GAMENAME " demo file!\n"); @@ -2732,8 +2760,8 @@ bool G_ProcessIFFDemo (FString &mapname) while (demo_p < zdemformend && !bodyHit) { - id = ReadLong (&demo_p); - len = ReadLong (&demo_p); + id = ReadInt32 (&demo_p); + len = ReadInt32 (&demo_p); nextchunk = demo_p + len + (len & 1); if (nextchunk > zdemformend) { @@ -2746,13 +2774,13 @@ bool G_ProcessIFFDemo (FString &mapname) case ZDHD_ID: headerHit = true; - demover = ReadWord (&demo_p); // ZDoom version demo was created with + demover = ReadInt16 (&demo_p); // ZDoom version demo was created with if (demover < MINDEMOVERSION) { Printf ("Demo requires an older version of " GAMENAME "!\n"); //return true; } - if (ReadWord (&demo_p) > DEMOGAMEVERSION) // Minimum ZDoom version + if (ReadInt16 (&demo_p) > DEMOGAMEVERSION) // Minimum ZDoom version { Printf ("Demo requires a newer version of " GAMENAME "!\n"); return true; @@ -2767,7 +2795,7 @@ bool G_ProcessIFFDemo (FString &mapname) mapname = FString((char*)demo_p, 8); demo_p += 8; } - rngseed = ReadLong (&demo_p); + rngseed = ReadInt32 (&demo_p); // Only reset the RNG if this demo is not in conjunction with a savegame. if (mapname[0] != 0) { @@ -2781,7 +2809,7 @@ bool G_ProcessIFFDemo (FString &mapname) break; case UINF_ID: - i = ReadByte (&demo_p); + i = ReadInt8 (&demo_p); if (!playeringame[i]) { playeringame[i] = 1; @@ -2804,7 +2832,7 @@ bool G_ProcessIFFDemo (FString &mapname) break; case COMP_ID: - uncompSize = ReadLong (&demo_p); + uncompSize = ReadInt32 (&demo_p); break; } @@ -2860,7 +2888,7 @@ void G_DoPlayDemo (void) gameaction = ga_nothing; // [RH] Allow for demos not loaded as lumps - demolump = fileSystem.CheckNumForFullName (defdemoname, true); + demolump = fileSystem.CheckNumForFullName (defdemoname.GetChars(), true); if (demolump >= 0) { int demolen = fileSystem.FileLength (demolump); @@ -2872,7 +2900,7 @@ void G_DoPlayDemo (void) FixPathSeperator (defdemoname); DefaultExtension (defdemoname, ".lmp"); FileReader fr; - if (!fr.OpenFile(defdemoname)) + if (!fr.OpenFile(defdemoname.GetChars())) { I_Error("Unable to open demo '%s'", defdemoname.GetChars()); } @@ -2889,7 +2917,7 @@ void G_DoPlayDemo (void) C_BackupCVars (); // [RH] Save cvars that might be affected by demo - if (ReadLong (&demo_p) != FORM_ID) + if (ReadInt32 (&demo_p) != FORM_ID) { const char *eek = "Cannot play non-" GAMENAME " demos.\n"; @@ -2919,7 +2947,7 @@ void G_DoPlayDemo (void) demonew = true; if (mapname.Len() != 0) { - G_InitNew (mapname, false); + G_InitNew (mapname.GetChars(), false); } else if (primaryLevel->sectors.Size() == 0) { @@ -3023,7 +3051,7 @@ bool G_CheckDemoStatus (void) { uint8_t *formlen; - WriteByte (DEM_STOP, &demo_p); + WriteInt8 (DEM_STOP, &demo_p); if (demo_compress) { @@ -3038,23 +3066,23 @@ bool G_CheckDemoStatus (void) if (r == Z_OK && outlen < len) { formlen = democompspot; - WriteLong (len, &democompspot); + WriteInt32 (len, &democompspot); memcpy (demobodyspot, compressed.Data(), outlen); demo_p = demobodyspot + outlen; } } FinishChunk (&demo_p); formlen = demobuffer + 4; - WriteLong (int(demo_p - demobuffer - 8), &formlen); + WriteInt32 (int(demo_p - demobuffer - 8), &formlen); - auto fw = FileWriter::Open(demoname); + auto fw = FileWriter::Open(demoname.GetChars()); bool saved = false; if (fw != nullptr) { const size_t size = demo_p - demobuffer; saved = fw->Write(demobuffer, size) == size; delete fw; - if (!saved) remove(demoname); + if (!saved) remove(demoname.GetChars()); } M_Free (demobuffer); demorecording = false; @@ -3133,6 +3161,7 @@ DEFINE_GLOBAL(globalfreeze) DEFINE_GLOBAL(gametic) DEFINE_GLOBAL(demoplayback) DEFINE_GLOBAL(automapactive); +DEFINE_GLOBAL(viewactive); DEFINE_GLOBAL(Net_Arbitrator); DEFINE_GLOBAL(netgame); DEFINE_GLOBAL(paused); diff --git a/src/g_game.h b/src/g_game.h index cbb18d5d61..caaf931884 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -30,6 +30,8 @@ struct event_t; +#include + #include "dobjgc.h" #include "name.h" #include "gamestate.h" diff --git a/src/g_hub.cpp b/src/g_hub.cpp index 346ace1737..250db2fd08 100644 --- a/src/g_hub.cpp +++ b/src/g_hub.cpp @@ -132,7 +132,7 @@ void G_LeavingHub(FLevelLocals *Level, int mode, cluster_info_t * cluster, wbsta { if (cluster->flags & CLUSTER_LOOKUPNAME) { - wbs->thisname = GStrings(cluster->ClusterName); + wbs->thisname = GStrings.GetString(cluster->ClusterName); } else { diff --git a/src/g_level.cpp b/src/g_level.cpp index 42e7be1ed6..b7101a7b98 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -146,17 +146,29 @@ CUSTOM_CVAR(Bool, gl_notexturefill, false, CVAR_NOINITCALL) } } -CUSTOM_CVAR(Int, gl_lightmode, 8, CVAR_ARCHIVE | CVAR_NOINITCALL) +CUSTOM_CVAR(Int, gl_maplightmode, -1, CVAR_NOINITCALL | CVAR_CHEAT) // this is just for testing. -1 means 'inactive' { - int newself = self; - if (newself > 8) newself = 16; // use 8 and 16 for software lighting to avoid conflicts with the bit mask ( in hindsight a bad idea.) - else if (newself > 5) newself = 8; - else if (newself < 0) newself = 0; - if (self != newself) self = newself; - else for (auto Level : AllLevels()) - { - if ((Level->info == nullptr || Level->info->lightmode == ELightMode::NotSet)) Level->lightMode = (ELightMode)*self; - } + if (self > 5 || self < -1) self = -1; +} + +CUSTOM_CVARD(Int, gl_lightmode, 1, CVAR_ARCHIVE, "Select lighting mode. 2 is vanilla accurate, 1 is accurate to the ZDoom software renderer and 0 is a less demanding non-shader implementation") +{ + if (self < 0 || self > 2) self = 1; +} + +ELightMode getRealLightmode(FLevelLocals* Level, bool for3d) +{ + // The rules are: + // 1) if the map sets a proper light mode, it is taken unconditionally. + if (Level->info->lightmode != ELightMode::NotSet) return Level->info->lightmode; + // 2) if the user sets gl_maplightmode, this is being used. + if (gl_maplightmode != -1) return (ELightMode)*gl_maplightmode; + // 3) if not for 3D use lightmode Doom. This is for the automap where the software light modes do not work + if (!for3d) return ELightMode::Doom; + // otherwise use lightmode Doom or software lighting based on user preferences. + if (gl_lightmode == 1) return ELightMode::ZDoomSoftware; + else if (gl_lightmode == 2) return ELightMode::DoomSoftware; + return ELightMode::Doom; } CVAR(Int, sv_alwaystally, 0, CVAR_SERVERINFO) @@ -226,7 +238,7 @@ bool CreateCutscene(CutsceneDef* cs, DObject* runner, level_info_t* map) return true; // play nothing but return as being validated if (cs->function.IsNotEmpty()) { - CallCreateMapFunction(cs->function, runner, map); + CallCreateMapFunction(cs->function.GetChars(), runner, map); return true; } else if (cs->video.IsNotEmpty()) @@ -258,7 +270,7 @@ void G_DeferedInitNew (const char *mapname, int newskill) void G_DeferedInitNew (FNewGameStartup *gs) { - if (gs->PlayerClass != NULL) playerclass = gs->PlayerClass; + if (gs->hasPlayerClass) playerclass = gs->PlayerClass.GetChars(); d_mapname = AllEpisodes[gs->Episode].mEpisodeMap; d_skill = gs->Skill; CheckWarpTransMap (d_mapname, true); @@ -406,7 +418,7 @@ UNSAFE_CCMD (open) { d_mapname = "file:"; d_mapname += argv[1]; - if (!P_CheckMapData(d_mapname)) + if (!P_CheckMapData(d_mapname.GetChars())) { Printf ("No map %s\n", d_mapname.GetChars()); } @@ -503,7 +515,7 @@ void G_DoNewGame (void) { gameskill = d_skill; } - G_InitNew (d_mapname, false); + G_InitNew (d_mapname.GetChars(), false); gameaction = ga_nothing; } @@ -562,8 +574,8 @@ void G_InitNew (const char *mapname, bool bTitleLevel) auto redirectmap = FindLevelInfo(mapname); if (redirectmap->RedirectCVAR != NAME_None) redirectmap = redirectmap->CheckLevelRedirect(); - if (redirectmap && redirectmap->MapName.GetChars()[0]) - mapname = redirectmap->MapName; + if (redirectmap && redirectmap->MapName.IsNotEmpty()) + mapname = redirectmap->MapName.GetChars(); } G_VerifySkill(); @@ -726,7 +738,7 @@ void FLevelLocals::ChangeLevel(const char *levelname, int position, int inflags, { FString reallevelname = levelname; CheckWarpTransMap(reallevelname, true); - nextinfo = FindLevelInfo (reallevelname, false); + nextinfo = FindLevelInfo (reallevelname.GetChars(), false); if (nextinfo != NULL) { level_info_t *nextredir = nextinfo->CheckLevelRedirect(); @@ -764,11 +776,12 @@ void FLevelLocals::ChangeLevel(const char *levelname, int position, int inflags, { if (thiscluster != nextcluster || (thiscluster && !(thiscluster->flags & CLUSTER_HUB))) { - if (nextinfo->flags2 & LEVEL2_RESETINVENTORY) + const bool doReset = dmflags3 & DF3_PISTOL_START; + if (doReset || (nextinfo->flags2 & LEVEL2_RESETINVENTORY)) { inflags |= CHANGELEVEL_RESETINVENTORY; } - if (nextinfo->flags2 & LEVEL2_RESETHEALTH) + if (doReset || (nextinfo->flags2 & LEVEL2_RESETHEALTH)) { inflags |= CHANGELEVEL_RESETHEALTH; } @@ -791,7 +804,7 @@ void FLevelLocals::ChangeLevel(const char *levelname, int position, int inflags, staticEventManager.WorldUnloaded(nextlevel); unloading = false; - STAT_ChangeLevel(nextlevel, this); + STAT_ChangeLevel(nextlevel.GetChars(), this); if (thiscluster && (thiscluster->flags & CLUSTER_HUB)) { @@ -838,7 +851,7 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, ChangeLevel) PARAM_INT(position); PARAM_INT(inflags); PARAM_INT(nextSkill); - self->ChangeLevel(levelname, position, inflags, nextSkill); + self->ChangeLevel(levelname.GetChars(), position, inflags, nextSkill); return 0; } @@ -849,13 +862,13 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, ChangeLevel) const char *FLevelLocals::GetSecretExitMap() { - const char *nextmap = NextMap; + const char *nextmap = NextMap.GetChars(); if (NextSecretMap.Len() > 0) { - if (NextSecretMap.Compare("enDSeQ", 6) == 0 || P_CheckMapData(NextSecretMap)) + if (NextSecretMap.Compare("enDSeQ", 6) == 0 || P_CheckMapData(NextSecretMap.GetChars())) { - nextmap = NextSecretMap; + nextmap = NextSecretMap.GetChars(); } } return nextmap; @@ -870,7 +883,7 @@ const char *FLevelLocals::GetSecretExitMap() void FLevelLocals::ExitLevel (int position, bool keepFacing) { flags3 |= LEVEL3_EXITNORMALUSED; - ChangeLevel(NextMap, position, keepFacing ? CHANGELEVEL_KEEPFACING : 0); + ChangeLevel(NextMap.GetChars(), position, keepFacing ? CHANGELEVEL_KEEPFACING : 0); } static void LevelLocals_ExitLevel(FLevelLocals *self, int position, bool keepFacing) @@ -923,7 +936,7 @@ DIntermissionController* FLevelLocals::CreateIntermission() thiscluster = FindClusterInfo (cluster); - bool endgame = strncmp (nextlevel, "enDSeQ", 6) == 0; + bool endgame = strncmp (nextlevel.GetChars(), "enDSeQ", 6) == 0; if (endgame) { FName endsequence = ENamedName(strtoll(nextlevel.GetChars()+6, NULL, 16)); @@ -944,11 +957,11 @@ DIntermissionController* FLevelLocals::CreateIntermission() auto ext = info->ExitMapTexts.CheckKey(flags3 & LEVEL3_EXITSECRETUSED ? NAME_Secret : NAME_Normal); if (ext != nullptr && (ext->mDefined & FExitText::DEF_TEXT)) { - controller = F_StartFinale(ext->mDefined & FExitText::DEF_MUSIC ? ext->mMusic : gameinfo.finaleMusic, + controller = F_StartFinale(ext->mDefined & FExitText::DEF_MUSIC ? ext->mMusic.GetChars() : gameinfo.finaleMusic.GetChars(), ext->mDefined & FExitText::DEF_MUSIC ? ext->mOrder : gameinfo.finaleOrder, -1, 0, - ext->mDefined & FExitText::DEF_BACKDROP ? ext->mBackdrop : gameinfo.FinaleFlat, - ext->mText, + ext->mDefined & FExitText::DEF_BACKDROP ? ext->mBackdrop.GetChars() : gameinfo.FinaleFlat.GetChars(), + ext->mText.GetChars(), false, ext->mDefined & FExitText::DEF_PIC, ext->mDefined & FExitText::DEF_LOOKUP, @@ -956,9 +969,9 @@ DIntermissionController* FLevelLocals::CreateIntermission() } else if (!(info->flags2 & LEVEL2_NOCLUSTERTEXT)) { - controller = F_StartFinale(thiscluster->MessageMusic, thiscluster->musicorder, + controller = F_StartFinale(thiscluster->MessageMusic.GetChars(), thiscluster->musicorder, thiscluster->cdtrack, thiscluster->cdid, - thiscluster->FinaleFlat, thiscluster->ExitText, + thiscluster->FinaleFlat.GetChars(), thiscluster->ExitText.GetChars(), thiscluster->flags & CLUSTER_EXITTEXTINLUMP, thiscluster->flags & CLUSTER_FINALEPIC, thiscluster->flags & CLUSTER_LOOKUPEXITTEXT, @@ -977,11 +990,11 @@ DIntermissionController* FLevelLocals::CreateIntermission() { if ((ext->mDefined & FExitText::DEF_TEXT)) { - controller = F_StartFinale(ext->mDefined & FExitText::DEF_MUSIC ? ext->mMusic : gameinfo.finaleMusic, + controller = F_StartFinale(ext->mDefined & FExitText::DEF_MUSIC ? ext->mMusic.GetChars() : gameinfo.finaleMusic.GetChars(), ext->mDefined & FExitText::DEF_MUSIC ? ext->mOrder : gameinfo.finaleOrder, -1, 0, - ext->mDefined & FExitText::DEF_BACKDROP ? ext->mBackdrop : gameinfo.FinaleFlat, - ext->mText, + ext->mDefined & FExitText::DEF_BACKDROP ? ext->mBackdrop.GetChars() : gameinfo.FinaleFlat.GetChars(), + ext->mText.GetChars(), false, ext->mDefined & FExitText::DEF_PIC, ext->mDefined & FExitText::DEF_LOOKUP, @@ -990,7 +1003,7 @@ DIntermissionController* FLevelLocals::CreateIntermission() return controller; } - nextcluster = FindClusterInfo (FindLevelInfo (nextlevel)->cluster); + nextcluster = FindClusterInfo (FindLevelInfo (nextlevel.GetChars())->cluster); if (nextcluster->cluster != cluster && !(info->flags2 & LEVEL2_NOCLUSTERTEXT)) { @@ -998,9 +1011,9 @@ DIntermissionController* FLevelLocals::CreateIntermission() // than the current one and we're not in deathmatch. if (nextcluster->EnterText.IsNotEmpty()) { - controller = F_StartFinale (nextcluster->MessageMusic, nextcluster->musicorder, + controller = F_StartFinale (nextcluster->MessageMusic.GetChars(), nextcluster->musicorder, nextcluster->cdtrack, nextcluster->cdid, - nextcluster->FinaleFlat, nextcluster->EnterText, + nextcluster->FinaleFlat.GetChars(), nextcluster->EnterText.GetChars(), nextcluster->flags & CLUSTER_ENTERTEXTINLUMP, nextcluster->flags & CLUSTER_FINALEPIC, nextcluster->flags & CLUSTER_LOOKUPENTERTEXT, @@ -1008,9 +1021,9 @@ DIntermissionController* FLevelLocals::CreateIntermission() } else if (thiscluster->ExitText.IsNotEmpty()) { - controller = F_StartFinale (thiscluster->MessageMusic, thiscluster->musicorder, + controller = F_StartFinale (thiscluster->MessageMusic.GetChars(), thiscluster->musicorder, thiscluster->cdtrack, nextcluster->cdid, - thiscluster->FinaleFlat, thiscluster->ExitText, + thiscluster->FinaleFlat.GetChars(), thiscluster->ExitText.GetChars(), thiscluster->flags & CLUSTER_EXITTEXTINLUMP, thiscluster->flags & CLUSTER_FINALEPIC, thiscluster->flags & CLUSTER_LOOKUPEXITTEXT, @@ -1116,9 +1129,9 @@ void G_DoCompleted (void) statusScreen = WI_Start (&staticWmInfo); } - bool endgame = strncmp(nextlevel, "enDSeQ", 6) == 0; + bool endgame = strncmp(nextlevel.GetChars(), "enDSeQ", 6) == 0; intermissionScreen = primaryLevel->CreateIntermission(); - auto nextinfo = !playinter || endgame? nullptr : FindLevelInfo(nextlevel, false); + auto nextinfo = !playinter || endgame? nullptr : FindLevelInfo(nextlevel.GetChars(), false); RunIntermission(primaryLevel->info, nextinfo, intermissionScreen, statusScreen, [=](bool) { if (!endgame) primaryLevel->WorldDone(); @@ -1143,7 +1156,7 @@ bool FLevelLocals::DoCompleted (FString nextlevel, wbstartstruct_t &wminfo) uint32_t langtable[2] = {}; wminfo.finished_ep = cluster - 1; - wminfo.LName0 = TexMan.CheckForTexture(info->PName, ETextureType::MiscPatch); + wminfo.LName0 = TexMan.CheckForTexture(info->PName.GetChars(), ETextureType::MiscPatch); wminfo.thisname = info->LookupLevelName(&langtable[0]); // re-get the name so we have more info about its origin. if (!wminfo.LName0.isValid() || !(info->flags3 & LEVEL3_HIDEAUTHORNAME)) wminfo.thisauthor = info->AuthorName; wminfo.current = MapName; @@ -1159,8 +1172,8 @@ bool FLevelLocals::DoCompleted (FString nextlevel, wbstartstruct_t &wminfo) } else { - level_info_t *nextinfo = FindLevelInfo (nextlevel, false); - if (nextinfo == NULL || strncmp (nextlevel, "enDSeQ", 6) == 0) + level_info_t *nextinfo = FindLevelInfo (nextlevel.GetChars(), false); + if (nextinfo == NULL || strncmp (nextlevel.GetChars(), "enDSeQ", 6) == 0) { wminfo.next = ""; wminfo.LName1.SetInvalid(); @@ -1170,7 +1183,7 @@ bool FLevelLocals::DoCompleted (FString nextlevel, wbstartstruct_t &wminfo) else { wminfo.next = nextinfo->MapName; - wminfo.LName1 = TexMan.CheckForTexture(nextinfo->PName, ETextureType::MiscPatch); + wminfo.LName1 = TexMan.CheckForTexture(nextinfo->PName.GetChars(), ETextureType::MiscPatch); wminfo.nextname = nextinfo->LookupLevelName(&langtable[1]); if (!wminfo.LName1.isValid() || !(nextinfo->flags3 & LEVEL3_HIDEAUTHORNAME)) wminfo.nextauthor = nextinfo->AuthorName; } @@ -1198,7 +1211,7 @@ bool FLevelLocals::DoCompleted (FString nextlevel, wbstartstruct_t &wminfo) CheckWarpTransMap (wminfo.next, true); nextlevel = wminfo.next; - wminfo.next_ep = FindLevelInfo (wminfo.next)->cluster - 1; + wminfo.next_ep = FindLevelInfo (wminfo.next.GetChars())->cluster - 1; wminfo.totalkills = killed_monsters; wminfo.maxkills = total_monsters; wminfo.maxitems = total_items; @@ -1308,7 +1321,7 @@ IMPLEMENT_CLASS(DAutosaver, false, false) void DAutosaver::Tick () { - Net_WriteByte (DEM_CHECKAUTOSAVE); + Net_WriteInt8 (DEM_CHECKAUTOSAVE); Destroy (); } @@ -1399,7 +1412,7 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au // a flat. The data is in the WAD only because // we look for an actual index, instead of simply // setting one. - skyflatnum = TexMan.GetTextureID (gameinfo.SkyFlatName, ETextureType::Flat, FTextureManager::TEXMAN_Overridable); + skyflatnum = TexMan.GetTextureID (gameinfo.SkyFlatName.GetChars(), ETextureType::Flat, FTextureManager::TEXMAN_Overridable); // [RH] Set up details about sky rendering InitSkyMap (this); @@ -1509,6 +1522,10 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au DoDeferedScripts (); // [RH] Do script actions that were triggered on another map. + // [Nash] allow modder control of autosaving + if ((changeflags & CHANGELEVEL_NOAUTOSAVE) || (vkdflags & VKDLEVELFLAG_NOAUTOSAVEONENTER)) + autosave = false; + // [RH] Always save the game when entering a new if (autosave && !savegamerestore && disableautosave < 1) { @@ -1699,7 +1716,7 @@ int FLevelLocals::FinishTravel () pawn->flags2 &= ~MF2_BLASTED; if (oldpawn != nullptr) { - StaticPointerSubstitution (oldpawn, pawn); + PlayerPointerSubstitution (oldpawn, pawn, true); oldpawn->Destroy(); } if (pawndup != NULL) @@ -1789,33 +1806,38 @@ void FLevelLocals::Init() flags = 0; flags2 = 0; flags3 = 0; + vkdflags = 0; ImpactDecalCount = 0; frozenstate = 0; - info = FindLevelInfo (MapName); + info = FindLevelInfo (MapName.GetChars()); skyspeed1 = info->skyspeed1; skyspeed2 = info->skyspeed2; - skytexture1 = TexMan.GetTextureID(info->SkyPic1, ETextureType::Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); - skytexture2 = TexMan.GetTextureID(info->SkyPic2, ETextureType::Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + skytexture1 = TexMan.GetTextureID(info->SkyPic1.GetChars(), ETextureType::Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + skytexture2 = TexMan.GetTextureID(info->SkyPic2.GetChars(), ETextureType::Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); fadeto = info->fadeto; cdtrack = info->cdtrack; cdid = info->cdid; FromSnapshot = false; if (fadeto == 0) { - if (strnicmp (info->FadeTable, "COLORMAP", 8) != 0) + if (strnicmp (info->FadeTable.GetChars(), "COLORMAP", 8) != 0) { flags |= LEVEL_HASFADETABLE; } } + + + globalcolormap = R_ColormapNumForName(info->CustomColorMap.GetChars()); airsupply = info->airsupply*TICRATE; outsidefog = info->outsidefog; WallVertLight = info->WallVertLight*2; WallHorizLight = info->WallHorizLight*2; if (info->gravity != 0.f) { - gravity = info->gravity * 35/TICRATE; + if (info->gravity == DBL_MAX) gravity = 0; + else gravity = info->gravity * 35/TICRATE; } if (info->aircontrol != 0.f) { @@ -1837,7 +1859,9 @@ void FLevelLocals::Init() flags |= info->flags; flags2 |= info->flags2; flags3 |= info->flags3; + vkdflags |= info->vkdflags; levelnum = info->levelnum; + LightningSound = info->LightningSound; Music = info->Music; musicorder = info->musicorder; MusicVolume = 1.f; @@ -1864,7 +1888,6 @@ void FLevelLocals::Init() DefaultEnvironment = info->DefaultEnvironment; - lightMode = info->lightmode == ELightMode::NotSet? (ELightMode)*gl_lightmode : info->lightmode; brightfog = info->brightfog < 0? gl_brightfog : !!info->brightfog; lightadditivesurfaces = info->lightadditivesurfaces < 0 ? gl_lightadditivesurfaces : !!info->lightadditivesurfaces; notexturefill = info->notexturefill < 0 ? gl_notexturefill : !!info->notexturefill; @@ -1951,7 +1974,7 @@ void G_WriteVisited(FSerializer &arc) { if (wi.flags & LEVEL_VISITED) { - arc.AddString(nullptr, wi.MapName); + arc.AddString(nullptr, wi.MapName.GetChars()); } } arc.EndArray(); @@ -1969,9 +1992,8 @@ void G_WriteVisited(FSerializer &arc) { if (playeringame[i]) { - FString key; - key.Format("%d", i); - arc(key, players[i].cls); + FStringf key("%d", i); + arc(key.GetChars(), players[i].cls); } } arc.EndObject(); @@ -1990,32 +2012,28 @@ void G_ReadSnapshots(FResourceFile *resf) G_ClearSnapshots(); - for (unsigned j = 0; j < resf->LumpCount(); j++) + for (unsigned j = 0; j < resf->EntryCount(); j++) { - FResourceLump * resl = resf->GetLump(j); - if (resl != nullptr) + auto name = resf->getName(j); + auto ptr = strstr(name, ".map.json"); + if (ptr != nullptr) { - auto name = resl->getName(); - auto ptr = strstr(name, ".map.json"); + ptrdiff_t maplen = ptr - name; + FString mapname(name, (size_t)maplen); + i = FindLevelInfo(mapname.GetChars()); + if (i != nullptr) + { + i->Snapshot = resf->GetRawData(j); + } + } + else + { + auto ptr = strstr(name, ".mapd.json"); if (ptr != nullptr) { ptrdiff_t maplen = ptr - name; FString mapname(name, (size_t)maplen); - i = FindLevelInfo(mapname); - if (i != nullptr) - { - i->Snapshot = resl->GetRawData(); - } - } - else - { - auto ptr = strstr(name, ".mapd.json"); - if (ptr != nullptr) - { - ptrdiff_t maplen = ptr - name; - FString mapname(name, (size_t)maplen); - TheDefaultLevelInfo.Snapshot = resl->GetRawData(); - } + TheDefaultLevelInfo.Snapshot = resf->GetRawData(j); } } } @@ -2034,7 +2052,7 @@ void G_ReadVisited(FSerializer &arc) { FString str; arc(nullptr, str); - auto i = FindLevelInfo(str); + auto i = FindLevelInfo(str.GetChars()); if (i != nullptr) i->flags |= LEVEL_VISITED; } arc.EndArray(); @@ -2046,9 +2064,8 @@ void G_ReadVisited(FSerializer &arc) { for (int i = 0; i < MAXPLAYERS; ++i) { - FString key; - key.Format("%d", i); - arc(key, players[i].cls); + FStringf key("%d", i); + arc(key.GetChars(), players[i].cls); } arc.EndObject(); } @@ -2080,7 +2097,7 @@ void P_WriteACSDefereds (FSerializer &arc) { if (wi.deferred.Size() > 0) { - arc(wi.MapName, wi.deferred); + arc(wi.MapName.GetChars(), wi.deferred); } } } @@ -2308,9 +2325,9 @@ void FLevelLocals::SetInterMusic(const char *nextmap) { auto mus = info->MapInterMusic.CheckKey(nextmap); if (mus != nullptr) - S_ChangeMusic(mus->first, mus->second); + S_ChangeMusic(mus->first.GetChars(), mus->second); else if (info->InterMusic.IsNotEmpty()) - S_ChangeMusic(info->InterMusic, info->intermusicorder); + S_ChangeMusic(info->InterMusic.GetChars(), info->intermusicorder); else S_ChangeMusic(gameinfo.intermissionMusic.GetChars(), gameinfo.intermissionOrder); } @@ -2319,7 +2336,7 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, SetInterMusic) { PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); PARAM_STRING(map); - self->SetInterMusic(map); + self->SetInterMusic(map.GetChars()); return 0; } @@ -2426,7 +2443,7 @@ int IsPointInMap(FLevelLocals *Level, double x, double y, double z) void FLevelLocals::SetMusic() { - S_ChangeMusic(Music, musicorder); + S_ChangeMusic(Music.GetChars(), musicorder); } @@ -2439,7 +2456,7 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, GetClusterName) if (cluster) { if (cluster->flags & CLUSTER_LOOKUPNAME) - retval = GStrings(cluster->ClusterName); + retval = GStrings.GetString(cluster->ClusterName); else retval = cluster->ClusterName; } @@ -2453,6 +2470,6 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, GetEpisodeName) // This will need some heuristics to assign a proper episode to each existing level. // Stuff for later. for now this just checks the STAT module for the currently running episode, // which should be fine unless cheating. - ACTION_RETURN_STRING(GStrings.localize(STAT_EpisodeName())); + ACTION_RETURN_STRING(GStrings.localize(STAT_EpisodeName().GetChars())); } diff --git a/src/g_level.h b/src/g_level.h index 75a0aab564..27c2d21113 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -3,10 +3,10 @@ #include "doomtype.h" #include "vectors.h" #include "sc_man.h" -#include "file_zip.h" #include "g_mapinfo.h" +using FileSys::FCompressedBuffer; extern bool savegamerestore; void G_InitNew (const char *mapname, bool bTitleLevel); @@ -27,6 +27,7 @@ enum CHANGELEVEL_NOINTERMISSION = 16, CHANGELEVEL_RESETHEALTH = 32, CHANGELEVEL_PRERAISEWEAPON = 64, + CHANGELEVEL_NOAUTOSAVE = 128, }; void G_DoLoadLevel (const FString &MapName, int position, bool autosave, bool newGame); diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 89460fea3b..2a9c41af69 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -194,7 +194,7 @@ struct FLevelLocals AActor *SpawnMapThing(int index, FMapThing *mt, int position); AActor *SpawnPlayer(FPlayerStart *mthing, int playernum, int flags = 0); void StartLightning(); - void ForceLightning(int mode); + void ForceLightning(int mode, FSoundID tempSound = NO_SOUND); void ClearDynamic3DFloorData(); void WorldDone(void); void AirControlChanged(); @@ -379,6 +379,11 @@ struct FLevelLocals return PointInSubsector(pos.X, pos.Y)->sector; } + sector_t* PointInSector(const DVector3& pos) + { + return PointInSubsector(pos.X, pos.Y)->sector; + } + sector_t *PointInSector(double x, double y) { return PointInSubsector(x, y)->sector; @@ -389,6 +394,11 @@ struct FLevelLocals return PointInRenderSubsector(FloatToFixed(pos.X), FloatToFixed(pos.Y)); } + subsector_t* PointInRenderSubsector(const DVector3& pos) + { + return PointInRenderSubsector(FloatToFixed(pos.X), FloatToFixed(pos.Y)); + } + FPolyObj *GetPolyobj (int polyNum) { auto index = Polyobjects.FindEx([=](const auto &poly) { return poly.tag == polyNum; }); @@ -417,6 +427,8 @@ struct FLevelLocals DThinker *thinker = static_cast(cls->CreateNew()); assert(thinker->IsKindOf(RUNTIME_CLASS(DThinker))); thinker->ObjectFlags |= OF_JustSpawned; + if (thinker->IsKindOf(RUNTIME_CLASS(DVisualThinker))) // [MC] This absolutely must happen for this class! + statnum = STAT_VISUALTHINKER; Thinkers.Link(thinker, statnum); thinker->Level = this; return thinker; @@ -454,13 +466,11 @@ struct FLevelLocals TArray linePortals; // Lightmaps - TArray LMSurfaces; - TArray LMTexCoords; - int LMTextureCount = 0; - int LMTextureSize = 0; - TArray LMTextureData; + bool lightmaps = false; + TArray Surfaces; FVector3 SunDirection; FVector3 SunColor; + uint16_t LightmapSampleDistance; // Portal information. FDisplacementTable Displacements; @@ -607,7 +617,8 @@ struct FLevelLocals uint32_t flags; uint32_t flags2; uint32_t flags3; - uint32_t flags9; + + uint32_t vkdflags; uint32_t fadeto; // The color the palette fades to (usually black) uint32_t outsidefog; // The fog for sectors with sky ceilings @@ -615,6 +626,7 @@ struct FLevelLocals uint32_t hazardcolor; // what color strife hazard blends the screen color as uint32_t hazardflash; // what color strife hazard flashes the screen color as + FString LightningSound = "world/thunder"; FString Music; int musicorder; int cdtrack; @@ -628,6 +640,7 @@ struct FLevelLocals double sky1pos, sky2pos; float hw_sky1pos, hw_sky2pos; bool skystretch; + uint32_t globalcolormap; int total_secrets; int found_secrets; @@ -650,7 +663,7 @@ struct FLevelLocals DSeqNode *SequenceListHead; // [RH] particle globals - uint32_t OldestParticle; // [MC] Oldest particle for replacing with PS_REPLACE + uint32_t OldestParticle; // [MC] Oldest particle for replacing with SPF_REPLACE uint32_t ActiveParticles; uint32_t InactiveParticles; TArray Particles; @@ -679,7 +692,6 @@ struct FLevelLocals float MusicVolume; // Hardware render stuff that can either be set via CVAR or MAPINFO - ELightMode lightMode; bool brightfog; bool lightadditivesurfaces; bool notexturefill; @@ -870,7 +882,7 @@ inline bool line_t::hitSkyWall(AActor* mo) const { return backsector && backsector->GetTexture(sector_t::ceiling) == skyflatnum && - mo->Z() >= backsector->ceilingplane.ZatPoint(mo->PosRelative(this)); + mo->Z() >= backsector->ceilingplane.ZatPoint(mo->PosRelative(this).XY()); } // This must later be extended to return an array with all levels. @@ -879,3 +891,5 @@ inline TArrayView AllLevels() { return TArrayView(&primaryLevel, 1); } + +ELightMode getRealLightmode(FLevelLocals* Level, bool for3d); diff --git a/src/g_pch.h b/src/g_pch.h index bad3eda563..a6623a2dad 100644 --- a/src/g_pch.h +++ b/src/g_pch.h @@ -1,3 +1,4 @@ +#pragma once #include #include #include @@ -9,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/g_pch2.h b/src/g_pch2.h index 4cd69197e0..5ac06f8f07 100644 --- a/src/g_pch2.h +++ b/src/g_pch2.h @@ -1,4 +1,5 @@ // This is separate because the files being compiled with it use different compiler settings which may affect how the header is compiled +#pragma once #include #include #include @@ -10,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/g_statusbar/hudmessages.cpp b/src/g_statusbar/hudmessages.cpp index ccf6174c30..c03922505a 100644 --- a/src/g_statusbar/hudmessages.cpp +++ b/src/g_statusbar/hudmessages.cpp @@ -208,26 +208,11 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h TextColor = textColor; State = 0; - SourceText = copystring (text); + SourceText = text; VisibilityFlags = 0; Style = STYLE_Translucent; Alpha = 1.; - ResetText (SourceText); -} - -//============================================================================ -// -// DHUDMessage Destructor -// -//============================================================================ - -void DHUDMessage::OnDestroy() -{ - if (SourceText != NULL) - { - delete[] SourceText; - SourceText = nullptr; - } + ResetText (SourceText.GetChars()); } //============================================================================ @@ -263,7 +248,7 @@ void DHUDMessage::Serialize(FSerializer &arc) if (arc.isReading()) { - ResetText(SourceText); + ResetText(SourceText.GetChars()); } } @@ -277,7 +262,7 @@ void DHUDMessage::ScreenSizeChanged () { if (HUDWidth == 0) { - ResetText (SourceText); + ResetText (SourceText.GetChars()); } } @@ -493,7 +478,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight) if (hudheight == 0) { int scale = active_con_scaletext(twod); - DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text, + DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text.GetChars(), DTA_VirtualWidth, twod->GetWidth() / scale, DTA_VirtualHeight, twod->GetHeight() / scale, DTA_Alpha, Alpha, @@ -503,7 +488,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight) } else { - DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text, + DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text.GetChars(), DTA_VirtualWidth, HUDWidth, DTA_VirtualHeight, hudheight, DTA_ClipLeft, ClipLeft, @@ -586,7 +571,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh if (hudheight == 0) { int scale = active_con_scaletext(twod); - DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text, + DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text.GetChars(), DTA_VirtualWidth, twod->GetWidth() / scale, DTA_VirtualHeight, twod->GetHeight() / scale, DTA_Alpha, trans, @@ -596,7 +581,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh } else { - DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text, + DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text.GetChars(), DTA_VirtualWidth, HUDWidth, DTA_VirtualHeight, hudheight, DTA_ClipLeft, ClipLeft, @@ -675,7 +660,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu if (hudheight == 0) { int scale = active_con_scaletext(twod); - DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text, + DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text.GetChars(), DTA_VirtualWidth, twod->GetWidth() / scale, DTA_VirtualHeight, twod->GetHeight() / scale, DTA_Alpha, trans, @@ -685,7 +670,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu } else { - DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text, + DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text.GetChars(), DTA_VirtualWidth, HUDWidth, DTA_VirtualHeight, hudheight, DTA_ClipLeft, ClipLeft, @@ -859,7 +844,7 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in if (hudheight == 0) { int scale = active_con_scaletext(twod); - DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text, + DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text.GetChars(), DTA_VirtualWidth, twod->GetWidth() / scale, DTA_VirtualHeight, twod->GetHeight() / scale, DTA_KeepRatio, true, @@ -870,7 +855,7 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in } else { - DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text, + DrawText(twod, Font, TextColor, x, y, Lines[linenum].Text.GetChars(), DTA_VirtualWidth, HUDWidth, DTA_VirtualHeight, hudheight, DTA_ClipLeft, ClipLeft, diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 278f6d9236..a1fa6926c9 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -43,6 +43,7 @@ #include "v_draw.h" #include "c_cvars.h" +class AActor; EXTERN_CVAR(Int, con_scaletext); inline int active_con_scaletext(F2DDrawer* drawer, bool newconfont = false) @@ -99,7 +100,6 @@ class DHUDMessage : public DHUDMessageBase public: DHUDMessage (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight, EColorRange textColor, float holdTime); - virtual void OnDestroy () override; virtual void Serialize(FSerializer &arc); @@ -125,7 +125,7 @@ class DHUDMessage : public DHUDMessageBase void SetNoWrap(bool nowrap) { NoWrap = nowrap; - ResetText(SourceText); + ResetText(SourceText.GetChars()); } void SetClipRect(int x, int y, int width, int height, bool aspect) { @@ -138,7 +138,7 @@ class DHUDMessage : public DHUDMessageBase void SetWrapWidth(int wrap) { WrapWidth = wrap; - ResetText(SourceText); + ResetText(SourceText.GetChars()); } protected: @@ -160,10 +160,10 @@ class DHUDMessage : public DHUDMessageBase double Alpha; void CalcClipCoords(int hudheight); - DHUDMessage () : SourceText(NULL) {} + DHUDMessage() = default; private: - char *SourceText; + FString SourceText; }; @@ -402,7 +402,7 @@ class DBaseStatusBar : public DStatusBarCore virtual bool MustDrawLog(EHudState state); virtual void SetMugShotState (const char *state_name, bool wait_till_done=false, bool reset=false); void DrawLog(); - uint32_t GetTranslation() const override; + FTranslationID GetTranslation() const override; void CreateAltHUD(); void DrawAltHUD(); diff --git a/src/g_statusbar/sbar_mugshot.cpp b/src/g_statusbar/sbar_mugshot.cpp index 3f79b96435..4931243898 100644 --- a/src/g_statusbar/sbar_mugshot.cpp +++ b/src/g_statusbar/sbar_mugshot.cpp @@ -97,7 +97,7 @@ FGameTexture *FMugShotFrame::GetTexture(const char *default_face, const char *sk } sprite.UnlockBuffer(); } - return TexMan.GetGameTexture(TexMan.CheckForTexture(sprite, ETextureType::Any, FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_AllowSkins)); + return TexMan.GetGameTexture(TexMan.CheckForTexture(sprite.GetChars(), ETextureType::Any, FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_AllowSkins)); } //=========================================================================== @@ -376,7 +376,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags) full_state_name = "pain."; } full_state_name += player->LastDamageType.GetChars(); - if (SetState(full_state_name, false, true)) + if (SetState(full_state_name.GetChars(), false, true)) { bDamageFaceActive = (CurrentState != NULL); LastDamageAngle = damage_angle; @@ -403,7 +403,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags) full_state_name = "pain."; } full_state_name += player->LastDamageType.GetChars(); - if (SetState(full_state_name)) + if (SetState(full_state_name.GetChars())) { bOuchActive = use_ouch; } @@ -445,7 +445,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags) full_state_name = "xdeath."; } full_state_name += player->LastDamageType.GetChars(); - SetState(full_state_name); + SetState(full_state_name.GetChars()); bNormal = true; //Allow the face to return to alive states when the player respawns. } return 0; @@ -479,7 +479,7 @@ FGameTexture *FMugShot::GetFace(player_t *player, const char *default_face, int if (CurrentState != NULL) { int skin = player->userinfo.GetSkin(); - const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? (GetDefaultByType(player->MorphedPlayerClass))->NameVar(NAME_Face).GetChars() : Skins[skin].Face.GetChars()); + const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->mo->alternative != nullptr ? (GetDefaultByType(player->MorphedPlayerClass))->NameVar(NAME_Face).GetChars() : Skins[skin].Face.GetChars()); return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle); } return NULL; diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index 6d6b8b7b36..1d855cc232 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -443,7 +443,7 @@ void SBarInfo::Load() { if(gameinfo.statusbar.IsNotEmpty()) { - int lump = fileSystem.CheckNumForFullName(gameinfo.statusbar, true); + int lump = fileSystem.CheckNumForFullName(gameinfo.statusbar.GetChars(), true); if(lump != -1) { if (!batchrun) Printf ("ParseSBarInfo: Loading default status bar definition.\n"); @@ -795,7 +795,7 @@ int SBarInfo::newImage(const char *patchname) } for(unsigned int i = 0;i < this->Images.Size();i++) //did we already load it? { - if(stricmp(this->Images[i], patchname) == 0) + if(stricmp(this->Images[i].GetChars(), patchname) == 0) { return i; } @@ -996,7 +996,7 @@ class DSBarInfo unsigned int i = 0; for(i = 0;i < script->Images.Size();i++) { - patchnames[i] = script->Images[i]; + patchnames[i] = script->Images[i].GetChars(); } for(i = 0;i < 9;i++) { @@ -1247,7 +1247,7 @@ class DSBarInfo DTA_ClipTop, static_cast(dcy), DTA_ClipRight, static_cast(min(INT_MAX, dcr)), DTA_ClipBottom, static_cast(min(INT_MAX, dcb)), - DTA_TranslationIndex, translate ? GetTranslation() : 0, + DTA_TranslationIndex, GetTranslationIndex(translate), DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, DTA_Alpha, Alpha, @@ -1264,7 +1264,7 @@ class DSBarInfo DTA_ClipTop, static_cast(dcy), DTA_ClipRight, static_cast(min(INT_MAX, dcr)), DTA_ClipBottom, static_cast(min(INT_MAX, dcb)), - DTA_TranslationIndex, translate ? GetTranslation() : 0, + DTA_TranslationIndex, GetTranslationIndex(translate), DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, DTA_Alpha, Alpha, @@ -1319,7 +1319,7 @@ class DSBarInfo DTA_ClipTop, static_cast(rcy), DTA_ClipRight, static_cast(rcr), DTA_ClipBottom, static_cast(rcb), - DTA_TranslationIndex, translate ? GetTranslation() : 0, + DTA_TranslationIndex, GetTranslationIndex(translate), DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, DTA_Alpha, Alpha, @@ -1336,7 +1336,7 @@ class DSBarInfo DTA_ClipTop, static_cast(rcy), DTA_ClipRight, static_cast(rcr), DTA_ClipBottom, static_cast(rcb), - DTA_TranslationIndex, translate ? GetTranslation() : 0, + DTA_TranslationIndex, GetTranslationIndex(translate), DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, DTA_Alpha, Alpha, @@ -1467,13 +1467,18 @@ class DSBarInfo } } - uint32_t GetTranslation() const + FTranslationID GetTranslation() const { if(gameinfo.gametype & GAME_Raven) return TRANSLATION(TRANSLATION_PlayersExtra, int(CPlayer - players)); return TRANSLATION(TRANSLATION_Players, int(CPlayer - players)); } + int GetTranslationIndex(bool translate) const + { + return translate? GetTranslation().index() : 0; + } + PClassActor *AmmoType(int no) const { auto w = StatusBar->CPlayer->ReadyWeapon; diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index a6e084ea3f..bbb3bc90fa 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -692,7 +692,7 @@ class CommandDrawString : public SBarInfoCommand auto lines = V_BreakLines(font, breakWidth, str.GetChars()); for(unsigned i = 0; i < lines.Size();i++) { - statusBar->DrawString(font, lines[i].Text, x, y+i*(font->GetHeight()+4), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow, shadowX, shadowY); + statusBar->DrawString(font, lines[i].Text.GetChars(), x, y+i*(font->GetHeight()+4), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow, shadowX, shadowY); } } else @@ -824,10 +824,7 @@ class CommandDrawString : public SBarInfoCommand { strValue = CONSTANT; sc.MustGetToken(TK_StringConst); - if(sc.String[0] == '$') - str = GStrings[sc.String+1]; - else - str = sc.String; + label = sc.String; } } void Reset() @@ -923,9 +920,10 @@ class CommandDrawString : public SBarInfoCommand break; } case LOGTEXT: - str = GStrings(statusBar->CPlayer->LogText); + str = GStrings.GetString(statusBar->CPlayer->LogText); break; default: + str = GStrings.localize(label.GetChars()); break; } } @@ -993,6 +991,7 @@ class CommandDrawString : public SBarInfoCommand StringValueType strValue; int valueArgument; FString str; + FString label; StringAlignment alignment; private: @@ -1183,7 +1182,7 @@ class CommandDrawNumber : public CommandDrawString // We have a name, but make sure it exists. If not, send notification so modders // are aware of the situation. - FBaseCVar *CVar = FindCVar(cvarName, nullptr); + FBaseCVar *CVar = FindCVar(cvarName.GetChars(), nullptr); if (CVar != nullptr) { @@ -1484,7 +1483,7 @@ class CommandDrawNumber : public CommandDrawString break; case INTCVAR: { - FBaseCVar *CVar = GetCVar(int(statusBar->CPlayer - players), cvarName); + FBaseCVar *CVar = GetCVar(int(statusBar->CPlayer - players), cvarName.GetChars()); if (CVar != nullptr) { ECVarType cvartype = CVar->GetRealType(); @@ -1618,7 +1617,7 @@ class CommandDrawMugShot : public SBarInfoCommand void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) { - FGameTexture *face = statusBar->wrapper->mugshot.GetFace(statusBar->CPlayer, defaultFace, accuracy, stateFlags); + FGameTexture *face = statusBar->wrapper->mugshot.GetFace(statusBar->CPlayer, defaultFace.GetChars(), accuracy, stateFlags); if (face != NULL) statusBar->DrawGraphic(face, x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); } @@ -2954,7 +2953,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl bool foundClass = false; for(unsigned int c = 0;c < PlayerClasses.Size();c++) { - if(stricmp(sc.String, PlayerClasses[c].Type->GetDisplayName()) == 0) + if(stricmp(sc.String, PlayerClasses[c].Type->GetDisplayName().GetChars()) == 0) { foundClass = true; classes.Push(PlayerClasses[c].Type); @@ -3499,7 +3498,7 @@ class CommandIfCVarInt : public SBarInfoNegatableFlowControl } cvarname = sc.String; - cvar = FindCVar(cvarname, nullptr); + cvar = FindCVar(cvarname.GetChars(), nullptr); if (cvar != nullptr) { @@ -3536,7 +3535,7 @@ class CommandIfCVarInt : public SBarInfoNegatableFlowControl SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged); bool result = false; - cvar = GetCVar(int(statusBar->CPlayer - players), cvarname); + cvar = GetCVar(int(statusBar->CPlayer - players), cvarname.GetChars()); if (cvar != nullptr) { diff --git a/src/g_statusbar/shared_hud.cpp b/src/g_statusbar/shared_hud.cpp index a6a6ea4107..f53e93a74f 100644 --- a/src/g_statusbar/shared_hud.cpp +++ b/src/g_statusbar/shared_hud.cpp @@ -74,6 +74,7 @@ CVAR (Int , hud_showlag, 0, CVAR_ARCHIVE); // Show input latency (maketic - g CVAR (Int, hud_ammo_order, 0, CVAR_ARCHIVE); // ammo image and text order CVAR (Int, hud_ammo_red, 25, CVAR_ARCHIVE) // ammo percent less than which status is red CVAR (Int, hud_ammo_yellow, 50, CVAR_ARCHIVE) // ammo percent less is yellow more green +CVAR (Bool, hud_swaphealtharmor, false, CVAR_ARCHIVE); // swap health and armor position on HUD CVAR (Int, hud_health_red, 25, CVAR_ARCHIVE) // health amount less than which status is red CVAR (Int, hud_health_yellow, 50, CVAR_ARCHIVE) // health amount less than which status is yellow CVAR (Int, hud_health_green, 100, CVAR_ARCHIVE) // health amount above is blue, below is green @@ -193,4 +194,3 @@ void DBaseStatusBar::DrawAltHUD() VMCall(func, params, countof(params), nullptr, 0); } } - diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 01a67a12a8..fc8060d6a9 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -157,45 +157,45 @@ void V_DrawFrame(F2DDrawer* drawer, int left, int top, int width, int height, bo if (!scalemode) { // Draw top and bottom sides. - p = TexMan.GetGameTextureByName(border->t); + p = TexMan.GetGameTextureByName(border->t.GetChars()); drawer->AddFlatFill(left, top - (int)p->GetDisplayHeight(), right, top, p, true); - p = TexMan.GetGameTextureByName(border->b); + p = TexMan.GetGameTextureByName(border->b.GetChars()); drawer->AddFlatFill(left, bottom, right, bottom + (int)p->GetDisplayHeight(), p, true); // Draw left and right sides. - p = TexMan.GetGameTextureByName(border->l); + p = TexMan.GetGameTextureByName(border->l.GetChars()); drawer->AddFlatFill(left - (int)p->GetDisplayWidth(), top, left, bottom, p, true); - p = TexMan.GetGameTextureByName(border->r); + p = TexMan.GetGameTextureByName(border->r.GetChars()); drawer->AddFlatFill(right, top, right + (int)p->GetDisplayWidth(), bottom, p, true); // Draw beveled corners. - DrawTexture(drawer, TexMan.GetGameTextureByName(border->tl), left - offset, top - offset, TAG_DONE); - DrawTexture(drawer, TexMan.GetGameTextureByName(border->tr), left + width, top - offset, TAG_DONE); - DrawTexture(drawer, TexMan.GetGameTextureByName(border->bl), left - offset, top + height, TAG_DONE); - DrawTexture(drawer, TexMan.GetGameTextureByName(border->br), left + width, top + height, TAG_DONE); + DrawTexture(drawer, TexMan.GetGameTextureByName(border->tl.GetChars()), left - offset, top - offset, TAG_DONE); + DrawTexture(drawer, TexMan.GetGameTextureByName(border->tr.GetChars()), left + width, top - offset, TAG_DONE); + DrawTexture(drawer, TexMan.GetGameTextureByName(border->bl.GetChars()), left - offset, top + height, TAG_DONE); + DrawTexture(drawer, TexMan.GetGameTextureByName(border->br.GetChars()), left + width, top + height, TAG_DONE); } else { // Draw top and bottom sides. - p = TexMan.GetGameTextureByName(border->t); + p = TexMan.GetGameTextureByName(border->t.GetChars()); drawer->AddFlatFill(left, top - (int)(p->GetDisplayHeight() / sh), right, top, p, -2); - p = TexMan.GetGameTextureByName(border->b); + p = TexMan.GetGameTextureByName(border->b.GetChars()); drawer->AddFlatFill(left, bottom, right, bottom + (int)(p->GetDisplayHeight() / sh), p, -2); // Draw left and right sides. - p = TexMan.GetGameTextureByName(border->l); + p = TexMan.GetGameTextureByName(border->l.GetChars()); drawer->AddFlatFill(left - (int)(p->GetDisplayWidth() / sw), top, left, bottom, p, -2); - p = TexMan.GetGameTextureByName(border->r); + p = TexMan.GetGameTextureByName(border->r.GetChars()); drawer->AddFlatFill(right, top, right + (int)(p->GetDisplayWidth() / sw), bottom, p, -2); // Draw beveled corners. - p = TexMan.GetGameTextureByName(border->tl); + p = TexMan.GetGameTextureByName(border->tl.GetChars()); drawer->AddFlatFill(left - (int)(p->GetDisplayWidth() / sw), top - (int)(p->GetDisplayHeight() / sh), left, top, p, -2); - p = TexMan.GetGameTextureByName(border->tr); + p = TexMan.GetGameTextureByName(border->tr.GetChars()); drawer->AddFlatFill(right, top - (int)(p->GetDisplayHeight() / sh), right + (int)(p->GetDisplayWidth() / sw), top, p, -2); - p = TexMan.GetGameTextureByName(border->bl); + p = TexMan.GetGameTextureByName(border->bl.GetChars()); drawer->AddFlatFill(left - (int)(p->GetDisplayWidth() / sw), bottom, left, bottom + (int)(p->GetDisplayHeight() / sh), p, -2); - p = TexMan.GetGameTextureByName(border->br); + p = TexMan.GetGameTextureByName(border->br.GetChars()); drawer->AddFlatFill(right, bottom, right + (int)(p->GetDisplayWidth() / sw), bottom + (int)(p->GetDisplayHeight() / sh), p, -2); } } @@ -233,6 +233,10 @@ void ST_LoadCrosshair(bool alwaysload) { num = crosshair; } + if (num < 0) + { + num = 0; + } ST_LoadCrosshair(num, alwaysload); } @@ -546,14 +550,14 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) if (!generic_ui) { // If the original font does not have accents this will strip them - but a fallback to the VGA font is not desirable here for such cases. - if (!font->CanPrint(GStrings("AM_MONSTERS")) || !font->CanPrint(GStrings("AM_SECRETS")) || !font->CanPrint(GStrings("AM_ITEMS"))) font2 = OriginalSmallFont; + if (!font->CanPrint(GStrings.GetString("AM_MONSTERS")) || !font->CanPrint(GStrings.GetString("AM_SECRETS")) || !font->CanPrint(GStrings.GetString("AM_ITEMS"))) font2 = OriginalSmallFont; } if (am_showtime) { sec = Tics2Seconds(primaryLevel->time); textbuffer.Format("%02d:%02d:%02d", sec / 3600, (sec % 3600) / 60, sec % 60); - DrawText(twod, font, crdefault, vwidth - zerowidth * 8 - textdist, y, textbuffer, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, + DrawText(twod, font, crdefault, vwidth - zerowidth * 8 - textdist, y, textbuffer.GetChars(), DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, DTA_Monospace, EMonospacing::CellCenter, DTA_Spacing, zerowidth, DTA_KeepRatio, true, TAG_END); y += fheight; } @@ -562,7 +566,7 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) { sec = Tics2Seconds(primaryLevel->totaltime); textbuffer.Format("%02d:%02d:%02d", sec / 3600, (sec % 3600) / 60, sec % 60); - DrawText(twod, font, crdefault, vwidth - zerowidth * 8 - textdist, y, textbuffer, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, + DrawText(twod, font, crdefault, vwidth - zerowidth * 8 - textdist, y, textbuffer.GetChars(), DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, DTA_Monospace, EMonospacing::CellCenter, DTA_Spacing, zerowidth, DTA_KeepRatio, true, TAG_END); } @@ -571,23 +575,23 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) y = 0; if (am_showmonsters) { - textbuffer.Format("%s\34%c %d/%d", GStrings("AM_MONSTERS"), crdefault + 65, primaryLevel->killed_monsters, primaryLevel->total_monsters); - DrawText(twod, font2, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); + textbuffer.Format("%s\34%c %d/%d", GStrings.GetString("AM_MONSTERS"), crdefault + 65, primaryLevel->killed_monsters, primaryLevel->total_monsters); + DrawText(twod, font2, highlight, textdist, y, textbuffer.GetChars(), DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); y += fheight; } if (am_showsecrets) { - textbuffer.Format("%s\34%c %d/%d", GStrings("AM_SECRETS"), crdefault + 65, primaryLevel->found_secrets, primaryLevel->total_secrets); - DrawText(twod, font2, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); + textbuffer.Format("%s\34%c %d/%d", GStrings.GetString("AM_SECRETS"), crdefault + 65, primaryLevel->found_secrets, primaryLevel->total_secrets); + DrawText(twod, font2, highlight, textdist, y, textbuffer.GetChars(), DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); y += fheight; } // Draw item count if (am_showitems) { - textbuffer.Format("%s\34%c %d/%d", GStrings("AM_ITEMS"), crdefault + 65, primaryLevel->found_items, primaryLevel->total_items); - DrawText(twod, font2, highlight, textdist, y, textbuffer, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); + textbuffer.Format("%s\34%c %d/%d", GStrings.GetString("AM_ITEMS"), crdefault + 65, primaryLevel->found_items, primaryLevel->total_items); + DrawText(twod, font2, highlight, textdist, y, textbuffer.GetChars(), DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); y += fheight; } @@ -627,7 +631,7 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) for (unsigned i = 0; i < numlines; i++) { int x = (vwidth - font->StringWidth(lines[i].Text)) / 2; - DrawText(twod, font, highlight, x, y, lines[i].Text, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); + DrawText(twod, font, highlight, x, y, lines[i].Text.GetChars(), DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); y += fheight; } } @@ -876,10 +880,10 @@ static FTextureID GetBorderTexture(FLevelLocals *Level) { if (Level != nullptr && Level->info != nullptr && Level->info->BorderTexture.Len() != 0) { - auto picnum = TexMan.CheckForTexture (Level->info->BorderTexture, ETextureType::Flat); + auto picnum = TexMan.CheckForTexture (Level->info->BorderTexture.GetChars(), ETextureType::Flat); if (picnum.isValid()) return picnum; } - return TexMan.CheckForTexture (gameinfo.BorderFlat, ETextureType::Flat); + return TexMan.CheckForTexture (gameinfo.BorderFlat.GetChars(), ETextureType::Flat); } //========================================================================== @@ -958,7 +962,7 @@ void DBaseStatusBar::RefreshBackground () const if (setblocks >= 10) { - FGameTexture *p = TexMan.GetGameTextureByName(gameinfo.Border.b); + FGameTexture *p = TexMan.GetGameTextureByName(gameinfo.Border.b.GetChars()); if (p != NULL) { if (!ui_screenborder_classic_scaling) @@ -1117,7 +1121,7 @@ void DBaseStatusBar::DrawLog () FFont *font = (generic_ui || log_vgafont)? NewSmallFont : SmallFont; int linelen = hudwidth<640? Scale(hudwidth,9,10)-40 : 560; - auto lines = V_BreakLines (font, linelen, text[0] == '$'? GStrings(text.GetChars()+1) : text.GetChars()); + auto lines = V_BreakLines (font, linelen, text[0] == '$'? GStrings.GetString(text.GetChars()+1) : text.GetChars()); int height = 20; for (unsigned i = 0; i < lines.Size(); i++) height += font->GetHeight (); @@ -1143,7 +1147,7 @@ void DBaseStatusBar::DrawLog () y+=10; for (const FBrokenLines &line : lines) { - DrawText(twod, font, CPlayer->SubtitleCounter? CR_CYAN : CR_UNTRANSLATED, x, y, line.Text, + DrawText(twod, font, CPlayer->SubtitleCounter? CR_CYAN : CR_UNTRANSLATED, x, y, line.Text.GetChars(), DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, TAG_DONE); y += font->GetHeight (); @@ -1376,7 +1380,7 @@ AActor *DBaseStatusBar::ValidateInvFirst (int numVisible) const return nullptr; } -uint32_t DBaseStatusBar::GetTranslation() const +FTranslationID DBaseStatusBar::GetTranslation() const { if (gameinfo.gametype & GAME_Raven) return TRANSLATION(TRANSLATION_PlayersExtra, int(CPlayer - players)); diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index a054d59300..10931c138d 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -91,14 +91,14 @@ FGameConfigFile::FGameConfigFile () OkayToWrite = false; // Do not allow saving of the config before DoKeySetup() bModSetup = false; pathname = GetConfigPath (true); - ChangePathName (pathname); + ChangePathName (pathname.GetChars()); LoadConfigFile (); // If zdoom.ini was read from the program directory, switch // to the user directory now. If it was read from the user // directory, this effectively does nothing. pathname = GetConfigPath (false); - ChangePathName (pathname); + ChangePathName (pathname.GetChars()); // Set default IWAD search paths if none present if (!SetSection ("IWADSearch.Directories")) @@ -107,10 +107,10 @@ FGameConfigFile::FGameConfigFile () SetValueForKey ("Path", ".", true); SetValueForKey ("Path", "$DOOMWADDIR", true); #ifdef __APPLE__ - SetValueForKey ("Path", user_docs, true); - SetValueForKey ("Path", user_app_support, true); + SetValueForKey ("Path", user_docs.GetChars(), true); + SetValueForKey ("Path", user_app_support.GetChars(), true); SetValueForKey ("Path", "$PROGDIR", true); - SetValueForKey ("Path", local_app_support, true); + SetValueForKey ("Path", local_app_support.GetChars(), true); #elif !defined(__unix__) SetValueForKey ("Path", "$HOME", true); SetValueForKey ("Path", "$PROGDIR", true); @@ -132,10 +132,10 @@ FGameConfigFile::FGameConfigFile () { SetSection ("FileSearch.Directories", true); #ifdef __APPLE__ - SetValueForKey ("Path", user_docs, true); - SetValueForKey ("Path", user_app_support, true); + SetValueForKey ("Path", user_docs.GetChars(), true); + SetValueForKey ("Path", user_app_support.GetChars(), true); SetValueForKey ("Path", "$PROGDIR", true); - SetValueForKey ("Path", local_app_support, true); + SetValueForKey ("Path", local_app_support.GetChars(), true); #elif !defined(__unix__) SetValueForKey ("Path", "$PROGDIR", true); #else @@ -155,14 +155,14 @@ FGameConfigFile::FGameConfigFile () { SetSection("SoundfontSearch.Directories", true); #ifdef __APPLE__ - SetValueForKey("Path", user_docs + "/soundfonts", true); - SetValueForKey("Path", user_docs + "/fm_banks", true); - SetValueForKey("Path", user_app_support + "/soundfonts", true); - SetValueForKey("Path", user_app_support + "/fm_banks", true); + SetValueForKey("Path", (user_docs + "/soundfonts").GetChars(), true); + SetValueForKey("Path", (user_docs + "/fm_banks").GetChars(), true); + SetValueForKey("Path", (user_app_support + "/soundfonts").GetChars(), true); + SetValueForKey("Path", (user_app_support + "/fm_banks").GetChars(), true); SetValueForKey("Path", "$PROGDIR/soundfonts", true); SetValueForKey("Path", "$PROGDIR/fm_banks", true); - SetValueForKey("Path", local_app_support + "/soundfonts", true); - SetValueForKey("Path", local_app_support + "/fm_banks", true); + SetValueForKey("Path", (local_app_support + "/soundfonts").GetChars(), true); + SetValueForKey("Path", (local_app_support + "/fm_banks").GetChars(), true); #elif !defined(__unix__) SetValueForKey("Path", "$PROGDIR/soundfonts", true); SetValueForKey("Path", "$PROGDIR/fm_banks", true); @@ -598,6 +598,15 @@ void FGameConfigFile::DoGlobalSetup () var->SetGenericRep(v, CVAR_Float); } } + if (last < 225) + { + if (const auto var = FindCVar("gl_lightmode", NULL)) + { + UCVarValue v = var->GetGenericRep(CVAR_Int); + v.Int = v.Int == 16 ? 2 : v.Int == 8 ? 1 : 0; + var->SetGenericRep(v, CVAR_Int); + } + } } } } diff --git a/src/gameconfigfile.h b/src/gameconfigfile.h index 023277ae7b..0b898112eb 100644 --- a/src/gameconfigfile.h +++ b/src/gameconfigfile.h @@ -36,6 +36,7 @@ #include "doomtype.h" #include "configfile.h" +#include "files.h" class FArgs; class FIWadManager; diff --git a/src/gamedata/a_keys.cpp b/src/gamedata/a_keys.cpp index e3defc739a..32f680a423 100644 --- a/src/gamedata/a_keys.cpp +++ b/src/gamedata/a_keys.cpp @@ -218,7 +218,7 @@ static void PrintMessage (const char *str) { if (str[0]=='$') { - str = GStrings(str+1); + str = GStrings.GetString(str+1); } C_MidPrint (nullptr, str); } @@ -487,7 +487,7 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet) { if (lock->check(owner)) return true; if (quiet) return false; - failtext = remote? lock->RemoteMsg : lock->Message; + failtext = remote? lock->RemoteMsg.GetChars() : lock->Message.GetChars(); failsound = &lock->locksound[0]; numfailsounds = lock->locksound.Size(); } diff --git a/src/gamedata/a_weapons.cpp b/src/gamedata/a_weapons.cpp index fa527d7708..93768fd54b 100644 --- a/src/gamedata/a_weapons.cpp +++ b/src/gamedata/a_weapons.cpp @@ -408,9 +408,9 @@ void FWeaponSlots::LocalSetup(PClassActor *type) { FString sectionclass(WeaponSection); sectionclass << '.' << type->TypeName.GetChars(); - if (RestoreSlots(GameConfig, sectionclass) == 0) + if (RestoreSlots(GameConfig, sectionclass.GetChars()) == 0) { - RestoreSlots(GameConfig, WeaponSection); + RestoreSlots(GameConfig, WeaponSection.GetChars()); } } else @@ -450,15 +450,15 @@ void FWeaponSlots::SendDifferences(int playernum, const FWeaponSlots &other) // The slots differ. Send mine. if (playernum == consoleplayer) { - Net_WriteByte(DEM_SETSLOT); + Net_WriteInt8(DEM_SETSLOT); } else { - Net_WriteByte(DEM_SETSLOTPNUM); - Net_WriteByte(playernum); + Net_WriteInt8(DEM_SETSLOTPNUM); + Net_WriteInt8(playernum); } - Net_WriteByte(i); - Net_WriteByte(Slots[i].Size()); + Net_WriteInt8(i); + Net_WriteInt8(Slots[i].Size()); for (j = 0; j < Slots[i].Size(); ++j) { Net_WriteWeapon(Slots[i].GetWeapon(j)); @@ -504,7 +504,7 @@ int FWeaponSlots::RestoreSlots(FConfigFile *config, const char *section) int slotsread = 0; section_name += ".Weapons"; - if (!config->SetSection(section_name)) + if (!config->SetSection(section_name.GetChars())) { return 0; } @@ -596,9 +596,9 @@ CCMD (setslot) Printf ("Slot %d cleared\n", slot); } - Net_WriteByte(DEM_SETSLOT); - Net_WriteByte(slot); - Net_WriteByte(argv.argc()-2); + Net_WriteInt8(DEM_SETSLOT); + Net_WriteInt8(slot); + Net_WriteInt8(argv.argc()-2); for (int i = 2; i < argv.argc(); i++) { Net_WriteWeapon(PClass::FindActor(argv[i])); @@ -647,8 +647,8 @@ CCMD (addslot) } else { - Net_WriteByte(DEM_ADDSLOT); - Net_WriteByte(slot); + Net_WriteInt8(DEM_ADDSLOT); + Net_WriteInt8(slot); Net_WriteWeapon(type); } } @@ -723,8 +723,8 @@ CCMD (addslotdefault) } else { - Net_WriteByte(DEM_ADDSLOTDEFAULT); - Net_WriteByte(slot); + Net_WriteInt8(DEM_ADDSLOTDEFAULT); + Net_WriteInt8(slot); Net_WriteWeapon(type); } } @@ -742,7 +742,7 @@ void P_PlaybackKeyConfWeapons(FWeaponSlots *slots) PlayingKeyConf = slots; for (unsigned int i = 0; i < KeyConfWeapons.Size(); ++i) { - AddCommandString(KeyConfWeapons[i]); + AddCommandString(KeyConfWeapons[i].GetChars()); } PlayingKeyConf = nullptr; } @@ -857,7 +857,7 @@ static int ntoh_cmp(const void *a, const void *b) void P_WriteDemoWeaponsChunk(uint8_t **demo) { - WriteWord(Weapons_ntoh.Size(), demo); + WriteInt16(Weapons_ntoh.Size(), demo); for (unsigned int i = 1; i < Weapons_ntoh.Size(); ++i) { WriteString(Weapons_ntoh[i]->TypeName.GetChars(), demo); @@ -879,7 +879,7 @@ void P_ReadDemoWeaponsChunk(uint8_t **demo) PClassActor *type; const char *s; - count = ReadWord(demo); + count = ReadInt16(demo); Weapons_ntoh.Resize(count); Weapons_hton.Clear(count); @@ -923,12 +923,12 @@ void Net_WriteWeapon(PClassActor *type) assert(index >= 0 && index <= 32767); if (index < 128) { - Net_WriteByte(index); + Net_WriteInt8(index); } else { - Net_WriteByte(0x80 | index); - Net_WriteByte(index >> 7); + Net_WriteInt8(0x80 | index); + Net_WriteInt8(index >> 7); } } @@ -942,10 +942,10 @@ PClassActor *Net_ReadWeapon(uint8_t **stream) { int index; - index = ReadByte(stream); + index = ReadInt8(stream); if (index & 0x80) { - index = (index & 0x7F) | (ReadByte(stream) << 7); + index = (index & 0x7F) | (ReadInt8(stream) << 7); } if ((unsigned)index >= Weapons_ntoh.Size()) { diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 442068a679..029878176b 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -97,6 +97,7 @@ static TArray OrgHeights; // disappear, but that doesn't explain why frame patches specify an exact // state rather than a code pointer.) static TArray CodePConv; +static bool dsdhacked = false; // Sprite names in the order Doom originally had them. struct DEHSprName @@ -104,6 +105,8 @@ struct DEHSprName char c[5]; }; static TArray OrgSprNames; +size_t OrgSprOrgSize; +static TMap stateSprites; struct StateMapper { @@ -122,6 +125,94 @@ static TArray SoundMap; // Names of different actor types, in original Doom 2 order static TArray InfoNames; +static PClassActor* FindInfoName(int index, bool mustexist = false) +{ + if (index < 0) return nullptr; + if (index < (int)InfoNames.Size()) return InfoNames[index]; + + if (dsdhacked) + { + FStringf name("~Dsdhacked~%d", index); + auto cls = PClass::FindActor(name); + if (!mustexist) + { + cls = static_cast(RUNTIME_CLASS(AActor)->CreateDerivedClass(name.GetChars(), (unsigned)sizeof(AActor))); + NewClassType(cls, -1); // This needs a VM type to work as intended. + cls->InitializeDefaults(); + } + if (cls) + { + GetDefaultByType(cls)->flags8 |= MF8_RETARGETAFTERSLAM; // This flag is not a ZDoom default, but it must be a Dehacked default. + return cls; + } + } + return nullptr; +} + +static FSoundID DehFindSound(int index,bool mustexist = false) +{ + if (index < 0) return NO_SOUND; + if (index < (int) SoundMap.Size() && SoundMap[index].isvalid()) return SoundMap[index]; + if (dsdhacked && !mustexist) + { + FStringf name("~dsdhacked/#%d", index); + return soundEngine->FindSoundTentative(name.GetChars()); + } + return NO_SOUND; +} + +static void ReplaceSoundName(int index, const char* newname) +{ + // This must physically replace the sound's lump name in the sound record. + auto snd = DehFindSound(index-1); + if (snd == NO_SOUND) return; + auto sfx = soundEngine->GetWritableSfx(snd); + FStringf dsname("ds%s", newname); + sfx->lumpnum = fileSystem.CheckNumForName(dsname.GetChars(), FileSys::ns_sounds); + sfx->bTentative = false; + sfx->bRandomHeader = false; + sfx->bLoadRAW = false; + sfx->b16bit = false; + sfx->bUsed = false; + sfx->UserData[0] = 0; +} + +void RemapAllSprites() +{ + TMap::Iterator it(stateSprites); + TMap::Pair *pair; + + while (it.NextPair(pair)) + { + int frameNum = 0; // Hmmm... + auto info = pair->Key; + int val = pair->Value; + unsigned int i; + + if (val >= 0 && val < (int)OrgSprNames.Size()) + { + for (i = 0; i < sprites.Size(); i++) + { + if (memcmp (OrgSprNames[val].c, sprites[i].name, 4) == 0) + { + info->sprite = (int)i; + break; + } + } + if (i == sprites.Size ()) + { + Printf ("Frame %d: Sprite %d (%s) is undefined\n", + frameNum, val, OrgSprNames[val].c); + } + } + else + { + Printf ("Frame %d: Sprite %d out of range\n", frameNum, val); + } + } + stateSprites.Clear(); +} + // bit flags for PatchThing (a .bex extension): struct BitName { @@ -150,7 +241,7 @@ struct MBFArgs int argsused; }; static TMap stateargs; -static FState* FindState(int statenum); +static FState* FindState(int statenum, bool mustexist = false); // DeHackEd trickery to support MBF-style parameters // List of states that are hacked to use a codepointer @@ -163,10 +254,8 @@ struct MBFParamState PClassActor* GetTypeArg(int i) { - PClassActor* type = nullptr; int num = (int)args[i]; - if (num > 0 && num < int(InfoNames.Size())) type = InfoNames[num-1]; // Dehacked is 1-based. - return type; + return FindInfoName(num-1, true); } FState* GetStateArg(int i) @@ -181,11 +270,10 @@ struct MBFParamState return argsused & (1 << i)? (int)args[i] : def; } - int GetSoundArg(int i, int def = 0) + FSoundID GetSoundArg(int i, int def = 0) { int num = argsused & (1 << i) ? (int)args[i] : def; - if (num > 0 && num <= int(SoundMap.Size())) return SoundMap[num-1].index(); - return 0; + return DehFindSound(num-1); } double GetFloatArg(int i, double def = 0) @@ -373,6 +461,8 @@ static int PatchPars (int); static int PatchCodePtrs (int); static int PatchMusic (int); static int DoInclude (int); +static int PatchSpriteNames(int); +static int PatchSoundNames(int); static bool DoDehPatch(); static const struct { @@ -396,6 +486,8 @@ static const struct { { "[PARS]", PatchPars }, { "[CODEPTR]", PatchCodePtrs }, { "[MUSIC]", PatchMusic }, + { "[SPRITES]", PatchSpriteNames }, + { "[SOUNDS]", PatchSoundNames }, { NULL, NULL }, }; @@ -456,19 +548,19 @@ static int FindSprite (const char *sprname) return f == UnchangedSpriteNames.Size() ? -1 : f; } -static FState *FindState (int statenum) +static FState *FindState (int statenum, bool mustexist) { int stateacc; unsigned i; - if (statenum == 0) + if (statenum <= 0) return NULL; for (i = 0, stateacc = 1; i < StateMap.Size(); i++) { if (stateacc <= statenum && stateacc + StateMap[i].StateSpan > statenum) { - if (StateMap[i].State != NULL) + if (StateMap[i].State != nullptr) { if (StateMap[i].OwnerIsPickup) { @@ -476,11 +568,28 @@ static FState *FindState (int statenum) } return StateMap[i].State + statenum - stateacc; } - else return NULL; + else break; } stateacc += StateMap[i].StateSpan; } - return NULL; + if (dsdhacked) + { + auto p = dehExtStates.CheckKey(statenum); + if (p) return *p; + if (!mustexist) + { + auto state = (FState*)ClassDataAllocator.Alloc(sizeof(FState)); + dehExtStates.Insert(statenum, state); + memset(state, 0, sizeof(*state)); + state->Tics = -1; + state->NextState = state; + state->DehIndex = statenum; + state->UseFlags = SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM; + return state; + } + + } + return nullptr; } int FindStyle (const char *namestr) @@ -694,11 +803,12 @@ static void CreateMushroomFunc(FunctionCallEmitter &emitters, int value1, int va // misc1 = type (arg +0), misc2 = Z-pos (arg +2) static void CreateSpawnFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) { // A_SpawnItem - if (InfoNames[value1-1] == nullptr) + auto p = FindInfoName(value1 - 1, true); + if (p == nullptr) { I_Error("No class found for dehackednum %d!\n", value1+1); } - emitters.AddParameterPointerConst(InfoNames[value1-1]); // itemtype + emitters.AddParameterPointerConst(p); // itemtype emitters.AddParameterFloatConst(0); // distance emitters.AddParameterFloatConst(value2); // height emitters.AddParameterIntConst(0); // useammo @@ -724,7 +834,7 @@ static void CreateFaceFunc(FunctionCallEmitter &emitters, int value1, int value2 static void CreateScratchFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) { // A_CustomMeleeAttack emitters.AddParameterIntConst(value1); // damage - emitters.AddParameterIntConst(value2 ? (int)SoundMap[value2 - 1].index() : 0); // hit sound + emitters.AddParameterIntConst(DehFindSound(value2 - 1, true).index()); // hit sound emitters.AddParameterIntConst(0); // miss sound emitters.AddParameterIntConst(NAME_None); // damage type emitters.AddParameterIntConst(true); // bleed @@ -733,7 +843,7 @@ static void CreateScratchFunc(FunctionCallEmitter &emitters, int value1, int val // misc1 = sound, misc2 = attenuation none (true) or normal (false) static void CreatePlaySoundFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) { // A_PlaySound - emitters.AddParameterIntConst(value1 ? (int)SoundMap[value1 - 1].index() : 0); // soundid + emitters.AddParameterIntConst(DehFindSound(value1 - 1, true).index()); // soundid emitters.AddParameterIntConst(CHAN_BODY); // channel emitters.AddParameterFloatConst(1); // volume emitters.AddParameterIntConst(false); // looping @@ -745,7 +855,7 @@ static void CreatePlaySoundFunc(FunctionCallEmitter &emitters, int value1, int v // misc1 = state, misc2 = probability static void CreateRandomJumpFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) { // A_Jump - auto symlabel = StateLabels.AddPointer(FindState(value1)); + auto symlabel = StateLabels.AddPointer(FindState(value1, true)); emitters.AddParameterIntConst(value2); // maxchance emitters.AddParameterIntConst(symlabel); // jumpto @@ -802,7 +912,7 @@ static void CreateMonsterMeleeAttackFunc(FunctionCallEmitter &emitters, int valu state->ValidateArgCount(4, "A_MonsterMeleeAttack"); emitters.AddParameterIntConst(state->GetIntArg(0, 3)); emitters.AddParameterIntConst(state->GetIntArg(1, 8)); - emitters.AddParameterIntConst(state->GetSoundArg(2, 0)); + emitters.AddParameterIntConst(state->GetSoundArg(2, 0).index()); emitters.AddParameterFloatConst(state->GetFloatArg(3)); } @@ -818,7 +928,7 @@ static void CreateHealChaseFunc(FunctionCallEmitter &emitters, int value1, int v { state->ValidateArgCount(2, "A_HealChase"); emitters.AddParameterPointerConst(state->GetStateArg(0)); - emitters.AddParameterIntConst(state->GetSoundArg(1)); + emitters.AddParameterIntConst(state->GetSoundArg(1).index()); } static void CreateSeekTracerFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) @@ -890,14 +1000,14 @@ static void CreateWeaponMeleeAttackFunc(FunctionCallEmitter &emitters, int value emitters.AddParameterIntConst(state->GetIntArg(0, 2)); emitters.AddParameterIntConst(state->GetIntArg(1, 10)); emitters.AddParameterFloatConst(state->GetFloatArg(2, 1)); - emitters.AddParameterIntConst(state->GetSoundArg(3)); + emitters.AddParameterIntConst(state->GetSoundArg(3).index()); emitters.AddParameterFloatConst(state->GetFloatArg(4)); } static void CreateWeaponSoundFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) { state->ValidateArgCount(2, "A_WeaponSound"); - emitters.AddParameterIntConst(state->GetSoundArg(0)); + emitters.AddParameterIntConst(state->GetSoundArg(0).index()); emitters.AddParameterIntConst(state->GetIntArg(1)); } @@ -965,11 +1075,6 @@ static void SetDehParams(FState *state, int codepointer, VMDisassemblyDumper &di bool returnsState = codepointer == 6; - // Fakey fake script position thingamajig. Because NULL cannot be used instead. - // Even if the lump was parsed by an FScanner, there would hardly be a way to - // identify which line is troublesome. - FScriptPosition *pos = new FScriptPosition(FString("DEHACKED"), 0); - // Let's identify the codepointer we're dealing with. PFunction *sym; sym = dyn_cast(PClass::FindActor(NAME_Weapon)->FindSymbol(FName(MBFCodePointers[codepointer].name), true)); @@ -1016,7 +1121,7 @@ static void SetDehParams(FState *state, int codepointer, VMDisassemblyDumper &di sfunc->NumArgs = numargs; sfunc->ImplicitArgs = numargs; state->SetAction(sfunc); - sfunc->PrintableName.Format("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2); + sfunc->PrintableName = ClassDataAllocator.Strdup(FStringf("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2).GetChars()); disasmdump.Write(sfunc, sfunc->PrintableName); @@ -1051,7 +1156,7 @@ static const struct DehFlags2 deh_mobjflags_mbf21[] = { {"RANGEHALF", [](AActor* defaults) { defaults->flags4 |= MF4_MISSILEMORE; }}, // use half distance for missile attack probability {"NOTHRESHOLD", [](AActor* defaults) { defaults->flags4 |= MF4_QUICKTORETALIATE; }}, // no targeting threshold {"LONGMELEE", [](AActor* defaults) { defaults->meleethreshold = 196; }}, // long melee range - {"BOSS", [](AActor* defaults) { defaults->flags2 |= MF2_BOSS; }}, // full volume see / death sound + splash immunity + {"BOSS", [](AActor* defaults) { defaults->flags2 |= MF2_BOSS; defaults->flags3 |= MF3_NORADIUSDMG; }}, // full volume see / death sound + splash immunity {"MAP07BOSS1", [](AActor* defaults) { defaults->flags8 |= MF8_MAP07BOSS1; }}, // Tag 666 "boss" on doom 2 map 7 {"MAP07BOSS2", [](AActor* defaults) { defaults->flags8 |= MF8_MAP07BOSS2; }}, // Tag 667 "boss" on doom 2 map 7 {"E1M8BOSS", [](AActor* defaults) { defaults->flags8 |= MF8_E1M8BOSS; }}, // E1M8 boss @@ -1108,29 +1213,17 @@ static int PatchThing (int thingy) type = NULL; info = (AActor *)&dummy; ednum = &dummyed; - if (thingy > (int)InfoNames.Size() || thingy <= 0) + auto thingytype = FindInfoName(thingy-1); + if (thingytype == nullptr) { - Printf ("Thing %d out of range.\n", thingy); + Printf ("Thing %d out of range or invalid.\n", thingy); } else { DPrintf (DMSG_SPAMMY, "Thing %d\n", thingy); - if (thingy > 0) - { - type = InfoNames[thingy - 1]; - if (type == NULL) - { - info = (AActor *)&dummy; - ednum = &dummyed; - // An error for the name has already been printed while loading DEHSUPP. - Printf ("Could not find thing %d\n", thingy); - } - else - { - info = GetDefaultByType (type); - ednum = &type->ActorInfo()->DoomEdNum; - } - } + type = thingytype; + info = GetDefaultByType (type); + ednum = &type->ActorInfo()->DoomEdNum; } oldflags = info->flags; @@ -1264,13 +1357,13 @@ static int PatchThing (int thingy) } else if (linelen == 12 && stricmp(Line1, "dropped item") == 0) { - val--; // This is 1-based and 0 means 'no drop'. - if ((unsigned)val < InfoNames.Size()) + auto drop = FindInfoName(val - 1); + if (drop) { FDropItem* di = (FDropItem*)ClassDataAllocator.Alloc(sizeof(FDropItem)); di->Next = nullptr; - di->Name = InfoNames[val]->TypeName.GetChars(); + di->Name = drop->TypeName; di->Probability = 255; di->Amount = -1; info->GetInfo()->DropItems = di; @@ -1297,7 +1390,7 @@ static int PatchThing (int thingy) if (val > 8 || val < 0) val = 0; unsigned color = bloodcolor[val]; info->BloodColor = color; - info->BloodTranslation = val == 0? 0 : TRANSLATION(TRANSLATION_Blood, CreateBloodTranslation(color)); + info->BloodTranslation = val == 0? NO_TRANSLATION : CreateBloodTranslation(color); } else if (linelen == 10 && stricmp(Line1, "MBF21 Bits") == 0) { @@ -1310,7 +1403,7 @@ static int PatchThing (int thingy) { if (IsNum(strval)) { - value |= (unsigned long)strtoll(strval, NULL, 10); + value |= (uint32_t)strtoll(strval, NULL, 10); vchanged = true; } else @@ -1386,9 +1479,9 @@ static int PatchThing (int thingy) } else if (stricmp (Line1 + linelen - 6, " sound") == 0) { - FSoundID snd = NO_SOUND; + FSoundID snd = DehFindSound(val - 1, false); - if (val == 0 || val >= SoundMap.Size()) + if (snd == NO_SOUND) // This won't trigger for dsdhacked patches! { if (endptr == Line2) { // Sound was not a (valid) number, @@ -1397,10 +1490,6 @@ static int PatchThing (int thingy) snd = S_FindSound(Line2); } } - else - { - snd = SoundMap[val-1]; - } if (!strnicmp (Line1, "Alert", 5)) info->SeeSound = snd; @@ -1440,7 +1529,7 @@ static int PatchThing (int thingy) { if (IsNum (strval)) { - value[0] |= (unsigned long)strtoll(strval, NULL, 10); + value[0] |= (uint32_t)strtoll(strval, NULL, 10); vchanged[0] = true; } else @@ -1541,6 +1630,11 @@ static int PatchThing (int thingy) value[0] &= ~MF_TRANSLUCENT; // clean the slot vchanged[2] = true; value[2] |= 2; // let the TRANSLUCxx code below handle it } + if (value[0] & MF_MISSILE) + { + // all missiles in Doom are NOTELEPORT, the other flags are for consistency. + info->flags2 |= MF2_IMPACT | MF2_PCROSS | MF2_NOTELEPORT; + } if ((info->flags & MF_MISSILE) && (info->flags2 & MF2_NOTELEPORT) && !(value[0] & MF_MISSILE)) { @@ -1746,7 +1840,7 @@ static int PatchFrame (int frameNum) int tics, misc1, frame; FState *info, dummy; - info = FindState (frameNum); + info = FindState (frameNum, false); if (info) { DPrintf (DMSG_SPAMMY, "Frame %d\n", frameNum); @@ -1792,28 +1886,7 @@ static int PatchFrame (int frameNum) } else if (keylen == 13 && stricmp (Line1, "Sprite number") == 0) { - unsigned int i; - - if (val < (int)OrgSprNames.Size()) - { - for (i = 0; i < sprites.Size(); i++) - { - if (memcmp (OrgSprNames[val].c, sprites[i].name, 4) == 0) - { - info->sprite = (int)i; - break; - } - } - if (i == sprites.Size ()) - { - Printf ("Frame %d: Sprite %d (%s) is undefined\n", - frameNum, val, OrgSprNames[val].c); - } - } - else - { - Printf ("Frame %d: Sprite %d out of range\n", frameNum, val); - } + stateSprites.Insert(info, val); } else if (keylen == 10 && stricmp (Line1, "Next frame") == 0) { @@ -1848,7 +1921,7 @@ static int PatchFrame (int frameNum) { if (IsNum(strval)) { - value |= (unsigned long)strtoll(strval, NULL, 10); + value |= (uint32_t)strtoll(strval, NULL, 10); vchanged = true; } else @@ -1915,7 +1988,7 @@ static int PatchSprite (int sprNum) int result; int offset = 0; - if ((unsigned)sprNum < OrgSprNames.Size()) + if ((unsigned)sprNum < OrgSprOrgSize) { DPrintf (DMSG_SPAMMY, "Sprite %d\n", sprNum); } @@ -1932,12 +2005,12 @@ static int PatchSprite (int sprNum) else Printf (unknown_str, Line1, "Sprite", sprNum); } - if (offset > 0 && sprNum != -1) + if (offset > 0 && sprNum != -1 && !dsdhacked) { // Calculate offset from beginning of sprite names. offset = (offset - toff[dversion] - 22044) / 8; - if ((unsigned)offset < OrgSprNames.Size()) + if ((unsigned)offset < OrgSprOrgSize) { sprNum = FindSprite (OrgSprNames[sprNum].c); if (sprNum != -1) @@ -2153,7 +2226,7 @@ static int PatchWeapon (int weapNum) { if (IsNum(strval)) { - value |= (unsigned long)strtoll(strval, NULL, 10); + value |= (uint32_t)strtoll(strval, NULL, 10); vchanged = true; } else @@ -2288,7 +2361,7 @@ static int PatchPointer (int ptrNum) { if ((unsigned)ptrNum < CodePConv.Size() && (!stricmp (Line1, "Codep Frame"))) { - FState *state = FindState (CodePConv[ptrNum]); + FState *state = FindState (CodePConv[ptrNum], true); if (state) { int index = atoi(Line2); @@ -2472,7 +2545,7 @@ static int PatchMisc (int dummy) auto health = GetDefaultByName ("HealthBonus"); if (health!=NULL) { - health->IntVar(NAME_MaxAmount) = 2 * deh.MaxHealth; + health->IntVar(NAME_MaxAmount) = -1; // needs to be evaluated at run time due to the compat flag. } health = GetDefaultByName ("Soulsphere"); @@ -2584,6 +2657,7 @@ static int PatchPars (int dummy) return result; } + static int PatchCodePtrs (int dummy) { int result; @@ -2635,6 +2709,8 @@ static int PatchCodePtrs (int dummy) // This skips the action table and goes directly to the internal symbol table // DEH compatible functions are easy to recognize. + // Note that A_CPosAttack needs to be remapped because it differs from the original and cannot be renamed anymore. + if (!symname.CompareNoCase("A_CPosAttack")) symname = "A_CPosAttackDehacked"; PFunction *sym = dyn_cast(PClass::FindActor(NAME_Weapon)->FindSymbol(symname, true)); if (sym == NULL) { @@ -2677,6 +2753,40 @@ static int PatchMusic (int dummy) return result; } + +// This repplaces a sprite name in the current working data +static void ReplaceSpriteInData(const char* oldStr, const char* newStr) + { + if (strncmp ("PLAY", oldStr, 4) == 0) + { + strncpy (deh.PlayerSprite, newStr, 4); + } + // If this sprite is used by a pickup, then the DehackedPickup sprite map + // needs to be updated too. + for (size_t i = 0; i < countof(DehSpriteMappings); ++i) + { + if (strncmp (DehSpriteMappings[i].Sprite, oldStr, 4) == 0) + { + // Found a match, so change it. + strncpy (DehSpriteMappings[i].Sprite, newStr, 4); + + // Now shift the map's entries around so that it stays sorted. + // This must be done because the map is scanned using a binary search. + while (i > 0 && strncmp (DehSpriteMappings[i-1].Sprite, newStr, 4) > 0) + { + std::swap (DehSpriteMappings[i-1], DehSpriteMappings[i]); + --i; + } + while ((size_t)i < countof(DehSpriteMappings)-1 && + strncmp (DehSpriteMappings[i+1].Sprite, newStr, 4) < 0) + { + std::swap (DehSpriteMappings[i+1], DehSpriteMappings[i]); + ++i; + } + break; + } + } + } static int PatchText (int oldSize) { @@ -2734,42 +2844,14 @@ static int PatchText (int oldSize) if (i != -1) { strncpy (sprites[i].name, newStr, 4); - if (strncmp ("PLAY", oldStr, 4) == 0) - { - strncpy (deh.PlayerSprite, newStr, 4); - } - for (unsigned ii = 0; ii < OrgSprNames.Size(); ii++) + for (unsigned ii = 0; ii < OrgSprOrgSize; ii++) { if (!stricmp(OrgSprNames[ii].c, oldStr)) { strcpy(OrgSprNames[ii].c, newStr); } } - // If this sprite is used by a pickup, then the DehackedPickup sprite map - // needs to be updated too. - for (i = 0; (size_t)i < countof(DehSpriteMappings); ++i) - { - if (strncmp (DehSpriteMappings[i].Sprite, oldStr, 4) == 0) - { - // Found a match, so change it. - strncpy (DehSpriteMappings[i].Sprite, newStr, 4); - - // Now shift the map's entries around so that it stays sorted. - // This must be done because the map is scanned using a binary search. - while (i > 0 && strncmp (DehSpriteMappings[i-1].Sprite, newStr, 4) > 0) - { - std::swap (DehSpriteMappings[i-1], DehSpriteMappings[i]); - --i; - } - while ((size_t)i < countof(DehSpriteMappings)-1 && - strncmp (DehSpriteMappings[i+1].Sprite, newStr, 4) < 0) - { - std::swap (DehSpriteMappings[i+1], DehSpriteMappings[i]); - ++i; - } - break; - } - } + ReplaceSpriteInData(oldStr, newStr); goto donewithtext; } } @@ -2850,6 +2932,59 @@ static int PatchStrings (int dummy) return result; } +static int PatchSoundNames (int dummy) +{ + int result; + + DPrintf (DMSG_SPAMMY, "[Sounds]\n"); + + while ((result = GetLine()) == 1) + { + stripwhite(Line2); + FString newname = skipwhite (Line2); + ReplaceSoundName((int)strtoll(Line1, nullptr, 10), newname.GetChars()); + DPrintf (DMSG_SPAMMY, "Sound %d set to:\n%s\n", Line1, newname.GetChars()); + } + + return result; +} + +static int PatchSpriteNames (int dummy) +{ + int result; + + DPrintf (DMSG_SPAMMY, "[Sprites]\n"); + + while ((result = GetLine()) == 1) + { + stripwhite(Line2); + FString newname = skipwhite (Line2); + if (newname.Len() != 4) + { + Printf("Sprite name must be 4 characters long, got '%s'\n", newname.GetChars()); + continue; + } + int64_t line1val = strtoll(Line1, nullptr, 10); + if (line1val >= OrgSprNames.Size()) + { + unsigned osize = OrgSprNames.Size(); + OrgSprNames.Resize(line1val + 1); + DEHSprName nulname{}; + for (unsigned o = osize; o < OrgSprNames.Size(); o++) + { + OrgSprNames[o] = nulname; + } + } + int v = GetSpriteIndex(newname.GetChars()); + memcpy(OrgSprNames[line1val].c, sprites[v].name, 5); + + DPrintf (DMSG_SPAMMY, "Sprite %d set to:\n%s\n", Line1, newname.GetChars()); + } + + return result; + } + + static int DoInclude (int dummy) { char *data; @@ -2896,15 +3031,15 @@ static int DoInclude (int dummy) // Try looking for the included file in the same directory // as the patch before looking in the current file. - const char *lastSlash = strrchr(savepatchname, '/'); + const char *lastSlash = strrchr(savepatchname.GetChars(), '/'); char *path = data; if (lastSlash != NULL) { - size_t pathlen = lastSlash - savepatchname + strlen (data) + 2; + size_t pathlen = lastSlash - savepatchname.GetChars() + strlen (data) + 2; path = new char[pathlen]; - strncpy (path, savepatchname, (lastSlash - savepatchname) + 1); - strcpy (path + (lastSlash - savepatchname) + 1, data); + strncpy (path, savepatchname.GetChars(), (lastSlash - savepatchname.GetChars()) + 1); + strcpy (path + (lastSlash - savepatchname.GetChars()) + 1, data); if (!FileExists (path)) { delete[] path; @@ -3004,7 +3139,7 @@ bool D_LoadDehLump(int lumpnum) PatchSize = fileSystem.FileLength(lumpnum); - PatchName = fileSystem.GetFileFullPath(lumpnum); + PatchName = fileSystem.GetFileFullPath(lumpnum).c_str(); PatchFile = new char[PatchSize + 1]; fileSystem.ReadFile(lumpnum, PatchFile); PatchFile[PatchSize] = '\0'; // terminate with a '\0' character @@ -3039,7 +3174,7 @@ bool D_LoadDehFile(const char *patchfile) // some WAD may need it. Should be deleted if it can // be confirmed that nothing uses this case. FString filebase(ExtractFileBase(patchfile)); - lumpnum = fileSystem.CheckNumForName(filebase); + lumpnum = fileSystem.CheckNumForName(filebase.GetChars()); } if (lumpnum >= 0) { @@ -3112,13 +3247,18 @@ static bool DoDehPatch() dversion = 1; else if (dversion == 21) dversion = 4; + else if (dversion == 2021) + { + dversion = 4; + dsdhacked = true; + } else { Printf ("Patch created with unknown DOOM version.\nAssuming version 1.9.\n"); dversion = 3; } - if (!LoadDehSupp ()) + if (StateMap.Size() == 0 && !LoadDehSupp ()) // only load this once. { Printf ("Could not load DEH support data\n"); UnloadDehSupp (); @@ -3140,7 +3280,6 @@ static bool DoDehPatch() } } while (cont); - UnloadDehSupp (); PatchName = ""; delete[] PatchFile; if (!batchrun) Printf ("Patch installed\n"); @@ -3152,44 +3291,34 @@ static inline bool CompareLabel (const char *want, const uint8_t *have) return *(uint32_t *)want == *(uint32_t *)have; } -static int DehUseCount; - static void UnloadDehSupp () { - if (--DehUseCount <= 0) - { - VMDisassemblyDumper disasmdump(VMDisassemblyDumper::Append); + VMDisassemblyDumper disasmdump(VMDisassemblyDumper::Append); - // Handle MBF params here, before the required arrays are cleared - for (unsigned int i=0; i < MBFParamStates.Size(); i++) - { - SetDehParams(MBFParamStates[i].state, MBFParamStates[i].pointer, disasmdump, &MBFParamStates[i]); - } - stateargs.Clear(); - MBFParamStates.Clear(); - MBFParamStates.ShrinkToFit(); - MBFCodePointers.Clear(); - MBFCodePointers.ShrinkToFit(); - // StateMap is not freed here, because if you load a second - // dehacked patch through some means other than including it - // in the first patch, it won't see the state information - // that was altered by the first. So we need to keep the - // StateMap around until all patches have been applied. - DehUseCount = 0; - Actions.Reset(); - OrgHeights.Reset(); - CodePConv.Reset(); - OrgSprNames.Reset(); - SoundMap.Reset(); - InfoNames.Reset(); - BitNames.Reset(); - StyleNames.Reset(); - AmmoNames.Reset(); - UnchangedSpriteNames.Reset(); + // Handle MBF params here, before the required arrays are cleared + for (unsigned int i=0; i < MBFParamStates.Size(); i++) + { + SetDehParams(MBFParamStates[i].state, MBFParamStates[i].pointer, disasmdump, &MBFParamStates[i]); } + stateargs.Clear(); + MBFParamStates.Clear(); + MBFParamStates.ShrinkToFit(); + MBFCodePointers.Clear(); + MBFCodePointers.ShrinkToFit(); + OrgSprNames.Reset(); + StateMap.Reset(); + Actions.Reset(); + OrgHeights.Reset(); + CodePConv.Reset(); + SoundMap.Reset(); + InfoNames.Reset(); + BitNames.Reset(); + StyleNames.Reset(); + AmmoNames.Reset(); + UnchangedSpriteNames.Reset(); } -static bool LoadDehSupp () +bool LoadDehSupp () { try { @@ -3209,12 +3338,6 @@ static bool LoadDehSupp () } bool gotnames = false; - - if (++DehUseCount > 1) - { - return true; - } - if (EnglishStrings.CountUsed() == 0) EnglishStrings = GStrings.GetDefaultStrings(); @@ -3247,7 +3370,8 @@ static bool LoadDehSupp () // all relevant code pointers are either defined in Weapon // or Actor so this will find all of them. FString name = "A_"; - name << sc.String; + if (sc.Compare("CPosAttack")) name << "CPosAttackDehacked"; + else name << sc.String; PFunction *sym = dyn_cast(wcls->FindSymbol(name, true)); if (sym == NULL) { @@ -3292,6 +3416,7 @@ static bool LoadDehSupp () } else if (sc.Compare("OrgSprNames")) { + bool addit = OrgSprNames.Size() == 0; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { @@ -3311,14 +3436,16 @@ static bool LoadDehSupp () { sc.ScriptError("Invalid sprite name '%s' (must be 4 characters)", sc.String); } - OrgSprNames.Push(s); + if (addit) OrgSprNames.Push(s); if (sc.CheckString("}")) break; sc.MustGetStringName(","); } + OrgSprOrgSize = OrgSprNames.Size(); } else if (sc.Compare("StateMap")) { bool addit = StateMap.Size() == 0; + int dehcount = 0; sc.MustGetStringName("{"); while (!sc.CheckString("}")) @@ -3360,6 +3487,14 @@ static bool LoadDehSupp () if (sc.CheckString("}")) break; sc.MustGetStringName(","); + // This mapping is mainly for P_SetSafeFlash. + for (int i = 0; i < s.StateSpan; i++) + { + assert(FState::StaticFindStateOwner(s.State + i)); + dehExtStates.Insert(dehcount, s.State + i); + s.State[i].DehIndex = dehcount; + dehcount++; + } } } else if (sc.Compare("SoundMap")) @@ -3519,7 +3654,8 @@ void FinishDehPatch () { GetDefaultByType(cls)->flags8 |= MF8_RETARGETAFTERSLAM; } - + RemapAllSprites(); + for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex) { PClassActor *subclass; @@ -3565,8 +3701,10 @@ void FinishDehPatch () type->ActorInfo()->Replacement = subclass; subclass->ActorInfo()->Replacee = type; + subclass->ActorInfo()->LightAssociations = type->ActorInfo()->LightAssociations; // If this actor was already replaced by another actor, copy that // replacement over to this item. + if (old_replacement != NULL) { subclass->ActorInfo()->Replacement = old_replacement; @@ -3586,11 +3724,11 @@ void FinishDehPatch () } } } - // Now that all Dehacked patches have been processed, it's okay to free StateMap. - StateMap.Reset(); + UnloadDehSupp(); TouchedActors.Reset(); EnglishStrings.Clear(); - GStrings.SetOverrideStrings(std::move(DehStrings)); + GStrings.SetOverrideStrings(DehStrings); + DehStrings.Clear(); // Now it gets nasty: We have to fiddle around with the weapons' ammo use info to make Doom's original // ammo consumption work as intended. @@ -3751,6 +3889,18 @@ void ClearCountkill(AActor* a) if (a->CountsAsKill() && a->health > 0) a->Level->total_monsters++; } +void SetBoss(AActor* a) +{ + a->flags2 |= MF2_BOSS; + a->flags3 |= MF3_NORADIUSDMG; +} + +void ClearBoss(AActor* a) +{ + a->flags2 &= ~MF2_BOSS; + a->flags3 &= ~MF3_NORADIUSDMG; +} + void SetCountitem(AActor* a) { if (!(a->flags & MF_COUNTITEM)) @@ -3816,10 +3966,9 @@ bool CheckTranslucent(AActor* a) return !(a->renderflags & RF_ZDOOMTRANS) && a->Alpha < 1 - FLT_EPSILON; } -constexpr int t0 = 0; -constexpr int t1 = TRANSLATION(TRANSLATION_Standard, 0); -constexpr int t2 = TRANSLATION(TRANSLATION_Standard, 1); -constexpr int t3 = TRANSLATION(TRANSLATION_Standard, 2); +constexpr FTranslationID t1 = TRANSLATION(TRANSLATION_Standard, 0); +constexpr FTranslationID t2 = TRANSLATION(TRANSLATION_Standard, 1); +constexpr FTranslationID t3 = TRANSLATION(TRANSLATION_Standard, 2); void SetTranslation1(AActor* a) { @@ -3830,7 +3979,7 @@ void SetTranslation1(AActor* a) void ClearTranslation1(AActor* a) { if (a->Translation == t3 || a->Translation == t2) a->Translation = t2; - else a->Translation = t0; + else a->Translation = NO_TRANSLATION; } bool CheckTranslation1(AActor* a) @@ -3847,7 +3996,7 @@ void SetTranslation2(AActor* a) void ClearTranslation2(AActor* a) { if (a->Translation == t3 || a->Translation == t1) a->Translation = t1; - else a->Translation = t0; + else a->Translation = NO_TRANSLATION; } bool CheckTranslation2(AActor* a) @@ -3880,12 +4029,14 @@ void ClearBounces(AActor* info) void SetMissile(AActor* info) { info->flags |= MF_MISSILE; + info->flags2 |= MF2_NOTELEPORT | MF2_PCROSS | MF2_IMPACT; if (info->BounceFlags & BOUNCE_DEH) info->BounceFlags = BOUNCE_Classic | BOUNCE_DEH; } void ClearMissile(AActor* info) { info->flags &= ~MF_MISSILE; + info->flags2 &= ~(MF2_NOTELEPORT | MF2_PCROSS | MF2_IMPACT); if (info->BounceFlags & BOUNCE_DEH) info->BounceFlags = BOUNCE_Grenade | BOUNCE_DEH; } @@ -3948,7 +4099,7 @@ static FlagHandler flag2handlers[32] = { F4(MF4_MISSILEMORE), F4(MF4_QUICKTORETALIATE), DEPF(DEPF_LONGMELEERANGE), - F2(MF2_BOSS), + { SetBoss, ClearBoss, [](AActor* a)->bool { return a->flags2 & MF2_BOSS; } }, F8(MF8_MAP07BOSS1), F8(MF8_MAP07BOSS2), F8(MF8_E1M8BOSS), diff --git a/src/gamedata/decallib.cpp b/src/gamedata/decallib.cpp index e765959b8f..8dee4e7fd4 100644 --- a/src/gamedata/decallib.cpp +++ b/src/gamedata/decallib.cpp @@ -92,7 +92,7 @@ struct FDecalLib::FTranslation uint32_t StartColor, EndColor; FTranslation *Next; - uint32_t Index; + FTranslationID Index; }; struct FDecalAnimator @@ -342,7 +342,7 @@ uint16_t FDecalLib::GetDecalID (FScanner &sc) } else { - unsigned long num = strtoul (sc.String, NULL, 10); + uint64_t num = strtoull (sc.String, NULL, 10); if (num < 1 || num > 65535) { sc.ScriptError ("Decal ID must be between 1 and 65535"); @@ -376,7 +376,7 @@ void FDecalLib::ParseDecal (FScanner &sc) sc.MustGetString (); if (sc.Compare ("}")) { - AddDecal (decalName, decalNum, newdecal); + AddDecal(decalName.GetChars(), decalNum, newdecal); break; } switch (sc.MustMatchString (DecalKeywords)) @@ -392,7 +392,7 @@ void FDecalLib::ParseDecal (FScanner &sc) case DECAL_PIC: sc.MustGetString (); picnum = TexMan.CheckForTexture (sc.String, ETextureType::Any); - if (!picnum.Exists() && (lumpnum = fileSystem.CheckNumForName (sc.String, ns_graphics)) >= 0) + if (!picnum.Exists() && (lumpnum = fileSystem.CheckNumForName (sc.String, FileSys::ns_graphics)) >= 0) { picnum = TexMan.CreateTexture (lumpnum, ETextureType::Decal); } @@ -577,7 +577,7 @@ void FDecalLib::ParseFader (FScanner &sc) sc.MustGetString (); if (sc.Compare ("}")) { - FDecalFaderAnim *fader = new FDecalFaderAnim (faderName); + FDecalFaderAnim *fader = new FDecalFaderAnim (faderName.GetChars()); fader->DecayStart = startTime; fader->DecayTime = decayTime; Animators.Push (fader); @@ -617,7 +617,7 @@ void FDecalLib::ParseStretcher (FScanner &sc) { if (goalX >= 0 || goalY >= 0) { - FDecalStretcherAnim *stretcher = new FDecalStretcherAnim (stretcherName); + FDecalStretcherAnim *stretcher = new FDecalStretcherAnim (stretcherName.GetChars()); stretcher->StretchStart = startTime; stretcher->StretchTime = takeTime; stretcher->GoalX = goalX; @@ -668,7 +668,7 @@ void FDecalLib::ParseSlider (FScanner &sc) { if ((/*distX |*/ distY) != 0) { - FDecalSliderAnim *slider = new FDecalSliderAnim (sliderName); + FDecalSliderAnim *slider = new FDecalSliderAnim (sliderName.GetChars()); slider->SlideStart = startTime; slider->SlideTime = takeTime; /*slider->DistX = distX;*/ @@ -719,7 +719,7 @@ void FDecalLib::ParseColorchanger (FScanner &sc) sc.MustGetString (); if (sc.Compare ("}")) { - FDecalColorerAnim *fader = new FDecalColorerAnim (faderName); + FDecalColorerAnim *fader = new FDecalColorerAnim (faderName.GetChars()); fader->DecayStart = startTime; fader->DecayTime = decayTime; fader->GoalColor = goal; @@ -772,7 +772,7 @@ void FDecalLib::ParseCombiner (FScanner &sc) if (last > first) { - FDecalCombinerAnim *combiner = new FDecalCombinerAnim (combinerName); + FDecalCombinerAnim *combiner = new FDecalCombinerAnim (combinerName.GetChars()); combiner->FirstAnimator = (int)first; combiner->NumAnimators = (int)(last - first); Animators.Push (combiner); @@ -1002,7 +1002,7 @@ FDecalLib::FTranslation::FTranslation (uint32_t start, uint32_t end) if (DecalTranslations.Size() == 256*256) { Printf ("Too many decal translations defined\n"); - Index = 0; + Index = NO_TRANSLATION; return; } @@ -1028,7 +1028,7 @@ FDecalLib::FTranslation::FTranslation (uint32_t start, uint32_t end) table[i] = ColorMatcher.Pick (ri >> 24, gi >> 24, bi >> 24); } table[0] = table[1]; - Index = (uint32_t)TRANSLATION(TRANSLATION_Decals, tablei >> 8); + Index = TRANSLATION(TRANSLATION_Decals, tablei >> 8); } FDecalLib::FTranslation *FDecalLib::FTranslation::LocateTranslation (uint32_t start, uint32_t end) diff --git a/src/gamedata/decallib.h b/src/gamedata/decallib.h index 3a6ede299a..d077c6c460 100644 --- a/src/gamedata/decallib.h +++ b/src/gamedata/decallib.h @@ -38,6 +38,7 @@ #include "doomtype.h" #include "renderstyle.h" +#include "palettecontainer.h" class FScanner; class FDecalTemplate; @@ -67,7 +68,7 @@ class FDecalTemplate : public FDecalBase { friend class FDecalLib; public: - FDecalTemplate () : Translation (0) {} + FDecalTemplate () : Translation (NO_TRANSLATION) {} void ApplyToDecal (DBaseDecal *actor, side_t *wall) const; const FDecalTemplate *GetDecal () const; @@ -75,7 +76,7 @@ class FDecalTemplate : public FDecalBase double ScaleX, ScaleY; uint32_t ShadeColor; - uint32_t Translation; + FTranslationID Translation; FRenderStyle RenderStyle; FTextureID PicNum; uint16_t RenderFlags; diff --git a/src/gamedata/doomfont.h b/src/gamedata/doomfont.h index 9b44a480f3..fedeb513c4 100644 --- a/src/gamedata/doomfont.h +++ b/src/gamedata/doomfont.h @@ -1,6 +1,7 @@ // // Globally visible constants. // +#pragma once #define HU_FONTSTART uint8_t('!') // the first font characters #define HU_FONTEND uint8_t('\377') // the last font characters @@ -17,7 +18,7 @@ void InitDoomFonts() if (fileSystem.CheckNumForName("FONTA_S") >= 0) { int wadfile = -1; - auto a = fileSystem.CheckNumForName("FONTA33", ns_graphics); + auto a = fileSystem.CheckNumForName("FONTA33", FileSys::ns_graphics); if (a != -1) wadfile = fileSystem.GetFileContainer(a); if (wadfile > fileSystem.GetIwadNum()) { @@ -31,10 +32,10 @@ void InitDoomFonts() SmallFont->SetCursor('['); } } - else if (fileSystem.CheckNumForName("STCFN033", ns_graphics) >= 0) + else if (fileSystem.CheckNumForName("STCFN033", FileSys::ns_graphics) >= 0) { int wadfile = -1; - auto a = fileSystem.CheckNumForName("STCFN065", ns_graphics); + auto a = fileSystem.CheckNumForName("STCFN065", FileSys::ns_graphics); if (a != -1) wadfile = fileSystem.GetFileContainer(a); if (wadfile > fileSystem.GetIwadNum()) { @@ -54,7 +55,7 @@ void InitDoomFonts() OriginalSmallFont = new FFont("OriginalSmallFont", "FONTA%02u", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, 1, -1, -1, false, true); OriginalSmallFont->SetCursor('['); } - else if (fileSystem.CheckNumForName("STCFN033", ns_graphics) >= 0) + else if (fileSystem.CheckNumForName("STCFN033", FileSys::ns_graphics) >= 0) { OriginalSmallFont = new FFont("OriginalSmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, true, true); } @@ -62,7 +63,7 @@ void InitDoomFonts() if (!(SmallFont2 = V_GetFont("SmallFont2"))) // Only used by Strife { - if (fileSystem.CheckNumForName("STBFN033", ns_graphics) >= 0) + if (fileSystem.CheckNumForName("STBFN033", FileSys::ns_graphics) >= 0) { SmallFont2 = new FFont("SmallFont2", "STBFN%.3d", "defsmallfont2", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1); } diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index 59f37bc52b..aedcd103ef 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -250,10 +250,13 @@ void level_info_t::Reset() else flags2 = LEVEL2_LAXMONSTERACTIVATION; flags3 = 0; + vkdflags = 0; + LightningSound = "world/thunder"; Music = ""; LevelName = ""; AuthorName = ""; FadeTable = "COLORMAP"; + CustomColorMap = "COLORMAP"; WallHorizLight = -8; WallVertLight = +8; F1Pic = ""; @@ -321,10 +324,10 @@ FString level_info_t::LookupLevelName(uint32_t *langtable) if (flags & LEVEL_LOOKUPLEVELNAME) { const char *thename; - const char *lookedup = GStrings.GetString(LevelName, langtable); + const char *lookedup = GStrings.CheckString(LevelName.GetChars(), langtable); if (lookedup == NULL) { - thename = LevelName; + thename = LevelName.GetChars(); } else { @@ -381,9 +384,9 @@ level_info_t *level_info_t::CheckLevelRedirect () if (playeringame[i] && players[i].mo->FindInventory(type)) { // check for actual presence of the map. - if (P_CheckMapData(RedirectMapName)) + if (P_CheckMapData(RedirectMapName.GetChars())) { - return FindLevelInfo(RedirectMapName); + return FindLevelInfo(RedirectMapName.GetChars()); } break; } @@ -403,14 +406,14 @@ level_info_t *level_info_t::CheckLevelRedirect () if (playeringame[i] && (var = GetCVar(i, RedirectCVAR.GetChars()))) { if (var->ToInt()) - if (P_CheckMapData(RedirectCVARMapName)) - return FindLevelInfo(RedirectCVARMapName); + if (P_CheckMapData(RedirectCVARMapName.GetChars())) + return FindLevelInfo(RedirectCVARMapName.GetChars()); } } } else if (var->ToInt()) - if (P_CheckMapData(RedirectCVARMapName)) - return FindLevelInfo(RedirectCVARMapName); + if (P_CheckMapData(RedirectCVARMapName.GetChars())) + return FindLevelInfo(RedirectCVARMapName.GetChars()); } } return NULL; @@ -830,7 +833,7 @@ void FMapInfoParser::ParseCluster() else { FStringf testlabel("CLUSTERENTER%d", clusterinfo->cluster); - if (GStrings.MatchDefaultString(testlabel, clusterinfo->EnterText)) + if (GStrings.MatchDefaultString(testlabel.GetChars(), clusterinfo->EnterText.GetChars())) { clusterinfo->EnterText = testlabel; clusterinfo->flags |= CLUSTER_LOOKUPENTERTEXT; @@ -845,7 +848,7 @@ void FMapInfoParser::ParseCluster() else { FStringf testlabel("CLUSTEREXIT%d", clusterinfo->cluster); - if (GStrings.MatchDefaultString(testlabel, clusterinfo->ExitText)) + if (GStrings.MatchDefaultString(testlabel.GetChars(), clusterinfo->ExitText.GetChars())) { clusterinfo->ExitText = testlabel; clusterinfo->flags |= CLUSTER_LOOKUPEXITTEXT; @@ -922,7 +925,7 @@ void FMapInfoParser::ParseCluster() // Remap Hexen's CLUS?MSG lumps to the string table, if applicable. The code here only checks what can actually be in an IWAD. if (clusterinfo->flags & CLUSTER_EXITTEXTINLUMP) { - int lump = fileSystem.CheckNumForFullName(clusterinfo->ExitText, true); + int lump = fileSystem.CheckNumForFullName(clusterinfo->ExitText.GetChars(), true); if (lump > 0) { // Check if this comes from either Hexen.wad or Hexdd.wad and if so, map to the string table. @@ -931,7 +934,7 @@ void FMapInfoParser::ParseCluster() if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, clusterinfo->ExitText.GetChars()); - if (GStrings.exists(key)) + if (GStrings.exists(key.GetChars())) { clusterinfo->ExitText = key; clusterinfo->flags &= ~CLUSTER_EXITTEXTINLUMP; @@ -996,6 +999,13 @@ DEFINE_MAP_OPTION(next, true) parse.ParseNextMap(info->NextMap); } +DEFINE_MAP_OPTION(lightningsound, true) +{ + parse.ParseAssign(); + parse.sc.MustGetString(); + info->LightningSound = parse.sc.String; +} + DEFINE_MAP_OPTION(author, true) { parse.ParseAssign(); @@ -1154,6 +1164,12 @@ DEFINE_MAP_OPTION(fadetable, true) parse.ParseLumpOrTextureName(info->FadeTable); } +DEFINE_MAP_OPTION(colormap, true) +{ + parse.ParseAssign(); + parse.ParseLumpOrTextureName(info->CustomColorMap); +} + DEFINE_MAP_OPTION(evenlighting, true) { info->WallVertLight = info->WallHorizLight = 0; @@ -1201,6 +1217,11 @@ DEFINE_MAP_OPTION(gravity, true) info->gravity = parse.sc.Float; } +DEFINE_MAP_OPTION(nogravity, true) +{ + info->gravity = DBL_MAX; +} + DEFINE_MAP_OPTION(aircontrol, true) { parse.ParseAssign(); @@ -1521,7 +1542,8 @@ DEFINE_MAP_OPTION(lightmode, false) parse.ParseAssign(); parse.sc.MustGetNumber(); - if ((parse.sc.Number >= 0 && parse.sc.Number <= 4) || parse.sc.Number == 8 || parse.sc.Number == 16) + if (parse.sc.Number == 8 || parse.sc.Number == 16) info->lightmode = ELightMode::NotSet; + else if (parse.sc.Number >= 0 && parse.sc.Number <= 5) { info->lightmode = ELightMode(parse.sc.Number); } @@ -1693,10 +1715,11 @@ enum EMIType MITYPE_SETFLAG3, MITYPE_CLRFLAG3, MITYPE_SCFLAGS3, - MITYPE_SETFLAG9, - MITYPE_CLRFLAG9, - MITYPE_SCFLAGS9, + MITYPE_SETVKDFLAG, + MITYPE_CLRVKDFLAG, + MITYPE_SCVKDFLAGS, MITYPE_COMPATFLAG, + MITYPE_CLRCOMPATFLAG, }; struct MapInfoFlagHandler @@ -1793,8 +1816,6 @@ MapFlagHandlers[] = { "nolightfade", MITYPE_SETFLAG3, LEVEL3_NOLIGHTFADE, 0 }, { "nocoloredspritelighting", MITYPE_SETFLAG3, LEVEL3_NOCOLOREDSPRITELIGHTING, 0 }, { "forceworldpanning", MITYPE_SETFLAG3, LEVEL3_FORCEWORLDPANNING, 0 }, - { "nousersave", MITYPE_SETFLAG9, LEVEL9_NOUSERSAVE, 0 }, - { "noautomap", MITYPE_SETFLAG9, LEVEL9_NOAUTOMAP, 0 }, { "propermonsterfallingdamage", MITYPE_SETFLAG3, LEVEL3_PROPERMONSTERFALLINGDAMAGE, 0 }, { "disableshadowmap", MITYPE_SETFLAG3, LEVEL3_NOSHADOWMAP, 0 }, { "enableshadowmap", MITYPE_CLRFLAG3, LEVEL3_NOSHADOWMAP, 0 }, @@ -1802,7 +1823,12 @@ MapFlagHandlers[] = { "disableskyboxao", MITYPE_CLRFLAG3, LEVEL3_SKYBOXAO, 0 }, { "avoidmelee", MITYPE_SETFLAG3, LEVEL3_AVOIDMELEE, 0 }, { "attenuatelights", MITYPE_SETFLAG3, LEVEL3_ATTENUATE, 0 }, + { "nousersave", MITYPE_SETVKDFLAG, VKDLEVELFLAG_NOUSERSAVE, 0 }, + { "noautomap", MITYPE_SETVKDFLAG, VKDLEVELFLAG_NOAUTOMAP, 0 }, + { "noautosaveonenter", MITYPE_SETVKDFLAG, VKDLEVELFLAG_NOAUTOSAVEONENTER, 0 }, { "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes + { "nopassover", MITYPE_COMPATFLAG, COMPATF_NO_PASSMOBJ, 0 }, + { "passover", MITYPE_CLRCOMPATFLAG, COMPATF_NO_PASSMOBJ, 0 }, { "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX, 0 }, { "compat_stairs", MITYPE_COMPATFLAG, COMPATF_STAIRINDEX, 0 }, { "compat_limitpain", MITYPE_COMPATFLAG, COMPATF_LIMITPAIN, 0 }, @@ -1954,27 +1980,34 @@ void FMapInfoParser::ParseMapDefinition(level_info_t &info) info.flags3 = (info.flags3 & handler->data2) | handler->data1; break; - case MITYPE_SETFLAG9: + case MITYPE_SETVKDFLAG: if (!CheckAssign()) { - info.flags9 |= handler->data1; + info.vkdflags |= handler->data1; } else { sc.MustGetNumber(); - if (sc.Number) info.flags9 |= handler->data1; - else info.flags9 &= ~handler->data1; + if (sc.Number) info.vkdflags |= handler->data1; + else info.vkdflags &= ~handler->data1; } - info.flags9 |= handler->data2; + info.vkdflags |= handler->data2; + break; + + case MITYPE_CLRVKDFLAG: + info.vkdflags &= ~handler->data1; + info.vkdflags |= handler->data2; break; - case MITYPE_CLRFLAG9: - info.flags9 &= ~handler->data1; - info.flags9 |= handler->data2; + case MITYPE_SCVKDFLAGS: + info.vkdflags = (info.vkdflags & handler->data2) | handler->data1; break; - case MITYPE_SCFLAGS9: - info.flags9 = (info.flags9 & handler->data2) | handler->data1; + case MITYPE_CLRCOMPATFLAG: + info.compatflags &= ~handler->data1; + info.compatflags2 &= ~handler->data2; + info.compatmask |= handler->data1; + info.compatmask2 |= handler->data2; break; case MITYPE_COMPATFLAG: @@ -2161,7 +2194,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) // This checks for a string labelled with the MapName and if that is identical to what got parsed here // the string table entry will be used. - if (GStrings.MatchDefaultString(levelinfo->MapName, sc.String)) + if (GStrings.MatchDefaultString(levelinfo->MapName.GetChars(), sc.String)) { levelinfo->flags |= LEVEL_LOOKUPLEVELNAME; levelinfo->LevelName = levelinfo->MapName; @@ -2178,7 +2211,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, levelinfo->MapName.GetChars()); - if (GStrings.exists(key)) + if (GStrings.exists(key.GetChars())) { levelinfo->flags |= LEVEL_LOOKUPLEVELNAME; levelinfo->LevelName = key; @@ -2191,7 +2224,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) // Set up levelnum now so that you can use Teleport_NewMap specials // to teleport to maps with standard names without needing a levelnum. - levelinfo->levelnum = GetDefaultLevelNum(levelinfo->MapName); + levelinfo->levelnum = GetDefaultLevelNum(levelinfo->MapName.GetChars()); // Does this map have a song defined via SNDINFO's $map command? // Set that as this map's default music if it does. @@ -2312,7 +2345,7 @@ void FMapInfoParser::ParseEpisodeInfo () if (optional && !remove) { - if (!P_CheckMapData(map)) + if (!P_CheckMapData(map.GetChars())) { // If the episode is optional and the map does not exist // just ignore this episode definition. @@ -2597,12 +2630,62 @@ void G_ParseMapInfo (FString basemapinfo) int lump, lastlump = 0; level_info_t gamedefaults; + int flags1 = 0, flags2 = 0; + if (gameinfo.gametype == GAME_Doom) + { + int comp = fileSystem.CheckNumForName("COMPLVL"); + if (comp >= 0) + { + auto complvl = fileSystem.ReadFile(comp); + auto data = complvl.string(); + int length = fileSystem.FileLength(comp); + if (length == 7 && !strnicmp("vanilla", data, 7)) + { + flags1 = + COMPATF_SHORTTEX | COMPATF_STAIRINDEX | COMPATF_USEBLOCKING | COMPATF_NODOORLIGHT | COMPATF_SPRITESORT | + COMPATF_TRACE | COMPATF_MISSILECLIP | COMPATF_SOUNDTARGET | COMPATF_DEHHEALTH | COMPATF_CROSSDROPOFF | + COMPATF_LIGHT | COMPATF_MASKEDMIDTEX | + COMPATF_LIMITPAIN | COMPATF_INVISIBILITY | COMPATF_VILEGHOSTS; + + flags2 = + COMPATF2_FLOORMOVE | COMPATF2_EXPLODE1 | COMPATF2_NOMBF21 | COMPATF2_POINTONLINE; + } + else if (length == 4 && !strnicmp("boom", data, 4)) + { + flags1 = + COMPATF_TRACE | COMPATF_SOUNDTARGET | COMPATF_BOOMSCROLL | COMPATF_MISSILECLIP | COMPATF_MASKEDMIDTEX | + COMPATF_INVISIBILITY; + + flags2 = + COMPATF2_EXPLODE1 | COMPATF2_NOMBF21 | COMPATF2_POINTONLINE; + } + else if (length == 3 && !strnicmp("mbf", data, 3)) + { + flags1 = + COMPATF_TRACE | COMPATF_SOUNDTARGET | COMPATF_BOOMSCROLL | COMPATF_MISSILECLIP | COMPATF_MUSHROOM | + COMPATF_MBFMONSTERMOVE | COMPATF_NOBLOCKFRIENDS | COMPATF_MASKEDMIDTEX | COMPATF_INVISIBILITY; + + flags2 = + COMPATF2_EXPLODE1 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT | COMPATF2_NOMBF21 | COMPATF2_POINTONLINE; + } + else if (length == 5 && !strnicmp("mbf21", data, 5)) + { + flags1 = + COMPATF_TRACE | COMPATF_SOUNDTARGET | COMPATF_BOOMSCROLL | COMPATF_MISSILECLIP | COMPATF_MUSHROOM | + COMPATF_MASKEDMIDTEX | COMPATF_INVISIBILITY; + + flags2 = + COMPATF2_EXPLODE1 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT | COMPATF2_POINTONLINE; + } + } + } + // Parse the default MAPINFO for the current game. This lump *MUST* come from zdoom.pk3. if (basemapinfo.IsNotEmpty()) { FMapInfoParser parse; level_info_t defaultinfo; - int baselump = fileSystem.GetNumForFullName(basemapinfo); + int baselump = fileSystem.GetNumForFullName(basemapinfo.GetChars()); if (fileSystem.GetFileContainer(baselump) > 0) { I_FatalError("File %s is overriding core lump %s.", @@ -2610,7 +2693,11 @@ void G_ParseMapInfo (FString basemapinfo) } parse.ParseMapInfo(baselump, gamedefaults, defaultinfo); } - + gamedefaults.compatflags |= flags1; + gamedefaults.compatmask |= flags1; + gamedefaults.compatflags2 |= flags2; + gamedefaults.compatmask2 |= flags2; + static const char *mapinfonames[] = { "MAPINFO", "ZMAPINFO", "UMAPINFO", NULL }; int nindex; @@ -2623,7 +2710,7 @@ void G_ParseMapInfo (FString basemapinfo) // If that exists we need to skip this one. int wad = fileSystem.GetFileContainer(lump); - int altlump = fileSystem.CheckNumForName("ZMAPINFO", ns_global, wad, true); + int altlump = fileSystem.CheckNumForName("ZMAPINFO", FileSys::ns_global, wad, true); if (altlump >= 0) continue; } @@ -2631,9 +2718,9 @@ void G_ParseMapInfo (FString basemapinfo) { // MAPINFO and ZMAPINFO will override UMAPINFO if in the same WAD. int wad = fileSystem.GetFileContainer(lump); - int altlump = fileSystem.CheckNumForName("ZMAPINFO", ns_global, wad, true); + int altlump = fileSystem.CheckNumForName("ZMAPINFO", FileSys::ns_global, wad, true); if (altlump >= 0) continue; - altlump = fileSystem.CheckNumForName("MAPINFO", ns_global, wad, true); + altlump = fileSystem.CheckNumForName("MAPINFO", FileSys::ns_global, wad, true); if (altlump >= 0) continue; } if (nindex != 2) diff --git a/src/gamedata/g_mapinfo.h b/src/gamedata/g_mapinfo.h index 4a3f380e0b..17fae62552 100644 --- a/src/gamedata/g_mapinfo.h +++ b/src/gamedata/g_mapinfo.h @@ -38,7 +38,6 @@ #include "doomtype.h" #include "vectors.h" #include "sc_man.h" -#include "file_zip.h" #include "screenjob.h" #include "hwrenderer/postprocessing/hw_postprocess.h" #include "hw_viewpointuniforms.h" @@ -272,9 +271,10 @@ enum ELevelFlags : unsigned int LEVEL3_NOJUMPDOWN = 0x00040000, // only for MBF21. Inverse of MBF's dog_jumping flag. LEVEL3_LIGHTCREATED = 0x00080000, // a light had been created in the last frame - // Deliberately skip ahead... - LEVEL9_NOUSERSAVE = 0x00000001, - LEVEL9_NOAUTOMAP = 0x00000002, + // VKDoom custom flags + VKDLEVELFLAG_NOUSERSAVE = 0x00000001, + VKDLEVELFLAG_NOAUTOMAP = 0x00000002, + VKDLEVELFLAG_NOAUTOSAVEONENTER = 0x00000004, // don't make an autosave when entering a map }; @@ -335,6 +335,7 @@ struct level_info_t FString SkyPic1; FString SkyPic2; FString FadeTable; + FString CustomColorMap; FString F1Pic; FString BorderTexture; FString MapBackground; @@ -347,14 +348,16 @@ struct level_info_t int32_t flags; uint32_t flags2; uint32_t flags3; - uint32_t flags9; + uint32_t vkdflags; + + FString LightningSound = "world/thunder"; FString Music; FString LevelName; FString AuthorName; int8_t WallVertLight, WallHorizLight; int musicorder; - FCompressedBuffer Snapshot; + FileSys::FCompressedBuffer Snapshot; TArray deferred; float skyspeed1; float skyspeed2; diff --git a/src/gamedata/g_skill.cpp b/src/gamedata/g_skill.cpp index 34dde60e1c..8a0f69fb3f 100644 --- a/src/gamedata/g_skill.cpp +++ b/src/gamedata/g_skill.cpp @@ -488,18 +488,18 @@ DEFINE_ACTION_FUNCTION(DObject, G_SkillPropertyFloat) const char * G_SkillName() { - const char *name = AllSkills[gameskill].MenuName; + const char *name = AllSkills[gameskill].MenuName.GetChars(); player_t *player = &players[consoleplayer]; - const char *playerclass = player->mo->GetInfo()->DisplayName; + const char *playerclass = player->mo->GetInfo()->DisplayName.GetChars(); if (playerclass != NULL) { FString * pmnm = AllSkills[gameskill].MenuNamesForPlayerClass.CheckKey(playerclass); - if (pmnm != NULL) name = *pmnm; + if (pmnm != NULL) name = pmnm->GetChars(); } - if (*name == '$') name = GStrings(name+1); + if (*name == '$') name = GStrings.GetString(name+1); return name; } diff --git a/src/gamedata/gi.cpp b/src/gamedata/gi.cpp index 643f63fc37..e907722e97 100644 --- a/src/gamedata/gi.cpp +++ b/src/gamedata/gi.cpp @@ -212,10 +212,10 @@ const char* GameInfoBorders[] = { \ sc.MustGetToken(TK_StringConst); \ FString color = sc.String; \ - FString colorName = V_GetColorStringByName(color); \ + FString colorName = V_GetColorStringByName(color.GetChars()); \ if(!colorName.IsEmpty()) \ color = colorName; \ - gameinfo.key = V_GetColorFromString(color); \ + gameinfo.key = V_GetColorFromString(color.GetChars()); \ } #define GAMEINFOKEY_BOOL(key, variable) \ diff --git a/src/gamedata/gi.h b/src/gamedata/gi.h index 5f11ecfa57..5e713628d3 100644 --- a/src/gamedata/gi.h +++ b/src/gamedata/gi.h @@ -51,6 +51,7 @@ enum GI_COMPATPOLY1 = 0x00000040, // Hexen's MAP36 needs old polyobject drawing GI_COMPATPOLY2 = 0x00000080, // so does HEXDD's MAP47 GI_IGNORETITLEPATCHES = 0x00000200, // Ignore the map name graphics when not runnning in English language + GI_NOSECTIONMERGE = 0x00000400, // For the original id IWADs: avoid merging sections due to how idbsp created its sectors. }; #include "gametype.h" diff --git a/src/gamedata/info.cpp b/src/gamedata/info.cpp index 3736cb4d2e..67fb87f678 100644 --- a/src/gamedata/info.cpp +++ b/src/gamedata/info.cpp @@ -132,16 +132,16 @@ void FState::CheckCallerType(AActor *self, AActor *stateowner) // This should really never happen. Any valid action function must have actor pointers here. if (!requiredType->isObjectPointer()) { - ThrowAbortException(X_OTHER, "Bad function prototype in function call to %s", ActionFunc->PrintableName.GetChars()); + ThrowAbortException(X_OTHER, "Bad function prototype in function call to %s", ActionFunc->PrintableName); } auto cls = static_cast(requiredType)->PointedClass(); if (check == nullptr) { - ThrowAbortException(X_OTHER, "%s called without valid caller. %s expected", ActionFunc->PrintableName.GetChars(), cls->TypeName.GetChars()); + ThrowAbortException(X_OTHER, "%s called without valid caller. %s expected", ActionFunc->PrintableName, cls->TypeName.GetChars()); } if (!(StateFlags & STF_DEHACKED) && !check->IsKindOf(cls)) { - ThrowAbortException(X_OTHER, "Invalid class %s in function call to %s. %s expected", check->GetClass()->TypeName.GetChars(), ActionFunc->PrintableName.GetChars(), cls->TypeName.GetChars()); + ThrowAbortException(X_OTHER, "Invalid class %s in function call to %s. %s expected", check->GetClass()->TypeName.GetChars(), ActionFunc->PrintableName, cls->TypeName.GetChars()); } }; @@ -487,6 +487,8 @@ void PClassActor::InitializeDefaults() { memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size); } + + optr->ObjectFlags = ((DObject*)ParentClass->Defaults)->ObjectFlags & OF_Transient; } else { @@ -783,17 +785,17 @@ static void SummonActor (int command, int command2, FCommandLine argv) Printf ("Unknown actor '%s'\n", argv[1]); return; } - Net_WriteByte (argv.argc() > 2 ? command2 : command); + Net_WriteInt8 (argv.argc() > 2 ? command2 : command); Net_WriteString (type->TypeName.GetChars()); if (argv.argc () > 2) { - Net_WriteWord (atoi (argv[2])); // angle - Net_WriteWord ((argv.argc() > 3) ? atoi(argv[3]) : 0); // TID - Net_WriteByte ((argv.argc() > 4) ? atoi(argv[4]) : 0); // special + Net_WriteInt16 (atoi (argv[2])); // angle + Net_WriteInt16 ((argv.argc() > 3) ? atoi(argv[3]) : 0); // TID + Net_WriteInt8 ((argv.argc() > 4) ? atoi(argv[4]) : 0); // special for (int i = 5; i < 10; i++) { // args[5] - Net_WriteLong((i < argv.argc()) ? atoi(argv[i]) : 0); + Net_WriteInt32((i < argv.argc()) ? atoi(argv[i]) : 0); } } } diff --git a/src/gamedata/info.h b/src/gamedata/info.h index d9e89037bb..69ad560e00 100644 --- a/src/gamedata/info.h +++ b/src/gamedata/info.h @@ -112,6 +112,7 @@ struct FState uint8_t DefineFlags; int32_t Misc1; // Was changed to int8_t, reverted to long for MBF compat int32_t Misc2; // Was changed to uint8_t, reverted to long for MBF compat + int32_t DehIndex; // we need this to resolve offsets in P_SetSafeFlash. public: inline int GetFrame() const { @@ -178,6 +179,8 @@ struct FState }; +extern TMap dehExtStates; + struct FStateLabels; struct FStateLabel { diff --git a/src/gamedata/keysections.cpp b/src/gamedata/keysections.cpp index 5f06f192e6..bcde05eddd 100644 --- a/src/gamedata/keysections.cpp +++ b/src/gamedata/keysections.cpp @@ -72,7 +72,7 @@ static void DoSaveKeys (FConfigFile *config, const char *section, FKeySection *k FKeyBindings *bindings = dbl? &DoubleBindings : &Bindings; for (unsigned i = 0; i < keysection->mActions.Size(); ++i) { - bindings->ArchiveBindings (config, keysection->mActions[i].mAction); + bindings->ArchiveBindings (config, keysection->mActions[i].mAction.GetChars()); } } @@ -165,13 +165,13 @@ void D_LoadWadSettings () while ((lump = fileSystem.FindLump ("KEYCONF", &lastlump)) != -1) { - FileData data = fileSystem.ReadFile (lump); - const char *eof = (char *)data.GetMem() + fileSystem.FileLength (lump); - const char *conf = (char *)data.GetMem(); + auto data = fileSystem.ReadFile (lump); + const char* conf = data.string(); + const char *eof = conf + data.size(); while (conf < eof) { - size_t i; + size_t i = 0; // Fetch a line to execute command.Clear(); @@ -179,14 +179,14 @@ void D_LoadWadSettings () { command.Push(conf[i]); } - if (i == 0) + if (i == 0) // Blank line { conf++; continue; } command.Push(0); conf += i; - if (*conf == '\n') + if (conf >= eof || *conf == '\n') { conf++; } diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index 74858907cc..efdbd49598 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -39,8 +39,10 @@ #include "fcolormap.h" #include "r_sky.h" #include "p_terrain.h" +#include "p_effect.h" #include "hwrenderer/data/buffers.h" +#include "hwrenderer/data/hw_levelmesh.h" // Some more or less basic data types // we depend on. @@ -60,7 +62,7 @@ struct sector_t; class AActor; struct FSection; struct FLevelLocals; -struct LightmapSurface; +struct DoomLevelMeshSurface; const uint16_t NO_INDEX = 0xffffu; const uint32_t NO_SIDE = 0xffffffffu; @@ -363,11 +365,21 @@ struct secplane_t return (D + normal.X*pos.X + normal.Y*pos.Y) * negiC; } + double ZatPoint(const DVector3& pos) const + { + return (D + normal.X * pos.X + normal.Y * pos.Y) * negiC; + } + double ZatPoint(const FVector2 &pos) const { return (D + normal.X*pos.X + normal.Y*pos.Y) * negiC; } + double ZatPoint(const FVector3& pos) const + { + return (D + normal.X * pos.X + normal.Y * pos.Y) * negiC; + } + double ZatPoint(const vertex_t *v) const { return (D + normal.X*v->fX() + normal.Y*v->fY()) * negiC; @@ -510,6 +522,7 @@ enum SECF_EXIT1 = 4096, SECF_EXIT2 = 8192, SECF_KILLMONSTERS = 16384, + SECF_LM_DYNAMIC = 32768, // Lightmap needs to be dynamically updated in this sector SECF_WASSECRET = 1 << 30, // a secret that was discovered SECF_SECRET = 1 << 31, // a secret sector @@ -656,6 +669,8 @@ struct sector_t float GlowHeight; FTextureID Texture; TextureManipulation TextureFx; + FTextureID skytexture[2]; + uint16_t LightmapSampleDistance; }; @@ -679,10 +694,10 @@ struct sector_t int special; // map-defined sector special type - int sky; // MBF sky transfer info. + int skytransfer; // MBF sky transfer info. int validcount; // if == validcount, already checked - uint32_t bottommap, midmap, topmap; // killough 4/4/98: dynamic colormaps + uint32_t selfmap, bottommap, midmap, topmap; // killough 4/4/98: dynamic colormaps // [RH] these can also be blend values if // the alpha mask is non-zero @@ -815,7 +830,6 @@ struct sector_t int CheckSpriteGlow(int lightlevel, const DVector3 &pos); bool GetWallGlow(float *topglowcolor, float *bottomglowcolor); - void SetXOffset(int pos, double o) { planes[pos].xform.xOffs = o; @@ -1014,6 +1028,11 @@ struct sector_t return pos == floor? floorplane:ceilingplane; } + const secplane_t& GetSecPlane(int pos) const + { + return pos == floor ? floorplane : ceilingplane; + } + bool isSecret() const { return !!(Flags & SECF_SECRET); @@ -1183,6 +1202,15 @@ struct side_t walltop = 0, wallbottom = 1, }; + enum ESkew + { + skew_none = 0, + skew_front_floor = 1, + skew_front_ceiling = 2, + skew_back_floor = 3, + skew_back_ceiling = 4 + }; + struct part { enum EPartFlags @@ -1198,11 +1226,13 @@ struct side_t double xScale; double yScale; TObjPtr interpolation; - int flags; + int16_t flags; + int8_t skew; FTextureID texture; TextureManipulation TextureFx; PalEntry SpecialColors[2]; PalEntry AdditiveColor; + uint16_t LightmapSampleDistance; void InitFrom(const part &other) @@ -1227,7 +1257,7 @@ struct side_t uint16_t Flags; int UDMFIndex; // needed to access custom UDMF fields which are stored in loading order. FLightNode * lighthead; // all dynamic lights that may affect this wall - LightmapSurface* lightmap; + TArrayView surface; // all mesh surfaces belonging to this sidedef seg_t **segs; // all segs belonging to this sidedef in ascending order. Used for precise rendering int numsegs; int sidenum; @@ -1490,6 +1520,8 @@ struct line_t : public linebase_t int healthgroup; // [ZZ] this is the "destructible object" id int linenum; + uint16_t LightmapSampleDistance[3]; // Used only as storage during map loading. + void setAlpha(double a) { alpha = a; @@ -1641,8 +1673,8 @@ struct subsector_t int Index() const { return subsectornum; } // 2: has one-sided walls FPortalCoverage portalcoverage[2]; - - LightmapSurface *lightmap[2]; + TArray sprites; + TArrayView surface[2]; // all mesh surfaces belonging to this subsector }; @@ -1687,28 +1719,6 @@ struct FMiniBSP TArray Verts; }; -// Lightmap data - -enum SurfaceType -{ - ST_NULL, - ST_MIDDLEWALL, - ST_UPPERWALL, - ST_LOWERWALL, - ST_CEILING, - ST_FLOOR -}; - -struct LightmapSurface -{ - SurfaceType Type; - subsector_t *Subsector; - side_t *Side; - sector_t *ControlSector; - uint32_t LightmapNum; - float *TexCoords; -}; - // // OTHER TYPES // diff --git a/src/gamedata/statistics.cpp b/src/gamedata/statistics.cpp index 39f67a9987..95d8165ae0 100644 --- a/src/gamedata/statistics.cpp +++ b/src/gamedata/statistics.cpp @@ -202,7 +202,7 @@ int compare_episode_names(const void *a, const void *b) FStatistics *A = (FStatistics*)a; FStatistics *B = (FStatistics*)b; - return strnatcasecmp(A->epi_header, B->epi_header); + return strnatcasecmp(A->epi_header.GetChars(), B->epi_header.GetChars()); } int compare_dates(const void *a, const void *b) @@ -291,7 +291,7 @@ static FStatistics *GetStatisticsList(TArray &statlist, const char { for(unsigned int i=0;iLevelname, B->Levelname); + return strnatcasecmp(A->Levelname.GetChars(), B->Levelname.GetChars()); } @@ -458,7 +458,7 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level) { // we reached the end of this episode int wad = 0; - MapData * map = P_OpenMapData(StartEpisode->mEpisodeMap, false); + MapData * map = P_OpenMapData(StartEpisode->mEpisodeMap.GetChars(), false); if (map != NULL) { wad = fileSystem.GetFileContainer(map->lumpnum); @@ -468,9 +468,9 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level) FString section = ExtractFileBase(name) + "." + StartEpisode->mEpisodeMap; section.ToUpper(); - const char *ep_name = StartEpisode->mEpisodeName; - if (*ep_name == '$') ep_name = GStrings(ep_name+1); - FStatistics *sl = GetStatisticsList(EpisodeStatistics, section, ep_name); + const char *ep_name = StartEpisode->mEpisodeName.GetChars(); + if (*ep_name == '$') ep_name = GStrings.GetString(ep_name+1); + FStatistics *sl = GetStatisticsList(EpisodeStatistics, section.GetChars(), ep_name); int statvals[6] = {0,0,0,0,0,0}; FString infostring; @@ -486,7 +486,7 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level) } infostring.Format("%4d/%4d, %4d/%4d, %3d/%3d, %2d", statvals[0], statvals[1], statvals[2], statvals[3], statvals[4], statvals[5], validlevels); - FSessionStatistics *es = StatisticsEntry(sl, infostring, Level->totaltime); + FSessionStatistics *es = StatisticsEntry(sl, infostring.GetChars(), Level->totaltime); for(unsigned i = 0; i < LevelData.Size(); i++) { @@ -495,7 +495,7 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level) infostring.Format("%4d/%4d, %4d/%4d, %3d/%3d", LevelData[i].killcount, LevelData[i].totalkills, LevelData[i].itemcount, LevelData[i].totalitems, LevelData[i].secretcount, LevelData[i].totalsecrets); - LevelStatEntry(es, lsection, infostring, LevelData[i].leveltime); + LevelStatEntry(es, lsection.GetChars(), infostring.GetChars(), LevelData[i].leveltime); } SaveStatistics(statfile, EpisodeStatistics); } @@ -602,7 +602,7 @@ CCMD(finishgame) return; } // This CCMD simulates an end-of-game action and exists to end mods that never exit their last Level-> - Net_WriteByte(DEM_FINISHGAME); + Net_WriteInt8(DEM_FINISHGAME); } ADD_STAT(statistics) diff --git a/src/gamedata/teaminfo.cpp b/src/gamedata/teaminfo.cpp index 629d110b98..1838d1b393 100644 --- a/src/gamedata/teaminfo.cpp +++ b/src/gamedata/teaminfo.cpp @@ -38,6 +38,7 @@ #include "gi.h" #include "teaminfo.h" +#include "texturemanager.h" #include "v_font.h" #include "v_video.h" #include "filesystem.h" @@ -244,7 +245,7 @@ void FTeam::ClearTeams () // //========================================================================== -bool FTeam::IsValidTeam (unsigned int uiTeam) +bool FTeam::IsValidTeam (unsigned int uiTeam) const { if (uiTeam >= Teams.Size ()) return false; @@ -260,7 +261,7 @@ bool FTeam::IsValidTeam (unsigned int uiTeam) const char *FTeam::GetName () const { - return m_Name; + return m_Name.GetChars(); } //========================================================================== @@ -303,7 +304,7 @@ int FTeam::GetTextColor () const // //========================================================================== -FString FTeam::GetLogo () const +const FString& FTeam::GetLogo () const { return m_Logo; } @@ -338,3 +339,75 @@ CCMD (teamlist) DEFINE_GLOBAL(Teams) DEFINE_FIELD_NAMED(FTeam, m_Name, mName) + +static int IsValid(unsigned int id) +{ + return TeamLibrary.IsValidTeam(id); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, IsValid, IsValid) +{ + PARAM_PROLOGUE; + PARAM_UINT(id); + + ACTION_RETURN_BOOL(TeamLibrary.IsValidTeam(id)); +} + +static int GetPlayerColor(FTeam* self) +{ + return self->GetPlayerColor(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, GetPlayerColor, GetPlayerColor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_INT(self->GetPlayerColor()); +} + +static int GetTextColor(FTeam* self) +{ + return self->GetTextColor(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, GetTextColor, GetTextColor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_INT(self->GetTextColor()); +} + +static int GetLogo(FTeam* self) +{ + const FString& name = self->GetLogo(); + if (name.IsEmpty()) + return -1; + + return TexMan.CheckForTexture(name.GetChars(), ETextureType::Any).GetIndex(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, GetLogo, GetLogo) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_INT(GetLogo(self)); +} + +static void GetLogoName(FTeam* self, FString* res) +{ + *res = self->GetLogo(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, GetLogoName, GetLogoName) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_STRING(self->GetLogo()); +} + +static int AllowsCustomPlayerColor(FTeam* self) +{ + return self->GetAllowCustomPlayerColor(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, AllowsCustomPlayerColor, AllowsCustomPlayerColor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_BOOL(self->GetAllowCustomPlayerColor()); +} diff --git a/src/gamedata/teaminfo.h b/src/gamedata/teaminfo.h index 1c84d9b9b8..1a3db705c9 100644 --- a/src/gamedata/teaminfo.h +++ b/src/gamedata/teaminfo.h @@ -46,12 +46,12 @@ class FTeam public: FTeam (); void ParseTeamInfo (); - bool IsValidTeam (unsigned int uiTeam); + bool IsValidTeam (unsigned int uiTeam) const; const char *GetName () const; int GetPlayerColor () const; int GetTextColor () const; - FString GetLogo () const; + const FString& GetLogo () const; bool GetAllowCustomPlayerColor () const; int m_iPlayerCount; diff --git a/src/gamedata/textures/anim_switches.cpp b/src/gamedata/textures/anim_switches.cpp index 78e49508df..ce7166ba95 100644 --- a/src/gamedata/textures/anim_switches.cpp +++ b/src/gamedata/textures/anim_switches.cpp @@ -66,8 +66,8 @@ void FTextureAnimator::InitSwitchList () if (lump != -1) { - FileData lumpdata = fileSystem.ReadFile (lump); - const char *alphSwitchList = (const char *)lumpdata.GetMem(); + auto lumpdata = fileSystem.ReadFile (lump); + auto alphSwitchList = lumpdata.string(); const char *list_p; FSwitchDef *def1, *def2; diff --git a/src/gamedata/textures/animations.cpp b/src/gamedata/textures/animations.cpp index 61bb6d29c1..d40f2c7c50 100644 --- a/src/gamedata/textures/animations.cpp +++ b/src/gamedata/textures/animations.cpp @@ -88,18 +88,19 @@ void FTextureAnimator::DeleteAll() FAnimDef *FTextureAnimator::AddAnim (FAnimDef& anim) { // Search for existing duplicate. - for (unsigned int i = 0; i < mAnimations.Size(); ++i) - { - if (mAnimations[i].BasePic == anim.BasePic) - { - // Found one! - mAnimations[i] = anim; - return &mAnimations[i]; - } + uint16_t * index = mAnimationIndices.CheckKey(anim.BasePic); + + if(index) + { // Found one! + mAnimations[*index] = anim; + return &mAnimations[*index]; + } + else + { // Didn't find one, so add it at the end. + mAnimationIndices.Insert(anim.BasePic, mAnimations.Size()); + mAnimations.Push (anim); + return &mAnimations.Last(); } - // Didn't find one, so add it at the end. - mAnimations.Push (anim); - return &mAnimations.Last(); } //========================================================================== @@ -203,9 +204,9 @@ void FTextureAnimator::InitAnimated (void) int lumpnum = fileSystem.CheckNumForName ("ANIMATED"); if (lumpnum != -1) { - FileData animatedlump = fileSystem.ReadFile (lumpnum); + auto animatedlump = fileSystem.ReadFile (lumpnum); int animatedlen = fileSystem.FileLength(lumpnum); - const uint8_t *animdefs = (const uint8_t *)animatedlump.GetMem(); + auto animdefs = animatedlump.bytes(); const uint8_t *anim_p; FTextureID pic1, pic2; int animtype; @@ -723,9 +724,9 @@ void FTextureAnimator::ParseCameraTexture(FScanner &sc) width = sc.Number; sc.MustGetNumber (); height = sc.Number; - FTextureID picnum = TexMan.CheckForTexture (picname, ETextureType::Flat, texflags); + FTextureID picnum = TexMan.CheckForTexture (picname.GetChars(), ETextureType::Flat, texflags); auto canvas = new FCanvasTexture(width, height); - FGameTexture *viewer = MakeGameTexture(canvas, picname, ETextureType::Wall); + FGameTexture *viewer = MakeGameTexture(canvas, picname.GetChars(), ETextureType::Wall); if (picnum.Exists()) { auto oldtex = TexMan.GameTexture(picnum); @@ -742,6 +743,17 @@ void FTextureAnimator::ParseCameraTexture(FScanner &sc) TexMan.AddGameTexture (viewer); } if (sc.GetString()) + { + if (sc.Compare ("hdr")) + { + canvas->SetHDR(true); + } + else + { + sc.UnGet(); + } + } + if (sc.GetString()) { if (sc.Compare ("fit")) { @@ -794,7 +806,7 @@ void FTextureAnimator::FixAnimations () bool noremap = false; const char *name; - name = TexMan.GameTexture(anim->BasePic)->GetName(); + name = TexMan.GameTexture(anim->BasePic)->GetName().GetChars(); nodecals = TexMan.GameTexture(anim->BasePic)->allowNoDecals(); for (j = 0; j < anim->NumFrames; ++j) { @@ -919,6 +931,104 @@ void FAnimDef::SetSwitchTime (uint64_t mstime) } } +static void AdvanceFrame(uint16_t &frame, uint8_t &AnimType, const FAnimDef &anim) +{ + switch (AnimType) + { + default: + case FAnimDef::ANIM_Forward: + frame = (frame + 1) % anim.NumFrames; + break; + + case FAnimDef::ANIM_Backward: + if (frame == 0) + { + frame = anim.NumFrames - 1; + } + else + { + frame--; + } + break; + case FAnimDef::ANIM_Random: + // select a random frame other than the current one + if (anim.NumFrames > 1) + { + uint16_t rndFrame = (uint16_t)pr_animatepictures(anim.NumFrames - 1); + if(rndFrame == frame) rndFrame++; + frame = rndFrame % anim.NumFrames; + } + break; + + case FAnimDef::ANIM_OscillateUp: + frame = frame + 1; + assert(frame < anim.NumFrames); + if (frame == anim.NumFrames - 1) + { + AnimType = FAnimDef::ANIM_OscillateDown; + } + break; + + case FAnimDef::ANIM_OscillateDown: + frame = frame - 1; + if (frame == 0) + { + AnimType = FAnimDef::ANIM_OscillateUp; + } + break; + } +} + +constexpr double msPerTic = 1'000.0 / TICRATE; + +bool FTextureAnimator::InitStandaloneAnimation(FStandaloneAnimation &animInfo, FTextureID tex, uint32_t curTic) +{ + animInfo.ok = false; + uint16_t * index = mAnimationIndices.CheckKey(tex); + if(!index) return false; + FAnimDef * anim = &mAnimations[*index]; + + animInfo.ok = true; + animInfo.AnimIndex = *index; + animInfo.CurFrame = 0; + animInfo.SwitchTic = curTic; + animInfo.AnimType = (anim->AnimType == FAnimDef::ANIM_OscillateDown) ? FAnimDef::ANIM_OscillateUp : anim->AnimType; + uint32_t time = anim->Frames[0].SpeedMin; + if(anim->Frames[0].SpeedRange != 0) + { + time += pr_animatepictures(anim->Frames[0].SpeedRange); + } + animInfo.SwitchTic += time / msPerTic; + return true; +} + +FTextureID FTextureAnimator::UpdateStandaloneAnimation(FStandaloneAnimation &animInfo, double curTic) +{ + if(!animInfo.ok) return nullptr; + auto &anim = mAnimations[animInfo.AnimIndex]; + if(animInfo.SwitchTic <= curTic) + { + uint16_t frame = animInfo.CurFrame; + uint16_t speedframe = anim.bDiscrete ? frame : 0; + while(animInfo.SwitchTic <= curTic) + { + AdvanceFrame(frame, animInfo.AnimType, anim); + + if(anim.bDiscrete) speedframe = frame; + + uint32_t time = anim.Frames[speedframe].SpeedMin; + if(anim.Frames[speedframe].SpeedRange != 0) + { + time += pr_animatepictures(anim.Frames[speedframe].SpeedRange); + } + + animInfo.SwitchTic += time / msPerTic; + } + animInfo.CurFrame = frame; + } + return anim.bDiscrete ? anim.Frames[animInfo.CurFrame].FramePic : (anim.BasePic + animInfo.CurFrame); +} + //========================================================================== // @@ -944,50 +1054,7 @@ void FTextureAnimator::UpdateAnimations (uint64_t mstime) { // Multiple frames may have passed since the last time calling // R_UpdateAnimations, so be sure to loop through them all. - switch (anim->AnimType) - { - default: - case FAnimDef::ANIM_Forward: - anim->CurFrame = (anim->CurFrame + 1) % anim->NumFrames; - break; - - case FAnimDef::ANIM_Backward: - if (anim->CurFrame == 0) - { - anim->CurFrame = anim->NumFrames - 1; - } - else - { - anim->CurFrame -= 1; - } - break; - - case FAnimDef::ANIM_Random: - // select a random frame other than the current one - if (anim->NumFrames > 1) - { - uint16_t rndFrame = (uint16_t)pr_animatepictures(anim->NumFrames - 1); - if (rndFrame >= anim->CurFrame) rndFrame++; - anim->CurFrame = rndFrame; - } - break; - - case FAnimDef::ANIM_OscillateUp: - anim->CurFrame = anim->CurFrame + 1; - if (anim->CurFrame >= anim->NumFrames - 1) - { - anim->AnimType = FAnimDef::ANIM_OscillateDown; - } - break; - - case FAnimDef::ANIM_OscillateDown: - anim->CurFrame = anim->CurFrame - 1; - if (anim->CurFrame == 0) - { - anim->AnimType = FAnimDef::ANIM_OscillateUp; - } - break; - } + AdvanceFrame(anim->CurFrame, anim->AnimType, *anim); anim->SetSwitchTime (mstime); } diff --git a/src/gamedata/textures/animations.h b/src/gamedata/textures/animations.h index 639005bd20..aa6b00e4e1 100644 --- a/src/gamedata/textures/animations.h +++ b/src/gamedata/textures/animations.h @@ -6,6 +6,17 @@ #include "tarray.h" #include "s_soundinternal.h" +struct FStandaloneAnimation +{ + double SwitchTic; + uint32_t AnimIndex; + uint16_t CurFrame; + bool ok = false; + uint8_t AnimType; +}; + +static_assert(sizeof(FStandaloneAnimation) == sizeof(uint64_t)*2); + struct FAnimDef { struct FAnimFrame @@ -62,6 +73,7 @@ struct FDoorAnimation class FTextureAnimator { + TMap mAnimationIndices; TArray mAnimations; TArray mSwitchDefs; TArray mAnimatedDoors; @@ -112,6 +124,9 @@ class FTextureAnimator FixAnimations(); InitSwitchList(); } + + bool InitStandaloneAnimation(FStandaloneAnimation &animInfo, FTextureID tex, uint32_t curTic); + FTextureID UpdateStandaloneAnimation(FStandaloneAnimation &animInfo, double curTic); }; extern FTextureAnimator TexAnim; diff --git a/src/gamedata/textures/buildloader.cpp b/src/gamedata/textures/buildloader.cpp index bfcc632251..83c547b501 100644 --- a/src/gamedata/textures/buildloader.cpp +++ b/src/gamedata/textures/buildloader.cpp @@ -41,12 +41,13 @@ #include "colormatcher.h" #include "bitmap.h" #include "textures.h" -#include "resourcefile.h" +#include "fs_filesystem.h" #include "image.h" #include "animations.h" #include "texturemanager.h" #include "r_translate.h" #include "r_data/sprites.h" +#include "m_swap.h" //=========================================================================== // @@ -83,8 +84,8 @@ static int BuildPaletteTranslation(int lump) return false; } - FileData data = fileSystem.ReadFile(lump); - const uint8_t *ipal = (const uint8_t *)data.GetMem(); + auto data = fileSystem.ReadFile(lump); + auto ipal = data.bytes(); FRemapTable opal; bool blood = false; @@ -157,7 +158,7 @@ void AddTiles(const FString& pathprefix, const void* tiles, FRemapTable *remap) if (width <= 0 || height <= 0) continue; FStringf name("%sBTIL%04d", pathprefix.GetChars(), i); - auto tex = MakeGameTexture(new FImageTexture(new FBuildTexture(pathprefix, i, tiledata, remap, width, height, xoffs, yoffs)), name, ETextureType::Override); + auto tex = MakeGameTexture(new FImageTexture(new FBuildTexture(pathprefix, i, tiledata, remap, width, height, xoffs, yoffs)), name.GetChars(), ETextureType::Override); texnum = TexMan.AddGameTexture(tex); tiledata += size; @@ -275,7 +276,7 @@ void InitBuildTiles() // only read from the same source as the palette. // The entire format here is just too volatile to allow liberal mixing. // An .ART set must be treated as one unit. - lumpnum = fileSystem.CheckNumForFullName(artpath, fileSystem.GetFileContainer(i)); + lumpnum = fileSystem.CheckNumForFullName(artpath.GetChars(), fileSystem.GetFileContainer(i)); if (lumpnum < 0) { break; diff --git a/src/gamedata/umapinfo.cpp b/src/gamedata/umapinfo.cpp index d6b391039c..08e16d9f88 100644 --- a/src/gamedata/umapinfo.cpp +++ b/src/gamedata/umapinfo.cpp @@ -42,6 +42,7 @@ struct UMapEntry FString InterText; FString InterTextSecret; TArray BossActions; + bool BossCleared = false; char levelpic[9] = ""; char nextmap[9] = ""; @@ -229,7 +230,7 @@ static int ParseStandardProperty(FScanner &scanner, UMapEntry *mape) if (split.Size() > 1) { - epi.mEpisodeName = strbin1(split[1]); + epi.mEpisodeName = strbin1(split[1].GetChars()); } if (split.Size() > 2 && split[2].IsNotEmpty()) { @@ -268,6 +269,7 @@ static int ParseStandardProperty(FScanner &scanner, UMapEntry *mape) // mark level free of boss actions classnum = special = tag = -1; mape->BossActions.Clear(); + mape->BossCleared = true; } else { @@ -387,7 +389,7 @@ void CommitUMapinfo(level_info_t *defaultinfo) { for (auto &map : Maps) { - auto levelinfo = FindLevelInfo(map.MapName, false); + auto levelinfo = FindLevelInfo(map.MapName.GetChars(), false); if (levelinfo == nullptr) { // Map did not exist yet. @@ -441,16 +443,19 @@ void CommitUMapinfo(level_info_t *defaultinfo) if (map.partime > 0) levelinfo->partime = map.partime; if (map.enterpic[0]) levelinfo->EnterPic = map.enterpic; if (map.exitpic[0]) levelinfo->ExitPic = map.exitpic; + /* UMAPINFO's intermusic is for the text screen, not the summary. if (map.intermusic[0]) { levelinfo->InterMusic = map.intermusic; levelinfo->intermusicorder = 0; } - if (map.BossActions.Size() > 0) + */ + if (map.BossActions.Size() > 0 || map.BossCleared) { // Setting a boss action will deactivate the flag based monster actions. levelinfo->specialactions = std::move(map.BossActions); levelinfo->flags &= ~(LEVEL_BRUISERSPECIAL | LEVEL_CYBORGSPECIAL | LEVEL_SPIDERSPECIAL | LEVEL_MAP07SPECIAL | LEVEL_MINOTAURSPECIAL | LEVEL_HEADSPECIAL | LEVEL_SORCERER2SPECIAL | LEVEL_SPECACTIONSMASK | LEVEL_SPECKILLMONSTERS); + levelinfo->flags3 &= ~(LEVEL3_E1M8SPECIAL | LEVEL3_E2M8SPECIAL | LEVEL3_E3M8SPECIAL | LEVEL3_E4M8SPECIAL | LEVEL3_E4M6SPECIAL); } const int exflags = FExitText::DEF_TEXT | FExitText::DEF_BACKDROP | FExitText::DEF_MUSIC; diff --git a/src/gamedata/xlat/parsecontext.cpp b/src/gamedata/xlat/parsecontext.cpp index cac663cfc3..0caa72f4b2 100644 --- a/src/gamedata/xlat/parsecontext.cpp +++ b/src/gamedata/xlat/parsecontext.cpp @@ -78,7 +78,7 @@ bool FParseContext::FindSym (char *sym, FParseSymbol **val) // // //========================================================================== -int FParseContext::GetToken (char *&sourcep, FParseToken *yylval) +int FParseContext::GetToken (const char *&sourcep, FParseToken *yylval) { char token[80]; int toksize; @@ -103,7 +103,7 @@ int FParseContext::GetToken (char *&sourcep, FParseToken *yylval) c = *sourcep++; if (c == 'x' || c == 'X') { - yylval->val = (int)strtoll(sourcep, &sourcep, 16); + yylval->val = (int)strtoll(sourcep, (char**)&sourcep, 16); return TokenTrans[NUM]; } else @@ -118,7 +118,7 @@ int FParseContext::GetToken (char *&sourcep, FParseToken *yylval) if (*endp == '.') { // It's a float - yylval->fval = strtod(sourcep, &sourcep); + yylval->fval = strtod(sourcep, (char**)& sourcep); return TokenTrans[FLOATVAL]; } else @@ -323,12 +323,12 @@ void FParseContext::ParseLump(const char *lumpname) } // Read the lump into a buffer and add a 0-terminator - auto lumpdata = fileSystem.GetFileData(lumpno, 1); SourceLine = 0; SourceFile = lumpname; - char *sourcep = (char*)lumpdata.Data(); + FString source = GetStringFromLump(lumpno); + const char *sourcep = source.GetChars(); while ( (tokentype = GetToken(sourcep, &token)) ) { // It is much easier to handle include statements outside the main parser. diff --git a/src/gamedata/xlat/parsecontext.h b/src/gamedata/xlat/parsecontext.h index 48a3425474..82c345f782 100644 --- a/src/gamedata/xlat/parsecontext.h +++ b/src/gamedata/xlat/parsecontext.h @@ -146,7 +146,7 @@ struct FParseContext void AddSym (char *sym, int val); bool FindSym (char *sym, FParseSymbol **val); virtual bool FindToken (char *tok, int *type) = 0; - int GetToken (char *&sourcep, FParseToken *yylval); + int GetToken (const char *&sourcep, FParseToken *yylval); int PrintError (const char *s); void ParseLump(const char *lumpname); }; diff --git a/src/gamedata/xlat/xlat.h b/src/gamedata/xlat/xlat.h index f488704ff1..516104af12 100644 --- a/src/gamedata/xlat/xlat.h +++ b/src/gamedata/xlat/xlat.h @@ -82,7 +82,7 @@ struct FBoomTranslator { uint16_t FirstLinetype = 0; uint16_t LastLinetype = 0; - uint8_t NewSpecial = 0; + uint16_t NewSpecial = 0; TArray Args; } ; diff --git a/src/hu_scores.cpp b/src/hu_scores.cpp index d9c36f8b40..797e222efa 100644 --- a/src/hu_scores.cpp +++ b/src/hu_scores.cpp @@ -336,10 +336,10 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER y += (BigFont->GetHeight() + 8) * CleanYfac; } - const char *text_color = GStrings("SCORE_COLOR"), - *text_frags = GStrings(deathmatch ? "SCORE_FRAGS" : "SCORE_KILLS"), - *text_name = GStrings("SCORE_NAME"), - *text_delay = GStrings("SCORE_DELAY"); + const char *text_color = GStrings.GetString("SCORE_COLOR"), + *text_frags = GStrings.GetString(deathmatch ? "SCORE_FRAGS" : "SCORE_KILLS"), + *text_name = GStrings.GetString("SCORE_NAME"), + *text_delay = GStrings.GetString("SCORE_DELAY"); col2 = (displayFont->StringWidth(text_color) + 16) * FontScale; col3 = col2 + (displayFont->StringWidth(text_frags) + 16) * FontScale; diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index fdcdd03253..c32812ce27 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -95,7 +95,7 @@ DEFINE_ACTION_FUNCTION(_Screen, GetTextScreenSize) void DrawFullscreenSubtitle(FFont* font, const char *text) { if (!text || !*text || !inter_subtitles) return; - if (*text == '$') text = GStrings[text + 1]; + text = GStrings.localize(text); // This uses the same scaling as regular HUD messages auto scale = active_con_scaletext(twod, generic_ui); @@ -129,7 +129,7 @@ void DrawFullscreenSubtitle(FFont* font, const char *text) y += 10; for (const FBrokenLines &line : lines) { - DrawText(twod, font, CR_UNTRANSLATED, x, y, line.Text, + DrawText(twod, font, CR_UNTRANSLATED, x, y, line.Text.GetChars(), DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, TAG_DONE); y += font->GetHeight(); @@ -146,11 +146,11 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) { if (!first && desc->mMusic.IsNotEmpty()) { - S_ChangeMusic (desc->mMusic, desc->mMusicOrder, desc->mMusicLooping); + S_ChangeMusic (desc->mMusic.GetChars(), desc->mMusicOrder, desc->mMusicLooping); } mDuration = desc->mDuration; - const char *texname = desc->mBackground; + const char *texname = desc->mBackground.GetChars(); if (*texname == '@') { char *pp; @@ -170,7 +170,7 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) } else if (*texname == '$') { - texname = GStrings(texname+1); + texname = GStrings.GetString(texname+1); } if (texname[0] != 0) { @@ -184,7 +184,7 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) mOverlays[i].x = desc->mOverlays[i].x; mOverlays[i].y = desc->mOverlays[i].y; mOverlays[i].mCondition = desc->mOverlays[i].mCondition; - mOverlays[i].mPic = TexMan.CheckForTexture(desc->mOverlays[i].mName, ETextureType::MiscPatch); + mOverlays[i].mPic = TexMan.CheckForTexture(desc->mOverlays[i].mName.GetChars(), ETextureType::MiscPatch); } mTicker = 0; mSubtitle = desc->mSubtitle; @@ -201,11 +201,11 @@ void DIntermissionScreen::Start() { if (mMusic.IsEmpty()) { - S_ChangeMusic(gameinfo.finaleMusic, gameinfo.finaleOrder, mMusicLooping); + S_ChangeMusic(gameinfo.finaleMusic.GetChars(), gameinfo.finaleOrder, mMusicLooping); } else { - S_ChangeMusic(mMusic, mMusicOrder, mMusicLooping); + S_ChangeMusic(mMusic.GetChars(), mMusicOrder, mMusicLooping); } } } @@ -261,7 +261,7 @@ void DIntermissionScreen::Drawer () DrawTexture(twod, mOverlays[i].mPic, false, mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, TAG_DONE); } FFont* font = generic_ui ? NewSmallFont : SmallFont; - DrawFullscreenSubtitle(font, mSubtitle); + DrawFullscreenSubtitle(font, mSubtitle.GetChars()); } void DIntermissionScreen::OnDestroy() @@ -330,7 +330,7 @@ void DIntermissionScreenText::Init(FIntermissionAction *desc, bool first) { Super::Init(desc, first); mText = static_cast(desc)->mText; - if (mText[0] == '$') mText = GStrings(&mText[1]); + if (mText[0] == '$') mText = GStrings.GetString(&mText[1]); auto lines = mText.Split("\n"); mText = ""; @@ -488,7 +488,7 @@ void DIntermissionScreenText::Drawer () void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first) { Super::Init(desc, first); - mName = static_cast(desc)->mName; + mName = static_cast(desc)->mName.GetChars(); mClass = PClass::FindActor(static_cast(desc)->mCastClass); if (mClass != NULL) mDefaults = GetDefaultByType(mClass); else @@ -514,8 +514,8 @@ void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first) else { advplayerstate = NULL; - casttranslation = 0; - if (mDefaults->Translation != 0) + casttranslation = NO_TRANSLATION; + if (mDefaults->Translation != NO_TRANSLATION) { casttranslation = mDefaults->Translation; } @@ -659,7 +659,7 @@ void DIntermissionScreenCast::Drawer () if (name != NULL) { auto font = generic_ui ? NewSmallFont : SmallFont; - if (*name == '$') name = GStrings(name+1); + if (*name == '$') name = GStrings.GetString(name+1); DrawText(twod, font, CR_UNTRANSLATED, (twod->GetWidth() - font->StringWidth (name) * CleanXfac)/2, (twod->GetHeight() * 180) / 200, @@ -707,7 +707,7 @@ void DIntermissionScreenCast::Drawer () DTA_DestWidthF, pic->GetDisplayWidth() * castscale.X, DTA_RenderStyle, mDefaults->RenderStyle, DTA_Alpha, mDefaults->Alpha, - DTA_TranslationIndex, casttranslation, + DTA_TranslationIndex, casttranslation.index(), TAG_DONE); } } @@ -722,7 +722,7 @@ void DIntermissionScreenScroller::Init(FIntermissionAction *desc, bool first) { Super::Init(desc, first); mFirstPic = mBackground; - mSecondPic = TexMan.CheckForTexture(static_cast(desc)->mSecondPic, ETextureType::MiscPatch); + mSecondPic = TexMan.CheckForTexture(static_cast(desc)->mSecondPic.GetChars(), ETextureType::MiscPatch); mScrollDelay = static_cast(desc)->mScrollDelay; mScrollTime = static_cast(desc)->mScrollTime; mScrollDir = static_cast(desc)->mScrollDir; diff --git a/src/intermission/intermission.h b/src/intermission/intermission.h index e25354c875..45c2efd8bc 100644 --- a/src/intermission/intermission.h +++ b/src/intermission/intermission.h @@ -246,7 +246,7 @@ class DIntermissionScreenCast : public DIntermissionScreen TArray mCastSounds; int casttics; - uint32_t casttranslation; // [RH] Draw "our hero" with their chosen suit color + FTranslationID casttranslation; // [RH] Draw "our hero" with their chosen suit color FState* caststate; FState* basestate; FState* advplayerstate; diff --git a/src/intermission/intermission_parse.cpp b/src/intermission/intermission_parse.cpp index 5b2de2c4db..4bb1f5455d 100644 --- a/src/intermission/intermission_parse.cpp +++ b/src/intermission/intermission_parse.cpp @@ -255,6 +255,7 @@ bool FIntermissionActionWiper::ParseKey(FScanner &sc) { "Crossfade", GS_FORCEWIPEFADE }, { "Melt", GS_FORCEWIPEMELT }, { "Burn", GS_FORCEWIPEBURN }, + { "Fizzlefade", GS_FORCEWIPEFIZZLEFADE }, { "Default", GS_FORCEWIPE }, { NULL, GS_FORCEWIPE } }; @@ -313,14 +314,14 @@ bool FIntermissionActionTextscreen::ParseKey(FScanner &sc) if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, sc.String); - if (GStrings.exists(key)) + if (GStrings.exists(key.GetChars())) { mText = "$" + key; done = true; } } if (!done) - mText = fileSystem.ReadFile(lump).GetString(); + mText = GetStringFromLump(lump); } else { @@ -864,7 +865,7 @@ DIntermissionController* F_StartFinale (const char *music, int musicorder, int c int lump = fileSystem.CheckNumForFullName(text, true); if (lump > 0) { - textscreen->mText = fileSystem.ReadFile(lump).GetString(); + textscreen->mText = GetStringFromLump(lump); } else { @@ -935,7 +936,7 @@ CCMD(testfinale) if (argv.argc() == 2) { - text = GStrings.GetString(argv[1], nullptr); + text = GStrings.CheckString(argv[1], nullptr); } else { @@ -954,7 +955,7 @@ CCMD(testfinale) return; } - auto controller = F_StartFinale(gameinfo.finaleMusic, gameinfo.finaleOrder, -1, 0, gameinfo.FinaleFlat, text, false, false, true, true); + auto controller = F_StartFinale(gameinfo.finaleMusic.GetChars(), gameinfo.finaleOrder, -1, 0, gameinfo.FinaleFlat.GetChars(), text, false, false, true, true); RunIntermission(nullptr, nullptr, controller, nullptr, [=](bool) { gameaction = ga_nothing; }); } diff --git a/src/launcher/launcherbanner.cpp b/src/launcher/launcherbanner.cpp new file mode 100644 index 0000000000..823b0021d0 --- /dev/null +++ b/src/launcher/launcherbanner.cpp @@ -0,0 +1,34 @@ + +#include "launcherbanner.h" +#include "gstrings.h" +#include "version.h" +#include +#include +#include + +LauncherBanner::LauncherBanner(Widget* parent) : Widget(parent) +{ + Logo = new ImageBox(this); + VersionLabel = new TextLabel(this); + VersionLabel->SetTextAlignment(TextLabelAlignment::Right); + + Logo->SetImage(Image::LoadResource("widgets/banner.png")); +} + +void LauncherBanner::UpdateLanguage() +{ + FString versionText = GStrings.GetString("PICKER_VERSION"); + versionText.Substitute("%s", GetVersionString()); + VersionLabel->SetText(versionText.GetChars()); +} + +double LauncherBanner::GetPreferredHeight() const +{ + return Logo->GetPreferredHeight(); +} + +void LauncherBanner::OnGeometryChanged() +{ + Logo->SetFrameGeometry(0.0, 0.0, GetWidth(), Logo->GetPreferredHeight()); + VersionLabel->SetFrameGeometry(20.0, GetHeight() - 10.0 - VersionLabel->GetPreferredHeight(), GetWidth() - 40.0, VersionLabel->GetPreferredHeight()); +} diff --git a/src/launcher/launcherbanner.h b/src/launcher/launcherbanner.h new file mode 100644 index 0000000000..9a27a5694d --- /dev/null +++ b/src/launcher/launcherbanner.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +class ImageBox; +class TextLabel; + +class LauncherBanner : public Widget +{ +public: + LauncherBanner(Widget* parent); + void UpdateLanguage(); + + double GetPreferredHeight() const; + +private: + void OnGeometryChanged() override; + + ImageBox* Logo = nullptr; + TextLabel* VersionLabel = nullptr; +}; diff --git a/src/launcher/launcherbuttonbar.cpp b/src/launcher/launcherbuttonbar.cpp new file mode 100644 index 0000000000..789881000e --- /dev/null +++ b/src/launcher/launcherbuttonbar.cpp @@ -0,0 +1,46 @@ + +#include "launcherbuttonbar.h" +#include "launcherwindow.h" +#include "gstrings.h" +#include + +LauncherButtonbar::LauncherButtonbar(LauncherWindow* parent) : Widget(parent) +{ + PlayButton = new PushButton(this); + ExitButton = new PushButton(this); + + PlayButton->OnClick = [=]() { OnPlayButtonClicked(); }; + ExitButton->OnClick = [=]() { OnExitButtonClicked(); }; +} + +void LauncherButtonbar::UpdateLanguage() +{ + PlayButton->SetText(GStrings.GetString("PICKER_PLAY")); + ExitButton->SetText(GStrings.GetString("PICKER_EXIT")); +} + +double LauncherButtonbar::GetPreferredHeight() const +{ + return 20.0 + std::max(PlayButton->GetPreferredHeight(), ExitButton->GetPreferredHeight()); +} + +void LauncherButtonbar::OnGeometryChanged() +{ + PlayButton->SetFrameGeometry(20.0, 10.0, 120.0, PlayButton->GetPreferredHeight()); + ExitButton->SetFrameGeometry(GetWidth() - 20.0 - 120.0, 10.0, 120.0, PlayButton->GetPreferredHeight()); +} + +void LauncherButtonbar::OnPlayButtonClicked() +{ + GetLauncher()->Start(); +} + +void LauncherButtonbar::OnExitButtonClicked() +{ + GetLauncher()->Exit(); +} + +LauncherWindow* LauncherButtonbar::GetLauncher() const +{ + return static_cast(Parent()); +} diff --git a/src/launcher/launcherbuttonbar.h b/src/launcher/launcherbuttonbar.h new file mode 100644 index 0000000000..4872cb6127 --- /dev/null +++ b/src/launcher/launcherbuttonbar.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class LauncherWindow; +class PushButton; + +class LauncherButtonbar : public Widget +{ +public: + LauncherButtonbar(LauncherWindow* parent); + void UpdateLanguage(); + + double GetPreferredHeight() const; + +private: + void OnGeometryChanged() override; + void OnPlayButtonClicked(); + void OnExitButtonClicked(); + + LauncherWindow* GetLauncher() const; + + PushButton* PlayButton = nullptr; + PushButton* ExitButton = nullptr; +}; diff --git a/src/launcher/launcherwindow.cpp b/src/launcher/launcherwindow.cpp new file mode 100644 index 0000000000..768872fda1 --- /dev/null +++ b/src/launcher/launcherwindow.cpp @@ -0,0 +1,109 @@ +#include "launcherwindow.h" +#include "launcherbanner.h" +#include "launcherbuttonbar.h" +#include "playgamepage.h" +#include "settingspage.h" +#include "v_video.h" +#include "version.h" +#include "i_interface.h" +#include "gstrings.h" +#include "c_cvars.h" +#include +#include +#include + +#if defined(EXTRAARGS) +CVAR(String, additional_parameters, "", CVAR_ARCHIVE | CVAR_NOSET | CVAR_GLOBALCONFIG); +#endif + +int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags) +{ + Size screenSize = GetScreenSize(); + double windowWidth = 615.0; + double windowHeight = 700.0; + + auto launcher = std::make_unique(wads, numwads, defaultiwad, autoloadflags); + launcher->SetFrameGeometry((screenSize.width - windowWidth) * 0.5, (screenSize.height - windowHeight) * 0.5, windowWidth, windowHeight); + launcher->Show(); + + DisplayWindow::RunLoop(); + + return launcher->ExecResult; +} + +LauncherWindow::LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags) : Widget(nullptr, WidgetType::Window) +{ + SetWindowTitle(GAMENAME); + + Banner = new LauncherBanner(this); + Pages = new TabWidget(this); + Buttonbar = new LauncherButtonbar(this); + + PlayGame = new PlayGamePage(this, wads, numwads, defaultiwad); + Settings = new SettingsPage(this, autoloadflags); + + Pages->AddTab(PlayGame, "Play"); + Pages->AddTab(Settings, "Settings"); + + UpdateLanguage(); + +#if defined(EXTRAARGS) + PlayGame->SetExtraArgs(static_cast(additional_parameters).GetChars()); +#endif + + Pages->SetCurrentWidget(PlayGame); + PlayGame->SetFocus(); +} + +void LauncherWindow::Start() +{ + Settings->Save(); + +#if defined(EXTRAARGS) + std::string extraargs = PlayGame->GetExtraArgs(); + if (extraargs != static_cast(additional_parameters).GetChars()) + { + additional_parameters = extraargs.c_str(); + + // To do: restart the process like the cocoa backend is doing? + } +#endif + + ExecResult = PlayGame->GetSelectedGame(); + DisplayWindow::ExitLoop(); +} + +void LauncherWindow::Exit() +{ + ExecResult = -1; + DisplayWindow::ExitLoop(); +} + +void LauncherWindow::UpdateLanguage() +{ + Pages->SetTabText(PlayGame, GStrings.GetString("PICKER_TAB_PLAY")); + Pages->SetTabText(Settings, GStrings.GetString("OPTMNU_TITLE")); + Banner->UpdateLanguage(); + PlayGame->UpdateLanguage(); + Settings->UpdateLanguage(); + Buttonbar->UpdateLanguage(); +} + +void LauncherWindow::OnClose() +{ + Exit(); +} + +void LauncherWindow::OnGeometryChanged() +{ + double top = 0.0; + double bottom = GetHeight(); + + Banner->SetFrameGeometry(0.0, top, GetWidth(), Banner->GetPreferredHeight()); + top += Banner->GetPreferredHeight(); + + bottom -= Buttonbar->GetPreferredHeight(); + Buttonbar->SetFrameGeometry(0.0, bottom, GetWidth(), Buttonbar->GetPreferredHeight()); + + Pages->SetFrameGeometry(0.0, top, GetWidth(), std::max(bottom - top, 0.0)); +} diff --git a/src/launcher/launcherwindow.h b/src/launcher/launcherwindow.h new file mode 100644 index 0000000000..8cdbc6ce77 --- /dev/null +++ b/src/launcher/launcherwindow.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include "tarray.h" +#include "zstring.h" + +class TabWidget; +class LauncherBanner; +class LauncherButtonbar; +class PlayGamePage; +class SettingsPage; +struct WadStuff; + +class LauncherWindow : public Widget +{ +public: + static int ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags); + + LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags); + void UpdateLanguage(); + + void Start(); + void Exit(); + +private: + void OnClose() override; + void OnGeometryChanged() override; + + LauncherBanner* Banner = nullptr; + TabWidget* Pages = nullptr; + LauncherButtonbar* Buttonbar = nullptr; + + PlayGamePage* PlayGame = nullptr; + SettingsPage* Settings = nullptr; + + int ExecResult = -1; +}; diff --git a/src/launcher/playgamepage.cpp b/src/launcher/playgamepage.cpp new file mode 100644 index 0000000000..55d777b737 --- /dev/null +++ b/src/launcher/playgamepage.cpp @@ -0,0 +1,115 @@ + +#include "playgamepage.h" +#include "launcherwindow.h" +#include "i_interface.h" +#include "gstrings.h" +#include "version.h" +#include +#include +#include + +PlayGamePage::PlayGamePage(LauncherWindow* launcher, WadStuff* wads, int numwads, int defaultiwad) : Widget(nullptr), Launcher(launcher) +{ + WelcomeLabel = new TextLabel(this); + SelectLabel = new TextLabel(this); +#if defined(EXTRAARGS) + ParametersLabel = new TextLabel(this); +#endif + GamesList = new ListView(this); +#if defined(EXTRAARGS) + ParametersEdit = new LineEdit(this); +#endif + + for (int i = 0; i < numwads; i++) + { + const char* filepart = strrchr(wads[i].Path.GetChars(), '/'); + if (filepart == NULL) + filepart = wads[i].Path.GetChars(); + else + filepart++; + + FString work; + if (*filepart) work.Format("%s (%s)", wads[i].Name.GetChars(), filepart); + else work = wads[i].Name.GetChars(); + + GamesList->AddItem(work.GetChars()); + } + + if (defaultiwad >= 0 && defaultiwad < numwads) + { + GamesList->SetSelectedItem(defaultiwad); + GamesList->ScrollToItem(defaultiwad); + } + + GamesList->OnActivated = [=]() { OnGamesListActivated(); }; +} + +#if defined(EXTRAARGS) +void PlayGamePage::SetExtraArgs(const std::string& args) +{ + ParametersEdit->SetText(args); +} + +std::string PlayGamePage::GetExtraArgs() +{ + return ParametersEdit->GetText(); +} +#endif + +int PlayGamePage::GetSelectedGame() +{ + return GamesList->GetSelectedItem(); +} + +void PlayGamePage::UpdateLanguage() +{ + SelectLabel->SetText(GStrings.GetString("PICKER_SELECT")); +#if defined(EXTRAARGS) + ParametersLabel->SetText(GStrings.GetString("PICKER_ADDPARM")); +#endif + FString welcomeText = GStrings.GetString("PICKER_WELCOME"); + welcomeText.Substitute("%s", GAMENAME); + WelcomeLabel->SetText(welcomeText.GetChars()); +} + +void PlayGamePage::OnGamesListActivated() +{ + Launcher->Start(); +} + +void PlayGamePage::OnSetFocus() +{ + GamesList->SetFocus(); +} + +void PlayGamePage::OnGeometryChanged() +{ + double y = 10.0; + + WelcomeLabel->SetFrameGeometry(0.0, y, GetWidth(), WelcomeLabel->GetPreferredHeight()); + y += WelcomeLabel->GetPreferredHeight(); + + y += 10.0; + + SelectLabel->SetFrameGeometry(0.0, y, GetWidth(), SelectLabel->GetPreferredHeight()); + y += SelectLabel->GetPreferredHeight(); + + double listViewTop = y; + + y = GetHeight() - 10.0; + +#if defined(EXTRAARGS) + double editHeight = 24.0; + y -= editHeight; + ParametersEdit->SetFrameGeometry(0.0, y, GetWidth(), editHeight); + y -= 5.0; + + double labelHeight = ParametersLabel->GetPreferredHeight(); + y -= labelHeight; + ParametersLabel->SetFrameGeometry(0.0, y, GetWidth(), labelHeight); + y -= 10.0; +#endif + + double listViewBottom = y - 10.0; + GamesList->SetFrameGeometry(0.0, listViewTop, GetWidth(), std::max(listViewBottom - listViewTop, 0.0)); +} diff --git a/src/launcher/playgamepage.h b/src/launcher/playgamepage.h new file mode 100644 index 0000000000..9378c37987 --- /dev/null +++ b/src/launcher/playgamepage.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +// #define EXTRAARGS + +class LauncherWindow; +class TextLabel; +class ListView; +class LineEdit; +struct WadStuff; + +class PlayGamePage : public Widget +{ +public: + PlayGamePage(LauncherWindow* launcher, WadStuff* wads, int numwads, int defaultiwad); + void UpdateLanguage(); + +#if defined(EXTRAARGS) + void SetExtraArgs(const std::string& args); + std::string GetExtraArgs(); +#endif + + int GetSelectedGame(); + +private: + void OnGeometryChanged() override; + void OnSetFocus() override; + void OnGamesListActivated(); + + LauncherWindow* Launcher = nullptr; + + TextLabel* WelcomeLabel = nullptr; + TextLabel* SelectLabel = nullptr; +#if defined(EXTRAARGS) + TextLabel* ParametersLabel = nullptr; +#endif + ListView* GamesList = nullptr; +#if defined(EXTRAARGS) + LineEdit* ParametersEdit = nullptr; +#endif +}; diff --git a/src/launcher/settingspage.cpp b/src/launcher/settingspage.cpp new file mode 100644 index 0000000000..9cd89bcd01 --- /dev/null +++ b/src/launcher/settingspage.cpp @@ -0,0 +1,207 @@ + +#include "settingspage.h" +#include "launcherwindow.h" +#include "gstrings.h" +#include "i_interface.h" +#include "v_video.h" +#include +#include +#include +#include + +#ifdef RENDER_BACKENDS +EXTERN_CVAR(Int, vid_preferbackend); +#endif + +EXTERN_CVAR(String, language) +EXTERN_CVAR(Bool, queryiwad); + +SettingsPage::SettingsPage(LauncherWindow* launcher, int* autoloadflags) : Widget(nullptr), Launcher(launcher), AutoloadFlags(autoloadflags) +{ + LangLabel = new TextLabel(this); + GeneralLabel = new TextLabel(this); + ExtrasLabel = new TextLabel(this); + FullscreenCheckbox = new CheckboxLabel(this); + DisableAutoloadCheckbox = new CheckboxLabel(this); + DontAskAgainCheckbox = new CheckboxLabel(this); + LightsCheckbox = new CheckboxLabel(this); + BrightmapsCheckbox = new CheckboxLabel(this); + WidescreenCheckbox = new CheckboxLabel(this); + +#ifdef RENDER_BACKENDS + BackendLabel = new TextLabel(this); + VulkanCheckbox = new CheckboxLabel(this); + OpenGLCheckbox = new CheckboxLabel(this); + GLESCheckbox = new CheckboxLabel(this); +#endif + + FullscreenCheckbox->SetChecked(vid_fullscreen); + DontAskAgainCheckbox->SetChecked(!queryiwad); + + int flags = *autoloadflags; + DisableAutoloadCheckbox->SetChecked(flags & 1); + LightsCheckbox->SetChecked(flags & 2); + BrightmapsCheckbox->SetChecked(flags & 4); + WidescreenCheckbox->SetChecked(flags & 8); + +#ifdef RENDER_BACKENDS + OpenGLCheckbox->SetRadioStyle(true); + VulkanCheckbox->SetRadioStyle(true); + GLESCheckbox->SetRadioStyle(true); + OpenGLCheckbox->FuncChanged = [this](bool on) { if (on) { VulkanCheckbox->SetChecked(false); GLESCheckbox->SetChecked(false); }}; + VulkanCheckbox->FuncChanged = [this](bool on) { if (on) { OpenGLCheckbox->SetChecked(false); GLESCheckbox->SetChecked(false); }}; + GLESCheckbox->FuncChanged = [this](bool on) { if (on) { VulkanCheckbox->SetChecked(false); OpenGLCheckbox->SetChecked(false); }}; + switch (vid_preferbackend) + { + case 0: + OpenGLCheckbox->SetChecked(true); + break; + case 1: + VulkanCheckbox->SetChecked(true); + break; + case 2: + GLESCheckbox->SetChecked(true); + break; + } +#endif + + LangList = new ListView(this); + + try + { + auto data = LoadWidgetData("menudef.txt"); + FScanner sc; + sc.OpenMem("menudef.txt", data); + while (sc.GetString()) + { + if (sc.Compare("OptionString")) + { + sc.MustGetString(); + if (sc.Compare("LanguageOptions")) + { + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FString iso = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + if(iso.CompareNoCase("auto")) + languages.push_back(std::make_pair(iso, FString(sc.String))); + } + } + } + } + } + catch (const std::exception& ex) + { + hideLanguage = true; + } + int i = 0; + for (auto& l : languages) + { + LangList->AddItem(l.second.GetChars()); + if (!l.first.CompareNoCase(::language)) + LangList->SetSelectedItem(i); + i++; + } + + LangList->OnChanged = [=](int i) { OnLanguageChanged(i); }; +} + +void SettingsPage::Save() +{ + vid_fullscreen = FullscreenCheckbox->GetChecked(); + queryiwad = !DontAskAgainCheckbox->GetChecked(); + + int flags = 0; + if (DisableAutoloadCheckbox->GetChecked()) flags |= 1; + if (LightsCheckbox->GetChecked()) flags |= 2; + if (BrightmapsCheckbox->GetChecked()) flags |= 4; + if (WidescreenCheckbox->GetChecked()) flags |= 8; + *AutoloadFlags = flags; + +#ifdef RENDER_BACKENDS + int v = 1; + if (OpenGLCheckbox->GetChecked()) v = 0; + else if (VulkanCheckbox->GetChecked()) v = 1; + else if (GLESCheckbox->GetChecked()) v = 2; + if (v != vid_preferbackend) vid_preferbackend = v; +#endif +} + +void SettingsPage::UpdateLanguage() +{ + LangLabel->SetText(GStrings.GetString("OPTMNU_LANGUAGE")); + GeneralLabel->SetText(GStrings.GetString("PICKER_GENERAL")); + ExtrasLabel->SetText(GStrings.GetString("PICKER_EXTRA")); + FullscreenCheckbox->SetText(GStrings.GetString("PICKER_FULLSCREEN")); + DisableAutoloadCheckbox->SetText(GStrings.GetString("PICKER_NOAUTOLOAD")); + DontAskAgainCheckbox->SetText(GStrings.GetString("PICKER_DONTASK")); + LightsCheckbox->SetText(GStrings.GetString("PICKER_LIGHTS")); + BrightmapsCheckbox->SetText(GStrings.GetString("PICKER_BRIGHTMAPS")); + WidescreenCheckbox->SetText(GStrings.GetString("PICKER_WIDESCREEN")); + +#ifdef RENDER_BACKENDS + BackendLabel->SetText(GStrings.GetString("PICKER_PREFERBACKEND")); + VulkanCheckbox->SetText(GStrings.GetString("OPTVAL_VULKAN")); + OpenGLCheckbox->SetText(GStrings.GetString("OPTVAL_OPENGL")); + GLESCheckbox->SetText(GStrings.GetString("OPTVAL_OPENGLES")); +#endif +} + +void SettingsPage::OnLanguageChanged(int i) +{ + ::language = languages[i].first.GetChars(); + GStrings.UpdateLanguage(::language); // CVAR callbacks are not active yet. + UpdateLanguage(); + Update(); + Launcher->UpdateLanguage(); +} + +void SettingsPage::OnGeometryChanged() +{ + double panelWidth = 200.0; + double y = 0.0; + double w = GetWidth(); + double h = GetHeight(); + + GeneralLabel->SetFrameGeometry(0.0, y, 190.0, GeneralLabel->GetPreferredHeight()); + ExtrasLabel->SetFrameGeometry(w - panelWidth, y, panelWidth, ExtrasLabel->GetPreferredHeight()); + y += GeneralLabel->GetPreferredHeight(); + + FullscreenCheckbox->SetFrameGeometry(0.0, y, 190.0, FullscreenCheckbox->GetPreferredHeight()); + LightsCheckbox->SetFrameGeometry(w - panelWidth, y, panelWidth, LightsCheckbox->GetPreferredHeight()); + y += FullscreenCheckbox->GetPreferredHeight(); + + DisableAutoloadCheckbox->SetFrameGeometry(0.0, y, 190.0, DisableAutoloadCheckbox->GetPreferredHeight()); + BrightmapsCheckbox->SetFrameGeometry(w - panelWidth, y, panelWidth, BrightmapsCheckbox->GetPreferredHeight()); + y += DisableAutoloadCheckbox->GetPreferredHeight(); + + DontAskAgainCheckbox->SetFrameGeometry(0.0, y, 190.0, DontAskAgainCheckbox->GetPreferredHeight()); + WidescreenCheckbox->SetFrameGeometry(w - panelWidth, y, panelWidth, WidescreenCheckbox->GetPreferredHeight()); + y += DontAskAgainCheckbox->GetPreferredHeight(); + +#ifdef RENDER_BACKENDS + double x = w / 2 - panelWidth / 2; + y = 0; + BackendLabel->SetFrameGeometry(x, y, 190.0, BackendLabel->GetPreferredHeight()); + y += BackendLabel->GetPreferredHeight(); + + VulkanCheckbox->SetFrameGeometry(x, y, 190.0, VulkanCheckbox->GetPreferredHeight()); + y += VulkanCheckbox->GetPreferredHeight(); + + OpenGLCheckbox->SetFrameGeometry(x, y, 190.0, OpenGLCheckbox->GetPreferredHeight()); + y += OpenGLCheckbox->GetPreferredHeight(); + + GLESCheckbox->SetFrameGeometry(x, y, 190.0, GLESCheckbox->GetPreferredHeight()); + y += GLESCheckbox->GetPreferredHeight(); +#endif + + if (!hideLanguage) + { + LangLabel->SetFrameGeometry(0.0, y, w, LangLabel->GetPreferredHeight()); + y += LangLabel->GetPreferredHeight(); + LangList->SetFrameGeometry(0.0, y, w, std::max(h - y, 0.0)); + } +} diff --git a/src/launcher/settingspage.h b/src/launcher/settingspage.h new file mode 100644 index 0000000000..77a6ff048e --- /dev/null +++ b/src/launcher/settingspage.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include "gstrings.h" + +// #define RENDER_BACKENDS + +class LauncherWindow; +class TextLabel; +class CheckboxLabel; +class ListView; + +class SettingsPage : public Widget +{ +public: + SettingsPage(LauncherWindow* launcher, int* autoloadflags); + void UpdateLanguage(); + + void Save(); + +private: + void OnLanguageChanged(int i); + void OnGeometryChanged() override; + + LauncherWindow* Launcher = nullptr; + + TextLabel* LangLabel = nullptr; + TextLabel* GeneralLabel = nullptr; + TextLabel* ExtrasLabel = nullptr; + CheckboxLabel* FullscreenCheckbox = nullptr; + CheckboxLabel* DisableAutoloadCheckbox = nullptr; + CheckboxLabel* DontAskAgainCheckbox = nullptr; + CheckboxLabel* LightsCheckbox = nullptr; + CheckboxLabel* BrightmapsCheckbox = nullptr; + CheckboxLabel* WidescreenCheckbox = nullptr; +#ifdef RENDER_BACKENDS + TextLabel* BackendLabel = nullptr; + CheckboxLabel* VulkanCheckbox = nullptr; + CheckboxLabel* OpenGLCheckbox = nullptr; + CheckboxLabel* GLESCheckbox = nullptr; +#endif + ListView* LangList = nullptr; + + int* AutoloadFlags = nullptr; + + TArray> languages; + bool hideLanguage = false; +}; diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index a4ac6bc39c..e918c24082 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -66,7 +66,7 @@ void cht_DoMDK(player_t *player, const char *mod) { if (player->mo == NULL) { - Printf("%s\n", GStrings("TXT_WHAT_KILL")); + Printf("%s\n", GStrings.GetString("TXT_WHAT_KILL")); } else if (!deathmatch) { @@ -119,41 +119,41 @@ void cht_DoCheat (player_t *player, int cheat) case CHT_GOD: player->cheats ^= CF_GODMODE; if (player->cheats & CF_GODMODE) - msg = GStrings("STSTR_DQDON"); + msg = GStrings.GetString("STSTR_DQDON"); else - msg = GStrings("STSTR_DQDOFF"); + msg = GStrings.GetString("STSTR_DQDOFF"); break; case CHT_BUDDHA: player->cheats ^= CF_BUDDHA; if (player->cheats & CF_BUDDHA) - msg = GStrings("TXT_BUDDHAON"); + msg = GStrings.GetString("TXT_BUDDHAON"); else - msg = GStrings("TXT_BUDDHAOFF"); + msg = GStrings.GetString("TXT_BUDDHAOFF"); break; case CHT_GOD2: player->cheats ^= CF_GODMODE2; if (player->cheats & CF_GODMODE2) - msg = GStrings("STSTR_DQD2ON"); + msg = GStrings.GetString("STSTR_DQD2ON"); else - msg = GStrings("STSTR_DQD2OFF"); + msg = GStrings.GetString("STSTR_DQD2OFF"); break; case CHT_BUDDHA2: player->cheats ^= CF_BUDDHA2; if (player->cheats & CF_BUDDHA2) - msg = GStrings("TXT_BUDDHA2ON"); + msg = GStrings.GetString("TXT_BUDDHA2ON"); else - msg = GStrings("TXT_BUDDHA2OFF"); + msg = GStrings.GetString("TXT_BUDDHA2OFF"); break; case CHT_NOCLIP: player->cheats ^= CF_NOCLIP; if (player->cheats & CF_NOCLIP) - msg = GStrings("STSTR_NCON"); + msg = GStrings.GetString("STSTR_NCON"); else - msg = GStrings("STSTR_NCOFF"); + msg = GStrings.GetString("STSTR_NCOFF"); break; case CHT_NOCLIP2: @@ -161,12 +161,12 @@ void cht_DoCheat (player_t *player, int cheat) if (player->cheats & CF_NOCLIP2) { player->cheats |= CF_NOCLIP; - msg = GStrings("STSTR_NC2ON"); + msg = GStrings.GetString("STSTR_NC2ON"); } else { player->cheats &= ~CF_NOCLIP; - msg = GStrings("STSTR_NC2OFF"); + msg = GStrings.GetString("STSTR_NC2OFF"); } if (player->mo->Vel.X == 0) player->mo->Vel.X = MinVel; // force some lateral movement so that internal variables are up to date break; @@ -174,9 +174,9 @@ void cht_DoCheat (player_t *player, int cheat) case CHT_NOVELOCITY: player->cheats ^= CF_NOVELOCITY; if (player->cheats & CF_NOVELOCITY) - msg = GStrings("TXT_LEADBOOTSON"); + msg = GStrings.GetString("TXT_LEADBOOTSON"); else - msg = GStrings("TXT_LEADBOOTSOFF"); + msg = GStrings.GetString("TXT_LEADBOOTSOFF"); break; case CHT_FLY: @@ -187,13 +187,13 @@ void cht_DoCheat (player_t *player, int cheat) { player->mo->flags |= MF_NOGRAVITY; player->mo->flags2 |= MF2_FLY; - msg = GStrings("TXT_LIGHTER"); + msg = GStrings.GetString("TXT_LIGHTER"); } else { player->mo->flags &= ~MF_NOGRAVITY; player->mo->flags2 &= ~MF2_FLY; - msg = GStrings("TXT_GRAVITY"); + msg = GStrings.GetString("TXT_GRAVITY"); } } break; @@ -206,25 +206,25 @@ void cht_DoCheat (player_t *player, int cheat) case CHT_NOTARGET: player->cheats ^= CF_NOTARGET; if (player->cheats & CF_NOTARGET) - msg = GStrings("TXT_NOTARGET_ON"); + msg = GStrings.GetString("TXT_NOTARGET_ON"); else - msg = GStrings("TXT_NOTARGET_OFF"); + msg = GStrings.GetString("TXT_NOTARGET_OFF"); break; case CHT_ANUBIS: player->cheats ^= CF_FRIGHTENING; if (player->cheats & CF_FRIGHTENING) - msg = GStrings("TXT_ANUBIS_ON"); + msg = GStrings.GetString("TXT_ANUBIS_ON"); else - msg = GStrings("TXT_ANUBIS_OFF"); + msg = GStrings.GetString("TXT_ANUBIS_OFF"); break; case CHT_CHASECAM: player->cheats ^= CF_CHASECAM; if (player->cheats & CF_CHASECAM) - msg = GStrings("TXT_CHASECAM_ON"); + msg = GStrings.GetString("TXT_CHASECAM_ON"); else - msg = GStrings("TXT_CHASECAM_OFF"); + msg = GStrings.GetString("TXT_CHASECAM_OFF"); R_ResetViewInterpolation (); break; @@ -236,7 +236,7 @@ void cht_DoCheat (player_t *player, int cheat) { player->mo->GiveInventoryType (type); } - msg = GStrings("STSTR_CHOPPERS"); + msg = GStrings.GetString("STSTR_CHOPPERS"); } // [RH] The original cheat also set powers[pw_invulnerability] to true. // Since this is a timer and not a boolean, it effectively turned off @@ -251,12 +251,12 @@ void cht_DoCheat (player_t *player, int cheat) if (item != NULL) { item->Destroy (); - msg = GStrings("TXT_CHEATPOWEROFF"); + msg = GStrings.GetString("TXT_CHEATPOWEROFF"); } else { player->mo->GiveInventoryType (PClass::FindActor(NAME_PowerWeaponLevel2)); - msg = GStrings("TXT_CHEATPOWERON"); + msg = GStrings.GetString("TXT_CHEATPOWERON"); } } break; @@ -267,7 +267,7 @@ void cht_DoCheat (player_t *player, int cheat) cht_Give (player, "ammo"); cht_Give (player, "keys"); cht_Give (player, "armor"); - msg = GStrings("STSTR_KFAADDED"); + msg = GStrings.GetString("STSTR_KFAADDED"); break; case CHT_IDFA: @@ -275,7 +275,7 @@ void cht_DoCheat (player_t *player, int cheat) cht_Give (player, "weapons"); cht_Give (player, "ammo"); cht_Give (player, "armor"); - msg = GStrings("STSTR_FAADDED"); + msg = GStrings.GetString("STSTR_FAADDED"); break; case CHT_BEHOLDV: @@ -320,7 +320,7 @@ void cht_DoCheat (player_t *player, int cheat) item->Destroy (); } } - msg = GStrings("STSTR_BEHOLDX"); + msg = GStrings.GetString("STSTR_BEHOLDX"); break; case CHT_MASSACRE: @@ -330,12 +330,12 @@ void cht_DoCheat (player_t *player, int cheat) // killough 3/22/98: make more intelligent about plural if (killcount == 1) { - msg = GStrings(cheat == CHT_MASSACRE? "TXT_MONSTER_KILLED" : "TXT_BADDIE_KILLED"); + msg = GStrings.GetString(cheat == CHT_MASSACRE? "TXT_MONSTER_KILLED" : "TXT_BADDIE_KILLED"); } else { // Note: Do not use the language string directly as a format template! - smsg = GStrings(cheat == CHT_MASSACRE? "TXT_MONSTERS_KILLED" : "TXT_BADDIES_KILLED"); + smsg = GStrings.GetString(cheat == CHT_MASSACRE? "TXT_MONSTERS_KILLED" : "TXT_BADDIES_KILLED"); FStringf countstr("%d", killcount); smsg.Substitute("%d", countstr); msg = smsg.GetChars(); @@ -347,13 +347,13 @@ void cht_DoCheat (player_t *player, int cheat) if (player->mo != NULL && player->playerstate == PST_LIVE) { player->health = player->mo->health = player->mo->GetDefault()->health; - msg = GStrings("TXT_CHEATHEALTH"); + msg = GStrings.GetString("TXT_CHEATHEALTH"); } break; case CHT_KEYS: cht_Give (player, "keys"); - msg = GStrings("TXT_CHEATKEYS"); + msg = GStrings.GetString("TXT_CHEATKEYS"); break; // [GRB] @@ -362,7 +362,7 @@ void cht_DoCheat (player_t *player, int cheat) { if (player->mo->IsKindOf("PlayerChunk")) { - Printf("%s\n", GStrings("TXT_NO_RESURRECT")); + Printf("%s\n", GStrings.GetString("TXT_NO_RESURRECT")); return; } else @@ -374,52 +374,52 @@ void cht_DoCheat (player_t *player, int cheat) case CHT_GIMMIEA: cht_Give (player, "ArtiInvulnerability"); - msg = GStrings("TAG_ARTIINVULNERABILITY"); + msg = GStrings.GetString("TAG_ARTIINVULNERABILITY"); break; case CHT_GIMMIEB: cht_Give (player, "ArtiInvisibility"); - msg = GStrings("TAG_ARTIINVISIBILITY"); + msg = GStrings.GetString("TAG_ARTIINVISIBILITY"); break; case CHT_GIMMIEC: cht_Give (player, "ArtiHealth"); - msg = GStrings("TAG_ARTIHEALTH"); + msg = GStrings.GetString("TAG_ARTIHEALTH"); break; case CHT_GIMMIED: cht_Give (player, "ArtiSuperHealth"); - msg = GStrings("TAG_ARTISUPERHEALTH"); + msg = GStrings.GetString("TAG_ARTISUPERHEALTH"); break; case CHT_GIMMIEE: cht_Give (player, "ArtiTomeOfPower"); - msg = GStrings("TAG_ARTITOMEOFPOWER"); + msg = GStrings.GetString("TAG_ARTITOMEOFPOWER"); break; case CHT_GIMMIEF: cht_Give (player, "ArtiTorch"); - msg = GStrings("TAG_ARTITORCH"); + msg = GStrings.GetString("TAG_ARTITORCH"); break; case CHT_GIMMIEG: cht_Give (player, "ArtiTimeBomb"); - msg = GStrings("TAG_ARTIFIREBOMB"); + msg = GStrings.GetString("TAG_ARTIFIREBOMB"); break; case CHT_GIMMIEH: cht_Give (player, "ArtiEgg"); - msg = GStrings("TAG_ARTIEGG"); + msg = GStrings.GetString("TAG_ARTIEGG"); break; case CHT_GIMMIEI: cht_Give (player, "ArtiFly"); - msg = GStrings("TAG_ARTIFLY"); + msg = GStrings.GetString("TAG_ARTIFLY"); break; case CHT_GIMMIEJ: cht_Give (player, "ArtiTeleport"); - msg = GStrings("TAG_ARTITELEPORT"); + msg = GStrings.GetString("TAG_ARTITELEPORT"); break; case CHT_GIMMIEZ: @@ -427,17 +427,17 @@ void cht_DoCheat (player_t *player, int cheat) { cht_Give (player, "artifacts"); } - msg = GStrings("TAG_ALL_ARTIFACTS"); + msg = GStrings.GetString("TAG_ALL_ARTIFACTS"); break; case CHT_TAKEWEAPS: cht_Takeweaps(player); - msg = GStrings("TXT_CHEATIDKFA"); + msg = GStrings.GetString("TXT_CHEATIDKFA"); break; case CHT_NOWUDIE: cht_Suicide (player); - msg = GStrings("TXT_CHEATIDDQD"); + msg = GStrings.GetString("TXT_CHEATIDDQD"); break; case CHT_ALLARTI: @@ -445,18 +445,18 @@ void cht_DoCheat (player_t *player, int cheat) { cht_Give (player, "artifacts"); } - msg = GStrings("TXT_CHEATARTIFACTS3"); + msg = GStrings.GetString("TXT_CHEATARTIFACTS3"); break; case CHT_PUZZLE: cht_Give (player, "puzzlepieces"); - msg = GStrings("TXT_CHEATARTIFACTS3"); + msg = GStrings.GetString("TXT_CHEATARTIFACTS3"); break; case CHT_MDK: if (player->mo == nullptr) { - Printf ("%s\n", GStrings("TXT_WHAT_KILL")); + Printf ("%s\n", GStrings.GetString("TXT_WHAT_KILL")); return; } else if (!deathmatch) @@ -471,7 +471,7 @@ void cht_DoCheat (player_t *player, int cheat) case CHT_DONNYTRUMP: cht_Give (player, "HealthTraining"); - msg = GStrings("TXT_MIDASTOUCH"); + msg = GStrings.GetString("TXT_MIDASTOUCH"); break; case CHT_LEGO: @@ -507,34 +507,34 @@ void cht_DoCheat (player_t *player, int cheat) cht_Give (player, "MedPatch"); cht_Give (player, "MedicalKit"); cht_Give (player, "SurgeryKit"); - msg = GStrings("TXT_GOTSTUFF"); + msg = GStrings.GetString("TXT_GOTSTUFF"); break; case CHT_PUMPUPP: cht_Give (player, "AmmoSatchel"); - msg = GStrings("TXT_GOTSTUFF"); + msg = GStrings.GetString("TXT_GOTSTUFF"); break; case CHT_PUMPUPS: cht_Give (player, "UpgradeStamina", 10); cht_Give (player, "UpgradeAccuracy"); - msg = GStrings("TXT_GOTSTUFF"); + msg = GStrings.GetString("TXT_GOTSTUFF"); break; case CHT_CLEARFROZENPROPS: player->cheats &= ~(CF_FROZEN|CF_TOTALLYFROZEN); - msg = GStrings("TXT_NOT_FROZEN"); + msg = GStrings.GetString("TXT_NOT_FROZEN"); break; case CHT_FREEZE: globalchangefreeze ^= 1; if (globalfreeze ^ globalchangefreeze) { - msg = GStrings("TXT_FREEZEON"); + msg = GStrings.GetString("TXT_FREEZEON"); } else { - msg = GStrings("TXT_FREEZEOFF"); + msg = GStrings.GetString("TXT_FREEZEOFF"); } break; } @@ -546,7 +546,7 @@ void cht_DoCheat (player_t *player, int cheat) Printf ("%s\n", msg); else if (cheat != CHT_CHASECAM) { - FString message = GStrings("TXT_X_CHEATS"); + FString message = GStrings.GetString("TXT_X_CHEATS"); message.Substitute("%s", player->userinfo.GetName()); Printf("%s: %s\n", message.GetChars(), msg); } @@ -626,10 +626,13 @@ class DSuicider : public DThinker double plyrdmgfact = Pawn->DamageFactor; Pawn->DamageFactor = 1.; P_DamageMobj (Pawn, Pawn, Pawn, TELEFRAG_DAMAGE, NAME_Suicide); - Pawn->DamageFactor = plyrdmgfact; - if (Pawn->health <= 0) + if (Pawn != nullptr) { - Pawn->flags &= ~MF_SHOOTABLE; + Pawn->DamageFactor = plyrdmgfact; + if (Pawn->health <= 0) + { + Pawn->flags &= ~MF_SHOOTABLE; + } } Destroy(); } @@ -676,6 +679,6 @@ CCMD (mdk) return; const char *name = argv.argc() > 1 ? argv[1] : ""; - Net_WriteByte (DEM_MDK); + Net_WriteInt8 (DEM_MDK); Net_WriteString(name); } diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 45af80cec7..1b451486bf 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -98,9 +98,8 @@ void M_FindResponseFile (void) else { char **argv; - TArray file; + FileSys::FileData file; int argc = 0; - int size; size_t argsize = 0; int index; @@ -117,10 +116,8 @@ void M_FindResponseFile (void) else { Printf ("Found response file %s!\n", Args->GetArg(i) + 1); - size = (int)fr.GetLength(); - file = fr.Read (size); - file[size] = 0; - argsize = ParseCommandLine ((char*)file.Data(), &argc, NULL); + file = fr.ReadPadded(1); + argsize = ParseCommandLine (file.string(), &argc, nullptr); } } else @@ -132,7 +129,7 @@ void M_FindResponseFile (void) { argv = (char **)M_Malloc (argc*sizeof(char *) + argsize); argv[0] = (char *)argv + argc*sizeof(char *); - ParseCommandLine ((char*)file.Data(), NULL, argv); + ParseCommandLine (file.string(), nullptr, argv); // Create a new argument vector FArgs *newargs = new FArgs; @@ -281,7 +278,7 @@ bool M_SaveDefaults (const char *filename) GameConfig->ArchiveGlobalData (); if (gameinfo.ConfigName.IsNotEmpty()) { - GameConfig->ArchiveGameData (gameinfo.ConfigName); + GameConfig->ArchiveGameData (gameinfo.ConfigName.GetChars()); } success = GameConfig->WriteConfigFile (); if (filename != nullptr) @@ -318,7 +315,7 @@ UNSAFE_CCMD (writeini) CCMD(openconfig) { M_SaveDefaults(nullptr); - I_OpenShellFolder(ExtractFilePath(GameConfig->GetPathName())); + I_OpenShellFolder(ExtractFilePath(GameConfig->GetPathName()).GetChars()); } // @@ -522,7 +519,7 @@ void WritePNGfile (FileWriter *file, const uint8_t *buffer, const PalEntry *pale !M_AppendPNGText (file, "Software", software) || !M_FinishPNG (file)) { - Printf ("%s\n", GStrings("TXT_SCREENSHOTERR")); + Printf ("%s\n", GStrings.GetString("TXT_SCREENSHOTERR")); } } @@ -537,7 +534,7 @@ static bool FindFreeName (FString &fullname, const char *extension) for (i = 0; i <= 9999; i++) { - const char *gamename = gameinfo.ConfigName; + const char *gamename = gameinfo.ConfigName.GetChars(); time_t now; tm *tm; @@ -601,8 +598,8 @@ void M_ScreenShot (const char *filename) autoname += '/'; } } - autoname = NicePath(autoname); - CreatePath(autoname); + autoname = NicePath(autoname.GetChars()); + CreatePath(autoname.GetChars()); if (!FindFreeName (autoname, writepcx ? "pcx" : "png")) { Printf ("M_ScreenShot: Delete some screenshots\n"); @@ -623,7 +620,7 @@ void M_ScreenShot (const char *filename) auto buffer = screen->GetScreenshotBuffer(pitch, color_type, gamma); if (buffer.Size() > 0) { - file = FileWriter::Open(autoname); + file = FileWriter::Open(autoname.GetChars()); if (file == NULL) { Printf ("Could not open %s\n", autoname.GetChars()); @@ -687,9 +684,9 @@ CCMD(openscreenshots) autoname += '/'; } } - autoname = NicePath(autoname); + autoname = NicePath(autoname.GetChars()); - CreatePath(autoname); + CreatePath(autoname.GetChars()); I_OpenShellFolder(autoname.GetChars()); } diff --git a/src/maploader/compatibility.cpp b/src/maploader/compatibility.cpp index 2a0fa07491..802ec3465e 100644 --- a/src/maploader/compatibility.cpp +++ b/src/maploader/compatibility.cpp @@ -127,6 +127,7 @@ static FCompatOption Options[] = { "noslopeid", BCOMPATF_NOSLOPEID, SLOT_BCOMPAT }, { "clipmidtex", BCOMPATF_CLIPMIDTEX, SLOT_BCOMPAT }, { "nosectionmerge", BCOMPATF_NOSECTIONMERGE, SLOT_BCOMPAT }, + { "nomirrors", BCOMPATF_NOMIRRORS, SLOT_BCOMPAT }, // list copied from g_mapinfo.cpp @@ -292,13 +293,19 @@ FName MapLoader::CheckCompatibility(MapData *map) Level->ib_compatflags = 0; // When playing Doom IWAD levels force BCOMPATF_NOSECTIONMERGE, COMPAT_SHORTTEX and COMPATF_LIGHT. - // I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. BCOMPATF_NOSECTIONMERGE is mainly for MAP18's sector 0 + // I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. // TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD. - if (fileSystem.GetFileContainer(map->lumpnum) == fileSystem.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM) + if (fileSystem.GetFileContainer(map->lumpnum) == fileSystem.GetIwadNum()) { - Level->ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT; - Level->ib_compatflags = BCOMPATF_NOSECTIONMERGE; - if (gameinfo.flags & GI_COMPATSTAIRS) Level->ii_compatflags |= COMPATF_STAIRINDEX; + if ((gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM) + { + Level->ii_compatflags = COMPATF_SHORTTEX | COMPATF_LIGHT; + if (gameinfo.flags & GI_COMPATSTAIRS) Level->ii_compatflags |= COMPATF_STAIRINDEX; + } + if (gameinfo.flags & GI_NOSECTIONMERGE) + { + //Level->ib_compatflags |= BCOMPATF_NOSECTIONMERGE; + } } map->GetChecksum(md5.Bytes); diff --git a/src/maploader/edata.cpp b/src/maploader/edata.cpp index 3bc4928f03..044fb08115 100644 --- a/src/maploader/edata.cpp +++ b/src/maploader/edata.cpp @@ -520,7 +520,7 @@ void MapLoader::InitED() FScanner sc; if (filename.IsEmpty()) return; - int lump = fileSystem.CheckNumForFullName(filename, true, ns_global); + int lump = fileSystem.CheckNumForFullName(filename.GetChars(), true, FileSys::ns_global); if (lump == -1) return; sc.OpenLumpNum(lump); @@ -659,7 +659,7 @@ void MapLoader::LoadMapinfoACSLump() { if (Level->info->acsName.IsNotEmpty()) { - int lump = fileSystem.CheckNumForName(Level->info->acsName); + int lump = fileSystem.CheckNumForName(Level->info->acsName.GetChars()); if (lump >= 0) Level->Behaviors.LoadModule(lump); } } diff --git a/src/maploader/glnodes.cpp b/src/maploader/glnodes.cpp index 21da9462a3..b41b22c0b9 100644 --- a/src/maploader/glnodes.cpp +++ b/src/maploader/glnodes.cpp @@ -42,7 +42,7 @@ #endif -#include +#include #include "m_argv.h" #include "c_dispatch.h" @@ -60,6 +60,7 @@ #include "g_levellocals.h" #include "i_time.h" #include "maploader.h" +#include "fs_findfile.h" EXTERN_CVAR(Bool, gl_cachenodes) EXTERN_CVAR(Float, gl_cachetime) @@ -208,7 +209,7 @@ bool MapLoader::LoadGLVertexes(FileReader &lump) auto gllen=lump.GetLength(); if (gllen < 4) return false; - auto gldata = glbuf.Data(); + auto gldata = glbuf.bytes(); if (*(int *)gldata == gNd5) { @@ -287,13 +288,13 @@ bool MapLoader::LoadGLSegs(FileReader &lump) const unsigned numverts = Level->vertexes.Size(); const unsigned numlines = Level->lines.Size(); - if (!format5 && memcmp(data.Data(), "gNd3", 4)) + if (!format5 && memcmp(data.data(), "gNd3", 4)) { numsegs/=sizeof(glseg_t); segs.Alloc(numsegs); memset(&segs[0],0,sizeof(seg_t)*numsegs); - glseg_t * ml = (glseg_t*)data.Data(); + auto ml = (const glseg_t*)data.data(); for(i = 0; i < numsegs; i++) { // check for gl-vertices @@ -323,21 +324,21 @@ bool MapLoader::LoadGLSegs(FileReader &lump) ldef = &Level->lines[lineidx]; segs[i].linedef = ldef; - ml->side=LittleShort(ml->side); - if (ml->side > 1) + auto side=LittleShort(ml->side); + if (side > 1) return false; - segs[i].sidedef = ldef->sidedef[ml->side]; - if (ldef->sidedef[ml->side] != nullptr) + segs[i].sidedef = ldef->sidedef[side]; + if (ldef->sidedef[side] != nullptr) { - segs[i].frontsector = ldef->sidedef[ml->side]->sector; + segs[i].frontsector = ldef->sidedef[side]->sector; } else { segs[i].frontsector = nullptr; } - if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != nullptr) + if (ldef->flags & ML_TWOSIDED && ldef->sidedef[side^1] != nullptr) { - segs[i].backsector = ldef->sidedef[ml->side^1]->sector; + segs[i].backsector = ldef->sidedef[side^1]->sector; } else { @@ -364,7 +365,7 @@ bool MapLoader::LoadGLSegs(FileReader &lump) segs.Alloc(numsegs); memset(&segs[0],0,sizeof(seg_t)*numsegs); - glseg3_t * ml = (glseg3_t*)(data.Data() + (format5? 0:4)); + const glseg3_t * ml = (const glseg3_t*)(data.bytes() + (format5? 0:4)); for(i = 0; i < numsegs; i++) { // check for gl-vertices const unsigned v1idx = checkGLVertex3(LittleLong(ml->v1)); @@ -394,21 +395,21 @@ bool MapLoader::LoadGLSegs(FileReader &lump) segs[i].linedef = ldef; - ml->side=LittleShort(ml->side); - if (ml->side > 1) + auto side=LittleShort(ml->side); + if (side > 1) return false; - segs[i].sidedef = ldef->sidedef[ml->side]; - if (ldef->sidedef[ml->side] != nullptr) + segs[i].sidedef = ldef->sidedef[side]; + if (ldef->sidedef[side] != nullptr) { - segs[i].frontsector = ldef->sidedef[ml->side]->sector; + segs[i].frontsector = ldef->sidedef[side]->sector; } else { segs[i].frontsector = nullptr; } - if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != nullptr) + if (ldef->flags & ML_TWOSIDED && ldef->sidedef[side^1] != nullptr) { - segs[i].backsector = ldef->sidedef[ml->side^1]->sector; + segs[i].backsector = ldef->sidedef[side^1]->sector; } else { @@ -453,9 +454,9 @@ bool MapLoader::LoadGLSubsectors(FileReader &lump) return false; } - if (!format5 && memcmp(datab.Data(), "gNd3", 4)) + if (!format5 && memcmp(datab.data(), "gNd3", 4)) { - mapsubsector_t * data = (mapsubsector_t*) datab.Data(); + auto data = (const mapsubsector_t*) datab.data(); numsubsectors /= sizeof(mapsubsector_t); Level->subsectors.Alloc(numsubsectors); auto &subsectors = Level->subsectors; @@ -477,7 +478,7 @@ bool MapLoader::LoadGLSubsectors(FileReader &lump) } else { - gl3_mapsubsector_t * data = (gl3_mapsubsector_t*) (datab.Data()+(format5? 0:4)); + auto data = (const gl3_mapsubsector_t*) (datab.bytes()+(format5? 0:4)); numsubsectors /= sizeof(gl3_mapsubsector_t); Level->subsectors.Alloc(numsubsectors); auto &subsectors = Level->subsectors; @@ -544,7 +545,7 @@ bool MapLoader::LoadNodes (FileReader &lump) lump.Seek(0, FileReader::SeekSet); auto buf = lump.Read(); - basemn = mn = (mapnode_t*)buf.Data(); + basemn = mn = (mapnode_t*)buf.data(); used.Resize(numnodes); memset (used.Data(), 0, sizeof(uint16_t)*numnodes); @@ -600,7 +601,7 @@ bool MapLoader::LoadNodes (FileReader &lump) lump.Seek(0, FileReader::SeekSet); auto buf = lump.Read(); - basemn = mn = (gl5_mapnode_t*)buf.Data(); + basemn = mn = (gl5_mapnode_t*)buf.data(); used.Resize(numnodes); memset(used.Data(), 0, sizeof(uint16_t)*numnodes); @@ -735,14 +736,14 @@ static int FindGLNodesInWAD(int labellump) glheader.Format("GL_%s", fileSystem.GetFileFullName(labellump)); if (glheader.Len()<=8) { - int gllabel = fileSystem.CheckNumForName(glheader, ns_global, wadfile); + int gllabel = fileSystem.CheckNumForName(glheader.GetChars(), FileSys::ns_global, wadfile); if (gllabel >= 0) return gllabel; } else { // Before scanning the entire WAD directory let's check first whether // it is necessary. - int gllabel = fileSystem.CheckNumForName("GL_LEVEL", ns_global, wadfile); + int gllabel = fileSystem.CheckNumForName("GL_LEVEL", FileSys::ns_global, wadfile); if (gllabel >= 0) { @@ -752,8 +753,8 @@ static int FindGLNodesInWAD(int labellump) { if (fileSystem.GetFileContainer(lump)==wadfile) { - FileData mem = fileSystem.ReadFile(lump); - if (MatchHeader(fileSystem.GetFileFullName(labellump), (const char *)mem.GetMem())) return lump; + auto mem = fileSystem.ReadFile(lump); + if (MatchHeader(fileSystem.GetFileFullName(labellump), GetStringFromLump(lump).GetChars())) return lump; } } } @@ -779,7 +780,7 @@ static int FindGLNodesInFile(FResourceFile * f, const char * label) FString glheader; bool mustcheck=false; - uint32_t numentries = f->LumpCount(); + uint32_t numentries = f->EntryCount(); glheader.Format("GL_%.8s", label); if (glheader.Len()>8) @@ -792,13 +793,13 @@ static int FindGLNodesInFile(FResourceFile * f, const char * label) { for(uint32_t i=0;iGetLump(i)->getName(), glheader, 8)) + if (!strnicmp(f->getName(i), glheader.GetChars(), 8)) { if (mustcheck) { char check[16]={0}; - auto fr = f->GetLump(i)->GetReader(); - fr->Read(check, 16); + auto fr = f->GetEntryReader(i, FileSys::READER_SHARED); + fr.Read(check, 16); if (MatchHeader(label, check)) return i; } else return i; @@ -883,7 +884,7 @@ bool MapLoader::LoadGLNodes(MapData * map) strcpy(ext, ".gwa"); // Todo: Compare file dates - f_gwa = FResourceFile::OpenResourceFile(path, true); + f_gwa = FResourceFile::OpenResourceFile(path); if (f_gwa==nullptr) return false; strncpy(map->MapLumps[0].Name, fileSystem.GetFileFullName(map->lumpnum), 8); @@ -899,13 +900,13 @@ bool MapLoader::LoadGLNodes(MapData * map) result=true; for(unsigned i=0; i<4;i++) { - if (strnicmp(f_gwa->GetLump(li+i+1)->getName(), check[i], 8)) + if (strnicmp(f_gwa->getName(li + i + 1), check[i], 8)) { result=false; break; } else - gwalumps[i] = f_gwa->GetLump(li+i+1)->NewReader(); + gwalumps[i] = f_gwa->GetEntryReader(li + i + 1, FileSys::READER_NEW, FileSys::READERFLAG_SEEKABLE); } if (result) result = DoLoadGLNodes(gwalumps); } @@ -1000,10 +1001,10 @@ typedef TArray MemFile; static FString CreateCacheName(MapData *map, bool create) { FString path = M_GetCachePath(create); - FString lumpname = fileSystem.GetFileFullPath(map->lumpnum); + FString lumpname = fileSystem.GetFileFullPath(map->lumpnum).c_str(); auto separator = lumpname.IndexOf(':'); path << '/' << lumpname.Left(separator); - if (create) CreatePath(path); + if (create) CreatePath(path.GetChars()); lumpname.ReplaceChars('/', '%'); lumpname.ReplaceChars(':', '$'); @@ -1124,7 +1125,7 @@ void MapLoader::CreateCachedNodes(MapData *map) memcpy(&compressed[offset - 4], "ZGL3", 4); FString path = CreateCacheName(map, true); - FileWriter *fw = FileWriter::Open(path); + FileWriter *fw = FileWriter::Open(path.GetChars()); if (fw != nullptr) { @@ -1153,7 +1154,7 @@ bool MapLoader::CheckCachedNodes(MapData *map) FString path = CreateCacheName(map, false); FileReader fr; - if (!fr.OpenFile(path)) return false; + if (!fr.OpenFile(path.GetChars())) return false; if (fr.Read(magic, 4) != 4) return false; if (memcmp(magic, "CACH", 4)) return false; @@ -1198,11 +1199,11 @@ bool MapLoader::CheckCachedNodes(MapData *map) UNSAFE_CCMD(clearnodecache) { - TArray list; + FileSys::FileList list; FString path = M_GetCachePath(false); path += "/"; - if (!ScanDirectory(list, path)) + if (!FileSys::ScanDirectory(list, path.GetChars(), "*", false)) { Printf("Unable to scan node cache directory %s\n", path.GetChars()); return; @@ -1210,15 +1211,15 @@ UNSAFE_CCMD(clearnodecache) // Scan list backwards so that when we reach a directory // all files within are already deleted. - for(int i = list.Size()-1; i >= 0; i--) + for(int i = (int)list.size()-1; i >= 0; i--) { if (list[i].isDirectory) { - rmdir(list[i].Filename); + rmdir(list[i].FilePath.c_str()); } else { - remove(list[i].Filename); + remove(list[i].FilePath.c_str()); } } diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index d07254343a..a62bf1c309 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -83,8 +83,10 @@ #include "vm.h" #include "texturemanager.h" #include "hw_vertexbuilder.h" -#include "scene/hw_meshcache.h" #include "version.h" +#include "fs_decompress.h" + +#include "common/utility/halffloat.h" enum { @@ -93,6 +95,8 @@ enum CVAR (Bool, genblockmap, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG); CVAR (Bool, gennodes, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG); +CVAR (Bool, genlightmaps, false, CVAR_GLOBALCONFIG); +CVAR (Bool, ignorelightmaplump, false, CVAR_GLOBALCONFIG); inline bool P_LoadBuildMap(uint8_t *mapdata, size_t len, FMapThing **things, int *numthings) { @@ -427,7 +431,7 @@ void MapLoader::LoadVertexes(MapData * map) if (numvertexes == 0) { - I_Error("Map has no vertices.\n"); + I_Error("Map has no vertices."); } // Allocate memory for buffer. @@ -498,6 +502,11 @@ void MapLoader::LoadGLZSegs (FileReader &data, int type) uint32_t partner = data.ReadUInt32(); uint32_t line; + if (partner != 0xffffffffu && partner >= Level->segs.Size()) + { + I_Error("partner seg index out of range for subsector %d, seg %d", i, j); + } + if (type >= 2) { line = data.ReadUInt32(); @@ -564,7 +573,7 @@ void MapLoader::LoadZNodes(FileReader &data, int glnodes) if (orgVerts > Level->vertexes.Size()) { // These nodes are based on a map with more vertex data than we have. // We can't use them. - throw CRecoverableError("Incorrect number of vertexes in nodes.\n"); + I_Error("Incorrect number of vertexes in nodes."); } auto oldvertexes = &Level->vertexes[0]; if (orgVerts + newVerts != Level->vertexes.Size()) @@ -607,7 +616,7 @@ void MapLoader::LoadZNodes(FileReader &data, int glnodes) // segs used by subsectors. if (numSegs != currSeg) { - throw CRecoverableError("Incorrect number of segs in nodes.\n"); + I_Error("Incorrect number of segs in nodes."); } Level->segs.Alloc(numSegs); @@ -734,45 +743,37 @@ bool MapLoader::LoadExtendedNodes (FileReader &dalump, uint32_t id) if (compressed) { FileReader zip; - try + if (OpenDecompressor(zip, dalump, -1, FileSys::METHOD_ZLIB, FileSys::DCF_EXCEPTIONS)) { - if (zip.OpenDecompressor(dalump, -1, METHOD_ZLIB, false, [](const char* err) { I_Error("%s", err); })) - { - LoadZNodes(zip, type); - } - else - { - Printf("Error loading nodes: Corrupt data.\n"); - return false; - } + LoadZNodes(zip, type); + return true; } - catch (const CRecoverableError& err) + else { - Printf("Error loading nodes: %s.\n", err.what()); - - ForceNodeBuild = true; - Level->subsectors.Clear(); - Level->segs.Clear(); - Level->nodes.Clear(); - return false; + Printf("Error loading nodes: Corrupt data.\n"); } } else { LoadZNodes(dalump, type); + return true; } - return true; } catch (CRecoverableError &error) { Printf("Error loading nodes: %s\n", error.GetMessage()); - - ForceNodeBuild = true; - Level->subsectors.Clear(); - Level->segs.Clear(); - Level->nodes.Clear(); - return false; } + catch (FileSys::FileSystemException& error) + { + Printf("Error loading nodes: %s\n", error.what()); + } + // clean up. + Printf("The BSP will be rebuilt\n"); + ForceNodeBuild = true; + Level->subsectors.Clear(); + Level->segs.Clear(); + Level->nodes.Clear(); + return false; } @@ -1167,12 +1168,11 @@ void MapLoader::LoadSectors (MapData *map, FMissingTextureTracker &missingtex) template bool MapLoader::LoadNodes (MapData * map) { - FileData data; + FileSys::FileData data; int j; int k; nodetype *mn; node_t* no; - uint16_t* used; int lumplen = map->Size(ML_NODES); int maxss = map->Size(ML_SSECTORS) / sizeof(subsectortype); @@ -1185,8 +1185,8 @@ bool MapLoader::LoadNodes (MapData * map) auto &nodes = Level->nodes; nodes.Alloc(numnodes); - used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes); - memset (used, 0, sizeof(uint16_t)*numnodes); + TArray used(numnodes, true); + memset (used.data(), 0, sizeof(uint16_t) * numnodes); auto mnp = map->Read(ML_NODES); mn = (nodetype*)(mnp.Data() + nodetype::NF_LUMPOFFSET); @@ -1664,7 +1664,7 @@ void MapLoader::FinishLoadingLineDefs () } else { - I_Error ("%d sidedefs is not enough\n", sidecount); + I_Error ("%d sidedefs is not enough", sidecount); } } @@ -2062,9 +2062,9 @@ void MapLoader::ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec // instead of figuring something out from the colormap. if (sec != nullptr) { - SetTexture (sd, side_t::bottom, &sec->bottommap, msd->bottomtexture); - SetTexture (sd, side_t::mid, &sec->midmap, msd->midtexture); - SetTexture (sd, side_t::top, &sec->topmap, msd->toptexture); + SetTexture (sd, side_t::bottom, &sec->bottommap, msd->bottomtexture.GetChars()); + SetTexture (sd, side_t::mid, &sec->midmap, msd->midtexture.GetChars()); + SetTexture (sd, side_t::top, &sec->topmap, msd->toptexture.GetChars()); } break; @@ -2076,9 +2076,9 @@ void MapLoader::ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec uint32_t color = MAKERGB(255,255,255), fog = 0; bool colorgood, foggood; - SetTextureNoErr (sd, side_t::bottom, &fog, msd->bottomtexture, &foggood, true); - SetTextureNoErr (sd, side_t::top, &color, msd->toptexture, &colorgood, false); - SetTexture(sd, side_t::mid, msd->midtexture, missingtex); + SetTextureNoErr (sd, side_t::bottom, &fog, msd->bottomtexture.GetChars(), &foggood, true); + SetTextureNoErr (sd, side_t::top, &color, msd->toptexture.GetChars(), &colorgood, false); + SetTexture(sd, side_t::mid, msd->midtexture.GetChars(), missingtex); if (colorgood | foggood) { @@ -2118,12 +2118,12 @@ void MapLoader::ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec { int lumpnum; - if (strnicmp ("TRANMAP", msd->midtexture, 8) == 0) + if (strnicmp ("TRANMAP", msd->midtexture.GetChars(), 8) == 0) { // The translator set the alpha argument already; no reason to do it again. sd->SetTexture(side_t::mid, FNullTextureID()); } - else if ((lumpnum = fileSystem.CheckNumForName (msd->midtexture)) > 0 && + else if ((lumpnum = fileSystem.CheckNumForName (msd->midtexture.GetChars())) > 0 && fileSystem.FileLength (lumpnum) == 65536) { auto fr = fileSystem.OpenFileReader(lumpnum); @@ -2131,9 +2131,7 @@ void MapLoader::ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec if (developer >= DMSG_NOTIFY) { - char lumpname[9]; - lumpname[8] = 0; - fileSystem.GetFileShortName(lumpname, lumpnum); + const char *lumpname = fileSystem.GetFileShortName(lumpnum); if (*alpha < 0) Printf("%s appears to be additive translucency %d (%d%%)\n", lumpname, -*alpha, -*alpha * 100 / 255); else Printf("%s appears to be translucency %d (%d%%)\n", lumpname, *alpha, *alpha * 100 / 255); } @@ -2707,7 +2705,7 @@ void MapLoader::GroupLines (bool buildmap) } if (flaggedNoFronts) { - I_Error ("You need to fix these lines to play this map.\n"); + I_Error ("You need to fix these lines to play this map."); } // build line tables for each sector @@ -2943,10 +2941,275 @@ void MapLoader::CalcIndices() // //========================================================================== +void MapLoader::InitLevelMesh(MapData* map) +{ + // Propagate sample distance where it isn't yet set + for (auto& line : Level->lines) + { + if (line.LightmapSampleDistance[0] || line.LightmapSampleDistance[1] || line.LightmapSampleDistance[2]) + { + for (int i = 0; i < 2; ++i) + { + if (auto sidedef = line.sidedef[i]) + { + for (int j = 0; j < 3; ++j) + { + if (!sidedef->textures[j].LightmapSampleDistance) + { + sidedef->textures[j].LightmapSampleDistance = line.LightmapSampleDistance[j]; + } + } + } + } + } + } + + if (map->Size(ML_LIGHTMAP)) + { + // Arbitrary ZDRay limit. This will break lightmap lump loading if not enforced. + Level->LightmapSampleDistance = Level->LightmapSampleDistance < 8 ? 8 : Level->LightmapSampleDistance; + + if (!Level->lightmaps) // We are unfortunately missing ZDRayInfo + { + Printf(PRINT_HIGH, "InitLevelMesh: The level contains LIGHTMAP, but no ZDRayInfo thing was detected in the level.\n"); + } + } + else + { + Level->lightmaps = Level->lightmaps || *genlightmaps; // Allow lightmapping in non-lightmapped levels. + } + + // Allocate room for surface arrays on sectors, sides and their 3D floors + + unsigned int allSurfaces = 0; + + for (unsigned int i = 0; i < Level->sides.Size(); i++) + allSurfaces += 4 + Level->sides[i].sector->e->XFloor.ffloors.Size(); + + for (unsigned int i = 0; i < Level->subsectors.Size(); i++) + allSurfaces += 2 + Level->subsectors[i].sector->e->XFloor.ffloors.Size() * 2; + + Level->Surfaces.Resize(allSurfaces); + memset(Level->Surfaces.Data(), 0, sizeof(DoomLevelMeshSurface*) * allSurfaces); + + unsigned int offset = 0; + for (unsigned int i = 0; i < Level->sides.Size(); i++) + { + auto& side = Level->sides[i]; + int count = 4 + side.sector->e->XFloor.ffloors.Size(); + side.surface = TArrayView(&Level->Surfaces[offset], count); + offset += count; + } + for (unsigned int i = 0; i < Level->subsectors.Size(); i++) + { + auto& subsector = Level->subsectors[i]; + unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size(); + subsector.surface[0] = TArrayView(&Level->Surfaces[offset], count); + subsector.surface[1] = TArrayView(&Level->Surfaces[offset + count], count); + offset += count * 2; + } + + // Create the levelmesh + Level->levelMesh = new DoomLevelMesh(*Level); + + // Lightmap binding/loading + if (!LoadLightmap(map)) + { + if (Level->lightmaps) + { + Level->levelMesh->SetupTileTransforms(); + Level->levelMesh->PackLightmapAtlas(0); + } + } +} + +bool MapLoader::LoadLightmap(MapData* map) +{ + if (!Level->lightmaps || !map->Size(ML_LIGHTMAP) || ignorelightmaplump) + return false; + + FileReader fr; + if (!OpenDecompressor(fr, map->Reader(ML_LIGHTMAP), -1, FileSys::METHOD_ZLIB)) + return false; + + int version = fr.ReadInt32(); + if (version < 3) + { + Printf(PRINT_HIGH, "LoadLightmap: This is an old unsupported version of the lightmap lump. Please rebuild the map with a newer version of zdray.\n"); + return false; + } + else if (version != 3) + { + Printf(PRINT_HIGH, "LoadLightmap: unsupported lightmap lump version\n"); + return false; + } + + uint32_t numTiles = fr.ReadUInt32(); + uint32_t numTexPixels = fr.ReadUInt32(); + + if (developer >= 5) + { + Printf("LoadLightmap: Tiles: %u, Pixels: %u\n", numTiles, numTexPixels); + } + + if (numTiles == 0 || numTexPixels == 0) + return false; + + int errors = 0; + + // Load the tiles we have lightmap data for + + struct TileEntry // V2 entries + { + uint32_t type, typeIndex; + uint32_t controlSector; // 0xFFFFFFFF is none + uint16_t width, height; // in pixels + uint32_t pixelsOffset; // offset in pixels array + FVector3 translateWorldToLocal; + FVector3 projLocalToU; + FVector3 projLocalToV; + }; + + TArray tileEntries; + tileEntries.Reserve(numTiles); + + uint32_t usedSurfaceIndex = 0; + for (uint32_t i = 0; i < numTiles; i++) + { + TileEntry& entry = tileEntries[i]; + entry.type = fr.ReadUInt32(); + entry.typeIndex = fr.ReadUInt32(); + entry.controlSector = fr.ReadUInt32(); + entry.width = fr.ReadUInt16(); + entry.height = fr.ReadUInt16(); + entry.pixelsOffset = fr.ReadUInt32(); + entry.translateWorldToLocal.X = fr.ReadFloat(); + entry.translateWorldToLocal.Y = fr.ReadFloat(); + entry.translateWorldToLocal.Z = fr.ReadFloat(); + entry.projLocalToU.X = fr.ReadFloat(); + entry.projLocalToU.Y = fr.ReadFloat(); + entry.projLocalToU.Z = fr.ReadFloat(); + entry.projLocalToV.X = fr.ReadFloat(); + entry.projLocalToV.Y = fr.ReadFloat(); + entry.projLocalToV.Z = fr.ReadFloat(); + } + + // Load pixels + TArray textureData; + textureData.Resize(numTexPixels * 3); + uint8_t* data = (uint8_t*)&textureData[0]; + fr.Read(data, numTexPixels * 3 * sizeof(uint16_t)); + + const auto textureSize = Level->levelMesh->LMTextureSize; + + // Create lookup for finding tiles + std::map levelTiles; + for (LightmapTile& tile : Level->levelMesh->LightmapTiles) + { + levelTiles[tile.Binding] = &tile; + } + + // Bind tiles and use the lump's tile transform + TArray> foundBindings; + for (const TileEntry& entry : tileEntries) + { + LightmapTileBinding binding; + binding.Type = entry.type; + binding.TypeIndex = entry.typeIndex; + binding.ControlSector = entry.controlSector; + + auto it = levelTiles.find(binding); + if (it == levelTiles.end()) + { + // ZDRay and HWWall don't always agree on which surfaces are visible. + // We can safely ignore the extra tiles. + continue; + } + + if (entry.width == 0 || entry.height == 0) + { + if (errors < 100 && developer >= 1) + Printf("Invalid lightmap tile found (type = %d, index = %d, control sector = %d)\n", entry.type, entry.typeIndex, entry.controlSector); + errors++; + continue; + } + + LightmapTile* tile = it->second; + + tile->AtlasLocation.Width = entry.width; + tile->AtlasLocation.Height = entry.height; + tile->Transform.TranslateWorldToLocal = entry.translateWorldToLocal; + tile->Transform.ProjLocalToU = entry.projLocalToU; + tile->Transform.ProjLocalToV = entry.projLocalToV; + tile->NeedsUpdate = false; + + foundBindings.Push({ &entry, tile }); + } + + // Setup the tile transform for any tile missing in the lump (shouldn't be any, but if there are we let the lightmapper bake them) + for (auto& tile : Level->levelMesh->LightmapTiles) + { + if (tile.NeedsUpdate) + tile.SetupTileTransform(Level->levelMesh->LMTextureSize); + } + + // Place all tiles in atlas textures + Level->levelMesh->PackLightmapAtlas(0); + + // Start with empty lightmap textures + Level->levelMesh->LMTextureData.Resize(Level->levelMesh->LMTextureCount * textureSize * textureSize * 3); + memset(Level->levelMesh->LMTextureData.Data(), 0, Level->levelMesh->LMTextureData.Size() * sizeof(uint16_t)); + + // Copy tile pixels to the texture + for (auto& binding : foundBindings) + { + const TileEntry* entry = binding.first; + LightmapTile* tile = binding.second; + + const uint16_t* src = textureData.Data() + entry->pixelsOffset; + uint16_t* dst = &Level->levelMesh->LMTextureData[tile->AtlasLocation.ArrayIndex * textureSize * textureSize * 3]; + int destx = tile->AtlasLocation.X; + int desty = tile->AtlasLocation.Y; + int width = tile->AtlasLocation.Width; + int height = tile->AtlasLocation.Height; + + for (int yy = 0; yy < height; yy++) + { + uint16_t* dstline = dst + (destx + (desty + yy) * textureSize) * 3; + const uint16_t* srcline = src + yy * (width * 3); + memcpy(dstline, srcline, width * 6); + } + + tile->NeedsUpdate = false; + } + + if (errors > 0) + { + if (developer <= 0) + Printf(PRINT_HIGH, "Pre-calculated LIGHTMAP surfaces do not match current level surfaces. Restart this level with 'developer 1' for further details.\nPerhaps you forget to rebuild lightmaps after modifying the map?\n"); + else + Printf(PRINT_HIGH, "Pre-calculated LIGHTMAP surfaces do not match current level surfaces.\nPerhaps you forget to rebuild lightmaps after modifying the map?\n"); + } + + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) { const int *oldvertextable = nullptr; + // Reset defaults for lightmapping + Level->SunColor = FVector3(1.f, 1.f, 1.f); + Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f); + Level->LightmapSampleDistance = 16; + Level->lightmaps = false; + // note: most of this ordering is important ForceNodeBuild = gennodes; @@ -3098,8 +3361,8 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) } } - // If loading the regular nodes failed try GL nodes before considering a rebuild - if (!NodesLoaded) + // If loading the regular nodes failed try GL nodes before considering a rebuild (unless a rebuild was already asked for) + if (!NodesLoaded && !ForceNodeBuild) { if (LoadGLNodes(map)) reloop = true; @@ -3209,12 +3472,6 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) SpawnThings(position); - // Load and link lightmaps - must be done after P_Spawn3DFloors (and SpawnThings? Potentially for baking static model actors?) - if (!ForceNodeBuild) - { - LoadLightmap(map); - } - for (int i = 0; i < MAXPLAYERS; ++i) { if (Level->PlayerInGame(i) && Level->Players[i]->mo != nullptr) @@ -3247,16 +3504,6 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) } InitRenderInfo(); // create hardware independent renderer resources for the level. This must be done BEFORE the PolyObj Spawn!!! - Level->ClearDynamic3DFloorData(); // CreateVBO must be run on the plain 3D floor data. - CreateVBO(*screen->RenderState(0), Level->sectors); - meshcache.Clear(); - - screen->InitLightmap(Level->LMTextureSize, Level->LMTextureCount, Level->LMTextureData); - - for (auto &sec : Level->sectors) - { - P_Recalculate3DFloors(&sec); - } SWRenderer->SetColormap(Level); //The SW renderer needs to do some special setup for the level's default colormap. InitPortalGroups(Level); @@ -3267,199 +3514,14 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) if (!Level->IsReentering()) Level->FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them. - Level->aabbTree = new DoomLevelAABBTree(Level); - Level->levelMesh = new DoomLevelMesh(*Level); -} + InitLevelMesh(map); -//========================================================================== -// -// -// -//========================================================================== - -void MapLoader::SetSubsectorLightmap(const LightmapSurface &surface) -{ - if (!surface.ControlSector) - { - int index = surface.Type == ST_CEILING ? 1 : 0; - surface.Subsector->lightmap[index][0] = surface; - } - else - { - int index = surface.Type == ST_CEILING ? 0 : 1; - const auto &ffloors = surface.Subsector->sector->e->XFloor.ffloors; - for (unsigned int i = 0; i < ffloors.Size(); i++) - { - if (ffloors[i]->model == surface.ControlSector) - { - surface.Subsector->lightmap[index][i + 1] = surface; - } - } - } -} - -void MapLoader::SetSideLightmap(const LightmapSurface &surface) -{ - if (!surface.ControlSector) - { - if (surface.Type == ST_UPPERWALL) - { - surface.Side->lightmap[0] = surface; - } - else if (surface.Type == ST_MIDDLEWALL) - { - surface.Side->lightmap[1] = surface; - surface.Side->lightmap[2] = surface; - } - else if (surface.Type == ST_LOWERWALL) - { - surface.Side->lightmap[3] = surface; - } - } - else - { - const auto &ffloors = surface.Side->sector->e->XFloor.ffloors; - for (unsigned int i = 0; i < ffloors.Size(); i++) - { - if (ffloors[i]->model == surface.ControlSector) - { - surface.Side->lightmap[4 + i] = surface; - } - } - } -} - -void MapLoader::LoadLightmap(MapData *map) -{ - // We have to reset everything as FLevelLocals is recycled between maps - Level->LMTexCoords.Reset(); - Level->LMSurfaces.Reset(); - Level->LMTextureData.Reset(); - Level->LMTextureCount = 0; - Level->LMTextureSize = 0; - - //if (!Args->CheckParm("-enablelightmaps")) - // return; // this feature is still too early WIP to allow general access - - if (!map->Size(ML_LIGHTMAP)) - return; - - FileReader fr; - if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, METHOD_ZLIB, false, [](const char* err) { I_Error("%s", err); })) - return; - - int version = fr.ReadInt32(); - if (version == 0) - { - Printf(PRINT_HIGH, "LoadLightmap: This is an old unsupported alpha version of the lightmap lump. Please rebuild the map with a newer version of zdray.\n"); - return; - } - if (version != 1) - { - Printf(PRINT_HIGH, "LoadLightmap: unsupported lightmap lump version\n"); - return; - } - - uint16_t textureSize = fr.ReadUInt16(); - uint16_t numTextures = fr.ReadUInt16(); - uint32_t numSurfaces = fr.ReadUInt32(); - uint32_t numTexCoords = fr.ReadUInt32(); - uint32_t numSubsectors = fr.ReadUInt32(); - uint32_t numTexBytes = numTextures * textureSize * textureSize * 3 * 2; - if (numSurfaces == 0 || numTexCoords == 0 || numTexBytes == 0) - return; - - float sunDir[3], sunColor[3]; - fr.Read(sunDir, sizeof(float) * 3); - fr.Read(sunColor, sizeof(float) * 3); - Level->SunDirection = FVector3(sunDir); - Level->SunColor = FVector3(sunColor); - - /*if (numSubsectors != Level->subsectors.Size()) - { - Printf(PRINT_HIGH, "LoadLightmap: subsector count for level doesn't match (%d in wad vs %d in engine)\n", (int)numSubsectors, (int)Level->subsectors.Size()); - }*/ - - Level->LMTexCoords.Resize(numTexCoords * 2); - - // Allocate room for all surfaces - - unsigned int allSurfaces = 0; - - for (unsigned int i = 0; i < Level->sides.Size(); i++) - allSurfaces += 4 + Level->sides[i].sector->e->XFloor.ffloors.Size(); - - for (unsigned int i = 0; i < Level->subsectors.Size(); i++) - allSurfaces += 2 + Level->subsectors[i].sector->e->XFloor.ffloors.Size() * 2; - - Level->LMSurfaces.Resize(allSurfaces); - memset(&Level->LMSurfaces[0], 0, sizeof(LightmapSurface) * allSurfaces); - - // Link the surfaces to sectors, sides and their 3D floors - - unsigned int offset = 0; - for (unsigned int i = 0; i < Level->sides.Size(); i++) - { - auto& side = Level->sides[i]; - side.lightmap = &Level->LMSurfaces[offset]; - offset += 4 + side.sector->e->XFloor.ffloors.Size(); - } - for (unsigned int i = 0; i < Level->subsectors.Size(); i++) - { - auto& subsector = Level->subsectors[i]; - unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size(); - subsector.lightmap[0] = &Level->LMSurfaces[offset]; - subsector.lightmap[1] = &Level->LMSurfaces[offset + count]; - offset += count * 2; - } - - // Load the surfaces we have lightmap data for - - for (uint32_t i = 0; i < numSurfaces; i++) + Level->ClearDynamic3DFloorData(); // CreateVBO must be run on the plain 3D floor data. + CreateVBO(*screen->RenderState(), Level->sectors); + for (auto& sec : Level->sectors) { - LightmapSurface surface; - memset(&surface, 0, sizeof(LightmapSurface)); - - SurfaceType type = (SurfaceType)fr.ReadUInt32(); - uint32_t typeIndex = fr.ReadUInt32(); - uint32_t controlSector = fr.ReadUInt32(); - uint32_t lightmapNum = fr.ReadUInt32(); - uint32_t firstTexCoord = fr.ReadUInt32(); - - if (controlSector != 0xffffffff) - surface.ControlSector = &Level->sectors[controlSector]; - - surface.Type = type; - surface.LightmapNum = lightmapNum; - surface.TexCoords = &Level->LMTexCoords[firstTexCoord * 2]; - - if (type == ST_CEILING || type == ST_FLOOR) - { - surface.Subsector = &Level->subsectors[typeIndex]; - surface.Subsector->firstline->sidedef->sector->HasLightmaps = true; - SetSubsectorLightmap(surface); - } - else if (type != ST_NULL) - { - surface.Side = &Level->sides[typeIndex]; - SetSideLightmap(surface); - } + P_Recalculate3DFloors(&sec); } - // Load texture coordinates - - fr.Read(&Level->LMTexCoords[0], numTexCoords * 2 * sizeof(float)); - - // Load lightmap textures - - Level->LMTextureCount = numTextures; - Level->LMTextureSize = textureSize; - Level->LMTextureData.Resize((numTexBytes + 1) / 2); - uint8_t* data = (uint8_t*)&Level->LMTextureData[0]; - fr.Read(data, numTexBytes); -#if 0 - // Apply compression predictor - for (uint32_t i = 1; i < numTexBytes; i++) - data[i] += data[i - 1]; -#endif + Level->aabbTree = new DoomLevelAABBTree(Level); } diff --git a/src/maploader/maploader.h b/src/maploader/maploader.h index 93c65f9838..fa765b0841 100644 --- a/src/maploader/maploader.h +++ b/src/maploader/maploader.h @@ -2,8 +2,8 @@ #include "nodebuild.h" #include "g_levellocals.h" +#include "files.h" -class FileReader; struct FStrifeDialogueNode; struct FStrifeDialogueReply; struct Response; @@ -152,7 +152,7 @@ class MapLoader // Polyobjects void InitSideLists(); void IterFindPolySides(FPolyObj *po, side_t *side); - void SpawnPolyobj(int index, int tag, int type); + void SpawnPolyobj(int index, int tag, int type, int damage); void TranslateToStartSpot(int tag, const DVector2 &origin); void InitPolyBlockMap(void); @@ -194,7 +194,7 @@ class MapLoader void SpawnSpecials(); void InitSectorSpecial(sector_t *sector, int special); void SpawnLights(sector_t *sector); - void CreateScroller(EScroll type, double dx, double dy, sector_t *affectee, int accel, EScrollPos scrollpos = EScrollPos::scw_all); + void CreateScroller(EScroll type, double dx, double dy, sector_t *sect, side_t* side, int accel, EScrollPos scrollpos = EScrollPos::scw_all, int scrollmode = 15/*SCROLL_All*/); void SpawnScrollers(); void SpawnFriction(); void SpawnPushers(); @@ -212,6 +212,10 @@ class MapLoader void Spawn3DFloors (); void SetTexture(side_t *side, int position, const char *name, FMissingTextureTracker &track); + void SetTexture(side_t* side, int position, const FString& name, FMissingTextureTracker& track) + { + SetTexture(side, position, name.GetChars(), track); + } void SetTexture(sector_t *sector, int index, int position, const char *name, FMissingTextureTracker &track, bool truncate); void SetTexture(side_t *side, int position, uint32_t *blend, const char *name); void SetTextureNoErr(side_t *side, int position, uint32_t *color, const char *name, bool *validcolor, bool isFog); @@ -304,9 +308,8 @@ class MapLoader void SetSlopes(); void CopySlopes(); - void SetSubsectorLightmap(const LightmapSurface &surface); - void SetSideLightmap(const LightmapSurface &surface); - void LoadLightmap(MapData *map); + void InitLevelMesh(MapData* map); + bool LoadLightmap(MapData* map); void LoadLevel(MapData *map, const char *lumpname, int position); diff --git a/src/maploader/polyobjects.cpp b/src/maploader/polyobjects.cpp index 00b7ccca40..1f662b134c 100644 --- a/src/maploader/polyobjects.cpp +++ b/src/maploader/polyobjects.cpp @@ -148,7 +148,22 @@ static int posicmp(const void *a, const void *b) return (*(const side_t **)a)->linedef->args[1] - (*(const side_t **)b)->linedef->args[1]; } -void MapLoader::SpawnPolyobj (int index, int tag, int type) +int SetPolyobjDamage(int type, int damage) +{ + int dam; + if (type != SMT_PolySpawn) + { + if (damage == 1) + dam = 3; + else if (damage > 1) + dam = TELEFRAG_DAMAGE; + else if (damage < 0) + dam = abs(damage); + } + return (type != SMT_PolySpawn) ? dam : 0; +} + +void MapLoader::SpawnPolyobj (int index, int tag, int type, int damage) { unsigned int ii; int i; @@ -181,8 +196,9 @@ void MapLoader::SpawnPolyobj (int index, int tag, int type) sd->linedef->args[0] = 0; IterFindPolySides(&Level->Polyobjects[index], sd); po->MirrorNum = sd->linedef->args[1]; - po->crush = (type != SMT_PolySpawn) ? 3 : 0; + po->crush = SetPolyobjDamage(type,damage); po->bHurtOnTouch = (type == SMT_PolySpawnHurt); + po->tag = tag; po->seqType = sd->linedef->args[2]; if (po->seqType < 0 || po->seqType > (MAX_SNDSEQS - 1)) @@ -222,7 +238,7 @@ void MapLoader::SpawnPolyobj (int index, int tag, int type) qsort(&po->Sidedefs[0], po->Sidedefs.Size(), sizeof(po->Sidedefs[0]), posicmp); if (po->Sidedefs.Size() > 0) { - po->crush = (type != SMT_PolySpawn) ? 3 : 0; + po->crush = SetPolyobjDamage(type,damage); po->bHurtOnTouch = (type == SMT_PolySpawnHurt); po->tag = tag; po->seqType = po->Sidedefs[0]->linedef->args[3]; @@ -359,13 +375,13 @@ void MapLoader::PO_Init (void) // Find the startSpot points, and spawn each polyobj for (int i=polythings.Size()-1; i >= 0; i--) { - // 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch + // 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch, Health = crusher/hurter damage int type = polythings[i]->info->Special; if (type >= SMT_PolySpawn && type <= SMT_PolySpawnHurt) { // Polyobj StartSpot Pt. - Level->Polyobjects[polyIndex].StartSpot.pos = polythings[i]->pos; - SpawnPolyobj(polyIndex, polythings[i]->angle, type); + Level->Polyobjects[polyIndex].StartSpot.pos = polythings[i]->pos.XY(); + SpawnPolyobj(polyIndex, polythings[i]->angle, type, polythings[i]->Health); polyIndex++; } } @@ -375,7 +391,7 @@ void MapLoader::PO_Init (void) if (type == SMT_PolyAnchor) { // Polyobj Anchor Pt. - TranslateToStartSpot (polythings[i]->angle, polythings[i]->pos); + TranslateToStartSpot (polythings[i]->angle, polythings[i]->pos.XY()); } } diff --git a/src/maploader/slopes.cpp b/src/maploader/slopes.cpp index 9567c6ef42..77c33cd745 100644 --- a/src/maploader/slopes.cpp +++ b/src/maploader/slopes.cpp @@ -424,7 +424,7 @@ void MapLoader::SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt, const i if (mt->info != NULL && mt->info->Type == NULL && (mt->info->Special == SMT_CopyFloorPlane || mt->info->Special == SMT_CopyCeilingPlane)) { - CopyPlane (mt->args[0], mt->pos, mt->info->Special == SMT_CopyCeilingPlane); + CopyPlane (mt->args[0], mt->pos.XY(), mt->info->Special == SMT_CopyCeilingPlane); mt->EdNum = 0; } } diff --git a/src/maploader/specials.cpp b/src/maploader/specials.cpp index 117e266c96..47663e8121 100644 --- a/src/maploader/specials.cpp +++ b/src/maploader/specials.cpp @@ -281,7 +281,7 @@ void MapLoader::SetupPortals() { if (s.mType == PORTS_STACKEDSECTORTHING && s.mSkybox) { - s.mDisplacement = s.mSkybox->Pos() - s.mSkybox->target->Pos(); + s.mDisplacement = s.mSkybox->Pos().XY() - s.mSkybox->target->Pos().XY(); s.mSkybox = nullptr; } } @@ -508,7 +508,7 @@ void MapLoader::InitSectorSpecial(sector_t *sector, int special) { if ((sector->special & DAMAGE_MASK) == 0x100) { - SetupSectorDamage(sector, TELEFRAG_DAMAGE, 0, 0, NAME_InstantDeath, 0); + SetupSectorDamage(sector, TELEFRAG_DAMAGE, 1, 256, NAME_InstantDeath, 0); } else if ((sector->special & DAMAGE_MASK) == 0x200) { @@ -574,7 +574,7 @@ void MapLoader::InitSectorSpecial(sector_t *sector, int special) case dScroll_EastLavaDamage: SetupSectorDamage(sector, 5, 16, 256, NAME_Fire, SECF_DMGTERRAINFX); - CreateScroller(EScroll::sc_floor, -4., 0, sector, 0); + CreateScroller(EScroll::sc_floor, -4., 0, sector, nullptr, 0); keepspecial = true; break; @@ -609,7 +609,7 @@ void MapLoader::InitSectorSpecial(sector_t *sector, int special) break; case Sky2: - sector->sky = PL_SKYFLAT; + sector->skytransfer = PL_SKYFLAT; break; default: @@ -631,13 +631,13 @@ void MapLoader::InitSectorSpecial(sector_t *sector, int special) int i = sector->special - Scroll_North_Slow; double dx = hexenScrollies[i][0] / 2.; double dy = hexenScrollies[i][1] / 2.; - CreateScroller(EScroll::sc_floor, dx, dy, sector, 0); + CreateScroller(EScroll::sc_floor, dx, dy, sector, nullptr, 0); } else if (sector->special >= Carry_East5 && sector->special <= Carry_East35) { // Heretic scroll special // Only east scrollers also scroll the texture - CreateScroller(EScroll::sc_floor, -0.5 * (1 << ((sector->special & 0xff) - Carry_East5)), 0, sector, 0); + CreateScroller(EScroll::sc_floor, -0.5 * (1 << ((sector->special & 0xff) - Carry_East5)), 0, sector, nullptr, 0); } keepspecial = true; break; @@ -872,7 +872,7 @@ void MapLoader::SpawnSpecials () { auto itr = Level->GetSectorTagIterator(line.args[0]); while ((s = itr.Next()) >= 0) - Level->sectors[s].sky = (line.Index() + 1) | PL_SKYFLAT; + Level->sectors[s].skytransfer = (line.Index() + 1) | PL_SKYFLAT; break; } } @@ -1466,7 +1466,8 @@ void MapLoader::SpawnScrollers() } -void MapLoader::CreateScroller(EScroll type, double dx, double dy, sector_t *affectee, int accel, EScrollPos scrollpos) +void MapLoader::CreateScroller(EScroll type, double dx, double dy, sector_t *sect, side_t* side, int accel, EScrollPos scrollpos, int scrollmode) { - Level->CreateThinker(type, dx, dy, nullptr, affectee, nullptr, accel, scrollpos); + Level->CreateThinker(type, dx, dy, nullptr, sect, side, accel, scrollpos, scrollmode); } + diff --git a/src/maploader/strifedialogue.cpp b/src/maploader/strifedialogue.cpp index cb2b2665bb..ac92736218 100644 --- a/src/maploader/strifedialogue.cpp +++ b/src/maploader/strifedialogue.cpp @@ -109,7 +109,7 @@ void MapLoader::LoadStrifeConversations (MapData *map, const char *mapname) bool addedDialogues = false; for (const FString &addd : gameinfo.AddDialogues) { - if (!LoadScriptFile(addd, true, 0)) + if (!LoadScriptFile(addd.GetChars(), true, 0)) { continue; } @@ -133,7 +133,7 @@ void MapLoader::LoadStrifeConversations (MapData *map, const char *mapname) if (gameinfo.Dialogue.IsNotEmpty()) { - if (LoadScriptFile(gameinfo.Dialogue, false, 0)) + if (LoadScriptFile(gameinfo.Dialogue.GetChars(), false, 0)) { if (addedDialogues) { diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index fb8fd8379d..ab2c939ede 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -52,6 +52,8 @@ #include "xlat/xlat.h" #include "maploader.h" #include "texturemanager.h" +#include "a_scroll.h" +#include "p_spec_thinkers.h" //=========================================================================== // @@ -104,6 +106,26 @@ static char HexenSectorSpecialOk[256]={ 1,1,1,1,1, }; +#if 0 +static const char* udmfsolidskewtypes[] = +{ + "none", + "front", + "back", + nullptr +}; + +static const char* udmfmaskedskewtypes[] = +{ + "none", + "front_floor", + "front_ceiling", + "back_floor", + "back_ceiling", + nullptr +}; +#endif + static inline bool P_IsThingSpecial(int specnum) { return (specnum >= Thing_Projectile && specnum <= Thing_SpawnNoFog) || @@ -279,7 +301,21 @@ const char *UDMFParserBase::CheckString(FName key) { sc.ScriptMessage("String value expected for key '%s'", key.GetChars()); } - return parsedString; + return parsedString.GetChars(); +} + +int UDMFParserBase::MatchString(FName key, const char* const* strings, int defval) +{ + const char* string = CheckString(key); + for (int i = 0; *strings != nullptr; i++, strings++) + { + if (!stricmp(string, *strings)) + { + return i; + } + } + sc.ScriptMessage("Unknown value %s for key '%s'", string, key.GetChars()); + return defval; } //=========================================================================== @@ -394,10 +430,10 @@ FString GetUDMFString(FLevelLocals *Level, int type, int index, FName key) struct UDMFScroll { - bool ceiling; + int where; int index; double x, y; - FName type; + int scrolltype; }; class UDMFParser : public UDMFParserBase @@ -413,7 +449,9 @@ class UDMFParser : public UDMFParserBase TArray ParsedSideTextures; TArray ParsedSectors; TArray ParsedVertices; - TArray UDMFScrollers; + TArray UDMFSectorScrollers; + TArray UDMFWallScrollers; + TArray UDMFThrusters; FDynamicColormap *fogMap = nullptr, *normMap = nullptr; FMissingTextureTracker &missingTex; @@ -480,6 +518,7 @@ class UDMFParser : public UDMFParserBase th->Alpha = -1; th->Health = 1; th->FloatbobPhase = -1; + th->SourceRadius = -1.0; sc.MustGetToken('{'); while (!sc.CheckToken('}')) { @@ -753,11 +792,33 @@ class UDMFParser : public UDMFParserBase th->friendlyseeblocks = CheckInt(key); break; + case NAME_SourceRadius: + th->SourceRadius = (float)CheckFloat(key); + break; + case NAME_lm_suncolor: - case NAME_lm_sampledistance: - case NAME_lm_gridsize: CHECK_N(Zd | Zdt) - break; + if (CheckInt(key) < 0 || CheckInt(key) > 0xFFFFFF) + { + DPrintf(DMSG_WARNING, "Sun Color '%x' is out of range %s\n", CheckInt(key)); + } + else + { + auto n = uint32_t(CheckInt(key)); + Level->SunColor = FVector3(float((n >> 16) & 0xFF) / 0xFF, float((n >> 8) & 0xFF) / 0xFF, float(n & 0xFF) / 0xFF); + } + break; + case NAME_lm_sampledist: + CHECK_N(Zd | Zdt) + if (CheckInt(key) >= 0 && CheckInt(key) <= 0xFFFF) + { + Level->LightmapSampleDistance = CheckInt(key); + } + else + { + DPrintf(DMSG_WARNING, "Can't set the global lm_sampledist to %s\n", key.GetChars()); + } + break; default: CHECK_N(Zd | Zdt) @@ -806,6 +867,16 @@ class UDMFParser : public UDMFParserBase th->special = 0; memset(th->args, 0, sizeof (th->args)); } + + if (th->EdNum == 9890) // ZDRAY INFO thing + { + FAngle angle = FAngle::fromDeg(float(th->angle)); + FAngle pitch = FAngle::fromDeg(float(th->pitch)); + + auto pc = pitch.Cos(); + Level->SunDirection = -FVector3 { pc * angle.Cos(), pc * angle.Sin(), -pitch.Sin() }; // [RaveYard]: is there a dedicated function for this? + Level->lightmaps = true; + } } //=========================================================================== @@ -1129,14 +1200,23 @@ class UDMFParser : public UDMFParserBase ld->healthgroup = CheckInt(key); break; - case NAME_lm_lightcolorline: - case NAME_lm_lightintensityline: - case NAME_lm_lightdistanceline: - case NAME_lm_sampledist_line: + case NAME_lm_sampledist: + CHECK_N(Zd | Zdt) + for (int i = 0; i < 3; ++i) + if (!ld->LightmapSampleDistance[i]) + ld->LightmapSampleDistance[i] = CheckInt(key); + break; case NAME_lm_sampledist_top: + CHECK_N(Zd | Zdt) + ld->LightmapSampleDistance[side_t::top] = CheckInt(key); + break; case NAME_lm_sampledist_mid: + CHECK_N(Zd | Zdt) + ld->LightmapSampleDistance[side_t::mid] = CheckInt(key); + break; case NAME_lm_sampledist_bot: CHECK_N(Zd | Zdt) + ld->LightmapSampleDistance[side_t::bottom] = CheckInt(key); break; default: @@ -1214,6 +1294,7 @@ class UDMFParser : public UDMFParserBase void ParseSidedef(side_t *sd, intmapsidedef_t *sdt, int index) { double texOfs[2]={0,0}; + DVector2 scrolls[4] = {}; memset(sd, 0, sizeof(*sd)); sdt->bottomtexture = "-"; @@ -1481,6 +1562,81 @@ class UDMFParser : public UDMFParserBase sd->Flags |= WALLF_EXTCOLOR; break; + case NAME_lm_sampledist: + CHECK_N(Zd | Zdt) + for (int i = 0; i < 3; ++i) + if (!sd->textures[i].LightmapSampleDistance) + sd->textures[i].LightmapSampleDistance = CheckInt(key); + break; + case NAME_lm_sampledist_top: + CHECK_N(Zd | Zdt) + sd->textures[side_t::top].LightmapSampleDistance = CheckInt(key); + break; + case NAME_lm_sampledist_mid: + CHECK_N(Zd | Zdt) + sd->textures[side_t::mid].LightmapSampleDistance = CheckInt(key); + break; + case NAME_lm_sampledist_bot: + CHECK_N(Zd | Zdt) + sd->textures[side_t::bottom].LightmapSampleDistance = CheckInt(key); + break; + +#if 0 // specs are to rough and too vague - needs to be cleared first how this works. + case NAME_skew_top_type: + CHECK_N(Zd | Zdt) + sd->textures[side_t::top].skew = MatchString(key, udmfsolidskewtypes, 0); + break; + + case NAME_skew_middle_type: + CHECK_N(Zd | Zdt) + sd->textures[side_t::mid].skew = MatchString(key, udmfmaskedskewtypes, 0); + break; + + case NAME_skew_bottom_type: + CHECK_N(Zd | Zdt) + sd->textures[side_t::bottom].skew = MatchString(key, udmfsolidskewtypes, 0); + break; +#endif + + case NAME_skew_top: + CHECK_N(Zd | Zdt) + sd->textures[side_t::top].skew = CheckInt(key); + break; + + case NAME_skew_middle: + CHECK_N(Zd | Zdt) + sd->textures[side_t::mid].skew = CheckInt(key); + break; + + case NAME_skew_bottom: + CHECK_N(Zd | Zdt) + sd->textures[side_t::bottom].skew = CheckInt(key); + break; + + case NAME_xscroll: + scrolls[0].X = CheckFloat(key); + break; + case NAME_yscroll: + scrolls[0].Y = CheckFloat(key); + break; + case NAME_xscrolltop: + scrolls[1].X = CheckFloat(key); + break; + case NAME_yscrolltop: + scrolls[1].Y = CheckFloat(key); + break; + case NAME_xscrollmid: + scrolls[2].X = CheckFloat(key); + break; + case NAME_yscrollmid: + scrolls[2].Y = CheckFloat(key); + break; + case NAME_xscrollbottom: + scrolls[3].X = CheckFloat(key); + break; + case NAME_yscrollbottom: + scrolls[3].Y = CheckFloat(key); + break; default: if (strnicmp("user_", key.GetChars(), 5)) DPrintf(DMSG_WARNING, "Unknown UDMF sidedef key %s\n", key.GetChars()); @@ -1499,6 +1655,21 @@ class UDMFParser : public UDMFParserBase sd->AddTextureYOffset(side_t::top, texOfs[1]); sd->AddTextureYOffset(side_t::mid, texOfs[1]); sd->AddTextureYOffset(side_t::bottom, texOfs[1]); + int scroll = scw_all; + for (int i = 1; i < 4; i++) + { + auto& scrl = scrolls[i]; + if (!scrl.isZero()) + { + int where = 1 << (i - 1); + scroll &= ~where; + UDMFWallScrollers.Push({ where, index, scrl.X, scrl.Y, 0 }); + } + } + if (!scrolls[0].isZero() && scroll) + { + UDMFWallScrollers.Push({ scroll, index, scrolls[0].X, scrolls[0].Y, 0}); + } } //=========================================================================== @@ -1520,11 +1691,19 @@ class UDMFParser : public UDMFParserBase // Brand new UDMF scroller properties double scroll_ceil_x = 0; double scroll_ceil_y = 0; - FName scroll_ceil_type = NAME_None; + int scroll_ceil_type = 0; double scroll_floor_x = 0; double scroll_floor_y = 0; - FName scroll_floor_type = NAME_None; + int scroll_floor_type = 0; + + double friction = -FLT_MAX, movefactor = -FLT_MAX; + + DVector2 thrust = { 0,0 }; + int thrustgroup = 0; + int thrustlocation = 0; + + const double scrollfactor = 1 / 3.2; // I hope this is correct, it's just a guess taken from Eternity's code. memset(sec, 0, sizeof(*sec)); sec->Level = Level; @@ -1938,30 +2117,110 @@ class UDMFParser : public UDMFParserBase break; case NAME_scroll_ceil_x: + scroll_ceil_x = CheckFloat(key) * scrollfactor; + break; + + case NAME_xscrollceiling: scroll_ceil_x = CheckFloat(key); break; case NAME_scroll_ceil_y: + scroll_ceil_y = CheckFloat(key) * scrollfactor; + break; + + case NAME_yscrollceiling: scroll_ceil_y = CheckFloat(key); break; + case NAME_scrollceilingmode: + scroll_ceil_type = CheckInt(key); + break; + case NAME_scroll_ceil_type: - scroll_ceil_type = CheckString(key); + { + const char* val = CheckString(key); + if (!stricmp(val, "both")) scroll_ceil_type = SCROLL_All; + else if (!stricmp(val, "visual")) scroll_ceil_type = SCROLL_Textures; + if (!stricmp(val, "physical")) scroll_ceil_type = SCROLL_All & ~SCROLL_Textures; + else scroll_ceil_type = 0; break; + } case NAME_scroll_floor_x: + scroll_floor_x = CheckFloat(key) * scrollfactor; + break; + + case NAME_xscrollfloor: scroll_floor_x = CheckFloat(key); break; case NAME_scroll_floor_y: + scroll_floor_y = CheckFloat(key) * scrollfactor; + break; + + case NAME_yscrollfloor: scroll_floor_y = CheckFloat(key); break; + case NAME_scrollfloormode: + scroll_floor_type = CheckInt(key); + break; + case NAME_scroll_floor_type: - scroll_floor_type = CheckString(key); + { + const char* val = CheckString(key); + if (!stricmp(val, "both")) scroll_floor_type = SCROLL_All; + else if (!stricmp(val, "visual")) scroll_floor_type = SCROLL_Textures; + if (!stricmp(val, "physical")) scroll_floor_type = SCROLL_All & ~SCROLL_Textures; + else scroll_floor_type = 0; + break; + } + + case NAME_colormap: + sec->selfmap = R_ColormapNumForName(CheckString(key)); + break; + + case NAME_frictionfactor: + friction = CheckFloat(key); + break; + + case NAME_movefactor: + movefactor = CheckFloat(key); + break; + + case NAME_skyfloor: + sec->planes[sector_t::floor].skytexture[0] = TexMan.CheckForTexture(CheckString(key), ETextureType::Wall, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); break; - // These two are used by Eternity for something I do not understand. + case NAME_skyfloor2: + sec->planes[sector_t::floor].skytexture[1] = TexMan.CheckForTexture(CheckString(key), ETextureType::Wall, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); + break; + + case NAME_skyceiling: + sec->planes[sector_t::ceiling].skytexture[0] = TexMan.CheckForTexture(CheckString(key), ETextureType::Wall, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); + break; + + case NAME_skyceiling2: + sec->planes[sector_t::ceiling].skytexture[1] = TexMan.CheckForTexture(CheckString(key), ETextureType::Wall, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); + break; + + case NAME_xthrust: + thrust.X = CheckFloat(key); + break; + + case NAME_ythrust: + thrust.Y = CheckFloat(key); + break; + + case NAME_thrustgroup: + thrustgroup = CheckInt(key); + break; + + case NAME_thrustlocation: + thrustlocation = CheckInt(key); + break; + + // These two are used by Eternity for something I do not understand. //case NAME_portal_ceil_useglobaltex: //case NAME_portal_floor_useglobaltex: @@ -1989,17 +2248,20 @@ class UDMFParser : public UDMFParserBase sec->health3dgroup = CheckInt(key); break; - case NAME_lm_lightcolorfloor: - case NAME_lm_lightintensityfloor: - case NAME_lm_lightdistancefloor: - case NAME_lm_lightcolorceiling: - case NAME_lm_lightintensityceiling: - case NAME_lm_lightdistanceceiling: case NAME_lm_sampledist_floor: + CHECK_N(Zd | Zdt) + sec->planes[sector_t::floor].LightmapSampleDistance = CheckInt(key); + break; + case NAME_lm_sampledist_ceiling: CHECK_N(Zd | Zdt) + sec->planes[sector_t::ceiling].LightmapSampleDistance = CheckInt(key); break; + case NAME_lm_dynamic: + Flag(sec->Flags, SECF_LM_DYNAMIC, key); + continue; + default: if (strnicmp("user_", key.GetChars(), 5)) DPrintf(DMSG_WARNING, "Unknown UDMF sector key %s\n", key.GetChars()); @@ -2032,14 +2294,18 @@ class UDMFParser : public UDMFParserBase sec->Flags &= ~SECF_DAMAGEFLAGS; } - // Cannot be initialized yet because they need the final sector array. + // These cannot be initialized yet because they need the final sector array. if (scroll_ceil_type != NAME_None) { - UDMFScrollers.Push({ true, index, scroll_ceil_x, scroll_ceil_y, scroll_ceil_type }); + UDMFSectorScrollers.Push({ true, index, scroll_ceil_x, scroll_ceil_y, scroll_ceil_type }); } if (scroll_floor_type != NAME_None) { - UDMFScrollers.Push({ false, index, scroll_floor_x, scroll_floor_y, scroll_floor_type }); + UDMFSectorScrollers.Push({ false, index, scroll_floor_x, scroll_floor_y, scroll_floor_type }); + } + if (!thrust.isZero()) + { + UDMFThrusters.Push({ thrustlocation, index, thrust.X, thrust.Y, thrustgroup }); } @@ -2063,6 +2329,7 @@ class UDMFParser : public UDMFParserBase DVector3 n = DVector3(cp[0], cp[1], cp[2]).Unit(); sec->ceilingplane.set(n.X, n.Y, n.Z, cp[3]); } + sec->CheckOverlap(); if (lightcolor == ~0u && fadecolor == ~0u && desaturation == -1 && fogdensity == -1) { @@ -2092,6 +2359,16 @@ class UDMFParser : public UDMFParserBase sec->Colormap.Desaturation = clamp(desaturation, 0, 255); sec->Colormap.FogDensity = clamp(fogdensity, 0, 512) / 2; } + if (friction > -FLT_MAX) + { + sec->friction = clamp(friction, 0., 1.); + sec->movefactor = FrictionToMoveFactor(sec->friction); + sec->Flags |= SECF_FRICTION; + } + if (movefactor > -FLT_MAX) + { + sec->movefactor = max(movefactor, 1 / 2048.); + } } //=========================================================================== @@ -2143,7 +2420,7 @@ class UDMFParser : public UDMFParserBase // //=========================================================================== - void ProcessLineDefs() + void ProcessLineDefs(TArray>& siderefs) { int sidecount = 0; for(unsigned i = 0, skipped = 0; i < ParsedLines.Size();) @@ -2178,6 +2455,7 @@ class UDMFParser : public UDMFParserBase } } unsigned numlines = ParsedLines.Size(); + siderefs.Resize(ParsedSides.Size()); Level->sides.Alloc(sidecount); Level->lines.Alloc(numlines); int line, side; @@ -2197,11 +2475,25 @@ class UDMFParser : public UDMFParserBase int mapside = int(intptr_t(lines[line].sidedef[sd]))-1; if (mapside < sidecount) { + siderefs[mapside].Push(side); sides[side] = ParsedSides[mapside]; sides[side].linedef = &lines[line]; sides[side].sector = &Level->sectors[intptr_t(sides[side].sector)]; lines[line].sidedef[sd] = &sides[side]; +#if 0 + if (sd == 1) + { + // fix flags for backside. The definition is linedef relative, not sidedef relative. + static const uint8_t swaps[] = { 0, side_t::skew_back, side_t::skew_front }; + static const uint8_t swapsm[] = {0, side_t::skew_back_floor, side_t::skew_back_ceiling, side_t::skew_front_floor, side_t::skew_front_ceiling}; + + sides[side].textures[side_t::top].skew = swaps[sides[side].textures[side_t::top].skew]; + sides[side].textures[side_t::bottom].skew = swaps[sides[side].textures[side_t::bottom].skew]; + sides[side].textures[side_t::mid].skew = swapsm[sides[side].textures[side_t::mid].skew]; + } +#endif + loader->ProcessSideTextures(!isExtended, &sides[side], sides[side].sector, &ParsedSideTextures[mapside], lines[line].special, lines[line].args[0], &tempalpha[sd], missingTex); @@ -2252,6 +2544,7 @@ class UDMFParser : public UDMFParserBase namespc = sc.String; switch(namespc.GetIndex()) { + case NAME_Dsda: case NAME_ZDoom: case NAME_Eternity: namespace_bits = Zd; @@ -2390,23 +2683,34 @@ class UDMFParser : public UDMFParserBase { Level->sectors[i].e = &Level->extsectors[i]; } + + // Create the real linedefs and decompress the sidedefs. Must be done before + TArray> siderefs; + ProcessLineDefs(siderefs); + // Now create the scrollers. - for (auto &scroll : UDMFScrollers) + for (auto &scroll : UDMFSectorScrollers) { - const double scrollfactor = 1 / 3.2; // I hope this is correct, it's just a guess taken from Eternity's code. - if (scroll.type == NAME_Both || scroll.type == NAME_Visual) + if (scroll.scrolltype & SCROLL_Textures) { - loader->CreateScroller(scroll.ceiling ? EScroll::sc_ceiling : EScroll::sc_floor, scroll.x * scrollfactor, scroll.y * scrollfactor, &Level->sectors[scroll.index], 0); + loader->CreateScroller(scroll.where == 1 ? EScroll::sc_ceiling : EScroll::sc_floor, -scroll.x, scroll.y, &Level->sectors[scroll.index], nullptr, 0); } - if (scroll.type == NAME_Both || scroll.type == NAME_Physical) + if (scroll.scrolltype & (SCROLL_StaticObjects | SCROLL_Players | SCROLL_Monsters)) { - // sc_carry_ceiling doesn't do anything yet. - loader->CreateScroller(scroll.ceiling ? EScroll::sc_carry_ceiling : EScroll::sc_carry, scroll.x * scrollfactor, scroll.y * scrollfactor, &Level->sectors[scroll.index], 0); + loader->CreateScroller(scroll.where == 1 ? EScroll::sc_carry_ceiling : EScroll::sc_carry, scroll.x, scroll.y, &Level->sectors[scroll.index], nullptr, 0, scw_all, scroll.scrolltype); } } - - // Create the real linedefs and decompress the sidedefs - ProcessLineDefs(); + for (auto& scroll : UDMFWallScrollers) + { + for(auto sd : siderefs[scroll.index]) + { + loader->CreateScroller(EScroll::sc_side, scroll.x, scroll.y, nullptr, &Level->sides[sd], 0); + } + } + for (auto& scroll : UDMFThrusters) + { + Level->CreateThinker(&Level->sectors[scroll.index], scroll.x, scroll.y, scroll.scrolltype, scroll.where); + } } }; diff --git a/src/maploader/udmf.h b/src/maploader/udmf.h index ed18345b54..38d904288b 100644 --- a/src/maploader/udmf.h +++ b/src/maploader/udmf.h @@ -21,6 +21,7 @@ class UDMFParserBase DAngle CheckAngle(FName key); bool CheckBool(FName key); const char *CheckString(FName key); + int MatchString(FName key, const char* const* strings, int defval); template bool Flag(T &value, int mask, FName key) diff --git a/src/menu/doommenu.cpp b/src/menu/doommenu.cpp index e9b5f018c7..08bf38f42c 100644 --- a/src/menu/doommenu.cpp +++ b/src/menu/doommenu.cpp @@ -85,6 +85,66 @@ bool OkForLocalization(FTextureID texnum, const char* substitute); FNewGameStartup NewGameStartupInfo; int LastSkill = -1; +void StartGameDirect(bool hasPlayerClass, bool randomPlayerClass, PClassActor * playerClass, int Episode, int Skill) +{ + // shouldn't work outside of a menu + if (DMenu::InMenu) + { + if(!netgame) + { + NewGameStartupInfo.hasPlayerClass = hasPlayerClass; + + if(hasPlayerClass) + { + if(randomPlayerClass) + { + NewGameStartupInfo.PlayerClass = "Random"; + } + else if(!playerClass) + { + NullParam("playerClass"); + } + else + { + NewGameStartupInfo.PlayerClass = playerClass->GetDisplayName(); + } + } + + NewGameStartupInfo.Episode = Episode; + NewGameStartupInfo.Skill = Skill; + + G_DeferedInitNew (&NewGameStartupInfo); + + if (gamestate == GS_FULLCONSOLE) + { + gamestate = GS_HIDECONSOLE; + gameaction = ga_newgame; + } + } + else + { + DPrintf(DMSG_WARNING, TEXTCOLOR_RED "Cannot start a new game during a netgame\n"); + } + + M_ClearMenus (); + } + else + { + ThrowAbortException(X_OTHER, "Attempt to start a new game outside of menu code"); + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(DMenu, StartGameDirect, StartGameDirect) +{ + PARAM_PROLOGUE; + PARAM_BOOL(hasPlayerClass); + PARAM_BOOL(randomPlayerClass); + PARAM_POINTER(playerClass, PClassActor); + PARAM_INT(Episode); + PARAM_INT(Skill); + StartGameDirect(hasPlayerClass, randomPlayerClass, playerClass, Episode, Skill); + return 0; +} bool M_SetSpecialMenu(FName& menu, int param) { @@ -126,9 +186,17 @@ bool M_SetSpecialMenu(FName& menu, int param) // sent from the player class menu NewGameStartupInfo.Skill = -1; NewGameStartupInfo.Episode = -1; - NewGameStartupInfo.PlayerClass = - param == -1000? nullptr : - param == -1? "Random" : GetPrintableDisplayName(PlayerClasses[param].Type).GetChars(); + + if(param == -1000) + { + NewGameStartupInfo.hasPlayerClass = false; + } + else + { + NewGameStartupInfo.hasPlayerClass = true; + NewGameStartupInfo.PlayerClass = (param == -1) ? FString("Random") : PlayerClasses[param].Type->GetDisplayName(); + } + M_StartupEpisodeMenu(&NewGameStartupInfo); // needs player class name from class menu (later) break; @@ -138,7 +206,7 @@ bool M_SetSpecialMenu(FName& menu, int param) if ((gameinfo.flags & GI_SHAREWARE) && param > 0) { // Only Doom and Heretic have multi-episode shareware versions. - M_StartMessage(GStrings("SWSTRING"), 1); + M_StartMessage(GStrings.GetString("SWSTRING"), 1); return false; } @@ -152,8 +220,8 @@ bool M_SetSpecialMenu(FName& menu, int param) NewGameStartupInfo.Skill = param; LastSkill = param; - const char *msg = AllSkills[param].MustConfirmText; - if (*msg==0) msg = GStrings("NIGHTMARE"); + const char *msg = AllSkills[param].MustConfirmText.GetChars(); + if (*msg==0) msg = GStrings.GetString("NIGHTMARE"); M_StartMessage (msg, 0, NAME_StartgameConfirmed); return false; } @@ -179,13 +247,13 @@ bool M_SetSpecialMenu(FName& menu, int param) if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer) || gamestate != GS_LEVEL) { // cannot save outside the game. - M_StartMessage (GStrings("SAVEDEAD"), 1); + M_StartMessage (GStrings.GetString("SAVEDEAD"), 1); return false; } - if ((primaryLevel->flags9 & LEVEL9_NOUSERSAVE)) + if ((primaryLevel->vkdflags & VKDLEVELFLAG_NOUSERSAVE)) { - M_StartMessage(GStrings("SAVEDEAD"), 1); + M_StartMessage(GStrings.GetString("SAVEDEAD"), 1); return false; } @@ -217,7 +285,7 @@ bool M_SetSpecialMenu(FName& menu, int param) { if ((*desc)->mNetgameMessage.IsNotEmpty() && netgame && !demoplayback) { - M_StartMessage((*desc)->mNetgameMessage, 1); + M_StartMessage((*desc)->mNetgameMessage.GetChars(), 1); return false; } } @@ -295,6 +363,7 @@ void System_M_Dim() static void M_Quit() { + DeleteScreenJob(); S_StopAllChannels(); S_StopMusic(true); CleanSWDrawer(); @@ -318,21 +387,21 @@ CCMD (menu_quit) const size_t messageindex = static_cast(gametic) % gameinfo.quitmessages.Size(); FString EndString; - const char *msg = gameinfo.quitmessages[messageindex]; + const char *msg = gameinfo.quitmessages[messageindex].GetChars(); if (msg[0] == '$') { if (msg[1] == '*') { - EndString = GStrings(msg + 2); + EndString = GStrings.GetString(msg + 2); } else { - EndString.Format("%s\n\n%s", GStrings(msg + 1), GStrings("DOSY")); + EndString.Format("%s\n\n%s", GStrings.GetString(msg + 1), GStrings.GetString("DOSY")); } } else EndString = gameinfo.quitmessages[messageindex]; - DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, EndString, 0, false, NAME_None, []() + DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, EndString.GetChars(), 0, false, NAME_None, []() { if (!netgame) { @@ -359,8 +428,8 @@ CCMD (menu_quit) void ActivateEndGameMenu() { - FString tempstring = GStrings(netgame ? "NETEND" : "ENDGAME"); - DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() + FString tempstring = GStrings.GetString(netgame ? "NETEND" : "ENDGAME"); + DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring.GetChars(), 0, false, NAME_None, []() { M_ClearMenus(); if (!netgame) @@ -402,7 +471,7 @@ CCMD (quicksave) return; } - if ((primaryLevel->flags9 & LEVEL9_NOUSERSAVE)) + if ((primaryLevel->vkdflags & VKDLEVELFLAG_NOUSERSAVE)) return; if (gamestate != GS_LEVEL) @@ -432,10 +501,10 @@ CCMD (quicksave) S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); - FString tempstring = GStrings("QSPROMPT"); + FString tempstring = GStrings.GetString("QSPROMPT"); tempstring.Substitute("%s", savegameManager.quickSaveSlot->SaveTitle.GetChars()); - DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() + DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring.GetChars(), 0, false, NAME_None, []() { G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars()); S_Sound(CHAN_VOICE, CHANF_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE); @@ -456,7 +525,7 @@ CCMD (quickload) if (netgame) { M_StartControlPanel(true); - M_StartMessage (GStrings("QLOADNET"), 1); + M_StartMessage (GStrings.GetString("QLOADNET"), 1); return; } @@ -475,12 +544,12 @@ CCMD (quickload) G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars()); return; } - FString tempstring = GStrings("QLPROMPT"); + FString tempstring = GStrings.GetString("QLPROMPT"); tempstring.Substitute("%s", savegameManager.quickSaveSlot->SaveTitle.GetChars()); M_StartControlPanel(true); - DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []() + DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring.GetChars(), 0, false, NAME_None, []() { G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars()); S_Sound(CHAN_VOICE, CHANF_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE); @@ -499,13 +568,13 @@ CCMD (togglemessages) { if (show_messages) { - Printf(TEXTCOLOR_RED "%s\n", GStrings("MSGOFF")); + Printf(TEXTCOLOR_RED "%s\n", GStrings.GetString("MSGOFF")); show_messages = false; } else { show_messages = true; - Printf(TEXTCOLOR_RED "%s\n", GStrings("MSGON")); + Printf(TEXTCOLOR_RED "%s\n", GStrings.GetString("MSGON")); } } @@ -547,8 +616,8 @@ CCMD(reset2defaults) CCMD(reset2saved) { GameConfig->DoGlobalSetup (); - GameConfig->DoGameSetup (gameinfo.ConfigName); - GameConfig->DoModSetup (gameinfo.ConfigName); + GameConfig->DoGameSetup (gameinfo.ConfigName.GetChars()); + GameConfig->DoModSetup (gameinfo.ConfigName.GetChars()); R_SetViewSize (screenblocks); } @@ -606,8 +675,8 @@ void M_StartupEpisodeMenu(FNewGameStartup *gs) { if (AllEpisodes[i].mPicName.IsNotEmpty()) { - FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName); - if (AllEpisodes[i].mEpisodeName.IsEmpty() || OkForLocalization(tex, AllEpisodes[i].mEpisodeName)) + FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName.GetChars()); + if (AllEpisodes[i].mEpisodeName.IsEmpty() || OkForLocalization(tex, AllEpisodes[i].mEpisodeName.GetChars())) continue; } if ((gameinfo.gametype & GAME_DoomStrifeChex) && spacing == 16) spacing = 18; @@ -638,12 +707,12 @@ void M_StartupEpisodeMenu(FNewGameStartup *gs) DMenuItemBase *it = nullptr; if (AllEpisodes[i].mPicName.IsNotEmpty()) { - FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName); - if (AllEpisodes[i].mEpisodeName.IsEmpty() || OkForLocalization(tex, AllEpisodes[i].mEpisodeName)) + FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName.GetChars()); + if (AllEpisodes[i].mEpisodeName.IsEmpty() || OkForLocalization(tex, AllEpisodes[i].mEpisodeName.GetChars())) continue; // We do not measure patch based entries. They are assumed to fit } - const char *c = AllEpisodes[i].mEpisodeName; - if (*c == '$') c = GStrings(c + 1); + const char *c = AllEpisodes[i].mEpisodeName.GetChars(); + if (*c == '$') c = GStrings.GetString(c + 1); int textwidth = ld->mFont->StringWidth(c); int textright = posx + textwidth; if (posx + textright > 320) posx = max(0, 320 - textright); @@ -654,14 +723,14 @@ void M_StartupEpisodeMenu(FNewGameStartup *gs) DMenuItemBase *it = nullptr; if (AllEpisodes[i].mPicName.IsNotEmpty()) { - FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName); - if (AllEpisodes[i].mEpisodeName.IsEmpty() || OkForLocalization(tex, AllEpisodes[i].mEpisodeName)) + FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName.GetChars()); + if (AllEpisodes[i].mEpisodeName.IsEmpty() || OkForLocalization(tex, AllEpisodes[i].mEpisodeName.GetChars())) it = CreateListMenuItemPatch(posx, posy, spacing, AllEpisodes[i].mShortcut, tex, NAME_Skillmenu, i); } if (it == nullptr) { it = CreateListMenuItemText(posx, posy, spacing, AllEpisodes[i].mShortcut, - AllEpisodes[i].mEpisodeName, ld->mFont, ld->mFontColor, ld->mFontColor2, NAME_Skillmenu, i); + AllEpisodes[i].mEpisodeName.GetChars(), ld->mFont, ld->mFontColor, ld->mFontColor2, NAME_Skillmenu, i); } ld->mItems.Push(it); posy += spacing; @@ -701,7 +770,7 @@ void M_StartupEpisodeMenu(FNewGameStartup *gs) GC::WriteBarrier(od); for(unsigned i = 0; i < AllEpisodes.Size(); i++) { - auto it = CreateOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName, "Skillmenu", i); + auto it = CreateOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName.GetChars(), "Skillmenu", i); od->mItems.Push(it); GC::WriteBarrier(od, it); } @@ -745,7 +814,7 @@ static void BuildPlayerclassMenu() { if (!(PlayerClasses[i].Flags & PCF_NOMENU)) { - const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); + const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type).GetChars(); if (pname != nullptr) { numclassitems++; @@ -782,7 +851,7 @@ static void BuildPlayerclassMenu() { if (!(PlayerClasses[i].Flags & PCF_NOMENU)) { - const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); + const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type).GetChars(); if (pname != nullptr) { auto it = CreateListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, @@ -801,7 +870,7 @@ static void BuildPlayerclassMenu() } if (n == 0) { - const char *pname = GetPrintableDisplayName(PlayerClasses[0].Type); + const char *pname = GetPrintableDisplayName(PlayerClasses[0].Type).GetChars(); if (pname != nullptr) { auto it = CreateListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, @@ -842,7 +911,7 @@ static void BuildPlayerclassMenu() { if (!(PlayerClasses[i].Flags & PCF_NOMENU)) { - const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); + const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type).GetChars(); if (pname != nullptr) { auto it = CreateOptionMenuItemSubmenu(pname, "Episodemenu", i); @@ -934,12 +1003,12 @@ static void InitKeySections() FKeySection *sect = &KeySections[i]; DMenuItemBase *item = CreateOptionMenuItemStaticText(" "); menu->mItems.Push(item); - item = CreateOptionMenuItemStaticText(sect->mTitle, 1); + item = CreateOptionMenuItemStaticText(sect->mTitle.GetChars(), 1); menu->mItems.Push(item); for (unsigned j = 0; j < sect->mActions.Size(); j++) { FKeyAction *act = §->mActions[j]; - item = CreateOptionMenuItemControl(act->mTitle, act->mAction, &Bindings); + item = CreateOptionMenuItemControl(act->mTitle.GetChars(), act->mAction, &Bindings); menu->mItems.Push(item); } } @@ -1142,8 +1211,8 @@ void M_StartupSkillMenu(FNewGameStartup *gs) { if (MenuSkills[i]->PicName.IsNotEmpty()) { - FTextureID tex = GetMenuTexture(MenuSkills[i]->PicName); - if (MenuSkills[i]->MenuName.IsEmpty() || OkForLocalization(tex, MenuSkills[i]->MenuName)) + FTextureID tex = GetMenuTexture(MenuSkills[i]->PicName.GetChars()); + if (MenuSkills[i]->MenuName.IsEmpty() || OkForLocalization(tex, MenuSkills[i]->MenuName.GetChars())) continue; } if ((gameinfo.gametype & GAME_DoomStrifeChex) && spacing == 16) spacing = 18; @@ -1181,19 +1250,19 @@ void M_StartupSkillMenu(FNewGameStartup *gs) DMenuItemBase *li = nullptr; FString *pItemText = nullptr; - if (gs->PlayerClass != nullptr) + if (gs->hasPlayerClass) { pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass); } if (skill.PicName.Len() != 0 && pItemText == nullptr) { - FTextureID tex = GetMenuTexture(skill.PicName); - if (skill.MenuName.IsEmpty() || OkForLocalization(tex, skill.MenuName)) + FTextureID tex = GetMenuTexture(skill.PicName.GetChars()); + if (skill.MenuName.IsEmpty() || OkForLocalization(tex, skill.MenuName.GetChars())) continue; } const char *c = pItemText ? pItemText->GetChars() : skill.MenuName.GetChars(); - if (*c == '$') c = GStrings(c + 1); + if (*c == '$') c = GStrings.GetString(c + 1); int textwidth = ld->mFont->StringWidth(c); int textright = posx + textwidth; if (posx + textright > 320) posx = max(0, 320 - textright); @@ -1208,7 +1277,7 @@ void M_StartupSkillMenu(FNewGameStartup *gs) FName action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ? NAME_StartgameConfirm : NAME_Startgame; FString *pItemText = nullptr; - if (gs->PlayerClass != nullptr) + if (gs->hasPlayerClass) { pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass); } @@ -1217,14 +1286,14 @@ void M_StartupSkillMenu(FNewGameStartup *gs) if (color == CR_UNTRANSLATED) color = ld->mFontColor; if (skill.PicName.Len() != 0 && pItemText == nullptr) { - FTextureID tex = GetMenuTexture(skill.PicName); - if (skill.MenuName.IsEmpty() || OkForLocalization(tex, skill.MenuName)) + FTextureID tex = GetMenuTexture(skill.PicName.GetChars()); + if (skill.MenuName.IsEmpty() || OkForLocalization(tex, skill.MenuName.GetChars())) li = CreateListMenuItemPatch(posx, y, spacing, skill.Shortcut, tex, action, SkillIndices[i]); } if (li == nullptr) { li = CreateListMenuItemText(posx, y, spacing, skill.Shortcut, - pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, SkillIndices[i]); + pItemText? pItemText->GetChars() : skill.MenuName.GetChars(), ld->mFont, color, ld->mFontColor2, action, SkillIndices[i]); } ld->mItems.Push(li); GC::WriteBarrier(*desc, li); @@ -1278,11 +1347,11 @@ void M_StartupSkillMenu(FNewGameStartup *gs) "StartgameConfirm" : "Startgame"; FString *pItemText = nullptr; - if (gs->PlayerClass != nullptr) + if (gs->hasPlayerClass) { pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass); } - li = CreateOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, SkillIndices[i]); + li = CreateOptionMenuItemSubmenu(pItemText? pItemText->GetChars() : skill.MenuName.GetChars(), action, SkillIndices[i]); od->mItems.Push(li); GC::WriteBarrier(od, li); if (!done) diff --git a/src/menu/doommenu.h b/src/menu/doommenu.h index f80c7571fd..3e9b5a75aa 100644 --- a/src/menu/doommenu.h +++ b/src/menu/doommenu.h @@ -4,7 +4,8 @@ struct FNewGameStartup { - const char *PlayerClass; + bool hasPlayerClass; + FString PlayerClass; int Episode; int Skill; }; diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 3eba261143..331575737e 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -44,7 +44,7 @@ #include "vm.h" #include "i_system.h" #include "v_video.h" -#include "findfile.h" +#include "fs_findfile.h" #include "v_draw.h" // Save name length limit for old binary formats. @@ -62,35 +62,29 @@ void FSavegameManager::ReadSaveStrings() { if (SaveGames.Size() == 0) { - void *filefirst; - findstate_t c_file; FString filter; LastSaved = LastAccessed = -1; quickSaveSlot = nullptr; - filter = G_BuildSaveName("*"); - filefirst = I_FindFirst(filter.GetChars(), &c_file); - if (filefirst != ((void *)(-1))) + FileSys::FileList list; + if (FileSys::ScanDirectory(list, G_GetSavegamesFolder().GetChars(), "*." SAVEGAME_EXT, true)) { - do + for (auto& entry : list) { - // I_FindName only returns the file's name and not its full path - FString filepath = G_BuildSaveName(I_FindName(&c_file)); - - std::unique_ptr savegame(FResourceFile::OpenResourceFile(filepath, true, true)); + std::unique_ptr savegame(FResourceFile::OpenResourceFile(entry.FilePath.c_str(), true)); if (savegame != nullptr) { bool oldVer = false; bool missing = false; - FResourceLump *info = savegame->FindLump("info.json"); - if (info == nullptr) + auto info = savegame->FindEntry("info.json"); + if (info < 0) { // savegame info not found. This is not a savegame so leave it alone. continue; } - void *data = info->Lock(); + auto data = savegame->Read(info); FSerializer arc; - if (arc.OpenReader((const char *)data, info->LumpSize)) + if (arc.OpenReader(data.string(), data.size())) { int savever = 0; arc("Save Version", savever); @@ -122,89 +116,14 @@ void FSavegameManager::ReadSaveStrings() } FSaveGameNode *node = new FSaveGameNode; - node->Filename = filepath; + node->Filename = entry.FilePath.c_str(); node->bOldVersion = oldVer; node->bMissingWads = missing; node->SaveTitle = title; InsertSaveNode(node); } - - } - else // check for old formats. - { - FileReader file; - if (file.OpenFile(filepath)) - { - PNGHandle *png; - char sig[16]; - char title[OLDSAVESTRINGSIZE + 1]; - bool oldVer = true; - bool addIt = false; - bool missing = false; - - // ZDoom 1.23 betas 21-33 have the savesig first. - // Earlier versions have the savesig second. - // Later versions have the savegame encapsulated inside a PNG. - // - // Old savegame versions are always added to the menu so - // the user can easily delete them if desired. - - title[OLDSAVESTRINGSIZE] = 0; - - if (nullptr != (png = M_VerifyPNG(file))) - { - char *ver = M_GetPNGText(png, "ZDoom Save Version"); - if (ver != nullptr) - { - // An old version - if (!M_GetPNGText(png, "Title", title, OLDSAVESTRINGSIZE)) - { - strncpy(title, I_FindName(&c_file), OLDSAVESTRINGSIZE); - } - addIt = true; - delete[] ver; - } - delete png; - } - else - { - file.Seek(0, FileReader::SeekSet); - if (file.Read(sig, 16) == 16) - { - - if (strncmp(sig, "ZDOOMSAVE", 9) == 0) - { - if (file.Read(title, OLDSAVESTRINGSIZE) == OLDSAVESTRINGSIZE) - { - addIt = true; - } - } - else - { - memcpy(title, sig, 16); - if (file.Read(title + 16, OLDSAVESTRINGSIZE - 16) == OLDSAVESTRINGSIZE - 16 && - file.Read(sig, 16) == 16 && - strncmp(sig, "ZDOOMSAVE", 9) == 0) - { - addIt = true; - } - } - } - } - - if (addIt) - { - FSaveGameNode *node = new FSaveGameNode; - node->Filename = filepath; - node->bOldVersion = true; - node->bMissingWads = false; - node->SaveTitle = title; - InsertSaveNode(node); - } - } } - } while (I_FindNext(filefirst, &c_file) == 0); - I_FindClose(filefirst); + } } } } @@ -252,7 +171,7 @@ FString FSavegameManager::ExtractSaveComment(FSerializer &arc) FString FSavegameManager::BuildSaveName(const char* prefix, int slot) { - return G_BuildSaveName(FStringf("%s%02d", prefix, slot)); + return G_BuildSaveName(FStringf("%s%02d", prefix, slot).GetChars()); } //============================================================================= diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index 6c930147cf..07192a2d90 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -81,7 +81,7 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, PlayerNameChanged) { PARAM_PROLOGUE; PARAM_STRING(s); - const char *pp = s; + const char *pp = s.GetChars(); FString command("name \""); if (DMenu::InMenu) @@ -96,7 +96,7 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, PlayerNameChanged) command << *p; } command << '"'; - C_DoCommand(command); + C_DoCommand(command.GetChars()); } return 0; } @@ -155,7 +155,7 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, SkinChanged) if (DMenu::InMenu) { players[consoleplayer].userinfo.SkinNumChanged(sel); - cvar_set("skin", Skins[sel].Name); + cvar_set("skin", Skins[sel].Name.GetChars()); } return 0; } diff --git a/src/namedef_custom.h b/src/namedef_custom.h index d0964ce7ff..39bba8085b 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -12,6 +12,9 @@ xx(BloodSplatter) xx(AxeBlood) xx(Spray) +// Actor properties +xx(BobPivot3D) + // Invulnerability types xx(Ghost) xx(Reflective) @@ -459,6 +462,7 @@ xx(WBobSpeed) xx(WBobFire) xx(PlayerClass) xx(MonsterClass) +xx(Morph) xx(MorphedMonster) xx(Wi_NoAutostartMap) @@ -672,6 +676,7 @@ xx(ZDoomTranslated) xx(Vavoom) xx(GZDoom) xx(Eternity) +xx(Dsda) xx(Xpanningfloor) xx(Ypanningfloor) @@ -849,24 +854,50 @@ xx(Sky) xx(Pagename) // Lightmap/ZDRay keywords -// (Surface lights are temporarily disabled and don't do anything) -xx(lm_lightcolorline) -xx(lm_lightintensityline) -xx(lm_lightdistanceline) -xx(lm_lightcolorfloor) -xx(lm_lightintensityfloor) -xx(lm_lightdistancefloor) -xx(lm_lightcolorceiling) -xx(lm_lightintensityceiling) -xx(lm_lightdistanceceiling) -xx(lm_sampledist_line) +xx(lm_sampledist) xx(lm_sampledist_top) xx(lm_sampledist_mid) xx(lm_sampledist_bot) xx(lm_sampledist_floor) xx(lm_sampledist_ceiling) +xx(lm_dynamic) xx(lm_suncolor) -xx(lm_sampledistance) -xx(lm_gridsize) + +// Light keywords +xx(SourceRadius) + +xx(skew_bottom_type) +xx(skew_middle_type) +xx(skew_top_type) +xx(skew_bottom) +xx(skew_middle) +xx(skew_top) + +xx(xscroll) +xx(yscroll) +xx(xscrolltop) +xx(yscrolltop) +xx(xscrollmid) +xx(yscrollmid) +xx(xscrollbottom) +xx(yscrollbottom) +xx(xscrollfloor) +xx(yscrollfloor) +xx(scrollfloormode) +xx(xscrollceiling) +xx(yscrollceiling) +xx(scrollceilingmode) +xx(xthrust) +xx(ythrust) +xx(thrustgroup) +xx(thrustlocation) +xx(colormap) +xx(skyfloor) +xx(skyceiling) +xx(skyfloor2) +xx(skyceiling2) +xx(frictionfactor) +xx(movefactor) xx(Corona) +xx(Fogball) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 47d9a896f5..f8ee0a8e5b 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -276,17 +276,17 @@ DEFINE_ACTION_FUNCTION(DConversationMenu, SendConversationReply) switch (node) { case -1: - Net_WriteByte(DEM_CONVNULL); + Net_WriteInt8(DEM_CONVNULL); break; case -2: - Net_WriteByte(DEM_CONVCLOSE); + Net_WriteInt8(DEM_CONVCLOSE); break; default: - Net_WriteByte(DEM_CONVREPLY); - Net_WriteWord(node); - Net_WriteByte(reply); + Net_WriteInt8(DEM_CONVREPLY); + Net_WriteInt16(node); + Net_WriteInt8(reply); break; } StaticLastReply = reply; @@ -503,7 +503,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply // No, you don't. Say so and let the NPC animate negatively. if (reply->QuickNo.IsNotEmpty() && isconsole) { - TerminalResponse(reply->QuickNo); + TerminalResponse(reply->QuickNo.GetChars()); } npc->ConversationAnimation(2); if (!(npc->flags8 & MF8_DONTFACETALKER)) @@ -576,7 +576,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply { TakeStrifeItem (player, reply->ItemCheck[i].Item, reply->ItemCheck[i].Amount); } - replyText = reply->QuickYes; + replyText = reply->QuickYes.GetChars(); } else { @@ -586,10 +586,10 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply // Update the quest log, if needed. if (reply->LogString.IsNotEmpty()) { - const char *log = reply->LogString; + const char *log = reply->LogString.GetChars(); if (log[0] == '$') { - log = GStrings(log + 1); + log = GStrings.GetString(log + 1); } player->SetLogText(log); @@ -677,8 +677,8 @@ void P_ConversationCommand (int netcode, int pnum, uint8_t **stream) } if (netcode == DEM_CONVREPLY) { - int nodenum = ReadWord(stream); - int replynum = ReadByte(stream); + int nodenum = ReadInt16(stream); + int replynum = ReadInt8(stream); HandleReply(player, pnum == consoleplayer, nodenum, replynum); } else @@ -713,7 +713,7 @@ static void TerminalResponse (const char *str) // handle string table replacement if (str[0] == '$') { - str = GStrings(str + 1); + str = GStrings.GetString(str + 1); } if (StatusBar != NULL) diff --git a/src/p_conversation.h b/src/p_conversation.h index b055d5f4c5..d674b3d53e 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -72,7 +72,5 @@ void P_ResumeConversation (); void P_ConversationCommand (int netcode, int player, uint8_t **stream); -class FileReader; - #endif diff --git a/src/p_openmap.cpp b/src/p_openmap.cpp index 771ae1d877..ef688cda6b 100644 --- a/src/p_openmap.cpp +++ b/src/p_openmap.cpp @@ -125,8 +125,8 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) delete map; return NULL; } - map->resource = FResourceFile::OpenResourceFile(mapname, true); - wadReader = map->resource->GetReader(); + map->resource = FResourceFile::OpenResourceFile(mapname); + wadReader = map->resource->GetContainerReader(); } else { @@ -140,9 +140,9 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) // Names with more than 8 characters will only be checked as .wad and .map. if (strlen(mapname) <= 8) lump_name = fileSystem.CheckNumForName(mapname); fmt.Format("maps/%s.wad", mapname); - lump_wad = fileSystem.CheckNumForFullName(fmt); + lump_wad = fileSystem.CheckNumForFullName(fmt.GetChars()); fmt.Format("maps/%s.map", mapname); - lump_map = fileSystem.CheckNumForFullName(fmt); + lump_map = fileSystem.CheckNumForFullName(fmt.GetChars()); if (lump_name > lump_wad && lump_name > lump_map && lump_name != -1) { @@ -265,7 +265,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) map->lumpnum = lump_wad; auto reader = fileSystem.ReopenFileReader(lump_wad); map->resource = FResourceFile::OpenResourceFile(fileSystem.GetFileFullName(lump_wad), reader, true); - wadReader = map->resource->GetReader(); + wadReader = map->resource->GetContainerReader(); } } uint32_t id; @@ -280,21 +280,21 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) char maplabel[9]=""; int index=0; - map->MapLumps[0].Reader = map->resource->GetLump(0)->NewReader(); - uppercopy(map->MapLumps[0].Name, map->resource->GetLump(0)->getName()); + map->MapLumps[0].Reader = map->resource->GetEntryReader(0, FileSys::READER_SHARED); + uppercopy(map->MapLumps[0].Name, map->resource->getName(0)); - for(uint32_t i = 1; i < map->resource->LumpCount(); i++) + for(uint32_t i = 1; i < map->resource->EntryCount(); i++) { - const char* lumpname = map->resource->GetLump(i)->getName(); + const char* lumpname = map->resource->getName(i); if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8)) { map->isText = true; - map->MapLumps[ML_TEXTMAP].Reader = map->resource->GetLump(i)->NewReader(); + map->MapLumps[ML_TEXTMAP].Reader = map->resource->GetEntryReader(i, FileSys::READER_SHARED); strncpy(map->MapLumps[ML_TEXTMAP].Name, lumpname, 8); for(int i = 2;; i++) { - lumpname = map->resource->GetLump(i)->getName(); + lumpname = map->resource->getName(i); if (!strnicmp(lumpname, "ZNODES",8)) { index = ML_GLZNODES; @@ -326,7 +326,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) return map; } else continue; - map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); + map->MapLumps[index].Reader = map->resource->GetEntryReader(i, FileSys::READER_SHARED); strncpy(map->MapLumps[index].Name, lumpname, 8); } } @@ -358,7 +358,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) maplabel[8]=0; } - map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); + map->MapLumps[index].Reader = map->resource->GetEntryReader(i, FileSys::READER_SHARED); strncpy(map->MapLumps[index].Name, lumpname, 8); } } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 25b244ffd3..6c72d3a524 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -62,6 +62,7 @@ #include "fragglescript/t_script.h" #include "s_music.h" #include "model.h" +#include "d_net.h" EXTERN_CVAR(Bool, save_formatted) @@ -140,6 +141,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si ("texture", part.texture, def->texture) ("interpolation", part.interpolation) ("flags", part.flags, def->flags) + ("skew", part.skew, def->skew) ("color1", part.SpecialColors[0], def->SpecialColors[0]) ("color2", part.SpecialColors[1], def->SpecialColors[1]) ("addcolor", part.AdditiveColor, def->AdditiveColor) @@ -302,11 +304,12 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sector_t &p, sector_t //("bottommap", p.bottommap) //("midmap", p.midmap) //("topmap", p.topmap) + //("selfmap", p.selfmap) // todo: if this becomes changeable we need a colormap serializer. ("damageamount", p.damageamount, def->damageamount) ("damageinterval", p.damageinterval, def->damageinterval) ("leakydamage", p.leakydamage, def->leakydamage) ("damagetype", p.damagetype, def->damagetype) - ("sky", p.sky, def->sky) + ("sky", p.skytransfer, def->skytransfer) ("moreflags", p.MoreFlags, def->MoreFlags) ("flags", p.Flags, def->Flags) .Array("portals", p.Portals, def->Portals, 2, true) @@ -651,6 +654,15 @@ void FLevelLocals::SerializePlayers(FSerializer &arc, bool skipload) ReadMultiplePlayers(arc, numPlayers, numPlayersNow, skipload); } arc.EndArray(); + + if (!skipload) + { + for (unsigned int i = 0u; i < MAXPLAYERS; ++i) + { + if (PlayerInGame(i) && Players[i]->mo != nullptr) + NetworkEntityManager::SetClientNetworkEntity(Players[i]); + } + } } if (!skipload && numPlayersNow > numPlayers) { @@ -870,11 +882,11 @@ void FLevelLocals::CopyPlayer(player_t *dst, player_t *src, const char *name) { dst->userinfo.TransferFrom(uibackup); // The player class must come from the save, so that the menu reflects the currently playing one. - dst->userinfo.PlayerClassChanged(src->mo->GetInfo()->DisplayName); + dst->userinfo.PlayerClassChanged(src->mo->GetInfo()->DisplayName.GetChars()); } // Validate the skin - dst->userinfo.SkinNumChanged(R_FindSkin(Skins[dst->userinfo.GetSkin()].Name, dst->CurrentPlayerClass)); + dst->userinfo.SkinNumChanged(R_FindSkin(Skins[dst->userinfo.GetSkin()].Name.GetChars(), dst->CurrentPlayerClass)); // Make sure the player pawn points to the proper player struct. if (dst->mo != nullptr) @@ -956,6 +968,9 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) } arc("saveversion", SaveVersion); + // this sets up some static data needed further down which means it must be done first. + StaticSerializeTranslations(arc); + if (arc.isReading()) { Thinkers.DestroyAllThinkers(); @@ -969,6 +984,8 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) arc("flags", flags) ("flags2", flags2) + ("flags3", flags3) + ("vkdflags", vkdflags) ("fadeto", fadeto) ("found_secrets", found_secrets) ("found_items", found_items) @@ -997,8 +1014,7 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) ("scrolls", Scrolls) ("automap", automap) ("interpolator", interpolator) - ("frozenstate", frozenstate) - ("savedModelFiles", savedModelFiles); + ("frozenstate", frozenstate); // Hub transitions must keep the current total time @@ -1036,7 +1052,6 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) arc("polyobjs", Polyobjects); SerializeSubsectors(arc, "subsectors"); StatusBar->SerializeMessages(arc); - StaticSerializeTranslations(arc); canvasTextureInfo.Serialize(arc); SerializePlayers(arc, hubload); SerializeSounds(arc); @@ -1068,6 +1083,8 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) automap->UpdateShowAllLines(); } + // clean up the static data we allocated + StaticClearSerializeTranslationsData(); } @@ -1132,7 +1149,7 @@ void FLevelLocals::UnSnapshotLevel(bool hubLoad) // If this isn't the unmorphed original copy of a player, destroy it, because it's extra. for (i = 0; i < MAXPLAYERS; ++i) { - if (PlayerInGame(i) && Players[i]->morphTics && Players[i]->mo->alternative == pawn) + if (PlayerInGame(i) && Players[i]->mo->alternative == pawn) { break; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 17ff41ae8d..53cbfce622 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -186,6 +186,10 @@ static void PrecacheLevel(FLevelLocals *Level) { AddToList(hitlist.Data(), Level->sectors[i].GetTexture(sector_t::floor), FTextureManager::HIT_Flat); AddToList(hitlist.Data(), Level->sectors[i].GetTexture(sector_t::ceiling), FTextureManager::HIT_Flat); + AddToList(hitlist.Data(), Level->sectors[i].planes[0].skytexture[0], FTextureManager::HIT_Wall); + AddToList(hitlist.Data(), Level->sectors[i].planes[0].skytexture[1], FTextureManager::HIT_Wall); + AddToList(hitlist.Data(), Level->sectors[i].planes[1].skytexture[0], FTextureManager::HIT_Wall); + AddToList(hitlist.Data(), Level->sectors[i].planes[1].skytexture[1], FTextureManager::HIT_Wall); } for (i = Level->sides.Size() - 1; i >= 0; i--) @@ -213,12 +217,12 @@ static void PrecacheLevel(FLevelLocals *Level) for (auto n : gameinfo.PrecachedTextures) { - FTextureID tex = TexMan.CheckForTexture(n, ETextureType::Wall, checkForTextureFlags); + FTextureID tex = TexMan.CheckForTexture(n.GetChars(), ETextureType::Wall, checkForTextureFlags); if (tex.Exists()) AddToList(hitlist.Data(), tex, FTextureManager::HIT_Wall); } for (unsigned i = 0; i < Level->info->PrecacheTextures.Size(); i++) { - FTextureID tex = TexMan.CheckForTexture(Level->info->PrecacheTextures[i], ETextureType::Wall, checkForTextureFlags); + FTextureID tex = TexMan.CheckForTexture(Level->info->PrecacheTextures[i].GetChars(), ETextureType::Wall, checkForTextureFlags); if (tex.Exists()) AddToList(hitlist.Data(), tex, FTextureManager::HIT_Wall); } @@ -285,7 +289,7 @@ void FLevelLocals::ClearLevelData(bool fullgc) auto it = GetThinkerIterator(NAME_None, STAT_TRAVELLING); for (AActor *actor = it.Next(); actor != nullptr; actor = it.Next()) { - actor->BlockingLine = nullptr; + actor->BlockingLine = actor->MovementBlockingLine = nullptr; actor->BlockingFloor = actor->BlockingCeiling = actor->Blocking3DFloor = nullptr; } } @@ -375,7 +379,7 @@ void FLevelLocals::ClearLevelData(bool fullgc) if (levelMesh) delete levelMesh; aabbTree = nullptr; levelMesh = nullptr; - if (screen) + if (screen && screen->mShadowMap) screen->mShadowMap->SetAABBTree(nullptr); } @@ -451,7 +455,7 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) // Free all level data from the previous map P_FreeLevelData(); - MapData *map = P_OpenMapData(Level->MapName, true); + MapData *map = P_OpenMapData(Level->MapName.GetChars(), true); if (map == nullptr) { I_Error("Unable to open map '%s'\n", Level->MapName.GetChars()); @@ -475,6 +479,8 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) loader.LoadLevel(map, Level->MapName.GetChars(), position); delete map; + screen->SetLevelMesh(Level->levelMesh); + // if deathmatch, randomly spawn the active players if (deathmatch) { diff --git a/src/p_setup.h b/src/p_setup.h index 27c646b5b9..e9142b3562 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -28,7 +28,7 @@ #ifndef __P_SETUP__ #define __P_SETUP__ -#include "resourcefile.h" +#include "fs_filesystem.h" #include "doomdata.h" #include "r_defs.h" #include "nodebuild.h" diff --git a/src/p_states.cpp b/src/p_states.cpp index 6c3ff2f338..841bb49252 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -40,10 +40,12 @@ #include "thingdef.h" #include "r_state.h" #include "templates.h" +#include "codegen.h" // stores indices for symbolic state labels for some old-style DECORATE functions. FStateLabelStorage StateLabels; +TMap dehExtStates; // Each state is owned by an actor. Actors can own any number of // states, but a single state cannot be owned by more than one @@ -65,15 +67,20 @@ DEFINE_ACTION_FUNCTION(FState, GetSpriteTexture) PARAM_INT(skin); PARAM_FLOAT(scalex); PARAM_FLOAT(scaley); + PARAM_INT(spritenum); + PARAM_INT(framenum); + + int sprnum = (spritenum == -1) ? self->sprite : spritenum; + int frnum = (framenum == -1) ? self->GetFrame() : framenum; spriteframe_t *sprframe; if (skin == 0) { - sprframe = &SpriteFrames[sprites[self->sprite].spriteframes + self->GetFrame()]; + sprframe = &SpriteFrames[sprites[sprnum].spriteframes + frnum]; } else { - sprframe = &SpriteFrames[sprites[Skins[skin].sprite].spriteframes + self->GetFrame()]; + sprframe = &SpriteFrames[sprites[Skins[skin].sprite].spriteframes + frnum]; scalex = Skins[skin].Scale.X; scaley = Skins[skin].Scale.Y; } @@ -138,6 +145,7 @@ FString FState::StaticGetStateName(const FState *state, PClassActor *info) } if (so == nullptr) { + if (state->DehIndex > 0) return FStringf("DehExtraState.%d", state->DehIndex); return ""; } return FStringf("%s.%d", so->TypeName.GetChars(), int(state - so->GetStates())); @@ -379,7 +387,7 @@ FState *FStateLabelStorage::GetState(int pos, PClassActor *cls, bool exact) //========================================================================== // -// State label conversion function for scripts +// State label conversion functions for scripts // //========================================================================== @@ -387,7 +395,7 @@ DEFINE_ACTION_FUNCTION(AActor, FindState) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(newstate); - PARAM_BOOL(exact) + PARAM_BOOL(exact); ACTION_RETURN_STATE(StateLabels.GetState(newstate, self->GetClass(), exact)); } @@ -399,6 +407,15 @@ DEFINE_ACTION_FUNCTION(AActor, ResolveState) ACTION_RETURN_STATE(newstate); } +// find state by string instead of label +DEFINE_ACTION_FUNCTION(AActor, FindStateByString) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(newstate); + PARAM_BOOL(exact); + ACTION_RETURN_STATE(self->GetClass()->FindStateByString(newstate.GetChars(), exact)); +} + //========================================================================== // // Search one list of state definitions for the given name @@ -489,8 +506,10 @@ int FStateDefinitions::GetStateLabelIndex (FName statename) { return -1; } - assert((size_t)std->State <= StateArray.Size() + 1); - return (int)((ptrdiff_t)std->State - 1); + if ((size_t)std->State <= StateArray.Size() + 1) + return (int)((ptrdiff_t)std->State - 1); + else + return -1; } //========================================================================== @@ -700,7 +719,7 @@ void FStateDefinitions::RetargetStatePointers (intptr_t count, const char *targe } else { - statelist[i].State = (FState *)copystring (target); + statelist[i].State = (FState *)FxAlloc.Strdup(target); statelist[i].DefineFlags = SDF_LABEL; } } @@ -801,7 +820,6 @@ FState *FStateDefinitions::ResolveGotoLabel (PClassActor *mytype, char *name) { Printf (TEXTCOLOR_RED "Attempt to get invalid state %s from actor %s.\n", label, type->TypeName.GetChars()); } - delete[] namestart; // free the allocated string buffer return state; } @@ -865,7 +883,7 @@ bool FStateDefinitions::SetGotoLabel(const char *string) // copy the text - this must be resolved later! if (laststate != NULL) { // Following a state definition: Modify it. - laststate->NextState = (FState*)copystring(string); + laststate->NextState = (FState*)FxAlloc.Strdup(string); laststate->DefineFlags = SDF_LABEL; laststatebeforelabel = NULL; return true; @@ -875,7 +893,7 @@ bool FStateDefinitions::SetGotoLabel(const char *string) RetargetStates (lastlabel+1, string); if (laststatebeforelabel != NULL) { - laststatebeforelabel->NextState = (FState*)copystring(string); + laststatebeforelabel->NextState = (FState*)FxAlloc.Strdup(string); laststatebeforelabel->DefineFlags = SDF_LABEL; laststatebeforelabel = NULL; } @@ -1029,6 +1047,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor) for (i = 0; i < count; i++) { + realstates[i].DehIndex = -1; // resolve labels and jumps switch (realstates[i].DefineFlags) { @@ -1074,16 +1093,20 @@ void DumpStateHelper(FStateLabels *StateList, const FString &prefix) { for (int i = 0; i < StateList->NumLabels; i++) { - if (StateList->Labels[i].State != NULL) + auto state = StateList->Labels[i].State; + if (state != NULL) { - const PClassActor *owner = FState::StaticFindStateOwner(StateList->Labels[i].State); + const PClassActor *owner = FState::StaticFindStateOwner(state); if (owner == NULL) { - Printf(PRINT_LOG, "%s%s: invalid\n", prefix.GetChars(), StateList->Labels[i].Label.GetChars()); + if (state->DehIndex >= 0) + Printf(PRINT_LOG, "%s%s: DehExtra %d\n", prefix.GetChars(), state->DehIndex); + else + Printf(PRINT_LOG, "%s%s: invalid\n", prefix.GetChars(), StateList->Labels[i].Label.GetChars()); } else { - Printf(PRINT_LOG, "%s%s: %s\n", prefix.GetChars(), StateList->Labels[i].Label.GetChars(), FState::StaticGetStateName(StateList->Labels[i].State).GetChars()); + Printf(PRINT_LOG, "%s%s: %s\n", prefix.GetChars(), StateList->Labels[i].Label.GetChars(), FState::StaticGetStateName(state).GetChars()); } } if (StateList->Labels[i].Children != NULL) @@ -1135,7 +1158,7 @@ DEFINE_ACTION_FUNCTION(FState, DistanceTo) { // Safely calculate the distance between two states. auto o1 = FState::StaticFindStateOwner(self); - if (o1->OwnsState(other)) retv = int(other - self); + if (o1 && o1->OwnsState(other)) retv = int(other - self); } ACTION_RETURN_INT(retv); } diff --git a/src/playsim/a_corona.cpp b/src/playsim/a_corona.cpp deleted file mode 100644 index 0e0cb4a980..0000000000 --- a/src/playsim/a_corona.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* -** Light Coronas -** Copyright (c) 2022 Nash Muhandes, Magnus Norddahl -** -** 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. -*/ - - -#include "actor.h" -#include "a_corona.h" -#include "a_dynlight.h" - -IMPLEMENT_CLASS(ACorona, false, false) - -void ACorona::Tick() -{ - Super::Tick(); -} diff --git a/src/playsim/a_corona.h b/src/playsim/a_corona.h deleted file mode 100644 index 2c66f0a204..0000000000 --- a/src/playsim/a_corona.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -** Light Coronas -** Copyright (c) 2022 Nash Muhandes, Magnus Norddahl -** -** 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. -*/ - -#pragma once - -#include "actor.h" - -EXTERN_CVAR(Bool, gl_coronas) - -class AActor; - -class ACorona : public AActor -{ - DECLARE_CLASS(ACorona, AActor) - -public: - void Tick(); - - float CoronaFade = 0.0f; -}; diff --git a/src/playsim/a_decals.cpp b/src/playsim/a_decals.cpp index fdb63a0a64..1d9aa9b266 100644 --- a/src/playsim/a_decals.cpp +++ b/src/playsim/a_decals.cpp @@ -243,17 +243,6 @@ void DBaseDecal::SetShade (int r, int g, int b) AlphaColor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b); } -//---------------------------------------------------------------------------- -// -// -// -//---------------------------------------------------------------------------- - -void DBaseDecal::SetTranslation(uint32_t trans) -{ - Translation = trans; -} - //---------------------------------------------------------------------------- // // Returns the texture the decal stuck to. @@ -708,7 +697,7 @@ void DImpactDecal::Expired() // //---------------------------------------------------------------------------- -DBaseDecal* DImpactDecal::StaticCreate (FLevelLocals *Level, const char *name, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color, uint32_t bloodTranslation) +DBaseDecal* DImpactDecal::StaticCreate (FLevelLocals *Level, const char *name, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color, FTranslationID bloodTranslation) { if (cl_maxdecals > 0) { @@ -728,7 +717,7 @@ DBaseDecal* DImpactDecal::StaticCreate (FLevelLocals *Level, const char *name, c // //---------------------------------------------------------------------------- -DBaseDecal* DImpactDecal::StaticCreate (FLevelLocals *Level, const FDecalTemplate *tpl, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color, uint32_t bloodTranslation, bool permanent) +DBaseDecal* DImpactDecal::StaticCreate (FLevelLocals *Level, const FDecalTemplate *tpl, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color, FTranslationID bloodTranslation, bool permanent) { DBaseDecal *decal = NULL; if (tpl != NULL && ((cl_maxdecals > 0 && !(wall->Flags & WALLF_NOAUTODECALS)) || permanent)) @@ -743,9 +732,7 @@ DBaseDecal* DImpactDecal::StaticCreate (FLevelLocals *Level, const FDecalTemplat if (tpl->ShadeColor != tpl_low->ShadeColor) lowercolor=0; else lowercolor = color; - uint32_t lowerTrans = (bloodTranslation != 0 ? bloodTranslation : 0); - - StaticCreate (Level, tpl_low, pos, wall, ffloor, lowercolor, lowerTrans, permanent); + StaticCreate (Level, tpl_low, pos, wall, ffloor, lowercolor, bloodTranslation, permanent); } if (!permanent) decal = Level->CreateThinker(pos.Z); else decal = Level->CreateThinker(pos.Z); @@ -768,7 +755,7 @@ DBaseDecal* DImpactDecal::StaticCreate (FLevelLocals *Level, const FDecalTemplat } // [Nash] opaque blood - if (bloodTranslation != 0 && tpl->ShadeColor == 0 && tpl->opaqueBlood) + if (bloodTranslation != NO_TRANSLATION && tpl->ShadeColor == 0 && tpl->opaqueBlood) { decal->SetTranslation(bloodTranslation); decal->RenderStyle = STYLE_Normal; @@ -860,7 +847,7 @@ void SprayDecal(AActor *shooter, const char *name, double distance, DVector3 off else dir = direction; - uint32_t bloodTrans = useBloodColor ? shooter->BloodTranslation : 0; + auto bloodTrans = useBloodColor ? shooter->BloodTranslation : NO_TRANSLATION; PalEntry entry = !useBloodColor ? (PalEntry)decalColor : shooter->BloodColor; if (Trace(off, shooter->Sector, dir, distance, 0, ML_BLOCKEVERYTHING, shooter, trace, TRACE_NoSky)) @@ -891,7 +878,7 @@ DBaseDecal *ShootDecal(FLevelLocals *Level, const FDecalTemplate *tpl, sector_t if (trace.HitType == TRACE_HitWall) { - return DImpactDecal::StaticCreate(Level, tpl, trace.HitPos, trace.Line->sidedef[trace.Side], trace.ffloor, 0, 0, permanent); + return DImpactDecal::StaticCreate(Level, tpl, trace.HitPos, trace.Line->sidedef[trace.Side], trace.ffloor, 0, NO_TRANSLATION, permanent); } return NULL; } diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index dddb9f54eb..42ccb8fef5 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -115,6 +115,7 @@ void AttachLight(AActor *self) light->pPitch = &self->Angles.Pitch; light->pLightFlags = (LightFlags*)&self->IntVar(NAME_lightflags); light->pArgs = self->args; + light->pSourceRadius = &self->SourceRadius; light->specialf1 = DAngle::fromDeg(double(self->SpawnAngle)).Normalized360().Degrees(); light->Sector = self->Sector; light->target = self; diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index 938292a951..a73074b4f9 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -130,6 +130,7 @@ class FLightDefaults DAngle m_spotInnerAngle = DAngle::fromDeg(10.0); DAngle m_spotOuterAngle = DAngle::fromDeg(25.0); DAngle m_pitch = nullAngle; + double SourceRadius = 5.0; friend FSerializer &Serialize(FSerializer &arc, const char *key, FLightDefaults &value, FLightDefaults *def); }; @@ -222,6 +223,7 @@ struct FDynamicLight bool IsActive() const { return m_active; } float GetRadius() const { return (IsActive() ? m_currentRadius * 2.f : 0.f); } + float GetSourceRadius() const { return (float)(*pSourceRadius); } int GetRed() const { return pArgs[LIGHT_RED]; } int GetGreen() const { return pArgs[LIGHT_GREEN]; } int GetBlue() const { return pArgs[LIGHT_BLUE]; } @@ -268,6 +270,7 @@ struct FDynamicLight const DAngle *pPitch; // This is to handle pitch overrides through GLDEFS, it can either point to the target's pitch or the light definition. const int *pArgs; const LightFlags *pLightFlags; + const double* pSourceRadius; // Softshadows. Physical size of the light source double specialf1; FDynamicLight *next, *prev; @@ -289,6 +292,13 @@ struct FDynamicLight bool swapped; bool explicitpitch; + // Locations in the level mesh light list. Ends with index = 0 or all entries used + enum { max_levelmesh_entries = 4 }; + struct + { + int index; + int portalgroup; + } levelmesh[max_levelmesh_entries]; }; diff --git a/src/playsim/a_morph.cpp b/src/playsim/a_morph.cpp index 80e6807af5..5f6c38b91a 100644 --- a/src/playsim/a_morph.cpp +++ b/src/playsim/a_morph.cpp @@ -37,7 +37,7 @@ bool P_MorphActor(AActor *activator, AActor *victim, PClassActor *ptype, PClassA bool P_UnmorphActor(AActor *activator, AActor *morphed, int flags, bool force) { - IFVIRTUALPTR(morphed, AActor, UnMorph) + IFVIRTUALPTR(morphed, AActor, Unmorph) { VMValue params[] = { morphed, activator, flags, force }; int retval; diff --git a/src/playsim/a_morph.h b/src/playsim/a_morph.h index 00303533cb..762cd01bb5 100644 --- a/src/playsim/a_morph.h +++ b/src/playsim/a_morph.h @@ -26,6 +26,8 @@ enum MORPH_UNDOBYTIMEOUT = 0x00001000, // Player unmorphs once countdown expires MORPH_UNDOALWAYS = 0x00002000, // Powerups must always unmorph, no matter what. MORPH_TRANSFERTRANSLATION = 0x00004000, // Transfer translation from the original actor to the morphed one + MORPH_KEEPARMOR = 0x00008000, // Don't lose current armor value when morphing. + MORPH_IGNOREINVULN = 0x00010000, // Completely ignore invulnerability status on players. MORPH_STANDARDUNDOING = MORPH_UNDOBYTOMEOFPOWER | MORPH_UNDOBYCHAOSDEVICE | MORPH_UNDOBYTIMEOUT, }; diff --git a/src/playsim/a_pickups.cpp b/src/playsim/a_pickups.cpp index f4c72b5f97..d5a9a524ff 100644 --- a/src/playsim/a_pickups.cpp +++ b/src/playsim/a_pickups.cpp @@ -63,7 +63,7 @@ void PrintPickupMessage(bool localview, const FString &str) StaticLastMessage = str; const char *pstr = str.GetChars(); - if (pstr[0] == '$') pstr = GStrings(pstr + 1); + if (pstr[0] == '$') pstr = GStrings.GetString(pstr + 1); if (pstr[0] != 0) Printf(PRINT_LOW, "%s\n", pstr); StatusBar->FlashCrosshair(); } diff --git a/src/playsim/a_sharedglobal.h b/src/playsim/a_sharedglobal.h index 3c86aa1094..4e4a9403e6 100644 --- a/src/playsim/a_sharedglobal.h +++ b/src/playsim/a_sharedglobal.h @@ -31,7 +31,11 @@ class DBaseDecal : public DThinker double GetRealZ (const side_t *wall) const; void SetShade (uint32_t rgb); void SetShade (int r, int g, int b); - void SetTranslation(uint32_t trans); + void SetTranslation(FTranslationID trans) + { + Translation = trans; + } + void Spread (const FDecalTemplate *tpl, side_t *wall, double x, double y, double z, F3DFloor * ffloor); void GetXY (side_t *side, double &x, double &y) const; @@ -42,7 +46,7 @@ class DBaseDecal : public DThinker double ScaleX = 1, ScaleY = 1; double Alpha = 1; uint32_t AlphaColor = 0; - int Translation = 0; + FTranslationID Translation = NO_TRANSLATION; FTextureID PicNum; uint32_t RenderFlags = 0; FRenderStyle RenderStyle; @@ -69,8 +73,8 @@ class DImpactDecal : public DBaseDecal } void Construct(side_t *wall, const FDecalTemplate *templ); - static DBaseDecal *StaticCreate(FLevelLocals *Level, const char *name, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color = 0, uint32_t bloodTranslation = 0); - static DBaseDecal *StaticCreate(FLevelLocals *Level, const FDecalTemplate *tpl, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color = 0, uint32_t bloodTranslation = 0, bool permanent = false); + static DBaseDecal *StaticCreate(FLevelLocals *Level, const char *name, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color = 0, FTranslationID bloodTranslation = NO_TRANSLATION); + static DBaseDecal *StaticCreate(FLevelLocals *Level, const FDecalTemplate *tpl, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color = 0, FTranslationID bloodTranslation = NO_TRANSLATION, bool permanent = false); void BeginPlay (); void Expired() override; @@ -116,15 +120,16 @@ enum QF_GROUNDONLY = 1 << 7, QF_AFFECTACTORS = 1 << 8, QF_SHAKEONLY = 1 << 9, + QF_DAMAGEFALLOFF = 1 << 10, }; struct FQuakeJiggers { - DVector3 Intensity; - DVector3 RelIntensity; - DVector3 Offset; - DVector3 RelOffset; - double RollIntensity, RollWave; + DVector3 Intensity = {}; + DVector3 RelIntensity = {}; + DVector3 Offset = {}; + DVector3 RelOffset = {}; + double RollIntensity = 0.0, RollWave = 0.0; }; class DEarthquake : public DThinker @@ -134,8 +139,8 @@ class DEarthquake : public DThinker public: static const int DEFAULT_STAT = STAT_EARTHQUAKE; void Construct(AActor *center, double intensityX, double intensityY, double intensityZ, int duration, - int damrad, int tremrad, FSoundID quakesfx, int flags, - double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave); + double damrad, double tremrad, FSoundID quakesfx, int flags, + double waveSpeedX, double waveSpeedY, double waveSpeedZ, double falloff, int highpoint, double rollIntensity, double rollWave, double damageMultiplier, double thrustMultiplier, int damage); void Serialize(FSerializer &arc); void Tick (); @@ -150,11 +155,13 @@ class DEarthquake : public DThinker double m_Falloff; int m_Highpoint, m_MiniCount; double m_RollIntensity, m_RollWave; + double m_DamageMultiplier, m_ThrustMultiplier; + int m_Damage; double GetModIntensity(double intensity, bool fake = false) const; double GetModWave(double ticFrac, double waveMultiplier) const; - double GetFalloff(double dist) const; - void DoQuakeDamage(DEarthquake *quake, AActor *victim) const; + double GetFalloff(double dist, double radius) const; + void DoQuakeDamage(DEarthquake *quake, AActor *victim, bool falloff) const; static int StaticGetQuakeIntensities(double ticFrac, AActor *viewer, FQuakeJiggers &jiggers); }; diff --git a/src/playsim/actionspecials.h b/src/playsim/actionspecials.h index 2e5e95b724..7cfa43ce56 100644 --- a/src/playsim/actionspecials.h +++ b/src/playsim/actionspecials.h @@ -272,6 +272,7 @@ DEFINE_SPECIAL(Ceiling_MoveToValueAndCrush, 280, 4, 5, 5) DEFINE_SPECIAL(Line_SetAutomapFlags, 281, 3, 3, 3) DEFINE_SPECIAL(Line_SetAutomapStyle, 282, 2, 2, 2) DEFINE_SPECIAL(Polyobj_StopSound, 283, 1, 1, 1) +DEFINE_SPECIAL(Generic_CrusherDist, 284, 5, 5, 5) DEFINE_SPECIAL(Line_QuickPortal, 301, -1, -1, 1) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index fa78ca84a5..4cb0cd60b2 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -206,8 +206,7 @@ enum ActorFlag2 // but still considered solid MF2_INVULNERABLE = 0x08000000, // mobj is invulnerable MF2_DORMANT = 0x10000000, // thing is dormant - MF2_ARGSDEFINED = 0x20000000, // Internal flag used by DECORATE to signal that the - // args should not be taken from the mapthing definition + MF2_ARGSDEFINED = 0x20000000, // Internal flag used by DECORATE to signal that the args should not be taken from the mapthing definition MF2_SEEKERMISSILE = 0x40000000, // is a seeker (for reflection) MF2_REFLECTIVE = 0x80000000, // reflects missiles }; @@ -394,11 +393,13 @@ enum ActorFlag7 MF7_SPRITEANGLE = 0x02000000, // [MC] Utilize the SpriteAngle property and lock the rotation to the degrees specified. MF7_SMASHABLE = 0x04000000, // dies if hitting the floor. MF7_NOSHIELDREFLECT = 0x08000000, // will not be reflected by shields. - MF7_FORCEZERORADIUSDMG = 0x10000000, // passes zero radius damage on to P_DamageMobj, this is necessary in some cases where DoSpecialDamage gets overrideen. + MF7_FORCEZERORADIUSDMG = 0x10000000,// passes zero radius damage on to P_DamageMobj, this is necessary in some cases where DoSpecialDamage gets overrideen. MF7_NOINFIGHTSPECIES = 0x20000000, // don't start infights with one's own species. MF7_FORCEINFIGHTING = 0x40000000, // overrides a map setting of 'no infighting'. MF7_INCHASE = 0x80000000, // [RH] used by A_Chase and A_Look to avoid recursion }; + +// --- mobj.flags8 --- enum ActorFlag8 { MF8_FRIGHTENING = 0x00000001, // for those moments when halloween just won't do @@ -428,12 +429,22 @@ enum ActorFlag8 MF8_STAYONLIFT = 0x02000000, // MBF AI enhancement. MF8_DONTFOLLOWPLAYERS = 0x04000000, // [inkoalawetrust] Friendly monster will not follow players. MF8_SEEFRIENDLYMONSTERS = 0X08000000, // [inkoalawetrust] Hostile monster can see friendly monsters. - MF8_CROSSLINECHECK = 0x10000000, // [MC]Enables CanCrossLine virtual + MF8_CROSSLINECHECK = 0x10000000, // [MC] Enables CanCrossLine virtual MF8_MASTERNOSEE = 0x20000000, // Don't show object in first person if their master is the current camera. MF8_ADDLIGHTLEVEL = 0x40000000, // [MC] Actor light level is additive with sector. MF8_ONLYSLAMSOLID = 0x80000000, // [B] Things with skullfly will ignore non-solid Actors. }; +// --- mobj.flags9 --- +enum ActorFlag9 +{ + MF9_SHADOWAIM = 0x00000001, // [inkoalawetrust] Monster still gets aim penalty from aiming at shadow actors even with MF6_SEEINVISIBLE on. + MF9_DOSHADOWBLOCK = 0x00000002, // [inkoalawetrust] Should the monster look for SHADOWBLOCK actors ? + MF9_SHADOWBLOCK = 0x00000004, // [inkoalawetrust] Actors in the line of fire with this flag trigger the MF_SHADOW aiming penalty. + MF9_SHADOWAIMVERT = 0x00000008, // [inkoalawetrust] Monster aim is also offset vertically when aiming at shadow actors. + MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states +}; + // --- mobj.renderflags --- enum ActorRenderFlag { @@ -470,7 +481,7 @@ enum ActorRenderFlag RF_MASKROTATION = 0x00200000, // [MC] Only draw the actor when viewed from a certain angle range. RF_ABSMASKANGLE = 0x00400000, // [MC] The mask rotation does not offset by the actor's angle. RF_ABSMASKPITCH = 0x00800000, // [MC] The mask rotation does not offset by the actor's pitch. - RF_INTERPOLATEANGLES = 0x01000000, // [MC] Allow interpolation of the actor's angle, pitch and roll. + RF_INTERPOLATEANGLES = 0x01000000, // [MC] Allow interpolation of the actor's angle, pitch and roll. RF_MAYBEINVISIBLE = 0x02000000, RF_DONTINTERPOLATE = 0x04000000, // no render interpolation ever! @@ -478,13 +489,18 @@ enum ActorRenderFlag RF_ZDOOMTRANS = 0x10000000, // is not normally transparent in Vanilla Doom RF_CASTSPRITESHADOW = 0x20000000, // actor will cast a sprite shadow RF_NOINTERPOLATEVIEW = 0x40000000, // don't interpolate the view next frame if this actor is a camera. - RF_NOSPRITESHADOW = 0x80000000, // actor will not cast a sprite shadow + RF_NOSPRITESHADOW = 0x80000000, // actor will not cast a sprite shadow }; enum ActorRenderFlag2 { RF2_INVISIBLEINMIRRORS = 0x0001, // [Nash] won't render in mirrors RF2_ONLYVISIBLEINMIRRORS = 0x0002, // [Nash] only renders in mirrors + RF2_BILLBOARDFACECAMERA = 0x0004, // Sprite billboard face camera (override gl_billboard_faces_camera) + RF2_BILLBOARDNOFACECAMERA = 0x0008, // Sprite billboard face camera angle (override gl_billboard_faces_camera) + RF2_FLIPSPRITEOFFSETX = 0x0010, + RF2_FLIPSPRITEOFFSETY = 0x0020, + RF2_CAMFOLLOWSPLAYER = 0x0040, // Matches the cam's base position and angles to the main viewpoint. }; // This translucency value produces the closest match to Heretic's TINTTAB. @@ -588,6 +604,7 @@ typedef TFlags ActorFlags5; typedef TFlags ActorFlags6; typedef TFlags ActorFlags7; typedef TFlags ActorFlags8; +typedef TFlags ActorFlags9; typedef TFlags ActorRenderFlags; typedef TFlags ActorRenderFlags2; typedef TFlags ActorBounceFlags; @@ -600,6 +617,7 @@ DEFINE_TFLAGS_OPERATORS (ActorFlags5) DEFINE_TFLAGS_OPERATORS (ActorFlags6) DEFINE_TFLAGS_OPERATORS (ActorFlags7) DEFINE_TFLAGS_OPERATORS (ActorFlags8) +DEFINE_TFLAGS_OPERATORS (ActorFlags9) DEFINE_TFLAGS_OPERATORS (ActorRenderFlags) DEFINE_TFLAGS_OPERATORS (ActorRenderFlags2) DEFINE_TFLAGS_OPERATORS (ActorBounceFlags) @@ -677,20 +695,65 @@ enum EViewPosFlags // [MC] Flags for SetViewPos. VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position. }; +enum EAnimOverrideFlags +{ + ANIMOVERRIDE_NONE = 1 << 0, // no animation + ANIMOVERRIDE_LOOP = 1 << 1, // animation loops, otherwise it stays on the last frame once it ends +}; + +struct AnimOverride +{ + int firstFrame; + int lastFrame; + int loopFrame; + double startFrame; + int flags = ANIMOVERRIDE_NONE; + float framerate; + double startTic; // when the current animation started (changing framerates counts as restarting) (or when animation starts if interpolating from previous animation) + double switchTic; // when the animation was changed -- where to interpolate the switch from +}; + +struct ModelOverride +{ + int modelID; + TArray surfaceSkinIDs; +}; + +struct AnimModelOverride +{ + int id; + + AnimModelOverride() = default; + + AnimModelOverride(int i) : id(i) {} + operator int() { return id; } +}; + +enum EModelDataFlags +{ + MODELDATA_HADMODEL = 1 << 0, + MODELDATA_OVERRIDE_FLAGS = 1 << 1, +}; + class DActorModelData : public DObject { DECLARE_CLASS(DActorModelData, DObject); public: - FName modelDef; - bool hasModel; - TArray modelIDs; - TArray skinIDs; - TArray surfaceSkinIDs; - TArray animationIDs; - TArray modelFrameGenerators; + PClass * modelDef; + TArray models; + TArray skinIDs; + TArray animationIDs; + TArray modelFrameGenerators; + int flags; + int overrideFlagsSet; + int overrideFlagsClear; + + AnimOverride curAnim; + AnimOverride prevAnim; // used for interpolation when switching anims DActorModelData() = default; virtual void Serialize(FSerializer& arc) override; + virtual void OnDestroy() override; }; class DViewPosition : public DObject @@ -717,7 +780,7 @@ class DViewPosition : public DObject Flags = f; } - bool isZero() + bool isZero() const { return Offset.isZero(); } @@ -726,7 +789,7 @@ class DViewPosition : public DObject const double MinVel = EQUAL_EPSILON; // Map Object definition. -class AActor : public DThinker +class AActor final : public DThinker { DECLARE_CLASS_WITH_META (AActor, DThinker, PClassActor) HAS_OBJECT_POINTERS @@ -741,6 +804,7 @@ class AActor : public DThinker virtual void PostSerialize() override; virtual void PostBeginPlay() override; // Called immediately before the actor's first tick virtual void Tick() override; + void EnableNetworking(const bool enable) override; static AActor *StaticSpawn (FLevelLocals *Level, PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false); @@ -832,6 +896,11 @@ class AActor : public DThinker // (virtual on the script side only) int SpecialMissileHit (AActor *victim); + // Called when bouncing to allow for custom behavior. + // Returns -1 for normal behavior, 0 to stop, and 1 to keep going. + // (virtual on the script side only) + int SpecialBounceHit(AActor* bounceMobj, line_t* bounceLine, secplane_t* bouncePlane); + // Returns true if it's okay to switch target to "other" after being attacked by it. bool CallOkayToSwitchTarget(AActor *other); bool OkayToSwitchTarget (AActor *other); @@ -844,6 +913,9 @@ class AActor : public DThinker // Returns true if this view is considered "local" for the player. bool CheckLocalView() const; + // Allows for enabling/disabling client-side rendering in a way the playsim can't access. + void DisableLocalRendering(const unsigned int pNum, const bool disable); + bool ShouldRenderLocally() const; // Finds the first item of a particular type. AActor *FindInventory (PClassActor *type, bool subclass=false); @@ -937,14 +1009,14 @@ class AActor : public DThinker double Distance2DSquared(AActor *other, bool absolute = false) { - DVector2 otherpos = absolute ? other->Pos() : other->PosRelative(this); - return (Pos().XY() - otherpos).LengthSquared(); + DVector3 otherpos = absolute ? other->Pos() : other->PosRelative(this); + return (Pos().XY() - otherpos.XY()).LengthSquared(); } double Distance2D(AActor *other, bool absolute = false) const { - DVector2 otherpos = absolute ? other->Pos() : other->PosRelative(this); - return (Pos().XY() - otherpos).Length(); + DVector3 otherpos = absolute ? other->Pos() : other->PosRelative(this); + return (Pos().XY() - otherpos.XY()).Length(); } double Distance2D(double x, double y) const @@ -974,19 +1046,19 @@ class AActor : public DThinker DAngle AngleTo(AActor *other, bool absolute = false) { - DVector2 otherpos = absolute ? other->Pos() : other->PosRelative(this); - return VecToAngle(otherpos - Pos().XY()); + DVector3 otherpos = absolute ? other->Pos() : other->PosRelative(this); + return VecToAngle(otherpos.XY() - Pos().XY()); } DAngle AngleTo(AActor *other, double oxofs, double oyofs, bool absolute = false) const { - DVector2 otherpos = absolute ? other->Pos() : other->PosRelative(this); - return VecToAngle(otherpos - Pos() + DVector2(oxofs, oyofs)); + DVector3 otherpos = absolute ? other->Pos() : other->PosRelative(this); + return VecToAngle(otherpos.XY() - Pos().XY() + DVector2(oxofs, oyofs)); } DVector2 Vec2To(AActor *other) const { - return other->PosRelative(this) - Pos(); + return other->PosRelative(this).XY() - Pos().XY(); } DVector3 Vec3To(AActor *other) const @@ -1046,6 +1118,7 @@ class AActor : public DThinker DAngle SpriteAngle; DAngle SpriteRotation; + DVector2 AutomapOffsets; // Offset the actors' sprite view on the automap by these coordinates. DRotator Angles; DRotator ViewAngles; // Angle offsets for cameras TObjPtr ViewPos; // Position offsets for cameras @@ -1059,11 +1132,12 @@ class AActor : public DThinker FRenderStyle RenderStyle; // Style to draw this actor with FTextureID picnum; // Draw this instead of sprite if valid uint32_t fillcolor; // Color to draw when STYLE_Shaded - uint32_t Translation; + FTranslationID Translation; uint32_t RenderRequired; // current renderer must have this feature set uint32_t RenderHidden; // current renderer must *not* have any of these features + bool NoLocalRender; // DO NOT EXPORT THIS! This is a way to disable rendering such that the playsim cannot access it. ActorRenderFlags renderflags; // Different rendering flags ActorRenderFlags2 renderflags2; // More rendering flags... ActorFlags flags; @@ -1074,6 +1148,7 @@ class AActor : public DThinker ActorFlags6 flags6; // Shit! Where did all the flags go? ActorFlags7 flags7; // WHO WANTS TO BET ON 8!? ActorFlags8 flags8; // I see your 8, and raise you a bet for 9. + ActorFlags9 flags9; // Happy ninth actor flag field GZDoom ! double Floorclip; // value to use for floor clipping double radius, Height; // for movement checking @@ -1190,6 +1265,8 @@ class AActor : public DThinker double Gravity; // [GRB] Gravity factor double Friction; double pushfactor; + double ShadowAimFactor; // [inkoalawetrust] How much the actors' aim is affected when attacking shadow actors. + double ShadowPenaltyFactor;// [inkoalawetrust] How much the shadow actor affects its' shooters' aim. int bouncecount; // Strife's grenades only bounce twice before exploding int FastChaseStrafeCount; int lastpush; @@ -1202,6 +1279,7 @@ class AActor : public DThinker AActor *BlockingMobj; // Actor that blocked the last move line_t *BlockingLine; // Line that blocked the last move + line_t *MovementBlockingLine; // Line that stopped the Actor's movement in P_XYMovement sector_t *Blocking3DFloor; // 3D floor that blocked the last move (if any) sector_t *BlockingCeiling; // Sector that blocked the last move (ceiling plane slope) sector_t *BlockingFloor; // Sector that blocked the last move (floor plane slope) @@ -1235,7 +1313,7 @@ class AActor : public DThinker uint8_t FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc) double FloatBobStrength; PalEntry BloodColor; - uint32_t BloodTranslation; + FTranslationID BloodTranslation; // [RH] Stuff that used to be part of an Actor Info FSoundID SeeSound; @@ -1292,6 +1370,11 @@ class AActor : public DThinker int SpawnTime; uint32_t SpawnOrder; + // landing speed from a jump with normal gravity (squats the player's view) + // (note: this is put into AActor instead of the PlayerPawn because non-players also use the value) + double LandingSpeed; + + double SourceRadius = 5.0; // Light source radius // ThingIDs void SetTID (int newTID); @@ -1413,6 +1496,11 @@ class AActor : public DThinker result.Roll = PrevAngles.Roll + deltaangle(PrevAngles.Roll, Angles.Roll) * ticFrac; return result; } + float GetSpriteOffset(bool y) const + { + if (y) return (float)(renderflags2 & RF2_FLIPSPRITEOFFSETY ? SpriteOffset.Y : -SpriteOffset.Y); + else return (float)(renderflags2 & RF2_FLIPSPRITEOFFSETX ? SpriteOffset.X : -SpriteOffset.X); + } DAngle GetSpriteAngle(DAngle viewangle, double ticFrac) { if (flags7 & MF7_SPRITEANGLE) @@ -1667,8 +1755,8 @@ struct FTranslatedLineTarget bool unlinked; // found by a trace that went through an unlinked portal. }; - -void StaticPointerSubstitution(AActor* old, AActor* notOld); +void PlayerPointerSubstitution(AActor* oldPlayer, AActor* newPlayer, bool removeOld); +int MorphPointerSubstitution(AActor* from, AActor* to); #define S_FREETARGMOBJ 1 diff --git a/src/playsim/bots/b_bot.cpp b/src/playsim/bots/b_bot.cpp index 415cc271d7..56a12b75eb 100644 --- a/src/playsim/bots/b_bot.cpp +++ b/src/playsim/bots/b_bot.cpp @@ -202,7 +202,7 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam) } players[i].~player_t(); ::new(&players[i]) player_t; - players[i].userinfo.Reset(); + players[i].userinfo.Reset(i); playeringame[i] = false; } @@ -214,7 +214,7 @@ CCMD (removebots) return; } - Net_WriteByte (DEM_KILLBOTS); + Net_WriteInt8 (DEM_KILLBOTS); } CCMD (freeze) @@ -228,8 +228,8 @@ CCMD (freeze) return; } - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_FREEZE); + Net_WriteInt8(DEM_GENERICCHEAT); + Net_WriteInt8(CHT_FREEZE); } CCMD (listbots) diff --git a/src/playsim/bots/b_func.cpp b/src/playsim/bots/b_func.cpp index 07cdd08d0c..e537bf9f7e 100644 --- a/src/playsim/bots/b_func.cpp +++ b/src/playsim/bots/b_func.cpp @@ -541,7 +541,7 @@ DAngle DBot::FireRox (AActor *enemy, ticcmd_t *cmd) //Predict. m = ((dist+1) / GetDefaultByName("Rocket")->Speed); - Level->BotInfo.SetBodyAt(Level, DVector3((enemy->Pos() + enemy->Vel * (m + 2)), ONFLOORZ), 1); + Level->BotInfo.SetBodyAt(Level, DVector3((enemy->Pos().XY() + enemy->Vel * (m + 2)), ONFLOORZ), 1); //try the predicted location if (P_CheckSight (actor, Level->BotInfo.body1, SF_IGNOREVISIBILITY)) //See the predicted location, so give a test missile diff --git a/src/playsim/bots/b_game.cpp b/src/playsim/bots/b_game.cpp index a43c83ce03..198692c1fd 100644 --- a/src/playsim/bots/b_game.cpp +++ b/src/playsim/bots/b_game.cpp @@ -142,7 +142,7 @@ void FCajunMaster::Main(FLevelLocals *Level) { if (t_join == ((wanted_botnum - botnum) * SPAWN_DELAY)) { - if (!SpawnBot (getspawned[spawn_tries])) + if (!SpawnBot (getspawned[spawn_tries].GetChars())) wanted_botnum--; spawn_tries++; } @@ -296,8 +296,8 @@ bool FCajunMaster::SpawnBot (const char *name, int color) thebot->inuse = BOTINUSE_Waiting; - Net_WriteByte (DEM_ADDBOT); - Net_WriteByte (botshift); + Net_WriteInt8 (DEM_ADDBOT); + Net_WriteInt8 (botshift); { //Set color. FString concat = thebot->Info; @@ -309,25 +309,25 @@ bool FCajunMaster::SpawnBot (const char *name, int color) { // Keep the bot on the same team when switching levels concat.AppendFormat("\\team\\%d\n", thebot->lastteam); } - Net_WriteString (concat); + Net_WriteString (concat.GetChars()); } - Net_WriteByte(thebot->skill.aiming); - Net_WriteByte(thebot->skill.perfection); - Net_WriteByte(thebot->skill.reaction); - Net_WriteByte(thebot->skill.isp); + Net_WriteInt8(thebot->skill.aiming); + Net_WriteInt8(thebot->skill.perfection); + Net_WriteInt8(thebot->skill.reaction); + Net_WriteInt8(thebot->skill.isp); return true; } void FCajunMaster::TryAddBot (FLevelLocals *Level, uint8_t **stream, int player) { - int botshift = ReadByte (stream); + int botshift = ReadInt8 (stream); char *info = ReadString (stream); botskill_t skill; - skill.aiming = ReadByte (stream); - skill.perfection = ReadByte (stream); - skill.reaction = ReadByte (stream); - skill.isp = ReadByte (stream); + skill.aiming = ReadInt8 (stream); + skill.perfection = ReadInt8 (stream); + skill.reaction = ReadInt8 (stream); + skill.isp = ReadInt8 (stream); botinfo_t *thebot = NULL; @@ -525,7 +525,7 @@ bool FCajunMaster::LoadBots () DPrintf (DMSG_ERROR, "No " BOTFILENAME ", so no bots\n"); return false; } - if (!sc.OpenFile(tmp)) + if (!sc.OpenFile(tmp.GetChars())) { Printf("Unable to open %s. So no bots\n", tmp.GetChars()); return false; diff --git a/src/playsim/bots/b_think.cpp b/src/playsim/bots/b_think.cpp index 12c7d4113a..9fba192d58 100644 --- a/src/playsim/bots/b_think.cpp +++ b/src/playsim/bots/b_think.cpp @@ -339,7 +339,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd) if (t_fight<(AFTERTICS/2)) player->mo->flags |= MF_DROPOFF; - old = player->mo->Pos(); + old = player->mo->Pos().XY(); } int P_GetRealMaxHealth(AActor *actor, int max); diff --git a/src/playsim/d_player.h b/src/playsim/d_player.h index 4ee4cfeb71..34ac55da6f 100644 --- a/src/playsim/d_player.h +++ b/src/playsim/d_player.h @@ -123,8 +123,9 @@ typedef enum CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame CF_INTERPVIEWANGLES = 1 << 15, // [MR] flag for interpolating view angles without interpolating the entire frame - CF_SCALEDNOLERP = 1 << 15, // [MR] flag for applying angles changes in the ticrate without interpolating the frame CF_NOFOVINTERP = 1 << 16, // [B] Disable FOV interpolation when instantly zooming + CF_SCALEDNOLERP = 1 << 17, // [MR] flag for applying angles changes in the ticrate without interpolating the frame + CF_NOVIEWPOSINTERP = 1 << 18, // Disable view position interpolation. CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths. CF_BUDDHA2 = 1 << 24, // [MC] Absolute buddha. No voodoo can kill it either. CF_GODMODE2 = 1 << 25, // [MC] Absolute godmode. No voodoo can kill it either. @@ -269,7 +270,7 @@ struct userinfo_t : TMap return *static_cast(*CheckKey(NAME_Wi_NoAutostartMap)); } - void Reset(); + void Reset(int pnum); int TeamChanged(int team); int SkinChanged(const char *skinname, int playerclass); int SkinNumChanged(int skinnum); @@ -375,6 +376,7 @@ class player_t int chickenPeck = 0; // chicken peck countdown int jumpTics = 0; // delay the next jump for a moment bool onground = 0; // Identifies if this player is on the ground or other object + bool crossingPortal = 0; // Crossing a portal (disables sprite from showing up) int respawn_time = 0; // [RH] delay respawning until this tic TObjPtr camera = MakeObjPtr(nullptr); // [RH] Whose eyes this player sees through @@ -457,8 +459,7 @@ class player_t bool Resurrect(); // Scaled angle adjustment info. Not for direct manipulation. - DRotator angleTargets; - DRotator angleAppliedAmounts; + DRotator angleOffsetTargets; }; // Bookkeeping on players - state. diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index 86ef7918cc..3214decf38 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -807,7 +807,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(DThinker, ChangeStatNum, ChangeStatNum) { PARAM_SELF_PROLOGUE(DThinker); PARAM_INT(stat); - ChangeStatNum(self, stat); + + // do not allow ZScript to reposition thinkers in or out of particle ticking. + if (stat != STAT_VISUALTHINKER && !dynamic_cast(self)) + { + ChangeStatNum(self, stat); + } return 0; } diff --git a/src/playsim/fragglescript/t_func.cpp b/src/playsim/fragglescript/t_func.cpp index 549c330ae8..f9fff1b9ef 100644 --- a/src/playsim/fragglescript/t_func.cpp +++ b/src/playsim/fragglescript/t_func.cpp @@ -54,6 +54,8 @@ #include "s_music.h" #include "texturemanager.h" +using namespace FileSys; + static FRandom pr_script("FScript"); // functions. FParser::SF_ means Script Function not, well.. heh, me @@ -557,7 +559,7 @@ void FParser::SF_Include(void) { if(t_argv[0].type == svt_string) { - strncpy(tempstr, t_argv[0].string, 8); + strncpy(tempstr, t_argv[0].string.GetChars(), 8); tempstr[8]=0; } else @@ -1867,7 +1869,7 @@ void FParser::SF_FloorTexture(void) if(t_argc > 1) { int i = -1; - FTextureID picnum = TexMan.GetTextureID(t_argv[1].string, ETextureType::Flat, FTextureManager::TEXMAN_Overridable); + FTextureID picnum = TexMan.GetTextureID(t_argv[1].string.GetChars(), ETextureType::Flat, FTextureManager::TEXMAN_Overridable); // set all sectors with tag auto itr = Level->GetSectorTagIterator(tagnum); @@ -1957,7 +1959,7 @@ void FParser::SF_CeilingTexture(void) if(t_argc > 1) { int i = -1; - FTextureID picnum = TexMan.GetTextureID(t_argv[1].string, ETextureType::Flat, FTextureManager::TEXMAN_Overridable); + FTextureID picnum = TexMan.GetTextureID(t_argv[1].string.GetChars(), ETextureType::Flat, FTextureManager::TEXMAN_Overridable); // set all sectors with tag auto itr = Level->GetSectorTagIterator(tagnum); @@ -2227,7 +2229,7 @@ void FParser::SF_SetLineTexture(void) } else // and an improved legacy version { - FTextureID picnum = TexMan.GetTextureID(t_argv[1].string, ETextureType::Wall, FTextureManager::TEXMAN_Overridable); + FTextureID picnum = TexMan.GetTextureID(t_argv[1].string.GetChars(), ETextureType::Wall, FTextureManager::TEXMAN_Overridable); side = !!intvalue(t_argv[2]); int sections = intvalue(t_argv[3]); @@ -2712,7 +2714,7 @@ void FParser::SF_MoveCamera(void) double targetheight = floatvalue(t_argv[2]); double movespeed = floatvalue(t_argv[3]); DVector3 campos = cam->Pos(); - DVector3 targpos = DVector3(target->Pos(), targetheight); + DVector3 targpos = DVector3(target->Pos().XY(), targetheight); DVector3 movement = targpos - campos; double movelen = movement.Length(); diff --git a/src/playsim/fragglescript/t_load.cpp b/src/playsim/fragglescript/t_load.cpp index efd27a070d..32518aa196 100644 --- a/src/playsim/fragglescript/t_load.cpp +++ b/src/playsim/fragglescript/t_load.cpp @@ -137,7 +137,7 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc) sc.MustGetString(); if (!FS_ChangeMusic(sc.String)) { - S_ChangeMusic(Level->Music, Level->musicorder); + S_ChangeMusic(Level->Music.GetChars(), Level->musicorder); } } else if (sc.Compare("skyname")) diff --git a/src/playsim/fragglescript/t_oper.cpp b/src/playsim/fragglescript/t_oper.cpp index 8b4368db77..beac99d0eb 100644 --- a/src/playsim/fragglescript/t_oper.cpp +++ b/src/playsim/fragglescript/t_oper.cpp @@ -167,7 +167,7 @@ void FParser::OPcmp(svalue_t &result, int start, int n, int stop) if(left.type == svt_string && right.type == svt_string) { - result.value.i = !strcmp(left.string, right.string); + result.value.i = !strcmp(left.string.GetChars(), right.string.GetChars()); return; } diff --git a/src/playsim/fragglescript/t_prepro.cpp b/src/playsim/fragglescript/t_prepro.cpp index 409faa1320..f5a8cee454 100644 --- a/src/playsim/fragglescript/t_prepro.cpp +++ b/src/playsim/fragglescript/t_prepro.cpp @@ -284,7 +284,7 @@ char *DFsScript::ProcessFindChar(char *datap, char find) Printf(PRINT_BOLD,"Script %d: ':' encountrered in incorrect position!\n",scriptnum); } - DFsVariable *newlabel = NewVariable(labelname, svt_label); + DFsVariable *newlabel = NewVariable(labelname.GetChars(), svt_label); newlabel->value.i = MakeIndex(labelptr); } @@ -410,7 +410,6 @@ void DFsScript::Preprocess(FLevelLocals *Level) void DFsScript::ParseInclude(FLevelLocals *Level, char *lumpname) { int lumpnum; - char *lump; if((lumpnum = fileSystem.CheckNumForName(lumpname)) == -1) { @@ -419,21 +418,18 @@ void DFsScript::ParseInclude(FLevelLocals *Level, char *lumpname) } int lumplen=fileSystem.FileLength(lumpnum); - lump=new char[lumplen+10]; - fileSystem.ReadFile(lumpnum,lump); + TArray lump(lumplen + 10); + fileSystem.ReadFile(lumpnum,lump.Data()); lump[lumplen]=0; // preprocess the include // we assume that it does not include sections or labels or // other nasty things - ProcessFindChar(lump, 0); + ProcessFindChar(lump.Data(), 0); // now parse the lump FParser parse(Level, this); - parse.Run(lump, lump, lump+lumplen); - - // free the lump - delete[] lump; + parse.Run(lump.Data(), lump.Data(), lump.Data() + lumplen); } diff --git a/src/playsim/fragglescript/t_script.cpp b/src/playsim/fragglescript/t_script.cpp index 2eb3ef2298..7af1424ab8 100644 --- a/src/playsim/fragglescript/t_script.cpp +++ b/src/playsim/fragglescript/t_script.cpp @@ -549,9 +549,9 @@ size_t DFraggleThinker::PropagateMark() // //========================================================================== -size_t DFraggleThinker::PointerSubstitution (DObject *old, DObject *notOld) +size_t DFraggleThinker::PointerSubstitution (DObject *old, DObject *notOld, bool nullOnFail) { - size_t changed = Super::PointerSubstitution(old, notOld); + size_t changed = Super::PointerSubstitution(old, notOld, nullOnFail); for(unsigned i=0;i(old)) diff --git a/src/playsim/fragglescript/t_script.h b/src/playsim/fragglescript/t_script.h index a809870780..2dc79a95e5 100644 --- a/src/playsim/fragglescript/t_script.h +++ b/src/playsim/fragglescript/t_script.h @@ -273,7 +273,7 @@ class CFsError CFsError(const FString &in) { - strncpy(msg, in, 2047); + strncpy(msg, in.GetChars(), 2047); msg[2047]=0; } }; @@ -701,7 +701,7 @@ class DFraggleThinker : public DThinker void Tick(); void InitFunctions(); size_t PropagateMark(); - size_t PointerSubstitution (DObject *old, DObject *notOld); + size_t PointerSubstitution (DObject *old, DObject *notOld, bool nullOnFail); bool wait_finished(DRunningScript *script); void AddRunningScript(DRunningScript *runscr); diff --git a/src/playsim/fragglescript/t_variable.cpp b/src/playsim/fragglescript/t_variable.cpp index 4244908052..f3ab238839 100644 --- a/src/playsim/fragglescript/t_variable.cpp +++ b/src/playsim/fragglescript/t_variable.cpp @@ -54,7 +54,7 @@ int intvalue(const svalue_t &v) { - return (v.type == svt_string ? atoi(v.string) : + return (v.type == svt_string ? atoi(v.string.GetChars()) : v.type == svt_fixed ? (int)(v.value.f / 65536.) : v.type == svt_mobj ? -1 : v.value.i ); } @@ -68,7 +68,7 @@ int intvalue(const svalue_t &v) fsfix fixedvalue(const svalue_t &v) { return (v.type == svt_fixed ? v.value.f : - v.type == svt_string ? (fsfix)(atof(v.string) * 65536.) : + v.type == svt_string ? (fsfix)(atof(v.string.GetChars()) * 65536.) : v.type == svt_mobj ? -65536 : v.value.i * 65536 ); } @@ -81,7 +81,7 @@ fsfix fixedvalue(const svalue_t &v) double floatvalue(const svalue_t &v) { return - v.type == svt_string ? atof(v.string) : + v.type == svt_string ? atof(v.string.GetChars()) : v.type == svt_fixed ? v.value.f / 65536. : v.type == svt_mobj ? -1. : (double)v.value.i; } @@ -99,7 +99,7 @@ const char *stringvalue(const svalue_t & v) switch(v.type) { case svt_string: - return v.string; + return v.string.GetChars(); case svt_mobj: // return the class name @@ -349,7 +349,7 @@ DFsVariable *DFsScript::VariableForName(const char *name) while(current) { - if(!strcmp(name, current->Name)) // found it? + if(!strcmp(name, current->Name.GetChars())) // found it? return current; current = current->next; // check next in chain } diff --git a/src/playsim/mapthinkers/a_floor.cpp b/src/playsim/mapthinkers/a_floor.cpp index 3307384947..0d330e4e90 100644 --- a/src/playsim/mapthinkers/a_floor.cpp +++ b/src/playsim/mapthinkers/a_floor.cpp @@ -155,7 +155,7 @@ void DFloor::Tick () case genFloorChgT: case genFloorChg0: m_Sector->SetSpecial(&m_NewSpecial); - //fall thru + [[fallthrough]]; case genFloorChg: m_Sector->SetTexture(sector_t::floor, m_Texture); break; @@ -171,7 +171,7 @@ void DFloor::Tick () case genFloorChgT: case genFloorChg0: m_Sector->SetSpecial(&m_NewSpecial); - //fall thru + [[fallthrough]]; case genFloorChg: m_Sector->SetTexture(sector_t::floor, m_Texture); break; @@ -811,7 +811,7 @@ bool FLevelLocals::EV_DoDonut (int tag, line_t *line, double pillarspeed, double if (!s2) // note lowest numbered line around continue; // pillar must be two-sided - if (!(compatflags2 & COMPATF2_FLOORMOVE) && s2->PlaneMoving(sector_t::floor)) + if (!(i_compatflags2 & COMPATF2_FLOORMOVE) && s2->PlaneMoving(sector_t::floor)) continue; for (auto ln : s2->Lines) diff --git a/src/playsim/mapthinkers/a_lightning.cpp b/src/playsim/mapthinkers/a_lightning.cpp index 854e262121..f6e0f713dd 100644 --- a/src/playsim/mapthinkers/a_lightning.cpp +++ b/src/playsim/mapthinkers/a_lightning.cpp @@ -36,6 +36,7 @@ #include "g_levellocals.h" #include "events.h" #include "gi.h" +#include static FRandom pr_lightning ("Lightning"); @@ -47,11 +48,12 @@ IMPLEMENT_CLASS(DLightningThinker, false, false) // //---------------------------------------------------------------------------- -void DLightningThinker::Construct() +void DLightningThinker::Construct(FSoundID tempSound) { Stopped = false; LightningFlashCount = 0; NextLightningFlash = ((pr_lightning()&15)+5)*TICRATE; // don't flash at level start + TempLightningSound = tempSound; LightningLightLevels.Resize(Level->sectors.Size()); fillshort(&LightningLightLevels[0], LightningLightLevels.Size(), SHRT_MAX); @@ -73,7 +75,8 @@ void DLightningThinker::Serialize(FSerializer &arc) arc("stopped", Stopped) ("next", NextLightningFlash) ("count", LightningFlashCount) - ("levels", LightningLightLevels); + ("levels", LightningLightLevels) + ("tempsound", TempLightningSound); } //---------------------------------------------------------------------------- @@ -176,7 +179,15 @@ void DLightningThinker::LightningFlash () } Level->flags |= LEVEL_SWAPSKIES; // set alternate sky - S_Sound (CHAN_AUTO, 0, "world/thunder", 1.0, ATTN_NONE); + if (TempLightningSound == NO_SOUND) + { + S_Sound(CHAN_AUTO, 0, Level->LightningSound, 1.0, ATTN_NONE); + } + else + { + S_Sound(CHAN_AUTO, 0, TempLightningSound, 1.0, ATTN_NONE); + TempLightningSound = NO_SOUND; + } // [ZZ] just in case Level->localEventManager->WorldLightning(); // start LIGHTNING scripts @@ -209,16 +220,18 @@ void DLightningThinker::LightningFlash () // //---------------------------------------------------------------------------- -void DLightningThinker::ForceLightning (int mode) +void DLightningThinker::ForceLightning (int mode, FSoundID tempSound) { switch (mode) { default: NextLightningFlash = 0; + TempLightningSound = tempSound; break; case 1: NextLightningFlash = 0; + TempLightningSound = tempSound; // Fall through case 2: Stopped = true; @@ -285,15 +298,24 @@ void FLevelLocals::StartLightning () // //---------------------------------------------------------------------------- -void FLevelLocals::ForceLightning (int mode) +void FLevelLocals::ForceLightning (int mode, FSoundID tempSound) { DLightningThinker *lightning = LocateLightning (this); if (lightning == nullptr) { - lightning = CreateThinker(); + lightning = CreateThinker(tempSound); } if (lightning != nullptr) { - lightning->ForceLightning (mode); + lightning->ForceLightning (mode, tempSound); } } + +DEFINE_ACTION_FUNCTION(FLevelLocals, ForceLightning) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_INT(mode); + PARAM_SOUND(tempSound); + self->ForceLightning(mode,tempSound); + return 0; +} \ No newline at end of file diff --git a/src/playsim/mapthinkers/a_lightning.h b/src/playsim/mapthinkers/a_lightning.h index 89992f620e..f8f9b71dfb 100644 --- a/src/playsim/mapthinkers/a_lightning.h +++ b/src/playsim/mapthinkers/a_lightning.h @@ -6,17 +6,18 @@ #endif #include "dthinker.h" +#include "s_soundinternal.h" class DLightningThinker : public DThinker { DECLARE_CLASS (DLightningThinker, DThinker); public: static const int DEFAULT_STAT = STAT_LIGHTNING; - void Construct(); + void Construct(FSoundID tempSound = NO_SOUND); ~DLightningThinker (); void Serialize(FSerializer &arc); void Tick (); - void ForceLightning (int mode); + void ForceLightning (int mode, FSoundID tempSound = NO_SOUND); void TerminateLightning(); protected: @@ -25,6 +26,7 @@ class DLightningThinker : public DThinker int NextLightningFlash; int LightningFlashCount; bool Stopped; + FSoundID TempLightningSound; TArray LightningLightLevels; }; diff --git a/src/playsim/mapthinkers/a_pusher.h b/src/playsim/mapthinkers/a_pusher.h index 36c9cfab6f..4ce7c73a5a 100644 --- a/src/playsim/mapthinkers/a_pusher.h +++ b/src/playsim/mapthinkers/a_pusher.h @@ -44,3 +44,18 @@ class DPusher : public DThinker friend bool PIT_PushThing (AActor *thing); }; +class DThruster : public DThinker +{ + DECLARE_CLASS(DThruster, DThinker) + + DVector2 m_PushVec; + sector_t* m_Sector; + int m_Type; + int m_Location; + +public: + void Construct(sector_t* sec, double dx, double dy, int type, int location); + void Serialize(FSerializer& arc); + void Tick(); + +}; diff --git a/src/playsim/mapthinkers/a_quake.cpp b/src/playsim/mapthinkers/a_quake.cpp index 35e979a49a..b21951562e 100644 --- a/src/playsim/mapthinkers/a_quake.cpp +++ b/src/playsim/mapthinkers/a_quake.cpp @@ -33,6 +33,8 @@ #include "d_player.h" #include "r_utility.h" #include "g_levellocals.h" +#include "actorinlines.h" +#include static FRandom pr_quake ("Quake"); @@ -49,9 +51,9 @@ IMPLEMENT_POINTERS_END //========================================================================== void DEarthquake::Construct(AActor *center, double intensityX, double intensityY, double intensityZ, int duration, - int damrad, int tremrad, FSoundID quakesound, int flags, - double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, - double rollIntensity, double rollWave) + double damrad, double tremrad, FSoundID quakesound, int flags, + double waveSpeedX, double waveSpeedY, double waveSpeedZ, double falloff, int highpoint, + double rollIntensity, double rollWave, double damageMultiplier, double thrustMultiplier, int damage) { m_QuakeSFX = quakesound; m_Spot = center; @@ -68,6 +70,9 @@ void DEarthquake::Construct(AActor *center, double intensityX, double intensityY m_MiniCount = highpoint; m_RollIntensity = rollIntensity; m_RollWave = rollWave; + m_DamageMultiplier = damageMultiplier; + m_ThrustMultiplier = thrustMultiplier; + m_Damage = damage; } //========================================================================== @@ -93,13 +98,16 @@ void DEarthquake::Serialize(FSerializer &arc) ("minicount", m_MiniCount) ("rollintensity", m_RollIntensity) ("rollwave", m_RollWave); + ("damagemultiplier", m_DamageMultiplier); + ("thrustmultiplier", m_ThrustMultiplier); + ("damage", m_Damage); } //========================================================================== // // DEarthquake :: Tick // -// Deals damage to any players near the earthquake and makes sure it's +// Deals damage to any actors near the earthquake and makes sure it's // making noise. // //========================================================================== @@ -123,16 +131,17 @@ void DEarthquake::Tick () { if (m_Flags & QF_AFFECTACTORS) { - auto iterator = m_Spot->Level->GetThinkerIterator(); - AActor* mo = nullptr; + FPortalGroupArray check(FPortalGroupArray::PGA_Full3d); + FMultiBlockThingsIterator it(check,m_Spot,m_DamageRadius,false); + FMultiBlockThingsIterator::CheckResult cres; - while ((mo = iterator.Next()) != NULL) + while (it.Next(&cres)) { - if (mo == m_Spot) //Ignore the earthquake origin. + AActor *mo = cres.thing; + if (mo == nullptr || mo == m_Spot) //Ignore null references and the earthquake origin. continue; - - DoQuakeDamage(this, mo); + DoQuakeDamage(this, mo, !!(m_Flags & QF_DAMAGEFALLOFF)); } } else @@ -142,7 +151,7 @@ void DEarthquake::Tick () if (Level->PlayerInGame(i) && !(Level->Players[i]->cheats & CF_NOCLIP)) { AActor* victim = Level->Players[i]->mo; - DoQuakeDamage(this, victim); + DoQuakeDamage(this, victim, !!(m_Flags & QF_DAMAGEFALLOFF)); } } } @@ -168,26 +177,37 @@ void DEarthquake::Tick () // //========================================================================== -void DEarthquake::DoQuakeDamage(DEarthquake *quake, AActor *victim) const +void DEarthquake::DoQuakeDamage(DEarthquake *quake, AActor *victim, bool falloff) const { double dist; + double thrustfalloff; + int damage; if (!quake || !victim) return; - dist = quake->m_Spot->Distance2D(victim, true); + dist = quake->m_Spot->Distance2D(victim); + thrustfalloff = falloff ? GetFalloff(dist, m_DamageRadius) : 1.0; // Check if in damage radius if (dist < m_DamageRadius && victim->Z() <= victim->floorz) { if (!(quake->m_Flags & QF_SHAKEONLY) && pr_quake() < 50) { - P_DamageMobj(victim, NULL, NULL, pr_quake.HitDice(1), NAME_Quake); + if (m_Damage < 1) + damage = falloff ? (int)(pr_quake.HitDice(1) * GetFalloff(dist, m_DamageRadius) * m_DamageMultiplier) : (int)(pr_quake.HitDice(1) * m_DamageMultiplier); + //[inkoalawetrust] Do the exact specified damage. + else + damage = falloff ? (int)(m_Damage * GetFalloff(dist, m_DamageRadius) * m_DamageMultiplier) : (int)(m_Damage * m_DamageMultiplier); + + damage = damage < 1 ? 1 : damage; //Do at least a tiny bit of damage when in radius. + + P_DamageMobj(victim, NULL, NULL, damage, NAME_Quake); } - // Thrust player or thrustable actor around - if (victim->player || !(victim->flags7 & MF7_DONTTHRUST)) + // Thrust pushable actor around + if (!(victim->flags7 & MF7_DONTTHRUST) && m_ThrustMultiplier > 0) { DAngle an = victim->Angles.Yaw + DAngle::fromDeg(pr_quake()); - victim->Vel.X += m_Intensity.X * an.Cos() * 0.5; - victim->Vel.Y += m_Intensity.Y * an.Sin() * 0.5; + victim->Vel.X += m_Intensity.X * an.Cos() * m_ThrustMultiplier * thrustfalloff; + victim->Vel.Y += m_Intensity.Y * an.Sin() * m_ThrustMultiplier * thrustfalloff; } } return; @@ -285,19 +305,19 @@ double DEarthquake::GetModIntensity(double intensity, bool fake) const // // DEarthquake :: GetFalloff // -// Given the distance of the player from the quake, find the multiplier. +// Given the distance of the actor from the quake, find the multiplier. // //========================================================================== -double DEarthquake::GetFalloff(double dist) const +double DEarthquake::GetFalloff(double dist, double radius) const { - if ((dist < m_Falloff) || (m_Falloff >= m_TremorRadius) || (m_Falloff <= 0) || (m_TremorRadius - m_Falloff <= 0)) - { //Player inside the minimum falloff range, or safety check kicked in. + if ((dist < m_Falloff) || (m_Falloff >= radius) || (m_Falloff <= 0) || (radius - m_Falloff <= 0)) + { //Actor inside the minimum falloff range, or safety check kicked in. return 1.; } - else if ((dist > m_Falloff) && (dist < m_TremorRadius)) - { //Player inside the radius, and outside the min distance for falloff. - double tremorsize = m_TremorRadius - m_Falloff; + else if ((dist > m_Falloff) && (dist < radius)) + { //Actor inside the radius, and outside the min distance for falloff. + double tremorsize = radius - m_Falloff; assert(tremorsize > 0); return (1. - ((dist - m_Falloff) / tremorsize)); } @@ -335,13 +355,13 @@ int DEarthquake::StaticGetQuakeIntensities(double ticFrac, AActor *victim, FQuak { double dist; - if (quake->m_Flags & QF_3D) dist = quake->m_Spot->Distance3D(victim, true); - else dist = quake->m_Spot->Distance2D(victim, true); + if (quake->m_Flags & QF_3D) dist = quake->m_Spot->Distance3D(victim); + else dist = quake->m_Spot->Distance2D(victim); if (dist < quake->m_TremorRadius) { ++count; - const double falloff = quake->GetFalloff(dist); + const double falloff = quake->GetFalloff(dist, quake->m_TremorRadius); const double r = quake->GetModIntensity(quake->m_RollIntensity); const double strength = quake->GetModIntensity(1.0, true); DVector3 intensity; @@ -409,9 +429,9 @@ int DEarthquake::StaticGetQuakeIntensities(double ticFrac, AActor *victim, FQuak //========================================================================== bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double intensityX, double intensityY, double intensityZ, int duration, - int damrad, int tremrad, FSoundID quakesfx, int flags, - double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, - double rollIntensity, double rollWave) + double damrad, double tremrad, FSoundID quakesfx, int flags, + double waveSpeedX, double waveSpeedY, double waveSpeedZ, double falloff, int highpoint, + double rollIntensity, double rollWave, double damageMultiplier, double thrustMultiplier, int damage) { AActor *center; bool res = false; @@ -425,7 +445,7 @@ bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double int if (activator != NULL) { Level->CreateThinker(activator, intensityX, intensityY, intensityZ, duration, damrad, tremrad, - quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave); + quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave, damageMultiplier, thrustMultiplier, damage); return true; } } @@ -436,14 +456,14 @@ bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double int { res = true; Level->CreateThinker(center, intensityX, intensityY, intensityZ, duration, damrad, tremrad, - quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave); + quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave, damageMultiplier, thrustMultiplier, damage); } } return res; } -bool P_StartQuake(FLevelLocals *Level, AActor *activator, int tid, double intensity, int duration, int damrad, int tremrad, FSoundID quakesfx) +bool P_StartQuake(FLevelLocals * Level, AActor * activator, int tid, double intensity, int duration, double damrad, double tremrad, FSoundID quakesfx) { //Maintains original behavior by passing 0 to intensityZ, flags, and everything else after QSFX. - return P_StartQuakeXYZ(Level, activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0, 0, 0, 0, 0, 0, 0, 0); + return P_StartQuakeXYZ(Level, activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0.5, 0); } diff --git a/src/playsim/mapthinkers/a_scroll.cpp b/src/playsim/mapthinkers/a_scroll.cpp index e0a561ad84..9ac20ccfb9 100644 --- a/src/playsim/mapthinkers/a_scroll.cpp +++ b/src/playsim/mapthinkers/a_scroll.cpp @@ -105,8 +105,11 @@ void DScroller::Serialize(FSerializer &arc) ("vdx", m_vdx) ("vdy", m_vdy) ("accel", m_Accel) + ("affect", m_Affect) .Enum("parts", m_Parts) .Array("interpolations", m_Interpolations, 3); + + if (arc.isReading() && m_Affect == 0) m_Affect = SCROLL_All; } //----------------------------------------------------------------------------- @@ -218,11 +221,55 @@ void DScroller::Tick () // mark all potentially affected things here so that the very expensive calculation loop in AActor::Tick does not need to run for actors which do not touch a scrolling sector. for (auto n = m_Sector->touching_thinglist; n; n = n->m_snext) { + AActor* actor = n->m_thing; + if (actor->player) + { + if (!(m_Affect & SCROLL_Players)) + continue; + } + else if (actor->flags3 & MF3_ISMONSTER) + { + if (!(m_Affect & SCROLL_Monsters)) + continue; + } + else if (!(m_Affect & SCROLL_StaticObjects)) + continue; + n->m_thing->flags8 |= MF8_INSCROLLSEC; } break; - case EScroll::sc_carry_ceiling: // to be added later + case EScroll::sc_carry_ceiling: + // this just copies DSDA's implementation. Usability is limited. + for (auto n = m_Sector->touching_thinglist; n; n = n->m_snext) + { + AActor* actor = n->m_thing; + + if ( + !(actor->flags & MF_NOCLIP) && + actor->flags & MF_SPAWNCEILING && + actor->flags & MF_NOGRAVITY && + actor->Top() == m_Sector->ceilingplane.ZatPoint(actor->Pos().XY()) + ) + { + + if (actor->player) + { + if (!(m_Affect & SCROLL_Players)) + continue; + } + else if (actor->flags3 & MF3_ISMONSTER) + { + if (!(m_Affect & SCROLL_Monsters)) + continue; + } + else if (!(m_Affect & SCROLL_StaticObjects)) + continue; + + n->m_thing->Vel.X = m_dx; + n->m_thing->Vel.Y = m_dy; + } + } break; } } @@ -247,7 +294,7 @@ void DScroller::Tick () // //----------------------------------------------------------------------------- -void DScroller::Construct (EScroll type, double dx, double dy, sector_t *ctrl, sector_t *sec, side_t *side, int accel, EScrollPos scrollpos) +void DScroller::Construct (EScroll type, double dx, double dy, sector_t *ctrl, sector_t *sec, side_t *side, int accel, EScrollPos scrollpos, int aff) { m_Type = type; m_dx = dx; @@ -256,6 +303,7 @@ void DScroller::Construct (EScroll type, double dx, double dy, sector_t *ctrl, m_Parts = scrollpos; m_vdx = m_vdy = 0; m_LastHeight = 0; + m_Affect = aff; if ((m_Controller = ctrl) != nullptr) { m_LastHeight = m_Controller->CenterFloor() + m_Controller->CenterCeiling(); @@ -344,6 +392,7 @@ void DScroller::Construct(double dx, double dy, const line_t *l, sector_t * cont m_Accel = accel; m_Parts = scrollpos; m_LastHeight = 0; + m_Affect = SCROLL_All; // not really relevant, so use the default. if ((m_Controller = control) != nullptr) { m_LastHeight = m_Controller->CenterFloor() + m_Controller->CenterCeiling(); diff --git a/src/playsim/mapthinkers/a_scroll.h b/src/playsim/mapthinkers/a_scroll.h index 95d985117b..f4d7c37966 100644 --- a/src/playsim/mapthinkers/a_scroll.h +++ b/src/playsim/mapthinkers/a_scroll.h @@ -1,5 +1,14 @@ #pragma once +enum EScrollAffect +{ + SCROLL_Textures = 1, + SCROLL_StaticObjects = 2, + SCROLL_Players = 4, + SCROLL_Monsters = 8, + SCROLL_All = 15 +}; + //----------------------------------------------------------------------------- // // killough 3/7/98: Add generalized scroll effects @@ -13,7 +22,7 @@ class DScroller : public DThinker public: static const int DEFAULT_STAT = STAT_SCROLLER; - void Construct(EScroll type, double dx, double dy, sector_t *control, sector_t *sec, side_t *side, int accel, EScrollPos scrollpos = EScrollPos::scw_all); + void Construct(EScroll type, double dx, double dy, sector_t *control, sector_t *sec, side_t *side, int accel, EScrollPos scrollpos = EScrollPos::scw_all, int aff = SCROLL_All); void Construct(double dx, double dy, const line_t *l, sector_t *control, int accel, EScrollPos scrollpos = EScrollPos::scw_all); void OnDestroy() override; @@ -29,6 +38,7 @@ class DScroller : public DThinker protected: EScroll m_Type; // Type of scroll effect + int m_Affect; double m_dx, m_dy; // (dx,dy) scroll speeds sector_t *m_Sector; // Affected sector side_t *m_Side; // ... or side diff --git a/src/playsim/mapthinkers/a_thruster.cpp b/src/playsim/mapthinkers/a_thruster.cpp new file mode 100644 index 0000000000..ca052678bd --- /dev/null +++ b/src/playsim/mapthinkers/a_thruster.cpp @@ -0,0 +1,155 @@ +//----------------------------------------------------------------------------- +// +// Copyright 2023 Ryan Krafnick +// Copyright 2023 Christoph Oelckers +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// +//----------------------------------------------------------------------------- +// +// DESCRIPTION: +// UDMF-style thruster +// +//----------------------------------------------------------------------------- + + +#include +#include "actor.h" +#include "p_spec.h" +#include "serializer.h" +#include "serializer_doom.h" +#include "p_spec_thinkers.h" + +EXTERN_CVAR(Bool, var_pushers); + +IMPLEMENT_CLASS(DThruster, false, false) + +enum +{ + THRUST_STATIC = 0x01, + THRUST_PLAYER = 0x02, + THRUST_MONSTER = 0x04, + THRUST_PROJECTILE = 0x08, + THRUST_WINDTHRUST = 0x10, + + THRUST_GROUNDED = 1, + THRUST_AIRBORNE = 2, + THRUST_CEILING = 4 +}; + + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +void DThruster::Serialize(FSerializer &arc) +{ + Super::Serialize (arc); + arc("type", m_Type) + ("location", m_Location) + ("pushvec", m_PushVec) + ("sector", m_Sector); +} + + +//----------------------------------------------------------------------------- +// +// Add a thrust thinker to the thinker list +// +//----------------------------------------------------------------------------- + +void DThruster::Construct(sector_t* sec, double dx, double dy, int type, int location) +{ + m_Type = type; + m_Location = location; + m_Sector = sec; + m_PushVec = { dx, dy }; +} + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +void DThruster::Tick () +{ + sector_t* sec = m_Sector; + + if (m_PushVec.isZero()) + return; + + for (auto node = sec->touching_thinglist; node; node = node->m_snext) + { + bool thrust_it = false; + AActor* thing = node->m_thing; + + if (thing->flags & MF_NOCLIP) + continue; + + if (!(thing->flags & MF_NOGRAVITY) && thing->Z() <= thing->floorz) + { + if (m_Location & THRUST_GROUNDED) + thrust_it = true; + } + else if ( + thing->flags & MF_SPAWNCEILING && + thing->flags & MF_NOGRAVITY && + thing->Top() == thing->ceilingz + ) + { + if (m_Location & THRUST_CEILING) + thrust_it = true; + } + else if (thing->flags & MF_NOGRAVITY || thing->Z() > thing->floorz) + { + if (m_Location & THRUST_AIRBORNE) + thrust_it = true; + } + + if (thrust_it) + { + thrust_it = false; + + if (thing->flags2 & MF2_WINDTHRUST && m_Type & THRUST_WINDTHRUST) + thrust_it = true; + else if (thing->flags3 & MF3_ISMONSTER) + { + if (m_Type & THRUST_MONSTER) + thrust_it = true; + } + else if (thing->player) + { + if (m_Type & THRUST_PLAYER) + thrust_it = true; + } + else if (thing->flags & MF_MISSILE) + { + if (m_Type & THRUST_PROJECTILE) + thrust_it = true; + } + else + { + if (m_Type & THRUST_STATIC) + thrust_it = true; + } + + if (thrust_it) + { + thing->Vel += m_PushVec; + } + } + } +} + diff --git a/src/playsim/p_3dmidtex.cpp b/src/playsim/p_3dmidtex.cpp index 315ded0c9c..0e2d7e10df 100644 --- a/src/playsim/p_3dmidtex.cpp +++ b/src/playsim/p_3dmidtex.cpp @@ -44,6 +44,7 @@ #include "g_levellocals.h" #include "actor.h" #include "texturemanager.h" +#include "vm.h" //============================================================================ @@ -258,6 +259,20 @@ bool P_GetMidTexturePosition(const line_t *line, int sideno, double *ptextop, do return true; } +DEFINE_ACTION_FUNCTION(_Line, GetMidTexturePosition) +{ + PARAM_SELF_STRUCT_PROLOGUE(line_t); + PARAM_INT(side); + double top = 0.0; + double bottom = 0.0; + + bool res = P_GetMidTexturePosition(self,side,&top,&bottom); + if (numret > 2) ret[2].SetFloat(bottom); + if (numret > 1) ret[1].SetFloat(top); + if (numret > 0) ret[0].SetInt(int(res)); + return numret; +} + //============================================================================ // // P_LineOpening_3dMidtex diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index ff97c7484e..b464ed2a5e 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -979,7 +979,7 @@ int ACSStringPool::AddString(FString &str) { unsigned int h = SuperFastHash(str.GetChars(), str.Len()); unsigned int bucketnum = h % NUM_BUCKETS; - int i = FindString(str, str.Len(), h, bucketnum); + int i = FindString(str.GetChars(), str.Len(), h, bucketnum); if (i >= 0) { return i | STRPOOL_LIBRARYID_OR; @@ -999,7 +999,7 @@ const char *ACSStringPool::GetString(int strnum) strnum &= ~LIBRARYID_MASK; if ((unsigned)strnum < Pool.Size() && Pool[strnum].Next != FREE_ENTRY) { - return Pool[strnum].Str; + return Pool[strnum].Str.GetChars(); } return NULL; } @@ -1299,7 +1299,7 @@ void ACSStringPool::ReadStrings(FSerializer &file, const char *key) file("string", Pool[ii].Str) ("locks", Pool[ii].Locks); - unsigned h = SuperFastHash(Pool[ii].Str, Pool[ii].Str.Len()); + unsigned h = SuperFastHash(Pool[ii].Str.GetChars(), Pool[ii].Str.Len()); unsigned bucketnum = h % NUM_BUCKETS; Pool[ii].Hash = h; Pool[ii].Next = PoolBuckets[bucketnum]; @@ -1595,7 +1595,7 @@ static void WriteArrayVars (FSerializer &file, FWorldGlobalArray *vars, unsigned FString arraykey; arraykey.Format("%d", i); - if (file.BeginObject(arraykey)) + if (file.BeginObject(arraykey.GetChars())) { FWorldGlobalArray::ConstIterator it(vars[i]); const FWorldGlobalArray::Pair *pair; @@ -1930,7 +1930,7 @@ void FBehaviorContainer::LoadDefaultModules () FScanner sc(lump); while (sc.GetString()) { - int acslump = fileSystem.CheckNumForName (sc.String, ns_acslibrary); + int acslump = fileSystem.CheckNumForName (sc.String, FileSys::ns_acslibrary); if (acslump >= 0) { LoadModule (acslump); @@ -2277,8 +2277,7 @@ bool FBehavior::Init(FLevelLocals *Level, int lumpnum, FileReader * fr, int len, if (fr == NULL) { - fileSystem.GetFileShortName (ModuleName, lumpnum); - ModuleName[8] = 0; + strcpy(ModuleName, fileSystem.GetFileShortName (lumpnum)); } else { @@ -2568,7 +2567,7 @@ bool FBehavior::Init(FLevelLocals *Level, int lumpnum, FileReader * fr, int len, if (parse[i]) { FBehavior *module = NULL; - int lump = fileSystem.CheckNumForName (&parse[i], ns_acslibrary); + int lump = fileSystem.CheckNumForName (&parse[i], FileSys::ns_acslibrary); if (lump < 0) { Printf (TEXTCOLOR_RED "Could not find ACS library %s.\n", &parse[i]); @@ -3249,7 +3248,7 @@ const char *FBehavior::LookupString (uint32_t index, bool forprint) const token.Truncate(5); FStringf label("TXT_ACS_%s_%d_%.5s", Level->MapName.GetChars(), index, token.GetChars()); - auto p = GStrings[label]; + auto p = GStrings.CheckString(label.GetChars()); if (p) return p; } @@ -6094,7 +6093,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) { newlen = oldlen - pos; } - return GlobalACSStrings.AddString(FString(oldstr + pos, newlen)); + return GlobalACSStrings.AddString(FString(oldstr + pos, newlen).GetChars()); } break; @@ -6243,7 +6242,10 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) argCount > 12 ? args[12] : 0, argCount > 13 ? args[13] : 0, argCount > 14 ? ACSToDouble(args[14]) : 0, - argCount > 15 ? ACSToDouble(args[15]) : 0); + argCount > 15 ? ACSToDouble(args[15]) : 0, + argCount > 16 ? ACSToDouble(args[16]) : 1.0, + argCount > 17 ? ACSToDouble(args[17]) : 0.5, + argCount > 18 ? args[18] : 0); } case ACSF_SetLineActivation: @@ -6672,7 +6674,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) auto a = Level->SingleActorFromTID(args[0], activator); if (a != nullptr) { - return GlobalACSStrings.AddString(TexMan.GetGameTexture(a->floorpic)->GetName()); + return GlobalACSStrings.AddString(TexMan.GetGameTexture(a->floorpic)->GetName().GetChars()); } else { @@ -8501,7 +8503,7 @@ int DLevelScript::RunScript() lookup = Level->Behaviors.LookupString (STACK(1), true); if (pcd == PCD_PRINTLOCALIZED) { - lookup = GStrings(lookup); + lookup = GStrings.GetString(lookup); } if (lookup != NULL) { @@ -8727,7 +8729,7 @@ int DLevelScript::RunScript() if (pcd == PCD_ENDPRINTBOLD || screen == NULL || screen->CheckLocalView()) { - C_MidPrint (activefont, work, pcd == PCD_ENDPRINTBOLD && (gameinfo.correctprintbold || (Level->flags2 & LEVEL2_HEXENHACK))); + C_MidPrint (activefont, work.GetChars(), pcd == PCD_ENDPRINTBOLD && (gameinfo.correctprintbold || (Level->flags2 & LEVEL2_HEXENHACK))); } STRINGBUILDER_FINISH(work); } @@ -8782,13 +8784,13 @@ int DLevelScript::RunScript() { default: // normal alpha = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 1.f; - msg = Create (activefont, work, x, y, hudwidth, hudheight, color, holdTime); + msg = Create (activefont, work.GetChars(), x, y, hudwidth, hudheight, color, holdTime); break; case 1: // fade out { float fadeTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.5f; alpha = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 1.f; - msg = Create (activefont, work, x, y, hudwidth, hudheight, color, holdTime, fadeTime); + msg = Create (activefont, work.GetChars(), x, y, hudwidth, hudheight, color, holdTime, fadeTime); } break; case 2: // type on, then fade out @@ -8796,7 +8798,7 @@ int DLevelScript::RunScript() float typeTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.05f; float fadeTime = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 0.5f; alpha = (optstart < sp-2) ? ACSToFloat(Stack[optstart+2]) : 1.f; - msg = Create (activefont, work, x, y, hudwidth, hudheight, color, typeTime, holdTime, fadeTime); + msg = Create (activefont, work.GetChars(), x, y, hudwidth, hudheight, color, typeTime, holdTime, fadeTime); } break; case 3: // fade in, then fade out @@ -8804,7 +8806,7 @@ int DLevelScript::RunScript() float inTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.5f; float outTime = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 0.5f; alpha = (optstart < sp-2) ? ACSToFloat(Stack[optstart + 2]) : 1.f; - msg = Create (activefont, work, x, y, hudwidth, hudheight, color, holdTime, inTime, outTime); + msg = Create (activefont, work.GetChars(), x, y, hudwidth, hudheight, color, holdTime, inTime, outTime); } break; } @@ -10502,7 +10504,7 @@ EXTERN_CVAR (Bool, sv_cheats) int P_StartScript (FLevelLocals *Level, AActor *who, line_t *where, int script, const char *map, const int *args, int argcount, int flags) { - if (map == NULL || 0 == strnicmp (Level->MapName, map, 8)) + if (map == NULL || 0 == strnicmp (Level->MapName.GetChars(), map, 8)) { FBehavior *module = NULL; const ScriptPtr *scriptdata; @@ -10557,7 +10559,7 @@ int P_StartScript (FLevelLocals *Level, AActor *who, line_t *where, int script, void P_SuspendScript (FLevelLocals *Level, int script, const char *map) { - if (strnicmp (Level->MapName, map, 8)) + if (strnicmp (Level->MapName.GetChars(), map, 8)) addDefered (FindLevelInfo (map), acsdefered_t::defsuspend, script, NULL, 0, NULL); else SetScriptState (Level->ACSThinker, script, DLevelScript::SCRIPT_Suspended); @@ -10565,7 +10567,7 @@ void P_SuspendScript (FLevelLocals *Level, int script, const char *map) void P_TerminateScript (FLevelLocals *Level, int script, const char *map) { - if (strnicmp (Level->MapName, map, 8)) + if (strnicmp (Level->MapName.GetChars(), map, 8)) addDefered (FindLevelInfo (map), acsdefered_t::defterminate, script, NULL, 0, NULL); else SetScriptState (Level->ACSThinker, script, DLevelScript::SCRIPT_PleaseRemove); @@ -10739,7 +10741,7 @@ static int sort_by_runs(const void *a_, const void *b_) return b->ProfileData->NumRuns - a->ProfileData->NumRuns; } -static void ShowProfileData(TArray &profiles, long ilimit, +static void ShowProfileData(TArray &profiles, int ilimit, int (*sorter)(const void *, const void *), bool functions) { static const char *const typelabels[2] = { "script", "function" }; @@ -10757,7 +10759,7 @@ static void ShowProfileData(TArray &profiles, long ilimit, if (ilimit > 0) { - Printf(TEXTCOLOR_ORANGE "Top %ld %ss:\n", ilimit, typelabels[functions]); + Printf(TEXTCOLOR_ORANGE "Top %lld %ss:\n", ilimit, typelabels[functions]); limit = (unsigned int)ilimit; } else @@ -10823,7 +10825,7 @@ void ACSProfile(FLevelLocals *Level, FCommandLine &argv) static const uint8_t sort_match_len[] = { 1, 2, 2, 1, 1 }; TArray ScriptProfiles, FuncProfiles; - long limit = 10; + int limit = 10; int (*sorter)(const void *, const void *) = sort_by_total_instr; assert(countof(sort_names) == countof(sort_match_len)); @@ -10845,7 +10847,7 @@ void ACSProfile(FLevelLocals *Level, FCommandLine &argv) { // If it's a number, set the display limit. char *endptr; - long num = strtol(argv[i], &endptr, 0); + int num = (int)strtoll(argv[i], &endptr, 0); if (endptr != argv[i]) { limit = num; diff --git a/src/playsim/p_acs.h b/src/playsim/p_acs.h index c2013a0f12..695b229488 100644 --- a/src/playsim/p_acs.h +++ b/src/playsim/p_acs.h @@ -38,12 +38,12 @@ #include "doomtype.h" #include "dthinker.h" #include "engineerrors.h" +#include "files.h" #define LOCAL_SIZE 20 #define NUM_MAPVARS 128 class FFont; -class FileReader; struct line_t; class FSerializer; diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index 157ef9336a..b6090213b3 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -70,20 +70,22 @@ #include "actorinlines.h" #include "types.h" #include "model.h" +#include "shadowinlines.h" +#include "i_time.h" static FRandom pr_camissile ("CustomActorfire"); static FRandom pr_cabullet ("CustomBullet"); static FRandom pr_cwjump ("CustomWpJump"); static FRandom pr_cwpunch ("CustomWpPunch"); static FRandom pr_grenade ("ThrowGrenade"); -static FRandom pr_crailgun ("CustomRailgun"); + FRandom pr_crailgun ("CustomRailgun"); static FRandom pr_spawndebris ("SpawnDebris"); static FRandom pr_spawnitemex ("SpawnItemEx"); static FRandom pr_burst ("Burst"); static FRandom pr_monsterrefire ("MonsterRefire"); static FRandom pr_teleport("A_Teleport"); static FRandom pr_bfgselfdamage("BFGSelfDamage"); -FRandom pr_cajump("CustomJump"); + FRandom pr_cajump("CustomJump"); //========================================================================== // @@ -127,9 +129,8 @@ static int CallStateChain (AActor *self, AActor *actor, FState *state) if (state->ActionFunc->Unsafe) { // If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash. - auto owner = FState::StaticFindStateOwner(state); Printf(TEXTCOLOR_RED "Unsafe state call in state %s to %s which accesses user variables. The action function has been removed from this state\n", - FState::StaticGetStateName(state).GetChars(), state->ActionFunc->PrintableName.GetChars()); + FState::StaticGetStateName(state).GetChars(), state->ActionFunc->PrintableName); state->ActionFunc = nullptr; } @@ -384,7 +385,7 @@ DEFINE_ACTION_FUNCTION(AActor, GetCVar) PARAM_SELF_PROLOGUE(AActor); PARAM_STRING(cvarname); - FBaseCVar *cvar = GetCVar(self->player ? int(self->player - players) : -1, cvarname); + FBaseCVar *cvar = GetCVar(self->player ? int(self->player - players) : -1, cvarname.GetChars()); if (cvar == nullptr) { ret->SetFloat(0); @@ -414,7 +415,7 @@ DEFINE_ACTION_FUNCTION(AActor, GetCVarString) PARAM_SELF_PROLOGUE(AActor); PARAM_STRING(cvarname); - FBaseCVar *cvar = GetCVar(self->player? int(self->player - players) : -1, cvarname); + FBaseCVar *cvar = GetCVar(self->player? int(self->player - players) : -1, cvarname.GetChars()); if (cvar == nullptr) { ret->SetString(""); @@ -1226,11 +1227,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun) self->Angles.Yaw = self->AngleTo(self->target,- self->target->Vel.X * veleffect, -self->target->Vel.Y * veleffect); } - if (self->target->flags & MF_SHADOW) - { - DAngle rnd = DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.)); - self->Angles.Yaw += rnd; - } + A_CustomRailgun_ShadowHandling(self, spawnofs_xy, spawnofs_z, spread_xy, flags); } if (!(flags & CRF_EXPLICITANGLE)) @@ -1295,7 +1292,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Print) PARAM_FLOAT (time); PARAM_NAME (fontname); - if (text[0] == '$') text = GStrings(&text[1]); + if (text[0] == '$') text = GStrings.GetString(&text[1]); if (self->CheckLocalView() || (self->target != NULL && self->target->CheckLocalView())) { @@ -1310,7 +1307,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Print) { con_midtime = float(time); } - FString formatted = strbin1(text); + FString formatted = strbin1(text.GetChars()); C_MidPrint(font, formatted.GetChars()); con_midtime = saved; } @@ -1333,7 +1330,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PrintBold) float saved = con_midtime; FFont *font = NULL; - if (text[0] == '$') text = GStrings(&text[1]); + if (text[0] == '$') text = GStrings.GetString(&text[1]); if (fontname != NAME_None) { font = V_GetFont(fontname.GetChars()); @@ -1342,7 +1339,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PrintBold) { con_midtime = float(time); } - FString formatted = strbin1(text); + FString formatted = strbin1(text.GetChars()); C_MidPrint(font, formatted.GetChars(), true); con_midtime = saved; return 0; @@ -1362,8 +1359,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_Log) if (local && !self->CheckLocalView()) return 0; - if (text[0] == '$') text = GStrings(&text[1]); - FString formatted = strbin1(text); + if (text[0] == '$') text = GStrings.GetString(&text[1]); + FString formatted = strbin1(text.GetChars()); Printf("%s\n", formatted.GetChars()); return 0; } @@ -1399,7 +1396,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LogFloat) if (local && !self->CheckLocalView()) return 0; IGNORE_FORMAT_PRE - Printf("%H\n", num); + Printf("%g\n", num); IGNORE_FORMAT_POST return 0; } @@ -1611,18 +1608,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnDebris) // A_SpawnParticle // //=========================================================================== -enum SPFflag -{ - SPF_FULLBRIGHT = 1, - SPF_RELPOS = 1 << 1, - SPF_RELVEL = 1 << 2, - SPF_RELACCEL = 1 << 3, - SPF_RELANG = 1 << 4, - SPF_NOTIMEFREEZE = 1 << 5, - SPF_ROLL = 1 << 6, - SPF_REPLACE = 1 << 7, - SPF_NO_XY_BILLBOARD = 1 << 8, -}; DEFINE_ACTION_FUNCTION(AActor, A_SpawnParticle) { @@ -1706,7 +1691,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnParticleEx) PARAM_FLOAT (rollacc) startalpha = clamp(startalpha, 0., 1.); - if (fadestep > 0) fadestep = clamp(fadestep, 0., 1.); + fadestep = clamp(fadestep, -1.0, 1.0); + size = fabs(size); if (lifetime != 0) { @@ -2059,7 +2045,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Respawn) } else { - oktorespawn = P_CheckPosition(self, self->Pos(), true); + oktorespawn = P_CheckPosition(self, self->Pos().XY(), true); } if (oktorespawn) @@ -2092,6 +2078,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Respawn) self->flags6 = defs->flags6; self->flags7 = defs->flags7; self->flags8 = defs->flags8; + self->flags9 = defs->flags9; self->SetState (self->SpawnState); self->renderflags &= ~RF_INVISIBLE; @@ -2689,7 +2676,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckFlag) PARAM_INT (checkpointer); AActor *owner = COPY_AAPTR(self, checkpointer); - ACTION_RETURN_BOOL(owner != nullptr && CheckActorFlag(owner, flagname)); + ACTION_RETURN_BOOL(owner != nullptr && CheckActorFlag(owner, flagname.GetChars())); } @@ -3335,8 +3322,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_Quake) PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT (intensity); PARAM_INT (duration); - PARAM_INT (damrad); - PARAM_INT (tremrad); + PARAM_FLOAT (damrad); + PARAM_FLOAT (tremrad); PARAM_SOUND (sound); P_StartQuake(self->Level, self, 0, intensity, duration, damrad, tremrad, sound); @@ -3358,19 +3345,22 @@ DEFINE_ACTION_FUNCTION(AActor, A_QuakeEx) PARAM_FLOAT(intensityY); PARAM_FLOAT(intensityZ); PARAM_INT(duration); - PARAM_INT(damrad); - PARAM_INT(tremrad); + PARAM_FLOAT(damrad); + PARAM_FLOAT(tremrad); PARAM_SOUND(sound); PARAM_INT(flags); PARAM_FLOAT(mulWaveX); PARAM_FLOAT(mulWaveY); PARAM_FLOAT(mulWaveZ); - PARAM_INT(falloff); + PARAM_FLOAT(falloff); PARAM_INT(highpoint); PARAM_FLOAT(rollIntensity); PARAM_FLOAT(rollWave); + PARAM_FLOAT(damageMultiplier); + PARAM_FLOAT(thrustMultiplier); + PARAM_INT(damage); P_StartQuakeXYZ(self->Level, self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ, falloff, highpoint, - rollIntensity, rollWave); + rollIntensity, rollWave, damageMultiplier, thrustMultiplier, damage); return 0; } @@ -3504,7 +3494,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WolfAttack) // Target can dodge if it can see enemy DAngle angle = absangle(self->target->Angles.Yaw, self->target->AngleTo(self)); - bool dodge = (P_CheckSight(self->target, self) && angle < DAngle::fromDeg(30. * 256. / 360.)); // 30 byteangles ~ 21 + bool dodge = (P_CheckSight(self->target, self) && angle < DAngle::fromDeg(30. * 256. / 360.)); // 30 byteangles ~ 21° // Distance check is simplistic DVector2 vec = self->Vec2To(self->target); @@ -3526,7 +3516,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WolfAttack) hitchance -= idist * (dodge ? 16 : 8); // While we're here, we may as well do something for this: - if (self->target->flags & MF_SHADOW) + if (A_WolfAttack_ShadowHandling(self)) { hitchance >>= 2; } @@ -4752,7 +4742,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckBlock) if (flags & CBF_NOACTORS) fpass |= PCM_NOACTORS; if (flags & CBF_NOLINES) fpass |= PCM_NOLINES; mobj->SetZ(pos.Z); - checker = P_CheckMove(mobj, pos, fpass); + checker = P_CheckMove(mobj, pos.XY(), fpass); mobj->SetZ(oldpos.Z); } else @@ -5080,7 +5070,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SprayDecal) PARAM_FLOAT(direction_z); PARAM_BOOL(useBloodColor); PARAM_COLOR(decalColor); - SprayDecal(self, name, dist, DVector3(offset_x, offset_y, offset_z), DVector3(direction_x, direction_y, direction_z), useBloodColor, decalColor); + SprayDecal(self, name.GetChars(), dist, DVector3(offset_x, offset_y, offset_z), DVector3(direction_x, direction_y, direction_z), useBloodColor, decalColor); return 0; } @@ -5089,7 +5079,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetMugshotState) PARAM_SELF_PROLOGUE(AActor); PARAM_STRING(name); if (self->CheckLocalView()) - StatusBar->SetMugShotState(name); + StatusBar->SetMugShotState(name.GetChars()); return 0; } @@ -5100,163 +5090,476 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetMugshotState) // This function allows the changing of an actor's modeldef, or models and/or skins at a given index //========================================================================== -enum ChangeModelFlags +static void EnsureModelData(AActor * mobj) { - CMDL_WEAPONTOPLAYER = 1, - CMDL_HIDEMODEL = 1 << 1, - CMDL_USESURFACESKIN = 1 << 2, + if (mobj->modelData == nullptr) + { + auto ptr = Create(); + + ptr->flags = (mobj->hasmodel ? MODELDATA_HADMODEL : 0); + ptr->modelDef = nullptr; + + mobj->modelData = ptr; + mobj->hasmodel = true; + GC::WriteBarrier(mobj, ptr); + } +} + +static void CleanupModelData(AActor * mobj) +{ + if ( !(mobj->flags9 & MF9_DECOUPLEDANIMATIONS) + && mobj->modelData->models.Size() == 0 + && mobj->modelData->modelFrameGenerators.Size() == 0 + && mobj->modelData->skinIDs.Size() == 0 + && mobj->modelData->animationIDs.Size() == 0 + && mobj->modelData->modelDef == nullptr + &&(mobj->modelData->flags & ~MODELDATA_HADMODEL) == 0 ) + { + mobj->hasmodel = mobj->modelData->flags & MODELDATA_HADMODEL; + mobj->modelData->Destroy(); + mobj->modelData = nullptr; + } +} + +enum ESetAnimationFlags +{ + SAF_INSTANT = 1 << 0, + SAF_LOOP = 1 << 1, + SAF_NOOVERRIDE = 1 << 2, }; -DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel) +extern double getCurrentFrame(const AnimOverride &anim, double tic); + +void SetAnimationInternal(AActor * self, FName animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags, double ticFrac) { - PARAM_ACTION_PROLOGUE(AActor); - PARAM_NAME(modeldef); - PARAM_INT(modelindex); - PARAM_STRING_VAL(modelpath); - PARAM_NAME(model); - PARAM_INT(skinindex); - PARAM_STRING_VAL(skinpath); - PARAM_NAME(skin); - PARAM_INT(flags); - PARAM_INT(generatorindex); - PARAM_INT(animationindex); - PARAM_STRING_VAL(animationpath); - PARAM_NAME(animation); + if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self"); - if (self == nullptr) - ACTION_RETURN_BOOL(false); - else if (modeldef != NAME_None && PClass::FindClass(modeldef.GetChars()) == nullptr) + if(!(self->flags9 & MF9_DECOUPLEDANIMATIONS)) { - Printf("Attempt to pass invalid modeldef name %s in %s.", modeldef.GetChars(), self->GetCharacterName()); - ACTION_RETURN_BOOL(false); + ThrowAbortException(X_OTHER, "Cannot set animation for non-decoupled actors"); } - else if (modelindex < 0) + + if(!BaseSpriteModelFrames.CheckKey(self->GetClass())) { - Printf("Attempt to pass invalid model index %d in %s, index must be non-negative.", modelindex, self->GetCharacterName()); - ACTION_RETURN_BOOL(false); + ThrowAbortException(X_OTHER, "Actor class is missing a MODELDEF definition or a MODELDEF BaseFrame"); } - else if (skinindex < 0) + + if(interpolateTics <= 0) interpolateTics = 1; + + EnsureModelData(self); + + if(animName == NAME_None) { - Printf("Attempt to pass invalid skin index %d in %s, index must be non-negative.", skinindex, self->GetCharacterName()); - ACTION_RETURN_BOOL(false); + self->modelData->curAnim.flags = ANIMOVERRIDE_NONE; + return; } - else if (animationindex < 0) + + double tic = self->Level->totaltime; + if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !self->Level->isFrozen()) { - Printf("Attempt to pass invalid animation index %d in %s, index must be non-negative.", animationindex, self->GetCharacterName()); - ACTION_RETURN_BOOL(false); + tic += ticFrac; } - AActor* mobj = (ACTION_CALL_FROM_PSPRITE() && (flags & CMDL_WEAPONTOPLAYER)) || ACTION_CALL_FROM_INVENTORY() ? self : stateowner; + FModel * mdl = Models[(self->modelData->models.Size() > 0 && self->modelData->models[0].modelID >= 0) ? self->modelData->models[0].modelID : BaseSpriteModelFrames[self->GetClass()].modelIDs[0]]; - if (modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/'; - if (skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/'; - if (animationpath[(int)animationpath.Len() - 1] != '/') animationpath += '/'; + int animStart = mdl->FindFirstFrame(animName); + if(animStart == FErr_NotFound) + { + self->modelData->curAnim.flags = ANIMOVERRIDE_NONE; + Printf("Could not find animation %s\n", animName.GetChars()); + return; + } - if (mobj->modelData == nullptr) + if((flags & SAF_NOOVERRIDE) && self->modelData->curAnim.flags != ANIMOVERRIDE_NONE && self->modelData->curAnim.firstFrame == animStart) { - auto ptr = Create(); - ptr->hasModel = mobj->hasmodel ? 1 : 0; - ptr->modelIDs = *new TArray(); - ptr->skinIDs = *new TArray(); - ptr->surfaceSkinIDs = *new TArray(); - ptr->animationIDs = *new TArray(); - ptr->modelFrameGenerators = *new TArray(); - ptr->modelDef = NAME_None; - mobj->modelData = ptr; - mobj->hasmodel = 1; - GC::WriteBarrier(mobj, ptr); + //same animation as current, skip setting it + return; + } + + if(!(flags & SAF_INSTANT)) + { + self->modelData->prevAnim = self->modelData->curAnim; + } + + int animEnd = mdl->FindLastFrame(animName); + + if(framerate < 0) + { + framerate = mdl->FindFramerate(animName); } + + int len = animEnd - animStart; + + if(startFrame >= len) + { + self->modelData->curAnim.flags = ANIMOVERRIDE_NONE; + Printf("frame %d (startFrame) is past the end of animation %s\n", startFrame, animName.GetChars()); + return; + } + else if(loopFrame >= len) + { + self->modelData->curAnim.flags = ANIMOVERRIDE_NONE; + Printf("frame %d (loopFrame) is past the end of animation %s\n", startFrame, animName.GetChars()); + return; + } + else if(endFrame >= len) + { + self->modelData->curAnim.flags = ANIMOVERRIDE_NONE; + Printf("frame %d (endFrame) is past the end of animation %s\n", endFrame, animName.GetChars()); + return; + } + + self->modelData->curAnim.firstFrame = animStart; + self->modelData->curAnim.lastFrame = endFrame < 0 ? animEnd - 1 : animStart + endFrame; + self->modelData->curAnim.startFrame = startFrame < 0 ? animStart : animStart + startFrame; + self->modelData->curAnim.loopFrame = loopFrame < 0 ? animStart : animStart + loopFrame; + self->modelData->curAnim.flags = (flags&SAF_LOOP) ? ANIMOVERRIDE_LOOP : 0; + self->modelData->curAnim.switchTic = tic; + self->modelData->curAnim.framerate = (float)framerate; + + if(!(flags & SAF_INSTANT)) + { + self->modelData->prevAnim.startFrame = getCurrentFrame(self->modelData->prevAnim, tic); + + self->modelData->curAnim.startTic = floor(tic) + interpolateTics; + } + else + { + self->modelData->curAnim.startTic = tic; + } +} + +void SetAnimationNative(AActor * self, int i_animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags) +{ + SetAnimationInternal(self, FName(ENamedName(i_animName)), framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, 1); +} + +void SetAnimationUINative(AActor * self, int i_animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags) +{ + SetAnimationInternal(self, FName(ENamedName(i_animName)), framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, I_GetTimeFrac()); +} + +void SetAnimationFrameRateInternal(AActor * self, double framerate, double ticFrac) +{ + if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self"); + + if(!(self->flags9 & MF9_DECOUPLEDANIMATIONS)) + { + ThrowAbortException(X_OTHER, "Cannot set animation for non-decoupled actors"); + } + + EnsureModelData(self); + + if(self->modelData->curAnim.flags & ANIMOVERRIDE_NONE) return; + + if(framerate < 0) + { + ThrowAbortException(X_OTHER, "Cannot set negative framerate"); + } + + + double tic = self->Level->totaltime; + if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !self->Level->isFrozen()) + { + tic += ticFrac; + } + + if(self->modelData->curAnim.startTic >= tic) + { + self->modelData->curAnim.framerate = (float)framerate; + return; + } + + double frame = getCurrentFrame(self->modelData->curAnim, tic); + + self->modelData->curAnim.startFrame = frame; + self->modelData->curAnim.startTic = tic; + self->modelData->curAnim.switchTic = tic; + self->modelData->curAnim.framerate = (float)framerate; +} - int maxModels = mobj->modelData->modelIDs.Size(); - int maxSkins = mobj->modelData->skinIDs.Size(); - int maxSurfaceSkins = mobj->modelData->surfaceSkinIDs.Size(); - int maxAnimations = mobj->modelData->animationIDs.Size(); - int maxGenerators = mobj->modelData->modelFrameGenerators.Size(); +void SetAnimationFrameRateNative(AActor * self, double framerate) +{ + SetAnimationFrameRateInternal(self, framerate, 1); +} - int skinPosition = skinindex + modelindex * MD3_MAX_SURFACES; +void SetAnimationFrameRateUINative(AActor * self, double framerate) +{ + SetAnimationFrameRateInternal(self, framerate, I_GetTimeFrac()); +} + +void SetModelFlag(AActor * self, int flag) +{ + EnsureModelData(self); + self->modelData->flags |= MODELDATA_OVERRIDE_FLAGS; + self->modelData->overrideFlagsSet |= flag; + self->modelData->overrideFlagsClear &= ~flag; +} + +void ClearModelFlag(AActor * self, int flag) +{ + EnsureModelData(self); + self->modelData->flags |= MODELDATA_OVERRIDE_FLAGS; + self->modelData->overrideFlagsClear |= flag; + self->modelData->overrideFlagsSet &= ~flag; +} + +void ResetModelFlags(AActor * self) +{ + if(self->modelData) + { + self->modelData->overrideFlagsClear = 0; + self->modelData->overrideFlagsSet = 0; + self->modelData->flags &= ~MODELDATA_OVERRIDE_FLAGS; + } +} + +enum ChangeModelFlags +{ + CMDL_WEAPONTOPLAYER = 1 << 0, + CMDL_HIDEMODEL = 1 << 1, + CMDL_USESURFACESKIN = 1 << 2, +}; + +void ChangeModelNative( + AActor * self, + AActor * invoker, + FStateParamInfo * stateinfo, + int i_modeldef, + int i_modelindex, + const FString &p_modelpath, + int i_model, + int i_skinindex, + const FString &p_skinpath, + int i_skin, + int flags, + int generatorindex, + int i_animationindex, + const FString &p_animationpath, + int i_animation +) { + if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self"); + + FName n_modeldef { ENamedName(i_modeldef) }; + FName model { ENamedName(i_model) }; + FName skin { ENamedName(i_skin) }; + FName animation { ENamedName(i_animation) }; + + PClass * modeldef = nullptr; + + if (n_modeldef != NAME_None && (modeldef = PClass::FindActor(n_modeldef.GetChars())) == nullptr) + { + Printf("Attempt to pass invalid modeldef name %s in %s.\n", n_modeldef.GetChars(), self->GetCharacterName()); + return; + } + + unsigned modelindex = i_modelindex < 0 ? 0 : i_modelindex; + unsigned skinindex = i_skinindex < 0 ? 0 : i_skinindex; + unsigned animationindex = i_animationindex < 0 ? 0 : i_animationindex; + + AActor* mobj = (ACTION_CALL_FROM_PSPRITE() && (flags & CMDL_WEAPONTOPLAYER)) || ACTION_CALL_FROM_INVENTORY() ? self : invoker; + + FString modelpath = p_modelpath; + FString skinpath = p_skinpath; + FString animationpath = p_animationpath; + + if (modelpath.Len() != 0 && modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/'; + if (skinpath.Len() != 0 && skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/'; + if (animationpath.Len() != 0 && animationpath[(int)animationpath.Len() - 1] != '/') animationpath += '/'; + + EnsureModelData(mobj); int queryModel = !(flags & CMDL_HIDEMODEL) ? model != NAME_None ? FindModel(modelpath.GetChars(), model.GetChars()) : -1 : -2; int queryAnimation = animation != NAME_None ? FindModel(animationpath.GetChars(), animation.GetChars()) : -1; - //[SM] - Let's clear out any potential entries at the specified indices mobj->modelData->modelDef = modeldef; - if(maxModels > modelindex) mobj->modelData->modelIDs.Pop(mobj->modelData->modelIDs[modelindex]); - if(maxAnimations > animationindex) mobj->modelData->animationIDs.Pop(mobj->modelData->animationIDs[animationindex]); - if(maxGenerators > modelindex) mobj->modelData->modelFrameGenerators.Pop(mobj->modelData->modelFrameGenerators[modelindex]); - if (flags & CMDL_USESURFACESKIN) + assert(mobj->modelData->models.Size() == mobj->modelData->modelFrameGenerators.Size()); + + if(mobj->modelData->models.Size() < modelindex) { - if (maxSurfaceSkins > skinPosition) - mobj->modelData->surfaceSkinIDs.Delete(skinPosition); //[SM] - It seems the only way to make sure this does what it's told is from Delete, not Pop + mobj->modelData->models.AppendFill({-1, {}}, modelindex - mobj->modelData->models.Size()); + mobj->modelData->modelFrameGenerators.AppendFill(-1, modelindex - mobj->modelData->modelFrameGenerators.Size()); + } + + if(mobj->modelData->animationIDs.Size() < animationindex) + { + mobj->modelData->animationIDs.AppendFill(-1, animationindex - mobj->modelData->animationIDs.Size()); + } + + auto skindata = skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID(); + + if(mobj->modelData->models.Size() == modelindex) + { + + if(flags & CMDL_USESURFACESKIN && skinindex >= 0) + { + TArray surfaceSkins; + if(skinindex > 0) + { + surfaceSkins.AppendFill(FNullTextureID(), skinindex); + } + surfaceSkins.Push(skindata); + mobj->modelData->models.Push({queryModel, std::move(surfaceSkins)}); + mobj->modelData->modelFrameGenerators.Push(generatorindex); + } + else + { + mobj->modelData->models.Push({queryModel, {}}); + mobj->modelData->modelFrameGenerators.Push(generatorindex); + } } else { - if (maxSkins > skinindex) - mobj->modelData->skinIDs.Pop(mobj->modelData->skinIDs[skinindex]); + if(flags & CMDL_USESURFACESKIN && skinindex >= 0) + { + if(skinindex > mobj->modelData->models[modelindex].surfaceSkinIDs.Size()) + { + mobj->modelData->models[modelindex].surfaceSkinIDs.AppendFill(FNullTextureID(), skinindex - mobj->modelData->models[modelindex].surfaceSkinIDs.Size()); + } + + if(skinindex == mobj->modelData->models[modelindex].surfaceSkinIDs.Size()) + { + mobj->modelData->models[modelindex].surfaceSkinIDs.Push(skindata); + } + else + { + mobj->modelData->models[modelindex].surfaceSkinIDs[skinindex] = skindata; + } + } + if(queryModel != -1) mobj->modelData->models[modelindex].modelID = queryModel; + if(generatorindex != -1) mobj->modelData->modelFrameGenerators[modelindex] = generatorindex; } - //[SM] - We need to fill up any holes this new index will make so that it doesn't leave behind any undefined behavior - while ((int)mobj->modelData->modelIDs.Size() < modelindex) mobj->modelData->modelIDs.Push(-1); - while ((int)mobj->modelData->modelFrameGenerators.Size() < modelindex) mobj->modelData->modelFrameGenerators.Push(-1); - while ((int)mobj->modelData->animationIDs.Size() < modelindex) mobj->modelData->animationIDs.Push(-1); - if (flags & CMDL_USESURFACESKIN) - while ((int)mobj->modelData->surfaceSkinIDs.Size() < skinPosition) mobj->modelData->surfaceSkinIDs.Push(FNullTextureID()); + if(mobj->modelData->animationIDs.Size() == animationindex) + { + mobj->modelData->animationIDs.Push(queryAnimation); + } else - while ((int)mobj->modelData->skinIDs.Size() < skinindex) mobj->modelData->skinIDs.Push(FNullTextureID()); + { + mobj->modelData->animationIDs[animationindex] = queryAnimation; + } + + if (!(flags & CMDL_USESURFACESKIN)) + { + if(mobj->modelData->skinIDs.Size() < skinindex) + { + mobj->modelData->skinIDs.AppendFill(FNullTextureID(), skinindex - mobj->modelData->skinIDs.Size()); + } + + if(mobj->modelData->skinIDs.Size() == skinindex) + { + mobj->modelData->skinIDs.Push(skindata); + } + else + { + mobj->modelData->skinIDs[skinindex] = skindata; + } + } + + CleanupModelData(mobj); + + return; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_ChangeModel, ChangeModelNative) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_NAME(modeldef); + PARAM_INT(modelindex); + PARAM_STRING_VAL(modelpath); + PARAM_NAME(model); + PARAM_INT(skinindex); + PARAM_STRING_VAL(skinpath); + PARAM_NAME(skin); + PARAM_INT(flags); + PARAM_INT(generatorindex); + PARAM_INT(animationindex); + PARAM_STRING_VAL(animationpath); + PARAM_NAME(animation); - mobj->modelData->modelIDs.Insert(modelindex, queryModel); - mobj->modelData->modelFrameGenerators.Insert(modelindex, generatorindex); - mobj->modelData->animationIDs.Insert(animationindex, queryAnimation); - if (flags & CMDL_USESURFACESKIN) - mobj->modelData->surfaceSkinIDs.Insert(skinPosition, skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID()); - else - mobj->modelData->skinIDs.Insert(skinindex, skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID()); - - //[SM] - We need to serialize file paths and model names so that they are pushed on loading save files. Likewise, let's not include models that were already parsed when initialized. - if (queryModel >= 0) - { - FString fullName; - fullName.Format("%s%s", modelpath.GetChars(), model.GetChars()); - bool allowPush = true; - for (unsigned i = 0; i < savedModelFiles.Size(); i++) if (!savedModelFiles[i].CompareNoCase(fullName)) allowPush = false; - for (unsigned i = 0; i < Models.Size()-1; i++) if (!Models[i]->mFileName.CompareNoCase(fullName)) allowPush = false; - - if(allowPush) savedModelFiles.Push(fullName); - } - //Same for animations - if (queryAnimation >= 0) - { - FString fullName; - fullName.Format("%s%s", animationpath.GetChars(), animation.GetChars()); - bool allowPush = true; - for (unsigned i = 0; i < savedModelFiles.Size(); i++) if (!savedModelFiles[i].CompareNoCase(fullName)) allowPush = false; - for (unsigned i = 0; i < Models.Size() - 1; i++) if (!Models[i]->mFileName.CompareNoCase(fullName)) allowPush = false; - - if (allowPush) savedModelFiles.Push(fullName); - } - - //[SM] - if an indice of modelIDs or skinIDs comes up blank and it's the last one, just delete it. For using very large amounts of indices, common sense says to just not run this repeatedly. - while (mobj->modelData->modelIDs.Size() > 0 && mobj->modelData->modelIDs.Last() == -1) - mobj->modelData->modelIDs.Pop(mobj->modelData->modelIDs.Last()); - while (mobj->modelData->modelFrameGenerators.Size() > 0 && mobj->modelData->modelFrameGenerators.Last() == -1) - mobj->modelData->modelFrameGenerators.Pop(mobj->modelData->modelFrameGenerators.Last()); - while (mobj->modelData->skinIDs.Size() > 0 && mobj->modelData->skinIDs.Last() == FNullTextureID()) - mobj->modelData->skinIDs.Pop(mobj->modelData->skinIDs.Last()); - while (mobj->modelData->surfaceSkinIDs.Size() > 0 && mobj->modelData->surfaceSkinIDs.Last() == FNullTextureID()) - mobj->modelData->surfaceSkinIDs.Pop(mobj->modelData->surfaceSkinIDs.Last()); - while (mobj->modelData->animationIDs.Size() > 0 && mobj->modelData->animationIDs.Last() == -1) - mobj->modelData->animationIDs.Pop(mobj->modelData->animationIDs.Last()); + ChangeModelNative(self,stateowner,stateinfo,modeldef.GetIndex(),modelindex,modelpath,model.GetIndex(),skinindex,skinpath,skin.GetIndex(),flags,generatorindex,animationindex,animationpath,animation.GetIndex()); + + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetAnimation, SetAnimationNative) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_NAME(animName); + PARAM_FLOAT(framerate); + PARAM_INT(startFrame); + PARAM_INT(loopFrame); + PARAM_INT(endFrame); + PARAM_INT(interpolateTics); + PARAM_INT(flags); - if (mobj->modelData->modelIDs.Size() == 0 && mobj->modelData->modelFrameGenerators.Size() == 0 && mobj->modelData->skinIDs.Size() == 0 && mobj->modelData->surfaceSkinIDs.Size() == 0 && mobj->modelData->animationIDs.Size() == 0 && modeldef == NAME_None) - { - mobj->hasmodel = mobj->modelData->hasModel; - mobj->modelData->modelIDs.Reset(); - mobj->modelData->modelFrameGenerators.Reset(); - mobj->modelData->skinIDs.Reset(); - mobj->modelData->surfaceSkinIDs.Reset(); - mobj->modelData->animationIDs.Reset(); - mobj->modelData->Destroy(); - } + SetAnimationInternal(self, animName, framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, 1); + + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetAnimationUI, SetAnimationUINative) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_NAME(animName); + PARAM_FLOAT(framerate); + PARAM_INT(startFrame); + PARAM_INT(loopFrame); + PARAM_INT(endFrame); + PARAM_INT(interpolateTics); + PARAM_INT(flags); + + SetAnimationInternal(self, animName, framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, I_GetTimeFrac()); + + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetAnimationFrameRate, SetAnimationFrameRateNative) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_FLOAT(framerate); + + SetAnimationFrameRateInternal(self, framerate, 1); + + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetAnimationFrameRateUI, SetAnimationFrameRateUINative) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_FLOAT(framerate); + + SetAnimationFrameRateInternal(self, framerate, I_GetTimeFrac()); + + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetModelFlag, SetModelFlag) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT(flag); + + SetModelFlag(self, flag); + + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearModelFlag, ClearModelFlag) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT(flag); + + ClearModelFlag(self, flag); + + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, ResetModelFlags, ResetModelFlags) +{ + PARAM_ACTION_PROLOGUE(AActor); + + ResetModelFlags(self); return 0; } diff --git a/src/playsim/p_destructible.cpp b/src/playsim/p_destructible.cpp index 126ddbd422..8e8b94f18b 100644 --- a/src/playsim/p_destructible.cpp +++ b/src/playsim/p_destructible.cpp @@ -448,11 +448,11 @@ static void PGRA_InsertIfCloser(TMap& damageGroupPos, int grou EXTERN_CVAR(Float, splashfactor); -void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, int bombdistance, FName damagetype, int fulldamagedistance) +void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, double bombdistance, FName damagetype, double fulldamagedistance) { TMap damageGroupPos; - double bombdistancefloat = 1. / (double)(bombdistance - fulldamagedistance); + double bombdistancefloat = 1.0 / (bombdistance - fulldamagedistance); // now, this is not entirely correct... but sector actions still _do_ require a valid source actor to trigger anything if (!bombspot) @@ -588,8 +588,8 @@ void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage int damage = 0; if (dst < bombdistance) { - dst = clamp(dst - (double)fulldamagedistance, 0, dst); - damage = (int)((double)bombdamage * (1. - dst * bombdistancefloat)); + dst = clamp(dst - fulldamagedistance, 0.0, dst); + damage = (int)((double)bombdamage * (1.0 - dst * bombdistancefloat)); if (bombsource == bombspot) damage = (int)(damage * splashfactor); } @@ -661,8 +661,8 @@ void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage int damage = 0; if (dst < bombdistance) { - dst = clamp(dst - (double)fulldamagedistance, 0, dst); - damage = (int)((double)bombdamage * (1. - dst * bombdistancefloat)); + dst = clamp(dst - fulldamagedistance, 0.0, dst); + damage = (int)((double)bombdamage * (1.0 - dst * bombdistancefloat)); if (bombsource == bombspot) damage = (int)(damage * splashfactor); } @@ -716,7 +716,7 @@ bool P_ProjectileHitLinedef(AActor* mo, line_t* line) } } - int wside = P_PointOnLineSide(mo->Pos(), line); + int wside = P_PointOnLineSide(mo->Pos().XY(), line); int oside = !wside; side_t* otherside = line->sidedef[oside]; // check if hit upper or lower part @@ -950,9 +950,9 @@ DEFINE_ACTION_FUNCTION(FDestructible, GeometryRadiusAttack) PARAM_OBJECT(bombspot, AActor); PARAM_OBJECT(bombsource, AActor); PARAM_INT(bombdamage); - PARAM_INT(bombdistance); + PARAM_FLOAT(bombdistance); PARAM_NAME(damagetype); - PARAM_INT(fulldamagedistance); + PARAM_FLOAT(fulldamagedistance); P_GeometryRadiusAttack(bombspot, bombsource, bombdamage, bombdistance, damagetype, fulldamagedistance); return 0; } diff --git a/src/playsim/p_destructible.h b/src/playsim/p_destructible.h index 24a95b6a48..c4e6e9d230 100644 --- a/src/playsim/p_destructible.h +++ b/src/playsim/p_destructible.h @@ -34,7 +34,7 @@ void P_DamageSector(sector_t* sector, AActor* source, int damage, FName damagety void P_DamageLinedef(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius, bool dogroups); void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName damageType); -void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, int bombdistance, FName damagetype, int fulldamagedistance); +void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, double bombdistance, FName damagetype, double fulldamagedistance); bool P_ProjectileHitLinedef(AActor* projectile, line_t* line); bool P_ProjectileHitPlane(AActor* projectile, int part); diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index a7588d1ba6..5ee7e9f3c9 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -49,6 +49,13 @@ #include "vm.h" #include "actorinlines.h" #include "g_game.h" +#include "serializer_doom.h" + +#include "hwrenderer/scene/hw_drawstructs.h" + +#ifdef _MSC_VER +#pragma warning(disable: 6011) // dereference null pointer in thinker iterator +#endif CVAR (Int, cl_rockettrails, 1, CVAR_ARCHIVE); CVAR (Bool, r_rail_smartspiral, false, CVAR_ARCHIVE); @@ -202,9 +209,26 @@ void P_ClearParticles (FLevelLocals *Level) // Group particles by subsectors. Because particles are always // in motion, there is little benefit to caching this information // from one frame to the next. +// [MC] VisualThinkers hitches a ride here void P_FindParticleSubsectors (FLevelLocals *Level) { + // [MC] Hitch a ride on particle subsectors since VisualThinkers are effectively using the same kind of system. + for (uint32_t i = 0; i < Level->subsectors.Size(); i++) + { + Level->subsectors[i].sprites.Clear(); + } + // [MC] Not too happy about using an iterator for this but I can't think of another way to handle it. + // At least it's on its own statnum for maximum efficiency. + auto it = Level->GetThinkerIterator(NAME_None, STAT_VISUALTHINKER); + DVisualThinker* sp; + while (sp = it.Next()) + { + if (!sp->PT.subsector) sp->PT.subsector = Level->PointInRenderSubsector(sp->PT.Pos); + + sp->PT.subsector->sprites.Push(sp); + } + // End VisualThinker hitching. Now onto the particles. if (Level->ParticlesInSubsec.Size() < Level->subsectors.Size()) { Level->ParticlesInSubsec.Reserve (Level->subsectors.Size() - Level->ParticlesInSubsec.Size()); @@ -271,16 +295,20 @@ void P_ThinkParticles (FLevelLocals *Level) { particle = &Level->Particles[i]; i = particle->tnext; - if (Level->isFrozen() && !(particle->flags &PT_NOTIMEFREEZE)) + if (Level->isFrozen() && !(particle->flags &SPF_NOTIMEFREEZE)) { + if(particle->flags & SPF_LOCAL_ANIM) + { + particle->animData.SwitchTic++; + } + prev = particle; continue; } - auto oldtrans = particle->alpha; particle->alpha -= particle->fadestep; particle->size += particle->sizestep; - if (particle->alpha <= 0 || oldtrans < particle->alpha || --particle->ttl <= 0 || (particle->size <= 0)) + if (particle->alpha <= 0 || --particle->ttl <= 0 || (particle->size <= 0)) { // The particle has expired, so free it *particle = {}; if (prev) @@ -305,7 +333,7 @@ void P_ThinkParticles (FLevelLocals *Level) particle->Pos.Z += particle->Vel.Z; particle->Vel += particle->Acc; - if(particle->flags & PT_DOROLL) + if(particle->flags & SPF_ROLL) { particle->Roll += particle->RollVel; particle->RollVel += particle->RollAcc; @@ -334,31 +362,21 @@ void P_ThinkParticles (FLevelLocals *Level) } } -enum PSFlag -{ - PS_FULLBRIGHT = 1, - PS_NOTIMEFREEZE = 1 << 5, - PS_ROLL = 1 << 6, - PS_REPLACE = 1 << 7, - PS_NO_XY_BILLBOARD = 1 << 8, -}; - void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, double fadestep, double sizestep, int flags, FTextureID texture, ERenderStyle style, double startroll, double rollvel, double rollacc) { - particle_t *particle = NewParticle(Level, !!(flags & PS_REPLACE)); + particle_t *particle = NewParticle(Level, !!(flags & SPF_REPLACE)); if (particle) { particle->Pos = pos; - particle->Vel = vel; - particle->Acc = accel; + particle->Vel = FVector3(vel); + particle->Acc = FVector3(accel); particle->color = ParticleColor(color); particle->alpha = float(startalpha); - if (fadestep < 0) particle->fadestep = FADEFROMTTL(lifetime); + if (fadestep <= -1.0) particle->fadestep = FADEFROMTTL(lifetime); else particle->fadestep = float(fadestep); particle->ttl = lifetime; - particle->bright = !!(flags & PS_FULLBRIGHT); particle->size = size; particle->sizestep = sizestep; particle->texture = texture; @@ -366,17 +384,10 @@ void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &v particle->Roll = startroll; particle->RollVel = rollvel; particle->RollAcc = rollacc; - if(flags & PS_NOTIMEFREEZE) - { - particle->flags |= PT_NOTIMEFREEZE; - } - if(flags & PS_ROLL) - { - particle->flags |= PT_DOROLL; - } - if(flags & PS_NO_XY_BILLBOARD) + particle->flags = flags; + if(flags & SPF_LOCAL_ANIM) { - particle->flags |= PT_NOXYBILLBOARD; + TexAnim.InitStandaloneAnimation(particle->animData, texture, Level->maptime); } } } @@ -428,10 +439,10 @@ static void MakeFountain (AActor *actor, int color1, int color2) particle->Pos = actor->Vec3Angle(out, an, actor->Height + 1); if (out < actor->radius/8) - particle->Vel.Z += 10./3; + particle->Vel.Z += 10.f/3; else particle->Vel.Z += 3; - particle->Acc.Z -= 1./11; + particle->Acc.Z -= 1.f/11; if (M_Random() < 30) { particle->size = 4; particle->color = color2; @@ -470,8 +481,8 @@ void P_RunEffect (AActor *actor, int effects) speed = (M_Random () - 128) * (1./200); particle->Vel.X += speed * an.Cos(); particle->Vel.Y += speed * an.Sin(); - particle->Vel.Z -= 1./36; - particle->Acc.Z -= 1./20; + particle->Vel.Z -= 1.f/36; + particle->Acc.Z -= 1.f/20; particle->color = yellow; particle->size = 2; } @@ -488,8 +499,8 @@ void P_RunEffect (AActor *actor, int effects) speed = (M_Random () - 128) * (1./200); particle->Vel.X += speed * an.Cos(); particle->Vel.Y += speed * an.Sin(); - particle->Vel.Z += 1. / 80; - particle->Acc.Z += 1. / 40; + particle->Vel.Z += 1.f / 80; + particle->Acc.Z += 1.f / 40; if (M_Random () & 7) particle->color = grey2; else @@ -631,7 +642,7 @@ void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle p->size = 4; p->color = M_Random() & 0x80 ? color1 : color2; p->Vel.Z = M_Random() * zvel; - p->Acc.Z = -1 / 22.; + p->Acc.Z = -1 / 22.f; if (kind) { an = angle + DAngle::fromDeg((M_Random() - 128) * (180 / 256.)); @@ -703,7 +714,7 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, AActor *mo = player->camera; double r = ((seg.start.Y - mo->Y()) * (-seg.dir.Y) - (seg.start.X - mo->X()) * (seg.dir.X)) / (seg.length * seg.length); r = clamp(r, 0., 1.); - seg.soundpos = seg.start + r * seg.dir; + seg.soundpos = seg.start.XY() + r * seg.dir.XY(); seg.sounddist = (seg.soundpos - mo->Pos()).LengthSquared(); } else @@ -784,10 +795,13 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, p->ttl = spiralduration; p->fadestep = FADEFROMTTL(spiralduration); p->size = 3; - p->bright = fullbright; + if(fullbright) + { + p->flags |= SPF_FULLBRIGHT; + } tempvec = DMatrix3x3(trail[segment].dir, deg) * trail[segment].extend; - p->Vel = tempvec * drift / 16.; + p->Vel = FVector3(tempvec * drift / 16.); p->Pos = tempvec + pos; pos += trail[segment].dir * stepsize; deg += DAngle::fromDeg(r_rail_spiralsparsity * 14); @@ -867,7 +881,10 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, p->Acc.Z -= 1./4096; pos += trail[segment].dir * stepsize; lencount -= stepsize; - p->bright = fullbright; + if(fullbright) + { + p->flags |= SPF_FULLBRIGHT; + } if (color2 == -1) { @@ -979,3 +996,307 @@ void P_DisconnectEffect (AActor *actor) p->size = 4; } } + +//=========================================================================== +// +// ZScript Sprite (DVisualThinker) +// Concept by Major Cooke +// Most code borrowed by Actor and particles above +// +//=========================================================================== + +void DVisualThinker::Construct() +{ + PT = {}; + PT.Pos = { 0,0,0 }; + PT.Vel = { 0,0,0 }; + Offset = { 0,0 }; + Scale = { 1,1 }; + PT.Roll = 0.0; + PT.alpha = 1.0; + LightLevel = -1; + PT.texture = FTextureID(); + PT.style = STYLE_Normal; + PT.flags = 0; + Translation = NO_TRANSLATION; + PT.subsector = nullptr; + cursector = nullptr; + PT.color = 0xffffff; + spr = new HWSprite(); + AnimatedTexture.SetNull(); +} + +DVisualThinker::DVisualThinker() +{ + Construct(); +} + +void DVisualThinker::OnDestroy() +{ + PT.alpha = 0.0; // stops all rendering. + if(spr) + { + delete spr; + spr = nullptr; + } + Super::OnDestroy(); +} + +DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* type) +{ + if (type == nullptr) + return nullptr; + else if (type->bAbstract) + { + Printf("Attempt to spawn an instance of abstract VisualThinker class %s\n", type->TypeName.GetChars()); + return nullptr; + } + else if (!type->IsDescendantOf(RUNTIME_CLASS(DVisualThinker))) + { + Printf("Attempt to spawn class not inherent to VisualThinker: %s\n", type->TypeName.GetChars()); + return nullptr; + } + + DVisualThinker *zs = static_cast(Level->CreateThinker(type, STAT_VISUALTHINKER)); + zs->Construct(); + return zs; +} + +static DVisualThinker* SpawnVisualThinker(FLevelLocals* Level, PClass* type) +{ + return DVisualThinker::NewVisualThinker(Level, type); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, SpawnVisualThinker, SpawnVisualThinker) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_CLASS_NOT_NULL(type, DVisualThinker); + DVisualThinker* zs = SpawnVisualThinker(self, type); + ACTION_RETURN_OBJECT(zs); +} + +void DVisualThinker::UpdateSpriteInfo() +{ + PT.style = ERenderStyle(GetRenderStyle()); + if((PT.flags & SPF_LOCAL_ANIM) && PT.texture != AnimatedTexture) + { + AnimatedTexture = PT.texture; + TexAnim.InitStandaloneAnimation(PT.animData, PT.texture, Level->maptime); + } +} + +// This runs just like Actor's, make sure to call Super.Tick() in ZScript. +void DVisualThinker::Tick() +{ + if (ObjectFlags & OF_EuthanizeMe) + return; + + // There won't be a standard particle for this, it's only for graphics. + if (!PT.texture.isValid()) + { + Printf("No valid texture, destroyed"); + Destroy(); + return; + } + + if (isFrozen()) + { // needed here because it won't retroactively update like actors do. + PT.subsector = Level->PointInRenderSubsector(PT.Pos); + cursector = PT.subsector->sector; + UpdateSpriteInfo(); + return; + } + Prev = PT.Pos; + PrevRoll = PT.Roll; + // Handle crossing a line portal + DVector2 newxy = Level->GetPortalOffsetPosition(PT.Pos.X, PT.Pos.Y, PT.Vel.X, PT.Vel.Y); + PT.Pos.X = newxy.X; + PT.Pos.Y = newxy.Y; + PT.Pos.Z += PT.Vel.Z; + + PT.subsector = Level->PointInRenderSubsector(PT.Pos); + cursector = PT.subsector->sector; + // Handle crossing a sector portal. + if (!cursector->PortalBlocksMovement(sector_t::ceiling)) + { + if (PT.Pos.Z > cursector->GetPortalPlaneZ(sector_t::ceiling)) + { + PT.Pos += cursector->GetPortalDisplacement(sector_t::ceiling); + PT.subsector = Level->PointInRenderSubsector(PT.Pos); + cursector = PT.subsector->sector; + } + } + else if (!cursector->PortalBlocksMovement(sector_t::floor)) + { + if (PT.Pos.Z < cursector->GetPortalPlaneZ(sector_t::floor)) + { + PT.Pos += cursector->GetPortalDisplacement(sector_t::floor); + PT.subsector = Level->PointInRenderSubsector(PT.Pos); + cursector = PT.subsector->sector; + } + } + UpdateSpriteInfo(); +} + +int DVisualThinker::GetLightLevel(sector_t* rendersector) const +{ + int lightlevel = rendersector->GetSpriteLight(); + + if (bAddLightLevel) + { + lightlevel += LightLevel; + } + else if (LightLevel > -1) + { + lightlevel = LightLevel; + } + return lightlevel; +} + +FVector3 DVisualThinker::InterpolatedPosition(double ticFrac) const +{ + if (bDontInterpolate) return FVector3(PT.Pos); + + DVector3 proc = Prev + (ticFrac * (PT.Pos - Prev)); + return FVector3(proc); + +} + +float DVisualThinker::InterpolatedRoll(double ticFrac) const +{ + if (bDontInterpolate) return PT.Roll; + + return float(PrevRoll + (PT.Roll - PrevRoll) * ticFrac); +} + + + +void DVisualThinker::SetTranslation(FName trname) +{ + // There is no constant for the empty name... + if (trname.GetChars()[0] == 0) + { + // '' removes it + Translation = NO_TRANSLATION; + return; + } + + auto tnum = R_FindCustomTranslation(trname); + if (tnum != INVALID_TRANSLATION) + { + Translation = tnum; + } + // silently ignore if the name does not exist, this would create some insane message spam otherwise. +} + +void SetTranslation(DVisualThinker * self, int i_trans) +{ + FName trans {ENamedName(i_trans)}; + self->SetTranslation(trans); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, SetTranslation, SetTranslation) +{ + PARAM_SELF_PROLOGUE(DVisualThinker); + PARAM_NAME(trans); + self->SetTranslation(trans); + return 0; +} + +static int IsFrozen(DVisualThinker * self) +{ + return !!(self->Level->isFrozen() && !(self->PT.flags & SPF_NOTIMEFREEZE)); +} + +bool DVisualThinker::isFrozen() +{ + return IsFrozen(this); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, IsFrozen, IsFrozen) +{ + PARAM_SELF_PROLOGUE(DVisualThinker); + ACTION_RETURN_BOOL(self->isFrozen()); +} + +static void SetRenderStyle(DVisualThinker *self, int mode) +{ + if(mode >= 0 && mode < STYLE_Count) + { + self->PT.style = ERenderStyle(mode); + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, SetRenderStyle, SetRenderStyle) +{ + PARAM_SELF_PROLOGUE(DVisualThinker); + PARAM_INT(mode); + + self->PT.style = ERenderStyle(mode); + return 0; +} + +int DVisualThinker::GetRenderStyle() +{ + return PT.style; +} + +float DVisualThinker::GetOffset(bool y) const // Needed for the renderer. +{ + if (y) + return (float)(bFlipOffsetY ? Offset.Y : -Offset.Y); + else + return (float)(bFlipOffsetX ? Offset.X : -Offset.X); +} + +void DVisualThinker::Serialize(FSerializer& arc) +{ + Super::Serialize(arc); + + arc + ("pos", PT.Pos) + ("vel", PT.Vel) + ("prev", Prev) + ("scale", Scale) + ("roll", PT.Roll) + ("prevroll", PrevRoll) + ("offset", Offset) + ("alpha", PT.alpha) + ("texture", PT.texture) + ("style", *reinterpret_cast(&PT.style)) + ("translation", Translation) + ("cursector", cursector) + ("scolor", PT.color) + ("flipx", bXFlip) + ("flipy", bYFlip) + ("dontinterpolate", bDontInterpolate) + ("addlightlevel", bAddLightLevel) + ("flipoffsetx", bFlipOffsetX) + ("flipoffsetY", bFlipOffsetY) + ("lightlevel", LightLevel) + ("flags", PT.flags); + +} + +IMPLEMENT_CLASS(DVisualThinker, false, false); +DEFINE_FIELD_NAMED(DVisualThinker, PT.color, SColor); +DEFINE_FIELD_NAMED(DVisualThinker, PT.Pos, Pos); +DEFINE_FIELD_NAMED(DVisualThinker, PT.Vel, Vel); +DEFINE_FIELD_NAMED(DVisualThinker, PT.Roll, Roll); +DEFINE_FIELD_NAMED(DVisualThinker, PT.alpha, Alpha); +DEFINE_FIELD_NAMED(DVisualThinker, PT.texture, Texture); +DEFINE_FIELD_NAMED(DVisualThinker, PT.flags, Flags); + +DEFINE_FIELD(DVisualThinker, Prev); +DEFINE_FIELD(DVisualThinker, Scale); +DEFINE_FIELD(DVisualThinker, Offset); +DEFINE_FIELD(DVisualThinker, PrevRoll); +DEFINE_FIELD(DVisualThinker, Translation); +DEFINE_FIELD(DVisualThinker, LightLevel); +DEFINE_FIELD(DVisualThinker, cursector); +DEFINE_FIELD(DVisualThinker, bXFlip); +DEFINE_FIELD(DVisualThinker, bYFlip); +DEFINE_FIELD(DVisualThinker, bDontInterpolate); +DEFINE_FIELD(DVisualThinker, bAddLightLevel); +DEFINE_FIELD(DVisualThinker, bFlipOffsetX); +DEFINE_FIELD(DVisualThinker, bFlipOffsetY); diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 3b542c19ec..0f439785cd 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -36,6 +36,9 @@ #include "vectors.h" #include "doomdef.h" #include "renderstyle.h" +#include "dthinker.h" +#include "palettecontainer.h" +#include "animations.h" enum { @@ -52,29 +55,40 @@ struct FLevelLocals; enum EParticleFlags { - PT_NOTIMEFREEZE = 1, - PT_DOROLL = 1 << 1, - PT_NOXYBILLBOARD = 1 << 2, + SPF_FULLBRIGHT = 1 << 0, + SPF_RELPOS = 1 << 1, + SPF_RELVEL = 1 << 2, + SPF_RELACCEL = 1 << 3, + SPF_RELANG = 1 << 4, + SPF_NOTIMEFREEZE = 1 << 5, + SPF_ROLL = 1 << 6, + SPF_REPLACE = 1 << 7, + SPF_NO_XY_BILLBOARD = 1 << 8, + SPF_LOCAL_ANIM = 1 << 9, }; +class DVisualThinker; struct particle_t { - DVector3 Pos; - DVector3 Vel; - DVector3 Acc; - double size, sizestep; - float fadestep, alpha; - subsector_t* subsector; - int32_t ttl; - int color; - FTextureID texture; - ERenderStyle style; - double Roll, RollVel, RollAcc; - uint16_t tnext, snext, tprev; - uint8_t bright; - uint8_t flags; + subsector_t* subsector; //+8 = 8 + DVector3 Pos; //+24 = 32 + FVector3 Vel; //+12 = 44 + FVector3 Acc; //+12 = 56 + float size, sizestep; //+8 = 64 + float fadestep, alpha; //+8 = 72 + int32_t ttl; // +4 = 76 + int color; //+4 = 80 + FTextureID texture; // +4 = 84 + ERenderStyle style; //+4 = 88 + float Roll, RollVel, RollAcc; //+12 = 100 + uint16_t tnext, snext, tprev; //+6 = 106 + uint16_t flags; //+2 = 108 + // uint32_t padding; //+4 = 112 + FStandaloneAnimation animData; //+16 = 128 }; +static_assert(sizeof(particle_t) == 128); + const uint16_t NO_PARTICLE = 0xffff; void P_InitParticles(FLevelLocals *); @@ -130,3 +144,54 @@ void P_DrawSplash (FLevelLocals *Level, int count, const DVector3 &pos, DAngle a void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int updown, int kind); void P_DisconnectEffect (AActor *actor); +//=========================================================================== +// +// VisualThinkers +// by Major Cooke +// Credit to phantombeta, RicardoLuis0 & RaveYard for aid +// +//=========================================================================== +class HWSprite; +struct FTranslationID; +class DVisualThinker : public DThinker +{ + DECLARE_CLASS(DVisualThinker, DThinker); +public: + DVector3 Prev; + DVector2 Scale, + Offset; + float PrevRoll; + int16_t LightLevel; + FTranslationID Translation; + FTextureID AnimatedTexture; + sector_t *cursector; + + bool bFlipOffsetX, + bFlipOffsetY, + bXFlip, + bYFlip, // flip the sprite on the x/y axis. + bDontInterpolate, // disable all interpolation + bAddLightLevel; // adds sector light level to 'LightLevel' + + // internal only variables + particle_t PT; + HWSprite *spr; //in an effort to cache the result. + + DVisualThinker(); + void Construct(); + void OnDestroy() override; + + static DVisualThinker* NewVisualThinker(FLevelLocals* Level, PClass* type); + void SetTranslation(FName trname); + int GetRenderStyle(); + bool isFrozen(); + int GetLightLevel(sector_t *rendersector) const; + FVector3 InterpolatedPosition(double ticFrac) const; + float InterpolatedRoll(double ticFrac) const; + + void Tick() override; + void UpdateSpriteInfo(); + void Serialize(FSerializer& arc) override; + + float GetOffset(bool y) const; +}; \ No newline at end of file diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 89ac8e2104..50ed1a74d8 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -50,6 +50,7 @@ #include "vm.h" #include "actorinlines.h" #include "a_ceiling.h" +#include "shadowinlines.h" #include "gi.h" @@ -61,8 +62,8 @@ static FRandom pr_lookformonsters ("LookForMonsters"); static FRandom pr_lookforplayers ("LookForPlayers"); static FRandom pr_scaredycat ("Anubis"); FRandom pr_chase ("Chase"); -static FRandom pr_facetarget ("FaceTarget"); -static FRandom pr_railface ("RailFace"); + FRandom pr_facetarget ("FaceTarget"); + FRandom pr_railface ("RailFace"); static FRandom pr_look2 ("LookyLooky"); static FRandom pr_look3 ("IGotHooky"); static FRandom pr_slook ("SlooK"); @@ -603,7 +604,7 @@ static int P_Move (AActor *actor) move = move.Rotated(anglediff); oldangle = actor->Angles.Yaw; } - start = actor->Pos() - move * i / steps; + start = actor->Pos().XY() - move * i / steps; } } @@ -627,9 +628,14 @@ static int P_Move (AActor *actor) // actually walking down a step. if (try_ok && !((actor->flags & MF_NOGRAVITY) || CanJump(actor)) - && actor->Z() > actor->floorz && !(actor->flags2 & MF2_ONMOBJ)) + && !(actor->flags2 & MF2_ONMOBJ)) + { - if (actor->Z() <= actor->floorz + actor->MaxStepHeight) + // account for imprecisions with slopes. A walking actor should never be below its own floorz. + if (actor->Z() < actor->floorz) + actor->SetZ(actor->floorz); + + else if (actor->Z() <= actor->floorz + actor->MaxStepHeight) { double savedz = actor->Z(); actor->SetZ(actor->floorz); @@ -754,6 +760,10 @@ int P_SmartMove(AActor* actor) ) actor->movedir = DI_NODIR; // avoid the area (most of the time anyway) + if (actor->flags2 & MF2_FLOORCLIP) + { + actor->AdjustFloorClip(); + } return true; } @@ -1261,7 +1271,7 @@ int P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams { maxdist = params->maxDist; mindist = params->minDist; - fov = params->Fov; + fov = allaround ? DAngle::fromDeg(0.) : params->Fov; // [RK] Account for LOOKALLAROUND flag. } else { @@ -2076,7 +2086,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LookEx) { // If we find a valid target here, the wandering logic should *not* // be activated! If would cause the seestate to be set twice. - if (P_LookForPlayers(self, true, ¶ms)) + if (P_LookForPlayers(self, (self->flags4 & MF4_LOOKALLAROUND), ¶ms)) // [RK] Passing true for allround should only occur if the flag is actually set. goto seeyou; } @@ -2206,6 +2216,7 @@ enum ChaseFlags CHF_NOPOSTATTACKTURN = 128, CHF_STOPIFBLOCKED = 256, CHF_DONTIDLE = 512, + CHF_DONTLOOKALLAROUND = 1024, }; void A_Wander(AActor *self, int flags) @@ -2432,7 +2443,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi } if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { // look for a new target - if (actor->target != NULL && (actor->target->flags2 & MF2_NONSHOOTABLE)) + if (actor->target != nullptr && (actor->target->flags2 & MF2_NONSHOOTABLE)) { // Target is only temporarily unshootable, so remember it. actor->lastenemy = actor->target; @@ -2440,17 +2451,17 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi // hurt our old one temporarily. actor->threshold = 0; } - if (P_LookForPlayers (actor, true, NULL) && actor->target != actor->goal) + if (P_LookForPlayers (actor, !(flags & CHF_DONTLOOKALLAROUND), nullptr) && actor->target != actor->goal) { // got a new target actor->flags7 &= ~MF7_INCHASE; return; } - if (actor->target == NULL) + if (actor->target == nullptr) { if (flags & CHF_DONTIDLE || actor->flags & MF_FRIENDLY) { //A_Look(actor); - if (actor->target == NULL) + if (actor->target == nullptr) { if (!dontmove) A_Wander(actor); actor->flags7 &= ~MF7_INCHASE; @@ -2562,11 +2573,10 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi } } } - } // [RH] Scared monsters attack less frequently - if (((actor->target->player == NULL || + if (((actor->target->player == nullptr || !((actor->target->player->cheats & CF_FRIGHTENING) || (actor->target->flags8 & MF8_FRIGHTENING))) && !(actor->flags4 & MF4_FRIGHTENED)) || pr_scaredycat() < 43) @@ -2615,7 +2625,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi lookForBetter = true; } AActor * oldtarget = actor->target; - gotNew = P_LookForPlayers (actor, true, NULL); + gotNew = P_LookForPlayers (actor, !(flags & CHF_DONTLOOKALLAROUND), nullptr); if (lookForBetter) { actor->flags3 |= MF3_NOSIGHTCHECK; @@ -2638,7 +2648,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi if ((!fastchase || !actor->FastChaseStrafeCount) && !dontmove) { // CANTLEAVEFLOORPIC handling was completely missing in the non-serpent functions. - DVector2 old = actor->Pos(); + DVector2 old = actor->Pos().XY(); int oldgroup = actor->PrevPortalGroup; FTextureID oldFloor = actor->floorpic; @@ -2800,7 +2810,7 @@ bool P_CheckForResurrection(AActor* self, bool usevilestates, FState* state = nu corpsehit->flags |= MF_SOLID; corpsehit->Height = corpsehit->GetDefault()->Height; - bool check = P_CheckPosition(corpsehit, corpsehit->Pos()); + bool check = P_CheckPosition(corpsehit, corpsehit->Pos().XY()); corpsehit->flags = oldflags; corpsehit->radius = oldradius; corpsehit->Height = oldheight; @@ -2889,13 +2899,8 @@ void A_Chase(AActor *self) A_DoChase(self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } -DEFINE_ACTION_FUNCTION(AActor, A_Chase) +void A_ChaseNative(AActor * self, int meleelabel, int missilelabel, int flags) { - PARAM_SELF_PROLOGUE(AActor); - PARAM_STATELABEL(meleelabel); - PARAM_STATELABEL(missilelabel); - PARAM_INT(flags); - FName meleename = ENamedName(meleelabel - 0x10000000); FName missilename = ENamedName(missilelabel - 0x10000000); if (meleename != NAME__a_chase_default || missilename != NAME__a_chase_default) @@ -2903,7 +2908,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Chase) FState *melee = StateLabels.GetState(meleelabel, self->GetClass()); FState *missile = StateLabels.GetState(missilelabel, self->GetClass()); if ((flags & CHF_RESURRECT) && P_CheckForResurrection(self, false)) - return 0; + return; A_DoChase(self, !!(flags&CHF_FASTCHASE), melee, missile, !(flags&CHF_NOPLAYACTIVE), !!(flags&CHF_NIGHTMAREFAST), !!(flags&CHF_DONTMOVE), flags & 0x3fffffff); @@ -2912,6 +2917,36 @@ DEFINE_ACTION_FUNCTION(AActor, A_Chase) { A_DoChase(self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_Chase, A_ChaseNative) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STATELABEL(meleelabel); + PARAM_STATELABEL(missilelabel); + PARAM_INT(flags); + + A_ChaseNative(self, meleelabel, missilelabel, flags); + + return 0; +} + +void A_DoChaseNative(AActor * self, FState *melee, FState *missile, int flags) +{ + if ((flags & CHF_RESURRECT) && P_CheckForResurrection(self, false)) + return; + A_DoChase(self, !!(flags&CHF_FASTCHASE), melee, missile, !(flags&CHF_NOPLAYACTIVE), !!(flags&CHF_NIGHTMAREFAST), !!(flags&CHF_DONTMOVE), flags & 0x3fffffff); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_DoChase, A_DoChaseNative) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STATE(melee); + PARAM_STATE(missile); + PARAM_INT(flags); + + A_DoChaseNative(self, melee, missile, flags); + return 0; } @@ -3018,15 +3053,11 @@ void A_Face(AActor *self, AActor *other, DAngle max_turn, DAngle max_pitch, DAng self->Angles.Pitch = other_pitch; } self->Angles.Pitch += pitch_offset; + A_Face_ShadowHandling(self, other, max_pitch, other_pitch, true); } - - // This will never work well if the turn angle is limited. - if (max_turn == nullAngle && (self->Angles.Yaw == other_angle) && other->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE) ) - { - self->Angles.Yaw += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.)); - } + A_Face_ShadowHandling(self,other,max_turn,other_angle,false); } void A_FaceTarget(AActor *self) @@ -3073,10 +3104,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) // Let the aim trail behind the player self->Angles.Yaw = self->AngleTo(self->target, -self->target->Vel.X * 3, -self->target->Vel.Y * 3); - if (self->target->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE)) - { - self->Angles.Yaw += DAngle::fromDeg(pr_railface.Random2() * 45./256); - } + A_MonsterRail_ShadowHandling(self); FRailParams p; @@ -3111,7 +3139,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain) PARAM_SELF_PROLOGUE(AActor); // [RH] Vary player pain sounds depending on health (ala Quake2) - if (self->player && self->player->morphTics == 0) + if (self->player && self->alternative == nullptr) { const char *pain_amount; FSoundID sfx_id = NO_SOUND; diff --git a/src/playsim/p_interaction.cpp b/src/playsim/p_interaction.cpp index 4baac07a45..0ae77e914c 100644 --- a/src/playsim/p_interaction.cpp +++ b/src/playsim/p_interaction.cpp @@ -219,7 +219,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf } FString obit = DamageTypeDefinition::GetObituary(mod); - if (attacker == nullptr && obit.IsNotEmpty()) messagename = obit; + if (attacker == nullptr && obit.IsNotEmpty()) messagename = obit.GetChars(); else { switch (mod.GetIndex()) @@ -249,11 +249,11 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf else { lookup.Format("$Obituary_%s_%s", attacker->GetClass()->TypeName.GetChars(), mod.GetChars()); - if (GStrings[lookup.GetChars() + 1]) message = lookup; + if (GStrings.CheckString(lookup.GetChars() + 1)) message = lookup.GetChars(); else { lookup.Format("$Obituary_%s", attacker->GetClass()->TypeName.GetChars()); - if (GStrings[lookup.GetChars() + 1]) message = lookup; + if (GStrings.CheckString(lookup.GetChars() + 1)) message = lookup.GetChars(); else { IFVIRTUALPTR(attacker, AActor, GetObituary) @@ -261,7 +261,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf VMValue params[] = { attacker, self, inflictor, mod.GetIndex(), !!(dmgflags & DMG_PLAYERATTACK) }; VMReturn rett(&ret); VMCall(func, params, countof(params), &rett, 1); - if (ret.IsNotEmpty()) message = ret; + if (ret.IsNotEmpty()) message = ret.GetChars(); } } } @@ -273,7 +273,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf if (message != NULL && message[0] == '$') { - message = GStrings.GetString(message+1, nullptr, self->player->userinfo.GetGender()); + message = GStrings.CheckString(message+1, nullptr, self->player->userinfo.GetGender()); } if (message == NULL) @@ -283,16 +283,16 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf if (mod == NAME_Melee) { FStringf ob("DEFHITOB_%s", cls); - message = GStrings.GetString(ob, nullptr, self->player->userinfo.GetGender()); + message = GStrings.CheckString(ob.GetChars(), nullptr, self->player->userinfo.GetGender()); } if (message == nullptr) { FStringf ob("DEFOB_%s", cls); - message = GStrings.GetString(ob, nullptr, self->player->userinfo.GetGender()); + message = GStrings.CheckString(ob.GetChars(), nullptr, self->player->userinfo.GetGender()); } if (message == nullptr) { - message = GStrings.GetString("OB_DEFAULT", nullptr, self->player->userinfo.GetGender()); + message = GStrings.CheckString("OB_DEFAULT", nullptr, self->player->userinfo.GetGender()); } } @@ -313,36 +313,54 @@ EXTERN_CVAR (Int, fraglimit) void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOfDeath) { - // Handle possible unmorph on death bool wasgibbed = (health < GetGibHealth()); + // Check to see if unmorph Actors need to be killed as well. Originally this was always + // called but that puts an unnecessary burden on the modder to determine whether it's + // a valid call or not. + if (alternative != nullptr && !(flags & MF_UNMORPHED)) { IFVIRTUAL(AActor, MorphedDeath) { - AActor *realthis = NULL; - int realstyle = 0; - int realhealth = 0; + // Return values are no longer used to ensure things stay properly managed. + AActor* const realMo = alternative; + int morphStyle = 0; VMValue params[] = { this }; - VMReturn returns[3]; - returns[0].PointerAt((void**)&realthis); - returns[1].IntAt(&realstyle); - returns[2].IntAt(&realhealth); - VMCall(func, params, 1, returns, 3); - if (realthis && !(realstyle & MORPH_UNDOBYDEATHSAVES)) { - if (wasgibbed) + IFVM(Actor, GetMorphStyle) { - int realgibhealth = realthis->GetGibHealth(); - if (realthis->health >= realgibhealth) - { - realthis->health = realgibhealth - 1; // if morphed was gibbed, so must original be (where allowed)l - } + VMReturn ret[] = { &morphStyle }; + VMCall(func, params, 1, ret, 1); } - realthis->CallDie(source, inflictor, dmgflags, MeansOfDeath); } + VMCall(func, params, 1, nullptr, 0); + + // Kill the dummy Actor if it didn't unmorph, otherwise checking the morph flags. Player pawns need + // to stay, otherwise they won't respawn correctly. + if (realMo != nullptr && !(realMo->flags6 & MF6_KILLED) + && ((alternative != nullptr && player == nullptr) || (alternative == nullptr && !(morphStyle & MORPH_UNDOBYDEATHSAVES)))) + { + if (wasgibbed) + { + const int realGibHealth = realMo->GetGibHealth(); + if (realMo->health >= realGibHealth) + realMo->health = realGibHealth - 1; // If morphed was gibbed, so must original be (where allowed). + } + else if (realMo->health > 0) + { + realMo->health = 0; + } + + // Pass appropriate damage information along when it's confirmed to die. + realMo->DamageTypeReceived = DamageTypeReceived; + realMo->DamageType = DamageType; + realMo->special1 = special1; + + realMo->CallDie(source, inflictor, dmgflags, MeansOfDeath); + } } } @@ -436,7 +454,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf player->fragcount--; if (deathmatch && player->spreecount >= 5 && cl_showsprees) { - PronounMessage (GStrings("SPREEKILLSELF"), buff, + PronounMessage (GStrings.GetString("SPREEKILLSELF"), buff, player->userinfo.GetGender(), player->userinfo.GetName(), player->userinfo.GetName()); StatusBar->AttachMessage (Create(nullptr, buff, @@ -458,7 +476,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf ++source->player->spreecount; } - if (source->player->morphTics) + if (source->alternative != nullptr) { // Make a super chicken source->GiveInventoryType (PClass::FindActor(NAME_PowerWeaponLevel2)); } @@ -471,19 +489,19 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf switch (source->player->spreecount) { case 5: - spreemsg = GStrings("SPREE5"); + spreemsg = GStrings.GetString("SPREE5"); break; case 10: - spreemsg = GStrings("SPREE10"); + spreemsg = GStrings.GetString("SPREE10"); break; case 15: - spreemsg = GStrings("SPREE15"); + spreemsg = GStrings.GetString("SPREE15"); break; case 20: - spreemsg = GStrings("SPREE20"); + spreemsg = GStrings.GetString("SPREE20"); break; case 25: - spreemsg = GStrings("SPREE25"); + spreemsg = GStrings.GetString("SPREE25"); break; default: spreemsg = NULL; @@ -494,7 +512,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf { if (!AnnounceSpreeLoss (this)) { - PronounMessage (GStrings("SPREEOVER"), buff, player->userinfo.GetGender(), + PronounMessage (GStrings.GetString("SPREEOVER"), buff, player->userinfo.GetGender(), player->userinfo.GetName(), source->player->userinfo.GetName()); StatusBar->AttachMessage (Create (nullptr, buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); @@ -536,16 +554,16 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf multimsg = NULL; break; case 2: - multimsg = GStrings("MULTI2"); + multimsg = GStrings.GetString("MULTI2"); break; case 3: - multimsg = GStrings("MULTI3"); + multimsg = GStrings.GetString("MULTI3"); break; case 4: - multimsg = GStrings("MULTI4"); + multimsg = GStrings.GetString("MULTI4"); break; default: - multimsg = GStrings("MULTI5"); + multimsg = GStrings.GetString("MULTI5"); break; } if (multimsg != NULL) @@ -569,7 +587,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf if (deathmatch && fraglimit && fraglimit <= D_GetFragCount (source->player)) { - Printf ("%s\n", GStrings("TXT_FRAGLIMIT")); + Printf ("%s\n", GStrings.GetString("TXT_FRAGLIMIT")); Level->ExitLevel (0, false); } } @@ -1329,7 +1347,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da if (damage >= player->health && !telefragDamage && (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch) - && !player->morphTics) + && target->alternative == nullptr) { // Try to use some inventory health P_AutoUseHealth (player, damage - player->health + 1); } @@ -1463,7 +1481,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da // check for special fire damage or ice damage deaths if (mod == NAME_Fire) { - if (player && !player->morphTics) + if (player && target->alternative == nullptr) { // Check for flame death if (!inflictor || ((target->health > -50) && (damage > 25)) || @@ -1614,6 +1632,9 @@ DEFINE_ACTION_FUNCTION(AActor, PoisonMobj) bool AActor::OkayToSwitchTarget(AActor *other) { + if (other == nullptr) + return false; + if (other == this) return false; // [RH] Don't hate self (can happen when shooting barrels) @@ -1794,7 +1815,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain } if (damage >= player->health && (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch) - && !player->morphTics) + && target->alternative == nullptr) { // Try to use some inventory health P_AutoUseHealth(player, damage - player->health+1); } @@ -1824,7 +1845,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain else { target->special1 = damage; - if (player && !player->morphTics) + if (player && target->alternative == nullptr) { // Check for flame death if ((player->poisontype == NAME_Fire) && (target->health > -50) && (damage > 25)) { @@ -1880,8 +1901,8 @@ CCMD (kill) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_MASSACRE); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_MASSACRE); } else if (!stricmp (argv[1], "baddies")) { @@ -1889,12 +1910,12 @@ CCMD (kill) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_MASSACRE2); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (CHT_MASSACRE2); } else { - Net_WriteByte (DEM_KILLCLASSCHEAT); + Net_WriteInt8 (DEM_KILLCLASSCHEAT); Net_WriteString (argv[1]); } } @@ -1905,7 +1926,7 @@ CCMD (kill) return; // Kill the player - Net_WriteByte (DEM_SUICIDE); + Net_WriteInt8 (DEM_SUICIDE); } C_HideConsole (); } @@ -1917,7 +1938,7 @@ CCMD(remove) if (CheckCheatmode()) return; - Net_WriteByte(DEM_REMOVE); + Net_WriteInt8(DEM_REMOVE); Net_WriteString(argv[1]); C_HideConsole(); } diff --git a/src/playsim/p_lnspec.cpp b/src/playsim/p_lnspec.cpp index 88b37f8c36..73666d0c39 100644 --- a/src/playsim/p_lnspec.cpp +++ b/src/playsim/p_lnspec.cpp @@ -175,7 +175,7 @@ FUNC(LS_Polyobj_MoveToSpot) auto iterator = Level->GetActorIterator(arg2); AActor *spot = iterator.Next(); if (spot == NULL) return false; - return EV_MovePolyTo (Level, ln, arg0, SPEED(arg1), spot->Pos(), false); + return EV_MovePolyTo (Level, ln, arg0, SPEED(arg1), spot->Pos().XY(), false); } FUNC(LS_Polyobj_DoorSwing) @@ -226,7 +226,7 @@ FUNC(LS_Polyobj_OR_MoveToSpot) auto iterator = Level->GetActorIterator(arg2); AActor *spot = iterator.Next(); if (spot == NULL) return false; - return EV_MovePolyTo (Level, ln, arg0, SPEED(arg1), spot->Pos(), true); + return EV_MovePolyTo (Level, ln, arg0, SPEED(arg1), spot->Pos().XY(), true); } FUNC(LS_Polyobj_Stop) @@ -941,6 +941,13 @@ FUNC(LS_Generic_Crusher2) SPEED(arg2), 0, arg4, arg3 ? 2 : 0, 0, DCeiling::ECrushMode::crushHexen); } +FUNC(LS_Generic_CrusherDist) +// Generic_CrusherDist (tag, dnspeed, upspeed, silent, damage) +{ + return Level->EV_DoCeiling(DCeiling::ceilCrushAndRaise, ln, arg0, SPEED(arg1), + SPEED(arg2), 8, arg4, arg3 ? 2 : 0, 0, (arg1 <= 24 && arg2 <= 24) ? DCeiling::ECrushMode::crushSlowdown : DCeiling::ECrushMode::crushDoom); +} + FUNC(LS_Plat_PerpetualRaise) // Plat_PerpetualRaise (tag, speed, delay) { @@ -1075,7 +1082,7 @@ FUNC(LS_Generic_Lift) FUNC(LS_Exit_Normal) // Exit_Normal (position) { - if (Level->CheckIfExitIsGood (it, FindLevelInfo(Level->NextMap))) + if (Level->CheckIfExitIsGood (it, FindLevelInfo(Level->NextMap.GetChars()))) { Level->ExitLevel (arg0, false); return true; @@ -1103,7 +1110,7 @@ FUNC(LS_Teleport_NewMap) if (info && Level->CheckIfExitIsGood (it, info)) { - Level->ChangeLevel(info->MapName, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0); + Level->ChangeLevel(info->MapName.GetChars(), arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0); return true; } } @@ -1870,7 +1877,7 @@ FUNC(LS_Thing_SetTranslation) // Thing_SetTranslation (tid, range) { auto iterator = Level->GetActorIterator(arg0); - int range; + FTranslationID range; AActor *target; bool ok = false; @@ -1888,7 +1895,7 @@ FUNC(LS_Thing_SetTranslation) } else { - range = 0; + range = NO_TRANSLATION; } if (arg0 == 0) @@ -1896,7 +1903,7 @@ FUNC(LS_Thing_SetTranslation) if (it != NULL) { ok = true; - it->Translation = range==0? it->GetDefault()->Translation : range; + it->Translation = range == NO_TRANSLATION ? it->GetDefault()->Translation : range; } } else @@ -1904,7 +1911,7 @@ FUNC(LS_Thing_SetTranslation) while ( (target = iterator.Next ()) ) { ok = true; - target->Translation = range==0? target->GetDefault()->Translation : range; + target->Translation = range == NO_TRANSLATION ? target->GetDefault()->Translation : range; } } @@ -1921,11 +1928,11 @@ FUNC(LS_ACS_Execute) if (arg1 == 0) { - mapname = Level->MapName; + mapname = Level->MapName.GetChars(); } else if ((info = FindLevelByNum(arg1)) != NULL) { - mapname = info->MapName; + mapname = info->MapName.GetChars(); } else { @@ -1944,11 +1951,11 @@ FUNC(LS_ACS_ExecuteAlways) if (arg1 == 0) { - mapname = Level->MapName; + mapname = Level->MapName.GetChars(); } else if ((info = FindLevelByNum(arg1)) != NULL) { - mapname = info->MapName; + mapname = info->MapName.GetChars(); } else { @@ -1984,7 +1991,7 @@ FUNC(LS_ACS_ExecuteWithResult) int args[4] = { arg1, arg2, arg3, arg4 }; int flags = (backSide ? ACS_BACKSIDE : 0) | ACS_ALWAYS | ACS_WANTRESULT; - return P_StartScript (Level, it, ln, arg0, Level->MapName, args, 4, flags); + return P_StartScript (Level, it, ln, arg0, Level->MapName.GetChars(), args, 4, flags); } FUNC(LS_ACS_Suspend) @@ -1993,9 +2000,9 @@ FUNC(LS_ACS_Suspend) level_info_t *info; if (arg1 == 0) - P_SuspendScript (Level, arg0, Level->MapName); + P_SuspendScript (Level, arg0, Level->MapName.GetChars()); else if ((info = FindLevelByNum (arg1)) ) - P_SuspendScript (Level, arg0, info->MapName); + P_SuspendScript (Level, arg0, info->MapName.GetChars()); return true; } @@ -2006,9 +2013,9 @@ FUNC(LS_ACS_Terminate) level_info_t *info; if (arg1 == 0) - P_TerminateScript (Level, arg0, Level->MapName); + P_TerminateScript (Level, arg0, Level->MapName.GetChars()); else if ((info = FindLevelByNum (arg1)) ) - P_TerminateScript (Level, arg0, info->MapName); + P_TerminateScript (Level, arg0, info->MapName.GetChars()); return true; } @@ -3173,7 +3180,7 @@ FUNC(LS_Autosave) if (gameaction != ga_savegame) { Level->flags2 &= ~LEVEL2_NOAUTOSAVEHINT; - Net_WriteByte (DEM_CHECKAUTOSAVE); + Net_WriteInt8 (DEM_CHECKAUTOSAVE); } return true; } @@ -3251,7 +3258,7 @@ FUNC(LS_SendToCommunicator) // Get the message from the LANGUAGE lump. FString msg; msg.Format("TXT_COMM%d", arg2); - const char *str = GStrings[msg]; + const char *str = GStrings.CheckString(msg.GetChars()); if (str != NULL) { Printf (PRINT_CHAT, "%s\n", str); @@ -3863,6 +3870,7 @@ static lnSpecFunc LineSpecials[] = /* 281 */ LS_Line_SetAutomapFlags, /* 282 */ LS_Line_SetAutomapStyle, /* 283 */ LS_Polyobj_StopSound, + /* 284 */ LS_Generic_CrusherDist }; #define DEFINE_SPECIAL(name, num, min, max, mmax) {#name, num, min, max, mmax}, diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index e1fae8d628..cde45f403c 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -51,6 +51,7 @@ struct FCheckPosition; struct FTranslatedLineTarget; struct FLinePortal; class DViewPosition; +struct FRenderViewpoint; #include @@ -268,6 +269,7 @@ void P_PlayerStartStomp (AActor *actor, bool mononly=false); // [RH] Stomp on t void P_SlideMove (AActor* mo, const DVector2 &pos, int numsteps); bool P_BounceWall (AActor *mo); bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop); +bool P_ReflectOffActor(AActor* mo, AActor* blocking); int P_CheckSight (AActor *t1, AActor *t2, int flags=0); enum ESightFlags @@ -391,11 +393,8 @@ bool P_CheckMissileSpawn(AActor *missile, double maxdist); void P_PlaySpawnSound(AActor *missile, AActor *spawner); -// [RH] Position the chasecam -void P_AimCamera (AActor *t1, DVector3 &, DAngle &, sector_t *&sec, bool &unlinked); - -// [MC] Aiming for ViewPos -void P_AdjustViewPos(AActor *t1, DVector3 orig, DVector3 &, sector_t *&sec, bool &unlinked, DViewPosition *VP); +// [RH] Position the cam's view offsets. +void R_OffsetView(FRenderViewpoint& viewPoint, const DVector3& dir, const double distance); // [RH] Means of death @@ -406,11 +405,14 @@ enum RADF_SOURCEISSPOT = 4, RADF_NODAMAGE = 8, RADF_THRUSTZ = 16, - RADF_OLDRADIUSDAMAGE = 32 + RADF_OLDRADIUSDAMAGE = 32, + RADF_THRUSTLESS = 64, + RADF_NOALLIES = 128, + RADF_CIRCULAR = 256 }; -int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int fulldmgdistance, bool oldradiusdmg); -int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, - FName damageType, int flags, int fulldamagedistance=0, FName species = NAME_None); +int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, double distance, double fulldmgdistance, bool oldradiusdmg, bool circular); +int P_RadiusAttack (AActor *spot, AActor *source, int damage, double distance, + FName damageType, int flags, double fulldamagedistance=0.0, FName species = NAME_None); void P_DelSeclist(msecnode_t *, msecnode_t *sector_t::*seclisthead); void P_DelSeclist(portnode_t *, portnode_t *FLinePortal::*seclisthead); diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 0ec9b68639..53329b96fb 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -92,6 +92,7 @@ #include "r_sky.h" #include "g_levellocals.h" #include "actorinlines.h" +#include CVAR(Bool, cl_bloodsplats, true, CVAR_ARCHIVE) CVAR(Int, sv_smartaim, 0, CVAR_ARCHIVE | CVAR_SERVERINFO) @@ -169,6 +170,25 @@ bool P_CanCollideWith(AActor *tmthing, AActor *thing) return true; } +void P_CollidedWith(AActor* const collider, AActor* const collidee) +{ + { + IFVIRTUALPTR(collider, AActor, CollidedWith) + { + VMValue params[] = { collider, collidee, false }; + VMCall(func, params, 3, nullptr, 0); + } + } + + { + IFVIRTUALPTR(collidee, AActor, CollidedWith) + { + VMValue params[] = { collidee, collider, true }; + VMCall(func, params, 3, nullptr, 0); + } + } +} + //========================================================================== // // CanCrossLine @@ -266,7 +286,7 @@ static bool PIT_FindFloorCeiling(FMultiBlockLinesIterator &mit, FMultiBlockLines return true; } - DVector2 refpoint = FindRefPoint(ld, cres.Position); + DVector2 refpoint = FindRefPoint(ld, cres.Position.XY()); FLineOpening open; P_LineOpening(open, tmf.thing, ld, refpoint, &cres.Position, flags); @@ -850,8 +870,8 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec { spechit_t spec; spec.line = ld; - spec.Refpos = cres.Position; - spec.Oldrefpos = tm.thing->PosRelative(ld); + spec.Refpos = cres.Position.XY(); + spec.Oldrefpos = tm.thing->PosRelative(ld).XY(); portalhit.Push(spec); return true; } @@ -962,12 +982,12 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec tm.thing->BlockingLine = ld; } // Calculate line side based on the actor's original position, not the new one. - CheckForPushSpecial(ld, P_PointOnLineSide(cres.Position, ld), tm.thing); + CheckForPushSpecial(ld, P_PointOnLineSide(cres.Position.XY(), ld), tm.thing); return false; } } } - DVector2 ref = FindRefPoint(ld, cres.Position); + DVector2 ref = FindRefPoint(ld, cres.Position.XY()); FLineOpening open; P_LineOpening(open, tm.thing, ld, ref, &cres.Position, cres.portalflags); @@ -1088,15 +1108,15 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec if (ld->special) { spec.line = ld; - spec.Refpos = cres.Position; - spec.Oldrefpos = tm.thing->PosRelative(ld); + spec.Refpos = cres.Position.XY(); + spec.Oldrefpos = tm.thing->PosRelative(ld).XY(); spechit.Push(spec); } if (ld->isLinePortal()) { spec.line = ld; - spec.Refpos = cres.Position; - spec.Oldrefpos = tm.thing->PosRelative(ld); + spec.Refpos = cres.Position.XY(); + spec.Oldrefpos = tm.thing->PosRelative(ld).XY(); portalhit.Push(spec); } @@ -1152,7 +1172,7 @@ static bool PIT_CheckPortal(FMultiBlockLinesIterator &mit, FMultiBlockLinesItera if (ld->backsector == NULL) continue; - DVector2 ref = FindRefPoint(ld, cres.Position); + DVector2 ref = FindRefPoint(ld, cres.Position.XY()); FLineOpening open; P_LineOpening(open, tm.thing, ld, ref, &cres.Position, 0); @@ -2016,7 +2036,7 @@ int P_TestMobjLocation(AActor *mobj) flags = mobj->flags; mobj->flags &= ~MF_PICKUP; - if (P_CheckPosition(mobj, mobj->Pos())) + if (P_CheckPosition(mobj, mobj->Pos().XY())) { // XY is ok, now check Z mobj->flags = flags; if ((mobj->Z() < mobj->floorz) || (mobj->Top() > mobj->ceilingz)) @@ -2045,8 +2065,15 @@ AActor *P_CheckOnmobj(AActor *thing) oldz = thing->Z(); P_FakeZMovement(thing); good = P_TestMobjZ(thing, false, &onmobj); - thing->SetZ(oldz); + // Make sure we don't double call a collision with it. + if (!good && onmobj != nullptr && onmobj != thing->BlockingMobj + && (thing->player == nullptr || !(thing->player->cheats & CF_PREDICTING))) + { + P_CollidedWith(thing, onmobj); + } + + thing->SetZ(oldz); return good ? NULL : onmobj; } @@ -2288,6 +2315,11 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, if (!P_CheckPosition(thing, pos, tm)) { AActor *BlockingMobj = thing->BlockingMobj; + // This gets called regardless of whether or not the following checks allow the thing to pass. This is because a player + // could step on top of an enemy but we still want it to register as a collision. + if (BlockingMobj != nullptr && (thing->player == nullptr || !(thing->player->cheats & CF_PREDICTING))) + P_CollidedWith(thing, BlockingMobj); + // Solid wall or thing if (!BlockingMobj || BlockingMobj->player || !thing->player) { @@ -2546,7 +2578,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, { FLinkContext ctx; thing->UnlinkFromWorld(&ctx); - thing->SetXY(tm.pos + port->mDisplacement); + thing->SetXY(tm.pos.XY() + port->mDisplacement); thing->Prev += port->mDisplacement; thing->LinkToWorld(&ctx); P_FindFloorCeiling(thing); @@ -2556,16 +2588,19 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, } else if (!portalcrossed) { - DVector3 pos(tm.pos, thing->Z()); + DVector3 pos(tm.pos.XY(), thing->Z()); DVector3 oldthingpos = thing->Pos(); - DVector2 thingpos = oldthingpos; + DVector2 thingpos = oldthingpos.XY(); P_TranslatePortalXY(ld, pos.X, pos.Y); P_TranslatePortalXY(ld, thingpos.X, thingpos.Y); P_TranslatePortalZ(ld, pos.Z); thing->SetXYZ(thingpos.X, thingpos.Y, pos.Z); - if (!P_CheckPosition(thing, pos, true)) // check if some actor blocks us on the other side. (No line checks, because of the mess that'd create.) + if (!P_CheckPosition(thing, pos.XY(), true)) // check if some actor blocks us on the other side. (No line checks, because of the mess that'd create.) { + if (thing->BlockingMobj != nullptr && (thing->player == nullptr || !(thing->player->cheats && CF_PREDICTING))) + P_CollidedWith(thing, thing->BlockingMobj); + thing->SetXYZ(oldthingpos); thing->flags6 &= ~MF6_INTRYMOVE; return false; @@ -2601,13 +2636,15 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, auto p = thing->Level->GetConsolePlayer(); if (p) p->viewz += hit.pos.Z; // needs to be done here because otherwise the renderer will not catch the change. P_TranslatePortalAngle(ld, hit.angle); + if (thing->player && (port->mType == PORTT_INTERACTIVE || port->mType == PORTT_TELEPORT)) + thing->player->crossingPortal = true; } R_AddInterpolationPoint(hit); } if (port->mType == PORTT_LINKED) { continue; - } + } } break; } @@ -2643,7 +2680,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) { spechit_t spec; - DVector2 lastpos = thing->Pos(); + DVector2 lastpos = thing->Pos().XY(); while (spechit.Pop(spec)) { line_t *ld = spec.line; @@ -2743,6 +2780,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, pushline: thing->flags6 &= ~MF6_INTRYMOVE; + thing->SetZ(oldz); // [RH] Don't activate anything if just predicting if (thing->player && (thing->player->cheats & CF_PREDICTING)) @@ -2750,7 +2788,6 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, return false; } - thing->SetZ(oldz); if (!(thing->flags&(MF_TELEPORT | MF_NOCLIP))) { int numSpecHitTemp; @@ -2987,7 +3024,7 @@ void FSlide::HitSlideLine(line_t* ld) // less than 45 degrees. // phares DVector3 pos = slidemo->PosRelative(ld); - side = P_PointOnLineSide(pos, ld); + side = P_PointOnLineSide(pos.XY(), ld); lineangle = ld->Delta().Angle(); @@ -3080,7 +3117,7 @@ void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end) if (!(li->flags & ML_TWOSIDED) || !li->backsector) { DVector3 pos = slidemo->PosRelative(li); - if (P_PointOnLineSide(pos, li)) + if (P_PointOnLineSide(pos.XY(), li)) { // don't hit the back side continue; @@ -3202,11 +3239,11 @@ void FSlide::SlideMove(AActor *mo, DVector2 tryp, int numsteps) // killough 3/15/98: Allow objects to drop off ledges move = { 0, tryp.Y }; walkplane = P_CheckSlopeWalk(mo, move); - if (!P_TryMove(mo, mo->Pos() + move, true, walkplane)) + if (!P_TryMove(mo, mo->Pos().XY() + move, true, walkplane)) { move = { tryp.X, 0 }; walkplane = P_CheckSlopeWalk(mo, move); - P_TryMove(mo, mo->Pos() + move, true, walkplane); + P_TryMove(mo, mo->Pos().XY() + move, true, walkplane); } return; } @@ -3221,7 +3258,7 @@ void FSlide::SlideMove(AActor *mo, DVector2 tryp, int numsteps) const DVector2 startvel = mo->Vel.XY(); // killough 3/15/98: Allow objects to drop off ledges - if (!P_TryMove(mo, mo->Pos() + newpos, true)) + if (!P_TryMove(mo, mo->Pos().XY() + newpos, true)) goto stairstep; if (mo->Vel.XY() != startvel) @@ -3254,7 +3291,7 @@ void FSlide::SlideMove(AActor *mo, DVector2 tryp, int numsteps) walkplane = P_CheckSlopeWalk(mo, tmmove); // killough 3/15/98: Allow objects to drop off ledges - if (!P_TryMove(mo, mo->Pos() + tmmove, true, walkplane)) + if (!P_TryMove(mo, mo->Pos().XY() + tmmove, true, walkplane)) { goto retry; } @@ -3334,7 +3371,7 @@ const secplane_t * P_CheckSlopeWalk(AActor *actor, DVector2 &move) DVector2 dest; double t; - dest = actor->Pos() + move; + dest = actor->Pos().XY() + move; t = (plane->Normal() | DVector3(dest, actor->Z())) + plane->fD(); if (t < 0) { // Desired location is behind (below) the plane @@ -3369,7 +3406,7 @@ const secplane_t * P_CheckSlopeWalk(AActor *actor, DVector2 &move) } if (dopush) { - move = plane->Normal() * 2; + move = plane->Normal().XY() * 2; actor->Vel.X = move.X; actor->Vel.Y = move.Y; } @@ -3378,7 +3415,7 @@ const secplane_t * P_CheckSlopeWalk(AActor *actor, DVector2 &move) } // Slide the desired location along the plane's normal // so that it lies on the plane's surface - dest -= plane->Normal() * t; + dest -= plane->Normal().XY() * t; move = dest - actor->Pos().XY(); return (actor->floorsector == actor->Sector) ? plane : NULL; } @@ -3388,7 +3425,7 @@ const secplane_t * P_CheckSlopeWalk(AActor *actor, DVector2 &move) { // Actor's current spot is on/in the plane, so walk down it // Same principle as walking up, except reversed - dest += plane->Normal() * t; + dest += plane->Normal().XY() * t; move = dest - actor->Pos().XY(); return (actor->floorsector == actor->Sector) ? plane : NULL; } @@ -3427,7 +3464,7 @@ bool FSlide::BounceTraverse(const DVector2 &start, const DVector2 &end) } if (!(li->flags&ML_TWOSIDED) || !li->backsector) { - if (P_PointOnLineSide(slidemo->Pos(), li)) + if (P_PointOnLineSide(slidemo->Pos().XY(), li)) continue; // don't hit the back side goto bounceblocking; } @@ -3517,6 +3554,16 @@ bool FSlide::BounceWall(AActor *mo) } line = bestslideline; + if (mo->flags & MF_MISSILE) + { + switch (mo->SpecialBounceHit(nullptr, line, nullptr)) + { + case 1: return true; + case 0: return false; + default: break; + } + } + if (line->special == Line_Horizon || ((mo->BounceFlags & BOUNCE_NotOnSky) && line->hitSkyWall(mo))) { mo->SeeSound = mo->BounceSound = NO_SOUND; // it might make a sound otherwise @@ -3546,7 +3593,7 @@ bool FSlide::BounceWall(AActor *mo) return true; } - side = P_PointOnLineSide(mo->Pos(), line); + side = P_PointOnLineSide(mo->Pos().XY(), line); lineangle = line->Delta().Angle(); if (side == 1) { @@ -3607,6 +3654,13 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop) case 0: return false; default: break; } + + switch (mo->SpecialBounceHit(BlockingMobj, nullptr, nullptr)) + { + case 1: return true; + case 0: return false; + default: break; + } } //Don't go through all of this if the actor is reflective and wants things to pass through them. @@ -3706,6 +3760,48 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop) return false; } +bool P_ReflectOffActor(AActor* mo, AActor* blocking) +{ + if (!(blocking->flags2 & MF2_REFLECTIVE)) + return false; + + // Don't change the angle if there's THRUREFLECT on the monster. + if (!(blocking->flags7 & MF7_THRUREFLECT)) + { + DAngle angle = blocking->AngleTo(mo); + if (mo->AdjustReflectionAngle(blocking, angle)) + return false; + + // Change angle for deflection/reflection + auto target = mo->target != NULL ? mo->target : blocking->target; + if (target && (blocking->flags7 & MF7_AIMREFLECT)) + { + //dest->x - source->x + DVector3 vect = mo->Vec3To(target); + vect.Z += target->Height * 0.5; + mo->Vel = vect.Resized(mo->Speed); + } + else if (blocking->flags7 & MF7_MIRRORREFLECT) + { + mo->Angles.Yaw += DAngle::fromDeg(180.0); + mo->Vel *= -0.5; + } + else + { + mo->Angles.Yaw = angle; + mo->VelFromAngle(mo->Speed * 0.5); + mo->Vel.Z *= -0.5; + } + } + + if (mo->flags2 & MF2_SEEKERMISSILE) + mo->tracer = mo->target; + + mo->target = blocking; + + return true; +} + //============================================================================ // // Aiming @@ -3987,7 +4083,7 @@ struct aim_t newtrace.startfrac = frac + 1 / attackrange; // this is to skip the transition line to the portal which would produce a bogus opening - DVector2 pos = newtrace.startpos + newtrace.aimtrace * newtrace.startfrac; + DVector2 pos = newtrace.startpos.XY() + newtrace.aimtrace * newtrace.startfrac; newtrace.lastsector = li->GetLevel()->PointInSector(pos); P_TranslatePortalZ(li, limitz); @@ -4452,6 +4548,11 @@ DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLin { *pLineTarget = *result; } + + DAngle newPitch = P_AimLineAttack_ShadowHandling(t1,target,result->linetarget,shootz); + if (newPitch != nullAngle) + result->pitch = newPitch; + return result->linetarget ? result->pitch : t1->Angles.Pitch; } @@ -5098,7 +5199,7 @@ void P_TraceBleed(int damage, const DVector3 &pos, AActor *actor, DAngle angle, bloodcolor.a = 1; } - uint32_t bloodTrans = (bloodcolor != 0 ? actor->BloodTranslation : 0); + auto bloodTrans = (bloodcolor != 0 ? actor->BloodTranslation : NO_TRANSLATION); DImpactDecal::StaticCreate(actor->Level, bloodType, bleedtrace.HitPos, bleedtrace.Line->sidedef[bleedtrace.Side], bleedtrace.ffloor, bloodcolor, bloodTrans); @@ -5472,55 +5573,39 @@ void P_RailAttack(FRailParams *p) CVAR(Float, chase_height, -8.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Float, chase_dist, 90.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -void P_AimCamera(AActor *t1, DVector3 &campos, DAngle &camangle, sector_t *&CameraSector, bool &unlinked) +void R_OffsetView(FRenderViewpoint& viewPoint, const DVector3& dir, const double distance) { - double distance = clamp(chase_dist, 0, 30000); - DAngle angle = t1->Angles.Yaw - DAngle::fromDeg(180); - DAngle pitch = t1->Angles.Pitch; - FTraceResults trace; - DVector3 vvec; - double sz; - - double pc = pitch.Cos(); - - vvec = { pc * angle.Cos(), pc * angle.Sin(), pitch.Sin() }; - sz = t1->Top() - t1->Floorclip + clamp(chase_height, -1000, 1000); - - if (Trace(t1->PosAtZ(sz), t1->Sector, vvec, distance, 0, 0, NULL, trace) && - trace.Distance > 10) + const DAngle baseYaw = dir.Angle(); + FTraceResults trace = {}; + if (Trace(viewPoint.Pos, viewPoint.sector, dir, distance, 0u, 0u, nullptr, trace)) { - // Position camera slightly in front of hit thing - campos = t1->PosAtZ(sz) + vvec *(trace.Distance - 5); + viewPoint.Pos = trace.HitPos - trace.HitVector * min(5.0, trace.Distance); + viewPoint.sector = viewPoint.ViewLevel->PointInRenderSubsector(viewPoint.Pos)->sector; } else { - campos = trace.HitPos - trace.HitVector * 1/256.; + viewPoint.Pos = trace.HitPos; + viewPoint.sector = trace.Sector; } - CameraSector = trace.Sector; - unlinked = trace.unlinked; - camangle = trace.SrcAngleFromTarget - DAngle::fromDeg(180.); -} - -// [MC] Used for ViewPos. Uses code borrowed from P_AimCamera. -void P_AdjustViewPos(AActor *t1, DVector3 orig, DVector3 &campos, sector_t *&CameraSector, bool &unlinked, DViewPosition *VP) -{ - FTraceResults trace; - const DVector3 vvec = campos - orig; - const double distance = vvec.Length(); - // Trace handles all of the portal crossing, which is why there is no usage of Vec#Offset(Z). - if (Trace(orig, t1->Sector, vvec.Unit(), distance, 0, 0, t1, trace) && - trace.Distance > 5) + viewPoint.Angles.Yaw += deltaangle(baseYaw, trace.SrcAngleFromTarget); + // TODO: Why does this even need to be done? Please fix tracers already. + if (dir.Z < 0.0) { - // Position camera slightly in front of hit thing - campos = orig + vvec.Unit() * (trace.Distance - 5); + while (!viewPoint.sector->PortalBlocksMovement(sector_t::floor) && viewPoint.Pos.Z < viewPoint.sector->GetPortalPlaneZ(sector_t::floor)) + { + viewPoint.Pos += viewPoint.sector->GetPortalDisplacement(sector_t::floor); + viewPoint.sector = viewPoint.sector->GetPortal(sector_t::floor)->mDestination; + } } - else + else if (dir.Z > 0.0) { - campos = trace.HitPos - trace.HitVector * 1 / 256.; + while (!viewPoint.sector->PortalBlocksMovement(sector_t::ceiling) && viewPoint.Pos.Z > viewPoint.sector->GetPortalPlaneZ(sector_t::ceiling)) + { + viewPoint.Pos += viewPoint.sector->GetPortalDisplacement(sector_t::ceiling); + viewPoint.sector = viewPoint.sector->GetPortal(sector_t::ceiling)->mDestination; + } } - CameraSector = trace.Sector; - unlinked = trace.unlinked; } //========================================================================== @@ -5629,7 +5714,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, return true; } - sec = P_PointOnLineSide(xpos, in->d.line) == 0 ? + sec = P_PointOnLineSide(xpos.XY(), in->d.line) == 0 ? in->d.line->frontsector : in->d.line->backsector; if (sec != NULL && sec->SecActTarget && @@ -5648,7 +5733,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, continue; // not a special line, but keep checking } - if (P_PointOnLineSide(xpos, in->d.line) == 1) + if (P_PointOnLineSide(xpos.XY(), in->d.line) == 1) { if (!(in->d.line->activation & SPAC_UseBack)) { @@ -5742,7 +5827,7 @@ void P_UseLines(player_t *player) bool foundline = false; // If the player is transitioning a portal, use the group that is at its vertical center. - DVector2 start = player->mo->GetPortalTransition(player->mo->Height / 2); + DVector2 start = player->mo->GetPortalTransition(player->mo->Height / 2).XY(); // [NS] Now queries the Player's UseRange. DVector2 end = start + player->mo->Angles.Yaw.ToVector(player->mo->FloatVar(NAME_UseRange)); @@ -5782,7 +5867,7 @@ int P_UsePuzzleItem(AActor *PuzzleItemUser, int PuzzleItemType) else usedist = USERANGE; - start = PuzzleItemUser->GetPortalTransition(PuzzleItemUser->Height / 2); + start = PuzzleItemUser->GetPortalTransition(PuzzleItemUser->Height / 2).XY(); end = PuzzleItemUser->Angles.Yaw.ToVector(usedist); FPathTraverse it(PuzzleItemUser->Level, start.X, start.Y, end.X, end.Y, PT_DELTA | PT_ADDLINES | PT_ADDTHINGS); @@ -5804,7 +5889,7 @@ int P_UsePuzzleItem(AActor *PuzzleItemUser, int PuzzleItemType) } continue; } - if (P_PointOnLineSide(PuzzleItemUser->Pos(), in->d.line) == 1) + if (P_PointOnLineSide(PuzzleItemUser->Pos().XY(), in->d.line) == 1) { // Don't use back sides return false; } @@ -5838,7 +5923,7 @@ int P_UsePuzzleItem(AActor *PuzzleItemUser, int PuzzleItemType) //========================================================================== // // RADIUS ATTACK -// +// Most of the explosion code resides here. Except P_GeometryRadiusAttack(). // //========================================================================== @@ -5864,7 +5949,7 @@ CUSTOM_CVAR(Float, splashfactor, 1.f, CVAR_SERVERINFO) // Used by anything without OLDRADIUSDMG flag //========================================================================== -static double GetRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, int bombdamage, int bombdistance, int fulldamagedistance, bool thingbombsource) +static double GetRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, int bombdamage, double bombdistance, double fulldamagedistance, bool thingbombsource, bool round) { // [RH] New code. The bounding box only covers the // height of the thing and not the height of the map. @@ -5873,47 +5958,55 @@ static double GetRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, double dx, dy; double boxradius; - double bombdistancefloat = 1. / (double)(bombdistance - fulldamagedistance); + double bombdistancefloat = 1.0 / (bombdistance - fulldamagedistance); double bombdamagefloat = (double)bombdamage; - DVector2 vec = bombspot->Vec2To(thing); - dx = fabs(vec.X); - dy = fabs(vec.Y); - boxradius = thing->radius; - - // The damage pattern is square, not circular. - len = double(dx > dy ? dx : dy); - - if (bombspot->Z() < thing->Z() || bombspot->Z() >= thing->Top()) + if (!round) { - double dz; + DVector2 vec = bombspot->Vec2To(thing); + dx = fabs(vec.X); + dy = fabs(vec.Y); + boxradius = thing->radius; - if (bombspot->Z() > thing->Z()) - { - dz = double(bombspot->Z() - thing->Top()); - } - else - { - dz = double(thing->Z() - bombspot->Z()); - } - if (len <= boxradius) + // The damage pattern is square, not circular. + len = double(dx > dy ? dx : dy); + + if (bombspot->Z() < thing->Z() || bombspot->Z() >= thing->Top()) { - len = dz; + double dz; + + if (bombspot->Z() > thing->Z()) + { + dz = double(bombspot->Z() - thing->Top()); + } + else + { + dz = double(thing->Z() - bombspot->Z()); + } + if (len <= boxradius) + { + len = dz; + } + else + { + len -= boxradius; + len = g_sqrt(len*len + dz*dz); + } } else { len -= boxradius; - len = g_sqrt(len*len + dz*dz); + if (len < 0.f) + len = 0.f; } } + //[inkoalwetrust]: Round explosions just use the actual distance between the source and victim. else { - len -= boxradius; - if (len < 0.f) - len = 0.f; + len = bombspot->Distance3D (thing); } - len = clamp(len - (double)fulldamagedistance, 0, len); - points = bombdamagefloat * (1. - len * bombdistancefloat); + len = clamp(len - fulldamagedistance, 0.0, len); + points = bombdamagefloat * (1.0 - len * bombdistancefloat); // Calculate the splash and radius damage factor if called by P_RadiusAttack. // Otherwise, just get the raw damage. This allows modders to manipulate it @@ -5941,7 +6034,7 @@ static double GetRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, // based on XY distance. //========================================================================== -static int GetOldRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, int bombdamage, int bombdistance, int fulldamagedistance) +static int GetOldRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, int bombdamage, double bombdistance, double fulldamagedistance) { const int ret = fromaction ? 0 : -1; // -1 is specifically for P_RadiusAttack; continue onto another actor. double dx, dy, dist; @@ -5962,8 +6055,8 @@ static int GetOldRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, // When called from the action function, ignore the sight check. if (fromaction || P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) { - dist = clamp(dist - fulldamagedistance, 0, dist); - int damage = Scale(bombdamage, bombdistance - int(dist), bombdistance); + dist = clamp(dist - fulldamagedistance, 0.0, dist); + int damage = (int)Scale((double)bombdamage, bombdistance - dist, bombdistance); if (!fromaction) { @@ -5985,7 +6078,7 @@ static int GetOldRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, // damage and not taking into account any damage reduction. //========================================================================== -int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int fulldmgdistance, bool oldradiusdmg) +int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, double distance, double fulldmgdistance, bool oldradiusdmg, bool circular) { if (!thing) @@ -5997,15 +6090,15 @@ int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int return damage; } - fulldmgdistance = clamp(fulldmgdistance, 0, distance - 1); + fulldmgdistance = clamp(fulldmgdistance, 0.0, distance - 1.0); // Mirroring A_Explode's behavior. - if (distance <= 0) + if (distance <= 0.0) distance = damage; const int newdam = oldradiusdmg ? GetOldRadiusDamage(true, self, thing, damage, distance, fulldmgdistance) - : int(GetRadiusDamage(true, self, thing, damage, distance, fulldmgdistance, false)); + : int(GetRadiusDamage(true, self, thing, damage, distance, fulldmgdistance, false, circular)); return newdam; } @@ -6017,15 +6110,15 @@ int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int // //========================================================================== -int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bombdistance, FName bombmod, - int flags, int fulldamagedistance, FName species) +int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, double bombdistance, FName bombmod, + int flags, double fulldamagedistance, FName species) { - if (bombdistance <= 0) + if (bombdistance <= 0.0) return 0; - fulldamagedistance = clamp(fulldamagedistance, 0, bombdistance - 1); + fulldamagedistance = clamp(fulldamagedistance, 0.0, bombdistance - 1.0); FPortalGroupArray grouplist(FPortalGroupArray::PGA_Full3d); - FMultiBlockThingsIterator it(grouplist, bombspot->Level, bombspot->X(), bombspot->Y(), bombspot->Z() - bombdistance, bombspot->Height + bombdistance*2, bombdistance, false, bombspot->Sector); + FMultiBlockThingsIterator it(grouplist, bombspot->Level, bombspot->X(), bombspot->Y(), bombspot->Z() - bombdistance, bombspot->Height + bombdistance*2.0, bombdistance, false, bombspot->Sector); FMultiBlockThingsIterator::CheckResult cres; if (flags & RADF_SOURCEISSPOT) @@ -6072,10 +6165,12 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom ) ) continue; - if((species != NAME_None) && (thing->Species != species)) - { + if ((species != NAME_None) && (thing->Species != species)) + continue; + + //[inkoalawetrust] Don't harm actors friendly to the explosions' source. But do harm the source. + if ((flags & RADF_NOALLIES) && bombsource->IsFriend(thing) && !(thing == bombsource || thing == bombspot)) continue; - } if (bombsource && thing != bombsource && bombsource->player && P_ShouldPassThroughPlayer(bombsource, thing)) continue; @@ -6092,7 +6187,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom if ((flags & RADF_NODAMAGE) || (!((bombspot->flags5 | thing->flags5) & MF5_OLDRADIUSDMG) && !(flags & RADF_OLDRADIUSDAMAGE) && !(thing->Level->i_compatflags2 & COMPATF2_EXPLODE2))) { - double points = GetRadiusDamage(false, bombspot, thing, bombdamage, bombdistance, fulldamagedistance, bombsource == thing); + double points = GetRadiusDamage(false, bombspot, thing, bombdamage, bombdistance, fulldamagedistance, bombsource == thing,!!(flags & RADF_CIRCULAR)); double check = int(points) * bombdamage; // points and bombdamage should be the same sign (the double cast of 'points' is needed to prevent overflows and incorrect values slipping through.) if ((check > 0 || (check == 0 && bombspot->flags7 & MF7_FORCEZERORADIUSDMG)) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) @@ -6101,15 +6196,22 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom double thrust; int damage = abs((int)points); int newdam = damage; + int dmgmask = 0; if (!(flags & RADF_NODAMAGE)) { + //[inkoalawetrust] Thrustless explosions don't push anything. + if (!(flags & RADF_THRUSTLESS)) + dmgmask = DMG_EXPLOSION; + else + dmgmask = DMG_EXPLOSION | DMG_THRUSTLESS; + //[MC] Don't count actors saved by buddha if already at 1 health. int prehealth = thing->health; - newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod, DMG_EXPLOSION); + newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod, dmgmask); if (thing->health < prehealth) count++; } - else if (thing->player == NULL && (!(flags & RADF_NOIMPACTDAMAGE) && !(thing->flags7 & MF7_DONTTHRUST))) + else if (thing->player == NULL && (!(flags & RADF_NOIMPACTDAMAGE && !(flags & RADF_THRUSTLESS)) && !(thing->flags7 & MF7_DONTTHRUST))) thing->flags2 |= MF2_BLASTED; if (!(thing->flags & MF_ICECORPSE)) @@ -6117,13 +6219,12 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom if (!(flags & RADF_NODAMAGE) && !(bombspot->flags3 & MF3_BLOODLESSIMPACT)) P_TraceBleed(newdam > 0 ? newdam : damage, thing, bombspot); - if ((flags & RADF_NODAMAGE) || !(bombspot->flags2 & MF2_NODMGTHRUST)) + if ((flags & RADF_NODAMAGE && !(flags & RADF_THRUSTLESS)) || !(bombspot->flags2 & MF2_NODMGTHRUST) && !(flags & RADF_THRUSTLESS)) { if (bombsource == NULL || !(bombsource->flags2 & MF2_NODMGTHRUST)) { if (!(thing->flags7 & MF7_DONTTHRUST)) { - thrust = points * 0.5 / (double)thing->Mass; if (bombsource == thing) { @@ -6230,7 +6331,7 @@ bool P_AdjustFloorCeil(AActor *thing, FChangePosition *cpos) thing->flags2 |= MF2_PASSMOBJ; } - bool isgood = P_CheckPosition(thing, thing->Pos(), tm); + bool isgood = P_CheckPosition(thing, thing->Pos().XY(), tm); if (!(thing->flags4 & MF4_ACTLIKEBRIDGE)) { thing->floorz = tm.floorz; @@ -6400,7 +6501,7 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos) mo->Vel.X = pr_crunch.Random2() / 16.; mo->Vel.Y = pr_crunch.Random2() / 16.; - if (thing->BloodTranslation != 0 && !(mo->flags2 & MF2_DONTTRANSLATE)) + if (thing->BloodTranslation != NO_TRANSLATION && !(mo->flags2 & MF2_DONTTRANSLATE)) { mo->Translation = thing->BloodTranslation; } diff --git a/src/playsim/p_maputl.cpp b/src/playsim/p_maputl.cpp index 16c7d183c5..8c172c479f 100644 --- a/src/playsim/p_maputl.cpp +++ b/src/playsim/p_maputl.cpp @@ -1686,7 +1686,7 @@ FPathTraverse::~FPathTraverse() // int P_CheckFov(AActor* t1, AActor* t2, double fov) { - return absangle(t1->AngleTo(t2), t1->Angles.Yaw) <= DAngle::fromDeg(fov); + return absangle(t1->AngleTo(PARAM_NULLCHECK(t2,t2)), t1->Angles.Yaw) <= DAngle::fromDeg(fov); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFov, P_CheckFov) diff --git a/src/playsim/p_maputl.h b/src/playsim/p_maputl.h index 53984f1d3a..7c89bab062 100644 --- a/src/playsim/p_maputl.h +++ b/src/playsim/p_maputl.h @@ -49,6 +49,11 @@ inline int P_PointOnLineSidePrecise(const DVector2 &pt, const linebase_t *line) return (pt.Y - line->v1->fY()) * line->Delta().X + (line->v1->fX() - pt.X) * line->Delta().Y > EQUAL_EPSILON; } +inline int P_PointOnLineSidePrecise(const DVector3& pt, const linebase_t* line) +{ + return (pt.Y - line->v1->fY()) * line->Delta().X + (line->v1->fX() - pt.X) * line->Delta().Y > EQUAL_EPSILON; +} + inline int P_PointOnLineSide (double x, double y, const line_t *line) { extern int P_VanillaPointOnLineSide(double x, double y, const line_t* line); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index be38b528d8..453ff5b788 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -99,6 +99,9 @@ #include "actorinlines.h" #include "a_dynlight.h" #include "fragglescript/t_fs.h" +#include "shadowinlines.h" +#include "model.h" +#include "d_net.h" // MACROS ------------------------------------------------------------------ @@ -120,7 +123,6 @@ EXTERN_CVAR (Int, cl_rockettrails) // PRIVATE DATA DEFINITIONS ------------------------------------------------ static FRandom pr_explodemissile ("ExplodeMissile"); -FRandom pr_bounce ("Bounce"); static FRandom pr_reflect ("Reflect"); static FRandom pr_nightmarerespawn ("NightmareRespawn"); static FRandom pr_botspawnmobj ("BotSpawnActor"); @@ -133,7 +135,6 @@ static FRandom pr_splat ("FAxeSplatter"); static FRandom pr_ripperblood ("RipperBlood"); static FRandom pr_chunk ("Chunk"); static FRandom pr_checkmissilespawn ("CheckMissileSpawn"); -static FRandom pr_spawnmissile ("SpawnMissile"); static FRandom pr_missiledamage ("MissileDamage"); static FRandom pr_multiclasschoice ("MultiClassChoice"); static FRandom pr_rockettrail("RocketTrail"); @@ -142,6 +143,8 @@ static FRandom pr_uniquetid("UniqueTID"); // PUBLIC DATA DEFINITIONS ------------------------------------------------- FRandom pr_spawnmobj ("SpawnActor"); +FRandom pr_bounce("Bounce"); +FRandom pr_spawnmissile("SpawnMissile"); CUSTOM_CVAR (Float, sv_gravity, 800.f, CVAR_SERVERINFO|CVAR_NOSAVE|CVAR_NOINITCALL) { @@ -177,6 +180,23 @@ IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(boneComponentData) IMPLEMENT_POINTERS_END +//========================================================================== +// +// Make sure Actors can never have their networking disabled. +// +//========================================================================== + +void AActor::EnableNetworking(const bool enable) +{ + if (!enable) + { + ThrowAbortException(X_OTHER, "Cannot disable networking on Actors. Consider a Thinker instead."); + return; + } + + Super::EnableNetworking(true); +} + //========================================================================== // // AActor :: Serialize @@ -233,6 +253,7 @@ void AActor::Serialize(FSerializer &arc) A("flags6", flags6) A("flags7", flags7) A("flags8", flags8) + A("flags9", flags9) A("weaponspecial", weaponspecial) A("special1", special1) A("special2", special2) @@ -308,6 +329,7 @@ void AActor::Serialize(FSerializer &arc) A("smokecounter", smokecounter) ("blockingmobj", BlockingMobj) A("blockingline", BlockingLine) + A("movementblockingline", MovementBlockingLine) A("blocking3dfloor", Blocking3DFloor) A("blockingceiling", BlockingCeiling) A("blockingfloor", BlockingFloor) @@ -370,7 +392,8 @@ void AActor::Serialize(FSerializer &arc) A("lightlevel", LightLevel) A("userlights", UserLights) A("WorldOffset", WorldOffset) - ("modelData", modelData); + ("modelData", modelData) + A("LandingSpeed", LandingSpeed); SerializeTerrain(arc, "floorterrain", floorterrain, &def->floorterrain); SerializeArgs(arc, "args", args, def->args, special); @@ -814,7 +837,7 @@ int P_GetRealMaxHealth(AActor *actor, int max) { max = actor->GetMaxHealth(true); // [MH] First step in predictable generic morph effects - if (player->morphTics) + if (actor->alternative != nullptr) { if (player->MorphStyle & MORPH_FULLHEALTH) { @@ -836,7 +859,7 @@ int P_GetRealMaxHealth(AActor *actor, int max) else { // Bonus health should be added on top of the item's limit. - if (player->morphTics == 0 || (player->MorphStyle & MORPH_ADDSTAMINA)) + if (actor->alternative == nullptr || (player->MorphStyle & MORPH_ADDSTAMINA)) { max += actor->IntVar(NAME_BonusHealth); } @@ -967,6 +990,44 @@ DEFINE_ACTION_FUNCTION(AActor, CheckLocalView) ACTION_RETURN_BOOL(self->CheckLocalView()); } +void AActor::DisableLocalRendering(const unsigned int pNum, const bool disable) +{ + if (pNum == consoleplayer) + NoLocalRender = disable; +} + +static void DisableLocalRendering(AActor* const self, const unsigned int pNum, const int disable) +{ + self->DisableLocalRendering(pNum, disable); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, DisableLocalRendering, DisableLocalRendering) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_UINT(pNum); + PARAM_INT(disable); + + DisableLocalRendering(self, pNum, disable); + return 0; +} + +bool AActor::ShouldRenderLocally() const +{ + return !NoLocalRender; +} + +static int ShouldRenderLocally(const AActor* const self) +{ + return self->ShouldRenderLocally(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, ShouldRenderLocally, ShouldRenderLocally) +{ + PARAM_SELF_PROLOGUE(AActor); + + ACTION_RETURN_INT(ShouldRenderLocally(self)); +} + //============================================================================ // // AActor :: IsInsideVisibleAngles @@ -1046,6 +1107,9 @@ bool AActor::IsVisibleToPlayer() const // [BB] Safety check. This should never be NULL. Nevertheless, we return true to leave the default ZDoom behavior unaltered. if (p == nullptr || p->camera == nullptr ) return true; + + if (!ShouldRenderLocally()) + return false; if (VisibleToTeam != 0 && teamplay && (signed)(VisibleToTeam-1) != p->userinfo.GetTeam() ) @@ -1324,16 +1388,92 @@ bool AActor::Massacre () // //---------------------------------------------------------------------------- +void SerializeModelID(FSerializer &arc, const char *key, int &id) +{ // TODO: make it a proper serializable type (FModelID) instead of an int + if(arc.isWriting()) + { + if(id >= 0) + { + arc(key, Models[id]->mFilePath); + } + } + else + { + if(arc.HasKey(key)) + { + std::pair modelFile; + arc(key, modelFile); + + id = FindModel(modelFile.first.GetChars(), modelFile.second.GetChars(), true); + } + else + { + id = -1; + } + } +} + +FSerializer &Serialize(FSerializer &arc, const char *key, ModelOverride &mo, ModelOverride *def) +{ + arc.BeginObject(key); + SerializeModelID(arc, "model", mo.modelID); + arc("surfaceSkinIDs", mo.surfaceSkinIDs); + arc.EndObject(); + return arc; +} + +FSerializer &Serialize(FSerializer &arc, const char *key, AnimModelOverride &amo, AnimModelOverride *def) +{ + int ok = arc.BeginObject(key); + if(arc.isReading() && !ok) + { + amo.id = -1; + } + else if(ok) + { + SerializeModelID(arc, "model", amo.id); + arc.EndObject(); + } + return arc; +} + +FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &ao, struct AnimOverride *def) +{ + arc.BeginObject(key); + arc("firstFrame", ao.firstFrame); + arc("lastFrame", ao.lastFrame); + arc("loopFrame", ao.loopFrame); + arc("startFrame", ao.startFrame); + arc("flags", ao.flags); + arc("framerate", ao.framerate); + arc("startTic", ao.startTic); + arc("switchTic", ao.switchTic); + arc.EndObject(); + return arc; +} + void DActorModelData::Serialize(FSerializer& arc) { Super::Serialize(arc); arc("modelDef", modelDef) - ("modelIDs", modelIDs) + ("models", models) ("skinIDs", skinIDs) - ("surfaceSkinIDs", surfaceSkinIDs) ("animationIDs", animationIDs) ("modelFrameGenerators", modelFrameGenerators) - ("hasModel", hasModel); + ("flags", flags) + ("overrideFlagsSet", overrideFlagsSet) + ("overrideFlagsClear", overrideFlagsClear) + ("curAnim", curAnim) + ("prevAnim", prevAnim); +} + +void DActorModelData::OnDestroy() +{ + models.Reset(); + modelFrameGenerators.Reset(); + skinIDs.Reset(); + //surfaceSkinIDs.Reset(); + animationIDs.Reset(); } //---------------------------------------------------------------------------- @@ -1525,6 +1665,17 @@ void AActor::PlayBounceSound(bool onfloor) bool AActor::FloorBounceMissile (secplane_t &plane) { + if (flags & MF_MISSILE) + { + switch (SpecialBounceHit(nullptr, nullptr, &plane)) + { + // This one is backwards for some reason... + case 1: return false; + case 0: return true; + default: break; + } + } + // [ZZ] if bouncing missile hits a damageable sector(plane), it dies if (P_ProjectileHitPlane(this, -1) && bouncecount > 0) { @@ -1847,7 +1998,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) { mo->Vel.MakeResize(VELOCITY_THRESHOLD); } - move = mo->Vel; + move = mo->Vel.XY(); // [RH] Carrying sectors didn't work with low speeds in BOOM. This is // because BOOM relied on the speed being fast enough to accumulate // despite friction. If the speed is too low, then its movement will get @@ -1933,7 +2084,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) // because it also calls P_CheckSlopeWalk on its clipped steps. DVector2 onestep = startmove / steps; - start = mo->Pos(); + start = mo->Pos().XY(); step = 1; totalsteps = steps; @@ -1958,7 +2109,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) ptry = start + move * step / steps; - DVector2 startvel = mo->Vel; + DVector2 startvel = mo->Vel.XY(); // killough 3/15/98: Allow objects to drop off // [RH] If walking on a slope, stay on the slope @@ -1966,7 +2117,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) { // blocked move AActor *BlockingMobj = mo->BlockingMobj; - line_t *BlockingLine = mo->BlockingLine; + line_t *BlockingLine = mo->MovementBlockingLine = mo->BlockingLine; // [ZZ] if (!BlockingLine && !BlockingMobj) // hit floor or ceiling while XY movement - sector actions @@ -2012,7 +2163,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) // If the move is done a second time (because it was too fast for one move), it // is still clipped against the wall at its full speed, so you effectively // execute two moves in one tic. - P_SlideMove (mo, mo->Vel, 1); + P_SlideMove (mo, mo->Vel.XY(), 1); } else { @@ -2026,7 +2177,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) { if (!player || !(mo->Level->i_compatflags & COMPATF_WALLRUN)) { - move = mo->Vel; + move = mo->Vel.XY(); onestep = move / steps; P_CheckSlopeWalk (mo, move); } @@ -2043,7 +2194,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) DVector2 t; t.X = 0, t.Y = onestep.Y; walkplane = P_CheckSlopeWalk (mo, t); - if (P_TryMove (mo, mo->Pos() + t, true, walkplane, tm)) + if (P_TryMove (mo, mo->Pos().XY() + t, true, walkplane, tm)) { mo->Vel.X = 0; } @@ -2051,7 +2202,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) { t.X = onestep.X, t.Y = 0; walkplane = P_CheckSlopeWalk (mo, t); - if (P_TryMove (mo, mo->Pos() + t, true, walkplane, tm)) + if (P_TryMove (mo, mo->Pos().XY() + t, true, walkplane, tm)) { mo->Vel.Y = 0; } @@ -2094,57 +2245,11 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) return Oldfloorz; } } - if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE)) + if (BlockingMobj && P_ReflectOffActor(mo, BlockingMobj)) { - bool seeker = (mo->flags2 & MF2_SEEKERMISSILE) ? true : false; - // Don't change the angle if there's THRUREFLECT on the monster. - if (!(BlockingMobj->flags7 & MF7_THRUREFLECT)) - { - DAngle angle = BlockingMobj->AngleTo(mo); - bool dontReflect = (mo->AdjustReflectionAngle(BlockingMobj, angle)); - // Change angle for deflection/reflection - - if (!dontReflect) - { - bool tg = (mo->target != NULL); - bool blockingtg = (BlockingMobj->target != NULL); - if ((BlockingMobj->flags7 & MF7_AIMREFLECT) && (tg | blockingtg)) - { - AActor *origin = tg ? mo->target : BlockingMobj->target; - - //dest->x - source->x - DVector3 vect = mo->Vec3To(origin); - vect.Z += origin->Height / 2; - mo->Vel = vect.Resized(mo->Speed); - } - else - { - if ((BlockingMobj->flags7 & MF7_MIRRORREFLECT) && (tg | blockingtg)) - { - mo->Angles.Yaw += DAngle::fromDeg(180.); - mo->Vel *= -.5; - } - else - { - mo->Angles.Yaw = angle; - mo->VelFromAngle(mo->Speed / 2); - mo->Vel.Z *= -.5; - } - } - } - else - { - goto explode; - } - } - if (mo->flags2 & MF2_SEEKERMISSILE) - { - mo->tracer = mo->target; - } - mo->target = BlockingMobj; return Oldfloorz; } -explode: + // explode a missile bool onsky = false; if (tm.ceilingline && tm.ceilingline->hitSkyWall(mo)) @@ -2208,7 +2313,7 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) move = move.Rotated(anglediff); oldangle = mo->Angles.Yaw; } - start = mo->Pos() - move * step / steps; + start = mo->Pos().XY() - move * step / steps; } } } @@ -2520,11 +2625,9 @@ static void P_ZMovement (AActor *mo, double oldfloorz) mo->SetZ(mo->floorz); if (mo->Vel.Z < 0) { - const double minvel = -8; // landing speed from a jump with normal gravity - // Spawn splashes, etc. P_HitFloor (mo); - if (mo->DamageType == NAME_Ice && mo->Vel.Z < minvel) + if (mo->DamageType == NAME_Ice && mo->Vel.Z < mo->LandingSpeed) { mo->tics = 1; mo->Vel.Zero(); @@ -2537,11 +2640,11 @@ static void P_ZMovement (AActor *mo, double oldfloorz) } if (mo->player) { - if (mo->player->jumpTics < 0 || mo->Vel.Z < minvel) + if (mo->player->jumpTics < 0 || mo->Vel.Z < mo->LandingSpeed) { // delay any jumping for a short while mo->player->jumpTics = 7; } - if (mo->Vel.Z < minvel && !(mo->flags & MF_NOGRAVITY)) + if (mo->Vel.Z < mo->LandingSpeed && !(mo->flags & MF_NOGRAVITY)) { // Squat down. // Decrease viewheight for a moment after hitting the ground (hard), @@ -2891,7 +2994,7 @@ void P_NightmareRespawn (AActor *mobj) } // something is occupying its position? - if (!P_CheckPosition(mo, mo->Pos(), true)) + if (!P_CheckPosition(mo, mo->Pos().XY(), true)) { //[GrafZahl] MF_COUNTKILL still needs to be checked here. mo->ClearCounters(); @@ -2920,7 +3023,7 @@ void P_NightmareRespawn (AActor *mobj) P_SpawnTeleportFog(mobj, mobj->Pos(), true, true); // spawn a teleport fog at the new spot - P_SpawnTeleportFog(mobj, DVector3(mobj->SpawnPoint, z), false, true); + P_SpawnTeleportFog(mobj, DVector3(mobj->SpawnPoint.XY(), z), false, true); // remove the old monster mobj->Destroy (); @@ -3222,6 +3325,21 @@ int AActor::SpecialMissileHit (AActor *victim) else return -1; } +// This virtual method only exists on the script side. +int AActor::SpecialBounceHit(AActor* bounceMobj, line_t* bounceLine, secplane_t* bouncePlane) +{ + IFVIRTUAL(AActor, SpecialBounceHit) + { + VMValue params[4] = { (DObject*)this, bounceMobj, bounceLine, bouncePlane }; + VMReturn ret; + int retval; + ret.IntAt(&retval); + VMCall(func, params, 4, &ret, 1); + return retval; + } + else return -1; +} + bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle) { if (flags2 & MF2_DONTREFLECT) return true; @@ -3230,11 +3348,9 @@ bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle) if (thing->flags4&MF4_SHIELDREFLECT) { // Shield reflection (from the Centaur) - if (absangle(angle, thing->Angles.Yaw) > DAngle::fromDeg(45)) + if ((flags7 & MF7_NOSHIELDREFLECT) || absangle(angle, thing->Angles.Yaw) > DAngle::fromDeg(45)) return true; // Let missile explode - if (thing->flags7 & MF7_NOSHIELDREFLECT) return true; - if (pr_reflect () < 128) angle += DAngle::fromDeg(45); else @@ -3436,22 +3552,16 @@ void AActor::SetPitch(DAngle p, int fflags) { if (player != nullptr) { - const bool mustLerp = !P_NoInterpolation(player, this); - - if ((fflags & SPF_INTERPOLATE) || ((fflags & SPF_SCALEDNOLERP) && mustLerp)) - { - Angles.Pitch = p; - player->cheats |= CF_INTERPVIEW; - } - else if ((fflags & SPF_SCALEDNOLERP) && !mustLerp) + if (fflags & SPF_SCALEDNOLERP) { - player->angleTargets.Pitch = deltaangle(Angles.Pitch, p); - player->angleAppliedAmounts.Pitch = nullAngle; + player->angleOffsetTargets.Pitch = deltaangle(Angles.Pitch, p); player->cheats |= CF_SCALEDNOLERP; } else { Angles.Pitch = p; + if (fflags & SPF_INTERPOLATE) + player->cheats |= CF_INTERPVIEW; } } else @@ -3468,22 +3578,16 @@ void AActor::SetAngle(DAngle ang, int fflags) { if (player != nullptr) { - const bool mustLerp = !P_NoInterpolation(player, this); - - if ((fflags & SPF_INTERPOLATE) || ((fflags & SPF_SCALEDNOLERP) && mustLerp)) - { - Angles.Yaw = ang; - player->cheats |= CF_INTERPVIEW; - } - else if ((fflags & SPF_SCALEDNOLERP) && !mustLerp) + if (fflags & SPF_SCALEDNOLERP) { - player->angleTargets.Yaw = deltaangle(Angles.Yaw, ang); - player->angleAppliedAmounts.Yaw = nullAngle; + player->angleOffsetTargets.Yaw = deltaangle(Angles.Yaw, ang); player->cheats |= CF_SCALEDNOLERP; } else { Angles.Yaw = ang; + if (fflags & SPF_INTERPOLATE) + player->cheats |= CF_INTERPVIEW; } } else @@ -3500,22 +3604,16 @@ void AActor::SetRoll(DAngle r, int fflags) { if (player != nullptr) { - const bool mustLerp = !P_NoInterpolation(player, this); - - if ((fflags & SPF_INTERPOLATE) || ((fflags & SPF_SCALEDNOLERP) && mustLerp)) - { - Angles.Roll = r; - player->cheats |= CF_INTERPVIEW; - } - else if ((fflags & SPF_SCALEDNOLERP) && !mustLerp) + if (fflags & SPF_SCALEDNOLERP) { - player->angleTargets.Roll = deltaangle(Angles.Roll, r); - player->angleAppliedAmounts.Roll = nullAngle; + player->angleOffsetTargets.Roll = deltaangle(Angles.Roll, r); player->cheats |= CF_SCALEDNOLERP; } else { Angles.Roll = r; + if (fflags & SPF_INTERPOLATE) + player->cheats |= CF_INTERPVIEW; } } else @@ -3708,6 +3806,22 @@ void AActor::Tick () static const uint8_t HereticScrollDirs[4] = { 6, 9, 1, 4 }; static const uint8_t HereticSpeedMuls[5] = { 5, 10, 25, 30, 35 }; + // Check for Actor unmorphing, but only on the thing that is the morphed Actor. + // Players do their own special checking for this. + if (alternative != nullptr && !(flags & MF_UNMORPHED) && player == nullptr) + { + int res = false; + IFVIRTUAL(AActor, CheckUnmorph) + { + VMValue params[] = { this }; + VMReturn ret[] = { &res }; + VMCall(func, params, 1, ret, 1); + } + + if (res) + return; + } + if (freezetics > 0) { freezetics--; @@ -3755,7 +3869,8 @@ void AActor::Tick () } else { - + if (player) + player->crossingPortal = false; if (!player || !(player->cheats & CF_PREDICTING)) { // Handle powerup effects here so that the order is controlled @@ -4085,6 +4200,7 @@ void AActor::Tick () // Handle X and Y velocities BlockingMobj = nullptr; + MovementBlockingLine = nullptr; sector_t* oldBlockingCeiling = BlockingCeiling; sector_t* oldBlockingFloor = BlockingFloor; Blocking3DFloor = nullptr; @@ -4732,6 +4848,7 @@ AActor *AActor::StaticSpawn(FLevelLocals *Level, PClassActor *type, const DVecto AActor *actor; actor = static_cast(Level->CreateThinker(type)); + actor->EnableNetworking(true); ConstructActor(actor, pos, SpawningMapThing); return actor; @@ -5000,6 +5117,16 @@ void AActor::CallDeactivate(AActor *activator) void AActor::OnDestroy () { + // If the Actor is leaving behind a premorph Actor, make sure it gets cleaned up as + // well so it's not stuck in the map. + if (alternative != nullptr && !(flags & MF_UNMORPHED)) + { + alternative->ClearCounters(); + alternative->alternative = nullptr; + alternative->Destroy(); + alternative = nullptr; + } + // [ZZ] call destroy event hook. // note that this differs from ThingSpawned in that you can actually override OnDestroy to avoid calling the hook. // but you can't really do that without utterly breaking the game, so it's ok. @@ -5121,59 +5248,157 @@ extern bool demonew; //========================================================================== // -// This once was the main method for pointer cleanup, but -// nowadays its only use is swapping out PlayerPawns. -// This requires pointer fixing throughout all objects and a few -// global variables, but it only needs to look at pointers that -// can point to a player. +// This function is only designed for swapping player pawns +// over to their new ones upon changing levels or respawning. It SHOULD NOT be +// used for anything else! Do not export this functionality as it's +// meant strictly for internal usage. // //========================================================================== -void StaticPointerSubstitution(AActor* old, AActor* notOld) +void PlayerPointerSubstitution(AActor* oldPlayer, AActor* newPlayer, bool removeOld) { - DObject* probe; - size_t changed = 0; - int i; + if (oldPlayer == nullptr || newPlayer == nullptr || oldPlayer == newPlayer + || !oldPlayer->IsKindOf(NAME_PlayerPawn) || !newPlayer->IsKindOf(NAME_PlayerPawn)) + { + return; + } + + // Go through player infos. + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (!oldPlayer->Level->PlayerInGame(i)) + continue; + + auto p = oldPlayer->Level->Players[i]; - if (old == nullptr) return; + if (p->mo == oldPlayer) + p->mo = newPlayer; + if (p->poisoner == oldPlayer) + p->poisoner = newPlayer; + if (p->attacker == oldPlayer) + p->attacker = newPlayer; + if (p->camera == oldPlayer) + p->camera = newPlayer; + if (p->ConversationNPC == oldPlayer) + p->ConversationNPC = newPlayer; + if (p->ConversationPC == oldPlayer) + p->ConversationPC = newPlayer; + } - // This is only allowed to replace players or swap out morphed monsters - if (!old->IsKindOf(NAME_PlayerPawn) || (notOld != nullptr && !notOld->IsKindOf(NAME_PlayerPawn))) + // Go through sectors. + for (auto& sec : oldPlayer->Level->sectors) { - if (notOld == nullptr) return; - if (!old->IsKindOf(NAME_MorphedMonster) && !notOld->IsKindOf(NAME_MorphedMonster)) return; + if (sec.SoundTarget == oldPlayer) + sec.SoundTarget = newPlayer; } - // Go through all objects. - i = 0; DObject* last = 0; - for (probe = GC::Root; probe != NULL; probe = probe->ObjNext) + + // Update all the remaining object pointers. + for (DObject* probe = GC::Root; probe != nullptr; probe = probe->ObjNext) + probe->PointerSubstitution(oldPlayer, newPlayer, removeOld); +} + +//========================================================================== +// +// This has some extra barriers compared to PlayerPointerSubstitution to allow +// Actors to freely morph into other Actors which is its main usage. +// It also allows morphing to be more extendable from ZScript. +// +//========================================================================== + +int MorphPointerSubstitution(AActor* from, AActor* to) +{ + // Special care is taken here to make sure things marked as a dummy Actor for a morphed thing aren't + // allowed to be changed into other things. Anything being morphed into that's considered a player + // is automatically out of the question to ensure modders aren't swapping clients around. + if (from == nullptr || to == nullptr || from == to || to->player != nullptr + || (from->flags & MF_UNMORPHED) // Another thing's dummy Actor, unmorphing the wrong way, etc. + || (from->alternative == nullptr && to->alternative != nullptr) // Morphing into something that's already morphed. + || (from->alternative != nullptr && from->alternative != to)) // Only allow something morphed to unmorph. { - i++; - changed += probe->PointerSubstitution(old, notOld); - last = probe; + return false; } - // Go through players. - for (i = 0; i < MAXPLAYERS; i++) + const bool toIsPlayer = to->IsKindOf(NAME_PlayerPawn); + if (from->IsKindOf(NAME_PlayerPawn)) { - if (playeringame[i]) - { - AActor* replacement = notOld; - auto& p = players[i]; + // Players are only allowed to turn into other valid player pawns. For + // valid pawns, make sure an actual player is changing into an empty one. + // Voodoo dolls aren't allowed to morph since that should be passed to + // the main player directly. + if (!toIsPlayer || from->player == nullptr || from->player->mo != from) + return false; + } + else if (toIsPlayer || from->player != nullptr + || (from->IsKindOf(NAME_Inventory) && from->PointerVar(NAME_Owner) != nullptr) + || (to->IsKindOf(NAME_Inventory) && to->PointerVar(NAME_Owner) != nullptr)) + { + // Only allow items to be swapped around if they aren't currently owned. Also prevent non-players from + // turning into fake players. + return false; + } - if (p.mo == old) p.mo = replacement, changed++; - if (p.poisoner.ForceGet() == old) p.poisoner = replacement, changed++; - if (p.attacker.ForceGet() == old) p.attacker = replacement, changed++; - if (p.camera.ForceGet() == old) p.camera = replacement, changed++; - if (p.ConversationNPC.ForceGet() == old) p.ConversationNPC = replacement, changed++; - if (p.ConversationPC.ForceGet() == old) p.ConversationPC = replacement, changed++; - } + // Since the check is good, move the inventory items over. This should always be done when + // morphing to emulate Heretic/Hexen's behavior since those stored the inventory in their + // player structs. + IFVM(Actor, ObtainInventory) + { + VMValue params[] = { to, from }; + VMCall(func, params, 2, nullptr, 0); + } + + // Go through player infos. + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (!from->Level->PlayerInGame(i)) + continue; + + auto p = from->Level->Players[i]; + + if (p->mo == from) + p->mo = to; + if (p->poisoner == from) + p->poisoner = to; + if (p->attacker == from) + p->attacker = to; + if (p->camera == from) + p->camera = to; + if (p->ConversationNPC == from) + p->ConversationNPC = to; + if (p->ConversationPC == from) + p->ConversationPC = to; + } + + // Go through sectors. + for (auto& sec : from->Level->sectors) + { + if (sec.SoundTarget == from) + sec.SoundTarget = to; + } + + // Replace any object pointers that are safe to swap around. + for (DObject* probe = GC::Root; probe != nullptr; probe = probe->ObjNext) + probe->PointerSubstitution(from, to, false); + + // Remaining maintenance related to morphing. + if (from->player != nullptr) + { + to->player = from->player; + from->player = nullptr; } - // Go through sectors. Only the level this actor belongs to is relevant. - for (auto& sec : old->Level->sectors) + if (from->alternative != nullptr) + { + to->flags &= ~MF_UNMORPHED; + to->alternative = from->alternative = nullptr; + } + else { - if (sec.SoundTarget == old) sec.SoundTarget = notOld; + from->flags |= MF_UNMORPHED; + from->alternative = to; + to->alternative = from; } + + return true; } void FLevelLocals::PlayerSpawnPickClass (int playernum) @@ -5283,6 +5508,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag p->mo = mobj; mobj->player = p; state = p->playerstate; + const auto heldWeap = state == PST_REBORN && (dmflags3 & DF3_REMEMBER_LAST_WEAP) ? p->ReadyWeapon : nullptr; if (state == PST_REBORN || state == PST_ENTER) { PlayerReborn (playernum); @@ -5299,7 +5525,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag } // [GRB] Reset skin - p->userinfo.SkinNumChanged(R_FindSkin (Skins[p->userinfo.GetSkin()].Name, p->CurrentPlayerClass)); + p->userinfo.SkinNumChanged(R_FindSkin (Skins[p->userinfo.GetSkin()].Name.GetChars(), p->CurrentPlayerClass)); if (!(mobj->flags2 & MF2_DONTTRANSLATE)) { @@ -5383,7 +5609,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag { // Special inventory handling for respawning in coop IFVM(PlayerPawn, FilterCoopRespawnInventory) { - VMValue params[] = { p->mo, oldactor }; + VMValue params[] = { p->mo, oldactor, ((heldWeap == nullptr || (heldWeap->ObjectFlags & OF_EuthanizeMe)) ? nullptr : heldWeap) }; VMCall(func, params, 2, nullptr, 0); } } @@ -5446,7 +5672,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag if (sec.SoundTarget == oldactor) sec.SoundTarget = nullptr; } - StaticPointerSubstitution (oldactor, p->mo); + PlayerPointerSubstitution (oldactor, p->mo, false); localEventManager->PlayerRespawned(PlayerNum(p)); Behaviors.StartTypedScripts (SCRIPT_Respawn, p->mo, true); @@ -5681,15 +5907,26 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) const AActor *info = GetDefaultByType (i); - // don't spawn keycards and players in deathmatch - if (deathmatch && info->flags & MF_NOTDMATCH) - return NULL; + // Don't spawn keycards and players in deathmatch. + if (deathmatch && (info->flags & MF_NOTDMATCH)) + return nullptr; - // don't spawn extra things in coop if so desired - if (multiplayer && !deathmatch && (dmflags2 & DF2_NO_COOP_THING_SPAWN)) + // Don't spawn extra things in co-op if desired. + if (multiplayer && !deathmatch) { - if ((mthing->flags & (MTF_DEATHMATCH|MTF_SINGLE)) == MTF_DEATHMATCH) - return NULL; + // Don't spawn DM-only things in co-op. + if ((dmflags2 & DF2_NO_COOP_THING_SPAWN) && (mthing->flags & (MTF_DEATHMATCH|MTF_SINGLE)) == MTF_DEATHMATCH) + return nullptr; + // Having co-op only functionality is a bit odd, but you never know. + if (!mthing->special && !mthing->thingid && (mthing->flags & (MTF_COOPERATIVE | MTF_SINGLE)) == MTF_COOPERATIVE) + { + // Don't spawn co-op only things in general. + if (dmflags3 & DF3_NO_COOP_ONLY_THINGS) + return nullptr; + // Don't spawn co-op only items. + if ((dmflags3 & DF3_NO_COOP_ONLY_ITEMS) && i->IsDescendantOf(NAME_Inventory)) + return nullptr; + } } // [RH] don't spawn extra weapons in coop if so desired @@ -5728,7 +5965,7 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) else sz = ONFLOORZ; - mobj = AActor::StaticSpawn (this, i, DVector3(mthing->pos, sz), NO_REPLACE, true); + mobj = AActor::StaticSpawn (this, i, DVector3(mthing->pos.XY(), sz), NO_REPLACE, true); if (sz == ONFLOORZ) { @@ -5809,6 +6046,8 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) if (mthing->fillcolor) mobj->fillcolor = (mthing->fillcolor & 0xffffff) | (ColorMatcher.Pick((mthing->fillcolor & 0xff0000) >> 16, (mthing->fillcolor & 0xff00) >> 8, (mthing->fillcolor & 0xff)) << 24); + if (mthing->SourceRadius >= 0.0) + mobj->SourceRadius = mthing->SourceRadius; // allow color strings for lights and reshuffle the args for spot lights if (i->IsDescendantOf(NAME_DynamicLight)) @@ -6538,7 +6777,7 @@ bool P_CheckMissileSpawn (AActor* th, double maxdist) // killough 3/15/98: no dropoff (really = don't care for missiles) auto oldf2 = th->flags2; th->flags2 &= ~(MF2_MCROSS|MF2_PCROSS); // The following check is not supposed to activate missile triggers. - if (!(P_TryMove (th, newpos, false, NULL, tm, true))) + if (!(P_TryMove (th, newpos.XY(), false, NULL, tm, true))) { // [RH] Don't explode ripping missiles that spawn inside something if (th->BlockingMobj == NULL || !(th->flags2 & MF2_RIP) || (th->BlockingMobj->flags5 & MF5_DONTRIP)) @@ -6647,7 +6886,7 @@ AActor *P_SpawnMissileXYZ (DVector3 pos, AActor *source, AActor *dest, PClassAct if (dest == NULL) { - Printf ("P_SpawnMissilyXYZ: Tried to shoot %s from %s with no dest\n", + Printf ("P_SpawnMissileXYZ: Tried to shoot %s from %s with no destination\n", type->TypeName.GetChars(), source->GetClass()->TypeName.GetChars()); return NULL; } @@ -6686,21 +6925,8 @@ AActor *P_SpawnMissileXYZ (DVector3 pos, AActor *source, AActor *dest, PClassAct } th->Vel = velocity.Resized(speed); - // invisible target: rotate velocity vector in 2D - // [RC] Now monsters can aim at invisible player as if they were fully visible. - if (dest->flags & MF_SHADOW && !(source->flags6 & MF6_SEEINVISIBLE)) - { - DAngle an = DAngle::fromDeg(pr_spawnmissile.Random2() * (22.5 / 256)); - double c = an.Cos(); - double s = an.Sin(); - - double newx = th->Vel.X * c - th->Vel.Y * s; - double newy = th->Vel.X * s + th->Vel.Y * c; - - th->Vel.X = newx; - th->Vel.Y = newy; - } - + P_SpawnMissileXYZ_ShadowHandling(source,dest,th,pos); + th->AngleFromVel(); if (th->flags4 & MF4_SPECTRAL) @@ -6821,14 +7047,11 @@ AActor *P_SpawnMissileZAimed (AActor *source, double z, AActor *dest, PClassActo an = source->Angles.Yaw; - if (dest->flags & MF_SHADOW) - { - an += DAngle::fromDeg(pr_spawnmissile.Random2() * (16. / 360.)); - } dist = source->Distance2D (dest); speed = GetDefaultSpeed (type); dist /= speed; vz = dist != 0 ? (dest->Z() - source->Z())/dist : speed; + an += P_SpawnMissileZAimed_ShadowHandling(source, dest, vz, speed, source->PosAtZ(z)); return P_SpawnMissileAngleZSpeed (source, z, type, an, vz, speed); } @@ -7479,7 +7702,7 @@ const char *AActor::GetTag(const char *def) const const char *tag = Tag->GetChars(); if (tag[0] == '$') { - return GStrings(tag + 1); + return GStrings.GetString(tag + 1); } else { @@ -7509,7 +7732,7 @@ const char *AActor::GetCharacterName() const const char *cname = Conversation->SpeakerName.GetChars(); if (cname[0] == '$') { - return GStrings(cname + 1); + return GStrings.GetString(cname + 1); } else return cname; } @@ -7574,8 +7797,8 @@ void AActor::SetTranslation(FName trname) return; } - int tnum = R_FindCustomTranslation(trname); - if (tnum >= 0) + auto tnum = R_FindCustomTranslation(trname); + if (tnum != INVALID_TRANSLATION) { Translation = tnum; } @@ -7592,7 +7815,7 @@ static FRandom pr_restore("RestorePos"); void AActor::RestoreSpecialPosition() { // Move item back to its original location - DVector2 sp = SpawnPoint; + DVector2 sp = SpawnPoint.XY(); FLinkContext ctx; UnlinkFromWorld(&ctx); @@ -7693,6 +7916,9 @@ void PrintMiscActorInfo(AActor *query) Printf("\n flags8: %x", query->flags8.GetValue()); for (flagi = 0; flagi <= 31; flagi++) if (query->flags8 & ActorFlags8::FromInt(1<flags9.GetValue()); + for (flagi = 0; flagi <= 31; flagi++) + if (query->flags9 & ActorFlags9::FromInt(1 << flagi)) Printf(" %s", FLAG_NAME(1 << flagi, flags9)); Printf("\nBounce flags: %x\nBounce factors: f:%f, w:%f", query->BounceFlags.GetValue(), query->bouncefactor, query->wallbouncefactor); diff --git a/src/playsim/p_pspr.cpp b/src/playsim/p_pspr.cpp index b32ce67e66..923923420b 100644 --- a/src/playsim/p_pspr.cpp +++ b/src/playsim/p_pspr.cpp @@ -171,7 +171,7 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) InterpolateTic(false), firstTic(true), Tics(0), - Translation(0), + Translation(NO_TRANSLATION), Flags(0), Owner(owner), State(nullptr), @@ -326,6 +326,13 @@ DPSprite *player_t::GetPSprite(PSPLayers layer) else { oldcaller = pspr->Caller; + + // update scaling properties here + if (newcaller != nullptr && newcaller->IsKindOf(NAME_Weapon)) + { + pspr->baseScale.X = newcaller->FloatVar(NAME_WeaponScaleX); + pspr->baseScale.Y = newcaller->FloatVar(NAME_WeaponScaleY); + } } // Always update the caller here in case we switched weapon @@ -556,7 +563,7 @@ void DPSprite::SetState(FState *newstate, bool pending) { // If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash. Printf(TEXTCOLOR_RED "Unsafe state call in state %sd to %s which accesses user variables. The action function has been removed from this state\n", - FState::StaticGetStateName(newstate).GetChars(), newstate->ActionFunc->PrintableName.GetChars()); + FState::StaticGetStateName(newstate).GetChars(), newstate->ActionFunc->PrintableName); newstate->ActionFunc = nullptr; } if (newstate->CallAction(Owner->mo, Caller, &stp, &nextstate)) @@ -634,6 +641,19 @@ void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac) DVector2 result; VMReturn ret(&result); VMCall(func, param, 2, &ret, 1); + + auto inv = player->mo->Inventory; + while(inv != nullptr && !(inv->ObjectFlags & OF_EuthanizeMe)) // same loop as ModifyDamage, except it actually checks if it's overriden before calling + { + auto nextinv = inv->Inventory; + IFOVERRIDENVIRTUALPTRNAME(inv, NAME_Inventory, ModifyBob) + { + VMValue param[] = { (DObject*)inv, result.X, result.Y, ticfrac }; + VMCall(func, param, 4, &ret, 1); + } + inv = nextinv; + } + *x = (float)result.X; *y = (float)result.Y; return; @@ -641,7 +661,8 @@ void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac) *x = *y = 0; } -void P_BobWeapon3D (player_t *player, FVector3 *translation, FVector3 *rotation, double ticfrac) { +void P_BobWeapon3D (player_t *player, FVector3 *translation, FVector3 *rotation, double ticfrac) +{ IFVIRTUALPTRNAME(player->mo, NAME_PlayerPawn, BobWeapon3D) { VMValue param[] = { player->mo, ticfrac }; @@ -650,6 +671,19 @@ void P_BobWeapon3D (player_t *player, FVector3 *translation, FVector3 *rotation, returns[0].Vec3At(&t); returns[1].Vec3At(&r); VMCall(func, param, 2, returns, 2); + + auto inv = player->mo->Inventory; + while(inv != nullptr && !(inv->ObjectFlags & OF_EuthanizeMe)) + { + auto nextinv = inv->Inventory; + IFOVERRIDENVIRTUALPTRNAME(inv, NAME_Inventory, ModifyBob3D) + { + VMValue param[] = { (DObject*)inv, t.X, t.Y, t.Z, r.X, r.Y, r.Z, ticfrac }; + VMCall(func, param, 8, returns, 2); + } + inv = nextinv; + } + translation->X = (float)t.X; translation->Y = (float)t.Y; translation->Z = (float)t.Z; @@ -959,9 +993,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayPivotAlign) if (pspr != nullptr) { if (halign >= PSPA_LEFT && halign <= PSPA_RIGHT) - pspr->HAlign |= halign; + pspr->HAlign = halign; if (valign >= PSPA_TOP && valign <= PSPA_BOTTOM) - pspr->VAlign |= valign; + pspr->VAlign = valign; } return 0; } @@ -989,12 +1023,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayTranslation) { // an empty string resets to the default // (unlike AActor::SetTranslation, there is no Default block for PSprites, so just set the translation to 0) - pspr->Translation = 0; + pspr->Translation = NO_TRANSLATION; return 0; } - int tnum = R_FindCustomTranslation(trname); - if (tnum >= 0) + auto tnum = R_FindCustomTranslation(trname); + if (tnum != INVALID_TRANSLATION) { pspr->Translation = tnum; } @@ -1344,25 +1378,35 @@ void P_SetSafeFlash(AActor *weapon, player_t *player, FState *flashstate, int in P_SetPsprite(player, PSP_FLASH, flashstate + index, true); return; } - else + else if (flashstate->DehIndex < 0) { - // oh, no! The state is beyond the end of the state table so use the original flash state. + // oh, no! The state is beyond the end of the state table so use the original flash state if it does not have a Dehacked index. P_SetPsprite(player, PSP_FLASH, flashstate, true); return; } + else break; // no need to continue. } // try again with parent class cls = static_cast(cls->ParentClass); } - // if we get here the state doesn't seem to belong to any class in the inheritance chain - // This can happen with Dehacked if the flash states are remapped. - // The only way to check this would be to go through all Dehacked modifiable actors, convert - // their states into a single flat array and find the correct one. - // Rather than that, just check to make sure it belongs to something. - if (FState::StaticFindStateOwner(flashstate + index) == NULL) - { // Invalid state. With no index offset, it should at least be valid. - index = 0; + + // if we get here the target state doesn't belong to any class in the inheritance chain. + // This can happen with Dehacked if the flash states are remapped. + // In this case we should check the Dehacked state map to get the proper state. + if (flashstate->DehIndex >= 0) + { + auto pTargetstate = dehExtStates.CheckKey(flashstate->DehIndex + index); + if (pTargetstate) + { + P_SetPsprite(player, PSP_FLASH, *pTargetstate, true); + return; + } } + + // If we still haven't found anything here, just use the base flash state. + // Normally this code should not be reachable. + index = 0; + } P_SetPsprite(player, PSP_FLASH, flashstate + index, true); } diff --git a/src/playsim/p_pspr.h b/src/playsim/p_pspr.h index 85add7b6bf..de019e62fc 100644 --- a/src/playsim/p_pspr.h +++ b/src/playsim/p_pspr.h @@ -31,6 +31,7 @@ #define __P_PSPR_H__ #include "renderstyle.h" +#include "palettecontainer.h" // Basic data types. // Needs fixed point, and BAM angles. @@ -104,7 +105,7 @@ class DPSprite : public DObject int GetSprite() const { return Sprite; } int GetFrame() const { return Frame; } int GetTics() const { return Tics; } - uint32_t GetTranslation() { return Translation; } + FTranslationID GetTranslation() { return Translation; } FState* GetState() const { return State; } DPSprite* GetNext() { return Next; } AActor* GetCaller() { return Caller; } @@ -127,7 +128,7 @@ class DPSprite : public DObject WeaponInterp Vert; // Current Position bool firstTic; int Tics; - uint32_t Translation; + FTranslationID Translation; int Flags; FRenderStyle Renderstyle; diff --git a/src/playsim/p_secnodes.cpp b/src/playsim/p_secnodes.cpp index f43b0e30e3..e19846c750 100644 --- a/src/playsim/p_secnodes.cpp +++ b/src/playsim/p_secnodes.cpp @@ -414,7 +414,7 @@ void AActor::UpdateRenderSectorList() if (planeh <= lasth) break; // broken setup. if (Top() + SPRITE_SPACE < planeh) break; lasth = planeh; - DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::ceiling); + DVector2 newpos = Pos().XY() + sec->GetPortalDisplacement(sector_t::ceiling); sec = sec->Level->PointInSector(newpos); touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); } @@ -426,7 +426,7 @@ void AActor::UpdateRenderSectorList() if (planeh >= lasth) break; // broken setup. if (Z() - SPRITE_SPACE > planeh) break; lasth = planeh; - DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::floor); + DVector2 newpos = Pos().XY() + sec->GetPortalDisplacement(sector_t::floor); sec = sec->Level->PointInSector(newpos); touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); } diff --git a/src/playsim/p_sectors.cpp b/src/playsim/p_sectors.cpp index a194f177ad..a9014c2ce2 100644 --- a/src/playsim/p_sectors.cpp +++ b/src/playsim/p_sectors.cpp @@ -1637,3 +1637,4 @@ void vertex_t::RecalcVertexHeights() if (numheights <= 2) numheights = 0; // is not in need of any special attention dirty = false; } + diff --git a/src/playsim/p_sight.cpp b/src/playsim/p_sight.cpp index b5564346ae..2cf957c8ce 100644 --- a/src/playsim/p_sight.cpp +++ b/src/playsim/p_sight.cpp @@ -127,7 +127,7 @@ class SightCheck void init(AActor * t1, AActor * t2, sector_t *startsector, SightTask *task, int flags) { sightstart = t1->PosRelative(task->portalgroup); - sightend = t2->PosRelative(task->portalgroup); + sightend = t2->PosRelative(task->portalgroup).XY(); sightstart.Z += t1->Height * 0.75; portalgroup = task->portalgroup; diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index 52760d9358..c0bfca34ad 100644 --- a/src/playsim/p_spec.cpp +++ b/src/playsim/p_spec.cpp @@ -619,7 +619,7 @@ void P_GiveSecret(FLevelLocals *Level, AActor *actor, bool printmessage, bool pl { if (printmessage) { - C_MidPrint(nullptr, GStrings["SECRETMESSAGE"]); + C_MidPrint(nullptr, GStrings.CheckString("SECRETMESSAGE")); if (showsecretsector && sectornum >= 0) { Printf(PRINT_HIGH | PRINT_NONOTIFY, "Secret found in sector %d\n", sectornum); @@ -696,7 +696,7 @@ void P_UpdateSpecials (FLevelLocals *Level) { if (Level->maptime >= (int)(timelimit * TICRATE * 60)) { - Printf ("%s\n", GStrings("TXT_TIMELIMIT")); + Printf ("%s\n", GStrings.GetString("TXT_TIMELIMIT")); Level->ExitLevel(0, false); } } diff --git a/src/playsim/p_spec.h b/src/playsim/p_spec.h index a0918da917..5d602eb1db 100644 --- a/src/playsim/p_spec.h +++ b/src/playsim/p_spec.h @@ -164,7 +164,7 @@ void P_TerminateScript (FLevelLocals *Level, int script, const char *map); // // [RH] p_quake.c // -bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double intensityX, double intensityY, double intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave); -bool P_StartQuake(FLevelLocals *Level, AActor *activator, int tid, double intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); +bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double intensityX, double intensityY, double intensityZ, int duration, double damrad, double tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, double falloff, int highpoint, double rollIntensity, double rollWave, double damageMultiplier, double thrustMultiplier, int damage); +bool P_StartQuake(FLevelLocals *Level, AActor *activator, int tid, double intensity, int duration, double damrad, double tremrad, FSoundID quakesfx); #endif diff --git a/src/playsim/p_switch.cpp b/src/playsim/p_switch.cpp index 73aa95daac..e89f030114 100644 --- a/src/playsim/p_switch.cpp +++ b/src/playsim/p_switch.cpp @@ -195,11 +195,14 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno, const DVector3 * } } - return (user->Level->i_compatflags2 & COMPATF2_CHECKSWITCHRANGE) + if ((user->Level->i_compatflags2 & COMPATF2_CHECKSWITCHRANGE) ? (user->Top() >= open.top) - : (user->Top() > open.top); + : (user->Top() > open.top)) + { + return true; + } } - else if ((TexAnim.FindSwitch(side->GetTexture(side_t::bottom))) != NULL) + if ((TexAnim.FindSwitch(side->GetTexture(side_t::bottom))) != NULL) { // Check 3D floors on back side { @@ -219,11 +222,14 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno, const DVector3 * } } - return (user->Level->i_compatflags2 & COMPATF2_CHECKSWITCHRANGE) + if ((user->Level->i_compatflags2 & COMPATF2_CHECKSWITCHRANGE) ? (user->Z() <= open.bottom) - : (user->Z() < open.bottom); + : (user->Z() < open.bottom)) + { + return true; + } } - else if ((flags & ML_3DMIDTEX) || (TexAnim.FindSwitch(side->GetTexture(side_t::mid))) != NULL) + if ((flags & ML_3DMIDTEX) || (TexAnim.FindSwitch(side->GetTexture(side_t::mid))) != NULL) { // 3DMIDTEX lines will force a mid texture check if no switch is found on this line // to keep compatibility with Eternity's implementation. diff --git a/src/playsim/p_tags.cpp b/src/playsim/p_tags.cpp index ae5ba5727a..591fcb0ed8 100644 --- a/src/playsim/p_tags.cpp +++ b/src/playsim/p_tags.cpp @@ -111,7 +111,7 @@ void FTagManager::RemoveLineIDs(int line) { while (allIDs[start].target == line) { - allTags[start].tag = allTags[start].target = -1; + allIDs[start].tag = allIDs[start].target = -1; start++; } } @@ -314,6 +314,96 @@ void FTagManager::DumpTags() } } +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +int FTagManager::CountSectorTags(const sector_t *sector) +{ + int i = sector->Index(); + + if (SectorHasTags(i)) + { + const int n = allTags.Size(); + + int j = startForSector[i]; + int c = 0; + + while(j < n && allTags[j].target == i) + { + j++; + c++; + } + + return c; + } + + return 0; +} + +int FTagManager::GetSectorTag(const sector_t *sector, int index) +{ + int i = sector->Index(); + + if (SectorHasTags(i)) + { + const int n = allTags.Size(); + + int j = startForSector[i] + index; + + return (j < n && allTags[j].target == i) ? allTags[j].tag : 0; + } + + return 0; +} + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +int FTagManager::CountLineIDs(const line_t *line) +{ + int i = line->Index(); + + if (LineHasIDs(i)) + { + const int n = allIDs.Size(); + + int j = startForLine[i]; + int c = 0; + + while(j < n && allIDs[j].target == i) + { + j++; + c++; + } + + return c; + } + + return 0; +} + +int FTagManager::GetLineID(const line_t *line, int index) +{ + int i = line->Index(); + + if (LineHasIDs(i)) + { + const int n = allIDs.Size(); + + int j = startForLine[i] + index; + + return (j < n && allIDs[j].target == i) ? allIDs[j].tag : 0; + } + + return 0; +} + //----------------------------------------------------------------------------- // // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO diff --git a/src/playsim/p_tags.h b/src/playsim/p_tags.h index 7452ef755d..aee44fbd45 100644 --- a/src/playsim/p_tags.h +++ b/src/playsim/p_tags.h @@ -77,6 +77,12 @@ class FTagManager void RemoveLineIDs(int line); void DumpTags(); + + int CountSectorTags(const sector_t *sector); + int GetSectorTag(const sector_t *sector, int index); + + int CountLineIDs(const line_t *line); + int GetLineID(const line_t *line, int index); }; class FSectorTagIterator diff --git a/src/playsim/p_teleport.cpp b/src/playsim/p_teleport.cpp index fb2217ef0c..1643b1b762 100644 --- a/src/playsim/p_teleport.cpp +++ b/src/playsim/p_teleport.cpp @@ -60,7 +60,7 @@ void P_SpawnTeleportFog(AActor *mobj, const DVector3 &pos, bool beforeTele, bool else { double fogDelta = mobj->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; - mo = Spawn(mobj->Level, (beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), DVector3(pos, pos.Z + fogDelta), ALLOW_REPLACE); + mo = Spawn(mobj->Level, (beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), pos.plusZ(fogDelta), ALLOW_REPLACE); } if (mo != NULL && setTarget) @@ -414,7 +414,7 @@ bool FLevelLocals::EV_Teleport (int tid, int tag, line_t *line, int side, AActor { badangle = DAngle::fromDeg(0.01); } - if (P_Teleport (thing, DVector3(searcher->Pos(), z), searcher->Angles.Yaw + badangle, flags)) + if (P_Teleport (thing, DVector3(searcher->Pos().XY(), z), searcher->Angles.Yaw + badangle, flags)) { // [RH] Lee Killough's changes for silent teleporters from BOOM if (line) @@ -658,7 +658,7 @@ bool FLevelLocals::EV_TeleportOther (int other_tid, int dest_tid, bool fog) bool DoGroupForOne (AActor *victim, AActor *source, AActor *dest, bool floorz, bool fog) { DAngle an = dest->Angles.Yaw - source->Angles.Yaw; - DVector2 off = victim->Pos() - source->Pos(); + DVector2 off = victim->Pos().XY() - source->Pos().XY(); DAngle offAngle = victim->Angles.Yaw - source->Angles.Yaw; DVector2 newp = { off.X * an.Cos() - off.Y * an.Sin(), off.X * an.Sin() + off.Y * an.Cos() }; double z = floorz ? ONFLOORZ : dest->Z() + victim->Z() - source->Z(); diff --git a/src/playsim/p_things.cpp b/src/playsim/p_things.cpp index 0089a29c22..3391030aac 100644 --- a/src/playsim/p_things.cpp +++ b/src/playsim/p_things.cpp @@ -468,7 +468,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser, int flags) thing->flags |= MF_SOLID; thing->Height = info->Height; // [RH] Use real height thing->radius = info->radius; // [RH] Use real radius - if (!(flags & RF_NOCHECKPOSITION) && !P_CheckPosition (thing, thing->Pos())) + if (!(flags & RF_NOCHECKPOSITION) && !P_CheckPosition (thing, thing->Pos().XY())) { thing->flags = oldflags; thing->radius = oldradius; @@ -512,7 +512,7 @@ bool P_Thing_CanRaise(AActor *thing) thing->Height = info->Height; thing->radius = info->radius; - bool check = P_CheckPosition (thing, thing->Pos()); + bool check = P_CheckPosition (thing, thing->Pos().XY()); // Restore checked properties thing->flags = oldflags; @@ -813,7 +813,7 @@ int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, do { caller->AddZ(reference->GetBobOffset()); } - P_TryMove(caller, caller->Pos(), false); + P_TryMove(caller, caller->Pos().XY(), false); } return true; } diff --git a/src/playsim/p_trace.cpp b/src/playsim/p_trace.cpp index d8b362ca7a..7e47a73234 100644 --- a/src/playsim/p_trace.cpp +++ b/src/playsim/p_trace.cpp @@ -406,7 +406,7 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit, bool spec } else { - lineside = P_PointOnLineSide(Start, in->d.line); + lineside = P_PointOnLineSide(Start.XY(), in->d.line); CurSector = lineside ? in->d.line->backsector : in->d.line->frontsector; } } diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 87633398cc..9751fc268c 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -376,7 +376,7 @@ void player_t::SetLogNumber (int num) // First look up TXT_LOGTEXT%d in the string table mysnprintf(lumpname, countof(lumpname), "$TXT_LOGTEXT%d", num); - auto text = GStrings[lumpname+1]; + auto text = GStrings.CheckString(lumpname+1); if (text) { SetLogText(lumpname); // set the label, not the content, so that a language change can be picked up. @@ -394,7 +394,7 @@ void player_t::SetLogNumber (int num) // If this is an original IWAD text, try looking up its lower priority string version first. mysnprintf(lumpname, countof(lumpname), "$TXT_ILOG%d", num); - auto text = GStrings[lumpname + 1]; + auto text = GStrings.CheckString(lumpname + 1); if (text) { SetLogText(lumpname); // set the label, not the content, so that a language change can be picked up. @@ -403,7 +403,7 @@ void player_t::SetLogNumber (int num) } auto lump = fileSystem.ReadFile(lumpnum); - SetLogText (lump.GetString()); + SetLogText (lump.string()); } } @@ -422,7 +422,7 @@ void player_t::SetLogText (const char *text) if (mo && mo->CheckLocalView()) { // Print log text to console - Printf(PRINT_HIGH | PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s\n", LogText[0] == '$' ? GStrings(text + 1) : text); + Printf(PRINT_HIGH | PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s\n", LogText[0] == '$' ? GStrings.GetString(text + 1) : text); } } @@ -430,7 +430,7 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, SetLogText) { PARAM_SELF_STRUCT_PROLOGUE(player_t); PARAM_STRING(log); - self->SetLogText(log); + self->SetLogText(log.GetChars()); return 0; } @@ -478,7 +478,7 @@ void player_t::SetFOV(float fov) { if (consoleplayer == Net_Arbitrator) { - Net_WriteByte(DEM_MYFOV); + Net_WriteInt8(DEM_MYFOV); } else { @@ -488,7 +488,7 @@ void player_t::SetFOV(float fov) } else { - Net_WriteByte(DEM_MYFOV); + Net_WriteInt8(DEM_MYFOV); } Net_WriteFloat(clamp(fov, 5.f, 179.f)); } @@ -637,9 +637,9 @@ void player_t::SendPitchLimits() const uppitch = downpitch = (int)maxviewpitch; } - Net_WriteByte(DEM_SETPITCHLIMIT); - Net_WriteByte(uppitch); - Net_WriteByte(downpitch); + Net_WriteInt8(DEM_SETPITCHLIMIT); + Net_WriteInt8(uppitch); + Net_WriteInt8(downpitch); } } @@ -693,7 +693,7 @@ bool player_t::Resurrect() P_BringUpWeapon(this); } - if (morphTics) + if (mo->alternative != nullptr) { P_UnmorphActor(mo, mo); } @@ -828,16 +828,16 @@ static int SetupCrouchSprite(AActor *self, int crouchsprite) FString normspritename = sprites[self->SpawnState->sprite].name; FString crouchspritename = sprites[crouchsprite].name; - int spritenorm = fileSystem.CheckNumForName(normspritename + "A1", ns_sprites); + int spritenorm = fileSystem.CheckNumForName((normspritename + "A1").GetChars(), FileSys::ns_sprites); if (spritenorm == -1) { - spritenorm = fileSystem.CheckNumForName(normspritename + "A0", ns_sprites); + spritenorm = fileSystem.CheckNumForName((normspritename + "A0").GetChars(), FileSys::ns_sprites); } - int spritecrouch = fileSystem.CheckNumForName(crouchspritename + "A1", ns_sprites); + int spritecrouch = fileSystem.CheckNumForName((crouchspritename + "A1").GetChars(), FileSys::ns_sprites); if (spritecrouch == -1) { - spritecrouch = fileSystem.CheckNumForName(crouchspritename + "A0", ns_sprites); + spritecrouch = fileSystem.CheckNumForName((crouchspritename + "A0").GetChars(), FileSys::ns_sprites); } if (spritenorm == -1 || spritecrouch == -1) @@ -1172,7 +1172,7 @@ void P_CheckEnvironment(player_t *player) P_PlayerOnSpecialFlat(player, P_GetThingFloorType(player->mo)); } if (player->mo->Vel.Z <= -player->mo->FloatVar(NAME_FallingScreamMinSpeed) && - player->mo->Vel.Z >= -player->mo->FloatVar(NAME_FallingScreamMaxSpeed) && !player->morphTics && + player->mo->Vel.Z >= -player->mo->FloatVar(NAME_FallingScreamMaxSpeed) && player->mo->alternative == nullptr && player->mo->waterlevel == 0) { auto id = S_FindSkinnedSound(player->mo, S_FindSound("*falling")); @@ -1239,6 +1239,17 @@ void P_PlayerThink (player_t *player) I_Error ("No player %td start\n", player - players + 1); } + for (unsigned int i = 0u; i < 3u; ++i) + { + if (fabs(player->angleOffsetTargets[i].Degrees()) >= EQUAL_EPSILON) + { + player->mo->Angles[i] += player->angleOffsetTargets[i]; + player->mo->PrevAngles[i] = player->mo->Angles[i]; + } + + player->angleOffsetTargets[i] = nullAngle; + } + if (player->SubtitleCounter > 0) { player->SubtitleCounter--; @@ -1267,6 +1278,7 @@ void P_PlayerThink (player_t *player) player->cheats &= ~CF_INTERPVIEWANGLES; player->cheats &= ~CF_SCALEDNOLERP; player->cheats &= ~CF_NOFOVINTERP; + player->cheats &= ~CF_NOVIEWPOSINTERP; player->mo->FloatVar("prevBob") = player->bob; IFVIRTUALPTRNAME(player->mo, NAME_PlayerPawn, PlayerThink) @@ -1620,6 +1632,7 @@ void player_t::Serialize(FSerializer &arc) if (arc.isReading()) { + userinfo.Reset(mo->Level->PlayerNum(this)); ReadUserInfo(arc, userinfo, skinname); } else @@ -1711,7 +1724,7 @@ void player_t::Serialize(FSerializer &arc) } if (skinname.IsNotEmpty()) { - userinfo.SkinChanged(skinname, CurrentPlayerClass); + userinfo.SkinChanged(skinname.GetChars(), CurrentPlayerClass); } } diff --git a/src/playsim/po_man.cpp b/src/playsim/po_man.cpp index f29001b9f6..a547d619a8 100644 --- a/src/playsim/po_man.cpp +++ b/src/playsim/po_man.cpp @@ -1097,7 +1097,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd) performBlockingThrust = true; } - DVector2 pos = mobj->PosRelative(ld); + DVector2 pos = mobj->PosRelative(ld).XY(); FBoundingBox box(pos.X, pos.Y, mobj->radius); if (!inRange(box, ld) || BoxOnLineSide(box, ld) != -1) @@ -1108,7 +1108,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd) if (ld->isLinePortal()) { // Fixme: this still needs to figure out if the polyobject move made the player cross the portal line. - if (P_TryMove(mobj, mobj->Pos(), false)) + if (P_TryMove(mobj, mobj->Pos().XY(), false)) { continue; } diff --git a/src/playsim/shadowinlines.h b/src/playsim/shadowinlines.h new file mode 100644 index 0000000000..60caa95069 --- /dev/null +++ b/src/playsim/shadowinlines.h @@ -0,0 +1,233 @@ +#pragma once + +#include "actor.h" +#include "r_defs.h" +#include "m_random.h" + +//----------------------------------------------------------------------------- +// +// DESCRIPTION: +// Handling of MF_SHADOW related code for attack and aiming functions. +// +//----------------------------------------------------------------------------- + + +// RNG VARIABLES ------------------------------------------------ +extern FRandom pr_spawnmissile; +extern FRandom pr_facetarget; +extern FRandom pr_railface; +extern FRandom pr_crailgun; +inline FRandom pr_shadowaimz("VerticalShadowAim"); + +//========================================================================== +// +// Generic checks +// +//========================================================================== + +struct SightCheckData +{ + AActor* HitShadow; +}; + +inline ETraceStatus CheckForShadowBlockers(FTraceResults& res, void* userdata) +{ + SightCheckData* output = (SightCheckData*)userdata; + if (res.HitType == TRACE_HitActor && res.Actor && (res.Actor->flags9 & MF9_SHADOWBLOCK)) + { + output->HitShadow = res.Actor; + return TRACE_Stop; + } + + if (res.HitType != TRACE_HitActor) + { + return TRACE_Stop; + } + + return TRACE_Continue; +} + +// [inkoalawetrust] Check if an MF9_SHADOWBLOCK actor is standing between t1 and t2. +inline AActor* P_CheckForShadowBlock(AActor* t1, AActor* t2, DVector3 pos, double& penaltyFactor) +{ + FTraceResults result; + SightCheckData ShadowCheck; + ShadowCheck.HitShadow = nullptr; + DVector3 dir; + double dist; + if (t2) + { + dir = t1->Vec3To(t2); + dist = dir.Length(); + } + //No second actor, fall back to shooting at facing direction. + else + { + dir = DRotator(-(t1->Angles.Pitch), t1->Angles.Yaw, t1->Angles.Yaw); + dist = 65536.0; //Arbitrary large value. + } + + Trace(pos, t1->Sector, dir, dist, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, t1, result, 0, CheckForShadowBlockers, &ShadowCheck); + + //Use the penalty factor of the shadowblocker that was hit. Otherwise, use the factor passed by PerformShadowChecks(). + if (ShadowCheck.HitShadow) + { + penaltyFactor = ShadowCheck.HitShadow->ShadowPenaltyFactor; + } + + return ShadowCheck.HitShadow; +} + +inline bool AffectedByShadows(AActor* self) +{ + return (!(self->flags6 & MF6_SEEINVISIBLE) || self->flags9 & MF9_SHADOWAIM); +} + +inline AActor* CheckForShadows(AActor* self, AActor* other, DVector3 pos, double& penaltyFactor) +{ + return ((other && (other->flags & MF_SHADOW)) || (self->flags9 & MF9_DOSHADOWBLOCK)) ? P_CheckForShadowBlock(self, other, pos, penaltyFactor) : nullptr; +} + +inline AActor* PerformShadowChecks(AActor* self, AActor* other, DVector3 pos, double& penaltyFactor) +{ + if (other != nullptr) penaltyFactor = other->ShadowPenaltyFactor; //Use target penalty factor by default. + else penaltyFactor = 1.0; + return AffectedByShadows(self) ? CheckForShadows(self, other, pos, penaltyFactor) : nullptr; +} + +//========================================================================== +// +// Function-specific inlines. +// +//========================================================================== + +inline void P_SpawnMissileXYZ_ShadowHandling(AActor* source, AActor* target, AActor* missile, DVector3 pos) +{ + double penaltyFactor; + // invisible target: rotate velocity vector in 2D + // [RC] Now monsters can aim at invisible player as if they were fully visible. + if (PerformShadowChecks(source, target, pos, penaltyFactor)) + { + DAngle an = DAngle::fromDeg(pr_spawnmissile.Random2() * (22.5 / 256)) * source->ShadowAimFactor * penaltyFactor; + double c = an.Cos(); + double s = an.Sin(); + + double newx = missile->Vel.X * c - missile->Vel.Y * s; + double newy = missile->Vel.X * s + missile->Vel.Y * c; + + missile->Vel.X = newx; + missile->Vel.Y = newy; + + if (source->flags9 & MF9_SHADOWAIMVERT) + { + DAngle pitch = DAngle::fromDeg(pr_spawnmissile.Random2() * (22.5 / 256)) * source->ShadowAimFactor * penaltyFactor; + double newz = -pitch.Sin() * missile->Speed; + missile->Vel.Z = newz; + } + } + return; +} + +//P_SpawnMissileZAimed uses a local variable for the angle it passes on. +inline DAngle P_SpawnMissileZAimed_ShadowHandling(AActor* source, AActor* target, double& vz, double speed, DVector3 pos) +{ + double penaltyFactor; + if (PerformShadowChecks(source, target, pos, penaltyFactor)) + { + if (source->flags9 & MF9_SHADOWAIMVERT) + { + DAngle pitch = DAngle::fromDeg(pr_spawnmissile.Random2() * (16. / 360.)) * source->ShadowAimFactor * penaltyFactor; + vz += -pitch.Sin() * speed; //Modify the Z velocity pointer that is then passed to P_SpawnMissileAngleZSpeed. + } + return DAngle::fromDeg(pr_spawnmissile.Random2() * (16. / 360.)) * source->ShadowAimFactor * penaltyFactor; + } + return nullAngle; +} + +inline void A_Face_ShadowHandling(AActor* self, AActor* other, DAngle max_turn, DAngle other_angle, bool vertical) +{ + double penaltyFactor; + if (!vertical) + { + // This will never work well if the turn angle is limited. + if (max_turn == nullAngle && (self->Angles.Yaw == other_angle) && PerformShadowChecks(self, other, self->PosAtZ(self->Center()), penaltyFactor)) + { + self->Angles.Yaw += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.)) * self->ShadowAimFactor * penaltyFactor; + } + } + else + { + //Randomly offset the pitch when looking at shadows. + if (self->flags9 & MF9_SHADOWAIMVERT && max_turn == nullAngle && (self->Angles.Pitch == other_angle) && PerformShadowChecks(self, other, self->PosAtZ(self->Center()), penaltyFactor)) + { + self->Angles.Pitch += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.)) * self->ShadowAimFactor * penaltyFactor; + } + } + return; +} + +inline void A_MonsterRail_ShadowHandling(AActor* self) +{ + double penaltyFactor; + double shootZ = self->Center() - self->FloatSpeed - self->Floorclip; // The formula P_RailAttack uses, minus offset_z since A_MonsterRail doesn't use it. + + if (PerformShadowChecks(self, self->target, self->PosAtZ(shootZ), penaltyFactor)) + { + self->Angles.Yaw += DAngle::fromDeg(pr_railface.Random2() * 45. / 256) * self->ShadowAimFactor * penaltyFactor; + if (self->flags9 & MF9_SHADOWAIMVERT) + self->Angles.Pitch += DAngle::fromDeg(pr_railface.Random2() * 45. / 256) * self->ShadowAimFactor * penaltyFactor; + } + return; +} + +//Also passes parameters to determine a firing position for the SHADOWBLOCK check. +inline void A_CustomRailgun_ShadowHandling(AActor* self, double spawnofs_xy, double spawnofs_z, DAngle spread_xy, int flags) +{ + double penaltyFactor; + // [inkoalawetrust] The exact formula P_RailAttack uses to determine where the railgun trace should spawn from. + DVector2 shootXY = (self->Vec2Angle(spawnofs_xy, (self->Angles.Yaw + spread_xy) - DAngle::fromDeg(90.))); + double shootZ = self->Center() - self->FloatSpeed + spawnofs_z - self->Floorclip; + if (flags & 16) shootZ += self->AttackOffset(); //16 is RGF_CENTERZ + DVector3 checkPos; + checkPos.X = shootXY.X; + checkPos.Y = shootXY.Y; + checkPos.Z = shootZ; + + if (PerformShadowChecks(self, self->target, checkPos, penaltyFactor)) + { + self->Angles.Yaw += DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.)) * self->ShadowAimFactor * penaltyFactor; + if (self->flags9 & MF9_SHADOWAIMVERT) + { + self->Angles.Pitch += DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.)) * self->ShadowAimFactor * penaltyFactor; + } + } + return; +} + +//If anything is returned, then AimLineAttacks' result pitch is changed to that value. +inline DAngle P_AimLineAttack_ShadowHandling(AActor*source, AActor* target, AActor* linetarget, double shootZ) +{ + double penaltyFactor; + AActor* mo; + if (target) + mo = target; + else + mo = linetarget; + + // [inkoalawetrust] Randomly offset the vertical aim of monsters. Roughly uses the SSG vertical spread. + if (source->player == NULL && source->flags9 & MF9_SHADOWAIMVERT && PerformShadowChecks (source, mo, source->PosAtZ (shootZ), penaltyFactor)) + { + if (linetarget) + return DAngle::fromDeg(pr_shadowaimz.Random2() * (28.388 / 256.)) * source->ShadowAimFactor * penaltyFactor; //Change the autoaims' pitch to this. + else + source->Angles.Pitch = DAngle::fromDeg(pr_shadowaimz.Random2() * (28.388 / 256.)) * source->ShadowAimFactor * penaltyFactor; + } + return nullAngle; +} + +//A_WolfAttack directly harms the target instead of firing a hitscan or projectile. So it handles shadows by lowering the chance of harming the target. +inline bool A_WolfAttack_ShadowHandling(AActor* self) +{ + double p; //Does nothing. + return (PerformShadowChecks(self, self->target, self->PosAtZ(self->Center()), p)); +} \ No newline at end of file diff --git a/src/playsim/statnums.h b/src/playsim/statnums.h index 7450ccbddc..f33ac21c03 100644 --- a/src/playsim/statnums.h +++ b/src/playsim/statnums.h @@ -69,6 +69,7 @@ enum STAT_ACTORMOVER, // actor movers STAT_SCRIPTS, // The ACS thinker. This is to ensure that it can't tick before all actors called PostBeginPlay STAT_BOT, // Bot thinker + STAT_VISUALTHINKER, // VisualThinker Thinker }; #endif \ No newline at end of file diff --git a/src/posix/i_steam.cpp b/src/posix/i_steam.cpp index 15265a6e02..f65478f3ea 100644 --- a/src/posix/i_steam.cpp +++ b/src/posix/i_steam.cpp @@ -163,7 +163,8 @@ static struct SteamAppInfo {"Strife", 317040}, {"Ultimate Doom/rerelease/DOOM_Data/StreamingAssets", 2280}, {"Doom 2/rerelease/DOOM II_Data/StreamingAssets", 2300}, - {"Doom 2/finaldoombase", 2300} + {"Doom 2/finaldoombase", 2300}, + {"Master Levels of Doom/doom2", 9160} }; TArray I_GetSteamPath() @@ -179,7 +180,7 @@ TArray I_GetSteamPath() FString regPath = appSupportPath + "/Steam/config/config.vdf"; try { - SteamInstallFolders = ParseSteamRegistry(regPath); + SteamInstallFolders = ParseSteamRegistry(regPath.GetChars()); } catch(class CRecoverableError &error) { @@ -187,7 +188,7 @@ TArray I_GetSteamPath() return result; } - SteamInstallFolders.Push(appSupportPath + "/Steam/SteamApps/common"); + SteamInstallFolders.Push(appSupportPath + "/Steam/steamapps/common"); #else char* home = getenv("HOME"); if(home != NULL && *home != '\0') @@ -198,11 +199,11 @@ TArray I_GetSteamPath() // .steam at some point. Not sure if it's just my setup so I guess we // can fall back on it? if(!FileExists(regPath)) - regPath.Format("%s/.local/share/Steam/config/config.vdf", home); + regPath.Format("%s/.steam/steam/config/config.vdf", home); try { - SteamInstallFolders = ParseSteamRegistry(regPath); + SteamInstallFolders = ParseSteamRegistry(regPath.GetChars()); } catch(class CRecoverableError &error) { @@ -210,7 +211,7 @@ TArray I_GetSteamPath() return result; } - regPath.Format("%s/.local/share/Steam/SteamApps/common", home); + regPath.Format("%s/.steam/steam/steamapps/common", home); SteamInstallFolders.Push(regPath); } #endif @@ -221,7 +222,7 @@ TArray I_GetSteamPath() { struct stat st; FString candidate(SteamInstallFolders[i] + "/" + AppInfo[app].BasePath); - if(DirExists(candidate)) + if(DirExists(candidate.GetChars())) result.Push(candidate); } } diff --git a/src/posix/osx/zdoom-info.plist b/src/posix/osx/zdoom-info.plist index 8fae54cef8..1250226b3f 100644 --- a/src/posix/osx/zdoom-info.plist +++ b/src/posix/osx/zdoom-info.plist @@ -9,11 +9,11 @@ CFBundleIconFile zdoom.icns CFBundleIdentifier - org.drdteam.gzdoom + org.vkdoom.app CFBundleInfoDictionaryVersion 6.0 CFBundleName - GZDoom + VKDoom CFBundlePackageType APPL CFBundleShortVersionString @@ -23,7 +23,7 @@ LSApplicationCategoryType public.app-category.action-games LSMinimumSystemVersion - 10.12 + 10.13 CFBundleDocumentTypes diff --git a/src/r_data/a_dynlightdata.cpp b/src/r_data/a_dynlightdata.cpp index c20c8d2e9c..da451282e1 100644 --- a/src/r_data/a_dynlightdata.cpp +++ b/src/r_data/a_dynlightdata.cpp @@ -126,6 +126,7 @@ void FLightDefaults::ApplyProperties(FDynamicLight * light) const light->lighttype = m_type; light->specialf1 = m_Param; light->pArgs = m_Args; + light->pSourceRadius = &SourceRadius; light->pLightFlags = &m_lightFlags; if (m_lightFlags & LF_SPOT) { diff --git a/src/r_data/colormaps.cpp b/src/r_data/colormaps.cpp index 2ee96133ad..4d9604b614 100644 --- a/src/r_data/colormaps.cpp +++ b/src/r_data/colormaps.cpp @@ -104,13 +104,11 @@ void R_InitColormaps (bool allowCustomColormap) for (uint32_t i = 0; i < NumLumps; i++) { - if (fileSystem.GetFileNamespace(i) == ns_colormaps) + if (fileSystem.GetFileNamespace(i) == FileSys::ns_colormaps) { - char name[9]; - name[8] = 0; - fileSystem.GetFileShortName (name, i); + auto name = fileSystem.GetFileShortName(i); - if (fileSystem.CheckNumForName (name, ns_colormaps) == (int)i) + if (fileSystem.CheckNumForName (name, FileSys::ns_colormaps) == (int)i) { strncpy(cm.name, name, 8); cm.blend = 0; diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index 006be20440..d4bc5d3937 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -76,7 +76,7 @@ static void do_uniform_set(float value, ExtraUniformCVARData* data) for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) { PostProcessShader& shader = PostProcessShaders[i]; - if (strcmp(shader.Name, data->Shader) == 0) + if (strcmp(shader.Name.GetChars(), data->Shader.GetChars()) == 0) { data->vec4 = shader.Uniforms[data->Uniform].Values; } @@ -154,7 +154,7 @@ static void ParseVavoomSkybox() sb->SetSize(); if (!error) { - TexMan.AddGameTexture(MakeGameTexture(sb, s, ETextureType::Override)); + TexMan.AddGameTexture(MakeGameTexture(sb, s.GetChars(), ETextureType::Override)); } } } @@ -1014,7 +1014,7 @@ class GLDefsParser break; case LIGHTTAG_LIGHT: ParseString(sc); - AddLightAssociation(name, frameName, sc.String); + AddLightAssociation(name.GetChars(), frameName.GetChars(), sc.String); break; default: sc.ScriptError("Unknown tag: %s\n", sc.String); @@ -1089,7 +1089,7 @@ class GLDefsParser sc.MustGetString(); FString s = sc.String; - FSkyBox * sb = new FSkyBox(s); + FSkyBox * sb = new FSkyBox(s.GetChars()); if (sc.CheckString("fliptop")) { sb->fliptop = true; @@ -1109,7 +1109,7 @@ class GLDefsParser sc.ScriptError("%s: Skybox definition requires either 3 or 6 faces", s.GetChars()); } sb->SetSize(); - TexMan.AddGameTexture(MakeGameTexture(sb, s, ETextureType::Override)); + TexMan.AddGameTexture(MakeGameTexture(sb, s.GetChars(), ETextureType::Override)); } //=========================================================================== @@ -1371,10 +1371,12 @@ class GLDefsParser if (tex) { bool okay = false; + size_t texIndex = 0; for (size_t i = 0; i < countof(mlay.CustomShaderTextures); i++) { if (!mlay.CustomShaderTextures[i]) { + mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::Default; mlay.CustomShaderTextures[i] = TexMan.FindGameTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny); if (!mlay.CustomShaderTextures[i]) { @@ -1383,6 +1385,7 @@ class GLDefsParser texNameList.Push(textureName); texNameIndex.Push((int)i); + texIndex = i; okay = true; break; } @@ -1391,6 +1394,37 @@ class GLDefsParser { sc.ScriptError("Error: out of texture units in texture '%s'", tex->GetName().GetChars()); } + + if (sc.CheckToken('{')) + { + while (!sc.CheckToken('}')) + { + sc.MustGetString(); + if (sc.Compare("filter")) + { + sc.MustGetString(); + if (sc.Compare("nearest")) + { + if(okay) + mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::NearestMipLinear; + } + else if (sc.Compare("linear")) + { + if (okay) + mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::LinearMipLinear; + } + else if (sc.Compare("default")) + { + if (okay) + mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::Default; + } + else + { + sc.ScriptError("Error: unexpected '%s' when reading filter property in texture '%s'\n", sc.String, tex ? tex->GetName().GetChars() : "(null)"); + } + } + } + } } } else if (sc.Compare("define")) @@ -1581,7 +1615,7 @@ class GLDefsParser if (is_cvar) { addedcvars = true; - if (!shaderdesc.Name.GetChars()) + if (shaderdesc.Name.IsEmpty()) sc.ScriptError("Shader must have a name to use cvar uniforms"); ECVarType cvartype = CVAR_Dummy; @@ -1605,7 +1639,7 @@ class GLDefsParser } sc.MustGetString(); cvarname = sc.String; - cvar = FindCVar(cvarname, NULL); + cvar = FindCVar(cvarname.GetChars(), NULL); UCVarValue oldval; UCVarValue val; @@ -1623,7 +1657,7 @@ class GLDefsParser { if (!cvar) { - cvar = C_CreateCVar(cvarname, cvartype, cvarflags); + cvar = C_CreateCVar(cvarname.GetChars(), cvartype, cvarflags); } else if (cvar && (((cvar->GetFlags()) & CVAR_MOD) == CVAR_MOD)) { @@ -1643,7 +1677,7 @@ class GLDefsParser { oldval.Float = cvar->GetGenericRep(CVAR_Float).Float; delete cvar; - cvar = C_CreateCVar(cvarname, cvartype, cvarflags); + cvar = C_CreateCVar(cvarname.GetChars(), cvartype, cvarflags); oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer(); } @@ -1758,10 +1792,12 @@ class GLDefsParser } sc.MustGetString(); bool okay = false; + size_t texIndex = 0; for (size_t i = 0; i < countof(mlay.CustomShaderTextures); i++) { if (!mlay.CustomShaderTextures[i]) { + mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::Default; mlay.CustomShaderTextures[i] = TexMan.FindGameTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny); if (!mlay.CustomShaderTextures[i]) { @@ -1770,6 +1806,7 @@ class GLDefsParser texNameList.Push(textureName); texNameIndex.Push((int)i); + texIndex = i; okay = true; break; } @@ -1921,7 +1958,7 @@ class GLDefsParser if (!sc.GetToken ()) { if (addedcvars) - GameConfig->DoModSetup (gameinfo.ConfigName); + GameConfig->DoModSetup (gameinfo.ConfigName.GetChars()); return; } type = sc.MatchString(CoreKeywords); diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index 84eb9aadab..df5c41e71e 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -45,6 +45,7 @@ #include "modelrenderer.h" #include "i_interface.h" #include "p_tick.h" +#include "actor.h" #ifdef _MSC_VER @@ -58,15 +59,17 @@ float pauseTimeOffset = .0f; extern TDeletingArray Voxels; extern TDeletingArray VoxelDefs; -void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, const int curTics, const PClass* ti, int translation, AActor* actor); +void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, const int curTics, FTranslationID translation, AActor* actor); void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, double ticFrac) { // Setup transformation. - int translation = 0; - if (!(smf->flags & MDL_IGNORETRANSLATION)) + int smf_flags = smf->getFlags(actor->modelData); + + FTranslationID translation = NO_TRANSLATION; + if (!(smf_flags & MDL_IGNORETRANSLATION)) translation = actor->Translation; // y scale for a sprite means height, i.e. z in the world! @@ -84,7 +87,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod float angle = angles.Yaw.Degrees(); // [BB] Workaround for the missing pitch information. - if ((smf->flags & MDL_PITCHFROMMOMENTUM)) + if ((smf_flags & MDL_PITCHFROMMOMENTUM)) { const double x = actor->Vel.X; const double y = actor->Vel.Y; @@ -104,7 +107,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod } } - if (smf->flags & MDL_ROTATING) + if (smf_flags & MDL_ROTATING) { bool isPaused = paused || P_CheckTickerPaused(); float timeFloat; @@ -134,13 +137,13 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod // Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing. // If both flags MDL_USEACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the velocity vector pitch. - if (smf->flags & MDL_USEACTORPITCH) + if (smf_flags & MDL_USEACTORPITCH) { double d = angles.Pitch.Degrees(); - if (smf->flags & MDL_BADROTATION) pitch += d; + if (smf_flags & MDL_BADROTATION) pitch += d; else pitch -= d; } - if (smf->flags & MDL_USEACTORROLL) roll += angles.Roll.Degrees(); + if (smf_flags & MDL_USEACTORROLL) roll += angles.Roll.Degrees(); VSMatrix objectToWorldMatrix; objectToWorldMatrix.loadIdentity(); @@ -156,7 +159,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod // [MK] distortions might happen depending on when the pixel stretch is compensated for // so we make the "undistorted" behavior opt-in - if (smf->flags & MDL_CORRECTPIXELSTRETCH) + if (smf_flags & MDL_CORRECTPIXELSTRETCH) { stretch = (smf->modelIDs[0] != -1 ? Models[smf->modelIDs[0]]->getAspectFactor(actor->Level->info->pixelstretch) : 1.f) / actor->Level->info->pixelstretch; objectToWorldMatrix.scale(1, stretch, 1); @@ -164,14 +167,14 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod // Applying model transformations: // 1) Applying actor angle, pitch and roll to the model - if (smf->flags & MDL_USEROTATIONCENTER) + if (smf_flags & MDL_USEROTATIONCENTER) { objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterZ/stretch, smf->rotationCenterY); } objectToWorldMatrix.rotate(-angle, 0, 1, 0); objectToWorldMatrix.rotate(pitch, 0, 0, 1); objectToWorldMatrix.rotate(-roll, 1, 0, 0); - if (smf->flags & MDL_USEROTATIONCENTER) + if (smf_flags & MDL_USEROTATIONCENTER) { objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterZ/stretch, -smf->rotationCenterY); } @@ -179,7 +182,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod // 2) Applying Doomsday like rotation of the weapon pickup models // The rotation angle is based on the elapsed time. - if (smf->flags & MDL_ROTATING) + if (smf_flags & MDL_ROTATING) { objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterY/stretch, smf->rotationCenterZ); objectToWorldMatrix.rotate(rotateOffset, smf->xrotate, smf->yrotate, smf->zrotate); @@ -197,7 +200,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1); objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0); - if (!(smf->flags & MDL_CORRECTPIXELSTRETCH)) + if (!(smf_flags & MDL_CORRECTPIXELSTRETCH)) { stretch = (smf->modelIDs[0] != -1 ? Models[smf->modelIDs[0]]->getAspectFactor(actor->Level->info->pixelstretch) : 1.f) / actor->Level->info->pixelstretch; objectToWorldMatrix.scale(1, stretch, 1); @@ -205,15 +208,17 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod float orientation = scaleFactorX * scaleFactorY * scaleFactorZ; - renderer->BeginDrawModel(actor->RenderStyle, smf, objectToWorldMatrix, orientation < 0); - RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, actor->modelData != nullptr ? actor->modelData->modelDef != NAME_None ? PClass::FindActor(actor->modelData->modelDef) : actor->GetClass() : actor->GetClass(), translation, actor); - renderer->EndDrawModel(actor->RenderStyle, smf); + renderer->BeginDrawModel(actor->RenderStyle, smf_flags, objectToWorldMatrix, orientation < 0); + RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, translation, actor); + renderer->EndDrawModel(actor->RenderStyle, smf_flags); } void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf) { AActor * playermo = players[consoleplayer].camera; + int smf_flags = smf->getFlags(psp->Caller->modelData); + // [BB] No model found for this sprite, so we can't render anything. if (smf == nullptr) return; @@ -224,14 +229,14 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio // [Nash] Optional scale weapon FOV float fovscale = 1.0f; - if (smf->flags & MDL_SCALEWEAPONFOV) + if (smf_flags & MDL_SCALEWEAPONFOV) { fovscale = tan(players[consoleplayer].DesiredFOV * (0.5f * M_PI / 180.f)); fovscale = 1.f + (fovscale - 1.f) * cl_scaleweaponfov; } // Scaling model (y scale for a sprite means height, i.e. z in the world!). - objectToWorldMatrix.scale(smf->xscale, smf->zscale, smf->yscale / fovscale); + objectToWorldMatrix.scale((psp->Flags & PSPF_FLIP) ? -smf->xscale : smf->xscale, smf->zscale, smf->yscale / fovscale); // Aplying model offsets (model offsets do not depend on model scalings). objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale); @@ -261,20 +266,100 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio float orientation = smf->xscale * smf->yscale * smf->zscale; - renderer->BeginDrawHUDModel(playermo->RenderStyle, objectToWorldMatrix, orientation < 0); - uint32_t trans = psp->GetTranslation() != 0 ? psp->GetTranslation() : 0; + renderer->BeginDrawHUDModel(playermo->RenderStyle, objectToWorldMatrix, orientation < 0, smf_flags); + auto trans = psp->GetTranslation(); if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation; - RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), psp->Caller->modelData != nullptr ? psp->Caller->modelData->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelData->modelDef) : psp->Caller->GetClass() : psp->Caller->GetClass(), trans, psp->Caller); - renderer->EndDrawHUDModel(playermo->RenderStyle); + + RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), trans, psp->Caller); + renderer->EndDrawHUDModel(playermo->RenderStyle, smf_flags); +} + +double getCurrentFrame(const AnimOverride &anim, double tic) +{ + if(anim.framerate <= 0) return anim.startFrame; + + double frame = ((tic - anim.startTic) / GameTicRate) * anim.framerate; // position in frames + + double duration = double(anim.lastFrame) - anim.startFrame; + + if((anim.flags & ANIMOVERRIDE_LOOP) && frame >= duration) + { + frame = frame - duration; + return fmod(frame, anim.lastFrame - anim.loopFrame) + anim.loopFrame; + } + else + { + return min(frame, duration) + anim.startFrame; + } +} + +static void calcFrame(const AnimOverride &anim, double tic, double &inter, int &prev, int &next) +{ + double frame = getCurrentFrame(anim, tic); + + prev = int(floor(frame)); + + inter = frame - prev; + + next = int(ceil(frame)); } -void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation, AActor* actor) +void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor) { // [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation // and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame. - FSpriteModelFrame * smfNext = nullptr; + + int smf_flags = smf->getFlags(actor->modelData); + + const FSpriteModelFrame * smfNext = nullptr; double inter = 0.; - if (gl_interpolate_model_frames && !(smf->flags & MDL_NOINTERPOLATION)) + double inter_main = -1.f; + double inter_next = -1.f; + + bool is_decoupled = (actor->flags9 & MF9_DECOUPLEDANIMATIONS); + + int decoupled_main_prev_frame = -1; + int decoupled_next_prev_frame = -1; + + int decoupled_main_frame = -1; + int decoupled_next_frame = -1; + + // if prev_frame == -1: interpolate(main_frame, next_frame, inter), else: interpolate(interpolate(main_prev_frame, main_frame, inter_main), interpolate(next_prev_frame, next_frame, inter_next), inter) + // 4-way interpolation is needed to interpolate animation switches between animations that aren't 35hz + + if(is_decoupled) + { + smfNext = smf = &BaseSpriteModelFrames[actor->GetClass()]; + if(actor->modelData && !(actor->modelData->curAnim.flags & ANIMOVERRIDE_NONE)) + { + double tic = actor->Level->totaltime; + if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !Level->isFrozen()) + { + tic += I_GetTimeFrac(); + } + if(actor->modelData->curAnim.startTic > tic) + { + inter = (tic - actor->modelData->curAnim.switchTic) / (actor->modelData->curAnim.startTic - actor->modelData->curAnim.switchTic); + + double nextFrame = actor->modelData->curAnim.startFrame; + + double prevFrame = actor->modelData->prevAnim.startFrame; + + decoupled_next_prev_frame = floor(nextFrame); + decoupled_next_frame = ceil(nextFrame); + inter_next = nextFrame - floor(nextFrame); + + decoupled_main_prev_frame = floor(prevFrame); + decoupled_main_frame = ceil(prevFrame); + inter_main = prevFrame - floor(prevFrame); + } + else + { + calcFrame(actor->modelData->curAnim, tic, inter, decoupled_main_frame, decoupled_next_frame); + } + } + } + else if (gl_interpolate_model_frames && !(smf_flags & MDL_NOINTERPOLATION)) { FState *nextState = curState->GetNextState(); if (curState != nextState && nextState) @@ -282,7 +367,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr // [BB] To interpolate at more than 35 fps we take tic fractions into account. float ticFraction = 0.; // [BB] In case the tic counter is frozen we have to leave ticFraction at zero. - if (ConsoleState == c_up && menuactive != MENU_On && !Level->isFrozen()) + if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !Level->isFrozen()) { ticFraction = I_GetTimeFrac(); } @@ -296,7 +381,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr { // [BB] Workaround for actors that use the same frame twice in a row. // Most of the standard Doom monsters do this in their see state. - if ((smf->flags & MDL_INTERPOLATEDOUBLEDFRAMES)) + if ((smf_flags & MDL_INTERPOLATEDOUBLEDFRAMES)) { const FState *prevState = curState - 1; if ((curState->sprite == prevState->sprite) && (curState->Frame == prevState->Frame)) @@ -311,86 +396,143 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr } } if (nextState && inter != 0.0) - smfNext = FindModelFrame(ti, nextState->sprite, nextState->Frame, false); + smfNext = FindModelFrame(actor, nextState->sprite, nextState->Frame, false); } } } - int modelsamount = smf->modelsAmount; + unsigned modelsamount = smf->modelsAmount; //[SM] - if we added any models for the frame to also render, then we also need to update modelsAmount for this smf if (actor->modelData != nullptr) { - if (actor->modelData->modelIDs.Size() > (unsigned)modelsamount) - modelsamount = actor->modelData->modelIDs.Size(); + if (actor->modelData->models.Size() > modelsamount) + modelsamount = actor->modelData->models.Size(); } TArray surfaceskinids; - TArray boneData = TArray(); + TArray boneData; int boneStartingPosition = 0; bool evaluatedSingle = false; - for (int i = 0; i < modelsamount; i++) + for (unsigned i = 0; i < modelsamount; i++) { int modelid = -1; int animationid = -1; int modelframe = -1; int modelframenext = -1; - FTextureID skinid; skinid.SetInvalid(); + FTextureID skinid(nullptr); surfaceskinids.Clear(); + if (actor->modelData != nullptr) { - if (i < (int)actor->modelData->modelIDs.Size()) - modelid = actor->modelData->modelIDs[i]; + //modelID + if (actor->modelData->models.Size() > i && actor->modelData->models[i].modelID >= 0) + { + modelid = actor->modelData->models[i].modelID; + } + else if(actor->modelData->models.Size() > i && actor->modelData->models[i].modelID == -2) + { + continue; + } + else if(smf->modelsAmount > i) + { + modelid = smf->modelIDs[i]; + } - if (i < (int)actor->modelData->animationIDs.Size()) + //animationID + if (actor->modelData->animationIDs.Size() > i && actor->modelData->animationIDs[i] >= 0) + { animationid = actor->modelData->animationIDs[i]; - - if (i < (int)actor->modelData->modelFrameGenerators.Size()) + } + else if(smf->modelsAmount > i) { - //[SM] - We will use this little snippet to allow a modder to specify a model index to clone. It's also pointless to clone something that clones something else in this case. And causes me headaches. - if (actor->modelData->modelFrameGenerators[i] >= 0 && actor->modelData->modelFrameGenerators[i] <= modelsamount && smf->modelframes[actor->modelData->modelFrameGenerators[i]] != -1) - { + animationid = smf->animationIDs[i]; + } + if(!is_decoupled) + { + //modelFrame + if (actor->modelData->modelFrameGenerators.Size() > i + && (unsigned)actor->modelData->modelFrameGenerators[i] < modelsamount + && smf->modelframes[actor->modelData->modelFrameGenerators[i]] >= 0 + ) { modelframe = smf->modelframes[actor->modelData->modelFrameGenerators[i]]; - if (smfNext) modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]]; + + if (smfNext) + { + if(smfNext->modelframes[actor->modelData->modelFrameGenerators[i]] >= 0) + { + modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]]; + } + else + { + modelframenext = smfNext->modelframes[i]; + } + } } + else if(smf->modelsAmount > i) + { + modelframe = smf->modelframes[i]; + if (smfNext) modelframenext = smfNext->modelframes[i]; + } + } + + //skinID + if (actor->modelData->skinIDs.Size() > i && actor->modelData->skinIDs[i].isValid()) + { + skinid = actor->modelData->skinIDs[i]; } - if (i < (int)actor->modelData->skinIDs.Size()) + else if(smf->modelsAmount > i) { - if (actor->modelData->skinIDs[i].isValid()) - skinid = actor->modelData->skinIDs[i]; + skinid = smf->skinIDs[i]; } - for (int surface = i * MD3_MAX_SURFACES; surface < (i + 1) * MD3_MAX_SURFACES; surface++) + + //surfaceSkinIDs + if(actor->modelData->models.Size() > i && actor->modelData->models[i].surfaceSkinIDs.Size() > 0) { - if (surface < (int)actor->modelData->surfaceSkinIDs.Size()) + unsigned sz1 = smf->surfaceskinIDs.Size(); + unsigned sz2 = actor->modelData->models[i].surfaceSkinIDs.Size(); + unsigned start = i * MD3_MAX_SURFACES; + + surfaceskinids = actor->modelData->models[i].surfaceSkinIDs; + surfaceskinids.Resize(MD3_MAX_SURFACES); + + for (unsigned surface = 0; surface < MD3_MAX_SURFACES; surface++) { - if (actor->modelData->surfaceSkinIDs[surface].isValid()) + if (sz2 > surface && (actor->modelData->models[i].surfaceSkinIDs[surface].isValid())) + { + continue; + } + if((surface + start) < sz1) + { + surfaceskinids[surface] = smf->surfaceskinIDs[surface + start]; + } + else { - // only make a copy of the surfaceskinIDs array if really needed - if (surfaceskinids.Size() == 0) surfaceskinids = smf->surfaceskinIDs; - surfaceskinids[surface] = actor->modelData->surfaceSkinIDs[surface]; + surfaceskinids[surface].SetNull(); } } } } - if (i < smf->modelsAmount) + else { - if (modelid == -1) modelid = smf->modelIDs[i]; - if (animationid == -1) animationid = smf->animationIDs[i]; - if (modelframe == -1) modelframe = smf->modelframes[i]; - if (modelframenext == -1 && smfNext) modelframenext = smfNext->modelframes[i]; - if (!skinid.isValid()) skinid = smf->skinIDs[i]; + modelid = smf->modelIDs[i]; + animationid = smf->animationIDs[i]; + modelframe = smf->modelframes[i]; + if (smfNext) modelframenext = smfNext->modelframes[i]; + skinid = smf->skinIDs[i]; } - if (modelid >= 0) + if (modelid >= 0 && modelid < Models.size()) { FModel * mdl = Models[modelid]; auto tex = skinid.isValid() ? TexMan.GetGameTexture(skinid, true) : nullptr; mdl->BuildVertexBuffer(renderer); - auto& ssids = surfaceskinids.Size() > 0 ? surfaceskinids : smf->surfaceskinIDs; - auto ssidp = (unsigned)(i * MD3_MAX_SURFACES) < ssids.Size() ? &ssids[i * MD3_MAX_SURFACES] : nullptr; + auto ssidp = surfaceskinids.Size() > 0 + ? surfaceskinids.Data() + : (((i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.Size()) ? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr); bool nextFrame = smfNext && modelframe != modelframenext; @@ -404,29 +546,47 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr GC::WriteBarrier(actor, ptr); } - if (animationid >= 0) + // [RL0] while per-model animations aren't done, DECOUPLEDANIMATIONS does the same as MODELSAREATTACHMENTS + if ((!(smf_flags & MDL_MODELSAREATTACHMENTS) && !is_decoupled) || !evaluatedSingle) { - FModel* animation = Models[animationid]; - const TArray* animationData = animation->AttachAnimationData(); - - if (!(smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false) + if (animationid >= 0) { - boneData = animation->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, animationData, actor->boneComponentData, i); + FModel* animation = Models[animationid]; + const TArray* animationData = animation->AttachAnimationData(); + + if(is_decoupled) + { + if(decoupled_main_frame != -1) + { + boneData = animation->CalculateBones(decoupled_main_frame, decoupled_next_frame, inter, decoupled_main_prev_frame, inter_main, decoupled_next_prev_frame, inter_next, animationData, actor->boneComponentData, i); + } + } + else + { + boneData = animation->CalculateBones(modelframe, modelframenext, nextFrame ? inter : -1.f, 0, -1.f, 0, -1.f, animationData, actor->boneComponentData, i); + } boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1); evaluatedSingle = true; } - } - else - { - if (!(smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false) + else { - boneData = mdl->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, nullptr, actor->boneComponentData, i); + if(is_decoupled) + { + if(decoupled_main_frame != -1) + { + boneData = mdl->CalculateBones(decoupled_main_frame, decoupled_next_frame, inter, decoupled_main_prev_frame, inter_main, decoupled_next_prev_frame, inter_next, nullptr, actor->boneComponentData, i); + } + } + else + { + boneData = mdl->CalculateBones(modelframe, modelframenext, nextFrame ? inter : -1.f, 0, -1.f, 0, -1.f, nullptr, actor->boneComponentData, i); + } boneStartingPosition = renderer->SetupFrame(mdl, 0, 0, 0, boneData, -1); evaluatedSingle = true; } } - mdl->RenderFrame(renderer, tex, modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, translation, ssidp, boneData, boneStartingPosition); + mdl->RenderFrame(renderer, tex, modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : -1.f, translation, ssidp, boneData, boneStartingPosition); } } } @@ -441,7 +601,7 @@ static TArray SpriteModelHash; // //=========================================================================== -static void ParseModelDefLump(int Lump); +void ParseModelDefLump(int Lump); void InitModels() { @@ -523,7 +683,7 @@ void InitModels() } } -static void ParseModelDefLump(int Lump) +void ParseModelDefLump(int Lump) { FScanner sc(Lump); while (sc.GetString()) @@ -809,6 +969,16 @@ static void ParseModelDefLump(int Lump) } } } + else if (sc.Compare("baseframe")) + { + FSpriteModelFrame *smfp = &BaseSpriteModelFrames.Insert(type, smf); + for(int modelID : smf.modelIDs) + { + if(modelID >= 0) + Models[modelID]->baseFrame = smfp; + } + GetDefaultByType(type)->hasmodel = true; + } else if (sc.Compare("frameindex") || sc.Compare("frame")) { bool isframe=!!sc.Compare("frame"); @@ -893,6 +1063,10 @@ static void ParseModelDefLump(int Lump) { smf.flags |= MDL_CORRECTPIXELSTRETCH; } + else if (sc.Compare("forcecullbackfaces")) + { + smf.flags |= MDL_FORCECULLBACKFACES; + } else { sc.ScriptMessage("Unrecognized string \"%s\"", sc.String); @@ -923,24 +1097,33 @@ static void ParseModelDefLump(int Lump) // //=========================================================================== -FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped) +FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped) { - if (GetDefaultByType(ti)->hasmodel) + auto def = GetDefaultByType(ti); + if (def->hasmodel) { - FSpriteModelFrame smf; + if(def->flags9 & MF9_DECOUPLEDANIMATIONS) + { + FSpriteModelFrame * smf = BaseSpriteModelFrames.CheckKey((void*)ti); + if(smf) return smf; + } + else + { + FSpriteModelFrame smf; - memset(&smf, 0, sizeof(smf)); - smf.type=ti; - smf.sprite=sprite; - smf.frame=frame; + memset(&smf, 0, sizeof(smf)); + smf.type=ti; + smf.sprite=sprite; + smf.frame=frame; - int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; + int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; - while (hash>=0) - { - FSpriteModelFrame * smff = &SpriteModelFrames[hash]; - if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff; - hash=smff->hashnext; + while (hash>=0) + { + FSpriteModelFrame * smff = &SpriteModelFrames[hash]; + if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff; + hash=smff->hashnext; + } } } @@ -962,6 +1145,20 @@ FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, boo return nullptr; } +FSpriteModelFrame * FindModelFrame(const AActor * thing, int sprite, int frame, bool dropped) +{ + if(!thing) return nullptr; + + if(thing->flags9 & MF9_DECOUPLEDANIMATIONS) + { + return BaseSpriteModelFrames.CheckKey((thing->modelData != nullptr && thing->modelData->modelDef != nullptr) ? thing->modelData->modelDef : thing->GetClass()); + } + else + { + return FindModelFrameRaw((thing->modelData != nullptr && thing->modelData->modelDef != nullptr) ? thing->modelData->modelDef : thing->GetClass(), sprite, frame, dropped); + } +} + //=========================================================================== // // IsHUDModelForPlayerAvailable @@ -976,8 +1173,13 @@ bool IsHUDModelForPlayerAvailable (player_t * player) // [MK] check that at least one psprite uses models for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext()) { - FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelData != nullptr ? psp->Caller->modelData->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelData->modelDef) : psp->Caller->GetClass() : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr; - if ( smf != nullptr ) return true; + if ( FindModelFrame(psp->Caller, psp->GetSprite(), psp->GetFrame(), false) != nullptr ) return true; } return false; } + + +unsigned int FSpriteModelFrame::getFlags(class DActorModelData * defs) const +{ + return (defs && defs->flags & MODELDATA_OVERRIDE_FLAGS)? (flags | defs->overrideFlagsSet) & ~(defs->overrideFlagsClear) : flags; +} \ No newline at end of file diff --git a/src/r_data/models.h b/src/r_data/models.h index 568ad5399a..4a7154446b 100644 --- a/src/r_data/models.h +++ b/src/r_data/models.h @@ -45,23 +45,25 @@ enum { // [BB] Color translations for the model skin are ignored. This is // useful if the skin texture is not using the game palette. - MDL_IGNORETRANSLATION = 1, - MDL_PITCHFROMMOMENTUM = 2, - MDL_ROTATING = 4, - MDL_INTERPOLATEDOUBLEDFRAMES = 8, - MDL_NOINTERPOLATION = 16, - MDL_USEACTORPITCH = 32, - MDL_USEACTORROLL = 64, - MDL_BADROTATION = 128, - MDL_DONTCULLBACKFACES = 256, - MDL_USEROTATIONCENTER = 512, - MDL_NOPERPIXELLIGHTING = 1024, // forces a model to not use per-pixel lighting. useful for voxel-converted-to-model objects. - MDL_SCALEWEAPONFOV = 2048, // scale weapon view model with higher user FOVs - MDL_MODELSAREATTACHMENTS = 4096, // any model index after 0 is treated as an attachment, and therefore will use the bone results of index 0 - MDL_CORRECTPIXELSTRETCH = 8192, // ensure model does not distort with pixel stretch when pitch/roll is applied + MDL_IGNORETRANSLATION = 1<<0, + MDL_PITCHFROMMOMENTUM = 1<<1, + MDL_ROTATING = 1<<2, + MDL_INTERPOLATEDOUBLEDFRAMES = 1<<3, + MDL_NOINTERPOLATION = 1<<4, + MDL_USEACTORPITCH = 1<<5, + MDL_USEACTORROLL = 1<<6, + MDL_BADROTATION = 1<<7, + MDL_DONTCULLBACKFACES = 1<<8, + MDL_USEROTATIONCENTER = 1<<9, + MDL_NOPERPIXELLIGHTING = 1<<10, // forces a model to not use per-pixel lighting. useful for voxel-converted-to-model objects. + MDL_SCALEWEAPONFOV = 1<<11, // scale weapon view model with higher user FOVs + MDL_MODELSAREATTACHMENTS = 1<<12, // any model index after 0 is treated as an attachment, and therefore will use the bone results of index 0 + MDL_CORRECTPIXELSTRETCH = 1<<13, // ensure model does not distort with pixel stretch when pitch/roll is applied + MDL_FORCECULLBACKFACES = 1<<14, }; -FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped); +FSpriteModelFrame * FindModelFrame(const AActor * thing, int sprite, int frame, bool dropped); +FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped); bool IsHUDModelForPlayerAvailable(player_t * player); // Check if circle potentially intersects with node AABB diff --git a/src/r_data/portalgroups.cpp b/src/r_data/portalgroups.cpp index 8d682b78e7..b7f0e7255d 100644 --- a/src/r_data/portalgroups.cpp +++ b/src/r_data/portalgroups.cpp @@ -400,7 +400,7 @@ static void GroupLinePortals(FLevelLocals *Level) for (unsigned i = 0; i < Level->linePortals.Size(); i++) { - auto port = Level->linePortals[i]; + const auto& port = Level->linePortals[i]; bool gotsome; if (tempindex[i] == -1) diff --git a/src/r_data/r_canvastexture.cpp b/src/r_data/r_canvastexture.cpp index c12d42e764..49e4e8ab20 100644 --- a/src/r_data/r_canvastexture.cpp +++ b/src/r_data/r_canvastexture.cpp @@ -98,7 +98,7 @@ void FCanvasTextureInfo::Add (AActor *viewpoint, FTextureID picnum, double fov) void SetCameraToTexture(AActor *viewpoint, const FString &texturename, double fov) { - FTextureID textureid = TexMan.CheckForTexture(texturename, ETextureType::Wall, FTextureManager::TEXMAN_Overridable); + FTextureID textureid = TexMan.CheckForTexture(texturename.GetChars(), ETextureType::Wall, FTextureManager::TEXMAN_Overridable); if (textureid.isValid()) { // Only proceed if the texture actually has a canvas. diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 0f130e30a6..8b197cda7d 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -54,6 +54,14 @@ #include "gi.h" +//---------------------------------------------------------------------------- +// +// helper stuff for serializing TRANSLATION_User +// +//---------------------------------------------------------------------------- + +static TArray> usertransmap; + //---------------------------------------------------------------------------- // // @@ -69,6 +77,7 @@ static void SerializeRemap(FSerializer &arc, FRemapTable &remap) void StaticSerializeTranslations(FSerializer &arc) { + usertransmap.Clear(); if (arc.BeginArray("translations")) { // Does this level have custom translations? @@ -79,7 +88,7 @@ void StaticSerializeTranslations(FSerializer &arc) auto size = GPalette.NumTranslations(TRANSLATION_LevelScripted); for (unsigned int i = 0; i < size; ++i) { - trans = GPalette.TranslationToTable(TRANSLATION(TRANSLATION_LevelScripted, i)); + trans = GPalette.GetTranslation(TRANSLATION_LevelScripted, i); if (trans != NULL && !trans->IsIdentity()) { if (arc.BeginObject(nullptr)) @@ -104,6 +113,60 @@ void StaticSerializeTranslations(FSerializer &arc) } arc.EndArray(); } + if (arc.BeginArray("usertranslations")) + { + // Does this level have custom translations? + FRemapTable* trans; + int w; + if (arc.isWriting()) + { + auto size = GPalette.NumTranslations(TRANSLATION_User); + for (unsigned int i = 0; i < size; ++i) + { + trans = GPalette.GetTranslation(TRANSLATION_User, i); + if (trans != NULL && !trans->IsIdentity()) + { + if (arc.BeginObject(nullptr)) + { + arc("index", i); + SerializeRemap(arc, *trans); + arc.EndObject(); + } + } + } + } + else + { + while (arc.BeginObject(nullptr)) + { + arc("index", w); + FRemapTable remap; + SerializeRemap(arc, remap); + // do not add the translation to the global list yet. We want to avoid adding tables that are not needed anymore. + usertransmap.Push(std::make_pair(TRANSLATION(TRANSLATION_User, w), remap)); + arc.EndObject(); + } + } + arc.EndArray(); + } +} + +void StaticClearSerializeTranslationsData() +{ + usertransmap.Reset(); +} + +FTranslationID RemapUserTranslation(FTranslationID trans) +{ + if (GetTranslationType(trans) == TRANSLATION_User) + { + for (auto& check : usertransmap) + { + if (trans == check.first) + return GPalette.AddTranslation(TRANSLATION_User, &check.second); + } + } + return trans; } //---------------------------------------------------------------------------- @@ -114,7 +177,7 @@ void StaticSerializeTranslations(FSerializer &arc) static TArray BloodTranslationColors; -int CreateBloodTranslation(PalEntry color) +FTranslationID CreateBloodTranslation(PalEntry color) { unsigned int i; @@ -132,7 +195,7 @@ int CreateBloodTranslation(PalEntry color) color.b == BloodTranslationColors[i].b) { // A duplicate of this translation already exists - return i; + return TRANSLATION(TRANSLATION_Blood, i); } } if (BloodTranslationColors.Size() >= MAX_DECORATE_TRANSLATIONS) @@ -152,7 +215,7 @@ int CreateBloodTranslation(PalEntry color) trans.Remap[i] = entry; } GPalette.AddTranslation(TRANSLATION_Blood, &trans); - return BloodTranslationColors.Push(color); + return TRANSLATION(TRANSLATION_Blood, BloodTranslationColors.Push(color)); } //---------------------------------------------------------------------------- @@ -430,8 +493,8 @@ static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerC } else { - FileData translump = fileSystem.ReadFile(colorset->Lump); - const uint8_t *trans = (const uint8_t *)translump.GetMem(); + auto translump = fileSystem.ReadFile(colorset->Lump); + auto trans = translump.bytes(); for (i = start; i <= end; ++i) { table->Remap[i] = GPalette.Remap[trans[i]]; @@ -614,7 +677,7 @@ DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation) if (cls != nullptr) { - PlayerSkin = R_FindSkin(Skins[PlayerSkin].Name, int(cls - &PlayerClasses[0])); + PlayerSkin = R_FindSkin(Skins[PlayerSkin].Name.GetChars(), int(cls - &PlayerClasses[0])); FRemapTable remap; R_GetPlayerTranslation(PlayerColor, GetColorSet(cls->Type, PlayerColorset), &Skins[PlayerSkin], &remap); @@ -628,9 +691,9 @@ DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation) // // //---------------------------------------------------------------------------- -static TMap customTranslationMap; +static TMap customTranslationMap; -int R_FindCustomTranslation(FName name) +FTranslationID R_FindCustomTranslation(FName name) { switch (name.GetIndex()) { @@ -639,7 +702,7 @@ int R_FindCustomTranslation(FName name) return TRANSLATION(TRANSLATION_Standard, 7); case NAME_None: - return 0; + return NO_TRANSLATION; case NAME_RainPillar1: case NAME_RainPillar2: @@ -662,15 +725,8 @@ int R_FindCustomTranslation(FName name) return TRANSLATION(TRANSLATION_Players, name.GetIndex() - NAME_Player1); } - int *t = customTranslationMap.CheckKey(name); - return (t != nullptr)? *t : -1; -} - -DEFINE_ACTION_FUNCTION(_Translation, GetID) -{ - PARAM_PROLOGUE; - PARAM_NAME(t); - ACTION_RETURN_INT(R_FindCustomTranslation(t)); + auto t = customTranslationMap.CheckKey(name); + return (t != nullptr)? *t : INVALID_TRANSLATION; } //---------------------------------------------------------------------------- @@ -705,16 +761,16 @@ void R_ParseTrnslate() { sc.ScriptError("Translation must be in the range [0,%d]", max); } - NewTranslation = *GPalette.TranslationToTable(TRANSLATION(TRANSLATION_Standard, sc.Number)); + NewTranslation = *GPalette.GetTranslation(TRANSLATION_Standard, sc.Number); } else if (sc.TokenType == TK_Identifier) { - int tnum = R_FindCustomTranslation(sc.String); - if (tnum == -1) + auto tnum = R_FindCustomTranslation(sc.String); + if (tnum == INVALID_TRANSLATION) { sc.ScriptError("Base translation '%s' not found in '%s'", sc.String, newtrans.GetChars()); } - NewTranslation = *GPalette.TranslationToTable(tnum); + NewTranslation = *GPalette.TranslationToTable(tnum.index()); } else { @@ -727,7 +783,7 @@ void R_ParseTrnslate() do { sc.MustGetToken(TK_StringConst); - int pallump = fileSystem.CheckNumForFullName(sc.String, true, ns_global); + int pallump = fileSystem.CheckNumForFullName(sc.String, true, FileSys::ns_global); if (pallump >= 0) // { int start = 0; @@ -753,7 +809,7 @@ void R_ParseTrnslate() } } while (sc.CheckToken(',')); - int trans = GPalette.StoreTranslation(TRANSLATION_Custom, &NewTranslation); + auto trans = GPalette.StoreTranslation(TRANSLATION_Custom, &NewTranslation); customTranslationMap[newtrans] = trans; } } @@ -780,7 +836,7 @@ DEFINE_ACTION_FUNCTION(_Translation, AddTranslation) { NewTranslation.Remap[i] = ColorMatcher.Pick(self->colors[i]); } - int trans = GPalette.StoreTranslation(TRANSLATION_Custom, &NewTranslation); - ACTION_RETURN_INT(trans); + auto trans = GPalette.StoreTranslation(TRANSLATION_User, &NewTranslation); + ACTION_RETURN_INT(trans.index()); } diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index 534c497951..549f4b3a03 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -19,6 +19,7 @@ enum TRANSLATION_Blood, TRANSLATION_RainPillar, TRANSLATION_Custom, + TRANSLATION_User, NUM_TRANSLATION_TABLES }; @@ -38,12 +39,15 @@ void R_InitTranslationTables (void); void R_BuildPlayerTranslation (int player); // [RH] Actually create a player's translation table. void R_GetPlayerTranslation (int color, const struct FPlayerColorSet *colorset, class FPlayerSkin *skin, struct FRemapTable *table); -int CreateBloodTranslation(PalEntry color); +FTranslationID CreateBloodTranslation(PalEntry color); -int R_FindCustomTranslation(FName name); +FTranslationID R_FindCustomTranslation(FName name); void R_ParseTrnslate(); -void StaticSerializeTranslations(FSerializer& arc); +// serialization stuff. +void StaticSerializeTranslations(FSerializer& arc); +void StaticClearSerializeTranslationsData(); +FTranslationID RemapUserTranslation(FTranslationID trans); #endif // __R_TRANSLATE_H diff --git a/src/r_data/r_vanillatrans.h b/src/r_data/r_vanillatrans.h index 702fc82123..d6b6a5d9ee 100644 --- a/src/r_data/r_vanillatrans.h +++ b/src/r_data/r_vanillatrans.h @@ -30,6 +30,7 @@ **--------------------------------------------------------------------------- ** */ +#pragma once void UpdateVanillaTransparency(); diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index 07a106e65f..0a7be96a12 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -335,7 +335,7 @@ void R_InitSpriteDefs () for (i = 0; i < smax; ++i) { auto tex = TexMan.GameByIndex(i); - if (tex->GetUseType() == ETextureType::Sprite && strlen(tex->GetName()) >= 6) + if (tex->GetUseType() == ETextureType::Sprite && strlen(tex->GetName().GetChars()) >= 6) { size_t bucket = TEX_DWNAME(tex) % smax; hashes[i].Next = hashes[bucket].Head; @@ -349,15 +349,13 @@ void R_InitSpriteDefs () memset(vhashes.Data(), -1, sizeof(VHasher)*vmax); for (i = 0; i < vmax; ++i) { - if (fileSystem.GetFileNamespace(i) == ns_voxels) + if (fileSystem.GetFileNamespace(i) == FileSys::ns_voxels) { - char name[9]; size_t namelen; int spin; int sign; - fileSystem.GetFileShortName(name, i); - name[8] = 0; + const char* name = fileSystem.GetFileShortName(i); namelen = strlen(name); if (namelen < 4) { // name is too short @@ -717,17 +715,17 @@ void R_InitSkins (void) int lump = fileSystem.CheckNumForName (sc.String, Skins[i].namespc); if (lump == -1) { - lump = fileSystem.CheckNumForFullName (sc.String, true, ns_sounds); + lump = fileSystem.CheckNumForFullName (sc.String, true, FileSys::ns_sounds); } if (lump != -1) { if (stricmp (key, "*pain") == 0) { // Replace all pain sounds in one go - aliasid = S_AddPlayerSound (Skins[i].Name, Skins[i].gender, + aliasid = S_AddPlayerSound (Skins[i].Name.GetChars(), Skins[i].gender, playersoundrefs[0], lump, true); for (int l = 3; l > 0; --l) { - S_AddPlayerSoundExisting (Skins[i].Name, Skins[i].gender, + S_AddPlayerSoundExisting (Skins[i].Name.GetChars(), Skins[i].gender, playersoundrefs[l], aliasid, true); } } @@ -736,7 +734,7 @@ void R_InitSkins (void) auto sndref = soundEngine->FindSoundNoHash (key); if (sndref.isvalid()) { - S_AddPlayerSound (Skins[i].Name, Skins[i].gender, sndref, lump, true); + S_AddPlayerSound (Skins[i].Name.GetChars(), Skins[i].gender, sndref, lump, true); } } } @@ -750,7 +748,7 @@ void R_InitSkins (void) sndlumps[j] = fileSystem.CheckNumForName (sc.String, Skins[i].namespc); if (sndlumps[j] == -1) { // Replacement not found, try finding it in the global namespace - sndlumps[j] = fileSystem.CheckNumForFullName (sc.String, true, ns_sounds); + sndlumps[j] = fileSystem.CheckNumForFullName (sc.String, true, FileSys::ns_sounds); } } } @@ -812,9 +810,7 @@ void R_InitSkins (void) // specified, use whatever immediately follows the specifier lump. if (intname == 0) { - char name[9]; - fileSystem.GetFileShortName (name, base+1); - memcpy(&intname, name, 4); + memcpy(&intname, fileSystem.GetFileShortName(base + 1), 4); } int basens = fileSystem.GetFileNamespace(base); @@ -845,9 +841,8 @@ void R_InitSkins (void) for (k = base + 1; fileSystem.GetFileNamespace(k) == basens; k++) { - char lname[9]; + const char* lname = fileSystem.GetFileShortName(k); uint32_t lnameint; - fileSystem.GetFileShortName (lname, k); memcpy(&lnameint, lname, 4); if (lnameint == intname) { @@ -866,7 +861,7 @@ void R_InitSkins (void) break; } - fileSystem.GetFileShortName (temp.name, base+1); + memcpy(temp.name, fileSystem.GetFileShortName (base+1), 4); temp.name[4] = 0; int sprno = (int)sprites.Push (temp); if (spr==0) Skins[i].sprite = sprno; @@ -893,12 +888,12 @@ void R_InitSkins (void) { if (j == 0 || sndlumps[j] != sndlumps[j-1]) { - aliasid = S_AddPlayerSound (Skins[i].Name, Skins[i].gender, + aliasid = S_AddPlayerSound (Skins[i].Name.GetChars(), Skins[i].gender, playersoundrefs[j], sndlumps[j], true); } else { - S_AddPlayerSoundExisting (Skins[i].Name, Skins[i].gender, + S_AddPlayerSoundExisting (Skins[i].Name.GetChars(), Skins[i].gender, playersoundrefs[j], aliasid, true); } } @@ -951,8 +946,8 @@ CCMD (skins) static void R_CreateSkinTranslation (const char *palname) { - FileData lump = fileSystem.ReadFile (palname); - const uint8_t *otherPal = (uint8_t *)lump.GetMem(); + auto lump = fileSystem.ReadFile (palname); + auto otherPal = lump.bytes(); for (int i = 0; i < 256; ++i) { @@ -1021,7 +1016,7 @@ void R_InitSprites () Skins[i].range0end = basetype->IntVar(NAME_ColorRangeEnd); Skins[i].Scale = basetype->Scale; Skins[i].sprite = basetype->SpawnState->sprite; - Skins[i].namespc = ns_global; + Skins[i].namespc = FileSys::ns_global; PlayerClasses[i].Skins.Push (i); diff --git a/src/r_data/v_palette.cpp b/src/r_data/v_palette.cpp index 333cb7579b..8af454445d 100644 --- a/src/r_data/v_palette.cpp +++ b/src/r_data/v_palette.cpp @@ -44,6 +44,8 @@ #include "m_png.h" #include "v_colortables.h" +using namespace FileSys; + /* Current color blending values */ int BlendR, BlendG, BlendB, BlendA; @@ -63,7 +65,7 @@ void InitPalette () if (lump != -1) { FileData cmap = fileSystem.ReadFile(lump); - const unsigned char* cmapdata = (const unsigned char*)cmap.GetMem(); + auto cmapdata = cmap.bytes(); GPalette.GenerateGlobalBrightmapFromColormap(cmapdata, 32); MakeGoodRemap((uint32_t*)GPalette.BaseColors, GPalette.Remap, cmapdata + 7936); // last entry in colormap } diff --git a/src/r_data/voxeldef.cpp b/src/r_data/voxeldef.cpp index 1288621787..35037158b9 100644 --- a/src/r_data/voxeldef.cpp +++ b/src/r_data/voxeldef.cpp @@ -50,6 +50,8 @@ #include "g_level.h" #include "r_data/sprites.h" +using namespace FileSys; + struct VoxelOptions { int DroppedSpin = 0; diff --git a/src/rendering/2d/v_blend.cpp b/src/rendering/2d/v_blend.cpp index 9fdba41791..ec3a7a3908 100644 --- a/src/rendering/2d/v_blend.cpp +++ b/src/rendering/2d/v_blend.cpp @@ -250,6 +250,8 @@ FVector4 V_CalcBlend(sector_t* viewsector, PalEntry* modulateColor) auto s = viewsector->heightsec; blendv = s->floorplane.PointOnSide(vpp) < 0 ? s->bottommap : s->ceilingplane.PointOnSide(vpp) < 0 ? s->topmap : s->midmap; } + else if (viewsector->selfmap != 0) blendv = viewsector->selfmap; + else blendv = viewsector->Level->globalcolormap; } else { diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index bbc4c6bb7a..6d714f6000 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -3,387 +3,1176 @@ #include "doom_levelmesh.h" #include "g_levellocals.h" #include "texturemanager.h" +#include "playsim/p_lnspec.h" +#include "c_dispatch.h" +#include "g_levellocals.h" +#include "a_dynlight.h" +#include "hw_renderstate.h" +#include "hw_vertexbuilder.h" +#include "hwrenderer/scene/hw_drawstructs.h" +#include "hwrenderer/scene/hw_drawinfo.h" +#include "hwrenderer/scene/hw_walldispatcher.h" +#include "hwrenderer/scene/hw_flatdispatcher.h" +#include + +static bool RequireLevelMesh() +{ + if (level.levelMesh) + return true; + + Printf("No level mesh. Perhaps your level has no lightmap loaded?\n"); + return false; +} -DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap) +static bool RequireLightmap() { - for (unsigned int i = 0; i < doomMap.sides.Size(); i++) + if (!RequireLevelMesh()) + return false; + + if (level.lightmaps) + return true; + + Printf("Lightmap is not enabled in this level.\n"); + return false; +} + +ADD_STAT(lightmap) +{ + FString out; + DoomLevelMesh* levelMesh = level.levelMesh; + + if (!levelMesh || !level.lightmaps) { - CreateSideSurfaces(doomMap, &doomMap.sides[i]); + out.Format("No lightmap"); + return out; } - CreateSubsectorSurfaces(doomMap); + uint32_t atlasPixelCount = levelMesh->AtlasPixelCount(); + auto stats = levelMesh->GatherTilePixelStats(); - for (size_t i = 0; i < Surfaces.Size(); i++) + out.Format("Surfaces: %u (awaiting updates: %u)\nSurface pixel area to update: %u\nSurface pixel area: %u\nAtlas pixel area: %u\nAtlas efficiency: %.4f%%", + stats.tiles.total, stats.tiles.dirty, + stats.pixels.dirty, + stats.pixels.total, + atlasPixelCount, + float(stats.pixels.total) / float(atlasPixelCount) * 100.0f ); + + return out; +} + +CCMD(dumplevelmesh) +{ + if (!RequireLevelMesh()) return; + level.levelMesh->DumpMesh(FString("levelmesh.obj"), FString("levelmesh.mtl")); + Printf("Level mesh exported.\n"); +} + +CCMD(invalidatelightmap) +{ + if (!RequireLightmap()) return; + + int count = 0; + for (auto& tile : level.levelMesh->LightmapTiles) + { + if (!tile.NeedsUpdate) + ++count; + tile.NeedsUpdate = true; + } + Printf("Marked %d out of %d tiles for update.\n", count, level.levelMesh->LightmapTiles.Size()); +} + +void PrintSurfaceInfo(const DoomLevelMeshSurface* surface) +{ + if (!RequireLevelMesh()) return; + + auto gameTexture = surface->Texture; + + Printf("Surface %d (%p)\n Type: %d, TypeIndex: %d, ControlSector: %d\n", level.levelMesh->GetSurfaceIndex(surface), surface, surface->Type, surface->TypeIndex, surface->ControlSector ? surface->ControlSector->Index() : -1); + if (surface->LightmapTileIndex >= 0) { - const Surface &s = Surfaces[i]; - int numVerts = s.numVerts; - unsigned int pos = s.startVertIndex; - FVector3* verts = &MeshVertices[pos]; + LightmapTile* tile = &level.levelMesh->LightmapTiles[surface->LightmapTileIndex]; + Printf(" Atlas page: %d, x:%d, y:%d\n", tile->AtlasLocation.ArrayIndex, tile->AtlasLocation.X, tile->AtlasLocation.Y); + Printf(" Pixels: %dx%d (area: %d)\n", tile->AtlasLocation.Width, tile->AtlasLocation.Height, tile->AtlasLocation.Area()); + Printf(" Sample dimension: %d\n", tile->SampleDimension); + Printf(" Needs update?: %d\n", tile->NeedsUpdate); + } + Printf(" Always update?: %d\n", surface->AlwaysUpdate); + Printf(" Sector group: %d\n", surface->SectorGroup); + Printf(" Texture: '%s'\n", gameTexture ? gameTexture->GetName().GetChars() : ""); + Printf(" Alpha: %f\n", surface->Alpha); +} - for (int j = 0; j < numVerts; j++) - { - MeshUVIndex.Push(j); - } +FVector3 RayDir(FAngle angle, FAngle pitch) +{ + auto pc = float(pitch.Cos()); + return FVector3{ pc * float(angle.Cos()), pc * float(angle.Sin()), -float(pitch.Sin()) }; +} + +DVector3 RayDir(DAngle angle, DAngle pitch) +{ + auto pc = pitch.Cos(); + return DVector3{ pc * (angle.Cos()), pc * (angle.Sin()), -(pitch.Sin()) }; +} + +CCMD(surfaceinfo) +{ + if (!RequireLevelMesh()) return; + + auto pov = players[consoleplayer].mo; + if (!pov) + { + Printf("players[consoleplayer].mo is null.\n"); + return; + } + + auto posXYZ = FVector3(pov->Pos()); + posXYZ.Z = float(players[consoleplayer].viewz); + auto angle = pov->Angles.Yaw; + auto pitch = pov->Angles.Pitch; - if (s.type == ST_FLOOR || s.type == ST_CEILING) + const auto surface = (DoomLevelMeshSurface*)level.levelMesh->Trace(posXYZ, FVector3(RayDir(angle, pitch)), 32000.0f); + if (surface) + { + PrintSurfaceInfo(surface); + } + else + { + Printf("No surface was hit.\n"); + } +} + +EXTERN_CVAR(Float, lm_scale); + +///////////////////////////////////////////////////////////////////////////// + +DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap) +{ + // Remove the empty mesh added in the LevelMesh constructor + Mesh.Vertices.clear(); + Mesh.Indexes.clear(); + + SunColor = doomMap.SunColor; // TODO keep only one copy? + SunDirection = doomMap.SunDirection; + + BuildSectorGroups(doomMap); + CreatePortals(doomMap); + + LightmapSampleDistance = doomMap.LightmapSampleDistance; + + CreateSurfaces(doomMap); + LinkSurfaces(doomMap); + + SortIndexes(); + BuildTileSurfaceLists(); + + Mesh.DynamicIndexStart = Mesh.Indexes.size(); + UpdateCollision(); + + // Assume double the size of the static mesh will be enough for anything dynamic. + Mesh.MaxVertices = std::max(Mesh.Vertices.size() * 2, (size_t)10000); + Mesh.MaxIndexes = std::max(Mesh.Indexes.size() * 2, (size_t)10000); + Mesh.MaxSurfaces = std::max(Mesh.SurfaceIndexes.size() * 2, (size_t)10000); + Mesh.MaxUniforms = std::max(Mesh.Uniforms.size() * 2, (size_t)10000); + Mesh.MaxSurfaceIndexes = std::max(Mesh.SurfaceIndexes.size() * 2, (size_t)10000); + Mesh.MaxNodes = std::max(Collision->get_nodes().size() * 2, (size_t)10000); + Mesh.MaxLights = 100'000; + Mesh.MaxLightIndexes = 4 * 1024 * 1024; +} + +void DoomLevelMesh::CreateLights(FLevelLocals& doomMap) +{ + if (Mesh.Lights.Size() != 0) + return; + + for (DoomLevelMeshSurface& surface : Surfaces) + { + surface.LightList.Pos = Mesh.LightIndexes.Size(); + surface.LightList.Count = 0; + + std::pair nodePortalGroup = GetSurfaceLightNode(&surface); + FLightNode* node = nodePortalGroup.first; + int portalgroup = nodePortalGroup.second; + if (!node) + continue; + + int listpos = 0; + while (node) { - for (int j = 2; j < numVerts; j++) + FDynamicLight* light = node->lightsource; + if (light && light->Trace()) { - if (!IsDegenerate(verts[0], verts[j - 1], verts[j])) + int lightindex = GetLightIndex(light, portalgroup); + if (lightindex >= 0) { - MeshElements.Push(pos); - MeshElements.Push(pos + j - 1); - MeshElements.Push(pos + j); - MeshSurfaces.Push((int)i); + Mesh.LightIndexes.Push(lightindex); + surface.LightList.Count++; } } + node = node->nextLight; } - else if (s.type == ST_MIDDLEWALL || s.type == ST_UPPERWALL || s.type == ST_LOWERWALL) + } +} + +int DoomLevelMesh::GetLightIndex(FDynamicLight* light, int portalgroup) +{ + int index; + for (index = 0; index < FDynamicLight::max_levelmesh_entries && light->levelmesh[index].index != 0; index++) + { + if (light->levelmesh[index].portalgroup == portalgroup) + return light->levelmesh[index].index - 1; + } + if (index == FDynamicLight::max_levelmesh_entries) + return 0; + + DVector3 pos = light->PosRelative(portalgroup); + + LevelMeshLight meshlight; + meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z }; + meshlight.RelativeOrigin = meshlight.Origin; + meshlight.Radius = (float)light->GetRadius(); + meshlight.Intensity = light->target ? (float)light->target->Alpha : 1.0f; + if (light->IsSpot() && light->pSpotInnerAngle && light->pSpotOuterAngle && light->pPitch && light->target) + { + meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos(); + meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos(); + + DAngle negPitch = -*light->pPitch; + DAngle Angle = light->target->Angles.Yaw; + double xzLen = negPitch.Cos(); + meshlight.SpotDir.X = float(-Angle.Cos() * xzLen); + meshlight.SpotDir.Y = float(-Angle.Sin() * xzLen); + meshlight.SpotDir.Z = float(-negPitch.Sin()); + } + else + { + meshlight.InnerAngleCos = -1.0f; + meshlight.OuterAngleCos = -1.0f; + meshlight.SpotDir.X = 0.0f; + meshlight.SpotDir.Y = 0.0f; + meshlight.SpotDir.Z = 0.0f; + } + meshlight.Color.X = light->GetRed() * (1.0f / 255.0f); + meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f); + meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f); + + meshlight.SourceRadius = light->GetSourceRadius(); + + if (light->Sector) + meshlight.SectorGroup = sectorGroup[light->Sector->Index()]; + else + meshlight.SectorGroup = 0; + + int lightindex = Mesh.Lights.Size(); + light->levelmesh[index].index = lightindex + 1; + light->levelmesh[index].portalgroup = portalgroup; + Mesh.Lights.Push(meshlight); + return lightindex; +} + +void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap) +{ + CreateLights(doomMap); +#if 0 + static_cast(DynamicMesh.get())->Update(doomMap); + if (doomMap.lightmaps) + { + DynamicMesh->SetupTileTransforms(); + DynamicMesh->PackLightmapAtlas(StaticMesh->LMTextureCount); + } +#endif +} + +bool DoomLevelMesh::TraceSky(const FVector3& start, FVector3 direction, float dist) +{ + FVector3 end = start + direction * dist; + auto surface = Trace(start, direction, dist); + return surface && surface->IsSky; +} + +std::pair DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf) +{ + FLightNode* node = nullptr; + int portalgroup = 0; + if (doomsurf->Type == ST_FLOOR || doomsurf->Type == ST_CEILING) + { + node = doomsurf->Subsector->section->lighthead; + portalgroup = doomsurf->Subsector->sector->PortalGroup; + } + else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE) + { + bool isPolyLine = !!(doomsurf->Side->Flags & WALLF_POLYOBJ); + if (isPolyLine) { - if (!IsDegenerate(verts[0], verts[1], verts[2])) - { - MeshElements.Push(pos + 0); - MeshElements.Push(pos + 1); - MeshElements.Push(pos + 2); - MeshSurfaces.Push((int)i); - } - if (!IsDegenerate(verts[1], verts[2], verts[3])) - { - MeshElements.Push(pos + 3); - MeshElements.Push(pos + 2); - MeshElements.Push(pos + 1); - MeshSurfaces.Push((int)i); - } + subsector_t* subsector = level.PointInRenderSubsector((doomsurf->Side->V1()->fPos() + doomsurf->Side->V2()->fPos()) * 0.5); + node = subsector->section->lighthead; + portalgroup = subsector->sector->PortalGroup; + } + else + { + node = doomsurf->Side->lighthead; + portalgroup = doomsurf->Side->sector->PortalGroup; } } - - Collision = std::make_unique(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size()); + return { node, portalgroup }; } -void DoomLevelMesh::CreateSideSurfaces(FLevelLocals &doomMap, side_t *side) +void DoomLevelMesh::CreateSurfaces(FLevelLocals& doomMap) { - sector_t *front; - sector_t *back; + bindings.clear(); + Sides.clear(); + Flats.clear(); + Sides.resize(doomMap.sides.size()); + Flats.resize(doomMap.sectors.Size()); + + // Create surface objects for all sides + for (unsigned int i = 0; i < doomMap.sides.Size(); i++) + { + side_t* side = &doomMap.sides[i]; + bool isPolyLine = !!(side->Flags & WALLF_POLYOBJ); + if (isPolyLine) + continue; - front = side->sector; - back = (side->linedef->frontsector == front) ? side->linedef->backsector : side->linedef->frontsector; + UpdateSide(doomMap, i); + } + + // Create surfaces for all flats + for (unsigned int i = 0; i < doomMap.sectors.Size(); i++) + { + sector_t* sector = &doomMap.sectors[i]; + if (sector->subsectors[0]->flags & SSECF_POLYORG) + continue; + UpdateFlat(doomMap, i); + } +} - if (IsControlSector(front)) +void DoomLevelMesh::UpdateSide(FLevelLocals& doomMap, unsigned int sideIndex) +{ + side_t* side = &doomMap.sides[sideIndex]; + seg_t* seg = side->segs[0]; + if (!seg) return; - FVector2 v1 = ToFVector2(side->V1()->fPos()); - FVector2 v2 = ToFVector2(side->V2()->fPos()); + subsector_t* sub = seg->Subsector; + + sector_t* front = side->sector; + sector_t* back = (side->linedef->frontsector == front) ? side->linedef->backsector : side->linedef->frontsector; + + HWMeshHelper result; + HWWallDispatcher disp(&doomMap, &result, getRealLightmode(&doomMap, true)); + HWWall wall; + wall.sub = sub; + wall.Process(&disp, state, seg, front, back); - float v1Top = (float)front->ceilingplane.ZatPoint(v1); - float v1Bottom = (float)front->floorplane.ZatPoint(v1); - float v2Top = (float)front->ceilingplane.ZatPoint(v2); - float v2Bottom = (float)front->floorplane.ZatPoint(v2); + // Part 1: solid geometry. This is set up so that there are no transparent parts + state.SetDepthFunc(DF_LEqual); + state.ClearDepthBias(); + state.EnableTexture(true); + state.EnableBrightmap(true); + state.AlphaFunc(Alpha_GEqual, 0.f); + CreateWallSurface(side, disp, state, result.list, false, true); + + for (HWWall& portal : result.portals) + { + WallPortals.Push(portal); + } - int typeIndex = side->Index(); + CreateWallSurface(side, disp, state, result.portals, true, false); - FVector2 dx(v2.X - v1.X, v2.Y - v1.Y); - float distance = dx.Length(); + /* + // final pass: translucent stuff + state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + state.SetRenderStyle(STYLE_Translucent); + CreateWallSurface(side, disp, state, result.translucent, false, true); + state.AlphaFunc(Alpha_GEqual, 0.f); + state.SetRenderStyle(STYLE_Normal); + */ +} - if (back) +void DoomLevelMesh::UpdateFlat(FLevelLocals& doomMap, unsigned int sectorIndex) +{ + sector_t* sector = &doomMap.sectors[sectorIndex]; + for (FSection& section : doomMap.sections.SectionsForSector(sectorIndex)) { - for (unsigned int j = 0; j < front->e->XFloor.ffloors.Size(); j++) + HWFlatMeshHelper result; + HWFlatDispatcher disp(&doomMap, &result, getRealLightmode(&doomMap, true)); + + HWFlat flat; + flat.section = §ion; + flat.ProcessSector(&disp, state, sector); + + // Part 1: solid geometry. This is set up so that there are no transparent parts + state.SetDepthFunc(DF_LEqual); + state.ClearDepthBias(); + state.EnableTexture(true); + state.EnableBrightmap(true); + CreateFlatSurface(disp, state, result.list, false, false); + + CreateFlatSurface(disp, state, result.portals, true, false); + + // final pass: translucent stuff + state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + state.SetRenderStyle(STYLE_Translucent); + CreateFlatSurface(disp, state, result.translucentborder, false, true); + state.SetDepthMask(false); + CreateFlatSurface(disp, state, result.translucent, false, true); + state.AlphaFunc(Alpha_GEqual, 0.f); + state.SetDepthMask(true); + state.SetRenderStyle(STYLE_Normal); + } +} + +void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray& list, bool isPortal, bool translucent) +{ + for (HWWall& wallpart : list) + { + if (isPortal) + { + state.SetEffect(EFF_PORTAL); + state.EnableTexture(false); + state.SetRenderStyle(STYLE_Normal); + + wallpart.MakeVertices(state, false); + wallpart.RenderWall(state, HWWall::RWF_BLANK); + wallpart.vertcount = 0; + + wallpart.LevelMeshInfo.Type = ST_NONE; + wallpart.LevelMeshInfo.ControlSector = nullptr; + + state.SetEffect(EFF_NONE); + state.EnableTexture(true); + } + else + { + if (wallpart.texture && wallpart.texture->isMasked()) + { + state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + } + else + { + state.AlphaFunc(Alpha_GEqual, 0.f); + } + + wallpart.DrawWall(&disp, state, translucent); + } + + int pipelineID = 0; + int startVertIndex = Mesh.Vertices.Size(); + int startElementIndex = Mesh.Indexes.Size(); + for (auto& it : state.mSortedLists) { - F3DFloor *xfloor = front->e->XFloor.ffloors[j]; + const MeshApplyState& applyState = it.first; - // Don't create a line when both sectors have the same 3d floor - bool bothSides = false; - for (unsigned int k = 0; k < back->e->XFloor.ffloors.Size(); k++) + pipelineID = screen->GetLevelMeshPipelineID(applyState.applyData, applyState.surfaceUniforms, applyState.material); + + int uniformsIndex = Mesh.Uniforms.Size(); + Mesh.Uniforms.Push(applyState.surfaceUniforms); + Mesh.Materials.Push(applyState.material); + + for (MeshDrawCommand& command : it.second.mDraws) { - if (back->e->XFloor.ffloors[k] == xfloor) + for (int i = command.Start, end = command.Start + command.Count; i < end; i++) { - bothSides = true; - break; + Mesh.Vertices.Push(state.mVertices[i]); + Mesh.UniformIndexes.Push(uniformsIndex); } - } - if (bothSides) - continue; - Surface surf; - surf.type = ST_MIDDLEWALL; - surf.typeIndex = typeIndex; - surf.controlSector = xfloor->model; - - FVector3 verts[4]; - verts[0].X = verts[2].X = v2.X; - verts[0].Y = verts[2].Y = v2.Y; - verts[1].X = verts[3].X = v1.X; - verts[1].Y = verts[3].Y = v1.Y; - verts[0].Z = (float)xfloor->model->floorplane.ZatPoint(v2); - verts[1].Z = (float)xfloor->model->floorplane.ZatPoint(v1); - verts[2].Z = (float)xfloor->model->ceilingplane.ZatPoint(v2); - verts[3].Z = (float)xfloor->model->ceilingplane.ZatPoint(v1); - - surf.startVertIndex = MeshVertices.Size(); - surf.numVerts = 4; - MeshVertices.Push(verts[0]); - MeshVertices.Push(verts[1]); - MeshVertices.Push(verts[2]); - MeshVertices.Push(verts[3]); - - surf.plane = ToPlane(verts[0], verts[1], verts[2]); - Surfaces.Push(surf); + if (command.DrawType == DT_TriangleFan) + { + for (int i = 2, count = command.Count; i < count; i++) + { + Mesh.Indexes.Push(startVertIndex); + Mesh.Indexes.Push(startVertIndex + i - 1); + Mesh.Indexes.Push(startVertIndex + i); + } + } + } } + state.mSortedLists.clear(); + state.mVertices.Clear(); + state.mIndexes.Clear(); - float v1TopBack = (float)back->ceilingplane.ZatPoint(v1); - float v1BottomBack = (float)back->floorplane.ZatPoint(v1); - float v2TopBack = (float)back->ceilingplane.ZatPoint(v2); - float v2BottomBack = (float)back->floorplane.ZatPoint(v2); + FVector2 v1 = FVector2(side->V1()->fPos()); + FVector2 v2 = FVector2(side->V2()->fPos()); + FVector2 N = FVector2(v2.Y - v1.Y, v1.X - v2.X).Unit(); - if (v1Top == v1TopBack && v1Bottom == v1BottomBack && v2Top == v2TopBack && v2Bottom == v2BottomBack) + uint16_t sampleDimension = 0; + if (wallpart.LevelMeshInfo.Type == ST_UPPERSIDE) + { + sampleDimension = side->textures[side_t::top].LightmapSampleDistance; + } + else if (wallpart.LevelMeshInfo.Type == ST_MIDDLESIDE) + { + sampleDimension = side->textures[side_t::mid].LightmapSampleDistance; + } + else if (wallpart.LevelMeshInfo.Type == ST_LOWERSIDE) { - return; + sampleDimension = side->textures[side_t::bottom].LightmapSampleDistance; } - // bottom seg - if (v1Bottom < v1BottomBack || v2Bottom < v2BottomBack) + DoomLevelMeshSurface surf; + surf.Type = wallpart.LevelMeshInfo.Type; + surf.ControlSector = wallpart.LevelMeshInfo.ControlSector; + surf.TypeIndex = side->Index(); + surf.Side = side; + surf.AlwaysUpdate = !!(side->sector->Flags & SECF_LM_DYNAMIC); + surf.SectorGroup = sectorGroup[side->sector->Index()]; + surf.Alpha = float(side->linedef->alpha); + surf.MeshLocation.StartVertIndex = startVertIndex; + surf.MeshLocation.StartElementIndex = startElementIndex; + surf.MeshLocation.NumVerts = Mesh.Vertices.Size() - startVertIndex; + surf.MeshLocation.NumElements = Mesh.Indexes.Size() - startElementIndex; + surf.Plane = FVector4(N.X, N.Y, 0.0f, v1 | N); + surf.Texture = wallpart.texture; + surf.PipelineID = pipelineID; + surf.PortalIndex = isPortal ? linePortals[side->linedef->Index()] : 0; + surf.IsSky = isPortal ? (wallpart.portaltype == PORTALTYPE_SKY || wallpart.portaltype == PORTALTYPE_SKYBOX || wallpart.portaltype == PORTALTYPE_HORIZON) : false; + surf.Bounds = GetBoundsFromSurface(surf); + surf.LightmapTileIndex = disp.Level->lightmaps ? AddSurfaceToTile(surf, sampleDimension) : -1; + Surfaces.Push(surf); + } +} + +int DoomLevelMesh::AddSurfaceToTile(const DoomLevelMeshSurface& surf, uint16_t sampleDimension) +{ + if (surf.IsSky) + return -1; + + LightmapTileBinding binding; + binding.Type = surf.Type; + binding.TypeIndex = surf.TypeIndex; + binding.ControlSector = surf.ControlSector ? surf.ControlSector->Index() : (int)0xffffffffUL; + + auto it = bindings.find(binding); + if (it != bindings.end()) + { + int index = it->second; + + LightmapTile& tile = LightmapTiles[index]; + tile.Bounds.min.X = std::min(tile.Bounds.min.X, surf.Bounds.min.X); + tile.Bounds.min.Y = std::min(tile.Bounds.min.Y, surf.Bounds.min.Y); + tile.Bounds.min.Z = std::min(tile.Bounds.min.Z, surf.Bounds.min.Z); + tile.Bounds.max.X = std::max(tile.Bounds.max.X, surf.Bounds.max.X); + tile.Bounds.max.Y = std::max(tile.Bounds.max.Y, surf.Bounds.max.Y); + tile.Bounds.max.Z = std::max(tile.Bounds.max.Z, surf.Bounds.max.Z); + + return index; + } + else + { + int index = LightmapTiles.Size(); + + LightmapTile tile; + tile.Binding = binding; + tile.Bounds = surf.Bounds; + tile.Plane = surf.Plane; + tile.SampleDimension = GetSampleDimension(surf, sampleDimension); + + LightmapTiles.Push(tile); + bindings[binding] = index; + return index; + } +} + +int DoomLevelMesh::GetSampleDimension(const DoomLevelMeshSurface& surf, uint16_t sampleDimension) +{ + if (sampleDimension <= 0) + { + sampleDimension = LightmapSampleDistance; + } + + sampleDimension = uint16_t(max(int(roundf(float(sampleDimension) / max(1.0f / 4, float(lm_scale)))), 1)); + + // Round to nearest power of two + uint32_t n = uint16_t(sampleDimension); + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n = (n + 1) >> 1; + sampleDimension = uint16_t(n) ? uint16_t(n) : uint16_t(0xFFFF); + + return sampleDimension; +} + +void DoomLevelMesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state, TArray& list, bool isSky, bool translucent) +{ + for (HWFlat& flatpart : list) + { + if (isSky) + { + state.SetEffect(EFF_PORTAL); + state.EnableTexture(false); + state.SetRenderStyle(STYLE_Normal); + + flatpart.DrawSubsectors(&disp, state); + + state.SetEffect(EFF_NONE); + state.EnableTexture(true); + } + else { - if (IsBottomSideVisible(side)) + if (flatpart.texture && flatpart.texture->isMasked()) { - Surface surf; - - FVector3 verts[4]; - verts[0].X = verts[2].X = v1.X; - verts[0].Y = verts[2].Y = v1.Y; - verts[1].X = verts[3].X = v2.X; - verts[1].Y = verts[3].Y = v2.Y; - verts[0].Z = v1Bottom; - verts[1].Z = v2Bottom; - verts[2].Z = v1BottomBack; - verts[3].Z = v2BottomBack; - - surf.startVertIndex = MeshVertices.Size(); - surf.numVerts = 4; - MeshVertices.Push(verts[0]); - MeshVertices.Push(verts[1]); - MeshVertices.Push(verts[2]); - MeshVertices.Push(verts[3]); - - surf.plane = ToPlane(verts[0], verts[1], verts[2]); - surf.type = ST_LOWERWALL; - surf.typeIndex = typeIndex; - surf.controlSector = nullptr; - - Surfaces.Push(surf); + state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); } + else + { + state.AlphaFunc(Alpha_GEqual, 0.f); + } + + flatpart.DrawFlat(&disp, state, translucent); + } + + VSMatrix textureMatrix; + textureMatrix.loadIdentity(); + + int pipelineID = 0; + int uniformsIndex = 0; + bool foundDraw = false; + for (auto& it : state.mSortedLists) + { + const MeshApplyState& applyState = it.first; + + pipelineID = screen->GetLevelMeshPipelineID(applyState.applyData, applyState.surfaceUniforms, applyState.material); + uniformsIndex = Mesh.Uniforms.Size(); + textureMatrix = applyState.textureMatrix; + Mesh.Uniforms.Push(applyState.surfaceUniforms); + Mesh.Materials.Push(applyState.material); + + foundDraw = true; + break; + } + state.mSortedLists.clear(); + state.mVertices.Clear(); + state.mIndexes.Clear(); + + if (!foundDraw) + continue; - v1Bottom = v1BottomBack; - v2Bottom = v2BottomBack; + uint16_t sampleDimension = 0; + if (flatpart.ceiling) + { + sampleDimension = flatpart.sector->planes[sector_t::ceiling].LightmapSampleDistance; + } + else + { + sampleDimension = flatpart.sector->planes[sector_t::floor].LightmapSampleDistance; } - // top seg - if (v1Top > v1TopBack || v2Top > v2TopBack) + DoomLevelMeshSurface surf; + surf.Type = flatpart.ceiling ? ST_CEILING : ST_FLOOR; + surf.ControlSector = flatpart.controlsector ? flatpart.controlsector->model : nullptr; + surf.AlwaysUpdate = !!(flatpart.sector->Flags & SECF_LM_DYNAMIC); + surf.SectorGroup = sectorGroup[flatpart.sector->Index()]; + surf.Alpha = flatpart.alpha; + surf.Texture = flatpart.texture; + surf.PipelineID = pipelineID; + surf.PortalIndex = sectorPortals[flatpart.ceiling][flatpart.sector->Index()]; + surf.IsSky = isSky; + + auto plane = surf.ControlSector ? surf.ControlSector->GetSecPlane(!flatpart.ceiling) : flatpart.sector->GetSecPlane(flatpart.ceiling); + surf.Plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D); + + if (surf.ControlSector) + surf.Plane = -surf.Plane; + + float skyZ = flatpart.ceiling ? 32768.0f : -32768.0f; + + for (subsector_t* sub : flatpart.section->subsectors) { - bool bSky = IsTopSideSky(front, back, side); - if (bSky || IsTopSideVisible(side)) + if (sub->numlines < 3) + continue; + + int startVertIndex = Mesh.Vertices.Size(); + int startElementIndex = Mesh.Indexes.Size(); + + for (int i = 0, end = sub->numlines; i < end; i++) + { + auto& vt = sub->firstline[end - 1 - i].v1; + + FVector3 pt((float)vt->fX(), (float)vt->fY(), isSky ? skyZ : (float)plane.ZatPoint(vt)); + FVector4 uv = textureMatrix * FVector4(pt.X * (1.0f / 64.0f), pt.Y * (-1.0f / 64.0f), 0.0f, 1.0f); + + FFlatVertex ffv; + ffv.x = pt.X; + ffv.y = pt.Y; + ffv.z = pt.Z; + ffv.u = uv.X; + ffv.v = uv.Y; + ffv.lu = 0.0f; + ffv.lv = 0.0f; + ffv.lindex = -1.0f; + + Mesh.Vertices.Push(ffv); + Mesh.UniformIndexes.Push(uniformsIndex); + } + + if (flatpart.ceiling) + { + for (int i = 2, count = sub->numlines; i < count; i++) + { + Mesh.Indexes.Push(startVertIndex); + Mesh.Indexes.Push(startVertIndex + i - 1); + Mesh.Indexes.Push(startVertIndex + i); + } + } + else { - Surface surf; - - FVector3 verts[4]; - verts[0].X = verts[2].X = v1.X; - verts[0].Y = verts[2].Y = v1.Y; - verts[1].X = verts[3].X = v2.X; - verts[1].Y = verts[3].Y = v2.Y; - verts[0].Z = v1TopBack; - verts[1].Z = v2TopBack; - verts[2].Z = v1Top; - verts[3].Z = v2Top; - - surf.startVertIndex = MeshVertices.Size(); - surf.numVerts = 4; - MeshVertices.Push(verts[0]); - MeshVertices.Push(verts[1]); - MeshVertices.Push(verts[2]); - MeshVertices.Push(verts[3]); - - surf.plane = ToPlane(verts[0], verts[1], verts[2]); - surf.type = ST_UPPERWALL; - surf.typeIndex = typeIndex; - surf.bSky = bSky; - surf.controlSector = nullptr; - - Surfaces.Push(surf); + for (int i = 2, count = sub->numlines; i < count; i++) + { + Mesh.Indexes.Push(startVertIndex + i); + Mesh.Indexes.Push(startVertIndex + i - 1); + Mesh.Indexes.Push(startVertIndex); + } } - v1Top = v1TopBack; - v2Top = v2TopBack; + surf.TypeIndex = sub->Index(); + surf.Subsector = sub; + surf.MeshLocation.StartVertIndex = startVertIndex; + surf.MeshLocation.StartElementIndex = startElementIndex; + surf.MeshLocation.NumVerts = sub->numlines; + surf.MeshLocation.NumElements = (sub->numlines - 2) * 3; + surf.Bounds = GetBoundsFromSurface(surf); + surf.LightmapTileIndex = disp.Level->lightmaps ? AddSurfaceToTile(surf, sampleDimension) : -1; + Surfaces.Push(surf); } } +} - // middle seg - if (back == nullptr) +#if 0 +void DoomLevelMesh::CreateDynamicSurfaces(FLevelLocals& doomMap) +{ + // Look for polyobjects + for (unsigned int i = 0; i < doomMap.lines.Size(); i++) { - Surface surf; + side_t* side = doomMap.lines[i].sidedef[0]; + bool isPolyLine = !!(side->Flags & WALLF_POLYOBJ); + if (!isPolyLine) + continue; + + // Make sure we have a surface array on the polyobj sidedef + if (!side->surface) + { + auto array = std::make_unique(4); + memset(array.get(), 0, sizeof(DoomLevelMeshSurface*)); + side->surface = array.get(); + PolyLMSurfaces.Push(std::move(array)); + } + + CreateSideSurfaces(doomMap, side); + } +} +#endif - FVector3 verts[4]; - verts[0].X = verts[2].X = v1.X; - verts[0].Y = verts[2].Y = v1.Y; - verts[1].X = verts[3].X = v2.X; - verts[1].Y = verts[3].Y = v2.Y; - verts[0].Z = v1Bottom; - verts[1].Z = v2Bottom; - verts[2].Z = v1Top; - verts[3].Z = v2Top; +void DoomLevelMesh::SortIndexes() +{ + // Order surfaces by pipeline + std::unordered_map> pipelineSurfaces; + for (size_t i = 0; i < Surfaces.Size(); i++) + { + DoomLevelMeshSurface* s = &Surfaces[i]; + pipelineSurfaces[(int64_t(s->PipelineID) << 32) | int64_t(s->IsSky)].Push(i); + } - surf.startVertIndex = MeshVertices.Size(); - surf.numVerts = 4; - MeshVertices.Push(verts[0]); - MeshVertices.Push(verts[1]); - MeshVertices.Push(verts[2]); - MeshVertices.Push(verts[3]); + // Create reorder surface indexes by pipeline and create a draw range for each + TArray sortedIndexes; + for (const auto& it : pipelineSurfaces) + { + LevelSubmeshDrawRange range; + range.PipelineID = it.first >> 32; + range.Start = sortedIndexes.Size(); - surf.plane = ToPlane(verts[0], verts[1], verts[2]); - surf.type = ST_MIDDLEWALL; - surf.typeIndex = typeIndex; - surf.controlSector = nullptr; + // Move indexes to new array + for (unsigned int i : it.second) + { + DoomLevelMeshSurface& s = Surfaces[i]; - Surfaces.Push(surf); + unsigned int start = s.MeshLocation.StartElementIndex; + unsigned int count = s.MeshLocation.NumElements; + + s.MeshLocation.StartElementIndex = sortedIndexes.Size(); + + for (unsigned int j = 0; j < count; j++) + { + sortedIndexes.Push(Mesh.Indexes[start + j]); + } + + for (unsigned int j = 0; j < count; j += 3) + { + Mesh.SurfaceIndexes.Push((int)i); + } + } + + range.Count = sortedIndexes.Size() - range.Start; + + if ((it.first & 1) == 0) + DrawList.Push(range); + else + PortalList.Push(range); + } + + Mesh.Indexes.Swap(sortedIndexes); +} + +void DoomLevelMesh::LinkSurfaces(FLevelLocals& doomMap) +{ + for (auto& surface : Surfaces) + { + if (surface.Type == ST_FLOOR || surface.Type == ST_CEILING) + { + SetSubsectorLightmap(&surface); + } + else + { + SetSideLightmap(&surface); + } } } -void DoomLevelMesh::CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor) +void DoomLevelMesh::SetSubsectorLightmap(DoomLevelMeshSurface* surface) { - Surface surf; + if (surface->Subsector->firstline && surface->Subsector->firstline->sidedef) + surface->Subsector->firstline->sidedef->sector->HasLightmaps = true; - if (!is3DFloor) + if (!surface->ControlSector) { - surf.plane = sector->floorplane; + int index = surface->Type == ST_CEILING ? 1 : 0; + surface->Subsector->surface[index][0] = surface; } else { - surf.plane = sector->ceilingplane; - surf.plane.FlipVert(); + int index = surface->Type == ST_CEILING ? 0 : 1; + const auto& ffloors = surface->Subsector->sector->e->XFloor.ffloors; + for (unsigned int i = 0; i < ffloors.Size(); i++) + { + if (ffloors[i]->model == surface->ControlSector) + { + surface->Subsector->surface[index][i + 1] = surface; + } + } } +} - surf.numVerts = sub->numlines; - surf.startVertIndex = MeshVertices.Size(); - MeshVertices.Resize(surf.startVertIndex + surf.numVerts); - FVector3* verts = &MeshVertices[surf.startVertIndex]; - - for (int j = 0; j < surf.numVerts; j++) +void DoomLevelMesh::SetSideLightmap(DoomLevelMeshSurface* surface) +{ + if (!surface->ControlSector) { - seg_t *seg = &sub->firstline[(surf.numVerts - 1) - j]; - FVector2 v1 = ToFVector2(seg->v1->fPos()); - - verts[j].X = v1.X; - verts[j].Y = v1.Y; - verts[j].Z = (float)surf.plane.ZatPoint(verts[j]); + if (surface->Type == ST_UPPERSIDE) + { + surface->Side->surface[0] = surface; + } + else if (surface->Type == ST_MIDDLESIDE) + { + surface->Side->surface[1] = surface; + surface->Side->surface[2] = surface; + } + else if (surface->Type == ST_LOWERSIDE) + { + surface->Side->surface[3] = surface; + } } + else + { + side_t* backside = surface->Side->linedef->sidedef[surface->Side == surface->Side->linedef->sidedef[0]]; + const auto& ffloors = backside->sector->e->XFloor.ffloors; + for (unsigned int i = 0; i < ffloors.Size(); i++) + { + if (ffloors[i]->model == surface->ControlSector) + { + backside->surface[4 + i] = surface; + } + } + } +} - surf.type = ST_FLOOR; - surf.typeIndex = typeIndex; - surf.controlSector = is3DFloor ? sector : nullptr; - - Surfaces.Push(surf); +BBox DoomLevelMesh::GetBoundsFromSurface(const LevelMeshSurface& surface) const +{ + BBox bounds; + bounds.Clear(); + for (int i = int(surface.MeshLocation.StartVertIndex); i < int(surface.MeshLocation.StartVertIndex) + surface.MeshLocation.NumVerts; i++) + { + FVector3 v = Mesh.Vertices[(int)i].fPos(); + bounds.min.X = std::min(bounds.min.X, v.X); + bounds.min.Y = std::min(bounds.min.Y, v.Y); + bounds.min.Z = std::min(bounds.min.Z, v.Z); + bounds.max.X = std::max(bounds.max.X, v.X); + bounds.max.Y = std::max(bounds.max.Y, v.Y); + bounds.max.Z = std::max(bounds.max.Z, v.Z); + } + return bounds; } -void DoomLevelMesh::CreateCeilingSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor) +void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilename) const { - Surface surf; - surf.bSky = IsSkySector(sector); + auto f = fopen(objFilename.GetChars(), "w"); + + fprintf(f, "# DoomLevelMesh debug export\n"); + fprintf(f, "# Vertices: %u, Indexes: %u, Surfaces: %u\n", Mesh.Vertices.Size(), Mesh.Indexes.Size(), Surfaces.Size()); + fprintf(f, "mtllib %s\n", mtlFilename.GetChars()); - if (!is3DFloor) + double scale = 1 / 10.0; + + for (const auto& v : Mesh.Vertices) { - surf.plane = sector->ceilingplane; + fprintf(f, "v %f %f %f\n", v.x * scale, v.y * scale, v.z * scale); } - else + + for (const auto& v : Mesh.Vertices) { - surf.plane = sector->floorplane; - surf.plane.FlipVert(); + fprintf(f, "vt %f %f\n", v.lu, v.lv); } - surf.numVerts = sub->numlines; - surf.startVertIndex = MeshVertices.Size(); - MeshVertices.Resize(surf.startVertIndex + surf.numVerts); - FVector3* verts = &MeshVertices[surf.startVertIndex]; + auto name = [](DoomLevelMeshSurfaceType type) -> const char* { + switch (type) + { + case ST_CEILING: + return "ceiling"; + case ST_FLOOR: + return "floor"; + case ST_LOWERSIDE: + return "lowerside"; + case ST_UPPERSIDE: + return "upperside"; + case ST_MIDDLESIDE: + return "middleside"; + case ST_NONE: + return "none"; + default: + break; + } + return "error"; + }; + - for (int j = 0; j < surf.numVerts; j++) + uint32_t lastSurfaceIndex = -1; + + + bool useErrorMaterial = false; + int highestUsedAtlasPage = -1; + + for (unsigned i = 0, count = Mesh.Indexes.Size(); i + 2 < count; i += 3) { - seg_t *seg = &sub->firstline[j]; - FVector2 v1 = ToFVector2(seg->v1->fPos()); + auto index = Mesh.SurfaceIndexes[i / 3]; + + if (index != lastSurfaceIndex) + { + lastSurfaceIndex = index; + + if (unsigned(index) >= Surfaces.Size()) + { + fprintf(f, "o Surface[%d] (bad index)\n", index); + fprintf(f, "usemtl error\n"); + + useErrorMaterial = true; + } + else + { + const auto& surface = Surfaces[index]; + fprintf(f, "o Surface[%d] %s %d%s\n", index, name(surface.Type), surface.TypeIndex, surface.IsSky ? " sky" : ""); + + if (surface.LightmapTileIndex >= 0) + { + auto& tile = LightmapTiles[surface.LightmapTileIndex]; + fprintf(f, "usemtl lightmap%d\n", tile.AtlasLocation.ArrayIndex); + + if (tile.AtlasLocation.ArrayIndex > highestUsedAtlasPage) + { + highestUsedAtlasPage = tile.AtlasLocation.ArrayIndex; + } + } + } + } + + // fprintf(f, "f %d %d %d\n", MeshElements[i] + 1, MeshElements[i + 1] + 1, MeshElements[i + 2] + 1); + fprintf(f, "f %d/%d %d/%d %d/%d\n", + Mesh.Indexes[i + 0] + 1, Mesh.Indexes[i + 0] + 1, + Mesh.Indexes[i + 1] + 1, Mesh.Indexes[i + 1] + 1, + Mesh.Indexes[i + 2] + 1, Mesh.Indexes[i + 2] + 1); - verts[j].X = v1.X; - verts[j].Y = v1.Y; - verts[j].Z = (float)surf.plane.ZatPoint(verts[j]); } - surf.type = ST_CEILING; - surf.typeIndex = typeIndex; - surf.controlSector = is3DFloor ? sector : nullptr; + fclose(f); + + // material - Surfaces.Push(surf); + f = fopen(mtlFilename.GetChars(), "w"); + + fprintf(f, "# DoomLevelMesh debug export\n"); + + if (useErrorMaterial) + { + fprintf(f, "# Surface indices that are referenced, but do not exists in the 'Surface' array\n"); + fprintf(f, "newmtl error\nKa 1 0 0\nKd 1 0 0\nKs 1 0 0\n"); + } + + for (int page = 0; page <= highestUsedAtlasPage; ++page) + { + fprintf(f, "newmtl lightmap%d\n", page); + fprintf(f, "Ka 1 1 1\nKd 1 1 1\nKs 0 0 0\n"); + fprintf(f, "map_Ka lightmap%d.png\n", page); + fprintf(f, "map_Kd lightmap%d.png\n", page); + } + + fclose(f); } -void DoomLevelMesh::CreateSubsectorSurfaces(FLevelLocals &doomMap) +void DoomLevelMesh::BuildSectorGroups(const FLevelLocals& doomMap) { - for (unsigned int i = 0; i < doomMap.subsectors.Size(); i++) + int groupIndex = 0; + + TArray queue; + + sectorGroup.Resize(doomMap.sectors.Size()); + memset(sectorGroup.Data(), 0, sectorGroup.Size() * sizeof(int)); + + for (int i = 0, count = doomMap.sectors.Size(); i < count; ++i) { - subsector_t *sub = &doomMap.subsectors[i]; + auto* sector = &doomMap.sectors[i]; - if (sub->numlines < 3) + auto& currentSectorGroup = sectorGroup[sector->Index()]; + if (currentSectorGroup == 0) { - continue; - } + currentSectorGroup = ++groupIndex; - sector_t *sector = sub->sector; - if (!sector || IsControlSector(sector)) - continue; + queue.Push(sector); - CreateFloorSurface(doomMap, sub, sector, i, false); - CreateCeilingSurface(doomMap, sub, sector, i, false); + while (queue.Size() > 0) + { + auto* sector = queue.Last(); + queue.Pop(); - for (unsigned int j = 0; j < sector->e->XFloor.ffloors.Size(); j++) - { - CreateFloorSurface(doomMap, sub, sector->e->XFloor.ffloors[j]->model, i, true); - CreateCeilingSurface(doomMap, sub, sector->e->XFloor.ffloors[j]->model, i, true); + for (auto& line : sector->Lines) + { + auto otherSector = line->frontsector == sector ? line->backsector : line->frontsector; + if (otherSector && otherSector != sector) + { + auto& id = sectorGroup[otherSector->Index()]; + + if (id == 0) + { + id = groupIndex; + queue.Push(otherSector); + } + } + } + } } } -} -bool DoomLevelMesh::IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side) -{ - return IsSkySector(frontsector) && IsSkySector(backsector); + if (developer >= 5) + { + Printf("DoomLevelMesh::BuildSectorGroups created %d groups.", groupIndex); + } } -bool DoomLevelMesh::IsTopSideVisible(side_t* side) +void DoomLevelMesh::CreatePortals(FLevelLocals& doomMap) { - auto tex = TexMan.GetGameTexture(side->GetTexture(side_t::top), true); - return tex && tex->isValid(); -} + std::map transformationIndices; + transformationIndices.emplace(LevelMeshPortal{}, 0); // first portal is an identity matrix -bool DoomLevelMesh::IsBottomSideVisible(side_t* side) -{ - auto tex = TexMan.GetGameTexture(side->GetTexture(side_t::bottom), true); - return tex && tex->isValid(); -} + sectorPortals[0].Resize(doomMap.sectors.Size()); + sectorPortals[1].Resize(doomMap.sectors.Size()); -bool DoomLevelMesh::IsSkySector(sector_t* sector) -{ - return sector->GetTexture(sector_t::ceiling) == skyflatnum; -} + for (unsigned int i = 0, count = doomMap.sectors.Size(); i < count; i++) + { + sector_t* sector = &doomMap.sectors[i]; + for (int plane = 0; plane < 2; plane++) + { + auto d = sector->GetPortalDisplacement(plane); + if (!d.isZero()) + { + // Note: Y and Z is swapped in the shader due to how the hwrenderer was implemented + VSMatrix transformation; + transformation.loadIdentity(); + transformation.translate((float)d.X, 0.0f, (float)d.Y); + + int targetSectorGroup = 0; + auto portalDestination = sector->GetPortal(plane)->mDestination; + if (portalDestination) + { + targetSectorGroup = sectorGroup[portalDestination->Index()]; + } -bool DoomLevelMesh::IsControlSector(sector_t* sector) -{ - //return sector->controlsector; - return false; -} + LevelMeshPortal portal; + portal.transformation = transformation; + portal.sourceSectorGroup = sectorGroup[i]; + portal.targetSectorGroup = targetSectorGroup; -bool DoomLevelMesh::IsDegenerate(const FVector3 &v0, const FVector3 &v1, const FVector3 &v2) -{ - // A degenerate triangle has a zero cross product for two of its sides. - float ax = v1.X - v0.X; - float ay = v1.Y - v0.Y; - float az = v1.Z - v0.Z; - float bx = v2.X - v0.X; - float by = v2.Y - v0.Y; - float bz = v2.Z - v0.Z; - float crossx = ay * bz - az * by; - float crossy = az * bx - ax * bz; - float crossz = ax * by - ay * bx; - float crosslengthsqr = crossx * crossx + crossy * crossy + crossz * crossz; - return crosslengthsqr <= 1.e-6f; + auto& index = transformationIndices[portal]; + if (index == 0) // new transformation was created + { + index = Portals.Size(); + Portals.Push(portal); + } + + sectorPortals[plane][i] = index; + } + else + { + sectorPortals[plane][i] = 0; + } + } + } + + linePortals.Resize(doomMap.lines.Size()); + for (unsigned int i = 0, count = doomMap.lines.Size(); i < count; i++) + { + linePortals[i] = 0; + + line_t* sourceLine = &doomMap.lines[i]; + if (sourceLine->isLinePortal()) + { + VSMatrix transformation; + transformation.loadIdentity(); + + auto targetLine = sourceLine->getPortalDestination(); + if (!targetLine || !sourceLine->frontsector || !targetLine->frontsector) + continue; + + double z = 0; + + // auto xy = surface.Side->linedef->getPortalDisplacement(); // Works only for static portals... ugh + auto sourceXYZ = DVector2((sourceLine->v1->fX() + sourceLine->v2->fX()) / 2, (sourceLine->v2->fY() + sourceLine->v1->fY()) / 2); + auto targetXYZ = DVector2((targetLine->v1->fX() + targetLine->v2->fX()) / 2, (targetLine->v2->fY() + targetLine->v1->fY()) / 2); + + // floor or ceiling alignment + auto alignment = sourceLine->GetLevel()->linePortals[sourceLine->portalindex].mAlign; + if (alignment != PORG_ABSOLUTE) + { + int plane = alignment == PORG_FLOOR ? 1 : 0; + + auto& sourcePlane = plane ? sourceLine->frontsector->floorplane : sourceLine->frontsector->ceilingplane; + auto& targetPlane = plane ? targetLine->frontsector->floorplane : targetLine->frontsector->ceilingplane; + + auto tz = targetPlane.ZatPoint(targetXYZ); + auto sz = sourcePlane.ZatPoint(sourceXYZ); + + z = tz - sz; + } + + // Note: Y and Z is swapped in the shader due to how the hwrenderer was implemented + transformation.rotate((float)sourceLine->getPortalAngleDiff().Degrees(), 0.0f, 1.0f, 0.0f); + transformation.translate((float)(targetXYZ.X - sourceXYZ.X), (float)z, (float)(targetXYZ.Y - sourceXYZ.Y)); + + int targetSectorGroup = 0; + if (auto sector = targetLine->frontsector ? targetLine->frontsector : targetLine->backsector) + { + targetSectorGroup = sectorGroup[sector->Index()]; + } + + LevelMeshPortal portal; + portal.transformation = transformation; + portal.sourceSectorGroup = sectorGroup[sourceLine->frontsector->Index()]; + portal.targetSectorGroup = targetSectorGroup; + + auto& index = transformationIndices[portal]; + if (index == 0) // new transformation was created + { + index = Portals.Size(); + Portals.Push(portal); + } + + linePortals[i] = index; + } + } } diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 5c668eb7d2..9b407f7b94 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -2,66 +2,98 @@ #pragma once #include "hw_levelmesh.h" +#include "scene/hw_drawstructs.h" +#include "common/rendering/hwrenderer/data/hw_meshbuilder.h" #include "tarray.h" #include "vectors.h" #include "r_defs.h" +#include "bounds.h" +#include +#include struct FLevelLocals; +struct FPolyObj; +struct HWWallDispatcher; +class DoomLevelMesh; +class MeshBuilder; -struct Surface +struct DoomLevelMeshSurface : public LevelMeshSurface { - SurfaceType type; - int typeIndex; - int numVerts; - unsigned int startVertIndex; - secplane_t plane; - sector_t *controlSector; - bool bSky; + DoomLevelMeshSurfaceType Type = ST_NONE; + int TypeIndex = 0; + + subsector_t* Subsector = nullptr; + side_t* Side = nullptr; + sector_t* ControlSector = nullptr; + + int PipelineID = 0; +}; + +struct SideSurfaceRange +{ + int StartSurface = 0; + int SurfaceCount = 0; }; -class DoomLevelMesh : public hwrenderer::LevelMesh +struct FlatSurfaceRange +{ + int StartSurface = 0; + int SurfaceCount = 0; +}; + +class DoomLevelMesh : public LevelMesh { public: DoomLevelMesh(FLevelLocals &doomMap); - bool TraceSky(const FVector3& start, FVector3 direction, float dist) - { - FVector3 end = start + direction * dist; - TraceHit hit = TriangleMeshShape::find_first_hit(Collision.get(), start, end); - if (hit.fraction == 1.0f) - return true; + LevelMeshSurface* GetSurface(int index) override { return &Surfaces[index]; } + unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const override { return (unsigned int)(ptrdiff_t)(static_cast(surface) - Surfaces.Data()); } + int GetSurfaceCount() override { return Surfaces.Size(); } + + void BeginFrame(FLevelLocals& doomMap); + bool TraceSky(const FVector3& start, FVector3 direction, float dist); + void DumpMesh(const FString& objFilename, const FString& mtlFilename) const; + + void BuildSectorGroups(const FLevelLocals& doomMap); + + TArray Surfaces; + TArray> PolyLMSurfaces; + TArray WallPortals; - int surfaceIndex = MeshSurfaces[hit.triangle]; - const Surface& surface = Surfaces[surfaceIndex]; - return surface.bSky; - } + TArray sectorGroup; // index is sector, value is sectorGroup + TArray sectorPortals[2]; // index is sector+plane, value is index into the portal list + TArray linePortals; // index is linedef, value is index into the portal list - TArray Surfaces; + void CreateLights(FLevelLocals& doomMap); private: - void CreateSubsectorSurfaces(FLevelLocals &doomMap); - void CreateCeilingSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor); - void CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor); - void CreateSideSurfaces(FLevelLocals &doomMap, side_t *side); - - static bool IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side); - static bool IsTopSideVisible(side_t* side); - static bool IsBottomSideVisible(side_t* side); - static bool IsSkySector(sector_t* sector); - static bool IsControlSector(sector_t* sector); - - static secplane_t ToPlane(const FVector3& pt1, const FVector3& pt2, const FVector3& pt3) - { - FVector3 n = ((pt2 - pt1) ^ (pt3 - pt2)).Unit(); - float d = pt1 | n; - secplane_t p; - p.set(n.X, n.Y, n.Z, d); - return p; - } - - static FVector2 ToFVector2(const DVector2& v) { return FVector2((float)v.X, (float)v.Y); } - static FVector3 ToFVector3(const DVector3& v) { return FVector3((float)v.X, (float)v.Y, (float)v.Z); } - static FVector4 ToFVector4(const DVector4& v) { return FVector4((float)v.X, (float)v.Y, (float)v.Z, (float)v.W); } - - static bool IsDegenerate(const FVector3 &v0, const FVector3 &v1, const FVector3 &v2); + void CreateSurfaces(FLevelLocals& doomMap); + + void UpdateSide(FLevelLocals& doomMap, unsigned int sideIndex); + void UpdateFlat(FLevelLocals& doomMap, unsigned int sectorIndex); + + void SetSubsectorLightmap(DoomLevelMeshSurface* surface); + void SetSideLightmap(DoomLevelMeshSurface* surface); + + void SortIndexes(); + + void CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray& list, bool isPortal, bool translucent); + void CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state, TArray& list, bool isSky, bool translucent); + + void LinkSurfaces(FLevelLocals& doomMap); + + BBox GetBoundsFromSurface(const LevelMeshSurface& surface) const; + + int AddSurfaceToTile(const DoomLevelMeshSurface& surf, uint16_t sampleDimension); + int GetSampleDimension(const DoomLevelMeshSurface& surf, uint16_t sampleDimension); + + void CreatePortals(FLevelLocals& doomMap); + std::pair GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf); + + int GetLightIndex(FDynamicLight* light, int portalgroup); + + TArray Sides; + TArray Flats; + std::map bindings; + MeshBuilder state; }; diff --git a/src/rendering/hwrenderer/hw_dynlightdata.cpp b/src/rendering/hwrenderer/hw_dynlightdata.cpp index 4f2d538242..2414f29015 100644 --- a/src/rendering/hwrenderer/hw_dynlightdata.cpp +++ b/src/rendering/hwrenderer/hw_dynlightdata.cpp @@ -135,6 +135,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f spotDirY = float(-negPitch.Sin()); spotDirZ = float(-Angle.Sin() * xzLen); } + float sourceRadius = light->GetSourceRadius(); float *data = &dld.arrays[i][dld.arrays[i].Reserve(16)]; data[0] = float(pos.X); @@ -151,7 +152,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f data[11] = lightType; data[12] = spotInnerAngle; data[13] = spotOuterAngle; - data[14] = 0.0f; // unused + data[14] = sourceRadius; data[15] = 0.0f; // unused } diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index 40a52b7318..8e7c363a1f 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -47,10 +47,13 @@ #include "hwrenderer/scene/hw_fakeflat.h" #include "hwrenderer/scene/hw_clipper.h" #include "hwrenderer/scene/hw_portal.h" -#include "hwrenderer/scene/hw_meshcache.h" +#include "hwrenderer/scene/hw_drawcontext.h" #include "hw_vrmodes.h" EXTERN_CVAR(Bool, cl_capfps) +EXTERN_CVAR(Float, r_visibility) +EXTERN_CVAR(Bool, gl_bandedswlight) + extern bool NoInterpolateView; static SWSceneDrawer *swdrawer; @@ -95,7 +98,6 @@ void CollectLights(FLevelLocals* Level) } } - //----------------------------------------------------------------------------- // // Renders one viewpoint in a scene @@ -104,11 +106,11 @@ void CollectLights(FLevelLocals* Level) sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen) { - auto& RenderState = *screen->RenderState(0); + auto& RenderState = *screen->RenderState(); R_SetupFrame(mainvp, r_viewwindow, camera); - if (mainview && toscreen && !(camera->Level->flags3 & LEVEL3_NOSHADOWMAP) && camera->Level->HasDynamicLights && gl_light_shadowmap && screen->allowSSBO() && (screen->hwcaps & RFL_SHADER_STORAGE_BUFFER)) + if (mainview && toscreen && !(camera->Level->flags3 & LEVEL3_NOSHADOWMAP) && camera->Level->HasDynamicLights && gl_light_shadows > 0) { screen->mShadowMap->SetAABBTree(camera->Level->aabbTree); screen->mShadowMap->SetCollectLights([=] { @@ -123,14 +125,14 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou screen->mShadowMap->SetCollectLights(nullptr); } - screen->SetLevelMesh(camera->Level->levelMesh); - - meshcache.Update(mainvp); - // Update the attenuation flag of all light defaults for each viewpoint. // This function will only do something if the setting differs. FLightDefaults::SetAttenuationForLevel(!!(camera->Level->flags3 & LEVEL3_ATTENUATE)); + static HWDrawContext mainthread_drawctx; + + hw_ClearFakeFlat(&mainthread_drawctx); + // Render (potentially) multiple views for stereo 3d // Fixme. The view offsetting should be done with a static table and not require setup of the entire render state for the mode. auto vrmode = VRMode::GetVRMode(mainview && toscreen); @@ -143,13 +145,13 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao { - bool useSSAO = (gl_ssao != 0); + bool useSSAO = (gl_ssao != 0 || gl_shownormals); screen->SetSceneRenderTarget(useSSAO); RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); RenderState.EnableDrawBuffers(RenderState.GetPassDrawBufferCount(), true); } - auto di = HWDrawInfo::StartDrawInfo(mainvp.ViewLevel, nullptr, mainvp, nullptr); + auto di = HWDrawInfo::StartDrawInfo(&mainthread_drawctx, mainvp.ViewLevel, nullptr, mainvp, nullptr); auto& vp = di->Viewpoint; di->Set3DViewport(RenderState); @@ -168,7 +170,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees()); di->SetupView(RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); - di->ProcessScene(toscreen, *screen->RenderState(0)); + di->ProcessScene(toscreen, *screen->RenderState()); if (mainview) { @@ -264,7 +266,7 @@ void WriteSavePic(player_t* player, FileWriter* file, int width, int height) bounds.top = 0; bounds.width = width; bounds.height = height; - auto& RenderState = *screen->RenderState(0); + auto& RenderState = *screen->RenderState(); // we must be sure the GPU finished reading from the buffer before we fill it with new data. screen->WaitForCommands(false); @@ -274,7 +276,6 @@ void WriteSavePic(player_t* player, FileWriter* file, int width, int height) screen->ImageTransitionScene(true); hw_postprocess.SetTonemapMode(level.info ? level.info->tonemap : ETonemapMode::None); - hw_ClearFakeFlat(); RenderState.ResetVertices(); RenderState.SetFlatVertexBuffer(); @@ -312,7 +313,7 @@ static void CheckTimer(FRenderState &state, uint64_t ShaderStartTime) sector_t* RenderView(player_t* player) { - auto RenderState = screen->RenderState(0); + auto RenderState = screen->RenderState(); RenderState->SetFlatVertexBuffer(); RenderState->ResetVertices(); hw_postprocess.SetTonemapMode(level.info ? level.info->tonemap : ETonemapMode::None); @@ -327,8 +328,6 @@ sector_t* RenderView(player_t* player) } else { - hw_ClearFakeFlat(); - iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0; checkBenchActive(); @@ -356,7 +355,7 @@ sector_t* RenderView(player_t* player) screen->RenderTextureView(canvas->Tex, [=](IntRect& bounds) { screen->SetViewportRects(&bounds); - Draw2D(&canvas->Drawer, *screen->RenderState(0), 0, 0, canvas->Tex->GetWidth(), canvas->Tex->GetHeight()); + Draw2D(&canvas->Drawer, *screen->RenderState(), 0, 0, canvas->Tex->GetWidth(), canvas->Tex->GetHeight()); canvas->Drawer.Clear(); }); canvas->Tex->SetUpdated(true); diff --git a/src/rendering/hwrenderer/hw_models.cpp b/src/rendering/hwrenderer/hw_models.cpp index 9c81631688..3e51dafae7 100644 --- a/src/rendering/hwrenderer/hw_models.cpp +++ b/src/rendering/hwrenderer/hw_models.cpp @@ -42,6 +42,7 @@ #include "hw_renderstate.h" #include "hwrenderer/scene/hw_portal.h" #include "hw_models.h" +#include "hwrenderer/scene/hw_drawcontext.h" CVAR(Bool, gl_light_models, true, CVAR_ARCHIVE) EXTERN_CVAR(Bool, gl_texture); @@ -53,7 +54,7 @@ VSMatrix FHWModelRenderer::GetViewToWorldMatrix() return objectToWorldMatrix; } -void FHWModelRenderer::BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) +void FHWModelRenderer::BeginDrawModel(FRenderStyle style, int smf_flags, const VSMatrix &objectToWorldMatrix, bool mirrored) { state.SetDepthFunc(DF_LEqual); state.EnableTexture(true); @@ -68,9 +69,9 @@ void FHWModelRenderer::BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf // This solves a few of the problems caused by the lack of depth sorting. // [Nash] Don't do back face culling if explicitly specified in MODELDEF // TO-DO: Implement proper depth sorting. - if (!(style == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES)) + if ((smf_flags & MDL_FORCECULLBACKFACES) || (!(style == DefaultRenderStyle()) && !(smf_flags & MDL_DONTCULLBACKFACES))) { - state.SetCulling((mirrored ^ portalState.isMirrored()) ? Cull_CCW : Cull_CW); + state.SetCulling((mirrored ^ di->drawctx->portalState.isMirrored()) ? Cull_CCW : Cull_CW); } VSMatrix normalModelMatrix; @@ -78,18 +79,19 @@ void FHWModelRenderer::BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf state.SetModelMatrix(objectToWorldMatrix, normalModelMatrix); } -void FHWModelRenderer::EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf) +void FHWModelRenderer::EndDrawModel(FRenderStyle style, int smf_flags) { state.SetBoneIndexBase(-1); state.SetModelMatrix(VSMatrix::identity(), VSMatrix::identity()); state.SetDepthFunc(DF_Less); - if (!(style == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES)) + if ((smf_flags & MDL_FORCECULLBACKFACES) || (!(style == DefaultRenderStyle()) && !(smf_flags & MDL_DONTCULLBACKFACES))) state.SetCulling(Cull_None); } -void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored) +void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, int smf_flags) { state.SetDepthFunc(DF_LEqual); + state.SetDepthClamp(true); state.EnableTexture(true); @@ -102,9 +104,9 @@ void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &obj // [BB] In case the model should be rendered translucent, do back face culling. // This solves a few of the problems caused by the lack of depth sorting. // TO-DO: Implement proper depth sorting. - if (!(style == DefaultRenderStyle())) + if (!(style == DefaultRenderStyle()) || (smf_flags & MDL_FORCECULLBACKFACES)) { - state.SetCulling((mirrored ^ portalState.isMirrored()) ? Cull_CW : Cull_CCW); + state.SetCulling((mirrored ^ di->drawctx->portalState.isMirrored()) ? Cull_CW : Cull_CCW); } VSMatrix normalModelMatrix; @@ -112,13 +114,13 @@ void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &obj state.SetModelMatrix(objectToWorldMatrix, normalModelMatrix); } -void FHWModelRenderer::EndDrawHUDModel(FRenderStyle style) +void FHWModelRenderer::EndDrawHUDModel(FRenderStyle style, int smf_flags) { state.SetBoneIndexBase(-1); state.SetModelMatrix(VSMatrix::identity(), VSMatrix::identity()); state.SetDepthFunc(DF_Less); - if (!(style == DefaultRenderStyle())) + if (!(style == DefaultRenderStyle()) || (smf_flags & MDL_FORCECULLBACKFACES)) state.SetCulling(Cull_None); } @@ -132,7 +134,7 @@ void FHWModelRenderer::SetInterpolation(double inter) state.SetInterpolationFactor((float)inter); } -void FHWModelRenderer::SetMaterial(FGameTexture *skin, bool clampNoFilter, int translation) +void FHWModelRenderer::SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation) { state.SetMaterial(skin, UF_Skin, 0, clampNoFilter ? CLAMP_NOFILTER : CLAMP_NONE, translation, -1); state.SetLightIndex(modellightindex); diff --git a/src/rendering/hwrenderer/hw_models.h b/src/rendering/hwrenderer/hw_models.h index 32248152b4..c3e5125da6 100644 --- a/src/rendering/hwrenderer/hw_models.h +++ b/src/rendering/hwrenderer/hw_models.h @@ -46,14 +46,14 @@ class FHWModelRenderer : public FModelRenderer FHWModelRenderer(HWDrawInfo *d, FRenderState &st, int mli) : modellightindex(mli), di(d), state(st) {} ModelRendererType GetType() const override { return GLModelRendererType; } - void BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override; - void EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf) override; + void BeginDrawModel(FRenderStyle style, int smf_flags, const VSMatrix &objectToWorldMatrix, bool mirrored) override; + void EndDrawModel(FRenderStyle style, int smf_flags) override; IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override; VSMatrix GetViewToWorldMatrix() override; - void BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored) override; - void EndDrawHUDModel(FRenderStyle style) override; + void BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, int smf_flags) override; + void EndDrawHUDModel(FRenderStyle style, int smf_flags) override; void SetInterpolation(double interpolation) override; - void SetMaterial(FGameTexture *skin, bool clampNoFilter, int translation) override; + void SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation) override; void DrawArrays(int start, int count) override; void DrawElements(int numIndices, size_t offset) override; int SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) override; diff --git a/src/rendering/hwrenderer/hw_precache.cpp b/src/rendering/hwrenderer/hw_precache.cpp index b58c292d77..d6837252d6 100644 --- a/src/rendering/hwrenderer/hw_precache.cpp +++ b/src/rendering/hwrenderer/hw_precache.cpp @@ -152,14 +152,14 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl while (it.NextPair(pair)) { PClassActor *cls = pair->Key; - auto remap = GPalette.TranslationToTable(GetDefaultByType(cls)->Translation); + auto remap = GPalette.TranslationToTable(GetDefaultByType(cls)->Translation.index()); int gltrans = remap == nullptr ? 0 : remap->Index; for (unsigned i = 0; i < cls->GetStateCount(); i++) { auto &state = cls->GetStates()[i]; spritelist[state.sprite].Insert(gltrans, true); - FSpriteModelFrame * smf = FindModelFrame(cls, state.sprite, state.Frame, false); + FSpriteModelFrame * smf = FindModelFrameRaw(cls, state.sprite, state.Frame, false); if (smf != NULL) { for (int i = 0; i < smf->modelsAmount; i++) @@ -316,7 +316,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl FImageSource::EndPrecaching(); // cache all used models - FModelRenderer* renderer = new FHWModelRenderer(nullptr, *screen->RenderState(0), -1); + FModelRenderer* renderer = new FHWModelRenderer(nullptr, *screen->RenderState(), -1); for (unsigned i = 0; i < Models.Size(); i++) { if (modellist[i]) diff --git a/src/rendering/hwrenderer/hw_vertexbuilder.cpp b/src/rendering/hwrenderer/hw_vertexbuilder.cpp index 89f5476ad5..2e64a07ed0 100644 --- a/src/rendering/hwrenderer/hw_vertexbuilder.cpp +++ b/src/rendering/hwrenderer/hw_vertexbuilder.cpp @@ -195,7 +195,7 @@ static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plan ffv.lindex = -1.0f; } -static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plane, float llu, float llv, int llindex) +static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plane, float llu, float llv, float llindex) { ffv.x = (float)vt->fX(); ffv.y = (float)vt->fY(); @@ -204,7 +204,7 @@ static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plan ffv.v = -(float)vt->fY() / 64.f; ffv.lu = llu; ffv.lv = llv; - ffv.lindex = (float)llindex; + ffv.lindex = llindex; } //========================================================================== @@ -214,7 +214,7 @@ static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plan // //========================================================================== -static int CreateIndexedSectorVerticesLM(FRenderState& renderstate, sector_t* sec, const secplane_t& plane, int floor, int h, int lightmapIndex) +static int CreateIndexedSectorVerticesLM(sector_t* sec, const secplane_t& plane, int floor, int h, int lightmapIndex) { int i, pos; float diff; @@ -236,54 +236,61 @@ static int CreateIndexedSectorVerticesLM(FRenderState& renderstate, sector_t* se int idx = ibo_data.Reserve((pos - 2 * sec->subsectorcount) * 3); // Create the actual vertices. - for (i = 0, pos = 0; i < sec->subsectorcount; i++) + auto sections = sec->Level->sections.SectionsForSector(sec); + pos = 0; + for(auto& section : sections) { - subsector_t* sub = sec->subsectors[i]; - LightmapSurface* lightmap = &sub->lightmap[h][lightmapIndex]; - if (lightmap->Type != ST_NULL) + for(auto& sub : section.subsectors) { - float* luvs = lightmap->TexCoords; - int lindex = lightmap->LightmapNum; - for (unsigned int j = 0; j < sub->numlines; j++) + // vertices + DoomLevelMeshSurface* lightmap = sub->surface[h].Size() > lightmapIndex ? sub->surface[h][lightmapIndex] : nullptr; + if (lightmap && lightmap->Type != ST_NONE) // surface may be missing if the subsector is degenerate triangle { - SetFlatVertex(vbo_shadowdata[vi + pos], sub->firstline[j].v1, plane, luvs[j * 2], luvs[j * 2 + 1], lindex); - vbo_shadowdata[vi + pos].z += diff; - pos++; + FFlatVertex* luvs = &level.levelMesh->Mesh.Vertices[lightmap->MeshLocation.StartVertIndex]; + for (unsigned int j = 0, end = sub->numlines; j < end; j++) + { + SetFlatVertex(vbo_shadowdata[vi + pos], sub->firstline[j].v1, plane, luvs[end - 1 - j].lu, luvs[end - 1 - j].lv, luvs[end - 1 - j].lindex); + vbo_shadowdata[vi + pos].z += diff; + pos++; + } } - } - else - { - for (unsigned int j = 0; j < sub->numlines; j++) + else { - SetFlatVertex(vbo_shadowdata[vi + pos], sub->firstline[j].v1, plane); - vbo_shadowdata[vi + pos].z += diff; - pos++; + for (unsigned int j = 0; j < sub->numlines; j++) + { + SetFlatVertex(vbo_shadowdata[vi + pos], sub->firstline[j].v1, plane); + vbo_shadowdata[vi + pos].z += diff; + pos++; + } } } } // Create the indices for the subsectors - for (i = 0, pos = 0; i < sec->subsectorcount; i++) + pos = 0; + for (auto& section : sections) { - subsector_t* sub = sec->subsectors[i]; - int firstndx = vi + pos; - for (unsigned int k = 2; k < sub->numlines; k++) + for (auto& sub : section.subsectors) { - ibo_data[idx++] = firstndx; - ibo_data[idx++] = firstndx + k - 1; - ibo_data[idx++] = firstndx + k; + int firstndx = vi + pos; + for (unsigned int k = 2; k < sub->numlines; k++) + { + ibo_data[idx++] = firstndx; + ibo_data[idx++] = firstndx + k - 1; + ibo_data[idx++] = firstndx + k; + } + pos += sub->numlines; } - pos += sec->subsectors[i]->numlines; } sec->ibocount = ibo_data.Size() - rt; return rt; } -static int CreateIndexedSectorVertices(FRenderState& renderstate, sector_t* sec, const secplane_t& plane, int floor, VertexContainer& verts, int h, int lightmapIndex) +static int CreateIndexedSectorVertices(sector_t* sec, const secplane_t& plane, int floor, VertexContainer& verts, int h, int lightmapIndex) { if (sec->HasLightmaps && lightmapIndex != -1) - return CreateIndexedSectorVerticesLM(renderstate, sec, plane, floor, h, lightmapIndex); + return CreateIndexedSectorVerticesLM(sec, plane, floor, h, lightmapIndex); auto& vbo_shadowdata = sector_vertices; unsigned vi = vbo_shadowdata.Reserve(verts.vertices.Size()); @@ -313,21 +320,21 @@ static int CreateIndexedSectorVertices(FRenderState& renderstate, sector_t* sec, // //========================================================================== -static int CreateIndexedVertices(FRenderState& renderstate, int h, sector_t* sec, const secplane_t& plane, int floor, VertexContainers& verts) +static int CreateIndexedVertices(int h, sector_t* sec, const secplane_t& plane, int floor, VertexContainers& verts) { auto& vbo_shadowdata = sector_vertices; sec->vboindex[h] = vbo_shadowdata.Size(); // First calculate the vertices for the sector itself sec->vboheight[h] = sec->GetPlaneTexZ(h); sec->ibocount = verts[sec->Index()].indices.Size(); - sec->iboindex[h] = CreateIndexedSectorVertices(renderstate, sec, plane, floor, verts[sec->Index()], h, 0); + sec->iboindex[h] = CreateIndexedSectorVertices(sec, plane, floor, verts[sec->Index()], h, 0); // Next are all sectors using this one as heightsec TArray& fakes = sec->e->FakeFloor.Sectors; for (unsigned g = 0; g < fakes.Size(); g++) { sector_t* fsec = fakes[g]; - fsec->iboindex[2 + h] = CreateIndexedSectorVertices(renderstate, fsec, plane, false, verts[fsec->Index()], h, -1); + fsec->iboindex[2 + h] = CreateIndexedSectorVertices(fsec, plane, false, verts[fsec->Index()], h, -1); } // and finally all attached 3D floors @@ -345,7 +352,7 @@ static int CreateIndexedVertices(FRenderState& renderstate, int h, sector_t* sec if (dotop || dobottom) { - auto ndx = CreateIndexedSectorVertices(renderstate, fsec, plane, false, verts[fsec->Index()], h, ffloorIndex + 1); + auto ndx = CreateIndexedSectorVertices(fsec, plane, false, verts[fsec->Index()], h, ffloorIndex + 1); if (dotop) ffloor->top.vindex = ndx; if (dobottom) ffloor->bottom.vindex = ndx; } @@ -362,7 +369,7 @@ static int CreateIndexedVertices(FRenderState& renderstate, int h, sector_t* sec // //========================================================================== -static void CreateIndexedFlatVertices(FRenderState& renderstate, TArray& sectors) +static void CreateIndexedFlatVertices(TArray& sectors) { auto verts = BuildVertices(sectors); @@ -391,7 +398,7 @@ static void CreateIndexedFlatVertices(FRenderState& renderstate, TArray& sectors) +static void CreateVertices(TArray& sectors) { sector_vertices.Clear(); - CreateIndexedFlatVertices(renderstate, sectors); + CreateIndexedFlatVertices(sectors); } //========================================================================== @@ -491,6 +498,6 @@ void CheckUpdate(FRenderState& renderstate, sector_t* sector) void CreateVBO(FRenderState& renderstate, TArray& sectors) { sector_vertices.Clear(); - CreateVertices(renderstate, sectors); + CreateVertices(sectors); renderstate.SetShadowData(sector_vertices, sector_indexes); } diff --git a/src/rendering/hwrenderer/hw_vertexbuilder.h b/src/rendering/hwrenderer/hw_vertexbuilder.h index 7d04df3f04..6bfe10709e 100644 --- a/src/rendering/hwrenderer/hw_vertexbuilder.h +++ b/src/rendering/hwrenderer/hw_vertexbuilder.h @@ -1,4 +1,4 @@ - +#pragma once #include "tarray.h" #include "r_defs.h" diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 684bed8516..6dd4d04bb1 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -42,6 +42,8 @@ #include "hw_clock.h" #include "flatvertices.h" #include "hw_vertexbuilder.h" +#include "hw_walldispatcher.h" +#include "hw_flatdispatcher.h" #ifdef ARCH_IA32 #include @@ -105,8 +107,10 @@ static RenderJobQueue jobQueue; // One static queue is sufficient here. This cod void HWDrawInfo::WorkerThread() { sector_t *front, *back; + HWWallDispatcher disp(this); + HWFlatDispatcher fdisp(this); - FRenderState& state = *screen->RenderState(0); + FRenderState& state = *screen->RenderState(); WTTotal.Clock(); isWorkerThread = true; // for adding asserts in GL API code. The worker thread may never call any GL API. @@ -140,18 +144,14 @@ void HWDrawInfo::WorkerThread() case RenderJob::WallJob: { - HWWall wall; - SetupWall.Clock(); - wall.sub = job->sub; - - front = hw_FakeFlat(job->sub->sector, in_area, false); + front = hw_FakeFlat(drawctx, job->sub->sector, in_area, false); auto seg = job->seg; auto backsector = seg->backsector; if (!backsector && seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]) // For one-sided portals use the portal's destination sector as backsector. { auto portal = seg->linedef->getPortal(); backsector = portal->mDestination->frontsector; - back = hw_FakeFlat(backsector, in_area, true); + back = hw_FakeFlat(drawctx, backsector, in_area, true); if (front->floorplane.isSlope() || front->ceilingplane.isSlope() || back->floorplane.isSlope() || back->ceilingplane.isSlope()) { // Having a one-sided portal like this with slopes is too messy so let's ignore that case. @@ -166,12 +166,15 @@ void HWDrawInfo::WorkerThread() } else { - back = hw_FakeFlat(backsector, in_area, true); + back = hw_FakeFlat(drawctx, backsector, in_area, true); } } else back = nullptr; - wall.Process(this, state, job->seg, front, back); + HWWall wall; + SetupWall.Clock(); + wall.sub = job->sub; + wall.Process(&disp, state, job->seg, front, back); rendered_lines++; SetupWall.Unclock(); break; @@ -182,22 +185,22 @@ void HWDrawInfo::WorkerThread() HWFlat flat; SetupFlat.Clock(); flat.section = job->sub->section; - front = hw_FakeFlat(job->sub->render_sector, in_area, false); - flat.ProcessSector(this, state, front); + front = hw_FakeFlat(drawctx, job->sub->render_sector, in_area, false); + flat.ProcessSector(&fdisp, state, front); SetupFlat.Unclock(); break; } case RenderJob::SpriteJob: SetupSprite.Clock(); - front = hw_FakeFlat(job->sub->sector, in_area, false); + front = hw_FakeFlat(drawctx, job->sub->sector, in_area, false); RenderThings(job->sub, front, state); SetupSprite.Unclock(); break; case RenderJob::ParticleJob: SetupSprite.Clock(); - front = hw_FakeFlat(job->sub->sector, in_area, false); + front = hw_FakeFlat(drawctx, job->sub->sector, in_area, false); RenderParticles(job->sub, front, state); SetupSprite.Unclock(); break; @@ -321,7 +324,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) // clipping checks are only needed when the backsector is not the same as the front sector if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); - backsector = hw_FakeFlat(seg->backsector, in_area, true); + backsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true); if (hw_CheckClip(seg->sidedef, currentsector, backsector)) { @@ -350,9 +353,10 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) else { HWWall wall; + HWWallDispatcher disp(this); SetupWall.Clock(); wall.sub = seg->Subsector; - wall.Process(this, state, seg, currentsector, backsector); + wall.Process(&disp, state, seg, currentsector, backsector); rendered_lines++; SetupWall.Unclock(); } @@ -596,16 +600,31 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector, FRenderState void HWDrawInfo::RenderParticles(subsector_t *sub, sector_t *front, FRenderState& state) { SetupSprite.Clock(); + for (uint32_t i = 0; i < sub->sprites.Size(); i++) + { + DVisualThinker *sp = sub->sprites[i]; + if (!sp || sp->ObjectFlags & OF_EuthanizeMe) + continue; + if (mClipPortal) + { + int clipres = mClipPortal->ClipPoint(sp->PT.Pos.XY()); + if (clipres == PClip_InFront) continue; + } + + assert(sp->spr); + + sp->spr->ProcessParticle(this, state, &sp->PT, front, sp); + } for (int i = Level->ParticlesInSubsec[sub->Index()]; i != NO_PARTICLE; i = Level->Particles[i].snext) { if (mClipPortal) { - int clipres = mClipPortal->ClipPoint(Level->Particles[i].Pos); + int clipres = mClipPortal->ClipPoint(Level->Particles[i].Pos.XY()); if (clipres == PClip_InFront) continue; } HWSprite sprite; - sprite.ProcessParticle(this, state, &Level->Particles[i], front); + sprite.ProcessParticle(this, state, &Level->Particles[i], front, nullptr); } SetupSprite.Unclock(); } @@ -648,7 +667,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) } if (mClipper->IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet. - fakesector=hw_FakeFlat(sector, in_area, false); + fakesector=hw_FakeFlat(drawctx, sector, in_area, false); if (mClipPortal) { @@ -668,7 +687,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) } // [RH] Add particles - if (gl_render_things && Level->ParticlesInSubsec[sub->Index()] != NO_PARTICLE) + if (gl_render_things && (sub->sprites.Size() > 0 || Level->ParticlesInSubsec[sub->Index()] != NO_PARTICLE)) { if (multithread) { @@ -725,7 +744,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) sector = sub->render_sector; // the planes of this subsector are faked to belong to another sector // This means we need the heightsec parts and light info of the render sector, not the actual one. - fakesector = hw_FakeFlat(sector, in_area, false); + fakesector = hw_FakeFlat(drawctx, sector, in_area, false); } uint8_t &srf = section_renderflags[Level->sections.SectionIndex(sub->section)]; @@ -741,8 +760,9 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) { HWFlat flat; flat.section = sub->section; + HWFlatDispatcher disp(this); SetupFlat.Clock(); - flat.ProcessSector(this, state, fakesector); + flat.ProcessSector(&disp, state, fakesector); SetupFlat.Unclock(); } } diff --git a/src/rendering/hwrenderer/scene/hw_clipper.cpp b/src/rendering/hwrenderer/scene/hw_clipper.cpp index fd69e267c2..b46e7837f4 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.cpp +++ b/src/rendering/hwrenderer/scene/hw_clipper.cpp @@ -39,13 +39,6 @@ #include "g_levellocals.h" #include "basics.h" -unsigned Clipper::starttime; - -Clipper::Clipper() -{ - starttime++; -} - //----------------------------------------------------------------------------- // // RemoveRange diff --git a/src/rendering/hwrenderer/scene/hw_clipper.h b/src/rendering/hwrenderer/scene/hw_clipper.h index e8da8172cf..4eeff16b35 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.h +++ b/src/rendering/hwrenderer/scene/hw_clipper.h @@ -1,5 +1,4 @@ -#ifndef __GL_CLIPPER -#define __GL_CLIPPER +#pragma once #include "doomtype.h" #include "xs_Float.h" @@ -22,7 +21,7 @@ class ClipNode class Clipper { - static unsigned starttime; + unsigned int starttime = 1; FMemArena nodearena; ClipNode * freelist = nullptr; @@ -41,8 +40,6 @@ class Clipper public: - Clipper(); - void Clear(); void Free(ClipNode *node) @@ -158,5 +155,3 @@ class Clipper } }; - -#endif diff --git a/src/rendering/hwrenderer/scene/hw_decal.cpp b/src/rendering/hwrenderer/scene/hw_decal.cpp index 25d3749ed8..cc0dd456c0 100644 --- a/src/rendering/hwrenderer/scene/hw_decal.cpp +++ b/src/rendering/hwrenderer/scene/hw_decal.cpp @@ -35,6 +35,7 @@ #include "hwrenderer/scene/hw_drawinfo.h" #include "hw_lighting.h" #include "hw_clock.h" +#include "hw_drawcontext.h" #include "flatvertices.h" #include "hw_renderstate.h" #include "texturemanager.h" @@ -70,7 +71,7 @@ void HWDecal::DrawDecal(HWDrawInfo *di, FRenderState &state) else state.AlphaFunc(Alpha_Greater, 0.f); - di->SetColor(state, lightlevel, rellight, di->isFullbrightScene(), Colormap, alpha); + SetColor(state, di->Level, di->lightmode, lightlevel, rellight, di->isFullbrightScene(), Colormap, alpha); // for additively drawn decals we must temporarily set the fog color to black. PalEntry fc = state.GetFogColor(); if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) @@ -101,9 +102,9 @@ void HWDecal::DrawDecal(HWDrawInfo *di, FRenderState &state) FColormap thiscm; thiscm.FadeColor = Colormap.FadeColor; CopyFrom3DLight(thiscm, &lightlist[k]); - di->SetColor(state, thisll, rellight, di->isFullbrightScene(), thiscm, alpha); + SetColor(state, di->Level, di->lightmode, thisll, rellight, di->isFullbrightScene(), thiscm, alpha); if (di->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize(); - di->SetFog(state, thisll, rellight, di->isFullbrightScene(), &thiscm, false); + SetFog(state, di->Level, di->lightmode, thisll, rellight, di->isFullbrightScene(), &thiscm, false, di->drawctx->portalState.inskybox); SetSplitPlanes(state, lightlist[k].plane, lowplane); state.Draw(DT_TriangleStrip, vertindex, 4); @@ -142,7 +143,7 @@ void HWDrawInfo::DrawDecals(FRenderState &state, TArray &decals) else { state.EnableSplit(false); - SetFog(state, gldecal->lightlevel, gldecal->rellight, isFullbrightScene(), &gldecal->Colormap, false); + SetFog(state, Level, lightmode, gldecal->lightlevel, gldecal->rellight, isFullbrightScene(), &gldecal->Colormap, false, drawctx->portalState.inskybox); } } gldecal->DrawDecal(this, state); @@ -164,7 +165,7 @@ void HWWall::DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArraySetFog(state, lightlevel, rellight + getExtraLight(), di->isFullbrightScene(), &Colormap, false); + SetFog(state, di->Level, di->lightmode, lightlevel, rellight + getExtraLight(), di->isFullbrightScene(), &Colormap, false, di->drawctx->portalState.inskybox); for (auto gldecal : decals) { if (gldecal->decal->Side == seg->sidedef) @@ -334,29 +335,6 @@ void HWWall::ProcessDecal(HWDrawInfo *di, FRenderState& state, DBaseDecal *decal dv[LR].u = dv[UR].u = righttex / decalscale; dv[LL].v = dv[LR].v = 1.f; - // lightmap texture index - for (i = 0; i < 4; i++) - { - dv[i].lindex = lindex; - } - - // lightmap texture coordinates - float tleft = left / linelength; - float tright = right / linelength; - float tuplft = ztop[0] != zbottom[0] ? (dv[UL].z - zbottom[0]) / (ztop[0] - zbottom[0]) : 0.0f; - float tuprgt = ztop[1] != zbottom[1] ? (dv[UR].z - zbottom[1]) / (ztop[1] - zbottom[1]) : 0.0f; - float tlolft = ztop[0] != zbottom[0] ? (dv[LL].z - zbottom[0]) / (ztop[0] - zbottom[0]) : 0.0f; - float tlorgt = ztop[1] != zbottom[1] ? (dv[LR].z - zbottom[1]) / (ztop[1] - zbottom[1]) : 0.0f; - - dv[LL].lu = mix(lightuv[LOLFT].u, lightuv[LORGT].u, tleft); - dv[LR].lu = mix(lightuv[LOLFT].u, lightuv[LORGT].u, tright); - dv[UL].lu = mix(lightuv[UPLFT].u, lightuv[UPRGT].u, tleft); - dv[UR].lu = mix(lightuv[UPLFT].u, lightuv[UPRGT].u, tright); - - dv[LL].lv = mix(lightuv[LOLFT].v, lightuv[UPLFT].v, tlolft); - dv[LR].lv = mix(lightuv[LORGT].v, lightuv[UPRGT].v, tlorgt); - dv[UL].lv = mix(lightuv[LOLFT].v, lightuv[UPLFT].v, tuplft); - dv[UR].lv = mix(lightuv[LORGT].v, lightuv[UPRGT].v, tuprgt); // now clip to the top plane float vzt = (ztop[UL] - ztop[LL]) / linelength; @@ -375,8 +353,6 @@ void HWWall::ProcessDecal(HWDrawInfo *di, FRenderState& state, DBaseDecal *decal float t1 = (dv[UR].z - topright) / (dv[UR].z - dv[LR].z); dv[UL].v = t0 * dv[LL].v; dv[UR].v = t1 * dv[LR].v; - dv[UL].lv = mix(dv[UL].lv, dv[LL].lv, t0); - dv[UR].lv = mix(dv[UR].lv, dv[LR].lv, t1); dv[UL].z = topleft; dv[UR].z = topright; } @@ -398,8 +374,6 @@ void HWWall::ProcessDecal(HWDrawInfo *di, FRenderState& state, DBaseDecal *decal float t1 = (dv[UR].z - bottomright) / (dv[UR].z - dv[LR].z); dv[LL].v = t0 * (dv[LL].v - dv[UL].v) + dv[UL].v; dv[LR].v = t1 * (dv[LR].v - dv[UR].v) + dv[UR].v; - dv[LL].lv = mix(dv[UL].lv, dv[LL].lv, t0); - dv[LR].lv = mix(dv[UR].lv, dv[LR].lv, t1); dv[LL].z = bottomleft; dv[LR].z = bottomright; } @@ -447,10 +421,24 @@ void HWWall::ProcessDecal(HWDrawInfo *di, FRenderState& state, DBaseDecal *decal auto verts = state.AllocVertices(4); gldecal->vertindex = verts.second; - - for (i = 0; i < 4; i++) + + if (surface && surface->LightmapTileIndex >= 0) { - verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v, dv[i].lu, dv[i].lv, dv[i].lindex); + LightmapTile* tile = &di->Level->levelMesh->LightmapTiles[surface->LightmapTileIndex]; + float lightmapindex = (float)tile->AtlasLocation.ArrayIndex; + + for (i = 0; i < 4; i++) + { + FVector2 lightmapuv = tile->ToUV(FVector3(dv[i].x, dv[i].y, dv[i].z), di->Level->levelMesh->LMTextureSize); + verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v, lightmapuv.X, lightmapuv.Y, lightmapindex); + } + } + else + { + for (i = 0; i < 4; i++) + { + verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v, 0.0f, 0.0f, -1.0f); + } } } diff --git a/src/rendering/hwrenderer/scene/hw_drawcontext.cpp b/src/rendering/hwrenderer/scene/hw_drawcontext.cpp new file mode 100644 index 0000000000..34829b4b80 --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_drawcontext.cpp @@ -0,0 +1,57 @@ + +#include "hw_drawcontext.h" +#include "hw_drawinfo.h" + +//========================================================================== +// +// Try to reuse the lists as often as possible as they contain resources that +// are expensive to create and delete. +// +// Note: If multithreading gets used, this class needs synchronization. +// +//========================================================================== + +HWDrawInfo* FDrawInfoList::GetNew() +{ + if (mList.Size() > 0) + { + HWDrawInfo* di; + mList.Pop(di); + return di; + } + return new HWDrawInfo(drawctx); +} + +void FDrawInfoList::Release(HWDrawInfo* di) +{ + di->ClearBuffers(); + di->Level = nullptr; + mList.Push(di); +} + +//========================================================================== + +SortNode* StaticSortNodeArray::GetNew() +{ + if (usecount == TArray::Size()) + { + Push(new SortNode); + } + return operator[](usecount++); +} + +//========================================================================== + +HWDrawContext::HWDrawContext() : RenderDataAllocator(1024 * 1024), FakeSectorAllocator(20 * sizeof(sector_t)) +{ + di_list.drawctx = this; +} + +HWDrawContext::~HWDrawContext() +{ +} + +void HWDrawContext::ResetRenderDataAllocator() +{ + RenderDataAllocator.FreeAll(); +} diff --git a/src/rendering/hwrenderer/scene/hw_drawcontext.h b/src/rendering/hwrenderer/scene/hw_drawcontext.h new file mode 100644 index 0000000000..62e971de12 --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_drawcontext.h @@ -0,0 +1,55 @@ +#pragma once + +#include "common/utility/tarray.h" +#include "hw_clipper.h" +#include "hw_portal.h" + +struct HWDrawInfo; +struct SortNode; +struct FDynamicLight; +class HWDrawContext; + +class FDrawInfoList +{ +public: + HWDrawContext* drawctx = nullptr; + TDeletingArray mList; + + HWDrawInfo* GetNew(); + void Release(HWDrawInfo*); +}; + +class StaticSortNodeArray : public TDeletingArray +{ +public: + unsigned int Size() { return usecount; } + void Clear() { usecount = 0; } + void Release(int start) { usecount = start; } + SortNode* GetNew(); + +private: + unsigned int usecount = 0; +}; + +class HWDrawContext +{ +public: + HWDrawContext(); + ~HWDrawContext(); + + void ResetRenderDataAllocator(); + + FDrawInfoList di_list; + Clipper staticClipper; // Since all scenes are processed sequentially we only need one clipper. + HWDrawInfo* gl_drawinfo = nullptr; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope. + + FMemArena RenderDataAllocator; // Use large blocks to reduce allocation time. + StaticSortNodeArray SortNodes; + + sector_t** fakesectorbuffer = nullptr; + FMemArena FakeSectorAllocator; + + FPortalSceneState portalState; + + TArray addedLightsArray; +}; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 39c65fc885..6211bcb0f5 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -34,6 +34,8 @@ #include "hw_portal.h" #include "hw_renderstate.h" #include "hw_drawinfo.h" +#include "hw_drawcontext.h" +#include "hw_walldispatcher.h" #include "po_man.h" #include "models.h" #include "hw_clock.h" @@ -41,14 +43,19 @@ #include "flatvertices.h" #include "hw_vrmodes.h" #include "hw_clipper.h" -#include "hw_meshcache.h" #include "v_draw.h" -#include "a_corona.h" #include "texturemanager.h" #include "actorinlines.h" #include "g_levellocals.h" +#include "hw_lighting.h" EXTERN_CVAR(Float, r_visibility) +EXTERN_CVAR(Int, lm_background_updates); +EXTERN_CVAR(Float, r_actorspriteshadowdist) +EXTERN_CVAR(Bool, gl_portals) + +CVAR(Bool, lm_always_update, false, 0) + CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE) CVAR(Bool, gl_sort_textures, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, gl_no_skyclear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -60,54 +67,10 @@ CVAR(Float, gl_mask_sprite_threshold, 0.5f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, gl_coronas, true, CVAR_ARCHIVE); -CVAR(Bool, gl_meshcache, false, 0/*CVAR_ARCHIVE | CVAR_GLOBALCONFIG*/) +CVAR(Bool, gl_levelmesh, false, 0/*CVAR_ARCHIVE | CVAR_GLOBALCONFIG*/) sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back); -//========================================================================== -// -// -// -//========================================================================== - -class FDrawInfoList -{ -public: - TDeletingArray mList; - - HWDrawInfo * GetNew(); - void Release(HWDrawInfo *); -}; - - -FDrawInfoList di_list; - -//========================================================================== -// -// Try to reuse the lists as often as possible as they contain resources that -// are expensive to create and delete. -// -// Note: If multithreading gets used, this class needs synchronization. -// -//========================================================================== - -HWDrawInfo *FDrawInfoList::GetNew() -{ - if (mList.Size() > 0) - { - HWDrawInfo *di; - mList.Pop(di); - return di; - } - return new HWDrawInfo(); -} - -void FDrawInfoList::Release(HWDrawInfo * di) -{ - di->ClearBuffers(); - di->Level = nullptr; - mList.Push(di); -} //========================================================================== // @@ -115,31 +78,22 @@ void FDrawInfoList::Release(HWDrawInfo * di) // //========================================================================== -HWDrawInfo *HWDrawInfo::StartDrawInfo(FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms) +HWDrawInfo *HWDrawInfo::StartDrawInfo(HWDrawContext* drawctx, FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms) { - HWDrawInfo *di = di_list.GetNew(); + HWDrawInfo *di = drawctx->di_list.GetNew(); di->Level = lev; di->StartScene(parentvp, uniforms); return di; } - -//========================================================================== -// -// -// -//========================================================================== - -static Clipper staticClipper; // Since all scenes are processed sequentially we only need one clipper. -static HWDrawInfo * gl_drawinfo; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope. - void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms) { - staticClipper.Clear(); - mClipper = &staticClipper; + drawctx->staticClipper.Clear(); + mClipper = &drawctx->staticClipper; Viewpoint = parentvp; - lightmode = Level->lightMode; + lightmode = getRealLightmode(Level, true); + if (uniforms) { VPUniforms = *uniforms; @@ -153,7 +107,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni VPUniforms.mViewMatrix.loadIdentity(); VPUniforms.mNormalViewMatrix.loadIdentity(); VPUniforms.mViewHeight = viewheight; - if (gl_lightmode == 5) + if (lightmode == ELightMode::Build) { VPUniforms.mGlobVis = 1 / 64.f; VPUniforms.mPalLightLevels = 32 | (static_cast(gl_fogmode) << 8) | ((int)lightmode << 16); @@ -164,7 +118,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni VPUniforms.mPalLightLevels = static_cast(gl_bandedswlight) | (static_cast(gl_fogmode) << 8) | ((int)lightmode << 16); } VPUniforms.mClipLine.X = -10000000.0f; - VPUniforms.mShadowmapFilter = static_cast(gl_shadowmap_filter); + VPUniforms.mShadowFilter = static_cast(gl_light_shadow_filter); VPUniforms.mLightBlendMode = (level.info ? (int)level.info->lightblendmode : 0); } mClipper->SetViewpoint(Viewpoint); @@ -174,14 +128,16 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset(); hudsprites.Clear(); Coronas.Clear(); + Fogballs.Clear(); + VisibleTiles.Clear(); vpIndex = 0; // Fullbright information needs to be propagated from the main view. if (outer != nullptr) FullbrightFlags = outer->FullbrightFlags; else FullbrightFlags = 0; - outer = gl_drawinfo; - gl_drawinfo = this; + outer = drawctx->gl_drawinfo; + drawctx->gl_drawinfo = this; } @@ -193,13 +149,13 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni HWDrawInfo *HWDrawInfo::EndDrawInfo() { - assert(this == gl_drawinfo); + assert(this == drawctx->gl_drawinfo); for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset(); - gl_drawinfo = outer; - di_list.Release(this); - if (gl_drawinfo == nullptr) - ResetRenderDataAllocator(); - return gl_drawinfo; + drawctx->gl_drawinfo = outer; + drawctx->di_list.Release(this); + if (drawctx->gl_drawinfo == nullptr) + drawctx->ResetRenderDataAllocator(); + return drawctx->gl_drawinfo; } @@ -421,7 +377,7 @@ HWPortal * HWDrawInfo::FindPortal(const void * src) HWDecal *HWDrawInfo::AddDecal(bool onmirror) { - auto decal = (HWDecal*)RenderDataAllocator.Alloc(sizeof(HWDecal)); + auto decal = (HWDecal*)drawctx->RenderDataAllocator.Alloc(sizeof(HWDecal)); Decals[onmirror ? 1 : 0].Push(decal); return decal; } @@ -441,14 +397,105 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1); // reset the portal manager - portalState.StartFrame(); + drawctx->portalState.StartFrame(); ProcessAll.Clock(); // clip the scene and fill the drawlists - if (!gl_meshcache) + if (gl_levelmesh && !outer) + { + // Give the DrawInfo the viewpoint in fixed point because that's what the nodes are. + viewx = FLOAT2FIXED(Viewpoint.Pos.X); + viewy = FLOAT2FIXED(Viewpoint.Pos.Y); + + validcount++; // used for processing sidedefs only once by the renderer. + + auto& portals = level.levelMesh->WallPortals; + + // draw level into depth buffer + state.SetColorMask(false); + state.SetCulling(Cull_CW); + state.DrawLevelMeshSurfaces(true); + if (gl_portals) + { + state.SetDepthBias(1, 128); + state.DrawLevelMeshPortals(true); + state.SetDepthBias(0, 0); + } + + // use occlusion queries on all portals in level to decide which are visible + int queryStart = state.GetNextQueryIndex(); + state.SetDepthMask(false); + state.EnableTexture(false); + state.SetEffect(EFF_PORTAL); + for (HWWall& wall : portals) + { + state.BeginQuery(); + + wall.MakeVertices(state, false); + wall.RenderWall(state, HWWall::RWF_BLANK); + wall.vertcount = 0; + + state.EndQuery(); + } + state.SetEffect(EFF_NONE); + state.EnableTexture(gl_texture); + state.SetColorMask(true); + state.SetDepthMask(true); + int queryEnd = state.GetNextQueryIndex(); + + // draw opaque level so the GPU has something to do while we examine the query results + state.DrawLevelMeshSurfaces(false); + if (!gl_portals) + { + state.SetDepthBias(1, 128); + state.DrawLevelMeshPortals(false); + state.SetDepthBias(0, 0); + } + state.SetCulling(Cull_None); + + // retrieve the query results and use them to fill the portal manager with portals + state.GetQueryResults(queryStart, queryEnd - queryStart, QueryResultsBuffer); + for (unsigned int i = 0, count = QueryResultsBuffer.Size(); i < count; i++) + { + bool portalVisible = QueryResultsBuffer[i]; + if (portalVisible) + { + PutWallPortal(portals[i], state); + } + } + + // Draw sprites + auto it = level.GetThinkerIterator(); + AActor* thing; + while ((thing = it.Next()) != nullptr) + { + HWSprite sprite; + + if (R_ShouldDrawSpriteShadow(thing)) + { + double dist = (thing->Pos() - vp.Pos).LengthSquared(); + double check = r_actorspriteshadowdist; + if (dist <= check * check) + { + sprite.Process(this, state, thing, thing->Sector, in_area, false, true); + } + } + + sprite.Process(this, state, thing, thing->Sector, in_area, false); + } + + // Process all the sprites on the current portal's back side which touch the portal. + if (mCurrentPortal != nullptr) mCurrentPortal->RenderAttached(this, state); + + if (drawpsprites) + PreparePlayerSprites(Viewpoint.sector, in_area, state); + } + else + { RenderBSP(Level->HeadNode(), drawpsprites, state); + } // And now the crappy hacks that have to be done to avoid rendering anomalies. // These cannot be multithreaded when the time comes because all these depend @@ -459,10 +506,136 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) PrepareUnhandledMissingTextures(state); DispatchRenderHacks(state); + // Sort fogballs by view order + FVector3 campos(vp.Pos); + std::sort(Fogballs.begin(), Fogballs.end(), [&](const Fogball& a, const Fogball& b) -> bool { + FVector3 rayA = a.Position - campos; + FVector3 rayB = b.Position - campos; + float distSqrA = rayA | rayA; + float distSqrB = rayB | rayB; + return distSqrA > distSqrB; + }); + ProcessAll.Unclock(); } +void HWDrawInfo::PutWallPortal(HWWall wall, FRenderState& state) +{ + HWWallDispatcher ddi(this); + + int portaltype = wall.portaltype; + int portalplane = wall.portalplane; + + HWSkyInfo skyinfo; + if (portaltype == PORTALTYPE_SKY) + { + skyinfo.init(this, wall.frontsector, sector_t::ceiling, wall.frontsector->skytransfer, wall.Colormap.FadeColor); + wall.sky = &skyinfo; + wall.PutPortal(&ddi, state, portaltype, portalplane); + } + else if (portaltype == PORTALTYPE_SECTORSTACK) + { + // To do: this seems to need AddSubsectorToPortal? + + //if (screen->instack[1 - portalplane]) + // return; + //wall.PutPortal(&ddi, state, portaltype, portalplane); + } + else if (portaltype == PORTALTYPE_PLANEMIRROR) + { + auto vpz = Viewpoint.Pos.Z; + if ((portalplane == sector_t::ceiling && vpz > wall.frontsector->ceilingplane.fD()) || (portalplane == sector_t::floor && vpz < -wall.frontsector->floorplane.fD())) + return; + wall.planemirror = (portalplane == sector_t::ceiling) ? &wall.frontsector->ceilingplane : &wall.frontsector->floorplane; + wall.PutPortal(&ddi, state, portaltype, portalplane); + } + else if (portaltype == PORTALTYPE_HORIZON) + { + HWHorizonInfo hi; + auto vpz = ddi.di->Viewpoint.Pos.Z; + if (vpz < wall.frontsector->GetPlaneTexZ(sector_t::ceiling)) + { + if (vpz > wall.frontsector->GetPlaneTexZ(sector_t::floor)) + wall.zbottom[1] = wall.zbottom[0] = vpz; + + hi.plane.GetFromSector(wall.frontsector, sector_t::ceiling); + hi.lightlevel = hw_ClampLight(wall.frontsector->GetCeilingLight()); + hi.colormap = wall.frontsector->Colormap; + hi.specialcolor = wall.frontsector->SpecialColors[sector_t::ceiling]; + if (wall.frontsector->e->XFloor.ffloors.Size()) + { + auto light = P_GetPlaneLight(wall.frontsector, &wall.frontsector->ceilingplane, true); + + if (!(wall.frontsector->GetFlags(sector_t::ceiling) & PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel); + hi.colormap.CopyLight(light->extra_colormap); + } + + if (ddi.isFullbrightScene()) hi.colormap.Clear(); + wall.horizon = &hi; + wall.PutPortal(&ddi, state, portaltype, portalplane); + } + if (vpz > wall.frontsector->GetPlaneTexZ(sector_t::floor)) + { + wall.zbottom[1] = wall.zbottom[0] = wall.frontsector->GetPlaneTexZ(sector_t::floor); + + hi.plane.GetFromSector(wall.frontsector, sector_t::floor); + hi.lightlevel = hw_ClampLight(wall.frontsector->GetFloorLight()); + hi.colormap = wall.frontsector->Colormap; + hi.specialcolor = wall.frontsector->SpecialColors[sector_t::floor]; + + if (wall.frontsector->e->XFloor.ffloors.Size()) + { + auto light = P_GetPlaneLight(wall.frontsector, &wall.frontsector->floorplane, false); + + if (!(wall.frontsector->GetFlags(sector_t::floor) & PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel); + hi.colormap.CopyLight(light->extra_colormap); + } + + if (ddi.isFullbrightScene()) hi.colormap.Clear(); + wall.horizon = &hi; + wall.PutPortal(&ddi, state, portaltype, portalplane); + } + } + else if (portaltype == PORTALTYPE_SKYBOX) + { + FSectorPortal* sportal = wall.frontsector->ValidatePortal(portalplane); + if (sportal != nullptr && sportal->mFlags & PORTSF_INSKYBOX) sportal = nullptr; // no recursions, delete it here to simplify the following code + wall.secportal = sportal; + if (sportal) + { + wall.PutPortal(&ddi, state, portaltype, portalplane); + } + } + else if (portaltype == PORTALTYPE_MIRROR) + { + wall.PutPortal(&ddi, state, portaltype, portalplane); + } + else if (portaltype == PORTALTYPE_LINETOLINE) + { + wall.lineportal = wall.seg->linedef->getPortal()->mGroup; + wall.PutPortal(&ddi, state, portaltype, portalplane); + } +} + +void HWDrawInfo::UpdateLightmaps() +{ + if (!outer && VisibleTiles.Size() < unsigned(lm_background_updates)) + { + for (auto& e : level.levelMesh->LightmapTiles) + { + if (e.NeedsUpdate) + { + VisibleTiles.Push(&e); + + if (VisibleTiles.Size() >= unsigned(lm_background_updates)) + break; + } + } + } + screen->UpdateLightmaps(VisibleTiles); +} + //----------------------------------------------------------------------------- // // RenderScene @@ -476,6 +649,8 @@ void HWDrawInfo::RenderScene(FRenderState &state) const auto &vp = Viewpoint; RenderAll.Clock(); + UpdateLightmaps(); + state.SetLightMode((int)lightmode); state.SetDepthMask(true); @@ -502,21 +677,11 @@ void HWDrawInfo::RenderScene(FRenderState &state) drawlists[GLDL_PLAINWALLS].DrawWalls(this, state, false); drawlists[GLDL_PLAINFLATS].DrawFlats(this, state, false); - if (gl_meshcache && meshcache.Opaque) - { - meshcache.Opaque->Draw(state); - } - // Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); drawlists[GLDL_MASKEDWALLS].DrawWalls(this, state, false); drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false); - if (gl_meshcache && meshcache.Translucent) - { - meshcache.Translucent->Draw(state); - } - // Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use. if (drawlists[GLDL_MASKEDWALLSOFS].Size() > 0) { @@ -525,13 +690,6 @@ void HWDrawInfo::RenderScene(FRenderState &state) state.ClearDepthBias(); } - if (gl_meshcache && meshcache.TranslucentDepthBiased) - { - state.SetDepthBias(-1, -128); - meshcache.TranslucentDepthBiased->Draw(state); - state.ClearDepthBias(); - } - drawlists[GLDL_MODELS].Draw(this, state, false); state.SetRenderStyle(STYLE_Translucent); @@ -582,7 +740,7 @@ void HWDrawInfo::RenderPortal(HWPortal *p, FRenderState &state, bool usestencil) { auto gp = static_cast(p); gp->SetupStencil(this, state, usestencil); - auto new_di = StartDrawInfo(this->Level, this, Viewpoint, &VPUniforms); + auto new_di = StartDrawInfo(drawctx, this->Level, this, Viewpoint, &VPUniforms); new_di->mCurrentPortal = gp; state.SetLightIndex(-1); gp->DrawContents(new_di, state); @@ -593,7 +751,7 @@ void HWDrawInfo::RenderPortal(HWPortal *p, FRenderState &state, bool usestencil) } -void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist) +void HWDrawInfo::DrawCorona(FRenderState& state, AActor* corona, float coronaFade, double dist) { spriteframe_t* sprframe = &SpriteFrames[sprites[corona->sprite].spriteframes + (size_t)corona->SpawnState->GetFrame()]; FTextureID patch = sprframe->Texture[0]; @@ -613,7 +771,7 @@ void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist) float screenX = halfViewportWidth + clipPos.X * invW * halfViewportWidth; float screenY = halfViewportHeight - clipPos.Y * invW * halfViewportHeight; - float alpha = corona->CoronaFade * float(corona->Alpha); + float alpha = coronaFade * float(corona->Alpha); // distance-based fade - looks better IMO float distNearFadeStart = float(corona->RenderRadius()) * 0.1f; @@ -628,11 +786,12 @@ void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist) alpha *= distFade; state.SetColorAlpha(0xffffff, alpha, 0); - if (isSoftwareLighting()) state.SetSoftLightLevel(255); + if (isSoftwareLighting(lightmode)) state.SetSoftLightLevel(255); else state.SetNoSoftLightLevel(); state.SetLightIndex(-1); state.SetRenderStyle(corona->RenderStyle); + state.SetTextureMode(TM_NORMAL); // This is needed because the next line doesn't always set the mode... state.SetTextureMode(corona->RenderStyle); state.SetMaterial(tex, UF_Sprite, CTF_Expand, CLAMP_XY_NOMIP, 0, 0); @@ -683,8 +842,9 @@ void HWDrawInfo::DrawCoronas(FRenderState& state) float timeElapsed = (screen->FrameTime - LastFrameTime) / 1000.0f; LastFrameTime = screen->FrameTime; - for (ACorona* corona : Coronas) + for (AActor* corona : Coronas) { + auto& coronaFade = corona->specialf1; auto cPos = corona->Vec3Offset(0., 0., corona->Height * 0.5); DVector3 direction = Viewpoint.Pos - cPos; double dist = direction.Length(); @@ -699,15 +859,15 @@ void HWDrawInfo::DrawCoronas(FRenderState& state) FTraceResults results; if (!Trace(cPos, corona->Sector, direction, dist, MF_SOLID, ML_BLOCKEVERYTHING, corona, results, 0, CheckForViewpointActor, &Viewpoint)) { - corona->CoronaFade = std::min(corona->CoronaFade + timeElapsed * fadeSpeed, 1.0f); + coronaFade = std::min(coronaFade + timeElapsed * fadeSpeed, 1.0); } else { - corona->CoronaFade = std::max(corona->CoronaFade - timeElapsed * fadeSpeed, 0.0f); + coronaFade = std::max(coronaFade - timeElapsed * fadeSpeed, 0.0); } - if (corona->CoronaFade > 0.0f) - DrawCorona(state, corona, dist); + if (coronaFade > 0.0f) + DrawCorona(state, corona, (float)coronaFade, dist); } state.SetTextureMode(TM_NORMAL); @@ -838,8 +998,14 @@ void HWDrawInfo::DrawScene(int drawmode, FRenderState& state) CreateScene(false, state); } + if (!outer) // Fogballs have no portal support. Always use the outermost scene's fogballs for now + { + int fogballIndex = state.UploadFogballs(Fogballs); + state.SetFogballIndex(fogballIndex); + } + state.SetDepthMask(true); - if (!gl_no_skyclear) portalState.RenderFirstSkyPortal(recursion, this, state); + if (!gl_no_skyclear && !gl_levelmesh) drawctx->portalState.RenderFirstSkyPortal(recursion, this, state); RenderScene(state); @@ -852,11 +1018,16 @@ void HWDrawInfo::DrawScene(int drawmode, FRenderState& state) // Handle all portals after rendering the opaque objects but before // doing all translucent stuff recursion++; - portalState.EndFrame(this, state); + drawctx->portalState.EndFrame(this, state); recursion--; + RenderTranslucent(state); -} + if (!outer) + { + state.SetFogballIndex(-1); + } +} //----------------------------------------------------------------------------- // @@ -866,7 +1037,7 @@ void HWDrawInfo::DrawScene(int drawmode, FRenderState& state) void HWDrawInfo::ProcessScene(bool toscreen, FRenderState& state) { - portalState.BeginScene(); + drawctx->portalState.BeginScene(); int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection; CurrentMapSections.Set(mapsection); @@ -885,7 +1056,7 @@ void HWDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub) auto portal = FindPortal(ptg); if (!portal) { - portal = new HWSectorStackPortal(&portalState, ptg); + portal = new HWSectorStackPortal(&drawctx->portalState, ptg); Portals.Push(portal); } auto ptl = static_cast(portal); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 268231e76e..e67bb77a68 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -9,6 +9,11 @@ #include "v_video.h" #include "hw_weapon.h" #include "hw_drawlist.h" +#include "hw_renderstate.h" +#include "g_levellocals.h" + +EXTERN_CVAR(Bool, lm_always_update); +EXTERN_CVAR(Int, lm_max_updates); enum EDrawMode { @@ -34,12 +39,9 @@ class Clipper; class HWPortal; class HWScenePortalBase; class FRenderState; +class HWDrawContext; -//========================================================================== -// // these are used to link faked planes due to missing textures to a sector -// -//========================================================================== struct gl_subsectorrendernode { gl_subsectorrendernode * next; @@ -132,6 +134,8 @@ struct HWDrawInfo bool isNightvision() const { return !!(FullbrightFlags & Nightvision); } bool isStealthVision() const { return !!(FullbrightFlags & StealthVision); } + HWDrawContext* drawctx = nullptr; + HWDrawList drawlists[GLDL_TYPES]; int vpIndex; ELightMode lightmode; @@ -142,14 +146,15 @@ struct HWDrawInfo std::atomic spriteindex; HWPortal *mClipPortal; HWPortal *mCurrentPortal; - //FRotator mAngles; Clipper *mClipper; FRenderViewpoint Viewpoint; HWViewpointUniforms VPUniforms; // per-viewpoint uniform state TArray Portals; TArray Decals[2]; // the second slot is for mirrors which get rendered in a separate pass. TArray hudsprites; // These may just be stored by value. - TArray Coronas; + TArray Coronas; + TArray Fogballs; + TArray VisibleTiles; uint64_t LastFrameTime = 0; TArray MissingUpperTextures; @@ -165,9 +170,6 @@ struct HWDrawInfo TMap floodFloorSegs; TMap floodCeilingSegs; - //TArray CeilingStacks; - //TArray FloorStacks; - TArray HandledSubsectors; TArray section_renderflags; @@ -180,45 +182,29 @@ struct HWDrawInfo fixed_t viewx, viewy; // since the nodes are still fixed point, keeping the view position also fixed point for node traversal is faster. bool multithread; - bool MeshBuilding = false; + TArray QueryResultsBuffer; -private: - // For ProcessLowerMiniseg - bool inview; - subsector_t * viewsubsector; - TArray lowersegs; - - subsector_t *currentsubsector; // used by the line processing code. - sector_t *currentsector; + HWDrawInfo(HWDrawContext* drawctx) : drawctx(drawctx) { for (HWDrawList& list : drawlists) list.drawctx = drawctx; } void WorkerThread(); void UnclipSubsector(subsector_t *sub); - void AddLine(seg_t *seg, bool portalclip, FRenderState& state); - void PolySubsector(subsector_t * sub, FRenderState& state); - void RenderPolyBSPNode(void *node, FRenderState& state); - void AddPolyobjs(subsector_t *sub, FRenderState& state); - void AddLines(subsector_t * sub, sector_t * sector, FRenderState& state); - void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, linebase_t *line, FRenderState& state); + void AddLine(seg_t *seg, bool portalclip); + void PolySubsector(subsector_t * sub); + void RenderPolyBSPNode(void *node); + void AddPolyobjs(subsector_t *sub); + void AddLines(subsector_t * sub, sector_t * sector); + void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, linebase_t *line); public: - void RenderThings(subsector_t * sub, sector_t * sector, FRenderState& state); - void RenderParticles(subsector_t *sub, sector_t *front, FRenderState& state); - void DoSubsector(subsector_t * sub, FRenderState& state); - int SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &lightdata, const secplane_t *plane, FRenderState& state); - int CreateOtherPlaneVertices(subsector_t *sub, const secplane_t *plane, FRenderState& state); - void DrawPSprite(HUDSprite *huds, FRenderState &state); - void SetColor(FRenderState &state, int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon = false); - void SetFog(FRenderState &state, int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive); - void SetShaderLight(FRenderState &state, float level, float olight); - int CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor); - PalEntry CalcLightColor(int light, PalEntry pe, int blendfactor); - float GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor); - bool CheckFog(sector_t *frontsector, sector_t *backsector); - WeaponLighting GetWeaponLighting(sector_t *viewsector, const DVector3 &pos, int cm, area_t in_area, const DVector3 &playerpos); - - void PreparePlayerSprites2D(sector_t * viewsector, area_t in_area, FRenderState& state); - void PreparePlayerSprites3D(sector_t * viewsector, area_t in_area, FRenderState& state); + void RenderThings(subsector_t * sub, sector_t * sector); + void RenderParticles(subsector_t *sub, sector_t *front); + void DoSubsector(subsector_t * sub); + void DrawPSprite(HUDSprite* huds, FRenderState& state); + WeaponLighting GetWeaponLighting(sector_t* viewsector, const DVector3& pos, int cm, area_t in_area, const DVector3& playerpos); + + void PreparePlayerSprites2D(sector_t* viewsector, area_t in_area, FRenderState& state); + void PreparePlayerSprites3D(sector_t* viewsector, area_t in_area, FRenderState& state); public: void SetCameraPos(const DVector3 &pos) @@ -239,11 +225,38 @@ struct HWDrawInfo VPUniforms.mClipHeight = 0; } + void PushVisibleSurface(LevelMeshSurface* surface) + { + if (outer) + { + outer->PushVisibleSurface(surface); + return; + } + + if (surface->LightmapTileIndex < 0) + return; + + LightmapTile* tile = &Level->levelMesh->LightmapTiles[surface->LightmapTileIndex]; + if (lm_always_update || surface->AlwaysUpdate) + { + tile->NeedsUpdate = true; + } + else if (VisibleTiles.Size() >= unsigned(lm_max_updates)) + { + return; + } + + if (tile->NeedsUpdate) + { + VisibleTiles.Push(tile); + } + } + HWPortal * FindPortal(const void * src); void RenderBSPNode(void *node, FRenderState& state); void RenderBSP(void *node, bool drawpsprites, FRenderState& state); - static HWDrawInfo *StartDrawInfo(FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); + static HWDrawInfo *StartDrawInfo(HWDrawContext* drawctx, FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); void StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); void ClearBuffers(); HWDrawInfo *EndDrawInfo(); @@ -252,6 +265,7 @@ struct HWDrawInfo void DrawScene(int drawmode, FRenderState& state); void CreateScene(bool drawpsprites, FRenderState& state); + void PutWallPortal(HWWall wall, FRenderState& state); void RenderScene(FRenderState &state); void RenderTranslucent(FRenderState &state); void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil); @@ -269,8 +283,6 @@ struct HWDrawInfo bool CollectSubsectorsFloor(subsector_t * sub, sector_t * anchor); bool CheckAnchorCeiling(subsector_t * sub); bool CollectSubsectorsCeiling(subsector_t * sub, sector_t * anchor); - void CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor, area_t in_area); - void CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor, area_t in_area); void DispatchRenderHacks(FRenderState& state); void AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight); @@ -284,9 +296,6 @@ struct HWDrawInfo void AddHackedSubsector(subsector_t * sub); void HandleHackedSubsectors(FRenderState& state); - void AddFloorStack(sector_t * sec); - void AddCeilingStack(sector_t * sec); - void ProcessSectorStacks(area_t in_area); void ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area, FRenderState& state); @@ -307,7 +316,7 @@ struct HWDrawInfo void DrawDecals(FRenderState &state, TArray &decals); void DrawPlayerSprites(bool hudModelStep, FRenderState &state); void DrawCoronas(FRenderState& state); - void DrawCorona(FRenderState& state, ACorona* corona, double dist); + void DrawCorona(FRenderState& state, AActor* corona, float coronaFade, double dist); void ProcessLowerMinisegs(TArray &lowersegs, FRenderState& state); void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub); @@ -317,34 +326,36 @@ struct HWDrawInfo void AddFlat(HWFlat *flat, bool fog); void AddSprite(HWSprite *sprite, bool translucent); + void RenderThings(subsector_t* sub, sector_t* sector, FRenderState& state); + void RenderParticles(subsector_t* sub, sector_t* front, FRenderState& state); + void DoSubsector(subsector_t* sub, FRenderState& state); + int SetupLightsForOtherPlane(subsector_t* sub, FDynLightData& lightdata, const secplane_t* plane, FRenderState& state); + int CreateOtherPlaneVertices(subsector_t* sub, const secplane_t* plane, FRenderState& state); HWDecal *AddDecal(bool onmirror); - bool isSoftwareLighting() const - { - return lightmode == ELightMode::ZDoomSoftware || lightmode == ELightMode::DoomSoftware || lightmode == ELightMode::Build; - } - - bool isBuildSoftwareLighting() const - { - return lightmode == ELightMode::Build; - } - - bool isDoomSoftwareLighting() const - { - return lightmode == ELightMode::ZDoomSoftware || lightmode == ELightMode::DoomSoftware; - } - - bool isDarkLightMode() const - { - return lightmode == ELightMode::Doom || lightmode == ELightMode::DoomDark; - } - void SetFallbackLightMode() { lightmode = ELightMode::Doom; } +private: + // For ProcessLowerMiniseg + bool inview; + subsector_t* viewsubsector; + TArray lowersegs; + + subsector_t* currentsubsector; // used by the line processing code. + sector_t* currentsector; + + void AddLine(seg_t* seg, bool portalclip, FRenderState& state); + void PolySubsector(subsector_t* sub, FRenderState& state); + void RenderPolyBSPNode(void* node, FRenderState& state); + void AddPolyobjs(subsector_t* sub, FRenderState& state); + void AddLines(subsector_t* sub, sector_t* sector, FRenderState& state); + void AddSpecialPortalLines(subsector_t* sub, sector_t* sector, linebase_t* line, FRenderState& state); + + void UpdateLightmaps(); }; void CleanSWDrawer(); @@ -353,3 +364,30 @@ void WriteSavePic(player_t* player, FileWriter* file, int width, int height); sector_t* RenderView(player_t* player); +inline bool isSoftwareLighting(ELightMode lightmode) +{ + return lightmode == ELightMode::ZDoomSoftware || lightmode == ELightMode::DoomSoftware || lightmode == ELightMode::Build; +} + +inline bool isBuildSoftwareLighting(ELightMode lightmode) +{ + return lightmode == ELightMode::Build; +} + +inline bool isDoomSoftwareLighting(ELightMode lightmode) +{ + return lightmode == ELightMode::ZDoomSoftware || lightmode == ELightMode::DoomSoftware; +} + +inline bool isDarkLightMode(ELightMode lightmode) +{ + return lightmode == ELightMode::Doom || lightmode == ELightMode::DoomDark; +} + +int CalcLightLevel(ELightMode lightmode, int lightlevel, int rellight, bool weapon, int blendfactor); +PalEntry CalcLightColor(ELightMode lightmode, int light, PalEntry pe, int blendfactor); +float GetFogDensity(FLevelLocals* Level, ELightMode lightmode, int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor); +bool CheckFog(FLevelLocals* Level, sector_t* frontsector, sector_t* backsector, ELightMode lightmode); +void SetColor(FRenderState& state, FLevelLocals* Level, ELightMode lightmode, int sectorlightlevel, int rellight, bool fullbright, const FColormap& cm, float alpha, bool weapon = false); +void SetShaderLight(FRenderState& state, FLevelLocals* Level, float level, float olight); +void SetFog(FRenderState& state, FLevelLocals* Level, ELightMode lightmode, int lightlevel, int rellight, bool fullbright, const FColormap* cmap, bool isadditive, bool inskybox); diff --git a/src/rendering/hwrenderer/scene/hw_drawlist.cpp b/src/rendering/hwrenderer/scene/hw_drawlist.cpp index 9d524034cf..f6dbb0bcf7 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlist.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawlist.cpp @@ -37,41 +37,9 @@ #include "hw_renderstate.h" #include "hw_drawinfo.h" #include "hw_fakeflat.h" - -FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time. - -void ResetRenderDataAllocator() -{ - RenderDataAllocator.FreeAll(); -} - -//========================================================================== -// -// -// -//========================================================================== -class StaticSortNodeArray : public TDeletingArray -{ - unsigned usecount; -public: - unsigned Size() { return usecount; } - void Clear() { usecount=0; } - void Release(int start) { usecount=start; } - SortNode * GetNew(); -}; - - -SortNode * StaticSortNodeArray::GetNew() -{ - if (usecount==TArray::Size()) - { - Push(new SortNode); - } - return operator[](usecount++); -} - - -static StaticSortNodeArray SortNodes; +#include "hw_drawcontext.h" +#include "hw_walldispatcher.h" +#include "hw_flatdispatcher.h" //========================================================================== // @@ -80,7 +48,7 @@ static StaticSortNodeArray SortNodes; //========================================================================== void HWDrawList::Reset() { - if (sorted) SortNodes.Release(SortNodeStart); + if (sorted) drawctx->SortNodes.Release(SortNodeStart); sorted=NULL; walls.Clear(); flats.Clear(); @@ -163,9 +131,9 @@ void HWDrawList::MakeSortList() SortNode * p, * n, * c; unsigned i; - SortNodeStart=SortNodes.Size(); + SortNodeStart=drawctx->SortNodes.Size(); p=NULL; - n=SortNodes.GetNew(); + n=drawctx->SortNodes.GetNew(); for(i=0;iitemindex=(int)i; @@ -174,7 +142,7 @@ void HWDrawList::MakeSortList() p=n; if (i!=drawitems.Size()-1) { - c=SortNodes.GetNew(); + c=drawctx->SortNodes.GetNew(); n->next=c; n=c; } @@ -268,7 +236,7 @@ void HWDrawList::SortPlaneIntoPlane(SortNode * head,SortNode * sort) // // //========================================================================== -void HWDrawList::SortWallIntoPlane(HWDrawInfo* di, FRenderState& state, SortNode * head, SortNode * sort) +void HWDrawList::SortWallIntoPlane(HWDrawInfo* di, SortNode * head, SortNode * sort) { HWFlat * fh = flats[drawitems[head->itemindex].index]; HWWall * ws = walls[drawitems[sort->itemindex].index]; @@ -282,33 +250,7 @@ void HWDrawList::SortWallIntoPlane(HWDrawInfo* di, FRenderState& state, SortNode HWWall *w = NewWall(); *w = *ws; - // Splitting is done in the shader with clip planes, if available - if (screen->hwcaps & RFL_NO_CLIP_PLANES) - { - ws->vertcount = 0; // invalidate current vertices. - float newtexv = ws->tcs[HWWall::UPLFT].v + ((ws->tcs[HWWall::LOLFT].v - ws->tcs[HWWall::UPLFT].v) / (ws->zbottom[0] - ws->ztop[0])) * (fh->z - ws->ztop[0]); - float newlmv = ws->lightuv[HWWall::UPLFT].v + ((ws->lightuv[HWWall::LOLFT].v - ws->lightuv[HWWall::UPLFT].v) / (ws->zbottom[0] - ws->ztop[0])) * (fh->z - ws->ztop[0]); - - // I make the very big assumption here that translucent walls in sloped sectors - // and 3D-floors never coexist in the same level - If that were the case this - // code would become extremely more complicated. - if (!ceiling) - { - ws->ztop[1] = w->zbottom[1] = ws->ztop[0] = w->zbottom[0] = fh->z; - ws->tcs[HWWall::UPRGT].v = w->tcs[HWWall::LORGT].v = ws->tcs[HWWall::UPLFT].v = w->tcs[HWWall::LOLFT].v = newtexv; - ws->lightuv[HWWall::UPRGT].v = w->lightuv[HWWall::LORGT].v = ws->lightuv[HWWall::UPLFT].v = w->lightuv[HWWall::LOLFT].v = newlmv; - } - else - { - w->ztop[1] = ws->zbottom[1] = w->ztop[0] = ws->zbottom[0] = fh->z; - w->tcs[HWWall::UPLFT].v = ws->tcs[HWWall::LOLFT].v = w->tcs[HWWall::UPRGT].v = ws->tcs[HWWall::LORGT].v = newtexv; - w->lightuv[HWWall::UPLFT].v = ws->lightuv[HWWall::LOLFT].v = w->lightuv[HWWall::UPRGT].v = ws->lightuv[HWWall::LORGT].v = newlmv; - } - w->MakeVertices(di, state, false); - ws->MakeVertices(di, state, false); - } - - SortNode * sort2 = SortNodes.GetNew(); + SortNode * sort2 = drawctx->SortNodes.GetNew(); memset(sort2, 0, sizeof(SortNode)); sort2->itemindex = drawitems.Size() - 1; @@ -347,25 +289,7 @@ void HWDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort) HWSprite *s = NewSprite(); *s = *ss; - // Splitting is done in the shader with clip planes, if available. - // The fallback here only really works for non-y-billboarded sprites. - if (screen->hwcaps & RFL_NO_CLIP_PLANES) - { - float newtexv = ss->vt + ((ss->vb - ss->vt) / (ss->z2 - ss->z1))*(fh->z - ss->z1); - - if (!ceiling) - { - ss->z1 = s->z2 = fh->z; - ss->vt = s->vb = newtexv; - } - else - { - s->z1 = ss->z2 = fh->z; - s->vt = ss->vb = newtexv; - } - } - - SortNode * sort2 = SortNodes.GetNew(); + SortNode * sort2 = drawctx->SortNodes.GetNew(); memset(sort2, 0, sizeof(SortNode)); sort2->itemindex = drawitems.Size() - 1; @@ -451,10 +375,10 @@ void HWDrawList::SortWallIntoWall(HWDrawInfo *di, FRenderState& state, SortNode w->zbottom[0]=ws->zbottom[1]=izb; w->tcs[HWWall::LOLFT].u = w->tcs[HWWall::UPLFT].u = ws->tcs[HWWall::LORGT].u = ws->tcs[HWWall::UPRGT].u = iu; w->lightuv[HWWall::LOLFT].u = w->lightuv[HWWall::UPLFT].u = ws->lightuv[HWWall::LORGT].u = ws->lightuv[HWWall::UPRGT].u = iu; - ws->MakeVertices(di, state, false); - w->MakeVertices(di, state, false); + ws->MakeVertices(state, false); + w->MakeVertices(state, false); - SortNode * sort2=SortNodes.GetNew(); + SortNode * sort2=drawctx->SortNodes.GetNew(); memset(sort2,0,sizeof(SortNode)); sort2->itemindex=drawitems.Size()-1; @@ -479,6 +403,7 @@ void HWDrawList::SortWallIntoWall(HWDrawInfo *di, FRenderState& state, SortNode //========================================================================== EXTERN_CVAR(Int, gl_billboard_mode) EXTERN_CVAR(Bool, gl_billboard_faces_camera) +EXTERN_CVAR(Bool, hw_force_cambbpref) EXTERN_CVAR(Bool, gl_billboard_particles) inline double CalcIntersectionVertex(HWSprite *s, HWWall * w2) @@ -490,7 +415,7 @@ inline double CalcIntersectionVertex(HWSprite *s, HWWall * w2) return ((ay - cy)*(dx - cx) - (ax - cx)*(dy - cy)) / ((bx - ax)*(dy - cy) - (by - ay)*(dx - cx)); } -void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, FRenderState& state, SortNode * head,SortNode * sort) +void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sort) { HWWall *wh= walls[drawitems[head->itemindex].index]; HWSprite * ss= sprites[drawitems[sort->itemindex].index]; @@ -522,7 +447,10 @@ void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, FRenderState& state, SortNod const bool drawWithXYBillboard = ((ss->particle && gl_billboard_particles) || (!(ss->actor && ss->actor->renderflags & RF_FORCEYBILLBOARD) && (gl_billboard_mode == 1 || (ss->actor && ss->actor->renderflags & RF_FORCEXYBILLBOARD)))); - const bool drawBillboardFacingCamera = gl_billboard_faces_camera; + const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera : + (gl_billboard_faces_camera && (ss->actor && !(ss->actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA))) + || (ss->actor && ss->actor->renderflags2 & RF2_BILLBOARDFACECAMERA); + // [Nash] has +ROLLSPRITE const bool rotated = (ss->actor != nullptr && ss->actor->renderflags & (RF_ROLLSPRITE | RF_WALLSPRITE | RF_FLATSPRITE)); @@ -553,7 +481,7 @@ void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, FRenderState& state, SortNod s->y1=ss->y2=iy; s->ul=ss->ur=iu; - SortNode * sort2=SortNodes.GetNew(); + SortNode * sort2=drawctx->SortNodes.GetNew(); memset(sort2,0,sizeof(SortNode)); sort2->itemindex=drawitems.Size()-1; @@ -567,16 +495,8 @@ void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, FRenderState& state, SortNod head->AddToLeft(sort); head->AddToRight(sort2); } - if (screen->BuffersArePersistent()) - { - s->vertexindex = ss->vertexindex = -1; - } - else - { - s->CreateVertices(di, state); - ss->CreateVertices(di, state); - } + s->vertexindex = ss->vertexindex = -1; } } @@ -654,7 +574,7 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, FRenderState& state, SortNode * he break; case DrawType_WALL: - SortWallIntoPlane(di,state,head,node); + SortWallIntoPlane(di,head,node); break; case DrawType_SPRITE: @@ -683,7 +603,7 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, FRenderState& state, SortNode * he break; case DrawType_SPRITE: - SortSpriteIntoWall(di, state, head, node); + SortSpriteIntoWall(di, head, node); break; case DrawType_FLAT: break; @@ -711,7 +631,7 @@ void HWDrawList::Sort(HWDrawInfo *di, FRenderState& state) reverseSort = !!(di->Level->i_compatflags & COMPATF_SPRITESORT); SortZ = di->Viewpoint.Pos.Z; MakeSortList(); - sorted = DoSort(di, state, SortNodes[SortNodeStart]); + sorted = DoSort(di, state, drawctx->SortNodes[SortNodeStart]); } //========================================================================== @@ -758,7 +678,7 @@ void HWDrawList::SortFlats() HWWall *HWDrawList::NewWall() { - auto wall = (HWWall*)RenderDataAllocator.Alloc(sizeof(HWWall)); + auto wall = (HWWall*)drawctx->RenderDataAllocator.Alloc(sizeof(HWWall)); drawitems.Push(HWDrawItem(DrawType_WALL, walls.Push(wall))); return wall; } @@ -770,7 +690,7 @@ HWWall *HWDrawList::NewWall() //========================================================================== HWFlat *HWDrawList::NewFlat() { - auto flat = (HWFlat*)RenderDataAllocator.Alloc(sizeof(HWFlat)); + auto flat = (HWFlat*)drawctx->RenderDataAllocator.Alloc(sizeof(HWFlat)); drawitems.Push(HWDrawItem(DrawType_FLAT,flats.Push(flat))); return flat; } @@ -782,7 +702,7 @@ HWFlat *HWDrawList::NewFlat() //========================================================================== HWSprite *HWDrawList::NewSprite() { - auto sprite = (HWSprite*)RenderDataAllocator.Alloc(sizeof(HWSprite)); + auto sprite = (HWSprite*)drawctx->RenderDataAllocator.Alloc(sizeof(HWSprite)); drawitems.Push(HWDrawItem(DrawType_SPRITE, sprites.Push(sprite))); return sprite; } @@ -799,8 +719,9 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i case DrawType_FLAT: { HWFlat * f= flats[drawitems[i].index]; + HWFlatDispatcher dis(di); RenderFlat.Clock(); - f->DrawFlat(di, state, translucent); + f->DrawFlat(&dis, state, translucent); RenderFlat.Unclock(); } break; @@ -808,8 +729,9 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i case DrawType_WALL: { HWWall * w= walls[drawitems[i].index]; + HWWallDispatcher dis(di); RenderWall.Clock(); - w->DrawWall(di, state, translucent); + w->DrawWall(&dis, state, translucent); RenderWall.Unclock(); } break; @@ -845,10 +767,11 @@ void HWDrawList::Draw(HWDrawInfo *di, FRenderState &state, bool translucent) //========================================================================== void HWDrawList::DrawWalls(HWDrawInfo *di, FRenderState &state, bool translucent) { + HWWallDispatcher dis(di); RenderWall.Clock(); for (auto &item : drawitems) { - walls[item.index]->DrawWall(di, state, translucent); + walls[item.index]->DrawWall(&dis, state, translucent); } RenderWall.Unclock(); } @@ -860,10 +783,11 @@ void HWDrawList::DrawWalls(HWDrawInfo *di, FRenderState &state, bool translucent //========================================================================== void HWDrawList::DrawFlats(HWDrawInfo *di, FRenderState &state, bool translucent) { + HWFlatDispatcher dis(di); RenderFlat.Clock(); for (unsigned i = 0; iDrawFlat(di, state, translucent); + flats[drawitems[i].index]->DrawFlat(&dis, state, translucent); } RenderFlat.Unclock(); } diff --git a/src/rendering/hwrenderer/scene/hw_drawlist.h b/src/rendering/hwrenderer/scene/hw_drawlist.h index 39a46910ff..fed3fab5ad 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlist.h +++ b/src/rendering/hwrenderer/scene/hw_drawlist.h @@ -2,12 +2,11 @@ #include "memarena.h" -extern FMemArena RenderDataAllocator; -void ResetRenderDataAllocator(); struct HWDrawInfo; class HWWall; class HWFlat; class HWSprite; +class HWDrawContext; class FRenderState; //========================================================================== @@ -60,22 +59,21 @@ struct SortNode struct HWDrawList { - //private: + HWDrawContext* drawctx = nullptr; TArray walls; TArray flats; TArray sprites; TArray drawitems; - int SortNodeStart; - float SortZ; - SortNode * sorted; - bool reverseSort; + int SortNodeStart = 0; + float SortZ = 0.0f; + SortNode* sorted = nullptr; + bool reverseSort = false; -public: HWDrawList() { - next=NULL; + next=nullptr; SortNodeStart=-1; - sorted=NULL; + sorted=nullptr; } ~HWDrawList() @@ -100,10 +98,10 @@ struct HWDrawList SortNode * FindSortPlane(SortNode * head); SortNode * FindSortWall(SortNode * head); void SortPlaneIntoPlane(SortNode * head,SortNode * sort); - void SortWallIntoPlane(HWDrawInfo* di, FRenderState& state, SortNode * head,SortNode * sort); + void SortWallIntoPlane(HWDrawInfo* di, SortNode * head,SortNode * sort); void SortSpriteIntoPlane(SortNode * head,SortNode * sort); void SortWallIntoWall(HWDrawInfo *di, FRenderState& state, SortNode * head,SortNode * sort); - void SortSpriteIntoWall(HWDrawInfo *di, FRenderState& state, SortNode * head,SortNode * sort); + void SortSpriteIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sort); int CompareSprites(SortNode * a,SortNode * b); SortNode * SortSpriteList(SortNode * head); SortNode * DoSort(HWDrawInfo *di, FRenderState& state, SortNode * head); @@ -117,7 +115,7 @@ struct HWDrawList void DrawSorted(HWDrawInfo *di, FRenderState &state, SortNode * head); void DrawSorted(HWDrawInfo *di, FRenderState &state); - HWDrawList * next; + HWDrawList *next = nullptr; } ; diff --git a/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp b/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp index cf59688c90..a44bc4e356 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp @@ -80,7 +80,7 @@ void HWDrawInfo::AddMirrorSurface(HWWall *w, FRenderState& state) auto tcs = newwall->tcs; tcs[HWWall::LOLFT].u = tcs[HWWall::LORGT].u = tcs[HWWall::UPLFT].u = tcs[HWWall::UPRGT].u = v.X; tcs[HWWall::LOLFT].v = tcs[HWWall::LORGT].v = tcs[HWWall::UPLFT].v = tcs[HWWall::UPRGT].v = v.Z; - newwall->MakeVertices(this, state, false); + newwall->MakeVertices(state, false); bool hasDecals = newwall->seg->sidedef && newwall->seg->sidedef->AttachedDecals; if (hasDecals && Level->HasDynamicLights && !isFullbrightScene()) diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index 4925daeb10..00706f81e4 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -13,6 +13,8 @@ #pragma warning(disable:4244) #endif +bool CheckFog(FLevelLocals* Level, sector_t* frontsector, sector_t* backsector, ELightMode lightmode); + struct HWHorizonInfo; struct HWSkyInfo; struct F3DFloor; @@ -29,6 +31,9 @@ class FRenderState; struct HWDecal; struct FSection; enum area_t : int; +class HWDrawContext; +struct DoomLevelMeshSurface; +struct HWFlatDispatcher; enum HWRenderStyle { @@ -63,6 +68,16 @@ enum PortalTypes PORTALTYPE_LINETOLINE, }; +enum DoomLevelMeshSurfaceType +{ + ST_NONE, + ST_MIDDLESIDE, + ST_UPPERSIDE, + ST_LOWERSIDE, + ST_CEILING, + ST_FLOOR +}; + //========================================================================== // // One sector plane, still in fixed point @@ -78,7 +93,7 @@ struct HWSectorPlane FVector2 Offs; FVector2 Scale; - void GetFromSector(sector_t * sec, int ceiling) + void GetFromSector(const sector_t * sec, int ceiling) { Offs.X = (float)sec->GetXOffset(ceiling); Offs.Y = (float)sec->GetYOffset(ceiling); @@ -113,6 +128,11 @@ struct texcoord }; struct HWDrawInfo; +class HWWall; + +// this only exists to keep HWWallDispatcher trivial + +struct HWWallDispatcher; class HWWall { @@ -121,13 +141,13 @@ class HWWall enum { - HWF_CLAMPX=1, - HWF_CLAMPY=2, - HWF_SKYHACK=4, - HWF_GLOW=8, // illuminated by glowing flats - HWF_NOSPLITUPPER=16, - HWF_NOSPLITLOWER=32, - HWF_NOSPLIT=64, + HWF_CLAMPX = 1, + HWF_CLAMPY = 2, + HWF_SKYHACK = 4, + HWF_GLOW = 8, // illuminated by glowing flats + HWF_NOSPLITUPPER = 16, + HWF_NOSPLITLOWER = 32, + HWF_NOSPLIT = 64, HWF_TRANSLUCENT = 128, HWF_NOSLICE = 256 }; @@ -151,13 +171,13 @@ class HWWall friend struct HWDrawList; friend class HWPortal; - vertex_t * vertexes[2]; // required for polygon splitting - FGameTexture *texture; - TArray *lightlist; - LightmapSurface *lightmap; + vertex_t* vertexes[2]; // required for polygon splitting + FGameTexture* texture; + TArray* lightlist; + DoomLevelMeshSurface* surface; HWSeg glseg; - float ztop[2],zbottom[2]; + float ztop[2], zbottom[2]; texcoord tcs[4]; texcoord lightuv[4]; float lindex; @@ -165,7 +185,7 @@ class HWWall FColormap Colormap; ERenderStyle RenderStyle; - + float ViewDistance; short lightlevel; @@ -181,15 +201,24 @@ class HWWall union { // it's either one of them but never more! - FSectorPortal *secportal; // sector portal (formerly skybox) - HWSkyInfo * sky; // for normal sky - HWHorizonInfo * horizon; // for horizon information - FSectorPortalGroup * portal; // stacked sector portals - secplane_t * planemirror; // for plane mirrors - FLinePortalSpan *lineportal; // line-to-line portals + FSectorPortal* secportal; // sector portal (formerly skybox) + HWSkyInfo* sky; // for normal sky + HWHorizonInfo* horizon; // for horizon information + FSectorPortalGroup* portal; // stacked sector portals + secplane_t* planemirror; // for plane mirrors + FLinePortalSpan* lineportal; // line-to-line portals + struct + { + int portaltype; // for the mesh builder. Real portals can only be assigned when being rendered. + int portalplane; + }; }; - + struct + { + DoomLevelMeshSurfaceType Type; + sector_t* ControlSector; + } LevelMeshInfo; // these are not the same as ytop and ybottom!!! float zceil[2]; @@ -199,92 +228,91 @@ class HWWall unsigned int vertcount; public: - seg_t * seg; // this gives the easiest access to all other structs involved - subsector_t * sub; // For polyobjects - sector_t *frontsector, *backsector; -//private: - - void PutWall(HWDrawInfo *di, FRenderState& state, bool translucent); - void PutPortal(HWDrawInfo *di, FRenderState& state, int ptype, int plane); - void CheckTexturePosition(FTexCoordInfo *tci); - - void Put3DWall(HWDrawInfo *di, FRenderState& state, lightlist_t * lightlist, bool translucent); - bool SplitWallComplex(HWDrawInfo *di, FRenderState& state, sector_t * frontsector, bool translucent, float& maplightbottomleft, float& maplightbottomright); - void SplitWall(HWDrawInfo *di, FRenderState& state, sector_t * frontsector, bool translucent); - - void SetupLights(HWDrawInfo *di, FRenderState& state, FDynLightData &lightdata); - - void MakeVertices(HWDrawInfo *di, FRenderState& state, bool nosplit); - - void SkyPlane(HWDrawInfo *di, FRenderState& state, sector_t *sector, int plane, bool allowmirror); - void SkyLine(HWDrawInfo *di, FRenderState& state, sector_t *sec, line_t *line); - void SkyNormal(HWDrawInfo *di, FRenderState& state, sector_t * fs,vertex_t * v1,vertex_t * v2); - void SkyTop(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); - void SkyBottom(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); - - bool DoHorizon(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2); - - bool SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float ceilingrefheight, - float topleft, float topright, float bottomleft, float bottomright, float t_ofs); - - void DoTexture(HWDrawInfo *di, FRenderState& state, int type,seg_t * seg,int peg, - float ceilingrefheight, float floorrefheight, - float CeilingHeightstart,float CeilingHeightend, - float FloorHeightstart,float FloorHeightend, - float v_offset); - - void DoMidTexture(HWDrawInfo *di, FRenderState& state, seg_t * seg, bool drawfogboundary, - sector_t * front, sector_t * back, - sector_t * realfront, sector_t * realback, - float fch1, float fch2, float ffh1, float ffh2, - float bch1, float bch2, float bfh1, float bfh2, float zalign); - - void GetPlanePos(F3DFloor::planeref * planeref, float & left, float & right); - - void BuildFFBlock(HWDrawInfo *di, FRenderState& state, seg_t * seg, F3DFloor * rover, int roverIndex, - float ff_topleft, float ff_topright, - float ff_bottomleft, float ff_bottomright); - void InverseFloors(HWDrawInfo *di, FRenderState& state, seg_t * seg, sector_t * frontsector, - float topleft, float topright, - float bottomleft, float bottomright); - void ClipFFloors(HWDrawInfo *di, FRenderState& state, seg_t * seg, F3DFloor * ffloor, int ffloorIndex, sector_t * frontsector, - float topleft, float topright, - float bottomleft, float bottomright); - void DoFFloorBlocks(HWDrawInfo *di, FRenderState& state, seg_t * seg, sector_t * frontsector, sector_t * backsector, - float fch1, float fch2, float ffh1, float ffh2, - float bch1, float bch2, float bfh1, float bfh2); - - void ProcessDecal(HWDrawInfo *di, FRenderState& state, DBaseDecal *decal, const FVector3 &normal); - void ProcessDecals(HWDrawInfo *di, FRenderState& state); - - int CreateVertices(FFlatVertex *&ptr, bool nosplit); - void SplitLeftEdge (FFlatVertex *&ptr); - void SplitRightEdge(FFlatVertex *&ptr); - void SplitUpperEdge(FFlatVertex *&ptr); - void SplitLowerEdge(FFlatVertex *&ptr); - - void CountLeftEdge (unsigned &ptr); - void CountRightEdge(unsigned &ptr); + seg_t* seg; // this gives the easiest access to all other structs involved + subsector_t* sub; // For polyobjects + sector_t* frontsector, * backsector; + //private: + + void PutWall(HWWallDispatcher* di, FRenderState& state, bool translucent); + void PutPortal(HWWallDispatcher* di, FRenderState& state, int ptype, int plane); + void CheckTexturePosition(FTexCoordInfo* tci); + + void Put3DWall(HWWallDispatcher* di, FRenderState& state, lightlist_t* lightlist, bool translucent); + void SplitWall(HWWallDispatcher* di, FRenderState& state, sector_t* frontsector, bool translucent); + + void SetupLights(HWDrawInfo* di, FRenderState& state, FDynLightData& lightdata); + + void MakeVertices(FRenderState& state, bool nosplit); + + void SkyPlane(HWWallDispatcher* di, FRenderState& state, sector_t* sector, int plane, bool allowmirror); + void SkyLine(HWWallDispatcher* di, FRenderState& state, sector_t* sec, line_t* line); + void SkyNormal(HWWallDispatcher* di, FRenderState& state, sector_t* fs, vertex_t* v1, vertex_t* v2); + void SkyTop(HWWallDispatcher* di, FRenderState& state, seg_t* seg, sector_t* fs, sector_t* bs, vertex_t* v1, vertex_t* v2); + void SkyBottom(HWWallDispatcher* di, FRenderState& state, seg_t* seg, sector_t* fs, sector_t* bs, vertex_t* v1, vertex_t* v2); + + bool DoHorizon(HWWallDispatcher* di, FRenderState& state, seg_t* seg, sector_t* fs, vertex_t* v1, vertex_t* v2); + + bool SetWallCoordinates(seg_t* seg, FTexCoordInfo* tci, float ceilingrefheight, + float topleft, float topright, float bottomleft, float bottomright, float t_ofs, float skew); + + void DoTexture(HWWallDispatcher* di, FRenderState& state, int type, seg_t* seg, int peg, + float ceilingrefheight, float floorrefheight, + float CeilingHeightstart, float CeilingHeightend, + float FloorHeightstart, float FloorHeightend, + float v_offset, float skew); + + void DoMidTexture(HWWallDispatcher* di, FRenderState& state, seg_t* seg, bool drawfogboundary, + sector_t* front, sector_t* back, + sector_t* realfront, sector_t* realback, + float fch1, float fch2, float ffh1, float ffh2, + float bch1, float bch2, float bfh1, float bfh2, float zalign, float skew); + + void GetPlanePos(F3DFloor::planeref* planeref, float& left, float& right); + + void BuildFFBlock(HWWallDispatcher* di, FRenderState& state, seg_t* seg, F3DFloor* rover, int roverIndex, + float ff_topleft, float ff_topright, + float ff_bottomleft, float ff_bottomright); + void InverseFloors(HWWallDispatcher* di, FRenderState& state, seg_t* seg, sector_t* frontsector, + float topleft, float topright, + float bottomleft, float bottomright); + void ClipFFloors(HWWallDispatcher* di, FRenderState& state, seg_t* seg, F3DFloor* ffloor, int ffloorIndex, sector_t* frontsector, + float topleft, float topright, + float bottomleft, float bottomright); + void DoFFloorBlocks(HWWallDispatcher* di, FRenderState& state, seg_t* seg, sector_t* frontsector, sector_t* backsector, + float fch1, float fch2, float ffh1, float ffh2, + float bch1, float bch2, float bfh1, float bfh2); + + void ProcessDecal(HWDrawInfo* di, FRenderState& state, DBaseDecal* decal, const FVector3& normal); + void ProcessDecals(HWDrawInfo* di, FRenderState& state); + + int CreateVertices(FFlatVertex*& ptr, bool nosplit); + void SplitLeftEdge(FFlatVertex*& ptr); + void SplitRightEdge(FFlatVertex*& ptr); + void SplitUpperEdge(FFlatVertex*& ptr); + void SplitLowerEdge(FFlatVertex*& ptr); + + void CountLeftEdge(unsigned& ptr); + void CountRightEdge(unsigned& ptr); int CountVertices(); - void RenderWall(HWDrawInfo *di, FRenderState &state, int textured); - void RenderFogBoundary(HWDrawInfo *di, FRenderState &state); - void RenderMirrorSurface(HWDrawInfo *di, FRenderState &state); - void RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags); - void RenderTranslucentWall(HWDrawInfo *di, FRenderState &state); - void DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray &decals); + void RenderWall(FRenderState& state, int textured); + void RenderFogBoundary(HWWallDispatcher* di, FRenderState& state); + void RenderMirrorSurface(HWWallDispatcher* di, FRenderState& state); + void RenderTexturedWall(HWWallDispatcher* di, FRenderState& state, int rflags); + void RenderTranslucentWall(HWWallDispatcher* di, FRenderState& state); + void DrawDecalsForMirror(HWDrawInfo* di, FRenderState& state, TArray& decals); public: - void Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t *frontsector, sector_t *backsector); - void ProcessLowerMiniseg(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t *frontsector, sector_t *backsector); + void Process(HWWallDispatcher* di, FRenderState& state, seg_t* seg, sector_t* frontsector, sector_t* backsector); + void ProcessLowerMiniseg(HWWallDispatcher* di, FRenderState& state, seg_t* seg, sector_t* frontsector, sector_t* backsector); - float PointOnSide(float x,float y) + float PointOnSide(float x, float y) { - return -((y-glseg.y1)*(glseg.x2-glseg.x1)-(x-glseg.x1)*(glseg.y2-glseg.y1)); + return -((y - glseg.y1) * (glseg.x2 - glseg.x1) - (x - glseg.x1) * (glseg.y2 - glseg.y1)); } - void DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent); + void DrawWall(HWWallDispatcher* di, FRenderState& state, bool translucent); }; @@ -320,16 +348,18 @@ class HWFlat int dynlightindex; + F3DFloor* controlsector; + void CreateSkyboxVertices(FFlatVertex *buffer); - void SetupLights(HWDrawInfo *di, FRenderState& state, FLightNode *head, FDynLightData &lightdata, int portalgroup); + void SetupLights(HWFlatDispatcher *di, FRenderState& state, FLightNode *head, FDynLightData &lightdata, int portalgroup); - void PutFlat(HWDrawInfo *di, FRenderState& state, bool fog = false); - void Process(HWDrawInfo *di, FRenderState& state, sector_t * model, int whichplane, bool notexture); + void PutFlat(HWFlatDispatcher *di, bool fog = false); + void Process(HWFlatDispatcher *di, FRenderState& state, sector_t * model, int whichplane, bool notexture); void SetFrom3DFloor(F3DFloor *rover, bool top, bool underside); - void ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * frontsector, int which = 7 /*SSRF_RENDERALL*/); // cannot use constant due to circular dependencies. + void ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t * frontsector, int which = 7 /*SSRF_RENDERALL*/); // cannot use constant due to circular dependencies. - void DrawSubsectors(HWDrawInfo *di, FRenderState &state); - void DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent); + void DrawSubsectors(HWFlatDispatcher *di, FRenderState &state); + void DrawFlat(HWFlatDispatcher *di, FRenderState &state, bool translucent); void DrawOtherPlanes(HWDrawInfo *di, FRenderState &state); void DrawFloodPlanes(HWDrawInfo *di, FRenderState &state); @@ -353,10 +383,11 @@ class HWSprite PalEntry ThingColor; // thing's own color FColormap Colormap; FSpriteModelFrame * modelframe; + int modelframeflags; FRenderStyle RenderStyle; int OverrideShader; - int translation; + FTranslationID translation; int index; float depth; int vertexindex; @@ -370,6 +401,7 @@ class HWSprite float vt,vb; float x1,y1,z1; float x2,y2,z2; + float offx, offy; float trans; int dynlightindex; @@ -389,7 +421,8 @@ class HWSprite void CreateVertices(HWDrawInfo *di, FRenderState& state); void PutSprite(HWDrawInfo *di, FRenderState& state, bool translucent); void Process(HWDrawInfo *di, FRenderState& state, AActor* thing,sector_t * sector, area_t in_area, int thruportal = false, bool isSpriteShadow = false); - void ProcessParticle (HWDrawInfo *di, FRenderState& state, particle_t *particle, sector_t *sector);//, int shade, int fakeside) + void ProcessParticle (HWDrawInfo *di, FRenderState& state, particle_t *particle, sector_t *sector, class DVisualThinker *spr);//, int shade, int fakeside) + void AdjustVisualThinker(HWDrawInfo *di, DVisualThinker *spr, sector_t *sector); void DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent); }; @@ -401,7 +434,6 @@ struct DecalVertex { float x, y, z; float u, v; - float lu, lv, lindex; }; struct HWDecal @@ -432,7 +464,7 @@ inline float Dist2(float x1,float y1,float x2,float y2) return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } -void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata); +void hw_GetDynModelLight(HWDrawContext* drawctx, AActor *self, FDynLightData &modellightdata); extern const float LARGE_VALUE; diff --git a/src/rendering/hwrenderer/scene/hw_fakeflat.cpp b/src/rendering/hwrenderer/scene/hw_fakeflat.cpp index a41d169244..fe85251388 100644 --- a/src/rendering/hwrenderer/scene/hw_fakeflat.cpp +++ b/src/rendering/hwrenderer/scene/hw_fakeflat.cpp @@ -34,11 +34,10 @@ #include "hw_fakeflat.h" #include "hw_drawinfo.h" #include "hw_cvars.h" +#include "hw_drawcontext.h" #include "r_utility.h" #include "texturemanager.h" -static sector_t **fakesectorbuffer; - extern thread_local bool isWorkerThread; //========================================================================== @@ -186,24 +185,17 @@ area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, secto return area_default; } -//========================================================================== -// -// -// -//========================================================================== -static FMemArena FakeSectorAllocator(20 * sizeof(sector_t)); - -static sector_t *allocateSector(sector_t *sec) +static sector_t *allocateSector(HWDrawContext* drawctx, sector_t *sec) { - if (fakesectorbuffer == nullptr) + if (drawctx->fakesectorbuffer == nullptr) { unsigned numsectors = sec->Level->sectors.Size(); - fakesectorbuffer = (sector_t**)FakeSectorAllocator.Alloc(numsectors * sizeof(sector_t*)); - memset(fakesectorbuffer, 0, numsectors * sizeof(sector_t*)); + drawctx->fakesectorbuffer = (sector_t**)drawctx->FakeSectorAllocator.Alloc(numsectors * sizeof(sector_t*)); + memset(drawctx->fakesectorbuffer, 0, numsectors * sizeof(sector_t*)); } auto sectornum = sec->sectornum; - fakesectorbuffer[sectornum] = (sector_t*)FakeSectorAllocator.Alloc(sizeof(sector_t)); - return fakesectorbuffer[sectornum]; + drawctx->fakesectorbuffer[sectornum] = (sector_t*)drawctx->FakeSectorAllocator.Alloc(sizeof(sector_t)); + return drawctx->fakesectorbuffer[sectornum]; } //========================================================================== @@ -213,7 +205,7 @@ static sector_t *allocateSector(sector_t *sec) // //========================================================================== -sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *localcopy) +sector_t * hw_FakeFlat(HWDrawContext* drawctx, sector_t * sec, area_t in_area, bool back, sector_t *localcopy) { if (!sec->GetHeightSec() || sec->heightsec==sec) { @@ -221,12 +213,12 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca // visual glitches because upper amd lower textures overlap. if (back && (sec->MoreFlags & SECMF_OVERLAPPING)) { - if (fakesectorbuffer && fakesectorbuffer[sec->sectornum]) return fakesectorbuffer[sec->sectornum]; - auto dest = localcopy? localcopy : allocateSector(sec); + if (drawctx->fakesectorbuffer && drawctx->fakesectorbuffer[sec->sectornum]) return drawctx->fakesectorbuffer[sec->sectornum]; + auto dest = localcopy? localcopy : allocateSector(drawctx, sec); *dest = *sec; - dest->ceilingplane = sec->floorplane; - dest->ceilingplane.FlipVert(); - dest->planes[sector_t::ceiling].TexZ = dest->planes[sector_t::floor].TexZ; + dest->floorplane = sec->ceilingplane; + dest->floorplane.FlipVert(); + dest->planes[sector_t::floor].TexZ = dest->planes[sector_t::ceiling].TexZ; dest->ClearPortal(sector_t::ceiling); dest->ClearPortal(sector_t::floor); return dest; @@ -241,9 +233,9 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca } #endif - if (fakesectorbuffer && fakesectorbuffer[sec->sectornum]) + if (drawctx->fakesectorbuffer && drawctx->fakesectorbuffer[sec->sectornum]) { - return fakesectorbuffer[sec->sectornum]; + return drawctx->fakesectorbuffer[sec->sectornum]; } assert(!(isWorkerThread && localcopy == nullptr)); @@ -255,7 +247,7 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca int diffTex = (sec->heightsec->MoreFlags & SECMF_CLIPFAKEPLANES); sector_t * s = sec->heightsec; - auto dest = localcopy ? localcopy : allocateSector(sec); + auto dest = localcopy ? localcopy : allocateSector(drawctx, sec); *dest = *sec; // Replace floor and ceiling height with control sector's heights. @@ -417,8 +409,8 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca } -void hw_ClearFakeFlat() +void hw_ClearFakeFlat(HWDrawContext* drawctx) { - FakeSectorAllocator.FreeAll(); - fakesectorbuffer = nullptr; + drawctx->FakeSectorAllocator.FreeAll(); + drawctx->fakesectorbuffer = nullptr; } diff --git a/src/rendering/hwrenderer/scene/hw_fakeflat.h b/src/rendering/hwrenderer/scene/hw_fakeflat.h index 2f670d222a..fdecdf2536 100644 --- a/src/rendering/hwrenderer/scene/hw_fakeflat.h +++ b/src/rendering/hwrenderer/scene/hw_fakeflat.h @@ -1,5 +1,7 @@ #pragma once +class HWDrawContext; + enum area_t : int { area_normal, @@ -8,10 +10,9 @@ enum area_t : int area_default }; - // Global functions. bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector); -void hw_ClearFakeFlat(); -sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *localcopy = nullptr); +void hw_ClearFakeFlat(HWDrawContext* drawctx); +sector_t * hw_FakeFlat(HWDrawContext* drawctx, sector_t * sec, area_t in_area, bool back, sector_t *localcopy = nullptr); area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector); diff --git a/src/rendering/hwrenderer/scene/hw_flatdispatcher.h b/src/rendering/hwrenderer/scene/hw_flatdispatcher.h new file mode 100644 index 0000000000..aff34bc4da --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_flatdispatcher.h @@ -0,0 +1,90 @@ +#pragma once + +struct HWFlatMeshHelper +{ + TArray list; + TArray translucent; + TArray translucentborder; + TArray portals; + uint8_t section_renderflags = 0; +}; + +struct HWFlatDispatcher +{ + FLevelLocals* Level; + HWDrawInfo* di; + HWFlatMeshHelper* mh; + ELightMode lightmode; + + HWFlatDispatcher(HWDrawInfo* info) + { + Level = info->Level; + di = info; + mh = nullptr; + lightmode = info->lightmode; + } + + HWFlatDispatcher(FLevelLocals* lev, HWFlatMeshHelper* help, ELightMode lm) + { + Level = lev; + di = nullptr; + mh = help; + lightmode = lm; + } + + bool isFullbrightScene() + { + // The mesh builder cannot know this and must treat everything as not fullbright. + return di && di->isFullbrightScene(); + } + + void AddFlat(HWFlat* flat, bool fog) + { + if (di) + { + di->AddFlat(flat, fog); + } + else if (flat->plane.texture == skyflatnum || flat->stack) + { + mh->portals.Push(*flat); + } + else + { + if (flat->renderstyle != STYLE_Translucent || flat->alpha < 1.f - FLT_EPSILON || fog || flat->texture == nullptr) + { + // translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list. + if (flat->renderflags & SSRF_RENDER3DPLANES) + mh->translucent.Push(*flat); + else + mh->translucentborder.Push(*flat); + } + else if (flat->texture->GetTranslucency()) + { + if (flat->stack) + { + mh->translucentborder.Push(*flat); + } + else if ((flat->renderflags & SSRF_RENDER3DPLANES) && !flat->plane.plane.isSlope()) + { + mh->translucent.Push(*flat); + } + else + { + mh->list.Push(*flat); + } + } + else + { + bool masked = flat->texture->isMasked() && ((flat->renderflags & SSRF_RENDER3DPLANES) || flat->stack); + if (masked) + { + mh->list.Push(*flat); // Do we need a different list for this? + } + else + { + mh->list.Push(*flat); + } + } + } + } +}; diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index 0b878da758..123675a73c 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -41,11 +41,13 @@ #include "hw_clock.h" #include "hw_lighting.h" #include "hw_material.h" +#include "hw_drawcontext.h" #include "hwrenderer/scene/hw_drawinfo.h" #include "flatvertices.h" #include "hw_drawstructs.h" #include "hw_renderstate.h" #include "texturemanager.h" +#include "hw_flatdispatcher.h" #ifdef _DEBUG CVAR(Int, gl_breaksec, -1, 0) @@ -57,6 +59,41 @@ CVAR(Int, gl_breaksec, -1, 0) // //========================================================================== +VSMatrix GetPlaneTextureRotationMatrix(FGameTexture* gltexture, const FVector2& uvOffset, float angle, const FVector2& scale) +{ + float uoffs = uvOffset.X / gltexture->GetDisplayWidth(); + float voffs = uvOffset.Y / gltexture->GetDisplayHeight(); + + float yscale1 = scale.Y; + if (gltexture->isHardwareCanvas()) + { + yscale1 = 0 - yscale1; + } + + float xscale2 = 64.f / gltexture->GetDisplayWidth(); + float yscale2 = 64.f / gltexture->GetDisplayHeight(); + + VSMatrix mat; + mat.loadIdentity(); + mat.scale(scale.X, yscale1, 1.0f); + mat.translate(uoffs, voffs, 0.0f); + mat.scale(xscale2, yscale2, 1.0f); + mat.rotate(angle, 0.0f, 0.0f, 1.0f); + return mat; +} + +VSMatrix GetPlaneTextureRotationMatrix(FGameTexture* gltexture, const HWSectorPlane& secplane) +{ + return GetPlaneTextureRotationMatrix(gltexture, secplane.Offs, -secplane.Angle, secplane.Scale); +} + +VSMatrix GetPlaneTextureRotationMatrix(FGameTexture* gltexture, const sector_t* sector, int plane) +{ + HWSectorPlane splane; + splane.GetFromSector(sector, plane); + return GetPlaneTextureRotationMatrix(gltexture, splane); +} + bool SetPlaneTextureRotation(FRenderState& state, HWSectorPlane* secplane, FGameTexture* gltexture) { // only manipulate the texture matrix if needed. @@ -66,27 +103,7 @@ bool SetPlaneTextureRotation(FRenderState& state, HWSectorPlane* secplane, FGame gltexture->GetDisplayWidth() != 64 || gltexture->GetDisplayHeight() != 64) { - float uoffs = secplane->Offs.X / gltexture->GetDisplayWidth(); - float voffs = secplane->Offs.Y / gltexture->GetDisplayHeight(); - - float xscale1 = secplane->Scale.X; - float yscale1 = secplane->Scale.Y; - if (gltexture->isHardwareCanvas()) - { - yscale1 = 0 - yscale1; - } - float angle = -secplane->Angle; - - float xscale2 = 64.f / gltexture->GetDisplayWidth(); - float yscale2 = 64.f / gltexture->GetDisplayHeight(); - - VSMatrix mat; - mat.loadIdentity(); - mat.scale(xscale1, yscale1, 1.0f); - mat.translate(uoffs, voffs, 0.0f); - mat.scale(xscale2, yscale2, 1.0f); - mat.rotate(angle, 0.0f, 0.0f, 1.0f); - state.SetTextureMatrix(mat); + state.SetTextureMatrix(GetPlaneTextureRotationMatrix(gltexture, *secplane)); return true; } return false; @@ -140,8 +157,14 @@ void HWFlat::CreateSkyboxVertices(FFlatVertex *vert) // //========================================================================== -void HWFlat::SetupLights(HWDrawInfo *di, FRenderState& state, FLightNode * node, FDynLightData &lightdata, int portalgroup) +void HWFlat::SetupLights(HWFlatDispatcher *di, FRenderState& state, FLightNode * node, FDynLightData &lightdata, int portalgroup) { + if (!di->di) + { + dynlightindex = -1; + return; + } + Plane p; lightdata.Clear(); @@ -184,15 +207,13 @@ void HWFlat::SetupLights(HWDrawInfo *di, FRenderState& state, FLightNode * node, // //========================================================================== -void HWFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state) +void HWFlat::DrawSubsectors(HWFlatDispatcher *di, FRenderState &state) { - if (di->Level->HasDynamicLights && screen->BuffersArePersistent() && !di->isFullbrightScene()) + if (di->Level->HasDynamicLights && !di->isFullbrightScene()) { SetupLights(di, state, section->lighthead, lightdata, sector->PortalGroup); } state.SetLightIndex(dynlightindex); - - state.DrawIndexed(DT_Triangles, iboindex + section->vertexindex, section->vertexcount); flatvertices += section->vertexcount; flatprimitives++; @@ -207,7 +228,7 @@ void HWFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state) void HWFlat::DrawOtherPlanes(HWDrawInfo *di, FRenderState &state) { - state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, 0, -1); + state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, NO_TRANSLATION, -1); // Draw the subsectors assigned to it due to missing textures auto pNode = (renderflags&SSRF_RENDERFLOOR) ? @@ -239,7 +260,7 @@ void HWFlat::DrawFloodPlanes(HWDrawInfo *di, FRenderState &state) // This requires a stencil because the projected plane interferes with // the depth buffer - state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, 0, -1); + state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, NO_TRANSLATION, -1); // Draw the subsectors assigned to it due to missing textures auto pNode = (renderflags&SSRF_RENDERFLOOR) ? @@ -295,7 +316,7 @@ void HWFlat::DrawFloodPlanes(HWDrawInfo *di, FRenderState &state) // // //========================================================================== -void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) +void HWFlat::DrawFlat(HWFlatDispatcher *di, FRenderState &state, bool translucent) { #ifdef _DEBUG if (sector->sectornum == gl_breaksec) @@ -308,8 +329,8 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetNormal(plane.plane.Normal().X, plane.plane.Normal().Z, plane.plane.Normal().Y); - di->SetColor(state, lightlevel, rel, di->isFullbrightScene(), Colormap, alpha); - di->SetFog(state, lightlevel, rel, di->isFullbrightScene(), &Colormap, false); + SetColor(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), Colormap, alpha); + SetFog(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), &Colormap, false, di->di ? di->di->drawctx->portalState.inskybox : false); state.SetObjectColor(FlatColor | 0xff000000); state.SetAddColor(AddColor | 0xff000000); state.ApplyTextureManipulation(TextureFx); @@ -317,17 +338,19 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) if (hacktype & SSRF_PLANEHACK) { - DrawOtherPlanes(di, state); + if (di->di) + DrawOtherPlanes(di->di, state); } else if (hacktype & SSRF_FLOODHACK) { - DrawFloodPlanes(di, state); + if (di->di) + DrawFloodPlanes(di->di, state); } else if (!translucent) { if (sector->special != GLSector_Skybox) { - state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, 0, -1); + state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, NO_TRANSLATION, -1); bool texmatrix = SetPlaneTextureRotation(state, &plane, texture); DrawSubsectors(di, state); if (texmatrix) @@ -335,7 +358,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) } else if (!hacktype) { - state.SetMaterial(texture, UF_Texture, 0, CLAMP_XY, 0, -1); + state.SetMaterial(texture, UF_Texture, 0, CLAMP_XY, NO_TRANSLATION, -1); state.SetLightIndex(dynlightindex); state.Draw(DT_TriangleStrip,iboindex, 4); flatvertices += 4; @@ -356,7 +379,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) { if (!texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); else state.AlphaFunc(Alpha_GEqual, 0.f); - state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, 0, -1); + state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, NO_TRANSLATION, -1); bool texmatrix = SetPlaneTextureRotation(state, &plane, texture); DrawSubsectors(di, state); if (texmatrix) @@ -377,19 +400,12 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) // //========================================================================== -inline void HWFlat::PutFlat(HWDrawInfo *di, FRenderState& state, bool fog) +inline void HWFlat::PutFlat(HWFlatDispatcher *di, bool fog) { if (di->isFullbrightScene()) { Colormap.Clear(); } - else if (!screen->BuffersArePersistent()) - { - if (di->Level->HasDynamicLights && texture != nullptr && !di->isFullbrightScene() && !(hacktype & (SSRF_PLANEHACK|SSRF_FLOODHACK)) ) - { - SetupLights(di, state, section->lighthead, lightdata, sector->PortalGroup); - } - } di->AddFlat(this, fog); } @@ -400,7 +416,7 @@ inline void HWFlat::PutFlat(HWDrawInfo *di, FRenderState& state, bool fog) // //========================================================================== -void HWFlat::Process(HWDrawInfo *di, FRenderState& state, sector_t * model, int whichplane, bool fog) +void HWFlat::Process(HWFlatDispatcher *di, FRenderState& state, sector_t * model, int whichplane, bool fog) { plane.GetFromSector(model, whichplane); if (whichplane != int(ceiling)) @@ -434,7 +450,7 @@ void HWFlat::Process(HWDrawInfo *di, FRenderState& state, sector_t * model, int } // For hacks this won't go into a render list. - PutFlat(di, state, fog); + PutFlat(di, fog); rendered_flats++; } @@ -471,6 +487,8 @@ void HWFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside) alpha = rover->alpha/255.0f; renderstyle = rover->flags&FF_ADDITIVETRANS? STYLE_Add : STYLE_Translucent; iboindex = plane.vindex; + + controlsector = rover; } //========================================================================== @@ -481,7 +499,7 @@ void HWFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside) // //========================================================================== -void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * frontsector, int which) +void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t * frontsector, int which) { lightlist_t * light; FSectorPortal *port; @@ -493,6 +511,8 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front } #endif + controlsector = nullptr; + // Get the real sector for this one. sector = &di->Level->sectors[frontsector->sectornum]; extsector_t::xfloor &x = sector->e->XFloor; @@ -500,8 +520,29 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front hacktype = (which & (SSRF_PLANEHACK|SSRF_FLOODHACK)); uint8_t sink; - uint8_t &srf = hacktype? sink : di->section_renderflags[di->Level->sections.SectionIndex(section)]; - const auto &vp = di->Viewpoint; + uint8_t &srf = hacktype? sink : (di->di ? di->di->section_renderflags[di->Level->sections.SectionIndex(section)] : di->mh->section_renderflags); + FRenderViewpoint* vp = di->di ? &di->di->Viewpoint : nullptr; + + // + // Lightmaps + // + if (di->di && level.lightmaps) + { + for (int i = 0, count = sector->subsectorcount; i < count; ++i) + { + for (int plane = 0; plane < 2; ++plane) + { + unsigned int count = sector->e->XFloor.ffloors.Size() + 1; + for (unsigned int j = 0; j < count; j++) + { + if (auto surface = sector->subsectors[i]->surface[plane].Size() > j ? sector->subsectors[i]->surface[plane][j] : nullptr) + { + di->di->PushVisibleSurface(surface); + } + } + } + } + } // // @@ -510,7 +551,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front // // // - if ((which & SSRF_RENDERFLOOR) && (di->MeshBuilding || frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERFLOOR))) + if ((which & SSRF_RENDERFLOOR) && (!di->di || (frontsector->floorplane.ZatPoint(vp->Pos) <= vp->Pos.Z && (!section || !(section->flags & FSection::DONTRENDERFLOOR))))) { // process the original floor first. @@ -538,7 +579,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front alpha = 1.0f - frontsector->GetReflect(sector_t::floor); } - if (alpha != 0.f && frontsector->GetTexture(sector_t::floor) != skyflatnum) + if ((di->di && alpha != 0.f && frontsector->GetTexture(sector_t::floor) != skyflatnum) || (!di->di && (alpha != 0.f || stack))) { iboindex = frontsector->iboindex[sector_t::floor]; @@ -568,7 +609,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front // // // - if ((which & SSRF_RENDERCEILING) && (di->MeshBuilding || frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERCEILING))) + if ((which & SSRF_RENDERCEILING) && ((!di->di || frontsector->ceilingplane.ZatPoint(vp->Pos) >= vp->Pos.Z && (!section || !(section->flags & FSection::DONTRENDERCEILING))))) { // process the original ceiling first. @@ -595,7 +636,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front alpha = 1.0f - frontsector->GetReflect(sector_t::ceiling); } - if (alpha != 0.f && frontsector->GetTexture(sector_t::ceiling) != skyflatnum) + if ((di->di && alpha != 0.f && frontsector->GetTexture(sector_t::ceiling) != skyflatnum) || (!di->di && (alpha != 0.f || stack))) { iboindex = frontsector->iboindex[sector_t::ceiling]; ceiling = true; @@ -653,7 +694,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front double ff_top = rover->top.plane->ZatPoint(sector->centerspot); if (ff_top < lastceilingheight) { - if (di->MeshBuilding || vp.Pos.Z <= rover->top.plane->ZatPoint(vp.Pos)) + if (!di->di || vp->Pos.Z <= rover->top.plane->ZatPoint(vp->Pos)) { SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -667,7 +708,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); if (ff_bottom < lastceilingheight) { - if (di->MeshBuilding || vp.Pos.Z <= rover->bottom.plane->ZatPoint(vp.Pos)) + if (!di->di || vp->Pos.Z <= rover->bottom.plane->ZatPoint(vp->Pos)) { SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -693,7 +734,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX)) { - if (di->MeshBuilding || vp.Pos.Z >= rover->bottom.plane->ZatPoint(vp.Pos)) + if (!di->di || vp->Pos.Z >= rover->bottom.plane->ZatPoint(vp->Pos)) { SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -714,7 +755,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front double ff_top = rover->top.plane->ZatPoint(sector->centerspot); if (ff_top > lastfloorheight) { - if (di->MeshBuilding || vp.Pos.Z >= rover->top.plane->ZatPoint(vp.Pos)) + if (!di->di || vp->Pos.Z >= rover->top.plane->ZatPoint(vp->Pos)) { SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; diff --git a/src/rendering/hwrenderer/scene/hw_lighting.cpp b/src/rendering/hwrenderer/scene/hw_lighting.cpp index 89354439e8..bfcaf5f749 100644 --- a/src/rendering/hwrenderer/scene/hw_lighting.cpp +++ b/src/rendering/hwrenderer/scene/hw_lighting.cpp @@ -76,13 +76,13 @@ CUSTOM_CVAR(Int, gl_distfog, 70, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // //========================================================================== -int HWDrawInfo::CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor) +int CalcLightLevel(ELightMode lightmode, int lightlevel, int rellight, bool weapon, int blendfactor) { int light; if (lightlevel <= 0) return 0; - bool darklightmode = (isDarkLightMode()) || (isSoftwareLighting() && blendfactor > 0); + bool darklightmode = (isDarkLightMode(lightmode)) || (isSoftwareLighting(lightmode) && blendfactor > 0); if (darklightmode && lightlevel < 192 && !weapon) { @@ -119,13 +119,13 @@ int HWDrawInfo::CalcLightLevel(int lightlevel, int rellight, bool weapon, int bl // //========================================================================== -PalEntry HWDrawInfo::CalcLightColor(int light, PalEntry pe, int blendfactor) +PalEntry CalcLightColor(ELightMode lightmode, int light, PalEntry pe, int blendfactor) { int r,g,b; if (blendfactor == 0) { - if (isSoftwareLighting()) + if (isSoftwareLighting(lightmode)) { return pe; } @@ -165,12 +165,12 @@ PalEntry HWDrawInfo::CalcLightColor(int light, PalEntry pe, int blendfactor) // //========================================================================== -float HWDrawInfo::GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor) +float GetFogDensity(FLevelLocals* Level, ELightMode lightmode, int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor) { float density; auto oldlightmode = lightmode; - if (isSoftwareLighting() && blendfactor > 0) lightmode = ELightMode::Doom; // The blendfactor feature does not work with software-style lighting. + if (isSoftwareLighting(lightmode) && blendfactor > 0) lightmode = ELightMode::Doom; // The blendfactor feature does not work with software-style lighting. if (lightmode == ELightMode::DoomLegacy) { @@ -185,7 +185,7 @@ float HWDrawInfo::GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfog else if ((fogcolor.d & 0xffffff) == 0) { // case 2: black fog - if ((!isDoomSoftwareLighting() || blendfactor > 0) && !(Level->flags3 & LEVEL3_NOLIGHTFADE)) + if ((!isDoomSoftwareLighting(lightmode) || blendfactor > 0) && !(Level->flags3 & LEVEL3_NOLIGHTFADE)) { density = distfogtable[lightmode != ELightMode::LinearStandard][hw_ClampLight(lightlevel)]; } @@ -227,7 +227,7 @@ float HWDrawInfo::GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfog // //========================================================================== -bool HWDrawInfo::CheckFog(sector_t *frontsector, sector_t *backsector) +bool CheckFog(FLevelLocals* Level, sector_t *frontsector, sector_t *backsector, ELightMode lightmode) { if (frontsector == backsector) return false; // there can't be a boundary if both sides are in the same sector. diff --git a/src/rendering/hwrenderer/scene/hw_meshcache.cpp b/src/rendering/hwrenderer/scene/hw_meshcache.cpp deleted file mode 100644 index c838ee21d5..0000000000 --- a/src/rendering/hwrenderer/scene/hw_meshcache.cpp +++ /dev/null @@ -1,160 +0,0 @@ - -#include "hw_meshcache.h" -#include "hw_drawinfo.h" -#include "hw_drawstructs.h" -#include "hw_mesh.h" -#include "hw_fakeflat.h" -#include "hw_vertexbuilder.h" -#include "g_levellocals.h" -#include - -EXTERN_CVAR(Bool, gl_texture) -EXTERN_CVAR(Float, gl_mask_threshold) -EXTERN_CVAR(Bool, gl_meshcache) - -HWMeshCache meshcache; - -void HWMeshCache::Clear() -{ -#if 0 - Sectors.Reset(); -#endif - Opaque.reset(); - Translucent.reset(); - TranslucentDepthBiased.reset(); -} - -void HWMeshCache::Update(FRenderViewpoint& vp) -{ - if (!gl_meshcache) - return; - - auto level = vp.ViewLevel; - -#if 0 - - unsigned int count = level->sectors.Size(); - Sectors.Resize(count); - - // Look for changes - for (unsigned int i = 0; i < count; i++) - { - auto sector = &level->sectors[i]; - auto cacheitem = &Sectors[i]; - if (cacheitem->Floorplane != sector->floorplane || cacheitem->Ceilingplane != sector->ceilingplane) // Sector height changes - { - cacheitem->NeedsUpdate = true; - for (line_t* line : sector->Lines) - { - sector_t* backsector = (line->frontsector == sector) ? line->backsector : line->frontsector; - if (backsector) - { - Sectors[backsector->Index()].NeedsUpdate = true; - } - } - } - } - - // Update changed sectors - for (unsigned int i = 0; i < count; i++) - { - auto sector = &level->sectors[i]; - auto cacheitem = &Sectors[i]; - if (cacheitem->NeedsUpdate) - { - cacheitem->NeedsUpdate = false; - cacheitem->Sector = sector; - cacheitem->Floorplane = sector->floorplane; - cacheitem->Ceilingplane = sector->ceilingplane; - cacheitem->Update(vp); - } - } - -#endif - - if (!Opaque) - { - HWDrawInfo* di = HWDrawInfo::StartDrawInfo(vp.ViewLevel, nullptr, vp, nullptr); - di->MeshBuilding = true; - - MeshBuilder state; - state.SetShadowData(sector_vertices, sector_indexes); - - // Add to the draw lists - - unsigned int count = level->sectors.Size(); - for (unsigned int i = 0; i < count; i++) - { - auto sector = &level->sectors[i]; - - // CheckUpdate(state, sector); - std::unordered_set seenSections; - for (int i = 0, count = sector->subsectorcount; i < count; i++) - { - subsector_t* subsector = sector->subsectors[i]; - if (seenSections.find(subsector->section) == seenSections.end()) - { - seenSections.insert(subsector->section); - - HWFlat flat; - flat.section = subsector->section; - sector_t* front = hw_FakeFlat(subsector->render_sector, area_default, false); - flat.ProcessSector(di, state, front); - } - } - - for (line_t* line : sector->Lines) - { - side_t* side = (line->sidedef[0]->sector == sector) ? line->sidedef[0] : line->sidedef[1]; - - HWWall wall; - wall.sub = sector->subsectors[0]; - wall.Process(di, state, side->segs[0], sector, (line->sidedef[0]->sector == sector) ? line->backsector : line->frontsector); - } - } - - // Convert draw lists to meshes - - state.SetDepthMask(true); - state.EnableFog(true); - state.SetRenderStyle(STYLE_Source); - - di->drawlists[GLDL_PLAINWALLS].SortWalls(); - di->drawlists[GLDL_PLAINFLATS].SortFlats(); - di->drawlists[GLDL_MASKEDWALLS].SortWalls(); - di->drawlists[GLDL_MASKEDFLATS].SortFlats(); - di->drawlists[GLDL_MASKEDWALLSOFS].SortWalls(); - - // Part 1: solid geometry. This is set up so that there are no transparent parts - state.SetDepthFunc(DF_Less); - state.AlphaFunc(Alpha_GEqual, 0.f); - state.ClearDepthBias(); - state.EnableTexture(gl_texture); - state.EnableBrightmap(true); - di->drawlists[GLDL_PLAINWALLS].DrawWalls(di, state, false); - di->drawlists[GLDL_PLAINFLATS].DrawFlats(di, state, false); - Opaque = state.Create(); - - // Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show - state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); - di->drawlists[GLDL_MASKEDWALLS].DrawWalls(di, state, false); - di->drawlists[GLDL_MASKEDFLATS].DrawFlats(di, state, false); - Translucent = state.Create(); - - // Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use. - if (di->drawlists[GLDL_MASKEDWALLSOFS].Size() > 0) - { - state.SetDepthBias(-1, -128); - di->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(di, state, false); - state.ClearDepthBias(); - TranslucentDepthBiased = state.Create(); - } - else - { - TranslucentDepthBiased.reset(); - } - - di->MeshBuilding = false; - di->EndDrawInfo(); - } -} diff --git a/src/rendering/hwrenderer/scene/hw_meshcache.h b/src/rendering/hwrenderer/scene/hw_meshcache.h deleted file mode 100644 index 5ca6bf269e..0000000000 --- a/src/rendering/hwrenderer/scene/hw_meshcache.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "hw_mesh.h" -#include "r_defs.h" - -struct FRenderViewpoint; - -#if 0 -class HWCachedSector -{ -public: - bool NeedsUpdate = true; - - sector_t* Sector = nullptr; - secplane_t Floorplane; - secplane_t Ceilingplane; -}; -#endif - -class HWMeshCache -{ -public: - void Clear(); - void Update(FRenderViewpoint& vp); - -#if 0 - TArray Sectors; -#endif - - std::unique_ptr Opaque; - std::unique_ptr Translucent; - std::unique_ptr TranslucentDepthBiased; -}; - -extern HWMeshCache meshcache; diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 3389487861..fe593719cd 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -36,6 +36,7 @@ #include "flatvertices.h" #include "hw_clock.h" #include "hw_lighting.h" +#include "hw_drawcontext.h" #include "texturemanager.h" EXTERN_CVAR(Int, r_mirror_recursions) @@ -73,7 +74,6 @@ CCMD(gl_portalinfo) } static FString indent; -FPortalSceneState portalState; //----------------------------------------------------------------------------- // @@ -107,7 +107,7 @@ void FPortalSceneState::EndFrame(HWDrawInfo *di, FRenderState &state) if (gl_portalinfo) { - indent.Truncate(long(indent.Len()-2)); + indent.Truncate(indent.Len()-2); Printf("%s}\n", indent.GetChars()); if (indent.Len() == 0) gl_portalinfo = false; } @@ -445,7 +445,7 @@ int HWLinePortal::ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; // should be handled properly. } - return P_ClipLineToPortal(linedef, this, viewpos) ? PClip_InFront : PClip_Inside; + return P_ClipLineToPortal(linedef, this, viewpos.XY()) ? PClip_InFront : PClip_Inside; } int HWLinePortal::ClipSubsector(subsector_t *sub) @@ -970,19 +970,19 @@ void HWHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state) if (texture->isFullbright()) { // glowing textures are always drawn full bright without color - di->SetColor(state, 255, 0, false, origin->colormap, 1.f); - di->SetFog(state, 255, 0, false, &origin->colormap, false); + SetColor(state, di->Level, di->lightmode, 255, 0, false, origin->colormap, 1.f); + SetFog(state, di->Level, di->lightmode, 255, 0, false, &origin->colormap, false, di->drawctx->portalState.inskybox); } else { int rel = getExtraLight(); - di->SetColor(state, origin->lightlevel, rel, di->isFullbrightScene(), origin->colormap, 1.0f); - di->SetFog(state, origin->lightlevel, rel, di->isFullbrightScene(), &origin->colormap, false); + SetColor(state, di->Level, di->lightmode, origin->lightlevel, rel, di->isFullbrightScene(), origin->colormap, 1.0f); + SetFog(state, di->Level, di->lightmode, origin->lightlevel, rel, di->isFullbrightScene(), &origin->colormap, false, di->drawctx->portalState.inskybox); } state.EnableBrightmap(true); - state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, 0, -1); + state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, NO_TRANSLATION, -1); state.SetObjectColor(origin->specialcolor); state.AlphaFunc(Alpha_GEqual, 0.f); state.SetRenderStyle(STYLE_Source); @@ -1028,7 +1028,7 @@ void HWEEHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state) sector->GetTexture(sector_t::ceiling) == skyflatnum) { HWSkyInfo skyinfo; - skyinfo.init(di, sector->sky, 0); + skyinfo.init(di, sector, sector_t::ceiling, sector->skytransfer, 0); HWSkyPortal sky(screen->mSkyData, mState, &skyinfo, true); sky.DrawContents(di, state); } diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index 218c09a15f..97d85523c4 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -30,7 +30,7 @@ struct HWSkyInfo { return !!memcmp(this, &inf, sizeof(*this)); } - void init(HWDrawInfo *di, int sky1, PalEntry fadecolor); + void init(HWDrawInfo *di, sector_t* sec, int skypos, int sky1, PalEntry fadecolor); }; struct HWHorizonInfo @@ -55,7 +55,7 @@ class HWPortal STP_AllInOne }; - ActorRenderFlags savedvisibility; + ActorRenderFlags savedvisibility = {}; TArray mPrimIndices; unsigned int mTopCap = ~0u, mBottomCap = ~0u; @@ -130,7 +130,6 @@ struct FPortalSceneState void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil, HWDrawInfo *outer_di); }; -extern FPortalSceneState portalState; class HWScenePortalBase : public HWPortal diff --git a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp index 2418fd8828..0df035da4a 100644 --- a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp @@ -33,6 +33,7 @@ #include "a_dynlight.h" #include "texturemanager.h" +#include "hw_drawcontext.h" #include "hw_drawinfo.h" #include "hw_drawstructs.h" #include "hw_clock.h" @@ -40,6 +41,8 @@ #include "flatvertices.h" #include "hwrenderer/scene/hw_portal.h" #include "hw_fakeflat.h" +#include "hw_walldispatcher.h" +#include "hw_flatdispatcher.h" //========================================================================== // @@ -49,6 +52,7 @@ void HWDrawInfo::DispatchRenderHacks(FRenderState& state) { + HWFlatDispatcher dis(this); TMap::Pair *pair; TMap::Pair *fpair; TMap::Iterator ofi(otherFloorPlanes); @@ -56,29 +60,29 @@ void HWDrawInfo::DispatchRenderHacks(FRenderState& state) glflat.section = nullptr; while (ofi.NextPair(pair)) { - auto sec = hw_FakeFlat(&Level->sectors[pair->Key], in_area, false); - glflat.ProcessSector(this, state, sec, SSRF_RENDERFLOOR | SSRF_PLANEHACK); + auto sec = hw_FakeFlat(drawctx, &Level->sectors[pair->Key], in_area, false); + glflat.ProcessSector(&dis, state, sec, SSRF_RENDERFLOOR | SSRF_PLANEHACK); } TMap::Iterator oci(otherCeilingPlanes); while (oci.NextPair(pair)) { - auto sec = hw_FakeFlat(&Level->sectors[pair->Key], in_area, false); - glflat.ProcessSector(this, state, sec, SSRF_RENDERCEILING | SSRF_PLANEHACK); + auto sec = hw_FakeFlat(drawctx, &Level->sectors[pair->Key], in_area, false); + glflat.ProcessSector(&dis, state, sec, SSRF_RENDERCEILING | SSRF_PLANEHACK); } TMap::Iterator ffi(floodFloorSegs); while (ffi.NextPair(fpair)) { - auto sec = hw_FakeFlat(&Level->sectors[fpair->Key], in_area, false); - glflat.ProcessSector(this, state, sec, SSRF_RENDERFLOOR | SSRF_FLOODHACK); + auto sec = hw_FakeFlat(drawctx, &Level->sectors[fpair->Key], in_area, false); + glflat.ProcessSector(&dis, state, sec, SSRF_RENDERFLOOR | SSRF_FLOODHACK); } TMap::Iterator fci(floodCeilingSegs); while (fci.NextPair(fpair)) { - auto sec = hw_FakeFlat(&Level->sectors[fpair->Key], in_area, false); - glflat.ProcessSector(this, state, sec, SSRF_RENDERCEILING | SSRF_FLOODHACK); + auto sec = hw_FakeFlat(drawctx, &Level->sectors[fpair->Key], in_area, false); + glflat.ProcessSector(&dis, state, sec, SSRF_RENDERCEILING | SSRF_FLOODHACK); } } @@ -89,14 +93,14 @@ void HWDrawInfo::DispatchRenderHacks(FRenderState& state) // //========================================================================== -static gl_subsectorrendernode *NewSubsectorRenderNode() +static gl_subsectorrendernode *NewSubsectorRenderNode(HWDrawContext* drawctx) { - return (gl_subsectorrendernode*)RenderDataAllocator.Alloc(sizeof(gl_subsectorrendernode)); + return (gl_subsectorrendernode*)drawctx->RenderDataAllocator.Alloc(sizeof(gl_subsectorrendernode)); } -static gl_floodrendernode *NewFloodRenderNode() +static gl_floodrendernode *NewFloodRenderNode(HWDrawContext* drawctx) { - return (gl_floodrendernode*)RenderDataAllocator.Alloc(sizeof(gl_floodrendernode)); + return (gl_floodrendernode*)drawctx->RenderDataAllocator.Alloc(sizeof(gl_floodrendernode)); } //========================================================================== @@ -335,7 +339,7 @@ bool HWDrawInfo::DoOneSectorUpper(subsector_t * subsec, float Planez, area_t in_ // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! - sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * sec = hw_FakeFlat(drawctx, seg->backsector, in_area, true); // Don't bother with slopes if (sec->ceilingplane.isSlope()) return false; @@ -393,7 +397,7 @@ bool HWDrawInfo::DoOneSectorLower(subsector_t * subsec, float Planez, area_t in_ // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! - sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * sec = hw_FakeFlat(drawctx, seg->backsector, in_area, true); // Don't bother with slopes if (sec->floorplane.isSlope()) return false; @@ -452,7 +456,7 @@ bool HWDrawInfo::DoFakeBridge(subsector_t * subsec, float Planez, area_t in_area // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! - sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * sec = hw_FakeFlat(drawctx, seg->backsector, in_area, true); // Don't bother with slopes if (sec->floorplane.isSlope()) return false; @@ -505,7 +509,7 @@ bool HWDrawInfo::DoFakeCeilingBridge(subsector_t * subsec, float Planez, area_t // Note: if this is a real line between sectors // we can be sure that render_sector is the real sector! - sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * sec = hw_FakeFlat(drawctx, seg->backsector, in_area, true); // Don't bother with slopes if (sec->ceilingplane.isSlope()) return false; @@ -553,7 +557,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) sector_t * sec = MissingUpperTextures[i].seg->backsector; for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = NewSubsectorRenderNode(); + gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(sec->sectornum, node, state); @@ -586,7 +590,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) { // It isn't a hole. Now check whether it might be a fake bridge - sector_t * fakesector = hw_FakeFlat(MissingUpperTextures[i].seg->frontsector, in_area, false); + sector_t * fakesector = hw_FakeFlat(drawctx, MissingUpperTextures[i].seg->frontsector, in_area, false); float planez = (float)fakesector->GetPlaneTexZ(sector_t::ceiling); backsub->validcount = validcount; @@ -594,7 +598,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) { for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = NewSubsectorRenderNode(); + gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(fakesector->sectornum, node, state); } @@ -620,7 +624,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = NewSubsectorRenderNode(); + gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(sec->sectornum, node, state); } @@ -652,7 +656,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) { // It isn't a hole. Now check whether it might be a fake bridge - sector_t * fakesector = hw_FakeFlat(MissingLowerTextures[i].seg->frontsector, in_area, false); + sector_t * fakesector = hw_FakeFlat(drawctx, MissingLowerTextures[i].seg->frontsector, in_area, false); float planez = (float)fakesector->GetPlaneTexZ(sector_t::floor); backsub->validcount = validcount; @@ -660,7 +664,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area, FRenderState& state) { for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = NewSubsectorRenderNode(); + gl_subsectorrendernode * node = NewSubsectorRenderNode(drawctx); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(fakesector->sectornum, node, state); } @@ -726,8 +730,8 @@ void HWDrawInfo::CreateFloodPoly(wallseg * ws, FFlatVertex *vertices, float plan void HWDrawInfo::PrepareUpperGap(seg_t * seg, FRenderState& state) { wallseg ws; - sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false); - sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * fakefsector = hw_FakeFlat(drawctx, seg->frontsector, in_area, false); + sector_t * fakebsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true); vertex_t * v1, *v2; @@ -763,7 +767,7 @@ void HWDrawInfo::PrepareUpperGap(seg_t * seg, FRenderState& state) CreateFloodStencilPoly(&ws, vertices.first); CreateFloodPoly(&ws, vertices.first+4, ws.z2, fakebsector, true); - gl_floodrendernode *node = NewFloodRenderNode(); + gl_floodrendernode *node = NewFloodRenderNode(drawctx); auto pNode = floodCeilingSegs.CheckKey(fakebsector->sectornum); node->next = pNode? *pNode : nullptr; @@ -782,8 +786,8 @@ void HWDrawInfo::PrepareUpperGap(seg_t * seg, FRenderState& state) void HWDrawInfo::PrepareLowerGap(seg_t * seg, FRenderState& state) { wallseg ws; - sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false); - sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true); + sector_t * fakefsector = hw_FakeFlat(drawctx, seg->frontsector, in_area, false); + sector_t * fakebsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true); vertex_t * v1, *v2; @@ -820,7 +824,7 @@ void HWDrawInfo::PrepareLowerGap(seg_t * seg, FRenderState& state) CreateFloodStencilPoly(&ws, vertices.first); CreateFloodPoly(&ws, vertices.first+4, ws.z1, fakebsector, false); - gl_floodrendernode *node = NewFloodRenderNode(); + gl_floodrendernode *node = NewFloodRenderNode(drawctx); auto pNode = floodFloorSegs.CheckKey(fakebsector->sectornum); node->next = pNode? *pNode : nullptr; @@ -1116,7 +1120,8 @@ void HWDrawInfo::ProcessLowerMinisegs(TArray &lowersegs, FRenderState& { seg_t * seg=lowersegs[j]; HWWall wall; - wall.ProcessLowerMiniseg(this, state, seg, seg->Subsector->render_sector, seg->PartnerSeg->Subsector->render_sector); + HWWallDispatcher disp(this); + wall.ProcessLowerMiniseg(&disp, state, seg, seg->Subsector->render_sector, seg->PartnerSeg->Subsector->render_sector); rendered_lines++; } } @@ -1141,7 +1146,7 @@ void HWDrawInfo::HandleHackedSubsectors(FRenderState& state) { for(unsigned int j=0;jsub = HandledSubsectors[j]; AddOtherFloorPlane(sub->render_sector->sectornum, node, state); } @@ -1163,7 +1168,7 @@ void HWDrawInfo::HandleHackedSubsectors(FRenderState& state) { for(unsigned int j=0;jsub = HandledSubsectors[j]; AddOtherCeilingPlane(sub->render_sector->sectornum, node, state); } diff --git a/src/rendering/hwrenderer/scene/hw_setcolor.cpp b/src/rendering/hwrenderer/scene/hw_setcolor.cpp index 2b0783a8fe..f8b150f676 100644 --- a/src/rendering/hwrenderer/scene/hw_setcolor.cpp +++ b/src/rendering/hwrenderer/scene/hw_setcolor.cpp @@ -31,27 +31,27 @@ #include "hw_portal.h" #include "hw_lighting.h" #include "hw_cvars.h" - +#include "hw_drawcontext.h" //========================================================================== // // set current light color // //========================================================================== -void HWDrawInfo::SetColor(FRenderState &state, int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon) +void SetColor(FRenderState &state, FLevelLocals* Level, ELightMode lightmode, int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon) { if (fullbright) { state.SetColorAlpha(0xffffff, alpha, 0); - if (isSoftwareLighting()) state.SetSoftLightLevel(255); + if (isSoftwareLighting(lightmode)) state.SetSoftLightLevel(255); else state.SetNoSoftLightLevel(); } else { - int hwlightlevel = CalcLightLevel(sectorlightlevel, rellight, weapon, cm.BlendFactor); - PalEntry pe = CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor); + int hwlightlevel = CalcLightLevel(lightmode, sectorlightlevel, rellight, weapon, cm.BlendFactor); + PalEntry pe = CalcLightColor(lightmode, hwlightlevel, cm.LightColor, cm.BlendFactor); state.SetColorAlpha(pe, alpha, cm.Desaturation); - if (isSoftwareLighting()) state.SetSoftLightLevel(hw_ClampLight(sectorlightlevel + rellight), cm.BlendFactor); + if (isSoftwareLighting(lightmode)) state.SetSoftLightLevel(hw_ClampLight(sectorlightlevel + rellight), cm.BlendFactor); else state.SetNoSoftLightLevel(); } } @@ -62,7 +62,7 @@ void HWDrawInfo::SetColor(FRenderState &state, int sectorlightlevel, int relligh // //========================================================================== -void HWDrawInfo::SetShaderLight(FRenderState &state, float level, float olight) +void SetShaderLight(FRenderState &state, FLevelLocals* Level, float level, float olight) { const float MAXDIST = 256.f; const float THRESHOLD = 96.f; @@ -96,7 +96,7 @@ void HWDrawInfo::SetShaderLight(FRenderState &state, float level, float olight) // //========================================================================== -void HWDrawInfo::SetFog(FRenderState &state, int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive) +void SetFog(FRenderState &state, FLevelLocals* Level, ELightMode lightmode, int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive, bool inskybox) { PalEntry fogcolor; float fogdensity; @@ -109,7 +109,7 @@ void HWDrawInfo::SetFog(FRenderState &state, int lightlevel, int rellight, bool else if (cmap != nullptr && !fullbright) { fogcolor = cmap->FadeColor; - fogdensity = GetFogDensity(lightlevel, fogcolor, cmap->FogDensity, cmap->BlendFactor); + fogdensity = GetFogDensity(Level, lightmode, lightlevel, fogcolor, cmap->FogDensity, cmap->BlendFactor); fogcolor.a = 0; } else @@ -119,7 +119,7 @@ void HWDrawInfo::SetFog(FRenderState &state, int lightlevel, int rellight, bool } // Make fog a little denser when inside a skybox - if (portalState.inskybox) fogdensity += fogdensity / 2; + if (inskybox) fogdensity += fogdensity / 2; // no fog in enhanced vision modes! @@ -130,10 +130,10 @@ void HWDrawInfo::SetFog(FRenderState &state, int lightlevel, int rellight, bool } else { - if ((lightmode == ELightMode::Doom || (isSoftwareLighting() && cmap && cmap->BlendFactor > 0)) && fogcolor == 0) + if ((lightmode == ELightMode::Doom || (isSoftwareLighting(lightmode) && cmap && cmap->BlendFactor > 0)) && fogcolor == 0) { - float light = (float)CalcLightLevel(lightlevel, rellight, false, cmap->BlendFactor); - SetShaderLight(state, light, lightlevel); + float light = (float)CalcLightLevel(lightmode, lightlevel, rellight, false, cmap->BlendFactor); + SetShaderLight(state, Level, light, lightlevel); } else if (lightmode == ELightMode::Build) { @@ -155,7 +155,7 @@ void HWDrawInfo::SetFog(FRenderState &state, int lightlevel, int rellight, bool state.SetFog(fogcolor, fogdensity); // Korshun: fullbright fog like in software renderer. - if (isSoftwareLighting() && cmap && cmap->BlendFactor == 0 && Level->brightfog && fogdensity != 0 && fogcolor != 0) + if (isSoftwareLighting(lightmode) && cmap && cmap->BlendFactor == 0 && Level->brightfog && fogdensity != 0 && fogcolor != 0) { state.SetSoftLightLevel(255); } diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 5382931a1b..ac2486ad07 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -33,16 +33,30 @@ #include "hwrenderer/scene/hw_portal.h" #include "hw_lighting.h" #include "hw_material.h" +#include "hw_walldispatcher.h" CVAR(Bool,gl_noskyboxes, false, 0) +//=========================================================================== +// +// +// +//=========================================================================== + +FTextureID GetSkyTexture(sector_t* sec, int plane, int second) +{ + auto tex = sec->planes[plane].skytexture[second]; + if (tex.isValid()) return tex; + return second ? sec->Level->skytexture2 : sec->Level->skytexture1; +} + //========================================================================== // // Set up the skyinfo struct // //========================================================================== -void HWSkyInfo::init(HWDrawInfo *di, int sky1, PalEntry FadeColor) +void HWSkyInfo::init(HWDrawInfo *di, sector_t* sec, int skypos, int sky1, PalEntry FadeColor) { memset(this, 0, sizeof(*this)); if ((sky1 & PL_SKYFLAT) && (sky1 & (PL_SKYFLAT - 1))) @@ -72,25 +86,27 @@ void HWSkyInfo::init(HWDrawInfo *di, int sky1, PalEntry FadeColor) else { normalsky: + auto skytex1 = GetSkyTexture(sec, skypos, false); + auto skytex2 = GetSkyTexture(sec, skypos, true); if (di->Level->flags&LEVEL_DOUBLESKY) { - auto tex1 = TexMan.GetGameTexture(di->Level->skytexture1, true); + auto tex1 = TexMan.GetGameTexture(skytex1); texture[1] = tex1; x_offset[1] = di->Level->hw_sky1pos; doublesky = true; } if ((di->Level->flags&LEVEL_SWAPSKIES || (sky1 == PL_SKYFLAT) || (di->Level->flags&LEVEL_DOUBLESKY)) && - di->Level->skytexture2 != di->Level->skytexture1) // If both skies are equal use the scroll offset of the first! + skytex2 != skytex1) // If both skies are equal use the scroll offset of the first! { - texture[0] = TexMan.GetGameTexture(di->Level->skytexture2, true); - skytexno1 = di->Level->skytexture2; + texture[0] = TexMan.GetGameTexture(skytex2, true); + skytexno1 = skytex2; sky2 = true; x_offset[0] = di->Level->hw_sky2pos; } else if (!doublesky) { - texture[0] = TexMan.GetGameTexture(di->Level->skytexture1, true); + texture[0] = TexMan.GetGameTexture(skytex1, true); skytexno1 = di->Level->skytexture1; x_offset[0] = di->Level->hw_sky1pos; } @@ -111,7 +127,7 @@ void HWSkyInfo::init(HWDrawInfo *di, int sky1, PalEntry FadeColor) // //========================================================================== -void HWWall::SkyPlane(HWDrawInfo *di, FRenderState& state, sector_t *sector, int plane, bool allowreflect) +void HWWall::SkyPlane(HWWallDispatcher *di, FRenderState& state, sector_t *sector, int plane, bool allowreflect) { int ptype = -1; @@ -121,10 +137,13 @@ void HWWall::SkyPlane(HWDrawInfo *di, FRenderState& state, sector_t *sector, int // Either a regular sky or a skybox with skyboxes disabled if ((sportal == nullptr && sector->GetTexture(plane) == skyflatnum) || (gl_noskyboxes && sportal != nullptr && sportal->mType == PORTS_SKYVIEWPOINT)) { - HWSkyInfo skyinfo; - skyinfo.init(di, sector->sky, Colormap.FadeColor); + if (di->di) + { + HWSkyInfo skyinfo; + skyinfo.init(di->di, sector, plane, sector->skytransfer, Colormap.FadeColor); + sky = &skyinfo; + } ptype = PORTALTYPE_SKY; - sky = &skyinfo; PutPortal(di, state, ptype, plane); } else if (sportal != nullptr) @@ -140,7 +159,7 @@ void HWWall::SkyPlane(HWDrawInfo *di, FRenderState& state, sector_t *sector, int { if (sector->PortalBlocksView(plane)) return; - if (screen->instack[1 - plane]) return; + if (di->di && screen->instack[1 - plane]) return; ptype = PORTALTYPE_SECTORSTACK; portal = glport; } @@ -155,13 +174,16 @@ void HWWall::SkyPlane(HWDrawInfo *di, FRenderState& state, sector_t *sector, int break; } } - else if (allowreflect && sector->GetReflect(plane) > 0) + else if (allowreflect && sector->GetReflect(plane) > 0 && !(di->Level->ib_compatflags & BCOMPATF_NOMIRRORS)) { - auto vpz = di->Viewpoint.Pos.Z; - if ((plane == sector_t::ceiling && vpz > sector->ceilingplane.fD()) || - (plane == sector_t::floor && vpz < -sector->floorplane.fD())) return; + if (di->di) + { + auto vpz = di->di->Viewpoint.Pos.Z; + if ((plane == sector_t::ceiling && vpz > sector->ceilingplane.fD()) || + (plane == sector_t::floor && vpz < -sector->floorplane.fD())) return; + planemirror = plane == sector_t::ceiling ? §or->ceilingplane : §or->floorplane; + } ptype = PORTALTYPE_PLANEMIRROR; - planemirror = plane == sector_t::ceiling ? §or->ceilingplane : §or->floorplane; } if (ptype != -1) { @@ -176,7 +198,7 @@ void HWWall::SkyPlane(HWDrawInfo *di, FRenderState& state, sector_t *sector, int // //========================================================================== -void HWWall::SkyLine(HWDrawInfo *di, FRenderState& state, sector_t *fs, line_t *line) +void HWWall::SkyLine(HWWallDispatcher *di, FRenderState& state, sector_t *fs, line_t *line) { FSectorPortal *secport = line->GetTransferredPortal(); HWSkyInfo skyinfo; @@ -192,7 +214,7 @@ void HWWall::SkyLine(HWDrawInfo *di, FRenderState& state, sector_t *fs, line_t * } else { - skyinfo.init(di, fs->sky, Colormap.FadeColor); + if (di->di) skyinfo.init(di->di, fs, sector_t::ceiling, fs->skytransfer, Colormap.FadeColor); ptype = PORTALTYPE_SKY; sky = &skyinfo; } @@ -210,7 +232,7 @@ void HWWall::SkyLine(HWDrawInfo *di, FRenderState& state, sector_t *fs, line_t * // //========================================================================== -void HWWall::SkyNormal(HWDrawInfo *di, FRenderState& state, sector_t * fs,vertex_t * v1,vertex_t * v2) +void HWWall::SkyNormal(HWWallDispatcher *di, FRenderState& state, sector_t * fs,vertex_t * v1,vertex_t * v2) { ztop[0]=ztop[1]=32768.0f; zbottom[0]=zceil[0]; @@ -229,7 +251,7 @@ void HWWall::SkyNormal(HWDrawInfo *di, FRenderState& state, sector_t * fs,vertex // //========================================================================== -void HWWall::SkyTop(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2) +void HWWall::SkyTop(HWWallDispatcher *di, FRenderState& state, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2) { if (fs->GetTexture(sector_t::ceiling)==skyflatnum) { @@ -323,7 +345,7 @@ void HWWall::SkyTop(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t * // //========================================================================== -void HWWall::SkyBottom(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2) +void HWWall::SkyBottom(HWWallDispatcher *di, FRenderState& state, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2) { if (fs->GetTexture(sector_t::floor)==skyflatnum) { @@ -343,8 +365,8 @@ void HWWall::SkyBottom(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t } else { - // Special hack for Vrack2b - if (bs->floorplane.ZatPoint(di->Viewpoint.Pos) > di->Viewpoint.Pos.Z) return; + // Special hack for Vrack2b. For mesh based rendering this check needs to be done in the actual render pass! + if (di->di && bs->floorplane.ZatPoint(di->di->Viewpoint.Pos) > di->di->Viewpoint.Pos.Z) return; } } zbottom[0]=zbottom[1]=-32768.0f; diff --git a/src/rendering/hwrenderer/scene/hw_skyportal.cpp b/src/rendering/hwrenderer/scene/hw_skyportal.cpp index 386b8fc1f7..89f83e130b 100644 --- a/src/rendering/hwrenderer/scene/hw_skyportal.cpp +++ b/src/rendering/hwrenderer/scene/hw_skyportal.cpp @@ -43,7 +43,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) // We have no use for Doom lighting special handling here, so disable it for this function. auto oldlightmode = di->lightmode; - if (di->isSoftwareLighting()) + if (isSoftwareLighting(oldlightmode)) { di->SetFallbackLightMode(); state.SetNoSoftLightLevel(); diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index 24bbd5f9a9..689e3d85d8 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -32,6 +32,7 @@ #include "g_level.h" #include "g_levellocals.h" #include "actorinlines.h" +#include "hw_drawcontext.h" #include "hw_dynlightdata.h" #include "hw_shadowmap.h" #include "hwrenderer/scene/hw_drawinfo.h" @@ -51,7 +52,7 @@ class ActorTraceStaticLight public: ActorTraceStaticLight(AActor* actor) : Actor(actor) { - if (Actor && Actor->Pos() != Actor->StaticLightsTraceCache.Pos) + if (Actor && (Actor->Pos() != Actor->StaticLightsTraceCache.Pos || (Actor->Sector && (Actor->Sector->Flags & SECF_LM_DYNAMIC)))) { Actor->StaticLightsTraceCache.Pos = Actor->Pos(); Actor->StaticLightsTraceCache.Bits = 0; @@ -73,7 +74,7 @@ class ActorTraceStaticLight } else { - bool traceResult = level.levelMesh->Trace(FVector3((float)light->Pos.X, (float)light->Pos.Y, (float)light->Pos.Z), FVector3(-L.X, -L.Y, -L.Z), dist); + bool traceResult = !level.levelMesh->Trace(FVector3((float)light->Pos.X, (float)light->Pos.Y, (float)light->Pos.Z), FVector3(-L.X, -L.Y, -L.Z), dist); Actor->StaticLightsTraceCache.Bits |= ((uint64_t)traceResult) << CurrentBit; CurrentBit++; return traceResult; @@ -82,7 +83,7 @@ class ActorTraceStaticLight bool TraceSunVisibility(float x, float y, float z) { - if (level.LMTextureCount == 0 || !Actor) + if (!level.lightmaps || !Actor) return false; if (!ActorMoved && CurrentBit < 64) @@ -93,7 +94,7 @@ class ActorTraceStaticLight } else { - bool traceResult = level.levelMesh->TraceSky(FVector3(x, y, z), level.SunDirection, 10000.0f); + bool traceResult = level.levelMesh->TraceSky(FVector3(x, y, z), level.SunDirection, 65536.0f); Actor->StaticLightsTraceCache.Bits |= ((uint64_t)traceResult) << CurrentBit; CurrentBit++; return traceResult; @@ -217,17 +218,14 @@ void HWDrawInfo::GetDynSpriteLight(AActor *thing, particle_t *particle, float *o } } -// static so that we build up a reserve (memory allocations stop) -// For multithread processing each worker thread needs its own copy, though. -static thread_local TArray addedLightsArray; -void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata) +void hw_GetDynModelLight(HWDrawContext* drawctx, AActor *self, FDynLightData &modellightdata) { modellightdata.Clear(); if (self) { - auto &addedLights = addedLightsArray; // avoid going through the thread local storage for each use. + auto &addedLights = drawctx->addedLightsArray; addedLights.Clear(); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 870e4a5028..9d67e4df9f 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -33,7 +33,6 @@ #include "r_sky.h" #include "r_utility.h" #include "a_pickups.h" -#include "a_corona.h" #include "d_player.h" #include "g_levellocals.h" #include "events.h" @@ -57,6 +56,8 @@ #include "hw_material.h" #include "hw_dynlightdata.h" #include "hw_renderstate.h" +#include "hw_drawcontext.h" +#include "quaternion.h" extern TArray sprites; extern TArray SpriteFrames; @@ -84,6 +85,7 @@ CVAR(Float, gl_sclipfactor, 1.8f, CVAR_ARCHIVE) CVAR(Int, gl_particles_style, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // 0 = square, 1 = round, 2 = smooth CVAR(Int, gl_billboard_mode, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, gl_billboard_faces_camera, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, hw_force_cambbpref, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, gl_billboard_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR(Int, gl_fuzztype, 8, CVAR_ARCHIVE) { @@ -104,9 +106,7 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) bool additivefog = false; bool foglayer = false; int rel = fullbright ? 0 : getExtraLight(); - auto &vp = di->Viewpoint; - - const bool UseActorLight = (actor && actor->LightLevel > -1); + auto &vp = di->Viewpoint; if (translucent) { @@ -145,7 +145,7 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) if (!Colormap.FadeColor.isBlack()) { float dist = Dist2(vp.Pos.X, vp.Pos.Y, x, y); - int fogd = di->GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.FogDensity, Colormap.BlendFactor); + int fogd = GetFogDensity(di->Level, di->lightmode, lightlevel, Colormap.FadeColor, Colormap.FogDensity, Colormap.BlendFactor); // this value was determined by trial and error and is scale dependent! float factor = 0.05f + exp(-fogd * dist / 62500.f); @@ -190,7 +190,7 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetObjectColor(finalcol); state.SetAddColor(cursec->AdditiveColors[sector_t::sprites] | 0xff000000); } - di->SetColor(state, lightlevel, rel, di->isFullbrightScene(), Colormap, trans); + SetColor(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), Colormap, trans); } @@ -217,7 +217,7 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) else RenderStyle.BlendOp = STYLEOP_Fuzz; // subtractive with models is not going to work. } - if (!foglayer) di->SetFog(state, foglevel, rel, di->isFullbrightScene(), &Colormap, additivefog); + if (!foglayer) SetFog(state, di->Level, di->lightmode, foglevel, rel, di->isFullbrightScene(), &Colormap, additivefog, di->drawctx->portalState.inskybox); else { state.EnableFog(false); @@ -258,10 +258,10 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) thiscm.Decolorize(); } - di->SetColor(state, thisll, rel, di->isFullbrightScene(), thiscm, trans); + SetColor(state, di->Level, di->lightmode, thisll, rel, di->isFullbrightScene(), thiscm, trans); if (!foglayer) { - di->SetFog(state, thislight, rel, di->isFullbrightScene(), &thiscm, additivefog); + SetFog(state, di->Level, di->lightmode, thislight, rel, di->isFullbrightScene(), &thiscm, additivefog, di->drawctx->portalState.inskybox); } SetSplitPlanes(state, *topplane, *lowplane); } @@ -274,11 +274,8 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) { state.SetNormal(0, 0, 0); + CreateVertices(di, state); - if (screen->BuffersArePersistent()) - { - CreateVertices(di, state); - } if (polyoffset) { state.SetDepthBias(-1, -128); @@ -289,7 +286,7 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) if (foglayer) { // If we get here we know that we have colored fog and no fixed colormap. - di->SetFog(state, foglevel, rel, false, &Colormap, additivefog); + SetFog(state, di->Level, di->lightmode, foglevel, rel, false, &Colormap, additivefog, di->drawctx->portalState.inskybox); state.SetTextureMode(TM_FOGLAYER); state.SetRenderStyle(STYLE_Translucent); state.Draw(DT_TriangleStrip, vertexindex, 4); @@ -351,8 +348,8 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetDynLight(0, 0, 0); state.SetRenderStyle(STYLE_Normal); state.SetTextureMode(TM_NORMAL); - di->SetFog(state, 0, 0, false, &Colormap, true); - di->SetColor(state, 255, 0, true, Colormap, true); + SetFog(state, di->Level, di->lightmode, 0, 0, false, &Colormap, true, di->drawctx->portalState.inskybox); + SetColor(state, di->Level, di->lightmode, 255, 0, true, Colormap, true); state.EnableTexture(false); int scales[12][6] = @@ -394,19 +391,32 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) // //========================================================================== -bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) +void HandleSpriteOffsets(Matrix3x4 *mat, const FRotator *HW, FVector2 *offset, bool XYBillboard) { - const auto &HWAngles = di->Viewpoint.HWAngles; + FAngle zero = FAngle::fromDeg(0); + FAngle pitch = (XYBillboard) ? HW->Pitch : zero; + FAngle yaw = FAngle::fromDeg(270.) - HW->Yaw; + + FQuaternion quat = FQuaternion::FromAngles(yaw, pitch, zero); + FVector3 sideVec = quat * FVector3(0, 1, 0); + FVector3 upVec = quat * FVector3(0, 0, 1); + FVector3 res = sideVec * offset->X + upVec * offset->Y; + mat->Translate(res.X, res.Z, res.Y); +} + +bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) +{ + FVector3 center = FVector3((x1 + x2) * 0.5, (y1 + y2) * 0.5, (z1 + z2) * 0.5); + const auto& HWAngles = di->Viewpoint.HWAngles; + Matrix3x4 mat; if (actor != nullptr && (actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE) { - Matrix3x4 mat; - mat.MakeIdentity(); - // [MC] Rotate around the center or offsets given to the sprites. // Counteract any existing rotations, then rotate the angle. // Tilt the actor up or down based on pitch (increase 'somersaults' forward). // Then counteract the roll and DO A BARREL ROLL. + mat.MakeIdentity(); FAngle pitch = FAngle::fromDeg(-Angles.Pitch.Degrees()); pitch.Normalized180(); @@ -416,12 +426,9 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) if (actor->renderflags & RF_ROLLCENTER) { - float cx = (x1 + x2) * 0.5; - float cy = (y1 + y2) * 0.5; - - mat.Translate(cx - x, 0, cy - y); + mat.Translate(center.X - x, 0, center.Y - y); mat.Rotate(0, 1, 0, - Angles.Roll.Degrees()); - mat.Translate(-cx, -z, -cy); + mat.Translate(-center.X, -z, -center.Y); } else { @@ -437,47 +444,56 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) } // [BB] Billboard stuff - const bool drawWithXYBillboard = ((particle && gl_billboard_particles && !(particle->flags & PT_NOXYBILLBOARD)) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD) + const bool drawWithXYBillboard = ((particle && gl_billboard_particles && !(particle->flags & SPF_NO_XY_BILLBOARD)) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD) //&& di->mViewActor != nullptr && (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD)))); - const bool drawBillboardFacingCamera = gl_billboard_faces_camera; + const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera : + (gl_billboard_faces_camera && (actor && !(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA))) + || !!(actor && actor->renderflags2 & RF2_BILLBOARDFACECAMERA); + // [Nash] has +ROLLSPRITE const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE); - - const bool drawRollParticle = (particle != nullptr && particle->flags & PT_DOROLL); - + const bool drawRollParticle = (particle != nullptr && particle->flags & SPF_ROLL); + const bool doRoll = (drawRollSpriteActor || drawRollParticle); // [fgsfds] check sprite type mask uint32_t spritetype = (uint32_t)-1; if (actor != nullptr) spritetype = actor->renderflags & RF_SPRITETYPEMASK; // [Nash] is a flat sprite - const bool isFlatSprite = (actor != nullptr) && (spritetype == RF_WALLSPRITE || spritetype == RF_FLATSPRITE); + const bool isWallSprite = (actor != nullptr) && (spritetype == RF_WALLSPRITE); const bool useOffsets = (actor != nullptr) && !(actor->renderflags & RF_ROLLCENTER); + FVector2 offset = FVector2( offx, offy ); + float xx = -center.X + x; + float yy = -center.Y + y; + float zz = -center.Z + z; // [Nash] check for special sprite drawing modes - if (drawWithXYBillboard || drawBillboardFacingCamera || drawRollSpriteActor || drawRollParticle || isFlatSprite) + if (drawWithXYBillboard || isWallSprite) { - // Compute center of sprite - float xcenter = (x1 + x2)*0.5; - float ycenter = (y1 + y2)*0.5; - float zcenter = (z1 + z2)*0.5; - float xx = -xcenter + x; - float zz = -zcenter + z; - float yy = -ycenter + y; - Matrix3x4 mat; + float pixelstretch = 1.2; + if (actor && actor->Level) + pixelstretch = actor->Level->pixelstretch; + else if (particle && particle->subsector && particle->subsector->sector && particle->subsector->sector->Level) + pixelstretch = particle->subsector->sector->Level->pixelstretch; + mat.MakeIdentity(); - mat.Translate(xcenter, zcenter, ycenter); // move to sprite center + mat.Translate(center.X, center.Z, center.Y); // move to sprite center + mat.Scale(1.0, 1.0/pixelstretch, 1.0); // unstretch sprite by level aspect ratio - // Order of rotations matters. Perform yaw rotation (Y, face camera) before pitch (X, tilt up/down). - if (drawBillboardFacingCamera && !isFlatSprite) + // [MC] Sprite offsets. + if (!offset.isZero()) + HandleSpriteOffsets(&mat, &HWAngles, &offset, true); + + // Order of rotations matters. Perform yaw rotation (Y, face camera) before pitch (X, tilt up/down). + if (drawBillboardFacingCamera && !isWallSprite) { // [CMB] Rotate relative to camera XY position, not just camera direction, // which is nicer in VR - float xrel = xcenter - vp->X; - float yrel = ycenter - vp->Y; - float absAngleDeg = RAD2DEG(atan2(-yrel, xrel)); + float xrel = center.X - vp->X; + float yrel = center.Y - vp->Y; + float absAngleDeg = atan2(-yrel, xrel) * (180 / M_PI); float counterRotationDeg = 270. - HWAngles.Yaw.Degrees(); // counteracts existing sprite rotation float relAngleDeg = counterRotationDeg + absAngleDeg; @@ -485,27 +501,24 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) } // [fgsfds] calculate yaw vectors - float yawvecX = 0, yawvecY = 0, rollDegrees = 0; + float rollDegrees = doRoll ? Angles.Roll.Degrees() : 0; float angleRad = (FAngle::fromDeg(270.) - HWAngles.Yaw).Radians(); - if (actor || drawRollParticle) rollDegrees = Angles.Roll.Degrees(); - if (isFlatSprite) - { - yawvecX = Angles.Yaw.Cos(); - yawvecY = Angles.Yaw.Sin(); - } // [fgsfds] Rotate the sprite about the sight vector (roll) - if (spritetype == RF_WALLSPRITE) + if (isWallSprite) { + float yawvecX = Angles.Yaw.Cos(); + float yawvecY = Angles.Yaw.Sin(); mat.Rotate(0, 1, 0, 0); if (drawRollSpriteActor) { - if (useOffsets) mat.Translate(xx, zz, yy); + + if (useOffsets) mat.Translate(xx, zz, yy); mat.Rotate(yawvecX, 0, yawvecY, rollDegrees); if (useOffsets) mat.Translate(-xx, -zz, -yy); } } - else if (drawRollSpriteActor || drawRollParticle) + else if (doRoll) { if (useOffsets) mat.Translate(xx, zz, yy); if (drawWithXYBillboard) @@ -523,7 +536,9 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) mat.Rotate(-sin(angleRad), 0, cos(angleRad), -HWAngles.Pitch.Degrees()); } - mat.Translate(-xcenter, -zcenter, -ycenter); // retreat from sprite center + mat.Scale(1.0, pixelstretch, 1.0); // stretch sprite by level aspect ratio + mat.Translate(-center.X, -center.Z, -center.Y); // retreat from sprite center + v[0] = mat * FVector3(x1, z1, y1); v[1] = mat * FVector3(x2, z1, y2); v[2] = mat * FVector3(x1, z2, y1); @@ -531,10 +546,40 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) } else // traditional "Y" billboard mode { - v[0] = FVector3(x1, z1, y1); - v[1] = FVector3(x2, z1, y2); - v[2] = FVector3(x1, z2, y1); - v[3] = FVector3(x2, z2, y2); + if (doRoll || !offset.isZero()) + { + mat.MakeIdentity(); + + if (!offset.isZero()) + HandleSpriteOffsets(&mat, &HWAngles, &offset, false); + + if (doRoll) + { + // Compute center of sprite + float angleRad = (FAngle::fromDeg(270.) - HWAngles.Yaw).Radians(); + float rollDegrees = Angles.Roll.Degrees(); + + mat.Translate(center.X, center.Z, center.Y); + if (useOffsets) mat.Translate(xx, zz, yy); + mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees); + if (useOffsets) mat.Translate(-xx, -zz, -yy); + mat.Translate(-center.X, -center.Z, -center.Y); + } + + v[0] = mat * FVector3(x1, z1, y1); + v[1] = mat * FVector3(x2, z1, y2); + v[2] = mat * FVector3(x1, z2, y1); + v[3] = mat * FVector3(x2, z2, y2); + + } + else + { + v[0] = FVector3(x1, z1, y1); + v[1] = FVector3(x2, z1, y2); + v[2] = FVector3(x1, z2, y1); + v[3] = FVector3(x2, z2, y2); + } + } return false; } @@ -548,19 +593,15 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) inline void HWSprite::PutSprite(HWDrawInfo *di, FRenderState& state, bool translucent) { // That's a lot of checks... - if (modelframe && !modelframe->isVoxel && !(modelframe->flags & MDL_NOPERPIXELLIGHTING) && RenderStyle.BlendOp != STYLEOP_Shadow && gl_light_sprites && di->Level->HasDynamicLights && !di->isFullbrightScene() && !fullbright) + if (modelframe && !modelframe->isVoxel && !(modelframeflags & MDL_NOPERPIXELLIGHTING) && RenderStyle.BlendOp != STYLEOP_Shadow && gl_light_sprites && di->Level->HasDynamicLights && !di->isFullbrightScene() && !fullbright) { - hw_GetDynModelLight(actor, lightdata); + hw_GetDynModelLight(di->drawctx, actor, lightdata); dynlightindex = state.UploadLights(lightdata); } else dynlightindex = -1; vertexindex = -1; - if (!screen->BuffersArePersistent()) - { - CreateVertices(di, state); - } di->AddSprite(this, translucent); } @@ -755,15 +796,28 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto // [ZZ] allow CustomSprite-style direct picnum specification bool isPicnumOverride = thing->picnum.isValid(); + bool isFogball = thing->IsKindOf(NAME_Fogball); + // Don't waste time projecting sprites that are definitely not visible. - if ((thing->sprite == 0 && !isPicnumOverride) || !thing->IsVisibleToPlayer() || ((thing->renderflags & RF_MASKROTATION) && !thing->IsInsideVisibleAngles())) + if ((thing->sprite == 0 && !isPicnumOverride && !isFogball) || !thing->IsVisibleToPlayer() || ((thing->renderflags & RF_MASKROTATION) && !thing->IsInsideVisibleAngles())) + { + return; + } + + if (isFogball) { + Fogball fogball; + fogball.Position = FVector3(thing->Pos()); + fogball.Radius = (float)thing->args[3]; + fogball.Color = FVector3(powf(thing->args[0] * (1.0f / 255.0f), 2.2), powf(thing->args[1] * (1.0f / 255.0f), 2.2), powf(thing->args[2] * (1.0f / 255.0f), 2.2)); + fogball.Fog = (float)thing->Alpha; + di->Fogballs.Push(fogball); return; } if (thing->IsKindOf(NAME_Corona)) { - di->Coronas.Push(static_cast(thing)); + di->Coronas.Push(thing); return; } @@ -809,13 +863,23 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto { return; } - // Some added checks if the camera actor is not supposed to be seen. It can happen that some portal setup has this actor in view in which case it may not be skipped here if (viewmaster == camera && !vp.showviewer) { + if (vp.bForceNoViewer || (viewmaster->player && viewmaster->player->crossingPortal)) return; DVector3 vieworigin = viewmaster->Pos(); if (thruportal == 1) vieworigin += di->Level->Displacements.getOffset(viewmaster->Sector->PortalGroup, sector->PortalGroup); if (fabs(vieworigin.X - vp.ActorPos.X) < 2 && fabs(vieworigin.Y - vp.ActorPos.Y) < 2) return; + + // Necessary in order to prevent sprite pop-ins with viewpos and models. + auto* sec = viewmaster->Sector; + if (sec && !sec->PortalBlocksMovement(sector_t::ceiling)) + { + double zh = sec->GetPortalPlaneZ(sector_t::ceiling); + double top = (viewmaster->player ? max(viewmaster->player->viewz, viewmaster->Top()) + 1 : viewmaster->Top()); + if (viewmaster->Z() < zh && top >= zh) + return; + } } // Thing is invisible if close to the camera. if (viewmaster->renderflags & RF_MAYBEINVISIBLE) @@ -825,20 +889,15 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto if (fabs(viewpos.X - vp.Pos.X) < 32 && fabs(viewpos.Y - vp.Pos.Y) < 32) return; } + modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing, spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); + modelframeflags = modelframe ? modelframe->getFlags(thing->modelData) : 0; + // Too close to the camera. This doesn't look good if it is a sprite. - if (fabs(thingpos.X - vp.Pos.X) < 2 && fabs(thingpos.Y - vp.Pos.Y) < 2) + if (fabs(thingpos.X - vp.Pos.X) < 2 && fabs(thingpos.Y - vp.Pos.Y) < 2 + && vp.Pos.Z >= thingpos.Z - 2 && vp.Pos.Z <= thingpos.Z + thing->Height + 2 + && !thing->Vel.isZero() && !modelframe) // exclude vertically moving objects from this check. { - if (vp.Pos.Z >= thingpos.Z - 2 && vp.Pos.Z <= thingpos.Z + thing->Height + 2) - { - // exclude vertically moving objects from this check. - if (!thing->Vel.isZero()) - { - if (!FindModelFrame(thing->GetClass(), spritenum, thing->frame, false)) - { - return; - } - } - } + return; } // don't draw first frame of a player missile @@ -858,7 +917,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto if (thruportal != 2 && di->mClipPortal != nullptr) { - int clipres = di->mClipPortal->ClipPoint(thingpos); + int clipres = di->mClipPortal->ClipPoint(thingpos.XY()); if (clipres == PClip_InFront) return; } // disabled because almost none of the actual game code is even remotely prepared for this. If desired, use the INTERPOLATE flag. @@ -871,7 +930,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto { // This cannot create a copy in the fake sector cache because it'd interfere with the main thread, so provide a local buffer for the copy. // Adding synchronization for this one case would cost more than it might save if the result here could be cached. - rendersector = hw_FakeFlat(thing->Sector, in_area, false, &rs); + rendersector = hw_FakeFlat(di->drawctx, thing->Sector, in_area, false, &rs); } else { @@ -898,14 +957,11 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto z += fz; } - modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->modelData != nullptr ? thing->modelData->modelDef != NAME_None ? PClass::FindActor(thing->modelData->modelDef) : thing->GetClass() : thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); - // don't bother drawing sprite shadows if this is a model (it will never look right) if (modelframe && isSpriteShadow) { return; } - if (!modelframe) { bool mirror = false; @@ -971,6 +1027,9 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto if (!tex || !tex->isValid()) return; auto& spi = tex->GetSpritePositioning(type == RF_FACESPRITE); + offx = (float)thing->GetSpriteOffset(false); + offy = (float)thing->GetSpriteOffset(true); + vt = spi.GetSpriteVT(); vb = spi.GetSpriteVB(); if (thing->renderflags & RF_YFLIP) std::swap(vt, vb); @@ -993,7 +1052,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto ur = spi.GetSpriteUL(); } - texture = TexMan.GetGameTexture(patch, false); + texture = tex; if (!texture || !texture->isValid()) return; @@ -1002,10 +1061,9 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 : sprscale.Y); - float SpriteOffY = thing->SpriteOffset.Y; - float rightfac = -r.left - thing->SpriteOffset.X; + float rightfac = -r.left; float leftfac = rightfac - r.width; - z1 = z - r.top - SpriteOffY; + z1 = z - r.top; z2 = z1 - r.height; float spriteheight = sprscale.Y * r.height; @@ -1013,7 +1071,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto // Tests show that this doesn't look good for many decorations and corpses if (spriteheight > 0 && gl_spriteclip > 0 && (thing->renderflags & RF_SPRITETYPEMASK) == RF_FACESPRITE) { - PerformSpriteClipAdjustment(thing, thingpos, spriteheight); + PerformSpriteClipAdjustment(thing, thingpos.XY(), spriteheight); } switch (spritetype) @@ -1031,7 +1089,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto } case RF_FLATSPRITE: { - float bottomfac = -r.top - SpriteOffY; + float bottomfac = -r.top; float topfac = bottomfac - r.height; x1 = x + leftfac; @@ -1041,8 +1099,8 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto // [MC] Counteract in case of any potential problems. Tests so far haven't // shown any outstanding issues but that doesn't mean they won't appear later // when more features are added. - z1 += SpriteOffY; - z2 += SpriteOffY; + z1 += offy; + z2 += offy; break; } case RF_WALLSPRITE: @@ -1183,7 +1241,11 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto // This is a non-translucent sprite (i.e. STYLE_Normal or equivalent) trans = 1.f; - if (!gl_sprite_blend || modelframe || (thing->renderflags & (RF_FLATSPRITE | RF_WALLSPRITE)) || gl_billboard_faces_camera) + if (!gl_sprite_blend || modelframe || + (thing->renderflags & (RF_FLATSPRITE | RF_WALLSPRITE)) || + (hw_force_cambbpref ? gl_billboard_faces_camera : + (gl_billboard_faces_camera && !(thing->renderflags2 & RF2_BILLBOARDNOFACECAMERA)) || + thing->renderflags2 & RF2_BILLBOARDFACECAMERA)) { RenderStyle.SrcAlpha = STYLEALPHA_One; RenderStyle.DestAlpha = STYLEALPHA_Zero; @@ -1266,24 +1328,12 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto if (thing->Sector->e->XFloor.lightlist.Size() != 0 && !di->isFullbrightScene() && !fullbright && RenderStyle.BlendOp != STYLEOP_Shadow && RenderStyle.BlendOp != STYLEOP_RevSub) { - if (screen->hwcaps & RFL_NO_CLIP_PLANES) // on old hardware we are rather limited... - { - lightlist = nullptr; - if (!drawWithXYBillboard && !modelframe) - { - SplitSprite(di, state, thing->Sector, hw_styleflags != STYLEHW_Solid); - } - } - else - { - lightlist = &thing->Sector->e->XFloor.lightlist; - } + lightlist = &thing->Sector->e->XFloor.lightlist; } else { lightlist = nullptr; } - PutSprite(di, state, hw_styleflags != STYLEHW_Solid); rendered_sprites++; } @@ -1295,18 +1345,33 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto // //========================================================================== -void HWSprite::ProcessParticle (HWDrawInfo *di, FRenderState& state, particle_t *particle, sector_t *sector)//, int shade, int fakeside) +void HWSprite::ProcessParticle(HWDrawInfo *di, FRenderState& state, particle_t *particle, sector_t *sector, DVisualThinker *spr)//, int shade, int fakeside) { - if (particle->alpha==0) return; + if (!particle || particle->alpha <= 0) + return; - lightlevel = hw_ClampLight(sector->GetSpriteLight()); + if (spr && spr->PT.texture.isNull()) + return; + + lightlevel = hw_ClampLight(spr ? spr->GetLightLevel(sector) : sector->GetSpriteLight()); foglevel = (uint8_t)clamp(sector->lightlevel, 0, 255); + trans = particle->alpha; + OverrideShader = 0; + modelframe = nullptr; + texture = nullptr; + topclip = LARGE_VALUE; + bottomclip = -LARGE_VALUE; + index = 0; + actor = nullptr; + this->particle = particle; + fullbright = particle->flags & SPF_FULLBRIGHT; + if (di->isFullbrightScene()) { Colormap.Clear(); } - else if (!particle->bright) + else if (!(particle->flags & SPF_FULLBRIGHT)) { TArray & lightlist=sector->e->XFloor.lightlist; double lightbottom; @@ -1336,8 +1401,6 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, FRenderState& state, particle_t Colormap.ClearColor(); } - trans=particle->alpha; - if(particle->style != STYLE_None) { RenderStyle = particle->style; @@ -1347,99 +1410,181 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, FRenderState& state, particle_t RenderStyle = STYLE_Translucent; } - OverrideShader = 0; - ThingColor = particle->color; ThingColor.a = 255; + const auto& vp = di->Viewpoint; - modelframe=nullptr; - texture=nullptr; - topclip = LARGE_VALUE; - bottomclip = -LARGE_VALUE; - index = 0; - - bool has_texture = !particle->texture.isNull(); - - int particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles + double timefrac = vp.TicFrac; + if (paused || (di->Level->isFrozen() && !(particle->flags & SPF_NOTIMEFREEZE))) + timefrac = 0.; - // [BB] Load the texture for round or smooth particles - if (particle_style) + if (spr) { - FTextureID lump; - if (particle_style == 1) - { - lump = TexMan.glPart2; - } - else if (particle_style == 2) + AdjustVisualThinker(di, spr, sector); + } + else + { + bool has_texture = particle->texture.isValid(); + bool custom_animated_texture = (particle->flags & SPF_LOCAL_ANIM) && particle->animData.ok; + + int particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles + + // [BB] Load the texture for round or smooth particles + if (particle_style) { - lump = has_texture ? particle -> texture : TexMan.glPart; + FTextureID lump; + if (particle_style == 1) + { + lump = TexMan.glPart2; + } + else if (particle_style == 2) + { + if(custom_animated_texture) + { + lump = TexAnim.UpdateStandaloneAnimation(particle->animData, di->Level->maptime + timefrac); + } + else if(has_texture) + { + lump = particle->texture; + } + else + { + lump = TexMan.glPart; + } + } + else + { + lump.SetNull(); + } + + if (lump.isValid()) + { + translation = NO_TRANSLATION; + + ul = vt = 0; + ur = vb = 1; + + texture = TexMan.GetGameTexture(lump, !custom_animated_texture); + } } - else lump.SetNull(); - if (lump.isValid()) + + float xvf = (particle->Vel.X) * timefrac; + float yvf = (particle->Vel.Y) * timefrac; + float zvf = (particle->Vel.Z) * timefrac; + + offx = 0.f; + offy = 0.f; + + x = float(particle->Pos.X) + xvf; + y = float(particle->Pos.Y) + yvf; + z = float(particle->Pos.Z) + zvf; + + if(particle->flags & SPF_ROLL) { - translation = 0; - //auto tex = TexMan.GetGameTexture(lump, false); - - ul = 0; - ur = 1; - vt = 0; - vb = 1; - texture = TexMan.GetGameTexture(lump, true); + float rvf = (particle->RollVel) * timefrac; + Angles.Roll = TAngle::fromDeg(particle->Roll + rvf); } + + float factor; + if (particle_style == 1) factor = 1.3f / 7.f; + else if (particle_style == 2) factor = 2.5f / 7.f; + else factor = 1 / 7.f; + float scalefac=particle->size * factor; + + float viewvecX = vp.ViewVector.X * scalefac; + float viewvecY = vp.ViewVector.Y * scalefac; + + x1=x+viewvecY; + x2=x-viewvecY; + y1=y-viewvecX; + y2=y+viewvecX; + z1=z-scalefac; + z2=z+scalefac; + + depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin); + + // [BB] Translucent particles have to be rendered without the alpha test. + if (particle_style != 2 && trans>=1.0f-FLT_EPSILON) hw_styleflags = STYLEHW_Solid; + else hw_styleflags = STYLEHW_NoAlphaTest; } - const auto &vp = di->Viewpoint; + if (sector->e->XFloor.lightlist.Size() != 0 && !di->isFullbrightScene() && !fullbright) + lightlist = §or->e->XFloor.lightlist; + else + lightlist = nullptr; + + PutSprite(di, state, hw_styleflags != STYLEHW_Solid); + rendered_sprites++; +} + +// [MC] VisualThinkers are to be rendered akin to actor sprites. The reason this whole system +// is hitching a ride on particle_t is because of the large number of checks with +// HWSprite elsewhere in the draw lists. +void HWSprite::AdjustVisualThinker(HWDrawInfo* di, DVisualThinker* spr, sector_t* sector) +{ + translation = spr->Translation; + + const auto& vp = di->Viewpoint; double timefrac = vp.TicFrac; - if (paused || di->Level->isFrozen()) + + if (paused || spr->isFrozen()) timefrac = 0.; - float xvf = (particle->Vel.X) * timefrac; - float yvf = (particle->Vel.Y) * timefrac; - float zvf = (particle->Vel.Z) * timefrac; + + bool custom_anim = ((spr->PT.flags & SPF_LOCAL_ANIM) && spr->PT.animData.ok); - x = float(particle->Pos.X) + xvf; - y = float(particle->Pos.Y) + yvf; - z = float(particle->Pos.Z) + zvf; + texture = TexMan.GetGameTexture( + custom_anim + ? TexAnim.UpdateStandaloneAnimation(spr->PT.animData, di->Level->maptime + timefrac) + : spr->PT.texture, !custom_anim); - if(particle->flags & PT_DOROLL) + if (spr->bDontInterpolate) + timefrac = 0.; + + FVector3 interp = spr->InterpolatedPosition(timefrac); + x = interp.X; + y = interp.Y; + z = interp.Z; + + offx = (float)spr->GetOffset(false); + offy = (float)spr->GetOffset(true); + + if (spr->PT.flags & SPF_ROLL) + Angles.Roll = TAngle::fromDeg(spr->InterpolatedRoll(timefrac)); + + auto& spi = texture->GetSpritePositioning(0); + + vt = spi.GetSpriteVT(); + vb = spi.GetSpriteVB(); + ul = spi.GetSpriteUR(); + ur = spi.GetSpriteUL(); + + auto r = spi.GetSpriteRect(); + r.Scale(spr->Scale.X, spr->Scale.Y); + + if (spr->bXFlip) { - float rvf = (particle->RollVel) * timefrac; - Angles.Roll = TAngle::fromDeg(particle->Roll + rvf); + std::swap(ul,ur); + r.left = -r.width - r.left; // mirror the sprite's x-offset } - - float factor; - if (particle_style == 1) factor = 1.3f / 7.f; - else if (particle_style == 2) factor = 2.5f / 7.f; - else factor = 1 / 7.f; - float scalefac=particle->size * factor; + if (spr->bYFlip) std::swap(vt,vb); float viewvecX = vp.ViewVector.X; float viewvecY = vp.ViewVector.Y; + float rightfac = -r.left; + float leftfac = rightfac - r.width; - x1=x+viewvecY*scalefac; - x2=x-viewvecY*scalefac; - y1=y-viewvecX*scalefac; - y2=y+viewvecX*scalefac; - z1=z-scalefac; - z2=z+scalefac; + x1 = x - viewvecY * leftfac; + x2 = x - viewvecY * rightfac; + y1 = y + viewvecX * leftfac; + y2 = y + viewvecX * rightfac; + z1 = z - r.top; + z2 = z1 - r.height; depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin); - actor=nullptr; - this->particle=particle; - fullbright = !!particle->bright; - // [BB] Translucent particles have to be rendered without the alpha test. - if (particle_style != 2 && trans>=1.0f-FLT_EPSILON) hw_styleflags = STYLEHW_Solid; - else hw_styleflags = STYLEHW_NoAlphaTest; - - if (sector->e->XFloor.lightlist.Size() != 0 && !di->isFullbrightScene() && !fullbright) - lightlist = §or->e->XFloor.lightlist; - else - lightlist = nullptr; - - PutSprite(di, state, hw_styleflags != STYLEHW_Solid); - rendered_sprites++; + hw_styleflags = STYLEHW_NoAlphaTest; } //========================================================================== @@ -1518,11 +1663,11 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area, // [Nash] draw sprite shadow if (R_ShouldDrawSpriteShadow(th)) { - spr.Process(this, state, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2, true); + spr.Process(this, state, th, hw_FakeFlat(drawctx, th->Sector, in_area, false, &fakesector), in_area, 2, true); } // This is called from the worker thread and must not alter the fake sector cache. - spr.Process(this, state, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2); + spr.Process(this, state, th, hw_FakeFlat(drawctx, th->Sector, in_area, false, &fakesector), in_area, 2); th->Angles.Yaw = savedangle; th->SetXYZ(savedpos); th->Prev -= newpos - savedpos; diff --git a/src/rendering/hwrenderer/scene/hw_walldispatcher.h b/src/rendering/hwrenderer/scene/hw_walldispatcher.h new file mode 100644 index 0000000000..23d9345348 --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_walldispatcher.h @@ -0,0 +1,80 @@ +#pragma once + +struct HWMissing +{ + side_t* side; + subsector_t* sub; + double plane; +}; + +struct HWMeshHelper +{ + TArray list; + TArray translucent; + TArray portals; + TArray lower; + TArray upper; +}; + + +struct HWWallDispatcher +{ + FLevelLocals* Level; + HWDrawInfo* di; + HWMeshHelper* mh; + ELightMode lightmode; + + HWWallDispatcher(HWDrawInfo* info) + { + Level = info->Level; + di = info; + mh = nullptr; + lightmode = info->lightmode; + } + + HWWallDispatcher(FLevelLocals* lev, HWMeshHelper* help, ELightMode lm) + { + Level = lev; + di = nullptr; + mh = help; + lightmode = lm; + } + + void AddUpperMissingTexture(side_t* side, subsector_t* sub, float height) + { + if (di) di->AddUpperMissingTexture(side, sub, height); + else + { + mh->upper.Reserve(1); + mh->upper.Last() = { side, sub, height }; + } + } + void AddLowerMissingTexture(side_t* side, subsector_t* sub, float height) + { + if (di) di->AddLowerMissingTexture(side, sub, height); + else + { + mh->lower.Reserve(1); + mh->lower.Last() = { side, sub, height }; + } + } + + bool isFullbrightScene() + { + // The mesh builder cannot know this and must treat everything as not fullbright. + return di && di->isFullbrightScene(); + } + + void AddWall(HWWall* wal) + { + if (di) di->AddWall(wal); + else if (!(wal->flags & HWWall::HWF_TRANSLUCENT)) mh->list.Push(*wal); + else mh->translucent.Push(*wal); + } + + void AddPortal(HWWall* wal) + { + mh->portals.Push(*wal); + } + +}; diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 8bb7a0a78c..fa4c0adfa3 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -37,12 +37,13 @@ #include "hw_cvars.h" #include "hw_clock.h" #include "hw_lighting.h" +#include "hw_drawcontext.h" #include "hwrenderer/scene/hw_drawinfo.h" #include "hwrenderer/scene/hw_drawstructs.h" #include "hwrenderer/scene/hw_portal.h" #include "hw_renderstate.h" #include "hw_skydome.h" - +#include "hw_walldispatcher.h" void SetGlowPlanes(FRenderState &state, const secplane_t& top, const secplane_t& bottom) { @@ -79,7 +80,7 @@ void SetSplitPlanes(FRenderState& state, const secplane_t& top, const secplane_t // //========================================================================== -void HWWall::RenderWall(HWDrawInfo *di, FRenderState &state, int textured) +void HWWall::RenderWall(FRenderState &state, int textured) { assert(vertcount > 0); state.SetLightIndex(dynlightindex); @@ -93,17 +94,17 @@ void HWWall::RenderWall(HWDrawInfo *di, FRenderState &state, int textured) // //========================================================================== -void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) +void HWWall::RenderFogBoundary(HWWallDispatcher*di, FRenderState &state) { if (gl_fogmode && !di->isFullbrightScene()) { int rel = rellight + getExtraLight(); state.EnableDrawBufferAttachments(false); - di->SetFog(state, lightlevel, rel, false, &Colormap, false); + SetFog(state, di->Level, di->lightmode, lightlevel, rel, false, &Colormap, false, di->di ? di->di->drawctx->portalState.inskybox : false); state.SetEffect(EFF_FOGBOUNDARY); state.AlphaFunc(Alpha_GEqual, 0.f); state.SetDepthBias(-1, -128); - RenderWall(di, state, HWWall::RWF_BLANK); + RenderWall(state, HWWall::RWF_BLANK); state.ClearDepthBias(); state.SetEffect(EFF_NONE); state.EnableDrawBufferAttachments(true); @@ -116,7 +117,7 @@ void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) // // //========================================================================== -void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) +void HWWall::RenderMirrorSurface(HWWallDispatcher*di, FRenderState &state) { if (!TexMan.mirrorTexture.isValid()) return; @@ -124,16 +125,16 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) // Use sphere mapping for this state.SetEffect(EFF_SPHEREMAP); - di->SetColor(state, lightlevel, 0, di->isFullbrightScene(), Colormap, 0.1f); - di->SetFog(state, lightlevel, 0, di->isFullbrightScene(), &Colormap, true); + SetColor(state, di->Level, di->lightmode, lightlevel, 0, di->isFullbrightScene(), Colormap, 0.1f); + SetFog(state, di->Level, di->lightmode, lightlevel, 0, di->isFullbrightScene(), &Colormap, true, di->di ? di->di->drawctx->portalState.inskybox : false); state.SetRenderStyle(STYLE_Add); state.AlphaFunc(Alpha_Greater, 0); auto tex = TexMan.GetGameTexture(TexMan.mirrorTexture, false); - state.SetMaterial(tex, UF_None, 0, CLAMP_NONE, 0, -1); // do not upscale the mirror texture. + state.SetMaterial(tex, UF_None, 0, CLAMP_NONE, NO_TRANSLATION, -1); // do not upscale the mirror texture. flags &= ~HWWall::HWF_GLOW; - RenderWall(di, state, HWWall::RWF_BLANK); + RenderWall(state, HWWall::RWF_BLANK); state.SetTextureMatrix(VSMatrix::identity()); state.SetEffect(EFF_NONE); @@ -144,9 +145,9 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) // This is drawn in the translucent pass which is done after the decal pass // As a result the decals have to be drawn here, right after the wall they are on, // because the depth buffer won't get set by translucent items. - if (seg->sidedef->AttachedDecals) + if (di->di && seg->sidedef->AttachedDecals) { - DrawDecalsForMirror(di, state, di->Decals[1]); + DrawDecalsForMirror(di->di, state, di->di->Decals[1]); } state.SetRenderStyle(STYLE_Translucent); } @@ -175,7 +176,7 @@ static const uint8_t renderwalltotier[] = CVAR(Bool, hw_npottest, false, 0) #endif -void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) +void HWWall::RenderTexturedWall(HWWallDispatcher*di, FRenderState &state, int rflags) { int tmode = state.GetTextureMode(); int rel = rellight + getExtraLight(); @@ -186,7 +187,7 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) state.SetGlowParams(topglowcolor, bottomglowcolor); SetGlowPlanes(state, frontsector->ceilingplane, frontsector->floorplane); } - state.SetMaterial(texture, UF_Texture, 0, flags & 3, 0, -1); + state.SetMaterial(texture, UF_Texture, 0, flags & 3, NO_TRANSLATION, -1); #ifdef NPOT_EMULATION // Test code, could be reactivated as a compatibility option in the unlikely event that some old vanilla map eve needs it. if (hw_npottest) @@ -211,7 +212,7 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) if (type == RENDERWALL_M2SNF) { - di->SetFog(state, 255, 0, di->isFullbrightScene(), nullptr, false); + SetFog(state, di->Level, di->lightmode, 255, 0, di->isFullbrightScene(), nullptr, false, di->di ? di->di->drawctx->portalState.inskybox : false); } if (type != RENDERWALL_COLOR && seg->sidedef != nullptr) { @@ -259,9 +260,9 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) float absalpha = fabsf(alpha); if (lightlist == nullptr) { - if (type != RENDERWALL_M2SNF) di->SetFog(state, lightlevel, rel, di->isFullbrightScene(), &Colormap, RenderStyle == STYLE_Add); - di->SetColor(state, lightlevel, rel, di->isFullbrightScene(), Colormap, absalpha); - RenderWall(di, state, rflags); + if (type != RENDERWALL_M2SNF) SetFog(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), &Colormap, RenderStyle == STYLE_Add, di->di ? di->di->drawctx->portalState.inskybox : false); + SetColor(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), Colormap, absalpha); + RenderWall(state, rflags); } else { @@ -281,10 +282,10 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) thiscm.FadeColor = Colormap.FadeColor; thiscm.FogDensity = Colormap.FogDensity; CopyFrom3DLight(thiscm, &(*lightlist)[i]); - di->SetColor(state, thisll, rel, false, thiscm, absalpha); - if (type != RENDERWALL_M2SNF) di->SetFog(state, thisll, rel, false, &thiscm, RenderStyle == STYLE_Add); + SetColor(state, di->Level, di->lightmode, thisll, rel, false, thiscm, absalpha); + if (type != RENDERWALL_M2SNF) SetFog(state, di->Level, di->lightmode, thisll, rel, false, &thiscm, RenderStyle == STYLE_Add, di->di ? di->di->drawctx->portalState.inskybox : false); SetSplitPlanes(state, (*lightlist)[i].plane, lowplane); - RenderWall(di, state, rflags); + RenderWall(state, rflags); } if (low1 <= zbottom[0] && low2 <= zbottom[1]) break; } @@ -308,7 +309,7 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) // //========================================================================== -void HWWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state) +void HWWall::RenderTranslucentWall(HWWallDispatcher*di, FRenderState &state) { state.SetRenderStyle(RenderStyle); if (texture) @@ -320,10 +321,10 @@ void HWWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state) else { state.AlphaFunc(Alpha_GEqual, 0.f); - di->SetColor(state, lightlevel, 0, false, Colormap, fabsf(alpha)); - di->SetFog(state, lightlevel, 0, false, &Colormap, RenderStyle == STYLE_Add); + SetColor(state, di->Level, di->lightmode, lightlevel, 0, false, Colormap, fabsf(alpha)); + SetFog(state, di->Level, di->lightmode, lightlevel, 0, false, &Colormap, RenderStyle == STYLE_Add, di->di ? di->di->drawctx->portalState.inskybox : false); state.EnableTexture(false); - RenderWall(di, state, HWWall::RWF_NOSPLIT); + RenderWall(state, HWWall::RWF_NOSPLIT); state.EnableTexture(true); } state.SetRenderStyle(STYLE_Translucent); @@ -334,16 +335,13 @@ void HWWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state) // // //========================================================================== -void HWWall::DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent) +void HWWall::DrawWall(HWWallDispatcher*di, FRenderState &state, bool translucent) { - if (screen->BuffersArePersistent()) + if (di->di && di->Level->HasDynamicLights && !di->isFullbrightScene() && texture != nullptr) { - if (di->Level->HasDynamicLights && !di->isFullbrightScene() && texture != nullptr) - { - SetupLights(di, state, lightdata); - } - MakeVertices(di, state, !!(flags & HWWall::HWF_TRANSLUCENT)); + SetupLights(di->di, state, lightdata); } + MakeVertices(state, !!(flags & HWWall::HWF_TRANSLUCENT)); state.SetNormal(glseg.Normal()); if (!translucent) @@ -375,7 +373,7 @@ void HWWall::DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent) // //========================================================================== -void HWWall::SetupLights(HWDrawInfo *di, FRenderState& state, FDynLightData &lightdata) +void HWWall::SetupLights(HWDrawInfo*di, FRenderState& state, FDynLightData &lightdata) { lightdata.Clear(); @@ -489,58 +487,53 @@ const char HWWall::passflag[] = { // // //========================================================================== -void HWWall::PutWall(HWDrawInfo *di, FRenderState& state, bool translucent) +void HWWall::PutWall(HWWallDispatcher *di, FRenderState& state, bool translucent) { if (texture && texture->GetTranslucency() && passflag[type] == 2) { translucent = true; } + + auto ddi = di->di; if (translucent) { flags |= HWF_TRANSLUCENT; - ViewDistance = (di->Viewpoint.Pos - (seg->linedef->v1->fPos() + seg->linedef->Delta() / 2)).XY().LengthSquared(); - } - - if (di->isFullbrightScene()) - { - // light planes don't get drawn with fullbright rendering - if (texture == NULL) return; - Colormap.Clear(); - } - - if (di->isFullbrightScene() || (Colormap.LightColor.isWhite() && lightlevel == 255)) - { - flags &= ~HWF_GLOW; } - - if (!screen->BuffersArePersistent()) + + if (di->di) { - if (di->Level->HasDynamicLights && !di->isFullbrightScene() && texture != nullptr) + if (translucent) { - SetupLights(di, state, lightdata); + ViewDistance = (ddi->Viewpoint.Pos - (seg->linedef->v1->fPos() + seg->linedef->Delta() / 2)).XY().LengthSquared(); } - MakeVertices(di, state, translucent); - } + if (ddi->isFullbrightScene()) + { + // light planes don't get drawn with fullbright rendering + if (texture == NULL) return; + Colormap.Clear(); + } + if (ddi->isFullbrightScene() || (Colormap.LightColor.isWhite() && lightlevel == 255)) + { + flags &= ~HWF_GLOW; + } - bool solid; - if (passflag[type] == 1) solid = true; - else if (type == RENDERWALL_FFBLOCK) solid = texture && !texture->isMasked(); - else solid = false; + bool solid; + if (passflag[type] == 1) solid = true; + else if (type == RENDERWALL_FFBLOCK) solid = texture && !texture->isMasked(); + else solid = false; - bool hasDecals = solid && seg->sidedef && seg->sidedef->AttachedDecals; - if (hasDecals) - { - // If we want to use the light infos for the decal we cannot delay the creation until the render pass. - if (screen->BuffersArePersistent()) + bool hasDecals = solid && seg->sidedef && seg->sidedef->AttachedDecals; + if (hasDecals) { - if (di->Level->HasDynamicLights && !di->isFullbrightScene() && texture != nullptr) + // If we want to use the light infos for the decal we cannot delay the creation until the render pass. + if (ddi->Level->HasDynamicLights && !ddi->isFullbrightScene() && texture != nullptr) { - SetupLights(di, state, lightdata); + SetupLights(ddi, state, lightdata); } + ProcessDecals(ddi, state); } - ProcessDecals(di, state); } @@ -559,116 +552,123 @@ void HWWall::PutWall(HWDrawInfo *di, FRenderState& state, bool translucent) // //========================================================================== -void HWWall::PutPortal(HWDrawInfo *di, FRenderState& state, int ptype, int plane) +void HWWall::PutPortal(HWWallDispatcher *di, FRenderState& state, int ptype, int plane) { - if (di->MeshBuilding) - return; - HWPortal * portal = nullptr; - MakeVertices(di, state, false); - switch (ptype) + auto ddi = di->di; + if (ddi) { - // portals don't go into the draw list. - // Instead they are added to the portal manager - case PORTALTYPE_HORIZON: - horizon = portalState.UniqueHorizons.Get(horizon); - portal = di->FindPortal(horizon); - if (!portal) + MakeVertices(state, false); + switch (ptype) { - portal = new HWHorizonPortal(&portalState, state, horizon, di->Viewpoint); - di->Portals.Push(portal); - } - portal->AddLine(this); - break; + // portals don't go into the draw list. + // Instead they are added to the portal manager + case PORTALTYPE_HORIZON: + horizon = ddi->drawctx->portalState.UniqueHorizons.Get(horizon); + portal = ddi->FindPortal(horizon); + if (!portal) + { + portal = new HWHorizonPortal(&ddi->drawctx->portalState, state, horizon, ddi->Viewpoint); + ddi->Portals.Push(portal); + } + portal->AddLine(this); + break; - case PORTALTYPE_SKYBOX: - portal = di->FindPortal(secportal); - if (!portal) - { - // either a regular skybox or an Eternity-style horizon - if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(&portalState, secportal); - else + case PORTALTYPE_SKYBOX: + portal = ddi->FindPortal(secportal); + if (!portal) { - portal = new HWSkyboxPortal(&portalState, secportal); - di->Portals.Push(portal); + // either a regular skybox or an Eternity-style horizon + if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(&ddi->drawctx->portalState, secportal); + else + { + portal = new HWSkyboxPortal(&ddi->drawctx->portalState, secportal); + ddi->Portals.Push(portal); + } } - } - portal->AddLine(this); - break; + portal->AddLine(this); + break; - case PORTALTYPE_SECTORSTACK: - portal = di->FindPortal(this->portal); - if (!portal) - { - portal = new HWSectorStackPortal(&portalState, this->portal); - di->Portals.Push(portal); - } - portal->AddLine(this); - break; + case PORTALTYPE_SECTORSTACK: + portal = ddi->FindPortal(this->portal); + if (!portal) + { + portal = new HWSectorStackPortal(&ddi->drawctx->portalState, this->portal); + ddi->Portals.Push(portal); + } + portal->AddLine(this); + break; - case PORTALTYPE_PLANEMIRROR: - if (portalState.PlaneMirrorMode * planemirror->fC() <= 0) - { - planemirror = portalState.UniquePlaneMirrors.Get(planemirror); - portal = di->FindPortal(planemirror); + case PORTALTYPE_PLANEMIRROR: + if (ddi->drawctx->portalState.PlaneMirrorMode * planemirror->fC() <= 0) + { + planemirror = ddi->drawctx->portalState.UniquePlaneMirrors.Get(planemirror); + portal = ddi->FindPortal(planemirror); + if (!portal) + { + portal = new HWPlaneMirrorPortal(&ddi->drawctx->portalState, planemirror); + ddi->Portals.Push(portal); + } + portal->AddLine(this); + } + break; + + case PORTALTYPE_MIRROR: + portal = ddi->FindPortal(seg->linedef); if (!portal) { - portal = new HWPlaneMirrorPortal(&portalState, planemirror); - di->Portals.Push(portal); + portal = new HWMirrorPortal(&ddi->drawctx->portalState, seg->linedef); + ddi->Portals.Push(portal); } portal->AddLine(this); - } - break; + if (gl_mirror_envmap) + { + // draw a reflective layer over the mirror + ddi->AddMirrorSurface(this, state); + } + break; - case PORTALTYPE_MIRROR: - portal = di->FindPortal(seg->linedef); - if (!portal) - { - portal = new HWMirrorPortal(&portalState, seg->linedef); - di->Portals.Push(portal); - } - portal->AddLine(this); - if (gl_mirror_envmap) - { - // draw a reflective layer over the mirror - di->AddMirrorSurface(this, state); - } - break; + case PORTALTYPE_LINETOLINE: + if (!lineportal) + return; + portal = ddi->FindPortal(lineportal); + if (!portal) + { + line_t* otherside = lineportal->lines[0]->mDestination; + if (otherside != nullptr && otherside->portalindex < ddi->Level->linePortals.Size()) + { + ddi->ProcessActorsInPortal(otherside->getPortal()->mGroup, ddi->in_area, state); + } + portal = new HWLineToLinePortal(&ddi->drawctx->portalState, lineportal); + ddi->Portals.Push(portal); + } + portal->AddLine(this); + break; - case PORTALTYPE_LINETOLINE: - if (!lineportal) - return; - portal = di->FindPortal(lineportal); - if (!portal) - { - line_t *otherside = lineportal->lines[0]->mDestination; - if (otherside != nullptr && otherside->portalindex < di->Level->linePortals.Size()) + case PORTALTYPE_SKY: + sky = ddi->drawctx->portalState.UniqueSkies.Get(sky); + portal = ddi->FindPortal(sky); + if (!portal) { - di->ProcessActorsInPortal(otherside->getPortal()->mGroup, di->in_area, state); + portal = new HWSkyPortal(screen->mSkyData, &ddi->drawctx->portalState, sky); + ddi->Portals.Push(portal); } - portal = new HWLineToLinePortal(&portalState, lineportal); - di->Portals.Push(portal); + portal->AddLine(this); + break; } - portal->AddLine(this); - break; + vertcount = 0; - case PORTALTYPE_SKY: - sky = portalState.UniqueSkies.Get(sky); - portal = di->FindPortal(sky); - if (!portal) + if (plane != -1 && portal) { - portal = new HWSkyPortal(screen->mSkyData, &portalState, sky); - di->Portals.Push(portal); + portal->planesused |= (1 << plane); } - portal->AddLine(this); - break; } - vertcount = 0; - - if (plane != -1 && portal) + else { - portal->planesused |= (1<AddPortal(this); } } @@ -678,7 +678,7 @@ void HWWall::PutPortal(HWDrawInfo *di, FRenderState& state, int ptype, int plane // //========================================================================== -void HWWall::Put3DWall(HWDrawInfo *di, FRenderState& state, lightlist_t * lightlist, bool translucent) +void HWWall::Put3DWall(HWWallDispatcher *di, FRenderState& state, lightlist_t * lightlist, bool translucent) { // only modify the light di->Level-> if it doesn't originate from the seg's frontsector. This is to account for light transferring effects if (lightlist->p_lightlevel != &seg->sidedef->sector->lightlevel) @@ -691,108 +691,7 @@ void HWWall::Put3DWall(HWDrawInfo *di, FRenderState& state, lightlist_t * lightl PutWall(di, state, translucent); } -//========================================================================== -// -// Splits a wall vertically if a 3D-floor -// creates different lighting across the wall -// -//========================================================================== - -bool HWWall::SplitWallComplex(HWDrawInfo *di, FRenderState& state, sector_t * frontsector, bool translucent, float& maplightbottomleft, float& maplightbottomright) -{ - // check for an intersection with the upper plane - if ((maplightbottomleftztop[1]) || - (maplightbottomleft>ztop[0] && maplightbottomright(fabsf(glseg.x2 - glseg.x1), fabsf(glseg.y2 - glseg.y1)); - - float dch = ztop[1] - ztop[0]; - float dfh = maplightbottomright - maplightbottomleft; - float coeff = (ztop[0] - maplightbottomleft) / (dfh - dch); - - // check for inaccuracies - let's be a little generous here! - if (coeff*clen<.1f) - { - maplightbottomleft = ztop[0]; - } - else if (coeff*clen>clen - .1f) - { - maplightbottomright = ztop[1]; - } - else - { - // split the wall in two at the intersection and recursively split both halves - HWWall copyWall1 = *this, copyWall2 = *this; - - copyWall1.glseg.x2 = copyWall2.glseg.x1 = glseg.x1 + coeff * (glseg.x2 - glseg.x1); - copyWall1.glseg.y2 = copyWall2.glseg.y1 = glseg.y1 + coeff * (glseg.y2 - glseg.y1); - copyWall1.ztop[1] = copyWall2.ztop[0] = ztop[0] + coeff * (ztop[1] - ztop[0]); - copyWall1.zbottom[1] = copyWall2.zbottom[0] = zbottom[0] + coeff * (zbottom[1] - zbottom[0]); - copyWall1.glseg.fracright = copyWall2.glseg.fracleft = glseg.fracleft + coeff * (glseg.fracright - glseg.fracleft); - copyWall1.tcs[UPRGT].u = copyWall2.tcs[UPLFT].u = tcs[UPLFT].u + coeff * (tcs[UPRGT].u - tcs[UPLFT].u); - copyWall1.tcs[UPRGT].v = copyWall2.tcs[UPLFT].v = tcs[UPLFT].v + coeff * (tcs[UPRGT].v - tcs[UPLFT].v); - copyWall1.tcs[LORGT].u = copyWall2.tcs[LOLFT].u = tcs[LOLFT].u + coeff * (tcs[LORGT].u - tcs[LOLFT].u); - copyWall1.tcs[LORGT].v = copyWall2.tcs[LOLFT].v = tcs[LOLFT].v + coeff * (tcs[LORGT].v - tcs[LOLFT].v); - copyWall1.lightuv[UPRGT].u = copyWall2.lightuv[UPLFT].u = lightuv[UPLFT].u + coeff * (lightuv[UPRGT].u - lightuv[UPLFT].u); - copyWall1.lightuv[UPRGT].v = copyWall2.lightuv[UPLFT].v = lightuv[UPLFT].v + coeff * (lightuv[UPRGT].v - lightuv[UPLFT].v); - copyWall1.lightuv[LORGT].u = copyWall2.lightuv[LOLFT].u = lightuv[LOLFT].u + coeff * (lightuv[LORGT].u - lightuv[LOLFT].u); - copyWall1.lightuv[LORGT].v = copyWall2.lightuv[LOLFT].v = lightuv[LOLFT].v + coeff * (lightuv[LORGT].v - lightuv[LOLFT].v); - - copyWall1.SplitWall(di, state, frontsector, translucent); - copyWall2.SplitWall(di, state, frontsector, translucent); - return true; - } - } - - // check for an intersection with the lower plane - if ((maplightbottomleftzbottom[1]) || - (maplightbottomleft>zbottom[0] && maplightbottomright(fabsf(glseg.x2 - glseg.x1), fabsf(glseg.y2 - glseg.y1)); - - float dch = zbottom[1] - zbottom[0]; - float dfh = maplightbottomright - maplightbottomleft; - float coeff = (zbottom[0] - maplightbottomleft) / (dfh - dch); - - // check for inaccuracies - let's be a little generous here because there's - // some conversions between floats and fixed_t's involved - if (coeff*clen<.1f) - { - maplightbottomleft = zbottom[0]; - } - else if (coeff*clen>clen - .1f) - { - maplightbottomright = zbottom[1]; - } - else - { - // split the wall in two at the intersection and recursively split both halves - HWWall copyWall1 = *this, copyWall2 = *this; - - copyWall1.glseg.x2 = copyWall2.glseg.x1 = glseg.x1 + coeff * (glseg.x2 - glseg.x1); - copyWall1.glseg.y2 = copyWall2.glseg.y1 = glseg.y1 + coeff * (glseg.y2 - glseg.y1); - copyWall1.ztop[1] = copyWall2.ztop[0] = ztop[0] + coeff * (ztop[1] - ztop[0]); - copyWall1.zbottom[1] = copyWall2.zbottom[0] = zbottom[0] + coeff * (zbottom[1] - zbottom[0]); - copyWall1.glseg.fracright = copyWall2.glseg.fracleft = glseg.fracleft + coeff * (glseg.fracright - glseg.fracleft); - copyWall1.tcs[UPRGT].u = copyWall2.tcs[UPLFT].u = tcs[UPLFT].u + coeff * (tcs[UPRGT].u - tcs[UPLFT].u); - copyWall1.tcs[UPRGT].v = copyWall2.tcs[UPLFT].v = tcs[UPLFT].v + coeff * (tcs[UPRGT].v - tcs[UPLFT].v); - copyWall1.tcs[LORGT].u = copyWall2.tcs[LOLFT].u = tcs[LOLFT].u + coeff * (tcs[LORGT].u - tcs[LOLFT].u); - copyWall1.tcs[LORGT].v = copyWall2.tcs[LOLFT].v = tcs[LOLFT].v + coeff * (tcs[LORGT].v - tcs[LOLFT].v); - copyWall1.lightuv[UPRGT].u = copyWall2.lightuv[UPLFT].u = lightuv[UPLFT].u + coeff * (lightuv[UPRGT].u - lightuv[UPLFT].u); - copyWall1.lightuv[UPRGT].v = copyWall2.lightuv[UPLFT].v = lightuv[UPLFT].v + coeff * (lightuv[UPRGT].v - lightuv[UPLFT].v); - copyWall1.lightuv[LORGT].u = copyWall2.lightuv[LOLFT].u = lightuv[LOLFT].u + coeff * (lightuv[LORGT].u - lightuv[LOLFT].u); - copyWall1.lightuv[LORGT].v = copyWall2.lightuv[LOLFT].v = lightuv[LOLFT].v + coeff * (lightuv[LORGT].v - lightuv[LOLFT].v); - - copyWall1.SplitWall(di, state, frontsector, translucent); - copyWall2.SplitWall(di, state, frontsector, translucent); - return true; - } - } - - return false; -} - -void HWWall::SplitWall(HWDrawInfo *di, FRenderState& state, sector_t * frontsector, bool translucent) +void HWWall::SplitWall(HWWallDispatcher *di, FRenderState& state, sector_t * frontsector, bool translucent) { float maplightbottomleft; float maplightbottomright; @@ -842,19 +741,10 @@ void HWWall::SplitWall(HWDrawInfo *di, FRenderState& state, sector_t * frontsect (maplightbottomleftzbottom[1]) || (maplightbottomleft > zbottom[0] && maplightbottomright < zbottom[1])) { - if (!(screen->hwcaps & RFL_NO_CLIP_PLANES)) - { - // Use hardware clipping if this cannot be done cleanly. - this->lightlist = &lightlist; - PutWall(di, state, translucent); - - goto out; - } - // crappy fallback if no clip planes available - else if (SplitWallComplex(di, state, frontsector, translucent, maplightbottomleft, maplightbottomright)) - { - goto out; - } + // Use hardware clipping if this cannot be done cleanly. + this->lightlist = &lightlist; + PutWall(di, state, translucent); + goto out; } // 3D floor is completely within this light @@ -877,10 +767,6 @@ void HWWall::SplitWall(HWDrawInfo *di, FRenderState& state, sector_t * frontsect (maplightbottomleft-copyWall1.ztop[0])*(copyWall1.tcs[LOLFT].v-copyWall1.tcs[UPLFT].v)/(zbottom[0]-copyWall1.ztop[0]); tcs[UPRGT].v=copyWall1.tcs[LORGT].v=copyWall1.tcs[UPRGT].v+ (maplightbottomright-copyWall1.ztop[1])*(copyWall1.tcs[LORGT].v-copyWall1.tcs[UPRGT].v)/(zbottom[1]-copyWall1.ztop[1]); - lightuv[UPLFT].v=copyWall1.lightuv[LOLFT].v=copyWall1.lightuv[UPLFT].v+ - (maplightbottomleft-copyWall1.ztop[0])*(copyWall1.lightuv[LOLFT].v-copyWall1.lightuv[UPLFT].v)/(zbottom[0]-copyWall1.ztop[0]); - lightuv[UPRGT].v=copyWall1.lightuv[LORGT].v=copyWall1.lightuv[UPRGT].v+ - (maplightbottomright-copyWall1.ztop[1])*(copyWall1.lightuv[LORGT].v-copyWall1.lightuv[UPRGT].v)/(zbottom[1]-copyWall1.ztop[1]); copyWall1.Put3DWall(di, state, &lightlist[i], translucent); } if (ztop[0]==zbottom[0] && ztop[1]==zbottom[1]) @@ -907,7 +793,7 @@ void HWWall::SplitWall(HWDrawInfo *di, FRenderState& state, sector_t * frontsect // // //========================================================================== -bool HWWall::DoHorizon(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) +bool HWWall::DoHorizon(HWWallDispatcher *di, FRenderState& state, seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) { HWHorizonInfo hi; lightlist_t * light; @@ -916,65 +802,74 @@ bool HWWall::DoHorizon(HWDrawInfo *di, FRenderState& state, seg_t * seg,sector_t ztop[1] = ztop[0] = fs->GetPlaneTexZ(sector_t::ceiling); zbottom[1] = zbottom[0] = fs->GetPlaneTexZ(sector_t::floor); - auto vpz = di->Viewpoint.Pos.Z; - if (vpz < fs->GetPlaneTexZ(sector_t::ceiling)) + auto ddi = di->di; + if (ddi) { - if (vpz > fs->GetPlaneTexZ(sector_t::floor)) - zbottom[1] = zbottom[0] = vpz; - - if (fs->GetTexture(sector_t::ceiling) == skyflatnum) - { - SkyPlane(di, state, fs, sector_t::ceiling, false); - } - else + auto vpz = ddi->Viewpoint.Pos.Z; + if (vpz < fs->GetPlaneTexZ(sector_t::ceiling)) { - hi.plane.GetFromSector(fs, sector_t::ceiling); - hi.lightlevel = hw_ClampLight(fs->GetCeilingLight()); - hi.colormap = fs->Colormap; - hi.specialcolor = fs->SpecialColors[sector_t::ceiling]; + if (vpz > fs->GetPlaneTexZ(sector_t::floor)) + zbottom[1] = zbottom[0] = vpz; - if (fs->e->XFloor.ffloors.Size()) + if (fs->GetTexture(sector_t::ceiling) == skyflatnum) { - light = P_GetPlaneLight(fs, &fs->ceilingplane, true); - - if(!(fs->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel); - hi.colormap.CopyLight(light->extra_colormap); + SkyPlane(di, state, fs, sector_t::ceiling, false); } + else + { + hi.plane.GetFromSector(fs, sector_t::ceiling); + hi.lightlevel = hw_ClampLight(fs->GetCeilingLight()); + hi.colormap = fs->Colormap; + hi.specialcolor = fs->SpecialColors[sector_t::ceiling]; - if (di->isFullbrightScene()) hi.colormap.Clear(); - horizon = &hi; - PutPortal(di, state, PORTALTYPE_HORIZON, -1); - } - ztop[1] = ztop[0] = zbottom[0]; - } + if (fs->e->XFloor.ffloors.Size()) + { + light = P_GetPlaneLight(fs, &fs->ceilingplane, true); - if (vpz > fs->GetPlaneTexZ(sector_t::floor)) - { - zbottom[1] = zbottom[0] = fs->GetPlaneTexZ(sector_t::floor); - if (fs->GetTexture(sector_t::floor) == skyflatnum) - { - SkyPlane(di, state, fs, sector_t::floor, false); + if (!(fs->GetFlags(sector_t::ceiling) & PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel); + hi.colormap.CopyLight(light->extra_colormap); + } + + if (ddi->isFullbrightScene()) hi.colormap.Clear(); + horizon = &hi; + PutPortal(di, state, PORTALTYPE_HORIZON, -1); + } + ztop[1] = ztop[0] = zbottom[0]; } - else - { - hi.plane.GetFromSector(fs, sector_t::floor); - hi.lightlevel = hw_ClampLight(fs->GetFloorLight()); - hi.colormap = fs->Colormap; - hi.specialcolor = fs->SpecialColors[sector_t::floor]; - if (fs->e->XFloor.ffloors.Size()) + if (vpz > fs->GetPlaneTexZ(sector_t::floor)) + { + zbottom[1] = zbottom[0] = fs->GetPlaneTexZ(sector_t::floor); + if (fs->GetTexture(sector_t::floor) == skyflatnum) { - light = P_GetPlaneLight(fs, &fs->floorplane, false); - - if(!(fs->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel); - hi.colormap.CopyLight(light->extra_colormap); + SkyPlane(di, state, fs, sector_t::floor, false); } + else + { + hi.plane.GetFromSector(fs, sector_t::floor); + hi.lightlevel = hw_ClampLight(fs->GetFloorLight()); + hi.colormap = fs->Colormap; + hi.specialcolor = fs->SpecialColors[sector_t::floor]; + + if (fs->e->XFloor.ffloors.Size()) + { + light = P_GetPlaneLight(fs, &fs->floorplane, false); - if (di->isFullbrightScene()) hi.colormap.Clear(); - horizon = &hi; - PutPortal(di, state, PORTALTYPE_HORIZON, -1); + if (!(fs->GetFlags(sector_t::floor) & PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel); + hi.colormap.CopyLight(light->extra_colormap); + } + + if (ddi->isFullbrightScene()) hi.colormap.Clear(); + horizon = &hi; + PutPortal(di, state, PORTALTYPE_HORIZON, -1); + } } } + else + { + // we cannot build the real portal yet, the mesh builder just needs a generic 'horizon' portal that needs to be filled in in the render pass. + PutPortal(di, state, PORTALTYPE_HORIZON, -1); + } return true; } @@ -986,7 +881,7 @@ static float ZeroLightmapUVs[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0. // //========================================================================== bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float texturetop, - float topleft, float topright, float bottomleft, float bottomright, float t_ofs) + float topleft, float topright, float bottomleft, float bottomright, float t_ofs, float skew) { // // @@ -1010,18 +905,6 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto texlength = 0; } - texcoord* srclightuv; - if (lightmap && lightmap->Type != ST_NULL) - { - srclightuv = (texcoord*)lightmap->TexCoords; - lindex = (float)lightmap->LightmapNum; - } - else - { - srclightuv = (texcoord*)ZeroLightmapUVs; - lindex = -1.0f; - } - // // // set up coordinates for the left side of the polygon @@ -1038,9 +921,6 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto tcs[UPLFT].v = tci->FloatToTexV(-ztop[0] + texturetop); tcs[LOLFT].v = tci->FloatToTexV(-zbottom[0] + texturetop); } - - lightuv[UPLFT].v = srclightuv[UPLFT].v; - lightuv[LOLFT].v = srclightuv[LOLFT].v; } else { @@ -1061,9 +941,6 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto { tcs[LOLFT].v = tcs[UPLFT].v = tci->FloatToTexV(-ztop[0] + texturetop); } - - lightuv[UPLFT].v = srclightuv[UPLFT].v + inter_x * (srclightuv[UPRGT].v - srclightuv[UPLFT].v); - lightuv[LOLFT].v = srclightuv[LOLFT].v + inter_x * (srclightuv[LORGT].v - srclightuv[LOLFT].v); } // @@ -1079,12 +956,9 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto if (tci) { - tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop); - tcs[LORGT].v = tci->FloatToTexV(-zbottom[1] + texturetop); + tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop + skew); + tcs[LORGT].v = tci->FloatToTexV(-zbottom[1] + texturetop + skew); } - - lightuv[UPRGT].v = srclightuv[UPRGT].v; - lightuv[LORGT].v = srclightuv[LORGT].v; } else { @@ -1102,21 +976,13 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto zbottom[1] = ztop[1] = inter_y; if (tci) { - tcs[LORGT].v = tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop); + tcs[LORGT].v = tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop + skew); } - - lightuv[UPRGT].v = srclightuv[UPRGT].v + inter_x * (srclightuv[UPRGT].v - srclightuv[UPLFT].v); - lightuv[LORGT].v = srclightuv[LORGT].v + inter_x * (srclightuv[LORGT].v - srclightuv[LOLFT].v); } tcs[UPLFT].u = tcs[LOLFT].u = l_ul + texlength * glseg.fracleft; tcs[UPRGT].u = tcs[LORGT].u = l_ul + texlength * glseg.fracright; - lightuv[UPLFT].u = srclightuv[UPLFT].u + (srclightuv[UPRGT].u - srclightuv[UPLFT].u) * glseg.fracleft; - lightuv[LOLFT].u = srclightuv[LOLFT].u + (srclightuv[LORGT].u - srclightuv[LOLFT].u) * glseg.fracleft; - lightuv[UPRGT].u = srclightuv[UPLFT].u + (srclightuv[UPRGT].u - srclightuv[UPLFT].u) * glseg.fracright; - lightuv[LORGT].u = srclightuv[LOLFT].u + (srclightuv[LORGT].u - srclightuv[LOLFT].u) * glseg.fracright; - if (texture != NULL) { bool normalize = false; @@ -1214,7 +1080,7 @@ void HWWall::CheckTexturePosition(FTexCoordInfo *tci) } -static void GetTexCoordInfo(FGameTexture *tex, FTexCoordInfo *tci, side_t *side, int texpos) +void GetTexCoordInfo(FGameTexture *tex, FTexCoordInfo *tci, side_t *side, int texpos) { tci->GetFromTexture(tex, (float)side->GetTextureXScale(texpos), (float)side->GetTextureYScale(texpos), !!(side->GetLevel()->flags3 & LEVEL3_FORCEWORLDPANNING)); } @@ -1224,11 +1090,11 @@ static void GetTexCoordInfo(FGameTexture *tex, FTexCoordInfo *tci, side_t *side, // Handle one sided walls, upper and lower texture // //========================================================================== -void HWWall::DoTexture(HWDrawInfo *di, FRenderState& state, int _type,seg_t * seg, int peg, +void HWWall::DoTexture(HWWallDispatcher *di, FRenderState& state, int _type,seg_t * seg, int peg, float ceilingrefheight,float floorrefheight, float topleft,float topright, float bottomleft,float bottomright, - float v_offset) + float v_offset, float skew) { if (topleft<=bottomleft && topright<=bottomright) return; @@ -1257,22 +1123,43 @@ void HWWall::DoTexture(HWDrawInfo *di, FRenderState& state, int _type,seg_t * se type = _type; - if (seg->sidedef->lightmap && type >= RENDERWALL_TOP && type <= RENDERWALL_BOTTOM) + if (di->di) { - lightmap = &seg->sidedef->lightmap[type - RENDERWALL_TOP]; + if (seg->sidedef->surface.Size() >= 4 && type >= RENDERWALL_TOP && type <= RENDERWALL_BOTTOM) + { + surface = seg->sidedef->surface[type - RENDERWALL_TOP]; + if (surface && di->di) + { + di->di->PushVisibleSurface(surface); + } + } + else + { + surface = nullptr; + } } else { - lightmap = nullptr; + if (type >= RENDERWALL_TOP && type <= RENDERWALL_BOTTOM) + { + static const DoomLevelMeshSurfaceType surfTypes[] = { ST_UPPERSIDE, ST_MIDDLESIDE, ST_MIDDLESIDE, ST_LOWERSIDE }; + LevelMeshInfo.Type = surfTypes[type - RENDERWALL_TOP]; + } + else + { + LevelMeshInfo.Type = ST_NONE; + } + LevelMeshInfo.ControlSector = nullptr; + surface = nullptr; } float floatceilingref = ceilingrefheight + tci.RowOffset(seg->sidedef->GetTextureYOffset(texpos)); if (peg) floatceilingref += tci.mRenderHeight - flh - v_offset; if (!SetWallCoordinates(seg, &tci, floatceilingref, topleft, topright, bottomleft, bottomright, - seg->sidedef->GetTextureXOffset(texpos))) return; + seg->sidedef->GetTextureXOffset(texpos), skew)) return; - if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors) + if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors && !(di->Level->ib_compatflags & BCOMPATF_NOMIRRORS)) { PutPortal(di, state, PORTALTYPE_MIRROR, -1); } @@ -1283,7 +1170,7 @@ void HWWall::DoTexture(HWDrawInfo *di, FRenderState& state, int _type,seg_t * se // Add this wall to the render list sector_t * sec = sub ? sub->sector : seg->frontsector; - if (sec->e->XFloor.lightlist.Size()==0 || di->isFullbrightScene()) PutWall(di, state, false); + if (sec->e->XFloor.lightlist.Size()==0 || di->isFullbrightScene()) PutWall(di, state, false); else SplitWall(di, state, sec, false); } @@ -1298,11 +1185,11 @@ void HWWall::DoTexture(HWDrawInfo *di, FRenderState& state, int _type,seg_t * se // //========================================================================== -void HWWall::DoMidTexture(HWDrawInfo *di, FRenderState& state, seg_t * seg, bool drawfogboundary, +void HWWall::DoMidTexture(HWWallDispatcher *di, FRenderState& state, seg_t * seg, bool drawfogboundary, sector_t * front, sector_t * back, sector_t * realfront, sector_t * realback, float fch1, float fch2, float ffh1, float ffh2, - float bch1, float bch2, float bfh1, float bfh2, float zalign) + float bch1, float bch2, float bfh1, float bfh2, float zalign, float skew) { FTexCoordInfo tci; @@ -1320,6 +1207,24 @@ void HWWall::DoMidTexture(HWDrawInfo *di, FRenderState& state, seg_t * seg, bool // if (texture) { + if (di->di) + { + if (seg->sidedef->surface.Size() >= 4) + { + surface = seg->sidedef->surface[side_t::mid]; + if (surface && di->di) + { + di->di->PushVisibleSurface(surface); + } + } + } + else + { + LevelMeshInfo.Type = ST_MIDDLESIDE; + LevelMeshInfo.ControlSector = nullptr; + surface = nullptr; + } + // Align the texture to the ORIGINAL sector's height!! // At this point slopes don't matter because they don't affect the texture's z-position @@ -1419,10 +1324,10 @@ void HWWall::DoMidTexture(HWDrawInfo *di, FRenderState& state, seg_t * seg, bool // if we don't need a fog sheet let's clip away some unnecessary parts of the polygon // // - if (!drawfogboundary && !wrap) + if (!drawfogboundary && !wrap && skew == 0) { - if (texturetopbottomleft && texturebottom>bottomright) bottomleft=bottomright=texturebottom; + if (texturetop < topleft && texturetop < topright) topleft = topright = texturetop; + if (texturebottom > bottomleft && texturebottom > bottomright) bottomleft = bottomright = texturebottom; } } else @@ -1435,8 +1340,10 @@ void HWWall::DoMidTexture(HWDrawInfo *di, FRenderState& state, seg_t * seg, bool // unwanted side effects. // // - topleft=topright=texturetop; - bottomleft=bottomright=texturebottom; + topleft = texturetop; + topright = texturetop + skew; + bottomleft = texturebottom; + bottomright = texturebottom + skew; } // nothing visible - skip the rest @@ -1499,7 +1406,7 @@ void HWWall::DoMidTexture(HWDrawInfo *di, FRenderState& state, seg_t * seg, bool // mid textures on portal lines need the same offsetting as mid textures on sky lines flags |= HWF_SKYHACK; } - SetWallCoordinates(seg, &tci, texturetop, topleft, topright, bottomleft, bottomright, t_ofs); + SetWallCoordinates(seg, &tci, texturetop, topleft, topright, bottomleft, bottomright, t_ofs, skew); // // @@ -1558,7 +1465,7 @@ void HWWall::DoMidTexture(HWDrawInfo *di, FRenderState& state, seg_t * seg, bool FloatRect *splitrect; int v = texture->GetAreas(&splitrect); if (seg->frontsector == seg->backsector) flags |= HWF_NOSPLIT; // we don't need to do vertex splits if a line has both sides in the same sector - if (v>0 && !drawfogboundary && !(seg->linedef->flags&ML_WRAP_MIDTEX) && !(flags & HWF_NOSLICE)) + if (v>0 && !drawfogboundary && !(seg->linedef->flags&ML_WRAP_MIDTEX) && !(flags & HWF_NOSLICE) && skew == 0) { // split the poly! int i,t=0; @@ -1633,7 +1540,7 @@ void HWWall::DoMidTexture(HWDrawInfo *di, FRenderState& state, seg_t * seg, bool // // //========================================================================== -void HWWall::BuildFFBlock(HWDrawInfo *di, FRenderState& state, seg_t * seg, F3DFloor * rover, int roverIndex, +void HWWall::BuildFFBlock(HWWallDispatcher *di, FRenderState& state, seg_t * seg, F3DFloor * rover, int roverIndex, float ff_topleft, float ff_topright, float ff_bottomleft, float ff_bottomright) { @@ -1647,14 +1554,24 @@ void HWWall::BuildFFBlock(HWDrawInfo *di, FRenderState& state, seg_t * seg, F3DF float texlength; FTexCoordInfo tci; - lightmap = nullptr; - if (seg->sidedef == seg->linedef->sidedef[0]) - lightmap = seg->linedef->sidedef[1]->lightmap; - else - lightmap = seg->linedef->sidedef[0]->lightmap; + if (di->di) + { + if (seg->sidedef == seg->linedef->sidedef[0]) + surface = seg->linedef->sidedef[1]->surface.Size() > 4 + roverIndex ? seg->linedef->sidedef[1]->surface[4 + roverIndex] : nullptr; + else + surface = seg->linedef->sidedef[0]->surface.Size() > 4 + roverIndex ? seg->linedef->sidedef[0]->surface[4 + roverIndex] : nullptr; - if (lightmap) - lightmap += 4 + roverIndex; + if (surface) + { + di->di->PushVisibleSurface(surface); + } + } + else + { + LevelMeshInfo.Type = ST_MIDDLESIDE; + LevelMeshInfo.ControlSector = rover->model; + surface = nullptr; + } if (rover->flags&FF_FOG) { @@ -1714,28 +1631,6 @@ void HWWall::BuildFFBlock(HWDrawInfo *di, FRenderState& state, seg_t * seg, F3DF tcs[LORGT].v = tci.FloatToTexV(to - ff_bottomright); type = RENDERWALL_FFBLOCK; CheckTexturePosition(&tci); - - texcoord* srclightuv; - if (lightmap && lightmap->Type != ST_NULL) - { - srclightuv = (texcoord*)lightmap->TexCoords; - lindex = (float)lightmap->LightmapNum; - } - else - { - srclightuv = (texcoord*)ZeroLightmapUVs; - lindex = -1.0f; - } - - lightuv[UPLFT].u = srclightuv[UPLFT].u + (srclightuv[UPRGT].u - srclightuv[UPLFT].u) * glseg.fracleft; - lightuv[LOLFT].u = srclightuv[LOLFT].u + (srclightuv[LORGT].u - srclightuv[LOLFT].u) * glseg.fracleft; - lightuv[UPRGT].u = srclightuv[UPLFT].u + (srclightuv[UPRGT].u - srclightuv[UPLFT].u) * glseg.fracright; - lightuv[LORGT].u = srclightuv[LOLFT].u + (srclightuv[LORGT].u - srclightuv[LOLFT].u) * glseg.fracright; - - lightuv[UPLFT].v = srclightuv[UPLFT].v; - lightuv[UPRGT].v = srclightuv[UPRGT].v; - lightuv[LOLFT].v = srclightuv[LOLFT].v; - lightuv[LORGT].v = srclightuv[LORGT].v; } ztop[0] = ff_topleft; @@ -1787,7 +1682,7 @@ __forceinline void HWWall::GetPlanePos(F3DFloor::planeref *planeref, float &left // // //========================================================================== -void HWWall::InverseFloors(HWDrawInfo *di, FRenderState& state, seg_t * seg, sector_t * frontsector, +void HWWall::InverseFloors(HWWallDispatcher *di, FRenderState& state, seg_t * seg, sector_t * frontsector, float topleft, float topright, float bottomleft, float bottomright) { @@ -1838,7 +1733,7 @@ void HWWall::InverseFloors(HWDrawInfo *di, FRenderState& state, seg_t * seg, sec // // //========================================================================== -void HWWall::ClipFFloors(HWDrawInfo *di, FRenderState& state, seg_t * seg, F3DFloor * ffloor, int ffloorIndex, sector_t * frontsector, +void HWWall::ClipFFloors(HWWallDispatcher *di, FRenderState& state, seg_t * seg, F3DFloor * ffloor, int ffloorIndex, sector_t * frontsector, float topleft, float topright, float bottomleft, float bottomright) { @@ -1912,7 +1807,7 @@ void HWWall::ClipFFloors(HWDrawInfo *di, FRenderState& state, seg_t * seg, F3DFl // // //========================================================================== -void HWWall::DoFFloorBlocks(HWDrawInfo *di, FRenderState& state, seg_t * seg, sector_t * frontsector, sector_t * backsector, +void HWWall::DoFFloorBlocks(HWWallDispatcher *di, FRenderState& state, seg_t * seg, sector_t * frontsector, sector_t * backsector, float fch1, float fch2, float ffh1, float ffh2, float bch1, float bch2, float bfh1, float bfh2) @@ -2012,12 +1907,16 @@ inline int CalcRelLight(int lightlevel, int orglightlevel, int rel) } } +CVAR(Int, topskew, 0, 0) +CVAR(Int, midskew, 0, 0) +CVAR(Int, bottomskew, 0, 0); + //========================================================================== // // // //========================================================================== -void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * frontsector, sector_t * backsector) +void HWWall::Process(HWWallDispatcher *di, FRenderState& state, seg_t *seg, sector_t * frontsector, sector_t * backsector) { vertex_t * v1, *v2; float fch1; @@ -2037,7 +1936,10 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * } #endif - lightmap = nullptr; + surface = nullptr; + + LevelMeshInfo.Type = ST_NONE; + LevelMeshInfo.ControlSector = nullptr; // note: we always have a valid sidedef and linedef reference when getting here. @@ -2168,9 +2070,14 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::mid), true); if (texture && texture->isValid()) { + int skewflag = seg->sidedef->textures[side_t::mid].skew; + if (skewflag == 0) skewflag = midskew; + float skew = + skewflag == side_t::skew_front_ceiling ? fch2 - fch1 : + skewflag == side_t::skew_front_floor ? ffh2 - ffh1 : 0.; DoTexture(di, state, RENDERWALL_M1S, seg, (seg->linedef->flags & ML_DONTPEGBOTTOM) > 0, crefz, frefz, // must come from the original! - fch1, fch2, ffh1, ffh2, 0); + fch1, fch2, ffh1, ffh2, 0, skew); } } } @@ -2238,9 +2145,31 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::top), true); if (texture && texture->isValid()) { + int skewflag = seg->sidedef->textures[side_t::top].skew; + float skew; + if (skewflag == 0) skewflag = topskew; + + switch (skewflag) + { + default: + skew = 0; + break; + case side_t::skew_front_ceiling: + skew = fch2 - fch1; + break; + case side_t::skew_back_ceiling: + skew = bch2 - bch1; + break; + case side_t::skew_front_floor: + skew = ffh2 - ffh1; + break; + case side_t::skew_back_floor: + skew = bfh2 - bfh1; + break; + } DoTexture(di, state, RENDERWALL_TOP, seg, (seg->linedef->flags & (ML_DONTPEGTOP)) == 0, crefz, realback->GetPlaneTexZ(sector_t::ceiling), - fch1, fch2, bch1a, bch2a, 0); + fch1, fch2, bch1a, bch2a, 0, skew); } else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) { @@ -2253,7 +2182,7 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * { DoTexture(di, state, RENDERWALL_TOP, seg, (seg->linedef->flags & (ML_DONTPEGTOP)) == 0, crefz, realback->GetPlaneTexZ(sector_t::ceiling), - fch1, fch2, bch1a, bch2a, 0); + fch1, fch2, bch1a, bch2a, 0, 0); } } else @@ -2272,7 +2201,7 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * /* mid texture */ sector_t *backsec = isportal? seg->linedef->getPortalDestination()->frontsector : backsector; - bool drawfogboundary = !di->isFullbrightScene() && di->CheckFog(frontsector, backsec); + bool drawfogboundary = !di->isFullbrightScene() && CheckFog(di->Level, frontsector, backsec, di->lightmode); auto tex = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::mid), true); if (tex != NULL && tex->isValid()) { @@ -2288,6 +2217,28 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::mid, false, &rel)); rellight = CalcRelLight(lightlevel, orglightlevel, rel); + float skew; + int skewflag = seg->sidedef->textures[side_t::mid].skew; + if (skewflag == 0) skewflag = midskew; + switch (skewflag) + { + default: + skew = 0; + break; + case side_t::skew_front_ceiling: + skew = fch2 - fch1; + break; + case side_t::skew_back_ceiling: + skew = bch2 - bch1; + break; + case side_t::skew_front_floor: + skew = ffh2 - ffh1; + break; + case side_t::skew_back_floor: + skew = bfh2 - bfh1; + break; + } + if (isportal) { lineportal = seg->linedef->getPortal()->mGroup; @@ -2300,7 +2251,7 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * if (texture && seg->backsector != nullptr) { DoMidTexture(di, state, seg, drawfogboundary, frontsector, backsector, realfront, realback, - fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2, zalign); + fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2, zalign, skew); } } else @@ -2309,7 +2260,7 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * if (texture || drawfogboundary) { DoMidTexture(di, state, seg, drawfogboundary, frontsector, backsector, realfront, realback, - fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2, zalign); + fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2, zalign, skew); } if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size()) @@ -2322,6 +2273,7 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * /* bottom texture */ // the back sector's ceiling obstructs part of this wall (specially important for sky sectors) + float bfh1a = bfh1, bfh2a = bfh2; if (fch1 < bfh1 && fch2 < bfh2 && (seg->linedef->flags & ML_DRAWFULLHEIGHT) == 0) { bfh1 = fch1; @@ -2335,12 +2287,34 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::bottom), true); if (texture && texture->isValid()) { + int skewflag = seg->sidedef->textures[side_t::bottom].skew; + if (skewflag == 0) skewflag = bottomskew; + float skew; + switch (skewflag) + { + default: + skew = 0; + break; + case side_t::skew_front_ceiling: + skew = fch2 - fch1; + break; + case side_t::skew_back_ceiling: + skew = bch2 - bch1; + break; + case side_t::skew_front_floor: + skew = ffh2 - ffh1; + break; + case side_t::skew_back_floor: + skew = bfh2a - bfh1a; + break; + } + DoTexture(di, state, RENDERWALL_BOTTOM, seg, (seg->linedef->flags & ML_DONTPEGBOTTOM) > 0, realback->GetPlaneTexZ(sector_t::floor), frefz, bfh1, bfh2, ffh1, ffh2, frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum ? frefz - realback->GetPlaneTexZ(sector_t::ceiling) : - frefz - crefz); + frefz - crefz, skew); } else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) { @@ -2356,7 +2330,7 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * { DoTexture(di, state, RENDERWALL_BOTTOM, seg, (seg->linedef->flags & ML_DONTPEGBOTTOM) > 0, realback->GetPlaneTexZ(sector_t::floor), frefz, - bfh1, bfh2, ffh1, ffh2, frefz - crefz); + bfh1, bfh2, ffh1, ffh2, frefz - crefz, 0); } } else if (backsector->GetTexture(sector_t::floor) != skyflatnum) @@ -2377,7 +2351,7 @@ void HWWall::Process(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * // // //========================================================================== -void HWWall::ProcessLowerMiniseg(HWDrawInfo *di, FRenderState& state, seg_t *seg, sector_t * frontsector, sector_t * backsector) +void HWWall::ProcessLowerMiniseg(HWWallDispatcher *di, FRenderState& state, seg_t *seg, sector_t * frontsector, sector_t * backsector) { if (frontsector->GetTexture(sector_t::floor) == skyflatnum) return; lightlist = NULL; @@ -2393,6 +2367,7 @@ void HWWall::ProcessLowerMiniseg(HWDrawInfo *di, FRenderState& state, seg_t *seg this->frontsector = frontsector; this->backsector = backsector; this->sub = NULL; + //this->lightmap = nullptr; // this came from gzdoom commit f796e55c0d313e1c48c3472a7334de37cc4ae775 vertex_t * v1 = seg->v1; vertex_t * v2 = seg->v2; @@ -2428,7 +2403,7 @@ void HWWall::ProcessLowerMiniseg(HWDrawInfo *di, FRenderState& state, seg_t *seg FTexCoordInfo tci; type = RENDERWALL_BOTTOM; tci.GetFromTexture(texture, 1, 1, false); - SetWallCoordinates(seg, &tci, bfh, bfh, bfh, ffh, ffh, 0); + SetWallCoordinates(seg, &tci, bfh, bfh, bfh, ffh, ffh, 0, 0); PutWall(di, state, false); } } diff --git a/src/rendering/hwrenderer/scene/hw_walls_vertex.cpp b/src/rendering/hwrenderer/scene/hw_walls_vertex.cpp index c66e111053..52b13763c5 100644 --- a/src/rendering/hwrenderer/scene/hw_walls_vertex.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls_vertex.cpp @@ -26,6 +26,8 @@ #include "hw_renderstate.h" #include "hwrenderer/scene/hw_drawinfo.h" #include "hwrenderer/scene/hw_drawstructs.h" +#include "doom_levelmesh.h" +#include "g_levellocals.h" EXTERN_CVAR(Bool, gl_seamless) @@ -193,6 +195,28 @@ void HWWall::SplitRightEdge(FFlatVertex *&ptr) int HWWall::CreateVertices(FFlatVertex *&ptr, bool split) { + if (surface && surface->LightmapTileIndex >= 0) + { + LightmapTile* tile = &level.levelMesh->LightmapTiles[surface->LightmapTileIndex]; + FVector2 lolft = tile->ToUV(FVector3(glseg.x1, glseg.y1, zbottom[0]), level.levelMesh->LMTextureSize); + FVector2 uplft = tile->ToUV(FVector3(glseg.x1, glseg.y1, ztop[0]), level.levelMesh->LMTextureSize); + FVector2 uprgt = tile->ToUV(FVector3(glseg.x2, glseg.y2, ztop[1]), level.levelMesh->LMTextureSize); + FVector2 lorgt = tile->ToUV(FVector3(glseg.x2, glseg.y2, zbottom[1]), level.levelMesh->LMTextureSize); + lightuv[LOLFT] = { lolft.X, lolft.Y }; + lightuv[UPLFT] = { uplft.X, uplft.Y }; + lightuv[UPRGT] = { uprgt.X, uprgt.Y }; + lightuv[LORGT] = { lorgt.X, lorgt.Y }; + lindex = (float)tile->AtlasLocation.ArrayIndex; + } + else + { + lightuv[LOLFT] = { 0.0f, 0.0f }; + lightuv[UPLFT] = { 0.0f, 0.0f }; + lightuv[UPRGT] = { 0.0f, 0.0f }; + lightuv[LORGT] = { 0.0f, 0.0f }; + lindex = -1.0f; + } + auto oo = ptr; ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v, lightuv[LOLFT].u, lightuv[LOLFT].v, lindex); ptr++; @@ -283,7 +307,7 @@ int HWWall::CountVertices() // //========================================================================== -void HWWall::MakeVertices(HWDrawInfo *di, FRenderState& state, bool nosplit) +void HWWall::MakeVertices(FRenderState& state, bool nosplit) { if (vertcount == 0) { diff --git a/src/rendering/hwrenderer/scene/hw_weapon.cpp b/src/rendering/hwrenderer/scene/hw_weapon.cpp index c2588c9d03..f5cef70940 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.cpp +++ b/src/rendering/hwrenderer/scene/hw_weapon.cpp @@ -46,6 +46,8 @@ #include "flatvertices.h" #include "hw_renderstate.h" +#include "vm.h" + EXTERN_CVAR(Float, transsouls) EXTERN_CVAR(Int, gl_fuzztype) EXTERN_CVAR(Bool, r_drawplayersprites) @@ -66,7 +68,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state) } else { - SetColor(state, huds->lightlevel, 0, isFullbrightScene(), huds->cm, huds->alpha, true); + SetColor(state, Level, lightmode, huds->lightlevel, 0, isFullbrightScene(), huds->cm, huds->alpha, true); } state.SetLightIndex(-1); state.SetRenderStyle(huds->RenderStyle); @@ -95,7 +97,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state) { float thresh = (huds->texture->GetTranslucency() || huds->OverrideShader != -1) ? 0.f : gl_mask_sprite_threshold; state.AlphaFunc(Alpha_GEqual, thresh); - uint32_t trans = huds->weapon->GetTranslation() != 0 ? huds->weapon->GetTranslation() : 0; + FTranslationID trans = huds->weapon->GetTranslation(); if ((huds->weapon->Flags & PSPF_PLAYERTRANSLATED)) trans = huds->owner->Translation; state.SetMaterial(huds->texture, UF_Sprite, CTF_Expand, CLAMP_XY_NOMIP, trans, huds->OverrideShader); state.Draw(DT_TriangleStrip, huds->mx, 4); @@ -118,7 +120,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state) void HWDrawInfo::DrawPlayerSprites(bool hudModelStep, FRenderState &state) { auto oldlightmode = lightmode; - if (!hudModelStep && isSoftwareLighting()) SetFallbackLightMode(); // Software lighting cannot handle 2D content. + if (!hudModelStep && isSoftwareLighting(oldlightmode)) SetFallbackLightMode(); // Software lighting cannot handle 2D content. for (auto &hudsprite : hudsprites) { if ((!!hudsprite.mframe) == hudModelStep) @@ -314,7 +316,7 @@ WeaponLighting HWDrawInfo::GetWeaponLighting(sector_t *viewsector, const DVector } else { - auto fakesec = hw_FakeFlat(viewsector, in_area, false); + auto fakesec = hw_FakeFlat(drawctx, viewsector, in_area, false); // calculate light level for weapon sprites l.lightlevel = hw_ClampLight(fakesec->lightlevel); @@ -350,9 +352,9 @@ WeaponLighting HWDrawInfo::GetWeaponLighting(sector_t *viewsector, const DVector if (Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) l.cm.ClearColor(); } - l.lightlevel = CalcLightLevel(l.lightlevel, getExtraLight(), true, 0); + l.lightlevel = CalcLightLevel(lightmode, l.lightlevel, getExtraLight(), true, 0); - if (isSoftwareLighting() || l.lightlevel < 92) + if (isSoftwareLighting(lightmode) || l.lightlevel < 92) { // Korshun: the way based on max possible light level for sector like in software renderer. double min_L = 36.0 / 31.0 - ((l.lightlevel / 255.0) * (63.0 / 31.0)); // Lightlevel in range 0-63 @@ -670,6 +672,10 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, FRenderState& state, DPSprite *psp //========================================================================== void HWDrawInfo::PreparePlayerSprites2D(sector_t * viewsector, area_t in_area, FRenderState& state) { + static PClass * wpCls = PClass::FindClass("Weapon"); + static unsigned ModifyBobLayerVIndex = GetVirtualIndex(wpCls, "ModifyBobLayer"); + static VMFunction * ModifyBobLayerOrigFunc = wpCls->Virtuals.Size() > ModifyBobLayerVIndex ? wpCls->Virtuals[ModifyBobLayerVIndex] : nullptr; + AActor * playermo = players[consoleplayer].camera; player_t * player = playermo->player; @@ -680,16 +686,29 @@ void HWDrawInfo::PreparePlayerSprites2D(sector_t * viewsector, area_t in_area, F WeaponPosition2D weap = GetWeaponPosition2D(camera->player, vp.TicFrac); WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos()); + VMFunction * ModifyBobLayer = nullptr; + DVector2 bobxy = DVector2(weap.bobx , weap.boby); + + if(weap.weapon) + { + if(auto caller = weap.weapon->GetCaller()) + { + PClass* cls = caller->GetClass(); + ModifyBobLayer = cls->Virtuals.Size() > ModifyBobLayerVIndex ? cls->Virtuals[ModifyBobLayerVIndex] : nullptr; + if( ModifyBobLayer == ModifyBobLayerOrigFunc) ModifyBobLayer = nullptr; + } + } + // hack alert! Rather than changing everything in the underlying lighting code let's just temporarily change // light mode here to draw the weapon sprite. auto oldlightmode = lightmode; - if (isSoftwareLighting()) SetFallbackLightMode(); + if (isSoftwareLighting(oldlightmode)) SetFallbackLightMode(); for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext()) { if (!psp->GetState()) continue; - FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelData != nullptr ? psp->Caller->modelData->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelData->modelDef) : psp->Caller->GetClass() : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr; + FSpriteModelFrame *smf = FindModelFrame(psp->Caller, psp->GetSprite(), psp->GetFrame(), false); // This is an 'either-or' proposition. This maybe needs some work to allow overlays with weapon models but as originally implemented this just won't work. if (smf) continue; @@ -701,6 +720,18 @@ void HWDrawInfo::PreparePlayerSprites2D(sector_t * viewsector, area_t in_area, F if (!hudsprite.GetWeaponRenderStyle(psp, camera, viewsector, light)) continue; + if(ModifyBobLayer && (psp->Flags & PSPF_ADDBOB)) + { + DVector2 out; + VMValue param[] = { weap.weapon->GetCaller() , bobxy.X , bobxy.Y , psp->GetID() , vp.TicFrac }; + VMReturn ret(&out); + + VMCall(ModifyBobLayer, param, 5, &ret, 1); + + weap.bobx = out.X; + weap.boby = out.Y; + } + FVector2 spos = BobWeapon2D(weap, psp, vp.TicFrac); hudsprite.dynrgb[0] = hudsprite.dynrgb[1] = hudsprite.dynrgb[2] = 0; @@ -719,6 +750,14 @@ void HWDrawInfo::PreparePlayerSprites2D(sector_t * viewsector, area_t in_area, F void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area, FRenderState& state) { + static PClass * wpCls = PClass::FindClass("Weapon"); + + static unsigned ModifyBobLayer3DVIndex = GetVirtualIndex(wpCls, "ModifyBobLayer3D"); + static unsigned ModifyBobPivotLayer3DVIndex = GetVirtualIndex(wpCls, "ModifyBobPivotLayer3D"); + + static VMFunction * ModifyBobLayer3DOrigFunc = wpCls->Virtuals.Size() > ModifyBobLayer3DVIndex ? wpCls->Virtuals[ModifyBobLayer3DVIndex] : nullptr; + static VMFunction * ModifyBobPivotLayer3DOrigFunc = wpCls->Virtuals.Size() > ModifyBobPivotLayer3DVIndex ? wpCls->Virtuals[ModifyBobPivotLayer3DVIndex] : nullptr; + AActor * playermo = players[consoleplayer].camera; player_t * player = playermo->player; @@ -729,15 +768,32 @@ void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area, F WeaponPosition3D weap = GetWeaponPosition3D(camera->player, vp.TicFrac); WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos()); + VMFunction * ModifyBobLayer3D = nullptr; + VMFunction * ModifyBobPivotLayer3D = nullptr; + + DVector3 translation = DVector3(weap.translation); + DVector3 rotation = DVector3(weap.rotation); + DVector3 pivot = DVector3(weap.pivot); + + if(weap.weapon && weap.weapon->GetCaller()) + { + PClass * cls = weap.weapon->GetCaller()->GetClass(); + ModifyBobLayer3D = cls->Virtuals.Size() > ModifyBobLayer3DVIndex ? cls->Virtuals[ModifyBobLayer3DVIndex] : nullptr; + ModifyBobPivotLayer3D = cls->Virtuals.Size() > ModifyBobPivotLayer3DVIndex ? cls->Virtuals[ModifyBobPivotLayer3DVIndex] : nullptr; + + if( ModifyBobLayer3D == ModifyBobLayer3DOrigFunc) ModifyBobLayer3D = nullptr; + if( ModifyBobPivotLayer3D == ModifyBobPivotLayer3DOrigFunc) ModifyBobPivotLayer3D = nullptr; + } + // hack alert! Rather than changing everything in the underlying lighting code let's just temporarily change // light mode here to draw the weapon sprite. auto oldlightmode = lightmode; - if (isSoftwareLighting()) SetFallbackLightMode(); + if (isSoftwareLighting(oldlightmode)) SetFallbackLightMode(); for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext()) { if (!psp->GetState()) continue; - FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelData != nullptr ? psp->Caller->modelData->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelData->modelDef) : psp->Caller->GetClass() : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr; + FSpriteModelFrame *smf = FindModelFrame(psp->Caller, psp->GetSprite(), psp->GetFrame(), false); // This is an 'either-or' proposition. This maybe needs some work to allow overlays with weapon models but as originally implemented this just won't work. if (!smf) continue; @@ -747,6 +803,34 @@ void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area, F hudsprite.mframe = smf; hudsprite.weapon = psp; + if(ModifyBobLayer3D && (psp->Flags & PSPF_ADDBOB)) + { + DVector3 t, r; + + VMReturn returns[2]; + + returns[0].Vec3At(&t); + returns[1].Vec3At(&r); + + VMValue param[] = { weap.weapon->GetCaller() , translation.X, translation.Y, translation.Z, rotation.X, rotation.Y, rotation.Z, psp->GetID() , vp.TicFrac }; + VMCall(ModifyBobLayer3D, param, 9, returns, 2); + + weap.translation = FVector3(t); + weap.rotation = FVector3(r); + } + + if(ModifyBobPivotLayer3D && (psp->Flags & PSPF_ADDBOB)) + { + DVector3 p; + + VMReturn ret(&p); + + VMValue param[] = { weap.weapon->GetCaller() , pivot.X, pivot.Y, pivot.Z, psp->GetID() , vp.TicFrac }; + VMCall(ModifyBobPivotLayer3D, param, 6, &ret, 1); + + weap.pivot = FVector3(p); + } + if (!hudsprite.GetWeaponRenderStyle(psp, camera, viewsector, light)) continue; //FVector2 spos = BobWeapon3D(weap, psp, hudsprite.translation, hudsprite.rotation, hudsprite.pivot, vp.TicFrac); @@ -758,7 +842,7 @@ void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area, F // set the lighting parameters if (hudsprite.RenderStyle.BlendOp != STYLEOP_Shadow && Level->HasDynamicLights && !isFullbrightScene() && gl_light_sprites) { - hw_GetDynModelLight(playermo, lightdata); + hw_GetDynModelLight(drawctx, playermo, lightdata); hudsprite.lightindex = state.UploadLights(lightdata); } diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index 6942236889..b78cf955d0 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -78,13 +78,15 @@ struct InterpolationViewer { struct instance { - DVector3 Pos; + DVector3 Pos, ViewPos; DRotator Angles; DRotator ViewAngles; }; - AActor *ViewActor; - int otic; + AActor* ViewActor; + DVector3 ViewOffset, RelativeViewOffset; // This has to be a separate field since it needs the real-time mouse angles. + DRotator AngleOffsets; + int prevTic; instance Old, New; }; @@ -443,18 +445,18 @@ EXTERN_CVAR (Bool, cl_noprediction) bool P_NoInterpolation(player_t const *player, AActor const *actor) { - return player != NULL && - !(player->cheats & CF_INTERPVIEW) && - player - players == consoleplayer && - actor == player->mo && - !demoplayback && - !(player->cheats & (CF_TOTALLYFROZEN | CF_FROZEN)) && - player->playerstate == PST_LIVE && - player->mo->reactiontime == 0 && - !NoInterpolateView && - !paused && - (!netgame || !cl_noprediction) && - !LocalKeyboardTurner; + return player != nullptr + && !(player->cheats & CF_INTERPVIEW) + && player - players == consoleplayer + && actor == player->mo + && !demoplayback + && !(player->cheats & (CF_TOTALLYFROZEN | CF_FROZEN)) + && player->playerstate == PST_LIVE + && player->mo->reactiontime == 0 + && !NoInterpolateView + && !paused + && (!netgame || !cl_noprediction) + && !LocalKeyboardTurner; } //========================================================================== @@ -463,143 +465,194 @@ bool P_NoInterpolation(player_t const *player, AActor const *actor) // //========================================================================== -void R_InterpolateView (FRenderViewpoint &viewpoint, player_t *player, double Frac, InterpolationViewer *iview) +void R_InterpolateView(FRenderViewpoint& viewPoint, const player_t* const player, const double ticFrac, InterpolationViewer* const iView) { if (NoInterpolateView) { InterpolationPath.Clear(); NoInterpolateView = false; - iview->Old = iview->New; + iView->Old = iView->New; } - auto Level = viewpoint.ViewLevel; - int oldgroup = Level->PointInRenderSubsector(iview->Old.Pos)->sector->PortalGroup; - int newgroup = Level->PointInRenderSubsector(iview->New.Pos)->sector->PortalGroup; - DAngle oviewangle = iview->Old.Angles.Yaw; - DAngle nviewangle = iview->New.Angles.Yaw; + const double inverseTicFrac = 1.0 - ticFrac; + const auto viewLvl = viewPoint.ViewLevel; + + DAngle prevYaw = iView->Old.Angles.Yaw; + DAngle curYaw = iView->New.Angles.Yaw; if (!cl_capfps) { - if ((iview->Old.Pos.X != iview->New.Pos.X || iview->Old.Pos.Y != iview->New.Pos.Y) && InterpolationPath.Size() > 0) + if ((iView->Old.Pos.X != iView->New.Pos.X || iView->Old.Pos.Y != iView->New.Pos.Y) && InterpolationPath.Size() > 0) { - DVector3 view = iview->New.Pos; - // Interpolating through line portals is a messy affair. // What needs be done is to store the portal transitions of the camera actor as waypoints // and then find out on which part of the path the current view lies. - // Needless to say, this doesn't work for chasecam mode or viewpos. - if (!viewpoint.showviewer && !viewpoint.NoPortalPath) + double totalPathLength = 0.0; + double totalZDiff = 0.0; + DAngle totalYawDiff = nullAngle; + DVector3a oldPos = { { iView->Old.Pos.X, iView->Old.Pos.Y, 0.0 }, nullAngle }; + DVector3a newPos = { { iView->New.Pos.X, iView->New.Pos.Y, 0.0 }, nullAngle }; + InterpolationPath.Push(newPos); // Add this to the array to simplify the loops below. + + for (size_t i = 0u; i < InterpolationPath.Size(); i += 2u) + { + const DVector3a& start = !i ? oldPos : InterpolationPath[i - 1u]; + const DVector3a& end = InterpolationPath[i]; + totalPathLength += (end.pos - start.pos).Length(); + totalZDiff += start.pos.Z; + totalYawDiff += start.angle; + } + + double interpolatedLength = totalPathLength * ticFrac; + double zDiff = 0.0; + DAngle yawDiff = nullAngle; + double prevViewZ = iView->Old.Pos.Z; + double curViewZ = iView->New.Pos.Z; + for (size_t i = 0u; i < InterpolationPath.Size(); i += 2u) { - double pathlen = 0; - double zdiff = 0; - double totalzdiff = 0; - DAngle adiff = nullAngle; - DAngle totaladiff = nullAngle; - double oviewz = iview->Old.Pos.Z; - double nviewz = iview->New.Pos.Z; - DVector3a oldpos = { { iview->Old.Pos.X, iview->Old.Pos.Y, 0 }, nullAngle }; - DVector3a newpos = { { iview->New.Pos.X, iview->New.Pos.Y, 0 }, nullAngle }; - InterpolationPath.Push(newpos); // add this to the array to simplify the loops below - - for (unsigned i = 0; i < InterpolationPath.Size(); i += 2) + const DVector3a& start = !i ? oldPos : InterpolationPath[i - 1u]; + const DVector3a& end = InterpolationPath[i]; + const double fragmentLength = (end.pos - start.pos).Length(); + zDiff += start.pos.Z; + yawDiff += start.angle; + + if (fragmentLength <= interpolatedLength) { - DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1]; - DVector3a &end = InterpolationPath[i]; - pathlen += (end.pos - start.pos).Length(); - totalzdiff += start.pos.Z; - totaladiff += start.angle; + interpolatedLength -= fragmentLength; } - double interpolatedlen = Frac * pathlen; - - for (unsigned i = 0; i < InterpolationPath.Size(); i += 2) + else { - DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1]; - DVector3a &end = InterpolationPath[i]; - double fraglen = (end.pos - start.pos).Length(); - zdiff += start.pos.Z; - adiff += start.angle; - if (fraglen <= interpolatedlen) - { - interpolatedlen -= fraglen; - } - else - { - double fragfrac = interpolatedlen / fraglen; - oviewz += zdiff; - nviewz -= totalzdiff - zdiff; - oviewangle += adiff; - nviewangle -= totaladiff - adiff; - DVector2 viewpos = start.pos + (fragfrac * (end.pos - start.pos)); - viewpoint.Pos = { viewpos, oviewz + Frac * (nviewz - oviewz) }; - break; - } + prevViewZ += zDiff; + curViewZ -= totalZDiff - zDiff; + prevYaw += yawDiff; + curYaw -= totalYawDiff - yawDiff; + + const DVector2 viewPos = start.pos.XY() + ((interpolatedLength / fragmentLength) * (end.pos - start.pos).XY()); + viewPoint.Pos = { viewPos, prevViewZ * inverseTicFrac + curViewZ * ticFrac }; + break; } - InterpolationPath.Pop(); - viewpoint.Path[0] = iview->Old.Pos; - viewpoint.Path[1] = viewpoint.Path[0] + (InterpolationPath[0].pos - viewpoint.Path[0]).XY().MakeResize(pathlen); } + + InterpolationPath.Pop(); + viewPoint.Path[0] = iView->Old.Pos; + viewPoint.Path[1] = viewPoint.Path[0] + (InterpolationPath[0].pos - viewPoint.Path[0]).XY().MakeResize(totalPathLength); } else { - DVector2 disp = viewpoint.ViewLevel->Displacements.getOffset(oldgroup, newgroup); - viewpoint.Pos = iview->Old.Pos + (iview->New.Pos - iview->Old.Pos - disp) * Frac; - viewpoint.Path[0] = viewpoint.Path[1] = iview->New.Pos; + const int prevPortalGroup = viewLvl->PointInRenderSubsector(iView->Old.Pos)->sector->PortalGroup; + const int curPortalGroup = viewLvl->PointInRenderSubsector(iView->New.Pos)->sector->PortalGroup; + + const DVector2 portalOffset = viewLvl->Displacements.getOffset(prevPortalGroup, curPortalGroup); + viewPoint.Pos = iView->Old.Pos * inverseTicFrac + (iView->New.Pos - portalOffset) * ticFrac; + viewPoint.Path[0] = viewPoint.Path[1] = iView->New.Pos; } } else { - viewpoint.Pos = iview->New.Pos; - viewpoint.Path[0] = viewpoint.Path[1] = iview->New.Pos; - } - if (P_NoInterpolation(player, viewpoint.camera) && - iview->New.Pos.X == viewpoint.camera->X() && - iview->New.Pos.Y == viewpoint.camera->Y()) - { - viewpoint.Angles.Yaw = (nviewangle + DAngle::fromBam(LocalViewAngle)).Normalized180(); - DAngle delta = player->centering ? nullAngle : DAngle::fromBam(LocalViewPitch); - viewpoint.Angles.Pitch = clamp((iview->New.Angles.Pitch - delta).Normalized180(), player->MinPitch, player->MaxPitch); - viewpoint.Angles.Roll = iview->New.Angles.Roll.Normalized180(); - } - else - { - viewpoint.Angles.Pitch = (iview->Old.Angles.Pitch + deltaangle(iview->Old.Angles.Pitch, iview->New.Angles.Pitch) * Frac).Normalized180(); - viewpoint.Angles.Yaw = (oviewangle + deltaangle(oviewangle, nviewangle) * Frac).Normalized180(); - viewpoint.Angles.Roll = (iview->Old.Angles.Roll + deltaangle(iview->Old.Angles.Roll, iview->New.Angles.Roll) * Frac).Normalized180(); - } - - // [MR] Apply the view angles as an offset if ABSVIEWANGLES isn't specified. - if (!(viewpoint.camera->flags8 & MF8_ABSVIEWANGLES)) - { - viewpoint.Angles += (!player || (player->cheats & CF_INTERPVIEWANGLES)) ? interpolatedvalue(iview->Old.ViewAngles, iview->New.ViewAngles, Frac) : iview->New.ViewAngles; + viewPoint.Pos = iView->New.Pos; + viewPoint.Path[0] = viewPoint.Path[1] = iView->New.Pos; } // Due to interpolation this is not necessarily the same as the sector the camera is in. - viewpoint.sector = Level->PointInRenderSubsector(viewpoint.Pos)->sector; + viewPoint.sector = viewLvl->PointInRenderSubsector(viewPoint.Pos)->sector; bool moved = false; - while (!viewpoint.sector->PortalBlocksMovement(sector_t::ceiling)) + while (!viewPoint.sector->PortalBlocksMovement(sector_t::ceiling)) { - if (viewpoint.Pos.Z > viewpoint.sector->GetPortalPlaneZ(sector_t::ceiling)) + if (viewPoint.Pos.Z > viewPoint.sector->GetPortalPlaneZ(sector_t::ceiling)) { - viewpoint.Pos += viewpoint.sector->GetPortalDisplacement(sector_t::ceiling); - viewpoint.ActorPos += viewpoint.sector->GetPortalDisplacement(sector_t::ceiling); - viewpoint.sector = Level->PointInRenderSubsector(viewpoint.Pos)->sector; + const DVector2 offset = viewPoint.sector->GetPortalDisplacement(sector_t::ceiling); + viewPoint.Pos += offset; + viewPoint.ActorPos += offset; + viewPoint.sector = viewPoint.sector->GetPortal(sector_t::ceiling)->mDestination; moved = true; } - else break; + else + { + break; + } } + if (!moved) { - while (!viewpoint.sector->PortalBlocksMovement(sector_t::floor)) + while (!viewPoint.sector->PortalBlocksMovement(sector_t::floor)) { - if (viewpoint.Pos.Z < viewpoint.sector->GetPortalPlaneZ(sector_t::floor)) + if (viewPoint.Pos.Z < viewPoint.sector->GetPortalPlaneZ(sector_t::floor)) + { + const DVector2 offset = viewPoint.sector->GetPortalDisplacement(sector_t::floor); + viewPoint.Pos += offset; + viewPoint.ActorPos += offset; + viewPoint.sector = viewPoint.sector->GetPortal(sector_t::floor)->mDestination; + } + else { - viewpoint.Pos += viewpoint.sector->GetPortalDisplacement(sector_t::floor); - viewpoint.ActorPos += viewpoint.sector->GetPortalDisplacement(sector_t::floor); - viewpoint.sector = Level->PointInRenderSubsector(viewpoint.Pos)->sector; - moved = true; + break; } - else break; } } + + if (P_NoInterpolation(player, viewPoint.camera)) + { + viewPoint.Angles.Yaw = curYaw + DAngle::fromBam(LocalViewAngle); + const DAngle delta = player->centering ? nullAngle : DAngle::fromBam(LocalViewPitch); + viewPoint.Angles.Pitch = clamp((iView->New.Angles.Pitch - delta).Normalized180(), player->MinPitch, player->MaxPitch); + viewPoint.Angles.Roll = iView->New.Angles.Roll; + } + else + { + viewPoint.Angles.Pitch = iView->Old.Angles.Pitch + deltaangle(iView->Old.Angles.Pitch, iView->New.Angles.Pitch) * ticFrac; + viewPoint.Angles.Yaw = prevYaw + deltaangle(prevYaw, curYaw) * ticFrac; + viewPoint.Angles.Roll = iView->Old.Angles.Roll + deltaangle(iView->Old.Angles.Roll, iView->New.Angles.Roll) * ticFrac; + } + + // Now that the base position and angles are set, add offsets. + + const DViewPosition* const vPos = iView->ViewActor->ViewPos; + if (vPos != nullptr && !(vPos->Flags & VPSF_ABSOLUTEPOS) + && (player == nullptr || gamestate == GS_TITLELEVEL || (!(player->cheats & CF_CHASECAM) && (!r_deathcamera || !(iView->ViewActor->flags6 & MF6_KILLED))))) + { + DVector3 vOfs = {}; + if (player == nullptr || !(player->cheats & CF_NOVIEWPOSINTERP)) + vOfs = iView->Old.ViewPos * inverseTicFrac + iView->New.ViewPos * ticFrac; + else + vOfs = iView->New.ViewPos; + + if (vPos->Flags & VPSF_ABSOLUTEOFFSET) + iView->ViewOffset += vOfs; + else + iView->RelativeViewOffset += vOfs; + } + + DVector3 posOfs = iView->ViewOffset; + if (!iView->RelativeViewOffset.isZero()) + posOfs += DQuaternion::FromAngles(viewPoint.Angles.Yaw, viewPoint.Angles.Pitch, viewPoint.Angles.Roll) * iView->RelativeViewOffset; + + // Now that we have the current interpolated position, offset from that directly (for view offset + chase cam). + if (!posOfs.isZero()) + { + const double distance = posOfs.Length(); + posOfs /= distance; + R_OffsetView(viewPoint, posOfs, distance); + } + + viewPoint.Angles += iView->AngleOffsets; + + // [MR] Apply the view angles as an offset if ABSVIEWANGLES isn't specified. + if (!(viewPoint.camera->flags8 & MF8_ABSVIEWANGLES)) + { + if (player == nullptr || (player->cheats & CF_INTERPVIEWANGLES)) + { + viewPoint.Angles.Yaw += iView->Old.ViewAngles.Yaw + deltaangle(iView->Old.ViewAngles.Yaw, iView->New.ViewAngles.Yaw) * ticFrac; + viewPoint.Angles.Pitch += iView->Old.ViewAngles.Pitch + deltaangle(iView->Old.ViewAngles.Pitch, iView->New.ViewAngles.Pitch) * ticFrac; + viewPoint.Angles.Roll += iView->Old.ViewAngles.Roll + deltaangle(iView->Old.ViewAngles.Roll, iView->New.ViewAngles.Roll) * ticFrac; + } + else + { + viewPoint.Angles += iView->New.ViewAngles; + } + } + + viewPoint.Angles.Yaw = viewPoint.Angles.Yaw.Normalized180(); + viewPoint.Angles.Pitch = viewPoint.Angles.Pitch.Normalized180(); + viewPoint.Angles.Roll = viewPoint.Angles.Roll.Normalized180(); } //========================================================================== @@ -616,24 +669,23 @@ void R_ResetViewInterpolation () //========================================================================== // -// R_SetViewAngle -// sets all values derived from the view angle. +// R_SetViewAngle +// sets all values derived from the view yaw. // //========================================================================== -void FRenderViewpoint::SetViewAngle (const FViewWindow &viewwindow) +void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow) { Sin = Angles.Yaw.Sin(); Cos = Angles.Yaw.Cos(); - TanSin = viewwindow.FocalTangent * Sin; - TanCos = viewwindow.FocalTangent * Cos; + TanSin = viewWindow.FocalTangent * Sin; + TanCos = viewWindow.FocalTangent * Cos; - DVector2 v = Angles.Yaw.ToVector(); + const DVector2 v = Angles.Yaw.ToVector(); ViewVector.X = v.X; ViewVector.Y = v.Y; HWAngles.Yaw = FAngle::fromDeg(270.0 - Angles.Yaw.Degrees()); - } //========================================================================== @@ -656,7 +708,7 @@ static InterpolationViewer *FindPastViewer (AActor *actor) InterpolationViewer iview; memset(&iview, 0, sizeof(iview)); iview.ViewActor = actor; - iview.otic = -1; + iview.prevTic = -1; InterpolationPath.Clear(); return &PastViewers[PastViewers.Push (iview)]; } @@ -782,26 +834,12 @@ static double QuakePower(double factor, double intensity, double offset) // //========================================================================== -static void R_DoActorTickerAngleChanges(player_t* const player, AActor* const actor, const double scale) +static void R_DoActorTickerAngleChanges(player_t* const player, DRotator& angles, const double scale) { for (unsigned i = 0; i < 3; i++) { - if (player->angleTargets[i].Sgn()) - { - // Calculate scaled amount of target and add to the accumlation buffer. - DAngle addition = player->angleTargets[i] * scale; - player->angleAppliedAmounts[i] += addition; - - // Test whether we're now reached/exceeded our target. - if (abs(player->angleAppliedAmounts[i]) >= abs(player->angleTargets[i])) - { - addition -= player->angleAppliedAmounts[i] - player->angleTargets[i]; - player->angleTargets[i] = player->angleAppliedAmounts[i] = nullAngle; - } - - // Apply the scaled addition to the angle. - actor->Angles[i] += addition; - } + if (fabs(player->angleOffsetTargets[i].Degrees()) >= EQUAL_EPSILON) + angles[i] += player->angleOffsetTargets[i] * scale; } } @@ -811,346 +849,261 @@ static void R_DoActorTickerAngleChanges(player_t* const player, AActor* const ac // //========================================================================== -void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor *actor) +EXTERN_CVAR(Float, chase_dist) +EXTERN_CVAR(Float, chase_height) + +void R_SetupFrame(FRenderViewpoint& viewPoint, const FViewWindow& viewWindow, AActor* const actor) { - if (actor == NULL) - { - I_Error ("Tried to render from a NULL actor."); - } - viewpoint.ViewLevel = actor->Level; + viewPoint.TicFrac = I_GetTimeFrac(); + if (cl_capfps || r_NoInterpolate) + viewPoint.TicFrac = 1.0; - player_t *player = actor->player; - unsigned int newblend; - InterpolationViewer *iview; - bool unlinked = false; + const int curTic = I_GetTime(); - if (player != NULL && player->mo == actor) - { // [RH] Use camera instead of viewplayer - viewpoint.camera = player->camera; - if (viewpoint.camera == NULL) - { - viewpoint.camera = player->camera = player->mo; - } - } - else - { - viewpoint.camera = actor; - } + if (actor == nullptr) + I_Error("Tried to render from a null actor."); - if (viewpoint.camera == NULL) - { - I_Error ("You lost your body. Bad dehacked work is likely to blame."); - } + viewPoint.ViewLevel = actor->Level; - // [MR] Get the input fraction, even if we don't need it this frame. Must run every frame. - const auto scaleAdjust = I_GetInputFrac(); + player_t* player = actor->player; + if (player != nullptr && player->mo == actor) + { + if (player->camera == nullptr) + player->camera = player->mo; - // [MR] Process player angle changes if permitted to do so. - if (player && (player->cheats & CF_SCALEDNOLERP) && P_NoInterpolation(player, viewpoint.camera)) + viewPoint.camera = player->camera; // [RH] Use camera instead of view player. + } + else { - R_DoActorTickerAngleChanges(player, viewpoint.camera, scaleAdjust); + viewPoint.camera = actor; } - iview = FindPastViewer (viewpoint.camera); + if (viewPoint.camera == nullptr) + I_Error("You lost your body. Bad dehacked work is likely to blame."); - int nowtic = I_GetTime (); - if (iview->otic != -1 && nowtic > iview->otic) + InterpolationViewer* const iView = FindPastViewer(viewPoint.camera); + // Always reset these back to zero. + iView->ViewOffset.Zero(); + iView->RelativeViewOffset.Zero(); + iView->AngleOffsets.Zero(); + if (iView->prevTic != -1 && curTic > iView->prevTic) { - iview->otic = nowtic; - iview->Old = iview->New; + iView->prevTic = curTic; + iView->Old = iView->New; } + + const auto& mainView = r_viewpoint; + AActor* const client = players[consoleplayer].mo; + const bool matchPlayer = gamestate != GS_TITLELEVEL && viewPoint.camera->player == nullptr && (viewPoint.camera->renderflags2 & RF2_CAMFOLLOWSPLAYER); + const bool usePawn = matchPlayer ? mainView.camera != client : false; //============================================================================================== - // Handles offsetting the camera with ChaseCam and/or viewpos. + // Sets up the view position offset. { - AActor *mo = viewpoint.camera; - DViewPosition *VP = mo->ViewPos; - const DVector3 orig = { mo->Pos().XY(), mo->player ? mo->player->viewz : mo->Z() + mo->GetCameraHeight() }; - viewpoint.ActorPos = orig; - - bool DefaultDraw = true; - - sector_t *oldsector = viewpoint.ViewLevel->PointInRenderSubsector(iview->Old.Pos)->sector; - if (gamestate != GS_TITLELEVEL && - ((player && (player->cheats & CF_CHASECAM)) || (r_deathcamera && viewpoint.camera->health <= 0))) + AActor* const mo = viewPoint.camera; + const DViewPosition* const viewOffset = mo->ViewPos; + DVector3 camPos; + if (matchPlayer) { - // [RH] Use chasecam view - DefaultDraw = false; - DVector3 campos; - DAngle camangle; - P_AimCamera(viewpoint.camera, campos, camangle, viewpoint.sector, unlinked); // fixme: This needs to translate the angle, too. - iview->New.Pos = campos; - iview->New.Angles.Yaw = camangle; - - viewpoint.showviewer = true; - // Interpolating this is a very complicated thing because nothing keeps track of the aim camera's movement, so whenever we detect a portal transition - // it's probably best to just reset the interpolation for this move. - // Note that this can still cause problems with unusually linked portals - if (viewpoint.sector->PortalGroup != oldsector->PortalGroup || (unlinked && ((iview->New.Pos.XY() - iview->Old.Pos.XY()).LengthSquared()) > 256 * 256)) + if (usePawn) + { + camPos = DVector3(client->Pos().XY(), client->player->viewz); + const DViewPosition* const pawnVP = client->ViewPos; + if (pawnVP != nullptr) + { + // Add these directly to the view position offset (not 100% accurate but close enough). + if (pawnVP->Flags & VPSF_ABSOLUTEPOS) + camPos = pawnVP->Offset; + else if (pawnVP->Flags & VPSF_ABSOLUTEOFFSET) + iView->ViewOffset = pawnVP->Offset; + else + iView->ViewOffset = DQuaternion::FromAngles(client->Angles.Yaw, client->Angles.Pitch, client->Angles.Roll) * pawnVP->Offset; + } + } + else { - iview->otic = nowtic; - iview->Old = iview->New; - r_NoInterpolate = true; + camPos = mainView.Pos; } - viewpoint.ActorPos = campos; } - else if (VP) // No chase/death cam and player is alive, wants viewpos. + else + { + camPos = { mo->Pos().XY(), mo->player != nullptr ? mo->player->viewz : mo->Z() + mo->GetCameraHeight() }; + } + + viewPoint.showviewer = false; + viewPoint.bForceNoViewer = matchPlayer; + + if (player != nullptr && gamestate != GS_TITLELEVEL + && ((player->cheats & CF_CHASECAM) || (r_deathcamera && (viewPoint.camera->flags6 & MF6_KILLED)))) { - viewpoint.sector = viewpoint.ViewLevel->PointInRenderSubsector(iview->New.Pos.XY())->sector; - viewpoint.showviewer = false; + // The cam Actor should probably be visible in third person. + viewPoint.showviewer = true; + camPos.Z = mo->Top() - mo->Floorclip; + iView->ViewOffset.Z = clamp(chase_height, -1000.0, 1000.0); + iView->RelativeViewOffset.X = -clamp(chase_dist, 0.0, 30000.0); + } - // [MC] Ignores all portal portal transitions since it's meant to be absolute. - // Modders must handle performing offsetting with the appropriate functions to get it to work. - // Hint: Check P_AdjustViewPos. - if (VP->Flags & VPSF_ABSOLUTEPOS) + if (viewOffset != nullptr) + { + // No chase/death cam, so use the view offset. + if (!viewPoint.bForceNoViewer) + viewPoint.bForceNoViewer = (viewOffset->Flags & VPSF_ABSOLUTEPOS) || !viewOffset->Offset.isZero(); + + if (viewOffset->Flags & VPSF_ABSOLUTEPOS) { - iview->New.Pos = VP->Offset; + iView->New.ViewPos.Zero(); + if (!matchPlayer) + camPos = viewOffset->Offset; } else { - DVector3 next = orig; - - if (VP->isZero()) - { - // Since viewpos isn't being used, it's safe to enable path interpolation - viewpoint.NoPortalPath = false; - } - else if (VP->Flags & VPSF_ABSOLUTEOFFSET) - { - // No relativity added from angles. - next += VP->Offset; - } - else - { - // [MC] Do NOT handle portals here! Trace must have the unportaled (absolute) position to - // get the correct angle and distance. Trace automatically handles portals by itself. - // Note: viewpos does not include view angles, and ViewZ/CameraHeight are applied before this. - - DAngle yaw = mo->Angles.Yaw; - DAngle pitch = mo->Angles.Pitch; - DAngle roll = mo->Angles.Roll; - DVector3 relx, rely, relz, Off = VP->Offset; - DMatrix3x3 rot = - DMatrix3x3(DVector3(0., 0., 1.), yaw.Cos(), yaw.Sin()) * - DMatrix3x3(DVector3(0., 1., 0.), pitch.Cos(), pitch.Sin()) * - DMatrix3x3(DVector3(1., 0., 0.), roll.Cos(), roll.Sin()); - relx = DVector3(1., 0., 0.)*rot; - rely = DVector3(0., 1., 0.)*rot; - relz = DVector3(0., 0., 1.)*rot; - next += relx * Off.X + rely * Off.Y + relz * Off.Z; - } - - if (next != orig) - { - // [MC] Disable interpolation if the camera view is crossing through a portal. Sometimes - // the player is made visible when crossing a portal and it's extremely jarring. - // Also, disable the portal interpolation pathing entirely when using the viewpos feature. - // Interpolation still happens with everything else though and seems to work fine. - DefaultDraw = false; - viewpoint.NoPortalPath = true; - P_AdjustViewPos(mo, orig, next, viewpoint.sector, unlinked, VP); - - if (viewpoint.sector->PortalGroup != oldsector->PortalGroup || (unlinked && ((iview->New.Pos.XY() - iview->Old.Pos.XY()).LengthSquared()) > 256 * 256)) - { - iview->otic = nowtic; - iview->Old = iview->New; - r_NoInterpolate = true; - } - iview->New.Pos = next; - } + iView->New.ViewPos = viewOffset->Offset; } } - - if (DefaultDraw) + + viewPoint.ActorPos = iView->New.Pos = camPos; + viewPoint.sector = viewPoint.ViewLevel->PointInRenderSubsector(camPos)->sector; + } + + if (!paused) + { + FQuakeJiggers jiggers; + if (DEarthquake::StaticGetQuakeIntensities(viewPoint.TicFrac, viewPoint.camera, jiggers) > 0) { - iview->New.Pos = orig; - viewpoint.sector = viewpoint.camera->Sector; - viewpoint.showviewer = viewpoint.NoPortalPath = false; + const double quakeFactor = r_quakeintensity; + if (jiggers.RollIntensity || jiggers.RollWave) + iView->AngleOffsets.Roll = DAngle::fromDeg(QuakePower(quakeFactor, jiggers.RollIntensity, jiggers.RollWave)); + + if (jiggers.RelIntensity.X || jiggers.RelOffset.X) + iView->RelativeViewOffset.X += QuakePower(quakeFactor, jiggers.RelIntensity.X, jiggers.RelOffset.X); + if (jiggers.RelIntensity.Y || jiggers.RelOffset.Y) + iView->RelativeViewOffset.Y += QuakePower(quakeFactor, jiggers.RelIntensity.Y, jiggers.RelOffset.Y); + if (jiggers.RelIntensity.Z || jiggers.RelOffset.Z) + iView->RelativeViewOffset.Z += QuakePower(quakeFactor, jiggers.RelIntensity.Z, jiggers.RelOffset.Z); + + if (jiggers.Intensity.X || jiggers.Offset.X) + iView->ViewOffset.X += QuakePower(quakeFactor, jiggers.Intensity.X, jiggers.Offset.X); + if (jiggers.Intensity.Y || jiggers.Offset.Y) + iView->ViewOffset.Y += QuakePower(quakeFactor, jiggers.Intensity.Y, jiggers.Offset.Y); + if (jiggers.Intensity.Z || jiggers.Offset.Z) + iView->ViewOffset.Z += QuakePower(quakeFactor, jiggers.Intensity.Z, jiggers.Offset.Z); } } // [MR] Apply view angles as the viewpoint angles if asked to do so. - iview->New.Angles = !(viewpoint.camera->flags8 & MF8_ABSVIEWANGLES) ? viewpoint.camera->Angles : viewpoint.camera->ViewAngles; - iview->New.ViewAngles = viewpoint.camera->ViewAngles; + if (matchPlayer) + iView->New.Angles = usePawn ? (client->flags8 & MF8_ABSVIEWANGLES ? client->ViewAngles : client->Angles + client->ViewAngles) : mainView.Angles; + else + iView->New.Angles = !(viewPoint.camera->flags8 & MF8_ABSVIEWANGLES) ? viewPoint.camera->Angles : viewPoint.camera->ViewAngles; - if (viewpoint.camera->player != 0) - { - player = viewpoint.camera->player; - } + iView->New.ViewAngles = viewPoint.camera->ViewAngles; + // [MR] Process player angle changes if permitted to do so. + if (player != nullptr && (player->cheats & CF_SCALEDNOLERP) && P_NoInterpolation(player, viewPoint.camera)) + R_DoActorTickerAngleChanges(player, iView->New.Angles, viewPoint.TicFrac); - if (iview->otic == -1 || r_NoInterpolate || (viewpoint.camera->renderflags & RF_NOINTERPOLATEVIEW)) - { - viewpoint.camera->renderflags &= ~RF_NOINTERPOLATEVIEW; - R_ResetViewInterpolation (); - iview->otic = nowtic; - } + // If currently tracking the player's real view, don't do any sort of interpolating. + if (matchPlayer && !usePawn) + viewPoint.camera->renderflags |= RF_NOINTERPOLATEVIEW; - viewpoint.TicFrac = I_GetTimeFrac (); - if (cl_capfps || r_NoInterpolate) + if (viewPoint.camera->player != nullptr) + player = viewPoint.camera->player; + + if (iView->prevTic == -1 || r_NoInterpolate || (viewPoint.camera->renderflags & RF_NOINTERPOLATEVIEW)) { - viewpoint.TicFrac = 1.; + viewPoint.camera->renderflags &= ~RF_NOINTERPOLATEVIEW; + R_ResetViewInterpolation(); + iView->prevTic = curTic; } - R_InterpolateView (viewpoint, player, viewpoint.TicFrac, iview); - viewpoint.SetViewAngle (viewwindow); + R_InterpolateView(viewPoint, player, viewPoint.TicFrac, iView); + + viewPoint.SetViewAngle(viewWindow); // Keep the view within the sector's floor and ceiling - if (viewpoint.sector->PortalBlocksMovement(sector_t::ceiling)) + if (viewPoint.sector->PortalBlocksMovement(sector_t::ceiling)) { - double theZ = viewpoint.sector->ceilingplane.ZatPoint(viewpoint.Pos) - 4; - if (viewpoint.Pos.Z > theZ) - { - viewpoint.Pos.Z = theZ; - } + const double z = viewPoint.sector->ceilingplane.ZatPoint(viewPoint.Pos) - 4.0; + if (viewPoint.Pos.Z > z) + viewPoint.Pos.Z = z; } - if (viewpoint.sector->PortalBlocksMovement(sector_t::floor)) + if (viewPoint.sector->PortalBlocksMovement(sector_t::floor)) { - double theZ = viewpoint.sector->floorplane.ZatPoint(viewpoint.Pos) + 4; - if (viewpoint.Pos.Z < theZ) - { - viewpoint.Pos.Z = theZ; - } + const double z = viewPoint.sector->floorplane.ZatPoint(viewPoint.Pos) + 4.0; + if (viewPoint.Pos.Z < z) + viewPoint.Pos.Z = z; } - if (!paused) - { - FQuakeJiggers jiggers; - - memset(&jiggers, 0, sizeof(jiggers)); - if (DEarthquake::StaticGetQuakeIntensities(viewpoint.TicFrac, viewpoint.camera, jiggers) > 0) - { - double quakefactor = r_quakeintensity; - DVector3 pos; pos.Zero(); - if (jiggers.RollIntensity != 0 || jiggers.RollWave != 0) - { - viewpoint.Angles.Roll += DAngle::fromDeg(QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave)); - } - if (jiggers.RelIntensity.X != 0 || jiggers.RelOffset.X != 0) - { - pos.X += QuakePower(quakefactor, jiggers.RelIntensity.X, jiggers.RelOffset.X); - } - if (jiggers.RelIntensity.Y != 0 || jiggers.RelOffset.Y != 0) - { - pos.Y += QuakePower(quakefactor, jiggers.RelIntensity.Y, jiggers.RelOffset.Y); - } - if (jiggers.RelIntensity.Z != 0 || jiggers.RelOffset.Z != 0) - { - pos.Z += QuakePower(quakefactor, jiggers.RelIntensity.Z, jiggers.RelOffset.Z); - } - // [MC] Tremendous thanks to Marisa Kirisame for helping me with this. - // Use a rotation matrix to make the view relative. - if (!pos.isZero()) - { - DAngle yaw = viewpoint.camera->Angles.Yaw; - DAngle pitch = viewpoint.camera->Angles.Pitch; - DAngle roll = viewpoint.camera->Angles.Roll; - DVector3 relx, rely, relz; - DMatrix3x3 rot = - DMatrix3x3(DVector3(0., 0., 1.), yaw.Cos(), yaw.Sin()) * - DMatrix3x3(DVector3(0., 1., 0.), pitch.Cos(), pitch.Sin()) * - DMatrix3x3(DVector3(1., 0., 0.), roll.Cos(), roll.Sin()); - relx = DVector3(1., 0., 0.)*rot; - rely = DVector3(0., 1., 0.)*rot; - relz = DVector3(0., 0., 1.)*rot; - viewpoint.Pos += relx * pos.X + rely * pos.Y + relz * pos.Z; - } - - if (jiggers.Intensity.X != 0 || jiggers.Offset.X != 0) - { - viewpoint.Pos.X += QuakePower(quakefactor, jiggers.Intensity.X, jiggers.Offset.X); - } - if (jiggers.Intensity.Y != 0 || jiggers.Offset.Y != 0) - { - viewpoint.Pos.Y += QuakePower(quakefactor, jiggers.Intensity.Y, jiggers.Offset.Y); - } - if (jiggers.Intensity.Z != 0 || jiggers.Offset.Z != 0) - { - viewpoint.Pos.Z += QuakePower(quakefactor, jiggers.Intensity.Z, jiggers.Offset.Z); - } - } - } - - viewpoint.extralight = viewpoint.camera->player ? viewpoint.camera->player->extralight : 0; + viewPoint.extralight = viewPoint.camera->player != nullptr ? viewPoint.camera->player->extralight : 0; // killough 3/20/98, 4/4/98: select colormap based on player status // [RH] Can also select a blend - newblend = 0; - - TArray &lightlist = viewpoint.sector->e->XFloor.lightlist; + unsigned int newBlend = 0u; + const TArray& lightlist = viewPoint.sector->e->XFloor.lightlist; if (lightlist.Size() > 0) { - for(unsigned int i = 0; i < lightlist.Size(); i++) + for (size_t i = 0u; i < lightlist.Size(); ++i) { - secplane_t *plane; - int viewside; - plane = (i < lightlist.Size()-1) ? &lightlist[i+1].plane : &viewpoint.sector->floorplane; - viewside = plane->PointOnSide(viewpoint.Pos); + const secplane_t& plane = (i < lightlist.Size() - 1u) ? lightlist[i + 1u].plane : viewPoint.sector->floorplane; + int viewSide = plane.PointOnSide(viewPoint.Pos); + // Reverse the direction of the test if the plane was downward facing. // We want to know if the view is above it, whatever its orientation may be. - if (plane->fC() < 0) - viewside = -viewside; - if (viewside > 0) + if (plane.fC() < 0.0) + viewSide = -viewSide; + + if (viewSide > 0) { - // 3d floor 'fog' is rendered as a blending value - PalEntry blendv = lightlist[i].blend; + // 3d floor 'fog' is rendered as a blending value. + PalEntry blend = lightlist[i].blend; - // If no alpha is set, use 50% - if (blendv.a==0 && blendv!=0) blendv.a=128; - newblend = blendv.d; + // If no alpha is set, use 50%. + if (!blend.a && blend != 0) + blend.a = 128u; + + newBlend = blend.d; break; } } } else { - const sector_t *s = viewpoint.sector->GetHeightSec(); - if (s != NULL) + const sector_t* const sec = viewPoint.sector->GetHeightSec(); + if (sec != nullptr) { - newblend = s->floorplane.PointOnSide(viewpoint.Pos) < 0 - ? s->bottommap - : s->ceilingplane.PointOnSide(viewpoint.Pos) < 0 - ? s->topmap - : s->midmap; - if (APART(newblend) == 0 && newblend >= fakecmaps.Size()) - newblend = 0; + newBlend = sec->floorplane.PointOnSide(viewPoint.Pos) < 0 + ? sec->bottommap + : sec->ceilingplane.PointOnSide(viewPoint.Pos) < 0 + ? sec->topmap + : sec->midmap; + + if (APART(newBlend) == 0u && newBlend >= fakecmaps.Size()) + newBlend = 0u; } } // [RH] Don't override testblend unless entering a sector with a // blend different from the previous sector's. Same goes with // NormalLight's maps pointer. - if (R_OldBlend != newblend) - { - R_OldBlend = newblend; - } + if (R_OldBlend != newBlend) + R_OldBlend = newBlend; - validcount++; + ++validcount; if (r_clearbuffer != 0) { - int color; + int color = 0; int hom = r_clearbuffer; - if (hom == 3) - { hom = ((screen->FrameTime / 128) & 1) + 1; - } if (hom == 1) - { color = GPalette.BlackIndex; - } else if (hom == 2) - { color = GPalette.WhiteIndex; - } else if (hom == 4) - { color = (screen->FrameTime / 32) & 255; - } else - { color = pr_hom(); - } + screen->SetClearColor(color); SWRenderer->SetClearColor(color); } @@ -1164,25 +1117,16 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor // Scale the pitch to account for the pixel stretching, because the playsim doesn't know about this and treats it as 1:1. // However, to set up a projection matrix this needs to be adjusted. - double radPitch = viewpoint.Angles.Pitch.Normalized180().Radians(); - double angx = cos(radPitch); - double angy = sin(radPitch) * actor->Level->info->pixelstretch; - double alen = sqrt(angx*angx + angy*angy); - viewpoint.HWAngles.Pitch = FAngle::fromRad((float)asin(angy / alen)); - - viewpoint.HWAngles.Roll = FAngle::fromDeg(viewpoint.Angles.Roll.Degrees()); // copied for convenience. - - // ViewActor only gets set, if the camera actor should not be rendered - if (actor->player && actor->player - players == consoleplayer && - ((actor->player->cheats & CF_CHASECAM) || (r_deathcamera && actor->health <= 0)) && actor == actor->player->mo) - { - viewpoint.ViewActor = nullptr; - } - else - { - viewpoint.ViewActor = actor; - } + const double radPitch = viewPoint.Angles.Pitch.Normalized180().Radians(); + const double angx = cos(radPitch); + const double angy = sin(radPitch) * actor->Level->info->pixelstretch; + const double alen = sqrt(angx*angx + angy*angy); + + viewPoint.HWAngles.Pitch = FAngle::fromRad((float)asin(angy / alen)); + viewPoint.HWAngles.Roll = FAngle::fromDeg(viewPoint.Angles.Roll.Degrees()); + // ViewActor only gets set if the camera actor shouldn't be rendered. + viewPoint.ViewActor = viewPoint.showviewer ? nullptr : actor; } diff --git a/src/rendering/r_utility.h b/src/rendering/r_utility.h index 77254ebece..3013961ebf 100644 --- a/src/rendering/r_utility.h +++ b/src/rendering/r_utility.h @@ -43,9 +43,8 @@ struct FRenderViewpoint int extralight; // extralight to be added to this viewpoint bool showviewer; // show the camera actor? - bool NoPortalPath; // Disable portal interpolation path for actor viewpos. - - void SetViewAngle(const FViewWindow &viewwindow); + bool bForceNoViewer; // Never show the camera Actor. + void SetViewAngle(const FViewWindow& viewWindow); }; @@ -118,7 +117,7 @@ void R_ClearInterpolationPath(); void R_AddInterpolationPoint(const DVector3a &vec); void R_SetViewSize (int blocks); void R_SetFOV (FRenderViewpoint &viewpoint, DAngle fov); -void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor * camera); +void R_SetupFrame(FRenderViewpoint& viewPoint, const FViewWindow& viewWindow, AActor* const camera); void R_SetViewAngle (FRenderViewpoint &viewpoint, const FViewWindow &viewwindow); // Called by startup code. diff --git a/src/rendering/swrenderer/line/r_farclip_line.cpp b/src/rendering/swrenderer/line/r_farclip_line.cpp index 8b2cd07f2d..fd662952e7 100644 --- a/src/rendering/swrenderer/line/r_farclip_line.cpp +++ b/src/rendering/swrenderer/line/r_farclip_line.cpp @@ -93,7 +93,7 @@ namespace swrenderer // reject lines that aren't seen from the portal (if any) // [ZZ] 10.01.2016: lines inside a skybox shouldn't be clipped, although this imposes some limitations on portals in skyboxes. - if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && P_ClipLineToPortal(line->linedef, renderportal->CurrentPortal->dst, Thread->Viewport->viewpoint.Pos)) + if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && P_ClipLineToPortal(line->linedef, renderportal->CurrentPortal->dst, Thread->Viewport->viewpoint.Pos.XY())) return; mFrontCeilingZ1 = mFrontSector->ceilingplane.ZatPoint(line->v1); diff --git a/src/rendering/swrenderer/line/r_line.cpp b/src/rendering/swrenderer/line/r_line.cpp index 1a6717450e..c09801d5ac 100644 --- a/src/rendering/swrenderer/line/r_line.cpp +++ b/src/rendering/swrenderer/line/r_line.cpp @@ -106,7 +106,7 @@ namespace swrenderer // reject lines that aren't seen from the portal (if any) // [ZZ] 10.01.2016: lines inside a skybox shouldn't be clipped, although this imposes some limitations on portals in skyboxes. - if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && P_ClipLineToPortal(line->linedef, renderportal->CurrentPortal->dst, Thread->Viewport->viewpoint.Pos)) + if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && P_ClipLineToPortal(line->linedef, renderportal->CurrentPortal->dst, Thread->Viewport->viewpoint.Pos.XY())) return; mFrontCeilingZ1 = mFrontSector->ceilingplane.ZatPoint(line->v1); diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index 0e2338d1e9..bd7ae48c4a 100644 --- a/src/rendering/swrenderer/line/r_walldraw.cpp +++ b/src/rendering/swrenderer/line/r_walldraw.cpp @@ -108,7 +108,7 @@ namespace swrenderer { for (int j = x1; j < x2; ++j) { - down[j] = clamp(most3.ScreenY[j], up[j], dwal[j]); + down[j] = max(min(most3.ScreenY[j], up[j]), dwal[j]); // this cannot use clamp due to failing range checks. } ProcessNormalWall(up, down, texcoords); up = down; diff --git a/src/rendering/swrenderer/line/r_wallsetup.cpp b/src/rendering/swrenderer/line/r_wallsetup.cpp index 2ecf3cab96..c2359325d1 100644 --- a/src/rendering/swrenderer/line/r_wallsetup.cpp +++ b/src/rendering/swrenderer/line/r_wallsetup.cpp @@ -501,7 +501,7 @@ namespace swrenderer double rowoffset = lineseg->sidedef->GetTextureYOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureYOffset(side_t::mid); double planez = rover->model->GetPlaneTexZ(sector_t::ceiling); - fixed_t xoffset = FLOAT2FIXED(lineseg->sidedef->GetTextureXOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureXOffset(side_t::mid)); + fixed_t xoffset = xs_Fix<16>::ToFix(lineseg->sidedef->GetTextureXOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureXOffset(side_t::mid)); if (rowoffset < 0) { rowoffset += pic->GetHeight(); @@ -633,7 +633,7 @@ namespace swrenderer fixed_t ProjectedWallTexcoords::GetXOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart) { - fixed_t TextureOffsetU = FLOAT2FIXED(lineseg->sidedef->GetTextureXOffset(texpart)); + fixed_t TextureOffsetU = xs_Fix<16>::ToFix(lineseg->sidedef->GetTextureXOffset(texpart)); double xscale = GetXScale(lineseg->sidedef, tex, texpart); fixed_t xoffset; diff --git a/src/rendering/swrenderer/plane/r_skyplane.cpp b/src/rendering/swrenderer/plane/r_skyplane.cpp index 35a04cf4c5..9020b76a7e 100644 --- a/src/rendering/swrenderer/plane/r_skyplane.cpp +++ b/src/rendering/swrenderer/plane/r_skyplane.cpp @@ -186,7 +186,7 @@ namespace swrenderer // to allow sky rotation as well as careful positioning. // However, the offset is scaled very small, so that it // allows a long-period of sky rotation. - skyangle += FLOAT2FIXED(s->GetTextureXOffset(pos)); + skyangle += xs_Fix<16>::ToFix(s->GetTextureXOffset(pos)); // Vertical offset allows careful sky positioning. skymid = s->GetTextureYOffset(pos) - 28.0; diff --git a/src/rendering/swrenderer/plane/r_slopeplane.cpp b/src/rendering/swrenderer/plane/r_slopeplane.cpp index 808a1a0b73..0a13c11ebd 100644 --- a/src/rendering/swrenderer/plane/r_slopeplane.cpp +++ b/src/rendering/swrenderer/plane/r_slopeplane.cpp @@ -89,7 +89,7 @@ namespace swrenderer auto viewport = Thread->Viewport.get(); // Stupid way of doing it, but at least it works - DVector3 worldP0(viewport->viewpoint.Pos, pl->height.ZatPoint(viewport->viewpoint.Pos)); + DVector3 worldP0(viewport->viewpoint.Pos.XY(), pl->height.ZatPoint(viewport->viewpoint.Pos)); DVector3 worldP1 = worldP0 + pl->height.Normal(); DVector3 viewP0 = viewport->PointWorldToView(worldP0); DVector3 viewP1 = viewport->PointWorldToView(worldP1); diff --git a/src/rendering/swrenderer/r_renderer.h b/src/rendering/swrenderer/r_renderer.h index 2ad6c79004..7d873f5f0b 100644 --- a/src/rendering/swrenderer/r_renderer.h +++ b/src/rendering/swrenderer/r_renderer.h @@ -11,7 +11,6 @@ class AActor; class player_t; struct sector_t; class FCanvasTexture; -class FileWriter; class DCanvas; struct FLevelLocals; class PClassActor; diff --git a/src/rendering/swrenderer/r_swcolormaps.cpp b/src/rendering/swrenderer/r_swcolormaps.cpp index a2ca4666df..1ff95c8b31 100644 --- a/src/rendering/swrenderer/r_swcolormaps.cpp +++ b/src/rendering/swrenderer/r_swcolormaps.cpp @@ -346,9 +346,9 @@ void SetDefaultColormap (const char *name) uint8_t unremap[256]; uint8_t remap[256]; - lump = fileSystem.CheckNumForFullName (name, true, ns_colormaps); + lump = fileSystem.CheckNumForFullName (name, true, FileSys::ns_colormaps); if (lump == -1) - lump = fileSystem.CheckNumForName (name, ns_global); + lump = fileSystem.CheckNumForName (name, FileSys::ns_global); // [RH] If using BUILD's palette, generate the colormap if (lump == -1 || fileSystem.CheckNumForFullName("palette.dat") >= 0 || fileSystem.CheckNumForFullName("blood.pal") >= 0) @@ -515,7 +515,7 @@ CCMD (testfade) { if ( !(colorstring = V_GetColorStringByName (argv[1])).IsEmpty() ) { - color = V_GetColorFromString (colorstring); + color = V_GetColorFromString (colorstring.GetChars()); } else { @@ -549,7 +549,7 @@ CCMD (testcolor) { if ( !(colorstring = V_GetColorStringByName (argv[1])).IsEmpty() ) { - color = V_GetColorFromString (colorstring); + color = V_GetColorFromString (colorstring.GetChars()); } else { diff --git a/src/rendering/swrenderer/r_swrenderer.cpp b/src/rendering/swrenderer/r_swrenderer.cpp index 4c2414db5a..bb7340ef4b 100644 --- a/src/rendering/swrenderer/r_swrenderer.cpp +++ b/src/rendering/swrenderer/r_swrenderer.cpp @@ -271,9 +271,13 @@ void FSoftwareRenderer::SetColormap(FLevelLocals *Level) NormalLight.Maps = realcolormaps.Maps; NormalLight.ChangeColor(PalEntry(255, 255, 255), 0); NormalLight.ChangeFade(Level->fadeto); - if (Level->fadeto == 0) + if(Level->globalcolormap != 0) // this deliberately ignores the translated value and goes directly to the source. { - SetDefaultColormap(Level->info->FadeTable); + SetDefaultColormap(Level->info->CustomColorMap.GetChars()); + } + else if (Level->fadeto == 0) + { + SetDefaultColormap(Level->info->FadeTable.GetChars()); } } diff --git a/src/rendering/swrenderer/r_swscene.cpp b/src/rendering/swrenderer/r_swscene.cpp index 491370dfcf..2b29d6f704 100644 --- a/src/rendering/swrenderer/r_swscene.cpp +++ b/src/rendering/swrenderer/r_swscene.cpp @@ -48,7 +48,7 @@ class FSWPaletteTexture : public FImageSource Height = 1; } - int CopyPixels(FBitmap *bmp, int conversion) override + int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override { PalEntry *pe = (PalEntry*)bmp->GetPixels(); for (int i = 0; i < 256; i++) @@ -102,7 +102,7 @@ sector_t *SWSceneDrawer::RenderView(player_t *player) fbtex.reset(MakeGameTexture(new FWrapperTexture(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor()), nullptr, ETextureType::SWCanvas)); GetSystemTexture()->AllocateBuffer(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor() ? 4 : 1); auto mat = FMaterial::ValidateTexture(fbtex.get(), false); - mat->AddTextureLayer(PaletteTexture, false); + mat->AddTextureLayer(PaletteTexture, false, MaterialLayerSampling::Default); Canvas.reset(); Canvas.reset(new DCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor())); diff --git a/src/rendering/swrenderer/scene/r_opaque_pass.cpp b/src/rendering/swrenderer/scene/r_opaque_pass.cpp index bcd864d05c..f942446441 100644 --- a/src/rendering/swrenderer/scene/r_opaque_pass.cpp +++ b/src/rendering/swrenderer/scene/r_opaque_pass.cpp @@ -555,7 +555,7 @@ namespace swrenderer frontsector->GetAlpha(sector_t::ceiling), !!(frontsector->GetFlags(sector_t::ceiling) & PLANEF_ADDITIVE), frontsector->planes[sector_t::ceiling].xform, - frontsector->sky, + frontsector->skytransfer, portal, basecolormap, Fake3DOpaque::Normal, @@ -595,7 +595,7 @@ namespace swrenderer frontsector->GetAlpha(sector_t::floor), !!(frontsector->GetFlags(sector_t::floor) & PLANEF_ADDITIVE), frontsector->planes[sector_t::floor].xform, - frontsector->sky, + frontsector->skytransfer, portal, basecolormap, Fake3DOpaque::Normal, @@ -732,7 +732,7 @@ namespace swrenderer tempsec.GetAlpha(sector_t::floor), !!(clip3d->fakeFloor->fakeFloor->flags & FF_ADDITIVETRANS), tempsec.planes[position].xform, - tempsec.sky, + tempsec.skytransfer, nullptr, basecolormap, Fake3DOpaque::FakeFloor, @@ -800,7 +800,7 @@ namespace swrenderer tempsec.GetAlpha(sector_t::ceiling), !!(clip3d->fakeFloor->fakeFloor->flags & FF_ADDITIVETRANS), tempsec.planes[position].xform, - tempsec.sky, + tempsec.skytransfer, nullptr, basecolormap, Fake3DOpaque::FakeCeiling, @@ -853,7 +853,7 @@ namespace swrenderer node_t *bsp = (node_t *)node; // Decide which side the view point is on. - int side = R_PointOnSide(Thread->Viewport->viewpoint.Pos, bsp); + int side = R_PointOnSide(Thread->Viewport->viewpoint.Pos.XY(), bsp); // Recursively divide front space (toward the viewer). RenderBSPNode(bsp->children[side]); @@ -1046,7 +1046,7 @@ namespace swrenderer // The X offsetting (SpriteOffset.X) is performed in r_sprite.cpp, in RenderSprite::Project(). sprite.pos = thing->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac); sprite.pos += thing->WorldOffset; - sprite.pos.Z += thing->GetBobOffset(Thread->Viewport->viewpoint.TicFrac) - thing->SpriteOffset.Y; + sprite.pos.Z += thing->GetBobOffset(Thread->Viewport->viewpoint.TicFrac) + thing->GetSpriteOffset(true); sprite.spritenum = thing->sprite; sprite.tex = nullptr; sprite.voxel = nullptr; diff --git a/src/rendering/swrenderer/textures/warpbuffer.h b/src/rendering/swrenderer/textures/warpbuffer.h index 7787068505..bbff5d9e72 100644 --- a/src/rendering/swrenderer/textures/warpbuffer.h +++ b/src/rendering/swrenderer/textures/warpbuffer.h @@ -31,6 +31,7 @@ **--------------------------------------------------------------------------- ** */ +#pragma once #include "textures.h" #include "texturemanager.h" @@ -43,7 +44,7 @@ void WarpBuffer(TYPE *Pixels, const TYPE *source, int width, int height, int xmu if (warptype == 1) { - TYPE *buffer = (TYPE *)alloca(sizeof(TYPE) * max(width, height)); + TArray buffer(max(width, height), true); // [mxd] Rewrote to fix animation for NPo2 textures unsigned timebase = unsigned(time * Speed * 32 / 28); for (y = height - 1; y >= 0; y--) @@ -63,10 +64,10 @@ void WarpBuffer(TYPE *Pixels, const TYPE *source, int width, int height, int xmu if (yf < 0) yf += height; int yt = yf; const TYPE *sourcep = Pixels + (x + ymask * x); - TYPE *dest = buffer; + TYPE *dest = buffer.data(); for (yt = height; yt; yt--, yf = (yf + 1) % height) *dest++ = sourcep[yf]; - memcpy(Pixels + (x + ymask*x), buffer, height * sizeof(TYPE)); + memcpy(Pixels + (x + ymask*x), buffer.data(), height * sizeof(TYPE)); } } else if (warptype == 2) diff --git a/src/rendering/swrenderer/things/r_particle.cpp b/src/rendering/swrenderer/things/r_particle.cpp index 23a859c0e5..ccd2fe064c 100644 --- a/src/rendering/swrenderer/things/r_particle.cpp +++ b/src/rendering/swrenderer/things/r_particle.cpp @@ -90,7 +90,7 @@ namespace swrenderer RenderPortal *renderportal = thread->Portal.get(); // [ZZ] Particle not visible through the portal plane - if (renderportal->CurrentPortal && !!P_PointOnLineSide(particle->Pos, renderportal->CurrentPortal->dst)) + if (renderportal->CurrentPortal && !!P_PointOnLineSide(particle->Pos.XY(), renderportal->CurrentPortal->dst)) return; // transform the origin point @@ -223,7 +223,7 @@ namespace swrenderer vis->floorclip = 0; vis->foggy = foggy; - vis->Light.SetColormap(thread, tz, lightlevel, foggy, map, particle->bright != 0, false, false, false, true); + vis->Light.SetColormap(thread, tz, lightlevel, foggy, map, particle->flags & SPF_FULLBRIGHT, false, false, false, true); thread->SpriteList->Push(vis); } diff --git a/src/rendering/swrenderer/things/r_playersprite.cpp b/src/rendering/swrenderer/things/r_playersprite.cpp index 87ae074961..4e81554d32 100644 --- a/src/rendering/swrenderer/things/r_playersprite.cpp +++ b/src/rendering/swrenderer/things/r_playersprite.cpp @@ -307,9 +307,9 @@ namespace swrenderer vis.yscale = float(pspriteyscale / stex->GetScale().Y); vis.pic = stex; - uint32_t trans = pspr->GetTranslation() != 0 ? pspr->GetTranslation() : 0; - if ((pspr->Flags & PSPF_PLAYERTRANSLATED)) trans = owner->Translation; - vis.Translation = trans; + auto itrans = pspr->GetTranslation(); + if ((pspr->Flags & PSPF_PLAYERTRANSLATED)) itrans = owner->Translation; + vis.Translation = itrans; // If flip is used, provided that it's not already flipped (that would just invert itself) // (It's an XOR...) @@ -432,7 +432,7 @@ namespace swrenderer accelSprite.x1 = x1; accelSprite.flip = vis.xiscale < 0; - accelSprite.Translation = trans; + accelSprite.Translation = itrans; if (vis.Light.BaseColormap >= &SpecialSWColormaps[0] && vis.Light.BaseColormap < &SpecialSWColormaps[SpecialColormaps.Size()]) @@ -468,7 +468,7 @@ namespace swrenderer viewwindowy + viewheight / 2 - sprite.texturemid * sprite.yscale - 0.5, DTA_DestWidthF, FIXED2DBL(sprite.pic->GetWidth() * sprite.xscale), DTA_DestHeightF, sprite.pic->GetHeight() * sprite.yscale, - DTA_TranslationIndex, sprite.Translation, + DTA_TranslationIndex, sprite.Translation.index(), DTA_FlipX, sprite.flip, DTA_TopOffset, 0, DTA_LeftOffset, 0, diff --git a/src/rendering/swrenderer/things/r_playersprite.h b/src/rendering/swrenderer/things/r_playersprite.h index b32f0bf8e1..23408d6afc 100644 --- a/src/rendering/swrenderer/things/r_playersprite.h +++ b/src/rendering/swrenderer/things/r_playersprite.h @@ -23,6 +23,7 @@ #include "r_visiblesprite.h" #include "r_data/colormaps.h" +#include "palettecontainer.h" class DPSprite; @@ -46,7 +47,7 @@ namespace swrenderer float Alpha = 0.0f; FRenderStyle RenderStyle; - uint32_t Translation = 0; + FTranslationID Translation = NO_TRANSLATION; uint32_t FillColor = 0; ColormapLight Light; @@ -66,7 +67,7 @@ namespace swrenderer float Alpha = 0.0f; FRenderStyle RenderStyle; - uint32_t Translation = 0; + FTranslationID Translation = NO_TRANSLATION; // this gets passed to the 2D code which works with high level IDs. uint32_t FillColor = 0; FDynamicColormap *basecolormap = nullptr; diff --git a/src/rendering/swrenderer/things/r_sprite.cpp b/src/rendering/swrenderer/things/r_sprite.cpp index 39c2e82e35..b05a674480 100644 --- a/src/rendering/swrenderer/things/r_sprite.cpp +++ b/src/rendering/swrenderer/things/r_sprite.cpp @@ -81,7 +81,7 @@ namespace swrenderer const double thingxscalemul = spriteScale.X / tex->GetScale().X; // Calculate billboard line for the sprite - double SpriteOffX = (thing) ? thing->SpriteOffset.X : 0.; + double SpriteOffX = (thing) ? -thing->GetSpriteOffset(false) : 0.; DVector2 dir = { viewport->viewpoint.Sin, -viewport->viewpoint.Cos }; DVector2 trs = pos.XY() - viewport->viewpoint.Pos.XY(); trs = { trs.X + SpriteOffX * dir.X, trs.Y + SpriteOffX * dir.Y }; diff --git a/src/rendering/swrenderer/things/r_sprite.h b/src/rendering/swrenderer/things/r_sprite.h index 12f9170ab7..8f08df086b 100644 --- a/src/rendering/swrenderer/things/r_sprite.h +++ b/src/rendering/swrenderer/things/r_sprite.h @@ -16,7 +16,7 @@ namespace swrenderer FWallCoords wallc; double SpriteScale; - uint32_t Translation = 0; + FTranslationID Translation = NO_TRANSLATION; uint32_t FillColor = 0; uint32_t dynlightcolor = 0; diff --git a/src/rendering/swrenderer/things/r_visiblesprite.cpp b/src/rendering/swrenderer/things/r_visiblesprite.cpp index 1878008cd5..a91b851a45 100644 --- a/src/rendering/swrenderer/things/r_visiblesprite.cpp +++ b/src/rendering/swrenderer/things/r_visiblesprite.cpp @@ -193,7 +193,7 @@ namespace swrenderer { // only things in specially marked sectors if (spr->FakeFlatStat != WaterFakeSide::AboveCeiling) { - double hz = spr->heightsec->floorplane.ZatPoint(spr->gpos); + double hz = spr->heightsec->floorplane.ZatPoint(spr->gpos.XY()); int h = xs_RoundToInt(viewport->CenterY - (hz - viewport->viewpoint.Pos.Z) * scale); if (spr->FakeFlatStat == WaterFakeSide::BelowFloor) @@ -215,7 +215,7 @@ namespace swrenderer } if (spr->FakeFlatStat != WaterFakeSide::BelowFloor && !(spr->heightsec->MoreFlags & SECMF_FAKEFLOORONLY)) { - double hz = spr->heightsec->ceilingplane.ZatPoint(spr->gpos); + double hz = spr->heightsec->ceilingplane.ZatPoint(spr->gpos.XY()); int h = xs_RoundToInt(viewport->CenterY - (hz - viewport->viewpoint.Pos.Z) * scale); if (spr->FakeFlatStat == WaterFakeSide::AboveCeiling) diff --git a/src/rendering/swrenderer/things/r_voxel.cpp b/src/rendering/swrenderer/things/r_voxel.cpp index 455ad48ab5..28d8921f07 100644 --- a/src/rendering/swrenderer/things/r_voxel.cpp +++ b/src/rendering/swrenderer/things/r_voxel.cpp @@ -373,8 +373,8 @@ namespace swrenderer if ((abs(globalposz - dasprz) >> 10) >= abs(dazscale)) return; x = 0; y = 0; j = max(mip->SizeX, mip->SizeY); - fixed_t *ggxinc = (fixed_t *)alloca((j + 1) * sizeof(fixed_t) * 2); - fixed_t *ggyinc = ggxinc + (j + 1); + TArray ggxinc((j + 1) * 2); + fixed_t *ggyinc = ggxinc.data() + (j + 1); for (i = 0; i <= j; i++) { ggxinc[i] = x; x += gxinc; diff --git a/src/rendering/swrenderer/things/r_voxel.h b/src/rendering/swrenderer/things/r_voxel.h index 94405ef97e..24b3dfc3e1 100644 --- a/src/rendering/swrenderer/things/r_voxel.h +++ b/src/rendering/swrenderer/things/r_voxel.h @@ -85,7 +85,7 @@ namespace swrenderer FVoxel *voxel = nullptr; bool bInMirror = false; - uint32_t Translation = 0; + FTranslationID Translation = NO_TRANSLATION; uint32_t FillColor = 0; enum { DVF_OFFSCREEN = 1, DVF_SPANSONLY = 2, DVF_MIRRORED = 4, DVF_FIND_X1X2 = 8 }; diff --git a/src/rendering/swrenderer/things/r_wallsprite.h b/src/rendering/swrenderer/things/r_wallsprite.h index b512ec960b..09384b474c 100644 --- a/src/rendering/swrenderer/things/r_wallsprite.h +++ b/src/rendering/swrenderer/things/r_wallsprite.h @@ -18,7 +18,7 @@ namespace swrenderer private: FWallCoords wallc; - uint32_t Translation = 0; + FTranslationID Translation = NO_TRANSLATION; uint32_t FillColor = 0; }; } diff --git a/src/rendering/swrenderer/viewport/r_spritedrawer.cpp b/src/rendering/swrenderer/viewport/r_spritedrawer.cpp index 8217eeaf5b..b40ddd8b4b 100644 --- a/src/rendering/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/rendering/swrenderer/viewport/r_spritedrawer.cpp @@ -432,7 +432,7 @@ namespace swrenderer } } - bool SpriteDrawerArgs::SetStyle(RenderViewport *viewport, FRenderStyle style, fixed_t alpha, int translation, uint32_t color, const ColormapLight &light) + bool SpriteDrawerArgs::SetStyle(RenderViewport *viewport, FRenderStyle style, fixed_t alpha, FTranslationID translation, uint32_t color, const ColormapLight &light) { if (light.BaseColormap) SetLight(light); @@ -466,19 +466,16 @@ namespace swrenderer alpha = clamp(alpha, 0, OPAQUE); } - if (translation != -1) + SetTranslationMap(nullptr); + if (translation != NO_TRANSLATION) { - SetTranslationMap(nullptr); - if (translation != 0) + FRemapTable *table = GPalette.TranslationToTable(translation); + if (table != NULL) { - FRemapTable *table = GPalette.TranslationToTable(translation); - if (table != NULL && !table->Inactive) - { - if (viewport->RenderTarget->IsBgra()) - SetTranslationMap((uint8_t*)table->Palette); - else - SetTranslationMap(table->Remap); - } + if (viewport->RenderTarget->IsBgra()) + SetTranslationMap((uint8_t*)table->Palette); + else + SetTranslationMap(table->Remap); } } @@ -547,7 +544,7 @@ namespace swrenderer return SpriteDrawerArgs::SetBlendFunc(style.BlendOp, fglevel, bglevel, style.Flags); } - bool SpriteDrawerArgs::SetStyle(RenderViewport *viewport, FRenderStyle style, float alpha, int translation, uint32_t color, const ColormapLight &light) + bool SpriteDrawerArgs::SetStyle(RenderViewport *viewport, FRenderStyle style, float alpha, FTranslationID translation, uint32_t color, const ColormapLight &light) { return SetStyle(viewport, style, FLOAT2FIXED(alpha), translation, color, light); } diff --git a/src/rendering/swrenderer/viewport/r_spritedrawer.h b/src/rendering/swrenderer/viewport/r_spritedrawer.h index e1c504f7c6..85d87f3299 100644 --- a/src/rendering/swrenderer/viewport/r_spritedrawer.h +++ b/src/rendering/swrenderer/viewport/r_spritedrawer.h @@ -28,8 +28,8 @@ namespace swrenderer public: SpriteDrawerArgs(); - bool SetStyle(RenderViewport *viewport, FRenderStyle style, fixed_t alpha, int translation, uint32_t color, const ColormapLight &light); - bool SetStyle(RenderViewport *viewport, FRenderStyle style, float alpha, int translation, uint32_t color, const ColormapLight &light); + bool SetStyle(RenderViewport *viewport, FRenderStyle style, fixed_t alpha, FTranslationID translation, uint32_t color, const ColormapLight &light); + bool SetStyle(RenderViewport *viewport, FRenderStyle style, float alpha, FTranslationID translation, uint32_t color, const ColormapLight &light); void SetSolidColor(int color) { dc_color = color; dc_color_bgra = GPalette.BaseColors[color]; } void SetDynamicLight(uint32_t color) { dynlightcolor = color; } diff --git a/src/scripting/backend/codegen_doom.cpp b/src/scripting/backend/codegen_doom.cpp index 1d008446ce..0e52790d72 100644 --- a/src/scripting/backend/codegen_doom.cpp +++ b/src/scripting/backend/codegen_doom.cpp @@ -57,6 +57,19 @@ PFunction* FindBuiltinFunction(FName funcname); // //========================================================================== +bool ShouldAllowGameSpecificVirtual(FName name, unsigned index, PType* arg, PType* varg) +{ + return (name == NAME_Morph && index == 3u && arg->isClassPointer() && varg->isClassPointer() + && PType::toClassPointer(varg)->ClassRestriction->TypeName == NAME_Actor + && PType::toClassPointer(arg)->ClassRestriction->TypeName == NAME_MorphedMonster); +} + +//========================================================================== +// +// +// +//========================================================================== + bool isActor(PContainerType *type) { auto cls = PType::toClass(type); @@ -92,7 +105,7 @@ static FxExpression *CustomTypeCast(FxTypeCast *func, FCompileContext &ctx) delete func; return nullptr; } - FxExpression *x = new FxMultiNameState(s, basex->ScriptPosition); + FxExpression *x = new FxMultiNameState(s.GetChars(), basex->ScriptPosition); x = x->Resolve(ctx); basex = nullptr; delete func; @@ -309,7 +322,8 @@ static bool UnravelVarArgAJump(FxVMFunctionCall *func, FCompileContext &ctx) static bool AJumpProcessing(FxVMFunctionCall *func, FCompileContext &ctx) { // Unfortunately the PrintableName is the only safe thing to catch this special case here. - if (func->Function->Variants[0].Implementation->PrintableName.CompareNoCase("Actor.A_Jump [Native]") == 0) + // [RL0] It's not valid to access Variant::Implementation on function pointer calls, so skip this + if (!func->FnPtrCall && stricmp(func->Function->Variants[0].Implementation->QualifiedName, "Actor.A_Jump") == 0) { // Unravel the varargs part of this function here so that the VM->native interface does not have to deal with it anymore. if (func->ArgList.Size() > 2) @@ -811,10 +825,10 @@ FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPositi if (scopeindex >= 0) { - scopename = FName(statestring, scopeindex, false); + scopename = FName(statestring.GetChars(), scopeindex, false); statestring = statestring.Right((ptrdiff_t)statestring.Len() - scopeindex - 2); } - names = MakeStateNameList(statestring); + names = MakeStateNameList(statestring.GetChars()); names.Insert(0, scopename); scope = checkclass; } @@ -925,6 +939,11 @@ static DObject *BuiltinNewDoom(PClass *cls, int outerside, int backwardscompatib ThrowAbortException(X_OTHER, "Cannot create actors with 'new'"); return nullptr; } + if (cls->IsDescendantOf(NAME_VisualThinker)) // Same for VisualThinkers. + { + ThrowAbortException(X_OTHER, "Cannot create VisualThinker or inheriting classes with 'new'. Use 'VisualThinker.Spawn' instead."); + return nullptr; + } if ((vm_warnthinkercreation || !backwardscompatible) && cls->IsDescendantOf(NAME_Thinker)) { // This must output a diagnostic warning @@ -966,3 +985,349 @@ void SetDoomCompileEnvironment() compileEnvironment.CheckCustomGlobalFunctions = ResolveGlobalCustomFunction; compileEnvironment.CustomBuiltinNew = "BuiltinNewDoom"; } + + +//========================================================================== +// +// FxCastForEachLoop +// +//========================================================================== + + +class FxCastForEachLoop : public FxTypedForEachLoop +{ +public: + using FxTypedForEachLoop::FxTypedForEachLoop; + + FxExpression *Resolve(FCompileContext&); + //ExpEmit Emit(VMFunctionBuilder *build); This node is transformed, so it won't ever be emitted itself +}; + +FxExpression *FxCastForEachLoop::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Expr, ctx); + + if(varName == NAME_None) + { + ScriptPosition.Message(MSG_ERROR, "missing var for foreach(Type var : it )"); + delete this; + return nullptr; + } + + PType * varType = nullptr; + PClass * itType = ((PObjectPointer*)Expr->ValueType)->PointedClass(); + + FName fieldName = NAME_None; + + if(itType->TypeName == NAME_ActorIterator) + { + fieldName = "Actor"; + } + else if(itType->TypeName == NAME_ThinkerIterator) + { + fieldName = "Thinker"; + } + else + { + ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - 'it' must be an actor or thinker iterator, but is a %s",Expr->ValueType->DescriptiveName()); + delete this; + return nullptr; + } + + if(className != NAME_None) + { + fieldName = className; + } + + PClass * varTypeClass = PClass::FindClass(fieldName); + varType = varTypeClass->VMType; + + if(!varType) + { + ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - could not find class '%s'",className.GetChars()); + delete this; + return nullptr; + } + + varType = NewPointer(varType, false); + + /* + { + CastType var; + ActorIterator|ThinkerIterator @it = expr; + while(var = CastType(@it.Next())) + body + } + */ + + auto block = new FxCompoundStatement(ScriptPosition); + + block->Add(new FxLocalVariableDeclaration(varType, varName, nullptr, 0, ScriptPosition)); + + block->Add(new FxLocalVariableDeclaration(Expr->ValueType, "@it", Expr, 0, ScriptPosition)); + + auto inner_block = new FxCompoundStatement(ScriptPosition); + + FxExpression * nextCallCast = new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "Next", {}, ScriptPosition); + + if(className != NAME_None) + { + nextCallCast = new FxDynamicCast(varTypeClass, nextCallCast); + } + + block->Add(new FxWhileLoop(new FxAssign(new FxIdentifier(varName, ScriptPosition), nextCallCast), Code, ScriptPosition)); + + Expr = Code = nullptr; + delete this; + return block->Resolve(ctx); +} + + + +//========================================================================== +// +// FxBlockIteratorForEachLoop +// +//========================================================================== + +class FxBlockIteratorForEachLoop : public FxThreeArgForEachLoop +{ +public: + using FxThreeArgForEachLoop::FxThreeArgForEachLoop; + + FxExpression *Resolve(FCompileContext&); + //ExpEmit Emit(VMFunctionBuilder *build); This node is transformed, so it won't ever be emitted itself +}; + +FxExpression *FxBlockIteratorForEachLoop::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(BlockIteratorExpr, ctx); + + + if(!(BlockIteratorExpr->ValueType->isObjectPointer())) + { + ScriptPosition.Message(MSG_ERROR, "foreach( v, p, f : b ) - 'b' must be a block things or block lines iterator, but is a %s",BlockIteratorExpr->ValueType->DescriptiveName()); + delete this; + return nullptr; + } + else if(varVarName == NAME_None) + { + ScriptPosition.Message(MSG_ERROR, "missing var for foreach( v, p, f : b )"); + delete this; + return nullptr; + } + + PType * varType = nullptr; + PClass * itType = ((PObjectPointer*)BlockIteratorExpr->ValueType)->PointedClass(); + + FName fieldName = NAME_None; + + if(itType->TypeName == NAME_BlockThingsIterator) + { + fieldName = "Thing"; + } + else if(itType->TypeName == NAME_BlockLinesIterator) + { + fieldName = "CurLine"; + } + else + { + ScriptPosition.Message(MSG_ERROR, "foreach( t, p, f : b ) - 'b' must be a block things or block lines iterator, but is a %s",BlockIteratorExpr->ValueType->DescriptiveName()); + delete this; + return nullptr; + } + + auto var = itType->FindSymbol(fieldName, false); + if(var && var->IsKindOf(RUNTIME_CLASS(PField))) + { + varType = static_cast(var)->Type; + } + + /* + { + Line|Actor var; + Vector3 pos; + int flags; + BlockLinesIterator|BlockThingsIterator @it = expr; + while(@it.Next()) + { + var = @it.CurLine|@it.Thing; + pos = @it.position; + flags = @it.portalflags; + body + } + } + */ + + auto block = new FxCompoundStatement(ScriptPosition); + + block->Add(new FxLocalVariableDeclaration(varType, varVarName, nullptr, 0, ScriptPosition)); + if(posVarName != NAME_None) + { + block->Add(new FxLocalVariableDeclaration(TypeVector3, posVarName, nullptr, 0, ScriptPosition)); + } + if(flagsVarName != NAME_None) + { + block->Add(new FxLocalVariableDeclaration(TypeSInt32, flagsVarName, nullptr, 0, ScriptPosition)); + } + + block->Add(new FxLocalVariableDeclaration(BlockIteratorExpr->ValueType, "@it", BlockIteratorExpr, 0, ScriptPosition)); + + auto inner_block = new FxCompoundStatement(ScriptPosition); + + inner_block->Add(new FxAssign(new FxIdentifier(varVarName, ScriptPosition), new FxMemberIdentifier(new FxIdentifier("@it", ScriptPosition), fieldName, ScriptPosition), true)); + if(posVarName != NAME_None) + { + inner_block->Add(new FxAssign(new FxIdentifier(posVarName, ScriptPosition), new FxMemberIdentifier(new FxIdentifier("@it", ScriptPosition), "position", ScriptPosition), true)); + } + if(flagsVarName != NAME_None) + { + inner_block->Add(new FxAssign(new FxIdentifier(flagsVarName, ScriptPosition), new FxMemberIdentifier(new FxIdentifier("@it", ScriptPosition), "portalflags", ScriptPosition), true)); + } + inner_block->Add(Code); + + block->Add(new FxWhileLoop(new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "Next", {}, ScriptPosition), inner_block, ScriptPosition)); + + BlockIteratorExpr = Code = nullptr; + delete this; + return block->Resolve(ctx); +} + + + + + + + + + + +bool IsGameSpecificForEachLoop(FxForEachLoop * loop) +{ + auto * vt = loop->Array->ValueType; + return (vt->isObjectPointer() && ( + ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_BlockLinesIterator + || ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_BlockThingsIterator + || ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_ActorIterator + || ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_ThinkerIterator + )); +} + +FxExpression * ResolveGameSpecificForEachLoop(FxForEachLoop * loop) +{ + FName cname = ((PObjectPointer*)loop->Array->ValueType)->PointedClass()->TypeName; + assert(loop->Array->ValueType->isObjectPointer()); + if(cname == NAME_BlockLinesIterator || cname == NAME_BlockThingsIterator) + { + auto blockIt = new FxBlockIteratorForEachLoop(loop->loopVarName, NAME_None, NAME_None, loop->Array, loop->Code, loop->ScriptPosition); + loop->Array = loop->Code = nullptr; + delete loop; + return blockIt; + } + else if(cname == NAME_ActorIterator || cname == NAME_ThinkerIterator) + { + auto castIt = new FxCastForEachLoop(NAME_None, loop->loopVarName, loop->Array, loop->Code, loop->ScriptPosition); + loop->Array = loop->Code = nullptr; + delete loop; + return castIt; + } + else + { + delete loop; + return nullptr; + } +} + + +bool HasGameSpecificTwoArgForEachLoopTypeNames() +{ + return true; +} + +const char * GetGameSpecificTwoArgForEachLoopTypeNames() +{ + return "a BlockLinesIterator, a BlockThingsIterator,"; +} + +bool IsGameSpecificTwoArgForEachLoop(FxTwoArgForEachLoop * loop) +{ + return (loop->MapExpr->ValueType->isObjectPointer() + && (((PObjectPointer*)loop->MapExpr->ValueType)->PointedClass()->TypeName == NAME_BlockLinesIterator + || ((PObjectPointer*)loop->MapExpr->ValueType)->PointedClass()->TypeName == NAME_BlockThingsIterator)); +} + +FxExpression * ResolveGameSpecificTwoArgForEachLoop(FxTwoArgForEachLoop * loop) +{ + assert(loop->MapExpr->ValueType->isObjectPointer()); + assert(((PObjectPointer*)loop->MapExpr->ValueType)->PointedClass()->TypeName == NAME_BlockLinesIterator || ((PObjectPointer*)loop->MapExpr->ValueType)->PointedClass()->TypeName == NAME_BlockThingsIterator); + + auto blockIt = new FxBlockIteratorForEachLoop(loop->keyVarName, loop->valueVarName, NAME_None, loop->MapExpr, loop->Code, loop->ScriptPosition); + loop->MapExpr = loop->Code = nullptr; + delete loop; + return blockIt; +} + + +bool HasGameSpecificThreeArgForEachLoopTypeNames() +{ + return true; +} + +const char * GetGameSpecificThreeArgForEachLoopTypeNames() +{ + return "a BlockLinesIterator or a BlockThingsIterator"; +} + +bool IsGameSpecificThreeArgForEachLoop(FxThreeArgForEachLoop * loop) +{ + return (loop->BlockIteratorExpr->ValueType->isObjectPointer() + && (((PObjectPointer*)loop->BlockIteratorExpr->ValueType)->PointedClass()->TypeName == NAME_BlockLinesIterator + || ((PObjectPointer*)loop->BlockIteratorExpr->ValueType)->PointedClass()->TypeName == NAME_BlockThingsIterator)); +} + +FxExpression * ResolveGameSpecificThreeArgForEachLoop(FxThreeArgForEachLoop * loop) +{ + assert(loop->BlockIteratorExpr->ValueType->isObjectPointer()); + assert(((PObjectPointer*)loop->BlockIteratorExpr->ValueType)->PointedClass()->TypeName == NAME_BlockLinesIterator || ((PObjectPointer*)loop->BlockIteratorExpr->ValueType)->PointedClass()->TypeName == NAME_BlockThingsIterator); + + auto blockIt = new FxBlockIteratorForEachLoop(loop->varVarName, loop->posVarName, loop->flagsVarName, loop->BlockIteratorExpr, loop->Code, loop->ScriptPosition); + loop->BlockIteratorExpr = loop->Code = nullptr; + delete loop; + return blockIt; +} + + + + + +bool HasGameSpecificTypedForEachLoopTypeNames() +{ + return true; +} + +const char * GetGameSpecificTypedForEachLoopTypeNames() +{ + return "an ActorIterator or a ThinkerIterator"; +} + +bool IsGameSpecificTypedForEachLoop(FxTypedForEachLoop * loop) +{ + auto * vt = loop->Expr->ValueType; + return (vt->isObjectPointer() && ( + ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_ActorIterator + || ((PObjectPointer*)vt)->PointedClass()->TypeName == NAME_ThinkerIterator + )); +} + +FxExpression * ResolveGameSpecificTypedForEachLoop(FxTypedForEachLoop * loop) +{ + assert(loop->Expr->ValueType->isObjectPointer()); + assert(((PObjectPointer*)loop->Expr->ValueType)->PointedClass()->TypeName == NAME_ActorIterator || ((PObjectPointer*)loop->Expr->ValueType)->PointedClass()->TypeName == NAME_ThinkerIterator); + + FxExpression * castIt = new FxCastForEachLoop(loop->className, loop->varName, loop->Expr, loop->Code, loop->ScriptPosition); + loop->Expr = loop->Code = nullptr; + delete loop; + return castIt; +} \ No newline at end of file diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 2658ebe184..1b27342be0 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -477,7 +477,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) { FArgumentList args; args.Push(exp); - exp = new FxFunctionCall(NAME_ResolveState, NAME_None, args, sc); + exp = new FxFunctionCall(NAME_ResolveState, NAME_None, std::move(args), sc); } sc.MustGetToken(')'); return exp; @@ -512,7 +512,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) ParseFunctionParameters(sc, cls, args, func, "", nullptr); } // FxVMFunctionCall cannot be used here as it lacks some important checks - return new FxFunctionCall(identifier, NAME_None, args, sc); + return new FxFunctionCall(identifier, NAME_None, std::move(args), sc); } } @@ -543,7 +543,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) while (sc.CheckToken(',')); sc.MustGetToken(')'); } - return new FxFunctionCall(identifier, NAME_None, args, sc); + return new FxFunctionCall(identifier, NAME_None, std::move(args), sc); } } else diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 8d49f76044..a1cc7702e9 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -458,7 +458,7 @@ static void ParseActorFlag (FScanner &sc, Baggage &bag, int mod) sc.MustGetString (); part2 = sc.String; } - HandleActorFlag(sc, bag, part1, part2, mod); + HandleActorFlag(sc, bag, part1.GetChars(), part2, mod); } //========================================================================== @@ -722,12 +722,12 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau case 'S': sc.MustGetString(); - conv.s = strings[strings.Reserve(1)] = sc.String; + conv.s = (strings[strings.Reserve(1)] = sc.String).GetChars(); break; case 'T': sc.MustGetString(); - conv.s = strings[strings.Reserve(1)] = strbin1(sc.String); + conv.s = (strings[strings.Reserve(1)] = strbin1(sc.String)).GetChars(); break; case 'C': @@ -747,7 +747,7 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau else { sc.MustGetString (); - conv.s = strings[strings.Reserve(1)] = sc.String; + conv.s = (strings[strings.Reserve(1)] = sc.String).GetChars(); pref.i = 1; } break; @@ -775,7 +775,7 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau do { sc.MustGetString (); - conv.s = strings[strings.Reserve(1)] = sc.String; + conv.s = (strings[strings.Reserve(1)] = sc.String).GetChars(); params.Push(conv); params[0].i++; } @@ -961,7 +961,7 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) sc.UnGet (); } - FPropertyInfo *prop = FindProperty(propname); + FPropertyInfo *prop = FindProperty(propname.GetChars()); if (prop != NULL) { @@ -976,9 +976,9 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) FScriptPosition::ErrorCounter++; } } - else if (MatchString(propname, statenames) != -1) + else if (MatchString(propname.GetChars(), statenames) != -1) { - bag.statedef.SetStateLabel(propname, CheckState (sc, bag.Info)); + bag.statedef.SetStateLabel(propname.GetChars(), CheckState (sc, bag.Info)); } else { @@ -1129,7 +1129,7 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag) { PClassActor *info = CreateNewActor(sc, typeName, parentName); info->ActorInfo()->DoomEdNum = DoomEdNum > 0 ? DoomEdNum : -1; - info->SourceLumpName = fileSystem.GetFileFullPath(sc.LumpNum); + info->SourceLumpName = fileSystem.GetFileFullPath(sc.LumpNum).c_str(); if (!info->SetReplacement(replaceName)) { diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 636d07d3c9..570905741a 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -170,7 +170,7 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage & statestring += '+'; statestring += sc.String; } - if (!bag.statedef.SetGotoLabel(statestring)) + if (!bag.statedef.SetGotoLabel(statestring.GetChars())) { sc.ScriptError("GOTO before first state"); } @@ -207,7 +207,7 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage & { do { - bag.statedef.AddStateLabel(statestring); + bag.statedef.AddStateLabel(statestring.GetChars()); statestring = ParseStateString(sc); if (!statestring.CompareNoCase("GOTO")) { @@ -230,7 +230,7 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage & } scp = sc; - state.sprite = GetSpriteIndex(statestring); + state.sprite = GetSpriteIndex(statestring.GetChars()); state.Misc1 = state.Misc2 = 0; sc.MustGetString(); statestring = sc.String; @@ -334,7 +334,7 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage & auto funcsym = CreateAnonymousFunction(actor->VMType, nullptr, state.UseFlags); state.ActionFunc = FunctionBuildList.AddFunction(bag.Namespace, bag.Version, funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true, bag.statedef.GetStateCount(), int(statestring.Len()), sc.LumpNum); } - int count = bag.statedef.AddStates(&state, statestring, scp); + int count = bag.statedef.AddStates(&state, statestring.GetChars(), scp); if (count < 0) { sc.ScriptError("Invalid frame character string '%s'", statestring.GetChars()); @@ -578,7 +578,7 @@ FxExpression* ParseAction(FScanner &sc, FState state, FString statestring, Bagga { FArgumentList args; ParseFunctionParameters(sc, bag.Info, args, afd, statestring, &bag.statedef); - call = new FxFunctionCall(symname, NAME_None, args, sc); + call = new FxFunctionCall(symname, NAME_None, std::move(args), sc); return call; } sc.ScriptError("Invalid parameter '%s'\n", sc.String); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index d170096fb6..6affab4c36 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -433,12 +433,12 @@ void ParseScripts() if (FScriptPosition::ErrorCounter > 0) { // Abort if the compiler produced any errors. Also do not compile further lumps, because they very likely miss some stuff. - I_Error("%d errors, %d warnings while compiling %s", FScriptPosition::ErrorCounter, FScriptPosition::WarnCounter, fileSystem.GetFileFullPath(lump).GetChars()); + I_Error("%d errors, %d warnings while compiling %s", FScriptPosition::ErrorCounter, FScriptPosition::WarnCounter, fileSystem.GetFileFullPath(lump).c_str()); } else if (FScriptPosition::WarnCounter > 0) { // If we got warnings, but no errors, print the information but continue. - Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s\n", FScriptPosition::WarnCounter, fileSystem.GetFileFullPath(lump).GetChars()); + Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s\n", FScriptPosition::WarnCounter, fileSystem.GetFileFullPath(lump).c_str()); } } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 320c28cd40..34cd346667 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -256,6 +256,7 @@ union FPropParam int i; double d; const char *s; + VMFunction* fu; FxExpression *exp; }; @@ -313,6 +314,9 @@ int MatchString (const char *in, const char **strings); #define PROP_STRING_PARM(var, no) \ const char *var = params[(no)+1].s; +#define PROP_NAME_PARM(var, no) \ + FName var = params[(no)+1].s; + #define PROP_EXP_PARM(var, no) \ FxExpression *var = params[(no)+1].exp; @@ -325,6 +329,9 @@ int MatchString (const char *in, const char **strings); #define PROP_DOUBLE_PARM(var, no) \ double var = params[(no)+1].d; +#define PROP_FUNC_PARM(var, no) \ + auto var = params[(no)+1].fu; + #define PROP_COLOR_PARM(var, no, scriptpos) \ int var = params[(no)+1].i== 0? params[(no)+2].i : V_GetColor(params[(no)+2].s, scriptpos); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 6ef9fa9ccd..997ab78b1a 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -57,6 +57,7 @@ #include "a_dynlight.h" #include "types.h" #include "dictionary.h" +#include "events.h" static TArray properties; static TArray AFTable; @@ -347,6 +348,12 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF8, ADDLIGHTLEVEL, AActor, flags8), DEFINE_FLAG(MF8, ONLYSLAMSOLID, AActor, flags8), + DEFINE_FLAG(MF9, SHADOWAIM, AActor, flags9), + DEFINE_FLAG(MF9, DOSHADOWBLOCK, AActor, flags9), + DEFINE_FLAG(MF9, SHADOWBLOCK, AActor, flags9), + DEFINE_FLAG(MF9, SHADOWAIMVERT, AActor, flags9), + DEFINE_FLAG(MF9, DECOUPLEDANIMATIONS, AActor, flags9), + // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), DEFINE_FLAG2(FX_ROCKET, ROCKETTRAIL, AActor, effects), @@ -355,8 +362,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF, FORCEYBILLBOARD, AActor, renderflags), DEFINE_FLAG(RF, FORCEXYBILLBOARD, AActor, renderflags), DEFINE_FLAG(RF, ROLLSPRITE, AActor, renderflags), // [marrub] roll the sprite billboard - // [fgsfds] Flat sprites - DEFINE_FLAG(RF, FLATSPRITE, AActor, renderflags), + DEFINE_FLAG(RF, FLATSPRITE, AActor, renderflags), // [fgsfds] Flat sprites DEFINE_FLAG(RF, WALLSPRITE, AActor, renderflags), DEFINE_FLAG(RF, DONTFLIP, AActor, renderflags), DEFINE_FLAG(RF, ROLLCENTER, AActor, renderflags), @@ -373,6 +379,11 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF, NOSPRITESHADOW, AActor, renderflags), DEFINE_FLAG(RF2, INVISIBLEINMIRRORS, AActor, renderflags2), DEFINE_FLAG(RF2, ONLYVISIBLEINMIRRORS, AActor, renderflags2), + DEFINE_FLAG(RF2, BILLBOARDFACECAMERA, AActor, renderflags2), + DEFINE_FLAG(RF2, BILLBOARDNOFACECAMERA, AActor, renderflags2), + DEFINE_FLAG(RF2, FLIPSPRITEOFFSETX, AActor, renderflags2), + DEFINE_FLAG(RF2, FLIPSPRITEOFFSETY, AActor, renderflags2), + DEFINE_FLAG(RF2, CAMFOLLOWSPLAYER, AActor, renderflags2), // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), @@ -392,6 +403,8 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG2(BOUNCE_NotOnShootables, DONTBOUNCEONSHOOTABLES, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_BounceOnUnrips, BOUNCEONUNRIPPABLES, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_NotOnSky, DONTBOUNCEONSKY, AActor, BounceFlags), + + DEFINE_FLAG2(OF_Transient, NOSAVEGAME, AActor, ObjectFlags), }; // These won't be accessible through bitfield variables @@ -639,6 +652,15 @@ static int propcmp(const void * a, const void * b) //========================================================================== void InitImports(); +struct UserInfoCVarNamePlayer +{ + FBaseCVar** addr; + FString name; + int pnum; +}; + +TArray LoadGameUserInfoCVars; + void InitThingdef() { // Some native types need size and serialization information added before the scripts get compiled. @@ -789,6 +811,10 @@ void InitThingdef() frp->Size = sizeof(FRailParams); frp->Align = alignof(FRailParams); + auto netcmdstruct = NewStruct("NetworkCommand", nullptr, true); + netcmdstruct->Size = sizeof(FNetworkCommand); + netcmdstruct->Align = alignof(FNetworkCommand); + auto fltd = NewStruct("FLineTraceData", nullptr); fltd->Size = sizeof(FLineTraceData); fltd->Align = alignof(FLineTraceData); @@ -796,6 +822,79 @@ void InitThingdef() auto fspp = NewStruct("FSpawnParticleParams", nullptr); fspp->Size = sizeof(FSpawnParticleParams); fspp->Align = alignof(FSpawnParticleParams); + + auto cvst = NewStruct("CVar", nullptr, true); + NewPointer(cvst, false)->InstallHandlers( + [](FSerializer &arc, const char *key, const void *addr) + { + const FBaseCVar * self = *(const FBaseCVar**)addr; + + if(self) + { + arc.BeginObject(key); + + + if(self->pnum != -1) + { + int32_t pnum = self->pnum; + FName name = self->userinfoName; + arc("name", name); + arc("player", pnum); + } + else + { + FString name = self->GetName(); + arc("name", name); + } + + arc.EndObject(); + } + }, + [](FSerializer &arc, const char *key, void *addr) + { + FBaseCVar ** self = (FBaseCVar**)addr; + + FString name; + arc.BeginObject(key); + + arc("name", name); + + FBaseCVar * backing = FindCVar(name.GetChars(), nullptr); + if(!backing) + { + I_Error("Attempt to load pointer to inexisted CVar '%s'", name.GetChars()); + } + else if((backing->GetFlags() & (CVAR_USERINFO|CVAR_IGNORE)) == CVAR_USERINFO) + { + if(int pnum; arc.ReadOptionalInt("player", pnum)) + { + *self = nullptr; + LoadGameUserInfoCVars.Push({self, name, pnum}); // this needs to be done later, since userinfo isn't loaded yet + arc.EndObject(); + return true; + } + } + + *self = backing; + + arc.EndObject(); + + return true; + } + ); +} + +void SetupLoadingCVars() +{ + LoadGameUserInfoCVars.Clear(); +} + +void FinishLoadingCVars() +{ + for(UserInfoCVarNamePlayer &cvar : LoadGameUserInfoCVars) + { + (*cvar.addr) = GetCVar(cvar.pnum, cvar.name.GetChars()); + } } void SynthesizeFlagFields() diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 1202d2489b..bedd66cd37 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -152,18 +152,18 @@ bool ModActorFlag(AActor *actor, const FString &flagname, bool set, bool printer if (actor != NULL) { auto Level = actor->Level; - const char *dot = strchr(flagname, '.'); + const char *dot = strchr(flagname.GetChars(), '.'); FFlagDef *fd; PClassActor *cls = actor->GetClass(); if (dot != NULL) { - FString part1(flagname.GetChars(), dot - flagname); - fd = FindFlag(cls, part1, dot + 1); + FString part1(flagname.GetChars(), dot - flagname.GetChars()); + fd = FindFlag(cls, part1.GetChars(), dot + 1); } else { - fd = FindFlag(cls, flagname, NULL); + fd = FindFlag(cls, flagname.GetChars(), NULL); } if (fd != NULL) @@ -245,7 +245,7 @@ INTBOOL CheckActorFlag(AActor *owner, const char *flagname, bool printerror) if (dot != NULL) { FString part1(flagname, dot-flagname); - fd = FindFlag (cls, part1, dot+1); + fd = FindFlag (cls, part1.GetChars(), dot+1); } else { @@ -747,8 +747,8 @@ DEFINE_PROPERTY(translation, L, Actor) for(int i = 1; i < PROP_PARM_COUNT; i++) { PROP_STRING_PARM(str, i); - int tnum; - if (i== 1 && PROP_PARM_COUNT == 2 && (tnum = R_FindCustomTranslation(str)) != -1) + FTranslationID tnum; + if (i== 1 && PROP_PARM_COUNT == 2 && (tnum = R_FindCustomTranslation(str)) != INVALID_TRANSLATION) { defaults->Translation = tnum; return; @@ -789,7 +789,7 @@ DEFINE_PROPERTY(bloodcolor, C, Actor) defaults->BloodColor = color; defaults->BloodColor.a = 255; // a should not be 0. - defaults->BloodTranslation = TRANSLATION(TRANSLATION_Blood, CreateBloodTranslation(color)); + defaults->BloodTranslation = CreateBloodTranslation(color); } //========================================================================== @@ -988,6 +988,7 @@ DEFINE_PROPERTY(clearflags, 0, Actor) defaults->flags6 = 0; defaults->flags7 = 0; defaults->flags8 = 0; + defaults->flags9 = 0; } //========================================================================== @@ -1376,7 +1377,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver) { FString st; st.Format("%s%s", strnicmp(str, "power", 5) ? "Power" : "", str); - cls = FindClassTentative(st, pow); + cls = FindClassTentative(st.GetChars(), pow); } else { @@ -1813,6 +1814,15 @@ DEFINE_CLASS_PROPERTY(playerclass, S, PowerMorph) defaults->PointerVar(NAME_PlayerClass) = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); } +//========================================================================== +// +//========================================================================== +DEFINE_CLASS_PROPERTY(monsterclass, S, PowerMorph) +{ + PROP_STRING_PARM(str, 0); + defaults->PointerVar(NAME_MonsterClass) = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); +} + //========================================================================== // //========================================================================== diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 5247f40284..6e8ee58eb6 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -80,7 +80,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, SetCameraToTexture, SetCameraToTexture) static void SetCameraTextureAspectRatio(const FString &texturename, double aspectScale, bool useTextureRatio) { - FTextureID textureid = TexMan.CheckForTexture(texturename, ETextureType::Wall, FTextureManager::TEXMAN_Overridable); + FTextureID textureid = TexMan.CheckForTexture(texturename.GetChars(), ETextureType::Wall, FTextureManager::TEXMAN_Overridable); if (textureid.isValid()) { // Only proceed if the texture actually has a canvas. @@ -1026,7 +1026,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) static void SetEnvironment(sector_t *self, const FString &env) { - self->Level->Zones[self->ZoneNumber].Environment = S_FindEnvironment(env); + self->Level->Zones[self->ZoneNumber].Environment = S_FindEnvironment(env.GetChars()); } DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetEnvironment, SetEnvironment) @@ -1139,6 +1139,29 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) ACTION_RETURN_INT(self->e->XFloor.attached.Size()); } + static int CountSectorTags(const sector_t *self) + { + return level.tagManager.CountSectorTags(self); + } + + DEFINE_ACTION_FUNCTION_NATIVE(_Sector, CountTags, CountSectorTags) + { + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + ACTION_RETURN_INT(level.tagManager.CountSectorTags(self)); + } + + static int GetSectorTag(const sector_t *self, int index) + { + return level.tagManager.GetSectorTag(self, index); + } + + DEFINE_ACTION_FUNCTION_NATIVE(_Sector, GetTag, GetSectorTag) + { + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_INT(index); + ACTION_RETURN_INT(level.tagManager.GetSectorTag(self, index)); + } + static int Get3DFloorTexture(F3DFloor *self, int pos) { if ( pos ) @@ -1240,6 +1263,29 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) ACTION_RETURN_INT(LineIndex(self)); } + static int CountLineIDs(const line_t *self) + { + return level.tagManager.CountLineIDs(self); + } + + DEFINE_ACTION_FUNCTION_NATIVE(_Line, CountIDs, CountLineIDs) + { + PARAM_SELF_STRUCT_PROLOGUE(line_t); + ACTION_RETURN_INT(level.tagManager.CountLineIDs(self)); + } + + static int GetLineID(const line_t *self, int index) + { + return level.tagManager.GetLineID(self, index); + } + + DEFINE_ACTION_FUNCTION_NATIVE(_Line, GetID, GetLineID) + { + PARAM_SELF_STRUCT_PROLOGUE(line_t); + PARAM_INT(index); + ACTION_RETURN_INT(level.tagManager.GetLineID(self, index)); + } + //=========================================================================== // // side_t exports @@ -1677,7 +1723,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) // This is needed to convert the strings to char pointers. static void ReplaceTextures(FLevelLocals *self, const FString &from, const FString &to, int flags) { - self->ReplaceTextures(from, to, flags); + self->ReplaceTextures(from.GetChars(), to.GetChars(), flags); } DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, ReplaceTextures, ReplaceTextures) @@ -1686,7 +1732,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, ReplaceTextures, ReplaceTextures) PARAM_STRING(from); PARAM_STRING(to); PARAM_INT(flags); - self->ReplaceTextures(from, to, flags); + self->ReplaceTextures(from.GetChars(), to.GetChars(), flags); return 0; } @@ -2051,7 +2097,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, Draw, SBar_Draw) static void SetMugshotState(DBaseStatusBar *self, const FString &statename, bool wait, bool reset) { - self->mugshot.SetState(statename, wait, reset); + self->mugshot.SetState(statename.GetChars(), wait, reset); } DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, SetMugshotState, SetMugshotState) @@ -2060,7 +2106,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, SetMugshotState, SetMugshotState) PARAM_STRING(statename); PARAM_BOOL(wait); PARAM_BOOL(reset); - self->mugshot.SetState(statename, wait, reset); + self->mugshot.SetState(statename.GetChars(), wait, reset); return 0; } @@ -2155,7 +2201,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, ReceivedWeapon, ReceivedWeapon) static int GetMugshot(DBaseStatusBar *self, int accuracy, int stateflags, const FString &def_face) { - auto tex = self->mugshot.GetFace(self->CPlayer, def_face, accuracy, (FMugShot::StateFlags)stateflags); + auto tex = self->mugshot.GetFace(self->CPlayer, def_face.GetChars(), accuracy, (FMugShot::StateFlags)stateflags); return (tex ? tex->GetID().GetIndex() : -1); } @@ -2568,7 +2614,7 @@ DEFINE_ACTION_FUNCTION(DObject, S_ChangeMusic) PARAM_INT(order); PARAM_BOOL(looping); PARAM_BOOL(force); - ACTION_RETURN_BOOL(S_ChangeMusic(music, order, looping, force)); + ACTION_RETURN_BOOL(S_ChangeMusic(music.GetChars(), order, looping, force)); } @@ -2589,7 +2635,7 @@ DEFINE_ACTION_FUNCTION(_Console, MidPrint) PARAM_STRING(text); PARAM_BOOL(bold); - const char* txt = text[0] == '$' ? GStrings(&text[1]) : text.GetChars(); + const char* txt = text[0] == '$' ? GStrings.GetString(&text[1]) : text.GetChars(); C_MidPrint(fnt, txt, bold); return 0; } @@ -2717,7 +2763,9 @@ DEFINE_FIELD_X(LevelInfo, level_info_t, sucktime) DEFINE_FIELD_X(LevelInfo, level_info_t, flags) DEFINE_FIELD_X(LevelInfo, level_info_t, flags2) DEFINE_FIELD_X(LevelInfo, level_info_t, flags3) +DEFINE_FIELD_X(LevelInfo, level_info_t, vkdflags) DEFINE_FIELD_X(LevelInfo, level_info_t, Music) +DEFINE_FIELD_X(LevelInfo, level_info_t, LightningSound) DEFINE_FIELD_X(LevelInfo, level_info_t, LevelName) DEFINE_FIELD_X(LevelInfo, level_info_t, AuthorName) DEFINE_FIELD_X(LevelInfo, level_info_t, musicorder) @@ -2761,6 +2809,7 @@ DEFINE_FIELD(FLevelLocals, NextSecretMap) DEFINE_FIELD(FLevelLocals, F1Pic) DEFINE_FIELD(FLevelLocals, AuthorName) DEFINE_FIELD(FLevelLocals, maptype) +DEFINE_FIELD(FLevelLocals, LightningSound) DEFINE_FIELD(FLevelLocals, Music) DEFINE_FIELD(FLevelLocals, musicorder) DEFINE_FIELD(FLevelLocals, skytexture1) @@ -2805,8 +2854,8 @@ DEFINE_FIELD_BIT(FLevelLocals, flags2, infinite_flight, LEVEL2_INFINITE_FLIGHT) DEFINE_FIELD_BIT(FLevelLocals, flags2, no_dlg_freeze, LEVEL2_CONV_SINGLE_UNFREEZE) DEFINE_FIELD_BIT(FLevelLocals, flags2, keepfullinventory, LEVEL2_KEEPFULLINVENTORY) DEFINE_FIELD_BIT(FLevelLocals, flags3, removeitems, LEVEL3_REMOVEITEMS) -DEFINE_FIELD_BIT(FLevelLocals, flags9, nousersave, LEVEL9_NOUSERSAVE) -DEFINE_FIELD_BIT(FLevelLocals, flags9, noautomap, LEVEL9_NOAUTOMAP) +DEFINE_FIELD_BIT(FLevelLocals, vkdflags, nousersave, VKDLEVELFLAG_NOUSERSAVE) +DEFINE_FIELD_BIT(FLevelLocals, vkdflags, noautomap, VKDLEVELFLAG_NOAUTOMAP) DEFINE_FIELD_X(Sector, sector_t, floorplane) DEFINE_FIELD_X(Sector, sector_t, ceilingplane) @@ -2817,7 +2866,7 @@ DEFINE_FIELD_X(Sector, sector_t, SoundTarget) DEFINE_FIELD_X(Sector, sector_t, special) DEFINE_FIELD_X(Sector, sector_t, lightlevel) DEFINE_FIELD_X(Sector, sector_t, seqType) -DEFINE_FIELD_X(Sector, sector_t, sky) +DEFINE_FIELD_NAMED_X(Sector, sector_t, skytransfer, sky) DEFINE_FIELD_X(Sector, sector_t, SeqName) DEFINE_FIELD_X(Sector, sector_t, centerspot) DEFINE_FIELD_X(Sector, sector_t, validcount) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index f302d335d1..7094212e0f 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -55,6 +55,7 @@ #include "actorinlines.h" #include "p_enemy.h" #include "gi.h" +#include "shadowinlines.h" DVector2 AM_GetPosition(); int Net_GetLatency(int *ld, int *ad); @@ -1227,6 +1228,23 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, LineTrace, LineTrace) ACTION_RETURN_BOOL(P_LineTrace(self,DAngle::fromDeg(angle),distance,DAngle::fromDeg(pitch),flags,offsetz,offsetforward,offsetside,data)); } +DEFINE_ACTION_FUNCTION(AActor, PerformShadowChecks) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); //If this pointer is null, the trace uses the facing direction instead. + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + + double penaltyFactor = 0.0; + AActor* shadow = PerformShadowChecks(self, other, DVector3(x, y, z), penaltyFactor); + if (numret > 2) ret[2].SetFloat(penaltyFactor); + if (numret > 1) ret[1].SetObject(shadow); + if (numret > 0) ret[0].SetInt(bool(shadow)); + return numret; +} + + static void TraceBleedAngle(AActor *self, int damage, double angle, double pitch) { P_TraceBleed(damage, self, DAngle::fromDeg(angle), DAngle::fromDeg(pitch)); @@ -1299,13 +1317,14 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetRadiusDamage, P_GetRadiusDamage) PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(thing, AActor); PARAM_INT(damage); - PARAM_INT(distance); - PARAM_INT(fulldmgdistance); + PARAM_FLOAT(distance); + PARAM_FLOAT(fulldmgdistance); PARAM_BOOL(oldradiusdmg); - ACTION_RETURN_INT(P_GetRadiusDamage(self, thing, damage, distance, fulldmgdistance, oldradiusdmg)); + PARAM_BOOL(circular); + ACTION_RETURN_INT(P_GetRadiusDamage(self, thing, damage, distance, fulldmgdistance, oldradiusdmg, circular)); } -static int RadiusAttack(AActor *self, AActor *bombsource, int bombdamage, int bombdistance, int damagetype, int flags, int fulldamagedistance, int species) +static int RadiusAttack(AActor *self, AActor *bombsource, int bombdamage, double bombdistance, int damagetype, int flags, double fulldamagedistance, int species) { return P_RadiusAttack(self, bombsource, bombdamage, bombdistance, ENamedName(damagetype), flags, fulldamagedistance, ENamedName(species)); } @@ -1315,10 +1334,10 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, RadiusAttack, RadiusAttack) PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(bombsource, AActor); PARAM_INT(bombdamage); - PARAM_INT(bombdistance); + PARAM_FLOAT(bombdistance); PARAM_INT(damagetype); PARAM_INT(flags); - PARAM_INT(fulldamagedistance); + PARAM_FLOAT(fulldamagedistance); PARAM_INT(species); ACTION_RETURN_INT(RadiusAttack(self, bombsource, bombdamage, bombdistance, damagetype, flags, fulldamagedistance, species)); } @@ -1538,20 +1557,21 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, LookForPlayers, P_LookForPlayers) ACTION_RETURN_BOOL(P_LookForPlayers(self, allaround, params)); } -static int CheckMonsterUseSpecials(AActor *self) +static int CheckMonsterUseSpecials(AActor *self, line_t *blocking) { spechit_t spec; int good = 0; if (!(self->flags6 & MF6_NOTRIGGER)) { + auto checkLine = blocking ? blocking : self->BlockingLine; while (spechit.Pop (spec)) { // [RH] let monsters push lines, as well as use them if (((self->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (spec.line, self, 0, SPAC_Use)) || ((self->flags2 & MF2_PUSHWALL) && P_ActivateLine (spec.line, self, 0, SPAC_Push))) { - good |= spec.line == self->BlockingLine ? 1 : 2; + good |= spec.line == checkLine ? 1 : 2; } } } @@ -1563,8 +1583,9 @@ static int CheckMonsterUseSpecials(AActor *self) DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckMonsterUseSpecials, CheckMonsterUseSpecials) { PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER(blocking, line_t); - ACTION_RETURN_INT(CheckMonsterUseSpecials(self)); + ACTION_RETURN_INT(CheckMonsterUseSpecials(self, blocking)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_Wander, A_Wander) @@ -1672,28 +1693,11 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_BossDeath, A_BossDeath) return 0; } -DEFINE_ACTION_FUNCTION_NATIVE(AActor, Substitute, StaticPointerSubstitution) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(replace, AActor); - StaticPointerSubstitution(self, replace); - return 0; -} - -DEFINE_ACTION_FUNCTION_NATIVE(_PlayerPawn, Substitute, StaticPointerSubstitution) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(replace, AActor); - StaticPointerSubstitution(self, replace); - return 0; -} - -DEFINE_ACTION_FUNCTION_NATIVE(_MorphedMonster, Substitute, StaticPointerSubstitution) +DEFINE_ACTION_FUNCTION_NATIVE(AActor, MorphInto, MorphPointerSubstitution) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(replace, AActor); - StaticPointerSubstitution(self, replace); - return 0; + PARAM_OBJECT(to, AActor); + ACTION_RETURN_INT(MorphPointerSubstitution(self, to)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetSpawnableType, P_GetSpawnableType) @@ -1860,6 +1864,15 @@ DEFINE_ACTION_FUNCTION(AActor, PlayBounceSound) return 0; } +DEFINE_ACTION_FUNCTION(AActor, ReflectOffActor) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(blocking, AActor); + + ACTION_RETURN_BOOL(P_ReflectOffActor(self, blocking)); +} + + static int isFrozen(AActor *self) { @@ -2045,6 +2058,7 @@ DEFINE_FIELD(AActor, lastbump) DEFINE_FIELD(AActor, DesignatedTeam) DEFINE_FIELD(AActor, BlockingMobj) DEFINE_FIELD(AActor, BlockingLine) +DEFINE_FIELD(AActor, MovementBlockingLine) DEFINE_FIELD(AActor, Blocking3DFloor) DEFINE_FIELD(AActor, BlockingCeiling) DEFINE_FIELD(AActor, BlockingFloor) @@ -2108,6 +2122,10 @@ DEFINE_FIELD_NAMED(AActor, ViewAngles.Yaw, viewangle) DEFINE_FIELD_NAMED(AActor, ViewAngles.Pitch, viewpitch) DEFINE_FIELD_NAMED(AActor, ViewAngles.Roll, viewroll) DEFINE_FIELD(AActor, LightLevel) +DEFINE_FIELD(AActor, ShadowAimFactor) +DEFINE_FIELD(AActor, ShadowPenaltyFactor) +DEFINE_FIELD(AActor, AutomapOffsets) +DEFINE_FIELD(AActor, LandingSpeed) DEFINE_FIELD_X(FCheckPosition, FCheckPosition, thing); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, pos); diff --git a/src/scripting/zscript/zcc_compile_doom.cpp b/src/scripting/zscript/zcc_compile_doom.cpp index 642fac09f6..4becfc4fe1 100644 --- a/src/scripting/zscript/zcc_compile_doom.cpp +++ b/src/scripting/zscript/zcc_compile_doom.cpp @@ -50,6 +50,7 @@ bool isActor(PContainerType *type); void AddActorInfo(PClass *cls); int GetIntConst(FxExpression* ex, FCompileContext& ctx); double GetFloatConst(FxExpression* ex, FCompileContext& ctx); +VMFunction* GetFuncConst(FxExpression* ex, FCompileContext& ctx); //========================================================================== // @@ -69,6 +70,7 @@ int ZCCDoomCompiler::Compile() InitDefaults(); InitFunctions(); CompileStates(); + InitDefaultFunctionPointers(); return FScriptPosition::ErrorCounter; } @@ -282,6 +284,10 @@ void ZCCDoomCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *pr conv.d = GetFloatConst(ex, ctx); break; + case 'G': + conv.fu = GetFuncConst(ex, ctx); + break; + case 'Z': // an optional string. Does not allow any numeric value. if (ex->ValueType != TypeString) { @@ -390,6 +396,46 @@ void ZCCDoomCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *pr // //========================================================================== +PFunction * FindFunctionPointer(PClass * cls, int fn_name); +PFunction *NativeFunctionPointerCast(PFunction *from, const PFunctionPointer *to); + +struct FunctionPointerProperties +{ + ZCC_PropertyStmt *prop; + PClass * cls; + FName name; + const PFunctionPointer * type; + PFunction ** addr; +}; + +TArray DefaultFunctionPointers; + +void ZCCDoomCompiler::InitDefaultFunctionPointers() +{ + for(auto &d : DefaultFunctionPointers) + { + PFunction * fn = FindFunctionPointer(d.cls, d.name.GetIndex()); + if(!fn) + { + Error(d.prop, "Could not find function '%s' in class '%s'",d.name.GetChars(), d.cls->TypeName.GetChars()); + } + else + { + PFunction * casted = NativeFunctionPointerCast(fn,d.type); + if(!casted) + { + FString fn_proto_name = PFunctionPointer::GenerateNameForError(fn); + Error(d.prop, "Function has incompatible types, cannot convert from '%s' to '%s'",fn_proto_name.GetChars(), d.type->DescriptiveName()); + } + else + { + (*d.addr) = casted; + } + } + } + DefaultFunctionPointers.Clear(); +} + void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *property, AActor *defaults, Baggage &bag) { ZCC_ExprConstant one; @@ -603,6 +649,44 @@ void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt * *(PClass**)addr = cls; } } + else if (f->Type->isFunctionPointer()) + { + const char * fn_str = GetStringConst(ex, ctx); + if (*fn_str == 0 || !stricmp(fn_str, "none")) + { + *(PFunction**)addr = nullptr; + } + else + { + TArray fn_info(FString(fn_str).Split("::", FString::TOK_SKIPEMPTY)); + if(fn_info.Size() != 2) + { + Error(property, "Malformed function pointer property \"%s\", must be \"Class::Function\"",fn_str); + } + PClass * cls = PClass::FindClass(fn_info[0]); + if(!cls) + { + Error(property, "Could not find class '%s'",fn_info[0].GetChars()); + *(PFunction**)addr = nullptr; + } + else + { + FName fn_name(fn_info[1], true); + if(fn_name.GetIndex() == 0) + { + Error(property, "Could not find function '%s' in class '%s'",fn_info[1].GetChars(),fn_info[0].GetChars()); + *(PFunction**)addr = nullptr; + } + else + { + DefaultFunctionPointers.Push({property, cls, fn_name, static_cast(f->Type), (PFunction**)addr}); + *(PFunction**)addr = nullptr; + } + + } + } + + } else { Error(property, "unhandled property type %s", f->Type->DescriptiveName()); @@ -650,7 +734,7 @@ void ZCCDoomCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt } - FPropertyInfo *property = FindProperty(propname); + FPropertyInfo *property = FindProperty(propname.GetChars()); if (property != nullptr && property->category != CAT_INFO) { @@ -987,7 +1071,7 @@ void ZCCDoomCompiler::CompileStates() { auto sl = static_cast(st); statename = FName(sl->Label).GetChars(); - statedef.AddStateLabel(statename); + statedef.AddStateLabel(statename.GetChars()); break; } case AST_StateLine: @@ -1046,7 +1130,7 @@ void ZCCDoomCompiler::CompileStates() auto l = sl->Lights; do { - AddStateLight(&state, StringConstFromNode(l, c->Type())); + AddStateLight(&state, StringConstFromNode(l, c->Type()).GetChars()); l = static_cast(l->SiblingNext); } while (l != sl->Lights); } @@ -1097,7 +1181,7 @@ void ZCCDoomCompiler::CompileStates() statename.AppendFormat("+%d", offset); } } - if (!statedef.SetGotoLabel(statename)) + if (!statedef.SetGotoLabel(statename.GetChars())) { Error(sg, "GOTO before first state"); } diff --git a/src/scripting/zscript/zcc_compile_doom.h b/src/scripting/zscript/zcc_compile_doom.h index 36d7a4680f..1fb8943728 100644 --- a/src/scripting/zscript/zcc_compile_doom.h +++ b/src/scripting/zscript/zcc_compile_doom.h @@ -25,6 +25,7 @@ class ZCCDoomCompiler : public ZCCCompiler void ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *prop, Baggage &bag); void ProcessDefaultFlag(PClassActor *cls, ZCC_FlagStmt *flg); void InitDefaults() override final; + void InitDefaultFunctionPointers(); FxExpression *SetupActionFunction(PClass *cls, ZCC_TreeNode *af, int StateFlags); void CompileStates(); int CheckActionKeyword(ZCC_FuncDeclarator *f, uint32_t &varflags, int useflags, ZCC_StructWork *c); diff --git a/src/serializer_doom.cpp b/src/serializer_doom.cpp index 953bb9afcc..2ec1c8b861 100644 --- a/src/serializer_doom.cpp +++ b/src/serializer_doom.cpp @@ -38,7 +38,7 @@ #define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 #define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag -#include +#include #include "rapidjson/rapidjson.h" #include "rapidjson/writer.h" #include "rapidjson/prettywriter.h" @@ -346,6 +346,13 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState arc.w->Uint((uint32_t)(state - info->GetStates())); arc.w->EndArray(); } + else if (state->DehIndex >= 0) + { + arc.w->StartArray(); + arc.w->String("@DehExtraState@"); + arc.w->Uint(state->DehIndex); + arc.w->EndArray(); + } else { arc.w->Null(); @@ -373,11 +380,18 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState assert(cls.IsString() && ndx.IsUint()); if (cls.IsString() && ndx.IsUint()) { - PClassActor *clas = PClass::FindActor(UnicodeToString(cls.GetString())); + auto str = UnicodeToString(cls.GetString()); + PClassActor *clas = PClass::FindActor(str); if (clas && ndx.GetUint() < (unsigned)clas->GetStateCount()) { state = clas->GetStates() + ndx.GetUint(); } + else if (!strcmp(str, "@DehExtraState@")) + { + state = nullptr; + auto pState = dehExtStates.CheckKey(ndx.GetInt()); + if (pState) state = *pState; + } else { // this can actually happen by changing the DECORATE so treat it as a warning, not an error. diff --git a/src/sound/s_advsound.cpp b/src/sound/s_advsound.cpp index 928cdeba5b..f48e6855e4 100644 --- a/src/sound/s_advsound.cpp +++ b/src/sound/s_advsound.cpp @@ -49,6 +49,9 @@ #include "vm.h" #include "i_system.h" #include "s_music.h" +#include "i_music.h" + +using namespace FileSys; // MACROS ------------------------------------------------------------------ @@ -132,6 +135,7 @@ enum SICommands SI_Registered, SI_ArchivePath, SI_MusicVolume, + SI_Replaygain, SI_MidiDevice, SI_IfDoom, SI_IfHeretic, @@ -170,6 +174,7 @@ struct FSavedPlayerSoundInfo // This specifies whether Timidity or Windows playback is preferred for a certain song (only useful for Windows.) MusicAliasMap MusicAliases; +static bool sndinfo_locked; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -219,6 +224,7 @@ static const char *SICommandStrings[] = "$registered", "$archivepath", "$musicvolume", + "$replaygain", "$mididevice", "$ifdoom", "$ifheretic", @@ -494,7 +500,7 @@ FSoundID S_AddPlayerSound (const char *pclass, int gender, FSoundID refid, int l fakename += '"'; fakename += sfx->name.GetChars(); - id = soundEngine->AddSoundLump (fakename, lumpnum, CurrentPitchMask); + id = soundEngine->AddSoundLump (fakename.GetChars(), lumpnum, CurrentPitchMask); int classnum = S_AddPlayerClass (pclass); int soundlist = S_AddPlayerGender (classnum, gender); @@ -579,7 +585,10 @@ void S_ParseSndInfo (bool redefine) { int lump; - if (!redefine) SavedPlayerSounds.Clear(); // clear skin sounds only for initial parsing. + if (redefine && sndinfo_locked) return; + + SavedPlayerSounds.Clear(); // clear skin sounds only for initial parsing. + S_ClearSoundData(); // remove old sound data first! CurrentPitchMask = 0; @@ -608,6 +617,11 @@ void S_ParseSndInfo (bool redefine) S_CheckIntegrity(); } +void S_LockLocalSndinfo() +{ + sndinfo_locked = true; +} + //========================================================================== // // Adds a level specific SNDINFO lump @@ -616,6 +630,11 @@ void S_ParseSndInfo (bool redefine) void S_AddLocalSndInfo(int lump) { + if (sndinfo_locked) + { + Printf("Local SNDINFO cannot be combined with DSDHacked sounds!"); + return; + } S_AddSNDINFO(lump); soundEngine->HashSounds (); @@ -775,8 +794,8 @@ static void S_AddSNDINFO (int lump) int gender; FSoundID refid, sfxnum; - S_ParsePlayerSoundCommon (sc, pclass, gender, refid); - sfxnum = S_AddPlayerSound (pclass, gender, refid, sc.String); + S_ParsePlayerSoundCommon(sc, pclass, gender, refid); + sfxnum = S_AddPlayerSound(pclass.GetChars(), gender, refid, sc.String); if (0 == stricmp(sc.String, "dsempty")) { soundEngine->GetWritableSfx(sfxnum)->UserData[0] |= SND_PlayerSilent; @@ -797,7 +816,7 @@ static void S_AddSNDINFO (int lump) { sc.ScriptError("%s is not a player sound", sc.String); } - S_DupPlayerSound (pclass, gender, refid, targid); + S_DupPlayerSound (pclass.GetChars(), gender, refid, targid); } break; @@ -810,7 +829,7 @@ static void S_AddSNDINFO (int lump) S_ParsePlayerSoundCommon (sc, pclass, gender, refid); sfxfrom = S_AddSound (sc.String, -1, &sc); - aliasto = S_LookupPlayerSound (pclass, gender, refid); + aliasto = S_LookupPlayerSound (pclass.GetChars(), gender, refid); auto sfx = soundEngine->GetWritableSfx(sfxfrom); sfx->link = aliasto; sfx->UserData[0] |= SND_PlayerCompat; @@ -825,7 +844,7 @@ static void S_AddSNDINFO (int lump) S_ParsePlayerSoundCommon (sc, pclass, gender, refid); soundnum = soundEngine->FindSoundTentative (sc.String); - S_AddPlayerSoundExisting (pclass, gender, refid, soundnum); + S_AddPlayerSoundExisting (pclass.GetChars(), gender, refid, soundnum); } break; @@ -1015,9 +1034,16 @@ static void S_AddSNDINFO (int lump) case SI_MusicVolume: { sc.MustGetString(); - FName musname (sc.String); - sc.MustGetFloat(); - MusicVolumes[musname] = (float)sc.Float; + int lumpnum = mus_cb.FindMusic(sc.String); + if (!sc.CheckFloat()) + { + sc.MustGetString(); + char* p; + double f = strtod(sc.String, &p); + if (!stricmp(p, "db")) sc.Float = dBToAmplitude((float)sc.Float); + else sc.ScriptError("Bad value for music volume: %s", sc.String); + } + if (lumpnum >= 0) MusicVolumes[lumpnum] = (float)sc.Float; } break; @@ -1051,7 +1077,7 @@ static void S_AddSNDINFO (int lump) case SI_MidiDevice: { sc.MustGetString(); - FName nm = sc.String; + int lumpnum = mus_cb.FindMusic(sc.String); FScanner::SavedPos save = sc.SavePos(); sc.SetCMode(true); @@ -1083,7 +1109,7 @@ static void S_AddSNDINFO (int lump) sc.RestorePos(save); sc.MustGetString(); } - MidiDevices[nm] = devset; + if (lumpnum >= 0) MidiDevices[lumpnum] = devset; } break; @@ -1108,7 +1134,7 @@ static void S_AddSNDINFO (int lump) } sc.MustGetString (); - S_AddSound (name, sc.String, &sc); + S_AddSound (name.GetChars(), sc.String, &sc); } } } @@ -1124,7 +1150,7 @@ static void S_AddSNDINFO (int lump) static void S_AddStrifeVoice (int lumpnum) { char name[16] = "svox/"; - fileSystem.GetFileShortName (name+5, lumpnum); + strcpy(name + 5, fileSystem.GetFileShortName (lumpnum)); S_AddSound (name, lumpnum); } @@ -1210,7 +1236,7 @@ static int S_FindPlayerClass (const char *name) for (i = 0; i < PlayerClassLookups.Size(); ++i) { - if (stricmp (name, PlayerClassLookups[i].Name) == 0) + if (stricmp (name, PlayerClassLookups[i].Name.GetChars()) == 0) { return (int)i; } @@ -1224,7 +1250,7 @@ static int S_FindPlayerClass (const char *name) while (min <= max) { int mid = (min + max) / 2; - int lexx = stricmp (PlayerClassLookups[mid].Name, name); + int lexx = stricmp (PlayerClassLookups[mid].Name.GetChars(), name); if (lexx == 0) { return mid; @@ -1279,13 +1305,13 @@ void S_ShrinkPlayerSoundLists () qsort (&PlayerClassLookups[0], PlayerClassLookups.Size(), sizeof(FPlayerClassLookup), SortPlayerClasses); PlayerClassesIsSorted = true; - DefPlayerClass = S_FindPlayerClass (DefPlayerClassName); + DefPlayerClass = S_FindPlayerClass (DefPlayerClassName.GetChars()); } static int SortPlayerClasses (const void *a, const void *b) { - return stricmp (((const FPlayerClassLookup *)a)->Name, - ((const FPlayerClassLookup *)b)->Name); + return stricmp (((const FPlayerClassLookup *)a)->Name.GetChars(), + ((const FPlayerClassLookup *)b)->Name.GetChars()); } //========================================================================== diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index bc5c092b01..33604ce61f 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -66,6 +66,7 @@ #include "g_game.h" #include "s_music.h" #include "v_draw.h" +#include "m_argv.h" // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -153,11 +154,11 @@ static FString LookupMusic(const char* musicname, int& order) // handle dehacked replacement. // Any music name defined this way needs to be prefixed with 'D_' because // Doom.exe does not contain the prefix so these strings don't either. - const char* mus_string = GStrings[musicname + 1]; + const char* mus_string = GStrings.CheckString(musicname + 1); if (mus_string != nullptr) { DEH_Music << "D_" << mus_string; - musicname = DEH_Music; + musicname = DEH_Music.GetChars(); } } @@ -176,36 +177,17 @@ static FString LookupMusic(const char* musicname, int& order) //========================================================================== // -// OpenMusic +// FindMusic // -// opens a FileReader for the music - used as a callback to keep -// implementation details out of the core player. +// loops up a music resource according to the engine's rules // //========================================================================== -static FileReader OpenMusic(const char* musicname) +static int FindMusic(const char* musicname) { - FileReader reader; - if (!FileExists(musicname)) - { - int lumpnum; - lumpnum = fileSystem.CheckNumForFullName(musicname); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, ns_music); - if (lumpnum == -1) - { - Printf("Music \"%s\" not found\n", musicname); - } - else if (fileSystem.FileLength(lumpnum) != 0) - { - reader = fileSystem.ReopenFileReader(lumpnum); - } - } - else - { - // Load an external file. - reader.OpenFile(musicname); - } - return reader; + int lumpnum = fileSystem.CheckNumForFullName(musicname); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, FileSys::ns_music); + return lumpnum; } //========================================================================== @@ -219,7 +201,7 @@ static FileReader OpenMusic(const char* musicname) void S_Init() { // Hook up the music player with the engine specific customizations. - static MusicCallbacks cb = { LookupMusic, OpenMusic }; + static MusicCallbacks cb = { LookupMusic, FindMusic }; S_SetMusicCallbacks(&cb); // Must be up before I_InitSound. @@ -229,14 +211,15 @@ void S_Init() } I_InitSound(); - I_InitMusic(); + I_InitMusic(Args->CheckParm("-nomusic") || Args->CheckParm("-nosound")); // Heretic and Hexen have sound curve lookup tables. Doom does not. int curvelump = fileSystem.CheckNumForName("SNDCURVE"); TArray curve; if (curvelump >= 0) { - curve = fileSystem.GetFileData(curvelump); + curve.Resize(fileSystem.FileLength(curvelump)); + fileSystem.ReadFile(curvelump, curve.Data()); } soundEngine->Init(curve); } @@ -312,7 +295,7 @@ void S_Start() if (LocalSndInfo.IsNotEmpty()) { // Now parse the local SNDINFO - int j = fileSystem.CheckNumForFullName(LocalSndInfo, true); + int j = fileSystem.CheckNumForFullName(LocalSndInfo.GetChars(), true); if (j >= 0) S_AddLocalSndInfo(j); } @@ -326,7 +309,7 @@ void S_Start() if (parse_ss) { - S_ParseSndSeq(LocalSndSeq.IsNotEmpty() ? fileSystem.CheckNumForFullName(LocalSndSeq, true) : -1); + S_ParseSndSeq(LocalSndSeq.IsNotEmpty() ? fileSystem.CheckNumForFullName(LocalSndSeq.GetChars(), true) : -1); } LastLocalSndInfo = LocalSndInfo; @@ -944,7 +927,7 @@ static void CalcSectorSoundOrg(const DVector3& listenpos, const sector_t* sec, i // Find the closest point on the sector's boundary lines and use // that as the perceived origin of the sound. DVector2 xy; - sec->ClosestPoint(listenpos, xy); + sec->ClosestPoint(listenpos.XY(), xy); pos.X = (float)xy.X; pos.Z = (float)xy.Y; } @@ -987,7 +970,7 @@ static void CalcPolyobjSoundOrg(const DVector3& listenpos, const FPolyObj* poly, sector_t* sec; DVector2 ppos; - poly->ClosestPoint(listenpos, ppos, &side); + poly->ClosestPoint(listenpos.XY(), ppos, &side); pos.X = (float)ppos.X; pos.Z = (float)ppos.Y; sec = side->sector; @@ -1167,7 +1150,10 @@ bool DoomSoundEngine::ValidatePosVel(int sourcetype, const void* source, const F TArray DoomSoundEngine::ReadSound(int lumpnum) { auto wlump = fileSystem.OpenFileReader(lumpnum); - return wlump.Read(); + TArray buffer(wlump.GetLength(), true); + auto len = wlump.Read(buffer.data(), buffer.size()); + buffer.Resize(len); + return buffer; } //========================================================================== @@ -1240,9 +1226,8 @@ void DoomSoundEngine::NoiseDebug() color = (chan->ChanFlags & CHANF_LOOP) ? CR_BROWN : CR_GREY; // Name - fileSystem.GetFileShortName(temp, S_sfx[chan->SoundID.index()].lumpnum); - temp[8] = 0; - DrawText(twod, NewConsoleFont, color, 0, y, temp, TAG_DONE); + auto tname = fileSystem.GetFileShortName(S_sfx[chan->SoundID.index()].lumpnum); + DrawText(twod, NewConsoleFont, color, 0, y, tname, TAG_DONE); if (!(chan->ChanFlags & CHANF_IS3D)) { @@ -1335,10 +1320,8 @@ ADD_STAT(sounddebug) void DoomSoundEngine::PrintSoundList() { - char lumpname[9]; unsigned int i; - lumpname[8] = 0; for (i = 0; i < soundEngine->GetNumSounds(); i++) { const sfxinfo_t* sfx = soundEngine->GetSfx(FSoundID::fromInt(i)); @@ -1358,8 +1341,7 @@ void DoomSoundEngine::PrintSoundList() } else if (S_sfx[i].lumpnum != -1) { - fileSystem.GetFileShortName(lumpname, sfx->lumpnum); - Printf("%3d. %s (%s)\n", i, sfx->name.GetChars(), lumpname); + Printf("%3d. %s (%s)\n", i, sfx->name.GetChars(), fileSystem.GetFileShortName(sfx->lumpnum)); } else if (S_sfx[i].link != sfxinfo_t::NO_LINK) { diff --git a/src/sound/s_doomsound.h b/src/sound/s_doomsound.h index b6c6dc3367..3dab94ace8 100644 --- a/src/sound/s_doomsound.h +++ b/src/sound/s_doomsound.h @@ -20,6 +20,10 @@ inline void S_Sound(int channel, EChanFlags flags, const char* sfxid, float volu { S_Sound(channel, flags, S_FindSound(sfxid), volume, attenuation); } +inline void S_Sound(int channel, EChanFlags flags, const FString& sfxid, float volume, float attenuation) +{ + S_Sound(channel, flags, S_FindSound(sfxid), volume, attenuation); +} void S_SoundPitch(int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch, float startTime = 0.f); diff --git a/src/sound/s_sound.h b/src/sound/s_sound.h index eb18009131..216f5829eb 100644 --- a/src/sound/s_sound.h +++ b/src/sound/s_sound.h @@ -65,6 +65,7 @@ extern MusicAliasMap MusicAliases; // [RH] S_sfx "maintenance" routines void S_ClearSoundData(); void S_ParseSndInfo (bool redefine); +void S_LockLocalSndinfo(); bool S_AreSoundsEquivalent (AActor *actor, FSoundID id1, FSoundID id2); FSoundID S_LookupPlayerSound (const char *playerclass, int gender, FSoundID refid); diff --git a/src/st_stuff.cpp b/src/st_stuff.cpp index 9fd7500cca..b56eb25e8f 100644 --- a/src/st_stuff.cpp +++ b/src/st_stuff.cpp @@ -439,8 +439,8 @@ static bool CheatAddKey (cheatseq_t *cheat, uint8_t key, bool *eat) static bool Cht_Generic (cheatseq_t *cheat) { - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (cheat->Args[0]); + Net_WriteInt8 (DEM_GENERICCHEAT); + Net_WriteInt8 (cheat->Args[0]); return true; } @@ -456,7 +456,7 @@ static bool Cht_Music (cheatseq_t *cheat) static bool Cht_BeholdMenu (cheatseq_t *cheat) { - Printf ("%s\n", GStrings("STSTR_BEHOLD")); + Printf ("%s\n", GStrings.GetString("STSTR_BEHOLD")); return false; } @@ -518,7 +518,7 @@ static bool Cht_MyPos (cheatseq_t *cheat) static bool Cht_Ticker (cheatseq_t *cheat) { ticker = !ticker; - Printf ("%s\n", GStrings(ticker ? "TXT_CHEATTICKERON" : "TXT_CHEATTICKEROFF")); + Printf ("%s\n", GStrings.GetString(ticker ? "TXT_CHEATTICKERON" : "TXT_CHEATTICKEROFF")); return true; } diff --git a/src/utility/nodebuilder/nodebuild.cpp b/src/utility/nodebuilder/nodebuild.cpp index 0efe38b0ef..58b20f6259 100644 --- a/src/utility/nodebuilder/nodebuild.cpp +++ b/src/utility/nodebuilder/nodebuild.cpp @@ -496,8 +496,9 @@ int FNodeBuilder::SelectSplitter (uint32_t set, node_t &node, uint32_t &splitseg } if (bestseg == UINT_MAX) - { // No lines split any others into two sets, so this is a convex region. - D(Printf (PRINT_LOG, "set %d, step %d, nosplit %d has no good splitter (%d)\n", set, step, nosplit, nosplitters)); + { + // No lines split any others into two sets, so this is a convex region. + D(Printf (PRINT_LOG, "set %d, step %d, nosplit %d has no good splitter (%d)\n", set, step, nosplit, nosplitters)); return nosplitters ? -1 : 0; } @@ -752,6 +753,54 @@ int FNodeBuilder::Heuristic (node_t &node, uint32_t set, bool honorNoSplit) return score; } +void FNodeBuilder::DoGLSegSplit (uint32_t set, node_t &node, uint32_t splitseg, uint32_t &outset0, uint32_t &outset1, int side, int sidev0, int sidev1, bool hack) +{ + FPrivSeg *seg = &Segs[set]; + + if (side >= 0 && GLNodes) + { + if (sidev0 == 0) + { + double dist1 = AddIntersection (node, seg->v1); + if (sidev1 == 0) + { + double dist2 = AddIntersection (node, seg->v2); + FSplitSharer share = { dist1, set, dist2 > dist1 }; + SplitSharers.Push (share); + } + } + else if (sidev1 == 0) + { + AddIntersection (node, seg->v2); + } + } + + if (hack && GLNodes) + { + uint32_t newback, newfront; + + newback = AddMiniseg (seg->v2, seg->v1, UINT_MAX, set, splitseg); + if (HackMate == UINT_MAX) + { + newfront = AddMiniseg (Segs[set].v1, Segs[set].v2, newback, set, splitseg); + Segs[newfront].next = outset0; + outset0 = newfront; + } + else + { + newfront = HackMate; + Segs[newfront].partner = newback; + Segs[newback].partner = newfront; + } + Segs[newback].frontsector = Segs[newback].backsector = + Segs[newfront].frontsector = Segs[newfront].backsector = + Segs[set].frontsector; + + Segs[newback].next = outset1; + outset1 = newback; + } +} + void FNodeBuilder::SplitSegs (uint32_t set, node_t &node, uint32_t splitseg, uint32_t &outset0, uint32_t &outset1, unsigned int &count0, unsigned int &count1) { unsigned int _count0 = 0; @@ -760,14 +809,15 @@ void FNodeBuilder::SplitSegs (uint32_t set, node_t &node, uint32_t splitseg, uin outset1 = UINT_MAX; Events.DeleteAll (); + UnsetSegs.Clear (); SplitSharers.Clear (); while (set != UINT_MAX) { + bool unset = false; bool hack; FPrivSeg *seg = &Segs[set]; int next = seg->next; - int sidev[2], side; if (HackSeg == set) @@ -844,73 +894,61 @@ void FNodeBuilder::SplitSegs (uint32_t set, node_t &node, uint32_t splitseg, uin } else { - // all that matters here is to prevent a crash so we must make sure that we do not end up with all segs being sorted to the same side - even if this may not be correct. - // But if we do not do that this code would not be able to move on. Just discarding the seg is also not an option because it won't guarantee that we achieve an actual split. - if (_count0 == 0) - { - side = 0; - seg->next = outset0; - outset0 = set; - _count0++; - } - else - { - side = 1; - seg->next = outset1; - outset1 = set; - _count1++; - } + // Sal May 28 2023 + // If all of the worst stars align: + // - The very first seg in the list doesn't know which side it should go to and makes it here. 0 are in front, so it goes to front. + // - Literally every other seg in the list all want to go to the front side from the other metrics + // - Oops! Now there's nothing in the back side! + // So we need to collect these now and do them later, otherwise the crash prevention fails. + UnsetSegs.Push(set); + unset = true; } break; } - if (side >= 0 && GLNodes) + if (unset == false) { - if (sidev[0] == 0) - { - double dist1 = AddIntersection (node, seg->v1); - if (sidev[1] == 0) - { - double dist2 = AddIntersection (node, seg->v2); - FSplitSharer share = { dist1, set, dist2 > dist1 }; - SplitSharers.Push (share); - } - } - else if (sidev[1] == 0) - { - AddIntersection (node, seg->v2); - } + DoGLSegSplit (set, node, splitseg, outset0, outset1, side, sidev[0], sidev[1], hack); } - if (hack && GLNodes) - { - uint32_t newback, newfront; + set = next; + } - newback = AddMiniseg (seg->v2, seg->v1, UINT_MAX, set, splitseg); - if (HackMate == UINT_MAX) - { - newfront = AddMiniseg (Segs[set].v1, Segs[set].v2, newback, set, splitseg); - Segs[newfront].next = outset0; - outset0 = newfront; - } - else - { - newfront = HackMate; - Segs[newfront].partner = newback; - Segs[newback].partner = newfront; - } - Segs[newback].frontsector = Segs[newback].backsector = - Segs[newfront].frontsector = Segs[newfront].backsector = - Segs[set].frontsector; + for (unsigned int i = 0; i < UnsetSegs.Size(); ++i) + { + uint32_t unsetID = UnsetSegs[i]; + FPrivSeg *seg = &Segs[unsetID]; + int sidev[2], side; + + side = ClassifyLine (node, &Vertices[seg->v1], &Vertices[seg->v2], sidev); - Segs[newback].next = outset1; - outset1 = newback; + // all that matters here is to prevent a crash so we must make sure that we do not end up with all segs being sorted to the same side - even if this may not be correct. + // But if we do not do that this code would not be able to move on. Just discarding the seg is also not an option because it won't guarantee that we achieve an actual split. + + if (_count0 == 0) + { + side = 0; + seg->next = outset0; + outset0 = unsetID; + _count0++; } - set = next; + else + { + side = 1; + seg->next = outset1; + outset1 = unsetID; + _count1++; + } + + DoGLSegSplit (unsetID, node, splitseg, outset0, outset1, side, sidev[0], sidev[1], false); } + FixSplitSharers (node); if (GLNodes) { AddMinisegs (node, splitseg, outset0, outset1); } + + assert(_count0 != 0 && _count1 != 0); + count0 = _count0; count1 = _count1; } diff --git a/src/utility/nodebuilder/nodebuild.h b/src/utility/nodebuilder/nodebuild.h index f9f6b018a3..1f5ef566cb 100644 --- a/src/utility/nodebuilder/nodebuild.h +++ b/src/utility/nodebuilder/nodebuild.h @@ -269,6 +269,7 @@ class FNodeBuilder TArray Colinear; // Loops with edges colinear to a splitter FEventTree Events; // Vertices intersected by the current splitter + TArray UnsetSegs; // Segs with no definitive side in current splitter TArray SplitSharers; // Segs colinear with the current splitter uint32_t HackSeg; // Seg to force to back of splitter @@ -294,7 +295,9 @@ class FNodeBuilder void CreateSubsectorsForReal (); bool CheckSubsector (uint32_t set, node_t &node, uint32_t &splitseg); bool CheckSubsectorOverlappingSegs (uint32_t set, node_t &node, uint32_t &splitseg); - bool ShoveSegBehind (uint32_t set, node_t &node, uint32_t seg, uint32_t mate); int SelectSplitter (uint32_t set, node_t &node, uint32_t &splitseg, int step, bool nosplit); + bool ShoveSegBehind (uint32_t set, node_t &node, uint32_t seg, uint32_t mate); + int SelectSplitter (uint32_t set, node_t &node, uint32_t &splitseg, int step, bool nosplit); + void DoGLSegSplit (uint32_t set, node_t &node, uint32_t splitseg, uint32_t &outset0, uint32_t &outset1, int side, int sidev0, int sidev1, bool hack); void SplitSegs (uint32_t set, node_t &node, uint32_t splitseg, uint32_t &outset0, uint32_t &outset1, unsigned int &count0, unsigned int &count1); uint32_t SplitSeg (uint32_t segnum, int splitvert, int v1InFront); int Heuristic (node_t &node, uint32_t set, bool honorNoSplit); diff --git a/src/utility/nodebuilder/nodebuild_utility.cpp b/src/utility/nodebuilder/nodebuild_utility.cpp index 30ead3424d..de3e32759a 100644 --- a/src/utility/nodebuilder/nodebuild_utility.cpp +++ b/src/utility/nodebuilder/nodebuild_utility.cpp @@ -460,7 +460,7 @@ void FNodeBuilder::FindPolyContainers (TArray &spots, TArray= 0) { closestdist = dist; - closestseg = (long)j; + closestseg = j; } } } diff --git a/src/version.h b/src/version.h index 824b157efa..d4257ef084 100644 --- a/src/version.h +++ b/src/version.h @@ -55,7 +55,7 @@ const char *GetVersionString(); // These are for zscript versioning. #define ZSCRIPT_VER_MAJOR 4 -#define ZSCRIPT_VER_MINOR 11 +#define ZSCRIPT_VER_MINOR 12 #define ZSCRIPT_VER_REVISION 0 // This should always refer to the VkDoom version a derived port is based on and not reflect the derived port's version number! @@ -71,7 +71,7 @@ const char *GetVersionString(); // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to // be able to migrate in FGameConfigFile::DoGlobalSetup(). -#define LASTRUNVERSION "224" +#define LASTRUNVERSION "225" // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index a37073a43c..dddc37c310 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -281,20 +281,20 @@ bool DInterBackground::LoadBackground(bool isenterpic) if (!isenterpic) tilebackground = false; texture.SetInvalid(); - level_info_t* li = FindLevelInfo(wbs->current); + level_info_t* li = FindLevelInfo(wbs->current.GetChars()); if (li != nullptr) { - exitpic = li->ExitPic; + exitpic = li->ExitPic.GetChars(); if (li->ExitPic.IsNotEmpty()) tilebackground = false; } lumpname = exitpic; if (isenterpic) { - level_info_t* li = FindLevelInfo(wbs->next); + level_info_t* li = FindLevelInfo(wbs->next.GetChars()); if (li != NULL) { - lumpname = li->EnterPic; + lumpname = li->EnterPic.GetChars(); if (li->EnterPic.IsNotEmpty()) tilebackground = false; } } @@ -309,7 +309,7 @@ bool DInterBackground::LoadBackground(bool isenterpic) case GAME_Doom: if (!(gameinfo.flags & GI_MAPxx)) { - const char* levelname = isenterpic ? wbs->next : wbs->current; + const char* levelname = isenterpic ? wbs->next.GetChars() : wbs->current.GetChars(); if (IsExMy(levelname)) { mysnprintf(buffer, countof(buffer), "$IN_EPI%c", levelname[1]); @@ -331,10 +331,10 @@ bool DInterBackground::LoadBackground(bool isenterpic) if (!(gameinfo.flags & GI_MAPxx)) { // not if the last level is not from the first 3 episodes - if (!IsExMy(wbs->current)) return false; + if (!IsExMy(wbs->current.GetChars())) return false; // not if the next level is one of the first 3 episodes - if (IsExMy(wbs->next)) return false; + if (IsExMy(wbs->next.GetChars())) return false; } } lumpname = "INTERPIC"; @@ -345,7 +345,7 @@ bool DInterBackground::LoadBackground(bool isenterpic) case GAME_Heretic: if (isenterpic) { - if (IsExMy(wbs->next)) + if (IsExMy(wbs->next.GetChars())) { mysnprintf(buffer, countof(buffer), "$IN_HTC%c", wbs->next[1]); lumpname = buffer; @@ -369,7 +369,7 @@ bool DInterBackground::LoadBackground(bool isenterpic) default: // Strife doesn't have an intermission pic so choose something neutral. if (isenterpic) return false; - lumpname = gameinfo.BorderFlat; + lumpname = gameinfo.BorderFlat.GetChars(); tilebackground = true; break; } @@ -664,38 +664,38 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe switch (a->type & ANIM_CONDITION) { case ANIM_IFVISITED: - li = FindLevelInfo(a->LevelName); + li = FindLevelInfo(a->LevelName.GetChars()); if (li == NULL || !(li->flags & LEVEL_VISITED)) continue; break; case ANIM_IFNOTVISITED: - li = FindLevelInfo(a->LevelName); + li = FindLevelInfo(a->LevelName.GetChars()); if (li == NULL || (li->flags & LEVEL_VISITED)) continue; break; // StatCount means 'leaving' - everything else means 'entering'! case ANIM_IFENTERING: - if (state == StatCount || strnicmp(a->LevelName, wbs->next, 8)) continue; + if (state == StatCount || a->LevelName.CompareNoCase(wbs->next, 8)) continue; break; case ANIM_IFNOTENTERING: - if (state != StatCount && !strnicmp(a->LevelName, wbs->next, 8)) continue; + if (state != StatCount && !a->LevelName.CompareNoCase(wbs->next, 8)) continue; break; case ANIM_IFLEAVING: - if (state != StatCount || strnicmp(a->LevelName, wbs->current, 8)) continue; + if (state != StatCount || a->LevelName.CompareNoCase(wbs->current, 8)) continue; break; case ANIM_IFNOTLEAVING: - if (state == StatCount && !strnicmp(a->LevelName, wbs->current, 8)) continue; + if (state == StatCount && !a->LevelName.CompareNoCase(wbs->current, 8)) continue; break; case ANIM_IFTRAVELLING: - if (strnicmp(a->LevelName2, wbs->current, 8) || strnicmp(a->LevelName, wbs->next, 8)) continue; + if (a->LevelName2.CompareNoCase(wbs->current, 8) || a->LevelName.CompareNoCase(wbs->next, 8)) continue; break; case ANIM_IFNOTTRAVELLING: - if (!strnicmp(a->LevelName2, wbs->current, 8) && !strnicmp(a->LevelName, wbs->next, 8)) continue; + if (!a->LevelName2.CompareNoCase(wbs->current, 8) && !a->LevelName.CompareNoCase(wbs->next, 8)) continue; break; } if (a->ctr >= 0) @@ -707,7 +707,7 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe { for (i = 0; iflags & LEVEL_VISITED) drawOnLnode(i, &splat, 1, animwidth, animheight); // draw a splat on taken cities. } } @@ -715,7 +715,7 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe // draw flashing ptr if (snl_pointeron && yah.Size()) { - unsigned int v = MapToIndex(wbs->next); + unsigned int v = MapToIndex(wbs->next.GetChars()); // Draw only if it points to a valid level on the current screen! if (v ParseSteamRegistry(const char* path) +{ + TArray result; + FScanner sc; + if (sc.OpenFile(path)) + { + sc.SetCMode(true); + + sc.MustGetToken(TK_StringConst); + sc.MustGetToken('{'); + // Get a list of possible install directories. + while(sc.GetToken() && sc.TokenType != '}') + { + sc.TokenMustBe(TK_StringConst); + sc.MustGetToken('{'); + + while(sc.GetToken() && sc.TokenType != '}') + { + sc.TokenMustBe(TK_StringConst); + FString key(sc.String); + if(key.CompareNoCase("path") == 0) + { + sc.MustGetToken(TK_StringConst); + result.Push(FString(sc.String) + "/steamapps/common"); + PSR_FindEndBlock(sc); + break; + } + else if(sc.CheckToken('{')) + { + PSR_FindEndBlock(sc); + } + else + { + sc.MustGetToken(TK_StringConst); + } + } + } + } + return result; +} + //========================================================================== // // QueryPathKey @@ -237,21 +295,34 @@ TArray I_GetSteamPath() "Strife", "Ultimate Doom/rerelease/DOOM_Data/StreamingAssets", "Doom 2/rerelease/DOOM II_Data/StreamingAssets", - "Doom 2/finaldoombase" + "Doom 2/finaldoombase", + "Master Levels of Doom/doom2" }; - FString path; + FString steamPath; - if (!QueryPathKey(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", L"SteamPath", path)) + if (!QueryPathKey(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", L"SteamPath", steamPath)) { - if (!QueryPathKey(HKEY_LOCAL_MACHINE, L"Software\\Valve\\Steam", L"InstallPath", path)) + if (!QueryPathKey(HKEY_LOCAL_MACHINE, L"Software\\Valve\\Steam", L"InstallPath", steamPath)) return result; } - path += "/SteamApps/common/"; + + TArray paths = ParseSteamRegistry((steamPath + "/config/libraryfolders.vdf").GetChars()); + + for(FString &path : paths) + { + path.ReplaceChars('\\','/'); + path+="/"; + } + + paths.Push(steamPath + "/steamapps/common/"); for(unsigned int i = 0; i < countof(steam_dirs); ++i) { - result.Push(path + steam_dirs[i]); + for(const FString &path : paths) + { + result.Push(path + steam_dirs[i]); + } } return result; diff --git a/src/win32/zdoom.rc b/src/win32/zdoom.rc index 4c5660a489..f53fae029d 100644 --- a/src/win32/zdoom.rc +++ b/src/win32/zdoom.rc @@ -41,7 +41,7 @@ END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" - " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""zdoom.exe.manifest""\r\n" + " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""..\\common\\platform\\win32\\manifest.xml""\r\n" "#endif\r\n" "\r\n" "/////////////////////////////////////////////////////////////////////////////\r\n" @@ -109,47 +109,10 @@ GUIDELINES DESIGNINFO BEGIN IDD_IWADDIALOG, DIALOG BEGIN - LEFTMARGIN, 5 - RIGHTMARGIN, 223 + LEFTMARGIN, 8 + RIGHTMARGIN, 264 TOPMARGIN, 7 - BOTTOMMARGIN, 241 - END - - IDD_EAXPROPERTYLIST, DIALOG - BEGIN - LEFTMARGIN, 2 - RIGHTMARGIN, 249 - VERTGUIDE, 88 - VERTGUIDE, 122 - TOPMARGIN, 7 - BOTTOMMARGIN, 400 - END - - IDD_EAXEDIT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 273 - TOPMARGIN, 7 - BOTTOMMARGIN, 319 - HORZGUIDE, 299 - END - - IDD_NEWEAX, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 341 - TOPMARGIN, 7 - BOTTOMMARGIN, 250 - HORZGUIDE, 216 - END - - IDD_SAVEEAX, DIALOG - BEGIN - LEFTMARGIN, 6 - RIGHTMARGIN, 377 - VERTGUIDE, 370 - BOTTOMMARGIN, 88 - HORZGUIDE, 12 + BOTTOMMARGIN, 222 END IDD_CRASHDIALOG, DIALOG @@ -202,30 +165,6 @@ END // Dialog // -IDD_IWADDIALOG DIALOGEX 0, 0, 225, 248 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU -EXSTYLE WS_EX_APPWINDOW -CAPTION "Welcome" -FONT 8, "MS Shell Dlg", 0, 0, 0x1 -BEGIN - ICON IDI_ICON1,IDC_STATIC,7,7,20,20 - LTEXT "Welcome to VkDoom!",IDC_STATIC,43,8,180,8 - LTEXT "",IDC_WELCOME_VERSION,43,18,180,8 - GROUPBOX "IWAD selection",IDC_STATIC,8,32,208,117 - LTEXT "Select which game file (IWAD) to run.",IDC_STATIC,12,44,190,8 - LISTBOX IDC_IWADLIST,12,56,200,87,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Video settings",IDC_STATIC,8,155,68,65 - CONTROL "&Fullscreen",IDC_WELCOME_FULLSCREEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,206,48,10 - GROUPBOX "Extra Graphics",IDC_STATIC,159,155,59,64 - CONTROL "Disable &autoload",IDC_WELCOME_NOAUTOLOAD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,86,166,65,10 - CONTROL "&Lights",IDC_WELCOME_LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,164,165,43,10 - CONTROL "&Brightmaps",IDC_WELCOME_BRIGHTMAPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,164,177,51,10 - CONTROL "&Widescreen",IDC_WELCOME_WIDESCREEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,164,188,48,12 - CONTROL "&Don't ask me again",IDC_DONTASKIWAD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,83,190,72,10 - DEFPUSHBUTTON "&Play Game!",IDOK,8,227,90,14 - PUSHBUTTON "E&xit",IDCANCEL,166,227,50,14 - CONTROL "&Vulkan",IDC_WELCOME_VULKAN2,"Button",BS_AUTORADIOBUTTON,13,176,37,10 -END IDD_CRASHDIALOG DIALOGEX 0, 0, 415, 308 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU @@ -243,10 +182,10 @@ STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN EDITTEXT IDC_CRASHINFO,7,126,377,90,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL - CONTROL "",IDC_PLEASETELLUS,"RichEdit20W",ES_MULTILINE | ES_READONLY,7,50,377,54,WS_EX_TRANSPARENT + CONTROL "",IDC_PLEASETELLUS,"RichEdit20W",0x804,7,50,377,54,WS_EX_TRANSPARENT LTEXT "(Optional) To help diagnose the cause of this error, please describe what you were doing when the error occured. If you were playing with custom wads, please also indicate where to obtain them:",IDC_STATIC,7,108,377,16,0,WS_EX_TRANSPARENT CONTROL IDB_BITMAP1,IDC_DEADGUYVIEWER,"Static",SS_BITMAP,345,7,23,26 - CONTROL "",IDC_CRASHHEADER,"RichEdit20W",ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY,18,13,306,25,WS_EX_TRANSPARENT + CONTROL "",IDC_CRASHHEADER,"RichEdit20W",0x884,18,13,306,25,WS_EX_TRANSPARENT CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,42,407,1 GROUPBOX "Summary",IDC_STATIC,7,223,377,34 LTEXT "Static",IDC_CRASHSUMMARY,14,233,363,20 @@ -260,7 +199,7 @@ BEGIN LTEXT "The selected file contains this information:",IDC_STATIC,7,74,136,8 RTEXT "Static",IDC_CRASHFILESIZE,337,74,55,8 LISTBOX IDC_CRASHFILES,7,15,385,53,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - CONTROL "",IDC_CRASHFILECONTENTS,"RichEdit20W",ES_MULTILINE | ES_READONLY | WS_BORDER | WS_VSCROLL | WS_TABSTOP,7,83,385,174 + CONTROL "",IDC_CRASHFILECONTENTS,"RichEdit20W",WS_BORDER | WS_VSCROLL | WS_TABSTOP | 0x804,7,83,385,174 END IDD_ERRORPANE DIALOGEX 0, 0, 190, 28 @@ -340,11 +279,11 @@ BEGIN BEGIN VALUE "Comments", "Thanks to id Software for creating DOOM and then releasing the source code. Thanks also to TeamTNT for creating BOOM, which ZDoom is partially based on. Includes code based on the Cajun Bot 0.97 by Martin Collberg." VALUE "CompanyName", " " - VALUE "FileDescription", "VkDoom " GIT_DESCRIPTION + VALUE "FileDescription", "VkDoom" GIT_DESCRIPTION VALUE "FileVersion", RC_FILEVERSION2 VALUE "InternalName", "VkDoom" - VALUE "LegalCopyright", "This isn't 1995. Typing a copyright here is silly!" - VALUE "LegalTrademarks", "Doom is a Registered Trademark of id Software, Inc." + VALUE "LegalCopyright", "Copyright 1993-1996 id Software, 1998-2010 Randy Heit, 2002-2010 Christoph Oelckers, et al." + VALUE "LegalTrademarks", "DoomR is a Registered Trademark of id Software, Inc." VALUE "OriginalFilename", "vkdoom.exe" VALUE "ProductName", "VkDoom" VALUE "ProductVersion", GIT_DESCRIPTION diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 8725c56e81..25f4d243c4 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 3.1.0 ) +cmake_minimum_required( VERSION 3.16 ) add_subdirectory( re2c ) add_subdirectory( lemon ) diff --git a/tools/lemon/CMakeLists.txt b/tools/lemon/CMakeLists.txt index 71418eda5a..a4da050b3d 100644 --- a/tools/lemon/CMakeLists.txt +++ b/tools/lemon/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 3.1.0 ) +cmake_minimum_required( VERSION 3.16 ) if( NOT CMAKE_CROSSCOMPILING ) set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG" ) diff --git a/tools/re2c/CMakeLists.txt b/tools/re2c/CMakeLists.txt index 9fcfef5a24..6b888773c5 100644 --- a/tools/re2c/CMakeLists.txt +++ b/tools/re2c/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 3.1.0 ) +cmake_minimum_required( VERSION 3.16 ) if( NOT CMAKE_CROSSCOMPILING ) diff --git a/tools/zipdir/CMakeLists.txt b/tools/zipdir/CMakeLists.txt index 65eb2fb72a..d08ca093c4 100644 --- a/tools/zipdir/CMakeLists.txt +++ b/tools/zipdir/CMakeLists.txt @@ -1,9 +1,9 @@ -cmake_minimum_required( VERSION 3.1.0 ) +cmake_minimum_required( VERSION 3.16 ) if( NOT CMAKE_CROSSCOMPILING ) - include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" ) + include_directories( SYSTEM "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" ) add_executable( zipdir zipdir.c ) - target_link_libraries( zipdir ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} lzma ) + target_link_libraries( zipdir miniz ${BZIP2_LIBRARIES} lzma ) set( CROSS_EXPORTS ${CROSS_EXPORTS} zipdir PARENT_SCOPE ) endif() diff --git a/tools/zipdir/zipdir.c b/tools/zipdir/zipdir.c index dab0dac048..4ae81d8e3e 100644 --- a/tools/zipdir/zipdir.c +++ b/tools/zipdir/zipdir.c @@ -46,7 +46,7 @@ #include #include #include -#include "zlib.h" +#include #include "bzlib.h" #include "LzmaEnc.h" #include "7zVersion.h" diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000000..0df558c005 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "builtin-baseline": "2c401863dd54a640aeb26ed736c55489c079323b", + "features": + { + "vcpkg-libvpx": + { + "description": "Use libvpx provided by vcpkg on Windows", + "dependencies": [ + { + "name": "libvpx", + "default-features": false, + "platform": "(!windows & static) | (windows & static & staticcrt)" + } + ] + }, + "vcpkg-openal-soft": + { + "description": "Use openal-soft provided by vcpkg.", + "dependencies": [ + { + "name": "openal-soft", + "default-features": false, + "platform": "(!windows & static) | (windows & static & staticcrt)" + } + ] + } + }, + "dependencies": [ + { + "name": "bzip2", + "platform": "(!windows & static) | (windows & static & staticcrt)" + }, + { + "name": "libvpx", + "platform": "!windows & static" + }, + { + "name": "gtk3", + "platform": "!windows & !osx & static" + }, + { + "name": "glib", + "platform": "!windows & !osx & static" + } + ] +} diff --git a/wadsrc/CMakeLists.txt b/wadsrc/CMakeLists.txt index 28412d7b6f..e8bd78e7cb 100644 --- a/wadsrc/CMakeLists.txt +++ b/wadsrc/CMakeLists.txt @@ -1,3 +1 @@ -cmake_minimum_required( VERSION 3.1.0 ) - add_pk3(vkdoom.pk3 ${CMAKE_CURRENT_SOURCE_DIR}/static) diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 635e27d70e..2440ef55f4 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -277,6 +277,7 @@ D7F6E9F08C39A17026349A04F8C0B0BE // Return to Hadron, e1m9 5B3F118B337BFBFB8D5C81E98AF7B71D // Ancient Aliens map23 7C1913DEE396BA26CFF22A0E9369B7D2 // Nuke Mine, e1m2 BFC69170CCE3550A0A53C4A556E7FD69 // btsx_e2a.wad map06 +566E9CCD2F2F41442E57A9C76074BF1A // pc_cp2.wad MAP27 { pointonline } @@ -320,3 +321,14 @@ F50C91A05E1A1E646690517641F0D1DD // daedalus.wad map19 { shorttex } + +65C155579BEA34642A7B83DF5481B29B // Conf256.pk3 CONF55 +{ + nomirrors +} + +F1EB6927F53047F219A54997DAD9DC81 // mm2.wad map20 +{ + rebuildnodes + trace +} diff --git a/wadsrc/static/engine/commonbinds.txt b/wadsrc/static/engine/commonbinds.txt index 6de42786a3..8493529f2d 100644 --- a/wadsrc/static/engine/commonbinds.txt +++ b/wadsrc/static/engine/commonbinds.txt @@ -61,10 +61,24 @@ dpadleft invprev dpadright invnext dpaddown invuse dpadup togglemap -pad_start pause -pad_back menu_main +pad_start menu_main +pad_back pause lthumb crouch +// Generic gamepad bindings +joy1 +use +joy4 +jump +axis6plus +attack +axis3plus +altattack +joy5 weapprev +joy6 weapnext +pov1left invprev +pov1right invnext +pov1down invuse +pov1up togglemap +joy8 menu_main +joy7 pause +joy10 crouch /* Default automap bindings */ mapbind f am_togglefollow @@ -83,3 +97,24 @@ mapbind kp- +am_zoomout mapbind kp+ +am_zoomin mapbind mwheelup "am_zoom 1.2" mapbind mwheeldown "am_zoom -1.2" + +/* Automap bindings for controllers (bare minimum functionality) */ +mapbind pad_x am_togglefollow +mapbind pad_a am_setmark +mapbind pad_b am_clearmarks +mapbind dpadright +am_panright +mapbind dpadleft +am_panleft +mapbind dpadup +am_panup +mapbind dpaddown +am_pandown +mapbind lshoulder +am_zoomout +mapbind rshoulder +am_zoomin + +mapbind joy3 am_togglefollow +mapbind joy1 am_setmark +mapbind joy2 am_clearmarks +mapbind pov1right +am_panright +mapbind pov1left +am_panleft +mapbind pov1up +am_panup +mapbind pov1down +am_pandown +mapbind joy5 +am_zoomout +mapbind joy6 +am_zoomin diff --git a/wadsrc/static/engine/leftbinds.txt b/wadsrc/static/engine/leftbinds.txt index 63cf50e81b..30604f10d4 100644 --- a/wadsrc/static/engine/leftbinds.txt +++ b/wadsrc/static/engine/leftbinds.txt @@ -1,4 +1,4 @@ -/* Default keybindings for all games */ +/* Default keybindings (keypad) for all games */ KP8 +forward KP5 +back diff --git a/wadsrc/static/filter/doom.id.doom1/after_iwad/sndinfo.txt b/wadsrc/static/filter/doom.id.doom1/after_iwad/sndinfo.txt new file mode 100644 index 0000000000..0c30de958c --- /dev/null +++ b/wadsrc/static/filter/doom.id.doom1/after_iwad/sndinfo.txt @@ -0,0 +1,9 @@ +$musicalias D_E4M1 D_E3M4 +$musicalias D_E4M2 D_E3M2 +$musicalias D_E4M3 D_E3M3 +$musicalias D_E4M4 D_E1M5 +$musicalias D_E4M5 D_E2M7 +$musicalias D_E4M6 D_E2M4 +$musicalias D_E4M7 D_E2M6 +$musicalias D_E4M8 D_E2M5 +$musicalias D_E4M9 D_E1M9 diff --git a/wadsrc/static/graphics/bootlogo.png b/wadsrc/static/graphics/bootlogo.png new file mode 100644 index 0000000000..dda16fa046 Binary files /dev/null and b/wadsrc/static/graphics/bootlogo.png differ diff --git a/wadsrc/static/language.0 b/wadsrc/static/language.0 index 549283172f..8dc54bbd18 100644 --- a/wadsrc/static/language.0 +++ b/wadsrc/static/language.0 @@ -1,9 +1,9 @@ -default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,ja jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,tr,uk,bg -,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,,,, +default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,ja jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,sv,tr,uk,bg +,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,,,,, Press Y or N.,PRESSYN,,,,Stiskni Y nebo N.,Tryk på Y eller N.,Drücke Y oder N.,"Πάτα Y ή N -",Premu Y aŭ N.,Presiona Y o N.,,Paina Y tai N.,Appuyez sur Y ou N.,Nyomj Y-t vagy N-t.,Premi Y oppure N.,YかNで答えろ,Y키 또는 N키를 누르시오.,Druk op Y of N.,Trykk på Y eller N.,Wciśnij Y lub N.,Aperte Y ou N.,Carrega Y ou N.,Apasă Y sau N.,Нажмите Y или N.,Притисните Y или N.,Y veya N tuşuna basın.,Натисніть Y або N.,Натисни Y или N. -Yes,TXT_YES,,,,Ano,Ja,Ja,Ναι,Jes,Sí,,Kyllä,Oui,Igen,Si,はい,네,Ja,Ja,Tak,Sim,,Da,Да,Да,Evet,Так,Да -No,TXT_NO,,,,Ne,Nej,Nein,Όχι,Ne,No,,Ei,Non,Nem,No,いいえ,아니요,Nee,Nei,Nie,Não,,Nu,Нет,Не,Hayır,Ні,Не +",Premu Y aŭ N.,Presiona Y o N.,,Paina Y tai N.,Appuyez sur Y ou N.,Nyomj Y-t vagy N-t.,Premi Y oppure N.,YかNで答えろ,Y키 또는 N키를 누르시오.,Druk op Y of N.,Trykk på Y eller N.,Wciśnij Y lub N.,Aperte Y ou N.,Carrega Y ou N.,Apasă Y sau N.,Нажмите Y или N.,Притисните Y или N.,Tryck på Y eller N.,Y veya N tuşuna basın.,Натисніть Y або N.,Натисни Y или N. +Yes,TXT_YES,,,,Ano,Ja,Ja,Ναι,Jes,Sí,,Kyllä,Oui,Igen,Si,はい,네,Ja,Ja,Tak,Sim,,Da,Да,Да,Ja,Evet,Так,Да +No,TXT_NO,,,,Ne,Nej,Nein,Όχι,Ne,,,Ei,Non,Nem,,いいえ,아니요,Nee,Nei,Nie,Não,,Nu,Нет,Не,Nej,Hayır,Ні,Не "You can't save if you aren't playing! Press a key.",SAVEDEAD,,,,"Mimo hru nelze ukládat! @@ -46,15 +46,15 @@ Apasă o tastă.","Невозможно сохранить игру, не нач Нажмите любую клавишу.","Не можете сачувати игру ако не играте! -Притисните тастер.","Eğer oynamıyorsanız kaydedemezsiniz! +Притисните тастер.",Du kan inte spara om du inte spelar! Tryck på en tangent.,"Eğer oynamıyorsanız kaydedemezsiniz! Bir tuşa bas.","Ви не можете зберегти гру, не почавши її! Натисніть будь яку клавішу.","Не може да запазите играта, ако не играете! Натиснете клавиш." -Do you really want to do this?,SAFEMESSAGE,,,,Vážně to chceš udělat?,Vil du virkelig gøre dette?,Möchtest du das wirklich tun?,,Ĉu vi vere volas fari ĉi tion?,¿Realmente quieres hacer esto?,¿Realmente quieres hacerlo?,Haluatko varmasti tehdä tämän?,Voulez-vous vraiment faire ça?,Biztos ezt akarod tenni?,Sei sicuro di volerlo fare?,本当に実行するのか?,정말로 정하시겠습니까?,Wil je dit echt doen?,Vil du virkelig gjøre dette?,Naprawdę chcesz to zrobić?,Você deseja mesmo fazer isso?,Desejas mesmo fazer isso?,Ești sigur că vrei să faci asta?,Вы уверены?,Да ли заиста желите то да урадите?,Bunu gerçekten yapmak istiyor musun?,Ви дійсно хочете цього?,Наистина ли искаш да направиш това? -Not set,NOTSET,,,,Není nastavené,Ikke indstillet,Nicht gesetzt,,Ne agordita,No asignado,,Ei asetettu,Pas paramétré,Nincs beállítva,Non assegnato,セットされてない,정하지 않음,Niet ingesteld,Ikke innstilt,Nie ustawiono,Não definido,,Nesetat,Не задан,Није намештено,Ayarlanmamış,Не встановлено,Не е зададено +Do you really want to do this?,SAFEMESSAGE,,,,Vážně to chceš udělat?,Vil du virkelig gøre dette?,Möchtest du das wirklich tun?,Θέλετε πραγματικά να το κάνετε αυτό;,Ĉu vi vere volas fari tion?,¿Realmente quieres hacer eso?,,Haluatko varmasti tehdä tämän?,Voulez-vous vraiment faire ça?,Biztos ezt akarod tenni?,Sei sicuro di volerlo fare?,本当に実行するのか?,정말로 정하시겠습니까?,Wil je dit echt doen?,Vil du virkelig gjøre dette?,Naprawdę chcesz to zrobić?,Você deseja mesmo fazer isso?,Desejas mesmo fazer isso?,Ești sigur că vrei să faci asta?,Вы уверены?,Да ли заиста желите то да урадите?,Vill du verkligen göra det här?,Bunu gerçekten yapmak istiyor musun?,Ви дійсно хочете цього?,Наистина ли искаш да направиш това? +Not set,NOTSET,,,,Není nastavené,Ikke indstillet,Nicht gesetzt,Δεν έχει οριστεί,Ne agordita,No asignado,,Ei asetettu,Pas paramétré,Nincs beállítva,Non assegnato,セットされてない,정하지 않음,Niet ingesteld,Ikke innstilt,Nie ustawiono,Não definido,,Nesetat,Не задан,Није намештено,Inte inställd,Ayarlanmamış,Не встановлено,Не е зададено "Quicksave over your game named '%s'? @@ -69,7 +69,9 @@ Stiskni Y nebo N.","Quicksave over dit spil navngivet Tryk på Y eller N.","Überschreibe %s mit einem Schnellspeicherspielstand? -Drücke Y oder N.",,"Ĉu rapidkonservi anstataŭigante vian ludadon nomitan +Drücke Y oder N.","Γρήγορη αποθήκευση πάνω από το παιχνίδι σας με το όνομα '%s'; + +Πατήστε Y ή N.","Ĉu rapidkonservi anstataŭigante vian ludadon nomitan '%s'? @@ -129,7 +131,8 @@ Apasă Y sau N.","Перезаписать быстрое сохранение „%s“? -Притисните Y или N.","%s' +Притисните Y или N.","Snabbspara över ditt spel som heter %s? +Tryck på Y eller N.","%s' adlı oyununuzun üzerine hızlı kaydetme? @@ -156,7 +159,9 @@ Stiskni Y nebo N.","Ønsker du at quickloade spillet ved navn Tryk på Y eller N.","Möchtest du den Spielstand %s schnellladen? -Drücke Y oder N.",,"Ĉu vi volas rapidŝargi la ludadon nomitan +Drücke Y oder N.","Θέλετε να κάνετε γρήγορη φόρτωση του παιχνιδιού με το όνομα '%s'; + +Πατήστε Y ή N.","Ĉu vi volas rapidŝargi la ludadon nomitan '%s'? @@ -216,7 +221,8 @@ Apasă Y sau N.","Загрузить быстрое сохранение „%s“? -Притисните Y или N.","%s' +Притисните Y или N.","Vill du snabbladda spelet som heter ""%s""? +Tryck på Y eller N.","%s' adlı oyunu hızlı yüklemek istiyor musunuz? @@ -229,620 +235,646 @@ Y veya N tuşuna basın.","Завантажити швидке збережен '%s'? Натисни Y или N." -%s cheats,TXT_X_CHEATS,This is a gender sensitive message where %s represents the player,,,%s podvádí,%s snyder,%s schummelt,@[art_gr] %s απατάει,%s trompas,%s hace trampas,%s hace trampa,%s huijaa,%s triche.,%s csal,%s imbroglia,%s はチート使用,%s 이(가) 치트를 사용 함,%s bedriegt,%s jukser,%s oszukuje,%s está trapaceando,%s está a fazer batota,%s trișează,%s использует чит-коды,%s вара,%s hileleri,%s чітерить,%s измамен код -Messages: OFF,MSGOFF,,,,Oznámení ZAP.,Meddelelser: FRA,Meldungen AUS,Μηνύματα ΚΛΕΙΣΤΑ,Mesaĝoj: MALŜALTITA,Mensajes DESACTIVADOS,,Viestit POIS PÄÄLTÄ,Messages désactivés.,Üzenetek: KI,Messaggi DISATTIVATI,メッセージ: オフ,메시지 끔,Berichten UIT,Meldinger: AV,Wiadomości WYŁĄCZONE,Mensagens DESATIVADAS,,Mesaje OPRITE,Сообщения ОТКЛЮЧЕНЫ,Поруке ИСКЉУЧЕНЕ,Mesajlar: KAPALI,Повідомлення: ВІДКЛЮЧЕНІ,Съобщения: Изкл -Messages: ON,MSGON,,,,Oznámení VYP.,Meddelelser: TIL,Meldungen AN,Μηνύματα ΑΝΟΙΧΤΑ,Mesaĝoj: ŜALTITA,Mensajes ACTIVADOS,,Viestit PÄÄLLÄ,Messages activés.,Üzenetek: BE,Messaggi ATTIVATI,メッセージ: オン,메시지 켬,Berichten AAN,Meldinger: PÅ,Wiadomości WŁĄCZONE,Mensagens ATIVADAS,,Mesaje PORNITE,Сообщения ВКЛЮЧЕНЫ,Поруке УКЉУЧЕНЕ,Mesajlar: AÇIK,Повідомлення: ВКЛЮЧЕНІ,Съобщения: Вкл -Say:,TXT_SAY,,,,Říct:,Sig:,Sage:,Πές:,Diri:,,,Sano:,Parler:,Üzenet:,Parla:,発言:,,Zeg:,Si:,Powiedz:,Dizer:,Diz:,Vorbește:,Чат:,Пиши:,Söyle:,Чат:,Пиши: -Press any key or click anywhere in the window to quit.,TXT_QUITENDOOM,,,,"Pro ukončení stiskni libovolnou klávesu, nebo klikni kdekoliv v okně.",Tryk på en vilkårlig tast eller klik et vilkårligt sted i vinduet for at afslutte.,Drücke eine Taste oder klicke mit der Maus ins Fenster zum Beenden.,Πάτα οποιοδήποτε πλήκτρο ή πάτα οπουδήποτε για να κάνεις έξοδο,Premu ajnan klavon aŭ alklaku ie ajn en la fenestro por forlasi.,Presiona una tecla o haz clic en cualquier lugar de la ventana para salir.,Presiona una tecla o cliquea en cualquier lugar de la ventana para salir.,Paina mitä tahansa näppäintä tai napsauta minne tahansa ikkunaa lopettaaksesi.,Appuyez sur une touche ou cliquez pour quitter.,Nyomjon egy gombot vagy kattintson valahova a kilépéshez.,Premi un qualunque tasto o fai un click ovunque nella finestra per uscire.,何かのキーを押すか、ウィンドウのどこかをクリックすると終了する。,아무 키를 누르거나 아무 곳이나 클릭하면 종료됩니다.,Druk op een willekeurige toets of klik ergens in het venster om te stoppen.,Trykk på en hvilken som helst tast eller klikk hvor som helst i vinduet for å avslutte.,Wciśnij dowolny klawisz lub gdziekolwiek kliknij myszką aby wyjść.,Aperte uma tecla ou clique em qualquer lugar na janela para sair.,Carrega numa tecla ou clique em qualquer lugar na janela para sair.,Apasă orice tastă sau apasă click oriunde în fereastră pentru a ieși.,"Нажмите любую клавишу или нажмите по окну, чтобы выйти.",Притисните било који тастер или кликните било где на екрану да одустанете.,Çıkmak için herhangi bir tuşa basın veya pencerede herhangi bir yere tıklayın.,"Натисніть будь яку клавішу чи натисніть по вікну, щоб вийти.","Натиснете който и да е клавиш или щракнете където и да е в прозореца, за да излезете." -,,Savegame,,,,,,,,,,,,,,,,,,,,,,,,,, -,NEWSAVE,,,,,,,,,,,,,<Új mentés>,,<新規セーブ>,<새로운 게임 저장>,,,,,,,<Новое сохранение>,<Нова сачувана игра>,,<Нове збереження>,<Нов запис на играта> -Game saved.,GGSAVED,,,,Hra uložena.,Spillet er gemt.,Spielstand gespeichert.,Παχνίδι αποθηκέυτηκε.,Ludado konservita.,Partida guardada.,,Peli tallennettu.,Partie sauvegardée.,Játék mentve.,Partita salvata.,セーブ完了。,게임이 저장됨.,Spel opgeslagen.,Spillet er lagret.,Gra zapisana.,Jogo salvo.,Jogo gravado.,Joc salvat.,Игра сохранена.,Игра сачувана.,Oyun kaydedildi.,Гру збережено.,Играта е записана +%s cheats,TXT_X_CHEATS,This is a gender sensitive message where %s represents the player,,,%s podvádí,%s snyder,%s schummelt,@[art_gr] %s απατάει,%s trompas,%s hace trampas,%s hace trampa,%s huijaa,%s triche.,%s csal,%s imbroglia,%s はチート使用,%s 이(가) 치트를 사용 함,%s bedriegt,%s jukser,%s oszukuje,%s está trapaceando,%s está a fazer batota,%s trișează,%s использует чит-коды,%s вара,%s fuskar,%s hileleri,%s чітерить,%s измамен код +Messages: OFF,MSGOFF,,,,Oznámení ZAP.,Meddelelser: FRA,Meldungen AUS,Μηνύματα ΚΛΕΙΣΤΑ,Mesaĝoj: MALŜALTITA,Mensajes DESACTIVADOS,,Viestit POIS PÄÄLTÄ,Messages désactivés.,Üzenetek: KI,Messaggi DISATTIVATI,メッセージ: オフ,메시지 끔,Berichten UIT,Meldinger: AV,Wiadomości WYŁĄCZONE,Mensagens DESATIVADAS,,Mesaje OPRITE,Сообщения ОТКЛЮЧЕНЫ,Поруке ИСКЉУЧЕНЕ,Meddelanden: Av,Mesajlar: KAPALI,Повідомлення: ВИМКНЕНІ,Съобщения: Изкл +Messages: ON,MSGON,,,,Oznámení VYP.,Meddelelser: TIL,Meldungen AN,Μηνύματα ΑΝΟΙΧΤΑ,Mesaĝoj: ŜALTITA,Mensajes ACTIVADOS,,Viestit PÄÄLLÄ,Messages activés.,Üzenetek: BE,Messaggi ATTIVATI,メッセージ: オン,메시지 켬,Berichten AAN,Meldinger: PÅ,Wiadomości WŁĄCZONE,Mensagens ATIVADAS,,Mesaje PORNITE,Сообщения ВКЛЮЧЕНЫ,Поруке УКЉУЧЕНЕ,Meddelanden: På,Mesajlar: AÇIK,Повідомлення: УВІМКНЕНІ,Съобщения: Вкл +Say:,TXT_SAY,,,,Říct:,Sig:,Sage:,Πές:,Diri:,,,Sano:,Parler:,Üzenet:,Parla:,発言:,,Zeg:,Si:,Mów:,Dizer:,Diz:,Vorbește:,Чат:,Пиши:,Säg:,Söyle:,Чат:,Пиши: +Press any key or click anywhere in the window to quit.,TXT_QUITENDOOM,,,,"Pro ukončení stiskni libovolnou klávesu, nebo klikni kdekoliv v okně.",Tryk på en vilkårlig tast eller klik et vilkårligt sted i vinduet for at afslutte.,Drücke eine Taste oder klicke mit der Maus ins Fenster zum Beenden.,Πάτα οποιοδήποτε πλήκτρο ή πάτα οπουδήποτε για να κάνεις έξοδο,Premu ajnan klavon aŭ alklaku ie ajn en la fenestro por forlasi.,Presiona una tecla o haz clic en cualquier lugar de la ventana para salir.,,Paina mitä tahansa näppäintä tai napsauta minne tahansa ikkunaa lopettaaksesi.,Appuyez sur une touche ou cliquez pour quitter.,Nyomjon egy gombot vagy kattintson valahova a kilépéshez.,Premi un qualunque tasto o fai un click ovunque nella finestra per uscire.,何かのキーを押すか、ウィンドウのどこかをクリックすると終了する。,아무 키를 누르거나 아무 곳이나 클릭하면 종료됩니다.,Druk op een willekeurige toets of klik ergens in het venster om te stoppen.,Trykk på en hvilken som helst tast eller klikk hvor som helst i vinduet for å avslutte.,Wciśnij dowolny klawisz lub kliknij myszką by wyjść.,Aperte uma tecla ou clique em qualquer lugar na janela para sair.,Carrega numa tecla ou clique em qualquer lugar na janela para sair.,Apasă orice tastă sau apasă click oriunde în fereastră pentru a ieși.,"Нажмите любую клавишу или нажмите по окну, чтобы выйти.",Притисните било који тастер или кликните било где на екрану да одустанете.,Tryck på någon tangent eller klicka någonstans i fönstret för att avsluta.,Çıkmak için herhangi bir tuşa basın veya pencerede herhangi bir yere tıklayın.,"Натисніть будь яку клавішу чи натисніть по вікну, щоб вийти.","Натиснете който и да е клавиш или щракнете където и да е в прозореца, за да излезете." +,,Savegame,,,,,,,,,,,,,,,,,,,,,,,,,,, +,NEWSAVE,,,,,,,<Νέο παιχνίδι αποθήκευσης>,,,,,,<Új mentés>,,<新規セーブ>,<새로운 게임 저장>,,,,,,,<Новое сохранение>,<Нова сачувана игра>,,,<Нове збереження>,<Нов запис на играта> +Game saved.,GGSAVED,,,,Hra uložena.,Spillet er gemt.,Spielstand gespeichert.,Παχνίδι αποθηκέυτηκε.,Ludado konservita.,Partida guardada.,,Peli tallennettu.,Partie sauvegardée.,Játék mentve.,Partita salvata.,セーブ完了。,게임이 저장됨.,Spel opgeslagen.,Spillet er lagret.,Gra zapisana.,Jogo salvo.,Jogo gravado.,Joc salvat.,Игра сохранена.,Игра сачувана.,Spelet är sparat.,Oyun kaydedildi.,Гру збережено.,Играта е записана Time,SAVECOMMENT_TIME,,,,Čas,Tid,Zeit,Χρόνος,Tempo,Tiempo,,Aika,Temps,Idő,Tempo,"時間 -",시간,Tijd,Tid,Czas,Tempo,,Timp,Время,Време,Zaman,Час,Време -Load Game,MNU_LOADGAME,,,,Načíst hru,Indlæs spil,Spiel laden,Φώρτωσε παιχνίδι,Ŝargi ludadon,Cargar cartida,,Lataa peli,Chargement,Játék betöltése,Carica partita,ロード,게임 불러오기,Laden spel,Last inn spill,Wczytaj Grę,Carregar jogo,,Încărcare Joc,Загрузка,Учитај игру,Oyun Yükle,Завантажити,Зареди игра -Save Game,MNU_SAVEGAME,,,,Uložit hru,Gem spil,Spiel sichern,Αποθήκευσε παιχνίδι,Konservi ludadon,Guardar partida,,Tallenna peli,Sauvegarde,Játék mentése,Salva partita,セーブ,게임 저장하기,Opslaan spel,Lagre spill,Zapisz Grę,Salvar jogo,Gravar,Salvare Joc,Сохранение,Сачувај игру,Oyunu Kaydet,Зберегти,Запази игра +",시간,Tijd,Tid,Czas,Tempo,,Timp,Время,Време,Tid,Zaman,Час,Време +Load Game,MNU_LOADGAME,,,,Načíst hru,Indlæs spil,Spiel laden,Φώρτωσε παιχνίδι,Ŝargi ludadon,Cargar partida,,Lataa peli,Chargement,Játék betöltése,Carica partita,ロード,게임 불러오기,Laden spel,Last inn spill,Wczytaj Grę,Carregar jogo,,Încărcare Joc,Загрузка,Учитај игру,Ladda spelet,Oyun Yükle,Завантажити,Зареди игра +Save Game,MNU_SAVEGAME,,,,Uložit hru,Gem spil,Spiel sichern,Αποθήκευσε παιχνίδι,Konservi ludadon,Guardar partida,,Tallenna peli,Sauvegarde,Játék mentése,Salva partita,セーブ,게임 저장하기,Opslaan spel,Lagre spill,Zapisz Grę,Salvar jogo,Gravar,Salvare Joc,Сохранение,Сачувај игру,Spara spelet,Oyunu Kaydet,Зберегти,Запази игра No Picture,MNU_NOPICTURE,,,,Bez obrázku,Intet billede,Kein Bild,Καμία εικόνα,Neniu bildo,Sin imagen,,Ei kuvaa,Pas d'image,Nincs kép,Nessuna immagine,画像無し,사진 없음,Geen beeld,Ingen bilde,Brak obrazka,Sem imagem,,Lipsă Imagine,"Нет -изображения",Нема слике,Resim yok,Немає зображення,Без изображение +изображения",Нема слике,Ingen bild,Resim yok,Немає зображення,Без изображение Different Version,MNU_DIFFVERSION,,,,Jiná verze,Anderledes version,Falsche Version,Διαφορετική έκδοση,Malsama versio,Versión diferente,,Eri versio,Version Différente,Eltérő verzió,Versione differente,"別バージョンの -データ",다른 버젼,Anders Versie,Annen versjon,Inna Wersja,Versão diferente,,Versiune Diferită,Другая версия,Другачија верзија,Farklı Versiyon,Інша версія,Различна версия -No files,MNU_NOFILES,,,,Žádné soubory,Ingen filer,Keine Dateien,Καθ΄λου αρχεία ,Neniu dosiero,Sin archivos,,Ei tiedostoja,Pas de fichiers,Nincsenek fájlok,Nessun file,ファイル無し,파일 없음,Geen bestanden,Ingen filer,Brak plików,Vazio,,Niciun fișier,Нет файлов,Нема фајлова,Dosya yok,Немає файлів,Няма файлове +データ",다른 버젼,Anders Versie,Annen versjon,Inna Wersja,Versão diferente,,Versiune Diferită,Другая версия,Другачија верзија,Annan version,Farklı Versiyon,Інша версія,Различна версия +No files,MNU_NOFILES,,,,Žádné soubory,Ingen filer,Keine Dateien,Καθ΄λου αρχεία ,Neniu dosiero,Sin archivos,,Ei tiedostoja,Pas de fichiers,Nincsenek fájlok,Nessun file,ファイル無し,파일 없음,Geen bestanden,Ingen filer,Brak plików,Vazio,,Niciun fișier,Нет файлов,Нема фајлова,Inga filer,Dosya yok,Немає файлів,Няма файлове "Do you really want to delete the savegame? ",MNU_DELETESG,,,,Opravdu smazat tuto uloženou hru?,Ønsker du virkelig at slette det gemte spil?,Willst du diesen Spielstand wirklich löschen?,Θέλεις όντος να διαγράξεις το αποθηκευμένο παιχνίδι;,Ĉu vi vere volas forigi la konservitan ludadon?,"¿Realmente deseas borrar la partida? ",,Haluatko varmasti poistaa tallennetun pelin ,"Voulez vous vraiment effacer cette sauvegarde? -",Biztosan törlöd a mentést?,Vuoi veramente cancellare il salvataggio?,本当にこのセーブを消すのか?,저장된 게임을 정말로 삭제하시겠습니까?,Wil je echt de opgeslagen spel verwijderen?,Vil du virkelig slette lagringsspillet?,Czy naprawdę chcesz usunąć zapis gry?,Deseja mesmo excluir o jogo salvo?,Deseja mesmo apagar o jogo,Vrei să ștergi salvarea?,Вы действительно хотите удалить сохранение?,Да ли стварно желите да избришете сачувану игру,"Gerçekten kayıt oyununu silmek istiyor musunuz? +",Biztosan törlöd a mentést?,Vuoi veramente cancellare il salvataggio?,本当にこのセーブを消すのか?,저장된 게임을 정말로 삭제하시겠습니까?,Wil je echt de opgeslagen spel verwijderen?,Vil du virkelig slette lagringsspillet?,Czy naprawdę chcesz usunąć zapis gry?,Deseja mesmo excluir o jogo salvo?,Deseja mesmo apagar o jogo,Vrei să ștergi salvarea?,Вы действительно хотите удалить сохранение?,Да ли стварно желите да избришете сачувану игру,Vill du verkligen radera sparfilen?,"Gerçekten kayıt oyununu silmek istiyor musunuz? ",Ви дійсно хочете видалити це збереження?,Найстина ли искаш да изтриеш запазената игра -,,General,,,,,,,,,,,,,,,,,,,,,,,,,, -Off,OPTVAL_OFF,,,,Vyp.,Fra,Aus,,Malŝaltita,Desactivado,,Pois,,Ki,Disattivo,オフ,끔,Uit,Av,Wyłączone,Não,,Pornit,Откл.,Искљ.,Kapalı,Вимк.,Изкл. -On,OPTVAL_ON,,,,Zap.,Til,An,,Ŝaltita,Activado,,Päällä,,Be,Attivo,オン,켬,Aan,På,Włączone,Sim,,Oprit,Вкл.,Укљ.,Açık,Увім.,Вкл. -Auto,OPTVAL_AUTO,,,,,Automatisk,,,Aŭtomata,Automático,,Automaattinen,,Automatikus,Automatico,自動,자동,,Auto,Automatycznie,Automático,,,Авто,Аутоматски,Otomatik,Авто,Автоматично -Options,OPTMNU_TITLE,,,,Možnosti,Indstillinger,Optionen,Ρυθμίσεις,Agordoj,Opciones,,Asetukset,Options,Beállítások,Opzioni,オプション,설정,Opties,Alternativer,Opcje,Opções,,Opțiuni,Настройки,Подешавања,Seçenekler,Налаштування,Настройки -Customize Controls,OPTMNU_CONTROLS,,,,Ovládání,Tilpas kontrolelementer,Steuerung einstellen,,Adapti regilojn,Personalizar controles,,Ohjausasetukset,Modifier les Contrôles,Irányítás testreszabása,Personalizza i controlli,キー配置変更,조작 사용자 지정,Instellen van de controle,Tilpass kontroller,Ustaw Klawisze,Personalizar comandos,Configurar Controlos,Personalizare Setări Control,Управление,Контроле,Kontrolleri Özelleştir,Керування,Управление -Mouse Options,OPTMNU_MOUSE,,,,Myš,Indstillinger for mus,Mauseinstellungen,Ρυθμίσεις ποντικίου,Muso-agordoj,Opciones de ratón,,Hiiriasetukset,Options de la Souris,Egér beállítások,Opzioni Mouse,マウス オプション,마우스 설정,Muis opties,Alternativer for mus,Opcje Myszki,Opções de mouse,Opções do rato,Setări Mouse,Мышь,Миш,Fare Seçenekleri,Миш,Мишка -Controller Options,OPTMNU_JOYSTICK,,,,Ovladač,Indstillinger for controller,Joystickeinstellungen,,Ludregilo-agordoj,Opciones de mando,,Peliohjainasetukset,Options de la Manette,Játékvezérlő beállítások,Opzioni Joystick,コントローラーオプション,조이스틱 설정,Controller opties,Kontrollalternativer,Opcje Kontrolera,Opções de controle,,Setări Controller,Контроллер,Контролер,Kontrolör Seçenekleri,Контролер,Контролер -Player Setup,OPTMNU_PLAYER,,,,Hráč,Spilleropsætning,Spieler einrichten,Ρυθμίσεις παίχτη,Ludanto-agordaĵo,Config. del jugador,,Pelaaja-asetukset,Options du Joueur,Játékos testreszabása,Settaggio giocatore,プレイヤーの特徴,플레이어 설정,Speler instellen,Spilleroppsett,Ustawienia Gracza,Configurações de jogador,Configurações do Jogador,Personalizare Jucător,Игрок,Играч,Oyuncu Kurulumu,Гравець,Играч -Gameplay Options,OPTMNU_GAMEPLAY,,,,Herní mechaniky,Indstillinger for gameplay,Spieleinstellungen,,Ludado-agordoj,Opciones de jugabilidad,,Pelattavuusasetukset,Options du Gameplay,Játékmenet beállítások,Opzioni Gameplay,ゲームプレイ オプション,게임 설정,Gameplay-opties,Spillalternativer,Opcje Rozgrywki,Opções de jogabilidade,,Setări pe timp de joc,Игра,Гејмплеј,Oynanış Seçenekleri,Гра,Игра -Automap Options,OPTMNU_AUTOMAP,,,,Automapa,Automap-indstillinger,Automapeinstellungen,,Aŭtomapo-agordoj,Opciones del automapa,,Automaattikartan asetukset,Options de la Carte,Térkép beállítások,Opzioni Automappa,オートマップ オプション,오토맵 설정,Automap-opties,Automap-alternativer,Opcje Mapy,Opções de automapa,,Hartă computerizată,Автокарта,Аутомапа,Otomatik Harita Seçenekleri,Автокарта,Автокарта -HUD Options,OPTMNU_HUD,,,,Rozhraní a HUD,HUD-indstillinger,HUD Einstellungen,Ρυθμίσεις HUD,Agordoj de HUD,Opciones del HUD,,Tilanäytön asetukset,Options de l'ATH,HUD beállítások,Opzioni HUD,HUD オプション,HUD 설정,HUD opties,HUD-alternativer,Opcje HUD,Opções de HUD,,Setări HUD,Интерфейс,HUD,HUD Seçenekleri,Ігровий інтерфейс,Интерфейс -Miscellaneous Options,OPTMNU_MISCELLANEOUS,,,,Ostatní,Diverse indstillinger,Verschiedene Einstellungen,Διάφορες ρυθμίσεις,Diversaĵaj agordoj,Opciones misceláneas,,Sekalaiset asetukset,Options Annexes,Egyéb beállítások,Opzioni Miste,その他のオプション,그 외 설정,Diverse opties,Diverse alternativer,Różne Opcje,Outras opções,,Setări diverse,Дополнительно,Разно,Çeşitli Seçenekler,Різне,Други настройки -Sound Options,OPTMNU_SOUND,,,,Zvuk,Lydindstillinger,Soundeinstellungen,Ρυθμίσεις ήχου,Sono-agordoj,Opciones de sonido,,Ääniasetukset,Options du Son,Hang beállítások,Opzioni Suono,サウンド オプション,음향 설정,Geluidsopties,Lydalternativer,Opcje Dźwięku,Opções de som,,Setări sunet,Звук,Звук,Ses Seçenekleri,Звук,Звука -Display Options,OPTMNU_DISPLAY,,,,Grafika,Visningsindstillinger,Anzeigeeinstellungen,,Ekrano-agordoj,Opciones de visualización,,Näyttöasetukset,Options de l'Affichage,Megjelenítés beállítások,Opzioni Display,ディスプレイ オプション,디스플레이 설정,Weergaveopties,Visningsalternativer,Opcje Wyświetlania,Opções de vídeo,,Setări afișare,Экран,Приказ,Görüntüleme Seçenekleri,Екран,Екрана -Set video mode,OPTMNU_VIDEO,,,,Obrazový výstup,Indstil videomodus,Videomodus,Άλλαξε λειτουργία βίντεο,Agordi videoreĝimon,Modos de vídeo,Modos de video,Aseta videotila,Choisir Mode D'Affichage,Videó beállítások,Settaggio modalità video,ビデオ 調整,화면 설정,Videomodus instellen,Angi videomodus,Ustaw tryb wideo,Definir modo de vídeo,,Setare mod video,Видеорежим,Видео мод,Video modunu ayarlama,Відеорежим,Видеорежим -Reset to defaults,OPTMNU_DEFAULTS,,,,Obnovit původní,Nulstil til standardindstillingerne,Auf Vorgaben zurücksetzen,Επαναφορά σε προεπιλεγμένες ρυθμίσεις,Restarigi al defaŭltoj,Valores por defecto,,Palauta oletusasetukset,Réinitialiser les paramètres,Alapértelmezett beállítások használata,Reimposta ai valori di default,初期設定に戻す,초기화,Terugzetten naar standaardinstellingen,Tilbakestill til standardinnstillinger,Resetuj do domyślnych,Redefinir para configurações padrão,,Revenire la setări implicite,Сбросить все настройки,Врати подразумевано,Varsayılanlara sıfırla,Скинути налаштування,Нулирай до стандартни -Reset to last saved,OPTMNU_RESETTOSAVED,,,,Obnovit naposledy uložené,Nulstil til sidst gemte,Auf gespeicherte Werte zurücksetzen,,Restarigi al lasta konservita,Últimos valores guardados,,Palauta viimeksi tallennettu tila,Recharger dernière config.,Legutóbbi mentett beállítások használata,Reimposta ai valori salvati l'ultima volta,最後に保存した設定に戻す,이전 설정으로 초기화,Reset naar laatste opgeslagen,Tilbakestill til sist lagret,Resetuj do ostatnio zapisanych,Redefinir para a última configuração salva,Redefinir para última configuração gravada,Revenire la ultimele setări salvate,Возврат к сохранённым настройкам,Врати задње сачувано,Son kaydedilene sıfırla,Відновити останні збережені налаштування,Нулирай до последно запазената игра -Save current settings,OPTMNU_WRITEINI,,,,Uložit současná nastavení,Gem de aktuelle indstillinger,Aktuelle Einstellungen speichern,Αποθήκευσε της τορινές ρυθμίσεις,Konservi nunajn reĝimojn,Guardar los ajustes de ahora,,Tallenna nykyiset asetukset,,Jelenlegi beállítások mentése,Salva le impostazioni correnti,現在の設定を保存,현재 설정 적용,Huidige instellingen opslaan ,Lagre gjeldende innstillinger,Zapisz aktualne opcje,Salvar configurações atuais,,Salvează setările curente,Сохранить текущие настройки,,Geçerli ayarları kaydet,Зберегти поточні налаштування,Запази сегашните настройки -Go to console,OPTMNU_CONSOLE,,,,Otevřít konzoli,Gå til konsol,Öffne Konsole,Μπές στη κονσόλα,Iri al konzolo,Ir a la consola,,Mene konsoliin,Ouvrir la console,Konzol megnyitása,Vai alla console,コンソールを開く,콘솔로 이동,Ga naar de console,Gå til konsoll,Przejdź do konsoli,Abrir console,Abrir consola,Mergi la consolă,Открыть консоль,Отвори конзолу,Konsola git,Відкрити консоль,Отвори конзолата -Network Options,OPTMNU_NETWORK,,,,Síť,Netværksindstillinger,Netzwerkeinstellungen,Ρυθμίσεις Δικτύου,Reto-agordoj,Opciones de red,,Verkkoasetukset,Options Réseau,Hálózati beállítások,Opzioni Network,ネットワーク オプション,네트워크 설정,Netwerkopties,Nettverksalternativer,Opcje Sieciowe,Opções de rede,,Setări de Rețea,Сеть,Мрежа,Ağ Seçenekleri,Мережа,Мрежа -Reverb environment editor,OPTMNU_REVERB,,,,Editor zvukové ozvěny,Reverb editor,Hall-Editor,Επεξεργαστής περιβαλλόντων απόσβεσης,Redaktoro pri resonmedio,Editor de amb. de reverberación,,Kaikutilaeditori,Editeur environement de révérb.,Visszhangkörnyezet-szerkesztő,Editor ambiente reverb,リバーブ環境エディタ,울림 환경 편집기,Reverb-omgeving editor,Reverb-miljøredigering,Edytor pogłosu środowiska,Editor de ambiente de reverberação,,Setări Reverb,Редактор реверберации,Уредник одјека у околини,Reverb ortam düzenleyicisi,Редактор ревербації,Редактор на среда за реверберация -,,Customize controls,,,,,,,,,,,,,,,,,,,,,,,,,, -"ENTER to change, BACKSPACE to clear",CNTRLMNU_SWITCHTEXT1,,,,"ENTER pro změnu, BACKSPACE pro smazání","ENTER for at ændre, BACKSPACE for at slette",ENTER: Editieren BACKSPACE: Löschen,,"ENTER por ŝanĝi, BACKSPACE por forigi","ENTER para cambiar, RETROCESO para borrar","ENTER para cambiar, BACKSPACE para borrar","Aseta ENTERILLÄ, tyhjennä ASKELPALAUTTIMELLA","ENTREE pour changer, RET. ARRIERE pour effacer.","ENTER a változtatáshoz, BACKSPACE a törléshez","INVIO per modificare, BACKSPACE per ripulire",Enter で決定、BackSpaceで無効化,"바꿀려면 ENTER키, 지울려면 BACKSPACE키를 누르시오","ENTER om te veranderen, BACKSPACE om te wissen.","ENTER for å endre, BACKSPACE for å slette","ENTER by zmienić, BACKSPACE by wyczyścić",Aperte ENTER para alterar e BACKSPACE para remover,,"ENTER pentru a schimba, BACKSPACE pentru ștergere","ENTER — изменить, BACKSPACE — очистить","ENTER за промену, BACKSPACE за чишћење","Değiştirmek için ENTER, silmek için BACKSPACE","ENTER — змінити, BACKSPACE — очистити","ENTER — промяна, BACKSPACE — изчистване" -"Press new key for control, ESC to cancel",CNTRLMNU_SWITCHTEXT2,,,,"Zmáčkni novou klávesu, nebo ESC pro storno","Tryk på ny tast for kontrol, ESC for at annullere",Drücke eine Taste oder ESC um abzubrechen,,"Premu novan klavon por regilo, ESC por nuligi","Presiona una tecla para el control, ESC para cancelar",,"Valitse näppäin toiminnolle, ESC peruuttaa","Appuyez sur la nouvelle touche pour l'assigner, -Appuyez sur ECHAP pour annuler.","Nyomj meg egy gombot, ESC a törléshez","Premi un nuovo tasto per il controllo, ESC per cancellare","登録したいキーを押すか, Escでキャンセル","명령을 얽으려면 아무 키를, 취소는 ESC키를 누르시오","Druk op de nieuwe toets voor controle, ESC om te annuleren.","Trykk på ny tast for kontroll, ESC for å avbryte","Wciśnij nowy przycisk by zmienić klawisz, ESC by anulować",Aperte uma nova tecla para o comando e ESC para cancelar,"Carrega a nova tecla para o comando, ESC para cancelar","Apasă tasta nouă, sau ESC pentru anulare","Нажмите новую клавишу, ESC для отмены","Притисните ново тастер за одређивање контроле, ESC за отказивање","Kontrol için yeni tuşa, iptal etmek için ESC'ye basın","Натисніть на клавішу для її призначення, ESC для скасування","Натисни нов клавиш за управление, ESC за отмяна" -Controls,CNTRLMNU_CONTROLS,,,,Ovládání,Kontrolelementer,Steuerung,,Regiloj,Controles,,Ohjaimet,Contrôles,Irányítás,Controlli,操作系統,조작,Bedieningselementen,Kontroller,Klawisze,Comandos,Controlos,Control,Управление,Контроле,Kontroller,Керування,Управление -Fire,CNTRLMNU_ATTACK,,,,Střelba,Ild,Feuer,Πυροβόλα,Pafi,Fuego,,Tuli,Tirer,Tűz,Fuoco,撃つ,공격,Vuur,Brann,Strzał,Atirar,,Foc,Атака,Нападни,Yangın,Атака,Атака -Secondary Fire,CNTRLMNU_ALTATTACK,,,,Sekundární střelba,Sekundær ild,Alternativfeuer,,Pafi duarange,Fuego secundario,,Vaihtoehtoistuli,Tir Secondaire,Másodlagos tüzelés,Fuoco secondario,セカンダリ,보조 공격,Secundaire vuur,Sekundær ild,Strzał Alternatywny,Tiro secundário,,Foc Secundar,Дополнительная атака,Секундарни напад,İkincil Yangın,Додаткова атака,Допълнителна атака -Weapon Reload,CNTRLMNU_RELOAD,,,,Přebít zbraň,Våben Genopladning,Waffe nachladen,Επαναφόρτωση Όπλου,Reŝargi armilon,Recargar Arma,,Aseen lataus,Recharger Arme,Fegyver újratöltése,Ricarica dell'arma,リロード,무기 장전,Wapenherladen,Våpen Reload,Przeładowanie Broni,Recarregar arma,,Încărcare Armă,Перезарядка,Напуни,Silah Yeniden Doldurma,Перезарядка,Презареди -Use / Open,CNTRLMNU_USE,,,,Použít/otevřít,Brug / Åbn,Benutzen / Öffnen,,Uzi/Malfermi,Usar/Abrir,,Käytä / Avaa,Utiliser/Ouvrir,Akciógomb/Nyitás,Usa/Apri,開く / スイッチ等使用,사용/열기,Gebruik / Openen,Bruk / Åpne,Użyj / Otwórz,Usar / Abrir,,Folosește / Deschide,Использовать/открыть,Користи / Отвори,Kullan / Aç,Відкрити / Використати,Използвай / Отвори -Move forward,CNTRLMNU_FORWARD,,,,Vpřed,Flyt fremad,Vorwärts bewegen,,Movi anatŭen,Avanzar,,Liiku eteenpäin,Avancer,Előre mozgás,Movimento in avanti,前進,앞으로 이동,Voorwaarts bewegen,Gå fremover,Idź do przodu,Mover-se para frente,,Deplasare în față,Движение вперёд,Крећи се напред,İlerleyin,Рухатись вперед,Движение напред -Move backward,CNTRLMNU_BACK,,,,Vzad,Bevæge sig bagud,Rückwarts bewegen,,Movi malantaŭen,Retroceder,,Liiku taaksepäin,Reculer,Hátra mozgás,Movimento in indietro,後退,뒤로 이동,Achteruit bewegen,Gå bakover,Idź do tyłu,Mover-se para trás,,Deplasare în spate,Движение назад,Крећи се уназад,Geriye doğru hareket et,Рухатись назад,Движение назад -Strafe left,CNTRLMNU_MOVELEFT,,,,Úkrok vlevo,Flyt til venstre,Nach links bewegen,,Flankmovi maldekstren,Moverse a la izquierda,,Astu sivuun vasemmalle,Aller à Gauche,Balra oldalazás,Movimento laterale a sinistra,左移動,왼쪽으로 이동,Verplaats naar links,Strafe venstre,Unik w lewo,Mover-se para a esquerda,,Deplasare diagonală stânga,Движение влево,Крећи се лево,Strafe sola,Рухатись вліво,Движение в ляво -Strafe right,CNTRLMNU_MOVERIGHT,,,,Úkrok vpravo,Flyt til højre,Nach rechts bewegen,,Flankmovi dekstren,Moverse a la derecha,,Astu sivuun oikealle,Aller à Droite,Jobbra oldalazás,Movimento laterale a destra,右移動,오른쪽으로 이동,Verplaats naar rechts,Strafe til høyre,Unik w prawo,Mover-se para a direita,,Deplasare diagonală dreapta,Движение вправо,Крећи се десно,Strafe sağa,Рухатись вправо,Движение в дясно +,,General,,,,,,,,,,,,,,,,,,,,,,,,,,, +Off,OPTVAL_OFF,,,,Vyp.,Fra,Aus,ενεργοποιημένη,Malŝaltita,Desactivado,,Pois,,Ki,Disattivo,オフ,끔,Uit,Av,Wyłączone,Não,,Pornit,Откл.,Искљ.,Av,Kapalı,Вимк.,Изкл. +On,OPTVAL_ON,,,,Zap.,Til,An,άπενεργοποιημένη,Ŝaltita,Activado,,Päällä,,Be,Attivo,オン,켬,Aan,På,Włączone,Sim,,Oprit,Вкл.,Укљ.,På,Açık,Увім.,Вкл. +Auto,OPTVAL_AUTO,,,,,Automatisk,,Αυτό,Aŭtomata,Automático,,Automaattinen,,Automatikus,Automatico,自動,자동,,,Automatycznie,Automático,,,Авто,Аутоматски,Automatiskt,Otomatik,Авто,Автоматично +Options,OPTMNU_TITLE,,,,Možnosti,Indstillinger,Optionen,Ρυθμίσεις,Agordoj,Opciones,,Asetukset,,Beállítások,Opzioni,オプション,설정,Opties,Alternativer,Opcje,Opções,,Opțiuni,Настройки,Подешавања,Alternativ,Seçenekler,Налаштування,Настройки +Customize Controls,OPTMNU_CONTROLS,,,,Ovládání,Tilpas kontrolelementer,Steuerung einstellen,Προσαρμογή χειριστηρίων,Adapti regilojn,Personalizar controles,,Ohjausasetukset,Modifier les Contrôles,Irányítás testreszabása,Personalizza i controlli,キー配置変更,조작 사용자 지정,Instellen van de controle,Tilpass kontroller,Ustaw Klawisze,Personalizar comandos,Configurar Controlos,Personalizare Setări Control,Управление,Контроле,Anpassa kontrollerna,Kontrolleri Özelleştir,Керування,Управление +Mouse Options,OPTMNU_MOUSE,,,,Myš,Indstillinger for mus,Mauseinstellungen,Ρυθμίσεις ποντικίου,Muso-agordoj,Opciones de ratón,,Hiiriasetukset,Options de la Souris,Egér beállítások,Opzioni Mouse,マウス オプション,마우스 설정,Muis opties,Alternativer for mus,Opcje Myszki,Opções de mouse,Opções do rato,Setări Mouse,Мышь,Миш,Alternativ för musen,Fare Seçenekleri,Миш,Мишка +Controller Options,OPTMNU_JOYSTICK,,,,Ovladač,Indstillinger for controller,Joystickeinstellungen,Επιλογές ελεγκτή,Ludregilo-agordoj,Opciones de mando,,Peliohjainasetukset,Options de la Manette,Játékvezérlő beállítások,Opzioni Joystick,コントローラーオプション,조이스틱 설정,Controller opties,Kontrollalternativer,Opcje Kontrolera,Opções de controle,,Setări Controller,Контроллер,Контролер,Alternativ för styrenhet,Kontrolör Seçenekleri,Контролер,Контролер +Player Setup,OPTMNU_PLAYER,,,,Hráč,Spilleropsætning,Spieler einrichten,Ρυθμίσεις παίχτη,Ludanto-agordaĵo,Configuración del jugador,,Pelaaja-asetukset,Options du Joueur,Játékos testreszabása,Settaggio giocatore,プレイヤーの特徴,플레이어 설정,Speler instellen,Spilleroppsett,Ustawienia Gracza,Configurações de jogador,Configurações do Jogador,Personalizare Jucător,Игрок,Играч,Inställning av spelare,Oyuncu Kurulumu,Гравець,Играч +Gameplay Options,OPTMNU_GAMEPLAY,,,,Herní mechaniky,Indstillinger for gameplay,Spieleinstellungen,Επιλογές παιχνιδιού,Ludado-agordoj,Opciones de jugabilidad,,Pelattavuusasetukset,Options du Gameplay,Játékmenet beállítások,Opzioni Gameplay,ゲームプレイ オプション,게임 설정,Gameplay-opties,Spillalternativer,Opcje Rozgrywki,Opções de jogabilidade,,Setări pe timp de joc,Игра,Гејмплеј,Spelalternativ,Oynanış Seçenekleri,Ігрові механіки,Игра +Automap Options,OPTMNU_AUTOMAP,,,,Automapa,Automap-indstillinger,Automapeinstellungen,Επιλογές Automap,Agordoj de la aŭtomata mapo,Opciones del automapa,,Automaattikartan asetukset,Options de la Carte,Térkép beállítások,Opzioni Automappa,オートマップ オプション,오토맵 설정,Automap-opties,Automap-alternativer,Opcje Mapy,Opções de automapa,,Hartă computerizată,Автокарта,Аутомапа,Automap-alternativ,Otomatik Harita Seçenekleri,Автокарта,Автокарта +HUD Options,OPTMNU_HUD,,,,Rozhraní a HUD,HUD-indstillinger,HUD Einstellungen,Ρυθμίσεις HUD,Agordoj de HUD,Opciones del HUD,,Tilanäytön asetukset,Options de l'ATH,HUD beállítások,Opzioni HUD,HUD オプション,HUD 설정,HUD opties,HUD-alternativer,Opcje HUD,Opções de HUD,,Setări HUD,Интерфейс,,HUD-alternativ,HUD Seçenekleri,Ігровий інтерфейс,Интерфейс +Miscellaneous Options,OPTMNU_MISCELLANEOUS,,,,Ostatní,Diverse indstillinger,Verschiedene Einstellungen,Διάφορες ρυθμίσεις,Diversaĵaj agordoj,Opciones misceláneas,,Sekalaiset asetukset,Options Annexes,Egyéb beállítások,Opzioni Miste,その他のオプション,그 외 설정,Diverse opties,Diverse alternativer,Różne Opcje,Outras opções,,Setări diverse,Дополнительно,Разно,Diverse alternativ,Çeşitli Seçenekler,Інше,Други настройки +Sound Options,OPTMNU_SOUND,,,,Zvuk,Lydindstillinger,Soundeinstellungen,Ρυθμίσεις ήχου,Sono-agordoj,Opciones de sonido,,Ääniasetukset,Options du Son,Hang beállítások,Opzioni Suono,サウンド オプション,음향 설정,Geluidsopties,Lydalternativer,Opcje Dźwięku,Opções de som,,Setări sunet,Звук,Звук,Ljudalternativ,Ses Seçenekleri,Звук,Звука +Display Options,OPTMNU_DISPLAY,,,,Grafika,Visningsindstillinger,Anzeigeeinstellungen,Επιλογές οθόνης,Ekrano-agordoj,Opciones de visualización,,Näyttöasetukset,Options de l'Affichage,Megjelenítés beállítások,Opzioni Display,ディスプレイ オプション,디스플레이 설정,Weergaveopties,Visningsalternativer,Opcje Wyświetlania,Opções de vídeo,,Setări afișare,Экран,Приказ,Visningsalternativ,Görüntüleme Seçenekleri,Екран,Екрана +Set video mode,OPTMNU_VIDEO,,,,Obrazový výstup,Indstil videomodus,Videomodus,Άλλαξε λειτουργία βίντεο,Agordi videoreĝimon,Modos de vídeo,Modos de video,Aseta videotila,Choisir Mode D'Affichage,Videó beállítások,Settaggio modalità video,ビデオ 調整,화면 설정,Videomodus instellen,Angi videomodus,Ustaw tryb wideo,Definir modo de vídeo,,Setare mod video,Видеорежим,Видео мод,Ställ in videoläge,Video modunu ayarlama,Відеорежим,Видеорежим +Reset to defaults,OPTMNU_DEFAULTS,,,,Obnovit původní,Nulstil til standardindstillingerne,Auf Vorgaben zurücksetzen,Επαναφορά σε προεπιλεγμένες ρυθμίσεις,Restarigi al defaŭltoj,Valores por defecto,,Palauta oletusasetukset,Réinitialiser les paramètres,Alapértelmezett beállítások használata,Reimposta ai valori di default,初期設定に戻す,초기화,Terugzetten naar standaardinstellingen,Tilbakestill til standardinnstillinger,Resetuj do domyślnych,Redefinir para configurações padrão,,Revenire la setări implicite,Сбросить все настройки,Врати подразумевано,Återställ till standardvärden,Varsayılanlara sıfırla,Скинути налаштування,Нулирай до стандартни +Reset to last saved,OPTMNU_RESETTOSAVED,,,,Obnovit naposledy uložené,Nulstil til sidst gemte,Auf gespeicherte Werte zurücksetzen,Επαναφορά στην τελευταία αποθήκευση,Restarigi al lasta konservita,Últimos valores guardados,,Palauta viimeksi tallennettu tila,Recharger dernière config.,Legutóbbi mentett beállítások használata,Reimposta ai valori salvati l'ultima volta,最後に保存した設定に戻す,이전 설정으로 초기화,Reset naar laatste opgeslagen,Tilbakestill til sist lagret,Resetuj do ostatnio zapisanych,Redefinir para a última configuração salva,Redefinir para última configuração gravada,Revenire la ultimele setări salvate,Возврат к сохранённым настройкам,Врати задње сачувано,Återställ till senast sparade,Son kaydedilene sıfırla,Відновити останні збережені налаштування,Нулирай до последно запазената игра +Save current settings,OPTMNU_WRITEINI,,,,Uložit současná nastavení,Gem de aktuelle indstillinger,Aktuelle Einstellungen speichern,Αποθήκευσε της τορινές ρυθμίσεις,Konservi nunajn reĝimojn,Guardar los ajustes de ahora,,Tallenna nykyiset asetukset,Sauvegarde des Paramètres Actuels,Jelenlegi beállítások mentése,Salva le impostazioni correnti,現在の設定を保存,현재 설정 적용,Huidige instellingen opslaan ,Lagre gjeldende innstillinger,Zapisz aktualne opcje,Salvar configurações atuais,,Salvează setările curente,Сохранить текущие настройки,,Spara aktuella inställningar,Geçerli ayarları kaydet,Зберегти поточні налаштування,Запази сегашните настройки +Go to console,OPTMNU_CONSOLE,,,,Otevřít konzoli,Gå til konsol,Öffne Konsole,Μπές στη κονσόλα,Iri al konzolo,Ir a la consola,,Mene konsoliin,Ouvrir la console,Konzol megnyitása,Vai alla console,コンソールを開く,콘솔로 이동,Ga naar de console,Gå til konsoll,Przejdź do konsoli,Abrir console,Abrir consola,Mergi la consolă,Открыть консоль,Отвори конзолу,Gå till konsolen,Konsola git,Відкрити консоль,Отвори конзолата +Network Options,OPTMNU_NETWORK,,,,Síť,Netværksindstillinger,Netzwerkeinstellungen,Ρυθμίσεις Δικτύου,Reto-agordoj,Opciones de red,,Verkkoasetukset,Options Réseau,Hálózati beállítások,Opzioni Network,ネットワーク オプション,네트워크 설정,Netwerkopties,Nettverksalternativer,Opcje Sieciowe,Opções de rede,,Setări de Rețea,Сеть,Мрежа,Nätverksalternativ,Ağ Seçenekleri,Мережа,Мрежа +Reverb environment editor,OPTMNU_REVERB,,,,Editor zvukové ozvěny,Reverb editor,Hall-Editor,Επεξεργαστής περιβαλλόντων απόσβεσης,Redaktoro pri resonmedio,Editor de amb. de reverberación,,Kaikutilaeditori,Editeur environement de révérb.,Visszhangkörnyezet-szerkesztő,Editor ambiente reverb,リバーブ環境エディタ,울림 환경 편집기,Reverb-omgeving editor,Reverb-miljøredigering,Edytor pogłosu środowiska,Editor de ambiente de reverberação,,Setări Reverb,Редактор реверберации,Уредник одјека у околини,Redigerare för reverbmiljö,Reverb ortam düzenleyicisi,Редактор реверберації,Редактор на среда за реверберация +,,Customize controls,,,,,,,,,,,,,,,,,,,,,,,,,,, +"ENTER to change, BACKSPACE to clear",CNTRLMNU_SWITCHTEXT1,,,,"ENTER pro změnu, BACKSPACE pro smazání","ENTER for at ændre, BACKSPACE for at slette",ENTER: Editieren BACKSPACE: Löschen,"ENTER για αλλαγή, BACKSPACE για διαγραφή","ENTER por ŝanĝi, BACKSPACE por forigi","ENTER para cambiar, RETROCESO para borrar","ENTER para cambiar, BACKSPACE para borrar","Aseta ENTERILLÄ, tyhjennä ASKELPALAUTTIMELLA","ENTREE pour changer, RET. ARRIERE pour effacer.","ENTER a változtatáshoz, BACKSPACE a törléshez","INVIO per modificare, BACKSPACE per ripulire",Enter で決定、BackSpaceで無効化,"바꿀려면 ENTER키, 지울려면 BACKSPACE키를 누르시오","ENTER om te veranderen, BACKSPACE om te wissen.","ENTER for å endre, BACKSPACE for å slette","ENTER by zmienić, BACKSPACE by wyczyścić",Aperte ENTER para alterar e BACKSPACE para remover,,"ENTER pentru a schimba, BACKSPACE pentru ștergere","ENTER — изменить, BACKSPACE — очистить","ENTER за промену, BACKSPACE за чишћење","ENTER för att ändra, BACKSPACE för att radera","Değiştirmek için ENTER, silmek için BACKSPACE","ENTER — змінити, BACKSPACE — очистити","ENTER — промяна, BACKSPACE — изчистване" +"Press new key for control, ESC to cancel",CNTRLMNU_SWITCHTEXT2,,,,"Zmáčkni novou klávesu, nebo ESC pro storno","Tryk på ny tast for kontrol, ESC for at annullere",Drücke eine Taste oder ESC um abzubrechen,"Πατήστε το νέο πλήκτρο για έλεγχο, ESC για ακύρωση","Premu novan klavon por regilo, ESC por nuligi","Presiona una tecla para el control, ESC para cancelar",,"Valitse näppäin toiminnolle, ESC peruuttaa","Appuyez sur la nouvelle touche pour l'assigner, +Appuyez sur ECHAP pour annuler.","Nyomj meg egy gombot, ESC a törléshez","Premi un nuovo tasto per il controllo, ESC per cancellare","登録したいキーを押すか, Escでキャンセル","명령을 얽으려면 아무 키를, 취소는 ESC키를 누르시오","Druk op de nieuwe toets voor controle, ESC om te annuleren.","Trykk på ny tast for kontroll, ESC for å avbryte","Wciśnij nowy przycisk by zmienić klawisz, ESC by anulować",Aperte uma nova tecla para o comando e ESC para cancelar,"Carrega a nova tecla para o comando, ESC para cancelar","Apasă tasta nouă, sau ESC pentru anulare","Нажмите новую клавишу, ESC для отмены","Притисните ново тастер за одређивање контроле, ESC за отказивање","Tryck på ny tangent för kontroll, ESC för att avbryta","Kontrol için yeni tuşa, iptal etmek için ESC'ye basın","Натисніть на клавішу для її призначення, ESC для скасування","Натисни нов клавиш за управление, ESC за отмяна" +Controls,CNTRLMNU_CONTROLS,,,,Ovládání,Kontrolelementer,Steuerung,Έλεγχοι,Regiloj,Controles,,Ohjaimet,Contrôles,Irányítás,Controlli,操作系統,조작,Bedieningselementen,Kontroller,Klawisze,Comandos,Controlos,Control,Управление,Контроле,Kontroller,Kontroller,Керування,Управление +Fire,CNTRLMNU_ATTACK,,,,Střelba,Ild,Feuer,Πυροβόλα,Pafi,Fuego,,Tuli,Tirer,Tűz,Fuoco,撃つ,공격,Vuur,Brann,Strzał,Atirar,,Foc,Атака,Нападни,Eld,Yangın,Атака,Атака +Secondary Fire,CNTRLMNU_ALTATTACK,,,,Sekundární střelba,Sekundær ild,Alternativfeuer,Δευτερεύουσα Πυροβόλα,Pafi duarange,Fuego secundario,,Vaihtoehtoistuli,Tir Secondaire,Másodlagos tüzelés,Fuoco secondario,セカンダリ,보조 공격,Secundaire vuur,Sekundær ild,Strzał Alternatywny,Tiro secundário,,Foc Secundar,Дополнительная атака,Секундарни напад,Sekundär eld,İkincil Yangın,Додаткова атака,Допълнителна атака +Weapon Reload,CNTRLMNU_RELOAD,,,,Přebít zbraň,Våben Genopladning,Waffe nachladen,Επαναφόρτωση Όπλου,Reŝargi armilon,Recargar arma,,Aseen lataus,Recharger Arme,Fegyver újratöltése,Ricarica dell'arma,リロード,무기 장전,Wapenherladen,Våpen Reload,Przeładowanie Broni,Recarregar arma,,Încărcare Armă,Перезарядка,Напуни,Ladda om vapen,Silah Yeniden Doldurma,Перезарядка,Презареди +Use / Open,CNTRLMNU_USE,,,,Použít/otevřít,Brug / Åbn,Benutzen / Öffnen,Χρήση / Άνοιγμα,Uzi/Malfermi,Usar/Abrir,,Käytä / Avaa,Utiliser/Ouvrir,Akciógomb/Nyitás,Usa/Apri,開く / スイッチ等使用,사용/열기,Gebruik / Openen,Bruk / Åpne,Użyj / Otwórz,Usar / Abrir,,Folosește / Deschide,Использовать/открыть,Користи / Отвори,Användning/öppna,Kullan / Aç,Відкрити / Використати,Използвай / Отвори +Move forward,CNTRLMNU_FORWARD,,,,Vpřed,Flyt fremad,Vorwärts bewegen,Μετακίνηση προς τα εμπρός,Moviĝi anatŭen,Avanzar,,Liiku eteenpäin,Avancer,Előre mozgás,Movimento in avanti,前進,앞으로 이동,Voorwaarts bewegen,Gå fremover,Idź do przodu,Mover-se para frente,,Deplasare în față,Движение вперёд,Крећи се напред,Flytta framåt,İlerleyin,Рухатись вперед,Движение напред +Move backward,CNTRLMNU_BACK,,,,Vzad,Bevæge sig bagud,Rückwarts bewegen,Μετακίνηση προς τα πίσω,Moviĝi malantaŭen,Retroceder,,Liiku taaksepäin,Reculer,Hátra mozgás,Movimento in indietro,後退,뒤로 이동,Achteruit bewegen,Gå bakover,Idź do tyłu,Mover-se para trás,,Deplasare în spate,Движение назад,Крећи се уназад,Flytta bakåt,Geriye doğru hareket et,Рухатись назад,Движение назад +Strafe left,CNTRLMNU_MOVELEFT,,,,Úkrok vlevo,Flyt til venstre,Nach links bewegen,Μετακίνηση προς τα αριστερά,Flankmovi maldekstren,Moverse a la izquierda,,Astu sivuun vasemmalle,Aller à Gauche,Balra oldalazás,Movimento laterale a sinistra,左移動,왼쪽으로 이동,Verplaats naar links,Strafe venstre,Unik w lewo,Mover-se para a esquerda,,Deplasare diagonală stânga,Движение влево,Крећи се лево,Strafe till vänster,Strafe sola,Рухатись вліво,Движение в ляво +Strafe right,CNTRLMNU_MOVERIGHT,,,,Úkrok vpravo,Flyt til højre,Nach rechts bewegen,Μετακίνηση προς τα δεξιά,Flankmovi dekstren,Moverse a la derecha,,Astu sivuun oikealle,Aller à Droite,Jobbra oldalazás,Movimento laterale a destra,右移動,오른쪽으로 이동,Verplaats naar rechts,Strafe til høyre,Unik w prawo,Mover-se para a direita,,Deplasare diagonală dreapta,Движение вправо,Крећи се десно,Strafe till höger,Strafe sağa,Рухатись вправо,Движение в дясно Turn left,CNTRLMNU_TURNLEFT,,,,Otočení vlevo,Drej til venstre,Nach links drehen,Γύρνα αριστερά,Turni maldekstren,Girar a la izquierda,,Käänny vasemmalle,Tourner à Gauche,Balra fordul,"Gira a sinistra -",左を向く,왼쪽으로 회전,Draai naar links,Sving til venstre,Obróć się w lewo,Girar para a esquerda,,Întoarcere stânga,Поворот налево,Окрени се лево,Sola dön,Повернутись ліворуч,Обръщане в ляво -Turn right,CNTRLMNU_TURNRIGHT,,,,Otočení vpravo,Drej til højre,Nach rechts drehen,Γύρνα δεξιά,Turni dekstren,Girar a la derecha,,Käänny oikealle,Tourner à Droite,Jobbra fordul,Gira a destra,右を向く,오른쪽으로 회전,Draai naar rechts,Sving til høyre,Obróć się w prawo,Girar para a direita,,Întoarcere dreapta,Поворот направо,Окрени се десно,Sağa dön,Повернутись праворуч,Обръщане в дясно -Quick Turn,CNTRLMNU_TURN180,,,,Rychlé otočení,Hurtig drejning,Schnelle Drehung,Γρήγορη γύριση,Rapida turno,Giro rápido,,Pikakäännös,Faire un 180,Megfordulás,Rotazione rapida,背後を向く,빠른 회전,Snelle draai,Rask sving,Szybki Obrót,Giro rápido,,Întoarcere rapidă,Быстрый разворот,Брзи окрет,Hızlı Dönüş,Швидкий розворот,Бързо обръщане -Jump,CNTRLMNU_JUMP,,,,Skok,Hop,Springen,Πήδα,Salti,Saltar,,Hyppää,Sauter,Ugrás,Salto,ジャンプ,점프,Springen,Hopp,Skok,Pular,Saltar,Salt,Прыжок,Скок,Atlama,Стрибок,Скок -Crouch,CNTRLMNU_CROUCH,,,,Kleknutí,Kryb,Ducken,,Kaŭri,Agacharse,,Kyyristy,S'accroupir (tenir),Guggolás,Abbassarsi,屈む,숙이기,Hurken,Huk,Kucnięcie,Agachar,,Ghemuire,Присесть,Чучни,Çömelme,Присісти,Клякане -Crouch Toggle,CNTRLMNU_TOGGLECROUCH,,,,Přepnout kleknutí,Krybbe omskifter,Ducken an/aus,,Kaŭrobaskuli,Alternar agachado,,Kyyristymisen vaihtokytkin,S'accroupir (alterner),Guggolási kapcsoló,Attivare/disattivare abbassamento,屈む切替,숙이기 토글,Hurken Toggle,Crouch Toggle,Przełącz kucnięcie,Agachar (alternar),,Comutator ghemuire,Присесть/встать,Чучни (без држања),Çömelme anahtarı,Лазити,Клякане постоянно -Mouse look,CNTRLMNU_MOUSELOOK,,,,Pohled myší,Musens udseende,Maus-Blick,Κοίτα με το ποντίκι,Musrigardo,Vista con ratón,,Hiirikatselu,Vue à la souris,Egérrel való nézelődés,Modalità vista col mouse,マウス視点上下化,마우스 룩,Muis-look,Museblikk,Rozglądanie się myszką,Visão com o mouse,Vista com o rato,Privire în jur cu mouse,Обзор мышью,Гледај мишем,Fare bakışı,Огляд мишкою,Поглед с мишката -Look up,CNTRLMNU_LOOKUP,Look doesn't change the aim! It only alters the view pitch,,,Pohled vzhůru,Se op,Nach oben schauen,Κοίτα απάνω,Rigardi supren,Mirar arriba,,Katso ylös,Regarder en haut,Felfele nézés,Guarda sopra,視点を上げる,위로 보기,Kijk omhoog,Se opp,Patrz w górę,Olhar para cima,,Privire în sus,Смотреть вверх,Гледај горе,Yukarı bak.,Подивитись вверх,Поглед нагоре -Look down,CNTRLMNU_LOOKDOWN,,,,Pohled dolů,Se nedad,Nach unten schauen,Κοίτα κάτω,Rigardi malsupren,Mirar abajo,,Katso alas,Regarder en bas,Lefele nézés,Guarda sotto,視点を下げる,아래로 보기,Kijk naar beneden,Se nedover,Patrz w dół,Olhar para baixo,,Privire în jos,Смотреть вниз,Гледај доле,Aşağı bak.,Подивитись вниз,Поглед надолу -Center view,CNTRLMNU_CENTERVIEW,,,Centre view,Vystředit pohled,Centreret visning,Ansicht zentrieren,,Centrigi vidon,Centrar vista,,Keskitä katse,Recentrer Vue,Nézet középreigazítása,Sguardo centrato,視点を戻す,중앙 시점으로 보기,Middenaanzicht,Midtstilt visning,Wyśrodkuj widok,Olhar para o centro,,Centrare privire,Отцентрировать взгляд,Централизирај поглед,Merkezden görünüm,Центрувати погляд,Центриране на погледа -Run,CNTRLMNU_RUN,,,,Běh,Kør,Rennen,Τρέχα,Kuri,Correr,,Juokse,Courir (tenir),Futás,Corri,駆け足,달리기,Rennen,Kjør,Bieg,Correr,,Fugă,Бежать,Трчи,Koşmak,Біг,Бягане -Toggle Run,CNTRLMNU_TOGGLERUN,,,,Přepnout běh,Skift Kør,Rennen an/aus,Ενεργοποίηση τρέξιμου,Baskuligi kuron,Alternar «Correr»,,Juoksun vaihtokytkin,Courir (alterner),Futás kapcsoló,Abilita/disabilita corsa,常時駆け足切替,달리기 토글,Rennen aan/uit,Veksle Kjør,Przełącz bieg,Correr (alternar),,Comutator fugă,Бежать/идти,Трчи (без држања),Değiştir Çalıştır,Бігти / ходити,Бягане постоянно -Strafe,CNTRLMNU_STRAFE,,,,Pohyb do stran,Strafe,Seitwärts,,Flankmovi,Desplazamiento,,Astu sivuttain,Pas de côté,Oldalazás,Spostamento laterale,横移動化,양옆으로 이동,Zijdelings bewegen,Strafe,Uniki,Deslocamento lateral,,Deplasare în diagonală,Движение боком,Кретање у страну,Strafe,Рухатись боком,Странично движение -Show Scoreboard,CNTRLMNU_SCOREBOARD,,,,Zobrazit tabulku skóre,Vis resultattavle,Punktetafel anzeigen,,Montri poentotabulon,Mostrar marcador,,Näytä pistetaulu,Afficher Scores (tenir),Eredményjelző megjelenítése,Mostra la tabella punteggio,スコアボード表示,점수창 표시,Scorebord tonen,Vis resultattavle,Pokaż tablicę wyników,Exibir placar,,Afișare tabelă de marcaj,Таблица очков,Табела,Skor Tablosunu Göster,Таблиця очків,Покажи резултати -Action,CNTRLMNU_ACTION,,,,Akce,Handling,Aktion,Δράσεις,Ago,Acción,,Toiminta,,Akció,Azione,アクション,동작,Actie,Handling,Akcja,Ação,,Acțiuni,Основное,Радња,Eylem,Дії,Действие -Customize Action Controls,CNTRLMNU_ACTION_TITLE,,,,Nastavení ovládání akcí,Tilpas handlingskontroller,Aktions-Steuerung einstellen,,Adapti agajn regilojn,Cambiar controles de acción,,Toimintaohjausasetukset,Changer Contrôles Action,Akció beállítások testreszabása,Personalizza i controlli di azione,アクション操作設定,사용자 지정 동작 컨트롤,Aanpassen van de actiecontroles,Tilpass handlingskontroller,Ustaw Klawisze Akcji,Personalizar comandos de ação,Configurar Controlos de Ação,Personalizare schemă acțiuni,Основные клавиши управления,Контроле радње,Eylem Kontrollerini Özelleştirme,Налаштування елементів дій,Персонализиране на контролите за действие -Chat,CNTRLMNU_CHAT,,,,Chat,Chat,Chat,Μίλα,Babili,Chat,,Keskustelu,Chat,Chat,Chat,チャット,채팅,Chat,Chat,Czat,Bate-papo,Conversar,Conversație,Чат,Ћаскање,Sohbet,Чат,Чат -Multiplayer,MNU_MULTIPLAYER,,,,,,Mehrspieler,,Plurludanta,Multijugador,,Moninpeli,Multijoueur,Többjátékos,Multigiocatore,マルチプレイヤー,,,Flerspiller,Tryb Wieloosobowy,Multijogador,,Joc Online,Сетевая игра,,Çok Oyunculu,Гра в мережі,Онлайн игра -Say,CNTRLMNU_SAY,,,,Říct,Sig,Reden,Πές,Diri,Hablar,,Sano,Parler,Üzenet ,Parla,発言,채팅하기,Zeg,Si,Powiedz,Dizer,,Vorbește,Сообщение,Пиши,Söyle,Написати повідомлення,Съобщение -Customize Chat Controls,CNTRLMNU_CHAT_TITLE,,,,Nastavení ovládání chatu,Tilpas chat-kontrollerne,Chat-Steuerung einstellen,,Adapti babilajn regilojn,Cambiar controles de chat,,Keskusteluohjausasetukset,Changer Contrôles Chat,Chatbeállítások testreszabása,Personalizza i controlli della chat,チャット操作設定,사용자 지정 채팅 컨트롤,Chat-controles aanpassen aan uw wensen,Tilpass chattekontroller,Ustaw Klawisze Czatu,Personalizar comandos do bate-papo,Configurar Controlos de Chat,Personalizare control scriere,Клавиши управления чатом,Контроле ћаскања,Sohbet Kontrollerini Özelleştirme,Клавіші керування чатом,Персонализиране на контролите за чата -Customize Weapon Controls,CNTRLMNU_WEAPONS_TITLE,,,,Nastavení ovládání zbraní,Tilpas våbenkontroller,Waffen-Steuerung einstellen,,Adapti armilojn regilojn,Cambiar controles de armas,,Aseohjausasetukset,Changer Contrôles Armes,Fegyverbeállítások testreszabása,Personalizza i controlli delle armi,武器操作設定,사용자 지정 무기 컨트롤,Wapencontroles aanpassen aan uw eigen wensen,Tilpass våpenkontroller,Ustaw Klawisze Broni,Personalizar comandos de arma,Configurar Controlos de Armas,Personalizare control arme,Клавиши управления оружием,Контроле оружја,Silah Kontrollerini Özelleştirme,Клавіші керування зброєю,Персонализиране на контролите за оръжия -Customize Inventory Controls,CNTRLMNU_INVENTORY_TITLE,,,,Nastavení ovládání inventáře,Tilpas kontrol af inventar,Inventar-Steuerung einstellen,,Adapti inventarajn regilojn,Cambiar controles de inventario,,Varusteohjausasetukset,Changer Contrôles Inventaires,Eszköztár beállítások testreszabása,Personalizza i controlli dell'inventario,インベントリ操作設定,사용자 지정 인벤토리 컨트롤,Inventariscontroles aanpassen aan uw wensen,Tilpass beholdningskontroller,Ustaw Klawisze Ekwipunku,Personalizar comandos do inventário,Configurar Controlos de Inventário,Personalizare control inventar,Клавиши управления инвентарём,Контроле складишта,Envanter Kontrollerini Özelleştirme,Клавіші керування інвентарем,Персонализиране на контролите за инвентара -Customize Other Controls,CNTRLMNU_OTHER_TITLE,,,,Nastavení ostatních ovládání,Tilpas andre kontrolelementer,Sonstige Steuerung einstellen,,Adapti ekstrajn regilojn,Cambiar otros controles,,Muut ohjausasetukset,Changer Autres Contrôles,Egyéb irányítás testreszabása,Personalizza altri controlli,その他の操作設定,사용자 지정 그 외 컨트롤,Andere bedieningselementen aanpassen,Tilpass andre kontroller,Ustaw Inne Klawisze,Personalizar outros comandos,Configurar Outros Controlos,Personalizare scheme de control diverse,Прочие клавиши,Друге контроле,Diğer Kontrolleri Özelleştirme,Інші клавіші,Персонализиране на други контроли -Weapons,CNTRLMNU_WEAPONS,,,,Zbraně,Våben,Waffen,Όπλα,Armiloj,Armas,,Aseet,Armes,Fegyverek,Armi,武器,무기,Wapens,Våpen,Bronie,Armas,,Arme,Оружие,Оружје,Silahlar,Зброя,Оръжия -Next weapon,CNTRLMNU_NEXTWEAPON,,,,Další zbraň,Næste våben,Nächste Waffe,Επόμενο όπλο,Sekva armilo,Arma siguiente,,Seuraava ase,Arme Suivante,Következő fegyver,Arma successiva,次の武器,다음 무기,Volgende wapen,Neste våpen,Następna broń,Arma seguinte,,Arma următoare,Следующее оружие,Следеће оружје,Sonraki silah,Наступна зброя,Следващо оръжие -Previous weapon,CNTRLMNU_PREVIOUSWEAPON,,,,Předchozí zbraň,Forrige våben,Vorherige Waffe,Προηγούμενο όπλο,Antaŭa armilo,Arma anterior,,Edellinen ase,Arme Précédente,Előző fegyver,Arma precedente,前の武器,이전 무기,Vorige wapen,Forrige våpen,Poprzednia broń,Arma anterior,,Arma anterioară,Предыдущее оружие,Претходно оружје,Önceki silah,Попередня зброя,Предишно оръжие -Weapon 1,CNTRLMNU_SLOT1,Todo - make game specific,,,Slot zbraně 1,Våben 1,Waffe 1,Όπλο 1,Armilo 1,Arma 1,,Aselokero 1,Emplacement D'Arme 1,1. fegyver,Slot arma 1,武器スロット 1,무기 슬롯 1,Wapenslot 1,Våpen 1,Broń 1,Arma 1,,Arma 1,Первое оружие,Оружје 1,Silah 1,Зброя 1,Оръжие 1 +",左を向く,왼쪽으로 회전,Draai naar links,Sving til venstre,Obróć się w lewo,Girar para a esquerda,,Întoarcere stânga,Поворот налево,Окрени се лево,Sväng vänster,Sola dön,Повернутись ліворуч,Обръщане в ляво +Turn right,CNTRLMNU_TURNRIGHT,,,,Otočení vpravo,Drej til højre,Nach rechts drehen,Γύρνα δεξιά,Turni dekstren,Girar a la derecha,,Käänny oikealle,Tourner à Droite,Jobbra fordul,Gira a destra,右を向く,오른쪽으로 회전,Draai naar rechts,Sving til høyre,Obróć się w prawo,Girar para a direita,,Întoarcere dreapta,Поворот направо,Окрени се десно,Sväng höger,Sağa dön,Повернутись праворуч,Обръщане в дясно +Quick Turn,CNTRLMNU_TURN180,,,,Rychlé otočení,Hurtig drejning,Schnelle Drehung,Γρήγορη γύριση,Rapida turno,Giro rápido,,Pikakäännös,Faire un 180,Megfordulás,Rotazione rapida,背後を向く,빠른 회전,Snelle draai,Rask sving,Szybki Obrót,Giro rápido,,Întoarcere rapidă,Быстрый разворот,Брзи окрет,Snabb vändning,Hızlı Dönüş,Швидкий розворот,Бързо обръщане +Jump,CNTRLMNU_JUMP,,,,Skok,Hop,Springen,Πήδα,Salti,Saltar,,Hyppää,Sauter,Ugrás,Salto,ジャンプ,점프,Springen,Hopp,Skok,Pular,Saltar,Salt,Прыжок,Скок,Hoppa,Atlama,Стрибок,Скок +Crouch,CNTRLMNU_CROUCH,,,,Kleknutí,Kryb,Ducken,Σκύψιμο,Kaŭri,Agacharse,,Kyyristy,S'accroupir (tenir),Guggolás,Abbassarsi,屈む,숙이기,Hurken,Huk,Kucnięcie,Agachar,,Ghemuire,Присесть,Чучни,Huk,Çömelme,Присісти,Клякане +Crouch Toggle,CNTRLMNU_TOGGLECROUCH,,,,Přepnout kleknutí,Krybbe omskifter,Ducken an/aus,Εναλλαγή σκύψιμο,Kaŭrobaskuli,Alternar agachado,,Kyyristymisen vaihtokytkin,S'accroupir (alterner),Guggolási kapcsoló,Attivare/disattivare abbassamento,屈む切替,숙이기 토글,Hurken Toggle,,Przełącz kucnięcie,Agachar (alternar),,Comutator ghemuire,Присесть/встать,Чучни (без држања),Växla huk,Çömelme anahtarı,Сісти/встати,Клякане постоянно +Mouse look,CNTRLMNU_MOUSELOOK,,,,Pohled myší,Musens udseende,Maus-Blick,Κοίτα με το ποντίκι,Musrigardo,Vista con ratón,,Hiirikatselu,Vue à la souris,Egérrel való nézelődés,Modalità vista col mouse,マウス視点上下化,마우스 룩,Muis-look,Museblikk,Rozglądanie się myszką,Visão com o mouse,Vista com o rato,Privire în jur cu mouse,Обзор мышью,Гледај мишем,Musens utseende,Fare bakışı,Огляд мишкою,Поглед с мишката +Look up,CNTRLMNU_LOOKUP,Look doesn't change the aim! It only alters the view pitch,,,Pohled vzhůru,Se op,Nach oben schauen,Κοίτα απάνω,Rigardi supren,Mirar arriba,,Katso ylös,Regarder en haut,Felfele nézés,Guarda sopra,視点を上げる,위로 보기,Kijk omhoog,Se opp,Patrz w górę,Olhar para cima,,Privire în sus,Смотреть вверх,Гледај горе,Titta uppåt,Yukarı bak.,Подивитись вверх,Поглед нагоре +Look down,CNTRLMNU_LOOKDOWN,,,,Pohled dolů,Se nedad,Nach unten schauen,Κοίτα κάτω,Rigardi malsupren,Mirar abajo,,Katso alas,Regarder en bas,Lefele nézés,Guarda sotto,視点を下げる,아래로 보기,Kijk naar beneden,Se nedover,Patrz w dół,Olhar para baixo,,Privire în jos,Смотреть вниз,Гледај доле,Titta ner,Aşağı bak.,Подивитись вниз,Поглед надолу +Center view,CNTRLMNU_CENTERVIEW,,,Centre view,Vystředit pohled,Centreret visning,Ansicht zentrieren,Προβολή στο κέντρο,Centrigi vidon,Centrar vista,,Keskitä katse,Recentrer Vue,Nézet középreigazítása,Sguardo centrato,視点を戻す,중앙 시점으로 보기,Middenaanzicht,Midtstilt visning,Wyśrodkuj widok,Olhar para o centro,,Centrare privire,Отцентрировать взгляд,Централизирај поглед,Centrerad vy,Merkezden görünüm,Центрувати погляд,Центриране на погледа +Run,CNTRLMNU_RUN,,,,Běh,Kør,Rennen,Τρέχα,Kuri,Correr,,Juokse,Courir (tenir),Futás,Corri,駆け足,달리기,Rennen,Kjør,Bieg,Correr,,Fugă,Бежать,Трчи,Spring,Koşmak,Біг,Бягане +Toggle Run,CNTRLMNU_TOGGLERUN,,,,Přepnout běh,Skift Kør,Rennen an/aus,Ενεργοποίηση τρέξιμου,Baskuligi kuron,Alternar «Correr»,,Juoksun vaihtokytkin,Courir (alterner),Futás kapcsoló,Abilita/disabilita corsa,常時駆け足切替,달리기 토글,Rennen aan/uit,Veksle Kjør,Przełącz bieg,Correr (alternar),,Comutator fugă,Бежать/идти,Трчи (без држања),Växla springa,Değiştir Çalıştır,Бігти / ходити,Бягане постоянно +Strafe,CNTRLMNU_STRAFE,,,,Pohyb do stran,Strafe,Seitwärts,,Flankmovi,Desplazamiento,,Astu sivuttain,Pas de côté,Oldalazás,Spostamento laterale,横移動化,양옆으로 이동,Zijdelings bewegen,,Uniki,Deslocamento lateral,,Deplasare în diagonală,Движение боком,Кретање у страну,Strafe,,Рухатись боком,Странично движение +Show Scoreboard,CNTRLMNU_SCOREBOARD,,,,Zobrazit tabulku skóre,Vis resultattavle,Punktetafel anzeigen,Εμφάνιση πίνακα αποτελεσμάτων,Montri poentotabulon,Mostrar marcador,,Näytä pistetaulu,Afficher Scores (tenir),Eredményjelző megjelenítése,Mostra la tabella punteggio,スコアボード表示,점수창 표시,Scorebord tonen,Vis resultattavle,Pokaż tablicę wyników,Exibir placar,,Afișare tabelă de marcaj,Таблица очков,Табела,Visa resultattavlan,Skor Tablosunu Göster,Таблиця лідерів,Покажи резултати +Action,CNTRLMNU_ACTION,,,,Akce,Handling,Aktion,Δράσεις,Ago,Acción,,Toiminta,,Akció,Azione,アクション,동작,Actie,Handling,Akcja,Ação,,Acțiuni,Основное,Радња,Åtgärd,Eylem,Дії,Действие +Customize Action Controls,CNTRLMNU_ACTION_TITLE,,,,Nastavení ovládání akcí,Tilpas handlingskontroller,Aktions-Steuerung einstellen,Προσαρμογή των χειριστηρίων δράσης,Adapti agajn regilojn,Cambiar controles de acción,,Toimintaohjausasetukset,Changer Contrôles Action,Akció beállítások testreszabása,Personalizza i controlli di azione,アクション操作設定,사용자 지정 동작 컨트롤,Aanpassen van de actiecontroles,Tilpass handlingskontroller,Ustaw Klawisze Akcji,Personalizar comandos de ação,Configurar Controlos de Ação,Personalizare schemă acțiuni,Основные клавиши управления,Контроле радње,Anpassa kontrollerna för åtgärder,Eylem Kontrollerini Özelleştirme,Налаштування елементів дій,Персонализиране на контролите за действие +Chat,CNTRLMNU_CHAT,,,,,,,Μίλα,Babili,,,Keskustelu,,,,チャット,채팅,,,Czat,Bate-papo,Conversar,Conversație,Чат,Ћаскање,Chatt,Sohbet,Чат,Чат +Multiplayer,MNU_MULTIPLAYER,,,,,,Mehrspieler,,Plurludanta,Multijugador,,Moninpeli,Multijoueur,Többjátékos,Multigiocatore,マルチプレイヤー,,,Flerspiller,Tryb Wieloosobowy,Multijogador,,Joc Online,Сетевая игра,,Flera spelare,Çok Oyunculu,Гра в мережі,Онлайн игра +Say,CNTRLMNU_SAY,,,,Říct,Sig,Reden,Πές,Diri,Hablar,,Sano,Parler,Üzenet ,Parla,発言,채팅하기,Zeg,Si,Powiedz,Dizer,,Vorbește,Сообщение,Пиши,Säg,Söyle,Написати повідомлення,Съобщение +Customize Chat Controls,CNTRLMNU_CHAT_TITLE,,,,Nastavení ovládání chatu,Tilpas chat-kontrollerne,Chat-Steuerung einstellen,Προσαρμογή ελέγχου συνομιλίας,Adapti babilajn regilojn,Cambiar controles de chat,,Keskusteluohjausasetukset,Changer Contrôles Chat,Chatbeállítások testreszabása,Personalizza i controlli della chat,チャット操作設定,사용자 지정 채팅 컨트롤,Chat-controles aanpassen aan uw wensen,Tilpass chattekontroller,Ustaw Klawisze Czatu,Personalizar comandos do bate-papo,Configurar Controlos de Chat,Personalizare control scriere,Клавиши управления чатом,Контроле ћаскања,Anpassa kontrollerna för chatt,Sohbet Kontrollerini Özelleştirme,Клавіші керування чатом,Персонализиране на контролите за чата +Customize Weapon Controls,CNTRLMNU_WEAPONS_TITLE,,,,Nastavení ovládání zbraní,Tilpas våbenkontroller,Waffen-Steuerung einstellen,Προσαρμογή ελέγχου όπλων,Adapti armilojn regilojn,Cambiar controles de armas,,Aseohjausasetukset,Changer Contrôles Armes,Fegyverbeállítások testreszabása,Personalizza i controlli delle armi,武器操作設定,사용자 지정 무기 컨트롤,Wapencontroles aanpassen aan uw eigen wensen,Tilpass våpenkontroller,Ustaw Klawisze Broni,Personalizar comandos de arma,Configurar Controlos de Armas,Personalizare control arme,Клавиши управления оружием,Контроле оружја,Anpassa vapenkontroller,Silah Kontrollerini Özelleştirme,Клавіші керування зброєю,Персонализиране на контролите за оръжия +Customize Inventory Controls,CNTRLMNU_INVENTORY_TITLE,,,,Nastavení ovládání inventáře,Tilpas kontrol af inventar,Inventar-Steuerung einstellen,Προσαρμογή Ελέγχου Απογραφής,Adapti inventarajn regilojn,Cambiar controles de inventario,,Varusteohjausasetukset,Changer Contrôles Inventaires,Eszköztár beállítások testreszabása,Personalizza i controlli dell'inventario,インベントリ操作設定,사용자 지정 인벤토리 컨트롤,Inventariscontroles aanpassen aan uw wensen,Tilpass beholdningskontroller,Ustaw Klawisze Ekwipunku,Personalizar comandos do inventário,Configurar Controlos de Inventário,Personalizare control inventar,Клавиши управления инвентарём,Контроле складишта,Anpassa kontrollerna för inventarier,Envanter Kontrollerini Özelleştirme,Клавіші керування інвентарем,Персонализиране на контролите за инвентара +Customize Other Controls,CNTRLMNU_OTHER_TITLE,,,,Nastavení ostatních ovládání,Tilpas andre kontrolelementer,Sonstige Steuerung einstellen,Προσαρμογή άλλων ελέγχων,Adapti ekstrajn regilojn,Cambiar otros controles,,Muut ohjausasetukset,Changer Autres Contrôles,Egyéb irányítás testreszabása,Personalizza altri controlli,その他の操作設定,사용자 지정 그 외 컨트롤,Andere bedieningselementen aanpassen,Tilpass andre kontroller,Ustaw Inne Klawisze,Personalizar outros comandos,Configurar Outros Controlos,Personalizare scheme de control diverse,Прочие клавиши,Друге контроле,Anpassa andra kontroller,Diğer Kontrolleri Özelleştirme,Інші клавіші,Персонализиране на други контроли +Weapons,CNTRLMNU_WEAPONS,,,,Zbraně,Våben,Waffen,Όπλα,Armiloj,Armas,,Aseet,Armes,Fegyverek,Armi,武器,무기,Wapens,Våpen,Bronie,Armas,,Arme,Оружие,Оружје,Vapen,Silahlar,Зброя,Оръжия +Next weapon,CNTRLMNU_NEXTWEAPON,,,,Další zbraň,Næste våben,Nächste Waffe,Επόμενο όπλο,Sekva armilo,Arma siguiente,,Seuraava ase,Arme Suivante,Következő fegyver,Arma successiva,次の武器,다음 무기,Volgende wapen,Neste våpen,Następna broń,Arma seguinte,,Arma următoare,Следующее оружие,Следеће оружје,Nästa vapen,Sonraki silah,Наступна зброя,Следващо оръжие +Previous weapon,CNTRLMNU_PREVIOUSWEAPON,,,,Předchozí zbraň,Forrige våben,Vorherige Waffe,Προηγούμενο όπλο,Antaŭa armilo,Arma anterior,,Edellinen ase,Arme Précédente,Előző fegyver,Arma precedente,前の武器,이전 무기,Vorige wapen,Forrige våpen,Poprzednia broń,Arma anterior,,Arma anterioară,Предыдущее оружие,Претходно оружје,Föregående vapen,Önceki silah,Попередня зброя,Предишно оръжие +Weapon 1,CNTRLMNU_SLOT1,Todo - make game specific,,,Slot zbraně 1,Våben 1,Waffe 1,Όπλο 1,Armilo 1,Arma 1,,Aselokero 1,Emplacement D'Arme 1,1. fegyver,Slot arma 1,武器スロット 1,무기 슬롯 1,Wapenslot 1,Våpen 1,Broń 1,Arma 1,,Arma 1,Первое оружие,Оружје 1,Vapen 1,Silah 1,Зброя 1,Оръжие 1 Weapon 2,CNTRLMNU_SLOT2,"only show appropriate slots per game -",,,Slot zbraně 2,Våben 2,Waffe 2,Όπλο 2,Armilo 2,Arma 2,,Aselokero 2,Emplacement D'Arme 2,2. fegyver,Slot arma 2,武器スロット 2,무기 슬롯 2,Wapenslot 2,Våpen 2,Broń 2,Arma 2,,Arma 2,Второе оружие,Оружје 2,Silah 2,Зброя 2,Оръжие 2 -Weapon 3,CNTRLMNU_SLOT3,,,,Slot zbraně 3,Våben 3,Waffe 3,Όπλο 3,Armilo 3,Arma 3,,Aselokero 3,Emplacement D'Arme 3,3. fegyver,Slot arma 3,武器スロット 3,무기 슬롯 3,Wapenslot 3,Våpen 3,Broń 3,Arma 3,,Arma 3,Третье оружие,Оружје 3,Silah 3,Зброя 3,Оръжие 3 -Weapon 4,CNTRLMNU_SLOT4,,,,Slot zbraně 4,Våben 4,Waffe 4,Όπλο 4,Armilo 4,Arma 4,,Aselokero 4,Emplacement D'Arme 4,4. fegyver,Slot arma 4,武器スロット 4,무기 슬롯 4,Wapenslot 4,Våpen 4,Broń 4,Arma 4,,Arma 4,Четвёртое оружие,Оружје 4,Silah 4,Зброя 4,Оръжие 4 -Weapon 5,CNTRLMNU_SLOT5,,,,Slot zbraně 5,Våben 5,Waffe 5,Όπλο 5,Armilo 5,Arma 5,,Aselokero 5,Emplacement D'Arme 5,5. fegyver,Slot arma 5,武器スロット 5,무기 슬롯 5,Wapenslot 5,Våpen 5,Broń 5,Arma 5,,Arma 5,Пятое оружие,Оружје 5,Silah 5,Зброя 5,Оръжие 5 -Weapon 6,CNTRLMNU_SLOT6,,,,Slot zbraně 6,Våben 6,Waffe 6,Όπλο 6,Armilo 6,Arma 6,,Aselokero 6,Emplacement D'Arme 6,6. fegyver,Slot arma 6,武器スロット 6,무기 슬롯 6,Wapenslot 6,Våpen 6,Broń 6,Arma 6,,Arma 6,Шестое оружие,Оружје 6,Silah 6,Зброя 6,Оръжие 6 -Weapon 7,CNTRLMNU_SLOT7,,,,Slot zbraně 7,Våben 7,Waffe 7,Όπλο 7,Armilo 7,Arma 7,,Aselokero 7,Emplacement D'Arme 7,7. fegyver,Slot arma 7,武器スロット 7,무기 슬롯 7,Wapenslot 7,Våpen 7,Broń 7,Arma 7,,Arma 7,Седьмое оружие,Оружје 7,Silah 7,Зброя 7,Оръжие 7 -Weapon 8,CNTRLMNU_SLOT8,,,,Slot zbraně 8,Våben 8,Waffe 8,Όπλο 8,Armilo 8,Arma 8,,Aselokero 8,Emplacement D'Arme 8,8. fegyver,Slot arma 8,武器スロット 8,무기 슬롯 8,Wapenslot 8,Våpen 8,Broń 8,Arma 8,,Arma 8,Восьмое оружие,Оружје 8,Silah 8,Зброя 8,Оръжие 8 -Weapon 9,CNTRLMNU_SLOT9,,,,Slot zbraně 9,Våben 9,Waffe 9,Όπλο 9,Armilo 9,Arma 9,,Aselokero 9,Emplacement D'Arme 9,9. fegyver,Slot arma 9,武器スロット 9,무기 슬롯 9,Wapenslot 9,Våpen 9,Broń 9,Arma 9,,Arma 9,Девятое оружие,Оружје 9,Silah 9,Зброя 9,Оръжие 9 -Weapon 10,CNTRLMNU_SLOT0,,,,Slot zbraně 10,Våben 10,Waffe 10,Όπλο 0,Armilo 10,Arma 10,,Aselokero 0,Emplacement D'Arme 0,0. fegyver,Slot arma 0,武器スロット 0,무기 슬롯 0,Wapenslot 0,Våpen 10,Broń 10,Arma 10,,Arma 0,Десятое оружие,Оружје 0,Silah 10,Зброя 0,Оръжие 10 -Inventory,CNTRLMNU_INVENTORY,,,,Inventář,Inventar,Inventar,Άντικείμενα,Inventaro,Inventario,,Varusteet,Inventaire,Eszköztár beállítások testreszabása,Inventario,所持品,인벤토리,Inventaris,Inventar,Ekwipunek,Inventário,,Inventar,Инвентарь,Инвентар,Envanter,Інвентар,Инвентар -Activate item,CNTRLMNU_USEITEM,,,,Aktivovat předmět,Aktiver genstand,Gegenstand aktivieren,Ενεργοποίηση αντικείμενου,Aktivigi objekton,Activar objeto,,Aktivoi varuste,Activer objet,Eszköz használata,Attiva oggetto,アイテムを使用,선택한 아이템 사용,Item activeren,Aktiver gjenstand,Użyj przedmiot,Ativar item,,Activează obiectul,Использовать предмет,Активирај предмет,Öğeyi etkinleştir,Активувати предмет,Използвай предмета -Activate all items,CNTRLMNU_USEALLITEMS,,,,Aktivovat všechny předměty,Aktivering af alle genstande,Alle Gegenstände aktivieren,Ενεργοποίησε όλα τα αντικείμενα,Aktivigi ĉiujn objektojn,Activar todos los objetos,,Aktivoi kaikki varusteet,Activer tous les objets,Minden eszköz használata,Attiva tutti gli oggetti,全てのアイテムを使用,모든 아이템 사용,Activeer alle items,Aktiver alle gjenstander,Użyj wszystkie przedmioty,Ativar todos os itens,,Activează tot inventarul,Использовать все предметы,Активирај све предмете,Tüm öğeleri etkinleştirin,Активувати усі предмети,Използвай всички предмети -Next item,CNTRLMNU_NEXTITEM,,,,Další předmět,Næste genstand,Nächster Gegenstand,Επόμενο αντικείμενο,Sekva objekto,Objeto siguiente,,Seuraava varuste,Objet suivant,Következő eszköz,Oggetto successivo,次のアイテム,다음 아이템,Volgende item,Neste element,Następny przedmiot,Item seguinte,,Următorul obiect,Следующий предмет,Следећи предмет,Sonraki madde,Наступний предмет,Следващ предмет -Previous item,CNTRLMNU_PREVIOUSITEM,,,,Předchozí předmět,Forrige genstand,Vorheriger Gegenstand,Προηγούμενο αντικείμενο,Antaŭa objekto,Objeto anterior,,Edellinen varuste,Objet précédent,Előző eszköz,Oggetto precedente,前のアイテム,이전 아이템,Vorige item,Forrige element,Poprzedni przedmiot,Item anterior,,Obiect anterior,Предыдущий предмет,Претходни предмет,Önceki madde,Попередній предмет,Предишен предмет -Customize Map Controls,MAPCNTRLMNU_TITLE,most are not used yet but will be,,,Nastavení ovládání mapy,Tilpas kontrolelementer til kortet,Automapsteuerung einstellen,,Adapti map-regilojn,Cambiar controles del mapa,,Kartanohjausasetukset,Contrôles Carte,Térkép irányításának testreszabása,Personalizza i controlli mappa,マップコントロール カスタマイズ,미니맵 단축키 설정,Kaartcontroles aanpassen,Tilpass kartkontroller,Ustaw klawisze mapy,Peronalizar comandos do mapa,,Personalizare schemă de control a hărții,Клавиши управления автокартой,Промени контроле мапе,Harita Kontrollerini Özelleştirme,Клавіші керування автокартою,Персонализиране контролите за картата -Map Controls,MAPCNTRLMNU_CONTROLS,,,,Mapa,Kontrolelementer til kort,Automapsteuerung,,Map-regiloj,Controles del mapa,,Kartanohjaus,Contrôles de la carte,Térkép irányítása,Controlli mappa,マップコントロール,미니맵 조정,Kaartcontroles,Kartkontroller,Klawisze mapy,Comandos do mapa,,Schemă de control a hărtii,Автокарта,Контроле мапе,Harita Kontrolleri,Автокарта,Контроли за карта -Pan left,MAPCNTRLMNU_PANLEFT,,,,Doleva,Panorere til venstre,Nach links,,Alturni maldekstren,Mover a la izquierda,,Panoroi vasemmalle,Aller à gauche,Balra igazítás,Sposta a sinistra,左に振る,왼쪽으로 이동,Pan links,Panorer til venstre,Przesuń w lewo,Mover para a esquerda,,Mutare spre stânga,Сдвиг влево,Лево,Sola kaydırın,Зсув вліво,Преместване наляво -Pan right,MAPCNTRLMNU_PANRIGHT,,,,Doprava,Panorering til højre,Nach rechts,,Alturni dekstren,Mover a la derecha,,Panoroi oikealle,Aller à droite,Jobbra igazítás,Sposta a destra,右に振る,오른쪽으로 이동,Pan rechts,Panorer til høyre,Przesuń w prawo,Mover para a direita,,Mutare spre dreapta,Сдвиг вправо,Десно,Sağa kaydırın,Зсув вправо,Преместване на дясно -Pan up,MAPCNTRLMNU_PANUP,,,,Nahoru,Panorere op,Nach oben,,Alturni supren,Mover hacia arriba,,Panoroi ylös,Aller en haut,Felfele igazítás,Sposta sopra,上に振る,위쪽으로 이동,Pan omhoog,Panorer opp,Przesuń w górę,Mover para cima,,Mutare în sus,Сдвиг вверх,Горе,Yukarı kaydırın,Зсув вверх,Преместване на горе -Pan down,MAPCNTRLMNU_PANDOWN,,,,Dolů,Panorere ned,Nach unten,,Alturni malsupren,Mover hacia abajo,,Panoroi alas,Aller en bas,Lefele igazítás,Sposta sotto,下に振る,아래쪽으로 이동,Pan neer,Panorer ned,Przesuń w dół,Mover para baixo,,Mutare în jos,Сдвиг вниз,Доле,Aşağı kaydırın,Зсув вниз,Преместване на долу -Zoom in,MAPCNTRLMNU_ZOOMIN,,,,Přiblížit,Zoom ind,Reinzoomen,,Zomi,Acercar,,Lähennä,Zoom avant,Ráközelítés,Ingrandisci,ズームイン,줌 확대,Inzoomen,Zoom inn,Przybliż,Ampliar,,Apropriere Cameră,Приблизить,Увеличати,Yakınlaştır,Наблизити,Приближи -Zoom out,MAPCNTRLMNU_ZOOMOUT,,,,Oddálit,Zoom ud,Rauszoomen,,Malzomi,Alejar,,Loitonna,Zoom arrière,Távolítás,Rimpicciolisci,ズームアウト,줌 축소,Uitzoomen,Zoom ut,Oddal,Afastar,,Depărtare Cameră,Отдалить,Одзумирати,Uzaklaştır,Віддалити,Отдалечи -Toggle zoom,MAPCNTRLMNU_TOGGLEZOOM,,,,Přiblížení vyp./zap.,Skift mellem zoom,Zoom an/aus,,Baskuligi zomon,Alternar zoom,,Zoomauksen vaihtokytkin,Alterner zoom,Közelítés átkapcsolása,Abilita/disabilita zoom,ズーム切替,표준배율 조정,Omschakelen van de zoom,Veksle mellom zoom,Przełącz przybliżanie,Ativar/desativar zoom,,Comutator Zoom,Приближение (перекл.),Укључи зум,Yakınlaştırmayı aç / kapat,Перемикач наближення,Приближи постоянно -Toggle follow,MAPCNTRLMNU_TOGGLEFOLLOW,,,,Sledování hráče vyp./zap.,Skift følge,Folgen an/aus,,Baskuligi sekvon,Alternar seguimiento,,Seuraamistilan vaihtokytkin,Alterner suivi,Követés átkapcsolása,Abilita/disabilita scorrimento mappa,追従切替,추적모드 조정,Schakelen volgen,Veksle følge,Przełącz śledzenie,Ativar/desativar seguimento,,Comutator urmărire jucător,Привязка к игроку (перекл.),Укључи праћење,Takip etmeyi değiştir,Перемикач слідування за гравцем,Следвай постаянно -Toggle grid,MAPCNTRLMNU_TOGGLEGRID,,,,Mřížka vyp./zap.,Skift gitter,Gitter an/aus,,Baskuligi kradon,Alternar cuadrícula,,Ruudukon vaihtokytkin,Alterner grille,Rács kapcsolása,Abilita/disabilita la griglia,グリッド切替,그리드 조정,Kiesnet,Veksle rutenett,Przełącz siatkę,Ativar/desativar grade,,Comutator grilă,Сетка (перекл.),Укључи координатну мрежу,Izgarayı değiştir,Перемикач сітки,Включи координатна мрежа -Toggle rotate,MAPCNTRLMNU_ROTATE,,,,Otáčení vyp./zap.,Skift til rotere,Rotation an/aus,,Baskuligi turnadon,Alternar rotación,,Kääntämisen vaihtokytkin,Alterner rotation,Forgás kapcsolása,Abilita/disabilita la rotazione,回転切替,,Toggle rotatie,Veksle mellom rotasjon,Przełącz obracanie,Ativar/desativar rotação,,Comutator rotire,Вращение (перекл.),Укључи ротацију,Döndürmeyi değiştir,Перемикач обертання,Завъртане (превключване) -Toggle texture,MAPCNTRLMNU_TOGGLETEXTURE,,,,Textury vyp./zap.,Skift tekstur,Texturen an/aus,,Baskuligi teksturon,Alternar textura,,Pintakuvioinnin vaihtokytkin,Alterner texture,Textúra kapcsolása,Abilita/disabilita le texture,テクスチャ切替,미니맵 텍스쳐 조정,Toggle textuur,Veksle tekstur,Przełącz tekstury,Ativar/desativar texturas,,Comutator mod texturat,Текстуры (перекл.),Укључи текстуру,Dokuyu değiştir,Перемикач текстур, -Toggle automap,CNTRLMNU_AUTOMAP,,,,Otevřít/zavřít automapu,Skift til automap,Automap an/aus,,Baskuligi aŭtomapo,Alternar automapa,,Kytke automaattikartta päälle/pois,Activer Carte,Térkép ki/bekapcsolása,Abilita/disabilita l'automappa,オートマップの切替,오토맵 조정,Automap aan/uit,Veksle mellom automap,Włącz mapę,Ativar/desativar automapa,,Comutator hartă computerizată,Автокарта (перекл.),Прикажи аутомапу,Otomatik haritayı değiştir,Перемикач автокарти, -Chasecam,CNTRLMNU_CHASECAM,,,,Kamera z třetí osoby,Chasecam,Verfolgerkamera,,Ĉaskamerao,Cámara de seguimiento,,Seurantakamera,Caméra 3ième personne,Külsőnézetű kamera,Telecamera di inseguimento,背後視点,3인칭 카메라,,,Kamera Śledzenia,Câmera em terceira pessoa,Câmera em terceira-pessoa,Cameră urmăritoare,Вид от 3-го лица,Чејс-кем,Chasecam,Вид від 3-го лиця, -Screenshot,CNTRLMNU_SCREENSHOT,,,,Pořídit snímek obrazovky,Skærmbillede,,,Ekrankopio,Captura de pantalla,,Kuvakaappaus,Capture d'écran,Képernyő lefényképezése,Cattura schermo,画面キャプチャ,스크린샷,,Skjermbilde,Zrzut ekranu,Captura de tela,,Captură ecran,Снимок экрана,Усликај,Ekran görüntüsü,Скріншот, -Open console,CNTRLMNU_CONSOLE,,,,Otevřít konzoli,Åbn konsollen,Konsole öffnen,,Malfermi konzolon,Abrir consola,,Avaa konsoli,Ouvrir Console,Konzol megnyitása,Apri la console,コンソールを開く,콘솔 열기,Open console,Åpne konsoll,Otwórz konsolę,Abrir console,Abrir consola,Deschide consola,Открыть консоль,Отвори консолу,Açık konsol,Відкрити консоль, -Pause,CNTRLMNU_PAUSE,,,,Pauza,Pause,,Πάυση,Paŭzo,Pausa,,Tauko,,Szünet,Pausa,ポーズ,일시정지,Pauze,Pause,Pauza,Pausar,,Pauză,Пауза,Пауза,Duraklat,Пауза, -Increase Display Size,CNTRLMNU_DISPLAY_INC,,,,Zvětšit velikost obrazovky,Forøg visningsstørrelsen,Anzeige vergrößern,,Kreskigi ekrangrandon,Agrandar ventana,,Suurenna näytön kokoa,Agrandir l'affichage,Képméret növelése,Aumenta la dimensione del display,画面サイズを拡大,화면 크기 늘리기,Vergroot het display,Øk visningsstørrelse,Powiększ Rozmiar Wyświetlania,Aumentar tamanho da exibição,Aumentar Tamanho do Ecrã,Mărire ecran,Увеличить размер экрана,Повећајте величину екрана,Ekran Boyutunu Artırın,Збільшити розмір екрану, -Decrease Display Size,CNTRLMNU_DISPLAY_DEC,,,,Zmenšit velikost obrazovky,Formindsk skærmstørrelse,Anzeige verkleinern,,Malkreskigi ekrangrandon,Reducir ventana,,Pienennä näytön kokoa,Réduire l'affichage,Képméret csökkentése,Riduci la dimensione del display,画面サイズを縮小,화면 크기 줄이기,Verlaag het display,Reduser visningsstørrelse,Pomniejsz Rozmiar Wyświetlania,Reduzir tamanho da exibição,Diminuir Tamanho do Ecrã,Micșorare ecran,Уменьшить размер экрана,Смањите величину екрана,Ekran Boyutunu Azaltma,Зменшити розмір екрану, +",,,Slot zbraně 2,Våben 2,Waffe 2,Όπλο 2,Armilo 2,Arma 2,,Aselokero 2,Emplacement D'Arme 2,2. fegyver,Slot arma 2,武器スロット 2,무기 슬롯 2,Wapenslot 2,Våpen 2,Broń 2,Arma 2,,Arma 2,Второе оружие,Оружје 2,Vapen 2,Silah 2,Зброя 2,Оръжие 2 +Weapon 3,CNTRLMNU_SLOT3,,,,Slot zbraně 3,Våben 3,Waffe 3,Όπλο 3,Armilo 3,Arma 3,,Aselokero 3,Emplacement D'Arme 3,3. fegyver,Slot arma 3,武器スロット 3,무기 슬롯 3,Wapenslot 3,Våpen 3,Broń 3,Arma 3,,Arma 3,Третье оружие,Оружје 3,Vapen 3,Silah 3,Зброя 3,Оръжие 3 +Weapon 4,CNTRLMNU_SLOT4,,,,Slot zbraně 4,Våben 4,Waffe 4,Όπλο 4,Armilo 4,Arma 4,,Aselokero 4,Emplacement D'Arme 4,4. fegyver,Slot arma 4,武器スロット 4,무기 슬롯 4,Wapenslot 4,Våpen 4,Broń 4,Arma 4,,Arma 4,Четвёртое оружие,Оружје 4,Vapen 4,Silah 4,Зброя 4,Оръжие 4 +Weapon 5,CNTRLMNU_SLOT5,,,,Slot zbraně 5,Våben 5,Waffe 5,Όπλο 5,Armilo 5,Arma 5,,Aselokero 5,Emplacement D'Arme 5,5. fegyver,Slot arma 5,武器スロット 5,무기 슬롯 5,Wapenslot 5,Våpen 5,Broń 5,Arma 5,,Arma 5,Пятое оружие,Оружје 5,Vapen 5,Silah 5,Зброя 5,Оръжие 5 +Weapon 6,CNTRLMNU_SLOT6,,,,Slot zbraně 6,Våben 6,Waffe 6,Όπλο 6,Armilo 6,Arma 6,,Aselokero 6,Emplacement D'Arme 6,6. fegyver,Slot arma 6,武器スロット 6,무기 슬롯 6,Wapenslot 6,Våpen 6,Broń 6,Arma 6,,Arma 6,Шестое оружие,Оружје 6,Vapen 6,Silah 6,Зброя 6,Оръжие 6 +Weapon 7,CNTRLMNU_SLOT7,,,,Slot zbraně 7,Våben 7,Waffe 7,Όπλο 7,Armilo 7,Arma 7,,Aselokero 7,Emplacement D'Arme 7,7. fegyver,Slot arma 7,武器スロット 7,무기 슬롯 7,Wapenslot 7,Våpen 7,Broń 7,Arma 7,,Arma 7,Седьмое оружие,Оружје 7,Vapen 7,Silah 7,Зброя 7,Оръжие 7 +Weapon 8,CNTRLMNU_SLOT8,,,,Slot zbraně 8,Våben 8,Waffe 8,Όπλο 8,Armilo 8,Arma 8,,Aselokero 8,Emplacement D'Arme 8,8. fegyver,Slot arma 8,武器スロット 8,무기 슬롯 8,Wapenslot 8,Våpen 8,Broń 8,Arma 8,,Arma 8,Восьмое оружие,Оружје 8,Vapen 8,Silah 8,Зброя 8,Оръжие 8 +Weapon 9,CNTRLMNU_SLOT9,,,,Slot zbraně 9,Våben 9,Waffe 9,Όπλο 9,Armilo 9,Arma 9,,Aselokero 9,Emplacement D'Arme 9,9. fegyver,Slot arma 9,武器スロット 9,무기 슬롯 9,Wapenslot 9,Våpen 9,Broń 9,Arma 9,,Arma 9,Девятое оружие,Оружје 9,Vapen 9,Silah 9,Зброя 9,Оръжие 9 +Weapon 10,CNTRLMNU_SLOT0,,,,Slot zbraně 10,Våben 10,Waffe 10,Όπλο 0,Armilo 10,Arma 10,,Aselokero 0,Emplacement D'Arme 0,0. fegyver,Slot arma 0,武器スロット 0,무기 슬롯 0,Wapenslot 0,Våpen 10,Broń 10,Arma 10,,Arma 0,Десятое оружие,Оружје 0,Vapen 10,Silah 10,Зброя 0,Оръжие 10 +Inventory,CNTRLMNU_INVENTORY,,,,Inventář,Inventar,Inventar,Άντικείμενα,Inventaro,Inventario,,Varusteet,Inventaire,Eszköztár beállítások testreszabása,Inventario,所持品,인벤토리,Inventaris,Inventar,Ekwipunek,Inventário,,Inventar,Инвентарь,Инвентар,Inventarium,Envanter,Інвентар,Инвентар +Activate item,CNTRLMNU_USEITEM,,,,Aktivovat předmět,Aktiver genstand,Gegenstand aktivieren,Ενεργοποίηση αντικείμενου,Aktivigi objekton,Activar objeto,,Aktivoi varuste,Activer objet,Eszköz használata,Attiva oggetto,アイテムを使用,선택한 아이템 사용,Item activeren,Aktiver gjenstand,Użyj przedmiot,Ativar item,,Activează obiectul,Использовать предмет,Активирај предмет,Aktivera föremål,Öğeyi etkinleştir,Активувати предмет,Използвай предмета +Activate all items,CNTRLMNU_USEALLITEMS,,,,Aktivovat všechny předměty,Aktivering af alle genstande,Alle Gegenstände aktivieren,Ενεργοποίησε όλα τα αντικείμενα,Aktivigi ĉiujn objektojn,Activar todos los objetos,,Aktivoi kaikki varusteet,Activer tous les objets,Minden eszköz használata,Attiva tutti gli oggetti,全てのアイテムを使用,모든 아이템 사용,Activeer alle items,Aktiver alle gjenstander,Użyj wszystkie przedmioty,Ativar todos os itens,,Activează tot inventarul,Использовать все предметы,Активирај све предмете,Aktivera alla föremål,Tüm öğeleri etkinleştirin,Активувати усі предмети,Използвай всички предмети +Next item,CNTRLMNU_NEXTITEM,,,,Další předmět,Næste genstand,Nächster Gegenstand,Επόμενο αντικείμενο,Sekva objekto,Objeto siguiente,,Seuraava varuste,Objet suivant,Következő eszköz,Oggetto successivo,次のアイテム,다음 아이템,Volgende item,Neste element,Następny przedmiot,Item seguinte,,Următorul obiect,Следующий предмет,Следећи предмет,Nästa objekt,Sonraki madde,Наступний предмет,Следващ предмет +Previous item,CNTRLMNU_PREVIOUSITEM,,,,Předchozí předmět,Forrige genstand,Vorheriger Gegenstand,Προηγούμενο αντικείμενο,Antaŭa objekto,Objeto anterior,,Edellinen varuste,Objet précédent,Előző eszköz,Oggetto precedente,前のアイテム,이전 아이템,Vorige item,Forrige element,Poprzedni przedmiot,Item anterior,,Obiect anterior,Предыдущий предмет,Претходни предмет,Föregående objekt,Önceki madde,Попередній предмет,Предишен предмет +Customize Map Controls,MAPCNTRLMNU_TITLE,most are not used yet but will be,,,Nastavení ovládání mapy,Tilpas kontrolelementer til kortet,Automapsteuerung einstellen,Προσαρμογή στοιχείων ελέγχου χάρτη,Adapti map-regilojn,Cambiar controles del mapa,,Kartanohjausasetukset,Contrôles Carte,Térkép irányításának testreszabása,Personalizza i controlli mappa,マップコントロール カスタマイズ,미니맵 단축키 설정,Kaartcontroles aanpassen,Tilpass kartkontroller,Ustaw klawisze mapy,Peronalizar comandos do mapa,,Personalizare schemă de control a hărții,Клавиши управления автокартой,Промени контроле мапе,Anpassa kartkontroller,Harita Kontrollerini Özelleştirme,Клавіші керування автомапою,Персонализиране контролите за картата +Map Controls,MAPCNTRLMNU_CONTROLS,,,,Mapa,Kontrolelementer til kort,Automapsteuerung,Έλεγχοι χάρτη,Map-regiloj,Controles del mapa,,Kartanohjaus,Contrôles de la carte,Térkép irányítása,Controlli mappa,マップコントロール,미니맵 조정,Kaartcontroles,Kartkontroller,Klawisze mapy,Comandos do mapa,,Schemă de control a hărtii,Автокарта,Контроле мапе,Kontroller för kartor,Harita Kontrolleri,Автомапа,Контроли за карта +Pan left,MAPCNTRLMNU_PANLEFT,,,,Doleva,Panorere til venstre,Nach links,Μετακίνηση προς τα αριστερά,Alturni maldekstren,Mover a la izquierda,,Panoroi vasemmalle,Aller à gauche,Balra igazítás,Sposta a sinistra,左に振る,왼쪽으로 이동,Pan links,Panorer til venstre,Przesuń w lewo,Mover para a esquerda,,Mutare spre stânga,Сдвиг влево,Лево,Panorera till vänster,Sola kaydırın,Зсув вліво,Преместване наляво +Pan right,MAPCNTRLMNU_PANRIGHT,,,,Doprava,Panorering til højre,Nach rechts,Μετακίνηση προς τα δεξιά,Alturni dekstren,Mover a la derecha,,Panoroi oikealle,Aller à droite,Jobbra igazítás,Sposta a destra,右に振る,오른쪽으로 이동,Pan rechts,Panorer til høyre,Przesuń w prawo,Mover para a direita,,Mutare spre dreapta,Сдвиг вправо,Десно,Panorera till höger,Sağa kaydırın,Зсув вправо,Преместване на дясно +Pan up,MAPCNTRLMNU_PANUP,,,,Nahoru,Panorere op,Nach oben,Μετακίνηση προς τα πάνω,Alturni supren,Mover hacia arriba,,Panoroi ylös,Aller en haut,Felfele igazítás,Sposta sopra,上に振る,위쪽으로 이동,Pan omhoog,Panorer opp,Przesuń w górę,Mover para cima,,Mutare în sus,Сдвиг вверх,Горе,Panorera uppåt,Yukarı kaydırın,Зсув вверх,Преместване на горе +Pan down,MAPCNTRLMNU_PANDOWN,,,,Dolů,Panorere ned,Nach unten,Μετακίνηση προς τα κάτω,Alturni malsupren,Mover hacia abajo,,Panoroi alas,Aller en bas,Lefele igazítás,Sposta sotto,下に振る,아래쪽으로 이동,Pan neer,Panorer ned,Przesuń w dół,Mover para baixo,,Mutare în jos,Сдвиг вниз,Доле,Panorera ner,Aşağı kaydırın,Зсув вниз,Преместване на долу +Zoom in,MAPCNTRLMNU_ZOOMIN,,,,Přiblížit,Zoom ind,Reinzoomen,Μεγέθυνση,Zomi,Acercar,,Lähennä,Zoom avant,Ráközelítés,Ingrandisci,ズームイン,줌 확대,Inzoomen,Zoom inn,Przybliż,Ampliar,,Apropriere Cameră,Приблизить,Увеличати,Zooma in,Yakınlaştır,Наблизити,Приближи +Zoom out,MAPCNTRLMNU_ZOOMOUT,,,,Oddálit,Zoom ud,Rauszoomen,Σμίκρυνση,Malzomi,Alejar,,Loitonna,Zoom arrière,Távolítás,Rimpicciolisci,ズームアウト,줌 축소,Uitzoomen,Zoom ut,Oddal,Afastar,,Depărtare Cameră,Отдалить,Одзумирати,Zooma ut,Uzaklaştır,Віддалити,Отдалечи +Toggle zoom,MAPCNTRLMNU_TOGGLEZOOM,,,,Přiblížení vyp./zap.,Skift mellem zoom,Zoom an/aus,Εναλλαγή ζουμ,Baskuligi zomon,Alternar zoom,,Zoomauksen vaihtokytkin,Zoom On/Off,Közelítés átkapcsolása,Abilita/disabilita zoom,ズーム切替,표준배율 조정,Omschakelen van de zoom,Veksle mellom zoom,Przełącz przybliżanie,Ativar/desativar zoom,,Comutator Zoom,Приближение (перекл.),Укључи зум,Växla zoom,Yakınlaştırmayı aç / kapat,Перемикач наближення,Приближи постоянно +Toggle follow,MAPCNTRLMNU_TOGGLEFOLLOW,,,,Sledování hráče vyp./zap.,Skift følge,Folgen an/aus,Εναλλαγή ακολουθίας,Baskuligi sekvon,Alternar seguimiento,,Seuraamistilan vaihtokytkin,Suivi On/Off,Követés átkapcsolása,Abilita/disabilita scorrimento mappa,追従切替,추적모드 조정,Schakelen volgen,Veksle følge,Przełącz śledzenie,Ativar/desativar seguimento,,Comutator urmărire jucător,Привязка к игроку (перекл.),Укључи праћење,Växla följning,Takip etmeyi değiştir,Слідувати за гравцем,Следвай постаянно +Toggle grid,MAPCNTRLMNU_TOGGLEGRID,,,,Mřížka vyp./zap.,Skift gitter,Gitter an/aus,Εναλλαγή πλέγματος,Baskuligi kradon,Alternar cuadrícula,,Ruudukon vaihtokytkin,Grille On/Off,Rács kapcsolása,Abilita/disabilita la griglia,グリッド切替,그리드 조정,Kiesnet,Veksle rutenett,Przełącz siatkę,Ativar/desativar grade,,Comutator grilă,Сетка (перекл.),Укључи координатну мрежу,Växla rutnät,Izgarayı değiştir,Увімкнути сітку,Включи координатна мрежа +Toggle rotate,MAPCNTRLMNU_ROTATE,,,,Otáčení vyp./zap.,Skift til rotere,Rotation an/aus,Εναλλαγή περιστροφής,Baskuligi turnadon,Alternar rotación,,Kääntämisen vaihtokytkin,Rotation On/Off,Forgás kapcsolása,Abilita/disabilita la rotazione,回転切替,,Toggle rotatie,Veksle mellom rotasjon,Przełącz obracanie,Ativar/desativar rotação,,Comutator rotire,Вращение (перекл.),Укључи ротацију,Växla rotera,Döndürmeyi değiştir,Ротація мапи,Завъртане (превключване) +Toggle texture,MAPCNTRLMNU_TOGGLETEXTURE,,,,Textury vyp./zap.,Skift tekstur,Texturen an/aus,Εναλλαγή υφής,Baskuligi teksturon,Alternar textura,,Pintakuvioinnin vaihtokytkin,Textures On/Off,Textúra kapcsolása,Abilita/disabilita le texture,テクスチャ切替,미니맵 텍스쳐 조정,Toggle textuur,Veksle tekstur,Przełącz tekstury,Ativar/desativar texturas,,Comutator mod texturat,Текстуры (перекл.),Укључи текстуру,Växla textur,Dokuyu değiştir,Увімкнути текстури, +Toggle automap,CNTRLMNU_AUTOMAP,,,,Otevřít/zavřít automapu,Skift til automap,Automap an/aus,Εναλλαγή automap,Baskuligi aŭtomatan mapon,Alternar automapa,,Kytke automaattikartta päälle/pois,Ouvrir/Fermer Carte,Térkép ki/bekapcsolása,Abilita/disabilita l'automappa,オートマップの切替,오토맵 조정,Automap aan/uit,Veksle mellom automap,Włącz mapę,Ativar/desativar automapa,,Comutator hartă computerizată,Автокарта (перекл.),Прикажи аутомапу,Växla automap,Otomatik haritayı değiştir,Відкрити автомапу, +Chasecam,CNTRLMNU_CHASECAM,,,,Kamera z třetí osoby,Chasecam,Verfolgerkamera,,Ĉaskamerao,Cámara de seguimiento,,Seurantakamera,Caméra 3ième personne,Külsőnézetű kamera,Telecamera di inseguimento,背後視点,3인칭 카메라,,,Kamera Śledzenia,Câmera em terceira pessoa,Câmera em terceira-pessoa,Cameră urmăritoare,Вид от 3-го лица,Чејс-кем,,,Вид від третьої особи, +Screenshot,CNTRLMNU_SCREENSHOT,,,,Pořídit snímek obrazovky,Skærmbillede,,Στιγμιότυπο,Ekrankopio,Captura de pantalla,,Kuvakaappaus,Capture d'écran,Képernyő lefényképezése,Cattura schermo,画面キャプチャ,스크린샷,,Skjermbilde,Zrzut ekranu,Captura de tela,,Captură ecran,Снимок экрана,Усликај,Skärmdump,Ekran görüntüsü,Скріншот, +Open console,CNTRLMNU_CONSOLE,,,,Otevřít konzoli,Åbn konsollen,Konsole öffnen,Ανοίξτε την κονσόλα,Malfermi konzolon,Abrir consola,,Avaa konsoli,Ouvrir Console,Konzol megnyitása,Apri la console,コンソールを開く,콘솔 열기,Open console,Åpne konsoll,Otwórz konsolę,Abrir console,Abrir consola,Deschide consola,Открыть консоль,Отвори консолу,Öppna konsolen,Açık konsol,Відкрити консоль, +Pause,CNTRLMNU_PAUSE,,,,Pauza,,,Πάυση,Paŭzo,Pausa,,Tauko,,Szünet,Pausa,ポーズ,일시정지,Pauze,,Pauza,Pausar,,Pauză,Пауза,Пауза,Pausa,Duraklat,Пауза, +Increase Display Size,CNTRLMNU_DISPLAY_INC,,,,Zvětšit velikost obrazovky,Forøg visningsstørrelsen,Anzeige vergrößern,Αύξηση μεγέθους οθόνης,Kreskigi ekrangrandon,Agrandar ventana,,Suurenna näytön kokoa,Agrandir l'affichage,Képméret növelése,Aumenta la dimensione del display,画面サイズを拡大,화면 크기 늘리기,Vergroot het display,Øk visningsstørrelse,Powiększ Rozmiar Wyświetlania,Aumentar tamanho da exibição,Aumentar Tamanho do Ecrã,Mărire ecran,Увеличить размер экрана,Повећајте величину екрана,Öka skärmstorleken,Ekran Boyutunu Artırın,Збільшити розмір екрану, +Decrease Display Size,CNTRLMNU_DISPLAY_DEC,,,,Zmenšit velikost obrazovky,Formindsk skærmstørrelse,Anzeige verkleinern,Μείωση μεγέθους οθόνης,Malkreskigi ekrangrandon,Reducir ventana,,Pienennä näytön kokoa,Réduire l'affichage,Képméret csökkentése,Riduci la dimensione del display,画面サイズを縮小,화면 크기 줄이기,Verlaag het display,Reduser visningsstørrelse,Pomniejsz Rozmiar Wyświetlania,Reduzir tamanho da exibição,Diminuir Tamanho do Ecrã,Micșorare ecran,Уменьшить размер экрана,Смањите величину екрана,Minska visningsstorleken,Ekran Boyutunu Azaltma,Зменшити розмір екрану, Open Help,CNTRLMNU_OPEN_HELP,,,,Nápověda,Åbn hjælp,Hilfe öffnen,Άνοιγμα βοήθειας,Malfermi helpon,Abrir ayuda,,Avaa ohje,Ouvrir Aide,Segítség előhozása,Apri la guida,"ヘルプを開く -",도움말 열기,Open hulp,Åpne Hjelp,Otwórz Pomoc,Abrir ajuda,,Deschide Ajutor,Экран помощи,Отвори помоћ,Açık Yardım,Відкрити екран допомоги, -Open Save Menu,CNTRLMNU_OPEN_SAVE,,,,Uložit hru,Åbn menuen Gem,Speichermenü öffnen,,Malfermi konservmenuon,Menú de guardar partida,,Avaa tallennusvalikko,Ouvrir Menu Sauvegarde,Mentés menü előhozása,Apri il menu di salvataggio,セーブメニューを開く,저장 화면 열기,Menu opslaan openen,Åpne Lagre-menyen,Otwórz Menu Zapisu,Abrir menu de salvar,Abrir Menu de Gravação,Deschide meniul de salvare,Меню сохранения игры,Отвори сачуване игре,Kaydet Menüsünü Aç,Меню збереженнь, -Open Load Menu,CNTRLMNU_OPEN_LOAD,,,,Načíst hru,Åbn indlæsningsmenuen,Lademenü öffnen,,Malfermi ŝargmenuon,Menú de cargar partida,,Avaa latausvalikko,Ouvrir Menu Chargement,Betöltés menü előhozása,Apri il menu di caricamento,ロードメニューを開く,불러오기 화면 열기,Menu laden openen,Åpne Last-menyen,Otwórz Menu Wczytania,Abrir menu de carregar,,Deschide meniul de încărcare,Меню загрузки игры,Отвори игре за учитати,Yük Menüsünü Aç,Меню завантаженнь, -Open Options Menu,CNTRLMNU_OPEN_OPTIONS,,,,Nastavení,Åbn menuen Indstillinger,Optionsmenü öffnen,,Malfermi agordmenuon,Menú de opciones,,Avaa asetusvalikko,Ouvrir Menu Options,Beállítások menü előhozása,Apri il menu delle opzioni,オプションメニューを開く,설정 화면 열기,Menu Opties openen,Åpne Alternativer-menyen,Otwórz Menu Opcji,Abrir menu de opções,,Deschide setările,Главное меню настроек,Отвори мени опција,Seçenekler Menüsünü Aç,Головне меню параметрів, -Open Display Menu,CNTRLMNU_OPEN_DISPLAY,,,,Nastavení grafiky,Åbn menuen Visning,Anzeigemenü öffnen,,Malfermi ekranmenuon,Menú de opciones de visualización,,Avaa näyttövalikko,Ouvrir Menu Affichage,Megjelenítés menü előhozása,Apri il menu del display,ディスプレイメニューを開く,디스플레이 화면 열기,Displaymenu openen,Åpne visningsmeny,Otwórz Menu Wyświetlania,Abrir menu de vídeo,,Deschide setările de afișare,Меню настроек видео,Отвори мени приказа,Ekran Menüsünü Aç,Параметри відео, -Quicksave,CNTRLMNU_QUICKSAVE,,,,Rychlé uložení,Quicksave,Schnellspeichern,,Rapidkonservo,Guardado rápido,,Pikatallenna,Sauv. Rapide,Gyorsmentés,Salvataggio rapido,クイックセーブ,빠른 저장,Snel opslaan,Hurtiglagring,Szybki Zapis,Salvar rapidamente,Gravação rápida,Salvare rapidă,Быстрое сохранение,Брзо-сачувај,Hızlı Tasarruf,Швидке збереження, -Quickload,CNTRLMNU_QUICKLOAD,,,,Rychlé načtení,Quickload,Schnellladen,,Rapidŝargo,Cargado rápido,,Pikalataa,Charg. Rapide,Gyorstöltés,Caricamento rapido,クイックロード,빠른 불러오기,Snel laden,Hurtiglasting,Szybkie Wczytanie,Carregar rapidamente,,Încărcare rapidă,Быстрая загрузка,Брзо-учитај,Hızlı Yükleme,Швидке завантаження, -Exit to Main Menu,CNTRLMNU_EXIT_TO_MAIN,,,,Odejít do hlavního menu,Afslut til hovedmenu,Zurück zum Hauptmenü,,Eliri al ĉefa menuo,Salir al menú principal,,Poistu päävalikkoon,Sortie Menu Principal,Kilépés a főmenübe,Esci dal menu principale,メインメニューに戻る,메뉴로 나오기,Afsluiten naar het hoofdmenu,Avslutt til hovedmeny,Wyjdź do Głównego Menu,Sair para o menu principal,,Revenire la meniul principal,Выход в главное меню,Изађи у главни мени,Ana Menüden Çıkış,Вихід в головне меню, -Toggle Messages,CNTRLMNU_TOGGLE_MESSAGES,,,,Povolit/skrýt oznámení,Skift mellem meddelelser,Nachrichten an/aus,,Baskuligi mesaĝojn,Alternar mensajes,,Kytke viestit päälle tai pois,Act./Déasct. Messages,Üzenetek kapcsolása,Toggle messaggi,メッセージ表示の切替,메시지 토글,Berichten aan/uit,Veksle meldinger,Włącz / Wyłącz Wiadomości,Ativar/desativar mensagens,,Comutator mesaje,Переключение сообщений,Таглави поруке,Mesajları Değiştir,Перемикач повідомлень, -Quit Game,CNTRLMNU_MENU_QUIT,,,,Ukončit hru,Afslut spil,Spiel beenden,Στάματα το παιχνίδι,Mallanĉi ludon,Salir del juego,,Lopeta peli,Quitter le Jeu,Kilépés a játékból,Esci dal gioco,ゲームを終了,게임 종료,Stop het spel,Avslutt spill,Wyjdź z Gry,Sair do jogo,,Ieși din Joc,Выход,Изађи из игре,Oyundan Çık,Вихід, -Adjust Gamma,CNTRLMNU_ADJUST_GAMMA,,,,Nastavit gamu,Juster Gamma,Gamma-Anpassung,,Agordi gamaon,Ajustar gama,,Säädä gammaa,Ajuster Gamma,Gamma állítása,Aggiustamento Gamma,ガンマ値を調整,감마 조정,Gamma aanpassen,Juster gamma,Dostosuj Gammę,Ajustar gama,,Ajustare gamma,Настройка гаммы,Подесите осветљење,Gama Ayarlama,Парамети гамми, -,,Mouse,,,,,,,,,,,,,,,,,,,,,,,,,, -Enable mouse,MOUSEMNU_ENABLEMOUSE,,,,Povolit myš,Aktiver mus,Maus aktiv,Ενεργοποίηση ποντικιόυ,Ebligi muson,Habilitar ratón,,Ota hiiri käyttöön,Activer Souris,Egér engedélyezése,Abilita il mouse,マウスの使用,마우스 사용,Muis inschakelen,Aktiver mus,Włącz myszkę,Ativar mouse,Permitir uso do rato,Activare mouse,Использовать мышь,Укључи миш,Fareyi etkinleştir,Використовувати миш, -Enable mouse in menus,MOUSEMNU_MOUSEINMENU,,,,Povolit myš v nabídkách,Aktiver mus i menuer,Maus aktiv in Menüs,Ενεργοποίηση ποντικιόυ στα μενού,Ebligi muson en menuoj,Usa ratón en los menús,,Ota hiiri käyttöön valikoissa,Activer Souris dans les Menus,Egér engedélyezése a menüben,Abilita il mouse nei menu,メニューでのマウスの使用,메뉴에서 마우스 사용,Muis in menu's inschakelen,Aktiver mus i menyer,Włącz myszkę w menu,Ativar mouse nos menus,Permitir rato nos menus,Activare mouse în meniuri,Использовать мышь в меню,Укључи миш у менијима,Menülerde fareyi etkinleştir,Використовувати миш в меню, -Show back button,MOUSEMNU_SHOWBACKBUTTON,,,,Zobrazit tlačítko zpět,Vis tilbage-knappen,Zeige Zurück-Knopf,,Montri reen-butonon,Mostrar botón de retroceso,,Näytä taaksenäppäin,Afficher le bouton retour,Vissza gomb mutatása,Mostra il bottone per tornare indietro,戻るボタンを表示,뒤로가기 버튼 보이기,Toon terug knop,Vis tilbake-knapp,Pokaż przycisk powrotu,Exibir botão de voltar,,Afișare buton de întoarcere,Расположение кнопки «назад»,Прикажи тастер за назад,Geri düğmesini göster,"Положення кнопки ""назад""", -Cursor,MOUSEMNU_CURSOR,,,,Kurzor,Markør,,,Musmontrilo,,,Osoitin,Curseur,Egérmutató,Cursore,カーソル,커서,,Markør,Kursor,Cursor,,,Курсор,Курсор,İmleç,Курсор, -Horizontal sensitivity,MOUSEMNU_SENSITIVITY_X,,,,Horizontální citlivost,Vandret følsomhed,Horizontale Empfindlichkeit,Οριζόντια ευαισθησία,Horizontala sentemo,Sensibilidad horizontal,,Vaakasuuntainen herkkyys,Sensibilité horizontale,Vízszintes érzékenység,Sensibilità orizzontale,水平感度,수평 감도,Horizontale gevoeligheid,Horisontal følsomhet,Czułość pozioma,Sensibilidade horizontal,,Sensibilitate orizontală,Горизонтальная чувствительность,Хоризонтална осетљивост,Yatay hassasiyet,Горизонтальна чутливість, -Vertical sensitivity,MOUSEMNU_SENSITIVITY_Y,,,,Vertikální citlivost,Lodret følsomhed,Vertikale Empfindlichkeit,Κάθετη ευαισθησία,Vertikala sentemo,Sensibilidad vertical,,Pystysuuntainen herkkyys,Sensibilité verticale,Függőleges érzékenység,Sensibilità verticale,垂直感度,수직 감도,Verticale gevoeligheid,Vertikal følsomhet,Czułość pionowa,Sensibilidade vertical,,Sensibilitate verticală,Вертикальная чувствительность,Вертикална осетљивост,Dikey hassasiyet,Вертикальна чутливість, -Smooth mouse movement,MOUSEMNU_SMOOTHMOUSE,,,,Vyhladit pohyb myši,Jævn bevægelse af musen,Mausbewegung glätten,,Glata musmovo,Mov. fluido del ratón,,Sulava hiiren liike,Lissage Souris,Egérmozgás simítása,Movimento del mouse liscio,マウス操作を滑らかにする,부드러운 움직임,Vlotte muisbeweging,Jevn musebevegelse,Gładki ruch myszki,Suavizar movimento do mouse,Movimento fluído do rato,Mișcare mouse fină,Плавное перемещение,Глатки окрет,Pürüzsüz fare hareketi,Плавний рух миші, -Turning speed,MOUSEMNU_TURNSPEED,,,,Rychlost otáčení,Drejehastighed,Umdrehgeschwindigkeit,,Turnorapido,Velocidad de giro,,Kääntymisnopeus,Vitesse pour tourner,Fordulás sebessége,Velocità di rotazione,旋回速度,회전 속도,Draaisnelheid,Dreiehastighet,Szybkość obracania się,Velocidade de giro,,Viteză rotire,Скорость поворота,Брзина окрета,Dönüş hızı,Швидкість повороту, -Mouselook speed,MOUSEMNU_MOUSELOOKSPEED,,,,Rychlost pohledu nahoru/dolů,Hastighed for mus-look,Mausblick-Geschwindigkeit,,Musrigarda rapido,Veloc. de vista con ratón,,Katselunopeus,Vitesse Vue Souris,Egérnézés sebessége,Velocità di rotazione della vista,上下視点速度,마우스룩 속도,Mouselook snelheid,Muselook-hastighet,Szybkość rozglądania się myszką,Velocidade da visão com mouse,Velocidade de vista com rato,Viteză privire în jur cu mouse,Скорость обзора,Брзина гледања мишем,Mouselook hızı,Швидкість огляду, -Forward/Backward speed,MOUSEMNU_FORWBACKSPEED,,,,Rychlost pohybu vpřed/vzad,Hastighed fremad/tilbage,Vor/Rückwärtsgeschwindigkeit,,Antaŭa/Malantaŭa rapido,Veloc. de avance/retroceso,,Eteen-/taaksepäin liikkeen nopeus,Vitesse Avancer/reculer,Előre/Hátra sebesség,Velocità avanti/indietro,"前進/後退速度 -",전진/후진 속도,Voorwaartse/achterwaartse snelheid,Hastighet forover/bakover,Szybkość chodzenia do przodu/do tyłu,Velocidade de deslocamento para frente/trás,,Viteză deplasare față/spate,Скорость передвижения,Брзина окрета напред/уназад,İleri/Geri hız,Швидкість руху вперед/назад, -Strafing speed,MOUSEMNU_STRAFESPEED,,,,Rychlost pohybu do stran,Strafing-hastighed,Seitwärtsgeschwindigkeit,,Flankmova rapido,Veloc. de mov. lateral,,Sivuttaisastunnan nopeus,Vitesse Gauche/Droite,Oldalazás sebessége,Velocità movimento laterale,横移動速度,좌진/우진 속도,Zijdelings snelheid,Hastigheten for stansing,Szybkość uników,Velocidade de deslocamento lateral,,Viteză deplasare în diagonală,Скорость движения боком,Брзина стрејфа,Strafe hızı,Швидкість руху боком, -Always Mouselook,MOUSEMNU_ALWAYSMOUSELOOK,,,,Vždy se rozhlížet myší,Altid mus-look,Mausblick immer an,Πάντα κοίτα με το ποντίκι,Ĉiam musrigardi,Siempre mirar con ratón,,Jatkuva hiirikatselu,Toujours vue Souris,Mindig egérrel nézelődés,Vista col mouse,常に上下視点をオン,마우스룩 사용,Altijd Mouselook,Alltid muselook,Zawsze zezwalaj na rozglądanie się myszką,Visão com mouse sempre ativada,Vista com rato sempre ligada,Privire în jur cu mouse permanentă,Обзор мышью,Гледање мишем,Her zaman Mouselook,Огляд мишкою, -Invert Mouse Y,MOUSEMNU_INVERTMOUSE,,,,Vertikálně obrátit myš,Inverter mus Y,Maus Y invertieren,,Inversi muson Y,Invertir ratón Y,,Käännä hiiri Y,Inverser Souris Y,Y tengely megfordítása,Mouse Y invertito,視点操作反転,마우스 방향 전환,Muis-Y-as omkeren,Inverter mus Y,Odwróć Myszkę - Oś Y,Inverter eixo Y do mouse,Inverter rato,Inversare axă mouse Y,Инверт. мышь по вертикали,Инвертуј миш Y,Fare Y'yi Ters Çevir,Інвертувати мишу Y, -Invert Mouse X,MOUSEMNU_INVERTMOUSEX,,,,Horizontálně obrátit myš,Inverter mus X,Maus X invertieren,,Inversi muson X,Invertir ratón X,,Käännä hiiri X,Inverser Souris X,X tengely megfordítása,Mouse X invertito,視点操作反転,마우스 방향 전환,Muis-X-as omkeren,Inverter mus X,Odwróć Myszkę - Oś X,Inverter eixo X do mouse,Inverter rato X,Inversare axă mouse X,Инверт. мышь по горизонтали,Инвертуј миш X,Fare X'i Ters Çevir,Інвертувати мишу Х, -Upper left,OPTVAL_UPPERLEFT,,,,Vlevo nahoře,Øverste venstre,Oben links,,Supra maldekstre,Sup. izquierda,,Ylävasemmalla,Supérieur gauche,Bal fent,Superiore sinistro,左上,왼쪽 위,Linksboven,Øvre venstre,Lewy górny róg,Esquerda superior,,Stânga sus,Вверху слева,Горње лево,Sol üst,Вгорі ліворуч, -Upper right,OPTVAL_UPPERRIGHT,,,,Vpravo nahoře,Øvre højre,Oben rechts,,Supra dekstre,Sup. derecha,,Yläoikealla,Supérieur droite,Jobb fent,Superiore destro,右上,오른쪽 위,Rechtsboven,Øverst til høyre,Prawy górny róg,Direita superior,,Dreapta sus,Вверху справа,Горње десно,Sağ üst,Вгорі праворуч, -Lower left,OPTVAL_LOWERLEFT,,,,Vlevo dole,Nederste venstre,Unten links ,,Suba maldekstre,Inf. izquierda,,Alavasemmalla,Inférieur gauche,Bal lent,Inferiore sinistro,左下,왼쪽 밑,Linksonder,Nedre venstre,Lewy dolny róg,Esquerda inferior,,Stânga jos,Внизу слева,Доње лево,Sol alt,Внизу ліворуч, -Lower right,OPTVAL_LOWERRIGHT,,,,Vpravo dole,Nederste højre,Unten rechts,,Suba dekstre,Inf. derecha,,Alaoikealla,Inférieur droite,Jobb lent,Inferiore destro,右下,오른쪽 밑,Rechtsonder,Nedre høyre,Prawy dolny róg,Direita inferior,,Dreapta jos,Внизу справа,Доње десно,Sağ alt,Внизу праворуч, -Touchscreen-like,OPTVAL_TOUCHSCREENLIKE,,,,Jako dotyková obrazovka,Touchscreen-lignende,Wie auf einem Touchscreen,,Tuŝekraneca,Pant. táctil,,Kosketusnäyttömäinen,Style écran tactile,Érintőképernyő-szerű,Come il Touchscreen,タッチスクリーン式,터치스크린 같게,Touchscreen-achtige,Berøringsskjerm-lignende,Jak ekrean dotykowy,Estilo touchscreen,,Precum touchscreen,Как сенсорный экран,Као додирни екран,Dokunmatik ekran benzeri,Як сенсорний екран, -Simple arrow,OPTSTR_SIMPLEARROW,,,,Jednoduchý kurzor,Simpel pil,Einfacher Pfeil,,Simpla sago,Flecha simple,,Yksinkertainen nuoli,Flèche simple,Sima nyíl,Freccia semplice,シンプル,기본 커서,Eenvoudige pijl,Enkel pil,Prosta strzałka,Seta simples,Cursor simples,Săgeată simplă,Стрелка,Стрелица,Basit ok,Стрілка, -System cursor,OPTSTR_SYSTEMCURSOR,,,,Systémový kurzor,Systemcursor,Systemcursor,Δείκτης συστήματος,Sistema kursoro,Cursor del sistema,,Järjestelmän osoitin,Curseur Système,Rendszer egérmutatója,Cursore di sistema,システム,시스템 커서,Systeemcursor,Systemmarkør,Kursor systemu,Cursor do sistema,,Cursor simplu,Системный курсор,Системска стрелица,Sistem imleci,Системний курсор, -Default,OPTVAL_DEFAULT,,,,Výchozí,Standard,Standard,Προεπιλογή,Defaŭlta,Por defecto,,Oletus,Défaut,Alapbeállítás,Predefinito,デフォルト,기본 설정,Standaard,Standard,Domyślne,Padrão,,Implicit,По умолчанию,Подраз.,Varsayılan,За замовчуванням, -,,Controller,,,,,,,,,,,,,,,,,,,,,,,,,, -Configure Controller,JOYMNU_TITLE,,,,Konfigurace ovladače,Konfigurer controller,Controller konfigurieren,,Agordi ludregilon,Configurar mando,,Peliohjainasetukset,Configurer Mannette,Kontroller testreszabása,Configura il controller,コントローラー構成:,컨트롤러 구성,Controller configureren,Konfigurer kontrolleren,Konfiguruj Kontroler,Configurar controle,Configurar Comando,Configurare controller,Настроить контроллер,Конфигурација контролера,Denetleyiciyi Yapılandırma,Параметри контролера, -Controller Options,JOYMNU_OPTIONS,,,,Ovladač,Indstillinger for styreenhed,Controlleroptionen,,Ludregilo-agordoj,Opciones del mando,,Peliohjainasetukset,Options Mannette,Kontroller beállítások,Opzioni del controller,コントローラー設定,컨트롤러 설정,Controller opties,Alternativer for styreenhet,Opcje Kontrolera,Opções de controle,Opções do Comando,Setări controller,Настройки контроллера,Подешавања контролера,Kontrolör Seçenekleri,Налаштування контролера, -Block controller input in menu,JOYMNU_NOMENU,,,,Zakázat ovladač v nabídkách,Bloker controller input i menuen,Blockiere Controllereingabe im Menü,,Blokigi ludregilan enigon en menuo,Bloq. entrada de mando en menú,,Estä ohjainsyötteet valikoissa,Bloquer manette dans les menus,Kontroller ne működjön a menüben,Blocca l'input del controller nei menu,メニューではコントローラーを無視,메뉴에서 컨트롤러 끄기,Blokkeer de controller in het menu,Blokker kontrollerinngang i menyen,Blokuj wejście kontrolera w menu,Bloquear controle no menu,Bloquear comando no menu,Blocare comenzi controller în meniu,Отключить контроллер в меню,Блокирај улаз контролера у менију,Menüde kontrolör girişini engelle,Відключити контролер в меню, -Enable controller support,JOYMNU_ENABLE,,,,Povolit podporu pro ovladače,Aktivering af controllerunderstøttelse,Erlaube Controllerunterstützung,,Ŝalti ludregilan subtenon,Activar soporte de mandos,,Ota käyttöön peliohjaintuki,Activer support contrôleur,Kontroller támogatás engedélyezése,Abilita il supporto del controller,コントローラーサポート許可,컨트롤러 지원 허용,Controllerondersteuning inschakelen,Aktiver støtte for styreenhet,Włącz wsparcie kontrolera,Ativar detecção de controles,,Activare support controller,Включить поддержку контроллера,Омогући подршку за контролере,Denetleyici desteğini etkinleştir,Увімкнути підтримку контролера, -Enable DirectInput controllers,JOYMNU_DINPUT,,,,Povolit ovladače DirectInput,Aktivering af DirectInput-controllere,Erlaube DirectInput-Controller,,Ŝalti DirectInput ludregilojn,Usa controles DirectInput,,Ota käyttöön DirectInput-ohjaimet,Activer contrôleurs DirectInput,DirectInput kontrollerek engedélyezése,Abilita i controlli DirectInput,ダイレクトインプットコントローラー許可,다이렉트 인풋 컨트롤러 허용,DirectInput-controllers inschakelen,Aktiver DirectInput-kontrollere,Włącz kontrolery DirectInput,Ativar controles DirectInput,,Activare controlere DirectInput,Включить контроллеры через DirectInput,Омогући директинпут контролере,DirectInput denetleyicilerini etkinleştirin,Увімкнути контролери DirectInput, -Enable XInput controllers,JOYMNU_XINPUT,,,,Povolit ovladače XInput,Aktiver XInput-controllere,Erlaube XInput-Controller,,Ŝalti XInput ludregilojn,Usa controles XInput,,Ota käyttöön XInput-ohjaimet,Activer contrôleurs XInput,XInput kontrollerek engedélyezése,Abilita i controlli XInput,Xinput コントローラー許可,X인풋 컨트롤러 허용,XInput-controllers inschakelen,Aktiver XInput-kontrollere,Włącz kontrolery XInput,Ativar controles XInput,,Activare controlere XInput,Включить контроллеры через XInput,Омогући Иксинпут контролере,XInput denetleyicilerini etkinleştirin,Увімкнути контролери XInput, -Enable raw PlayStation 2 adapters,JOYMNU_PS2,,,,Povolit ovladače PlayStation 2,Aktiver rå PlayStation 2-adaptere,Erlaube Playstation 2-Controller,,Ŝalti krudajn adaptilojn de PlayStation 2 ,Usa adaptadores de PlayStation 2,,Ota käyttöön raa'at PlayStation 2 -adapterit,Activer adaptateurs PS2 bruts,PlayStation 2 adapterek engedélyezése,Abilita gli adattatori raw PlayStation 2,PlayStation2 アダプター許可,PS2 어뎁터 허용,Raw PlayStation 2-adapters inschakelen,Aktiver rå PlayStation 2-adaptere,Włącz adaptery PlayStation 2,Ativar adaptadores de PlayStation 2,,Activare adaptoare PS2,Использовать адаптеры PlayStation 2 напрямую,Омогући сирове Плејстејшн 2 адаптере,Ham PlayStation 2 adaptörlerini etkinleştirin,Використовувати адаптери PlayStation 2 напряму, -No controllers detected,JOYMNU_NOCON,,,,Nenalezeny žádné ovladače.,Ingen controllere er fundet,Keine Controller gefunden,,Neniu ludregilo detektita,No hay mandos detectados,,Ei havaittuja ohjaimia,Aucun Contrôleur détecté.,Nem érzékelhető kontroller,Nessun controller trovato,コントローラーが見つかりません,인식된 컨트롤러 없음,Geen controllers gedetecteerd,Ingen kontrollere oppdaget,Nie wykryto kontrolerów,Nenhum controle detectado.,Nenhum comando foi detectado,Niciun controller detectat,Контроллеры не обнаружены,Нема детектованих контролера,Denetleyici algılanmadı,Контролерів не виявлено, -Configure controllers:,JOYMNU_CONFIG,,,,Nastavit ovladače:,Konfigurer controllere:,Controller konfigurieren,,Agordi ludregilojn:,Configurar controles:,,Mukauta ohjaimia:,Configurer contrôleurs:,Kontrollerek konfigurációja:,Configura i controller:,コントローラー構成:,컨트롤러 설정:,Configureer controllers:,Konfigurer kontrollere:,Konfiguruj kontrolery:,Configurar controles:,Configurar comandos,Configurare controlere:,Настроить контроллер:,Подешавања контролере:,Denetleyicileri yapılandırın:,Налаштувати контролери, -Controller support must be,JOYMNU_DISABLED1,,,,Pro nalezení ovladačů musí,Der skal være støtte til controlleren,Controllerunterstütung muss aktiviert sein,,Ludregilo-subteno devas esti,El soporte de mandos debe estar,,Ohjaintuen täytyy olla otettu,Le Support de contrôleur doit être activé,A kontroller támogatásnak,Il supporto ai controller deve essere,コントローラーサポートは,감지하려면 컨트롤러 지원을,Controller ondersteuning moet ingeschakeld zijn,Støtte for kontrollere må være,Wsparcie kontrolera musi być,A detecção de controles deve,Suporte a comandos devem ser,Supportul pentru controller trebuie,Включите поддержку контроллера,Омогућите подржавање контролера,Denetleyici desteği şu şekilde olmalıdır,Включіть підтримку контролерів, -enabled to detect any,JOYMNU_DISABLED2,Supposed to be empty in Russian and Serbian.,,,být zapnuta jejich podpora.,aktiveret for at registrere enhver,um welche zu finden,,ŝaltita por detekti iun ajn,activado para detectar alguno,,käyttöön ohjainten havaitsemiseksi,avant de pouvoir en détecter un.,"engedélyezve kell lenni, hogy érzékeljen bármit is.",abilitato a trovare ogni,検出しました,활성화 해야합니다.,om eventuele regelaars te detecteren.,aktivert for å oppdage en hvilken som helst,Włączony by wykryć jakikolwiek,ser ativada para exibi-los.,,activat pentru a putea fi detectate, \n, \n,tespit etmek için etkinleştirildi, \n, -Invalid controller specified for menu,JOYMNU_INVALID,,,,Vybrán nesprávný ovladač pro nabídky,Ugyldig controller angivet til menuen,Ungültiger Controller für Menü ausgewählt,,Nevalida ludregilo specifigita por menuo,Mando inválido especificado para el menú,,Epäkelpo ohjain määritetty valikolle,Contrôleur invalide spécifé dans le menu.,Hibás kontroller van a menühöz osztva,Controller invalido specificato per il menu,メニューではコントローラーを使用しない,메뉴에 특정된 컨트롤러가 아닙니다.,Ongeldige regelaar gespecificeerd voor het menu,Ugyldig kontroller spesifisert for menyen,Niewłaściwy kontroler określony dla menu,Controle inválido especificado para o menu.,Comando inválido,Controller pentru meniu invalid,Недопустимый контроллер выбран для меню,Невалидан контролер специфиран за мени,Menü için geçersiz denetleyici belirtildi,Для меню вибрано невідповідний контролер, -Overall sensitivity,JOYMNU_OVRSENS,,,,Celková citlivost,Samlet følsomhed,Allgemeine Empfindlichkeit,,Tuta sentemeco,Sensibilidad general,,Yleisherkkyys,Sensibilité générale,Teljes érzékenység,Sensibilità generale,全体的な感度,전체 민감도,Algemene gevoeligheid,Samlet følsomhet,Ogólna Czułość,Sensibilidade geral,,Sensibilitate în ansamblu,Общая чувствительность,Уупна сензитивност,Genel hassasiyet,Загальна чутливість, -Axis Configuration,JOYMNU_AXIS,,,,Nastavení os,Konfiguration af akserne,Achsenkonfiguration,,Akso-agordoj,Configuración del eje,,Akseleiden säätäminen,Configuration des axes,Tengely konfigurálása,Configurazione assi,軸構成,축 구성,Asconfiguratie,Konfigurasjon av akse,Konfiguruj Oś,Configuração de eixo,,Configurare axă,Конфигурация осей,Конфигурација осе,Eksen Konfigürasyonu,Конфігурація осей, -Invert,JOYMNU_INVERT,,,,Obrátit,Invert,Invertieren,,Inversigi,Invertir,,Käännä,Inverser,Megfordítás,Inverti,反転,순서 바꿈,Omkeren,Invertering,Odwróć,Inverter,,Inversare,Инвертировать,Инвертовано,Ters çevir,Інвертувати, -Dead zone,JOYMNU_DEADZONE,,,,Mrtvá zóna,Dødzone,Totzone,,Mortozono,Zona muerta,,Kuollut alue,Zone neutre,Holttér,Zona cieca,デッドゾーン,불감대,Dode zone,Død sone,Martwa strefa,Zona morta,,Zonă moartă,Мёртвая зона,Мртва зона,Ölü bölge,Мертва зона, -No configurable axes,JOYMNU_NOAXES,,,,Žádné nastavitelné osy,Ingen konfigurerbare akser,Keine konfigurierbaren Achsen,,Neniuj agordeblaj aksoj,No hay ejes configurables,,Ei säädettäviä akseleita,Aucun axe à configurer,Nincs beállítható tengely,Nessun asse configurabile,軸構成を無効,설정할 방향키가 없습니다.,Geen configureerbare assen,Ingen konfigurerbare akser,Brak osi do skonfigurowania,Nenhum eixo configurável,,Nicio axă configurabilă,Нет настраиваемых осей,Нема конфигурационих оса,Yapılandırılabilir eksen yok,Немає настроюваних осей, -None,OPTVAL_NONE,,,,Žádný,Ingen,Kein,,Neniu,Ninguno,,Ei mitään,Aucun,Nincs,Nessuno,無し,없음,Geen,Ingen,Żaden,Nenhum,,Niciuna,Откл.,Ништа,Hiçbiri,Вимк., -Turning,OPTVAL_TURNING,,,,Otáčení,Drejning,Umdrehen,,Turnanta,Girar,,Kääntyminen,Tourner,Fordulás,Rotazione,旋回,회전,Draaien,Dreie,Obracanie się,Girar,,Rotire,Поворот,Скретање,Dönüş,Поворот, -Looking Up/Down,OPTVAL_LOOKINGUPDOWN,,,,Dívání se nahoru/dolů,Kigger op/ned,Hoch/runterblicken,,Rigardanta (mal)supren,Mirar hacia arriba/abajo,,Ylös/Alas katsominen,Vue haut/bas,Fel-/lenézés,Sguardo Sopra/Sotto,視点上下,위/아래로 보기,Omhoog/omlaag zoeken,Ser opp/ned,Patrzenie w górę/w dół,Olhar para cima/baixo,,Privire Sus/Jos,Взгляд вверх/вниз,Гледање горе/доле,Yukarı/Aşağı Bakmak,Дивитись вгору, -Moving Forward,OPTVAL_MOVINGFORWARD,,,,Pohyb vpřed,Bevæger sig fremad,Vorwärtsbewegung,,Movanta antaŭen,Avanzar,,Eteenpäin liikkuminen,Avancer,Előre mozgás,Movimento in avanti,前進,앞으로 전진,Voorwaarts bewegen,Beveger seg fremover,Poruszanie się do przodu,Mover-se para a frente,,Deplasare în Față,Движение вперёд,Кретање напред,İleriye Doğru,Рухатись вперед, -Strafing,OPTVAL_STRAFING,,,,Pohyb do stran,Strafing,Seitwärtsbewegung,,Flankmovanta,Desplazarse,,Sivuttaisastunta,Pas de côté,Oldalazás,Movimento laterale,横移動,양옆으로 이동,Strafelen,Straffe,Uniki,Deslocamento lateral,,Deplasare în Diagonală,Движение боком,Кретање у страну,Strafing,Рухатись боком, -Moving Up/Down,OPTVAL_MOVINGUPDOWN,,,,Pohyb nahoru/dolů,Bevægelse op/ned,Auf/abwärtsbewegung,,Movanta (mal)supren,Moverse hacia arriba/abajo,,Ylös/Alas liikkuminen,Mouvement haut/bas,Felfele/Lefele mozgás,Movimento Sopra/Sotto,前進後退,위/아래로 이동,Naar boven/beneden bewegen,Beveger seg opp/ned,Poruszanie się w górę/w dół,Mover-se para cima/baixo,,Mișcare Sus/Jos,Движение вверх/вниз,Кретање горе/доле,Yukarı/Aşağı Hareket Etme,Рухатись вгору/вниз, -Inverted,OPTVAL_INVERTED,,,,Inverzní,Omvendt,Invertiert,,Inversigita,Invertido,,Käännetty,Inversé,Felcserélve,Invertito,反転する,반전,Omgekeerd,Invertert,Odwrócony,Invertido,,Inversat,Инвертировано,Обрнуто,Ters çevrilmiş,Інвертовано, -Not Inverted,OPTVAL_NOTINVERTED,,,,Neinverzní,Ikke omvendt,nicht invertiert,,Ne inversigita,No invertido,,Ei käännetty,Non Inversé,Nincs felcserélve,Non invertito,反転しない,반전되지 않음,Niet omgekeerd,Ikke invertert,Nieodwrócony,Não invertido,,Neinversat,Прямо,Не обрнуто,Ters Çevrilmemiş,Не інвертовано, -,,Player Menu,,,,,,,,,,,,,,,,,,,,,,,,,, -Blue,TXT_COLOR_BLUE,,,,Modrá,Blå,Blau,Μπλέ,Blua,Azul,,Sininen,Bleu,Kék,Blu,青,청색,Blauw,Blå,Niebieski,Azul,,Albastru,Синий,Плава,Mavi,Синій, -Red,TXT_COLOR_RED,,,,Červená,Rød,Rot,Κόκκινο,Ruĝa,Rojo,,Punainen,Rouge,Vörös,Rosso,赤,적색,Rood,Rød,Czerwony,Vermelho,,Roșu,Красный,Црвена,Kırmızı,Червоний, -Green,TXT_COLOR_GREEN,,,,Zelená,Grøn,Grün,Πράσινο,Verda,Verde,,Vihreä,Vert,Zöld,Verde,緑,녹색,Groen,Grønn,Zielony,Verde,,Verde,Зелёный,Зелена,Yeşil,Зелений, -Gray,TXT_COLOR_GRAY,,,Grey,Šedá,Grå,Grau,Γκρί,Griza,Gris,,Harmaa,Gris,Szürke,Grigio,灰,회색,Grijs,Grå,Szary,Cinza,,Gri,Серый,Сива,Gri,Сірий, +",도움말 열기,Open hulp,Åpne Hjelp,Otwórz Pomoc,Abrir ajuda,,Deschide Ajutor,Экран помощи,Отвори помоћ,Öppna hjälp,Açık Yardım,Відкрити екран допомоги, +Open Save Menu,CNTRLMNU_OPEN_SAVE,,,,Uložit hru,Åbn menuen Gem,Speichermenü öffnen,Άνοιγμα μενού αποθήκευσης,Malfermi konservmenuon,Menú de guardar partida,,Avaa tallennusvalikko,Ouvrir Menu Sauvegarde,Mentés menü előhozása,Apri il menu di salvataggio,セーブメニューを開く,저장 화면 열기,Menu opslaan openen,Åpne Lagre-menyen,Otwórz Menu Zapisu,Abrir menu de salvar,Abrir Menu de Gravação,Deschide meniul de salvare,Меню сохранения игры,Отвори сачуване игре,Öppna sparmenyn,Kaydet Menüsünü Aç,Меню збережень, +Open Load Menu,CNTRLMNU_OPEN_LOAD,,,,Načíst hru,Åbn indlæsningsmenuen,Lademenü öffnen,Άνοιγμα μενού φόρτωσης,Malfermi ŝargmenuon,Menú de cargar partida,,Avaa latausvalikko,Ouvrir Menu Chargement,Betöltés menü előhozása,Apri il menu di caricamento,ロードメニューを開く,불러오기 화면 열기,Menu laden openen,Åpne Last-menyen,Otwórz Menu Wczytania,Abrir menu de carregar,,Deschide meniul de încărcare,Меню загрузки игры,Отвори игре за учитати,Öppna laddningsmenyn,Yük Menüsünü Aç,Меню завантаженнь, +Open Options Menu,CNTRLMNU_OPEN_OPTIONS,,,,Nastavení,Åbn menuen Indstillinger,Optionsmenü öffnen,Άνοιγμα μενού επιλογών,Malfermi agordmenuon,Menú de opciones,,Avaa asetusvalikko,Ouvrir Menu Options,Beállítások menü előhozása,Apri il menu delle opzioni,オプションメニューを開く,설정 화면 열기,Menu Opties openen,Åpne Alternativer-menyen,Otwórz Menu Opcji,Abrir menu de opções,,Deschide setările,Главное меню настроек,Отвори мени опција,Öppna alternativmenyn,Seçenekler Menüsünü Aç,Головне меню параметрів, +Open Display Menu,CNTRLMNU_OPEN_DISPLAY,,,,Nastavení grafiky,Åbn menuen Visning,Anzeigemenü öffnen,Άνοιγμα μενού οθόνης,Malfermi ekranmenuon,Menú de opciones de visualización,,Avaa näyttövalikko,Ouvrir Menu Affichage,Megjelenítés menü előhozása,Apri il menu del display,ディスプレイメニューを開く,디스플레이 화면 열기,Displaymenu openen,Åpne visningsmeny,Otwórz Menu Wyświetlania,Abrir menu de vídeo,,Deschide setările de afișare,Меню настроек видео,Отвори мени приказа,Öppna visningsmenyn,Ekran Menüsünü Aç,Параметри відео, +Quicksave,CNTRLMNU_QUICKSAVE,,,,Rychlé uložení,Quicksave,Schnellspeichern,Γρήγορη αποθήκευση,Rapidkonservo,Guardado rápido,,Pikatallenna,Sauv. Rapide,Gyorsmentés,Salvataggio rapido,クイックセーブ,빠른 저장,Snel opslaan,Hurtiglagring,Szybki Zapis,Salvar rapidamente,Gravação rápida,Salvare rapidă,Быстрое сохранение,Брзо-сачувај,Snabbspara,Hızlı Tasarruf,Швидке збереження, +Quickload,CNTRLMNU_QUICKLOAD,,,,Rychlé načtení,Quickload,Schnellladen,Γρήγορη φόρτωση,Rapidŝargo,Cargado rápido,,Pikalataa,Charg. Rapide,Gyorstöltés,Caricamento rapido,クイックロード,빠른 불러오기,Snel laden,Hurtiglasting,Szybkie Wczytanie,Carregar rapidamente,,Încărcare rapidă,Быстрая загрузка,Брзо-учитај,Snabbladdning,Hızlı Yükleme,Швидке завантаження, +Exit to Main Menu,CNTRLMNU_EXIT_TO_MAIN,,,,Odejít do hlavního menu,Afslut til hovedmenu,Zurück zum Hauptmenü,Έξοδος στο κύριο μενού,Eliri al ĉefa menuo,Salir al menú principal,,Poistu päävalikkoon,Sortie Menu Principal,Kilépés a főmenübe,Esci dal menu principale,メインメニューに戻る,메뉴로 나오기,Afsluiten naar het hoofdmenu,Avslutt til hovedmeny,Wyjdź do Głównego Menu,Sair para o menu principal,,Revenire la meniul principal,Выход в главное меню,Изађи у главни мени,Avsluta till huvudmenyn,Ana Menüden Çıkış,Вихід в головне меню, +Toggle Messages,CNTRLMNU_TOGGLE_MESSAGES,,,,Povolit/skrýt oznámení,Skift mellem meddelelser,Nachrichten an/aus,Εναλλαγή μηνυμάτων,Baskuligi mesaĝojn,Alternar mensajes,,Kytke viestit päälle tai pois,Messages On/Off,Üzenetek kapcsolása,Toggle messaggi,メッセージ表示の切替,메시지 토글,Berichten aan/uit,Veksle meldinger,Włącz / Wyłącz Wiadomości,Ativar/desativar mensagens,,Comutator mesaje,Переключение сообщений,Таглави поруке,Växla meddelanden,Mesajları Değiştir,Увімкнути повідомлення, +Quit Game,CNTRLMNU_MENU_QUIT,,,,Ukončit hru,Afslut spil,Spiel beenden,Στάματα το παιχνίδι,Mallanĉi ludon,Salir del juego,,Lopeta peli,Quitter le Jeu,Kilépés a játékból,Esci dal gioco,ゲームを終了,게임 종료,Stop het spel,Avslutt spill,Wyjdź z Gry,Sair do jogo,,Ieși din Joc,Выход,Изађи из игре,Avsluta spelet,Oyundan Çık,Вихід, +Adjust Gamma,CNTRLMNU_ADJUST_GAMMA,,,,Nastavit gamu,Juster Gamma,Gamma-Anpassung,Ρύθμιση Γάμμα,Agordi gamaon,Ajustar gama,,Säädä gammaa,Ajuster Gamma,Gamma állítása,Aggiustamento Gamma,ガンマ値を調整,감마 조정,Gamma aanpassen,Juster gamma,Dostosuj Gammę,Ajustar gama,,Ajustare gamma,Настройка гаммы,Подесите осветљење,Justera Gamma,Gama Ayarlama,Налаштування гамми, +,,Mouse,,,,,,,,,,,,,,,,,,,,,,,,,,, +Enable mouse,MOUSEMNU_ENABLEMOUSE,,,,Povolit myš,Aktiver mus,Maus aktiv,Ενεργοποίηση ποντικιόυ,Ebligi muson,Habilitar ratón,,Ota hiiri käyttöön,Activer Souris,Egér engedélyezése,Abilita il mouse,マウスの使用,마우스 사용,Muis inschakelen,Aktiver mus,Włącz myszkę,Ativar mouse,Permitir uso do rato,Activare mouse,Использовать мышь,Укључи миш,Aktivera musen,Fareyi etkinleştir,Увімкнути миш, +Enable mouse in menus,MOUSEMNU_MOUSEINMENU,,,,Povolit myš v nabídkách,Aktiver mus i menuer,Maus aktiv in Menüs,Ενεργοποίηση ποντικιόυ στα μενού,Ebligi muson en menuoj,Usa ratón en los menús,,Ota hiiri käyttöön valikoissa,Activer Souris dans les Menus,Egér engedélyezése a menüben,Abilita il mouse nei menu,メニューでのマウスの使用,메뉴에서 마우스 사용,Muis in menu's inschakelen,Aktiver mus i menyer,Włącz myszkę w menu,Ativar mouse nos menus,Permitir rato nos menus,Activare mouse în meniuri,Использовать мышь в меню,Укључи миш у менијима,Aktivera musen i menyer,Menülerde fareyi etkinleştir,Увімкнути миш в меню, +Show back button,MOUSEMNU_SHOWBACKBUTTON,,,,Zobrazit tlačítko zpět,Vis tilbage-knappen,Zeige Zurück-Knopf,Εμφάνιση του κουμπιού επιστροφής,Montri reen-butonon,Mostrar botón de retroceso,,Näytä taaksenäppäin,Afficher le bouton retour,Vissza gomb mutatása,Mostra il bottone per tornare indietro,戻るボタンを表示,뒤로가기 버튼 보이기,Toon terug knop,Vis tilbake-knapp,Pokaż przycisk powrotu,Exibir botão de voltar,,Afișare buton de întoarcere,Расположение кнопки «назад»,Прикажи тастер за назад,Visa bakåtknappen,Geri düğmesini göster,"Кнопка ""назад""", +Cursor,MOUSEMNU_CURSOR,,,,Kurzor,Markør,,Δρομέας,Musmontrilo,,,Osoitin,Curseur,Egérmutató,Cursore,カーソル,커서,,Markør,Kursor,Cursor,,,Курсор,Курсор,Markör,İmleç,Курсор, +Horizontal sensitivity,MOUSEMNU_SENSITIVITY_X,,,,Horizontální citlivost,Vandret følsomhed,Horizontale Empfindlichkeit,Οριζόντια ευαισθησία,Horizontala sentemo,Sensibilidad horizontal,,Vaakasuuntainen herkkyys,Sensibilité horizontale,Vízszintes érzékenység,Sensibilità orizzontale,水平感度,수평 감도,Horizontale gevoeligheid,Horisontal følsomhet,Czułość pozioma,Sensibilidade horizontal,,Sensibilitate orizontală,Горизонтальная чувствительность,Хоризонтална осетљивост,Horisontell känslighet,Yatay hassasiyet,Горизонтальна чутливість, +Vertical sensitivity,MOUSEMNU_SENSITIVITY_Y,,,,Vertikální citlivost,Lodret følsomhed,Vertikale Empfindlichkeit,Κάθετη ευαισθησία,Vertikala sentemo,Sensibilidad vertical,,Pystysuuntainen herkkyys,Sensibilité verticale,Függőleges érzékenység,Sensibilità verticale,垂直感度,수직 감도,Verticale gevoeligheid,Vertikal følsomhet,Czułość pionowa,Sensibilidade vertical,,Sensibilitate verticală,Вертикальная чувствительность,Вертикална осетљивост,Vertikal känslighet,Dikey hassasiyet,Вертикальна чутливість, +Smooth mouse movement,MOUSEMNU_SMOOTHMOUSE,,,,Vyhladit pohyb myši,Jævn bevægelse af musen,Mausbewegung glätten,Ομαλή κίνηση του ποντικιού,Glata musmovo,Mov. fluido del ratón,,Sulava hiiren liike,Lissage Souris,Egérmozgás simítása,Movimento del mouse liscio,マウス操作を滑らかにする,부드러운 움직임,Vlotte muisbeweging,Jevn musebevegelse,Gładki ruch myszki,Suavizar movimento do mouse,Movimento fluído do rato,Mișcare mouse fină,Плавное перемещение,Глатки окрет,Smidig musrörelse,Pürüzsüz fare hareketi,Плавний рух миші, +Turning speed,MOUSEMNU_TURNSPEED,,,,Rychlost otáčení,Drejehastighed,Umdrehgeschwindigkeit,Ταχύτητα περιστροφής,Turnorapido,Velocidad de giro,,Kääntymisnopeus,Vitesse pour tourner,Fordulás sebessége,Velocità di rotazione,旋回速度,회전 속도,Draaisnelheid,Dreiehastighet,Szybkość obracania się,Velocidade de giro,,Viteză rotire,Скорость поворота,Брзина окрета,Vändningshastighet,Dönüş hızı,Швидкість повороту, +Mouselook speed,MOUSEMNU_MOUSELOOKSPEED,,,,Rychlost pohledu nahoru/dolů,Hastighed for mus-look,Mausblick-Geschwindigkeit,Ταχύτητα εμφάνισης ποντικιού,Musrigarda rapido,Veloc. de vista con ratón,,Katselunopeus,Vitesse Vue Souris,Egérnézés sebessége,Velocità di rotazione della vista,上下視点速度,마우스룩 속도,Mouselook snelheid,Muselook-hastighet,Szybkość rozglądania się myszką,Velocidade da visão com mouse,Velocidade de vista com rato,Viteză privire în jur cu mouse,Скорость обзора,Брзина гледања мишем,Hastighet för muspekning,Mouselook hızı,Швидкість огляду, +Forward/Backward speed,MOUSEMNU_FORWBACKSPEED,,,,Rychlost pohybu vpřed/vzad,Hastighed fremad/tilbage,Vor/Rückwärtsgeschwindigkeit,Ταχύτητα προς τα εμπρός/πίσω,Antaŭa/Malantaŭa rapido,Veloc. de avance/retroceso,,Eteen-/taaksepäin liikkeen nopeus,Vitesse Avancer/reculer,Előre/Hátra sebesség,Velocità avanti/indietro,"前進/後退速度 +",전진/후진 속도,Voorwaartse/achterwaartse snelheid,Hastighet forover/bakover,Szybkość chodzenia do przodu/do tyłu,Velocidade de deslocamento para frente/trás,,Viteză deplasare față/spate,Скорость передвижения,Брзина окрета напред/уназад,Hastighet framåt/bakåt,İleri/Geri hız,Швидкість руху вперед/назад, +Strafing speed,MOUSEMNU_STRAFESPEED,,,,Rychlost pohybu do stran,Strafing-hastighed,Seitwärtsgeschwindigkeit,Ταχύτητα καταδίωξης,Flankmova rapido,Veloc. de mov. lateral,,Sivuttaisastunnan nopeus,Vitesse Gauche/Droite,Oldalazás sebessége,Velocità movimento laterale,横移動速度,좌진/우진 속도,Zijdelings snelheid,Hastigheten for stansing,Szybkość uników,Velocidade de deslocamento lateral,,Viteză deplasare în diagonală,Скорость движения боком,Брзина стрејфа,Hastighet för strafe,Strafe hızı,Швидкість руху боком, +Always Mouselook,MOUSEMNU_ALWAYSMOUSELOOK,,,,Vždy se rozhlížet myší,Altid mus-look,Mausblick immer an,Πάντα κοίτα με το ποντίκι,Ĉiam musrigardi,Siempre mirar con ratón,,Jatkuva hiirikatselu,Toujours vue Souris,Mindig egérrel nézelődés,Vista col mouse,常に上下視点をオン,마우스룩 사용,Altijd Mouselook,Alltid muselook,Zawsze zezwalaj na rozglądanie się myszką,Visão com mouse sempre ativada,Vista com rato sempre ligada,Privire în jur cu mouse permanentă,Обзор мышью,Гледање мишем,Alltid muspekande,Her zaman Mouselook,Огляд мишкою, +Invert Mouse Y,MOUSEMNU_INVERTMOUSE,,,,Vertikálně obrátit myš,Inverter mus Y,Maus Y invertieren,Αντιστροφή ποντικιού Y,Inversi muson Y,Invertir ratón Y,,Käännä hiiri Y,Inverser Souris Y,Y tengely megfordítása,Mouse Y invertito,視点操作反転,마우스 방향 전환,Muis-Y-as omkeren,Inverter mus Y,Odwróć Myszkę - Oś Y,Inverter eixo Y do mouse,Inverter rato,Inversare axă mouse Y,Инверт. мышь по вертикали (Y),Инвертуј миш Y,Invertera mus Y,Fare Y'yi Ters Çevir,Інвертувати мишу Y, +Invert Mouse X,MOUSEMNU_INVERTMOUSEX,,,,Horizontálně obrátit myš,Inverter mus X,Maus X invertieren,Αντιστροφή ποντικιού X,Inversi muson X,Invertir ratón X,,Käännä hiiri X,Inverser Souris X,X tengely megfordítása,Mouse X invertito,視点操作反転,마우스 방향 전환,Muis-X-as omkeren,Inverter mus X,Odwróć Myszkę - Oś X,Inverter eixo X do mouse,Inverter rato X,Inversare axă mouse X,Инверт. мышь по горизонтали (X),Инвертуј миш X,Invertera mus X,Fare X'i Ters Çevir,Інвертувати мишу Х, +Upper left,OPTVAL_UPPERLEFT,,,,Vlevo nahoře,Øverste venstre,Oben links,Πάνω αριστερά,Supra maldekstre,Sup. izquierda,,Ylävasemmalla,Supérieur gauche,Bal fent,Superiore sinistro,左上,왼쪽 위,Linksboven,Øvre venstre,Lewy górny róg,Esquerda superior,,Stânga sus,Вверху слева,Горње лево,Övre vänster,Sol üst,"Кнопка ""назад"": Зверху-ліворуч", +Upper right,OPTVAL_UPPERRIGHT,,,,Vpravo nahoře,Øvre højre,Oben rechts,Πάνω δεξιά,Supra dekstre,Sup. derecha,,Yläoikealla,Supérieur droite,Jobb fent,Superiore destro,右上,오른쪽 위,Rechtsboven,Øverst til høyre,Prawy górny róg,Direita superior,,Dreapta sus,Вверху справа,Горње десно,Övre höger,Sağ üst,"Кнопка ""назад"": Зверху-праворуч", +Lower left,OPTVAL_LOWERLEFT,,,,Vlevo dole,Nederste venstre,Unten links ,Κάτω αριστερά,Suba maldekstre,Inf. izquierda,,Alavasemmalla,Inférieur gauche,Bal lent,Inferiore sinistro,左下,왼쪽 밑,Linksonder,Nedre venstre,Lewy dolny róg,Esquerda inferior,,Stânga jos,Внизу слева,Доње лево,Nedre vänster,Sol alt,"Кнопка ""назад"": Знизу-ліворуч", +Lower right,OPTVAL_LOWERRIGHT,,,,Vpravo dole,Nederste højre,Unten rechts,Κάτω δεξιά,Suba dekstre,Inf. derecha,,Alaoikealla,Inférieur droite,Jobb lent,Inferiore destro,右下,오른쪽 밑,Rechtsonder,Nedre høyre,Prawy dolny róg,Direita inferior,,Dreapta jos,Внизу справа,Доње десно,Nedre höger,Sağ alt,"Кнопка ""назад"": Знизу-праворуч", +Touchscreen-like,OPTVAL_TOUCHSCREENLIKE,,,,Jako dotyková obrazovka,Touchscreen-lignende,Wie auf einem Touchscreen,Οθόνη αφής,Tuŝekraneca,Pant. táctil,,Kosketusnäyttömäinen,Style écran tactile,Érintőképernyő-szerű,Come il Touchscreen,タッチスクリーン式,터치스크린 같게,Touchscreen-achtige,Berøringsskjerm-lignende,Jak ekrean dotykowy,Estilo touchscreen,,Precum touchscreen,Как сенсорный экран,Као додирни екран,Pekskärmsliknande,Dokunmatik ekran benzeri,Як сенсорний екран, +Simple arrow,OPTSTR_SIMPLEARROW,,,,Jednoduchý kurzor,Simpel pil,Einfacher Pfeil,Απλό βέλος,Simpla sago,Flecha simple,,Yksinkertainen nuoli,Flèche simple,Sima nyíl,Freccia semplice,シンプル,기본 커서,Eenvoudige pijl,Enkel pil,Prosta strzałka,Seta simples,Cursor simples,Săgeată simplă,Стрелка,Стрелица,Enkel pil,Basit ok,Стрілка, +System cursor,OPTSTR_SYSTEMCURSOR,,,,Systémový kurzor,Systemcursor,Systemcursor,Δείκτης συστήματος,Sistema kursoro,Cursor del sistema,,Järjestelmän osoitin,Curseur Système,Rendszer egérmutatója,Cursore di sistema,システム,시스템 커서,Systeemcursor,Systemmarkør,Kursor systemu,Cursor do sistema,,Cursor simplu,Системный курсор,Системска стрелица,Systemmarkör,Sistem imleci,Системний курсор, +Default,OPTVAL_DEFAULT,,,,Výchozí,Standard,Standard,Προεπιλογή,Defaŭlta,Por defecto,,Oletus,Défaut,Alapbeállítás,Predefinito,デフォルト,기본 설정,Standaard,Standard,Domyślne,Padrão,,Implicit,По умолчанию,Подраз.,Standard,Varsayılan,За замовчуванням, +,,Controller,,,,,,,,,,,,,,,,,,,,,,,,,,, +Configure Controller,JOYMNU_TITLE,,,,Konfigurace ovladače,Konfigurer controller,Controller konfigurieren,,Agordi ludregilon,Configurar mando,,Peliohjainasetukset,Configurer Mannette,Kontroller testreszabása,Configura il controller,コントローラー構成:,컨트롤러 구성,Controller configureren,Konfigurer kontrolleren,Konfiguruj Kontroler,Configurar controle,Configurar Comando,Configurare controller,Настроить контроллер,Конфигурација контролера,Konfigurera kontroller,Denetleyiciyi Yapılandırma,Параметри контролера, +Controller Options,JOYMNU_OPTIONS,,,,Ovladač,Indstillinger for styreenhed,Controlleroptionen,,Ludregilo-agordoj,Opciones del mando,,Peliohjainasetukset,Options Mannette,Kontroller beállítások,Opzioni del controller,コントローラー設定,컨트롤러 설정,Controller opties,Alternativer for styreenhet,Opcje Kontrolera,Opções de controle,Opções do Comando,Setări controller,Настройки контроллера,Подешавања контролера,Alternativ för kontroller,Kontrolör Seçenekleri,Налаштування контролера, +Block controller input in menu,JOYMNU_NOMENU,,,,Zakázat ovladač v nabídkách,Bloker controller input i menuen,Blockiere Controllereingabe im Menü,,Blokigi ludregilan enigon en menuo,Bloq. entrada de mando en menú,,Estä ohjainsyötteet valikoissa,Bloquer manette dans les menus,Kontroller ne működjön a menüben,Blocca l'input del controller nei menu,メニューではコントローラーを無視,메뉴에서 컨트롤러 끄기,Blokkeer de controller in het menu,Blokker kontrollerinngang i menyen,Blokuj wejście kontrolera w menu,Bloquear controle no menu,Bloquear comando no menu,Blocare comenzi controller în meniu,Отключить контроллер в меню,Блокирај улаз контролера у менију,Blockera inmatning av kontroller i menyn,Menüde kontrolör girişini engelle,Відключити контролер в меню, +Enable controller support,JOYMNU_ENABLE,,,,Povolit podporu pro ovladače,Aktivering af controllerunderstøttelse,Erlaube Controllerunterstützung,,Ŝalti ludregilan subtenon,Activar soporte de mandos,,Ota käyttöön peliohjaintuki,Activer support contrôleur,Kontroller támogatás engedélyezése,Abilita il supporto del controller,コントローラーサポート許可,컨트롤러 지원 허용,Controllerondersteuning inschakelen,Aktiver støtte for styreenhet,Włącz wsparcie kontrolera,Ativar detecção de controles,,Activare support controller,Включить поддержку контроллера,Омогући подршку за контролере,Aktivera stöd för kontroller,Denetleyici desteğini etkinleştir,Увімкнути підтримку контролера, +Enable DirectInput controllers,JOYMNU_DINPUT,,,,Povolit ovladače DirectInput,Aktivering af DirectInput-controllere,Erlaube DirectInput-Controller,,Ŝalti DirectInput ludregilojn,Usa controles DirectInput,,Ota käyttöön DirectInput-ohjaimet,Activer contrôleurs DirectInput,DirectInput kontrollerek engedélyezése,Abilita i controlli DirectInput,ダイレクトインプットコントローラー許可,다이렉트 인풋 컨트롤러 허용,DirectInput-controllers inschakelen,Aktiver DirectInput-kontrollere,Włącz kontrolery DirectInput,Ativar controles DirectInput,,Activare controlere DirectInput,Включить контроллеры через DirectInput,Омогући директинпут контролере,Aktivera DirectInput-kontroller,DirectInput denetleyicilerini etkinleştirin,Увімкнути контролери DirectInput, +Enable XInput controllers,JOYMNU_XINPUT,,,,Povolit ovladače XInput,Aktiver XInput-controllere,Erlaube XInput-Controller,,Ŝalti XInput ludregilojn,Usa controles XInput,,Ota käyttöön XInput-ohjaimet,Activer contrôleurs XInput,XInput kontrollerek engedélyezése,Abilita i controlli XInput,Xinput コントローラー許可,X인풋 컨트롤러 허용,XInput-controllers inschakelen,Aktiver XInput-kontrollere,Włącz kontrolery XInput,Ativar controles XInput,,Activare controlere XInput,Включить контроллеры через XInput,Омогући Иксинпут контролере,Aktivera XInput-kontroller,XInput denetleyicilerini etkinleştirin,Увімкнути контролери XInput, +Enable raw PlayStation 2 adapters,JOYMNU_PS2,,,,Povolit ovladače PlayStation 2,Aktiver rå PlayStation 2-adaptere,Erlaube Playstation 2-Controller,,Ŝalti krudajn adaptilojn de PlayStation 2 ,Usa adaptadores de PlayStation 2,,Ota käyttöön raa'at PlayStation 2 -adapterit,Activer adaptateurs PS2 bruts,PlayStation 2 adapterek engedélyezése,Abilita gli adattatori raw PlayStation 2,PlayStation2 アダプター許可,PS2 어뎁터 허용,Raw PlayStation 2-adapters inschakelen,Aktiver rå PlayStation 2-adaptere,Włącz adaptery PlayStation 2,Ativar adaptadores de PlayStation 2,,Activare adaptoare PS2,Использовать адаптеры PlayStation 2 напрямую,Омогући сирове Плејстејшн 2 адаптере,Aktivera råa PlayStation 2-adaptrar,Ham PlayStation 2 adaptörlerini etkinleştirin,Використовувати адаптери PlayStation 2 напряму, +No controllers detected,JOYMNU_NOCON,,,,Nenalezeny žádné ovladače.,Ingen controllere er fundet,Keine Controller gefunden,,Neniu ludregilo detektita,No hay mandos detectados,,Ei havaittuja ohjaimia,Aucun Contrôleur détecté.,Nem érzékelhető kontroller,Nessun controller trovato,コントローラーが見つかりません,인식된 컨트롤러 없음,Geen controllers gedetecteerd,Ingen kontrollere oppdaget,Nie wykryto kontrolerów,Nenhum controle detectado.,Nenhum comando foi detectado,Niciun controller detectat,Контроллеры не обнаружены,Нема детектованих контролера,Inga kontroller upptäcks,Denetleyici algılanmadı,Контролерів не виявлено, +Configure controllers:,JOYMNU_CONFIG,,,,Nastavit ovladače:,Konfigurer controllere:,Controller konfigurieren,,Agordi ludregilojn:,Configurar controles:,,Mukauta ohjaimia:,Configurer contrôleurs:,Kontrollerek konfigurációja:,Configura i controller:,コントローラー構成:,컨트롤러 설정:,Configureer controllers:,Konfigurer kontrollere:,Konfiguruj kontrolery:,Configurar controles:,Configurar comandos,Configurare controlere:,Настроить контроллер:,Подешавања контролере:,Konfigurera kontroller:,Denetleyicileri yapılandırın:,Налаштувати контролери, +Controller support must be,JOYMNU_DISABLED1,,,,Pro nalezení ovladačů musí,Der skal være støtte til controlleren,Controllerunterstütung muss aktiviert sein,,Ludregilo-subteno devas esti,El soporte de mandos debe estar,,Ohjaintuen täytyy olla otettu,Le Support de contrôleur doit être activé,A kontroller támogatásnak,Il supporto ai controller deve essere,コントローラーサポートは,감지하려면 컨트롤러 지원을,Controller ondersteuning moet ingeschakeld zijn,Støtte for kontrollere må være,Wsparcie kontrolera musi być,A detecção de controles deve,Suporte a comandos devem ser,Supportul pentru controller trebuie,Включите поддержку контроллера,Омогућите подржавање контролера,Stöd för kontroller måste vara aktiverat,Denetleyici desteği şu şekilde olmalıdır,Включіть підтримку контролерів, +enabled to detect any,JOYMNU_DISABLED2,Supposed to be empty in Russian and Serbian.,,,být zapnuta jejich podpora.,aktiveret for at registrere enhver,um welche zu finden,,ŝaltita por detekti iun ajn,activado para detectar alguno,,käyttöön ohjainten havaitsemiseksi,avant de pouvoir en détecter un.,"engedélyezve kell lenni, hogy érzékeljen bármit is.",abilitato a trovare ogni,検出しました,활성화 해야합니다.,om eventuele regelaars te detecteren.,aktivert for å oppdage en hvilken som helst,Włączony by wykryć jakikolwiek,ser ativada para exibi-los.,,activat pentru a putea fi detectate, \n, \n,för att det ska gå att upptäcka några,tespit etmek için etkinleştirildi, \n, +Invalid controller specified for menu,JOYMNU_INVALID,,,,Vybrán nesprávný ovladač pro nabídky,Ugyldig controller angivet til menuen,Ungültiger Controller für Menü ausgewählt,,Nevalida ludregilo specifigita por menuo,Mando inválido especificado para el menú,,Epäkelpo ohjain määritetty valikolle,Contrôleur invalide spécifé dans le menu.,Hibás kontroller van a menühöz osztva,Controller invalido specificato per il menu,メニューではコントローラーを使用しない,메뉴에 특정된 컨트롤러가 아닙니다.,Ongeldige regelaar gespecificeerd voor het menu,Ugyldig kontroller spesifisert for menyen,Niewłaściwy kontroler określony dla menu,Controle inválido especificado para o menu.,Comando inválido,Controller pentru meniu invalid,Недопустимый контроллер выбран для меню,Невалидан контролер специфиран за мени,Ogiltig kontroller har angetts för menyn,Menü için geçersiz denetleyici belirtildi,Для меню вибрано невідповідний контролер, +Overall sensitivity,JOYMNU_OVRSENS,,,,Celková citlivost,Samlet følsomhed,Allgemeine Empfindlichkeit,,Tuta sentemeco,Sensibilidad general,,Yleisherkkyys,Sensibilité générale,Teljes érzékenység,Sensibilità generale,全体的な感度,전체 민감도,Algemene gevoeligheid,Samlet følsomhet,Ogólna Czułość,Sensibilidade geral,,Sensibilitate în ansamblu,Общая чувствительность,Уупна сензитивност,Övergripande känslighet,Genel hassasiyet,Загальна чутливість, +Axis Configuration,JOYMNU_AXIS,,,,Nastavení os,Konfiguration af akserne,Achsenkonfiguration,,Akso-agordoj,Configuración del eje,,Akseleiden säätäminen,Configuration des axes,Tengely konfigurálása,Configurazione assi,軸構成,축 구성,Asconfiguratie,Konfigurasjon av akse,Konfiguruj Oś,Configuração de eixo,,Configurare axă,Конфигурация осей,Конфигурација осе,Konfiguration av axlar,Eksen Konfigürasyonu,Конфігурація осей, +Invert,JOYMNU_INVERT,,,,Obrátit,Invert,Invertieren,,Inversigi,Invertir,,Käännä,Inverser,Megfordítás,Inverti,反転,순서 바꿈,Omkeren,Invertering,Odwróć,Inverter,,Inversare,Инвертировать,Инвертовано,Invertera,Ters çevir,Інвертувати, +Dead zone,JOYMNU_DEADZONE,,,,Mrtvá zóna,Dødzone,Totzone,,Mortozono,Zona muerta,,Kuollut alue,Zone neutre,Holttér,Zona cieca,デッドゾーン,불감대,Dode zone,Død sone,Martwa strefa,Zona morta,,Zonă moartă,Мёртвая зона,Мртва зона,Dödzon,Ölü bölge,Мертва зона, +No configurable axes,JOYMNU_NOAXES,,,,Žádné nastavitelné osy,Ingen konfigurerbare akser,Keine konfigurierbaren Achsen,,Neniuj agordeblaj aksoj,No hay ejes configurables,,Ei säädettäviä akseleita,Aucun axe à configurer,Nincs beállítható tengely,Nessun asse configurabile,軸構成を無効,설정할 방향키가 없습니다.,Geen configureerbare assen,Ingen konfigurerbare akser,Brak osi do skonfigurowania,Nenhum eixo configurável,,Nicio axă configurabilă,Нет настраиваемых осей,Нема конфигурационих оса,Inga konfigurerbara axlar,Yapılandırılabilir eksen yok,Немає настроюваних осей, +None,OPTVAL_NONE,,,,Žádný,Ingen,Kein,,Neniu,Ninguno,,Ei mitään,Aucun,Nincs,Nessuno,無し,없음,Geen,Ingen,Żaden,Nenhum,,Niciuna,Откл.,Ништа,Ingen,Hiçbiri,Вимк., +Turning,OPTVAL_TURNING,,,,Otáčení,Drejning,Umdrehen,,Turnanta,Girar,,Kääntyminen,Tourner,Fordulás,Rotazione,旋回,회전,Draaien,Dreie,Obracanie się,Girar,,Rotire,Поворот,Скретање,Vridning,Dönüş,Поворот, +Looking Up/Down,OPTVAL_LOOKINGUPDOWN,,,,Dívání se nahoru/dolů,Kigger op/ned,Hoch/runterblicken,,Rigardanta (mal)supren,Mirar hacia arriba/abajo,,Ylös/Alas katsominen,Vue haut/bas,Fel-/lenézés,Sguardo Sopra/Sotto,視点上下,위/아래로 보기,Omhoog/omlaag zoeken,Ser opp/ned,Patrzenie w górę/w dół,Olhar para cima/baixo,,Privire Sus/Jos,Взгляд вверх/вниз,Гледање горе/доле,Titta uppåt/nedåt,Yukarı/Aşağı Bakmak,Дивитись вгору, +Moving Forward,OPTVAL_MOVINGFORWARD,,,,Pohyb vpřed,Bevæger sig fremad,Vorwärtsbewegung,,Movanta antaŭen,Avanzar,,Eteenpäin liikkuminen,Avancer,Előre mozgás,Movimento in avanti,前進,앞으로 전진,Voorwaarts bewegen,Beveger seg fremover,Poruszanie się do przodu,Mover-se para a frente,,Deplasare în Față,Движение вперёд,Кретање напред,Rör sig framåt,İleriye Doğru,Рухатись вперед, +Strafing,OPTVAL_STRAFING,,,,Pohyb do stran,Strafing,Seitwärtsbewegung,,Flankmovanta,Desplazarse,,Sivuttaisastunta,Pas de côté,Oldalazás,Movimento laterale,横移動,양옆으로 이동,Strafelen,Straffe,Uniki,Deslocamento lateral,,Deplasare în Diagonală,Движение боком,Кретање у страну,Strafing,Strafing,Рухатись боком, +Moving Up/Down,OPTVAL_MOVINGUPDOWN,,,,Pohyb nahoru/dolů,Bevægelse op/ned,Auf/abwärtsbewegung,,Movanta (mal)supren,Moverse hacia arriba/abajo,,Ylös/Alas liikkuminen,Mouvement haut/bas,Felfele/Lefele mozgás,Movimento Sopra/Sotto,前進後退,위/아래로 이동,Naar boven/beneden bewegen,Beveger seg opp/ned,Poruszanie się w górę/w dół,Mover-se para cima/baixo,,Mișcare Sus/Jos,Движение вверх/вниз,Кретање горе/доле,Rör sig uppåt/nedåt,Yukarı/Aşağı Hareket Etme,Рухатись вгору/вниз, +Inverted,OPTVAL_INVERTED,,,,Inverzní,Omvendt,Invertiert,,Inversigita,Invertido,,Käännetty,Inversé,Felcserélve,Invertito,反転する,반전,Omgekeerd,Invertert,Odwrócony,Invertido,,Inversat,Инвертировано,Обрнуто,Inverterad,Ters çevrilmiş,Інвертовано, +Not Inverted,OPTVAL_NOTINVERTED,,,,Neinverzní,Ikke omvendt,nicht invertiert,,Ne inversigita,No invertido,,Ei käännetty,Non Inversé,Nincs felcserélve,Non invertito,反転しない,반전되지 않음,Niet omgekeerd,Ikke invertert,Nieodwrócony,Não invertido,,Neinversat,Прямо,Не обрнуто,Inte inverterad,Ters Çevrilmemiş,Не інвертовано, +,,Player Menu,,,,,,,,,,,,,,,,,,,,,,,,,,, +Blue,TXT_COLOR_BLUE,,,,Modrá,Blå,Blau,Μπλέ,Blua,Azul,,Sininen,Bleu,Kék,Blu,青,청색,Blauw,Blå,Niebieski,Azul,,Albastru,Синий,Плава,Blå,Mavi,Синій, +Red,TXT_COLOR_RED,,,,Červená,Rød,Rot,Κόκκινο,Ruĝa,Rojo,,Punainen,Rouge,Vörös,Rosso,赤,적색,Rood,Rød,Czerwony,Vermelho,,Roșu,Красный,Црвена,Röd,Kırmızı,Червоний, +Green,TXT_COLOR_GREEN,,,,Zelená,Grøn,Grün,Πράσινο,Verda,Verde,,Vihreä,Vert,Zöld,Verde,緑,녹색,Groen,Grønn,Zielony,Verde,,Verde,Зелёный,Зелена,Grön,Yeşil,Зелений, +Gray,TXT_COLOR_GRAY,,,Grey,Šedá,Grå,Grau,Γκρί,Griza,Gris,,Harmaa,Gris,Szürke,Grigio,灰,회색,Grijs,Grå,Szary,Cinza,,Gri,Серый,Сива,Grå,Gri,Сірий, Dark gray,TXT_COLOR_DARKGRAY,,,"Dark grey -",Tmavě šedá,Mørkegrå,Dunkelgrau,Σκοτεινό γρκί,Malhelgriza,Gris oscuro,,Tummanharmaa,Gris sombre,Sötétszürke,Grigio scuro,鉛,치색,Donkergrijs,Mørkegrå,Ciemnoszary,Cinza escuro,,Gri închis,Тёмно-серый,Тамно сива,Koyu gri,Темно-сірий, -Dark Green,TXT_COLOR_DARKGREEN,,,,Tmavě zelená,Mørkegrøn,Dunkelgrün,Σκοτεινό πράσινο,Malhelverda,Verde oscuro,,Tummanvihreä,Vert sombre,Sötétzöld,Verde scuro,深,흑녹색,Donkergroen,Mørkegrønn,Ciemnozielony,Verde escuro,,Verde închis,Тёмно-зелёный,Тамна зелена,Koyu Yeşil,Темно-зелений, -Brown,TXT_COLOR_BROWN,,,,Hnědá,Brun,Braun,Σκούρο,Bruna,Marrón,,Ruskea,Brun,Barna,Marrone,茶,갈색,Bruin,Brun,Brązowy,Marrom,,Maro,Коричневый,Браон,Kahverengi,Коричневий, -Dark Blue,TXT_COLOR_DARKBLUE,,,,Tmavě modrá,Mørk blå,Dunkelblau,Σκοτεινό μπλέ,Malhelblua,Azul oscuro,,Tummansininen,Bleu sombre,Sötétkék,Blu scuro,紺,,Donkerblauw,Mørkeblå,Ciemnoniebieski,Azul escuro,,Albastru închis,Тёмно-синий,Тамна Плава,Koyu Mavi,Темно-синій, -Light Red,TXT_COLOR_LIGHTRED,,,,Světle červená,Lysrød,Hellrot,Ανοιχτό κόκκινο,Helruĝa,Rojo claro,,Vaaleanpunainen,Rouge clair,Világospiros,Rosso chiaro,丹,옅은 적색,Licht Rood,Lys rød,Jasnoczerwony,Vermelho claro,,Roșu deschis,Светло-красный,Светло црвена,Açık Kırmızı,Світло-червоний, -Yellow,TXT_COLOR_YELLOW,,,,Žlutá,Gul,Gelb,Κίτρινο,Flava,Amarillo,,Keltainen,Jaune,Sárga,Giallo,黄,노란색,Geel,Gul,Żółty,Amarelo,,Galben,Жёлтый,Жута,Sarı,Жовтий, -Purple,TXT_COLOR_PURPLE,,,,Fialová,Lilla,Violett,Μόβ,Purpura,Morado,,Purppura,Violet,Lila,Viola,紫,보라색,Paars,Lilla,Fioletowy,Roxo,,Mov,Фиолетовый,Љубичаста,Mor,Фіолетовий, -Olive,TXT_COLOR_DULLGREEN,,,,Bledě zelená,Oliven,Blassgrün,,Olivkolora,Oliva,,Haaleanvihreä,Vert pâle,Olíva,Verde pallido,苔,암녹색,Saaie groen,Oliven,Matowa Zieleń,Verde oliva,,Măsliniu,Мутно-зелёный,Тупа зелена,Zeytin,Темний жовто-зелений, -Beige,TXT_COLOR_BEIGE,,,,Béžová,Beige,,Μπέζ,Flavgriza,Beis,Beige,Beesi,,Bézs,,淡,담갈색,Beige,Beige,Beżowy,Bege,,Bej,Бежевый,Беж,Bej,Бежевий, -Light Green,TXT_COLOR_LIGHTGREEN,,,,Světle zelená,Lysegrøn,Hellgrün,Ανοιχτό Πράσινο,Helverda,Verde claro,,Vaaleanvihreä,Vert clair,Világoszöld,Verde chiaro,葵,옅은 녹색,Licht groen,Lysegrønn,Jasonzielony,Verde claro,,Verde Deschis,Светло-зелёный,Светло зелена,Açık Yeşil,Світло-зелений, -Light Blue,TXT_COLOR_LIGHTBLUE,,,,Světle modrá,Lys blå,Hellblau,Γαλάζιο,Helblua,Azul claro,,Vaaleansininen,Bleu clair,Világoskék,Blu chiaro,空,옅은 청색,Licht blauw,Lyseblå,Jasnoniebieski,Azul claro,,Albastru Deschis,Светло-синий,Светло плава,Açık Mavi,Світло-синій, -Light Gray,TXT_COLOR_LIGHTGRAY,,,Light Grey,Světle šedá,Lysegrå,Hellgrau,Ανοιχτό Γκρι,Helgriza,Gris claro,,Vaaleanharmaa,Gris clair,Világosszürke,Grigio chiaro,鉛,옅은 회색,Lichtgrijs,Lysegrå,Jasnoszary,Cinza claro,,Gri Deschis,Светло-серый,Светло сива,Açık Gri,Світло-сірий, -Light Brown,TXT_COLOR_LIGHTBROWN,,,,Světle hnědá,Lys brun,Hellbraun,Ανοιχτό Καφέ,Helbruna,Marrón claro,,Vaaleanruskea,Brun clair,Világosbarna,Marrone chiaro,褐,옅은 고동색,Lichtbruin,Lysebrun,Jasnobrązowy,Marrom claro,,Maro Deschis,Светло-коричневый,Светло браон,Açık Kahverengi,Світло-коричневий, -Gold,TXT_COLOR_GOLD,,,,Zlatá,Guld,,Χρυσό,Orkolora,Dorado,,Kulta,Or,Arany,Oro,金,금색,Goud,Gull,Złoty,Dourado,,Auriu,Золотой,Златна,Altın,Золотий, -Bright Green,TXT_COLOR_BRIGHTGREEN,,,,Jasně zelená,Lysegrøn,Hellgrün,Φωτινό Πράσινο,Brilverda,Verde claro,,Vaaleanvihreä,Vert clair,Fényeszöld,Verde chiaro,鮮,밝은 녹색,Helder groen,Lysegrønn,Jasnozielony,Verde claro,,Verde Deschis,Ярко-зелёный,Светла зелена,Parlak Yeşil,Яскраво-зелений, -Rust,TXT_COLOR_RUST,,,,Rezavá,Rust,Rostbraun,Σκουριά,Rustokolora,Óxido,,Ruoste,Rouille,Rozsda,Arrugginito,錆,주황 적갈색,Roest,Rust,Rdzawy,Ferrugem,,Ruginiu,Ржавый,Рђа,Pas,Іржавий, -Name,PLYRMNU_NAME,,,,Jméno,Navn,,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Navn,Imię,Nome,,Nume,Имя,Надимак,İsim,Ім'я, -Team,PLYRMNU_TEAM,,,,Tým,,,Ομάδα,Teamo,Equipo,,Joukkue,Equipe,Csapat,Squadra,チーム,팀,Team,Lag,Drużyna,Equipe,Equipa,Echipă,Команда,Тим,Takım,Команда, -Color,PLYRMNU_PLAYERCOLOR,,,Colour,Barva,Farve,Farbe,Χρώμα,Koloro,,,Väri,Couleur,Szín,Colore,色,색상,Kleur,Farge,Kolor,Cor,,Culoare,Цвет,Боја,Renk,Колір, -Gender,PLYRMNU_PLAYERGENDER,,,,Pohlaví,Køn,Geschlecht,Φύλο,Genro,Género,,Sukupuoli,Genre,Nem,Sesso,性別,성별,Geslacht,Kjønn,Płeć,Gênero,,Sex,Пол,Пол,Cinsiyet,Стать, -Male,OPTVAL_MALE,,,,Muž,Mand,Männlich,Αρσενικό,Vira,Masculino,,Miespuolinen,Masculin,Férfi,Maschio,男,남성,Man,Mannlig,Mężczyzna,Masculino,,Masculin,Мужской,Мушко,Erkek,Чоловіча, -Female,OPTVAL_FEMALE,,,,Žena,Kvinde,Weiblich,Θηλυκό,Ina,Femenino,,Naispuolinen,Féminin,Nő,Femmina,女,여성,Vrouw,Kvinne,Kobieta,Feminino,,Feminin,Женский,Женско,Kadın,Жіноча, -Neutral,OPTVAL_NEUTRAL,,,,Neutrální,Neutral,Neutral,Ουδέτερο,Neŭtra (Ri),Neutro,,Sukupuoleton,Neutre,Semleges,Neutrale,中間,중성,Neutraal,Nøytral,Neutralne,Neutro,,Neutru,Нейтральный,Неутрално,Nötr,Нейтральна, -Object,OPTVAL_OTHER,,,,Objekt,Objekt,Objekt,Αντικείμενο,Objekto (Ĝi),Objeto,,Olio,Objet,Tárgy,Oggetto,物体,기타,Doel,Gjenstand,Obiekt,Objeto,,Obiect,Предмет,Предмет,Nesne,Предмет, -Gameplay Options,GMPLYMNU_TITLE,,,,Nastavení herních mechanik,Gameplay-muligheder,Gameplay-Optionen,,Ludado-agordoj,Opciones de jugabilidad,,Pelattavuusasetukset,Options Gameplay,Játékmenet beállításai,Opzioni gameplay,ゲームプレイ オプション,게임플레이 설정,Gameplay-opties,Spillalternativer,Opcje Rozgrywki,Opções de jogabilidade,,Setări de Joc,Настройки игры,Подешавања гејмплеја,Oynanış Seçenekleri,Налаштування гри, -Always,OPTVAL_ALWAYS,,,,Vždy,Altid,Immer,Πάντα,Ĉiam,Siempre,,Aina,Toujours,Mindig,Sempre,常に,언제나,Altijd,Alltid,Zawsze,Sempre,,Mereu,Всегда,Увек,Her zaman,Завжди, -Never,OPTVAL_NEVER,,,,Nikdy,Aldrig,Nie,Ποτέ,Neniam,Nunca,,Ei koskaan,Jamais,Soha,Mai,しない,없음,Nooit,Aldri,Nigdy,Nunca,,Niciodată,Никогда,Никад,Asla,Ніколи, -Autoaim,PLYRMNU_AUTOAIM,,,,Automatické míření,Autoaim,Automatisch zielen,,Celasisto,Autoapuntar,,Automaattitähtäys,Auto-visée,Automatikus célzás,Mira automatica,自動照準,자동 조준,Autoaim,Autoaim,Auto-celowanie,Mira automática,,Autoțintire,Автоприцеливание,Аутоматско циљање,Autoaim,Автонаведення, -Always Run,PLYRMNU_ALWAYSRUN,,,,Vždy běžet,Altid løbe,Immer Rennen,Πάντα τρέχα,Ĉiam kuri,Siempre correr,,Jatkuva juoksu,Toujours courir,Mindig fusson,Corri sempre,常に駆け足,달리기 토글,Altijd lopen,Kjør alltid,Zawsze Biegaj,Sempre correr,Correr Sempre,Fugă în permanență,Постоянный бег,Увек трчи,Daima Koş,Постійно бігти, -,,Display,,,,,,,,,,,,,,,,,,,,,,,,,, -Screen size,DSPLYMNU_SCREENSIZE,,,,Velikost obrazovky,Skærmstørrelse,Bildschirmgröße,Μέγεθος οθόνης,Ekrangrando,Tamaño de pantalla,,Näytön koko,Taille de l'écran,Képernyő mérete,Dimensione della schermata,画面サイズ,화면 크기,Schermgrootte,Skjermstørrelse,Rozmiar Ekranu,Tamanho da tela,Tamanho do ecrã,Mărime ecran,Размер экрана,Величина екрана,Ekran boyutu,Розмір екрану, -Vertical Sync,DSPLYMNU_VSYNC,,,,Vertikální synchronizace,Lodret synkronisering,Vertikale Synchronisation,,Vertikala-sinkronigo,Sincronización vertical,,Pystytahdistys,Synchronisation Verticale,Függőleges szinkronizálás,Sincronia verticale,垂直同期,수직 동기화,Verticale Sync,Vertikal synkronisering,Synchronizacja Pionowa,Sincronização vertical,,Sincronizare Verticală,Вертикальная синхронизация,Вертикална синхорнизација,Dikey Senkronizasyon,Вертикальна синхронізація, -Models,DSPLYMNU_MODELS,,,,Modely,Modeller,Modelle,Μοντέλα,Modeloj,Modelos,,Mallit,Modèles,3D modellek,Modelli,モデル,모델,Modellen,Modeller,Modele,Modelos,,Modele,Модели,Модели,Modeller,3D Моделі, -Scale crosshair,DSPLYMNU_CROSSHAIRSCALE,,,,Velikost zaměřovače,Skalerer trådkorset,Fadenkreuz skalieren,,Skali reteton,Escalar retícula,,Skaalaa tähtäintä,Mise à l'échelle du viseur,Célkereszt méret,Scala del mirino,照準スケール,조준점 크기,Dradenkruis schalen,Skala trådkors,Skala celownika,Escala da mira,,Scară țintă,Размер прицела,Размера нишана,Ölçekli artı işareti,Розмір прицілу, -Brightness,DSPLYMNU_BRIGHTNESS,,,,Jas,Lysstyrke,Helligkeit,Φωτηνότητα,Brileco,Brillo,,Kirkkaus,Luminosité,Fényerő,Luminosità,明るさ,밝기,Helderheid,Lysstyrke,Jasność,Brilho,,Luminozitate,Яркость,Осветљење,Parlaklık,Яскравість, -Gamma correction,DSPLYMNU_GAMMA,,,,Korekce gama,Gammakorrektion,Gammakorrektur,,Gamaa korektado,Corrección gamma,,Gammakorjaus,Correction Gamma,Gamma korrekció,Correzione gamma,ガンマ値,감마 조정,Gamma correctie,Gammakorreksjon,Korekta gammy,Correção de gama,,Gamma,Гамма-коррекция,Корекција светлости,Gama düzeltme,Гамма-корекція, -Contrast,DSPLYMNU_CONTRAST,,,,Kontrast,Kontrast,Kontrast,,Kontrasto,Contraste,,Sävykkyys,Contraste,Kontraszt,Contrasto,コントラスト,대비,,Kontrast,Kontrast,Contraste,,,Контраст,Контраст,Kontrast,Контраст, -Saturation,DSPLYMNU_SATURATION,,,,Sytost,Mætning,Sättigung,,Satureco,Saturación,,Värikylläisyys,,Telítettség,Saturazione,サチュレーション,채도,Verzadiging,Metning,Nasycenie,Saturação,,Saturație,Насыщенность,Сатурација,Doygunluk,Насиченість, -Status Bar Scale,DSPLYMNU_SBSCALE,,,,Velikost stavového panelu,Skala for statuslinje,Statusleistengröße,,Skalo de stata breto,Escala de barra de estado,,Tilapalkin skaalaus,Mise à l'échelle HUD,Állapotjelző mérete,Dimensioni Status Bar,ステータススケール,,Statusbalkschaal,Statuslinjeskala,Skala paska statusu,Escala da barra de estado,,Scară bară de stare,Размер строки состояния,,Durum Çubuğu Ölçeği,Розмір строки стану, -Messages,DSPLYMNU_MESSAGES,,,,Oznámení,Meddelelser,Nachrichten,Μηνύματα,Mesaĝoj,Mensajes,,Viestit,Messages,Üzenetek,Messaggi,メッセージ類,메시지,Berichten,Meldinger,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке,Mesajlar,Повідомлення, -Center messages,MSGMNU_CENTERMESSAGES,,,Centre messages,Oznámení na střed,Centrerede meddelelser,Nachrichten zentrieren,,Centrigi mesaĝojn,Centrar mensajes,,Keskitä viestit,Messages centrés,Üzenetek középre helyezése,Messaggi centrati,メッセージを中央に,메시지 중간에 위치,Berichten centreren,Sentrumsmeldinger,Wyśrodkuj wiadomości,Centralizar mensagens,Centrar mensagens,Mesaje centrate,Центрирование сообщений,Централне поруке,Merkez mesajları,Центрування повідомлень, -Pulsating message Display,MSGMNU_PULSEMESSAGES,,,,Pulzující oznámení,Pulserende meddelelser Visning,Pulsierende Nachrichtenanzeige,,Pulsanta mesaĝ-montrejo,Mostrar mensajes pulsantes,,Sykkivät viestit,Messages pulsés,Pulzáló üzenet,Mostra messaggi pulsanti,取得時等の文を明滅,,Pulserende berichtendisplay,Pulserende melding Display,Pulsujące wyświetlanie wiadomości,Exibir mensagem pulsante,,Afișare Mesaje Pulsante,Пульсация сообщений,,Titreşimli mesaj Ekranı,Пульсація повідомлень, -Message Scale,MSGMNU_MESSAGESCALE,,,,Velikost oznámení,Skala for meddelelser,Nachrichtengröße,Μέγεθος μηνύματον,Skalo de mesaĝoj,Escala de mensajes,,Viestien skaalaus,Mise à l'échelle Messages,Üzenet mérete,Dimensioni Messaggi,メッセージスケール,,Berichtschaal,Meldingsskala,Skalowanie Wiadomości,Escala de mensagem,,Scară Mesaje,Размер сообщений,,Mesaj Ölçeği,Розмір повідомлень, -,,Automap,,,,,,,,,,,,,,,,,,,,,,,,,, -Select Color,MNU_COLORPICKER,,,Select Colour,Výběr barvy,Vælg farve,Farbe auswählen,Επιλογή Χρώματος,Elektu koloron:,Elige un color,,Valitse väri,Choisir Couleur,Szín választása,Scegli il colore,色選択,색상을 고르시오,Selecteer Kleur,Velg farge,Wybierz Kolor,Selecione uma cor,,Alege o Culoare,Выбор цвета,Изабери боју,Renk Seçiniz,Вибір кольору, -Rotate automap,AUTOMAPMNU_ROTATE,,,,Otáčet automapu,Rotere automap,Rotiere Automap,,Turni aŭtomapon,Rotar automapa,,Kiertyvä automaattikartta,Rotation de la Carte,Térkép forgatása,Ruota l'automappa,オートマップの回転表示,오토맵 회전,Automatisch roteren,Roter automatisk kart,Obracaj mapę,Girar automapa,,Rotire hartă computerizată,Вращающаяся автокарта,Ротирај аутомапу,Otomatik haritayı döndür,Обертання автокарти, -Follow player,AUTOMAPMNU_FOLLOW,,,,Následovat hráče,Følg spilleren,Folge dem Spieler,Ακουλούθα το παίχτη,Sekvi ludanton,Seguir jugador,,Seuraa pelaajaa,Suivre le joueur,Kövesse a játékost,Segui il giocatore,プレイヤー追従,플레이어 추적,Volg de speler,Følg spiller,Podążaj za graczem,Seguir jogador,,Urmărire jucător,Привязка к игроку,Прати играча,Oyuncuyu takip et,Прив'язка до гравця, -Line alpha,AUTOMAPMNU_LINEALPHA,,,,Průhlednost čar,Linje alfa,Alpha für Linien,,Travidebleca de linio,Transparencia de línea,,Viivan alpha,Translucidité des lignes,Vonal áttetszóség,Traslucenza delle linee,線の半透明度,선 반투명도,Doorschijnendheid van lijnen,Linje alfa,Przezroczystość Linii,Transparência da linha,,Transparență linii,Прозрачность линий,Транслуценција линија,Çizgi alfa,Прозорість ліній, -Line thickness,AUTOMAPMNU_LINETHICKNESS,,,,Tloušťka čar,Linjetykkelse,Dicke der Linien,,Dikeca de linio,Grosor de línea,,Viivan paksuus,Épaisseur des lignes,Vonal vastagság,Spessore delle linee,線の太さ,선 두께,Dikte van lijnen,Linjetykkelse,Grubość Linii,Espessura da linha,,Grosime linii,Толщина линий,Дебљина линија,Çizgi kalınlığı,Товщина ліній, -Customize Map Colors,MAPCOLORMNU_TITLE,,,Customize Map Colours,Nastavení barev mapy,Tilpas kortfarver,Automapfarben einstellen,,Adapti mapkolorojn,Personalizar colores (mapa),,Värien mukautus,Couleurs Carte Personnalisées,Térkép színeinek testreszabása,Personalizza i colori della mappa,カスタム色を決める,미니맵 색상 설정,Kaartkleuren aanpassen,Tilpass kartfarger,Ustaw kolory mapy,Personalizar cores do mapa,,Personalizare culori hartă,Настройки цветов автокарты,Промени боју мапе,Harita Renklerini Özelleştirin,Налаштування кольорів автокарти, -Restore default custom colors,MAPCOLORMNU_DEFAULTMAPCOLORS,,,Restore default custom colours,Obnovit původní vlastní barvy,Gendan standard brugerdefinerede farver,Standardfarben wiederherstellen,,Restaŭri defaŭltajn laŭmendajn kolorojn,Restaurar colores personalizados,,Palauta oletusvärit,Couleurs par défaut,Eredeti színek visszaállítása,Reimposta i colori personalizzati al default,カスタム色を初期化,기본 색상으로 복구,Standaard aangepaste kleuren herstellen,Gjenopprett egendefinerte standardfarger,Przywróć domyślne kolory,Restaurar cores personalizadas padrão,,Revenire la culorile implicite,Вернуть стандартные цвета,Врати уобичајене разне боје,Varsayılan özel renkleri geri yükleme,Повернути стандартні кольори, -,,Sound,,,,,,,,,,,,,,,,,,,,,,,,,, -Sound enabled,SNDMNU_SNDENABLED,,,,Zvuk zapnut,Lyd aktiveret,Sound aktiv,Ήχος ενεργοποιημένος,Sono ŝaltita,Sonido activado,,Ääni päällä,Son activé,Hang engedélyezve,Abilita gli effetti sonori,サウンド有効,,Geluid actief,Lyd aktivert,Dźwięk włączony,Som ativado,,Sunet activat,Звук включён,,Ses etkin,Звук вимкнено, -Music enabled,SNDMNU_MUSENABLED,,,,Hudba zapnuta,Musik aktiveret,Musik aktiv,Μουσική ενεργοποιημένη,Muziko ŝaltita,Música activada,,Musiikki päällä,Musique activée,Zene engedélyezve,Abilita la musica,音楽有効,,Muziek actief ,Musikk aktivert,Muzyka włączona,Música ativada,,Muzică activată,Музыка включена,,Müzik etkin,Музику вимкнено, -4000 Hz,OPTVAL_4000HZ,,,,,,,,,,,,,,,,,,,,,,,4000 Гц,,,4000 Гц, -8000 Hz,OPTVAL_8000HZ,,,,,,,,,,,,,,,,,,,,,,,8000 Гц,,,8000 Гц, -11025 Hz,OPTVAL_11025HZ,,,,,,,,,,,,,,,,,,,,,,,11025 Гц,,,11025 Гц, -22050 Hz,OPTVAL_22050HZ,,,,,,,,,,,,,,,,,,,,,,,22050 Гц,,,22050 Гц, -32000 Hz,OPTVAL_32000HZ,,,,,,,,,,,,,,,,,,,,,,,32000 Гц,,,32000 Гц, -44100 Hz,OPTVAL_44100HZ,,,,,,,,,,,,,,,,,,,,,,,44100 Гц,,,44100 Гц, -48000 Hz,OPTVAL_48000HZ,,,,,,,,,,,,,,,,,,,,,,,48000 Гц,,,48000 Гц, -64 samples,OPTVAL_64SAMPLES,,,,64 vzorků,,,64 δείγματα,64 specimenoj,64 muestras,,64 näytettä,,,,,64 샘플,,64 samplinger,64 sample,64 amostras,,64 monstre,64 семпла,64 узорка,64 örnek,64 семпла, -128 samples,OPTVAL_128SAMPLES,,,,128 vzorků,,,128 δείγματα,128 specimenoj,128 muestras,,128 näytettä,,,,,128 샘플,,128 samplinger,128 sampli,128 amostras,,128 monstre,128 семплов,128 узорка,128 örnek,128 семплів, -256 samples,OPTVAL_256SAMPLES,,,,256 vzorků,,,256 δείγματα,256 specimenoj,256 muestras,,256 näytettä,,,,,256 샘플,,256 samplinger,256 sampli,256 amostras,,256 monstre,256 семплов,256 узорка,256 örnek,256 семплів, -512 samples,OPTVAL_512SAMPLES,,,,512 vzorků,,,512 δείγματα,512 specimenoj,512 muestras,,512 näytettä,,,,,512 샘플,,512 samplinger,512 sampli,512 amostras,,512 monstre,512 семплов,512 узорка,512 örnek,512 семплів, -1024 samples,OPTVAL_1024SAMPLES,,,,1024 vzorků,,,1024 δείγματα,1024 specimenoj,1024 muestras,,1024 näytettä,,,,,1024 샘플,,1024 samplinger,1024 sampli,1.024 amostras,,1024 monstre,1024 семпла,1024 узорка,1024 örnek,1024 семплів, -2048 samples,OPTVAL_2048SAMPLES,,,,2048 vzorků,,,2048 δείγματα,2048 specimenoj,2048 muestras,,2048 näytettä,,,,,2048 샘플,,2048 samplinger,2048 sampli,2.048 amostras,,2048 monstre,2048 семплов,2048 узорка,2048 örnek,2048 семплів, -4096 samples,OPTVAL_4096SAMPLES,,,,4096 vzorků,,,4096 δείγματα,4096 specimenoj,4096 muestras,,4096 näytettä,,,,,4096 샘플,,4096 samplinger,4096 sampli,4.096 amostras,,4096 monstre,4096 семплов,4096 узорка,4096 örnek,4096 семплів, -Auto,OPTSTR_AUTO,,,,,Automatisk,,,Aŭtomata,Automático,,Automaattinen,,Automatikus,Automatico,自動,오토,,,Automatycznie,Automático,,,Авто,Аутоматски,Otomatik,Авто, -Mono,OPTSTR_MONO,,,,,,,,Monofonia,,,,,Monó,,モノラル,모노,,,,,,,Моно,Монотоно,,Моно, -Stereo,OPTSTR_STEREO,,,,,,,,Stereofonia,Estéreo,,,Stéréo,Sztereó,,ステレオ,스테레오,,,,Estéreo,,,Стерео,Стереотоно,,Стерео, -Dolby Pro Logic Decoder,OPTSTR_PROLOGIC,,,,,Dolby Pro Logic-dekoder,,,Malkodilo de Dolby Pro Logic ,,,,,,,ドルビー プロロジック デコーダー,돌비 프로 로직 디코더,,Dolby Pro Logic Dekoder,,Decodificador Dolby Pro Logic,,Decodor Pro Logic Dolby,Декодер Dolby Pro Logic,,Dolby Pro Logic Dekoder,Декодер Dolby Pro Logic, -Quad,OPTSTR_QUAD,,,,,,,,Kvadratofonia,Cuádruple,,Dolby Pro Logic -dekooderi,,,,クァッド,쿼드,,,Cztery kanały,Quadrifônico,,,Четырёхканальный,Четвородупло,Dörtlü,Чотирьохканальний, -5 speakers,OPTSTR_SURROUND,,,,5 reproduktorů,5 højttalere,5 Lautsprecher,,5 Laŭtparoliloj,5 altavoces,,5 kaiutinta,5 enceintes,5 hangfal,Surround,5 スピーカー,5 스피커,5 luidsprekers,5 høyttalere,Głośniki 5,5 alto-falantes,,5 boxe,5 динамиков,5 спикер,5 hoparlörler,5 динаміків, -5.1 speakers,OPTSTR_5POINT1,,,,Reproduktory 5.1,5.1-højttalere,5.1 Lautsprecher,,5.1 Laŭtparoliloj,Altavoces 5.1,,5.1 kaiutinta,Enceintes 5.1,5.1 hangrendszer,Surround 5.1,5.1 スピーカー,5.1 스피커,5.1 luidsprekers,5.1 høyttalere,Głośniki 5.1,Auto-falantes 5.1,,Boxe 5.1,Динамики 5.1,5.1 спикер,5.1 hoparlörler,Динаміки 5.1, -7.1 speakers,OPTSTR_7POINT1,,,,Reproduktory 7.1,7.1-højttalere,7.1 Lautsprecher,,7.1 Laŭtparoliloj,Altavoces 7.1,,7.1 kaiutinta,Enceintes 7.1,7.1 hangrendszer,Surround 7.1,7.1 スピーカー,7.1스피커,7.1 luidsprekers,7.1-høyttalere,Głośniki 7.1,Auto-falantes 7.1,,Boxe 7.1,Динамики 7.1,7.1 спикер,7.1 hoparlörler,Динаміки 7.1, -Playback device,OPENALMNU_PLAYBACKDEVICE,,,,Přehravací zařízení,Afspilningsenhed,Wiedergabegerät,,Ludado-aparato,Dispositivo de reproducción,,Äänitoistolaite,Sortie sonore,Visszajátszó eszköz,Dispositivo di playback,プレイバック デバイス,재생 장치,Afspeelapparaat,Avspillingsenhet,Urządzenie odtwarzania,Dispositivo de reprodução,,Dispozitiv de redare,Устройство воспроизведения,Аудио уређај,Oynatma cihazı,Пристрій відтворення, -Enable EFX,OPENALMNU_ENABLEEFX,,,,Povolit EFX,Aktiver EFX,EFX aktiv,,Ŝalti EFX,Permitir EFX,,Ota käyttöön EFX,Activer EFX,EFX engedélyezése,Abilita EFX,EFXを有効化,EFX 켬,EFX inschakelen,Aktiver EFX,Pozwól na EFX,Ativar EFX,,Activare EFX,Включить EFX,Укључи EFX,EFX'i Etkinleştir,Увімкнути EFX, -Resampler,OPENALMNU_RESAMPLER,,,,,Resampler,,,Respecimenilo,,,Näytteenottotaajuusmuunnin,,,,リサンプラー,재배열 기기,,,Resampler,Reamostrador,,,Передискретизатор,Ресемплер,Yeniden Örnekleyici,Ресемплер, -Sounds volume,SNDMNU_SFXVOLUME,,,,Hlasitost zvuků,Lydstyrke,Effektlautstärke,Φονή ήχων,Sona laŭteco,Volumen de sonido,,Äänitehosteiden voimakkuus,Volume des Sons,Effektek hangereje,Volume suoni,効果音音量,효과음 음량,Geluidsvolume,Lydvolum,Głośność Dźwięku,Volume de sons,,Volum efecte,Громкость звука,Јачина звука,Ses seviyesi,Гучність звуків, -Menu volume,SNDMNU_MENUVOLUME,,,,Hlasitost nabídek,Menu-volumen,Menülautstärke,Φονή μενού,Menuo-laŭteco,Volumen del menú,,Valikon äänenvoimakkuus,Volume du Menu,Menü hangereje,Volume menù,メニュー音量,메뉴 음량,Menu volume,Menyvolum,Głośność Menu,Volume do menu,,Volum meniu,Громкость меню,Јачина менија,Menü ses seviyesi,Гучність меню, -Music volume,SNDMNU_MUSICVOLUME,,,,Hlasitost hudby,Lydstyrke for musik,Musiklautstärke,Φονή μουσικής,Muzika laŭteco,Volumen de la música,,Musiikin äänenvoimakkuus,Volume Musique,Zene hangereje,Volume musica,音楽音量,배경음 음량,Muziekvolume,Musikkvolum,Głośność Muzyki,Volume da música,,Volum muzică,Громкость музыки,Јачина музике,Müzik sesi,Гучність музики, -MIDI device,SNDMNU_MIDIDEVICE,,,,MIDI zařízení,MIDI-enhed,MIDI-Gerät,MIDI συσκεύη,MIDI-aparato,Dispositivo MIDI,,MIDI-laite,Sortie MIDI,MIDI eszköz,Dispositivo MIDI,MIDIデバイス,MIDI 장치,MIDI-apparaat,MIDI-enhet,Urządzenie MIDI,Dispositivo MIDI,,Dispozitiv MIDI,MIDI-проигрыватель,MIDI уређај,MIDI cihazı,MIDI програвач, -Sound in Background,SNDMNU_BACKGROUND,,,,Zvuk na pozadí,Lyd i baggrunden,Sound im Hintergrund,Ήχος στο παρασκήνιο,Sono en fono,Sonido en segundo plano,,Ääni taustalla,Son activé en arrière plan,Háttérhangok,Suono di sottofondo,バックグラウンドでのサウンド,배경화면에서도 소리 재생,Geluid in de achtergrond,Lyd i bakgrunnen,Dźwięk w Tle,Som em segundo plano,,Sunet pe fundal,Звук в фоне,Звуци у позадини,Arka Planda Ses,Звуки на фоні, -Underwater reverb,SNDMNU_UNDERWATERREVERB,,,,Ozvěna pod vodou,Undervandsreverb,Unterwasserhall,,Subakva resono,Reverberación bajo el agua,,Vedenalaiskaiku,Reverbération sous l'eau,Vízalatti visszaverődés,Reverb sott'acqua,水中反響音,수중 울림효과,Onderwater nagalm,Undervanns romklang,Pogłos pod wodą,Reverberação debaixo d'água,Reverberação debaixo de água,Reverb subacvatic,Эффект затухания под водой,Подводни одјек,Su altı yankısı,Підводний ефект, -Randomize pitches,SNDMNU_RANDOMIZEPITCHES,,,,Náhodné výšky tónu,Randomisere tonehøjder,Zufällige Tonhöhe,,Malcertigi son-peĉojn,Tonos aleatorios,,Satunnaista äänenkorkeuksia,Tons sonores aléatoires,Hangmagasság keverése,Rendi casuale il tono,ランダマイズ ピッチ,음높이 무작위화,Willekeurige plaatsen,Tilfeldig tonehøyde,Losuj tonacje,Tons aleatórios,Tons aleatórios,Ton sunete aleatoriu,Случайная высота,Рандомизација тонова,Sahaları rastgele ayarlayın,Випадкова висота, -Sound channels,SNDMNU_CHANNELS,,,,Počet zvukových kanálů,Lydkanaler,Soundkanäle,Κανάλια ήχου,Sonokanaloj,Canales de sonido,,Äänikanavat,Canaux sonores,Hangcsatorna,Numero canali del suono,サウンド チャンネル,음향 채널,Geluidskanalen,Lydkanaler,Kanały dźwiękowe,Canais de som,,Canale de sunet,Количество каналов,Звучни канали,Ses kanalları,Кількість каналів, -Sound backend,SNDMNU_BACKEND,,,,Zvukový systém,Lyd backend,Soundsystem,,Sonoservilo,Sistema de sonido,,Äänijärjestelmä,Traitement Son,Hang backend,Backend suono,サウンド バックエンド,음향 말미,Geluidsarme achterkant,Lyd backend,System dźwiękowy,Sistema de som,,Sistem de sunet,Звуковая подсистема,Звучни бекенд,Ses arka ucu,Звукова система, -OpenAL options,SNDMNU_OPENAL,,,,Nastavení OpenAL,OpenAL-muligheder,OpenAL Optionen,OpenAL ρυθμίσεις,OpenAL agordoj,Opciones de OpenAL,,OpenAL-asetukset,Options OpenAL,OpenAL beállításai,Opzioni OpenAL,OpenAL オプション,오픈에이엘 설정,OpenAL opties,OpenAL-alternativer,Opcje OpenAL,Opções de OpenAL,,Setări OpenAL,Настройки OpenAL,OpenAL подешавања,OpenAL seçenekleri,Параметри OpenAL, -Restart sound,SNDMNU_RESTART,,,,Restartovat zvuk,Genstart af lyd,Sound neu starten,,Rekomenci sonon,Reiniciar sonido,,Käynnistä ääni uudelleen,Redémarrer moteur sonore,Hang újraindítása,Resetta il suono,サウンド再起動,음향 재시작,Herstart geluid,Start lyd på nytt,Zresetuj dźwięk,Reiniciar som,,Reinițializare sunet,Перезапустить звук,Поново покрени звук,Sesi yeniden başlat,Перезавантажити звук, -Advanced options,SNDMNU_ADVANCED,,,,Pokročilá nastavení,Avancerede indstillinger,Erweiterte Optionen,Προχήρημενες ρυθμίσεις,Altnivelaj agordoj,Opciones avanzadas,,Edistyneet asetukset,Options avancées,Haladó beállítások,Opzioni avanzate,高度なオプション,고급 설정,Geavanceerde opties,Avanserte alternativer,Zaawansowane Opcje,Opções avançadas,,Setări avansate,Расширенные настройки,Напредна подешавања,Gelişmiş seçenekler,Розширені налаштування, -Module replayer options,SNDMNU_MODREPLAYER,,,,Nastavení přehrávače modulů,Indstillinger for modulafspiller,Modul-Spieler-Optionen,,Agordoj por modulreludilo,Opciones reproductor de módulos,,Moduulisoitinasetukset,Options lecteur de module,Modul lejátszó beállításai,Opzioni Module replayer,モジュールリプレイヤー オプション,모듈 재생 설정,Module replayer opties,Alternativer for modulavspiller,Opcje Modułu Odtwarzacza,Opções de reprodutor de módulos,,Setări de redare a modulelor,Параметры воспроизведения модулей,Подешавања модулног риплејера,Modül yeniden oynatıcı seçenekleri,Параметри відтворення модулів, -Midi player options,SNDMNU_MIDIPLAYER,,,,Nastavení MIDI přehrávače,Indstillinger for Midi-afspiller,MIDI-Spieler-Optionen,,Agordoj por MIDI-ludilo,Opciones de reproductor MIDI,,MIDI-soitinasetukset,Option lecteur MIDI,Midi lejátszó beállításai,Opzioni Midi player,Midi再生のオプション,MIDI 플레이어 설정,Midi speler opties,Alternativer for midispiller,Opcje Odtwarzacza Midi,Opções de reprodutor MIDI,,Setări player MIDI,Настройки MIDI-проигрывателя,MIDI плејер подешавања,Midi oynatıcı seçenekleri,Параметри MIDI-програвача, -Sound in Menus,SNDMNU_MENUSOUND,,,,Zvuk v menu,Lyd i menuer,Sound in Menüs,,Sono en menuoj,,,Ääni valikoissa,,Hang a menükben,Suono nei menù,メニューでのサウンド,,Geluid in menu's,Lyd i menyer,Dźwięk w Menu,Som em menus,,Sunet in meniuri,Звук в меню,,Menülerde Ses,Звук в меню, -Advanced Sound Options,ADVSNDMNU_TITLE,,,,Pokročilá nastavení zvuku,Avancerede lydindstillinger,Erweiterte Soundoptionen,,Altnivelaj sonaj agordoj,Opciones avanzadas de sonido,,Edistyneet ääniasetukset,Options Sonores Avancées,Haladó hangbeállítások,Opzioni avanzate dei suoni,高度なサウンドオプション,고급 음향 설정,Geavanceerde geluidsopties,Avanserte lydalternativer,Zaawansowane Opcje Dźwięku,Opções de áudio avançadas,,Setări de sunet avansate,Расширенные настройки,Напредна подешавања звука,Gelişmiş Ses Seçenekleri,Розширені налаштування звуку, -Sample rate,ADVSNDMNU_SAMPLERATE,,,,Vzorkovací frekvence,Samplerate,Samplerate,,Specimenrapideco,Frecuencia de muestreo,,Näytteenottotaajuus,Cadence de Sampling,Mintavételezési ráta,,サンプルレート,샘플링레이트,Steekproeftarief,Samplingsfrekvens,Częstotliwość próbkowania,Taxa de amostragem,,Frecvență de eșantionare,Частота дискретизации,Фреквенција узорковања,Örnek oranı,Частота дискретизації, -HRTF,ADVSNDMNU_HRTF,,,,,,,,,,,,,,,,머리전달함수,,,,,,,,,,, -OPL Synthesis,ADVSNDMNU_OPLSYNTHESIS,,,,Emulace OPL,OPL-syntese,OPL Synthese,,OPL-sintezo,Síntesis OPL,,OPL-synteesi,Synthèse OPL,OPL szintézis,,OPLシンセサイズ,OPL 합성,OPL synthese,OPL-syntese,Synteza OPL,Síntese OPL,,Sinteză OPL,Синтез OPL,OPL синтеза,OPL Sentezi,Синтез OPL, -Number of emulated OPL chips,ADVSNDMNU_OPLNUMCHIPS,,,,Počet emulovaných OPL čipů,Antal emulerede OPL-chips,Anzahl OPL Chips,,Nombro da imititaj OPL-blatoj,Número de chips OPL emulados,,Emuloitavien OPL-piirien lukumäärä,Puces OPL émulées,Emulált OPL csipek száma,Numero di chip OPL emulati,OPLチップエミュレートの番号,에뮬레이트된 OPL 칩 수,Aantal geëmuleerde OPL chips,Antall emulerte OPL-brikker,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,Număr de cipuri OPL emulate,Количество эмулируемых чипов OPL,Број емулираних OPL чипа,Taklit edilen OPL çiplerinin sayısı,Кількість емульованих OPL-чіпів, -Full MIDI stereo panning,ADVSNDMNU_OPLFULLPAN,,,,Plné MIDI stereo,Fuld MIDI stereo panorering,Echte MIDI-Stereoeffekte,,Tuta MIDI-sterepanoramado,Balance estéreo MIDI completo,,Täysi MIDI-stereopanorointi,Latéralisation complète MIDI,Teljes MIDI sztereó tájolás,,Full MIDIステレオパンニング,완전한 MIDI 스테레오 패닝,Volledige MIDI stereo panning,Full MIDI stereo panorering,Pełne efekty stereo dla MIDI,Lateralidade estéreo completa para MIDI,,Panoramă stereo pentru MIDI,Полная стереопанорама для MIDI,Пуно MIDI стерео каналисање,Tam MIDI stereo kaydırma,Повна стереопанорама для MIDI, -OPL Emulator Core,ADVSNDMNU_OPLCORES,,,,Emulační jádro OPL,OPL-emulatorkerne,OPL Emulatorkern,,OPL-imitilkerno,Núcleo de emulador OPL,,OPL-emulaattoriydin,Cœur émulateur OPL,,,OPL エミュレート コア,OPL 에뮬레이터 코어,OPL Emulator Kern,OPL-emulatorkjerne,Rdzeń Emulatora OPL,Núcleo do emulador de OPL,,Nucleu de emulare OPL,Ядро эмуляции OPL,OPL језгро емулације,OPL Emülatör Çekirdeği,Ядро емуляції OPL, -MIDI voices,ADVSNDMNU_MIDIVOICES,,,,Počet MIDI hlasů,MIDI-stemmer,MIDI Stimmen,,MIDI-voĉoj,Voces MIDI,,MIDI-äänet,Voix MIDI,MIDI hangok,Voci MIDI,MIDI ボイス,MIDI 최대 음색 양,MIDI-stemmen,MIDI stemmer,Głosy MIDI,Vozes MIDI,,Voci MIDI,MIDI-голоса,MIDI гласови,MIDI sesleri,MIDI-голоси, -FluidSynth,ADVSNDMNU_FLUIDSYNTH,,,,,,,,,,,,,,,,,,,,,,,,,,, -Global,ADVSNDMNU_GLOBAL,,,,Globální,,,,Malloka,Global,,Yleinen,,,Globale,グローバル,전반적,Globaal,,Globalne,,,,Общие,Глобално,Küresel,Загальні, -Freeverb,ADVSNDMNU_FREEVERB,,,,,,,,,,,,,,,フリーバーブ,프리버브,,,,,,,,,Freeverb,, -Global Freeverb,ADVSNDMNU_GLOBAL_FREEVERB,,,,Globální Freeverb,Global Freeverb,Globales Freeverb,,Malloka Freeverb,Freeverb Global,,Yleinen Freeverb,Freeverb Global,,Freeverb globale,グローバル フリーバーブ,전반적 프리버브,Globale Freeverb,,Globalny Freeverb,Freeverb global,,Freeverb Global,Глобальный Freeverb,Глобални Freeverb,Küresel Freeverb,Глобальний Freeverb, -Patch set,ADVSNDMNU_FLUIDPATCHSET,,,,Nástrojová sada,Patch-sæt,Patch-Set,,Flikaro,Set de parche,,Patch-asetus,Banque de Sons,,,パッチ セット,패치 세트,,Patch-sett,Zestaw łatek,Banco de sons,,Set patch,Патч-набор,Печ сет,Yama seti,Патч-набір, -Gain,ADVSNDMNU_FLUIDGAIN,,,,Zesílení,,Relative Lautstärke,,Akiro,Ganancia,,Vahvistus,,Visszaverődés,,ゲイン,쌓기,Relatief volume,,Wzmocnienie,Ganho,,Amplificare,Усиление,Појачање,Kazanç,Підсилення, -Reverb,ADVSNDMNU_REVERB,,,,Ozvěna,,Hall,,Resono,Reverberación,,Kaiku,Réverbération,Visszhang,,リバーブ,리버브,Nagalm,,Pogłos,Reverberação,,,Реверберация,Одјек,Reverb,Ревербація, -Reverb Level,ADVSNDMNU_REVERB_LEVEL,,,,Intenzita ozvěny,,Hallintensität,,Nivelo de resono,Nivel de reverberación,,Kaiunvoimakkuus,Niveau Réverb.,Visszhang szintje,,リバーブ量,리버브 강도,Nagalm niveau,Reverb-nivå,Poziom pogłosu,Nível de reverberação,,Nivel Reverb,Уровень реверберации,Ниво одјека,Reverb Seviyesi,Рівень ревербації, -Chorus,ADVSNDMNU_CHORUS,,,,,,,,Koruso,,,,,,,コーラス,코러스,,,,,,Cor,Хор,Корус,Koro,Хорус, -Timidity++,ADVSNDMNU_TIMIDITY,,,,,,,,,,,,,,,,,,,,,,,,,,, -ADLMidi,ADVSNDMNU_ADLMIDI,,,,,,,,,,,,,,,,,,,,,,,,,,, -OPNMidi,ADVSNDMNU_OPNMIDI,,,,,,,,,,,,,,,,,,,,,,,,,,, -Timidity config file,ADVSNDMNU_TIMIDITYCONFIG,,,,Konfigurační soubor Timidity,Timidity-konfigurationsfil,Timidity Konfigurationsdatei,,Agorda dosiero de Timidity,Ruta al archivo config. Timidity,,Timidity-config-tiedosto,Fichier de config. TiMidity,Timidity konfigurációs fájl,File configurazione Timidity,Timidity コンフィグファイル,Timidity 코딩 파일,Timidity++ configuratiebestand,Timidity konfigurasjonsfil,Plik konfiguracyjny Timidity,Arquivo de configuração do Timidity,,Fișier configurație Timidity,Файл конфигурации Timidity,Timidity конфигурациона датотека,Timidity yapılandırma dosyası,Файл конфігурації Timidity, -Relative volume,ADVSNDMNU_TIMIDITYVOLUME,,,,Relativní hlasitost,Relativ lydstyrke,Relative Lautstärke,,Relativa laŭteco,Volumen relativo,,Suhteellinen äänenvoimakkuus,Volume Relatif,Relatív hangerő,Volume relativo,相対音量,비교적인 볼륨,Relatief volume,Relativt volum,Względna głośność,Volume relativo,,Volum relativ,Относительная громкость,Релативна јачина,Bağıl hacim,Відносна гучність, -WildMidi,ADVSNDMNU_WILDMIDI,,,,,,,,,,,,,,,,,,,,WildMidi,,,,,,, -WildMidi config file,ADVSNDMNU_WILDMIDICONFIG,,,,Konfigurační soubor WildMidi,WildMidi konfigurationsfil,WilfMidi Konfigurationsdatei,,Agorda dosiero de WildMidi,Archivo de config. WildMidi,,WildMidi-config-tiedosto,Fichier config. WildMidi,WildMidi konfigurációs fájl,File WildMidi config,WildMidi コンフィグファイル,WildMidi 코딩 파일,WildMidi configuratiebestand,WildMidi konfigurasjonsfil,Plik konfiguracyjny WildMidi,Arquivo de configuração do WildMidi,,Fișier configurație WildMidi,Файл конфигурации WildMidi,WildMidi конфигурациона датотека,WildMidi yapılandırma dosyası,Файл конфігурації WildMidi, -Select configuration,ADVSNDMNU_SELCONFIG,,,,Vybrat konfiguraci,Vælg konfiguration,Konfiguration wählen,,Elekti agordojn,Seleccionar configuración,,Valitse kokoonpano,Sélectionner configuration,Konfiguráció kiválasztása,Seleziona la configurazione,構成選択,설정을 고르시오,Selecteer configuratie,Velg konfigurasjon,Wybierz konfigurację,Selecionar configuração,,Selectare configurație,Выбор конфигурации,Изабери конфигурацију,Yapılandırma seçin,Вибір конфігурації, -Advanced Resampling,ADVSNDMNU_ADVRESAMPLING,,,,Pokročilé převzorkování,Avanceret resampling,Erweitertes Resampling,,Altnivela respecimenado,Resampleo avanzado,,Kehittynyt näytteenottotaajuuden muuntaminen,Resampling Avancé,Fejlett Resmapling,Resampling avanzato,高度なリサンプリング,향상된 리샘플링,Geavanceerde herbemonstering,Avansert resampling,Zaawansowane Próbkowanie,Reamostragem avançada,,Resempling avansat,Продвинутый ресэмплинг,Напредно ресампловање,Gelişmiş Yeniden Örnekleme,Розширений ресемплінг, -OPL Bank,ADVSNDMNU_OPLBANK,,,,OPL sada,OPL Bank,,,Banko por OPL,Banco OPL,,OPL-pankki,Banque OPL,,,,OPL 뱅크,,,Bank OPL,Banco OPL,,Bancă OPL,Банк OPL,OPL банка,OPL Bank,Банк OPL, -OPL Emulator Core,ADVSNDMNU_ADLOPLCORES,,,,Emulační jádro OPL,OPL-emulatorkerne,OPL Emulatorkern,,Imitilkerno por OPL,Núcleos de emulador OPL,,OPL-emulaattoriydin,Cœur Emulateur OPL,OPL emulátor mag,,OPL エミュレートコア,OPL 에뮬레이터 코어,OPL Emulator Kern,OPL-emulatorkjerne,Rdzeń Emulatora OPL,Núcleo do emulador de OPL,,Nucleu de emulare OPL,Ядро эмуляции OPL,OPL емулационо језгро,OPL Emülatör Çekirdeği,Ядро емуляції OPL, -Run emulator at PCM rate,ADVSNDMNU_RUNPCMRATE,,,,Emulátor používá PCM vzorkovací frekvenci,Kør emulator ved PCM-hastighed,Emulator benutzt PCM Samplerate,,Kurigi imitilon laŭ rapido de PCM,Ejecutar emulador a velocidad PCM,,Aja emulaattoria PCM-taajuudella,Emulateur utilise cadence PCM,Emulátor futtatása PCM rátán,Esegui l'emulatore con rate PCM,PCMレートでエミュレート実行,PCM 속도로 에뮬레이터 실행,Emulator maakt gebruik van PCM Samplerate,Kjør emulator med PCM-hastighet,Uruchom emulator w częstotliwości PCM,Rodar emulador em taxa PCM,,Utilizare cu frecvența PCM,Использовать с частотой PCM,Покрени емулацију на PCM стопи,Emülatörü PCM hızında çalıştırın,Використовувати з частотою PCM, -Number of emulated OPL chips,ADVSNDMNU_ADLNUMCHIPS,,,,Počet emulovaných OPL čipů,Antal emulerede OPL-chips,Anzahl OPL Chips,,Numbro da imitaj OPL-blatoj,Número de chips OPL emulados,,Emuloitavien OPL-piirien lukumäärä,Puces OPL émulées,Emulált OPL csipek száma,Numero di chip OPL emulati,OPLチップエミュレートの番号,에뮬레이트된 OPL 칩 개수,Aantal geëmuleerde OPL chips,Antall emulerte OPL-brikker,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,Număr de cipuri GUS emulate,Количество эмулируемых чипов OPL,Број емулираних OPL чипова,Taklit edilen OPL çiplerinin sayısı,Кількість емульованих OPL-чіпів, -Volume model,ADVSNDMNU_VLMODEL,,,,Model hlasitosti,Volumenmodel,Lautstärkemodell,,Modelo de laŭteco,Modelo de volumen,,Äänenvoimakkuusmalli,Modèle de Volume,Hangmodell,Modello di volume,音量モデル,모델 볼륨,Volume model,Volummodell,Model głośności,Modelo de volume,,Model volum,Модель громкости,Волумски модел,Hacim modeli,Модель гучності, -OPN2 Emulator Core,ADVSNDMNU_OPNCORES,,,,Emulační jádro OPN2,OPN2-emulatorkerne,OPN2 Emulatorkern,,OPN2 Imitilkerno,Núcleo de emulador OPN2,,OPN2-emulaattoriydin,Cœur émulateur OPN2,OPN2 Emulátor Mag,,OPN2 エミュレート コア,OPN2 에뮬레이터 코어,OPN2 Emulatorkern van de OPN2-emulator,OPN2 Emulatorkjerne,Rdzeń Emulatora OPN2,Núcleo do emulador de OPN2,,Nucleu de emulare OPN2,Ядро эмуляции OPN2,OPN2 језгро емулације,OPN2 Emülatör Çekirdeği,Ядро емуляції OPN2, -GUS Emulation,ADVSNDMNU_GUSEMULATION,,,,Emulace GUS,GUS-emulering,GUS Emulation,,GUS Imitado,Emulación GUS,,GUS-emulaatio,Emulation GUS,GUS Emuláció,,GUS エミュレーション,GUS 에뮬레이션,GUS-emulatie,GUS-emulering,Emulacja GUS,Emulação de GUS,,Emulare GUS,Эмуляция GUS,GUS емулација,GUS Emülasyonu,Емуляція GUS, -GUS config file,ADVSNDMNU_GUSCONFIG,,,,Konfigurační soubor GUS,GUS-konfigurationsfil,GUS Konfigurationsdatei,,Agorda dosiero de GUS,Archivo de config. GUS,,GUS-config-tiedosto,Fichier Config. GUS,GUS konfigurációs fájl,File GUS config,GUS コンフィグファイル,GUS 코딩 파일,GUS-configuratiebestand,GUS konfigurasjonsfil,Plik konfiguracyjny GUS,Arquivo de configuração do GUS,,Fișier configurație GUS,Файл конфигурации для GUS,GUS конфигурациона датотека,GUS yapılandırma dosyası,Файл конфігурації для GUS, -Read DMXGUS lumps,ADVSNDMNU_DMXGUS,,,,Načíst DMXGUS soubory,Læs DMXGUS-klumper,Lese DMXGUS,,Legi DMXGUS Masojn,Leer archivos DMXGUS,,Lue DMXGUS-tietoja,Lire fichiers DMXGUS,DMXGUS lumpok beolvasása,Leggi i lump DMXGUS,DMXGUS ランプを読む,DMXGUS 럼프 읽기,DMXGUS-klonten lezen,Les DMXGUS-filer,Czytaj pliki DMXGUS,Ler lumps DMXGUS,,Citire fișiere DMXGUS,Читать файлы DMXGUS,Читај DMXGUS фајлове,DMXGUS dosyalarını okuma,Читати файли DMXGUS, -GUS memory size,ADVSNDMNU_GUSMEMSIZE,,,,Velikost paměti GUS,GUS-hukommelsesstørrelse,GUS Speichergröße,,GUS Memorampleksoj,Tamaño de memoria de GUS,,GUS-muistikoko,Taille mémoire GUS,GUS memória mérete,Dimensione della memoria per GUS,GUS メモリーサイズ,GUS 메모리 크기,GUS-geheugengrootte,GUS-minne størrelse,Rozmiar pamięci GUS,Tamanho de memória do GUS,,Memorie alocată pentru GUS,Размер памяти GUS,GUS величина памћења,GUS bellek boyutu,Розмір пам'яті GUS, -Number of emulated OPN chips,ADVSNDMNU_OPNNUMCHIPS,,,,Počet emulovaných OPN čipů,Antal emulerede OPN-chips,Anzahl OPN Chips,,Nombro da imititaj OPL-blatoj,Número de chip OPN emulados,,Emuloitavien OPN-piirien lukumäärä,Puces OPN émulées,Emulált OPL csipek száma,Numero di chip OPN emulati,OPNチップエミュレートの番号,에뮬레이트된 OPN 칩 개수,Aantal geëmuleerde OPL chips,Antall emulerte OPN-brikker,Liczba emulowanych czipów OPN,Número de chips OPN emulados,,Număr de cipuri OPN emulate,Количество эмулируемых чипов OPN,Број емулираних OPN чипова,Taklit edilen OPN çiplerinin sayısı,Кількість емульованих OPN-чіпів, -Use custom WOPL bank,ADVSNDMNU_ADLCUSTOMBANK,,,,Použít vlastní WOPL sadu,Brug af brugerdefineret WOPL-bank,Benutzerdefinierte WOPL Bank,,Uzi laŭmendan WOPL-bankon,Utilizar banco WOPL personalizado,,Käytä mukautettua WOPL-pankkia,Utiliser Banque WOPL perso,Saját WOPL bank használata,Usa WOPL bank personalizzato,カスタムWOPL bankを使用,사용자 지정 WOPL 뱅크 사용,Gebruik de aangepaste WOPL bank,Bruk egendefinert WOPL-bank,Użyj niestandardowego banku WOPL,Usar banco WOPL personalizado,,Utilizați propriul bank WOPN,Использовать собственный банк WOPL,Користи прилагођенуу WOPL банку,Özel WOPL bankası kullanın,Використовувати власний банк WOPL, -WOPL Bank file,ADVSNDMNU_OPLBANKFILE,,,,Soubor WOPL sady,WOPL Bank-fil,WOPL Bank-Datei,,WOPL-Bankodosiero,Archivo de banco WOPL,,WOPL-pankkitiedosto,Banque WOPL,WOPL Bank fájl,File WOPL Bank,WOPL bankファイル,WOPL 뱅크 파일,WOPL Bank-bestand,WOPL Bank-fil,Plik banku WOPL,Banco WOPL,,Fișier WOPN bank,Файл с банком WOPL,WOPL фајл банка,WOPL Bank dosyası,Файл з банком WOPL, -Use custom WOPN bank,ADVSNDMNU_OPNCUSTOMBANK,,,,Použít vlastní WOPN sadu,Brug af brugerdefineret WOPN-bank,Benutzerdefinierte WOPN Bank,,Uzi laŭmendan WOPN-bankon,Utilizar banco WOPN personalizado,,Käytä mukautettua WOPN-pankkia,Utiliser Banque WOPL perso,Saját WOPN bank használata,Usa WOPN bank personalizzato,カスタムWOPN bankを使用,사용자 지정 WOPN 뱅크 사용,Gebruik aangepaste WOPN-bank op maat,Bruk egendefinert WOPN-bank,Użyj niestandardowego banku WOPN,Usar banco WOPN personalizado,,Utilizați propriul bank WOPN,Использовать собственный банк WOPN,Користи прилагођену WOPN банку,Özel WOPN bankası kullanın,Використовувати власний банк WOPN, -WOPN Bank file,ADVSNDMNU_OPNBANKFILE,,,,Soubor WOPN sady,WOPN Bank-fil,WOPN Bank-Datei,,WOPN-Bankodosiero,Archivo de banco WOPN,,WOPN-pankkitiedosto,Banque WOPL,WOPN Bank fájl,File WOPN Bank,WOPN bankファイル,WOPN 뱅크 파일,WOPN Bank-bestand,WOPN-bankfil,Plik banku WOPN,Banco WOPN,,Fișier WOPN bank,Файл с банком WOPN,WOPN фајл банка,WOPN Banka dosyası,Файл з банком WOPN, -Aliasing,OPTVAL_ALIASING,,,,,Aliasing,,,Krenelaro,,,,,,,エイリアシング,에일리어싱,,,,,,Dedublare,Сглаживание,Преклапање,Takma Adlandırma,Згладжування, -Linear,OPTVAL_LINEAR_1,This setting is duplicated threefold in order to allow for different grammatical gender endings,,,Lineární,Lineær,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Lineær,Liniowy,Linear,,Liniar,Линейное,Линеаран,Doğrusal,Лінійне, -Linear,OPTVAL_LINEAR_2,,,,Lineární,Lineær,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Lineær,Liniowa,Linear,,Liniar,Линейная,Линеаран,Doğrusal,Лінійна, -Linear,OPTVAL_LINEAR_3,,,,Lineární,Lineær,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Lineær Lineær,Liniowe,Linear,,Liniar,Линейный,Линеаран,Doğrusal,Лінійний, -Nearest,OPTVAL_NEAREST,,,,Nejbližší,Nærmeste,Nächster Nachbar,,Plej proksima,Cercano,,Lähin,Nearest,Legközelebbi,Il più vicino,最寄り,가까이,Naast,Nærmeste,Najbiższe,Mais próximo,,Cel mai apropriat,Ближайший,Најближе,En yakın,Найближчий, -PCF (Low),OPTVAL_PCF_LOW,,,,PCF (nízké),PCF (lav),PCF (niedrig),,PCF (Malalta),PCF (Bajo),,PCF (matala),PCF (Low),PCF (Alacsony),PCF (basso),PCF (低),PCF (하급),PCF (Laag),PCF (lav),PCF (Niski),PCF (Baixo),,PCF (Scăzut),PCF (низкий),PCF (ниско),PCF (Düşük),PCF (низький), -PCF (Medium),OPTVAL_PCF_MEDIUM,,,,PCF (střední),PCF (medium),PCF (mittel),,PCF (Meza),PCF (Medio),,PCF (keskitaso),PCF (Medium),PCF (Közepes),PCF (medio),PCF (中),PCF (중급),PCF (Medium),PCF (middels),PCF (Średni),PCF (Médio),,PCF (Mediu),PCF (средний),PCF (средње),PCF (Orta),PCF (средній), -PCF (High),OPTVAL_PCF_HIGH,,,,PCF (vysoké),PCF (høj),PCF (hoch),,PCF (Alta),PCF (Alto),,PCF (korkea),PCF (High),PCF (Magas),PCF (alto),PCF (高),PCF (상급),PCF (Hoog),PCF (høy),PCF (Wysoki),PCF (Alto),,PCF (Ridicat),PCF (высокий),PCF (високо),PCF (Yüksek),PCF (високий), -Cubic,OPTVAL_CUBIC,,,,Kubická,Kubisk,Kubisch,,Kuba,Cúbico,,Kuutio,Cubique,Négyzetes,Cubico,キュービック,큐빅,Kubieke,Kubisk,Sześcienny,Cúbico,,Cub,Кубическое,Кубан,Kübik,Кубічне, -Band-limited step,OPTVAL_BLEP,,,,Omezené krokování,Båndbegrænset trin,Bandbegrenzte Schritte,,Bendo-limigita paŝo,Paso limitado por banda,,Kaistarajoitettu askel,Step limité par bande,Sáv-limitált lépés,Passo limitato dalla banda,帯域制限ステップ,제한된 단계별 밴드,Bandbeperkte stap,Båndbegrenset trinn,Krok ograniczony pasmem,Passo limitado por banda,,Limitare frecvență pas-cu-pas,Ограниченный полосой пропускания шаг,Постепено ограничење фреквенције,Bant sınırlı adım,Покрокове обмеження частоти, -Linear (Slower),OPTVAL_LINEARSLOW,,,,Lineární (pomalejší),Lineær (langsommere),Linear (langsamer),,Lineara (Pli malrapida),Lineal (más lento),,Lineaarinen (hitaampi),Linéaire (Lent),Lineáris (Lassabb),Lineare (più lento),リニア(遅め),선형 (느리게),Lineair (langzamer),Lineær (langsommere),Liniowy (wolniejszy),Linear (mais lento),,Liniar (Mai lent),Линейное (медленнее),Линеаран (спорије),Doğrusal (Daha Yavaş),Лінійне (повільніше), -Band-limited linear,OPTVAL_BLAM,,,,Omezená lineární,Båndbegrænset lineær,Bandbegrenzt linear,,Bendo-limigita lineara,Lineal limitado por banda,,Kaistarajoitettu lineaarinen,Linéaire limité par bande,Sáv-limitált lineáris,Lineare limitato dalla banda,帯域制限リニア,밴드 제한 식 선형,Band-beperkt lineair,Båndbegrenset lineær,Liniowy ograniczony pasmem,Linear limitado por banda,,Limitare frecvență liniară,Ограниченное полосой пропускания линейное,Линеарно ограничење фреквенције,Bant sınırlı doğrusal,Лінійне обмеження частоти, -Cubic (Slower),OPTVAL_CUBICSLOW,,,,Kubická (pomalejší),Kubisk (langsommere),Kubisch (langsamer),,Kuba (Pli malrapida),Cúbico (más lento),,Kuutio (hitaampi),Cubique (Lent),Négyzetes (Lassabb),Cubico (più lento),キュービック (遅め),큐빅 (느리게),Kubieke (langzamer),Kubisk (langsommere),Sześcienny (wolniejszy),Cúbico (mais lento),,Cub (Mai lent),Кубическое (медленнее),Кубан (спорије),Kübik (Daha Yavaş),Кубічне (повільніше), -Sinc,OPTVAL_SINC,,,,,Sinc,,,,Seno cardinal,,,,,,シンク,싱크,,,,Seno cardinal,,Sinus cardinal,Кардинальный синус,Синк,,Функція sinc, -Note on/off only,OPTVAL_NOTEONOFFONLY,,,,Pouze začátek/konec noty,Kun note on/off,Nur für Note an/aus ,,Nur noto ek/for,Solo notas de Activ./Desact.,,Vain nuotti päällä/pois,Note on/off seulement,Hangjegy ki/be csak,Note solamente ON/OFF,ノート オン/オフ のみ,노트를 끄거나 켰을 때,Alleen toon aan/uit,Merk kun på/av,Tylko dla włączonych/wyłączonych notatek,Somente notas ligadas/desligadas,,Numai la activarea/oprirea notelor,Только при включении/отключении нот,Само током укључења/искључења ноте,Yalnızca not açma/kapama,Тільки при ввімкненні/вимкненні нот, -Full ramping,OPTVAL_FULLRAMPING,,,,Plný náběh,Fuld rampe,,,Plena pligrandigado,Aumento completo,,Täysi kerrytys,Rampe complète,Teljes ramping,Ramping completo,フルランピング,최대 램핑,Volledige helling,Full ramping,Pełne zwiększenie,Rampa completa,,Creștere completă,Полное наращивание,Пуно појачање,Tam rampa,Повне нарощування, -Master volume,MODMNU_MASTERVOLUME,,,,Celková hlasitost,Master-volumen,Grundlautstärke,,Ĉeflaŭteco,Volumen maestro,,Yleisäänenvoimakkuus,Volume maître,Fő hangerő,Volume master,全体音量,마스터 볼륨,Hoofdvolume,Hovedvolum,Całkowita głośność,Volume geral,,Volum general,Общая громкость,Глацни звук,Ana ses seviyesi,Загальна гучність, -Quality,MODMNU_QUALITY,,,,Kvalita,Kvalitet,Qualität,,Kvaliteco,Calidad,,Laatu,Qualité,Minőség,Qualità,クオリティ,품질,Kwaliteit,Kvalitet,Jakość,Qualidade,,Calitate,Качество,Квалитет,Kalite,Якість, -Volume ramping,MODMNU_VOLUMERAMPING,,,,Křivka hlasitosti,Lydstyrke-rampe,Lautstärkeverhalten,,Laŭteco-pligrandigado,Aumento gradual de Volumen,,Äänenvoimakkuuden kertyminen,Rampe du volume,,Ramping volume,音量ランピング,볼륨 램핑,Volume-aanvulling,Volumramping,Zwiększenie głośności,Rampa de volume,,Creștere volum,Наращивание громкости,Појачавање звука,Hacim artırma,Нарощування гучності, -Chip-o-matic,MODMNU_CHIPOMATIC,,,,,,,,,,,,,,,チップ オー マチック,칩-오-매틱,,,,,,,,,,, -MAME OPL2,OPTVAL_MAMEOPL2,,,,,,,,,,,,,,,,마메 OPL2,,,,,,,,,,, -DOSBox OPL3,OPTVAL_DOSBOXOPL3,,,,,,,,,,,,,,,,도스박스 OPL3,,,,,,,,,,, -Java OPL3,OPTVAL_JAVAOPL3,,,,,,,,,,,,,,,,자바 OPL3,,,,,,,,,,, -Nuked OPL3,OPTVAL_NUKEDOPL3,,,,,,,,,,,,,,,,,,,,,,,,,,, -MAME YM2612,OPTVAL_MAMEOPN2,,,,,,,,,,,,,,,,마메 YM2612,,,,,,,,,,, -Neko Project II Kai OPNA,OPTVAL_NP2OPNA,,,,,,,,,,,,,,,,,,,,,,,,,,, -MAME YM2608,OPTVAL_MAMEOPNA,,,,,,,,,,,,,,,,마메 YM2608,,,,,,,,,,, -PMDWin OPNA,OPTVAL_PMDWINOPNA,,,,,,,,,,,,,,,,,,,,,,,,,,, -Opal OPL3,OPTVAL_OPALOPL3,,,,,,,,,,,,,,,,,,,,,,,,,,, -Nuked OPL3 v1.7.4,OPTVAL_NUKEDOPL3174,,,,,,,,,,,,,,,,,,,,,,,,,,, -Nuked OPN2,OPTVAL_NUKEDOPN2,,,,,,,,,,,,,,,,,,,,,,,,,,, -GENS YM2612,OPTVAL_GENSOPN2,,,,,,,,,,,,,,,,,,,,,,,,,,, -Auto (Use setup of bank),ADLVLMODEL_AUTO,,,,Auto (použít nastavení sady),Auto (Brug opsætning af bank),Auto (Benutze Einstelliung der Bank),,Aŭtomata (Uzi bankagordaĵon),Auto (Usar config. del banco),,Automaattinen (käytä pankin asetuksia),Auto (Utiliser paramètre banque),Automatikus (Beállított bank használata),Automatico (Usa le impostazioni del bank),自動(bankのセットアップ使用),자동(뱅크 셋업 사용),Auto (gebruik instelling van de bank),Auto (Bruk oppsett av bank),Automatycznie (Użyj ustawień banku),Automático (usar definições de banco),,Auto (configurare din bancă),Авто (настройка из банка),Аутоматски (користи намештену банку),Otomatik (Banka kurulumunu kullan),Авто (налаштування з банку), -Generic,ADLVLMODEL_GENERIC,,,,Standardní,Generisk,Allgemein,,Komuna,Genérico,,Yleinen,Générique,Általános,Generico,一般的,전형적,Algemeen,Generisk,Ogólne,Genérico,,,Общий,Генерично,Jenerik,Загальний, -OPL Native,ADLVLMODEL_NATIVE,,,,Nativní OPL,OPL Native,OPL Nativ,,Nativa OPL,Nativo OPL,,Luontainen OPL,OPL Natif,Natív OPL,,OPLネイティブ,고유 OPL,,,Natywne OPL,Nativo OPL,,OPL propriu,Встроенная OPL,OPL домаћи,OPL Yerli,Вбудована OPL, -"DMX (Accurate, with AM bug)",ADLVLMODEL_DMX,,,,"DMX (Přesný, s AM chybou)","DMX (nøjagtig, med AM-fejl)",,,,,,,,"DMX (Pontos, de AM buggal)",,,데이터 마이닝 확장,"DMX (accuraat, met AM bug)","DMX (Nøyaktig, med AM-feil)",,"DMX (preciso, com bug de AM)",,"DMX (Precis, cu probleme în AM)","DMX (Точная, с ошибкой АМ)",,"DMX (Doğru, AM hatalı)","DMX (Точна, з помилкою АМ)", -"Apogee (Accurate, with AM bug)",ADLVLMODEL_APOGEE,,,,"Apogee (Přesný, s AM chybou)","Apogee (nøjagtig, med AM-fejl)",,,,,,,,"Apogee (Pontos, de AM buggal)",,,어포지,"Apogee (accuraat, met AM bug)","Apogee (Nøyaktig, med AM-feil)",,"Apogee (preciso, com bug de AM)",,"Apogee (Precis, cu probleme în AM)","Apogee (Точная, с ошибкой АМ)",,"Apogee (Doğru, AM hatası ile)","Apogee (Точна, з помилкою АМ)", -Win9X-like (SB16),ADLVLMODEL_WIN9X,,,,Jako Windows 9X (SB16),Win9X-lignende (SB16),Wie Windows 9X (SB16),,Kiel Win9X (SB16),Como Win9X (SB16),,Win9x-kaltainen (SB16),,Win9X szerű (SB16),,Win9X式 (SB16),Win9X 같게 (SB16),Win9X-achtig (SB16),Win9X-lignende (SB16),Jak w Win9X (SB16),Estilo Win9X (SB16),,Similar cu Win9X (SB16),Похожая на Win9X (Вариант SB16),Као у Win9X-у (SB16),Win9X benzeri (SB16),Схожа на Win9X (Варіант SB16), -Win9X-like (Generic FM),ADLVLMODEL_WIN9XGENERIC,,,,Jako Windows 9X (Generic FM),Win9X-lignende (generisk FM),Wie Windows 9X (Generic FM),,Kiel Win9X (Generic FM),Como Win9X (Generic FM),,Win9x-kaltainen (Generic FM),,Win9X szerű (Általános FM),,Win9X式 (Generic FM),Win9X 같게 (Generic FM),Win9X-achtig (Generic FM),Win9X-lignende (Generisk FM),Jak w Win9X (Generic FM),Estilo Win9X (FM genérico),,Similar cu Win9X (Generic FM),Похожая на Win9X (Вариант Generic FM),Као у Win9X-у (Generic FM),Win9X benzeri (Jenerik FM),Схожа на Win9X (Варіант Generic FM), -DMX (Without AM voice bug),ADLVLMODEL_DMX_FIXED,,,,DMX (Bez AM hlasové chyby),DMX (uden AM-stemmefejl),DMX (Ohne AM-Stimmenfehler),,DMX (Sen cimo de AM-voĉo),DMX (Sin bug de voz AM),,DMX (ilman AM-äänivikaa),DMX (Sans bug canaux AM),DMX (AM hanghiba nélkül),,DMX(AMボイスバグ無し),,DMX (zonder AM voice bug),DMX (uten AM-stemmefeil),DMX (bez głosowego błędu AM),DMX (sem bug de voz de AM),,DMX (Fără probleme în AM),DMX (Без ошибки АМ),,DMX (AM ses hatası olmadan),DMX (Без помилки АМ), -Apogee (Without AM voice bug),ADLVLMODEL_APOGEE_FIXED,,,,Apogee (Bez AM hlasové chyby),Apogee (uden AM-stemmefejl),Apogee (Ohne AM-Stimmenfehler),,Apogee (Sen cimo de AM-voĉo),Apogee (Sin bug de voz AM),,Apogee (ilman AM-äänivikaa),Apogee (avec bug canaux AM),Apogee (AM hanghiba nélkül),,Apogee(AMボイスバグ無し),,Apogee (zonder AM voice bug),Apogee (uten AM-stemmefeil),Apogee (bez głosowego błędu AM),Apogee (sem bug de voz de AM),,Apogee (Fără probleme în AM),Apogee (Без ошибки АМ),,Apogee (AM ses hatası olmadan),Apogee (Без помилки АМ), -IBM Audio Library Interface,ADLVLMODEL_AIL,,,,,,,,IBM Aŭdbibiloteka Interfaco,,,,,IBM Hang Könyvtár Interfész,,,,,,Interfejs Biblioteki Dźwięków IBM,Interface de Biblioteca de Áudio IBM,,Interfață de Bibliotecă IBM,IBM AIL,,IBM Ses Kitaplığı Arayüzü,, -HMI Sound Operating System,ADLVLMODEL_HMI,,,,,,,,HMI Sonoperaciumo,,,,,HMI Hang Operációs Rendszer,,,,,,System Operacyjny Dźwięków HMI,Sistema Operacional de Som HMI,,Sistem Sonor HMI,HMI SOS,,HMI Ses İşletim Sistemi,, -"HMI SOS (Old, with bugs)",ADLVLMODEL_HMIOLD,,,,"HMI SOS (Starý, s chybami)","HMI SOS (gammelt, med fejl)","HMI SOS (alt, mit Fehlern)",,"HMI SOS (Malnova, kun cimoj)","HMI SOS (Viejo, con bugs)",,"HMI SOS (vanha, vikainen)",HMI SOS (vieux et buggé),"HMI SOS (Régi, bugokkal)",,"HMI SOS(旧式,バグ含む)",,"HMI SOS (oud, met bugs)","HMI SOS (gammel, med feil)","HMI SOS (Stare, z błędami)","SOS HMI (antigo, com bugs)",,"HMI SOS (Vechi, cu probleme)",HMI SOS (Старый вариант с ошибками),,"HMI SOS (Eski, hatalı)",HMI SOS (Старий варіант з помилками), -Unlimited,OPTVAL_UNLIMITED,,,,Neomezené,Ubegrænset,Unlimitiert,,Senlima,Ilimitado,,Rajoittamaton,Illimité,Végtelen,Illimitato,無制限,무제한,Onbeperkt,Ubegrenset,Nieskończone,Sem limites,,Nelimitat,Без ограничений,Бескрајно,Sınırsız,Безмежно, -256K,OPTVAL_256K,,,,,,,,,,,,,,,,,,,,,,,,,,, -512K,OPTVAL_512K,,,,,,,,,,,,,,,,,,,,,,,,,,, -768K,OPTVAL_768K,,,,,,,,,,,,,,,,,,,,,,,,,,, -1024K,OPTVAL_1024K,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,Postprocessing,,,,,,,,,,,,,,,,,,,,,,,,,, -Uncharted 2,OPTVAL_UNCHARTED2,,,,,,,,,,,,,,,,,,,,,,,,,,, -Hejl Dawson,OPTVAL_HEJLDAWSON,,,,,,,,,,,,,,,,,,,,,,,,,,, -Reinhard,OPTVAL_REINHARD,,,,,,,,,,,,,,,,,,,,,,,,,,, -Palette,OPTVAL_PALETTE,,,,Paleta,Palet,,Παλέτα,Paletro,Paleta,,Paletti,,Paletta,Palette,パレット,팔레트,Palet,Palette,Paleta,Paleta,Palete,Paletă,Палитра игры,Палет,Palet,Палітра гри, -Low,OPTVAL_LOW,,,,Nízká,Lav,Niedrig,Χαμηλό,Malalta,Bajo,,Matala,Bas,Alacsony,Basso,低,낮음,Laag,Lav,Niskie,Baixo,,Scăzut,Низкое,Ниско,Düşük,Низьке, -Medium,OPTVAL_MEDIUM,,,,Střední,Medium,Mittel,Μεσαίο,Meza,Medio,,Keskitaso,Moyen,Közepes,Medio,中,중간,Middel,Middels,Średnie,Médio,,Mediu,Среднее,Средње,Orta,Середнє, -High,OPTVAL_HIGH,,,,Vysoká,Høj,Hoch,Υψηλό,Alta,Alto,,Korkea,Haut,Magas,Alto,高,높음,Hoog,Høy,Wysokie,Alto,,Ridicat,Высокое,Високо,Yüksek,Високе, -Extreme,OPTVAL_EXTREME,,,,Extrémní,Ekstrem,Extrem,Ακράιο,Ekstrema,Extremo,,Äärimmäinen,Extrême,Extrém,Estremo,最高,매우 높음,Extreem,Ekstrem,Ekstremalne,Extremo,,Extrem,Максимальное,Екстремно,Aşırı,Максимальне, -Obverse,OPTVAL_OBVERSEFIRST,,,,Vpřed (obvers),Forside,Obvers,Παρατήρησε,Antaŭa,Anverso,,Etupuoli,,Ellentétes,Dritto,正面,앞면,Obvers,Forside,Awers,Obverso,,Avers,Прямой,Супротно,Ön yüz,Прямий, -Reverse,OPTVAL_REVERSEFIRST,,,,Vzad (revers),Bagside,Revers,Αντίστροφο,Inversa,Inverso,,Käänteinen,Inverse,Fordított,Contrario,反転,반전,Revers,Baksiden,Rewers,Reverso,,Invers,Обратный,Обрнуто,Ters,Зворотний, -Postprocessing,GLMNU_POSTPROCESS,,,,,Efterbehandling,,Μετα-επεξεργασία,Postprocezado,Postprocesado,,Jälkikäsittely,,,,ポストプロセッシング,포스트프로세싱 적용,Nabewerking,Etterbehandling,Przetwarzanie końcowe,Pós-processamento,,Postprocesare,Постобработка,Пост обрада,İşlem sonrası,Постобробка, -Tonemap Mode,GLPREFMNU_TONEMAP,,,,Režim tónovací mapy,Tonemap-tilstand,Tonemap Modus,,Reĝimo de Tonmapo,Modo de mapa de tonos,,Sävykarttatila,Mode Tonemap,Színleképzés módja,Modalità Tonemap,トーンマップ モード,톤맵 모드,Tonemap modus,Tonemap-modus,Tryb Mapowania Tonów,Tipo de tonemap,,Mod Tonemap,Режим тонового отображения,Тонирано-мапни мод,Ton Haritası Modu,Режим тонального відображення, -Lens distortion effect,GLPREFMNU_LENS,,,,Efekt distorze čočky,Objektivforvrængningseffekt,Optischer Verzerrungseffekt,,Lensdistorto-efiko,Efecto de distorsión de lente,,Linssinvääristystehoste,Effet distorsion de lentille,Lencsetorzulás effekt,Effetto distorsione della lente,レンズの歪みエフェクト,렌즈 왜곡 효과,Effect van de lensvervorming,Linseforvrengningseffekt,Efekt zniekształcenia obiektywu,Distorção de lente,Efeito de distorção da lente,Efect de distorsionare,Эффект искажения линзы,Дисторзија објектива ефект,Lens bozulma efekti,Ефект деформації лінзи, -FXAA Quality,GLPREFMNU_FXAA,,,,Kvalita FXAA,FXAA-kvalitet,FXAA Qualität,FXAA ποίοτητα,Kvaliteco de FXAA,Calidad FXAA,,FXAA-laatu,Qualité FXAA,FXAA minősége,Qualità FXAA,FXAA品質,FXAA 품질,FXAA-kwaliteit,FXAA-kvalitet,Jakość FXAA,Qualidade de FXAA,,Calitate FXAA,Качество FXAA,FXAA квалитет,FXAA Kalitesi,Якість FXAA, -Dither output,GLPREFMNU_DITHER,,,,Dithering,Dither-udgang,Dithering,,Apliki punktojn al eligo,Dither de salida,,Sekoitussävytyksen (dithering) ulostulo,Dithering,Árnyalás kimenet,Dithering,ディザー出力,떨림 효과 출력,Dither output,Dither-utgang,Dygotanie,Dithering,,Putere Dithering,Дизеринг,Учестаност трептања,Dither çıkışı,Дитеринг, -Tonemap Palette Order,GLPREFMNU_PALTONEMAPORDER,,,,Pořadí palety tónovací mapy,Tonemap-palettens rækkefølge,Palettensortierung für Tonemap,,Ordo de Kolormapo-Paletro,Orden de la paleta en mapa de tonos,,Sävykartan paletin järjestys,Ordre des palettes tonemap,Színleképzés paletta sorrend,Ordine della Palette Tonemap,トーンマップパレット順序,톤맵 팔레트 순서,Tonemap Palet Orde van het Tonemap-palet,Tonemap-palettrekkefølge,Kolejność Palet Mapowania Tonów,Ordem da paleta tonemap,,Ordine paletă Tonemap,Порядок палитры тонового отображения,Тонирано-мапни палетни ред,Ton Haritası Palet Sırası,Порядок палітри тонального відображення, -Tonemap Palette Exponent,GLPREFMNU_PALTONEMAPPOWER,,,,Exponent palety tónovací mapy,Tonemap-palettens eksponent,Palettenexponent für Tonemap,,Exponeto de Kolormapo-Paletro,Exponente paleta en mapa de tonos,,Sävykartan paletin eksponentti,Exponent des palettes tonemap,Tonemap Paletta Exponens,Esponente della Palette Tonemap,トーンマップパレット指数,톤맵 팔레트 지수,Tonemap Palet Exponent,Tonemap Palette Eksponent,Wykładnik Palet Mapowania Tonów,Expoente da paleta tonemap,,Exponent paletă Tonemap,Экспонента палитры тонового отображения,Тонирано-мапни палетни експонент,Ton Haritası Paleti Üsteli,Експонента палітри тонального відображення, -Multisample,GLPREFMNU_MULTISAMPLE,,,,Multisampling,Multisample,Multisampling,,Plurspecimeno,Multisampling,,Moninäytteistys,,,,マルチサンプル,멀티샘플,,,Multipróbkowanie,Multiamostragem,,Multisampling,Мультисэмплинг,Мулти-узорак,Çoklu Örneklem,Багатовибіркове згладжування, -Bloom effect,GLPREFMNU_BLOOM,,,,Efekt bloom,Bloom-effekt,Bloom Effekt,,Lumŝmiro-efiko,Efecto Bloom,,Hehkutehoste (bloom),Effet surbrillance,Bloom effekt,Effetto Bloom,ブルーム エフェクト,블룸 효과,Bloom-effect,Bloom-effekt,Effekt Bloom,Bloom,,Efect Bloom,Свечение,Мутан вид ефект,Çiçeklenme etkisi,Ефект сяйва, -Ambient occlusion quality,GLPREFMNU_SSAO,,,,Kvalita ambient occlusion,Omgivende okklusionskvalitet,Ambient Occlusion Qualität,,Kvaliteco de media obstrukceco,Calidad de oclusión ambiental,,Yleisvarjostuksen (ambient occlusion) laatu,Qualité Occlusion Ambiente,Ambient occlusion minősége,Qualità occlusione ambientale,アンビエント オクルージョンの品質,주변 환경 가림 효과 품질,Kwaliteit van omgevingsverduistering,Omgivende okklusjonskvalitet,Jakość okluzji otoczenia,Qualidade de oclusão de ambiente,,Calitate ocluzie ambientală,Качество глобального затенения,Оклузија амбијента ефект,Ortam oklüzyon kalitesi,Якість глобального затінення, -Portals with AO,GLPREFMNU_SSAO_PORTALS,,,,Portály s AO,Portaler med AO,Portale mit AO,,Portaloj kun Media obstrukceco,Portales con OA,,Yleisvarjostuksen portaalit,OA pour les portails,Portálok AO-val,Portali con l'OA,AOを伴うポータル,주변 환경 가려진 포탈,Portals met AO,Portaler med AO,Portale z okluzją otoczenia,Portais com oclusão de ambiente,,Portaluri cu ocluzie ambientală,Порталы с глобальным затенением,Портали са AO,AO'lu Portallar,Портали з глобальним затіненням, -Menu Blur,GLPREFMNU_MENUBLUR,,,,Rozostření pozadí v menu,Menu sløring,Menüunschärfe,Θόλοση μενού,Malklarigo de menuo ,Difuminación de menú,,Valikon sumennus,Flou menu,Menü mosódás,Blur del menu,メニューブラー,메뉴 흐림 효과,Menu vervagen,Meny uskarphet,Rozmycie w Menu,Desfoque do menu,Desfocagem do Menu,Neclaritate Meniu,Размытие фона меню,Блур мениа,Menü Bulanıklığı,Розмиття фону в меню, -Environment map on mirrors,GLPREFMNU_ENVIRONMENTMAPMIRROR,,,,Mapa prostředí na zrcadlech,Miljøkort på spejle,Lichteffekt auf Spiegeln,,Medimapo sur speguloj,Mapa de entorno en espejos,,Ympäristökartta peileissä,Mappage environment sur les miroirs,Környezet tükröződés,Ambiente mappa sugli specchi,マップオンミラーの画像表示,거울 주변의지도 활성,Milieukaart op spiegels,Omgivelseskart på speil,Mapa środowiska w lustrach,Mapa de ambiente em espelhos,,Efecte suplimentare pentru oglinzi,Карта окружения на зеркалах,Околинска мапа на прозорима,Aynalar üzerinde çevre haritası,Карта оточення на дзеркалах, -Rendering quality,GLPREFMNU_RENDERQUALITY,,,,Kvalita vykreslování,Renderingskvalitet,Renderqualität,,Kvalito de bildigado,Calidad de renderizado,,Hahmonnuslaatu,Qualité du rendu,Renderelés minősége,Qualità resa grafica,レンダリング品質,렌더링 품질,Het teruggeven van kwaliteit,Renderingskvalitet,Jakość Renderowania,Qualidade de renderização,,Calitate video,Качество отрисовки,Квалитет рендовања,Render kalitesi,Якість візуалізації, -Speed,OPTVAL_SPEED,,,,Rychlost,Hastighed,Geschwindigkeit,Ταχύτητα,Rapido,Velocidad,,Nopeus,Vitesse,Sebesség,Prestazioni,速度寄り,성능,Snelheid,Hastighet,Szybkość,Velocidade,,Viteză,Скорость,Брзина,Hız,Швидкість, -Quality,OPTVAL_QUALITY,,,,Kvalita,Kvalitet,Qualität,Ποιότητα,Kvalito,Calidad,,Laatu,Qualité,Minőség,Qualità,品質寄り,고품질,Kwaliteit,Kvalitet,Jakość,Qualidade,,Calitate,Качество,Квалитет,Kalite,Якість, -Sector light mode,GLPREFMNU_SECLIGHTMODE,,,,Režim osvětlení sektorů,Sektorlystilstand,Sektorlichtmodus,,Reĝimo de sektorlumo,Modo de luz de sector,,Sektorivalojen tila,Mode de lumière Secteur,Szektor fény mód,Modalità luce di settore,セクターライトモード,섹터 조명 모드,Sector lichte wijze,Sektorlysmodus,Tryb oświetlenia sektorów,Modo de luz de setor,,Mod iluminare sectorială,Режим освещения секторов,Секторско светло мод,Sektör ışığı modu,Режим освітлення секторів, -Fog mode,GLPREFMNU_FOGMODE,,,,Režim mlhy,Tågetilstand,Nebelmodus,Λειτουργία ομίχλης,Reĝimo de nebulo,Modo de niebla,,Sumutila,Mode du broullard,Köd mód,Effetto nebbia,フォグモード,안개 모드,Mistmodus,Tåkemodus,Tryb mgły,Modo de neblina,,Mod ceață,Режим тумана,Магла мод,Sis modu,Режим туману, -Radial,OPTVAL_RADIAL,,,,Radiální,Radial,,Ακτινικό,Radiusa,,,Säteittäinen,,Sugaras,Radiale,放射状,방사형,Radiaal,,Promieniowe,,,Radială,Круговой,Радијално,Radyal,Радіальний, -Standard,OPTVAL_STANDARD,,,,Standardní,,,,Norma,Estándar,,Normaali,,Szabvány,Standard,標準,기본,Standaard,,Standard,Padrão,,,Стандартный,Стандардно,Standart,Стандартний, -,,Texture options,,,,,,,,,,,,,,,,,,,,,,,,,, -Texture Filter mode,GLTEXMNU_TEXFILTER,,,,Režim filtrování textur,Tilstand for teksturfilter,Texturfiltermodus,,Reĝimo por Teksturfiltrado,Modo de filtro de texturas,,Pintakuviointien suodatustapa,Mode de Filtrage Texture,Textúrafilter módja,Modalità filtro texture,テクスチャーフィルター モード,텍스쳐 필터 모드,Textuurfiltermodus,Teksturfilter-modus,Tryb Filtrowania Tekstur,Modo de filtro de textura,,Mod Filtrare Texturi,Фильтрация текстур,Текстурни филтер мод,Doku Filtresi modu,Тип фільтрації текстур, -Anisotropic filter,GLTEXMNU_ANISOTROPIC,,,,Anisotropické filtrování,Anisotropisk filter,Anisotropische Filterung,,Anizotropa filtro,Filtro anisotrópico,,Anisotrooppinen suodatus,Filtre Anisotropique,Anizotropikus filter,Filtro anisotropico,異方性フィルター,이방성 필터,Anisotroopfilter,Anisotropisk filter,Filtr anizotropowy,Filtro anisotrópico,,Filtrare Anizotropică,Анизотропная фильтрация,Анизотропни фолтер,Anizotropik filtre,Анізотропна фільтрація, -None (nearest mipmap),OPTVAL_NONENEARESTMIPMAP,,,,Žádné (mipmapa - nejbližší soused),Ingen (nærmeste mipmap),Aus (nächste Mipmap),,Nenio (plej proksima mipmapo),Ninguno (mipmap cercano),,Ei mitään (lähin mipkartta),Aucun (mipmap proche voisin),Semmilyen (közeli mipmap),Nessuno (mipmap più vicina),なし(最寄りミップマップ),없음 (밉멥에 가까움),Geen (dichtstbijzijnde mipmap),Ingen (nærmeste mipmap),Brak (najbliższa mipmapa),Nenhum (mipmap mais próximo),,Niciuna (mipmap de apropriere),Нет (ближайший MIP-уровень),Ништа (најближи мипмап),Yok (en yakın mipmap),Ніякий (найближчий міпмап), -None (linear mipmap),OPTVAL_NONELINEARMIPMAP,,,,Žádné (mipmapa - lineární),Ingen (lineær mipmap),Aus (lineare Mipmap),,Nenio (linia mipmapo),Ninguno (mipmap lineal),,Ei mitään (lin. mipkartta),Aucun (mipmap linéaire),Semmilyen (lineáris mipmap),Nessuno (mipmap lineare),なし(リニアミップマップ),없음 (선형 밉맵),Geen (lineaire mipmap),Ingen (lineær mipmap),Brak (liniowa mipmapa),Nenhum (mipmap linear),,Niciuna (mipmap liniar),Нет (линейный MIP-уровень),Ништа (линеаран мипмап),Yok (doğrusal mipmap),Ніякий (лінійний міпмап), -None (trilinear),OPTVAL_NONETRILINEAR,,,,Žádné (trilineární),Ingen (trilineær),Aus (trilinear),,Nenio (trilinia),Ninguno (trilineal),,Ei mitään (trilineaarinen),Aucun (mipmap trilinéaire),Semmilyen (trilineáris),Nessuno (mipmap trilineare),なし(トライリニア),없음 (삼선형),Geen (trilineair),Ingen (trilineær),Brak (trzyliniowe),Nenhum (trilinear),,Niciuna (trilinar),Нет (трилинейная),Ништа (трилинеарно),Yok (trilineer),Ніякий (трилінійний), -Bilinear,OPTVAL_BILINEAR,,,,Bilineární,Bilineær,,,Dulinia,Bilineal,,Bilineaarinen,Bilinéaire,Bilineáris,Bilineare,バイリニア,쌍선형,Bilineair,Bilineær,Dwuliniowe,Bilinear,,Biliniar,Билинейная,Билинеарно,Bilineer,Білінійний, -Trilinear,OPTVAL_TRILINEAR,,,,Trilineární,Trilineær,,,Trilinia,Trilineal,,Trilineaarinen,Trilinéaire,Trilineáris,Trilineare,トライリニア,삼선형,Trilineair,Trilineær,Trzyliniowe,Trilinear,,Triliniar,Трилинейная,Трилинеарно,Trilineer,Трилінійний, -2x,OPTVAL_2X,,,,,,,,2-oble,,,,,,,,,,,,,,,,,,, -4x,OPTVAL_4X,,,,,,,,4-oble,,,,,,,,,,,,,,,,,,, -8x,OPTVAL_8X,,,,,,,,8-oble,,,,,,,,,,,,,,,,,,, -16x,OPTVAL_16X,,,,,,,,16-oble,,,,,,,,,,,,,,,,,,, -32x,OPTVAL_32X,,,,,,,,32-oble,,,,,,,,,,,,,,,,,,, -Texture Options,GLTEXMNU_TITLE,,,,Nastavení textur,Indstillinger for teksturer,Texturoptionen,,Agordoj de Teksturoj,Opciones de texturas,,Pintakuviointiasetukset,Options Textures,Textúra Beállítások,Opzioni Texture,テクスチャー オプション,텍스쳐 설정,Textuur Opties,Teksturalternativer,Opcje Tekstur,Opções de Textura,,Setări Texturi,Настройки текстур,Подешавања текстура,Doku Seçenekleri,Параметри текстур, -Textures enabled,GLTEXMNU_TEXENABLED,,,,Povolit textury,Teksturer aktiveret,Texturen an,,Teksturoj ŝaltitaj,Texturas activadas,,Pintakuvioinnit otettu käyttöön,Textures activées,Textúrák bekapcsolása,Texture abilitate,テクスチャー有効,텍스쳐 사용,Texturen ingeschakeld,Teksturer aktivert,Tekstury włączone,Texturas ativadas,,Texturi Activate,Включить текстуры,Текстуре омогућене,Dokular etkinleştirildi,Увімкнути текстури, -Enable hires textures,GLTEXMNU_ENABLEHIRES,,,,Povolit textury ve vysokém rozlišení,Aktivere hi-res teksturer,Hochauflösende Texturen an,,Ŝalti Altdistingivajn Teksturojn,Activar texturas de alta resolución,,Salli korkean erotuskyvyn pintakuvioinnit,Activer Textures haute résolution,Magas felbontású textúrák bekapcsolása,Abilita texture alta qualità,ハイレゾ テクスチャー有効,고해상도 텍스쳐 사용,Hoge-resolutie texturen op,Aktivere høyoppløselige teksturer,Włącz tekstury wysokiej jakości,Habilitar texturas de alta resolução,,Texturi de înaltă rezoluție,Текстуры высокого разрешения,Омогући текстуре велике резолуције,Yüksek çözünürlüklü dokuları etkinleştir,Увімкнути текстури високого розширення, -High Quality Resize mode,GLTEXMNU_HQRESIZE,,,,Režim zvětšovače textur,Tilstand til ændring af størrelse i høj kvalitet,Texturskalierungsmodus,,Reĝimo de Altdistingivigo-Skalilo,Modo de ajuste de alta calidad,,Korkealaatuinen kuvakoon muutostapa,Mise à l'échelle haute résolution,Magas minőségű újraméretező mód,Modalità resize alta qualità,高品質リサイズ モード,고퀄리티 리사이즈 모드,Textuurschaalmodus,Høy kvalitet Endre størrelse-modus,Tryb Wysokiej Jakości Zmieniania Rozmiaru,Modo de Redimensionamento de Alta Qualidade,,Mod Redimensionare de Înaltă Calitate,Режим высококачественного масштабирования текстур,Промена величине високог квалитета мод,Yüksek Kalite Yeniden Boyutlandırma modu,Масштабування текстур, -High Quality Resize multiplier,GLTEXMNU_HQRESIZEMULT,,,,Faktor zvětšovače textur,Multiplikator for ændring af størrelse i høj kvalitet,Texturskaluerungsfaktor,,Obligilo de Altdistingivigo-Skalilo,Multiplicador de ajuste de alta calidad,,Korkealaatuisen kuvakokomuutoksen kerroin,Multiplicateur de mise à l'échelle,Magas minőségű újraméretezés szorzó,Moltiplicatore resize alta qualità,高品質リサイズ乗数,고퀄리티 리사이징 승수,Textuurschaalfactor,Multiplikator for størrelsesendring av høy kvalitet,Mnożnik Wysokiej Jakośći Rozmiaru,Multiplicador de Redimensionamento de Alta Qualidade,,Factor de Scalare,Множитель высококачественного масштабирования,Промена величине високог квалитета мултипликатор,Yüksek Kalite Yeniden Boyutlandırma çarpanı,Множник масштабування, -This mode requires %d times more video memory,GLTEXMNU_HQRESIZEWARN,,,,Tento režim potřebuje %dkrát více paměti,Denne tilstand kræver %d gange mere videohukommelse,Dieser Modus benötigt das %d-fache an Videospeicher,Αυτή η λειτουργία χρειάζετε %d περισσότερες φορές μνήμη βίντεο,Ĉi tiu reĝimo bezonas %d-oble pli da ekranmemoro.,Este modo requiere %d veces más memoria de vídeo,,Tämä tila vaatii %d kertaa enemmän videomuistia,Ce mode nécessite %d fois plus de mémoire vidéo,Ez a mód a jelenlegi videó memória %d-szeresét igényli,Questa modalità richiede %d volte la memoria video,このモードでは %d 倍以上のビデオメモリが必要です!,이 설정은 비디오 메모리의 %d 배가 더 필요합니다.,Deze modus vereist %d keer meer videogeheugen.,Denne modusen krever %d ganger mer videominne,Ten tryb wymaga %d razy więcej pamięci wideo,Este modo precisa de %d vezes mais memória de vídeo,,Acest mod necesită de %d mai multă memorie video,Данный режим требует в %d раз больше видеопамяти,Овај мод тражи %d пута више видео меморије,Bu mod %d kat daha fazla video belleği gerektirir,Цьому типу потрібно в %d більше відеопам'яті, -Resize textures,GLTEXMNU_RESIZETEX,,,,Škálovat textury,Ændre størrelse på teksturer,Texturen skalieren,,Regrandigi teksturojn,Ajustar texturas,,Muuta pintakuviointien kokoa,Mise à l'échelle textures,Textúrák újraméretezése,Resize delle texture,リサイズ テクスチャー,텍스쳐 리사이징,Texturen schalen,Endre størrelse på teksturer,Zmień rozmiar tekstur,Redimensionar texturas,,Redimensionare texturi,Масштабирование текстур,Промена величине текстура,Dokuları yeniden boyutlandırma,Масштабування текстур, -Resize sprites,GLTEXMNU_RESIZESPR,,,,Škálovat sprity,Ændre størrelse på sprites,Sprites skalieren,,Regrandigi spritojn,Ajustar sprites,,Muuta spritejen kokoa,Mise à l'échelle sprites,Sprite-ok újraméretezése,Resize degli sprite,リサイズ スプライト,스프라이트 리사이징,Sprites schalen,Endre størrelse på sprites,Zmień rozmiar sprite'ów,Redimensionar sprites,,Redimensionare sprite-uri,Масштабирование спрайтов,Промена величине спрајтова,Sprite'ları yeniden boyutlandırma,Масштабування спрайтів, -Resize fonts,GLTEXMNU_RESIZEFNT,,,,Škálovat fonty,Ændre størrelse på skrifttyper,Zeichensätze skalieren,,Regrandigi tiparojn,Ajustar fuentes,,Muuta kirjasinten kokoa,Mise à l'échelle texte,Betűk újraméretezése,Resize dei font,リサイズ フォント,폰트 리사이징,Lettertypen schalen,Endre størrelse på skrifter,Zmień rozmiar czcionek,Redimensionar fontes,,Redimensionare fonturi,Масштабирование шрифтов,Промена величине фонта,Yazı tiplerini yeniden boyutlandırma,Масштабування шрифтів, -Resize model skins,GLTEXMNU_RESIZESKN,,,,Škálovat skiny modelů,Ændre størrelsen på modelskins,,,Regrandigi haŭtojn de modeloj,Ajustar texturas de modelo,,Muuta ulkoasujen kokoa,,Model fazon újraméretezése,Ridimensiona skin modello,リサイズ モデルスキン,,,Endre størrelse på modellskinn,Zmień rozmiar modelu,Redimensionar skins de modelos,,Redimensionare modele,Масштабирование обликов моделей,,Model kaplamalarını yeniden boyutlandırma,Масштабування текстур моделей, -Precache GL textures,GLTEXMNU_PRECACHETEX,,,,Přednačíst GL textury do cache,Precache GL-teksturer,GL Texturen zwischenspeichern,,Antaŭkaŝmemorigi GL-teksturojn,Precaché de texturas GL,,Kirjoita GL-pintakuvioinnit välimuistiin,Mise en cache des textures,Előcachelt GL textúrák,Precache texture GL,プリキャッシュ GLテクスチャー,지엘 텍스쳐 미리 캐싱함,Precache GL texturen,Precache GL-teksturer,Tekstury GL pamięci podręcznej,Precachê de texturas GL,,Preîncărcarcă texturile GL,Кэшировать GL-текстуры,Прикеширане GL текстуре,GL dokularını önceden önbelleğe alma,Кешувати GL-текстури, -Video Mode,VIDMNU_TITLE,,,,Režim displeje,Videotilstand,Videomodus,Λειτουργία βίντεο,Video-reĝimo,Modos de vídeo,Modos de video,Videotila,Mode Vidéo,Videó mód,Modalità video,ビデオ 調整,화면 설정,Videomodus,Videomodus,Tryb Wideo,Modo de vídeo,,Mod Video,Настройки видеорежима,Видео мод,Video Modu,Налаштування відеорежиму, -Notebook Switchable GPU,DSPLYMNU_GPUSWITCH,,,,Přepínatelné GPU pro notebooky,Notebook Switchable GPU,GPU Umschaltung für Notebooks,,Kajero-ŝanĝebla GPU,GPU switching de portátil,,Kannettavan kytkettävä grafiikkapiiri,GPU alternatif sur PC Portable,Laptop Váltható GPU,Scheda GPU Switchable per notebook,ノートブックGPU切替,노트북 성능 조정,Notitieboekje schakelbare GPU,Notatbok Byttbar GPU,Zmiana GPU Notebooka,Placa de vídeo alternável de notebook,,Placă Video Alternativă pentru Notebook,Использование видеокарты ноутбука,Користи GPU ноутбук,Dizüstü Bilgisayar Değiştirilebilir GPU,Використання GPU ноутбука, -Scaled (Nearest),OPTVAL_SCALENEAREST,,,,Škálován (nejbližší),Skaleret (Nærmeste),Skaliert (nächster Nachbar),,Skalita (Plej proksime),Escalado (Lo más cerca),,Skaalattu (läheisin),Mis à l'échelle (Proche Voisin),Átméretezett (Közeli),Scalato (più vicino),スケーリング (最寄り),확대 (가깝게),Geschaald (Dichtstbijzijnd),Skalert (nærmeste),Przeskalowany (Najbliższy),Redimensionado (mais próximo),Redimensionado (Apróximado),Redimensionat (Cel mai aproape),Масштабировать (ближайшее),Скалиран (најближи),Ölçeklendirilmiş (En Yakın),Збільшення (ближнє), -Scaled (Linear),OPTVAL_SCALELINEAR,,,,Škálován (lineární),Skaleret (lineær),Skaliert(linear),,Skalita (Linie),Escalado (Lineal),,Skaalattu (lineaarinen),Mis à l'échelle (Linéaire),Átméretezett (Lineáris),Scalato (lineare),スケーリング (リニア),확대 (선형 식),Geschaald (Lineair),Skalert (lineær),Przeskalowany (Liniowy),Redimensionado (linear),,Redimensionat (Liniar),Масштабировать (линейное),Скалиран (линеарно),Ölçeklendirilmiş (Doğrusal),Збільшення (лінійне), -Letterbox,OPTVAL_LETTERBOX,,,,,,,,Leterkesto,Barras negras,,Mustat reunat,,Levágott,Bande nere,レターボックス,레터박스,,,,Barras pretas,,Ecran Parțial,Экранное каше,Поштанско сандуче,,Техніка каше, -Stretch,OPTVAL_STRETCH,,,,Roztažený,Stræk,Strecken,,Streĉi,Estrechado,Estrecho,Venytetty,Etirer,Nyújtott,Disteso,伸縮,늘림,Rek,Strekk,Rozciągnięty,Esticado,,Lărgire,Растянутый,Растегнуто,Esneme,Розтягнутий, -Render Mode,VIDMNU_RENDERMODE,,,,Režim rendereru,Rendertilstand,Rendermodus,,Bildigo-reĝimo,Modo de renderizado,,Hahmonnustila,Mode de Rendu,Render Mód,Modalità rendering,レンダラー,렌더링 설정,Rendermodus,Gjengivelsesmodus,Tryb Renderowania,Modo de renderização,,Mod Video,Режим отрисовки,Рендер мод,İşleme Modu,Режим візуалізації, -Fullscreen,VIDMNU_FULLSCREEN,,,,Přes celou obrazovku,Fuld skærm,Vollbild,Πλήρης οθόνη,Plena ekrano,Pantalla completa,,Koko näyttö,Plein écran,Teljes Képernyő,Schermata piena,全画面,전체화면,Volledig scherm,Fullskjerm,Pełen Ekran,Tela cheia,Ecrã cheio,Ecran Complet,Полный экран,Цео екран,Tam Ekran,Повноекранний, -Retina/HiDPI support,VIDMNU_HIDPI,,,,Podpora Retiny/HiDPI,Retina/HiDPI-understøttelse,Retina/HDPI-Unterstützung,,Retino/HiDPI subteno,Soporte para Retina/HiDPI,,Retina/HiDPI-tuki,Support Retina/HiDPI ,Retina/HiDPI támogatás,Supporto Retina/HiDPi,Retina/HiDPI サポート,망막/하이DPI 활성화,Retina / HiDPI-ondersteuning,Retina/HiDPI-støtte,Wsparcie Retina/HiDPI,Suporte para Retina/HiDPI,,Suport Retina/HiDPI,Поддержка Retina/HiDPI,Retina/HiDPI подршка,Retina/HiDPI desteği,Підтримка Retina/HiDPI, -Aspect ratio,VIDMNU_ASPECTRATIO,,,,Poměr stran,Aspektforhold,Seitenverhältnis,,Ekran-proporcio,Relación de aspecto,,Kuvasuhde,Rapport D'Aspect,Képarány,Proporzioni,アスペクト比,종횡비,Beeldverhouding,Bildeforhold,Wpółczynnik proporcji,Proporção de tela,Proporção de ecrã,Aspect Imagine,Соотношение сторон,Однос гледишта,En boy oranı,Співвідношення сторін, -Force aspect ratio,VIDMNU_FORCEASPECT,,,,Vynutit poměr stran,Tvinge formatforhold,Erzwinge Seitenverhältnis,,Devigi ekran-proporcion,Forzar relación de aspecto,,Pakota kuvasuhde,Forcer Rapport,Képarány kényszerítése,Forza le proporzioni video,アスペクト比に従う,강제 종횡비,Geforceerde beeldverhouding,Tving sideforhold,Wymuś współczynnik proporcji,Forçar proporção de tela,Forçar proporcção de ecrã,Forțează aspectul imaginii,Принудительное соотношение сторон,Присили однос гледишта,Kuvvet en-boy oranı,Примусове співвідношення сторін, -Forced ratio style,VIDMNU_CROPASPECT,,,,Vynucený poměr stran,Stil med tvunget forhold,Modus für erzwungenes Seitenverhältnis,,Stilo por devigita proporcio,Relación de aspecto forzada,,Kuvasuhteen pakotustapa,Style de Ratio forcé,Kényszerített képarány stílusa,Forza lo stile delle proporzioni,比率の形式,강제 비율 스타일,Geforceerde verhoudingsstijl,Tvunget formatforhold-stil,Wymuszony styl współczynnika,Estilo de proporção forçado,,Forțează tipul proporțiilor,Тип принудительного соотношения сторон,Присиљен стил односа,Zorlanmış oran stili,Тип примусового співвідношення сторін, -Enable 5:4 aspect ratio,VIDMNU_5X4ASPECTRATIO,,,,Povolit poměr stran 5:4,Aktiver 5:4-billedformat,Erlaube 5:4 Seitenverhältnis,,Ŝalti 5:4 ekran-proporcion,Activar relación de aspecto 5:4,,Ota käyttöön 5:4-kuvasuhde,Activer Rapport 5:4,5:4 képarány engedélyezése,Abilita le proporzioni 5:4,5:4アスペクト比を可能にする,5:4 비율 사용,Schakel 5:4 beeldverhouding in,Aktiver 5:4 sideforhold,Włącz współczynnik proporcji 5:4,Ativar proporção de tela 5:4,,Activează formatul 5:4,Включить соотношение сторон 5:4,Омогући 5:4 однос гледишта,5:4 en boy oranını etkinleştirin,Увімкнути співвідношення сторін 5:4, -Resolution scale,VIDMNU_SCALEMODE,,,,Škálování rozlišení,Opløsningsskala,Skalierung,,Distingivo-skalo,Escala de resolución,,Resoluution skaalaus,Echelle de Résolution,Felbontás mérete,Scala di risoluzione,画面スケール,해상도 크기,Resolutieschaal,Oppløsningsskala,Skala rozdzielczości,Escala de resolução,,Scară rezoluție,Масштабирование,Резолуцијска скала,Çözünürlük ölçeği,Масштабування, -Scale Factor,VIDMNU_SCALEFACTOR,,,,Faktor rozlišení,Skalafaktor,Skalierungsfaktor,,Skalfaktoro,Factor de escala,,Skaalauskerroin,Facteur d'échelle,Méretezési Faktor,Fattore di scala,スケール倍率,축척 펙터,Schaalfactor,Skaleringsfaktor,Współczynnik Skali,Fator de escala,,Factor Scalare,Значение масштаба,Фактор скалирања,Ölçek Faktörü,Значення масштабування, -Use Linear Scaling (Fullscreen),VIDMNU_USELINEAR,,,,Použít lineární škálování (přes celou obrazovku),Brug lineær skalering (fuld skærm),Lineare Skalierung (Vollbild),,Uzi linian skaladon (Plenekrane),Usar escalado linear (Pant. completa),,Lineaarinen skaalaus (koko näyttö),Mise à l'échelle Linéaire (Plein écran),Lineáris Méretezés Használata (Teljes képernyő),Usa lo scaling lineare (a schermo pieno),リニアスケールを使う(全画面),선형 스케일링 사용 (전체화면),Lineaire schaalverdeling gebruiken (volledig scherm),Bruk lineær skalering (fullskjerm),Użyj Liniowego Skalowania (Pełen Ekran),Usar escala linear (tela cheia),Usar escala linear (ecrã cheio),Folosește Scalarea Liniară (Ecran Complet),Линейное масштабирование (полный экран),Користи линеарно скалирање (цео екран),Doğrusal Ölçeklemeyi Kullan (Tam Ekran),Лінійне масштабування (повний екран), -Custom Pixel Scaling,VIDMNU_CUSTOMRES,,,,Vlastní škálování pixelů,Brugerdefineret pixelskalering,Benutzerdefinierte Skalierung,,Adaptita rastrumero-skalo,Escalado de píxel personalizado,,Mukautettu skaalaus,Résolution Personalisée,Egyéni Pixelméretezés,Scaling dei pixel personalizzato,カスタム ピクセルスケール,사용자 지정 픽셀 크기 조정,Aangepaste pixelschaalvergroting,Egendefinert pikselskalering,Niestandardowe Skalowanie Pikseli,Escala de pixels personalizada,,Scară Pixeli Personalizată,Масштабирование пикселей,Пиксел скалирање,Özel Piksel Ölçeklendirme,Масштабування пікселів, -Custom Width,VIDMNU_CUSTOMX,,,,Vlastní šířka,Brugerdefineret bredde,Benutzerdefinierte Breite,,Adaptita larĝeco,Ancho personalizado,,Mukautettu leveys,Largeur Personalisée,Egyéni szélesség,Lunghezza,カスタム 幅,사용자 지정 너비,Aangepaste breedte,Egendefinert bredde,Niestandardowa Szerokość,Largura personalizada,,Lățime Personalizată,Длина,Ширина,Özel Genişlik,Довжина, -Custom Height,VIDMNU_CUSTOMY,,,,Vlastní výška,Brugerdefineret højde,Benutzerdefinierte Höhe,,Adaptita alteco,Alto personalizado,,Mukautettu korkeus,Hauteur Personalisée,Egyéni magasság,Altezza,カスタム 高さ,사용자 지정 높이,Aangepaste hoogte,Egendefinert høyde,Niestandardowa Wysokość,Altura personalizada,,Înălțime Personalizată,Высота,Висина,Özel Yükseklik,Висота, -Apply Changes (Windowed),VIDMNU_APPLYW,,,,Použít změny (v okně),Anvend ændringer (vindue),Änderungen anwenden (Fenster),,Apliki ŝanĝojn (Fenestrite),Aplicar cambios (Ventana),,Ota käyttöön muutokset (ikkuna),Appliquer Changements (Fenêtre),Változtatások Elfogadása (Ablak),Applica le modifiche (a finestra),変更を適用(ウィンドウ化),변경 적용 (윈도우),Wijzigingen toepassen (in venster),Bruk endringer (vindusbasert),Zatwierdź Zmiany (Okno),Aplicar alterações (janela),,Aplică Schimbările (Mod Fereastră),Сохранить изменения (оконный режим),Примени промене (прозор),Değişiklikleri Uygula (Pencereli),Зберегти зміни (віконний режим), -Apply Changes (Fullscreen),VIDMNU_APPLYFS,,,,Použít změny (přes celou obrazovku),Anvend ændringer (fuld skærm),Änderungen anwenden (Vollbild),,Apliki ŝanĝojn (Plenekrane),Aplicar cambios (Pant. completa),,Ota käyttöön muutokset (koko näyttö),Appliquer Changements (Plein écran),Változtatások Elfogadása (Teljes képernyő),Applica le modifiche (a schermo pieno),変更を適用(全画面化),변경 적용 (전체화면),Wijzigingen toepassen (Volledig scherm),Bruk endringer (fullskjerm),Zatwierdź Zmiany (Pełen Ekran),Aplicar alterações (tela cheia),Aplicar alterações (ecrã cheio),Aplică Schimbările (Mod Ecran Complet),Сохранить изменения (полный экран),Примени промене (цели екран),Değişiklikleri Uygula (Tam Ekran),Зберегти зміни (повноекранний режим), -Choose Resolution Preset,VIDMNU_RESPRESET,,,,Vybrat přednastavené rozlišení,Vælg forindstillet opløsning,Auflösungsvoreinstellung,,Elekti antaŭagorditan distingivon,Elegir resolución predefinida,,Valitse ennalta määritetty resoluutio,Choisir paramètre personalisé,Felbontási Sablon Kiválasztása,Scegli preset di risoluzione,解像度プリセットを選ぶ,해상도 사전 설정 선택,Kies een vooraf ingestelde resolutie,Velg forhåndsinnstilt oppløsning,Wybierz Zestaw Rozdzielczości,Escolher resolução predefinida,,Alege Rezoluția Predefinită,Выбор шаблона разрешения,Резолуцијска подешавања,Çözünürlük Ön Ayarını Seçin,Вибір пресету роздільної здатності, -Custom Resolution Presets,VIDMNU_RESPRESETTTL,,,,Vlastní přednastavení rozlišení,Brugerdefinerede opløsningsforudindstillinger,Benutzerdefinierte Auflösungsvoreinstellungen,,Viaj antaŭagorditaj distingivoj,Resoluciones predefinidas personalizadas,,Ennalta määritetyt mukautetut resoluutiot,Résolutions Personalisée,Egyéni Felbontási Sablonok,Preset di risoluzione personalizzati,カスタム解像度プリセット,사용자 지정 해상도 미리 조정,Vooraf ingestelde aangepaste resoluties,Egendefinerte forhåndsinnstillinger for oppløsning,Niestandardowe Zestawy Rozdzielczości,Predefinições de resolução personalizadas,,Rezoluții Personalizate,Пользовательские шаблоны,Резолуцијска подешавања,Özel Çözünürlük Ön Ayarları,Користувацькі пресети, -Preset Resolution Modes,VIDMNU_RESPRESETHEAD,,,,Přednastavená rozlišení,Forindstillede opløsningsmodes,Vordefinierte Auflösungsmodi,,Reĝimoj pri antaŭagordita distingivo,Modos de resolución predefinida,,Ennalta määritetyt resoluutiotilat,Choisir mode de Résolution,Felbontási Sablon Módok,Modalità preset di risoluzione,解像度モードの調整,해상도 미리 조정 모드,Vooraf ingestelde resolutiemodi,Forhåndsinnstilte oppløsningsmoduser,Tryby Zestawów Rozdzielczości,Modos de resolução predefinidas,,Rezoluții Predefinite,Доступные разрешения,Постављени резолуцијски модови,Önceden Ayarlanmış Çözünürlük Modları,Доступні роздільні здатності, -4:3 Aspect,VIDMNU_ASPECT43,,,,Poměr stran 4:3,4:3 Aspekt,4:3 Seitenverhältnis,,4:3 proporcio,Aspecto 4:3,,4:3-tilat,Rapport 4:3,4:3 Arány,Aspetto 4:3,4:3アスペクト比,4:3 비율,Beeldverhouding 4:3,4:3 Aspekt,Proporcje 4:3,Proporção 4:3,,Aspect 4:3,Соотношение сторон 4:3,4:3 гледиште,4:3 Görüntü,Співвідношення сторін 4:3, -5:4 Aspect,VIDMNU_ASPECT54,,,,Poměr stran 5:4,5:4 Aspekt,5:4 Seitenverhältnis,,5:4 proporcio,Aspecto 5:4,,5:4-tilat,Rapport 5:4,5:4 Arány,Aspetto 5:4,5:4アスペクト比,5:4 비율,Beeldverhouding 5:4,5:4 Aspekt,Proporcje 5:4,Proporção 5:4,,Aspect 5:4,Соотношение сторон 5:4,5:4 гледиште,5:4 Görüntü,Співвідношення сторін 5:4, -16:9 Aspect,VIDMNU_ASPECT169,,,,Poměr stran 16:9,16:9 Aspekt,16:9 Seitenverhältnis,,16:9 proporcio,Aspecto 16:9,,16:9-tilat,Rapport 16:9,16:9 Arány,Aspetto 16:9,16:9アスペクト比,16:9 비율,Beeldverhouding 16:9,16:9 Aspekt,Proporcje 16:9,Proporção 16:9,,Aspect 16:9,Соотношение сторон 16:9,16:9 гледиште,16:9 Görüntü,Співвідношення сторін 16:9, -16:10 Aspect,VIDMNU_ASPECT1610,,,,Poměr stran 16:10,16:10 Aspekt,16.10 Seitenverhältnis,,16:10 proporcio,Aspecto 16:10,,16:10-tilat,Rapport 16:10,16:10 Arány,Aspetto 16:10,16:10アスペクト比,16:10 비율,Beeldverhouding 16:10,16:10 Aspekt,Proporcje 16:10,Proporção 16:10,,Aspect 16:10,Соотношение сторон 16:10,16:10 гледиште,16:10 Aspect,Співвідношення сторін 16:10, -21:9 Aspect,VIDMNU_ASPECT219,,,,Poměr stran 21:9,21:9 Aspekt,21.9 Seitenverhältnis,,21:9 proporcio,Aspecto 21:9,,21:9-tilat,Rapport 21:9,21:9 Arány,Aspetto 21:9,21:9アスペクト比,21:9 비율,Beeldverhouding 21:9,21:9 Aspekt,Proporcje 21:9,Proporção 21:9,,Aspect 21:9,Соотношение сторон 21:9,21:9 гледиште,21:9 Görüntü,Співвідношення сторін 21:9, -Normal,OPTVAL_NORMAL,,,,Normální,,,,Normala,,,Normaali,,Normál,Normale,通常,기본형,Normaal,,Normalny,Normal,,,Обычный,Нормално,Normal,Нормальний, -Lowest Possible Scale,OPTVAL_LOWEST,"This describes vid_scalemode 1, which represents the lowest possible scaling to fill the allocated screen area",,,Nejmenší možná velikost,Lavest mulige skala,Kleinstmögliche Auflösung,,Plej malalta ebla skalo,Menor escala posible,,Pienin mahdollinen skaalaus,Echelle la plus faible,Lehető legkisebb méret,Scala minima,可能な限り最小,,Laagst mogelijk schaal,Lavest mulig skala,Najniższa możliwa skala,Menor escala possível,,Cea mai Mică Scară Posibilă,Наименьший возможный масштаб,,Mümkün Olan En Düşük Ölçek,Найменш можливий масштаб, -Custom,OPTVAL_CUSTOM,,,,Vlastní,Brugerdefineret,Benutzerdefiniert,,Agordita de vi,Personalizado,,Mukautettu,Modifié,Egyéni,Personalizzato,カスタム,사용자 지정,Gebruikergedefinieerd,Egendefinert,Niestandardowe,Personalizado,,Personalizat,Польз.,Прилагођ.,Özel,Корист., -Max FPS,VIDMNU_MAXFPS,,,,Maximální FPS,,,,Maksimumaj kadroj laŭ sekundo,Límite de FPS,,Kuvataajuuden rajoitin,,,FPS Massimi,最大FPS値,,Max FPS,Maks FPS,Maksymalna ilość klatek,FPS máximo,,Cadre pe secundă,Максимальная частота кадров,,Maksimum FPS,Макс. частота кадрів, -60 fps,OPTVAL_60FPS,,,,,,,,,,,60 kuvaa/s,,,,,,,,,60 FPS,,,60 к/с,,,60 кадрів, -75 fps,OPTVAL_75FPS,,,,,,,,,,,75 kuvaa/s,,,,,,,,,75 FPS,,,75 к/с,,,75 кадрів, -90 fps,OPTVAL_90FPS,,,,,,,,,,,90 kuvaa/s,,,,,,,,,90 FPS,,,90 к/с,,,90 кадрів, -120 fps,OPTVAL_120FPS,,,,,,,,,,,120 kuvaa/s,,,,,,,,,120 FPS,,,120 к/с,,,120 кадрів, -144 fps,OPTVAL_144FPS,,,,,,,,,,,144 kuvaa/s,,,,,,,,,144 FPS,,,144 к/с,,,144 кадри, -200 fps,OPTVAL_200FPS,,,,,,,,,,,200 kuvaa/s,,,,,,,,,200 FPS,,,200 к/с,,,200 кадрів, -Preferred Rendering API,VIDMNU_PREFERBACKEND,,,,Upřednostňované render API,Foretrukken Rendering API,Bevorzugtes Render API,Προτιμούμενο Rendering API,Preferita bildigado de API,API de renderizado preferida,,Ensisijainen hahmonnuksen ohjelmointirajapinta,API de rendu préférée,Előnyben részesített renderelő API,API di rendering preferita,優先レンダリングAPI,기본적인 API 랜더링,Voorkeur rendering API,Foretrukket Rendering API,Preferowany interfejs API renderowania,API de renderização preferida,,API Video Preferat,Предпочтительный API отрисовки,Преферред АПИ приказивања,Tercih Edilen Rendering API,Бажаний інтерфейс візуалізації, -OpenGL,OPTVAL_OPENGL,,,,,,,,,,,,,,,,,,,,,,,,,,, -Vulkan,OPTVAL_VULKAN,,,,,,,,,,,,,,,,,,,,,,,,,,, -OpenGL ES,OPTVAL_OPENGLES,Rendering backend,,,,,,,,,,,,,,,,,,,,,,,,,, -,,Miscellaneous Options,,,,,,,,,,,,,,,,,,,,,,,,,, -Merge left+right Alt/Ctrl/Shift,MISCMNU_MERGEKEYS,,,,Kombinovat pravý a levý Alt/Ctrl/Shift,Flette venstre+højre Alt/Ctrl/Shift,Linke und rechte Umschalt/Strg/Alt zusammenfassen,,Kunigi maldekstran kaj dekstran Alt/Ctrl/Shift,Combinar Alt/Ctrl/Mayús izq. y der.,Combinar Alt/Ctrl/Shift izq. y der.,Yhdistä vasen ja oikea Alt/Ctrl/Vaihto,Combiner Alt/Ctrl/maj gauche & droite,Bal és jobb Ctrl/Alt/Shift egyként érzékelése,Unisci sinistra+destra Alt/Control/Maiusc,左と右のALT/CTRL/SHIFTキーを統合,양쪽 ALT/CTRL/SHIFT키 합병,Samenvoegen links+rechts Alt/Ctrl/Shift,Slå sammen venstre+høyre Alt/Ctrl/Shift,Połącz przyciski lewo+prawo Alt/Ctrl/Shift,"Unir as teclas Alt, Ctrl e Shift esquerdos e direitos",Juntar Alt/Ctrl/Shift esquerdo+direito,Combină Alt/Ctrl/Shift stâng+drept,Не различать левую/правую ALT/CTRL/SHIFT,Споји лево+десно Аlt/Ctrl/Shift,Sol+sağ birleştirme Alt/Ctrl/Shift,Не розділяти лівий/правий ALT/CTRL/SHIFT, -Alt-Enter toggles fullscreen,MISCMNU_WINFULLSCREENTOGGLE,,,,Alt-Enter přepíná celou obrazovku,Alt-Enter skifter til fuld skærm,Alt-Enter schaltet Vollbild an/aus,,Alt+Enter baskuligas tutekranan reĝimon,Alt+Enter alterna pantalla completa,,Alt-Enter kytkee täyden ruudun päälle/pois,Alt-Entrée alterne plein écran,Alt-Enter teljes képernyőre kapcsol,Alt-Invio attiva/disattiva lo schermo pieno,ALTとENTERで全画面に切り替え,ALT+ENTER키로 전체화면 조정,Alt-Enter schakelt het volledige scherm aan/uit,Alt-Enter veksler til fullskjerm,Alt-Enter przełącza na pełen ekran,Alt+Enter ativa tela cheia,Alt-Enter ativa ecrã cheio,Alt-Enter comută modul ecran complet,Переключение полного экрана по ALT+ENTER,Alt-Enter пребацује на цео екран,Alt-Enter tam ekrana geçiş yapar,Перемикання повного екрану на ALT+ENTER, -Command-F toggles fullscreen,MISCMNU_MACFULLSCREENTOGGLE,,,,Command-F přepíná celou obrazovku,Command-F skifter til fuld skærm,Cmd-F schaltet Vollbild an/aus,,Komando-F baskuligas tutekranan reĝimon,Cmd-F alterna pantalla completa,,Komento-F kytkee täyden ruudun päälle/pois,Command-F alterne plein écran,Command-F teljes képernyőre kapcsol,Command-F attiva/disattiva lo schermo pieno,Ctrl + Fキーで全画面表示,COMMAND+F키로 전체화면 조정,Command-F schakelt het volledige scherm aan/uit,Kommando-F veksler til fullskjerm,Command-F przełącza pełny ekran,Command+F ativa tela cheia,Command-F ativa ecrã cheio,Command-F comută modul ecran complet,Переключение полного экрана по Command+F,Command-F пребацује на цео екран,Command-F tam ekrana geçiş yapar,Перемикання повного екрану на Command+F, -Enable autosaves,MISCMNU_ENABLEAUTOSAVES,,,,Povolit automatické ukládání,Aktiver autosaves,Automatisches Speichern,,Ŝalti aŭtomatajn konservojn de ludadoj,Activar autoguardado,,Ota käyttöön automaattiset tallennukset,Activer Sauvegardes auto,Automentések engedélyezése,Abilita i salvataggi automatici,オートセーブを有効化,빠른 저장 허용,Automatisch opslaan inschakelen,Aktiver automatisk lagring,Włącz autozapis,Ativar salvamento automático,Permitir gravação automática,Permite salvări automate,Автосохранения,Омогући аутосејвове,Otomatik kaydetmeyi etkinleştir,Автозбереження, -Number of autosaves,MISCMNU_AUTOSAVECOUNT,,,,Počet automaticky uložených her,Antal autosaves,Anzahl von automatischen Speicherständen,,Maksimuma kvanto da aŭtomataj konservoj,Cantidad máxima de autoguardados,,Automaattisten tallennusten lukumäärä,Total de sauvegardes auto,Automentések száma,Numero di salvataggi automatici,オートセーブの最大数,빠른 저장 수,Aantal auto-opslagen,Antall autolagringer,Liczba autozapisów,Número de salvamentos automáticos,Número de gravações automáticas,Număr salvări automate,Количество автосохранений,Број аутоматских чувања,Otomatik kaydetme sayısı,Кількість автозбрежень, -Save/Load confirmation,MISCMNU_SAVELOADCONFIRMATION,,,,Potvrzení o uložení/načtení,Bekræftelse af gem/indlæsning,Laden/Speichern bestätigen,,Konfirmo de konservo/ŝargo,Confirmación al guardar/cargar,,Tallennuksen/Latauksen vahvistus,Confirmation C/S,Mentés/betöltés megerősítése,Conferma Salvataggio/Caricamento,セーブ/ロード時に確認,스크립트로 스크린샷 생성 허용,Opslaan/Laad bevestiging,Bekreftelse for lagring/innlasting,Potwierdzenie zapisu/wczytania,Confirmação ao salvar/carregar,Confirmação ao gravar/carregar,Dialog de confirmare la Salvare/Încărcare,Подтверждение при сохранении/загрузке,Потврђивање током чувања/учитавања,Kaydet/Yükle onayı,Підтвердження при збереженні/завантаженні, -Disable keyboard cheats,MISCMNU_NOCHEATS,,,,Vypnout cheaty z klávesnice,Deaktivere snyderier med tastaturet,Tastatur-Cheats deaktivieren,,Malvalidigi klavarajn trompojn,Desactivar trucos por teclado,,Poista näppäinhuijaukset,,Billentyűs csalások letiltása,Disabilita i trucchi classici,キーボードからのチート無効,,Schakel cheats uit,Deaktiver tastaturjuks,Wyłącz Oszustwa z Klawiatury,Desativar trapaças de teclado,,Dezactivează codurile din tastatură,Отключить клавиатурные чит-коды,,Klavye hilelerini devre dışı bırak,Вимкнути клавіатурні чіт-коди, -Quicksave rotation,MISCMNU_QUICKSAVEROTATION,,,,Rotace rychle uložených her,Quicksave-rotation,Schnellspeicherrotation,,Rotacio de rapidkonservo,Rotación al hacer un guardado rápido,,Pikatallennuskierto,Rotation Sauvegardes Rapides,Gyorsmentés forgás,Rotazione del quicksave,クイックセーブ間隔,빠른 저장 간격,Rouleer snelopslag,Hurtiglagring-rotasjon,Rotacja szybkich zapisów,Rotação de salvamentos rápidos,Rotação de gravações rápidas,Rotație salvări automate,Менять ячейки для быстрых сохранений,Окретање брзих чувања,Hızlı kaydetme rotasyonu,Чергування слотів швидких збережень, -Number of quicksaves in rotation,MISCMNU_QUICKSAVECOUNT,,,,Počet rychle uložených her v rotaci,Antal quicksaves i rotation,Anzahl Schnellspeicherplätze,,Kvanto da rapidkonservoj en rotaciado,Cantidad de guardados rápidos en rotación,,Pikatallennusten määrä kierrossa,Nombre de sauvegardes en rotation,Gyorsmentések száma a forgásban,Numero di quicksave in rotazione,間隔クイックセーブの数,빠른 저장 간격의 수,Aantal roulerende snelopslagplekken,Antall hurtiglagringer i rotasjon,Ilość szybkich zapisów w rotacji,Número de salvamentos rápidos em rotação,Número de gravações rápidas em rotação,Număr salvări rapide în rotație,Кол-во ячеек для быстрых сохранений,Број брзих чувања у окретању,Rotasyondaki quicksave sayısı,Кількість слотів для швидких збережень, -Disable Menu Clean Scaling,MISCMNU_CLEANMENU,,,,Zakázat čisté škálování nabídek,Deaktivere Menu Clean Scaling,Gleichmäßige Menüskalierung deaktivieren,,Malebligi puran skaladon en la ĉefmenuo,El menú principal no ocupa toda la pantalla,,Poista käytöstä valikon siisti skaalautuminen,Ne pas utilisé mise à l'échelle menu propre,Menü Tisztaarányítás kikapcsolása,Disabilita il fattore di scala pulito del menu,メニュー画面を伸縮させない,,Schakel uniforme menuschaling uit,Deaktiver ren skalering av meny,Wyłącz Czyste Skalowanie Menu,Desativar escala limpa do menu,,Dezactivează Scara Nouă a Meniurilor,Отключить чистое масштабирование меню,,Menü Temiz Ölçeklendirmeyi Devre Dışı Bırak,Вимкнути чисте масштабування меню, -Pause game in background,MISCMNU_PAUSEINBACKGROUND,,,,Pozastavit hru na pozadí,Pause spil i baggrunden,Spiel pausieren wenn im Hintergrund,,Paŭzigi ludon fone,Pausar el juego en segundo plano,,Pysäytä peli taustalla,Mettre le jeu en pause en arrière-plan,Játék megállítása a háttérben,Pausa il gioco in background,バックグラウンド時に一時停止,백그라운드에서 게임 일시 중지,Pauzeer het spel op de achtergrond,Pauser spillet i bakgrunnen,Zapauzuj grę w tle,Pausar jogo ao minimizar,,Pauză dacă jocul este minimizat.,Пауза при сворачивании окна,Паузирајте игру у позадини,Oyunu arka planda duraklat,Пауза при згортуванні вікна, -Default Crosshair,HUDMNU_CROSSHAIR,,,,Výchozí zaměřovač,Standardtrådkorset,Standard-Fadenkreuz,,Defaŭlta reteto,Retícula por defecto,,Oletustähtäin,Viseur par défaut,Alap célkereszt,Mirino di default,デフォルトの照準,기본 조준점,Standaard dradenkruis,Standard trådkors,Domyślny celownik,Mira padrão,,Țintă implicită,Прицел по умолчанию,Уобичајени нишан,Varsayılan Nişangah,Типи прицілів, -Crosshair color,HUDMNU_CROSSHAIRCOLOR,,,Crosshair colour,Barva zaměřovače,Trådkors farve,Fadenkreuzfarbe,,Retetokoloro,Color de la retícula,,Tähtäimen väri,Couleur Viseur,Célkereszt színe,Colore mirino,照準色,조준점 색깔,Dradenkruis kleur,Farge på trådkors,Kolor celownika,Cor da mira,,Culoare țintă,Цвет прицела,Боја нишана,Nişangah rengi,Колір прицілу, -Crosshair shows health,HUDMNU_CROSSHAIRHEALTH,,,,Zaměřovač zobrazuje zdraví,Trådkors viser helbred,Fadenkreuz zeigt Gesundheit,,Reteto montras sanon,Mostrar salud en retícula,,Tähtäin näyttää terveyden,Couleur Viseur selon santé,Életerő jelzése a célkereszten,Il mirino mostra la salute,照準のヘルス表示,조준점과 체력 연동,Dradenkruis toont gezondheid,Trådkorset viser helse,Celownik pokazuje zdrowie,Exibir saúde na mira,Mostra vida na mira,Ținta afișează starea sănătății,Прицел отображает здоровье,Нишан приказује здравље,Artı işareti sağlığı gösterir,Колір прицілу за станом здоров'я, -Scale crosshair,HUDMNU_CROSSHAIRSCALE,,,,Velikost zaměřovače,Skalerer trådkorset,Fadenkreuz skalieren,,Skali reteton,Escalar retícula,,Skaalaa tähtäintä,Mise à l'échelle du viseur,Célkereszt mérete,Fattore di scala del mirino,照準サイズ,조준점 크기,Dradenkruis schalen,Skalere trådkors,Skala celownika,Redimensionar mira,,Dimensiune țintă,Размер прицела,Размера нишана,Ölçekli artı işareti,Розмір прицілу, -Standard,OPTVAL_YES_STANDARD,copied from elsewhere,,,Standardní,,,Πρότυπο,Norma,Estándar,,Normaali,,Alap,,標準,기본,Standaard,,Standard,Padrão,,,Стандартный,Стандардни,Standart,Стандартний, -Enhanced,OPTVAL_YES_ENHANCED,,,,Vylepšené,Forbedret,Verbessert,Ενισχυομένο,Bonigita,Mejorado,,Paranneltu,Amélioré,Fejlesztett,Migliorata,強調,고급,Verbeterd,Forbedret,Ulepszone,Melhorado,,Îmbunătățită,Улучшенный,Побољшани,Geliştirilmiş,Покращений, -Language,OPTMNU_LANGUAGE,,,,Jazyk,Sprog,Sprache,Γλώσσα,Lingvo,Idioma,,Kieli,Langage,Nyelv,Lingua,言語設定,언어,Taal,Språk,Język,Idioma,,Limbă,Язык,Језик,Dil,Мова, -,,Reverb editor,,,,,,,,,,,,,,,,,,,,,,,,,, -Undo Changes,TXT_UNDOCHANGES,,,,Zrušit změny,Fortryd ændringer,Rückgängig machen,Αναίρεση Αλλαγών,Malfari ŝanĝojn,Anular cambios,,Peruuttaa muutokset,Révoquer les changements,Változtatások Visszavonása,Revocare le modifiche,変更を戻す,변경 사항 취소,Wijzigingen ongedaan maken,Angre endringer,Cofnij Zmiany,Desfazer alterações,,Anulează Modificările,Отменить изменения,Поништи промене,Değişiklikleri Geri Al,Відмінити зміни, -Select Environment,REVMNU_SELECT,,,,Vybrat prostředí,Vælg miljø,Umgebung wählen,Επιλογή Περιβάλλοντος,Elekti medion,Seleccionar ambiente,,Valitse tila,Sélectionner un environnement,Környezet Kiválasztása,Seleziona ambiente,反響選択,환경 선택,Selecteer omgeving,Velg miljø,Wybierz Środowisko,Selecione o ambiente,,Alegere Mediu,Выбрать окружение,Изабери окружење,Ortam Seçiniz,Вибрати оточення, -Test Environment,REVMNU_TEST,,,,Testovat prostředí,Test miljø,Umgebung testen,Δοκιμαστκό Περιβάλλον,Provi medion,Probar ambiente,,Testaa tilaa,Tester un environnement,Környezet Tesztelése,Testa ambiente,反響テスト,환경 테스트,Test omgeving,Test miljø,Testuj Środowisko,Testar ambiente,,Testare Mediu,Тестировать окружение,Тестирај окружење,Test Ortamı,Тестувати оточення, -Edit Environment,REVMNU_EDIT,,,,Upravit prostředí,Rediger miljø,Umgebung editieren,Επεξεργασία Περιβάλλοντος,Modifi medion,Editar ambiente,,Muokkaa tilaa,Modifier un environnement,Környezet Szerkesztése,Modifica ambiente,反響編集,환경 편집,Omgeving bewerken,Rediger miljø,Edytuj Środowisko,Editar ambiente,,Editare Mediu,Редактировать окружение,Уреди окружење,Ortamı Düzenle,Редагувати оточення, -New Environment,REVMNU_NEW,,,,Nové prostředí,Nyt miljø,Neue Umgebung,Νέο Περιβάλλον,Nova medio,Nuevo ambiente,,Uusi tila,Nouveau environnement,Új Környezet,Nuovo ambiente,新規反響設定,새로운 환경 생성,Nieuwe omgeving,Nytt miljø,Nowe Środowisko,Novo ambiente,,Mediu Nou,Новое окружение,Ново окружење,Yeni Çevre,Нове оточення, -Revert settings,REVMNU_REVERT,,,,Obnovit nastavení,Tilbageføre indstillinger,Zurücksetzen,Επαναφορά Ρυθμίσεων,Malfari agordojn,Revertir configuración,,Palauta asetukset,Réinitialiser les paramètres,Változtatások elvetése,Ripristina le impostazioni,設定を戻す,설정 되돌리기,Instellingen terugzetten,Tilbake innstillinger,Przywróć ustawienia,Reverter configurações,,Revenire la setările precedente,Сбросить настройки,Врати подешавања,Ayarları geri döndür,Налаштування за замовчуванням, -Environment Size,REVMNU_ENVIRONMENT_SIZE,Please translate only if you know how to properly name this technical jargon!,,,,,,Μέγεθος Περιβάλλοντος,Mediamplekso,Tamaño de ambiente,,Tilan koko,Taille Environnement,,Dimensioni dell'ambiente,反響サイズ,공간 크기,,,Rozmiar Środowiska,Tamanho do ambiente,,,,,,, -Environment Diffusion,REVMNU_ENVIRONMENT_DIFFUSION,,,,,,,Διάχυση Περιβάλλοντος,Medidifuzo,Difusión de ambiente,,Tilan äänen hajautuminen,Diffusion Environnement,,Diffusione dell'ambiente,反響伝播,공간 잔향 확산,,,Dyfuzja Środowiska,Difusão do ambiente,,,,,,, -Room,REVMNU_ROOM,,,,,,,Δωμάτιο,Ĉambro,Sala,,Tilan keskitaajuudet,Salle,,,,룸 효과,,,Pokój,Sala,,,,,,, -Room HF,REVMNU_ROOM_HF,,,,,,,Δωμάτιο HF,Ĉambro (AF),Sala (Frecuencia alta),,Tilan korkeat taajuudet,HF Salle,,,,룸 효과 HF,,,Pokój (wysokie częstotliwości),Sala (alta frequência),,,,,,, -Room LF,REVMNU_ROOM_LF,,,,,,,Δωμάτιο LF,Ĉambro (MaF),Sala (Frecuencia baja),,Tilan matalat taajuudet,LF Salle,,,,룸 효과 LF,,,Pokój (niskie częstotliwości),Sala (baixa frequência),,,,,,, -Decay Time,REVMNU_DECAY_TIME,,,,,,,,Putriĝo-tempo,Tiempo de decadencia,,Häipymäaika,Temps Decay,,,,잔향 감쇠 시간,,,Czas Rozkładu,Tempo de decaimento,,,,,,, -Decay HF Ratio,REVMNU_DECAY_HF_RATIO,,,,,,,,Putriĝo-proporcio (AF),Ratio de decadencia (Frecuencia alta),,Korkeiden taajuuksien (HF) häipymissuhdeluku,,,,Decay HF比率,잔향 감쇠 HF 비율,,,Wskażnik Rozkładu dla wysokich częstotliwości,Taxa de decaimento (alta freq.),,,,,,, -Decay LF Ratio,REVMNU_DECAY_LF_RATIO,,,,,,,,Putriĝo-proporcio (MaF),Ratio de decadencia (Frecuencia baja),,Matalien taajuuksien (LF) häipymissuhdeluku,,,,Decay LF比率,잔향 감쇠 LF 비율,,,Wskaźnik Rozkładu dla niskich częstotliwości,Taxa de decaimento (baixa freq.),,,,,,, -Reflections,REVMNU_REFLECTIONS,,,,,,,Αντανακλάσεις,Reflektoj,Reflejos,,Ensiheijastukset,,,,,룸 반사,,,Obicia,Reflexos,,,,,,, -Reflections Delay,REVMNU_REFLECTIONS_DELAY,,,,,,,Καθυστέρηση Αντανακλάσεων,Prokrasto de reflektoj,Retraso de reflejos,,Ensiheijastusten viive,Délai Reflections,,,,룸 반사 딜레이 시간,,,Opóźnienie Odbić,Atraso de reflexos,,,,,,, -Reflections Pan X,REVMNU_REFLECTIONS_PAN_X,,,,,,,,Reflektoj alturnas tra X,Desplazamiento en X de reflejos,,Ensiheijastusten X-panorointi,Orientation Reflections X,,,Reflections X定位,X축 룸 반사,,,Odbicia Osi X,Deslocamento X de reflexos,,,,,,, -Reflections Pan Y,REVMNU_REFLECTIONS_PAN_Y,,,,,,,,Reflektoj alturnas tra Y,Desplazamiento en Y de reflejos,,Ensiheijastusten Y-panorointi,Orientation Reflections Y,,,Reflections Y定位,Y축 룸 반사,,,Odbicia Osi Y,Deslocamento Y de reflexos,,,,,,, -Reflections Pan Z,REVMNU_REFLECTIONS_PAN_Z,,,,,,,,Reflektoj alturnas tra Z,Desplazamiento en Z de reflejos,,Ensiheijastusten Z-panorointi,Orientation Reflections Z,,,Reflections Z定位,Z축 룸 반사,,,Odbicia Osi Z,Deslocamento Z de reflexos,,,,,,, -Reverb,REVMNU_REVERB,,,,,,,,Resono,Reverberación,,Jälkikaiunta,,,,,리버브,,,Pogłos,Reverberação,,,,,,, -Reverb Delay,REVMNU_REVERB_DELAY,,,,,,,,Prokrasto de resono,Retraso de reverberación,,Jälkikaiunnan viive,Délai Reverb,,,,리버브 지연,,,Opóźnienie Pogłosu,Atraso de reverberação,,,,,,, -Reverb Pan X,REVMNU_REVERB_PAN_X,,,,,,,,Resono alturnas tra X,Desplazamiento en X de reverberación,,Jälkikaiunnan X-panorointi,Orientation Reverb X,,,Reverb X定位,X축 리버브,,,Pogłos Osi X,Deslocamento X de reverberação,,,,,,, -Reverb Pan Y,REVMNU_REVERB_PAN_Y,,,,,,,,Resono alturnas tra Y,Desplazamiento en Y de reverberación,,Jälkikaiunnan Y-panorointi,Orientation Reverb Y,,,Reverb Y定位,Y축 리버브,,,Pogłos Osi Y,Deslocamento Y de reverberação,,,,,,, -Reverb Pan Z,REVMNU_REVERB_PAN_Z,,,,,,,,Resono alturnas tra Z,Desplazamiento en Z de reverberación,,Jälkikaiunnan Z-panorointi,Orientation Reverb Z,,,Reverb Z定位,Z축 리버브,,,Pogłos Osi Z,Deslocamento Z de reverberação,,,,,,, -Echo Time,REVMNU_ECHO_TIME,,,,,,,,Tempo de eĥo,Tiempo de eco,,Kaikuaika,Longueur écho,,,,에코 시간,,,Czas Echa,Tempo de eco,,,,,,, -Echo Depth,REVMNU_ECHO_DEPTH,,,,,,,,Produndo de eĥo,Profundidad de eco,,Kaiun syvyys,Profondeur écho,,,,에코 깊이,,,Głębokość Echa,Profundidade de eco,,,,,,, -Modulation Time,REVMNU_MODULATION_TIME,,,,,,,,Tempo de modulado,Tiempo de modulación,,Modulaatioaika,Longueur Modulation,,,,전조 시간,,,Czas Modulacji,Tempo de modulação,,,,,,, -Modulation Depth,REVMNU_MODULATION_DEPTH,,,,,,,,Produndo de modulado,Profundidad de modulación,,Modulaation syvyys,Profondeur Modulation,,,,전조 깊이,,,Głębokość Modulacji,Profundidade de modulação,,,,,,, -Air Absorption HF,REVMNU_AIR_ABSORPTION_HF,,,,,,,,Aer-absorbo AF,Absorción en aire de frecuencia alta,,Korkeiden taajuuksien (HF) ilma-absorptio,,,,,대기 흡수 HF,,,Absorbcja Powietrza (wysokie częstotliwości),Absorção de ar de alta freq.,,,,,,, -HF Reference,REVMNU_HF_REFERENCE,,,,,,,,AF referenco,Referencia de frecuencia alta,,Korkeiden taajuuksien vertausarvo,,,,HF参照値,HF 참조치,,,Odniesienie wysokich częstotliwości,Referência de alta freq.,,,,,,, -LF Reference,REVMNU_LF_REFERENCE,,,,,,,,MaF referenco,Referencia de frecuencia baja,,Matalien taajuuksien vertausarvo,,,,LF参照値,LF 참조치,,,Odniesienie niskich częstotliwości,Referência de baixa freq.,,,,,,, -Room Rolloff Factor,REVMNU_ROOM_ROLLOFF_FACTOR,,,,,,,,Ĉambro-Rolloff-faktoro,Factor de Roll-off de sala,,Tilan vaimenemiskerroin,Facteur de rolloff Salle,,,,룸 감쇠 양,,,Czynnik Zejścia,Fator de roll-off de sala,,,,,,, -Diffusion,REVMNU_DIFFUSION,,,,,,,,Difuzo,Difusión,,Diffuusio,,,,,잔향 확산,,,Dyfuzja,Difusão,,,,,,, -Density,REVMNU_DENSITY,,,,,,,,Denseco,Densidad,,Tiheys,Densité,,,密度,잔향 밀도,,,Zagęszczenie,Densidade,,,,,,, -Reflections Scale,REVMNU_Reflections_Scale,,,,,,,,Skalo de reflektoj,Escala de reflejos,,Ensiheijastusten skaala,Echelle Reflections,,,Reflections音階,룸 반사 음계,,,Rozmiar Odbić,Escala de reflexos,,,,,,, -Reflections Delay Scale,REVMNU_Reflections_Delay_Scale,,,,,,,,Prokrastskalo de reflektoj,Escala de retraso de reflejos,,Ensiheijastusten viiveen skaala,Délai d'échelle reflections,,,Reflections Delay音階,룸 반사 딜레이 음계,,,Skala Opóźnienia Odbić,Escala de atraso de reflexos,,,,,,, -Decay Time Scale,REVMNU_Decay_Time_Scale,,,,,,,,Tempskalo de purtiĝo,Escala de tiempo de decadencia,,Häipymäajan skaala,Echelle temporelle Decay,,,Decay Time音階,잔향 감쇠시간 음계,,,Skala Czasu Rozkładu,Escala de tempo de decaimento,,,,,,, -Decay HF Limit,REVMNU_Decay_HF_Limit,,,,,,,,AF-Limito de purtiĝo,Limite de decadencia de alta frecuencia,,Häipymän korkeiden taajuuksien raja-arvo,,,,Decay HF限度,잔향 감쇠 HF 한도,,,Limit Rozkładu Wysokich Częstotliwości,Limite de decaimento em alta freq.,,,,,,, -Reverb Scale,REVMNU_Reverb_Scale,,,,,,,,Skalo de resono,Escala de reverberación,,Jälkikaiunnan skaala,Echelle Reverb,,,Reverb音階,리버브 음계,,,Skala Pogłosu,Escala de reverberação,,,,,,, -Reverb Delay Scale,REVMNU_Reverb_Delay_Scale,,,,,,,,Prokrastskalo de resono,Escala de retraso de reverberación,,Jälkikaiunnan viiveen skaala,Délai d'échelle Reverb,,,Reverb Delay音階,리버브 딜레이 음계,,,Skala Opóźnienia Pogłosu,Escala de atraso de reverberação,,,,,,, -Echo Time Scale,REVMNU_Echo_Time_Scale,,,,,,,,Tempskalo de eĥo,Escala de tiempo de eco,,Kaikuajan skaala,Echelle temporelle Echo,,,Echo Time音階,에코 시간 음계,,,Skala Czasu Echa,Escala de tempo de eco,,,,,,, -Modulation Time Scale,REVMNU_Modulation_Time_Scale,,,,,,,,Tempskalo de modulado,Escala de tiempo de modulación,,Modulaatioajan skaala,Echelle temporelle Modulation,,,Modulation Time音階,전조 시간 음계,,,Skala Modulacji Czasu,Escala de tempo de modulação,,,,,,, -Based on,REVMNU_Based_on,,,,Založeno na,Baseret på,Basierend auf,Βασισμένο σε,Bazita de,Basado en,,Perustana,Basé sur,Minta,Basato su,音響の元,음향 원본,Gebaseerd op,Basert på,Bazowane na,Baseado em,,Bazat pe,Основано на,Засновано на,Buna göre,Засновано на, -Name,REVMNU_Name,,,,Název,Navn,,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Navn,Nazwa,Nome,,Nume,Название,Назив,İsim,Назва, -ID #1,REVMNU_ID_1,,,,,,,ID #1,Identigo #1,ID Nº1,,,,,ID N°1,,아이디 #1,,,ID #1,ID #1,,,ИД №1,,,, -ID #2,REVMNU_ID_2,,,,,,,ID #2,Identigo #2,ID Nº2,,,,,ID N°2,,아이디 #2,,,ID #2,ID #2,,,ИД №2,,,, -Create,REVMNU_Create,,,,Vytvořit,Opret,Erstellen,Δημιουργία,Krei,Crear,,Luo,Créer,Készítés,Creare,作成,생성,Aanmaken,Opprett,Stwórz,Criar,,Creare,Создать,Направи,Oluştur,Створити, -Save...,REVMNU_Save,,,,Uložit...,Gem...,Speichern...,Αποθήκευση,Konservi...,Guardar...,,Tallenna...,Sauvegarder...,Mentés...,Salvare...,セーブする...,저장 하기...,Opslaan...,Lagre...,Zapisz...,Salvar...,,Salvare...,Сохранить...,Сачувај...,Kaydet...,Зберегти..., -File name,REVMNU_File_name,,,,Název souboru,Filnavn,Dateiname,Όνομα αρχείου,Dosiernomo,Nombre de archivo,,Tiedostonimi,Nom de fichier,Fájlnév,Nome del file,ファイル名,파일 이름,Bestandsnaam,Filnavn,Nazwa pliku,Nome do arquivo,,Nume fișier,Имя файла,Назив фајла,Dosya adı,Назва файлу, -Environments to save,REVMNU_Environments_to_save,,,,Prostředí k uložení,"Miljøer, der skal gemmes",Zu speichernde Umgebungen,Περιβάλλοντα για αποθήκευση,Medioj por konservi,Ambientes para guardar,,Tallennettavat tilat,Environnements à sauvegarder,Mentendő Környezetek,Ambienti da salvare,音響を保存,저장할 공간,Omgevingen om op te slaan,Miljøer som skal lagres,Środowiska do zapisu,Ambientes para salvar,,Medii de salvat,Сохранить окружения...,Окружења за чување,Kurtarılacak ortamlar,Зберегти оточення..., -,,Vulkan,,,,,,,,,,,,,,,,,,,,,,,,,, -Vulkan Options (Experimental),DSPLYMNU_VKOPT,,,,Nastavení Vulkanu (Experimentální),Vulkan-indstillinger (eksperimentelt),Vulkan Optionen (Experimentell),Vulka Ρυθμίσεις (Πειραματικές),Agordoj por Vulkan (Eksperimenta),Opciones de Vulkan (Experimental),,Vulkan-asetukset (kokeellinen),Options Vulkan (Expérimental),Vulkan Beállítások (Kísérleti),Opzioni Vulkan (Sperimentale),Vulkan機能オプション(実験的),벌칸 설정(실험적),Vulkan-opties (Experimenteel),Vulkan Alternativer (Eksperimentell),Opcje Vulkan (Eksperymentalne),Opções de Vulkan (experimental),,Setări Mod Vulkan (În curs de testare),Настройки Vulkan (экспериментальные),Vulkan подешавања (експериментална),Vulkan Seçenekleri (Deneysel),Налаштування Vulkan (експериментальні), -Vulkan Options,VK_TITLE,,,,Nastavení Vulkanu,Vulkan-indstillinger,Vulkan Optionen,Vulkan Ρυθμίσεις,Agordoj por Vulkan,Opciones de Vulkan,,Vulkan-asetukset,Options Vulkan,Vulkan Beállítások,Opzioni Vulkan,Vulkan機能オプション,벌칸 설정,Vulkan-opties,Vulkan-alternativer,Opcje Vulkan,Opções de Vulkan,,Setări Mod Vulkan,Настройки Vulkan,Vulkan подешавања,Vulkan Seçenekleri,Налаштування Vulkan, -Enable Vulkan,VKMNU_ENABLE,,,,Povolit Vulkan,Aktiver Vulkan,Aktiviere Vulkan,Ενεργοποιηση του Vulkan,Ŝalti Vulkan,Activar Vulkan,,Ota käyttöön Vulkan,Activer Vulkan,Vulkan Engedélyezése,Abilita Vulkan,Vulkanを有効化,벌칸 렌더러 사용,Vulkan inschakelen,Aktiver Vulkan,Włącz Vulkan,Ativar Vulkan,,Activează modul video Vulkan,Использовать Vulkan,Омогући Vulkan,Vulkan'ı Etkinleştir,Увімкнути Vulkan, -Vulkan Device ID,VKMNU_DEVICE,,,,ID zařízení Vulkanu,Vulkan-enheds-id,Vulkan Geräte ID,Vulkan ID Συσκευής,Identigo de Vulkan-aparato,ID de dispositivo Vulkan,,Vulkan-laitetunniste,ID du périphérique Vulkan,Vulkan Eszköz ID,Dispositivo ID Vulkan,Vulkanデバイス ID,벌칸 장치 아이디,Vulkan apparaat-ID,Vulkan Enhets-ID,ID urządzenia Vulkan,ID do dispositivo Vulkan,,ID Dispozitiv Vulkan,ИД устройства Vulkan,Vulkan ID уређаја,Vulkan Cihaz Kimliği,ID пристрою Vulkan, -High Dynamic Range,VKMNU_HDR,,,,Vysoký dynamický rozsah (HDR),Høj dynamisk rækkevidde,,Υψηλό Δυναμική Εμβέλεια,Alta dinamika intervalo,Alto rango dinámico,,Korkea dynamiikka-alue (HDR),,,,ハイダイナミックレンジ,하이 다이나믹 레인지,Hoog dynamisch bereik,Høyt dynamisk område,Obraz HDR,Alto alcance dinâmico (HDR),,HDR,Расширенный динамический диапазон (HDR),HDR,Yüksek Dinamik Aralık,HDR, -Warning: The Vulkan renderer is highly experimental!,VK_WARNING,,,,Varování: Vulkan renderer je velmi experimentální!,Advarsel: Vulkan-rendereren er meget eksperimentel!,Achtung: Der Vulkan Renderer ist noch sehr experimentell!,Προειδοποίηση: Ο Vulkan renderer είναι υψηλά πειραματικός!,Averto: La bildigilo de Vulkan estas alte eksperimenta!,Advertencia: ¡El renderizado por Vulkan es altamente experimental!,,Varoitus: Vulkan-hahmonnin on hyvin kokeellinen!,Attention: Le moteur de rendu Vulkan est très expérimental!,Vigyázat: A Vulkan renderer még teljesen kísérleti!,Attenzione: il motore grafico Vulkan è altamente sperimentale!,警告:Vulkanレンダラーは実験段階です!,경고: 벌칸 렌더러는 매우 실험적입니다!,Waarschuwing: De Vulkan renderer is zeer experimenteel!,Advarsel: Vulkan-rendereren er svært eksperimentell!,Uwaga: Renderer Vulkan jest bardzo eksperymentalny!,Atenção: o renderizador Vulkan é altamente experimental!,,Atenție: Modul Vulkan este încă în curs de testare!,Внимание: рендерер Vulkan в стадии тестирования!,УПОЗОРЕЊЕ: Vulkan рендерер је врло експерименталан!,Uyarı: Vulkan işleyici son derece deneyseldir!,Увага: рендер Vulkan на стадії тестування!, -These options will require a restart to take effect.,VK_RESTART,,,,Tato nastavení vyžadují restart hry.,Disse indstillinger kræver en genstart for at få effekt.,Diese Option erfordert einen Neustart!,Αυτές η ρυθμίσεις θα χρειαστούνε επανεκκίνηση για να ισχύσουν,Ĉi tiuj agordoj bezonos relanĉon por efikiĝi.,Estas opciones requieren reiniciar para tener efecto.,,Nämä asetukset vaativat uudelleenkäynnistyksen astuakseen voimaan.,Ces options nécessitent un redémarrage.,Ezen beállítások életbelépéséhez újraindítás szükséges.,Queste opzioni richiedono il riavvio per avere effetto.,これらのオプションを有効にするには再起動が必要です。,이 설정을 적용하려면 게임을 재시작해야 합니다.,Deze opties vereisen een herstart om van kracht te worden.,Disse alternativene krever en omstart for å tre i kraft.,"Te opcje będą wymagały ponownego włączenia, aby miały efekt.",É necessário reiniciar para que essas configurações surtam efeito.,É necessário reiniciar para estas configurações fazerem efeito.,Aceste setări necesită o repornire pentru a putea fi aplicate,Для применения этих изменений требуется перезапуск игры.,Морате поново покренути GZDoom да би промене ступиле на снагу.,Bu seçeneklerin etkili olması için yeniden başlatılması gerekecektir.,Для застосування змін протрібно перезапустити гру., -Select Vulkan Device,VKMNU_DEVICESELECT,This is not yet implemented - but it is planned,,,Vybrat zařízení Vulkanu,Vælg Vulkan-enhed,Vulkan Gerät auswählen,Επιλογή Vulkan Συσκευής,Elekti Vulkan-aparaton,Seleccionar dispositivo Vulkan,,Valitse Vulkan-laite,Sélectionner périphérique Vulkan,Vulkan eszköz kiválasztása,Seleziona il Dispositivo Vulkan,Vulkanデバイスの選択,벌칸 장치를 고르시오,Selecteer Vulkan Apparaat,Velg Vulkan-enhet,Wybierz Urządzenie Vulkan,Selecione o dispositivo Vulkan,,Selectare Dispozitiv Vulkan,Выбрать устройство Vulkan,Изаберите Vulkan уређај,Vulkan Aygıtını Seçin,Виберіть пристрій Vulkan, -,,Texture scaling,,,,,,,,,,,,,,,,,,,,,,,,,, -ScaleNx,OPTVAL_SCALENX,,,,,,,,,,,,,,,,,,,,,,,,,,, -NormalNx,OPTVAL_NORMALNX,,,,,,,,,,,,,,,,,,,,,,,,,,, -hqNx,OPTVAL_HQNX,,,,,,,,,,,,,,,,,,,,,,,,,,, -hqNx MMX,OPTVAL_HQNXMMX,,,,,,,,,,,,,,,,,,,,,,,,,,, -xBRZ,OPTVAL_NXBRZ,,,,,,,,,,,,,,,,,,,,,,,,,,, -Old xBRZ,OPTVAL_OLD_NXBRZ,,,,xBRZ (starší),Gamle xBRZ,xBRZ alt,Παλίο xBRZ,Malnova xBRZ,Antiguo xBRZ,,Vanha xBRZ,Ancien xBRZ,Régi xBRZ,Vecchio xBRZ,旧xBRZ,구형 xBRZ,Oud xBRZ,Gammel xBRZ,Stare xBRZ,Antigo xBRZ,,Vechiul xBRZ,Старый xBRZ,Стари xBRZ,Eski xBRZ,Старий xBRZ, -,,Option Search,,,,,,,,,,,,,,,,,,,,,,,,,, -Option Search,OS_TITLE,,,,Vyhledávání možností,Mulighed Søgning,Optionssuche,Αναζήτηση Ρυθμίσεων,Serĉi agordojn,Buscar opciones,,Asetushaku,Recherche Option,Beállítások keresése,Opzioni di ricerca,オプション検索,옵션 검색,Optie zoeken,Alternativt søk,Szukanie Opcji,Buscar opção,Procurar opção,Căutare Setări,Поиск настройки,Претрага,Seçenek Arama,Пошук налаштування, -Search for any term,OS_ANY,,,,Hledat jakékoli klíčové slovo,Søg efter et vilkårligt begreb,Suche nach beliebigem Begriff,Αναζήτηση για όποιαδηποτε λέξη,Serĉi por iu ajn termino,Buscar cualquier término,,Etsi mitä tahansa sanaa,N'importe quel mot,Keresés bármely kifejezésre,Cerca per ciascun termine,いずれかの用語を探す,용어 검색,Zoek naar eender welke term,Søk etter en hvilken som helst term,Szukaj jakiegokolwiek wyrażenia,Buscar por qualquer termo,Procurar por um termo qualquer,Căutare după orice termen,Искать любое из слов,Тражи било који термин,Herhangi bir terim için arama yapın,Шукати будь яке з слів, -Search for all terms,OS_ALL,,,,Hledat všechna klíčová slova,Søg efter alle udtryk,Suche nach allen Begriffen,Αναζήτηση για όλες της λέξεις,Serĉi por ĉiuj terminoj,Buscar todos los términos,,Etsi kaikki sanat,Tous les mots,Keresés minden kifejezésre,Cerca per tutti i termini,全ての用語を探す,모든 조건 검색,Zoek naar alle termen,Søk etter alle termer,Szukaj wszystkich wyrażeń,Buscar por todos os termos,Procurar por todos os termos,Căutare după toți termenii,Искать все слова,Тражи сваки термин,Tüm terimler için arama yapın,Шукати всі слова, -No results found.,OS_NO_RESULTS,,,,Nic nenalezeno.,Ingen resultater fundet.,Keine Resultate,Δέν βρέθηκαν αποτελέσματα,Neniu trafo.,Ningún resultado.,,Ei tuloksia.,Pas de résultat trouvé,Nincs találat,Nessun risultato trovato.,見つかりませんでした。,검색 결과 없음.,Geen resultaten gevonden.,Ingen resultater funnet.,Brak wyników,Nenhum resultado encontrado.,,Niciun rezultat găsit.,Результаты не найдены.,Нема резултата.,Sonuç bulunamadı.,Нічого не знайдено., -Search:,OS_LABEL,,,,Hledat:,Søg:,Suche:,Αναζήτηση:,Serĉi:,Buscar:,,Etsi:,Recherche:,Keresés:,Trova:,検索:,검색:,Zoeken:,Søk:,Szukaj:,Busca:,Procura:,Caută:,Поиск:,Претрага:,Ara:,Пошук:, -,,Blood Bath Announcer,,,,,,,,,,,,,,,,,,,,,,,,,, -%k boned %o like a fish,TXT_OBITUARY1,,,,%o byl@[ao_cs] vykoštěn@[ao_cs] jako ryba hráčem %k,%k udbenede %o som en fisk,%k hat %o zerlegt wie einen Fisch,Ο/Η %k ξεκοκάλοσε @[pro2_gr] %o σα ψάρι,%k senostigis %o kiel fiŝon,%k ha deshuesado a %o como a un pescado,%k deshuesó a %o como a un pescado,%k perkasi %o paran kuin kalan,%k a désossé %o comme un poisson,%k kifilézte %o -t mint a halat,%k ha dissossato %o come un pesce,%k は %o の骨を魚のように引っこ抜いた。,%k 은(는) %o 의 뼈를 발랐다.,%k mergelde %o als een vis,%k utbeinet %o som en fisk,%k odfiletował@[ao_pl] %o jak rybę,%k desossou %o como um peixe,,%k l-a dezosat pe %o ca pe un pește,%k пересчитал косточки игрока %o,%k је очистио %o као рибу,"%o, %k tarafından balık gibi kemirildi.",%k порахував ребра %o, -%k castrated %o,TXT_OBITUARY2,,,,%o byl@[ao_cs] vykastrován@[ao_cs] hráčem %k,%k kastrerede %o,%k hat %o kastriert,Ο/Η %k ευνούχισε %o,%k kastris %o,%k ha castrado a %o,%k castró a %o,%k kastroi %o paran,%k a castré %o,%k kasztrálta %o -t,%k ha castrato %o,%k は %o を去勢した。,%k 은(는) %o 을(를) 거세시켰다.,%k castreerde %o,%k kastrert %o,%k wykastrował@[ao_pl] %o,%k castrou %o,,%k l-a castrat pe %o,%k кастрировал игрока %o,%k је кастрирао %o,"%o, %k tarafından hadım edildi.",%k кастрував %o, -%k creamed %o,TXT_OBITUARY3,,,,%o byl@[ao_cs] rozšlehán@[ao_cs] hráčem %k,%k smurte %o,%k hat %o eingeseift,Ο/Η %k κρέμασε @[pro2_gr] %o,%k kremigis %o,%k ha cremado a %o,%k cremó a %o,%k kermasi %o paran,%k a battu %o à plate couture ,%k elkente %o -t,%k ha cremato %o,%k は %o に反吐ブチ撒けさせた。,%k 은(는) %o 을(를) 양념시켰다.,%k pureerde %o,%k fløtet %o,%k spienił@[ao_pl] %o,%k fez creme de %o,,%k l-a transformat în cremă pe %o,%k взбил игрока %o,%k је истукао %o,,%k розпушив %o, -%k decimated %o,TXT_OBITUARY4,,,,%o byl@[ao_cs] zdecimován@[ao_cs] hráčem %k,%k decimerede %o,%k hat %o dezimiert,Ο/Η %k αποδεκάτισε @[pro2_gr] %o,%k detruegis %o,%k ha diezmado a %o,%k diezmó a %o,%k hävitti %o paran,%k a décimé %o,%k megtizedelte %o -t,%k ha decimato %o,%k は %o の居場所を間引いた。,%k 은(는) %o 을(를) 망가뜨렸다.,%k decimeerde %o,%k desimert %o,%k przetrzebił@[ao_pl] %o,%k decimou %o,,%k l-a decimat pe %o,%k скосил игрока %o,%k је десетковао %o,"%o, %k tarafından yok edildi.",%k зітнув %o, -%k destroyed %o,TXT_OBITUARY5,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k,%k ødelagde %o,%k hat %o zerstört,Ο/Η %k κατέστεψε @[pro2_gr] %o,%k detruis %o,%k ha destruido a %o,%k destruyó a %o,%k tuhosi %o paran,%k a détruit %o,%k elpusztította %o -t,%k ha distrutto %o,%k は %o を完全に破壊した。,%k 은(는) %o 을(를) 파괴했다.,%k vernietigde %o,%k destruert %o,%k zniszczył@[ao_pl] %o,%k destruiu %o,,%k l-a distrus pe %o,%k уничтожил игрока %o,%k је уништио %o,,%k знищив %o, -%k diced %o,TXT_OBITUARY6,,,,%o byl@[ao_cs] nakrájen@[ao_cs] na kostičky hráčem %k,%k skar %o i tern,%k hat %o in Würfel zerteilt,Ο/Η %k τεμάχησε @[pro2_gr] %o,%k diskubigis %o,%k ha picado en cubitos a %o,%k picó en cubitos a %o,%k pilkkosi %o paran,%k a coupé en dés %o,%k kockára vágta %o -t,%k ha tagliato a cubetti %o,%k は %o を賽の目に切った。,%k 은(는) %o 을(를) 잘게 잘게 썰었다.,%k sneed %o in stukjes,%k skåret %o i terninger,%k pokroił@[ao_pl] w kostkę %o,%k fez picadinho de %o,%k cortou %o,%k l-a feliat pe %o,%k разрезал игрока %o,%k је исецкао %o,"%o, %k tarafından doğrandı.",%k нарізав %o, -%k disembowled %o,TXT_OBITUARY7,,,,%o byl@[ao_cs] vykuchán@[ao_cs] hráčem %k,%k udkløvede %o,%k hat %o ausgeweidet,Ο/Η %k ισοπέδοσε @[pro2_gr] %o,%k sentripigis %o,%k ha destripado a %o,%k destripó a %o,%k suolisti %o paran,%k a étripé %o,%k kibelezte %o -t,%k ha smembrato %o,%k は %o の臓物を引きずり出した。,%k 은(는) %o 의 내장을 도려냈다.,%k ontleedde %o,%k sprettet opp %o,%k wypatroszył@[ao_pl] %o,%k estripou %o,,%k l-a eviscerat pe %o,%k выпотрошил игрока %o,%k је ампутирао %o,,%k випотрошив %o, -%k flattened %o,TXT_OBITUARY8,,,,%o byl@[ao_cs] zplacatěn@[ao_cs] hráčem %k,%k smadrede %o,%k hat %o dem Erdboden gleichgemacht,Ο/Η %k ησοπέδοσε @[pro2_gr] %o,%k platigis %o,%k ha aplanado a %o,%k aplanó a %o,%k lyttäsi %o paran,%k a aplati %o,%k kilapította %o -t,%k ha schiacciato %o,%k は %o をぶっ潰した。,%k 은(는) %o 의 코를 납작하게 만들었다.,%k plette %o,%k flatet ut %o,%k rozpłaszczył@[ao_pl] %o,%k achatou %o,%k espalmou %o,%k l-a făcut plat pe %o,%k сплюснул игрока %o,%k је изравнао %o,"%o, %k tarafından dümdüz edildi.",%k сплющив %o, -%k gave %o Anal Justice,TXT_OBITUARY9,,,,%o utržil@[ao_cs] anální spravedlnost od hráče %k,%k lemlæstede %o,%k hat %o anale Gerechtigkeit gegeben,Ο/Η %k γάμησε @[pro2_gr] %o @[pro3_gr] κόλο,%k donis pugan juston al %o,%k le ha dado justicia anal a %o,%k le dió justicia anal a %o,%k jakoi %o paralle anaalioikeutta,%k a rendu une justice anale a %o,%k Anális Igazságot adott %o -nak ,%k ha dato a %o Giustizia Anale,%k は %o のケツにぶち込んだ。,%k 은(는) %o 에게 홍콩행을 보냈다.,%k gaf %o anale rechtvaardigheid,%k ga %o anal rettferdighet,%k dał@[ao_pl] %o Analną Sprawiedliwość,%k deu Justiça Anal para %o,,%k i-a făcut jucătorului %o o Justiție Anală,%k устроил анальное правосудие игроку %o,%k је дао %o аналну правду,"%o, %k tarafından dümdüz edildi.",%k влаштував анальне правосуддя %o, -%k gave AnAl MaDnEsS to %o,TXT_OBITUARY10,,,,%o utrpěl@[ao_cs] AnÁlNí ŠíLeNsTvÍ od hráče %k,%k spildte %o,%k gab %o AnAlEn WaHnSiNn,Ο/Η %k έσκισε τον κόλο του/της] %o,%k donis pUgAn frEnEzOn al %o,%k le ha dado LoCuRa AnAl a %o,%k le dió LoCuRa AnAl a %o,%k teki %o paran AnAaLiHuLlUkSi,%k a donné la FOLIE ANALE a %o,%k SeGgBe KüLDtE %o -t,%k ha dato FoLlIa AnAle a %o,%k は %o のケツをガバガバにした。,%o 은(는) %k 의 찰진 맛을 보았다.,%k gaf aNaLe DoLhEiD aan %o,%k ga %o anal rettferdighet,%k dał@[ao_pl] %o AnAlNe SzAlEńStWo ,%k deu LoUcUrA aNaL para %o,,%k i-a dat NeBuNiE AnAlĂ jucătorului %o,%k устроил АнАЛ КаРнаВаЛ игроку %o,%k је дао АнАлНо ЛуДиЛо %o,"%o, %k tarafından dümdüz edildi.",%k влаштував АнАЛ ГуЛяНнЯ %o, -%k killed %o,TXT_OBITUARY11,,,,%o byl@[ao_cs] zabit@[ao_cs] hráčem %k,%k dræbte %o,%k hat %o getötet,Ο/Η %k σκότωσε @[pro2_gr] %o,%k mortigis %o,%k ha matado a %o,%k mató a %o,%k tappoi %o paran,%k a tué %o,%k kicsinálta %o -t,%k ha ucciso %o,%k は %o をブッ殺した。,%k 은(는) %o 을(를) 죽였다.,%k doodde %o,%k drepte %o,%k zabił@[ao_pl] %o,%k matou %o,,%k l-a omorât pe %o,%k убил игрока %o,%k је убио %o,"%o, %k tarafından öldürüldü.",%k вбив %o, -%k made mincemeat out of %o,TXT_OBITUARY12,,,,%o byl@[ao_cs] namelen@[ao_cs] hráčem %k,%k gjorde hakket kød af %o,%k hat %o zu Hackfleisch verarbeitet,Ο/Η %k έφτιαξε κυμά με @[pro2_gr] %o,%k farigis farĉon el %o,%k ha hecho picadillo de %o,%k hizo picadillo de %o,%k teki jauhelihaa %o parasta,%k a fait de la viande hachée de %o,%k ledarálta %o -t,%k ha triturato %o,%k は %o をミンチにした。,%o 은(는) %k 에 의해 분쇄됐다.,%k maakte gehakt van %o,%k laget kjøttdeig av %o,%k zrobił@[ao_pl] mięso mielone z %o,%k fez carne moída de %o,%k fez carne picada do %o,%k a facut tocătură din %o,%k сделал отбивную из игрока %o,%k је направио млевено месо од %o,"%o, %k tarafından kıyma haline getirildi.",%k зробив відбивну з %o, -%k massacred %o,TXT_OBITUARY13,,,,%o byl@[ao_cs] zmasakrován@[ao_cs] hráčem %k,%k massakrerede %o,%k hat %o niedergemetzelt,Ο/Η %k δολοφώνησε @[pro2_gr] %o,%k masakris %o,%k ha masacrado a %o,%k masacró a %o,%k verilöylytti %o parkaa,%k a massacré %o,%k lemészárolta %o -t,%k ha fatto di %o carne tritata,%k は %o を虐殺した。,%k 은(는) %o 을(를) 참살했다.,%k slachtte %o af,%k massakrerte %o,%k zmasakrował@[ao_pl] %o,%k massacrou %o,,%k a fost masacrat de către %o,%k устроил бойню игроку %o,%k је масакрирао %o,"%o, %k tarafından katledildi",%k влаштував для %o бійню, -%k mutilated %o,TXT_OBITUARY14,,,,%o byl@[ao_cs] zmrzačen@[ao_cs] hráčem %k,%k lemlæstede %o,%k hat %o verstümmelt,Ο/Η %k ακρωτηριάσε @[pro2_gr] %o,%k mutilis %o,%k ha mutilado a %o,%k mutiló a %o,%k silpoi %o paran,%k a mutilé %o,%k megcsonkította %o -t,%k ha massacrato %o,%k は %o をバラバラ死体にした。,%k 은(는) %o 의 팔다리를 절단했다.,%k verminkte %o,%k lemlestet %o,%k rozszarpał@[ao_pl] %o,%k mutilou %o,,%k l-a mutilat pe %o,%k изуродовал игрока %o,%k је мутилирао %o,"%o, %k tarafından sakat bırakıldı.",%k знівечив %o, -%k reamed %o,TXT_OBITUARY15,,,,%o byl@[ao_cs] proděravěn@[ao_cs] hráčem %k,%k skændede %o,%k hat %o aufgerieben,Ο/Η %k δέσμισε @[pro2_gr] %o,%k alezis %o,%k ha escariado a %o,%k escarió a %o,%k porasi %o paran,%k a découpé en fines lamelles %o,%k seggbe rakta %o -t,%k ha squartato %o,%k は %o の穴を大きく広げた。,%k 은(는) %o 을(를) 크게 혼냈다.,%k holde %o uit,%k maltraktert %o,%k rozwiercił@[ao_pl] %o,%k esquartejou %o,,%k l-a transformat într-un top de hârtie pe %o,%k рассверлил игрока %o,%k је наоружао %o,"%o, %k tarafından öldürüldü.",%k просверлив %o, -%k ripped %o a new orifice,TXT_OBITUARY16,,,,%o má novou díru od hráče %k,%k flåede %o en ny åbning,%k hat %o eine neue Körperöffnung verpasst,Ο/Η άνοιξε μια νέα τρύπα @[pro3_gr] %o,%k ŝiris novan truon en %o,%k le ha hecho a %o un nuevo orificio,%k le hizo a %o un nuevo orificio,%k repi %o paralle uuden aukon,%k a ouvert un nouvel orifice a %o,%k új szájat csinált %o -nak,%k ha aperto a %o un altro orifizio,%k は %o を切り裂いて新しい穴を作ってあげた。,%k 은(는) %o 을(를) 죽여 뜯어서 작품을 만들었다.,%k scheurde een opening uit %o,%k revet %o en ny kroppsåpning,%k rozerwał@[ao_pl] %o nowy otwór,%k abriu um novo orifício em %o,,%k i-a făcut jucătorului %o un nou orificiu,%k проделал новое отверстие в игроке %o,%k је исцепао %o нови отвор,"%o, %k tarafından yeni bir delik açıldı.",%k зробив в %o нову дірку, -%k slaughtered %o,TXT_OBITUARY17,,,,%o byl@[ao_cs] zavražděn@[ao_cs] hráčem %k,%k slagtede %o,%k hat %o geschlachtet,Ο/Η %k έσφαξε @[pro2_gr] %o,%k buĉis %o,%k ha sacrificado a %o,%k sacrificó a %o,%k teurasti %o paran,%k a meurtri %o,%k lemészárolta %o -t,%k ha macellato %o,%k は %o を屠殺した。,%o 은(는) %k 에 의해 도살당했다.,%k slachtte %o,%k slaktet %o,%k zarżn@[irreg_2_pl] %o,%k abateu %o,,%k l-a măcelărit pe %o,%k устроил резню игроку %o,%k је заклао %o,"%o, %k tarafından katledildi.",%k провів різню %o, -%k smashed %o,TXT_OBITUARY18,,,,%o byl@[ao_cs] zmlácen@[ao_cs] hráčem %k,%k smadrede %o,%k hat %o zerklatscht,Ο/Η %k τσάκισε @[pro2_gr] %o,%k frakasis %o,%k ha destrozado a %o,%k destrozó a %o,%k murskasi %o paran,%k a enfoncé %o,%k földbe döngölte %o -t,%k ha distrutto %o,%k は %o をぶっ飛ばした。,%k 은(는) %o 을(를) 내팽개쳤다.,%k vermorzelde %o,%k knust %o,%k stłukł@[ao_pl] %o,%k esmagou %o,,%k l-a spart pe %o,%k размазал игрока %o,%k је поломио %o,"%o, %k tarafından ezildi.",%k розмазав %o, -%k sodomized %o,TXT_OBITUARY19,,,,Hráč %k se dopustil sodomie na hráči %o,%k sodomiserede %o,%k hat %o sodomisiert,Ο/Η %k γάμησε @[pro2_gr] %o,%k sodomizis %o,%k ha sodomizado a %o,%k sodomizó a %o,%k anaaliraiskasi %o paran,%k y a sodomisé n %o,%k szodomizálta %o -t,%k ha sodomizzato %o,%o は %k にカマを掘られた。 ,%o 은(는) %k 을(를) 위해 등을 보였다.,%k sodomiseerde %o,%k sodomisert %o,%k spenetrował@[ao_pl] %o,%k sodomizou %o,,%k l-a sodomizat pe %o,%k содомировал игрока %o,%k је изјебао %o,"%o, %k tarafından sodomize edildi.",%k зґвалтував %o, -%k splattered %o,TXT_OBITUARY20,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] hráčem %k,%k sprøjtede %o,%k hat %o zerspritzt,Ο/Η %k έσκασε @[pro2_gr] %o,%k disĵetis %o,%k ha rociado a %o,%k roció a %o,%k roiski %o paran yltympäri,%k a explosé de %o,%k szétloccsantotta %o -t,%k ha spiaccicato %o,%k は %o にばら撒かれた。,%k 은(는) %o 을(를) 박살냈다.,%k splette %o,%k sprutet %o,%k rozbryzgał@[ao_pl] %o,%k explodiu %o,,%k l-a împrăștiat pe %o,%k разбрызгал игрока %o,%k је спљоштио %o,"%o, %k tarafından parçalandı.",%k розбризкав %o, -%k squashed %o,TXT_OBITUARY21,,,,%o byl@[ao_cs] rozmáčknut@[ao_cs] hráčem %k,%k kværnede %o,%k hat %o zerquetscht,Ο/Η %k πάτησε @[pro2_gr] %o,%k premplatigis %o,%k ha aplastado a %o,%k aplastó a %o,%k litisti %o paran,%k a écrabouillé %o,%k eltaposta %o -t,%k ha schiacciato %o,%k は %o に潰された。,%k 은(는) %o 을(를) 짓이겼다.,%k plette %o,%k knust %o,%k zmiażdżył@[ao_pl] %o,%k espatifou %o,,%k l-a strivit pe %o,%k расплющил игрока %o,%k је згњечио %o,"%o, %k tarafından ezildi.",%k розчавив %o, +",Tmavě šedá,Mørkegrå,Dunkelgrau,Σκοτεινό γρκί,Malhelgriza,Gris oscuro,,Tummanharmaa,Gris sombre,Sötétszürke,Grigio scuro,鉛,치색,Donkergrijs,Mørkegrå,Ciemnoszary,Cinza escuro,,Gri închis,Тёмно-серый,Тамно сива,Mörkgrått,Koyu gri,Темно-сірий, +Dark Green,TXT_COLOR_DARKGREEN,,,,Tmavě zelená,Mørkegrøn,Dunkelgrün,Σκοτεινό πράσινο,Malhelverda,Verde oscuro,,Tummanvihreä,Vert sombre,Sötétzöld,Verde scuro,深,흑녹색,Donkergroen,Mørkegrønn,Ciemnozielony,Verde escuro,,Verde închis,Тёмно-зелёный,Тамна зелена,Mörkgrön,Koyu Yeşil,Темно-зелений, +Brown,TXT_COLOR_BROWN,,,,Hnědá,Brun,Braun,Σκούρο,Bruna,Marrón,Marrón/Café,Ruskea,Brun,Barna,Marrone,茶,갈색,Bruin,Brun,Brązowy,Marrom,,Maro,Коричневый,Браон,Brun,Kahverengi,Коричневий, +Dark Blue,TXT_COLOR_DARKBLUE,,,,Tmavě modrá,Mørk blå,Dunkelblau,Σκοτεινό μπλέ,Malhelblua,Azul oscuro,,Tummansininen,Bleu sombre,Sötétkék,Blu scuro,紺,,Donkerblauw,Mørkeblå,Ciemnoniebieski,Azul escuro,,Albastru închis,Тёмно-синий,Тамна Плава,Mörkblå,Koyu Mavi,Темно-синій, +Light Red,TXT_COLOR_LIGHTRED,,,,Světle červená,Lysrød,Hellrot,Ανοιχτό κόκκινο,Helruĝa,Rojo claro,,Vaaleanpunainen,Rouge clair,Világospiros,Rosso chiaro,丹,옅은 적색,Licht Rood,Lys rød,Jasnoczerwony,Vermelho claro,,Roșu deschis,Светло-красный,Светло црвена,Ljusröd,Açık Kırmızı,Світло-червоний, +Yellow,TXT_COLOR_YELLOW,,,,Žlutá,Gul,Gelb,Κίτρινο,Flava,Amarillo,,Keltainen,Jaune,Sárga,Giallo,黄,노란색,Geel,Gul,Żółty,Amarelo,,Galben,Жёлтый,Жута,Gul,Sarı,Жовтий, +Purple,TXT_COLOR_PURPLE,,,,Fialová,Lilla,Violett,Μόβ,Purpura,Morado,,Purppura,Violet,Lila,Viola,紫,보라색,Paars,Lilla,Fioletowy,Roxo,,Mov,Фиолетовый,Љубичаста,Lila,Mor,Фіолетовий, +Olive,TXT_COLOR_DULLGREEN,,,,Bledě zelená,Oliven,Blassgrün,,Olivkolora,Oliva,,Haaleanvihreä,Vert pâle,Olíva,Verde pallido,苔,암녹색,Saaie groen,Oliven,Matowa Zieleń,Verde oliva,,Măsliniu,Мутно-зелёный,Тупа зелена,Oliv,Zeytin,Темний жовто-зелений, +Beige,TXT_COLOR_BEIGE,,,,Béžová,Beige,,Μπέζ,Flavgriza,Beis,Beige,Beesi,,Bézs,,淡,담갈색,Beige,Beige,Beżowy,Bege,,Bej,Бежевый,Беж,Beige,Bej,Бежевий, +Light Green,TXT_COLOR_LIGHTGREEN,,,,Světle zelená,Lysegrøn,Hellgrün,Ανοιχτό Πράσινο,Helverda,Verde claro,,Vaaleanvihreä,Vert clair,Világoszöld,Verde chiaro,葵,옅은 녹색,Licht groen,Lysegrønn,Jasonzielony,Verde claro,,Verde Deschis,Светло-зелёный,Светло зелена,Ljusgrön,Açık Yeşil,Світло-зелений, +Light Blue,TXT_COLOR_LIGHTBLUE,,,,Světle modrá,Lys blå,Hellblau,Γαλάζιο,Helblua,Azul claro,,Vaaleansininen,Bleu clair,Világoskék,Blu chiaro,空,옅은 청색,Licht blauw,Lyseblå,Jasnoniebieski,Azul claro,,Albastru Deschis,Светло-синий,Светло плава,Ljusblå,Açık Mavi,Світло-синій, +Light Gray,TXT_COLOR_LIGHTGRAY,,,Light Grey,Světle šedá,Lysegrå,Hellgrau,Ανοιχτό Γκρι,Helgriza,Gris claro,,Vaaleanharmaa,Gris clair,Világosszürke,Grigio chiaro,鉛,옅은 회색,Lichtgrijs,Lysegrå,Jasnoszary,Cinza claro,,Gri Deschis,Светло-серый,Светло сива,Ljusgrå,Açık Gri,Світло-сірий, +Light Brown,TXT_COLOR_LIGHTBROWN,,,,Světle hnědá,Lys brun,Hellbraun,Ανοιχτό Καφέ,Helbruna,Marrón claro,Marrón/Café claro,Vaaleanruskea,Brun clair,Világosbarna,Marrone chiaro,褐,옅은 고동색,Lichtbruin,Lysebrun,Jasnobrązowy,Marrom claro,,Maro Deschis,Светло-коричневый,Светло браон,Ljusbrun,Açık Kahverengi,Світло-коричневий, +Gold,TXT_COLOR_GOLD,,,,Zlatá,Guld,,Χρυσό,Orkolora,Dorado,,Kulta,Or,Arany,Oro,金,금색,Goud,Gull,Złoty,Dourado,,Auriu,Золотой,Златна,Guld,Altın,Золотий, +Bright Green,TXT_COLOR_BRIGHTGREEN,,,,Jasně zelená,Lysegrøn,Hellgrün,Φωτινό Πράσινο,Brilverda,Verde claro,,Vaaleanvihreä,Vert clair,Fényeszöld,Verde chiaro,鮮,밝은 녹색,Helder groen,Lysegrønn,Jasnozielony,Verde claro,,Verde Deschis,Ярко-зелёный,Светла зелена,Ljusgrön,Parlak Yeşil,Яскраво-зелений, +Rust,TXT_COLOR_RUST,,,,Rezavá,,Rostbraun,Σκουριά,Rustokolora,Óxido,,Ruoste,Rouille,Rozsda,Arrugginito,錆,주황 적갈색,Roest,,Rdzawy,Ferrugem,,Ruginiu,Ржавый,Рђа,Rost,Pas,Іржавий, +Name,PLYRMNU_NAME,,,,Jméno,Navn,,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Navn,Imię,Nome,,Nume,Имя,Надимак,Namn,İsim,Ім'я, +Team,PLYRMNU_TEAM,,,,Tým,,,Ομάδα,Teamo,Equipo,,Joukkue,Equipe,Csapat,Squadra,チーム,팀,,Lag,Drużyna,Equipe,Equipa,Echipă,Команда,Тим,Lag,Takım,Команда, +Color,PLYRMNU_PLAYERCOLOR,,,Colour,Barva,Farve,Farbe,Χρώμα,Koloro,,,Väri,Couleur,Szín,Colore,色,색상,Kleur,Farge,Kolor,Cor,,Culoare,Цвет,Боја,Färg,Renk,Колір, +Gender,PLYRMNU_PLAYERGENDER,,,,Pohlaví,Køn,Geschlecht,Φύλο,Sekso,Sexo,,Sukupuoli,Genre,Nem,Sesso,性別,성별,Geslacht,Kjønn,Płeć,Gênero,,Sex,Пол,Пол,Kön,Cinsiyet,Стать, +Male,OPTVAL_MALE,,,,Muž,Mand,Männlich,Αρσενικό,Vira,Masculino,,Miespuolinen,Masculin,Férfi,Maschio,男,남성,Man,Mannlig,Mężczyzna,Masculino,,Masculin,Мужской,Мушко,Man,Erkek,Чоловіча, +Female,OPTVAL_FEMALE,,,,Žena,Kvinde,Weiblich,Θηλυκό,Ina,Femenino,,Naispuolinen,Féminin,Nő,Femmina,女,여성,Vrouw,Kvinne,Kobieta,Feminino,,Feminin,Женский,Женско,Kvinna,Kadın,Жіноча, +Neutral,OPTVAL_NEUTRAL,,,,Neutrální,,,Ουδέτερο,Neŭtra (Ri),Neutro,,Sukupuoleton,Neutre,Semleges,Neutrale,中間,중성,Neutraal,Nøytral,Neutralne,Neutro,,Neutru,Нейтральный,Неутрално,Neutral,Nötr,Нейтральна, +Object,OPTVAL_OTHER,,,,Objekt,Objekt,Objekt,Αντικείμενο,Objekto (Ĝi),Objeto,,Olio,Objet,Tárgy,Oggetto,物体,기타,Doel,Gjenstand,Obiekt,Objeto,,Obiect,Предмет,Предмет,Objekt,Nesne,Предмет, +Gameplay Options,GMPLYMNU_TITLE,,,,Nastavení herních mechanik,Gameplay-muligheder,Gameplay-Optionen,,Ludado-agordoj,Opciones de jugabilidad,,Pelattavuusasetukset,Options Gameplay,Játékmenet beállításai,Opzioni gameplay,ゲームプレイ オプション,게임플레이 설정,Gameplay-opties,Spillalternativer,Opcje Rozgrywki,Opções de jogabilidade,,Setări de Joc,Настройки игры,Подешавања гејмплеја,Spelalternativ,Oynanış Seçenekleri,Налаштування гри, +Always,OPTVAL_ALWAYS,,,,Vždy,Altid,Immer,Πάντα,Ĉiam,Siempre,,Aina,Toujours,Mindig,Sempre,常に,언제나,Altijd,Alltid,Zawsze,Sempre,,Mereu,Всегда,Увек,Alltid,Her zaman,Завжди, +Never,OPTVAL_NEVER,,,,Nikdy,Aldrig,Nie,Ποτέ,Neniam,Nunca,,Ei koskaan,Jamais,Soha,Mai,しない,없음,Nooit,Aldri,Nigdy,Nunca,,Niciodată,Никогда,Никад,Aldrig,Asla,Ніколи, +Autoaim,PLYRMNU_AUTOAIM,,,,Automatické míření,,Automatisch zielen,,Celasisto,Autoapuntar,,Automaattitähtäys,Auto-visée,Automatikus célzás,Mira automatica,自動照準,자동 조준,,,Auto-celowanie,Mira automática,,Autoțintire,Автоприцеливание,Аутоматско циљање,automatiskt sikte,,Автонаведення, +Always Run,PLYRMNU_ALWAYSRUN,,,,Vždy běžet,Altid løbe,Immer Rennen,Πάντα τρέχα,Ĉiam kuri,Siempre correr,,Jatkuva juoksu,Toujours courir,Mindig fusson,Corri sempre,常に駆け足,달리기 토글,Altijd lopen,Kjør alltid,Zawsze Biegaj,Sempre correr,Correr Sempre,Fugă în permanență,Постоянный бег,Увек трчи,Alltid springa,Daima Koş,Постійний біг, +,,Display,,,,,,,,,,,,,,,,,,,,,,,,,,, +Screen size,DSPLYMNU_SCREENSIZE,,,,Velikost obrazovky,Skærmstørrelse,Bildschirmgröße,Μέγεθος οθόνης,Ekrangrando,Tamaño de pantalla,,Näytön koko,Taille de l'écran,Képernyő mérete,Dimensione della schermata,画面サイズ,화면 크기,Schermgrootte,Skjermstørrelse,Rozmiar Ekranu,Tamanho da tela,Tamanho do ecrã,Mărime ecran,Размер экрана,Величина екрана,Skärmstorlek,Ekran boyutu,Розмір екрану, +Vertical Sync,DSPLYMNU_VSYNC,,,,Vertikální synchronizace,Lodret synkronisering,Vertikale Synchronisation,,Vertikala-sinkronigo,Sincronización vertical,,Pystytahdistys,Synchronisation Verticale,Függőleges szinkronizálás,Sincronia verticale,垂直同期,수직 동기화,Verticale Sync,Vertikal synkronisering,Synchronizacja Pionowa,Sincronização vertical,,Sincronizare Verticală,Вертикальная синхронизация,Вертикална синхорнизација,Vertikal synkronisering,Dikey Senkronizasyon,Вертикальна синхронізація, +Models,DSPLYMNU_MODELS,,,,Modely,Modeller,Modelle,Μοντέλα,Modeloj,Modelos,,Mallit,Modèles,3D modellek,Modelli,モデル,모델,Modellen,Modeller,Modele,Modelos,,Modele,Модели,Модели,Modeller,Modeller,3D Моделі, +Scale crosshair,DSPLYMNU_CROSSHAIRSCALE,,,,Velikost zaměřovače,Skalerer trådkorset,Fadenkreuz skalieren,,Skali reteton,Escalar retícula,,Skaalaa tähtäintä,Mise à l'échelle du viseur,Célkereszt méret,Scala del mirino,照準スケール,조준점 크기,Dradenkruis schalen,Skala trådkors,Skala celownika,Escala da mira,,Scară țintă,Размер прицела,Размера нишана,Skala hårkorset,Ölçekli artı işareti,Розмір прицілу, +Brightness,DSPLYMNU_BRIGHTNESS,,,,Jas,Lysstyrke,Helligkeit,Φωτηνότητα,Brileco,Brillo,,Kirkkaus,Luminosité,Fényerő,Luminosità,明るさ,밝기,Helderheid,Lysstyrke,Jasność,Brilho,,Luminozitate,Яркость,Осветљење,Ljusstyrka,Parlaklık,Яскравість, +Gamma correction,DSPLYMNU_GAMMA,,,,Korekce gama,Gammakorrektion,Gammakorrektur,,Gamaa korektado,Corrección gamma,,Gammakorjaus,Correction Gamma,Gamma korrekció,Correzione gamma,ガンマ値,감마 조정,Gamma correctie,Gammakorreksjon,Korekta gammy,Correção de gama,,Gamma,Гамма-коррекция,Корекција светлости,Gammakorrigering,Gama düzeltme,Гамма-корекція, +Contrast,DSPLYMNU_CONTRAST,,,,Kontrast,Kontrast,Kontrast,,Kontrasto,Contraste,,Sävykkyys,Contraste,Kontraszt,Contrasto,コントラスト,대비,,Kontrast,Kontrast,Contraste,,,Контраст,Контраст,Kontrast,Kontrast,Контраст, +Saturation,DSPLYMNU_SATURATION,,,,Sytost,Mætning,Sättigung,,Satureco,Saturación,,Värikylläisyys,,Telítettség,Saturazione,サチュレーション,채도,Verzadiging,Metning,Nasycenie,Saturação,,Saturație,Насыщенность,Сатурација,Mättnad,Doygunluk,Насиченість, +Status Bar Scale,DSPLYMNU_SBSCALE,,,,Velikost stavového panelu,Skala for statuslinje,Statusleistengröße,,Skalo de stata breto,Escala de barra de estado,,Tilapalkin skaalaus,Mise à l'échelle HUD,Állapotjelző mérete,Dimensioni Status Bar,ステータススケール,,Statusbalkschaal,Statuslinjeskala,Skala paska statusu,Escala da barra de estado,,Scară bară de stare,Размер строки состояния,,Skala för statusfältet,Durum Çubuğu Ölçeği,Розмір строки стану, +Messages,DSPLYMNU_MESSAGES,,,,Oznámení,Meddelelser,Nachrichten,Μηνύματα,Mesaĝoj,Mensajes,,Viestit,,Üzenetek,Messaggi,メッセージ類,메시지,Berichten,Meldinger,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке,Meddelanden,Mesajlar,Повідомлення, +Center messages,MSGMNU_CENTERMESSAGES,,,Centre messages,Oznámení na střed,Centrerede meddelelser,Nachrichten zentrieren,,Centrigi mesaĝojn,Centrar mensajes,,Keskitä viestit,Messages centrés,Üzenetek középre helyezése,Messaggi centrati,メッセージを中央に,메시지 중간에 위치,Berichten centreren,Sentrumsmeldinger,Wyśrodkuj wiadomości,Centralizar mensagens,Centrar mensagens,Mesaje centrate,Центрирование сообщений,Централне поруке,Centrerade meddelanden,Merkez mesajları,Центрування повідомлень, +Pulsating message Display,MSGMNU_PULSEMESSAGES,,,,Pulzující oznámení,Pulserende meddelelser Visning,Pulsierende Nachrichtenanzeige,,Pulsanta mesaĝ-montrejo,Mostrar mensajes pulsantes,,Sykkivät viestit,Messages pulsés,Pulzáló üzenet,Mostra messaggi pulsanti,取得時等の文を明滅,,Pulserende berichtendisplay,Pulserende melding Display,Pulsujące wyświetlanie wiadomości,Exibir mensagem pulsante,,Afișare Mesaje Pulsante,Пульсация сообщений,,Pulserande meddelande Visning,Titreşimli mesaj Ekranı,Пульсація повідомлень, +Message Scale,MSGMNU_MESSAGESCALE,,,,Velikost oznámení,Skala for meddelelser,Nachrichtengröße,Μέγεθος μηνύματον,Skalo de mesaĝoj,Escala de mensajes,,Viestien skaalaus,Mise à l'échelle Messages,Üzenet mérete,Dimensioni Messaggi,メッセージスケール,,Berichtschaal,Meldingsskala,Skalowanie Wiadomości,Escala de mensagem,,Scară Mesaje,Размер сообщений,,Meddelandeskala,Mesaj Ölçeği,Розмір повідомлень, +,,Automap,,,,,,,,,,,,,,,,,,,,,,,,,,, +Select Color,MNU_COLORPICKER,,,Select Colour,Výběr barvy,Vælg farve,Farbe auswählen,Επιλογή Χρώματος,Elektu koloron:,Elige un color,,Valitse väri,Choisir Couleur,Szín választása,Scegli il colore,色選択,색상을 고르시오,Selecteer Kleur,Velg farge,Wybierz Kolor,Selecione uma cor,,Alege o Culoare,Выбор цвета,Изабери боју,Välj färg,Renk Seçiniz,Вибір кольору, +Rotate automap,AUTOMAPMNU_ROTATE,,,,Otáčet automapu,Rotere automap,Rotiere Automap,,Turni aŭtomatan mapon,Rotar automapa,,Kiertyvä automaattikartta,Rotation de la Carte,Térkép forgatása,Ruota l'automappa,オートマップの回転表示,오토맵 회전,Automatisch roteren,Roter automatisk kart,Obracaj mapę,Girar automapa,,Rotire hartă computerizată,Вращающаяся автокарта,Ротирај аутомапу,Rotera automap,Otomatik haritayı döndür,Обертання автокарти, +Follow player,AUTOMAPMNU_FOLLOW,,,,Následovat hráče,Følg spilleren,Folge dem Spieler,Ακουλούθα το παίχτη,Sekvi ludanton,Seguir jugador,,Seuraa pelaajaa,Suivre le joueur,Kövesse a játékost,Segui il giocatore,プレイヤー追従,플레이어 추적,Volg de speler,Følg spiller,Podążaj za graczem,Seguir jogador,,Urmărire jucător,Привязка к игроку,Прати играча,Följ spelaren,Oyuncuyu takip et,Прив'язка до гравця, +Line alpha,AUTOMAPMNU_LINEALPHA,,,,Průhlednost čar,Linje alfa,Alpha für Linien,,Travidebleca de linio,Transparencia de línea,,Viivan alpha,Translucidité des lignes,Vonal áttetszóség,Traslucenza delle linee,線の半透明度,선 반투명도,Doorschijnendheid van lijnen,Linje alfa,Przezroczystość Linii,Transparência da linha,,Transparență linii,Прозрачность линий,Транслуценција линија,Linje alfa,Çizgi alfa,Прозорість ліній, +Line thickness,AUTOMAPMNU_LINETHICKNESS,,,,Tloušťka čar,Linjetykkelse,Dicke der Linien,,Dikeca de linio,Grosor de línea,,Viivan paksuus,Épaisseur des lignes,Vonal vastagság,Spessore delle linee,線の太さ,선 두께,Dikte van lijnen,Linjetykkelse,Grubość Linii,Espessura da linha,,Grosime linii,Толщина линий,Дебљина линија,Linjens tjocklek,Çizgi kalınlığı,Товщина ліній, +Customize Map Colors,MAPCOLORMNU_TITLE,,,Customize Map Colours,Nastavení barev mapy,Tilpas kortfarver,Automapfarben einstellen,,Adapti mapkolorojn,Personalizar colores (mapa),,Värien mukautus,Couleurs Carte Personnalisées,Térkép színeinek testreszabása,Personalizza i colori della mappa,カスタム色を決める,미니맵 색상 설정,Kaartkleuren aanpassen,Tilpass kartfarger,Ustaw kolory mapy,Personalizar cores do mapa,,Personalizare culori hartă,Настройки цветов автокарты,Промени боју мапе,Anpassa kartans färger,Harita Renklerini Özelleştirin,Налаштування кольорів автокарти, +Restore default custom colors,MAPCOLORMNU_DEFAULTMAPCOLORS,,,Restore default custom colours,Obnovit původní vlastní barvy,Gendan standard brugerdefinerede farver,Standardfarben wiederherstellen,,Restaŭri defaŭltajn laŭmendajn kolorojn,Restaurar colores personalizados,,Palauta oletusvärit,Couleurs par défaut,Eredeti színek visszaállítása,Reimposta i colori personalizzati al default,カスタム色を初期化,기본 색상으로 복구,Standaard aangepaste kleuren herstellen,Gjenopprett egendefinerte standardfarger,Przywróć domyślne kolory,Restaurar cores personalizadas padrão,,Revenire la culorile implicite,Вернуть стандартные цвета,Врати уобичајене разне боје,Återställ anpassade standardfärger,Varsayılan özel renkleri geri yükleme,Повернути стандартні кольори, +,,Sound,,,,,,,,,,,,,,,,,,,,,,,,,,, +Sound enabled,SNDMNU_SNDENABLED,,,,Zvuk zapnut,Lyd aktiveret,Sound aktiv,Ήχος ενεργοποιημένος,Sono ŝaltita,Sonido activado,,Ääni päällä,Son activé,Hang engedélyezve,Abilita gli effetti sonori,サウンド有効,,Geluid actief,Lyd aktivert,Dźwięk włączony,Som ativado,,Sunet activat,Звук включён,,Ljud aktiverat,Ses etkin,Звук увімкнено, +Music enabled,SNDMNU_MUSENABLED,,,,Hudba zapnuta,Musik aktiveret,Musik aktiv,Μουσική ενεργοποιημένη,Muziko ŝaltita,Música activada,,Musiikki päällä,Musique activée,Zene engedélyezve,Abilita la musica,音楽有効,,Muziek actief ,Musikk aktivert,Muzyka włączona,Música ativada,,Muzică activată,Музыка включена,,Musik aktiverad,Müzik etkin,Музику увімкнено, +4000 Hz,OPTVAL_4000HZ,,,,,,,,,,,,,,,,,,,,,,,4000 Гц,,,,4000 Гц, +8000 Hz,OPTVAL_8000HZ,,,,,,,,,,,,,,,,,,,,,,,8000 Гц,,,,8000 Гц, +11025 Hz,OPTVAL_11025HZ,,,,,,,,,,,,,,,,,,,,,,,11025 Гц,,,,11025 Гц, +22050 Hz,OPTVAL_22050HZ,,,,,,,,,,,,,,,,,,,,,,,22050 Гц,,,,22050 Гц, +32000 Hz,OPTVAL_32000HZ,,,,,,,,,,,,,,,,,,,,,,,32000 Гц,,,,32000 Гц, +44100 Hz,OPTVAL_44100HZ,,,,,,,,,,,,,,,,,,,,,,,44100 Гц,,,,44100 Гц, +48000 Hz,OPTVAL_48000HZ,,,,,,,,,,,,,,,,,,,,,,,48000 Гц,,,,48000 Гц, +64 samples,OPTVAL_64SAMPLES,,,,64 vzorků,,,64 δείγματα,64 specimenoj,64 muestras,,64 näytettä,,,,,64 샘플,,64 samplinger,64 sample,64 amostras,,64 monstre,64 семпла,64 узорка,64 samplingar,64 örnek,64 семпла, +128 samples,OPTVAL_128SAMPLES,,,,128 vzorků,,,128 δείγματα,128 specimenoj,128 muestras,,128 näytettä,,,,,128 샘플,,128 samplinger,128 sampli,128 amostras,,128 monstre,128 семплов,128 узорка,128 samplingar,128 örnek,128 семплів, +256 samples,OPTVAL_256SAMPLES,,,,256 vzorků,,,256 δείγματα,256 specimenoj,256 muestras,,256 näytettä,,,,,256 샘플,,256 samplinger,256 sampli,256 amostras,,256 monstre,256 семплов,256 узорка,256 samplingar,256 örnek,256 семплів, +512 samples,OPTVAL_512SAMPLES,,,,512 vzorků,,,512 δείγματα,512 specimenoj,512 muestras,,512 näytettä,,,,,512 샘플,,512 samplinger,512 sampli,512 amostras,,512 monstre,512 семплов,512 узорка,512 samplingar,512 örnek,512 семплів, +1024 samples,OPTVAL_1024SAMPLES,,,,1024 vzorků,,,1024 δείγματα,1024 specimenoj,1024 muestras,,1024 näytettä,,,,,1024 샘플,,1024 samplinger,1024 sampli,1.024 amostras,,1024 monstre,1024 семпла,1024 узорка,1024 samplingar,1024 örnek,1024 семплів, +2048 samples,OPTVAL_2048SAMPLES,,,,2048 vzorků,,,2048 δείγματα,2048 specimenoj,2048 muestras,,2048 näytettä,,,,,2048 샘플,,2048 samplinger,2048 sampli,2.048 amostras,,2048 monstre,2048 семплов,2048 узорка,2048 samplingar,2048 örnek,2048 семплів, +4096 samples,OPTVAL_4096SAMPLES,,,,4096 vzorků,,,4096 δείγματα,4096 specimenoj,4096 muestras,,4096 näytettä,,,,,4096 샘플,,4096 samplinger,4096 sampli,4.096 amostras,,4096 monstre,4096 семплов,4096 узорка,4096 samplingar,4096 örnek,4096 семплів, +Auto,OPTSTR_AUTO,,,,,Automatisk,,,Aŭtomata,Automático,,Automaattinen,,Automatikus,Automatico,自動,오토,,,Automatycznie,Automático,,,Авто,Аутоматски,Automatisk,Otomatik,Авто, +Mono,OPTSTR_MONO,,,,,,,,Monofonia,,,,,Monó,,モノラル,모노,,,,,,,Моно,Монотоно,,,Моно, +Stereo,OPTSTR_STEREO,,,,,,,,Stereofonia,Estéreo,,,Stéréo,Sztereó,,ステレオ,스테레오,,,,Estéreo,,,Стерео,Стереотоно,,,Стерео, +Dolby Pro Logic Decoder,OPTSTR_PROLOGIC,,,,,Dolby Pro Logic-dekoder,,,Malkodilo de Dolby Pro Logic ,,,,,,,ドルビー プロロジック デコーダー,돌비 프로 로직 디코더,,Dolby Pro Logic Dekoder,,Decodificador Dolby Pro Logic,,Decodor Pro Logic Dolby,Декодер Dolby Pro Logic,,Dolby Pro Logic-dekoder,Dolby Pro Logic Dekoder,Декодер Dolby Pro Logic, +Quad,OPTSTR_QUAD,,,,,,,,Kvadratofonia,Cuádruple,,Dolby Pro Logic -dekooderi,,,,クァッド,쿼드,,,Cztery kanały,Quadrifônico,,,Четырёхканальный,Четвородупло,,Dörtlü,Чотирьохканальний, +5 speakers,OPTSTR_SURROUND,,,,5 reproduktorů,5 højttalere,5 Lautsprecher,,5 Laŭtparoliloj,5 altavoces,,5 kaiutinta,5 enceintes,5 hangfal,Surround,5 スピーカー,5 스피커,5 luidsprekers,5 høyttalere,Głośniki 5,5 alto-falantes,,5 boxe,5 динамиков,5 спикер,5 högtalare,5 hoparlörler,5 динаміків, +5.1 speakers,OPTSTR_5POINT1,,,,Reproduktory 5.1,5.1-højttalere,5.1 Lautsprecher,,5.1 Laŭtparoliloj,Altavoces 5.1,,5.1 kaiutinta,Enceintes 5.1,5.1 hangrendszer,Surround 5.1,5.1 スピーカー,5.1 스피커,5.1 luidsprekers,5.1 høyttalere,Głośniki 5.1,Auto-falantes 5.1,,Boxe 5.1,Динамики 5.1,5.1 спикер,5.1-högtalare,5.1 hoparlörler,Динаміки 5.1, +7.1 speakers,OPTSTR_7POINT1,,,,Reproduktory 7.1,7.1-højttalere,7.1 Lautsprecher,,7.1 Laŭtparoliloj,Altavoces 7.1,,7.1 kaiutinta,Enceintes 7.1,7.1 hangrendszer,Surround 7.1,7.1 スピーカー,7.1스피커,7.1 luidsprekers,7.1-høyttalere,Głośniki 7.1,Auto-falantes 7.1,,Boxe 7.1,Динамики 7.1,7.1 спикер,7.1-högtalare,7.1 hoparlörler,Динаміки 7.1, +Playback device,OPENALMNU_PLAYBACKDEVICE,,,,Přehravací zařízení,Afspilningsenhed,Wiedergabegerät,,Ludado-aparato,Dispositivo de reproducción,,Äänitoistolaite,Sortie sonore,Visszajátszó eszköz,Dispositivo di playback,プレイバック デバイス,재생 장치,Afspeelapparaat,Avspillingsenhet,Urządzenie odtwarzania,Dispositivo de reprodução,,Dispozitiv de redare,Устройство воспроизведения,Аудио уређај,Uppspelningsenhet,Oynatma cihazı,Пристрій відтворення, +Enable EFX,OPENALMNU_ENABLEEFX,,,,Povolit EFX,Aktiver EFX,EFX aktiv,,Ŝalti EFX,Permitir EFX,,Ota käyttöön EFX,Activer EFX,EFX engedélyezése,Abilita EFX,EFXを有効化,EFX 켬,EFX inschakelen,Aktiver EFX,Pozwól na EFX,Ativar EFX,,Activare EFX,Включить EFX,Укључи EFX,Aktivera EFX,EFX'i Etkinleştir,Увімкнути EFX, +Resampler,OPENALMNU_RESAMPLER,,,,,Resampler,,,Respecimenilo,,,Näytteenottotaajuusmuunnin,,,,リサンプラー,재배열 기기,,,,Reamostrador,,,Передискретизатор,Ресемплер,,Yeniden Örnekleyici,Ресемплер, +Sounds volume,SNDMNU_SFXVOLUME,,,,Hlasitost zvuků,Lydstyrke,Effektlautstärke,Φονή ήχων,Sona laŭteco,Volumen de sonido,,Äänitehosteiden voimakkuus,Volume des Sons,Effektek hangereje,Volume suoni,効果音音量,효과음 음량,Geluidsvolume,Lydvolum,Głośność Dźwięku,Volume de sons,,Volum efecte,Громкость звука,Јачина звука,Ljudvolym,Ses seviyesi,Гучність звуків, +Menu volume,SNDMNU_MENUVOLUME,,,,Hlasitost nabídek,Menu-volumen,Menülautstärke,Φονή μενού,Menuo-laŭteco,Volumen del menú,,Valikon äänenvoimakkuus,Volume du Menu,Menü hangereje,Volume menù,メニュー音量,메뉴 음량,Menu volume,Menyvolum,Głośność Menu,Volume do menu,,Volum meniu,Громкость меню,Јачина менија,Volym för menyer,Menü ses seviyesi,Гучність меню, +Music volume,SNDMNU_MUSICVOLUME,,,,Hlasitost hudby,Lydstyrke for musik,Musiklautstärke,Φονή μουσικής,Muzika laŭteco,Volumen de la música,,Musiikin äänenvoimakkuus,Volume Musique,Zene hangereje,Volume musica,音楽音量,배경음 음량,Muziekvolume,Musikkvolum,Głośność Muzyki,Volume da música,,Volum muzică,Громкость музыки,Јачина музике,Musikvolym,Müzik sesi,Гучність музики, +MIDI device,SNDMNU_MIDIDEVICE,,,,MIDI zařízení,MIDI-enhed,MIDI-Gerät,MIDI συσκεύη,MIDI-aparato,Dispositivo MIDI,,MIDI-laite,Sortie MIDI,MIDI eszköz,Dispositivo MIDI,MIDIデバイス,MIDI 장치,MIDI-apparaat,MIDI-enhet,Urządzenie MIDI,Dispositivo MIDI,,Dispozitiv MIDI,MIDI-проигрыватель,MIDI уређај,MIDI-enhet,MIDI cihazı,MIDI програвач, +Sound in Background,SNDMNU_BACKGROUND,,,,Zvuk na pozadí,Lyd i baggrunden,Sound im Hintergrund,Ήχος στο παρασκήνιο,Sono en fono,Sonido en segundo plano,,Ääni taustalla,Son activé en arrière plan,Háttérhangok,Suono di sottofondo,バックグラウンドでのサウンド,배경화면에서도 소리 재생,Geluid in de achtergrond,Lyd i bakgrunnen,Dźwięk w Tle,Som em segundo plano,,Sunet pe fundal,Звук в фоне,Звуци у позадини,Ljud i bakgrunden,Arka Planda Ses,Звуки на фоні, +Underwater reverb,SNDMNU_UNDERWATERREVERB,,,,Ozvěna pod vodou,Undervandsreverb,Unterwasserhall,,Subakva resono,Reverberación bajo el agua,,Vedenalaiskaiku,Reverbération sous l'eau,Vízalatti visszaverődés,Reverb sott'acqua,水中反響音,수중 울림효과,Onderwater nagalm,Undervanns romklang,Pogłos pod wodą,Reverberação debaixo d'água,Reverberação debaixo de água,Reverb subacvatic,Эффект затухания под водой,Подводни одјек,Undervattensreverb,Su altı yankısı,Підводний ефект, +Randomize pitches,SNDMNU_RANDOMIZEPITCHES,,,,Náhodné výšky tónu,Randomisere tonehøjder,Zufällige Tonhöhe,,Malcertigi son-peĉojn,Tonos aleatorios,,Satunnaista äänenkorkeuksia,Tons sonores aléatoires,Hangmagasság keverése,Rendi casuale il tono,ランダマイズ ピッチ,음높이 무작위화,Willekeurige plaatsen,Tilfeldig tonehøyde,Losuj tonacje,Tons aleatórios,Tons aleatórios,Ton sunete aleatoriu,Случайная высота,Рандомизација тонова,Slumpmässiga tonhöjder,Sahaları rastgele ayarlayın,Змінювати висоту звуків, +Sound channels,SNDMNU_CHANNELS,,,,Počet zvukových kanálů,Lydkanaler,Soundkanäle,Κανάλια ήχου,Sonokanaloj,Canales de sonido,,Äänikanavat,Canaux sonores,Hangcsatorna,Numero canali del suono,サウンド チャンネル,음향 채널,Geluidskanalen,Lydkanaler,Kanały dźwiękowe,Canais de som,,Canale de sunet,Количество каналов,Звучни канали,Ljudkanaler,Ses kanalları,Кількість каналів, +Sound backend,SNDMNU_BACKEND,,,,Zvukový systém,Lyd backend,Soundsystem,,Sonoservilo,Sistema de sonido,,Äänijärjestelmä,Traitement Son,Hang backend,Backend suono,サウンド バックエンド,음향 말미,Geluidsarme achterkant,Lyd backend,System dźwiękowy,Sistema de som,,Sistem de sunet,Звуковая подсистема,Звучни бекенд,Ljudbakgrund,Ses arka ucu,Звукова система, +OpenAL options,SNDMNU_OPENAL,,,,Nastavení OpenAL,OpenAL-muligheder,OpenAL Optionen,OpenAL ρυθμίσεις,OpenAL agordoj,Opciones de OpenAL,,OpenAL-asetukset,Options OpenAL,OpenAL beállításai,Opzioni OpenAL,OpenAL オプション,오픈에이엘 설정,OpenAL opties,OpenAL-alternativer,Opcje OpenAL,Opções de OpenAL,,Setări OpenAL,Настройки OpenAL,OpenAL подешавања,OpenAL-alternativ,OpenAL seçenekleri,Параметри OpenAL, +Restart sound,SNDMNU_RESTART,,,,Restartovat zvuk,Genstart af lyd,Sound neu starten,,Rekomenci sonon,Reiniciar sonido,,Käynnistä ääni uudelleen,Redémarrer moteur sonore,Hang újraindítása,Resetta il suono,サウンド再起動,음향 재시작,Herstart geluid,Start lyd på nytt,Zresetuj dźwięk,Reiniciar som,,Reinițializare sunet,Перезапустить звук,Поново покрени звук,Starta om ljudet,Sesi yeniden başlat,Перезавантажити звук, +Advanced options,SNDMNU_ADVANCED,,,,Pokročilá nastavení,Avancerede indstillinger,Erweiterte Optionen,Προχήρημενες ρυθμίσεις,Altnivelaj agordoj,Opciones avanzadas,,Edistyneet asetukset,Options avancées,Haladó beállítások,Opzioni avanzate,高度なオプション,고급 설정,Geavanceerde opties,Avanserte alternativer,Zaawansowane Opcje,Opções avançadas,,Setări avansate,Расширенные настройки,Напредна подешавања,Avancerade alternativ,Gelişmiş seçenekler,Розширені налаштування, +Module replayer options,SNDMNU_MODREPLAYER,,,,Nastavení přehrávače modulů,Indstillinger for modulafspiller,Modul-Spieler-Optionen,,Agordoj por modulreludilo,Opciones reproductor de módulos,,Moduulisoitinasetukset,Options lecteur de module,Modul lejátszó beállításai,Opzioni Module replayer,モジュールリプレイヤー オプション,모듈 재생 설정,Module replayer opties,Alternativer for modulavspiller,Opcje Modułu Odtwarzacza,Opções de reprodutor de módulos,,Setări de redare a modulelor,Параметры воспроизведения модулей,Подешавања модулног риплејера,Alternativ för modulåterspelare,Modül yeniden oynatıcı seçenekleri,"Параметри ""Module replayer""", +Midi player options,SNDMNU_MIDIPLAYER,,,,Nastavení MIDI přehrávače,Indstillinger for Midi-afspiller,MIDI-Spieler-Optionen,,Agordoj por MIDI-ludilo,Opciones de reproductor MIDI,,MIDI-soitinasetukset,Option lecteur MIDI,Midi lejátszó beállításai,Opzioni Midi player,Midi再生のオプション,MIDI 플레이어 설정,Midi speler opties,Alternativer for midispiller,Opcje Odtwarzacza Midi,Opções de reprodutor MIDI,,Setări player MIDI,Настройки MIDI-проигрывателя,MIDI плејер подешавања,Alternativ för Midi-spelare,Midi oynatıcı seçenekleri,Параметри MIDI-програвача, +Sound in Menus,SNDMNU_MENUSOUND,,,,Zvuk v menu,Lyd i menuer,Sound in Menüs,,Sono en menuoj,,,Ääni valikoissa,Son dans les menus,Hang a menükben,Suono nei menù,メニューでのサウンド,,Geluid in menu's,Lyd i menyer,Dźwięk w Menu,Som em menus,,Sunet in meniuri,Звук в меню,,Ljud i menyer,Menülerde Ses,Звук в меню, +Advanced Sound Options,ADVSNDMNU_TITLE,,,,Pokročilá nastavení zvuku,Avancerede lydindstillinger,Erweiterte Soundoptionen,,Altnivelaj sonaj agordoj,Opciones avanzadas de sonido,,Edistyneet ääniasetukset,Options Sonores Avancées,Haladó hangbeállítások,Opzioni avanzate dei suoni,高度なサウンドオプション,고급 음향 설정,Geavanceerde geluidsopties,Avanserte lydalternativer,Zaawansowane Opcje Dźwięku,Opções de áudio avançadas,,Setări de sunet avansate,Расширенные настройки,Напредна подешавања звука,Avancerade ljudalternativ,Gelişmiş Ses Seçenekleri,Розширені налаштування звуку, +Sample rate,ADVSNDMNU_SAMPLERATE,,,,Vzorkovací frekvence,Samplerate,Samplerate,,Specimenrapideco,Frecuencia de muestreo,,Näytteenottotaajuus,Cadence de Sampling,Mintavételezési ráta,,サンプルレート,샘플링레이트,Steekproeftarief,Samplingsfrekvens,Częstotliwość próbkowania,Taxa de amostragem,,Frecvență de eșantionare,Частота дискретизации,Фреквенција узорковања,Samplingsfrekvens,Örnek oranı,Частота дискретизації, +HRTF,ADVSNDMNU_HRTF,,,,,,,,,,,,,,,,머리전달함수,,,,,,,,,,,3D звук у навушниках (HRTF), +OPL Synthesis,ADVSNDMNU_OPLSYNTHESIS,,,,Emulace OPL,OPL-syntese,OPL Synthese,,OPL-sintezo,Síntesis OPL,,OPL-synteesi,Synthèse OPL,OPL szintézis,,OPLシンセサイズ,OPL 합성,OPL synthese,OPL-syntese,Synteza OPL,Síntese OPL,,Sinteză OPL,Синтез OPL,OPL синтеза,OPL-syntes,OPL Sentezi,Синтезатор OPL, +Number of emulated OPL chips,ADVSNDMNU_OPLNUMCHIPS,,,,Počet emulovaných OPL čipů,Antal emulerede OPL-chips,Anzahl OPL Chips,,Nombro da imititaj OPL-blatoj,Número de chips OPL emulados,,Emuloitavien OPL-piirien lukumäärä,Puces OPL émulées,Emulált OPL csipek száma,Numero di chip OPL emulati,OPLチップエミュレートの番号,에뮬레이트된 OPL 칩 수,Aantal geëmuleerde OPL chips,Antall emulerte OPL-brikker,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,Număr de cipuri OPL emulate,Количество эмулируемых чипов OPL,Број емулираних OPL чипа,Antal emulerade OPL-chips,Taklit edilen OPL çiplerinin sayısı,Кількість емульованих OPL-чіпів, +Full MIDI stereo panning,ADVSNDMNU_OPLFULLPAN,,,,Plné MIDI stereo,Fuld MIDI stereo panorering,Echte MIDI-Stereoeffekte,,Tuta MIDI-sterepanoramado,Balance estéreo MIDI completo,,Täysi MIDI-stereopanorointi,Latéralisation complète MIDI,Teljes MIDI sztereó tájolás,,Full MIDIステレオパンニング,완전한 MIDI 스테레오 패닝,Volledige MIDI stereo panning,Full MIDI stereo panorering,Pełne efekty stereo dla MIDI,Lateralidade estéreo completa para MIDI,,Panoramă stereo pentru MIDI,Полная стереопанорама для MIDI,Пуно MIDI стерео каналисање,Full MIDI-stereopanorering,Tam MIDI stereo kaydırma,Повне панорамування MIDI, +OPL Emulator Core,ADVSNDMNU_OPLCORES,,,,Emulační jádro OPL,OPL-emulatorkerne,OPL Emulatorkern,,OPL-imitilkerno,Núcleo de emulador OPL,,OPL-emulaattoriydin,Cœur émulateur OPL,,,OPL エミュレート コア,OPL 에뮬레이터 코어,OPL Emulator Kern,OPL-emulatorkjerne,Rdzeń Emulatora OPL,Núcleo do emulador de OPL,,Nucleu de emulare OPL,Ядро эмуляции OPL,OPL језгро емулације,OPL-emulatorns kärna,OPL Emülatör Çekirdeği,Тип OPL, +MIDI voices,ADVSNDMNU_MIDIVOICES,,,,Počet MIDI hlasů,MIDI-stemmer,MIDI Stimmen,,MIDI-voĉoj,Voces MIDI,,MIDI-äänet,Voix MIDI,MIDI hangok,Voci MIDI,MIDI ボイス,MIDI 최대 음색 양,MIDI-stemmen,MIDI stemmer,Głosy MIDI,Vozes MIDI,,Voci MIDI,MIDI-голоса,MIDI гласови,MIDI-stämmor,MIDI sesleri,MIDI поліфонія, +FluidSynth,ADVSNDMNU_FLUIDSYNTH,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Global,ADVSNDMNU_GLOBAL,,,,Globální,,,,Malloka,,,Yleinen,,,Globale,グローバル,전반적,Globaal,,Globalne,,,,Общие,Глобално,,Küresel,Загальні, +Freeverb,ADVSNDMNU_FREEVERB,,,,,,,,,,,,,,,フリーバーブ,프리버브,,,,,,,,,,Freeverb,, +Global Freeverb,ADVSNDMNU_GLOBAL_FREEVERB,,,,Globální Freeverb,Global Freeverb,Globales Freeverb,,Malloka Freeverb,Freeverb Global,,Yleinen Freeverb,Freeverb Global,,Freeverb globale,グローバル フリーバーブ,전반적 프리버브,Globale Freeverb,,Globalny Freeverb,Freeverb global,,Freeverb Global,Глобальный Freeverb,Глобални Freeverb,,Küresel Freeverb,Глобальний Freeverb, +Patch set,ADVSNDMNU_FLUIDPATCHSET,,,,Nástrojová sada,Patch-sæt,Patch-Set,,Flikaro,Set de parche,,Patch-asetus,Banque de Sons,,,パッチ セット,패치 세트,,Patch-sett,Zestaw łatek,Banco de sons,,Set patch,Патч-набор,Печ сет,Patch-uppsättning,Yama seti,Патч-набір, +Gain,ADVSNDMNU_FLUIDGAIN,,,,Zesílení,,Relative Lautstärke,,Akiro,Ganancia,,Vahvistus,,Visszaverődés,,ゲイン,쌓기,Relatief volume,,Wzmocnienie,Ganho,,Amplificare,Усиление,Појачање,Relativ volym,Kazanç,Підсилення, +Reverb,ADVSNDMNU_REVERB,,,,Ozvěna,,Hall,,Resono,Reverberación,,Kaiku,Réverbération,Visszhang,,リバーブ,리버브,Nagalm,,Pogłos,Reverberação,,,Реверберация,Одјек,,,Реверберація, +Reverb Level,ADVSNDMNU_REVERB_LEVEL,,,,Intenzita ozvěny,,Hallintensität,,Nivelo de resono,Nivel de reverberación,,Kaiunvoimakkuus,Niveau Réverb.,Visszhang szintje,,リバーブ量,리버브 강도,Nagalm niveau,Reverb-nivå,Poziom pogłosu,Nível de reverberação,,Nivel Reverb,Уровень реверберации,Ниво одјека,Reverb-nivå,Reverb Seviyesi,Рівень реверберації, +Chorus,ADVSNDMNU_CHORUS,,,,,,,,Koruso,,,,,,,コーラス,코러스,,,,,,Cor,Хор,Корус,,Koro,Хорус, +Timidity++,ADVSNDMNU_TIMIDITY,,,,,,,,,,,,,,,,,,,,,,,,,,,, +ADLMidi,ADVSNDMNU_ADLMIDI,,,,,,,,,,,,,,,,,,,,,,,,,,,, +OPNMidi,ADVSNDMNU_OPNMIDI,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Timidity config file,ADVSNDMNU_TIMIDITYCONFIG,,,,Konfigurační soubor Timidity,Timidity-konfigurationsfil,Timidity Konfigurationsdatei,,Agorda dosiero de Timidity,Ruta al archivo config. Timidity,,Timidity-config-tiedosto,Fichier de config. TiMidity,Timidity konfigurációs fájl,File configurazione Timidity,Timidity コンフィグファイル,Timidity 코딩 파일,Timidity++ configuratiebestand,Timidity konfigurasjonsfil,Plik konfiguracyjny Timidity,Arquivo de configuração do Timidity,,Fișier configurație Timidity,Файл конфигурации Timidity,Timidity конфигурациона датотека,Timidity-konfigurationsfil,Timidity yapılandırma dosyası,Файл конфігурації Timidity, +Relative volume,ADVSNDMNU_TIMIDITYVOLUME,,,,Relativní hlasitost,Relativ lydstyrke,Relative Lautstärke,,Relativa laŭteco,Volumen relativo,,Suhteellinen äänenvoimakkuus,Volume Relatif,Relatív hangerő,Volume relativo,相対音量,비교적인 볼륨,Relatief volume,Relativt volum,Względna głośność,Volume relativo,,Volum relativ,Относительная громкость,Релативна јачина,Relativ volym,Bağıl hacim,Відносна гучність, +WildMidi,ADVSNDMNU_WILDMIDI,,,,,,,,,,,,,,,,,,,,,,,,,,,, +WildMidi config file,ADVSNDMNU_WILDMIDICONFIG,,,,Konfigurační soubor WildMidi,WildMidi konfigurationsfil,WilfMidi Konfigurationsdatei,,Agorda dosiero de WildMidi,Archivo de config. WildMidi,,WildMidi-config-tiedosto,Fichier config. WildMidi,WildMidi konfigurációs fájl,File WildMidi config,WildMidi コンフィグファイル,WildMidi 코딩 파일,WildMidi configuratiebestand,WildMidi konfigurasjonsfil,Plik konfiguracyjny WildMidi,Arquivo de configuração do WildMidi,,Fișier configurație WildMidi,Файл конфигурации WildMidi,WildMidi конфигурациона датотека,WildMidi-konfigurationsfil,WildMidi yapılandırma dosyası,Файл конфігурації WildMidi, +Select configuration,ADVSNDMNU_SELCONFIG,,,,Vybrat konfiguraci,Vælg konfiguration,Konfiguration wählen,,Elekti agordojn,Seleccionar configuración,,Valitse kokoonpano,Sélectionner configuration,Konfiguráció kiválasztása,Seleziona la configurazione,構成選択,설정을 고르시오,Selecteer configuratie,Velg konfigurasjon,Wybierz konfigurację,Selecionar configuração,,Selectare configurație,Выбор конфигурации,Изабери конфигурацију,Välj konfiguration,Yapılandırma seçin,Вибір конфігурації, +Advanced Resampling,ADVSNDMNU_ADVRESAMPLING,,,,Pokročilé převzorkování,Avanceret resampling,Erweitertes Resampling,,Altnivela respecimenado,Resampleo avanzado,,Kehittynyt näytteenottotaajuuden muuntaminen,Resampling Avancé,Fejlett Resmapling,Resampling avanzato,高度なリサンプリング,향상된 리샘플링,Geavanceerde herbemonstering,Avansert resampling,Zaawansowane Próbkowanie,Reamostragem avançada,,Resempling avansat,Продвинутый ресэмплинг,Напредно ресампловање,Avancerad återampling,Gelişmiş Yeniden Örnekleme,Розширений ресемплінг, +OPL Bank,ADVSNDMNU_OPLBANK,,,,OPL sada,,,,Banko por OPL,Banco OPL,,OPL-pankki,Banque OPL,,,,OPL 뱅크,,,Bank OPL,Banco OPL,,Bancă OPL,Банк OPL,OPL банка,OPL-bank,,Банк OPL, +OPL Emulator Core,ADVSNDMNU_ADLOPLCORES,,,,Emulační jádro OPL,OPL-emulatorkerne,OPL Emulatorkern,,Imitilkerno por OPL,Núcleos de emulador OPL,,OPL-emulaattoriydin,Cœur Emulateur OPL,OPL emulátor mag,,OPL エミュレートコア,OPL 에뮬레이터 코어,OPL Emulator Kern,OPL-emulatorkjerne,Rdzeń Emulatora OPL,Núcleo do emulador de OPL,,Nucleu de emulare OPL,Ядро эмуляции OPL,OPL емулационо језгро,OPL-emulatorns kärna,OPL Emülatör Çekirdeği,Ядро емуляції OPL, +Run emulator at PCM rate,ADVSNDMNU_RUNPCMRATE,,,,Emulátor používá PCM vzorkovací frekvenci,Kør emulator ved PCM-hastighed,Emulator benutzt PCM Samplerate,,Ruli imitilon laŭ rapido de PCM,Ejecutar emulador a velocidad PCM,,Aja emulaattoria PCM-taajuudella,Emulateur utilise cadence PCM,Emulátor futtatása PCM rátán,Esegui l'emulatore con rate PCM,PCMレートでエミュレート実行,PCM 속도로 에뮬레이터 실행,Emulator maakt gebruik van PCM Samplerate,Kjør emulator med PCM-hastighet,Uruchom emulator w częstotliwości PCM,Rodar emulador em taxa PCM,,Utilizare cu frecvența PCM,Использовать с частотой PCM,Покрени емулацију на PCM стопи,Kör emulatorn med PCM-frekvens,Emülatörü PCM hızında çalıştırın,Використовувати з частотою PCM, +Number of emulated OPL chips,ADVSNDMNU_ADLNUMCHIPS,,,,Počet emulovaných OPL čipů,Antal emulerede OPL-chips,Anzahl OPL Chips,,Numbro da imitaj OPL-blatoj,Número de chips OPL emulados,,Emuloitavien OPL-piirien lukumäärä,Puces OPL émulées,Emulált OPL csipek száma,Numero di chip OPL emulati,OPLチップエミュレートの番号,에뮬레이트된 OPL 칩 개수,Aantal geëmuleerde OPL chips,Antall emulerte OPL-brikker,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,Număr de cipuri GUS emulate,Количество эмулируемых чипов OPL,Број емулираних OPL чипова,Antal emulerade OPL-chips,Taklit edilen OPL çiplerinin sayısı,Кількість емульованих OPL-чіпів, +Volume model,ADVSNDMNU_VLMODEL,,,,Model hlasitosti,Volumenmodel,Lautstärkemodell,,Modelo de laŭteco,Modelo de volumen,,Äänenvoimakkuusmalli,Modèle de Volume,Hangmodell,Modello di volume,音量モデル,모델 볼륨,Volume model,Volummodell,Model głośności,Modelo de volume,,Model volum,Модель громкости,Волумски модел,Volymmodell,Hacim modeli,Модель гучності, +OPN2 Emulator Core,ADVSNDMNU_OPNCORES,,,,Emulační jádro OPN2,OPN2-emulatorkerne,OPN2 Emulatorkern,,OPN2 Imitilkerno,Núcleo de emulador OPN2,,OPN2-emulaattoriydin,Cœur émulateur OPN2,OPN2 Emulátor Mag,,OPN2 エミュレート コア,OPN2 에뮬레이터 코어,OPN2 Emulatorkern van de OPN2-emulator,OPN2 Emulatorkjerne,Rdzeń Emulatora OPN2,Núcleo do emulador de OPN2,,Nucleu de emulare OPN2,Ядро эмуляции OPN2,OPN2 језгро емулације,OPN2-emulatorkärna,OPN2 Emülatör Çekirdeği,Ядро емуляції OPN2, +GUS Emulation,ADVSNDMNU_GUSEMULATION,,,,Emulace GUS,GUS-emulering,GUS Emulation,,GUS Imitado,Emulación GUS,,GUS-emulaatio,Emulation GUS,GUS Emuláció,,GUS エミュレーション,GUS 에뮬레이션,GUS-emulatie,GUS-emulering,Emulacja GUS,Emulação de GUS,,Emulare GUS,Эмуляция GUS,GUS емулација,GUS-emulering,GUS Emülasyonu,Емуляція GUS, +GUS config file,ADVSNDMNU_GUSCONFIG,,,,Konfigurační soubor GUS,GUS-konfigurationsfil,GUS Konfigurationsdatei,,Agorda dosiero de GUS,Archivo de config. GUS,,GUS-config-tiedosto,Fichier Config. GUS,GUS konfigurációs fájl,File GUS config,GUS コンフィグファイル,GUS 코딩 파일,GUS-configuratiebestand,GUS konfigurasjonsfil,Plik konfiguracyjny GUS,Arquivo de configuração do GUS,,Fișier configurație GUS,Файл конфигурации для GUS,GUS конфигурациона датотека,GUS-konfigurationsfil,GUS yapılandırma dosyası,Файл конфігурації для GUS, +Read DMXGUS lumps,ADVSNDMNU_DMXGUS,,,,Načíst DMXGUS soubory,Læs DMXGUS-klumper,Lese DMXGUS,,Legi DMXGUS Masojn,Leer archivos DMXGUS,,Lue DMXGUS-tietoja,Lire fichiers DMXGUS,DMXGUS lumpok beolvasása,Leggi i lump DMXGUS,DMXGUS ランプを読む,DMXGUS 럼프 읽기,DMXGUS-klonten lezen,Les DMXGUS-filer,Czytaj pliki DMXGUS,Ler lumps DMXGUS,,Citire fișiere DMXGUS,Читать файлы DMXGUS,Читај DMXGUS фајлове,Läsa DMXGUS-filer,DMXGUS dosyalarını okuma,Читати файли DMXGUS, +GUS memory size,ADVSNDMNU_GUSMEMSIZE,,,,Velikost paměti GUS,GUS-hukommelsesstørrelse,GUS Speichergröße,,GUS Memorampleksoj,Tamaño de memoria de GUS,,GUS-muistikoko,Taille mémoire GUS,GUS memória mérete,Dimensione della memoria per GUS,GUS メモリーサイズ,GUS 메모리 크기,GUS-geheugengrootte,GUS-minne størrelse,Rozmiar pamięci GUS,Tamanho de memória do GUS,,Memorie alocată pentru GUS,Размер памяти GUS,GUS величина памћења,GUS minnesstorlek,GUS bellek boyutu,Розмір пам'яті GUS, +Number of emulated OPN chips,ADVSNDMNU_OPNNUMCHIPS,,,,Počet emulovaných OPN čipů,Antal emulerede OPN-chips,Anzahl OPN Chips,,Nombro da imititaj OPL-blatoj,Número de chip OPN emulados,,Emuloitavien OPN-piirien lukumäärä,Puces OPN émulées,Emulált OPL csipek száma,Numero di chip OPN emulati,OPNチップエミュレートの番号,에뮬레이트된 OPN 칩 개수,Aantal geëmuleerde OPL chips,Antall emulerte OPN-brikker,Liczba emulowanych czipów OPN,Número de chips OPN emulados,,Număr de cipuri OPN emulate,Количество эмулируемых чипов OPN,Број емулираних OPN чипова,Antal emulerade OPN-chips,Taklit edilen OPN çiplerinin sayısı,Кількість емульованих OPN-чіпів, +Use custom WOPL bank,ADVSNDMNU_ADLCUSTOMBANK,,,,Použít vlastní WOPL sadu,Brug af brugerdefineret WOPL-bank,Benutzerdefinierte WOPL Bank,,Uzi laŭmendan WOPL-bankon,Utilizar banco WOPL personalizado,,Käytä mukautettua WOPL-pankkia,Utiliser Banque WOPL perso,Saját WOPL bank használata,Usa WOPL bank personalizzato,カスタムWOPL bankを使用,사용자 지정 WOPL 뱅크 사용,Gebruik de aangepaste WOPL bank,Bruk egendefinert WOPL-bank,Użyj niestandardowego banku WOPL,Usar banco WOPL personalizado,,Utilizați propriul bank WOPN,Использовать собственный банк WOPL,Користи прилагођенуу WOPL банку,Använd anpassad WOPL-bank,Özel WOPL bankası kullanın,Використовувати власний банк WOPL, +WOPL Bank file,ADVSNDMNU_OPLBANKFILE,,,,Soubor WOPL sady,WOPL Bank-fil,WOPL Bank-Datei,,WOPL-Bankodosiero,Archivo de banco WOPL,,WOPL-pankkitiedosto,Banque WOPL,WOPL Bank fájl,File WOPL Bank,WOPL bankファイル,WOPL 뱅크 파일,WOPL Bank-bestand,WOPL Bank-fil,Plik banku WOPL,Banco WOPL,,Fișier WOPN bank,Файл с банком WOPL,WOPL фајл банка,WOPL Bank-fil,WOPL Bank dosyası,Файл з банком WOPL, +Use custom WOPN bank,ADVSNDMNU_OPNCUSTOMBANK,,,,Použít vlastní WOPN sadu,Brug af brugerdefineret WOPN-bank,Benutzerdefinierte WOPN Bank,,Uzi laŭmendan WOPN-bankon,Utilizar banco WOPN personalizado,,Käytä mukautettua WOPN-pankkia,Utiliser Banque WOPN perso,Saját WOPN bank használata,Usa WOPN bank personalizzato,カスタムWOPN bankを使用,사용자 지정 WOPN 뱅크 사용,Gebruik aangepaste WOPN-bank op maat,Bruk egendefinert WOPN-bank,Użyj niestandardowego banku WOPN,Usar banco WOPN personalizado,,Utilizați propriul bank WOPN,Использовать собственный банк WOPN,Користи прилагођену WOPN банку,Använd anpassad WOPN-bank,Özel WOPN bankası kullanın,Використовувати власний банк WOPN, +WOPN Bank file,ADVSNDMNU_OPNBANKFILE,,,,Soubor WOPN sady,WOPN Bank-fil,WOPN Bank-Datei,,WOPN-Bankodosiero,Archivo de banco WOPN,,WOPN-pankkitiedosto,Banque WOPN,WOPN Bank fájl,File WOPN Bank,WOPN bankファイル,WOPN 뱅크 파일,WOPN Bank-bestand,WOPN-bankfil,Plik banku WOPN,Banco WOPN,,Fișier WOPN bank,Файл с банком WOPN,WOPN фајл банка,WOPN Bank-fil,WOPN Banka dosyası,Файл з банком WOPN, +Aliasing,OPTVAL_ALIASING,,,,,,,,Krenelaro,,,,,,,エイリアシング,에일리어싱,,,,,,Dedublare,Сглаживание,Преклапање,,Takma Adlandırma,Згладжування, +Linear,OPTVAL_LINEAR_1,This setting is duplicated threefold in order to allow for different grammatical gender endings,,,Lineární,Lineær,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Lineær,Liniowy,,,Liniar,Линейное,Линеаран,Linjär,Doğrusal,Лінійне, +Linear,OPTVAL_LINEAR_2,,,,Lineární,Lineær,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Lineær,Liniowa,,,Liniar,Линейная,Линеаран,Linjär,Doğrusal,Лінійна, +Linear,OPTVAL_LINEAR_3,,,,Lineární,Lineær,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Lineær Lineær,Liniowe,,,Liniar,Линейный,Линеаран,Linjär,Doğrusal,Лінійний, +Nearest,OPTVAL_NEAREST,,,,Nejbližší,Nærmeste,Nächster Nachbar,,Plej proksima,Cercano,,Lähin,Nearest,Legközelebbi,Il più vicino,最寄り,가까이,Naast,Nærmeste,Najbiższe,Mais próximo,,Cel mai apropriat,Ближайший,Најближе,Närmaste,En yakın,Найближчий, +PCF (Low),OPTVAL_PCF_LOW,,,,PCF (nízké),PCF (lav),PCF (niedrig),,PCF (Malalta),PCF (Bajo),,PCF (matala),PCF (Low),PCF (Alacsony),PCF (basso),PCF (低),PCF (하급),PCF (Laag),PCF (lav),PCF (Niski),PCF (Baixo),,PCF (Scăzut),PCF (низкий),PCF (ниско),PCF (låg),PCF (Düşük),PCF (низький), +PCF (Medium),OPTVAL_PCF_MEDIUM,,,,PCF (střední),PCF (medium),PCF (mittel),,PCF (Meza),PCF (Medio),,PCF (keskitaso),PCF (Medium),PCF (Közepes),PCF (medio),PCF (中),PCF (중급),,PCF (middels),PCF (Średni),PCF (Médio),,PCF (Mediu),PCF (средний),PCF (средње),PCF (medelhög),PCF (Orta),PCF (средній), +PCF (High),OPTVAL_PCF_HIGH,,,,PCF (vysoké),PCF (høj),PCF (hoch),,PCF (Alta),PCF (Alto),,PCF (korkea),PCF (High),PCF (Magas),PCF (alto),PCF (高),PCF (상급),PCF (Hoog),PCF (høy),PCF (Wysoki),PCF (Alto),,PCF (Ridicat),PCF (высокий),PCF (високо),PCF (hög),PCF (Yüksek),PCF (високий), +Cubic,OPTVAL_CUBIC,,,,Kubická,Kubisk,Kubisch,,Kuba,Cúbico,,Kuutio,Cubique,Négyzetes,Cubico,キュービック,큐빅,Kubieke,Kubisk,Sześcienny,Cúbico,,Cub,Кубическое,Кубан,Kubisk,Kübik,Кубічне, +Band-limited step,OPTVAL_BLEP,,,,Omezené krokování,Båndbegrænset trin,Bandbegrenzte Schritte,,Bendo-limigita paŝo,Paso limitado por banda,,Kaistarajoitettu askel,Step limité par bande,Sáv-limitált lépés,Passo limitato dalla banda,帯域制限ステップ,제한된 단계별 밴드,Bandbeperkte stap,Båndbegrenset trinn,Krok ograniczony pasmem,Passo limitado por banda,,Limitare frecvență pas-cu-pas,Ограниченный полосой пропускания шаг,Постепено ограничење фреквенције,Bandbegränsat steg,Bant sınırlı adım,Покрокове обмеження частоти, +Linear (Slower),OPTVAL_LINEARSLOW,,,,Lineární (pomalejší),Lineær (langsommere),Linear (langsamer),,Lineara (Pli malrapida),Lineal (más lento),,Lineaarinen (hitaampi),Linéaire (Lent),Lineáris (Lassabb),Lineare (più lento),リニア(遅め),선형 (느리게),Lineair (langzamer),Lineær (langsommere),Liniowy (wolniejszy),Linear (mais lento),,Liniar (Mai lent),Линейное (медленнее),Линеаран (спорије),Linjär (långsammare),Doğrusal (Daha Yavaş),Лінійне (повільніше), +Band-limited linear,OPTVAL_BLAM,,,,Omezená lineární,Båndbegrænset lineær,Bandbegrenzt linear,,Bendo-limigita lineara,Lineal limitado por banda,,Kaistarajoitettu lineaarinen,Linéaire limité par bande,Sáv-limitált lineáris,Lineare limitato dalla banda,帯域制限リニア,밴드 제한 식 선형,Band-beperkt lineair,Båndbegrenset lineær,Liniowy ograniczony pasmem,Linear limitado por banda,,Limitare frecvență liniară,Ограниченное полосой пропускания линейное,Линеарно ограничење фреквенције,Bandbegränsad linjär,Bant sınırlı doğrusal,Лінійне обмеження частоти, +Cubic (Slower),OPTVAL_CUBICSLOW,,,,Kubická (pomalejší),Kubisk (langsommere),Kubisch (langsamer),,Kuba (Pli malrapida),Cúbico (más lento),,Kuutio (hitaampi),Cubique (Lent),Négyzetes (Lassabb),Cubico (più lento),キュービック (遅め),큐빅 (느리게),Kubieke (langzamer),Kubisk (langsommere),Sześcienny (wolniejszy),Cúbico (mais lento),,Cub (Mai lent),Кубическое (медленнее),Кубан (спорије),Kubisk (långsammare),Kübik (Daha Yavaş),Кубічне (повільніше), +Sinc,OPTVAL_SINC,,,,,Sinc,,,,Seno cardinal,,,,,,シンク,싱크,,,,Seno cardinal,,Sinus cardinal,Кардинальный синус,Синк,,,Функція sinc, +Note on/off only,OPTVAL_NOTEONOFFONLY,,,,Pouze začátek/konec noty,Kun note on/off,Nur für Note an/aus ,,Nur noto ek/for,Solo notas de Activ./Desact.,,Vain nuotti päällä/pois,Note on/off seulement,Hangjegy ki/be csak,Note solamente ON/OFF,ノート オン/オフ のみ,노트를 끄거나 켰을 때,Alleen toon aan/uit,Merk kun på/av,Tylko dla włączonych/wyłączonych notatek,Somente notas ligadas/desligadas,,Numai la activarea/oprirea notelor,Только при включении/отключении нот,Само током укључења/искључења ноте,Endast anteckning på/av,Yalnızca not açma/kapama,Лише для нот, +Full ramping,OPTVAL_FULLRAMPING,,,,Plný náběh,Fuld rampe,,,Plena pligrandigado,Aumento completo,,Täysi kerrytys,Rampe complète,Teljes ramping,Ramping completo,フルランピング,최대 램핑,Volledige helling,,Pełne zwiększenie,Rampa completa,,Creștere completă,Полное наращивание,Пуно појачање,Full rampning,Tam rampa,Згладжування різких змін гучності, +Master volume,MODMNU_MASTERVOLUME,,,,Celková hlasitost,Master-volumen,Grundlautstärke,,Ĉeflaŭteco,Volumen maestro,,Yleisäänenvoimakkuus,Volume maître,Fő hangerő,Volume master,全体音量,마스터 볼륨,Hoofdvolume,Hovedvolum,Całkowita głośność,Volume geral,,Volum general,Общая громкость,Глацни звук,Huvudvolym,Ana ses seviyesi,Загальна гучність, +Quality,MODMNU_QUALITY,,,,Kvalita,Kvalitet,Qualität,,Kvaliteco,Calidad,,Laatu,Qualité,Minőség,Qualità,クオリティ,품질,Kwaliteit,Kvalitet,Jakość,Qualidade,,Calitate,Качество,Квалитет,Kvalitet,Kalite,Якість, +Volume ramping,MODMNU_VOLUMERAMPING,,,,Křivka hlasitosti,Lydstyrke-rampe,Lautstärkeverhalten,,Laŭteco-pligrandigado,Aumento gradual de Volumen,,Äänenvoimakkuuden kertyminen,Rampe du volume,,Ramping volume,音量ランピング,볼륨 램핑,Volume-aanvulling,Volumramping,Zwiększenie głośności,Rampa de volume,,Creștere volum,Наращивание громкости,Појачавање звука,Volymrampning,Hacim artırma,Нарощування гучності, +Chip-o-matic,MODMNU_CHIPOMATIC,,,,,,,,,,,,,,,チップ オー マチック,칩-오-매틱,,,,,,,,,,,, +MAME OPL2,OPTVAL_MAMEOPL2,,,,,,,,,,,,,,,,마메 OPL2,,,,,,,,,,,, +DOSBox OPL3,OPTVAL_DOSBOXOPL3,,,,,,,,,,,,,,,,도스박스 OPL3,,,,,,,,,,,, +Java OPL3,OPTVAL_JAVAOPL3,,,,,,,,,,,,,,,,자바 OPL3,,,,,,,,,,,, +Nuked OPL3,OPTVAL_NUKEDOPL3,,,,,,,,,,,,,,,,,,,,,,,,,,,, +MAME YM2612,OPTVAL_MAMEOPN2,,,,,,,,,,,,,,,,마메 YM2612,,,,,,,,,,,, +Neko Project II Kai OPNA,OPTVAL_NP2OPNA,,,,,,,,,,,,,,,,,,,,,,,,,,,, +MAME YM2608,OPTVAL_MAMEOPNA,,,,,,,,,,,,,,,,마메 YM2608,,,,,,,,,,,, +PMDWin OPNA,OPTVAL_PMDWINOPNA,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Opal OPL3,OPTVAL_OPALOPL3,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Nuked OPL3 v1.7.4,OPTVAL_NUKEDOPL3174,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Nuked OPN2,OPTVAL_NUKEDOPN2,,,,,,,,,,,,,,,,,,,,,,,,,,,, +GENS YM2612,OPTVAL_GENSOPN2,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Auto (Use setup of bank),ADLVLMODEL_AUTO,,,,Auto (použít nastavení sady),Auto (Brug opsætning af bank),Auto (Benutze Einstelliung der Bank),,Aŭtomata (Uzi bankagordaĵon),Auto (Usar config. del banco),,Automaattinen (käytä pankin asetuksia),Auto (Utiliser paramètre banque),Automatikus (Beállított bank használata),Automatico (Usa le impostazioni del bank),自動(bankのセットアップ使用),자동(뱅크 셋업 사용),Auto (gebruik instelling van de bank),Auto (Bruk oppsett av bank),Automatycznie (Użyj ustawień banku),Automático (usar definições de banco),,Auto (configurare din bancă),Авто (настройка из банка),Аутоматски (користи намештену банку),Auto (använder bankens inställning),Otomatik (Banka kurulumunu kullan),Авто (налаштування з банку), +Generic,ADLVLMODEL_GENERIC,,,,Standardní,Generisk,Allgemein,,Komuna,Genérico,,Yleinen,Générique,Általános,Generico,一般的,전형적,Algemeen,Generisk,Ogólne,Genérico,,,Общий,Генерично,Generisk,Jenerik,Загальний, +OPL Native,ADLVLMODEL_NATIVE,,,,Nativní OPL,OPL Native,OPL Nativ,,Nativa OPL,Nativo OPL,,Luontainen OPL,OPL Natif,Natív OPL,,OPLネイティブ,고유 OPL,,,Natywne OPL,Nativo OPL,,OPL propriu,Встроенная OPL,OPL домаћи,OPL inhemsk,OPL Yerli,Вбудована OPL, +"DMX (Accurate, with AM bug)",ADLVLMODEL_DMX,,,,"DMX (Přesný, s AM chybou)","DMX (nøjagtig, med AM-fejl)",,,,,,,,"DMX (Pontos, de AM buggal)",,,데이터 마이닝 확장,"DMX (accuraat, met AM bug)","DMX (Nøyaktig, med AM-feil)",,"DMX (preciso, com bug de AM)",,"DMX (Precis, cu probleme în AM)","DMX (Точная, с ошибкой АМ)",,"DMX (exakt, med AM-bugg)","DMX (Doğru, AM hatalı)","DMX (Точна, з помилкою АМ)", +"Apogee (Accurate, with AM bug)",ADLVLMODEL_APOGEE,,,,"Apogee (Přesný, s AM chybou)","Apogee (nøjagtig, med AM-fejl)",,,,,,,,"Apogee (Pontos, de AM buggal)",,,어포지,"Apogee (accuraat, met AM bug)","Apogee (Nøyaktig, med AM-feil)",,"Apogee (preciso, com bug de AM)",,"Apogee (Precis, cu probleme în AM)","Apogee (Точная, с ошибкой АМ)",,"Apogee (Exakt, med AM-bugg)","Apogee (Doğru, AM hatası ile)","Apogee (Точна, з помилкою АМ)", +Win9X-like (SB16),ADLVLMODEL_WIN9X,,,,Jako Windows 9X (SB16),Win9X-lignende (SB16),Wie Windows 9X (SB16),,Kiel Win9X (SB16),Como Win9X (SB16),,Win9x-kaltainen (SB16),,Win9X szerű (SB16),,Win9X式 (SB16),Win9X 같게 (SB16),Win9X-achtig (SB16),Win9X-lignende (SB16),Jak w Win9X (SB16),Estilo Win9X (SB16),,Similar cu Win9X (SB16),Похожая на Win9X (Вариант SB16),Као у Win9X-у (SB16),Win9X-liknande (SB16),Win9X benzeri (SB16),Схожа на Win9X (Варіант SB16), +Win9X-like (Generic FM),ADLVLMODEL_WIN9XGENERIC,,,,Jako Windows 9X (Generic FM),Win9X-lignende (generisk FM),Wie Windows 9X (Generic FM),,Kiel Win9X (Generic FM),Como Win9X (Generic FM),,Win9x-kaltainen (Generic FM),,Win9X szerű (Általános FM),,Win9X式 (Generic FM),Win9X 같게 (Generic FM),Win9X-achtig (Generic FM),Win9X-lignende (Generisk FM),Jak w Win9X (Generic FM),Estilo Win9X (FM genérico),,Similar cu Win9X (Generic FM),Похожая на Win9X (Вариант Generic FM),Као у Win9X-у (Generic FM),Win9X-liknande (generisk FM),Win9X benzeri (Jenerik FM),Схожа на Win9X (Варіант Generic FM), +DMX (Without AM voice bug),ADLVLMODEL_DMX_FIXED,,,,DMX (Bez AM hlasové chyby),DMX (uden AM-stemmefejl),DMX (Ohne AM-Stimmenfehler),,DMX (Sen cimo de AM-voĉo),DMX (Sin bug de voz AM),,DMX (ilman AM-äänivikaa),DMX (Sans bug canaux AM),DMX (AM hanghiba nélkül),,DMX(AMボイスバグ無し),,DMX (zonder AM voice bug),DMX (uten AM-stemmefeil),DMX (bez głosowego błędu AM),DMX (sem bug de voz de AM),,DMX (Fără probleme în AM),DMX (Без ошибки АМ),,DMX (utan AM-röstfel),DMX (AM ses hatası olmadan),DMX (Без помилки АМ), +Apogee (Without AM voice bug),ADLVLMODEL_APOGEE_FIXED,,,,Apogee (Bez AM hlasové chyby),Apogee (uden AM-stemmefejl),Apogee (Ohne AM-Stimmenfehler),,Apogee (Sen cimo de AM-voĉo),Apogee (Sin bug de voz AM),,Apogee (ilman AM-äänivikaa),Apogee (avec bug canaux AM),Apogee (AM hanghiba nélkül),,Apogee(AMボイスバグ無し),,Apogee (zonder AM voice bug),Apogee (uten AM-stemmefeil),Apogee (bez głosowego błędu AM),Apogee (sem bug de voz de AM),,Apogee (Fără probleme în AM),Apogee (Без ошибки АМ),,Apogee (utan AM-röstfel),Apogee (AM ses hatası olmadan),Apogee (Без помилки АМ), +IBM Audio Library Interface,ADLVLMODEL_AIL,,,,,,,,IBM Aŭdbibiloteka Interfaco,,,,,IBM Hang Könyvtár Interfész,,,,,,Interfejs Biblioteki Dźwięków IBM,Interface de Biblioteca de Áudio IBM,,Interfață de Bibliotecă IBM,IBM AIL,,IBM Audio Library Interface (gränssnitt för ljudbibliotek),IBM Ses Kitaplığı Arayüzü,, +HMI Sound Operating System,ADLVLMODEL_HMI,,,,,,,,HMI Sonoperaciumo,,,,,HMI Hang Operációs Rendszer,,,,,,System Operacyjny Dźwięków HMI,Sistema Operacional de Som HMI,,Sistem Sonor HMI,HMI SOS,,HMI-ljud Operativsystem,HMI Ses İşletim Sistemi,, +"HMI SOS (Old, with bugs)",ADLVLMODEL_HMIOLD,,,,"HMI SOS (Starý, s chybami)","HMI SOS (gammelt, med fejl)","HMI SOS (alt, mit Fehlern)",,"HMI SOS (Malnova, kun cimoj)","HMI SOS (Viejo, con bugs)",,"HMI SOS (vanha, vikainen)",HMI SOS (vieux et buggé),"HMI SOS (Régi, bugokkal)",,HMI SOS(旧式、バグ含む),,"HMI SOS (oud, met bugs)","HMI SOS (gammel, med feil)","HMI SOS (Stare, z błędami)","SOS HMI (antigo, com bugs)",,"HMI SOS (Vechi, cu probleme)",HMI SOS (Старый вариант с ошибками),,"HMI SOS (gammalt, med fel)","HMI SOS (Eski, hatalı)",HMI SOS (Старий варіант з помилками), +Unlimited,OPTVAL_UNLIMITED,,,,Neomezené,Ubegrænset,Unlimitiert,,Senlima,Ilimitado,,Rajoittamaton,Illimité,Végtelen,Illimitato,無制限,무제한,Onbeperkt,Ubegrenset,Nieskończone,Sem limites,,Nelimitat,Без ограничений,Бескрајно,Obegränsad,Sınırsız,Необмежено, +256K,OPTVAL_256K,,,,,,,,,,,,,,,,,,,,,,,,,,,, +512K,OPTVAL_512K,,,,,,,,,,,,,,,,,,,,,,,,,,,, +768K,OPTVAL_768K,,,,,,,,,,,,,,,,,,,,,,,,,,,, +1024K,OPTVAL_1024K,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,Postprocessing,,,,,,,,,,,,,,,,,,,,,,,,,,, +Uncharted 2,OPTVAL_UNCHARTED2,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Hejl Dawson,OPTVAL_HEJLDAWSON,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Reinhard,OPTVAL_REINHARD,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Palette,OPTVAL_PALETTE,,,,Paleta,Palet,,Παλέτα,Paletro,Paleta,,Paletti,,Paletta,Palette,パレット,팔레트,Palet,,Paleta,Paleta,Palete,Paletă,Палитра игры,Палет,Palett,Palet,Палітра гри, +Low,OPTVAL_LOW,,,,Nízká,Lav,Niedrig,Χαμηλό,Malalta,Bajo,,Matala,Bas,Alacsony,Basso,低,낮음,Laag,Lav,Niskie,Baixo,,Scăzut,Низкое,Ниско,Låg,Düşük,Низьке, +Medium,OPTVAL_MEDIUM,,,,Střední,,Mittel,Μεσαίο,Meza,Medio,,Keskitaso,Moyen,Közepes,Medio,中,중간,Middel,Middels,Średnie,Médio,,Mediu,Среднее,Средње,Medelstor,Orta,Середнє, +High,OPTVAL_HIGH,,,,Vysoká,Høj,Hoch,Υψηλό,Alta,Alto,,Korkea,Elevé,Magas,Alto,高,높음,Hoog,Høy,Wysokie,Alto,,Ridicat,Высокое,Високо,Hög,Yüksek,Високе, +Extreme,OPTVAL_EXTREME,,,,Extrémní,Ekstrem,Extrem,Ακράιο,Ekstrema,Extremo,,Äärimmäinen,Extrême,Extrém,Estremo,最高,매우 높음,Extreem,Ekstrem,Ekstremalne,Extremo,,Extrem,Максимальное,Екстремно,Extremt,Aşırı,Максимальне, +Obverse,OPTVAL_OBVERSEFIRST,,,,Vpřed (obvers),Forside,Obvers,Παρατήρησε,Antaŭa,Anverso,,Etupuoli,,Ellentétes,Dritto,正面,앞면,Obvers,Forside,Awers,Obverso,,Avers,Прямой,Супротно,Framsida,Ön yüz,Прямий, +Reverse,OPTVAL_REVERSEFIRST,,,,Vzad (revers),Bagside,Revers,Αντίστροφο,Inversa,Inverso,,Käänteinen,Inverse,Fordított,Contrario,反転,반전,Revers,Baksiden,Rewers,Reverso,,Invers,Обратный,Обрнуто,Baksida,Ters,Зворотний, +Postprocessing,GLMNU_POSTPROCESS,,,,,Efterbehandling,,Μετα-επεξεργασία,Postprocezado,Postprocesado,,Jälkikäsittely,,,,ポストプロセッシング,포스트프로세싱 적용,Nabewerking,Etterbehandling,Przetwarzanie końcowe,Pós-processamento,,Postprocesare,Постобработка,Пост обрада,Efterbehandling,İşlem sonrası,Постобробка, +Tonemap Mode,GLPREFMNU_TONEMAP,,,,Režim tónovací mapy,Tonemap-tilstand,Tonemap Modus,,Reĝimo de Tonmapo,Modo de mapa de tonos,,Sävykarttatila,Mode Tonemap,Színleképzés módja,Modalità Tonemap,トーンマップ モード,톤맵 모드,Tonemap modus,Tonemap-modus,Tryb Mapowania Tonów,Tipo de tonemap,,Mod Tonemap,Режим тонового отображения,Тонирано-мапни мод,Tonemap-läge,Ton Haritası Modu,Режим тонального відображення, +Lens distortion effect,GLPREFMNU_LENS,,,,Efekt distorze čočky,Objektivforvrængningseffekt,Optischer Verzerrungseffekt,,Lensdistorto-efiko,Efecto de distorsión de lente,,Linssinvääristystehoste,Effet distorsion de lentille,Lencsetorzulás effekt,Effetto distorsione della lente,レンズの歪みエフェクト,렌즈 왜곡 효과,Effect van de lensvervorming,Linseforvrengningseffekt,Efekt zniekształcenia obiektywu,Distorção de lente,Efeito de distorção da lente,Efect de distorsionare,Эффект искажения линзы,Дисторзија објектива ефект,Linsförvrängningseffekt,Lens bozulma efekti,Ефект деформації лінзи, +FXAA Quality,GLPREFMNU_FXAA,,,,Kvalita FXAA,FXAA-kvalitet,FXAA Qualität,FXAA ποίοτητα,Kvaliteco de FXAA,Calidad FXAA,,FXAA-laatu,Qualité FXAA,FXAA minősége,Qualità FXAA,FXAA品質,FXAA 품질,FXAA-kwaliteit,FXAA-kvalitet,Jakość FXAA,Qualidade de FXAA,,Calitate FXAA,Качество FXAA,FXAA квалитет,FXAA-kvalitet,FXAA Kalitesi,Якість FXAA, +Dither output,GLPREFMNU_DITHER,,,,Dithering,Dither-udgang,Dithering,,Apliki punktojn al eligo,Dither de salida,,Sekoitussävytyksen (dithering) ulostulo,Dithering,Árnyalás kimenet,Dithering,ディザー出力,떨림 효과 출력,Dither output,Dither-utgang,Dygotanie,Dithering,,Putere Dithering,Дизеринг,Учестаност трептања,Dither-utgång,Dither çıkışı,Дитеринг, +Tonemap Palette Order,GLPREFMNU_PALTONEMAPORDER,,,,Pořadí palety tónovací mapy,Tonemap-palettens rækkefølge,Palettensortierung für Tonemap,,Ordo de Kolormapo-Paletro,Orden de la paleta en mapa de tonos,,Sävykartan paletin järjestys,Ordre des palettes tonemap,Színleképzés paletta sorrend,Ordine della Palette Tonemap,トーンマップパレット順序,톤맵 팔레트 순서,Tonemap Palet Orde van het Tonemap-palet,Tonemap-palettrekkefølge,Kolejność Palet Mapowania Tonów,Ordem da paleta tonemap,,Ordine paletă Tonemap,Порядок палитры тонового отображения,Тонирано-мапни палетни ред,Tonemappalettordning,Ton Haritası Palet Sırası,Порядок палітри тонального відображення, +Tonemap Palette Exponent,GLPREFMNU_PALTONEMAPPOWER,,,,Exponent palety tónovací mapy,Tonemap-palettens eksponent,Palettenexponent für Tonemap,,Exponeto de Kolormapo-Paletro,Exponente paleta en mapa de tonos,,Sävykartan paletin eksponentti,Exponent des palettes tonemap,Tonemap Paletta Exponens,Esponente della Palette Tonemap,トーンマップパレット指数,톤맵 팔레트 지수,Tonemap Palet Exponent,Tonemap Palette Eksponent,Wykładnik Palet Mapowania Tonów,Expoente da paleta tonemap,,Exponent paletă Tonemap,Экспонента палитры тонового отображения,Тонирано-мапни палетни експонент,Exponent för tonemappalett,Ton Haritası Paleti Üsteli,Експонента палітри тонального відображення, +Multisample,GLPREFMNU_MULTISAMPLE,,,,Multisampling,,Multisampling,,Plurspecimeno,Multisampling,,Moninäytteistys,,,,マルチサンプル,멀티샘플,,,Multipróbkowanie,Multiamostragem,,Multisampling,Мультисэмплинг,Мулти-узорак,,Çoklu Örneklem,Багатовибіркове згладжування, +Bloom effect,GLPREFMNU_BLOOM,,,,Efekt bloom,Bloom-effekt,Bloom Effekt,,Lumŝmiro-efiko,Efecto Bloom,,Hehkutehoste (bloom),Effet surbrillance,Bloom effekt,Effetto Bloom,ブルーム エフェクト,블룸 효과,Bloom-effect,Bloom-effekt,Effekt Bloom,Bloom,,Efect Bloom,Свечение,Мутан вид ефект,Bloom-effekt,Çiçeklenme etkisi,Ефект сяйва (Bloom), +Ambient occlusion quality,GLPREFMNU_SSAO,,,,Kvalita ambient occlusion,Omgivende okklusionskvalitet,Ambient Occlusion Qualität,,Kvaliteco de media obstrukceco,Calidad de oclusión ambiental,,Yleisvarjostuksen (ambient occlusion) laatu,Qualité Occlusion Ambiente,Ambient occlusion minősége,Qualità occlusione ambientale,アンビエント オクルージョンの品質,주변 환경 가림 효과 품질,Kwaliteit van omgevingsverduistering,Omgivende okklusjonskvalitet,Jakość okluzji otoczenia,Qualidade de oclusão de ambiente,,Calitate ocluzie ambientală,Качество глобального затенения,Оклузија амбијента ефект,Kvalitet för omgivande ocklusion,Ortam oklüzyon kalitesi,Якість імітації тіней, +Portals with AO,GLPREFMNU_SSAO_PORTALS,,,,Portály s AO,Portaler med AO,Portale mit AO,,Portaloj kun Media obstrukceco,Portales con OA,,Yleisvarjostuksen portaalit,OA pour les portails,Portálok AO-val,Portali con l'OA,AOを伴うポータル,주변 환경 가려진 포탈,Portals met AO,Portaler med AO,Portale z okluzją otoczenia,Portais com oclusão de ambiente,,Portaluri cu ocluzie ambientală,Порталы с глобальным затенением,Портали са AO,Portaler med omgivande ocklusion,AO'lu Portallar,Портали з глобальним затіненням, +Menu Blur,GLPREFMNU_MENUBLUR,,,,Rozostření pozadí v menu,Menu sløring,Menüunschärfe,Θόλοση μενού,Malklarigo de menuo ,Difuminación de menú,,Valikon sumennus,Flou menu,Menü mosódás,Blur del menu,メニューブラー,메뉴 흐림 효과,Menu vervagen,Meny uskarphet,Rozmycie w Menu,Desfoque do menu,Desfocagem do Menu,Neclaritate Meniu,Размытие фона меню,Блур мениа,Menyns oskärpa,Menü Bulanıklığı,Розмиття фону в меню, +Environment map on mirrors,GLPREFMNU_ENVIRONMENTMAPMIRROR,,,,Mapa prostředí na zrcadlech,Miljøkort på spejle,Lichteffekt auf Spiegeln,,Medimapo sur speguloj,Mapa de entorno en espejos,,Ympäristökartta peileissä,Mappage environment sur les miroirs,Környezet tükröződés,Ambiente mappa sugli specchi,マップオンミラーの画像表示,거울 주변의지도 활성,Milieukaart op spiegels,Omgivelseskart på speil,Mapa środowiska w lustrach,Mapa de ambiente em espelhos,,Efecte suplimentare pentru oglinzi,Карта окружения на зеркалах,Околинска мапа на прозорима,Miljökarta på speglar,Aynalar üzerinde çevre haritası,Карта оточення на дзеркалах, +Rendering quality,GLPREFMNU_RENDERQUALITY,,,,Kvalita vykreslování,Renderingskvalitet,Renderqualität,,Kvalito de bildigado,Calidad de renderizado,,Hahmonnuslaatu,Qualité du rendu,Renderelés minősége,Qualità resa grafica,レンダリング品質,렌더링 품질,Het teruggeven van kwaliteit,Renderingskvalitet,Jakość Renderowania,Qualidade de renderização,,Calitate video,Качество обработки,Квалитет рендовања,Renderingskvalitet,Render kalitesi,Якість візуалізації, +Speed,OPTVAL_SPEED,,,,Rychlost,Hastighed,Geschwindigkeit,Ταχύτητα,Rapido,Velocidad,,Nopeus,Vitesse,Sebesség,Prestazioni,速度寄り,성능,Snelheid,Hastighet,Szybkość,Velocidade,,Viteză,Скорость,Брзина,Hastighet,Hız,Швидкість, +Quality,OPTVAL_QUALITY,,,,Kvalita,Kvalitet,Qualität,Ποιότητα,Kvalito,Calidad,,Laatu,Qualité,Minőség,Qualità,品質寄り,고품질,Kwaliteit,Kvalitet,Jakość,Qualidade,,Calitate,Качество,Квалитет,Kvalitet,Kalite,Якість, +Sector light mode,GLPREFMNU_SECLIGHTMODE,,,,Režim osvětlení sektorů,Sektorlystilstand,Sektorlichtmodus,,Reĝimo de sektorlumo,Modo de luz de sector,,Sektorivalojen tila,Mode de lumière Secteur,Szektor fény mód,Modalità luce di settore,セクターライトモード,섹터 조명 모드,Sector lichte wijze,Sektorlysmodus,Tryb oświetlenia sektorów,Modo de luz de setor,,Mod iluminare sectorială,Режим освещения секторов,Секторско светло мод,Sektorljusläge,Sektör ışığı modu,Режим освітлення секторів, +Fog mode,GLPREFMNU_FOGMODE,,,,Režim mlhy,Tågetilstand,Nebelmodus,Λειτουργία ομίχλης,Reĝimo de nebulo,Modo de niebla,,Sumutila,Mode du broullard,Köd mód,Effetto nebbia,フォグモード,안개 모드,Mistmodus,Tåkemodus,Tryb mgły,Modo de neblina,,Mod ceață,Режим тумана,Магла мод,Dimläge,Sis modu,Режим туману, +Radial,OPTVAL_RADIAL,,,,Radiální,Radial,,Ακτινικό,Radiusa,,,Säteittäinen,,Sugaras,Radiale,放射状,방사형,Radiaal,,Promieniowe,,,Radială,Круговой,Радијално,,Radyal,Радіальний, +Standard,OPTVAL_STANDARD,,,,Standardní,,,,Norma,Estándar,,Normaali,,Szabvány,,標準,기본,Standaard,,,Padrão,,,Стандартный,Стандардно,,Standart,Стандартний, +,,Texture options,,,,,,,,,,,,,,,,,,,,,,,,,,, +Texture Filter mode,GLTEXMNU_TEXFILTER,,,,Režim filtrování textur,Tilstand for teksturfilter,Texturfiltermodus,,Reĝimo por Teksturfiltrado,Modo de filtro de texturas,,Pintakuviointien suodatustapa,Mode de Filtrage Texture,Textúrafilter módja,Modalità filtro texture,テクスチャーフィルター モード,텍스쳐 필터 모드,Textuurfiltermodus,Teksturfilter-modus,Tryb Filtrowania Tekstur,Modo de filtro de textura,,Mod Filtrare Texturi,Фильтрация текстур,Текстурни филтер мод,Texturfilterläge,Doku Filtresi modu,Тип фільтрації текстур, +Anisotropic filter,GLTEXMNU_ANISOTROPIC,,,,Anisotropické filtrování,Anisotropisk filter,Anisotropische Filterung,,Anizotropa filtro,Filtro anisotrópico,,Anisotrooppinen suodatus,Filtre Anisotropique,Anizotropikus filter,Filtro anisotropico,異方性フィルター,이방성 필터,Anisotroopfilter,Anisotropisk filter,Filtr anizotropowy,Filtro anisotrópico,,Filtrare Anizotropică,Анизотропная фильтрация,Анизотропни фолтер,Anisotropt filter,Anizotropik filtre,Анізотропна фільтрація, +None (nearest mipmap),OPTVAL_NONENEARESTMIPMAP,,,,Žádné (mipmapa - nejbližší soused),Ingen (nærmeste mipmap),Aus (nächste Mipmap),,Nenio (plej proksima mipmapo),Ninguno (mipmap cercano),,Ei mitään (lähin mipkartta),Aucun (mipmap proche voisin),Semmilyen (közeli mipmap),Nessuno (mipmap più vicina),なし(最寄りミップマップ),없음 (밉멥에 가까움),Geen (dichtstbijzijnde mipmap),Ingen (nærmeste mipmap),Brak (najbliższa mipmapa),Nenhum (mipmap mais próximo),,Niciuna (mipmap de apropriere),Нет (ближайший MIP-уровень),Ништа (најближи мипмап),Ingen (närmaste mipmap),Yok (en yakın mipmap),Відсутня (найближчий міпмап), +None (linear mipmap),OPTVAL_NONELINEARMIPMAP,,,,Žádné (mipmapa - lineární),Ingen (lineær mipmap),Aus (lineare Mipmap),,Nenio (linia mipmapo),Ninguno (mipmap lineal),,Ei mitään (lin. mipkartta),Aucun (mipmap linéaire),Semmilyen (lineáris mipmap),Nessuno (mipmap lineare),なし(リニアミップマップ),없음 (선형 밉맵),Geen (lineaire mipmap),Ingen (lineær mipmap),Brak (liniowa mipmapa),Nenhum (mipmap linear),,Niciuna (mipmap liniar),Нет (линейный MIP-уровень),Ништа (линеаран мипмап),Ingen (linjär mipmap),Yok (doğrusal mipmap),Відсутня (лінійний міпмап), +None (trilinear),OPTVAL_NONETRILINEAR,,,,Žádné (trilineární),Ingen (trilineær),Aus (trilinear),,Nenio (trilinia),Ninguno (trilineal),,Ei mitään (trilineaarinen),Aucun (mipmap trilinéaire),Semmilyen (trilineáris),Nessuno (mipmap trilineare),なし(トライリニア),없음 (삼선형),Geen (trilineair),Ingen (trilineær),Brak (trzyliniowe),Nenhum (trilinear),,Niciuna (trilinar),Нет (трилинейная),Ништа (трилинеарно),Ingen (trilinjär),Yok (trilineer),Відсутня (трилінійна), +Bilinear,OPTVAL_BILINEAR,,,,Bilineární,Bilineær,,,Dulinia,Bilineal,,Bilineaarinen,Bilinéaire,Bilineáris,Bilineare,バイリニア,쌍선형,Bilineair,Bilineær,Dwuliniowe,,,Biliniar,Билинейная,Билинеарно,Bilinjär,Bilineer,Білінійна, +Trilinear,OPTVAL_TRILINEAR,,,,Trilineární,Trilineær,,,Trilinia,Trilineal,,Trilineaarinen,Trilinéaire,Trilineáris,Trilineare,トライリニア,삼선형,Trilineair,Trilineær,Trzyliniowe,,,Triliniar,Трилинейная,Трилинеарно,Trilinjär,Trilineer,Трилінійна, +2x,OPTVAL_2X,,,,,,,,2-oble,,,,,,,,,,,,,,,,,,,, +4x,OPTVAL_4X,,,,,,,,4-oble,,,,,,,,,,,,,,,,,,,, +8x,OPTVAL_8X,,,,,,,,8-oble,,,,,,,,,,,,,,,,,,,, +16x,OPTVAL_16X,,,,,,,,16-oble,,,,,,,,,,,,,,,,,,,, +32x,OPTVAL_32X,,,,,,,,32-oble,,,,,,,,,,,,,,,,,,,, +Texture Options,GLTEXMNU_TITLE,,,,Nastavení textur,Indstillinger for teksturer,Texturoptionen,,Agordoj de Teksturoj,Opciones de texturas,,Pintakuviointiasetukset,Options Textures,Textúra Beállítások,Opzioni Texture,テクスチャー オプション,텍스쳐 설정,Textuur Opties,Teksturalternativer,Opcje Tekstur,Opções de Textura,,Setări Texturi,Настройки текстур,Подешавања текстура,Alternativ för textur,Doku Seçenekleri,Параметри текстур, +Textures enabled,GLTEXMNU_TEXENABLED,,,,Povolit textury,Teksturer aktiveret,Texturen an,,Teksturoj ŝaltitaj,Texturas activadas,,Pintakuvioinnit otettu käyttöön,Textures activées,Textúrák bekapcsolása,Texture abilitate,テクスチャー有効,텍스쳐 사용,Texturen ingeschakeld,Teksturer aktivert,Tekstury włączone,Texturas ativadas,,Texturi Activate,Включить текстуры,Текстуре омогућене,Texturer aktiverade,Dokular etkinleştirildi,Увімкнути текстури, +Enable hires textures,GLTEXMNU_ENABLEHIRES,,,,Povolit textury ve vysokém rozlišení,Aktivere hi-res teksturer,Hochauflösende Texturen an,,Ŝalti Altdistingivajn Teksturojn,Activar texturas de alta resolución,,Salli korkean erotuskyvyn pintakuvioinnit,Activer Textures haute résolution,Magas felbontású textúrák bekapcsolása,Abilita texture alta qualità,ハイレゾ テクスチャー有効,고해상도 텍스쳐 사용,Hoge-resolutie texturen op,Aktivere høyoppløselige teksturer,Włącz tekstury wysokiej jakości,Habilitar texturas de alta resolução,,Texturi de înaltă rezoluție,Текстуры высокого разрешения,Омогући текстуре велике резолуције,Aktivera texturer med högre upplösning,Yüksek çözünürlüklü dokuları etkinleştir,Увімкнути текстури високого розширення, +High Quality Resize mode,GLTEXMNU_HQRESIZE,,,,Režim zvětšovače textur,Tilstand til ændring af størrelse i høj kvalitet,Texturskalierungsmodus,,Reĝimo de Altdistingivigo-Skalilo,Modo de ajuste de alta calidad,,Korkealaatuinen kuvakoon muutostapa,Mise à l'échelle haute résolution,Magas minőségű újraméretező mód,Modalità resize alta qualità,高品質リサイズ モード,고퀄리티 리사이즈 모드,Textuurschaalmodus,Høy kvalitet Endre størrelse-modus,Tryb Wysokiej Jakości Zmieniania Rozmiaru,Modo de Redimensionamento de Alta Qualidade,,Mod Redimensionare de Înaltă Calitate,Режим высококачественного масштабирования текстур,Промена величине високог квалитета мод,Högkvalitativt storleksanpassningsläge,Yüksek Kalite Yeniden Boyutlandırma modu,Масштабування текстур, +High Quality Resize multiplier,GLTEXMNU_HQRESIZEMULT,,,,Faktor zvětšovače textur,Multiplikator for ændring af størrelse i høj kvalitet,Texturskaluerungsfaktor,,Obligilo de Altdistingivigo-Skalilo,Multiplicador de ajuste de alta calidad,,Korkealaatuisen kuvakokomuutoksen kerroin,Multiplicateur de mise à l'échelle,Magas minőségű újraméretezés szorzó,Moltiplicatore resize alta qualità,高品質リサイズ乗数,고퀄리티 리사이징 승수,Textuurschaalfactor,Multiplikator for størrelsesendring av høy kvalitet,Mnożnik Wysokiej Jakośći Rozmiaru,Multiplicador de Redimensionamento de Alta Qualidade,,Factor de Scalare,Множитель высококачественного масштабирования,Промена величине високог квалитета мултипликатор,Multiplikator för storleksändring av hög kvalitet,Yüksek Kalite Yeniden Boyutlandırma çarpanı,Множник масштабування, +This mode requires %d times more video memory,GLTEXMNU_HQRESIZEWARN,,,,Tento režim potřebuje %dkrát více paměti,Denne tilstand kræver %d gange mere videohukommelse,Dieser Modus benötigt das %d-fache an Videospeicher,Αυτή η λειτουργία χρειάζετε %d περισσότερες φορές μνήμη βίντεο,Ĉi tiu reĝimo bezonas %d-oble pli da ekranmemoro.,Este modo requiere %d veces más memoria de vídeo,,Tämä tila vaatii %d kertaa enemmän videomuistia,Ce mode nécessite %d fois plus de mémoire vidéo,Ez a mód a jelenlegi videó memória %d-szeresét igényli,Questa modalità richiede %d volte la memoria video,このモードでは %d 倍以上のビデオメモリが必要です!,이 설정은 비디오 메모리의 %d 배가 더 필요합니다.,Deze modus vereist %d keer meer videogeheugen.,Denne modusen krever %d ganger mer videominne,Ten tryb wymaga %d razy więcej pamięci wideo,Este modo precisa de %d vezes mais memória de vídeo,,Acest mod necesită de %d mai multă memorie video,Данный режим требует в %d раз больше видеопамяти,Овај мод тражи %d пута више видео меморије,Det här läget kräver %d gånger mer videominne,Bu mod %d kat daha fazla video belleği gerektirir,Цьому типу потрібно в %d рази більше відеопам'яті, +Resize textures,GLTEXMNU_RESIZETEX,,,,Škálovat textury,Ændre størrelse på teksturer,Texturen skalieren,,Regrandigi teksturojn,Ajustar texturas,,Muuta pintakuviointien kokoa,Mise à l'échelle textures,Textúrák újraméretezése,Resize delle texture,テクスチャー類のリサイズ,텍스쳐 리사이징,Texturen schalen,Endre størrelse på teksturer,Zmień rozmiar tekstur,Redimensionar texturas,,Redimensionare texturi,Масштабирование текстур,Промена величине текстура,Ändra storlek på texturer,Dokuları yeniden boyutlandırma,Масштабувати текстури, +Resize sprites,GLTEXMNU_RESIZESPR,,,,Škálovat sprity,Ændre størrelse på sprites,Sprites skalieren,,Regrandigi mov-rastrumojn,Ajustar sprites,,Muuta spritejen kokoa,Mise à l'échelle sprites,Sprite-ok újraméretezése,Resize degli sprite,スプライト類のリサイズ,스프라이트 리사이징,Sprites schalen,Endre størrelse på sprites,Zmień rozmiar sprite'ów,Redimensionar sprites,,Redimensionare sprite-uri,Масштабирование спрайтов,Промена величине спрајтова,Ändra storlek på sprites,Sprite'ları yeniden boyutlandırma,Масштабувати спрайти, +Resize fonts,GLTEXMNU_RESIZEFNT,,,,Škálovat fonty,Ændre størrelse på skrifttyper,Zeichensätze skalieren,,Regrandigi tiparojn,Ajustar fuentes,,Muuta kirjasinten kokoa,Mise à l'échelle texte,Betűk újraméretezése,Resize dei font,フォント類のリサイズ,폰트 리사이징,Lettertypen schalen,Endre størrelse på skrifter,Zmień rozmiar czcionek,Redimensionar fontes,,Redimensionare fonturi,Масштабирование шрифтов,Промена величине фонта,Ändra storlek på teckensnitt,Yazı tiplerini yeniden boyutlandırma,Масштабувати шрифти, +Resize model skins,GLTEXMNU_RESIZESKN,,,,Škálovat skiny modelů,Ændre størrelsen på modelskins,,,Regrandigi haŭtojn de modeloj,Ajustar texturas de modelo,,Muuta ulkoasujen kokoa,Mise à l'échelle des skins des modèles 3D,Model fazon újraméretezése,Ridimensiona skin modello,モデルスキン類のリサイズ,,,Endre størrelse på modellskinn,Zmień rozmiar modelu,Redimensionar skins de modelos,,Redimensionare modele,Масштабирование обликов моделей,,Ändra storlek på modellskinn,Model kaplamalarını yeniden boyutlandırma,Масштабувати текстури моделей, +Precache GL textures,GLTEXMNU_PRECACHETEX,,,,Přednačíst GL textury do cache,Precache GL-teksturer,GL Texturen zwischenspeichern,,Antaŭkaŝmemorigi GL-teksturojn,Precaché de texturas GL,,Kirjoita GL-pintakuvioinnit välimuistiin,Mise en cache des textures,Előcachelt GL textúrák,Precache texture GL,プリキャッシュGLテクスチャー,지엘 텍스쳐 미리 캐싱함,Precache GL texturen,Precache GL-teksturer,Tekstury GL pamięci podręcznej,Precachê de texturas GL,,Preîncărcarcă texturile GL,Кэшировать GL-текстуры,Прикеширане GL текстуре,Precache GL-texturer,GL dokularını önceden önbelleğe alma,Кешувати GL-текстури, +Video Mode,VIDMNU_TITLE,,,,Režim displeje,Videotilstand,Videomodus,Λειτουργία βίντεο,Video-reĝimo,Modos de vídeo,Modos de video,Videotila,Mode Vidéo,Videó mód,Modalità video,ビデオ調整,화면 설정,Videomodus,Videomodus,Tryb Wideo,Modo de vídeo,,Mod Video,Настройки видеорежима,Видео мод,Videoläge,Video Modu,Налаштування відеорежиму, +Scaled (Nearest),OPTVAL_SCALENEAREST,,,,Škálován (nejbližší),Skaleret (Nærmeste),Skaliert (nächster Nachbar),,Skalita (Plej proksime),Escalado (Lo más cerca),,Skaalattu (läheisin),Mis à l'échelle (Proche Voisin),Átméretezett (Közeli),Scalato (più vicino),スケーリング (最寄り),확대 (가깝게),Geschaald (Dichtstbijzijnd),Skalert (nærmeste),Przeskalowany (Najbliższy),Redimensionado (mais próximo),Redimensionado (Apróximado),Redimensionat (Cel mai aproape),Масштабировать (ближайшее),Скалиран (најближи),Skalad (närmast),Ölçeklendirilmiş (En Yakın),Збільшення (ближнє), +Scaled (Linear),OPTVAL_SCALELINEAR,,,,Škálován (lineární),Skaleret (lineær),Skaliert(linear),,Skalita (Linie),Escalado (Lineal),,Skaalattu (lineaarinen),Mis à l'échelle (Linéaire),Átméretezett (Lineáris),Scalato (lineare),スケーリング (リニア),확대 (선형 식),Geschaald (Lineair),Skalert (lineær),Przeskalowany (Liniowy),Redimensionado (linear),,Redimensionat (Liniar),Масштабировать (линейное),Скалиран (линеарно),Skalad (linjär),Ölçeklendirilmiş (Doğrusal),Збільшення (лінійне), +Letterbox,OPTVAL_LETTERBOX,,,,,,,,Leterkesto,Barras negras,,Mustat reunat,,Levágott,Bande nere,レターボックス,레터박스,,,,Barras pretas,,Ecran Parțial,Экранное каше,Поштанско сандуче,Brevlåda,,Техніка каше, +Stretch,OPTVAL_STRETCH,,,,Roztažený,Stræk,Strecken,,Streĉi,Estrechado,Estrecho,Venytetty,Etirer,Nyújtott,Disteso,伸縮,늘림,Rek,Strekk,Rozciągnięty,Esticado,,Lărgire,Растянутый,Растегнуто,Sträcka,Esneme,Розтягнутий, +Render Mode,VIDMNU_RENDERMODE,,,,Režim rendereru,Rendertilstand,Rendermodus,,Bildigo-reĝimo,Modo de renderizado,,Hahmonnustila,Mode de Rendu,Render Mód,Modalità rendering,レンダラー,렌더링 설정,Rendermodus,Gjengivelsesmodus,Tryb Renderowania,Modo de renderização,,Mod Video,Режим обработки,Рендер мод,Renderläge,İşleme Modu,Режим візуалізації, +Fullscreen,VIDMNU_FULLSCREEN,,,,Přes celou obrazovku,Fuld skærm,Vollbild,Πλήρης οθόνη,Plena ekrano,Pantalla completa,,Koko näyttö,Plein écran,Teljes Képernyő,Schermata piena,全画面,전체화면,Volledig scherm,Fullskjerm,Pełen Ekran,Tela cheia,Ecrã cheio,Ecran Complet,Полный экран,Цео екран,Fullskärm,Tam Ekran,Повноекранний, +Retina/HiDPI support,VIDMNU_HIDPI,,,,Podpora Retiny/HiDPI,Retina/HiDPI-understøttelse,Retina/HDPI-Unterstützung,,Retino/HiDPI subteno,Soporte para Retina/HiDPI,,Retina/HiDPI-tuki,Support Retina/HiDPI ,Retina/HiDPI támogatás,Supporto Retina/HiDPi,Retina/HiDPI サポート,망막/하이DPI 활성화,Retina / HiDPI-ondersteuning,Retina/HiDPI-støtte,Wsparcie Retina/HiDPI,Suporte para Retina/HiDPI,,Suport Retina/HiDPI,Поддержка Retina/HiDPI,Retina/HiDPI подршка,Retina/HiDPI-stöd,Retina/HiDPI desteği,Підтримка Retina/HiDPI, +Aspect ratio,VIDMNU_ASPECTRATIO,,,,Poměr stran,Aspektforhold,Seitenverhältnis,,Ekran-proporcio,Relación de aspecto,,Kuvasuhde,Rapport D'Aspect,Képarány,Proporzioni,アスペクト比,종횡비,Beeldverhouding,Bildeforhold,Wpółczynnik proporcji,Proporção de tela,Proporção de ecrã,Aspect Imagine,Соотношение сторон,Однос гледишта,Bildförhållande,En boy oranı,Співвідношення сторін, +Force aspect ratio,VIDMNU_FORCEASPECT,,,,Vynutit poměr stran,Tvinge formatforhold,Erzwinge Seitenverhältnis,,Devigi ekran-proporcion,Forzar relación de aspecto,,Pakota kuvasuhde,Forcer Rapport,Képarány kényszerítése,Forza le proporzioni video,アスペクト比に従う,강제 종횡비,Geforceerde beeldverhouding,Tving sideforhold,Wymuś współczynnik proporcji,Forçar proporção de tela,Forçar proporcção de ecrã,Forțează aspectul imaginii,Принудительное соотношение сторон,Присили однос гледишта,Forcerat bildförhållande,Kuvvet en-boy oranı,Примусове співвідношення сторін, +Forced ratio style,VIDMNU_CROPASPECT,,,,Vynucený poměr stran,Stil med tvunget forhold,Modus für erzwungenes Seitenverhältnis,,Stilo por devigita proporcio,Relación de aspecto forzada,,Kuvasuhteen pakotustapa,Style de Ratio forcé,Kényszerített képarány stílusa,Forza lo stile delle proporzioni,比率の形式,강제 비율 스타일,Geforceerde verhoudingsstijl,Tvunget formatforhold-stil,Wymuszony styl współczynnika,Estilo de proporção forçado,,Forțează tipul proporțiilor,Тип принудительного соотношения сторон,Присиљен стил односа,Stil för tvingat förhållande,Zorlanmış oran stili,Тип примусового співвідношення сторін, +Enable 5:4 aspect ratio,VIDMNU_5X4ASPECTRATIO,,,,Povolit poměr stran 5:4,Aktiver 5:4-billedformat,Erlaube 5:4 Seitenverhältnis,,Ŝalti 5:4 ekran-proporcion,Activar relación de aspecto 5:4,,Ota käyttöön 5:4-kuvasuhde,Activer Rapport 5:4,5:4 képarány engedélyezése,Abilita le proporzioni 5:4,5:4アスペクト比を可能にする,5:4 비율 사용,Schakel 5:4 beeldverhouding in,Aktiver 5:4 sideforhold,Włącz współczynnik proporcji 5:4,Ativar proporção de tela 5:4,,Activează formatul 5:4,Включить соотношение сторон 5:4,Омогући 5:4 однос гледишта,Aktivera bildförhållandet 5:4,5:4 en boy oranını etkinleştirin,Увімкнути співвідношення сторін 5:4, +Resolution scale,VIDMNU_SCALEMODE,,,,Škálování rozlišení,Opløsningsskala,Skalierung,,Distingivo-skalo,Escala de resolución,,Resoluution skaalaus,Echelle de Résolution,Felbontás mérete,Scala di risoluzione,画面スケール,해상도 크기,Resolutieschaal,Oppløsningsskala,Skala rozdzielczości,Escala de resolução,,Scară rezoluție,Масштабирование,Резолуцијска скала,Upplösningsskala,Çözünürlük ölçeği,Масштабування, +Scale Factor,VIDMNU_SCALEFACTOR,,,,Faktor rozlišení,Skalafaktor,Skalierungsfaktor,,Skalfaktoro,Factor de escala,,Skaalauskerroin,Facteur d'échelle,Méretezési Faktor,Fattore di scala,スケール倍率,축척 펙터,Schaalfactor,Skaleringsfaktor,Współczynnik Skali,Fator de escala,,Factor Scalare,Значение масштаба,Фактор скалирања,Skalfaktor,Ölçek Faktörü,Значення масштабування, +Use Linear Scaling (Fullscreen),VIDMNU_USELINEAR,,,,Použít lineární škálování (přes celou obrazovku),Brug lineær skalering (fuld skærm),Lineare Skalierung (Vollbild),,Uzi linian skaladon (Plenekrane),Usar escalado linear (Pant. completa),,Lineaarinen skaalaus (koko näyttö),Mise à l'échelle Linéaire (Plein écran),Lineáris Méretezés Használata (Teljes képernyő),Usa lo scaling lineare (a schermo pieno),リニアスケールを使う(全画面),선형 스케일링 사용 (전체화면),Lineaire schaalverdeling gebruiken (volledig scherm),Bruk lineær skalering (fullskjerm),Użyj Liniowego Skalowania (Pełen Ekran),Usar escala linear (tela cheia),Usar escala linear (ecrã cheio),Folosește Scalarea Liniară (Ecran Complet),Линейное масштабирование (полный экран),Користи линеарно скалирање (цео екран),Använd linjär skalning (helskärm),Doğrusal Ölçeklemeyi Kullan (Tam Ekran),Лінійне масштабування (повний екран), +Custom Pixel Scaling,VIDMNU_CUSTOMRES,,,,Vlastní škálování pixelů,Brugerdefineret pixelskalering,Benutzerdefinierte Skalierung,,Adaptita rastrumero-skalo,Escalado de píxel personalizado,,Mukautettu skaalaus,Résolution Personalisée,Egyéni Pixelméretezés,Scaling dei pixel personalizzato,カスタム ピクセルスケール,사용자 지정 픽셀 크기 조정,Aangepaste pixelschaalvergroting,Egendefinert pikselskalering,Niestandardowe Skalowanie Pikseli,Escala de pixels personalizada,,Scară Pixeli Personalizată,Масштабирование пикселей,Пиксел скалирање,Anpassad pixelskalning,Özel Piksel Ölçeklendirme,Масштабування пікселів, +Custom Width,VIDMNU_CUSTOMX,,,,Vlastní šířka,Brugerdefineret bredde,Benutzerdefinierte Breite,,Adaptita larĝeco,Ancho personalizado,,Mukautettu leveys,Largeur Personalisée,Egyéni szélesség,Lunghezza,カスタム 幅,사용자 지정 너비,Aangepaste breedte,Egendefinert bredde,Niestandardowa Szerokość,Largura personalizada,,Lățime Personalizată,Длина,Ширина,Anpassad bredd,Özel Genişlik,Довжина, +Custom Height,VIDMNU_CUSTOMY,,,,Vlastní výška,Brugerdefineret højde,Benutzerdefinierte Höhe,,Adaptita alteco,Alto personalizado,,Mukautettu korkeus,Hauteur Personalisée,Egyéni magasság,Altezza,カスタム 高さ,사용자 지정 높이,Aangepaste hoogte,Egendefinert høyde,Niestandardowa Wysokość,Altura personalizada,,Înălțime Personalizată,Высота,Висина,Anpassad höjd,Özel Yükseklik,Висота, +Apply Changes (Windowed),VIDMNU_APPLYW,,,,Použít změny (v okně),Anvend ændringer (vindue),Änderungen anwenden (Fenster),,Apliki ŝanĝojn (Fenestrite),Aplicar cambios (Ventana),,Ota käyttöön muutokset (ikkuna),Appliquer Changements (Fenêtre),Változtatások Elfogadása (Ablak),Applica le modifiche (a finestra),変更を適用(ウィンドウ化),변경 적용 (윈도우),Wijzigingen toepassen (in venster),Bruk endringer (vindusbasert),Zatwierdź Zmiany (Okno),Aplicar alterações (janela),,Aplică Schimbările (Mod Fereastră),Сохранить изменения (оконный режим),Примени промене (прозор),Tillämpa ändringarna (fönsterskärm),Değişiklikleri Uygula (Pencereli),Зберегти зміни (віконний режим), +Apply Changes (Fullscreen),VIDMNU_APPLYFS,,,,Použít změny (přes celou obrazovku),Anvend ændringer (fuld skærm),Änderungen anwenden (Vollbild),,Apliki ŝanĝojn (Plenekrane),Aplicar cambios (Pant. completa),,Ota käyttöön muutokset (koko näyttö),Appliquer Changements (Plein écran),Változtatások Elfogadása (Teljes képernyő),Applica le modifiche (a schermo pieno),変更を適用(全画面化),변경 적용 (전체화면),Wijzigingen toepassen (Volledig scherm),Bruk endringer (fullskjerm),Zatwierdź Zmiany (Pełen Ekran),Aplicar alterações (tela cheia),Aplicar alterações (ecrã cheio),Aplică Schimbările (Mod Ecran Complet),Сохранить изменения (полный экран),Примени промене (цели екран),Tillämpa ändringar (helskärm),Değişiklikleri Uygula (Tam Ekran),Зберегти зміни (повноекранний режим), +Choose Resolution Preset,VIDMNU_RESPRESET,,,,Vybrat přednastavené rozlišení,Vælg forindstillet opløsning,Auflösungsvoreinstellung,,Elekti antaŭagorditan distingivon,Elegir resolución predefinida,,Valitse ennalta määritetty resoluutio,Choisir paramètre personalisé,Felbontási Sablon Kiválasztása,Scegli preset di risoluzione,解像度プリセットを選ぶ,해상도 사전 설정 선택,Kies een vooraf ingestelde resolutie,Velg forhåndsinnstilt oppløsning,Wybierz Zestaw Rozdzielczości,Escolher resolução predefinida,,Alege Rezoluția Predefinită,Выбор шаблона разрешения,Резолуцијска подешавања,Välj förinställning för upplösning,Çözünürlük Ön Ayarını Seçin,Вибір пресету роздільної здатності, +Custom Resolution Presets,VIDMNU_RESPRESETTTL,,,,Vlastní přednastavení rozlišení,Brugerdefinerede opløsningsforudindstillinger,Benutzerdefinierte Auflösungsvoreinstellungen,,Viaj antaŭagorditaj distingivoj,Resoluciones predefinidas personalizadas,,Ennalta määritetyt mukautetut resoluutiot,Résolutions Personalisée,Egyéni Felbontási Sablonok,Preset di risoluzione personalizzati,カスタム解像度プリセット,사용자 지정 해상도 미리 조정,Vooraf ingestelde aangepaste resoluties,Egendefinerte forhåndsinnstillinger for oppløsning,Niestandardowe Zestawy Rozdzielczości,Predefinições de resolução personalizadas,,Rezoluții Personalizate,Пользовательские шаблоны,Резолуцијска подешавања,Anpassade förinställningar för upplösning,Özel Çözünürlük Ön Ayarları,Користувацькі пресети, +Preset Resolution Modes,VIDMNU_RESPRESETHEAD,,,,Přednastavená rozlišení,Forindstillede opløsningsmodes,Vordefinierte Auflösungsmodi,,Reĝimoj pri antaŭagordita distingivo,Modos de resolución predefinida,,Ennalta määritetyt resoluutiotilat,Choisir mode de Résolution,Felbontási Sablon Módok,Modalità preset di risoluzione,解像度モードの調整,해상도 미리 조정 모드,Vooraf ingestelde resolutiemodi,Forhåndsinnstilte oppløsningsmoduser,Tryby Zestawów Rozdzielczości,Modos de resolução predefinidas,,Rezoluții Predefinite,Доступные разрешения,Постављени резолуцијски модови,Förinställda upplösningslägen,Önceden Ayarlanmış Çözünürlük Modları,Доступні роздільні здатності, +4:3 Aspect,VIDMNU_ASPECT43,,,,Poměr stran 4:3,4:3 Aspekt,4:3 Seitenverhältnis,,4:3 proporcio,Aspecto 4:3,,4:3-tilat,Rapport 4:3,4:3 Arány,Aspetto 4:3,アスペクト比 4:3,4:3 비율,Beeldverhouding 4:3,4:3 Aspekt,Proporcje 4:3,Proporção 4:3,,Aspect 4:3,Соотношение сторон 4:3,4:3 гледиште,4:3 aspekt,4:3 Görüntü,Співвідношення сторін 4:3, +5:4 Aspect,VIDMNU_ASPECT54,,,,Poměr stran 5:4,5:4 Aspekt,5:4 Seitenverhältnis,,5:4 proporcio,Aspecto 5:4,,5:4-tilat,Rapport 5:4,5:4 Arány,Aspetto 5:4,アスペクト比 5:4,5:4 비율,Beeldverhouding 5:4,5:4 Aspekt,Proporcje 5:4,Proporção 5:4,,Aspect 5:4,Соотношение сторон 5:4,5:4 гледиште,5:4 Aspekt,5:4 Görüntü,Співвідношення сторін 5:4, +16:9 Aspect,VIDMNU_ASPECT169,,,,Poměr stran 16:9,16:9 Aspekt,16:9 Seitenverhältnis,,16:9 proporcio,Aspecto 16:9,,16:9-tilat,Rapport 16:9,16:9 Arány,Aspetto 16:9,アスペクト比 16:9,16:9 비율,Beeldverhouding 16:9,16:9 Aspekt,Proporcje 16:9,Proporção 16:9,,Aspect 16:9,Соотношение сторон 16:9,16:9 гледиште,16:9 aspekt,16:9 Görüntü,Співвідношення сторін 16:9, +16:10 Aspect,VIDMNU_ASPECT1610,,,,Poměr stran 16:10,16:10 Aspekt,16.10 Seitenverhältnis,,16:10 proporcio,Aspecto 16:10,,16:10-tilat,Rapport 16:10,16:10 Arány,Aspetto 16:10,アスペクト比 16:10,16:10 비율,Beeldverhouding 16:10,16:10 Aspekt,Proporcje 16:10,Proporção 16:10,,Aspect 16:10,Соотношение сторон 16:10,16:10 гледиште,16:10 aspekt,16:10 Aspect,Співвідношення сторін 16:10, +21:9 Aspect,VIDMNU_ASPECT219,,,,Poměr stran 21:9,21:9 Aspekt,21.9 Seitenverhältnis,,21:9 proporcio,Aspecto 21:9,,21:9-tilat,Rapport 21:9,21:9 Arány,Aspetto 21:9,アスペクト比 21:9,21:9 비율,Beeldverhouding 21:9,21:9 Aspekt,Proporcje 21:9,Proporção 21:9,,Aspect 21:9,Соотношение сторон 21:9,21:9 гледиште,21:9 Aspekt,21:9 Görüntü,Співвідношення сторін 21:9, +Normal,OPTVAL_NORMAL,,,,Normální,,,,Normala,,,Normaali,,Normál,Normale,通常,기본형,Normaal,,Normalny,,,,Обычный,Нормално,Normal,,Нормальний, +Lowest Possible Scale,OPTVAL_LOWEST,"This describes vid_scalemode 1, which represents the lowest possible scaling to fill the allocated screen area",,,Nejmenší možná velikost,Lavest mulige skala,Kleinstmögliche Auflösung,,Plej malalta ebla skalo,Menor escala posible,,Pienin mahdollinen skaalaus,Echelle la plus faible,Lehető legkisebb méret,Scala minima,可能な限り最小,,Laagst mogelijk schaal,Lavest mulig skala,Najniższa możliwa skala,Menor escala possível,,Cea mai Mică Scară Posibilă,Наименьший возможный масштаб,,Lägsta möjliga skala,Mümkün Olan En Düşük Ölçek,Найменш можливий масштаб, +Custom,OPTVAL_CUSTOM,,,,Vlastní,Brugerdefineret,Benutzerdefiniert,,Agordita de vi,Personalizado,,Mukautettu,Modifié,Egyéni,Personalizzato,カスタム,사용자 지정,Gebruikergedefinieerd,Egendefinert,Niestandardowe,Personalizado,,Personalizat,Польз.,Прилагођ.,Anpassad,Özel,Корист., +Max FPS,VIDMNU_MAXFPS,,,,Maximální FPS,,,,Maksimumaj kadroj laŭ sekundo,Límite de FPS,,Kuvataajuuden rajoitin,,,FPS Massimi,最大FPS値,,,Maks FPS,Maksymalna ilość klatek,FPS máximo,,Cadre pe secundă,Максимальная частота кадров,,,Maksimum FPS,Макс. частота кадрів, +60 fps,OPTVAL_60FPS,,,,,,,,,,,60 kuvaa/s,,,,,,,,,60 FPS,,,60 к/с,,,,60 кадрів, +75 fps,OPTVAL_75FPS,,,,,,,,,,,75 kuvaa/s,,,,,,,,,75 FPS,,,75 к/с,,,,75 кадрів, +90 fps,OPTVAL_90FPS,,,,,,,,,,,90 kuvaa/s,,,,,,,,,90 FPS,,,90 к/с,,,,90 кадрів, +120 fps,OPTVAL_120FPS,,,,,,,,,,,120 kuvaa/s,,,,,,,,,120 FPS,,,120 к/с,,,,120 кадрів, +144 fps,OPTVAL_144FPS,,,,,,,,,,,144 kuvaa/s,,,,,,,,,144 FPS,,,144 к/с,,,,144 кадри, +200 fps,OPTVAL_200FPS,,,,,,,,,,,200 kuvaa/s,,,,,,,,,200 FPS,,,200 к/с,,,,200 кадрів, +Preferred Rendering API,VIDMNU_PREFERBACKEND,,,,Upřednostňované renderovací API,Foretrukken Rendering API,Bevorzugtes Render API,Προτιμούμενο Rendering API,Preferita bildigado de API,API de renderizado preferida,,Ensisijainen hahmonnuksen ohjelmointirajapinta,API de rendu préférée,Előnyben részesített renderelő API,API di rendering preferita,優先レンダリングAPI,기본적인 API 랜더링,Voorkeur rendering API,Foretrukket Rendering API,Preferowany interfejs API renderowania,API de renderização preferida,,API Video Preferat,Предпочтительный API обработки,Преферред АПИ приказивања,Företrädesvis API för rendering,Tercih Edilen Rendering API,Бажаний інтерфейс візуалізації, +OpenGL,OPTVAL_OPENGL,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Vulkan,OPTVAL_VULKAN,,,,,,,,,,,,,,,,,,,,,,,,,,,, +OpenGL ES,OPTVAL_OPENGLES,Rendering backend,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,Miscellaneous Options,,,,,,,,,,,,,,,,,,,,,,,,,,, +Merge left+right Alt/Ctrl/Shift,MISCMNU_MERGEKEYS,,,,Kombinovat pravý a levý Alt/Ctrl/Shift,Flette venstre+højre Alt/Ctrl/Shift,Linke und rechte Umschalt/Strg/Alt zusammenfassen,,Kunigi maldekstran kaj dekstran Alt/Ctrl/Shift,Combinar Alt/Ctrl/Mayús izq. y der.,Combinar Alt/Ctrl/Shift izq. y der.,Yhdistä vasen ja oikea Alt/Ctrl/Vaihto,Combiner Alt/Ctrl/maj gauche & droite,Bal és jobb Ctrl/Alt/Shift egyként érzékelése,Unisci sinistra+destra Alt/Control/Maiusc,左と右のALT/CTRL/SHIFTキーを統合,양쪽 ALT/CTRL/SHIFT키 합병,Samenvoegen links+rechts Alt/Ctrl/Shift,Slå sammen venstre+høyre Alt/Ctrl/Shift,Połącz przyciski lewo+prawo Alt/Ctrl/Shift,"Unir as teclas Alt, Ctrl e Shift esquerdos e direitos",Juntar Alt/Ctrl/Shift esquerdo+direito,Combină Alt/Ctrl/Shift stâng+drept,Не различать левую/правую ALT/CTRL/SHIFT,Споји лево+десно Аlt/Ctrl/Shift,Sammanfoga vänster+höger Alt/Ctrl/Shift,Sol+sağ birleştirme Alt/Ctrl/Shift,Не розділяти лівий/правий ALT/CTRL/SHIFT, +Alt-Enter toggles fullscreen,MISCMNU_WINFULLSCREENTOGGLE,,,,Alt-Enter přepíná celou obrazovku,Alt-Enter skifter til fuld skærm,Alt-Enter schaltet Vollbild an/aus,,Alt+Enter baskuligas tutekranan reĝimon,Alt+Enter alterna pantalla completa,,Alt-Enter kytkee täyden ruudun päälle/pois,Alt-Entrée alterne plein écran,Alt-Enter teljes képernyőre kapcsol,Alt-Invio attiva/disattiva lo schermo pieno,ALTとENTERで全画面に切り替え,ALT+ENTER키로 전체화면 조정,Alt-Enter schakelt het volledige scherm aan/uit,Alt-Enter veksler til fullskjerm,Alt-Enter przełącza na pełen ekran,Alt+Enter ativa tela cheia,Alt-Enter ativa ecrã cheio,Alt-Enter comută modul ecran complet,Переключение полного экрана по ALT+ENTER,Alt-Enter пребацује на цео екран,Alt-Enter växlar till fullskärm,Alt-Enter tam ekrana geçiş yapar,Перемикання повного екрану на ALT+ENTER, +Command-F toggles fullscreen,MISCMNU_MACFULLSCREENTOGGLE,,,,Command-F přepíná celou obrazovku,Command-F skifter til fuld skærm,Cmd-F schaltet Vollbild an/aus,,Komando-F baskuligas tutekranan reĝimon,Cmd-F alterna pantalla completa,,Komento-F kytkee täyden ruudun päälle/pois,Command-F alterne plein écran,Command-F teljes képernyőre kapcsol,Command-F attiva/disattiva lo schermo pieno,Ctrl + Fキーで全画面表示,COMMAND+F키로 전체화면 조정,Command-F schakelt het volledige scherm aan/uit,Kommando-F veksler til fullskjerm,Command-F przełącza pełny ekran,Command+F ativa tela cheia,Command-F ativa ecrã cheio,Command-F comută modul ecran complet,Переключение полного экрана по Cmd+F,Command-F пребацује на цео екран,Command-F växlar till fullskärm,Command-F tam ekrana geçiş yapar,Перемикання повного екрану на Command+F, +Enable autosaves,MISCMNU_ENABLEAUTOSAVES,,,,Povolit automatické ukládání,Aktiver autosaves,Automatisches Speichern,,Ŝalti aŭtomatajn konservojn de ludadoj,Activar autoguardado,,Ota käyttöön automaattiset tallennukset,Activer Sauvegardes auto,Automentések engedélyezése,Abilita i salvataggi automatici,オートセーブを有効化,빠른 저장 허용,Automatisch opslaan inschakelen,Aktiver automatisk lagring,Włącz autozapis,Ativar salvamento automático,Permitir gravação automática,Permite salvări automate,Автосохранения,Омогући аутосејвове,Aktivera autosparande,Otomatik kaydetmeyi etkinleştir,Автозбереження, +Number of autosaves,MISCMNU_AUTOSAVECOUNT,,,,Počet automaticky uložených her,Antal autosaves,Anzahl von automatischen Speicherständen,,Maksimuma kvanto da aŭtomataj konservoj,Cantidad máxima de autoguardados,,Automaattisten tallennusten lukumäärä,Total de sauvegardes auto,Automentések száma,Numero di salvataggi automatici,オートセーブの最大数,빠른 저장 수,Aantal auto-opslagen,Antall autolagringer,Liczba autozapisów,Número de salvamentos automáticos,Número de gravações automáticas,Număr salvări automate,Количество автосохранений,Број аутоматских чувања,Antal autosparande,Otomatik kaydetme sayısı,Кількість автозбрежень, +Save/Load confirmation,MISCMNU_SAVELOADCONFIRMATION,,,,Potvrzení o uložení/načtení,Bekræftelse af gem/indlæsning,Laden/Speichern bestätigen,,Konfirmo de konservo/ŝargo,Confirmación al guardar/cargar,,Tallennuksen/Latauksen vahvistus,Confirmation C/S,Mentés/betöltés megerősítése,Conferma Salvataggio/Caricamento,セーブ/ロード時に確認,스크립트로 스크린샷 생성 허용,Opslaan/Laad bevestiging,Bekreftelse for lagring/innlasting,Potwierdzenie zapisu/wczytania,Confirmação ao salvar/carregar,Confirmação ao gravar/carregar,Dialog de confirmare la Salvare/Încărcare,Подтверждение при сохранении/загрузке,Потврђивање током чувања/учитавања,Bekräftelse av sparande/laddning,Kaydet/Yükle onayı,Підтвердження при збереженні/завантаженні, +Disable keyboard cheats,MISCMNU_NOCHEATS,,,,Vypnout cheaty z klávesnice,Deaktivere snyderier med tastaturet,Tastatur-Cheats deaktivieren,,Malvalidigi klavarajn trompojn,Desactivar trucos por teclado,,Poista näppäinhuijaukset,Déasctiver les codes de triche au clavier,Billentyűs csalások letiltása,Disabilita i trucchi classici,キーボードからのチート無効,,Schakel cheats uit,Deaktiver tastaturjuks,Wyłącz Oszustwa z Klawiatury,Desativar trapaças de teclado,,Dezactivează codurile din tastatură,Отключить клавиатурные чит-коды,,Inaktivera fusk med tangentbordet,Klavye hilelerini devre dışı bırak,Вимкнути клавіатурні чіт-коди, +Quicksave rotation,MISCMNU_QUICKSAVEROTATION,,,,Rotace rychle uložených her,Quicksave-rotation,Schnellspeicherrotation,,Rotacio de rapidkonservo,Rotación al hacer un guardado rápido,,Pikatallennuskierto,Rotation Sauvegardes Rapides,Gyorsmentés forgás,Rotazione del quicksave,クイックセーブ間隔,빠른 저장 간격,Rouleer snelopslag,Hurtiglagring-rotasjon,Rotacja szybkich zapisów,Rotação de salvamentos rápidos,Rotação de gravações rápidas,Rotație salvări automate,Менять ячейки для быстрых сохранений,Окретање брзих чувања,Rotation av snabbregistrering,Hızlı kaydetme rotasyonu,Чергування слотів швидких збережень, +Number of quicksaves in rotation,MISCMNU_QUICKSAVECOUNT,,,,Počet rychle uložených her v rotaci,Antal quicksaves i rotation,Anzahl Schnellspeicherplätze,,Kvanto da rapidkonservoj en rotaciado,Cantidad de guardados rápidos en rotación,,Pikatallennusten määrä kierrossa,Nombre de sauvegardes en rotation,Gyorsmentések száma a forgásban,Numero di quicksave in rotazione,間隔クイックセーブの数,빠른 저장 간격의 수,Aantal roulerende snelopslagplekken,Antall hurtiglagringer i rotasjon,Ilość szybkich zapisów w rotacji,Número de salvamentos rápidos em rotação,Número de gravações rápidas em rotação,Număr salvări rapide în rotație,Кол-во ячеек для быстрых сохранений,Број брзих чувања у окретању,Antal quicksaves i rotation,Rotasyondaki quicksave sayısı,Кількість слотів для швидких збережень, +Disable Menu Clean Scaling,MISCMNU_CLEANMENU,,,,Zakázat čisté škálování nabídek,Deaktivere Menu Clean Scaling,Gleichmäßige Menüskalierung deaktivieren,,Malebligi puran skaladon en la ĉefmenuo,El menú principal ocupa toda la pantalla,,Poista käytöstä valikon siisti skaalautuminen,Ne pas utilisé mise à l'échelle menu propre,Menü Tisztaarányítás kikapcsolása,Disabilita il fattore di scala pulito del menu,メニュー画面を伸縮させない,,Schakel uniforme menuschaling uit,Deaktiver ren skalering av meny,Wyłącz Skalowanie Menu,Desativar escala limpa do menu,,Dezactivează Scara Nouă a Meniurilor,Отключить чистое масштабирование меню,,Inaktivera ren menyskalning,Menü Temiz Ölçeklendirmeyi Devre Dışı Bırak,Вимкнути чисте масштабування меню, +Pause game in background,MISCMNU_PAUSEINBACKGROUND,,,,Pozastavit hru na pozadí,Pause spil i baggrunden,Spiel pausieren wenn im Hintergrund,,Paŭzigi ludon fone,Pausar el juego en segundo plano,,Pysäytä peli taustalla,Mettre le jeu en pause en arrière-plan,Játék megállítása a háttérben,Pausa il gioco in background,バックグラウンド時に一時停止,백그라운드에서 게임 일시 중지,Pauzeer het spel op de achtergrond,Pauser spillet i bakgrunnen,Zapauzuj grę w tle,Pausar jogo ao minimizar,,Pauză dacă jocul este minimizat.,Пауза при сворачивании окна,Паузирајте игру у позадини,Pausa spelet i bakgrunden,Oyunu arka planda duraklat,Пауза при згортуванні вікна, +Default Crosshair,HUDMNU_CROSSHAIR,,,,Výchozí zaměřovač,Standardtrådkorset,Standard-Fadenkreuz,,Defaŭlta reteto,Retícula por defecto,,Oletustähtäin,Viseur par défaut,Alap célkereszt,Mirino di default,デフォルトの照準,기본 조준점,Standaard dradenkruis,Standard trådkors,Domyślny celownik,Mira padrão,,Țintă implicită,Прицел по умолчанию,Уобичајени нишан,Standardkorshår,Varsayılan Nişangah,Типи прицілів, +Crosshair color,HUDMNU_CROSSHAIRCOLOR,,,Crosshair colour,Barva zaměřovače,Trådkors farve,Fadenkreuzfarbe,,Retetokoloro,Color de la retícula,,Tähtäimen väri,Couleur Viseur,Célkereszt színe,Colore mirino,照準色,조준점 색깔,Dradenkruis kleur,Farge på trådkors,Kolor celownika,Cor da mira,,Culoare țintă,Цвет прицела,Боја нишана,Färg på hårkorset,Nişangah rengi,Колір прицілу, +Crosshair shows health,HUDMNU_CROSSHAIRHEALTH,,,,Zaměřovač zobrazuje zdraví,Trådkors viser helbred,Fadenkreuz zeigt Gesundheit,,Reteto montras sanon,Mostrar salud en retícula,,Tähtäin näyttää terveyden,Couleur Viseur selon santé,Életerő jelzése a célkereszten,Il mirino mostra la salute,照準のヘルス表示,조준점과 체력 연동,Dradenkruis toont gezondheid,Trådkorset viser helse,Celownik pokazuje zdrowie,Exibir saúde na mira,Mostra vida na mira,Ținta afișează starea sănătății,Прицел отображает здоровье,Нишан приказује здравље,Hårkorset visar hälsa,Artı işareti sağlığı gösterir,Колір прицілу за станом здоров'я, +Scale crosshair,HUDMNU_CROSSHAIRSCALE,,,,Velikost zaměřovače,Skalerer trådkorset,Fadenkreuz skalieren,,Skali reteton,Escalar retícula,,Skaalaa tähtäintä,Mise à l'échelle du viseur,Célkereszt mérete,Fattore di scala del mirino,照準サイズ,조준점 크기,Dradenkruis schalen,Skalere trådkors,Skala celownika,Redimensionar mira,,Dimensiune țintă,Размер прицела,Размера нишана,Skala hårkorset,Ölçekli artı işareti,Розмір прицілу, +Standard,OPTVAL_YES_STANDARD,copied from elsewhere,,,Standardní,,,Πρότυπο,Norma,Estándar,,Normaali,,Alap,,標準,기본,Standaard,,,Padrão,,,Стандартный,Стандардни,,Standart,Стандартний, +Enhanced,OPTVAL_YES_ENHANCED,,,,Vylepšené,Forbedret,Verbessert,Ενισχυομένο,Bonigita,Mejorado,,Paranneltu,Amélioré,Fejlesztett,Migliorata,強調,고급,Verbeterd,Forbedret,Ulepszone,Melhorado,,Îmbunătățită,Улучшенный,Побољшани,Förbättrad,Geliştirilmiş,Покращений, +Language,OPTMNU_LANGUAGE,,,,Jazyk,Sprog,Sprache,Γλώσσα,Lingvo,Idioma,,Kieli,Langage,Nyelv,Lingua,言語設定,언어,Taal,Språk,Język,Idioma,,Limbă,Язык,Језик,Språk,Dil,Мова, +,,Reverb editor,,,,,,,,,,,,,,,,,,,,,,,,,,, +Undo Changes,TXT_UNDOCHANGES,,,,Zrušit změny,Fortryd ændringer,Rückgängig machen,Αναίρεση Αλλαγών,Malfari ŝanĝojn,Anular cambios,,Peruuttaa muutokset,Révoquer les changements,Változtatások Visszavonása,Revocare le modifiche,変更を戻す,변경 사항 취소,Wijzigingen ongedaan maken,Angre endringer,Cofnij Zmiany,Desfazer alterações,,Anulează Modificările,Отменить изменения,Поништи промене,Ångra ändringar,Değişiklikleri Geri Al,Відмінити зміни, +Select Environment,REVMNU_SELECT,,,,Vybrat prostředí,Vælg miljø,Umgebung wählen,Επιλογή Περιβάλλοντος,Elekti medion,Seleccionar ambiente,,Valitse tila,Sélectionner un environnement,Környezet Kiválasztása,Seleziona ambiente,反響選択,환경 선택,Selecteer omgeving,Velg miljø,Wybierz Środowisko,Selecione o ambiente,,Alegere Mediu,Выбрать окружение,Изабери окружење,Välj miljö,Ortam Seçiniz,Вибрати оточення, +Test Environment,REVMNU_TEST,,,,Testovat prostředí,Test miljø,Umgebung testen,Δοκιμαστκό Περιβάλλον,Provi medion,Probar ambiente,,Testaa tilaa,Tester un environnement,Környezet Tesztelése,Testa ambiente,反響テスト,환경 테스트,Test omgeving,Test miljø,Testuj Środowisko,Testar ambiente,,Testare Mediu,Проверка окружения,Тестирај окружење,Testa miljön,Test Ortamı,Тестувати оточення, +Edit Environment,REVMNU_EDIT,,,,Upravit prostředí,Rediger miljø,Umgebung editieren,Επεξεργασία Περιβάλλοντος,Modifi medion,Editar ambiente,,Muokkaa tilaa,Modifier un environnement,Környezet Szerkesztése,Modifica ambiente,反響編集,환경 편집,Omgeving bewerken,Rediger miljø,Edytuj Środowisko,Editar ambiente,,Editare Mediu,Редактировать окружение,Уреди окружење,Redigera miljön,Ortamı Düzenle,Редагувати оточення, +New Environment,REVMNU_NEW,,,,Nové prostředí,Nyt miljø,Neue Umgebung,Νέο Περιβάλλον,Nova medio,Nuevo ambiente,,Uusi tila,Nouveau environnement,Új Környezet,Nuovo ambiente,新規反響設定,새로운 환경 생성,Nieuwe omgeving,Nytt miljø,Nowe Środowisko,Novo ambiente,,Mediu Nou,Новое окружение,Ново окружење,Ny miljö,Yeni Çevre,Нове оточення, +Revert settings,REVMNU_REVERT,,,,Obnovit nastavení,Tilbageføre indstillinger,Zurücksetzen,Επαναφορά Ρυθμίσεων,Malfari agordojn,Revertir configuración,,Palauta asetukset,Réinitialiser les paramètres,Változtatások elvetése,Ripristina le impostazioni,設定を戻す,설정 되돌리기,Instellingen terugzetten,Tilbake innstillinger,Przywróć ustawienia,Reverter configurações,,Revenire la setările precedente,Сбросить настройки,Врати подешавања,Återkalla inställningar,Ayarları geri döndür,Налаштування за замовчуванням, +Environment Size,REVMNU_ENVIRONMENT_SIZE,Please translate only if you know how to properly name this technical jargon!,,,,,,Μέγεθος Περιβάλλοντος,Mediamplekso,Tamaño de ambiente,,Tilan koko,Taille Environnement,,Dimensioni dell'ambiente,反響サイズ,공간 크기,,,Rozmiar Środowiska,Tamanho do ambiente,,,,,Miljö storlek,,, +Environment Diffusion,REVMNU_ENVIRONMENT_DIFFUSION,,,,,,,Διάχυση Περιβάλλοντος,Medidifuzo,Difusión de ambiente,,Tilan äänen hajautuminen,Diffusion Environnement,,Diffusione dell'ambiente,反響伝播,공간 잔향 확산,,,Dyfuzja Środowiska,Difusão do ambiente,,,,,Miljö spridning,,, +Room,REVMNU_ROOM,,,,,,,Δωμάτιο,Ĉambro,Sala,,Tilan keskitaajuudet,Salle,,,,룸 효과,,,Pokój,Sala,,,,,,,, +Room HF,REVMNU_ROOM_HF,,,,,,,Δωμάτιο HF,Ĉambro (AF),Sala (Frecuencia alta),,Tilan korkeat taajuudet,HF Salle,,,,룸 효과 HF,,,Pokój (wysokie częstotliwości),Sala (alta frequência),,,,,,,, +Room LF,REVMNU_ROOM_LF,,,,,,,Δωμάτιο LF,Ĉambro (MaF),Sala (Frecuencia baja),,Tilan matalat taajuudet,LF Salle,,,,룸 효과 LF,,,Pokój (niskie częstotliwości),Sala (baixa frequência),,,,,,,, +Decay Time,REVMNU_DECAY_TIME,,,,,,,,Putriĝo-tempo,Tiempo de decadencia,,Häipymäaika,Temps Decay,,,,잔향 감쇠 시간,,,Czas Rozkładu,Tempo de decaimento,,,,,,,, +Decay HF Ratio,REVMNU_DECAY_HF_RATIO,,,,,,,,Putriĝo-proporcio (AF),Ratio de decadencia (Frecuencia alta),,Korkeiden taajuuksien (HF) häipymissuhdeluku,,,,Decay HF比率,잔향 감쇠 HF 비율,,,Wskażnik Rozkładu dla wysokich częstotliwości,Taxa de decaimento (alta freq.),,,,,,,, +Decay LF Ratio,REVMNU_DECAY_LF_RATIO,,,,,,,,Putriĝo-proporcio (MaF),Ratio de decadencia (Frecuencia baja),,Matalien taajuuksien (LF) häipymissuhdeluku,,,,Decay LF比率,잔향 감쇠 LF 비율,,,Wskaźnik Rozkładu dla niskich częstotliwości,Taxa de decaimento (baixa freq.),,,,,,,, +Reflections,REVMNU_REFLECTIONS,,,,,,,Αντανακλάσεις,Reflektoj,Reflejos,,Ensiheijastukset,,,,,룸 반사,,,Obicia,Reflexos,,,,,,,, +Reflections Delay,REVMNU_REFLECTIONS_DELAY,,,,,,,Καθυστέρηση Αντανακλάσεων,Prokrasto de reflektoj,Retraso de reflejos,,Ensiheijastusten viive,Délai Reflections,,,,룸 반사 딜레이 시간,,,Opóźnienie Odbić,Atraso de reflexos,,,,,,,, +Reflections Pan X,REVMNU_REFLECTIONS_PAN_X,,,,,,,,Reflektoj alturnas tra X,Desplazamiento en X de reflejos,,Ensiheijastusten X-panorointi,Orientation Reflections X,,,Reflections X定位,X축 룸 반사,,,Odbicia Osi X,Deslocamento X de reflexos,,,,,,,, +Reflections Pan Y,REVMNU_REFLECTIONS_PAN_Y,,,,,,,,Reflektoj alturnas tra Y,Desplazamiento en Y de reflejos,,Ensiheijastusten Y-panorointi,Orientation Reflections Y,,,Reflections Y定位,Y축 룸 반사,,,Odbicia Osi Y,Deslocamento Y de reflexos,,,,,,,, +Reflections Pan Z,REVMNU_REFLECTIONS_PAN_Z,,,,,,,,Reflektoj alturnas tra Z,Desplazamiento en Z de reflejos,,Ensiheijastusten Z-panorointi,Orientation Reflections Z,,,Reflections Z定位,Z축 룸 반사,,,Odbicia Osi Z,Deslocamento Z de reflexos,,,,,,,, +Reverb,REVMNU_REVERB,,,,,,,,Resono,Reverberación,,Jälkikaiunta,,,,,리버브,,,Pogłos,Reverberação,,,,,,,, +Reverb Delay,REVMNU_REVERB_DELAY,,,,,,,,Prokrasto de resono,Retraso de reverberación,,Jälkikaiunnan viive,Délai Reverb,,,,리버브 지연,,,Opóźnienie Pogłosu,Atraso de reverberação,,,,,,,, +Reverb Pan X,REVMNU_REVERB_PAN_X,,,,,,,,Resono alturnas tra X,Desplazamiento en X de reverberación,,Jälkikaiunnan X-panorointi,Orientation Reverb X,,,Reverb X定位,X축 리버브,,,Pogłos Osi X,Deslocamento X de reverberação,,,,,,,, +Reverb Pan Y,REVMNU_REVERB_PAN_Y,,,,,,,,Resono alturnas tra Y,Desplazamiento en Y de reverberación,,Jälkikaiunnan Y-panorointi,Orientation Reverb Y,,,Reverb Y定位,Y축 리버브,,,Pogłos Osi Y,Deslocamento Y de reverberação,,,,,,,, +Reverb Pan Z,REVMNU_REVERB_PAN_Z,,,,,,,,Resono alturnas tra Z,Desplazamiento en Z de reverberación,,Jälkikaiunnan Z-panorointi,Orientation Reverb Z,,,Reverb Z定位,Z축 리버브,,,Pogłos Osi Z,Deslocamento Z de reverberação,,,,,,,, +Echo Time,REVMNU_ECHO_TIME,,,,,,,,Tempo de eĥo,Tiempo de eco,,Kaikuaika,Longueur écho,,,,에코 시간,,,Czas Echa,Tempo de eco,,,,,,,, +Echo Depth,REVMNU_ECHO_DEPTH,,,,,,,,Produndo de eĥo,Profundidad de eco,,Kaiun syvyys,Profondeur écho,,,,에코 깊이,,,Głębokość Echa,Profundidade de eco,,,,,,,, +Modulation Time,REVMNU_MODULATION_TIME,,,,,,,,Tempo de modulado,Tiempo de modulación,,Modulaatioaika,Longueur Modulation,,,,전조 시간,,,Czas Modulacji,Tempo de modulação,,,,,,,, +Modulation Depth,REVMNU_MODULATION_DEPTH,,,,,,,,Produndo de modulado,Profundidad de modulación,,Modulaation syvyys,Profondeur Modulation,,,,전조 깊이,,,Głębokość Modulacji,Profundidade de modulação,,,,,,,, +Air Absorption HF,REVMNU_AIR_ABSORPTION_HF,,,,,,,,Aer-absorbo AF,Absorción en aire de frecuencia alta,,Korkeiden taajuuksien (HF) ilma-absorptio,,,,,대기 흡수 HF,,,Absorbcja Powietrza (wysokie częstotliwości),Absorção de ar de alta freq.,,,,,,,, +HF Reference,REVMNU_HF_REFERENCE,,,,,,,,AF referenco,Referencia de frecuencia alta,,Korkeiden taajuuksien vertausarvo,,,,HF参照値,HF 참조치,,,Odniesienie wysokich częstotliwości,Referência de alta freq.,,,,,,,, +LF Reference,REVMNU_LF_REFERENCE,,,,,,,,MaF referenco,Referencia de frecuencia baja,,Matalien taajuuksien vertausarvo,,,,LF参照値,LF 참조치,,,Odniesienie niskich częstotliwości,Referência de baixa freq.,,,,,,,, +Room Rolloff Factor,REVMNU_ROOM_ROLLOFF_FACTOR,,,,,,,,Ĉambro-Rolloff-faktoro,Factor de Roll-off de sala,,Tilan vaimenemiskerroin,Facteur de rolloff Salle,,,,룸 감쇠 양,,,Czynnik Zejścia,Fator de roll-off de sala,,,,,,,, +Diffusion,REVMNU_DIFFUSION,,,,,,,,Difuzo,Difusión,,Diffuusio,,,,,잔향 확산,,,Dyfuzja,Difusão,,,,,,,, +Density,REVMNU_DENSITY,,,,,,,,Denseco,Densidad,,Tiheys,Densité,,,密度,잔향 밀도,,,Zagęszczenie,Densidade,,,,,,,, +Reflections Scale,REVMNU_Reflections_Scale,,,,,,,,Skalo de reflektoj,Escala de reflejos,,Ensiheijastusten skaala,Echelle Reflections,,,Reflections音階,룸 반사 음계,,,Rozmiar Odbić,Escala de reflexos,,,,,,,, +Reflections Delay Scale,REVMNU_Reflections_Delay_Scale,,,,,,,,Prokrastskalo de reflektoj,Escala de retraso de reflejos,,Ensiheijastusten viiveen skaala,Délai d'échelle reflections,,,Reflections Delay音階,룸 반사 딜레이 음계,,,Skala Opóźnienia Odbić,Escala de atraso de reflexos,,,,,,,, +Decay Time Scale,REVMNU_Decay_Time_Scale,,,,,,,,Tempskalo de purtiĝo,Escala de tiempo de decadencia,,Häipymäajan skaala,Echelle temporelle Decay,,,Decay Time音階,잔향 감쇠시간 음계,,,Skala Czasu Rozkładu,Escala de tempo de decaimento,,,,,,,, +Decay HF Limit,REVMNU_Decay_HF_Limit,,,,,,,,AF-Limito de purtiĝo,Limite de decadencia de alta frecuencia,,Häipymän korkeiden taajuuksien raja-arvo,Limite HF Decay,,,Decay HF限度,잔향 감쇠 HF 한도,,,Limit Rozkładu Wysokich Częstotliwości,Limite de decaimento em alta freq.,,,,,,,, +Reverb Scale,REVMNU_Reverb_Scale,,,,,,,,Skalo de resono,Escala de reverberación,,Jälkikaiunnan skaala,Echelle Reverb,,,Reverb音階,리버브 음계,,,Skala Pogłosu,Escala de reverberação,,,,,,,, +Reverb Delay Scale,REVMNU_Reverb_Delay_Scale,,,,,,,,Prokrastskalo de resono,Escala de retraso de reverberación,,Jälkikaiunnan viiveen skaala,Délai d'échelle Reverb,,,Reverb Delay音階,리버브 딜레이 음계,,,Skala Opóźnienia Pogłosu,Escala de atraso de reverberação,,,,,,,, +Echo Time Scale,REVMNU_Echo_Time_Scale,,,,,,,,Tempskalo de eĥo,Escala de tiempo de eco,,Kaikuajan skaala,Echelle temporelle Echo,,,Echo Time音階,에코 시간 음계,,,Skala Czasu Echa,Escala de tempo de eco,,,,,,,, +Modulation Time Scale,REVMNU_Modulation_Time_Scale,,,,,,,,Tempskalo de modulado,Escala de tiempo de modulación,,Modulaatioajan skaala,Echelle temporelle Modulation,,,Modulation Time音階,전조 시간 음계,,,Skala Modulacji Czasu,Escala de tempo de modulação,,,,,,,, +Based on,REVMNU_Based_on,,,,Založeno na,Baseret på,Basierend auf,Βασισμένο σε,Bazita de,Basado en,,Perustana,Basé sur,Minta,Basato su,音響の元,음향 원본,Gebaseerd op,Basert på,Bazowane na,Baseado em,,Bazat pe,Основано на,Засновано на,Baserat på,Buna göre,На основі, +Name,REVMNU_Name,,,,Název,Navn,,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Navn,Nazwa,Nome,,Nume,Название,Назив,Namn,İsim,Назва, +ID #1,REVMNU_ID_1,,,,,,,,Identigo #1,ID Nº1,,,,,ID N°1,,아이디 #1,,,,,,,ИД №1,,,,, +ID #2,REVMNU_ID_2,,,,,,,,Identigo #2,ID Nº2,,,,,ID N°2,,아이디 #2,,,,,,,ИД №2,,,,, +Create,REVMNU_Create,,,,Vytvořit,Opret,Erstellen,Δημιουργία,Krei,Crear,,Luo,Créer,Készítés,Creare,作成,생성,Aanmaken,Opprett,Stwórz,Criar,,Creare,Создать,Направи,Skapa,Oluştur,Створити, +Save...,REVMNU_Save,,,,Uložit...,Gem...,Speichern...,Αποθήκευση,Konservi...,Guardar...,,Tallenna...,Sauvegarder...,Mentés...,Salvare...,セーブする...,저장 하기...,Opslaan...,Lagre...,Zapisz...,Salvar...,,Salvare...,Сохранить...,Сачувај...,Spara...,Kaydet...,Зберегти..., +File name,REVMNU_File_name,,,,Název souboru,Filnavn,Dateiname,Όνομα αρχείου,Dosiernomo,Nombre de archivo,,Tiedostonimi,Nom de fichier,Fájlnév,Nome del file,ファイル名,파일 이름,Bestandsnaam,Filnavn,Nazwa pliku,Nome do arquivo,,Nume fișier,Имя файла,Назив фајла,Filnamn,Dosya adı,Назва файлу, +Environments to save,REVMNU_Environments_to_save,,,,Prostředí k uložení,"Miljøer, der skal gemmes",Zu speichernde Umgebungen,Περιβάλλοντα για αποθήκευση,Medioj por konservi,Ambientes para guardar,,Tallennettavat tilat,Environnements à sauvegarder,Mentendő Környezetek,Ambienti da salvare,音響を保存,저장할 공간,Omgevingen om op te slaan,Miljøer som skal lagres,Środowiska do zapisu,Ambientes para salvar,,Medii de salvat,Сохранить окружения...,Окружења за чување,Miljöer som ska sparas,Kurtarılacak ortamlar,Зберегти оточення..., +,,Vulkan,,,,,,,,,,,,,,,,,,,,,,,,,,, +Vulkan Options (Experimental),DSPLYMNU_VKOPT,,,,Nastavení Vulkanu (Experimentální),Vulkan-indstillinger (eksperimentelt),Vulkan Optionen (Experimentell),Vulka Ρυθμίσεις (Πειραματικές),Agordoj por Vulkan (Eksperimenta),Opciones de Vulkan (Experimental),,Vulkan-asetukset (kokeellinen),Options Vulkan (Expérimental),Vulkan Beállítások (Kísérleti),Opzioni Vulkan (Sperimentale),Vulkan機能オプション(実験的),벌칸 설정(실험적),Vulkan-opties (Experimenteel),Vulkan Alternativer (Eksperimentell),Opcje Vulkan (Eksperymentalne),Opções de Vulkan (experimental),,Setări Mod Vulkan (În curs de testare),Настройки Vulkan (экспериментальные),Vulkan подешавања (експериментална),Vulkan-alternativ (experimentellt),Vulkan Seçenekleri (Deneysel),Налаштування Vulkan (експериментальні), +Vulkan Options,VK_TITLE,,,,Nastavení Vulkanu,Vulkan-indstillinger,Vulkan Optionen,Vulkan Ρυθμίσεις,Agordoj por Vulkan,Opciones de Vulkan,,Vulkan-asetukset,Options Vulkan,Vulkan Beállítások,Opzioni Vulkan,Vulkan機能オプション,벌칸 설정,Vulkan-opties,Vulkan-alternativer,Opcje Vulkan,Opções de Vulkan,,Setări Mod Vulkan,Настройки Vulkan,Vulkan подешавања,Vulkan-alternativ,Vulkan Seçenekleri,Налаштування Vulkan, +Enable Vulkan,VKMNU_ENABLE,,,,Povolit Vulkan,Aktiver Vulkan,Aktiviere Vulkan,Ενεργοποιηση του Vulkan,Ŝalti Vulkan,Activar Vulkan,,Ota käyttöön Vulkan,Activer Vulkan,Vulkan Engedélyezése,Abilita Vulkan,Vulkanを有効化,벌칸 렌더러 사용,Vulkan inschakelen,Aktiver Vulkan,Włącz Vulkan,Ativar Vulkan,,Activează modul video Vulkan,Использовать Vulkan,Омогући Vulkan,Aktivera Vulkan,Vulkan'ı Etkinleştir,Увімкнути Vulkan, +Vulkan Device ID,VKMNU_DEVICE,,,,ID zařízení Vulkanu,Vulkan-enheds-id,Vulkan Geräte ID,Vulkan ID Συσκευής,Identigo de Vulkan-aparato,ID de dispositivo Vulkan,,Vulkan-laitetunniste,ID du périphérique Vulkan,Vulkan Eszköz ID,Dispositivo ID Vulkan,Vulkanデバイス ID,벌칸 장치 아이디,Vulkan apparaat-ID,Vulkan Enhets-ID,ID urządzenia Vulkan,ID do dispositivo Vulkan,,ID Dispozitiv Vulkan,ИД устройства Vulkan,Vulkan ID уређаја,Vulkan-enhets-ID,Vulkan Cihaz Kimliği,ID пристрою Vulkan, +High Dynamic Range,VKMNU_HDR,,,,Vysoký dynamický rozsah (HDR),Høj dynamisk rækkevidde,,Υψηλό Δυναμική Εμβέλεια,Alta dinamika intervalo,Alto rango dinámico,,Korkea dynamiikka-alue (HDR),,,,ハイダイナミックレンジ,하이 다이나믹 레인지,Hoog dynamisch bereik,Høyt dynamisk område,Obraz HDR,Alto alcance dinâmico (HDR),,HDR,Расширенный динамический диапазон (HDR),HDR,Högt dynamiskt omfång,Yüksek Dinamik Aralık,HDR, +Warning: The Vulkan renderer is highly experimental!,VK_WARNING,,,,Varování: Vulkan renderer je velmi experimentální!,Advarsel: Vulkan-rendereren er meget eksperimentel!,Achtung: Der Vulkan Renderer ist noch sehr experimentell!,Προειδοποίηση: Ο Vulkan renderer είναι υψηλά πειραματικός!,Averto: La bildigilo de Vulkan estas alte eksperimenta!,Advertencia: ¡El renderizado por Vulkan es altamente experimental!,,Varoitus: Vulkan-hahmonnin on hyvin kokeellinen!,Attention: Le moteur de rendu Vulkan est très expérimental!,Vigyázat: A Vulkan renderer még teljesen kísérleti!,Attenzione: il motore grafico Vulkan è altamente sperimentale!,警告:Vulkanレンダラーは実験段階です!,경고: 벌칸 렌더러는 매우 실험적입니다!,Waarschuwing: De Vulkan renderer is zeer experimenteel!,Advarsel: Vulkan-rendereren er svært eksperimentell!,Uwaga: Renderer Vulkan jest bardzo eksperymentalny!,Atenção: o renderizador Vulkan é altamente experimental!,,Atenție: Modul Vulkan este încă în curs de testare!,Внимание: обработчик Vulkan в стадии тестирования!,УПОЗОРЕЊЕ: Vulkan рендерер је врло експерименталан!,Varning: Vulkan-renderaren är mycket experimentell!,Uyarı: Vulkan işleyici son derece deneyseldir!,Увага: рендер Vulkan на стадії тестування!, +These options will require a restart to take effect.,VK_RESTART,,,,Tato nastavení vyžadují restart hry.,Disse indstillinger kræver en genstart for at få effekt.,Diese Option erfordert einen Neustart!,Αυτές η ρυθμίσεις θα χρειαστούνε επανεκκίνηση για να ισχύσουν,Ĉi tiuj agordoj bezonos relanĉon por efikiĝi.,Estas opciones requieren reiniciar para tener efecto.,,Nämä asetukset vaativat uudelleenkäynnistyksen astuakseen voimaan.,Ces options nécessitent un redémarrage.,Ezen beállítások életbelépéséhez újraindítás szükséges.,Queste opzioni richiedono il riavvio per avere effetto.,これらのオプションを有効にするには再起動が必要です。,이 설정을 적용하려면 게임을 재시작해야 합니다.,Deze opties vereisen een herstart om van kracht te worden.,Disse alternativene krever en omstart for å tre i kraft.,"Te opcje będą wymagały ponownego włączenia, aby miały efekt.",É necessário reiniciar para que essas configurações surtam efeito.,É necessário reiniciar para estas configurações fazerem efeito.,Aceste setări necesită o repornire pentru a putea fi aplicate,Для применения этих изменений требуется перезапуск игры.,Морате поново покренути GZDoom да би промене ступиле на снагу.,De här alternativen kräver en omstart för att få effekt.,Bu seçeneklerin etkili olması için yeniden başlatılması gerekecektir.,Для застосування змін протрібно перезапустити гру., +Select Vulkan Device,VKMNU_DEVICESELECT,This is not yet implemented - but it is planned,,,Vybrat zařízení Vulkanu,Vælg Vulkan-enhed,Vulkan Gerät auswählen,Επιλογή Vulkan Συσκευής,Elekti Vulkan-aparaton,Seleccionar dispositivo Vulkan,,Valitse Vulkan-laite,Sélectionner périphérique Vulkan,Vulkan eszköz kiválasztása,Seleziona il Dispositivo Vulkan,Vulkanデバイスの選択,벌칸 장치를 고르시오,Selecteer Vulkan Apparaat,Velg Vulkan-enhet,Wybierz Urządzenie Vulkan,Selecione o dispositivo Vulkan,,Selectare Dispozitiv Vulkan,Выбрать устройство Vulkan,Изаберите Vulkan уређај,Välj Vulkan-enhet,Vulkan Aygıtını Seçin,Виберіть пристрій Vulkan, +,,Texture scaling,,,,,,,,,,,,,,,,,,,,,,,,,,, +ScaleNx,OPTVAL_SCALENX,,,,,,,,,,,,,,,,,,,,,,,,,,,, +NormalNx,OPTVAL_NORMALNX,,,,,,,,,,,,,,,,,,,,,,,,,,,, +hqNx,OPTVAL_HQNX,,,,,,,,,,,,,,,,,,,,,,,,,,,, +hqNx MMX,OPTVAL_HQNXMMX,,,,,,,,,,,,,,,,,,,,,,,,,,,, +xBRZ,OPTVAL_NXBRZ,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Old xBRZ,OPTVAL_OLD_NXBRZ,,,,xBRZ (starší),Gamle xBRZ,xBRZ alt,Παλίο xBRZ,Malnova xBRZ,Antiguo xBRZ,,Vanha xBRZ,Ancien xBRZ,Régi xBRZ,Vecchio xBRZ,旧xBRZ,구형 xBRZ,Oud xBRZ,Gammel xBRZ,Stare xBRZ,Antigo xBRZ,,Vechiul xBRZ,Старый xBRZ,Стари xBRZ,Gamla xBRZ,Eski xBRZ,Старий xBRZ, +,,Option Search,,,,,,,,,,,,,,,,,,,,,,,,,,, +Option Search,OS_TITLE,,,,Vyhledávání možností,Mulighed Søgning,Optionssuche,Αναζήτηση Ρυθμίσεων,Serĉi agordojn,Buscar opciones,,Asetushaku,Recherche Option,Beállítások keresése,Opzioni di ricerca,オプション検索,옵션 검색,Optie zoeken,Alternativt søk,Szukanie Opcji,Buscar opção,Procurar opção,Căutare Setări,Поиск настройки,Претрага,Sökning av alternativ,Seçenek Arama,Пошук налаштування, +Search for any term,OS_ANY,,,,Hledat jakékoli klíčové slovo,Søg efter et vilkårligt begreb,Suche nach beliebigem Begriff,Αναζήτηση για όποιαδηποτε λέξη,Serĉi iun ajn terminon,Buscar cualquier término,,Etsi mitä tahansa sanaa,N'importe quel mot,Keresés bármely kifejezésre,Cerca per ciascun termine,いずれかの用語を探す,용어 검색,Zoek naar eender welke term,Søk etter en hvilken som helst term,Szukaj jakiegokolwiek wyrażenia,Buscar por qualquer termo,Procurar por um termo qualquer,Căutare după orice termen,Искать любое из слов,Тражи било који термин,Sök efter valfri term,Herhangi bir terim için arama yapın,Шукати будь яке з слів, +Search for all terms,OS_ALL,,,,Hledat všechna klíčová slova,Søg efter alle udtryk,Suche nach allen Begriffen,Αναζήτηση για όλες της λέξεις,Serĉi ĉiujn terminojn,Buscar todos los términos,,Etsi kaikki sanat,Tous les mots,Keresés minden kifejezésre,Cerca per tutti i termini,全ての用語を探す,모든 조건 검색,Zoek naar alle termen,Søk etter alle termer,Szukaj wszystkich wyrażeń,Buscar por todos os termos,Procurar por todos os termos,Căutare după toți termenii,Искать все слова,Тражи сваки термин,Sök efter alla termer,Tüm terimler için arama yapın,Шукати всі слова, +No results found.,OS_NO_RESULTS,,,,Nic nenalezeno.,Ingen resultater fundet.,Keine Resultate,Δέν βρέθηκαν αποτελέσματα,Neniu trafo.,Ningún resultado.,,Ei tuloksia.,Pas de résultat trouvé,Nincs találat,Nessun risultato trovato.,見つかりませんでした。,검색 결과 없음.,Geen resultaten gevonden.,Ingen resultater funnet.,Brak wyników,Nenhum resultado encontrado.,,Niciun rezultat găsit.,Результаты не найдены.,Нема резултата.,Inga resultat hittades.,Sonuç bulunamadı.,Нічого не знайдено., +Search:,OS_LABEL,,,,Hledat:,Søg:,Suche:,Αναζήτηση:,Serĉi:,Buscar:,,Etsi:,Recherche:,Keresés:,Trova:,検索:,검색:,Zoeken:,Søk:,Szukaj:,Busca:,Procura:,Caută:,Поиск:,Претрага:,Sök:,Ara:,Пошук:, +,,Blood Bath Announcer,,,,,,,,,,,,,,,,,,,,,,,,,,, +%k boned %o like a fish,TXT_OBITUARY1,,,,%o byl@[ao_cs] vykoštěn@[ao_cs] jako ryba hráčem %k,%k udbenede %o som en fisk,%k hat %o zerlegt wie einen Fisch,Ο/Η %k ξεκοκάλοσε @[pro2_gr] %o σα ψάρι,%k senostigis %o kiel fiŝon,%k ha deshuesado a %o como a un pescado,%k deshuesó a %o como a un pescado,%k perkasi %o paran kuin kalan,%k a désossé %o comme un poisson,%k kifilézte %o -t mint a halat,%k ha dissossato %o come un pesce,%k は %o の骨を魚のように引っこ抜いた。,%k 은(는) %o 의 뼈를 발랐다.,%k mergelde %o als een vis,%k utbeinet %o som en fisk,%k odfiletował@[ao_pl] %o jak rybę,%k desossou %o como um peixe,,%k l-a dezosat pe %o ca pe un pește,%k пересчитал косточки игрока %o,%k је очистио %o као рибу,%k benade %o som en fisk,"%o, %k tarafından balık gibi kemirildi.",%k порахува@[adj_1_ua] ребра %o, +%k castrated %o,TXT_OBITUARY2,,,,%o byl@[ao_cs] vykastrován@[ao_cs] hráčem %k,%k kastrerede %o,%k hat %o kastriert,Ο/Η %k ευνούχισε %o,%k kastris %o,%k ha castrado a %o,%k castró a %o,%k kastroi %o paran,%k a castré %o,%k kasztrálta %o -t,%k ha castrato %o,%k は %o を去勢した。,%k 은(는) %o 을(를) 거세시켰다.,%k castreerde %o,%k kastrert %o,%k wykastrował@[ao_pl] %o,%k castrou %o,,%k l-a castrat pe %o,%k кастрировал игрока %o,%k је кастрирао %o,%k kastrerade %o,"%o, %k tarafından hadım edildi.",%k каструва@[adj_1_ua] %o, +%k creamed %o,TXT_OBITUARY3,,,,%o byl@[ao_cs] rozšlehán@[ao_cs] hráčem %k,%k smurte %o,%k hat %o eingeseift,Ο/Η %k κρέμασε @[pro2_gr] %o,%k kremigis %o,%k ha cremado a %o,%k cremó a %o,%k kermasi %o paran,%k a battu %o à plate couture ,%k elkente %o -t,%k ha cremato %o,%k は %o に反吐ブチ撒けさせた。,%k 은(는) %o 을(를) 양념시켰다.,%k pureerde %o,%k fløtet %o,%k spienił@[ao_pl] %o,%k fez creme de %o,,%k l-a transformat în cremă pe %o,%k взбил игрока %o,%k је истукао %o,%k gräddade %o,,%k розпуши@[adj_1_ua] %o, +%k decimated %o,TXT_OBITUARY4,,,,%o byl@[ao_cs] zdecimován@[ao_cs] hráčem %k,%k decimerede %o,%k hat %o dezimiert,Ο/Η %k αποδεκάτισε @[pro2_gr] %o,%k detruegis %o,%k ha diezmado a %o,%k diezmó a %o,%k hävitti %o paran,%k a décimé %o,%k megtizedelte %o -t,%k ha decimato %o,%k は %o の居場所を間引いた。,%k 은(는) %o 을(를) 망가뜨렸다.,%k decimeerde %o,%k desimert %o,%k przetrzebił@[ao_pl] %o,%k decimou %o,,%k l-a decimat pe %o,%k скосил игрока %o,%k је десетковао %o,%k decimerade %o,"%o, %k tarafından yok edildi.",%k зітну@[adj_1_ua] %o, +%k destroyed %o,TXT_OBITUARY5,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k,%k ødelagde %o,%k hat %o zerstört,Ο/Η %k κατέστεψε @[pro2_gr] %o,%k detruis %o,%k ha destruido a %o,%k destruyó a %o,%k tuhosi %o paran,%k a détruit %o,%k elpusztította %o -t,%k ha distrutto %o,%k は %o を完全に破壊した。,%k 은(는) %o 을(를) 파괴했다.,%k vernietigde %o,%k destruert %o,%k zniszczył@[ao_pl] %o,%k destruiu %o,,%k l-a distrus pe %o,%k уничтожил игрока %o,%k је уништио %o,%k förstörde %o,,%k знищи@[adj_1_ua] %o, +%k diced %o,TXT_OBITUARY6,,,,%o byl@[ao_cs] nakrájen@[ao_cs] na kostičky hráčem %k,%k skar %o i tern,%k hat %o in Würfel zerteilt,Ο/Η %k τεμάχησε @[pro2_gr] %o,%k diskubigis %o,%k ha picado en cubitos a %o,%k picó en cubitos a %o,%k pilkkosi %o paran,%k a coupé en dés %o,%k kockára vágta %o -t,%k ha tagliato a cubetti %o,%k は %o を賽の目に切った。,%k 은(는) %o 을(를) 잘게 잘게 썰었다.,%k sneed %o in stukjes,%k skåret %o i terninger,%k pokroił@[ao_pl] w kostkę %o,%k fez picadinho de %o,%k cortou %o,%k l-a feliat pe %o,%k разрезал игрока %o,%k је исецкао %o,%k skar %o i tärningar,"%o, %k tarafından doğrandı.",%k наріза@[adj_1_ua] %o, +%k disembowled %o,TXT_OBITUARY7,,,,%o byl@[ao_cs] vykuchán@[ao_cs] hráčem %k,%k udkløvede %o,%k hat %o ausgeweidet,Ο/Η %k ισοπέδοσε @[pro2_gr] %o,%k sentripigis %o,%k ha destripado a %o,%k destripó a %o,%k suolisti %o paran,%k a étripé %o,%k kibelezte %o -t,%k ha smembrato %o,%k は %o の臓物を引きずり出した。,%k 은(는) %o 의 내장을 도려냈다.,%k ontleedde %o,%k sprettet opp %o,%k wypatroszył@[ao_pl] %o,%k estripou %o,,%k l-a eviscerat pe %o,%k выпотрошил игрока %o,%k је ампутирао %o,%k tog upp %o i bitar,,%k випотроши@[adj_1_ua] %o, +%k flattened %o,TXT_OBITUARY8,,,,%o byl@[ao_cs] zplacatěn@[ao_cs] hráčem %k,%k smadrede %o,%k hat %o dem Erdboden gleichgemacht,Ο/Η %k ησοπέδοσε @[pro2_gr] %o,%k platigis %o,%k ha aplanado a %o,%k aplanó a %o,%k lyttäsi %o paran,%k a aplati %o,%k kilapította %o -t,%k ha schiacciato %o,%k は %o をぶっ潰した。,%k 은(는) %o 의 코를 납작하게 만들었다.,%k plette %o,%k flatet ut %o,%k rozpłaszczył@[ao_pl] %o,%k achatou %o,%k espalmou %o,%k l-a făcut plat pe %o,%k сплюснул игрока %o,%k је изравнао %o,%k plattade %o,"%o, %k tarafından dümdüz edildi.",%k сплющи@[adj_1_ua] %o, +%k gave %o Anal Justice,TXT_OBITUARY9,,,,%o utržil@[ao_cs] anální spravedlnost od hráče %k,%k lemlæstede %o,%k hat %o anale Gerechtigkeit gegeben,Ο/Η %k γάμησε @[pro2_gr] %o @[pro3_gr] κόλο,%k donis pugan juston al %o,%k le ha dado justicia anal a %o,%k le dió justicia anal a %o,%k jakoi %o paralle anaalioikeutta,%k a rendu une justice anale a %o,%k Anális Igazságot adott %o -nak ,%k ha dato a %o Giustizia Anale,%k は %o のケツにぶち込んだ。,%k 은(는) %o 에게 홍콩행을 보냈다.,%k gaf %o anale rechtvaardigheid,%k ga %o anal rettferdighet,%k dał@[ao_pl] %o Analną Sprawiedliwość,%k deu Justiça Anal para %o,,%k i-a făcut jucătorului %o o Justiție Anală,%k устроил анальное правосудие игроку %o,%k је дао %o аналну правду,%k gav %o anal rättvisa,"%o, %k tarafından dümdüz edildi.",%k влаштува@[adj_1_ua] анальне правосуддя %o, +%k gave AnAl MaDnEsS to %o,TXT_OBITUARY10,,,,%o utrpěl@[ao_cs] AnÁlNí ŠíLeNsTvÍ od hráče %k,%k spildte %o,%k gab %o AnAlEn WaHnSiNn,Ο/Η %k έσκισε τον κόλο του/της] %o,%k donis pUgAn frEnEzOn al %o,%k le ha dado LoCuRa AnAl a %o,%k le dió LoCuRa AnAl a %o,%k teki %o paran AnAaLiHuLlUkSi,%k a donné la FOLIE ANALE a %o,%k SeGgBe KüLDtE %o -t,%k ha dato FoLlIa AnAle a %o,%k は %o のケツをガバガバにした。,%o 은(는) %k 의 찰진 맛을 보았다.,%k gaf aNaLe DoLhEiD aan %o,%k ga %o anal rettferdighet,%k dał@[ao_pl] %o AnAlNe SzAlEńStWo ,%k deu LoUcUrA aNaL para %o,,%k i-a dat NeBuNiE AnAlĂ jucătorului %o,%k устроил АнАЛ КаРнаВаЛ игроку %o,%k је дао АнАлНо ЛуДиЛо %o,%k gav %o anal rättvisa,"%o, %k tarafından dümdüz edildi.",%k влаштува@[adj_1_ua] АнАЛ ГуЛяНнЯ %o, +%k killed %o,TXT_OBITUARY11,,,,%o byl@[ao_cs] zabit@[ao_cs] hráčem %k,%k dræbte %o,%k hat %o getötet,Ο/Η %k σκότωσε @[pro2_gr] %o,%k mortigis %o,%k ha matado a %o,%k mató a %o,%k tappoi %o paran,%k a tué %o,%k kicsinálta %o -t,%k ha ucciso %o,%k は %o をブッ殺した。,%k 은(는) %o 을(를) 죽였다.,%k doodde %o,%k drepte %o,%k zabił@[ao_pl] %o,%k matou %o,,%k l-a omorât pe %o,%k убил игрока %o,%k је убио %o,%k dödade %o,"%o, %k tarafından öldürüldü.",%k вби@[adj_1_ua] %o, +%k made mincemeat out of %o,TXT_OBITUARY12,,,,%o byl@[ao_cs] namelen@[ao_cs] hráčem %k,%k gjorde hakket kød af %o,%k hat %o zu Hackfleisch verarbeitet,Ο/Η %k έφτιαξε κυμά με @[pro2_gr] %o,%k farigis farĉon el %o,%k ha hecho picadillo de %o,%k hizo picadillo de %o,%k teki jauhelihaa %o parasta,%k a fait de la viande hachée de %o,%k ledarálta %o -t,%k ha triturato %o,%k は %o をミンチにした。,%o 은(는) %k 에 의해 분쇄됐다.,%k maakte gehakt van %o,%k laget kjøttdeig av %o,%k zrobił@[ao_pl] mięso mielone z %o,%k fez carne moída de %o,%k fez carne picada do %o,%k a facut tocătură din %o,%k сделал отбивную из игрока %o,%k је направио млевено месо од %o,%k gjorde köttfärs av %o,"%o, %k tarafından kıyma haline getirildi.",%k зроби@[adj_1_ua] відбивну з %o, +%k massacred %o,TXT_OBITUARY13,,,,%o byl@[ao_cs] zmasakrován@[ao_cs] hráčem %k,%k massakrerede %o,%k hat %o niedergemetzelt,Ο/Η %k δολοφώνησε @[pro2_gr] %o,%k masakris %o,%k ha masacrado a %o,%k masacró a %o,%k verilöylytti %o parkaa,%k a massacré %o,%k lemészárolta %o -t,%k ha fatto di %o carne tritata,%k は %o を虐殺した。,%k 은(는) %o 을(를) 참살했다.,%k slachtte %o af,%k massakrerte %o,%k zmasakrował@[ao_pl] %o,%k massacrou %o,,%k a fost masacrat de către %o,%k устроил бойню игроку %o,%k је масакрирао %o,%k massakrerade %o,"%o, %k tarafından katledildi",%k влаштува@[adj_1_ua] для %o бійню, +%k mutilated %o,TXT_OBITUARY14,,,,%o byl@[ao_cs] zmrzačen@[ao_cs] hráčem %k,%k lemlæstede %o,%k hat %o verstümmelt,Ο/Η %k ακρωτηριάσε @[pro2_gr] %o,%k mutilis %o,%k ha mutilado a %o,%k mutiló a %o,%k silpoi %o paran,%k a mutilé %o,%k megcsonkította %o -t,%k ha massacrato %o,%k は %o をバラバラ死体にした。,%k 은(는) %o 의 팔다리를 절단했다.,%k verminkte %o,%k lemlestet %o,%k rozszarpał@[ao_pl] %o,%k mutilou %o,,%k l-a mutilat pe %o,%k изуродовал игрока %o,%k је мутилирао %o,%k lemlästade %o,"%o, %k tarafından sakat bırakıldı.",%k знівечи@[adj_1_ua] %o, +%k reamed %o,TXT_OBITUARY15,,,,%o byl@[ao_cs] proděravěn@[ao_cs] hráčem %k,%k skændede %o,%k hat %o aufgerieben,Ο/Η %k δέσμισε @[pro2_gr] %o,%k alezis %o,%k ha escariado a %o,%k escarió a %o,%k porasi %o paran,%k a découpé en fines lamelles %o,%k seggbe rakta %o -t,%k ha squartato %o,%k は %o の穴を大きく広げた。,%k 은(는) %o 을(를) 크게 혼냈다.,%k holde %o uit,%k maltraktert %o,%k rozwiercił@[ao_pl] %o,%k esquartejou %o,,%k l-a transformat într-un top de hârtie pe %o,%k рассверлил игрока %o,%k је наоружао %o,%k har gjort %o illa.,"%o, %k tarafından öldürüldü.",%k просверли@[adj_1_ua] %o, +%k ripped %o a new orifice,TXT_OBITUARY16,,,,%o má novou díru od hráče %k,%k flåede %o en ny åbning,%k hat %o eine neue Körperöffnung verpasst,Ο/Η άνοιξε μια νέα τρύπα @[pro3_gr] %o,%k ŝiris novan truon en %o,%k le ha hecho a %o un nuevo orificio,%k le hizo a %o un nuevo orificio,%k repi %o paralle uuden aukon,%k a ouvert un nouvel orifice a %o,%k új szájat csinált %o -nak,%k ha aperto a %o un altro orifizio,%k は %o を切り裂いて新しい穴を作ってあげた。,%k 은(는) %o 을(를) 죽여 뜯어서 작품을 만들었다.,%k scheurde een opening uit %o,%k revet %o en ny kroppsåpning,%k rozerwał@[ao_pl] %o nowy otwór,%k abriu um novo orifício em %o,,%k i-a făcut jucătorului %o un nou orificiu,%k проделал новое отверстие в игроке %o,%k је исцепао %o нови отвор,%k slet upp en ny öppning i %o,"%o, %k tarafından yeni bir delik açıldı.",%k зроби@[adj_1_ua] в %o нову дірку, +%k slaughtered %o,TXT_OBITUARY17,,,,%o byl@[ao_cs] zavražděn@[ao_cs] hráčem %k,%k slagtede %o,%k hat %o geschlachtet,Ο/Η %k έσφαξε @[pro2_gr] %o,%k buĉis %o,%k ha sacrificado a %o,%k sacrificó a %o,%k teurasti %o paran,%k a meurtri %o,%k lemészárolta %o -t,%k ha macellato %o,%k は %o を屠殺した。,%o 은(는) %k 에 의해 도살당했다.,%k slachtte %o,%k slaktet %o,%k zarżn@[irreg_2_pl] %o,%k abateu %o,,%k l-a măcelărit pe %o,%k устроил резню игроку %o,%k је заклао %o,%k slaktade %o,"%o, %k tarafından katledildi.",%k прові@[adj_1_ua] різню %o, +%k smashed %o,TXT_OBITUARY18,,,,%o byl@[ao_cs] zmlácen@[ao_cs] hráčem %k,%k smadrede %o,%k hat %o zerklatscht,Ο/Η %k τσάκισε @[pro2_gr] %o,%k frakasis %o,%k ha destrozado a %o,%k destrozó a %o,%k murskasi %o paran,%k a enfoncé %o,%k földbe döngölte %o -t,%k ha distrutto %o,%k は %o をぶっ飛ばした。,%k 은(는) %o 을(를) 내팽개쳤다.,%k vermorzelde %o,%k knust %o,%k stłukł@[ao_pl] %o,%k esmagou %o,,%k l-a spart pe %o,%k размазал игрока %o,%k је поломио %o,%k krossade %o,"%o, %k tarafından ezildi.",%k розмаза@[adj_1_ua] %o, +%k sodomized %o,TXT_OBITUARY19,,,,Hráč %k se dopustil sodomie na hráči %o,%k sodomiserede %o,%k hat %o sodomisiert,Ο/Η %k γάμησε @[pro2_gr] %o,%k sodomizis %o,%k ha sodomizado a %o,%k sodomizó a %o,%k anaaliraiskasi %o paran,%k y a sodomisé n %o,%k szodomizálta %o -t,%k ha sodomizzato %o,%o は %k にカマを掘られた。 ,%o 은(는) %k 을(를) 위해 등을 보였다.,%k sodomiseerde %o,%k sodomisert %o,%k spenetrował@[ao_pl] %o,%k sodomizou %o,,%k l-a sodomizat pe %o,%k содомировал игрока %o,%k је изјебао %o,%k sodomiserade %o,"%o, %k tarafından sodomize edildi.",%k зґвалтува@[adj_1_ua] %o, +%k splattered %o,TXT_OBITUARY20,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] hráčem %k,%k sprøjtede %o,%k hat %o zerspritzt,Ο/Η %k έσκασε @[pro2_gr] %o,%k disĵetis %o,%k ha rociado a %o,%k roció a %o,%k roiski %o paran yltympäri,%k a explosé de %o,%k szétloccsantotta %o -t,%k ha spiaccicato %o,%k は %o にばら撒かれた。,%k 은(는) %o 을(를) 박살냈다.,%k splette %o,%k sprutet %o,%k rozbryzgał@[ao_pl] %o,%k explodiu %o,,%k l-a împrăștiat pe %o,%k разбрызгал игрока %o,%k је спљоштио %o,%k sprutade %o.,"%o, %k tarafından parçalandı.",%k розбризка@[adj_1_ua] %o, +%k squashed %o,TXT_OBITUARY21,,,,%o byl@[ao_cs] rozmáčknut@[ao_cs] hráčem %k,%k kværnede %o,%k hat %o zerquetscht,Ο/Η %k πάτησε @[pro2_gr] %o,%k premplatigis %o,%k ha aplastado a %o,%k aplastó a %o,%k litisti %o paran,%k a écrabouillé %o,%k eltaposta %o -t,%k ha schiacciato %o,%k は %o に潰された。,%k 은(는) %o 을(를) 짓이겼다.,%k plette %o,%k knust %o,%k zmiażdżył@[ao_pl] %o,%k espatifou %o,,%k l-a strivit pe %o,%k расплющил игрока %o,%k је згњечио %o,%k krossade %o,"%o, %k tarafından ezildi.",%k розчави@[adj_1_ua] %o, %k throttled %o,TXT_OBITUARY22,,,,%o byl@[ao_cs] zaškrcen@[ao_cs] hráčem %k,%k kvæler %o,%k hat %o erdrosselt,Ο/Η %k κομμάτιασε @[pro2_gr] %o,%k strangolis %o,%k ha estrangulado a %o,%k ahorcó a %o,%k polki %o paran,%k a étouffé %o,%k megfolytotta %o -t,%k ha strozzato %o,%k は %o に絞られた。,%k 은(는) %o 을(를) 목 졸라 죽였다.,%k wurgde %o,%k kvalt %o,"%k udusił@[ao_pl] %o -",%k estrangulou %o,,%k l-a strâns de gât pe %o,%k задушил игрока %o,%k је угушио %o,"%o, %k tarafından boğazlandı.",%k вдушив %o, -%k wasted %o,TXT_OBITUARY23,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k,%k spildte %o,%k hat %o verbraucht,Ο/Η %k σκότωσε @[pro2_gr] %o,%k malŝparis %o,%k ha desechado a %o,%k desechó a %o,%k kulutti %o paran,%k a décharné %o,%k elpusztította %o -t,%k ha distrutto %o,%k は %o に消された。,%k 은(는) %o 을(를) 쓰레기처럼 내다 버렸다.,%k maakte %o koud,%k bortkastet %o,%k roztrwonił@[ao_pl] %o,%k detonou %o,,%k l-a risipit pe %o,%k замочил игрока %o,%k је убио %o,"%o, %k tarafından harcandı.",%k загнав у могилу %o, -%k body bagged %o,TXT_OBITUARY24,,,,Hráč %k narval %o@[psn1_cs] tělo do pytle,%k tog %o i en pose med kroppen,%k hat %o eingesackt,Ο/Η %k έχωσε @[pro2_gr] %o στη κάσα του/της,%k ensakigis %o,%k ha embolsado a %o,%k embolsó a %o,%k kääri %o paran ruumispussiin,%k a placé %o dans son linceul,%k összecsomagolta %o -t,%k ha mandato %o all'obitorio,%k は %o を死体袋にした。,%k 은(는) %o 의 장례식을 치렀다.,%k stopte %o in een lijkzak,%k lagt %o i likpose,%k spakował@[ao_pl] %o do torby na zwłoki,%k mandou %o para o necrotério,,%k l-a băgat în sac pe %o,%k упаковал игрока %o в мешок для трупов,%k је умртвио %o,"%o, %k tarafından öldürüldü.",%k запакував %o в мішок для трупів, -%k sent %o to Hell,TXT_OBITUARY25,,,,%o byl@[ao_cs] poslán@[ao_cs] do pekla hráčem %k,%k sendte %o til helvede,%k hat %o zur Hölle fahren lassen,Ο/Η %k έστειλε @[pro2_gr] %o στο δίαολο,%k sendis %o al Infero,%k ha enviado a %o al infierno,%k mandó a %o al infierno,%k lähetti %o paran helvettiin,%k a envoyé %o en enfer,%k elküldte %o -t a Pokolba,%k ha spedito %o all'Inferno,%k は %o を地獄に送った。,%o 은(는) %k 덕에 지옥으로 돌아갔다.,%k zond %o naar de hel,%k sendt %o til helvete,%k wysłał@[ao_pl] %o do Piekła,%k mandou %o para o Inferno,,%k l-a trimis pe %o în Infern,%k отправил в ад игрока %o,%k је послао %o до Врага,"%o, %k tarafından cehenneme gönderildi.",%k послав %o до дідька лисого, -%k toasted %o,TXT_OBITUARY26,,,,%o byl@[ao_cs] upečen@[ao_cs] hráčem %k,%k skålede %o,%k hat %o geröstet,Ο/Η %k έψησε @[pro2_gr] %o,%k tostis %o,%k ha tostado a %o,%k tostó a %o,%k käristi %o paran,%k a grillé %o,%k megpirította %o -t,%k ha arrostito %o,%k は %o を焼却した。,%o 은(는) %k 덕에 맛있게 구워졌다.,%k roosterde %o,%k ristet %o,%k stostował@[ao_pl] %o,%k tostou %o,,%k l-a prăjit pe %o,%k поджарил игрока %o,%k је тостирао %o,"%o, %k tarafından öldürüldü.",%k піджарив %o, -%k snuffed %o,TXT_OBITUARY27,,,,%o byl@[ao_cs] rozsápán@[ao_cs] hráčem %k,%k snusede %o,%k hat %o vernichtet,Ο/Η %k έσβησε @[pro2_gr] %o,%k snufis %o,%k ha aspirado a %o,%k aspiró a %o,%k sammutti %o paran,%k a crevé %o,%k kinyiffantotta %o -t,%k ha spento %o,%k は %o を処刑した。,%o 은(는) %k 에 의해 짓눌려졌다.,%k legde %o om,%k snuffet %o,%k powąchał@[ao_pl] %o,%k apagou %o,,%k l-a mirosit pe %o,%k прикончил игрока %o,%k је угасио %o,"%o, %k tarafından öldürüldü.",%k загасив %o, -%k hosed %o,TXT_OBITUARY28,,,,%o byl@[ao_cs] odstříknut@[ao_cs] hráčem %k,%k sprøjtede %o,%k hat %o eingetütet,Ο/Η %k έονιξε @[pro2_gr] %o σε σφαίρες,%k hosis %o,%k se ha cargado a %o,%k se cargó a %o,%k pesi %o paran,%k a arrosé %o,%k felhúzta %o gatyáját,%k l'ha fatta sopra %o,%k は %o にぶっかけた。,%k 은(는) %o 을(를) 패배로 씻겼다.,%k bespoot %o,%k spylt med vann %o,%k załatwił@[ao_pl] %o,%k metralhou %o,,%k a pus furtunul pe %o,%k расстрелял игрока %o,%k је упскао %o,"%o, %k'in hışmına uğradı.",%o перепало від %k, -%k sprayed %o,TXT_OBITUARY29,,,,%o byl@[ao_cs] postříkán@[ao_cs] hráčem %k,%k sprøjtede %o,%k hat %o pulverisiert,Ο/Η %k ψέκασε @[pro2_gr] %o,%k ŝprucigis %o,%k ha pulverizado a %o,%k pulverizó a %o,%k ruiskutti %o paran,%k a pulvérise %o,%k szétporlasztotta %o -t,%k ha vaporizzato %o,%k は %o を撒き散らした。,%o 의 피는 %k 의 물감으로 쓰였다.,%k besproeide %o,%k sprayet %o,%k rozpryskał@[ao_pl] %o,%k pulverizou %o,,%k l-a pulverizat pe %o,%k распылил игрока %o,%k је испрскао %o,"%o, %k tarafından püskürtüldü.",%k розпилили %o, -%k made dog meat out of %o,TXT_OBITUARY30,,,,%o byl@[ao_cs] hozen@[ao_cs] psům hráčem %k,%k lavede hundekød ud af %o,%k hat Hundefutter aus %o gemacht,Ο/Η %k γύρισε @[pro2_gr] %o σε κιμά,%k farigis hundan viandon el %o,%k ha hecho comida para perros de %o,%k hizo alimento para perros de %o,%k teki %o parasta koiranruokaa,%k a fait de la pâtée pour chien de %o,%k döghúst csinált %o -ból,%k ha fatto di %o polpette,%k は %o を犬の餌にした。,%k 은(는) %o 로 개밥을 만들었다.,%k maakte hondenvlees van %o,%k laget hundekjøtt av %o,%k zrobił@[ao_pl] mięso dla psów z %o,%k fez almôndegas de %o,,%k l-a transformat în mâncare de câini pe %o,%k скормил псам игрока %o,%k је направио псеће месо од %o,"%o, %k tarafından köpek etine dönüştürüldü.",%k зтовк %o до псєчих харчів, -%k beat %o like a cur,TXT_OBITUARY31,,,,%o byl@[ao_cs] zmlácen@[ao_cs] jako pes hráčem %k,%k bankede %o som en skiderik,%k hat %o wie einen Hund geschlagen,Ο/Η %k πλάκοσε @[pro2_gr] %o σαν κοπρίτης,%k batis %o kiel hundaĉon,%k ha pateado a %o como a un perro callejero,,%k huitoi %o parkaa kuin rakkia,%k a battu %o,%k szétverte %o -t mint egy korcsot,%k ha battuto %o come un cane,%k は %o を狂犬の様に扱った。,%o 은(는) %k 에게 똥개처럼 맞았다.,%k sloeg %o als een hond,%k slått %o som en hund,%k pobił@[ao_pl] %o jak kundla,%k espancou %o como um cachorro,%k espancou %o como um cão,%k îl bate pe %o ca pe o jigodie,%k сделал игрока %o как худую свинью,%k је превио %o ко мачку,"%o, %k tarafından dövüldü.",%k відбив печінки %o, -%o is excrement,TXT_SELFOBIT1,,,,%o je exkrement,%o er ekskrementer,%o wurde zu Exkrement verarbeitet,@[art_gr] %o είναι κόπρανα,%o estas ekskremento,%o es excremento,,%o on ulostetta,%o est une merde,%o ürülék lett,%o è un escremento,%o はもはや排泄物のようだ。,%o 은(는) 배설물이 되었다.,%o is uitschot,%o er ekskrementer,%o został@[ao_pl] odpadkami,%o virou escremento,,%o e excrement,%o теперь экскремент,%o је сада измет,%o dışkıdır,%o тепер екскремент, -%o is hamburger,TXT_SELFOBIT2,,,,%o je hamburger,%o er en hamburger,%o ist Hamburger,@[art_gr] %o είναι χάμπουργκερ,%o estas hamburgero,%o es una hamburguesa,,%o on hakkelusta,%o est un hamburger,%o hamburger lett,%o è un hamburger,%o はハンバーガーになった。,%o 은(는) 고기 반죽이 되었다.,%o is hamburger,%o er hamburger,%o został@[ao_pl] hamburgerem,%o virou hambúrguer,,%o e hamburger,%o теперь гамбургер,%o је сада пљескавица,%o hamburgerdir,%o тепер гамбургер, -%o suffered scrotum separation,TXT_SELFOBIT3,,,,%o prodělal@[ao_cs] separaci šourku,%o fik skrotumskæring,%os Eier wurden gebraten,Οι όρχις @[pro4_gr] %o βγήκανε,%o suferis skrotan disigon,%o ha sufrido separación de escroto,%o sufrió separación de escroto,%o kärsii kivespussin erotuksesta,%o a souffert d'une séparation du scrotum,%o heréi szétváltak,%o ha subito la separazione dello scroto,%o の陰嚢は剥離していた。,%o 은(는) 고자가 되었다.,%o onderging scrotumscheiding,%o led pungseparasjon,%o doznał@[ao_pl] oddzielenia moszny,%o sofreu separação escrotal,,%o a suferit o separație de șcrot,%o страдает от потери тестикул,%o му је исечена патка,%o skrotum ayrılması yaşadı,%o постраждав від втрати мошонки, -%o volunteered for population control,TXT_SELFOBIT4,,,,%o se zúčastnil@[ao_cs] čistky obyvatelstva,%o meldte sig frivilligt til befolkningskontrol,%o hat sich freiwillig zur Bevölkerungskontrolle gemeldet,@[art_gr] %o εθελώντησε για έλεγχο του πληθυσμού,%o volontulis por loĝantara regado,%o se ha hecho voluntario para control de población,%o se hizo voluntario para control de población,%o ilmoittautui vapaaehtoiseksi väestönhallintaan,%o s'est proposé pour un contrôle de la population,%o önként jelentkezett népességszabályozásra,%o si è offerto per il controllo della popolazione,%o は人口削減政策の実験台に志願した。,%o 은(는) 자연에 의해 낙태 당했다.,%o was vrijwilliger voor bevolkingsbeperking,%o meldte seg frivillig til befolkningskontroll,%o zgłosił@[ao_pl] się na kontrolę ludności,%o se voluntariou para o controle populacional,%o se voluntariou para o controlo populacional,%o a voluntariat pentru controlul populației,%o стал добровольцем в борьбе с перенаселением,%o је волунтирао за контролу популације,Nüfus kontrolü için %o gönüllü oldu,%o борется з перенаселенням, -%o has suicided,TXT_SELFOBIT5,,,,%o spáchal@[ao_cs] sebevraždu,%o har begået selvmord,%o hat Selbstmord begangen,@[art_gr] %o έχει αυτοκτονήση,%o sin mortigis,%o se ha suicidado,%o se suicidó,%o on tehnyt itsemurhan,%o s'est suicidé,%o öngyilkos lett,%o si è suicidato,%o は勝手にくたばった。,%o 은(는) 한심하게 자살했다.,%o heeft zelfmoord gepleegd,%o har begått selvmord,%o popełnił@[ao_pl] samobójstwo,%o se suicidou,%o suicidou-se,%o s-a sinucis,Игрок %o самоубился,%o је убио самог себе,%o intihar etti,%o самовбився, -%o received the Darwin Award,TXT_SELFOBIT6,,,,%o dostal@[ao_cs] Darwinovu cenu,%o modtog Darwin-prisen,%o hat den Darwinpreis erhalten,@[art_gr] %o κέρδισε το Darwin βραβείο,%o ricevis la Darwin-premion,%o ha recibido el Premio Darwin,%o recibió el Premio Darwin,%o sai Darwin-palkinnon,%o a recu la médaille Darwin,És a Darwin-díj nyertese: %o,%o ha ricevuto il Darwin Award,%o にはダーウィン賞が授与された。,%o 은(는) 다윈상을 받을 자격이 있다.,%o ontving de Darwin Award,%o mottok Darwin-prisen,%o otrzymał@[ao_pl] Nagrodę Darwina,%o ganhou o Prêmio Darwin,,%o a primit Premiul Darwin,Игрок %o получил премию Дарвина,%o је добио Дарвиново признање,%o Darwin Ödülü'nü aldı,%o отримав премію Дарвіна, -,USE_GENERIC_FONT,This is not a text to be translated but an engine switch for complex languages.,,,,,,,,,,,,,,1,1,,,,,,,,,,, +",%k estrangulou %o,,%k l-a strâns de gât pe %o,%k задушил игрока %o,%k је угушио %o,%k tog strypgrepp på %o,"%o, %k tarafından boğazlandı.",%k вдуши@[adj_1_ua] %o, +%k wasted %o,TXT_OBITUARY23,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k,%k spildte %o,%k hat %o verbraucht,Ο/Η %k σκότωσε @[pro2_gr] %o,%k malŝparis %o,%k ha desechado a %o,%k desechó a %o,%k kulutti %o paran,%k a décharné %o,%k elpusztította %o -t,%k ha distrutto %o,%k は %o に消された。,%k 은(는) %o 을(를) 쓰레기처럼 내다 버렸다.,%k maakte %o koud,%k bortkastet %o,%k roztrwonił@[ao_pl] %o,%k detonou %o,,%k l-a risipit pe %o,%k замочил игрока %o,%k је убио %o,%k slösade bort %o,"%o, %k tarafından harcandı.",%k загна@[adj_1_ua] у могилу %o, +%k body bagged %o,TXT_OBITUARY24,,,,Hráč %k narval %o@[psn1_cs] tělo do pytle,%k tog %o i en pose med kroppen,%k hat %o eingesackt,Ο/Η %k έχωσε @[pro2_gr] %o στη κάσα του/της,%k ensakigis %o,%k ha embolsado a %o,%k embolsó a %o,%k kääri %o paran ruumispussiin,%k a placé %o dans son linceul,%k összecsomagolta %o -t,%k ha mandato %o all'obitorio,%k は %o を死体袋にした。,%k 은(는) %o 의 장례식을 치렀다.,%k stopte %o in een lijkzak,%k lagt %o i likpose,%k spakował@[ao_pl] %o do torby na zwłoki,%k mandou %o para o necrotério,,%k l-a băgat în sac pe %o,%k упаковал игрока %o в мешок для трупов,%k је умртвио %o,%k dödade %o,"%o, %k tarafından öldürüldü.",%k запакува@[adj_1_ua] %o в мішок для трупів, +%k sent %o to Hell,TXT_OBITUARY25,,,,%o byl@[ao_cs] poslán@[ao_cs] do pekla hráčem %k,%k sendte %o til helvede,%k hat %o zur Hölle fahren lassen,Ο/Η %k έστειλε @[pro2_gr] %o στο δίαολο,%k sendis %o al Infero,%k ha enviado a %o al infierno,%k mandó a %o al infierno,%k lähetti %o paran helvettiin,%k a envoyé %o en enfer,%k elküldte %o -t a Pokolba,%k ha spedito %o all'Inferno,%k は %o を地獄に送った。,%o 은(는) %k 덕에 지옥으로 돌아갔다.,%k zond %o naar de hel,%k sendt %o til helvete,%k wysłał@[ao_pl] %o do Piekła,%k mandou %o para o Inferno,,%k l-a trimis pe %o în Infern,%k отправил в ад игрока %o,%k је послао %o до Врага,%k skickade %o till helvetet,"%o, %k tarafından cehenneme gönderildi.",%k посла@[adj_1_ua] %o до дідька лисого, +%k toasted %o,TXT_OBITUARY26,,,,%o byl@[ao_cs] upečen@[ao_cs] hráčem %k,%k skålede %o,%k hat %o geröstet,Ο/Η %k έψησε @[pro2_gr] %o,%k tostis %o,%k ha tostado a %o,%k tostó a %o,%k käristi %o paran,%k a grillé %o,%k megpirította %o -t,%k ha arrostito %o,%k は %o を焼却した。,%o 은(는) %k 덕에 맛있게 구워졌다.,%k roosterde %o,%k ristet %o,%k stostował@[ao_pl] %o,%k tostou %o,,%k l-a prăjit pe %o,%k поджарил игрока %o,%k је тостирао %o,%k rostade %o,"%o, %k tarafından öldürüldü.",%k піджари@[adj_1_ua] %o, +%k snuffed %o,TXT_OBITUARY27,,,,%o byl@[ao_cs] rozsápán@[ao_cs] hráčem %k,%k snusede %o,%k hat %o vernichtet,Ο/Η %k έσβησε @[pro2_gr] %o,%k snufis %o,%k ha aspirado a %o,%k aspiró a %o,%k sammutti %o paran,%k a crevé %o,%k kinyiffantotta %o -t,%k ha spento %o,%k は %o を処刑した。,%o 은(는) %k 에 의해 짓눌려졌다.,%k legde %o om,%k snuffet %o,%k powąchał@[ao_pl] %o,%k apagou %o,,%k l-a mirosit pe %o,%k прикончил игрока %o,%k је угасио %o,%k snusade %o,"%o, %k tarafından öldürüldü.",%k загаси@[adj_1_ua] %o, +%k hosed %o,TXT_OBITUARY28,,,,%o byl@[ao_cs] odstříknut@[ao_cs] hráčem %k,%k sprøjtede %o,%k hat %o eingetütet,Ο/Η %k έονιξε @[pro2_gr] %o σε σφαίρες,%k hosis %o,%k se ha cargado a %o,%k se cargó a %o,%k pesi %o paran,%k a arrosé %o,%k felhúzta %o gatyáját,%k l'ha fatta sopra %o,%k は %o にぶっかけた。,%k 은(는) %o 을(를) 패배로 씻겼다.,%k bespoot %o,%k spylt med vann %o,%k załatwił@[ao_pl] %o,%k metralhou %o,,%k a pus furtunul pe %o,%k расстрелял игрока %o,%k је упскао %o,%k sprutade %o,"%o, %k'in hışmına uğradı.",%o перепало від %k, +%k sprayed %o,TXT_OBITUARY29,,,,%o byl@[ao_cs] postříkán@[ao_cs] hráčem %k,%k sprøjtede %o,%k hat %o pulverisiert,Ο/Η %k ψέκασε @[pro2_gr] %o,%k ŝprucigis %o,%k ha pulverizado a %o,%k pulverizó a %o,%k ruiskutti %o paran,%k a pulvérise %o,%k szétporlasztotta %o -t,%k ha vaporizzato %o,%k は %o を撒き散らした。,%o 의 피는 %k 의 물감으로 쓰였다.,%k besproeide %o,%k sprayet %o,%k rozpryskał@[ao_pl] %o,%k pulverizou %o,,%k l-a pulverizat pe %o,%k распылил игрока %o,%k је испрскао %o,%k sprayade %o,"%o, %k tarafından püskürtüldü.",%k розпили@[adj_1_ua] %o, +%k made dog meat out of %o,TXT_OBITUARY30,,,,%o byl@[ao_cs] hozen@[ao_cs] psům hráčem %k,%k lavede hundekød ud af %o,%k hat Hundefutter aus %o gemacht,Ο/Η %k γύρισε @[pro2_gr] %o σε κιμά,%k farigis hundan viandon el %o,%k ha hecho comida para perros de %o,%k hizo alimento para perros de %o,%k teki %o parasta koiranruokaa,%k a fait de la pâtée pour chien de %o,%k döghúst csinált %o -ból,%k ha fatto di %o polpette,%k は %o を犬の餌にした。,%k 은(는) %o 로 개밥을 만들었다.,%k maakte hondenvlees van %o,%k laget hundekjøtt av %o,%k zrobił@[ao_pl] mięso dla psów z %o,%k fez almôndegas de %o,,%k l-a transformat în mâncare de câini pe %o,%k скормил псам игрока %o,%k је направио псеће месо од %o,%k gjorde hundkött av %o,"%o, %k tarafından köpek etine dönüştürüldü.",%k зтовк@[adj_3_ua] %o до псєчих харчів, +%k beat %o like a cur,TXT_OBITUARY31,,,,%o byl@[ao_cs] zmlácen@[ao_cs] jako pes hráčem %k,%k bankede %o som en skiderik,%k hat %o wie einen Hund geschlagen,Ο/Η %k πλάκοσε @[pro2_gr] %o σαν κοπρίτης,%k batis %o kiel hundaĉon,%k ha pateado a %o como a un perro callejero,,%k huitoi %o parkaa kuin rakkia,%k a battu %o,%k szétverte %o -t mint egy korcsot,%k ha battuto %o come un cane,%k は %o を狂犬の様に扱った。,%o 은(는) %k 에게 똥개처럼 맞았다.,%k sloeg %o als een hond,%k slått %o som en hund,%k pobił@[ao_pl] %o jak kundla,%k espancou %o como um cachorro,%k espancou %o como um cão,%k îl bate pe %o ca pe o jigodie,%k сделал игрока %o как худую свинью,%k је превио %o ко мачку,%k rostade %o,"%o, %k tarafından dövüldü.",%k відби@[adj_1_ua] печінки %o, +%o is excrement,TXT_SELFOBIT1,,,,%o je exkrement,%o er ekskrementer,%o wurde zu Exkrement verarbeitet,@[art_gr] %o είναι κόπρανα,%o estas ekskremento,%o es excremento,,%o on ulostetta,%o est une merde,%o ürülék lett,%o è un escremento,%o はもはや排泄物のようだ。,%o 은(는) 배설물이 되었다.,%o is uitschot,%o er ekskrementer,%o został@[ao_pl] odpadkami,%o virou escremento,,%o e excrement,%o теперь экскремент,%o је сада измет,%o är avföring,%o dışkıdır,%o тепер екскремент, +%o is hamburger,TXT_SELFOBIT2,,,,%o je hamburger,%o er en hamburger,%o ist Hamburger,@[art_gr] %o είναι χάμπουργκερ,%o estas hamburgero,%o es una hamburguesa,,%o on hakkelusta,%o est un hamburger,%o hamburger lett,%o è un hamburger,%o はハンバーガーになった。,%o 은(는) 고기 반죽이 되었다.,%o is hamburger,%o er hamburger,%o został@[ao_pl] hamburgerem,%o virou hambúrguer,,%o e hamburger,%o теперь гамбургер,%o је сада пљескавица,%o är hamburgare,%o hamburgerdir,%o тепер гамбургер, +%o suffered scrotum separation,TXT_SELFOBIT3,,,,%o prodělal@[ao_cs] separaci šourku,%o fik skrotumskæring,%os Eier wurden gebraten,Οι όρχις @[pro4_gr] %o βγήκανε,%o suferis skrotan disigon,%o ha sufrido separación de escroto,%o sufrió separación de escroto,%o kärsii kivespussin erotuksesta,%o a souffert d'une séparation du scrotum,%o heréi szétváltak,%o ha subito la separazione dello scroto,%o の陰嚢は剥離していた。,%o 은(는) 고자가 되었다.,%o onderging scrotumscheiding,%o led pungseparasjon,%o doznał@[ao_pl] oddzielenia moszny,%o sofreu separação escrotal,,%o a suferit o separație de șcrot,%o страдает от потери тестикул,%o му је исечена патка,%o fick pungen separerad,%o skrotum ayrılması yaşadı,%o постражда@[adj_1_ua] від втрати мошонки, +%o volunteered for population control,TXT_SELFOBIT4,,,,%o se zúčastnil@[ao_cs] čistky obyvatelstva,%o meldte sig frivilligt til befolkningskontrol,%o hat sich freiwillig zur Bevölkerungskontrolle gemeldet,@[art_gr] %o εθελώντησε για έλεγχο του πληθυσμού,%o volontulis por loĝantara regado,%o se ha hecho voluntario para control de población,%o se hizo voluntario para control de población,%o ilmoittautui vapaaehtoiseksi väestönhallintaan,%o s'est proposé pour un contrôle de la population,%o önként jelentkezett népességszabályozásra,%o si è offerto per il controllo della popolazione,%o は人口削減政策の実験台に志願した。,%o 은(는) 자연에 의해 낙태 당했다.,%o was vrijwilliger voor bevolkingsbeperking,%o meldte seg frivillig til befolkningskontroll,%o zgłosił@[ao_pl] się na kontrolę ludności,%o se voluntariou para o controle populacional,%o se voluntariou para o controlo populacional,%o a voluntariat pentru controlul populației,%o стал добровольцем в борьбе с перенаселением,%o је волунтирао за контролу популације,%o anmälde sig frivilligt till befolkningskontroll,Nüfus kontrolü için %o gönüllü oldu,%o борется з перенаселенням, +%o has suicided,TXT_SELFOBIT5,,,,%o spáchal@[ao_cs] sebevraždu,%o har begået selvmord,%o hat Selbstmord begangen,@[art_gr] %o έχει αυτοκτονήση,%o sin mortigis,%o se ha suicidado,%o se suicidó,%o on tehnyt itsemurhan,%o s'est suicidé,%o öngyilkos lett,%o si è suicidato,%o は勝手にくたばった。,%o 은(는) 한심하게 자살했다.,%o heeft zelfmoord gepleegd,%o har begått selvmord,%o popełnił@[ao_pl] samobójstwo,%o se suicidou,%o suicidou-se,%o s-a sinucis,Игрок %o самоубился,%o је убио самог себе,%o har begått självmord,%o intihar etti,%o самовби@[adj_2_ua], +%o received the Darwin Award,TXT_SELFOBIT6,,,,%o dostal@[ao_cs] Darwinovu cenu,%o modtog Darwin-prisen,%o hat den Darwinpreis erhalten,@[art_gr] %o κέρδισε το Darwin βραβείο,%o ricevis la Darwin-premion,%o ha recibido el Premio Darwin,%o recibió el Premio Darwin,%o sai Darwin-palkinnon,%o a recu la médaille Darwin,És a Darwin-díj nyertese: %o,%o ha ricevuto il Darwin Award,%o にはダーウィン賞が授与された。,%o 은(는) 다윈상을 받을 자격이 있다.,%o ontving de Darwin Award,%o mottok Darwin-prisen,%o otrzymał@[ao_pl] Nagrodę Darwina,%o ganhou o Prêmio Darwin,,%o a primit Premiul Darwin,Игрок %o получил премию Дарвина,%o је добио Дарвиново признање,%o fick Darwinpriset,%o Darwin Ödülü'nü aldı,%o отрима@[adj_1_ua] премію Дарвіна, +,USE_GENERIC_FONT,This is not a text to be translated but an engine switch for complex languages.,,,,,,,,,,,,,,1,1,,,,,,,,,,,, ,REQUIRED_CHARACTERS,This should list all uppercase characters that are REQUIRED for proper language display. If it is acceptable that accents get omitted a character should NOT be listed here!,,,ÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ,ÅÆØÉ,ÄÖÜẞ,ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ,ĈĜĤĴŜŬ,ÁÉÍÓÚÑÜ,,ÄÖ,ÀÂÇÉÈÊËÎÏÔŒÙÛŸ,ÁÉÍÓÖÚÜŐŰ,ÀÈÉÌÒÙ,,,"ÉËÖ -",ÅÆØÉ,ĄĆĘŁŃÓŚŹŻ,ÁÉÍÓÚÀÃÕÂÊÔÇ,,ĂÎȚÂȘ,АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ,АБВГДЂЕЖЗИЈКЛЉМНЊОПРСТЋУФХЦЧЏШ,ÖÜÇĞİŞ,АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ, -Full options menu,OPTMNU_FULLOPTIONS,,,,Úplná nastavení,Fuld menu med indstillinger,Alle Optionen,Πλήρες μενού ρυθμίσεον,Plena agordo-menuo,Menú de opciones completo,,Täysi asetusvalikko,Menu options complet,Teljes beállításmenü,Opzioni complete,全オプション欄,전체 옵션 메뉴,Alle opties tonen,Full alternativmeny,Pełne Menu Opcji,Menu de opções completo,,Meniu Setări Complet,Полное меню настроек,,Tam seçenekler menüsü,Повне меню налаштувань, -Simple options menu,OPTMNU_SIMPLEON,,,,Zjednodušená nastavení,Enkel menu med indstillinger,Einfaches Optionsmenü,Απλό μενού ρυθμίσεον,Simpla agordo-menuo,Menú de opciones simplificado,,Yksinkertainen asetusvalikko,Menu options simplifié,Egyszerű beállításmenü,Opzioni base,必要なオプションのみ,간단한 옵션 메뉴,Eenvoudig optiemenu,Enkel meny med alternativer,Proste Menu Opcji,Menu de opções simples,,Meniu Setări Simplificat,Упрощённое меню настроек,,Basit seçenekler menüsü,Спрощене меню налаштувань, -Browse Game Config,OPTMNU_OPENCONFIG,,,,Procházet konfigurační soubory,Gennemse spilkonfiguration,Konfigurationsdatei anzeigen,,Foliumi agordojn de ludo,Abrir carpeta de configuración de juego,,Selaa pelin asetuksia,Parcourir configuration,Játék konfiguráció böngészése,Apri le Configurazioni di Gioco,ゲームコンフィグ参照,게임 환경설정 찾아보기,Door gameconfiguratie bladeren,Bla gjennom spillkonfigurasjon,Przeglądaj Ustawienia Gry,Abrir pasta de configuração de jogo,,Caută Configurația Jocului,Открыть файл настроек игры,,Oyun Yapılandırmasına Gözat,Перегляд налаштувань гри, -Browse Screenshots,OPTMNU_OPENSCREENSHOTS,,,,Procházet snímky obrazovky,Gennemse skærmbilleder,Screenshots anzeigen,,Foliumi ekrankopiojn,Abrir carpeta de capturas de pantalla,,Selaa kuvakaappauksia,Parcourir les captures d'écran,Képernyőképek böngészése,Apri gli Screenshot,クリーンショット参照,스크린샷 찾아보기,Door schermafbeeldingen bladeren,Bla gjennom skjermbilder,Przeglądaj Zrzuty Ekranu,Abrir pasta de capturas de tela,,Caută Capturi de Ecran,Просмотр снимков экрана,,Ekran Görüntülerine Gözat,Перегляд скріншотів, -Browse Saved Games,OPTMNU_OPENSAVES,,,,Procházet uložené hry,Gennemse gemte spil,Spielstände anzeigen,,Foliumi konservitajn ludadojn,Abrir carpeta de partidas guardadas,,Selaa tallennettuja pelejä,Parcourir sauvegardes,Elmentett játékok böngészése,Apri i Giochi Salvati,セーブしたゲーム参照,저장된 게임 찾아보기,Door opgeslagen games bladeren,Bla gjennom lagrede spill,Przeglądaj Zapisy Gry,Abrir pasta de jogos salvos,,Caută Salvări,Просмотр сохранённых игр,,Kaydedilen Oyunlara Gözat,Перегляд збережень ігр, -Swap mouse buttons,MOUSEMNU_SWAPBUTTONS,,,,Prohodit tlačítka myši,Udskift museknapper,Maustasten vertauschen,,Permuti musbutonojn,Alternar botones de ratón,,Vaihda hiiren painikkeita,Permuter les boutons de la souris,Egérgombok felcserélése,Inverti i comandi del mouse,マウスボタンを反転,마우스 버튼 바꾸기,Muisknoppen verwisselen,Bytt museknapper,Zamień Przyciski Myszki,Trocar botões do mouse,,Schimbă Butoanele Mouse-ului între Ele,Поменять местами кнопки мыши,,Fare düğmelerini değiştirme,Поміняти місцями кнопки миші, -,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Only modified,OPTVAL_ONLYMODIFIED,,,,Pouze upravené,Kun ændret,Nur modfizierte,,Nur modifitaj,Solo modificados,,Vain muunneltu,Modifié seulement,Csak módosított,Solo modificato,モディファイのみ,수정된 것만,Alleen gewijzigd,Bare endret,Tylko zmodyfikowane,Somente modificado,,Numai modificat,Только изменённый,Само модификовано,Yalnızca değiştirilmiş,Тільки в модифікаціях, -Unknown,TXT_UNKNOWN,,,,Neznámé,Ukendt,Unbekannt,Άχνωστο,Nekonata,Desconocido,,Tuntematon,Inconnue,Ismeretlen,Sconosciuto,不明,알 수 없음,Onbekend,Ukjent,Nieznane,Desconhecido,,Necunoscut,Неизвестно,Непознат,Bilinmiyor,Невідомо, -HUD,OPTVAL_HUD,,,,,,,,,,,,ATH,,,,,,,,HUD,,,Отображение информации,,,Інтерфейс, -Automap,OPTVAL_AUTOMAP,,,,Automapa,,,,Aŭtomapo,Automapa,,,Carte,,Automappa,オートマップ,오토맵,,,Automapa,Automapa,,Hartă Computerizată,Автокарта,Аутомап,,Автокарта, -HUD + Automap,OPTVAL_HUDANDMAP,,,,HUD + Automapa,,,,HUD + Aŭtomapo,HUD + Automapa,,,ATH + Carte,,HUD + Automappa,HUD+オートマップ,HUD + 오토맵,,,HUD + Automapa,HUD + Automapa,,Interfață + Hartă Computerizată,Интерфейс + автокарта,HUD + Аутомап,,Інтерфейс + Автокарта, -This savegame needs these files,TXT_SAVEGAMENEEDS,,,,Uložená hra potřebuje tyto soubory,Dette savegame har brug for disse filer,Dieser Spielstand benötigt die folgenden Dateien,Το αρχείο αποθήκευσης χριάζετε αυτά τα αρχεία,Ĉi tiu konservita ludo bezonas ĉi tiujn dosierojn,Esta partida guardada necesita los siguientes archivos,,Tämä pelitallenne tarvitsee nämä tiedostot,Cette sauvegarde nécessite les fichiers suivants:,Ehhez a mentéshez a következő fájlok kellenek:,Questo salvataggio ha bisogno di questi file,このセーブデータには 必要なファイルがある,이 저장 된 게임은 해당 파일이 필요합니다.,Dit spel heeft de volgende bestanden nodig,Dette lagringsspillet trenger disse filene,Ten zapis gry potrzebuje tych plików,Este jogo salvo precisa destes arquivos,Este jogo guardado precisa destes arquivos,Acest joc salvat necesită următoarele fișiere,Данное сохранение требует следующие файлы,Овој сачуваној игри требају ови фајлови,Bu kayıt oyunu şu dosyalara ihtiyaç duyar,Цій грі потрібні такі файли, \ No newline at end of file +",ÅÆØÉ,ĄĆĘŁŃÓŚŹŻ,ÁÉÍÓÚÀÃÕÂÊÔÇ,,ĂÎȚÂȘ,АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ,АБВГДЂЕЖЗИЈКЛЉМНЊОПРСТЋУФХЦЧЏШ,ÄÖÅÉ,ÖÜÇĞİŞ,АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ, +Full options menu,OPTMNU_FULLOPTIONS,,,,Úplná nastavení,Fuld menu med indstillinger,Alle Optionen,Πλήρες μενού ρυθμίσεον,Plena agordo-menuo,Menú de opciones completo,,Täysi asetusvalikko,Menu options complet,Teljes beállításmenü,Opzioni complete,全オプション欄,전체 옵션 메뉴,Alle opties tonen,Full alternativmeny,Pełne Menu Opcji,Menu de opções completo,,Meniu Setări Complet,Полное меню настроек,,Fullständig alternativmeny,Tam seçenekler menüsü,Повне меню налаштувань, +Simple options menu,OPTMNU_SIMPLEON,,,,Zjednodušená nastavení,Enkel menu med indstillinger,Einfaches Optionsmenü,Απλό μενού ρυθμίσεον,Simpla agordo-menuo,Menú de opciones simplificado,,Yksinkertainen asetusvalikko,Menu options simplifié,Egyszerű beállításmenü,Opzioni base,必要なオプションのみ,간단한 옵션 메뉴,Eenvoudig optiemenu,Enkel meny med alternativer,Proste Menu Opcji,Menu de opções simples,,Meniu Setări Simplificat,Упрощённое меню настроек,,Enkel alternativmeny,Basit seçenekler menüsü,Спрощене меню налаштувань, +Browse Game Config,OPTMNU_OPENCONFIG,,,,Procházet konfigurační soubory,Gennemse spilkonfiguration,Konfigurationsdatei anzeigen,,Foliumi agordojn de ludo,Abrir carpeta de configuración de juego,,Selaa pelin asetuksia,Parcourir configuration,Játék konfiguráció böngészése,Apri le Configurazioni di Gioco,ゲームコンフィグ参照,게임 환경설정 찾아보기,Door gameconfiguratie bladeren,Bla gjennom spillkonfigurasjon,Przeglądaj Ustawienia Gry,Abrir pasta de configuração de jogo,,Caută Configurația Jocului,Открыть файл настроек игры,,Bläddra i spelkonfigurationen,Oyun Yapılandırmasına Gözat,Перегляд налаштувань гри, +Browse Screenshots,OPTMNU_OPENSCREENSHOTS,,,,Procházet snímky obrazovky,Gennemse skærmbilleder,Screenshots anzeigen,,Foliumi ekrankopiojn,Abrir carpeta de capturas de pantalla,,Selaa kuvakaappauksia,Parcourir les captures d'écran,Képernyőképek böngészése,Apri gli Screenshot,クリーンショット参照,스크린샷 찾아보기,Door schermafbeeldingen bladeren,Bla gjennom skjermbilder,Przeglądaj Zrzuty Ekranu,Abrir pasta de capturas de tela,,Caută Capturi de Ecran,Просмотр снимков экрана,,Bläddra bland skärmdumpar,Ekran Görüntülerine Gözat,Перегляд скріншотів, +Browse Saved Games,OPTMNU_OPENSAVES,,,,Procházet uložené hry,Gennemse gemte spil,Spielstände anzeigen,,Foliumi konservitajn ludadojn,Abrir carpeta de partidas guardadas,,Selaa tallennettuja pelejä,Parcourir sauvegardes,Elmentett játékok böngészése,Apri i Giochi Salvati,セーブしたゲーム参照,저장된 게임 찾아보기,Door opgeslagen games bladeren,Bla gjennom lagrede spill,Przeglądaj Zapisy Gry,Abrir pasta de jogos salvos,,Caută Salvări,Просмотр сохранённых игр,,Bläddra bland sparade spel,Kaydedilen Oyunlara Gözat,Перегляд збережень ігр, +Swap mouse buttons,MOUSEMNU_SWAPBUTTONS,,,,Prohodit tlačítka myši,Udskift museknapper,Maustasten vertauschen,,Permuti musbutonojn,Alternar botones de ratón,,Vaihda hiiren painikkeita,Permuter les boutons de la souris,Egérgombok felcserélése,Inverti i comandi del mouse,マウスボタンを反転,마우스 버튼 바꾸기,Muisknoppen verwisselen,Bytt museknapper,Zamień Przyciski Myszki,Trocar botões do mouse,,Schimbă Butoanele Mouse-ului între Ele,Поменять местами кнопки мыши,Замените дугмад миша,Byta musknappar,Fare düğmelerini değiştirme,Поміняти місцями кнопки миші, +,,Additional menu texts,,,,,,,,,,,,,,,,,,,,,,,,,,, +Only modified,OPTVAL_ONLYMODIFIED,,,,Pouze upravené,Kun ændret,Nur modfizierte,,Nur modifitaj,Solo modificados,,Vain muunneltu,Modifié seulement,Csak módosított,Solo modificato,モディファイのみ,수정된 것만,Alleen gewijzigd,Bare endret,Tylko zmodyfikowane,Somente modificado,,Numai modificat,Только изменённый,Само модификовано,Endast ändrat,Yalnızca değiştirilmiş,Тільки в модифікаціях, +Unknown,TXT_UNKNOWN,,,,Neznámé,Ukendt,Unbekannt,Άχνωστο,Nekonata,Desconocido,,Tuntematon,Inconnue,Ismeretlen,Sconosciuto,不明,알 수 없음,Onbekend,Ukjent,Nieznane,Desconhecido,,Necunoscut,Неизвестно,Непознат,Okänd,Bilinmiyor,Невідомо, +HUD,OPTVAL_HUD,,,,,,,,,,,,ATH,,,,,,,,,,,Отображение информации,,,,Інтерфейс, +Automap,OPTVAL_AUTOMAP,,,,Automapa,,,,Aŭtomata mapo,Automapa,,,Carte,Auto-térkép,Automappa,オートマップ,오토맵,,,Automapa,Automapa,,Hartă Computerizată,Автокарта,Аутомап,,,Автокарта, +HUD + Automap,OPTVAL_HUDANDMAP,,,,HUD + Automapa,,,,HUD + Aŭtomata mapo,HUD + Automapa,,,ATH + Carte,HUD + Auto-térkép,HUD + Automappa,HUD+オートマップ,HUD + 오토맵,,,HUD + Automapa,HUD + Automapa,,Interfață + Hartă Computerizată,Интерфейс + автокарта,HUD + Аутомап,,,Інтерфейс + Автокарта, +This savegame needs these files,TXT_SAVEGAMENEEDS,,,,Uložená hra potřebuje tyto soubory,Dette savegame har brug for disse filer,Dieser Spielstand benötigt die folgenden Dateien,Το αρχείο αποθήκευσης χριάζετε αυτά τα αρχεία,Ĉi tiu konservita ludo bezonas ĉi tiujn dosierojn,Esta partida guardada necesita los siguientes archivos,,Tämä pelitallenne tarvitsee nämä tiedostot,Cette sauvegarde nécessite les fichiers suivants:,Ehhez a mentéshez a következő fájlok kellenek:,Questo salvataggio ha bisogno di questi file,このセーブデータには 必要なファイルがある,이 저장 된 게임은 해당 파일이 필요합니다.,Dit spel heeft de volgende bestanden nodig,Dette lagringsspillet trenger disse filene,Ten zapis gry potrzebuje tych plików,Este jogo salvo precisa destes arquivos,Este jogo guardado precisa destes arquivos,Acest joc salvat necesită următoarele fișiere,Данное сохранение требует следующие файлы,Овој сачуваној игри требају ови фајлови,Detta sparande behöver dessa filer,Bu kayıt oyunu şu dosyalara ihtiyaç duyar,Цій грі потрібні такі файли, +Multiplayer Options,OPTMNU_MULTIPLAYER,,,,Multiplayer,Multiplayer-indstillinger,Mehrspieleroptionen,,Agordoj de la plurludanta reĝimo,Opciones del multijugador,,Moninpelivaihtoehdot,Options multijoueurs,Többjátékos lehetőségek,Opzioni multigiocatore,マルチプレイ オプション,멀티플레이어 옵션,Multiplayer Opties,Alternativer for flerspiller,Opcje Trybu Wielu Graczy,Opções de multijogador,,Opțiuni multiplayer,Настройки сетевой игры,Опције за више играча,Alternativ för flera spelare,Çok Oyunculu Seçenekler,Параметри багатокористувацької гри, +Input Options,OPTMNU_INPUT,,,,Vstupní zařízení,Input-indstillinger,Eingabeoptionen,,Enig-agordoj,Opciones de entrada (input),,Syöttöasetukset,Options d'entrée,Beviteli beállítások,Opzioni di ingresso,入力オプション,입력 옵션,In1voeropties,Alternativer for inndata,Opcje Sterowania,Opções de entrada,,Opțiuni de intrare,Настройки ввода,Опције уноса,Inmatningsalternativ,Girdi Seçenekleri,Параметри введення, +System Options,OPTMNU_SYSTEM,,,,Systém,Systemindstillinger,Systemoptionen,,Agordoj de la sistemo,Opciones del sistema,,Järjestelmäasetukset,Options du système,Rendszerbeállítások,Opzioni di sistema,システムオプション,시스템 옵션,Systeem Opties,Systemalternativer,Opcje Systemowe,Opções de sistema,,Opțiuni de sistem,Настройки системы,Системске опције,Systemalternativ,Sistem Seçenekleri,Системні налаштування, +Light Options,OPTMNU_LIGHT,,,,Osvětlení,Lysindstillinger,Beleuchtungsoptionen,,Lum-agordoj,Opciones de iluminación,,Valoasetukset,Options de lumière,Fénybeállítások,Opzioni luce,光源オプション,조명 옵션,Licht Opties,Alternativer for lys,Opcje Oświetlenia,Opções de iluminação,,Opțiuni de lumină,Настройки освещения,Опције осветљења,Alternativ för ljus,Işık Seçenekleri,Параметри освітлення, +Sprite Options,OPTMNU_SPRITE,,,,Sprity,Sprite-indstillinger,Spriteoptionen,,Agordoj de la mov-rastrumoj,Opciones de los «sprites»,,Sprite-asetukset,Options des sprites,Sprite beállítások,Opzioni Sprite,スプライトオプション,스프라이트 옵션,Sprite-opties,Sprite-alternativer,Opcje Sprite'ów,Opções de sprite,,Opțiuni Sprite,Настройки спрайтов,Сприте опције,Alternativ för sprite,Sprite Seçenekleri,Параметри спрайтів, +Coronas,GLPREFMNU_CORONAS,,,,Záře,Coronas,,,Lum-ampoloj,Focos de luz,,Coronat,Corons,Coronák,Corone,光冠,코로나,Corona's,Koronaer,Korony,,,Coronas,Короны,Цоронас,Koronor,Koronalar,Корони, +Appearance,DSPLYMNU_APPEARANCE,,,,Vzhled,Udseende,Spieldarstellung,,Aspekto,Apariencia,,Ulkonäkö,Apparence,Megjelenés,Aspetto,アピアランス,외형,Uiterlijk,Utseende,Wygląd,Aparência,,Aspect,Внешность,Изглед,Utseende,Görünüş,Зовнішній вигляд, +Advanced Display Options,DSPLYMNU_ADVANCED,,,,Grafika (pokročilé),Avancerede visningsindstillinger,Erweiterte Anzeigeoptionen,,Altnivelaj ekran-agordoj,Opciones avanzadas de visualización,,Näytön lisäasetukset,Options d'affichage avancées,Speciális megjelenítési beállítások,Opzioni di visualizzazione avanzate,高度なディスプレイオプション,고급 디스플레이 옵션,Geavanceerde Weergave Opties,Avanserte visningsalternativer,Zaawansowane Opcje Wyświetlania,Opções de vídeo avançadas,,Opțiuni avansate de afișare,Расширенные настройки экрана,Напредне опције приказа,Avancerade visningsalternativ,Gelişmiş Görüntüleme Seçenekleri,Додаткові параметри відображення, +,,IWAD/Game picker,,,,,,,,,,,,,,,,,,,,,,,,,,, +Select which game file to run.,PICKER_SELECT,,,,"Vyberte, jaký herní soubor spustit.","Vælg, hvilket spil du vil spille",Bitte wähle ein Spiel aus.,,Elektu kiun ludodosieron ruli.,,,Valitse suoritettava pelitiedosto.,Sélectionner le jeu à jouer,"Válassza ki, hogy melyik játékfájlt futtassa.",Selezionare il file di gioco da eseguire.,実行するゲームファイルを選択します。,실행할 게임 파일을 선택합니다.,Selecteer welk spel je wilt spelen,Velg hvilket spill du vil spille,"Wybierz, który plik gry uruchomić.",Selecione o arquivo de jogo para rodar.,,Selectați ce fișier de joc să rulați.,Выбор файла игры для запуска.,Изаберите коју датотеку игре желите да покренете.,Välj vilket spel du vill spela,Hangi oyunu oynayacağınızı seçin,Виберіть файл гри для запуску., +Play Game,PICKER_PLAY,,,,Hrát hru,Start spil,Spielen,,Ludi Ludon,,,Pelin pelaaminen,Démarrer le jeu,Játék lejátszása,Esegui gioco,ゲームをプレイする,게임 플레이,Spel starten,Start spill,Graj,Jogar,,Joacă jocul,Играть,Играј игру,Starta spel,Oyunu Başlat,Запустити гру, +Exit,PICKER_EXIT,,,,Odejít,Afslut,Verlassen,,Eliri,,,Poistu,Quitter,Kilépés,Esci,終了,종료,Verlaten,Avslutt,Wyjdź,Sair,,Ieșire,Выход,Изађи,Avsluta,Çıkış,Вихід, +General,PICKER_GENERAL,,,,Obecné,Generelt,Allgemein,,Ĝenerala,,,Yleistä,Général,Általános,Generale,一般,일반,Algemeen,Generelt,Ogólne,Geral,,,Общее,Генерал,Allmänt,Genel,Загальні, +Extra Graphics,PICKER_EXTRA,,,,Grafické doplňky,Ekstra grafik,Extragrafiken,,Ekstra Grafiko,,,Extra Graphics,Graphiques supplémentaires,Extra grafika,Grafica extra,追加グラフィックス,추가 그래픽,Extra afbeeldingen,Ekstra grafikk,Ekstra grafiki,Gráficos extras,,Grafică suplimentară,Доп. графика,Ектра Грапхицс,Extra grafik,Ekstra Grafikler,Додаткова графіка, +Fullscreen,PICKER_FULLSCREEN,,,,Přes celou obrazovku,Fuld skærm,Vollbild,,Plena ekrano,,,Koko näyttö,Plein écran,Teljes képernyő,Schermo intero,フルスクリーン,전체 화면,Volledig scherm,Fullskjerm,Pełny ekran,Tela cheia,,Ecran complet,Полный экран,Цео екран,Fullskärm,Tam Ekran,Повноекранний режим, +Disable autoload,PICKER_NOAUTOLOAD,,,,Zakázat autoload,Deaktiver autoload,Autoload deaktivieren,,Malvalidigi aŭtomatan ŝargon,,,Poista automaattinen lataus käytöstä,Désactiver le chargement automatique,Automatikus betöltés kikapcsolása,Disabilita il caricamento automatico,オートロードを無効にする,자동 로드 비활성화,Autoload uitschakelen,Deaktiver autolading,Wyłącz auto-ładowanie,Desativar autocarregamento,,Dezactivați încărcarea automată,Отключить автозагрузку,Онемогући аутоматско учитавање,Inaktivera autoload,Otomatik yükleme yok,Вимкнути автозавантаження, +Don't ask me again,PICKER_DONTASK,,,,Již se neptat,Spørg mig ikke igen,Nicht nochmal fragen,,Ne demandu min denove,,,Älä kysy uudestaan,Ne me demandez plus rien,Ne kérdezz újra,Non chiedermelo più,二度と聞くな,다시 묻지 마세요,Vraag me niet opnieuw,Ikke spør meg igjen,Nie pytaj ponownie,Não me pergunte de novo,,Nu mă mai întrebați din nou,Не спрашивать снова,Не питај ме поново,Fråga mig inte igen,Bir daha sorma.,Не запитуйте мене більше, +Lights,PICKER_LIGHTS,,,,Světla,Lys,Lichtdefinitionen,,Lumoj,,,Valot,Lumières,Fények,Luci,ライト,조명,Verlichting,Lysdefinisjoner,Oświetlenie,Luzes,,Lumini,Освещение,Светла,Definitioner av ljus,Işık tanımları,Освітлення, +Brightmaps,PICKER_BRIGHTMAPS,,,,,,,,Helomapoj,,,Brightmaps,Cartes lumineuses,Brightmaps,Mappe luminose,ブライトマップ,브라이트맵,Heldermaps,Lyskart,Mapowanie świateł,,,,Карты освещения,Бригхтмапс,Ljuskartor,Brightmaps,Яскраві карти, +Widescreen,PICKER_WIDESCREEN,,,,,,Breitbildunterstützung,,Larĝekrana,,,Laajakuva,Écran large,Szélesképernyő,Schermo largo,ワイドスクリーン,와이드스크린,Breedbeeld,Bredskjerm,Szeroki ekran,,,,Широкий экран,Широки екран,Bredbildsskärm,Geniş Ekran,Широкоформатний, +Additional Parameters:,PICKER_ADDPARM,,,,Dodatečné parametry:,Yderligere parametre:,Zusätzliche Parameter,,Aldonaj Parametroj,,,Lisäparametrit:,Paramètres supplémentaires :,További paraméterek:,Parametri aggiuntivi:,追加パラメータ,환영합니다: %s!,Extra parameters:,Ytterligere parametere:,Dodatkowe parametry:,Parâmetros adicionais:,,Parametrii suplimentari:,Доп. параметры:,Додатни параметри:,Ytterligare parametrar:,Ek Parametreler:,Додаткові параметри:, +Welcome to %s!,PICKER_WELCOME,,,,Vítejte v enginu %s!,Velkommen til %s!,Willkommen bei %s!,,Bonvenon en %s!,,,Tervetuloa %s!,Bienvenue à %s !,Üdvözöljük a %s!,Benvenuti a %s!,ようこそ: %s!,에 오신 것을 환영합니다!,Welkom bij %s!,Velkommen til %s!,Witaj w %s!,Boas vindas ao %s!,,Bine ați venit la %s!,Добро пожаловать в %s!,Добродошли у %s!,Välkommen till %s!,S'ye hoş geldiniz!,Ласкаво просимо до %s!, +Version %s,PICKER_VERSION,,,,Verze %s,,,,Versio %s,,,Versio %s,,Verzió %s,Versione %s,バージョン %s,버전 %s,Versie %s,Versjon %s,Wersja %s,Versão %s,,Versiunea %s,Версия %s,Верзија %s,,Sürüm %s,Версія %s, +Rendering API,PICKER_PREFERBACKEND,,,,Renderovací API,,Render API,,Bildigado de API,API de renderizado,,Renderöinti API,API de rendu,Renderelő API,API di rendering,優先レンダリングAPI,기본적인 API 랜더링,,,API renderowania,API de renderização,,API Video Preferat,API для рендеринга,АПИ приказивања,API för rendering,,API для візуалізації, +Game,PICKER_TAB_PLAY,,,,Hra,Spil,Spiel,,Ludo,Juego,,Peli,Jeu,Játék,Gioco,ゲーム,게임,Spel,Spill,Gra,Jogo,,Joc,Игра,Игра,Spel,Oyun,Гра, +Enable this controller,JOYMNU_JOYENABLE,Option to enable or disable individual controllers/joysticks when configuring it in the Controller Options menu,,,Povolit tento ovladač,Aktivér denne controller,Diesen Controller aktivieren,,Ŝalti ĉi tiun ludregilon,Habilitar este controlador,,Aktivoi tämä ohjain,Activer ce contrôleur,Engedélyezze ezt a vezérlőt,Abilitare questo controllore,このコントローラーを有効にする,이 컨트롤러 활성화,Deze controller inschakelen,Aktiver denne kontrolleren,,,,Activați acest controler,Включить этот контроллер,Омогућите овај контролер,Aktivera denna styrenhet,Bu denetleyiciyi etkinleştirin,Увімкніть цей контролер, +Open Main Menu,CNTRLMNU_OPEN_MAIN,,,,Otevřít hlavní menu,Åbn hovedmenuen,Hauptmenü öffnen,,Malfermi Ĉefan Menuon,Abrir el menú principal,,Avaa päävalikko,Ouvrir le menu principal,Főmenü megnyitása,Aprire il menu principale,メインメニューを開く,메인 메뉴 열기,Hoofdmenu openen,Åpne hovedmenyen,,,,Deschideți meniul principal,Открыть главное меню,Отворите главни мени,Öppna huvudmenyn,Ana Menüyü Aç,Відкрити головне меню, \ No newline at end of file diff --git a/wadsrc/static/language.csv b/wadsrc/static/language.csv index c1179d3746..080a605b28 100644 --- a/wadsrc/static/language.csv +++ b/wadsrc/static/language.csv @@ -1,15 +1,16 @@ -default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,tr -,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,, -Press a key.,PRESSKEY,,,,Stiskni klávesu.,Tryk på en tast.,Drücke eine Taste,Πάτα οποιοδήποτε πλήκτρο.,Premu klavon.,Presiona una tecla.,,Paina jotain näppäintä.,Appuyez sur une touche.,Nyomjon meg egy gombot.,Premi un tasto.,何かキーを押せ,키를 누르시오.,Druk op een toets.,Trykk på en tast.,Wciśnij dowolny klawisz.,Aperte uma tecla.,Carrega numa tecla qualquer.,Apasă o tastă.,Нажмите любую клавишу.,Притисните било који тастер.,Bir tuşa bas. -A secret is revealed!,SECRETMESSAGE,,,,Nalezl[@ao_cs] jsi skrýš!,En hemmelighed bliver afsløret!,Ein Geheimnis wurde enthüllt!,Ένα μυστικό αποκαλύφθηκε!,Sekretejo estas malkaŝita!,¡Se ha revelado un secreto!,,Sala löydetty!,Vous avez découvert un secret!,Egy rejtekhely feltárva!,È stato svelato un segreto! ,シークレットを解き明かした!,비밀 발견!,Een geheim is onthuld!,En hemmelighet er avslørt!,Znaleziono sekret!,Segredo revelado!,,Ai găsit un secret!,Обнаружен тайник!,Откривена тајна!,Bir sır açığa çıkıyor! +default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,sv,tr,uk +,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,,,, +Press a key.,PRESSKEY,,,,Stiskni klávesu.,Tryk på en tast.,Drücke eine Taste,Πάτα οποιοδήποτε πλήκτρο.,Premu klavon.,Presiona una tecla.,,Paina jotain näppäintä.,Appuyez sur une touche.,Nyomjon meg egy gombot.,Premi un tasto.,何かキーを押せ,키를 누르시오.,Druk op een toets.,Trykk på en tast.,Wciśnij dowolny klawisz.,Aperte uma tecla.,Carrega numa tecla qualquer.,Apasă o tastă.,Нажмите любую клавишу.,Притисните било који тастер.,Tryck på en tangent.,Bir tuşa bas.,Натисніть будь яку клавішу. +A secret is revealed!,SECRETMESSAGE,,,,Nalezl[@ao_cs] jsi skrýš!,En hemmelighed bliver afsløret!,Ein Geheimnis wurde enthüllt!,Ένα μυστικό αποκαλύφθηκε!,Vi trovis sekretejon!,¡Lugar secreto descubierto!,,Sala löydetty!,Vous avez découvert un secret!,Egy rejtekhely feltárva!,È stato svelato un segreto! ,シークレットを解き明かした!,비밀 발견!,Een geheim is onthuld!,En hemmelighet er avslørt!,Znaleziono sekret!,Segredo revelado!,,Ai găsit un secret!,Обнаружен тайник!,Откривена тајна!,En hemlighet avslöjas!,Bir sır açığa çıkıyor!,Знайдено схованку! "Useless mode ON. ",D_DEVSTR,,,,Zbytečný režim ZAP.,Ubrugelig tilstand slået til.,Nutzloser Modus EIN.,Άχρηστη λειτουργία είναι ΑΝΟΙΧΤΗ,Senutila reĝimo ŜALTITA.,"Modo inútil ACTIVADO. ",,Hyödytön tila PÄÄLLÄ.,"Mode inutile ON. ",Haszontalan mód BE.,"Modalità inutile ATTIVATA. ",このモードは使わないでおけ,쓸모없는 모드 켬.,Nutteloze modus AAN.,"Ubrukelig modus PÅ. ",Tryb bezużyteczny WŁĄCZONY.,"Modo inútil ATIVADO. -",,Modul inutil ACTIVAT.,Бесполезный режим ВКЛЮЧЁН.,Програмерски режим УКЉУЧЕН.,"Yararsız mod AÇIK. -" +",,Modul inutil ACTIVAT.,Бесполезный режим ВКЛЮЧЁН.,Програмерски режим УКЉУЧЕН.,"Oanvändbart läge på. +","Yararsız mod AÇIK. +",Увімкнено режим розробника "Are you sure you want to quit this great game?",QUITMSG,,,,"Jsi si jist@[adj_cs], že chceš opustit tuto skvělou hru?","Er du sikker på, at du vil forlade dette fantastiske spil?","Willst du dieses großartige Spiel @@ -24,7 +25,7 @@ met dit geweldige spel?",Er du sikker på at du vil avslutte dette flotte spille wyjść z tej świetnej gry?","Deseja mesmo sair deste excelente jogo?","Tem a certeza que deseja sair deste excelente jogo?",Ești sigur că vrei să ieși din acest joc grozav?,"Ты действительно хочешь выйти -из этой замечательной игры?",Желиш ли заиста да изађеш из ове чудесне игре?,Bu harika oyunu bırakmak istediğine emin misin? +из этой замечательной игры?",Желиш ли заиста да изађеш из ове чудесне игре?,Är du säker på att du vill sluta med detta fantastiska spel?,Bu harika oyunu bırakmak istediğine emin misin?,Ти дійсно хочеш вийти з цієї прекрасної гри? "You can't do load while in a net game! Press a key.",LOADNET,"In some languages, it may make more sense to translate “Press a key” as “Press any key.”",,,"Během síťové hry nelze načíst hru! @@ -69,7 +70,10 @@ Apasă orice tastă.","Невозможно загрузить сохранен Нажмите любую клавишу.","Не можете да учитате чување током мрежне игре! -Притисните тастер.",Bir ağ oyunundayken yükleme yapamazsınız! Bir tuşa basın. +Притисните тастер.","Du kan inte göra lastning när du är i ett nätspel! +Tryck på en tangent.",Bir ağ oyunundayken yükleme yapamazsınız! Bir tuşa basın.,"Неможливо завантажити збереження під час мережевої гри! + +Натисніть будь яку клавішу." "You can't quickload during a netgame! Press a key.",QLOADNET,,,,"Během síťové hry nelze rychle načíst hru! @@ -114,8 +118,11 @@ Apasă orice tastă.","Невозможно загрузить быстрое с Нажмите любую клавишу.","Не можете да учитате брзо чување током мрежне игре! -Притисните тастер.","Bir ağ oyunu sırasında hızlı yükleme yapamazsınız! -Bir tuşa basın." +Притисните тастер.","Du kan inte snabblasta under ett nätspel! +Tryck på en tangent.","Bir ağ oyunu sırasında hızlı yükleme yapamazsınız! +Bir tuşa basın.","Неможливо завантажити швидке збереження під час мережевої гри! + +Натисніть будь яку клавішу." "You haven't picked a quicksave slot yet! Press a key.",QSAVESPOT,,,,"Ještě nebyl vybrán slot pro rychlé uložení! @@ -155,12 +162,15 @@ Aperte uma tecla.","Você ainda não escolheu um slot de quicksave! Carrega numa tecla qualquer.","Nu ai ales un slot pentru încărcare rapidă încă! -Apasă orice tastă.","Не выбран слот быстрого сохранения! +Apasă orice tastă.","Не выбрана ячейка быстрого сохранения! Нажмите любую клавишу.","Нисте још изабрали слот за брзо чување! -Притисните тастер.","Henüz bir hızlı kaydetme yuvası seçmediniz! -Bir tuşa basın." +Притисните тастер.","Du har inte valt en plats för snabbsparning ännu! +Tryck på en tangent.","Henüz bir hızlı kaydetme yuvası seçmediniz! +Bir tuşa basın.","Не вибраний слот для швидкого збереження! + +Натисніть будь яку клавішу." "You can't start a new game while in a network game. @@ -171,7 +181,7 @@ mens du er i et netspil. Tryk på en tast.",Du kannst während eines Netzwerkspiels kein neues Spiel starten.,"Δέν μπορείς να ξεκινήσεις ένα νέο παιχνίδι ενώ εισαι σε ένα δικτυακό παιχνίδι. -Πάτα οποιδήποτε πλήκτρο.","Vi ne povas lanĉi novan ludon dum retludo. +Πάτα οποιδήποτε πλήκτρο.","Vi ne povas lanĉi novan ludadon dum retludo. Premu klavon.","No puedes iniciar una nueva partida mientras estás jugando en línea. @@ -214,8 +224,11 @@ Apasă orice tastă.","Невозможно начать новую игру Нажмите любую клавишу.","Не можете да започнете нову игру током мрежне игре. -Притисните тастер.","Bir ağ oyunundayken yeni bir oyun başlatamazsınız. -Bir tuşa basın." +Притисните тастер.","Du kan inte starta ett nytt spel när du är i ett nätspel. +Tryck på en tangent.","Bir ağ oyunundayken yeni bir oyun başlatamazsınız. +Bir tuşa basın.","Ви не можете розпочати нову гру під час мережевої гри. + +Натисніть будь яку клавішу." "Are you sure? This skill level isn't even remotely fair. @@ -274,10 +287,14 @@ Apasă Y sau N.","Уверены? Этот уровень сложности Нажмите Y или N.","Сигурни сте? Овај ниво тежине није нимали фер. -Притисните Y или N.","Emin misiniz? Bu beceri seviyesi +Притисните Y или N.","Är du säker? Den här färdighetsnivån +är inte ens tillnärmelsevis rättvis. +Tryck på Y eller N.","Emin misiniz? Bu beceri seviyesi hiç adil değil. -Y veya N'ye basın." +Y veya N'ye basın.","Впевнений? Цей рівень складності навіть близько не стоїть до чесного. + +Натисніть Y або N." "This is the shareware version of Doom. You need to order the entire trilogy. @@ -300,11 +317,11 @@ Drücke eine Taste","Αυτή είναι η Shareware έκδοση του Doom. Πάτα οποιδήποτε πλήκτρο.","Ĉi tiu estas la propagaĵa versio de Doom. -Vi bezonas mendi la tutan trilogion. +Vi bezonas mendi la plenan version (Ultimate). Premu klavon.","Esta es la versión demo (shareware) de Doom. -Necesitas adquirir la trilogía completa. +Necesitas adquirir la versión completa (Ultimate). Presiona una tecla.",,"Tämä on Doomin shareware-versio. @@ -361,7 +378,12 @@ Apasă orice tastă.","Это условно-бесплатная версия D Потребно је да наручите целу трилогију. -Притисните било који тастер.",Bu Doom'un shareware versiyonu. Tüm üçlemeyi sipariş etmeniz gerekiyor. Bir tuşa bas. +Притисните било који тастер.","Detta är sharewareversionen av Doom. Du måste beställa hela trilogin. +Tryck på en tangent.",Bu Doom'un shareware versiyonu. Tüm üçlemeyi sipariş etmeniz gerekiyor. Bir tuşa bas.,"Це демонстраційна версія Doom. + +Вам потрібно купити повну версію. + +Натисніть будь яку клавішу." "You can't end a netgame! Press a key.",NETEND,,,,"Síťovou hru nelze ukončit! @@ -404,7 +426,10 @@ Apasă orice tastă.","Невозможно закончить сетевую и Нажмите любую клавишу.","Не можете да завршите мрежну игру! -Притисните било који тастер.",Net oyununu bitiremezsin! Bir tuşa basın. +Притисните било који тастер.","Du kan inte avsluta ett nätspel! +Tryck på en tangent.",Net oyununu bitiremezsin! Bir tuşa basın.,"Ви не можете завершити мережеву гру! + +Натисніть будь яку клавішу." "Are you sure you want to end the game? Press Y or N.",ENDGAME,,,,"Opravdu si přeješ ukončit hru? @@ -447,19 +472,22 @@ Apasă Y sau N.","Вы действительно хотите закончит Нажмите Y или N.","Желите ли сигурно да завршите игру? -Притисните Y или N.",Oyunu bitirmek istediğinizden emin misiniz? Y veya N'ye basın. +Притисните Y или N.","Är du säker på att du vill avsluta spelet? +Tryck på Y eller N.",Oyunu bitirmek istediğinizden emin misiniz? Y veya N'ye basın.,"Ви дійсно хочете завершити гру? + +Натисніть Y або N." Are you sure you want to quit?,RAVENQUITMSG,,,,Přeješ si odejít?,"Er du sikker på, at du vil holde op?","Bist du dir sicher, dass du gehen willst?","Είσαι σίγουρος ότι θέλεις να φύγεις? -","Ĉu vi certas, ke vi volas forlasi?",¿Estás segur@[ao_esp] de que quieres salir?,,Haluatko varmasti lopettaa?,Êtes vous sûr de vouloir quitter ?,Biztosan ki akarsz lépni?,Sei sicuro di voler abbandonare?,本当に終了するのか?,정말 종료하시겠습니까?,Weet je zeker dat je wilt stoppen?,Er du sikker på at du vil avslutte?,Czy jesteś pewien że chcesz wyjść?,Deseja mesmo sair?,Tens a certeza que queres sair?,Ești sigur că vrei să ieși din joc?,Вы действительно желаете выйти?,Желите ли сигурно да изађете?,Çıkmak istediğinizden emin misiniz? -Only available in the registered version,SWSTRING,,heretic,,Dostupné pouze v registrované verzi,Kun tilgængelig i den registrerede version,Nur in der registrierten Version verfügbar,Μόνο διαθέσιμο στήν εχγραμμένη έκδοση.,Nur havebla en la komercaĵa versio,Solo disponible en la versión registrada,,Käytettävissä vain rekisteröidyssä versiossa,Disponible uniquement dans la version enregistrée,Csak a teljes verzióban érhető el,Disponibile solamente nella versione registrata,製品版でのみ可能だ。,정품 버전에서만 가능합니다,Alleen beschikbaar in de geregistreerde versie,Bare tilgjengelig i den registrerte versjonen,Dostępne tylko w zarejestrowanej wersji,Disponível somente na versão registrada,Apenas disponível na versão registrada,Disponibil doar în versiunea înregistrată.,Эпизод доступен только в полной версии,Само могуће у регистрованој верзији,Sadece kayıtlı sürümde mevcuttur -(Press Y to quit),DOSY,,,,(Stiskni Y pro odchod),(Tryk på Y for at afslutte),(Drücke Y zum Verlassen.),(Πάτα Y για να φύγεις),(Premu Y por forlasi),(Presiona Y para salir),,(Paina Y lopettaaksesi),(Appuyez sur Y pour revenir à votre OS.),(Nyomj Y-t a kilépéshez.),(Premi Y per uscire),(Y で終了),(Y을 누르시면 종료합니다),(Druk op Y om te stoppen),(Trykk Y for å avslutte),"(Wciśnij Y, aby wyjść)",(Aperte Y para sair),(Carrega Y para sair),(Apasă Y pentru a ieși),"(нажмите Y, чтобы выйти)",(Притисните Y да завршите),(Çıkmak için Y'ye basın) -,,Quit messages,,,,,,,,,,,,,,,,,,,,,,,, +","Ĉu vi certas, ke vi volas forlasi?",¿Estás segur@[ao_esp] de que quieres salir?,,Haluatko varmasti lopettaa?,Êtes vous sûr de vouloir quitter ?,Biztosan ki akarsz lépni?,Sei sicuro di voler abbandonare?,本当に終了するのか?,정말 종료하시겠습니까?,Weet je zeker dat je wilt stoppen?,Er du sikker på at du vil avslutte?,Czy jesteś pewien że chcesz wyjść?,Deseja mesmo sair?,Tens a certeza que queres sair?,Ești sigur că vrei să ieși din joc?,Вы действительно желаете выйти?,Желите ли сигурно да изађете?,Är du säker på att du vill avsluta?,Çıkmak istediğinizden emin misiniz?,Ви дійсно хочете вийти? +Only available in the registered version,SWSTRING,,heretic,,Dostupné pouze v registrované verzi,Kun tilgængelig i den registrerede version,Nur in der registrierten Version verfügbar,Μόνο διαθέσιμο στήν εχγραμμένη έκδοση.,Nur havebla en la komercaĵa versio,Solo disponible en la versión registrada,,Käytettävissä vain rekisteröidyssä versiossa,Disponible uniquement dans la version enregistrée,Csak a teljes verzióban érhető el,Disponibile solamente nella versione registrata,製品版でのみ可能だ。,정품 버전에서만 가능합니다,Alleen beschikbaar in de geregistreerde versie,Bare tilgjengelig i den registrerte versjonen,Dostępne tylko w zarejestrowanej wersji,Disponível somente na versão registrada,Apenas disponível na versão registrada,Disponibil doar în versiunea înregistrată.,Эпизод доступен только в полной версии,Само могуће у регистрованој верзији,Endast tillgänglig i den registrerade versionen,Sadece kayıtlı sürümde mevcuttur,Доступно только в полной версии +(Press Y to quit),DOSY,,,,(Stiskni Y pro odchod),(Tryk på Y for at afslutte),(Drücke Y zum Verlassen.),(Πάτα Y για να φύγεις),(Premu Y por forlasi),(Presiona Y para salir),,(Paina Y lopettaaksesi),(Appuyez sur Y pour revenir à votre OS.),(Nyomj Y-t a kilépéshez.),(Premi Y per uscire),(Y で終了),(Y을 누르시면 종료합니다),(Druk op Y om te stoppen),(Trykk Y for å avslutte),"(Wciśnij Y, aby wyjść)",(Aperte Y para sair),(Carrega Y para sair),(Apasă Y pentru a ieși),"(нажмите Y, чтобы выйти)",(Притисните Y да завршите),(Tryck på Y för att avsluta),(Çıkmak için Y'ye basın),(Натисніть Y для виходу) +,,Quit messages,,,,,,,,,,,,,,,,,,,,,,,,,, "Please don't leave, there's more demons to toast!",QUITMSG1,,,,"Nenechávej mě tu, je tu víc démonů k vymletí!","Du må ikke gå, der er flere dæmoner at stege!!","Bitte gehe nicht, es gibt noch mehr Dämonen zu erlegen.","Παρακαλώ μη φύγεις, υπάρχουνε περισσότεροi δαίμονες να ψήσεις!","Bonvolu ne foriri, estas pliaj -rostindaj demonoj!","¡Por favor no te vayas, que -hay más demonios para freír!",,Älä lähde; demoneita on vielä kärvennettävänä!,"Ne partez pas, il ya encore +rostindaj demonoj!","¡No te vayas, que aún quedan +demonios para freír!",,Älä lähde; demoneita on vielä kärvennettävänä!,"Ne partez pas, il ya encore des démons a buter!","Kérlek ne lépj le, sok démon vár még arra, hogy felaprítsd!","Per favore non uscire, ci sono altri demoni da ammazzare!","離れないでくれ! まだ獲物が残っているんだ!","부디 나가지 말아줘, 아직 죽여야 할 악마들이 남아있단 말이야!","Ga alsjeblieft niet weg, er zijn meer demonen te roosteren!","Vennligst ikke gå, det er flere demoner å skåle!","Proszę, nie odchodź, jest więcej @@ -467,7 +495,7 @@ demonów do stostowania!","Por favor, não vá embora. Tem mais demônios para torrar!","Por favor não te vás embora, há mais demônios para matar!","Te rog nu ieși, mai sunt demoni care trebuie prăjiți!","Пожалуйста, не уходи, тут ещё полно демонов для поджарки!","Молим те, не одлази! -Има још демона да се побије!","Lütfen gitmeyin, kadeh kaldıracak daha çok iblis var!" +Има још демона да се побије!","Lämna inte spelet, det finns fler demoner att skåla för!","Lütfen gitmeyin, kadeh kaldıracak daha çok iblis var!","Будь ласка, не йди - тут ще купа демонів!" "Let's beat it -- this is turning into a bloodbath!",QUITMSG2,,,,"Utečme -- začíná tu téct krev!","Lad os smutte - det her er @@ -481,14 +509,14 @@ um banho de sangue!","Falando a sério -- Isto está se a tornar num banho de sangue!","S-o lăsăm baltă -- situația degenerează într-o baie de sânge!","Давай покончим с этим — оно превращается в кровавую баню!","Хајде, бриши одавде -ако ти је ово одвећ крваво!","Hadi gidelim, ortalık kan gölüne dönüyor!" +ако ти је ово одвећ крваво!",Vi sticker - det här håller på att bli ett blodbad!,"Hadi gidelim, ortalık kan gölüne dönüyor!","Споримо, що ця кривава баня тобі не по зубах!?" "I wouldn't leave if I were you. DOS is much worse.",QUITMSG3,,,,"Být tebou, neodcházel bych. DOS je mnohem horší.","Jeg ville ikke gå, hvis jeg var dig. DOS er meget værre.","Ich würde nicht gehen, wenn ich du wäre. DOS ist viel übler.","Δέν θα έφευγα αμμα είμουνα εσύ. -Το DOS είναι πολύ χυρότερο.","Mi ne forirus, se mi estus vi. -DOS estas multe pli malbona.","No me iría si fuera tú. +Το DOS είναι πολύ χυρότερο.","Mi ne forirus, se mi estus vi: +MS-DOS estas multe pli malbona.","No me iría si fuera tú: MS-DOS es mucho peor.",,Sinuna en lähtisi. DOS on paljon pahempi.,"Je ne quitterais pas si j'étais vous. Votre OS est bien pire.","A helyedben nem lépnék ki. A DOS sokkal rosszabb.","Non uscirei se fossi in te. @@ -499,12 +527,12 @@ O DOS é bem pior.","Se fosse a ti não saia daqui. O DOS é bem pior.","Eu n-aș pleca în locul tău - sistemul DOS e mult mai rău.","На твоём месте я бы не уходил. DOS намного скучнее.","Да сам на твом месту, не бих одлазио. -DOS је много досаднији.",Yerinde olsam gitmezdim. DOS çok daha kötü. +DOS је много досаднији.",Jag skulle inte lämna om jag var du. DOS är mycket värre.,Yerinde olsam gitmezdim. DOS çok daha kötü.,Я б не йшов на твоєму місці. DOS значно нудніший. "You're trying to say you like DOS better than me, right?",QUITMSG4,,,,"Chceš mi říct, že máš radši DOS než mě?","Du prøver at sige, at du bedre kan lide DOS end mig, ikke?","Willst du sagen, dass DOS -besser ist als ich?","Προσπαθείς να πείς οτι το DOS είναι καλήτερο απο εμένα, σωστά?","Vi provas diri, ke DOS +besser ist als ich?","Προσπαθείς να πείς οτι το DOS είναι καλήτερο απο εμένα, σωστά?","Vi provas diri, ke MS-DOS estas pli bona ol mi, ĉu?","Estás tratando de decir que el MS-DOS es mejor que yo, ¿cierto?",,"Yritätkö sanoa pitäväsi DOSista enemmän kuin minusta, niinkö?","Vous essayez de dire que vous aimez DOS mieux que moi, pas vrai?","Azt akarod mondani, hogy @@ -515,14 +543,14 @@ ode mnie, prawda?","Tá querendo dizer que você gosta mais do DOS do que eu, é isso?","Estás a tentar dizer que gostas mais do do DOS do que eu, é isso?","Încerci să spui că-ți place de sistemul DOS mai mult decât de mine, așa-i?","Ты хочешь сказать, что DOS тебе нравится больше, чем я, а?","Више ти допада DOS -него ја, је ли?","DOS'u benden daha çok sevdiğini söylemeye çalışıyorsun, değil mi?" +него ја, је ли?","Du försöker säga att du gillar DOS bättre än mig, eller hur?","DOS'u benden daha çok sevdiğini söylemeye çalışıyorsun, değil mi?","Хочеш сказати, що DOS цікавіший за мене, так?" "Don't leave yet -- there's a demon around that corner!",QUITMSG5,,,,"Ještě nechoď -- tam za rohem je démon!","Du må ikke gå endnu - der er en dæmon rundt om det hjørne!","Bitte gehe noch nicht - hinter der Ecke da lauert ein Dämon.","Μη φύγεις ακόμα, είναι ένας δαίμονας πίσω απο αυτή τι γονία!","Ne foriru ankoraŭ, estas -demono ĉirkaŭ tiu angulo!","No te vayas aún, ¡que hay un -demonio cerca de esa esquina!",,Älä lähde vielä -- tuon kulman takana on demoni!,"Ne partez pas encore! Il y a +demono ĉirkaŭ tiu angulo!","¡No te vayas, que aún hay +demonios en la costa!",,Älä lähde vielä -- tuon kulman takana on demoni!,"Ne partez pas encore! Il y a un démon dans le coin!",Még ne menj -- a sarkon túl még vár rád egy démon!,"Non abbandonare ora - c'è un demone dietro l'angolo!","待ってくれ!まだあそこの角に デーモンが残っているんだ!",나가지 마- 저 구석에 악마가 숨어있다고!,Ga nog niet weg - er is een demoon hier om de hoek!,Ikke gå ennå. Det er en demon rundt hjørnet.,"Nie odchodź jeszcze -- demon czai @@ -530,7 +558,7 @@ się w tamtym zaułku!","Não vá embora ainda, tem um demônio naquele canto!","Não te vás embora agora -- Está um demônio ao virar da esquina!",Nu pleca încă -- e un demon după colțul acela!,"Не уходи! За тем углом притаился ещё один монстр!","Немој да одеш -- -иза угла има још један демон!","Hemen gitme, şu köşede bir iblis var!" +иза угла има још један демон!",Gå inte än -- det finns en demon runt hörnet!,"Hemen gitme, şu köşede bir iblis var!",Зачекай! Не йди - тут за куточком сховався ще один демон! "Ya know, next time you come in here I'm gonna toast ya.",QUITMSG6,,,,"Tak hele, až se vrátíš, dostanu tě.","Ved du hvad, næste gang du @@ -546,19 +574,20 @@ stostuje cię.","Na próxima vez que você vier aqui, eu vou te detonar em pedaços.","Sabes, da próxima vez que vieres para aqui vou te fazer explodir em bocadinhos.","Să știi, data viitoare când treci pe-aici o să te prăjesc!","Знаешь, по возвращении тебя будут ждать большие неприятности.","Знаш, по повратку ће те -чекати велике невоље.","Biliyor musun, bir dahaki sefere buraya geldiğinde seni tost yapacağım." +чекати велике невоље.",Nästa gång du kommer hit ska jag skåla för dig.,"Biliyor musun, bir dahaki sefere buraya geldiğinde seni tost yapacağım.","Шоб знав, коли повернешся - я намилю тобі шию." Go ahead and leave. see if I care.,QUITMSG7,,,,"Jen do toho, odejdi; schválně, jestli mi to bude jedno.",Gå bare. Se om jeg er ligeglad.,"Dann geh doch! Interessiert mich nicht.","Φύγε, δες αν νιάζομαι.",Ja foriru. Mi fajfas pri tio.,Ya vete. A ver si me importa.,,"Ole hyvä vain ja lähde. Arvaa, välitänkö.","Allez y, partez, allez voir si j'y suis.","Menj nyugodtan, nem mintha bárkit érdekelne.","Esci pure, sai che mi frega.",置いて行っちゃうんだ。勝手にしろ。,그럼 나가버려. 난 신경 안 써.,"Ga maar, eens kijken of het me interesseert.",Bare gå. Jeg bryr meg ikke.,"No dalej, odejdź. Zobaczymy czy -mnie to obchodzi.","Vai, pode ir embora. Tô nem aí.",Vai te em embora. Vê lá se eu quero saber.,"Hai, pleacă, vezi dacă-mi pasă.","Давай, уходи. Мне совершенно всё равно.","Хајде, одлази. Уопште ме није брига.",Devam et ve git. Bakalım umurumda olacak mı? +mnie to obchodzi.","Vai, pode ir embora. Tô nem aí.",Vai te em embora. Vê lá se eu quero saber.,"Hai, pleacă, vezi dacă-mi pasă.","Давай, уходи. Мне совершенно всё равно.","Хајде, одлази. Уопште ме није брига.",Gå du bara och se om jag bryr mig.,Devam et ve git. Bakalım umurumda olacak mı?,"Давай, йди... ніби мені не все одно." "You want to quit? Then, thou hast lost an eighth!",QUITMSG8,More info here.,,,"Chceš odejít? Nuže, přišel jsi o přízeň boží!","Vil du gå? Har du mistet forstanden?","Du willst gehen? Hast du den Verstand verloren?","Θέλεις να φύγεις ? Τότε, έχασες ένα έκτο!","Ĉu vi volas forlasi? -Tiuokaze, vi perdos okonon!","¿Quieres salir? Entonces, -¡habrás perdido una octava!",,"Haluat siis lopettaa? +Tiuokaze, vi perdos okonon!","Salir del juego: +golpe de remo.","Si intentas salir +del juego, hay tabla.","Haluat siis lopettaa? Oletko menettänyt järkesi?","Vous voulez vraiment quitter? Vous avez vraiment les fils qui se croisent!","Ki akarsz lépni? Akkor beszolgáltatik a Te vagyonod nyolcada!","Vuoi uscire? @@ -568,7 +597,7 @@ Só pode ter perdido a cabeça!","Queres sair? Só podes ter perdido a cabeça!","Vrei să ieși? Atunci, ai pierdut o virtute!","Всерьёз задумываешь выйти? Тем самым ты упустил что-то важное!","Озбиљно желиш да изађеш? -Није то нимало паметно!",Bırakmak mı istiyorsun? O zaman sekizde birini kaybettin! +Није то нимало паметно!",Vill du sluta? Då har du förlorat en åttondel!,Bırakmak mı istiyorsun? O zaman sekizde birini kaybettin!,Вийти? ВИЙТИ?! Це так не працює. "Don't go now, there's a dimensional shambler waiting at the DOS prompt!",QUITMSG9,A “dimensional shambler” is a creature appearing in the works of H. P. Lovecraft.,,,"Teď neodcházej, na příkazové řádce @@ -577,7 +606,7 @@ dimensionsødelægger der venter på DOS-prompten!","Bitte geh noch nicht! An der Eingabeaufforderung wartet ein Dimensionszerstörer auf dich!","Μη πας τώρα, υπάρχει ένας διαστατικός τρίκλιστης ο οπίος περιμένει στη DOS γραμμή εντολών!","Ne foriru, dimensia malordo -atendas ĉe la DOS-konzolo!","No te vayas, ¡hay un desorden +atendas ĉe la DOS-konzolo!","¡No te vayas, que hay un vagabundo dimensional en la consola de DOS!",,Älä mene nyt; DOS-kehotteella väijyy hirviö toisesta ulottuvuudesta!,"Ne partez pas maintenant, il y a un monstre interdimensionnel qui dans attend dans votre OS!","Ne menj most, egy dimenzióforgató @@ -595,14 +624,14 @@ te așteaptă la promptul DOS!","Не уходи сейчас, межпрост бродяга поджидает в DOS!","Немој да одеш! Међудимензионално чудовиште -чека код DOS промпта!","Şimdi gitme, DOS komut isteminde bekleyen boyutsal bir shambler var!" +чека код DOS промпта!","Gå inte nu, det finns en dimensionell shambler som väntar vid DOS-prompten!","Şimdi gitme, DOS komut isteminde bekleyen boyutsal bir shambler var!","Підіжди трохи, між строками DOS причаївся міжпросторовий шамблер!" "Get outta here and go back to your boring programs.",QUITMSG10,,,,"Vypadni odsud a vrať se ke svým nudným programům.","Forsvind herfra og gå tilbage til dine kedelige programmer.","Dann geh doch zurück zu deinen langweiligen Programmen",Βγές απο'δω και πήγαινε πίσω στα βαρετά προγράματα σου.,"Forigu kaj reiru al viaj -enuigaj programoj.","Lárgate de aquí y vuelve -a tus aburridos programas.",,Ala laputtaa takaisin tylsien ohjelmiesi pariin.,"Tirez vous de là et retournez +enuigaj programoj.","Ya vete y vuelve a tus +programitas aburridos.",,Ala laputtaa takaisin tylsien ohjelmiesi pariin.,"Tirez vous de là et retournez à vos programmes ennuyeux.","Húzz innen, és menj vissza az unalmas programjaidhoz.","Vai fuori di qui e torna ai tuoi noiosi programmi.","早く出ていって、いつものつまらない @@ -612,14 +641,14 @@ os seus programas chatos.","Desaparece daqui e volta para os teus programas chatos.","Cară-te de aici și întoarce-te la programele tale plictisitoare.","Вот и убирайся отсюда к своим скучным программам.","Губи се одавде -својим досадним програмима.",Git buradan ve sıkıcı programlarına geri dön. +својим досадним програмима.",Försvinn härifrån och gå tillbaka till dina tråkiga program.,Git buradan ve sıkıcı programlarına geri dön.,"Ну і котись звідсіль, до своїх марудних програм." "If I were your boss, I'd deathmatch ya in a minute!",QUITMSG11,,,,"Být tvým šéfem, v deathmatchi bych tě zabil do minuty!","Hvis jeg var din chef, ville jeg slå dig ihjel på et minut!","Wenn ich dein Boss wäre, würde ich dich im Deathmatch in einer Minute schlagen.","Άμα ήμουν το αφεντικό σου, θα σε προκαλούσα σε ενα deathmatch αυτη τη στιγμή!","Se mi estus via ĉefo, mi -mortomaĉus vin post minuto!","Si yo fuera tu jefe, ¡te golpearía -a muerte dentro de un minuto!",,"Jos oisin pomosi, lyttäisin sut kuolonottelussa minuutissa!","Si j'étais votre patron, je vous +mortomaĉus vin post minuto!","Si yo fuera tu jefe, te golpearía +a muerte dentro de un minuto.",,"Jos oisin pomosi, lyttäisin sut kuolonottelussa minuutissa!","Si j'étais votre patron, je vous collerai un Deathmatch dans la minute!","Ha én lennék a főnököd, lejátszanék egy Deathmatch-et veled perceken belül!","Se fossi il tuo capo, ti batterei a un deathmatch in un minuto!","もし私が君の上司なら、すぐにでも デスマッチを始める所だぞ!","만약 내가 너의 상사였다면, 지금 당장 데스매치를 열었을 거다!","Als ik je baas was, zou ik je in een minuut doodmaken!","Hvis jeg var sjefen din, ville jeg dødsmatche deg med en gang!","Gdybym był twoim szefem, @@ -628,7 +657,7 @@ para um mata-mata rapidinho!","Se eu fosse o teu chefe, lutava num deathmatch contigo agora mesmo!","Dacă eram șeful tău, te-aș fi luat la o rundă de deathmatch!","Будь я твоим боссом, я бы разобрался бы с тобой за минуту!","Да сам твој шеф, -средио бих те за један минут!","Patronun olsaydım, seni bir dakika içinde öldürürdüm!" +средио бих те за један минут!",Om jag var din chef skulle jag döda dig på en minut!,"Patronun olsaydım, seni bir dakika içinde öldürürdüm!",Був би я твоїм боссом - розніс у дедматчі за хвилину! "Look, bud. you leave now and you forfeit your body count!",QUITMSG12,,,,"Hele, kámo, když teď odejdeš, přijdeš o svoje skóre!","Så, kammerat, hvis du flygter nu, @@ -645,7 +674,7 @@ a sua contagem de vítimas!","Olha, se saires agora perdes a tua contagem de mortes!","Uite, amice, pleci acum și renunți la numărul de cadavre!","Послушай, дружище. Выйдешь — и сбросишь свой счётчик убийств!","Чуј, ортак. Одеш ли, -изгубићеш свој број убистава!","Bak, dostum. Şimdi gidersen ceset sayını kaybedersin!" +изгубићеш свој број убистава!","Lyssna, kompis. Om du går nu förlorar du antalet döda!","Bak, dostum. Şimdi gidersen ceset sayını kaybedersin!",Слухай друже. Якщо підеш зараз - твій лічильник вбивств впаде до нуля! "Just leave. when you come back, I'll be waiting with a bat.",QUITMSG13,,,,"Jen odejdi. Až se vrátíš, budu čekat s baseballkou.","Bare gå. Når du kommer tilbage, @@ -662,7 +691,7 @@ vou estar te esperando com um taco.","Vá lá, sai. Quando voltares eu estarei a tua espera com uma moca.","Doar pleacă. Când te intorci o să te aștept cu o bâtă.","Уходи, уходи... но когда вернёшься, я буду ждать тебя с битой.","Иди, иди... али када се вратиш, -чекаћу те са палицом.",Sadece git. Geri döndüğünde bir sopayla bekliyor olacağım. +чекаћу те са палицом.",Gå bara. När du kommer tillbaka väntar jag med ett slagträ.,Sadece git. Geri döndüğünde bir sopayla bekliyor olacağım.,"Давай, йди. Бита почекає тебе." "You're lucky I don't smack you for thinking about leaving.",QUITMSG14,,,,"Máš štěstí, že tě neprofackuju za to, že přemýšlíš o odchodu.","Du er heldig, at jeg ikke slår dig, @@ -680,7 +709,7 @@ uma surra por pensar em sair.","Tens muita sorte em eu não te dar um excerto de porrada por teres pensado em sair.","Ai noroc că nu-ți trag una pentru că te gândești să pleci.","Тебе повезло, что я не вмажу тебе за то, что ты выходишь.","Имаш среће што те не ошамарим -због тога што одлазиш.",Gitmeyi düşündüğün için seni tokatlamadığım için şanslısın. +због тога што одлазиш.",Du har tur att jag inte slår dig för att du funderar på att gå.,Gitmeyi düşündüğün için seni tokatlamadığım için şanslısın.,"Тобі пощастило, що я не шибану тебе за вихід." "Where are you going?! What about the rebellion?",QUITMSG15,,,,"Kam jdeš?! A co bude s odbojem?","Hvor skal du hen?! @@ -698,7 +727,8 @@ E a rebelião?","Para onde estás a ir?! E então a rebelião?","Unde pleci?! Cu rebeliunea cum rămâne?","Куда ты собрался? А как же восстание?!","Где ћеш? -Шта ће бити са устанком?!",Nereye gidiyorsun?! İsyan ne olacak? +Шта ће бити са устанком?!",Vart är du på väg?! Hur blir det med upproret?,Nereye gidiyorsun?! İsyan ne olacak?,"Куди зібрався?! +А повстання?" "Carnage interruptus... What a tease!",QUITMSG16,,,,"Masakr přerušus... Takhle mě neškádli!","Carnage interruptus... @@ -716,7 +746,8 @@ Co za złośliwość!","Massacre interrompido... Que provocante!",,"Carnagiu întrerupt... Ce mai tachinare!","Вот так всегда... На самом интересном месте!","Покољ се прекида... -на најзанимљивијем месту!",Katliam kesintisi. Ne alay ama! +на најзанимљивијем месту!",Carnage interruptus... Vilket hångel!,Katliam kesintisi. Ne alay ama!,"Різанина затихає... +Бісить!" "But you're the hope -- my only chance!!",QUITMSG17,,,,"Ale ty jsi naše naděje -- moje jediná šance!","Men du er håbet @@ -726,19 +757,20 @@ Mia ununura ŝanco!!","Pero tú eres la esperanza... -- ainoa mahdollisuuteni!!","Mais vous êtes l'espoir, notre unique chance!","Te vagy a remény -- az egyetlen esélyem!","Ma tu sei la speranza --- la mia unica possibilità!!","だがお前が希望なんだ --- 唯一の可能性だ!!",하지만 넌 희망이야- 나의 유일한 기회라고!!,Maar jij bent de hoop - Mijn enige kans!!,Men du er håpet... min eneste sjanse!!!,"Ale ty jesteś nadzieją +-- la mia unica possibilità!!","それでもお前を信じている +-- 唯一の希望なんだ!!",하지만 넌 희망이야- 나의 유일한 기회라고!!,Maar jij bent de hoop - Mijn enige kans!!,Men du er håpet... min eneste sjanse!!!,"Ale ty jesteś nadzieją -- moją jedyną szansą!!","Mas você é a esperança — minha única chance!","Mas tu és a nossa esperança -- a minha única chance!!","Dar tu ești speranța -- singura mea șansă!!","Но на тебя вся надежда — ты мой единственный шанс!","Али на тебе је сва нада -- -ти си моја једина шанса!","Ama sen umudumsun, tek şansımsın!" -Nobody walks out on Blackbird.,QUITMSG18,,,,Nikdo se neobrací zády ke Strace.,Ingen går ud fra Blackbird. ,Niemand lässt Blackbird stehen.,Κανένας δεν παρατάει τον Μπλακμπερτ.,Neniu forlasas BlackBird.,Nadie abandona a BlackBird.,,Kukaan ei käännä selkäänsä Blackbirdille.,Personne n'abandonne Blackbird!,Senki nem kezdhet ki a Feketerigóval!,Nessuno gira le spalle a Blackbird.,ブラックバードに気付かれず抜け出せるのか。,그 누구도 블랙버드를 내 버릴 수 없지.,Niemand loopt weg van Blackbird.,Ingen forlater Blackbird.,Nikt nie opuszcza Blackbird.,Ninguém vira as costas para a Blackbird.,,Nimeni nu iese afară pe Blackbird.,Ещё никто не ушёл от «Чёрного дрозда».,Нико још није побегао од Црне птице.,Kimse Karatavuk'ü bırakıp gidemez. -I thought you were different...,QUITMSG19,,,,"Myslela jsem, že jsi jin@[adj_cs]...","Jeg troede, du var anderledes...","Ich dachte, du wärst anders...",Νόμιζα οτι είσουν διαφορετικός...,"Mi pensis, ke vi estas malsama...",Pensé que eras diferente...,Creí que eras diferente...,"Luulin, että olit erilainen kuin muut...",Je vous croyais différent...,Azt hittem te más vagy...,Pensavo tu fossi diverso...,私は あなたは特別だと思っていた...,난 네가 다를 줄 알았는데...,Ik dacht dat je anders was....,Jeg trodde du var annerledes...,"Myślałam, że jesteś inny...",Eu achei que você era diferente...,Eu achei que eras diferente...,Am crezut că tu ești diferit...,Я думал о тебе иначе...,О теби сам мислила другачије...,Senin farklı olduğunu sanıyordum. +ти си моја једина шанса!",Men du är hoppet - min enda chans!!,"Ama sen umudumsun, tek şansımsın!","Ти ж моя єдина надія - +мій останній шанс!" +Nobody walks out on Blackbird.,QUITMSG18,,,,Nikdo se neobrací zády ke Strace.,Ingen går ud fra Blackbird. ,Niemand lässt Blackbird stehen.,Κανένας δεν παρατάει τον Μπλακμπερτ.,Neniu forlasas Merlon.,Nadie abandona a Blackbird.,,Kukaan ei käännä selkäänsä Blackbirdille.,Personne n'abandonne Blackbird!,Senki nem kezdhet ki a Feketerigóval!,Nessuno gira le spalle a Blackbird.,ブラックバードに気付かれず抜け出せるのか。,그 누구도 블랙버드를 내 버릴 수 없지.,Niemand loopt weg van Blackbird.,Ingen forlater Blackbird.,Nikt nie opuszcza Blackbird.,Ninguém vira as costas para a Blackbird.,,Nimeni nu iese afară pe Blackbird.,Ещё никто не ушёл от «Чёрного дрозда».,Нико још није побегао од Црне птице.,Ingen lämnar Blackbird.,Kimse Karatavuk'ü bırakıp gidemez.,Ще ніхто не дав чосу від Чорного дрозда. +I thought you were different...,QUITMSG19,,,,"Myslela jsem, že jsi jin@[adj_cs]...","Jeg troede, du var anderledes...","Ich dachte, du wärst anders...",Νόμιζα οτι είσουν διαφορετικός...,"Mi pensis, ke vi estas malsama...",Pensé que eras diferente...,Creí que eras diferente...,"Luulin, että olit erilainen kuin muut...",Je vous croyais différent...,Azt hittem te más vagy...,Pensavo tu fossi diverso...,私は あなたは特別だと思っていた...,난 네가 다를 줄 알았는데...,Ik dacht dat je anders was....,Jeg trodde du var annerledes...,"Myślałam, że jesteś inny...",Eu achei que você era diferente...,Eu achei que eras diferente...,Am crezut că tu ești diferit...,Я думал о тебе иначе...,О теби сам мислила другачије...,Jag trodde att du var annorlunda...,Senin farklı olduğunu sanıyordum.,"Я думав, що ти інший..." Fine! just kill and run!,QUITMSG20,,,,Fajn! Prostě zab a uteč!,Fint! Bare dræb og løb!,"Na toll! Töten und dann wegrennen.",Καλά! Απλώς σκότοσε και φύγε!,Bone! Nur mortigu kaj fuĝu!,¡Bien! ¡Matas y huyes!,,Hyvä! Senkun vain tapat ja lähdet!,"C'est ça! Tuez n'importe-qui -et barrez-vous comme ça!",Oké! Csak ölj és fuss!,Ma bravo! Uccidi e scappi!,いいぞ! ゲリラ戦の時間だ!,그래그래 알았다! 그럼 그냥 뛰고 죽이기나 해!,"Goed hoor, schieten en meteen wegrennen!",Greit! Bare drep og løp!,Dobra! Zabijaj i biegaj!,Ótimo! Mate e fuja!,Pronto! Mata e foge!,Fie! Doar omoară și fugi!,Отлично! Пострелял и смылся!,Добро! Само убијај и бежи!,İyi! Sadece öldür ve kaç! +et barrez-vous comme ça!",Oké! Csak ölj és fuss!,Ma bravo! Uccidi e scappi!,いいぞ! ゲリラ戦の時間だ!,그래그래 알았다! 그럼 그냥 뛰고 죽이기나 해!,"Goed hoor, schieten en meteen wegrennen!",Greit! Bare drep og løp!,Dobra! Zabijaj i biegaj!,Ótimo! Mate e fuja!,Pronto! Mata e foge!,Fie! Doar omoară și fugi!,Отлично! Пострелял и смылся!,Добро! Само убијај и бежи!,Okej! Döda bara och spring!,İyi! Sadece öldür ve kaç!,Прекрасно! Зробив амінь чортам і втік! "You can quit... but you can't hide...",QUITMSG21,,,,"Můžeš odejít... ale nemůžeš se skrýt...","Du kan stoppe... @@ -757,7 +789,9 @@ mas não pode se esconder...","Podes sair... mas não te podes esconder...","Poți să ieși... dar nu te poți ascunde...","Ты можешь уйти... но не можешь спрятаться...","Можеш да одеш... -али не можеш да се кријеш...",Bırakabilirsin... ama saklanamazsın... +али не можеш да се кријеш...","Du kan sluta... +men du kan inte gömma dig...",Bırakabilirsin... ama saklanamazsın...,"Ти можеш вийти... +але не сховатись..." "Whaaa, what's the matter? Mommy says dinnertime?",QUITMSG22,,,,"Cóó, copak je? Maminka volá na večeři?","Whaaa, hvad er der i vejen? Mor siger spisetid?","Hey, was ist los? @@ -775,7 +809,9 @@ A mamãe disse que tá na hora da janta?","Qual é o problema? A mamã chamou para o jantar?","Ceee, ce s-a întâmplat? Mami zice că e timpul pentru cină?","Ха! В чём дело? Мама зовёт обедать?","Ха! Шта је било? -Мама те зове на вечеру?",Ne oldu? Annem yemek vakti mi dedi? +Мама те зове на вечеру?","Vad är det för fel? +Mamma säger att det är dags för middag?",Ne oldu? Annem yemek vakti mi dedi?,"Гааа, шо таке? +Мамуся покликала їстоньки?" "Don't quit now, there are still flemoids on the loose!",QUITMSG23,,,,"Teď neodcházej, stále tu pobíhají slizouni!","Du må ikke give op nu, der er stadig flemoider på fri fod!","Bitte gehe nicht, es laufen noch mehr @@ -788,7 +824,7 @@ flemoidi a piede libero!","まだやめないでくれ、 Ainda tem flemoides à solta!","Não desistas agora! Ainda há flemoids à solta!","Nu ieși acum, încă mai sunt flemoizi liberi!","Не выходи сейчас! Здесь есть ещё много флемоидов!","Немој сада да одустајеш! -Има још много љигавца! ","Şimdi pes etme, hala serbest flemoidler var!" +Има још много љигавца! ","Ge inte upp nu, det finns fortfarande flemoider på fri fot!","Şimdi pes etme, hala serbest flemoidler var!","Не виходь поки, тут ще багато флемоїдів лишилось!" "Don't give up -- the flemoids will get the upper hand!",QUITMSG24,,,,"Teď to nevzdávej - slizouni budou mít výhodu!","Du må ikke give op - Flemoiderne @@ -804,7 +840,7 @@ ci sopraffaranno!","あきらめてはダメだ、 vão levar a melhor!","Não desistas -- os flemóides estão a ganhar!",Nu renunța - flemoizii vor avea avantajul!,"Не сдавайся — не то флемоиды получат преимущество!","Немој да одустајеш -- -љигавци ће добити предност!","Sakın pes etme, flemoidler üstünlüğü ele geçirecek!" +љигавци ће добити предност!",Ge inte upp - flemoiderna kommer att ta överhanden!,"Sakın pes etme, flemoidler üstünlüğü ele geçirecek!",Не здавайся -- а то флемоїди візьмуть верх! "Don't leave now. We need your help!",QUITMSG25,,,,"Teď neodcházej. Potřebujeme tvoji pomoc!",Du må ikke gå nu. Vi har brug for din hjælp!,"Bitte geh nicht. @@ -823,7 +859,8 @@ Precisamos da sua ajuda!","Não te vás embora agora. Nós precisamos da tua ajuda!","Nu pleca. Avem nevoie de ajutorul tău!","Не уходи сейчас. Нам нужна твоя помощь!","Не излази сада. -Треба нам твоја помоћ!",Şimdi gitmeyin. Yardımınıza ihtiyacımız var! +Треба нам твоја помоћ!",Gå inte nu. Vi behöver din hjälp!,Şimdi gitmeyin. Yardımınıza ihtiyacımız var!,"Не залишай нас. +Нам потрібна твоя допомога!" "I hope you're just taking a break for Chex(R) party mix.",QUITMSG26,,,,"Doufám, že si jen dáváš pauzu na Chex(R) Party Mix.","Jeg håber, at du bare holder en pause for Chex(R) party mix.","Ich hoffe mal, dass du nur eine @@ -839,7 +876,7 @@ pausa pra um Chex(R) Party Mix.","Espero que só estejas a fazer uma pausa pra um Chex(R) Party Mix.","Sper că iei doar o pauză cu un bol de cereale Chex(R).","Надеюсь, ты лишь делаешь перерыв на тарелку хлопьев Chex(R).","Надам се да само паузираш -за Chex житарице.",Umarım Chex(R) parti karışımı için ara vermişsinizdir. +за Chex житарице.",Jag hoppas att du bara tar en paus för Chex(R) party mix.,Umarım Chex(R) parti karışımı için ara vermişsinizdir.,"Маю надію, що ти робиш перерву на пластівці Chex(R)." "Don't quit now! We need your help!",QUITMSG27,,,,"Teď neodcházej. Potřebujeme tvoji pomoc!",Du må ikke give op nu! Vi har brug for din hjælp!,"Bitte verlasse uns nicht. @@ -858,7 +895,8 @@ Precisamos da sua ajuda!","Não saias agora! Nós precisamos da tua ajuda!","Nu abandona acum! Avem nevoie de ajutorul tău!","Не бросай всё сейчас! Нам нужна твоя помощь!","Не одустај сада! -Треба нам твоја помоћ!",Şimdi bırakmayın! Yardımınıza ihtiyacımız var! +Треба нам твоја помоћ!",Sluta inte nu! Vi behöver din hjälp!,Şimdi bırakmayın! Yardımınıza ihtiyacımız var!,"Не виходь! +Нам потрібна твоя допомога!" "Don't abandon the Intergalactic Federation of Cereals!",QUITMSG28,,,,"Neopouštěj Intergalaktickou federaci cereálií!",Forlad ikke den Intergalaktiske Føderation af Cerealprodukter!,"Bitte lasse die Intergalaktische @@ -871,7 +909,7 @@ Federazione Intergalattica dei Cereali!","ぎんがシリアルれんぽう を みすてないでくれ!",은하연합시리얼국을 위해서라도 부디 떠나지 말아 주시길 바랍니다!,Laat de Intergalactische Federatie van Granen niet in de steek!,Ikke forlat Den intergalaktiske kornføderasjonen!,Nie opuszczaj Międzygalaktycznej Federacji Płatków!,"Não abandone a Federação Intergaláctica de Cereais!",,Nu abandona Federația Intergalactică a Cerealelor!,"Не оставляй Межгалактическую Федерацию Хлопьев!","Не напуштај Интергалактичку -федерацију овсених пахуљица!",Galaksilerarası Tahıl Federasyonu'nu terk etmeyin! +федерацију овсених пахуљица!",Överge inte Intergalactic Federation of Cereals!,Galaksilerarası Tahıl Federasyonu'nu terk etmeyin!,Не покидай Міжгалактичну Федерацію Пластівців! "The real Chex(R) Warrior wouldn't give up so fast!",QUITMSG29,,,,"Skutečný Chex(R) bojovník by se tak rychle nevzdal!",Den rigtige Chex(R)-kriger ville ikke give op så hurtigt!,"Der echte Chex(R) Krieger @@ -886,1008 +924,979 @@ nie poddałby się tak szybko!","O verdadeiro Guerreiro Chex(R) não desistiria tão rapido!",,"Adevăratul Luptător Chex(R) nu s-ar da bătut atât de ușor!","Настоящий воин Chex(R) не сдастся так быстро!","Прави Чекс ратници не -би одустали тако лако!",Gerçek Chex(R) Savaşçısı bu kadar çabuk pes etmez! -,,Pickups,,,,,,,,,,,,,,,,,,,,,,,, -You got a pickup,TXT_DEFAULTPICKUPMSG,,,,Dostal@[ao_cs] jsi věc,Du har samlet noget op,Du hast etwas aufgesammelt,Πήρες ένα πράγμα.,Vi trovis aĵon,Encuentras un objeto.,Hallaste un objeto,Sait jotakin,Quelque chose récupéré.,Felvettél egy tárgyat.,Hai raccolto qualcosa ,何か拾った,무언가를 집어냈다,Je hebt iets opgepakt...,Du har en henting,Zebrano przedmiot,Você pegou um item,Apanhaste um item,Ai ridicat un obiect.,Что-то получено,Покупили сте нешто,Bir pikabın var -,,Locks,,,,,,,,,,,,,,,,,,,,,,,, -Any key will open this door,PD_ANY,,,,Tyto dveře otevře jakýkoliv klíč,Enhver nøgle kan åbne denne dør,Jeder Schlüssel wird diese Tür öffnen,Οποιδήποτε κλειδί θα ανοίξει τη πόρτα,Iu ajn ŝlosilo povas malfermi ĉi tiun pordon,Cualquier llave puede abrir esta puerta,,Mikä tahansa avain avaa tämän oven,N'importe quelle clé peut ouvrir cette porte.,Bármilyen kulcs kinyitja ezt az ajtót.,Una chiave qualunque aprirà questa porta,いずれかのキーで開けることができる。,어느 열쇠든 이 문을 열 수 있습니다,Elke sleutel zal deze deur openen,Hvilken som helst nøkkel åpner denne døren,Dowolny klucz otworzy te drzwi,Qualquer chave abre esta porta,Qualquer chave pode abrir esta porta,Orice cheie va deschide ușa aceasta.,Для открытия нужен любой ключ,За отварање потребан је било који кључ,Herhangi bir anahtar bu kapıyı açar -Any key will activate this object,PD_ANYOBJ,,,,Tento objekt aktivuje jakýkoliv klíč,Enhver nøgle vil aktivere dette objekt,Jeder Schlüssel wird dieses Objekt aktivieren,Οποιδήποτε κλειδί θα ενεργοποιήσει αυτό το αντικείμενο,Iu ajn ŝlosilo povas aktivigi ĉi tiun objekton,Cualquier llave puede activar este objeto,,Mikä tahansa avain aktivoi tämän kappaleen,N'importe quelle clé peut activer cet objet.,Bármilyen kulcs aktiválja ezt a tárgyat.,Una chiave qualunque attiverà questo oggetto,いずれかのキーで起動させることができる。,어느 열쇠든 이 물체를 작동 시킬 것입니다,Elke sleutel zal dit object activeren,Hvilken som helst nøkkel vil aktivere dette objektet,Dowolny klucz aktywuje ten przedmiot,Qualquer chave ativa este objeto,Qualquer chave pode ativar este objeto,Orice cheie va activa obiectul acesta.,Для включения нужен любой ключ,За активирање потребан је било који кључ,Herhangi bir tuş bu nesneyi etkinleştirir +би одустали тако лако!",Den riktiga Chex(R)-krigaren skulle inte ge upp så snabbt!,Gerçek Chex(R) Savaşçısı bu kadar çabuk pes etmez!,Справжній воїн Chex(R) не здається так швидко! +,,Pickups,,,,,,,,,,,,,,,,,,,,,,,,,, +You got a pickup,TXT_DEFAULTPICKUPMSG,,,,Dostal@[ao_cs] jsi věc,Du har samlet noget op,Du hast etwas aufgesammelt,Πήρες ένα πράγμα.,Vi trovis aĵon,Encuentras un objeto,,Sait jotakin,Quelque chose récupéré.,Felvettél egy tárgyat.,Hai raccolto qualcosa ,何か拾った,무언가를 집어냈다,Je hebt iets opgepakt...,Du har en henting,Zebrano przedmiot,Você pegou um item,Apanhaste um item,Ai ridicat un obiect.,Что-то получено,Покупили сте нешто,Du har en pickup,Bir pikabın var,Ви щось підібрали +,,Locks,,,,,,,,,,,,,,,,,,,,,,,,,, +Any key will open this door,PD_ANY,,,,Tyto dveře otevře jakýkoliv klíč,Enhver nøgle kan åbne denne dør,Jeder Schlüssel wird diese Tür öffnen,Οποιδήποτε κλειδί θα ανοίξει τη πόρτα,Iu ajn ŝlosilo povas malfermi ĉi tiun pordon,Cualquier llave puede abrir esta puerta,,Mikä tahansa avain avaa tämän oven,N'importe quelle clé peut ouvrir cette porte.,Bármilyen kulcs kinyitja ezt az ajtót.,Una chiave qualunque aprirà questa porta,いずれかのキーで開けることができる。,어느 열쇠든 이 문을 열 수 있습니다,Elke sleutel zal deze deur openen,Hvilken som helst nøkkel åpner denne døren,Dowolny klucz otworzy te drzwi,Qualquer chave abre esta porta,Qualquer chave pode abrir esta porta,Orice cheie va deschide ușa aceasta.,Для открытия нужен любой ключ,За отварање потребан је било који кључ,Vilken nyckel som helst kan öppna den här dörren.,Herhangi bir anahtar bu kapıyı açar,Будь який ключ відкриє ці двері +Any key will activate this object,PD_ANYOBJ,,,,Tento objekt aktivuje jakýkoliv klíč,Enhver nøgle vil aktivere dette objekt,Jeder Schlüssel wird dieses Objekt aktivieren,Οποιδήποτε κλειδί θα ενεργοποιήσει αυτό το αντικείμενο,Iu ajn ŝlosilo povas aktivigi ĉi tiun objekton,Cualquier llave puede activar este objeto,,Mikä tahansa avain aktivoi tämän kappaleen,N'importe quelle clé peut activer cet objet.,Bármilyen kulcs aktiválja ezt a tárgyat.,Una chiave qualunque attiverà questo oggetto,いずれかのキーで起動させることができる。,어느 열쇠든 이 물체를 작동 시킬 것입니다,Elke sleutel zal dit object activeren,Hvilken som helst nøkkel vil aktivere dette objektet,Dowolny klucz aktywuje ten przedmiot,Qualquer chave ativa este objeto,Qualquer chave pode ativar este objeto,Orice cheie va activa obiectul acesta.,Для включения нужен любой ключ,За активирање потребан је било који кључ,Alla nycklar aktiverar det här objektet,Herhangi bir tuş bu nesneyi etkinleştirir,Будь який ключ активує цей об'єкт You need all three keys to open this door,PD_ALL3,,,,K otevření těchto dveří jsou potřeba všechny tři klíče,Du skal bruge alle tre nøgler for at åbne denne dør,"Du brauchst alle drei Schlüssel, um diese Tür zu öffnen",Χρειάζεσαι όλα τα τρία κλειδία για να ανοίξεις αυτή τη πόρτα,Vi bezonas ĉiujn tri ŝlosilojn por malfermi ĉi tiun pordon,Necesitas las tres llaves para abrir esta puerta,,Kaikki kolme avainta tarvitaan tämän oven avaamiseksi,Il vous faut une clé de chaque couleur pour ouvrir cette porte.,"Mind a 3 kulcs szükséges, hogy kinyisd ezt az ajtót.",Ti servono tutte e tre le chiavi per aprire questa porta,3つのキー全てが無ければ開かない。,이 문을 열기 위해선 3 종류의 열쇠가 필요합니다,Je hebt alle drie de sleutels nodig om deze deur te openen,Du trenger alle tre nøklene for å åpne denne døren,"Potrzebujesz wszystkich trzech kluczy, aby otworzyć te drzwi",Você precisa de todas as três chaves para abrir esta porta,Precisas de todas as três chaves para abrir esta porta,"Ai nevoie de toate cele trei chei pentru a deschide -ușa aceasta.",Для открытия требуются все три ключа,За отварање потребна су сва три кључа ,Bu kapıyı açmak için üç anahtara da ihtiyacınız var +ușa aceasta.",Для открытия требуются все три ключа,За отварање потребна су сва три кључа ,Du behöver alla tre nycklarna för att öppna den här dörren.,Bu kapıyı açmak için üç anahtara da ihtiyacınız var,"Вам потрібні всі три ключі, щоб відкрити ці двері" You need all three keys to activate this object,PD_ALL3O,,,,K aktivaci tohoto objektu jsou potřeba všechny tři klíče,Du skal bruge alle tre nøgler for at aktivere dette objekt,"Du brauchst alle drei Schlüssel, um dieses Objekt zu aktivieren",Χρειάζεσε όλα τα τρία κλειδιά για να ενεργοποιήσεις αυτό το αντικείμενο,Vi bezonas ĉiujn tri ŝlosilojn por aktivigi ĉi tiun objekton,Necesitas las tres llaves para activar este objeto,,Kaikki kolme avainta tarvitaan tämän kappaleen aktivoimiseksi,Il vous faut une clé de chaque couleur pour activer cet objet.,Mind a 3 kulcs kell hogy aktiváld ezt a tárgyat.,Ti servono tutte e tre le chiavi per attivare questo oggetto ,3つのキー全てが必要だ。,이 물체를 작동시키기 위해선 3 종류의 열쇠가 필요합니다,Je hebt alle drie de sleutels nodig om dit object te activeren,Du trenger alle tre nøklene for å aktivere dette objektet,"Potrzebujesz wszystkich trzech kluczy, aby aktywować ten przedmiot",Você precisa de todas as três chaves para ativar este objeto,Precisas de todas as três chaves para ativar este objeto,"Ai nevoie de toate cele trei chei pentru a activa -acest obiect.",Для включения требуются все три ключа,За активирање потребна су сва три кључа,Bu nesneyi etkinleştirmek için üç tuşa da ihtiyacınız var +acest obiect.",Для включения требуются все три ключа,За активирање потребна су сва три кључа,Du behöver alla tre nycklarna för att aktivera det här föremålet.,Bu nesneyi etkinleştirmek için üç tuşa da ihtiyacınız var,"Вам потрібні всі три ключі, щоб активувати цей об'єкт" You need all six keys to open this door,PD_ALL6,,,,K otevření těchto dveří je potřeba všech šest klíčů,Du skal bruge alle seks nøgler for at åbne denne dør,"Du brauchst alle sechs Schlüssel, um diese Tür zu öffnen",Χρειάζεσαι όλα τα έξι κλειδία για να ανοίξεις αυτή τη πόρτα,Vi bezonas ĉiujn ses ŝlosilojn por malfermi ĉi tiun pordon,Necesitas las seis llaves para abrir esta puerta,,Kaikki kuusi avainta tarvitaan tämän oven avaamiseksi,Il vous faut les six clés pour ouvrir cette porte.,Mind a 6 kulcsnak meg kell lennie az ajtó kinyitásához.,Ti servono tutte e sei le chiavi per aprire questa porta,6つ全てのキーが無ければ開かない。,이 문을 열기 위해선 6 종류의 열쇠가 필요합니다,Je hebt alle zes de sleutels nodig om deze deur te openen,Du trenger alle seks nøklene for å åpne denne døren,"Potrzebujesz wszystkich sześciu kluczy, aby otworzyć te drzwi",Você precisa de todas as seis chaves para abrir esta porta,Precisas de todas as seis chaves para abrir esta porta,"Ai nevoie de toate cele sase chei pentru a deschide -aceasta usa.",Для открытия требуются все шесть ключей,За отварање потребна су свих шест кључева,Bu kapıyı açmak için altı anahtara da ihtiyacınız var +aceasta usa.",Для открытия требуются все шесть ключей,За отварање потребна су свих шест кључева,Du behöver alla sex nycklar för att öppna den här dörren.,Bu kapıyı açmak için altı anahtara da ihtiyacınız var,"Вам потрібні всі шість ключів, щоб відкрити ці двері" You need all six keys to activate this object,PD_ALL6O,,,,K aktivaci tohoto objektu je potřeba všech šest klíčů,Du skal bruge alle seks nøgler for at aktivere dette objekt,"Du brauchst alle sechs Schlüssel, um dieses Objekt zu aktivieren",Χρειάζεσε όλα τα έξι κλειδιά για να ενεργοποιήσεις αυτό το αντικείμενο,Vi bezonas ĉiujn ses ŝlosilojn por aktivigi ĉi tiun objekton,Necesitas las seis llaves para activar este objeto,,Kaikki kuusi avainta tarvitaan tämän kappaleen aktivoimiseksi,Il vous faut les six clés pour activer cet objet.,"Mind a 6 kulcs kell, hogy aktiváld ezt az objektumot.",Ti servono tutte e tre le chiavi per attivare questo oggetto ,6つ全てのキーが必要だ。,이 물체를 작동시키기 위해선 6 종류의 열쇠가 필요합니다,Je hebt alle zes de sleutels nodig om dit object te activeren,Du trenger alle seks nøklene for å aktivere dette objektet,"Potrzebujesz wszystkich sześciu kluczy, aby aktywować ten przedmiot",Você precisa de todas as seis chaves para ativar este objeto,Precisas de todas as seis chaves para ativar este objeto,"Ai nevoie de toate cele șase chei pentru a activa -acest obiect.",Для включения требуются все шесть ключей,За активирање потребна су свих шест кључева,Bu nesneyi etkinleştirmek için altı tuşa da ihtiyacınız var -You need all the keys,PD_ALLKEYS,,,,Potřebuješ všechny klíče,Du skal bruge alle nøglerne,Du brauchst alle Schlüssel,Χρειάζεσαι όλα τα κλειδία,Vi bezonas ĉiujn ŝlosilojn,Necesitas todas las llaves,,Kaikki avaimet tarvitaan,Vous avez besoin de toutes les six clés.,Az összes kulcsra szükséged van.,Ti servono tutte le chiavi,全てのキーが必要だ。,모든 열쇠가 필요합니다,Je hebt alle sleutels nodig,Du trenger alle nøklene,Potrzebujesz wszystkich kluczy,Você precisa de todas as chaves,Precisas de todas as chaves,Ai nevoie de toate cheile.,Требуются все ключи,Потребни су сви кључеви,Tüm anahtarlara ihtiyacın var -,,Chat,,,,,,,,,,,,,,,,,,,,,,,, -[Message unsent],HUSTR_MSGU,,,,[Zpráva neposlána],[Besked ikke sendt],[Nachricht nicht gesendet],[Δέν στάλθηκε],[Mesaĝo ne sendita],[Mensaje sin enviar],,[Viestiä ei lähetetty],[Message Non Envoyé],[Üzenet nincs elküldve],[Messaggio non inviato],[メッセージ未送信],[메시지가 전달되지 않음],[Bericht niet verzonden],[Melding ikke sendt],[Wiadomość niewysłana],[Mensagem não enviada],,[Mesaj netrimis],[Сообщение не отправлено],[Порука непослата],[Mesaj gönderilmemiş] -You mumble to yourself,HUSTR_TALKTOSELF1,,,,Něco si zamumláš pro sebe.,Du mumler for dig selv,Du murmelst zu dir selbst,Μουρμουράς στον εαυτό σου,Vi murmuras al vi mem,Te murmuras a ti mism@[ao_esp],,Mutiset itseksesi,Vous parlez tout seul.,Magadban motyogsz,Pensi fra te e te,ネタにならない呟きだ,자기 혼자서 중얼거렸다,Je mompelt in jezelf,Du mumler for deg selv,Mamroczesz do siebie,Você resmunga para si mesm@[ao_ptb]...,Tu resmungas contigo própri@[ao_ptb]...,Bolborosești în sine,Неразборчивое бормотание,Промумљате себи,Kendi kendine mırıldanıyorsun -Who's there?,HUSTR_TALKTOSELF2,,,,Kdo je tam?,Hvem er der?,Wer ist da?,Πιός είναι εκεί?,Kiu estas tie?,¿Quién está ahí?,,Kuka siellä?,Qui est là?,Ki van ott?,Chi c'è lì?,誰かいるか?,거기 누구 있나?,Wie is daar?,Hvem er der?,Kto tam?,Quem está aí?,,Cine-i acolo?,Кто там?,Ко је то?,Kim var orada? +acest obiect.",Для включения требуются все шесть ключей,За активирање потребна су свих шест кључева,Du behöver alla sex nycklar för att aktivera detta objekt.,Bu nesneyi etkinleştirmek için altı tuşa da ihtiyacınız var,"Вам потрібні всі шість ключів, щоб активувати цей об'єкт" +You need all the keys,PD_ALLKEYS,,,,Potřebuješ všechny klíče,Du skal bruge alle nøglerne,Du brauchst alle Schlüssel,Χρειάζεσαι όλα τα κλειδία,Vi bezonas ĉiujn ŝlosilojn,Necesitas todas las llaves,,Kaikki avaimet tarvitaan,Vous avez besoin de toutes les six clés.,Az összes kulcsra szükséged van.,Ti servono tutte le chiavi,全てのキーが必要だ。,모든 열쇠가 필요합니다,Je hebt alle sleutels nodig,Du trenger alle nøklene,Potrzebujesz wszystkich kluczy,Você precisa de todas as chaves,Precisas de todas as chaves,Ai nevoie de toate cheile.,Требуются все ключи,Потребни су сви кључеви,Du behöver alla nycklar,Tüm anahtarlara ihtiyacın var,Потрібні всі ключі +,,Chat,,,,,,,,,,,,,,,,,,,,,,,,,, +[Message unsent],HUSTR_MSGU,,,,[Zpráva neposlána],[Besked ikke sendt],[Nachricht nicht gesendet],[Δέν στάλθηκε],[Mesaĝo ne sendita],[Mensaje sin enviar],,[Viestiä ei lähetetty],[Message Non Envoyé],[Üzenet nincs elküldve],[Messaggio non inviato],[メッセージ未送信],[메시지가 전달되지 않음],[Bericht niet verzonden],[Melding ikke sendt],[Wiadomość niewysłana],[Mensagem não enviada],,[Mesaj netrimis],[Сообщение не отправлено],[Порука непослата],[Meddelande ej skickat],[Mesaj gönderilmemiş],[Повідомлення не відправлено] +You mumble to yourself,HUSTR_TALKTOSELF1,,,,Něco si zamumláš pro sebe.,Du mumler for dig selv,Du murmelst zu dir selbst,Μουρμουράς στον εαυτό σου,Vi murmuras al vi mem,Te murmuras a ti mism@[ao_esp],,Mutiset itseksesi,Vous parlez tout seul.,Magadban motyogsz,Pensi fra te e te,ネタにならない呟きだ,자기 혼자서 중얼거렸다,Je mompelt in jezelf,Du mumler for deg selv,Mamroczesz do siebie,Você resmunga para si mesm@[ao_ptb]...,Tu resmungas contigo própri@[ao_ptb]...,Bolborosești în sine,Неразборчивое бормотание,Промумљате себи,Du mumlar för dig själv,Kendi kendine mırıldanıyorsun,Ви бормочете собі під ніс +Who's there?,HUSTR_TALKTOSELF2,,,,Kdo je tam?,Hvem er der?,Wer ist da?,Πιός είναι εκεί?,Kiu estas tie?,¿Quién está ahí?,,Kuka siellä?,Qui est là?,Ki van ott?,Chi c'è lì?,誰かいるか?,거기 누구 있나?,Wie is daar?,Hvem er der?,Kto tam?,Quem está aí?,,Cine-i acolo?,Кто там?,Ко је то?,Vem är där?,Kim var orada?,Хто тут? You scare yourself,HUSTR_TALKTOSELF3,,,,Vystrašíš se.,Du skræmmer dig selv,Du machst dir Angst,Φοβήζεις τον εαυτό σου,Vi timigas vin mem,Te asustas a ti mism@[ao_esp],,Pelotat itseäsi,Vous vous surprenez.,Megijeszted magad,Ti spaventi da solo,"怯えているな -",자기 혼자서 벌벌 떨고 있다,Je wordt bang van jezelf,Du skremmer deg selv,Przestraszyłeś się,Você se assusta,Assustas-te a ti propri@[ao_ptb],Te speri pe tine însuți,Что это было?,Плашите самог себе,Kendini korkutuyorsun. -You start to rave,HUSTR_TALKTOSELF4,,,,Začneš pařit.,Du begynder at rave,Du beginnst zu toben,Αρχίζεις να ουρλίαζεις,Vi komencas frenezi,Empiezas a delirar,,Alat hourailla,Vous commencez à délirer!,Reszketni kezdesz,Inizi a delirare,イカレ始めた,횡설수설하기 시작했다,Je begint te razen,Du begynner å rave,Zaczynasz wariować,Você começa a delirar,Começas a delirar,Începi să aiurezi,Вы бредите.,Брбљате,Çıldırmaya başlıyorsun -You've lost it...,HUSTR_TALKTOSELF5,,,,Kleplo ti...,Du har mistet den...,Du verlierst den Verstand...,Το έχασες,Vi freneziĝis...,Te has vuelto loc@[ao_esp]...,Te volviste loc@[ao_esp]...,Olet seonnut...,Vous avez perdu les pédales...,Eldobod az agyad...,Sei andato...,我を失った...,미치기 시작했다...,Je bent het kwijt,You've lost it...,Oszalałeś...,Você enlouqueceu...,Enlouqueceste,Ai luat-o pe ulei...,Какая досада...,Лудите...,Kaybettin... -[Message Sent],HUSTR_MESSAGESENT,,,,[Zpráva odeslána],[besked sendt],[Nachricht gesendet],[Στάλθηκε],[Mesaĝo sendita],[Mensaje enviado],,[Viesti lähetetty],[Message Envoyé],[Üzenet elküldve],[Messaggio Inviato],[メッセージ送信],[메시지가 전달됨],[Bericht verzonden],[Melding sendt],[Wiadomość wysłana],[Mensagem enviada],,[Mesaj Trimis],[Сообщение отправлено],[Порука послата],[Mesaj Gönderildi] -,,Cheats,,,,,,,,,,,,,,,,,,,,,,,, -Music Change,STSTR_MUS,,,,Změna hudby,Musik Ændring,Musikwechsel,Άλλαξε μουσική,Muzikŝanĝo,Cambio de música,,Musiikin vaihtaminen,Changement de Musique,Zene Váltás,Cambio di musica,music変更,음악 전환,Muziek veranderen,Music Change,Zmieniono muzykę,Trocando música,Mudar a música,Schimbare muzică...,Смена музыки,Промена музике,Müzik Değişimi -Impossible Selection,STSTR_NOMUS,,,,Nemožný výběr,Umuligt valg,Falsche Auswahl,Αδήνατη επιλογή,Malebla Elektaĵo,Selección impossible,,Valinta ei mahdollinen,Séléction Impossible!,Lehetetlen Kiválasztás,Selezione impossibile,その変更は不可能だ,불가능한 선택입니다,Onmogelijke selectie,Umulig valg,Niemożliwy wybór,Seleção impossível,,Selectare Imposibilă,Неверный выбор,НЕМОГУЋИ ИЗБОР,İmkansız Seçim -Degreelessness Mode ON,STSTR_DQDON,,,,Nesmrtelnost ZAP,Gradeløs tilstand TIL,Unverwundbarkeit AN,Θεική λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Nevundebla Reĝimo ŜALTITA,Modo de estado sin grado ACTIVADO,,Kuolemattomuustila PÄÄLLÄ,Invulnérabilité ON ,Sérthetetlenség Mód BE,Modalità Invincibilità ATTIVATA,無敵モード: オン,무미건조한 모드 켬,Gegradeloosheid modus AAN,Gradløshetsmodus PÅ,Niewrażliwość WŁĄCZONA,Modo invencível ATIVADO,,Modul invincibil ACTIVAT,Безграмотность ВКЛЮЧЕНА,Нерањивост УКЉУЧЕНА,Dokunulmazlık Modu AÇIK -Degreelessness Mode OFF,STSTR_DQDOFF,,,,Nesmrtelnost VYP,Gradeløs tilstand FRA,Unverwundbarkeit AUS,Θεική λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Nevundebla Reĝimo MALŜALTITA,Modo de estado sin grado DESACTIVADO,,Kuolemattomuustila POIS PÄÄLTÄ,Invulnérabilité OFF,Sérthetetlenség Mód KI,Modalità Invincibilità DISATTIVATA,無敵モード: オフ,무미건조한 모드 끔,Gegradeloosheid modus UIT,Gradløshetsmodus AV,Niewrażliwość WYŁĄCZONA,Modo invencível DESATIVADO,,Modul Invincibil DEZACTIVAT,Безграмотность ОТКЛЮЧЕНА,Нерањивост ИСКЉУЧЕНА,Dokunulmazlık Modu KAPALI -Ultimate Degreelessness Mode ON,STSTR_DQD2ON,,,,Supernesmrtelnost ZAP,Ultimativ gradløs tilstand TIL,Ultimative Unverwundbarkeit AN,Απόλητη θεική λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Pleja Nevundebla Reĝimo ŜALTITA,Modo de estado sin grado final ACTIVADO,,Varma kuolemattomuustila PÄÄLLÄ,Parfaite Invulnérabilité ON,Tökéletes Sérthetetlenség Mód BE,Modalità Invincibilità Ultima ATTIVATA,究極無敵モード: オン,엄청나게 무미건조한 모드 켬,Uiteindelijke Gegradeloosheid modus AAN,Ultimativ gradløshetsmodus PÅ,Maksymalna niewrażliwość WŁĄCZONA,Modo invencível supremo ATIVADO,,Modul Invincibilitate Supremă ACTIVAT,Полная безграмотность ВКЛЮЧЕНА,Ултимативна нерањивост УКЉУЧЕНА,Nihai Dokunulmazlık Modu AÇIK -Ultimate Degreelessness Mode OFF,STSTR_DQD2OFF,,,,Supernesmrtelnost VYP,Ultimativ gradløs tilstand FRA,Ultimative Unverwundbarkeit AUS,Απόλητη θεική λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Pleja Nevundebla Reĝimo MALŜALTITA,Modo de estado sin grado final DESACTIVADO,,Varma kuolemattomuustila POIS PÄÄLTÄ,Parfaite Invulnérabilité OFF,Tökéletes Sérthetetlenség Mód KI,Modalità Invincibilità Ultima DISATTIVATA,究極無敵モード: オフ,엄청나게 무미건조한 모드 끔,Uiteindelijke Gegradeloosheid modus UIT,Ultimativ gradløshetsmodus AV,Maksymalna niewrażliwość WYŁĄCZONA,Modo invencível supremo DESATIVADO,,Modul Invincibilitate Supremă DEZACTIVAT,Полная безграмотность ОТКЛЮЧЕНА,Ултимативна нерањивост ИСКЉУЧЕНА,Nihai Dokunulmazlık Modu KAPALI -Very Happy Ammo Added,STSTR_KFAADDED,,,,Velmi veselá munice přidána,Meget lykkelig Ammo tilføjet,Munition hinzugefügt,Πάρα Πολύ Χαρούμενα Πυρομαχηκά Προστέθηκαν,Tre Feliĉa Municio Aldonita,Munición añadida hasta el tope,,Täysaseistus,Armement Maximum!,Összes Lőszer Megadva,Equipaggiamento Completato,とても満足する武器弾薬を受け取った,아주 행복한 탄약 추가됨,Zeer gelukkige munitie toegevoegd,Veldig glad ammunisjon lagt til,Bardzo szczęśliwa amunicja dodana,Equipamento completo,,Echipament complet,Боезапас на счастье пополнен,Веома Срећна Муниција Додана,Çok Mutlu Cephane Eklendi -Ammo (no keys) Added,STSTR_FAADDED,,,,Munice (bez klíčú) přidána,Ammo (ingen nøgler) Tilføjet,Munition (keine Schlüssel) hinzugefügt,Πυρομαχικά (Όχι κλειδία) προστέθηκαν,Municio (neniuj ŝlosiloj) Aldonita,Munición añadida (sin llaves),,Täysaseistus (ilman avaimia),Arsenal ajouté. (Pas de clés!),Lőszer (nincsenek kulcsok) Megadva,Equipaggiamento Completato (senza chiavi),武器弾薬(鍵なし)を受け取った,탄약(열쇠 없이) 추가됨,Munitie (geen sleutels) toegevoegd,Ammo (ingen nøkler) Lagt til,Amunicja (bez kluczy) dodana,Equipamento completo (sem chaves),,Echipament complet (fără muniție),Боезапас пополнен (без ключей),Муниција (без кључева) Додана,Cephane (anahtar yok) Eklendi -No Clipping Mode ON,STSTR_NCON,,,,Bezkolizní režim ZAP,Ikke-kollisionstilstand TIL,Nicht-Kollisionsmodus AN,Noclip λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Reĝimo de Neniu Tondado ŜALTITA,Modo de traspaso ACTIVADO,,Seinänläpikulkutila PÄÄLLÄ,Collisions OFF,Falonátmenés Mód BE,No Clipping ATTIVATO,壁抜けモード: オン,노 클립 모드 켬,Geen Clipping Modus AAN,Ingen klipping-modus PÅ,Tryb no-clip WŁĄCZONY,Modo sem colisão ATIVADO,,Modul fără coliziune ACTIVAT,Режим без столкновений ВКЛЮЧЕН,Пролажење кроз зидове УКЉУЧЕНО,Klipsleme Yok Modu AÇIK -No Clipping Mode OFF,STSTR_NCOFF,,,,Bezkolizní režim VYP,Ikke-kollisionstilstand FRA,Nicht-Kollisionsmodus AUS,Noclip λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Reĝimo de Neniu Tondado MALŜALTITA,Modo de traspaso DESACTIVADO,,Seinänläpikulkutila POIS PÄÄLTÄ,Collisions ON,Falonátmenés Mód KI,No Clipping DISATTIVATO,壁抜けモード: オフ,노 클립 모드 끔,Geen Clipping Modus OFF,Ingen klippemodus AV,Tryb no-clip WYŁĄCZONY,Modo sem colisão DESATIVADO,,Modul fără coliziune DEZACTIVAT,Режим без столкновений ОТКЛЮЧЕН,Пролажење кроз зидове ИСКЉУЧЕНО,Klipsleme Yok Modu KAPALI -No Clipping Mode 2 ON,STSTR_NC2ON,,,,Bezkolizní režim 2 ZAP,Ikke-kollisionstilstand 2 TIL,Nicht-Kollisionsmodus 2 AN,Δέυτερη noclip λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Reĝimo de Neniu Tondado 2 ŜALTITA,Modo de traspaso 2 ACTIVADO,,Seinänläpikulkutila 2 PÄÄLLÄ,Collisions 3D OFF,Falonátmenés 2. Mód BE,No Clipping 2 ATTIVATO,壁抜けモード2: オン,노 클립 모드 2 켬,Geen Clipping Modus 2 AAN,No Clipping Mode 2 PÅ,Drugi tryb no-clip WŁĄCZONY,Modo sem colisão 2 ATIVADO,,Modul fără coliziune 2 ACTIVAT,Режим без столкновений 2 ВКЛЮЧЁН,Секундарни режим пролажења кроз зидове УКЉУЧЕНО,Klipsleme Yok Modu 2 AÇIK -No Clipping Mode 2 OFF,STSTR_NC2OFF,,,,Bezkolizní režim 2 VYP,Ikke-kollisionstilstand 2 FRA,Nicht-Kollisionsmodus 2 AUS,Noclip λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Reĝimo de Neniu Tondado 2 MALŜALTITA,Modo de traspaso 2 DESACTIVADO,,Seinänläpikulkutila 2 POIS PÄÄLTÄ,Collisions 3D ON,Falonátmenés 2 Mód KI,No Clipping 2 DISATTIVATO,壁抜けモード2: オフ,노 클립 모드 2 끔,Geen Clipping Modus 2 OFF,Ingen klippemodus 2 AV,Drugy tryb no-clip WYŁĄCZONY,Modo sem colisão 2 DESATIVADO,,Modul fără coliziune 2 DEZACTIVAT,Режим без столкновений 2 ОТКЛЮЧЁН,Секундарни режим пролажења кроз зидове ИСКЉУЧЕНО,Klipsleme Yok Modu 2 KAPALI +",자기 혼자서 벌벌 떨고 있다,Je wordt bang van jezelf,Du skremmer deg selv,Przestraszyłeś się,Você se assusta,Assustas-te a ti propri@[ao_ptb],Te speri pe tine însuți,Что это было?,Плашите самог себе,Du skrämmer dig själv.,Kendini korkutuyorsun.,Ви налякали себе +You start to rave,HUSTR_TALKTOSELF4,,,,Začneš pařit.,Du begynder at rave,Du beginnst zu toben,Αρχίζεις να ουρλίαζεις,Vi komencas frenezi,Empiezas a delirar,,Alat hourailla,Vous commencez à délirer!,Reszketni kezdesz,Inizi a delirare,イカレ始めた,횡설수설하기 시작했다,Je begint te razen,Du begynner å rave,Zaczynasz wariować,Você começa a delirar,Começas a delirar,Începi să aiurezi,Вы бредите.,Брбљате,Du börjar rasa.,Çıldırmaya başlıyorsun,Ви починаєте марити +You've lost it...,HUSTR_TALKTOSELF5,,,,Kleplo ti...,Du har mistet den...,Du verlierst den Verstand...,Το έχασες,Vi freneziĝis...,Te has vuelto loc@[ao_esp]...,Te volviste loc@[ao_esp]...,Olet seonnut...,Vous avez perdu les pédales...,Eldobod az agyad...,Sei andato...,我を失った...,미치기 시작했다...,Je bent het kwijt,You've lost it...,Oszalałeś...,Você enlouqueceu...,Enlouqueceste,Ai luat-o pe ulei...,Какая досада...,Лудите...,Du har förlorat det...,Kaybettin...,Як сумно... +[Message Sent],HUSTR_MESSAGESENT,,,,[Zpráva odeslána],[besked sendt],[Nachricht gesendet],[Στάλθηκε],[Mesaĝo sendita],[Mensaje enviado],,[Viesti lähetetty],[Message Envoyé],[Üzenet elküldve],[Messaggio Inviato],[メッセージ送信],[메시지가 전달됨],[Bericht verzonden],[Melding sendt],[Wiadomość wysłana],[Mensagem enviada],,[Mesaj Trimis],[Сообщение отправлено],[Порука послата],[Meddelande skickat],[Mesaj Gönderildi],[Повідомлення відправлено] +,,Cheats,,,,,,,,,,,,,,,,,,,,,,,,,, +Music Change,STSTR_MUS,,,,Změna hudby,Musik Ændring,Musikwechsel,Άλλαξε μουσική,Muzikŝanĝo,Cambio de música,,Musiikin vaihtaminen,Changement de Musique,Zene Váltás,Cambio di musica,music変更,음악 전환,Muziek veranderen,Music Change,Zmieniono muzykę,Trocando música,Mudar a música,Schimbare muzică...,Смена музыки,Промена музике,Musikbyte,Müzik Değişimi,Зміна музики +Impossible Selection,STSTR_NOMUS,,,,Nemožný výběr,Umuligt valg,Falsche Auswahl,Αδήνατη επιλογή,Malebla Elektaĵo,Selección imposible,,Valinta ei mahdollinen,Séléction Impossible!,Lehetetlen Kiválasztás,Selezione impossibile,その変更は不可能だ,불가능한 선택입니다,Onmogelijke selectie,Umulig valg,Niemożliwy wybór,Seleção impossível,,Selectare Imposibilă,Неверный выбор,НЕМОГУЋИ ИЗБОР,Omöjligt val,İmkansız Seçim,НЕКОРЕКТНИЙ ВИБІР +Degreelessness Mode ON,STSTR_DQDON,,,,Nesmrtelnost ZAP,Gradeløs tilstand TIL,Unverwundbarkeit AN,Θεική λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Nevundebla Reĝimo ŜALTITA,Invulnerabilidad ACTIVADA,,Kuolemattomuustila PÄÄLLÄ,Invulnérabilité ON ,Sérthetetlenség Mód BE,Modalità Invincibilità ATTIVATA,無敵モード: オン,무미건조한 모드 켬,Gegradeloosheid modus AAN,Gradløshetsmodus PÅ,Niewrażliwość WŁĄCZONA,Modo invencível ATIVADO,,Modul invincibil ACTIVAT,Безграмотность ВКЛЮЧЕНА,Нерањивост УКЉУЧЕНА,Gradlöshetsläge på,Dokunulmazlık Modu AÇIK,Безсмертя ввімкнено +Degreelessness Mode OFF,STSTR_DQDOFF,,,,Nesmrtelnost VYP,Gradeløs tilstand FRA,Unverwundbarkeit AUS,Θεική λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Nevundebla Reĝimo MALŜALTITA,Invulnerabilidad DESACTIVADA,,Kuolemattomuustila POIS PÄÄLTÄ,Invulnérabilité OFF,Sérthetetlenség Mód KI,Modalità Invincibilità DISATTIVATA,無敵モード: オフ,무미건조한 모드 끔,Gegradeloosheid modus UIT,Gradløshetsmodus AV,Niewrażliwość WYŁĄCZONA,Modo invencível DESATIVADO,,Modul Invincibil DEZACTIVAT,Безграмотность ОТКЛЮЧЕНА,Нерањивост ИСКЉУЧЕНА,Gradlöshetsläge av,Dokunulmazlık Modu KAPALI,Безсмертя вимкнено +Ultimate Degreelessness Mode ON,STSTR_DQD2ON,,,,Supernesmrtelnost ZAP,Ultimativ gradløs tilstand TIL,Ultimative Unverwundbarkeit AN,Απόλητη θεική λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Pleja Nevundebla Reĝimo ŜALTITA,Invulnerabilidad absoluta ACTIVADA,,Varma kuolemattomuustila PÄÄLLÄ,Parfaite Invulnérabilité ON,Tökéletes Sérthetetlenség Mód BE,Modalità Invincibilità Ultima ATTIVATA,究極無敵モード: オン,엄청나게 무미건조한 모드 켬,Uiteindelijke Gegradeloosheid modus AAN,Ultimativ gradløshetsmodus PÅ,Maksymalna niewrażliwość WŁĄCZONA,Modo invencível supremo ATIVADO,,Modul Invincibilitate Supremă ACTIVAT,Полная безграмотность ВКЛЮЧЕНА,Ултимативна нерањивост УКЉУЧЕНА,Ultimat gradlöshetsläge på,Nihai Dokunulmazlık Modu AÇIK,Повне безсмертя ввімкнено +Ultimate Degreelessness Mode OFF,STSTR_DQD2OFF,,,,Supernesmrtelnost VYP,Ultimativ gradløs tilstand FRA,Ultimative Unverwundbarkeit AUS,Απόλητη θεική λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Pleja Nevundebla Reĝimo MALŜALTITA,Invulnerabilidad absoluta DESACTIVADA,,Varma kuolemattomuustila POIS PÄÄLTÄ,Parfaite Invulnérabilité OFF,Tökéletes Sérthetetlenség Mód KI,Modalità Invincibilità Ultima DISATTIVATA,究極無敵モード: オフ,엄청나게 무미건조한 모드 끔,Uiteindelijke Gegradeloosheid modus UIT,Ultimativ gradløshetsmodus AV,Maksymalna niewrażliwość WYŁĄCZONA,Modo invencível supremo DESATIVADO,,Modul Invincibilitate Supremă DEZACTIVAT,Полная безграмотность ОТКЛЮЧЕНА,Ултимативна нерањивост ИСКЉУЧЕНА,Ultimat gradlöshetsläge av,Nihai Dokunulmazlık Modu KAPALI,Повне безсмертя вимкнено +Very Happy Ammo Added,STSTR_KFAADDED,,,,Velmi veselá munice přidána,Meget lykkelig Ammo tilføjet,Munition hinzugefügt,Πάρα Πολύ Χαρούμενα Πυρομαχηκά Προστέθηκαν,Tre Feliĉa Municio Aldonita,Munición añadida hasta el tope,,Täysaseistus,Armement Maximum!,Összes Lőszer Megadva,Equipaggiamento Completato,とても満足する武器弾薬を受け取った,아주 행복한 탄약 추가됨,Zeer gelukkige munitie toegevoegd,Veldig glad ammunisjon lagt til,Bardzo szczęśliwa amunicja dodana,Equipamento completo,,Echipament complet,Боезапас на счастье пополнен,Веома Срећна Муниција Додана,Mycket lycklig ammunition har lagts till,Çok Mutlu Cephane Eklendi,Спорядження поповнено +Ammo (no keys) Added,STSTR_FAADDED,,,,Munice (bez klíčú) přidána,Ammo (ingen nøgler) Tilføjet,Munition (keine Schlüssel) hinzugefügt,Πυρομαχικά (Όχι κλειδία) προστέθηκαν,Municio (neniuj ŝlosiloj) Aldonita,Munición añadida (sin llaves),,Täysaseistus (ilman avaimia),Arsenal ajouté. (Pas de clés!),Lőszer (nincsenek kulcsok) Megadva,Equipaggiamento Completato (senza chiavi),武器弾薬(鍵なし)を受け取った,탄약(열쇠 없이) 추가됨,Munitie (geen sleutels) toegevoegd,Ammo (ingen nøkler) Lagt til,Amunicja (bez kluczy) dodana,Equipamento completo (sem chaves),,Echipament complet (fără muniție),Боезапас пополнен (без ключей),Муниција (без кључева) Додана,Ammo (inga nycklar) Tillagd,Cephane (anahtar yok) Eklendi,Спорядження поповнено (без ключів) +No Clipping Mode ON,STSTR_NCON,,,,Bezkolizní režim ZAP,Ikke-kollisionstilstand TIL,Nicht-Kollisionsmodus AN,Noclip λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Reĝimo de Neniu Tondado ŜALTITA,Modo de traspaso ACTIVADO,,Seinänläpikulkutila PÄÄLLÄ,Collisions OFF,Falonátmenés Mód BE,No Clipping ATTIVATO,壁抜けモード: オン,노 클립 모드 켬,Geen Clipping Modus AAN,Ingen klipping-modus PÅ,Tryb no-clip WŁĄCZONY,Modo sem colisão ATIVADO,,Modul fără coliziune ACTIVAT,Режим без столкновений ВКЛЮЧЕН,Пролажење кроз зидове УКЉУЧЕНО,Inget klippningsläge på,Klipsleme Yok Modu AÇIK,"Прохід крізь стіни +ВВІМКНЕНО" +No Clipping Mode OFF,STSTR_NCOFF,,,,Bezkolizní režim VYP,Ikke-kollisionstilstand FRA,Nicht-Kollisionsmodus AUS,Noclip λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Reĝimo de Neniu Tondado MALŜALTITA,Modo de traspaso DESACTIVADO,,Seinänläpikulkutila POIS PÄÄLTÄ,Collisions ON,Falonátmenés Mód KI,No Clipping DISATTIVATO,壁抜けモード: オフ,노 클립 모드 끔,Geen Clipping Modus OFF,Ingen klippemodus AV,Tryb no-clip WYŁĄCZONY,Modo sem colisão DESATIVADO,,Modul fără coliziune DEZACTIVAT,Режим без столкновений ОТКЛЮЧЕН,Пролажење кроз зидове ИСКЉУЧЕНО,Inget klippningsläge av,Klipsleme Yok Modu KAPALI,"Прохід крізь стіни +ВИМКНЕНО" +No Clipping Mode 2 ON,STSTR_NC2ON,,,,Bezkolizní režim 2 ZAP,Ikke-kollisionstilstand 2 TIL,Nicht-Kollisionsmodus 2 AN,Δέυτερη noclip λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Reĝimo de Neniu Tondado 2 ŜALTITA,Modo de traspaso 2 ACTIVADO,,Seinänläpikulkutila 2 PÄÄLLÄ,Collisions 3D OFF,Falonátmenés 2. Mód BE,No Clipping 2 ATTIVATO,壁抜けモード2: オン,노 클립 모드 2 켬,Geen Clipping Modus 2 AAN,No Clipping Mode 2 PÅ,Drugi tryb no-clip WŁĄCZONY,Modo sem colisão 2 ATIVADO,,Modul fără coliziune 2 ACTIVAT,Режим без столкновений 2 ВКЛЮЧЁН,Секундарни режим пролажења кроз зидове УКЉУЧЕНО,Inget klippningsläge 2 på,Klipsleme Yok Modu 2 AÇIK,"Проліт крізь стіни +ВВІМКНЕНО" +No Clipping Mode 2 OFF,STSTR_NC2OFF,,,,Bezkolizní režim 2 VYP,Ikke-kollisionstilstand 2 FRA,Nicht-Kollisionsmodus 2 AUS,Noclip λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Reĝimo de Neniu Tondado 2 MALŜALTITA,Modo de traspaso 2 DESACTIVADO,,Seinänläpikulkutila 2 POIS PÄÄLTÄ,Collisions 3D ON,Falonátmenés 2 Mód KI,No Clipping 2 DISATTIVATO,壁抜けモード2: オフ,노 클립 모드 2 끔,Geen Clipping Modus 2 OFF,Ingen klippemodus 2 AV,Drugy tryb no-clip WYŁĄCZONY,Modo sem colisão 2 DESATIVADO,,Modul fără coliziune 2 DEZACTIVAT,Режим без столкновений 2 ОТКЛЮЧЁН,Секундарни режим пролажења кроз зидове ИСКЉУЧЕНО,Inget klippningsläge 2 av,Klipsleme Yok Modu 2 KAPALI,"Проліт крізь стіни +ВИМКНЕНО" "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp",STSTR_BEHOLD,"“inVuln”: Invulnerability sphere “Str”: Berserk “Inviso”: Blur sphere “Rad”: Radiation-shielding suit “Allmap”: Computer area map “Lite-amp”: Light-amplification visor",,,"nesmrt(V), (S)íla, nev(I)d, (R)ad, m(A)pa nebo svět(L)o","inVuln, Str, Inviso, Rad, Allmap, eller Lite-amp","inVuln, Str, Inviso, Rad, Allmap, oder Lite-amp",,"inVuln, Str, Inviso, Rad, Allmap, aŭ Lite-amp","inVuln, Str, Inviso, Rad, Allmap, o Lite-amp.",,"haavoittumattomuus (V), voima (S), näkymättömyys (I), koko kartta (A) tai valonvahvistus (L)","in V ulnérable, S urpuissance, I nvisible, p R otection, c A rte, où L umière?","Sérthetetlenség (V), berzerker mód (S), láthatatlanság (i), védőRuha, térkép (A), vagy éjjelLátó sisak","inVuln, berSerk, Invisib, tuta anti-Rad, mAppa tutta, o amplif-Luce","v,i,s,a,r,l の何れかを選べ","무적, 광전사, 투명, 보호복, 지도, 아니면 바이저","onSterv, Bzk, Inviso, Rad, Allmap, of Lvizier","inVuln, Str, Inviso, Rad, Allmap eller Lite-forsterker","niezniszczalność (V), siła (S), niewidzialność (I), kombinezon (R), mapa (A) lub gogle noktowizyjne (L)","Invulnerabilidade (V), Frenesi (S), Invisibilidade (I), Antirradiação (R), Mapa Completo (A) ou Amplificação de Luz (L)",,"InVinc, Forță amplificată, Invizib, Hartă completă, sau -Vedere amplificată","Бессм. (V), сила (S), невид. (I), кост. (R), п. карта (A), ус. света (L).","нерањ., снага, невидљ., радиј., мапа или ноћ. визор", -Power-up Toggled,STSTR_BEHOLDX,,,,Power-up vybrán,Strømoptagelse Skiftet,Verbesserung umgeschaltet!,,Plifortigaĵo Baskuligita,Poder alternado,,Tehostin kytketty,Amélioration Activée!,Képesség hozzáadva,Power-up concesso/tolto,パワーアップ 適用,파워-업 전환됨,Versterking ingeschakeld,Oppstart aktivert,Wzmocnienie aktywowane,Potencializador ativado,,Putere Activată,Усиление включено,Супер моћи заглављене,Güç Açma Değiştirildi -... doesn't suck - GM,STSTR_CHOPPERS,"Printed when entering the idchoppers cheat, which gives the player a chainsaw",,,... není cucák - GM,... er ikke dårlig - GM,... gar nicht übel - GM,... δέν είναι χάλια - GW,... ne aĉas - GM,... no apesta - GM,,... ei ole syvältä - GM,... C'est pas de la merde. - GM,... nem annyira gáz - GM,... non fa schifo - GM,...わるかぁねえぞ --gm,... 후진 건 아니지만 - GM,.... is niet slecht - GM,... suger ikke - GM,... nie ssie - GM,... não tá ruim — GM,,... nu e jalnic - GM,...не отстой — GM,... није лоша - GM,... berbat değil - GM +Vedere amplificată","Бессм. (V), сила (S), невид. (I), кост. (R), п. карта (A), ус. света (L).","нерањ., снага, невидљ., радиј., мапа или ноћ. визор","inVuln, Str, Inviso, Rad, Allmap eller Lite-amp",,"Безсм. (V), берс. (S), нев. (I), кос. (R), карта (A), ПНВ (L)." +Power-up Toggled,STSTR_BEHOLDX,,,,Power-up vybrán,Strømoptagelse Skiftet,Verbesserung umgeschaltet!,,Plifortigaĵo Baskuligita,Poder alternado,,Tehostin kytketty,Amélioration Activée!,Képesség hozzáadva,Power-up concesso/tolto,パワーアップ 適用,파워-업 전환됨,Versterking ingeschakeld,Oppstart aktivert,Wzmocnienie aktywowane,Potencializador ativado,,Putere Activată,Усиление включено,Супер моћи заглављене,Start av strömmen växlade,Güç Açma Değiştirildi,Підсилення ввімкнено +... doesn't suck - GM,STSTR_CHOPPERS,"Printed when entering the idchoppers cheat, which gives the player a chainsaw",,,... není cucák - GM,... er ikke dårlig - GM,... gar nicht übel - GM,... δέν είναι χάλια - GW,... ne aĉas - GM,... no apesta - GM,,... ei ole syvältä - GM,... C'est pas de la merde. - GM,... nem annyira gáz - GM,... non fa schifo - GM,...わるかぁねえぞ --gm,... 후진 건 아니지만 - GM,.... is niet slecht - GM,... suger ikke - GM,... nie ssie - GM,... não tá ruim — GM,,... nu e jalnic - GM,...не отстой — GM,... није лоша - GM,... suger inte - GM,... berbat değil - GM,... непогано — г.м. Changing Level...,STSTR_CLEV,,,,Měním level...,Ændring af niveau ...,Wechsle Level...,Αλλαγή πίστας...,Ŝanĝante Nivelon...,"Cambiando de nivel... ",,Vaihdetaan tasoa...,Changement de niveau...,Pályaváltás...,"Cambio di livello... ",場所を変更...,레벨 변경 중...,Level veranderen...,Endre nivå ...,Zmienianie poziomu...,Trocando de fase...,"A mudar de nível... ",Schimbare hartă...,"Смена уровня... -",Мењам ниво...,Seviye Değiştirme... -Buddha mode ON,TXT_BUDDHAON,,,,Buddha mód ZAP,Buddha-tilstand TIL,Buddhamodus AN,Λειτουργία Βουδα ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Budha reĝimo ŜALTITA,Modo Buda ACTIVADO,,Buddhatila PÄÄLLÄ,Mode Bouddha ON,Buddha Mód BE,Modalità Buddha ATTIVATA,ブッダモード: オン,부처 모드 켬,Boeddha-modus AAN,Buddha-modus PÅ,Tryb Buddy WŁĄCZONY,Modo Buda ATIVADO,,Modul Buddha ACTIVAT,Режим Будды ВКЛЮЧЁН,Буда Мод УКЉУЧЕН,Buda modu AÇIK -Buddha mode OFF,TXT_BUDDHAOFF,,,,Buddha mód VYP,Buddha-tilstand FRA,Buddhamodus AUS,Λειτουργία Βουδα ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Budha reĝimo MALŜALTITA,Modo Buda DESACTIVADO,,Buddhatila POIS PÄÄLTÄ,Mode Bouddha OFF,Buddha Mód KI,Modalità Buddha DISATTIVATA,ブッダモード: オフ,부처 모드 끔,Boeddha-modus UIT,Buddha-modus AV,Tryb Buddy WYŁĄCZONY,Modo Buda DESATIVADO,,Modul Buddha DEZACTIVAT,Режим Будды ОТКЛЮЧЁН,Буда Мод ИСКЉУЧЕН,Buda modu KAPALI -Ultimate Buddha Mode ON,TXT_BUDDHA2ON,,,,Super Buddha mód ZAP,Ultimate Buddha-tilstand TIL,Ultimativer Buddhamodus AN,Λειτουργία Απόλητου Βουδα ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Pleja Budha Reĝimo ŜALTITA,Modo Buda Supremo ACTIVADO,,Korkein buddhatila PÄÄLLÄ,Mode Bouddha Ultime ON,Tökéletes Buddha Mód BE,Modalità Ultimo Buddha ATTIVATA,究極ブッダモード: オン,나무 아미타불 모드 켬,Ultieme Boeddha-modus AAN,Ultimativ Buddha-modus PÅ,Maksymalny Tryb Buddy WŁĄCZONY,Modo Buda supremo ATIVADO,,Modul Buddha Suprem ACTIVAT,Окончательный режим Будды ВКЛЮЧЁН,Ултимативни Буда Мод УКЉУЧЕН,Nihai Buda Modu AÇIK -Ultimate Buddha Mode OFF,TXT_BUDDHA2OFF,,,,Super Buddha mód VYP,Ultimate Buddha-tilstand FRA,Ultimativer Buddhamodus AUS,Λειτουργία Απόλητου Βουδα ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Pleja Budha Reĝimo MALŜALTITA,Modo Buda Supremo DESACTIVADO,,Korkein buddhatila POIS PÄÄLTÄ,Mode Bouddha Ultime OFF,Tökéletes Buddha Mód KI,Modalità Ultimo Buddha DISATTIVATA,究極ブッダモード: オフ,나무 아미타불 모드 끔,Ultieme Boeddha-modus UIT,Ultimativ Buddha-modus AV,Maksymalny Tryb Buddy WYŁĄCZONY,Modo Buda supremo DESATIVADO,,Modul Buddha Suprem DEZACTIVAT,Окончательный режим Будды ОТКЛЮЧЁН,Ултимативни Буда Мод ИСКЉУЧЕН,Nihai Buda Modu KAPALI -Power on,TXT_CHEATPOWERON,,,,Energie ZAP,Evne TIL,Fähigkeit AN,Δύναμη ενεργοποιημένη,Povo ŝaltita,Poder activado,,Voima päällä,Pouvoir Activée,Energia BE,Potere ATTIVATO,パワー オン,파워 켬,Vermogen aan,Strøm PÅ,Zasilanie włączone,Poder ativado,,Putere activată,Сила активирована,Моћ УКЉУЧЕНА,Güç açık -Power off,TXT_CHEATPOWEROFF,,,,Energie VYP,Evne FRA,Fähigkeit AUS,Δύναμη άπενεργοποιημένη,Povo malŝaltita,Poder desactivado,,Voima pois päältä,Pouvoir Désactivée,Energia KI,Potere DISATTIVATO,パワー オフ,파워 끔,Vermogen uit,Slå AV,Zasilanie wyłączone,Poder desativado,,Putere dezactivată,Сила деактивирована,Моћ ИСКЉУЧЕНА,Güç kapalı -Full health,TXT_CHEATHEALTH,,,,Plné zdraví,Fuldt helbred,Volle Lebensenergie,Ολόκληρη υγεία,Plena sano,Salud al máximo,,Täysi terveys,Pleine Santé,Teljes életerő,Piena salute,ヘルス全回復,체력 완전 회복,Volledige gezondheid,Full helse,Pełne zdrowie,Saúde completa,Vida totalmente cheia,Sănătate completă,Полное здоровье,Здравље напуњено,Tam sağlık -All keys,TXT_CHEATKEYS,,,,Všechny klíče,Alle taster,Alle Schlüssel,Όλα τα κλειδία,Ĉiuj ŝlosiloj,Todas las llaves,,Kaikki avaimet,Toutes les Clés,Összes kulcs,Tutte le chiavi,キー全部,모든 열쇠,Alle sleutels,Alle taster,Wszystkie klucze,Todas as chaves,,Toate cheile,Все ключи,Сви кључеви,Tüm anahtarlar -Sound debug on,TXT_CHEATSOUNDON,,,,Debug zvuku ZAP,Sound debug TIL,Sound Debug AN,Debug ήχου ενεργοποιημένη,Sono-sencimiga reĝimo ŝaltita,Depuración de sonido activada,,Äänen vianmääritystila päällä,Débogage du son activé.,Hang debug BE,Debug del suono attivato,サウンドデバッグ オン,효과음 디버그 켬,Geluid debug aan,Lyd feilsøking PÅ,Debugowanie dźwięku włączone,Depuração de som ativada,,Debug sunet activat,Отладка звука включена,Дебаговање звука УКЉУЧЕНО,Ses hata ayıklama açık -Sound debug off,TXT_CHEATSOUNDOFF,,,,Debug zvuku VYP,Sound debug FRA,Sound Debug AUS,Debug ήχου άπενεργοποιημένη,Sono-sencimiga reĝimo malŝaltita,Depuración de sonido desactivada,,Äänen vianmääritystila pois päältä,Débogage du son désactivé.,Hang debug KI,Debug del suono disattivato,サウンドデバッグ オフ,효과음 디버그 끔,Geluid debug uit,Lyd feilsøking AV,Debugowanie dźwięku wyłączone,Depuração de som desativada,,Debug sunet dezactivat,Отладка звука отключена,Дебаговање звука ИСКЉУЧЕНО,Ses hata ayıklama kapalı -"Trying to cheat, eh? Now you die!",TXT_CHEATIDDQD,,,,"Pokoušíš se cheatovat, co? Teď zemřeš!","Prøver du at snyde, hva'? Nu dør du!","Versuchst zu betrügen, was? Nun stirbst du!","Προσπαθείς να εξαπατήσεις, ε? Τώρα πεθένεις!","Provas trompi, ĉu vi? Nun vi mortas! ","¿Tratando de hacer trampas, eh? ¡Muere!",,"Yrität huijata, vai? Nyt kuolet!","Tu essaie de tricher, hein? Maintenant tu meurs!","Csalni akarsz, mi? Most meghalsz!","Cerchi di barare, eh? Allora muori!",その名を唱えたな? 褒美に死をやろう!,치트 쓸려고? 그럼 죽어야지!,"Je wou valsspelen, hè? Nu ga je dood!",Prøver du å jukse? Nå dør du!,"Próbujesz oszukiwać, co? Teraz giń!","Tentando trapacear, né? Morra!","A fazer batota, é? Morre!","Încerci să trișezi, ei? Acum mori!","Жульничаешь, э? Так умри!","Покушаваш да вараш, ех? Сада умиреш!","Hile yapmaya çalışıyorsun, ha? Şimdi öleceksin!" -Cheater - you don't deserve weapons,TXT_CHEATIDKFA,,,,Podvodníku - nezasloužíš si zbraně,Snyder - du fortjener ikke våben,Betrüger - du verdienst keine Waffen,Απατεόνα δέν σου αξήζουν όπλα,Trompanto - vi ne meritas armilojn,Trampos@[ao_esp] - No mereces tener armas,,Huijari - et ansaitse aseita,Tricheur- Tu ne mérite pas d'armes!,Csaló - nem érdemelsz fegyvert!,Imbroglione - non meriti armi,不届き者め、貴様が偉業を成すはずがない,사기꾼놈! 너는 무기를 가질 자격이 없어!,Valsspeler - je verdient geen wapens.,Juksemaker - du fortjener ikke våpen,Oszust - nie zasługujesz na bronie,Trapaceiros não merecem armas,Batoteir@[ao_ptb] - Não mereces armamento,Trișor - Nu meriți arme,Жулик — ты не заслуживаешь оружия,Варалице - ти не заслужујеш оружје,"Hileci, silahları hak etmiyorsun." -Ticker on,TXT_CHEATTICKERON,,,,Počítadlo ZAP,Ticker TIL,Zähler AN,Χρονόμετρο ενεργοποιημένο,Nombrilo ŝaltita,Contador activado,,Laskuri päällä,Compteur allumé,Számláló BE,Ticker attivato,ティッカー オン,프레임 속도 표시 켬,Ticker aan,Ticker PÅ,Wskaźnik włączony,Contador ativado,,Ticăitoare activată,Счётчик включён,Бројач укључен,Ticker açık -Ticker off,TXT_CHEATTICKEROFF,,,,Počítadlo VYP,Ticker FRA,Zähler AUS,Χρονόμετρο άπενεργοποιημένο,Nombrilo malŝaltita,Contador desactivado,,Laskuri pois päältä,Compteur éteint,Számláló KI,Ticker disattivato,ティッカー オフ,프레임 속도 표시 끔,Ticker uit,Ticker AV,Wskaźnik wyłączony,Contador desativado,,Ticăitoare dezactivată,Счётчик отключён,Бројач искључен,Ticker kapalı -You got it,TXT_CHEATARTIFACTS3,,,,Máš to mít,Du fik det,Du hast es,Το πήρες,Vi akiris ĝin,Lo tienes,,Saamasi pitää,C'est à vous!,Megkaptad,Concesso,それを渡そう。,얻었다,Je hebt het,Du har det,Udało ci się,Concedido,,Ai ce-ți trebuie,Вы получили это,Уреду,Tamamdır. -"You got the Midas Touch, baby",TXT_MIDASTOUCH,,,,"Máš Midasův dotek, zlato","Du har Midas Touch, baby",Dagobert Duck lässt grüßen!,"Έχεις το αγγιγμα το Μίδα, μωρό.","Vi akiris la Tuŝon de Midas, kara","Tienes el toque de Midas, muchach@[ao_esp]",,"Kulta, sinulla on Midaksen kosketus",,"Minden arannyá válik amit megérintesz, öreg","Hai avuto il Tocco di Mida, baby",ミダス王の様だな、ベイビー,넌 미다스의 손을 얻었어 베이베!,"Je hebt de Midas Touch, schatje","Du har Midas Touch, baby","Zdobył@[irreg_3_pl] dotyk Midasa, skarbie","Você tem o Toque de Midas, baby","Tens o Toque de Midas, baby","Ai Atingerea lui Midas, dragule","Ты превращаешь всё в золото, детка!","Имаш златке руке, душо","Sende Midas Dokunuşu var, bebeğim" -You got the stuff!,TXT_GOTSTUFF,,,,Dostal jsi věci!,Du har det hele!,Du hast den Kram erhalten,Πήρες τηατ πράγματα !,Vi akiris la aĵojn!,¡Tienes un montón de cosas!,¡Tienes muchas cosas!,Sait kamppeet!,Voilà ton équipement!,Megkaptad a cuccot!,Hai avuto il materiale!,スタッフを手に入れた!,무언가를 얻었다!,Je hebt het spul!,Du har greiene!,Zdobył@[irreg_3_pl] parę rzeczy!,Você ganhou muitas coisas!,ganhaste muitas coisas!,Ai tot ce-ți trebuie!,Получены предметы!,Покупили сте ствари!,Mal sende! -Freeze mode on,TXT_FREEZEON,,,,Režim zamrznutí ZAP,Frysetilstand TIL,Gefriermodus AN,Παγομένη λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Movhalta reĝimo ŝaltita,Modo suspendido activado,,Jäädytystila päällä,Temps arrêté.,Fagyasztás BE,Modalità arresto del tempo attivata,フリーズモード オン,시간정지 켬,Bevriesmodus aan,Frysemodus PÅ,Tryb zamrożenia włączony,Modo congelado ativado,,Modul înghețat activat,Режим заморозки включён,Мод замрзавања УКЉУЧЕН,Dondurma modu açık -Freeze mode off,TXT_FREEZEOFF,,,,Režim zamrznutí VYP,Frysetilstand FRA,Gefriermodus AUS,Παγομένη λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Movhalta reĝimo malŝaltita,Modo suspendido desactivado,,Jäädytystila pois päältä,Le temps reprend son cours..,Fagyasztás KI,Modalità arresto del tempo disattivata,フリーズモード オフ,시간정지 끔,Bevriesmodus uit,Frysemodus AV,Tryb zamrożenia wyłączony,Modo congelado desativado,,Modul înghețat dezactivat,Режим заморозки отключён,Мод замрзавања ИСКЉУЧЕН,Dondurma modu kapalı -You feel strange...,TXT_STRANGE,,,,Cítíš se divně...,Du føler dig mærkelig...,Du fühlst dich merkwürdig...,Νιώθης περίεργα...,Vi sentas vin strange...,Te sientes extrañ@[ao_esp]...,,Sinulla on kummallinen olo...,Vous vous sentez mal à l'aise...,Furán érzed magad...,Ti senti strano...,これは奇妙な感じだな...,뭔가 이상한 기분이...,Je voelt je vreemd...,Du føler deg rar...,Dziwnie się czujesz...,Você está com uma sensação estranha...,Tu sentes-te estranh@[ao_ptb].,Te simți ciudat...,Вы чувствуете себя странно...,Осећате се чудно...,Garip hissediyorsun. -You feel even stranger.,TXT_STRANGER,,,,Cítíš se ještě divněji...,Du føler dig endnu mere mærkelig.,Du fühlst dich noch merkwürdiger,Νιώθης ακόμα πιό περίεργα...,Vi sentas vin eĉ pli strange.,Te sientes aún más extrañ@[ao_esp],,Olosi on vieläkin kummempi.,Vous vous sentez très mal à l'aise...,Még furábban érzed magad.,Ti senti ancora più strano.,これはかなり奇妙だ。,기분이 더더욱 이상해졌다.,Je voelt je nog vreemder.,Du føler deg enda merkeligere.,Czujesz się jeszcze dziwniej.,Você está com uma sensação mais estranha ainda.,Tu sentes-te ainda mais estranh@[ao_ptb].,Te simți și mai ciudat.,Вы чувствуете себя очень странно.,Осећате се врло чудно.,Daha da garip hissediyorsun. -You feel like yourself again.,TXT_NOTSTRANGE,,,,Cítíš se opět jako ty.,Du føler dig som dig selv igen.,Du fühlst dich wieder wie du selbst,Νιώθης σάν τον εαύτο σου ξανά...,Vi denove sentas vin kiel vi mem.,Te sientes como tu mism@[ao_esp] otra vez.,,Tunnet olevasi jälleen oma itsesi.,Vous vous sentez mieux.,Magadhoz tértél.,Ti senti di nuovo te stesso.,自分自身の様に感じている。,자기 자신처럼 생각하게 됐다.,Je voelt je weer als jezelf.,Du føler deg som deg selv igjen.,Znów czujesz się sobą.,Você se sente normal novamente.,Tu sentes-te normal novamente.,Ți-ai revenit în simțiri.,Вы снова чувствуете себя собой.,Поново се осећате као ви.,Tekrar kendin gibi hissediyorsun. -Lead boots on,TXT_LEADBOOTSON,,,,Olověné boty ZAP,Blystøvler TIL,Bleistiefel AN,Μολυβδένιες μπότες ΕΝΕΡΓΟΠΟΙΗΜΈΝΕΣ,Botoj el plumbo ŝaltita,Botas de plomo activadas,,Lyijysaappaat päällä,Bottes en plomb ON,Ólomcsizma BE,Stivali di Piombo ON,足枷 オン,납 부츠 켬,Loden laarzen aan,Blystøvler PÅ,Ołowiane buty włączone,Botas de chumbo ativadas,,Bocanci de plumb activați,Свинцовые сапоги надеты,Оловне чизме УКЉУЧЕНЕ,Kurşun çizmeler -Lead boots off,TXT_LEADBOOTSOFF,,,,Olověné boty VYP,Blystøvler FRA,Bleistiefel AUS,Μολυβδένιες μπότες ΆΠΕΝΕΡΓΟΠΟΙΗΜΕΝΕΣ,Botoj el plumbo malŝaltita,Botas de plomo desactivadas,,Lyijysaappaat pois päältä,Bottes en plomb OFF,Ólomcsizma KI,Stivali di Piombo OFF,足枷 オフ,납 부츠 끔,Loden laarzen uit,Blystøvler AV,Ołowiane buty wyłączone,Botas de chumbo desativadas,,Bocanci de plumb dezactivați,Свинцовые сапоги сняты,Оловне чизме ИСКЉУЧЕНЕ,Kurşun çizmeler kapalı -You feel lighter,TXT_LIGHTER,,,,Cítíš se lehčí,Du føler dig lettere,Du fühlst dich leichter,Νιώθης πιο ελαφρής,Vi sentas vin pli malpeze,Te sientes más liger@[ao_esp],,Tunnet olosi kevyemmäksi,Vous vous sentez très léger.,Könnyűnek érzed magad,Ti senti più leggero,体が軽くなった,가벼운 느낌이 든다,Je voelt je lichter,Du føler deg lettere,Czujesz się lżejsz@[adj_pl],Você se sente mais leve,Tu sentes-te mais leve,Te simți mai ușor,Вы чувствуете лёгкость.,Осећате лакоћу.,Daha hafif hissediyorsun -Gravity weighs you down,TXT_GRAVITY,,,,Gravitace tě táhne dolů,Tyngdekraften tynger dig ned,Schwerkraft belastet dich,Η βαρύτητα σε πιάνει.,Gravito pezigas vin,La gravedad te hace descender,,Painovoima painaa sinua alas,La gravité vous ramène au sol.,A gravitáció lehúz téged,La gravità ti riporta a terra,重力に従った,중력이 당신을 붙잡았다,Zwaartekracht werkt op je...,Tyngdekraften tynger deg ned,Grawitacja znów cię przyciąga,A gravidade volta a funcionar normalmente,A gravidade voltou ao normal,Gravitația te trage în jos,Гравитация тянет вас вниз.,Гравитација Вас вуче надоле.,Yerçekimi seni ağırlaştırır -No Target ON,TXT_NOTARGET_ON,,,,Neútočící příšery ZAP,Ingen mål TIL,notarget AN,Αστόχευτη λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Neniu Celo ŜALTITA,No Objetivo ACTIVADO,,Hyökkäämättömyystila PÄÄLLÄ,Monstres aveugles et sourds ON,Nem támadnak a szörnyek BE,Modalità Mostri ciechi e sordi ATTIVATA,ノーターゲット オン,적 표적 감지 켬,Geen doelwit AAN,No Target PÅ,Głuche i Ślepe Potwory WŁĄCZONE,Sem alvos ATIVADO,,Modul Inamici fără Țintă ACTIVAT,Незаметность ВКЛЮЧЕНА,Нема мете УКЉУЧЕНО,Hedef Yok AÇIK -No Target OFF,TXT_NOTARGET_OFF,,,,Neútočící příšery VYP,Ingen mål FRA,notarget AUS,Αστόχευτη λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Neniu Celo MALŜALTITA,No Objetivo DESACTIVADO,,Hyökkäämättömyystila POIS PÄÄLTÄ,Monstres aveugles et sourds OFF,Nem támadnak a szörnyek KI,Modalità Mostri ciechi e sordi DISATTIVATA,ノーターゲット オフ,적 표적 감지 끔,Geen doelwit UIT,No Target AV,Głuche i Ślepe Potwory WYŁĄCZONE,Sem alvos DESATIVADO,,Modul Inamici fără Țintă DEZACTIVAT,Незаметность ОТКЛЮЧЕНА,Нема мете ИСКЉУЧЕНО,Hedef Yok KAPALI -"""Quake with fear!""",TXT_ANUBIS_ON,,,,„Třeste se strachy!“,"""Skælv af frygt!""","""Bebe vor Angst!""","""Τρέμε με φόβο!""","""Tremu pro timo!""","""¡Temblad de miedo!""","""Estremecete de Miedo!""","""Vapise pelosta!""",« Tremblez de terreur! »,"""Reszkess, halandó!""","""Trema con terrore!""",恐れおののけ!,공포에 떨어라!,„Beving van angst!“,Skjelv av frykt!,"""Trzęś się ze strachu""","""Trema de medo!""","""Trema com medo!""","""Tremură de Frică!""",«Дрожите от страха!»,„Дрхтите у страху!“,Korkudan titre! -No more Ogre Armor,TXT_ANUBIS_OFF,,,,Už žádné zlobří brnění,Ikke mere troldepanser,Keine Ogerrüstung mehr,Καθόλου δρακοντική πανοπλία πια,Ne plu Ogrokiraso,No más armadura de Ogro,,Ei enää örkkipanssaria,Plus d'armure d'ogre,Ogre pajzs lejárt,Niente più armatura Ogre,オーガアーマーはもう嫌,오거 갑옷은 이제 없다.,Geen Ogre Pantser meer,Ikke mer Ogre Armor,Nigdy więcej Pancerza Ogrów,Chega de Armadura de Ogro,Chega de Armadura de Ogre,Gata cu Armura de Căpcăun,Броня огра снята,Нема више бауков оклоп,Artık Ogre Zırhı yok -chasecam ON,TXT_CHASECAM_ON,,,,Pohled z třetí osoby ZAP,chasecam TIL,chasecam AN,Κάμερα τρίτου πρωσώπου ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Ĉaskamerao ŜALTITA,Cámara de seguimiento ACTIVADA,,Seurantakamera PÄÄLLÄ,,követő kamera BE,Modalità camera da inseguimento ATTIVATA,チェイスカメラ オン,3인칭 카메라 켬,Chasecam AAN,chasecam PÅ,kamera śledzenia WŁĄCZONA,Câmera em terceira pessoa ATIVADA,Câmara em Terceira Pessoa ATIVADA,Perspectivă la Persoana a 3-a ACTIVATĂ,Вид от третьего лица ВКЛЮЧЁН,Чејс-кам УКЉУЧЕН,Chasecam AÇIK -chasecam OFF,TXT_CHASECAM_OFF,,,,Pohled z třetí osoby VYP,chasecam FRA,chasecam AUS,Κάμερα τρίτου πρωσώπου ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Ĉaskamerao MALŜALTITA,Cámara de seguimiento DESACTIVADA,,Seurantakamera POIS PÄÄLTÄ,,követő kamera KI,Modalità camera da inseguimento DISATTIVATA,チェイスカメラ オフ,3인칭 카메라 끔,Chasecam UIT,chasecam AV,kamera śledzenia WYŁĄCZONA,Câmera em terceira pessoa DESATIVADA,Câmara em Terceira Pessoa DESATIVADA,Perspectivă la Persoana a 3-a DEZACTIVATĂ,Вид от третьего лица ОТКЛЮЧЁН,Чејс-кам ИСКЉУЧЕН,Chasecam KAPALI -1 baddie killed,TXT_BADDIE_KILLED,,,,1 zloun zabit,1 baddie dræbt,1 Bösewicht getötet,Ενας κακός πέθανε,1 malbonulo mortigita,1 malo matado,,1 pahis tapettu,1 enemi tué,1 rosszfiú kinyírva,Ucciso 1 maligno,1 体 殺した,1 명의 나쁜놈이 사살됨.,1 slechterik gedood,1 skurk drept,1 zabity przeciwnik,1 inimigo morto,,1 slab ucis,1 плохиш убит,Један зликовац убијен,1 kötü öldürüldü -%d baddies killed,TXT_BADDIES_KILLED,,,,%d zlounů zabito,%d baddies dræbt,%d Bösewichte getötet,%d τον κακόν πέθαναν,%d malbonuloj mortigitaj,%d malos matados,,%d pahista tapettu,%d enemis tués,%d rosszfiú kinyírva,Uccisi %d maligni,%d 体 殺した,%d 명의 나쁜놈들이 사살됨.,%d slechteriken gedood,%d skurker drept,%d zabitych przeciwników,%d inimigos mortos,,%d slabi uciși,Плохишей убито: %d,%d зликовца убијено,%d kötüler öldürüldü -1 monster killed,TXT_MONSTER_KILLED,,,,1 příšera zabita,1 monster dræbt,1 Monster getötet,Ένα τέρας πέθανε,1 monstro mortigita,1 monstruo matado,,1 hirviö tapettu,1 monstre tué,1 szörny kinyírva,Ucciso 1 mostro,1 匹 殺した,1 마리의 몬스터가 사살됨.,1 monster gedood,1 monster drept,1 zabity potwór,1 monstro morto,,1 monstru ucis,1 монстр убит,Једно чудовиште убијено,1 canavar öldürüldü -%d monsters killed,TXT_MONSTERS_KILLED,,,,%d příšer zabito,%d monster dræbt,%d Monster getötet,%d τον τεράτων πέθαναν,%d monstroj mortigitaj,%d monstruos matados,,%d hirviötä tapettu,%d monstres tués,%d szörny kinyírva,Uccisi %d mostri,%d 匹 殺した,%d 마리의 몬스터들이 사살됨.,%d monsters gedood,%d monstre drept,%d zabitych potworów,%d monstros mortos,,%d monștri uciși,Убито монстров: %d,%d чудовишта убијено,öldürülen %d canavar -Unable to resurrect. Player is no longer connected to its body.,TXT_NO_RESURRECT,,,,"Oživení není možno, hráč už není spojen se svým tělem.",Kan ikke genoplive. Spilleren er ikke længere forbundet med sin krop.,Kann nicht wiederbeleben. Der Spieler ist nicht mehr mit seinem Körper verbunden.,"Ανάσταση αδύνατη, ο παίχτης δεν είναι πια στο σώμα @[pro4_gr]","Ne kapablas revivi. Ludanto ne plu -estas konektita al sia korpo.",Imposible resucitar. El jugador ya no está conectado a su cuerpo.,,Ei mahdollista herätä henkiin. Pelaaja ei ole enää yhteydessä ruumiiseensa.,Impossible de ressuciter. Le joueur n'est plus connecté à son corps.,Nem sikerült a felélesztés. A játékos nincs összekötve a testtel.,Impossibile resuscitarsi. Il giocatore non è più connesso al suo corpo.,復活できない。プレイヤーはこの体に宿っていない。,부활할 수 없습니다. 플레이어는 더 이상 육체와 연결돼있지 않습니다.,Kan niet reanimeren. De speler is niet langer verbonden met zijn lichaam.,Kan ikke gjenoppstå. Spilleren er ikke lenger koblet til kroppen sin.,Nie można wskrzesić. Gracz nie jest już połączony z resztą swojego ciała.,"Impossível ressuscitar. O jogador não -está mais ligado ao próprio corpo.",,Imposibil de înviat. Jucătorul nu mai e conectat la cadavru.,Воскрешение невозможно. Игрок больше не соединён с трупом.,Немогуће оживети. Играч није више повезан са својим телом.,Diriltilemiyor. Oyuncu artık bedenine bağlı değil. -All Artifacts!,TXT_ALL_ARTIFACTS,,,All Artefacts!,Všechny artefakty!,Alle artefakter!,Alle Artefakte!,Όλα τα τεχνουργίματα!,Ĉiuj Artefaktoj!,¡Todos los Artefactos!,,Kaikki artefaktit!,Tous les artéfacts!,Összes értéktárgy!,Tutti gli Artefatti!,全アーティファクト!,모든 유물들!,Alle artefacten!,Alle artefakter!,Wszystkie Artefakty!,Todos os artefatos!,,Toate Artefactele!,Все артефакты!,Сви артифакти!,Tüm eserler! -What do you want to kill outside of a game?,TXT_WHAT_KILL,,,,"Co chceš zabít, když nejsi ve hře?",Hvad vil du dræbe uden for et spil?,Was willst du eigentlich außerhalb eines Spiels töten?,Τί θέλεις να σκοτώσεις έξω απο ένα παιχνίδι ?,Kion vi volas mortigi ekster ludo?,¿Qué intentas matar fuera de una partida?,,Mitä haluat tappaa pelin ulkopuolella?,Que voulez-vous tuer en dehors d'une partie?,Mit tudnál megölni játékon kívül?,Cosa vorresti uccidere fuori dal gioco?,ゲーム外で何を殺す気だ?,게임 밖에서 무엇을 죽이고 싶습니까?,Wat wil je buiten een spel om doden?,Hva vil du drepe utenfor et spill?,Co ty chcesz zabić poza grą?,O que você gostaria de matar fora de um jogo?,,Ce vrei să ucizi în afara unui joc?,Что вы хотите убить вне игры?,Шта желите да убијете ван игре?,Oyun dışında ne öldürmek istiyorsun? -Frozen player properties turned off,TXT_NOT_FROZEN,,,,Vlastnosti držící hráče na místě vypnuty,Frysningstilstand er slået fra.,Gefrier-Modus abgeschaltet.,Η ιδιότητες ενος παγομένου παίχτη απενεργοποίθηκαν,Atributoj de movhaltitaj ludantoj malŝaltitaj,Propiedades de jugador congelado desactivadas,,Jäätyneen pelaajan ominaisuudet kytketty pois päältä,Propriété gelée du joueur annulée.,Fagyasztott játékos tulajdonságai kikapcsolva,Proprietà del giocatore ghiacciato disattivate,凍ったプレイヤーのプロパティを無効化,플레이어 정지 속성이 꺼졌습니다.,Eigenschappen van de bevroren speler uitgeschakeld,Frosne spilleregenskaper slått av,Właściwości zamrożonego gracza wyłączone,Propriedades de jogador congelado desativadas,,Proprietăți jucători înghețați DEZACTIVATE,Свойства замороженного игрока отключены,Смрзнути играчи искључени,Dondurulmuş oyuncu özellikleri kapatıldı -,,Automap,,,,,,,,,,,,,,,,,,,,,,,, -Follow Mode OFF,AMSTR_FOLLOWOFF,,,,Režim sledování VYP,Følg-tilstand TIL,Folgen-Modus AUS,Ακολούθηση ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Sekvigreĝimo MALŜALTITA,Modo de seguimiento DESACTIVADO,,Seuraamistila POIS PÄÄLTÄ,Suivi du Joueur OFF,Követés mód KI,Mappa scorribile ATTIVATA,追従モード: オフ,추적 모드 끔,Volgmodus UIT,Følgemodus AV,Tryb śledzenia WYŁĄCZONY,Modo de seguimento DESATIVADO,,Mod Urmărire DEZACTIVAT,Привязка к игроку ОТКЛЮЧЕНА,Праћење ИСКЉУЧЕНО,Takip Modu KAPALI -Follow Mode ON,AMSTR_FOLLOWON,,,,Režim sledování ZAP,Følg-tilstand FRA,Folgen-Modus AN,Ακολούθηση ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Sekvigreĝimo ŜALTITA,Modo de seguimiento ACTIVADO,,Seuraamistila PÄÄLLÄ,Suivi du Joueur ON,Követés mód BE,Mappa scorribile DISATTIVATA,追従モード: オン,추적 모드 켬,Volgmodus AAN,Følgemodus PÅ,Tryb śledzenia WŁĄCZONY,Modo de seguimento ATIVADO,,Mod Urmărire ACTIVAT,Привязка к игроку ВКЛЮЧЕНА,Праћење УКЉУЧЕНО,Takip Modu AÇIK -Grid ON,AMSTR_GRIDON,,,,Mřížka ZAP,Raster TIL,Gitter AN,Πλέχμα ΕΝΕΡΓΟΠΟΙΜΈΝΟ,Krado ŜALTITA,Cuadrícula ACTIVADA,,Ruudukko PÄÄLLÄ,Quadrillage ON,Rács BE,Griglia ATTIVATA,グリッド: オン,격자 켬,Raster AAN,Rutenett PÅ,Siatka WŁĄCZONA,Grade ATIVADA,Grelha ATIVADA,Grilă ACTIVATĂ,Сетка ВКЛЮЧЕНА,Мрежа УКЉУЧЕНА,Izgara AÇIK -Grid OFF,AMSTR_GRIDOFF,,,,Mrizka VYP,Raster FRA,Gitter AUS,Πλέχμα ΆΠΕΝΕΡΓΟΠΟΙΜΈΝΟ,Krado MALŜALTITA,Cuadrícula DESACTIVADA,,Ruudukko POIS PÄÄLTÄ,Quadrillage OFF,Rács KI,Griglia DISATTIVATA,グリッド: オフ,격자 끔,Raster UIT,Rutenett AV,Siatka WYŁĄCZONA,Grade DESATIVADA,Grelha DESATIVADA,Grilă DEZACTIVATĂ,Сетка ОТКЛЮЧЕНА,Мрежа ИСКЉУЧЕНА,Izgara KAPALI -Texture Mode ON,AMSTR_TEXON,,,,Texturovaný režim ZAP,Teksturtilstand TIL,Texturmodus AN,Γραφικός χάρτης ΕΝΕΡΓΟΠΟΙΜΈΝΟΣ,Tekstura Reĝimo ŜALTITA,Modo de texturas ACTIVADO,,Pintakuviointitila PÄÄLLÄ,Mode Texturé ON,Textúrák mód BE,Modalità Texture ATTIVATA,テクスチャーモード: オン,텍스쳐 모드 켬,Textuurmodus AAN,Teksturmodus PÅ,Tekstury WŁĄCZONE,Modo de textura ATIVADO,,Mod Texturat ACTIVAT,Текстурный режим ВКЛЮЧЁН,Текстуре УКЉУЧЕНЕ,Doku Modu AÇIK -Texture Mode OFF,AMSTR_TEXOFF,,,,Texturovaný režim VYP,Teksturtilstand FRA,Texturmodus AUS,Γραφικός χάρτης ΑΠΕΝΕΡΓΟΠΟΙΜΈΝΟΣ,Tekstura Reĝimo MALŜALTITA,Modo de texturas DESACTIVADO,,Pintakuviointitila POIS PÄÄLTÄ,Mode Texturé OFF,Textúrák mód KI,Modalità Texture DISATTIVATA,テクスチャーモード: オフ,텍스쳐 모드 끔,Textuurmodus UIT,Teksturmodus AV,Tekstury WYŁĄCZONE,Modo de textura DESATIVADO,,Mod Netexturat DEZACTIVAT,Текстурный режим ОТКЛЮЧЁН,Текстуре ИСКЉУЧЕНЕ,Doku Modu KAPALI -Marked Spot,AMSTR_MARKEDSPOT,,,,Značka,Markeret placering,Punkt markiert,Μαρκαρησμένη τοποθεσεία,Loko Markita,Punto marcado,,Merkitty paikka,Repère marqué.,Megjelölt hely,Posizione segnata,目標をマークした,지점 추가,Gemarkeerde plek,Markert punkt,Oznaczono miejsce,Posição marcada,,Loc Marcat,Отметка,Означено место,İşaretli Nokta -All Marks Cleared,AMSTR_MARKSCLEARED,,,,Všechny značky smazány,Alle markeringer slettes,Alle Markierungen gelöscht,Όλες η μαρκαρησμένη τοποθεσείες είναι καθαρησμένες,Ĉiuj Markoj Forigitaj,Todas las marcas eliminadas,,Kaikki merkit pyyhitty,Repères éffacés.,Összes jelölés törölve,Cancellati tutti i segni,全目標を解除した,모든 지점 지워짐,Alle markingen gewist,Alle merker fjernet,Wszystkie miejsca wyczyszczone,Todas as marcas removidas,,Toate Marcările Șterse,Отметки очищены,Ознаке избрисане,Tüm İşaretler Temizlendi -,,Multiplayer,,,,,,,,,,,,,,,,,,,,,,,, -Fraglimit hit.,TXT_FRAGLIMIT,,,,Fraglimit dosáhnut.,Fraggrænse nået,Fraglimit erreicht,Το όριο κοματιασμόν έχει φτάσει.,Ludmurdo-limo trafita.,Límite de bajas alcanzado.,,Frägiraja saavutettu.,Limite de frags atteinte.,Fraghatár elérve.,Fraglimit raggiunto.,フラグリミット!,킬제한에 도달했습니다.,Fraglimiet bereikt.,Fraglimit treff.,Limit fragów wyczerpany.,Limite de frags atingido.,,Limita de ucideri atinsă.,Достигнут лимит фрагов.,Фраг-лимит достигнут.,Frag limiti vuruldu. -Timelimit hit.,TXT_TIMELIMIT,,,,Časový limit dosáhnut.,Tidsgrænse nået,Zeitlimit erreicht,Το χρονικό όριο έχει φτάσει.,Tempolimo trafita.,Límite de tiempo alcanzado.,,Aikaraja saavutettu.,Limite de temps atteinte.,Időhatár elérve.,Timelimit raggiunto.,ゲームセット!,시간제한에 도달했습니다.,Tijdslimiet bereikt.,Tidsbegrensningen er nådd.,Limit czasowy wyczerpany.,Limite de tempo atingido.,,Limita de timp atinsă.,Достигнут лимит времени.,Временско ограничење достигнуто.,Zaman limiti vuruldu. -%o was looking good until %g killed %hself!,SPREEKILLSELF,,,,%o vypadal@[ao_cs] dobře dokud se @[self_cs] nezabil@[ao_cs]!,"%o så godt ud, indtil @[pro_dk] dræbte sig selv!","%o sah gut aus, bis das Unglück geschah.",@[art_gr] %o πήγενε μια χαρά μέχρι που αυτοκτόνησε!,"%o estis faranta bone, ĝis @[pro_eo] mortigis sin!",¡%o se veía bien hasta que %g se mató a si mism@[ao_esp]!,,"%o oli liekeissä, kunnes meni tappamaan itsensä!",%o était en pleine folie meurtrière avant qu' %g ne se bute!,%o jól nézett ki még mielőtt megölte magát!,%o stava andando bene finchè non si è ucciso da solo!,%o は自滅するまでなかなか良かったぞ!,%o 이(가) 잘 나가려던 참에 자살했습니다!,%o zag er goed uit tot %g zelfmoord pleegde!,%o så bra ut helt til %g tok livet av seg!,%o wyglądał dobrze dopóki się nie zabił@[ao_pl],%o estava indo bem até se matar!,,%o arăta atât de bine până să se sinucidă,"%o неплохо выглядел@[ao_rus], пока не покончил@[ao_rus] с собой!",%o је изгледа@[ao_1_sr] добро док није уби@[ao_1_sr] сам@[ao_3_sr] себе!,%o kendini öldürene kadar iyi görünüyordu! -%o's killing spree was ended by %k,SPREEOVER,,,,%o@[psn1_cs] vraždící řádění ukončil hráč %k.,%os drabstog blev afsluttet af %k,%os Amoklauf wurde von %k beendet.,Ο/Η %k σταμάτησε την ανθρωποκτονία %h %o.,La mortigado de %o estis finita de %k,%k acabó con la racha de muerte de %o,,%k päätti pelaajan %o tapposarjan,La folie meurtrière de %o à été terminée par %k!,%o ámokfutását %k megállította.,La sequela di frag di %o è stata terminata da %k,%k が %o の快進撃を断ち切った!,%k 이(가) %o 의 연속 킬을 처단했습니다,%o's moordpartij werd beëindigd door %k.,%o's drapsturné ble avsluttet av %k.,Seria zabójstw %o zakończona przez %k,A matança de %o foi interrompida por %k,,Pofta de ucis a lui %o a fost pusă în cui de către %k,Игрок %k прервал череду убийств игрока %o,Серијско убијање играча %o је завршио играч %k,%o onu öldürene kadar %k iyi görünüyordu. -%k is on a killing spree!,SPREE5,,,,%k začal@[ao_cs] řádit!,%k er i gang med en mordserie!,%k läuft Amok!,Ο/Η %k άρχισε μια ανθρωποκτονία!,%k estas sur mortigado!,¡%k está atacando de lo lindo!,,%k on sarjamurhaaja!,%k est en folie meurtrière!,%o egy Ámokfutó!,%k è preda di un momento omicida!,%k が連続キル!,%k 연속 킬!,%k is op een moordpartij!,%k er på drapsturné!,%k popełnia serię morderstw!,%k está cometendo uma matança!,,%k are chef de ucis!,Игрок %k совершил череду убийств!,%k је серијални убица!,%k bir ölüm çılgınlığında! -%k is on a rampage!,SPREE10,,,,%k zuří!,%k er på et amokløb!,%k tobt sich aus!,Ο/Η %k είναι σε ξέσπασμα!,%k estas sur furiozado!,¡%k está en medio de una aniquilación!,,%k riehuu valtoimenaan!,%k est en plein massacre!,%o Tombol!,%k sta facendo un massacro!,%k が大暴れだ!,%k 이(가) 미쳐 날뛰고 있습니다!,%k heeft razernij!,%k går amok!,%k doznaje szału!,%k está massacrando!,,%k e înverșunat!,Игрок %k в неистовстве!,%k дивља!,%k kudurmuş durumda! -%k is dominating!,SPREE15,,,,%k dominuje!,%k er dominerende!,%k dominiert!,Ο/Η %k κατακτεί.,%k estas dominanta!,¡%k está dominando!,,%k hallitsee suvereenisti!,%k domine!,%o Uralkodik!,%k sta dominando tutti!,%k が圧倒している!,%k 이(가) 우세하고 있습니다!,%k domineert!,%k dominerer!,%k dominuje!,%k está dominando!,,%k domină!,Игрок %k господствует!,%k доминира!,%k hükmediyor! -%k is unstoppable!,SPREE20,,,,%k je nezastaviteln@[adj_cs]!,%k er ustoppelig!,%k kann nicht gestoppt werden!,Ο/Η %k είναι ασταμάτητος/η!,%k estas nehaltigebla!,¡%k es imparable!,,%k on pysäyttämätön!,%k est inarrétable!,%o Megállíthatatlan!,%k è inarrestabile!,%k が止まらない!,%k 을(를) 막을 수없습니다!,%k is niet te stoppen!,%k er ustoppelig!,%k jest niepowstrzymany!,%k é implacável!,,%k e de neoprit!,Игрок %k неостановим!,Играч %k је незаустављив!,%k durdurulamaz! -%k is Godlike!,SPREE25,,,,%k je boží!,%k er som en gud!,%k ist wie Gott!,Ο/Η %k είναι σαν θεός/θεά!,%k estas Dia!,¡%k es una máquina de matar!,,%k on kuin jumala!,%k est un dieu!,%o Istencsászár!,%k è un dio!,%k が神の様だ!,%k 은(는) 신적입니다! ,%k is Goddelijk!,%k er guddommelig!,%k jest Bogem!,%k é um deus da matança!,,%k e precum un Zeu!,Игрок %k богоподобен!,Играч %k је божанствен!,%k tanrı gibi! -Double kill!,MULTI2,,,,Dvoj-zabití!,Dobbelt drab!,Doppel-Kill!,Δυπλός Θάνατος!,Duobla mortigo!,¡Dos menos!,,Tuplatappo!,Double meurtre!,Dupla gyilok!,Doppia uccisione!,ダブルキル!,더블 킬!,Dubbele kill!,Dobbeltdrap!,Podwójne zabójstwo!,Morte dupla!,,Dublă ucidere!,Двойное убийство!,Дупло убиство!,Çifte öldürme! -Multi kill!,MULTI3,,,,Multi-zabití!,Multi-drab!,Multi-Kill!,Πολυθάνατος!,Pluraj mortigoj!,¡Multidestrucción!,,Multitappo!,Multi meurtre!,Multi gyilok!,Tripla uccisione!,マルチキル!,멀티 킬!,,Multidrap!,Multi-zabójstwo!,Morte tripla!,,Ucidere multiplă!,Массовое убийство!,Вишеструко убиство!,Çoklu öldürme! -Ultra kill!,MULTI4,,,,Ultra-zabití!,Ultra-drab!,Ultra-Kill!,Υπερθάνατος!,Ekstremaj mortigoj!,¡¡HIPERDESTRUCCIÓN!!,,Ultratappo!,Ultra meurtre!,Ultra gyilok!,Ultra uccisione!,ウルトラキル!,울트라 킬!,,Ultra drep!,Ultra-zabójstwo!,Ultra matança!,,Ultra ucidere!,Ультра-убийство!,Ултра убиство!,Ultra öldürme! -Monster kill!,MULTI5,,,,Monstr-zabití!,Monster-drab!,Monster-Kill!,Τερατόδες σκοτωμός!,Monstraj mortigoj!,¡¡¡S.U.P.E.R.D.E.S.T.R.U.C.C.I.Ó.N!!!,,Hirviömäinen tappo!,,Szörnyű gyilkolás!,Uccisione Mostruosa!,モンスターキル!,몬스터 킬!,,Monster drep!,Potworne zabójstwo!,Matança monstro!,Matança monstruosa!,Ucidere monstruoasă!,Чудовищное убийство!,Монструозно убиство!,Canavar öldürme! -,,Scoreboard,,,,,,,,,,,,,,,,,,,,,,,, -Items,SCORE_ITEMS,,,,Předměty,Genstande,Gegenstände,Αντεικείμενα,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,획득한 아이템,Items,Gjenstander,Przedmioty,Itens,,Obiecte,Предметы,Предмети,Eşyalar -Bonus,SCORE_BONUS,,,,,,Bonus,Bonus,Bonuso,Bonificaciones,,Lisäedut,,Bónusz,Bonus,ボーナス,보너스,Bonus,,Bonusy,Bônus,,Bonus,Бонус,Бонус,Bonus -Color,SCORE_COLOR,,,Colour,Barva,Farve,Farbe,Χρώμα,Koloro,,,Väri,Couleur,Szín,Colore ,色,색상,Kleur,Farge,Kolor,Cor,,Culoare,Цвет,Боја,Renk -Secret,SCORE_SECRET,,,,Skrýše,Hemmeligt,Geheimnis,Μυστικό,Sekreto,Secreto,,Salat,,Titok,Segreto,シークレット,밝혀낸 비밀,Geheim,Hemmelig,Sekret,Segredo,,Secret,Тайники,Тајна,Sır -Name,SCORE_NAME,,,,Jméno,Navn,Name,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Navn,Nazwa,Nome,,Nume,Игрок,Име,İsim -Delay (ms),SCORE_DELAY,,,,Zpoždění (ms),Forsinkelse (ms),Verzögerung (ms),Kαθυστέρηση (μδ),Prokrasto (ms),Retraso (ms),,Viive (ms),Délai (ms),Késleltetés (ms),Ritardo (ms) ,ping,핑 (밀리초당),Vertraging (ms),Forsinkelse (ms),Opóźnienie (ms),Atraso (ms),,Întârziere (ms),Задержка (мс),Кашњење (мс),Gecikme (ms) -Kills,SCORE_KILLS,,,,Zabití,Dræber,,Σκοτομοί,Mortigoj,Asesinatos,,Tapot,Victimes,Áldozatok,Uccisioni,キル,킬수,Dood,Drepte,Zabici,Vítimas,,Ucideri,Убийства,Убиства,Öldürür -Frags,SCORE_FRAGS,,,,Fragy,,,Κοματιασμοί,Ludmurdoj,Bajas,,Frägit,,Frag-ek,Frags,フラグ,플레이어 킬수,,,Fragi,Frags,,Victime,Фраги,Фрагови,Frags -Deaths,SCORE_DEATHS,,,,Smrti,Dødsfald,Tode,Θάνατοι,Mortoj,Muertes,,Kuolemat,Morts,Halálok,Morti,デス,사망한 횟수,Sterfgevallen,Dødsfall,Śmierci,Mortes,,Decese,Смерти,Смрти,Ölümler -Other,SCORE_OTHER,,,,Ostatní,Andre,Andere,,Alia,Demás,,Muu,,Egyéb,Altro,その他,,Anders,Andre,Inne,Outro,,Altele,Прочее,,Diğer -Missed,SCORE_MISSED,,,,Minuto,Forpasset,Verfehlt,Ξεχάστηκαν,Mankita,Pérdidas,,Hudit,Ratés,Kihagyva,Mancati ,ミス,놓친 수,Gemist,Ubesvarte,Ominięte,Perdido,,Ratate,Пропущено,Пропуштено,Cevapsız -Total,SCORE_TOTAL,,,,Celkem,,Gesamt,Συνολικό,Tuto,,,Yhteensä,Total,Összesen,Totale,合計,총점,Totaal,Totalt,Totalne,Total,,Total,Всего,Укупно,Toplam -Level Time,SCORE_LVLTIME,,,,Čas v levelu,Niveau Tid,Levelzeit,Χρόνος Πίστας,Daŭro de Nivelo,Tiempo de nivel,,Tasoaika,Temps niveau,Pályaidő,Tempo Livello ,時間,레벨 시간,Leveltijd,Nivå Tid,Czas,Tempo de fase,Tempo do Nível,Timp Petrecut,Время уровня,Време нивоа,Seviye Zaman -,,Level Summary,,,,,,,,,,,,,,,,,,,,,,,, -Kills,TXT_IMKILLS,,,,Zabití,Dræber,,Σκοτομοί,Mortigoj,Muertes,,Tapot,Morts,Áldozatok,Uccisioni,キル,킬수,Dood,Drepte,Zabici,Vítimas,,Ucideri,Убийств,Непријатељи,Öldürür -Items,TXT_IMITEMS,,,,Předměty,Genstande,Gegenstände,Αντεικείμενα,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,획득한 아이템,Items,Gjenstander,Przedmioty,Itens,,Obiecte,Предметов,Ставке,Eşyalar -Secrets,TXT_IMSECRETS,,,,Skrýše,Hemmeligheder,Geheimnisse,Μυστικά,Sekretoj,Secretos,,Salat,,Titkok,Segreti,シークレット,밝혀낸 비밀,Geheimen,Hemmeligheter,Sekrety,Segredos,,Secrete,Тайников,Тајне,Sırlar -Time,TXT_IMTIME,,,,Čas,Tid,Zeit,Χρόνος,Daŭro,Tiempo,,Aika,Temps,Idő,Tempo,経過時間,소모한 시간,Tijd,Tid,Czas,Tempo,,Timp,Время,Време,Zaman -Par,TXT_IMPAR,,,,,,,Μέσος Όρος,Alparo,,,,,Átlag,Media,最速時間,기준 시간,,,Par,Média,,Record,Рекорд,Рекорд,Par -Finished,WI_FINISHED,,,,Dokončeno,Færdig,Abgeschlossen,Ολοκληρώθηκε,Finita,Completado,,Suoritettu,Terminé,Teljesítve,Finito,攻略,완료,Klaar,Ferdig,Ukończono,Finalizado,,Terminat,Уровень завершён,Ниво завршен,Bitti -Entering,WI_ENTERING,,,,Vstupuješ do,Indtastning af,Betrete,Είσοδος,Enirante,Entrando a:,,Seuraava kohde,Niveau Suivant,Következik,Prossimo livello,突入開始,입장,Volgende,Går inn,Wchodzisz do:,Próxima fase,Próximo nível,Începe,Переход,Следећи ниво,Giriş -Now entering:,WI_ENTERING,,heretic hexen,,Nyní vstupuješ do:,Indtastning af:,Betrete:,Τώρα εισέρχεσε στο:,Nun enirante:,Ahora entrando a:,,Seuraava kohde:,Vous entrez dans:,Következik:,Entrando adesso in:,突入中:,입장합니다:,Volgende:,Går nå inn:,Teraz wchodzisz do:,Entrando em:,A entrar em:,Acum începe:,Переход на:,Следећи ниво:,Şimdi giriyoruz: -,,HUD,,,,,,,,,,,,,,,,,,,,,,,, -Monsters:,AM_MONSTERS,,,,Příšery:,Monstre:,Monster:,Τέρατα,Monstroj:,Monstruos:,,Hirviöt:,Monstres:,Szörnyek:,Mostri,奴等:,죽인 적들:,Monsters:,Monstre:,Potwory:,Monstros:,,Monștri:,Монстры:,Чудовишта:,Canavarlar: -Secrets:,AM_SECRETS,,,,Skrýše:,Hemmeligheder:,Geheimnisse:,Μυστικά,Sekretoj:,Secretos:,,Salat:,,Titkos helyek:,Segreti,隠場:,찾은 비밀:,Geheimen:,Hemmeligheter:,Sekrety:,Segredos:,,Secrete:,Тайники:,Тајне:,Sırlar: -Items:,AM_ITEMS,,,,Věci:,Genstande:,Gegenstände:,Αντεικείμενα,Objektoj:,Objetos:,,Esineet:,Objets:,Tárgyak:,Oggetti,物資:,얻은 아이템:,Items:,Gjenstander:,Przedmioty:,Itens:,,Obiecte:,Предметы:,Предмети:,Eşyalar: -,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,, -%o suicides.,OB_SUICIDE,,,,%o spáchal@[ao_cs] sebevraždu.,%o begår selvmord.,%o begeht Selbstmord.,@[art_gr] %o αυτοκτόνησε,%o sinmortigis.,%o se ha suicidado.,%o se suicidó.,%o teki itsemurhan.,%o se suicide.,%o öngyilkos lett.,%o si è suicidato.,%o は自殺した。,%o 은(는) 자살했다.,%o pleegt zelfmoord.,%o begår selvmord.,%o popełnił@[ao_pl] samobójstwo.,%o se suicidou.,,%o se sinucide.,Игрок %o покончил с собой.,%o самоубиства.,%o intihar eder. -%o fell too far.,OB_FALLING,,,,%o spadl@[ao_cs] příliš daleko.,%o faldt for langt ned.,%o fiel zu tief.,@[art_gr] %o έπεσε,%o falis tro fore.,%o se ha caído desde muy alto.,%o se cayó desde muy alto.,%o putosi liian kaukaa.,%o est tombé@[e_fr] trop loin.,%o túl messze esett.,%o è caduto troppo in basso.,%o はあまりにも高い所から転落した。,%o 은(는) 높은 곳에서 떨어져 사망했다.,%o viel te ver.,%o falt for langt.,%o spadł@[ao_pl] za daleko.,%o caiu de um lugar alto.,,%o a căzut prea departe.,Игрок %o упал слишком далеко.,%o је па@[ao_1_sr] до сад.,%o çok uzağa düştü. -%o was squished.,OB_CRUSH,,,,%o byl@[ao_cs] rozdrcen@[ao_cs].,%o blev mast.,%o wurde zerquetscht,@[art_gr] %o συνθλίφτηκε,%o estis dispremita.,%o ha sido aplastad@[ao_esp].,%o fue aplastad@[ao_esp].,%o liiskautui.,%o a été écrasé@[e_fr].,%o össze lett lapítva.,%o è stato schiacciato.,%o は潰された。,%o 은(는) 뭉게졌다.,%o werd geplet.,%o ble knust.,%o spłaszczył@[ao_pl] się.,%o foi esmagad@[ao_ptb].,,%o a fost strivit.,Игрок %o был раздавлен.,%o је здробљен@[adj_1_sr].,%o ezildi. -%o tried to leave.,OB_EXIT,,,,%o se pokusil@[ao_cs] odejít.,%o forsøgte at gå.,%o wollte gehen.,@[art_gr] %o προσπάθησε να φύγει,%o provis foriri.,%o ha tratado de huir.,%o trató de huir.,%o yritti häipyä.,%o a tenté de partir.,%o megpróbált lelépni.,%o ha provato a uscire.,%o は逃げようとした。,%o 은(는) 나가려고 발버둥 쳤다.,%o probeerde te vertrekken.,%o prøvde å dra.,%o spróbował@[ao_pl] odejść.,%o tentou sair.,,%o a încercat să plece.,Игрок %o попытался уйти.,%o покуша@[ao_1_sr] да оде.,%o gitmeye çalıştı. -%o can't swim.,OB_WATER,,,,%o neumí plavat.,%o kan ikke svømme.,%o kann nicht schwimmen.,@[art_gr] %o δέν μπορεί να κολυμπήσει,%o ne scipovas naĝi.,%o no sabe nadar.,,%o ei osaa uida.,%o ne sait pas nager.,%o nem tud úszni.,%o non sapeva nuotare.,%o は泳げなかった。,%o 은(는) 익사했다.,%o kan niet zwemmen.,%o kan ikke svømme.,%o nie umie pływać.,%o não sabe nadar.,,%o nu poate înota.,Игрок %o не умел плавать.,%o не може да плива.,%o yüzme bilmiyor. -%o mutated.,OB_SLIME,,,,%o zmutoval@[ao_cs].,%o muterede.,%o mutierte.,@[art_gr] %o μεταλάχθηκε,%o mutaciis.,%o ha mutado.,%o mutó.,%o mutatoitui.,%o a muté.,%o mutánssá alakult.,%o è mutato.,%o は変異した。,%o 은(는) 돌연사를 당했다.,%o muteerde.,%o muterte.,%o zmutował@[ao_pl].,%o sofreu mutação.,,%o a avut parte de o mutație.,Игрок %o мутировал.,%o је мутиран@[adj_1_sr].,%o mutasyona uğradı. -%o melted.,OB_LAVA,,,,%o se rozpustil@[ao_cs].,%o smeltede.,%o schmolz.,@[art_gr] %o έλειοσε,%o fandiĝis.,%o se ha fundido.,%o se fundió.,%o suli.,%o a fondu.,%o megolvadt.,%o si è sciolto.,%o は溶かされた。,%o 은(는) 녹아버렸다.,%o smolt.,%o smeltet.,%o stopił@[ao_pl] się.,%o derreteu.,%o derreteu-se.,%o s-a topit.,Игрок %o расплавился.,%o је отопљен@[adj_1_sr].,%o eridi. -%o went boom.,OB_BARREL,,,,%o udělal@[ao_cs] bum.,%o gik bum.,%o explodierte.,@[art_gr] %o έσκασε,%o eksplodis.,%o ha explotado en mil pedazos.,%o explotó en mil pedazos.,%o poksahti.,%o s'est pété@[e_fr] la face.,%o felrobbant.,%o ha fatto bum.,%o は爆発で吹き飛ばされた。,%o 은(는) 폭사했다.,%o ging boem.,%o gikk i lufta.,%o zrobił@[ao_pl] bum.,%o explodiu.,,%o a explodat.,Игрок %o взорвался.,%o је отиш@[ao_2_sr] бум.,%o patladı. -%o stood in the wrong spot.,OB_SPLASH,,,,%o stál@[ao_cs] na špatném místě.,%o stod på det forkerte sted.,%o war am falschen Ort.,@[art_gr] %o έκατσε στο λάθος σημείο,%o staris en la malĝusta loko.,%o estaba en el sitio equivocado.,,%o seisoi väärässä paikassa.,%o s'est tenu@[e_fr] au mauvais endroit.,%o rossz helyre állt.,%o si è trovato nel posto sbagliato.,%o はいけない場所に立っていた。,%o 은(는) 위험한 곳에 서 있었다.,%o stond op de verkeerde plek.,%o sto på feil sted.,%o stan@[irreg_2_pl] w złym miejscu.,%o ficou no lugar errado.,,%o a stat în locul nepotrivit.,Игрок %o стоял в неверной точке.,%o је стаја@[ao_1_sr] на погрешно место.,%o yanlış yerde durdu. -%o should have stood back.,OB_R_SPLASH,,,,%o měl@[ao_cs] stát o trochu dál.,%o skulle have stået tilbage.,%o hätte Abstand halten sollen.,@[art_gr] %o έπρεπε να είχε κάτσι πίσω,%o devintus forstarinta.,%o debería haberse apartado.,,%o oli liian likellä.,%o aurait dû garder ses distances.,%o túl közel állt.,%o si sarebbe dovuto allontanare.,%o は後ろへ引くべきだった。,%o 은(는) 좀 더 떨어져야만 했다.,%o had afstand moeten houden.,%o burde ha stått tilbake.,%o nie ustąpił@[ao_pl] na bok.,%o deveria ter se afastado.,,%o ar fi trebuit să stea deoparte.,Игрок %o не отступил в сторону.,Играчу %o је требало да стоји назад.,%o geri çekilmeliydi. -%o should have stood back.,OB_ROCKET,,,,%o měl@[ao_cs] stát o trochu dál.,%o skulle have stået tilbage.,%o hätte Abstand halten sollen.,@[art_gr] %o έπρεπε να είχε κάτσι πίσω,%o devintus forstarinta.,%o debería haberse apartado.,,%o oli liian likellä.,%o aurait dû garder ses distances.,%o túl közel állt.,%o si sarebbe dovuto allontanare.,%o は後ろへ引くべきだった。,%o 은(는) 더 멀리 떨어져야만 했다.,%o had afstand moeten houden.,%o burde ha stått tilbake.,%o nie ustąpił@[ao_pl] na bok.,%o deveria ter se afastado.,,%o ar fi trebuit să stea deoparte.,Игрок %o не отступил в сторону.,Играчу %o је требало да стоји назад.,%o geri çekilmeliydi. -%o killed %hself.,OB_KILLEDSELF,,,,%o se zabil@[ao_cs].,%o begik selvmord.,%o tötete sich selbst.,@[art_gr] %o αυτοκτόνησε,%o mortigis sin.,%o se ha matado a sí mism@[ao_esp].,%o se mató a sí mism@[ao_esp].,%o tappoi itsensä.,%o s'est tué@[e_fr].,%o megölte magát.,%o ha ucciso se stesso.,%o は自滅した。,%o 은(는) 자멸했다.,%o bracht zichzelf om.,%o begår selvmord.,%o zabił@[ao_pl] się.,%o se matou.,%o matou-se,%o s-a sinucis.,Игрок %o убил себя.,%o је уби@[ao_1_sr] себе.,%o kendini öldürdü. -%o was killed by the power of voodoo.,OB_VOODOO,,,,%o byl@[ao_cs] zabit@[ao_cs] sílou voodoo.,%o blev dræbt af voodooens magt.,%o wurde durch Voodoo getötet.,@[art_gr] %o πέθανε απο τη δύναμη του βουντου,%o estis mortigita de la povo de voduo.,%o ha sido asesinad@[ao_esp] con el poder del vudú.,%o fue asesinad@[ao_esp] con el poder del vudú.,%o kuoli voodoon voimasta.,%o a succombé au pouvoir du Vaudou.,%o meghalt a voodoo erejének köszönhetően.,%o è stato ucciso dalla potenza del voodoo.,%o はブードゥー人形で殺された。,%o 은(는) 부두 마법의 저주를 받았다.,%o werd gedood door de kracht van voodoo.,%o ble drept av voodooens kraft.,%o umarł@[ao_pl] od mocy voodoo.,%o morreu pelo poder do voodoo.,,%o a fost omorât prin puterea voodoo.,Игрок %o убит силой Вуду.,%o је убијен@[adj_1_sr] од стране моћи Voodoo-а.,%o voodoo'nun gücü tarafından öldürüldü. -%o was telefragged by %k.,OB_MPTELEFRAG,,,,%o byl@[ao_cs] telefraggnut %kem.,%o blev telefragged af %k.,%o stand %k im Wege.,@[art_gr] %o κοματιάστηκε μέσω τηλεμεταφοράς απο τον/την %k,%o estis teleportumita de %k.,%o ha sido telefragmentad@[ao_esp] por %k.,%o fue telefragmentad@[ao_esp] por %k.,%k telefräggäsi %o paran.,%o a été téléfragué@[e_fr] par %k.,%o telefrag-et kapott %k által.,%o è stato telefraggato da %k.,%o は %k にテレフラグされた。,%o 은(는) %k 에 의해 텔레프랙을 당했다.,%o werd getelefragged door %k.,%o ble telefragget av %k.,%o został@[ao_pl] ztelefragowan@[adj_pl] przez %k.,%o foi telefragad@[ao_ptb] por %k.,,%o a fost omorât prin teleportare de către %k.,Игрок %o стал жертвой телепортации игрока %k.,%o је телефрагован@[adj_1_sr] од стране %k.,"%o, %k tarafından telefrag edildi." -%o was telefragged.,OB_MONTELEFRAG,,,,%o byl@[ao_cs] telefraggnut@[ao_cs].,%o blev telefragged.,%o stand jemandem im Wege.,@[art_gr] %o κοματιάστηκε μέσω τηλεμεταφοράς,%o estis teleportumita.,%o ha sido telefragmentad@[ao_esp].,%o fue telefragmentad@[ao_esp].,%o telefrägättiin.,%o a été téléfragué@[e_fr].,%o telefraggelve lett.,%o si è fatto telefraggare.,%o はテレフラグされた。,%o 은(는) 텔레프랙을 당했다.,%o werd getelefragged.,%o ble telefragget.,%o został@[ao_pl] ztelefragowan@[adj_pl].,%o foi telefragad@[ao_ptb] por um monstro.,,%o a fost omorât prin teleportare.,Игрок %o стал жертвой телепортации.,%o је телефрагован@[adj_1_sr].,%o telefragged edildi. +",Мењам ниво...,Ändrad nivå ...,Seviye Değiştirme...,Зміна рівня... +Buddha mode ON,TXT_BUDDHAON,,,,Buddha mód ZAP,Buddha-tilstand TIL,Buddhamodus AN,Λειτουργία Βουδα ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Budha reĝimo ŜALTITA,Modo Buda ACTIVADO,,Buddhatila PÄÄLLÄ,Mode Bouddha ON,Buddha Mód BE,Modalità Buddha ATTIVATA,ブッダモード: オン,부처 모드 켬,Boeddha-modus AAN,Buddha-modus PÅ,Tryb Buddy WŁĄCZONY,Modo Buda ATIVADO,,Modul Buddha ACTIVAT,Режим Будды ВКЛЮЧЁН,Буда Мод УКЉУЧЕН,Buddha-läge på,Buda modu AÇIK,Будда-мод ВВІМК. +Buddha mode OFF,TXT_BUDDHAOFF,,,,Buddha mód VYP,Buddha-tilstand FRA,Buddhamodus AUS,Λειτουργία Βουδα ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Budha reĝimo MALŜALTITA,Modo Buda DESACTIVADO,,Buddhatila POIS PÄÄLTÄ,Mode Bouddha OFF,Buddha Mód KI,Modalità Buddha DISATTIVATA,ブッダモード: オフ,부처 모드 끔,Boeddha-modus UIT,Buddha-modus AV,Tryb Buddy WYŁĄCZONY,Modo Buda DESATIVADO,,Modul Buddha DEZACTIVAT,Режим Будды ОТКЛЮЧЁН,Буда Мод ИСКЉУЧЕН,Buddha-läge avstängt,Buda modu KAPALI,Будда-мод ВИМК. +Ultimate Buddha Mode ON,TXT_BUDDHA2ON,,,,Super Buddha mód ZAP,Ultimate Buddha-tilstand TIL,Ultimativer Buddhamodus AN,Λειτουργία Απόλητου Βουδα ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Pleja Budha Reĝimo ŜALTITA,Modo Buda Supremo ACTIVADO,,Korkein buddhatila PÄÄLLÄ,Mode Bouddha Ultime ON,Tökéletes Buddha Mód BE,Modalità Ultimo Buddha ATTIVATA,究極ブッダモード: オン,나무 아미타불 모드 켬,Ultieme Boeddha-modus AAN,Ultimativ Buddha-modus PÅ,Maksymalny Tryb Buddy WŁĄCZONY,Modo Buda supremo ATIVADO,,Modul Buddha Suprem ACTIVAT,Окончательный режим Будды ВКЛЮЧЁН,Ултимативни Буда Мод УКЉУЧЕН,Ultimat Buddha-läge på,Nihai Buda Modu AÇIK,Ультимативний Будда-мод ВВІМК. +Ultimate Buddha Mode OFF,TXT_BUDDHA2OFF,,,,Super Buddha mód VYP,Ultimate Buddha-tilstand FRA,Ultimativer Buddhamodus AUS,Λειτουργία Απόλητου Βουδα ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Pleja Budha Reĝimo MALŜALTITA,Modo Buda Supremo DESACTIVADO,,Korkein buddhatila POIS PÄÄLTÄ,Mode Bouddha Ultime OFF,Tökéletes Buddha Mód KI,Modalità Ultimo Buddha DISATTIVATA,究極ブッダモード: オフ,나무 아미타불 모드 끔,Ultieme Boeddha-modus UIT,Ultimativ Buddha-modus AV,Maksymalny Tryb Buddy WYŁĄCZONY,Modo Buda supremo DESATIVADO,,Modul Buddha Suprem DEZACTIVAT,Окончательный режим Будды ОТКЛЮЧЁН,Ултимативни Буда Мод ИСКЉУЧЕН,Ultimat Buddha-läge av,Nihai Buda Modu KAPALI,Ультимативний Будда-мод ВИМК. +Power on,TXT_CHEATPOWERON,,,,Energie ZAP,Evne TIL,Fähigkeit AN,Δύναμη ενεργοποιημένη,Povo ŝaltita,Poder activado,,Voima päällä,Pouvoir Activée,Energia BE,Potere ATTIVATO,パワー オン,파워 켬,Vermogen aan,Strøm PÅ,Zasilanie włączone,Poder ativado,,Putere activată,Сила активирована,Моћ УКЉУЧЕНА,Makt på,Güç açık,Сила активована +Power off,TXT_CHEATPOWEROFF,,,,Energie VYP,Evne FRA,Fähigkeit AUS,Δύναμη άπενεργοποιημένη,Povo malŝaltita,Poder desactivado,,Voima pois päältä,Pouvoir Désactivée,Energia KI,Potere DISATTIVATO,パワー オフ,파워 끔,Vermogen uit,Slå AV,Zasilanie wyłączone,Poder desativado,,Putere dezactivată,Сила деактивирована,Моћ ИСКЉУЧЕНА,Makt av,Güç kapalı,Сила деактивована +Full health,TXT_CHEATHEALTH,,,,Plné zdraví,Fuldt helbred,Volle Lebensenergie,Ολόκληρη υγεία,Plena sano,Salud al máximo,,Täysi terveys,Pleine Santé,Teljes életerő,Piena salute,ヘルス全回復,체력 완전 회복,Volledige gezondheid,Full helse,Pełne zdrowie,Saúde completa,Vida totalmente cheia,Sănătate completă,Полное здоровье,Здравље напуњено,Full hälsa,Tam sağlık,Повне здоров'я +All keys,TXT_CHEATKEYS,,,,Všechny klíče,Alle taster,Alle Schlüssel,Όλα τα κλειδία,Ĉiuj ŝlosiloj,Todas las llaves,,Kaikki avaimet,Toutes les Clés,Összes kulcs,Tutte le chiavi,キー全部,모든 열쇠,Alle sleutels,Alle taster,Wszystkie klucze,Todas as chaves,,Toate cheile,Все ключи,Сви кључеви,Alla tangenter,Tüm anahtarlar,Усі ключі +Sound debug on,TXT_CHEATSOUNDON,,,,Debug zvuku ZAP,Sound debug TIL,Sound Debug AN,Debug ήχου ενεργοποιημένη,Sono-sencimiga reĝimo ŝaltita,Depuración de sonido activada,,Äänen vianmääritystila päällä,Débogage du son activé.,Hang debug BE,Debug del suono attivato,サウンドデバッグ オン,효과음 디버그 켬,Geluid debug aan,Lyd feilsøking PÅ,Debugowanie dźwięku włączone,Depuração de som ativada,,Debug sunet activat,Отладка звука включена,Дебаговање звука УКЉУЧЕНО,Ljud felsökning på,Ses hata ayıklama açık,Налагодження звуку УВІМКНЕНО +Sound debug off,TXT_CHEATSOUNDOFF,,,,Debug zvuku VYP,Sound debug FRA,Sound Debug AUS,Debug ήχου άπενεργοποιημένη,Sono-sencimiga reĝimo malŝaltita,Depuración de sonido desactivada,,Äänen vianmääritystila pois päältä,Débogage du son désactivé.,Hang debug KI,Debug del suono disattivato,サウンドデバッグ オフ,효과음 디버그 끔,Geluid debug uit,Lyd feilsøking AV,Debugowanie dźwięku wyłączone,Depuração de som desativada,,Debug sunet dezactivat,Отладка звука отключена,Дебаговање звука ИСКЉУЧЕНО,Ljud felsökning av,Ses hata ayıklama kapalı,Налагодження звуку ВИМКНЕНО +"Trying to cheat, eh? Now you die!",TXT_CHEATIDDQD,,,,"Pokoušíš se cheatovat, co? Teď zemřeš!","Prøver du at snyde, hva'? Nu dør du!","Versuchst zu betrügen, was? Nun stirbst du!","Προσπαθείς να εξαπατήσεις, ε? Τώρα πεθένεις!","Provas trompi, ĉu vi? Nun vi mortas! ","¿Tratando de hacer trampas, eh? ¡Muere!",,"Yrität huijata, vai? Nyt kuolet!","Tu essaie de tricher, hein? Maintenant tu meurs!","Csalni akarsz, mi? Most meghalsz!","Cerchi di barare, eh? Allora muori!",その名を唱えたな? 褒美に死をやろう!,치트 쓸려고? 그럼 죽어야지!,"Je wou valsspelen, hè? Nu ga je dood!",Prøver du å jukse? Nå dør du!,"Próbujesz oszukiwać, co? Teraz giń!","Tentando trapacear, né? Morra!","A fazer batota, é? Morre!","Încerci să trișezi, ei? Acum mori!","Жульничаешь, э? Так умри!","Покушаваш да вараш, ех? Сада умиреш!",Försöker du fuska? Nu dör du!,"Hile yapmaya çalışıyorsun, ha? Şimdi öleceksin!","Хех, чітериш? Тепер помри!" +Cheater - you don't deserve weapons,TXT_CHEATIDKFA,,,,Podvodníku - nezasloužíš si zbraně,Snyder - du fortjener ikke våben,Betrüger - du verdienst keine Waffen,Απατεόνα δέν σου αξήζουν όπλα,Trompanto - vi ne meritas armilojn,¡Trampos@[ao_esp]! No mereces tener armas,,Huijari - et ansaitse aseita,Tricheur- Tu ne mérite pas d'armes!,Csaló - nem érdemelsz fegyvert!,Imbroglione - non meriti armi,不届き者め、貴様が偉業を成すはずがない,사기꾼놈! 너는 무기를 가질 자격이 없어!,Valsspeler - je verdient geen wapens.,Juksemaker - du fortjener ikke våpen,Oszust - nie zasługujesz na bronie,Trapaceiros não merecem armas,Batoteir@[ao_ptb] - Não mereces armamento,Trișor - Nu meriți arme,Жулик — ты не заслуживаешь оружия,Варалице - ти не заслужујеш оружје,Fuskare - du förtjänar inte vapen.,"Hileci, silahları hak etmiyorsun.",Пройдисвіт - ти не заслужив зброї +Ticker on,TXT_CHEATTICKERON,,,,Počítadlo ZAP,Ticker TIL,Zähler AN,Χρονόμετρο ενεργοποιημένο,Nombrilo ŝaltita,Contador activado,,Laskuri päällä,Compteur allumé,Számláló BE,Ticker attivato,ティッカー オン,프레임 속도 표시 켬,Ticker aan,Ticker PÅ,Wskaźnik włączony,Contador ativado,,Ticăitoare activată,Счётчик включён,Бројач укључен,Ticker på,Ticker açık,Лічильник Ввімк. +Ticker off,TXT_CHEATTICKEROFF,,,,Počítadlo VYP,Ticker FRA,Zähler AUS,Χρονόμετρο άπενεργοποιημένο,Nombrilo malŝaltita,Contador desactivado,,Laskuri pois päältä,Compteur éteint,Számláló KI,Ticker disattivato,ティッカー オフ,프레임 속도 표시 끔,Ticker uit,Ticker AV,Wskaźnik wyłączony,Contador desativado,,Ticăitoare dezactivată,Счётчик отключён,Бројач искључен,Ticker av,Ticker kapalı,Лічильник Вимк. +You got it,TXT_CHEATARTIFACTS3,,,,Máš to mít,Du fik det,Du hast es,Το πήρες,Vi akiris ĝin,Lo tienes,,Saamasi pitää,C'est à vous!,Megkaptad,Concesso,それを渡そう。,얻었다,Je hebt het,Du har det,Udało ci się,Concedido,,Ai ce-ți trebuie,Вы получили это,Уреду,Du fick det,Tamamdır.,Ви отримали це +"You got the Midas Touch, baby",TXT_MIDASTOUCH,,,,"Máš Midasův dotek, zlato","Du har Midas Touch, baby",Dagobert Duck lässt grüßen!,"Έχεις το αγγιγμα το Μίδα, μωρό.","Vi akiris la Tuŝon de Midas, kara","Tienes el toque de Midas, muchach@[ao_esp]",,"Kulta, sinulla on Midaksen kosketus",,"Minden arannyá válik amit megérintesz, öreg","Hai avuto il Tocco di Mida, baby",ミダス王の様だな、ベイビー,넌 미다스의 손을 얻었어 베이베!,"Je hebt de Midas Touch, schatje","Du har Midas Touch, baby","Zdobył@[irreg_3_pl] dotyk Midasa, skarbie","Você tem o Toque de Midas, baby","Tens o Toque de Midas, baby","Ai Atingerea lui Midas, dragule","Ты превращаешь всё в золото, детка!","Имаш златке руке, душо","Du har Midas Touch, baby","Sende Midas Dokunuşu var, bebeğim","Дар Мідаса у твоїх руках, золотце" +You got the stuff!,TXT_GOTSTUFF,,,,Dostal jsi věci!,Du har det hele!,Du hast den Kram erhalten,Πήρες τηατ πράγματα !,Vi akiris la aĵojn!,¡Tienes un montón de cosas!,,Sait kamppeet!,Voilà ton équipement!,Megkaptad a cuccot!,Hai avuto il materiale!,スタッフを手に入れた!,무언가를 얻었다!,Je hebt het spul!,Du har greiene!,Zdobył@[irreg_3_pl] parę rzeczy!,Você ganhou muitas coisas!,ganhaste muitas coisas!,Ai tot ce-ți trebuie!,Получены предметы!,Покупили сте ствари!,Du har grejerna!,Mal sende!,Отримано предмети! +Freeze mode on,TXT_FREEZEON,,,,Režim zamrznutí ZAP,Frysetilstand TIL,Gefriermodus AN,Παγομένη λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Movhalta reĝimo ŝaltita,Modo suspendido activado,,Jäädytystila päällä,Temps arrêté.,Fagyasztás BE,Modalità arresto del tempo attivata,フリーズモード オン,시간정지 켬,Bevriesmodus aan,Frysemodus PÅ,Tryb zamrożenia włączony,Modo congelado ativado,,Modul înghețat activat,Режим заморозки включён,Мод замрзавања УКЉУЧЕН,Frysningsläge på,Dondurma modu açık,Режим заморозки ВВІМКНЕНО +Freeze mode off,TXT_FREEZEOFF,,,,Režim zamrznutí VYP,Frysetilstand FRA,Gefriermodus AUS,Παγομένη λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Movhalta reĝimo malŝaltita,Modo suspendido desactivado,,Jäädytystila pois päältä,Le temps reprend son cours..,Fagyasztás KI,Modalità arresto del tempo disattivata,フリーズモード オフ,시간정지 끔,Bevriesmodus uit,Frysemodus AV,Tryb zamrożenia wyłączony,Modo congelado desativado,,Modul înghețat dezactivat,Режим заморозки отключён,Мод замрзавања ИСКЉУЧЕН,Frysningsläge av,Dondurma modu kapalı,Режим заморозки ВИМКНЕНО +You feel strange...,TXT_STRANGE,,,,Cítíš se divně...,Du føler dig mærkelig...,Du fühlst dich merkwürdig...,Νιώθης περίεργα...,Vi sentas vin strange...,Te sientes extrañ@[ao_esp]...,,Sinulla on kummallinen olo...,Vous vous sentez mal à l'aise...,Furán érzed magad...,Ti senti strano...,これは奇妙な感じだな...,뭔가 이상한 기분이...,Je voelt je vreemd...,Du føler deg rar...,Dziwnie się czujesz...,Você está com uma sensação estranha...,Tu sentes-te estranh@[ao_ptb].,Te simți ciudat...,Вы чувствуете себя странно...,Осећате се чудно...,Du känner dig konstig...,Garip hissediyorsun.,Ви почуваєте себе дивно... +You feel even stranger.,TXT_STRANGER,,,,Cítíš se ještě divněji...,Du føler dig endnu mere mærkelig.,Du fühlst dich noch merkwürdiger,Νιώθης ακόμα πιό περίεργα...,Vi sentas vin eĉ pli strange.,Te sientes aún más extrañ@[ao_esp],,Olosi on vieläkin kummempi.,Vous vous sentez très mal à l'aise...,Még furábban érzed magad.,Ti senti ancora più strano.,これはかなり奇妙だ。,기분이 더더욱 이상해졌다.,Je voelt je nog vreemder.,Du føler deg enda merkeligere.,Czujesz się jeszcze dziwniej.,Você está com uma sensação mais estranha ainda.,Tu sentes-te ainda mais estranh@[ao_ptb].,Te simți și mai ciudat.,Вы чувствуете себя очень странно.,Осећате се врло чудно.,Du känner dig ännu konstigare.,Daha da garip hissediyorsun.,Ви почуваєте себе ще дивніше. +You feel like yourself again.,TXT_NOTSTRANGE,,,,Cítíš se opět jako ty.,Du føler dig som dig selv igen.,Du fühlst dich wieder wie du selbst,Νιώθης σάν τον εαύτο σου ξανά...,Vi denove sentas vin kiel vi mem.,Te sientes como tú mism@[ao_esp] otra vez.,,Tunnet olevasi jälleen oma itsesi.,Vous vous sentez mieux.,Magadhoz tértél.,Ti senti di nuovo te stesso.,自分自身の様に感じている。,자기 자신처럼 생각하게 됐다.,Je voelt je weer als jezelf.,Du føler deg som deg selv igjen.,Znów czujesz się sobą.,Você se sente normal novamente.,Tu sentes-te normal novamente.,Ți-ai revenit în simțiri.,Вы снова чувствуете себя собой.,Поново се осећате као ви.,Du känner dig som dig själv igen.,Tekrar kendin gibi hissediyorsun.,Ви почуваєтесь собою. +Lead boots on,TXT_LEADBOOTSON,,,,Olověné boty ZAP,Blystøvler TIL,Bleistiefel AN,Μολυβδένιες μπότες ΕΝΕΡΓΟΠΟΙΗΜΈΝΕΣ,Botoj el plumbo ŝaltita,Botas de plomo activadas,,Lyijysaappaat päällä,Bottes en plomb ON,Ólomcsizma BE,Stivali di Piombo ON,足枷 オン,납 부츠 켬,Loden laarzen aan,Blystøvler PÅ,Ołowiane buty włączone,Botas de chumbo ativadas,,Bocanci de plumb activați,Свинцовые сапоги надеты,Оловне чизме УКЉУЧЕНЕ,Blystövlar på,Kurşun çizmeler,Одягнено свинцеві чоботи +Lead boots off,TXT_LEADBOOTSOFF,,,,Olověné boty VYP,Blystøvler FRA,Bleistiefel AUS,Μολυβδένιες μπότες ΆΠΕΝΕΡΓΟΠΟΙΗΜΕΝΕΣ,Botoj el plumbo malŝaltita,Botas de plomo desactivadas,,Lyijysaappaat pois päältä,Bottes en plomb OFF,Ólomcsizma KI,Stivali di Piombo OFF,足枷 オフ,납 부츠 끔,Loden laarzen uit,Blystøvler AV,Ołowiane buty wyłączone,Botas de chumbo desativadas,,Bocanci de plumb dezactivați,Свинцовые сапоги сняты,Оловне чизме ИСКЉУЧЕНЕ,Blykängor av,Kurşun çizmeler kapalı,Знято свинцеві чоботи +You feel lighter,TXT_LIGHTER,,,,Cítíš se lehčí,Du føler dig lettere,Du fühlst dich leichter,Νιώθης πιο ελαφρής,Vi sentas vin pli malpeza,Te sientes más liger@[ao_esp],,Tunnet olosi kevyemmäksi,Vous vous sentez très léger.,Könnyűnek érzed magad,Ti senti più leggero,体が軽くなった,가벼운 느낌이 든다,Je voelt je lichter,Du føler deg lettere,Czujesz się lżejsz@[adj_pl],Você se sente mais leve,Tu sentes-te mais leve,Te simți mai ușor,Вы чувствуете лёгкость.,Осећате лакоћу.,Du känner dig lättare.,Daha hafif hissediyorsun,Ви побороли гравітацію +Gravity weighs you down,TXT_GRAVITY,,,,Gravitace tě táhne dolů,Tyngdekraften tynger dig ned,Schwerkraft belastet dich,Η βαρύτητα σε πιάνει.,Gravito pezigas vin,La gravedad te hace descender,,Painovoima painaa sinua alas,La gravité vous ramène au sol.,A gravitáció lehúz téged,La gravità ti riporta a terra,重力に従った,중력이 당신을 붙잡았다,Zwaartekracht werkt op je...,Tyngdekraften tynger deg ned,Grawitacja znów cię przyciąga,A gravidade volta a funcionar normalmente,A gravidade voltou ao normal,Gravitația te trage în jos,Гравитация тянет вас вниз.,Гравитација Вас вуче надоле.,Tyngdkraften tynger ner dig,Yerçekimi seni ağırlaştırır,Гравітація знову притискає вас до землі +No Target ON,TXT_NOTARGET_ON,,,,Neútočící příšery ZAP,Ingen mål TIL,notarget AN,Αστόχευτη λειτουργία ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Neniu Celo ŜALTITA,No Objetivo ACTIVADO,,Hyökkäämättömyystila PÄÄLLÄ,Monstres aveugles et sourds ON,Nem támadnak a szörnyek BE,Modalità Mostri ciechi e sordi ATTIVATA,ノーターゲット オン,적 표적 감지 켬,Geen doelwit AAN,No Target PÅ,Głuche i Ślepe Potwory WŁĄCZONE,Sem alvos ATIVADO,,Modul Inamici fără Țintă ACTIVAT,Незаметность ВКЛЮЧЕНА,Нема мете УКЉУЧЕНО,Inget mål på,Hedef Yok AÇIK,Невідчутність ввімкнено +No Target OFF,TXT_NOTARGET_OFF,,,,Neútočící příšery VYP,Ingen mål FRA,notarget AUS,Αστόχευτη λειτουργία ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Neniu Celo MALŜALTITA,No Objetivo DESACTIVADO,,Hyökkäämättömyystila POIS PÄÄLTÄ,Monstres aveugles et sourds OFF,Nem támadnak a szörnyek KI,Modalità Mostri ciechi e sordi DISATTIVATA,ノーターゲット オフ,적 표적 감지 끔,Geen doelwit UIT,No Target AV,Głuche i Ślepe Potwory WYŁĄCZONE,Sem alvos DESATIVADO,,Modul Inamici fără Țintă DEZACTIVAT,Незаметность ОТКЛЮЧЕНА,Нема мете ИСКЉУЧЕНО,Inget mål av,Hedef Yok KAPALI,Невідчутність вимкнено +"""Quake with fear!""",TXT_ANUBIS_ON,,,,„Třeste se strachy!“,"""Skælv af frygt!""",„Zittere vor Angst!“,"""Τρέμε με φόβο!""","""Tremu pro timo!""","""¡Temblad de miedo!""","""¡Tiemblen de miedo!""","""Vapise pelosta!""",« Tremblez de terreur! »,"""Reszkess, halandó!""","""Trema con terrore!""",恐れおののけ!,공포에 떨어라!,„Beving van angst!“,"""Skjelv av frykt!""","""Trzęś się ze strachu""","""Trema de medo!""","""Trema com medo!""","""Tremură de Frică!""",«Дрожите от страха!»,„Дрхтите у страху!“,"""Skräck skakar av rädsla!""","""Korkudan titre!""","""Трясись зі страху!""" +No more Ogre Armor,TXT_ANUBIS_OFF,,,,Už žádné zlobří brnění,Ikke mere troldepanser,Keine Ogerrüstung mehr,Καθόλου δρακοντική πανοπλία πια,Ne plu Ogrokiraso,No más armadura de Ogro,,Ei enää örkkipanssaria,Plus d'armure d'ogre,Ogre pajzs lejárt,Niente più armatura Ogre,オーガアーマーはもう嫌,오거 갑옷은 이제 없다.,Geen Ogre Pantser meer,Ikke mer Ogre Armor,Nigdy więcej Pancerza Ogrów,Chega de Armadura de Ogro,Chega de Armadura de Ogre,Gata cu Armura de Căpcăun,Броня огра снята,Нема више бауков оклоп,Inget mer träsktorns rustning,Artık Ogre Zırhı yok,Броню огра знято +chasecam ON,TXT_CHASECAM_ON,,,,Pohled z třetí osoby ZAP,chasecam TIL,chasecam AN,Κάμερα τρίτου πρωσώπου ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Ĉaskamerao ŜALTITA,Cámara de seguimiento ACTIVADA,,Seurantakamera PÄÄLLÄ,,követő kamera BE,Modalità camera da inseguimento ATTIVATA,チェイスカメラ オン,3인칭 카메라 켬,Chasecam AAN,chasecam PÅ,kamera śledzenia WŁĄCZONA,Câmera em terceira pessoa ATIVADA,Câmara em Terceira Pessoa ATIVADA,Perspectivă la Persoana a 3-a ACTIVATĂ,Вид от третьего лица ВКЛЮЧЁН,Чејс-кам УКЉУЧЕН,chasecam på,Chasecam AÇIK,Камера від 3-го лиця активована +chasecam OFF,TXT_CHASECAM_OFF,,,,Pohled z třetí osoby VYP,chasecam FRA,chasecam AUS,Κάμερα τρίτου πρωσώπου ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Ĉaskamerao MALŜALTITA,Cámara de seguimiento DESACTIVADA,,Seurantakamera POIS PÄÄLTÄ,,követő kamera KI,Modalità camera da inseguimento DISATTIVATA,チェイスカメラ オフ,3인칭 카메라 끔,Chasecam UIT,chasecam AV,kamera śledzenia WYŁĄCZONA,Câmera em terceira pessoa DESATIVADA,Câmara em Terceira Pessoa DESATIVADA,Perspectivă la Persoana a 3-a DEZACTIVATĂ,Вид от третьего лица ОТКЛЮЧЁН,Чејс-кам ИСКЉУЧЕН,chasecam av,Chasecam KAPALI,Камера від 3-го лиця деактивована +1 baddie killed,TXT_BADDIE_KILLED,,,,1 zloun zabit,1 baddie dræbt,1 Bösewicht getötet,Ενας κακός πέθανε,1 malbonulo mortigita,Un malote aniquilado,,1 pahis tapettu,1 enemi tué,1 rosszfiú kinyírva,Ucciso 1 maligno,1 体 殺した,1 명의 나쁜놈이 사살됨.,1 slechterik gedood,1 skurk drept,1 zabity przeciwnik,1 inimigo morto,,1 slab ucis,1 плохиш убит,Један зликовац убијен,1 skurk dödad,1 kötü öldürüldü,1 поганець вмер +%d baddies killed,TXT_BADDIES_KILLED,,,,%d zlounů zabito,%d baddies dræbt,%d Bösewichte getötet,%d τον κακόν πέθαναν,%d malbonuloj mortigitaj,%d malotes aniquilados,,%d pahista tapettu,%d enemis tués,%d rosszfiú kinyírva,Uccisi %d maligni,%d 体 殺した,%d 명의 나쁜놈들이 사살됨.,%d slechteriken gedood,%d skurker drept,%d zabitych przeciwników,%d inimigos mortos,,%d slabi uciși,Плохишей убито: %d,%d зликовца убијено,%d skurkar dödade,%d kötüler öldürüldü,Поганців вмерло: %d +1 monster killed,TXT_MONSTER_KILLED,,,,1 příšera zabita,1 monster dræbt,1 Monster getötet,Ένα τέρας πέθανε,1 monstro mortigita,Un monstruo aniquilado,,1 hirviö tapettu,1 monstre tué,1 szörny kinyírva,Ucciso 1 mostro,1 匹 殺した,1 마리의 몬스터가 사살됨.,1 monster gedood,1 monster drept,1 zabity potwór,1 monstro morto,,1 monstru ucis,1 монстр убит,Једно чудовиште убијено,1 monster dödat,1 canavar öldürüldü,1 монстра убито +%d monsters killed,TXT_MONSTERS_KILLED,,,,%d příšer zabito,%d monster dræbt,%d Monster getötet,%d τον τεράτων πέθαναν,%d monstroj mortigitaj,%d monstruos aniquilados,,%d hirviötä tapettu,%d monstres tués,%d szörny kinyírva,Uccisi %d mostri,%d 匹 殺した,%d 마리의 몬스터들이 사살됨.,%d monsters gedood,%d monstre drept,%d zabitych potworów,%d monstros mortos,,%d monștri uciși,Убито монстров: %d,%d чудовишта убијено,%d monster dödade,öldürülen %d canavar,Монстрів вбито: %d +Unable to resurrect. Player is no longer connected to its body.,TXT_NO_RESURRECT,,,,"Oživení není možno, hráč už není spojen se svým tělem.",Kan ikke genoplive. Spilleren er ikke længere forbundet med sin krop.,Kann nicht wiederbeleben. Der Spieler ist nicht mehr mit seinem Körper verbunden.,"Ανάσταση αδύνατη, ο παίχτης δεν είναι πια στο σώμα @[pro4_gr]","Nerevivigebla. La ludanto ne plu +estas konektita al sia korpo.",Imposible de resucitar. El jugador ya no está conectado a su cuerpo.,,Ei mahdollista herätä henkiin. Pelaaja ei ole enää yhteydessä ruumiiseensa.,Impossible de ressuciter. Le joueur n'est plus connecté à son corps.,Nem sikerült a felélesztés. A játékos nincs összekötve a testtel.,Impossibile resuscitarsi. Il giocatore non è più connesso al suo corpo.,復活できない。プレイヤーはこの体に宿っていない。,부활할 수 없습니다. 플레이어는 더 이상 육체와 연결돼있지 않습니다.,Kan niet reanimeren. De speler is niet langer verbonden met zijn lichaam.,Kan ikke gjenoppstå. Spilleren er ikke lenger koblet til kroppen sin.,Nie można wskrzesić. Gracz nie jest już połączony z resztą swojego ciała.,"Impossível ressuscitar. O jogador não +está mais ligado ao próprio corpo.",,Imposibil de înviat. Jucătorul nu mai e conectat la cadavru.,Воскрешение невозможно. Игрок больше не соединён с трупом.,Немогуће оживети. Играч није више повезан са својим телом.,Det går inte att återuppliva. Spelaren är inte längre ansluten till sin kropp.,Diriltilemiyor. Oyuncu artık bedenine bağlı değil.,Воскресіння неможливе. Гравець більше не з'єднаний з тілом. +All Artifacts!,TXT_ALL_ARTIFACTS,,,All Artefacts!,Všechny artefakty!,Alle artefakter!,Alle Artefakte!,Όλα τα τεχνουργίματα!,Ĉiuj Artefaktoj!,¡Todos los artefactos!,,Kaikki artefaktit!,Tous les artéfacts!,Összes értéktárgy!,Tutti gli Artefatti!,全アーティファクト!,모든 유물들!,Alle artefacten!,Alle artefakter!,Wszystkie Artefakty!,Todos os artefatos!,,Toate Artefactele!,Все артефакты!,Сви артифакти!,Alla artefakter!,Tüm eserler!,Усі артефакти! +What do you want to kill outside of a game?,TXT_WHAT_KILL,,,,"Co chceš zabít, když nejsi ve hře?",Hvad vil du dræbe uden for et spil?,Was willst du eigentlich außerhalb eines Spiels töten?,Τί θέλεις να σκοτώσεις έξω απο ένα παιχνίδι ?,Kion vi volas mortigi ekster ludo?,¿Qué intentas matar fuera de una partida?,,Mitä haluat tappaa pelin ulkopuolella?,Que voulez-vous tuer en dehors d'une partie?,Mit tudnál megölni játékon kívül?,Cosa vorresti uccidere fuori dal gioco?,ゲーム外で何を殺す気だ?,게임 밖에서 무엇을 죽이고 싶습니까?,Wat wil je buiten een spel om doden?,Hva vil du drepe utenfor et spill?,Co ty chcesz zabić poza grą?,O que você gostaria de matar fora de um jogo?,,Ce vrei să ucizi în afara unui joc?,Что вы хотите убить вне игры?,Шта желите да убијете ван игре?,Vad vill du döda utanför ett spel?,Oyun dışında ne öldürmek istiyorsun?,"Що, хочеш вбивати в реальності?" +Frozen player properties turned off,TXT_NOT_FROZEN,,,,Vlastnosti držící hráče na místě vypnuty,Frysningstilstand er slået fra.,Gefrier-Modus abgeschaltet.,Η ιδιότητες ενος παγομένου παίχτη απενεργοποίθηκαν,Atributoj de movhaltitaj ludantoj malŝaltitaj,Propiedades de jugador congelado desactivadas,,Jäätyneen pelaajan ominaisuudet kytketty pois päältä,Propriété gelée du joueur annulée.,Fagyasztott játékos tulajdonságai kikapcsolva,Proprietà del giocatore ghiacciato disattivate,凍ったプレイヤーのプロパティを無効化,플레이어 정지 속성이 꺼졌습니다.,Eigenschappen van de bevroren speler uitgeschakeld,Frosne spilleregenskaper slått av,Właściwości zamrożonego gracza wyłączone,Propriedades de jogador congelado desativadas,,Proprietăți jucători înghețați DEZACTIVATE,Свойства замороженного игрока отключены,Смрзнути играчи искључени,Frysta spelaregenskaper avstängda,Dondurulmuş oyuncu özellikleri kapatıldı,Властивості замороженого гравця вимкнено +,,Automap,,,,,,,,,,,,,,,,,,,,,,,,,, +Follow Mode OFF,AMSTR_FOLLOWOFF,,,,Režim sledování VYP,Følg-tilstand TIL,Folgen-Modus AUS,Ακολούθηση ΆΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Sekvigreĝimo MALŜALTITA,Modo de seguimiento DESACTIVADO,,Seuraamistila POIS PÄÄLTÄ,Suivi du Joueur OFF,Követés mód KI,Mappa scorribile ATTIVATA,追従モード: オフ,추적 모드 끔,Volgmodus UIT,Følgemodus AV,Tryb śledzenia WYŁĄCZONY,Modo de seguimento DESATIVADO,,Mod Urmărire DEZACTIVAT,Привязка к игроку ОТКЛЮЧЕНА,Праћење ИСКЉУЧЕНО,Följningsläget av,Takip Modu KAPALI,Прив'язка до гравца ВВІМК. +Follow Mode ON,AMSTR_FOLLOWON,,,,Režim sledování ZAP,Følg-tilstand FRA,Folgen-Modus AN,Ακολούθηση ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Sekvigreĝimo ŜALTITA,Modo de seguimiento ACTIVADO,,Seuraamistila PÄÄLLÄ,Suivi du Joueur ON,Követés mód BE,Mappa scorribile DISATTIVATA,追従モード: オン,추적 모드 켬,Volgmodus AAN,Følgemodus PÅ,Tryb śledzenia WŁĄCZONY,Modo de seguimento ATIVADO,,Mod Urmărire ACTIVAT,Привязка к игроку ВКЛЮЧЕНА,Праћење УКЉУЧЕНО,Följningsläget på,Takip Modu AÇIK,Прив'язка до гравца ВИМК. +Grid ON,AMSTR_GRIDON,,,,Mřížka ZAP,Raster TIL,Gitter AN,Πλέχμα ΕΝΕΡΓΟΠΟΙΜΈΝΟ,Krado ŜALTITA,Cuadrícula ACTIVADA,,Ruudukko PÄÄLLÄ,Quadrillage ON,Rács BE,Griglia ATTIVATA,グリッド: オン,격자 켬,Raster AAN,Rutenett PÅ,Siatka WŁĄCZONA,Grade ATIVADA,Grelha ATIVADA,Grilă ACTIVATĂ,Сетка ВКЛЮЧЕНА,Мрежа УКЉУЧЕНА,Rutnät på,Izgara AÇIK,Сітка ВВІМК. +Grid OFF,AMSTR_GRIDOFF,,,,Mrizka VYP,Raster FRA,Gitter AUS,Πλέχμα ΆΠΕΝΕΡΓΟΠΟΙΜΈΝΟ,Krado MALŜALTITA,Cuadrícula DESACTIVADA,,Ruudukko POIS PÄÄLTÄ,Quadrillage OFF,Rács KI,Griglia DISATTIVATA,グリッド: オフ,격자 끔,Raster UIT,Rutenett AV,Siatka WYŁĄCZONA,Grade DESATIVADA,Grelha DESATIVADA,Grilă DEZACTIVATĂ,Сетка ОТКЛЮЧЕНА,Мрежа ИСКЉУЧЕНА,Rutnät av,Izgara KAPALI,Сітка ВИМК. +Texture Mode ON,AMSTR_TEXON,,,,Texturovaný režim ZAP,Teksturtilstand TIL,Texturmodus AN,Γραφικός χάρτης ΕΝΕΡΓΟΠΟΙΜΈΝΟΣ,Tekstura Reĝimo ŜALTITA,Modo de texturas ACTIVADO,,Pintakuviointitila PÄÄLLÄ,Mode Texturé ON,Textúrák mód BE,Modalità Texture ATTIVATA,テクスチャーモード: オン,텍스쳐 모드 켬,Textuurmodus AAN,Teksturmodus PÅ,Tekstury WŁĄCZONE,Modo de textura ATIVADO,,Mod Texturat ACTIVAT,Текстурный режим ВКЛЮЧЁН,Текстуре УКЉУЧЕНЕ,Texturläge på,Doku Modu AÇIK,Текстурний режим ВВІМК. +Texture Mode OFF,AMSTR_TEXOFF,,,,Texturovaný režim VYP,Teksturtilstand FRA,Texturmodus AUS,Γραφικός χάρτης ΑΠΕΝΕΡΓΟΠΟΙΜΈΝΟΣ,Tekstura Reĝimo MALŜALTITA,Modo de texturas DESACTIVADO,,Pintakuviointitila POIS PÄÄLTÄ,Mode Texturé OFF,Textúrák mód KI,Modalità Texture DISATTIVATA,テクスチャーモード: オフ,텍스쳐 모드 끔,Textuurmodus UIT,Teksturmodus AV,Tekstury WYŁĄCZONE,Modo de textura DESATIVADO,,Mod Netexturat DEZACTIVAT,Текстурный режим ОТКЛЮЧЁН,Текстуре ИСКЉУЧЕНЕ,Texturläge av,Doku Modu KAPALI,Текстурний режим ВИМК. +Marked Spot,AMSTR_MARKEDSPOT,,,,Značka,Markeret placering,Punkt markiert,Μαρκαρησμένη τοποθεσεία,Loko Markita,Punto marcado,,Merkitty paikka,Repère marqué.,Megjelölt hely,Posizione segnata,目標をマークした,지점 추가,Gemarkeerde plek,Markert punkt,Oznaczono miejsce,Posição marcada,,Loc Marcat,Отметка,Означено место,Markerad punkt,İşaretli Nokta,Позначка +All Marks Cleared,AMSTR_MARKSCLEARED,,,,Všechny značky smazány,Alle markeringer slettes,Alle Markierungen gelöscht,Όλες η μαρκαρησμένη τοποθεσείες είναι καθαρησμένες,Ĉiuj Markoj Forigitaj,Todas las marcas eliminadas,,Kaikki merkit pyyhitty,Repères éffacés.,Összes jelölés törölve,Cancellati tutti i segni,全目標を解除した,모든 지점 지워짐,Alle markingen gewist,Alle merker fjernet,Wszystkie miejsca wyczyszczone,Todas as marcas removidas,,Toate Marcările Șterse,Отметки очищены,Ознаке избрисане,Alla markeringar raderas,Tüm İşaretler Temizlendi,Усі позначки стерто +,,Multiplayer,,,,,,,,,,,,,,,,,,,,,,,,,, +Fraglimit hit.,TXT_FRAGLIMIT,,,,Fraglimit dosáhnut.,Fraggrænse nået,Fraglimit erreicht,Το όριο κοματιασμόν έχει φτάσει.,Ludmurdo-limo trafita.,Límite de bajas alcanzado.,,Frägiraja saavutettu.,Limite de frags atteinte.,Fraghatár elérve.,Fraglimit raggiunto.,フラグリミット!,킬제한에 도달했습니다.,Fraglimiet bereikt.,Fraglimit treff.,Limit fragów wyczerpany.,Limite de frags atingido.,,Limita de ucideri atinsă.,Достигнут лимит фрагов.,Фраг-лимит достигнут.,Fragbegränsning träffad.,Frag limiti vuruldu.,Досягнуто ліміт фрагів. +Timelimit hit.,TXT_TIMELIMIT,,,,Časový limit dosáhnut.,Tidsgrænse nået,Zeitlimit erreicht,Το χρονικό όριο έχει φτάσει.,Tempolimo trafita.,Límite de tiempo alcanzado.,,Aikaraja saavutettu.,Limite de temps atteinte.,Időhatár elérve.,Timelimit raggiunto.,ゲームセット!,시간제한에 도달했습니다.,Tijdslimiet bereikt.,Tidsbegrensningen er nådd.,Limit czasowy wyczerpany.,Limite de tempo atingido.,,Limita de timp atinsă.,Достигнут лимит времени.,Временско ограничење достигнуто.,Tidsbegränsning träffad.,Zaman limiti vuruldu.,Досягнуто ліміт часу. +%o was looking good until %g killed %hself!,SPREEKILLSELF,,,,%o vypadal@[ao_cs] dobře dokud se @[self_cs] nezabil@[ao_cs]!,"%o så godt ud, indtil @[pro_dk] dræbte sig selv!","%o sah gut aus, bis das Unglück geschah.",@[art_gr] %o πήγενε μια χαρά μέχρι που αυτοκτόνησε!,"%o estis faranta bone, ĝis @[pro_eo] mortigis sin!",¡%o se veía bien hasta que %g se mató a si mism@[ao_esp]!,,"%o oli liekeissä, kunnes meni tappamaan itsensä!",%o était en pleine folie meurtrière avant qu' %g ne se bute!,%o jól nézett ki még mielőtt megölte magát!,%o stava andando bene finchè non si è ucciso da solo!,%o は自滅するまでなかなか良かったぞ!,%o 이(가) 잘 나가려던 참에 자살했습니다!,%o zag er goed uit tot %g zelfmoord pleegde!,%o så bra ut helt til %g tok livet av seg!,%o wyglądał dobrze dopóki się nie zabił@[ao_pl],%o estava indo bem até se matar!,,%o arăta atât de bine până să se sinucidă,"%o неплохо выглядел@[ao_rus], пока не покончил@[ao_rus] с собой!",%o је изгледа@[ao_1_sr] добро док није уби@[ao_1_sr] сам@[ao_3_sr] себе!,%o såg bra ut tills han tog livet av sig!,%o kendini öldürene kadar iyi görünüyordu!,"%o вигляда@[adj_1_ua] добре, поки не вби@[adj_1_ua] себе!" +%o's killing spree was ended by %k,SPREEOVER,,,,%o@[psn1_cs] vraždící řádění ukončil hráč %k.,%os drabstog blev afsluttet af %k,%os Amoklauf wurde von %k beendet.,Ο/Η %k σταμάτησε την ανθρωποκτονία %h %o.,La mortigado de %o estis finita de %k,%k acabó con la racha de muerte de %o,,%k päätti pelaajan %o tapposarjan,La folie meurtrière de %o à été terminée par %k!,%o ámokfutását %k megállította.,La sequela di frag di %o è stata terminata da %k,%k が %o の快進撃を断ち切った!,%k 이(가) %o 의 연속 킬을 처단했습니다,%o's moordpartij werd beëindigd door %k.,%o's drapsturné ble avsluttet av %k.,Seria zabójstw %o zakończona przez %k,A matança de %o foi interrompida por %k,,Pofta de ucis a lui %o a fost pusă în cui de către %k,Игрок %k прервал череду убийств игрока %o,Серијско убијање играча %o је завршио играч %k,%os dödskampanj avslutades av %k.,%o onu öldürene kadar %k iyi görünüyordu.,%k закінчи@[adj_1_ua] бійню %o +%k is on a killing spree!,SPREE5,,,,%k začal@[ao_cs] řádit!,%k er i gang med en mordserie!,%k läuft Amok!,Ο/Η %k άρχισε μια ανθρωποκτονία!,%k estas sur mortigado!,¡%k está atacando de lo lindo!,,%k on sarjamurhaaja!,%k est en folie meurtrière!,%o egy Ámokfutó!,%k è preda di un momento omicida!,%k が連続キル!,%k 연속 킬!,%k is op een moordpartij!,%k er på drapsturné!,%k popełnia serię morderstw!,%k está cometendo uma matança!,,%k are chef de ucis!,Игрок %k совершил череду убийств!,%k је серијални убица!,%k är på en mordresa!,%k bir ölüm çılgınlığında!,%k смакує різанину! +%k is on a rampage!,SPREE10,,,,%k zuří!,%k er på et amokløb!,%k tobt sich aus!,Ο/Η %k είναι σε ξέσπασμα!,%k estas sur furiozado!,¡%k está en medio de una aniquilación!,,%k riehuu valtoimenaan!,%k est en plein massacre!,%o Tombol!,%k sta facendo un massacro!,%k が大暴れだ!,%k 이(가) 미쳐 날뛰고 있습니다!,%k heeft razernij!,%k går amok!,%k doznaje szału!,%k está massacrando!,,%k e înverșunat!,Игрок %k в неистовстве!,%k дивља!,%k är på en våldsam resa!,%k kudurmuş durumda!,%k лютує! +%k is dominating!,SPREE15,,,,%k dominuje!,%k er dominerende!,%k dominiert!,Ο/Η %k κατακτεί.,%k estas dominanta!,¡%k está dominando!,,%k hallitsee suvereenisti!,%k domine!,%o Uralkodik!,%k sta dominando tutti!,%k が圧倒している!,%k 이(가) 우세하고 있습니다!,%k domineert!,%k dominerer!,%k dominuje!,%k está dominando!,,%k domină!,Игрок %k господствует!,%k доминира!,%k dominerar!,%k hükmediyor!,%k домінує! +%k is unstoppable!,SPREE20,,,,%k je nezastaviteln@[adj_cs]!,%k er ustoppelig!,%k kann nicht gestoppt werden!,Ο/Η %k είναι ασταμάτητος/η!,%k estas nehaltigebla!,¡%k es imparable!,,%k on pysäyttämätön!,%k est inarrétable!,%o Megállíthatatlan!,%k è inarrestabile!,%k が止まらない!,%k 을(를) 막을 수없습니다!,%k is niet te stoppen!,%k er ustoppelig!,%k jest niepowstrzymany!,%k é implacável!,,%k e de neoprit!,Игрок %k неостановим!,Играч %k је незаустављив!,%k är ostoppbar!,%k durdurulamaz!,%k неспинний! +%k is Godlike!,SPREE25,,,,%k je boží!,%k er som en gud!,%k ist wie Gott!,Ο/Η %k είναι σαν θεός/θεά!,%k estas Dia!,¡%k es una máquina de matar!,,%k on kuin jumala!,%k est un dieu!,%o Istencsászár!,%k è un dio!,%k が神の様だ!,%k 은(는) 신적입니다! ,%k is Goddelijk!,%k er guddommelig!,%k jest Bogem!,%k é um deus da matança!,,%k e precum un Zeu!,Игрок %k богоподобен!,Играч %k је божанствен!,%k är som en gud!,%k tanrı gibi!,%k божественний! +Double kill!,MULTI2,,,,Dvoj-zabití!,Dobbelt drab!,Doppel-Kill!,Δυπλός Θάνατος!,Duobla mortigo!,¡Dos menos!,,Tuplatappo!,,Dupla gyilok!,Doppia uccisione!,ダブルキル!,더블 킬!,Dubbele kill!,Dobbeltdrap!,Podwójne zabójstwo!,Morte dupla!,,Dublă ucidere!,Двойное убийство!,Дупло убиство!,Dubbeldödning!,Çifte öldürme!,Подвійне вбивство! +Multi kill!,MULTI3,,,,Multi-zabití!,Multi-drab!,Multi-Kill!,Πολυθάνατος!,Pluraj mortigoj!,¡Multidestrucción!,,Multitappo!,,Multi gyilok!,Tripla uccisione!,マルチキル!,멀티 킬!,,Multidrap!,Multi-zabójstwo!,Morte tripla!,,Ucidere multiplă!,Массовое убийство!,Вишеструко убиство!,Flera dödar!,Çoklu öldürme!,Массове вбивство! +Ultra kill!,MULTI4,,,,Ultra-zabití!,Ultra-drab!,Ultra-Kill!,Υπερθάνατος!,Ekstremaj mortigoj!,¡¡HIPERDESTRUCCIÓN!!,,Ultratappo!,,Ultra gyilok!,Ultra uccisione!,ウルトラキル!,울트라 킬!,,Ultra drep!,Ultra-zabójstwo!,Ultra matança!,,Ultra ucidere!,Ультра-убийство!,Ултра убиство!,Ultra-död!,Ultra öldürme!,Безмежне вбивство! +Monster kill!,MULTI5,,,,Monstr-zabití!,Monster-drab!,Monster-Kill!,Τερατόδες σκοτωμός!,Monstraj mortigoj!,¡¡¡S.U.P.E.R.D.E.S.T.R.U.C.C.I.Ó.N!!!,,Hirviömäinen tappo!,,Szörnyű gyilkolás!,Uccisione Mostruosa!,モンスターキル!,몬스터 킬!,,Monster drep!,Potworne zabójstwo!,Matança monstro!,Matança monstruosa!,Ucidere monstruoasă!,Чудовищное убийство!,Монструозно убиство!,Monsterdöd!,Canavar öldürme!,Монструозне вбивство! +,,Scoreboard,,,,,,,,,,,,,,,,,,,,,,,,,, +Bonus,SCORE_BONUS,,,,,,,,Bonuso,Bonificaciones,,Lisäedut,,Bónusz,,ボーナス,보너스,Bonus,,Bonusy,Bônus,,,Бонус,Бонус,,,Бонус +Color,SCORE_COLOR,,,Colour,Barva,Farve,Farbe,Χρώμα,Koloro,,,Väri,Couleur,Szín,Colore ,色,색상,Kleur,Farge,Kolor,Cor,,Culoare,Цвет,Боја,Färg,Renk,Колір +Secret,SCORE_SECRET,,,,Skrýše,Hemmeligt,Geheimnis,Μυστικό,Sekreto,Secreto,,Salat,,Titok,Segreto,シークレット,밝혀낸 비밀,Geheim,Hemmelig,Sekret,Segredo,,,Тайники,Тајна,Hemlig,Sır,Схованки +Name,SCORE_NAME,,,,Jméno,Navn,Name,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Navn,Nazwa,Nome,,Nume,Игрок,Име,Namn,İsim,Гравець +Delay (ms),SCORE_DELAY,,,,Zpoždění (ms),Forsinkelse (ms),Verzögerung (ms),Kαθυστέρηση (μδ),Prokrasto (ms),Retraso (ms),,Viive (ms),Délai (ms),Késleltetés (ms),Ritardo (ms) ,ping,핑 (밀리초당),Vertraging (ms),Forsinkelse (ms),Opóźnienie (ms),Atraso (ms),,Întârziere (ms),Задержка (мс),Кашњење (мс),Fördröjning (ms),Gecikme (ms),Затримка (мс) +Frags,SCORE_FRAGS,,,,Fragy,,,Κοματιασμοί,Ludmurdoj,Bajas,,Frägit,,Frag-ek,,フラグ,플레이어 킬수,,,Fragi,,,Victime,Фраги,Фрагови,,,Фраги +Deaths,SCORE_DEATHS,,,,Smrti,Dødsfald,Tode,Θάνατοι,Mortoj,Muertes,,Kuolemat,Morts,Halálok,Morti,デス,사망한 횟수,Sterfgevallen,Dødsfall,Śmierci,Mortes,,Decese,Смерти,Смрти,Dödsfall,Ölümler,Смерті +Other,SCORE_OTHER,,,,Ostatní,Andre,Andere,,Alia,Demás,,Muu,Autre,Egyéb,Altro,その他,,Anders,Andre,Inne,Outro,,Altele,Прочее,,Andra,Diğer,Інше +Missed,SCORE_MISSED,,,,Minuto,Forpasset,Verfehlt,Ξεχάστηκαν,Mankita,Pérdidas,,Hudit,Ratés,Kihagyva,Mancati ,ミス,놓친 수,Gemist,Ubesvarte,Ominięte,Perdido,,Ratate,Пропущено,Пропуштено,Missade,Cevapsız,Пропущено +Total,SCORE_TOTAL,,,,Celkem,,Gesamt,Συνολικό,Tuto,,,Yhteensä,,Összesen,Totale,合計,총점,Totaal,Totalt,Totalne,,,,Всего,Укупно,Totalt,Toplam,Разом +Level Time,SCORE_LVLTIME,,,,Čas v levelu,Niveau Tid,Levelzeit,Χρόνος Πίστας,Daŭro de Nivelo,Tiempo de nivel,,Tasoaika,Temps niveau,Pályaidő,Tempo Livello ,時間,레벨 시간,Leveltijd,Nivå Tid,Czas,Tempo de fase,Tempo do Nível,Timp Petrecut,Время уровня,Време нивоа,Nivå Tid,Seviye Zaman,Час рівня +,,Level Summary,,,,,,,,,,,,,,,,,,,,,,,,,, +Kills,TXT_IMKILLS,,,,Zabití,Dræber,,Σκοτομοί,Mortigoj,Muertes,,Tapot,Morts,Áldozatok,Uccisioni,キル,킬수,Dood,Drepte,Zabici,Vítimas,,Ucideri,Убийств,Непријатељи,Dödade,Öldürür,Вороги +Items,TXT_IMITEMS,,,,Předměty,Genstande,Gegenstände,Αντεικείμενα,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,획득한 아이템,,Gjenstander,Przedmioty,Itens,,Obiecte,Предметов,Ставке,Föremål,Eşyalar,Предмети +Secrets,TXT_IMSECRETS,,,,Skrýše,Hemmeligheder,Geheimnisse,Μυστικά,Sekretoj,Secretos,,Salat,,Titkok,Segreti,シークレット,밝혀낸 비밀,Geheimen,Hemmeligheter,Sekrety,Segredos,,Secrete,Тайников,Тајне,Hemligheter,Sırlar,Схованки +Time,TXT_IMTIME,,,,Čas,Tid,Zeit,Χρόνος,Daŭro,Tiempo,,Aika,Temps,Idő,Tempo,経過時間,소모한 시간,Tijd,Tid,Czas,Tempo,,Timp,Время,Време,Tid,Zaman,Час +Par,TXT_IMPAR,,,,,,,Μέσος Όρος,Alparo,,,,,Átlag,Media,最速時間,기준 시간,,,,Média,,Record,Рекорд,Рекорд,,,Рекорд +Finished,WI_FINISHED,,,,Dokončeno,Færdig,Abgeschlossen,Ολοκληρώθηκε,Finita,Completado,,Suoritettu,Terminé,Teljesítve,Finito,攻略,완료,Klaar,Ferdig,Ukończono,Finalizado,,Terminat,Уровень завершён,Ниво завршен,Avslutad,Bitti,Завершено +Entering,WI_ENTERING,,,,Vstupuješ do,Indtastning af,Betrete,Είσοδος,Enirante,Entrando a:,,Seuraava kohde,Niveau Suivant,Következik,Prossimo livello,突入開始,입장,Volgende,Går inn,Wchodzisz do:,Próxima fase,Próximo nível,Începe,Переход,Следећи ниво,Ingång till,Giriş,Заходимо +Now entering:,WI_ENTERING,,heretic hexen,,Nyní vstupuješ do:,Indtastning af:,Betrete:,Τώρα εισέρχεσε στο:,Nun enirante:,Ahora entrando a:,,Seuraava kohde:,Vous entrez dans:,Következik:,Entrando adesso in:,突入中:,입장합니다:,Volgende:,Går nå inn:,Teraz wchodzisz do:,Entrando em:,A entrar em:,Acum începe:,Переход на:,Следећи ниво:,Ingång till,Şimdi giriyoruz:,Просуваємось до: +,,HUD,,,,,,,,,,,,,,,,,,,,,,,,,, +Monsters:,AM_MONSTERS,,,,Příšery:,Monstre:,Monster:,Τέρατα,Monstroj:,Monstruos:,,Hirviöt:,Monstres:,Szörnyek:,Mostri,奴等:,죽인 적들:,,Monstre:,Potwory:,Monstros:,,Monștri:,Монстры:,Чудовишта:,Monster:,Canavarlar:,Монстри +Secrets:,AM_SECRETS,,,,Skrýše:,Hemmeligheder:,Geheimnisse:,Μυστικά,Sekretoj:,Secretos:,,Salat:,,Titkos helyek:,Segreti,隠場:,찾은 비밀:,Geheimen:,Hemmeligheter:,Sekrety:,Segredos:,,Secrete:,Тайники:,Тајне:,Hemligheter:,Sırlar:,Схованки: +Items:,AM_ITEMS,,,,Věci:,Genstande:,Gegenstände:,Αντεικείμενα,Objektoj:,Objetos:,,Esineet:,Objets:,Tárgyak:,Oggetti,物資:,얻은 아이템:,,Gjenstander:,Przedmioty:,Itens:,,Obiecte:,Предметы:,Предмети:,Föremål:,Eşyalar:,Предмети: +,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,,,, +%o suicides.,OB_SUICIDE,,,,%o spáchal@[ao_cs] sebevraždu.,%o begår selvmord.,%o begeht Selbstmord.,@[art_gr] %o αυτοκτόνησε,%o sinmortigis.,%o se ha suicidado.,%o se suicidó.,%o teki itsemurhan.,%o se suicide.,%o öngyilkos lett.,%o si è suicidato.,%o は自殺した。,%o 은(는) 자살했다.,%o pleegt zelfmoord.,%o begår selvmord.,%o popełnił@[ao_pl] samobójstwo.,%o se suicidou.,,%o se sinucide.,Игрок %o покончил с собой.,%o самоубиства.,%o tar självmord.,%o intihar eder.,%o самовби@[adj_2_ua]. +%o fell too far.,OB_FALLING,,,,%o spadl@[ao_cs] příliš daleko.,%o faldt for langt ned.,%o fiel zu tief.,@[art_gr] %o έπεσε,%o falis tro fore.,%o se ha caído desde muy alto.,%o se cayó desde muy alto.,%o putosi liian kaukaa.,%o est tombé@[e_fr] trop loin.,%o túl messze esett.,%o è caduto troppo in basso.,%o はあまりにも高い所から転落した。,%o 은(는) 높은 곳에서 떨어져 사망했다.,%o viel te ver.,%o falt for langt.,%o spadł@[ao_pl] za daleko.,%o caiu de um lugar alto.,,%o a căzut prea departe.,Игрок %o упал слишком далеко.,%o је па@[ao_1_sr] до сад.,%o föll för långt.,%o çok uzağa düştü.,%o впа@[adj_1_ua] надто глибоко. +%o was squished.,OB_CRUSH,,,,%o byl@[ao_cs] rozdrcen@[ao_cs].,%o blev mast.,%o wurde zerquetscht,@[art_gr] %o συνθλίφτηκε,%o estis dispremita.,%o ha quedado aplastad@[ao_esp].,%o quedó aplastad@[ao_esp].,%o liiskautui.,%o a été écrasé@[e_fr].,%o össze lett lapítva.,%o è stato schiacciato.,%o は潰された。,%o 은(는) 뭉게졌다.,%o werd geplet.,%o ble knust.,%o spłaszczył@[ao_pl] się.,%o foi esmagad@[ao_ptb].,,%o a fost strivit.,Игрок %o был раздавлен.,%o је здробљен@[adj_1_sr].,%o blev mosad.,%o ezildi.,%o розчавило. +%o tried to leave.,OB_EXIT,,,,%o se pokusil@[ao_cs] odejít.,%o forsøgte at gå.,%o wollte gehen.,@[art_gr] %o προσπάθησε να φύγει,%o provis foriri.,%o ha tratado de huir.,%o trató de huir.,%o yritti häipyä.,%o a tenté de partir.,%o megpróbált lelépni.,%o ha provato a uscire.,%o は逃げようとした。,%o 은(는) 나가려고 발버둥 쳤다.,%o probeerde te vertrekken.,%o prøvde å dra.,%o spróbował@[ao_pl] odejść.,%o tentou sair.,,%o a încercat să plece.,Игрок %o попытался уйти.,%o покуша@[ao_1_sr] да оде.,%o försökte lämna.,%o gitmeye çalıştı.,%o намага@[adj_2_ua] втекти. +%o can't swim.,OB_WATER,,,,%o neumí plavat.,%o kan ikke svømme.,%o kann nicht schwimmen.,@[art_gr] %o δέν μπορεί να κολυμπήσει,%o ne scipovas naĝi.,%o no sabe nadar.,,%o ei osaa uida.,%o ne sait pas nager.,%o nem tud úszni.,%o non sapeva nuotare.,%o は泳げなかった。,%o 은(는) 익사했다.,%o kan niet zwemmen.,%o kan ikke svømme.,%o nie umie pływać.,%o não sabe nadar.,,%o nu poate înota.,Игрок %o не умел плавать.,%o не може да плива.,%o kan inte simma.,%o yüzme bilmiyor.,%o не вміє плавати. +%o mutated.,OB_SLIME,,,,%o zmutoval@[ao_cs].,%o muterede.,%o mutierte.,@[art_gr] %o μεταλάχθηκε,%o mutaciis.,%o ha mutado.,%o mutó.,%o mutatoitui.,%o a muté.,%o mutánssá alakult.,%o è mutato.,%o は変異した。,%o 은(는) 돌연사를 당했다.,%o muteerde.,%o muterte.,%o zmutował@[ao_pl].,%o sofreu mutação.,,%o a avut parte de o mutație.,Игрок %o мутировал.,%o је мутиран@[adj_1_sr].,%o muterade.,%o mutasyona uğradı.,%o мутува@[adj_1_ua]. +%o melted.,OB_LAVA,,,,%o se rozpustil@[ao_cs].,%o smeltede.,%o schmolz.,@[art_gr] %o έλειοσε,%o fandiĝis.,%o se ha fundido.,%o se fundió.,%o suli.,%o a fondu.,%o megolvadt.,%o si è sciolto.,%o は溶かされた。,%o 은(는) 녹아버렸다.,%o smolt.,%o smeltet.,%o stopił@[ao_pl] się.,%o derreteu.,%o derreteu-se.,%o s-a topit.,Игрок %o расплавился.,%o је отопљен@[adj_1_sr].,%o smälte.,%o eridi.,%o розплави@[adj_2_ua]. +%o went boom.,OB_BARREL,,,,%o udělal@[ao_cs] bum.,%o gik bum.,%o explodierte.,@[art_gr] %o έσκασε,%o eksplodis.,%o ha explotado en mil pedazos.,%o explotó en mil pedazos.,%o poksahti.,%o s'est pété@[e_fr] la face.,%o felrobbant.,%o ha fatto bum.,%o は爆発で吹き飛ばされた。,%o 은(는) 폭사했다.,%o ging boem.,%o gikk i lufta.,%o zrobił@[ao_pl] bum.,%o explodiu.,,%o a explodat.,Игрок %o взорвался.,%o је отиш@[ao_2_sr] бум.,%o blev boom.,%o patladı.,%o вибухну@[adj_1_ua]. +%o stood in the wrong spot.,OB_SPLASH,,,,%o stál@[ao_cs] na špatném místě.,%o stod på det forkerte sted.,%o war am falschen Ort.,@[art_gr] %o έκατσε στο λάθος σημείο,%o staris en la malĝusta loko.,%o estaba en el sitio equivocado.,,%o seisoi väärässä paikassa.,%o s'est tenu@[e_fr] au mauvais endroit.,%o rossz helyre állt.,%o si è trovato nel posto sbagliato.,%o はいけない場所に立っていた。,%o 은(는) 위험한 곳에 서 있었다.,%o stond op de verkeerde plek.,%o sto på feil sted.,%o stan@[irreg_2_pl] w złym miejscu.,%o ficou no lugar errado.,,%o a stat în locul nepotrivit.,Игрок %o стоял в неверной точке.,%o је стаја@[ao_1_sr] на погрешно место.,%o stod på fel plats.,%o yanlış yerde durdu.,%o бу@[adj_1_ua] не в тому місці. +%o should have stood back.,OB_R_SPLASH,,,,%o měl@[ao_cs] stát o trochu dál.,%o skulle have stået tilbage.,%o hätte Abstand halten sollen.,@[art_gr] %o έπρεπε να είχε κάτσι πίσω,%o devintus forstarinta.,%o debería haberse apartado.,,%o oli liian likellä.,%o aurait dû garder ses distances.,%o túl közel állt.,%o si sarebbe dovuto allontanare.,%o は後ろへ引くべきだった。,%o 은(는) 좀 더 떨어져야만 했다.,%o had afstand moeten houden.,%o burde ha stått tilbake.,%o nie ustąpił@[ao_pl] na bok.,%o deveria ter se afastado.,,%o ar fi trebuit să stea deoparte.,Игрок %o не отступил в сторону.,Играчу %o је требало да стоји назад.,%o borde ha stått tillbaka.,%o geri çekilmeliydi.,%o треба було відійти подалі. +%o should have stood back.,OB_ROCKET,,,,%o měl@[ao_cs] stát o trochu dál.,%o skulle have stået tilbage.,%o hätte Abstand halten sollen.,@[art_gr] %o έπρεπε να είχε κάτσι πίσω,%o devintus forstarinta.,%o debería haberse apartado.,,%o oli liian likellä.,%o aurait dû garder ses distances.,%o túl közel állt.,%o si sarebbe dovuto allontanare.,%o は後ろへ引くべきだった。,%o 은(는) 더 멀리 떨어져야만 했다.,%o had afstand moeten houden.,%o burde ha stått tilbake.,%o nie ustąpił@[ao_pl] na bok.,%o deveria ter se afastado.,,%o ar fi trebuit să stea deoparte.,Игрок %o не отступил в сторону.,Играчу %o је требало да стоји назад.,%o borde ha stått tillbaka.,%o geri çekilmeliydi.,%o треба було відійти подалі. +%o killed %hself.,OB_KILLEDSELF,,,,%o se zabil@[ao_cs].,%o begik selvmord.,%o tötete sich selbst.,@[art_gr] %o αυτοκτόνησε,%o mortigis sin.,%o se ha matado a sí mism@[ao_esp].,%o se mató a sí mism@[ao_esp].,%o tappoi itsensä.,%o s'est tué@[e_fr].,%o megölte magát.,%o ha ucciso se stesso.,%o は自滅した。,%o 은(는) 자멸했다.,%o bracht zichzelf om.,%o begår selvmord.,%o zabił@[ao_pl] się.,%o se matou.,%o matou-se,%o s-a sinucis.,Игрок %o убил себя.,%o је уби@[ao_1_sr] себе.,%o tog livet av sig.,%o kendini öldürdü.,%o вби@[adj_1_ua] себе. +%o was killed by the power of voodoo.,OB_VOODOO,,,,%o byl@[ao_cs] zabit@[ao_cs] sílou voodoo.,%o blev dræbt af voodooens magt.,%o wurde durch Voodoo getötet.,@[art_gr] %o πέθανε απο τη δύναμη του βουντου,%o estis mortigita de la povo de voduo.,A %o l@[ao_esp] ha matado el poder del vudú.,A %o l@[ao_esp] mató el poder del vudú.,%o kuoli voodoon voimasta.,%o a succombé au pouvoir du Vaudou.,%o meghalt a voodoo erejének köszönhetően.,%o è stato ucciso dalla potenza del voodoo.,%o はブードゥー人形で殺された。,%o 은(는) 부두 마법의 저주를 받았다.,%o werd gedood door de kracht van voodoo.,%o ble drept av voodooens kraft.,%o umarł@[ao_pl] od mocy voodoo.,%o morreu pelo poder do voodoo.,,%o a fost omorât prin puterea voodoo.,Игрок %o убит силой Вуду.,%o је убијен@[adj_1_sr] од стране моћи Voodoo-а.,%o dödades av voodoo-kraften.,%o voodoo'nun gücü tarafından öldürüldü.,%o вбито силою вуду. +%o was telefragged by %k.,OB_MPTELEFRAG,,,,%o byl@[ao_cs] telefraggnut %kem.,%o blev telefragged af %k.,%o stand %k im Wege.,@[art_gr] %o κοματιάστηκε μέσω τηλεμεταφοράς απο τον/την %k,%o estis teleportumita de %k.,A %o l@[ao_esp] ha telefragmentado %k.,A %o l@[ao_esp] telefragmentó %k.,%k telefräggäsi %o paran.,%o a été téléfragué@[e_fr] par %k.,%o telefrag-et kapott %k által.,%o è stato telefraggato da %k.,%o は %k にテレフラグされた。,%o 은(는) %k 에 의해 텔레프랙을 당했다.,%o werd getelefragged door %k.,%o ble telefragget av %k.,%o został@[ao_pl] ztelefragowan@[adj_pl] przez %k.,%o foi telefragad@[ao_ptb] por %k.,,%o a fost omorât prin teleportare de către %k.,Игрок %o стал жертвой телепортации игрока %k.,%o је телефрагован@[adj_1_sr] од стране %k.,%o blev telefragged av %k.,"%o, %k tarafından telefrag edildi.",%o телефрагнуто %k. +%o was telefragged.,OB_MONTELEFRAG,,,,%o byl@[ao_cs] telefraggnut@[ao_cs].,%o blev telefragged.,%o stand jemandem im Wege.,@[art_gr] %o κοματιάστηκε μέσω τηλεμεταφοράς,%o estis teleportumita.,A %o l@[ao_esp] han telefragmentado.,A %o l@[ao_esp] telefragmentaron.,%o telefrägättiin.,%o a été téléfragué@[e_fr].,%o telefraggelve lett.,%o si è fatto telefraggare.,%o はテレフラグされた。,%o 은(는) 텔레프랙을 당했다.,%o werd getelefragged.,%o ble telefragget.,%o został@[ao_pl] ztelefragowan@[adj_pl].,%o foi telefragad@[ao_ptb] por um monstro.,,%o a fost omorât prin teleportare.,Игрок %o стал жертвой телепортации.,%o је телефрагован@[adj_1_sr].,%o blev telefragged.,%o telefragged edildi.,%o вбито телепортом. %o died.,OB_DEFAULT,,,,"%o zemřel@[ao_cs]. -",%o døde.,%o ist gestorben.,@[art_gr] %o πέθανε,%o mortis.,%o ha muerto.,%o acaba de morir.,%o kuoli.,%o est mort@[e_fr].,%o meghalt.,%o è morto.,%o は死亡した。,%o 은(는) 죽었다.,%o ging dood.,%o døde.,%o umarł@[ao_pl].,%o morreu.,,%o a murit.,Игрок %o погиб.,%o је умр@[ao_1_sr].,%o öldü. -%o was killed by %k.,OB_MPDEFAULT,,,,%o byl@[ao_cs] zabit@[ao_cs] hráčem %k.,%o blev dræbt af %k.,%o wurde von %k getötet.,@[art_gr] %o στοτώθηκε απο τον/την %k,%o estis mortigita de %k.,%o ha sido asesinad@[ao_esp] por %k.,%o fue asesinad@[ao_esp] por %k.,%k tappoi %o paran.,%o a été tué@[e_fr] par %k.,%k megölte %o-t.,%o è stato ucciso da %k,%o は %k によって殺された。,%o 은(는) %k 에 의해 죽임을 당했다.,%o werd gedood door %k.,%o ble drept av %k.,%o został@[ao_pl] zabit@[adj_pl] przez %k.,%o foi mort@[ao_ptb] por %k.,,%o a fost omorât de către %k.,Игрока %o убил игрок %k.,Играча %o је уби@[ao_1_sr] %k.,"%o, %k tarafından öldürüldü." -%k mows down a teammate.,OB_FRIENDLY1,,,,%o rozsekal@[ao_cs] spoluhráče.,%k mejer en holdkammerat ned.,%o wurde von einem Teamkameraden niedergestreckt.,Ο/Η %k σκότωσε έναν σύμαχο,%k buĉas teamanon.,%k acribilla a un compañero.,,%k niitti joukkuetoverin.,%k élimine un de ses équipiers.,%k lekaszabolta a csapattársát.,%k falcia via un compagno.,%k は仲間を無慈悲に殺した。,%o 은(는) 자신의 팀원을 죽였다.,%k maait een teamgenoot neer.,%k meier ned en lagkamerat.,%k kosi kompana.,%k matou um colega de equipe.,%k matou um companheiro de equipa.,%k face pulbere pe un coechipier.,Игрок %k сбивает союзника.,%k је обори@[ao_1_sr] саиграча.,%k bir takım arkadaşını biçti. -%k seems to need glasses.,OB_FRIENDLY2,English was changed to remove problematic pronoun referencing the killer,,,%k nejspíš potřebuje brýle.,%k har tilsyneladende brug for briller.,%k sollte eine Brille benutzen.,Ο/Η %k φαίνεται να χρειάζετε γυαλία,%o ŝajnas bezoni okulvitrojn.,%k parece necesitar gafas.,%k parece necesitar lentes.,%k näyttää tarvitsevan laseja.,%k vérifie ses lunettes.,%k-nak szemüvegre van szüksége.,%k sembra che abbia bisogno di occhiali.,%k には眼鏡が必要なようだ。,%o 은(는) 자신의 안경을 확인했다.,%k lijkt een bril nodig te hebben.,%k ser ut til å trenge briller.,%k wydaje się potrzebować okularów.,%k parece que precisa de óculos.,,%k pare să aibă nevoie de ochelari.,Игроку %k следует носить свои очки.,Играчу %k би приличиле наочаре.,%k net göremiyor -%k gets a frag for the other team.,OB_FRIENDLY3,,,,%k dostal@[ao_cs] frag pro další tým.,%k får en fragment til det andet hold.,%k macht für das andere Team einen Punkt.,Ο/Η %k πάιρνει έναν κοματιασμό για την άλλη ομάδα.,%k gajnas ludmurdon por la alia teamo.,%k marca una baja para el otro equipo.,,%k teki frägin vieraalle joukkueelle.,%k marque un point pour l'autre équipe.,%k szerez egy frag-et a másik csapatnak.,%k regala un frag all'altro team.,%k は敵チームに得点を入れた。,%o 은(는) 의도치 않게 상대방 팀을 도왔다.,%k doet een frag voor het andere team.,%k får en frag for det andre laget.,%k zdobywa fraga dla przeciwnej drużyny.,%k dá um frag para o outro time.,%k dá um frag para a outra equipa.,%k face o victimă pentru echipa adversă.,Игрок %k преподнёс другой команде фраг.,%k осваја фраг за други тим.,%k diğer takım için bir parça aldı. -%k loses another friend.,OB_FRIENDLY4,,,,%k ztratil@[ao_cs] dalšího přítele.,%k mister endnu en ven.,%k hat wieder einen Freund verloren.,Ο/Η %k χάνει ακόμα έναν αλλο φίλο,%k perdis alian amikon.,%k pierde otro amigo.,,%k menetti jälleen ystävän.,%k a perdu un autre ami.,%k elveszít egy másik barátot.,%k perde un altro amico.,%k はまた友達を失った。,%o 은(는) 친구를 원치 않았다.,%k verliest nog een vriend.,%k mister enda en venn.,%k tracil kolejnego przyjaciela.,%k perde mais um amigo.,,%k mai pierde un prieten.,Игрок %k потерял ещё одного друга.,%k је изгуби@[ao_1_sr] још једног пријатеља.,%k başka bir arkadaşını kaybetti. -,,Pickup,,,,,,,,,,,,,,,,,,,,,,,, -Picked up the armor.,GOTARMOR,,,Picked up the armour.,Sebráno brnění.,Hentede rustningen.,Panzer genommen.,Πήρες την πανοπλία.,Vi trovis armaĵon.,Encuentras una armadura.,Hallaste una armadura.,Poimit panssarin.,Armure récupérée.,Felvettél egy páncélt.,Raccolto un'armatura.,アーマーを身に着けた。,방호구를 얻었다.,Je hebt het harnas opgepakt.,Plukket opp rustningen.,Zebrano zbroję.,Pegou uma armadura.,Apanhaste uma armadura.,Ai ridicat o armură.,Получена броня.,Покупили сте панцир.,Zırhı aldım. -Picked up the MegaArmor!,GOTMEGA,,,Picked up the MegaArmour!,Sebráno MegaBrnění!,Hentede Mega-rustningen!,MegaPanzer genommen!,Πήρες την μέγα πανοπλία!,Vi trovis superan armaĵon!,¡Encuentras una Megaarmadura!,¡Hallaste una Megaarmadura!,Poimit megapanssarin!,Méga-Armure récupérée!,Felvettél egy MegaPáncélt!,Raccolto una MegaArmatura!,メガアーマーを身に着けた!,메가아머를 얻었다!,Je hebt het megaharnas opgepakt!,Plukket opp mega rustningen!,Zebrano megazbroję!,Pegou uma Mega-armadura!,Apanhaste uma MegaArmadura.,Ai ridicat o MegaArmură!,Получена мегаброня!,Покупили сте мегапанцир!,MegaZırhı aldı! -Picked up a health bonus.,GOTHTHBONUS,,,,Sebráno bonusové zdraví.,Hentede en sundhedsbonus.,Gesundheitsbonus genommen.,Πήρες ένα bonus υγείας.,Vi trovis aldonan sanon.,Encuentras salud extra.,Hallaste salud extra.,Poimit terveyslisän.,Bonus de Santé récupéré.,Felvettél egy életbónuszt.,Raccolto un bonus di salute.,ヘルスボーナスを拾った。,체력 보너스를 얻었다.,Je hebt een gezondheidsbonus opgepakt.,Plukket opp en helsebonus.,Zebrano bonus do zdrowia.,Pegou um bônus de saúde.,Apanhaste um bônus de vida.,Ai ridicat un bonus de sănătate.,Получен бонус к здоровью.,Покупили сте бонус здравља.,Bir sağlık bonusu aldı. -Picked up an armor bonus.,GOTARMBONUS,,,Picked up an armour bonus.,Sebráno bonusové brnění.,Hentede en rustningsbonus.,Panzerbonus genommen.,Πήρες ένα bonus πανο.πλίας.,Vi trovis aldonan kirason.,Encuentras blindaje extra.,Hallaste blindaje extra.,Poimit panssarilisän.,Bonus d'Armure récupéré.,Felvettél egy páncélbónuszt.,Raccolto un bonus d'armatura.,アーマーボーナスを拾った。,보호 보너스를 얻었다.,Je hebt een harnasbonus opgepakt.,Plukket opp en rustningsbonus.,Zebrano bonus do zbroi.,Pegou um bônus de armadura.,Apanhaste um bônus de armadura.,Ai ridicat un bonus de armură.,Получен бонус к броне.,Покупили сте бонус панцира.,Bir zırh bonusu aldı. -Picked up a stimpack.,GOTSTIM,,,,Sebrán stimulant.,Hentede en stimpack.,Stimpack genommen.,Πήρες ένα μικρό πακέτο υγείας.,Vi trovis stimulilo-pakon.,Encuentras un estimulante.,Hallaste un estimulante.,Poimit piristeruiskeen.,Stimpack récupéré.,Felvettél egy szurit.,Raccolto uno stimpack.,スティムパックを拾った。,스팀팩을 사용했다.,Je hebt een opwekpakket opgepakt.,Plukket opp en stimpack.,Zebrano małą apteczkę.,Pegou um estimulante.,Apanhaste um kit de primeiros socorros.,Ai ridicat un kit de prim-ajutor mic.,Получен стимулятор.,Покупили сте стимпак.,Bir uyarıcı aldı. -Picked up a medikit that you REALLY need!,GOTMEDINEED,,,,"Sebrána lékárnička, kterou jsi FAKT potřeboval@[ao_cs].","Hentede en medikit, som du VIRKELIG har brug for!","Medikit genommen, das du WIRKLICH brauchst!",Πήρες πρώτες βοήθειες που χρειαζόσουνα ΠΆΡΑ ΠΟΛΥ!,"Vi trovis sukurkeston, kiun vi VERE bezonas!",¡Encuentras un botiquín que REALMENTE necesitabas!,¡Hallaste un botiquín que REALMENTE necesitabas!,"Poimit lääkintälaukun, jota TODELLA tarvitsit!","Médikit récupéré, et vous en aviez vraiment besoin!",Felvettél egy életcsomagot amire NAGYON szükséged volt már!,Hai raccolto un kit medico di cui avevi PROPRIO bisogno!,本当に必要なメディキットを手に入れた!,메디킷을 필요한 순간에 사용했다!,"Je hebt een verbandsdoos, die je ECHT nodig had, opgepakt!",Plukket opp en medikit som du virkelig trenger!,"Zebrano apteczkę, w OSTATNIEJ chwili!","Pegou um kit médico +",%o døde.,%o ist gestorben.,@[art_gr] %o πέθανε,%o mortis.,%o ha muerto.,%o murió.,%o kuoli.,%o est mort@[e_fr].,%o meghalt.,%o è morto.,%o は死亡した。,%o 은(는) 죽었다.,%o ging dood.,%o døde.,%o umarł@[ao_pl].,%o morreu.,,%o a murit.,Игрок %o погиб.,%o је умр@[ao_1_sr].,%o dog.,%o öldü.,%o помер@[adj_3_ua]. +%o was killed by %k.,OB_MPDEFAULT,,,,%o byl@[ao_cs] zabit@[ao_cs] hráčem %k.,%o blev dræbt af %k.,%o wurde von %k getötet.,@[art_gr] %o στοτώθηκε απο τον/την %k,%o estis mortigita de %k.,A %o l@[ao_esp] ha matado %k.,A %o l@[ao_esp] mató %k.,%k tappoi %o paran.,%o a été tué@[e_fr] par %k.,%k megölte %o-t.,%o è stato ucciso da %k,%o は %k によって殺された。,%o 은(는) %k 에 의해 죽임을 당했다.,%o werd gedood door %k.,%o ble drept av %k.,%o został@[ao_pl] zabit@[adj_pl] przez %k.,%o foi mort@[ao_ptb] por %k.,,%o a fost omorât de către %k.,Игрока %o убил игрок %k.,Играча %o је уби@[ao_1_sr] %k.,%o dödades av %k.,"%o, %k tarafından öldürüldü.",%o вбито гравцем %k. +%k mows down a teammate.,OB_FRIENDLY1,,,,%o rozsekal@[ao_cs] spoluhráče.,%k mejer en holdkammerat ned.,%o wurde von einem Teamkameraden niedergestreckt.,Ο/Η %k σκότωσε έναν σύμαχο,%k buĉas teamanon.,%k ha acribillado a un compañero.,%k acribilló a un compañero.,%k niitti joukkuetoverin.,%k élimine un de ses équipiers.,%k lekaszabolta a csapattársát.,%k falcia via un compagno.,%k は仲間を無慈悲に殺した。,%o 은(는) 자신의 팀원을 죽였다.,%k maait een teamgenoot neer.,%k meier ned en lagkamerat.,%k kosi kompana.,%k matou um colega de equipe.,%k matou um companheiro de equipa.,%k face pulbere pe un coechipier.,Игрок %k сбивает союзника.,%k је обори@[ao_1_sr] саиграча.,%k mejar ner en lagkamrat.,%k bir takım arkadaşını biçti.,%k скоси@[adj_1_ua] соратника. +%k seems to need glasses.,OB_FRIENDLY2,English was changed to remove problematic pronoun referencing the killer,,,%k nejspíš potřebuje brýle.,%k har tilsyneladende brug for briller.,%k sollte eine Brille benutzen.,Ο/Η %k φαίνεται να χρειάζετε γυαλία,%o ŝajnas bezoni okulvitrojn.,%k parece necesitar gafas.,%k parece necesitar lentes.,%k näyttää tarvitsevan laseja.,%k vérifie ses lunettes.,%k-nak szemüvegre van szüksége.,%k sembra che abbia bisogno di occhiali.,%k には眼鏡が必要なようだ。,%o 은(는) 자신의 안경을 확인했다.,%k lijkt een bril nodig te hebben.,%k ser ut til å trenge briller.,%k wydaje się potrzebować okularów.,%k parece que precisa de óculos.,,%k pare să aibă nevoie de ochelari.,Игроку %k следует носить свои очки.,Играчу %k би приличиле наочаре.,%k verkar behöva glasögon.,%k net göremiyor,"Схоже, що %k потрібні окуляри." +%k gets a frag for the other team.,OB_FRIENDLY3,,,,%k dostal@[ao_cs] frag pro další tým.,%k får en fragment til det andet hold.,%k macht für das andere Team einen Punkt.,Ο/Η %k πάιρνει έναν κοματιασμό για την άλλη ομάδα.,%k gajnas ludmurdon por la alia teamo.,%k ha marcado una baja para el otro equipo.,%k marcó una baja para el otro equipo.,%k teki frägin vieraalle joukkueelle.,%k marque un point pour l'autre équipe.,%k szerez egy frag-et a másik csapatnak.,%k regala un frag all'altro team.,%k は敵チームに得点を入れた。,%o 은(는) 의도치 않게 상대방 팀을 도왔다.,%k doet een frag voor het andere team.,%k får en frag for det andre laget.,%k zdobywa fraga dla przeciwnej drużyny.,%k dá um frag para o outro time.,%k dá um frag para a outra equipa.,%k face o victimă pentru echipa adversă.,Игрок %k преподнёс другой команде фраг.,%k осваја фраг за други тим.,%k får ett frag till det andra laget.,%k diğer takım için bir parça aldı.,%k відда@[adj_1_ua] фраг іншій команді. +%k loses another friend.,OB_FRIENDLY4,,,,%k ztratil@[ao_cs] dalšího přítele.,%k mister endnu en ven.,%k hat wieder einen Freund verloren.,Ο/Η %k χάνει ακόμα έναν αλλο φίλο,%k perdis alian amikon.,%k ha perdido a otro amigo.,%k perdió a otro amigo.,%k menetti jälleen ystävän.,%k a perdu un autre ami.,%k elveszít egy másik barátot.,%k perde un altro amico.,%k はまた友達を失った。,%o 은(는) 친구를 원치 않았다.,%k verliest nog een vriend.,%k mister enda en venn.,%k tracil kolejnego przyjaciela.,%k perde mais um amigo.,,%k mai pierde un prieten.,Игрок %k потерял ещё одного друга.,%k је изгуби@[ao_1_sr] још једног пријатеља.,%k förlorar ännu en vän.,%k başka bir arkadaşını kaybetti.,%k втрати@[adj_1_ua] ще одного друга. +,,Pickup,,,,,,,,,,,,,,,,,,,,,,,,,, +Picked up the armor.,GOTARMOR,,,Picked up the armour.,Sebráno brnění.,Hentede rustningen.,Panzer genommen.,Πήρες την πανοπλία.,Vi trovis armaĵon.,Encuentras una armadura.,,Poimit panssarin.,Armure récupérée.,Felvettél egy páncélt.,Raccolto un'armatura.,アーマーを身に着けた。,방호구를 얻었다.,Je hebt het harnas opgepakt.,Plukket opp rustningen.,Zebrano zbroję.,Pegou uma armadura.,Apanhaste uma armadura.,Ai ridicat o armură.,Получена броня.,Покупили сте панцир.,Plockade upp rustningen.,Zırhı aldım.,Взято броню. +Picked up the MegaArmor!,GOTMEGA,,,Picked up the MegaArmour!,Sebráno MegaBrnění!,Hentede Mega-rustningen!,MegaPanzer genommen!,Πήρες την μέγα πανοπλία!,Vi trovis plejan armaĵon!,¡Encuentras una Megaarmadura!,,Poimit megapanssarin!,Méga-Armure récupérée!,Felvettél egy MegaPáncélt!,Raccolto una MegaArmatura!,メガアーマーを身に着けた!,메가아머를 얻었다!,Je hebt het megaharnas opgepakt!,Plukket opp mega rustningen!,Zebrano megazbroję!,Pegou uma Mega-armadura!,Apanhaste uma MegaArmadura.,Ai ridicat o MegaArmură!,Получена мегаброня!,Покупили сте мегапанцир!,Plockade upp mega rustningen!,MegaZırhı aldı!,Взято мегаброню! +Picked up a health bonus.,GOTHTHBONUS,,,,Sebráno bonusové zdraví.,Hentede en sundhedsbonus.,Gesundheitsbonus genommen.,Πήρες ένα bonus υγείας.,Vi trovis aldonan sanon.,Encuentras salud extra.,,Poimit terveyslisän.,Bonus de Santé récupéré.,Felvettél egy életbónuszt.,Raccolto un bonus di salute.,ヘルスボーナスを拾った。,체력 보너스를 얻었다.,Je hebt een gezondheidsbonus opgepakt.,Plukket opp en helsebonus.,Zebrano bonus do zdrowia.,Pegou um bônus de saúde.,Apanhaste um bônus de vida.,Ai ridicat un bonus de sănătate.,Получен бонус к здоровью.,Покупили сте бонус здравља.,Plockade upp en hälsobonus.,Bir sağlık bonusu aldı.,Взято бонус здоров'я. +Picked up an armor bonus.,GOTARMBONUS,,,Picked up an armour bonus.,Sebráno bonusové brnění.,Hentede en rustningsbonus.,Panzerbonus genommen.,Πήρες ένα bonus πανο.πλίας.,Vi trovis aldonan kirason.,Encuentras blindaje extra.,,Poimit panssarilisän.,Bonus d'Armure récupéré.,Felvettél egy páncélbónuszt.,Raccolto un bonus d'armatura.,アーマーボーナスを拾った。,보호 보너스를 얻었다.,Je hebt een harnasbonus opgepakt.,Plukket opp en rustningsbonus.,Zebrano bonus do zbroi.,Pegou um bônus de armadura.,Apanhaste um bônus de armadura.,Ai ridicat un bonus de armură.,Получен бонус к броне.,Покупили сте бонус панцира.,Plockade upp en rustningsbonus.,Bir zırh bonusu aldı.,Взято бонус броні. +Picked up a stimpack.,GOTSTIM,,,,Sebrán stimulant.,Hentede en stimpack.,Stimpack genommen.,Πήρες ένα μικρό πακέτο υγείας.,Vi trovis stimulilo-pakon.,Encuentras un estimulante.,,Poimit piristeruiskeen.,Stimpack récupéré.,Felvettél egy szurit.,Raccolto uno stimpack.,スティムパックを拾った。,스팀팩을 사용했다.,Je hebt een opwekpakket opgepakt.,Plukket opp en stimpack.,Zebrano małą apteczkę.,Pegou um estimulante.,Apanhaste um kit de primeiros socorros.,Ai ridicat un kit de prim-ajutor mic.,Получен стимулятор.,Покупили сте стимпак.,Plockade upp en stimpack.,Bir uyarıcı aldı.,Взято стимулятор. +Picked up a medikit that you REALLY need!,GOTMEDINEED,,,,"Sebrána lékárnička, kterou jsi FAKT potřeboval@[ao_cs].","Hentede en medikit, som du VIRKELIG har brug for!","Medikit genommen, das du WIRKLICH brauchst!",Πήρες πρώτες βοήθειες που χρειαζόσουνα ΠΆΡΑ ΠΟΛΥ!,"Vi trovis sukurkeston, kiun vi VERE bezonas!",¡Encuentras un botiquín que REALMENTE necesitabas!,,"Poimit lääkintälaukun, jota TODELLA tarvitsit!","Médikit récupéré, et vous en aviez vraiment besoin!",Felvettél egy életcsomagot amire NAGYON szükséged volt már!,Hai raccolto un kit medico di cui avevi PROPRIO bisogno!,本当に必要なメディキットを手に入れた!,메디킷을 필요한 순간에 사용했다!,"Je hebt een verbandsdoos, die je ECHT nodig had, opgepakt!",Plukket opp en medikit som du virkelig trenger!,"Zebrano apteczkę, w OSTATNIEJ chwili!","Pegou um kit médico que você REALMENTE precisava!","Apanhaste um kit médico que estavas MESMO a precisar!","Ai ridicat un kit de prim-ajutor de care CHIAR aveai -nevoie!",Получена КРАЙНЕ необходимая аптечка!,Покупили сте медикит који вам је СТВАРНО потребан!,GERÇEKTEN ihtiyacın olan bir medikit aldı! -Picked up a medikit.,GOTMEDIKIT,,,,Sebrána lékárnička.,Samlede en medikit op.,Medikit genommen.,Πήρες πρώτες βοήθειες.,Vi trovis sukurkeston.,Encuentras un botiquín.,Hallaste un botiquín.,Poimit lääkintälaukun.,Médikit récupéré.,Felvettél egy életcsomagot.,Raccolto un kit medico.,メディキットを拾った。,메디킷을 사용했다.,Je hebt een verbandsdoos opgepakt.,Plukket opp en medikit.,Zebrano apteczkę.,Pegou um kit médico.,Apanhaste um kit médico.,Ai ridicat un kit de prim-ajutor.,Получена аптечка.,Покупили сте медикит.,Bir medikit aldı. -Supercharge!,GOTSUPER,,,,Superzdraví!,,Super-Ladung!,Υπερφόρτοση!,Superŝargo!,¡Supercarga!,,Supervaraus!,,Szupertöltés!,Sfera dell'Anima!,スーパーチャージ!,슈퍼차지!,,,Supernaładowanie!,Supercarga!,,Superîncărcătură!,Сверхзаряд!,Супернабој!,Süper şarj! -Picked up a blue keycard.,GOTBLUECARD,,,,Sebrána modrá karta.,Samlede et blåt nøglekort op.,Blaue Schlüsselkarte genommen.,Πήρες ένα μπλε κλειδί.,Vi trovis bluan ŝlosilkarton.,Encuentras una tarjeta de acceso azul.,Hallaste una tarjeta de acceso azul.,Poimit sinisen avainkortin.,Carte d'accès BLEUE récupérée.,Felvettél egy kék kulcskártyát.,Raccolta una card d'accesso blu.,ブルー キーカードを手に入れた。,청색 키카드를 얻었다.,Je hebt een blauwe sleutelkaart opgepakt.,Plukket opp et blått nøkkelkort.,Zebrano niebieską kartę klucz.,Pegou um cartão de acesso azul.,Apanhaste um cartão de acesso azul.,Ai ridicat un card cheie albastru.,Получена синяя ключ-карта.,Покупили сте плаву кључну карту.,Mavi bir anahtar kartı aldı. -Picked up a yellow keycard.,GOTYELWCARD,,,,Sebrána žlutá karta.,Samlede et gult nøglekort op.,Gelbe Schlüsselkarte genommen.,Πήρες ένα κύτρινο κλειδί.,Vi trovis flavan ŝlosilkarton.,Encuentras una tarjeta de acceso amarilla.,Hallaste una tarjeta de acceso amarilla.,Poimit keltaisen avainkortin.,Carte d'accès JAUNE récupérée.,Felvettél egy sárga kulcskártyát.,Raccolta una card d'accesso gialla.,イエローキーカードを手に入れた。,황색 키카드를 얻었다.,Je hebt een gele sleutelkaart opgepakt.,Plukket opp et gult nøkkelkort.,Zebrano żółtą kartę klucz.,Pegou um cartão de acesso amarelo.,Apanhaste um cartão de acesso amarelo.,Ai ridicat un card cheie galben.,Получена жёлтая ключ-карта,Покупили сте жуту кључну карту.,Sarı bir anahtar kartı aldı. -Picked up a red keycard.,GOTREDCARD,,,,Sebrána červená karta.,Samlede et rødt nøglekort op.,Rote Schlüsselkarte genommen.,Πήρες ένα κόκινο κλειδί.,Vi trovis ruĝan ŝlosilkarton.,Encuentras una tarjeta de acceso roja.,Hallaste una tarjeta de acceso roja.,Poimit punaisen avainkortin.,Carte d'accès ROUGE récupérée.,Felvettél egy piros kulcskártyát.,Raccolta una card d'accesso rossa.,レッド キーカードを手に入れた。,적색 키카드를 얻었다.,Je hebt een rode sleutelkaart opgepakt.,Plukket opp et rødt nøkkelkort.,Zebrano czerwoną kartę klucz.,Pegou um cartão de acesso vermelho.,Apanhaste um cartão de acesso vermelho.,Ai ridicat un card cheie roșu.,Получена красная ключ-карта.,Покупили сте црвену кључну карту.,Kırmızı bir anahtar kartı aldı. -Picked up a blue skull key.,GOTBLUESKUL,,,,Sebrána modrá lebka.,Samlede en blå kranie-nøgle op.,Blauen Schädel-Schlüssel genommen.,Πήρες ένα μπλε κρανίο.,Vi trovis bluan kraniŝlosilon.,Encuentras una llave de calavera azul.,Hallaste una llave de calavera azul.,Poimit sinisen kalloavaimen.,Clef Crâne BLEUE récupérée.,Felvettél egy kék koponyakulcsot.,Raccolta una chiave-teschio blu.,ブルー スカルキーを手に入れた。,청색 해골열쇠를 얻었다.,Je hebt een blauwe schedelsleutel opgepakt.,Plukket opp en blå hodeskallenøkkel.,Zebrano niebieską czaszkę.,Pegou uma chave-crânio azul.,Apanhaste uma chave crânio azul.,Ai ridicat o cheie craniu albastră.,Получен синий череп-ключ.,Покупили сте плави кључ лобање.,Mavi bir kafatası anahtarı aldı. -Picked up a yellow skull key.,GOTYELWSKUL,,,,Sebrána žlutá lebka.,Samlede en gul kranie-nøgle op.,Geben Schädel-Schlüssel genommen.,Πήρες ένα κύτρινο κρανίο.,Vi trovis flavan kraniŝlosilon.,Encuentras una llave de calavera amarilla,Hallaste una llave de calavera amarilla,Poimit keltaisen kalloavaimen.,Clef Crâne JAUNE récupérée.,Felvettél egy sárga koponyakulcsot.,Raccolta una chiave-teschio gialla.,イエロースカルキーを手に入れた。,황색 해골열쇠를 얻었다.,Je hebt een gele schedelsleutel opgepakt.,Plukket opp en gul hodeskallenøkkel.,Zebrano żółtą czaszkę.,Pegou uma chave-crânio amarela.,Apanhaste uma chave crânio amarela.,Ai ridicat o cheie craniu galbenă.,Получен жёлтый череп-ключ.,Покупили сте жути кључ лобање.,Sarı bir kafatası anahtarı aldı. -Picked up a red skull key.,GOTREDSKUL,,,,Sebrána červená lebka.,Samlede en rød kranie-nøgle op.,Roten Schädel-Schlüssel genommen.,Πήρες ένα κοκινο κρανίο.,Vi trovis ruĝan kraniŝlosilon.,Encuentras una llave de calavera roja.,Hallaste una llave de calavera roja.,Poimit punaisen kalloavaimen.,Clef Crâne ROUGE récupérée.,Felvettél egy piros koponyakulcsot.,Raccolta una chiave-teschio rossa.,レッド スカルキーを手に入れた。,적색 해골열쇠를 얻었다.,Je hebt een rode schedelsleutel opgepakt.,Plukket opp en rød hodeskallenøkkel.,Zebrano czerwoną czaszkę.,Pegou uma chave-crânio vermelha.,Apanhaste uma chave crânio vermelha.,Ai ridicat o cheie craniu roșie.,Получен красный череп-ключ.,Покупили сте црвени кључ лобање.,Kırmızı kafatası anahtarı aldı. -Invulnerability!,GOTINVUL,,,,Nezranitelnost!,Udsårbarhed!,Unverwundbarkeit!,Αθανασία!,Nevundebleco!,¡Invulnerabilidad!,,Haavoittumattomuus!,Invulnérabilité!,Sérthetetlenség!,Invulnerabilità!,不死身だ!,무적!,Onkwetsbaarheid!,Usårbarhet!,Niezniszczalność!,Invulnerabilidade!,,Invincibilitate!,Неуязвимость!,Нерањивост!,Dokunulmazlık! -Berserk!,GOTBERSERK,,,,,,,Μανία!,Furiozigaĵo!,¡Berserker!,,Raivo!,,Dühödt mód!,,バーサーク!,광전사!,,,Szał!,Frenesi!,,Forță amplificată!,Берсерк!,Берсерк!,Berserk! -Partial Invisibility,GOTINVIS,,,,Částečná neviditelnost,Delvis usynlighed,Teilweise Unsichtbarkeit,Ημη-αoρατότητα,Parta nevidebleco,Invisibilidad parcial,,Osittainen näkymättömyys,Invisibilité Partielle,Részleges láthatatlanság,Invisibilità parziale,半透明化スフィア,일시적 투명 효과!,Gedeeltelijke onzichtbaarheid,Delvis usynlighet,Częściowa niewidzialność,Invisibilidade parcial,,Invizibilitate parțială,Частичная невидимость.,Делимична невидљивост,Kısmi Görünmezlik -Radiation Shielding Suit,GOTSUIT,,,,Ochranný oblek proti radioaktivitě,Stråleafskærmningsdragt,Strahlenschutzanzug.,Προστατευτηκή Στολή,Radiado-ŝirma vesto,Traje antiradiación,,Säteilysuojapuku,Combinaison Hazmat,Védőruha,Tuta anti-radiazioni,放射線防護服 ,방사능 보호복,Stralingsbeschermingspak,Strålingsskjermingsdrakt,Kombinezon przeciwradiacyjny,Traje antirradiação,Fato anti-radiação,Costum de protecție împotriva radiaților,Костюм радиационной защиты.,Одело против радијације,Radyasyon Koruyucu Giysi -Computer Area Map,GOTMAP,,,,Počítačová mapa,Computerkort.,Computerkarte.,Τοπικός Χάρτης,Komputila mapo de areo,Mapa ordenador del área,Mapa computadora del área,Alueen tietokonekartta,Carte Informatique,Térkép,Mappa Completata,コンピューターエリアマップ,구역 지도 컴퓨터,Computerkaart,Datakart,Komputerowa mapa obszaru,Mapa completo,,Hartă completă,Компьютерная карта уровня.,Компјутерска мапа нивоа,Bilgisayar Alanı Haritası +nevoie!",Получена КРАЙНЕ необходимая аптечка!,Покупили сте медикит који вам је СТВАРНО потребан!,Plockade upp en medikit som du VÄLDIGT behöver!,GERÇEKTEN ihtiyacın olan bir medikit aldı!,Взято КРАЙНЄ необхідну аптечку! +Picked up a medikit.,GOTMEDIKIT,,,,Sebrána lékárnička.,Samlede en medikit op.,Medikit genommen.,Πήρες πρώτες βοήθειες.,Vi trovis sukurkeston.,Encuentras un botiquín.,,Poimit lääkintälaukun.,Médikit récupéré.,Felvettél egy életcsomagot.,Raccolto un kit medico.,メディキットを拾った。,메디킷을 사용했다.,Je hebt een verbandsdoos opgepakt.,Plukket opp en medikit.,Zebrano apteczkę.,Pegou um kit médico.,Apanhaste um kit médico.,Ai ridicat un kit de prim-ajutor.,Получена аптечка.,Покупили сте медикит.,Plockade upp en medikit.,Bir medikit aldı.,Взято аптечку. +Supercharge!,GOTSUPER,,,,Superzdraví!,,Super-Ladung!,Υπερφόρτοση!,Superŝargo!,¡Supercarga!,,Supervaraus!,,Szupertöltés!,Sfera dell'Anima!,スーパーチャージ!,슈퍼차지!,,,Supernaładowanie!,Supercarga!,,Superîncărcătură!,Сверхзаряд!,Супернабој!,Superladdning!,Süper şarj!,Суперзаряд! +Picked up a blue keycard.,GOTBLUECARD,,,,Sebrána modrá karta.,Samlede et blåt nøglekort op.,Blaue Schlüsselkarte genommen.,Πήρες ένα μπλε κλειδί.,Vi trovis bluan ŝlosilkarton.,Encuentras una tarjeta de acceso azul.,,Poimit sinisen avainkortin.,Carte d'accès BLEUE récupérée.,Felvettél egy kék kulcskártyát.,Raccolta una card d'accesso blu.,ブルー キーカードを手に入れた。,청색 키카드를 얻었다.,Je hebt een blauwe sleutelkaart opgepakt.,Plukket opp et blått nøkkelkort.,Zebrano niebieską kartę klucz.,Pegou um cartão de acesso azul.,Apanhaste um cartão de acesso azul.,Ai ridicat un card cheie albastru.,Получена синяя ключ-карта.,Покупили сте плаву кључну карту.,Plockade upp ett blått nyckelkort.,Mavi bir anahtar kartı aldı.,Взято синю ключ-карту. +Picked up a yellow keycard.,GOTYELWCARD,,,,Sebrána žlutá karta.,Samlede et gult nøglekort op.,Gelbe Schlüsselkarte genommen.,Πήρες ένα κύτρινο κλειδί.,Vi trovis flavan ŝlosilkarton.,Encuentras una tarjeta de acceso amarilla.,,Poimit keltaisen avainkortin.,Carte d'accès JAUNE récupérée.,Felvettél egy sárga kulcskártyát.,Raccolta una card d'accesso gialla.,イエローキーカードを手に入れた。,황색 키카드를 얻었다.,Je hebt een gele sleutelkaart opgepakt.,Plukket opp et gult nøkkelkort.,Zebrano żółtą kartę klucz.,Pegou um cartão de acesso amarelo.,Apanhaste um cartão de acesso amarelo.,Ai ridicat un card cheie galben.,Получена жёлтая ключ-карта.,Покупили сте жуту кључну карту.,Plockade upp ett gult nyckelkort.,Sarı bir anahtar kartı aldı.,Взято жовту ключ-карту. +Picked up a red keycard.,GOTREDCARD,,,,Sebrána červená karta.,Samlede et rødt nøglekort op.,Rote Schlüsselkarte genommen.,Πήρες ένα κόκινο κλειδί.,Vi trovis ruĝan ŝlosilkarton.,Encuentras una tarjeta de acceso roja.,,Poimit punaisen avainkortin.,Carte d'accès ROUGE récupérée.,Felvettél egy piros kulcskártyát.,Raccolta una card d'accesso rossa.,レッド キーカードを手に入れた。,적색 키카드를 얻었다.,Je hebt een rode sleutelkaart opgepakt.,Plukket opp et rødt nøkkelkort.,Zebrano czerwoną kartę klucz.,Pegou um cartão de acesso vermelho.,Apanhaste um cartão de acesso vermelho.,Ai ridicat un card cheie roșu.,Получена красная ключ-карта.,Покупили сте црвену кључну карту.,Plockade upp ett rött nyckelkort.,Kırmızı bir anahtar kartı aldı.,Взято червону ключ-карту. +Picked up a blue skull key.,GOTBLUESKUL,,,,Sebrána modrá lebka.,Samlede en blå kranie-nøgle op.,Blauen Schädel-Schlüssel genommen.,Πήρες ένα μπλε κρανίο.,Vi trovis bluan kraniŝlosilon.,Encuentras una llave de calavera azul.,,Poimit sinisen kalloavaimen.,Clef Crâne BLEUE récupérée.,Felvettél egy kék koponyakulcsot.,Raccolta una chiave-teschio blu.,ブルー スカルキーを手に入れた。,청색 해골열쇠를 얻었다.,Je hebt een blauwe schedelsleutel opgepakt.,Plukket opp en blå hodeskallenøkkel.,Zebrano niebieską czaszkę.,Pegou uma chave-crânio azul.,Apanhaste uma chave crânio azul.,Ai ridicat o cheie craniu albastră.,Получен синий череп-ключ.,Покупили сте плави кључ лобање.,Plockade upp en blå dödskalle-nyckel.,Mavi bir kafatası anahtarı aldı.,Взято синій ключ-череп. +Picked up a yellow skull key.,GOTYELWSKUL,,,,Sebrána žlutá lebka.,Samlede en gul kranie-nøgle op.,Geben Schädel-Schlüssel genommen.,Πήρες ένα κύτρινο κρανίο.,Vi trovis flavan kraniŝlosilon.,Encuentras una llave de calavera amarilla,,Poimit keltaisen kalloavaimen.,Clef Crâne JAUNE récupérée.,Felvettél egy sárga koponyakulcsot.,Raccolta una chiave-teschio gialla.,イエロースカルキーを手に入れた。,황색 해골열쇠를 얻었다.,Je hebt een gele schedelsleutel opgepakt.,Plukket opp en gul hodeskallenøkkel.,Zebrano żółtą czaszkę.,Pegou uma chave-crânio amarela.,Apanhaste uma chave crânio amarela.,Ai ridicat o cheie craniu galbenă.,Получен жёлтый череп-ключ.,Покупили сте жути кључ лобање.,Plockade upp en gul dödskalle-nyckel.,Sarı bir kafatası anahtarı aldı.,Взято жовтий ключ-череп. +Picked up a red skull key.,GOTREDSKUL,,,,Sebrána červená lebka.,Samlede en rød kranie-nøgle op.,Roten Schädel-Schlüssel genommen.,Πήρες ένα κοκινο κρανίο.,Vi trovis ruĝan kraniŝlosilon.,Encuentras una llave de calavera roja.,,Poimit punaisen kalloavaimen.,Clef Crâne ROUGE récupérée.,Felvettél egy piros koponyakulcsot.,Raccolta una chiave-teschio rossa.,レッド スカルキーを手に入れた。,적색 해골열쇠를 얻었다.,Je hebt een rode schedelsleutel opgepakt.,Plukket opp en rød hodeskallenøkkel.,Zebrano czerwoną czaszkę.,Pegou uma chave-crânio vermelha.,Apanhaste uma chave crânio vermelha.,Ai ridicat o cheie craniu roșie.,Получен красный череп-ключ.,Покупили сте црвени кључ лобање.,Plockade upp en röd dödskalle-nyckel.,Kırmızı kafatası anahtarı aldı.,Взято червоний ключ-череп. +Invulnerability!,GOTINVUL,,,,Nezranitelnost!,Udsårbarhed!,Unverwundbarkeit!,Αθανασία!,Nevundebleco!,¡Invulnerabilidad!,,Haavoittumattomuus!,Invulnérabilité!,Sérthetetlenség!,Invulnerabilità!,不死身だ!,무적!,Onkwetsbaarheid!,Usårbarhet!,Niezniszczalność!,Invulnerabilidade!,,Invincibilitate!,Неуязвимость!,Нерањивост!,Osårbarhet!,Dokunulmazlık!,Невразливість! +Berserk!,GOTBERSERK,,,,,,,Μανία!,Furiozigaĵo!,¡Berserker!,,Raivo!,,Dühödt mód!,,バーサーク!,광전사!,,,Szał!,Frenesi!,,Forță amplificată!,Берсерк!,Берсерк!,,,Берсерк! +Partial Invisibility,GOTINVIS,,,,Částečná neviditelnost,Delvis usynlighed,Teilweise Unsichtbarkeit,Ημη-αoρατότητα,Parta nevidebleco,Invisibilidad parcial,,Osittainen näkymättömyys,Invisibilité Partielle,Részleges láthatatlanság,Invisibilità parziale,半透明化スフィア,일시적 투명 효과!,Gedeeltelijke onzichtbaarheid,Delvis usynlighet,Częściowa niewidzialność,Invisibilidade parcial,,Invizibilitate parțială,Частичная невидимость.,Делимична невидљивост,Partiell osynlighet,Kısmi Görünmezlik,Часткова невидимість +Radiation Shielding Suit,GOTSUIT,,,,Ochranný oblek proti radioaktivitě,Stråleafskærmningsdragt,Strahlenschutzanzug.,Προστατευτηκή Στολή,Radiado-ŝirma vesto,Traje antiradiación,,Säteilysuojapuku,Combinaison Hazmat,Védőruha,Tuta anti-radiazioni,放射線防護服 ,방사능 보호복,Stralingsbeschermingspak,Strålingsskjermingsdrakt,Kombinezon przeciwradiacyjny,Traje antirradiação,Fato anti-radiação,Costum de protecție împotriva radiaților,Костюм радиационной защиты.,Одело против радијације,Strålningsskyddande dräkt,Radyasyon Koruyucu Giysi,Антирадіаційний костюм +Computer Area Map,GOTMAP,,,,Počítačová mapa,Computerkort.,Computerkarte.,Τοπικός Χάρτης,Plena mapo,Mapa completo,,Alueen tietokonekartta,Carte Informatique,Térkép,Mappa Completata,コンピューターエリアマップ,구역 지도 컴퓨터,Computerkaart,Datakart,Mapa obszaru,Mapa completo,,Hartă completă,Компьютерная карта уровня.,Компјутерска мапа нивоа,Karta över datorområdet,Bilgisayar Alanı Haritası,Комп'ютерна карта району Light Amplification Visor,GOTVISOR,,,,Noktovizor,Lysforstærkningsvisir,Lichtverstärkungsgerät,Νυχτερινή Όραση,Vizilo de luma amplifikado,Visor de amplificación de luz,,Valonvahvistusvisiiri,Lunettes de Vision Nocturne,Éjjellátó sisak,Amplificatore di luce,"暗視バイザー -",야간투시 바이저,Lichtversterkingsvizier,Lysforsterkende visir,Gogle noktowizyjne,Visor de amplificação de luz,Visor de amplificação luminosa,Vedere amplificată,Очки ночного видения.,Ноћни визир,Işık Amplifikasyon Vizörü -MegaSphere!,GOTMSPHERE,,,,MegaSféra!,,MegaSphäre!,Μεγασφαίρα!,Supera sfero!,¡MegaEsfera!,,Megakuula!,Mégasphère!,MegaGömb!,MegaSfera!,メガスフィアー!,메가스피어!,,,Megasfera!,Megaesfera!,,Megasferă!,Мегасфера!,Мегасфера!,MegaSfer! -Picked up a clip.,GOTCLIP,,,,Sebrán zásobník.,Hentede et magasin med kugler.,Magazin genommen.,Πήρες ένα κουτάκι σφαιρών.,Vi trovis magazenon.,Encuentras un cargador.,Hallaste un cargador.,Poimit lippaan.,Chargeur récupéré.,Felvettél egy töltényt.,Raccolto un caricatore.,弾倉を拾った。,탄창을 얻었다.,Je hebt een patroon opgepakt.,Plukket opp et magasin.,Zebrano magazynek.,Pegou um carregador.,Apanhaste um carregador,Ai ridicat un cartuș.,Получен магазин.,Покупили сте оквир.,Bir şarjör aldım. -Picked up a box of bullets.,GOTCLIPBOX,,,,Sebrána krabice s kulkami.,Hentede en kasse med kugler.,Kiste mit Pistolenkugeln genommen.,Πήρες ένα κουτί με σφαίρες.,Vi trovis skatolon da kugloj.,Encuentras una caja de balas.,Hallaste una caja de balas.,Poimit laatikollisen luoteja.,Boîte de balles récupérée.,Felvettél egy doboz töltényt.,Raccolta una scatola di proiettili.,弾薬箱を拾った。,실탄 탄통을 얻었다.,Je hebt een doos kogels opgepakt.,Plukket opp en eske med kuler.,Zebrano pudełko z nabojami.,Pegou uma caixa de balas.,Apanhaste uma caixa de balas,Ai ridicat o cutie cu gloanțe.,Получена коробка патронов.,Покупили сте кутију метака.,Bir kutu mermi aldı. -Picked up a rocket.,GOTROCKET,,,,Sebrána raketa.,Hentede en raket.,Rakete genommen,Πήρες ένα πύραυλο.,Vi trovis misilon.,Encuentras un misil.,Hallaste un misil.,Poimit raketin.,Roquette récupérée.,Felvettél egy rakétát.,Raccolto un razzo.,ロケットを拾った。,로켓을 얻었다.,Je hebt een raket opgepakt.,Plukket opp en rakett.,Zebrano rakietę.,Pegou um foguete.,Apanhaste um míssil,Ai ridicat o rachetă.,Получена ракета.,Покупили сте ракету.,Bir roket aldı. -Picked up a box of rockets.,GOTROCKBOX,,,,Sebrána krabice s raketami.,Hentede en kasse med raketter.,Kiste mit Raketen genommen.,Πήρες ένα κουτί με πυράυλους.,Vi trovis keston da misiloj.,Encuentras una caja de misiles.,Hallaste una caja de misiles.,Poimit laatikollisen raketteja.,Caisse de roquettes récupérée.,Felvettél egy doboz rakétát.,Raccolta una cassa di razzi.,ロケット箱を拾った。,로켓 상자를 얻었다.,Je hebt een doos raketten opgepakt.,Plukket opp en eske med raketter.,Zebrano pudełko z rakietami.,Pegou uma caixa de foguetes.,Apanhaste uma caixa de mísseis,Ai ridicat o cutie cu rachete.,Получен ящик ракет.,Покупили сте кутију ракета.,Bir kutu roket aldı. -Picked up an energy cell.,GOTCELL,,,,Sebrán energetický článek.,Hentede en energicelle.,Energiezelle genommen.,Πήρες ένα κύτταρο ενέργιας.,Vi trovis energiĉelon.,Encuentras una célula de energía.,Hallaste una célula de energía.,Poimit energia-akun.,Cellule énergétique récupérée.,Felvettél egy energia cellát.,Raccolta una batteria.,エネルギーセルを拾った。,에너지 셀을 얻었다.,Je hebt een energiecel opgepakt.,Plukket opp en energicelle.,Zebrano ogniwo energetyczne.,Pegou uma célula de energia.,Apanhaste uma célula de energia,Ai ridicat o celulă cu energie.,Получена энергобатарея.,Покупили сте енергетску ћелију.,Bir enerji hücresi aldı. -Picked up an energy cell pack.,GOTCELLBOX,,,,Sebrán svazek energetických článků.,Hentede en energicellepakke.,Energiezellenpackung genommen.,Πήρες ένα πακέτο κύτταρων ενέργιας.,Vi trovis energiĉelo-pakon.,Encuentras un paquete de células de energía.,Hallaste un paquete de células de energía.,Poimit energia-akkupaketin.,Pack de cellules énergétiques récupéré.,Felvettél egy doboznyi energia cellát.,Raccolta una confezione di batterie.,エネルギーセルパックを拾った。,대용량 에너지 셀을 얻었다.,Je hebt een energiecelpakket opgepakt.,Plukket opp en energipakke.,Zebrano paczkę ogniw energetycznych.,Pegou um pacote de células de energia.,Apanhaste um pacote de células de energia.,Ai ridicat un pachet de celule cu energie.,Получен комплект энергобатарей.,Покупили сте паковање енергетских ћелија.,Bir enerji hücresi paketi aldı. -Picked up 4 shotgun shells.,GOTSHELLS,,,,Sebrány 4 broky.,Hentede 4 haglpatroner.,4 Schrotflintenpatronen genommen,Πήρες τέσσερεις σφάιρες ντουγεκιόυ.,Vi trovis 4 kartoĉojn.,Encuentras 4 cartuchos de escopeta.,Hallaste 4 cartuchos de escopeta.,Poimit 4 haulikon patruunaa.,4 cartouches récupérées.,Felvettél 4 sörétes töltényt.,Raccolte 4 cartucce per fucile.,4発の散弾を拾った。,샷건 쉘 4개를 얻었다.,Je hebt 4 jachtgeweerkogels opgepakt.,Plukket opp 4 haglpatroner.,Zebrano 4 loftki do strzelby.,Pegou 4 cartuchos de espingarda.,Apanhaste 4 cartuchos de espingarda.,Ai ridicat 4 proiectile pentru pușcă.,Получено 4 патрона для дробовика.,Покупили сте 4 патроне од пумпарице.,4 av tüfeği mermisi aldı. -Picked up a box of shotgun shells.,GOTSHELLBOX,,,,Sebrána krabice s broky.,Hentede en kasse med haglpatroner.,Kiste mit Schrotflintenpatronen genommen.,Πήρες ένα κουτί με σφάιρες ντουγεκιόυ.,Vi trovis skatolon da kartoĉoj.,Encuentras una caja de cartuchos de escopeta.,Hallaste una caja de cartuchos de escopeta.,Poimit laatikollisen haulikon patruunoita.,Boîte de cartouches récupérée.,Felvettél egy doboz sörétes töltényt.,Raccolta una scatola di cartucce per fucile.,散弾箱を拾った。,샷건 쉘 보관함을 얻었다.,Je hebt een doos jachtgeweerkogels opgepakt.,Plukket opp en eske med haglepatroner.,Zebrano pudełko loftek do strzelby.,Pegou uma caixa de cartuchos de espingarda.,Apanhaste uma caixa de cartuchos de espingarda,Ai ridicat o cutie cu proiectile pentru pușcă.,Получена коробка патронов для дробовика.,Покупили сте кутију патрона од пумпарице.,Bir kutu av tüfeği mermisi aldı. -Picked up a backpack full of ammo!,GOTBACKPACK,,,,Sebrán batoh s haldou munice!,Hentede en rygsæk fuld af ammunition!,Rucksack mit Munition genommen.,Πήρες μια τσάντα γεμάτη με πυρομαχικά!,Vi trovis tornistron plena de municioj!,¡Encuentras una mochila llena de munición!,¡Hallaste una mochila llena de munición!,Poimit repun täynnä ammuksia!,Sac à dos plein de munitions récupéré!,Felvettél egy tölténnyel teli hátizsákot!,Raccolto uno zaino zeppo di munizioni!,弾薬の入ったバックパックを手に入れた!,탄약이 들어있는 배낭을 얻었다!,Je hebt een rugzak vol munitie opgepakt!,Plukket opp en ryggsekk full av ammunisjon!,Zebrano plecak pełen amunicji!,Pegou uma mochila cheia de munição!,Apanhaste uma mochila cheia de munição,Ai ridicat o raniță plină cu muniție!,"Получен рюкзак, полный патронов!",Покупили сте ранац с патронама!,Cephane dolu bir sırt çantası aldı! -"You got the BFG9000! Oh, yes.",GOTBFG9000,,,,"Sebráno BFG9000! Ó, ano!","Du fik BFG9000! Åh, ja.","Das BFG9000! Oh, ja!","Πήρες το BFG9000! ο, ΝΑΊ.","Vi trovis BFG9000! Ho, jes.",¡Encuentras una BFG9000! Qué guay.,¡Hallaste una BFG9000! Genial.,Sait BFG9000:n! Voi kyllä.,"UN BFG9000! OH, OUI!",Felvetted a BFG9000-et! Ezaz.,"Hai trovato il BFG9000! Eh, sì!",BFG9000を手に入れた!やったぜ。,당신은 BFG9000을 습득했다! 오우 예.,Je hebt de BFG9000! Jawel.,"Du har BFG9000! Å, ja.","Zebrano BFG9000! O, tak.","Você pegou a BFG! Ah, que delícia!","Apanhaste a BFG9000! Oh, SIM!","Ai pus mâna pe BFG9000! Oh, da.","У вас BFG9000! О, да!","Покупили сте ВЈП9000! О, да.","BFG9000'i aldın! Oh, evet." -You got the chaingun!,GOTCHAINGUN,,,,Sebrán kulomet.,Du har et maskingevær!,Maschinengewehr genommen.,Πήρες το πολυβόλο.,Vi trovis maŝinpafilon!,¡Encuentras una ametralladora!,¡Hallaste una ametralladora!,Sait Gatling-konekiväärin!,Une MITRAILLEUSE!,Felvetted a golyószórót!,Hai trovato un mitragliatore!,チェーンガンを手に入れた!,당신은 체인건을 습득했다!,Je hebt het machinegeweer!,Du har en maskinpistol!,Zebrano karabin maszynowy!,Você pegou a metralhadora!,Apanhaste a metrelhadora!,Ai pus mâna pe mitraliera rotativă!,Получен пулемёт!,Покупили сте митраљез!,Silahı aldın! -A chainsaw! Find some meat!,GOTCHAINSAW,,,,Motorová pila! Najdi maso!,En motorsav! Find noget kød!,Eine Kettensäge. Such mir etwas Fleisch!,Ένα αλυσοπρίονο! Βρες κρέας!,Ĉensegilo! Trovu ian karnon!,¡Una motosierra! ¡Busca algo de carne!,,Moottorisaha! Mene etsimään lihaa!,Une TRONCONNEUSE! Viande frâiche!,Egy láncfűrész! Keress valami aprítanivalót!,Una motosega! Trova un pò di carne!,チェーンソウだ!肉を寄越せ!,당신은 전기톱을 습득했다! 도륙할 시간!,Een kettingzaag! Vind vlees!,En motorsag! Finn litt kjøtt!,Piła łańcuchowa! Znajdź trochę mięsa!,Uma motoserra! Encontre alguma carne!,Uma motoserra! Bora encontrar alguma carne!,O drujbă! Găsește niște carne!,Бензопила! Найди немного мяса!,Тестера! Нађи месо!,Elektrikli testere! Biraz et bul! -You got the rocket launcher!,GOTLAUNCHER,,,,Sebrán raketomet.,Du har en raketkaster!,Raketenwerfer genommen.,Πήρες το πυραβλοβόλο.,Vi trovis misilpafilon!,¡Encuentras un lanzamisiles!,¡Hallaste un lanzamisiles!,Sait singon!,Un LANCE-ROQUETTES!,Felvetted a rakétavetőt!,Hai trovato un lanciarazzi!,ロケットランチャーを手に入れた!,당신은 로켓 런쳐를 습득했다!,Je hebt de raketwerper!,Du har rakettkasteren!,Zebrano wyrzutnię rakiet!,Você pegou um lança-foguetes!,Apanhaste um lança-mísseis!,Ai pus mâna pe lansatorul de rachete!,Получен ракетомёт!,Покупили сте ракетни бацач!,Roketatarı aldın! -You got the plasma gun!,GOTPLASMA,,,,Sebrána plazmová puška.,Du har plasmapistolen!,Plasma-Gewehr genommen.,Πήρες το όπλο πλάσματος!,Vi trovis plasmo-pafilon!,¡Encuentras un fusil de plasma!,¡Hallaste un fusil de plasma!,Sait plasmapyssyn!,Un FUSIL A PLASMA!,Felvetted a plazmafegyvert!,Hai trovato un fucile al plasma!,プラズマライフルを手に入れた!,당신은 플라즈마 건을 습득했다!,Je hebt het plasmageweer!,Du har plasmapistolen!,Zebrano karabin plazmowy!,Você pegou o fuzil de plasma!,Apanhaste uma pistola de plasma!,Ai pus mâna pe arma cu plasmă!,Получен плазмомёт!,Покупили сте плазма оружје!,Plazma silahın var! -You got the shotgun!,GOTSHOTGUN,,,,Sebrána brokovnice.,Du har et haglgevær!,Schrotflinte genommen.,Πήρες το ντουφέκι!,Vi trovis kartoĉan fusilon!,¡Encuentras una escopeta!,¡Hallaste una escopeta!,Sait haulikon!,Un FUSIL A POMPE!,Felvetted a puskát!,Hai trovato un fucile!,ショットガンを手に入れた!,당신은 샷건을 습득했다!,Je hebt het jachtgeweer!,Du har haglen!,Zebrano strzelbę!,Você pegou a espingarda!,Apanhaste uma espingarda.,Ai pus mâna pe pușcă!,Получен дробовик!,Покупили сте пумпарицу!,Pompalı tüfeğin var! -You got the super shotgun!,GOTSHOTGUN2,,,,Sebrána superbrokovnice.,Du har et super-haglgevær!,Super-Schrotflinte genommen.,Πήρες το διπλό ντουφέκι!,Vi trovis dutuban fusilon!,¡Encuentras una superescopeta!,¡Hallaste una superescopeta!,Sait superhaulikon!,Un SUPER FUSIL DE CHASSE!,Felvetted a Szuper puskát!,Hai trovato una doppietta!,スーパーショットガンを手に入れた!,당신은 슈퍼 샷건을 습득했다!,Je hebt het superjachtgeweer!,Du har supergeværet!,Zebrano super strzelbę!,Você pegou uma espingarda de cano duplo!,Apanhaste uma espingarda de cano duplo!,Ai pus mâna pe super pușcă!,Получен супердробовик!,Покупили сте двоцевку!,Süper av tüfeğini aldın! -Picked up a pistol.,PICKUP_PISTOL_DROPPED,,,,Sebrána pistole.,Du har fået en pistol.,Pistole genommen.,Πήρες ενα πιστόλι.,Prenis pistolon.,Una pistola.,,Poimit pistoolin.,Un PISTOLET.,Felvettél egy pisztolyt.,Raccolta una pistola.,ピストルを拾った。,권총을 주웠다.,Je hebt het pistool opgepakt.,Plukket opp en pistol.,Zebrano pistolet.,Pegou uma pistola.,Apanhaste uma pistola.,Ai ridicat un pistol.,Получен пистолет.,Покупили сте пиштољ.,Bir tabanca aldın. -You pick up a demonic dagger.,BETA_BONUS1,,,,Sebrána démonická dýka.,Du har samlet en dæmonisk dolk op.,Dämonischen Dolch genommen.,Πήρες ένα δαιμονικό μαχαίρι.,Vi trovis demonan ponardon.,Encuentras una daga demoníaca.,Hallaste una daga demoníaca.,Poimit demonisen tikarin.,Dague diabolique récupérée.,Felvettél egy démoni tőrt.,Hai raccolto un pugnale demoniaco.,デモニックダガーを拾った。,당신은 마귀내린 단검을 얻었다.,Je hebt een demonische dolk opgepakt.,Du plukket opp en demonisk dolk.,Zebrano demoniczny sztylet.,Você pegou uma adaga demoníaca.,Apanhaste uma navalha demoníaca.,Ai ridicat un pumnal demonic.,Вы подобрали демонический кинжал.,Купите демонски бодеж.,Şeytani bir hançer aldın. -You pick up a skullchest.,BETA_BONUS2,,,,Sebrána lebkotruhla.,Du samler en kraniekasse op.,Schädelkiste genommen.,Πήρες ένα κρανομπαούλο.,Vi trovis kraniokeston.,Encuentras un cofre de calaveras.,Hallaste un cofre de calaveras.,Poimit kalloarkun.,Coffre-crâne récupéré.,Felvettél egy skullchest-et.,Hai raccolto un cofanetto del teschio.,スカルチェストを拾った。,당신은 해골상자를 얻었다.,Je hebt een schedelborst opgepakt.,Du plukker opp en hodeskalle.,Zebrano skrzynię czaszki.,Você pegou um cofre-caveira.,Apanhaste um cofre caveira.,Ai ridicat o cutie cu craniu.,Вы подобрали сундук с черепом.,Купите ковчег с лобањом.,Bir kafatası sandığı aldın. -You pick up an evil sceptre.,BETA_BONUS3,,,,Sebráno zlé žezlo.,Du samler et ondt scepter op.,Teuflisches Zepter genommen.,Πήρες το μοχθηρό σκήπτρο.,Vi trovis malbonan sceptron.,Encuentras un cetro del mal.,Hallaste un cetro del mal.,Poimit pahan valtikan.,Sceptre maléfique récupéré.,Felvettél egy gonosz jogart.,Hai raccolto uno scettro del male.,エビルセプターを拾った。,당신은 사악한 홀을 얻었다.,Je hebt een kwaadaardige scepter opgepakt.,Du plukker opp et ondt septer.,Zebrano złe berło.,Você pegou um cetro maligno.,Apanhaste um cetro maligno,Ai ridicat un sceptru malefic.,Вы подобрали скипетр зла.,Купите зли скиптар.,Şeytani bir asa alıyorsun. -You pick up an unholy bible.,BETA_BONUS4,,,,Sebrána bezbožná bible.,Du samler en uhellig bibel op.,Unheilige Bibel genommen,Πήρες τήν ανίερη βίβλο.,Vi trovis malsanktan biblion.,Encuentras una biblia profana.,Hallaste una biblia profana.,Poimit epäpyhän raamatun.,Bible profane récupérée.,Felvettél egy istentelen bibliát.,Hai raccolto una bibbia profana.,アンホーリーバイブルを拾った。,당신은 불경스러운 성서를 얻었다.,Je hebt een onheilige bijbel opgepakt.,Du plukker opp en uhellig bibel.,Zebrano nieświętą biblię.,Você pegou uma bíblia profana.,Apanhaste uma bíblia profana.,Ai ridicat o biblie nesfântă.,Вы подобрали порочную библию.,Купите несвету библију.,Kutsal olmayan bir İncil aldın. -,,Locks,,,,,,,,,,,,,,,,,,,,,,,, +",야간투시 바이저,Lichtversterkingsvizier,Lysforsterkende visir,Gogle noktowizyjne,Visor de amplificação de luz,Visor de amplificação luminosa,Vedere amplificată,Очки ночного видения.,Ноћни визир,Ljusförstärkande visir,Işık Amplifikasyon Vizörü,Окуляри нічного бачення +MegaSphere!,GOTMSPHERE,,,,MegaSféra!,,MegaSphäre!,Μεγασφαίρα!,Pleja sfero!,¡MegaEsfera!,,Megakuula!,Mégasphère!,MegaGömb!,MegaSfera!,メガスフィアー!,메가스피어!,,,Megasfera!,Megaesfera!,,Megasferă!,Мегасфера!,Мегасфера!,,MegaSfer!,Мегасфера! +Picked up a clip.,GOTCLIP,,,,Sebrán zásobník.,Hentede et magasin med kugler.,Magazin genommen.,Πήρες ένα κουτάκι σφαιρών.,Vi trovis magazenon.,Encuentras un cargador.,,Poimit lippaan.,Chargeur récupéré.,Felvettél egy töltényt.,Raccolto un caricatore.,弾倉を拾った。,탄창을 얻었다.,Je hebt een patroon opgepakt.,Plukket opp et magasin.,Zebrano magazynek.,Pegou um carregador.,Apanhaste um carregador,Ai ridicat un cartuș.,Получен магазин.,Покупили сте оквир.,Plockade upp ett klipp.,Bir şarjör aldım.,Взято набійницю. +Picked up a box of bullets.,GOTCLIPBOX,,,,Sebrána krabice s kulkami.,Hentede en kasse med kugler.,Kiste mit Pistolenkugeln genommen.,Πήρες ένα κουτί με σφαίρες.,Vi trovis skatolon da kugloj.,Encuentras una caja de balas.,,Poimit laatikollisen luoteja.,Boîte de balles récupérée.,Felvettél egy doboz töltényt.,Raccolta una scatola di proiettili.,弾薬箱を拾った。,실탄 탄통을 얻었다.,Je hebt een doos kogels opgepakt.,Plukket opp en eske med kuler.,Zebrano pudełko z nabojami.,Pegou uma caixa de balas.,Apanhaste uma caixa de balas,Ai ridicat o cutie cu gloanțe.,Получена коробка пуль.,Покупили сте кутију метака.,Plockade upp en låda med kulor.,Bir kutu mermi aldı.,Взято коробку набоїв. +Picked up a rocket.,GOTROCKET,,,,Sebrána raketa.,Hentede en raket.,Rakete genommen,Πήρες ένα πύραυλο.,Vi trovis misilon.,Encuentras un misil.,,Poimit raketin.,Roquette récupérée.,Felvettél egy rakétát.,Raccolto un razzo.,ロケットを拾った。,로켓을 얻었다.,Je hebt een raket opgepakt.,Plukket opp en rakett.,Zebrano rakietę.,Pegou um foguete.,Apanhaste um míssil,Ai ridicat o rachetă.,Получена ракета.,Покупили сте ракету.,Plockade upp en raket.,Bir roket aldı.,Взято ракету. +Picked up a box of rockets.,GOTROCKBOX,,,,Sebrána krabice s raketami.,Hentede en kasse med raketter.,Kiste mit Raketen genommen.,Πήρες ένα κουτί με πυράυλους.,Vi trovis keston da misiloj.,Encuentras una caja de misiles.,,Poimit laatikollisen raketteja.,Caisse de roquettes récupérée.,Felvettél egy doboz rakétát.,Raccolta una cassa di razzi.,ロケット箱を拾った。,로켓 상자를 얻었다.,Je hebt een doos raketten opgepakt.,Plukket opp en eske med raketter.,Zebrano pudełko z rakietami.,Pegou uma caixa de foguetes.,Apanhaste uma caixa de mísseis,Ai ridicat o cutie cu rachete.,Получен ящик ракет.,Покупили сте кутију ракета.,Plockade upp en låda med raketer.,Bir kutu roket aldı.,Взято коробку з ракетами. +Picked up an energy cell.,GOTCELL,,,,Sebrán energetický článek.,Hentede en energicelle.,Energiezelle genommen.,Πήρες ένα κύτταρο ενέργιας.,Vi trovis energiĉelon.,Encuentras una célula de energía.,,Poimit energia-akun.,Cellule énergétique récupérée.,Felvettél egy energia cellát.,Raccolta una batteria.,エネルギーセルを拾った。,에너지 셀을 얻었다.,Je hebt een energiecel opgepakt.,Plukket opp en energicelle.,Zebrano ogniwo energetyczne.,Pegou uma célula de energia.,Apanhaste uma célula de energia,Ai ridicat o celulă cu energie.,Получена энергобатарея.,Покупили сте енергетску ћелију.,Plockade upp en energicell.,Bir enerji hücresi aldı.,Взято енергетичну батарею. +Picked up an energy cell pack.,GOTCELLBOX,,,,Sebrán svazek energetických článků.,Hentede en energicellepakke.,Energiezellenpackung genommen.,Πήρες ένα πακέτο κύτταρων ενέργιας.,Vi trovis energiĉelo-pakon.,Encuentras un paquete de células de energía.,,Poimit energia-akkupaketin.,Pack de cellules énergétiques récupéré.,Felvettél egy doboznyi energia cellát.,Raccolta una confezione di batterie.,エネルギーセルパックを拾った。,대용량 에너지 셀을 얻었다.,Je hebt een energiecelpakket opgepakt.,Plukket opp en energipakke.,Zebrano paczkę ogniw energetycznych.,Pegou um pacote de células de energia.,Apanhaste um pacote de células de energia.,Ai ridicat un pachet de celule cu energie.,Получен комплект энергобатарей.,Покупили сте паковање енергетских ћелија.,Plockade upp ett energicellpaket.,Bir enerji hücresi paketi aldı.,Взято велику енергетичну батарею. +Picked up 4 shotgun shells.,GOTSHELLS,,,,Sebrány 4 broky.,Hentede 4 haglpatroner.,4 Schrotflintenpatronen genommen,Πήρες τέσσερεις σφάιρες ντουγεκιόυ.,Vi trovis 4 kartoĉojn.,Encuentras 4 cartuchos de escopeta.,,Poimit 4 haulikon patruunaa.,4 cartouches récupérées.,Felvettél 4 sörétes töltényt.,Raccolte 4 cartucce per fucile.,4発の散弾を拾った。,샷건 쉘 4개를 얻었다.,Je hebt 4 jachtgeweerkogels opgepakt.,Plukket opp 4 haglpatroner.,Zebrano 4 loftki do strzelby.,Pegou 4 cartuchos de espingarda.,Apanhaste 4 cartuchos de espingarda.,Ai ridicat 4 proiectile pentru pușcă.,Получено 4 патрона дробовика.,Покупили сте 4 патроне од пумпарице.,Plockade upp 4 hagelpatroner.,4 av tüfeği mermisi aldı.,Взято 4 рушничні набої. +Picked up a box of shotgun shells.,GOTSHELLBOX,,,,Sebrána krabice s broky.,Hentede en kasse med haglpatroner.,Kiste mit Schrotflintenpatronen genommen.,Πήρες ένα κουτί με σφάιρες ντουγεκιόυ.,Vi trovis skatolon da kartoĉoj.,Encuentras una caja de cartuchos de escopeta.,,Poimit laatikollisen haulikon patruunoita.,Boîte de cartouches récupérée.,Felvettél egy doboz sörétes töltényt.,Raccolta una scatola di cartucce per fucile.,散弾箱を拾った。,샷건 쉘 보관함을 얻었다.,Je hebt een doos jachtgeweerkogels opgepakt.,Plukket opp en eske med haglepatroner.,Zebrano pudełko loftek do strzelby.,Pegou uma caixa de cartuchos de espingarda.,Apanhaste uma caixa de cartuchos de espingarda,Ai ridicat o cutie cu proiectile pentru pușcă.,Получена коробка патронов дробовика.,Покупили сте кутију патрона од пумпарице.,Plockade upp en låda med hagelpatroner.,Bir kutu av tüfeği mermisi aldı.,Взято коробку рушничних набоїв. +Picked up a backpack full of ammo!,GOTBACKPACK,,,,Sebrán batoh s haldou munice!,Hentede en rygsæk fuld af ammunition!,Rucksack mit Munition genommen.,Πήρες μια τσάντα γεμάτη με πυρομαχικά!,Vi trovis tornistron plena de municioj!,¡Encuentras una mochila llena de munición!,,Poimit repun täynnä ammuksia!,Sac à dos plein de munitions récupéré!,Felvettél egy tölténnyel teli hátizsákot!,Raccolto uno zaino zeppo di munizioni!,弾薬の入ったバックパックを手に入れた!,탄약이 들어있는 배낭을 얻었다!,Je hebt een rugzak vol munitie opgepakt!,Plukket opp en ryggsekk full av ammunisjon!,Zebrano plecak pełen amunicji!,Pegou uma mochila cheia de munição!,Apanhaste uma mochila cheia de munição,Ai ridicat o raniță plină cu muniție!,"Получен рюкзак, полный патронов!",Покупили сте ранац с патронама!,Plockade upp en ryggsäck full av ammunition!,Cephane dolu bir sırt çantası aldı!,Взято рюкзак повний набоїв! +"You got the BFG9000! Oh, yes.",GOTBFG9000,,,,"Sebráno BFG9000! Ó, ano!","Du fik BFG9000! Åh, ja.","Das BFG9000! Oh, ja!","Πήρες το BFG9000! ο, ΝΑΊ.",Vi trovis BFG9000! Bonege.,¡Encuentras una BFG9000! Qué guay.,¡Encuentras una BFG9000! Genial.,Sait BFG9000:n! Voi kyllä.,"UN BFG9000! OH, OUI!",Felvetted a BFG9000-et! Ezaz.,"Hai trovato il BFG9000! Eh, sì!",BFG9000を手に入れた!やったぜ。,당신은 BFG9000을 습득했다! 오우 예.,Je hebt de BFG9000! Jawel.,"Du har BFG9000! Å, ja.","Zebrano BFG9000! O, tak.","Você pegou a BFG! Ah, que delícia!","Apanhaste a BFG9000! Oh, SIM!","Ai pus mâna pe BFG9000! Oh, da.","У вас BFG9000! О, да!","Покупили сте ВЈП9000! О, да.","Du fick fått BFG9000! Ja, ja.","BFG9000'i aldın! Oh, evet.",Взято БФГ9000! О так. +You got the chaingun!,GOTCHAINGUN,,,,Sebrán kulomet.,Du har et maskingevær!,Maschinengewehr genommen.,Πήρες το πολυβόλο.,Vi trovis maŝinpafilon!,¡Encuentras una ametralladora!,,Sait Gatling-konekiväärin!,Une MITRAILLEUSE!,Felvetted a golyószórót!,Hai trovato un mitragliatore!,チェーンガンを手に入れた!,당신은 체인건을 습득했다!,Je hebt het machinegeweer!,Du har en maskinpistol!,Zebrano karabin maszynowy!,Você pegou a metralhadora!,Apanhaste a metrelhadora!,Ai pus mâna pe mitraliera rotativă!,Получен пулемёт!,Покупили сте митраљез!,Du fick kedjepistolen!,Silahı aldın!,Взято кулемета. +A chainsaw! Find some meat!,GOTCHAINSAW,,,,Motorová pila! Najdi maso!,En motorsav! Find noget kød!,Eine Kettensäge. Such mir etwas Fleisch!,Ένα αλυσοπρίονο! Βρες κρέας!,Ĉensegilo! Trovu ian karnon!,¡Una motosierra! ¡Busca algo de carne!,,Moottorisaha! Mene etsimään lihaa!,Une TRONCONNEUSE! Viande frâiche!,Egy láncfűrész! Keress valami aprítanivalót!,Una motosega! Trova un po' di carne!,チェーンソウだ!肉を寄越せ!,당신은 전기톱을 습득했다! 도륙할 시간!,Een kettingzaag! Vind vlees!,En motorsag! Finn litt kjøtt!,Piła łańcuchowa! Znajdź trochę mięsa!,Uma motoserra! Encontre alguma carne!,Uma motoserra! Bora encontrar alguma carne!,O drujbă! Găsește niște carne!,Бензопила! Найди немного мяса!,Тестера! Нађи месо!,En motorsåg! Hitta lite kött!,Elektrikli testere! Biraz et bul!,Бензопила! Знайди трохи м'яса! +You got the rocket launcher!,GOTLAUNCHER,,,,Sebrán raketomet.,Du har en raketkaster!,Raketenwerfer genommen.,Πήρες το πυραβλοβόλο.,Vi trovis misilpafilon!,¡Encuentras un lanzamisiles!,,Sait singon!,Un LANCE-ROQUETTES!,Felvetted a rakétavetőt!,Hai trovato un lanciarazzi!,ロケットランチャーを手に入れた!,당신은 로켓 런쳐를 습득했다!,Je hebt de raketwerper!,Du har rakettkasteren!,Zebrano wyrzutnię rakiet!,Você pegou um lança-foguetes!,Apanhaste um lança-mísseis!,Ai pus mâna pe lansatorul de rachete!,Получен ракетомёт!,Покупили сте ракетни бацач!,Du fick raketkastaren!,Roketatarı aldın!,Взято ракетомет! +You got the plasma gun!,GOTPLASMA,,,,Sebrána plazmová puška.,Du har plasmapistolen!,Plasma-Gewehr genommen.,Πήρες το όπλο πλάσματος!,Vi trovis plasmo-pafilon!,¡Encuentras un fusil de plasma!,,Sait plasmapyssyn!,Un FUSIL A PLASMA!,Felvetted a plazmafegyvert!,Hai trovato un fucile al plasma!,プラズマライフルを手に入れた!,당신은 플라즈마 건을 습득했다!,Je hebt het plasmageweer!,Du har plasmapistolen!,Zebrano karabin plazmowy!,Você pegou o fuzil de plasma!,Apanhaste uma pistola de plasma!,Ai pus mâna pe arma cu plasmă!,Получен плазмомёт!,Покупили сте плазма оружје!,Du fick plasmapistolen!,Plazma silahın var!,Взято плазмаган! +You got the shotgun!,GOTSHOTGUN,,,,Sebrána brokovnice.,Du har et haglgevær!,Schrotflinte genommen.,Πήρες το ντουφέκι!,Vi trovis kartoĉan fusilon!,¡Encuentras una escopeta!,,Sait haulikon!,Un FUSIL A POMPE!,Felvetted a puskát!,Hai trovato un fucile!,ショットガンを手に入れた!,당신은 샷건을 습득했다!,Je hebt het jachtgeweer!,Du har haglen!,Zebrano strzelbę!,Você pegou a espingarda!,Apanhaste uma espingarda.,Ai pus mâna pe pușcă!,Получен дробовик!,Покупили сте пумпарицу!,Du fick hagelgeväret!,Pompalı tüfeğin var!,Взято дробовик! +You got the super shotgun!,GOTSHOTGUN2,,,,Sebrána superbrokovnice.,Du har et super-haglgevær!,Super-Schrotflinte genommen.,Πήρες το διπλό ντουφέκι!,Vi trovis dutuban fusilon!,¡Encuentras una superescopeta!,,Sait superhaulikon!,Un SUPER FUSIL DE CHASSE!,Felvetted a Szuper puskát!,Hai trovato una doppietta!,スーパーショットガンを手に入れた!,당신은 슈퍼 샷건을 습득했다!,Je hebt het superjachtgeweer!,Du har supergeværet!,Zebrano super strzelbę!,Você pegou uma espingarda de cano duplo!,Apanhaste uma espingarda de cano duplo!,Ai pus mâna pe super pușcă!,Получен супердробовик!,Покупили сте двоцевку!,Du fick super-hagelgeväret!,Süper av tüfeğini aldın!,Взято двостволку! +Picked up a pistol.,PICKUP_PISTOL_DROPPED,,,,Sebrána pistole.,Du har fået en pistol.,Pistole genommen.,Πήρες ενα πιστόλι.,Prenis pistolon.,Una pistola.,,Poimit pistoolin.,Un PISTOLET.,Felvettél egy pisztolyt.,Raccolta una pistola.,ピストルを拾った。,권총을 주웠다.,Je hebt het pistool opgepakt.,Plukket opp en pistol.,Zebrano pistolet.,Pegou uma pistola.,Apanhaste uma pistola.,Ai ridicat un pistol.,Получен пистолет.,Покупили сте пиштољ.,Jag plockade upp en pistol.,Bir tabanca aldın.,Взято пістолет. +You pick up a demonic dagger.,BETA_BONUS1,,,,Sebrána démonická dýka.,Du har samlet en dæmonisk dolk op.,Dämonischen Dolch genommen.,Πήρες ένα δαιμονικό μαχαίρι.,Vi trovis demonan ponardon.,Encuentras una daga demoníaca.,,Poimit demonisen tikarin.,Dague diabolique récupérée.,Felvettél egy démoni tőrt.,Hai raccolto un pugnale demoniaco.,デモニックダガーを拾った。,당신은 마귀내린 단검을 얻었다.,Je hebt een demonische dolk opgepakt.,Du plukket opp en demonisk dolk.,Zebrano demoniczny sztylet.,Você pegou uma adaga demoníaca.,Apanhaste uma navalha demoníaca.,Ai ridicat un pumnal demonic.,Вы подобрали демонический кинжал.,Купите демонски бодеж.,Plockade upp en demonisk dolk.,Şeytani bir hançer aldın.,Взято демонічний кинжал. +You pick up a skullchest.,BETA_BONUS2,,,,Sebrána lebkotruhla.,Du samler en kraniekasse op.,Schädelkiste genommen.,Πήρες ένα κρανομπαούλο.,Vi trovis kraniokeston.,Encuentras un cofre de calaveras.,,Poimit kalloarkun.,Coffre-crâne récupéré.,Felvettél egy skullchest-et.,Hai raccolto un cofanetto del teschio.,スカルチェストを拾った。,당신은 해골상자를 얻었다.,Je hebt een schedelborst opgepakt.,Du plukker opp en hodeskalle.,Zebrano skrzynię czaszki.,Você pegou um cofre-caveira.,Apanhaste um cofre caveira.,Ai ridicat o cutie cu craniu.,Вы подобрали сундук с черепом.,Купите ковчег с лобањом.,Plockade upp en skalle.,Bir kafatası sandığı aldın.,Взято скриню з черепом. +You pick up an evil sceptre.,BETA_BONUS3,,,,Sebráno zlé žezlo.,Du samler et ondt scepter op.,Teuflisches Zepter genommen.,Πήρες το μοχθηρό σκήπτρο.,Vi trovis malbonan sceptron.,Encuentras un cetro del mal.,,Poimit pahan valtikan.,Sceptre maléfique récupéré.,Felvettél egy gonosz jogart.,Hai raccolto uno scettro del male.,エビルセプターを拾った。,당신은 사악한 홀을 얻었다.,Je hebt een kwaadaardige scepter opgepakt.,Du plukker opp et ondt septer.,Zebrano złe berło.,Você pegou um cetro maligno.,Apanhaste um cetro maligno,Ai ridicat un sceptru malefic.,Вы подобрали скипетр зла.,Купите зли скиптар.,Plockade upp en ond scepter.,Şeytani bir asa alıyorsun.,Взято скіпетр зла. +You pick up an unholy bible.,BETA_BONUS4,,,,Sebrána bezbožná bible.,Du samler en uhellig bibel op.,Unheilige Bibel genommen,Πήρες τήν ανίερη βίβλο.,Vi trovis malsanktan biblion.,Encuentras una biblia profana.,,Poimit epäpyhän raamatun.,Bible profane récupérée.,Felvettél egy istentelen bibliát.,Hai raccolto una bibbia profana.,アンホーリーバイブルを拾った。,당신은 불경스러운 성서를 얻었다.,Je hebt een onheilige bijbel opgepakt.,Du plukker opp en uhellig bibel.,Zebrano nieświętą biblię.,Você pegou uma bíblia profana.,Apanhaste uma bíblia profana.,Ai ridicat o biblie nesfântă.,Вы подобрали порочную библию.,Купите несвету библију.,Plockade upp en ohelig bibel.,Kutsal olmayan bir İncil aldın.,Взято нечестиву біблію. +,,Locks,,,,,,,,,,,,,,,,,,,,,,,,,, You need a blue key to activate this object,PD_BLUEO,,,,K aktivaci tohoto objektu potřebuješ modrý klíč.,Du skal bruge en blå nøgle for at aktivere dette objekt,"Du brauchst einen blauen Schlüssel, um dieses Objekt zu aktivieren.",Χρειάζεσε ένα μπλέ κλειδί για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas bluan ŝlosilon por aktivigi ĉi tiun objekton,Necesitas una llave azul para activar este objeto,,Tarvitset sinisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé bleue pour activer cet objet.,Egy kék kulcs szükséges az tárgy aktiválásához.,Ti serve una chiave blu per attivare questo oggetto,この装置には ブルーキーが必要だ。,이 물체를 작동시키기 위해선 청색 열쇠가 필요합니다,Je hebt een blauwe sleutel nodig om dit object te activeren.,Du trenger en blå nøkkel for å aktivere denne gjenstanden,"Potrzebujesz niebieskiego klucza, aby aktywować ten przedmiot",Você precisa de uma chave azul para ativar este objeto,Precisas de uma chave azul para ativar este objeto,"Ai nevoie de o cheie albastră pentru a activa acest -obiect",Для применения нужен синий ключ,Треба вам плави кључ да би активирали овај предмет,Bu nesneyi etkinleştirmek için mavi bir anahtara ihtiyacınız var +obiect",Для применения нужен синий ключ,Треба вам плави кључ да би активирали овај предмет,Du behöver en blå nyckel för att aktivera det här föremålet.,Bu nesneyi etkinleştirmek için mavi bir anahtara ihtiyacınız var,"Вам потрібна синя ключ-карта, щоб активувати цей об'єкт" You need a red key to activate this object,PD_REDO,,,,K aktivaci tohoto objektu potřebuješ červený klíč.,Du skal bruge en rød nøgle for at aktivere dette objekt,"Du brauchst einen roten Schlüssel, um dieses Objekt zu aktivieren.",Χρειάζεσε ένα κόκινο κλειδί για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas ruĝan ŝlosilon por aktivigi ĉi tiun objekton,Necesitas una llave roja para activar este objeto,,Tarvitset punaisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé rouge pour activer cet objet.,"Piros kulcs kell, hogy aktiválhasd ezt a tárgyat.",Ti serve una chiave rossa per attivare questo oggetto,この装置には レッドキーが必要だ。,이 물체를 작동시키기 위해선 적색 열쇠가 필요합니다,Je hebt een rode sleutel nodig om dit object te activeren.,Du trenger en rød nøkkel for å aktivere dette objektet,"Potrzebujesz czerwonego klucza, aby aktywować ten przedmiot",Você precisa de uma chave vermelha para ativar este objeto,Precisas de uma chave vermelha para ativar este objeto,"Ai nevoie de o cheie roșie pentru a activa acest -obiect",Для применения нужен красный ключ,Треба вам црвени кључ да би активирали овај предмет,Bu nesneyi etkinleştirmek için kırmızı bir anahtara ihtiyacınız var +obiect",Для применения нужен красный ключ,Треба вам црвени кључ да би активирали овај предмет,Du behöver en röd nyckel för att aktivera det här föremålet.,Bu nesneyi etkinleştirmek için kırmızı bir anahtara ihtiyacınız var,"Вам потрібна червона ключ-карта, щоб активувати цей об'єкт" You need a yellow key to activate this object,PD_YELLOWO,,,,K aktivaci tohoto objektu potřebuješ žlutý klíč.,Du skal bruge en gul nøgle for at aktivere dette objekt,"Du brauchst einen gelben Schlüssel, um dieses Objekt zu aktivieren.",Χρειάζεσε ένα κύτρινο κλειδί για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas flavan ŝlosilon por aktivigi ĉi tiun objekton,Necesitas una llave amarilla para activar este objeto,,Tarvitset keltaisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé jaune pour activer cet objet.,Egy sárga kulccsal aktiválható ez a tárgy,Ti serve una chiave gialla per attivare questo oggetto,この装置にはイエローキーが必要だ。,이 물체를 작동시키기 위해선 황색 열쇠가 필요합니다,Je hebt een gele sleutel nodig om dit object te activeren.,Du trenger en gul nøkkel for å aktivere dette objektet,"Potrzebujesz żółtego klucza, aby aktywować ten przedmiot",Você precisa de uma chave amarela para ativar este objeto,Precisas de uma chave amarela para ativar este objeto,"Ai nevoie de o cheie galbenă pentru a activa acest -obiect",Для применения нужен жёлтый ключ,Треба вам жути кључ да би активирали овај предмет,Bu nesneyi etkinleştirmek için sarı bir anahtara ihtiyacınız var +obiect",Для применения нужен жёлтый ключ,Треба вам жути кључ да би активирали овај предмет,Du behöver en gul nyckel för att aktivera det här föremålet.,Bu nesneyi etkinleştirmek için sarı bir anahtara ihtiyacınız var,"Вам потрібна жовта ключ-карта, щоб активувати цей об'єкт" You need a blue key to open this door,PD_BLUEK,,,,K otevření těchto dveří potřebuješ modrý klíč.,Du skal bruge en blå nøgle for at åbne denne dør,"Du brauchst einen blauen Schlüssel, um diese Tür zu öffnen.",Χρειάζεσε ένα μπλέ κλειδί για να ανοίξεις αυτή τη πόρτα,Vi bezonas bluan ŝlosilon por malfermi ĉi tiun pordon,Necesitas una llave azul para abrir esta puerta,,Tarvitset sinisen avaimen avataksesi tämän oven,Il vous faut une clé bleue pour ouvrir cette porte.,Az ajtót egy kék kulcs nyitja.,Ti serve una chiave blu per aprire questa porta,このドアには ブルーキーが必要だ。,이 문을 열기 위해선 청색 열쇠가 필요합니다,Je hebt een blauwe sleutel nodig om deze deur te openen.,Du trenger en blå nøkkel for å åpne denne døren,"Potrzebujesz niebieskiego klucza, aby otworzyć te drzwi",Você precisa de uma chave azul para abrir esta porta,Precisas de uma chave azul para abrir esta porta,"Ai nevoie de o cheie albastră pentru a deschide -ușa aceasta",Для открытия нужен синий ключ,Треба вам плави кључ да би отворили ова врата,Bu kapıyı açmak için mavi bir anahtara ihtiyacın var. +ușa aceasta",Для открытия нужен синий ключ,Треба вам плави кључ да би отворили ова врата,Du behöver en blå nyckel för att öppna den här dörren,Bu kapıyı açmak için mavi bir anahtara ihtiyacın var.,"Вам потрібна синя ключ-карта, щоб відкрити ці двері" You need a red key to open this door,PD_REDK,,,,K otevření těchto dveří potřebuješ červený klíč.,Du skal bruge en rød nøgle for at åbne denne dør,"Du brauchst einen roten Schlüssel, um diese Tür zu öffnen.",Χρειάζεσε ένα κόκινο κλειδί για να ανοίξεις αυτή τη πόρτα,Vi bezonas ruĝan ŝlosilon por malfermi ĉi tiun pordon,Necesitas una llave roja para abrir esta puerta,,Tarvitset punaisen avaimen avataksesi tämän oven,Il vous faut une clé rouge pour ouvrir cette porte.,"Piros kulcs szükséges, hogy az ajtót kinyithasd.",Ti serve una chiave rossa per aprire questa porta,このドアには レッドキーが必要だ。,이 문을 열기 위해선 적색 열쇠가 필요합니다,Je hebt een rode sleutel nodig om deze deur te openen.,Du trenger en rød nøkkel for å åpne denne døren,"Potrzebujesz czerwonego klucza, aby otworzyć te drzwi",Você precisa de uma chave vermelha para abrir esta porta,Precisas de uma chave vermelha para abrir esta porta,"Ai nevoie de o cheie roșie pentru a deschide ușa -aceasta",Для открытия нужен красный ключ,Треба вам црвени кључ да би отворили ова врата,Bu kapıyı açmak için kırmızı bir anahtara ihtiyacın var. +aceasta",Для открытия нужен красный ключ,Треба вам црвени кључ да би отворили ова врата,Du behöver en röd nyckel för att öppna den här dörren,Bu kapıyı açmak için kırmızı bir anahtara ihtiyacın var.,"Вам потрібна червона ключ-карта, щоб відкрити ці двері" You need a yellow key to open this door,PD_YELLOWK,,,,K otevření těchto dveří potřebuješ žlutý klíč.,Du skal bruge en gul nøgle for at åbne denne dør,"Du brauchst einen gelben Schlüssel, um diese Tür zu öffnen.",Χρειάζεσε ένα κύτρινο κλειδί για να ανοίξεις αυτή τη πόρτα,Vi bezonas flavan ŝlosilon por malfermi ĉi tiun pordon,Necesitas una llave amarilla para abrir esta puerta,,Tarvitset keltaisen avaimen avataksesi tämän oven,Il vous faut une clé jaune pour ouvrir cette porte.,Kell egy sárga kulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave gialla per aprire questa porta,このドアには イエローキー が必要だ。,이 문을 열기 위해선 황색 열쇠가 필요합니다,Je hebt een gele sleutel nodig om deze deur te openen.,Du trenger en gul nøkkel for å åpne denne døren,"Potrzebujesz żółtego klucza, aby otworzyć te drzwi",Você precisa de uma chave amarela para abrir esta porta,Precisas de uma chave amarela para abrir esta porta,"Ai nevoie de o cheie galbena pentru a deschide ușa -aceasta",Для открытия нужен жёлтый ключ,Треба вам жути кључ да би отворили ова врата,Bu kapıyı açmak için sarı bir anahtara ihtiyacınız var +aceasta",Для открытия нужен жёлтый ключ,Треба вам жути кључ да би отворили ова врата,Du behöver en gul nyckel för att öppna den här dörren.,Bu kapıyı açmak için sarı bir anahtara ihtiyacınız var,"Вам потрібна жовта ключ-карта, щоб відкрити ці двері" You need a blue card to activate this object,PD_BLUECO,,,,K aktivaci tohoto objektu potřebuješ modrou kartu.,Du skal bruge et blåt kort for at aktivere denne objekt,"Du brauchst eine blaue Schlüsselkarte, um dieses Objekt zu aktivieren.",Χρειάζεσε μια μπλέ κάρτα για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas bluan karton por aktivigi ĉi tiun objekton,Necesitas una tarjeta azul para activar este objeto,,Tarvitset sinisen avainkortin aktivoidaksesi tämän kappaleen,Il vous faut une carte bleue pour activer cet objet.,"Egy kék kártya kell, hogy ezt a tárgyat aktiválhasd",Ti serve una card d'accesso blu per attivare questo oggetto ,この装置には ブルーカード が必要だ。,이 물체를 작동시키기 위해선 청색 키카드가 필요합니다,Je hebt een blauwe sleutelkaart nodig om dit voorwerp te activeren.,Du trenger et blått kort for å aktivere dette objektet,"Potrzebujesz niebieskiej karty, aby aktywować ten obiekt",Você precisa de um cartão de acesso azul para ativar este objeto,Precisas de um cartão de acesso azul para ativar este objeto,"Ai nevoie de un card albastru pentru a activa -acest obiect",Для применения нужен синий ключ,Треба вам плава карта да би активирали овај предмет,Bu nesneyi etkinleştirmek için mavi bir karta ihtiyacınız var +acest obiect",Для применения нужна синяя карта,Треба вам плава карта да би активирали овај предмет,Du behöver ett blått kort för att aktivera det här objektet.,Bu nesneyi etkinleştirmek için mavi bir karta ihtiyacınız var,"Вам потрібна синя ключ-карта, щоб активувати цей об'єкт" You need a red card to activate this object,PD_REDCO,,,,K aktivaci tohoto objektu potřebuješ červenou kartu.,Du skal bruge et rødt kort for at aktivere denne objekt,"Du brauchst eine rote Schlüsselkarte, um dieses Objekt zu aktivieren.",Χρειάζεσε μια κόκινη κάρτα για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas ruĝan karton por aktivigi ĉi tiun objekton,Necesitas una tarjeta roja para activar este objeto,,Tarvitset punaisen avainkortin aktivoidaksesi tämän kappaleen,Il vous faut une carte rouge pour activer cet objet.,Piros kártyával aktiválható ez a tárgy,Ti serve una card d'accesso rossa per attivare questo oggetto ,この装置には レッドカード が必要だ。,이 물체를 작동시키기 위해선 적색 키카드가 필요합니다,Je hebt een rode sleutelkaart nodig om dit voorwerp te activeren.,Du trenger et rødt kort for å aktivere dette objektet,"Potrzebujesz czerwonej karty, aby aktywować ten obiekt",Você precisa de um cartão de acesso vermelho para ativar este objeto,Precisas de um cartão de acesso vermelho para ativar este objeto,"Ai nevoie de un card roșu pentru a activa -acest obiect",Для применения нужен красный ключ,Треба вам црвена карта да би активирали овај предмет,Bu nesneyi etkinleştirmek için kırmızı bir karta ihtiyacınız var +acest obiect",Для применения нужна красная карта,Треба вам црвена карта да би активирали овај предмет,Du behöver ett rött kort för att aktivera det här föremålet.,Bu nesneyi etkinleştirmek için kırmızı bir karta ihtiyacınız var,"Вам потрібна червона ключ-карта, щоб активувати цей об'єкт" You need a yellow card to activate this object,PD_YELLOWCO,,,,K aktivaci tohoto objektu potřebuješ žlutou kartu.,Du skal bruge et gult kort for at aktivere denne objekt,"Du brauchst eine gelbe Schlüsselkarte, um dieses Objekt zu aktivieren.",Χρειάζεσε μια κύτρινη κάρτα για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas flavan karton por aktivigi ĉi tiun objekton,Necesitas una tarjeta amarilla para activar este objeto,,Tarvitset keltaisen avainkortin aktivoidaksesi tämän kappaleen,Il vous faut une carte jaune pour activer cet objet.,Kell egy sárga kártya hogy aktiváld ezt a tárgyat,ti serve una card d'accesso gialla per attivare questo oggetto ,この装置には イエローカード が必要だ。,이 물체를 작동시키기 위해선 황색 키카드가 필요합니다,Je hebt een gele sleutelkaart nodig om dit voorwerp te activeren.,Du trenger et gult kort for å aktivere dette objektet,"Potrzebujesz żółtej karty, aby aktywować ten obiekt",Você precisa de um cartão de acesso amarelo para ativar este objeto,Precisas de um cartão de acesso amarelo para ativar este objeto,"Ai nevoie de un card galben pentru a activa -acest obiect",Для применения нужен жёлтый ключ,Треба вам жута карта да би активирали овај предмет,Bu nesneyi etkinleştirmek için sarı bir karta ihtiyacınız var +acest obiect",Для применения нужна жёлтая карта,Треба вам жута карта да би активирали овај предмет,Du behöver ett gult kort för att aktivera det här föremålet.,Bu nesneyi etkinleştirmek için sarı bir karta ihtiyacınız var,"Вам потрібна жовта ключ-карта, щоб активувати цей об'єкт" You need a blue skull to activate this object,PD_BLUESO,,,,K aktivaci tohoto objektu potřebuješ modrou lebku.,Du skal bruge et blåt kranium for at aktivere denne objekt,"Du brauchst einen blauen Schädel-Schlüssel, um dieses Objekt zu aktivieren.",Χρειάζεσε ένα μπλέ κρανιο για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas bluan kranion por aktivigi ĉi tiun objekton,Necesitas una calavera azul para activar este objeto,Necesitas un cráneo azul para activar este objeto,Tarvitset sinisen kalloavaimen aktivoidaksesi tämän kappaleen,Il vous faut un crâne bleu pour activer cet objet.,Kell egy kék koponya hogy aktiváld ezt a tárgyat.,ti serve una chiave-teschio blu per attivare questo oggetto ,この装置には ブルースカル が必要だ。,이 물체를 작동시키기 위해선 청색 해골이 필요합니다,Je hebt een blauwe schedel nodig om dit voorwerp te activeren.,Du trenger en blå hodeskalle for å aktivere dette objektet,"Potrzebujesz niebieskiej czaszki, aby aktywować ten obiekt",Você precisa de uma chave-crânio azul para ativar este objeto,Precisas de uma chave crânio azul para ativar este objeto,"Ai nevoie de un craniu albastru pentru a activa -acest obiect",Для применения нужен синий череп,Треба вам плава лобања да би активирали овај предмет,Bu nesneyi etkinleştirmek için mavi bir kafatasına ihtiyacınız var +acest obiect",Для применения нужен синий череп,Треба вам плава лобања да би активирали овај предмет,Du behöver en blå skalle för att aktivera det här objektet.,Bu nesneyi etkinleştirmek için mavi bir kafatasına ihtiyacınız var,"Вам потрібен синій ключ-череп, щоб активувати цей об'єкт" You need a red skull to activate this object,PD_REDSO,,,,K aktivaci tohoto objektu potřebuješ červenou lebku.,Du skal bruge et rødt kranium for at aktivere denne objekt,"Du brauchst einen roten Schädel-Schlüssel, um dieses Objekt zu aktivieren.",Χρειάζεσε ένα κόκινο κρανιο για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas ruĝan kranion por aktivigi ĉi tiun objekton,Necesitas una calavera roja para activar este objeto,Necesitas un cráneo rojo para activar este objeto,Tarvitset punaisen kalloavaimen aktivoidaksesi tämän kappaleen,Il vous faut un crâne rouge pour activer cet objet.,Kell egy piros koponya hogy aktiváld ezt a tárgyat.,ti serve una chiave-teschio rossa per attivare questo oggetto ,この装置には レッドスカル が必要だ。,이 물체를 작동시키기 위해선 적색 해골이 필요합니다,Je hebt een rode schedel nodig om dit voorwerp te activeren.,Du trenger en rød hodeskalle for å aktivere dette objektet,"Potrzebujesz czerwonej czaszki, aby aktywować ten obiekt",Você precisa de uma chave-crânio vermelha para ativar este objeto,Precisas de uma chave crânio vermelha para ativar este objeto,"Ai nevoie de un craniu roșu pentru a activa -acest obiect",Для применения нужен красный череп,Треба вам црвена лобања да би активирали овај предмет,Bu nesneyi etkinleştirmek için kırmızı bir kafatasına ihtiyacınız var +acest obiect",Для применения нужен красный череп,Треба вам црвена лобања да би активирали овај предмет,Du behöver en röd skalle för att aktivera det här föremålet.,Bu nesneyi etkinleştirmek için kırmızı bir kafatasına ihtiyacınız var,"Вам потрібен червоний ключ-череп, щоб активувати цей об'єкт" You need a yellow skull to activate this object,PD_YELLOWSO,,,,K aktivaci tohoto objektu potřebuješ žlutou lebku.,Du skal bruge et gult kranium for at aktivere denne objekt,"Du brauchst einen gelben Schädel-Schlüssel, um dieses Objekt zu aktivieren.",Χρειάζεσε ένα κύτρινο κρανιο για να ενεργοποίησεις αυτο το αντικείμενο,Vi bezonas flavan kranion por aktivigi ĉi tiun objekton,Necesitas una calavera amarilla para activar este objeto,Necesitas un cráneo amarillo para activar este objeto,Tarvitset keltaisen kalloavaimen aktivoidaksesi tämän kappaleen,Il vous faut un crâne jaune pour activer cet objet.,Kell egy sárga koponya hogy aktiváld ezt a tárgyat.,ti serve una chiave-teschio gialla per attivare questo oggetto ,この装置には イエロースカル が必要だ。,이 물체를 작동시키기 위해선 황색 해골이 필요합니다,Je hebt een gele schedel nodig om dit voorwerp te activeren.,Du trenger en gul hodeskalle for å aktivere dette objektet,"Potrzebujesz żółtej czaszki, aby aktywować ten obiekt",Você precisa de uma chave-crânio amarela para ativar este objeto,Precisas de uma chave crânio amarela para ativar este objeto,"Ai nevoie de un craniu galben pentru a activa -acest obiect",Для применения нужен жёлтый череп,Треба вам жута лобања да би активирали овај предмет,Bu nesneyi etkinleştirmek için sarı bir kafatasına ihtiyacınız var +acest obiect",Для применения нужен жёлтый череп,Треба вам жута лобања да би активирали овај предмет,Du behöver en gul skalle för att aktivera detta föremål.,Bu nesneyi etkinleştirmek için sarı bir kafatasına ihtiyacınız var,"Вам потрібен жовтий ключ-череп, щоб активувати цей об'єкт" You need a blue card to open this door,PD_BLUEC,,,,K otevření těchto dveří potřebuješ modrou kartu.,Du skal bruge et blåt kort for at åbne denne dør,"Du brauchst eine blaue Schlüsselkarte, um diese Tür zu öffnen",Χρειάζεσε μια μπλέ κάρτα για να ανοίξεις αυτή τη πόρτα,Vi bezonas bluan karton por malfermi ĉi tiun pordon,Necesitas una tarjeta azul para abrir esta puerta,,Tarvitset sinisen avainkortin avataksesi tämän oven,Il vous faut une carte bleue pour ouvrir cette porte.,Ez az ajtó egy kék kártyával nyílik.,Ti serve una card d'accesso blu per aprire questa porta,このドアには ブルーカード が必要だ。,이 문을 열기 위해선 청색 키카드가 필요합니다,Je hebt een blauwe sleutelkaart nodig om deze deur te openen.,Du trenger et blått kort for å åpne denne døren,"Potrzebujesz niebieskiej karty, aby otworzyć te drzwi",Você precisa de um cartão de acesso azul para abrir esta porta,Precisas de um cartão de acesso azul para abrir esta porta,"Ai nevoie de un card albastru pentru a activa -această usă",Для открытия нужна синяя карта,Треба вам плава карта да би отворили ова врата,Bu kapıyı açmak için mavi bir karta ihtiyacınız var +această usă",Для открытия нужна синяя карта,Треба вам плава карта да би отворили ова врата,Du behöver ett blått kort för att öppna den här dörren.,Bu kapıyı açmak için mavi bir karta ihtiyacınız var,"Вам потрібна синя карта, щоб активувати цей об'єкт" You need a red card to open this door,PD_REDC,,,,K otevření těchto dveří potřebuješ červenou kartu.,Du skal bruge et rødt kort for at åbne denne dør,"Du brauchst eine rote Schlüsselkarte, um diese Tür zu öffnen",Χρειάζεσε μια κόκινη κάρτα για να ανοίξεις αυτή τη πόρτα,Vi bezonas ruĝan karton por malfermi ĉi tiun pordon,Necesitas una tarjeta roja para abrir esta puerta,,Tarvitset punaisen avainkortin avataksesi tämän oven,Il vous faut une carte rouge pour ouvrir cette porte.,Ez az ajtó egy piros kártyával nyílik.,Ti serve una card d'accesso rossa per aprire questa porta,このドアには レッドカード が必要だ。,이 문을 열기 위해선 적색 키카드가 필요합니다,Je hebt een rode sleutelkaart nodig om deze deur te openen.,Du trenger et rødt kort for å åpne denne døren,"Potrzebujesz czerwonej karty, aby otworzyć te drzwi",Você precisa de um cartão de acesso vermelho para abrir esta porta,Precisas de um cartão de acesso vermelho para abrir esta porta,"Ai nevoie de un card galben pentru a activa -această ușă",Для открытия нужна красная карта,Треба вам црвена карта да би отворили ова врата,Bu kapıyı açmak için kırmızı bir karta ihtiyacınız var. +această ușă",Для открытия нужна красная карта,Треба вам црвена карта да би отворили ова врата,Du behöver ett rött kort för att öppna den här dörren.,Bu kapıyı açmak için kırmızı bir karta ihtiyacınız var.,"Вам потрібна червона карта, щоб активувати цей об'єкт" You need a yellow card to open this door,PD_YELLOWC,,,,K otevření těchto dveří potřebuješ žlutou kartu.,Du skal bruge et gult kort for at åbne denne dør,"Du brauchst eine gelbe Schlüsselkarte, um diese Tür zu öffnen",Χρειάζεσε μια κύτρινη κάρτα για να ανοίξεις αυτή τη πόρτα,Vi bezonas flavan karton por malfermi ĉi tiun pordon,Necesitas una tarjeta amarilla para abrir esta puerta,,Tarvitset keltaisen avainkortin avataksesi tämän oven,Il vous faut une carte jaune pour ouvrir cette porte.,Ez az ajtó egy sárga kártyával nyílik.,Ti serve una card d'accesso gialla per aprire questa porta,このドアには イエローカード が必要だ。,이 문을 열기 위해선 황색 키카드가 필요합니다,Je hebt een gele sleutelkaart nodig om deze deur te openen.,Du trenger et gult kort for å åpne denne døren,"Potrzebujesz żółtej karty, aby otworzyć te drzwi",Você precisa de um cartão de acesso amarelo para abrir esta porta,Precisas de um cartão de acesso amarelo para abrir esta porta,"Ai nevoie de un card galben pentru a activa -această ușă",Для открытия нужна жёлтая карта,Треба вам жута карта да би отворили ова врата,Bu kapıyı açmak için sarı bir karta ihtiyacınız var +această ușă",Для открытия нужна жёлтая карта,Треба вам жута карта да би отворили ова врата,Du behöver ett gult kort för att öppna den här dörren.,Bu kapıyı açmak için sarı bir karta ihtiyacınız var,"Вам потрібна жовта карта, щоб активувати цей об'єкт" You need a blue skull to open this door,PD_BLUES,,,,K otevření těchto dveří potřebuješ modrou lebku.,Du skal bruge et blåt kranium for at åbne denne dør,"Du brauchst einen blauen Schädel-Schlüssel, um diese Tür zu öffnen",Χρειάζεσε ένα μπλέ κρανίο για να ανοίξεις αυτή τη πόρτα,Vi bezonas bluan kranion por malfermi ĉi tiun pordon,Necesitas una calavera azul para abrir esta puerta,Necesitas un cráneo azul para abrir esta puerta,Tarvitset sinisen kalloavaimen avataksesi tämän oven,Il vous faut un crâne bleu pour ouvrir cette porte.,Ez az ajtó egy kék koponyával nyílik.,Ti serve una chiave-teschio blu per aprire questa porta,このドアには ブルースカル が必要だ。,이 문을 열기 위해선 청색 해골이 필요합니다,Je hebt een blauwe schedel nodig om deze deur te openen.,Du trenger en blå hodeskalle for å åpne denne døren,"Potrzebujesz niebieskiej czaszki, aby otworzyć te drzwi",Você precisa de uma chave-crânio azul para abrir esta porta,Precisas de uma chave crânio azul para abrir esta porta,"Ai nevoie de un craniu albastru pentru a activa -această ușă",Для открытия нужен синий череп,Треба вам плава лобања да би отворили ова врата,Bu kapıyı açmak için mavi bir kafatasına ihtiyacın var. +această ușă",Для открытия нужен синий череп,Треба вам плава лобања да би отворили ова врата,Du behöver en blå skalle för att öppna den här dörren.,Bu kapıyı açmak için mavi bir kafatasına ihtiyacın var.,"Вам потрібен синій череп, щоб активувати цей об'єкт" You need a red skull to open this door,PD_REDS,,,,K otevření těchto dveří potřebuješ červenou lebku.,Du skal bruge et rødt kranium for at åbne denne dør,"Du brauchst einen roten Schädel-Schlüssel, um diese Tür zu öffnen",Χρειάζεσε ένα κόκινο κρανίο για να ανοίξεις αυτή τη πόρτα,Vi bezonas ruĝan kranion por malfermi ĉi tiun pordon,Necesitas una calavera roja para abrir esta puerta,Necesitas un cráneo rojo para abrir esta puerta,Tarvitset punaisen kalloavaimen avataksesi tämän oven,Il vous faut un crâne rouge pour ouvrir cette porte.,Ez az ajtó egy piros koponyával nyílik.,Ti serve una chiave-teschio rossa per aprire questa porta,このドアには レッドスカル が必要だ。,이 문을 열기 위해선 적색 해골이 필요합니다,Je hebt een rode schedel nodig om deze deur te openen.,Du trenger en rød hodeskalle for å åpne denne døren,"Potrzebujesz czerwonej czaszki, aby otworzyć te drzwi",Você precisa de uma chave-crânio vermelha para abrir esta porta,Precsias de uma chave crânio vermelha para abrir esta porta,"Ai nevoie de un craniu roșu pentru a activa -această ușă",Для открытия нужен красный череп,Треба вам црвена лобања да би отворили ова врата,Bu kapıyı açmak için kırmızı bir kafatasına ihtiyacın var. +această ușă",Для открытия нужен красный череп,Треба вам црвена лобања да би отворили ова врата,Du behöver en röd skalle för att öppna den här dörren.,Bu kapıyı açmak için kırmızı bir kafatasına ihtiyacın var.,"Вам потрібен червоний череп, щоб активувати цей об'єкт" You need a yellow skull to open this door,PD_YELLOWS,,,,K otevření těchto dveří potřebuješ žlutou lebku.,Du skal bruge et gult kranium for at åbne denne dør,"Du brauchst einen gelben Schädel-Schlüssel, um diese Tür zu öffnen",Χρειάζεσε ένα κύτρινο κρανίο για να ανοίξεις αυτή τη πόρτα,Vi bezonas flavan kranion por malfermi ĉi tiun pordon,Necesitas una calavera amarilla para abrir esta puerta,Necesitas un cráneo amarillo para abrir esta puerta,Tarvitset keltaisen kalloavaimen avataksesi tämän oven,Il vous faut un crâne jaune pour ouvrir cette porte.,Ez az ajtó egy sárga koponyával nyílik.,Ti serve una chiave-teschio gialla per aprire questa porta,このドアには イエロースカル が必要だ。,이 문을 열기 위해선 황색 해골이 필요합니다,Je hebt een gele schedel nodig om deze deur te openen.,Du trenger en gul hodeskalle for å åpne denne døren,"Potrzebujesz żółtej czaszki, aby otworzyć te drzwi",Você precisa de uma chave-crânio amarela para abrir esta porta,Precisas de uma chave crânio amarela para abrir esta porta,"Ai nevoie de un craniu galben pentru a activa -această ușă",Для открытия нужен жёлтый череп,Треба вам жута лобања да би отворили ова врата,Bu kapıyı açmak için sarı bir kafatasına ihtiyacın var. -,,Cast call names,,,,,,,,,,,,,,,,,,,,,,,, -Zombieman,CC_ZOMBIE,,,,Zombie,Zombie,Zombie,Ζόμπι,Zombiviro,Zombi,,Zombimies,Zombie,Zombi,Zombie Marine,ゾンビ兵,좀비맨,Zombie,Zombiemann,Zombie,Zumbi,Homem Zombie,Zombi,Зомби,Зомби,Zombi -Shotgun Guy,CC_SHOTGUN,a.k.a. (former human) sergeant,,,Seržant,Sergent,Schütze,Τύπος με ντουφέκι,Ĉaspafilulo,Tipo de Escopeta,Tipo de la escopeta,Haulikkohemmo,Type au Fusil,Őrmester,Zombie Sergente,ショットガンゾンビ,샷건 가이,Jachtgeweerkerel,Sersjant,Zombie-sierżant,Sargento Possuído,Tipo de Espingarda,Pușcaș,Зомби-сержант,Пумпераш,Çavuş -Heavy Weapon Dude,CC_HEAVY,a.k.a. former commando,,,Kulometčík,,MG-Schütze,Τύπος με βαρί όπλο,Pezarmilulo,Tipo de Armas Pesadas,Ametrallador,Raskasaseäijä,Type au Gros Flingue,Kommandós,Zombie Commando,ヘビーウェポンゾンビ,헤비 웨폰 듀드,Zwarewapenskerel,Maskingeværskyt,Ciężkozbrojny Zombie,Comando Possuído,Gajo das Armas Pesadas,Mitralior,Зомби-пулемётчик,Митраљезац,Ağır Silah Dostum -Imp,CC_IMP,,,,Čert,,Kobold,Διάβολος,Diableto,,,Piru,Diablotin,Tűzkobold,Imp,インプ,임프,,,Diablik,Diabrete,,Drac,Имп,Враг,İmp -Demon,CC_DEMON,,,,Démon,Dæmon,Dämon,Δαίμονας,Demono,Demonio,,Demoni,Démon,Démon,Pinky,デーモン,데몬,Demoon,Demon,Demon,Demônio,,Demon,Демон,Демон,İblis -Lost Soul,CC_LOST,,,,Ztracená duše,Fortabt sjæl,Verlorene Seele,Χαμένη Ξυχή,Perdita Animo,Alma Errante,,Kadonnut sielu,Ame Perdue,Kóbor lélek,Anima Errante,ロストソウル,로스트 소울,Verloren ziel,Fortapt sjel,Zaginiona Dusza,Alma Perdida,Alma Penada,Suflet Pierdut,Потерянная душа,Изгубљена душа,Kayıp Ruh -Cacodemon,CC_CACO,,,,Kakodémon,Cacodæmon,Cacodämon,Κακοδαίμονας,Kakodemono,Cacodemonio,,Kakodemoni,Cacodémon,Kakodémon,Cacodemone,カコデーモン,카코데몬,Cacodemoon,Kacodemon,Kakodemon,Cacodemônio,,Cacodemon,Какодемон,Какодемон,Cacodemon -Hell Knight,CC_HELL,,,,Pekelný rytíř,Helvedesridder,Höllenritter,Ιππότης της Κόλασης,Inferkavaliro,Caballero del Infierno,,Hornanritari,Chevalier Infernal,Pokollovag,Cavaliere Infernale,ヘルナイト,헬 나이트,Helleridder,Helvetesridder,Rycerz Piekła,Cavaleiro Infernal,Cavaleiro Infernal,Cavaler al Infernului,Рыцарь ада,Витез пакла,Cehennem Şövalyesi -Baron of Hell,CC_BARON,,,,Baron pekel,Helvedesbaron,Höllenbaron,Βαρώνος της Κολασης,Barono de Infero,Barón del Infierno,,Hornanparoni,Baron des Enfers,Pokolbáró,Barone Infernale,バロンオブヘル,바론 오브 헬,Baron des Hels,Helvetesbaron,Baron Piekła,Barão do Inferno,,Baron al Infernului,Барон ада,Барон пакла,Cehennem Baronu -Arachnotron,CC_ARACH,,,,,,,Αράχνοτρον,Elektraraneo,Aracnotrón,,Araknotroni,Arachnotron,Póktron,Arachnotron,アラクノトロン,아라크노트론,,,Arachnotron,Aracnotron,,Aracnotron,Арахнотрон,Паукотрон,Araknotron -Pain Elemental,CC_PAIN,,,,Živel trýzně,Smerteelementar,Elementarschmerz,Στοιχείομα του Πόνου,Doloro-Elementulo,Elemental del Dolor,,Kivun henki,Elémentaire de Douleur,Elemi Kín,Elementale del Dolore,ペインエレメンタル,페인 엘리멘탈,Smartelementaal,Smerte Elemental,Żywiołak Bólu,Elemental da Dor,,Elemental al Durerii,Элементаль боли,Елементал патње,Acı Elementi -Revenant,CC_REVEN,,,,Umrlec,Hævnen,Wiederauferstandener,Εκδικητής,Renaskitulo,,,Henkiinpalannut,Revenant,Kísértet,Revenant,レバナント,레버넌트,Wreker,Gjenganger,Zjawa,Insepulto,Renascido,Nemort,Ревенант,Повратник,Revenant -Mancubus,CC_MANCU,,,,Mankubus,,,Χοντρός,Mankubo,,,Mankubus,Mancube,Mankubusz,Mancubus,マンキュバス,맨큐버스,,,Antropokub,,,,Манкубус,Манкубус,Mancubus -Arch-Vile,CC_ARCH,,,,Veleběs,Ærkevile,Scheusal,Νεκρομάντις,Ĉef-Fiulo,,,Arkkihirvitys,Arche-vile,Ősármány,Arch-vile,アーチバイル,아크-바일,Aartsgedrocht,Erkefiende,Arcy-Podlec,Arquivil,,Abject,Архвиль,Арчвајл,Baş Aşağılık -The Spider Mastermind,CC_SPIDER,,,,Pavoučí velevůdce,Edderkoppen Mastermind,Der Spinnenmeister,Το Αραχνό Ιθύνων Νους,La Elektraraneo-Mastro,La Mente-Maestra Arácnida,,Hämähäkkiaivot,L'Araignée Commandante,Pókelme,L'Aracnomente Suprema,スパイダーマスターマインド,스파이더 마스터마인드,Het Spinnenmeesterbrein,Edderkopphjernen,Pajęczy Mistrz,A Aranha-Mestra,,Păianjen Maestru,Паук-предводитель,Паук-руководилац,Örümcek Beyni -The Cyberdemon,CC_CYBER,,,,Kyberdémon,Cyberdæmonen,Der Cyberdämon,Ο Cyber-δαίμονας,La Ciberdemono,El Ciberdemonio,,Kyberdemoni,Le Cyberdémon,A Kiberdémon,Il Cyberdemonio,サイバーデーモン,사이버데몬,Het Cyberdemoon,Kyberdemonen,Cyberdemon,O Ciberdemônio,,Ciberdemon,Кибердемон,Сајбердемон,Siber Şeytan -Our Hero,CC_HERO,,,,Náš hrdina,Vores helt,Unser Held,Ο ήρωας μας,Nia Heroo,Nuestro Héroe,,Sankarimme,Notre Héros,Hősünk,Il Nostro eroe,我らのヒーロー,우리들의 영웅,Onze held,Vår helt,Nasz bohater,Nosso herói,O Nosso Herói,Eroul Nostru,Наш герой,Наш херој,Bizim Kahramanımız -,,Actor tag names,,,,,,,,,,,,,,,,,,,,,,,, -Zombieman,FN_ZOMBIE,,,,Zombie,Zombie,Zombie,Ζόμπι,Zombiviro,Zombi,,Zombi,Zombie,Zombi,Zombie Marine,ゾンビ兵,좀비맨,Zombie,Zombiemannen,Zombie,Zumbi,Homem Zombie,Zombi,Зомби,Зомби,Zombi -Sergeant,FN_SHOTGUN,,,,Seržant,Sergent,Schütze,Λοχίας,Serĝento,Sargento,,Kersantti,Type au Fusil,Őrmester,Zombie Sergente,ゾンビ軍曹,샷건 가이,Sergeant,Sersjant,Zombie-sierżant,Sargento Possuído,Sargento,Sergent,Зомби-сержант,Водник,Çavuş -Chaingunner,FN_HEAVY,,,,Kulometčík,,MG-Schütze,Πολυβόλο Ζόμπι,Maŝinpafilisto,Ametrallador,,Konekiväärimies,Type au Gros Flingue,Kommandós,Zombie Commando,チェーンガンゾンビ,체인거너,Machinegeweerman,Maskingeværskyt,Ciężkozbrojny Zombie,Comando Possuído,Metrelhador,Mitralior,Зомби-пулемётчик,Митраљезац,Ağır Silah Dostum -Imp,FN_IMP,,,,Čert,,Kobold,Διάβολος,Diableto,,,Piru,Diablotin,Tűzkobold,Imp,インプ,임프,,,Diablik,Diabrete,,Drac,Имп,Враг,İmp -Demon,FN_DEMON,,,,Démon,Dæmon,Dämon,Δαίμονας,Demono,Demonio,,Demoni,Démon,Démon,Pinky,デーモン,데몬,Demoon,Demon,Demon,Demônio,,Demon,Демон,Демон,İblis -Spectre,FN_SPECTRE,,,,Přízrak,Spøgelse,Schemen,Φάντασμα,Fantomo,Espectro,,Haamu,,Lidérc,Spettro,スペクトル,스펙터,Spook,Spøkelse,Widmo,Espectro,,Spectru,Призрак,Авет,Hayalet -Lost Soul,FN_LOST,,,,Ztracená duše,Fortabt sjæl,Verlorene Seele,Χαμένη Ξυχή,Perdita Animo,Alma Errante,,Kadonnut sielu,Ame Perdue,Kóbor lélek,Anima Errante,ロストソウル,로스트 소울,Verloren Ziel,Fortapt sjel,Zaginiona Dusza,Alma Perdida,Alma Penada,Suflet Pierdut,Потерянная душа,Изгубљена душа,Kayıp Ruh -Cacodemon,FN_CACO,,,,Kakodémon,Cacodæmon,Cacodämon,Κακοδαίμονας,Kakodemono,Cacodemonio,,Kakodemoni,Cacodémon,Kakodémon,Cacodemone,カコデーモン,카코 데몬,Cacodemoon,Kacodemon,Kakodemon,Cacodemônio,,Cacodemon,Какодемон,Какодемон,Caco İblis -Hell Knight,FN_HELL,,,,Pekelný rytíř,Helvedesridder,Höllenritter,Ιππότης της Κόλασης,Inferkavaliro,Caballero del Infierno,,Hornanritari,Chevalier Infernal,Pokollovag,Cavaliere Infernale,ヘルナイト,헬 나이트,Helleridder,Helvetesridder,Rycerz Piekła,Cavaleiro Infernal,Cavaleiro Infernal,Cavaler al Infernului,Рыцарь ада,Витез пакла,Cehennem Şövalyesi -Baron of Hell,FN_BARON,,,,Baron pekel,Helvedesbaron,Höllenbaron,Βαρώνος της Κολασης,Barono de Infero,Barón del Infierno,,Hornanparoni,Baron des Enfers,Pokolbáró,Barone Infernale,バロンオブヘル,바론 오브 헬,Baron des Hels,Helvetesbaron,Baron Piekła,Barão do Inferno,,Baron al Infernului,Барон ада,Барон пакла,Cehennem Baronu -Arachnotron,FN_ARACH,,,,,,,Αράχνοτρον,Elektraraneo,Aracnotrón,,Araknotroni,,Póktron,Arachnotron,アラクノトロン,아라크노트론,,,,,,Aracnotron,Арахнотрон,Паукотрон,Araknotron -Pain Elemental,FN_PAIN,,,,Živel trýzně,Smerteelementar,Elementarschmerz,Στοιχείομα του Πόνου,Doloro-Elementulo,Elemental del Dolor,,Kivun henki,Elémentaire de Douleur,Elemi Kín,Elementale del Dolore,ペインエレメンタル,페인 엘리멘탈,Smartelementaal,Smerte Elemental,Żywiołak Bólu,Elemental da Dor,,Elemental al Durerii,Элементаль боли,Елементал патње,Acı Elementi -Revenant,FN_REVEN,,,,Umrlec,Hævnen,Wiederauferstandener,Εκδικητής,Renaskitulo,,,Henkiinpalannut,,Kísértet,Revenant,レバナント,레버넌트,Wreker,Gjenganger,Zjawa,Insepulto,Renascido,Nemort,Ревенант,Повратник,İskelet -Mancubus,FN_MANCU,,,,Mankubus,,,Χοντρός,Mankubo,,,Mankubus,Mancube,Mankubusz,Mancubus,マンキュバス,맨큐버스,,,Antropokub,,,,Манкубус,Манкубус,Mancubus -Arch-vile,FN_ARCH,,,,Veleběs,Ærkevile,Scheusal,Νεκρομάντις,Ĉef-fiulo,,,Arkkihirvitys,Arche-vile,Ősármány,Arch-vile,アーチバイル,아크-바일,Aartsgedrocht,Erkefiende,Arcy-Podlec,Arquivil,,Abject,Архвиль,Арчвајл,İğrençlik -Spider Mastermind,FN_SPIDER,,,,Pavoučí velevůdce,Edderkoppen Mastermind,Spinnenmeister,Αραχνό Ιθύνων Νους,Elektraraneo-Mastro,Mente-Maestra Arácnida,,Hämähäkkiaivot,L'Araignée Commandante,Pókelme,L'Aracnomente Suprema,スパイダーマスターマインド,스파이더 마스터마인드,Spinnenmeesterbrein,Edderkopphjerne,Pajęczy Mistrz,A Aranha-Mestra,,Păianjen Maestru,Паук-предводитель,Паук-руководилац,Örümcek Beyni -Cyberdemon,FN_CYBER,,,,Kyberdémon,Cyberdæmon,Cyberdämon,Cyber-δαίμονας,Ciberdemono,Ciberdemonio,,Kyberdemoni,Le Cyberdémon,Kiberdémon,Il Cyberdemonio,サイバーデーモン,사이버데몬,Cyberdemoon,Kyberdemon,Cyberdemon,O Ciberdemônio,,Ciberdemon,Кибердемон,Сајбердемон,Siber İblis -Nazi,FN_WOLFSS,,,,Nácek,,,Ναζιστής,Nazio,,,Natsi,,Náci,Nazista,ナチ兵,나치,,Nazist,Nazista,Nazista,Nazi,Nazist,Нацист,Нациста,Nazi -Dog,FN_DOG,,,,Pes,Hund,Hund,Σκύλος,Hundo,Perro,,Koira,Chien,Kutya,Cane,犬,개,Hond,Hund,Pies,Cão,,Câine,Собака,Пас,Köpek -Brass Knuckles,TAG_FIST,,,,Boxer,Messing knoer,Schlagringe,Γροθιά,Pugningo,Puño americano,Manopla (puño de acero),Nyrkkirauta,Poing Américain,Bokszer,Tirapugni ,ナックルダスター,너클,Boksbeugels,Knokejern,Kastety,Soco Inglês,Soqueira,Rozetă,Латунный кастет,Боксер,Pirinç Muşta -Chainsaw,TAG_CHAINSAW,,,,Motorová pila,Kædesav,Kettensäge,Αλλησοπρίονο,Ĉensegilo,Motosierra,,Moottorisaha,Tronçonneuse,Láncfűrész,Motosega,チェーンソウ,전기톱,Kettingzaag,Motorsag,Piła łańcuchowa,Motosserra,,Drujbă,Бензопила,Моторна тестера,Testere -Pistol,TAG_PISTOL,,,,Pistole,,Pistole,Πιστόλι,Pafileto,Pistola,,Pistooli,Pistolet,Pisztoly,Pistola,ピストル,권총,Pistool,,Pistolet,Pistola,,Pistol,Пистолет,Пиштољ,Tabanca -Shotgun,TAG_SHOTGUN,,,,Brokovnice,Haglgevær,Schrotflinte,Ντουφέκι,Kartoĉa fusilo,Escopeta,,Haulikko,Fusil à pompe,Sörétes Puska,Fucile,ショットガン,샷건,Jachtgeweer,Haglgevær,Strzelba,Espingarda,,Pușcă,Дробовик,Пумпарица,Av Tüfeği -Super Shotgun,TAG_SUPERSHOTGUN,,,,Superbrokovnice,Super-Haglgevær,Super-Schrotflinte,Διπλό Ντουφέκι,Dutuba fusilo,Superescopeta,,Superhaulikko,Super Fusil de chasse,Szuper Sörétes,Fucile a doppia canna ,スーパーショットガン,슈퍼 샷건,Superjachtgeweer,Super-Haglgevær,Super strzelba,Espingarda de cano duplo,,Super Pușcă,Супердробовик,Двоцевка,Süper Av Tüfeği -Chaingun,TAG_CHAINGUN,,,,Kulomet,Maskingevær,Maschinengewehr,Πολυβόλο,Maŝinpafilo,Ametralladora,,Gatling-kk,Mitrailleuse,Golyószóró,Mitragliatore a canne rotanti ,チェーンガン,체인건,Machinegeweer,Maskinpistol,Karabin maszynowy,Metralhadora,,Mitralieră rotativă,Пулемёт,Митраљез,Chaingun -Rocket Launcher,TAG_ROCKETLAUNCHER,,,,Raketomet,Raketkaster,Raketenwerfer,Πυραυλοβόλο,Misilpafilo,Lanzamisiles,,Sinko,Lance-Roquettes,Rakétavető,Lanciamissili,ロケットランチャー,로켓 런쳐,Raketwerper,Rakettkaster,Wyrzutnia rakiet,Lança-foguetes,Lança-Mísseis,Lansator de Rachete,Ракетомёт,Бацач ракета,Roket Fırlatıcı -Plasma Rifle,TAG_PLASMARIFLE,,,,Plazmová puška,Plasma riffel,Plasmagewehr,Πλάσμα Όπλο,Plasmo-pafilo,Fusil de plasma,,Plasmapyssy,Fusil à Plasma,Plazmafegyver,Fucile al Plasma ,プラズマライフル,플라즈마 라이플,Plasmageweer,Plasmagevær,Karabin plazmowy,Fuzil de Plasma,Pistola de Plasma,Pușcă cu Plasmă,Плазменная пушка,Плазма оружје,Plazma Tüfeği -BFG 9000,TAG_BFG9000,,,,,BFG 9000,,,,,,,,,,,,,,,,,,,ВЈП 9000, -Bullets,AMMO_CLIP,,,,Kulky,Kugler,Patronen,Σφαίρες,Kugloj,Balas,,Luodit,Balles,Töltények,Proiettili,銃弾,권총 탄약,Kogels,Kuler,Naboje,Balas,,Gloanțe,Пули,Меци,Kurşunlar -Shotgun Shells,AMMO_SHELLS,,,,Broky,Haglgeværpatroner,Schrotpatronen,Σφαίρες Ντουφεκιού,Kartoĉoj,Cartuchos de escopeta,,Haulikon patruunat,Cartouches,Sörétek,Cartucce per fucile,散弾シェル,샷건 탄약,Jachtgeweerkogels,Haglepatroner,Loftki,Cartuchos de Espingarda,,Proiectile pentru Pușcă,Патроны для дробовика,Патроне за пумпарицу,Av Tüfeği Fişekleri -Rockets,AMMO_ROCKETS,,,,Rakety,Raketter,Raketen,Πύραυλοι,Raketoj,Cohetes,,Raketit,Roquettes,Rakéták,Razzi,ロケット弾,로켓,Raketten,Raketter,Rakiety,Foguetes,Mísseis,Rachete,Ракеты,Ракете,Roketler -Energy Cells,AMMO_CELLS,,,,Energetické články,Energiceller,Energiezellen,Κύτταρα Ενέργιας,Energiĉeloj,Célula de energía,,Energia-akut,Cellules,Energiacellák,Batterie,エネルギーセル,에너지 셀,Energiecellen,Energiceller,Ogniwa energetyczne,Células de Energia,,Celule cu Energie,Энергобатареи,Енергетске ћелије,Enerji Hücreleri -,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,, -%o thought %g saw an arachnotron.,OB_STEALTHBABY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] arachnotrona.","%o troede, @[pro_dk] så en arachnotron.","%o dachte, ein Arachnotron zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Αραχνοτρόν.,"%o pensis, ke @[pro_eo] vidis elektraraneon.",%o creyó haber visto un aracnotrón.,,%o luuli nähneensä araknotronin.,%o a cru voir un Arachnotron.,"%o azt hitte, hogy látott egy póktront.",a %o sembrava di aver visto un arachnotron.,%o がアラクノトロンを見た気がした。,%o 은(는) 아라크노트론을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een arachnotron zag.,%o trodde @[pro_dk] så et arachnotron.,%o kątem oka zauważył@[ao_pl] arachnotrona.,%o achou que viu uma arachnotron.,,%o a crezut că %g a văzut un aracnotron.,Игрок %o краем глаза заметил арахнотрона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] паукотрона.,%o bir araknotron gördüğünü sandı. -%o thought %g saw an archvile.,OB_STEALTHVILE,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] veleběsa.","%o troede, @[pro_dk] så en ærkevile.","%o dachte, ein Scheusal zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Νεκρομάντη,"%o pensis, ke @[pro_eo] vidis ĉef-fiulon.",%o creyó haber visto un arch-vile.,,%o luuli nähneensä arkkihirvityksen,%o a cru voir un Arche-Vile.,"%o azt hitte, hogy látott egy ősármányt.",a %o sembrava di aver visto un Arch-Vile.,%o がアーチバイルを見た気がした。,%o 은(는) 아크-바일을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een aartsvijand zag.,%o trodde @[pro_dk] så en erkefiende.,%o kątem oka zauważył@[ao_pl] arcypodleca.,%o achou que viu um arquivil.,,%o a crezut că %g a văzut un abject.,Игрок %o краем глаза заметил архвиля.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] једног арчвајла.,%o bir iğrençlik gördüğünü sandı. -%o thought %g saw a Baron of Hell.,OB_STEALTHBARON,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] barona pekel.","%o troede, @[pro_dk] så en helvedesbaron.","%o dachte, einen Höllenbaron zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Βαρώνο της Κόλασης.,"%o pensis, ke @[pro_eo] vidis Baronon de Infero.",%o creyó haber visto un Barón del Infierno.,,%o luuli nähneensä hornanparonin.,%o a cru voir un Baron des enfers.,"%o azt hitte, hogy látott egy pokolbárót.",a %o sembrava di aver visto un Barone Infernale.,%o がバロンを見た気がした。,%o 은(는) 바론 오브 헬을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een baron van de Hel zag.,%o trodde @[pro_dk] så en helvetesbaron,%o kątem oka zauważył@[ao_pl] Barona Piekła.,%o achou que viu um barão do inferno.,,%o a crezut că %g a văzut un Baron al Infernului.,Игрок %o краем глаза заметил барона ада.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] барона пакла.,%o bir Cehennem Baronu gördüğünü sandı. -%o thought %g saw a cacodemon.,OB_STEALTHCACO,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] kakodémona.","%o troede, @[pro_dk] så en cacodemon.","%o dachte, einen Cacodämonen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Κακοδαίμονα.,"%o pensis, ke @[pro_eo] vidis kakodemonon.",%o creyó haber visto un cacodemonio.,,%o luuli nähneensä kakodemonin.,%o a cru voir un Cacodémon.,"%o azt hitte, hogy látott egy kakodémont.",a %o sembrava di aver visto un cacodemone.,%o がカコデーモンを見た気がした。,%o 은(는) 카코데몬을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een cacodemon zag.,%o trodde @[pro_dk] så en kakodemon.,%o kątem oka zauważył@[ao_pl] kakodemona.,%o achou que viu um cacodemônio.,,%o a crezut că %g a văzut un cacodemon.,Игрок %o краем глаза заметил какодемона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] какодемона.,%o bir caco iblisi gördüğünü sandı. -%o thought %g saw a chaingunner.,OB_STEALTHCHAINGUY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] kulometčíka.","%o troede, @[pro_dk] så en chaingunner.","%o dachte, einen MG-Schützen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Ζόμπι με ένα πολυβόλο.,"%o pensis, ke @[pro_eo] vidis maŝinpafiliston.",%o creyó haber visto un ametrallador.,,%o luuli nähneensä konekiväärimiehen.,%o a cru voir un mitrailleur.,"%o azt hitte, hogy látott egy kommandóst.",a %o sembrava di aver visto uno zombie commando.,%o がチェインガンナーを見た気がした。,%o 은(는) 체인거너를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een zware wapens kerel zag.,%o trodde @[pro_dk] så en maskingeværskyt.,%o kątem oka zauważył@[ao_pl] ciężkozbrojnego zombie.,%o achou que viu um comando possuído.,%o achou que viu um metrelhador.,%o a crezut că %g a văzut un mitralior.,Игрок %o краем глаза заметил пулемётчика.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] митраљезца.,%o bir ağır silah dostu gördüğünü sandı. -%o thought %g saw a demon.,OB_STEALTHDEMON,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] démona.","%o troede, @[pro_dk] så en dæmon.","%o dachte, einen Dämonen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα δαίμονα.,"%o pensis, ke @[pro_eo] vidis demonon.",%o creyó haber visto un demonio.,,%o luuli nähneensä demonin.,%o a cru voir un démon.,"%o azt hitte, hogy látott egy démont.",a %o sembrava di aver visto un demone.,%o がデーモンを見た気がした。,%o 은(는) 데몬을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een demon zag.,%o trodde @[pro_dk] så en demon.,%o kątem oka zauważył@[ao_pl] demona.,%o achou que viu um demônio.,,%o a crezut că %g a văzut un demon.,Игрок %o краем глаза заметил демона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] демона.,%o bir iblis gördüğünü sandı. -%o thought %g saw a Hell Knight.,OB_STEALTHKNIGHT,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] rytíře pekel.","%o troede, @[pro_dk] så en helvedesridder.","%o dachte, einen Höllenritter zu sehen.",@[art_gr] %o νόμιζε οτι είδε έναν Ιππότη της Κόλασης.,"%o pensis, ke @[pro_eo] vidis Inferkavaliron.",%o creyó haber visto un Caballero del Infierno.,,%o luuli nähneensä hornanritarin.,%o a cru voir un chevalier infernal.,"%o azt hitte, hogy látott egy pokollovagot.",a %o sembrava di aver visto un Cavaliere Infernale.,%o がヘルナイトを見た気がした。,%o 은(는) 헬 나이트를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een hel ridder zag.,%o trodde @[pro_dk] så en helvetesridder.,%o kątem oka zauważył@[ao_pl] Rycerza Piekła.,%o achou que viu um cavaleiro infernal.,%o achou que viu um cavaleiro infernal.,%o a crezut că %g a văzut un Cavaler al Infernului.,Игрок %o краем глаза заметил рыцаря ада.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] витеза пакла.,%o bir Cehennem Şövalyesi gördüğünü sandı. -%o thought %g saw an imp.,OB_STEALTHIMP,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] čerta.","%o troede, @[pro_dk] så en imp.","%o dachte, einen Kobold zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Διάβολο.,"%o pensis, ke @[pro_eo] vidis diableton.",%o creyó haber visto un imp.,,%o luuli nähneensä pirun.,%o a cru voir un diablotin.,"%o azt hitte, hogy látott egy tűzkoboldot.",a %o sembrava di aver visto un imp.,%o がインプを見た気がした。,%o 은(는) 임프를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een imp zag.,%o trodde @[pro_dk] så en imp.,%o kątem oka zauważył@[ao_pl] diablika.,%o achou que viu um diabrete.,,%o a crezut că %g a văzut un drac.,Игрок %o краем глаза заметил импа.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] врага.,%o bir impus gördüğünü sandı. -%o thought %g saw a mancubus.,OB_STEALTHFATSO,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] mankuba.","%o troede, @[pro_dk] så en mankubus.","%o dachte, einen Mancubus zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Χοντρό.,"%o pensis, ke @[pro_eo] vidis mankubon.",%o creyó haber visto un mancubus.,,%o luuli nähneensä mankubuksen.,%o a cru voir un mancube.,"%o azt hitte, hogy látott egy mankubuszt.",a %o sembrava di aver visto un mancubus.,%o がマンキュバスを見た気がした。,%o 은(는) 맨큐버스를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een mancubus zag.,%o trodde @[pro_dk] så en mancubus.,%o kątem oka zauważył@[ao_pl] antropokuba.,%o achou que viu um mancubus.,,%o a crezut că %g a văzut un mancubus.,Игрок %o краем глаза заметил манкубуса.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] манкубуса.,%o bir mancubus gördüğünü sandı. -%o thought %g saw a revenant.,OB_STEALTHUNDEAD,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] umrlce.","%o troede, @[pro_dk] så en hævnen.","%o dachte, einen Wiederauferstandenen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Εκδικητή.,"%o pensis, ke @[pro_eo] vidis renaskitulon.",%o creyó haber visto un revenant.,,%o luuli nähneensä henkiinpalanneen.,%o a cru voir un revenant.,"%o azt hitte, hogy látott egy kísértetet.",a %o sembrava di aver visto un revenant.,%o がレバナントを見た気がした。,%o 은(는) 레버넌트를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een wraakzuchtige zag.,%o trodde @[pro_dk] så en gjenganger.,%o kątem oka zauważył@[ao_pl] zjawę.,%o achou que viu um insepulto.,%o achou que viu um renascido.,%o a crezut că %g a văzut un nemort.,Игрок %o краем глаза заметил ревенанта.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] повратника.,%o bir iskelet gördüğünü sandı. -%o thought %g saw a sergeant.,OB_STEALTHSHOTGUNGUY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] seržanta.","%o troede, @[pro_dk] så en sergent.","%o dachte, einen Schützen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Λοχία.,"%o pensis, ke @[pro_eo] vidis serĝenton.",%o creyó haber visto un sargento.,,%o luuli nähneensä kersantin.,%o a cru voir un type au fusil.,"%o azt hitte, hogy látott egy őrmestert.",a %o sembrava di aver visto un zombie sergente.,%o が軍曹を見た気がした。,%o 은(는) 샷건 가이를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een jachtgeweer kerel zag.,%o trodde @[pro_dk] så en sersjant.,%o kątem oka zauważył@[ao_pl] zombie-sierżanta.,%o achou que viu um sargento possuído.,%o achou que viu um sargento.,%o a crezut că %g a văzut un sergent.,Игрок %o краем глаза заметил сержанта.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] водника.,%o bir çavuş gördüğünü sandı. -%o thought %g saw a zombieman.,OB_STEALTHZOMBIE,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] zombíka.","%o troede, @[pro_dk] så en zombie.","%o dachte, einen Zombie zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Ζόμπι.,"%o pensis, ke @[pro_eo] vidis zombiviron.",%o creyó haber visto un zombi.,,%o luuli nähneensä zombin.,%o a cru voir un zombie.,"%o azt hitte, hogy látott egy zombit.",a %o sembrava di aver visto uno zombie marine.,%o がゾンビ兵を見た気がした。,%o 은(는) 좀비맨을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een zombie zag.,%o trodde @[pro_dk] så en zombiemann.,%o kątem oka zauważył@[ao_pl] zombie.,%o achou que viu um zumbi.,%o achou que viu um zombie.,%o a crezut că %g a văzut un zombi.,Игрок %o краем глаза заметил зомби.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] зомбија.,%o bir zombi gördüğünü sandı. -%o was punched by a revenant.,OB_UNDEADHIT,,,,%o byl@[ao_cs] udeřen@[ao_cs] umrlcem.,%o blev slået af en genfødt.,%o wurde von einem Wiederauferstandenen K.O geschlagen.,@[art_gr] %o έφαγε μια μπουνία απο έναν Εκδικητή.,%o estis pugnita de renaskitulo.,%o fue golpead@[ao_esp] por un revenant.,,%o joutui henkiinpalanneen lyömäksi.,%o s'est pris@[e_fr] une raclée de la part d'un revenant.,%o-t kiütötte egy kísértet.,%o è stato colpito dal pugno di un revenant.,%o はレバナントに殴られた。,%o 은(는) 레버넌트에게 맞아 죽었다.,%o werd geslagen door een wraakzuchtige.,%o ble slått av en gjenganger.,%o został@[ao_pl] uderzon@[adj_pl] przez zjawę.,%o foi socad@[ao_ptb] por um insepulto.,%o foi socad@[ao_ptb] por um renascido.,%o a primit un pumn de la un nemort.,Игрока %o ударил ревенант.,%o је ударен@[adj_1_sr] од стане повратника.,%o bir iskelet tarafından yumruklandı. -%o was slashed by an imp.,OB_IMPHIT,,,,%o byl@[ao_cs] rozsápán@[ao_cs] čertem.,%o blev skåret ned af en spøgelse.,%o wurde von einem Kobold gekratzt.,@[art_gr] %o κόπηκε απο ενα Διάβολο.,%o estis tranĉvundita de diableto.,%o fue desgarrad@[ao_esp] por un imp.,,%o joutui pirun sivaltamaksi.,%o a été lacéré@[e_fr] par un diablotin.,%o-t széttépte egy tűzkobold.,%o è stato squarciato da un imp.,%o はインプに切り裂かれた。,%o 은(는) 임프에게 찢겨 죽었다.,%o werd gesneden door een imp.,%o ble kuttet av en imp.,%o został@[ao_pl] rozcięt@[adj_pl] przez diablika.,%o foi dilacerad@[ao_ptb] por um diabrete.,,%o a fost zgâriat de un drac.,Игрока %o расцарапал имп.,Играча %o је пресеко враг.,%o bir imp tarafından kesildi. -%o got too close to a cacodemon.,OB_CACOHIT,,,,%o se dostal@[ao_cs] moc blízko ke kakodémonovi.,%o kom for tæt på en cacodæmon.,%o kam dem Cacodämonen zu nahe.,@[art_gr] %o ήτανε πολυ κοντά σε ένα Κακοδαίμονα.,%o tro proksimiĝis al kakodemono.,%o se acercó demasiado a un cacodemonio.,,%o meni liian lähelle kakodemonia.,%o s'est approché@[e_fr] trop près d'un Cacodémon.,%o túl közel ment egy kakodémonhoz.,%o si è avvicinato troppo a un cacodemone.,%o はカコデーモンに近づきすぎた。,%o 은(는) 카코데몬과 가까웠다.,%o kwam te dicht bij een cacodemon.,%o kom for nær en kakodemon.,%o pod@[irreg_1_pl] zbyt blisko do kakodemona.,%o chegou muito perto de um cacodemônio.,,%o s-a apropiat prea mult de un cacodemon.,Игрок %o слишком сблизился с какодемоном.,%o се превише приближи@[ao_1_sr] какодемону.,%o bir caco iblisiyle çok yakınlaştı. -%o was bit by a demon.,OB_DEMONHIT,,,,%o byl@[ao_cs] rozkousán@[ao_cs] démonem.,%o blev bidt af en dæmon.,%o wurde von einem Dämonen gebissen.,@[art_gr] %o δαγκόθηκε απο ένα Δαίμονα.,%o estis mordita de demono.,%o fue mordid@[ao_esp] por un demonio.,,%o joutui demonin puremaksi.,%o a été mordu@[e_fr] par un démon.,%o-t megharapta egy démon.,%o è stato sbranato da un demone.,%o はデーモンに噛まれた。,%o 은(는) 데몬에게 물렸다.,%o werd gebeten door een demon.,%o ble bitt av en demon.,%o wpada w szczęki demona.,%o foi mordid@[ao_ptb] por um demônio.,,%o a fost mușcat de un demon.,Игрока %o укусил демон.,Играча %o је ујео демон.,%o bir iblis tarafından ısırıldı. -%o was eaten by a spectre.,OB_SPECTREHIT,,,,%o byl@[ao_cs] sežrán@[ao_cs] přízrakem.,%o blev spist af et imp.,%o wurde von dem Schemen gefressen.,Ένα φάντασμα έφαγε @[pro_gr] %o.,%o estis manĝita de fantomo.,%o fue devorad@[ao_esp] por un espectro.,,%o joutui haamun syömäksi.,%o a été dévoré@[e_fr] par un spectre.,%o-t felfalta egy lidérc.,%o è stato divorato da uno spettro.,%o はスペクトルに喰われた。,%o 은(는) 스펙터에게 잡아먹혔다.,%o werd opgegeten door een spook.,%o ble spist av et spøkelse.,%o został@[ao_pl] zjedzon@[adj_pl] przez widmo.,%o foi devorad@[ao_ptb] por um espectro.,,%o a fost mâncat de un spectru.,Игрока %o сожрал призрак.,Играча %o је појео авет.,%o bir hayalet tarafından yenildi. -%o was ripped open by a Baron of Hell.,OB_BARONHIT,,,,%o byl@[ao_cs] rozčtvrcen@[ao_cs] baronem pekel.,%o blev flået op af en helvedesbaron.,%o wurde von dem Höllenbaron aufgerissen.,@[art_gr] %o σχίστηκε απο εναν Βαρώνο της Κόλασης.,%o estis disŝirigita de Barono de Infero.,%o quedó hech@[ao_esp] trizas por un Barón del Infierno.,,%o joutui hornanparonin auki repimäksi.,%o a été déchiré@[e_fr] par un Baron des Enfers.,%o-t széttépte egy pokolbáró.,%o è stato scoperchiato da un Barone dell'Inferno.,%o はバロンオブヘルに体を抉じ開けられた。,%o 은(는) 바론 오브 헬에게 뜯겨 죽었다.,%o werd opengereten door een Baron van de hel.,%o ble revet opp av en helvetesbaron.,%o został@[ao_pl] rozerwan@[adj_pl] przez Barona Piekła.,%o foi rasgad@[ao_ptb] por um Barão do Inferno.,%o foi desventrad@[ao_ptb] por um Barão do Inferno.,%o a fost deschis pe viu de un Baron al Infernului.,Игрока %o разорвал барон ада.,%o је поцеп@[adj_2_sr] од стране барон пакла.,%o bir Cehennem Baronu tarafından parçalandı. -%o was gutted by a Hell Knight.,OB_KNIGHTHIT,,,,%o byl@[ao_cs] vykuchán@[ao_cs] rytířem pekel.,%o blev udtaget af en helvedesridder.,%o wurde von dem Höllenritter ausgenommen.,@[art_gr] %o ξεκοιλιάστηκε απο έναν Ιππότη της Κόλασης.,%o estis senintestigita de Inferkavaliro.,%o fue destripad@[ao_esp] por un Caballero del Infierno.,,%o joutui hornanritarin perkaamaksi.,%o a été étripé@[e_fr] par un un chevalier infernal.,%o-t kibelezte egy pokollovag.,%o è stato sbudellato da un Cavaliere dell'Inferno.,%o はヘルナイトに内臓を抉られた。,%o 은(는) 헬 나이트에게 도륙당했다.,%o werd gestript door een hel ridder.,%o ble sløyet av en helvetesridder.,%o został@[ao_pl] wypatroszon@[adj_pl] przez Rycerza Piekła.,%o foi estripad@[ao_ptb] por um Cavaleiro Infernal.,%o foi estripad@[ao_ptb] por um Cavaleiro Infernal.,%o a fost măcelărit de un Cavaler al Infernului.,Игрока %o распотрошил рыцарь ада.,Играча %o је унаказио витез пакла.,%o bir Cehennem Şövalyesi tarafından parçalandı. -%o was killed by a zombieman.,OB_ZOMBIE,,,,%o byl@[ao_cs] zabit@[ao_cs] zombíkem.,%o blev dræbt af en zombie.,%o wurde von einem Zombie getötet.,@[art_gr] %o σκοτώθηκε απο ένα Ζόμπι.,%o estis mortigita de zombiviro.,%o fue asesinad@[ao_esp] por un zombi.,,%o joutui zombin tappamaksi.,%o a été tué@[e_fr] par un zombie.,%o-t megölte egy zombi.,%o è stato ucciso da uno zombie marine.,%o はゾンビ兵に殺された。,%o 은(는) 좀비맨에게 죽었다.,%o werd gedood door een zombie.,%o ble drept av en zombiemann.,%o został@[ao_pl] zabit@[adj_pl] przez zombie.,%o foi mort@[ao_ptb] por um zumbi.,%o foi mort@[ao_ptb] por um zombie.,%o a fost omorât de un zombi.,Игрока %o убил зомби.,%o је убијен@[adj_1_sr] од стране зомбија.,%o bir zombi tarafından öldürüldü. -%o was shot by a sergeant.,OB_SHOTGUY,,,,%o byl@[ao_cs] zastřelen@[ao_cs] seržantem.,%o blev skudt af en sergent.,%o wurde von einem Schützen erschossen.,Ένας Λοχίας πυροβόλησε @[pro_gr] %o.,%o estis pafita de serĝento.,%o fue fusilad@[ao_esp] por un sargento.,,%o joutui kersantin ampumaksi.,%o s'est fait flinguer par un type au fusil.,%o-t lelőtte egy őrmester.,%o è sato impallinato da uno zombie sergente.,%o はゾンビ軍曹に撃たれた。,%o 은(는) 서전트에게 총을 맞았다.,%o werd neergeschoten door een sergeant.,%o ble skutt av en sersjant.,%o został@[ao_pl] zastrzelon@[adj_pl] przez zombie-sierżanta.,%o levou um tiro de um sargento possuído.,,%o a fost împușcat de un sergent.,Игрока %o застрелил сержант.,Играча %o је погодио водник.,%o bir çavuş tarafından vuruldu. -%o was incinerated by an archvile.,OB_VILE,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] veleběsem.,%o blev brændt af en ærkevile.,%o wurde von einem Scheusal verbrannt.,@[art_gr] %o αποτεφρώθηκε απο ένα Νεκρομάντη.,%o estis cindrigita de ĉef-fiulo.,%o fue calcinad@[ao_esp] por un arch-vile.,,%o joutui arkkihirvityksen kärventämäksi.,%o a été incinéré@[e_fr] par un Arche-Vile.,%o-t megpörkölte egy ősármány.,%o è stato incenerito da un arch-vile.,%o はアーチバイルに焼き尽くされた。,%o 은(는) 아크-바일에 의해 소각되었다.,%o werd verbrand door een aartsvijand.,%o ble brent av en erkefiende.,%o został@[ao_pl] spalon@[adj_pl] przez arcypodleca.,%o foi incinerad@[ao_ptb] pelo arquivil.,,%o a fost incinerat de un abject.,Игрока %o заживо сжёг архвиль.,Играча %o је запалио арчвајл.,%o bir iğrençlik tarafından yakıldı. -%o couldn't evade a revenant's fireball.,OB_UNDEAD,,,,%o se nevyhnul@[ao_cs] umrlčí ohnivé kouli.,%o kunne ikke undvige en ildkugle fra en hævnen.,%o konnte dem Feuerball des Wiederauferstandenen nicht ausweichen.,@[art_gr] %o δέν μπορούσε να αποφείγει τον πύραυλο ενός Εκδικητή.,%o ne povis eviti fajrobulon de renaskitulo.,%o no pudo esquivar la bola de fuego de un revenant.,,%o ei kyennyt väistämään henkiinpalanneen tulipalloa.,%o n'a pas réussi à esquiver un missile de revenant.,%o nem tudta kivédeni egy kísértet tűzgolyóját.,%o non ha potuto evitare il missile di un revenant.,%o はレバナントのファイアボールを回避できなかった。,%o 은(는) 레버넌트의 화염구를 피하지 못했다.,%o kon de vuurbal van een wraakzuchtige niet ontwijken.,%o klarte ikke å unngå en gjengangers ildkule.,%o nie udaje się uniknąć pocisku od zjawy.,%o não conseguiu desviar do míssil do insepulto.,%o não conseguiu desviar do míssil do renascido.,%o n-a putut scăpa de mingea de foc a nemortului.,Игрок %o не успел увернуться от снаряда ревенанта.,%o није мог@[ao_2_sr] да избегне повратникову пламену куглу.,%o bir iskeletin ateş topundan kaçamadı. -%o was squashed by a mancubus.,OB_FATSO,,,,%o byl@[ao_cs] rozmačkán@[ao_cs] mankubem.,%o blev knust af en mankubus.,%o wurde von einem Mancubus plattgemacht.,@[art_gr] %o λιόθηκε απο έναν Χοντρό.,%o estis dispremita de mankubo.,%o fue pulverizad@[ao_esp] por un mancubus.,,%o joutui mankubuksen liiskaamaksi.,%o s'est fait@[e_fr] aplatir par un Mancube.,%o-t szétlapította egy mankubusz.,%o è stato disintegrato da un mancubus.,%o はマンキュバスに潰された。,%o 은(는) 맨큐버스에게 짓이겨졌다.,%o werd verpletterd door een mancubus.,%o ble knust av en mancubus.,%o został@[ao_pl] zmiażdżon@[adj_pl] przez antropokuba.,%o foi esmagad@[ao_ptb] por um mancubus.,,%o a fost strivit de un mancubus.,Игрока %o раздавил манкубус.,Играча %o је изгњечио манкубус.,%o bir mancubus tarafından ezildi. -%o was perforated by a chaingunner.,OB_CHAINGUY,,,,%o byl@[ao_cs] prostřelen@[ao_cs] kulometčíkem.,%o blev perforeret af en chaingunner.,%o wurde von einem MG-Schützen perforiert.,@[art_gr] %o εκτελέστικε απο ένα Ζόμπι με ένα πολυβόλο.,%o estis truigadita de maŝinpafilisto.,%o fue perforad@[ao_esp] por un ametrallador.,,%o joutui konekiväärimiehen rei'ittämäksi.,%o a été perforé@[e_fr] par un mitrailleur.,%o-t szitává lőtte egy kommandós.,%o è stato perforato da uno zombie commando.,%o はチェインガンナーに蜂の巣にされた。,%o 은(는) 체인거너에 의해 벌집이 됐다.,%o werd geperforeerd door een zware wapens kerel.,%o ble perforert av en chaingunner.,%o został@[ao_pl] przedziurawion@[adj_pl] przez ciężkozbrojnego zombie.,%o foi perfurad@[ao_ptb] por um comando possuído.,%o foi perfurad@[ao_ptb] por um metrelhador.,%o a fost perforat de un mitralior.,Игрока %o продырявил пулемётчик.,Играча %o је изрешетао митраљезац.,%o bir ağır silah tarafından delindi. -%o was spooked by a lost soul.,OB_SKULL,,,,%o se lekl@[ao_cs] ztracené duše.,%o blev skræmt af en fortabt sjæl.,%o wurde von einer Verlorenen Seele heimgesucht.,Μια Χαμένη Ξυχή φόβησε @[pro_gr] %o.,%o estis timigita de perdita animo.,%o se murió de miedo ante un alma errante.,,%o joutui kadonneen sielun säikäyttämäksi.,%o s'est fait@[e_fr] surprendre par une âme perdue.,%o-t halálra ijesztette egy kóbor lélek.,%o è stato spaventato a morte da un'Anima Errante.,%o はロストソウルにビビらされた。,%o 은(는) 로스트 소울을 보고 깜짝 놀랐다.,%o werd bang gemaakt door een verloren ziel.,%o ble skremt av en fortapt sjel.,%o został@[ao_pl] przestraszon@[adj_pl] przez zaginioną duszę.,%o se assustou com uma alma perdida.,%o se assustou com uma alma penada.,%o a fost speriat de un suflet pierdut.,Игрок %o запуган до смерти потерянной душой.,%o је уплашен@[adj_1_sr] од изгубљене душе.,%o kayıp bir ruh tarafından korkutuldu. -%o was burned by an imp.,OB_IMP,,,,%o byl@[ao_cs] spálen@[ao_cs] čertem.,%o blev brændt af en spøgelse.,%o wurde von einem Kobold verbrannt.,@[art_gr] %o κάικε απο έναν Διάβολο.,%o estis bruligita de diableto.,%o fue incendiad@[ao_esp] por un imp.,,%o joutui pirun polttamaksi.,%o brûlé@[e_fr] par un diablotin.,%o-t szénné égette egy tűzkobold.,%o è stato bruciato da un imp.,%o はインプに焼かれた。,%o 은(는) 임프에게 불태워졌다.,%o werd verbrand door een imp.,%o ble brent av en imp.,%o został@[ao_pl] spalon@[adj_pl] przez diablika.,%o foi queimad@[ao_ptb] por um diabrete.,,%o a fost ars de un demon.,Игрока %o сжёг имп.,%o је изгорен@[adj_1_sr] од стране врага.,%o bir imp tarafından yakıldı. -%o was smitten by a cacodemon.,OB_CACO,,,,%o byl@[ao_cs] udeřen@[ao_cs] kakodémonem.,%o blev ramt af en cacodæmon.,%o wurde von einem Cacodämonen gequält.,@[art_gr] %o καίκε απο έναν Κακοδαίμονα.,%o estis venkobatita de kakodemono.,%o fue aniquilad@[ao_esp] por un cacodemonio.,,%o joutui kakodemonin iskemäksi.,%o a été terrassé@[e_fr] par un Cacodémon.,%o-ra lesújtott egy kakodémon.,%o è stato abbattuto da un cacodemone.,%o はカコデーモンに裁きを受けた。,%o 은(는) 카코데몬에게 엄습 당했다.,%o werd geslagen door een cacodemon.,%o ble slått av en kakodemon.,%o został@[ao_pl] porażon@[adj_pl] przez kakodemona.,%o foi golpead@[ao_ptb] por um cacodemônio.,,%o a fost lovit de un cacodemon.,Игрока %o поразил какодемон.,Играча %o је ударио какодемон.,%o bir caco iblisi tarafından vuruldu. -%o was bruised by a Baron of Hell.,OB_BARON,,,,%o byl@[ao_cs] pomačkán@[ao_cs] baronem pekel.,%o blev såret af en helvedesbaron.,%o wurde von einem Höllenbaron geröstet.,@[art_gr] %o γρατζουνήθηκε απο ένα Βαρώνο της Κόλασης.,%o estis kontuzita de Barono de Infero.,%o fue vapulead@[ao_esp] por un Barón del Infierno.,,%o joutui hornanparonin ruhjomaksi.,%o a été démoli@[e_fr] par un Baron des Enfers.,%o-t összezúzta egy pokolbáró.,%o è stato scorticato da un Barone Infernale.,%o はバロンオブヘルに痛めつけられた。,%o 은(는) 바론 오브 헬에게 상처받았다.,%o werd gekneusd door een baron van de hel.,%o ble forslått av en helvetesbaron.,%o został@[ao_pl] stłuczon@[adj_pl] Barona Piekła.,%o foi ferid@[ao_ptb] por um Barão do Inferno.,,%o a fost contuzionat de un Baron al Infernului.,Игрок %o зашиблен бароном ада.,%o је мод@[adj_3_sr] због барона пакла.,%o bir Cehennem Baronu tarafından yaralandı. -%o was splayed by a Hell Knight.,OB_KNIGHT,,,,%o byl@[ao_cs] rozpůlen@[ao_cs] rytířem pekel.,%o blev splejset af en helvedesridder.,%o wurde von einem Höllenritter gebraten.,@[art_gr] %o απλώθηκε απο έναν Ιππότη της Κόλασης,%o estis bisekcita de Inferkavaliro.,%o fue partid@[ao_esp] en dos por un Caballero del Infierno.,,%o joutui hornanritarin repimäksi.,%o a été éclaté@[e_fr] par un chevalier infernal.,%o-t kilapította egy pokollovag.,%o è stato squartato da un Cavaliere Infernale.,%o はヘルナイトにバラ撒かれた。,%o 은(는) 헬 나이트에게 갈라졌다.,%o werd gespierd door een hel ridder.,Jeg ble sprettet opp av en helvetesridder.,%o został@[ao_pl] rozcapierzon@[adj_pl] przez Rycerza Piekła.,%o foi espalmad@[ao_ptb] por um Cavaleiro Infernal.,%o foi espalmad@[ao_ptb] por um Cavaleiro Infernal.,%o a fost scrântit de un Cavaler al Infernului.,Игрока %o распластал рыцарь ада.,%o је раширен@[adj_1_sr] због витеза пакла.,%o bir Cehennem Şövalyesi tarafından yere serildi. -%o stood in awe of the spider demon.,OB_SPIDER,,,,%o zůstal@[ao_cs] stát v úžasu před pavoučím démonem.,%o stod i ærefrygt for edderkoppedæmonen.,%o stand in Ehrfurcht vor dem Spinnendämon.,@[art_gr] %o στάθηκε με δέος μπροστά στόν αραχνοδαίμονα.,%o staris mirigita antaŭ la aranedemono.,%o no tuvo oportunidad contra la mente-maestra arácnida.,,%o kunnioitti syvästi hämähäkkidemonia,%o est resté pris@[e_fr] d'admiration devant le Démon Arachnéen.,%o halálra ijedt a Pókelme.,%o è stato soggiogato dal Ragno demoniaco.,%o はスパイダーデーモンに恐れをなした。,%o 은(는) 거미악마의 무자비함을 느꼈다.,%o stond in ontzag voor de spindemon.,%o sto i ærefrykt for edderkoppdemonen.,%o podziwiał@[ao_pl] pajęczego mistrza.,%o ajoelhou-se em frente da Aranha-Mestra.,,%o a stat înfricoșat în fața păianjenului maestru.,Игрок %o стоял в восторге перед пауком-предводителем.,%o се смрзну@[ao_1_sr] у очарању паук-руководилаца.,%o örümcek iblisin karşısında huşu içinde durdu. -%o let an arachnotron get %h.,OB_BABY,,,,%o se nechal@[ao_cs] dostat arachnotronem.,%o blev sprængt af en arachnotron.,%o ließ sich von einem Arachnotron erledigen.,@[art_gr] %o άφησε ένα Αράχνοτρον να @[pro_gr] σκοτώσει.,%o lasis elektraraneon venki @[pro_eo]n.,%o fue alcanzad@[ao_esp] por un aracnotrón.,,%o antoi anaktrotronin saada hänet.,%o a laissé un arachnotron l'avoir@[e_fr].,"%o hagyta, hogy elkapja egy póktron.",%o ha permesso che un arachnotron l'uccidesse.,%o が アラクノトロンに討ち取られた。,%o 은(는) 아라크노트론이 %o를(을) 죽이도록 놔두었다.,%o werd gedood door een arachnotron,%o ble sprengt av et arachnotron.,%o pozwolił@[ao_pl] arachnotronowi się do siebie dobrać.,%o foi peg@[ao_ptb] por uma arachnotron.,%o foi apanhad@[ao_ptb] por uma arachnotron.,%o s-a lăsat prins de un aracnotron.,Игрок %o дал себя на откуп арахнотрону.,%o је допусти@[ao_1_sr] да паукотрон дође до %h.,%o bir araknotronun onu yakalamasına izin verdi. -%o was splattered by a cyberdemon.,OB_CYBORG,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] na kaši kyberdémonem.,%o blev splattet af en cyberdæmon.,%o wurde von einem Cyberdämon zerfetzt.,@[art_gr] %o έσκασε απο ένα Cyber-δαίμονα.,%o estis disŝprucigita de ciberdemono.,%o fue hech@[ao_esp] pedazos por un ciberdemonio.,,%o joutui kyberdemonin yltympäri roiskimaksi.,%o a été pulvérisé@[e_fr] par un Cyberdémon.,%o-t cafatokra tépték a kiberdémon rakétái.,%o è stato spiaccicato da un Cyberdemone.,%o はサイバーデーモンにバラバラにされた。,%o 은(는) 사이버데몬에 의해 산산조각이 났다.,%o werd gespetterd door een cyberdemon.,%o ble sprutet av en kyberdemon.,%o został@[ao_pl] rozbryzgan@[adj_pl] przez cyberdemona.,%o foi arrebentad@[ao_ptb] pelo Ciberdemônio.,,%o a fost împroșcat de ciberdemon.,Игрока %o размазал кибердемон.,%o је спљоштен@[adj_1_sr] од стране сајбердемона,%o bir siber iblis tarafından parçalandı. -%o met a Nazi.,OB_WOLFSS,,,,%o potkal@[ao_cs] nácka.,%o mødte en nazist.,%o traf einen Nazi.,@[art_gr] %o χνώρισε ένα Ναζιστή.,%o renkontis Nazion.,%o se encontró a un Nazi.,,%o tapasi natsin.,%o a rencontré un Nazi.,%o találkozott egy nácival.,%o ha incontrato un Nazista.,%o はナチ兵と遭遇した。,%o 은(는) 나치를 만났다.,%o ontmoette een nazi.,Jeg møtte en nazist.,%o spotkał@[ao_pl] nazistę.,%o encontrou um Nazista.,%o encontrou um Nazi.,%o a întâlnit un Nazist.,Игрок %o встретил нациста.,%o је упозна@[ao_1_sr] нацисту.,%o bir Nazi ile karşılaştı. -%o was mauled by a dog.,OB_DOG,,,,%o byl@[ao_cs] roztrhán@[ao_cs] psem.,%o blev mast af en hund.,%o wurde von einem Hund zerrissen.,@[art_gr] %o φαγόθικε απο ένα σκύλο.,%o estis atakita de hundo.,%o fue magullad@[ao_esp] por un perro.,,%o joutui koiran raatelemaksi.,%o s'est fait mordre par un chien.,%o-t szétmarcangolta egy kutya.,%o è stato sbranato da un cane.,%o は犬に引き裂かれた。,%o 은(는) 개한테 으스러졌다.,%o werd verminkt door een hond.,%o ble maltraktert av en hund.,%o został@[ao_pl] poturbowan@[adj_pl] przez psa.,%o foi mutilad@[ao_ptb] por um cachorro.,%o foi mutilad@[ao_ptb] por um cão.,%o a fost sfâșiat de un câine.,Игрока %o разорвала собака.,Играча %o је удавио пас.,%o bir köpek tarafından parçalandı. -%o chewed on %k's fist.,OB_MPFIST,,,,%o si pochutnal@[ao_cs] na pěsti hráče %k.,%o tyggede på %ks knytnæve.,%o kaute auf %ks Faust herum.,@[art_gr] %o μάσησε τη γροθία του/της %k.,%o maĉis la pugnon de %k.,%o masticó el puño de %k.,,%k rusikoi %o paran.,%o a bouffé le poing de %k.,%o megkóstolta %k ökleit.,%o si è schiantato contro il pugno di %k.,%o は %k の拳を顔面に受けた。,%o 은(는) %k 의 주먹을 물었다.,%o gekauwd op %k's vuist.,%o tygget på %ks knyttneve.,%o przygryza pięść %k.,%o foi espancad@[ao_ptb] até a morte por %k,,%o a mestecat pumnul lui %k.,Игрок %o отведал кулака игрока %k.,Играча %o је сажвакао песницу играча %k.,"%o, %k tarafından öldürüldü." -%o was mowed over by %k's chainsaw.,OB_MPCHAINSAW,,,,%o byl@[ao_cs] zkácen@[ao_cs] motorovkou hráče %k.,%o blev slået ned af %ks motorsav.,%o wurde von %ks Kettensäge zerteilt.,@[art_gr] %o κόπηκε απο το αλλησοπρίονο του/της %k.,%o estis buĉita de la ĉensegilo de %k.,%o fue masacrad@[ao_esp] por la motosierra de %k.,,%k katkoi %o paran.,%o a été tondu@[e_fr] par la tronconneuse de %k.,%o-t kettészelte %k láncfűrésze.,%o è stato falciato dalla motosega di %k.,%o は %k のチェーンソーで刈り取られた。,%o 은(는) %k 의 전기톱에 갈렸다.,%o werd gemaaid met %k's kettingzaag.,%o ble klippet over av %ks motorsag.,%o został@[ao_pl] skoszon@[adj_pl] przez piłę łańcuchową %k.,%o foi picad@[ao_ptb] pela motoserra de %k,,%o a fost tăiat de drujba lui %k.,Игрока %o разрезал бензопилой игрок %k.,%o је исечен@[adj_1_sr] моторном тестером играча %k.,"%o, %k tarafından biçildi" -%o was tickled by %k's pea shooter.,OB_MPPISTOL,,,,%o byl@[ao_cs] polechtán@[ao_cs] pistolkou hráče %k.,%o blev kildet af %ks ærteskytte.,%o wurde von %ks Erbsenpistole gekitzelt.,@[art_gr] %o γαργαλίθηκε απο το οπλάκι του/της %k.,%o estis tiklita de la pafileto de %k.,%o fue cosquillead@[ao_esp] por el tirachinas de %k.,%o ha sido asesinad@[ao_esp] por la pipa de %k.,%o kutitti %o parkaa hernepyssyllään.,%o a été châtouillé@[e_fr] par le pistolet de %k.,%o meg lett csiklandozva %k játékpisztolyával.,%o è stato sforacchiato dalla pistola di %k'.,%o は %k の豆鉄砲でくすぐられた。,%o 은(는) %k 의 권총에 간지럼을 탔다.,%o werd gekieteld door %k's erwtenschutter.,%o ble kilt av %ks ertebøsse.,%o został@[ao_pl] połaskotan@[adj_pl] przez spluwę %k.,%o levou cócegas da pistolinha de %k.,,%o a fost gâdilat de pistolașul lui %k.,Игрока %o защекочен вусмерть из горохострела игрока %k.,%o је заголицан@[adj_1_sr] пиштољем играча %k.,"%o, %k tarafından gıdıklandı" -%o chewed on %k's boomstick.,OB_MPSHOTGUN,,,,%o si pochutnal@[ao_cs] na brokádě hráče %k.,%o tyggede på %ks bommestok.,%o wurde Opfer von %ks Schrotflinte.,@[art_gr] %o έφαγε το ντουφέκι του/της %k.,%o maĉis la ĉaspafilon de %k.,%o mordió@[ao_esp] el trabuco de %k.,%o ha sido agujeread@[ao_esp] por el trabuco de %k.,%k jauhoi %o paran tussarillaan.,%o a s'est mangé@[e_fr] de la chevrotine de la part de %k.,%o megízlelte %k villámbotját.,%o si è trovato davanti il fucile di %k.,%o は %k のブームスティックを顔面に受けた。,%o 은(는) %k 의 붐스틱에 꽂혔다.,%o gekauwd op %k's boomstick.,%o tygget på %ks boomstick.,%o przygryza pukawkę %k.,%o foi mort@[ao_ptb] pela espingarda de %k.,,%o a mestecat pușca lui %k.,Игрока %o накормил дробью игрок %k.,%o је сажвака@[ao_1_sr] на пумпарицу играча %k.,"%o, %k tarafından patlatıldı" -%o was splattered by %k's super shotgun.,OB_MPSSHOTGUN,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] na kaši superbrokovnicí hráče %k.,%o blev sprøjtet af %ks super haglgevær.,%o wurde von %ks Super-Schrotflinte zerfetzt.,@[art_gr] %o διαλύθηκε απο το διπλό ντουφέκι του/της %k,%o estis disŝprucigita de la supera ĉaspafilo de %k.,%o fue reventad@[ao_esp] por la súper escopeta de %k.,,%k roiski %o paran yltympäriinsä superhaulikollaan.,%o s'est fait@[e_fr] gicler par le fusil de chasse de %k.,%o-t cafatokra tépte %k szupersörétese.,%o è stato smembrato dalla doppietta di %k.,%o は %k のスーパーショットガンでバラバラにされた。,%o 은(는) %k 의 슈퍼 샷건에 의해 터졌다.,%o werd gespat door %k's super jachtgeweer.,%o ble skutt med %ks super-haglgevær.,%o został@[ao_pl] rozpryskan@[adj_pl] przez super strzelbę %k.,%o foi estraçalhad@[ao_ptb] pela espingarda de cano duplo de %k.,,%o a fost împroșcat de super pușca lui %k.,Игрока %o размазал из супердробовика игрок %k.,Играча %o је спљоштила двоцевка играча %k.,"%o, %k tarafından sıçratıldı" -%o was mowed down by %k's chaingun.,OB_MPCHAINGUN,,,,%o byl@[ao_cs] prostřílen@[ao_cs] kulometem hráče %k.,%o blev mejet ned af %ks maskingevær.,%o wurde von %ks Maschinengewehr niedergemäht.,@[art_gr] %o κοματίαστηκε απο το πολυβόλο του/της %k.,%o estis kuglo-plenigita de la maŝinpafilo de %k.,%o fue masacrado por la ametralladora de %k.,,%k niitti %o paran konekiväärillään.,%o a été ventilé@[e_fr] par la mitrailleuse de %k.,%k gépágyúval szétszaggatta %o testét.,%o è stato falciato dal mitragliatore di %k.,%o は %k のチェーンガンで蜂の巣にされた。,%o 은(는) %k 의 체인건에 의해 으깨졌다.,%o werd gemaaid met %k's machinegeweer.,%o ble meiet ned av %ks maskinpistol.,%o został@[ao_pl] skoszon@[adj_pl] przez karabin maszynowy %k.,%o foi massacrad@[ao_ptb] pela metralhadora de %k.,,%o a fost secerat de mitraliera rotativă a lui %k.,Игрок %o скошен из пулемёта игрока %k.,%o је покоси@[ao_1_sr] митраљез играча %k.,"%o, %k tarafından biçildi" -%o rode %k's rocket.,OB_MPROCKET,,,,%o se projel@[ao_cs] na raketě hráče %k.,%o red på %ks raket.,%o ritt auf %ks Rakete.,@[art_gr] %o καβάλησε τον πύραυλο του/της %k.,%o rajdis la raketon de %k.,%o se montó en el cohete de %k.,%o quería montarse en el cohete de %k.,%o ratsasti pelaajan %k raketilla.,%o a chevauché la roquette de %k.,%o meglovagolta %k rakétáját.,%o ha cavalcato il razzo di %k.,%o は %k のロケットに乗ってしまった。,%o 은(는) %k 의 로켓을 탔다.,%o reed op %k's raket.,%o red på %ks rakett.,%o ujeżdżał@[ao_pl] rakietę %k.,%o não viu o foguete de %k.,%o não viu o míssil de %k.,%o a călărit racheta lui %k.,Игрок %o прокатился на ракете игрока %k.,%o је ујаха@[ao_1_sr] ракету играча %k.,"%o, %k tarafından sıçratıldı" -%o almost dodged %k's rocket.,OB_MPR_SPLASH,,,,%o se skoro vyhnul@[ao_cs] raketě hráče %k.,%o undgik næsten %ks raket.,"%o schaffte es fast, %ks Rakete auszuweichen.",@[art_gr] %o σχεδόν απόφηγε τον πύραυλο του/της %k.,%o preskaŭ evitis la raketon de %k.,%o casi esquivó el cohete de %k.,%o casi esquiva el cohete de %k.,%o melkein väisti pelaajan %k raketin.,%o a presque esquivé la roquette de %k.,%o majdnem kitért %k rakétája elől.,%o aveva quasi schivato il razzo di %k.,%o は %k のロケットをあと少しで避けられそうだった。,%o 은(는) %k 의 로켓 폭발을 거의 피했다.,%o ontweek bijna %k's raket.,%o unngikk nesten %ks rakett.,%o prawie unika rakiety %k.,%o quase escapou do foguete de %k.,%o quase escapou do míssil de %k.,%o aproape a evitat racheta lui %k.,Игрок %o почти увернулся от ракеты %k.,%o је за длаку избега@[ao_1_sr] ракету играча %k.,"%o, %k tarafından sıçratıldı" -%o was melted by %k's plasma gun.,OB_MPPLASMARIFLE,,,,%o se roztekl@[ao_cs] plazmapuškou hráče %k.,%o blev smeltet af %ks plasma riffel.,%o wurde von %ks Plasmagewehr geschmolzen.,@[art_gr] %o λίοθηκε απο το πλάσμα όπλο του/της %k.,%o estis fandigita de la plasmo-pafilo de %k.,%o fue derretid@[ao_esp] por el rifle de plasma de %k.,,%k sulatti %o paran plasmapyssyllään.,%o a été réduit@[e_fr] en bouillie par le fusil a plasma de %k.,%k plazmafegyverével megolvaszotta %o testét.,%o è stato fuso dal fucile al plasma di %k.,%o は %k のプラズマガンに溶かされた。,%o 은(는) %k 의 플라즈마 건에 의해 융해되었다.,%o was gesmolten door %k's plasmageweer.,%o ble smeltet av %ks plasmakanon.,%o został@[ao_pl] stopion@[adj_pl] przez pistolet plasmowy %k.,%o foi torrad@[ao_ptb] pelo fuzil de plasma de %k.,%o foi torrad@[ao_ptb] pela pistola de plasma de %k.,%o a fost topit de pușca cu plasmă a lui %k.,Игрока %o расплавил из плазмомёта игрок %k.,%o је отопљен@[adj_1_sr] плазма оружјем играча %k.,"%o, %k tarafından eritildi" -%o was splintered by %k's BFG.,OB_MPBFG_BOOM,,,,%o byl@[ao_cs] rozštěpen@[ao_cs] BFGčkem hráče %k.,%o blev splintret af %ks BFG.,%o wurde von %ks BFG in Stücke gerissen.,@[art_gr] %o κοματιάστηκε απο το BFG του/της %k.,%o estis splitigita de la BFG de %k.,%o fue aniquilado por la BFG de %k.,,%k pirstoi %o paran BFG:llään.,%o a été oblitéré@[e_fr] par le BFG de %k.,%o teste atomjaira szakadt %k BFG-jétől.,%o è stato sminuzzato dal BFG di %k.,%o は %k のBFGで木っ端微塵にされた。,%o 은(는) %k 의 BFG덕에 산산조각 났다.,%o was versplinterd door %k's BFG.,%o ble splintret av %ks BFG.,%o został@[ao_pl] rozpryskan@[adj_pl] przez BFG %k.,%o foi vaporizad@[ao_ptb] pela BFG de %k.,,%o a fost despicat de către BFG-ul lui %k.,Игрока %o порвал на осколки выстрел из BFG игрока %k.,%o је расцепан@[adj_1_sr] ВЈП играча %k.,"%o, %k tarafından parçalandı" -%o couldn't hide from %k's BFG.,OB_MPBFG_SPLASH,,,,%o se nemohl@[ao_cs] ukrýt před BFGčkem hráče %k.,%o kunne ikke gemme sig for %ks BFG.,%o konnte sich nicht vor %ks BFG verstecken.,@[art_gr] %o δέν μπόρεσε να κρυφτέι απο το BFG του/της %k.,%o ne povis kaŝi sin de la BFG de %k.,%o no pudo esconderse de la BFG de %k.,,%o ei kyennyt piiloutumaan pelaajan %k BFG:ltä.,%o n a pas pu se couvrir du BFG de %k.,%o nem tudott elmenekülni %k BFG-je elől.,%o non poteva nascondersi dal BFG di %k.,%o は %k のBFGから隠れることはできなかった。,%o 은(는) %k 의 BFG의 일격으로부터 피할 수 없었다.,%o kon zich niet verbergen voor %k's BFG.,%o kunne ikke gjemme seg for %ks BFG.,%o nie może się schować przed BFG %k.,%o não conseguiu se esconder da BFG de %k,,%o nu s-a putut ascunde de BFG-ul lui %k.,Игрок %o не успел спрятаться от BFG игрока %k.,%o се није мог@[ao_2_sr] сакрити од ВЈП играча %k.,"%o, %k tarafından parçalandı" -%o was railed by %k.,OB_RAILGUN,,,,%o byl@[ao_cs] napíchnut@[ao_cs] hráčem %k.,%o blev skudt af %k.,%o stand in %ks Schusslinie.,@[art_gr] %o καρφόθηκε απο τον/την %k.,%o estis traborita de la elektropafilo de %k.,%o fue rielad@[ao_esp] por %k.,,%o lävisti %o paran.,%o a été aligné@[e_fr] par %k.,%o beleállt %k lézerébe.,%o è stato bucherellato dal railgun di %k.,%o は %k のレールガンで死亡した。,%o 은(는) %k 의 레일건에 관통당했다.,%o werd gespaakt door %k.,%o ble skutt av %k.,%o stał@[ao_pl] na linii ognia %k.,%o estava na mira do canhão elétrico de %k.,,%o a fost ocărit de %k.,Игрока %o пробил насквозь игрок %k.,%o је убијен@[adj_1_sr] од играча %k.,%o %k tarafından kovuldu. -%o was burned by %k's BFG.,OB_MPBFG_MBF,,,,%o shořel@[ao_cs] BFGčkem hráče %k.,%o blev brændt af %ks BFG.,%o wurde von %ks BFG verbrannt.,@[art_gr] %o κάικε απο το BFG του/της %k.,%o estis bruligita de la BFG de %k.,%o fue vaporizad@[ao_esp] por la BFG de %k.,,%k korvensi %o paran BFG:llään.,%o a été irradié@[e_fr] par le BFG de %k.,%k hamuvá égette %o testét BFG-vel.,%o è stato bruciato dal BFG di %k.,%o は %k のBFGで焼き殺された。,%o 은(는) %k 의 BFG에 의해 타올랐다.,%o werd verbrand door %k's BFG.,%o ble brent av %ks BFG.,%o został@[ao_pl] spalon@[adj_pl] przez BFG %k.,%o foi cozid@[ao_ptb] pela BFG de %k.,,%o a fost ars de BFG-ul lui %k.,Игрока %o сжёг из BFG игрок %k.,%o је изгоре@[ao_1_sr] од ВЈП играча %k.,%o %k tarafından yakıldı -,,Heretic,,,,,,,,,,,,,,,,,,,,,,,, -,,Pickup ,,,,,,,,,,,,,,,,,,,,,,,, -Blue Key,TXT_GOTBLUEKEY,,,,Modrý klíč,Blå nøgle,Blauer Schlüssel,Μπλέ Κλειδί,Blua Ŝlosilo,Llave Azul,,Sininen avain,Clé Bleue,Kék kulcs,Chiave blu,青の鍵,청색 열쇠,Blauwe sleutel,Blå nøkkel,Niebieski klucz,Chave Azul,,Cheie Albastră,Синий ключ,Плави кључ,Mavi Anahtar -Yellow Key,TXT_GOTYELLOWKEY,,,,Žlutý klíč,Gul nøgle,Gelber Schlüssel,Κύτρινο Κλειδί,Flava Ŝlosilo,Llave Amarilla,,Keltainen avain,Clé Jaune,Sárga kulcs,Chiave gialla,黄の鍵,황색 열쇠,Gele sleutel,Gul nøkkel,Żółty klucz,Chave Amarela,,Cheie Galbenă,Жёлтый ключ,Жути кључ,Sarı Anahtar -Green Key,TXT_GOTGREENKEY,,,,Zelený klíč,Grøn nøgle,Grüner Schlüssel,Πράσινο Κλειδί,Verda Ŝlosilo,Llave Verde,,Vihreä avain,Clé Verte,Zöld kulcs,Chiave verde,緑の鍵,녹색 열쇠,Groene sleutel,Grønn nøkkel,Zielony klucz,Chave Verde,,Cheie Verde,Зелёный ключ,Зелени кључ,Yeşil Anahtar -Quartz Flask,TXT_ARTIHEALTH,,,,Blyštivá baňka,Kvartsflaske,Quarzflasche,Φλάσκα Χαλαζίας,Kvarca Flakono,Frasco de Cuarzo,,Kvartsipullo,Flasque en Quartz,Kvarc flaska,Ampolla di quarzo,石英フラスコ,석영 플라스크,Kwartskolf,Kvartskolbe,Kwarcowa Butelka,Frasco de Quartzo,,Flacon de Quartz,Кварцевый флакон,Кварцна боца,Kuvars Şişesi -Wings of Wrath,TXT_ARTIFLY,,,,Křídla hněvu,Vredens vinger,Flügel des Zorns,Φτερά της Οργής,Flugiloj de Kolero,Alas de Ira,,Kiihtymyksen siivet,Ailes du Courroux,A Harag Szárnyai,Ali iraconde,レイスの翼,분노의 날개,Vleugels der Toorn,Vredens vinger,Skrzydła Gniewu,Asas da Ira,,Aripile Furiei,Крылья гнева,Крила гнева,Gazap Kanatları -Ring of Invincibility,TXT_ARTIINVULNERABILITY,,,,Prsten nesmrtelnosti,Ring af uovervindelighed,Ring der Unverwundbarkeit,Δαχτυλίδι της Αθανασίας,Ringo de Nevenkebleco,Anillo de Invencibilidad,,Näkymättömyyden sormus,Anneau d'Invincibilité,A Sérthetetlenség Gyűrűje,Anello dell'invincibilità,不死の指輪,불멸의 반지,Ring van Onoverwinnelijkheid,Uovervinnelighetens ring,Pierścień Niewrażliwości,Anel da Invencibilidade,,Inelul Invincibilității,Кольцо неуязвимости,Прстен непобедивости,Yenilmezlik Yüzüğü -Tome of Power,TXT_ARTITOMEOFPOWER,,,,Kniha moci,Bog om magt,Buch der Macht,Τομός της Δύναμης,Librego de Forto,Tomo de Poder,,Väkevyyden kirja,Livre du Pouvoir,Az Erő Kódexe,Tomo del potere,力の術書,힘의 서,Boek van de Macht,Maktens bok,Tom Mocy,Livro do Poder,Livro do Poder,Cartea Puterii,Том могущества,Том моћи,Güç Kitabı -Shadowsphere,TXT_ARTIINVISIBILITY,,,,Šerosféra,Skyggesfære,Schattensphäre,Σκιόσφαιρα,Ombrosfero,Esfera de Sombra,,Varjokehrä,Sphère des Ombres,Árnygömb,Sfera dell'ombra,闇の球体,그림자 구체,Schaduwbol,Skyggesfære,Sfera Cieni,Esfera das Sombras,,Sfera Umbrei,Теневая сфера,Сфера сенки,Gölge Küre -Morph Ovum,TXT_ARTIEGG,,,,Měnivejce,Morph Ovum,Transformations-Ei,Μετασχηματίζοντικο Ωάριο,Ovo de Transformado,Huevo de Transformación,,Muodonmuutoksen muna,Ovule de Métamorphose,Alakváltó tojás,Uovo della metamorfosi,変貌の卵子,변신 알,Morfose-Ei,Morph Ovum,Jajko Morfujące,Ovo da Metamorfose,,Oul Metamorfozei,Яйцо превращения,Преображавајуће јајашце,Dönüşümlü Yumurta -Mystic Urn,TXT_ARTISUPERHEALTH,,,,Tajemná urna,Mystisk urne,Mystische Urne,Μυστικό Δοχείο,Mistika Urno,Urna Mística,,Mystinen uurna,Urne Mystique,Misztikus urna,Urna mistica,神秘の骨壷,신비한 항아리,Mystieke Urn,Mystisk urne,Mistyczna Urna,Urna Mística,,Urnă Mistică,Мистическая урна,Мистериозна урна,Mistik Urn -Torch,TXT_ARTITORCH,,,,Pochodeň,Fakkel,Fackel,Πυρσός,Torĉo,Antorcha,,Soihtu,Torche,Fáklya,Torcia,松明,횃불,Fakkel,Fakkel,Pochodnia,Tocha,,Torță,Факел,Бакља,Meşale -Time Bomb of the Ancients,TXT_ARTIFIREBOMB,,,,Časovaná bomba starověku,De ældres tidsbombe,Zeitbombe der Alten,Χρονοβόμβα τον Αρχαίων,Tempobombo de la Antikvuloj,Bomba de tiempo de los Ancestros,,Vanhain aikapommi,Bombe a Retardement des Anciens,Az Ősök Időbombája,Bomba a tempo degli antichi,古代の時限爆薬,고대의 시한폭탄,Tijdbom der Tijden,De eldgamles tidsinnstilte bombe,Starożytna Bomba Czasu,Bomba-relógio dos Anciãos,,Bomba cu Ceas a Anticilor,Часовая бомба древних,Временска бомба древних,Kadimlerin Saatli Bombası +această ușă",Для открытия нужен жёлтый череп,Треба вам жута лобања да би отворили ова врата,Du behöver en gul skalle för att öppna den här dörren.,Bu kapıyı açmak için sarı bir kafatasına ihtiyacın var.,"Вам потрібен жовтий череп, щоб активувати цей об'єкт" +,,Cast call names,,,,,,,,,,,,,,,,,,,,,,,,,, +Zombieman,CC_ZOMBIE,,,,Zombie,Zombie,Zombie,Ζόμπι,Zombio,Zombi,,Zombimies,Zombie,Zombi,Zombie Marine,ゾンビ兵,좀비맨,Zombie,Zombiemann,Zombie,Zumbi,Homem Zombie,Zombi,Зомби,Зомби,Zombie,Zombi,Зомбі +Shotgun Guy,CC_SHOTGUN,a.k.a. (former human) sergeant,,,Seržant,Sergent,Schütze,Τύπος με ντουφέκι,Ĉaspafilulo,Sargento,,Haulikkohemmo,Type au Fusil,Őrmester,Zombie Sergente,ショットガンゾンビ,샷건 가이,Jachtgeweerkerel,Sersjant,Zombie-sierżant,Sargento Possuído,Tipo de Espingarda,Pușcaș,Зомби-сержант,Пумпераш,Hagelgevärskille,Çavuş,Зомбі-сержант +Heavy Weapon Dude,CC_HEAVY,a.k.a. former commando,,,Kulometčík,,MG-Schütze,Τύπος με βαρί όπλο,Pezarmilulo,Ametrallador,,Raskasaseäijä,Type au Gros Flingue,Kommandós,Zombie Commando,ヘビーウェポンゾンビ,헤비 웨폰 듀드,Zwarewapenskerel,Maskingeværskyt,Ciężkozbrojny Zombie,Comando Possuído,Gajo das Armas Pesadas,Mitralior,Зомби-пулемётчик,Митраљезац,Tunga vapen kille,Ağır Silah Dostum,Кулеметник +Imp,CC_IMP,,,,Čert,,Kobold,Διάβολος,Diableto,,,Piru,Diablotin,Tűzkobold,,インプ,임프,,,Diablik,Diabrete,,Drac,Имп,Враг,,İmp,Імп +Demon,CC_DEMON,,,,Démon,Dæmon,Dämon,Δαίμονας,Demono,Demonio,,Demoni,Démon,Démon,Pinky,デーモン,데몬,Demoon,,,Demônio,,,Демон,Демон,,İblis,Демон +Lost Soul,CC_LOST,,,,Ztracená duše,Fortabt sjæl,Verlorene Seele,Χαμένη Ξυχή,Perdita Animo,Alma Errante,,Kadonnut sielu,Ame Perdue,Kóbor lélek,Anima Errante,ロストソウル,로스트 소울,Verloren ziel,Fortapt sjel,Zaginiona Dusza,Alma Perdida,Alma Penada,Suflet Pierdut,Потерянная душа,Изгубљена душа,Förlorad själ,Kayıp Ruh,Пропаща душа +Cacodemon,CC_CACO,,,,Kakodémon,Cacodæmon,Cacodämon,Κακοδαίμονας,Kakodemono,Cacodemonio,,Kakodemoni,Cacodémon,Kakodémon,Cacodemone,カコデーモン,카코데몬,Cacodemoon,Kacodemon,Kakodemon,Cacodemônio,,Cacodemon,Какодемон,Какодемон,Cacodemon,Cacodemon,Какодемон +Hell Knight,CC_HELL,,,,Pekelný rytíř,Helvedesridder,Höllenritter,Ιππότης της Κόλασης,Inferkavaliro,Caballero del Infierno,,Hornanritari,Chevalier Infernal,Pokollovag,Cavaliere Infernale,ヘルナイト,헬 나이트,Helleridder,Helvetesridder,Rycerz Piekła,Cavaleiro Infernal,Cavaleiro Infernal,Cavaler al Infernului,Рыцарь ада,Витез пакла,Helvete riddare,Cehennem Şövalyesi,Лицар Пекла +Baron of Hell,CC_BARON,,,,Baron pekel,Helvedesbaron,Höllenbaron,Βαρώνος της Κολασης,Barono de Infero,Barón del Infierno,,Hornanparoni,Baron des Enfers,Pokolbáró,Barone Infernale,バロンオブヘル,바론 오브 헬,Baron des Hels,Helvetesbaron,Baron Piekła,Barão do Inferno,,Baron al Infernului,Барон ада,Барон пакла,Helvetets baron,Cehennem Baronu,Барон Пекла +Arachnotron,CC_ARACH,,,,,,,Αράχνοτρον,Elektraraneo,Aracnotrón,,Araknotroni,,Póktron,,アラクノトロン,아라크노트론,,,,Aracnotron,,Aracnotron,Арахнотрон,Паукотрон,,Araknotron,Арахнотрон +Pain Elemental,CC_PAIN,,,,Živel trýzně,Smerteelementar,Elementarschmerz,Στοιχείομα του Πόνου,Doloro-Elementulo,Elemental del Dolor,,Kivun henki,Elémentaire de Douleur,Elemi Kín,Elementale del Dolore,ペインエレメンタル,페인 엘리멘탈,Smartelementaal,Smerte Elemental,Żywiołak Bólu,Elemental da Dor,,Elemental al Durerii,Элементаль боли,Елементал патње,Smärta elementär,Acı Elementi,Елементаль болю +Revenant,CC_REVEN,,,,Umrlec,Hævnen,Wiederauferstandener,Εκδικητής,Renaskitulo,,,Henkiinpalannut,,Kísértet,,レバナント,레버넌트,Wreker,Gjenganger,Zjawa,Insepulto,Renascido,Nemort,Ревенант,Повратник,Återfödare,,Ревевант +Mancubus,CC_MANCU,,,,Mankubus,,,Χοντρός,Mankubo,,,Mankubus,Mancube,Mankubusz,,マンキュバス,맨큐버스,,,Antropokub,,,,Манкубус,Манкубус,,,Манкубус +Arch-Vile,CC_ARCH,,,,Veleběs,Ærkevile,Scheusal,Νεκρομάντις,Ĉef-Fiulo,,,Arkkihirvitys,Arche-vile,Ősármány,Arch-vile,アーチバイル,아크-바일,Aartsgedrocht,Erkefiende,Arcy-Podlec,Arquivil,,Abject,Архвиль,Арчвајл,Ärkevild,Baş Aşağılık,Арчвайл +The Spider Mastermind,CC_SPIDER,,,,Pavoučí velevůdce,Edderkoppen Mastermind,Der Spinnenmeister,Το Αραχνό Ιθύνων Νους,La Elektraraneo-Mastro,La Mente-Maestra Arácnida,,Hämähäkkiaivot,L'Araignée Commandante,Pókelme,L'Aracnomente Suprema,スパイダーマスターマインド,스파이더 마스터마인드,Het Spinnenmeesterbrein,Edderkopphjernen,Pajęczy Mistrz,A Aranha-Mestra,,Păianjen Maestru,Паук-предводитель,Паук-руководилац,Spindelns hjärna,Örümcek Beyni,Павук-полководець +The Cyberdemon,CC_CYBER,,,,Kyberdémon,Cyberdæmonen,Der Cyberdämon,Ο Cyber-δαίμονας,La Ciberdemono,El Ciberdemonio,,Kyberdemoni,Le Cyberdémon,A Kiberdémon,Il Cyberdemonio,サイバーデーモン,사이버데몬,Het Cyberdemoon,Kyberdemonen,Cyberdemon,O Ciberdemônio,,Ciberdemon,Кибердемон,Сајбердемон,Cyberdemon,Siber Şeytan,Кібердемон +Our Hero,CC_HERO,,,,Náš hrdina,Vores helt,Unser Held,Ο ήρωας μας,Nia heroo,Nuestro héroe,,Sankarimme,Notre Héros,Hősünk,Il Nostro eroe,我らのヒーロー,우리들의 영웅,Onze held,Vår helt,Nasz bohater,Nosso herói,O Nosso Herói,Eroul Nostru,Наш герой,Наш херој,Vår hjälte,Bizim Kahramanımız,Наш герой +,,Actor tag names,,,,,,,,,,,,,,,,,,,,,,,,,, +Sergeant,FN_SHOTGUN,,,,Seržant,Sergent,Schütze,Λοχίας,Serĝento,Sargento,,Kersantti,Type au Fusil,Őrmester,Zombie Sergente,ゾンビ軍曹,샷건 가이,,Sersjant,Zombie-sierżant,Sargento,Sargento,Sergent,Зомби-сержант,Водник,Hagelgevärskille,Çavuş,Зомбі-сержант +Chaingunner,FN_HEAVY,,,,Kulometčík,,MG-Schütze,Πολυβόλο Ζόμπι,Maŝinpafilisto,Ametrallador,,Konekiväärimies,Type au Gros Flingue,Kommandós,Zombie Commando,チェーンガンゾンビ,체인거너,Machinegeweerman,Maskingeværskyt,Ciężkozbrojny Zombie,Comando,Metrelhador,Mitralior,Зомби-пулемётчик,Митраљезац,Tunga vapen kille,Ağır Silah Dostum,Кулеметник +Spectre,FN_SPECTRE,,,,Přízrak,Spøgelse,Schemen,Φάντασμα,Fantomo,Espectro,,Haamu,,Lidérc,Spettro,スペクトル,스펙터,Spook,Spøkelse,Widmo,Espectro,,Spectru,Фантом,Авет,,Hayalet,Примара +Spider Mastermind,FN_SPIDER,,,,Pavoučí velevůdce,Edderkoppen Mastermind,Spinnenmeister,Αραχνό Ιθύνων Νους,Elektraraneo-Mastro,Mente-Maestra Arácnida,,Hämähäkkiaivot,L'Araignée Commandante,Pókelme,L'Aracnomente Suprema,スパイダーマスターマインド,스파이더 마스터마인드,Spinnenmeesterbrein,Edderkopphjerne,Pajęczy Mistrz,Aranha-Mestra,,Păianjen Maestru,Паук-предводитель,Паук-руководилац,Spindelns hjärna,Örümcek Beyni,Павук-полководець +Cyberdemon,FN_CYBER,,,,Kyberdémon,Cyberdæmon,Cyberdämon,Cyber-δαίμονας,Ciberdemono,Ciberdemonio,,Kyberdemoni,Le Cyberdémon,Kiberdémon,Il Cyberdemonio,サイバーデーモン,사이버데몬,Cyberdemoon,Kyberdemon,Cyberdemon,Ciberdemônio,,Ciberdemon,Кибердемон,Сајбердемон,Cyberdemon,Siber İblis,Кібердемон +Nazi,FN_WOLFSS,,,,Nácek,,,Ναζιστής,Nazio,,,Natsi,,Náci,Nazista,ナチ兵,나치,,Nazist,Nazista,Nazista,,Nazist,Нацист,Нациста,Nazist,,Нацист +Dog,FN_DOG,,,,Pes,Hund,Hund,Σκύλος,Hundo,Perro,,Koira,Chien,Kutya,Cane,犬,개,Hond,Hund,Pies,Cão,,Câine,Собака,Пас,Hund,Köpek,Пес +Brass Knuckles,TAG_FIST,,,,Boxer,Messing knoer,Schlagringe,Γροθιά,Pugningo,Puño americano,Manopla (puño de acero),Nyrkkirauta,Poing Américain,Bokszer,Tirapugni ,ナックルダスター,너클,Boksbeugels,Knokejern,Kastety,Soco Inglês,Soqueira,Rozetă,Латунный кастет,Боксер,Mässingsknoglar,Pirinç Muşta,Кулаки +Chainsaw,TAG_CHAINSAW,,,,Motorová pila,Kædesav,Kettensäge,Αλλησοπρίονο,Ĉensegilo,Motosierra,,Moottorisaha,Tronçonneuse,Láncfűrész,Motosega,チェーンソウ,전기톱,Kettingzaag,Motorsag,Piła łańcuchowa,Motosserra,,Drujbă,Бензопила,Моторна тестера,Motorsåg,Testere,Бензопила +Pistol,TAG_PISTOL,,,,Pistole,,Pistole,Πιστόλι,Pafileto,Pistola,,Pistooli,Pistolet,Pisztoly,Pistola,ピストル,권총,Pistool,,Pistolet,Pistola,,,Пистолет,Пиштољ,,Tabanca,Пістолет +Shotgun,TAG_SHOTGUN,,,,Brokovnice,Haglgevær,Schrotflinte,Ντουφέκι,Kartoĉa fusilo,Escopeta,,Haulikko,Fusil à pompe,Sörétes Puska,Fucile,ショットガン,샷건,Jachtgeweer,Haglgevær,Strzelba,Espingarda,,Pușcă,Дробовик,Пумпарица,Hagelgevär,Av Tüfeği,Дробовик +Super Shotgun,TAG_SUPERSHOTGUN,,,,Superbrokovnice,Super-Haglgevær,Super-Schrotflinte,Διπλό Ντουφέκι,Dutuba fusilo,Superescopeta,,Superhaulikko,Super Fusil de chasse,Szuper Sörétes,Fucile a doppia canna ,スーパーショットガン,슈퍼 샷건,Superjachtgeweer,Super-Haglgevær,Super strzelba,Espingarda de cano duplo,,Super Pușcă,Супердробовик,Двоцевка,Super hagelgevär,Süper Av Tüfeği,Двостволка +Chaingun,TAG_CHAINGUN,,,,Kulomet,Maskingevær,Maschinengewehr,Πολυβόλο,Maŝinpafilo,Ametralladora,,Gatling-kk,Mitrailleuse,Golyószóró,Mitragliatore a canne rotanti ,チェーンガン,체인건,Machinegeweer,Maskinpistol,Karabin maszynowy,Metralhadora,,Mitralieră rotativă,Пулемёт,Митраљез,Kedjepistol,,Кулемет +Rocket Launcher,TAG_ROCKETLAUNCHER,,,,Raketomet,Raketkaster,Raketenwerfer,Πυραυλοβόλο,Misilpafilo,Lanzamisiles,,Sinko,Lance-Roquettes,Rakétavető,Lanciamissili,ロケットランチャー,로켓 런쳐,Raketwerper,Rakettkaster,Wyrzutnia rakiet,Lança-foguetes,Lança-Mísseis,Lansator de Rachete,Ракетомёт,Бацач ракета,Raketkastare,Roket Fırlatıcı,Ракетомет +Plasma Rifle,TAG_PLASMARIFLE,,,,Plazmová puška,Plasma riffel,Plasmagewehr,Πλάσμα Όπλο,Plasmo-pafilo,Fusil de plasma,,Plasmapyssy,Fusil à Plasma,Plazmafegyver,Fucile al Plasma ,プラズマライフル,플라즈마 라이플,Plasmageweer,Plasmagevær,Karabin plazmowy,Fuzil de Plasma,Pistola de Plasma,Pușcă cu Plasmă,Плазменная пушка,Плазма оружје,Plasmagevär,Plazma Tüfeği,Плазмаган +BFG 9000,TAG_BFG9000,,,,,,,,,,,,,,,,,,,,,,,,ВЈП 9000,,,БФГ 9000 +Bullets,AMMO_CLIP,,,,Kulky,Kugler,Patronen,Σφαίρες,Kugloj,Balas,,Luodit,Balles,Töltények,Proiettili,銃弾,권총 탄약,Kogels,Kuler,Naboje,Balas,,Gloanțe,Пули,Меци,Kulor,Kurşunlar,Кулі +Shotgun Shells,AMMO_SHELLS,,,,Broky,Haglgeværpatroner,Schrotpatronen,Σφαίρες Ντουφεκιού,Kartoĉoj,Cartuchos de escopeta,,Haulikon patruunat,Cartouches,Sörétek,Cartucce per fucile,散弾シェル,샷건 탄약,Jachtgeweerkogels,Haglepatroner,Loftki,Cartuchos de Espingarda,,Proiectile pentru Pușcă,Патроны дробовика,Патроне за пумпарицу,Skottgubbar,Av Tüfeği Fişekleri,Рушничні набої +Rockets,AMMO_ROCKETS,,,,Rakety,Raketter,Raketen,Πύραυλοι,Raketoj,Cohetes,,Raketit,Roquettes,Rakéták,Razzi,ロケット弾,로켓,Raketten,Raketter,Rakiety,Foguetes,Mísseis,Rachete,Ракеты,Ракете,Raketer,Roketler,Ракети +Energy Cells,AMMO_CELLS,,,,Energetické články,Energiceller,Energiezellen,Κύτταρα Ενέργιας,Energiĉeloj,Célula de energía,,Energia-akut,Cellules,Energiacellák,Batterie,エネルギーセル,에너지 셀,Energiecellen,Energiceller,Ogniwa energetyczne,Células de Energia,,Celule cu Energie,Энергобатареи,Енергетске ћелије,Energiceller,Enerji Hücreleri,Енергетичні батареї +,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,,,, +%o thought %g saw an arachnotron.,OB_STEALTHBABY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] arachnotrona.","%o troede, @[pro_dk] så en arachnotron.","%o dachte, ein Arachnotron zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Αραχνοτρόν.,"%o pensis, ke @[pro_eo] vidis elektraraneon.",%o ha creído ver un Aracnotrón.,%o creyó haber visto un Aracnotrón.,%o luuli nähneensä araknotronin.,%o a cru voir un Arachnotron.,"%o azt hitte, hogy látott egy póktront.",a %o sembrava di aver visto un arachnotron.,%o がアラクノトロンを見た気がした。,%o 은(는) 아라크노트론을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een arachnotron zag.,%o trodde @[pro_dk] så et arachnotron.,%o kątem oka zauważył@[ao_pl] arachnotrona.,%o achou que viu uma arachnotron.,,%o a crezut că %g a văzut un aracnotron.,Игрок %o краем глаза заметил арахнотрона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] паукотрона.,%o trodde att @[pro_sv] såg en arachnotron.,%o bir araknotron gördüğünü sandı.,Арахнотрон мелькнув перед очима %o. +%o thought %g saw an archvile.,OB_STEALTHVILE,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] veleběsa.","%o troede, @[pro_dk] så en ærkevile.","%o dachte, ein Scheusal zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Νεκρομάντη,"%o pensis, ke @[pro_eo] vidis ĉef-fiulon.",%o ha creído ver un Arch-Vile.,%o creyó haber visto un Arch-Vile.,%o luuli nähneensä arkkihirvityksen,%o a cru voir un Arche-Vile.,"%o azt hitte, hogy látott egy ősármányt.",a %o sembrava di aver visto un Arch-Vile.,%o がアーチバイルを見た気がした。,%o 은(는) 아크-바일을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een aartsvijand zag.,%o trodde @[pro_dk] så en erkefiende.,%o kątem oka zauważył@[ao_pl] arcypodleca.,%o achou que viu um arquivil.,,%o a crezut că %g a văzut un abject.,Игрок %o краем глаза заметил архвиля.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] једног арчвајла.,%o trodde att @[pro_sv] såg en ärkevild.,%o bir iğrençlik gördüğünü sandı.,Арчвайл мелькнув перед очима %o. +%o thought %g saw a Baron of Hell.,OB_STEALTHBARON,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] barona pekel.","%o troede, @[pro_dk] så en helvedesbaron.","%o dachte, einen Höllenbaron zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Βαρώνο της Κόλασης.,"%o pensis, ke @[pro_eo] vidis Baronon de Infero.",%o ha creído ver un Barón del Infierno.,%o creyó haber visto un Barón del Infierno.,%o luuli nähneensä hornanparonin.,%o a cru voir un Baron des enfers.,"%o azt hitte, hogy látott egy pokolbárót.",a %o sembrava di aver visto un Barone Infernale.,%o がバロンを見た気がした。,%o 은(는) 바론 오브 헬을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een baron van de Hel zag.,%o trodde @[pro_dk] så en helvetesbaron,%o kątem oka zauważył@[ao_pl] Barona Piekła.,%o achou que viu um barão do inferno.,,%o a crezut că %g a văzut un Baron al Infernului.,Игрок %o краем глаза заметил барона ада.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] барона пакла.,%o trodde att @[pro_sv] såg en helvetets baron.,%o bir Cehennem Baronu gördüğünü sandı.,Барон Пекла мелькнув перед очима %o. +%o thought %g saw a cacodemon.,OB_STEALTHCACO,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] kakodémona.","%o troede, @[pro_dk] så en cacodemon.","%o dachte, einen Cacodämonen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Κακοδαίμονα.,"%o pensis, ke @[pro_eo] vidis kakodemonon.",%o ha creído ver un Cacodemonio.,%o creyó haber visto un Cacodemonio.,%o luuli nähneensä kakodemonin.,%o a cru voir un Cacodémon.,"%o azt hitte, hogy látott egy kakodémont.",a %o sembrava di aver visto un cacodemone.,%o がカコデーモンを見た気がした。,%o 은(는) 카코데몬을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een cacodemon zag.,%o trodde @[pro_dk] så en kakodemon.,%o kątem oka zauważył@[ao_pl] kakodemona.,%o achou que viu um cacodemônio.,,%o a crezut că %g a văzut un cacodemon.,Игрок %o краем глаза заметил какодемона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] какодемона.,%o trodde att @[pro_sv] såg en cacodemon.,%o bir caco iblisi gördüğünü sandı.,Какодемон мелькнув перед очима %o. +%o thought %g saw a chaingunner.,OB_STEALTHCHAINGUY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] kulometčíka.","%o troede, @[pro_dk] så en chaingunner.","%o dachte, einen MG-Schützen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Ζόμπι με ένα πολυβόλο.,"%o pensis, ke @[pro_eo] vidis maŝinpafiliston.",%o ha creído ver un Ametrallador.,%o creyó haber visto un Ametrallador.,%o luuli nähneensä konekiväärimiehen.,%o a cru voir un mitrailleur.,"%o azt hitte, hogy látott egy kommandóst.",a %o sembrava di aver visto uno zombie commando.,%o がチェインガンナーを見た気がした。,%o 은(는) 체인거너를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een zware wapens kerel zag.,%o trodde @[pro_dk] så en maskingeværskyt.,%o kątem oka zauważył@[ao_pl] ciężkozbrojnego zombie.,%o achou que viu um comando possuído.,%o achou que viu um metrelhador.,%o a crezut că %g a văzut un mitralior.,Игрок %o краем глаза заметил пулемётчика.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] митраљезца.,%o trodde att @[pro_sv] såg en tunga vapen kille.,%o bir ağır silah dostu gördüğünü sandı.,Кулеметник мелькнув перед очима %o. +%o thought %g saw a demon.,OB_STEALTHDEMON,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] démona.","%o troede, @[pro_dk] så en dæmon.","%o dachte, einen Dämonen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα δαίμονα.,"%o pensis, ke @[pro_eo] vidis demonon.",%o ha creído ver un Demonio.,%o creyó haber visto un Demonio.,%o luuli nähneensä demonin.,%o a cru voir un démon.,"%o azt hitte, hogy látott egy démont.",a %o sembrava di aver visto un demone.,%o がデーモンを見た気がした。,%o 은(는) 데몬을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een demon zag.,%o trodde @[pro_dk] så en demon.,%o kątem oka zauważył@[ao_pl] demona.,%o achou que viu um demônio.,,%o a crezut că %g a văzut un demon.,Игрок %o краем глаза заметил демона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] демона.,%o trodde att @[pro_sv] såg en demon.,%o bir iblis gördüğünü sandı.,Демон мелькнув перед очима %o. +%o thought %g saw a Hell Knight.,OB_STEALTHKNIGHT,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] rytíře pekel.","%o troede, @[pro_dk] så en helvedesridder.","%o dachte, einen Höllenritter zu sehen.",@[art_gr] %o νόμιζε οτι είδε έναν Ιππότη της Κόλασης.,"%o pensis, ke @[pro_eo] vidis Inferkavaliron.",%o ha creído ver un Caballero del Infierno.,%o creyó haber visto un Caballero del Infierno.,%o luuli nähneensä hornanritarin.,%o a cru voir un chevalier infernal.,"%o azt hitte, hogy látott egy pokollovagot.",a %o sembrava di aver visto un Cavaliere Infernale.,%o がヘルナイトを見た気がした。,%o 은(는) 헬 나이트를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een hel ridder zag.,%o trodde @[pro_dk] så en helvetesridder.,%o kątem oka zauważył@[ao_pl] Rycerza Piekła.,%o achou que viu um cavaleiro infernal.,%o achou que viu um cavaleiro infernal.,%o a crezut că %g a văzut un Cavaler al Infernului.,Игрок %o краем глаза заметил рыцаря ада.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] витеза пакла.,%o trodde att @[pro_sv] såg en helvetesriddare.,%o bir Cehennem Şövalyesi gördüğünü sandı.,Лицар Пекла мелькнув перед очима %o. +%o thought %g saw an imp.,OB_STEALTHIMP,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] čerta.","%o troede, @[pro_dk] så en imp.","%o dachte, einen Kobold zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Διάβολο.,"%o pensis, ke @[pro_eo] vidis diableton.",%o ha creído ver un Imp.,%o creyó haber visto un Imp.,%o luuli nähneensä pirun.,%o a cru voir un diablotin.,"%o azt hitte, hogy látott egy tűzkoboldot.",a %o sembrava di aver visto un imp.,%o がインプを見た気がした。,%o 은(는) 임프를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een imp zag.,%o trodde @[pro_dk] så en imp.,%o kątem oka zauważył@[ao_pl] diablika.,%o achou que viu um diabrete.,,%o a crezut că %g a văzut un drac.,Игрок %o краем глаза заметил импа.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] врага.,%o trodde att @[pro_sv] såg en imp.,%o bir impus gördüğünü sandı.,Імп мелькнув перед очима %o. +%o thought %g saw a mancubus.,OB_STEALTHFATSO,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] mankuba.","%o troede, @[pro_dk] så en mankubus.","%o dachte, einen Mancubus zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Χοντρό.,"%o pensis, ke @[pro_eo] vidis mankubon.",%o ha creído ver un Mancubus.,%o creyó haber visto un Mancubus.,%o luuli nähneensä mankubuksen.,%o a cru voir un mancube.,"%o azt hitte, hogy látott egy mankubuszt.",a %o sembrava di aver visto un mancubus.,%o がマンキュバスを見た気がした。,%o 은(는) 맨큐버스를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een mancubus zag.,%o trodde @[pro_dk] så en mancubus.,%o kątem oka zauważył@[ao_pl] antropokuba.,%o achou que viu um mancubus.,,%o a crezut că %g a văzut un mancubus.,Игрок %o краем глаза заметил манкубуса.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] манкубуса.,%o trodde att @[pro_sv] såg en mancubus.,%o bir mancubus gördüğünü sandı.,Манкубус мелькнув перед очима %o. +%o thought %g saw a revenant.,OB_STEALTHUNDEAD,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] umrlce.","%o troede, @[pro_dk] så en hævnen.","%o dachte, einen Wiederauferstandenen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Εκδικητή.,"%o pensis, ke @[pro_eo] vidis renaskitulon.",%o ha creído ver un Revenant.,%o creyó haber visto un Revenant.,%o luuli nähneensä henkiinpalanneen.,%o a cru voir un revenant.,"%o azt hitte, hogy látott egy kísértetet.",a %o sembrava di aver visto un revenant.,%o がレバナントを見た気がした。,%o 은(는) 레버넌트를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een wraakzuchtige zag.,%o trodde @[pro_dk] så en gjenganger.,%o kątem oka zauważył@[ao_pl] zjawę.,%o achou que viu um insepulto.,%o achou que viu um renascido.,%o a crezut că %g a văzut un nemort.,Игрок %o краем глаза заметил ревенанта.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] повратника.,%o trodde att @[pro_sv] såg en återfödare.,%o bir iskelet gördüğünü sandı.,Ревенант мелькнув перед очима %o. +%o thought %g saw a sergeant.,OB_STEALTHSHOTGUNGUY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] seržanta.","%o troede, @[pro_dk] så en sergent.","%o dachte, einen Schützen zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Λοχία.,"%o pensis, ke @[pro_eo] vidis serĝenton.",%o ha creído ver un Sargento.,%o creyó haber visto un Sargento.,%o luuli nähneensä kersantin.,%o a cru voir un type au fusil.,"%o azt hitte, hogy látott egy őrmestert.",a %o sembrava di aver visto un zombie sergente.,%o が軍曹を見た気がした。,%o 은(는) 샷건 가이를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een jachtgeweer kerel zag.,%o trodde @[pro_dk] så en sersjant.,%o kątem oka zauważył@[ao_pl] zombie-sierżanta.,%o achou que viu um sargento possuído.,%o achou que viu um sargento.,%o a crezut că %g a văzut un sergent.,Игрок %o краем глаза заметил сержанта.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] водника.,%o trodde att @[pro_sv] såg en hagelgevärskille.,%o bir çavuş gördüğünü sandı.,Сержант мелькнув перед очима %o. +%o thought %g saw a zombieman.,OB_STEALTHZOMBIE,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] zombíka.","%o troede, @[pro_dk] så en zombie.","%o dachte, einen Zombie zu sehen.",@[art_gr] %o νόμιζε οτι είδε ένα Ζόμπι.,"%o pensis, ke @[pro_eo] vidis zombion.",%o ha creído ver un Zombi.,%o creyó haber visto un Zombi.,%o luuli nähneensä zombin.,%o a cru voir un zombie.,"%o azt hitte, hogy látott egy zombit.",a %o sembrava di aver visto uno zombie marine.,%o がゾンビ兵を見た気がした。,%o 은(는) 좀비맨을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een zombie zag.,%o trodde @[pro_dk] så en zombiemann.,%o kątem oka zauważył@[ao_pl] zombie.,%o achou que viu um zumbi.,%o achou que viu um zombie.,%o a crezut că %g a văzut un zombi.,Игрок %o краем глаза заметил зомби.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] зомбија.,%o trodde att @[pro_sv] såg en zombie.,%o bir zombi gördüğünü sandı.,Зомбі мелькнув перед очима %o. +%o was punched by a revenant.,OB_UNDEADHIT,,,,%o byl@[ao_cs] udeřen@[ao_cs] umrlcem.,%o blev slået af en genfødt.,%o wurde von einem Wiederauferstandenen K.O geschlagen.,@[art_gr] %o έφαγε μια μπουνία απο έναν Εκδικητή.,%o estis pugnita de renaskitulo.,A %o l@[ao_esp] ha golpeado un Revenant.,A %o l@[ao_esp] golpeó un Revenant.,%o joutui henkiinpalanneen lyömäksi.,%o s'est pris@[e_fr] une raclée de la part d'un revenant.,%o-t kiütötte egy kísértet.,%o è stato colpito dal pugno di un revenant.,%o はレバナントに殴られた。,%o 은(는) 레버넌트에게 맞아 죽었다.,%o werd geslagen door een wraakzuchtige.,%o ble slått av en gjenganger.,%o został@[ao_pl] uderzon@[adj_pl] przez zjawę.,Um insepulto socou %o.,%o foi socad@[ao_ptb] por um renascido.,%o a primit un pumn de la un nemort.,Игрока %o ударил ревенант.,%o је ударен@[adj_1_sr] од стане повратника.,%o blev slagen av en återfödare.,%o bir iskelet tarafından yumruklandı.,%o бу@[adj_1_ua] забит@[adj_4_ua] ревевантом. +%o was slashed by an imp.,OB_IMPHIT,,,,%o byl@[ao_cs] rozsápán@[ao_cs] čertem.,%o blev skåret ned af en spøgelse.,%o wurde von einem Kobold gekratzt.,@[art_gr] %o κόπηκε απο ενα Διάβολο.,%o estis tranĉvundita de diableto.,A %o l@[ao_esp] ha desgarrado un Imp.,A %o l@[ao_esp] desgarró un Imp.,%o joutui pirun sivaltamaksi.,%o a été lacéré@[e_fr] par un diablotin.,%o-t széttépte egy tűzkobold.,%o è stato squarciato da un imp.,%o はインプに切り裂かれた。,%o 은(는) 임프에게 찢겨 죽었다.,%o werd gesneden door een imp.,%o ble kuttet av en imp.,%o został@[ao_pl] rozcięt@[adj_pl] przez diablika.,Um diabrete dilacerou %o.,,%o a fost zgâriat de un drac.,Игрока %o расцарапал имп.,Играча %o је пресеко враг.,%o blev knivhuggen av en imp.,%o bir imp tarafından kesildi.,%o роздер імп. +%o got too close to a cacodemon.,OB_CACOHIT,,,,%o se dostal@[ao_cs] moc blízko ke kakodémonovi.,%o kom for tæt på en cacodæmon.,%o kam dem Cacodämonen zu nahe.,@[art_gr] %o ήτανε πολυ κοντά σε ένα Κακοδαίμονα.,%o tro proksimiĝis al kakodemono.,%o se ha acercado demasiado a un Cacodemonio.,%o se acercó demasiado a un Cacodemonio.,%o meni liian lähelle kakodemonia.,%o s'est approché@[e_fr] trop près d'un Cacodémon.,%o túl közel ment egy kakodémonhoz.,%o si è avvicinato troppo a un cacodemone.,%o はカコデーモンに近づきすぎた。,%o 은(는) 카코데몬과 가까웠다.,%o kwam te dicht bij een cacodemon.,%o kom for nær en kakodemon.,%o pod@[irreg_1_pl] zbyt blisko do kakodemona.,%o chegou muito perto de um cacodemônio.,,%o s-a apropiat prea mult de un cacodemon.,Игрок %o слишком сблизился с какодемоном.,%o се превише приближи@[ao_1_sr] какодемону.,%o kom för nära en cacodemon.,%o bir caco iblisiyle çok yakınlaştı.,%o опини@[adj_2_ua] надто близько до какодемона. +%o was bit by a demon.,OB_DEMONHIT,,,,%o byl@[ao_cs] rozkousán@[ao_cs] démonem.,%o blev bidt af en dæmon.,%o wurde von einem Dämonen gebissen.,@[art_gr] %o δαγκόθηκε απο ένα Δαίμονα.,%o estis mordita de demono.,A %o l@[ao_esp] ha mordido un Demonio.,A %o l@[ao_esp] mordió un Demonio.,%o joutui demonin puremaksi.,%o a été mordu@[e_fr] par un démon.,%o-t megharapta egy démon.,%o è stato sbranato da un demone.,%o はデーモンに噛まれた。,%o 은(는) 데몬에게 물렸다.,%o werd gebeten door een demon.,%o ble bitt av en demon.,%o wpada w szczęki demona.,Um demônio mordeu %o.,,%o a fost mușcat de un demon.,Игрока %o укусил демон.,Играча %o је ујео демон.,%o blev biten av en demon.,%o bir iblis tarafından ısırıldı.,%o покусав демон. +%o was eaten by a spectre.,OB_SPECTREHIT,,,,%o byl@[ao_cs] sežrán@[ao_cs] přízrakem.,%o blev spist af et imp.,%o wurde von dem Schemen gefressen.,Ένα φάντασμα έφαγε @[pro_gr] %o.,%o estis manĝita de fantomo.,A %o l@[ao_esp] ha devorado un Espectro.,A %o l@[ao_esp] devoró un Espectro.,%o joutui haamun syömäksi.,%o a été dévoré@[e_fr] par un spectre.,%o-t felfalta egy lidérc.,%o è stato divorato da uno spettro.,%o はスペクトルに喰われた。,%o 은(는) 스펙터에게 잡아먹혔다.,%o werd opgegeten door een spook.,%o ble spist av et spøkelse.,%o został@[ao_pl] zjedzon@[adj_pl] przez widmo.,Um espectro devorou %o.,,%o a fost mâncat de un spectru.,Игрока %o сожрал фантом.,Играча %o је појео авет.,%o blev uppäten av ett spöke.,%o bir hayalet tarafından yenildi.,%o зжерла примара. +%o was ripped open by a Baron of Hell.,OB_BARONHIT,,,,%o byl@[ao_cs] rozčtvrcen@[ao_cs] baronem pekel.,%o blev flået op af en helvedesbaron.,%o wurde von dem Höllenbaron aufgerissen.,@[art_gr] %o σχίστηκε απο εναν Βαρώνο της Κόλασης.,%o estis disŝirigita de Barono de Infero.,A %o l@[ao_esp] ha hecho trizas un Barón del Infierno.,A %o l@[ao_esp] hizo trizas un Barón del Infierno.,%o joutui hornanparonin auki repimäksi.,%o a été déchiré@[e_fr] par un Baron des Enfers.,%o-t széttépte egy pokolbáró.,%o è stato scoperchiato da un Barone dell'Inferno.,%o はバロンオブヘルに体を抉じ開けられた。,%o 은(는) 바론 오브 헬에게 뜯겨 죽었다.,%o werd opengereten door een Baron van de hel.,%o ble revet opp av en helvetesbaron.,%o został@[ao_pl] rozerwan@[adj_pl] przez Barona Piekła.,Um Barão do Inferno rasgou %o.,%o foi desventrad@[ao_ptb] por um Barão do Inferno.,%o a fost deschis pe viu de un Baron al Infernului.,Игрока %o разорвал барон ада.,%o је поцеп@[adj_2_sr] од стране барон пакла.,%o slets upp av en helvetesbaron.,%o bir Cehennem Baronu tarafından parçalandı.,Барон Пекла роздер %o. +%o was gutted by a Hell Knight.,OB_KNIGHTHIT,,,,%o byl@[ao_cs] vykuchán@[ao_cs] rytířem pekel.,%o blev udtaget af en helvedesridder.,%o wurde von dem Höllenritter ausgenommen.,@[art_gr] %o ξεκοιλιάστηκε απο έναν Ιππότη της Κόλασης.,%o estis senintestigita de Inferkavaliro.,A %o l@[ao_esp] ha destripado un Caballero del Infierno.,A %o l@[ao_esp] destripó un Caballero del Infierno.,%o joutui hornanritarin perkaamaksi.,%o a été étripé@[e_fr] par un un chevalier infernal.,%o-t kibelezte egy pokollovag.,%o è stato sbudellato da un Cavaliere dell'Inferno.,%o はヘルナイトに内臓を抉られた。,%o 은(는) 헬 나이트에게 도륙당했다.,%o werd gestript door een hel ridder.,%o ble sløyet av en helvetesridder.,%o został@[ao_pl] wypatroszon@[adj_pl] przez Rycerza Piekła.,Um Cavaleiro Infernal estripou %o.,%o foi estripad@[ao_ptb] por um Cavaleiro Infernal.,%o a fost măcelărit de un Cavaler al Infernului.,Игрока %o распотрошил рыцарь ада.,Играча %o је унаказио витез пакла.,%o blev uppsliten av en helvetesriddare.,%o bir Cehennem Şövalyesi tarafından parçalandı.,Лицар Пекла розпотрошив %o. +%o was killed by a zombieman.,OB_ZOMBIE,,,,%o byl@[ao_cs] zabit@[ao_cs] zombíkem.,%o blev dræbt af en zombie.,%o wurde von einem Zombie getötet.,@[art_gr] %o σκοτώθηκε απο ένα Ζόμπι.,%o estis mortigita de zombio.,A %o se l@[ao_esp] ha cargado un Zombi.,A %o l@[ao_esp] mató un Zombi.,%o joutui zombin tappamaksi.,%o a été tué@[e_fr] par un zombie.,%o-t megölte egy zombi.,%o è stato ucciso da uno zombie marine.,%o はゾンビ兵に殺された。,%o 은(는) 좀비맨에게 죽었다.,%o werd gedood door een zombie.,%o ble drept av en zombiemann.,%o został@[ao_pl] zabit@[adj_pl] przez zombie.,Um zumbi matou %o.,%o foi mort@[ao_ptb] por um zombie.,%o a fost omorât de un zombi.,Игрока %o убил зомби.,%o је убијен@[adj_1_sr] од стране зомбија.,%o blev dödad av en zombie.,%o bir zombi tarafından öldürüldü.,%o вбив зомбі. +%o was shot by a sergeant.,OB_SHOTGUY,,,,%o byl@[ao_cs] zastřelen@[ao_cs] seržantem.,%o blev skudt af en sergent.,%o wurde von einem Schützen erschossen.,Ένας Λοχίας πυροβόλησε @[pro_gr] %o.,%o estis pafita de serĝento.,A %o l@[ao_esp] ha fusilado un Sargento.,A %o l@[ao_esp] fusiló un Sargento.,%o joutui kersantin ampumaksi.,%o s'est fait@[e_fr] flinguer par un type au fusil.,%o-t lelőtte egy őrmester.,%o è sato impallinato da uno zombie sergente.,%o はゾンビ軍曹に撃たれた。,%o 은(는) 서전트에게 총을 맞았다.,%o werd neergeschoten door een sergeant.,%o ble skutt av en sersjant.,%o został@[ao_pl] zastrzelon@[adj_pl] przez zombie-sierżanta.,Um sargento possuído atirou em %o.,,%o a fost împușcat de un sergent.,Игрока %o застрелил сержант.,Играча %o је погодио водник.,%o blev skjuten av en hagelgevärskille.,%o bir çavuş tarafından vuruldu.,Сержант застрелив %o. +%o was incinerated by an archvile.,OB_VILE,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] veleběsem.,%o blev brændt af en ærkevile.,%o wurde von einem Scheusal verbrannt.,@[art_gr] %o αποτεφρώθηκε απο ένα Νεκρομάντη.,%o estis cindrigita de ĉef-fiulo.,A %o l@[ao_esp] ha incinerado un Arch-Vile.,A %o l@[ao_esp] incineró un Arch-Vile.,%o joutui arkkihirvityksen kärventämäksi.,%o a été incinéré@[e_fr] par un Arche-Vile.,%o-t megpörkölte egy ősármány.,%o è stato incenerito da un arch-vile.,%o はアーチバイルに焼き尽くされた。,%o 은(는) 아크-바일에 의해 소각되었다.,%o werd verbrand door een aartsvijand.,%o ble brent av en erkefiende.,%o został@[ao_pl] spalon@[adj_pl] przez arcypodleca.,Um arquivil incinerou %o.,,%o a fost incinerat de un abject.,Игрока %o заживо сжёг архвиль.,Играча %o је запалио арчвајл.,%o blev förbränd av en ärkevilde,%o bir iğrençlik tarafından yakıldı.,Арчвайл спалив вщент %o. +%o couldn't evade a revenant's fireball.,OB_UNDEAD,,,,%o se nevyhnul@[ao_cs] umrlčí ohnivé kouli.,%o kunne ikke undvige en ildkugle fra en hævnen.,%o konnte dem Feuerball des Wiederauferstandenen nicht ausweichen.,@[art_gr] %o δέν μπορούσε να αποφείγει τον πύραυλο ενός Εκδικητή.,%o ne povis eviti fajrobulon de renaskitulo.,A %o l@[ao_esp] ha hecho reventar un Revenant.,A %o l@[ao_esp] hizo reventar un Revenant.,%o ei kyennyt väistämään henkiinpalanneen tulipalloa.,%o n'a pas réussi à esquiver un missile de revenant.,%o nem tudta kivédeni egy kísértet tűzgolyóját.,%o non ha potuto evitare il missile di un revenant.,%o はレバナントのファイアボールを回避できなかった。,%o 은(는) 레버넌트의 화염구를 피하지 못했다.,%o kon de vuurbal van een wraakzuchtige niet ontwijken.,%o klarte ikke å unngå en gjengangers ildkule.,%o nie udaje się uniknąć pocisku od zjawy.,%o não conseguiu desviar do míssil do insepulto.,%o não conseguiu desviar do míssil do renascido.,%o n-a putut scăpa de mingea de foc a nemortului.,Игрок %o не успел увернуться от снаряда ревенанта.,%o није мог@[ao_2_sr] да избегне повратникову пламену куглу.,%o kunde inte undvika en återfödds eldklot.,%o bir iskeletin ateş topundan kaçamadı.,Снаряд ревенанта дістав %o. +%o was squashed by a mancubus.,OB_FATSO,,,,%o byl@[ao_cs] rozmačkán@[ao_cs] mankubem.,%o blev knust af en mankubus.,%o wurde von einem Mancubus plattgemacht.,@[art_gr] %o λιόθηκε απο έναν Χοντρό.,%o estis dispremita de mankubo.,A %o l@[ao_esp] ha pulverizado un Mancubus.,A %o l@[ao_esp] pulverizó un Mancubus.,%o joutui mankubuksen liiskaamaksi.,%o s'est fait@[e_fr] aplatir par un Mancube.,%o-t szétlapította egy mankubusz.,%o è stato disintegrato da un mancubus.,%o はマンキュバスに潰された。,%o 은(는) 맨큐버스에게 짓이겨졌다.,%o werd verpletterd door een mancubus.,%o ble knust av en mancubus.,%o został@[ao_pl] zmiażdżon@[adj_pl] przez antropokuba.,Um mancubus esmagou %o.,,%o a fost strivit de un mancubus.,Игрока %o раздавил манкубус.,Играча %o је изгњечио манкубус.,%o blev krossad av en mancubus.,%o bir mancubus tarafından ezildi.,%o розчавлено манкубусом. +%o was perforated by a chaingunner.,OB_CHAINGUY,,,,%o byl@[ao_cs] prostřelen@[ao_cs] kulometčíkem.,%o blev perforeret af en chaingunner.,%o wurde von einem MG-Schützen perforiert.,@[art_gr] %o εκτελέστικε απο ένα Ζόμπι με ένα πολυβόλο.,%o estis truigadita de maŝinpafilisto.,A %o l@[ao_esp] ha perforado un Ametrallador.,A %o l@[ao_esp] perforó un Ametrallador.,%o joutui konekiväärimiehen rei'ittämäksi.,%o a été perforé@[e_fr] par un mitrailleur.,%o-t szitává lőtte egy kommandós.,%o è stato perforato da uno zombie commando.,%o はチェインガンナーに蜂の巣にされた。,%o 은(는) 체인거너에 의해 벌집이 됐다.,%o werd geperforeerd door een zware wapens kerel.,%o ble perforert av en chaingunner.,%o został@[ao_pl] przedziurawion@[adj_pl] przez ciężkozbrojnego zombie.,Um comando possuído perfurou %o.,%o foi perfurad@[ao_ptb] por um metrelhador.,%o a fost perforat de un mitralior.,Игрока %o продырявил пулемётчик.,Играча %o је изрешетао митраљезац.,%o blev perforerad av en tunga vapen kille.,%o bir ağır silah tarafından delindi.,%o отрима@[adj_1_ua] численні отвори від куль кулеметника. +%o was spooked by a lost soul.,OB_SKULL,,,,%o se lekl@[ao_cs] ztracené duše.,%o blev skræmt af en fortabt sjæl.,%o wurde von einer Verlorenen Seele heimgesucht.,Μια Χαμένη Ξυχή φόβησε @[pro_gr] %o.,%o estis timigita de perdita animo.,%o se ha muerto de miedo con un Alma Errante.,%o se murió de miedo con un Alma Errante.,%o joutui kadonneen sielun säikäyttämäksi.,%o s'est fait@[e_fr] surprendre par une âme perdue.,%o-t halálra ijesztette egy kóbor lélek.,%o è stato spaventato a morte da un'Anima Errante.,%o はロストソウルにビビらされた。,%o 은(는) 로스트 소울을 보고 깜짝 놀랐다.,%o werd bang gemaakt door een verloren ziel.,%o ble skremt av en fortapt sjel.,%o został@[ao_pl] przestraszon@[adj_pl] przez zaginioną duszę.,Uma alma penada assustou %o.,%o se assustou com uma alma penada.,%o a fost speriat de un suflet pierdut.,Игрок %o запуган до смерти потерянной душой.,%o је уплашен@[adj_1_sr] од изгубљене душе.,%o blev skrämd av en förlorad själ.,%o kayıp bir ruh tarafından korkutuldu.,Заблудла душа перестрашила %o. +%o was burned by an imp.,OB_IMP,,,,%o byl@[ao_cs] spálen@[ao_cs] čertem.,%o blev brændt af en spøgelse.,%o wurde von einem Kobold verbrannt.,@[art_gr] %o κάικε απο έναν Διάβολο.,%o estis bruligita de diableto.,A %o l@[ao_esp] ha calcinado un Imp.,A %o l@[ao_esp] calcinó un Imp.,%o joutui pirun polttamaksi.,%o brûlé@[e_fr] par un diablotin.,%o-t szénné égette egy tűzkobold.,%o è stato bruciato da un imp.,%o はインプに焼かれた。,%o 은(는) 임프에게 불태워졌다.,%o werd verbrand door een imp.,%o ble brent av en imp.,%o został@[ao_pl] spalon@[adj_pl] przez diablika.,Um diabrete queimou %o.,,%o a fost ars de un demon.,Игрока %o сжёг имп.,%o је изгорен@[adj_1_sr] од стране врага.,%o blev bränd av en imp.,%o bir imp tarafından yakıldı.,%o спалено імпом. +%o was smitten by a cacodemon.,OB_CACO,,,,%o byl@[ao_cs] udeřen@[ao_cs] kakodémonem.,%o blev ramt af en cacodæmon.,%o wurde von einem Cacodämonen gequält.,@[art_gr] %o καίκε απο έναν Κακοδαίμονα.,%o estis venkobatita de kakodemono.,A %o l@[ao_esp] ha cascado un Cacodemonio.,A %o l@[ao_esp] cascó un Cacodemonio.,%o joutui kakodemonin iskemäksi.,%o a été terrassé@[e_fr] par un Cacodémon.,%o-ra lesújtott egy kakodémon.,%o è stato abbattuto da un cacodemone.,%o はカコデーモンに裁きを受けた。,%o 은(는) 카코데몬에게 엄습 당했다.,%o werd geslagen door een cacodemon.,%o ble slått av en kakodemon.,%o został@[ao_pl] porażon@[adj_pl] przez kakodemona.,Um cacodemônio golpeou %o.,,%o a fost lovit de un cacodemon.,Игрока %o поразил какодемон.,Играча %o је ударио какодемон.,%o blev förkrossad av en cacodemon.,%o bir caco iblisi tarafından vuruldu.,%o уражено какодемоном. +%o was bruised by a Baron of Hell.,OB_BARON,,,,%o byl@[ao_cs] pomačkán@[ao_cs] baronem pekel.,%o blev såret af en helvedesbaron.,%o wurde von einem Höllenbaron geröstet.,@[art_gr] %o γρατζουνήθηκε απο ένα Βαρώνο της Κόλασης.,%o estis kontuzita de Barono de Infero.,A %o l@[ao_esp] ha magullado un Barón del Infierno.,A %o l@[ao_esp] magulló un Barón del Infierno.,%o joutui hornanparonin ruhjomaksi.,%o a été démoli@[e_fr] par un Baron des Enfers.,%o-t összezúzta egy pokolbáró.,%o è stato scorticato da un Barone Infernale.,%o はバロンオブヘルに痛めつけられた。,%o 은(는) 바론 오브 헬에게 상처받았다.,%o werd gekneusd door een baron van de hel.,%o ble forslått av en helvetesbaron.,%o został@[ao_pl] stłuczon@[adj_pl] Barona Piekła.,Um Barão do Inferno feriu %o.,,%o a fost contuzionat de un Baron al Infernului.,Игрок %o зашиблен бароном ада.,%o је мод@[adj_3_sr] због барона пакла.,%o blev skadad av en helvetesbaron.,%o bir Cehennem Baronu tarafından yaralandı.,%o потовчено бароном Пекла. +%o was splayed by a Hell Knight.,OB_KNIGHT,,,,%o byl@[ao_cs] rozpůlen@[ao_cs] rytířem pekel.,%o blev splejset af en helvedesridder.,%o wurde von einem Höllenritter gebraten.,@[art_gr] %o απλώθηκε απο έναν Ιππότη της Κόλασης,%o estis bisekcita de Inferkavaliro.,A %o l@[ao_esp] ha partido en dos un Caballero del Infierno.,A %o l@[ao_esp] partió en dos un Caballero del Infierno.,%o joutui hornanritarin repimäksi.,%o a été éclaté@[e_fr] par un chevalier infernal.,%o-t kilapította egy pokollovag.,%o è stato squartato da un Cavaliere Infernale.,%o はヘルナイトにバラ撒かれた。,%o 은(는) 헬 나이트에게 갈라졌다.,%o werd gespierd door een hel ridder.,Jeg ble sprettet opp av en helvetesridder.,%o został@[ao_pl] rozcapierzon@[adj_pl] przez Rycerza Piekła.,Um Cavaleiro Infernal espalmou %o.,%o foi espalmad@[ao_ptb] por um Cavaleiro Infernal.,%o a fost scrântit de un Cavaler al Infernului.,Игрока %o распластал рыцарь ада.,%o је раширен@[adj_1_sr] због витеза пакла.,%o blev spretad av en helvetesriddare.,%o bir Cehennem Şövalyesi tarafından yere serildi.,Лицар Пекла розкатав %o. +%o stood in awe of the spider demon.,OB_SPIDER,,,,%o zůstal@[ao_cs] stát v úžasu před pavoučím démonem.,%o stod i ærefrygt for edderkoppedæmonen.,%o stand in Ehrfurcht vor dem Spinnendämon.,@[art_gr] %o στάθηκε με δέος μπροστά στόν αραχνοδαίμονα.,%o staris mirigita antaŭ la aranedemono.,%o se ha arrodillado ante la Mente-Maestra Arácnida.,%o se arrodilló ante la Mente-Maestra Arácnida.,%o kunnioitti syvästi hämähäkkidemonia,%o est resté pris@[e_fr] d'admiration devant le Démon Arachnéen.,%o halálra ijedt a Pókelme.,%o è stato soggiogato dal Ragno demoniaco.,%o はスパイダーデーモンに恐れをなした。,%o 은(는) 거미악마의 무자비함을 느꼈다.,%o stond in ontzag voor de spindemon.,%o sto i ærefrykt for edderkoppdemonen.,%o podziwiał@[ao_pl] pajęczego mistrza.,%o ajoelhou-se em frente à Aranha-Mestra.,,%o a stat înfricoșat în fața păianjenului maestru.,Игрок %o стоял в восторге перед пауком-предводителем.,%o се смрзну@[ao_1_sr] у очарању паук-руководилаца.,%o stod i vördnad inför spindeldemonen.,%o örümcek iblisin karşısında huşu içinde durdu.,%o бу@[adj_1_ua] захоплен@[ao_ua] могутністю павука-воєводи. +%o let an arachnotron get %h.,OB_BABY,,,,%o se nechal@[ao_cs] dostat arachnotronem.,%o blev sprængt af en arachnotron.,%o ließ sich von einem Arachnotron erledigen.,@[art_gr] %o άφησε ένα Αράχνοτρον να @[pro_gr] σκοτώσει.,%o lasis elektraraneon venki @[pro_eo]n.,A %o l@[ao_esp] ha alcanzado un Aracnotrón.,A %o l@[ao_esp] alcanzó un Aracnotrón.,%o antoi anaktrotronin saada hänet.,%o a laissé un arachnotron l'avoir@[e_fr].,"%o hagyta, hogy elkapja egy póktron.",%o ha permesso che un arachnotron l'uccidesse.,%o が アラクノトロンに討ち取られた。,%o 은(는) 아라크노트론이 %o를(을) 죽이도록 놔두었다.,%o werd gedood door een arachnotron,%o ble sprengt av et arachnotron.,%o pozwolił@[ao_pl] arachnotronowi się do siebie dobrać.,Uma arachnotron pegou %o.,%o foi apanhad@[ao_ptb] por uma arachnotron.,%o s-a lăsat prins de un aracnotron.,Игрок %o дал себя на откуп арахнотрону.,%o је допусти@[ao_1_sr] да паукотрон дође до %h.,%o lät en arachnotron ta @[ref_sv].,%o bir araknotronun onu yakalamasına izin verdi.,%o да@[adj_1_ua] арахнотрону себе вбити. +%o was splattered by a cyberdemon.,OB_CYBORG,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] na kaši kyberdémonem.,%o blev splattet af en cyberdæmon.,%o wurde von einem Cyberdämon zerfetzt.,@[art_gr] %o έσκασε απο ένα Cyber-δαίμονα.,%o estis disŝprucigita de ciberdemono.,A %o l@[ao_esp] ha hecho pedazos un Ciberdemonio.,A %o l@[ao_esp] hizo pedazos un Ciberdemonio.,%o joutui kyberdemonin yltympäri roiskimaksi.,%o a été pulvérisé@[e_fr] par un Cyberdémon.,%o-t cafatokra tépték a kiberdémon rakétái.,%o è stato spiaccicato da un Cyberdemone.,%o はサイバーデーモンにバラバラにされた。,%o 은(는) 사이버데몬에 의해 산산조각이 났다.,%o werd gespetterd door een cyberdemon.,%o ble sprutet av en kyberdemon.,%o został@[ao_pl] rozbryzgan@[adj_pl] przez cyberdemona.,Um Ciberdemônio arrebentou %o.,,%o a fost împroșcat de ciberdemon.,Игрока %o размазал кибердемон.,%o је спљоштен@[adj_1_sr] од стране сајбердемона,%o blev sönderslagen av en cyberdemon.,%o bir siber iblis tarafından parçalandı.,Кібердемон перетворив %o в хмарину крові. +%o met a Nazi.,OB_WOLFSS,,,,%o potkal@[ao_cs] nácka.,%o mødte en nazist.,%o traf einen Nazi.,@[art_gr] %o χνώρισε ένα Ναζιστή.,%o renkontis Nazion.,%o se ha topado con un Nazi.,%o se topó con un Nazi.,%o tapasi natsin.,%o a rencontré un Nazi.,%o találkozott egy nácival.,%o ha incontrato un Nazista.,%o はナチ兵と遭遇した。,%o 은(는) 나치를 만났다.,%o ontmoette een nazi.,Jeg møtte en nazist.,%o spotkał@[ao_pl] nazistę.,%o encontrou um Nazista.,%o encontrou um Nazi.,%o a întâlnit un Nazist.,Игрок %o встретил нациста.,%o је упозна@[ao_1_sr] нацисту.,%o mötte en nazist.,%o bir Nazi ile karşılaştı.,%o зустрі@[adj_1_ua] нациста. +%o was mauled by a dog.,OB_DOG,,,,%o byl@[ao_cs] roztrhán@[ao_cs] psem.,%o blev mast af en hund.,%o wurde von einem Hund zerrissen.,@[art_gr] %o φαγόθικε απο ένα σκύλο.,%o estis atakita de hundo.,A %o l@[ao_esp] ha despedazado un Perro.,A %o l@[ao_esp] despedazó un Perro.,%o joutui koiran raatelemaksi.,%o s'est fait mordre par un chien.,%o-t szétmarcangolta egy kutya.,%o è stato sbranato da un cane.,%o は犬に引き裂かれた。,%o 은(는) 개한테 으스러졌다.,%o werd verminkt door een hond.,%o ble maltraktert av en hund.,%o został@[ao_pl] poturbowan@[adj_pl] przez psa.,Um cachorro mutilou %o.,%o foi mutilad@[ao_ptb] por um cão.,%o a fost sfâșiat de un câine.,Игрока %o разорвала собака.,Играча %o је удавио пас.,%o blev misshandlad av en hund.,%o bir köpek tarafından parçalandı.,%o загризла собака. +%o chewed on %k's fist.,OB_MPFIST,,,,%o si pochutnal@[ao_cs] na pěsti hráče %k.,%o tyggede på %ks knytnæve.,%o kaute auf %ks Faust herum.,@[art_gr] %o μάσησε τη γροθία του/της %k.,%o maĉis la pugnon de %k.,%o se ha comido el puño de %k.,%o se comió el puño de %k.,%k rusikoi %o paran.,%o a bouffé le poing de %k.,%o megkóstolta %k ökleit.,%o si è schiantato contro il pugno di %k.,%o は %k の拳を顔面に受けた。,%o 은(는) %k 의 주먹을 물었다.,%o gekauwd op %k's vuist.,%o tygget på %ks knyttneve.,%o przygryza pięść %k.,%k espancou %o até a morte.,,%o a mestecat pumnul lui %k.,Игрок %o отведал кулака игрока %k.,Играча %o је сажвакао песницу играча %k.,%o tuggade på %ks knytnäve.,"%o, %k tarafından öldürüldü.",%o відчу@[adj_1_ua] кулак %k. +%o was mowed over by %k's chainsaw.,OB_MPCHAINSAW,,,,%o byl@[ao_cs] zkácen@[ao_cs] motorovkou hráče %k.,%o blev slået ned af %ks motorsav.,%o wurde von %ks Kettensäge zerteilt.,@[art_gr] %o κόπηκε απο το αλλησοπρίονο του/της %k.,%o estis buĉita de la ĉensegilo de %k.,Ha habido matanza de %o con la motosierra de %k.,Hubo mascare de %o con la motosierra de %k.,%k katkoi %o paran.,%o a été tondu@[e_fr] par la tronconneuse de %k.,%o-t kettészelte %k láncfűrésze.,%o è stato falciato dalla motosega di %k.,%o は %k のチェーンソーで刈り取られた。,%o 은(는) %k 의 전기톱에 갈렸다.,%o werd gemaaid met %k's kettingzaag.,%o ble klippet over av %ks motorsag.,%o został@[ao_pl] skoszon@[adj_pl] przez piłę łańcuchową %k.,%k fez picadinho de %o com sua motoserra.,,%o a fost tăiat de drujba lui %k.,Игрока %o разрезал бензопилой игрок %k.,%o је исечен@[adj_1_sr] моторном тестером играча %k.,%o blev överkörd av %ks motorsåg.,"%o, %k tarafından biçildi",%k розпили@[adj_1_ua] %o бензопилою. +%o was tickled by %k's pea shooter.,OB_MPPISTOL,,,,%o byl@[ao_cs] polechtán@[ao_cs] pistolkou hráče %k.,%o blev kildet af %ks ærteskytte.,%o wurde von %ks Erbsenpistole gekitzelt.,@[art_gr] %o γαργαλίθηκε απο το οπλάκι του/της %k.,%o estis tiklita de la pistolo de %k.,A %o le ha hecho cosquillas la pistola de %k.,A %o le hizo cosquillas la pistola de %k.,%o kutitti %o parkaa hernepyssyllään.,%o a été châtouillé@[e_fr] par le pistolet de %k.,%o meg lett csiklandozva %k játékpisztolyával.,%o è stato sforacchiato dalla pistola di %k'.,%o は %k の豆鉄砲でくすぐられた。,%o 은(는) %k 의 권총에 간지럼을 탔다.,%o werd gekieteld door %k's erwtenschutter.,%o ble kilt av %ks ertebøsse.,%o został@[ao_pl] połaskotan@[adj_pl] przez spluwę %k.,%k fez cócegas em %o com sua pistolinha.,,%o a fost gâdilat de pistolașul lui %k.,Игрока %o защекочен вусмерть из горохострела игрока %k.,%o је заголицан@[adj_1_sr] пиштољем играча %k.,%o blev kittlad av %ks ärtskytt.,"%o, %k tarafından gıdıklandı",%o бу@[adj_1_ua] заколупан@[ao_ua] пістолетом %k. +%o chewed on %k's boomstick.,OB_MPSHOTGUN,,,,%o si pochutnal@[ao_cs] na brokádě hráče %k.,%o tyggede på %ks bommestok.,%o wurde Opfer von %ks Schrotflinte.,@[art_gr] %o έφαγε το ντουφέκι του/της %k.,%o maĉis la kartoĉan fusilon de %k.,A %o l@[ao_esp] ha agujereado la escopeta de %k.,A %o l@[ao_esp] agujereó la escopeta de %k.,%k jauhoi %o paran tussarillaan.,%o a s'est mangé@[e_fr] de la chevrotine de la part de %k.,%o megízlelte %k villámbotját.,%o si è trovato davanti il fucile di %k.,%o は %k のブームスティックを顔面に受けた。,%o 은(는) %k 의 붐스틱에 꽂혔다.,%o gekauwd op %k's boomstick.,%o tygget på %ks boomstick.,%o przygryza pukawkę %k.,%k meteu chumbo em %o com sua espingarda.,,%o a mestecat pușca lui %k.,Игрока %o накормил дробью игрок %k.,%o је сажвака@[ao_1_sr] на пумпарицу играча %k.,%o tuggade på %ks bomstock.,"%o, %k tarafından patlatıldı",%k насипа@[adj_1_ua] свинцевого гороху %o. +%o was splattered by %k's super shotgun.,OB_MPSSHOTGUN,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] na kaši superbrokovnicí hráče %k.,%o blev sprøjtet af %ks super haglgevær.,%o wurde von %ks Super-Schrotflinte zerfetzt.,@[art_gr] %o διαλύθηκε απο το διπλό ντουφέκι του/της %k,%o estis disŝprucigita de la dutuba fusilo de %k.,A %o l@[ao_esp] reventado la superescopeta de %k.,A %o l@[ao_esp] reventó la superescopeta de %k.,%k roiski %o paran yltympäriinsä superhaulikollaan.,%o s'est fait@[e_fr] gicler par le fusil de chasse de %k.,%o-t cafatokra tépte %k szupersörétese.,%o è stato smembrato dalla doppietta di %k.,%o は %k のスーパーショットガンでバラバラにされた。,%o 은(는) %k 의 슈퍼 샷건에 의해 터졌다.,%o werd gespat door %k's super jachtgeweer.,%o ble skutt med %ks super-haglgevær.,%o został@[ao_pl] rozpryskan@[adj_pl] przez super strzelbę %k.,%k estraçalhou %o com sua espingarda de cano duplo.,,%o a fost împroșcat de super pușca lui %k.,Игрока %o размазал из супердробовика игрок %k.,Играча %o је спљоштила двоцевка играча %k.,%o blev besprutat av %ks super-hagelgevär.,"%o, %k tarafından sıçratıldı",%k розмаза@[adj_1_ua] з двустволки %o. +%o was mowed down by %k's chaingun.,OB_MPCHAINGUN,,,,%o byl@[ao_cs] prostřílen@[ao_cs] kulometem hráče %k.,%o blev mejet ned af %ks maskingevær.,%o wurde von %ks Maschinengewehr niedergemäht.,@[art_gr] %o κοματίαστηκε απο το πολυβόλο του/της %k.,%o estis kuglo-plenigita de la maŝinpafilo de %k.,A %o l@[ao_esp] ha dejado hecho colador la ametralladora de %k.,A %o l@[ao_esp] dejó hecho colador la ametralladora de %k.,%k niitti %o paran konekiväärillään.,%o a été ventilé@[e_fr] par la mitrailleuse de %k.,%k gépágyúval szétszaggatta %o testét.,%o è stato falciato dal mitragliatore di %k.,%o は %k のチェーンガンで蜂の巣にされた。,%o 은(는) %k 의 체인건에 의해 으깨졌다.,%o werd gemaaid met %k's machinegeweer.,%o ble meiet ned av %ks maskinpistol.,%o został@[ao_pl] skoszon@[adj_pl] przez karabin maszynowy %k.,%k massacrou %o com sua metralhadora.,,%o a fost secerat de mitraliera rotativă a lui %k.,Игрок %o скошен из пулемёта игрока %k.,%o је покоси@[ao_1_sr] митраљез играча %k.,%o blev nedklippt av %ks kedjepistol.,"%o, %k tarafından biçildi",%k скоси@[adj_1_ua] кулеметом %o. +%o rode %k's rocket.,OB_MPROCKET,,,,%o se projel@[ao_cs] na raketě hráče %k.,%o red på %ks raket.,%o ritt auf %ks Rakete.,@[art_gr] %o καβάλησε τον πύραυλο του/της %k.,%o rajdis la raketon de %k.,%o ha montado el misil de %k.,%o montó el misil de %k.,%o ratsasti pelaajan %k raketilla.,%o a chevauché la roquette de %k.,%o meglovagolta %k rakétáját.,%o ha cavalcato il razzo di %k.,%o は %k のロケットに乗ってしまった。,%o 은(는) %k 의 로켓을 탔다.,%o reed op %k's raket.,%o red på %ks rakett.,%o ujeżdżał@[ao_pl] rakietę %k.,%o não viu o foguete de %k.,%o não viu o míssil de %k.,%o a călărit racheta lui %k.,Игрок %o прокатился на ракете игрока %k.,%o је ујаха@[ao_1_sr] ракету играча %k.,%o åkte på %ks raket.,"%o, %k tarafından sıçratıldı",%o проїха@[adj_2_ua] на ракеті %k. +%o almost dodged %k's rocket.,OB_MPR_SPLASH,,,,%o se skoro vyhnul@[ao_cs] raketě hráče %k.,%o undgik næsten %ks raket.,"%o schaffte es fast, %ks Rakete auszuweichen.",@[art_gr] %o σχεδόν απόφηγε τον πύραυλο του/της %k.,%o preskaŭ evitis la raketon de %k.,%o casi esquiva el misil de %k.,,%o melkein väisti pelaajan %k raketin.,%o a presque esquivé la roquette de %k.,%o majdnem kitért %k rakétája elől.,%o aveva quasi schivato il razzo di %k.,%o は %k のロケットをあと少しで避けられそうだった。,%o 은(는) %k 의 로켓 폭발을 거의 피했다.,%o ontweek bijna %k's raket.,%o unngikk nesten %ks rakett.,%o prawie unika rakiety %k.,%o quase escapou do foguete de %k.,%o quase escapou do míssil de %k.,%o aproape a evitat racheta lui %k.,Игрок %o почти увернулся от ракеты %k.,%o је за длаку избега@[ao_1_sr] ракету играча %k.,%o undvek nästan %ks raket.,"%o, %k tarafından sıçratıldı",%o майже укникну@[adj_1_ua] ракети %k. +%o was melted by %k's plasma gun.,OB_MPPLASMARIFLE,,,,%o se roztekl@[ao_cs] plazmapuškou hráče %k.,%o blev smeltet af %ks plasma riffel.,%o wurde von %ks Plasmagewehr geschmolzen.,@[art_gr] %o λίοθηκε απο το πλάσμα όπλο του/της %k.,%o estis fandigita de la plasmo-pafilo de %k.,A %o l@[ao_esp] ha derretido el fusil de plasma de %k.,A %o l@[ao_esp] derritió el fusil de plasma de %k.,%k sulatti %o paran plasmapyssyllään.,%o a été réduit@[e_fr] en bouillie par le fusil a plasma de %k.,%k plazmafegyverével megolvaszotta %o testét.,%o è stato fuso dal fucile al plasma di %k.,%o は %k のプラズマガンに溶かされた。,%o 은(는) %k 의 플라즈마 건에 의해 융해되었다.,%o was gesmolten door %k's plasmageweer.,%o ble smeltet av %ks plasmakanon.,%o został@[ao_pl] stopion@[adj_pl] przez pistolet plasmowy %k.,%k torrou %o com seu fuzil de plasma.,%o foi torrad@[ao_ptb] pela pistola de plasma de %k.,%o a fost topit de pușca cu plasmă a lui %k.,Игрока %o расплавил из плазмомёта игрок %k.,%o је отопљен@[adj_1_sr] плазма оружјем играча %k.,%o smältes av %ks plasmagevär.,"%o, %k tarafından eritildi",%k розплавив з плазмагана %o. +%o was splintered by %k's BFG.,OB_MPBFG_BOOM,,,,%o byl@[ao_cs] rozštěpen@[ao_cs] BFGčkem hráče %k.,%o blev splintret af %ks BFG.,%o wurde von %ks BFG in Stücke gerissen.,@[art_gr] %o κοματιάστηκε απο το BFG του/της %k.,%o estis splitigita de la BFG de %k.,A %o l@[ao_esp] ha astillado la BFG de %k.,A %o l@[ao_esp] astilló la BFG de %k.,%k pirstoi %o paran BFG:llään.,%o a été oblitéré@[e_fr] par le BFG de %k.,%o teste atomjaira szakadt %k BFG-jétől.,%o è stato sminuzzato dal BFG di %k.,%o は %k のBFGで木っ端微塵にされた。,%o 은(는) %k 의 BFG덕에 산산조각 났다.,%o was versplinterd door %k's BFG.,%o ble splintret av %ks BFG.,%o został@[ao_pl] rozpryskan@[adj_pl] przez BFG %k.,%k vaporizou %o com sua BFG.,,%o a fost despicat de către BFG-ul lui %k.,Игрока %o порвал на осколки выстрел из BFG игрока %k.,%o је расцепан@[adj_1_sr] ВЈП играча %k.,%o splittrades av %ks BFG.,"%o, %k tarafından parçalandı",%o розірвало снарядом БФГ %k. +%o couldn't hide from %k's BFG.,OB_MPBFG_SPLASH,,,,%o se nemohl@[ao_cs] ukrýt před BFGčkem hráče %k.,%o kunne ikke gemme sig for %ks BFG.,%o konnte sich nicht vor %ks BFG verstecken.,@[art_gr] %o δέν μπόρεσε να κρυφτέι απο το BFG του/της %k.,%o ne povis kaŝi sin de la BFG de %k.,%o no ha conseguido esconderse de la BFG de %k.,%o no logró esconderse de la BFG de %k.,%o ei kyennyt piiloutumaan pelaajan %k BFG:ltä.,%o n a pas pu se couvrir du BFG de %k.,%o nem tudott elmenekülni %k BFG-je elől.,%o non poteva nascondersi dal BFG di %k.,%o は %k のBFGから隠れることはできなかった。,%o 은(는) %k 의 BFG의 일격으로부터 피할 수 없었다.,%o kon zich niet verbergen voor %k's BFG.,%o kunne ikke gjemme seg for %ks BFG.,%o nie może się schować przed BFG %k.,%o não conseguiu se esconder da BFG de %k,,%o nu s-a putut ascunde de BFG-ul lui %k.,Игрок %o не успел спрятаться от BFG игрока %k.,%o се није мог@[ao_2_sr] сакрити од ВЈП играча %k.,%o kunde inte gömma sig för %ks BFG.,"%o, %k tarafından parçalandı",%o не встиг@[adj_3_ua] сховатись від БФГ %k. +%o was railed by %k.,OB_RAILGUN,,,,%o byl@[ao_cs] napíchnut@[ao_cs] hráčem %k.,%o blev skudt af %k.,%o stand in %ks Schusslinie.,@[art_gr] %o καρφόθηκε απο τον/την %k.,%o estis traborita de la elektropafilo de %k.,A %o l@[ao_esp] ha agujereado el cañón de riel de %k.,A %o l@[ao_esp] agujereó el cañón de riel de %k.,%o lävisti %o paran.,%o a été aligné@[e_fr] par %k.,%o beleállt %k lézerébe.,%o è stato bucherellato dal railgun di %k.,%o は %k のレールガンで死亡した。,%o 은(는) %k 의 레일건에 관통당했다.,%o werd gespaakt door %k.,%o ble skutt av %k.,%o stał@[ao_pl] na linii ognia %k.,%k acertou %o com seu canhão elétrico.,,%o a fost ocărit de %k.,Игрока %o пробил насквозь игрок %k.,%o је убијен@[adj_1_sr] од играча %k.,%o blev fördärvad av %k.,%o %k tarafından kovuldu.,%k прониза@[adj_1_ua] %o наскрізь. +%o was burned by %k's BFG.,OB_MPBFG_MBF,,,,%o shořel@[ao_cs] BFGčkem hráče %k.,%o blev brændt af %ks BFG.,%o wurde von %ks BFG verbrannt.,@[art_gr] %o κάικε απο το BFG του/της %k.,%o estis bruligita de la BFG de %k.,A %o l@[ao_esp] ha calcinado la BFG de %k.,A %o l@[ao_esp] calcinó la BFG de %k.,%k korvensi %o paran BFG:llään.,%o a été irradié@[e_fr] par le BFG de %k.,%k hamuvá égette %o testét BFG-vel.,%o è stato bruciato dal BFG di %k.,%o は %k のBFGで焼き殺された。,%o 은(는) %k 의 BFG에 의해 타올랐다.,%o werd verbrand door %k's BFG.,%o ble brent av %ks BFG.,%o został@[ao_pl] spalon@[adj_pl] przez BFG %k.,%k cozinhou %o com sua BFG.,,%o a fost ars de BFG-ul lui %k.,Игрока %o сжёг из BFG игрок %k.,%o је изгоре@[ao_1_sr] од ВЈП играча %k.,%o blev bränd av %ks BFG.,%o %k tarafından yakıldı,%o спалило БФГ %k. +,,Heretic,,,,,,,,,,,,,,,,,,,,,,,,,, +,,Pickup ,,,,,,,,,,,,,,,,,,,,,,,,,, +Blue Key,TXT_GOTBLUEKEY,,,,Modrý klíč,Blå nøgle,Blauer Schlüssel,Μπλέ Κλειδί,Blua Ŝlosilo,Llave Azul,,Sininen avain,Clé Bleue,Kék kulcs,Chiave blu,青の鍵,청색 열쇠,Blauwe sleutel,Blå nøkkel,Niebieski klucz,Chave Azul,,Cheie Albastră,Синий ключ,Плави кључ,Blå nyckel,Mavi Anahtar,Синій ключ +Yellow Key,TXT_GOTYELLOWKEY,,,,Žlutý klíč,Gul nøgle,Gelber Schlüssel,Κύτρινο Κλειδί,Flava Ŝlosilo,Llave Amarilla,,Keltainen avain,Clé Jaune,Sárga kulcs,Chiave gialla,黄の鍵,황색 열쇠,Gele sleutel,Gul nøkkel,Żółty klucz,Chave Amarela,,Cheie Galbenă,Жёлтый ключ,Жути кључ,Gul nyckel,Sarı Anahtar,Жовтий ключ +Green Key,TXT_GOTGREENKEY,,,,Zelený klíč,Grøn nøgle,Grüner Schlüssel,Πράσινο Κλειδί,Verda Ŝlosilo,Llave Verde,,Vihreä avain,Clé Verte,Zöld kulcs,Chiave verde,緑の鍵,녹색 열쇠,Groene sleutel,Grønn nøkkel,Zielony klucz,Chave Verde,,Cheie Verde,Зелёный ключ,Зелени кључ,Grön nyckel,Yeşil Anahtar,Зелений ключ +Quartz Flask,TXT_ARTIHEALTH,,,,Blyštivá baňka,Kvartsflaske,Quarzflasche,Φλάσκα Χαλαζίας,Kvarca Flakono,Frasco de Cuarzo,,Kvartsipullo,Flasque en Quartz,Kvarc flaska,Ampolla di quarzo,石英フラスコ,석영 플라스크,Kwartskolf,Kvartskolbe,Kwarcowa Butelka,Frasco de Quartzo,,Flacon de Quartz,Кварцевый флакон,Кварцна боца,Kvartsflaska,Kuvars Şişesi,Кварцова пляшечка +Wings of Wrath,TXT_ARTIFLY,,,,Křídla hněvu,Vredens vinger,Flügel des Zorns,Φτερά της Οργής,Flugiloj de Kolero,Alas de Ira,,Kiihtymyksen siivet,Ailes du Courroux,A Harag Szárnyai,Ali iraconde,レイスの翼,분노의 날개,Vleugels der Toorn,Vredens vinger,Skrzydła Gniewu,Asas da Ira,,Aripile Furiei,Крылья гнева,Крила гнева,Vridsvingar,Gazap Kanatları,Крила гніву +Ring of Invincibility,TXT_ARTIINVULNERABILITY,,,,Prsten nesmrtelnosti,Ring af uovervindelighed,Ring der Unverwundbarkeit,Δαχτυλίδι της Αθανασίας,Ringo de Nevenkebleco,Anillo de Invencibilidad,,Näkymättömyyden sormus,Anneau d'Invincibilité,A Sérthetetlenség Gyűrűje,Anello dell'invincibilità,不死の指輪,불멸의 반지,Ring van Onoverwinnelijkheid,Uovervinnelighetens ring,Pierścień Niewrażliwości,Anel da Invencibilidade,,Inelul Invincibilității,Кольцо неуязвимости,Прстен непобедивости,Ring av oövervinnlighet,Yenilmezlik Yüzüğü,Кільце Непереможності +Tome of Power,TXT_ARTITOMEOFPOWER,,,,Kniha moci,Bog om magt,Buch der Macht,Τομός της Δύναμης,Librego de Forto,Tomo de Poder,,Väkevyyden kirja,Livre du Pouvoir,Az Erő Kódexe,Tomo del potere,力の術書,힘의 서,Boek van de Macht,Maktens bok,Tom Mocy,Livro do Poder,Livro do Poder,Cartea Puterii,Том могущества,Том моћи,Maktens tome,Güç Kitabı,Том сили +Shadowsphere,TXT_ARTIINVISIBILITY,,,,Šerosféra,Skyggesfære,Schattensphäre,Σκιόσφαιρα,Ombrosfero,Esfera de Sombra,,Varjokehrä,Sphère des Ombres,Árnygömb,Sfera dell'ombra,闇の球体,그림자 구체,Schaduwbol,Skyggesfære,Sfera Cieni,Esfera das Sombras,,Sfera Umbrei,Теневая сфера,Сфера сенки,Skuggsfär,Gölge Küre,Сфера тіні +Morph Ovum,TXT_ARTIEGG,,,,Měnivejce,,Transformations-Ei,Μετασχηματίζοντικο Ωάριο,Ovo de Transformado,Huevo de Transformación,,Muodonmuutoksen muna,Ovule de Métamorphose,Alakváltó tojás,Uovo della metamorfosi,変貌の卵子,변신 알,Morfose-Ei,,Jajko Morfujące,Ovo da Metamorfose,,Oul Metamorfozei,Яйцо превращения,Преображавајуће јајашце,,Dönüşümlü Yumurta,Яйце трансформації +Mystic Urn,TXT_ARTISUPERHEALTH,,,,Tajemná urna,Mystisk urne,Mystische Urne,Μυστικό Δοχείο,Mistika Urno,Urna Mística,,Mystinen uurna,Urne Mystique,Misztikus urna,Urna mistica,神秘の骨壷,신비한 항아리,Mystieke Urn,Mystisk urne,Mistyczna Urna,Urna Mística,,Urnă Mistică,Мистическая урна,Мистериозна урна,Mystisk urna,Mistik Urn,Містична урна +Torch,TXT_ARTITORCH,,,,Pochodeň,Fakkel,Fackel,Πυρσός,Torĉo,Antorcha,,Soihtu,Torche,Fáklya,Torcia,松明,횃불,Fakkel,Fakkel,Pochodnia,Tocha,,Torță,Факел,Бакља,Fackel,Meşale,Смолоскип +Time Bomb of the Ancients,TXT_ARTIFIREBOMB,,,,Časovaná bomba starověku,De ældres tidsbombe,Zeitbombe der Alten,Χρονοβόμβα τον Αρχαίων,Tempobombo de la Antikvuloj,Bomba de tiempo de los Ancestros,,Vanhain aikapommi,Bombe a Retardement des Anciens,Az Ősök Időbombája,Bomba a tempo degli antichi,古代の時限爆薬,고대의 시한폭탄,Tijdbom der Tijden,De eldgamles tidsinnstilte bombe,Starożytna Bomba Czasu,Bomba-relógio dos Anciãos,,Bomba cu Ceas a Anticilor,Часовая бомба древних,Временска бомба древних,De gamlas tidsbomb,Kadimlerin Saatli Bombası,Часова бомба древніх Chaos Device,TXT_ARTITELEPORT,,,,Zmatkostroj,Chaos-enhed,Chaosgerät,Συσκευή του Χάος,Ĥaos-Aparato,Dispositivo del Caos,,Kaaoskoje,Outil du Chaos,Káoszszerkezet,"Dispositivo del Caos -",カオスデバイス,혼돈의 장치,Chaosapparaat,Kaosinnretning,Urządzenie Chaosu,Dispositivo do Caos,,Dispozitiv al Haosolui,Механизм хаоса,Уређај хаоса,Kaos Cihazı -Crystal Vial,TXT_ITEMHEALTH,,,,Křišťálový flakón,Krystalflaske,Kristallfläschchen,Κρυσταλλικό Φιάλιδο,Fiolo de Kristalo,Tubo de Cristal,,Kristallipullo,Fiole de Cristal,Kristályampulla,Fiala di cristallo,水晶瓶,수정 약병,Kristallen Flesje,Krystallflaske,Kryształowa Fiolka,Ampola de Cristal,,Fiolă de Cristal,Кристальный флакон,Кристална бочица,Kristal Şişe -Bag of Holding,TXT_ITEMBAGOFHOLDING,,,,Tlumok,Pose med opbevaringspose,Rucksack,Τσάντα Κρατησης,Taŝo de Tenado,Bolso sin Fondo,,Säilön laukku,Sac sans Fond,A Birtoklás Batyuja,Borsa Portaoggetti,持ち物袋,보관용 가방,Rugzak,Posen som holder,Plecak,Bolsa de Utensílios,,Poșetă,Носильный кошель,Торба носивости,Holding Çantası -Silver Shield,TXT_ITEMSHIELD1,,,,Stříbrný štít,Sølvskjold,Silberner Schild,Ασημένια Ασπίδα,Arĝenta Ŝildo,Escudo Plateado,,Hopeakilpi,Bouclier d'Argent,Ezüst Pajzs,Scudo d'argento,銀の盾,은 방패,Zilveren Schild,Sølvskjold,Srebrna Tarcza,Escudo de Prata,,Scut de Argint,Серебряный щит,Сребрни штит,Gümüş Kalkan -Enchanted Shield,TXT_ITEMSHIELD2,,,,Kouzelný štít,Fortryllet skjold,Verzauberter Schild,,Sorĉita Ŝildo,Escudo Encantado,,Lumottu kilpi,Bouclier Enchanté,Bűvös Pajzs,Scudo incantato,魔法の盾,마력 강화 방패,Betoverd schild,Fortryllet skjold,Zaklęta Tarcza,Escudo Encantado,,Scut Mistificat,Зачарованный щит,Зачарани штит,Büyülü Kalkan -Map Scroll,TXT_ITEMSUPERMAP,,,,Mapa,Kortrulle,Kartenrolle,,Map-volvolibro,Mapa en Pergamino,,Karttakäärö,Rouleau du Cartographe,Térkép Tekercs,Pergamena della Mappa,地図の巻物,두루마리 지도,Kaartrol,Kartrulle,Zwój Mapy,Pergaminho do Mapa,,Hartă Pergament,Свиток карты,Мапа,Harita Kaydırma -Wand Crystal,TXT_AMMOGOLDWAND1,,,,Zlaté krystaly,Stav krystal,Zauberstabkristall,,Kristalo de Sorĉbastono,Cristal para Vara,,Sauvakristalli,Cristal Elfique,Kristálypor,Bacchetta di cristallo,ワンドクリスタル,지팡이 결정,Toverstok van Kristal,Tryllestav-krystall,Kryształ do Różdżki,Cristal para o Cetro,,Cristal pentru Toiag,Кристалл для эльфийского жезла,Кристали за штап,Değnek Kristali -Crystal Geode,TXT_AMMOGOLDWAND2,,,,Shluk krystalů,Krystal-geode,Kristallklumpen,,Kristalgeodo,Geoda de Cristal,,Kristalligeoidi,Géode de Cristal,Kristály Geoda,Geode di cristallo,晶洞石,결정 원석,Kristal Geode,Krystallgeode,Kryształowa Geoda,Geodo de Cristal,,Geodă de Cristal,Жеода кристалла,Кристални камен,Kristal Jeot -Mace Spheres,TXT_AMMOMACE1,,,,Žezlometné koule,Kølle kugler,Keulenkugeln,,Klabsferoj,Esferas de Maza,,Nuijakuulia,Sphère de Masse,Jogargömbök,Sfere per la mazza,メイス球弾,철퇴 포탄,Strijdknotsen,Mace-kuler,Kule do Buzdyganu,Esferas para Clava,,Sfere pentru Buzdugan,Сферы для булавы,Сфере за буздован,Ateş Küreleri -Pile of Mace Spheres,TXT_AMMOMACE2,,,,Hromada žezlometných koulí,Bunke af kølle kugler,Haufen von Keulenkugeln,,Stako de Klabsferoj,Pila de Esferas de Maza,,Nuijakuulakasa,Pile de Sphères de Masse,Egy rakás jogargömb,Pila di sfere per la mazza,メイス球弾の固まり,철퇴 포탄 무더기,Stapel Strijdknotsen,Haug med muskettkuler,Sterta Kul do Buzdyganu,Pilha de Esferas para Clava,,Grămadă de Sfere pentru Buzdugan,Груда сфер для булавы,Гомила сфера за буздован,Ateş Küreleri Yığını -Ethereal Arrows,TXT_AMMOCROSSBOW1,,,,Éterické šípy,Æteriske pile,Ätherische Pfeile,,Eteraj Sagoj,Flechas Etéreas,,Eetterinuolia,Carreaux Ethériques,Éteri nyílvesszők,Frecce eteree,イセリアルの矢,유체 화살,Etherische Pijlen,Eteriske piler,Eteryczne Strzały,Flechas Etéreas,,Săgeți Celeste,Эфирные стрелы,Етеричне стреле,Eterik Oklar -Quiver of Ethereal Arrows,TXT_AMMOCROSSBOW2,,,,Toulec éterických šípů,Kogger af æteriske pile,Köcher mit ätherischen Pfeilen,,Sagujo da Eteraj Sagoj,Carcaj de Flechas Etéreas,Carcaza de Flechas Etéreas,Eetterinuoliviini,Carquois de Carreaux Ethériques,Éteri nyíltok,Faretra di frecce eteree,イセリアルの矢筒,유체 화살집,Koker van Etherische Pijlen,Kogger av eteriske piler,Kołczan Eterycznych Strzał,Aljava de Flechas Etéreas,,Tolbă de Săgeți Celeste,Колчан эфирных стрел,Тоболац етеричних стрела,Eterik Okların Sadağı -Claw Orb,TXT_AMMOBLASTER1,,,,Pazouří střela,Klovkugle,Klauenball,,Kriforbo,Orbe de Garra,,Kynsikehrä,Orbe de Griffe,Karomgömb,Sfera d'artiglio,クローオーブ,발톱 보주,Klauwbal,Klo-kule,Kula do Pazura,Orbe para Garra,Esfera para Garra,Glob pentru Gheară,Когтевой шар,Канџаста сфера,Pençe Küresi -Energy Orb,TXT_AMMOBLASTER2,,,,Silová střela,Energikugle,Energieball,,Energiorbo,Orbe de Energía,,Energiakehrä,Orbe Draconique,Energiagömb,Sfera di energia,エネルギーオーブ,기력의 보주,Energiebal,Energikule,Kula Energii,Orbe de Energia,Esfera de Energia,Glob de Energie,Энергетический шар,Енергетска сфера,Enerji Küresi -Lesser Runes,TXT_AMMOSKULLROD1,,,,Menší runy,Mindre runer,Kleine Runen,,Runetoj,Runas Menores,,Vähäriimut,Runes Mineurs,Gyenge rúnák,Rune inferiori,レッサールーン,룬 조각,Lichte Runen,Mindre runer,Gorsze Runy,Runas Inferiores,,Rune Mici,Младшие руны,Нижа руна,Küçük Rünler -Greater Runes,TXT_AMMOSKULLROD2,,,,Větší runy,Større runer,Große Runen,,Runegoj,Runas Mayores,,Isoriimut,Runes Supérieures,Erős rúnák,Rune superiori,グレータールーン,최상급 룬,Zware Runen,Store runer,Lepsze Runy,Runas Superiores,,Rune Mari,Старшие руны,Већа руна,Büyük Rünler -Flame Orb,TXT_AMMOPHOENIXROD1,,,,Plamenný náboj,Flamme kugle,Flammenkugel,,Flamorbo,Orbe de Flama,,Liekkikehrä,Orbe de Flammes,Tűzgömb,Sfera di fuoco,フレイムオーブ,화염 구슬,Vuurbal,Flammekule,Kula Ognia,Orbe de Chamas,Esfera de Chamas,Glob de Foc,Пламенный шар,Ватрена сфера,Alev Küresi -Inferno Orb,TXT_AMMOPHOENIXROD2,,,,Pekelný náboj,Inferno-kugle,Infernokugel,,Brulorbo,Orbe de Averno,,Infernokehrä,Orbe Infernal,Pokolgömb,Sfera infernale,インフェルノオーブ,지옥불 구슬,Infernobal,Inferno-kule,Kula Piekielna,Orbe Infernal,Esfera Infernal,Glob Infernal,Инфернальный шар,Пламена сфера,Cehennem Küresi -Gold Wand,TXT_WPNGOLDWAND,,,,Zlatá hůl,Guldstav,Goldener Zauberstab,,Ora Sorĉbastono,Vara Dorada,,Kultasauva,Baguette Elfique,Aranypálca,Bacchetta d'oro,ゴールドワンド,황금 지팡이,Gouden Toverstok,Gullstav,Złota Różdżka,Varinha de Ouro,,Toiag cu Aur,Эльфийский жезл,Златни магични штап,Altın Değnek +",カオスデバイス,혼돈의 장치,Chaosapparaat,Kaosinnretning,Urządzenie Chaosu,Dispositivo do Caos,,Dispozitiv al Haosolui,Механизм хаоса,Уређај хаоса,Chaos-enhet,Kaos Cihazı,Пристрій Хаосу +Crystal Vial,TXT_ITEMHEALTH,,,,Křišťálový flakón,Krystalflaske,Kristallfläschchen,Κρυσταλλικό Φιάλιδο,Fiolo de Kristalo,Tubo de Cristal,,Kristallipullo,Fiole de Cristal,Kristályampulla,Fiala di cristallo,水晶瓶,수정 약병,Kristallen Flesje,Krystallflaske,Kryształowa Fiolka,Ampola de Cristal,,Fiolă de Cristal,Кристальный флакон,Кристална бочица,Kristallflaska,Kristal Şişe,Кришталевий флакон +Bag of Holding,TXT_ITEMBAGOFHOLDING,,,,Tlumok,Pose med opbevaringspose,Rucksack,Τσάντα Κρατησης,Taŝo de Tenado,Bolso sin Fondo,,Säilön laukku,Sac sans Fond,A Birtoklás Batyuja,Borsa Portaoggetti,持ち物袋,보관용 가방,Rugzak,Posen som holder,Plecak,Bolsa de Utensílios,,Poșetă,Носильный кошель,Торба носивости,Väska med behållare,Holding Çantası,Запасний підсумок +Silver Shield,TXT_ITEMSHIELD1,,,,Stříbrný štít,Sølvskjold,Silberner Schild,Ασημένια Ασπίδα,Arĝenta Ŝildo,Escudo Plateado,,Hopeakilpi,Bouclier d'Argent,Ezüst Pajzs,Scudo d'argento,銀の盾,은 방패,Zilveren Schild,Sølvskjold,Srebrna Tarcza,Escudo de Prata,,Scut de Argint,Серебряный щит,Сребрни штит,Silversköld,Gümüş Kalkan,Срібний щит +Enchanted Shield,TXT_ITEMSHIELD2,,,,Kouzelný štít,Fortryllet skjold,Verzauberter Schild,,Sorĉita Ŝildo,Escudo Encantado,,Lumottu kilpi,Bouclier Enchanté,Bűvös Pajzs,Scudo incantato,魔法の盾,마력 강화 방패,Betoverd schild,Fortryllet skjold,Zaklęta Tarcza,Escudo Encantado,,Scut Mistificat,Зачарованный щит,Зачарани штит,Förtrollad sköld,Büyülü Kalkan,Зачарований щит +Map Scroll,TXT_ITEMSUPERMAP,,,,Mapa,Kortrulle,Kartenrolle,,Map-volvolibro,Mapa en Pergamino,,Karttakäärö,Rouleau du Cartographe,Térkép Tekercs,Pergamena della Mappa,地図の巻物,두루마리 지도,Kaartrol,Kartrulle,Zwój Mapy,Pergaminho do Mapa,,Hartă Pergament,Свиток карты,Мапа,Kartrulle,Harita Kaydırma,Сувій-карта +Wand Crystal,TXT_AMMOGOLDWAND1,,,,Zlaté krystaly,Stav krystal,Zauberstabkristall,,Kristalo de Sorĉbastono,Cristal para Vara,,Sauvakristalli,Cristal Elfique,Kristálypor,Bacchetta di cristallo,ワンドクリスタル,지팡이 결정,Toverstok van Kristal,Tryllestav-krystall,Kryształ do Różdżki,Cristal para o Cetro,,Cristal pentru Toiag,Кристалл эльфийского жезла,Кристали за штап,Stavkristall,Değnek Kristali,Кристал для жезлу +Crystal Geode,TXT_AMMOGOLDWAND2,,,,Shluk krystalů,Krystal-geode,Kristallklumpen,,Kristalgeodo,Geoda de Cristal,,Kristalligeoidi,Géode de Cristal,Kristály Geoda,Geode di cristallo,晶洞石,결정 원석,Kristal Geode,Krystallgeode,Kryształowa Geoda,Geodo de Cristal,,Geodă de Cristal,Жеода кристалла,Кристални камен,Kristallgeod,Kristal Jeot,Кристалічна жеода +Mace Spheres,TXT_AMMOMACE1,,,,Žezlometné koule,Kølle kugler,Keulenkugeln,,Klabsferoj,Esferas de Maza,,Nuijakuulia,Sphère de Masse,Jogargömbök,Sfere per la mazza,メイス球弾,철퇴 포탄,Strijdknotsen,Mace-kuler,Kule do Buzdyganu,Esferas para Clava,,Sfere pentru Buzdugan,Сферы булавы,Сфере за буздован,Eldstötsfärer,Ateş Küreleri,Сфери для булави +Pile of Mace Spheres,TXT_AMMOMACE2,,,,Hromada žezlometných koulí,Bunke af kølle kugler,Haufen von Keulenkugeln,,Stako de Klabsferoj,Pila de Esferas de Maza,,Nuijakuulakasa,Pile de Sphères de Masse,Egy rakás jogargömb,Pila di sfere per la mazza,メイス球弾の固まり,철퇴 포탄 무더기,Stapel Strijdknotsen,Haug med muskettkuler,Sterta Kul do Buzdyganu,Pilha de Esferas para Clava,,Grămadă de Sfere pentru Buzdugan,Груда сфер булавы,Гомила сфера за буздован,Hög med Eldstötsfärer,Ateş Küreleri Yığını,Купа булавних сфер +Ethereal Arrows,TXT_AMMOCROSSBOW1,,,,Éterické šípy,Æteriske pile,Ätherische Pfeile,,Eteraj Sagoj,Flechas Etéreas,,Eetterinuolia,Carreaux Ethériques,Éteri nyílvesszők,Frecce eteree,イセリアルの矢,유체 화살,Etherische Pijlen,Eteriske piler,Eteryczne Strzały,Flechas Etéreas,,Săgeți Celeste,Эфирные стрелы,Етеричне стреле,Eteriska pilar,Eterik Oklar,Ефірні стріли +Quiver of Ethereal Arrows,TXT_AMMOCROSSBOW2,,,,Toulec éterických šípů,Kogger af æteriske pile,Köcher mit ätherischen Pfeilen,,Sagujo da Eteraj Sagoj,Carcaj de Flechas Etéreas,Carcaza de Flechas Etéreas,Eetterinuoliviini,Carquois de Carreaux Ethériques,Éteri nyíltok,Faretra di frecce eteree,イセリアルの矢筒,유체 화살집,Koker van Etherische Pijlen,Kogger av eteriske piler,Kołczan Eterycznych Strzał,Aljava de Flechas Etéreas,,Tolbă de Săgeți Celeste,Колчан эфирных стрел,Тоболац етеричних стрела,Kvant av eteriska pilar,Eterik Okların Sadağı,Сагайдак ефірних стріл +Claw Orb,TXT_AMMOBLASTER1,,,,Pazouří střela,Klovkugle,Klauenball,,Kriforbo,Orbe de Garra,,Kynsikehrä,Orbe de Griffe,Karomgömb,Sfera d'artiglio,クローオーブ,발톱 보주,Klauwbal,Klo-kule,Kula do Pazura,Orbe para Garra,Esfera para Garra,Glob pentru Gheară,Когтевой шар,Канџаста сфера,Klorör klot,Pençe Küresi,Кігтьова сфера +Energy Orb,TXT_AMMOBLASTER2,,,,Silová střela,Energikugle,Energieball,,Energiorbo,Orbe de Energía,,Energiakehrä,Orbe Draconique,Energiagömb,Sfera di energia,エネルギーオーブ,기력의 보주,Energiebal,Energikule,Kula Energii,Orbe de Energia,Esfera de Energia,Glob de Energie,Энергетический шар,Енергетска сфера,Energikulor,Enerji Küresi,Енергетична сфера +Lesser Runes,TXT_AMMOSKULLROD1,,,,Menší runy,Mindre runer,Kleine Runen,,Runetoj,Runas Menores,,Vähäriimut,Runes Mineurs,Gyenge rúnák,Rune inferiori,レッサールーン,룬 조각,Lichte Runen,Mindre runer,Gorsze Runy,Runas Inferiores,,Rune Mici,Младшие руны,Нижа руна,Mindre runor,Küçük Rünler,Молодші руни +Greater Runes,TXT_AMMOSKULLROD2,,,,Větší runy,Større runer,Große Runen,,Runegoj,Runas Mayores,,Isoriimut,Runes Supérieures,Erős rúnák,Rune superiori,グレータールーン,최상급 룬,Zware Runen,Store runer,Lepsze Runy,Runas Superiores,,Rune Mari,Старшие руны,Већа руна,Större runor,Büyük Rünler,Старші руни +Flame Orb,TXT_AMMOPHOENIXROD1,,,,Plamenný náboj,Flamme kugle,Flammenkugel,,Flamorbo,Orbe de Flama,,Liekkikehrä,Orbe de Flammes,Tűzgömb,Sfera di fuoco,フレイムオーブ,화염 구슬,Vuurbal,Flammekule,Kula Ognia,Orbe de Chamas,Esfera de Chamas,Glob de Foc,Пламенный шар,Ватрена сфера,Flamkula,Alev Küresi,Вогняна сфера +Inferno Orb,TXT_AMMOPHOENIXROD2,,,,Pekelný náboj,Inferno-kugle,Infernokugel,,Brulorbo,Orbe de Averno,,Infernokehrä,Orbe Infernal,Pokolgömb,Sfera infernale,インフェルノオーブ,지옥불 구슬,Infernobal,Inferno-kule,Kula Piekielna,Orbe Infernal,Esfera Infernal,Glob Infernal,Инфернальный шар,Пламена сфера,Infernokula,Cehennem Küresi,Пекельна сфера +Gold Wand,TXT_WPNGOLDWAND,,,,Zlatá hůl,Guldstav,Goldener Zauberstab,,Ora Sorĉbastono,Vara Dorada,,Kultasauva,Baguette Elfique,Aranypálca,Bacchetta d'oro,ゴールドワンド,황금 지팡이,Gouden Toverstok,Gullstav,Złota Różdżka,Varinha de Ouro,,Toiag cu Aur,Эльфийский жезл,Златни магични штап,Guldstav,Altın Değnek,Посох Ельфів Firemace,TXT_WPNMACE,,,,Žezlomet,Ildspyd,Feuerkeule,,Fajroklabo,Maza de Fuego,,Tulinuija,Masse de Feu,Tűzbuzogány,"Mazza di fuoco -",ファイアメイス,투사철퇴,Vuurfoelie,Ildsted,Buzdygan Ognia,Clava de Fogo,,Buzdugan de Foc,Огненная булава,Ватрени буздован,Ateş Çubuğu -Ethereal Crossbow,TXT_WPNCROSSBOW,,,,Éterická kuše,Æterisk armbrøst,Ätherische Armbrust,,Etera Arbalesto,Ballesta Etérea,,Eetterivarsijousi,Arbalète Ethérique,Éteri számszeríj,Balestra eterea,イセリアルクロスボウ,유체 쇠뇌,Etherische kruisboog,Eterisk armbrøst,Eteryczna Kusza,Besta Etérea,,Arbaletă Celestă,Эфирный арбалет,Етерични самострел,Eterik Arbalet -Dragon Claw,TXT_WPNBLASTER,,,,Drakospár,Drageklo,Drachenklaue,,Drakokrifo,Garra de Dragón,,Lohikäärmeenkynsi,Griffe Draconique,Sárkány karom,Artiglio del drago,ドラゴンクロー,용발톱,Drakenklauw,Drageklo,Smoczy Pazur,Garra de Dragão,,Gheara Dragonului,Коготь дракона,Змајева канџа,Ejder Pençesi -Hellstaff,TXT_WPNSKULLROD,,,,Peklopal,Helvedestav,Höllenrute,,Inferbastono,Bastón Infernal,,Hornansauva,Bâton Infernal,Pokolpálca,Staffa infernale,ヘルスタッフ,지옥지팡이,Hellestaf,Helvetesstav,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох Ада,Паклени штап,Cehennem Çubuğu -Phoenix Rod,TXT_WPNPHOENIXROD,,,,Fénixova hůl,Phønix-stang,Phönixstab,,Feniksvergo,Báculo del Fénix,,Feenikssauva,Bâton du Phénix,Főnix Rúd,Asta della fenice,フェニックスロッド,불사조 지팡이,Feniksstaf,Føniksstaven,Różdżka Feniksa,Bastão da Fênix,,Joarda Phoenix,Жезл феникса,Шипка феникса,Anka Kuşu Çubuğu -Gauntlets of the Necromancer,TXT_WPNGAUNTLETS,,,,Nekromancerovy rukavice,Nekromantikernes handsker,Handschuhe des Zauberers,,Fergantoj de la Nekromancisto,Guanteletes del Nigromante,,Manaajan rautakintaat,Gantelets du Nécromancien,Halottidéző Páncélkesztyűi,Guanti del Negromante,ネクロマンサーの篭手,강령술사의 건틀릿,Handschoenen van de Geestenbezweerder,Nekromantens hansker,Rękawice Nekromanty,Manoplas do Necromante,,Mănușile Necromantului,Перчатки некроманта,Рукавице призивача духова,Ölü Çağıranın Eldivenleri -,,Locks,,,,,,,,,,,,,,,,,,,,,,,, +",ファイアメイス,투사철퇴,Vuurfoelie,Ildsted,Buzdygan Ognia,Clava de Fogo,,Buzdugan de Foc,Огненная булава,Ватрени буздован,Eldstöt,Ateş Çubuğu,Вогняна булава +Ethereal Crossbow,TXT_WPNCROSSBOW,,,,Éterická kuše,Æterisk armbrøst,Ätherische Armbrust,,Etera Arbalesto,Ballesta Etérea,,Eetterivarsijousi,Arbalète Ethérique,Éteri számszeríj,Balestra eterea,イセリアルクロスボウ,유체 쇠뇌,Etherische kruisboog,Eterisk armbrøst,Eteryczna Kusza,Besta Etérea,,Arbaletă Celestă,Эфирный арбалет,Етерични самострел,Eteriskt armborst,Eterik Arbalet,Ефірний арбалет +Dragon Claw,TXT_WPNBLASTER,,,,Drakospár,Drageklo,Drachenklaue,,Drakokrifo,Garra de Dragón,,Lohikäärmeenkynsi,Griffe Draconique,Sárkány karom,Artiglio del drago,ドラゴンクロー,용발톱,Drakenklauw,Drageklo,Smoczy Pazur,Garra de Dragão,,Gheara Dragonului,Коготь дракона,Змајева канџа,Drakklocka,Ejder Pençesi,Кіготь Дракона +Hellstaff,TXT_WPNSKULLROD,,,,Peklopal,Helvedestav,Höllenrute,,Inferbastono,Bastón Infernal,,Hornansauva,Bâton Infernal,Pokolpálca,Staffa infernale,ヘルスタッフ,지옥지팡이,Hellestaf,Helvetesstav,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох Ада,Паклени штап,Helvetesstång,Cehennem Çubuğu,Пекельний посох +Phoenix Rod,TXT_WPNPHOENIXROD,,,,Fénixova hůl,Phønix-stang,Phönixstab,,Feniksvergo,Báculo del Fénix,,Feenikssauva,Bâton du Phénix,Főnix Rúd,Asta della fenice,フェニックスロッド,불사조 지팡이,Feniksstaf,Føniksstaven,Różdżka Feniksa,Bastão da Fênix,,Joarda Phoenix,Жезл феникса,Шипка феникса,Fenixstång,Anka Kuşu Çubuğu,Жезл Фенікса +Gauntlets of the Necromancer,TXT_WPNGAUNTLETS,,,,Nekromancerovy rukavice,Nekromantikernes handsker,Handschuhe des Zauberers,,Fergantoj de la Nekromancisto,Guanteletes del Nigromante,,Manaajan rautakintaat,Gantelets du Nécromancien,Halottidéző Páncélkesztyűi,Guanti del Negromante,ネクロマンサーの篭手,강령술사의 건틀릿,Handschoenen van de Geestenbezweerder,Nekromantens hansker,Rękawice Nekromanty,Manoplas do Necromante,,Mănușile Necromantului,Перчатки некроманта,Рукавице призивача духова,Nekromantikerns handskar,Ölü Çağıranın Eldivenleri,Рукавиці Некроманта +,,Locks,,,,,,,,,,,,,,,,,,,,,,,,,, You need a blue key to open this door,TXT_NEEDBLUEKEY,,,,K otevření těchto dveří potřebuješ modrý klíč,Du skal bruge en blå nøgle for at åbne denne dør,Du brauchst einen blauen Schlüssel um diese Tür zu öffnen,Χρειάζεσε ένα μπλέ κλειδί για να ενεργοποίησεις αυτη τη πόρτα,Vi bezonas bluan ŝlosilon por malfermi ĉi tiun pordon,Necesitas una llave azul para abrir esta puerta,,Tarvitset sinisen avaimen avataksesi tämän oven,Cette porte nécessite une clé bleue pour s'ouvrir.,Az ajtó nyitásához szükséged van egy kék kulcsra,"Ti serve una chiave blu per aprire questa porta ",開くには 青の鍵が必要だ,이 문을 열기 위해선 청색 열쇠가 필요하다,Je hebt een blauwe sleutel nodig om deze deur te openen,Du trenger en blå nøkkel for å åpne denne døren,"Potrzebujesz niebieskiego klucza, by otworzyć te drzwi.",Você precisa da chave azul para abrir esta porta,Precisas da chave azul para abrir esta porta,"Ai nevoie de o cheie albastră pentru a deschide -această ușă",Для открытия нужен синий ключ,Треба вам плави кључ да би отворили ова врата,Bu kapıyı açmak için mavi bir anahtara ihtiyacın var. +această ușă",Для открытия нужен синий ключ,Треба вам плави кључ да би отворили ова врата,Du behöver en blå nyckel för att öppna den här dörren.,Bu kapıyı açmak için mavi bir anahtara ihtiyacın var.,"Вам потрібен синій ключ, щоб відкрити ці двері" You need a green key to open this door,TXT_NEEDGREENKEY,,,,K otevření těchto dveří potřebuješ červený klíč,Du skal bruge en grøn nøgle for at åbne denne dør,Du brauchst einen grünen Schlüssel um diese Tür zu öffnen,Χρειάζεσε ένα πράσινο κλειδί για να ενεργοποίησεις αυτη τη πόρτα,Vi bezonas verdan ŝlosilon por malfermi ĉi tiun pordon,Necesitas una llave verde para abrir esta puerta,,Tarvitset vihreän avaimen avataksesi tämän oven,Cette porte nécessite une clé verte pour s'ouvrir.,Az ajtó nyitásához szükséged van egy zöld kulcsra,"Ti serve una chiave verde per aprire questa porta ",開くには 緑の鍵が必要だ,이 문을 열기 위해선 녹색 열쇠가 필요하다,Je hebt een groene sleutel nodig om deze deur te openen,Du trenger en grønn nøkkel for å åpne denne døren,"Potrzebujesz zielonego klucza, by otworzyć te drzwi.",Você precisa da chave verde para abrir esta porta,Precisas da chave verde para abrir esta porta,"Ai nevoie de o cheie verde pentru a deschide -această ușă",Для открытия нужен зелёный ключ,Треба вам зелени кључ да би отворили ова врата,Bu kapıyı açmak için yeşil bir anahtara ihtiyacın var. +această ușă",Для открытия нужен зелёный ключ,Треба вам зелени кључ да би отворили ова врата,Du behöver en grön nyckel för att öppna den här dörren,Bu kapıyı açmak için yeşil bir anahtara ihtiyacın var.,"Вам потрібен зелений ключ, щоб відкрити ці двері" You need a yellow key to open this door,TXT_NEEDYELLOWKEY,,,,K otevření těchto dveří potřebuješ žlutý klíč.,Du skal bruge en gul nøgle for at åbne denne dør,Du brauchst einen gleben Schlüssel um diese Tür zu öffnen,Χρειάζεσε ένα κύτρινο κλειδί για να ενεργοποίησεις αυτη τη πόρτα,Vi bezonas flavan ŝlosilon por malfermi ĉi tiun pordon,Necesitas una llave amarilla para abrir esta puerta,,Tarvitset keltaisen avaimen avataksesi tämän oven,Cette porte nécessite une clé jaune pour s'ouvrir.,Az ajtó nyitásához szükséged van egy sárga kulcsra,Ti serve una chiave gialla per aprire questa porta,開くには 黄の鍵が必要だ,이 문을 열기 위해선 황색 열쇠가 필요하다,Je hebt een gele sleutel nodig om deze deur te openen,Du trenger en gul nøkkel for å åpne denne døren,"Potrzebujesz żółtego klucza, by otworzyć te drzwi.",Você precisa da chave amarela para abrir esta porta,Precisas da chave amarela para abrir esta porta,"Ai nevoie de o cheie galbenă pentru a deschide -această ușă",Для открытия нужен жёлтый ключ,Треба вам жути кључ да би отворили ова врата,Bu kapıyı açmak için sarı bir anahtara ihtiyacınız var -,,Actor tag names,,,,,,,,,,,,,,,,,,,,,,,, -Chicken,FN_CHICKEN,,,,Slepice,Kylling,Huhn,Κότα,Koko,Pollo,,Kana,Poulet,Csirke,Pollo,鶏,닭,Kip,Kylling,Kurczak,Galinha,,Găină,Цыплёнок,Кокошка,Tavuk -Weredragon,FN_BEAST,,,,Vlkodrak,Varedrage,Werdrache,Θηρίο,Lupdrako,Bestia dragón,,Ihmislohikäärme,Dragon-garou,Vérsárkány,Drago Mannaro,ウェア ドラゴン,웨어드래곤,Weerdraak,Vardrage,Smokołak,Homem-dragão,,Vârcodragon,Дракон-оборотень,Змајодлак,Kurt ejderha -Sabreclaw,FN_CLINK,,,,Šavlozub,Sabelklo,Säbelklaue,,Sabrokrifo,Garra de sable,,Sapelikynsi,Sabregriffe,Szablyakarom,Lamartiglio,サーベルクロー,세이버클로,Sabelklauw,Sabreklo,Szabloszpon,Unhas-de-sabre,,Gheară de Sabie,Саблекоготь,Тигар,Kılıçpençe -D'Sparil,FN_DSPARIL,,,,,,,,,,,,D'Sparil,,D'Sparil,デ'スパリル,드'스파릴,D'Sparil,,D'Sparil,,,D'Sparil,Д'Спарил,Д'Спарил,D'Sparil -Gargoyle,FN_HERETICIMP,,,,Chrlič,,,,Gargojlo,Gárgola,,Gargoili,Gargouille,Vízköpő,Gargoyle,ガーゴイル,가고일,,,Gargulec,Gárgula,,Garguie,Горгулья,Камена утвара,Gargoyle -Ironlich,FN_IRONLICH,,,,Železný kostěj,Jern lig,Eiserne Leiche,,Ferliĉo,Liche de hierro,,Rautakalmo,Liche de Fer,Ezüst lich,Lich di Ferro,アイアンリッチ,아이언 리치,IJzeren Lijk,Jernlich,Żelazny Lisz,Lich de Ferro,,Cadavru de Fier,Железный лич,Челични лич,Demir Ceset -Undead Warrior,FN_BONEKNIGHT,,,,Nemrtvý válečník,Udøde Kriger,Untoter Krieger,Αθάνατος Πολεμιστής,Malviva Batalisto,Guerrero no-muerto,,Epäkuollut soturi,Guerrier Mort-Vivant,Élőhalott harcos,Guerriero Non Morto,アンデット兵,언데드 전사,Ondode Krijger,Udød kriger,Nieumarły wojownik,Guerreiro Morto-vivo,,Războinic Nemort,Воин-нежить,Немртви ратник,Ölümsüz Savaşçı -Maulotaur,FN_MINOTAUR,,,,Minotaurus,Maulotaurus,Minotaurus,Μινόταυρος,Bategtaŭro,Mazotauro,,Maulotauri,Massetaure,,Maulotauro,マウロタウロス,몰로타우어,Maulotaurus,Maulotaur,Młototaur,Marretauro,,,Избитавр,Минотаур,Maulotor -Golem,FN_MUMMY,,,,Golém,,,,Golemo,,,,Golem,Gólem,Golem,ゴーレム,골렘,,,Golem,,,,Голем,Голем,Golem -Nitrogolem,FN_MUMMYLEADER,,,,Střelgolém,,,,Azotgolemo,,,,Nitrogolem,Nitrógólem,Nitrogolem,ニトロゴーレム,니트로 골렘,,,Nitrogolem,,,,Нитроголем,Нитро голем,Nitrogolem -Ophidian,FN_SNAKE,,,,Šupinatec,,,,Ofidio,Ofidio,,Käärmeolio,Ophidien,Ofidián,Ophidian,オフィディアン,오피디안,Ophidiaan,,Wężowaty,Ofídio,,Ofidian,Офидиан,Змија,Ophidian -Wizard,FN_WIZARD,,,,Čaroděj,Troldmand,Zauberer,Μάγος,Sorĉisto,Mago,,Velho,Magicien,Mágus,Mago,ウィザード,마법사,Tovenaar,Trollmann,Czarownik,Mago,,Vrăjitor,Колдун,Чаробњак,Sihirbaz -Wand Crystals,AMMO_GOLDWAND,,,,Zlaté krystaly,Stav krystaller,Elfenstabkristalle,,Sorĉbastono-Kristaloj,Cristales para vara,,Sauvakristalleja,Cristaux,Pálca kristályok,Cristalli per la bacchetta,ワンド クリスタル,지팡이 결정,Toverstafkristallen,Tryllestavkrystaller,Kryształy do Różdżki,Cristais para o Cetro,,Cristale pentru Toiag,Кристалл для эльфийского жезла,Кристали за штап,Değnek Kristalleri -Ethereal Arrows,AMMO_CROSSBOW,,,,Éterické šípy,Æteriske pile,Ätherische Pfeile,,Eteraj Sagoj,Flechas etéreas,,Eetterinuolia,Carreaux,Éteri nyilak,Frecce eteree,イセリアルの矢,유체 화살,Etherische Pijlen,Eteriske piler,Eteryczne Strzały,Flechas Etéreas,,Săgeți Celeste,Эфирные стрелы,Етеричне стреле,Eterik Oklar -Claw Orbs,AMMO_BLASTER,,,,Pazouří střely,Kugler med kløer,Klauenbälle,,Kriforboj,Orbes de garra,,Kynsikehriä,Orbes,Karom golyók,Sfere di artigli,クロー オーブ,발톱 보주,Klauwbollen,Klo-kuler,Kule do Pazura,Orbes para Garra,,Globuri pentru Gheară,Когтевые шары,Канџаста сфера,Pençe Küreleri -Mace Spheres,AMMO_MACE,,,,Žezlometné koule,Kugler til stridskølle,Energiebälle,,Klabsferoj,Esferas de maza,,Nuijakuulia,Sphères,Buzogány gömbök,Sfere per la mazza,メイス スフィア,철퇴 포탄,Strijdknotsen,Ildsted-kuler,Kule do Buzdyganu,Esferas para Clava,,Sfere pentru Buzdugan,Сферы для булавы,Сфере за буздован,Ateş Küreleri -Hellstaff Runes,AMMO_SKULLROD,,,,Peklopalné runy,Helvedestav-runer,Höllenrutenrunen,,Inferbastono-Runoj,Runas de Vara Infernal,,Hornansauvan riimuja,Runes,Pokolbot rúnák,Rune infernali,ヘルスタッフ ルーン,룬 조각,Hellestafrunen,Helvetesstav-runer,Runy do Piekielnego Kostura,Runas Infernais,,Rune pentru Bastonul Infernal,Руны посоха ада,Пуне за паклени штап,Cehennem Asası Rünleri -Flame Orbs,AMMO_PHOENIXROD,,,,Plamenné náboje,Flammekugler,Flammenkugeln,,Flamorboj,Orbes de llama,Orbes de flama,Liekkikehriä,Orbes de Feu,Tűzgolyók,Sfere di fuoco,フレイム オーブ,화염 구슬,Vuurballen,Flammekuler,Kule Ognia,Orbes de Chamas,,Globuri de Foc,Пламенные шары,Ватрена сфера,Alev Küreleri -Staff,TAG_STAFF,,,,Hole,Stav,Stab,Ράβδος,Bastono,Bastón,,Sauva,Bâton,Bot,Staffa,杖,지팡이,Staf,Stav,Kostur,Bastão,,Baston,Посох,Штап,Çubuk -Gauntlets of the Necromancer,TAG_GAUNTLETS,,,,Nekromancerovy rukavice,Nekromantikernes handsker,Handschuhe des Zauberers,,Fergantoj de la Nekromancisto,Guanteletes del Nigromante,,Manaajan rautakintaat,Gantelets du Nécromancien,Halottidéző páncélkesztyűi,Guanti del Negromante,ネクロマンサーの篭手,강령술사의 건틀릿,Handschoenen van de Geestenbezweerder,Nekromantens hansker,Rękawice Nekromanty,Manoplas do Necromante,,Mănușile Necromantului,Перчатки некроманта,Рукавице призивача духова,Ölü Çağıranın Eldivenleri -Elven Wand,TAG_GOLDWAND,,,,Elfí hůlka,Elverstav,Elfenstab,,Elfa Sorĉbastono,Vara de Elfo,,Haltiasauva,Baguette Elfique,Elf pálca,Scettro Elfico,エルフのワンド,엘프 지팡이,Elvenstokje,Alvestav,Elfia Różdżka,Cetro Élfico,,Toiag,Эльфийский жезл,Вилењачки штапић,Elf Asası -Ethereal Crossbow,TAG_CROSSBOW,,,,Éterická kuše,Æterisk armbrøst,Ätherische Armbrust,,Etera Arbalesto,Ballesta Etérea,,Eetterivarsijousi,Arbalète Etherique,Éteri nyílpuska,Balestra Eterea ,イセリアルクロスボウ,유체 쇠뇌,Etherische Kruisboog,Eterisk armbrøst,Eteryczna Kusza,Besta Etérea,,Arbaletă Celestă,Эфирный арбалет,Етерични самострел,Eterik Arbalet -Dragon Claw,TAG_BLASTER,,,,Drakospár,Drageklo,Drachenklaue,,Drakokrifo,Garra de Dragón,,Lohikäärmeenkynsi,Griffe Draconique,Sárkány karom,Artiglio del Drago ,ドラゴンの鉤爪,용발톱,Drakenklauw,Drageklo,Smoczy Pazur,Garra de Dragão,,Gheara Dragonului,Драконий коготь,Змајева канџа,Ejder Pençesi -Hellstaff,TAG_SKULLROD,,,,Peklopal,Helvedestav,Höllenrute,,Inferbastono,Bastón infernal,,Hornansauva,Bâton Infernal,Pokolbot,Staffa Infernale ,ヘルスタッフ,지옥지팡이,Hellestaf,Helvetesstav,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох ада,Паклени штап,Cehennem Çubuğu -Phoenix Rod,TAG_PHOENIXROD,,,,Fénixova hůl,Phønix-stang,Phönixstab,,Feniksvergo,Báculo del Fénix,,Feenikssauva,Bâton du Phénix,Főnix rúd,Bastone della Fenice,フェニックスロッド,불사조 지팡이,Feniksstaf,Føniksstaven,Różdżka Feniksa,Bastão da Fênix,,Joardă Phoenix,Жезл феникса,Шипка феникса,Anka Kuşu Çubuğu -Firemace,TAG_MACE,,,,Žezlomet,Ildspyd,Feuerkeule,,Fajroklabo,Maza de Fuego,,Tulinuija,Masse de Feu,Tűzbuzogány,Mazza del Fuoco ,ファイアメイス,투사철퇴,Vuurknots,Ildsted,Buzdygan Ognia,Clava de Fogo,,Buzdugan de Foc,Огненная булава,Ватрени буздован,Ateş Çubuğu -Staff,TAG_STAFFP,,,,Hůl,Stav,Stab,Ράβδος,Bastono,Bastón,,Sauva,Bâton,Jogar,Staffa ,杖,마법부가 지팡이,Staf,Stav,Kostur,Bastão,,Baston,Посох,Штап,Çubuk -Gauntlets of the Necromancer,TAG_GAUNTLETSP,,,,Nekromancerovy rukavice,Nekromantikernes handsker,Handschuhe des Zauberers,,Fergantoj de la Nekromancisto,Guanteletes del Nigromante,,Manaajan rautakintaat,Gantelets du Nécromancien,Halottidéző páncélkesztyű,Guanti del Negromante,ネクロマンサーの篭手,마법부가 강령술사 건틀릿,Handschoenen van de Geestenbezweerder,Nekromantens hansker,Rękawice Nekromanty,Manoplas do Necromante,,Mănușile Necromantului,Перчатки некроманта,Рукавице некроманцера,Ölü Çağıranın Eldivenleri -Elven Wand,TAG_GOLDWANDP,,,,Elfí hůlka,Elverstav,Elfenstab,,Elfa Sorĉbastono,Vara de Elfo,,Haltiasauva,Baguette Elfique,Elf jogar,Scettro Elfico,エルフのワンド,마법부가 엘프 지팡이,Elvenstokje,Alvestav,Elfia Różdżka,Cetro Élfico,,Toiag,Эльфийский жезл,Вилењачки штапић,Elf Asası -Ethereal Crossbow,TAG_CROSSBOWP,,,,Éterická kuše,Æterisk armbrøst,Ätherische Armbust,,Etera Arbalesto,Ballesta Etérea,,Eetterivarsijousi,Arbalète Etherique,Éteri nyílpuska,Balestra Eterea ,イセリアルクロスボウ,마법부가 유체 쇠뇌,Etherische Kruisboog,Eterisk armbrøst,Eteryczna Kusza,Besta Etérea,,Arbaletă Celestă,Эфирный арбалет,Етерични самострел,Ethereal Arbalet -Dragon Claw,TAG_BLASTERP,,,,Drakospár,Drageklo,Drachenklaue,,Drakokrifo,Garra de Dragón,,Lohikäärmeenkynsi,Griffe Draconique,Sárkány karom,Artiglio del Drago ,ドラゴンの鉤爪,마법부가 용발톱,Drakenklauw,Drageklo,Smoczy Pazur,Garra de Dragão,,Gheara Dragonului,Коготь дракона,Змајева канџа,Ejder Pençesi -Hellstaff,TAG_SKULLRODP,,,,Peklopal,Helvedestav,Höllenrute,,Inferbastono,Bastón infernal,,Hornansauva,Bâton Infernal,Pokolbot,Staffa Infernale ,ヘルスタッフ,마법부가 지옥지팡이,Hellestaf,Helvetesstav,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох ада,Мотка пакла,Cehennem Çubuğu -Phoenix Rod,TAG_PHOENIXRODP,,,,Fénixova hůl,Phønix-stav,Phönixstab,,Feniksvergo,Báculo del Fénix,,Feenikssauva,Bâton du Phénix,Főnix rúd,Bastone della Fenice,フェニックスロッド,마법부가 불사조 지팡이,Feniksstaf,Føniksstaven,Różdżka Feniksa,Bastão da Fênix,,Joardă Phoenix,Жезл феникса,Фениксов прут,Anka Kuşu Çubuğu -Firemace,TAG_MACEP,,,,Žezlomet,Ildspyd,Feuerkeule,,Fajrklabo,Maza de Fuego,,Tulinuija,Masse de Feu,Tűzbuzogány,Mazza del Fuoco ,ファイアメイス,마법부가 투사철퇴,Vuurknots,Ildsted,Buzdygan Ognia,Clava de Fogo,,Buzdugan de Foc,Огненная булава,Ватрени буздован,Ateş Çubuğu -Morph Ovum,TAG_ARTIEGG,,,,Měnivejce,Morph Ovum,Transformations-Ei,,Ovo de Transformado,Huevo de Transformación,,Muodonmuutoksen muna,Ovule de Métamorphose,Átváltoztató gömb,Morph Ovum,変貌の卵子,변신 알,Morfose-Ei,Morph Ovum,Jajko Morfujące,Ovo da Metamorfose,,Oul Metamorfozei,Яйцо превращения,Преображајyће јајашце,Dönüşümlü Yumurta -Time Bomb of the Ancients,TAG_ARTIFIREBOMB,,,,Časovaná bomba starověku,De ældgamles tidsbombe,Zeitbombe der Alten,,Tempobombo de la Antikvuloj,Bomba de tiempo de los Ancestros,,Vanhain aikapommi,Bombe a retardement des Anciens,Ősiek időbombája,Bomba a Tempo degli Antichi,古代の時限爆薬,고대의 시한폭탄,Tijdbom der Tijden,De eldgamles tidsinnstilte bombe,Starożytna Bomba Czasu,Bomba-relógio dos Anciãos,,Bomba cu Ceas a Anticilor,Часовая бомба древних,Временска бомба древних,Kadimlerin Saatli Bombası -Wings of Wrath,TAG_ARTIFLY,,,,Křídla hněvu,Vredens vinger,Flügel des Zorns,,Flugiloj de Kolero,Alas de Ira,,Kiihtymyksen siivet,Ailes du Courroux,Harag szárnyai,Ali Iraconde,レイスの翼,분노의 날개,Vleugels der Toorn,Vredens vinger,Skrzydła Gniewu,Asas da Ira,,Aripile Furiei,Крылья гнева,Крила гнева,Gazap Kanatları -Quartz Flask,TAG_ARTIHEALTH,,,,Blyštivá baňka,Kvartsflaske,Quarzflasche,,Kvarca Flakono,Frasco de Cuarzo,,Kvartsipullo,Flasque en Quartz,Kvarc flaska,Fiaschetta al Quarzo,石英フラスコ,석영 플라스크,Kwartskolf,Kvartskolbe,Kwarcowa Butelka,Frasco de Quartzo,,Flacon de Quartz,Кварцевый флакон,Кварцна боца,Kuvars Şişesi -Shadowsphere,TAG_ARTIINVISIBILITY,,,,Šerosféra,Skyggesfære,Schattensphäre,Σκιόσφαιρα,Ombrosfero,Esfera de Sombra,,Varjokehrä,Orbe des Ombres,Sötétgömb,Ombrosfera,闇の球体,그림자 구체,Schaduwbol,Skyggesfære,Sfera Cieni,Esfera das Sombras,,Sfera Umbrei,Теневая сфера,Сфера сенки,Gölge Küre -Ring of Invincibility,TAG_ARTIINVULNERABILITY,,,,Prsten nesmrtelnosti,Ring af uovervindelighed,Ring der Unverwundbarkeit,,Ringo de Nevenkebleco,Anillo de Invencibilidad,,Näkymättömyyden sormus,Anneau d'Invincibilité,Sérthetetlenség gyűrűje,Anello dell'invincibilità,不死の指輪,불멸의 반지,Ring van Onoverwinnelijkheid,Uovervinnelighetens ring,Pierścień Niewrażliwości,Anel da Invencibilidade,,Inelul Invincibilității,Кольцо неуязвимости,Прстен непобедивости,Yenilmezlik Yüzüğü -Mystic Urn,TAG_ARTISUPERHEALTH,,,,Tajemná urna,Mystisk urne,Mystische Urne,,Mistika Urno,Urna Mística,,Mystinen uurna,Urne Mystique,Misztikus urna,Urna Mistica,神秘の骨壷,신비한 항아리,Mystieke Urn,Mystisk urne,Mistyczna Urna,Urna Mística,,Urnă Mistică,Мистическая урна,Мистериозна урна,Mistik Urn -Chaos Device,TAG_ARTITELEPORT,,,,Zmatkostroj,Chaos-enhed,Chaosgerät,Συσκευή του Χάος,Ĥaos-Aparato,Dispositivo del Caos,,Kaaoskoje,Outil du Chaos,Káosz eszköz,Strumento del Caos,カオスデバイス,혼돈의 장치,Chaosapparaat,Kaosinnretning,Urządzenie Chaosu,Dispositivo do Caos,,Dispozitiv al Haosului,Механизм хаоса,Уређај хаоса,Kaos Cihazı -Tome of Power,TAG_ARTITOMEOFPOWER,,,,Kniha moci,Bog om magt,Buch der Macht,Τόμος της Δύναμης,Librego de Potenco,Tomo de Poder,,Väkevyyden kirja,Livre du Pouvoir,Erő kódexe,Tomo del Potere,力の術書,힘의 서,Boek van de Macht,Maktens bok,Tom Mocy,Tomo do Poder,,Cartea Puterii,Том могущества,Табла моћи,Güç Kubbesi -Torch,TAG_ARTITORCH,,,,Pochodeň,Fakkel,Fackel,Πύρσος,Torĉo,Antorcha,,Soihtu,Torche,Fáklya,Torcia ,松明,횃불,Fakkel,Fakkel,Pochodnia,Tocha,Torcha,Torță,Факел,Бакља,Meşale -,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,, -%o was pecked to death.,OB_CHICKEN,,,,%o byl@[ao_cs] uklován@[ao_cs] k smrti.,%o blev hakket ihjel.,%o wurde zu Tode gepickt.,,%o estis bekita ĝis morto.,%o fue picotead@[ao_esp] hasta la muerte.,,%o nokittiin kuoliaaksi.,%o a été picoré@[e_fr] a mort.,%o halálra lett csípve.,%o è stato beccato a morte.,%o はくちばしで突かれ死んだ。,%o 은(는) 쪽팔리게 쪼여 죽었다.,%o werd doodgepikt.,%o ble hakket i hjel.,%o został@[ao_pl] zadzioban@[adj_pl] na śmierć.,%o foi bicad@[ao_ptb] até a morte.,%o foi picad@[ao_ptb] até a morte.,%o a fost ciocănit până la moarte.,Игрок %o заклёван до смерти.,%o је искљуцан@[adj_1_sr] до смрти.,%o gagalanarak öldürüldü. -%o was charred by a weredragon.,OB_BEAST,,,,%o byl@[ao_cs] spálen@[ao_cs] vlkodrakem.,%o blev forkullet af en varedrage.,%o wurde von dem Werdrachen verschmort.,,%o brulegiĝis de lupdrako.,%o fue carbonizad@[ao_esp] por una bestia dragón.,,%o joutui ihmislohikäärmeen kärventämäksi.,%o a été carbonisé@[e_fr] par un dragon-garou.,%o szénné égett egy Vérsárkány által.,%o è stato carbonizzato da una bestia.,%o はウェアドラゴンに黒焦げにされた。,%o 은(는) 웨어드래곤에 의해 검게 탔다.,%o werd verbrand door een weerdraak.,%o ble forkullet av en vardrage.,%o został@[ao_pl] zwęglon@[adj_pl] przez smokołaka.,%o foi carbonizad@[ao_ptb] por um homem-dragão.,,%o a fost ceruit de un vârcodragon.,Игрок %o обуглен драконом-оборотнем.,%o је реш печен@[adj_1_sr] од стране замјодлака.,%o bir kurt ejderha tarafından yakıldı. -%o was slashed by a sabreclaw.,OB_CLINK,,,,%o byl@[ao_cs] rozsápán@[ao_cs] šavlozubem.,%o blev skåret op af en sabreklo.,%o wurde von der Säbelklaue zerschlitzt.,,%o tranĉegiĝis de sabrokrifo.,%o fue acuchillad@[ao_esp] por un garra de sable.,,%o joutui sapelikynnen sivaltamaksi.,%o s'est fait découper par un sabregriffe.,%o meg lett vágva egy Szablyakarom által.,%o è stato squarciato da un lapillo.,%o はサーベルクローに切り裂かれた。,%o 은(는) 세이버클로에게 잘렸다.,%o werd door een sabelklauw gesneden.,%o ble kuttet av en sabelklo.,%o został@[ao_pl] posiekan@[adj_pl] przez szabloszpona.,Um Unhas-de-sabre cortou %o.,,%o a fost tăiat de o gheară de sabie.,Игрока %o нарезал саблекоготь.,Играча %o је исекао тигар.,%o bir kılıç pençe tarafından kesildi. -%o was scalded by D'Sparil's serpent.,OB_DSPARIL1,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] ořem D'Sparila.,%o blev skoldet af D'Sparils slange.,%o wurde von D'Sparils Schlange verbrüht.,,%o varmegiĝis de la serpento de D'Sparil.,%o fue abrasad@[ao_esp] por la serpiente de D'Sparil.,,%o joutui D'Sparilin käärmeen kalttaamaksi.,%o a été ébouillanté@[e_fr] par un serpent de D'Sparil.,%o le lett forrázva D'Sparil Kígyója által.,%o è stato bruciato dal serpente di D'Sparil.,%o はデ'スパリルのサーペントに火傷を負わされた。,%o 은(는) 드'스파릴의 서펜트에 데였다.,%o werd gebroeid door de slang van D'Sparil.,%o ble skåldet av D'Sparils slange.,%o został@[ao_pl] poparzon@[adj_pl] przez węża D'Sparila.,%o foi escaldad@[ao_ptb] pela serpente de D'Sparil.,,%o a fost opărit de șarpele lui D'Sparil.,Игрока %o обжёг змей Д'Спарила.,Играча %o је опекао Д'Спарилова змија.,"%o, D'Sparil'in yılanı tarafından haşlandı." -%o was chewed up by D'Sparil's serpent.,OB_DSPARIL1HIT,,,,%o byl@[ao_cs] rozkousán@[ao_cs] ořem D'Sparila.,%o blev tygget op af D'Sparils slange.,%o wurde von D'Sparils Schlange verspeist.,,%o maĉegiĝis de la serpento de D'Sparil.,%o fue engullid@[ao_esp] por la serpiente de D'Sparil.,,%o joutui D'Sparilin käärmeen pureksimaksi.,%o a été dévoré@[e_fr] par un serpent de D'Sparil.,%o meg lett rágva D'Sparil Kigyója által.,%o è stato masticato dal serpente di D'Sparil.,%o はデ'スパリルのサーペントに噛み砕かれた。,%o 은(는) 드'스파릴의 서펜트에게 씹혔다.,%o werd door de slang van D'Sparil opgekauwd.,%o ble tygd opp av D'Sparils slange.,%o został@[ao_pl] przeżut@[adj_pl] przez węża D'Sparila.,%o foi mastigad@[ao_ptb] pela serpente de D'Sparil.,,%o a fost mestecat de șarpele lui D'Sparil.,Игрока %o пожрал змей Д'Спарила.,%o је сажвакан@[adj_1_sr] од стране Д'Спарилове змије.,"%o, D'Sparil'in yılanı tarafından çiğnendi." -%o was no match for D'Sparil.,OB_DSPARIL2,,,,%o nebyl@[ao_cs] pro D'Sparila žádná výzva.,%o kunne ikke klare D'Sparil.,%o war kein Gegner für D'Sparil.,,%o ne estis rivalo por D'Sparil. ,%o no fue rival para D'Sparil.,,%o ei mahtanut mitään D'Sparilille.,%o n'a pas pu égaler D'Sparil.,%o nem volt méltó ellenfél D'Sparil számára.,%o non era all'altezza di D'Sparil.,%o はデ'スパリルには全く歯が立たなかった。,%o 은(는) 드'스파릴에겐 상대가 되지 못했다.,%o was geen partij voor D'Sparil.,%o var ingen match for D'Sparil.,%o nie miał@[ao_pl] szans z D'Sparilem.,%o não foi páreo para D'Sparil.,%o não foi desafio para D'Sparil.,%o n-a fost nici pe departe pe măsura lui D'Sparil.,Игрок %o был не ровня Д'Спарилу.,%o није ни до колена Д'Спарилу.,"%o, D'Sparil'in dengi değildi." -%o was smacked down by D'Sparil.,OB_DSPARIL2HIT,,,,%o byl@[ao_cs] sražen@[ao_cs] D'Sparilem.,%o blev slået ned af D'Sparil.,%o wurde von D'Sparil zerklatscht.,,%o frapiĝis de D'Sparil.,%o fue vapulead@[ao_esp] por D'Sparil.,%o ha sido golpead@[ao_esp] por D'Sparil.,%o joutui D'Sparilin löylyttämäksi.,%o a été battu@[e_fr] a plate couture par D'Sparil.,%o a földre lett csapva D'Sparil által.,%o è stato abbattuto da D'Sparil.,%o はデ'スパリルに打ち負かされた。,%o 은(는) 드'스파릴의 맹격에 쓰러졌다.,%o werd neergeslagen door D'Sparil.,%o ble slått ned av D'Sparil.,%o został@[ao_pl] roztrzaskan@[adj_pl] przez D'Sparila,%o foi mort@[ao_ptb] por D'Sparil.,,%o a fost pus la pământ de D'Sparil.,Игрок %o сбит с ног Д'Спарилом.,%o је претучен@[adj_1_sr] од стране Д'Спарила.,"%o, D'Sparil tarafından yere serildi." -%o was scarred by a gargoyle.,OB_HERETICIMP,,,,%o byl@[ao_cs] upálen@[ao_cs] chrličem.,%o blev mærket af en gargoyle.,%o wurde von einem Gargoyle zerkratzt.,,%o ĉikartiĝis de gargojlo.,%o fue cicatrizad@[ao_esp] por una gárgola.,,%o joutui gargoilin arpeuttamaksi.,%o a été effrayé@[e_fr] par une gargouille.,%o meg lett sebesítve egy vízköpő által.,%o è stato terrorizzato da un imp.,%o はガーゴイルに傷を負わされた。,%o 은(는) 가고일에 의해 다쳤다.,%o was getekend door een gargoyle.,%o ble arret av en gargoyle.,%o został@[ao_pl] zadrapan@[adj_pl] przez gargulca,%o foi cicatrizad@[ao_ptb] por uma gárgula.,,%o a fost cicatrizat de o garguie.,Игрока %o изуродовала горгулья.,%o је ожиљкан@[adj_1_sr] од стране камене утваре.,%o bir gargoyle tarafından yaralandı. -%o was hacked by a gargoyle.,OB_HERETICIMPHIT,,,,%o byl@[ao_cs] rozsekán@[ao_cs] chrličem.,%o blev hakket af en gargoyle.,%o wurde von einem Gargoyle zerhackt.,,%o hakiĝis de gargojlo.,%o fue arañad@[ao_esp] por una gárgola.,,%o joutui gargoilin pilkkomaksi.,%o a été mis@[e_fr] en pièces par une gargouille.,%o fel lett vágva egy vízköpő által.,%o è stato eliminato da un imp.,%o はガーゴイルに切り刻まれた。,%o 은(는) 가고일에 의해 베였다.,%o werd gehackt door een gargoyle.,%o ble hakket av en gargoyle.,%o został@[ao_pl] pocięt@[adj_pl] przez gargulca,%o foi mutilad@[ao_ptb] por uma gárgula.,,%o a fost tăiat de o garguie.,Игрока %o покалечила горгулья.,Играча %o је исекла камена утвара.,%o bir gargoyle tarafından kesildi. -%o was devastated by an ironlich.,OB_IRONLICH,,,,%o byl@[ao_cs] zničen@[ao_cs] železným kostějem.,%o blev ødelagt af en jern lig.,%o wurde von der Eisernen Leiche zerstört.,,%o ruiniĝis de ferliĉo.,%o fue devastad@[ao_esp] por un liche de hierro.,,%o joutui rautakalmon hävittämäksi.,%o a été dévasté@[e_fr] par une Liche de Fer.,%o elpusztult egy ezüst lich miatt.,%o è stato devastato da un ironlich.,%o はアイアンリッチに吹き飛ばされた。,%o 은(는) 아이언 리치에게 붕괴 당했다.,%o werd verwoest door een ijzeren lijk.,%o ble knust av en jernlich.,%o został@[ao_pl] zdewastowan@[adj_pl] przez żelaznego lisza,%o foi devastad@[ao_ptb] por um lich de ferro.,,%o a fost devastat de un cadavru de fier.,Игрока %o растоптал железный лич.,%o је уништен@[adj_1_sr] од стране челичног лича.,%o demir bir ceset tarafından harap edildi. -%o got up-close and personal with an ironlich.,OB_IRONLICHHIT,,,,%o se dostal@[ao_cs] moc blízko k železnému kostěji.,%o kom helt tæt på en jern lig.,%o kam der Eisernen Leiche zu nahe.,,%o havis proksiman kaj desonan rekonton kun ferliĉo.,%o tuvo un encuentro cercano y personal con un liche de hierro.,,%o meni lähelle rautakalmoa.,%o a fait ami@[e_fr]-ami@[e_fr] avec une Liche de Fer.,%o közel került és személyes volt egy ezüst lichhel szemben.,%o è andato troppo vicino a un ironlich.,%o はアイアンリッチと密接に関わった。,%o 은(는) 사적인 이유로 아이언 리치에게 다가왔다.,%o werd door een ijzeren lijk onheus bejegend.,%o fikk nærkontakt med en jernlich.,%o był@[ao_pl] blisko i na osobności z żelaznym liszem,%o chegou muito perto de um lich de ferro.,,"%o s-a apropiat prea mult de un -cadavru de fier.",Игрок %o близко и лимно узнал железного лича.,%o се лично приближи@[ao_1_sr] челичном личу.,%o demir bir cesede çok yaklaştı. -%o was axed by an undead warrior.,OB_BONEKNIGHT,,,,%o dostal@[ao_cs] sekyrou od nemrtvého válečníka.,%o blev øksehugget af en udød kriger.,%o wurde von dem Untoten Krieger mit der Axt bearbeitet.,,%o hakiliĝis de malviva batalisto.,%o recibió un hachazo de un guerrero no-muerto.,,%o joutui epäkuolleen soturin kirvestämäksi.,%o s'est pris@[e_fr] la hâche d'un guerrier mort-vivant.,%o baltát kapott egy Élőhalott Harcostól.,%o è stato accettato da un guerriero non morto .,%o はアンデッド兵の斧でやられた。,%o 은(는) 언데드 전사에게 도끼질 당했다.,%o werd doorkliefd door een ondode krijger.,%o ble hugget av en udød kriger.,%o został@[ao_pl] rozłupany siekierą przez nieumarłego wojownika,%o foi decepad@[ao_ptb] por um guerreiro morto-vivo.,%o foi decapitad@[ao_ptb] por um guerreiro morto-vivo.,%o a primit un topor de la un războinic nemort.,Игрока %o зарубил воин-нежить.,%o је исечен@[adj_1_sr] од стане немртвог ратника.,%o bir ölümsüz savaşçı tarafından baltalandı. -%o was slain by an undead warrior.,OB_BONEKNIGHTHIT,,,,%o byl@[ao_cs] zabit@[ao_cs] nemrtvým válečníkem.,%o blev dræbt af en udød kriger.,%o wurde von dem Untoten Krieger hingemetzelt.,,%o estis mortigita de malviva batalisto.,%o fue descuartizad@[ao_esp] por un guerrero no-muerto.,,%o joutui epäkuolleen soturin tappamaksi.,%o s'est fait pourfendre par un guerrier mort-vivant.,%o meghalt egy Élőhalott Harcos által.,%o è stato ucciso da un guerriero non morto. ,%o はアンデッド兵の手で葬られた。,%o 은(는) 언데드 전사에게 처단당했다.,%o werd gedood door een ondode krijger.,%o ble drept av en levende død kriger.,%o został@[ao_pl] zgładzon@[adj_pl] przez nieumarłego wojownika,%o foi picotad@[ao_ptb] por um guerreiro morto-vivo.,,%o a fost omorât de un războinic nemort.,Игрока %o сразил воин-нежить.,Играча %o је убио немртви ратник.,%o bir ölümsüz savaşçı tarafından katledildi. -%o was blasted into cinders by a Maulotaur.,OB_MINOTAUR,,,,%o byl@[ao_cs] rozmetán@[ao_cs] na popel Minotaurem.,%o blev sprængt i aske af en Maulotaurus.,%o wurde von dem Minotaurus in Asche verwandelt.,,%o eksplodiĝis en cindrojn de Bategtaŭro.,%o fue volad@[ao_esp] en cenizas por un Mazotauro.,,%o tuhottiin tuusan nuuskaksi maulotaurin toimesta.,%o s'est fait@[e_fr] incinérer par un Massetaure.,%o darabokra robbant egy Maulotaurusz által.,%o è stato incenerito da un Maulotauro. ,%o はマウロタウロスに燃やされ炭化した。,%o 은(는) 몰로타우어에게 잿더미가 되도록 파괴당했다.,%o werd door een Maulotaurus tot sintels geblazen.,%o ble sprengt til aske av en Maulotaur.,%o został@[ao_pl] obrócon@[adj_pl] w popiół przez Młototaura,%o foi incinerad@[ao_ptb] por um Marretauro,,%o a fost făcut cenușă de un Maulotaur.,Игрока %o разнёс на угольки Избитавр.,%o је испуцан@[adj_1_sr] у пепео од стране минотаура.,%o bir Maulotor tarafından kül haline getirildi. -%o was pulped by a Maulotaur.,OB_MINOTAURHIT,,,,%o byl@[ao_cs] rozmáčknut@[ao_cs] Minotaurem.,%o blev knust af en Maulotaurus.,%o wurde von dem Minotaurus zu Brei verarbeitet.,,%o pulpiĝis de Bategtaŭro.,%o fue pulpad@[ao_esp] por un Mazotauro.,,%o joutui maulotaurin möyhentämäksi.,%o s'est fait@[e_fr] éclater par un Massetaure.,%o péppé lett zúzva egy Maulotaurusz által.,%o è stato ridotto in poltiglia da un Maulotauro. ,%o はマウロタウロスにグシャグシャにされた。,%o 은(는) 몰로타우어에 의해 내동댕이쳐졌다.,%o werd verpulverd door een Maulotaurus.,%o ble knust av en maulotaur.,%o został@[ao_pl] roztart@[adj_pl] na miazgę przez Młototaura,%o foi esmagad@[ao_ptb] por um Marretauro,,%o a fost descojit de un Maulotaur.,Игрока %o превратил в кровавое месиво Избитавр.,Играча %o је претукао минотаур.,%o bir Maulotor tarafından ezildi. -%o was smashed by a golem.,OB_MUMMY,,,,%o byl@[ao_cs] umlácen@[ao_cs] golémem.,%o blev smadret af en golem.,%o wurde von einem Golem erschlagen.,,%o frakasiĝis de golemo.,%o fue aplastad@[ao_esp] por un golem.,,%o joutui golemin murskaamaksi.,%o a été défoncé@[e_fr] par un golem.,%o össze lett törve egy Gólem által.,%o è stato schiacciato da un golem.,%o はゴーレムに叩きのめされた。,%o 은(는) 골렘에게 두들겨 맞았다.,%o werd verbrijzeld door een golem.,%o ble knust av en golem.,%o został@[ao_pl] stłuczon@[adj_pl] przez golema,%o foi esmagad@[ao_ptb] por um golem.,,%o a fost lovit de un golem.,Игрока %o разбил голем.,Играча %o је смрвио голем.,%o bir golem tarafından parçalandı. -%o was shrieked to death by a nitrogolem.,OB_MUMMYLEADER,,,,%o byl@[ao_cs] ukřičen@[ao_cs] k smrti střelgolémem.,%o blev skriget til døde af en nitrogolem.,%o wurde von einem Nitrogolem zu Tode gekreischt.,,%o estis kriegita ĝis morto de azotgolemo.,%o fue chillad@[ao_esp] hasta la muerte por un nitrogolem.,%o ha sido aplanad@[ao_esp] hasta la muerte por un nitrogolem.,%o kirkaistiin kuoliaaksi nitrogolemin toimesta.,%o s'est fait@[e_fr] percer les tympans par un nitrogolem.,%o halálra lett ijesztve egy Nitrógólem által.,%o è stato stroncato da un golem.,%o はニトロゴーレムに脅かされた。,%o 은(는) 니트로 골렘에 의해 비명횡사 당했다.,%o werd doodgekrijst door een nitrogolem.,%o ble skreket i hjel av en nitrogolem.,%o został@[ao_pl] zakrzyczan@[adj_pl] na śmierć przez nitrogolema,%o agonizou na frente de um nitrogolem.,,%o a fost chiuit până la moarte de un nitrogolem.,Игрока %o убил криком нитроголем.,Играча %o је извриштао до смрти нитроголем.,%o bir nitrogolem tarafından çığlık çığlığa öldürüldü. -%o was rattled by an ophidian.,OB_SNAKE,,,,%o byl@[ao_cs] zachřestěn@[ao_cs] šupinatcem.,%o blev rystet af en ophidian.,%o hörte das Klappern des Ophidian.,,%o klakiĝis de ofidio.,%o fue agitad@[ao_esp] por un ofidio.,,%o joutui käärmeolion kalkattamaksi.,%o s'est fait@[e_fr] sonner par un ophidien.,%o halálra lett csörgetve egy Ofidián által.,%o è stato stritolato da un serpente.,%o はオフィディアンに動揺した。,%o 은(는) 오피디안에게 흔들렸다.,%o werd gerammeld door een ophidiaan.,%o ble rystet av en ophidian.,%o został@[ao_pl] rozgrzechotan@[adj_pl] przez wężowatego,%o foi sacudid@[ao_ptb] por um ofídio.,,%o a fost bătut până la moarte de un ofidian.,Игрока %o потряс офидиан.,Играча %o је угризла змија.,%o bir ophidian tarafından sarsıldı. -%o was cursed by a wizard.,OB_WIZARD,,,,%o byl@[ao_cs] zaklet@[ao_cs] čarodějem.,%o blev forbandet af en troldmand.,%o wurde von dem Magier verflucht.,,%o malbeniĝis de sorĉisto.,%o fue maldecid@[ao_esp] por un mago.,%o ha sido hechizad@[ao_esp] por un mago.,%o joutui velhon kiroamaksi.,%o a été maudit@[e_fr] par un sorcier.,%o meg lett átkozva egy Varázsló által.,%o è stato maledetto da un mago.,%o はウィザードに呪われた。,%o 은(는) 드'스파릴의 제자에 의해 저주받았다.,%o werd vervloekt door een tovenaar.,%o ble forbannet av en trollmann.,%o został@[ao_pl] przeklęt@[adj_pl] przez czarownika,%o foi amaldiçoad@[ao_ptb] por um mago.,,%o a fost blestemat de un vrăjitor.,Игрока %o проклял колдун.,%o је проклет@[adj_1_sr] од стране чаробњака.,%o bir büyücü tarafından lanetlendi. -%o was palpated by a wizard.,OB_WIZARDHIT,,,,%o byl@[ao_cs] prozkoumán@[ao_cs] čarodějem.,%o blev palperet af en troldmand.,%o spürte den Hauch des Magiers.,,%o palpatiĝis de sorĉisto.,%o fue palpad@[ao_esp] por un mago.,,%o joutui velhon tunnustelemaksi.,%o a été palpé@[e_fr] par un sorcier.,%o meg lett tapogatva egy Varázsló által.,%o è stato toccato da un mago.,%o はウィザードに触診されてしまった。,%o 은(는) 드'스파릴의 제자에게 촉진당했다.,%o werd betast door een tovenaar.,%o ble palpert av en trollmann.,%o został@[ao_pl] przebadan@[adj_pl] przez czarownika,%o foi apalpad@[ao_ptb] por um mago.,,%o a fost palpat de un vrăjitor.,Игрока %o пощупал колдун.,Играча %o је палпатирао чаробњак.,%o bir büyücü tarafından palpe edildi. -%o got staffed by %k.,OB_MPSTAFF,,,,%o dostal@[ao_cs] holí od hráče %k.,%o blev stafferet af %k.,%o wurde von %k verprügelt.,,%o bategiĝis de %k.,%o fue apalead@[ao_esp] por %k.,,%k sauvoi %k paran.,%o s'est fait@[e_fr] matraquer par %k.,%o meg lett botozva %k által.,%o è stato preso a colpi di staffa da %k.,%o は %k の棒でぶん殴られた。,%o 은(는) %k 의 지팡이에 제압당했다.,%o kreeg een tik van %k's staf.,%o ble staffet av %k.,%o został@[ao_pl] walnięt@[adj_pl] laską przez %k,%o levou uma sova do bastão de %k.,,%o a fost bastonat de %k.,Игрок %o дополнил посох игрока %k.,%o је претуцан@[adj_1_sr] штапом од стране %k.,"%o, %k tarafından öldüresiye dövüldü." -%o got a shock from %k's gauntlets.,OB_MPGAUNTLETS,,,,%o byl@[ao_cs] prošokován@[ao_cs] rukavicemi hráče %k.,%o fik et chok af %ks handsker.,%o bekam einen Schock von %ks Handschuhen.,,%o recivis ŝokon de la fergantoj de %k.,%o recibió un choque de los guanteletes de %k.,,%o sai sähköiskun pelaajan %k kintaista.,%o s'est pris@[e_fr] un coup de jus des gantelets de %k.,%o kapott egy sokkot %k által.,%o è stato folgorato dai guanti di %k.,%o は %k の篭手からショックを受けた。,%o 은(는) %k 가 쓰고 있는 건틀릿의 전격을 느꼈다.,%o kreeg een schok van %k's handschoenen.,%o fikk støt av %ks hansker.,%o został@[ao_pl] wstrząśnięt@[adj_pl] rękawicami %k,%o tomou um choque das manoplas de %k.,,%o a primit un șoc de la mănușile lui %k.,Игрок %o шокирован перчатками игрока %k.,%o је доби@[ao_1_sr] шок од %k штапа.,"%o, %k tarafından şoklandı." -%o waved goodbye to %k's elven wand.,OB_MPGOLDWAND,,,,%o zamával@[ao_cs] elfské hůlce hráče %k.,%o vinkede farvel til %ks elverstav.,%o sagte „Tschüß“ zu %ks Elfenstab.,,%o ĝisis al la elfa sorĉbastono de %k.,%o le dijo adiós a la vara de elfo de %k.,,%o heilutti hyvästit pelaajan %k haltiasauvalle.,%o à fait coucou à la baguette magique de %k.,%o integetett egy viszlátot %k Elf Pálcájának.,%o ha fatto ciao ciao allo scettro elfico di %k.,%o は %k のエルフのワンドに別れの挨拶をした。,%o 은(는) %k 의 엘프 지팡이를 보고 작별인사를 했다.,%o zwaaide afscheid van %k's elvenstaf.,%o vinket farvel til %ks alvestav.,%o pomachał@[ao_pl] na do widzenia elfiej różdżce %k,%o deu tchauzinho para o cetro élfico de %k.,%o disse adeuzinho para o cetro élfico de %k.,%o a facut cu mână toiagului lui %k.,Игрок %o узрел прощальный взмах эльфийского жезла игрока %k.,%o је рек@[ao_2_sr] збогом %k вилењачком штапићу.,"%o, %k tarafından delik deşik edildi." -%o was pegged by %k's ethereal crossbow.,OB_MPCROSSBOW,,,,%o byl@[ao_cs] prostřelen@[ao_cs] éterickou kuší hráče %k.,%o blev stukket af %ks æteriske armbrøst.,%o von %ks Armbrustbolzen aufgespießt.,,%o kejlis de la etera arbalesto de %k.,%o fue flechad@[ao_esp] por la ballesta etérea de %k.,,%k ripusti %o paran eteerivarsijousellaan.,%o s'est fait@[e_fr] clouer par l'arbalète étherique de %k.,%o fel lett rögzítve %k Éteri Nyílpuskájának által.,%o è stato inchiodato dalla balestra eterea di %k.,%o は %k のイセリアルクロスボウで釘付けにされた。,%o 은(는) %k 의 유체 쇠뇌에 의해 처박혔다.,%o was vastgepind door %k's etherische kruisboog.,%o ble truffet av %ks eteriske armbrøst.,%o został@[ao_pl] przebit@[adj_pl] przez eteryczną kuszę %k,%o foi esmigalhad@[ao_ptb] pela besta etérea de %k.,,%o a fost prins de arbaleta celestă a lui %k.,Игрок %o изранен болтами эфирного арбалета игрока %k.,%o је упуц@[adj_2_sr] од стране %k етералног самострела.,"%o, %k tarafından çivilendi." -%o was blasted a new one by %k's dragon claw.,OB_MPBLASTER,,,,%o poznal@[ao_cs] středověk drakospárem hráče %k.,%o blev sprængt en ny af %ks drageklo.,%o bekam %ks Drachenklaue zu spüren.,,%o estis diseksplodita de la drakokrifo de %k.,%o quedó bien jodid@[ao_esp] por la garra de dragón de %k.,,%k puhkoi %o parkaan uuden aukon lohikäärmeenkynnellään.,%o s'est fait flinguer par la griffe draconique de %k.,%o újszerűnek látszik %k Sárkány Karomjának köszönhetően.,A %o èstato aperto un buco nuovo dall'Artiglio di Drago di %k.,%o は %k のドラゴンクローで発破体験した。,%o 은(는) %k 의 용발톱에 의해 형태를 잃었다.,%o werd opengescheurd door %k's drakenklauw.,%o fikk en ny en av %ks drageklo.,%o został wysadzony nowy otwór przez %k,%o sentiu o poder da garra de dragão de %k.,,%o a fost aruncat în aer de gheara dragonului a lui %k.,Игрок %o получил новую форму драконьим когтем игрока %k.,Играчу %o је отворена нова рупа змајевском канџом играча %k.,"%o, %k tarafından patlatıldı." -%o got sent down under by %k's hellstaff.,OB_MPSKULLROD,,,,Pod hráčem %o se propadla zem peklopalem hráče %k.,%o blev sendt ned under jorden af %ks helvedestav.,%o brach unter %ks Höllenrute zusammen.,,%o forsendiĝis sub de la inferbastono de %k.,%o se inclinó ante el bastón infernal de %k.,,%k lähetti %o paran maan syövereihin hornansauvallaan.,%o repose six pieds sous terre grâce au Bâton infernal de %k.,%o le lett küldve %k Pokolbotjának köszönhetően.,%o è stato mandato sottoterra dalla Staffa Infernale di %k.,%o は %k のヘルスタッフで冥界に送られた。,%o 은(는) %k 의 지옥지팡이에 의해 저승으로 날아갔다.,%o werd door %k's hellestaf naar beneden gestuurd.,%o ble sendt til helvete av %ks helvetesstav.,%o został@[ao_pl] zesłan@[adj_pl] pod piekielny kostur %k,%o foi mandad@[ao_ptb] pra baixo do solo pelo cajado infernal de %k.,,%o a fost trimis sub bastonul infernal al lui %k.,Игрок %o сослан в самый низ посохом ада игрока %k.,%o је укопан@[adj_1_sr] од стране пакленог штапа играча %k.,"%o, %k tarafından biçildi." -%o was scorched to cinders by %k's phoenix rod.,OB_MPPHOENIXROD,,,,%o byl@[ao_cs] spálen@[ao_cs] na prach fénixovou holí hráče %k.,%o blev brændt til aske af %ks føniksstav.,%o wurde voin %ks Phönixstab verschmort.,,%o brulegiĝis en cindrojn de la feniksvergo de %k.,%o fue reducid@[ao_esp] a cenizas por el báculo del Fénix de %k.,,%k kärvensi %o paran tuhannen päreiksi feenikssauvallaan.,%o s'est fait@[e_fr] réduire en cendres par le Bâton du Phénix de %k.,%o halomra lett égve %k Főnix Rúdjának által.,%o è stato ridotto in cenere dal Bastone della Fenice di %k.,%o は %k のフェニックスロッドで焼かれた。,%o 은(는) %k 의 불사조 지팡이 덕에 검게 익었다.,%o werd door %k's feniksstaf tot sintels verschroeid.,%o ble svidd til aske av %ks føniksstav.,%o został@[ao_pl] spalon@[adj_pl] na popiół przez różdżkę feniksa %k,%o virou cinzas com o bastão da fênix de %k.,,%o a fost făcut cenușă de joarda phoenix a lui %k.,Игрок %o сожжён до пепла жезлом феникса игрока %k.,%o запаљен@[adj_1_sr] у пепео од стране шипке феникса играча %k.,"%o, %k tarafından cayır cayır yakıldı." -%o was bounced by %k's firemace.,OB_MPMACE,,,,%o byl@[ao_cs] odpálen@[ao_cs] žezlometem hráče %k.,%o blev kastet afsted af %ks ildspyd.,%o prallte an %ks Feuerkeule ab.,,%o estis resaltita de la fajroklabo de %k.,%o recibió los rebotes de la maza de fuego de %k.,,%k pomputti %o parkaa tulinuijallaan.,%o a rebondi@[e_fr] sur les balles de la Masse de Feu à %k.,%o pattant egy nagyot %k Tűzbuzogányának köszönhetően.,%o è stato spazzato via dalla Mazza del Fuoco di %k.,%o は %k のファイアメイスで飛ばされた。,%o 은(는) %k 의 투사철퇴의 포탄을 맞고 튕겨져 날아갔다.,%o werd door %k's vuurknots geraakt.,%o ble kastet av %ks ildkule.,%o został@[ao_pl] wybit@[adj_pl] przez buzdygan ognia %k,%o saiu pulando após ver a clava de fogo de %k.,,"%o a fost aruncat de colo colo de buzduganul de -foc al lui %k.",Игрок %o отбит огненной булавой игрока %k.,%o је ударен@[adj_1_sr] са ватреним буздованом играча %k.,"%o, %k tarafından ezildi." -%o got clapped by %k's charged staff.,OB_MPPSTAFF,,,,%o byl@[ao_cs] profackován@[ao_cs] nabitou holí hráče %k.,%o blev klappet af %ks ladede stav.,%o bekam eine Klatsche durch %ks geladenen Stab.,,%o estis aplaŭdita de la ŝargita bastono de %k.,%o recibió los palos del bastón cargado de %k .,,%k jyrisytti %o parkaa varatulla sauvallaan.,%o à été foudroyé@[e_fr] par le bâton chargé de %k.,%o csattant egy nagyot %k Feltöltött Botjának által.,%o è scoppiato a causa della staffa incantata di %k.,%o は %k の魔力を帯びた棒で暖かく迎えられた。,%o 은(는) %k 의 마법부가 지팡이를 얻어맞았다.,%o kreeg een klap van %k's opgeladen staf.,%o ble klappet av %ks ladede stav.,%o został@[ao_pl] trzepnięt@[adj_pl] naładowaną laską %k,%o tomou uma pancada do bastão carregado de %k.,,%o a fost tăiat de bastonul încărcat al lui %k.,Игрок %o отведал заряженного посоха игрока %k.,%o је потапшан@[adj_1_sr] напуњеним штапом играча %k.,"%o, %k tarafından yakıldı." -%o was bled dry by %k's gauntlets.,OB_MPPGAUNTLETS,,,,Rukavicemi hráče %k nezůstala v těle hráče %o ani kapka krve.,%o blev udblødt af %ks handsker.,%o wurde von %ks Handschuhen ausgeblutet.,,%o sensangiĝis de la fergantoj de %k.,%o fue desangrad@[ao_esp] por los guanteletes de %k.,,%k vuodatti %o paran kuiviin kintaillaan.,%o s'est fait@[e_fr] saigner à blanc par les gantelets de %k.,%k megtanította %o-t Páncélkesztyűbe dudálni.,Il sangue di %o è stato prosciugato dai guanti di %k.,%o は %k の篭手で血を絞り取られた。,%o 은(는) %k 의 마법부가 건틀릿에 의해 바싹 말랐다.,%o werd leeggebloed door %k's handschoenen.,%o ble tappet for blod av %ks hansker.,%o wykrwawił@[ao_pl] się przez rękawice %k,%o sangrou nas manoplas de %k.,,"%o a fost stors până la ultima picătură de sânge -de mănușile lui %k.",Игрок %o был обескровлен перчатками игрока %k.,%o је путпуно искрвари@[ao_1_sr] од рукавица играча %k.,"%o, %k tarafından kan kaybından kurutuldu." -%o was assaulted by %k's elven wand.,OB_MPPGOLDWAND,,,,%o byl@[ao_cs] napaden@[ao_cs] elfskou hůlkou hráče %k.,%o blev overfaldet af %ks elverstav.,%o wurde von %ks Elfenstab überwältigt.,,%o atakiĝis de la elfa sorĉbastono de %k.,%o fue asaltad@[ao_esp] por la vara de elfo de %k.,,%o joutui pelaajan %k haltiasauvan pahoinpitelemäksi.,%o à été assailli@[e_fr] par la baguette elfique de %k.,%k megbotozta %o az Elf Botjával.,%o è stato assalito dallo Scettro Elfico di %k.,%o は %k のエルフのワンドで襲われた。,%o 은(는) %k 의 마법부가 엘프 지팡이에 의해 사냥당했다.,%o werd aangevallen door %k's elvenstaf.,%o ble angrepet av %ks alvestav.,%o został@[ao_pl] zaatakowan@[adj_pl] przez elfią różdżkę %k,%o foi atacad@[ao_ptb] pelo cetro élfico de %k.,,%o a fost luat cu asalt de togaiul lui %k.,Игрок %o атакован эльфийским жезлом игрока %k.,%o је нападнут@[adj_1_sr] вилењачким штапом играча %k.,"%o, %k tarafından saldırıya uğradı." -%o was shafted by %k's ethereal crossbow.,OB_MPPCROSSBOW,,,,%o byl@[ao_cs] proděravěn@[ao_cs] éterickou kuší hráče %k.,%o blev ramt af %ks æteriske armbrøst.,%o wurde von %ks Armbrustbolzen durchbohrt.,,%o akiris novan truon de etera arbalesto de %k.,%o fue encañonad@[ao_esp] por la ballesta etérea de %k.,,%k joutui pelaajan %k eteerivarsijousen kepittämäksi.,%o s'est fait@[e_fr] transpercer par l'arbalète éthérique de %k.,%o megkóstolta %k Éteri Nyílpuskáját.,%o è stato impalato dalla balestra eterea di %k.,%o は %k のイセリアルクロスボウで押された。,%o 은(는) %k 의 마법부가 유체 쇠뇌에 의해 무뎌졌다.,%o werd door %k's etherische kruisboog geschaafd.,%o ble truffet av %ks eteriske armbrøst.,%o został@[ao_pl] wykiwan@[adj_pl] przez eteryczną kuszę %k,%o foi flechad@[ao_ptb] pela besta etérea de %k.,,"%o a fost pus la proțap de arbaleta celestă a lui -%k.",Игрок %o пробит эфирным арбалетом игрока %k.,%o је упуцан@[adj_1_sr] етеричним самострелом играча %k.,"%o, %k tarafından şaftlandı." -%o was ripped apart by %k's dragon claw.,OB_MPPBLASTER,,,,%o byl@[ao_cs] roztrhnut@[ao_cs] naskrz drakospárem hráče %k.,%o blev flået i stykker af %ks drageklo.,%o wurde von der Drachenklaue zerrissen.,,%o disrompiĝis de la drakokrifo de %k.,%o fue desgarrad@[ao_esp] por la garra de dragón de %k.,,%k repi %o paran kappaleiksi lohikäärmeenkynnellään.,%o à été mis@[e_fr] en pièces par la griffe draconique de %k.,%o szét lett tépve %k Sárkány Karomja által.,%è stato fatto a brandelli dall'Artiglio di Drago di %k.,%o は %k のドラゴンの鉤爪でバラバラに引き裂かれた。,%o 은(는) %k 의 마법부가 용발톱에 갈기갈기 찢겨졌다.,%o werd uit elkaar gescheurd door %k's drakenklauw.,%o ble revet i filler av %ks drageklo.,%o został@[ao_pl] rozerwan@[adj_pl] przez smoczy pazur %k,%o foi cortad@[ao_ptb] pela garra de dragão de %k.,,%k a fost făcut bucăți de gheara lui %k.,Игрок %o разорван драконьим когтём игрока %k.,%o је поцепан@[adj_1_sr] змајевим канџама играча %k.,"%o, %k tarafından parçalara ayrıldı." -%k poured the hellstaff on %o.,OB_MPPSKULLROD,,,,Hráč %k vylil svůj peklopal na hráče %o.,%k hældte helvedesstaven ud over %o.,%k ließ den Höllenregen auf %o los.,,%k ŝutas la inferbastonon sur %o.,%k virtió su bastón infernal en %o.,,%k vuodatti hornansauvansa %o parkaan.,%k à versé toute la rage des enfers sur %o.,%o nem hozott esernyőt %o Pokolbot zápora ellen.,%k ha fatto sgorgare la sua Staffa Infernale su %o.,%o は %k にヘルスタッフを %p 注ぎ込まれた。,%k의 마법부가 지옥지팡이가 쏟아붓는 비를 %o 이(가) 맞았다.,%k liet de helregen los op %o.,%k helte helvetesstaven over %o.,%k polał@[ao_pl] swoim piekielnym kosturem %o,%k usou seu cajado infernal no %o.,,%k a vărsat bastonul infernal pe %o.,Игрок %k залил игрока %o горячим дождём при помощи посоха ада.,%k је просипа@[ao_1_sr] пламени штап на %o.,"%o, %k tarafından yakıldı." -%o was burned down by %k's phoenix staff.,OB_MPPPHOENIXROD,,,,%o byl@[ao_cs] vyhořen@[ao_cs] fénixovou holí hráče %k.,%o blev brændt ned af %ks Føniks stav.,%o wurde von %ks Phönixstab verbrannt.,,%o torĉiĝis de la feniksvergo de %k.,%o fue rostizad@[ao_esp] por el báculo del Fénix de %k.,,%k poltti %o paran feenikssauvallaan.,%o à été incinéré@[e_fr] par le Bâton du Phénix de %k.,%o elégett %k Főnix Botjának által.,%o è stato incendiato dal Bastone della Fenice di %k.,%o は %k のフェニックスロッドで焼き滅ぼされた。,%o 은(는) %k 의 마법부가 불사조 지팡이에 의해 화장당했다.,%o werd afgebrand door %k's feniksstaf.,%o ble brent ned av %ks føniksstav.,%o został@[ao_pl] spalon@[adj_pl] przez różdżkę feniksa %k,%o foi queimad@[ao_ptb] pelo bastão da fênix de %k.,,%o a fost ars complet de joarda lui %k.,Игрок %o сожжён жезлом феникса игрока %k.,%o је изгоре@[ao_1_sr] шипком феникса играча %k.,"%o, %k tarafından yakıldı." -%o was squished by %k's giant mace sphere.,OB_MPPMACE,,,,%o byl@[ao_cs] rozmačkán@[ao_cs] obrovskou žezlometnou koulí hráče %k.,%o blev mast af %ks ildspyd kugle.,%o wurde von %ks Feuerkeule zerquetscht.,,%o premiĝis de la grandega klubsfero de %k.,%o fue aplastad@[ao_esp] por una esfera gigante de la maza de %k.,,%k liiskasi %o paran jättiläisnuijapallollaan.,%o s'est fait@[e_fr] écraser par la balle de Masse géante de %k.,%o össze lett nyomva %k hatalmas buzogány gömbje által.,%o è stato spiaccicato da una sfera gigante della Mazza del Fuoco di %k.,%o は %k の巨大なメイススフィアで潰された。,%o 은(는) %k 의 마법부가 투사철퇴가 뿜은 거대포탄에 의해 납작해졌다.,%o werd verpletterd door %k's reusachtige strijdknots.,%o ble knust av %ks gigantiske muskatblomstkule.,%o został@[ao_pl] zmiażdżon@[adj_pl] przez ogromną kulę z buzdygana %k,%o foi esmagad@[ao_ptb] pela esfera de clava gigante de %k.,,"%o a fost strivit de globul buzduganului -lui %k.",Игрок %o раздавлен огромной сферой из огненной булавы %k.,%o је смрвљен@[adj_1_sr] од стане огромном сферско буздована играча %k.,"%o, %k tarafından ezildi." -,,Hexen,,,,,,,,,,,,,,,,,,,,,,,, -,,Pickup,,,,,,,,,,,,,,,,,,,,,,,, -Blue Mana,TXT_MANA_1,,,,Modrá mana,Blå Mana,Blaues Mana,,Blua Manao,Maná Azul,Mana Azul,Sininen mana,Mana Bleu,Kék Mana,Mana blu,青マナ,청색 마나,Blauwe Mana,Blå Mana,Niebieska Mana,Mana Azul,,Mană Albastră,Синяя мана,Плава мана,Mavi Mana -Green Mana,TXT_MANA_2,,,,Zelená mana,Grøn Mana,Grünes Mana,,Verda Manao,Maná Verde,Mana Verde,Vihreä mana,Mana Vert,Zöld Mana,Mana verde,緑マナ,녹색 마나,Groene Mana,Grønn Mana,Zielona Mana,Mana Verde,,Mană Verde,Зелёная мана,Зелена мана,Yeşil Mana -Combined Mana,TXT_MANA_BOTH,,,,Smíšená mana,Kombineret Mana,Kombiniertes Mana,,Kuna Manao,Maná Combinado,Mana Combinado,Yhdistetty mana,Mana Combiné,Kombinált Mana,Mana misto,複合マナ,윰합된 마나,Gecombineerde Mana,Kombinert mana,Połączona Mana,Mana Combinado,,Mană Mixtă,Общая мана,Комбинована мана,Kombine Mana -Steel Key,TXT_KEY_STEEL,,,,Ocelový klíč,Stålnøgle,Stahlschlüssel,Ατσάλινο Κλειδί,Ŝtala Ŝlosilo,Llave de Acero,,Teräsavain,Clé d'Acier,Acél Kulcs,Chiave d'acciaio,鋼の鍵,강철 열쇠,Stalen Sleutel,Stålnøkkel,Stalowy Klucz,Chave de Aço,,Cheia din Oțel,Стальной ключ,Челични кључ,Çelik Anahtar -Cave Key,TXT_KEY_CAVE,,,,Klíč od jeskyně,Hule-nøgle,Höhlenschlüssel,,Kavern-Ŝlosilo,Llave de la Caverna,,Luola-avain,Clé de la Cave,Barlang Kulcs,Chiave della caverna,洞窟の鍵,동굴 열쇠,Grotsleutel,Hulenøkkel,Klucz do Jaskini,Chave da Caverna,,Cheia Peșterii,Пещерный ключ,Пећински кључ,Mağara Anahtarı -Axe Key,TXT_KEY_AXE,,,,Sekyrový klíč,Økse-nøgle,Axtschlüssel,,Hakil-Ŝlosilo,Llave de Hacha,,Kirvesavain,Clé de la Hache,Fejsze Kulcs,Chiave dell'ascia,斧の鍵,도끼 열쇠,Bijlsleutel,Økse-nøkkel,Klucz-topór,Chave do Machado,,Cheia Topor,Топор-ключ,Кључ секира,Balta Anahtarı -Fire Key,TXT_KEY_FIRE,,,,Ohnivý klíč,Ild-nøgle,Feuerschlüssel,,Fajro-Ŝlosilo,Llave de Fuego,,Tuliavain,Clé du Feu,Tűz Kulcs,Chiave del fuoco,炎の鍵,불 열쇠,Vuursleutel,Ildnøkkel,Ognisty Klucz,Chave do Fogo,,Cheia de Foc,Огненный ключ,Огњени кључ,Yangın Anahtarı -Emerald Key,TXT_KEY_EMERALD,,,,Smaragdový klíč,Smaragdnøgle,Smaragdschlüssel,,Smerelda Ŝlosilo,Llave Esmeralda,,Smaragdiavain,Clé d'Emeraude,Smaragd Kulcs,Chiave di smeraldo,翠玉の鍵,에메랄드 열쇠,Smaragden Sleutel,Smaragdnøkkel,Szmaragdowy Klucz,Chave de Esmeralda,,Cheia din Smarald,Изумрудный ключ,Смарагдни кључ,Zümrüt Anahtar -Dungeon Key,TXT_KEY_DUNGEON,,,,Klíč od žaláře,Dungeon-nøgle,Kerkerschlüssel,,Karcer-Ŝlosilo,Llave del Calabozo,,Tyrmän avain,Clé du Donjon,Várbörtön Kulcs,Chiave del sotterraneo,迷宮の鍵,지하감옥 열쇠,Kerkersleutel,Dungeon-nøkkel,Klucz do Lochu,Chave da Masmorra,,Cheia Temniței,Ключ от подземелья,Кључ од лагума,Zindan Anahtarı -Silver Key,TXT_KEY_SILVER,,,,Stříbrný klíč,Sølvnøgle,Silberschlüssel,Ασυμένιο Κλειδί,Arĝenta Ŝlosilo,Llave de Plata,,Hopea-avain,Clé d'Argent,Ezüst Kulcs,Chiave d'argento,銀の鍵,은 열쇠,Zilveren Sleutel,Sølvnøkkel,Srebrny Klucz,Chave de Prata,,Cheia din Argint,Серебряный ключ,Сребрни кључ,Gümüş Anahtar -Rusted Key,TXT_KEY_RUSTED,,,,Zrezivělý klíč,Rustet nøgle,Rostiger Schlüssel,Σκουριασμένο Κλειδί,Rusta Ŝlosilo,Llave Oxidada,,Ruosteinen avain,Clé Rouillée,Rozsdás Kulcs,Chiave arrugginita,錆びた鍵,녹슨 열쇠,Geroeste Sleutel,Rustet nøkkel,Zardzewiały Klucz,Chave Enferrujada,,Cheia Ruginită,Ржавый ключ,Зарђали кључ,Paslı Anahtar -Horn Key,TXT_KEY_HORN,,,,Parožní klíč,Hornnøgle,Hornschlüssel,,Hup-Ŝlosilo,Llave de Cuerno,,Sarviavain,Clé Corne,Szarv Kulcs,Chiave del corno,角の鍵,뿔 열쇠,Hoornsleutel,Horn-nøkkel,Rogowy Klucz,Chave do Chifre,,Cheia Corn,Роговой ключ,Рогати кључ,Korna Anahtarı -Swamp Key,TXT_KEY_SWAMP,,,,Klíč od bažiny,Sumpnøgle,Sumpfschlüssel,,Marĉo-Ŝlosilo,Llave del Pantano,,Suoavain,Clé des Marécages,Mocsár Kulcs,Chiave della palude,沼の鍵,늪지대 열쇠,Moerassleutel,Sumpnøkkel,Bagienny Klucz,Chave do Pântano,,Cheia Mlaștinii,Болотный ключ,Мочварни кључ,Bataklık Anahtarı -Castle Key,TXT_KEY_CASTLE,,,,Klíč od hradu,Slotsnøgle,Burgschlüssel,,Kastel-Ŝlosilo,Llave del Castillo,,Linnan avain,Clé du Château,Kastély Kulcs,Chiave del castello,城の鍵,성 열쇠,Kasteelsleutel,Slottsnøkkel,Klucz do Zamku,Chave do Castelo,,Cheia Castelului,Ключ от замка,Кључ од замка,Kale Anahtarı -Icon of the Defender,TXT_ARTIINVULNERABILITY2,,,,Obráncova ikona,Ikon af forsvareren,Ikone des Verteidigers,,Ikono de la Defendanto,Icono del Defensor,Ícono del Defensor,Puolustajan ikoni,Icône du Défenseur,Védelmező Ikonja,Icona del difensore,守護者の像,수호의 성상,Symbool van de Verdediger,Forsvarerens ikon,Ikona Obrońcy,Ícone do Defensor,,Imaginea Apărătorului,Символ защитника,Симбол браниоца,Savunucunun Simgesi -Dark Servant,TXT_ARTISUMMON,,,,Temný služebník,Mørk tjener,Dunkler Diener,,Malluma Servanto,Sirviente Oscuro,,Pimeä palvelija,Serviteur Noir,Árny Szolga,Servitore oscuro,闇の従者,어둠의 하인,Donkere Dienaar,Mørk tjener,Mroczny Sługa,Servo Negro,,Servitor Întunecat,Тёмный слуга,Мрачни слуга,Karanlık Hizmetkar -Porkalator,TXT_ARTIEGG2,,,,Vepřovitel,,,,Porkigilo,Porcinador,,Sikaannuttaja,Porcificateur,Ártányátok,Porchificatore,ポークレイター,돈육기,,,Schabowator,Porquificador,,Porcolator,Свиновизатор,Свињатор,Porkalator -Flechette,TXT_ARTIPOISONBAG,,,,Střelka,,,,Flakono,Flechette,,,Fléchette,Flakon,Fiaschetta,フレチェット,플레셰트,,,Flaszka,,,Flacon,Флешетта,Бочица,Flechette -Banishment Device,TXT_ARTITELEPORTOTHER,,,,Vyhošťovač,Forvisningsanordning,Verbannungsgerät,,Forpelilo,Dispositivo de Desvanecimiento,,Häivytyskoje,Outil de Banissement,Száműző,Artifatto dell'esilio,追放のデバイス,소멸 장치,Verbanningsapparaat,Forvisningsanordning,Urządzenie Wygnania ,Dispositivo do Banimento,,Dispozitiv al Alungării,Устройство изгнания,Амблем прогањања,Sürgün Cihazı -Boots of Speed,TXT_ARTISPEED,,,,Běhuté boty,Støvler af hastighed,Turbo-Stiefel,,Botoj de Rapideco,Botas de Velocidad,,Ripeyssaappaat,Bottes de Célérité,Sebesség Cipője,Stivali della velocità,素早さの靴,속도의 신발,Snelheidslaarzen,Støvler av fart,Buty Szybkości,Botas da Velocidade,,Bocancii Vitezei,Сапоги-скороходы,Брзинске чизме,Hız Çizmeleri -Krater of Might,TXT_ARTIBOOSTMANA,,,,Kalich síly,Krater of Might,Kelch der Macht,,Kratero de Potenco,Vasija de Fuerza,,Mahtikrateeri,Cratère de Pouvoir,Hatalom Krátere,Calice della forza,魔力の盃,힘의 향로,Beker van Macht,Krater av makt,Czara mocy,Cálice do Poder,,Pocal al Puterii,Чаша могущества,Чаша силе,Kudret Krateri -Dragonskin Bracers,TXT_ARTIBOOSTARMOR,,,,Dračí nátepníky,Drageskindsarmbøjler,Drachenhaut-Armschutz,,Brakbendo el Drakhaŭto,Brazaletes de piel de Dragón,,Lohikäärmeennahkarannesuojat,Bracelets en Peau de Dragon,Sárkánybőr Karkötők,Bracciali in pelle di drago,竜皮の小手,용가죽 팔찌,Drakenhuidbescherming,Dragehud-bindinger,Karwasze ze Smoczej Skóry,Braçadeiras de Pele de Dragão,,Brățări din Piele de Dragon,Наручи из драконьей кожи,Наруквице од змајеве коже,Ejderha Derisi Bilezikler -Disc of Repulsion,TXT_ARTIBLASTRADIUS,,,,Kotouč odpuzení,Skive af frastødning,Rückstoßscheibe,,Disko de Repelado,Disco de Repulsión,,Karkotuskiekko,Disque de Répulsion,Visszaverés Lemeze,Disco della repulsione,反発の円盤,방탄의 원반,Schijf van Afstoting,Frastøtelsesskive,Dysk Odpychania,Disco da Repulsão,,Disc al Repulsiei,Диск отторжения,Диск одбијања,İtme Diski -Mystic Ambit Incant,TXT_ARTIHEALINGRADIUS,,,,Tajemný čár koljdoucí,Mystic Ambit Incant,Verbannungsgerät,,Sorĉo de Mistika Sfero,Encanto de Ámbito Místico,,Mystisen piirin loitsu,Incantation Mystique,Misztikus Mágialista,Confine mistico,魅知国の秘法,신비 영역의 주문,,Mystic Ambit-besvergelse,Inkantancja Mistycznego Kręgu,Encanto Místico,,Pergament Mistic,Чары магического единства,Чаролија магичног јединства,Mistik Ambit Büyüsü -Yorick's Skull,TXT_ARTIPUZZSKULL,,,,Jorikova lebka,Yoricks kranium,Yoricks Schädel,,Kranio de Yorick,Calavera de Yorick,,Yorickin kallo,Crâne de Yorick,Yorick Koponyája,Teschio di Yorick,ヨリックの髑髏,요릭의 두개골,Yorick's Schedel,Yoricks hodeskalle,Czaszka Yoricka,Caveira de Yorick,,Craniul lui Yorick,Череп Йорика,Јорикова лобања,Yorick'in Kafatası -Heart of D'sparil,TXT_ARTIPUZZGEMBIG,,,,Srdce D'Sparila,D'sparils hjerte,D'Sparils Herz,,Koro de D'sparil,Corazón de D'Sparil,,D'Sparilin sydän,Cœur de D'Sparil,D'Sparil szíve,Cuore di d'sparil,デ'スパリルの心,드'스파릴의 심장,Hart van D'sparil,D'Sparils hjerte,Serce D'Sparila,Coração de D'Sparil,,Inima lui D'Sparil,Сердце Д'Спарила,Д'Спарилино срце,D'sparil'in Kalbi -Ruby Planet,TXT_ARTIPUZZGEMRED,,,,Rubínová planeta,Rubinplanet,Rubinplanet,,Rubena Planedo,Planeta Rubí,,Rubiiniplaneetta,Planète de Rubis,Rubin Bolygó,Pianeta di rubino,ルビーの宝石,루비 행성석,Robijnrode Planeet,Rubinplaneten,Rubinowa Planeta,Planeta Rubi,,Planetă din Rubin,Рубиновая планета,Планета рубина,Yakut Gezegeni -Emerald Planet,TXT_ARTIPUZZGEMGREEN1,,,,Smaragdová planeta,Smaragdplanet,Smaragdplanet,,Smeralda Planedo,Planeta Esmeralda,,Smaragdiplaneetta,Planète d'Emeraude,Smaragd Bolygó,Pianeta di smeraldo,エメラルドの宝石,에메랄드 행성석 (1),Smaragdgroene Planeet,Smaragdplaneten,Szmaragdowa Planeta,Planeta Esmeralda,,Planetă din Smarald,Изумрудная планета,Смарагдна планета,Zümrüt Gezegen -Emerald Planet,TXT_ARTIPUZZGEMGREEN2,,,,Smaragdová planeta,Smaragdplanet,Smaragdplanet,,Smeralda Planedo,Planeta Esmeralda,,Smaragdiplaneetta,Planète de Saphir,Smaragd Bolygó,Pianeta di smeraldo,エメラルドの宝石,에메랄드 행성석 (2),Smaragdgroene Planeet,Smaragdplaneten,Szmaragdowa Planeta,Planeta Esmeralda,,Planetă din Smarald,Изумрудная планета,Смарагдна планета,Zümrüt Gezegen -Sapphire Planet,TXT_ARTIPUZZGEMBLUE1,,,,Safírová planeta,Safirplanet,Saphirplanet,,Safira Planedo,Planeta Zafiro,,Safiiriplaneetta,Planète de Saphir,Zafír Bolygó,Pianeta di zaffiro,サファイアの宝石,사파이어 행성석 (1),Saffierblauwe Planeet,Safirplaneten,Szafirowa Planeta,Planeta Safira,,Planetă din Safir,Сапфировая планета,Сафирна планета,Safir Gezegen -Sapphire Planet,TXT_ARTIPUZZGEMBLUE2,,,,Safírová planeta,Safirplanet,Saphirplanet,,Safira Planedo,Planeta Zafiro,,Safiiriplaneetta,Planète de Saphir,Zafír Bolygó,Pianeta di zaffiro,サファイアの宝石,사파이어 행성석 (2),Saffierblauwe Planeet,Safirplaneten,Szafirowa Planeta,Planeta Safira,,Planetă din Safir,Сапфировая планета,Сафирна планета,Safir Gezegen -Daemon Codex,TXT_ARTIPUZZBOOK1,,,,,,,,Kodekso de Demono,Códice del Demonio,,Daemon-koodeksi,Codex Démoniaque,Démon Kódex,Codice Demoniaco ,デーモンの写本,악마의 고문서,,,Demoniczny Kodeks,Códice Demoníaco,,Codexul Demonilor,Демонический кодекс,Демонски кодекс, -Liber Oscura,TXT_ARTIPUZZBOOK2,,,,,,,,Liber Oscura,Liber Oscura,,,,,,オスキュラ公文書,어둠의 자유서,,,Liber Oscura,,,,Либер Оскура,Либер Оскура, -Flame Mask,TXT_ARTIPUZZSKULL2,,,,Plamenná maska,Flammemaske,Flammenmaske,,Flamomasko,Máscara de llamas,,Liekkinaamio,Masque de Flammes,Láng Maszk,Maschera delle fiamme,炎の仮面,화염의 가면,Vuurmasker,Flammemaske,Maska Płomieni,Máscara das Chamas,,Mască de Foc,Маска пламени,Маска пламена,Alev Maskesi -Glaive Seal,TXT_ARTIPUZZFWEAPON,,,,Glévská pečeť,Glasur-segl,Schwetsiegel,,Sigelo de Glavo,Sello de Espada,,Miekkasinetti,Sceau du Glaive,Pallos Pecsét,Sigillo della brando,グレイブシール,밀폐된 칼날,Lanszegel,Glaive segl,Pieczęć Glewii,Selo do Gládio,,Sigiliu Spadă,Печать воителя,Војников печат,Glaive Mühür -Holy Relic,TXT_ARTIPUZZCWEAPON,,,,Svatá relikvie,Hellig relikvie,Heiliges Relikt,,Sankta Relikvo,Santa Reliquia,,Pyhä reliikki,Relique Sacrée,Szent Ereklye,Reliquia sacra,聖遺物,신성한 유물,Heilige Relikwie,Hellig relikvie,Święta Relikwia,Relíquia Sagrada,,Relicvă Sfântă,Святая реликвия,Света реликвија,Kutsal Emanet -Sigil of the Magus,TXT_ARTIPUZZMWEAPON,,,,Mágovo sigilium,Magus' segl,Symbol des Magiers,,Sigelo de la Mago,Emblema del Mago,,Taikurin sinetti,Sceau du Mage,Mágus Pecsétje,Suggello del magus,メイガスの印章,마거스의 인장,Sigaar van de Magus,Magusens segl,Emblemat Maga,Sigilo do Mago,,Sigiliul Magului,Печать Мага,Чаробњаков симбол,Büyücünün Sigil'i -Clock Gear,TXT_ARTIPUZZGEAR,,,,Ozubené kolečko,Urværk,Zahnrad,,Dentrado de Horloĝo,Engranaje de reloj,,Kellonratas,Rouage d'Horloge,Óra Szerkezet,Ingranaggio d'orologio,時計の歯車,시계 톱니바퀴,Kloktandwiel,Klokkeutstyr,Mechanizm Zegara,Engrenagem de Relógio,,Mecanism Ceas,Часовая шестерня,Сатни зупчаник,Saat Dişlisi -You Cannot Use This Here,TXT_USEPUZZLEFAILED,,,,Zde se tento předmět použít nedá,Du kan ikke bruge dette her,Das kannst du hier nicht benutzen,,Vi ne povas uzi ĉi tion ĉi tie.,No puedes usar esto aquí,,Et voi käyttää tätä tässä,Vous ne pouvez pas utiliser cela ici.,Ezt Itt Nem Használhatod,Non puoi usare questo oggetto qui,ここでは使用できない,이것은 여기에 사용할 수 없다,Dat kan je hier niet gebruiken,Du kan ikke bruke dette her,Nie możesz użyć tego tutaj,Você não pode usar isso aqui,Não podes usar isto aqui,Nu Poți Folosi Asta Aici,Здесь это невозможно использовать,Ово се не може користити овде,Bunu Burada Kullanamazsınız -Mesh Armor,TXT_ARMOR1,,,Mesh Armour,Kroužkové brnění,Mesh Armor,Kettenrüstung,,Marŝkiraso,Armadura de Malla,,Rengashaarniska,Armure de Mailles,Háló Páncél,Maglia metallica,鎖帷子,사슬 갑옷,Maliënkolder,Nettrustning,Kolczuga,Armadura de Malha,,Armură din Zale,Кольчуга,Верижњача,Örgü Zırh -Falcon Shield,TXT_ARMOR2,,,,Sokolí štít,Falke-skjold,Falkenschild,,Falko-Ŝildo,Escudo de Halcón,,Haukkakilpi,Bouclier du Faucon,Sólyom Pajzs,Scudo del falco,鷹の盾,팔콘 방패,Valkenschild,Falkeskjold,Sokola Tarcza,Escudo do Falcão,,Scut Șoim,Соколиный щит,Соколов штит,Falcon Kalkanı -Platinum Helmet,TXT_ARMOR3,,,,Platinová helma,Platin-hjelm,Platinhelm,,Platena Kasko,Casco de Platino,,Platinakypärä,Casque de Platine,Platina Sisak,Elmo di platino,白金の兜,백금 투구,Platina Helm,Platinahjelm,Platynowy Hełm,Capacete de Platina,,Coif de Platină,Платиновый шлем,Шлем од платине,Platin Kask -Amulet of Warding,TXT_ARMOR4,,,,Amulet uhýbání,Amulet af afværge,Wachamulett,,Amuleto de Gardado,Amuleto de Guarda,,Suojelusamuletti,Amulette de Protection,Oltalom Amulettje,Amuleto di protezione,回避の護符,수호의 부적,Amulet van Bescherming,Amulett av beskyttelse,Amulet Ochrony,Amuleto da Proteção,,Amuleta Protecției,Амулет стража,Амулет страже,Korunma Tılsımı -Timon's Axe,TXT_WEAPON_F2,,,,Timonova sekera,Timons økse,Timons Axt,,Hakilo de Timon,Hacha de Timón,,Timonin kirves,Hache de Timon,Timon Baltája,Ascia di timon,タイモンの斧,티몬의 도끼,Timon's Bijl,Timons øks,Topór Timona,Machado de Timon,,Toporul lui Timon,Топор Тимона,Тимонова секира,Timon'un Baltası -Hammer of Retribution,TXT_WEAPON_F3,,,,Kladivo odplaty,Gengældelsens hammer,Hammer der Rache,,Martelo de Repago,Martillo de Retribución,,Koston vasara,Marteau de la Rétribution,Kárhozat Kalapácsa,Martello del castigo,報復の金槌,징벌의 망치,Hamer der Vergelding,Gjengjeldelsens hammer,Młot Odkupienia,Martelo da Retribuição,,Ciocanul Salvării,Молот возмездия,Чекић одмазде,İntikam Çekici -Quietus Assembled,TXT_WEAPON_F4,,,,Složený Tišitel,Forløser samlet,Erlöser komplettiert,,Kvietus' Muntita,Quietus Ensamblado,,Quietus koottuna,Quietus Assemblée,Némusz Összerakva,Quietus assemblato,組み立てた 死滅の剣,완성된 종언의 검,Quietus in elkaar gezet,Quietus samlet,Złożony Uciszacz,Quietus Montada,,Argument Final Asamblat,Последний довод собран воедино,Самрт је сабрана,Quietus Birleştirildi -Serpent Staff,TXT_WEAPON_C2,,,,Hadí hůl,Slange-stav,Schlangenstab,,Serpentbastono,Vara de Serpiente,,Käärmesauva,Sceptre du Serpent,Kígyó Bot,Bastone del serpente,蛇の杖,뱀 지팡이,Slangenstaf,Slangestav,Laska Węży,Cetro da Serpente,,Bastonul Șarpelui,Змеиный посох,Змијски штап,Yılan Asa -Firestorm,TXT_WEAPON_C3,,,,Ohnivá bouře,Ildstorm,Feuersturm,,Fajroŝtormo,Tormenta de Fuego,,Tulimyrsky,Tempête de Feu,Tűzvihar,Tempesta di fuoco,ファイアストーム,화염폭풍,Vuurstorm,Ildstorm,Burza Ognia,Tempestade-de-Fogo,,Furtună de Foc,Огненный шторм,Огњена олуја,Ateş Fırtınası -Wraithverge Assembled,TXT_WEAPON_C4,,,,Složený Zjevitel,Spirit Bringer samlet,Geisterbringer komplettiert,,Fantomkruc' Muntita,Báculo Fantasmal Ensamblado,Vara Fantasmal Ensamblada,Haamusauva koottuna,Verge Phantasmale Assemblée,Bosszúbot Összerakva,Verga Sconfinaspettri assemblata,組み立てた レイスバージ,완성된 사령의 십자가,Schimroede in elkaar gezet,Wraithverge samlet,Złożony Widmoskraj,Cajado Fantasma Montado,,Toiag Stafie Asamblat,Жезл духов собран воедино,Жезло утвара је сабрано,Wraithverge Birleştirildi -Frost Shards,TXT_WEAPON_M2,,,,Ledové střepy,Frostskår,Frostsplitter,,Frostfragmentoj,Fragmentos de Escarcha,,Pakkassirpaleet,Eclats de Givre,Fagyos Szilánkok,Frantumi gelati,フロスト シャード,얼음 파편,Vorstscherven,Frostskår,Lodowe Odłamki,Fragmentos de Geada,,Cioburi de Gheață,Ледяные осколки,Ледене крхотине,Buz Kırıkları -Arc of Death,TXT_WEAPON_M3,,,,Jiskry smrti,Dødens bue,Todesblitz,,Arko de Morto,Arcos de la Muerte,,Kuolonkaari,Foudre Mortelle,Halál Boltíve,Arco della morte,死の円弧,죽음의 번갯불,Doodsboog,Dødens bue,Łuk Śmierci,Arcos da Morte,,Izvorul Morții,Дуга смерти,Лук смрти,Ölüm Arkı -Bloodscourge Assembled,TXT_WEAPON_M4,,,,Složený Krvehrom,Blodgisel samlet,Blutgeißel komplettiert,,Sangskurĝ' Muntita,Plaga Sangrienta ensamblada,,Veripiiska koottuna,Fléau Sanglant Assemblé,Vérkorbács Összerakva,Flagello di Sangue assemblato,組み立てた 天罰,완성된 피의 재앙,Bloedgesel in elkaar gezet,Bloodscourge samlet,Złożona Krwioplaga,Flagelo de Sangue Montado,,Flagel Sângeros Asamblat,Кровавый бич собран воедино,Крвави бич је сабран,Bloodscourge Birleştirildi -A weapon piece! This is your lucky day!,TXT_WEAPONPIECE,,,,Část zbraně! Dnes je tvůj šťastný den!,Et våbenstykke! Dette er din heldige dag!,Ein Waffensegment. Das ist dein Glückstag!,,Peco de armilo! Estas via bonŝanca tago!,¡Una pieza de un arma! ¡Es tu día de suerte!,,Aseen osa! Tämä on onnenpäiväsi!,Une pièce d'arme! C'est votre jour de chance!,Egy fegyver darab! Szerencés napod van!,Il frammento di un'arma! È il tuo giorno fortunato! ,武器の一片! 今日は吉日だ!,무기의 한 조각이다! 운수 좋은 날인 것 같다!,Een wapenstuk! Dit is je geluksdag!,En våpendel! Dette er lykkedagen din!,Część broni! To twój szczęśliwy dzień!,Um fragmento de arma! Esse é o seu dia de sorte!,Um fragmento de arma! Este é o teu dia de sorte!,O piesă din super armă! E ziua ta norocoasă!,Часть оружия! Сегодня ваш счастливый день!,Део оружја! Данас Вам је срећан дан!,Bir silah parçası! Bugün şanslı gününüz! -Segment of Quietus,TXT_QUIETUS_PIECE,,,,Část Tišitele,Segment af Forløseren,Segment des Erlösers,,Segmento de Kvietus',Segmento de Quietus,,Quietuksen osa,Segment de Quietus,Darab a Némuszból,Parte del Quietus,死滅の剣の切片,종언의 검 조각,Segment van Quietus,Segment av Quietus,Fragment Uciszacza,Segmento de Quietus,,Fragment din Argumentul Final,Часть последнего довода,Део Самрти,Quietus'un bir bölümü -Segment of Wraithverge,TXT_WRAITHVERGE_PIECE,,,,Část Zjevitele,Segment af Spirit Bringer,Segment des Geisterbringers,,Segmento de Fantomkruc',Segmento del Báculo Fantasmal,,Haamusauvan osa,Segment de la Verge Phantasmale,Darab a Bosszúbotból,Parte della Verga Sconfinaspettri,レイスバージの切片,사령의 십자가 조각,Segment van Schimroede,Segment av Wraithverge,Fragment Widmoskraju,Segmento do Cajado Fantasma,,Fragment din Toiagul Stafie,Часть жезла духов,Део Жезла утвара,Wraithverge'in Segmenti -Segment of Bloodscourge,TXT_BLOODSCOURGE_PIECE,,,,Část Krvehromu,Segment af Blodgiselen,Segment der Blutgeißel,,Segmento de Sangskurĝ',Segmento de la Plaga Sangrienta,,Veripiiskan osa,Segment du Fléau Sanglant,Darab a Vérkorbácsból,Parte del Flagello di Sangue,天罰の切片,피의 재앙 조각,Segment van Bloedgesel,Segment av Bloodscourge,Fragment Krwioplagi,Segmento do Flagelo de Sangue,,Fragment din Flagelul Sângeros,Часть кровавого бича,Део Крвавог бича,Bloodscourge'un Segmenti -,,Locks,,,,,,,,,,,,,,,,,,,,,,,, -You need the Steel Key,TXT_NEED_KEY_STEEL,,,,Potřebuješ ocelový klíč,Du skal bruge stålnøglen,Du brauchst den Stahlschlüssel,Χρειάζεσε το Ατσάλινο κλειδί.,Vi bezonas la Ŝtalan Ŝlosilon,Necesitas la Llave de Acero,,Tarvitset teräsavaimen,Vous avez besoin de la Clé d'Acier,Az Acél Kulcsra van szükséged,Ti serve la Chiave d'Acciaio,鋼の鍵が必要だ,강철 열쇠가 필요하다,Je hebt de Stalen Sleutel nodig.,Du trenger stålnøkkelen,Potrzebujesz Stalowego Klucza,Você precisa da Chave de Aço,Precisas da Chave de Aço,Ai nevoie de Cheia din Oțel,Нужен стальной ключ,За отварање је потребан челични кључ,Çelik Anahtara ihtiyacın var -You need the Cave Key,TXT_NEED_KEY_CAVE,,,,Potřebuješ klíč od jeskyně,Du skal bruge hulenøglen,Du brauchst den Höhlenschlüssel,,Vi bezonas la Kavern-Ŝlosilon,Necesitas la Llave de la Caverna,,Tarvitset luola-avaimen,Vous avez besoin de la Clé de la Cave,A Barlang Kulcsra van szükséged,Ti serve la Chiave della Caverna ,洞窟の鍵が必要だ,동굴 열쇠가 필요하다,Je hebt de Grotsleutel nodig.,Du trenger hulenøkkelen,Potrzebujesz Klucza do Jaskini,Você precisa da Chave da Caverna,Precisas da Chave da Caverna,Ai nevoie de Cheia Peșterii,Нужен пещерный ключ,За отварање је потребан пећински кључ,Mağara Anahtarına ihtiyacın var -You need the Axe Key,TXT_NEED_KEY_AXE,,,,Potřebuješ sekyrový klíč,Du skal bruge øksenøglen,Du brauchst den Axtschlüssel,,Vi bezonas la Hakil-Ŝlosilon,Necesitas la Llave de Hacha,,Tarvitset kirvesavaimen,Vous avez besoin de la Clé de la Hache,A Fejsze Kulcsra van szükséged,Ti serve la Chiave dell'Ascia,斧の鍵が必要だ,도끼 열쇠가 필요하다,Je hebt de Bijlsleutel nodig.,Du trenger øksenøkkelen,Potrzebujesz Klucza-Topora,Você precisa da Chave do Machado,Precisas da Chave do Machado,Ai nevoie de Cheia Topor,Нужен ключ-топор,За отварање је потребан кључ секира,Balta Anahtarına ihtiyacın var -You need the Fire Key,TXT_NEED_KEY_FIRE,,,,Potřebuješ ohnivý klíč,Du skal bruge brandnøglen,Du brauchst den Feuerschlüssel,,Vi bezonas la Fajro-Ŝlosilon,Necesitas la Llave de Fuego,,Tarvitset tuliavaimen,Vous avez besoin de la Clé du Feu,A Tűz Kulcsra van szükséged,Ti serve la Chiave del Fuoco ,炎の鍵が必要だ,불 열쇠가 필요하다,Je hebt de Vuursleutel nodig.,Du trenger Ildnøkkelen,Potrzebujesz Ognistego Klucza,Você precisa da Chave do Fogo,Precisas da Chave do Fogo,Ai nevoie de Cheia de Foc,Нужен огненный ключ,За отварање је потребан огњени кључ,Ateş Anahtarına ihtiyacın var -You need the Emerald Key,TXT_NEED_KEY_EMERALD,,,,Potřebuješ smaragdový klíč,Du skal bruge smaragdnøglen,Du brauchst den Smaragdschlüssel,,Vi bezonas la Smeraldan Ŝlosilon,Necesitas la Llave Esmeralda,,Tarvitset smaragdiavaimen,Vous avez besoin de la Clé d'Emeraude,A Smaragd Kulcsra van szükséged,Ti serve la Chiave di Smeraldo ,翠玉の鍵が必要だ,에메랄드 열쇠가 필요하다,Je hebt de Smaragden Sleutel nodig.,Du trenger smaragdnøkkelen,Potrzebujesz Szmaragdowego Klucza,Você precisa da Chave Esmeralda,Precisas da Chave Esmeralda,Ai nevoie de Cheia din Smarald,Нужен изумрудный ключ,За отварање је потребан смарагдни кључ,Zümrüt Anahtarı'na ihtiyacın var. -You need the Dungeon Key,TXT_NEED_KEY_DUNGEON,,,,Potřebuješ klíč od žaláře,Du skal bruge fangehulsnøglen,Du brauchst den Kerkerschlüssel,,Vi bezonas la Karcer-Ŝlosilon,Necesitas la Llave del Calabozo,,Tarvitset tyrmän avaimen,Vous avez besoin de la Clé du Donjon,A Várbörtön Kulcsra van szükséged,Ti serve la Chiave del Sotterraneo ,迷宮の鍵が必要だ,지하감옥 열쇠가 필요하다,Je hebt de Kerkersleutel nodig.,Du trenger fangehullsnøkkelen,Potrzebujesz Klucza do Lochu,Você precisa da Chave da Masmorra,Precisas da Chave das Masmorras,Ai nevoie de Cheia Temniței,Нужен ключ от подземелья,За отварање је потребан кључ од лагума,Zindan Anahtarına ihtiyacın var -You need the Silver Key,TXT_NEED_KEY_SILVER,,,,Potřebuješ stříbrný klíč,Du skal bruge sølvnøglen,Du brauchst den Silberschlüssel,Χρειάζεσε το Ασυμένιο κλειδί.,Vi bezonas la Arĝentan Ŝlosilon,Necesitas la Llave de Plata,,Tarvitset hopea-avaimen,Vous avez besoin de la Clé d'Argent,Az Ezüst Kulcsra van szükséged,Ti serve la Chiave d'Argento ,銀の鍵が必要だ,은 열쇠가 필요하다,Je hebt de Zilveren Sleutel nodig.,Du trenger sølvnøkkelen,Potrzebujesz Srebrnego Klucza,Você precisa da Chave de Prata,Precisas da Chave Prata,Ai nevoie de Cheia din Argint,Нужен серебряный ключ,За отварање је потребан сребрни кључ,Gümüş Anahtara ihtiyacın var -You need the Rusted Key,TXT_NEED_KEY_RUSTED,,,,Potřebuješ zrezivělý klíč,Du skal bruge den rustne nøgle,Du brauchst den rostigen Schlüssel,Χρειάζεσε το Σκουριασμένο κλειδί.,Vi bezonas la Rustan Ŝlosilon,Necesitas la Llave Oxidada,,Tarvitset ruosteisen avaimen,Vous avez besoin de la Clé Rouillée,A Rozsdás Kulcsra van szükséged,Ti serve la Chiave Arrugginita ,錆びた鍵が必要だ,녹슨 열쇠가 필요하다,Je hebt de Geroeste Sleutel nodig.,Du trenger den rustne nøkkelen,Potrzebujesz Zardzewiałego Klucza,Você precisa da Chave Enferrujada,Precisas da Chave Enferrujada,Ai nevoie de Cheia Ruginită,Нужен ржавый ключ,За отварање је потребан зарђали кључ,Paslı Anahtar'a ihtiyacın var. -You need the Horn Key,TXT_NEED_KEY_HORN,,,,Potřebuješ parožní klíč,Du skal bruge hornnøglen,Du brauchst den Hornschlüssel,,Vi bezonas la Hup-Ŝlosilon,Necesitas la Llave de Cuerno,,Tarvitset sarviavaimen,Vous avez besoin de la Clé Corne,A Szarv Kulcsra van szükséged,Ti serve la Chiave del Corno ,角の鍵が必要だ,뿔 열쇠가 필요하다,Je hebt de Hoornsleutel nodig.,Du trenger Horn-nøkkelen,Potrzebujesz Rogowego Klucza,Você precisa da Chave do Chifre,Precisas da Chave do Chifre,Ai nevoie de Cheia Corn,Нужен роговой ключ,За отварање је потребан рогати кључ,Korna Anahtarına ihtiyacınız var -You need the Swamp Key,TXT_NEED_KEY_SWAMP,,,,Potřebuješ klíč od bažiny,Du skal bruge sumpnøglen,Du brauchst den Sumpfschlüssel,,Vi bezonas la Marĉ-Ŝlosilon,Necesitas la Llave del Pantano,,Tarvitset suoavaimen,Vous avez besoin de la Clé des Marécages,A Mocsár Kulcsra van szükséged,Ti serve la Chiave della Palude ,沼の鍵が必要だ,늪지대 열쇠가 필요하다,Je hebt de Moerassleutel nodig.,Du trenger Sump-nøkkelen,Potrzebujesz Bagiennego Klucza,Você precisa da Chave do Pântano,Precisas da Chave do Pântano,Ai nevoie de Cheia Mlaștinii,Нужен болотный ключ,За отварање је потребан мочварни кључ,Bataklık Anahtarına ihtiyacın var. -You need the Castle Key,TXT_NEED_KEY_CASTLE,,,,Potřebuješ klíč od hradu,Du skal bruge slotsnøglen,Du brauchst den Burgschlüssel,,Vi bezonas la Kastel-Ŝlosilon,Necesitas la Llave del Castillo,,Tarvitset linnan avaimen,Vous avez besoin de la Clé du Château,A Kastély Kulcsra van szükséged,Ti serve la Chiave del Castello ,城の鍵が必要だ,성 열쇠가 필요하다,Je hebt de Kasteelsleutel nodig.,Du trenger slottsnøkkelen,Potrzebujesz Klucza do Zamku,Você precisa da Chave do Castelo,Precisas da Chave do Castelo,Ai nevoie de Cheia Castelului,Нужен ключ от замка,За отварање је потребан кључ од замка,Kale Anahtarına ihtiyacın var -,,Actor tag names,,,,,,,,,,,,,,,,,,,,,,,, -Afrit,FN_FIREDEMON,,,,,,,,Afrito,,,,,,Afrit,アフリート,아프리트,Afriet,,Afrit,,,Demon de Foc,Африт,Африт,Afrit -Serpent,FN_DEMON1,,,,Zlohad,Slange,Chaos-Schlange,,Serpento,Serpiente,,Käärme,,Kígyó,Serpente del Caos,サーペント,서펜트,Slang,Slangen,Wąż,Serpente,,Șarpe,Змей,Серпент,Yılan -Ettin,FN_ETTIN,,,,Skřet,,,,Gigantaĉo,,,,,,Ettin,エティン,에틴,,,Ettin,,,Etin,Эттин,Етин,Ettin -Centaur,FN_CENTAUR,,,,Kentaur,Kentaur,Zentaur,,Centaŭro,Centauro,,Kentauri,Centaure,Kentaur,Centauro,ケンタウロス,켄타우로스,Centaurus,Kentaur,Centaur,Centauro,,Centaur,Кентавр,Кентаур,Kentaur -Slaughtaur,FN_SLAUGHTAUR,,,,Ničitaur,Slagtaur,Schlachtaur,,Buĉataŭro,Masacratauro,,Teurastauri,Sangtaure,Vágtaur,Sventrauro,スロアタウル,슬로터로스,Slachttaurus,Slakttaur,Rzeziotaur,Chacinotauro,,Centaur Violent,Убитавр,Кентаур старешина,Katlaur -Bishop,FN_BISHOP,,,,Biskup,Biskop,Bischof,,Episkopo,Obispo,,Piispa,Evèque,Érsek,Vescovo,ビショップ,비숍,Bisschop,Biskop,Biskup,Bispo,,Episcop,Епископ,Епископ,Piskopos -Wendigo,FN_ICEGUY,,,,,,,,Vendiko,,,,,,Wendigo,ウェンディゴ,윈디고,,,Wendigo,,,Vendigo,Вендиго,Вендиго,Wendigo -Stalker,FN_SERPENT,,,,Slídil,,Wasserjäger,,Gvatanto,Acechador,,Vaanija,Chasseur,Orvhalász,Cacciatore,ストーカー,스토커,,,Prześladowca,Caçador,,Vânător,Преследователь,Вребач,Stalker -Reiver,FN_WRAITH,,,,Přízrak,,Phantom,,Fantomo,Saqueador,,Ryöväri,,Martalóc,Incursore,レイバー,리버,Rover,,Rozbójnik,Fantasma,,Pungaș,Грабитель,Грабљивац,Hayalet -Death Wyvern,FN_DRAGON,,,,Smrtidrak,Døden Wyvern,Todesdrache,,Morta viverno,Guiverno de la muerte,,Kuolontraakki,Vouivre de la Mort,A Halál Sárkánya,Viverna Mortale,デス ワイバーン,데스 와이번,Doodsdraak,Døden Wyvern,Wiwerna Śmierci,Serpe da Morte,,Balaur al Morții,Виверна смерти,Змајак смрти,Ölüm Wyvern -Korax,FN_KORAX,,,,,,,,Korax,,,Kooraks,,,Korax,唯一神コラックス,코락스,,,Korax,Korax,,,Коракс,Коракс, -Zedek,FN_FBOSS,,,,,,,,Zedeko,,,Sedek,,,Zedek,ゼデク,제닥,,,Zedek,Zedek,,,Зедек,Зедек, -Menelkir,FN_MBOSS,,,,,,,,Menelkiro,,,Menelkir,,,Menelkir,メネルキル,메넬키어,,,Menelkir,Menelkir,,,Менелкир,Менелкир, -Traductus,FN_CBOSS,,,,Traduktus,,,,Traduktuso,,,Traduktus,,Traduktusz,Traductus,トラダクタス,트라닥투스,,,Traductus,Traductus,,,Традуктус,Традуктус, -Heresiarch,FN_HERESIARCH,,,,Arcikacíř,Heresiark,Erzketzer,,Ĉefherezulo,Heresiarca,,Kerettiarkki,L'Hérésiarche,Főeretnek,Eresiarca,ヘレシアーク,헤러시아크,,Heresiark,Herezjarcha,Heresiarca,,Ereziarh,Ересиарх,Јересијарх,Heresiark -Blue Mana,AMMO_MANA1,,,,Modrá mana,Blå Mana,Blaues Mana,,Blua Manao,Maná azul,,Sininen mana,Mana Bleu,Kék Mana,Mana blu,ブルーマナ,청색 마나,Blauwe Mana,Blå Mana,Niebieska Mana,Mana Azul,,Mană Albastră,Синяя мана,Плава мана,Mavi Mana -Green Mana,AMMO_MANA2,,,,Zelená mana,Grøn Mana,Grünes Mana,,Verda Manao,Maná verde,,Vihreä mana,Mana Vert,Zöld Mana,Mana verde,グリーンマナ,녹색 마나,Groene Mana,Grønn Mana,Zielona Mana,Mana Verde,,Mană Verde,Зелёная мана,Зелена мана,Yeşil Mana -Mace of Contrition,TAG_CWEAPMACE,,,,Palcát kajícnosti,Stridskølle af anger,Streitkolben,,Klabo de Penteco,Maza de Contrición,,Katumuksen nuija,Masse de Pénitence,Bűnbánat Buzogánya,Mazza del Pentimento,懺悔のメイス,참회의 철퇴,Knots van Wroeging,Mace of Contrition,Buzdygan Skruchy,Maça da Contrição,,Buzduganul Remușcării,Булава раскаяния,Буздован покајања,Pişmanlık Topuzu -Serpent Staff,TAG_CWEAPSTAFF,,,,Hadí hůl,Slange-stav,Schlangenstab,,Serpentbastono,Bastón de Serpiente,,Käärmesauva,Sceptre du Serpent,Kígyó Bot,Staffa del Serpente ,蛇の杖,뱀 지팡이,Slangenstaf,Slangestav,Laska Węży,Cetro da Serpente,,Bastonul Șarpelui,Змеиный посох,Змијски штап,Yılan Asa -Firestorm,TAG_CWEAPFLAME,,,,Ohnivá bouře,Ildstorm,Feuersturm,,Fajrŝtormo,Tormenta de Fuego,,Tulimyrsky,Tempête de Feu,Tűzvihar,Tempesta di Fuoco ,ファイアストーム,화염폭풍,Vuurstorm,Ildstorm,Burza Ognia,Tempestade-de-fogo,,Furtună de Foc,Огненный шторм,Огњена олуја,Ateş Fırtınası -Wraithverge,TAG_CWEAPWRAITHVERGE,,,,Zjevitel,Spirit Bringer,Geisterbringer,,Fantomkruc',Báculo Fantasmal,,Haamusauva,Verge Phantasmale,Lidércvég,Verga SconfinaSpettri,レイスバージ,사령의 십자가,Schimroede,Wraithverge,Widmoskraj,Cajado Fantasma,,Toiag Stafie,Жезл духов,Жезло утвара,Wraithverge -Spiked Gauntlets,TAG_FWEAPFIST,,,,Ohrocené rukavice,Spidse handsker,Stachelhandschuhe,,Pintaj Fergantoj,Guanteletes Puntiagudos,,Piikkirautakintaat,Gantelets à Pointes,Tűskés Páncélkesztyűk,Guantoni Spinati,スパイク ガントレット,가시 장갑,Spijkerhandschoenen,Pigghansker,Kolczaste Rękawice,Manoplas Espinhadas,,Mănuși cu Țepi,Шипастые перчатки,Бодљикаве рукавице,Çivili Eldivenler -Timon's Axe,TAG_FWEAPAXE,,,,Timonova sekera,Timons økse,Timons Axt,,Hakilo de Timon,Hacha de Timón,,Timonin kirves,Hache de Timon,Timon Baltája,Ascia di Timon,タイモンの斧,티몬의 도끼,Timon's Bijl,Timons øks,Topór Timona,Machado de Timon,,Toporul lui Timon,Топор Тимона,Тимонова секира,Timon'un Baltası -Hammer of Retribution,TAG_FWEAPHAMMER,,,,Kladivo odplaty,Hævnens hammer,Hammer der Rache,,Martelo de Repago,Martillo de Retribución,,Koston vasara,Marteau de la Rétribution,Kárhozat Kalapácsa,Martello del Castigo,報復の金槌,징벌의 망치,Hamer van Vergelding,Gjengjeldelsens hammer,Młot Odkupienia,Martelo da Retribuição,,Ciocanul Salvării,Молот возмездия,Чекић одмазде,İntikam Çekici -Quietus,TAG_FWEAPQUIETUS,,,,Tišitel,Forløser,Erlöser,,Kvietus',,,,Quietus,Némusz,Quietus,死滅の剣,종언의 검,,Quietus,Uciszacz,Quietus,,Argument Final,Последний довод,Самрт,Quietus -Sapphire Wand,TAG_MWEAPWAND,,,,Safírová hůl,Safir-stav,Saphirstab,,Safirsorĉbastono,Varita de Zafiro,,Safiirisauva,Baguette de Saphir,Zafír Pálca,Scettro di Zaffiro ,サファイア ワンド,사파이어 지팡이,Saffieren Toverstok,Safirstaven,Szafirowa Różdżka,Cetro de Safira,,Toiag cu Safir,Сапфировая волшебная палочка,Сафирни штап,Safir Değnek -Frost Shards,TAG_MWEAPFROST,,,,Ledové střepy,Frostskår,Frostsplitter,,Frostfragmentoj,Fragmentos de Escarcha,,Pakkassirpaleet,Eclats de Givre,Fagyos Szilánkok,Schegge di Ghiaccio ,フロスト シャード,얼음 파편,Vorstscherven,Frostskår,Lodowe Odłamki,Fragmentos de Geada,,Cioburi de Gheață,Замораживающие осколки,Ледене крхотине,Buz Kırıkları -Arcs of Death,TAG_MWEAPLIGHTNING,,,,Jiskry smrti,Dødens buer,Todesblitz,,Arkoj de Morto,Arcos de la Muerte,,Kuolonkaaret,Foudre Mortelle,Halál Boltíve,Archi della Morte ,死の円弧,죽음의 번갯불,Doodsboog,Dødens buer,Łuki Śmierci,Arcos da Morte,,Izvoarele Morții,Дуга смерти,Лук смрти,Ölüm Yayları -Bloodscourge,TAG_MWEAPBLOODSCOURGE,,,,Krvehrom,Blodgisel,Blutgeißel,,Sangskurĝ',Plaga Sangrienta,,Veripiiska,Fléau Sanglant,Vérkorbács,Flagello di Sangue,天罰,피의 재앙,Bloedgesel,Bloodscourge,Krwioplaga,Flagelo de Sangue,,Flagel Sângeros,Кровавый бич,Крвави бич,Bloodscourge -Disc of Repulsion,TAG_ARTIBLASTRADIUS,,,,Kotouč odpuzení,Afstødningsskive,Rückstoßscheibe,,Disko de Repelado,Disco de Repulsión,,Karkotuskiekko,Disque de Répulsion,Visszaverő Pajzs,Disco della Repulsione ,反発の円盤,방탄의 원반,Schijf van Afstoting,Frastøtelsens skive,Dysk Odpychania,Disco da Repulsão,,Disc al Repulsiei,Диск отторжения,Диск одбијања,İtme Diski -Dragonskin Bracers,TAG_ARTIBOOSTARMOR,,,,Dračí nátepníky,Drageskindsarmbøjler,Drachenhaut-Armschutz,,Brakbendo el Drakhaŭto,Brazaletes de piel de Dragón,,Lohikäärmeennahkarannesuojat,Brassards en peau de Dragon,Sárkánybőr Karkötők,Bracciali in Pelle di Drago ,竜皮の小手,용가죽 팔찌,Drakenhuidbescherming,Dragehud-bindinger,Karwasze ze Smoczej Skóry,Braçadeiras de Pele de Dragão,,Brățări din Piele de Dragon,Наручи драконьей кожи,Наруквице од змајеве коже,Ejderha Derisi Bilezikler -Krater of Might,TAG_ARTIBOOSTMANA,,,,Kalich síly,Kraftens bæger,Kelch der Macht,,Kratero de Potenco,Crátera de Poder,,Mahtikrateeri,Cratère de Pouvoir,Hatalom Kráterje,Calice della Forza,魔力の盃,힘의 향로,Beker van Macht,Krater av makt,Czara mocy,Cálice do Poder,,Pocal al Puterii,Кубок могущества,Чаша силе,Kudret Krateri -Flechette,TAG_ARTIPOISONBAG,,,,Střelka,,,,Flakono,,,,Fléchette,Nyílhegy,Fiaschetta ,フレシェット,플레셰트,,,Flaszka,,,Flacon,Флешетта,Бочица,Flechette -Poison Cloud Flechette,TAG_ARTIPOISONBAG1,,,,Otrávená střelka,Flechette (giftig sky),Flechette (Giftwolke),,Venennub-Flakono,Flechette de Nube Venenosa,,Myrkkypilviflechette,Fléchette - Nuage Toxique,Méregfelhő hegy,Fiaschetta Velenosa,毒ガス フレシェット,독구름 플레셰트,Flechette (giftige wolk),Giftsky-flechette,Flaszka Trującej Chmury,Flechette de Nuvem Venenosa,,Flacon cu Otravă,Флешетта ядовитого облака,Бочица отровног облака,Zehirli Bulut Flechette -Timebomb Flechette,TAG_ARTIPOISONBAG2,,,,Časovaná střelka,Flechette (tidsbombe),Flechette (Zeitbombe),,Horloĝbomb-Flakono ,Bomba de Tiempo Flechette,,Aikapommiflechette,Fléchette - Bombe a Retardement,Időbomba hegy,Fiaschetta a Tempo ,時限爆弾フレシェット,시한폭탄 플레셰트,Flechette (tijdbom),Tidsbombe Flechette,Flaszka-Bomba Zegarowa,Flechette Bomba-Relógio,,Bombă cu Ceas,Флешетта часовой бомбы,Бочица временске бомбе,Saatli bomba Flechette -Grenade Flechette,TAG_ARTIPOISONBAG3,,,,Granátová střelka,Flechette (granat),Flechettre (Granate),,Grenad-Flakono,Granada Flechette,,Kranaattiflechette,Fléchette - Grenade,Robbanó hegy,Fiaschetta da Lancio,グレネードフレシェット,폭발성 플레셰트,Flechette (granaat),Granat Flechette,Flaszka-Granat,Flechette Granada,,Flacon-Grenadă,Гранатная флешетта ,Бочица граната,El Bombası Flechette -Mystic Ambit Incant,TAG_ARTIHEALINGRADIUS,,,,Tajemný čár koljdoucí,,,,Sorĉo de Mistika Sfero,Encantamiento de Ámbito Místico,,Mystisen piirin loitsu,Incantation Mystique,Misztikus Mágialista,Incantamento Mistico ,魅知国の秘法,신비 영역의 주문,,,Inkantancja Mistycznego Kręgu,Encantamento Místico,,Pergament Mistic,Мистический зачарованный свиток,Чаролија магичног јединства,Mistik Ambit Büyüsü -Icon of the Defender,TAG_ARTIDEFENDER,,,,Obráncova ikona,Ikon af forsvareren,Ikone des Verteidigers,,Ikono de la Defendanto,Icono del Defensor,Ícono del Defensor,Puolustajan ikoni,Icône du Défenseur,Védelmező Ikonja,Emblema del Difensore ,守護者の像,수호의 성상,,Forsvarerens ikon,Ikona Obrońcy,Ícone do Defensor,,Imaginea Apărătorului,Символ защитника,Симбол браниоца,Savunucunun Simgesi -Porkalator,TAG_ARTIPORK,,,,Vepřovitel,,Porkalator,,Porkigilo,Porcinador,,Sikaannuttaja,Porcificateur,Ártányátok,Porchificatore,ポークレイター,돈육기,,,Schabowator,Porquificador,,Porcolator,Свиновизатор,Свињатор,Porkalator -Boots of Speed,TAG_ARTISPEED,,,,Běhuté boty,Støvler af hastighed,Turbo-Stiefel,,Botoj de Rapideco,Botas de Velocidad,,Ripeyssaappaat,Bottes de Célérité,Sebesség Cipői,Stivali della Fretta,素早さの靴,속도의 부츠,Snelheidslaarzen,Støvler av fart,Buty Szybkości,Botas da Rapidez,,Bocancii Vitezei,Сапоги-скороходы,Брзинске чизме,Hız Çizmeleri -Dark Servant,TAG_ARTISUMMON,,,,Temný služebník,Mørk tjener,Dunkler Diener,,Malluma Servanto,Servidor Oscuro,,Pimeä palvelija,Serviteur Noir,Árny Szolga,Servo Oscuro,闇の従者,어둠의 하인,Donkere Dienaar,Mørk tjener,Mroczny Sługa,Servo Negro,,Servitor Întunecat,Тёмный слуга,Мрачни слуга,Karanlık Hizmetkar -Banishment Device,TAG_ARTITELEPORTOTHER,,,,Vyhošťovač,Forvisningsanordning,Verbannungsgerät,,Forpelilo,Dispositivo de Destierro,,Häivytyskoje,Outil de Banissement,Számüzető Szerkentyű,Congegno dell'Esilio,追放のデバイス,소멸 장치,Verbanningsapparaat,Forvisningsinnretning,Urządzenie Wygnania ,Dispositivo do Banimento,,Dispozitiv al Alungării,Механизм изгнания,Амблем прогањања,Sürgün Cihazı -Yorick's Skull,TAG_ARTIPUZZSKULL,,,,Jorikova lebka,Yoricks kranium,Yoricks Schädel,,Kranio de Yorick,Calavera de Yorick,Cráneo de Yorick,Yorickin kallo,Crâne de Yorick,Yorick Koponyája,Teschio di Yorick,ヨリックの髑髏,요릭의 두개골,Yorick's Schedel,Yoricks hodeskalle,Czaszka Yoricka,Crânio de Yorick,,Craniul lui Yorick,Череп Йорика,Јорикова лобања,Yorick'in Kafatası -Heart of D'Sparil,TAG_ARTIPUZZGEMBIG,,,,Srdce D'Sparila,D'Sparils hjerte,D'Sparils Herz,,Koro de D'Sparil,Corazón de D'Sparil,,D'Sparilin sydän,Cœur de D'Sparil,D'Sparil Szíve,Cuore di D'Sparil,デ'スパリルの心,드'스파릴의 심장,Hart van D'Sparil,D'Sparils hjerte,Serce D'Sparila,Coração de D'Sparil,,Inima lui D'Sparil,Сердце Д'Спарила,Д'Спарилово срце,D'Sparil'in Kalbi -Ruby Planet,TAG_ARTIPUZZGEMRED,,,,Rubínová planeta,Rubinplanet,Rubinplanet,,Rubena Planedo,Planeta Rubí,,Rubiiniplaneetta,Planète en rubis,Rubin Bolygó,Pianeta di Rubino,ルビーの宝石,루비 행성석,Robijnrode Planeet,Rubinplaneten,Rubinowa Planeta,Planeta Rubi,,Planetă din Rubin,Рубиновая планета,Планета рубина,Yakut Gezegeni -Emerald Planet (1),TAG_ARTIPUZZGEMGREEN1,,,,Smaragdová planeta (1),Smaragdplanet (1),Smaragdplanet (1),,Smeralda Planedo (1),Planeta Esmeralda (1),,Smaragdiplaneetta (1),Planète en émeraude (1),Smaragd Bolygó (1),Pianeta di Smeraldo (1),エメラルドの宝石1,에메랄드 행성석 (1),Smaragdgroene Planeet (1),Smaragdplaneten (1),Szmaragdowa Planeta (1),Planeta Esmeralda (1),,Planetă din Smarald (1),Изумрудная планета (1),Смарагдна планета (1),Zümrüt Gezegen (1) -Emerald Planet (2),TAG_ARTIPUZZGEMGREEN2,,,,Smaragdová planeta (2),Smaragdplanet (2),Smaragdplanet (2),,Smeralda Planedo (2),Planeta Esmeralda (2),,Smaragdiplaneetta (2),Planète en émeraude (2),Smaragd Bolygó (2),Pianeta di Smeraldo (2),エメラルドの宝石2,에메랄드 행성석 (2),Smaragdgroene Planeet (2),Smaragdplaneten (2),Szmaragdowa Planeta (2),Planeta Esmeralda (2),,Planetă din Smarald (2),Изумрудная планета (2),Смарагдна планета (2),Zümrüt Gezegen (2) -Sapphire Planet (1),TAG_ARTIPUZZGEMBLUE1,,,,Safírová planeta (1),Safirplanet (1),Saphirplanet (1),,Safira Planedo (1),Planeta Zafiro (1),,Safiiriplaneetta (1),Planète en saphir (1),Zafír Bolygó (1),Pianeta di Zaffiro (1),サファイアの宝石1,사파이어 행성석 (1),Saffierblauwe Planeet (1),Safirplaneten (1),Szafirowa Planeta (1),Planeta Safira (1),,Planetă din Safir (1),Сапфировая планета (1),Сафирна планета (1),Safir Gezegen (1) -Sapphire Planet (2),TAG_ARTIPUZZGEMBLUE2,,,,Safírová planeta (2),Safirplanet (2),Saphirplanet (2),,Safira Planedo (2),Planeta Zafiro (2),,Safiiriplaneetta (2),Planète en saphir (2),Zafír Bolygó (2),Pianeta di Zaffiro (2),サファイアの宝石2,사파이어 행성석 (2),Saffierblauwe Planeet (2),Safirplaneten (2),Szafirowa Planeta (2),Planeta Safira (2),,Planetă din Safir (2),Сапфировая планета (2),Сафирна планета (2),Safir Gezegen (2) -Daemon Codex,TAG_ARTIPUZZBOOK1,,,,,,,,Kodekso de Demono,Códice del Demonio,,Daemon-koodeksi,Codex Démoniaque,Démon Kódex,Codice Demoniaco ,デーモンの写本,악마의 고문서,,,Demoniczny Kodeks,Códice Demoníaco,,Codexul Demonilor,Демонический кодекс,Демонски кодекс, -Liber Oscura,TAG_ARTIPUZZBOOK2,,,,,,,,Liber Oscura,Liber Oscura,,,,,,オスキュラ公文書,어둠의 자유서,,,Liber Oscura,,,Liber Obscura,Либер Оскура,Либер Оскура, -Flame Mask,TAG_ARTIPUZZSKULL2,,,,Plamenná maska,Flamme-maske,Flammenmaske,,Fajrmasko,Mascara de Llamas,Mascara de Flamas,Liekkinaamio,Masque de Flammes,Láng Maszk,Maschera delle Fiamme ,炎の仮面,화염의 가면,Vuurmasker,Flammemaske,Maska Płomieni,Máscara das Chamas,,Mască de Foc,Маска пламени,Маска пламена,Alev Maskesi -Glaive Seal,TAG_ARTIPUZZFWEAPON,,,,Glévská pečeť,Sværdsegl,Schwertsiegel,,Sigelo de Glavo,Sello de Espada,,Miekkasinetti,Sceau du Glaive,Pallos Pecsét,Sigillo del Brando,グレイブシール,밀폐된 칼날,Lanszegel,Glaive segl,Pieczęć Glewii,Selo do Gládio,,Sigiliu Spadă,Печать воителя,Војников печат,Glaive Mühür -Holy Relic,TAG_ARTIPUZZCWEAPON,,,,Svatá relikvie,Hellig relikvie,Heiliges Relikt,,Sankta Relikvo,Santa Reliquia,,Pyhä reliikki,Relique Sacrée,Szent Ereklye,Reliquia Sacra,聖遺物,신성한 유물,Heilige Relikwie,Hellig relikvie,Święta Relikwia,Relíquia Sagrada,,Relicvă Sfântă,Святая реликвия,Света реликвија,Kutsal Emanet -Sigil of the Magus,TAG_ARTIPUZZMWEAPON,,,,Mágovo sigilium,Magus' segl,Symbol des Magiers,,Sigelo de la Mago,Emblema del Mago,,Taikurin sinetti,Sceau du Mage,Mágus Pecsétje,Suggello del Magus,メイガスの印章,마거스의 인장,Sigaar van de Magus,Magusens segl,Emblemat Maga,Sígilo do Mago,,Sigiliul Magului,Печать Мага,Чаробњаков симбол,Büyücünün Sigil'i -Iron gear,TAG_ARTIPUZZGEAR1,,,,Železné kolečko,Tandhjul af jern,Eisenzahnrad,,Fera Dentrado,Engranaje de Hierro,,Rautaratas,Engrenage en Fer,Vas Felszerelés,Ingranaggio di Ferro,鉄の歯車,양철 톱니바퀴,IJzeren uitrusting,Jernutstyr,Żelazna Zębatka,Engrenagem de ferro,,Mecanism din fier,Железная шестерня,Гвожђени зупчаник,Demir dişli -Brass gear,TAG_ARTIPUZZGEAR2,,,,Mosazné kolečko,Tandhjul i messing,Messingzahnrad,,Latuna Dentrado,Engranaje de Bronce,,Messinkiratas,Engrenage en Bronze,Réz Felszerelés,Ingranaggio di Ottone ,真鍮のギア,황동 톱니바퀴,Messing uitrusting,Utstyr av messing,Mosiężna Zębatka,Engrenagem de latão,,Mecanism din alamă,Латунная шестерня,Месингани зупчаник,Pirinç dişli -Brass and iron gear,TAG_ARTIPUZZGEAR3,,,,Mosazno-železné kolečko,Tandhjul af messing og jern,Messing-und-Eisen-Zahnrad,,Latuna Fera Dentrado,Engranaje de Bronce y Hierro,,Messinki- ja rautaratas,Engrenage en Fer et Bronze,Vas és Réz Felszerelés,Ingranaggio di Ferro e Ottone ,鉄と真鍮のギア,황동과 양철 톱니바퀴,Messing en ijzeren uitrusting,Utstyr av messing og jern,Zębatka z mosiądzu i żelaza,Engrenagem de ferro e latão,,Mecanism din alamă și fier,Латунно-железная шестерня,Месинганoгвожђени зупчаник,Pirinç ve demir dişli -Silver and brass gear,TAG_ARTIPUZZGEAR4,,,,Stříbro-mosazné kolečko,Tandhjul af sølv og messing,Silber-und-Messing-Zahnrad,,Arĝenta Latuna Dentrado,Engranaje de Plata y Bronce,,Hopea- ja messinkiratas,Engrenage en Argent et Bronze,Ezüst és Réz Felszerelés,Ingranaggio di Ottone e Argento ,銀と真鍮のギア,은과 황동 톱니바퀴,Zilveren en messing uitrusting,Utstyr av sølv og messing,Zębatka ze srebra i mosiądzu,Engrenagem de prata e latão,,Mecanism din argint și alamă,Серебряно-латунная шестерня,Сребрномесигани зупчаник,Gümüş ve pirinç dişli -,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,, -%o tasted an Afrit's fire.,OB_FIREDEMON,,,,%o okusil@[ao_cs] afritův oheň.,%o smagte en afrits ild.,%o spürte das Feuer des Afrits.,,%o gustis la fajron de Afrito.,%o probó el fuego de un Afrit.,,%o maistoi afritin tulta.,%o a goûté au feu d'un Afrit.,%o megkóstolta a Tűz Szellem parazsát.,%o ha assaggiato il fuoco di un Afrit. ,%o はアフリートの炎を味わった。,%o 은(는) 아프리트의 화염을 맛봤다.,%o proefde het vuur van een Afriet.,%o smakte en Afrits ild.,%o spróbował@[ao_pl] ognia Afrita.,%o provou o fogo de um Afrit.,,%o a gustat flacăra Demonului de Foc.,Игрок %o отведал огня африта.,%o је окуси@[ao_1_sr] Афритов огањ.,%o bir Afrit'in ateşini tattı. -%o was scalded by a Serpent.,OB_DEMON1,,,,%o byl@[ao_cs] upálen@[ao_cs] zlohadem.,%o blev skoldet af en slange.,%o wurde von der Chaos-Schlange gebissen.,,%o brogiĝis de Serpento.,%o fue escaldad@[ao_esp] por una Serpiente.,,%o joutui käärmeen kalttaamaksi.,%o a été brûlé@[e_fr] par un Serpent.,%o testét leforrázta egy Kígyó,%o è stato sciolto da un Serpente del Caos,%o はサーペントに火傷を負わされた。,%o 은(는) 서펜트에 데였다.,%o werd gebroeid door een Slang.,%o ble skåldet av en slange.,%o został@[ao_pl] poparzon@[adj_pl] przez Węża.,Uma Serpente escaldou %o.,,%o a fost opărit de un Șarpe.,Игрока %o спален змеем.,Играча %o је спалио Серпент.,%o bir yılan tarafından haşlandı. -%o was poisoned by a Serpent.,OB_DEMON2,,,,%o byl@[ao_cs] otráven@[ao_cs] zlohadem.,%o blev forgiftet af en slange.,%o wurde von der Chaos-Schlange verbrannt.,,%o veneniĝis de Serpento.,%o fue envenenad@[ao_esp] por una Serpiente.,,%o joutui käärmeen myrkyttämäksi.,%o a été empoisonné@[e_fr] par un Serpent.,%o vérébe mérget juttatott egy Kígyó,%o è stato avvelenato da un Serpente del Caos. ,%o はサーペントの毒にやられた。,%o 은(는) 독 서펜트에게 중독 당했다.,%o werd vergiftigd door een Slang.,%o ble forgiftet av en slange.,%o został@[ao_pl] zatrut@[adj_pl] przez Węża.,%o foi envenenad@[ao_ptb] por uma Serpente.,,%o a fost otrăvit de un Șarpe.,Игрока %o отравлен змеем.,Играча %o је отровао Серпент.,%o bir yılan tarafından zehirlendi. -%o was mashed by an Ettin.,OB_ETTIN,,,,%o byl@[ao_cs] umlácen@[ao_cs] skřetem.,%o blev moset af en Ettin.,%o wurde von dem Ettin zermatscht.,,%o frakasiĝis de Gigantaĉo.,%o fue hech@[ao_esp] puré por un Ettin.,%o quedó hech@[ao_esp] puré por un Ettin.,%o joutui ettinin muhentamaksi.,%o a été réduit@[e_fr] en purée par un Ettin.,%o csillagokat lát az Ettin miatt.,%o è stato schiacciato da un Ettin. ,%o はエティンに潰された。,%o 은(는) 에틴에게 철퇴를 맞았다.,%o werd gepureerd door een Ettin.,%o ble knust av en Ettin.,%o został@[ao_pl] stłuczon@[adj_pl] przez Ettina.,%o foi feito purê por um Ettin.,,%o a fost făcut piure de un Etin.,Игрока %o раздробил эттин.,Играча %o је смрскао Еттин.,%o bir Ettin tarafından ezildi. -%o was cut up by a Centaur.,OB_CENTAUR,,,,%o byl@[ao_cs] rozsekán@[ao_cs] kentaurem.,%o blev skåret op af en kentaur.,%o wurde von dem Zentaur aufgeschlitzt.,,%o distranĉiĝis de Centaŭro.,%o fue partid@[ao_esp] por un Centauro.,,%o joutui kentaurin pilkkomaksi.,%o a été tranché@[e_fr] par un Centaure.,%o fel lett vágva a Kentaur jóvoltából.,%o è stato affettato da un Centauro. ,%o はケンタウロスに切り刻まれた。,%o 은(는) 켄타우로스에 의해 절단됐다.,%o werd versneden door een Centaurus.,%o ble kuttet opp av en Kentaur.,%o został@[ao_pl] pocięt@[adj_pl] przez Centaura.,%o foi fatiad@[ao_ptb] por um Centauro.,,%o a fost tăiat deschis de un Centaur.,Игрока %o разрезал кентавр.,Играча %o је расекао Кентаур.,%o bir Kentaur tarafından kesildi. -%o was cut up by a Slaughtaur.,OB_SLAUGHTAURHIT,,,,%o byl@[ao_cs] rozsekán@[ao_cs] ničitaurem.,%o blev skåret op af en slagtaur.,%o wurde von dem Schlachtaur aufgeschlitzt.,,%o distranĉiĝis de Buĉataŭro.,%o fue partid@[ao_esp] por un Masacratauro.,,%o joutui teurastaurin pilkkomaksi.,%o a été tranché@[e_fr] par un Sangtaure.,%o nagyon felvágott és a Vágtaur is a játékost,%o è stato affettato da uno Sventrauro. ,%o はスロアタウルに切り刻まれた。,%o 은(는) 슬로터로스에 의해 심하게 절단됐다.,%o werd versneden door een Slachtaurus.,%o ble kuttet opp av en Slakttaur.,%o został@[ao_pl] pocięt@[adj_pl] Rzeziotaura.,%o foi fatiad@[ao_ptb] por um Chacinotauro.,,%o a fost tăiat deschis de un Centaur Violent.,Игрока %o разрезал убитавр.,Играча %o је расекао Кентаур старешина.,%o bir Katlaur tarafından kesildi. -%o was struck down by a Slaughtaur's fireball.,OB_SLAUGHTAUR,,,,%o byl@[ao_cs] zabit@[ao_cs] ničitaurovou ohnivou koulí.,%o blev slået ned af en slagtauras ildkugle.,%o wurde von dem Feuerball des Schlachtaurs niedergestreckt.,,%o subite mortiĝis de fajropilko de Buĉataŭro.,%o fue abatid@[ao_esp] por la bola de fuego de un Masacratauro.,,%o joutui teurastaurin tulipallon kaatamaksi.,%o a été touché@[e_fr] par une boule de feu de Sangtaure.,%o másodfokú égési sérüléseket szenvedett el a Vágtaur tűzgolyójától.,%o è stato abbattuto dalla palla di fuoco di uno Sventrauro. ,%o はスロアタウルの火玉に倒された。,%o 은(는) 슬로터로스의 마법구에 의해 피격당했다.,%o werd neergeslagen door een Slachtaurus' vuurbal.,%o ble truffet av en Slakttaurs ildkule.,%o został@[ao_pl] trafion@[adj_pl] przez kulę ognia Rzeziotaura.,%o foi abatid@[ao_ptb] pela bola de fogo de um Chacinotauro.,,"%o a fost răpus de mingea de foc a unui Centaur -Violent.",Игрока %o сбил огненным шаром убитавр.,Играча %o је огњеном куглом оборио Кентаур старешина.,%o bir Katlaur'un ateş topuyla vuruldu. -%o succumbed to a Bishop's dark power.,OB_BISHOP,,,,%o podlehl@[ao_cs] biskupově temné moci.,%o bukkede under for en biskops mørke kraft.,%o fiel der dunklen Macht des Bischofs zum Opfer.,,%o subfaliĝis de malluma potenco de Episkopo.,%o fue sucumbid@[ao_esp] al poder oscuro de un Obispo.,,%o lankesi piispan pimeään voimaan.,%o a succombé au pouvoir obscur d'un évèque.,%o megadta magát a Püspök sötét erejének,%o è stato sottomesso dalla magia oscura di un Vescovo. ,%o はビショップの闇の力に屈した。,%o 은(는) 비숍의 힘에 무릎을 꿇었다.,%o bezweek aan de donkere kracht van een Bisschop.,%o bukket under for en Biskops mørke kraft.,%o uległ@[ao_pl] mrocznej mocy Biskupa.,%o sucumbiu ao poder negro de um Bispo.,,%o a cedat puterii întunecate a Episcopului.,Игрок %o поддался чёрным силам Епископа.,%o је подлег@[ao_2_sr] Епископовим црним силама.,%o bir Piskopos'un karanlık gücüne yenik düştü. -%o was frozen solid by a Wendigo.,OB_ICEGUY,,,,%o byl@[ao_cs] zamrznut@[ao_cs] wendigem.,%o blev frosset fast af en wendigo.,%o wurde von dem Wendigo tiefgefroren.,,%o tute frostiĝis de Vendiko.,%o quedó congelad@[ao_esp] por un Wendigo.,,%o joutui wendigon läpikotaisin jäädyttämäksi.,%o a été gelé@[e_fr] par un Wendigo.,%o testét keményre fagyasztotta egy Wendigo,%o è stato congelato da un Wendigo. ,%o はウェンディゴによって固められた。,%o 은(는) 윈디고에 의해 단단하게 얼려졌다.,%o werd bevroren door een Wendigo.,%o ble frosset fast av en Wendigo.,%o został@[ao_pl] zamrożon@[adj_pl] przez Wendigo.,%o foi congelad@[ao_ptb] por um Wendigo.,,%o a fost făcut statuie de un Vendigo.,Игрока %o полностью заморозил вендиго.,Играча %o је потпуно замрзнуо Вендиго.,%o bir Wendigo tarafından kaskatı donduruldu. -%o was mauled by a Stalker.,OB_SERPENTHIT,,,,%o byl@[ao_cs] umlácen@[ao_cs] slídilem.,%o blev mast af en stalker.,%o wurde von dem Wasserjäger zerfleischt.,,%o vundegiĝis de Gvatanto.,%o fue triturad@[ao_esp] por un Acechador.,,%o joutui vaanijan raatelemaksi.,%o a été mutilé@[e_fr] par un Chasseur.,%o szét lett marcangolva egy Orhalász által.,%o è stato malmenato da un Cacciatore. ,%o はストーカーに引っ掻かれた。,%o 은(는) 스토커에게 발렸다.,%o werd verminkt door een Stalker.,%o ble maltraktert av en Stalker.,%o został@[ao_pl] poturbowan@[adj_pl] przez Prześladowcę.,%o foi mutilad@[ao_ptb] por um Caçador.,,%o a fost sfâșiat de un Vânător.,Игрок %o покусан преследователем.,Играча %o је растргао Вребач.,%o bir Stalker tarafından parçalandı. -%o was melted by a Stalker.,OB_SERPENT,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] slídilem.,%o blev smeltet af en stalker.,%o wurde von dem Wasserjäger geschmolzen.,,%o fandiĝis de Gvatanto.,%o fue derretid@[ao_esp] por un Acechador.,,%o joutui vaanijan sulattamaksi.,%o a été fondu@[e_fr] par un Chasseur.,%o csontjairól a húst leolvasztotta egy Orvhalász,%o è stato squagliato da un Cacciatore. ,%o はストーカーに溶かされた。,%o 은(는) 스토커에 의해 녹았다.,%o werd gesmolten door een Stalker.,%o ble smeltet av en Stalker.,%o został@[ao_pl] stopion@[adj_pl] przez Prześladowcę.,%o foi derretid@[ao_ptb] por um Caçador.,,%o a fost topit de un Vânător.,Игрока %o расплавил преследователь.,Играча %o је растопио Вребач.,%o bir Takipçi tarafından eritildi. -%o was charred by a Reiver.,OB_WRAITH,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] přízrakem.,%o blev forkullet af en reiver.,%o wurde von dem Phantom verkohlt.,,%o brulegiĝis de Fantomo.,%o fue carbonizad@[ao_esp] por un Saqueador.,,%o joutui ryövärin hiiltämäksi.,%o a été carbonisé@[e_fr] par un Reiver.,%o testét egy Martalóc elszenesítette.,%o è stato carbonizzato da un Incursore. ,%o はレイバーに黒焦げにされた。,%o 은(는) 리버에 의해 그슬렸다.,%o werd verbrand door een Rover.,%o ble forkullet av en Reiver.,%o został@[ao_pl] zwęglon@[adj_pl] przez Rozbójnika.,%o foi carbonizad@[ao_ptb] por um Fantasma.,,%o a fost ceruit de un Pungaș.,Игрока %o обуглил грабитель.,Играча %o је угљенисао Вребач.,%o bir Hayalet tarafından yakıldı. -%o had %p life stolen by a Reiver.,OB_WRAITHHIT,,,,%o si nechal@[ao_cs] ukradnout život přízrakem.,%o fik sit liv stjålet af en reiver.,%o wurde das Leben von dem Phantom gestohlen.,,%o havis sian vivon ŝtelita de Fantomo.,%o fue robad@[ao_esp] de su vida por un Saqueador.,,Ryöväri riisti pelaajan %o hengen.,%o a perdu la vie face à un Reiver.,%o %p életét ellopta egy Martalóc,%o ha permesso che un Incursore prosciugasse la sua vita ,%o はレイバーに命を %p盗まれた。,%o 은(는) 리버에게 영혼을 도둑맞았다.,%o had @[zijn_haar_nl] leven gestolen door een Rover.,%o fikk %p liv stjålet av en Reiver.,"Życie %o zostało skradzione przez Rozbójnika. -",%o teve sua vida roubada por um Fantasma.,,Viața lui %o a fost furată de un Pungaș.,Жизнь игрока %o украл грабитель.,Играчу %o је живот украо Вребач.,%o bir Hayalet tarafından kurutuldu. -%o was incinerated by the Death Wyvern.,OB_DRAGON,,,,%o byl@[ao_cs] upálen@[ao_cs] smrtidrakem.,%o blev forbrændt af wyvern.,%o wurde von dem Todesdrachen verbrannt.,,%o cindriĝis de Mortviverno.,%o fue calcinad@[ao_esp] por el Guiverno de la Muerte.,,%o joutui kuolontraakin polttamaksi.,%o a été incinéré@[e_fr] par une vouivre de la mort.,%o testét porig égette egy Halálsárkány,%o è stato incenerito da una Viverna Mortale. ,%o はダークワイバーンに焼却された。,%o 은(는) 데스 와이번에 의해 분신 당했다.,%o werd verbrand door de Doodsdraak.,%o ble brent opp av en Døden Wyvern.,%o został@[ao_pl] spalon@[adj_pl] przez Wiwernę Śmierci.,%o foi incinerad@[ao_ptb] por uma Serpe da Morte,,%o a fost incinerat de Balaurul Morții.,Игрока %o кремировала виверна Смерти.,Играча %o је кремировао Змајак смрти.,"%o, Ölüm Wyvern tarafından yakıldı." -%o was swept from the board by Korax.,OB_KORAX,,,,%o byl@[ao_cs] odhozen@[ao_cs] ze šachovnice Koraxem.,%o blev fejet væk fra brættet af Korax.,%o wurde von Korax vom Feld gefegt.,,%o estis prenita el la tabulo de Korax.,%o fue barrid@[ao_esp] del tablero por Korax.,,%o pyyhkäistiin laudalta Kooraksen voimasta.,%o a été balayé@[e_fr] de l'échiquier par Korax.,%o el lett söpörve a tábláról Korax által.,%o è stato eliminato dalla scacchiera da Korax. ,%o は唯一神の怒りに触れた。,%o 은(는) 코락스의 체스판에서 사라졌다.,%o werd door Korax van het bord geveegd.,%o ble feid fra brettet av Korax.,%o został@[ao_pl] zmiecion@[adj_pl] z pokładu przez Koraxa.,%o foi eliminad@[ao_ptb] do tabuleiro por Korax.,,%o a fost măturat de pe drum de Korax.,Игрока %o скинул с доски Коракс.,Играча %o је с табле уклонио Коракс.,"%o, Korax tarafından tahtadan süpürüldü." -%o was slain by Zedek.,OB_FBOSS,,,,%o byl@[ao_cs] zabit@[ao_cs] Zedekem.,%o blev dræbt af Zedek.,%o wurde von Zedek hingemetzelt.,,%o mortigis de Zedeko.,%o recibió una puñalada de Zedek.,,%o joutui Sedekin tappamaksi.,%o a été pourfendu@[e_fr] par Zedek.,%o meghalt Zedek által.,%o è stato ammazzato da Zedek. ,%o はゼデクに討ち取られた。,%o 은(는) 제닥의 이름으로 쓰러졌다.,%o werd gedood door Zedek.,%o ble drept av Zedek.,%o został@[ao_pl] zgładzon@[adj_pl] przez Zedeka.,%o foi mort@[ao_ptb] por Zedek.,,%o a fost omorât de Zedek.,Игрока %o сразил Зедек.,Играча %o је оборио Коракс.,"%o, Zedek tarafından öldürüldü." -%o couldn't absorb Menelkir's Mana.,OB_MBOSS,,,,%o nemohl@[ao_cs] pojmout Menelkirovu manu.,%o kunne ikke absorbere Menelkirs Mana.,%o konnte Menelkirs Mana nicht verkraften.,,%o ne povis absorbi la Manaon de Menelkiro.,%o no pudo absorber el maná de Menelkir.,%o No pudo absorber el mana de Menelkir.,%o ei kyennyt ottamaan vastaan Menelkirin manaa.,%o n'aurait pu absorber le mana de Menelkir.,%o nem tudta elnyelni Menelkir manáját.,%o non è riuscito ad assorbire il mana di Menelkir. ,%o はメネルキルのマナを吸収できなかった。,%o 은(는) 메넬키어의 마나를 흡수하지 못했다.,%o kon Menelkir's mana niet absorberen.,%o kunne ikke absorbere Menelkirs Mana.,%o nie m@[irreg_4_pl] wchłonąć Many Menelkira.,%o não conseguiu absorver o Mana de Menelkir.,,%o nu a reușit să absoarbă mana lui Menelkir.,Игрок %o не смог поглотить ману Менелкира.,%o се није узмог@[ao_2_sr] носити с Менелкировом маном.,"%o, Menelkir'in Mana'sını ememedi." -%o was baptized by Traductus.,OB_CBOSS,,,,%o byl@[ao_cs] posvěcen@[ao_cs] Traduktem.,%o blev døbt af Traductus.,%o wurde von Traductus getauft.,,%o baptiĝis de Traduktuso.,%o fue bautizad@[ao_esp] por Traductus.,,%o joutui Traduktuksen kastamaksi.,%o a été baptisé@[e_fr] par Traductus.,%o meg lett keresztelve Traductus által.,%o è stato battezzato da Traductus. ,%o はトラダクタスの洗礼を受けた。,%o 은(는) 트라닥투스에게 침례를 당했다.,%o werd gedoopt door Traductus.,%o ble døpt av Traductus.,%o został@[ao_pl] ochrzczon@[adj_pl] przez Traductusa.,%o foi batizad@[ao_ptb] por Traductus.,,%o a fost botezat de Traductus.,Игрока %o крестил Традуктус.,Играча %o је крстио Традуктус.,"%o, Traductus tarafından vaftiz edildi." -%o had %p bones rolled by the Heresiarch.,OB_HERESIARCH,,,,%o si nechal@[ao_cs] rozmetat kosti Arcikacířem.,%o fik sine knogler rullet af Heresiark.,%os Knochen wurden vom Erzketzer gerollt.,,%o havis siajn ostojn rulis de la Ĉefherezulo.,%o tuvo sus huesos arrollados por el Heresiarca.,,Kerettiarkki jyräsi pelaajan %o luut.,%o s'est fait@[e_fr] rouler les os par l'Hérésiarche.,%o csontváza ki lett forgatva az Eretnek Vezér által.,Le ossa di %o sono state accartocciate dall'Eresiarca. ,%o はヘレシアークに骨を %p本 撒き散らされた。,%o 은(는) 헤러시아크에 의해 뼈와 살이 분리되었다.,%o @[zijn_haar_nl] botten werden opgerold door de Heresiarch.,%o fikk %p bein rullet av Heresiark.,Kości %o zostały porozrzucane przez Herezjarchę.,%o teve seus ossos moídos pelo Heresiarca.,,Oasele lui %o au fost făcute praf de către Ereziarh.,Ересиарх сыграл в кости игрока %o.,На играча %o су пале Јересијархове коцке.,"%o, Heresiark tarafından kutsandı." -%o was beaten to a pulp by %k's bare fists.,OB_MPFWEAPFIST,,,,%o byl@[ao_cs] umlácen@[ao_cs] k smrti holými pěstmi hráče %k.,%o blev slået til plukfisk af %ks bare næver.,%o wurde von %ks nackten Fäusten zu Hackfleisch verarbeitet.,,%o kaĉe draŝiĝis de la nudaj pugnoj de %k.,%o quedó molid@[ao_esp] a golpes por los puños limpios de %k.,,%k hakkasi %o paran muusiksi paljailla nyrkeillään.,%o à été tabassé@[e_fr] à mort par les poings de %k.,%o péppé lett verve %k ökleivel.,%k ha ridotto %o in poltiglia a mani nude.,%o は %k に素手でボコボコにされた。,%o 은(는) %k 의 맨손 타격으로 묵사발이 되었다.,%o werd tot pulp geslagen door %k's blote vuisten.,%o ble slått til mos av %ks bare never.,%o został@[ao_pl] zbit@[adj_pl] na miazgę przez gołe pięści %k.,%o foi espancad@[ao_ptb] até a morte pelos punhos nus de %k.,,%k l-a omorât în bătaie pe %o cu mâinile goale.,Игрок %o избит в мясо голыми руками игрока %k.,%o је пребијен@[adj_1_sr] на смрт голим рукама играч %k.,"%o, %k tarafından eşek sudan gelinceye kadar dövüldü." -%o got the axe from %k.,OB_MPFWEAPAXE,,,,%o dostal@[ao_cs] sekerou od hráče %k.,%o fik øksen af %k.,%o sah %ks Axt.,,%o ricevis la hakilon el %k.,%o recibió el hachazo de %k.,,%o sai pelaajan %k kirveestä.,%o s'est fait@[e_fr] hacher menu par %k.,%o megkapta %k baltáját.,%o ha preso un colpo d'ascia da %k.,%o は %k から斧を受けた。,%o 은(는) %k 의 티몬의 도끼를 어설프게 받아쳤다.,%o kreeg de bijl van %k.,%o fikk øksa av %k.,%o dostał@[ao_pl] z topora %k.,%o recebeu o machado de %k.,,%o a primit un topor de la %k.,Игрок %o словил топорик игрока %k.,%o је добио секиру од %k.,"%o, %k tarafından baltayla dövüldü." -%o had %p head caved in by %k's hammer.,OB_MPFWEAPHAMMERM,,,,%o dostal@[ao_cs] po hlavě kladivem hráče %k.,%o fik sit hoved udhulet af %ks hammer.,%o wurde der Kopf von %ks Hammer eingeschlagen.,,%p havis sian kapon enfalis de la martelo de %k.,%o tuvo su cabeza hundida por el martillo de %k.,,%k painoi vasarallaan %o paran pään kasaan.,%o s'est fait@[e_fr] éclater le crâne par le marteau de %k.,%o kapott egy üreges fejet %k Kalapácsa által.,La testa di %o è stata aperta in due dal martello di %k.,%o は %k のハンマーで頭に空洞を開けられた。,%k 은(는) 징벌의 망치로 %o 의 머리 위에 우물을 만들었다.,%o had @[zijn_haar_nl] kop ingestort met %k's hamer.,%o fikk %p hode knust av %ks hammer.,Głowa %o została zmiażdżona przez młot %k.,%o teve seu crânio afundado pelo martelo de %k.,%o teve seu crânio amolgado pelo martelo de %k.,%k i-a băgat capul lui %o în interior cu ciocanul.,Голова игрока %o была вдолблена в тело молотом игрока %k.,Играч %k је расцепао играчу %o главу.,"%o, %k tarafından dövüldü." -%o's soul was forged anew by %k's hammer.,OB_MPFWEAPHAMMERR,,,,%o@[psf1_cs] duše byla obrozena kladivem hráče %k.,%os sjæl blev smedet på ny af %ks hammer.,%os Seele wurde durch %ks Hammer erneuert.,,La animo de %o nove forĝiĝis de la martelo de %k.,El alma de %o fue forjada de nuevo por el martillo de %k.,,%k uudelleentakoi %o paran sielun vasarallaan.,%o a eu son âme reforgée par le marteau de %k.,%o lelke újra lett kovácsolva %k Kalapácsa által.,L'anima di %o è stata riforgiata dal martello di %k.,%o の魂は %k のハンマーで一から鍛え直された。,%o 의 영혼은 %k 의 징벌의 망치에 의해 철거되었다.,%o's ziel werd omgesmeed door %k's hamer.,%o's sjel ble smidd på nytt av %ks hammer.,Dusza %o została wykuta na nowo przez młot %k.,%o teve sua alma reforjada pelo martelo de %k.,,%k i-a făcut sufletul lui %o ca nou cu ciocanul.,Душа игрока %o была перекована молотом игрока %k.,Играч %k је прековао душу играча %o чекићем.,"%o, %k tarafından dövüldü." -%o was silenced by %k's mighty Quietus.,OB_MPFWEAPQUIETUS,,,,%o byl@[ao_cs] umlčen@[ao_cs] mocným Tišitelem hráče %k.,%o blev bragt til tavshed af %ks mægtige Forløser.,%o wurde durch %ks Erlöser befreit.,,%o slientiĝis de La Pova Kvietus' de %k.,%o fue silenciad@[ao_esp] por el poderoso Quietus de %k.,,%k vaiensi %o paran mahtavalla Quietuksellaan.,%o à été réduit@[e_fr] au silence par le pouvoir de %k et Quietus.,%o el lett némítva %k hatalmas Némusza által.,%o è stato zittito dal potente Quietus di %k.,%o は %k の強靭なクワイエタスで静かにされた。,%o 은(는) %k 의 종언의 검 덕에 침묵을 지킬 수 있었다.,%o werd tot zwijgen gebracht door %k's machtige Quietus.,%o ble brakt til taushet av %ks mektige Quietus.,%o został@[ao_pl] uciszon@[adj_pl] przez %k.,%o foi silenciad@[ao_ptb] pelo poderoso Quietus de %k.,,"%o a fost redus la tăcere de argumentul final al -lui %k.",Игрок %o утихомирен легендарным Последним доводом игрока %k.,%o је утишан@[adj_1_sr] од моћи Куиетуса играч %k.,"%o, %k tarafından susturuldu." -%o got a mace to the face from %k.,OB_MPCWEAPMACE,,,,%o dostal@[ao_cs] palcátem po hlavě od hráče %k.,%o fik en stridskølle i ansigtet af %k.,%o bekam %ks Streitkolben ins Gesicht.,,%o prenis klabon al la vizaĝon el %k.,%o consiguió un mazazo a la cara de parte de %k.,,%o sai pelaajan %k nuijasta naamaansa.,%o s'est fait@[e_fr] casser la figure par la masse de %k.,%o kapott egy buzogányt a fejébe %k által.,%o si è preso una mazzata in faccia da %k.,%o は自らの顔に %k のメイスを受けた。,%o 은(는) %k 의 철퇴를 맞은 뒤에야 철이 들었다.,%o kreeg een %k's gesel in @[zijn_haar_nl] gezicht.,%o ble slått i ansiktet av %k.,%o dostał@[ao_pl] buzdyganem %k w twarz.,%o levou com a maça de %k na cara.,,%o a primit un buzdugan în față de la %k.,Игрок %o получил по морде булавой игрока %k.,%o је доби@[ao_1_sr] буздован у фацу играч %k.,"%o, %k tarafından eşek sudan gelinceye kadar dövüldü." -%o was bitten by %k's serpent staff.,OB_MPCWEAPSTAFFM,,,,%o byl@[ao_cs] kousnut@[ao_cs] hadí holí hráče %k.,%o blev bidt af %ks slange-stav.,%o wurde von %ks Schlangenstab gebissen.,,%o mordiĝis de la serpentbastono de %k.,%o fue mordid@[ao_esp] por el bastón de la serpiente de %k.,,%k puri %o parkaa käärmesauvallaan.,%o s'est fait@[e_fr] mordre par le Bâton du Serpent %k.,%o meg lett harapva %k Kígyó Botja által.,%o è stato morso dalla Staffa del Serpente di %k.,%o は %k の蛇の杖に噛まれた。,%o 은(는) %k 의 뱀 지팡이에 의해 독살당했다.,%o werd gebeten door %k's slangenstaf.,%o ble bitt av %ks slangestav.,%o został@[ao_pl] ugryzion@[adj_pl] laską węży %k.,%o foi mordid@[ao_ptb] pelo Cetro da Serpente de %k.,,%o a fost mușcat de bastonul șarpe al lui %k.,Игрок %o искусан змеиным посохом игрока %k.,%o је угрижен@[adj_1_sr] змијским штапом играч %k.,"%o, %k tarafından zehirlendi." -%o choked on %k's serpent staff.,OB_MPCWEAPSTAFFR,,,,%o se zadusil@[ao_cs] hadí holí hráče %k.,%o blev kvalt af %ks slange stav.,%o verschluckte sich an %ks Schlangenstab.,,%o sufokis la serpentbastonon de %k.,%o se ahogó con el bastón de la serpiente de %k.,,%o tukehtui pelaajan %k käärmesauvaan.,%o s'est étranglé@[e_fr] sur le Bâton du Serpent de %k,%o megfulladt %k Kígyó Botja által.,%o è soffocato a causa della Staffa del Serpente di %k.,%o は %k の蛇の杖に息の根を止められた。,%o 은(는) %k 의 뱀 지팡이 때문에 숨을 쉬지 못했다.,%o stikte in %k's slangenstaf.,%o ble kvalt av %ks slangestav.,%o zakrztusił@[ao_pl] się laską węży %k.,%o se engasgou com o Cetro da Serpente de %k,,%o s-a sufocat pe bastonul șarpe al lui %k.,Игрок %o задушен змеиным посохом игрока %k.,%o је задављен@[adj_1_sr] змијским штапом играч %k.,"%o, %k tarafından kurutuldu." -%o was lit up by %k's flames.,OB_MPCWEAPFLAME,,,,%o vzplanul@[ao_cs] plameny hráče %k.,%o blev tændt af %ks flammer.,%o wurde von %ks Flammen erleuchtet.,,%o ekbruliĝis de la fajroj de %k.,%o fue encendid@[ao_esp] por las llamas de %k.,,%o syttyi pelaajan %k liekeistä.,%o s'est fait@[e_fr] allumer par %k.,%o fel lett gyújtva %k tűze által.,%o è stato illuminato dalle fiamme di %k.,%o は %k によって炎を灯された。,%o 은(는) %k 의 화염폭풍에 휩쓸렸다.,%o werd opgelicht door %k's vlammen.,%o ble opplyst av %ks flammer.,%o został@[ao_pl] oświetlon@[adj_pl] płomieniami %k.,%o foi incendiad@[ao_ptb] pelas chamas de %k.,,%o s-a aprins de la flăcările lui %k.,Игрок %o сгорел в огне игрока %k.,%o је осветљен@[adj_1_sr] пламеном играч %k.,"%o, %k tarafından aydınlatıldı." -%o was cleansed by %k's Wraithverge.,OB_MPCWEAPWRAITHVERGE,,,,%o byl@[ao_cs] očištěn@[ao_cs] Zjevitelem hráče %k.,%o blev renset af %ks Spirit Bringer.,%o wurde durch %ks Geisterbringer geläutert.,,%o puriĝis de la Fantomkruc' de %k.,%o fue limpiad@[ao_esp] por la vara fantasmal de %k.,,%k puhdisti pelaajan %o Haamusauvallaan.,%o a été purifié@[e_fr] par la Verge Phantasmale de %k.,%o meg lett tisztítva %k Bosszúbot által.,%o è stato purificato dalla Verga SconfinaSpettri di %k.,%o は %k のレイスバージによって浄化された。,%o 은(는) %k 의 사령의 지팡이에 의해 정화되었다.,%o werd gereinigd door %k's Schimroede.,%o ble renset av %ks Wraithverge.,%o został@[ao_pl] oczyszczon@[adj_pl] przez Widmoskraj %k.,%o foi purificad@[ao_ptb] pelo Cajado Fantasma de %k.,,%o a fost purificat de Toiagul Stafie al lui %k.,Игрок %o очищен жезлом духов игрока %k.,%o je прочишћен@[adj_1_sr] штапом утваре играч %k.,"%o, %k tarafından temizlendi." -%o took one too many sapphire beams from %k.,OB_MPMWEAPWAND,,,,%o koupil@[ao_cs] přespříliš safírových střel od hráče %k.,%o tog en safirstråle for meget fra %k.,%o bekam zu viele Saphierstrahlen von %k ab.,,%o recivis unu tro da safira radio de %k.,%o recibió demasiados rayos de zafiro de %k.,,%o otti vastaan yhden liikaa pelaajan %k safiirisäteistä.,%o s'est pris@[e_fr] un rayon saphirique en trop de la part de %k.,%o túl sok zafír sugarat kapott %k-tól/től.,%o si è buscato un raggio di zaffiro di troppo da %k.,%o は %k から多量のサファイアビームを受け取った。,%o 은(는) %k 의 사파이어 빛을 너무 많이 째려봤다.,%o kreeg een saffierstraal teveel van %k.,%o fikk en safirstråle for mye fra %k.,%o wzi@[irreg_2_pl] o jeden szafirowy promień od %k za dużo.,%o levou muitos raios de safira de %k.,,%o a primit o rază în plus de la safirul lui %k.,Игрок %o схватил слишком много сапфировых зарядов от игрока %k.,%o је узе@[ao_1_sr] превише сафирских зракова играч %k.,"%o, %k tarafından dönüştürüldü." -%o was turned into a frosty fellow by %k.,OB_MPMWEAPFROST,,,,%o byl@[ao_cs] zchlazen@[ao_cs] hráčem %k.,%o blev forvandlet til en frostklar fyr af %k.,%o wurde von %k schockgefrostet.,,%o farigiĝis frostulon de %k.,%o fue convertid@[ao_esp] en un helado por %k.,%o fue convertid@[ao_esp] en una persona helada por %k.,%k muutti %o paran pakkasveikoksi.,%o s'est fait@[e_fr] transformer en glaçon par %k.,%o jégbaráttá alakult %k által.,%o è stato trasformato in un simpatico pupazzo di neve da %k.,%o は %k によって冷ややかな輩になった。,%o 은(는) %k 의 얼음 파편에 의해 눈사람이 되었다.,%o werd ijskoud veranderd door %k.,%o ble forvandlet til en iskald fyr av %k.,%o został@[ao_pl] zmienion@[adj_pl] w mroźnego koleżkę przez %k.,%o foi transformad@[ao_ptb] em picolé por %k.,,%o a fost transformat într-un amic de gheață de %k.,Игрок %o обращается в ледяную скульптуру игроком %k.,%o је претворен@[adj_1_sr] у лед играч %k.,"%o, %k tarafından soğuk bir adama dönüştürüldü." -%o received a shocking revelation from %k.,OB_MPMWEAPLIGHTNING,,,,%o zjistil@[ao_cs] šokující odhalení hráče %k.,%o fik en chokerende åbenbaring af %k.,%o musste eine schockierende Enthüllung von %k verkraften.,,%o recivis teruran revelacion de %k.,%o recibió una revelación impactante de %k.,,%o sai sähköistävän ilmestyksen pelaajalta %k.,%o a reçu un sacré coup de jus de la part de %k.,%o kapott egy sokkoló relevációt %k-tól/től,"%o ha ricevuto una notizia ""elettrizzante"" da %k.",%o は %k から衝撃的な啓示を受けた。,%o 은(는) %k 의 번갯불 덕에 충격적인 계시를 받았다.,%o kreeg een schokkende openbaring van %k.,%o fikk en sjokkerende åpenbaring fra %k.,%o otrzymał@[ao_pl] szokujące objawienie od %k.,%o recebeu uma revelação chocante de %k.,,%o a avut parte de o revelație șocantă de la %k.,Игрок %o откровенно шокирован игроком %k.,%o је прими@[ao_1_sr] шокантно откриће играч %k.,"%o, %k tarafından şoka uğratıldı." -%o was wiped off the face of the universe by %k's Bloodscourge.,OB_MPMWEAPBLOODSCOURGE,,,,%o byl@[ao_cs] vymýcen@[ao_cs] ze jsoucna vesmíru Krvehromem hráče %k.,%o blev udslettet af universets overflade af %ks Blodgisel.,%o wurde von %ks Blutgeißel aus dem Universum verbannt.,,%o disdetruiĝis el la universo de la Sangskurĝ' de %k.,%o fue borrad@[ao_esp] de la faz del universo por la plaga sangrienta de %k.,,%k pyyhki %o paran maailmankaikkeudesta.,%o s'est fait@[e_fr] effacer de l'univers par le Fléau Sanglant de %k.,%o ki lett törölve az univerzumból %k Vérkorbácsának köszönhetően.,%o è stato cancellato dalla faccia dell'universo dal Flagello di Sangue di %k.,%o は %k の天罰によりこの世から一掃された。,%o 은(는) %k 이(가) 피의 재앙을 씀으로써 전혀 존재하지 않는 존재가 되어버렸다.,%o werd van het gezicht van het universum geveegd door %k's Bloedgesel.,%o ble utslettet fra universets overflate av %ks Bloodscourge.,Twarz %o została zmieciona z wszechświata przez Krwioplagę %k.,%o foi varrid@[ao_ptb] da face do universo pelo Flagelo de Sangue de %k.,,"%o a fost ras de pe fața universului de -Flagelul Sângeros al lui %k.",Игрок %o стёрт с лица вселенной Кровавым бичом игрока %k.,%o је обрисан@[adj_1_sr] са лица свемира од Крвавог зла играч %k.,"%o, %k tarafından evrenden silindi." -,,Strife,,,,,,,,,,,,,,,,,,,,,,,, -,,Pickups,,,,,,,,,,,,,,,,,,,,,,,, -You picked up the Metal Armor.,TXT_METALARMOR,,,You picked up the Metal Armour.,Sebral@[ao_cs] jsi kovové brnění.,Du samlede metalrustningen op.,Du hast die Metallrüstung genommen.,Πήρες τη Μεταληκή Πανοπλία.,Vi trovis metalan armaĵon.,Encuentras una armadura de metal.,Hallaste una armadura de metal.,Poimit metallihaarniskan.,Vous avez pris l'armure de métal.,Felvetted a Fémpáncélt.,Hai raccolto l'Armatura di Metallo.,メタルアーマー 入手。,강철 갑옷을 획득했다.,Je hebt het metalen harnas opgepakt.,Du plukket opp metallrustningen.,Podniosł@[irreg_3_pl] Metalowy Pancerz.,Você pegou a Armadura de Metal.,Apanhaste a Armadura de Metal.,Ai ridicat Armura din Metal.,Получена металлическая броня.,Покупио си метални оклоп.,Metal Zırhı aldın. -You picked up the Leather Armor.,TXT_LEATHERARMOR,,,You picked up the Leather Armour.,Sebral@[ao_cs] jsi kožené brnění.,Du samlede læderrustningen op.,Du hast die Lederrüstung genommen.,Πήρες τη Δερμάτινη Πανοπλία.,Vi trovis ledan armaĵon.,Encuentras una armadura de cuero.,Hallaste una armadura de cuero.,Poimit nahkasuojuksen.,Vous avez pris l'armure de cuir.,Felvetted a Bőrpáncélt.,Hai raccolto l'Armatura di Cuoio.,レザーアーマー 入手。,가죽 갑옷을 획득했다.,Je hebt het leren harnas opgepakt.,Du plukket opp lærrustningen.,Podniosł@[irreg_3_pl] Skórzany Pancerz.,Você pegou a Armadura de Couro.,Apanhaste a Armadura de Couro.,Ai ridicat Armura din Piele.,Получена кожаная броня.,Покупио си кожни оклоп.,Deri Zırhı aldın. -You picked up the Med patch.,TXT_MEDPATCH,,,,Sebral@[ao_cs] jsi obvaz.,Du samlede Med patch op.,Du hast den Verband genommen.,,Vi trovis kuracbendojn.,Encuentras unas tiritas.,Hallaste unas curitas.,Poimit sidekääreen.,Vous avez pris le pansement.,Felvetted a Ragtapaszt.,Hai raccolto le Bende.,医薬パッチ 入手。,의료 붕대를 획득했다.,Je hebt de med-patch opgepakt.,Du plukket opp en Med-patch.,Podniosł@[irreg_3_pl] Bandaż.,Você pegou a compressa médica.,Apanhaste a compressa médica.,Ai ridicat Trusa de Prim-Ajutor.,Получен медицинский бинт.,Покупио си прву помоћ.,Sağlık bandını aldın. -You picked up the Medical kit.,TXT_MEDICALKIT,,,,Sebral@[ao_cs] jsi lékárničku.,Du samlede Medicinsk kit op.,Du hast den Verbandskasten genommen.,,Vi trovis sukurkeston.,Encuentras un botiquín.,Hallaste un botiquín.,Poimit lääkintälaukun.,Vous avez pris le kit médical.,Felvetted az Elsősegélycsomagot.,Hai raccolto il Kit di Pronto Soccorso.,医療用キット 入手。,구급 키트를 획득했다.,Je hebt de medicijndoos opgepakt.,Du plukket opp det medisinske settet.,Podniosł@[irreg_3_pl] Apteczkę.,Você pegou o Kit Médico.,Apanhaste o Kit Médico.,Ai ridicat Kitul de Prim-Ajutor.,Получена аптечка.,Покупио си медицински комплет,Tıbbi kiti aldın. -You picked up the Surgery Kit.,TXT_SURGERYKIT,,,,Sebral@[ao_cs] jsi chirurgickou soupravu.,Du samlede kirurgisættet op.,Du hast den Erste-Hilfe-Kasten genommen.,,Vi trovis kirurgian keston.,Encuentras un kit quirúrgico.,Hallaste un kit quirúrgico.,Poimit kirurgilaukun.,Vous avez pris le kit de chirurgie.,Felvetted az Orvosi Műtőfelszerelést.,Hai raccolto il Kit Chirurgico.,手術キット 入手。,수술 키트를 획득했다.,Je hebt het chirurgenpakket opgepakt.,Du plukket opp Kirurgi-settet.,Podniosł@[irreg_3_pl] Zestaw Chirurga.,Você pegou o Kit de Cirurgia.,Apanhaste o Kit de Cirugia.,Ai ridicat Kitul pentru Operații.,Получен медкомплект.,Покупио си хируршки комплет,Ameliyat setini aldın. -You picked up the map.,TXT_STRIFEMAP,,,,Sebral@[ao_cs] jsi mapu.,Du samlede kortet op.,Du hast die Karte genommen.,Πήρες το χάρτη.,Vi trovis la mapon.,Encuentras el mapa.,Hallaste el mapa.,Poimit kartan.,Vous avez pris la carte,Felvetted a térképet.,Hai raccolto la Mappa.,マップ 取得。,지도를 획득했다.,Je hebt de kaart opgepakt.,Du plukket opp kartet.,Podniosł@[irreg_3_pl] mapę.,Você pegou o mapa.,Apanhaste o mapa.,Ai ridicat harta.,Получена карта.,Покупио си мапу.,Haritayı aldın. -You picked up the ring.,TXT_BELDINSRING,,,,Sebral@[ao_cs] jsi prsten.,Du samlede ringen op.,Du hast den Ring genommen.,Πήρες το Δακτύλιο.,Vi prenis la ringon.,Tienes el anillo.,,Poimit sormuksen.,Vous avez pris l'anneau.,Felvetted a Gyűrűt.,Hai raccolto l'Anello.,指輪 取得。,반지를 획득했다.,Je hebt de ring opgepakt.,Du plukket opp ringen.,Podniosł@[irreg_3_pl] pierścień.,Você pegou o anel.,Apanhaste o anel.,Ai ridicat inelul.,Получено кольцо.,Покупио си прстен.,Yüzüğü aldın. -You picked up the Offering Chalice.,TXT_OFFERINGCHALICE,,,,Sebral@[ao_cs] jsi obětní kalich.,Du samlede offerkalken op.,Du hast den Opferkelch genommen.,,Vi prenis la oferdonan kalikon.,Tienes el cáliz de ofrenda.,,Poimit uhrimaljan.,Vous avez pris le Calice d'obole.,Felvetted az Áldozati Kelyhet.,Hai raccolto il Calice delle Offerte.,寄贈された聖杯 取得。,번제 성배를 훔쳤다.,Je hebt de Offerbeker opgepakt.,Du plukket opp offerbegeret.,Podniosł@[irreg_3_pl] Kielich Ofiarny.,Você pegou o Cálice de Oferenda.,Apanhaste o Cálice de Oferenda.,Ai ridicat Potirul pentru Ofrande.,Получена чаша для подношений.,Покупио си Жртвени пехар.,Adak Kadehini aldın. -You picked up the ear.,TXT_EAR,,,,Sebral@[ao_cs] jsi ucho.,Du samlede øret op.,Du hast das Ohr gernommen.,Πήρες το αυτί.,Vi prenis la orelon.,Tienes la oreja.,,Poimit korvan.,Vous avez pris l'oreille.,Felvetted a Fület.,Hai raccolto l'Orecchio.,耳 取得。,잘린 귀를 주웠다.,Je hebt het oor opgepakt.,Du plukket opp øret.,Podniosł@[irreg_3_pl] ucho.,Você pegou a orelha.,Apanhaste a orelha.,Ai ridicat urechea.,Получено ухо.,Покупио си уво.,Kulağı aldın. -You picked up the broken power coupling.,TXT_BROKENCOUPLING,,,,Sebral@[ao_cs] jsi rozbitou spojku.,Du samlede den ødelagte strømkobling op.,Du hast den defekten Stromabnehmer genommen.,,Vi havas la rompitan energian kuplilon.,Tienes el acoplador de energía roto.,,Poimit rikkinäisen virtaliittimen.,Vous avez pris le coupleur énergétique cassé.,Felvetted a hibás tápcsatlakozót.,Hai raccolto la Coppia Energetica Rotta.,壊れたパワーカップリング 取得。,망가진 동력선 장치를 획득했다.,Je hebt de kapotte stroomkoppeling opgepakt.,Du plukket opp den ødelagte kraftkoblingen.,Podniosł@[irreg_3_pl] zepsute obwody zasilające.,Você pegou o acoplador de energia quebrado.,Apanhaste o acoplador de energia partido.,Ai ridicat cuplajul defect de curent.,Получена повреждённая муфта.,Покупио си неисправну спојницу напајања.,Kırık güç bağlantısını aldın. -You picked up the Shadow armor.,TXT_SHADOWARMOR,,,You picked up the Shadow armour.,Sebral@[ao_cs] jsi krycí brnění.,Du samlede skyggerustningen op.,Du hast die Schattenrüstung genommen.,,Vi trovis ombran armaĵon.,Encuentras una armadura de sombra.,Hallaste una armadura de sombra.,Poimit varjohaarniskan.,Vous avez pris l'armure de l'ombre.,Felvetted az Árnyékpáncélt.,Hai raccolto l'Armatura Ombra.,シャドウアーマー 入手。,그림자 갑옷을 획득했다.,Je hebt het schaduwharnas opgepakt.,Du plukket opp Skygge-rustningen.,Podniosł@[irreg_3_pl] Cienisty Pancerz.,Você pegou a armadura das sombras.,Apanhaste a armadura das sombras.,Ai ridicat Armura Umbrei.,Получена теневая броня.,Покупио си оклоп сенки.,Gölge zırhını aldın. -You picked up the Environmental Suit.,TXT_ENVSUIT,,,,Sebral@[ao_cs] jsi ochranný oděv,Du samlede miljødragten op.,Du hast den Schutzanzug genommen.,,Vi trovis medi-ŝirman veston,Encuentras un traje de protección ambiental.,Hallaste un traje de protección ambiental.,Poimit ympäristösuojapuvun.,Vous avez pris la combinaison hazmat.,Felvetted a Védőruhát.,Hai raccolto la Tuta Ambientale.,耐環境スーツ 入手。,환경 방호복을 획득했다.,Je hebt het beschermende pak opgepakt.,Du plukket opp miljødrakten.,Podniosł@[irreg_3_pl] Skafander Ochronny.,Você pegou o Traje de Proteção.,Apanhaste o Fato Protetor.,Ai ridicat Costumul de Protecție.,Получен защитный костюм.,Покупио си заштитно одело.,Çevresel Kıyafeti aldın. -You picked up the Guard Uniform.,TXT_GUARDUNIFORM,,,,Sebral@[ao_cs] jsi hlídačovu uniformu.,Du samlede vagtuniformen op.,Du hast die Wächteruniform genommen.,,Vi prenis la uniformon de gardisto.,Tienes el uniforme de un guardia.,,Poimit vartijan univormun.,Vous avez pris l'Uniforme du garde.,Felvetted az Őr Egyenruhát.,Hai raccolto l'Uniforme da Guardia.,守衛の制服 入手。,경비 전투복을 획득했다.,Je hebt het wachtersuniform opgepakt.,Du plukket opp vaktuniformen.,Podniosł@[irreg_3_pl] Mundur Strażnika.,Você pegou o Uniforme de Guarda.,Apanhaste o Uniforme de Guarda.,Ai ridicat Uniforma de Paznic.,Получена униформа стражника.,Покупио си стражарску униформу,Muhafız Üniformasını aldın. -You picked up the Officer's Uniform.,TXT_OFFICERSUNIFORM,,,,Sebral@[ao_cs] jsi důstojníkovu uniformu.,Du samlede officersuniformen op.,Du hast die Offiziersuniform genommen.,,Vi trovis oficiran uniformon.,Encuentras un uniforme de oficial.,Hallaste un uniforme de oficial.,Poimit upseerin univormun.,Vous avez pris l'Uniforme de l'officier.,Felvetted a Tiszti Egyenruhát.,Hai raccolto l'Uniforme da Ufficiale.,士官の制服 入手。,장교 전투복을 획득했다.,Je hebt het officiersuniform opgepakt.,Du plukket opp offisersuniformen.,Podniosł@[irreg_3_pl] Mundur Oficera.,Você pegou o Uniforme de Oficial.,Apanhaste o Uniforme de Oficial.,Ai ridicat Uniforma Ofițerului.,Получена униформа офицера.,Покупио си официрску униформу,Subay üniformasını aldın. -You picked up the flame thrower parts.,TXT_FTHROWERPARTS,,,,Sebral@[ao_cs] jsi součásti plamenometu.,Du samlede flammekasterdele op.,Du hast die Flammenwerferteile genommen.,,Vi havas la partojn de flamĵetilo.,Tienes las partes de un lanzallamas.,,Poimit liekinheittimen osat.,Vous avez pris les pièces du lance-flames.,Felvetted a lángszóró részeit.,Hai raccolto delle parti di Lanciafiamme.,火炎放射器の部品 入手。,화염방사기 부품을 획득했다.,Je hebt de vlammenwerperonderdelen opgepakt.,Du plukket opp delene til flammekasteren.,Podniosł@[irreg_3_pl] części miotacza ognia.,Você pegou as partes do lança-chamas.,Apanhaste as peças do lança-chamas.,Ai ridicat bucățile aruncătorului de flăcări.,Получены детали для огнемёта.,Покупио си делове за бацач пламена.,Alev silahının parçalarını aldın. -You picked up the report.,TXT_REPORT,,,,Sebral@[ao_cs] jsi hlášení.,Du samlede rapporten op.,Du hast den Report genommen.,,Vi prenis la raporton.,Recogiste el reporte.,,Poimit raportin.,Vous avez pris le compte-rendu.,Felvetted a jelentést.,Hai raccolto il rapporto.,報告書 取得。,보고서를 획득했다.,Je hebt het rapport opgepakt.,Du plukket opp rapporten.,Podniosł@[irreg_3_pl] raport.,Você pegou o relatório.,Apanhaste o relatório.,Ai ridicat raportul.,Получен отчёт.,Покупио си извештај.,Raporu aldın. -You picked up the info.,TXT_INFO,,,,Sebral@[ao_cs] jsi informace.,Du samlede oplysningerne op.,Du hast die Info genommen.,Πήρες της πληροφορίες,Vi prenis la informon.,Recogiste la información.,,Poimit tiedot.,Vous avez pris l'info.,Felvetted az információt.,Hai raccolto delle Informazioni.,情報 取得。,정보를 획득했다.,Je hebt de informatie opgepakt.,Du plukket opp informasjonen.,Podniosł@[irreg_3_pl] informacje.,Você pegou a informação.,Apanhaste a informação.,Ai recepționat informația.,Получена сводка.,Покупио си инфо.,Bilgiyi aldın. -You picked up the Targeter.,TXT_TARGETER,,,,Sebral@[ao_cs] jsi zaměřovač.,Du samlede targeter op.,Du hast die Zielhilfe genommen.,Πήρες τον Στοχευτή.,Vi prenis la Celilon.,Recogiste el apuntador.,,Poimit tähtäinlaitteen.,Vous avez pris le cibleur.,Felvetted a Célzóberendezést.,Hai raccolto il Puntatore.,照準器 入手。,조준기를 획득했다.,Je hebt het Richter opgepakt.,Du plukket opp Targeteren.,Podniosł@[irreg_3_pl] Namierzacz.,Você pegou a Mira.,Apanhaste a Mira.,Ai ridicat Țintitorul.,Получен целеуказатель.,Покупио си нишанитеља.,Hedefleyiciyi aldın. -You picked up the Communicator.,TXT_COMMUNICATOR,,,,Sebral@[ao_cs] jsi komunikátor.,Du samlede kommunikatoren op.,Du hast den Kommunikator genommen.,,Vi prenis la Komunikilon.,Recogiste el comunicador.,,Poimit viestintälaitteen.,Vous avez pris le Communicateur,Felvetted a Kommunikátort,Hai raccolto il Comunicatore.,コミュニケーター 取得。,연락장치를 획득했다.,Je hebt de Communicator opgepakt.,Du plukket opp kommunikatoren.,Podniosł@[irreg_3_pl] Komunikator.,Você pegou o Comunicador.,Apanhaste o Comunicador.,Ai ridicat Comunicatorul.,Получен передатчик.,Покупио си комуникатор.,İletişim cihazını aldın. -You picked up the coin.,TXT_COIN,,,,Sebral@[ao_cs] jsi minci.,Du samlede mønten op.,Du hast die Münze genommen.,Πήρες το κέρμα.,Vi trovis moneron.,Encuentras una moneda.,,Poimit kolikon.,Vous avez pris la pièce.,Felvetted az érmét.,Hai raccolto la Moneta.,コイン 入手。,동전을 주웠다.,Je hebt de munt opgepakt.,Du plukket opp mynten.,Podniosł@[irreg_3_pl] monetę.,Você pegou a moeda.,Apanhaste a moeda.,Ai ridicat moneda.,Получена монета.,Покупио си новчић.,Parayı aldın. -You picked up %d gold.,TXT_XGOLD,,,,Sebral@[ao_cs] jsi %d zlatých.,Du samlede %d guld op.,Du hast %d Gold genommen.,,Vi trovis %d da oro.,Encuentras %d monedas de oro.,,Poimit kultaa %d arvosta.,Vous avez pris %d pièces.,Felvettél %d aranyat.,Hai raccolto %d pezzi d'oro.,%d ゴールド 入手。,골드 %d 개를 획득했다.,Je hebt %d goud opgepakt.,Du plukket opp %d gull.,Podniosł@[irreg_3_pl] %d monet.,Você pegou %d moedas de ouro.,Apanhaste %d moedas de ouro.,Ai ridicat %g bucăți de aur.,Получено %d золотых.,Покупио си %d златника.,%d altın aldın. -You picked up the Teleporter Beacon.,TXT_BEACON,,,,Sebral@[ao_cs] jsi teleportační maják.,Du samlede Teleporter Beacon op.,Du hast das Teleportersignal genommen.,,Vi prenis la Formovilan Signalilon.,Recogiste un faro de teletransportación.,,Poimit kaukosiirrinmajakan.,Vous avez pris la balise de téléporteur.,Felvetted a Teleport jelzőt.,Hai raccolto il Radiofaro per Teletrasporto.,テレポータービーコン 取得。,텔레포터 비콘을 획득했다.,Je hebt de teleporterbaken opgepakt.,Du plukket opp Teleporter-signalet.,Podniosł@[irreg_3_pl] Nadajnik Teleportera.,Você pegou o Sinalizador de Teletransporte.,Apanhaste o Sinalizador de Teletransporte.,Ai ridicat Luminatorul pentru Teleportor.,Получен телепортационный маяк.,Покупио си одашиљач за телепортовање.,Işınlayıcı İşaretini aldın. -You picked up the Degnin Ore.,TXT_DEGNINORE,,,,Sebral@[ao_cs] jsi degninskou rudu.,Du samlede Degnin Ore op.,Du hast das Degnin-Erz genommen.,,Vi prenis la Degninan Ercon.,Recogiste el Mineral Degnin.,,Poimit Degnin-malmia.,Vous avez pris le minerai de Degnin.,Felvetted a Degnin Ércet.,Hai raccolto il Minerale Degnin.,デグニン鉱石 取得。,데그닌 광석을 획득했다.,Je hebt het Degnin-erts opgepakt.,Du plukket opp Degnin-malmen.,Podniosł@[irreg_3_pl] Rudę Degninu.,Você pegou o Minério Degnin.,Apanhaste o Minério Degnin.,Ai ridicat minereul de Degnin.,Получена дегнинская руда.,Покупио си Дегнинску руду.,Degnin Cevherini aldın. -You picked up the scanner.,TXT_SCANNER,,,,Sebral@[ao_cs] jsi skener.,Du samlede scanneren op.,Du hast den Scanner genommen.,Πήρες το σαρωτή.,Vi prenis la skanilon.,Recogiste el escáner.,,Poimit skannerin.,Vous avez pris l'analyseur.,Felvetted a szkennert.,Hai raccolto lo Scanner.,スキャナー 入手。,탐지기를 획득했다.,Je hebt de scanner opgepakt.,Du plukket opp skanneren.,Podniosł@[irreg_3_pl] skaner.,Você pegou o scanner.,Apanhaste o scanner.,Ai ridicat scannerul.,Получен сканер.,Покупио си скенер.,Tarayıcıyı aldın. +această ușă",Для открытия нужен жёлтый ключ,Треба вам жути кључ да би отворили ова врата,Du behöver en gul nyckel för att öppna den här dörren,Bu kapıyı açmak için sarı bir anahtara ihtiyacınız var,"Вам потрібен жовтий ключ, щоб відкрити ці двері" +,,Actor tag names,,,,,,,,,,,,,,,,,,,,,,,,,, +Chicken,FN_CHICKEN,,,,Slepice,Kylling,Huhn,Κότα,Koko,Pollo,,Kana,Poulet,Csirke,Pollo,鶏,닭,Kip,Kylling,Kurczak,Galinha,,Găină,Цыплёнок,Кокошка,Kyckling,Tavuk,Курка +Weredragon,FN_BEAST,Wordplay: werewolf,,,Vlkodrak,Varedrage,Werdrache,Θηρίο,Drakfantomo,Hombre dragón,,Ihmislohikäärme,Dragon-garou,Vérsárkány,Drago Mannaro,ウェア ドラゴン,웨어드래곤,Weerdraak,Vardrage,Smokołak,Homem-dragão,,Vârcodragon,Дракон-оборотень,Змајодлак,Vardrake,Kurt ejderha,Дракон-перевертень +Sabreclaw,FN_CLINK,Wordplay: sabre-tooth,,,Šavlozub,Sabelklo,Säbelklaue,,Sabrokrifo,Garras de sable,,Sapelikynsi,Sabregriffe,Szablyakarom,Lamartiglio,サーベルクロー,세이버클로,Sabelklauw,Sabreklo,Szabloszpon,Unhas-de-sabre,,Gheară de Sabie,Саблекоготь,Тигар,Sabelklo,Kılıçpençe,Шаблекіготь +D'Sparil,FN_DSPARIL,,,,,,,,,,,,,,,デ'スパリル,드'스파릴,,,,,,,Д'Спарил,Д'Спарил,,,Д'Спаріл +Gargoyle,FN_HERETICIMP,,,,Chrlič,,,,Gargojlo,Gárgola,,Gargoili,Gargouille,Vízköpő,,ガーゴイル,가고일,,,Gargulec,Gárgula,,Garguie,Горгулья,Камена утвара,,,Ґарґуйль. +Ironlich,FN_IRONLICH,,,,Železný kostěj,Jern lig,Eiserne Leiche,,Ferliĉo,Liche de hierro,,Rautakalmo,Liche de Fer,Ezüst lich,Lich di Ferro,アイアンリッチ,아이언 리치,IJzeren Lijk,Jernlich,Żelazny Lisz,Lich de Ferro,,Cadavru de Fier,Железный лич,Челични лич,Järnlich,Demir Ceset,Залізний Ліч +Undead Warrior,FN_BONEKNIGHT,,,,Nemrtvý válečník,Udøde Kriger,Untoter Krieger,Αθάνατος Πολεμιστής,Malmortinta Batalisto,Guerrero no muerto,,Epäkuollut soturi,Guerrier Mort-Vivant,Élőhalott harcos,Guerriero Non Morto,アンデット兵,언데드 전사,Ondode Krijger,Udød kriger,Nieumarły wojownik,Guerreiro Morto-vivo,,Războinic Nemort,Воин-нежить,Немртви ратник,Odöd krigare,Ölümsüz Savaşçı,Воїн-нежить +Maulotaur,FN_MINOTAUR,,,,Minotaurus,Maulotaurus,Minotaurus,Μινόταυρος,Bategtaŭro,Mazotauro,,Maulotauri,Massetaure,,Maulotauro,マウロタウロス,몰로타우어,Maulotaurus,Maulotaur,Młototaur,Marretauro,,,Избитавр,Минотаур,Maulotaurus,Maulotor,Молотаур +Golem,FN_MUMMY,,,,Golém,,,,Golemo,Gólem,,,,Gólem,,ゴーレム,골렘,,,,,,,Голем,Голем,,,Голем +Nitrogolem,FN_MUMMYLEADER,,,,Střelgolém,,,,Azotgolemo,Gólem de ázoe,,,,Nitrógólem,,ニトロゴーレム,니트로 골렘,,,,,,,Нитроголем,Нитро голем,,,Нітроголем +Ophidian,FN_SNAKE,,,,Šupinatec,,,,Ofidio,Ofidio,,Käärmeolio,Ophidien,Ofidián,,オフィディアン,오피디안,Ophidiaan,,Wężowaty,Ofídio,,Ofidian,Офидиан,Змија,,,Офідіан +Wizard,FN_WIZARD,,,,Čaroděj,Troldmand,Zauberer,Μάγος,Sorĉisto,Mago,Hechicero,Velho,Magicien,Mágus,Mago,ウィザード,마법사,Tovenaar,Trollmann,Czarownik,Mago,,Vrăjitor,Колдун,Чаробњак,Trollkarl,Sihirbaz,Чаклун +Wand Crystals,AMMO_GOLDWAND,,,,Zlaté krystaly,Stav krystaller,Elfenstabkristalle,,Sorĉbastono-Kristaloj,Cristales para vara,,Sauvakristalleja,Cristaux,Pálca kristályok,Cristalli per la bacchetta,ワンド クリスタル,지팡이 결정,Toverstafkristallen,Tryllestavkrystaller,Kryształy do Różdżki,Cristais para o Cetro,,Cristale pentru Toiag,Кристалл эльфийского жезла,Кристали за штап,Stavkristaller,Değnek Kristalleri,Кристал для жезлу +Ethereal Arrows,AMMO_CROSSBOW,,,,Éterické šípy,Æteriske pile,Ätherische Pfeile,,Eteraj Sagoj,Flechas etéreas,,Eetterinuolia,Carreaux,Éteri nyilak,Frecce eteree,イセリアルの矢,유체 화살,Etherische Pijlen,Eteriske piler,Eteryczne Strzały,Flechas Etéreas,,Săgeți Celeste,Эфирные стрелы,Етеричне стреле,Eteriska pilar,Eterik Oklar,Ефірні стріли +Claw Orbs,AMMO_BLASTER,,,,Pazouří střely,Kugler med kløer,Klauenbälle,,Kriforboj,Orbes de garra,,Kynsikehriä,Orbes,Karom golyók,Sfere di artigli,クロー オーブ,발톱 보주,Klauwbollen,Klo-kuler,Kule do Pazura,Orbes para Garra,,Globuri pentru Gheară,Когтевые шары,Канџаста сфера,Klor bollar,Pençe Küreleri,Кігтьова сфера +Mace Spheres,AMMO_MACE,,,,Žezlometné koule,Kugler til stridskølle,Energiebälle,,Klabsferoj,Esferas de maza,,Nuijakuulia,Sphères,Buzogány gömbök,Sfere per la mazza,メイス スフィア,철퇴 포탄,Strijdknotsen,Ildsted-kuler,Kule do Buzdyganu,Esferas para Clava,,Sfere pentru Buzdugan,Сферы булавы,Сфере за буздован,Eldstötsfärer,Ateş Küreleri,Сфери для булави +Hellstaff Runes,AMMO_SKULLROD,,,,Peklopalné runy,Helvedestav-runer,Höllenrutenrunen,,Inferbastono-Runoj,Runas de Vara Infernal,,Hornansauvan riimuja,Runes,Pokolbot rúnák,Rune infernali,ヘルスタッフ ルーン,룬 조각,Hellestafrunen,Helvetesstav-runer,Runy do Piekielnego Kostura,Runas Infernais,,Rune pentru Bastonul Infernal,Руны посоха ада,Пуне за паклени штап,Runor för helvetesstång,Cehennem Asası Rünleri,Руни пекельного посоху +Flame Orbs,AMMO_PHOENIXROD,,,,Plamenné náboje,Flammekugler,Flammenkugeln,,Flamorboj,Orbes de llama,,Liekkikehriä,Orbes de Feu,Tűzgolyók,Sfere di fuoco,フレイム オーブ,화염 구슬,Vuurballen,Flammekuler,Kule Ognia,Orbes de Chamas,,Globuri de Foc,Пламенные шары,Ватрена сфера,Flamkärnor,Alev Küreleri,Вогняна сфера +Staff,TAG_STAFF,,,,Hole,Stav,Stab,Ράβδος,Bastono,Bastón,,Sauva,Bâton,Bot,Staffa,杖,지팡이,Staf,Stav,Kostur,Bastão,,Baston,Посох,Штап,Stav,Çubuk,Палиця +Elven Wand,TAG_GOLDWAND,,,,Elfí hůlka,Elverstav,Elfenstab,,Elfa Sorĉbastono,Vara de Elfo,,Haltiasauva,Baguette Elfique,Elf pálca,Scettro Elfico,エルフのワンド,엘프 지팡이,Elvenstokje,Alvestav,Elfia Różdżka,Cetro Élfico,,Toiag,Эльфийский жезл,Вилењачки штапић,Elfenstav,Elf Asası,Посох Ельфів +,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,,,, +%o was pecked to death.,OB_CHICKEN,,,,%o byl@[ao_cs] uklován@[ao_cs] k smrti.,%o blev hakket ihjel.,%o wurde zu Tode gepickt.,,%o estis bekita ĝis morto.,A %o l@[ao_esp] han picoteado a muerte.,A %o l@[ao_esp] picotearon a muerte.,%o nokittiin kuoliaaksi.,%o a été picoré@[e_fr] a mort.,%o halálra lett csípve.,%o è stato beccato a morte.,%o はくちばしで突かれ死んだ。,%o 은(는) 쪽팔리게 쪼여 죽었다.,%o werd doodgepikt.,%o ble hakket i hjel.,%o został@[ao_pl] zadzioban@[adj_pl] na śmierć.,%o foi bicad@[ao_ptb] até a morte.,%o foi picad@[ao_ptb] até a morte.,%o a fost ciocănit până la moarte.,Игрок %o заклёван до смерти.,%o је искљуцан@[adj_1_sr] до смрти.,%o blev hackad till döds.,%o gagalanarak öldürüldü.,%o задзьобано до смерті. +%o was charred by a weredragon.,OB_BEAST,,,,%o byl@[ao_cs] spálen@[ao_cs] vlkodrakem.,%o blev forkullet af en varedrage.,%o wurde von dem Werdrachen verschmort.,,%o brulegiĝis de drakfantomo.,A %o l@[ao_esp] ha carbonizado un hombre dragón.,A %o l@[ao_esp] carbonizó un hombre dragón.,%o joutui ihmislohikäärmeen kärventämäksi.,%o a été carbonisé@[e_fr] par un dragon-garou.,%o szénné égett egy Vérsárkány által.,%o è stato carbonizzato da una bestia.,%o はウェアドラゴンに黒焦げにされた。,%o 은(는) 웨어드래곤에 의해 검게 탔다.,%o werd verbrand door een weerdraak.,%o ble forkullet av en vardrage.,%o został@[ao_pl] zwęglon@[adj_pl] przez smokołaka.,%o foi carbonizad@[ao_ptb] por um homem-dragão.,,%o a fost ceruit de un vârcodragon.,Игрок %o обуглен драконом-оборотнем.,%o је реш печен@[adj_1_sr] од стране замјодлака.,%o blev förkolnad av en vardrake.,%o bir kurt ejderha tarafından yakıldı.,%o було спалено драконом-перевертнем. +%o was slashed by a sabreclaw.,OB_CLINK,,,,%o byl@[ao_cs] rozsápán@[ao_cs] šavlozubem.,%o blev skåret op af en sabreklo.,%o wurde von der Säbelklaue zerschlitzt.,,%o tranĉegiĝis de sabrokrifo.,A %o l@[ao_esp] ha cortado un garras de sable.,A %o l@[ao_esp] cortó un garras de sable.,%o joutui sapelikynnen sivaltamaksi.,%o s'est fait découper par un sabregriffe.,%o meg lett vágva egy Szablyakarom által.,%o è stato squarciato da un lapillo.,%o はサーベルクローに切り裂かれた。,%o 은(는) 세이버클로에게 잘렸다.,%o werd door een sabelklauw gesneden.,%o ble kuttet av en sabelklo.,%o został@[ao_pl] posiekan@[adj_pl] przez szabloszpona.,Um Unhas-de-sabre cortou %o.,,%o a fost tăiat de o gheară de sabie.,Игрока %o нарезал саблекоготь.,Играча %o је исекао тигар.,%o blev huggen av en sabelklo.,%o bir kılıç pençe tarafından kesildi.,%o було розсічено шаблекігтем. +%o was scalded by D'Sparil's serpent.,OB_DSPARIL1,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] ořem D'Sparila.,%o blev skoldet af D'Sparils slange.,%o wurde von D'Sparils Schlange verbrüht.,,%o varmegiĝis de la serpento de D'Sparil.,A %o l@[ao_esp] ha carbonizado la serpiente de D'Sparil.,A %o l@[ao_esp] carbonizó la serpiente de D'Sparil.,%o joutui D'Sparilin käärmeen kalttaamaksi.,%o a été ébouillanté@[e_fr] par un serpent de D'Sparil.,%o le lett forrázva D'Sparil Kígyója által.,%o è stato bruciato dal serpente di D'Sparil.,%o はデ'スパリルのサーペントに火傷を負わされた。,%o 은(는) 드'스파릴의 서펜트에 데였다.,%o werd gebroeid door de slang van D'Sparil.,%o ble skåldet av D'Sparils slange.,%o został@[ao_pl] poparzon@[adj_pl] przez węża D'Sparila.,%o foi escaldad@[ao_ptb] pela serpente de D'Sparil.,,%o a fost opărit de șarpele lui D'Sparil.,Игрока %o обжёг змей Д'Спарила.,Играча %o је опекао Д'Спарилова змија.,%o blev skållad av D'Sparils orm.,"%o, D'Sparil'in yılanı tarafından haşlandı.",%o було спалено змієм Д'Спаріла. +%o was chewed up by D'Sparil's serpent.,OB_DSPARIL1HIT,,,,%o byl@[ao_cs] rozkousán@[ao_cs] ořem D'Sparila.,%o blev tygget op af D'Sparils slange.,%o wurde von D'Sparils Schlange verspeist.,,%o maĉegiĝis de la serpento de D'Sparil.,A %o l@[ao_esp] ha engullido la serpiente de D'Sparil.,A %o l@[ao_esp] tragó la serpiente de D'Sparil.,%o joutui D'Sparilin käärmeen pureksimaksi.,%o a été dévoré@[e_fr] par un serpent de D'Sparil.,%o meg lett rágva D'Sparil Kigyója által.,%o è stato masticato dal serpente di D'Sparil.,%o はデ'スパリルのサーペントに噛み砕かれた。,%o 은(는) 드'스파릴의 서펜트에게 씹혔다.,%o werd door de slang van D'Sparil opgekauwd.,%o ble tygd opp av D'Sparils slange.,%o został@[ao_pl] przeżut@[adj_pl] przez węża D'Sparila.,%o foi mastigad@[ao_ptb] pela serpente de D'Sparil.,,%o a fost mestecat de șarpele lui D'Sparil.,Игрока %o пожрал змей Д'Спарила.,%o је сажвакан@[adj_1_sr] од стране Д'Спарилове змије.,%o blev tuggad av D'Sparils orm.,"%o, D'Sparil'in yılanı tarafından çiğnendi.",Змій Д'Спаріла зжер %o . +%o was no match for D'Sparil.,OB_DSPARIL2,,,,%o nebyl@[ao_cs] pro D'Sparila žádná výzva.,%o kunne ikke klare D'Sparil.,%o war kein Gegner für D'Sparil.,,%o ne estis rivalo por D'Sparil. ,%o no era rival para D'Sparil.,,%o ei mahtanut mitään D'Sparilille.,%o n'a pas pu égaler D'Sparil.,%o nem volt méltó ellenfél D'Sparil számára.,%o non era all'altezza di D'Sparil.,%o はデ'スパリルには全く歯が立たなかった。,%o 은(는) 드'스파릴에겐 상대가 되지 못했다.,%o was geen partij voor D'Sparil.,%o var ingen match for D'Sparil.,%o nie miał@[ao_pl] szans z D'Sparilem.,%o não foi páreo para D'Sparil.,%o não foi desafio para D'Sparil.,%o n-a fost nici pe departe pe măsura lui D'Sparil.,Игрок %o был не ровня Д'Спарилу.,%o није ни до колена Д'Спарилу.,%o var ingen match för D'Sparil.,"%o, D'Sparil'in dengi değildi.",%o ніщо проти Д'Спаріла. +%o was smacked down by D'Sparil.,OB_DSPARIL2HIT,,,,%o byl@[ao_cs] sražen@[ao_cs] D'Sparilem.,%o blev slået ned af D'Sparil.,%o wurde von D'Sparil zerklatscht.,,%o frapiĝis de D'Sparil.,A %o l@[ao_esp] ha humillado D'Sparil.,A %o l@[ao_esp] humilló D'Sparil.,%o joutui D'Sparilin löylyttämäksi.,%o a été battu@[e_fr] a plate couture par D'Sparil.,%o a földre lett csapva D'Sparil által.,%o è stato abbattuto da D'Sparil.,%o はデ'スパリルに打ち負かされた。,%o 은(는) 드'스파릴의 맹격에 쓰러졌다.,%o werd neergeslagen door D'Sparil.,%o ble slått ned av D'Sparil.,%o został@[ao_pl] roztrzaskan@[adj_pl] przez D'Sparila,%o foi mort@[ao_ptb] por D'Sparil.,,%o a fost pus la pământ de D'Sparil.,Игрок %o сбит с ног Д'Спарилом.,%o је претучен@[adj_1_sr] од стране Д'Спарила.,%o blev nedslagen av D'Sparil.,"%o, D'Sparil tarafından yere serildi.",Д'Спаріл збив %o. +%o was scarred by a gargoyle.,OB_HERETICIMP,,,,%o byl@[ao_cs] upálen@[ao_cs] chrličem.,%o blev mærket af en gargoyle.,%o wurde von einem Gargoyle zerkratzt.,,%o ĉikartiĝis de gargojlo.,"A %o l@[ao_esp] ha marcado, y no de cicatrices, una gárgola.","A %o l@[ao_esp] marcó, y no de cicatrices, una gárgola.",%o joutui gargoilin arpeuttamaksi.,%o a été effrayé@[e_fr] par une gargouille.,%o meg lett sebesítve egy vízköpő által.,%o è stato terrorizzato da un imp.,%o はガーゴイルに傷を負わされた。,%o 은(는) 가고일에 의해 다쳤다.,%o was getekend door een gargoyle.,%o ble arret av en gargoyle.,%o został@[ao_pl] zadrapan@[adj_pl] przez gargulca,%o foi cicatrizad@[ao_ptb] por uma gárgula.,,%o a fost cicatrizat de o garguie.,Игрока %o изуродовала горгулья.,%o је ожиљкан@[adj_1_sr] од стране камене утваре.,%o blev ärrad av en gargoyle.,%o bir gargoyle tarafından yaralandı.,%o понівечено ґарґуйлем. +%o was hacked by a gargoyle.,OB_HERETICIMPHIT,,,,%o byl@[ao_cs] rozsekán@[ao_cs] chrličem.,%o blev hakket af en gargoyle.,%o wurde von einem Gargoyle zerhackt.,,%o hakiĝis de gargojlo.,A %o l@[ao_esp] ha arañado una gárgola.,A %o l@[ao_esp] arañó una gárgola.,%o joutui gargoilin pilkkomaksi.,%o a été mis@[e_fr] en pièces par une gargouille.,%o fel lett vágva egy vízköpő által.,%o è stato eliminato da un imp.,%o はガーゴイルに切り刻まれた。,%o 은(는) 가고일에 의해 베였다.,%o werd gehackt door een gargoyle.,%o ble hakket av en gargoyle.,%o został@[ao_pl] pocięt@[adj_pl] przez gargulca,%o foi mutilad@[ao_ptb] por uma gárgula.,,%o a fost tăiat de o garguie.,Игрока %o покалечила горгулья.,Играча %o је исекла камена утвара.,%o blev hackad av en gargoyle.,%o bir gargoyle tarafından kesildi.,%o скалічено ґарґуйлем. +%o was devastated by an ironlich.,OB_IRONLICH,,,,%o byl@[ao_cs] zničen@[ao_cs] železným kostějem.,%o blev ødelagt af en jern lig.,%o wurde von der Eisernen Leiche zerstört.,,%o ruiniĝis de ferliĉo.,A %o l@[ao_esp] ha devastado un liche de hierro.,A %o l@[ao_esp] devastó un liche de hierro.,%o joutui rautakalmon hävittämäksi.,%o a été dévasté@[e_fr] par une Liche de Fer.,%o elpusztult egy ezüst lich miatt.,%o è stato devastato da un ironlich.,%o はアイアンリッチに吹き飛ばされた。,%o 은(는) 아이언 리치에게 붕괴 당했다.,%o werd verwoest door een ijzeren lijk.,%o ble knust av en jernlich.,%o został@[ao_pl] zdewastowan@[adj_pl] przez żelaznego lisza,%o foi devastad@[ao_ptb] por um lich de ferro.,,%o a fost devastat de un cadavru de fier.,Игрока %o растоптал железный лич.,%o је уништен@[adj_1_sr] од стране челичног лича.,%o blev förödd av en järnlich,%o demir bir ceset tarafından harap edildi.,%o знищено залізним лічем. +%o got up-close and personal with an ironlich.,OB_IRONLICHHIT,,,,%o se dostal@[ao_cs] moc blízko k železnému kostěji.,%o kom helt tæt på en jern lig.,%o kam der Eisernen Leiche zu nahe.,,%o havis proksiman kaj desonan rekonton kun ferliĉo.,%o ha tenido un encuentro cercano y personal con un liche de hierro.,%o tuvo un encuentro cercano y personal con un liche de hierro.,%o meni lähelle rautakalmoa.,%o a fait ami@[e_fr]-ami@[e_fr] avec une Liche de Fer.,%o közel került és személyes volt egy ezüst lichhel szemben.,%o è andato troppo vicino a un ironlich.,%o はアイアンリッチと密接に関わった。,%o 은(는) 사적인 이유로 아이언 리치에게 다가왔다.,%o werd door een ijzeren lijk onheus bejegend.,%o fikk nærkontakt med en jernlich.,%o był@[ao_pl] blisko i na osobności z żelaznym liszem,%o chegou muito perto de um lich de ferro.,,"%o s-a apropiat prea mult de un +cadavru de fier.",Игрок %o близко и лимно узнал железного лича.,%o се лично приближи@[ao_1_sr] челичном личу.,%o kom nära och personligt med en järnlich.,%o demir bir cesede çok yaklaştı.,%o надто зблизи@[adj_2_ua] з залізним лічем. +%o was axed by an undead warrior.,OB_BONEKNIGHT,,,,%o dostal@[ao_cs] sekyrou od nemrtvého válečníka.,%o blev øksehugget af en udød kriger.,%o wurde von dem Untoten Krieger mit der Axt bearbeitet.,,%o hakiliĝis de malmortinta batalisto.,%o ha recibido un hachazo de un guerrero no muerto.,%o recibió un hachazo de un guerrero no muerto.,%o joutui epäkuolleen soturin kirvestämäksi.,%o s'est pris@[e_fr] la hâche d'un guerrier mort-vivant.,%o baltát kapott egy Élőhalott Harcostól.,%o è stato accettato da un guerriero non morto .,%o はアンデッド兵の斧でやられた。,%o 은(는) 언데드 전사에게 도끼질 당했다.,%o werd doorkliefd door een ondode krijger.,%o ble hugget av en udød kriger.,%o został@[ao_pl] rozłupany siekierą przez nieumarłego wojownika,%o foi decepad@[ao_ptb] por um guerreiro morto-vivo.,%o foi decapitad@[ao_ptb] por um guerreiro morto-vivo.,%o a primit un topor de la un războinic nemort.,Игрока %o зарубил воин-нежить.,%o је исечен@[adj_1_sr] од стане немртвог ратника.,%o blev yxad av en odöd krigare.,%o bir ölümsüz savaşçı tarafından baltalandı.,Воїн-нежить зарубав %o. +%o was slain by an undead warrior.,OB_BONEKNIGHTHIT,,,,%o byl@[ao_cs] zabit@[ao_cs] nemrtvým válečníkem.,%o blev dræbt af en udød kriger.,%o wurde von dem Untoten Krieger hingemetzelt.,,%o estis mortigita de malmortinta batalisto.,A %o l@[ao_esp] ha descuartizado un guerrero no muerto.,A %o l@[ao_esp] descuartizó un guerrero no muerto.,%o joutui epäkuolleen soturin tappamaksi.,%o s'est fait pourfendre par un guerrier mort-vivant.,%o meghalt egy Élőhalott Harcos által.,%o è stato ucciso da un guerriero non morto. ,%o はアンデッド兵の手で葬られた。,%o 은(는) 언데드 전사에게 처단당했다.,%o werd gedood door een ondode krijger.,%o ble drept av en levende død kriger.,%o został@[ao_pl] zgładzon@[adj_pl] przez nieumarłego wojownika,%o foi picotad@[ao_ptb] por um guerreiro morto-vivo.,,%o a fost omorât de un războinic nemort.,Игрока %o сразил воин-нежить.,Играча %o је убио немртви ратник.,%o blev dödad av en odödlig krigare.,%o bir ölümsüz savaşçı tarafından katledildi.,%o бу@[adj_1_ua] повален@[ao_ua] воїном-нежитю. +%o was blasted into cinders by a Maulotaur.,OB_MINOTAUR,,,,%o byl@[ao_cs] rozmetán@[ao_cs] na popel Minotaurem.,%o blev sprængt i aske af en Maulotaurus.,%o wurde von dem Minotaurus in Asche verwandelt.,,%o eksplodiĝis en cindrojn de Bategtaŭro.,A %o l@[ao_esp] ha volado en cenizas un Mazotauro.,A %o l@[ao_esp] voló en cenizas un Mazotauro.,%o tuhottiin tuusan nuuskaksi maulotaurin toimesta.,%o s'est fait@[e_fr] incinérer par un Massetaure.,%o darabokra robbant egy Maulotaurusz által.,%o è stato incenerito da un Maulotauro. ,%o はマウロタウロスに燃やされ炭化した。,%o 은(는) 몰로타우어에게 잿더미가 되도록 파괴당했다.,%o werd door een Maulotaurus tot sintels geblazen.,%o ble sprengt til aske av en Maulotaur.,%o został@[ao_pl] obrócon@[adj_pl] w popiół przez Młototaura,%o foi incinerad@[ao_ptb] por um Marretauro,,%o a fost făcut cenușă de un Maulotaur.,Игрока %o разнёс на угольки Избитавр.,%o је испуцан@[adj_1_sr] у пепео од стране минотаура.,%o blev sprängd till aska av en maulotaurus.,%o bir Maulotor tarafından kül haline getirildi.,%o бу@[adj_1_ua] стерт@[ao_ua] в пил Молотауром. +%o was pulped by a Maulotaur.,OB_MINOTAURHIT,,,,%o byl@[ao_cs] rozmáčknut@[ao_cs] Minotaurem.,%o blev knust af en Maulotaurus.,%o wurde von dem Minotaurus zu Brei verarbeitet.,,%o pulpiĝis de Bategtaŭro.,A %o l@[ao_esp] ha hecho puré un Mazotauro.,A %o l@[ao_esp] hizo puré un Mazotauro.,%o joutui maulotaurin möyhentämäksi.,%o s'est fait@[e_fr] éclater par un Massetaure.,%o péppé lett zúzva egy Maulotaurusz által.,%o è stato ridotto in poltiglia da un Maulotauro. ,%o はマウロタウロスにグシャグシャにされた。,%o 은(는) 몰로타우어에 의해 내동댕이쳐졌다.,%o werd verpulverd door een Maulotaurus.,%o ble knust av en maulotaur.,%o został@[ao_pl] roztart@[adj_pl] na miazgę przez Młototaura,%o foi esmagad@[ao_ptb] por um Marretauro,,%o a fost descojit de un Maulotaur.,Игрока %o превратил в кровавое месиво Избитавр.,Играча %o је претукао минотаур.,%o blev krossad av en maulotaurus.,%o bir Maulotor tarafından ezildi.,Молотаур перетворив %o в криваве місиво. +%o was smashed by a golem.,OB_MUMMY,,,,%o byl@[ao_cs] umlácen@[ao_cs] golémem.,%o blev smadret af en golem.,%o wurde von einem Golem erschlagen.,,%o frakasiĝis de golemo.,A %o l@[ao_esp] ha aplastado un gólem.,A %o l@[ao_esp] aplastó un gólem.,%o joutui golemin murskaamaksi.,%o a été défoncé@[e_fr] par un golem.,%o össze lett törve egy Gólem által.,%o è stato schiacciato da un golem.,%o はゴーレムに叩きのめされた。,%o 은(는) 골렘에게 두들겨 맞았다.,%o werd verbrijzeld door een golem.,%o ble knust av en golem.,%o został@[ao_pl] stłuczon@[adj_pl] przez golema,%o foi esmagad@[ao_ptb] por um golem.,,%o a fost lovit de un golem.,Игрока %o разбил голем.,Играча %o је смрвио голем.,%o blev krossad av en golem.,%o bir golem tarafından parçalandı.,%o потовк голем. +%o was shrieked to death by a nitrogolem.,OB_MUMMYLEADER,,,,%o byl@[ao_cs] ukřičen@[ao_cs] k smrti střelgolémem.,%o blev skriget til døde af en nitrogolem.,%o wurde von einem Nitrogolem zu Tode gekreischt.,,%o estis kriegita ĝis morto de azotgolemo.,A %o le ha chillado a muerte un gólem de ázoe.,A %o le gritó a muerte un gólem de ázoe.,%o kirkaistiin kuoliaaksi nitrogolemin toimesta.,%o s'est fait@[e_fr] percer les tympans par un nitrogolem.,%o halálra lett ijesztve egy Nitrógólem által.,%o è stato stroncato da un golem.,%o はニトロゴーレムに脅かされた。,%o 은(는) 니트로 골렘에 의해 비명횡사 당했다.,%o werd doodgekrijst door een nitrogolem.,%o ble skreket i hjel av en nitrogolem.,%o został@[ao_pl] zakrzyczan@[adj_pl] na śmierć przez nitrogolema,%o agonizou na frente de um nitrogolem.,,%o a fost chiuit până la moarte de un nitrogolem.,Игрока %o убил криком нитроголем.,Играча %o је извриштао до смрти нитроголем.,%o skrek ihjäl av en nitrogolem.,%o bir nitrogolem tarafından çığlık çığlığa öldürüldü.,%o почу@[adj_1_ua] смертельний крик нітроголема. +%o was rattled by an ophidian.,OB_SNAKE,,,,%o byl@[ao_cs] zachřestěn@[ao_cs] šupinatcem.,%o blev rystet af en ophidian.,%o hörte das Klappern des Ophidian.,,%o klakiĝis de ofidio.,A %o l@[ao_esp] ha agitado un ofidio.,A %o l@[ao_esp] sacudió un ofidio.,%o joutui käärmeolion kalkattamaksi.,%o s'est fait@[e_fr] sonner par un ophidien.,%o halálra lett csörgetve egy Ofidián által.,%o è stato stritolato da un serpente.,%o はオフィディアンに動揺した。,%o 은(는) 오피디안에게 흔들렸다.,%o werd gerammeld door een ophidiaan.,%o ble rystet av en ophidian.,%o został@[ao_pl] rozgrzechotan@[adj_pl] przez wężowatego,%o foi sacudid@[ao_ptb] por um ofídio.,,%o a fost bătut până la moarte de un ofidian.,Игрока %o потряс офидиан.,Играча %o је угризла змија.,%o blev skrämd av en ophidian.,%o bir ophidian tarafından sarsıldı.,Офідіан загриз совість %o. +%o was cursed by a wizard.,OB_WIZARD,,,,%o byl@[ao_cs] zaklet@[ao_cs] čarodějem.,%o blev forbandet af en troldmand.,%o wurde von dem Magier verflucht.,,%o malbeniĝis de sorĉisto.,A %o l@[ao_esp] ha maldecido un mago.,A %o l@[ao_esp] maldijo un hechicero.,%o joutui velhon kiroamaksi.,%o a été maudit@[e_fr] par un sorcier.,%o meg lett átkozva egy Varázsló által.,%o è stato maledetto da un mago.,%o はウィザードに呪われた。,%o 은(는) 드'스파릴의 제자에 의해 저주받았다.,%o werd vervloekt door een tovenaar.,%o ble forbannet av en trollmann.,%o został@[ao_pl] przeklęt@[adj_pl] przez czarownika,%o foi amaldiçoad@[ao_ptb] por um mago.,,%o a fost blestemat de un vrăjitor.,Игрока %o проклял колдун.,%o је проклет@[adj_1_sr] од стране чаробњака.,%o blev förbannad av en trollkarl.,%o bir büyücü tarafından lanetlendi.,%o бу@[adj_1_ua] проклят@[ao_ua] чаклуном. +%o was palpated by a wizard.,OB_WIZARDHIT,,,,%o byl@[ao_cs] prozkoumán@[ao_cs] čarodějem.,%o blev palperet af en troldmand.,%o spürte den Hauch des Magiers.,,%o palpatiĝis de sorĉisto.,A %o l@[ao_esp] ha tocado un mago.,A %o l@[ao_esp] tocó un hechicero.,%o joutui velhon tunnustelemaksi.,%o a été palpé@[e_fr] par un sorcier.,%o meg lett tapogatva egy Varázsló által.,%o è stato toccato da un mago.,%o はウィザードに触診されてしまった。,%o 은(는) 드'스파릴의 제자에게 촉진당했다.,%o werd betast door een tovenaar.,%o ble palpert av en trollmann.,%o został@[ao_pl] przebadan@[adj_pl] przez czarownika,%o foi apalpad@[ao_ptb] por um mago.,,%o a fost palpat de un vrăjitor.,Игрока %o пощупал колдун.,Играча %o је палпатирао чаробњак.,%o blev palperad av en trollkarl.,%o bir büyücü tarafından palpe edildi.,Чаклун дослідив внутрішній світ %o. +%o got staffed by %k.,OB_MPSTAFF,,,,%o dostal@[ao_cs] holí od hráče %k.,%o blev stafferet af %k.,%o wurde von %k verprügelt.,,%o bategiĝis de %k.,A %o l@[ao_esp] ha apaleado %k.,A %o l@[ao_esp] apaleó %k.,%k sauvoi %k paran.,%o s'est fait@[e_fr] matraquer par %k.,%o meg lett botozva %k által.,%o è stato preso a colpi di staffa da %k.,%o は %k の棒でぶん殴られた。,%o 은(는) %k 의 지팡이에 제압당했다.,%o kreeg een tik van %k's staf.,%o ble staffet av %k.,%o został@[ao_pl] walnięt@[adj_pl] laską przez %k,%o levou uma sova do bastão de %k.,,%o a fost bastonat de %k.,Игрок %o дополнил посох игрока %k.,%o је претуцан@[adj_1_sr] штапом од стране %k.,%o blev bemannad av %k.,"%o, %k tarafından öldüresiye dövüldü.",%o скуштува@[adj_1_ua] палицю %k. +%o got a shock from %k's gauntlets.,OB_MPGAUNTLETS,,,,%o byl@[ao_cs] prošokován@[ao_cs] rukavicemi hráče %k.,%o fik et chok af %ks handsker.,%o bekam einen Schock von %ks Handschuhen.,,%o recivis ŝokon de la fergantoj de %k.,%o ha recibido un choque de los guanteletes de %k.,%o recibió un choque de los guanteletes de %k.,%o sai sähköiskun pelaajan %k kintaista.,%o s'est pris@[e_fr] un coup de jus des gantelets de %k.,%o kapott egy sokkot %k által.,%o è stato folgorato dai guanti di %k.,%o は %k の篭手からショックを受けた。,%o 은(는) %k 가 쓰고 있는 건틀릿의 전격을 느꼈다.,%o kreeg een schok van %k's handschoenen.,%o fikk støt av %ks hansker.,%o został@[ao_pl] wstrząśnięt@[adj_pl] rękawicami %k,%o tomou um choque das manoplas de %k.,,%o a primit un șoc de la mănușile lui %k.,Игрок %o шокирован перчатками игрока %k.,%o је доби@[ao_1_sr] шок од %k штапа.,%o blev chockad av %ks handskar.,"%o, %k tarafından şoklandı.",%k використа@[adj_1_ua] зворотню дефібриляцію на %o. +%o waved goodbye to %k's elven wand.,OB_MPGOLDWAND,,,,%o zamával@[ao_cs] elfské hůlce hráče %k.,%o vinkede farvel til %ks elverstav.,%o sagte „Tschüß“ zu %ks Elfenstab.,,%o ĝisis al la elfa sorĉbastono de %k.,%o se ha despedido de la vara de elfo de %k.,%o se despidió de la vara de elfo de %k.,%o heilutti hyvästit pelaajan %k haltiasauvalle.,%o à fait coucou à la baguette magique de %k.,%o integetett egy viszlátot %k Elf Pálcájának.,%o ha fatto ciao ciao allo scettro elfico di %k.,%o は %k のエルフのワンドに別れの挨拶をした。,%o 은(는) %k 의 엘프 지팡이를 보고 작별인사를 했다.,%o zwaaide afscheid van %k's elvenstaf.,%o vinket farvel til %ks alvestav.,%o pomachał@[ao_pl] na do widzenia elfiej różdżce %k,%o deu tchauzinho para o cetro élfico de %k.,%o disse adeuzinho para o cetro élfico de %k.,%o a facut cu mână toiagului lui %k.,Игрок %o узрел прощальный взмах эльфийского жезла игрока %k.,%o је рек@[ao_2_sr] збогом %k вилењачком штапићу.,%o vinkade farväl till %ks elviga stav.,"%o, %k tarafından delik deşik edildi.",%k помаха@[adj_1_ua] ельфійським посохом на прощання %o. +%o was pegged by %k's ethereal crossbow.,OB_MPCROSSBOW,,,,%o byl@[ao_cs] prostřelen@[ao_cs] éterickou kuší hráče %k.,%o blev stukket af %ks æteriske armbrøst.,%o von %ks Armbrustbolzen aufgespießt.,,%o kejlis de la etera arbalesto de %k.,A %o l@[ao_esp] ha flechado la ballesta etérea de %k.,A %o l@[ao_esp] flechó la ballesta etérea de %k.,%k ripusti %o paran eteerivarsijousellaan.,%o s'est fait@[e_fr] clouer par l'arbalète étherique de %k.,%o fel lett rögzítve %k Éteri Nyílpuskájának által.,%o è stato inchiodato dalla balestra eterea di %k.,%o は %k のイセリアルクロスボウで釘付けにされた。,%o 은(는) %k 의 유체 쇠뇌에 의해 처박혔다.,%o was vastgepind door %k's etherische kruisboog.,%o ble truffet av %ks eteriske armbrøst.,%o został@[ao_pl] przebit@[adj_pl] przez eteryczną kuszę %k,%o foi esmigalhad@[ao_ptb] pela besta etérea de %k.,,%o a fost prins de arbaleta celestă a lui %k.,Игрок %o изранен болтами эфирного арбалета игрока %k.,%o је упуц@[adj_2_sr] од стране %k етералног самострела.,%o blev fast av %ks eteriska armborst.,"%o, %k tarafından çivilendi.",%k насипа@[adj_1_ua] %o трохи магічних болтів. +%o was blasted a new one by %k's dragon claw.,OB_MPBLASTER,,,,%o poznal@[ao_cs] středověk drakospárem hráče %k.,%o blev sprængt en ny af %ks drageklo.,%o bekam %ks Drachenklaue zu spüren.,,%o estis diseksplodita de la drakokrifo de %k.,%o ha quedado bien jodid@[ao_esp] por la garra de dragón de %k.,%o quedó irreconocible por la garra de dragón de %k.,%k puhkoi %o parkaan uuden aukon lohikäärmeenkynnellään.,%o s'est fait flinguer par la griffe draconique de %k.,%o újszerűnek látszik %k Sárkány Karomjának köszönhetően.,A %o èstato aperto un buco nuovo dall'Artiglio di Drago di %k.,%o は %k のドラゴンクローで発破体験した。,%o 은(는) %k 의 용발톱에 의해 형태를 잃었다.,%o werd opengescheurd door %k's drakenklauw.,%o fikk en ny en av %ks drageklo.,%o został wysadzony nowy otwór przez %k,%o sentiu o poder da garra de dragão de %k.,,%o a fost aruncat în aer de gheara dragonului a lui %k.,Игрок %o получил новую форму драконьим когтем игрока %k.,Играчу %o је отворена нова рупа змајевском канџом играча %k.,%o blev skjuten på nytt av %ks drakklo.,"%o, %k tarafından patlatıldı.",%o отрима@[adj_1_ua] кігтедраконових вибухів від %k. +%o got sent down under by %k's hellstaff.,OB_MPSKULLROD,,,,Pod hráčem %o se propadla zem peklopalem hráče %k.,%o blev sendt ned under jorden af %ks helvedestav.,%o brach unter %ks Höllenrute zusammen.,,%o forsendiĝis sub de la inferbastono de %k.,%o se ha inclinado ante el bastón infernal de %k.,%o se inclinó ante el bastón infernal de %k.,%k lähetti %o paran maan syövereihin hornansauvallaan.,%o repose six pieds sous terre grâce au Bâton infernal de %k.,%o le lett küldve %k Pokolbotjának köszönhetően.,%o è stato mandato sottoterra dalla Staffa Infernale di %k.,%o は %k のヘルスタッフで冥界に送られた。,%o 은(는) %k 의 지옥지팡이에 의해 저승으로 날아갔다.,%o werd door %k's hellestaf naar beneden gestuurd.,%o ble sendt til helvete av %ks helvetesstav.,%o został@[ao_pl] zesłan@[adj_pl] pod piekielny kostur %k,%o foi mandad@[ao_ptb] pra baixo do solo pelo cajado infernal de %k.,,%o a fost trimis sub bastonul infernal al lui %k.,Игрок %o сослан в самый низ посохом ада игрока %k.,%o је укопан@[adj_1_sr] од стране пакленог штапа играча %k.,%o blev nedskjuten av %ks helvetesstång.,"%o, %k tarafından biçildi.",%o па@[adj_1_ua] в самі глибини від пекельного посоху %k. +%o was scorched to cinders by %k's phoenix rod.,OB_MPPHOENIXROD,,,,%o byl@[ao_cs] spálen@[ao_cs] na prach fénixovou holí hráče %k.,%o blev brændt til aske af %ks føniksstav.,%o wurde voin %ks Phönixstab verschmort.,,%o brulegiĝis en cindrojn de la feniksvergo de %k.,A %o l@[ao_esp] ha pulverizado el báculo del Fénix de %k.,A %o l@[ao_esp] pulverizó el báculo del Fénix de %k.,%k kärvensi %o paran tuhannen päreiksi feenikssauvallaan.,%o s'est fait@[e_fr] réduire en cendres par le Bâton du Phénix de %k.,%o halomra lett égve %k Főnix Rúdjának által.,%o è stato ridotto in cenere dal Bastone della Fenice di %k.,%o は %k のフェニックスロッドで焼かれた。,%o 은(는) %k 의 불사조 지팡이 덕에 검게 익었다.,%o werd door %k's feniksstaf tot sintels verschroeid.,%o ble svidd til aske av %ks føniksstav.,%o został@[ao_pl] spalon@[adj_pl] na popiół przez różdżkę feniksa %k,%o virou cinzas com o bastão da fênix de %k.,,%o a fost făcut cenușă de joarda phoenix a lui %k.,Игрок %o сожжён до пепла жезлом феникса игрока %k.,%o запаљен@[adj_1_sr] у пепео од стране шипке феникса играча %k.,%o blev bränd till aska av %ks fenixstav.,"%o, %k tarafından cayır cayır yakıldı.",Від %o залишився тільки попіл через жезл фенікса %k. +%o was bounced by %k's firemace.,OB_MPMACE,,,,%o byl@[ao_cs] odpálen@[ao_cs] žezlometem hráče %k.,%o blev kastet afsted af %ks ildspyd.,%o prallte an %ks Feuerkeule ab.,,%o estis resaltita de la fajroklabo de %k.,%o ha rebotado en la maza de fuego de %k.,%o rebotó en la maza de fuego de %k.,%k pomputti %o parkaa tulinuijallaan.,%o a rebondi@[e_fr] sur les balles de la Masse de Feu à %k.,%o pattant egy nagyot %k Tűzbuzogányának köszönhetően.,%o è stato spazzato via dalla Mazza del Fuoco di %k.,%o は %k のファイアメイスで飛ばされた。,%o 은(는) %k 의 투사철퇴의 포탄을 맞고 튕겨져 날아갔다.,%o werd door %k's vuurknots geraakt.,%o ble kastet av %ks ildkule.,%o został@[ao_pl] wybit@[adj_pl] przez buzdygan ognia %k,%o saiu pulando após ver a clava de fogo de %k.,,%o a fost aruncat de colo colo de buzduganul de foc al lui %k.,Игрок %o отбит огненной булавой игрока %k.,%o је ударен@[adj_1_sr] са ватреним буздованом играча %k.,%o blev utvisad av %ks eldstöt,"%o, %k tarafından ezildi.",%o вбили в землю вогняною булавою %k. +%o got clapped by %k's charged staff.,OB_MPPSTAFF,,,,%o byl@[ao_cs] profackován@[ao_cs] nabitou holí hráče %k.,%o blev klappet af %ks ladede stav.,%o bekam eine Klatsche durch %ks geladenen Stab.,,%o estis aplaŭdita de la ŝargita bastono de %k.,A %o l@[ao_esp] ha apaleado el bastón cargado de %k .,A %o l@[ao_esp] apaleó el bastón cargado de %k .,%k jyrisytti %o parkaa varatulla sauvallaan.,%o à été foudroyé@[e_fr] par le bâton chargé de %k.,%o csattant egy nagyot %k Feltöltött Botjának által.,%o è scoppiato a causa della staffa incantata di %k.,%o は %k の魔力を帯びた棒で暖かく迎えられた。,%o 은(는) %k 의 마법부가 지팡이를 얻어맞았다.,%o kreeg een klap van %k's opgeladen staf.,%o ble klappet av %ks ladede stav.,%o został@[ao_pl] trzepnięt@[adj_pl] naładowaną laską %k,%o tomou uma pancada do bastão carregado de %k.,,%o a fost tăiat de bastonul încărcat al lui %k.,Игрок %o отведал заряженного посоха игрока %k.,%o је потапшан@[adj_1_sr] напуњеним штапом играча %k.,%o fick en klapp av %ks laddade stav.,"%o, %k tarafından yakıldı.",%o перечепи@[adj_2_ua] через заряджену палицю %k. +%o was bled dry by %k's gauntlets.,OB_MPPGAUNTLETS,,,,Rukavicemi hráče %k nezůstala v těle hráče %o ani kapka krve.,%o blev udblødt af %ks handsker.,%o wurde von %ks Handschuhen ausgeblutet.,,%o sensangiĝis de la fergantoj de %k.,A %o l@[ao_esp] han dejado exangüe los guanteletes de %k.,A %o l@[ao_esp] dejaron exangüe los guanteletes de %k.,%k vuodatti %o paran kuiviin kintaillaan.,%o s'est fait@[e_fr] saigner à blanc par les gantelets de %k.,%k megtanította %o-t Páncélkesztyűbe dudálni.,Il sangue di %o è stato prosciugato dai guanti di %k.,%o は %k の篭手で血を絞り取られた。,%o 은(는) %k 의 마법부가 건틀릿에 의해 바싹 말랐다.,%o werd leeggebloed door %k's handschoenen.,%o ble tappet for blod av %ks hansker.,%o wykrwawił@[ao_pl] się przez rękawice %k,%o sangrou nas manoplas de %k.,,"%o a fost stors până la ultima picătură de sânge +de mănușile lui %k.",Игрок %o был обескровлен перчатками игрока %k.,%o је путпуно искрвари@[ao_1_sr] од рукавица играча %k.,%o blev blödd av %ks handskar.,"%o, %k tarafından kan kaybından kurutuldu.",%k висмокта@[adj_1_ua] дух %o через рукавиці. +%o was assaulted by %k's elven wand.,OB_MPPGOLDWAND,,,,%o byl@[ao_cs] napaden@[ao_cs] elfskou hůlkou hráče %k.,%o blev overfaldet af %ks elverstav.,%o wurde von %ks Elfenstab überwältigt.,,%o atakiĝis de la elfa sorĉbastono de %k.,%o ha sido asaltad@[ao_esp] por la vara de elfo de %k.,%o fue asaltad@[ao_esp] por la vara de elfo de %k.,%o joutui pelaajan %k haltiasauvan pahoinpitelemäksi.,%o à été assailli@[e_fr] par la baguette elfique de %k.,%k megbotozta %o az Elf Botjával.,%o è stato assalito dallo Scettro Elfico di %k.,%o は %k のエルフのワンドで襲われた。,%o 은(는) %k 의 마법부가 엘프 지팡이에 의해 사냥당했다.,%o werd aangevallen door %k's elvenstaf.,%o ble angrepet av %ks alvestav.,%o został@[ao_pl] zaatakowan@[adj_pl] przez elfią różdżkę %k,%o foi atacad@[ao_ptb] pelo cetro élfico de %k.,,%o a fost luat cu asalt de togaiul lui %k.,Игрок %o атакован эльфийским жезлом игрока %k.,%o је нападнут@[adj_1_sr] вилењачким штапом играча %k.,%o blev attackerad av %ks älvstav.,"%o, %k tarafından saldırıya uğradı.",%o бу@[adj_1_ua] атакований ельфійським посохом %k. +%o was shafted by %k's ethereal crossbow.,OB_MPPCROSSBOW,,,,%o byl@[ao_cs] proděravěn@[ao_cs] éterickou kuší hráče %k.,%o blev ramt af %ks æteriske armbrøst.,%o wurde von %ks Armbrustbolzen durchbohrt.,,%o akiris novan truon de etera arbalesto de %k.,%o ha sido encañonad@[ao_esp] por la ballesta etérea de %k.,%o fue encañonad@[ao_esp] por la ballesta etérea de %k.,%k joutui pelaajan %k eteerivarsijousen kepittämäksi.,%o s'est fait@[e_fr] transpercer par l'arbalète éthérique de %k.,%o megkóstolta %k Éteri Nyílpuskáját.,%o è stato impalato dalla balestra eterea di %k.,%o は %k のイセリアルクロスボウで押された。,%o 은(는) %k 의 마법부가 유체 쇠뇌에 의해 무뎌졌다.,%o werd door %k's etherische kruisboog geschaafd.,%o ble truffet av %ks eteriske armbrøst.,%o został@[ao_pl] wykiwan@[adj_pl] przez eteryczną kuszę %k,%o foi flechad@[ao_ptb] pela besta etérea de %k.,,"%o a fost pus la proțap de arbaleta celestă a lui +%k.",Игрок %o пробит эфирным арбалетом игрока %k.,%o је упуцан@[adj_1_sr] етеричним самострелом играча %k.,%o blev skjuten av %ks eteriska armborst.,"%o, %k tarafından şaftlandı.",%k проби@[adj_1_ua] %o магічним болтом. +%o was ripped apart by %k's dragon claw.,OB_MPPBLASTER,,,,%o byl@[ao_cs] roztrhnut@[ao_cs] naskrz drakospárem hráče %k.,%o blev flået i stykker af %ks drageklo.,%o wurde von der Drachenklaue zerrissen.,,%o disrompiĝis de la drakokrifo de %k.,A %o l@[ao_esp] ha desgarrado la garra de dragón de %k.,A %o l@[ao_esp] desgarró la garra de dragón de %k.,%k repi %o paran kappaleiksi lohikäärmeenkynnellään.,%o à été mis@[e_fr] en pièces par la griffe draconique de %k.,%o szét lett tépve %k Sárkány Karomja által.,%è stato fatto a brandelli dall'Artiglio di Drago di %k.,%o は %k のドラゴンの鉤爪でバラバラに引き裂かれた。,%o 은(는) %k 의 마법부가 용발톱에 갈기갈기 찢겨졌다.,%o werd uit elkaar gescheurd door %k's drakenklauw.,%o ble revet i filler av %ks drageklo.,%o został@[ao_pl] rozerwan@[adj_pl] przez smoczy pazur %k,%o foi cortad@[ao_ptb] pela garra de dragão de %k.,,%k a fost făcut bucăți de gheara lui %k.,Игрок %o разорван драконьим когтём игрока %k.,%o је поцепан@[adj_1_sr] змајевим канџама играча %k.,%o blev sliten i bitar av %ks drakklo.,"%o, %k tarafından parçalara ayrıldı.",%o розірвало кігтем дракона %k. +%k poured the hellstaff on %o.,OB_MPPSKULLROD,,,,Hráč %k vylil svůj peklopal na hráče %o.,%k hældte helvedesstaven ud over %o.,%k ließ den Höllenregen auf %o los.,,%k ŝutas la inferbastonon sur %o.,%k ha vertido su bastón infernal en %o.,%k vertió su bastón infernal en %o.,%k vuodatti hornansauvansa %o parkaan.,%k à versé toute la rage des enfers sur %o.,%o nem hozott esernyőt %o Pokolbot zápora ellen.,%k ha fatto sgorgare la sua Staffa Infernale su %o.,%o は %k にヘルスタッフを %p 注ぎ込まれた。,%k의 마법부가 지옥지팡이가 쏟아붓는 비를 %o 이(가) 맞았다.,%k liet de helregen los op %o.,%k helte helvetesstaven over %o.,%k polał@[ao_pl] swoim piekielnym kosturem %o,%k usou seu cajado infernal no %o.,,%k a vărsat bastonul infernal pe %o.,Игрок %k залил игрока %o горячим дождём при помощи посоха ада.,%k је просипа@[ao_1_sr] пламени штап на %o.,%k hällde helvetesstången på %o.,"%o, %k tarafından yakıldı.",%k залив %o пекельним дощем. +%o was burned down by %k's phoenix staff.,OB_MPPPHOENIXROD,,,,%o byl@[ao_cs] vyhořen@[ao_cs] fénixovou holí hráče %k.,%o blev brændt ned af %ks Føniks stav.,%o wurde von %ks Phönixstab verbrannt.,,%o torĉiĝis de la feniksvergo de %k.,A %o l@[ao_esp] ha calcinado el báculo del Fénix de %k.,A %o l@[ao_esp] calcinó el báculo del Fénix de %k.,%k poltti %o paran feenikssauvallaan.,%o à été incinéré@[e_fr] par le Bâton du Phénix de %k.,%o elégett %k Főnix Botjának által.,%o è stato incendiato dal Bastone della Fenice di %k.,%o は %k のフェニックスロッドで焼き滅ぼされた。,%o 은(는) %k 의 마법부가 불사조 지팡이에 의해 화장당했다.,%o werd afgebrand door %k's feniksstaf.,%o ble brent ned av %ks føniksstav.,%o został@[ao_pl] spalon@[adj_pl] przez różdżkę feniksa %k,%o foi queimad@[ao_ptb] pelo bastão da fênix de %k.,,%o a fost ars complet de joarda lui %k.,Игрок %o сожжён жезлом феникса игрока %k.,%o је изгоре@[ao_1_sr] шипком феникса играча %k.,%o brändes ner av %ks Fenix-stav.,"%o, %k tarafından yakıldı.",%o згорі@[adj_1_ua] через жезл фенікса %k. +%o was squished by %k's giant mace sphere.,OB_MPPMACE,,,,%o byl@[ao_cs] rozmačkán@[ao_cs] obrovskou žezlometnou koulí hráče %k.,%o blev mast af %ks ildspyd kugle.,%o wurde von %ks Feuerkeule zerquetscht.,,%o premiĝis de la grandega klubsfero de %k.,A %o l@[ao_esp] ha aplastado una esfera gigante de la maza de %k.,A %o l@[ao_esp] aplastó una esfera gigante de la maza de %k.,%k liiskasi %o paran jättiläisnuijapallollaan.,%o s'est fait@[e_fr] écraser par la balle de Masse géante de %k.,%o össze lett nyomva %k hatalmas buzogány gömbje által.,%o è stato spiaccicato da una sfera gigante della Mazza del Fuoco di %k.,%o は %k の巨大なメイススフィアで潰された。,%o 은(는) %k 의 마법부가 투사철퇴가 뿜은 거대포탄에 의해 납작해졌다.,%o werd verpletterd door %k's reusachtige strijdknots.,%o ble knust av %ks gigantiske muskatblomstkule.,%o został@[ao_pl] zmiażdżon@[adj_pl] przez ogromną kulę z buzdygana %k,%o foi esmagad@[ao_ptb] pela esfera de clava gigante de %k.,,"%o a fost strivit de globul buzduganului +lui %k.",Игрок %o раздавлен огромной сферой из огненной булавы %k.,%o је смрвљен@[adj_1_sr] од стане огромном сферско буздована играча %k.,%o blev mosad av %ks gigantiska eldstötsfär.,"%o, %k tarafından ezildi.",%k розчави@[adj_1_ua] %o велитенською вогняною сферою. +,,Hexen,,,,,,,,,,,,,,,,,,,,,,,,,, +,,Pickup,,,,,,,,,,,,,,,,,,,,,,,,,, +Blue Mana,TXT_MANA_1,,,,Modrá mana,Blå Mana,Blaues Mana,,Blua Manao,Maná Azul,,Sininen mana,Mana Bleu,Kék Mana,Mana blu,青マナ,청색 마나,Blauwe Mana,Blå Mana,Niebieska Mana,Mana Azul,,Mană Albastră,Синяя мана,Плава мана,Blå Mana,Mavi Mana,Синя мана +Green Mana,TXT_MANA_2,,,,Zelená mana,Grøn Mana,Grünes Mana,,Verda Manao,Maná Verde,,Vihreä mana,Mana Vert,Zöld Mana,Mana verde,緑マナ,녹색 마나,Groene Mana,Grønn Mana,Zielona Mana,Mana Verde,,Mană Verde,Зелёная мана,Зелена мана,Grön Mana,Yeşil Mana,Зелена мана +Combined Mana,TXT_MANA_BOTH,,,,Smíšená mana,Kombineret Mana,Kombiniertes Mana,,Kuna Manao,Maná Combinado,,Yhdistetty mana,Mana Combiné,Kombinált Mana,Mana misto,複合マナ,윰합된 마나,Gecombineerde Mana,Kombinert mana,Połączona Mana,Mana Combinado,,Mană Mixtă,Общая мана,Комбинована мана,Kombinerad Mana,Kombine Mana,Комбінована мана +Steel Key,TXT_KEY_STEEL,,,,Ocelový klíč,Stålnøgle,Stahlschlüssel,Ατσάλινο Κλειδί,Ŝtala Ŝlosilo,Llave de Acero,,Teräsavain,Clé d'Acier,Acél Kulcs,Chiave d'acciaio,鋼の鍵,강철 열쇠,Stalen Sleutel,Stålnøkkel,Stalowy Klucz,Chave de Aço,,Cheia din Oțel,Стальной ключ,Челични кључ,Stålnyckel,Çelik Anahtar,Сталевий ключ +Cave Key,TXT_KEY_CAVE,,,,Klíč od jeskyně,Hule-nøgle,Höhlenschlüssel,,Kavern-Ŝlosilo,Llave de la Caverna,,Luola-avain,Clé de la Cave,Barlang Kulcs,Chiave della caverna,洞窟の鍵,동굴 열쇠,Grotsleutel,Hulenøkkel,Klucz do Jaskini,Chave da Caverna,,Cheia Peșterii,Пещерный ключ,Пећински кључ,Grottnyckel,Mağara Anahtarı,Печерний ключ +Axe Key,TXT_KEY_AXE,,,,Sekyrový klíč,Økse-nøgle,Axtschlüssel,,Hakil-Ŝlosilo,Llave de Hacha,,Kirvesavain,Clé de la Hache,Fejsze Kulcs,Chiave dell'ascia,斧の鍵,도끼 열쇠,Bijlsleutel,Økse-nøkkel,Klucz-topór,Chave do Machado,,Cheia Topor,Топор-ключ,Кључ секира,Yxnyckel,Balta Anahtarı,Сокирний ключ +Fire Key,TXT_KEY_FIRE,,,,Ohnivý klíč,Ild-nøgle,Feuerschlüssel,,Fajro-Ŝlosilo,Llave de Fuego,,Tuliavain,Clé du Feu,Tűz Kulcs,Chiave del fuoco,炎の鍵,불 열쇠,Vuursleutel,Ildnøkkel,Ognisty Klucz,Chave do Fogo,,Cheia de Foc,Огненный ключ,Огњени кључ,Eldnyckel,Yangın Anahtarı,Вогняний ключ +Emerald Key,TXT_KEY_EMERALD,,,,Smaragdový klíč,Smaragdnøgle,Smaragdschlüssel,,Smerelda Ŝlosilo,Llave Esmeralda,,Smaragdiavain,Clé d'Emeraude,Smaragd Kulcs,Chiave di smeraldo,翠玉の鍵,에메랄드 열쇠,Smaragden Sleutel,Smaragdnøkkel,Szmaragdowy Klucz,Chave de Esmeralda,,Cheia din Smarald,Изумрудный ключ,Смарагдни кључ,Smaragdnyckel,Zümrüt Anahtar,Смарагдовий ключ +Dungeon Key,TXT_KEY_DUNGEON,,,,Klíč od žaláře,Dungeon-nøgle,Kerkerschlüssel,,Karcer-Ŝlosilo,Llave del Calabozo,,Tyrmän avain,Clé du Donjon,Várbörtön Kulcs,Chiave del sotterraneo,迷宮の鍵,지하감옥 열쇠,Kerkersleutel,Dungeon-nøkkel,Klucz do Lochu,Chave da Masmorra,,Cheia Temniței,Ключ от подземелья,Кључ од лагума,Kerker-nyckel,Zindan Anahtarı,Ключ від підземелля +Silver Key,TXT_KEY_SILVER,,,,Stříbrný klíč,Sølvnøgle,Silberschlüssel,Ασυμένιο Κλειδί,Arĝenta Ŝlosilo,Llave de Plata,,Hopea-avain,Clé d'Argent,Ezüst Kulcs,Chiave d'argento,銀の鍵,은 열쇠,Zilveren Sleutel,Sølvnøkkel,Srebrny Klucz,Chave de Prata,,Cheia din Argint,Серебряный ключ,Сребрни кључ,Silvernyckel,Gümüş Anahtar,Срібний ключ +Rusted Key,TXT_KEY_RUSTED,,,,Zrezivělý klíč,Rustet nøgle,Rostiger Schlüssel,Σκουριασμένο Κλειδί,Rusta Ŝlosilo,Llave Oxidada,,Ruosteinen avain,Clé Rouillée,Rozsdás Kulcs,Chiave arrugginita,錆びた鍵,녹슨 열쇠,Geroeste Sleutel,Rustet nøkkel,Zardzewiały Klucz,Chave Enferrujada,,Cheia Ruginită,Ржавый ключ,Зарђали кључ,Rostad nyckel,Paslı Anahtar,Іржавий ключ +Horn Key,TXT_KEY_HORN,,,,Parožní klíč,Hornnøgle,Hornschlüssel,,Hup-Ŝlosilo,Llave de Cuerno,,Sarviavain,Clé Corne,Szarv Kulcs,Chiave del corno,角の鍵,뿔 열쇠,Hoornsleutel,Horn-nøkkel,Rogowy Klucz,Chave do Chifre,,Cheia Corn,Роговой ключ,Рогати кључ,Horn-nyckel,Korna Anahtarı,Ріговий ключ +Swamp Key,TXT_KEY_SWAMP,,,,Klíč od bažiny,Sumpnøgle,Sumpfschlüssel,,Marĉo-Ŝlosilo,Llave del Pantano,,Suoavain,Clé des Marécages,Mocsár Kulcs,Chiave della palude,沼の鍵,늪지대 열쇠,Moerassleutel,Sumpnøkkel,Bagienny Klucz,Chave do Pântano,,Cheia Mlaștinii,Болотный ключ,Мочварни кључ,Träsknyckel,Bataklık Anahtarı,Болотний ключ +Castle Key,TXT_KEY_CASTLE,,,,Klíč od hradu,Slotsnøgle,Burgschlüssel,,Kastel-Ŝlosilo,Llave del Castillo,,Linnan avain,Clé du Château,Kastély Kulcs,Chiave del castello,城の鍵,성 열쇠,Kasteelsleutel,Slottsnøkkel,Klucz do Zamku,Chave do Castelo,,Cheia Castelului,Ключ от замка,Кључ од замка,Slottsnyckel,Kale Anahtarı,Ключ від фортеці +Icon of the Defender,TXT_ARTIINVULNERABILITY2,,,,Obráncova ikona,Ikon af forsvareren,Ikone des Verteidigers,,Ikono de la Defendanto,Icono del Defensor,Ícono del Defensor,Puolustajan ikoni,Icône du Défenseur,Védelmező Ikonja,Icona del difensore,守護者の像,수호의 성상,Symbool van de Verdediger,Forsvarerens ikon,Ikona Obrońcy,Ícone do Defensor,,Imaginea Apărătorului,Символ защитника,Симбол браниоца,Försvararens ikon,Savunucunun Simgesi,Символ захисника +Dark Servant,TXT_ARTISUMMON,,,,Temný služebník,Mørk tjener,Dunkler Diener,,Malluma Servanto,Sirviente Oscuro,,Pimeä palvelija,Serviteur Noir,Árny Szolga,Servitore oscuro,闇の従者,어둠의 하인,Donkere Dienaar,Mørk tjener,Mroczny Sługa,Servo Negro,,Servitor Întunecat,Тёмный слуга,Мрачни слуга,Mörk tjänare,Karanlık Hizmetkar,Темний слуга +Porkalator,TXT_ARTIEGG2,,,,Vepřovitel,,,,Porkigilo,Porcinador,,Sikaannuttaja,Porcificateur,Ártányátok,Porchificatore,ポークレイター,돈육기,,,Schabowator,Porquificador,,Porcolator,Свиновизатор,Свињатор,,,Захрюкувач +Flechette,TXT_ARTIPOISONBAG,,,,Střelka,,,,Flakono,,,,Fléchette,Flakon,Fiaschetta,フレチェット,플레셰트,,,Flaszka,,,Flacon,Флешетта,Бочица,,,Флешета +Banishment Device,TXT_ARTITELEPORTOTHER,,,,Vyhošťovač,Forvisningsanordning,Verbannungsgerät,,Forpelilo,Dispositivo de Desvanecimiento,,Häivytyskoje,Outil de Banissement,Száműző,Artifatto dell'esilio,追放のデバイス,소멸 장치,Verbanningsapparaat,Forvisningsanordning,Urządzenie Wygnania ,Dispositivo do Banimento,,Dispozitiv al Alungării,Устройство изгнания,Амблем прогањања,Förvisningsenhet,Sürgün Cihazı,Пристрій заслання +Boots of Speed,TXT_ARTISPEED,,,,Běhuté boty,Støvler af hastighed,Turbo-Stiefel,,Botoj de Rapideco,Botas de Velocidad,,Ripeyssaappaat,Bottes de Célérité,Sebesség Cipője,Stivali della velocità,素早さの靴,속도의 신발,Snelheidslaarzen,Støvler av fart,Buty Szybkości,Botas da Velocidade,,Bocancii Vitezei,Сапоги-скороходы,Брзинске чизме,Snabbhetens stövlar,Hız Çizmeleri,Семимильні чоботи +Krater of Might,TXT_ARTIBOOSTMANA,,,,Kalich síly,Krater of Might,Kelch der Macht,,Kratero de Potenco,Vasija de Fuerza,,Mahtikrateeri,Cratère de Pouvoir,Hatalom Krátere,Calice della forza,魔力の盃,힘의 향로,Beker van Macht,Krater av makt,Czara mocy,Cálice do Poder,,Pocal al Puterii,Чаша могущества,Чаша силе,Mäktighetens krater,Kudret Krateri,Чаша міці +Dragonskin Bracers,TXT_ARTIBOOSTARMOR,,,,Dračí nátepníky,Drageskindsarmbøjler,Drachenhaut-Armschutz,,Brakbendo el Drakhaŭto,Brazaletes de piel de Dragón,,Lohikäärmeennahkarannesuojat,Bracelets en Peau de Dragon,Sárkánybőr Karkötők,Bracciali in pelle di drago,竜皮の小手,용가죽 팔찌,Drakenhuidbescherming,Dragehud-bindinger,Karwasze ze Smoczej Skóry,Braçadeiras de Pele de Dragão,,Brățări din Piele de Dragon,Наручи из драконьей кожи,Наруквице од змајеве коже,Drakskinnsarmbågar,Ejderha Derisi Bilezikler,Наручі зі шкіри дракона +Disc of Repulsion,TXT_ARTIBLASTRADIUS,,,,Kotouč odpuzení,Skive af frastødning,Rückstoßscheibe,,Disko de Repelado,Disco de Repulsión,,Karkotuskiekko,Disque de Répulsion,Visszaverés Lemeze,Disco della repulsione,反発の円盤,방탄의 원반,Schijf van Afstoting,Frastøtelsesskive,Dysk Odpychania,Disco da Repulsão,,Disc al Repulsiei,Диск отторжения,Диск одбијања,Skiva av avstötning,İtme Diski,Диск відштовхування +Mystic Ambit Incant,TXT_ARTIHEALINGRADIUS,,,,Tajemný čár koljdoucí,Mystic Ambit Incant,Verbannungsgerät,,Sorĉo de Mistika Sfero,Encanto de Ámbito Místico,,Mystisen piirin loitsu,Incantation Mystique,Misztikus Mágialista,Confine mistico,魅知国の秘法,신비 영역의 주문,,Mystic Ambit-besvergelse,Inkantancja Mistycznego Kręgu,Encanto Místico,,Pergament Mistic,Чары магического единства,Чаролија магичног јединства,,Mistik Ambit Büyüsü,Закляття містичної області +Yorick's Skull,TXT_ARTIPUZZSKULL,,,,Jorikova lebka,Yoricks kranium,Yoricks Schädel,,Kranio de Yorick,Calavera de Yorick,,Yorickin kallo,Crâne de Yorick,Yorick Koponyája,Teschio di Yorick,ヨリックの髑髏,요릭의 두개골,Yorick's Schedel,Yoricks hodeskalle,Czaszka Yoricka,Caveira de Yorick,,Craniul lui Yorick,Череп Йорика,Јорикова лобања,Yoricks skalle,Yorick'in Kafatası,Череп Йоріка +Heart of D'sparil,TXT_ARTIPUZZGEMBIG,,,,Srdce D'Sparila,D'sparils hjerte,D'Sparils Herz,,Koro de D'sparil,Corazón de D'Sparil,,D'Sparilin sydän,Cœur de D'Sparil,D'Sparil szíve,Cuore di d'sparil,デ'スパリルの心,드'스파릴의 심장,Hart van D'sparil,D'Sparils hjerte,Serce D'Sparila,Coração de D'Sparil,,Inima lui D'Sparil,Сердце Д'Спарила,Д'Спарилино срце,D'sparils hjärta,D'sparil'in Kalbi,Серце Д'Спаріла +Ruby Planet,TXT_ARTIPUZZGEMRED,,,,Rubínová planeta,Rubinplanet,Rubinplanet,,Rubena Planedo,Planeta Rubí,,Rubiiniplaneetta,Planète de Rubis,Rubin Bolygó,Pianeta di rubino,ルビーの宝石,루비 행성석,Robijnrode Planeet,Rubinplaneten,Rubinowa Planeta,Planeta Rubi,,Planetă din Rubin,Рубиновая планета,Планета рубина,Rubinplanet,Yakut Gezegeni,Рубінова планета +Emerald Planet,TXT_ARTIPUZZGEMGREEN1,,,,Smaragdová planeta,Smaragdplanet,Smaragdplanet,,Smeralda Planedo,Planeta Esmeralda,,Smaragdiplaneetta,Planète d'Emeraude,Smaragd Bolygó,Pianeta di smeraldo,エメラルドの宝石,에메랄드 행성석 (1),Smaragdgroene Planeet,Smaragdplaneten,Szmaragdowa Planeta,Planeta Esmeralda,,Planetă din Smarald,Изумрудная планета,Смарагдна планета,Smaragdplanet,Zümrüt Gezegen,Смарагдова планета +Emerald Planet,TXT_ARTIPUZZGEMGREEN2,,,,Smaragdová planeta,Smaragdplanet,Smaragdplanet,,Smeralda Planedo,Planeta Esmeralda,,Smaragdiplaneetta,Planète de Saphir,Smaragd Bolygó,Pianeta di smeraldo,エメラルドの宝石,에메랄드 행성석 (2),Smaragdgroene Planeet,Smaragdplaneten,Szmaragdowa Planeta,Planeta Esmeralda,,Planetă din Smarald,Изумрудная планета,Смарагдна планета,Smaragdplanet,Zümrüt Gezegen,Смарагдова планета +Sapphire Planet,TXT_ARTIPUZZGEMBLUE1,,,,Safírová planeta,Safirplanet,Saphirplanet,,Safira Planedo,Planeta Zafiro,,Safiiriplaneetta,Planète de Saphir,Zafír Bolygó,Pianeta di zaffiro,サファイアの宝石,사파이어 행성석 (1),Saffierblauwe Planeet,Safirplaneten,Szafirowa Planeta,Planeta Safira,,Planetă din Safir,Сапфировая планета,Сафирна планета,Safirplanet,Safir Gezegen,Сапфірова планета +Sapphire Planet,TXT_ARTIPUZZGEMBLUE2,,,,Safírová planeta,Safirplanet,Saphirplanet,,Safira Planedo,Planeta Zafiro,,Safiiriplaneetta,Planète de Saphir,Zafír Bolygó,Pianeta di zaffiro,サファイアの宝石,사파이어 행성석 (2),Saffierblauwe Planeet,Safirplaneten,Szafirowa Planeta,Planeta Safira,,Planetă din Safir,Сапфировая планета,Сафирна планета,Safirplanet,Safir Gezegen,Сапфірова планета +Daemon Codex,TXT_ARTIPUZZBOOK1,,,,,,,,Kodekso de Demono,Códice del Demonio,,Daemon-koodeksi,Codex Démoniaque,Démon Kódex,Codice Demoniaco ,デーモンの写本,악마의 고문서,,,Demoniczny Kodeks,Códice Demoníaco,,Codexul Demonilor,Демонический кодекс,Демонски кодекс,,,Демонічний кодекс +Liber Oscura,TXT_ARTIPUZZBOOK2,,,,,,,,,,,,,,,オスキュラ公文書,어둠의 자유서,,,Liber Oscura,,,,Либер Оскура,Либер Оскура,,,Лібер Оскура +Flame Mask,TXT_ARTIPUZZSKULL2,,,,Plamenná maska,Flammemaske,Flammenmaske,,Flamomasko,Máscara de llamas,,Liekkinaamio,Masque de Flammes,Láng Maszk,Maschera delle fiamme,炎の仮面,화염의 가면,Vuurmasker,Flammemaske,Maska Płomieni,Máscara das Chamas,,Mască de Foc,Маска пламени,Маска пламена,Flam-mask,Alev Maskesi,Полум'яна маска +Glaive Seal,TXT_ARTIPUZZFWEAPON,,,,Glévská pečeť,Glasur-segl,Schwetsiegel,,Sigelo de Glavo,Sello de Espada,,Miekkasinetti,Sceau du Glaive,Pallos Pecsét,Sigillo della brando,グレイブシール,밀폐된 칼날,Lanszegel,Glaive segl,Pieczęć Glewii,Selo do Gládio,,Sigiliu Spadă,Печать воителя,Војников печат,Glasögonsegel,Glaive Mühür,Воїнська печатка +Holy Relic,TXT_ARTIPUZZCWEAPON,,,,Svatá relikvie,Hellig relikvie,Heiliges Relikt,,Sankta Relikvo,Santa Reliquia,,Pyhä reliikki,Relique Sacrée,Szent Ereklye,Reliquia sacra,聖遺物,신성한 유물,Heilige Relikwie,Hellig relikvie,Święta Relikwia,Relíquia Sagrada,,Relicvă Sfântă,Святая реликвия,Света реликвија,Heliga reliker,Kutsal Emanet,Свята реліквія +Sigil of the Magus,TXT_ARTIPUZZMWEAPON,,,,Mágovo sigilium,Magus' segl,Symbol des Magiers,,Sigelo de la Mago,Emblema del Mago,,Taikurin sinetti,Sceau du Mage,Mágus Pecsétje,Suggello del magus,メイガスの印章,마거스의 인장,Sigaar van de Magus,Magusens segl,Emblemat Maga,Sigilo do Mago,,Sigiliul Magului,Печать Мага,Чаробњаков симбол,Magikerns sigill,Büyücünün Sigil'i,Знак магів +Clock Gear,TXT_ARTIPUZZGEAR,,,,Ozubené kolečko,Urværk,Zahnrad,,Dentrado de Horloĝo,Engranaje de reloj,,Kellonratas,Rouage d'Horloge,Óra Szerkezet,Ingranaggio d'orologio,時計の歯車,시계 톱니바퀴,Kloktandwiel,Klokkeutstyr,Mechanizm Zegara,Engrenagem de Relógio,,Mecanism Ceas,Часовая шестерня,Сатни зупчаник,Klockan växel,Saat Dişlisi,Механічна шестерня +You Cannot Use This Here,TXT_USEPUZZLEFAILED,,,,Zde se tento předmět použít nedá,Du kan ikke bruge dette her,Das kannst du hier nicht benutzen,,Vi ne povas uzi ĉi tion ĉi tie.,No puedes usar esto aquí,,Et voi käyttää tätä tässä,Vous ne pouvez pas utiliser cela ici.,Ezt Itt Nem Használhatod,Non puoi usare questo oggetto qui,ここでは使用できない,이것은 여기에 사용할 수 없다,Dat kan je hier niet gebruiken,Du kan ikke bruke dette her,Nie możesz użyć tego tutaj,Você não pode usar isso aqui,Não podes usar isto aqui,Nu Poți Folosi Asta Aici,Здесь это невозможно использовать,Ово се не може користити овде,Du kan inte använda detta här,Bunu Burada Kullanamazsınız,Ви не можете використати тут це +Mesh Armor,TXT_ARMOR1,,,Mesh Armour,Kroužkové brnění,,Kettenrüstung,,Marŝkiraso,Armadura de Malla,,Rengashaarniska,Armure de Mailles,Háló Páncél,Maglia metallica,鎖帷子,사슬 갑옷,Maliënkolder,Nettrustning,Kolczuga,Armadura de Malha,,Armură din Zale,Кольчуга,Верижњача,Nätrustning,Örgü Zırh,Кольчуга +Falcon Shield,TXT_ARMOR2,,,,Sokolí štít,Falke-skjold,Falkenschild,,Falko-Ŝildo,Escudo de Halcón,,Haukkakilpi,Bouclier du Faucon,Sólyom Pajzs,Scudo del falco,鷹の盾,팔콘 방패,Valkenschild,Falkeskjold,Sokola Tarcza,Escudo do Falcão,,Scut Șoim,Соколиный щит,Соколов штит,Falken-sköld,Falcon Kalkanı,Соколиний щит +Platinum Helmet,TXT_ARMOR3,,,,Platinová helma,Platin-hjelm,Platinhelm,,Platena Kasko,Casco de Platino,,Platinakypärä,Casque de Platine,Platina Sisak,Elmo di platino,白金の兜,백금 투구,Platina Helm,Platinahjelm,Platynowy Hełm,Capacete de Platina,,Coif de Platină,Платиновый шлем,Шлем од платине,Platinahjälm,Platin Kask,Платиновий шолом +Amulet of Warding,TXT_ARMOR4,,,,Amulet uhýbání,Amulet af afværge,Wachamulett,,Amuleto de Gardado,Amuleto de Guarda,,Suojelusamuletti,Amulette de Protection,Oltalom Amulettje,Amuleto di protezione,回避の護符,수호의 부적,Amulet van Bescherming,Amulett av beskyttelse,Amulet Ochrony,Amuleto da Proteção,,Amuleta Protecției,Амулет стража,Амулет страже,Amulett för skydd,Korunma Tılsımı,Амулет вартового +Timon's Axe,TXT_WEAPON_F2,,,,Timonova sekera,Timons økse,Timons Axt,,Hakilo de Timon,Hacha de Timón,,Timonin kirves,Hache de Timon,Timon Baltája,Ascia di timon,タイモンの斧,티몬의 도끼,Timon's Bijl,Timons øks,Topór Timona,Machado de Timon,,Toporul lui Timon,Топор Тимона,Тимонова секира,Timons yxa,Timon'un Baltası,Тімонова сокира +Hammer of Retribution,TXT_WEAPON_F3,,,,Kladivo odplaty,Gengældelsens hammer,Hammer der Rache,,Martelo de Repago,Martillo de Retribución,,Koston vasara,Marteau de la Rétribution,Kárhozat Kalapácsa,Martello del castigo,報復の金槌,징벌의 망치,Hamer der Vergelding,Gjengjeldelsens hammer,Młot Odkupienia,Martelo da Retribuição,,Ciocanul Salvării,Молот возмездия,Чекић одмазде,Hämndhammaren,İntikam Çekici,Молот відплати +Quietus Assembled,TXT_WEAPON_F4,,,,Složený Tišitel,Forløser samlet,Erlöser komplettiert,,Kvietus' Muntita,Quietus Ensamblado,,Quietus koottuna,Quietus Assemblée,Némusz Összerakva,Quietus assemblato,組み立てた 死滅の剣,완성된 종언의 검,Quietus in elkaar gezet,Quietus samlet,Złożony Uciszacz,Quietus Montada,,Argument Final Asamblat,Последний довод собран воедино,Самрт је сабрана,Quietus monterad,Quietus Birleştirildi,Упокій зібрано воєдино +Serpent Staff,TXT_WEAPON_C2,,,,Hadí hůl,Slange-stav,Schlangenstab,,Serpentbastono,Vara de Serpiente,,Käärmesauva,Sceptre du Serpent,Kígyó Bot,Bastone del serpente,蛇の杖,뱀 지팡이,Slangenstaf,Slangestav,Laska Węży,Cetro da Serpente,,Bastonul Șarpelui,Змеиный посох,Змијски штап,Ormens stav,Yılan Asa,Посох змія +Firestorm,TXT_WEAPON_C3,,,,Ohnivá bouře,Ildstorm,Feuersturm,,Fajroŝtormo,Tormenta de Fuego,,Tulimyrsky,Tempête de Feu,Tűzvihar,Tempesta di fuoco,ファイアストーム,화염폭풍,Vuurstorm,Ildstorm,Burza Ognia,Tempestade-de-Fogo,,Furtună de Foc,Огненный шторм,Огњена олуја,Eldstorm,Ateş Fırtınası,Вогняний шторм +Wraithverge Assembled,TXT_WEAPON_C4,,,,Složený Zjevitel,Spirit Bringer samlet,Geisterbringer komplettiert,,Fantomkruc' Muntita,Báculo Fantasmal Ensamblado,Vara Fantasmal Ensamblada,Haamusauva koottuna,Verge Phantasmale Assemblée,Bosszúbot Összerakva,Verga Sconfinaspettri assemblata,組み立てた レイスバージ,완성된 사령의 십자가,Schimroede in elkaar gezet,Wraithverge samlet,Złożony Widmoskraj,Cajado Fantasma Montado,,Toiag Stafie Asamblat,Жезл духов собран воедино,Жезло утвара је сабрано,Wraithverge monterad,Wraithverge Birleştirildi,Символ Мари зібрано воєдино +Frost Shards,TXT_WEAPON_M2,,,,Ledové střepy,Frostskår,Frostsplitter,,Frostfragmentoj,Fragmentos de Escarcha,,Pakkassirpaleet,Eclats de Givre,Fagyos Szilánkok,Frantumi gelati,フロスト シャード,얼음 파편,Vorstscherven,Frostskår,Lodowe Odłamki,Fragmentos de Geada,,Cioburi de Gheață,Ледяные осколки,Ледене крхотине,Frostskärvor,Buz Kırıkları,Льодяні уламки +Arc of Death,TXT_WEAPON_M3,,,,Jiskry smrti,Dødens bue,Todesblitz,,Arko de Morto,Arcos de la Muerte,,Kuolonkaari,Foudre Mortelle,Halál Boltíve,Arco della morte,死の円弧,죽음의 번갯불,Doodsboog,Dødens bue,Łuk Śmierci,Arcos da Morte,,Izvorul Morții,Дуга смерти,Лук смрти,Dödsbåge,Ölüm Arkı,Арка смерті +Bloodscourge Assembled,TXT_WEAPON_M4,,,,Složený Krvehrom,Blodgisel samlet,Blutgeißel komplettiert,,Sangskurĝ' Muntita,Plaga Sangrienta ensamblada,,Veripiiska koottuna,Fléau Sanglant Assemblé,Vérkorbács Összerakva,Flagello di Sangue assemblato,組み立てた 天罰,완성된 피의 재앙,Bloedgesel in elkaar gezet,Bloodscourge samlet,Złożona Krwioplaga,Flagelo de Sangue Montado,,Flagel Sângeros Asamblat,Кровавый бич собран воедино,Крвави бич је сабран,Bloodscourge monterad,Bloodscourge Birleştirildi,Кривава Кара зібрана воєдино +A weapon piece! This is your lucky day!,TXT_WEAPONPIECE,,,,Část zbraně! Dnes je tvůj šťastný den!,Et våbenstykke! Dette er din heldige dag!,Ein Waffensegment. Das ist dein Glückstag!,,Peco de armilo! Estas via bonŝanca tago!,¡Una pieza de un arma! ¡Es tu día de suerte!,,Aseen osa! Tämä on onnenpäiväsi!,Une pièce d'arme! C'est votre jour de chance!,Egy fegyver darab! Szerencés napod van!,Il frammento di un'arma! È il tuo giorno fortunato! ,武器の一片! 今日は吉日だ!,무기의 한 조각이다! 운수 좋은 날인 것 같다!,Een wapenstuk! Dit is je geluksdag!,En våpendel! Dette er lykkedagen din!,Część broni! To twój szczęśliwy dzień!,Um fragmento de arma! Esse é o seu dia de sorte!,Um fragmento de arma! Este é o teu dia de sorte!,O piesă din super armă! E ziua ta norocoasă!,Часть оружия! Сегодня ваш счастливый день!,Део оружја! Данас Вам је срећан дан!,En vapendel! Detta är din lyckodag!,Bir silah parçası! Bugün şanslı gününüz!,Частина зброї! Та ви щасливчик! +Segment of Quietus,TXT_QUIETUS_PIECE,,,,Část Tišitele,Segment af Forløseren,Segment des Erlösers,,Segmento de Kvietus',Segmento de Quietus,,Quietuksen osa,Segment de Quietus,Darab a Némuszból,Parte del Quietus,死滅の剣の切片,종언의 검 조각,Segment van Quietus,Segment av Quietus,Fragment Uciszacza,Segmento de Quietus,,Fragment din Argumentul Final,Часть последнего довода,Део Самрти,Segment av Quietus,Quietus'un bir bölümü,Частина Упокою +Segment of Wraithverge,TXT_WRAITHVERGE_PIECE,,,,Část Zjevitele,Segment af Spirit Bringer,Segment des Geisterbringers,,Segmento de Fantomkruc',Segmento del Báculo Fantasmal,,Haamusauvan osa,Segment de la Verge Phantasmale,Darab a Bosszúbotból,Parte della Verga Sconfinaspettri,レイスバージの切片,사령의 십자가 조각,Segment van Schimroede,Segment av Wraithverge,Fragment Widmoskraju,Segmento do Cajado Fantasma,,Fragment din Toiagul Stafie,Часть жезла духов,Део Жезла утвара,Segment av Wraithverge,Wraithverge'in Segmenti,Частина Символу Мари +Segment of Bloodscourge,TXT_BLOODSCOURGE_PIECE,,,,Část Krvehromu,Segment af Blodgiselen,Segment der Blutgeißel,,Segmento de Sangskurĝ',Segmento de la Plaga Sangrienta,,Veripiiskan osa,Segment du Fléau Sanglant,Darab a Vérkorbácsból,Parte del Flagello di Sangue,天罰の切片,피의 재앙 조각,Segment van Bloedgesel,Segment av Bloodscourge,Fragment Krwioplagi,Segmento do Flagelo de Sangue,,Fragment din Flagelul Sângeros,Часть кровавого бича,Део Крвавог бича,Segment av Bloodscourge,Bloodscourge'un Segmenti,Частина Кривавої Кари +,,Locks,,,,,,,,,,,,,,,,,,,,,,,,,, +You need the Steel Key,TXT_NEED_KEY_STEEL,,,,Potřebuješ ocelový klíč,Du skal bruge stålnøglen,Du brauchst den Stahlschlüssel,Χρειάζεσε το Ατσάλινο κλειδί.,Vi bezonas la Ŝtalan Ŝlosilon,Necesitas la Llave de Acero,,Tarvitset teräsavaimen,Vous avez besoin de la Clé d'Acier,Az Acél Kulcsra van szükséged,Ti serve la Chiave d'Acciaio,鋼の鍵が必要だ,강철 열쇠가 필요하다,Je hebt de Stalen Sleutel nodig.,Du trenger stålnøkkelen,Potrzebujesz Stalowego Klucza,Você precisa da Chave de Aço,Precisas da Chave de Aço,Ai nevoie de Cheia din Oțel,Нужен стальной ключ,За отварање је потребан челични кључ,Du behöver stålnyckeln.,Çelik Anahtara ihtiyacın var,Вам потрібен сталевий ключ +You need the Cave Key,TXT_NEED_KEY_CAVE,,,,Potřebuješ klíč od jeskyně,Du skal bruge hulenøglen,Du brauchst den Höhlenschlüssel,,Vi bezonas la Kavern-Ŝlosilon,Necesitas la Llave de la Caverna,,Tarvitset luola-avaimen,Vous avez besoin de la Clé de la Cave,A Barlang Kulcsra van szükséged,Ti serve la Chiave della Caverna ,洞窟の鍵が必要だ,동굴 열쇠가 필요하다,Je hebt de Grotsleutel nodig.,Du trenger hulenøkkelen,Potrzebujesz Klucza do Jaskini,Você precisa da Chave da Caverna,Precisas da Chave da Caverna,Ai nevoie de Cheia Peșterii,Нужен пещерный ключ,За отварање је потребан пећински кључ,Du behöver grottnyckeln,Mağara Anahtarına ihtiyacın var,Вам потрібен печерний ключ +You need the Axe Key,TXT_NEED_KEY_AXE,,,,Potřebuješ sekyrový klíč,Du skal bruge øksenøglen,Du brauchst den Axtschlüssel,,Vi bezonas la Hakil-Ŝlosilon,Necesitas la Llave de Hacha,,Tarvitset kirvesavaimen,Vous avez besoin de la Clé de la Hache,A Fejsze Kulcsra van szükséged,Ti serve la Chiave dell'Ascia,斧の鍵が必要だ,도끼 열쇠가 필요하다,Je hebt de Bijlsleutel nodig.,Du trenger øksenøkkelen,Potrzebujesz Klucza-Topora,Você precisa da Chave do Machado,Precisas da Chave do Machado,Ai nevoie de Cheia Topor,Нужен ключ-топор,За отварање је потребан кључ секира,Du behöver yxnyckeln,Balta Anahtarına ihtiyacın var,Вам потрібен сокирний ключ +You need the Fire Key,TXT_NEED_KEY_FIRE,,,,Potřebuješ ohnivý klíč,Du skal bruge brandnøglen,Du brauchst den Feuerschlüssel,,Vi bezonas la Fajro-Ŝlosilon,Necesitas la Llave de Fuego,,Tarvitset tuliavaimen,Vous avez besoin de la Clé du Feu,A Tűz Kulcsra van szükséged,Ti serve la Chiave del Fuoco ,炎の鍵が必要だ,불 열쇠가 필요하다,Je hebt de Vuursleutel nodig.,Du trenger Ildnøkkelen,Potrzebujesz Ognistego Klucza,Você precisa da Chave do Fogo,Precisas da Chave do Fogo,Ai nevoie de Cheia de Foc,Нужен огненный ключ,За отварање је потребан огњени кључ,Du behöver eldnyckeln,Ateş Anahtarına ihtiyacın var,Вам потрібен вогняний ключ +You need the Emerald Key,TXT_NEED_KEY_EMERALD,,,,Potřebuješ smaragdový klíč,Du skal bruge smaragdnøglen,Du brauchst den Smaragdschlüssel,,Vi bezonas la Smeraldan Ŝlosilon,Necesitas la Llave Esmeralda,,Tarvitset smaragdiavaimen,Vous avez besoin de la Clé d'Emeraude,A Smaragd Kulcsra van szükséged,Ti serve la Chiave di Smeraldo ,翠玉の鍵が必要だ,에메랄드 열쇠가 필요하다,Je hebt de Smaragden Sleutel nodig.,Du trenger smaragdnøkkelen,Potrzebujesz Szmaragdowego Klucza,Você precisa da Chave Esmeralda,Precisas da Chave Esmeralda,Ai nevoie de Cheia din Smarald,Нужен изумрудный ключ,За отварање је потребан смарагдни кључ,Du behöver smaragdnyckeln,Zümrüt Anahtarı'na ihtiyacın var.,Вам потрібен смарагдовий ключ +You need the Dungeon Key,TXT_NEED_KEY_DUNGEON,,,,Potřebuješ klíč od žaláře,Du skal bruge fangehulsnøglen,Du brauchst den Kerkerschlüssel,,Vi bezonas la Karcer-Ŝlosilon,Necesitas la Llave del Calabozo,,Tarvitset tyrmän avaimen,Vous avez besoin de la Clé du Donjon,A Várbörtön Kulcsra van szükséged,Ti serve la Chiave del Sotterraneo ,迷宮の鍵が必要だ,지하감옥 열쇠가 필요하다,Je hebt de Kerkersleutel nodig.,Du trenger fangehullsnøkkelen,Potrzebujesz Klucza do Lochu,Você precisa da Chave da Masmorra,Precisas da Chave das Masmorras,Ai nevoie de Cheia Temniței,Нужен ключ от подземелья,За отварање је потребан кључ од лагума,Du behöver Kerker-nyckeln,Zindan Anahtarına ihtiyacın var,Вам потрібен ключ від підземелля +You need the Silver Key,TXT_NEED_KEY_SILVER,,,,Potřebuješ stříbrný klíč,Du skal bruge sølvnøglen,Du brauchst den Silberschlüssel,Χρειάζεσε το Ασυμένιο κλειδί.,Vi bezonas la Arĝentan Ŝlosilon,Necesitas la Llave de Plata,,Tarvitset hopea-avaimen,Vous avez besoin de la Clé d'Argent,Az Ezüst Kulcsra van szükséged,Ti serve la Chiave d'Argento ,銀の鍵が必要だ,은 열쇠가 필요하다,Je hebt de Zilveren Sleutel nodig.,Du trenger sølvnøkkelen,Potrzebujesz Srebrnego Klucza,Você precisa da Chave de Prata,Precisas da Chave Prata,Ai nevoie de Cheia din Argint,Нужен серебряный ключ,За отварање је потребан сребрни кључ,Du behöver silvernyckeln,Gümüş Anahtara ihtiyacın var,Вам потрібен срібний ключ +You need the Rusted Key,TXT_NEED_KEY_RUSTED,,,,Potřebuješ zrezivělý klíč,Du skal bruge den rustne nøgle,Du brauchst den rostigen Schlüssel,Χρειάζεσε το Σκουριασμένο κλειδί.,Vi bezonas la Rustan Ŝlosilon,Necesitas la Llave Oxidada,,Tarvitset ruosteisen avaimen,Vous avez besoin de la Clé Rouillée,A Rozsdás Kulcsra van szükséged,Ti serve la Chiave Arrugginita ,錆びた鍵が必要だ,녹슨 열쇠가 필요하다,Je hebt de Geroeste Sleutel nodig.,Du trenger den rustne nøkkelen,Potrzebujesz Zardzewiałego Klucza,Você precisa da Chave Enferrujada,Precisas da Chave Enferrujada,Ai nevoie de Cheia Ruginită,Нужен ржавый ключ,За отварање је потребан зарђали кључ,Du behöver den rostade nyckeln,Paslı Anahtar'a ihtiyacın var.,Вам потрібен іржавий ключ +You need the Horn Key,TXT_NEED_KEY_HORN,,,,Potřebuješ parožní klíč,Du skal bruge hornnøglen,Du brauchst den Hornschlüssel,,Vi bezonas la Hup-Ŝlosilon,Necesitas la Llave de Cuerno,,Tarvitset sarviavaimen,Vous avez besoin de la Clé Corne,A Szarv Kulcsra van szükséged,Ti serve la Chiave del Corno ,角の鍵が必要だ,뿔 열쇠가 필요하다,Je hebt de Hoornsleutel nodig.,Du trenger Horn-nøkkelen,Potrzebujesz Rogowego Klucza,Você precisa da Chave do Chifre,Precisas da Chave do Chifre,Ai nevoie de Cheia Corn,Нужен роговой ключ,За отварање је потребан рогати кључ,Du behöver hornnyckeln,Korna Anahtarına ihtiyacınız var,Вам потрібен ріговий ключ +You need the Swamp Key,TXT_NEED_KEY_SWAMP,,,,Potřebuješ klíč od bažiny,Du skal bruge sumpnøglen,Du brauchst den Sumpfschlüssel,,Vi bezonas la Marĉ-Ŝlosilon,Necesitas la Llave del Pantano,,Tarvitset suoavaimen,Vous avez besoin de la Clé des Marécages,A Mocsár Kulcsra van szükséged,Ti serve la Chiave della Palude ,沼の鍵が必要だ,늪지대 열쇠가 필요하다,Je hebt de Moerassleutel nodig.,Du trenger Sump-nøkkelen,Potrzebujesz Bagiennego Klucza,Você precisa da Chave do Pântano,Precisas da Chave do Pântano,Ai nevoie de Cheia Mlaștinii,Нужен болотный ключ,За отварање је потребан мочварни кључ,Du behöver träsknyckeln,Bataklık Anahtarına ihtiyacın var.,Вам потрібен болотний ключ +You need the Castle Key,TXT_NEED_KEY_CASTLE,,,,Potřebuješ klíč od hradu,Du skal bruge slotsnøglen,Du brauchst den Burgschlüssel,,Vi bezonas la Kastel-Ŝlosilon,Necesitas la Llave del Castillo,,Tarvitset linnan avaimen,Vous avez besoin de la Clé du Château,A Kastély Kulcsra van szükséged,Ti serve la Chiave del Castello ,城の鍵が必要だ,성 열쇠가 필요하다,Je hebt de Kasteelsleutel nodig.,Du trenger slottsnøkkelen,Potrzebujesz Klucza do Zamku,Você precisa da Chave do Castelo,Precisas da Chave do Castelo,Ai nevoie de Cheia Castelului,Нужен ключ от замка,За отварање је потребан кључ од замка,Du behöver slottsnyckeln,Kale Anahtarına ihtiyacın var,Вам потрібен ключ від фортеці +,,Actor tag names,,,,,,,,,,,,,,,,,,,,,,,,,, +Afrit,FN_FIREDEMON,,,,,,,,Afrito,,,,,,,アフリート,아프리트,Afriet,,,,,Demon de Foc,Африт,Африт,,,Африт +Serpent,FN_DEMON1,,,,Zlohad,Slange,Chaos-Schlange,,Serpento,Serpiente,,Käärme,,Kígyó,Serpente del Caos,サーペント,서펜트,Slang,Slangen,Wąż,Serpente,,Șarpe,Змей,Серпент,Ormen,Yılan,Змій +Ettin,FN_ETTIN,,,,Skřet,,,,Gigantaĉo,,,,,,,エティン,에틴,,,,,,Etin,Эттин,Етин,Ettin,,Еттін +Centaur,FN_CENTAUR,,,,Kentaur,Kentaur,Zentaur,,Centaŭro,Centauro,,Kentauri,Centaure,Kentaur,Centauro,ケンタウロス,켄타우로스,Centaurus,Kentaur,,Centauro,,,Кентавр,Кентаур,Kentaur,Kentaur,Кентавр +Slaughtaur,FN_SLAUGHTAUR,,,,Ničitaur,Slagtaur,Schlachtaur,,Buĉataŭro,Masacratauro,,Teurastauri,Sangtaure,Vágtaur,Sventrauro,スロアタウル,슬로터로스,Slachttaurus,Slakttaur,Rzeziotaur,Chacinotauro,,Centaur Violent,Убитавр,Кентаур старешина,Slaktaur,Katlaur,Кентавр хорунжий +Bishop,FN_BISHOP,,,,Biskup,Biskop,Bischof,,Episkopo,Obispo,,Piispa,Evèque,Érsek,Vescovo,ビショップ,비숍,Bisschop,Biskop,Biskup,Bispo,,Episcop,Епископ,Епископ,Biskop,Piskopos,Єпископ +Wendigo,FN_ICEGUY,,,,,,,,Vendiko,,,,,,,ウェンディゴ,윈디고,,,,,,Vendigo,Вендиго,Вендиго,,,Віндіго +Stalker,FN_SERPENT,,,,Slídil,,Wasserjäger,,Gvatanto,Acechador,,Vaanija,Chasseur,Orvhalász,Cacciatore,ストーカー,스토커,,,Prześladowca,Caçador,,Vânător,Преследователь,Вребач,,,Сталкер +Reiver,FN_WRAITH,,,,Přízrak,,Phantom,,Fantomo,Saqueador,,Ryöväri,,Martalóc,Incursore,レイバー,리버,Rover,,Rozbójnik,Fantasma,,Pungaș,Грабитель,Грабљивац,Reiver,Hayalet,Розбійник +Death Wyvern,FN_DRAGON,,,,Smrtidrak,Døden Wyvern,Todesdrache,,Morta viverno,Guiverno de la muerte,,Kuolontraakki,Vouivre de la Mort,A Halál Sárkánya,Viverna Mortale,デス ワイバーン,데스 와이번,Doodsdraak,Døden Wyvern,Wiwerna Śmierci,Serpe da Morte,,Balaur al Morții,Виверна смерти,Змајак смрти,Döds Wyvern,Ölüm Wyvern,Віверна Смерті +Korax,FN_KORAX,,,,,,,,,,,Kooraks,,,,唯一神コラックス,코락스,,,,,,,Коракс,Коракс,,,Коракс +Zedek,FN_FBOSS,,,,,,,,Zedeko,,,Sedek,,,,ゼデク,제닥,,,,,,,Зедек,Зедек,,,Зедек +Menelkir,FN_MBOSS,,,,,,,,Menelkiro,,,Menelkir,,,,メネルキル,메넬키어,,,,,,,Менелкир,Менелкир,,,Менелкір +Traductus,FN_CBOSS,,,,Traduktus,,,,Traduktuso,,,Traduktus,,Traduktusz,,トラダクタス,트라닥투스,,,,,,,Традуктус,Традуктус,,,Традуктус +Heresiarch,FN_HERESIARCH,,,,Arcikacíř,Heresiark,Erzketzer,,Ĉefherezulo,Heresiarca,,Kerettiarkki,L'Hérésiarche,Főeretnek,Eresiarca,ヘレシアーク,헤러시아크,,Heresiark,Herezjarcha,Heresiarca,,Ereziarh,Ересиарх,Јересијарх,Heresiark,Heresiark,Єресіарх +Blue Mana,AMMO_MANA1,,,,Modrá mana,Blå Mana,Blaues Mana,,Blua Manao,Maná azul,,Sininen mana,Mana Bleu,Kék Mana,Mana blu,ブルーマナ,청색 마나,Blauwe Mana,Blå Mana,Niebieska Mana,Mana Azul,,Mană Albastră,Синяя мана,Плава мана,Blå Mana,Mavi Mana,Синя мана +Green Mana,AMMO_MANA2,,,,Zelená mana,Grøn Mana,Grünes Mana,,Verda Manao,Maná verde,,Vihreä mana,Mana Vert,Zöld Mana,Mana verde,グリーンマナ,녹색 마나,Groene Mana,Grønn Mana,Zielona Mana,Mana Verde,,Mană Verde,Зелёная мана,Зелена мана,Grön Mana,Yeşil Mana,Зелена мана +Mace of Contrition,TAG_CWEAPMACE,,,,Palcát kajícnosti,Stridskølle af anger,Streitkolben,,Klabo de Penteco,Maza de Contrición,,Katumuksen nuija,Masse de Pénitence,Bűnbánat Buzogánya,Mazza del Pentimento,懺悔のメイス,참회의 철퇴,Knots van Wroeging,Mace of Contrition,Buzdygan Skruchy,Maça da Contrição,,Buzduganul Remușcării,Булава раскаяния,Буздован покајања,Tystnadens stridsspira,Pişmanlık Topuzu,Булава покаяння +Serpent Staff,TAG_CWEAPSTAFF,,,,Hadí hůl,Slange-stav,Schlangenstab,,Serpentbastono,Bastón de Serpiente,,Käärmesauva,Sceptre du Serpent,Kígyó Bot,Staffa del Serpente ,蛇の杖,뱀 지팡이,Slangenstaf,Slangestav,Laska Węży,Cetro da Serpente,,Bastonul Șarpelui,Змеиный посох,Змијски штап,Ormens stav,Yılan Asa,Посох змія +Firestorm,TAG_CWEAPFLAME,,,,Ohnivá bouře,Ildstorm,Feuersturm,,Fajrŝtormo,Tormenta de Fuego,,Tulimyrsky,Tempête de Feu,Tűzvihar,Tempesta di Fuoco ,ファイアストーム,화염폭풍,Vuurstorm,Ildstorm,Burza Ognia,Tempestade-de-fogo,,Furtună de Foc,Огненный шторм,Огњена олуја,Eldstorm,Ateş Fırtınası,Вогняний шторм +Wraithverge,TAG_CWEAPWRAITHVERGE,,,,Zjevitel,Spirit Bringer,Geisterbringer,,Fantomkruc',Báculo Fantasmal,,Haamusauva,Verge Phantasmale,Lidércvég,Verga SconfinaSpettri,レイスバージ,사령의 십자가,Schimroede,Wraithverge,Widmoskraj,Cajado Fantasma,,Toiag Stafie,Жезл духов,Жезло утвара,,Wraithverge,Символ Мари +Spiked Gauntlets,TAG_FWEAPFIST,,,,Ohrocené rukavice,Spidse handsker,Stachelhandschuhe,,Pintaj Fergantoj,Guanteletes Puntiagudos,,Piikkirautakintaat,Gantelets à Pointes,Tűskés Páncélkesztyűk,Guantoni Spinati,スパイク ガントレット,가시 장갑,Spijkerhandschoenen,Pigghansker,Kolczaste Rękawice,Manoplas Espinhadas,,Mănuși cu Țepi,Шипастые перчатки,Бодљикаве рукавице,Spikade handskar,Çivili Eldivenler,Шипасті рукавиці +Timon's Axe,TAG_FWEAPAXE,,,,Timonova sekera,Timons økse,Timons Axt,,Hakilo de Timon,Hacha de Timón,,Timonin kirves,Hache de Timon,Timon Baltája,Ascia di Timon,タイモンの斧,티몬의 도끼,Timon's Bijl,Timons øks,Topór Timona,Machado de Timon,,Toporul lui Timon,Топор Тимона,Тимонова секира,Timons yxa,Timon'un Baltası,Тімонова сокира +Hammer of Retribution,TAG_FWEAPHAMMER,,,,Kladivo odplaty,Hævnens hammer,Hammer der Rache,,Martelo de Repago,Martillo de Retribución,,Koston vasara,Marteau de la Rétribution,Kárhozat Kalapácsa,Martello del Castigo,報復の金槌,징벌의 망치,Hamer van Vergelding,Gjengjeldelsens hammer,Młot Odkupienia,Martelo da Retribuição,,Ciocanul Salvării,Молот возмездия,Чекић одмазде,Hämndhammaren,İntikam Çekici,Молот відплати +Quietus,TAG_FWEAPQUIETUS,,,,Tišitel,Forløser,Erlöser,,Kvietus',,,,Quietus,Némusz,,死滅の剣,종언의 검,,,Uciszacz,,,Argument Final,Последний довод,Самрт,,,Упокій +Sapphire Wand,TAG_MWEAPWAND,,,,Safírová hůl,Safir-stav,Saphirstab,,Safirsorĉbastono,Varita de Zafiro,,Safiirisauva,Baguette de Saphir,Zafír Pálca,Scettro di Zaffiro ,サファイア ワンド,사파이어 지팡이,Saffieren Toverstok,Safirstaven,Szafirowa Różdżka,Cetro de Safira,,Toiag cu Safir,Сапфировая волшебная палочка,Сафирни штап,Safirstav,Safir Değnek,Сапфіровий жезл +Frost Shards,TAG_MWEAPFROST,,,,Ledové střepy,Frostskår,Frostsplitter,,Frostfragmentoj,Fragmentos de Escarcha,,Pakkassirpaleet,Eclats de Givre,Fagyos Szilánkok,Schegge di Ghiaccio ,フロスト シャード,얼음 파편,Vorstscherven,Frostskår,Lodowe Odłamki,Fragmentos de Geada,,Cioburi de Gheață,Замораживающие осколки,Ледене крхотине,Frostskärvor,Buz Kırıkları,Льодяні уламки +Arcs of Death,TAG_MWEAPLIGHTNING,,,,Jiskry smrti,Dødens buer,Todesblitz,,Arkoj de Morto,Arcos de la Muerte,,Kuolonkaaret,Foudre Mortelle,Halál Boltíve,Archi della Morte ,死の円弧,죽음의 번갯불,Doodsboog,Dødens buer,Łuki Śmierci,Arcos da Morte,,Izvoarele Morții,Дуга смерти,Лук смрти,Dödsbågar,Ölüm Yayları,Арка смерті +Bloodscourge,TAG_MWEAPBLOODSCOURGE,,,,Krvehrom,Blodgisel,Blutgeißel,,Sangskurĝ',Plaga Sangrienta,,Veripiiska,Fléau Sanglant,Vérkorbács,Flagello di Sangue,天罰,피의 재앙,Bloedgesel,,Krwioplaga,Flagelo de Sangue,,Flagel Sângeros,Кровавый бич,Крвави бич,,,Кривава Кара +Disc of Repulsion,TAG_ARTIBLASTRADIUS,,,,Kotouč odpuzení,Afstødningsskive,Rückstoßscheibe,,Disko de Repelado,Disco de Repulsión,,Karkotuskiekko,Disque de Répulsion,Visszaverő Pajzs,Disco della Repulsione ,反発の円盤,방탄의 원반,Schijf van Afstoting,Frastøtelsens skive,Dysk Odpychania,Disco da Repulsão,,Disc al Repulsiei,Диск отторжения,Диск одбијања,Skiva av avstötning,İtme Diski,Диск відштовхування +Dragonskin Bracers,TAG_ARTIBOOSTARMOR,,,,Dračí nátepníky,Drageskindsarmbøjler,Drachenhaut-Armschutz,,Brakbendo el Drakhaŭto,Brazaletes de piel de Dragón,,Lohikäärmeennahkarannesuojat,Brassards en peau de Dragon,Sárkánybőr Karkötők,Bracciali in Pelle di Drago ,竜皮の小手,용가죽 팔찌,Drakenhuidbescherming,Dragehud-bindinger,Karwasze ze Smoczej Skóry,Braçadeiras de Pele de Dragão,,Brățări din Piele de Dragon,Наручи драконьей кожи,Наруквице од змајеве коже,Drakskinnsarmband,Ejderha Derisi Bilezikler,Наручі зі шкіри дракона +Krater of Might,TAG_ARTIBOOSTMANA,,,,Kalich síly,Kraftens bæger,Kelch der Macht,,Kratero de Potenco,Crátera de Poder,,Mahtikrateeri,Cratère de Pouvoir,Hatalom Kráterje,Calice della Forza,魔力の盃,힘의 향로,Beker van Macht,Krater av makt,Czara mocy,Cálice do Poder,,Pocal al Puterii,Кубок могущества,Чаша силе,Mäktighetens krater,Kudret Krateri,Чаша міці +Flechette,TAG_ARTIPOISONBAG,,,,Střelka,,,,Flakono,,,,Fléchette,Nyílhegy,Fiaschetta ,フレシェット,플레셰트,,,Flaszka,,,Flacon,Флешетта,Бочица,,,Флешета +Poison Cloud Flechette,TAG_ARTIPOISONBAG1,,,,Otrávená střelka,Flechette (giftig sky),Flechette (Giftwolke),,Venennub-Flakono,Flechette de Nube Venenosa,,Myrkkypilviflechette,Fléchette - Nuage Toxique,Méregfelhő hegy,Fiaschetta Velenosa,毒ガス フレシェット,독구름 플레셰트,Flechette (giftige wolk),Giftsky-flechette,Flaszka Trującej Chmury,Flechette de Nuvem Venenosa,,Flacon cu Otravă,Флешетта ядовитого облака,Бочица отровног облака,Flechette med giftmoln,Zehirli Bulut Flechette,Флешета отруйної хмари +Timebomb Flechette,TAG_ARTIPOISONBAG2,,,,Časovaná střelka,Flechette (tidsbombe),Flechette (Zeitbombe),,Horloĝbomb-Flakono ,Bomba de Tiempo Flechette,,Aikapommiflechette,Fléchette - Bombe a Retardement,Időbomba hegy,Fiaschetta a Tempo ,時限爆弾フレシェット,시한폭탄 플레셰트,Flechette (tijdbom),Tidsbombe Flechette,Flaszka-Bomba Zegarowa,Flechette Bomba-Relógio,,Bombă cu Ceas,Флешетта часовой бомбы,Бочица временске бомбе,Tidsbomb Flechette,Saatli bomba Flechette,Флешета часової бомби +Grenade Flechette,TAG_ARTIPOISONBAG3,,,,Granátová střelka,Flechette (granat),Flechettre (Granate),,Grenad-Flakono,Granada Flechette,,Kranaattiflechette,Fléchette - Grenade,Robbanó hegy,Fiaschetta da Lancio,グレネードフレシェット,폭발성 플레셰트,Flechette (granaat),Granat Flechette,Flaszka-Granat,Flechette Granada,,Flacon-Grenadă,Гранатная флешетта ,Бочица граната,Granat Flechette,El Bombası Flechette,Гранатна флешета +Mystic Ambit Incant,TAG_ARTIHEALINGRADIUS,,,,Tajemný čár koljdoucí,,,,Sorĉo de Mistika Sfero,Encantamiento de Ámbito Místico,,Mystisen piirin loitsu,Incantation Mystique,Misztikus Mágialista,Incantamento Mistico ,魅知国の秘法,신비 영역의 주문,,,Inkantancja Mistycznego Kręgu,Encantamento Místico,,Pergament Mistic,Мистический зачарованный свиток,Чаролија магичног јединства,,Mistik Ambit Büyüsü,Закляття містичної області +Icon of the Defender,TAG_ARTIDEFENDER,,,,Obráncova ikona,Ikon af forsvareren,Ikone des Verteidigers,,Ikono de la Defendanto,Icono del Defensor,Ícono del Defensor,Puolustajan ikoni,Icône du Défenseur,Védelmező Ikonja,Emblema del Difensore ,守護者の像,수호의 성상,,Forsvarerens ikon,Ikona Obrońcy,Ícone do Defensor,,Imaginea Apărătorului,Символ защитника,Симбол браниоца,Försvararens ikon,Savunucunun Simgesi,Символ захисника +Porkalator,TAG_ARTIPORK,,,,Vepřovitel,,,,Porkigilo,Porcinador,,Sikaannuttaja,Porcificateur,Ártányátok,Porchificatore,ポークレイター,돈육기,,,Schabowator,Porquificador,,Porcolator,Свиновизатор,Свињатор,,,Захрюкувач +Boots of Speed,TAG_ARTISPEED,,,,Běhuté boty,Støvler af hastighed,Turbo-Stiefel,,Botoj de Rapideco,Botas de Velocidad,,Ripeyssaappaat,Bottes de Célérité,Sebesség Cipői,Stivali della Fretta,素早さの靴,속도의 부츠,Snelheidslaarzen,Støvler av fart,Buty Szybkości,Botas da Rapidez,,Bocancii Vitezei,Сапоги-скороходы,Брзинске чизме,Stövlar av snabbhet,Hız Çizmeleri,Семимильні чоботи +Dark Servant,TAG_ARTISUMMON,,,,Temný služebník,Mørk tjener,Dunkler Diener,,Malluma Servanto,Servidor Oscuro,,Pimeä palvelija,Serviteur Noir,Árny Szolga,Servo Oscuro,闇の従者,어둠의 하인,Donkere Dienaar,Mørk tjener,Mroczny Sługa,Servo Negro,,Servitor Întunecat,Тёмный слуга,Мрачни слуга,Mörk tjänare,Karanlık Hizmetkar,Темний слуга +Banishment Device,TAG_ARTITELEPORTOTHER,,,,Vyhošťovač,Forvisningsanordning,Verbannungsgerät,,Forpelilo,Dispositivo de Destierro,,Häivytyskoje,Outil de Banissement,Számüzető Szerkentyű,Congegno dell'Esilio,追放のデバイス,소멸 장치,Verbanningsapparaat,Forvisningsinnretning,Urządzenie Wygnania ,Dispositivo do Banimento,,Dispozitiv al Alungării,Механизм изгнания,Амблем прогањања,Förvisningsenhet,Sürgün Cihazı,Пристрій заслання +Yorick's Skull,TAG_ARTIPUZZSKULL,,,,Jorikova lebka,Yoricks kranium,Yoricks Schädel,,Kranio de Yorick,Calavera de Yorick,Cráneo de Yorick,Yorickin kallo,Crâne de Yorick,Yorick Koponyája,Teschio di Yorick,ヨリックの髑髏,요릭의 두개골,Yorick's Schedel,Yoricks hodeskalle,Czaszka Yoricka,Crânio de Yorick,,Craniul lui Yorick,Череп Йорика,Јорикова лобања,Yoricks skalle,Yorick'in Kafatası,Череп Йоріка +Heart of D'Sparil,TAG_ARTIPUZZGEMBIG,,,,Srdce D'Sparila,D'Sparils hjerte,D'Sparils Herz,,Koro de D'Sparil,Corazón de D'Sparil,,D'Sparilin sydän,Cœur de D'Sparil,D'Sparil Szíve,Cuore di D'Sparil,デ'スパリルの心,드'스파릴의 심장,Hart van D'Sparil,D'Sparils hjerte,Serce D'Sparila,Coração de D'Sparil,,Inima lui D'Sparil,Сердце Д'Спарила,Д'Спарилово срце,D'Sparils hjärta,D'Sparil'in Kalbi,Серце Д'Спаріла +Ruby Planet,TAG_ARTIPUZZGEMRED,,,,Rubínová planeta,Rubinplanet,Rubinplanet,,Rubena Planedo,Planeta Rubí,,Rubiiniplaneetta,Planète en rubis,Rubin Bolygó,Pianeta di Rubino,ルビーの宝石,루비 행성석,Robijnrode Planeet,Rubinplaneten,Rubinowa Planeta,Planeta Rubi,,Planetă din Rubin,Рубиновая планета,Планета рубина,Rubinplanet,Yakut Gezegeni,Рубінова планета +Emerald Planet (1),TAG_ARTIPUZZGEMGREEN1,,,,Smaragdová planeta (1),Smaragdplanet (1),Smaragdplanet (1),,Smeralda Planedo (1),Planeta Esmeralda (1),,Smaragdiplaneetta (1),Planète en émeraude (1),Smaragd Bolygó (1),Pianeta di Smeraldo (1),エメラルドの宝石1,에메랄드 행성석 (1),Smaragdgroene Planeet (1),Smaragdplaneten (1),Szmaragdowa Planeta (1),Planeta Esmeralda (1),,Planetă din Smarald (1),Изумрудная планета (1),Смарагдна планета (1),Smaragdplanet (1),Zümrüt Gezegen (1),Смарагдова планета (1) +Emerald Planet (2),TAG_ARTIPUZZGEMGREEN2,,,,Smaragdová planeta (2),Smaragdplanet (2),Smaragdplanet (2),,Smeralda Planedo (2),Planeta Esmeralda (2),,Smaragdiplaneetta (2),Planète en émeraude (2),Smaragd Bolygó (2),Pianeta di Smeraldo (2),エメラルドの宝石2,에메랄드 행성석 (2),Smaragdgroene Planeet (2),Smaragdplaneten (2),Szmaragdowa Planeta (2),Planeta Esmeralda (2),,Planetă din Smarald (2),Изумрудная планета (2),Смарагдна планета (2),Smaragdplanet (2),Zümrüt Gezegen (2),Смарагдова планета (2) +Sapphire Planet (1),TAG_ARTIPUZZGEMBLUE1,,,,Safírová planeta (1),Safirplanet (1),Saphirplanet (1),,Safira Planedo (1),Planeta Zafiro (1),,Safiiriplaneetta (1),Planète en saphir (1),Zafír Bolygó (1),Pianeta di Zaffiro (1),サファイアの宝石1,사파이어 행성석 (1),Saffierblauwe Planeet (1),Safirplaneten (1),Szafirowa Planeta (1),Planeta Safira (1),,Planetă din Safir (1),Сапфировая планета (1),Сафирна планета (1),Safirplanet (1),Safir Gezegen (1),Сапфірова планета (1) +Sapphire Planet (2),TAG_ARTIPUZZGEMBLUE2,,,,Safírová planeta (2),Safirplanet (2),Saphirplanet (2),,Safira Planedo (2),Planeta Zafiro (2),,Safiiriplaneetta (2),Planète en saphir (2),Zafír Bolygó (2),Pianeta di Zaffiro (2),サファイアの宝石2,사파이어 행성석 (2),Saffierblauwe Planeet (2),Safirplaneten (2),Szafirowa Planeta (2),Planeta Safira (2),,Planetă din Safir (2),Сапфировая планета (2),Сафирна планета (2),Safirplanet (2),Safir Gezegen (2),Сапфірова планета (2) +Daemon Codex,TAG_ARTIPUZZBOOK1,,,,,,,,Kodekso de Demono,Códice del Demonio,,Daemon-koodeksi,Codex Démoniaque,Démon Kódex,Codice Demoniaco ,デーモンの写本,악마의 고문서,,,Demoniczny Kodeks,Códice Demoníaco,,Codexul Demonilor,Демонический кодекс,Демонски кодекс,,,Демонічний кодекс +Liber Oscura,TAG_ARTIPUZZBOOK2,,,,,,,,Liber Oscura,Liber Oscura,,,,,,オスキュラ公文書,어둠의 자유서,,,Liber Oscura,,,Liber Obscura,Либер Оскура,Либер Оскура,,,Лібер Оскура +Flame Mask,TAG_ARTIPUZZSKULL2,,,,Plamenná maska,Flamme-maske,Flammenmaske,,Fajrmasko,Mascara de Llamas,Mascara de Flamas,Liekkinaamio,Masque de Flammes,Láng Maszk,Maschera delle Fiamme ,炎の仮面,화염의 가면,Vuurmasker,Flammemaske,Maska Płomieni,Máscara das Chamas,,Mască de Foc,Маска пламени,Маска пламена,Flam-Mask,Alev Maskesi,Полум'яна маска +Glaive Seal,TAG_ARTIPUZZFWEAPON,,,,Glévská pečeť,Sværdsegl,Schwertsiegel,,Sigelo de Glavo,Sello de Espada,,Miekkasinetti,Sceau du Glaive,Pallos Pecsét,Sigillo del Brando,グレイブシール,밀폐된 칼날,Lanszegel,Glaive segl,Pieczęć Glewii,Selo do Gládio,,Sigiliu Spadă,Печать воителя,Војников печат,Glasögonsegel,Glaive Mühür,Воїнська печатка +Holy Relic,TAG_ARTIPUZZCWEAPON,,,,Svatá relikvie,Hellig relikvie,Heiliges Relikt,,Sankta Relikvo,Santa Reliquia,,Pyhä reliikki,Relique Sacrée,Szent Ereklye,Reliquia Sacra,聖遺物,신성한 유물,Heilige Relikwie,Hellig relikvie,Święta Relikwia,Relíquia Sagrada,,Relicvă Sfântă,Святая реликвия,Света реликвија,Heliga reliker,Kutsal Emanet,Свята реліквія +Sigil of the Magus,TAG_ARTIPUZZMWEAPON,,,,Mágovo sigilium,Magus' segl,Symbol des Magiers,,Sigelo de la Mago,Emblema del Mago,,Taikurin sinetti,Sceau du Mage,Mágus Pecsétje,Suggello del Magus,メイガスの印章,마거스의 인장,Sigaar van de Magus,Magusens segl,Emblemat Maga,Sígilo do Mago,,Sigiliul Magului,Печать Мага,Чаробњаков симбол,Magikerns sigill,Büyücünün Sigil'i,Знак магів +Iron gear,TAG_ARTIPUZZGEAR1,,,,Železné kolečko,Tandhjul af jern,Eisenzahnrad,,Fera Dentrado,Engranaje de Hierro,,Rautaratas,Engrenage en Fer,Vas Felszerelés,Ingranaggio di Ferro,鉄の歯車,양철 톱니바퀴,IJzeren uitrusting,Jernutstyr,Żelazna Zębatka,Engrenagem de ferro,,Mecanism din fier,Железная шестерня,Гвожђени зупчаник,Kugghjul av järn,Demir dişli,Залізна шестерня +Brass gear,TAG_ARTIPUZZGEAR2,,,,Mosazné kolečko,Tandhjul i messing,Messingzahnrad,,Latuna Dentrado,Engranaje de Bronce,,Messinkiratas,Engrenage en Bronze,Réz Felszerelés,Ingranaggio di Ottone ,真鍮のギア,황동 톱니바퀴,Messing uitrusting,Utstyr av messing,Mosiężna Zębatka,Engrenagem de latão,,Mecanism din alamă,Латунная шестерня,Месингани зупчаник,Kugghjul av mässing,Pirinç dişli,Латунна шестерня +Brass and iron gear,TAG_ARTIPUZZGEAR3,,,,Mosazno-železné kolečko,Tandhjul af messing og jern,Messing-und-Eisen-Zahnrad,,Latuna Fera Dentrado,Engranaje de Bronce y Hierro,,Messinki- ja rautaratas,Engrenage en Fer et Bronze,Vas és Réz Felszerelés,Ingranaggio di Ferro e Ottone ,鉄と真鍮のギア,황동과 양철 톱니바퀴,Messing en ijzeren uitrusting,Utstyr av messing og jern,Zębatka z mosiądzu i żelaza,Engrenagem de ferro e latão,,Mecanism din alamă și fier,Латунно-железная шестерня,Месинганoгвожђени зупчаник,Kugghjul av mässing och järn,Pirinç ve demir dişli,Латунно-залізна шестерня +Silver and brass gear,TAG_ARTIPUZZGEAR4,,,,Stříbro-mosazné kolečko,Tandhjul af sølv og messing,Silber-und-Messing-Zahnrad,,Arĝenta Latuna Dentrado,Engranaje de Plata y Bronce,,Hopea- ja messinkiratas,Engrenage en Argent et Bronze,Ezüst és Réz Felszerelés,Ingranaggio di Ottone e Argento ,銀と真鍮のギア,은과 황동 톱니바퀴,Zilveren en messing uitrusting,Utstyr av sølv og messing,Zębatka ze srebra i mosiądzu,Engrenagem de prata e latão,,Mecanism din argint și alamă,Серебряно-латунная шестерня,Сребрномесигани зупчаник,Kugghjul av silver och mässing,Gümüş ve pirinç dişli,Срібно-латунна шестерня +,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,,,, +%o tasted an Afrit's fire.,OB_FIREDEMON,,,,%o okusil@[ao_cs] afritův oheň.,%o smagte en afrits ild.,%o spürte das Feuer des Afrits.,,%o gustis la fajron de Afrito.,%o ha probado el fuego de un Afrit.,%o probó el fuego de un Afrit.,%o maistoi afritin tulta.,%o a goûté au feu d'un Afrit.,%o megkóstolta a Tűz Szellem parazsát.,%o ha assaggiato il fuoco di un Afrit. ,%o はアフリートの炎を味わった。,%o 은(는) 아프리트의 화염을 맛봤다.,%o proefde het vuur van een Afriet.,%o smakte en Afrits ild.,%o spróbował@[ao_pl] ognia Afrita.,%o provou o fogo de um Afrit.,,%o a gustat flacăra Demonului de Foc.,Игрок %o отведал огня африта.,%o је окуси@[ao_1_sr] Афритов огањ.,%o smakade en Afrits eld.,%o bir Afrit'in ateşini tattı.,%o скуштува@[adj_1_ua] вогню Африта. +%o was scalded by a Serpent.,OB_DEMON1,,,,%o byl@[ao_cs] upálen@[ao_cs] zlohadem.,%o blev skoldet af en slange.,%o wurde von der Chaos-Schlange gebissen.,,%o brogiĝis de Serpento.,A %o l@[ao_esp] ha carbonizado una Serpiente.,A %o l@[ao_esp] carbonizó una Serpiente.,%o joutui käärmeen kalttaamaksi.,%o a été brûlé@[e_fr] par un Serpent.,%o testét leforrázta egy Kígyó,%o è stato sciolto da un Serpente del Caos,%o はサーペントに火傷を負わされた。,%o 은(는) 서펜트에 데였다.,%o werd gebroeid door een Slang.,%o ble skåldet av en slange.,%o został@[ao_pl] poparzon@[adj_pl] przez Węża.,Uma Serpente escaldou %o.,,%o a fost opărit de un Șarpe.,Игрок %o спалён змеем.,Играча %o је спалио Серпент.,%o blev skållad av en orm.,%o bir yılan tarafından haşlandı.,%o було спалено змієм. +%o was poisoned by a Serpent.,OB_DEMON2,,,,%o byl@[ao_cs] otráven@[ao_cs] zlohadem.,%o blev forgiftet af en slange.,%o wurde von der Chaos-Schlange verbrannt.,,%o veneniĝis de Serpento.,A %o l@[ao_esp] ha envenenado una Serpiente.,A %o l@[ao_esp] envenenó una Serpiente.,%o joutui käärmeen myrkyttämäksi.,%o a été empoisonné@[e_fr] par un Serpent.,%o vérébe mérget juttatott egy Kígyó,%o è stato avvelenato da un Serpente del Caos. ,%o はサーペントの毒にやられた。,%o 은(는) 독 서펜트에게 중독 당했다.,%o werd vergiftigd door een Slang.,%o ble forgiftet av en slange.,%o został@[ao_pl] zatrut@[adj_pl] przez Węża.,%o foi envenenad@[ao_ptb] por uma Serpente.,,%o a fost otrăvit de un Șarpe.,Игрок %o отравлен змеем.,Играча %o је отровао Серпент.,%o blev förgiftad av en orm.,%o bir yılan tarafından zehirlendi.,%o було отруєно змієм. +%o was mashed by an Ettin.,OB_ETTIN,,,,%o byl@[ao_cs] umlácen@[ao_cs] skřetem.,%o blev moset af en Ettin.,%o wurde von dem Ettin zermatscht.,,%o frakasiĝis de Gigantaĉo.,%o ha quedado hech@[ao_esp] puré por un Ettin.,%o quedó hech@[ao_esp] puré por un Ettin.,%o joutui ettinin muhentamaksi.,%o a été réduit@[e_fr] en purée par un Ettin.,%o csillagokat lát az Ettin miatt.,%o è stato schiacciato da un Ettin. ,%o はエティンに潰された。,%o 은(는) 에틴에게 철퇴를 맞았다.,%o werd gepureerd door een Ettin.,%o ble knust av en Ettin.,%o został@[ao_pl] stłuczon@[adj_pl] przez Ettina.,%o foi feito purê por um Ettin.,,%o a fost făcut piure de un Etin.,Игрока %o раздробил эттин.,Играча %o је смрскао Еттин.,%o blev mosad av en Ettin.,%o bir Ettin tarafından ezildi.,%o затовк еттін. +%o was cut up by a Centaur.,OB_CENTAUR,,,,%o byl@[ao_cs] rozsekán@[ao_cs] kentaurem.,%o blev skåret op af en kentaur.,%o wurde von dem Zentaur aufgeschlitzt.,,%o distranĉiĝis de Centaŭro.,A %o l@[ao_esp] ha partido un Centauro.,A %o l@[ao_esp] partió un Centauro.,%o joutui kentaurin pilkkomaksi.,%o a été tranché@[e_fr] par un Centaure.,%o fel lett vágva a Kentaur jóvoltából.,%o è stato affettato da un Centauro. ,%o はケンタウロスに切り刻まれた。,%o 은(는) 켄타우로스에 의해 절단됐다.,%o werd versneden door een Centaurus.,%o ble kuttet opp av en Kentaur.,%o został@[ao_pl] pocięt@[adj_pl] przez Centaura.,%o foi fatiad@[ao_ptb] por um Centauro.,,%o a fost tăiat deschis de un Centaur.,Игрока %o разрезал кентавр.,Играча %o је расекао Кентаур.,%o blev styckad av en Kentaur.,%o bir Kentaur tarafından kesildi.,%o зарізав кентавр. +%o was cut up by a Slaughtaur.,OB_SLAUGHTAURHIT,,,,%o byl@[ao_cs] rozsekán@[ao_cs] ničitaurem.,%o blev skåret op af en slagtaur.,%o wurde von dem Schlachtaur aufgeschlitzt.,,%o distranĉiĝis de Buĉataŭro.,A %o l@[ao_esp] ha partido un Masacratauro.,A %o l@[ao_esp] partió un Masacratauro.,%o joutui teurastaurin pilkkomaksi.,%o a été tranché@[e_fr] par un Sangtaure.,%o nagyon felvágott és a Vágtaur is a játékost,%o è stato affettato da uno Sventrauro. ,%o はスロアタウルに切り刻まれた。,%o 은(는) 슬로터로스에 의해 심하게 절단됐다.,%o werd versneden door een Slachtaurus.,%o ble kuttet opp av en Slakttaur.,%o został@[ao_pl] pocięt@[adj_pl] Rzeziotaura.,%o foi fatiad@[ao_ptb] por um Chacinotauro.,,%o a fost tăiat deschis de un Centaur Violent.,Игрока %o разрезал убитавр.,Играча %o је расекао Кентаур старешина.,%o blev styckad av en Slaktaur.,%o bir Katlaur tarafından kesildi.,%o зарізав кентавр хорунжий. +%o was struck down by a Slaughtaur's fireball.,OB_SLAUGHTAUR,,,,%o byl@[ao_cs] zabit@[ao_cs] ničitaurovou ohnivou koulí.,%o blev slået ned af en slagtauras ildkugle.,%o wurde von dem Feuerball des Schlachtaurs niedergestreckt.,,%o subite mortiĝis de fajropilko de Buĉataŭro.,A %o l@[ao_esp] ha abatido la bola de fuego de un Masacratauro.,A %o l@[ao_esp] derribó la bola de fuego de un Masacratauro.,%o joutui teurastaurin tulipallon kaatamaksi.,%o a été touché@[e_fr] par une boule de feu de Sangtaure.,%o másodfokú égési sérüléseket szenvedett el a Vágtaur tűzgolyójától.,%o è stato abbattuto dalla palla di fuoco di uno Sventrauro. ,%o はスロアタウルの火玉に倒された。,%o 은(는) 슬로터로스의 마법구에 의해 피격당했다.,%o werd neergeslagen door een Slachtaurus' vuurbal.,%o ble truffet av en Slakttaurs ildkule.,%o został@[ao_pl] trafion@[adj_pl] przez kulę ognia Rzeziotaura.,%o foi abatid@[ao_ptb] pela bola de fogo de um Chacinotauro.,,"%o a fost răpus de mingea de foc a unui Centaur +Violent.",Игрока %o сбил огненным шаром убитавр.,Играча %o је огњеном куглом оборио Кентаур старешина.,%o blev nedslagen av en Slauktaurs eldklot.,%o bir Katlaur'un ateş topuyla vuruldu.,Кентавр хорунжий знищив %o фаєрболом. +%o succumbed to a Bishop's dark power.,OB_BISHOP,,,,%o podlehl@[ao_cs] biskupově temné moci.,%o bukkede under for en biskops mørke kraft.,%o fiel der dunklen Macht des Bischofs zum Opfer.,,%o subfaliĝis de malluma potenco de Episkopo.,%o ha sucumbido ante el poder oscuro de un Obispo.,%o sucumbió ante el poder oscuro de un Obispo.,%o lankesi piispan pimeään voimaan.,%o a succombé au pouvoir obscur d'un évèque.,%o megadta magát a Püspök sötét erejének,%o è stato sottomesso dalla magia oscura di un Vescovo. ,%o はビショップの闇の力に屈した。,%o 은(는) 비숍의 힘에 무릎을 꿇었다.,%o bezweek aan de donkere kracht van een Bisschop.,%o bukket under for en Biskops mørke kraft.,%o uległ@[ao_pl] mrocznej mocy Biskupa.,%o sucumbiu ao poder negro de um Bispo.,,%o a cedat puterii întunecate a Episcopului.,Игрок %o поддался чёрным силам Епископа.,%o је подлег@[ao_2_sr] Епископовим црним силама.,%o gav efter för en biskops mörka kraft.,%o bir Piskopos'un karanlık gücüne yenik düştü.,%o підкори@[adj_2_ua] темній магії епископа. +%o was frozen solid by a Wendigo.,OB_ICEGUY,,,,%o byl@[ao_cs] zamrznut@[ao_cs] wendigem.,%o blev frosset fast af en wendigo.,%o wurde von dem Wendigo tiefgefroren.,,%o tute frostiĝis de Vendiko.,A %o l@[ao_esp] ha congelado un Wendigo.,A %o l@[ao_esp] congeló un Wendigo.,%o joutui wendigon läpikotaisin jäädyttämäksi.,%o a été gelé@[e_fr] par un Wendigo.,%o testét keményre fagyasztotta egy Wendigo,%o è stato congelato da un Wendigo. ,%o はウェンディゴによって固められた。,%o 은(는) 윈디고에 의해 단단하게 얼려졌다.,%o werd bevroren door een Wendigo.,%o ble frosset fast av en Wendigo.,%o został@[ao_pl] zamrożon@[adj_pl] przez Wendigo.,%o foi congelad@[ao_ptb] por um Wendigo.,,%o a fost făcut statuie de un Vendigo.,Игрока %o полностью заморозил вендиго.,Играча %o је потпуно замрзнуо Вендиго.,%o blev frusen av en Wendigo.,%o bir Wendigo tarafından kaskatı donduruldu.,Вендіго повністю заморозив %o. +%o was mauled by a Stalker.,OB_SERPENTHIT,,,,%o byl@[ao_cs] umlácen@[ao_cs] slídilem.,%o blev mast af en stalker.,%o wurde von dem Wasserjäger zerfleischt.,,%o vundegiĝis de Gvatanto.,A %o l@[ao_esp] ha triturado un Acechador.,A %o l@[ao_esp] trituró un Acechador.,%o joutui vaanijan raatelemaksi.,%o a été mutilé@[e_fr] par un Chasseur.,%o szét lett marcangolva egy Orhalász által.,%o è stato malmenato da un Cacciatore. ,%o はストーカーに引っ掻かれた。,%o 은(는) 스토커에게 발렸다.,%o werd verminkt door een Stalker.,%o ble maltraktert av en Stalker.,%o został@[ao_pl] poturbowan@[adj_pl] przez Prześladowcę.,%o foi mutilad@[ao_ptb] por um Caçador.,,%o a fost sfâșiat de un Vânător.,Игрок %o покусан преследователем.,Играча %o је растргао Вребач.,%o blev söndersliten av en Stalker.,%o bir Stalker tarafından parçalandı.,%o роздер сталкер. +%o was melted by a Stalker.,OB_SERPENT,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] slídilem.,%o blev smeltet af en stalker.,%o wurde von dem Wasserjäger geschmolzen.,,%o fandiĝis de Gvatanto.,A %o l@[ao_esp] ha derretido un Acechador.,A %o l@[ao_esp] derritió un Acechador.,%o joutui vaanijan sulattamaksi.,%o a été fondu@[e_fr] par un Chasseur.,%o csontjairól a húst leolvasztotta egy Orvhalász,%o è stato squagliato da un Cacciatore. ,%o はストーカーに溶かされた。,%o 은(는) 스토커에 의해 녹았다.,%o werd gesmolten door een Stalker.,%o ble smeltet av en Stalker.,%o został@[ao_pl] stopion@[adj_pl] przez Prześladowcę.,%o foi derretid@[ao_ptb] por um Caçador.,,%o a fost topit de un Vânător.,Игрока %o расплавил преследователь.,Играча %o је растопио Вребач.,%o blev smält av en Stalker.,%o bir Takipçi tarafından eritildi.,%o розплавив сталкер. +%o was charred by a Reiver.,OB_WRAITH,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] přízrakem.,%o blev forkullet af en reiver.,%o wurde von dem Phantom verkohlt.,,%o brulegiĝis de Fantomo.,A %o l@[ao_esp] ha carbonizado un Saqueador.,A %o l@[ao_esp] carbonizó un Saqueador.,%o joutui ryövärin hiiltämäksi.,%o a été carbonisé@[e_fr] par un Reiver.,%o testét egy Martalóc elszenesítette.,%o è stato carbonizzato da un Incursore. ,%o はレイバーに黒焦げにされた。,%o 은(는) 리버에 의해 그슬렸다.,%o werd verbrand door een Rover.,%o ble forkullet av en Reiver.,%o został@[ao_pl] zwęglon@[adj_pl] przez Rozbójnika.,%o foi carbonizad@[ao_ptb] por um Fantasma.,,%o a fost ceruit de un Pungaș.,Игрока %o обуглил грабитель.,Играча %o је угљенисао Вребач.,%o blev förkolnad av en Reiver.,%o bir Hayalet tarafından yakıldı.,%o було спалено розбійником. +%o had %p life stolen by a Reiver.,OB_WRAITHHIT,,,,%o si nechal@[ao_cs] ukradnout život přízrakem.,%o fik sit liv stjålet af en reiver.,%o wurde das Leben von dem Phantom gestohlen.,,%o havis sian vivon ŝtelita de Fantomo.,A %o le ha robado la vida un Saqueador.,A %o le robó la vida un Saqueador.,Ryöväri riisti pelaajan %o hengen.,%o a perdu la vie face à un Reiver.,%o %p életét ellopta egy Martalóc,%o ha permesso che un Incursore prosciugasse la sua vita ,%o はレイバーに命を %p盗まれた。,%o 은(는) 리버에게 영혼을 도둑맞았다.,%o had @[zijn_haar_nl] leven gestolen door een Rover.,%o fikk %p liv stjålet av en Reiver.,"Życie %o zostało skradzione przez Rozbójnika. +",%o teve sua vida roubada por um Fantasma.,,Viața lui %o a fost furată de un Pungaș.,Жизнь игрока %o украл грабитель.,Играчу %o је живот украо Вребач.,%o fick sitt liv stulet av en Reiver.,%o bir Hayalet tarafından kurutuldu.,Життя %o було вкрадено розбійником. +%o was incinerated by the Death Wyvern.,OB_DRAGON,,,,%o byl@[ao_cs] upálen@[ao_cs] smrtidrakem.,%o blev forbrændt af wyvern.,%o wurde von dem Todesdrachen verbrannt.,,%o cindriĝis de Mortviverno.,A %o l@[ao_esp] ha incinerado el Guiverno de la Muerte.,A %o l@[ao_esp] incineró el Guiverno de la Muerte.,%o joutui kuolontraakin polttamaksi.,%o a été incinéré@[e_fr] par une vouivre de la mort.,%o testét porig égette egy Halálsárkány,%o è stato incenerito da una Viverna Mortale. ,%o はダークワイバーンに焼却された。,%o 은(는) 데스 와이번에 의해 분신 당했다.,%o werd verbrand door de Doodsdraak.,%o ble brent opp av en Døden Wyvern.,%o został@[ao_pl] spalon@[adj_pl] przez Wiwernę Śmierci.,%o foi incinerad@[ao_ptb] por uma Serpe da Morte,,%o a fost incinerat de Balaurul Morții.,Игрока %o кремировала виверна Смерти.,Играча %o је кремировао Змајак смрти.,%o blev bränd av Döds Wyvern.,"%o, Ölüm Wyvern tarafından yakıldı.",Віверна Смерті спалила %o вщент. +%o was swept from the board by Korax.,OB_KORAX,,,,%o byl@[ao_cs] odhozen@[ao_cs] ze šachovnice Koraxem.,%o blev fejet væk fra brættet af Korax.,%o wurde von Korax vom Feld gefegt.,,%o estis prenita el la tabulo de Korax.,%o ha sido barrid@[ao_esp] del tablero por Korax.,%o fue barrid@[ao_esp] del tablero por Korax.,%o pyyhkäistiin laudalta Kooraksen voimasta.,%o a été balayé@[e_fr] de l'échiquier par Korax.,%o el lett söpörve a tábláról Korax által.,%o è stato eliminato dalla scacchiera da Korax. ,%o は唯一神の怒りに触れた。,%o 은(는) 코락스의 체스판에서 사라졌다.,%o werd door Korax van het bord geveegd.,%o ble feid fra brettet av Korax.,%o został@[ao_pl] zmiecion@[adj_pl] z pokładu przez Koraxa.,%o foi eliminad@[ao_ptb] do tabuleiro por Korax.,,%o a fost măturat de pe drum de Korax.,Игрока %o скинул с доски Коракс.,Играча %o је с табле уклонио Коракс.,%o blev avförd från spelplanen av Korax.,"%o, Korax tarafından tahtadan süpürüldü.",Коракс скинув з ігрової дошки %o. +%o was slain by Zedek.,OB_FBOSS,,,,%o byl@[ao_cs] zabit@[ao_cs] Zedekem.,%o blev dræbt af Zedek.,%o wurde von Zedek hingemetzelt.,,%o mortigis de Zedeko.,A %o l@[ao_esp] ha asesinado Zedek.,A %o l@[ao_esp] asesinó Zedek.,%o joutui Sedekin tappamaksi.,%o a été pourfendu@[e_fr] par Zedek.,%o meghalt Zedek által.,%o è stato ammazzato da Zedek. ,%o はゼデクに討ち取られた。,%o 은(는) 제닥의 이름으로 쓰러졌다.,%o werd gedood door Zedek.,%o ble drept av Zedek.,%o został@[ao_pl] zgładzon@[adj_pl] przez Zedeka.,%o foi mort@[ao_ptb] por Zedek.,,%o a fost omorât de Zedek.,Игрока %o сразил Зедек.,Играча %o је оборио Коракс.,%o blev dödad av Zedek.,"%o, Zedek tarafından öldürüldü.",%o зустрі@[adj_1_ua] смерть від Зедека. +%o couldn't absorb Menelkir's Mana.,OB_MBOSS,,,,%o nemohl@[ao_cs] pojmout Menelkirovu manu.,%o kunne ikke absorbere Menelkirs Mana.,%o konnte Menelkirs Mana nicht verkraften.,,%o ne povis absorbi la Manaon de Menelkiro.,%o intenta absorber el maná de Menelkir y sale mal.,,%o ei kyennyt ottamaan vastaan Menelkirin manaa.,%o n'aurait pu absorber le mana de Menelkir.,%o nem tudta elnyelni Menelkir manáját.,%o non è riuscito ad assorbire il mana di Menelkir. ,%o はメネルキルのマナを吸収できなかった。,%o 은(는) 메넬키어의 마나를 흡수하지 못했다.,%o kon Menelkir's mana niet absorberen.,%o kunne ikke absorbere Menelkirs Mana.,%o nie m@[irreg_4_pl] wchłonąć Many Menelkira.,%o não conseguiu absorver o Mana de Menelkir.,,%o nu a reușit să absoarbă mana lui Menelkir.,Игрок %o не смог поглотить ману Менелкира.,%o се није узмог@[ao_2_sr] носити с Менелкировом маном.,%o kunde inte absorbera Menelkirs Mana.,"%o, Menelkir'in Mana'sını ememedi.",У %o не вийшло побороти ману Менелкіра. +%o was baptized by Traductus.,OB_CBOSS,,,,%o byl@[ao_cs] posvěcen@[ao_cs] Traduktem.,%o blev døbt af Traductus.,%o wurde von Traductus getauft.,,%o baptiĝis de Traduktuso.,A %o l@[ao_esp] ha bautizado Traductus.,A %o l@[ao_esp] bautizó Traductus.,%o joutui Traduktuksen kastamaksi.,%o a été baptisé@[e_fr] par Traductus.,%o meg lett keresztelve Traductus által.,%o è stato battezzato da Traductus. ,%o はトラダクタスの洗礼を受けた。,%o 은(는) 트라닥투스에게 침례를 당했다.,%o werd gedoopt door Traductus.,%o ble døpt av Traductus.,%o został@[ao_pl] ochrzczon@[adj_pl] przez Traductusa.,%o foi batizad@[ao_ptb] por Traductus.,,%o a fost botezat de Traductus.,Игрока %o крестил Традуктус.,Играча %o је крстио Традуктус.,%o blev döpt av Traductus.,"%o, Traductus tarafından vaftiz edildi.",Традуктус похрестив %o. +%o had %p bones rolled by the Heresiarch.,OB_HERESIARCH,,,,%o si nechal@[ao_cs] rozmetat kosti Arcikacířem.,%o fik sine knogler rullet af Heresiark.,%os Knochen wurden vom Erzketzer gerollt.,,%o havis siajn ostojn rulis de la Ĉefherezulo.,A %o le ha arrollado los huesos el Heresiarca.,A %o le arrolló los huesos el Heresiarca.,Kerettiarkki jyräsi pelaajan %o luut.,%o s'est fait@[e_fr] rouler les os par l'Hérésiarche.,%o csontváza ki lett forgatva az Eretnek Vezér által.,Le ossa di %o sono state accartocciate dall'Eresiarca. ,%o はヘレシアークに骨を %p本 撒き散らされた。,%o 은(는) 헤러시아크에 의해 뼈와 살이 분리되었다.,%o @[zijn_haar_nl] botten werden opgerold door de Heresiarch.,%o fikk %p bein rullet av Heresiark.,Kości %o zostały porozrzucane przez Herezjarchę.,%o teve seus ossos moídos pelo Heresiarca.,,Oasele lui %o au fost făcute praf de către Ereziarh.,Ересиарх сыграл в кости игрока %o.,На играча %o су пале Јересијархове коцке.,%o fick sina ben rullade av Heresiark.,"%o, Heresiark tarafından kutsandı.",Єресіарх зіграв партію кістками %o. +%o was beaten to a pulp by %k's bare fists.,OB_MPFWEAPFIST,,,,%o byl@[ao_cs] umlácen@[ao_cs] k smrti holými pěstmi hráče %k.,%o blev slået til plukfisk af %ks bare næver.,%o wurde von %ks nackten Fäusten zu Hackfleisch verarbeitet.,,%o kaĉe draŝiĝis de la nudaj pugnoj de %k.,%o ha quedado molid@[ao_esp] por los puños limpios de %k.,%o quedó molid@[ao_esp] por los puños limpios de %k.,%k hakkasi %o paran muusiksi paljailla nyrkeillään.,%o à été tabassé@[e_fr] à mort par les poings de %k.,%o péppé lett verve %k ökleivel.,%k ha ridotto %o in poltiglia a mani nude.,%o は %k に素手でボコボコにされた。,%o 은(는) %k 의 맨손 타격으로 묵사발이 되었다.,%o werd tot pulp geslagen door %k's blote vuisten.,%o ble slått til mos av %ks bare never.,%o został@[ao_pl] zbit@[adj_pl] na miazgę przez gołe pięści %k.,%o foi espancad@[ao_ptb] até a morte pelos punhos nus de %k.,,%k l-a omorât în bătaie pe %o cu mâinile goale.,Игрок %o избит в мясо голыми руками игрока %k.,%o је пребијен@[adj_1_sr] на смрт голим рукама играч %k.,%o blev slagen till mos av %ks nakna knytnävar.,"%o, %k tarafından eşek sudan gelinceye kadar dövüldü.",%k заби@[adj_1_ua] %o голими руками. +%o got the axe from %k.,OB_MPFWEAPAXE,,,,%o dostal@[ao_cs] sekerou od hráče %k.,%o fik øksen af %k.,%o sah %ks Axt.,,%o ricevis la hakilon el %k.,%o ha recibido el hachazo de %k.,%o recibió el hachazo de %k.,%o sai pelaajan %k kirveestä.,%o s'est fait@[e_fr] hacher menu par %k.,%o megkapta %k baltáját.,%o ha preso un colpo d'ascia da %k.,%o は %k から斧を受けた。,%o 은(는) %k 의 티몬의 도끼를 어설프게 받아쳤다.,%o kreeg de bijl van %k.,%o fikk øksa av %k.,%o dostał@[ao_pl] z topora %k.,%o recebeu o machado de %k.,,%o a primit un topor de la %k.,Игрок %o словил топорик игрока %k.,%o је добио секиру од %k.,%o fick yxan av %k.,"%o, %k tarafından baltayla dövüldü.",%o отрима@[adj_1_ua] сокирою від %k. +%o had %p head caved in by %k's hammer.,OB_MPFWEAPHAMMERM,,,,%o dostal@[ao_cs] po hlavě kladivem hráče %k.,%o fik sit hoved udhulet af %ks hammer.,%o wurde der Kopf von %ks Hammer eingeschlagen.,,%p havis sian kapon enfalis de la martelo de %k.,A %o le ha abollado la cabeza el martillo de %k.,A %o le abolló la cabeza el martillo de %k.,%k painoi vasarallaan %o paran pään kasaan.,%o s'est fait@[e_fr] éclater le crâne par le marteau de %k.,%o kapott egy üreges fejet %k Kalapácsa által.,La testa di %o è stata aperta in due dal martello di %k.,%o は %k のハンマーで頭に空洞を開けられた。,%k 은(는) 징벌의 망치로 %o 의 머리 위에 우물을 만들었다.,%o had @[zijn_haar_nl] kop ingestort met %k's hamer.,%o fikk %p hode knust av %ks hammer.,Głowa %o została zmiażdżona przez młot %k.,%o teve seu crânio afundado pelo martelo de %k.,%o teve seu crânio amolgado pelo martelo de %k.,%k i-a băgat capul lui %o în interior cu ciocanul.,Голова игрока %o была вдолблена в тело молотом игрока %k.,Играч %k је расцепао играчу %o главу.,%o fick huvudet krossat av %ks hammare.,"%o, %k tarafından dövüldü.",Голова %o опинилась всередині тіла через молот %k. +%o's soul was forged anew by %k's hammer.,OB_MPFWEAPHAMMERR,,,,%o@[psf1_cs] duše byla obrozena kladivem hráče %k.,%os sjæl blev smedet på ny af %ks hammer.,%os Seele wurde durch %ks Hammer erneuert.,,La animo de %o nove forĝiĝis de la martelo de %k.,El alma de %o ha sido forjada de nuevo por el martillo de %k.,El alma de %o fue forjada de nuevo por el martillo de %k.,%k uudelleentakoi %o paran sielun vasarallaan.,%o a eu son âme reforgée par le marteau de %k.,%o lelke újra lett kovácsolva %k Kalapácsa által.,L'anima di %o è stata riforgiata dal martello di %k.,%o の魂は %k のハンマーで一から鍛え直された。,%o 의 영혼은 %k 의 징벌의 망치에 의해 철거되었다.,%o's ziel werd omgesmeed door %k's hamer.,%o's sjel ble smidd på nytt av %ks hammer.,Dusza %o została wykuta na nowo przez młot %k.,%o teve sua alma reforjada pelo martelo de %k.,,%k i-a făcut sufletul lui %o ca nou cu ciocanul.,Душа игрока %o была перекована молотом игрока %k.,Играч %k је прековао душу играча %o чекићем.,%os själ smiddes på nytt av %ks hammare.,"%o, %k tarafından dövüldü.",Душа %o була наново перекована молотом %k. +%o was silenced by %k's mighty Quietus.,OB_MPFWEAPQUIETUS,,,,%o byl@[ao_cs] umlčen@[ao_cs] mocným Tišitelem hráče %k.,%o blev bragt til tavshed af %ks mægtige Forløser.,%o wurde durch %ks Erlöser befreit.,,%o slientiĝis de La Pova Kvietus' de %k.,A %o l@[ao_esp] ha silenciado el poderoso Quietus de %k.,A %o l@[ao_esp] silenció el poderoso Quietus de %k.,%k vaiensi %o paran mahtavalla Quietuksellaan.,%o à été réduit@[e_fr] au silence par le pouvoir de %k et Quietus.,%o el lett némítva %k hatalmas Némusza által.,%o è stato zittito dal potente Quietus di %k.,%o は %k の強靭なクワイエタスで静かにされた。,%o 은(는) %k 의 종언의 검 덕에 침묵을 지킬 수 있었다.,%o werd tot zwijgen gebracht door %k's machtige Quietus.,%o ble brakt til taushet av %ks mektige Quietus.,%o został@[ao_pl] uciszon@[adj_pl] przez %k.,%o foi silenciad@[ao_ptb] pelo poderoso Quietus de %k.,,"%o a fost redus la tăcere de argumentul final al +lui %k.",Игрок %o утихомирен легендарным Последним доводом игрока %k.,%o је утишан@[adj_1_sr] од моћи Куиетуса играч %k.,%o tystades av %ks mäktiga Quietus.,"%o, %k tarafından susturuldu.",%k упокої@[adj_1_ua] %o. З миром? +%o got a mace to the face from %k.,OB_MPCWEAPMACE,,,,%o dostal@[ao_cs] palcátem po hlavě od hráče %k.,%o fik en stridskølle i ansigtet af %k.,%o bekam %ks Streitkolben ins Gesicht.,,%o prenis klabon al la vizaĝon el %k.,%o ha recibido un mazazo en la cara por %k.,%o recibió un mazazo en la cara por %k.,%o sai pelaajan %k nuijasta naamaansa.,%o s'est fait@[e_fr] casser la figure par la masse de %k.,%o kapott egy buzogányt a fejébe %k által.,%o si è preso una mazzata in faccia da %k.,%o は自らの顔に %k のメイスを受けた。,%o 은(는) %k 의 철퇴를 맞은 뒤에야 철이 들었다.,%o kreeg een %k's gesel in @[zijn_haar_nl] gezicht.,%o ble slått i ansiktet av %k.,%o dostał@[ao_pl] buzdyganem %k w twarz.,%o levou com a maça de %k na cara.,,%o a primit un buzdugan în față de la %k.,Игрок %o получил по морде булавой игрока %k.,%o је доби@[ao_1_sr] буздован у фацу играч %k.,%o fick en stridsklubba i ansiktet av %k.,"%o, %k tarafından eşek sudan gelinceye kadar dövüldü.",%o отрима@[adj_1_ua] по пиці булавою %k. +%o was bitten by %k's serpent staff.,OB_MPCWEAPSTAFFM,,,,%o byl@[ao_cs] kousnut@[ao_cs] hadí holí hráče %k.,%o blev bidt af %ks slange-stav.,%o wurde von %ks Schlangenstab gebissen.,,%o mordiĝis de la serpentbastono de %k.,A %o l@[ao_esp] ha mordido el bastón de la serpiente de %k.,A %o l@[ao_esp] mordió el bastón de la serpiente de %k.,%k puri %o parkaa käärmesauvallaan.,%o s'est fait@[e_fr] mordre par le Bâton du Serpent %k.,%o meg lett harapva %k Kígyó Botja által.,%o è stato morso dalla Staffa del Serpente di %k.,%o は %k の蛇の杖に噛まれた。,%o 은(는) %k 의 뱀 지팡이에 의해 독살당했다.,%o werd gebeten door %k's slangenstaf.,%o ble bitt av %ks slangestav.,%o został@[ao_pl] ugryzion@[adj_pl] laską węży %k.,%o foi mordid@[ao_ptb] pelo Cetro da Serpente de %k.,,%o a fost mușcat de bastonul șarpe al lui %k.,Игрок %o искусан змеиным посохом игрока %k.,%o је угрижен@[adj_1_sr] змијским штапом играч %k.,%o blev biten av %ks ormstab.,"%o, %k tarafından zehirlendi.",Посох змія %k покусав %o. +%o choked on %k's serpent staff.,OB_MPCWEAPSTAFFR,,,,%o se zadusil@[ao_cs] hadí holí hráče %k.,%o blev kvalt af %ks slange stav.,%o verschluckte sich an %ks Schlangenstab.,,%o sufokis la serpentbastonon de %k.,%o se ha ahogado con el bastón de la serpiente de %k.,%o se ahogó con el bastón de la serpiente de %k.,%o tukehtui pelaajan %k käärmesauvaan.,%o s'est étranglé@[e_fr] sur le Bâton du Serpent de %k,%o megfulladt %k Kígyó Botja által.,%o è soffocato a causa della Staffa del Serpente di %k.,%o は %k の蛇の杖に息の根を止められた。,%o 은(는) %k 의 뱀 지팡이 때문에 숨을 쉬지 못했다.,%o stikte in %k's slangenstaf.,%o ble kvalt av %ks slangestav.,%o zakrztusił@[ao_pl] się laską węży %k.,%o se engasgou com o Cetro da Serpente de %k,,%o s-a sufocat pe bastonul șarpe al lui %k.,Игрок %o задушен змеиным посохом игрока %k.,%o је задављен@[adj_1_sr] змијским штапом играч %k.,%o kvävdes av %ks ormstab.,"%o, %k tarafından kurutuldu.",Посох змія %k задушив %o. +%o was lit up by %k's flames.,OB_MPCWEAPFLAME,,,,%o vzplanul@[ao_cs] plameny hráče %k.,%o blev tændt af %ks flammer.,%o wurde von %ks Flammen erleuchtet.,,%o ekbruliĝis de la fajroj de %k.,A %o l@[ao_esp] han calcinado las llamas de %k.,A %o l@[ao_esp] calcinaron las llamas de %k.,%o syttyi pelaajan %k liekeistä.,%o s'est fait@[e_fr] allumer par %k.,%o fel lett gyújtva %k tűze által.,%o è stato illuminato dalle fiamme di %k.,%o は %k によって炎を灯された。,%o 은(는) %k 의 화염폭풍에 휩쓸렸다.,%o werd opgelicht door %k's vlammen.,%o ble opplyst av %ks flammer.,%o został@[ao_pl] oświetlon@[adj_pl] płomieniami %k.,%o foi incendiad@[ao_ptb] pelas chamas de %k.,,%o s-a aprins de la flăcările lui %k.,Игрок %o сгорел в огне игрока %k.,%o је осветљен@[adj_1_sr] пламеном играч %k.,%o blev upplyst av %ks lågor.,"%o, %k tarafından aydınlatıldı.",%o було спалено в полум'ї %k. +%o was cleansed by %k's Wraithverge.,OB_MPCWEAPWRAITHVERGE,,,,%o byl@[ao_cs] očištěn@[ao_cs] Zjevitelem hráče %k.,%o blev renset af %ks Spirit Bringer.,%o wurde durch %ks Geisterbringer geläutert.,,%o puriĝis de la Fantomkruc' de %k.,A %o l@[ao_esp] ha limpiado la vara fantasmal de %k.,A %o l@[ao_esp] limpió la vara fantasmal de %k.,%k puhdisti pelaajan %o Haamusauvallaan.,%o a été purifié@[e_fr] par la Verge Phantasmale de %k.,%o meg lett tisztítva %k Bosszúbot által.,%o è stato purificato dalla Verga SconfinaSpettri di %k.,%o は %k のレイスバージによって浄化された。,%o 은(는) %k 의 사령의 지팡이에 의해 정화되었다.,%o werd gereinigd door %k's Schimroede.,%o ble renset av %ks Wraithverge.,%o został@[ao_pl] oczyszczon@[adj_pl] przez Widmoskraj %k.,%o foi purificad@[ao_ptb] pelo Cajado Fantasma de %k.,,%o a fost purificat de Toiagul Stafie al lui %k.,Игрок %o очищен жезлом духов игрока %k.,%o je прочишћен@[adj_1_sr] штапом утваре играч %k.,%o blev renad av %ks Wraithverge.,"%o, %k tarafından temizlendi.",%k очисти@[adj_1_ua] %o Символом Мари. +%o took one too many sapphire beams from %k.,OB_MPMWEAPWAND,,,,%o koupil@[ao_cs] přespříliš safírových střel od hráče %k.,%o tog en safirstråle for meget fra %k.,%o bekam zu viele Saphierstrahlen von %k ab.,,%o recivis unu tro da safira radio de %k.,%o ha recibido demasiados rayos de zafiro de %k.,%o recibió demasiados rayos de zafiro de %k.,%o otti vastaan yhden liikaa pelaajan %k safiirisäteistä.,%o s'est pris@[e_fr] un rayon saphirique en trop de la part de %k.,%o túl sok zafír sugarat kapott %k-tól/től.,%o si è buscato un raggio di zaffiro di troppo da %k.,%o は %k から多量のサファイアビームを受け取った。,%o 은(는) %k 의 사파이어 빛을 너무 많이 째려봤다.,%o kreeg een saffierstraal teveel van %k.,%o fikk en safirstråle for mye fra %k.,%o wzi@[irreg_2_pl] o jeden szafirowy promień od %k za dużo.,%o levou muitos raios de safira de %k.,,%o a primit o rază în plus de la safirul lui %k.,Игрок %o схватил слишком много сапфировых зарядов от игрока %k.,%o је узе@[ao_1_sr] превише сафирских зракова играч %k.,%o tog emot en för många safirstrålar från %k.,"%o, %k tarafından dönüştürüldü.",%o хапану@[adj_1_ua] надто багато сапфірових снарядів від %k. +%o was turned into a frosty fellow by %k.,OB_MPMWEAPFROST,,,,%o byl@[ao_cs] zchlazen@[ao_cs] hráčem %k.,%o blev forvandlet til en frostklar fyr af %k.,%o wurde von %k schockgefrostet.,,%o farigiĝis frostulon de %k.,%o ha sido convertid@[ao_esp] en un helado por %k.,%o fue convertid@[ao_esp] en un helado por %k.,%k muutti %o paran pakkasveikoksi.,%o s'est fait@[e_fr] transformer en glaçon par %k.,%o jégbaráttá alakult %k által.,%o è stato trasformato in un simpatico pupazzo di neve da %k.,%o は %k によって冷ややかな輩になった。,%o 은(는) %k 의 얼음 파편에 의해 눈사람이 되었다.,%o werd ijskoud veranderd door %k.,%o ble forvandlet til en iskald fyr av %k.,%o został@[ao_pl] zmienion@[adj_pl] w mroźnego koleżkę przez %k.,%o foi transformad@[ao_ptb] em picolé por %k.,,%o a fost transformat într-un amic de gheață de %k.,Игрок %o обращается в ледяную скульптуру игроком %k.,%o је претворен@[adj_1_sr] у лед играч %k.,%o förvandlades till en frostig kille av %k.,"%o, %k tarafından soğuk bir adama dönüştürüldü.",%o перетвори@[adj_2_ua] в лід завдяки %k. +%o received a shocking revelation from %k.,OB_MPMWEAPLIGHTNING,,,,%o zjistil@[ao_cs] šokující odhalení hráče %k.,%o fik en chokerende åbenbaring af %k.,%o musste eine schockierende Enthüllung von %k verkraften.,,%o recivis teruran revelacion de %k.,%o ha recibido una revelación impactante de %k.,%o recibió una revelación impactante de %k.,%o sai sähköistävän ilmestyksen pelaajalta %k.,%o a reçu un sacré coup de jus de la part de %k.,%o kapott egy sokkoló relevációt %k-tól/től,"%o ha ricevuto una notizia ""elettrizzante"" da %k.",%o は %k から衝撃的な啓示を受けた。,%o 은(는) %k 의 번갯불 덕에 충격적인 계시를 받았다.,%o kreeg een schokkende openbaring van %k.,%o fikk en sjokkerende åpenbaring fra %k.,%o otrzymał@[ao_pl] szokujące objawienie od %k.,%o recebeu uma revelação chocante de %k.,,%o a avut parte de o revelație șocantă de la %k.,Игрок %o откровенно шокирован игроком %k.,%o је прими@[ao_1_sr] шокантно откриће играч %k.,%o fick ett chockerande avslöjande av %k.,"%o, %k tarafından şoka uğratıldı.",%k розкри@[adj_1_ua] для %o шокуючу істину. +%o was wiped off the face of the universe by %k's Bloodscourge.,OB_MPMWEAPBLOODSCOURGE,,,,%o byl@[ao_cs] vymýcen@[ao_cs] ze jsoucna vesmíru Krvehromem hráče %k.,%o blev udslettet af universets overflade af %ks Blodgisel.,%o wurde von %ks Blutgeißel aus dem Universum verbannt.,,%o disdetruiĝis el la universo de la Sangskurĝ' de %k.,%o ha sido borrad@[ao_esp] de la faz del universo por la plaga sangrienta de %k.,%o fue borrad@[ao_esp] de la faz del universo por la plaga sangrienta de %k.,%k pyyhki %o paran maailmankaikkeudesta.,%o s'est fait@[e_fr] effacer de l'univers par le Fléau Sanglant de %k.,%o ki lett törölve az univerzumból %k Vérkorbácsának köszönhetően.,%o è stato cancellato dalla faccia dell'universo dal Flagello di Sangue di %k.,%o は %k の天罰によりこの世から一掃された。,%o 은(는) %k 이(가) 피의 재앙을 씀으로써 전혀 존재하지 않는 존재가 되어버렸다.,%o werd van het gezicht van het universum geveegd door %k's Bloedgesel.,%o ble utslettet fra universets overflate av %ks Bloodscourge.,Twarz %o została zmieciona z wszechświata przez Krwioplagę %k.,%o foi varrid@[ao_ptb] da face do universo pelo Flagelo de Sangue de %k.,,"%o a fost ras de pe fața universului de +Flagelul Sângeros al lui %k.",Игрок %o стёрт с лица вселенной Кровавым бичом игрока %k.,%o је обрисан@[adj_1_sr] са лица свемира од Крвавог зла играч %k.,%o blev utplånad från universums yta av %ks Bloodscourge.,"%o, %k tarafından evrenden silindi.",%o було стерто з лиця всесвіту за допомогою Кривавої Кари %k. +,,Strife,,,,,,,,,,,,,,,,,,,,,,,,,, +,,Pickups,,,,,,,,,,,,,,,,,,,,,,,,,, +You picked up the Metal Armor.,TXT_METALARMOR,,,You picked up the Metal Armour.,Sebral@[ao_cs] jsi kovové brnění.,Du samlede metalrustningen op.,Du hast die Metallrüstung genommen.,Πήρες τη Μεταληκή Πανοπλία.,Vi trovis metalan armaĵon.,Encuentras una armadura de metal.,,Poimit metallihaarniskan.,Vous avez pris l'armure de métal.,Felvetted a Fémpáncélt.,Hai raccolto l'Armatura di Metallo.,メタルアーマー 入手。,강철 갑옷을 획득했다.,Je hebt het metalen harnas opgepakt.,Du plukket opp metallrustningen.,Podniosł@[irreg_3_pl] Metalowy Pancerz.,Você pegou a Armadura de Metal.,Apanhaste a Armadura de Metal.,Ai ridicat Armura din Metal.,Получена металлическая броня.,Покупио си метални оклоп.,Du plockade upp metallrustningen.,Metal Zırhı aldın.,Взято Металічну броню. +You picked up the Leather Armor.,TXT_LEATHERARMOR,,,You picked up the Leather Armour.,Sebral@[ao_cs] jsi kožené brnění.,Du samlede læderrustningen op.,Du hast die Lederrüstung genommen.,Πήρες τη Δερμάτινη Πανοπλία.,Vi trovis ledan armaĵon.,Encuentras una armadura de cuero.,,Poimit nahkasuojuksen.,Vous avez pris l'armure de cuir.,Felvetted a Bőrpáncélt.,Hai raccolto l'Armatura di Cuoio.,レザーアーマー 入手。,가죽 갑옷을 획득했다.,Je hebt het leren harnas opgepakt.,Du plukket opp lærrustningen.,Podniosł@[irreg_3_pl] Skórzany Pancerz.,Você pegou a Armadura de Couro.,Apanhaste a Armadura de Couro.,Ai ridicat Armura din Piele.,Получена кожаная броня.,Покупио си кожни оклоп.,Du plockade upp läderrustningen.,Deri Zırhı aldın.,Взято Шкіряну броню. +You picked up the Med patch.,TXT_MEDPATCH,,,,Sebral@[ao_cs] jsi obvaz.,Du samlede Med patch op.,Du hast den Verband genommen.,,Vi trovis kuracbendojn.,Encuentras unas tiritas.,Encuentras unas curitas.,Poimit sidekääreen.,Vous avez pris le pansement.,Felvetted a Ragtapaszt.,Hai raccolto le Bende.,医薬パッチ 入手。,의료 붕대를 획득했다.,Je hebt de med-patch opgepakt.,Du plukket opp en Med-patch.,Podniosł@[irreg_3_pl] Bandaż.,Você pegou a compressa médica.,Apanhaste a compressa médica.,Ai ridicat Trusa de Prim-Ajutor.,Получен медицинский бинт.,Покупио си прву помоћ.,Du plockade upp den medicinska plåstret.,Sağlık bandını aldın.,Взято оклюзійну пов'язку. +You picked up the Medical kit.,TXT_MEDICALKIT,,,,Sebral@[ao_cs] jsi lékárničku.,Du samlede Medicinsk kit op.,Du hast den Verbandskasten genommen.,,Vi trovis sukurkeston.,Encuentras un botiquín.,,Poimit lääkintälaukun.,Vous avez pris le kit médical.,Felvetted az Elsősegélycsomagot.,Hai raccolto il Kit di Pronto Soccorso.,医療用キット 入手。,구급 키트를 획득했다.,Je hebt de medicijndoos opgepakt.,Du plukket opp det medisinske settet.,Podniosł@[irreg_3_pl] Apteczkę.,Você pegou o Kit Médico.,Apanhaste o Kit Médico.,Ai ridicat Kitul de Prim-Ajutor.,Получена аптечка.,Покупио си медицински комплет,Du plockade upp den medicinska utrustningen.,Tıbbi kiti aldın.,Взято індивідуальну аптечку. +You picked up the Surgery Kit.,TXT_SURGERYKIT,,,,Sebral@[ao_cs] jsi chirurgickou soupravu.,Du samlede kirurgisættet op.,Du hast den Erste-Hilfe-Kasten genommen.,,Vi trovis kirurgian keston.,Encuentras un kit quirúrgico.,,Poimit kirurgilaukun.,Vous avez pris le kit de chirurgie.,Felvetted az Orvosi Műtőfelszerelést.,Hai raccolto il Kit Chirurgico.,手術キット 入手。,수술 키트를 획득했다.,Je hebt het chirurgenpakket opgepakt.,Du plukket opp Kirurgi-settet.,Podniosł@[irreg_3_pl] Zestaw Chirurga.,Você pegou o Kit de Cirurgia.,Apanhaste o Kit de Cirugia.,Ai ridicat Kitul pentru Operații.,Получен медкомплект.,Покупио си хируршки комплет,Du plockade upp operationssatsen.,Ameliyat setini aldın.,Взято медичний кейс. +You picked up the map.,TXT_STRIFEMAP,,,,Sebral@[ao_cs] jsi mapu.,Du samlede kortet op.,Du hast die Karte genommen.,Πήρες το χάρτη.,Vi trovis la mapon.,Encuentras el mapa.,,Poimit kartan.,Vous avez pris la carte,Felvetted a térképet.,Hai raccolto la Mappa.,マップ 取得。,지도를 획득했다.,Je hebt de kaart opgepakt.,Du plukket opp kartet.,Podniosł@[irreg_3_pl] mapę.,Você pegou o mapa.,Apanhaste o mapa.,Ai ridicat harta.,Получена карта.,Покупио си мапу.,Du plockade upp kartan.,Haritayı aldın.,Взято карту. +You picked up the ring.,TXT_BELDINSRING,,,,Sebral@[ao_cs] jsi prsten.,Du samlede ringen op.,Du hast den Ring genommen.,Πήρες το Δακτύλιο.,Vi havas la ringon.,Tienes el anillo.,,Poimit sormuksen.,Vous avez pris l'anneau.,Felvetted a Gyűrűt.,Hai raccolto l'Anello.,指輪 取得。,반지를 획득했다.,Je hebt de ring opgepakt.,Du plukket opp ringen.,Podniosł@[irreg_3_pl] pierścień.,Você pegou o anel.,Apanhaste o anel.,Ai ridicat inelul.,Получено кольцо.,Покупио си прстен.,Du plockade upp ringen.,Yüzüğü aldın.,Взято каблучку. +You picked up the Offering Chalice.,TXT_OFFERINGCHALICE,,,,Sebral@[ao_cs] jsi obětní kalich.,Du samlede offerkalken op.,Du hast den Opferkelch genommen.,,Vi trovis oferdonan kalikon.,Encuentras un cáliz de ofrenda.,,Poimit uhrimaljan.,Vous avez pris le Calice d'obole.,Felvetted az Áldozati Kelyhet.,Hai raccolto il Calice delle Offerte.,寄贈された聖杯 取得。,번제 성배를 훔쳤다.,Je hebt de Offerbeker opgepakt.,Du plukket opp offerbegeret.,Podniosł@[irreg_3_pl] Kielich Ofiarny.,Você pegou o Cálice de Oferenda.,Apanhaste o Cálice de Oferenda.,Ai ridicat Potirul pentru Ofrande.,Получена чаша для подношений.,Покупио си Жртвени пехар.,Du plockade upp offerkalken.,Adak Kadehini aldın.,Взято чашу для жертвоприношення. +You picked up the ear.,TXT_EAR,,,,Sebral@[ao_cs] jsi ucho.,Du samlede øret op.,Du hast das Ohr gernommen.,Πήρες το αυτί.,Vi havas la orelon.,Tienes la oreja.,,Poimit korvan.,Vous avez pris l'oreille.,Felvetted a Fület.,Hai raccolto l'Orecchio.,耳 取得。,잘린 귀를 주웠다.,Je hebt het oor opgepakt.,Du plukket opp øret.,Podniosł@[irreg_3_pl] ucho.,Você pegou a orelha.,Apanhaste a orelha.,Ai ridicat urechea.,Получено ухо.,Покупио си уво.,Du plockade upp örat.,Kulağı aldın.,Взято вухо. +You picked up the broken power coupling.,TXT_BROKENCOUPLING,,,,Sebral@[ao_cs] jsi rozbitou spojku.,Du samlede den ødelagte strømkobling op.,Du hast den defekten Stromabnehmer genommen.,,Vi havas la rompitan energian kuplilon.,Tienes el acoplador de energía roto.,,Poimit rikkinäisen virtaliittimen.,Vous avez pris le coupleur énergétique cassé.,Felvetted a hibás tápcsatlakozót.,Hai raccolto la Coppia Energetica Rotta.,壊れたパワーカップリング 取得。,망가진 동력선 장치를 획득했다.,Je hebt de kapotte stroomkoppeling opgepakt.,Du plukket opp den ødelagte kraftkoblingen.,Podniosł@[irreg_3_pl] zepsute obwody zasilające.,Você pegou o acoplador de energia quebrado.,Apanhaste o acoplador de energia partido.,Ai ridicat cuplajul defect de curent.,Получена повреждённая муфта.,Покупио си неисправну спојницу напајања.,Du plockade upp den trasiga kraftkopplingen.,Kırık güç bağlantısını aldın.,Взято зламану силову муфту. +You picked up the Shadow armor.,TXT_SHADOWARMOR,,,You picked up the Shadow armour.,Sebral@[ao_cs] jsi krycí brnění.,Du samlede skyggerustningen op.,Du hast die Schattenrüstung genommen.,,Vi trovis ombran armaĵon.,Encuentras una armadura de sombra.,,Poimit varjohaarniskan.,Vous avez pris l'armure de l'ombre.,Felvetted az Árnyékpáncélt.,Hai raccolto l'Armatura Ombra.,シャドウアーマー 入手。,그림자 갑옷을 획득했다.,Je hebt het schaduwharnas opgepakt.,Du plukket opp Skygge-rustningen.,Podniosł@[irreg_3_pl] Cienisty Pancerz.,Você pegou a armadura das sombras.,Apanhaste a armadura das sombras.,Ai ridicat Armura Umbrei.,Получена теневая броня.,Покупио си оклоп сенки.,Du plockade upp skuggrustningen.,Gölge zırhını aldın.,Взято Тіньову броню. +You picked up the Environmental Suit.,TXT_ENVSUIT,,,,Sebral@[ao_cs] jsi ochranný oděv,Du samlede miljødragten op.,Du hast den Schutzanzug genommen.,,Vi trovis medi-ŝirman veston,Encuentras un traje NBQ.,,Poimit ympäristösuojapuvun.,Vous avez pris la combinaison hazmat.,Felvetted a Védőruhát.,Hai raccolto la Tuta Ambientale.,耐環境スーツ 入手。,환경 방호복을 획득했다.,Je hebt het beschermende pak opgepakt.,Du plukket opp miljødrakten.,Podniosł@[irreg_3_pl] Skafander Ochronny.,Você pegou o Traje de Proteção.,Apanhaste o Fato Protetor.,Ai ridicat Costumul de Protecție.,Получен защитный костюм.,Покупио си заштитно одело.,Du plockade upp miljödräkten.,Çevresel Kıyafeti aldın.,Взято захисний костюм. +You picked up the Guard Uniform.,TXT_GUARDUNIFORM,,,,Sebral@[ao_cs] jsi hlídačovu uniformu.,Du samlede vagtuniformen op.,Du hast die Wächteruniform genommen.,,Vi havas la uniformon de gardisto.,Tienes el uniforme de un guardia.,,Poimit vartijan univormun.,Vous avez pris l'Uniforme du garde.,Felvetted az Őr Egyenruhát.,Hai raccolto l'Uniforme da Guardia.,守衛の制服 入手。,경비 전투복을 획득했다.,Je hebt het wachtersuniform opgepakt.,Du plukket opp vaktuniformen.,Podniosł@[irreg_3_pl] Mundur Strażnika.,Você pegou o Uniforme de Guarda.,Apanhaste o Uniforme de Guarda.,Ai ridicat Uniforma de Paznic.,Получена униформа стражника.,Покупио си стражарску униформу,Du plockade upp vaktuniformen.,Muhafız Üniformasını aldın.,Взято уніформу охоронця. +You picked up the Officer's Uniform.,TXT_OFFICERSUNIFORM,,,,Sebral@[ao_cs] jsi důstojníkovu uniformu.,Du samlede officersuniformen op.,Du hast die Offiziersuniform genommen.,,Vi trovis oficiran uniformon.,Encuentras un uniforme de oficial.,,Poimit upseerin univormun.,Vous avez pris l'Uniforme de l'officier.,Felvetted a Tiszti Egyenruhát.,Hai raccolto l'Uniforme da Ufficiale.,士官の制服 入手。,장교 전투복을 획득했다.,Je hebt het officiersuniform opgepakt.,Du plukket opp offisersuniformen.,Podniosł@[irreg_3_pl] Mundur Oficera.,Você pegou o Uniforme de Oficial.,Apanhaste o Uniforme de Oficial.,Ai ridicat Uniforma Ofițerului.,Получена униформа офицера.,Покупио си официрску униформу,Du plockade upp officersuniformen.,Subay üniformasını aldın.,Взято офіцерську уніформу. +You picked up the flame thrower parts.,TXT_FTHROWERPARTS,,,,Sebral@[ao_cs] jsi součásti plamenometu.,Du samlede flammekasterdele op.,Du hast die Flammenwerferteile genommen.,,Vi havas la partojn de flamĵetilo.,Tienes las partes de un lanzallamas.,,Poimit liekinheittimen osat.,Vous avez pris les pièces du lance-flames.,Felvetted a lángszóró részeit.,Hai raccolto delle parti di Lanciafiamme.,火炎放射器の部品 入手。,화염방사기 부품을 획득했다.,Je hebt de vlammenwerperonderdelen opgepakt.,Du plukket opp delene til flammekasteren.,Podniosł@[irreg_3_pl] części miotacza ognia.,Você pegou as partes do lança-chamas.,Apanhaste as peças do lança-chamas.,Ai ridicat bucățile aruncătorului de flăcări.,Получены детали для огнемёта.,Покупио си делове за бацач пламена.,Du plockade upp delarna till flamkastaren.,Alev silahının parçalarını aldın.,Взято деталі для вогнемету. +You picked up the report.,TXT_REPORT,,,,Sebral@[ao_cs] jsi hlášení.,Du samlede rapporten op.,Du hast den Report genommen.,,Vi havas la raporton.,Tienes el reporte.,,Poimit raportin.,Vous avez pris le compte-rendu.,Felvetted a jelentést.,Hai raccolto il rapporto.,報告書 取得。,보고서를 획득했다.,Je hebt het rapport opgepakt.,Du plukket opp rapporten.,Podniosł@[irreg_3_pl] raport.,Você pegou o relatório.,Apanhaste o relatório.,Ai ridicat raportul.,Получен отчёт.,Покупио си извештај.,Du plockade upp rapporten.,Raporu aldın.,Взято звіт. +You picked up the info.,TXT_INFO,,,,Sebral@[ao_cs] jsi informace.,Du samlede oplysningerne op.,Du hast die Info genommen.,Πήρες της πληροφορίες,Vi havas la informojn.,Tienes la información.,,Poimit tiedot.,Vous avez pris l'info.,Felvetted az információt.,Hai raccolto delle Informazioni.,情報 取得。,정보를 획득했다.,Je hebt de informatie opgepakt.,Du plukket opp informasjonen.,Podniosł@[irreg_3_pl] informacje.,Você pegou a informação.,Apanhaste a informação.,Ai recepționat informația.,Получена сводка.,Покупио си инфо.,Du plockade upp informationen.,Bilgiyi aldın.,Отримано данні. +You picked up the Targeter.,TXT_TARGETER,,,,Sebral@[ao_cs] jsi zaměřovač.,Du samlede targeter op.,Du hast die Zielhilfe genommen.,Πήρες τον Στοχευτή.,Vi trovis celilon.,Encuentras una mira de arma.,,Poimit tähtäinlaitteen.,Vous avez pris le cibleur.,Felvetted a Célzóberendezést.,Hai raccolto il Puntatore.,照準器 入手。,조준기를 획득했다.,Je hebt het Richter opgepakt.,Du plukket opp Targeteren.,Podniosł@[irreg_3_pl] Namierzacz.,Você pegou a Mira.,Apanhaste a Mira.,Ai ridicat Țintitorul.,Получен целеуказатель.,Покупио си нишанитеља.,Du plockade upp targeter.,Hedefleyiciyi aldın.,Взято цілевказівник. +You picked up the Communicator.,TXT_COMMUNICATOR,,,,Sebral@[ao_cs] jsi komunikátor.,Du samlede kommunikatoren op.,Du hast den Kommunikator genommen.,,Vi trovis interfonon.,Encuentras un intercomunicador.,,Poimit viestintälaitteen.,Vous avez pris le Communicateur,Felvetted a Kommunikátort,Hai raccolto il Comunicatore.,コミュニケーター 取得。,연락장치를 획득했다.,Je hebt de Communicator opgepakt.,Du plukket opp kommunikatoren.,Podniosł@[irreg_3_pl] Komunikator.,Você pegou o Comunicador.,Apanhaste o Comunicador.,Ai ridicat Comunicatorul.,Получен передатчик.,Покупио си комуникатор.,Du plockade upp kommunikatorn.,İletişim cihazını aldın.,Взято комунікатор. +You picked up the coin.,TXT_COIN,,,,Sebral@[ao_cs] jsi minci.,Du samlede mønten op.,Du hast die Münze genommen.,Πήρες το κέρμα.,Vi trovis moneron.,Encuentras una moneda.,,Poimit kolikon.,Vous avez pris la pièce.,Felvetted az érmét.,Hai raccolto la Moneta.,コイン 入手。,동전을 주웠다.,Je hebt de munt opgepakt.,Du plukket opp mynten.,Podniosł@[irreg_3_pl] monetę.,Você pegou a moeda.,Apanhaste a moeda.,Ai ridicat moneda.,Получена монета.,Покупио си новчић.,Du plockade upp myntet.,Parayı aldın.,Взято монету. +You picked up %d gold.,TXT_XGOLD,,,,Sebral@[ao_cs] jsi %d zlatých.,Du samlede %d guld op.,Du hast %d Gold genommen.,,Vi trovis %d da oro.,Encuentras %d monedas de oro.,,Poimit kultaa %d arvosta.,Vous avez pris %d pièces.,Felvettél %d aranyat.,Hai raccolto %d pezzi d'oro.,%d ゴールド 入手。,골드 %d 개를 획득했다.,Je hebt %d goud opgepakt.,Du plukket opp %d gull.,Podniosł@[irreg_3_pl] %d monet.,Você pegou %d moedas de ouro.,Apanhaste %d moedas de ouro.,Ai ridicat %g bucăți de aur.,Получено %d золотых.,Покупио си %d златника.,Du plockade upp %d guld.,%d altın aldın.,Взято %d золотих. +You picked up the Teleporter Beacon.,TXT_BEACON,,,,Sebral@[ao_cs] jsi teleportační maják.,Du samlede Teleporter Beacon op.,Du hast das Teleportersignal genommen.,,Vi trovis teleportil-signalilon.,Encuentras una baliza de teletransporte.,,Poimit kaukosiirrinmajakan.,Vous avez pris la balise de téléporteur.,Felvetted a Teleport jelzőt.,Hai raccolto il Radiofaro per Teletrasporto.,テレポータービーコン 取得。,텔레포터 비콘을 획득했다.,Je hebt de teleporterbaken opgepakt.,Du plukket opp Teleporter-signalet.,Podniosł@[irreg_3_pl] Nadajnik Teleportera.,Você pegou o Sinalizador de Teletransporte.,Apanhaste o Sinalizador de Teletransporte.,Ai ridicat Luminatorul pentru Teleportor.,Получен телепортационный маяк.,Покупио си одашиљач за телепортовање.,Du plockade upp teleporterfyren.,Işınlayıcı İşaretini aldın.,Взято пристрій телепортації. +You picked up the Degnin Ore.,TXT_DEGNINORE,,,,Sebral@[ao_cs] jsi degninskou rudu.,Du samlede Degnin Ore op.,Du hast das Degnin-Erz genommen.,,Vi trovis degninan minaĵon.,Encuentras mineral de Degnin.,,Poimit Degnin-malmia.,Vous avez pris le minerai de Degnin.,Felvetted a Degnin Ércet.,Hai raccolto il Minerale Degnin.,デグニン鉱石 取得。,데그닌 광석을 획득했다.,Je hebt het Degnin-erts opgepakt.,Du plukket opp Degnin-malmen.,Podniosł@[irreg_3_pl] Rudę Degninu.,Você pegou o Minério Degnin.,Apanhaste o Minério Degnin.,Ai ridicat minereul de Degnin.,Получена дегнинская руда.,Покупио си Дегнинску руду.,Du plockade upp Degnin Malm.,Degnin Cevherini aldın.,Взято Дегінську руду. +You picked up the scanner.,TXT_SCANNER,,,,Sebral@[ao_cs] jsi skener.,Du samlede scanneren op.,Du hast den Scanner genommen.,Πήρες το σαρωτή.,Vi trovis skanilon.,Encuentras un escáner.,,Poimit skannerin.,Vous avez pris l'analyseur.,Felvetted a szkennert.,Hai raccolto lo Scanner.,スキャナー 入手。,탐지기를 획득했다.,Je hebt de scanner opgepakt.,Du plukket opp skanneren.,Podniosł@[irreg_3_pl] skaner.,Você pegou o scanner.,Apanhaste o scanner.,Ai ridicat scannerul.,Получен сканер.,Покупио си скенер.,Du plockade upp skannern.,Tarayıcıyı aldın.,Отримано сканер. "The scanner won't work without a map! ",TXT_NEEDMAP,,,,Skener bez mapy fungovat nebude!,"Scanneren virker ikke uden et kort! -",Der Scanner kann ohne Karte nicht funktionieren.,Ο σαρωτής δέν θα δουλέψει χωρίς ένα χάρτη!,La skanilo ne funkcios sen mapo!,¡El escáner no funcionará sin un mapa!,,Skanneri ei toimi ilman karttaa!,"L'analyseur ne marchera pas sans une carte! +",Der Scanner kann ohne Karte nicht funktionieren.,Ο σαρωτής δέν θα δουλέψει χωρίς ένα χάρτη!,La skanilo ne funkcias sen mapo!,¡El escáner no funciona sin un mapa!,,Skanneri ei toimi ilman karttaa!,"L'analyseur ne marchera pas sans une carte! ",Térkép nélkül nem fog működni a szkenner!,Lo scanner non può funzionare senza una mappa!,マップが無ければ スキャナーは機能しない!,지도 없이는 탐지기를 사용할 수 없다!,De scanner werkt niet zonder een kaart!,"Skanneren virker ikke uten et kart! ",Skaner nie zadziała bez mapy!,"O scanner não funciona sem um mapa! ",,Scannerul nu poate funcționa fără o hartă!,"Сканер не будет работать без карты! -",Скенер неће радити без мапе!,"Tarayıcı harita olmadan çalışmaz! -" -You picked up the Prison pass.,TXT_PRISONPASS,,,,Sebral@[ao_cs] jsi propustku do vězení.,Du samlede fængselspasset op.,Du hast den Gefängnispass genommen.,,Vi havas la malliberejan paspermeson.,Tienes el pase a la prisión.,,Poimit vankilan pääsyluvan.,Vous avez pris le passe de la prison.,Felvetted a Börtön belépőkártyát.,Hai raccolto il lasciapassare per la Prigione.,刑務所の許可証 取得。,감옥 통행증을 획득했다.,Je hebt de gevangenispas opgepakt.,Du plukket opp fengselspasset.,Podniosł@[irreg_3_pl] przepustkę do Więzienia.,Você pegou o passe da Prisão.,Apanhaste o passe da Prisão.,Ai ridicat Legitimația pentru Închisoare.,Получен пропуск в тюрьму.,Покупио си затворску пропусницу.,Hapishane kartını aldın. -You picked up the crossbow.,TXT_STRIFECROSSBOW,,,,Sebral@[ao_cs] jsi kuši.,Du samlede armbrøst op.,Du hast die Armbrust genommen.,Πήρες το τόξο,Vi trovis arbaleston.,Encuentras una ballesta.,,Poimit jousipyssyn.,Vous avez pris l'arbalète.,Felvetted a számszeríjat.,Hai raccolto la Balestra.,クロスボウ 入手。,석궁을 획득했다.,Je hebt de kruisboog opgepakt.,Du plukket opp armbrøsten.,Podniosł@[irreg_3_pl] kuszę.,Você pegou a besta.,Apanhaste uma besta.,Ai ridicat arbaleta.,Получен арбалет.,Покупио си самострел.,Tatar yayını aldın. -You picked up the assault gun.,TXT_ASSAULTGUN,,,,Sebral@[ao_cs] jsi pušku.,Du samlede pistolen op.,Du hast das Sturmgewehr genommen.,Πήρες το πολυβόλο.,Vi trovis sturmofusilon.,Encuentras un fusil de asalto.,,Poimit rynnäkkökiväärin.,Vous avez pris le fusil d'assaut.,Felvetted a gépfegyvert.,Hai raccolto il fucile d'assalto.,アサルトガン 入手。,돌격소총을 획득했다.,Je hebt het aanvalswapen opgepakt.,Du plukket opp stormgeværet.,Podniosł@[irreg_3_pl] karabin szturmowy.,Você pegou o fuzil de assalto.,Apanhaste a arma de assalto.,Ai ridicat pușca de asalt.,Получена штурмовая винтовка.,Покупио си аутоматску пушку.,Saldırı silahını aldın. -You picked up the mini missile launcher.,TXT_MMLAUNCHER,,,,Sebral@[ao_cs] jsi miniraketomet.,Du samlede mini-missilkasteren op.,Du hast den Miniraketenwerfer genommen.,Πήρες το μίνι πυραυλοβόλο.,Vi trovis misilet-pafilon.,Encuentras un minilanzacohetes.,,Poimit miniohjuslaukaisimen.,Vous avez pris le lance mini-missile.,Felvetted a minirakétavetőt.,Hai raccolto il Mini-Lanciamissili.,ミニミサイル ランチャー入手。,미니 미사일 런쳐를 획득했다.,Je hebt de mini-raketwerper opgepakt.,Du plukket opp mini-missilkasteren.,Podniosł@[irreg_3_pl] wyrzutnię minipocisków.,Você pegou o mini lança-mísseis.,Apanhaste o mini lança-mísseis,Ai ridicat mini lansatorul de rachete.,Получена мини-ракетница.,Покупио си мини ручни бацач.,Mini füze fırlatıcısını aldın. -You picked up the flame thrower.,TXT_FLAMER,,,,Sebral@[ao_cs] jsi plamenomet.,Du samlede flammekasteren op.,Du hast den Flammenwerfer genommen.,Πήρες το φλογοβόλο.,Vi trovis flamĵetilon.,Encuentras un lanzallamas.,,Poimit liekinheittimen.,Vous avez pris le lance-flames.,Felvetted a lángszórót.,Hai raccolto il Lanciafiamme.,火炎放射器 入手。,완성된 화염방사기를 얻었다.,Je hebt de vlammenwerper opgepakt.,Du plukket opp flammekasteren.,Podniosł@[irreg_3_pl] miotacz ognia.,Você pegou o lança-chamas.,Apanhaste o lança-chamas.,Ai ridicat aruncătorul de flăcări.,Получен огнемёт.,Покупио си бацач пламена.,Alev silahını aldın. -You picked up the mauler.,TXT_MAULER,,,,Sebral@[ao_cs] jsi trhač.,Du tog mauleren op.,Du hast den Vernichter genommen.,,Vi trovis vundegilon.,Encuentras un triturador.,Hallaste un triturador.,Poimit moukarin.,Vous avez pris le Broyeur.,Felvetted a marcangolót.,Hai raccolto il Pestatore.,マウラー 入手。,마울러를 획득했다.,Je hebt de toetakelaar opgepakt.,Du plukket opp mauleren.,Podniosł@[irreg_3_pl] miażdżyciel.,Você pegou o desintegrador.,Apanhaste o desintegrador.,Ai ridicat sfâșietorul.,Получен истязатель.,Покупио си маулер.,Parçalayıcıyı aldın. -You picked up the Grenade launcher.,TXT_GLAUNCHER,,,,Sebral@[ao_cs] jsi granátomet.,Du samlede granatkasteren op.,Du hast den Granatwerfer genommen.,Πήρες το εκτοξευτη χειροβομβίδων.,Vi trovis grenadĵetilon.,Encuentras un lanzagranadas.,,Poimit kranaatinheittimen.,Vous avez pris le lance-grenades,Felvetted a gránátvetőt.,Hai raccolto il Lanciagranate.,グレネードランチャー 入手。,유탄발사기를 획득했다.,Je hebt de granaatwerper opgepakt.,Du plukket opp granatkasteren.,Podniosł@[irreg_3_pl] wyrzutnię granatów.,Você pegou o lança-granadas.,Apanhaste o lança-granadas.,Ai ridicat Lansatorul de rachete.,Получен гранатомёт.,Покупио си бацач граната.,El bombası fırlatıcısını aldın. -You picked up the SIGIL.,TXT_SIGIL,,,,Sebral@[ao_cs] jsi Pečeť.,Du samlede SIGIL op.,Du hast das SIGIL genommen.,,Vi prenis la SIGELON.,Recogiste el EMBLEMA.,,Poimit SINETIN.,Vous avez pris le SIGIL.,Felvetted a Pecsétet.,Hai raccolto il SIGILLO.,シジル 取得。,시질은 이제 당신의 것이다.,Je hebt de SIGIL opgepakt.,Du plukket opp SIGIL.,Podniosł@[irreg_3_pl] PIECZĘĆ.,Você pegou o SIGILO.,Apanhaste o SIGILO,Ai ridicat SIGILIUL.,Получена ПЕЧАТЬ.,Покупио си СИГИЛ.,SİGİL'i aldın. -You picked up the Base Key.,TXT_BASEKEY,,,,Sebral@[ao_cs] jsi klíč od základny.,Du samlede Base nøglen op.,Du hast den Basisschlüssel genommen.,,Vi havas la ŝlosilon de la bazo.,Tienes la llave de la base.,,Poimit tukikohdan avaimen.,Vous avez pris la clé de la Base.,Felvetted a Bázis kulcsát.,Hai raccolto la chiave della Base.,基地のキー 取得。,기지 키를 획득했다.,Je hebt de basissleutel opgepakt.,Du plukket opp basenøkkelen.,Podniosł@[irreg_3_pl] Klucz do Bazy.,Você pegou a Chave da Base.,Apanhaste a Chave da Base.,Ai ridicat Cheia Bazei.,Получен ключ от базы.,Покупио си кључ базе.,Üs Anahtarını aldın. -You picked up the Govs Key.,TXT_GOVSKEY,,,,Sebral@[ao_cs] jsi klíč ke guvernérovi.,Du samlede guvernørens nøglen op.,Du hast den Gouverneursschlüssel genommen.,,Vi havas la ŝlosilon de la registo.,Tienes la llave del Gobernador.,,Poimit kuvernöörin avaimen.,Vous avez pris la clé du Gouverneur.,Felvetted a Kormányzó parcellájának kulcsát.,Hai raccolto la chiave del Governatore.,政府のキー 取得。,총독의 키를 획득했다.,Je hebt de gouverneursleutel opgepakt.,Du plukket opp regjeringsnøkkelen.,Podniosł@[irreg_3_pl] Klucz Gubernatora.,Você pegou a Chave do Governador.,Apanhaste a Chave do Governador.,Ai ridicat Cheia Guvernatorului.,Получен ключ губернатора.,Покупио си клуч гувернанте.,Hükümet Anahtarını aldın. -You picked up the Passcard.,TXT_PASSCARD,,,,Sebral@[ao_cs] jsi průkazku.,Du samlede Adgangskort op.,Du hast die Zugangskarte genommen.,,Vi havas la ŝlosilon de la elektra centralo.,Tienes la llave de la central eléctrica.,,Poimit avainkortin.,Vous avez pris le passe.,Felvetted a Belépőkártyát.,Hai raccolto la Tessera Lasciapassare.,パスカード 取得。,통행 카드를 획득했다.,Je hebt de doorgangskaart opgepakt.,Du plukket opp adgangskortet.,Podniosł@[irreg_3_pl] Kartę Dostępu.,Você pegou o Cartão de Acesso.,Apanhaste o Cartão de Acesso.,Ai ridicat Legitimația.,Получен пропуск.,Покупио си пасош.,Erişim kartıni aldın. -You picked up the ID Badge.,TXT_IDBADGE,,,,Sebral@[ao_cs] jsi identifikační odznak.,Du samlede ID Badge op.,Du hast die Identitätskarte genommen.,,Vi havas la insignon de la malliberejo.,Tienes la insignia de la prisión.,,Poimit henkilötunnisteen.,Vous avez pris le Badge d'identification.,Felvetted az Azonosítójelvényt.,Hai raccolto il Distintivo.,IDバッジ 取得。,신분 휘장을 획득했다.,Je hebt de ID-badge opgepakt.,Du plukket opp ID-skiltet.,Podniosł@[irreg_3_pl] Odznakę Identyfikacyjną.,Você pegou o Crachá de Identificação.,Apanhaste o Crachá de Identificação,Ai ridicat Ecusonul de Identificare.,Получена личная карта.,Покупио си личну карту.,Kimlik Rozetini aldın. -You picked up the Prison Key.,TXT_PRISONKEY,,,,Sebral@[ao_cs] jsi klič k vězení.,Du samlede nøglen til fængslet op.,Du hast den Gefängnisschlüssel genommen.,,Vi havas la ŝlosilon de la malliberejo.,Tienes la llave de la prisión.,,Poimit vankilan avaimen.,Vous avez pris la clé de la Prison.,Felvetted a Börtönkulcsot.,Hai raccolto la chiave della Prigione.,刑務所のキー 取得。,감옥 키를 획득했다.,Je hebt de gevangenissleutel opgepakt.,Du plukket opp Fengselsnøkkelen.,Podniosł@[irreg_3_pl] Klucz do Więzienia.,Você pegou a Chave da Prisão.,Apanhaste a Chave da Prisão.,Ai ridicat Cheia Închisorii.,Получен ключ от тюрьмы.,Покупио си затворски кључ,Hapishane Anahtarını aldın. -You picked up the Severed Hand.,TXT_SEVEREDHAND,,,,Sebral@[ao_cs] jsi useknutou ruku.,Du samlede den afhuggede hånd op.,Du hast die abgetrennte Hand genommen.,,Vi havas amputitan manon.,Tienes una mano amputada.,,Poimit katkenneen käden.,Vous avez pris la main coupée.,Felvetted a Levágott kezet.,Hai raccolto la Mano Mozzata.,切り取った手 取得。,잘린 손목을 주웠다.,Je hebt de Gescheurde Hand opgepakt.,Du plukket opp den avkuttede hånden.,Podniosł@[irreg_3_pl] Odciętą Rękę.,Você pegou a Mão Decepada.,Apanhaste a Mão Desmenbrada.,Ai ridicat Mâna Retezată.,Получена отрезанная рука.,Покупио си шаку,Kesik El'i aldın. -You picked up the Power1 Key.,TXT_POWER1KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 1.,Du samlede Power1-nøglen op.,Du hast den Kraftwerksschlüssel 1 genommen,,Vi havas la unuan centralan identigilon.,Tienes una identificación nivel uno de la central.,,Poimit voimalan 1-avaimen.,Vous avez pris la clé Power1.,Felvetted az 1-es Áram kulcsot.,Hai raccolto la chiave della Centrale n.1,パワー1キー 取得。,발전소 1호 키를 획득했다.,Je hebt de 1e Machtsleutel opgepakt.,Du plukket opp Power1-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Elektrowni 1.,Você pegou a Chave da Usina 1.,Apanhaste a Chave Energética 1,Ai ridicat Cheia Putere1.,Получен ключ электростанции №1.,Покупио си први кључ од електране.,Güç1 Anahtarını aldın. -You picked up the Power2 Key.,TXT_POWER2KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 2.,Du samlede Power2-nøglen op.,Du hast den Kraftwerksschlüssel 2 genommen,,Vi havas la duan centralan identigilon.,Tienes una identificación nivel dos de la central.,,Poimit voimalan 2-avaimen.,Vous avez pris la clé Power2.,Felvetted az 2-es Áram kulcsot.,Hai raccolto la chiave della Centrale n.2,パワー2キー 取得。,발전소 2호 키를 획득했다.,Je hebt de 2e Machtsleutel opgepakt.,Du plukket opp Power2-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Elektrowni 2.,Você pegou a Chave da Usina 2.,Apanhaste a Chave Energética 2,Ai ridicat Cheia Putere2.,Получен ключ электростанции №2.,Покупио си други кључ од електране.,Güç2 Anahtarını aldın. -You picked up the Power3 Key.,TXT_POWER3KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 3.,Du samlede Power3-nøglen op.,Du hast den Kraftwerksschlüssel 3 genommen,,Vi havas la trian centralan identigilon.,Tienes una identificación nivel tres de la central.,,Poimit voimalan 3-avaimen.,Vous avez pris la clé Power3.,Felvetted az 3-as Áram kulcsot.,Hai raccolto la chiave della Centrale n.3,パワー3キー 取得。,발전소 3호 키를 획득했다.,Je hebt de 3e Machtsleutel opgepakt.,Du plukket opp Power3-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Elektrowni 3.,Você pegou a Chave da Usina 3.,Apanhaste a Chave Energética 3,Ai ridicat Cheia Putere3.,Получен ключ электростанции №3.,Покупио си трећи кључ од електране.,Güç3 Anahtarını aldın. -You picked up the Gold Key.,TXT_GOLDKEY,,,,Sebral@[ao_cs] jsi zlatý klíč.,Du samlede den guldnøglen op.,Du hast den Goldschlüssel genommen.,,Vi havas oran ŝlosilon.,Tienes una llave dorada.,,Poimit kulta-avaimen.,Vous avez pris la clé d'or.,Felvetted az Aranykulcsot.,Hai raccolto la chiave dorata,ゴールドキー 取得。,황금 키를 획득했다.,Je hebt de gouden sleutel opgepakt.,Du plukket opp Gullnøkkelen.,Podniosł@[irreg_3_pl] Złoty Klucz.,Você pegou a Chave de Ouro.,Apanhaste a Chave de Ouro,Ai ridicat Cheia de Aur.,Получен золотой ключ.,Покупио си златни кључ.,Altın Anahtarı aldın. -You picked up the ID Card.,TXT_IDCARD,,,,Sebral@[ao_cs] jsi ID kartu.,Du samlede ID-kortet op.,Du hast den Ausweis genommen.,,Vi havas identigilon de la kloakoj.,Tienes una identificación de las alcantarillas.,,Poimit henkilökortin.,Vous avez pris la Carte d'identité.,Felvetted az Igazolványt.,Hai raccolto la Tessera di Identificazione.,IDカード 取得。,신분증을 획득했다.,Je hebt de ID-kaart opgepakt.,Du plukket opp ID-kortet.,Podniosł@[irreg_3_pl] Kartę Identyfikacyjną.,Você pegou o Cartão de Identifiçacão.,Apanhaste o Cartão de Identificação,Ai ridicat Cardul de Identitate.,Получено удостоверение.,Покупио си идентификациону картицу.,Kimlik Kartını aldın. -You picked up the Silver Key.,TXT_SILVERKEY,,,,Sebral@[ao_cs] jsi stříbrný klíč.,Du tog sølvnøglen op.,Du hast den Silberschlüssel genommen.,,Vi havas arĝentan ŝlosilon.,Tienes una llave plateada.,,Poimit hopea-avaimen.,Vous avez pris la clé d'argent.,Felvetted az Ezüstkulcsot.,Hai raccolto la chiave argentata,シルバーキー 取得。,은 키를 획득했다.,Je hebt de zilveren sleutel opgepakt.,Du plukket opp sølvnøkkelen.,Podniosł@[irreg_3_pl] Srebrny Klucz.,Você pegou a Chave de Prata.,Apanhaste a Chave de Prata,Ai ridicat Cheia de Argint.,Получен серебряный ключ.,Покупио си сребрни кључ.,Gümüş Anahtarı aldınız. -You picked up the Oracle Key.,TXT_ORACLEKEY,,,,Sebral@[ao_cs] jsi věštcův klíč.,Du tog Oracle-nøglen op.,Du hast den Orakelschlüssel genommen.,,Vi havas ŝlosilon de la Orakolo,Tienes una llave del Oráculo.,,Poimit Oraakkelin avaimen.,Vous avez pris la clé Oraclé.,Felvetted az Orákulum kulcsát.,Hai raccolto la chiave dell'Oracolo.,オラクルキー 取得。,오라클 키를 획득했다.,Je hebt de Orakelsleutel opgepakt.,Du plukket opp Oracle-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Wyroczni.,Você pegou a Chave do Oráculo.,Apanhaste a Chave do Oráculo.,Ai ridicat Cheia Oracol.,Получен ключ Оракула.,Покупио си кључ пророка,Kahin Anahtarını aldın. -You picked up the Military ID.,TXT_MILITARYID,,,,Sebral@[ao_cs] jsi vojenské ID.,Du samlede militær-ID op.,Du hast den Militärausweis genommen.,,Vi havas militan identigilon.,Tienes una identificación militar.,,Poimit sotilastunnuksen.,Vous avez pris l'ID Militaire.,Felvetted a Katonai igazolványt.,Hai raccolto l'Identificativo Militare.,ミリタリーID 取得。,군용 아이디를 획득했다.,Je hebt de militaire ID opgepakt.,Du plukket opp den militære ID-en.,Podniosł@[irreg_3_pl] Wojskowy Identyfikator.,Você pegou a Identificação Militar.,Apanhaste a Identificação Militar.,Ai ridicat Legitimația Militară.,Получено военное удостоверение.,Покупио си војну идентификацију,Askeri Kimliği aldın. -You picked up the Order Key.,TXT_ORDERKEY,,,,Sebral@[ao_cs] jsi klíč Řádu.,Du samlede Ordensnøglen op.,Du hast den Ordensschlüssel genommen.,,Vi prenis la Ŝlosilon de La Ordono.,Tienes la llave de La Orden.,,Poimit Veljeskunnan avaimen.,Vous avez pris la clé de l'Ordre.,Felvetted a Rend kulcsát.,Hai raccolto la chiave dell'Ordine.,オーダーキー 取得。,오더의 키를 획득했다.,Je hebt de Ordesleutel opgepakt.,Du plukket opp Bestillingsnøkkelen.,Podniosł@[irreg_3_pl] Klucz Zakonu.,Você pegou a Chave da Ordem.,Apanhaste a Chave da Ordem.,Ai ridicat Cheia Ordinului.,Получен ключ Ордена.,Покупио си кључ одреда,Emir Anahtarını aldın. -You picked up the Warehouse Key.,TXT_WAREHOUSEKEY,,,,Sebral@[ao_cs] jsi klíč ke skladu.,Du samlede lagernøglen op.,Du hast den Lagerhausschlüssel genommen,,Vi prenis la Ŝlosilon de la Magazeno.,Recogiste la Llave del Almacén.,,Poimit varaston avaimen.,Vous avez pris la clé de l'entrepôt.,Felvetted a Raktár kulcsát.,Hai raccolto la chiave del Magazzino.,倉庫のキー 取得。,창고 키를 획득했다.,Je hebt de pakhuissleutel opgepakt.,Du plukket opp Lagernøkkelen.,Podniosł@[irreg_3_pl] Klucz do Magazynu.,Você pegou a Chave do Armazém.,Apanhaste a Chave do Armazém,Ai ridicat Cheia Depozitului.,Получен ключ от склада.,Покупио си кључ складишта,Depo Anahtarını aldın. -You picked up the Brass Key.,TXT_BRASSKEY,,,,Sebral@[ao_cs] jsi mosazný klíč.,Du samlede messingnøglen op.,Du hast den Messingschlüssel genommen.,,Vi prenis la Latunan Ŝlosilon.,Recogiste la Llave de Latón.,,Poimit messinkiavaimen.,Vous avez pris la clé de bronze.,Felvetted a Rézkulcsot.,Hai raccolto la chiave d'Ottone.,ブラスキー 取得。,황동 키를 획득했다.,Je hebt de messing sleutel opgepakt.,Du plukket opp messingnøkkelen.,Podniosł@[irreg_3_pl] Mosiężny Klucz.,Você pegou a Chave de Latão.,Apanhaste a Chave de Latão,Ai ridicat Cheia din Alamă.,Получен латунный ключ.,Покупио си кључ месинга,Pirinç Anahtarı aldın. -You picked up the Red Crystal Key.,TXT_REDCRYSTAL,,,,Sebral@[ao_cs] jsi červený krystalový klíč.,Du samlede den røde krystalnøgle op.,Du hast den roten Kristallschlüssel genommen.,,Vi prenis la Ruĝan Kristalan Ŝlosilon.,Recogiste la Llave de Cristal Rojo.,,Poimit punaisen kristalliavaimen.,Vous avez pris la clé cristal rouge.,Felvetted a Vörös Kristály Kulcsot.,Hai raccolto la chiave del Cristallo Rosso.,赤水晶のキー 取得。,적색 크리스탈 키를 획득했다.,Je hebt de rode kristallen sleutel opgepakt.,Du plukket opp den røde krystallnøkkelen.,Podniosł@[irreg_3_pl] Czerwony Kryształowy Klucz.,Você pegou a Chave de Cristal Vermelho.,Apanhaste a Chave de Cristal Vermelho.,Ai ridicat Cheia din Cristal Roșu.,Получен красный ключ-кристалл.,Покупио си кључ од црвеног кристала,Kırmızı Kristal Anahtarı aldın. -You picked up the Blue Crystal Key.,TXT_BLUECRYSTAL,,,,Sebral@[ao_cs] jsi modrý krystalový klíč.,Du samlede den blå krystalnøgle op.,Du hast den blauen Kristallschlüssel genommen.,,Vi prenis la Bluan Kristalan Ŝlosilon,Recogiste la Llave de Cristal Azul.,,Poimit sinisen kristalliavaimen.,Vous avez pris la clé cristal bleu.,Felvetted a Kék Kristály Kulcsot.,Hai raccolto la chiave del Cristallo Blu.,青水晶のキー 取得。,청색 크리스탈 키를 획득했다.,Je hebt de blauwe kristallen sleutel opgepakt.,Du plukket opp den blå krystallnøkkelen.,Podniosł@[irreg_3_pl] Niebieski Kryształowy Klucz.,Você pegou a Chave de Cristal Azul.,Apanhaste a Chave de Cristal Azul.,Ai ridicat Cheia din Cristal Albastru.,Получен синий ключ-кристалл.,Покупио си кључ од плавог кристала,Mavi Kristal Anahtarı aldın. -You picked up the Chapel Key.,TXT_CHAPELKEY,,,,Sebral@[ao_cs] jsi klíč ke kapli.,Du samlede Kapel-nøglen op.,Du hast den Kapellenschlüssel genommen.,,Vi prenis la Ŝlosilon de la Preĝejeto.,Recogiste la Llave de la Capilla.,,Poimit kappelin avaimen.,Vous avez pris la clé de la chapelle.,Felvetted a Kápolna Kulcsát.,Hai raccolto la chiave della Cappella,チャペルキー 取得。,예배당 키를 획득했다.,Je hebt de kapelsleutel opgepakt.,Du plukket opp kapellnøkkelen.,Podniosł@[irreg_3_pl] Klucz do Kaplicy.,Você pegou a Chave da Capela.,Apanhaste a Chave da Capela.,Ai ridicat Cheia Capelei.,Получен ключ от часовни.,Покупио си кључ капеле,Şapel Anahtarını aldın. -You picked up the Catacomb Key.,TXT_CATACOMBKEY,,,,Sebral@[ao_cs] jsi klíč do katakomb.,Du samlede Katakombe-nøglen op.,Du hast den Katakombenschlüssel genommen.,,Vi prenis la Ŝlosilon de la Katakombo.,Recogiste la Llave de la Catacumba.,,Poimit katakombin avaimen.,Vous avez pris la clé des catacombes.,Felvetted a Katakombák kulcsát.,Hai raccolto la chiave delle Catacombe.,カタコンベキー 取得。,고대 묘지 키를 획득했다.,Je hebt de catacombesleutel opgepakt.,Du plukket opp Katakomb-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Katakumb.,Você pegou a Chave da Catacumba.,Apanhaste a Chave da Catacumba.,Ai ridicat Cheia Catacombei.,Получен ключ от катакомб.,Покупио си кључ катакомбе,Yeraltı Mezarı Anahtarını aldın. -You picked up the Security Key.,TXT_SECURITYKEY,,,,Sebral@[ao_cs] jsi klíč ochranky.,Du samlede sikkerhedsnøglen op.,Du hast den Sicherheitsschlüssel genommen.,,Vi prenis la Sekurecŝlosilon.,Recogiste la Llave de Seguridad.,,Poimit turvamiesavaimen.,Vous avez pris la clé de la sécurité.,Felvetted a Biztonsági Kulcsot.,Hai raccolto la chiave della Sicurezza.,警備のキー 取得。,보안 키를 획득했다.,Je hebt de beveiligingssleutel opgepakt.,Du plukket opp Sikkerhetsnøkkelen.,Podniosł@[irreg_3_pl] Klucz Ochrony.,Você pegou a Chave de Seguranca.,Apanhaste a Chave de Segurança,Ai ridicat Cheia Securității.,Получен ключ охраны.,Покупио си кључ обезбеђења,Güvenlik Anahtarını aldın. -You picked up the Core Key.,TXT_COREKEY,,,,Sebral@[ao_cs] jsi klíč k jádru.,Du samlede reaktornøglen op.,Du hast den Reaktorschlüssel genommen.,,Vi trovis la ŝlosilon de la kernejo.,Encuentras la llave del núcleo.,Hallaste la llave del núcleo.,Poimit ytimen avaimen.,Vous avez pris la clé du réacteur.,Felvetted a Mag kulcsát.,Hai raccolto la chiave del Nucleo.,コアキー 取得。,중심부 키를 획득했다.,Je hebt de kernsleutel opgepakt.,Du plukket opp Kjernenøkkelen.,Podniosł@[irreg_3_pl] Klucz do Rdzenia.,Você pegou a Chave do Núcleo.,Apanhaste a Chave do Núcleo.,Ai ridicat Cheia Nucleului.,Получен ключ от реактора.,Покупио си кључ језгра,Çekirdek Anahtarını aldın. -You picked up the Mauler Key.,TXT_MAULERKEY,,,,Sebral@[ao_cs] jsi klíč k trhačům.,Du samlede Mauler-nøglen op.,Du hast den Vernichterschlüssel genommen.,,Vi havas la ŝlosilon de la vundegiloj.,Tiene la llave de los trituradores.,,Poimit moukarin avaimen.,Vous avez pris la clé du Broyeur.,Felvetted a Marcangoló kulcsot.,Hai raccolto la chiave del Pestatore.,マウラーキー 取得。,마울러 키를 획득했다.,Je hebt de toetakelaarssleutel opgepakt.,Du plukket opp Mauler-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Magazynu Miażdżycieli.,Você pegou a Chave do Mauler.,Apanhaste a Chave do Mauler.,Ai ridicat Cheia Sfâșietorului.,Получен ключ истязателя.,Покупио си кључ Маулера.,Mauler Anahtarını aldın. -You picked up the Factory Key.,TXT_FACTORYKEY,,,,Sebral@[ao_cs] jsi klíč do továrny.,Du samlede fabriksnøglen op.,Du hast den Fabrikschlüssel genommen.,,Vi prenis la Ŝlosilon de la Fabriko.,Recogiste la Llave de la Fábrica.,,Poimit tehtaan avaimen.,Vous avez pris la clé de l'usine.,Felvetted a Gyár kulcsát.,Hai raccolto la chiave della Fabbrica.,工場のキー 取得。,공장 키를 획득했다.,Je hebt de fabriekssleutel opgepakt.,Du plukket opp fabrikknøkkelen.,Podniosł@[irreg_3_pl] Klucz do Fabryki.,Você pegou a Chave da Fábrica.,Apanhaste a Chave da Fábrica.,Ai ridicat Cheia Fabricii.,Получен ключ от фабрики.,Покупио си кључ фабрике,Fabrika Anahtarını aldın. -You picked up the Mine Key.,TXT_MINEKEY,,,,Sebral@[ao_cs] jsi klíč do dolů.,Du samlede minenøglen op.,Du hast den Minenschlüssel genommen.,,Vi prenis la Ŝlosilon de la Minejo.,Recogiste la Llave de la Mina.,,Poimit kaivoksen avaimen.,Vous avez pris la clé de la mine.,Felvetted a Bánya kulcsát.,Hai raccolto la chiave della Miniera.,鉱山のキー 取得。,탄광 키를 획득했다.,Je hebt de mijnsleutel opgepakt.,Du plukket opp Gruvenøkkelen.,Podniosł@[irreg_3_pl] Klucz do Kopalni.,Você pegou a Chave da Mina.,Apanhaste a Chave da Mina.,Ai ridicat Cheia Minei.,Получен ключ от шахт.,Покупио си кључ рудника,Maden Anahtarını aldın. -You picked up the New Key5.,TXT_NEWKEY5,,,,Sebral@[ao_cs] jsi nový klíč 5.,Du samlede den nye nøgle5 op.,Du hast den neuen Schlüssel 5 genommen.,,Vi prenis la Novan Ŝlosilon5.,Recogiste la Llave Nueva5.,,Poimit uuden 5-avaimen.,Vous avez pris la nouvelle clé 5.,Felvetted az 5. kulcsot.,Hai raccolto la Nuova Chiave n.5,ニューキー5 取得。,새로운 키5를 획득했다.,Je hebt de nieuwe sleutel 5 opgepakt.,Du plukket opp den nye nøkkelen5.,Podniosł@[irreg_3_pl] Nowy Klucz5,Você pegou a Chave Nova 5.,Apanhaste a Chave Nova 5.,Ai ridicat Cheia Nouă5.,Получен новый ключ №5.,Покупио си нови кључ5,Yeni Anahtar5'i aldın. -You picked up the Oracle Pass.,TXT_ORACLEPASS,,,,Sebral@[ao_cs] jsi věštcovu propustku.,Du samlede orakelpas op.,Du hast den Orakelpass genommen.,,Vi prenis la Pasaĵo de la Okralo.,Recogiste el Pase del Oráculo.,,Poimit Oraakkelin passin.,Vous avez pris le passe de l'Oracle.,Felvetted az Orákulum Belépőkártyáját.,Hai raccolto il Lasciapassare dell'Oracolo.,オラクルパス 取得。,오라클의 통행증을 획득했다.,Je hebt de Orakelkaart opgepakt.,Du plukket opp Orakelpasset.,Podniosł@[irreg_3_pl] Przepustkę Wyroczni.,Você pegou o Passe do Oráculo.,Apanhaste o Passe do Oráculo.,Ai ridicat Legitimația Oracol.,Получен пропуск Оракула.,Покупио си пророкову пропусницу,Kahin Geçiş Kartını aldın. -You picked up the HE-Grenade Rounds.,TXT_HEGRENADES,,,,Sebral@[ao_cs] jsi výbušné granáty.,Du samlede HE-granaterne op.,Du hast die HE-Granaten genommen.,,Vi prenis la PE-Gernadmuniciojn.,Recogiste las Granadas HE.,,Poimit räjähdekranaattiammuksia.,Vous avez pris les Grenades Explosives.,Felvetted a robbanó gránátot.,Hai raccolto delle granate ad Alto Potenziale,HEグレネード弾 入手。,고폭 유탄을 획득했다.,Je hebt de HE-granaten opgepakt.,Du plukket opp HE-granaten.,Podniosł@[irreg_3_pl] Wiązkę Granatów.,Você pegou as Granadas Explosivas.,Apanhaste as Granadas Explosivas.,Ai ridicat Grenadele Explozive.,Получена связка гранат.,Покупио си ХЕ-Граната чауре,HE-Bombası Mermilerini aldın. -You picked up the Phosphorus-Grenade Rounds.,TXT_PHGRENADES,,,,Sebral@[ao_cs] jsi fosforové granáty.,Du samlede fosforgranaterne op.,Du hasr die Phosphorgranaten genommen.,,Vi prenis la Fosforajn Gernadmuniciojn.,Recogiste las Granadas de Fósforo.,,Poimit fosforikranaattiammuksia.,Vous avez pris les Grenades Phosphoriques.,Felvetted a foszfor-gránátokat.,Hai raccolto delle Granate al Fosforo.,白リングレネード弾 入手。,소이 유탄을 획득했다.,Je hebt de fosforgranaten opgepakt.,Du plukket opp fosforgranaten.,Podniosł@[irreg_3_pl] Wiązkę Fosforowych Granatów.,Você pegou as Granadas de Fósforo.,Apanhaste as Granadas de Fósforo.,Ai ridicat Grenadele cu Fosfor.,Получена связка фосфорных гранат.,Покупио си шаржер фосфорних граната.,Fosforlu El Bombası Mermilerini aldın. -You picked up the clip of bullets.,TXT_CLIPOFBULLETS,,,,Sebral@[ao_cs] jsi zásobník s náboji.,Du samlede patroner op.,Du hast die Gewehrmunition genommen.,Πήρες το κουτάκι με σφαίρες.,Vi prenis la kuglujon.,Recogiste un cargador con balas.,,Poimit luotilippaan.,Vous avez pris le Chargeur.,Felvettél egy tár lőszert.,Hai raccolto un caricatore di proiettili.,銃弾倉 入手。,돌격소총 탄창을 획득했다.,Je hebt de patroon met kogels opgepakt.,Du plukket opp magasinet med kuler.,Podniosł@[irreg_3_pl] magazynek.,Você pegou o carregador.,Apanhaste o carregador.,Ai ridicat cartușul cu gloanțe.,Получена обойма.,,Mermi şarjörünü aldın. -You picked up the box of bullets.,TXT_BOXOFBULLETS,,,,Sebral@[ao_cs] jsi krabici nábojů.,Du samlede kassen med kugler op.,Du hast die Munitionskiste genommen.,Πήρες το κουτί με σφαίρες.,Vi prenis la kuglarujon.,Recogiste una caja de balas.,,Poimit luotilaatikon.,Vous avez pris la boîte de balles.,Felvettél egy doboz lőszert.,Hai raccolto una scatola di proiettili.,弾薬箱 入手。,돌격소총 탄약 박스를 획득했다.,Je hebt de doos met kogels opgepakt.,Du plukket opp esken med kuler.,Podniosł@[irreg_3_pl] pudło z amunicją.,Você pegou a caixa de balas.,Apanhaste a caixa de balas.,Ai ridicat cutia cu gloanțe.,Получена коробка патронов.,Покупио си кутију меткова,Mermi kutusunu aldın. -You picked up the mini missiles.,TXT_MINIMISSILES,,,,Sebral@[ao_cs] jsi minirakety.,Du samlede mini-missiler op.,Du hast die Miniraketen genommen.,Πήρες τους μινι-πυράυλους.,Vi prenis la misiletojn.,Recogiste mini misiles.,,Poimit miniohjuksia.,Vous avez pris les mini-missiles.,Felvetted a minirakétákat.,Hai raccolto dei mini-missili.,ミニミサイル 入手。,미니 미사일 꾸러미를 획득했다.,Je hebt de mini-raketten opgepakt.,Du plukket opp minirakettene.,Podniosł@[irreg_3_pl] mini pociski.,Você pegou os mini-mísseis.,Apanhaste os mini-mísseis.,Ai ridicat mini proiectilele.,Получены мини-ракеты.,Покупио си мини ракете,Mini füzeleri aldın. -You picked up the crate of missiles.,TXT_CRATEOFMISSILES,,,,Sebral@[ao_cs] jsi bednu miniraket.,Du samlede kassen med missiler op.,Du hast die Miniraketenkiste genommen.,Πήρες το κιβώτιο με πυράυλους.,Vi prenis la misilarujon.,Recogiste una caja de misiles.,,Poimit ohjuslaatikon.,Vous avez pris la caisse de missiles.,Felvettél egy ládányi minirakétát.,Hai raccolto una cassa di missili.,ミサイルの箱 入手。,미니 미사일 박스를 획득했다.,Je hebt de kist met raketten opgepakt.,Du plukket opp kassen med missiler.,Podniosł@[irreg_3_pl] skrzynię z pociskami.,Você pegou a caixa de mísseis.,Apanhaste a caixa de mísseis.,Ai ridicat lada cu proiectile.,Получен ящик мини-ракет.,Покупио си кутију ракета,Füze sandığını aldın. -You picked up the energy pod.,TXT_ENERGYPOD,,,,Sebral@[ao_cs] jsi energetický kokón.,Du samlede energipoden op.,Du hast die Energiezelle genommen.,,Vi prenis la umon de energio.,Recogiste una vaina de energía.,,Poimit energia-akun.,Vous avez pris la cellule d'énergie.,Felvettél egy energiahüvelyt.,Hai raccolto un nucleo energetico.,エネルギーポット 入手。,에너지 포드를 획득했다.,Je hebt de energiecel opgepakt.,Du plukket opp energikapselen.,Podniosł@[irreg_3_pl] kapsułę energii.,Você pegou a célula de energia (pequeno).,Apanhaste a célula de energia (pequeno).,Ai ridicat capsula cu energie.,Получена энергокапсула.,Покупио си енергетско постоље.,Enerji kapsülünü aldın. -You picked up the energy pack.,TXT_ENERGYPACK,,,,Sebral@[ao_cs] jsi energetický svazek.,Du samlede energipakken op.,Du hast das Energiepack genommen.,,Vi prenis la pako de energio.,Recogiste un pack de energía.,,Poimit energiapaketin.,Vous avez pris le pack énergétique.,Felvetted az energiacsomagot.,Hai raccolto una carica energetica grande.,エネルギーパック 入手。,에너지 팩을 획득했다.,Je hebt het energiepak opgepakt.,Du plukket opp energipakken.,Podniosł@[irreg_3_pl] zasobnik energii.,Você pegou a célula de energia (grande).,Apanhaste a célula de energia (grande).,Ai ridicat pachetul cu energie.,Получен энергокомплект.,Покупио си пакет енергије,Enerji paketini aldın. -You picked up the poison bolts.,TXT_POISONBOLTS,,,,Sebral@[ao_cs] jsi otrávené šípy.,Du samlede giftboltene op.,Du hase die Giftbolzen genommen.,,Vi prenis la venenajn sagetojn.,Recogiste las flechas venenosas.,,Poimit myrkkynuolia.,Vous avez pris les carreaux empoisonnés.,Felvetted a mérgezett nyilakat.,Hai raccolto dei dardi velenosi.,ポイズンボルト 入手。,맹독 볼트를 획득했다.,Je hebt de gifbouten opgepakt.,Du plukket opp giftboltene.,Podniosł@[irreg_3_pl] zatrute bełty.,Você pegou as setas envenenadas.,Apanhaste as setas envenedadas.,Ai ridicat bolțurile cu otravă.,Получены отравленные болты.,Покупио си отровне стреле,Zehirli cıvataları aldın. -You picked up the electric bolts.,TXT_ELECTRICBOLTS,,,,Sebral@[ao_cs] jsi elektrické šípy.,Du samlede de elektriske bolte op.,Du hast die elektrischen Bolzen genommen.,,Vi prenis la elektrajn sagetojn.,Recogiste las flechas eléctricas.,,Poimit sähkönuolia.,Vous avez pris les carreaux électriques.,Felvetted az elektromos nyilakat.,Hai raccolto dei dardi elettrici.,エレクトリックボルト 入手。,전격 볼트를 획득했다.,Je hebt de elektrische bouten opgepakt.,Du plukket opp de elektriske boltene.,Podniosł@[irreg_3_pl] elektryczne bełty.,Você pegou as setas eletricas.,Apanhaste as setas electricas.,Ai ridicat bolțurile cu electricitate.,Получены электрические болты.,Покупио си електричне стреле,Elektrikli cıvataları aldın. -You picked up the ammo satchel.,TXT_AMMOSATCHEL,,,,Sebral@[ao_cs] jsi brašnu na munici.,Du samlede ammunitionstasken op.,Du hast die Munitionstasche genommen.,,Vi prenis la municiingo.,Recogiste un estuche de munición.,,Poimit ammuslaukun.,Vous avez pris la sacoche de munitions,Felvetted a lőszeres táskát.,Hai raccolto una Borsa delle Munizioni.,弾薬鞄 入手。,탄약 배낭을 획득했다.,Je hebt de munitietas opgepakt.,Du plukket opp ammunisjonsvesken.,Podniosł@[irreg_3_pl] torbę z amunicją.,Você pegou a mochila de munição.,Apanhaste a mochila de munição.,Ai ridicat sacoșa cu muniție.,Получен ранец для боеприпасов.,Покупио си торбицу муниције,Cephane çantasını aldın. -You have a feeling that it wasn't to be touched...,MSG_TALISMANRED,,,,"Máš pocit, že jsi na to sahat neměl@[ao_cs]...","Du har en fornemmelse af, at den ikke måtte røres...","Du hast das Gefühl, dass man es nicht anfassen sollte...",,"Vi sentas, ke ĝi ne devas tuŝiĝi...",Tienes la sensación de que no debía ser tocado...,,"Sinusta tuntuu, ettei siihen olisi pitänyt koskea.",Vous avez un pressentiment qu'il ne fallait pas y toucher.....,Úgy érzed azt nem kéne megérinteni...,Hai la sensazione che non doveva essere toccato...,己の勘が 触れてはならない物だと訴えている...,"결코, 만지면 안 된다는 생각이 든다...",Je hebt het gevoel dat het niet aangeraakt dient te worden...,Du har en følelse av at den ikke skulle røres...,"Czujesz, że trzeba było tego nie dotykać...",Você tem um pressentimento de que isso não devia ser tocado...,Tens um pressentimento que não devias ter mexido nisso.,Ai sentimentul că nu trebuia atinsă...,"Кажется, эту вещь лучше не трогать...",Имаш осећај да није требало бити дирано...,İçinizde dokunulmaması gerektiğine dair bir his var. -"Whatever it is, it doesn't belong in this world...",MSG_TALISMANGREEN,,,,"Je jedno, co to je, do tohoto světa to nepatří...","Uanset hvad det er, hører det ikke hjemme i denne verden...","Was auch immer es ist, es gehört nicht in diese Welt...","Οτιδήποτε είναι, δέν είναι απο αυτό τον κόσμο...","Kio ajn ĝi estas, ĝi ne apartenas al ĉi tiu mundo...","Sea lo que sea, no pertenece a este mundo...",,"Mikä ikinä se onkaan, se ei kuulu tähän maailmaan...","Quel que soit cette chose, elle ne devrait pas être ici...","Bármi legyen ez, nem ebben a világban van a helye...","Qualunque cosa sia, non appartiene a questo mondo...",何であろうと、この世には属さない物だ...,뭔지는 몰라도 이 세상에 속한 것이 아닌 것 같다...,"Wat het ook is, het hoort niet thuis in deze wereld...","Uansett hva det er, hører det ikke hjemme i denne verden...","Cokolwiek to jest, nie należy to do tego świata...","Seja o que for, isso não pertence a este mundo...","O que quer que isso seja, não pertence a este mundo...","Orice ar fi, nu are ce căuta în lumea asta...","Что бы это ни было, оно не из этого мира...","Шта год да је, не припада овом свету...","O her neyse, bu dünyaya ait değil." -It must do something...,MSG_TALISMANBLUE,,,,Něco to dělat musí...,Det må gøre noget...,Es muss etwas tun...,Πρέπει να κάνι κάτι...,Ĝi devas fari ion...,Debe hacer algo...,,Sen on pakko tehdä jotakin...,Ca doit servir a quelque chose...,Valamit kell hogy csináljon...,Deve fare qualcosa...,何かを成し遂げなければならない...,분명히 뭔가를 할 것이다...,Het moet iets doen....,Det må gjøre noe...,To musi coś robić...,Deveria fazer alguma coisa...,Devia fazer alguma coisa.,Trebuie să facă ceva...,Оно ведь зачем-то нужно?..,Мора урадити нешто...,Bir şey yapmalı. -You have super strength!,MSG_TALISMANPOWER,,,,Získal@[ao_cs] jsi super sílu!,Du har superstyrke!,Du hast Superkräfte,,Vi havas superan forton!,¡Tienes superfuerza!,,Sinulla on supervoimat!,Vous avez une puissance inégalée!,Tied a Szuper Erő!,Hai la super forza!,豪剛なる力を得た!,엄청난 힘이 솟는다!,Je hebt superkracht!,Du har superkrefter!,Masz super siłę!,Você tem a super força!,Tu tens super força!,Ai super forță!,Вы получили сверхсилу!,Имаш супер снагу!,Süper gücün var! -,,Locks,,,,,,,,,,,,,,,,,,,,,,,, -You don't have the key,TXT_NEEDKEY,,,,Nemáš klíč.,Du har ikke nøglen,Du hast den Schlüssel nicht,Δέν έχεις το κλειδί,Vi ne havas la ŝlosilon,No tienes la llave,,Sinulla ei ole avainta,Vous n'avez pas la clé.,Ehhez nincs kulcsod.,Non hai la chiave necessaria,キーを持っていない,필요한 열쇠가 없다,Je hebt de sleutel niet.,Du har ikke nøkkelen,Nie masz klucza,Você não tem a chave,Tu não tens a chave,Nu ai cheia,Нужен ключ,Немаш кључ,Anahtar sende değil. -You need a passcard,TXT_NEED_PASSCARD,,,,Potřebuješ průkaz.,Du har brug for et adgangskort,Du brauchst eine Zugangskarte.,,Vi bezonas central-ŝlosilon,Necesitas la llave de la central,,Tarvitset avainkortin,Vous avez besoin du passe.,Belépőkártyára lesz szükséged.,Ti serve un lasciapassare,パスカード が必要だ,통행 카드가 필요하다,Je hebt een doorgangskaart nodig.,Du trenger et passerkort,Potrzebujesz karty dostępu,Você precisa de um cartão de acesso,Precisas de um cartão de acesso,Ai nevoie de un card de acces,Нужен пропуск,Треба ти пропусница,Bir erişim kartına ihtiyacınız var +",Скенер неће радити без мапе!,"Skannern fungerar inte utan en karta! +","Tarayıcı harita olmadan çalışmaz! +",Сканер не буде працювати без карти! +You picked up the Prison pass.,TXT_PRISONPASS,,,,Sebral@[ao_cs] jsi propustku do vězení.,Du samlede fængselspasset op.,Du hast den Gefängnispass genommen.,,Vi havas la malliberejan paspermeson.,Tienes el pase a la prisión.,,Poimit vankilan pääsyluvan.,Vous avez pris le passe de la prison.,Felvetted a Börtön belépőkártyát.,Hai raccolto il lasciapassare per la Prigione.,刑務所の許可証 取得。,감옥 통행증을 획득했다.,Je hebt de gevangenispas opgepakt.,Du plukket opp fengselspasset.,Podniosł@[irreg_3_pl] przepustkę do Więzienia.,Você pegou o passe da Prisão.,Apanhaste o passe da Prisão.,Ai ridicat Legitimația pentru Închisoare.,Получен пропуск в тюрьму.,Покупио си затворску пропусницу.,Du plockade upp fängelsepasset.,Hapishane kartını aldın.,Взято пропуск до тюрми. +You picked up the crossbow.,TXT_STRIFECROSSBOW,,,,Sebral@[ao_cs] jsi kuši.,Du samlede armbrøst op.,Du hast die Armbrust genommen.,Πήρες το τόξο,Vi trovis arbaleston.,Encuentras una ballesta.,,Poimit jousipyssyn.,Vous avez pris l'arbalète.,Felvetted a számszeríjat.,Hai raccolto la Balestra.,クロスボウ 入手。,석궁을 획득했다.,Je hebt de kruisboog opgepakt.,Du plukket opp armbrøsten.,Podniosł@[irreg_3_pl] kuszę.,Você pegou a besta.,Apanhaste uma besta.,Ai ridicat arbaleta.,Получен арбалет.,Покупио си самострел.,Du plockade upp armborstet.,Tatar yayını aldın.,Взято арбалет. +You picked up the assault gun.,TXT_ASSAULTGUN,,,,Sebral@[ao_cs] jsi pušku.,Du samlede pistolen op.,Du hast das Sturmgewehr genommen.,Πήρες το πολυβόλο.,Vi trovis sturmofusilon.,Encuentras un fusil de asalto.,,Poimit rynnäkkökiväärin.,Vous avez pris le fusil d'assaut.,Felvetted a gépfegyvert.,Hai raccolto il fucile d'assalto.,アサルトガン 入手。,돌격소총을 획득했다.,Je hebt het aanvalswapen opgepakt.,Du plukket opp stormgeværet.,Podniosł@[irreg_3_pl] karabin szturmowy.,Você pegou o fuzil de assalto.,Apanhaste a arma de assalto.,Ai ridicat pușca de asalt.,Получена штурмовая винтовка.,Покупио си аутоматску пушку.,Du plockade upp pistolen.,Saldırı silahını aldın.,Взято штурмову гвинтівку. +You picked up the mini missile launcher.,TXT_MMLAUNCHER,,,,Sebral@[ao_cs] jsi miniraketomet.,Du samlede mini-missilkasteren op.,Du hast den Miniraketenwerfer genommen.,Πήρες το μίνι πυραυλοβόλο.,Vi trovis misilet-pafilon.,Encuentras un minilanzamisiles.,,Poimit miniohjuslaukaisimen.,Vous avez pris le lance mini-missile.,Felvetted a minirakétavetőt.,Hai raccolto il Mini-Lanciamissili.,ミニミサイル ランチャー入手。,미니 미사일 런쳐를 획득했다.,Je hebt de mini-raketwerper opgepakt.,Du plukket opp mini-missilkasteren.,Podniosł@[irreg_3_pl] wyrzutnię minipocisków.,Você pegou o mini lança-mísseis.,Apanhaste o mini lança-mísseis,Ai ridicat mini lansatorul de rachete.,Получена мини-ракетница.,Покупио си мини ручни бацач.,Du plockade upp mini-missilkastaren.,Mini füze fırlatıcısını aldın.,Взято міні-ракетомет. +You picked up the flame thrower.,TXT_FLAMER,,,,Sebral@[ao_cs] jsi plamenomet.,Du samlede flammekasteren op.,Du hast den Flammenwerfer genommen.,Πήρες το φλογοβόλο.,Vi trovis flamĵetilon.,Encuentras un lanzallamas.,,Poimit liekinheittimen.,Vous avez pris le lance-flames.,Felvetted a lángszórót.,Hai raccolto il Lanciafiamme.,火炎放射器 入手。,완성된 화염방사기를 얻었다.,Je hebt de vlammenwerper opgepakt.,Du plukket opp flammekasteren.,Podniosł@[irreg_3_pl] miotacz ognia.,Você pegou o lança-chamas.,Apanhaste o lança-chamas.,Ai ridicat aruncătorul de flăcări.,Получен огнемёт.,Покупио си бацач пламена.,Du plockade upp flamkastaren.,Alev silahını aldın.,Взято вогнемет. +You picked up the mauler.,TXT_MAULER,,,,Sebral@[ao_cs] jsi trhač.,Du tog mauleren op.,Du hast den Vernichter genommen.,,Vi trovis polvigilon.,Encuentras un triturador.,,Poimit moukarin.,Vous avez pris le Broyeur.,Felvetted a marcangolót.,Hai raccolto il Pestatore.,マウラー 入手。,마울러를 획득했다.,Je hebt de toetakelaar opgepakt.,Du plukket opp mauleren.,Podniosł@[irreg_3_pl] miażdżyciel.,Você pegou o desintegrador.,Apanhaste o desintegrador.,Ai ridicat sfâșietorul.,Получен истязатель.,Покупио си маулер.,Du plockade upp mauler.,Parçalayıcıyı aldın.,Взято розсіювач. +You picked up the Grenade launcher.,TXT_GLAUNCHER,,,,Sebral@[ao_cs] jsi granátomet.,Du samlede granatkasteren op.,Du hast den Granatwerfer genommen.,Πήρες το εκτοξευτη χειροβομβίδων.,Vi trovis grenadĵetilon.,Encuentras un lanzagranadas.,,Poimit kranaatinheittimen.,Vous avez pris le lance-grenades,Felvetted a gránátvetőt.,Hai raccolto il Lanciagranate.,グレネードランチャー 入手。,유탄발사기를 획득했다.,Je hebt de granaatwerper opgepakt.,Du plukket opp granatkasteren.,Podniosł@[irreg_3_pl] wyrzutnię granatów.,Você pegou o lança-granadas.,Apanhaste o lança-granadas.,Ai ridicat Lansatorul de rachete.,Получен гранатомёт.,Покупио си бацач граната.,Du plockade upp granatkastaren.,El bombası fırlatıcısını aldın.,Взято гранатомет. +You picked up the SIGIL.,TXT_SIGIL,,,,Sebral@[ao_cs] jsi Pečeť.,Du samlede SIGIL op.,Du hast das SIGIL genommen.,,Vi trovis la SIGELON.,Encuentras el EMBLEMA.,,Poimit SINETIN.,Vous avez pris le SIGIL.,Felvetted a Pecsétet.,Hai raccolto il SIGILLO.,シジル 取得。,시질은 이제 당신의 것이다.,Je hebt de SIGIL opgepakt.,Du plukket opp SIGIL.,Podniosł@[irreg_3_pl] PIECZĘĆ.,Você pegou o SIGILO.,Apanhaste o SIGILO,Ai ridicat SIGILIUL.,Получена ПЕЧАТЬ.,Покупио си СИГИЛ.,Du plockade upp Sigillet.,SİGİL'i aldın.,Отримано СІГІЛ. +You picked up the Base Key.,TXT_BASEKEY,,,,Sebral@[ao_cs] jsi klíč od základny.,Du samlede Base nøglen op.,Du hast den Basisschlüssel genommen.,,Vi havas la ŝlosilon de la bazo.,Tienes la llave de la base.,,Poimit tukikohdan avaimen.,Vous avez pris la clé de la Base.,Felvetted a Bázis kulcsát.,Hai raccolto la chiave della Base.,基地のキー 取得。,기지 키를 획득했다.,Je hebt de basissleutel opgepakt.,Du plukket opp basenøkkelen.,Podniosł@[irreg_3_pl] Klucz do Bazy.,Você pegou a Chave da Base.,Apanhaste a Chave da Base.,Ai ridicat Cheia Bazei.,Получен ключ от базы.,Покупио си кључ базе.,Du plockade upp basnyckeln.,Üs Anahtarını aldın.,Взято ключ від бази. +You picked up the Govs Key.,TXT_GOVSKEY,,,,Sebral@[ao_cs] jsi klíč ke guvernérovi.,Du samlede guvernørens nøglen op.,Du hast den Gouverneursschlüssel genommen.,,Vi havas la ŝlosilon de la registo.,Tienes la llave del Gobernador.,,Poimit kuvernöörin avaimen.,Vous avez pris la clé du Gouverneur.,Felvetted a Kormányzó parcellájának kulcsát.,Hai raccolto la chiave del Governatore.,政府のキー 取得。,총독의 키를 획득했다.,Je hebt de gouverneursleutel opgepakt.,Du plukket opp regjeringsnøkkelen.,Podniosł@[irreg_3_pl] Klucz Gubernatora.,Você pegou a Chave do Governador.,Apanhaste a Chave do Governador.,Ai ridicat Cheia Guvernatorului.,Получен ключ губернатора.,Покупио си клуч гувернанте.,Du plockade upp Govs nyckeln.,Hükümet Anahtarını aldın.,Взято ключ губернатора. +You picked up the Passcard.,TXT_PASSCARD,,,,Sebral@[ao_cs] jsi průkazku.,Du samlede Adgangskort op.,Du hast die Zugangskarte genommen.,,Vi havas la ŝlosilon de la elektra centralo.,Tienes la llave de la central eléctrica.,,Poimit avainkortin.,Vous avez pris le passe.,Felvetted a Belépőkártyát.,Hai raccolto la Tessera Lasciapassare.,パスカード 取得。,통행 카드를 획득했다.,Je hebt de doorgangskaart opgepakt.,Du plukket opp adgangskortet.,Podniosł@[irreg_3_pl] Kartę Dostępu.,Você pegou o Cartão de Acesso.,Apanhaste o Cartão de Acesso.,Ai ridicat Legitimația.,Получен пропуск.,Покупио си пасош.,Du plockade upp passerkortet.,Erişim kartıni aldın.,Взято карту доступу. +You picked up the ID Badge.,TXT_IDBADGE,,,,Sebral@[ao_cs] jsi identifikační odznak.,Du samlede ID Badge op.,Du hast die Identitätskarte genommen.,,Vi havas la insignon de la malliberejo.,Tienes la insignia de la prisión.,,Poimit henkilötunnisteen.,Vous avez pris le Badge d'identification.,Felvetted az Azonosítójelvényt.,Hai raccolto il Distintivo.,IDバッジ 取得。,신분 휘장을 획득했다.,Je hebt de ID-badge opgepakt.,Du plukket opp ID-skiltet.,Podniosł@[irreg_3_pl] Odznakę Identyfikacyjną.,Você pegou o Crachá de Identificação.,Apanhaste o Crachá de Identificação,Ai ridicat Ecusonul de Identificare.,Получена личная карта.,Покупио си личну карту.,Du plockade upp ID-brickan.,Kimlik Rozetini aldın.,Взято бейджик. +You picked up the Prison Key.,TXT_PRISONKEY,,,,Sebral@[ao_cs] jsi klič k vězení.,Du samlede nøglen til fængslet op.,Du hast den Gefängnisschlüssel genommen.,,Vi havas la ŝlosilon de la malliberejo.,Tienes la llave de la prisión.,,Poimit vankilan avaimen.,Vous avez pris la clé de la Prison.,Felvetted a Börtönkulcsot.,Hai raccolto la chiave della Prigione.,刑務所のキー 取得。,감옥 키를 획득했다.,Je hebt de gevangenissleutel opgepakt.,Du plukket opp Fengselsnøkkelen.,Podniosł@[irreg_3_pl] Klucz do Więzienia.,Você pegou a Chave da Prisão.,Apanhaste a Chave da Prisão.,Ai ridicat Cheia Închisorii.,Получен ключ от тюрьмы.,Покупио си затворски кључ,Du tog upp fängelsenyckeln.,Hapishane Anahtarını aldın.,Взято ключ від тюрми. +You picked up the Severed Hand.,TXT_SEVEREDHAND,,,,Sebral@[ao_cs] jsi useknutou ruku.,Du samlede den afhuggede hånd op.,Du hast die abgetrennte Hand genommen.,,Vi havas amputitan manon.,Tienes una mano amputada.,,Poimit katkenneen käden.,Vous avez pris la main coupée.,Felvetted a Levágott kezet.,Hai raccolto la Mano Mozzata.,切り取った手 取得。,잘린 손목을 주웠다.,Je hebt de Gescheurde Hand opgepakt.,Du plukket opp den avkuttede hånden.,Podniosł@[irreg_3_pl] Odciętą Rękę.,Você pegou a Mão Decepada.,Apanhaste a Mão Desmenbrada.,Ai ridicat Mâna Retezată.,Получена отрезанная рука.,Покупио си шаку,Du plockade upp den avhuggna handen.,Kesik El'i aldın.,Взято відрізану руку. +You picked up the Power1 Key.,TXT_POWER1KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 1.,Du samlede Power1-nøglen op.,Du hast den Kraftwerksschlüssel 1 genommen,,Vi havas la unuan centralan identigilon.,Tienes una identificación nivel uno de la central.,,Poimit voimalan 1-avaimen.,Vous avez pris la clé Power1.,Felvetted az 1-es Áram kulcsot.,Hai raccolto la chiave della Centrale n.1,パワー1キー 取得。,발전소 1호 키를 획득했다.,Je hebt de 1e Machtsleutel opgepakt.,Du plukket opp Power1-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Elektrowni 1.,Você pegou a Chave da Usina 1.,Apanhaste a Chave Energética 1,Ai ridicat Cheia Putere1.,Получен ключ электростанции №1.,Покупио си први кључ од електране.,Du plockade upp kraftnyckeln 1.,Güç1 Anahtarını aldın.,Взято ключ від електростанції 1. +You picked up the Power2 Key.,TXT_POWER2KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 2.,Du samlede Power2-nøglen op.,Du hast den Kraftwerksschlüssel 2 genommen,,Vi havas la duan centralan identigilon.,Tienes una identificación nivel dos de la central.,,Poimit voimalan 2-avaimen.,Vous avez pris la clé Power2.,Felvetted az 2-es Áram kulcsot.,Hai raccolto la chiave della Centrale n.2,パワー2キー 取得。,발전소 2호 키를 획득했다.,Je hebt de 2e Machtsleutel opgepakt.,Du plukket opp Power2-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Elektrowni 2.,Você pegou a Chave da Usina 2.,Apanhaste a Chave Energética 2,Ai ridicat Cheia Putere2.,Получен ключ электростанции №2.,Покупио си други кључ од електране.,Du plockade upp kraftnyckeln 2.,Güç2 Anahtarını aldın.,Взято ключ від електростанції 2. +You picked up the Power3 Key.,TXT_POWER3KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 3.,Du samlede Power3-nøglen op.,Du hast den Kraftwerksschlüssel 3 genommen,,Vi havas la trian centralan identigilon.,Tienes una identificación nivel tres de la central.,,Poimit voimalan 3-avaimen.,Vous avez pris la clé Power3.,Felvetted az 3-as Áram kulcsot.,Hai raccolto la chiave della Centrale n.3,パワー3キー 取得。,발전소 3호 키를 획득했다.,Je hebt de 3e Machtsleutel opgepakt.,Du plukket opp Power3-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Elektrowni 3.,Você pegou a Chave da Usina 3.,Apanhaste a Chave Energética 3,Ai ridicat Cheia Putere3.,Получен ключ электростанции №3.,Покупио си трећи кључ од електране.,Du plockade upp kraftnyckeln 3.,Güç3 Anahtarını aldın.,Взято ключ від електростанції 3. +You picked up the Gold Key.,TXT_GOLDKEY,,,,Sebral@[ao_cs] jsi zlatý klíč.,Du samlede den guldnøglen op.,Du hast den Goldschlüssel genommen.,,Vi havas oran ŝlosilon.,Tienes una llave dorada.,,Poimit kulta-avaimen.,Vous avez pris la clé d'or.,Felvetted az Aranykulcsot.,Hai raccolto la chiave dorata,ゴールドキー 取得。,황금 키를 획득했다.,Je hebt de gouden sleutel opgepakt.,Du plukket opp Gullnøkkelen.,Podniosł@[irreg_3_pl] Złoty Klucz.,Você pegou a Chave de Ouro.,Apanhaste a Chave de Ouro,Ai ridicat Cheia de Aur.,Получен золотой ключ.,Покупио си златни кључ.,Du plockade upp guldnyckeln.,Altın Anahtarı aldın.,Взято золотий ключ. +You picked up the ID Card.,TXT_IDCARD,,,,Sebral@[ao_cs] jsi ID kartu.,Du samlede ID-kortet op.,Du hast den Ausweis genommen.,,Vi havas identigilon de la kloakoj.,Tienes una identificación de las clocacas.,,Poimit henkilökortin.,Vous avez pris la Carte d'identité.,Felvetted az Igazolványt.,Hai raccolto la Tessera di Identificazione.,IDカード 取得。,신분증을 획득했다.,Je hebt de ID-kaart opgepakt.,Du plukket opp ID-kortet.,Podniosł@[irreg_3_pl] Kartę Identyfikacyjną.,Você pegou o Cartão de Identifiçacão.,Apanhaste o Cartão de Identificação,Ai ridicat Cardul de Identitate.,Получено удостоверение.,Покупио си идентификациону картицу.,Du plockade upp ID-kortet.,Kimlik Kartını aldın.,Взято ідентифікаційну карту. +You picked up the Silver Key.,TXT_SILVERKEY,,,,Sebral@[ao_cs] jsi stříbrný klíč.,Du tog sølvnøglen op.,Du hast den Silberschlüssel genommen.,,Vi havas arĝentan ŝlosilon.,Tienes una llave plateada.,,Poimit hopea-avaimen.,Vous avez pris la clé d'argent.,Felvetted az Ezüstkulcsot.,Hai raccolto la chiave argentata,シルバーキー 取得。,은 키를 획득했다.,Je hebt de zilveren sleutel opgepakt.,Du plukket opp sølvnøkkelen.,Podniosł@[irreg_3_pl] Srebrny Klucz.,Você pegou a Chave de Prata.,Apanhaste a Chave de Prata,Ai ridicat Cheia de Argint.,Получен серебряный ключ.,Покупио си сребрни кључ.,Du plockade upp silvernyckeln.,Gümüş Anahtarı aldınız.,Взято срібний ключ +You picked up the Oracle Key.,TXT_ORACLEKEY,,,,Sebral@[ao_cs] jsi věštcův klíč.,Du tog Oracle-nøglen op.,Du hast den Orakelschlüssel genommen.,,Vi havas ŝlosilon de la Orakolo,Tienes una llave del Oráculo.,,Poimit Oraakkelin avaimen.,Vous avez pris la clé Oraclé.,Felvetted az Orákulum kulcsát.,Hai raccolto la chiave dell'Oracolo.,オラクルキー 取得。,오라클 키를 획득했다.,Je hebt de Orakelsleutel opgepakt.,Du plukket opp Oracle-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Wyroczni.,Você pegou a Chave do Oráculo.,Apanhaste a Chave do Oráculo.,Ai ridicat Cheia Oracol.,Получен ключ Оракула.,Покупио си кључ пророка,Du plockade upp Orakel-nyckeln.,Kahin Anahtarını aldın.,Взято ключ Оракула. +You picked up the Military ID.,TXT_MILITARYID,,,,Sebral@[ao_cs] jsi vojenské ID.,Du samlede militær-ID op.,Du hast den Militärausweis genommen.,,Vi havas militan identigilon.,Tienes una identificación militar.,,Poimit sotilastunnuksen.,Vous avez pris l'ID Militaire.,Felvetted a Katonai igazolványt.,Hai raccolto l'Identificativo Militare.,ミリタリーID 取得。,군용 아이디를 획득했다.,Je hebt de militaire ID opgepakt.,Du plukket opp den militære ID-en.,Podniosł@[irreg_3_pl] Wojskowy Identyfikator.,Você pegou a Identificação Militar.,Apanhaste a Identificação Militar.,Ai ridicat Legitimația Militară.,Получено военное удостоверение.,Покупио си војну идентификацију,Du plockade upp det militära ID-kortet.,Askeri Kimliği aldın.,Взято військову ID карту. +You picked up the Order Key.,TXT_ORDERKEY,,,,Sebral@[ao_cs] jsi klíč Řádu.,Du samlede Ordensnøglen op.,Du hast den Ordensschlüssel genommen.,,Vi havas la ŝlosilon de La Ordeno.,Tienes la llave de La Orden.,,Poimit Veljeskunnan avaimen.,Vous avez pris la clé de l'Ordre.,Felvetted a Rend kulcsát.,Hai raccolto la chiave dell'Ordine.,オーダーキー 取得。,오더의 키를 획득했다.,Je hebt de Ordesleutel opgepakt.,Du plukket opp Bestillingsnøkkelen.,Podniosł@[irreg_3_pl] Klucz Zakonu.,Você pegou a Chave da Ordem.,Apanhaste a Chave da Ordem.,Ai ridicat Cheia Ordinului.,Получен ключ Ордена.,Покупио си кључ одреда,Du plockade ordernyckeln.,Emir Anahtarını aldın.,Взято ключ Ордену. +You picked up the Warehouse Key.,TXT_WAREHOUSEKEY,,,,Sebral@[ao_cs] jsi klíč ke skladu.,Du samlede lagernøglen op.,Du hast den Lagerhausschlüssel genommen,,Vi havas la ŝlosilon de la magazeno.,Tienes la llave del almacén.,,Poimit varaston avaimen.,Vous avez pris la clé de l'entrepôt.,Felvetted a Raktár kulcsát.,Hai raccolto la chiave del Magazzino.,倉庫のキー 取得。,창고 키를 획득했다.,Je hebt de pakhuissleutel opgepakt.,Du plukket opp Lagernøkkelen.,Podniosł@[irreg_3_pl] Klucz do Magazynu.,Você pegou a Chave do Armazém.,Apanhaste a Chave do Armazém,Ai ridicat Cheia Depozitului.,Получен ключ от склада.,Покупио си кључ складишта,Du plockade lagernyckeln.,Depo Anahtarını aldın.,Взято ключ від складу. +You picked up the Brass Key.,TXT_BRASSKEY,,,,Sebral@[ao_cs] jsi mosazný klíč.,Du samlede messingnøglen op.,Du hast den Messingschlüssel genommen.,,Vi havas la latunan ŝlosilon.,Tienes la llave de latón.,,Poimit messinkiavaimen.,Vous avez pris la clé de bronze.,Felvetted a Rézkulcsot.,Hai raccolto la chiave d'Ottone.,ブラスキー 取得。,황동 키를 획득했다.,Je hebt de messing sleutel opgepakt.,Du plukket opp messingnøkkelen.,Podniosł@[irreg_3_pl] Mosiężny Klucz.,Você pegou a Chave de Latão.,Apanhaste a Chave de Latão,Ai ridicat Cheia din Alamă.,Получен латунный ключ.,Покупио си кључ месинга,Du plockade mässingsnyckeln.,Pirinç Anahtarı aldın.,Взято латунний ключ. +You picked up the Red Crystal Key.,TXT_REDCRYSTAL,,,,Sebral@[ao_cs] jsi červený krystalový klíč.,Du samlede den røde krystalnøgle op.,Du hast den roten Kristallschlüssel genommen.,,Vi trovis la ruĝkristalan ŝlosilon.,Encuentras la llave de cristal rojo.,,Poimit punaisen kristalliavaimen.,Vous avez pris la clé cristal rouge.,Felvetted a Vörös Kristály Kulcsot.,Hai raccolto la chiave del Cristallo Rosso.,赤水晶のキー 取得。,적색 크리스탈 키를 획득했다.,Je hebt de rode kristallen sleutel opgepakt.,Du plukket opp den røde krystallnøkkelen.,Podniosł@[irreg_3_pl] Czerwony Kryształowy Klucz.,Você pegou a Chave de Cristal Vermelho.,Apanhaste a Chave de Cristal Vermelho.,Ai ridicat Cheia din Cristal Roșu.,Получен красный ключ-кристалл.,Покупио си кључ од црвеног кристала,Du plockade upp den röda kristallnyckeln.,Kırmızı Kristal Anahtarı aldın.,Взято червоний кристальний ключ. +You picked up the Blue Crystal Key.,TXT_BLUECRYSTAL,,,,Sebral@[ao_cs] jsi modrý krystalový klíč.,Du samlede den blå krystalnøgle op.,Du hast den blauen Kristallschlüssel genommen.,,Vi trovis la blukristalan ŝlosilon,Encuentras la llave de cristal azul.,,Poimit sinisen kristalliavaimen.,Vous avez pris la clé cristal bleu.,Felvetted a Kék Kristály Kulcsot.,Hai raccolto la chiave del Cristallo Blu.,青水晶のキー 取得。,청색 크리스탈 키를 획득했다.,Je hebt de blauwe kristallen sleutel opgepakt.,Du plukket opp den blå krystallnøkkelen.,Podniosł@[irreg_3_pl] Niebieski Kryształowy Klucz.,Você pegou a Chave de Cristal Azul.,Apanhaste a Chave de Cristal Azul.,Ai ridicat Cheia din Cristal Albastru.,Получен синий ключ-кристалл.,Покупио си кључ од плавог кристала,Du plockade upp den blå kristallnyckeln.,Mavi Kristal Anahtarı aldın.,Взято синій кристальний ключ. +You picked up the Chapel Key.,TXT_CHAPELKEY,,,,Sebral@[ao_cs] jsi klíč ke kapli.,Du samlede Kapel-nøglen op.,Du hast den Kapellenschlüssel genommen.,,Vi trovis la ŝlosilon de la kapelo.,Encuentras la llave de la capilla.,,Poimit kappelin avaimen.,Vous avez pris la clé de la chapelle.,Felvetted a Kápolna Kulcsát.,Hai raccolto la chiave della Cappella,チャペルキー 取得。,예배당 키를 획득했다.,Je hebt de kapelsleutel opgepakt.,Du plukket opp kapellnøkkelen.,Podniosł@[irreg_3_pl] Klucz do Kaplicy.,Você pegou a Chave da Capela.,Apanhaste a Chave da Capela.,Ai ridicat Cheia Capelei.,Получен ключ от часовни.,Покупио си кључ капеле,Du plockade upp kapellnyckeln.,Şapel Anahtarını aldın.,Взято ключ від каплиці. +You picked up the Catacomb Key.,TXT_CATACOMBKEY,,,,Sebral@[ao_cs] jsi klíč do katakomb.,Du samlede Katakombe-nøglen op.,Du hast den Katakombenschlüssel genommen.,,Vi havas la ŝlosilon de la katakombo.,Tienes la llave de las catacumbas.,,Poimit katakombin avaimen.,Vous avez pris la clé des catacombes.,Felvetted a Katakombák kulcsát.,Hai raccolto la chiave delle Catacombe.,カタコンベキー 取得。,고대 묘지 키를 획득했다.,Je hebt de catacombesleutel opgepakt.,Du plukket opp Katakomb-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Katakumb.,Você pegou a Chave da Catacumba.,Apanhaste a Chave da Catacumba.,Ai ridicat Cheia Catacombei.,Получен ключ от катакомб.,Покупио си кључ катакомбе,Du plockade upp katakomberna nyckeln.,Yeraltı Mezarı Anahtarını aldın.,Взято ключ від катакомб. +You picked up the Security Key.,TXT_SECURITYKEY,,,,Sebral@[ao_cs] jsi klíč ochranky.,Du samlede sikkerhedsnøglen op.,Du hast den Sicherheitsschlüssel genommen.,,Vi havas la sekureco-ŝlosilon.,Tienes la llave de seguridad.,,Poimit turvamiesavaimen.,Vous avez pris la clé de la sécurité.,Felvetted a Biztonsági Kulcsot.,Hai raccolto la chiave della Sicurezza.,警備のキー 取得。,보안 키를 획득했다.,Je hebt de beveiligingssleutel opgepakt.,Du plukket opp Sikkerhetsnøkkelen.,Podniosł@[irreg_3_pl] Klucz Ochrony.,Você pegou a Chave de Seguranca.,Apanhaste a Chave de Segurança,Ai ridicat Cheia Securității.,Получен ключ охраны.,Покупио си кључ обезбеђења,Du plockade upp säkerhetsnyckeln.,Güvenlik Anahtarını aldın.,Взято ключ охорони. +You picked up the Core Key.,TXT_COREKEY,,,,Sebral@[ao_cs] jsi klíč k jádru.,Du samlede reaktornøglen op.,Du hast den Reaktorschlüssel genommen.,,Vi trovis la ŝlosilon de la kernejo.,Encuentras la llave del núcleo.,,Poimit ytimen avaimen.,Vous avez pris la clé du réacteur.,Felvetted a Mag kulcsát.,Hai raccolto la chiave del Nucleo.,コアキー 取得。,중심부 키를 획득했다.,Je hebt de kernsleutel opgepakt.,Du plukket opp Kjernenøkkelen.,Podniosł@[irreg_3_pl] Klucz do Rdzenia.,Você pegou a Chave do Núcleo.,Apanhaste a Chave do Núcleo.,Ai ridicat Cheia Nucleului.,Получен ключ от реактора.,Покупио си кључ језгра,Du plockade upp kärnnyckeln.,Çekirdek Anahtarını aldın.,Взято ключ від реактора. +You picked up the Mauler Key.,TXT_MAULERKEY,,,,Sebral@[ao_cs] jsi klíč k trhačům.,Du samlede Mauler-nøglen op.,Du hast den Vernichterschlüssel genommen.,,Vi havas la ŝlosilon de la polvigiloj.,Tienes la llave de los trituradores.,,Poimit moukarin avaimen.,Vous avez pris la clé du Broyeur.,Felvetted a Marcangoló kulcsot.,Hai raccolto la chiave del Pestatore.,マウラーキー 取得。,마울러 키를 획득했다.,Je hebt de toetakelaarssleutel opgepakt.,Du plukket opp Mauler-nøkkelen.,Podniosł@[irreg_3_pl] Klucz do Magazynu Miażdżycieli.,Você pegou a Chave do Mauler.,Apanhaste a Chave do Mauler.,Ai ridicat Cheia Sfâșietorului.,Получен ключ истязателя.,Покупио си кључ Маулера.,Du plockade upp Mauler-nyckeln.,Mauler Anahtarını aldın.,Взято ключ розсіювача. +You picked up the Factory Key.,TXT_FACTORYKEY,,,,Sebral@[ao_cs] jsi klíč do továrny.,Du samlede fabriksnøglen op.,Du hast den Fabrikschlüssel genommen.,,Vi trovis la ŝlosilon de la fabriko.,Encuentras la llave de la fábrica.,,Poimit tehtaan avaimen.,Vous avez pris la clé de l'usine.,Felvetted a Gyár kulcsát.,Hai raccolto la chiave della Fabbrica.,工場のキー 取得。,공장 키를 획득했다.,Je hebt de fabriekssleutel opgepakt.,Du plukket opp fabrikknøkkelen.,Podniosł@[irreg_3_pl] Klucz do Fabryki.,Você pegou a Chave da Fábrica.,Apanhaste a Chave da Fábrica.,Ai ridicat Cheia Fabricii.,Получен ключ от фабрики.,Покупио си кључ фабрике,Du plockade upp fabriksnyckeln.,Fabrika Anahtarını aldın.,Взято ключ від фабрики. +You picked up the Mine Key.,TXT_MINEKEY,,,,Sebral@[ao_cs] jsi klíč do dolů.,Du samlede minenøglen op.,Du hast den Minenschlüssel genommen.,,Vi trovis la ŝlosilon de la minejo.,Encuentras la llave de la mina.,,Poimit kaivoksen avaimen.,Vous avez pris la clé de la mine.,Felvetted a Bánya kulcsát.,Hai raccolto la chiave della Miniera.,鉱山のキー 取得。,탄광 키를 획득했다.,Je hebt de mijnsleutel opgepakt.,Du plukket opp Gruvenøkkelen.,Podniosł@[irreg_3_pl] Klucz do Kopalni.,Você pegou a Chave da Mina.,Apanhaste a Chave da Mina.,Ai ridicat Cheia Minei.,Получен ключ от шахт.,Покупио си кључ рудника,Du plockade upp gruvnyckeln.,Maden Anahtarını aldın.,Взято ключ від шахт. +You picked up the New Key5.,TXT_NEWKEY5,,,,Sebral@[ao_cs] jsi nový klíč 5.,Du samlede den nye nøgle5 op.,Du hast den neuen Schlüssel 5 genommen.,,Vi havas la novan ŝlosilon kvin.,Tienes la llave nueva cinco.,,Poimit uuden 5-avaimen.,Vous avez pris la nouvelle clé 5.,Felvetted az 5. kulcsot.,Hai raccolto la Nuova Chiave n.5,ニューキー5 取得。,새로운 키5를 획득했다.,Je hebt de nieuwe sleutel 5 opgepakt.,Du plukket opp den nye nøkkelen5.,Podniosł@[irreg_3_pl] Nowy Klucz5,Você pegou a Chave Nova 5.,Apanhaste a Chave Nova 5.,Ai ridicat Cheia Nouă5.,Получен новый ключ №5.,Покупио си нови кључ5,Du hämtade den nya nyckeln5.,Yeni Anahtar5'i aldın.,Взято новий ключ 5. +You picked up the Oracle Pass.,TXT_ORACLEPASS,,,,Sebral@[ao_cs] jsi věštcovu propustku.,Du samlede orakelpas op.,Du hast den Orakelpass genommen.,,Vi havas la paspermeson de la Orakolo.,Tienes el pase del Oráculo.,,Poimit Oraakkelin passin.,Vous avez pris le passe de l'Oracle.,Felvetted az Orákulum Belépőkártyáját.,Hai raccolto il Lasciapassare dell'Oracolo.,オラクルパス 取得。,오라클의 통행증을 획득했다.,Je hebt de Orakelkaart opgepakt.,Du plukket opp Orakelpasset.,Podniosł@[irreg_3_pl] Przepustkę Wyroczni.,Você pegou o Passe do Oráculo.,Apanhaste o Passe do Oráculo.,Ai ridicat Legitimația Oracol.,Получен пропуск Оракула.,Покупио си пророкову пропусницу,Du plockade upp orakelpasset.,Kahin Geçiş Kartını aldın.,Взято пропуск Оракула. +You picked up the HE-Grenade Rounds.,TXT_HEGRENADES,,,,Sebral@[ao_cs] jsi výbušné granáty.,Du samlede HE-granaterne op.,Du hast die HE-Granaten genommen.,,Vi trovis eksplodeg-povajn grenadojn.,Encuentras granadas de conmoción.,,Poimit räjähdekranaattiammuksia.,Vous avez pris les Grenades Explosives.,Felvetted a robbanó gránátot.,Hai raccolto delle granate ad Alto Potenziale,HEグレネード弾 入手。,고폭 유탄을 획득했다.,Je hebt de HE-granaten opgepakt.,Du plukket opp HE-granaten.,Podniosł@[irreg_3_pl] Wiązkę Granatów.,Você pegou as Granadas Explosivas.,Apanhaste as Granadas Explosivas.,Ai ridicat Grenadele Explozive.,Получена связка гранат.,Покупио си ХЕ-Граната чауре,Du plockade upp HE-granaterna.,HE-Bombası Mermilerini aldın.,Взято в'язку гранат. +You picked up the Phosphorus-Grenade Rounds.,TXT_PHGRENADES,,,,Sebral@[ao_cs] jsi fosforové granáty.,Du samlede fosforgranaterne op.,Du hasr die Phosphorgranaten genommen.,,Vi trovis fosforajn grenadojn.,Encuentras granadas de fósforo.,,Poimit fosforikranaattiammuksia.,Vous avez pris les Grenades Phosphoriques.,Felvetted a foszfor-gránátokat.,Hai raccolto delle Granate al Fosforo.,白リングレネード弾 入手。,소이 유탄을 획득했다.,Je hebt de fosforgranaten opgepakt.,Du plukket opp fosforgranaten.,Podniosł@[irreg_3_pl] Wiązkę Fosforowych Granatów.,Você pegou as Granadas de Fósforo.,Apanhaste as Granadas de Fósforo.,Ai ridicat Grenadele cu Fosfor.,Получена связка фосфорных гранат.,Покупио си шаржер фосфорних граната.,Du plockade upp fosforgranater.,Fosforlu El Bombası Mermilerini aldın.,Взято в'язку фосфорних гранат. +You picked up the clip of bullets.,TXT_CLIPOFBULLETS,,,,Sebral@[ao_cs] jsi zásobník s náboji.,Du samlede patroner op.,Du hast die Gewehrmunition genommen.,Πήρες το κουτάκι με σφαίρες.,Vi trovis magazenon.,Encuentras un cargador.,,Poimit luotilippaan.,Vous avez pris le Chargeur.,Felvettél egy tár lőszert.,Hai raccolto un caricatore di proiettili.,銃弾倉 入手。,돌격소총 탄창을 획득했다.,Je hebt de patroon met kogels opgepakt.,Du plukket opp magasinet med kuler.,Podniosł@[irreg_3_pl] magazynek.,Você pegou o carregador.,Apanhaste o carregador.,Ai ridicat cartușul cu gloanțe.,Получена обойма.,,Du plockade upp ett magasin med kulor.,Mermi şarjörünü aldın.,Взято набійницю. +You picked up the box of bullets.,TXT_BOXOFBULLETS,,,,Sebral@[ao_cs] jsi krabici nábojů.,Du samlede kassen med kugler op.,Du hast die Munitionskiste genommen.,Πήρες το κουτί με σφαίρες.,Vi trovis munici-keston.,Encuentras una caja de municiones.,,Poimit luotilaatikon.,Vous avez pris la boîte de balles.,Felvettél egy doboz lőszert.,Hai raccolto una scatola di proiettili.,弾薬箱 入手。,돌격소총 탄약 박스를 획득했다.,Je hebt de doos met kogels opgepakt.,Du plukket opp esken med kuler.,Podniosł@[irreg_3_pl] pudło z amunicją.,Você pegou a caixa de balas.,Apanhaste a caixa de balas.,Ai ridicat cutia cu gloanțe.,Получена коробка пуль.,Покупио си кутију меткова,Du plockade upp lådan med kulor.,Mermi kutusunu aldın.,Взято коробку куль. +You picked up the mini missiles.,TXT_MINIMISSILES,,,,Sebral@[ao_cs] jsi minirakety.,Du samlede mini-missiler op.,Du hast die Miniraketen genommen.,Πήρες τους μινι-πυράυλους.,Vi trovis misiletojn.,Encuentras minimisiles.,,Poimit miniohjuksia.,Vous avez pris les mini-missiles.,Felvetted a minirakétákat.,Hai raccolto dei mini-missili.,ミニミサイル 入手。,미니 미사일 꾸러미를 획득했다.,Je hebt de mini-raketten opgepakt.,Du plukket opp minirakettene.,Podniosł@[irreg_3_pl] mini pociski.,Você pegou os mini-mísseis.,Apanhaste os mini-mísseis.,Ai ridicat mini proiectilele.,Получены мини-ракеты.,Покупио си мини ракете,Du plockade upp miniraketerna.,Mini füzeleri aldın.,Взято міні-ракети. +You picked up the crate of missiles.,TXT_CRATEOFMISSILES,,,,Sebral@[ao_cs] jsi bednu miniraket.,Du samlede kassen med missiler op.,Du hast die Miniraketenkiste genommen.,Πήρες το κιβώτιο με πυράυλους.,Vi trovis misilet-keston.,Encuentras una caja de minimisiles.,,Poimit ohjuslaatikon.,Vous avez pris la caisse de missiles.,Felvettél egy ládányi minirakétát.,Hai raccolto una cassa di missili.,ミサイルの箱 入手。,미니 미사일 박스를 획득했다.,Je hebt de kist met raketten opgepakt.,Du plukket opp kassen med missiler.,Podniosł@[irreg_3_pl] skrzynię z pociskami.,Você pegou a caixa de mísseis.,Apanhaste a caixa de mísseis.,Ai ridicat lada cu proiectile.,Получен ящик мини-ракет.,Покупио си кутију ракета,Du plockade upp lådan med missiler.,Füze sandığını aldın.,Взято ящик міні-ракети. +You picked up the energy pod.,TXT_ENERGYPOD,,,,Sebral@[ao_cs] jsi energetický kokón.,Du samlede energipoden op.,Du hast die Energiezelle genommen.,,Vi trovis energi-kapsulon.,Encuentras una cápsula de energía.,,Poimit energia-akun.,Vous avez pris la cellule d'énergie.,Felvettél egy energiahüvelyt.,Hai raccolto un nucleo energetico.,エネルギーポット 入手。,에너지 포드를 획득했다.,Je hebt de energiecel opgepakt.,Du plukket opp energikapselen.,Podniosł@[irreg_3_pl] kapsułę energii.,Você pegou a célula de energia (pequeno).,Apanhaste a célula de energia (pequeno).,Ai ridicat capsula cu energie.,Получена энергокапсула.,Покупио си енергетско постоље.,Du plockade upp energipodden.,Enerji kapsülünü aldın.,Взято енерго-капсулу. +You picked up the energy pack.,TXT_ENERGYPACK,,,,Sebral@[ao_cs] jsi energetický svazek.,Du samlede energipakken op.,Du hast das Energiepack genommen.,,Vi trovis pakon de energio.,Encuentras un paquete de energía.,,Poimit energiapaketin.,Vous avez pris le pack énergétique.,Felvetted az energiacsomagot.,Hai raccolto una carica energetica grande.,エネルギーパック 入手。,에너지 팩을 획득했다.,Je hebt het energiepak opgepakt.,Du plukket opp energipakken.,Podniosł@[irreg_3_pl] zasobnik energii.,Você pegou a célula de energia (grande).,Apanhaste a célula de energia (grande).,Ai ridicat pachetul cu energie.,Получен энергокомплект.,Покупио си пакет енергије,Du plockade upp energipaketet.,Enerji paketini aldın.,Взято енерго-батарею. +You picked up the poison bolts.,TXT_POISONBOLTS,,,,Sebral@[ao_cs] jsi otrávené šípy.,Du samlede giftboltene op.,Du hase die Giftbolzen genommen.,,Vi trovis venenajn sagojn.,Encuentras flechas envenenadas.,,Poimit myrkkynuolia.,Vous avez pris les carreaux empoisonnés.,Felvetted a mérgezett nyilakat.,Hai raccolto dei dardi velenosi.,ポイズンボルト 入手。,맹독 볼트를 획득했다.,Je hebt de gifbouten opgepakt.,Du plukket opp giftboltene.,Podniosł@[irreg_3_pl] zatrute bełty.,Você pegou as setas envenenadas.,Apanhaste as setas envenedadas.,Ai ridicat bolțurile cu otravă.,Получены отравленные болты.,Покупио си отровне стреле,Du plockade upp giftbultarna.,Zehirli cıvataları aldın.,Взято отруйні болти. +You picked up the electric bolts.,TXT_ELECTRICBOLTS,,,,Sebral@[ao_cs] jsi elektrické šípy.,Du samlede de elektriske bolte op.,Du hast die elektrischen Bolzen genommen.,,Vi trovis elektrajn sagojn.,Encuentras flechas eléctricas.,,Poimit sähkönuolia.,Vous avez pris les carreaux électriques.,Felvetted az elektromos nyilakat.,Hai raccolto dei dardi elettrici.,エレクトリックボルト 入手。,전격 볼트를 획득했다.,Je hebt de elektrische bouten opgepakt.,Du plukket opp de elektriske boltene.,Podniosł@[irreg_3_pl] elektryczne bełty.,Você pegou as setas eletricas.,Apanhaste as setas electricas.,Ai ridicat bolțurile cu electricitate.,Получены электрические болты.,Покупио си електричне стреле,Du plockade upp de elektriska bultarna.,Elektrikli cıvataları aldın.,Взято електричні болти. +You picked up the ammo satchel.,TXT_AMMOSATCHEL,,,,Sebral@[ao_cs] jsi brašnu na munici.,Du samlede ammunitionstasken op.,Du hast die Munitionstasche genommen.,,Vi trovis munici-sakon.,Encuentras un bolso de munición.,,Poimit ammuslaukun.,Vous avez pris la sacoche de munitions,Felvetted a lőszeres táskát.,Hai raccolto una Borsa delle Munizioni.,弾薬鞄 入手。,탄약 배낭을 획득했다.,Je hebt de munitietas opgepakt.,Du plukket opp ammunisjonsvesken.,Podniosł@[irreg_3_pl] torbę z amunicją.,Você pegou a mochila de munição.,Apanhaste a mochila de munição.,Ai ridicat sacoșa cu muniție.,Получен ранец боеприпасов.,Покупио си торбицу муниције,Du plockade upp ammunitionsväskan.,Cephane çantasını aldın.,Взято сумку для набоїв. +You have a feeling that it wasn't to be touched...,MSG_TALISMANRED,,,,"Máš pocit, že jsi na to sahat neměl@[ao_cs]...","Du har en fornemmelse af, at den ikke måtte røres...","Du hast das Gefühl, dass man es nicht anfassen sollte...",,"Vi sentas, ke vi ne devis tuŝi ĝin...",Tienes la sensación de que no debía ser tocado...,,"Sinusta tuntuu, ettei siihen olisi pitänyt koskea.",Vous avez un pressentiment qu'il ne fallait pas y toucher.....,Úgy érzed azt nem kéne megérinteni...,Hai la sensazione che non doveva essere toccato...,己の勘が 触れてはならない物だと訴えている...,"결코, 만지면 안 된다는 생각이 든다...",Je hebt het gevoel dat het niet aangeraakt dient te worden...,Du har en følelse av at den ikke skulle røres...,"Czujesz, że trzeba było tego nie dotykać...",Você tem um pressentimento de que isso não devia ser tocado...,Tens um pressentimento que não devias ter mexido nisso.,Ai sentimentul că nu trebuia atinsă...,"Кажется, эту вещь лучше не трогать...",Имаш осећај да није требало бити дирано...,Du har en känsla av att den inte fick röras...,İçinizde dokunulmaması gerektiğine dair bir his var.,"Ви відчуваєте, що не слід це чіпати..." +"Whatever it is, it doesn't belong in this world...",MSG_TALISMANGREEN,,,,"Je jedno, co to je, do tohoto světa to nepatří...","Uanset hvad det er, hører det ikke hjemme i denne verden...","Was auch immer es ist, es gehört nicht in diese Welt...","Οτιδήποτε είναι, δέν είναι απο αυτό τον κόσμο...","Tio ajn, kio ĝi estas, ĝi ne apartenas al ĉi tiu mondo...","Sea lo que sea, no pertenece a este mundo...",,"Mikä ikinä se onkaan, se ei kuulu tähän maailmaan...","Quel que soit cette chose, elle ne devrait pas être ici...","Bármi legyen ez, nem ebben a világban van a helye...","Qualunque cosa sia, non appartiene a questo mondo...",何であろうと、この世には属さない物だ...,뭔지는 몰라도 이 세상에 속한 것이 아닌 것 같다...,"Wat het ook is, het hoort niet thuis in deze wereld...","Uansett hva det er, hører det ikke hjemme i denne verden...","Cokolwiek to jest, nie należy to do tego świata...","Seja o que for, isso não pertence a este mundo...","O que quer que isso seja, não pertence a este mundo...","Orice ar fi, nu are ce căuta în lumea asta...","Что бы это ни было, оно не из этого мира...","Шта год да је, не припада овом свету...",Vad det än är så hör det inte hemma i den här världen...,"O her neyse, bu dünyaya ait değil.","Що б це не було, воно не належить цьому світу..." +It must do something...,MSG_TALISMANBLUE,,,,Něco to dělat musí...,Det må gøre noget...,Es muss etwas tun...,Πρέπει να κάνι κάτι...,Ĝi devas fari ion...,Debe hacer algo...,,Sen on pakko tehdä jotakin...,Ca doit servir a quelque chose...,Valamit kell hogy csináljon...,Deve fare qualcosa...,何かを成し遂げなければならない...,분명히 뭔가를 할 것이다...,Het moet iets doen....,Det må gjøre noe...,To musi coś robić...,Deveria fazer alguma coisa...,Devia fazer alguma coisa.,Trebuie să facă ceva...,Оно ведь зачем-то нужно?..,Мора урадити нешто...,Det måste göra något...,Bir şey yapmalı.,Воно повинно мати якесь призначення... +You have super strength!,MSG_TALISMANPOWER,,,,Získal@[ao_cs] jsi super sílu!,Du har superstyrke!,Du hast Superkräfte,,Vi havas superan forton!,¡Tienes superfuerza!,,Sinulla on supervoimat!,Vous avez une puissance inégalée!,Tied a Szuper Erő!,Hai la super forza!,豪剛なる力を得た!,엄청난 힘이 솟는다!,Je hebt superkracht!,Du har superkrefter!,Masz super siłę!,Você tem a super força!,Tu tens super força!,Ai super forță!,Вы получили сверхсилу!,Имаш супер снагу!,Du har superstyrka!,Süper gücün var!,Ви отримали суперсилу! +,,Locks,,,,,,,,,,,,,,,,,,,,,,,,,, +You don't have the key,TXT_NEEDKEY,,,,Nemáš klíč.,Du har ikke nøglen,Du hast den Schlüssel nicht,Δέν έχεις το κλειδί,Vi ne havas la ŝlosilon,No tienes la llave,,Sinulla ei ole avainta,Vous n'avez pas la clé.,Ehhez nincs kulcsod.,Non hai la chiave necessaria,キーを持っていない,필요한 열쇠가 없다,Je hebt de sleutel niet.,Du har ikke nøkkelen,Nie masz klucza,Você não tem a chave,Tu não tens a chave,Nu ai cheia,Нужен ключ,Немаш кључ,Du har inte nyckeln.,Anahtar sende değil.,У вас немає ключа +You need a passcard,TXT_NEED_PASSCARD,,,,Potřebuješ průkaz.,Du har brug for et adgangskort,Du brauchst eine Zugangskarte.,,Vi bezonas central-ŝlosilon,Necesitas la llave de la central,,Tarvitset avainkortin,Vous avez besoin du passe.,Belépőkártyára lesz szükséged.,Ti serve un lasciapassare,パスカード が必要だ,통행 카드가 필요하다,Je hebt een doorgangskaart nodig.,Du trenger et passerkort,Potrzebujesz karty dostępu,Você precisa de um cartão de acesso,Precisas de um cartão de acesso,Ai nevoie de un card de acces,Нужен пропуск,Треба ти пропусница,Du behöver ett passerkort.,Bir erişim kartına ihtiyacınız var,Потрібна карта доступу You need a pass card key to open this door,TXT_NEED_PASSCARD_DOOR,,,,Pro otevření dveří potřebuješ průkaz.,Du skal bruge en adgangskort for at åbne denne dør,"Du brauchst eine Zugangskarte, um diese Tür zu öffnen.",,"Vi bezonas central-ŝlosilon -por malfermi tiun pordon.","Necesitas una llave de la +por malfermi tiun pordon","Necesitas una llave de la central para abrir esta puerta",,Tarvitset avainkortin tämän oven avaamiseksi,Vous avez besoin du passe ouvrir cette porte.,Belépőkártya nélkül nem nyílik ez az ajtó.,Ti serve una tessera lasciapassare per aprire questa porta.,このドアには パスカード が必要だ,이 문을 열기 위해서는 통행 카드가 필요하다,Je hebt een doorgangskaart nodig om deze deur te openen.,Du trenger en passerkortnøkkel for å åpne denne døren.,Potrzebujesz karty dostępu aby otworzyć te drzwi,Você precisa de um cartão de acesso para abrir esta porta,Precisas de um cartão de acesso para abrir esta porta,"Ai nevoie de un card de acces ca să deschizi ușa -asta",Для открытия нужен пропуск,Треба ти пасош да отвориш ова врата,Bu kapıyı açmak için bir erişim kartı anahtarına ihtiyacınız var -You need an ID card,TXT_NEED_IDCARD,,,,Potřebuješ identifikační kartu.,Du skal bruge et ID-kort,Du brauchst einen Ausweis.,,Vi bezonas identigil-karton.,Necesitas una tarjeta de Identificación,,Tarvitset henkilökortin,Vous avez besoin d'une carte d'identité.,Igazolvány szükséges,Ti serve una tessera identificativa.,IDカード が必要だ,신분증이 필요하다,Je hebt een ID-kaart nodig.,Du trenger et ID-kort,Potrzebujesz karty identyfikacyjną,Você precisa do cartão de identificação,Precisas do cartão de identificação,Ai nevoie de un card de identitate,Нужна личная карта,Треба ти идентификациона картица,Bir kimlik kartına ihtiyacınız var -You don't have the key to the prison,TXT_NEED_PRISONKEY,,,,Nemáš klíč do vězení.,Du har ikke nøglen til fængslet,Du brauchst den Schlüssel zum Gefängnis,,Vi ne havas la ŝlosilon de la malliberejo.,No tienes la llave a la prisión,,Sinulla ei ole vankilan avainta,Vous n'avez pas la clé de la prison.,Nincs kulcsod a börtönhöz.,Ti manca la chiave per la prigione,刑務所のキーを持っていない,감옥에 입장하기 위한 열쇠가 없다,Je hebt de sleutel van de gevangenis niet.,Du har ikke nøkkelen til fengselet.,Nie masz klucza do więzienia,Você não tem a chave da prisão,Não tens a chave da prisão,Nu ai cheia închisorii,Нужен ключ от тюрьмы,Треба ти кључ затвора,Hapishanenin anahtarı sende değil. -Hand print not on file,TXT_NEED_HANDPRINT,,,,Otisk ruky není v databázi.,Håndaftryk er ikke registreret,Handabdruck nicht gespeichert!,,Manspuro ne registrita,Huella de la mano no registrada,,Kädenjälki puuttuu tiedostosta,Votre main n'est pas reconnue par le scanner.,Azonosítatlan kézlenyomat.,Impronta digitale non in archivio,手形認証が一致しません,알 수 없는 지문입니다,Handafdruk niet in het bestand.,Håndavtrykk finnes ikke i filen,Brak odcisku dłoni w bazie danych,Biometria não autorizada,Impressão digital não autorizada,Amprenta mâinii nerecunoscută,Отпечаток руки не распознан,Отисак длана није у записнику,El izi dosyada yok -You need the Gold Key,TXT_NEED_GOLDKEY,,,,Potřebuješ zlatý klíč.,Du har brug for guldnøglen,Du brauchst den goldenen Schlüssel,,Vi bezonas la oran ŝlosilon.,Necesitas la llave dorada,,Tarvitset kulta-avaimen,Vous avez besoin d'une clé d'or.,Aranykulcs szükséges.,Ti serve la chiave dorata,ゴールドキーが必要だ,황금 키가 필요하다,Je hebt de gouden sleutel nodig.,Du trenger gullnøkkelen,Potrzebujesz Złotego Klucza,Você precisa da Chave de Ouro,Precisas da Chave de Ouro,Ai nevoie de cheia din Aur,Нужен золотой ключ,Треба ти златни кључ,Altın Anahtara ihtiyacınız var -You need an ID Badge,TXT_NEED_IDBADGE,,,,Potřebuješ identifikační odznak.,Du har brug for et ID-badge,Du brauchst eine Identitätskarte.,,Vi bezonas malliberejan insignon.,Necesitas una insignia de la prisión,,Tarvitset henkilötunnisteen,Vous avez besoin d'un badge d'identification.,Azonosító jelvény szükséges.,Ti serve un distintivo di identificazione,IDバッジが必要だ,신분 휘장이 필요하다,Je hebt een ID-badge nodig.,Du trenger en ID-badge,Potrzebujesz Odznaki Identyfikacyjnej,Você precisa do Crachá de Identificação,Precisas do Crachá de Identificação,Ai nevoie de un ecuson de identificare,Нужна личная карта,Треба ти лична карта,Bir Kimlik Rozetine ihtiyacınız var +asta",Для открытия нужен пропуск,Треба ти пасош да отвориш ова врата,Du behöver ett passerkort för att öppna den här dörren.,Bu kapıyı açmak için bir erişim kartı anahtarına ihtiyacınız var,"Вам потрібна карта доступу, щоб відкрити ці двері" +You need an ID card,TXT_NEED_IDCARD,,,,Potřebuješ identifikační kartu.,Du skal bruge et ID-kort,Du brauchst einen Ausweis.,,Vi bezonas identigil-karton,"Necesitas una tarjeta +de identificación",,Tarvitset henkilökortin,Vous avez besoin d'une carte d'identité.,Igazolvány szükséges,Ti serve una tessera identificativa.,IDカード が必要だ,신분증이 필요하다,Je hebt een ID-kaart nodig.,Du trenger et ID-kort,Potrzebujesz karty identyfikacyjną,Você precisa do cartão de identificação,Precisas do cartão de identificação,Ai nevoie de un card de identitate,Нужна личная карта,Треба ти идентификациона картица,Du behöver ett ID-kort,Bir kimlik kartına ihtiyacınız var,Вам потрібна ідентифікаційна карта. +You don't have the key to the prison,TXT_NEED_PRISONKEY,,,,Nemáš klíč do vězení.,Du har ikke nøglen til fængslet,Du brauchst den Schlüssel zum Gefängnis,,"Vi ne havas la ŝlosilon +de la malliberejo",No tienes la llave a la prisión,,Sinulla ei ole vankilan avainta,Vous n'avez pas la clé de la prison.,Nincs kulcsod a börtönhöz.,Ti manca la chiave per la prigione,刑務所のキーを持っていない,감옥에 입장하기 위한 열쇠가 없다,Je hebt de sleutel van de gevangenis niet.,Du har ikke nøkkelen til fengselet.,Nie masz klucza do więzienia,Você não tem a chave da prisão,Não tens a chave da prisão,Nu ai cheia închisorii,Нужен ключ от тюрьмы,Треба ти кључ затвора,Du har inte nyckeln till fängelset.,Hapishanenin anahtarı sende değil.,У вас немає ключа від в'язниці. +Hand print not on file,TXT_NEED_HANDPRINT,,,,Otisk ruky není v databázi.,Håndaftryk er ikke registreret,Handabdruck nicht gespeichert!,,Neregistrita manspuro,Huella de la mano no registrada,,Kädenjälki puuttuu tiedostosta,Votre main n'est pas reconnue par le scanner.,Azonosítatlan kézlenyomat.,Impronta digitale non in archivio,手形認証が一致しません,알 수 없는 지문입니다,Handafdruk niet in het bestand.,Håndavtrykk finnes ikke i filen,Brak odcisku dłoni w bazie danych,Biometria não autorizada,Impressão digital não autorizada,Amprenta mâinii nerecunoscută,Отпечаток руки не распознан,Отисак длана није у записнику,Handavtryck finns inte i registret,El izi dosyada yok,Відбиток руки не упізнано +You need the Gold Key,TXT_NEED_GOLDKEY,,,,Potřebuješ zlatý klíč.,Du har brug for guldnøglen,Du brauchst den goldenen Schlüssel,,Vi bezonas la oran ŝlosilon,Necesitas la llave dorada,,Tarvitset kulta-avaimen,Vous avez besoin d'une clé d'or.,Aranykulcs szükséges.,Ti serve la chiave dorata,ゴールドキーが必要だ,황금 키가 필요하다,Je hebt de gouden sleutel nodig.,Du trenger gullnøkkelen,Potrzebujesz Złotego Klucza,Você precisa da Chave de Ouro,Precisas da Chave de Ouro,Ai nevoie de cheia din Aur,Нужен золотой ключ,Треба ти златни кључ,Du behöver guldnyckeln,Altın Anahtara ihtiyacınız var,Вам потрібен золотий ключ +You need an ID Badge,TXT_NEED_IDBADGE,,,,Potřebuješ identifikační odznak.,Du har brug for et ID-badge,Du brauchst eine Identitätskarte.,,Vi bezonas malliberejan insignon,"Necesitas una insignia +de la prisión",,Tarvitset henkilötunnisteen,Vous avez besoin d'un badge d'identification.,Azonosító jelvény szükséges.,Ti serve un distintivo di identificazione,IDバッジが必要だ,신분 휘장이 필요하다,Je hebt een ID-badge nodig.,Du trenger en ID-badge,Potrzebujesz Odznaki Identyfikacyjnej,Você precisa do Crachá de Identificação,Precisas do Crachá de Identificação,Ai nevoie de un ecuson de identificare,Нужна личная карта,Треба ти лична карта,Du behöver ett ID-bricka,Bir Kimlik Rozetine ihtiyacınız var,Вам потрібен бейджик You need an ID Badge to open this door,TXT_NEED_IDBADGE_DOOR,,,,Pro otevření dveří potřebuješ identifikační odznak.,Du har brug for et ID Badge for at åbne denne dør,"Du brauchst eine Identitätskarte, um diese Tür zu öffnen.",,"Vi bezonas malliberejan insignon -por malfermi ĉi tiun pordon.","Necesitas una insignia de la +por malfermi ĉi tiun pordon","Necesitas una insignia de la prisión para abrir esta puerta",,Tarvitset henkilötunnisteen tämän oven avaamiseksi,Vous avez besoin d'un badge d'identification pour ouvrir cette porte.,Azonosító jelvény szükséges az ajtó kinyitásához.,Ti serve un distintivo di identificazione per superare questa porta,このドアには IDバッジ が必要だ,이 문을 열기 위해서는 신분 휘장이 필요하다,Je hebt een ID-badge nodig om deze deur te openen.,Du trenger en ID-badge for å åpne denne døren,Potrzebujesz Odznaki Identyfikacyjnej aby otworzyć te drzwi,Você precisa do Crachá de Identificação para abrir a porta,Precisas do Crachá de Identificação para abrir a porta,"Ai nevoie de un ecuson de identificare ca să -deschizi ușa",Для открытия нужна личная карта,Треба ти лична карта да отвориш ова врата,Bu kapıyı açmak için kimlik kartına ihtiyacınız var -You need the Silver Key,TXT_NEED_SILVERKEY,,,,Potřebuješ stříbrný klíč.,Du skal bruge sølvnøglen,Du brauchst den Silberschlüssel,,Vi bezonas la arĝentan ŝlosilon. ,Necesitas la llave plateada,,Tarvitset hopea-avaimen,Vous avez besoin de la clé en argent.,Az ezüstkulcs szükséges.,Ti serve la chiave argentata,シルバーキーが必要だ,은 키가 필요하다,Je hebt de zilveren sleutel nodig.,Du trenger sølvnøkkelen,Potrzebujesz Srebrnego Klucza,Você precisa da Chave de Prata,Precisas da Chavede Prata,Ai nevoie de cheia din Argint,Нужен серебряный ключ,Треба ти сребрни кључ,Gümüş Anahtara ihtiyacın var -You need the Brass Key,TXT_NEED_BRASSKEY,,,,Potřebuješ mosazný klíč.,Du skal bruge messingnøglen,Du brauchst den Messingschlüssel,,Vi bezonas la Latunan Ŝlosilon.,Necesitas la Llave de Bronce,,Tarvitset messinkiavaimen,Vous avez besoin de la clé en bronze.,A rézkulcs szükséges.,Ti serve la chiave d'ottone,ブラスキーが必要だ,황동 키가 필요하다,Je hebt de messing sleutel nodig.,Du trenger messingnøkkelen,Potrzebujesz Mosiężnego Klucza,Você precisa da Chave de Latão,Precisas da Chave de Latão,Ai nevoie de cheia din Alamă,Нужен латунный ключ,Треба ти кључ од месинга,Pirinç Anahtara ihtiyacın var -You need the Red Crystal,TXT_NEED_REDCRYSTAL,,,,Potřebuješ červený krystal.,Du skal bruge den røde krystal,Du brauchst den roten Kristall,,Vi bezonas la Ruĝan Kristalon.,Necesitas el Cristal Rojo,,Tarvitset punaisen kristallin,Vous avez besoin du cristal rouge.,A vörös kristályra lesz szükség itt.,Ti serve il Cristallo Rosso,赤水晶のキーが必要だ,적색 크리스탈이 필요하다,Je hebt de rode kristallen sleutel nodig.,Du trenger den røde krystallen,Potrzebujesz Czerwonego Kryształu,Você precisa do Cristal Vermelho,Precisas do Cristal Vermelho,Ai nevoie de Cristalul Roșu,Нужен красный кристалл,Треба ти црвени кристал,Kırmızı Kristal'e ihtiyacın var. -You need the Blue Crystal,TXT_NEED_BLUECRYSTAL,,,,Potřebuješ modrý krystal.,Du skal bruge den blå krystal,Du brauchst den blauen Kristall,,Vi bezonas la Bluan Kristalon.,Necesitas el Cristal Azul,,Tarvitset sinisen kristallin,Vous avez besoin du cristal bleu.,A kék kristályra lesz szükség itt.,Ti serve il Cristallo Blu,青水晶のキーが必要だ,청색 크리스탈이 필요하다,Je hebt de blauwe kristallen sleutel nodig.,Du trenger den blå krystallen,Potrzebujesz Niebieskiego Kryształu,Você precisa do Cristal Azul,Precisas do Cristal Azul,Ai nevoie de Cristalul Albastru,Нужен синий кристалл,Треба ти плави кристал,Mavi Kristal'e ihtiyacın var. +deschizi ușa",Для открытия нужна личная карта,Треба ти лична карта да отвориш ова врата,Du behöver en ID-bricka för att öppna den här dörren.,Bu kapıyı açmak için kimlik kartına ihtiyacınız var,"Вам потрібен бейджик, щоб відкрити ці двері" +You need the Silver Key,TXT_NEED_SILVERKEY,,,,Potřebuješ stříbrný klíč.,Du skal bruge sølvnøglen,Du brauchst den Silberschlüssel,,Vi bezonas la arĝentan ŝlosilon,Necesitas la llave plateada,,Tarvitset hopea-avaimen,Vous avez besoin de la clé en argent.,Az ezüstkulcs szükséges.,Ti serve la chiave argentata,シルバーキーが必要だ,은 키가 필요하다,Je hebt de zilveren sleutel nodig.,Du trenger sølvnøkkelen,Potrzebujesz Srebrnego Klucza,Você precisa da Chave de Prata,Precisas da Chavede Prata,Ai nevoie de cheia din Argint,Нужен серебряный ключ,Треба ти сребрни кључ,Du behöver silvernyckeln,Gümüş Anahtara ihtiyacın var,Вам потрібен срібний ключ +You need the Brass Key,TXT_NEED_BRASSKEY,,,,Potřebuješ mosazný klíč.,Du skal bruge messingnøglen,Du brauchst den Messingschlüssel,,Vi bezonas la latunan ŝlosilon,Necesitas la llave de latón,,Tarvitset messinkiavaimen,Vous avez besoin de la clé en bronze.,A rézkulcs szükséges.,Ti serve la chiave d'ottone,ブラスキーが必要だ,황동 키가 필요하다,Je hebt de messing sleutel nodig.,Du trenger messingnøkkelen,Potrzebujesz Mosiężnego Klucza,Você precisa da Chave de Latão,Precisas da Chave de Latão,Ai nevoie de cheia din Alamă,Нужен латунный ключ,Треба ти кључ од месинга,Du behöver mässingsnyckeln,Pirinç Anahtara ihtiyacın var,Вам потрібен латунний ключ +You need the Red Crystal,TXT_NEED_REDCRYSTAL,,,,Potřebuješ červený krystal.,Du skal bruge den røde krystal,Du brauchst den roten Kristall,,Vi bezonas la ruĝan kristalon,Necesitas el cristal rojo,,Tarvitset punaisen kristallin,Vous avez besoin du cristal rouge.,A vörös kristályra lesz szükség itt.,Ti serve il Cristallo Rosso,赤水晶のキーが必要だ,적색 크리스탈이 필요하다,Je hebt de rode kristallen sleutel nodig.,Du trenger den røde krystallen,Potrzebujesz Czerwonego Kryształu,Você precisa do Cristal Vermelho,Precisas do Cristal Vermelho,Ai nevoie de Cristalul Roșu,Нужен красный кристалл,Треба ти црвени кристал,Du behöver den röda kristallen,Kırmızı Kristal'e ihtiyacın var.,Вам потрібен червоний кристальний ключ +You need the Blue Crystal,TXT_NEED_BLUECRYSTAL,,,,Potřebuješ modrý krystal.,Du skal bruge den blå krystal,Du brauchst den blauen Kristall,,Vi bezonas la bluan kristalon,Necesitas el cristal azul,,Tarvitset sinisen kristallin,Vous avez besoin du cristal bleu.,A kék kristályra lesz szükség itt.,Ti serve il Cristallo Blu,青水晶のキーが必要だ,청색 크리스탈이 필요하다,Je hebt de blauwe kristallen sleutel nodig.,Du trenger den blå krystallen,Potrzebujesz Niebieskiego Kryształu,Você precisa do Cristal Azul,Precisas do Cristal Azul,Ai nevoie de Cristalul Albastru,Нужен синий кристалл,Треба ти плави кристал,Du behöver den blå kristallen,Mavi Kristal'e ihtiyacın var.,Вам потрібен синій кристальний ключ This area is only available in the retail version of Strife,TXT_RETAIL_ONLY,,,,Tato oblast je dostupná pouze v registrované verzi.,Dette område er kun tilgængeligt i detailudgaven af Strife,Dieser Bereich ist nur in der kompletten Version von Strife erreichbar.,Αυτή η περιοχή είναι μονο διαθέσημη στήν εγραμμένη έκδοση του Strife,"Ĉi tiu loko estas enirebla nur en la komercaĵa versio de Strife","Esta área solo está disponible en la versión completa de Strife",,Tämä alue on saatavilla ainoastaan Strifen kokoversiossa,Cette zone n'est accessible que dans la version complète de Strife.,Ez a terület kizárólag a Strife teljes verziójában érhető el,Quest'area è disponibile solo nella versione completa di Strife.,このエリアは Strifeの製品版でのみ利用可能です,이 구역은 정품 버전에서만 입장이 가능합니다,Deze ruimte is alleen beschikbaar in de verkoopversie van Strife.,Dette området er bare tilgjengelig i salgsversjonen av Strife.,Ten obszar jest dostępny tylko w pełnej wersji Strife,Essa área está disponível apenas na versão registrada de Strife,,"Această zonă e disponibilă doar în versiunea -cumpărată a jocului Strife",Эта локация доступна только в полной версии Strife,Ова област је само доступна у пуној верзији Strife-а,Bu alan yalnızca Strife'ın perakende sürümünde mevcuttur -That doesn't seem to work,TXT_DOES_NOT_WORK,,,,Takhle to nepůjde.,Det ser ikke ud til at virke,Das scheint nicht zu funktionieren,,Tio ŝajne ne funkcias.,Parece que eso no funciona,,Se ei näytä toimivan,Cela ne semble pas fonctionner.,Ez nem akar működni.,Non sembra funzionare,それは作動していない,작동이 안 되는 것 같다,Dat lijkt niet te werken.,Det ser ikke ut til å virke,To zdaje się nie działać,Parece que isso não funciona,,Nu pare să funcționeze,"Похоже, что не работает",То изгледа да не ради,Bu işe yaramıyor gibi görünüyor. -You need the chalice!,TXT_NEED_CHALICE,,,,Potřebuješ kalich!,Du skal bruge bægeret!,Du brauchst den Kelch!,,Vi bezonas la kalikon!,¡Necesitas el Cáliz!,,Tarvitset maljan!,Vous avez besoin du calice!,A Kupára van szükséged!,Hai bisogno del calice.,聖杯が必要だ!,성배가 필요하다!,Je hebt de beker nodig!,Du trenger begeret!,Potrzebujesz kielicha!,Você precisa do cálice!,Precisas do cálice!,Ai nevoie de potir!,Нужна чаша!,Треба ти пехар!,Kadehe ihtiyacın var! +cumpărată a jocului Strife",Эта локация доступна только в полной версии Strife,Ова област је само доступна у пуној верзији Strife-а,Det här området finns bara i detaljhandelsversionen av Strife.,Bu alan yalnızca Strife'ın perakende sürümünde mevcuttur,Ця локація доступна тільки у повній версії Strife +That doesn't seem to work,TXT_DOES_NOT_WORK,,,,Takhle to nepůjde.,Det ser ikke ud til at virke,Das scheint nicht zu funktionieren,,Tio ŝajne ne funkcias,Parece que eso no funciona,,Se ei näytä toimivan,Cela ne semble pas fonctionner.,Ez nem akar működni.,Non sembra funzionare,それは作動していない,작동이 안 되는 것 같다,Dat lijkt niet te werken.,Det ser ikke ut til å virke,To zdaje się nie działać,Parece que isso não funciona,,Nu pare să funcționeze,"Похоже, что не работает",То изгледа да не ради,Det verkar inte fungera.,Bu işe yaramıyor gibi görünüyor.,"Здається, воно не працює" +You need the chalice!,TXT_NEED_CHALICE,,,,Potřebuješ kalich!,Du skal bruge bægeret!,Du brauchst den Kelch!,,Vi bezonas la kalikon!,¡Necesitas el Cáliz!,,Tarvitset maljan!,Vous avez besoin du calice!,A Kupára van szükséged!,Hai bisogno del calice.,聖杯が必要だ!,성배가 필요하다!,Je hebt de beker nodig!,Du trenger begeret!,Potrzebujesz kielicha!,Você precisa do cálice!,Precisas do cálice!,Ai nevoie de potir!,Нужна чаша!,Треба ти пехар!,Du behöver kalken!,Kadehe ihtiyacın var!,Вам потрібна чаша! You need the Oracle Pass!,TXT_NEED_OPASS,,,,Potřebuješ propustku od věštce!,Du har brug for orakelpas!,Du brauchst den Orakelpass!,,"Vi bezonas la paspermeson -de la Orakolo!",¡Necesitas el Pase del Oráculo!,,Tarvitset Oraakkelin passin,Vous avez besoin du passe Oracle!,Az Orákulum Engedélyére van szükséged!,Hai bisogno del pass dell'Oracolo.,オラクルパスが必要だ!,오라클 통행증이 필요하다!,Je hebt de Orakelpas nodig!,Du trenger Orakelpasset!,Potrzebujesz Przepustki Wyroczni!,Você precisa do Passe do Oráculo!,Precisas do Passe do Oráculo!,Ai nevoie de legitimația Oracol!,Нужен пропуск Оракула!,Треба ти Пророкова пропусница!,Kahin Kartı'na ihtiyacın var! -,,Actor tags,,,,,,,,,,,,,,,,,,,,,,,, -Dagger,TAG_PUNCHDAGGER,,,,Dýka,Dolk,Dolch,Μαχάιρι,Ponardo,Daga,,Tikari,Dague de Poing,Tőr,Pugnale,ダガー,단검,Dolk,Dolk,Sztylet,Punhal,,Pumnal,Кинжал,Бодеж,Hançer -Crossbow,TAG_STRIFECROSSBOW1,Crossbow with electric bolts,,,Kuše,Armbrøst,Armbrust,Τόξο (Δηλητήριο),Arbalesto (Elektraj sagoj),Ballesta (eléctrica),,Jousipyssy,Arbalète Electrique,Nyílpuska,Balestra ,クロスボウ,석궁 (전격),Kruisboog,Armbrøst,Kusza,Besta,,Arbaletă,Арбалет,Самострел,Arbalet -Crossbow,TAG_STRIFECROSSBOW2,Crossbow with poison bolts,,,Kuše,Armbrøst,Armbrust,Τόξο (Ηλεκτρικό),Arbalesto (Venenaj sagoj),Ballesta (veneno),,Jousipyssy,Arbalète Empoisonée,Nyílpuska,Balestra ,クロスボウ,석궁 (맹독),Kruisboog,Armbrøst,Kusza,Besta,,Arbaletă,Арбалет,Самострел,Arbalet -Assault Gun,TAG_ASSAULTGUN,,,,Útočná puška,Angrebsvåben,Sturmgewehr,,Sturmofusilo,Fusil de asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'Assalto ,アサルトガン,돌격소총,Aanvalswapen,Stormgevær,Karabin Szturmowy,Fuzil de Assalto,Arma de Assalto,Pușcă de Asalt,Штурмовая винтовка,Аутоматска пушка,Saldırı Silahı -Mini Missile Launcher,TAG_MMLAUNCHER,,,,Miniraketomet,Mini-missilkaster,Miniraketenwerfer,Μίνι-Πυραυλοβόλο,Misilet-ĵetilo,Minilanzamisiles,,Miniohjuslaukaisin,Lanceur de Mini-Missiles,Mini Rakétavető,Mini-Lanciamissili,ミニミサイルランチャー,미니 미사일 런쳐,Miniraketwerper,Mini rakettkaster,Wyrzutnia Minipocisków,Mini Lança-mísseis,,Mini Lansator de Proiectile,Мини-гранатомёт,Мини ракетни бацач,Mini Füze Fırlatıcı -Flame Thrower,TAG_FLAMER,,,,Plamenomet,Flammekaster,Flammenwerfer,,Flamĵetilo,Lanzallamas,,Liekinheitin,Lance-Flammes,Lángszóró,Lanciafiamme ,火炎放射器,화염방사기,Vlammenwerper,Flammekaster,Miotacz Ognia,Lança-chamas,,Aruncător de Flăcări,Огнемёт,Бацеч пламена,Alev Fırlatıcı -Mauler,TAG_MAULER1,,,,Trhač,Mauler,Vernichter,,Vundegilo,Triturador (dispersión),,Moukari,Broyeur,Marcangoló,Pestatore ,マウラー,마울러 (저출력),Toetakelaar,Mauler,Miażdżyciel,Desintegrador,,Sfâșietor,Истязатель,Маулер,Parçalayıcı -Mauler,TAG_MAULER2,,,,Trhač,Mauler,Vernichter,,Vundegilo,Triturador (torpedo),,Moukari,Broyeur,Marcangoló,Pestatore,マウラー,마울러 (고출력),Toetakelaar,Mauler,Miażdżyciel,Desintegrador,,Sfâșietor,Истязатель,Маулер,Parçalayıcı -Grenade Launcher,TAG_GLAUNCHER1,High-explosive grenade launcher,,,Granátomet,Granatkaster,Granatwerfer,,Granadĵetilo (PE),Lanzagranadas,,Kranaatinheitin,Lance-Grenades Explosif,Gránátvető,Lanciagranate,グレネードランチャー,유탄발사기 (고폭탄),Granaatwerper,Granatkaster,Wyrzutnia Granatów,Lança-granadas,,Lansator de Grenade,Гранатомёт,Бацач граната,El Bombası Fırlatıcı -Grenade Launcher,TAG_GLAUNCHER2,White phosphorous grenade launcher ,,,Granátomet,Granatkaster,Granatwerfer,,Granadĵetilo (Fosfora),Lanzagranadas (fósforo),,Kranaatinheitin,Lance-Grenades Incendiaire,Gránátvető,Lanciagranate,グレネードランチャー,유탄발사기 (소이탄),Granaatwerper,Granatkaster,Wyrzutnia Granatów,Lança-granadas,,Lansator de Grenade,Гранатомёт,Бацач граната,El Bombası Fırlatıcı -Sigil,TAG_SIGIL,,,,Pečeť,,,,Sigelo,Emblema,,Sinetti,,Pecsét,Sigillo,シジル,시질,Sigil,,Pieczęć,Sigilo,,Sigiliu,Печать,Сигил,Sigil -Coin,TAG_COIN,,,,Mince,Mønt,Münze,,Monero,Moneda,,Kolikko,Pièce,Érme,Moneta,コイン,동전,Munt,Mynt,Moneta,Moeda(s),,Monedă,Монета,Новчић,Madeni Para -Med patch,TAG_MEDPATCH,,,,Obvazy,Medicinsk bandage,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekääre,Pansement,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinsk lapp,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинт,Прва помоћ,Med yama -Medical kit,TAG_MEDICALKIT,,,,Lékárnička,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku,Kit Médical,Orvosi Készlet,Kit di Pronto Soccorso ,医療キット,구급 키트,Medicijndoos,Medisinsk sett,Apteczka,Kit médico,,Kit de Prim-Ajutor,Аптечка,Медицински прибор,Tıbbi kit -Surgery Kit,TAG_SURGERYKIT,,,,Chirurgická souprava,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kirurgilaukku,Kit de Chirurgie,Sebészeti Készlet,Kit Chirurgico ,手術キット,수술 키트,Chirurgiepakket,Kirurgisk sett,Zestaw Chirurga,Kit de Cirurgia,,Kit pentru Operații,Медкомплект,Хируршки прибор,Ameliyat Kiti -Ring,TAG_BELDINSRING,,,,Prsten,,,,Ringo,Anillo,,Sormus,Anneau,Gyűrű,Anello ,指輪,반지,Ring,,Pierścień,Anel,,Inel,Кольцо,Прстен,Yüzük -Offering Chalice,TAG_OFFERINGCHALICE,,,,Obětní kalich,Offerkalk,Opferkelch,,Oferdona kaliko,Cáliz de ofrenda,,Uhrimalja,Calice d'Obole,Áldozati kehely,Calice delle Offerte,寄贈された聖杯,번제 성배,Offerbeker,Offerbeger,Kielich Ofiarny,Calice de Oferenda,,Potir pentru Ofrande,Чаша для подношений,Жртвени пехар,Adak Kadehi -Ear,TAG_EAR,,,,Ucho,Øre,Ohr,,Orelo,Oreja,,Korva,Oreille,Fül,Orecchio,耳,귀,Oor,Øre,Ucho,Orelha,,Ureche,Ухо,Уво,Kulak -Broken Power Coupling,TAG_BROKENCOUPLING,,,,Rozbitá spojka,Brækket strømkobling,Defekter Stromabnehmer,,Rompita energia kuplilo,Acoplador de energía roto,,Rikkinäinen virtaliitin,Coupleur Energétique cassé,Elromlott Tápcsatlakozó,Coppia Energetica Rotta ,壊れたパワーカップリング,망가진 동력선,Gebroken stroomkoppeling,Ødelagt kraftkobling,Zepsute Obwody Zasilające,Acoplador de Energia Quebrado,Acoplador de Energia Partido,Cuplaj de Putere Defect,Повреждённая муфта,Неисправна спојница напајања,Kırık Güç Kaplini -Shadow Armor,TAG_SHADOWARMOR,,,Shadow Armour,Stínové brnění,Skygge rustning,Schattenrüstung,,Ombra armaĵo,Armadura de sombra,,Varjohaarniska,Armure de l'Ombre,Sötét Páncél,Armatura Ombra ,シャドウアーマー,그림자 갑옷,Schaduwharnas,Skygge rustning,Cienisty Pancerz,Armadura das Sombras,,Armura Umbrei,Теневая броня,Оклоп сенки,Gölge Zırhı -Environmental Suit,TAG_ENVSUIT,,,,Ochranný oblek,Miljømæssig dragt,Schutzanzug,,Medi-ŝirma vesto,Traje de protección ambiental,,Ympäristösuojapuku,Combinaison Hazmat,Védőöltözet,Tuta Ambientale ,耐環境スーツ,환경 방호복,Beschermend pak,Miljødrakt,Skafander Ochronny,Traje de Proteção,Fato Protetor,Costum de Protecție,Защитный костюм,Заштитно одело,Çevresel Takım -Guard Uniform,TAG_GUARDUNIFORM,,,,Hlídačova uniforma,Gardeuniform,Wächteruniform,,Gardista uniformo,Uniforme de guardia,,Vartijan univormu,Uniforme de Garde,Őr Egyenruha,Uniforme da Guardia,ガードの制服,경비 전투복,Wachtersuniform,Vaktuniform,Mundur Strażnika,Uniforme de Guarda,,Uniformă de Paznic,Униформа стражника,Стражарска униформа,Bekçi Üniforması -Officer's Uniform,TAG_OFFICERSUNIFORM,,,,Důstojníkova uniforma,Officersuniform,Offiziersuniform,,Oficira uniformo,Uniforme de oficial,,Upseerin univormu,Uniforme d'Officier,Tiszti Egyenruha,Uniforme da Ufficiale ,士官の制服,장교 전투복,Officiersuniform,Offisersuniform,Mundur Oficera,Uniforme de Oficial,,Uniformă de Ofițer,Офицерская униформа,Официрска униформа,Memur Üniforması -Flame Thrower Parts,TAG_FTHROWERPARTS,,,,Díly plamenometu,Dele til flammekasteren,Flammenwerferteile,,Partoj de flamjetilo,Partes de lanzallamas,,Liekinheittimen osat,Pièces de Lance-Flamme,Lángszóró Alkatrészek,Parti di Lanciafiamme ,火炎放射器の部品,화염방사기 부품,Vlammenwerperonderdelen,Deler til flammekaster,Części Miotacza Ognia,Partes do lança-chamas,,Bucăți de Aruncător de Flăcări,Детали огнемёта,Делови бацача пламена,Alev Püskürtücü Parçaları -Report,TAG_REPORT,,,,Hlášení,Rapport,,,Raporto,Reporte,,Raportti,Compte-rendu,Jelentés,Rapporto ,報告書,보고서,Verslag,Rapport,Raport,Relatório,,Raport,Отчёт,Извештај,Rapor -Info,TAG_INFO,,,,Informace,,,,Informo,Información,,Tiedot,,Információ,Informazioni ,情報,정보,Info,Informasjon,Informacje,Informação,,Informație,Сводка,Инфо,Bilgi -Targeter,TAG_TARGETER,,,,Zaměřovač,,Zielhilfe,,Celilo,Apuntador,,Tähtäinlaite,Cibleur,Célzó eszköz,Puntatore,照準器,조준기,Richter,,Namierzacz,Mira,,Țintitor,Целеуказатель,Нишанџија,Hedefleme cihazı -Communicator,TAG_COMMUNICATOR,,,,Komunikátor,Kommunikator,Kommunikator,,Komunikilo,Comunicador,,Viestintälaite,Communicateur,Kommunikátor,Comunicatore ,コミュニケーター,연락장치,Communicator,Kommunikator,Komunikator,Comunicador,,Comunicator,Передатчик,Комуникатор,İletişimci -Degnin Ore,TAG_DEGNINORE,,,,Degninská ruda,Degnin malm,Degnin-Erz,,Degnina Erco,Mineral Degnin,,Degnin-malmi,Minerai de Degnin,Degnin Érc,Minerale Degnin,デグニン鉱石,데그닌 광석,Degnin-erts,Degnin malm,Ruda Degninu,Minério Degnin,,Minereu de Degnir,Денгинская руда,Дегнинска руда,Degnin Cevheri -Accuracy,TAG_GUNTRAINING,,,,Přesnost,Nøjagtighed,Präzision,,Akurateco,Precisión,,Tarkkuus,Précision,Pontosság,Precisione,精度,정확도,Nauwkeurigheid,Nøyaktighet,Precyzja,Precisão,,Acuratețe,Меткость,Прецизност,Doğruluk -Toughness,TAG_HEALTHTRAINING,,,,Tvrdost,Robusthed,Ausdauer,,Forteco,Dureza,,Sitkeys,Endurance,Kitartás,Robustezza ,タフネス,힘,Stevigheid,Seighet,Wytrzymałość,Força,,Rezistență,Живучесть,Издржљивост,Sertlik -Scanner,TAG_SCANNER,,,,Skener,,,,Skanilo,Escáner,,Skanneri,Analyseur,Szkenner,Scanner,スキャナー,탐지기,Scanner,Skanner,Skaner,Scanner,,Scanner,Сканер,Скенер,Tarayıcı -Prison Pass,TAG_PRISONPASS,,,,Propustka do vězení,Fængselspas,Gefängnispass,,Mallibereja pasilo,Pase a la prisión,,Vankilan pääsylupa,Passe de la Prison,Börtön Engedély,Lasciapassare Prigione ,刑務所の許可証,감옥 통행증,Gevangenispas,Fengselspass,Przepustka do Więzienia,Passe da Prisão,,Legitimația pentru Închisoare,Пропуск в тюрьму,Затворска пропусница,Hapishane Kartı -Alarm,TAG_ALARM,,,,,,,,Alarmo,Alarma,,Hälytys,Alarme,Riasztó,Allarme ,警報,알람,Alarm,,,Alarme,,Alarmă,Тревога,Аларм,Alarm -Ammo,TAG_AMMOFILLUP,,,,Munice,Munition,Munition,,Municio,Munición,,Ammukset,Munitions,Lőszer,Munizioni ,弾薬,탄약,Munitie,Ammunisjon,Amunicja,Munição,,Muniție,Боеприпасы,Муниција,Cephane -Health,TAG_HEALTHFILLUP,,,,Zdraví,Sundhed,Gesundheit,,Sano,Salud,,Terveys,Santé,Életerő,Salute ,体力,체력,Gezondheid,Helse,Zdrowie,Saúde,,Sănătate,Здоровье,Живот,Sağlık -Teleporter Beacon,TAG_TELEPORTERBEACON,,,,Teleportační maják,Teleportør-bakke,Teleportersignal,,Formovila Signalilo,Faro de Teletransportación,,Kaukosiirrinmajakka,Balise de téléportation,Teleport Vészfény,Radiofaro per Teletrasporto ,テレポータービーコン,텔레포터 비콘,Teleporterbaken,Teleporter Beacon,Nadajnik Teleportera,Sinalizador para Teletransporte,,Lumină pentru Teleportor,Телепортационный маяк,Одашиљач за телепортовање,Işınlayıcı İşaretçisi -Metal Armor,TAG_METALARMOR,,,Metal Armour,Kovové brnění,Metal rustning,Metallrüstung,,Metala armaĵo,Armadura de metal,,Metallihaarniska,Armure en Métal,Fém Páncél,Armatura di Metallo ,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowy Pancerz,Armadura de Metal,,Armură din Metal,Металлическая броня,Метални оклоп,Metal Zırh -Leather Armor,TAG_LEATHER,,,Leather Armour,Kožené brnění,Læderpanser,Lederrüstung,,Leda armaĵo,Armadura de cuero,,Nahkasuojus,Armure en Cuir,Bőr Páncél,Armatura di Cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Lær rustning,Skórzany Pancerz,Armadura de Couro,,Armură din Piele,Кожаная броня,Кожни оклоп,Deri Zırh -HE-Grenade Rounds,TAG_HEGRENADES,,,,Výbušné granáty,HE-granater,HE-Granaten,,HE-grenadoj,Granadas HE,,Räjähdekranaatit,Grenades Explosives,Gránát Lőszer,Granata HE,HEグレネード弾,고폭 유탄,HE-granaten,HE-Granater,Wiązka Granatów,Munição - Granadas Explosivas,,Grenade Explozive,Осколочные гранаты,Хе-Граната чауре,HE-Bomba Mermileri -Phosphorus-Grenade Rounds,TAG_PHGRENADES,,,,Fosforové granáty,Fosforgranater,Phosphorgranaten,,Fosforaj grenadoj,Granadas de fósforo,,Fosforikranaatit,Grenades Incendiaires,Foszfor-Gránát Lőszer,Granata al Fosforo ,白リングレネード弾,소이 유탄,Fosforgranaten,Fosforgranater,Wiązka Fosforowych Granatów,Municão - Granadas de Fósforo,,Grenade cu Fosfor,Фосфорные гранаты,Фосфорне гранате,Fosforlu El Bombası Mermileri -Clip of Bullets,TAG_CLIPOFBULLETS,,,,Zásobník s náboji,Kugleklip,Gewehrmunition,,Magazeno,Cargador de balas,,Luotilipas,Chargeur d'Assaut,Golyó töltények,Caricatore di Proiettili ,弾丸のクリップ,소총 탄창,Patroon kogels,Klipp av kuler,Magazynek,Carregador de Balas,,Cartuș cu Gloanțe,Обойма,Клип метака,Kurşun Klipsi -Ammo,TAG_BOXOFBULLETS,,,,Krabice nábojů,Munition,Munitionskiste,,Municikesto,Caja de municiones,,Luotilaatikko,Bôite de Munitions,Lőszer,Munizioni ,弾薬箱,탄약,Munitie,Ammunisjon,Amunicja,Caixa de Balas,,Muniție,Боеприпасы,Муниција,Cephane -Mini Missiles,TAG_MINIMISSILES,,,,Minirakety,Mini missiler,Miniraketen,,Misiletoj,Minimisiles,,Miniohjukset,Mini-Missiles,Mini Rakéták,Mini-Missili,ミニミサイル,미니 미사일,Mini-raketten,Mini missiler,Mini Pociski,Mísseis,,Mini Proiectile,Мини-ракеты,Мини Ракете,Mini Füzeler -Crate of Missiles,TAG_CRATEOFMISSILES,,,,Bedna raket,kasse med missiler,Raketenkiste,,Misilet-kesto,Caja de misiles,,Ohjuslaatikko,Caisse de Mini-Missiles,Ládányi Rakéta,Cassa di Missili,ミサイルの箱,미사일 박스,Krat raketten,Kasse med missiler,Skrzynia z Pociskami,Caixa de Mísseis,,Ladă cu Proiectile,Коробка ракет,Кутија ракета,Füze Sandığı -Energy Pod,TAG_ENERGYPOD,,,,Energetický kokón,Energipod,Energiezelle,,Umo de Energio,Vaina de Energía,,Energia-akku,Cellule Energétique,Energia Lőszer,Nucleo Enegetico ,エネルギーポット,에너지 포드,Energiecel,Energikapsel,Kapsuła Energii,Energia (pequeno),,Capsulă cu Energie,Энергоячейка,Енергетска шипка,Enerji Bölmesi -Energy Pack,TAG_ENERGYPACK,,,,Energetický svazek,Energipakke,Energiepack,,Pako de Energio,Pack de Energía,,Energiapaketti,Pack Energétique,Energia Csomag,Carica Energetica ,エネルギーパック,에너지 팩,Energiepak,Energipakke,Zasobnik Energii,Energia (grande),,Pachet cu Energie,Энергобатарея,Паковање енергије,Enerji Paketi -Poison Bolts,TAG_POISONBOLTS,,,,Otrávené šípy,Giftige bolte,Giftbolzen,,Venenaj sagoj,Flechas venenosas,,Myrkkynuolet,Carreaux Empoisonnés,Mérgező hegyek,Dardi Velenosi ,ポイズンボルト,맹독 볼트,Giftige bouten,Giftbolter,Zatrute Bełty,Setas Envenenadas,,Bolțuri cu Otravă,Отравленные болты,Отровне стреле,Zehirli Cıvatalar -Electric Bolts,TAG_ELECTRICBOLTS,,,,Elektrické šípy,Elektriske bolte,Elektrische Bolzen,,Elektraj sagoj,Flechas eléctricas,,Sähkönuolet,Carreaux Electriques,Elektromos hegyek,Dardi Elettrici ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektriske bolter,Elektryczne Bełty,Setas Elétricas,,Bolțuri cu Electricitate,Электрические болты,Електричне стреле,Elektrikli Cıvatalar -Ammo Satchel,TAG_AMMOSATCHEL,,,,Brašna na munici,Ammo Satchel,Munitionstasche,,Sako da municioj,Bolso de municiones,,Ammuslaukku,Sacoche à munitions,Lőszeres táska,Borsa di Munizioni ,弾薬鞄,탄약 배낭,Munitietassen,Ammunisjonsveske,Torba z Amunicją,Bolsa de Munição,,Sacoșă cu Muniție,Ранец для боеприпасов,Торбица муниције,Cephane Çantası -Base Key,TAG_BASEKEY,,,,Klíč od základny,Basisnøgle,Basisschlüssel,,Bazŝlosilo,Llave de la base,,Tukikohdan avain,Clé de la base,Bázis Kulcs,Chiave della Base,,기지 키,Basissleutel,Basenøkkel,Klucz do Bazy,Chave da Base,,Cheia Bazei,Ключ от базы,Кључ базе,Temel Anahtar -Govs Key,TAG_GOVSKEY,,,,Klíč ke guvernérovi,Govs nøgle,Gouverneursschlüssel,,Ŝlosilo de registo,Llave Gobernador,,Kuvernöörin avain,Clé du Gouverneur,Kormányzó Kulcs,Chiave del Governatore ,,총독의 키,Gouverneursleutel,Regjeringsnøkkel,Klucz Gubernatora,Chave do Governador,,Cheia Guvernatorului,Ключ губернатора,Гувернеров кључ,Govs Anahtar -Passcard,TAG_PASSCARD,,,,Vstupní karta,Adgangskort,Zugangskarte,,Central-ŝlosilo,Llave de la central,,Avainkortti,Passe,Belépőkártya,Tessera Lasciapassare ,,통행 카드,Paspoortkaart,Adgangskort,Karta Dostępu,Cartão de Acesso,,Legitimație,Пропуск,Пропусница,Geçiş kartı -ID Badge,TAG_IDBADGE,,,,Identifikační odznak,ID-badge,Identitätskarte,,Mallibereja insigno,Insignia de prisión,,Henkilötunniste,Badge d'Identification,Azonosító Jelvény,Distintivo ,,신분 휘장,ID-Badge,ID-badge,Odznaka Identyfikacyjna,Crachá de Identificação,,Ecuson de Identificare,Личная карта,Идентификациона значка,Kimlik Rozeti -Prison Key,TAG_PRISONKEY,,,,Klíč od věznice,Fængselsnøgle,Gefängnisschlüssel,,Mallibereja ŝlosilo,Llave de la prisión,,Vankilan avain,Clé de la Prison,Börtön Kulcs,Chiave della Prigione ,,감옥 키,Gevangenissleutel,Fengselsnøkkel,Klucz do Więzienia,Chave da Prisão,,Cheia Închisorii,Ключ от тюрьмы,Кључ од 3атвора,Hapishane Anahtarı -Severed Hand,TAG_SEVEREDHAND,,,,Useknutá ruka,Afskåret hånd,Abgetrennte Hand,,Amputita mano,Mano amputada,,Katkennut käsi,Main coupée,Levágott Kéz,Mano Mozzata,,잘린 손목,Gescheurde Hand,Avkuttet hånd,Odcięta Ręka,Mão Decepada,Mão Desmenbrada,Mână Retezată,Отрезанная рука,Одвојена шака,Kesik El -Power1 Key,TAG_POWER1KEY,,,,Klíč od elektrárny 1,Power1 nøgle,Kraftwerksschlüssel 1,,Central-identigo 1,Ident. central nv. 1,,Voimalan 1-avain,Clé Power1,1. erő kulcs,Chiave della Centrale 1,,발전소 1호 키,1e Machtsleutel,Power1-nøkkel,Klucz do Elektrowni 1,Chave da Usina 1,Chave Energética 1,Cheia Putere1,Ключ ЭС №1,Кључ од ел. 1,Güç1 Anahtarı -Power2 Key,TAG_POWER2KEY,,,,Klíč od elektrárny 2,Power2-nøgle,Kraftwerksschlüssel 2,,Central-identigo 2,Ident. central nv. 2,,Voimalan 2-avain,Clé Power2,2. erő kulcs,Chiave della Centrale 2,,발전소 2호 키,2e Machtsleutel,Power2-nøkkel,Klucz do Elektrowni 2,Chave da Usina 2,Chave Energética 2,Cheia Putere2,Ключ ЭС №2,Кључ од ел. 2,Güç2 Anahtarı -Power3 Key,TAG_POWER3KEY,,,,Klíč od elektrárny 3,Power3-nøgle,Kraftwerksschlüssel 3,,Central-identigo 3,Ident. central nv. 3,,Voimalan 3-avain,Clé Power3,3. erő kulcs,Chiave della Centrale 3,,발전소 3호 키,3e Machtsleutel,Power3-nøkkel,Klucz do Elektrowni 3,Chave da Usina 3,Chave Energética 3,Cheia Putere3,Ключ ЭС №3,Кључ од ел. 3,Güç3 Anahtarı -Gold Key,TAG_GOLDKEY,,,,Zlatý klíč,Guldnøgle,Goldschlüssel,,Ora ŝlosilo,Llave dorada,,Kulta-avain,Clé en Or,Aranykulcs,Chiave Dorata,,황금 키,Gouden sleutel,Gullnøkkel,Złoty Klucz,Chave de Ouro,,Cheia din Aur,Золотой ключ,Златни кључ,Altın Anahtar -ID Card,TAG_IDCARD,,,,Identifikační karta,ID-kort,Ausweis,,Kloaka identigilo,Ident. alcantarillas,,Henkilökortti,Carte d'Identité,Azonosító Kártya,Tessera Identificativa,,신분증,ID-Kaart,ID-kort,Karta Identyfikacyjna,Cartão de Identificação,,Card de Identitate,Удостоверение,Лична карта,Kimlik Kartı -Silver Key,TAG_SILVERKEY,,,,Stříbrný klíč,Sølvnøgle,Silberschlüssel,,Arĝenta ŝlosilo,Llave plateada,,Hopea-avain,Clé en Argent,Ezüst Kulcs,Chiave Argentata,,은 키,Zilveren sleutel,Sølv-nøkkel,Srebrny Klucz,Chave de Prata,,Cheia din Argint,Серебряный ключ,Сребрни кључ,Gümüş Anahtar -Oracle Key,TAG_ORACLEKEY,,,,Věštcův klíč,Orakel-nøgle,Orakelschlüssel,,Orakolo-ŝlosilo,Llave del Oráculo,,Oraakkelin avain,Clé de l'Oracle,Orákulum kulcs,Chiave dell'Oracolo ,,오라클 키,Orakelsleutel,Oracle-nøkkel,Klucz do Wyroczni,Chave do Oráculo,,Cheia Oracol,Ключ Оракула,Пророков кључ,Kahin Anahtarı -Military ID,TAG_MILITARYID,,,,Vojenské ID,Militær ID,Militärausweis,,Milita identigilo,Identif. militar,,Sotilastunnus,Identification Militaire,Katonai Azonosító Kártya,Identificativo Militare,,군용 아이디,Militaire ID,Militær ID,Wojskowy Identyfikator,ID Militar,,Legitimație Militară,Удостовер. военного,Војна идентификација,Askeri Kimlik -Order Key,TAG_ORDERKEY,,,,Klíč Řádu,Bestillingsnøgle,Ordensschlüssel,,Ordona ŝlosilo,Llave de La Orden,,Veljeskunnan avain,Clé de l'Ordre,Rend Kulcs,Chiave dell'Ordine,,오더의 키,Ordesleutel,Bestillingsnøkkel,Klucz Zakonu,Chave da Ordem,,Cheia Ordinului,Ключ Ордена,Кључ одреда,Sipariş Anahtarı -Warehouse Key,TAG_WAREHOUSEKEY,,,,Klíč ke skladu,Lagernøgle,Lagerhausschlüssel,,Magazena ŝlosilo,Llave del almacén,,Varaston avain,Clé de l'Entrepôt,Raktár Kulcs,Chiave del Magazzino ,,창고 키,Magazijnsleutel,Lagernøkkel,Klucz do Magazynu,Chave do Armazém,,Cheia Depozitului,Ключ от склада,Кључ складишта,Depo Anahtarı -Brass Key,TAG_BRASSKEY,,,,Mosazný klíč,Messingnøgle,Messingschlüssel,,Latuna Ŝlosilo,Llave de Latón,,Messinkiavain,Clé en Bronze,Réz Kulcs,Chiave d'Ottone ,,황동 키,Messing sleutel,Messingnøkkel,Mosiężny Klucz,Chave de Latão,,Cheia din Alamă,Латунный ключ,Кључ од месинга,Pirinç Anahtar -Red Crystal Key,TAG_REDCRYSTALKEY,,,,Červený krystalový klíč,Rød krystalnøgle,Roter Kristallschlüssel,,Ruĝa Kristala Ŝlosilo,Llave de Cristal Rojo,,Punainen kristalliavain,Clé de Cristal Rouge,Piros Kristály Kulcs,Chiave di Cristallo Rosso ,,적색 크리스탈 키,Rode kristallen sleutel,Rød krystallnøkkel,Czerwony Kryształowy Klucz,Chave de Cristal Vermelho,,Cheia din Cristal Roșu,Крас. ключ-кристалл,Кључ од црвеног кристала,Kırmızı Kristal Anahtar -Blue Crystal Key,TAG_BLUECRYSTALKEY,,,,Modrý krystalový klíč,Blå krystalnøgle,Blauer Kristallschlüssel,,Blua Kristala Ŝlosilo,Llave de Cristal Azul,,Sininen kristalliavain,Clé de Crisal Bleu,Kék Kristály Kulcs,Chiave di Cristallo Blu,,청색 크리스탈 키,Blauwe kristallen sleutel,Blå krystallnøkkel,Niebieski Kryształowy Klucz,Chave de Cristal Azul,,Cheia din Cristal Albastru,Син. ключ-кристалл,Кључ од плавог кристала,Mavi Kristal Anahtar -Chapel Key,TAG_CHAPELKEY,,,,Klíč od kaple,Kapel nøgle,Kapellenschlüssel,,Kapelŝlosilo,Llave de la Capilla,,Kappelin avain,Clé de la Chapelle,Kápolna Kulcs,Chiave della Cappella ,,예배당 키,Kappelsleutel,Kapell-nøkkel,Klucz do Kaplicy,Chave da Capela,,Cheia Capelei,Ключ от часовни,Кључ капеле,Şapel Anahtarı -Catacomb Key,TAG_CATACOMBKEY,,,,Klíč do katakomb,Katakomb Nøgle,Katakombenschlüssel,,Katakombŝlosilo,Llave de la Catacumba,,Katakombin avain,Clé des Catacombes,Katakomba Kulcs,Chiave delle Catacombe ,,고대 묘지 키,Catacombesleutel,Katakomb-nøkkel,Klucz do Katakumb,Chave da Catacumba,,Cheia Catacombei,Ключ от катакомб,Кључ од катакомби,Katakomb Anahtarı -Security Key,TAG_SECURITYKEY,,,,Klíč ochranky,Sikkerhedsnøgle,Sicherheitsschlüssel,,Gardŝlosilo,Llave de Seguridad,,Turvamiesavain,Clé de la Sécurité,Biztonsági Kulcs,Chiave della Sicurezza ,,보안 키,Beveiligingssleutel,Sikkerhetsnøkkel,Klucz Ochrony,Chave de Segurança,,Cheia Securității,Ключ охраны,Сигурносни кључ,Güvenlik Anahtarı -Core Key,TAG_COREKEY,,,,Klíč k jádru,Reaktor Nøgle,Reaktorschlüssel,,Kernŝlosilo,Llave del Núcleo,,Ytimen avain,Clé du Réacteur,Mag Kulcs,Chiave del Nucleo,,중심부 키,Kernsleutel,Kjernenøkkel,Klucz do Rdzenia,Chave do Núcleo,,Cheia Nucleului,Ключ от реактора,Кључ језгра,Çekirdek Anahtar -Mauler Key,TAG_MAULERKEY,,,,Klíč k trhačům,Mauler-nøgle,Vernichterschlüssel,,Vundegilo-ŝlosilo,Llave Triturador,,Moukarin avain,Clé du Broyeur,Marcangoló Kulcs,Chiave del Pestatore ,,마울러 키,Toetakelaarssleutel,Mauler-nøkkel,Klucz do Magazynu Miażdżycieli,Chave - Mauler,,Cheia Sfâșietorului,Ключ истязателя,Маулер кључ,Mauler Anahtar -Factory Key,TAG_FACTORYKEY,,,,Klíč do továrny,Fabriksnøgle,Fabrikschlüssel,,Fabriko-ŝlosilo,Llave de la Fábrica,,Tehtaan avain,Clé de l'Usine,Gyár Kulcs,Chiave della Fabbrica ,,공장 키,Fabriekssleutel,Fabrikknøkkel,Klucz do Fabryki,Chave da Fábrica,,Cheia Fabricii,Ключ от фабрики,Кључ фабрике,Fabrika Anahtarı -Mine Key,TAG_MINEKEY,,,,Klíč od dolů,Mine-nøgle,Minenschlüssel,,Minejŝlosilo,Llave de la Mina,,Kaivoksen avain,Clé de la Mine,Bánya Kulcs,Chiave della Miniera ,,탄광 키,Mijnsleutel,Gruve-nøkkel,Klucz do Kopalni,Chave da Mina,,Cheia Minei,Ключ от шахт,Кључ рудника,Maden Anahtarı -New Key5,TAG_NEWKEY5,,,,Nový klíč 5,Ny nøgle5,Neuer Schlüssel 5,,Nova Ŝlosilo5,Llave Nueva5,,Uusi 5-avain,Clé nouveau 5,5. kulcs,Nuova Chiave 5,,새로운 키5,Nieuwe sleutel 5,Ny nøkkel5,Nowy Klucz5,Chave Nova 5,,Noua Cheie5,Новый ключ №5,Нови кључ5,Yeni Anahtar5 -Oracle Pass,TAG_ORACLEPASS,,,,Věštcova propustka,Orakelpas,Orakelpass,,Orakolo-pasilo,Pase del Oráculo,,Oraakkelin kulkulupa,Passe de l'Oracle,Orákulum útlevél,Lasciapassare dell'Oracolo ,,오라클의 통행증,Orakelpas,Oracle Pass,Przepustka Wyroczni,Passe do Oráculo,,Legitimația Oracol,Пропуск Оракула,Пророкова пропусница,Kahin Kartı -10 gold,TAG_10GOLD,,,,10 zlatých,10 guld,,,10 da oro,10 de oro,,10 kolikkoa,10 Pièces,10 arany,10 pezzi d'oro ,10ゴールド,10 골드,10 goud,10 gull,10 monet,10 moedas,10 moedas de ouro,10 monezi de aur,10 золотых,10 златника,10 altın -25 gold,TAG_25GOLD,,,,25 zlatých,25 guld,,,25 da oro,25 de oro,,25 kolikkoa,25 Pièces,25 arany,25 pezzi d'oro ,25ゴールド,25 골드,25 goud,25 gull,25 monet,25 moedas,25 moedas de ouro,25 de monezi de aur,25 золотых,25 златника,25 altın -50 gold,TAG_50GOLD,,,,50 zlatých,50 guld,,,50 da oro,50 de oro,,50 kolikkoa,50 Pièces,50 arany,50 pezzi d'oro ,50ゴールド,50 골드,50 goud,50 gull,50 monet,50 moedas,50 moedas de ouro,50 de monezi de aur,50 золотых,50 златника,50 altın -300 gold,TAG_300GOLD,,,,300 zlatých,300 guld,,,300 da oro,300 de oro,,300 kolikkoa,300 Pièces,300 arany,300 pezzi d'oro ,300ゴールド,300 골드,300 goud,300 gull,300 monet,300 moedas,300 moedas de ouro,300 de monezi de aur,300 золотых,300 златника,300 altın -Person,TXT_PERSON,,,,Osoba,,,,Persono,Persona,,Henkilö,Personne,Személy,Persona,一員,민간인,Persoon,,Osoba,Pessoa,,Persoană,Горожанин,Особа,Kişi -Acolyte,TAG_ACOLYTE,,,,Akolyta,Akolyt,Ministrant,,Akolito,Acólito,,Akoluutti,,Ministráns,Accolito ,アコライト,아콜라이트,Acoliet,Akolytt,Akolita,Acólito,,Acolit,Служитель,Следбеник,Yardımcı -Armorer,TAG_ARMORER,,,Armourer,Kovář,Våbendør,Rüster,,Armilisto,Armero,,Asemestari,Armurier,Páncélkovács,Armaiolo ,装甲,병기공,Harnassmid,Våpensmed,Płatnerz,Armeiro,,Armurier,Продавец брони,Ковач,Zırhçı -Bar Keep,TAG_BARKEEP,,,,Výčepní,Bar-værn,Wirt,,Trinkejisto,Cantinero,,Baarimikko,Barman,Csapos,Barista,酒屋,바텐더,Barman,Bartender,Barman,Dono do Bar,,Barman,Хозяин таверны,Конобар,Barmen -Beggar,TAG_BEGGAR,,,,Žebrák,Tigger,Bettler,,Almozulo,Mendigo,,Kerjäläinen,Mendiant,Koldus,Mendicante ,乞食,거지,Bedelaar,Tigger,Żebrak,Mendigo,,Sărman,Нищий,Просјак,Dilenci -Macil,TAG_MACIL1,,,,Macil,,,,,,,,,,Macil,マシル,마실,Macil,,Macil,Macil,,Macil,Мэйсил,Мејсил,Macil -Macil,TAG_MACIL2,,,,Macil,,,,,,,,,,Macil ,マシル,마실,Macil,,Macil,Macil,,Macil,Мэйсил,Мејсил,Macil -Medic,TAG_MEDIC,,,,Medik,Læge,Sanitäter,,Kuracisto,Médico,,Lääkintämies,Médecin,Szanitéc,Medico,メディック,의무관,Paramedicus,,Medyk,Médico,,Medic,Врач,Болничар,Medic -Oracle,TAG_ORACLE,,,,Věštec,Orakel,Orakel,,Orakolo,Oráculo,,Oraakkeli,,Orákulum,Oracolo,オラクル,오라클,Orakel,Orakel,Wyrocznia,Oráculo,,Oracol,Оракул,Пророк,Kahin -Priest,TAG_PRIEST,,,,Kněz,Præst,Priester,,Pastro,Sacerdote,,Pappi,Prêtre,Pap,Sacerdote,プリースト,성직자,Priester,Prest,Kapłan,Sacerdote,,Preot,Жрец,Свештеник,Rahip -Rat Buddy,TAG_RATBUDDY,,,,Krysík,Rottekammerat,Ratte,,Rato,Rata,,Rottakamu,Copain Rat,Patkánypajtás,Ratto,ラット バディ,생쥐 친구,Rattenvriendje,Rottekompis,Koleżka Szczurów,Rato,,Amicul Șobolanilor,Крыса-друг,Друг пацов,Sıçan Dostu -Rebel,TAG_REBEL,,,,,Rebel,Rebell,,Ribelanto,Rebelde,,Kapinallinen,Rebelle,Lázadó,Ribelle ,反乱軍,저항군,Rebel,Rebell,Rebeliant,Rebelde,,Rebel,Повстанец,Побуњеник,Asi -Templar,TAG_TEMPLAR,,,,Templář,Tempelridder,Templer,,Templano,Templario,,Temppeliherra,Templier,Templomos,Templare ,騎士団員,템플러,Tempelier,Tempelridder,Templariusz,Templário,,Templier,Храмовник,Темплар,Tapınakçı -Weapon Smith,TAG_WEAPONSMITH,,,,Zbraňmistr,Våbensmed,Waffenschmied,,Armilforĝisto,Forjador de Armas,,Aseseppä,Forgeron,Fegyverkovács,Fabbro ,武器工,무기 제조상,Wapensmid,Våpensmed,Wytwórca Broni,Ferreiro,,Făurar,Оружейник,Ковач оружја,Silah Ustası -Red Talisman,TAG_TALISMANRED,,,,Červený talisman,Rød Talisman,Roter Talisman,,Ruĝa Talismano,Talismán rojo,,Punainen talismaani,Talisman Rouge,Vörös Talizmán,Talismano rosso,赤の魔除け,붉은 부적,Rode Talisman,Rød talisman,Czerwony Talizman,Talismã Vermelho,,Talisman Roșu,Красный талисман,Црвени талисман,Kızıl Tılsım -Green Talisman,TAG_TALISMANGREEN,,,,Zelený talisman,Grøn Talisman,Grüner Talisman,,Verda Talismano,Talismán verde,,Vihreä talismaani,Talisman Vert,Zöld Talizmán,Talismano verde,緑の魔除け,녹색 부적,Groene Talisman,Grønn talisman,Zielony Talizman,Talismã Verde,,Talisman Verde,Зелёный талисман,Зелени талисман,Yeşil Tılsım -Blue Talisman,TAG_TALISMANBLUE,,,,Modrý talisman,Blå Talisman,Blauer Talisman,,Blua Talismano,Talismán azul,,Sininen talismaani,Talisman Bleu,Kék Talizmán,Talismano blu,青の魔除け,푸른 부적,Blauwe Talisman,Blå talisman,Niebieski Talizman,Talismã Azul,,Talisman Albastru,Синий талисман,Плави талисман,Mavi Tılsım -,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,, -%o was zealously shot down by an Acolyte.,OB_ACOLYTE,,,,%o byl@[ao_cs] horlivě zastřelen@[ao_cs] akolytou.,%o blev skudt ned af en akolyt.,%o wurde eifrig von dem Ministranten erschossen.,,%o fervore pafiĝis de Akolito.,%o ha sido derribad@[ao_esp] con fervor por un Acólito.,%o fue derribad@[ao_esp] con entusiasmo por un Acólito.,%o joutui kiivailevan akoluutin ampumaksi.,%o a souffert d'une bavure policière.,%o-t buzgó módon le lett lőve egy Oltárszolga által.,%o è stato zelantemente abbattuto da un accolito. ,%o は熱心なアコライトに堕とされた。,%o 은(는) 아콜라이트에게 맹신적으로 사격 당했다.,%o werd gretig neergeschoten door een Acoliet.,%o ble nidkjært skutt ned av en akolytt.,%o został@[ao_pl] żarliwie zastrzelon@[adj_pl] przez Akolitę.,%o foi zelosamente abatid@[ao_ptb] por um Acólito.,,%o a fost împușcat zelos de un Acolit.,Игрок %o фанатично убит служителем.,%o је ревносно упуцан@[adj_1_sr] од стране секташа.,"%o, bir yardımcısı tarafından gayretle vuruldu." +de la Orakolo!",¡Necesitas el pase del Oráculo!,,Tarvitset Oraakkelin passin,Vous avez besoin du passe Oracle!,Az Orákulum Engedélyére van szükséged!,Hai bisogno del pass dell'Oracolo.,オラクルパスが必要だ!,오라클 통행증이 필요하다!,Je hebt de Orakelpas nodig!,Du trenger Orakelpasset!,Potrzebujesz Przepustki Wyroczni!,Você precisa do Passe do Oráculo!,Precisas do Passe do Oráculo!,Ai nevoie de legitimația Oracol!,Нужен пропуск Оракула!,Треба ти Пророкова пропусница!,Du behöver Orakelpasset!,Kahin Kartı'na ihtiyacın var!,Вам потрібен пропуск Оракула! +,,Actor tags,,,,,,,,,,,,,,,,,,,,,,,,,, +Dagger,TAG_PUNCHDAGGER,,,,Dýka,Dolk,Dolch,Μαχάιρι,Ponardo,Daga,,Tikari,Dague de Poing,Tőr,Pugnale,ダガー,단검,Dolk,Dolk,Sztylet,Punhal,,Pumnal,Кинжал,Бодеж,Dolk,Hançer,Кинжал +Crossbow,TAG_STRIFECROSSBOW1,Crossbow with electric bolts,,,Kuše,Armbrøst,Armbrust,Τόξο (Δηλητήριο),Arbalesto (elektraj sagoj),Ballesta (eléctrica),,Jousipyssy,Arbalète Electrique,Nyílpuska,Balestra ,クロスボウ,석궁 (전격),Kruisboog,Armbrøst,Kusza,Besta,,Arbaletă,Арбалет,Самострел,Armborst,Arbalet,Арбалет +Crossbow,TAG_STRIFECROSSBOW2,Crossbow with poison bolts,,,Kuše,Armbrøst,Armbrust,Τόξο (Ηλεκτρικό),Arbalesto (venenaj sagoj),Ballesta (veneno),,Jousipyssy,Arbalète Empoisonée,Nyílpuska,Balestra ,クロスボウ,석궁 (맹독),Kruisboog,Armbrøst,Kusza,Besta,,Arbaletă,Арбалет,Самострел,Armborst,Arbalet,Арбалет +Assault Gun,TAG_ASSAULTGUN,,,,Útočná puška,Angrebsvåben,Sturmgewehr,,Sturmofusilo,Fusil de asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'Assalto ,アサルトガン,돌격소총,Aanvalswapen,Stormgevær,Karabin Szturmowy,Fuzil de Assalto,Arma de Assalto,Pușcă de Asalt,Штурмовая винтовка,Аутоматска пушка,Anfallspistol,Saldırı Silahı,Штурмова гвинтівка +Mini Missile Launcher,TAG_MMLAUNCHER,,,,Miniraketomet,Mini-missilkaster,Miniraketenwerfer,Μίνι-Πυραυλοβόλο,Misilet-pafilo,Minilanzamisiles,,Miniohjuslaukaisin,Lanceur de Mini-Missiles,Mini Rakétavető,Mini-Lanciamissili,ミニミサイルランチャー,미니 미사일 런쳐,Miniraketwerper,Mini rakettkaster,Wyrzutnia Minipocisków,Mini Lança-mísseis,,Mini Lansator de Proiectile,Мини-гранатомёт,Мини ракетни бацач,Mini missilkastare,Mini Füze Fırlatıcı,Міні-ракетниця +Flame Thrower,TAG_FLAMER,,,,Plamenomet,Flammekaster,Flammenwerfer,,Flamĵetilo,Lanzallamas,,Liekinheitin,Lance-Flammes,Lángszóró,Lanciafiamme ,火炎放射器,화염방사기,Vlammenwerper,Flammekaster,Miotacz Ognia,Lança-chamas,,Aruncător de Flăcări,Огнемёт,Бацеч пламена,Flamkastare,Alev Fırlatıcı,Вогнемет +Mauler,TAG_MAULER1,,,,Trhač,,Vernichter,,Polvigilo (normala),Triturador (dispersión),,Moukari,Broyeur,Marcangoló,Pestatore ,マウラー,마울러 (저출력),Toetakelaar,,Miażdżyciel,Desintegrador,,Sfâșietor,Истязатель,Маулер,,Parçalayıcı,Розсіювач +Mauler,TAG_MAULER2,,,,Trhač,,Vernichter,,Polvigilo (fortega),Triturador (torpedo),,Moukari,Broyeur,Marcangoló,Pestatore,マウラー,마울러 (고출력),Toetakelaar,,Miażdżyciel,Desintegrador,,Sfâșietor,Истязатель,Маулер,,Parçalayıcı,Розсіювач +Grenade Launcher,TAG_GLAUNCHER1,High-explosive grenade launcher,,,Granátomet,Granatkaster,Granatwerfer,,Grenadĵetilo (eksplodeg-pova),Lanzagranadas (conmoción),,Kranaatinheitin,Lance-Grenades Explosif,Gránátvető,Lanciagranate,グレネードランチャー,유탄발사기 (고폭탄),Granaatwerper,Granatkaster,Wyrzutnia Granatów,Lança-granadas,,Lansator de Grenade,Гранатомёт,Бацач граната,Granatkastare,El Bombası Fırlatıcı,Гранатомет +Grenade Launcher,TAG_GLAUNCHER2,White phosphorous grenade launcher ,,,Granátomet,Granatkaster,Granatwerfer,,Grenadĵetilo (fosfora),Lanzagranadas (fósforo),,Kranaatinheitin,Lance-Grenades Incendiaire,Gránátvető,Lanciagranate,グレネードランチャー,유탄발사기 (소이탄),Granaatwerper,Granatkaster,Wyrzutnia Granatów,Lança-granadas,,Lansator de Grenade,Гранатомёт,Бацач граната,Granatkastare,El Bombası Fırlatıcı,Гранатомет +Sigil,TAG_SIGIL,,,,Pečeť,,,,Sigelo,Emblema,,Sinetti,,Pecsét,Sigillo,シジル,시질,,,Pieczęć,Sigilo,,Sigiliu,Печать,Сигил,,,Сигіл +Coin,TAG_COIN,,,,Mince,Mønt,Münze,,Monero,Moneda,,Kolikko,Pièce,Érme,Moneta,コイン,동전,Munt,Mynt,Moneta,Moeda(s),,Monedă,Монета,Новчић,Mynt,Madeni Para,Монета +Med patch,TAG_MEDPATCH,,,,Obvazy,Medicinsk bandage,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekääre,Pansement,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinsk lapp,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинт,Прва помоћ,Medicinska plåster,Med yama,Оклюзійна пов'язка +Medical kit,TAG_MEDICALKIT,,,,Lékárnička,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku,Kit Médical,Orvosi Készlet,Kit di Pronto Soccorso ,医療キット,구급 키트,Medicijndoos,Medisinsk sett,Apteczka,Kit médico,,Kit de Prim-Ajutor,Аптечка,Медицински прибор,Medicinsk utrustning,Tıbbi kit,Індивідуальна аптечка +Surgery Kit,TAG_SURGERYKIT,,,,Chirurgická souprava,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kirurgilaukku,Kit de Chirurgie,Sebészeti Készlet,Kit Chirurgico ,手術キット,수술 키트,Chirurgiepakket,Kirurgisk sett,Zestaw Chirurga,Kit de Cirurgia,,Kit pentru Operații,Медкомплект,Хируршки прибор,Kirurgiskt kit,Ameliyat Kiti,Медичний кейс +Ring,TAG_BELDINSRING,,,,Prsten,,,,Ringo,Anillo,,Sormus,Anneau,Gyűrű,Anello ,指輪,반지,,,Pierścień,Anel,,Inel,Кольцо,Прстен,,Yüzük,Каблучка +Offering Chalice,TAG_OFFERINGCHALICE,,,,Obětní kalich,Offerkalk,Opferkelch,,Oferdona kaliko,Cáliz de ofrenda,,Uhrimalja,Calice d'Obole,Áldozati kehely,Calice delle Offerte,寄贈された聖杯,번제 성배,Offerbeker,Offerbeger,Kielich Ofiarny,Calice de Oferenda,,Potir pentru Ofrande,Чаша для подношений,Жртвени пехар,Offertkalke,Adak Kadehi,Чаша для жертвоприношення +Ear,TAG_EAR,,,,Ucho,Øre,Ohr,,Orelo,Oreja,,Korva,Oreille,Fül,Orecchio,耳,귀,Oor,Øre,Ucho,Orelha,,Ureche,Ухо,Уво,Öra,Kulak,Вухо +Broken Power Coupling,TAG_BROKENCOUPLING,,,,Rozbitá spojka,Brækket strømkobling,Defekter Stromabnehmer,,Rompita energia kuplilo,Acoplador de energía roto,,Rikkinäinen virtaliitin,Coupleur Energétique cassé,Elromlott Tápcsatlakozó,Coppia Energetica Rotta ,壊れたパワーカップリング,망가진 동력선,Gebroken stroomkoppeling,Ødelagt kraftkobling,Zepsute Obwody Zasilające,Acoplador de Energia Quebrado,Acoplador de Energia Partido,Cuplaj de Putere Defect,Повреждённая муфта,Неисправна спојница напајања,Trasig kraftkoppling,Kırık Güç Kaplini,Зламана силова муфта +Shadow Armor,TAG_SHADOWARMOR,,,Shadow Armour,Stínové brnění,Skygge rustning,Schattenrüstung,,Ombra armaĵo,Armadura de sombra,,Varjohaarniska,Armure de l'Ombre,Sötét Páncél,Armatura Ombra ,シャドウアーマー,그림자 갑옷,Schaduwharnas,Skygge rustning,Cienisty Pancerz,Armadura das Sombras,,Armura Umbrei,Теневая броня,Оклоп сенки,Skuggarmering,Gölge Zırhı,Тіньова броня +Environmental Suit,TAG_ENVSUIT,,,,Ochranný oblek,Miljømæssig dragt,Schutzanzug,,Medi-ŝirma vesto,Traje NBQ,,Ympäristösuojapuku,Combinaison Hazmat,Védőöltözet,Tuta Ambientale ,耐環境スーツ,환경 방호복,Beschermend pak,Miljødrakt,Skafander Ochronny,Traje de Proteção,Fato Protetor,Costum de Protecție,Защитный костюм,Заштитно одело,Miljödräkt,Çevresel Takım,Захисний костюм +Guard Uniform,TAG_GUARDUNIFORM,,,,Hlídačova uniforma,Gardeuniform,Wächteruniform,,Gardista uniformo,Uniforme de guardia,,Vartijan univormu,Uniforme de Garde,Őr Egyenruha,Uniforme da Guardia,ガードの制服,경비 전투복,Wachtersuniform,Vaktuniform,Mundur Strażnika,Uniforme de Guarda,,Uniformă de Paznic,Униформа стражника,Стражарска униформа,Skyddsuniform,Bekçi Üniforması,Уніформа охоронця +Officer's Uniform,TAG_OFFICERSUNIFORM,,,,Důstojníkova uniforma,Officersuniform,Offiziersuniform,,Oficira uniformo,Uniforme de oficial,,Upseerin univormu,Uniforme d'Officier,Tiszti Egyenruha,Uniforme da Ufficiale ,士官の制服,장교 전투복,Officiersuniform,Offisersuniform,Mundur Oficera,Uniforme de Oficial,,Uniformă de Ofițer,Офицерская униформа,Официрска униформа,Officersuniform,Memur Üniforması,Уніформа офіцера +Flame Thrower Parts,TAG_FTHROWERPARTS,,,,Díly plamenometu,Dele til flammekasteren,Flammenwerferteile,,Partoj de flamjetilo,Partes de lanzallamas,,Liekinheittimen osat,Pièces de Lance-Flamme,Lángszóró Alkatrészek,Parti di Lanciafiamme ,火炎放射器の部品,화염방사기 부품,Vlammenwerperonderdelen,Deler til flammekaster,Części Miotacza Ognia,Partes do lança-chamas,,Bucăți de Aruncător de Flăcări,Детали огнемёта,Делови бацача пламена,Delar till flamkastaren,Alev Püskürtücü Parçaları,Деталі для вогнемету +Report,TAG_REPORT,,,,Hlášení,Rapport,,,Raporto,Reporte,,Raportti,Compte-rendu,Jelentés,Rapporto ,報告書,보고서,Verslag,Rapport,Raport,Relatório,,Raport,Отчёт,Извештај,Rapportera,Rapor,Звіт +Info,TAG_INFO,,,,Informace,,,,Informoj,Información,,Tiedot,,Információ,Informazioni ,情報,정보,,Informasjon,Informacje,Informação,,Informație,Сводка,Инфо,,Bilgi,Дані +Targeter,TAG_TARGETER,,,,Zaměřovač,,Zielhilfe,,Celilo,Mira de arma,,Tähtäinlaite,Cibleur,Célzó eszköz,Puntatore,照準器,조준기,Richter,,Namierzacz,Mira,,Țintitor,Целеуказатель,Нишанџија,,Hedefleme cihazı,Цілевказівник +Communicator,TAG_COMMUNICATOR,,,,Komunikátor,Kommunikator,Kommunikator,,Interfono,Intercomunicador,,Viestintälaite,Communicateur,Kommunikátor,Comunicatore ,コミュニケーター,연락장치,,Kommunikator,Komunikator,Comunicador,,Comunicator,Передатчик,Комуникатор,Kommunikator,İletişimci,Комунікатор +Degnin Ore,TAG_DEGNINORE,,,,Degninská ruda,Degnin malm,Degnin-Erz,,Degnina minaĵo,Mineral de Degnin,,Degnin-malmi,Minerai de Degnin,Degnin Érc,Minerale Degnin,デグニン鉱石,데그닌 광석,Degnin-erts,Degnin malm,Ruda Degninu,Minério Degnin,,Minereu de Degnir,Денгинская руда,Дегнинска руда,Degnin Malm,Degnin Cevheri,Дегінська руда +Accuracy,TAG_GUNTRAINING,,,,Přesnost,Nøjagtighed,Präzision,,Akurateco,Precisión,,Tarkkuus,Précision,Pontosság,Precisione,精度,정확도,Nauwkeurigheid,Nøyaktighet,Precyzja,Precisão,,Acuratețe,Меткость,Прецизност,Noggrannhet,Doğruluk,Точність +Toughness,TAG_HEALTHTRAINING,,,,Tvrdost,Robusthed,Ausdauer,,Forteco,Dureza,,Sitkeys,Endurance,Kitartás,Robustezza ,タフネス,힘,Stevigheid,Seighet,Wytrzymałość,Força,,Rezistență,Живучесть,Издржљивост,Seghet,Sertlik,Стійкість +Scanner,TAG_SCANNER,,,,Skener,,,,Skanilo,Escáner,,Skanneri,Analyseur,Szkenner,Scanner,スキャナー,탐지기,Scanner,Skanner,Skaner,Scanner,,Scanner,Сканер,Скенер,Scanner,Tarayıcı,Сканер +Prison Pass,TAG_PRISONPASS,,,,Propustka do vězení,Fængselspas,Gefängnispass,,Mallibereja pasilo,Pase a la prisión,,Vankilan pääsylupa,Passe de la Prison,Börtön Engedély,Lasciapassare Prigione ,刑務所の許可証,감옥 통행증,Gevangenispas,Fengselspass,Przepustka do Więzienia,Passe da Prisão,,Legitimația pentru Închisoare,Пропуск в тюрьму,Затворска пропусница,Fängelsepass,Hapishane Kartı,Тюремний пропуск +Alarm,TAG_ALARM,,,,,,,,Alarmo,Alarma,,Hälytys,Alarme,Riasztó,Allarme ,警報,알람,,,,Alarme,,Alarmă,Тревога,Аларм,Larm,,Тривога +Ammo,TAG_AMMOFILLUP,,,,Munice,Munition,Munition,,Municio,Munición,,Ammukset,Munitions,Lőszer,Munizioni ,弾薬,탄약,Munitie,Ammunisjon,Amunicja,Munição,,Muniție,Боеприпасы,Муниција,Ammunition,Cephane,Набої +Health,TAG_HEALTHFILLUP,,,,Zdraví,Sundhed,Gesundheit,,Sano,Salud,,Terveys,Santé,Életerő,Salute ,体力,체력,Gezondheid,Helse,Zdrowie,Saúde,,Sănătate,Здоровье,Живот,Hälsa,Sağlık,Здоров'я +Teleporter Beacon,TAG_TELEPORTERBEACON,,,,Teleportační maják,Teleportør-bakke,Teleportersignal,,Teleportil-signalilo,Baliza de teletransporte,,Kaukosiirrinmajakka,Balise de téléportation,Teleport Vészfény,Radiofaro per Teletrasporto ,テレポータービーコン,텔레포터 비콘,Teleporterbaken,Teleporter Beacon,Nadajnik Teleportera,Sinalizador para Teletransporte,,Lumină pentru Teleportor,Телепортационный маяк,Одашиљач за телепортовање,Teleporterfyr,Işınlayıcı İşaretçisi,Пристрій телепортації +Metal Armor,TAG_METALARMOR,,,Metal Armour,Kovové brnění,Metal rustning,Metallrüstung,,Metala armaĵo,Armadura de metal,,Metallihaarniska,Armure en Métal,Fém Páncél,Armatura di Metallo ,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowy Pancerz,Armadura de Metal,,Armură din Metal,Металлическая броня,Метални оклоп,Metall rustning,Metal Zırh,Металічна броня +Leather Armor,TAG_LEATHER,,,Leather Armour,Kožené brnění,Læderpanser,Lederrüstung,,Leda armaĵo,Armadura de cuero,,Nahkasuojus,Armure en Cuir,Bőr Páncél,Armatura di Cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Lær rustning,Skórzany Pancerz,Armadura de Couro,,Armură din Piele,Кожаная броня,Кожни оклоп,Läderrustning,Deri Zırh,Шкіряна броня +HE-Grenade Rounds,TAG_HEGRENADES,,,,Výbušné granáty,HE-granater,HE-Granaten,,Eksplodeg-povaj grenadoj,Granadas de conmoción,,Räjähdekranaatit,Grenades Explosives,Gránát Lőszer,Granata HE,HEグレネード弾,고폭 유탄,HE-granaten,HE-Granater,Wiązka Granatów,Munição - Granadas Explosivas,,Grenade Explozive,Осколочные гранаты,Хе-Граната чауре,HE-granater,HE-Bomba Mermileri,В'язка гранат +Phosphorus-Grenade Rounds,TAG_PHGRENADES,,,,Fosforové granáty,Fosforgranater,Phosphorgranaten,,Fosforaj grenadoj,Granadas de fósforo,,Fosforikranaatit,Grenades Incendiaires,Foszfor-Gránát Lőszer,Granata al Fosforo ,白リングレネード弾,소이 유탄,Fosforgranaten,Fosforgranater,Wiązka Fosforowych Granatów,Municão - Granadas de Fósforo,,Grenade cu Fosfor,Фосфорные гранаты,Фосфорне гранате,Fosforgranater,Fosforlu El Bombası Mermileri,В'язка фосфорних гранат. +Clip of Bullets,TAG_CLIPOFBULLETS,,,,Zásobník s náboji,Kugleklip,Gewehrmunition,,Magazeno,Cargador de balas,,Luotilipas,Chargeur d'Assaut,Golyó töltények,Caricatore di Proiettili ,弾丸のクリップ,소총 탄창,Patroon kogels,Klipp av kuler,Magazynek,Carregador de Balas,,Cartuș cu Gloanțe,Обойма,Клип метака,Kulor i klipp,Kurşun Klipsi,Набійниця +Ammo,TAG_BOXOFBULLETS,,,,Krabice nábojů,Munition,Munitionskiste,,Munici-kesto,Caja de municiones,,Luotilaatikko,Bôite de Munitions,Lőszer,Munizioni ,弾薬箱,탄약,Munitie,Ammunisjon,Amunicja,Caixa de Balas,,Muniție,Боеприпасы,Муниција,Ammunition,Cephane,Набої +Mini Missiles,TAG_MINIMISSILES,,,,Minirakety,Mini missiler,Miniraketen,,Misiletoj,Minimisiles,,Miniohjukset,Mini-Missiles,Mini Rakéták,Mini-Missili,ミニミサイル,미니 미사일,Mini-raketten,Mini missiler,Mini Pociski,Mísseis,,Mini Proiectile,Мини-ракеты,Мини Ракете,Miniraketer,Mini Füzeler,Міні-ракети +Crate of Missiles,TAG_CRATEOFMISSILES,,,,Bedna raket,kasse med missiler,Raketenkiste,,Misilet-kesto,Caja de minimisiles,,Ohjuslaatikko,Caisse de Mini-Missiles,Ládányi Rakéta,Cassa di Missili,ミサイルの箱,미사일 박스,Krat raketten,Kasse med missiler,Skrzynia z Pociskami,Caixa de Mísseis,,Ladă cu Proiectile,Коробка ракет,Кутија ракета,Låda med missiler,Füze Sandığı,Ящик мініракет +Energy Pod,TAG_ENERGYPOD,,,,Energetický kokón,Energipod,Energiezelle,,Energi-kapsulo,Cápsula de energía,,Energia-akku,Cellule Energétique,Energia Lőszer,Nucleo Enegetico ,エネルギーポット,에너지 포드,Energiecel,Energikapsel,Kapsuła Energii,Energia (pequeno),,Capsulă cu Energie,Энергоячейка,Енергетска шипка,Energipod,Enerji Bölmesi,Енерго-капсула +Energy Pack,TAG_ENERGYPACK,,,,Energetický svazek,Energipakke,Energiepack,,Pako de energio,Paquete de energía,,Energiapaketti,Pack Energétique,Energia Csomag,Carica Energetica ,エネルギーパック,에너지 팩,Energiepak,Energipakke,Zasobnik Energii,Energia (grande),,Pachet cu Energie,Энергобатарея,Паковање енергије,Energipaket,Enerji Paketi,Енерго-батарея +Poison Bolts,TAG_POISONBOLTS,,,,Otrávené šípy,Giftige bolte,Giftbolzen,,Venenaj sagoj,Flechas venenosas,,Myrkkynuolet,Carreaux Empoisonnés,Mérgező hegyek,Dardi Velenosi ,ポイズンボルト,맹독 볼트,Giftige bouten,Giftbolter,Zatrute Bełty,Setas Envenenadas,,Bolțuri cu Otravă,Отравленные болты,Отровне стреле,Giftiga bultar,Zehirli Cıvatalar,Отруйні болти +Electric Bolts,TAG_ELECTRICBOLTS,,,,Elektrické šípy,Elektriske bolte,Elektrische Bolzen,,Elektraj sagoj,Flechas eléctricas,,Sähkönuolet,Carreaux Electriques,Elektromos hegyek,Dardi Elettrici ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektriske bolter,Elektryczne Bełty,Setas Elétricas,,Bolțuri cu Electricitate,Электрические болты,Електричне стреле,Elektriska bultar,Elektrikli Cıvatalar,Електричні болти +Ammo Satchel,TAG_AMMOSATCHEL,,,,Brašna na munici,Ammo Satchel,Munitionstasche,,Sako da municioj,Bolso de municiones,,Ammuslaukku,Sacoche à munitions,Lőszeres táska,Borsa di Munizioni ,弾薬鞄,탄약 배낭,Munitietassen,Ammunisjonsveske,Torba z Amunicją,Bolsa de Munição,,Sacoșă cu Muniție,Ранец боеприпасов,Торбица муниције,Ammo Satchel,Cephane Çantası,Сумка для набоїв +Base Key,TAG_BASEKEY,,,,Klíč od základny,Basisnøgle,Basisschlüssel,,Bazoŝlosilo,Llave de la base,,Tukikohdan avain,Clé de la base,Bázis Kulcs,Chiave della Base,,기지 키,Basissleutel,Basenøkkel,Klucz do Bazy,Chave da Base,,Cheia Bazei,Ключ от базы,Кључ базе,Basnyckel,Temel Anahtar,Ключ від бази +Govs Key,TAG_GOVSKEY,,,,Klíč ke guvernérovi,Govs nøgle,Gouverneursschlüssel,,Ŝlosilo de registo,Llave Gobernador,,Kuvernöörin avain,Clé du Gouverneur,Kormányzó Kulcs,Chiave del Governatore ,,총독의 키,Gouverneursleutel,Regjeringsnøkkel,Klucz Gubernatora,Chave do Governador,,Cheia Guvernatorului,Ключ губернатора,Гувернеров кључ,Govs-nyckel,Govs Anahtar,Ключ губернатора +Passcard,TAG_PASSCARD,,,,Vstupní karta,Adgangskort,Zugangskarte,,Central-ŝlosilo,Llave de la central,,Avainkortti,Passe,Belépőkártya,Tessera Lasciapassare ,,통행 카드,Paspoortkaart,Adgangskort,Karta Dostępu,Cartão de Acesso,,Legitimație,Пропуск,Пропусница,Passerkort,Geçiş kartı,Карта доступу +ID Badge,TAG_IDBADGE,,,,Identifikační odznak,ID-badge,Identitätskarte,,Mallibereja insigno,Insignia de prisión,,Henkilötunniste,Badge d'Identification,Azonosító Jelvény,Distintivo ,,신분 휘장,ID-Badge,ID-badge,Odznaka Identyfikacyjna,Crachá de Identificação,,Ecuson de Identificare,Личная карта,Идентификациона значка,ID-bricka,Kimlik Rozeti,Бейджик +Prison Key,TAG_PRISONKEY,,,,Klíč od věznice,Fængselsnøgle,Gefängnisschlüssel,,Mallibereja ŝlosilo,Llave de la prisión,,Vankilan avain,Clé de la Prison,Börtön Kulcs,Chiave della Prigione ,,감옥 키,Gevangenissleutel,Fengselsnøkkel,Klucz do Więzienia,Chave da Prisão,,Cheia Închisorii,Ключ от тюрьмы,Кључ од 3атвора,Fängelsenyckel,Hapishane Anahtarı,Ключ від тюрми +Severed Hand,TAG_SEVEREDHAND,,,,Useknutá ruka,Afskåret hånd,Abgetrennte Hand,,Amputita mano,Mano amputada,,Katkennut käsi,Main coupée,Levágott Kéz,Mano Mozzata,,잘린 손목,Gescheurde Hand,Avkuttet hånd,Odcięta Ręka,Mão Decepada,Mão Desmenbrada,Mână Retezată,Отрезанная рука,Одвојена шака,Avskuren hand,Kesik El,Відрізана рука +Power1 Key,TAG_POWER1KEY,,,,Klíč od elektrárny 1,Power1 nøgle,Kraftwerksschlüssel 1,,Central-identigo 1,Ident. central nv. 1,,Voimalan 1-avain,Clé Power1,1. erő kulcs,Chiave della Centrale 1,,발전소 1호 키,1e Machtsleutel,Power1-nøkkel,Klucz do Elektrowni 1,Chave da Usina 1,Chave Energética 1,Cheia Putere1,Ключ ЭС №1,Кључ од ел. 1,Kraftnyckel 1,Güç1 Anahtarı,Ключ від електростанції 1 +Power2 Key,TAG_POWER2KEY,,,,Klíč od elektrárny 2,Power2-nøgle,Kraftwerksschlüssel 2,,Central-identigo 2,Ident. central nv. 2,,Voimalan 2-avain,Clé Power2,2. erő kulcs,Chiave della Centrale 2,,발전소 2호 키,2e Machtsleutel,Power2-nøkkel,Klucz do Elektrowni 2,Chave da Usina 2,Chave Energética 2,Cheia Putere2,Ключ ЭС №2,Кључ од ел. 2,Kraftnyckel 2,Güç2 Anahtarı,Ключ від електростанції 2 +Power3 Key,TAG_POWER3KEY,,,,Klíč od elektrárny 3,Power3-nøgle,Kraftwerksschlüssel 3,,Central-identigo 3,Ident. central nv. 3,,Voimalan 3-avain,Clé Power3,3. erő kulcs,Chiave della Centrale 3,,발전소 3호 키,3e Machtsleutel,Power3-nøkkel,Klucz do Elektrowni 3,Chave da Usina 3,Chave Energética 3,Cheia Putere3,Ключ ЭС №3,Кључ од ел. 3,Kraftnyckel 3,Güç3 Anahtarı,Ключ від електростанції 3 +Gold Key,TAG_GOLDKEY,,,,Zlatý klíč,Guldnøgle,Goldschlüssel,,Ora ŝlosilo,Llave dorada,,Kulta-avain,Clé en Or,Aranykulcs,Chiave Dorata,,황금 키,Gouden sleutel,Gullnøkkel,Złoty Klucz,Chave de Ouro,,Cheia din Aur,Золотой ключ,Златни кључ,Guldnyckel,Altın Anahtar,Золотий ключ +ID Card,TAG_IDCARD,,,,Identifikační karta,ID-kort,Ausweis,,Kloaka identigilo,Identif. cloacas,,Henkilökortti,Carte d'Identité,Azonosító Kártya,Tessera Identificativa,,신분증,ID-Kaart,ID-kort,Karta Identyfikacyjna,Cartão de Identificação,,Card de Identitate,Удостоверение,Лична карта,ID-kort,Kimlik Kartı,Ідентифікаційна карта +Silver Key,TAG_SILVERKEY,,,,Stříbrný klíč,Sølvnøgle,Silberschlüssel,,Arĝenta ŝlosilo,Llave plateada,,Hopea-avain,Clé en Argent,Ezüst Kulcs,Chiave Argentata,,은 키,Zilveren sleutel,Sølv-nøkkel,Srebrny Klucz,Chave de Prata,,Cheia din Argint,Серебряный ключ,Сребрни кључ,Silvernyckel,Gümüş Anahtar,Срібний ключ +Oracle Key,TAG_ORACLEKEY,,,,Věštcův klíč,Orakel-nøgle,Orakelschlüssel,,Orakolo-ŝlosilo,Llave del Oráculo,,Oraakkelin avain,Clé de l'Oracle,Orákulum kulcs,Chiave dell'Oracolo ,,오라클 키,Orakelsleutel,Oracle-nøkkel,Klucz do Wyroczni,Chave do Oráculo,,Cheia Oracol,Ключ Оракула,Пророков кључ,Oracle-nyckel,Kahin Anahtarı,Ключ Оракула +Military ID,TAG_MILITARYID,,,,Vojenské ID,Militær ID,Militärausweis,,Milita identigilo,Identif. militar,,Sotilastunnus,Identification Militaire,Katonai Azonosító Kártya,Identificativo Militare,,군용 아이디,Militaire ID,Militær ID,Wojskowy Identyfikator,ID Militar,,Legitimație Militară,Удостовер. военного,Војна идентификација,Militärt ID,Askeri Kimlik,Військова ID карта +Order Key,TAG_ORDERKEY,,,,Klíč Řádu,Bestillingsnøgle,Ordensschlüssel,,Ordena ŝlosilo,Llave de La Orden,,Veljeskunnan avain,Clé de l'Ordre,Rend Kulcs,Chiave dell'Ordine,,오더의 키,Ordesleutel,Bestillingsnøkkel,Klucz Zakonu,Chave da Ordem,,Cheia Ordinului,Ключ Ордена,Кључ одреда,Beställningsnyckel,Sipariş Anahtarı,Ключ Ордену +Warehouse Key,TAG_WAREHOUSEKEY,,,,Klíč ke skladu,Lagernøgle,Lagerhausschlüssel,,Magazena ŝlosilo,Llave del almacén,,Varaston avain,Clé de l'Entrepôt,Raktár Kulcs,Chiave del Magazzino ,,창고 키,Magazijnsleutel,Lagernøkkel,Klucz do Magazynu,Chave do Armazém,,Cheia Depozitului,Ключ от склада,Кључ складишта,Lagernyckel,Depo Anahtarı,Ключ від складу +Brass Key,TAG_BRASSKEY,,,,Mosazný klíč,Messingnøgle,Messingschlüssel,,Latuna ŝlosilo,Llave de latón,,Messinkiavain,Clé en Bronze,Réz Kulcs,Chiave d'Ottone ,,황동 키,Messing sleutel,Messingnøkkel,Mosiężny Klucz,Chave de Latão,,Cheia din Alamă,Латунный ключ,Кључ од месинга,Mässingsnyckel,Pirinç Anahtar,Латунний ключ +Red Crystal Key,TAG_REDCRYSTALKEY,,,,Červený krystalový klíč,Rød krystalnøgle,Roter Kristallschlüssel,,Ruĝkristala ŝlosilo,Llave cristal rojo,,Punainen kristalliavain,Clé de Cristal Rouge,Piros Kristály Kulcs,Chiave di Cristallo Rosso ,,적색 크리스탈 키,Rode kristallen sleutel,Rød krystallnøkkel,Czerwony Kryształowy Klucz,Chave de Cristal Vermelho,,Cheia din Cristal Roșu,Крас. ключ-кристалл,Кључ од црвеног кристала,Nyckel i röd kristall,Kırmızı Kristal Anahtar,Червоний кристальний ключ +Blue Crystal Key,TAG_BLUECRYSTALKEY,,,,Modrý krystalový klíč,Blå krystalnøgle,Blauer Kristallschlüssel,,Blukristala ŝlosilo,Llave cristal azul,,Sininen kristalliavain,Clé de Crisal Bleu,Kék Kristály Kulcs,Chiave di Cristallo Blu,,청색 크리스탈 키,Blauwe kristallen sleutel,Blå krystallnøkkel,Niebieski Kryształowy Klucz,Chave de Cristal Azul,,Cheia din Cristal Albastru,Син. ключ-кристалл,Кључ од плавог кристала,Blå kristallnyckel,Mavi Kristal Anahtar,Синій кристальний ключ +Chapel Key,TAG_CHAPELKEY,,,,Klíč od kaple,Kapel nøgle,Kapellenschlüssel,,Kapelo-ŝlosilo,Llave de la Capilla,,Kappelin avain,Clé de la Chapelle,Kápolna Kulcs,Chiave della Cappella ,,예배당 키,Kappelsleutel,Kapell-nøkkel,Klucz do Kaplicy,Chave da Capela,,Cheia Capelei,Ключ от часовни,Кључ капеле,Kapellnyckel,Şapel Anahtarı,Ключ від каплиці +Catacomb Key,TAG_CATACOMBKEY,,,,Klíč do katakomb,Katakomb Nøgle,Katakombenschlüssel,,Katakomb-ŝlosilo,Llave Catacumbas,,Katakombin avain,Clé des Catacombes,Katakomba Kulcs,Chiave delle Catacombe ,,고대 묘지 키,Catacombesleutel,Katakomb-nøkkel,Klucz do Katakumb,Chave da Catacumba,,Cheia Catacombei,Ключ от катакомб,Кључ од катакомби,Katakomb-nyckel,Katakomb Anahtarı,Ключ від катакомб +Security Key,TAG_SECURITYKEY,,,,Klíč ochranky,Sikkerhedsnøgle,Sicherheitsschlüssel,,Sekureco-ŝlosilo,Llave de Seguridad,,Turvamiesavain,Clé de la Sécurité,Biztonsági Kulcs,Chiave della Sicurezza ,,보안 키,Beveiligingssleutel,Sikkerhetsnøkkel,Klucz Ochrony,Chave de Segurança,,Cheia Securității,Ключ охраны,Сигурносни кључ,Säkerhetsnyckel,Güvenlik Anahtarı,Ключ охорони +Core Key,TAG_COREKEY,,,,Klíč k jádru,Reaktor Nøgle,Reaktorschlüssel,,Kernoŝlosilo,Llave del Núcleo,,Ytimen avain,Clé du Réacteur,Mag Kulcs,Chiave del Nucleo,,중심부 키,Kernsleutel,Kjernenøkkel,Klucz do Rdzenia,Chave do Núcleo,,Cheia Nucleului,Ключ от реактора,Кључ језгра,Kärnnyckel,Çekirdek Anahtar,Ключ від реактора +Mauler Key,TAG_MAULERKEY,,,,Klíč k trhačům,Mauler-nøgle,Vernichterschlüssel,,Polvigilo-ŝlosilo,Llave Triturador,,Moukarin avain,Clé du Broyeur,Marcangoló Kulcs,Chiave del Pestatore ,,마울러 키,Toetakelaarssleutel,Mauler-nøkkel,Klucz do Magazynu Miażdżycieli,Chave - Mauler,,Cheia Sfâșietorului,Ключ истязателя,Маулер кључ,Mauler-nyckel,Mauler Anahtar,Ключ розсіювача +Factory Key,TAG_FACTORYKEY,,,,Klíč do továrny,Fabriksnøgle,Fabrikschlüssel,,Fabriko-ŝlosilo,Llave de la Fábrica,,Tehtaan avain,Clé de l'Usine,Gyár Kulcs,Chiave della Fabbrica ,,공장 키,Fabriekssleutel,Fabrikknøkkel,Klucz do Fabryki,Chave da Fábrica,,Cheia Fabricii,Ключ от фабрики,Кључ фабрике,Fabriksnyckel,Fabrika Anahtarı,Ключ від фабрики +Mine Key,TAG_MINEKEY,,,,Klíč od dolů,Mine-nøgle,Minenschlüssel,,Minejo-ŝlosilo,Llave de la Mina,,Kaivoksen avain,Clé de la Mine,Bánya Kulcs,Chiave della Miniera ,,탄광 키,Mijnsleutel,Gruve-nøkkel,Klucz do Kopalni,Chave da Mina,,Cheia Minei,Ключ от шахт,Кључ рудника,Gruvnyckel,Maden Anahtarı,Ключ від шахт +New Key5,TAG_NEWKEY5,,,,Nový klíč 5,Ny nøgle5,Neuer Schlüssel 5,,Nova ŝlosilo kvin,Llave nueva cinco,,Uusi 5-avain,Clé nouveau 5,5. kulcs,Nuova Chiave 5,,새로운 키5,Nieuwe sleutel 5,Ny nøkkel5,Nowy Klucz5,Chave Nova 5,,Noua Cheie5,Новый ключ №5,Нови кључ5,Ny nyckel5,Yeni Anahtar5,Новий ключ 5 +Oracle Pass,TAG_ORACLEPASS,,,,Věštcova propustka,Orakelpas,Orakelpass,,Orakolo-pasilo,Pase del Oráculo,,Oraakkelin kulkulupa,Passe de l'Oracle,Orákulum útlevél,Lasciapassare dell'Oracolo ,,오라클의 통행증,Orakelpas,Oracle Pass,Przepustka Wyroczni,Passe do Oráculo,,Legitimația Oracol,Пропуск Оракула,Пророкова пропусница,Orakelpass,Kahin Kartı,Пропуск Оракула +10 gold,TAG_10GOLD,,,,10 zlatých,10 guld,,,10 da oro,10 de oro,,10 kolikkoa,10 Pièces,10 arany,10 pezzi d'oro ,10ゴールド,10 골드,10 goud,10 gull,10 monet,10 moedas,10 moedas de ouro,10 monezi de aur,10 золотых,10 златника,10 guld,10 altın,10 золотих +25 gold,TAG_25GOLD,,,,25 zlatých,25 guld,,,25 da oro,25 de oro,,25 kolikkoa,25 Pièces,25 arany,25 pezzi d'oro ,25ゴールド,25 골드,25 goud,25 gull,25 monet,25 moedas,25 moedas de ouro,25 de monezi de aur,25 золотых,25 златника,25 guld,25 altın,25 золотих +50 gold,TAG_50GOLD,,,,50 zlatých,50 guld,,,50 da oro,50 de oro,,50 kolikkoa,50 Pièces,50 arany,50 pezzi d'oro ,50ゴールド,50 골드,50 goud,50 gull,50 monet,50 moedas,50 moedas de ouro,50 de monezi de aur,50 золотых,50 златника,50 guld,50 altın,50 золотих +300 gold,TAG_300GOLD,,,,300 zlatých,300 guld,,,300 da oro,300 de oro,,300 kolikkoa,300 Pièces,300 arany,300 pezzi d'oro ,300ゴールド,300 골드,300 goud,300 gull,300 monet,300 moedas,300 moedas de ouro,300 de monezi de aur,300 золотых,300 златника,300 guld,300 altın,300 золотих +Person,TXT_PERSON,,,,Osoba,,,,Persono,Persona,,Henkilö,Personne,Személy,Persona,一員,민간인,Persoon,,Osoba,Pessoa,,Persoană,Горожанин,Особа,Person,Kişi,Цивільний +Acolyte,TAG_ACOLYTE,,,,Akolyta,Akolyt,Ministrant,,Akolito,Acólito,,Akoluutti,,Ministráns,Accolito ,アコライト,아콜라이트,Acoliet,Akolytt,Akolita,Acólito,,Acolit,Служитель,Следбеник,Akolyt,Yardımcı,Адепт +Armorer,TAG_ARMORER,,,Armourer,Kovář,Våbendør,Rüster,,Armilisto,Armero,,Asemestari,Armurier,Páncélkovács,Armaiolo ,装甲,병기공,Harnassmid,Våpensmed,Płatnerz,Armeiro,,Armurier,Продавец брони,Ковач,Rusthållare,Zırhçı,Коваль +Bar Keep,TAG_BARKEEP,,,,Výčepní,Bar-værn,Wirt,,Drinkejestro,Cantinero,,Baarimikko,Barman,Csapos,Barista,酒屋,바텐더,Barman,Bartender,Barman,Dono do Bar,,Barman,Хозяин таверны,Конобар,Bartender,Barmen,Бармен +Beggar,TAG_BEGGAR,,,,Žebrák,Tigger,Bettler,,Almozulo,Mendigo,,Kerjäläinen,Mendiant,Koldus,Mendicante ,乞食,거지,Bedelaar,Tigger,Żebrak,Mendigo,,Sărman,Нищий,Просјак,Tiggare,Dilenci,Жебрак +Macil,TAG_MACIL1,,,,,,,,,,,,,,,マシル,마실,,,,,,,Мэйсил,Мејсил,,Macil,Масіл +Macil,TAG_MACIL2,,,,,,,,,,,,,,,マシル,마실,,,,,,,Мэйсил,Мејсил,,Macil,Масіл +Medic,TAG_MEDIC,,,,Medik,Læge,Sanitäter,,Kuracisto,Médico,,Lääkintämies,Médecin,Szanitéc,Medico,メディック,의무관,Paramedicus,,Medyk,Médico,,,Врач,Болничар,Sjukvårdare,,Лікар +Oracle,TAG_ORACLE,,,,Věštec,Orakel,Orakel,,Orakolo,Oráculo,,Oraakkeli,,Orákulum,Oracolo,オラクル,오라클,Orakel,Orakel,Wyrocznia,Oráculo,,Oracol,Оракул,Пророк,Orakel,Kahin,Оракул +Priest,TAG_PRIEST,,,,Kněz,Præst,Priester,,Pastro,Sacerdote,,Pappi,Prêtre,Pap,Sacerdote,プリースト,성직자,Priester,Prest,Kapłan,Sacerdote,,Preot,Жрец,Свештеник,Präst,Rahip,Священник +Rat Buddy,TAG_RATBUDDY,,,,Krysík,Rottekammerat,Ratte,,Rato,Rata,,Rottakamu,Copain Rat,Patkánypajtás,Ratto,ラット バディ,생쥐 친구,Rattenvriendje,Rottekompis,Koleżka Szczurów,Rato,,Amicul Șobolanilor,Крыса-друг,Друг пацов,Råttkompis,Sıçan Dostu,Друзяка щур +Rebel,TAG_REBEL,,,,,,Rebell,,Ribelanto,Rebelde,,Kapinallinen,Rebelle,Lázadó,Ribelle ,反乱軍,저항군,,Rebell,Rebeliant,Rebelde,,,Повстанец,Побуњеник,Rebell,Asi,Повстанець +Templar,TAG_TEMPLAR,,,,Templář,Tempelridder,Templer,,Templano,Templario,,Temppeliherra,Templier,Templomos,Templare ,騎士団員,템플러,Tempelier,Tempelridder,Templariusz,Templário,,Templier,Храмовник,Темплар,Tempelriddare,Tapınakçı,Тамплієр +Weapon Smith,TAG_WEAPONSMITH,,,,Zbraňmistr,Våbensmed,Waffenschmied,,Armilforĝisto,Forjador de armas,,Aseseppä,Forgeron,Fegyverkovács,Fabbro ,武器工,무기 제조상,Wapensmid,Våpensmed,Wytwórca Broni,Ferreiro,,Făurar,Оружейник,Ковач оружја,Vapensmed,Silah Ustası,Зброяр +Red Talisman,TAG_TALISMANRED,,,,Červený talisman,Rød Talisman,Roter Talisman,,Ruĝa Talismano,Talismán rojo,,Punainen talismaani,Talisman Rouge,Vörös Talizmán,Talismano rosso,赤の魔除け,붉은 부적,Rode Talisman,Rød talisman,Czerwony Talizman,Talismã Vermelho,,Talisman Roșu,Красный талисман,Црвени талисман,Röd talisman,Kızıl Tılsım,Червоний талісман +Green Talisman,TAG_TALISMANGREEN,,,,Zelený talisman,Grøn Talisman,Grüner Talisman,,Verda Talismano,Talismán verde,,Vihreä talismaani,Talisman Vert,Zöld Talizmán,Talismano verde,緑の魔除け,녹색 부적,Groene Talisman,Grønn talisman,Zielony Talizman,Talismã Verde,,Talisman Verde,Зелёный талисман,Зелени талисман,Grön Talisman,Yeşil Tılsım,Зелений талісман +Blue Talisman,TAG_TALISMANBLUE,,,,Modrý talisman,Blå Talisman,Blauer Talisman,,Blua Talismano,Talismán azul,,Sininen talismaani,Talisman Bleu,Kék Talizmán,Talismano blu,青の魔除け,푸른 부적,Blauwe Talisman,Blå talisman,Niebieski Talizman,Talismã Azul,,Talisman Albastru,Синий талисман,Плави талисман,Blå Talisman,Mavi Tılsım,Синій талісман +,,Obituaries,,,,,,,,,,,,,,,,,,,,,,,,,, +%o was zealously shot down by an Acolyte.,OB_ACOLYTE,,,,%o byl@[ao_cs] horlivě zastřelen@[ao_cs] akolytou.,%o blev skudt ned af en akolyt.,%o wurde eifrig von dem Ministranten erschossen.,,%o fervore pafiĝis de Akolito.,A %o l@[ao_esp] ha derribado con fervor un Acólito.,A %o l@[ao_esp] derribó con entusiasmo un Acólito.,%o joutui kiivailevan akoluutin ampumaksi.,%o a souffert d'une bavure policière.,%o-t buzgó módon le lett lőve egy Oltárszolga által.,%o è stato zelantemente abbattuto da un accolito. ,%o は熱心なアコライトに堕とされた。,%o 은(는) 아콜라이트에게 맹신적으로 사격 당했다.,%o werd gretig neergeschoten door een Acoliet.,%o ble nidkjært skutt ned av en akolytt.,%o został@[ao_pl] żarliwie zastrzelon@[adj_pl] przez Akolitę.,%o foi zelosamente abatid@[ao_ptb] por um Acólito.,,%o a fost împușcat zelos de un Acolit.,Игрок %o фанатично убит служителем.,%o је ревносно упуцан@[adj_1_sr] од стране секташа.,%o blev nitiskt nedskjuten av en akolyt.,"%o, bir yardımcısı tarafından gayretle vuruldu.",Адепт пристрелив %o. %o should have never rebelled against Macil.,OB_MACIL,,,,%o se nikdy neměl@[ao_cs] vzbouřit vůči Macilovi.,%o skulle aldrig have gjort oprør mod Macil.,%o hätte nicht gegen Macil rebellieren sollen.,,%o ne estus devinta ribeli kontraŭ Macil.,%o no debería haberse rebelado contra Macil.,%o hizo mal en rebelarse contra Macil.,%o paran ei olisi ikinä pitänyt kapinoida Macilia vastaan.,%o n'aurait jamais du se rebeller contre Macil.,%o Macil ellen próbált fellázadni.,%o non avrebbe mai dovuto opporsi a Macil. ,%o はマシルに歯向かうべきではなかった。,%o 은(는) 마실의 적이 되지 말았어야 했다.,%o had nooit in opstand mogen komen tegen Macil.,%o skulle aldri ha gjort opprør mot Macil.,%o nie powin@[irreg_5_pl] buntować się przeciwko Macilowi.,%o nunca deveria ter se rebelado contra Macil.,%o nunca deveria ter se rebeliado contra Macil.,"%o nu ar fi trebuit să se răscoale împotriva lui -Macil.",Игроку %o не следовало восставать против Мэйсила.,%o никад није треба@[ao_1_sr] да се супротстави Мејсилу.,"%o, Macil'e karşı asla isyan etmemeliydi." -%o was gunned down by a Rebel.,OB_REBEL,,,,%o byl@[ao_cs] odstřelen@[ao_cs] rebelem.,%o blev skudt ned af en oprører.,%o wurde von einem Rebellen erschossen.,,%o pafegiĝis de ribelanto.,%o ha sido fusilad@[ao_esp] por un Rebelde.,%o fue fusilad@[ao_esp] por un Rebelde.,%o joutui kapinallisen alas ampumaksi.,%o a été abattu@[e_fr] par un rebelle.,%o le lett lőve egy Lázadó által.,%o è stato colpito a morte da un Ribelle. ,%o は反乱軍に撃ち殺された。,%o 은(는) 저항군에 의해 제압당했다.,%o werd neergeschoten door een Rebel.,%o ble skutt ned av en opprører.,%o został@[ao_pl] rozstrzelan@[adj_pl] przez Rebelianta.,%o foi abatid@[ao_ptb] por um Rebelde.,,%o a fost pus la pământ de un Rebel.,Игрока %o расстрелял повстанец.,%o је упуцан@[adj_1_sr] од стране побуњеника.,%o bir asi tarafından vuruldu. -%o was beaten to death by the poor.,OB_BEGGAR,,,,%o byl@[ao_cs] umlácen@[ao_cs] chudinou.,%o blev slået ihjel af de fattige.,%o fiel der Armut zum Opfer.,,%o morte bategiĝis de la malriĉuloj.,%o ha sido abatid@[ao_esp] hasta morir por los pobres.,%o recibió una paliza letal de los pobres.,%o joutui köyhälistön kuoliaaksi hakkaamaksi.,%o a été battu@[e_fr] a mort par un pauvre.,%o halálra lett verve a szegénység által.,%o è stato calpestato dalla povertà. ,%o は貧民に殴り殺された。,%o 은(는) 자업자득으로 거지에게 맞아 죽었다.,%o werd door de armen doodgeslagen.,%o ble slått i hjel av de fattige.,%o został@[ao_pl] zatłuczon@[adj_pl] na śmierć przez żebraka.,%o foi espancad@[ao_ptb] até a morte pelos pobres.,,%o a fost omorât în bătaie de sărmani.,Игрока %o забили до смерти нищие.,%o је претучен@[adj_1_sr] од стране просјака.,%o fakirler tarafından ölene kadar dövüldü. -%o should have never picked a fight with a civilian.,OB_PEASANT,,,,%o si neměl@[ao_cs] začínat s civilistou.,%o skulle aldrig have taget et slagsmål med en civilist.,%o hätte sich nicht mit einem Zivilisten anlegen sollen.,,%o ne estus devinta komenci batalon al civilulo.,%o no debería haber empezado una pelea con un civil.,%o hizo mal en iniciar una pelea con un civil.,%o hölmön ei olisi ikinä pitänyt haastaa riitaa siviilin kanssa.,%o n'aurait jamais du chercher des noises a un civil.,%o ujjat húzott egy civillel.,%o non avrebbe mai dovuto prendersela con un civile. ,%o は庶民に戦いを挑むべきではなかった。,%o 은(는) 민간인과 싸울 힘도 전혀 없었다.,%o had nooit een gevecht met een burger moeten aangaan.,%o skulle aldri ha kranglet med en sivilist.,%o nigdy nie powin@[irreg_5_pl] wdawać się w bójkę z cywilem.,%o nunca deveria ter arrumado briga com um civil.,%o nunca deveria ter pegado à briga com um civil.,%o n-ar fi trebuit să se încaiere cu un civil.,Игроку %o не следовало начинать драку с горожанином.,%o никад није треба@[ao_1_sr] да се потуче са цивилом.,%o asla bir sivil ile kavga etmemeliydi. -%o was struck down by the Spectre.,OB_ALIENSPECTRE,,,,%o byl@[ao_cs] zničen@[ao_cs] přízrakem.,%o blev slået ned af spøgelset.,%o wurde von dem Schemen niedergestreckt.,,%o subite mortiĝis de la Fantomo.,%o ha sido fulminad@[ao_esp] por el Espectro.,%o fue fulminad@[ao_esp] por el Espectro.,%o joutui haamun kaatamaksi.,%o a été terrassé@[e_fr] par le Spectre.,%o ki lett ütve a lidérc által.,%o è stato abbattuto dallo Spettro. ,%o はスペクトルに討ち滅ぼされた。,%o 은(는) 스펙터에 의해 무너져 내렸다.,%o werd door de Specter neergeslagen.,%o ble slått ned av Spekter.,%o został@[ao_pl] powalon@[adj_pl] przez Widmo.,%o foi abatid@[ao_ptb] por um Espectro.,,%o a fost răpus de Spectru.,Игрока %o уничтожил призрак.,%o је обори@[ao_1_sr] са ногу утвара.,%o Hortlak tarafından vuruldu. -%o felt the wrath of The One God.,OB_ENTITY,,,,%o pocítil@[ao_cs] vztek Jediného Boha,%o følte den ene Guds vrede.,%o spürte den Zorn des Einen Gottes.,,%o sentis la koleregon de La Ununura Dio.,%o acaba de sentir la ira del Dios Único.,%o sintió la ira del Dios Único.,%o sai tuta Yhden Ainoan Jumalan vihan.,%o a senti le courroux du Seul Dieu.,%o megérezte az Egyetlen Isten haragját.,%o ha assistito all'ira dell'Unico Dio. ,%o は唯一神の怒りに触れた。,%o 은(는) 유일신의 이름으로 천벌을 받았다.,%o voelde de toorn van de Ene God.,%o følte vreden til Den ene Gud.,%o poczuł@[ao_pl] gniew Jedynego Boga.,%o sentiu a ira do Deus Único.,,%o a simțit furia Zeului.,Игрок %o столкнулся с гневом Единого Бога.,Играча %o је осетио бес Јединог бога.,%o Tek Tanrı'nın gazabını hissetti. -%o couldn't escape from the Lore Master's grasp.,OB_LOREMASTER,,,,%o nemohl@[ao_cs] utéct Dějepiscově sevření.,%o kunne ikke undslippe Loremesterens greb.,%o konnte dem Griff des Wissensmeisters nicht entkommen.,,%o ne povis eskapi el la kapto de la Ĉef-folklorulo.,%o no ha conseguido huir de las garras del Maestro del Conocimiento.,%o no pudo huir de las garras del Maestro del Conocimiento.,%o ei kyennyt pakenemaan Oppi-Isän otteesta.,%o n'a pu échapper a l'emprise du Maître des Traditions.,%o nem tudott elmenekülni a Tan Mester elől.,%o non è riuscito a sfuggire alla stretta del Sapiente.,%o はロアマスターの手から逃れられなかった。,%o 은(는) 로어마스터의 촉수를 벗어나지 못했다.,%o kon niet ontsnappen aan de greep van de kennismeester.,%o kunne ikke unnslippe Loremesterens grep.,%o nie m@[irreg_4_pl] uniknąć chwytu Mędrca.,%o não conseguiu escapar do alcance do Mestre do Conhecimento.,,"%o n-a putut scăpa din mâinile Maestrului -Cunoștințelor.",Игрок %o не смог избежать длани Хранителя мудрости.,%o није успе@[ao_1_sr] побећи из Чувареве мудрости домашаја.,"%o, İrfan Ustası'nın elinden kaçamadı." +Macil.",Игроку %o не следовало восставать против Мэйсила.,%o никад није треба@[ao_1_sr] да се супротстави Мејсилу.,%o borde aldrig ha gjort uppror mot Macil.,"%o, Macil'e karşı asla isyan etmemeliydi.",%o ніколи не ма@[adj_1_ua] бунтувати проти Масіла. +%o was gunned down by a Rebel.,OB_REBEL,,,,%o byl@[ao_cs] odstřelen@[ao_cs] rebelem.,%o blev skudt ned af en oprører.,%o wurde von einem Rebellen erschossen.,,%o pafegiĝis de ribelanto.,A %o l@[ao_esp] ha fusilado un Rebelde.,A %o l@[ao_esp] fusiló un Rebelde.,%o joutui kapinallisen alas ampumaksi.,%o a été abattu@[e_fr] par un rebelle.,%o le lett lőve egy Lázadó által.,%o è stato colpito a morte da un Ribelle. ,%o は反乱軍に撃ち殺された。,%o 은(는) 저항군에 의해 제압당했다.,%o werd neergeschoten door een Rebel.,%o ble skutt ned av en opprører.,%o został@[ao_pl] rozstrzelan@[adj_pl] przez Rebelianta.,%o foi abatid@[ao_ptb] por um Rebelde.,,%o a fost pus la pământ de un Rebel.,Игрока %o расстрелял повстанец.,%o је упуцан@[adj_1_sr] од стране побуњеника.,%o blev skjuten av en rebell.,%o bir asi tarafından vuruldu.,%o було розстріляно повстанцем. +%o was beaten to death by the poor.,OB_BEGGAR,,,,%o byl@[ao_cs] umlácen@[ao_cs] chudinou.,%o blev slået ihjel af de fattige.,%o fiel der Armut zum Opfer.,,%o morte bategiĝis de la malriĉuloj.,%o ha sido abatid@[ao_esp] a muerte por los pobres.,%o recibió una paliza letal de los pobres.,%o joutui köyhälistön kuoliaaksi hakkaamaksi.,%o a été battu@[e_fr] a mort par un pauvre.,%o halálra lett verve a szegénység által.,%o è stato calpestato dalla povertà. ,%o は貧民に殴り殺された。,%o 은(는) 자업자득으로 거지에게 맞아 죽었다.,%o werd door de armen doodgeslagen.,%o ble slått i hjel av de fattige.,%o został@[ao_pl] zatłuczon@[adj_pl] na śmierć przez żebraka.,%o foi espancad@[ao_ptb] até a morte pelos pobres.,,%o a fost omorât în bătaie de sărmani.,Игрока %o забили до смерти нищие.,%o је претучен@[adj_1_sr] од стране просјака.,%o blev ihjälslagen av de fattiga.,%o fakirler tarafından ölene kadar dövüldü.,%o забив до смерті жебрак. +%o should have never picked a fight with a civilian.,OB_PEASANT,,,,%o si neměl@[ao_cs] začínat s civilistou.,%o skulle aldrig have taget et slagsmål med en civilist.,%o hätte sich nicht mit einem Zivilisten anlegen sollen.,,%o ne estus devinta komenci batalon al civilulo.,%o no debería haber empezado una pelea con un civil.,%o hizo mal en iniciar una pelea con un civil.,%o hölmön ei olisi ikinä pitänyt haastaa riitaa siviilin kanssa.,%o n'aurait jamais du chercher des noises a un civil.,%o ujjat húzott egy civillel.,%o non avrebbe mai dovuto prendersela con un civile. ,%o は庶民に戦いを挑むべきではなかった。,%o 은(는) 민간인과 싸울 힘도 전혀 없었다.,%o had nooit een gevecht met een burger moeten aangaan.,%o skulle aldri ha kranglet med en sivilist.,%o nigdy nie powin@[irreg_5_pl] wdawać się w bójkę z cywilem.,%o nunca deveria ter arrumado briga com um civil.,%o nunca deveria ter pegado à briga com um civil.,%o n-ar fi trebuit să se încaiere cu un civil.,Игроку %o не следовало начинать драку с горожанином.,%o никад није треба@[ao_1_sr] да се потуче са цивилом.,%o skulle aldrig ha börjat slåss med en civilperson.,%o asla bir sivil ile kavga etmemeliydi.,%o не варто було починати бійку з цивільним. +%o was struck down by the Spectre.,OB_ALIENSPECTRE,,,,%o byl@[ao_cs] zničen@[ao_cs] přízrakem.,%o blev slået ned af spøgelset.,%o wurde von dem Schemen niedergestreckt.,,%o subite mortiĝis de la Fantomo.,A %o l@[ao_esp] ha fulminado el Espectro.,A %o l@[ao_esp] fulminó el Espectro.,%o joutui haamun kaatamaksi.,%o a été terrassé@[e_fr] par le Spectre.,%o ki lett ütve a lidérc által.,%o è stato abbattuto dallo Spettro. ,%o はスペクトルに討ち滅ぼされた。,%o 은(는) 스펙터에 의해 무너져 내렸다.,%o werd door de Specter neergeslagen.,%o ble slått ned av Spekter.,%o został@[ao_pl] powalon@[adj_pl] przez Widmo.,%o foi abatid@[ao_ptb] por um Espectro.,,%o a fost răpus de Spectru.,Игрока %o уничтожил фантом.,%o је обори@[ao_1_sr] са ногу утвара.,%o blev nedsliten av spektret.,%o Hortlak tarafından vuruldu.,Спектр вразив %o. +%o felt the wrath of The One God.,OB_ENTITY,,,,%o pocítil@[ao_cs] vztek Jediného Boha,%o følte den ene Guds vrede.,%o spürte den Zorn des Einen Gottes.,,%o sentis la koleregon de la Vera Dio.,%o ha sentido la ira del Dios Único.,%o sintió la ira del Dios Único.,%o sai tuta Yhden Ainoan Jumalan vihan.,%o a senti le courroux du Seul Dieu.,%o megérezte az Egyetlen Isten haragját.,%o ha assistito all'ira dell'Unico Dio. ,%o は唯一神の怒りに触れた。,%o 은(는) 유일신의 이름으로 천벌을 받았다.,%o voelde de toorn van de Ene God.,%o følte vreden til Den ene Gud.,%o poczuł@[ao_pl] gniew Jedynego Boga.,%o sentiu a ira do Deus Único.,,%o a simțit furia Zeului.,Игрок %o столкнулся с гневом Единого Бога.,Играча %o је осетио бес Јединог бога.,%o fick känna på den ende gudens vrede.,%o Tek Tanrı'nın gazabını hissetti.,%o відчу@[adj_1_ua] гнів Єдиного Бога. +%o couldn't escape from the Lore Master's grasp.,OB_LOREMASTER,,,,%o nemohl@[ao_cs] utéct Dějepiscově sevření.,%o kunne ikke undslippe Loremesterens greb.,%o konnte dem Griff des Wissensmeisters nicht entkommen.,,%o ne povis eskapi el la kapto de la Folkloristo.,%o no ha conseguido huir de las garras del Maestro del Conocimiento.,%o no logró huir de las garras del Maestro del Conocimiento.,%o ei kyennyt pakenemaan Oppi-Isän otteesta.,%o n'a pu échapper a l'emprise du Maître des Traditions.,%o nem tudott elmenekülni a Tan Mester elől.,%o non è riuscito a sfuggire alla stretta del Sapiente.,%o はロアマスターの手から逃れられなかった。,%o 은(는) 로어마스터의 촉수를 벗어나지 못했다.,%o kon niet ontsnappen aan de greep van de kennismeester.,%o kunne ikke unnslippe Loremesterens grep.,%o nie m@[irreg_4_pl] uniknąć chwytu Mędrca.,%o não conseguiu escapar do alcance do Mestre do Conhecimento.,,"%o n-a putut scăpa din mâinile Maestrului +Cunoștințelor.",Игрок %o не смог избежать длани Хранителя мудрости.,%o није успе@[ao_1_sr] побећи из Чувареве мудрости домашаја.,%o kunde inte fly från läromästarens grepp.,"%o, İrfan Ustası'nın elinden kaçamadı.",%o не здужа@[adj_1_ua] хват Хранителя мудрості. %o was deleted by the Programmer.,OB_PROGRAMMER,,,,%o byl@[ao_cs] vymazán@[ao_cs] Programátorem.,%o blev slettet af Programmøren.,%o wurde vom Programmierer gelöscht.,,%o eksiĝis de La Programisto.,%o ha sido suprimid@[ao_esp] por El Programador.,%o fue suprimid@[ao_esp] por El Programador.,%o joutui Ohjelmoijan poistamaksi.,%o a été effacé@[e_fr] par le Programmeur.,%o ki lett törölve a Programozó által.,%o è stato cancellato dal Programmatore. ,%o はプログラマーに消去された。,%o 은(는) 프로그래머에 의해 삭제됐다.,%o werd door de programmeur verwijderd.,%o ble slettet av Programmereren.,"%o został@[ao_pl] usunięt@[adj_pl] przez Programistę. -",%o foi deletad@[ao_ptb] pelo Programador.,%o foi apagad@[ao_ptb] pelo Programador.,%o a fost șters de Programator.,Игрока %o удалил Программист.,Играча %о је обрисао Програмер.,%o Programcı tarafından silindi. -%o was blown away by the Bishop.,OB_STFBISHOP,,,,%o byl@[ao_cs] odpálen@[ao_cs] Biskupem.,%o blev sprængt væk af Biskoppen.,%o wurde vom Bischof weggeblasen.,,%o forbloviĝis de la Episkopo.,%o ha sido volad@[ao_esp] en pedazos por el Obispo.,%o fue volad@[ao_esp] en pedazos por el Obispo.,%o joutui Piispan tyrmäämäksi.,%o a été pulvérisé@[e_fr] par l'Evèque.,%o el lett fújva a Püspök által.,%o è stato spazzato via dal Vescovo. ,%o はビショップに吹き飛ばされた。,%o 은(는) 비숍에 의해 초토화되었다.,%o werd door de bisschop weggeblazen.,%o ble blåst bort av biskopen.,%o został@[ao_pl] wysadzon@[adj_pl] przez Biskupa.,%o foi detonad@[ao_ptb] pelo Bispo.,,%o a fost aruncat cât colo de Episcop.,Игрока %o поразил Епископ.,Играча %o је екслопдирао Епископ.,"%o, Piskopos tarafından havaya uçuruldu." -%o was shot down by a Sentinel.,OB_SENTINEL,,,,%o byl@[ao_cs] odstřelen@[ao_cs] strážným robotem.,%o blev skudt ned af en Sentinel.,%o wurde von dem Wächter niedergeschossen.,,%o pafegiĝis de Sentinelo.,%o ha sido derribad@[ao_esp] por un Centinela.,%o fue derribad@[ao_esp] por un Centinela.,%o joutui vartijan ampumaksi.,%o a été abattu@[e_fr] par une Sentinelle.,%o meg lett lőve egy Őrszem által.,%o è stato impallinato dalla Sentinella. ,%o はセンティネルに堕とされた。,%o 은(는) 센티넬의 레이져를 맞았다.,%o werd neergeschoten door een Sentinel.,%o ble skutt ned av en Sentinel.,%o został@[ao_pl] zastrzelon@[adj_pl] przez Wartownika.,%o foi abatid@[ao_ptb] por uma Sentinela.,,%o a fost pus la pământ de o Santinelă.,Игрока %o застрелил страж.,Играча %o је упуцао стражар.,%o bir Nöbetçi tarafından vuruldu. -%o was swept away by a Crusader.,OB_CRUSADER,,,,%o byl@[ao_cs] odhozen@[ao_cs] křižákem.,%o blev fejet væk af en korsfarer.,%o wurde vom Ordensritter weggeblasen.,,%o tute detruiĝis de Krucisto.,%o ha sido aniquilad@[ao_esp] por un Cruzado.,%o fue aniquilad@[ao_esp] por un Cruzado.,%o joutui ristiretkeläisen pois pyyhkäisemäksi.,%o a été balayé@[e_fr] par un Croisé.,%o el lett söpörve egy Keresztes Lovag által.,%o è stato tolto di mezzo da un Crociato. ,"%o はクルセーダーに一掃された。 -",%o 은(는) 크루세이더의 공격에 날라갔다.,%o werd weggevaagd door een kruisvaarder.,%o ble feid bort av en korsfarer.,%o został@[ao_pl] zmiecion@[adj_pl] przez Krzyżowca.,%o foi varrid@[ao_ptb] por um Cruzado.,,%o a fost măturat de un Cruciat.,Игрока %o смёл крестоносец.,%o је обори@[ao_1_sr] с ногу крсташ.,%o bir Haçlı tarafından süpürüldü. -%o was sentenced by an Inquisitor.,OB_INQUISITOR,,,,%o byl@[ao_cs] odsouzen@[ao_cs] inkvizitorem.,%o blev dømt af en inkvisitor.,%o wurde vom Inquisitor verurteilt.,,%o kondamniĝis de Inkvizitoro.,%o ha sido sentenciad@[ao_esp] por un Inquisidor.,%o fue sentenciad@[ao_esp] por un Inquisidor.,%o joutui inkvisiittorin tuomitsemaksi.,%o a été condamné@[e_fr] par un Inquisiteur.,%o el lett ítélve egy Vizsgálóbíró által.,%o è stato condannato da un Inquisitore. ,"%o は審問官によって宣告された。 -",%o 은(는) 인퀴지터에 의해 처벌받았다.,%o werd veroordeeld door een inquisiteur.,%o ble dømt av en inkvisitor.,%o został@[ao_pl] skazan@[adj_pl] przez Inkwizytora.,%o foi condenad@[ao_ptb] por um Inquisidor.,,%o a fost condamnat de un Inchizitor.,Игрока %o приговорил инквизитор.,Играчу %o је пресудио инквизитор.,%o bir Engizisyoncu tarafından mahkum edildi. -%o was bugged by a Stalker.,OB_STALKER,,,,%o se nechal@[ao_cs] otravovat slídilem.,%o blev aflyttet af en Stalker.,%o wurde von dem Jäger genervt.,,%o ĝeniĝis de Persekutanto.,%o ha sido fastidiad@[ao_esp] por un Acechador.,%o fue fastidiad@[ao_esp] por un Acechador.,%o joutui vaanijan häiritsemäksi.,%o a été asticoté@[e_fr] par un chasseur.,%o bogaras lett egy Settenkedő által.,%o è stato violentato da un Cacciatore. ,"%o はストーカーに精神を蝕まれた。 -",%o 은(는) 스토커에게 벌레 물림을 당했다.,%o werd afgeluisterd door een Stalker.,%o ble avlyttet av en Stalker.,%o został@[ao_pl] zaczepion@[adj_pl] przez Prześladowcę.,%o foi atacad@[ao_ptb] por um Caçador.,,%o a fost cicălit de un Hărțuitor.,Игрока %o ужалил преследователь.,Играча %o је убио прогонитељ.,%o bir Takipçi tarafından dinlendi. -%o triggered the automatic defenses.,OB_TURRET,,,%o triggered the automatic defences.,%o spustil@[ao_cs] automatickou obranu.,%o udløste det automatiske forsvar.,%o hat die automatische Verteidigung ausgelöst.,,%o ekagigis la aŭtomatajn defendojn.,%o ha activado las defensas automáticas.,%o activó las defensas automáticas.,%o laukaisi automaattipuolustukset.,%o a déclenché les défenses automatiques.,%o bekapcsolta az automata védelmi rendszert.,%o ha attivato le difese automatiche. ,%o は警備システムを起動してしまった。,%o 은(는) 경비 시스템에 발각되었다.,%o activeerde de automatische verdediging.,%o utløste det automatiske forsvaret.,%o aktywował@[ao_pl] automatyczne zabezpieczenia.,%o ativou as defesas automáticas.,,%o a alertat sistemul de protecție automat.,Из-за игрока %o активировалась автоматическая защита.,%o је активира@[ao_1_sr] дефанзивне системе.,%o otomatik savunmayı tetikledi. -%o was clawed by a Templar.,OB_TEMPLARHIT,,,,%o byl@[ao_cs] rozsápán@[ao_cs] templářem.,%o blev kløet af en Tempelridder.,%o wurde von dem Templer aufgeschlitzt.,,%o ungegiĝis de Templano.,%o ha sido desgarrad@[ao_esp] por un Templario.,%o fue desgarrad@[ao_esp] por un Templario.,%o joutui temppeliherran raatelemaksi.,%o a été griffé@[e_fr] par un Templier.,%o meg lett karmolva egy Templomos által.,%o è stato artigliato da un Templare. ,%o は騎士団員に連行された。,%o 은(는) 템플러에게 할큄을 당했다.,%o werd geklauwd door een Tempelier.,%o ble klort av en tempelridder.,%o został@[ao_pl] rozszarpan@[adj_pl] przez Templariusza.,%o foi rasgad@[ao_ptb] por um Templário.,,%o a fost zgâriat de un Templier.,Игрока %o разорвал храмовник.,%o је пресечен@[adj_1_sr] од стране темплара.,%o bir Tapınakçı tarafından pençelendi. -%o was vaporized by a Templar.,OB_TEMPLAR,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] templářem.,%o blev fordampet af en Tempelridder.,%o wurde von dem Templer vaporisiert.,,%o vaporiĝis de Templano.,%o ha sido vaporizad@[ao_esp] por un Templario.,%o fue vaporizad@[ao_esp] por un Templario.,%o joutui temppeliherran höyryttämäksi.,%o a été vaporisé@[e_fr] par un Templier.,%o elpárolgott egy Templomos által.,%o è stato vaporizzato da un Templare. ,%o は騎士団員に浄化された。,%o 은(는) 템플러에 의해 존재가 소멸됐다.,%o werd verdampt door een Tempelier.,%o ble fordampet av en tempelridder.,%o rozpłyn@[irreg_2_pl] się przez Templariusza.,%o foi vaporizad@[ao_ptb] por um Templário.,,%o a fost vaporizat de un Templier.,Игрока %o испепелил храмовник.,Играча %o је испарио темплар.,%o bir Tapınakçı tarafından buharlaştırıldı. -%o was sliced open by a Reaver.,OB_REAVERHIT,,,,%o byl@[ao_cs] rozřezán@[ao_cs] pleničem.,%o blev skåret op af en Reaver.,%o wude von dem Plünderer aufgeschlitzt.,,%o distranĉiĝis de Lerta roboto.,%o ha sido rebanad@[ao_esp] por un Saqueador.,%o fue rebanad@[ao_esp] por un Saqueador.,%o joutui raastajan auki viiltämäksi.,%o a été fendu@[e_fr] par un Reaver.,%o szét lett vágva egy Fosztogató által.,%o è stato aperto a metà da un Saccheggiatore. ,%o はリーバーに切り裂かれた。,%o 은(는) 리버에게 해부되었다.,%o werd opengesneden door een Reaver.,%o ble skåret opp av en Reaver.,%o został@[ao_pl] rozcięt@[adj_pl] przez Rozbójnika.,%o foi fatiad@[ao_ptb] por um Saqueador.,,%o a fost feliat de un Pungaș.,Игрока %o разрезал на куски похититель.,%o је исечен@[adj_1_sr] на отворено од стране сакупљача.,%o bir Yağmacı tarafından kesildi. -%o was shot down by a Reaver.,OB_REAVER,,,,%o byl@[ao_cs] zastřelen@[ao_cs] pleničem.,%o blev skudt ned af en Reaver.,%o wurde von dem Plünderer niedergeschossen.,,%o pafegiĝis de Lerta roboto.,%o ha sido derribad@[ao_esp] por un Saqueador.,%o fue derribad@[ao_esp] por un Saqueador.,%o joutui raastajan alas ampumaksi.,%o a été descendu@[e_fr] par un Reaver.,%o le lett lőve egy Fosztogató által.,%o è stato colpito da un Saccheggiatore. ,%o はリーバーに撃ち殺された。,%o 은(는) 리버에게 격파되었다.,%o werd neergeschoten door een Reaver.,%o ble skutt ned av en Reaver.,%o został@[ao_pl] zastrzelon@[adj_pl] przez Rozbójnika.,%o foi abatid@[ao_ptb] por um Saqueador.,,%o a fost împușcat de un Pungaș.,Игрока %o застрелил похититель.,Играча %o је упуцао сакупљач.,%o bir Yağmacı tarafından vuruldu. -%o was unwittingly backstabbed by %k.,OB_MPPUNCHDAGGER,,,,%o dostal@[ao_cs] kudlou do zad od hráče %k.,%o blev ufrivilligt stukket i ryggen af %k.,%o wurde von %k hinterrücks erdolcht.,,%o akcidente dorspikiĝis de %k.,%o ha sido apuñalad@[ao_esp] sin querer por %k.,%o fue apuñalad@[ao_esp] sin querer por %k.,%o joutui tahattomasti pelaajan %k selkäänpuukottamaksi.,%o s'est fait@[e_fr] planter un lame dans le dos de la part de %k.,%o véletlenül hátbalett szúrva %k által.,%o è stato colto alle spalle da %k senza che se ne accorgesse.,%o は電気ショックを %k からもらった。,%o 은(는) 모르는 사이에 %k 에 의해 비수를 찔렸다.,%o werd achtergestoken door %k.,%o ble uforvarende dolket i ryggen av %k.,%o został@[ao_pl] bezwiednie dźgnięt@[adj_pl] przez %k.,%o foi apunhalad@[ao_ptb] de surpresa por %k.,,%o a fost înjunghiat pe la spate de %k.,Игрок %o был непреднамеренно заколот кинжалом игрока %k.,%o је убоден@[adj_1_sr] у леђа од стране играча %k.,"%o, %k tarafından farkında olmadan arkadan bıçaklandı." -%o got bolted to the wall by %k.,OB_MPELECTRICBOLT,,,,%o byl@[ao_cs] přišpendlen@[ao_cs] ke zdi hráčem %k.,%o blev boltet fast til væggen af %k.,%o wurde von %k an die Wand genagelt.,,%o pafiĝis de sageto sur la muro de %k.,%o ha quedado atornillad@[ao_esp] a la pared por %k.,%o quedó atornillad@[ao_esp] a la pared por %k.,%o naulitsi %o paran seinään.,%o s'est fait@[e_fr] clouer au mur par %k.,%o falra lett szegezve %k által.,%o è stato inchiodato al muro da %k.,%o は %k に壁へ打ち付けられた。,%o 은(는) %k 의 전류가 흐르는 볼트촉을 만졌다.,%o werd door %k aan de muur geschroefd.,%o ble boltet fast til veggen av %k.,%o został@[ao_pl] przybit@[adj_pl] do ściany przez %k.,%o foi pregad@[ao_ptb] na parede por %k.,,%o a fost agățat de perete de %k.,Игрок %o был прибит к стене игроком %k.,%o је причвршћен@[adj_1_sr] за зид од стране играча %k.,"%o, %k tarafından duvara yapıştırıldı." -%o received a lethal dose of %k's wrath.,OB_MPPOISONBOLT,,,,%o přijal@[ao_cs] smrtelnou dávku hněvu hráče %k.,%o fik en dødelig dosis af %ks vrede.,%o erhielt eine tödliche Dosis von %ks Zorn.,,%o recivis mortigan dozon de la kolerego de %k.,%o ha recibido una dosis letal de la ira de %k.,%o recibió una dosis letal de la ira de %k.,%o sai tappavan annoksen pelaajan %k vihaa.,%o a recu une dose létale de la colère de %k.,%o kapott egy halálos adagot %k-tól/től.,%o ha ricevuto una dose letale dell'ira di %k.,%o は 致死量の %k の怒りを盛られた。,%o 은(는) %k 로부터 암살 같지 않은 암살을 당했다.,%o kreeg een dodelijke dosis van %k's toorn.,%o fikk en dødelig dose av %ks vrede.,%o dostał@[ao_pl] śmiertelną dawkę gniewu %k.,%o recebeu uma dose letal da ira de %k.,,%o a primit o doză letală din furia lui %k.,Игрок %o получил смертельную дозу гнева игрока %k.,%o је доби@[ao_1_sr] смртну дозу гнева играча %k.,"%o, %k tarafından zehirlendi." +",%o foi deletad@[ao_ptb] pelo Programador.,%o foi apagad@[ao_ptb] pelo Programador.,%o a fost șters de Programator.,Игрока %o удалил Программист.,Играча %о је обрисао Програмер.,%o blev raderad av programmeraren.,%o Programcı tarafından silindi.,Програміст стер %o. +%o was blown away by the Bishop.,OB_STFBISHOP,,,,%o byl@[ao_cs] odpálen@[ao_cs] Biskupem.,%o blev sprængt væk af Biskoppen.,%o wurde vom Bischof weggeblasen.,,%o forbloviĝis de la Episkopo.,%o ha sido volad@[ao_esp] en pedazos por el Obispo.,%o fue volad@[ao_esp] en pedazos por el Obispo.,%o joutui Piispan tyrmäämäksi.,%o a été pulvérisé@[e_fr] par l'Evèque.,%o el lett fújva a Püspök által.,%o è stato spazzato via dal Vescovo. ,%o はビショップに吹き飛ばされた。,%o 은(는) 비숍에 의해 초토화되었다.,%o werd door de bisschop weggeblazen.,%o ble blåst bort av biskopen.,%o został@[ao_pl] wysadzon@[adj_pl] przez Biskupa.,%o foi detonad@[ao_ptb] pelo Bispo.,,%o a fost aruncat cât colo de Episcop.,Игрока %o поразил Епископ.,Играча %o је екслопдирао Епископ.,%o blev bortblåst av biskopen.,"%o, Piskopos tarafından havaya uçuruldu.",%o підірвано Єпископом. +%o was shot down by a Sentinel.,OB_SENTINEL,,,,%o byl@[ao_cs] odstřelen@[ao_cs] strážným robotem.,%o blev skudt ned af en Sentinel.,%o wurde von dem Wächter niedergeschossen.,,%o pafegiĝis de Sentinelo.,A %o l@[ao_esp] ha derribado un Centinela.,A %o l@[ao_esp] derribó un Centinela.,%o joutui vartijan ampumaksi.,%o a été abattu@[e_fr] par une Sentinelle.,%o meg lett lőve egy Őrszem által.,%o è stato impallinato dalla Sentinella. ,%o はセンティネルに堕とされた。,%o 은(는) 센티넬의 레이져를 맞았다.,%o werd neergeschoten door een Sentinel.,%o ble skutt ned av en Sentinel.,%o został@[ao_pl] zastrzelon@[adj_pl] przez Wartownika.,%o foi abatid@[ao_ptb] por uma Sentinela.,,%o a fost pus la pământ de o Santinelă.,Игрока %o застрелил страж.,Играча %o је упуцао стражар.,%o blev nedskjuten av en Sentinel.,%o bir Nöbetçi tarafından vuruldu.,Вартовий пристрелив %o. +%o was swept away by a Crusader.,OB_CRUSADER,,,,%o byl@[ao_cs] odhozen@[ao_cs] křižákem.,%o blev fejet væk af en korsfarer.,%o wurde vom Ordensritter weggeblasen.,,%o tute detruiĝis de Krucisto.,A %o l@[ao_esp] ha aniquilado un Cruzado.,A %o l@[ao_esp] aniquiló un Cruzado.,%o joutui ristiretkeläisen pois pyyhkäisemäksi.,%o a été balayé@[e_fr] par un Croisé.,%o el lett söpörve egy Keresztes Lovag által.,%o è stato tolto di mezzo da un Crociato. ,"%o はクルセーダーに一掃された。 +",%o 은(는) 크루세이더의 공격에 날라갔다.,%o werd weggevaagd door een kruisvaarder.,%o ble feid bort av en korsfarer.,%o został@[ao_pl] zmiecion@[adj_pl] przez Krzyżowca.,%o foi varrid@[ao_ptb] por um Cruzado.,,%o a fost măturat de un Cruciat.,Игрока %o смёл крестоносец.,%o је обори@[ao_1_sr] с ногу крсташ.,%o sveptes bort av en korsriddare.,%o bir Haçlı tarafından süpürüldü.,%o змів хрестоносець. +%o was sentenced by an Inquisitor.,OB_INQUISITOR,,,,%o byl@[ao_cs] odsouzen@[ao_cs] inkvizitorem.,%o blev dømt af en inkvisitor.,%o wurde vom Inquisitor verurteilt.,,%o kondamniĝis de Inkvizitoro.,A %o l@[ao_esp] ha sentenciado un Inquisidor.,A %o l@[ao_esp] sentenció un Inquisidor.,%o joutui inkvisiittorin tuomitsemaksi.,%o a été condamné@[e_fr] par un Inquisiteur.,%o el lett ítélve egy Vizsgálóbíró által.,%o è stato condannato da un Inquisitore. ,"%o は審問官によって宣告された。 +",%o 은(는) 인퀴지터에 의해 처벌받았다.,%o werd veroordeeld door een inquisiteur.,%o ble dømt av en inkvisitor.,%o został@[ao_pl] skazan@[adj_pl] przez Inkwizytora.,%o foi condenad@[ao_ptb] por um Inquisidor.,,%o a fost condamnat de un Inchizitor.,Игрока %o приговорил инквизитор.,Играчу %o је пресудио инквизитор.,%o blev dömd av en inkvisitor.,%o bir Engizisyoncu tarafından mahkum edildi.,Інквізитор здійснив суд над %o. +%o was bugged by a Stalker.,OB_STALKER,,,,%o se nechal@[ao_cs] otravovat slídilem.,%o blev aflyttet af en Stalker.,%o wurde von dem Jäger genervt.,,%o ĝeniĝis de Gvatanto.,A %o l@[ao_esp] ha fastidiado un Acechador.,A %o l@[ao_esp] fastidió un Acechador.,%o joutui vaanijan häiritsemäksi.,%o a été asticoté@[e_fr] par un chasseur.,%o bogaras lett egy Settenkedő által.,%o è stato violentato da un Cacciatore. ,"%o はストーカーに精神を蝕まれた。 +",%o 은(는) 스토커에게 벌레 물림을 당했다.,%o werd afgeluisterd door een Stalker.,%o ble avlyttet av en Stalker.,%o został@[ao_pl] zaczepion@[adj_pl] przez Prześladowcę.,%o foi atacad@[ao_ptb] por um Caçador.,,%o a fost cicălit de un Hărțuitor.,Игрока %o ужалил преследователь.,Играча %o је убио прогонитељ.,%o blev avlyssnad av en Stalker.,%o bir Takipçi tarafından dinlendi.,%o загриз сталкер. +%o triggered the automatic defenses.,OB_TURRET,,,%o triggered the automatic defences.,%o spustil@[ao_cs] automatickou obranu.,%o udløste det automatiske forsvar.,%o hat die automatische Verteidigung ausgelöst.,,%o ekagigis la aŭtomatajn defendojn.,%o ha activado las defensas automáticas.,%o activó las defensas automáticas.,%o laukaisi automaattipuolustukset.,%o a déclenché les défenses automatiques.,%o bekapcsolta az automata védelmi rendszert.,%o ha attivato le difese automatiche. ,%o は警備システムを起動してしまった。,%o 은(는) 경비 시스템에 발각되었다.,%o activeerde de automatische verdediging.,%o utløste det automatiske forsvaret.,%o aktywował@[ao_pl] automatyczne zabezpieczenia.,%o ativou as defesas automáticas.,,%o a alertat sistemul de protecție automat.,Из-за игрока %o активировалась автоматическая защита.,%o је активира@[ao_1_sr] дефанзивне системе.,%o utlöste det automatiska försvaret.,%o otomatik savunmayı tetikledi.,%o активува@[adj_1_ua] автоматичний захист. +%o was clawed by a Templar.,OB_TEMPLARHIT,,,,%o byl@[ao_cs] rozsápán@[ao_cs] templářem.,%o blev kløet af en Tempelridder.,%o wurde von dem Templer aufgeschlitzt.,,%o ungegiĝis de Templano.,A %o l@[ao_esp] ha desgarrado un Templario.,A %o l@[ao_esp] desgarró un Templario.,%o joutui temppeliherran raatelemaksi.,%o a été griffé@[e_fr] par un Templier.,%o meg lett karmolva egy Templomos által.,%o è stato artigliato da un Templare. ,%o は騎士団員に連行された。,%o 은(는) 템플러에게 할큄을 당했다.,%o werd geklauwd door een Tempelier.,%o ble klort av en tempelridder.,%o został@[ao_pl] rozszarpan@[adj_pl] przez Templariusza.,%o foi rasgad@[ao_ptb] por um Templário.,,%o a fost zgâriat de un Templier.,Игрока %o разорвал храмовник.,%o је пресечен@[adj_1_sr] од стране темплара.,%o blev klömsugen av en tempelriddare.,%o bir Tapınakçı tarafından pençelendi.,%o розірвав тамплієр. +%o was vaporized by a Templar.,OB_TEMPLAR,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] templářem.,%o blev fordampet af en Tempelridder.,%o wurde von dem Templer vaporisiert.,,%o vaporiĝis de Templano.,A %o l@[ao_esp] ha vaporizado un Templario.,A %o l@[ao_esp] vaporizó un Templario.,%o joutui temppeliherran höyryttämäksi.,%o a été vaporisé@[e_fr] par un Templier.,%o elpárolgott egy Templomos által.,%o è stato vaporizzato da un Templare. ,%o は騎士団員に浄化された。,%o 은(는) 템플러에 의해 존재가 소멸됐다.,%o werd verdampt door een Tempelier.,%o ble fordampet av en tempelridder.,%o rozpłyn@[irreg_2_pl] się przez Templariusza.,%o foi vaporizad@[ao_ptb] por um Templário.,,%o a fost vaporizat de un Templier.,Игрока %o испепелил храмовник.,Играча %o је испарио темплар.,%o blev förångad av en tempelriddare.,%o bir Tapınakçı tarafından buharlaştırıldı.,Тамплієр розсіяв %o. +%o was sliced open by a Reaver.,OB_REAVERHIT,,,,%o byl@[ao_cs] rozřezán@[ao_cs] pleničem.,%o blev skåret op af en Reaver.,%o wude von dem Plünderer aufgeschlitzt.,,%o distranĉiĝis de Lertulo.,A %o l@[ao_esp] ha rebanado un Saqueador.,A %o l@[ao_esp] rebanó un Saqueador.,%o joutui raastajan auki viiltämäksi.,%o a été fendu@[e_fr] par un Reaver.,%o szét lett vágva egy Fosztogató által.,%o è stato aperto a metà da un Saccheggiatore. ,%o はリーバーに切り裂かれた。,%o 은(는) 리버에게 해부되었다.,%o werd opengesneden door een Reaver.,%o ble skåret opp av en Reaver.,%o został@[ao_pl] rozcięt@[adj_pl] przez Rozbójnika.,%o foi fatiad@[ao_ptb] por um Saqueador.,,%o a fost feliat de un Pungaș.,Игрока %o разрезал на куски похититель.,%o је исечен@[adj_1_sr] на отворено од стране сакупљача.,%o blev uppskuren av en Reaver.,%o bir Yağmacı tarafından kesildi.,Рейдер нарізав на куски %o. +%o was shot down by a Reaver.,OB_REAVER,,,,%o byl@[ao_cs] zastřelen@[ao_cs] pleničem.,%o blev skudt ned af en Reaver.,%o wurde von dem Plünderer niedergeschossen.,,%o pafegiĝis de Lertulo.,A %o l@[ao_esp] ha derribado un Saqueador.,A %o l@[ao_esp] derribó un Saqueador.,%o joutui raastajan alas ampumaksi.,%o a été descendu@[e_fr] par un Reaver.,%o le lett lőve egy Fosztogató által.,%o è stato colpito da un Saccheggiatore. ,%o はリーバーに撃ち殺された。,%o 은(는) 리버에게 격파되었다.,%o werd neergeschoten door een Reaver.,%o ble skutt ned av en Reaver.,%o został@[ao_pl] zastrzelon@[adj_pl] przez Rozbójnika.,%o foi abatid@[ao_ptb] por um Saqueador.,,%o a fost împușcat de un Pungaș.,Игрока %o застрелил похититель.,Играча %o је упуцао сакупљач.,%o blev nedskjuten av en Reaver.,%o bir Yağmacı tarafından vuruldu.,Рейдер пристрелив %o. +%o was unwittingly backstabbed by %k.,OB_MPPUNCHDAGGER,,,,%o dostal@[ao_cs] kudlou do zad od hráče %k.,%o blev ufrivilligt stukket i ryggen af %k.,%o wurde von %k hinterrücks erdolcht.,,%o akcidente dorspikiĝis de %k.,%o ha sido apuñalad@[ao_esp] sin querer por %k.,%o fue apuñalad@[ao_esp] sin querer por %k.,%o joutui tahattomasti pelaajan %k selkäänpuukottamaksi.,%o s'est fait@[e_fr] planter un lame dans le dos de la part de %k.,%o véletlenül hátbalett szúrva %k által.,%o è stato colto alle spalle da %k senza che se ne accorgesse.,%o は電気ショックを %k からもらった。,%o 은(는) 모르는 사이에 %k 에 의해 비수를 찔렸다.,%o werd achtergestoken door %k.,%o ble uforvarende dolket i ryggen av %k.,%o został@[ao_pl] bezwiednie dźgnięt@[adj_pl] przez %k.,%o foi apunhalad@[ao_ptb] de surpresa por %k.,,%o a fost înjunghiat pe la spate de %k.,Игрок %o был непреднамеренно заколот кинжалом игрока %k.,%o је убоден@[adj_1_sr] у леђа од стране играча %k.,%o blev omedvetet knivhuggen i ryggen av %k.,"%o, %k tarafından farkında olmadan arkadan bıçaklandı.",%k випадково заріза@[adj_1_ua] %o. +%o got bolted to the wall by %k.,OB_MPELECTRICBOLT,,,,%o byl@[ao_cs] přišpendlen@[ao_cs] ke zdi hráčem %k.,%o blev boltet fast til væggen af %k.,%o wurde von %k an die Wand genagelt.,,%o pafiĝis de sageto sur la muro de %k.,%o ha quedado atornillad@[ao_esp] a la pared por %k.,%o quedó atornillad@[ao_esp] a la pared por %k.,%o naulitsi %o paran seinään.,%o s'est fait@[e_fr] clouer au mur par %k.,%o falra lett szegezve %k által.,%o è stato inchiodato al muro da %k.,%o は %k に壁へ打ち付けられた。,%o 은(는) %k 의 전류가 흐르는 볼트촉을 만졌다.,%o werd door %k aan de muur geschroefd.,%o ble boltet fast til veggen av %k.,%o został@[ao_pl] przybit@[adj_pl] do ściany przez %k.,%o foi pregad@[ao_ptb] na parede por %k.,,%o a fost agățat de perete de %k.,Игрок %o был прибит к стене игроком %k.,%o је причвршћен@[adj_1_sr] за зид од стране играча %k.,%o blev bultad mot väggen av %k.,"%o, %k tarafından duvara yapıştırıldı.",%k приби@[adj_1_ua] до стіни %o. +%o received a lethal dose of %k's wrath.,OB_MPPOISONBOLT,,,,%o přijal@[ao_cs] smrtelnou dávku hněvu hráče %k.,%o fik en dødelig dosis af %ks vrede.,%o erhielt eine tödliche Dosis von %ks Zorn.,,%o recivis mortigan dozon de la kolerego de %k.,%o ha recibido una dosis letal de la ira de %k.,%o recibió una dosis letal de la ira de %k.,%o sai tappavan annoksen pelaajan %k vihaa.,%o a recu une dose létale de la colère de %k.,%o kapott egy halálos adagot %k-tól/től.,%o ha ricevuto una dose letale dell'ira di %k.,%o は 致死量の %k の怒りを盛られた。,%o 은(는) %k 로부터 암살 같지 않은 암살을 당했다.,%o kreeg een dodelijke dosis van %k's toorn.,%o fikk en dødelig dose av %ks vrede.,%o dostał@[ao_pl] śmiertelną dawkę gniewu %k.,%o recebeu uma dose letal da ira de %k.,,%o a primit o doză letală din furia lui %k.,Игрок %o получил смертельную дозу гнева игрока %k.,%o је доби@[ao_1_sr] смртну дозу гнева играча %k.,%o fick en dödlig dos av %ks vrede.,"%o, %k tarafından zehirlendi.",%o відчу@[adj_1_ua] смертельну дозу гніву %k. %o was drilled full of holes by %k's assault gun.,OB_MPASSAULTGUN,,,,%o byl@[ao_cs] proděravěn@[ao_cs] skrz na skrz puškou hráče %k.,%o blev boret fuld af huller af %ks angrebspistol.,%o wurde von %ks Sturmgewehr perforiert.,,%o boriĝis kun multaj truoj de la sturmofusilo de %k.,%o ha sido taladrad@[ao_esp] por el fusil de asalto de %k.,%o fue taladrad@[ao_esp] por el fusil de asalto de %k.,%k porasi %o paran täyteen reikiä rynnäkkökiväärillään.,%o s'est fait@[e_fr] couvrir de trous par le fusil d'assaut de %k.,%o ki lett lyukasztva %k Gépfegyvere által.,%o è stato crivellato dall'arma d'assalto di %k.,%o は %k のアサルトガンで穴だらけにされた。,%o 은(는) %k 의 돌격소총 덕분에 멋진 구멍을 선물 받았다.,%o werd geperforeerd door %k.,%o ble boret full av hull av %ks stormgevær.,%o został@[ao_pl] przedziurkowan@[adj_pl] przez karabin szturmowy %k.,%o foi perfurad@[ao_ptb] pelo fuzil de assalto de %k.,,"%o a fost umplut de găuri de pușca lui -%k.",Игрок %o изрешечён штурмовой винтовкой игрока %k.,%o је изрешетан@[adj_1_sr] од стране јуришне пушке играча %k.,"%o, %k tarafından delik deşik edildi." -%o gulped down %k's missile.,OB_MPMINIMISSILELAUNCHER,,,,%o spolknul@[ao_cs] raketu hráče %k.,%o slugte %ks missil.,%o schluckte %ks Rakete herunter.,,%o glutis la misilon de %k.,%o se ha tragado el misil de %k.,%o se tragó el misil de %k.,%o nieli alas pelaajan %k ohjuksen.,%o a avalé le missile de %k.,%o lenyelte %k rakétáját.,%o ha inghiottito il missile di %k.,%o は %k のミサイルを味わった。,%o 은(는) %k 의 미니 미사일을 고맙게 삼켰다.,%o heeft %k's raket naar beneden geslingerd.,%o slukte %k's missil.,%o połkn@[irreg_2_pl] rakietę %k.,%o engoliu o míssil de %k.,,%o a înghițit proiectilul lui %k.,Игрок %o проглотил ракету игрока %k.,%o је прогута@[ao_1_sr] ракету играча %k.,"%o, %k tarafından patlatıldı." -%o was inverted by %k's H-E grenade.,OB_MPSTRIFEGRENADE,,,,%o byl@[ao_cs] otočen@[ao_cs] naruby výbušným granátem hráče %k.,%o blev omvendt af %ks H-E granat.,%o wurde von %ks HE-Granate invertiert.,,%o estis inversigita de la HE-grenado de %k.,%o ha sido invertid@[ao_esp] por la granada HE de %k.,%o fue invertid@[ao_esp] por la granada HE de %k.,%k käänsi %o paran nurinpäin räjähdekranaatillaan.,%o a été mis@[e_fr] sens dessus dessous par la grenade explosive de %k.,%o ki lett fordítva %k gránátája által.,%o è stato invertito dalla granata H-E di %k.,%o は %k のHE手榴弾によって反逆された。,%o 은(는) %k 의 고폭탄에 의해 역전당했다.,%o werd omgekeerd door %k's HE-granaat.,%o ble invertert av %ks H-E-granat.,%o został@[ao_pl] wywrócon@[adj_pl] przez granat %k.,%o foi peg@[ao_ptb] pelas granadas de %k.,,%o a fost întors pe dos de grenada lui %k.,Игрок %o вывернут наизнанку разрывной гранатой игрока %k.,%o се преокрену@[ao_1_sr] од стране Х-Е гранате играча %k.,"%o, %k tarafından ters çevrildi." -%o took a flame bath in %k's phosphorous pyre.,OB_MPPHOSPHOROUSGRENADE,,,,%o si dal@[ao_cs] ohnivou koupel ve fosforovém žáru hráče %k.,%o tog et flambad i %ks fosforbål.,%o nahm ein Flammenbad in %ks Scheiterhaufen.,,%o prenis flaman banon en la fosfora ŝtiparo de %k.,%o se ha bañado en las llamas de fósforo de %k.,%o se bañó en las llamas de fósforo de %k.,%o otti liekkikylvyn pelaajan %k fosforiroviolla.,%o s'est permis@[e_fr] une pyroclave dans les flammes phosphoriques de %k.,%o kapott egy tűzfürdőt %k máglyájától.,%o ha fatto un bagno nelle fiamme nella pira di fosforo di %k.,%o は %k の白リン弾で炎に包まれた。,%o 은(는) %k 의 소이탄이 뿜는 화염에 몸을 담갔다.,%o nam een vlammenbad in %k's fosforbrandstapel.,%o tok et flammebad i %ks fosforbål.,%o wzi@[irreg_2_pl] ognistą kąpiel w fosforowym stosie %k.,%o se banhou nas chamas de fósforo de %k.,,%o a făcut o baie fierbinte in fosforul lui %k.,Игрок %o принял горячую ванну из чистого фосфора игрока %k.,%o се окупа@[ao_1_sr] у пламену од стране фосфорне гранате играча %k.,"%o, %k tarafından fosforlu ateşte alev banyosu yaptırıldı." -%o was barbecued by %k.,OB_MPFLAMETHROWER,,,,%o byl@[ao_cs] usmažen@[ao_cs] hráčem %k.,%o blev grillet af %k.,%o wurde von %k gegrillt,,%o kradrostiĝis de %k.,%o ha sido asad@[ao_esp] por %k.,%o fue asad@[ao_esp] por %k.,%k grillasi %o paran.,%o est passé@[e_fr] au barbecue de %k.,%o meg lett sütve %k által.,%o è stato fatto alla griglia da %k.,%o は %k に丸焼きにされてしまった。,%o 은(는) %k 의 바비큐 파티에 참여했다. 혼자서.,%o werd gebarbecued door %k.,%o ble grillet av %k.,%o został@[ao_pl] ugrillowan@[adj_pl] przez %k.,%o virou churrasco por causa de %k.,,%o a fost făcut grătar de %k.,Игрок %k поджарил игрока %o.,%o је реш печен@[adj_1_sr] од стране играча %k.,"%o, %k tarafından mangalda pişirildi." -%o was zapped by %k.,OB_MPMAULER1,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k.,%o blev zappet af %k.,%o wurde von %k geschockt.,,%o elektrokutiĝis de %k.,%o ha sido electrocutad@[ao_esp] por %k.,%o fue electrocutad@[ao_esp] por %k.,%o joutui pelaajan %k sähköistämäksi.,%o s'est fait@[e_fr] électrocuter par %k.,%o kapott egy áramot %k által.,%o è stato fulminato da %k.,%o は %k から電気ショックを浴びた。,%o 은(는) %k 이(가) 가한 전기 충격을 당했다.,%o werd door %k gezapt.,%o fikk støt av %k.,%o został@[ao_pl] porażon@[adj_pl] przez %k.,%o foi eletrocutad@[ao_ptb] por %k.,,%o a fost electrocutat de %k.,Игрок %k ударил током игрока %o.,%o је елетрошокиран@[adj_1_sr] од стране играча %k.,"%o, %k tarafından zaplandı." -%o was viciously vaporized by %k.,OB_MPMAULER,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] hráčem %k.,%o blev brutalt fordampet af %k.,%o wurde von %k vaporisiert.,,%o estis brutale vaporigita de %k.,%o ha sido ferozmente vaporizad@[ao_esp] por %k.,%o fue ferozmente vaporizad@[ao_esp] por %k.,%o joutui pelaajan %k höyrystämäksi.,%o à été vicieusement vaporisé@[e_fr] par %k.,%o elpárolgott %k által.,%o è stato crudelmente vaporizzato da %k.,%o は %k の悪辣さにより気化した。,%o 은(는) %k 에 의해 소극적으로 소멸되었다.,%o was door %k verdampt.,%o ble ondskapsfullt fordampet av %k.,%o rozpłyn@[irreg_2_pl] się przez %k.,%o foi vaporizad@[ao_ptb] por %k.,,%o a fost evaporat în mod violent de %k.,Игрок %k безжалостно распылил игрока %o.,%o је брутално испари@[ao_1_sr] од стране играча %k.,"%o, %k tarafından acımasızca buharlaştırıldı." +%k.",Игрок %o изрешечён штурмовой винтовкой игрока %k.,%o је изрешетан@[adj_1_sr] од стране јуришне пушке играча %k.,%o blev fullborrad med hål av %ks attackpistol.,"%o, %k tarafından delik deşik edildi.",%k нароби@[adj_1_ua] дірок в %o штурмовою гвинтівкою. +%o gulped down %k's missile.,OB_MPMINIMISSILELAUNCHER,,,,%o spolknul@[ao_cs] raketu hráče %k.,%o slugte %ks missil.,%o schluckte %ks Rakete herunter.,,%o glutis la misilon de %k.,%o se ha tragado el misil de %k.,%o se tragó el misil de %k.,%o nieli alas pelaajan %k ohjuksen.,%o a avalé le missile de %k.,%o lenyelte %k rakétáját.,%o ha inghiottito il missile di %k.,%o は %k のミサイルを味わった。,%o 은(는) %k 의 미니 미사일을 고맙게 삼켰다.,%o heeft %k's raket naar beneden geslingerd.,%o slukte %k's missil.,%o połkn@[irreg_2_pl] rakietę %k.,%o engoliu o míssil de %k.,,%o a înghițit proiectilul lui %k.,Игрок %o проглотил ракету игрока %k.,%o је прогута@[ao_1_sr] ракету играча %k.,%o slukade %ks missil.,"%o, %k tarafından patlatıldı.",%o ковтну@[adj_1_ua] ракети %k. +%o was inverted by %k's H-E grenade.,OB_MPSTRIFEGRENADE,,,,%o byl@[ao_cs] otočen@[ao_cs] naruby výbušným granátem hráče %k.,%o blev omvendt af %ks H-E granat.,%o wurde von %ks HE-Granate invertiert.,,%o estis inversigita de la HE-grenado de %k.,%o ha sido invertid@[ao_esp] por la granada HE de %k.,%o fue invertid@[ao_esp] por la granada HE de %k.,%k käänsi %o paran nurinpäin räjähdekranaatillaan.,%o a été mis@[e_fr] sens dessus dessous par la grenade explosive de %k.,%o ki lett fordítva %k gránátája által.,%o è stato invertito dalla granata H-E di %k.,%o は %k のHE手榴弾によって反逆された。,%o 은(는) %k 의 고폭탄에 의해 역전당했다.,%o werd omgekeerd door %k's HE-granaat.,%o ble invertert av %ks H-E-granat.,%o został@[ao_pl] wywrócon@[adj_pl] przez granat %k.,%o foi peg@[ao_ptb] pelas granadas de %k.,,%o a fost întors pe dos de grenada lui %k.,Игрок %o вывернут наизнанку разрывной гранатой игрока %k.,%o се преокрену@[ao_1_sr] од стране Х-Е гранате играча %k.,%o blev omvänd av %ks H-E-granat.,"%o, %k tarafından ters çevrildi.",%o інвертува@[adj_2_ua] гранатою %k. +%o took a flame bath in %k's phosphorous pyre.,OB_MPPHOSPHOROUSGRENADE,,,,%o si dal@[ao_cs] ohnivou koupel ve fosforovém žáru hráče %k.,%o tog et flambad i %ks fosforbål.,%o nahm ein Flammenbad in %ks Scheiterhaufen.,,%o prenis flaman banon en la fosfora ŝtiparo de %k.,%o se ha bañado en las llamas de fósforo de %k.,%o se bañó en las llamas de fósforo de %k.,%o otti liekkikylvyn pelaajan %k fosforiroviolla.,%o s'est permis@[e_fr] une pyroclave dans les flammes phosphoriques de %k.,%o kapott egy tűzfürdőt %k máglyájától.,%o ha fatto un bagno nelle fiamme nella pira di fosforo di %k.,%o は %k の白リン弾で炎に包まれた。,%o 은(는) %k 의 소이탄이 뿜는 화염에 몸을 담갔다.,%o nam een vlammenbad in %k's fosforbrandstapel.,%o tok et flammebad i %ks fosforbål.,%o wzi@[irreg_2_pl] ognistą kąpiel w fosforowym stosie %k.,%o se banhou nas chamas de fósforo de %k.,,%o a făcut o baie fierbinte in fosforul lui %k.,Игрок %o принял горячую ванну из чистого фосфора игрока %k.,%o се окупа@[ao_1_sr] у пламену од стране фосфорне гранате играча %k.,%o tog ett flambad i %ks fosforbål.,"%o, %k tarafından fosforlu ateşte alev banyosu yaptırıldı.",%k приготува@[adj_1_ua] ванну з чистого фосфору для %o. +%o was barbecued by %k.,OB_MPFLAMETHROWER,,,,%o byl@[ao_cs] usmažen@[ao_cs] hráčem %k.,%o blev grillet af %k.,%o wurde von %k gegrillt,,%o kradrostiĝis de %k.,%o ha sido asad@[ao_esp] por %k.,%o fue asad@[ao_esp] por %k.,%k grillasi %o paran.,%o est passé@[e_fr] au barbecue de %k.,%o meg lett sütve %k által.,%o è stato fatto alla griglia da %k.,%o は %k に丸焼きにされてしまった。,%o 은(는) %k 의 바비큐 파티에 참여했다. 혼자서.,%o werd gebarbecued door %k.,%o ble grillet av %k.,%o został@[ao_pl] ugrillowan@[adj_pl] przez %k.,%o virou churrasco por causa de %k.,,%o a fost făcut grătar de %k.,Игрок %k поджарил игрока %o.,%o је реш печен@[adj_1_sr] од стране играча %k.,%o blev grillad av %k.,"%o, %k tarafından mangalda pişirildi.",%k зажари@[adj_1_ua] %o. +%o was zapped by %k.,OB_MPMAULER1,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k.,%o blev zappet af %k.,%o wurde von %k geschockt.,,%o elektrokutiĝis de %k.,A %o l@[ao_esp] ha electrocutado %k.,A %o l@[ao_esp] electrocutó %k.,%o joutui pelaajan %k sähköistämäksi.,%o s'est fait@[e_fr] électrocuter par %k.,%o kapott egy áramot %k által.,%o è stato fulminato da %k.,%o は %k から電気ショックを浴びた。,%o 은(는) %k 이(가) 가한 전기 충격을 당했다.,%o werd door %k gezapt.,%o fikk støt av %k.,%o został@[ao_pl] porażon@[adj_pl] przez %k.,%o foi eletrocutad@[ao_ptb] por %k.,,%o a fost electrocutat de %k.,Игрок %k ударил током игрока %o.,%o је елетрошокиран@[adj_1_sr] од стране играча %k.,%o blev zappad av %k.,"%o, %k tarafından zaplandı.",%o отрима@[adj_1_ua] дозу струму від %k. +%o was viciously vaporized by %k.,OB_MPMAULER,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] hráčem %k.,%o blev brutalt fordampet af %k.,%o wurde von %k vaporisiert.,,%o estis brutale vaporigita de %k.,%o ha sido ferozmente vaporizad@[ao_esp] por %k.,%o fue ferozmente vaporizad@[ao_esp] por %k.,%o joutui pelaajan %k höyrystämäksi.,%o à été vicieusement vaporisé@[e_fr] par %k.,%o elpárolgott %k által.,%o è stato crudelmente vaporizzato da %k.,%o は %k の悪辣さにより気化した。,%o 은(는) %k 에 의해 소극적으로 소멸되었다.,%o was door %k verdampt.,%o ble ondskapsfullt fordampet av %k.,%o rozpłyn@[irreg_2_pl] się przez %k.,%o foi vaporizad@[ao_ptb] por %k.,,%o a fost evaporat în mod violent de %k.,Игрок %k безжалостно распылил игрока %o.,%o је брутално испари@[ao_1_sr] од стране играча %k.,%o blev brutalt förångad av %k.,"%o, %k tarafından acımasızca buharlaştırıldı.",%k безжалісно розсія@[adj_1_ua] %o. %o bowed down to the sheer power of %k's Sigil.,OB_MPSIGIL,,,,%o poklekl@[ao_cs] před čirou sílou Pečeti hráče %k.,%o bøjede sig for %ks sigil.,%o kapitulierte vor der Macht von %ks Sigil.,,%o kliniĝis antaŭ la plena potenco de la Sigelo de %k.,%o se ha inclinado ante el poder puro del emblema de %k.,%o se inclinó ante el poder puro del emblema de %k.,%o kumartui pelaajan %k Sinetin silkasta voimasta.,%o s'est prosterné@[e_fr] face à la toute puissance du Sigil de %k.,%o fejet hajtott %k Pecsétje ereje előtt.,%o si è prostrato davanti alla pura potenza del Sigillo di %k.,%o は %k のシジルによる威圧に屈した。,%o 은(는) %k 를 죽이기 전에 시질의 이름으로 절을 해야만 했다.,%o boog voor de kracht van %k's Sigil.,%o bøyde seg for kraften til %ks Sigil.,%o pokłonił@[ao_pl] się czystej mocy Pieczęci %k.,%o sentiu o poder do Sigilo de %k.,,"%o s-a plecat în fața puterii imense a Sigiliului -lui %k.",Игрок %o склонился перед силой Печати игрока %k.,%o је одклекну@[ao_1_sr] сировој моћи %k Сигила.,"%o, %k'in Sigil'inin katıksız gücüne boyun eğdi." -,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,, -Quest for the Sigil,TXT_STRIFE_EPI,,,,Pátrání za Pečetí,Jagten på Sigilet,Suche nach dem Sigil,,Serĉado por la Sigelo,La búsqueda del Emblema,,Päämääränä Sinetti,La Quête du Sigil,A Pecsét felkutatása,Alla ricerca del Sigillo,シジルの探求,시질을 위한 임무,Zoektocht naar de Sigil,Jakten på sigilet,Poszukiwanie Pieczęci,Em Busca do Sigilo,Demanda pelo Sigilo,În căutarea Sigiliului,В поисках Печати,Потрага за Сигил,Sigilin Peşinde +lui %k.",Игрок %o склонился перед силой Печати игрока %k.,%o је одклекну@[ao_1_sr] сировој моћи %k Сигила.,%o böjde sig för den rena kraften i %ks Sigill.,"%o, %k'in Sigil'inin katıksız gücüne boyun eğdi.",%o покори@[adj_2_ua] Сігілу %k. +,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,,,, +Quest for the Sigil,TXT_STRIFE_EPI,,,,Pátrání za Pečetí,Jagten på Sigilet,Suche nach dem Sigil,,Serĉado por la Sigelo,La búsqueda del Emblema,,Päämääränä Sinetti,La Quête du Sigil,A Pecsét felkutatása,Alla ricerca del Sigillo,シジルの探求,시질을 위한 임무,Zoektocht naar de Sigil,Jakten på sigilet,Poszukiwanie Pieczęci,Em Busca do Sigilo,Demanda pelo Sigilo,În căutarea Sigiliului,В поисках Печати,Потрага за Сигил,Jakten på Sigillet,Sigilin Peşinde, You've freed the prisoners!,TXT_FREED_PRISONERS,,,,Vysvobodil@[ao_cs] jsi vězně!,Du har befriet fangerne!,Du hast die Gefangenen befreit!,,Vi liberigis la kaptitojn!,¡Has liberado a los prisioneros!,¡Liberaste a los prisioneros!,Olet vapauttanut vangit!,Vous avez libéré les prisonniers!,Kiszabadítottad a foglyokat!,"Hai liberato i prigionieri! -",囚人を解放した!,죄수들을 탈옥시켰다!,Je hebt de gevangenen bevrijd!,Du har befridd fangene!,Uwolnił@[irreg_3_pl] więźniów,Você liberou os prisioneiros!,Libertaste os prisioneiros!,Ai eliberat prizonierii!,Пленники освобождены!,Затвореници су ослобођени!,Mahkumları serbest bıraktınız! -You've destroyed the Converter!,TXT_DESTROYED_CONVERTER,,,,Zničil@[ao_cs] jsi konvertér!,Du har ødelagt konverteren!,Du hast den Konverter zerstört!,,Vi detruis la konvertilon!,¡Has destruido el convertidor!,¡Destruiste el convertidor!,Olet tuhonnut muuntajan!,Vous avez détruit le convertisseur!,Elpusztítottad a konvertálót!,Hai distrutto i Convertitori!,コンバーターを破壊した!,개조 장치를 파괴했다!,Je hebt de Converter vernietigd!,Du har tilintetgjort Omformeren!,Zniszczył@[irreg_3_pl] Transformator!,Você destruiu o Conversor!,Destruiste o Transformador!,Ai distrus Convertorul!,Преобразователь уничтожен!,Претварач је уништен!,Dönüştürücüyü yok ettiniz! +",囚人を解放した!,죄수들을 탈옥시켰다!,Je hebt de gevangenen bevrijd!,Du har befridd fangene!,Uwolnił@[irreg_3_pl] więźniów,Você liberou os prisioneiros!,Libertaste os prisioneiros!,Ai eliberat prizonierii!,Пленники освобождены!,Затвореници су ослобођени!,Du har befriat fångarna!,Mahkumları serbest bıraktınız!,Ви звільнили в'язнів! +You've destroyed the Converter!,TXT_DESTROYED_CONVERTER,,,,Zničil@[ao_cs] jsi konvertér!,Du har ødelagt konverteren!,Du hast den Konverter zerstört!,,Vi detruis la konvertilon!,¡Has destruido el convertidor!,¡Destruiste el convertidor!,Olet tuhonnut muuntajan!,Vous avez détruit le convertisseur!,Elpusztítottad a konvertálót!,Hai distrutto i Convertitori!,コンバーターを破壊した!,개조 장치를 파괴했다!,Je hebt de Converter vernietigd!,Du har tilintetgjort Omformeren!,Zniszczył@[irreg_3_pl] Transformator!,Você destruiu o Conversor!,Destruiste o Transformador!,Ai distrus Convertorul!,Преобразователь уничтожен!,Претварач је уништен!,Du har förstört omvandlaren!,Dönüştürücüyü yok ettiniz!,Ви знищили конвертер! Congratulations! You have completed the training area,TXT_COMPLETED_TRAINING,,,,Gratulujeme! Dokončil@[ao_cs] jsi tréninkový areál,Tillykke med det! Du har gennemført træningsområdet,Gratuliere! Du hast das Trainingsprogramm bestanden.,,Gratulon! Vi kompletigis la trejnejon,"¡Enhorabuena! Has completado la zona de entrenamiento","¡Muy bien! Completaste -la zona de entrenamiento",Onnittelut! Olet suorittanut koulutusalueen,Félicitations! Vous êtes arrivé à la fin de l'entraînement.,Gratulálok! Elvégezted a gyakorló területet.,Congratulazioni! Hai completato l'area di addestramento,おめでとう!トレーニングエリアを完了した,훈련 코스를 마쳤다. 능력치 업!,Gefeliciteerd! Je hebt de training voltooid.,Gratulerer! Du har fullført treningsområdet,Gratulacje! Ukończył@[irreg_3_pl] trening,Parabéns! Você completou a área de treinamento,Parabéns! Completaste a área de treino,Felicitări! Ai încheiat cu zona de antrenament,Браво! Ты прошёл тренировку,Честитке! Завршио си тренинг подручје,Tebrikler! Eğitim alanını tamamladınız -You've blown up the Crystal,TXT_QUEST_14,,,,Odpálil@[ao_cs] jsi krystal,Du ødelagde krystallen.,Du hast den Kristall zerstört.,,Vi eksplodigis la kristalon,Has volado el cristal,Volaste el cristal,Olet räjäyttänyt kristallin,Vous avez explosé le cristal!,Szétrobbantottad a kristályt,Hai fatto esplodere il Cristallo,クリスタルを爆破した,수정체를 파괴했다,Je hebt de Crystal opgeblazen.,Du har sprengt krystallen,Wysadził@[irreg_3_pl] Kryształ,Você explodiu o cristal,Explodiste o cristal,Ai aruncat în aer Cristalul,Кристалл взорван,Дигао си у ваздух кристал,Kristali havaya uçurdun. -You've blown up the Gates,TXT_QUEST_16,,,,Odpálil@[ao_cs] jsi brány,Du åbnede portene.,Du hast die Tore geöffnet.,,Vi detruis la pordegojn,Has destruido las puertas,Destruiste las puertas,Olet räjäyttänyt portit,Vous avez explosé les portes!,A levegőbe repítetted a kapukat,Hai fatto esplodere i Cancelli,ゲートを爆破した,성문을 파괴해서 열었다,Je hebt de Gates opgeblazen.,Du har sprengt portene,Wysadził@[irreg_3_pl] Bramy,Você explodiu as portões,Explodiste os portões,Ai aruncat în aer Porțile,Ворота взорваны,Дигао си у ваздух капију,Kapıları havaya uçurdun. -You've blown up the Computer,TXT_QUEST_27,,,,Odpálil@[ao_cs] jsi počítač,Du har ødelagt computeren.,Du hast den Computer zerstört.,,Vi detruis la komputilon,Has destruido el Ordenador,Destruiste la computadora,Olet räjäyttänyt tietokoneen,Vous avez explosé l'ordinateur!,Felrobbantottad a számítógépet,Hai fatto esplodere il Computer,コンピューターを爆破した,컴퓨터를 파괴했다,Je hebt de computer opgeblazen.,Du har sprengt Datamaskinen,Wysadził@[irreg_3_pl] Komputer,Você explodiu o computador,Explodiste o computador,Ai aruncat în aer Calculatorul,Компьютер взорван,Дигао си у ваздух компјутер,Bilgisayarı havaya uçurdun. -You killed the Bishop!,TXT_KILLED_BISHOP,,,,Zabil@[ao_cs] jsi Biskupa!,Du har dræbt biskoppen!,Du hast den Bischof getötet.,,Vi mortigis la Episkopon!,¡Has matado al Arzobispo!,¡Mataste al Arzobispo!,Olet tappanut Piispan!,Vous avez tué l'évèque!,Megölted a Püspököt!,Hai ucciso il Vescovo!,ビショップを殺した!,비숍을 사살했다!,Je hebt de bisschop vermoord!,Du har drept Biskopen!,Zabił@[irreg_3_pl] Biskupa!,Você matou o Bispo!,Mataste o Bispo!,Ai omorât Episcopul!,Епископ убит!,Епископ је мртав!,Piskoposu öldürdün! -You've killed the Oracle!,TXT_KILLED_ORACLE,,,,Zabil@[ao_cs] jsi Věštce!,Du har dræbt Oraklet!,Du hast das Orakel getötet,,Vi mortigis la Orakolon!,¡Has matado al Oráculo!,¡Mataste al Oráculo!,Olet tappanut Oraakkelin!,Vous avez tué l'oracle!,Megölted az Orákulumot!,Hai ucciso l'Oracolo!,オラクルの予言を覆した!,오라클의 음모를 막았다!,Je hebt het Orakel vermoord!,Du har drept Oraklet!,Zabił@[irreg_3_pl] Wyrocznię!,Você matou o Oráculo!,Mataste o Oráculo,Ai omorât Oracolul!,Оракул убит!,Пророк је мртав!,Kahini öldürdün! -You killed Macil!,TXT_KILLED_MACIL,,,,Zabil@[ao_cs] jsi Macila!,Du har dræbt Macil!,Du hast Macil getötet.,,Vi mortigis Macil!,¡Has matado a Macil!,¡Mataste a Macil!,Tapoit Macilin!,Vous avez tué Macil!,Megölted Macilt!,Hai ucciso Macil!,マシルを討ち取った!,마실을 처단했다!,Je hebt Macil vermoord!,Du har drept Macil!,Zabił@[irreg_3_pl] Macila!,Você matou o Macil!,Mataste Macil!,L-ai omorât pe Macil!,Мэйсил убит!,Мејсил је мртав!,Macil'i öldürdün! -You've killed the Loremaster!,TXT_KILLED_LOREMASTER,,,,Zabil@[ao_cs] jsi Dějepisce!,Du har dræbt Loremesteren!,Du hast den Wissensmeister getötet!,,Vi mortigis la Scimajstro!,¡Has matado al Maestro del Conocimiento!,¡Mataste al Maestro del Conocimiento!,Olet tappanut Oppi-Isän!,Vous avez tué le Maitre des traditions!,Megölted a Tudóst!,Hai ucciso il Sapiente!,ロアマスターを吊り上げた!,로어마스터의 목숨에 종지부를 찍었다!,Je hebt de Kennismeester vermoord!,Du har drept Loremaster!,Zabił@[irreg_3_pl] Mędrca!,Você matou o Mestre do Conhecimento!,Mataste o Mestre do Conhecimento!,L-ai omorât pe Maestrul Cunoștințelor!,Хранитель мудрости убит!,Чувара мудрости је мртав!,Loremaster'ı öldürdün! +la zona de entrenamiento",Onnittelut! Olet suorittanut koulutusalueen,Félicitations! Vous êtes arrivé à la fin de l'entraînement.,Gratulálok! Elvégezted a gyakorló területet.,Congratulazioni! Hai completato l'area di addestramento,おめでとう!トレーニングエリアを完了した,훈련 코스를 마쳤다. 능력치 업!,Gefeliciteerd! Je hebt de training voltooid.,Gratulerer! Du har fullført treningsområdet,Gratulacje! Ukończył@[irreg_3_pl] trening,Parabéns! Você completou a área de treinamento,Parabéns! Completaste a área de treino,Felicitări! Ai încheiat cu zona de antrenament,Браво! Ты прошёл тренировку,Честитке! Завршио си тренинг подручје,Grattis! Du har avslutat träningsområdet,Tebrikler! Eğitim alanını tamamladınız,Вітаю! Ви пройшли курс тренувань +You've blown up the Crystal,TXT_QUEST_14,,,,Odpálil@[ao_cs] jsi krystal,Du ødelagde krystallen.,Du hast den Kristall zerstört.,,Vi eksplodigis la kristalon,Has volado el cristal,Volaste el cristal,Olet räjäyttänyt kristallin,Vous avez explosé le cristal!,Szétrobbantottad a kristályt,Hai fatto esplodere il Cristallo,クリスタルを爆破した,수정체를 파괴했다,Je hebt de Crystal opgeblazen.,Du har sprengt krystallen,Wysadził@[irreg_3_pl] Kryształ,Você explodiu o cristal,Explodiste o cristal,Ai aruncat în aer Cristalul,Кристалл взорван,Дигао си у ваздух кристал,Du har sprängt kristallen.,Kristali havaya uçurdun.,Ви підірвали кристал +You've blown up the Gates,TXT_QUEST_16,,,,Odpálil@[ao_cs] jsi brány,Du åbnede portene.,Du hast die Tore geöffnet.,,Vi detruis la pordegojn,Has destruido las puertas,Destruiste las puertas,Olet räjäyttänyt portit,Vous avez explosé les portes!,A levegőbe repítetted a kapukat,Hai fatto esplodere i Cancelli,ゲートを爆破した,성문을 파괴해서 열었다,Je hebt de Gates opgeblazen.,Du har sprengt portene,Wysadził@[irreg_3_pl] Bramy,Você explodiu as portões,Explodiste os portões,Ai aruncat în aer Porțile,Ворота взорваны,Дигао си у ваздух капију,Du har sprängt portarna.,Kapıları havaya uçurdun.,Ви підірвали ворота +You've blown up the Computer,TXT_QUEST_27,,,,Odpálil@[ao_cs] jsi počítač,Du har ødelagt computeren.,Du hast den Computer zerstört.,,Vi detruis la komputilon,Has destruido el ordenador,Destruiste la computadora,Olet räjäyttänyt tietokoneen,Vous avez explosé l'ordinateur!,Felrobbantottad a számítógépet,Hai fatto esplodere il Computer,コンピューターを爆破した,컴퓨터를 파괴했다,Je hebt de computer opgeblazen.,Du har sprengt Datamaskinen,Wysadził@[irreg_3_pl] Komputer,Você explodiu o computador,Explodiste o computador,Ai aruncat în aer Calculatorul,Компьютер взорван,Дигао си у ваздух компјутер,Du har sprängt datorn.,Bilgisayarı havaya uçurdun.,Ви підірвали комп'ютер +You killed the Bishop!,TXT_KILLED_BISHOP,,,,Zabil@[ao_cs] jsi Biskupa!,Du har dræbt biskoppen!,Du hast den Bischof getötet.,,Vi mortigis la Episkopon!,¡Has matado al Obispo!,¡Mataste al Obispo!,Olet tappanut Piispan!,Vous avez tué l'évèque!,Megölted a Püspököt!,Hai ucciso il Vescovo!,ビショップを殺した!,비숍을 사살했다!,Je hebt de bisschop vermoord!,Du har drept Biskopen!,Zabił@[irreg_3_pl] Biskupa!,Você matou o Bispo!,Mataste o Bispo!,Ai omorât Episcopul!,Епископ убит!,Епископ је мртав!,Du har dödat biskopen!,Piskoposu öldürdün!,Єпископа вбито! +You've killed the Oracle!,TXT_KILLED_ORACLE,,,,Zabil@[ao_cs] jsi Věštce!,Du har dræbt Oraklet!,Du hast das Orakel getötet,,Vi mortigis la Orakolon!,¡Has matado al Oráculo!,¡Mataste al Oráculo!,Olet tappanut Oraakkelin!,Vous avez tué l'oracle!,Megölted az Orákulumot!,Hai ucciso l'Oracolo!,オラクルの予言を覆した!,오라클의 음모를 막았다!,Je hebt het Orakel vermoord!,Du har drept Oraklet!,Zabił@[irreg_3_pl] Wyrocznię!,Você matou o Oráculo!,Mataste o Oráculo,Ai omorât Oracolul!,Оракул убит!,Пророк је мртав!,Du har dödat oraklet!,Kahini öldürdün!,Оракула вбито! +You killed Macil!,TXT_KILLED_MACIL,,,,Zabil@[ao_cs] jsi Macila!,Du har dræbt Macil!,Du hast Macil getötet.,,Vi mortigis Macil-on!,¡Has matado a Macil!,¡Mataste a Macil!,Tapoit Macilin!,Vous avez tué Macil!,Megölted Macilt!,Hai ucciso Macil!,マシルを討ち取った!,마실을 처단했다!,Je hebt Macil vermoord!,Du har drept Macil!,Zabił@[irreg_3_pl] Macila!,Você matou o Macil!,Mataste Macil!,L-ai omorât pe Macil!,Мэйсил убит!,Мејсил је мртав!,Du har dödat Macil!,Macil'i öldürdün!,Масіла вбито! +You've killed the Loremaster!,TXT_KILLED_LOREMASTER,,,,Zabil@[ao_cs] jsi Dějepisce!,Du har dræbt Loremesteren!,Du hast den Wissensmeister getötet!,,Vi mortigis la Folkloriston!,"¡Has matado al +Maestro del Conocimiento!","¡Mataste al +Maestro del Conocimiento!",Olet tappanut Oppi-Isän!,Vous avez tué le Maitre des traditions!,Megölted a Tudóst!,Hai ucciso il Sapiente!,ロアマスターを吊り上げた!,로어마스터의 목숨에 종지부를 찍었다!,Je hebt de Kennismeester vermoord!,Du har drept Loremaster!,Zabił@[irreg_3_pl] Mędrca!,Você matou o Mestre do Conhecimento!,Mataste o Mestre do Conhecimento!,L-ai omorât pe Maestrul Cunoștințelor!,Хранитель мудрости убит!,Чувара мудрости је мртав!,Du har dödat Läromästaren!,Loremaster'ı öldürdün!,Хранителя мудрості вбито! You fool! You've set off the alarm.,TXT_YOUFOOL,,,,Blázne! Spustil@[ao_cs] jsi alarm!,Dit fjols! Du har udløst alarmen.,Du Trottel! Du hast den Alarm ausgelöst.,,"Stultulo! Vi ekigis la alarmon.","¡Insensat@[ao_esp]! Has activado la alarma.","¡Tont@[ao_esp]! -Activaste la alarma.",Sinä mieletön! Olet laukaissut hälytyksen.,Vous êtes fou! Vous avez activé l'alarme!,Te barom! Beindítottad a riasztót.,Stolto! Hai fatto scattare l'allarme.,バカな真似を! 警報を鳴らしてしまった。,어리석은 것! 알람이 작동되었다고!,Jij dwaas! Je hebt het alarm laten afgaan.,Din idiot! Du har utløst alarmen.,Głupcze! Włączył@[irreg_3_pl] alarm!,Seu idiota! Você ativou o alarme.,Idiota! Ativaste o alarme.,Nesăbuitule! Ai declanșat alarma!,Глупец. Ты привёл в действие сигнализацию!,Будало! Активирао си аларм.,Seni aptal! Alarmı çalıştırdın. +Activaste la alarma.",Sinä mieletön! Olet laukaissut hälytyksen.,Vous êtes fou! Vous avez activé l'alarme!,Te barom! Beindítottad a riasztót.,Stolto! Hai fatto scattare l'allarme.,バカな真似を! 警報を鳴らしてしまった。,어리석은 것! 알람이 작동되었다고!,Jij dwaas! Je hebt het alarm laten afgaan.,Din idiot! Du har utløst alarmen.,Głupcze! Włączył@[irreg_3_pl] alarm!,Seu idiota! Você ativou o alarme.,Idiota! Ativaste o alarme.,Nesăbuitule! Ai declanșat alarma!,Глупец. Ты привёл в действие сигнализацию!,Будало! Активирао си аларм.,Din idiot! Du har utlöst larmet.,Seni aptal! Alarmı çalıştırdın.,Дурень! Ти активував тривогу. You're dead! You set off the alarm.,TXT_YOUREDEAD,,,,Jsi mrtv@[adj_cs]! Spustil@[ao_cs] jsi alarm!,Du er død! Du udløste alarmen.,Du bist tot. Du hast den Alarm ausgelöst.,,"Vi estas mortinta! Vi ekigis la alarmon.","¡Estás muert@[ao_esp]! Has activado la alarma.","¡Estás muert@[ao_esp]! -Activaste la alarma.",Sinä kuolet! Laukaisit hälytyksen.,Vous êtes mort! Vous avez activé l'alarme!,Beindult a riasztó. Halott vagy!,Sei morto! L'allarme è scattato.,絶望的だ! 警報を鳴らしてしまった。,알람이 작동되었다. 넌 죽었어!,Je bent dood! Je hebt het alarm laten afgaan.,Du er død! Du utløste alarmen.,Już nie żyjesz! Włączył@[irreg_3_pl] alarm!,Você está mort@[ao_ptb]! Você ativou o alarme.,Estás mort@[ao_ptb]! Ativaste o alarme.,Ești mort! AI declanșat alarma!,Ты поднял тревогу! Готовься к смерти!,Активирао си аларм. Спреми се да умреш!,Sen öldün! Alarmı çalıştırdın. -You seem to have enough!,TXT_HAVEENOUGH,,,,Ty už máš přece dost!,Du ser ud til at have nok!,Du scheinst genug zu haben.,,Vi ŝajnas havi sufiĉe!,¡Se ve que tienes suficiente!,,Sinulla näyttää olevan tarpeeksi!,Vous avez l'air d'en avoir assez!,Úgy néz ki eleged van már!,Sembri averne abbastanza!,十分に持ち合わせている!,충분히 가진 것 같은데?,Je lijkt genoeg te hebben!,Du har visst fått nok!,"Wydaje się, że już ci wystarczy!",Você parece ter o suficiente!,Pareces ter o suficiente!,Pare că ai destule!,"Кажется, тебе хватит!",Изгледа да ти је доста!,Yeterince var gibi görünüyor! -Go away!,TXT_GOAWAY,,,,Jdi pryč!,Gå væk!,Verschwinde!,,Foriru!,¡Lárgate!,,Häivy!,Allez-vous en!,Takarodj!,Vattene via!,逃げ出せ!,저리 가!,Ga weg!,Forsvinn!,Idź stąd!,Vá embora!,Vai-te embora!,Pleacă!,Уходи!,Одлази!,Git başımdan! -Incoming Message...,TXT_COMM0,,,,Příchozí zpráva...,Indkommende besked...,Nachricht erhalten...,,Alvenas mesaĝo...,Mensaje entrante...,,Vastaantuleva viesti...,Message reçu.,Bejövő Üzenet...,Messaggio in arrivo...,メッセージが届いた...,메시지가 옴...,Inkomend bericht....,Innkommende melding...,Nadchodzi wiadomość...,Recebendo Mensagem...,A Receber Mensagem...,Mesaj în intrare...,Входящее сообщение...,Наилази порука...,Gelen Mesaj... -Incoming Message from BlackBird...,TXT_COMM1,,,,Příchozí zpráva od Straky...,Indkommende besked fra BlackBird...,Nachricht von Blackbird erhalten...,,Alvenas mesaĝo de BlackBird...,Mensaje entrante de BlackBird...,,Vastaantuleva viesti Blackbirdiltä...,Message reçu de BlackBird,Bejövő Üzenet Feketerigótól...,Messaggio in arrivo da Blackbird...,ブラックバードからのメッセージが届いた...,블랙버드로부터 메시지가 옴...,Inkomend bericht van BlackBird....,Innkommende melding fra BlackBird...,Nadchodzi wiadomość od BlackBird...,Recebendo Mensagem de BlackBird...,A Receber Mensagem de BlackBird...,Mesaj în intrare de la BlackBird...,Входящее сообщение от «Чёрного дрозда»...,Наилази порука од Црне птице....,Gelen Mesaj... -Find help,TXT_FINDHELP,,,,Najdi pomoc.,Find hjælp,Finde Hilfe,,Trovu helpon,Busca ayuda,,Etsi apua,Trouvez de L'aide,Keress segítséget,Trova aiuto,助けを探せ,도움말,Zoek hulp,Finn hjelp,Znajdź pomoc,Procure ajuda,Procura ajuda,Găsește ajutor,Найди помощь,Нађи помоћ,Yardım bul -for %u,TXT_TRADE,As in for %u amount of money.,,,za %u zlatých,til %u,für %u,,kontraŭ %u da oro.,por %u de oro.,,hintaan %u,pour %u,%u számára,per %u,%u ゴールド,(가격: %u),voor %u,til %u,za %u,por %u,,pentru %u,за %u,за %u,için %u -,,Chex Quest,,,,,,,,,,,,,,,,,,,,,,,, -,,Pickups,,,,,,,,,,,,,,,,,,,,,,,, -Picked up the Chex(R) Armor.,GOTCHEXARMOR,,,Picked up the Chex(R) Armour.,Sebráno Chex(R) brnění.,Hentede Chex(R) Rustning.,Du hast die Chex(R) Rüstung genommen,,Prenis la Chex(R)-kirason.,Recogiste la Armadura Chex(R).,,Poimit Chex(R)-panssarin.,Vous avez pris l'armure Chex(R).,Felvettél egy Chex(R) páncélt.,Raccolta un'Armatura Chex(R).,チェックス(R)アーマー をてにいれた。,첵스(R) 갑옷 획득.,Je hebt het Chex(R) harnas opgepakt.,Plukket opp Chex(R) Armor.,Zebrano Pancerz Chex(R).,Pegou uma Armadura Chex(R).,Apanhaste uma Armadura Chex(R).,Ai ridicat Armura Chex(R).,Получена Chex(R)-броня.,Покупио си Чех оклоп.,Chex(R) Zırhı'nı aldım. -Picked up the Super Chex(R) Armor!,GOTSUPERCHEXARMOR,,,Picked up the Super Chex(R) Armour!,Sebráno Super Chex(R) brnění!,Hentede Super Chex(R) Rustning!,Du hast die Superchex(R)Rüstung genommen!,,Prenis la superan Chex(R)-kirason!,¡Recogiste la Súper-Armadura Chex(R)!,,Poimit Super-Chex(R)-panssarin!,Vous avez pris la super armure Chex(R)!,Felvettél egy szuper Chex(R) páncélt!,Raccolta la Super Armatura Chex(R)!,スーパーチェックス(R)アーマー をてにいれた。,슈퍼 첵스(R) 갑옷 획득!,Je hebt het Super-Chex(R) harnas opgehaald!,Plukket opp Super Chex(R) Armor!,Zebrano Super Pancerz Chex(R)!,Pegou uma Super Armadura Chex(R)!,Apanhaste uma Super Armadura Chex(R)!,Ai ridicat Super Armura Chex(R)!,Получена Chex(R)-сверхброня!,Покупио си Супер Чех оклоп.,Süper Chex(R) Zırhı'nı aldı! -Picked up a glass of water.,GOTWATER,,,,Sebrána sklenice vody.,Samlede et glas vand op.,Du hast ein Glas Wasser genommen.,,Prenis glason de akvo.,Recogiste un vaso de agua.,,Poimit vesilasin.,Vous avez pris un verre d'eau.,Felvettél egy pohár vizet.,Raccolto un bicchiere d'acqua.,コップいっぱいの みずをひろった。,물 한 컵 섭취.,Je hebt een glas water opgepakt.,Hentet et glass vann.,Zebrano szklankę wody.,Pegou um copo d'água.,Apanhaste um copo de água.,Ai ridicat un pahar cu apă.,Получен стакан воды.,Покупио си чашу воде,Bir bardak su aldım. -Picked up slime repellent.,GOTREPELLENT,,,,Sebrán repelent proti slizu.,Hentede slimafvisende middel.,Du hast das Schleimabwehrmittel genommen.,,Prenis mukforigilon.,Recogiste un repelente de baba.,,Poimit limakarkotteen.,Vous avez pris de la chaux répulsive.,Felvettél egy nyálkataszítót.,Raccolto del repellente allo slime.,スライム はんぱつざい をひろった。,오물 방수제 획득.,Je hebt de slijmafstotende stof opgepakt.,Plukket opp slime repellent.,Zebrano odstraszacz szlamu.,Pegou repelente de gosma.,Apanhaste repelente de gosma.,Ai ridicat respingătorul de mâzga.,Получен репеллент от слизи.,Покупио си одбијаш љигавца.,Balçık kovucu aldım. -Supercharge Breakfast!,GOTBREAKFAST,,,,Supervýživná snídaně!,Supercharge Morgenmad!,Überladenes Frühstück!,,Ŝargega Matenmanĝon!,¡Desayuno supercargado!,,Superaamiaislatinki!,Petit-déjeuner superchargé!,Szupertöltött Reggeli!,Colazione da supercarica!,ちょうしょく スーパーチャージ!,힘찬 아침식사 섭취!,Overbelast ontbijt!,Superladet frokost!,Supernaładowane Śniadanie!,Super Café da Manhã!,Super Pequeno-Almoço!,Superîncărcătură Mic Dejun!,Завтрак из сверхзаряда!,Супер-напуњен доручак.,Süper Şarjlı Kahvaltı! -Picked up a blue key.,GOTCBLUEKEY,,,,Sebrán modrý klíč.,Samlede en blå nøgle op.,Du hast einen blauen Schlüssel genommen.,,Prenis bluan ŝlosilon.,Recogiste una llave azul.,,Poimit sinisen avaimen.,Vous avez pris une clé bleue.,Felvettél egy kék kulcsot.,Raccolta una chiave blu.,あお のかぎ をひろった。,파란색 열쇠 획득.,Je hebt een blauwe sleutel opgepakt.,Plukket opp en blå nøkkel.,Zebrano niebieski klucz.,Pegou a chave azul.,Apanhaste a chave azul.,Ai ridicat o cheie albastră.,Получен синий ключ.,Покупио си плави кључ.,Mavi bir anahtar aldı. -Picked up a yellow key.,GOTCYELLOWKEY,,,,Sebrán žlutý klíč.,Samlede en gul nøgle op.,Du hast einen gelben Schlüssel genommen.,,Prenis ruĝan ŝlosilon.,Recogiste una llave amarilla.,,Poimit keltaisen avaimen.,Vous avez pris une clé jaune.,Felvettél egy sárga kulcsot.,Raccolta una chiave gialla.,きいろ のかぎ をひろった。,노란색 열쇠 획득.,Je hebt een gele sleutel opgepakt.,Plukket opp en gul nøkkel.,Zebrano żółty klucz.,Pegou a chave amarela.,Apanhaste a chave amarela.,Ai ridicat o cheie galbenă.,Получен жёлтый ключ.,Покупио си жути кључ.,Sarı bir anahtar aldı. -Picked up a red key.,GOTCREDKEY,,,,Sebrán červený klíč.,Samlede en rød nøgle op.,Du hast einen roten Schlüssel genommen.,,Prenis flavan ŝlosilon.,Recogiste una llave roja.,,Poimit punaisen avaimen.,Vous avez pris une clé rouge.,Felvettél egy piros kulcsot.,Raccolta una chiave rossa.,あか のかぎ をひろった。,빨간색 열쇠 획득.,Je hebt een rode sleutel opgepakt.,Plukket opp en rød nøkkel.,Zebrano czerwony klucz.,Pegou a chave vermelha.,Apanhaste a chave vermelha.,Ai ridicat o cheie roșie.,Получен красный ключ.,Покупио си црвени кључ.,Kırmızı bir anahtar aldı. -Picked up a bowl of fruit.,GOTFRUIT,,,,Sebrána mísa s ovocem.,Samlede en skål med frugt op.,Du hast eine Obstschale genommen.,,Prenis bovlon de fruktoj.,Recogiste un tazón de fruta.,,Poimit hedelmäkulhon.,Vous avez pris un bol de fruits.,Felvettél egy tál gyümölcsöt.,Raccolto un vassoio di frutta.,フルーツのボウル をひろった。,과일 한 그릇 섭취.,Je hebt een fruitschaal opgepakt.,Plukket opp en bolle med frukt.,Zebrano miskę owoców.,Pegou uma tigela de frutas.,Apanhaste uma taça com fruta.,Ai ridicat un bol de fructe.,Получена тарелка с фруктами.,Покупио си чинију воћа.,Bir kase meyve al. -Vegetables are REALLY good for you!,GOTVEGETABLESNEED,,,,Zelenina je VELMI zdravá!,Grøntsager er VIRKELIG gode for dig!,Gemüse ist RICHTIG gut für dich!,,Legomoj estas TRE bonaj por vi!,¡Las verduras son REALMENTE buenas para ti!,,Vihannekset ovat TOSI terveellisiä!,Les légumes sont VRAIMENT bons pour vous!,A zöldségek NAGYON jót tesznek neked!,La verdura ti fa DAVVERO bene!,いま とってもひつような やさいのボウルだ!,채소의 건강한 영양분이 독 기운을 없앴습니다!,Groenten zijn echt goed voor je!,Grønnsaker er VIRKELIG bra for deg!,Warzywa są BARDZO dobre dla ciebie!,Vegetais fazem MUITO bem para você!,Os Vegetais são MUITO bons para ti!,Legumele sunt FOARTE bune pentru tine!,Овощи ОЧЕНЬ полезны для здоровья!,Поврће је ЈАКО добро за тебе!,Sebzeler sizin için GERÇEKTEN iyidir! -Picked up a bowl of vegetables.,GOTVEGETABLES,,,,Sebrána mísa se zeleninou.,Samlede en skål med grøntsager op.,Du hast eine Gemüseschale genommen.,,Prenis bovlon de legomoj.,Recogiste un tazón de verduras.,,Poimit vihannesvadin.,Vous avez pris un bol de légumes.,Felvettél egy tál zöldséget.,Raccolto un vassoio di verdura.,やさいのボウル をひろった。,채소 한 그릇 섭취.,Je hebt een kom groenten opgepakt.,Plukket opp en bolle med grønnsaker.,Zebrano miskę warzyw.,Pegou uma tigela de vegetais.,Apanhaste uma tigela com vegetais.,Ai ridicat un bol de legume.,Получена тарелка с овощами.,Покупио си чинију поврћа.,Bir kase sebze aldı. -Found a Slime-Proof Suit,GOTSLIMESUIT,,,,Nalezen slizu odolný oblek.,Fandt et slim-sikret jakkesæt,Du hast einen Schleimbeständigen Anzug gefunden,,Trovis mukimunan kompleton.,Encontraste un traje a prueba de baba.,,Löysit limaapitävän puvun,Combinaison pare-gelée,Felvettél egy nyálkaálló védőruhát,Raccolto un vestito a prova di slime,たい スライム スーツ をてにいれた。,오물 보호복 사용.,Je hebt een slijtvast pak opgepakt.,Fant en slimsikker drakt,Znaleziono Szlamoodporny Kombinezon,Achou um Traje Anti-Gosma,Apanhaste um Fato Anti-Gosma.,Ai ridicat un Costum Rezistent la Mâzgă,Получен противослизневый костюм,Нашо си љигаво-отпорано одело.,Balçık Geçirmez Takım Elbise Buldum -Found a Computer Area Map,GOTCHEXMAP,,,,Nalezena počítačová mapa oblasti.,Fandt et kort over et computerområde,Du hast eine Computerkarte gefunden,,Trovis komputilan regionmapon.,Encontraste un mapa computarizado del área.,,Löysit alueen tietokonekartan,Vous avez trouve une carte informatique de la zone.,Felvettél egy Számítógépes Térképet,Trovata una mappa computerizzata,コンピューターエリアマップ をてにいれた。,컴퓨터 지도 사용.,Je hebt een computerkaart opgepakt.,Fant et datamaskinkart,Znaleziono Komputerową Mapę Obszaru,Achou um Mapa Computadorizado,Apanhaste um Mapa Digital.,Ai ridicat o Hartă Generată pe Calculator a Zonei.,Получена компьютерная карта местности,Нашао компјутерку мапу окружења,Bilgisayar Alanı Haritası Bulundu -Picked up a mini zorch recharge.,GOTZORCHRECHARGE,,,,Sebrán minibzukový náboj.,Samlede en mini zorch-opladning op.,Du hast eine Minizorcher-Ladung genommen.,,Prenis zorĉreŝargeton.,Recogiste una recarga de mini zorch.,,Poimit minizorchlatauksen.,Vous avez pris une mini recharge zorch.,Felvettél egy Mini Zorker Újratöltőt,Raccolta una ricarica di mini zorch.,ミニゾーチ リチャージ をひろった。,소형 저치 전지 획득.,Je hebt een minizorcherlading opgepakt.,Plukket opp en mini zorch-opplading.,Zebrano mini ładunek zorch.,Pegou recarga para mini zorch.,Apanhaste uma recarga para o mini zorch.,Ai ridicat o mini încărcătură pentru zorch.,Получена зарядка для мини-Зорчера.,Покупио си мини зорч пуњач.,Mini bir Zorch şarjı aldım. -Picked up a mini zorch pack.,GOTMINIZORCHPACK,,,,Sebrán minibzukový balík.,Afhentede en mini zorch-pakke.,Du hast ein Minizorcher-Ladepaket genommen.,,Prenis zorĉpaketon,Recogiste un paquete de mini zorch.,,Poimit minizorchpaketin.,Vous avez pris un pack de mini recharges zorch.,Felvettél egy Mini Zorker Csomagot,Raccolta una scatola di mini zorch.,ミニゾーチ パック をひろった。,저치 전지 박스 획득.,Je hebt een pakket met minizorcherladingen opgepakt.,Plukket opp en mini zorch-pakke.,Zebrano mini paczkę zorch.,Pegou um pacote de recargas de mini zorch.,Apanhaste um pagcote de recargas para o mini zorch.,Ai ridicat un mini patchet de încărcătură pentru zorch.,Получена батарея для мини-Зорчера.,Покупио си мини зорч пакет.,Mini bir Zorch paketi aldım. -Picked up a zorch propulsor recharge.,GOTPROPULSORRECHARGE,,,,Sebrán náboj pro bzukový propulzor.,Afhentede en zorch propulsor opladning.,Du hast eine Propeller-Ladung genommen.,,Prenis zorĉpropulsilo-reŝargon.,Recogiste una recarga de propulsor de zorch.,,Poimit zorchtyöntimen latauksen.,Vous avez pris une recharge propulseur zorch.,Felvettél egy Zork Elhárító Újratöltőt,Raccolta una ricarica di zorch a propulsione.,ゾーチプロパルサーリチャージ をひろった。,저치 추진료 획득.,Je hebt een propulsorlading opgepakt.,Plukket opp en zorch propulsor-opplading.,Zebrano ładunek do pędnika zorch.,Pegou recarga para propulsor de zorch.,Apanhaste recarga para o propulsor de zorch.,Ai ridicat o încărcătură pentru acceleratorul zorch.,Получена зарядка для ускорителя Зорча.,Покупио си зорч погонски пуњач.,Bir Zorch itici şarjı aldı. -Picked up a zorch propulsor pack.,GOTPROPULSORPACK,,,,Sebrán balík pro bzukový propulzor.,Afhentede en zorch propulsorpakke.,Du hast ein Propeller-Ladepaket genommen.,,Prenis zorĉpropulsilo-pakon.,Recogiste un paquete de propulsor de zorch.,,Poimit zorchtyöntimen paketin.,Vous avez pris un paquet propulseur zorch.,Felvettél egy Zork Elhárító Csomagot,Raccolta una scatola di zorch a propulsione.,ゾーチプロパルサーパック をひろった。,저치 추진 팩 획득.,Je hebt een pakket met propulsorladingen opgepakt.,Plukket opp en zorch fremdriftspakke.,Zebrano paczkę pędnika zorch.,Pegou um pacote de recargas para propulsor de zorch.,Apanhaste um pacote de recargas para o propulsor de zorch,Ai ridicat un pachet de baterii pentru acceleratorul zorch.,Получена батарея для ускорителя Зорча.,Покупио си зорч погонски пакет.,Bir Zorch itici paketi aldı. -Picked up a phasing zorcher recharge,GOTPHASINGZORCHERRECHARGE,,,,Sebrán náboj pro fázovací bzukr.,Afhentede en zorcher-opladning til faseopladning.,Du hast eine Phasenzorcher-Ladung genommen.,,Prenis fluktuantzorĉilo-reŝargon.,Recogiste una recarga de zorch de fase.,,Poimit vaiheiszorcherin latauksen.,Vous avez pris une recharge zorch phasée.,Felvettél egy Fázis Zorker Újratöltőt,Raccolta una ricarica per zorcher a phasing,フェイシング ゾーチャーリチャージ をひろった。,저치 전자 충전기 획득.,Je hebt een phasenzorcherlading opgepakt.,Plukket opp en fasing zorcher oppladning.,Zebrano ładunek do fazowego zorchera.,Pegou recarga para zorcher fásico.,Apanhaste recarga para o zorcher fásico,Ai ridicat o încărcătură fazată pentru zorcher,Получена зарядка для фазерного Зорчера.,Покупио си фазни зорчер пуњач.,Bir faz zorcher şarjı aldı +Activaste la alarma.",Sinä kuolet! Laukaisit hälytyksen.,Vous êtes mort! Vous avez activé l'alarme!,Beindult a riasztó. Halott vagy!,Sei morto! L'allarme è scattato.,絶望的だ! 警報を鳴らしてしまった。,알람이 작동되었다. 넌 죽었어!,Je bent dood! Je hebt het alarm laten afgaan.,Du er død! Du utløste alarmen.,Już nie żyjesz! Włączył@[irreg_3_pl] alarm!,Você está mort@[ao_ptb]! Você ativou o alarme.,Estás mort@[ao_ptb]! Ativaste o alarme.,Ești mort! AI declanșat alarma!,Ты поднял тревогу! Готовься к смерти!,Активирао си аларм. Спреми се да умреш!,Du är död! Du utlöste larmet.,Sen öldün! Alarmı çalıştırdın.,Ти труп! Тривогу активовано. +You seem to have enough!,TXT_HAVEENOUGH,,,,Ty už máš přece dost!,Du ser ud til at have nok!,Du scheinst genug zu haben.,,Vi ŝajnas havi sufiĉe!,¡Se ve que tienes suficiente!,,Sinulla näyttää olevan tarpeeksi!,Vous avez l'air d'en avoir assez!,Úgy néz ki eleged van már!,Sembri averne abbastanza!,十分に持ち合わせている!,충분히 가진 것 같은데?,Je lijkt genoeg te hebben!,Du har visst fått nok!,"Wydaje się, że już ci wystarczy!",Você parece ter o suficiente!,Pareces ter o suficiente!,Pare că ai destule!,"Кажется, тебе хватит!",Изгледа да ти је доста!,Du verkar ha fått nog!,Yeterince var gibi görünüyor!,"Здається, тобі досить!" +Go away!,TXT_GOAWAY,,,,Jdi pryč!,Gå væk!,Verschwinde!,,Foriru!,¡Lárgate!,,Häivy!,Allez-vous en!,Takarodj!,Vattene via!,逃げ出せ!,저리 가!,Ga weg!,Forsvinn!,Idź stąd!,Vá embora!,Vai-te embora!,Pleacă!,Уходи!,Одлази!,Gå härifrån!,Git başımdan!,Йди геть! +Incoming Message...,TXT_COMM0,,,,Příchozí zpráva...,Indkommende besked...,Nachricht erhalten...,,Alvenas mesaĝo...,Mensaje entrante...,,Vastaantuleva viesti...,Message reçu.,Bejövő Üzenet...,Messaggio in arrivo...,メッセージが届いた...,메시지가 옴...,Inkomend bericht....,Innkommende melding...,Nadchodzi wiadomość...,Recebendo Mensagem...,A Receber Mensagem...,Mesaj în intrare...,Входящее сообщение...,Наилази порука...,Inkommande meddelande...,Gelen Mesaj...,Вхідне повідомлення... +Incoming Message from BlackBird...,TXT_COMM1,,,,Příchozí zpráva od Straky...,Indkommende besked fra BlackBird...,Nachricht von Blackbird erhalten...,,Alvenas mesaĝo de Merlo...,Mensaje entrante de Blackbird...,,Vastaantuleva viesti Blackbirdiltä...,Message reçu de BlackBird,Bejövő Üzenet Feketerigótól...,Messaggio in arrivo da Blackbird...,ブラックバードからのメッセージが届いた...,블랙버드로부터 메시지가 옴...,Inkomend bericht van BlackBird....,Innkommende melding fra BlackBird...,Nadchodzi wiadomość od BlackBird...,Recebendo Mensagem de BlackBird...,A Receber Mensagem de BlackBird...,Mesaj în intrare de la BlackBird...,Входящее сообщение от «Чёрного дрозда»...,Наилази порука од Црне птице....,Inkommande meddelande från BlackBird...,Gelen Mesaj...,Вхідне повідомлення від Чорного Дрозда... +Find help,TXT_FINDHELP,,,,Najdi pomoc.,Find hjælp,Finde Hilfe,,Trovu helpon.,Busca ayuda.,,Etsi apua,Trouvez de L'aide,Keress segítséget,Trova aiuto,助けを探せ,도움말,Zoek hulp,Finn hjelp,Znajdź pomoc,Procure ajuda,Procura ajuda,Găsește ajutor,Найди помощь,Нађи помоћ,Hitta hjälp,Yardım bul,Знайди допомогу +for %u,TXT_TRADE,As in for %u amount of money.,,,za %u zlatých,til %u,für %u,,kontraŭ %u da oro.,por %u de oro.,,hintaan %u,pour %u,%u számára,per %u,%u ゴールド,(가격: %u),voor %u,til %u,za %u,por %u,,pentru %u,за %u,за %u,för %u,için %u,за %u +,,Chex Quest,,,,,,,,,,,,,,,,,,,,,,,,,, +,,Pickups,,,,,,,,,,,,,,,,,,,,,,,,,, +Picked up the Chex(R) Armor.,GOTCHEXARMOR,,,Picked up the Chex(R) Armour.,Sebráno Chex(R) brnění.,Hentede Chex(R) Rustning.,Du hast die Chex(R) Rüstung genommen,,Prenis la Chex(R)-kirason.,Recogiste la Armadura Chex(R).,,Poimit Chex(R)-panssarin.,Vous avez pris l'armure Chex(R).,Felvettél egy Chex(R) páncélt.,Raccolta un'Armatura Chex(R).,チェックス(R)アーマー をてにいれた。,첵스(R) 갑옷 획득.,Je hebt het Chex(R) harnas opgepakt.,Plukket opp Chex(R) Armor.,Zebrano Pancerz Chex(R).,Pegou uma Armadura Chex(R).,Apanhaste uma Armadura Chex(R).,Ai ridicat Armura Chex(R).,Получена Chex(R)-броня.,Покупио си Чех оклоп.,Plockade upp Chex(R) rustningen.,Chex(R) Zırhı'nı aldım.,Взято Chex(R) броню. +Picked up the Super Chex(R) Armor!,GOTSUPERCHEXARMOR,,,Picked up the Super Chex(R) Armour!,Sebráno Super Chex(R) brnění!,Hentede Super Chex(R) Rustning!,Du hast die Superchex(R)Rüstung genommen!,,Prenis la superan Chex(R)-kirason!,¡Recogiste la Súper-Armadura Chex(R)!,,Poimit Super-Chex(R)-panssarin!,Vous avez pris la super armure Chex(R)!,Felvettél egy szuper Chex(R) páncélt!,Raccolta la Super Armatura Chex(R)!,スーパーチェックス(R)アーマー をてにいれた。,슈퍼 첵스(R) 갑옷 획득!,Je hebt het Super-Chex(R) harnas opgehaald!,Plukket opp Super Chex(R) Armor!,Zebrano Super Pancerz Chex(R)!,Pegou uma Super Armadura Chex(R)!,Apanhaste uma Super Armadura Chex(R)!,Ai ridicat Super Armura Chex(R)!,Получена Chex(R)-сверхброня!,Покупио си Супер Чех оклоп.,Plockade upp Super Chex(R) rustningen!,Süper Chex(R) Zırhı'nı aldı!,Взято Chex(R) супер броню! +Picked up a glass of water.,GOTWATER,,,,Sebrána sklenice vody.,Samlede et glas vand op.,Du hast ein Glas Wasser genommen.,,Prenis glason de akvo.,Recogiste un vaso de agua.,,Poimit vesilasin.,Vous avez pris un verre d'eau.,Felvettél egy pohár vizet.,Raccolto un bicchiere d'acqua.,コップいっぱいの みずをひろった。,물 한 컵 섭취.,Je hebt een glas water opgepakt.,Hentet et glass vann.,Zebrano szklankę wody.,Pegou um copo d'água.,Apanhaste um copo de água.,Ai ridicat un pahar cu apă.,Получен стакан воды.,Покупио си чашу воде,Plockade upp ett glas vatten.,Bir bardak su aldım.,Взято стакан води. +Picked up slime repellent.,GOTREPELLENT,,,,Sebrán repelent proti slizu.,Hentede slimafvisende middel.,Du hast das Schleimabwehrmittel genommen.,,Prenis mukforigilon.,Recogiste un repelente de baba.,,Poimit limakarkotteen.,Vous avez pris de la chaux répulsive.,Felvettél egy nyálkataszítót.,Raccolto del repellente allo slime.,スライム はんぱつざい をひろった。,오물 방수제 획득.,Je hebt de slijmafstotende stof opgepakt.,Plukket opp slime repellent.,Zebrano odstraszacz szlamu.,Pegou repelente de gosma.,Apanhaste repelente de gosma.,Ai ridicat respingătorul de mâzga.,Получен репеллент от слизи.,Покупио си одбијаш љигавца.,Plockade upp ett slemavvisande medel.,Balçık kovucu aldım.,Взято репелент проти слизняків. +Supercharge Breakfast!,GOTBREAKFAST,,,,Supervýživná snídaně!,Supercharge Morgenmad!,Überladenes Frühstück!,,Ŝargega Matenmanĝon!,¡Desayuno supercargado!,,Superaamiaislatinki!,Petit-déjeuner superchargé!,Szupertöltött Reggeli!,Colazione da supercarica!,ちょうしょく スーパーチャージ!,힘찬 아침식사 섭취!,Overbelast ontbijt!,Superladet frokost!,Supernaładowane Śniadanie!,Super Café da Manhã!,Super Pequeno-Almoço!,Superîncărcătură Mic Dejun!,Завтрак из сверхзаряда!,Супер-напуњен доручак.,Supercharge frukost!,Süper Şarjlı Kahvaltı!,Суперзаряджений сніданок! +Picked up a blue key.,GOTCBLUEKEY,,,,Sebrán modrý klíč.,Samlede en blå nøgle op.,Du hast einen blauen Schlüssel genommen.,,Prenis bluan ŝlosilon.,Recogiste una llave azul.,,Poimit sinisen avaimen.,Vous avez pris une clé bleue.,Felvettél egy kék kulcsot.,Raccolta una chiave blu.,あお のかぎ をひろった。,파란색 열쇠 획득.,Je hebt een blauwe sleutel opgepakt.,Plukket opp en blå nøkkel.,Zebrano niebieski klucz.,Pegou a chave azul.,Apanhaste a chave azul.,Ai ridicat o cheie albastră.,Получен синий ключ.,Покупио си плави кључ.,Plockade upp en blå nyckel.,Mavi bir anahtar aldı.,Взято синій ключ. +Picked up a yellow key.,GOTCYELLOWKEY,,,,Sebrán žlutý klíč.,Samlede en gul nøgle op.,Du hast einen gelben Schlüssel genommen.,,Prenis ruĝan ŝlosilon.,Recogiste una llave amarilla.,,Poimit keltaisen avaimen.,Vous avez pris une clé jaune.,Felvettél egy sárga kulcsot.,Raccolta una chiave gialla.,きいろ のかぎ をひろった。,노란색 열쇠 획득.,Je hebt een gele sleutel opgepakt.,Plukket opp en gul nøkkel.,Zebrano żółty klucz.,Pegou a chave amarela.,Apanhaste a chave amarela.,Ai ridicat o cheie galbenă.,Получен жёлтый ключ.,Покупио си жути кључ.,Plockade upp en gul nyckel.,Sarı bir anahtar aldı.,Взято жовтий ключ. +Picked up a red key.,GOTCREDKEY,,,,Sebrán červený klíč.,Samlede en rød nøgle op.,Du hast einen roten Schlüssel genommen.,,Prenis flavan ŝlosilon.,Recogiste una llave roja.,,Poimit punaisen avaimen.,Vous avez pris une clé rouge.,Felvettél egy piros kulcsot.,Raccolta una chiave rossa.,あか のかぎ をひろった。,빨간색 열쇠 획득.,Je hebt een rode sleutel opgepakt.,Plukket opp en rød nøkkel.,Zebrano czerwony klucz.,Pegou a chave vermelha.,Apanhaste a chave vermelha.,Ai ridicat o cheie roșie.,Получен красный ключ.,Покупио си црвени кључ.,Plockade upp en röd nyckel.,Kırmızı bir anahtar aldı.,Взято червоний ключ. +Picked up a bowl of fruit.,GOTFRUIT,,,,Sebrána mísa s ovocem.,Samlede en skål med frugt op.,Du hast eine Obstschale genommen.,,Prenis bovlon de fruktoj.,Recogiste un tazón de fruta.,,Poimit hedelmäkulhon.,Vous avez pris un bol de fruits.,Felvettél egy tál gyümölcsöt.,Raccolto un vassoio di frutta.,フルーツのボウル をひろった。,과일 한 그릇 섭취.,Je hebt een fruitschaal opgepakt.,Plukket opp en bolle med frukt.,Zebrano miskę owoców.,Pegou uma tigela de frutas.,Apanhaste uma taça com fruta.,Ai ridicat un bol de fructe.,Получена тарелка с фруктами.,Покупио си чинију воћа.,Plockade upp en skål med frukt.,Bir kase meyve al.,Взято тарілку фруктів. +Vegetables are REALLY good for you!,GOTVEGETABLESNEED,,,,Zelenina je VELMI zdravá!,Grøntsager er VIRKELIG gode for dig!,Gemüse ist RICHTIG gut für dich!,,Legomoj estas TRE bonaj por vi!,¡Las verduras son REALMENTE buenas para ti!,,Vihannekset ovat TOSI terveellisiä!,Les légumes sont VRAIMENT bons pour vous!,A zöldségek NAGYON jót tesznek neked!,La verdura ti fa DAVVERO bene!,いま とってもひつような やさいのボウルだ!,채소의 건강한 영양분이 독 기운을 없앴습니다!,Groenten zijn echt goed voor je!,Grønnsaker er VIRKELIG bra for deg!,Warzywa są BARDZO dobre dla ciebie!,Vegetais fazem MUITO bem para você!,Os Vegetais são MUITO bons para ti!,Legumele sunt FOARTE bune pentru tine!,Овощи ОЧЕНЬ полезны для здоровья!,Поврће је ЈАКО добро за тебе!,Grönsaker är VÄLDIGT bra för dig!,Sebzeler sizin için GERÇEKTEN iyidir!,Овочі ДУЖЕ корисні для тебе! +Picked up a bowl of vegetables.,GOTVEGETABLES,,,,Sebrána mísa se zeleninou.,Samlede en skål med grøntsager op.,Du hast eine Gemüseschale genommen.,,Prenis bovlon de legomoj.,Recogiste un tazón de verduras.,,Poimit vihannesvadin.,Vous avez pris un bol de légumes.,Felvettél egy tál zöldséget.,Raccolto un vassoio di verdura.,やさいのボウル をひろった。,채소 한 그릇 섭취.,Je hebt een kom groenten opgepakt.,Plukket opp en bolle med grønnsaker.,Zebrano miskę warzyw.,Pegou uma tigela de vegetais.,Apanhaste uma tigela com vegetais.,Ai ridicat un bol de legume.,Получена тарелка с овощами.,Покупио си чинију поврћа.,Plockade upp en skål med grönsaker.,Bir kase sebze aldı.,Взято тарілку овочів. +Found a Slime-Proof Suit,GOTSLIMESUIT,,,,Nalezen slizu odolný oblek.,Fandt et slim-sikret jakkesæt,Du hast einen Schleimbeständigen Anzug gefunden,,Trovis mukimunan kompleton.,Encontraste un traje a prueba de baba.,,Löysit limaapitävän puvun,Combinaison pare-gelée,Felvettél egy nyálkaálló védőruhát,Raccolto un vestito a prova di slime,たい スライム スーツ をてにいれた。,오물 보호복 사용.,Je hebt een slijtvast pak opgepakt.,Fant en slimsikker drakt,Znaleziono Szlamoodporny Kombinezon,Achou um Traje Anti-Gosma,Apanhaste um Fato Anti-Gosma.,Ai ridicat un Costum Rezistent la Mâzgă,Получен противослизневый костюм,Нашо си љигаво-отпорано одело.,Hittade en slimsäker kostym,Balçık Geçirmez Takım Elbise Buldum,Взято протислизнячий костюм +Found a Computer Area Map,GOTCHEXMAP,,,,Nalezena počítačová mapa oblasti.,Fandt et kort over et computerområde,Du hast eine Computerkarte gefunden,,Trovis komputilan regionmapon.,Encontraste un mapa computarizado del área.,,Löysit alueen tietokonekartan,Vous avez trouve une carte informatique de la zone.,Felvettél egy Számítógépes Térképet,Trovata una mappa computerizzata,コンピューターエリアマップ をてにいれた。,컴퓨터 지도 사용.,Je hebt een computerkaart opgepakt.,Fant et datamaskinkart,Znaleziono Komputerową Mapę Obszaru,Achou um Mapa Computadorizado,Apanhaste um Mapa Digital.,Ai ridicat o Hartă Generată pe Calculator a Zonei.,Получена компьютерная карта местности,Нашао компјутерку мапу окружења,Hittade en karta över datorområdet,Bilgisayar Alanı Haritası Bulundu,Знайдено комп'ютерну карту району +Picked up a mini zorch recharge.,GOTZORCHRECHARGE,,,,Sebrán minibzukový náboj.,Samlede en mini zorch-opladning op.,Du hast eine Minizorcher-Ladung genommen.,,Prenis zorĉreŝargeton.,Recogiste una recarga de mini zorch.,,Poimit minizorchlatauksen.,Vous avez pris une mini recharge zorch.,Felvettél egy Mini Zorker Újratöltőt,Raccolta una ricarica di mini zorch.,ミニゾーチ リチャージ をひろった。,소형 저치 전지 획득.,Je hebt een minizorcherlading opgepakt.,Plukket opp en mini zorch-opplading.,Zebrano mini ładunek zorch.,Pegou recarga para mini zorch.,Apanhaste uma recarga para o mini zorch.,Ai ridicat o mini încărcătură pentru zorch.,Получена зарядка мини-зорчера.,Покупио си мини зорч пуњач.,Plockade upp en mini zorch-uppladdning.,Mini bir Zorch şarjı aldım.,Взято заряд міні-Зорчера. +Picked up a mini zorch pack.,GOTMINIZORCHPACK,,,,Sebrán minibzukový balík.,Afhentede en mini zorch-pakke.,Du hast ein Minizorcher-Ladepaket genommen.,,Prenis zorĉpaketon,Recogiste un paquete de mini zorch.,,Poimit minizorchpaketin.,Vous avez pris un pack de mini recharges zorch.,Felvettél egy Mini Zorker Csomagot,Raccolta una scatola di mini zorch.,ミニゾーチ パック をひろった。,저치 전지 박스 획득.,Je hebt een pakket met minizorcherladingen opgepakt.,Plukket opp en mini zorch-pakke.,Zebrano mini paczkę zorch.,Pegou um pacote de recargas de mini zorch.,Apanhaste um pagcote de recargas para o mini zorch.,Ai ridicat un mini patchet de încărcătură pentru zorch.,Получена батарея мини-зорчера.,Покупио си мини зорч пакет.,Plockade upp en mini zorch pack.,Mini bir Zorch paketi aldım.,Взято батарею для міні-Зорчера. +Picked up a zorch propulsor recharge.,GOTPROPULSORRECHARGE,,,,Sebrán náboj pro bzukový propulzor.,Afhentede en zorch propulsor opladning.,Du hast eine Propeller-Ladung genommen.,,Prenis zorĉpropulsilo-reŝargon.,Recogiste una recarga de propulsor de zorch.,,Poimit zorchtyöntimen latauksen.,Vous avez pris une recharge propulseur zorch.,Felvettél egy Zork Elhárító Újratöltőt,Raccolta una ricarica di zorch a propulsione.,ゾーチプロパルサーリチャージ をひろった。,저치 추진료 획득.,Je hebt een propulsorlading opgepakt.,Plukket opp en zorch propulsor-opplading.,Zebrano ładunek do pędnika zorch.,Pegou recarga para propulsor de zorch.,Apanhaste recarga para o propulsor de zorch.,Ai ridicat o încărcătură pentru acceleratorul zorch.,Получена зарядка ускорителя зорча.,Покупио си зорч погонски пуњач.,Plockade upp en zorch propulsoruppladdning.,Bir Zorch itici şarjı aldı.,Взято заряд Зорч-прискорювача. +Picked up a zorch propulsor pack.,GOTPROPULSORPACK,,,,Sebrán balík pro bzukový propulzor.,Afhentede en zorch propulsorpakke.,Du hast ein Propeller-Ladepaket genommen.,,Prenis zorĉpropulsilo-pakon.,Recogiste un paquete de propulsor de zorch.,,Poimit zorchtyöntimen paketin.,Vous avez pris un paquet propulseur zorch.,Felvettél egy Zork Elhárító Csomagot,Raccolta una scatola di zorch a propulsione.,ゾーチプロパルサーパック をひろった。,저치 추진 팩 획득.,Je hebt een pakket met propulsorladingen opgepakt.,Plukket opp en zorch fremdriftspakke.,Zebrano paczkę pędnika zorch.,Pegou um pacote de recargas para propulsor de zorch.,Apanhaste um pacote de recargas para o propulsor de zorch,Ai ridicat un pachet de baterii pentru acceleratorul zorch.,Получена батарея ускорителя зорча.,Покупио си зорч погонски пакет.,Plockade upp en zorch propulsor pack.,Bir Zorch itici paketi aldı.,Взято батарею Зорч-прискорювача. +Picked up a phasing zorcher recharge,GOTPHASINGZORCHERRECHARGE,,,,Sebrán náboj pro fázovací bzukr.,Afhentede en zorcher-opladning til faseopladning.,Du hast eine Phasenzorcher-Ladung genommen.,,Prenis fluktuantzorĉilo-reŝargon.,Recogiste una recarga de zorch de fase.,,Poimit vaiheiszorcherin latauksen.,Vous avez pris une recharge zorch phasée.,Felvettél egy Fázis Zorker Újratöltőt,Raccolta una ricarica per zorcher a phasing,フェイシング ゾーチャーリチャージ をひろった。,저치 전자 충전기 획득.,Je hebt een phasenzorcherlading opgepakt.,Plukket opp en fasing zorcher oppladning.,Zebrano ładunek do fazowego zorchera.,Pegou recarga para zorcher fásico.,Apanhaste recarga para o zorcher fásico,Ai ridicat o încărcătură fazată pentru zorcher,Получена зарядка фазерного зорчера.,Покупио си фазни зорчер пуњач.,Plockade upp en phasing zorcher-uppladdning.,Bir faz zorcher şarjı aldı,Взято заряд фазового Зорчера. Picked up a phasing zorcher pack.,GOTPHASINGZORCHERPACK,,,,Sebrán balík pro fázovací bzukr.,Afhentede en phasing zorcher-pakke.,Du hast ein Phasenzorcher-Ladepaket genommen.,,Prenis fluktuantzorĉilo-pakon.,Recogiste un paquete de zorch de fase.,,Poimit vaiheiszorcherin paketin.,Vous avez pris un pack de recharges zorch phasée.,Felvettél egy Fázis Zorker Csomagot,Raccolta una scatola per zorcher a phasing.,フェイシング ゾーチャーパック をひろった。,특대 저치 충전기 획득.,Je hebt een pakket met phasenzorcherladingen opgepakt.,Plukket opp en fasing zorcher-pakke.,Zebrano paczkę fazowego zorchera.,Pegou um pacote de recargas para zorcher fásico.,Apanhaste um pacote de recargas para o zorcher fásico,"Ai ridicat un pachet de încărcături fazate pentru -zorcher.",Получена батарея для фазерного Зорчера.,Покупио си фазни зорчер пакет.,Bir faz zorcher paketi aldım. -Picked up a large zorcher recharge.,GOTLARGEZORCHERRECHARGE,,,,Sebrán náboj pro velký bzukr.,Afhentede en stor zorcher-opladning.,Du hast eine Zorcher-Ladung genommen.,,Prenis grandzorĉilo-reŝargon.,Recogiste una gran recarga de zorch.,,Poimit ison zorcherin latauksen,Vous avez pris une recharge pour zorcheur large.,Felvettél egy Nagy Zorker Újratöltőt,Raccolta una ricarica per zorcher grande.,ラージ ゾーチャーリチャージ をひろった。,대형 저치 카트리지 획득.,Je hebt een zorcherlading opgepakt.,Plukket opp en stor zorcher-opplading.,Zebrano ładunek do dużego zorchera.,Pegou recarga para zorcher grande.,Apanhaste recarga para o zorcher grande.,Ai ridicat o încărcătură mare pentru zorcher.,Получена зарядка для большого Зорчера.,Покупио си велики зорчер пуњач.,Büyük bir zorcher şarjı aldım. -Picked up a large zorcher pack.,GOTLARGEZORCHERPACK,,,,Sebrán balík pro velký bzukr.,Afhentede en stor zorcher-pakke.,Du hast ein Zorcher-Ladepaket genommen.,,Prenis grandegzorĉilo-reŝargon.,Recogiste un gran paquete de zorch.,,Poimit ison zorcherin paketin.,Vous avez pris un pack de recharges pour zorcheur large.,Felvettél egy Nagy Zorker Csomagot,Raccolta una scatola per zorcher grande.,ラージ ゾーチャーパック をひろった。,저치 카트리지 묶음 획득.,Je hebt een pakket met zorcherladingen opgepakt.,Plukket opp en stor zorcherpakke.,Zebrano paczkę dużego zorchera.,Pegou um pacote de recargas para zorcher grande.,Apanhaste um pacote de recargas para o zocher grande.,Ai ridicat un pachet mare de încărcături pentru zorcher.,Получена батарея для большого Зорчера.,Покупио си велики зорчер пакет.,Büyük bir zorcher paketi aldı. -Picked up a Zorchpak!,GOTZORCHPACK,,,,Sebrán Bzukrbatoh!,Afhentede en Zorchpak!,Du hast ein Zorchpaket genommen.,,Prenis Zorĉpakon!,¡Recogiste un Zorchpak!,,Poimit zorchpakin!,Vous avez pris un zorchpak!,Felvettél egy Zorkpakkot!,Raccolto uno ZorchZaino!,ゾーチパックをてにいれた!,저치 팩 획득!,Je hebt en zorchpak opgepakt.,Plukket opp en Zorchpak!,Zebrano Paczkę Zorch.,Pegou um Zorchpak!,Apanhaste um Zorchpak!,Ai ridicat un Ghiozdan Zorch!,Получен Зорч-рюкзак!,Покупио си зорчпак.,Bir Zorchpak aldım! -You got the LAZ Device! Woot!,GOTLAZDEVICE,,,,Získal@[ao_cs] jsi velkodosahový bzukr! Cooo?,Du fik LAZ-enheden! Woot!,Du hast den Flächenzorcher!,,Vi prenis la LAZ-aparaton! Hura!,¡Tienes el dispositivo LAZ! ¡Yuju!,,Sait SAZ-laitteen! Juhuu!,Vous avez pris l'Outil ZZL! Wahou!,Felvetted a LAZ Készüléket! Wáó!,Hai trovato il dispositivo LAZ! Cavolo!,LAZ デバイスをてにいれた! ワァオ!,LAZ 장치 습득! 완전 짱인걸!,Je hebt het LAZ-apparaat! Woot!,Du har LAZ-enheten! Woot!,Zdobył@[irreg_3_pl] urządzenie LAZ! Juhu!,Você achou o Dispositivo LAZ! Oba!,Apanhaste um Dispositivo LAZ! Fixe!,Ai ridicat un Dispozitiv LAZ! Uraa!,Получено устройство Зорчирования большого радиуса! Ура!,Добио си ЛАЗ уређај. ВУТ!,LAZ cihazını aldın! Woot! -You got the Rapid Zorcher!,GOTRAPIDZORCHER,,,,Získal@[ao_cs] jsi rychlobzukr!,Du fik en Rapid Zorcher!,Du hast den schnellen Zorcher genommen!,,Vi prenis la Rapidzorĉilon!,¡Tienes el Zorcher Rápido!,,Sait pikazorcherin!,Vous avez pris le Zorcheur Rapide!,Felvetted a Gyors Zorkert!,Hai trovato il zorcher rapido!,ラピッドゾーチャー をてにいれた!,속사 자쳐 습득!,Je hebt de snelle Zorcher!,Du har Rapid Zorcher!,Zdobył@[irreg_3_pl] Szybkostrzelny Zorcher!,Você pegou o Zorcher Automático!,Apanhaste o Zorcher Automático!,Ai ridicat un Zorcher cu Foc Rapid!,Получен скорострельный Зорчер!,Добио си рапидан зорчер!,Hızlı Zorcher'ı aldın! -You got the Super Bootspork!,GOTSUPERBOOTSPORK,,,,Získal@[ao_cs] jsi super botovidličku!,Du fik Super Bootspork!,Du hast den Super-Gabelquirl genommen!,,Vi prenis la Superan Ŝargmanĝilaron!,¡Tienes el Súper Cuchador!,,Sait superluhan!,Vous avez pris la Super Fourchette!,Felvetted a Szuper Rotációs Villát!,Hai trovato il super bootspork!,スーパーさきわれスプーン をてにいれた!,부트스포크 습득!,Je hebt de Super Bootspork!,Du har Super Bootspork!,Zdobył@[irreg_3_pl] Super Łyżkowidelec!,Você pegou o Super Garfo!,Apanhaste o Super Garfo-Colher!,Ai ridicat o Super Lingură!,Получена суперложковилка!,Добио си супер чизмо-порк!,Süper Bootspork'u aldın! -You got the Zorch Propulsor!,GOTZORCHPROPULSOR,,,,Získal@[ao_cs] jsi bzukový propulsor!,Du fik Zorch-propulsoren!,Du hast den Propellerzorcher genommen!,,Vi prenis la Zorĉpropulsilon!,¡Tienes el Propulsor de Zorch!,,Sait zorchtyöntimen!,Vous avez pris le Propulseur Zorch!,Felvetted a Zork Elhárítót!,Hai trovato il propulsore zorch!,ロケット ゾーチャー をてにいれた!,저치 추진기 습득!,Je hebt de Zorch Propulsor!,Du fikk Zorch Propulsor!,Zdobył@[irreg_3_pl] Pędnik Zorch!,Você pegou o Propulsor de Zorch!,Apanhaste o Propulsor de Zorch!,Ai ridicat un Accelerator Zorch!,Получен ускоритель Зорча!,Добио си зорч погон!,Zorch Propulsor'u aldın! -You got the Phasing Zorcher!,GOTPHASINGZORCHER,,,,Získal@[ao_cs] jsi fázovací bzukr!,Du fik Phasing Zorcher!,Du hast den Phasenzorcher genommen!,,Vi prenis la Fluktuantzorĉilon!,¡Tienes el Zorcher de Fase!,,Sait vaiheiszorcherin!,Vous avez pris le Zorcheur phasé!,Felvetted a Fázis Zorkert!,Hai trovato il zorcher a phasing!,フェイシング ゾーチャー をてにいれた!,전자 자쳐 습득!,Je hebt de Fasezorcher!,Du har Phasing Zorcher!,Zdobył@[irreg_3_pl] Fazowy Zorcher!,Você pegou o Zorcher Fásico!,Apanhaste o Zorcher Fásico!,Ai ridicat un Zorcher Fazat!,Получен фазерный Зорчер!,Добио си фазни зорчер!,Fazlama Zorcher'ı aldın! -You got the Large Zorcher!,GOTLARGEZORCHER,,,,Získal@[ao_cs] jsi velký bzukr!,Du fik den store Zorcher!,Du hast den großen Zorcher genommen!,,Vi prenis la Grandzorĉilon,¡Tienes el Zorcher Grande!,,Sait ison zorcherin!,Vous avez pris le Zorcheur Large!,Felvetted a Nagy Zorkert!,Hai trovato il zorcher grande!,おおがたゾーチャー をてにいれた!,대형 자쳐 습득!,Je hebt de grote Zorcher!,Du har den store Zorcher!,Zdobył@[irreg_3_pl] Duży Zorcher!,Você pegou o Zorcher Grande!,Apanhaste o Zorcher Grande!,Ai ridicat un Zorcher Mare!,Получен большой Зорчер!,Добио си велики зорчер!,Büyük Zorcher'ı aldınız! -You got the Mega Zorcher!,GOTSUPERLARGEZORCHER,,,,Získal@[ao_cs] jsi megabzukr!,Du fik Mega Zorcher!,Du hast den Megazorcher genommen!,,Vi prenis la Grandegzorĉilon!,¡Tienes el Mega Zorcher!,,Sait megazorcherin!,Vous avez pris le méga Zorcheur!,Felvetted a Mega Zorkert!,Hai trovato il mega zorcher!,ちょうおおがたゾーチャー をてにいれた!,초대형 자쳐 습득!,Je hebt de Megazorcher!,Du har Mega Zorcher!,Zdobył@[irreg_3_pl] Mega Zorcher!,Você pegou o Mega Zorcher!,Apanhaste o Mega Zorcher!,Ai ridicat un Mega Zorcher!,Получен Мегазорчер!,Добио си мега зорчер!,Mega Zorcher'ı aldın! -Picked up a Mini Zorcher.,GOTMINIZORCHER,,,,Sebrán minibzukr.,Du har fået en Mini Zorcher.,Du hast einen Minizorcher genommen.,,Prenis Zorĉileton.,Recogiste un Mini Zorcher,,Poimit minizorcherin.,Vous avez pris le Mini Zorcheur.,Felvettél egy Mini Zorkert.,Raccolto un mini zorcher.,こがたゾーチャー をてにいれた。,소형 자쳐 습득.,Je hebt een minizorcher opgepakt.,Plukket opp en Mini Zorcher.,Zebrano Mini Zorcher.,Você pegou um Mini Zorcher.,Apanhaste um Mini Zorcher.,Ai ridicat un Mini Zorcher.,Получен мини-Зорчер.,Покупио си мини зорчер!,Bir Mini Zorcher aldın. -,,Actor tags,,,,,,,,,,,,,,,,,,,,,,,, -Spoon,TAG_SPOON,,,,Lžíce,Ske,Löffel,,Kulero,Cuchara,,Lusikka,Cuillère à Botte,Kanál,Cucchiaio ,スプーン,숟가락,Lepel,Skje,Łyżka,Colher,,Lingură,Ложка,Кашика,Kaşık -Super Bootspork,TAG_SPORK,,,,Super botodlička,,Supergabel,,Ega Ŝargmanĝilaro,Súper Cuchador,,Superluha,Super Fourchette,Szuper Rotációs Villa,Super Forcucchiaio,スーパーさきわれスプーン,부트스포크,,,Super Łyżkowidelec,Super Garfo,Super Garfo-Colher,Super Lingură,Суперложковилка,Супер виљушка,Süper Bootspork -Mini Zorcher,TAG_MINIZORCHER,,,,Minibzukr,,Minizorcher,,Zorĉileto,Mini Zorcher,,Minizorcheri,Mini Zorcheur,Mini Zorker,Mini Zorcher,こがたゾーチャー,소형 자쳐,Minizorcher,,Mini Zorcher,Mini Zorcher,,Mini Zorcher,Мини-Зорчер,Мини зорчер,Mini Zorcher -Large Zorcher,TAG_LARGEZORCHER,,,,Velký bzukr,Stor Zorcher,Großer Zorcher,,Granda Zorĉilo,Zorcher Grande,,Iso zorcheri,Zorcheur Large,Nagy Zorker,Grosso Zorcher ,おおがたゾーチャー,대형 자쳐,Grote Zorcher,Stor Zorcher,Duży Zorcher,Zorcher Grande,,Zorcher Mare,Большой Зорчер,Велики зорчер,Büyük Zorcher -Super-Large Zorcher,TAG_SUPERLARGEZORCHER,,,,Supervelký bzukr,Super-stor Zorcher,Riesenzorcher,,Grandega Zorĉilo,Zorcher Súper Grande,,Superiso zorcheri,Zorcheur Extra-large,Hatalmas Zorker,Zorcher Enorme ,ちょうおおがたゾーチャー,초대형 자쳐,Super grote Zorcher,Super-stor Zorcher,Większy Zorcher,Super Zorcher Grande,,Zorcher Super-Mare,Мега-Зорчер,Супер-велики зорчер,Süper Büyük Zorcher -Rapid Zorcher,TAG_RAPIDZORCHER,,,,Rychlobzukr,,Schnellzorcher,,Rapida Zorĉilo,Zorcher Rápido,,Pikazorcheri,Zorcheur Rapide,Gyors Zorker,Zorcher Rapido,れんしゃ ゾーチャー,속사 자쳐,Snelle Zorcher,,Szybkostrzelny Zorcher,Zorcher Automático,,Zorcher cu Foc Rapid,Быстрый Зорчер,Рапидни зорчер,Hızlı Zorcher -Zorch Propulsor,TAG_ZORCHPROPULSOR,,,,Bzukový propulzor,,Zorch-Propeller,,Zorĉpropulsilo,Propulsor de Zorch,,Zorchtyönnin,Propulseur de Zorch,Zork Elhárító,Propulsore Zorch,ロケット ゾーチ,저치 추진기,,,Pędnik Zorch,Propulsor de Zorch,,Accelerator Zorch,Ускоритель Зорча,Погонски зорчер,Zorch Propulsor -Phasing Zorcher,TAG_PHASINGZORCHER,,,,Fázovací bzukr,,Phasenzorcher,,Fluktuantzorĉilo,Zorcher de Fase,,Vaiheiszorcheri,Zorcheur à Phase,Fokozatos Zorker,Zorcher di Fase,フェイシング ゾーチャー,전자 자쳐,Fasezorcher,,Fazowy Zorcher,Zorcher Fásico,,Zorcher Fazat,Фазерный Зорчер,Фазни зорчер,Fazlama Zorcher -LAZ Device,TAG_LAZDEVICE,,,,Velkodosahový bzukr,LAZ-enhed,Flächenzorcher,,LAZ-Aparato,Dispositivo LAZ,,SAZ-laite,Zorcheur Zone Large,LAZ Készülék,Dispositivo LAZ,ラージエリアゾーキング デバイス,LAZ 장치,LAZ-aparaat,LAZ-enhet,Urządzenie LAZ,Dispositivo LAZ,,Dispozitiv LAZ,Устройство «ЗБР»,ЛАЗ уређај,LAZ Cihazı +zorcher.",Получена батарея фазерного зорчера.,Покупио си фазни зорчер пакет.,Plockade upp en phasing zorcher pack.,Bir faz zorcher paketi aldım.,Взято батарею фазового Зорчера. +Picked up a large zorcher recharge.,GOTLARGEZORCHERRECHARGE,,,,Sebrán náboj pro velký bzukr.,Afhentede en stor zorcher-opladning.,Du hast eine Zorcher-Ladung genommen.,,Prenis grandzorĉilo-reŝargon.,Recogiste una gran recarga de zorch.,,Poimit ison zorcherin latauksen,Vous avez pris une recharge pour zorcheur large.,Felvettél egy Nagy Zorker Újratöltőt,Raccolta una ricarica per zorcher grande.,ラージ ゾーチャーリチャージ をひろった。,대형 저치 카트리지 획득.,Je hebt een zorcherlading opgepakt.,Plukket opp en stor zorcher-opplading.,Zebrano ładunek do dużego zorchera.,Pegou recarga para zorcher grande.,Apanhaste recarga para o zorcher grande.,Ai ridicat o încărcătură mare pentru zorcher.,Получена зарядка большого зорчера.,Покупио си велики зорчер пуњач.,Plockade upp en stor zorcher-uppladdning.,Büyük bir zorcher şarjı aldım.,Взято заряд великого Зорчера. +Picked up a large zorcher pack.,GOTLARGEZORCHERPACK,,,,Sebrán balík pro velký bzukr.,Afhentede en stor zorcher-pakke.,Du hast ein Zorcher-Ladepaket genommen.,,Prenis grandegzorĉilo-reŝargon.,Recogiste un gran paquete de zorch.,,Poimit ison zorcherin paketin.,Vous avez pris un pack de recharges pour zorcheur large.,Felvettél egy Nagy Zorker Csomagot,Raccolta una scatola per zorcher grande.,ラージ ゾーチャーパック をひろった。,저치 카트리지 묶음 획득.,Je hebt een pakket met zorcherladingen opgepakt.,Plukket opp en stor zorcherpakke.,Zebrano paczkę dużego zorchera.,Pegou um pacote de recargas para zorcher grande.,Apanhaste um pacote de recargas para o zocher grande.,Ai ridicat un pachet mare de încărcături pentru zorcher.,Получена батарея большого зорчера.,Покупио си велики зорчер пакет.,Plockade upp ett stort zorcherpaket.,Büyük bir zorcher paketi aldı.,Взято батарею великого Зорчера. +Picked up a Zorchpak!,GOTZORCHPACK,,,,Sebrán Bzukrbatoh!,Afhentede en Zorchpak!,Du hast ein Zorchpaket genommen.,,Prenis Zorĉpakon!,¡Recogiste un Zorchpak!,,Poimit zorchpakin!,Vous avez pris un zorchpak!,Felvettél egy Zorkpakkot!,Raccolto uno ZorchZaino!,ゾーチパックをてにいれた!,저치 팩 획득!,Je hebt en zorchpak opgepakt.,Plukket opp en Zorchpak!,Zebrano Paczkę Zorch.,Pegou um Zorchpak!,Apanhaste um Zorchpak!,Ai ridicat un Ghiozdan Zorch!,Получен зорч-рюкзак!,Покупио си зорчпак.,Jag hämtade en Zorchpak!,Bir Zorchpak aldım!,Взято Зорч-сумку! +You got the LAZ Device! Woot!,GOTLAZDEVICE,,,,Získal@[ao_cs] jsi velkodosahový bzukr! Cooo?,Du fik LAZ-enheden! Woot!,Du hast den Flächenzorcher!,,Vi prenis la LAZ-aparaton! Hura!,¡Tienes el dispositivo LAZ! ¡Yuju!,,Sait SAZ-laitteen! Juhuu!,Vous avez pris l'Outil ZZL! Wahou!,Felvetted a LAZ Készüléket! Wáó!,Hai trovato il dispositivo LAZ! Cavolo!,LAZ デバイスをてにいれた! ワァオ!,LAZ 장치 습득! 완전 짱인걸!,Je hebt het LAZ-apparaat! Woot!,Du har LAZ-enheten! Woot!,Zdobył@[irreg_3_pl] urządzenie LAZ! Juhu!,Você achou o Dispositivo LAZ! Oba!,Apanhaste um Dispositivo LAZ! Fixe!,Ai ridicat un Dispozitiv LAZ! Uraa!,Получено устройство зорчирования большого радиуса! Ура!,Добио си ЛАЗ уређај. ВУТ!,Du fick LAZ-enheten! Woot!,LAZ cihazını aldın! Woot!,Ти отримав пристрій LAZ! Супер! +You got the Rapid Zorcher!,GOTRAPIDZORCHER,,,,Získal@[ao_cs] jsi rychlobzukr!,Du fik en Rapid Zorcher!,Du hast den schnellen Zorcher genommen!,,Vi prenis la Rapidzorĉilon!,¡Tienes el Zorcher Rápido!,,Sait pikazorcherin!,Vous avez pris le Zorcheur Rapide!,Felvetted a Gyors Zorkert!,Hai trovato il zorcher rapido!,ラピッドゾーチャー をてにいれた!,속사 자쳐 습득!,Je hebt de snelle Zorcher!,Du har Rapid Zorcher!,Zdobył@[irreg_3_pl] Szybkostrzelny Zorcher!,Você pegou o Zorcher Automático!,Apanhaste o Zorcher Automático!,Ai ridicat un Zorcher cu Foc Rapid!,Получен скорострельный зорчер!,Добио си рапидан зорчер!,Du fick den snabba Zorcher!,Hızlı Zorcher'ı aldın!,Ти отримав Авто Зорчер! +You got the Super Bootspork!,GOTSUPERBOOTSPORK,,,,Získal@[ao_cs] jsi super botovidličku!,Du fik Super Bootspork!,Du hast den Super-Gabelquirl genommen!,,Vi prenis la Superan Ŝargmanĝilaron!,¡Tienes el Súper Cuchador!,,Sait superluhan!,Vous avez pris la Super Fourchette!,Felvetted a Szuper Rotációs Villát!,Hai trovato il super bootspork!,スーパーさきわれスプーン をてにいれた!,부트스포크 습득!,Je hebt de Super Bootspork!,Du har Super Bootspork!,Zdobył@[irreg_3_pl] Super Łyżkowidelec!,Você pegou o Super Garfo!,Apanhaste o Super Garfo-Colher!,Ai ridicat o Super Lingură!,Получена суперложковилка!,Добио си супер чизмо-порк!,Du fick Super Bootspork!,Süper Bootspork'u aldın!,Ти отримав Супер Вилколожку! +You got the Zorch Propulsor!,GOTZORCHPROPULSOR,,,,Získal@[ao_cs] jsi bzukový propulsor!,Du fik Zorch-propulsoren!,Du hast den Propellerzorcher genommen!,,Vi prenis la Zorĉpropulsilon!,¡Tienes el Propulsor de Zorch!,,Sait zorchtyöntimen!,Vous avez pris le Propulseur Zorch!,Felvetted a Zork Elhárítót!,Hai trovato il propulsore zorch!,ロケット ゾーチャー をてにいれた!,저치 추진기 습득!,Je hebt de Zorch Propulsor!,Du fikk Zorch Propulsor!,Zdobył@[irreg_3_pl] Pędnik Zorch!,Você pegou o Propulsor de Zorch!,Apanhaste o Propulsor de Zorch!,Ai ridicat un Accelerator Zorch!,Получен ускоритель хорча!,Добио си зорч погон!,Du fick Zorch Propulsor!,Zorch Propulsor'u aldın!,Ти отримав Зорч-Двигун! +You got the Phasing Zorcher!,GOTPHASINGZORCHER,,,,Získal@[ao_cs] jsi fázovací bzukr!,Du fik Phasing Zorcher!,Du hast den Phasenzorcher genommen!,,Vi prenis la Fluktuantzorĉilon!,¡Tienes el Zorcher de Fase!,,Sait vaiheiszorcherin!,Vous avez pris le Zorcheur phasé!,Felvetted a Fázis Zorkert!,Hai trovato il zorcher a phasing!,フェイシング ゾーチャー をてにいれた!,전자 자쳐 습득!,Je hebt de Fasezorcher!,Du har Phasing Zorcher!,Zdobył@[irreg_3_pl] Fazowy Zorcher!,Você pegou o Zorcher Fásico!,Apanhaste o Zorcher Fásico!,Ai ridicat un Zorcher Fazat!,Получен фазерный зорчер!,Добио си фазни зорчер!,Du fick Fasande Zorcher!,Fazlama Zorcher'ı aldın!,Ти отримав Прискорений Зорчер! +You got the Large Zorcher!,GOTLARGEZORCHER,,,,Získal@[ao_cs] jsi velký bzukr!,Du fik den store Zorcher!,Du hast den großen Zorcher genommen!,,Vi prenis la Grandzorĉilon,¡Tienes el Zorcher Grande!,,Sait ison zorcherin!,Vous avez pris le Zorcheur Large!,Felvetted a Nagy Zorkert!,Hai trovato il zorcher grande!,おおがたゾーチャー をてにいれた!,대형 자쳐 습득!,Je hebt de grote Zorcher!,Du har den store Zorcher!,Zdobył@[irreg_3_pl] Duży Zorcher!,Você pegou o Zorcher Grande!,Apanhaste o Zorcher Grande!,Ai ridicat un Zorcher Mare!,Получен большой зорчер!,Добио си велики зорчер!,Du har den stora Zorcher!,Büyük Zorcher'ı aldınız!,Ти отримав Великий Зорчер! +You got the Mega Zorcher!,GOTSUPERLARGEZORCHER,,,,Získal@[ao_cs] jsi megabzukr!,Du fik Mega Zorcher!,Du hast den Megazorcher genommen!,,Vi prenis la Grandegzorĉilon!,¡Tienes el Mega Zorcher!,,Sait megazorcherin!,Vous avez pris le méga Zorcheur!,Felvetted a Mega Zorkert!,Hai trovato il mega zorcher!,ちょうおおがたゾーチャー をてにいれた!,초대형 자쳐 습득!,Je hebt de Megazorcher!,Du har Mega Zorcher!,Zdobył@[irreg_3_pl] Mega Zorcher!,Você pegou o Mega Zorcher!,Apanhaste o Mega Zorcher!,Ai ridicat un Mega Zorcher!,Получен мегазорчер!,Добио си мега зорчер!,Du har Mega Zorcher!,Mega Zorcher'ı aldın!,Ти отримав Мега Зорчер! +Picked up a Mini Zorcher.,GOTMINIZORCHER,,,,Sebrán minibzukr.,Du har fået en Mini Zorcher.,Du hast einen Minizorcher genommen.,,Prenis Zorĉileton.,Recogiste un Mini Zorcher,,Poimit minizorcherin.,Vous avez pris le Mini Zorcheur.,Felvettél egy Mini Zorkert.,Raccolto un mini zorcher.,こがたゾーチャー をてにいれた。,소형 자쳐 습득.,Je hebt een minizorcher opgepakt.,Plukket opp en Mini Zorcher.,Zebrano Mini Zorcher.,Você pegou um Mini Zorcher.,Apanhaste um Mini Zorcher.,Ai ridicat un Mini Zorcher.,Получен мини-зорчер.,Покупио си мини зорчер!,Du fick en Mini Zorcher.,Bir Mini Zorcher aldın.,Ти отримав Міні Зорчер. +,,Actor tags,,,,,,,,,,,,,,,,,,,,,,,,,, +Spoon,TAG_SPOON,,,,Lžíce,Ske,Löffel,,Kulero,Cuchara,,Lusikka,Cuillère à Botte,Kanál,Cucchiaio ,スプーン,숟가락,Lepel,Skje,Łyżka,Colher,,Lingură,Ложка,Кашика,Sked,Kaşık,Ложка +Super Bootspork,TAG_SPORK,,,,Super botodlička,,Supergabel,,Ega Ŝargmanĝilaro,Súper Cuchador,,Superluha,Super Fourchette,Szuper Rotációs Villa,Super Forcucchiaio,スーパーさきわれスプーン,부트스포크,,,Super Łyżkowidelec,Super Garfo,Super Garfo-Colher,Super Lingură,Суперложковилка,Супер виљушка,Super Bootspork,Süper Bootspork,Супер Вилколожка +Mini Zorcher,TAG_MINIZORCHER,,,,Minibzukr,,Minizorcher,,Zorĉileto,,,Minizorcheri,Mini Zorcheur,Mini Zorker,,こがたゾーチャー,소형 자쳐,Minizorcher,,,Mini Zorcher,,,Мини-зорчер,Мини зорчер,,,Міні Зорчер +Large Zorcher,TAG_LARGEZORCHER,,,,Velký bzukr,Stor Zorcher,Großer Zorcher,,Granda Zorĉilo,Zorcher Grande,,Iso zorcheri,Zorcheur Large,Nagy Zorker,Grosso Zorcher ,おおがたゾーチャー,대형 자쳐,Grote Zorcher,Stor Zorcher,Duży Zorcher,Zorcher Grande,,Zorcher Mare,Большой зорчер,Велики зорчер,Stor Zorcher,Büyük Zorcher,Великий Зорчер +Super-Large Zorcher,TAG_SUPERLARGEZORCHER,,,,Supervelký bzukr,Super-stor Zorcher,Riesenzorcher,,Grandega Zorĉilo,Zorcher Súper Grande,,Superiso zorcheri,Zorcheur Extra-large,Hatalmas Zorker,Zorcher Enorme ,ちょうおおがたゾーチャー,초대형 자쳐,Super grote Zorcher,Super-stor Zorcher,Większy Zorcher,Super Zorcher Grande,,Zorcher Super-Mare,Мегазорчер,Супер-велики зорчер,Superstor Zorcher,Süper Büyük Zorcher,Мега Зорчер +Rapid Zorcher,TAG_RAPIDZORCHER,,,,Rychlobzukr,,Schnellzorcher,,Rapida Zorĉilo,Zorcher Rápido,,Pikazorcheri,Zorcheur Rapide,Gyors Zorker,Zorcher Rapido,れんしゃ ゾーチャー,속사 자쳐,Snelle Zorcher,,Szybkostrzelny Zorcher,Zorcher Automático,,Zorcher cu Foc Rapid,Быстрый зорчер,Рапидни зорчер,Snabbt Zorcher,Hızlı Zorcher,Авто Зорчер +Zorch Propulsor,TAG_ZORCHPROPULSOR,,,,Bzukový propulzor,,Zorch-Propeller,,Zorĉpropulsilo,Propulsor de Zorch,,Zorchtyönnin,Propulseur de Zorch,Zork Elhárító,Propulsore Zorch,ロケット ゾーチ,저치 추진기,,,Pędnik Zorch,Propulsor de Zorch,,Accelerator Zorch,Ускоритель зорча,Погонски зорчер,,,Прискорений Зорчер +Phasing Zorcher,TAG_PHASINGZORCHER,,,,Fázovací bzukr,,Phasenzorcher,,Fluktuantzorĉilo,Zorcher de Fase,,Vaiheiszorcheri,Zorcheur à Phase,Fokozatos Zorker,Zorcher di Fase,フェイシング ゾーチャー,전자 자쳐,Fasezorcher,,Fazowy Zorcher,Zorcher Fásico,,Zorcher Fazat,Фазерный зорчер,Фазни зорчер,Fasande Zorcher,Fazlama Zorcher,Фазовий Зорчер +LAZ Device,TAG_LAZDEVICE,,,,Velkodosahový bzukr,LAZ-enhed,Flächenzorcher,,LAZ-Aparato,Dispositivo LAZ,,SAZ-laite,Zorcheur Zone Large,LAZ Készülék,Dispositivo LAZ,ラージエリアゾーキング デバイス,LAZ 장치,LAZ-aparaat,LAZ-enhet,Urządzenie LAZ,Dispositivo LAZ,,Dispozitiv LAZ,Устройство «ЗБР»,ЛАЗ уређај,LAZ-enhet,LAZ Cihazı,Пристрій LAZ %o was slimed by a flemoid.,OB_COMMONUS,,,,%o byl@[ao_cs] osliznut@[ao_cs] slizounem.,%o blev slimet af en flemoid.,%o wurde von einem Flemoiden vollgeschleimt.,,%o estas ŝlimiga de mukulo.,%o fue pegotead@[ao_esp] por un flemoide.,,%o joutui limatuksen limaamaksi.,%o à été gélifié par un flemoid.,%o el lett trutyizva egy Flemoid által.,%o è stato coperto di slime da un flemoid.,%o はフレモイドにベトベトにされた。,%o 은(는) 플레모이드에 의해 더러워졌습니다.,%o werd afgeslankt door een flemoid.,%o ble slimet av en flemoid.,"%o został@[ao_pl] oszlamion@[adj_pl] przez flemoida. -",%o foi melecad@[ao_ptb] por um flemóide.,%o foi suj@[ao_ptb] por um flemóide.,%o a fost transformat în mâzgă de un flemoid.,Игрока %o обслюнявил флемоид.,%o је унаказио љигавац.,%o bir flemoid tarafından sümüklendi. -%o was slimed by a bipedicus.,OB_BIPEDICUS,,,,%o byl@[ao_cs] osliznut@[ao_cs] dvojnožkem.,%o blev slimet af en bipedicus.,%o wurde von einem Bipedicus vollgeschleimt.,,%o estas ŝlimiga de dupiedmukulo.,%o fue pegotead@[ao_esp] por un bipedicus.,,%o joutui bipedicuksen limaamaksi.,%o à été gélifié@[e_fr] par un bipedicus.,%o el lett trutyizva egy kétlábusz által.,%o è stato coperto di slime da un bipedicus.,%o はバイペディクスにベトベトにされた。,%o 은(는) 바이피디쿠스의 끈쩍한 시야에 걸렸습니다.,%o werd afgeslankt door een bipedicus.,%o ble slimet av en bipedicus.,%o został@[ao_pl] oszlamion@[adj_pl] przez bipedicusa.,%o foi melecad@[ao_ptb] por um bipedicus.,%o foi suj@[ao_ptb] por um bipedicus.,% a fost transformat în mâzgă de un biped.,Игрока %o обслюнявила двуножка.,%o је унаказио двоножни-љигавац.,%o bir bipedicus tarafından sümüklendi. +",%o foi melecad@[ao_ptb] por um flemóide.,%o foi suj@[ao_ptb] por um flemóide.,%o a fost transformat în mâzgă de un flemoid.,Игрока %o обслюнявил флемоид.,%o је унаказио љигавац.,%o blev slemmad av en flemoid.,%o bir flemoid tarafından sümüklendi.,Виберіть рівень важкості: +%o was slimed by a bipedicus.,OB_BIPEDICUS,,,,%o byl@[ao_cs] osliznut@[ao_cs] dvojnožkem.,%o blev slimet af en bipedicus.,%o wurde von einem Bipedicus vollgeschleimt.,,%o estas ŝlimiga de dupiedmukulo.,%o fue pegotead@[ao_esp] por un bipedicus.,,%o joutui bipedicuksen limaamaksi.,%o à été gélifié@[e_fr] par un bipedicus.,%o el lett trutyizva egy kétlábusz által.,%o è stato coperto di slime da un bipedicus.,%o はバイペディクスにベトベトにされた。,%o 은(는) 바이피디쿠스의 끈쩍한 시야에 걸렸습니다.,%o werd afgeslankt door een bipedicus.,%o ble slimet av en bipedicus.,%o został@[ao_pl] oszlamion@[adj_pl] przez bipedicusa.,%o foi melecad@[ao_ptb] por um bipedicus.,%o foi suj@[ao_ptb] por um bipedicus.,% a fost transformat în mâzgă de un biped.,Игрока %o обслюнявила двуножка.,%o је унаказио двоножни-љигавац.,%o blev slemmad av en bipedicus.,%o bir bipedicus tarafından sümüklendi., %o was slimed by an armored bipedicus.,OB_BIPEDICUS2,,,%o was slimed by an armoured bipedicus.,%o byl@[ao_cs] osliznut@[ao_cs] obrněným dvojnožkem.,%o blev slimet af en pansret bipedicus.,%o wurde von einem gepanzerten Bipedicus vollgeschleimt.,,%o estas ŝlimiga de kirasa dupiedmukulo.,%o fue pegotead@[ao_esp] por un bipedicus blindado.,,%o joutui panssaroidun bipedicuksen limaamaksi.,%o à été gélifié@[e_fr] par un bipedicus en armure.,%o el lett trutyizva egy páncélozott kétlábusz által.,%o è stato coperto di slime da un bipedicus corazzato.,%o はアーマードペディクスにベトベトにされた。,%o 은(는) 정예 바이피디쿠스의 찐득한 공격을 받았습니다.,%o werd afgeslankt door een gepantserde bipedicus.,%o ble slimet av en pansret bipedicus.,%o został@[ao_pl] oszlamion@[adj_pl] przez opancerzonego bipedicusa.,%o foi melecad@[ao_ptb] por um bipedicus de armadura.,%o foi suj@[ao_ptb] por um bipedicus de armadura.,"%o a fost transformat în mâzgă de un biped cu -armură.",Игрока %o обслюнявила бронированная двуножка.,%o је унаказио оклопни-љигавац.,%o zırhlı bir bipedicus tarafından sümüklendi. -%o was slimed by a cycloptis.,OB_CYCLOPTIS,,,,%o byl@[ao_cs] osliznut@[ao_cs] jednoočkem.,%o blev slimet af en cycloptis.,%o wurde von einem Cycloptis vollgeschleimt.,,%o estas ŝlimiga de ciklopmukulo,%o fue pegotead@[ao_esp] por un cicloptis.,,%o joutui cycloptiksen limaamaksi.,%o à été gélifié@[e_fr] par un cycloptis.,%o el lett trutyizva egy kükloptisz által.,%o è stato coperto di slime da un cycloptis.,%o はサイクロプティスにベトベトにされた。,%o 은(는) 사이클롭티스 곁에 미끄러졌습니다.,%o werd afgeslankt door een cycloptis.,%o ble slimet av en cycloptis.,%o został@[ao_pl] oszlamion@[adj_pl] przez cykloptisa.,%o foi melecad@[ao_ptb] por um cycloptis.,%o foi suj@[ao_ptb] por um cycloptis.,%o a fost transformat în mâzgă de un ciclioptic.,Игрока %o обслюнявил циклоптис.,%o је унаказио циклогавац.,%o bir cycloptis tarafından sümüklendi. -%o was defeated by the Flembrane.,OB_FLEMBRANE,,,,%o byl@[ao_cs] poražen@[ao_cs] Slizobránou.,%o blev besejret af Flembrane.,%o wurde von der Flembrane geschlagen,,%o estas venkita de La Mukmembrano.,%o fue vencid@[ao_esp] por la Flembrana.,,%o joutui Limakalvon päihittämäksi.,%o à été battu@[e_fr] par la Flembrane.,%o vereséget szenvedett a Slejmbrántól.,%o è stato sconfitto dalla Flembrana.,%o はフレムブランにはいぼくした。,%o 은(는) 역겨운 플렘브레인을 돌파하지 못했습니다.,%o werd verslagen door de Flembrane.,%o ble beseiret av Flembrane.,%o został@[ao_pl] pokonan@[adj_pl] przez Flembranę.,%o foi derrotad@[ao_ptb] pela Flembrane.,,%o a fost învins de Flembrană.,Игрока %o победила Флембрана.,%o је поразио љигомозак.,"%o, Flembrane tarafından yenildi." -%o was spoon fed by %k.,OB_MPSPOON,,,,%o byl@[ao_cs] nakrmen@[ao_cs] lžičkou hráče %k.,%o blev spoon-fodret af %k.,%o wurde von %k mit dem Löffel gefüttert.,,%o estas kulernutrita de %k.,%o fue cucharead@[ao_esp] por %k.,,%k syötti pelaajaa %o lusikalla.,%o à été nourri@[e_fr] a la petite cuillière par %k.,%o kanállal lett etetve %k által.,%o è stato imboccato da %k.,%o は %k にスプーンでたべさせられた。,%k 이(가) %o 을(를) 숟가락으로 맛있게 먹였습니다.,%o werd met een lepel gevoed door %k.,%o ble matet med skje av %k.,%o został@[ao_pl] nakarmion@[adj_pl] łyżką przez %k.,%o foi comid@[ao_ptb] de colher por %k.,,%o a fost hrănit cu lingura de %k.,Игрок %o поел с ложечки у игрока %k.,%o је накашикан од %k,"%o, %k tarafından kaşıkla beslendi." -%o was thoroughly mixed with %k's bootspork.,OB_MPBOOTSPORK,,,,%o byl@[ao_cs] pořádně namíchán@[ao_cs] botovidličkou hráče %k.,%o blev grundigt blandet med %ks støvlespork.,%o wurde von %k gründlich durchgerührt.,,%o estas plene miksita de la ŝargmanĝilaro de %k.,%o fue profundamente revuelt@[ao_esp] por el cubierto de %k.,,%k läpikotaisin sekoitti %o paran luhallaan.,%o à été mélangé@[e_fr] minutieusement par la Super Fourchette de %k.,%o össze lett keverve %k Rotációsvillája által.,%o è stato mischiato ben bene dal bootspork di %k.,%o は %k にスーパーさきわれスプーンでかきまぜられた。,%k 이(가) %o 을(를) 부트스포크로 빙빙 돌렸습니다.,%o werd grondig gemengd met %k's bootspork.,%o ble grundig blandet med %k's bootspork.,%o został@[ao_pl] dokładnie wymieszan@[adj_pl] łyżkowidelcem %k.,%o foi mexid@[ao_ptb] pelo garfo de %k.,%o foi mexid@[ao_ptb] pelo garfo-colher de %k.,%o a fost amestecat bine de lingura lui %k.,Игрок %o тщательно перемешан ложковилкой игрока %k.,%o је темељно измешан од стране %k супер виљушке.,%o iyice karıştırıldı. -%o was zorched by %k.,OB_MPZORCH,,,,%o byl@[ao_cs] bzukrnut@[ao_cs] hráčem %k.,%o blev zorched af %k.,%o wurde von %k gezorcht,,%o estas zorĉita de %k.,%o fue electrizad@[ao_esp] por %k.,,%k zorchasi %o paran.,%o à été zorché@[e_fr] par %k.,%o zorkolva lett %k által.,%o è stato zorchato da %k.,%o は %k にビリビリさせられた。,%o 은(는) %k 의 소형 자쳐 광선에 맞았습니다.,%o werd gezorched door %k.,%o ble svidd av %k.,%o został@[ao_pl] został zazorchowan@[adj_pl] przez %k.,%o foi zorchead@[ao_ptb] por %k.,,%o a fost înlăturat de zorcherul lui %k.,Игрок %o получил заряд из Зорчера %k.,%o је зорчован %k.,"%o, %k tarafından yenildi." -%o was hit by %k's mega-zorcher.,OB_MPMEGAZORCH,,,,%o byl@[ao_cs] trefen@[ao_cs] megabzukrem hráče %k.,%o blev ramt af %k's mega-zorcher.,%o wurde von%ks Mega-Zorcher getroffen,,%o estas trafita de la zorĉilego de %k.,%o fue impactad@[ao_esp] por el mega-zorcher de %k.,,%k osui %o parkaan megazorcherillaan.,%o à été frappé@[e_fr] par le méga zorcheur de %k.,%o elérte %k mega zorkerét.,%o è stato colpito dal mega-zorcher di %k.,%o に %k のメガゾーチャーがヒットした。,%o 은(는) %k 의 초대형 자쳐 광선에 날라갔습니다.,%o werd geraakt door %k's megazorcher.,%o ble truffet av %k's mega-zorcher.,%o został@[ao_pl] trafion@[adj_pl] mega-zorcherem %k.,%o foi atingid@[ao_ptb] pelo mega-zorcher de %k.,,%o a fost lovit de mega-zorcherul lui %k.,Игрок %o подстрелен из Мегазорчера %k.,%o је ударен од стране %k мега-зорчера.,"%o, %k tarafından yenildi." -%o was rapid zorched by %k.,OB_MPRAPIDZORCH,,,,%o dostal@[ao_cs] rychlobzukrem hráče %k.,%o blev hurtigt zorched af %k.,%o wurde von %k schnellgezorcht.,,%o estas rapidzorĉita de %k.,%o fue electrizad@[ao_esp] rápidamente por %k.,,%k pikazorchasi %o paran.,%o à été zorché@[e_fr] rapidement par %k.,%o gyors zorkolva lett %k által.,%o è stato rapid-zorchato da %k.,%o は %k に めをまわされた。,%o 은(는) %k 의 속사 자쳐 때문에 춤을 췄습니다.,%o werd snel zorched door %k.,%o ble raskt svidd av %k.,%o został@[ao_pl] szybko zazorchowan@[adj_pl] przez %k.,%o foi zorchead@[ao_ptb] automaticamente por %k.,,%o a fost învins de zorcherul rapid al lui %k.,Игрок %o получил заряд из быстрого Зорчера %k.,%o је рапидно зорчован %k,"%o, %k tarafından yenildi." -%o was zorched by %k's propulsor.,OB_MPPROPULSOR,,,,%o byl@[ao_cs] bzukrnut@[ao_cs] propulzorem hráče %k.,%o blev zorched af %ks propulsor.,%o wurde von %ks Propeller gezorcht,,%o estas zorĉita de la propulsilo de %k.,%o fue electrizad@[ao_esp] por el propulsor de %k.,,%k zorchasi %o paran työntimellään.,%o à été zorché@[e_fr] par le propulseur de %k.,%o zorkolva lett %k elhárítója által.,%o è stato zorchato dal propulsore di %k.,%o は %k のロケットゾーチャーにあたった。,%o 은(는) %k 의 저치 추진기 쓴 맛을 봤습니다.,%o werd zorched door %k's propulsor.,%o ble zorched av %k's propulsor.,%o został@[ao_pl] zazorchowan@[adj_pl] przez pędnik %k.,%o foi zorchead@[ao_ptb] pelo propulsor de %k.,,%o a fost învins de acceleratorul zorch al lui %k.,Игрок %o получил заряд из ускорителя Зорча %k.,%o је зорчован %k погоном.,"%o, %k tarafından yenildi." -%o was hit by %k's propulsor.,OB_MPP_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráčem %k.,%o blev ramt af %k's propulsor.,%o wurde von %ks Propeller getroffen,,%o estas trafita de la propulsilo de %k.,%o fue impactad@[ao_esp] por el propulsor de %k.,,%k osui %o parkaan työntimellään.,%o à été frappé@[e_fr] par le propulseur de %k.,%o elérte %k elhárítóját.,%o è stato colpito dal propulsore di %k.,%o に %k のロケットゾーチャーがとどいた。,%o 은(는) %k 의 저치 추진기의 방사 능력을 우습게 봤습니다.,%o werd geraakt door %k's propulsor.,%o ble truffet av %k's propulsor.,%o został@[ao_pl] trafion@[adj_pl] pędnikiem %k.,%o foi atingid@[ao_ptb] pelo propulsor de %k.,,%o a fost învins de acceleratorul lui %k.,Игрок %o подстрелен из ускорителя Зорча %k.,%o је ударен %k погоном.,"%o, %k tarafından yenildi." -%o was phase zorched by %k.,OB_MPPHASEZORCH,,,,%o byl@[ao_cs] bzukr-vyfázován@[ao_cs] hráčem %k.,%o blev fasezorched af %k.,%o wurde von %k wegsynchronisiert,,%o estas fluktuantzorĉita de %k.,%o fue electrizad@[ao_esp] en fase por %k.,,%k vaiheiszorchasi %o paran.,%o à été phasé@[e_fr] par %k.,%o fázis zorker áldozata lett %k által.,%o è stato phase-zorchato da %k.,%o は %k によってスベスベにされた。,%o 은(는) %k 의 전자 자쳐에 의해 쓰러졌습니다.,%o was fase zorched door %k.,%o ble fasebrent av %k.,%o został@[ao_pl] został sfazowan@[adj_pl] przez %k.,%o foi atingid@[ao_ptb] pelo zorcher fásico por %k.,,%o a fost înfrânt de zorcherul fazat al lui %k.,Игрок %o получил заряд из фазерного Зорчера %k.,%o је фазно торчован %k.,"%o, %k tarafından yenildi." -%o fell prey to %k's LAZ device.,OB_MPLAZ_BOOM,,,,%o padl@[ao_cs] velkodosahovému bzukru hráče %k.,%o blev offer for %k's LAZ-enhed.,%o fiel %ks Flächenzorcher zum Opfer,,%o iĝis predo de la LAZ-aparato de %k.,%o cayó pres@[ao_esp] ante el dispositivo LAZ de %k.,,%o lankesi pelaajan %k SAZ-laitteen uhriksi.,%o est devenu@[e_fr] la proie du ZZL de %k.,%o prédául lett ejtve %k LAZ készülékével.,%o è stato preda del dispositivo LAZ di %k.,%o は %k のLAZデバイスのえじきになった。,%k 이(가) LAZ 장치를 들기 전에 %o 은(는) 도망쳐야 했습니다.,%o viel ten prooi aan %k's LAZ apparaat.,%o ble offer for %k's LAZ-enhet.,%o stał@[ao_pl] się ofiarą urządzenia LAZ %k.,%o foi vítima do dispositivo LAZ de %k.,,%o a căzut pradă dispozitivului LAZ al lui %k.,Игрок %o склонился перед «ЗБР» игрока %k.,%o је постао жртва %k ЛАЗ уређаја.,"%o, %k tarafından lazzlandı." -%o was lazzed by %k.,OB_MPLAZ_SPLASH,,,,%o byl@[ao_cs] odbzukrován hráčem %k.,%o blev lazzed af %k.,%o wurde von %k weggebeamt.,,%o estas LAZ-ita de %k.,%o fue LAZeado por %k.,,%k sazzasi pelaajaan %o.,%o à été pris@[e_fr] par le ZZL de %k.,%o el lett lazzázva %k által.,%o è stato lazzato da %k.,%o は %k にとかされた。,%o 은(는) %k 의 LAZ 장치 범위를 벗어날 수 없었습니다.,%o werd gelazed door %k.,%o ble lazzed av %k.,%o został@[ao_pl] zLAZowan@[adj_pl] przez %k.,%o foi LAZead@[ao_ptb] por %k.,,%o a fost stropit de dispozitivul LAZ al lui %k.,Игрок %o получил заряд из «ЗБР» игрока %k.,%o је ЛАЗ-овао %k.,"%o, %k tarafından lazzlandı." -,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,, -E1M1: Landing Zone,CHUSTR_E1M1,,,,E1M1: Přistávací zóna,E1M1: Landingszone,E1M1: Landezone,,E1M1: Surterejo,E1M1: Zona de Aterrizaje,,E1M1: Laskeutumisalue,E1M1: La piste d'atterissage,E1M1: Leszállópálya,E1M1: Zona di Atterraggio,E1M1: ちゃくりく ちてん,E1M1: 착륙 지점,E1M1: Landingszone,E1M1: Landingssone,E1M1: Strefa Lądowania,E1M1: Zona de Pouso,E1M1: Zona de Aterragem,E1M1: Pista de Aterizare,E1M1: Зона приземления,Е1М1: Зона слетања,E1M1: İniş Bölgesi -E1M2: Storage Facility,CHUSTR_E1M2,,,,E1M2: Skladiště,E1M2: Opbevaringsanlæg,E1M2: Lagerhalle,,E1M2: Stokejo,E1M2: Instalación de Almacenamiento,,E1M2: Varastolaitos,E1M2: Le centre de stockage,E1M2: Raktárépület,E1M2: Struttura di Immagazzinamento,E1M2: ほかん しせつ,E1M2: 저장 시설,E1M2: Opslagfaciliteit,E1M2: Lagringsanlegg,E1M2: Magazyn,E1M2: Depósito,E1M2: Armazém,E1M2: Depozitul,E1M2: Хранилище,Е1М2: Складиште,E1M2: Depolama Tesisi -E1M3: Experimental Lab,CHUSTR_E1M3,,,,E1M3: Testovací laboratoř,E1M3: Forsøgslaboratorium,E1M3: Experimentelles Labor,,E1M3: Eksperimenta Laboratorio,E1M3: Laboratorio Experimental,,E1M3: Koelaboratorio,E1M3: Les labos expérimentaux,E1M3: Laboratórium,E1M3: Laboratorio Sperimentale,E1M3: じっけんしつ,E1M3: 연구소,E1M3: Experimenteel laboratorium,E1M3: Eksperimentelt laboratorium,E1M3: Laboratorium Eksperymentalne,E1M3: Laboratório de Experimentos,E1M3: Laboratório Experimental,E1M2: Laboratorul,E1M3: Лаборатория,Е1М3: Експериментална лабораторија,E1M3: Deneysel Laboratuvar -E1M4: Arboretum,CHUSTR_E1M4,,,,,,,,E1M4: Arbejo,E1M4: Arboreto,,,E1M4: L'Arboretum,E1M4: Arborétum,E1M4: Arboreto,E1M4: じゅもくえん,E1M4: 수목원,E1M4: Arboretum,E1M4: Arboretet,E1M4: Arboretum,E1M4: Arvoredo,,E1M4: Arboretum,E1M4: Дендрарий,Е1М4: Ботаничка башта,E1M4: Arboretum -E1M5: Caverns of Bazoik,CHUSTR_E1M5,,,,E1M5: Bazoikské jeskyně,E1M5: Bazoiks grotter,E1M5: Die Höhlen von Bazoik,,E1M5: Kavernoj de Bazojko,E1M5: Cavernas de Bazoik,,E1M5: Bazoikin luolastot,E1M5: Les cavernes de Bazoik,E1M5: Bazoik barlangjai,E1M5: Caverne di Bazoik,E1M5: バゾイクの どうくつ,E1M5: 바조이크의 대동굴,E1M5: Grotten van Bazoik,E1M5: Grottene til Bazoik,E1M5: Jaskinie Bazoik,E1M5: Cavernas de Bazoik,,E1M5: Cavernele lui Bazoik,E1M5: Пещеры Базоика,Е1М5: Пећине Базоика,E1M5: Bazoik Mağaraları +armură.",Игрока %o обслюнявила бронированная двуножка.,%o је унаказио оклопни-љигавац.,%o blev slemmad av en bepansrad bipedicus.,%o zırhlı bir bipedicus tarafından sümüklendi., +%o was slimed by a cycloptis.,OB_CYCLOPTIS,,,,%o byl@[ao_cs] osliznut@[ao_cs] jednoočkem.,%o blev slimet af en cycloptis.,%o wurde von einem Cycloptis vollgeschleimt.,,%o estas ŝlimiga de ciklopmukulo,%o fue pegotead@[ao_esp] por un cicloptis.,,%o joutui cycloptiksen limaamaksi.,%o à été gélifié@[e_fr] par un cycloptis.,%o el lett trutyizva egy kükloptisz által.,%o è stato coperto di slime da un cycloptis.,%o はサイクロプティスにベトベトにされた。,%o 은(는) 사이클롭티스 곁에 미끄러졌습니다.,%o werd afgeslankt door een cycloptis.,%o ble slimet av en cycloptis.,%o został@[ao_pl] oszlamion@[adj_pl] przez cykloptisa.,%o foi melecad@[ao_ptb] por um cycloptis.,%o foi suj@[ao_ptb] por um cycloptis.,%o a fost transformat în mâzgă de un ciclioptic.,Игрока %o обслюнявил циклоптис.,%o је унаказио циклогавац.,%o blev slemmad av en cycloptis.,%o bir cycloptis tarafından sümüklendi., +%o was defeated by the Flembrane.,OB_FLEMBRANE,,,,%o byl@[ao_cs] poražen@[ao_cs] Slizobránou.,%o blev besejret af Flembrane.,%o wurde von der Flembrane geschlagen,,%o estas venkita de La Mukmembrano.,%o fue vencid@[ao_esp] por la Flembrana.,,%o joutui Limakalvon päihittämäksi.,%o à été battu@[e_fr] par la Flembrane.,%o vereséget szenvedett a Slejmbrántól.,%o è stato sconfitto dalla Flembrana.,%o はフレムブランにはいぼくした。,%o 은(는) 역겨운 플렘브레인을 돌파하지 못했습니다.,%o werd verslagen door de Flembrane.,%o ble beseiret av Flembrane.,%o został@[ao_pl] pokonan@[adj_pl] przez Flembranę.,%o foi derrotad@[ao_ptb] pela Flembrane.,,%o a fost învins de Flembrană.,Игрока %o победила Флембрана.,%o је поразио љигомозак.,%o blev besegrad av Flembrane.,"%o, Flembrane tarafından yenildi.", +%o was spoon fed by %k.,OB_MPSPOON,,,,%o byl@[ao_cs] nakrmen@[ao_cs] lžičkou hráče %k.,%o blev spoon-fodret af %k.,%o wurde von %k mit dem Löffel gefüttert.,,%o estas kulernutrita de %k.,%o fue cucharead@[ao_esp] por %k.,,%k syötti pelaajaa %o lusikalla.,%o à été nourri@[e_fr] a la petite cuillière par %k.,%o kanállal lett etetve %k által.,%o è stato imboccato da %k.,%o は %k にスプーンでたべさせられた。,%k 이(가) %o 을(를) 숟가락으로 맛있게 먹였습니다.,%o werd met een lepel gevoed door %k.,%o ble matet med skje av %k.,%o został@[ao_pl] nakarmion@[adj_pl] łyżką przez %k.,%o foi comid@[ao_ptb] de colher por %k.,,%o a fost hrănit cu lingura de %k.,Игрок %o поел с ложечки у игрока %k.,%o је накашикан од %k,%o blev matad med sked av %k.,"%o, %k tarafından kaşıkla beslendi.", +%o was thoroughly mixed with %k's bootspork.,OB_MPBOOTSPORK,,,,%o byl@[ao_cs] pořádně namíchán@[ao_cs] botovidličkou hráče %k.,%o blev grundigt blandet med %ks støvlespork.,%o wurde von %k gründlich durchgerührt.,,%o estas plene miksita de la ŝargmanĝilaro de %k.,%o fue profundamente revuelt@[ao_esp] por el cubierto de %k.,,%k läpikotaisin sekoitti %o paran luhallaan.,%o à été mélangé@[e_fr] minutieusement par la Super Fourchette de %k.,%o össze lett keverve %k Rotációsvillája által.,%o è stato mischiato ben bene dal bootspork di %k.,%o は %k にスーパーさきわれスプーンでかきまぜられた。,%k 이(가) %o 을(를) 부트스포크로 빙빙 돌렸습니다.,%o werd grondig gemengd met %k's bootspork.,%o ble grundig blandet med %k's bootspork.,%o został@[ao_pl] dokładnie wymieszan@[adj_pl] łyżkowidelcem %k.,%o foi mexid@[ao_ptb] pelo garfo de %k.,%o foi mexid@[ao_ptb] pelo garfo-colher de %k.,%o a fost amestecat bine de lingura lui %k.,Игрок %o тщательно перемешан ложковилкой игрока %k.,%o је темељно измешан од стране %k супер виљушке.,%o blev ordentligt uppblandad med %ks bootspork.,%o iyice karıştırıldı., +%o was zorched by %k.,OB_MPZORCH,,,,%o byl@[ao_cs] bzukrnut@[ao_cs] hráčem %k.,%o blev zorched af %k.,%o wurde von %k gezorcht,,%o estas zorĉita de %k.,%o fue electrizad@[ao_esp] por %k.,,%k zorchasi %o paran.,%o à été zorché@[e_fr] par %k.,%o zorkolva lett %k által.,%o è stato zorchato da %k.,%o は %k にビリビリさせられた。,%o 은(는) %k 의 소형 자쳐 광선에 맞았습니다.,%o werd gezorched door %k.,%o ble svidd av %k.,%o został@[ao_pl] został zazorchowan@[adj_pl] przez %k.,%o foi zorchead@[ao_ptb] por %k.,,%o a fost înlăturat de zorcherul lui %k.,Игрок %o получил заряд из зорчера %k.,%o је зорчован %k.,%o blev zorchad av %k.,"%o, %k tarafından yenildi.", +%o was hit by %k's mega-zorcher.,OB_MPMEGAZORCH,,,,%o byl@[ao_cs] trefen@[ao_cs] megabzukrem hráče %k.,%o blev ramt af %k's mega-zorcher.,%o wurde von%ks Mega-Zorcher getroffen,,%o estas trafita de la zorĉilego de %k.,%o fue impactad@[ao_esp] por el mega-zorcher de %k.,,%k osui %o parkaan megazorcherillaan.,%o à été frappé@[e_fr] par le méga zorcheur de %k.,%o elérte %k mega zorkerét.,%o è stato colpito dal mega-zorcher di %k.,%o に %k のメガゾーチャーがヒットした。,%o 은(는) %k 의 초대형 자쳐 광선에 날라갔습니다.,%o werd geraakt door %k's megazorcher.,%o ble truffet av %k's mega-zorcher.,%o został@[ao_pl] trafion@[adj_pl] mega-zorcherem %k.,%o foi atingid@[ao_ptb] pelo mega-zorcher de %k.,,%o a fost lovit de mega-zorcherul lui %k.,Игрок %o подстрелен из мегазорчера %k.,%o је ударен од стране %k мега-зорчера.,%o blev träffad av %ks mega-zorcher.,"%o, %k tarafından yenildi.", +%o was rapid zorched by %k.,OB_MPRAPIDZORCH,,,,%o dostal@[ao_cs] rychlobzukrem hráče %k.,%o blev hurtigt zorched af %k.,%o wurde von %k schnellgezorcht.,,%o estas rapidzorĉita de %k.,%o fue electrizad@[ao_esp] rápidamente por %k.,,%k pikazorchasi %o paran.,%o à été zorché@[e_fr] rapidement par %k.,%o gyors zorkolva lett %k által.,%o è stato rapid-zorchato da %k.,%o は %k に めをまわされた。,%o 은(는) %k 의 속사 자쳐 때문에 춤을 췄습니다.,%o werd snel zorched door %k.,%o ble raskt svidd av %k.,%o został@[ao_pl] szybko zazorchowan@[adj_pl] przez %k.,%o foi zorchead@[ao_ptb] automaticamente por %k.,,%o a fost învins de zorcherul rapid al lui %k.,Игрок %o получил заряд из быстрого зорчера %k.,%o је рапидно зорчован %k,%o blev snabbt zorchad av %k.,"%o, %k tarafından yenildi.", +%o was zorched by %k's propulsor.,OB_MPPROPULSOR,,,,%o byl@[ao_cs] bzukrnut@[ao_cs] propulzorem hráče %k.,%o blev zorched af %ks propulsor.,%o wurde von %ks Propeller gezorcht,,%o estas zorĉita de la propulsilo de %k.,%o fue electrizad@[ao_esp] por el propulsor de %k.,,%k zorchasi %o paran työntimellään.,%o à été zorché@[e_fr] par le propulseur de %k.,%o zorkolva lett %k elhárítója által.,%o è stato zorchato dal propulsore di %k.,%o は %k のロケットゾーチャーにあたった。,%o 은(는) %k 의 저치 추진기 쓴 맛을 봤습니다.,%o werd zorched door %k's propulsor.,%o ble zorched av %k's propulsor.,%o został@[ao_pl] zazorchowan@[adj_pl] przez pędnik %k.,%o foi zorchead@[ao_ptb] pelo propulsor de %k.,,%o a fost învins de acceleratorul zorch al lui %k.,Игрок %o получил заряд из ускорителя зорча %k.,%o је зорчован %k погоном.,%o blev zorchad av %ks propulsor.,"%o, %k tarafından yenildi.", +%o was hit by %k's propulsor.,OB_MPP_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráčem %k.,%o blev ramt af %k's propulsor.,%o wurde von %ks Propeller getroffen,,%o estas trafita de la propulsilo de %k.,%o fue impactad@[ao_esp] por el propulsor de %k.,,%k osui %o parkaan työntimellään.,%o à été frappé@[e_fr] par le propulseur de %k.,%o elérte %k elhárítóját.,%o è stato colpito dal propulsore di %k.,%o に %k のロケットゾーチャーがとどいた。,%o 은(는) %k 의 저치 추진기의 방사 능력을 우습게 봤습니다.,%o werd geraakt door %k's propulsor.,%o ble truffet av %k's propulsor.,%o został@[ao_pl] trafion@[adj_pl] pędnikiem %k.,%o foi atingid@[ao_ptb] pelo propulsor de %k.,,%o a fost învins de acceleratorul lui %k.,Игрок %o подстрелен из ускорителя зорча %k.,%o је ударен %k погоном.,%o blev träffad av %ks propulsor.,"%o, %k tarafından yenildi.", +%o was phase zorched by %k.,OB_MPPHASEZORCH,,,,%o byl@[ao_cs] bzukr-vyfázován@[ao_cs] hráčem %k.,%o blev fasezorched af %k.,%o wurde von %k wegsynchronisiert,,%o estas fluktuantzorĉita de %k.,%o fue electrizad@[ao_esp] en fase por %k.,,%k vaiheiszorchasi %o paran.,%o à été phasé@[e_fr] par %k.,%o fázis zorker áldozata lett %k által.,%o è stato phase-zorchato da %k.,%o は %k によってスベスベにされた。,%o 은(는) %k 의 전자 자쳐에 의해 쓰러졌습니다.,%o was fase zorched door %k.,%o ble fasebrent av %k.,%o został@[ao_pl] został sfazowan@[adj_pl] przez %k.,%o foi atingid@[ao_ptb] pelo zorcher fásico por %k.,,%o a fost înfrânt de zorcherul fazat al lui %k.,Игрок %o получил заряд из фазерного зорчера %k.,%o је фазно торчован %k.,%o blev faszorchad av %k.,"%o, %k tarafından yenildi.", +%o fell prey to %k's LAZ device.,OB_MPLAZ_BOOM,,,,%o padl@[ao_cs] velkodosahovému bzukru hráče %k.,%o blev offer for %k's LAZ-enhed.,%o fiel %ks Flächenzorcher zum Opfer,,%o iĝis predo de la LAZ-aparato de %k.,%o cayó pres@[ao_esp] ante el dispositivo LAZ de %k.,,%o lankesi pelaajan %k SAZ-laitteen uhriksi.,%o est devenu@[e_fr] la proie du ZZL de %k.,%o prédául lett ejtve %k LAZ készülékével.,%o è stato preda del dispositivo LAZ di %k.,%o は %k のLAZデバイスのえじきになった。,%k 이(가) LAZ 장치를 들기 전에 %o 은(는) 도망쳐야 했습니다.,%o viel ten prooi aan %k's LAZ apparaat.,%o ble offer for %k's LAZ-enhet.,%o stał@[ao_pl] się ofiarą urządzenia LAZ %k.,%o foi vítima do dispositivo LAZ de %k.,,%o a căzut pradă dispozitivului LAZ al lui %k.,Игрок %o склонился перед «ЗБР» игрока %k.,%o је постао жртва %k ЛАЗ уређаја.,%o föll offer för %ks LAZ-enhet.,"%o, %k tarafından lazzlandı.", +%o was lazzed by %k.,OB_MPLAZ_SPLASH,,,,%o byl@[ao_cs] odbzukrován hráčem %k.,%o blev lazzed af %k.,%o wurde von %k weggebeamt.,,%o estas LAZ-ita de %k.,%o fue LAZeado por %k.,,%k sazzasi pelaajaan %o.,%o à été pris@[e_fr] par le ZZL de %k.,%o el lett lazzázva %k által.,%o è stato lazzato da %k.,%o は %k にとかされた。,%o 은(는) %k 의 LAZ 장치 범위를 벗어날 수 없었습니다.,%o werd gelazed door %k.,%o ble lazzed av %k.,%o został@[ao_pl] zLAZowan@[adj_pl] przez %k.,%o foi LAZead@[ao_ptb] por %k.,,%o a fost stropit de dispozitivul LAZ al lui %k.,Игрок %o получил заряд из «ЗБР» игрока %k.,%o је ЛАЗ-овао %k.,%o blev lazzad av %k.,"%o, %k tarafından lazzlandı.", +,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,,,, +E1M1: Landing Zone,CHUSTR_E1M1,,,,E1M1: Přistávací zóna,E1M1: Landingszone,E1M1: Landezone,,E1M1: Surterejo,E1M1: Zona de Aterrizaje,,E1M1: Laskeutumisalue,E1M1: La piste d'atterissage,E1M1: Leszállópálya,E1M1: Zona di Atterraggio,E1M1: ちゃくりく ちてん,E1M1: 착륙 지점,E1M1: Landingszone,E1M1: Landingssone,E1M1: Strefa Lądowania,E1M1: Zona de Pouso,E1M1: Zona de Aterragem,E1M1: Pista de Aterizare,E1M1: Зона приземления,Е1М1: Зона слетања,E1M1: Landningszon,E1M1: İniş Bölgesi,E1M1: Зона висадки +E1M2: Storage Facility,CHUSTR_E1M2,,,,E1M2: Skladiště,E1M2: Opbevaringsanlæg,E1M2: Lagerhalle,,E1M2: Stokejo,E1M2: Instalación de Almacenamiento,,E1M2: Varastolaitos,E1M2: Le centre de stockage,E1M2: Raktárépület,E1M2: Struttura di Immagazzinamento,E1M2: ほかん しせつ,E1M2: 저장 시설,E1M2: Opslagfaciliteit,E1M2: Lagringsanlegg,E1M2: Magazyn,E1M2: Depósito,E1M2: Armazém,E1M2: Depozitul,E1M2: Хранилище,Е1М2: Складиште,E1M2: Förvaringsanläggning,E1M2: Depolama Tesisi,E1M2: Сховище +E1M3: Experimental Lab,CHUSTR_E1M3,,,,E1M3: Testovací laboratoř,E1M3: Forsøgslaboratorium,E1M3: Experimentelles Labor,,E1M3: Eksperimenta Laboratorio,E1M3: Laboratorio Experimental,,E1M3: Koelaboratorio,E1M3: Les labos expérimentaux,E1M3: Laboratórium,E1M3: Laboratorio Sperimentale,E1M3: じっけんしつ,E1M3: 연구소,E1M3: Experimenteel laboratorium,E1M3: Eksperimentelt laboratorium,E1M3: Laboratorium Eksperymentalne,E1M3: Laboratório de Experimentos,E1M3: Laboratório Experimental,E1M2: Laboratorul,E1M3: Лаборатория,Е1М3: Експериментална лабораторија,E1M3: Experimentellt labb,E1M3: Deneysel Laboratuvar,E1M3: Експериментальна лабораторія +E1M4: Arboretum,CHUSTR_E1M4,,,,,,,,E1M4: Arbejo,E1M4: Arboreto,,,E1M4: L'Arboretum,E1M4: Arborétum,E1M4: Arboreto,E1M4: じゅもくえん,E1M4: 수목원,,E1M4: Arboretet,,E1M4: Arvoredo,,,E1M4: Дендрарий,Е1М4: Ботаничка башта,,,E1M4: Дендропарк +E1M5: Caverns of Bazoik,CHUSTR_E1M5,,,,E1M5: Bazoikské jeskyně,E1M5: Bazoiks grotter,E1M5: Die Höhlen von Bazoik,,E1M5: Kavernoj de Bazojko,E1M5: Cavernas de Bazoik,,E1M5: Bazoikin luolastot,E1M5: Les cavernes de Bazoik,E1M5: Bazoik barlangjai,E1M5: Caverne di Bazoik,E1M5: バゾイクの どうくつ,E1M5: 바조이크의 대동굴,E1M5: Grotten van Bazoik,E1M5: Grottene til Bazoik,E1M5: Jaskinie Bazoik,E1M5: Cavernas de Bazoik,,E1M5: Cavernele lui Bazoik,E1M5: Пещеры Базоика,Е1М5: Пећине Базоика,E1M5: Bazoiks grottor,E1M5: Bazoik Mağaraları,E1M5: Печери Базойка "Mission accomplished. Are you prepared for the next mission? @@ -2061,7 +2070,16 @@ Apasă tasta Esc pentru a continua...","Миссия выполнена. -Притисни ESC да наставиш...","Görev tamamlandı. +Притисни ESC да наставиш...","Uppdraget slutfört. + +Är du redo för nästa uppdrag? + + + + + + +Tryck på escape-tangenten för att fortsätta...","Görev tamamlandı. Bir sonraki görev için hazır mısınız? @@ -2070,10 +2088,19 @@ Bir sonraki görev için hazır mısınız? -Devam etmek için kaçış tuşuna basın..." -You've done it!,CE2TEXT,,,,Dokázal@[ao_cs] jsi to!,Du har gjort det!,Du hast es geschafft!,,Vi sukcesis!,¡Lo hiciste!,,Teit sen!,Vous l'avez fait!,Megcsináltad!,Ce l'hai fatta!,よくやった!,해내셨습니다!,Het is je gelukt!,Du klarte det!,Udało ci się!,Você conseguiu!,Conseguiste!,Ai reușit!,Вы справились!,Урадио си то!,Başardınız! -Wonderful Job!,CE3TEXT,,,,Skvělá práce!,Vidunderligt arbejde!,Großartige Arbeit!,,Mirindan Laboron!,¡Maravilloso!,,Hienoa työtä!,Merveilleux travail!,Tökéletes munka!,Meraviglioso!,ワンダフル!,멋지게 잘하셨습니다!,Geweldig werk!,Fantastisk jobb!,Dobra Robota!,Ótimo trabalho!,,O treabă minunată!,Превосходная работа!,Изванредан посао!,Harika bir iş! -Fantastic,CE4TEXT,,,,Fantastické,Fantastisk,Fantastisch,,Mirinda,¡Fantástico!,,Fantastista,Fantastique!,Fantasztikus!,Fantastico,すばらしい!,환상적,Fantastisch,Fantastisk!,Fantastycznie,Fantástico,,Fantastic,Великолепно.,Фантастично,Fantastik +Devam etmek için kaçış tuşuna basın...","Місія виконана. + +Ти готов@[ao_ua] до наступної місії? + + + + + + +Натисни клавішу escape, щоб продовжити..." +You've done it!,CE2TEXT,,,,Dokázal@[ao_cs] jsi to!,Du har gjort det!,Du hast es geschafft!,,Vi sukcesis!,¡Lo hiciste!,,Teit sen!,Vous l'avez fait!,Megcsináltad!,Ce l'hai fatta!,よくやった!,해내셨습니다!,Het is je gelukt!,Du klarte det!,Udało ci się!,Você conseguiu!,Conseguiste!,Ai reușit!,Вы справились!,Урадио си то!,Du har gjort det!,Başardınız!,У тебе вийшло! +Wonderful Job!,CE3TEXT,,,,Skvělá práce!,Vidunderligt arbejde!,Großartige Arbeit!,,Mirindan Laboron!,¡Maravilloso!,,Hienoa työtä!,Merveilleux travail!,Tökéletes munka!,Meraviglioso!,ワンダフル!,멋지게 잘하셨습니다!,Geweldig werk!,Fantastisk jobb!,Dobra Robota!,Ótimo trabalho!,,O treabă minunată!,Превосходная работа!,Изванредан посао!,Underbart jobb!,Harika bir iş!,Чудова робота! +Fantastic,CE4TEXT,,,,Fantastické,Fantastisk,Fantastisch,,Mirinda,¡Fantástico!,,Fantastista,Fantastique!,Fantasztikus!,Fantastico,すばらしい!,환상적,Fantastisch,Fantastisk!,Fantastycznie,Fantástico,,,Великолепно.,Фантастично,Fantastiskt,Fantastik,Фантастика "You can't do load while in a net quest! Press a key.",CLOADNET,,,,"Nemůžeš použít načtení, když hraješ síťové pátrání! @@ -2117,9 +2144,12 @@ Apasă orice tastă.","Невозможно загрузить сохранен Нажмите любую клавишу.","Не можете учитати док сте у мрежној потрази! -Притисните тастер.","Bir ağ görevindeyken yükleme yapamazsınız! +Притисните тастер.","Du kan inte göra lastning när du är i ett nätspel! +Tryck på en tangent.","Bir ağ görevindeyken yükleme yapamazsınız! -Bir tuşa basın." +Bir tuşa basın.","Ти не можеш завантажитись під час мережевого квесту! + +Натисни будь яку клавішу." "Quicksave over your quest named '%s'? @@ -2188,11 +2218,16 @@ Apasă Y sau N.","Выполнить быстрое сохранение зад «%s»? -Нажмите Y или N.",Брзо-сачувајте преко ваше потраге назване '%s'? Притисните Y или N.,"%s' +Нажмите Y или N.",Брзо-сачувајте преко ваше потраге назване '%s'? Притисните Y или N.,"Snabbt spara över ditt spel som heter %s? +Tryck på Y eller N.","%s' adlı oyununuzun üzerine hızlı kaydetme? -Y veya N tuşuna basın." +Y veya N tuşuna basın.","Швидко перезаписати твій квест під назвою + +'%s'? + +Натисни Y або N." "You can't quickload during a netquest! Press a key.",QLOADNET,,chex,,"Nemůžeš použít rychlé načtení , když hraješ síťové pátrání! @@ -2238,8 +2273,12 @@ Apasă orice tastă.","Невозможно загрузить быстрое с Нажмите любую клавишу.","Не можете брзо-учитати док сте у мрежној потрази! -Притисните тастер.","Bir ağ oyunu sırasında hızlı yükleme yapamazsınız! -Bir tuşa basın." +Притисните тастер.","Du kan inte snabbladda under ett nätspel! + +Tryck på en tangent.","Bir ağ oyunu sırasında hızlı yükleme yapamazsınız! +Bir tuşa basın.","Ти не можеш швидко завантажитись під час мережевого квесту! + +Натисни будь яку клавішу." "Do you want to quickload the quest named '%s'? @@ -2312,11 +2351,16 @@ Apasă Y sau N.","Загрузить быстрое сохранение зад Нажмите Y или N.","Да ли желиш да брзо-учиташ потрагу названу '%s'? -Притисните Y или N.","%s' +Притисните Y или N.","Vill du snabbladda spelet som heter ""%s""? +Tryck på Y eller N.","%s' adlı oyunu hızlı yüklemek istiyor musunuz? -Y veya N tuşuna basın." +Y veya N tuşuna basın.","Швидко завантажити твій квест під назвою + +'%s'? + +Натисни Y або N." "You can't start a new quest while in a network quest. @@ -2366,10 +2410,14 @@ Apasă orice tastă.","Невозможно начать новое задани Нажмите любую клавишу.","Не можете почети нову потрагу док сте у мрежној потрази. -Притисните тастер.","Yeni bir görev başlatamazsınız +Притисните тастер.","Du kan inte starta ett nytt spel när du är i ett nätspel. + +Tryck på en tangent.","Yeni bir görev başlatamazsınız bir ağ görevindeyken. -Bir tuşa basın." +Bir tuşa basın.","Ти не можеш почати новий квест під час мережевого квесту! + +Натисни будь яку клавішу." "Careful, this will be tough. Do you wish to continue? @@ -2429,10 +2477,16 @@ Apasă Y sau N.","Осторожно — будет сложно. Нажмите Y или N.","Пажљиво, ово је ће бити тешко. Да ли желиш да наставиш? -Притисните Y или N.","Dikkatli ol, bu zor olacak. +Притисните Y или N.","Försiktigt, det här kommer att bli svårt. +Vill du fortsätta? + +Tryck på Y eller N.","Dikkatli ol, bu zor olacak. Devam etmek istiyor musunuz? -Y veya N tuşuna basın." +Y veya N tuşuna basın.","Бережись, тут буде скрутно. +Хочеш продовжити? + +Натисни Y або N." "This is Chex(R) Quest. look for future levels at www.chexquest.com. @@ -2511,11 +2565,17 @@ Apasă orice tastă.","Вы играете в Chex(R) Quest. Остальные нивое на www.chexquest.com. -Притисните Y или N.","Bu Chex(R) Görevi. +Притисните Y или N.","Det här är Chex(R) Quest. + +framtida nivåer på www.chexquest.com. + +Tryck på en tangent.","Bu Chex(R) Görevi. www.chexquest.com adresinde gelecekteki seviyeler. -Bir tuşa basın." +Bir tuşa basın.","Ти граєш в Chex(R) Quest. Інші рівні тут - www.chexquest.com. + +Натисни Y або N." "You can't end a netquest! Press a key.",NETEND,,chex,,"Nemůžeš ukončit síťové pátrání! @@ -2558,9 +2618,12 @@ Apasă orice tastă.","Невозможно прервать сетевое за Нажмите любую клавишу.","Не можете завршити мрежну потрагу! -Притисните тастер.","Bir netquest'i sonlandıramazsınız! +Притисните тастер.","Du kan inte avsluta ett nätspel! +Tryck på en tangent.","Bir netquest'i sonlandıramazsınız! + +Bir tuşa basın.","Ти не можеш завершити мережевий квест! -Bir tuşa basın." +Натисни будь яку клавішу." "Are you sure you want to end the quest? Press Y or N.",ENDGAME,,chex,,"Opravdu si přeješ ukončit pátrání? @@ -2602,710 +2665,727 @@ Apasă Y sau N.","Вы точно хотите завершить задание Нажмите Y или N.","Да ли си сигуран да желиш да завршиш трагање? -Притисни Y или N.","Görevi sonlandırmak istediğinizden emin misiniz? - -Y veya N tuşuna basın." -Invincible Mode ON,STSTR_DQDON,,chex,,Režim nezranitelnosti ZAP,Uovervindelig tilstand TIL,Unbesiegbarer Modus EIN,,Nevenkebla-reĝimo ŜALTITA,Modo invencible ACTIVADO,,Kuolemattomuustila PÄÄLLÄ,Mode invincible ON,Sérthetetlen mód BE,Modalità invincibile attivata,むてきモード オン,무적 모드 켬,Onoverwinnelijke modus AAN,Uovervinnelig modus PÅ,Tryb Niewrażliwości WŁĄCZONY,Modo invencível ATIVADO,,Modul Invincibil ACTIVAT,Режим неуязвимости ВКЛЮЧЁН,Неуништив УКЉУЧЕН,Yenilmez Mod AÇIK -Invincible Mode OFF,STSTR_DQDOFF,,chex,,Režim nezranitelnosti VYP,Uovervindelig tilstand FRA,Unbesiegbarer Modus AUS,,Nevenkebla-reĝimo MALŜALTITA,Modo invencible DESACTIVADO,,Kuolemattomuustila POIS PÄÄLLÄ,Mode invincible OFF,Sérthetetlen mód KI,Modalità invincibile disattivata,むてきモード オフ,무적 모드 끔,Onoverwinnelijke modus UIT,Uovervinnelig modus AV,Tryb Niewrażliwości WYŁĄCZONY,Modo invencível DESATIVADO,,Modul Invincibil DEZACTIVAT,Режим неуязвимости ОТКЛЮЧЁН,Неуништив ИСКЉУЧЕН,Yenilmez Modu KAPALI -Zorch Added,STSTR_FAADDED,,chex,,Bzukry přidány,Zorch tilføjet,Zorch hinzugefügt,,Zorĉo Aldonita,Zorch añadido,,Zorch lisätty,Zorch Ajouté,Szörcs felvéve,Zorch aggiunto,ゾーチ ついか,모든 저치 에너지 추가,Zorch toegevoegd,Zorch lagt til,Zorch dodany,Zorch adicionado,,Zorcher Adăugat,Добавлен Зорч,Зорч додат,Zorch Eklendi -Super Zorch Added,STSTR_KFAADDED,,chex,,Superbzukry přidány,Super Zorch Tilføjet,Super Zorch hinzugefügt,,Supera Zorĉo Aldonita,Súper Zorch añadido,,Superzorch lisätty,Super Zorch Ajouté,Szuper Szörcs feléve,Super Zorch aggiunto,スーパーゾーチ ついか,모든 아이템 습득!,Super Zorch toegevoegd,Super Zorch lagt til,Super Zorch dodany,Super Zorch adicionado,,Super Lingură Adăugată,Добавлен Суперзорч,Супер зорч додат,Süper Zorch Eklendi -... Eat Chex(R)!,STSTR_CHOPPERS,,chex,,... Jez Chex(R)!,... Spis Chex(R)!,...Iss Chex(R)!,,... Manĝu Chex(R)-on!,... Come Chex(R),,... Syö Chex(R):ä!,... Mangez du Chex(R)!,...egyél Chex(R)-et!,... Mangia I Chex(R)!,...Chex(R)をたべよう!,... 첵스(R) 를 많이 먹자!,... Eet Chex(R)!,... Spis Chex(R)!,... jedz płatki Chex(R)!,... coma Chex(R)!,,... Mănâncă Chex(R)!,...ешь Chex(R)!,... Једи Chex(R)!,... Chex(R) yiyin! -Mini Zorch Charge,AMMO_CLIP,,chex,,Minibzukrové náboje,Mini Zorch ladning,Minizorcher-Ladung,,Zorĉileto-Ŝarĝo,Carga de Mini Zorch,,Minizorchvaraus,Charge Zorch,Mini szörcs töltet,Ricarica Mini Zorch,ミニゾーチ ほきゅう,소형 저치 전지,Mini Zorchlading,Mini Zorch ladning,Mini Ładunek Zorch,Recarga de Mini Zorch,,Mini Încărcătură pentru Zorcher,Заряд мини-Зорчера,Мини зорч пуњач,Mini Zorch Şarjı -Large Zorcher Charge,AMMO_SHELLS,,chex,,Velkobzukrové náboje,Stor Zorch ladning,Zorcher-Ladung,,Ŝarĝo por Granda Zorĉilo,Carga de Zorcher Grande,,Ison zorcherin varaus,Charge de Zorcheur Large,Nagy szörcs töltet,Ricarica Grande Zorch,ラージゾーチャー ほきゅう,대형 저치 카트리지,Grote Zorchlading,Stor Zorch ladning,Ładunek do Dużego Zorchera,Recarga de Zorch Grande,,Încărcătură Mare pentru Zorcher,Заряд большого Зорчера,Велики зорч пуњач,Büyük Zorcher Şarjı -Propulsor Charge,AMMO_ROCKETS,,chex,,Propulzorové náboje,Propulsor ladning,Propeller-Ladung,,Zorĉpropulsilo-ŝarĝo,Carga de Propulsor de Zorch ,,Työntimen varaus,Charge de Propulseur,Hajtómű töltet,Ricarica Propulsore,プロパルサー ほきゅう,저치 추진료,Propulsorlading,Propulsor ladning,Ładunek do Pędnika,Recarga de Propulsor de Zorch,,Încărcătură pentru Accelerator,Заряд ускорителя,Погонски зорч пуњач,İtici Şarjı -Phasing Zorcher Charge,AMMO_CELLS,,chex,,Fázovací náboje,Phasing-Zorcher ladning,Phasenzorcher-Ladung,,Fluktuantzorĉilo-ŝarĝo,Carga de Zorcher de Fase,,Vaiheiszorcherin varaus,Charge de Phaseur,Fázisszörcsölő töltet,Ricarica Zorcher di Fase,フェイシング ゾーチャー ほきゅう,저치 전자 충전기,Fasezorcherlading,Phasing-Zorcher ladning,Ładunek do Fazowego Zorchera,Recarga de Zorcher Fásico,,Încărcătură pentru Zorcherul Fazat,Заряд фазерного Зорчера,Фазни зорч пуњач,Zorcher Yükünün Aşamalandırılması -,,Menus,,,,,,,,,,,,,,,,,,,,,,,, -,,Main Menus,,,,,,,,,,,,,,,,,,,,,,,, -New Game,MNU_NEWGAME,,,,Nová hra,Nyt spil,Neues Spiel,Νέο Παιχνίδι,Nova ludado,Nueva partida,,Uusi peli,Nouvelle Partie,Új játék,Nuova partita,新規ゲーム,새로운 게임,Nieuw spel,Nytt spill,Nowa Gra,Novo jogo,,Joc Nou,Новая игра,Нова игра,Yeni Oyun -Options,MNU_OPTIONS,,,,Možnosti,Indstillinger,Optionen,Ρυθμίσεις,Agordoj,Opciones,,Asetukset,Options,Beállítások,Opzioni,オプション,설정,Opties,Alternativer,Opcje,Opções,,Opțiuni,Настройки,Подешавања,Seçenekler -Game Files,MNU_GAMEFILES,,,,Uložené hry,Spilfiler,Spieldateien,Αρχεία Παιχνιδιού,Ludo-dosieroj,Archivos del juego,,Pelitiedostot,Fichiers de jeu,Játékfájlok,File di gioco,ゲームファイル,게임 파일,Spelbestanden,Spillfiler,Pliki Gry,Jogos salvos,Jogos Gravados,Fișiere Joc,Файлы игры,Фајлови игре,Oyun Dosyaları -Info,MNU_INFO,,,,Informace,Info,Informationen,Πληροφορίες,Informoj,Información,,Tiedot,Info,Információ,Informazioni,情報,정보,Info,Info,Info,Informações,,Info,Информация,Подаци,Bilgi -Quit Game,MNU_QUITGAME,,,,Ukončit hru,Afslut spil,Spiel verlassen,Έξοδος,Forlasi ludon,Salir del juego,,Lopeta peli,Quitter le jeu,Kilépés,Esci dal gioco,終了,게임 종료,Verlaat spel,Avslutt spill,Wyjdź z Gry,Sair,,Ieșire din Joc,Выход из игры,Заврши игру,Oyundan Çık -Choose Skill Level:,MNU_CHOOSESKILL,This text is extremely space limited!,,,Vyber obtížnost:,Vælg færdighedsniveau:,Schwierigkeitsgrad:,Επίλεξε ΔυσκολΊα:,Elektu malfacilecon:,Elige nivel de dificultad:,,Valitse vaikeustaso:,Difficulté:,Nehézségi szint:,Livello di difficoltà:,実力を選べ:,난이도를 고르시오:,Vaardigheidsniveau:,Velg ferdighetsnivå:,Poziom Trudności:,Escolha o nível de dificuldade:,,Alege Dificultatea:,Уровень сложности:,Ниво тежине:,Beceri Seviyesini Seçin: -I'm too young to die.,SKILL_BABY,,,,Ještě nechci umřít.,Jeg er for ung til at dø.,Ich bin zu jung zum Sterben.,Είμαι πολύ νεαρός για να πεθάνω!,Mi tro junas por morti.,Soy muy joven para morir.,,Olen liian nuori kuolemaan.,Trop jeune pour mourir!,Kicsi vagyok még a halálhoz.,Troppo giovane per morire.,死ぬには若すぎる,난 죽기엔 너무 젊어.,Ik ben te jong om te sterven.,Jeg er for ung til å dø.,Jestem za młody by umierać.,Sou jovem demais para morrer.,Demasiado novo para morrer.,Sunt prea tânăr ca să mor.,Мне рано умирать.,Премлад сам да умрем.,Ölmek için çok gencim. -"Hey, not too rough.",SKILL_EASY,,,,"Hej, ne tak tvrdě.","Hey, ikke for hårdt.","He, nicht so ruppig.",Όχι πολύ δύσκολο,"He, ne tro malafable.","Oye, no seas tan duro.",,"Hei, ei liian kovaa.","Hé, pas trop fort!","Hé, ne túl erősen!","Ehi, non troppo duro!",あまり激しくするな,너무 세게 하지는 마.,"Hé, niet te ruw.","Hei, ikke for hardhendt.","Hej, nie tak mocno.","Opa, pega leve aí.","Ei, mais devagar.","Hei, nu foarte dur.","Эй, не слишком грубо.","Хеј, не претерано грубо.",Çok sert değil. -Hurt me plenty.,SKILL_NORMAL,,,,Pojď do mě.,Gør mig rigeligt ondt.,Tu mir weh.,Πόνεσε με,Vundu min multe.,Hazme mucho daño.,,Satuta minua kunnolla.,Fais-moi mal!,Adjál bőven!,Fammi molto male.,手加減無用,마음껏 때려봐.,Doe me veel pijn.,Skader meg mye.,Dowal mi.,Vem com tudo.,Dá-me com força.,Rănește-mă din plin.,Сделай мне больно.,Повреди ме кол'ко можеш.,Beni çok incittin. -Ultra-Violence.,SKILL_HARD,,,,Ultrařežba.,Ultra-vold.,Volle Gewalt.,Ύπερ-Βία,Ekstrema perforto.,Ultraviolencia.,,Ultraväkivalta.,Ultra-Violence!,Ultraerőszak!,Ultra-violenza.,ウルトラ バイオレンス,극단적인-폭력.,Ultra Geweld.,Ultra-vold.,Ultra-Przemoc.,Ultraviolência.,,Ultra-Violență.,Ультранасилие.,Ултра-насилно.,Ultra Şiddet. -Nightmare!,SKILL_NIGHTMARE,,,,Noční můra!,Mareridt!,Alptraum!,Εφιάλτης!,Inkubo!,¡Pesadilla!,,Painajainen!,Cauchemar!,Rémálom!,Incubo!,悪夢だ!,악몽!,Nachtmerrie!,Mareritt!,Koszmar!,Pesadelo!,,Coșmar!,Кошмар!,Ноћна мора!,Kabus! -Easy does it,CSKILL_BABY,,,,Hezky zlehka,Let gør det,Immer sachte,,Kvietiĝu,Así de fácil,,Hiljaa hyvä tulee,On y va Doucement,Csak gyengéden.,Facile no?,やさしくして,살살 하면 좋겠네,Gemakkelijk doet het,Rolig nå,Łatwizna,Vamos com calma,,Merge ușor,Потихоньку-полегоньку,Лагано сад,Sakin ol. +Притисни Y или N.","Är du säker på att du vill avsluta spelet? +Tryck på Y eller N.","Görevi sonlandırmak istediğinizden emin misiniz? + +Y veya N tuşuna basın.","Ти дійсно хочеш завершити квест? + +Натисни Y або N." +Invincible Mode ON,STSTR_DQDON,,chex,,Režim nezranitelnosti ZAP,Uovervindelig tilstand TIL,Unbesiegbarer Modus EIN,,Nevenkebla-reĝimo ŜALTITA,Modo invencible ACTIVADO,,Kuolemattomuustila PÄÄLLÄ,Mode invincible ON,Sérthetetlen mód BE,Modalità invincibile attivata,むてきモード オン,무적 모드 켬,Onoverwinnelijke modus AAN,Uovervinnelig modus PÅ,Tryb Niewrażliwości WŁĄCZONY,Modo invencível ATIVADO,,Modul Invincibil ACTIVAT,Режим неуязвимости ВКЛЮЧЁН,Неуништив УКЉУЧЕН,Oövervinnerligt läge på,Yenilmez Mod AÇIK,Невразливість увімкнено +Invincible Mode OFF,STSTR_DQDOFF,,chex,,Režim nezranitelnosti VYP,Uovervindelig tilstand FRA,Unbesiegbarer Modus AUS,,Nevenkebla-reĝimo MALŜALTITA,Modo invencible DESACTIVADO,,Kuolemattomuustila POIS PÄÄLLÄ,Mode invincible OFF,Sérthetetlen mód KI,Modalità invincibile disattivata,むてきモード オフ,무적 모드 끔,Onoverwinnelijke modus UIT,Uovervinnelig modus AV,Tryb Niewrażliwości WYŁĄCZONY,Modo invencível DESATIVADO,,Modul Invincibil DEZACTIVAT,Режим неуязвимости ОТКЛЮЧЁН,Неуништив ИСКЉУЧЕН,Oövervinnerligt läge av,Yenilmez Modu KAPALI,Невразливість вимкнено +Zorch Added,STSTR_FAADDED,,chex,,Bzukry přidány,Zorch tilføjet,Zorch hinzugefügt,,Zorĉo Aldonita,Zorch añadido,,Zorch lisätty,Zorch Ajouté,Szörcs felvéve,Zorch aggiunto,ゾーチ ついか,모든 저치 에너지 추가,Zorch toegevoegd,Zorch lagt til,Zorch dodany,Zorch adicionado,,Zorcher Adăugat,Получен зорч,Зорч додат,Zorch har lagts till,Zorch Eklendi,Додано Зорч +Super Zorch Added,STSTR_KFAADDED,,chex,,Superbzukry přidány,Super Zorch Tilføjet,Super Zorch hinzugefügt,,Supera Zorĉo Aldonita,Súper Zorch añadido,,Superzorch lisätty,Super Zorch Ajouté,Szuper Szörcs feléve,Super Zorch aggiunto,スーパーゾーチ ついか,모든 아이템 습득!,Super Zorch toegevoegd,Super Zorch lagt til,Super Zorch dodany,Super Zorch adicionado,,Super Lingură Adăugată,Получен суперзорч,Супер зорч додат,Super Zorch läggs till,Süper Zorch Eklendi,Додано Супер Зорч +... Eat Chex(R)!,STSTR_CHOPPERS,,chex,,... Jez Chex(R)!,... Spis Chex(R)!,...Iss Chex(R)!,,... Manĝu Chex(R)-on!,... Come Chex(R),,... Syö Chex(R):ä!,... Mangez du Chex(R)!,...egyél Chex(R)-et!,... Mangia I Chex(R)!,...Chex(R)をたべよう!,... 첵스(R) 를 많이 먹자!,... Eet Chex(R)!,... Spis Chex(R)!,... jedz płatki Chex(R)!,... coma Chex(R)!,,... Mănâncă Chex(R)!,...ешь Chex(R)!,... Једи Chex(R)!,... Ät Chex(R)!,... Chex(R) yiyin!,... Їж Chex(R)! +Mini Zorch Charge,AMMO_CLIP,,chex,,Minibzukrové náboje,Mini Zorch ladning,Minizorcher-Ladung,,Zorĉileto-Ŝarĝo,Carga de Mini Zorch,,Minizorchvaraus,Charge Zorch,Mini szörcs töltet,Ricarica Mini Zorch,ミニゾーチ ほきゅう,소형 저치 전지,Mini Zorchlading,Mini Zorch ladning,Mini Ładunek Zorch,Recarga de Mini Zorch,,Mini Încărcătură pentru Zorcher,Заряд мини-зорчера,Мини зорч пуњач,,Mini Zorch Şarjı,Заряд міні-Зорчера +Large Zorcher Charge,AMMO_SHELLS,,chex,,Velkobzukrové náboje,Stor Zorch ladning,Zorcher-Ladung,,Ŝarĝo por Granda Zorĉilo,Carga de Zorcher Grande,,Ison zorcherin varaus,Charge de Zorcheur Large,Nagy szörcs töltet,Ricarica Grande Zorch,ラージゾーチャー ほきゅう,대형 저치 카트리지,Grote Zorchlading,Stor Zorch ladning,Ładunek do Dużego Zorchera,Recarga de Zorch Grande,,Încărcătură Mare pentru Zorcher,Заряд большого зорчера,Велики зорч пуњач,Stor Zorch-laddning,Büyük Zorcher Şarjı,Заряд Великого Зорчера +Propulsor Charge,AMMO_ROCKETS,,chex,,Propulzorové náboje,Propulsor ladning,Propeller-Ladung,,Zorĉpropulsilo-ŝarĝo,Carga de Propulsor de Zorch ,,Työntimen varaus,Charge de Propulseur,Hajtómű töltet,Ricarica Propulsore,プロパルサー ほきゅう,저치 추진료,Propulsorlading,Propulsor ladning,Ładunek do Pędnika,Recarga de Propulsor de Zorch,,Încărcătură pentru Accelerator,Заряд ускорителя,Погонски зорч пуњач,Propulsor-laddning,İtici Şarjı,Заряд Прискорювача +Phasing Zorcher Charge,AMMO_CELLS,,chex,,Fázovací náboje,Phasing-Zorcher ladning,Phasenzorcher-Ladung,,Fluktuantzorĉilo-ŝarĝo,Carga de Zorcher de Fase,,Vaiheiszorcherin varaus,Charge de Phaseur,Fázisszörcsölő töltet,Ricarica Zorcher di Fase,フェイシング ゾーチャー ほきゅう,저치 전자 충전기,Fasezorcherlading,Phasing-Zorcher ladning,Ładunek do Fazowego Zorchera,Recarga de Zorcher Fásico,,Încărcătură pentru Zorcherul Fazat,Заряд фазерного зорчера,Фазни зорч пуњач,Zorcher-laddning för fasning,Zorcher Yükünün Aşamalandırılması,Заряд фазового Зорчера +,,Menus,,,,,,,,,,,,,,,,,,,,,,,,,, +,,Main Menus,,,,,,,,,,,,,,,,,,,,,,,,,, +New Game,MNU_NEWGAME,,,,Nová hra,Nyt spil,Neues Spiel,Νέο Παιχνίδι,Nova ludado,Nueva partida,,Uusi peli,Nouvelle Partie,Új játék,Nuova partita,新規ゲーム,새로운 게임,Nieuw spel,Nytt spill,Nowa Gra,Novo jogo,,Joc Nou,Новая игра,Нова игра,Nytt spel,Yeni Oyun,Нова гра +Options,MNU_OPTIONS,,,,Možnosti,Indstillinger,Optionen,Ρυθμίσεις,Agordoj,Opciones,,Asetukset,Options,Beállítások,Opzioni,オプション,설정,Opties,Alternativer,Opcje,Opções,,Opțiuni,Настройки,Подешавања,Alternativ,Seçenekler,Налаштування +Game Files,MNU_GAMEFILES,,,,Uložené hry,Spilfiler,Spieldateien,Αρχεία Παιχνιδιού,Ludo-dosieroj,Archivos del juego,,Pelitiedostot,Fichiers de jeu,Játékfájlok,File di gioco,ゲームファイル,게임 파일,Spelbestanden,Spillfiler,Pliki Gry,Jogos salvos,Jogos Gravados,Fișiere Joc,Файлы игры,Фајлови игре,Spelfiler,Oyun Dosyaları,Ігрові файли +Info,MNU_INFO,,,,Informace,,Informationen,Πληροφορίες,Informoj,Información,,Tiedot,,Információ,Informazioni,情報,정보,,,,Informações,,,Информация,Подаци,,Bilgi,Інформація +Quit Game,MNU_QUITGAME,,,,Ukončit hru,Afslut spil,Spiel verlassen,Έξοδος,Forlasi ludon,Salir del juego,,Lopeta peli,Quitter le jeu,Kilépés,Esci dal gioco,終了,게임 종료,Verlaat spel,Avslutt spill,Wyjdź z Gry,Sair,,Ieșire din Joc,Выход из игры,Заврши игру,Avsluta spelet,Oyundan Çık,Вихід +Choose Skill Level:,MNU_CHOOSESKILL,This text is extremely space limited!,,,Vyber obtížnost:,Vælg færdighedsniveau:,Schwierigkeitsgrad:,Επίλεξε ΔυσκολΊα:,Elektu malfacilecon:,Elige nivel de dificultad:,,Valitse vaikeustaso:,Difficulté:,Nehézségi szint:,Livello di difficoltà:,実力を選べ:,난이도를 고르시오:,Vaardigheidsniveau:,Velg ferdighetsnivå:,Poziom Trudności:,Escolha o nível de dificuldade:,,Alege Dificultatea:,Уровень сложности:,Ниво тежине:,Välj färdighetsnivå:,Beceri Seviyesini Seçin:, +I'm too young to die.,SKILL_BABY,,,,Ještě nechci umřít.,Jeg er for ung til at dø.,Ich bin zu jung zum Sterben.,Είμαι πολύ νεαρός για να πεθάνω!,Mi tro junas por morti.,Soy muy joven para morir.,,Olen liian nuori kuolemaan.,Trop jeune pour mourir!,Kicsi vagyok még a halálhoz.,Troppo giovane per morire.,死ぬには若すぎる,난 죽기엔 너무 젊어.,Ik ben te jong om te sterven.,Jeg er for ung til å dø.,Jestem za młody by umierać.,Sou jovem demais para morrer.,Demasiado novo para morrer.,Sunt prea tânăr ca să mor.,Мне рано умирать.,Премлад сам да умрем.,Jag är för ung för att dö.,Ölmek için çok gencim., +"Hey, not too rough.",SKILL_EASY,,,,"Hej, ne tak tvrdě.","Hey, ikke for hårdt.","He, nicht so ruppig.",Όχι πολύ δύσκολο,"He, ne tro malafable.","Oye, no seas tan duro.",,"Hei, ei liian kovaa.","Hé, pas trop fort!","Hé, ne túl erősen!","Ehi, non troppo duro!",あまり激しくするな,너무 세게 하지는 마.,"Hé, niet te ruw.","Hei, ikke for hardhendt.","Hej, nie tak mocno.","Opa, pega leve aí.","Ei, mais devagar.","Hei, nu foarte dur.","Эй, не слишком грубо.","Хеј, не претерано грубо.",Inte alltför grovt.,Çok sert değil., +Hurt me plenty.,SKILL_NORMAL,,,,Pojď do mě.,Gør mig rigeligt ondt.,Tu mir weh.,Πόνεσε με,Vundu min multe.,Dame con todo.,,Satuta minua kunnolla.,Fais-moi mal!,Adjál bőven!,Fammi molto male.,手加減無用,마음껏 때려봐.,Doe me veel pijn.,Skader meg mye.,Dowal mi.,Vem com tudo.,Dá-me com força.,Rănește-mă din plin.,Сделай мне больно.,Повреди ме кол'ко можеш.,Gör mig mycket illa.,Beni çok incittin., +Ultra-Violence.,SKILL_HARD,,,,Ultrařežba.,Ultra-vold.,Volle Gewalt.,Ύπερ-Βία,Ekstrema perforto.,Ultraviolencia.,,Ultraväkivalta.,Ultra-Violence!,Ultraerőszak!,Ultra-violenza.,ウルトラ バイオレンス,극단적인-폭력.,Ultra Geweld.,Ultra-vold.,Ultra-Przemoc.,Ultraviolência.,,Ultra-Violență.,Ультранасилие.,Ултра-насилно.,Ultra-våld.,Ultra Şiddet., +Nightmare!,SKILL_NIGHTMARE,,,,Noční můra!,Mareridt!,Alptraum!,Εφιάλτης!,Inkubo!,¡Pesadilla!,,Painajainen!,Cauchemar!,Rémálom!,Incubo!,悪夢だ!,악몽!,Nachtmerrie!,Mareritt!,Koszmar!,Pesadelo!,,Coșmar!,Кошмар!,Ноћна мора!,Mardröm!,Kabus!,Кошмар! +Easy does it,CSKILL_BABY,,,,Hezky zlehka,Let gør det,Immer sachte,,Kvietiĝu,Así de fácil,,Hiljaa hyvä tulee,On y va Doucement,Csak gyengéden.,Facile no?,やさしくして,살살 하면 좋겠네,Gemakkelijk doet het,Rolig nå,Łatwizna,Vamos com calma,,Merge ușor,Потихоньку-полегоньку,Лагано сад,Det är lätt att göra det.,Sakin ol., Not so sticky,CSKILL_EASY,,,,Ne tak ulepeně,Ikke så klistret,Nicht so schmierig,,Ne tiel glueca,No tan pegajoso,,Ei niin tahmaista,Pas trop Collant,Ne túl ragadósan!,"Non così appiccicoso -",ダラダラしない,질척하진 않게,Niet zo plakkerig.,Ikke så klissete,Nie tak lepko,Não tão gosmento,,Nu așa de lipicios,Не особо липко,Не тако лепљиво,Çok yapışkan değil +",ダラダラしない,질척하진 않게,Niet zo plakkerig.,Ikke så klissete,Nie tak lepko,Não tão gosmento,,Nu așa de lipicios,Не особо липко,Не тако лепљиво,Inte så klibbigt,Çok yapışkan değil, Gobs of goo,CSKILL_NORMAL,,,,Hafo hlenu,Masser af klister,Schleimklumpen,,Buloj de muko,Montón de moco,,Limaklönttejä,Des Tonnes de Gelée,Egy csomó trutymó,Sputi di sostanza,"カッチカチスライム -",적지 않은 질퍽함,brokken slijm,Klumper av klister,Maziste Gęby,Um montão de meleca,Um montão de ranho,Multă mâzgă,Масса слизи,Лопте љиге,Çok fazla çamur +",적지 않은 질퍽함,brokken slijm,Klumper av klister,Maziste Gęby,Um montão de meleca,Um montão de ranho,Multă mâzgă,Масса слизи,Лопте љиге,Massor av kladd,Çok fazla çamur, Extreme Ooze,CSKILL_HARD,,,,Extra bláto,Ekstrem slim,Extrem glitschig,,Ekstrema pusado,Goteo extremo,,Äärimmäisen mönjäistä,Extrêmement Gluant,Extrém nyúlós,Melma estrema,"かげきなウーズ -",엄청난 끈끈함,Uiterst glibberig,Ekstrem slim,Ekstremalny Muł,Gosma ao extremo,,Noroi Extrem,Экстремальная грязь,Екстремно љигаво,Aşırı Sızıntı -Super Slimey!,CSKILL_NIGHTMARE,,,,Superslizké!,Super slimet!,Super schleimig!,,Tre ŝlima!,¡Súper viscoso!,,Superlimaista!,Carrément Crade!,Szupernyálkás!,Super Viscido!,ちょうベトベト!,끈쩍함 천지!,Super slijmerig!,Super slimete!,Super Oślizgły!,Super Gosmento!,,Super Mâzgos!,Сверхсклизский!,СУПЕР ЉИГАВО,Süper yapışkan! -Training,SSKILL_BABY,,,,Trénink,Træning,,Eκπαίδευση,Trejnado,Práctica,,Koulutus,Entrâinement,Kiképzés,Allenamento,トレーニング,훈련병,Opleiding,Trening,Trening,Treinamento,Treino,În Pregătiri,Разминка,Тренинг,Eğitim -Rookie,SSKILL_EASY,,,,Zelenáč,Nybegynder,Anfänger,Αρχάριος,Komencanto,Novato,,Aloittelija,Recrue,Újonc,Matricola,ルーキー,신병,,Nybegynner,Rekrut,Novato,,Începător,Новичок,Новајлија,Çaylak -Veteran,SSKILL_NORMAL,,,,Veterán,,,,Veterano,Veterano,,Veteraani,Véteran,Veterán,Veterano,ベテラン,고참병,Veteraan,,Weteran,Veterano,,Veteran,Ветеран,Ветеран,Gazi -Elite,SSKILL_HARD,,,,Elita,,,,Elito,Élite,,Eliitti,,Elit,Elite,エリート,정예병,,,Elita,Elite,,Elită,Элита,Елитни,Elit -Bloodbath,SSKILL_NIGHTMARE,,,,Krveřežba,Blodbad,Blutbad,,Sangoverŝado,Baño de sangre,,Verilöyly,Massacre!,Vérfürdő,Bagno di sangue,ブラッドバス,피의 목욕,Bloedbad,Blodbad,Rozlew krwi,Banho de sangue,,Baie de sânge,Кровавая бойня,Купка крви,Kan banyosu -Thou needeth a Wet-Nurse,MNU_WETNURSE,,,,Potřěbuješ krmlici?,Du har brug for en våd sygeplejerske,Wo ist die Krankenschwester?,,Vi nutristinon bezonas,Necesitaréis una nodriza,,Tarvitseos imettäjää,Une Nourrice Vous Voulez,Süldőgyermek,Necessiti di un'infermiera per neonati,汝は乳母を欲する,그대에게는 유모가 필요하다,Waar is de verpleegster?,Du trenger en amme,Wciąż w pieluszkach,Tu precisas de uma Ama-de-Leite,Tu precisas de uma Ama-Seca,Doica are Nevoie de Mine,Нянечка надобна мне,Треба ти бабица,Islak bir hemşireye ihtiyacın var. -Yellowbellies-R-Us,MNU_YELLOWBELLIES,,,,"Nemehla, tož jsme my",,Vereinigte Waschlappen,,Malkuraĝuloj-as-ni,Somos pusilánimes,,Mameronapero,Un Trouillard-Tu-Est,Ne bántsék kend!,Codardo-tu-sei,我等こそが臆病者,장난감을 가지고 노는가,Verenigd washandje,Yellowbellies-R-Us,"Nie książę, lecz tchórz",Tu és um Amarelão,Tu és um Cobardolas,Nu Sunt Așa de Curajos,Не столь мужественен я,Ми-смо-жутица,Birleşik Korkak Kediler -Bringest Them Oneth,MNU_BRINGEST,,,,Chtějúci se práti?,Kom med dem,Her damit,,Al mi ilin kunvenigu,Traédnoslos,,Antaos tullaos,Amenez les moi!,Ide velük hinnye,Portali a me,招かれし者共,혈투를 벌일 준비하라,Geef me dat.,Kom med dem,Dawajże Ich,Podeis Virdes,Podeis Virdes,Aduceți-mi,Подайте мне их,Донеси изабраног,Onları Getir -Thou art a Smite-Meister,MNU_SMITE,,,,Ktož jsú boží bojovníci,Du er mesterdræberen,Du bist der Meistertöter,,Vi Venkobatanto estas,Sois un regicida,,Olet lyömäherra,Tu est Maître-Meurtrier,Csapjunk bele kend!,Sei un maestro assassino,汝は芸術的殺戮者,그대야말로 타격의 대가,Jij bent de meestermoordenaar.,Du er mesterdraperen,Mistrz w swoim fachu,Tu és Mestre-de-Massacres,,Lupta mă Ispitește,Искушён я сражениями,Ти си обузети-мајстор,Sen baş sihirbazsın -Black Plague Possesses Thee,MNU_BLACKPLAGUE,,,,Jsúci Smrtonošem morovým!,Den sorte pest besætter dig,Von der Pest besessen,,Nigra morto vin posedas,La peste negra os posee,,Musta surma on saanut sun,La Peste Noire me Possède!,Ehun gyün a pestis,La peste nera ti possiede,汝に憑した黒死病,흑사병이 그대를 저주 내리리,Geobsedeerd door de pest,Den svarte pesten besetter deg,Sługa Czarnej Plagi,A Peste Negra te Possui,A Peste Negra Possui-te,Ciuma Neagră mă Posedă,Чума овладела мной,Имаш црну кугу,Kara Veba Seni Ele Geçirdi -Squire,MNU_SQUIRE,,,,Panoš,Laird,Gutsherr,,Varleto,Escudero,,Aseenkantaja,Ecuyer,Apród,Scudiero,見習い騎士,향사,Squire,Væpner,Giermek,Escudeiro,,Scutier,Оруженосец,Штитоноша,Beyefendi -Knight,MNU_KNIGHT,,,,Rytíř,Ridder,Ritter,Ιππότης,Kavaliro,Caballero,,Ritari,Chevalier,Lovag,Cavaliere,騎士,기사,Ridder,Ridder,Rycerz,Cavaleiro,,Cavaler,Рыцарь,Витез,Şövalye -Warrior,MNU_WARRIOR,,,,Válečník,Kriger,Krieger,Πολεμιστής,Militisto,Guerrero,,Soturi,Guerrier,Katona,Guerriero,戦士,전사,Krijger,Kriger,Wojownik,Guerreiro,,Războinic,Воитель,Борац,Savaşçı -Berserker,MNU_BERSERKER,,,,Berserkr,,,,Frenezisto,Berserker,,Berserkkeri,,Harcos,Berserker,狂戦士,광전사,Berserker,,Szaleniec,,,Turbat,Берсерк,Делија,Berserker -Titan,MNU_TITAN,,,,Titán,,,Τιτάνας,Titano,Titán,,Titaani,,Titán,Titano,タイタン,철인,Titan,,Tytan,Titã,,Titan,Титан,Титан,Titan -Altar Boy,MNU_ALTARBOY,,,,Ministrant,Alterdreng,Novize,,Messervanto,Monaguillo,,Pyhäkköpoika,Enfant de Chœur,Ministráns,Chirichetto,堂役,복사,Altaarjongen,Altergutt,Ministrant,Menino de coral,Menino do coro,Paracliser,Алтарник,Министрант,Sunak Çocuğu -Acolyte,MNU_ACOLYTE,,,,Akolyta,Akolyt,Missionar,,Akolito,Acólito,,Akoluutti,,Oltárszolga,Accolito,侍祭,시종,Acoliet,Akolytt,Akolita,Coroinha,Acólito,Acolit,Служитель,Помоћник,Yardımcı -Priest,MNU_PRIEST,,,,Kněz,Præst,Priester,,Pastro,Sacerdote,,Pappi,Prêtre,Pap,Prete,司祭,사제,Priester,Prest,Kapłan,Padre,,Preot,Священник,Свештеник,Rahip -Cardinal,MNU_CARDINAL,,,,Kardinál,Kardinal,Kardinal,,Kardinalo,Cardenal,,Kardinaali,,Bíboros,Cardinale,枢機卿,추기경,Kardinaal,Kardinal,Kardynał,Cardeal,,Cardinal,Кардинал,Кардинал,Kardinal -Pope,MNU_POPE,,,,Papež,Pave,Papst,Πάπας,Papo,Papa,,Paavi,Pape,Pápa,Papa,教皇,교황,Paus,Pave,Papież,Papa,,Papă,Епископ,Папа,Papa -Apprentice,MNU_APPRENTICE,,,,Učeň,Lærling,Lehrling,,Lernanto,Aprendiz,,Kisälli,Apprenti,Tanonc,Apprendista,入門者,조수,Leerling,Lærling,Uczeń,Aprendiz,,Ucenic,Ученик,Шегрт,Çırak -Enchanter,MNU_ENCHANTER,,,,Kouzelník,Fortryller,Zauberer,,Ravisto,Encantador,,Lumooja,Enchanteur,Bűvölő,Incantatore,妖術士,주술사,Betoveraar,Trollmann,Zaklinacz,Encantador,,Fermecător,Чародей,Чаробњак,Sihirbaz -Sorcerer,MNU_SORCERER,,,,Čaroděj,Troldmand,Hexer,,Sorĉisto,Hechicero,,Taikuri,Sorcier,Varázsló,Mago,魔術士,마법사,Tovenaar,Magiker,Mag,Feiticeiro,,Mag,Колдун,Врачар,Büyücü -Warlock,MNU_WARLOCK,,,,Zaklínač,,Hexenmeister,,Magiisto,Brujo,,Noita,Mage de Guerre,Boszorkánymester,Stregone,黒魔術士,전투술사,Tovenaar,Veiviser,Wiedźmak,Mago,,Vrăjitor,Чернокнижник,Вештац,Efsuncu -Archmage,MNU_ARCHMAGE,,,,Arcimág,Ærkemagiker,Erzmagier,,Magiantestro,Archimago,,Arkkivelho,Archimage,Főmágus,Arcimago,大魔導師,대마법사,Aartsbisschop,Erkemagiker,Arcymag,Arquimago,,Prim-Vrăjitor,Архимаг,Врховни вештац,Başbüyücü -Choose Class:,MNU_CHOOSECLASS,,,,Vyber třídu:,Vælg klasse:,Figurengruppe wählen:,,Elektu klason:,Elige tu clase:,,Valitse luokka:,Choissisez une Classe:,Válassz kasztot:,Scegli la classe:,クラス選抜:,영웅 선택:,Kies klasse:,Velg klasse:,Wybierz klasę:,Escolha a classe:,,Alege Clasa:,Класс:,Класа:,Sınıf seç: -Fighter,MNU_FIGHTER,,,,Bojovník,Kriger,Krieger,,Batalanto,Luchador,,Taistelija,Guerrier,Harcos,Combattente,戦士,전사,Vechter,Kriger,Wojownik,Lutador,,Luptător,Воин,Борац,Dövüşçü -Cleric,MNU_CLERIC,,,,Klerik,Kleriker,Geistlicher,,Kleriko,Clérigo,,Pappi,Moine,Lelkész,Chierico,僧侶,성직자,Geestelijk,Kleriker,Kleryk,Clérigo,,,Клерик,Свештеник,Ruhban -Mage,MNU_MAGE,,,,Mág,Mage,Magier,,Magianto,Mago,,Velho,,Mágus,Mago,魔導士,마법사,Tovenaar,Magiker,Mag,Mago,,Magician,Маг,Чаробњак,Sihirbaz -Random,MNU_RANDOM,,,,Náhodný,Tilfældig,Zufällig,,Hazarda,Al azar,,Satunnainen,Au Hasard,Véletlenszerű,Casuale,ランダム,랜덤,Willekeurig,Tilfeldig,Losowa,Aleatório,,Aleatoriu,Наугад,Насумично,Rastgele -Which Episode?,MNU_EPISODE,,,,Jakou epizodu?,Hvilken episode?,Welche Episode?,,Kiu epizodo?,¿Qué episodio?,,Mikä episodi?,Quel épisode?,Melyik epizód?,Quale episodio?,どのエピソードだ?,에피소드 선택:,Welke aflevering?,Hvilken episode?,Który Epizod?,Qual Episódio?,,Care Episod?,Какой эпизод?,Која епизода?,Hangi Bölüm? -Choose Campaign,MNU_EPISODE,,strife,,Vyber kampaň,Vælg kampagne,Mission auswählen,,Elektu kampanjon,Selecciona una campaña,,Valitse kampanja,Choisissez la Campagne,Válassz hadjáratot,Scegli la campagna,キャンペーンを選べ,캠페인을 고르시오:,Kies campagne,Velg kampanje,Wybierz kampanię,Escolha a Campanha,,Alege Campania,Выбор кампании,Изабери кампању,Kampanyayı Seçin -City of the Damned,MNU_COTD,,,,Město zatracených,Byen af de forbandede,Stadt der Verdammten,,Urbo de la damnitaj,Ciudad de los condenados,,Kirottuin kaupunki,La Cité des Damnés,Az átkozottak városa,Città del dannato,呪われた都,멸망한 도시,Stad van de verdoemden,De fordømtes by,Miasto Przeklętych,Cidade dos Condenados,,Orașul Blestemaților,Город проклятых,Град проклетих,Lanetliler Şehri -Hell's Maw,MNU_HELLSMAW,,,,Chřtán pekel,Helvedes gab,Der Schlund zur Hölle,,Faŭko de Infero,Fauces del infierno,,Hornankita,La Geule des Enfers,A Pokol bugyrai,Lo Stomaco dell'Inferno,地獄の肚,지옥의 목구멍,De slokdarm naar de hel,Helvetes gap,Paszcza Piekieł,A Boca do Inferno,,Străfundurile Infernului,Адское жерло,Чељусти пакла,Cehennem Ağzı -The Dome of D'Sparil,MNU_DOME,,,,Báň D'Sparilova,D'Sparils kuppel,D'Sparils Dom,,La Kupolo de D'Sparil,La Cúpula de D'Sparil,El Domo de D'Sparil,D'Sparilin kupoli,Le Dôme de D'Sparil,D'Sparil kupolája,La Casa del D'Sparil,デ'スパリルの穹窿,드'스파릴의 돔,D'Sparils Kathedraal,D'Sparils kuppel,Gmach D'Sparila,A Cúpula de D'Sparil,,Domul lui D'Sparil,Купол Д'Спарила,Купола Д'Спарила,D'Sparil'in Kubbesi -The Ossuary,MNU_OSSUARY,,,,Kostnice,Benhuset,Das Beinhaus,,La Ostejo,El Osario,,Luuhuone,L'Ossuaire,Csontkamra,L'Ossario,納骨堂,납골당,Het Ossuarium,Beinhuset,Kostnica,O Ossuário,O Ossário,Osuarul,Склеп,Костурница,Mezar Odası -The Stagnant Demesne,MNU_DEMESNE,,,,Zatuchlé panství,Den stagnerede demesne,Das stagnierende Reich,,La Senmova Posedaĵo,La Heredad Estancada,,Seisahtunut maa,Le domaine Stagnant,A pangó birtok,La Proprietà terriera Stagnante,澱んだ荘園,침체된 영지,Het stagnerende rijk,Den stillestående herregården,Opuszczone Włości,O Reino Estagnado,,Tărâmul Stagnării,Застойная Демесна,Стагнирајући домени,Durgun Diyar -,,Gameplay menus,,,,,,,,,,,,,,,,,,,,,,,, -Teamplay,GMPLYMNU_TEAMPLAY,,,,Týmová hra,,Teamspiel,,Teamludado,Juego por equipos,,Joukkuepeli,Jeu en équipe,Csapatjáték,Gioco di squadra,チーム制,팀플레이,Teamplay,Lagspill,Gra Drużynowa,Jogo em equipe,Jogo em Equipa,Joc în Echipă,Командная игра,Тимска игра,Takım Oyunu -Team damage scalar,GMPLYMNU_TEAMDAMAGE,,,,Faktor týmového poškození,Skala for holdskader,Team-Schadenfaktor,,Teamdamaĝo-skalio,Escalar de daño del equipo,,Omien tulen vahinkokerroin,Facteur de Tir Fratricide,Csapatsebzés mértéke,Fattore danno da fuoco amico,チームメンバーへのダメージ倍率,팀 데미지 배율,Teamschade scalair,Skalar for lagskade,Skalar Obrażeń Drużyny,Escala de fogo amigo,,Multiplicator daune,Множитель урона по своим,Мултипликатор пријатељске ватре,Takım hasar skalası -Smart Autoaim,GMPLYMNU_SMARTAUTOAIM,,,,Chytré automatické zaměřování,Intelligent Autoaim,Intelligente Zielautomatik,,Inteligenta Celasisto,Autoapuntado inteligente,,Älykäs automaattitähtäys,Autovisée intelligente,Okos automata célzás,Mira automatica intelligente,スマートオートエイム,정확한 자동 조준,Slimme Autoaim,Smart Autoaim,Mądre Autocelowanie,Mira automática inteligente,,Asistare inteligentă la țintire,Умное автоприцеливание,Паметни нишан,Akıllı Autoaim -Falling damage,GMPLYMNU_FALLINGDAMAGE,,,,Zranění pádem,Faldskader,Fallschaden,,Faldamaĝo,Daño por caída,,Putoamisvahinko,Dommages de chute,Eséskor sebzés,Danno da caduta,落下ダメージ,낙하 데미지,Vallende schade,Fallende skade,Obrażenia przy upadku,Dano de queda,,Daune la căderi libere,Урон от падения,Штета од пада,Düşme hasarı +",엄청난 끈끈함,Uiterst glibberig,Ekstrem slim,Ekstremalny Muł,Gosma ao extremo,,Noroi Extrem,Экстремальная грязь,Екстремно љигаво,Extremt slemmigt,Aşırı Sızıntı, +Super Slimey!,CSKILL_NIGHTMARE,,,,Superslizké!,Super slimet!,Super schleimig!,,Tre ŝlima!,¡Súper viscoso!,,Superlimaista!,Carrément Crade!,Szupernyálkás!,Super Viscido!,ちょうベトベト!,끈쩍함 천지!,Super slijmerig!,Super slimete!,Super Oślizgły!,Super Gosmento!,,Super Mâzgos!,Сверхсклизский!,СУПЕР ЉИГАВО,Super slemmig!,Süper yapışkan!, +Training,SSKILL_BABY,,,,Trénink,Træning,,Eκπαίδευση,Trejnado,Práctica,,Koulutus,Entrâinement,Kiképzés,Allenamento,トレーニング,훈련병,Opleiding,Trening,Trening,Treinamento,Treino,În Pregătiri,Разминка,Тренинг,Träning,Eğitim, +Rookie,SSKILL_EASY,,,,Zelenáč,Nybegynder,Anfänger,Αρχάριος,Komencanto,Novato,,Aloittelija,Recrue,Újonc,Matricola,ルーキー,신병,,Nybegynner,Rekrut,Novato,,Începător,Новичок,Новајлија,Nybörjare,Çaylak, +Veteran,SSKILL_NORMAL,,,,Veterán,,,,Veterano,Veterano,,Veteraani,Véteran,Veterán,Veterano,ベテラン,고참병,Veteraan,,Weteran,Veterano,,,Ветеран,Ветеран,,Gazi, +Elite,SSKILL_HARD,,,,Elita,,,,Elito,Élite,,Eliitti,,Elit,,エリート,정예병,,,Elita,,,Elită,Элита,Елитни,,Elit, +Bloodbath,SSKILL_NIGHTMARE,,,,Krveřežba,Blodbad,Blutbad,,Sangoverŝado,Baño de sangre,,Verilöyly,Massacre!,Vérfürdő,Bagno di sangue,ブラッドバス,피의 목욕,Bloedbad,Blodbad,Rozlew krwi,Banho de sangue,,Baie de sânge,Кровавая бойня,Купка крви,Blodbad,Kan banyosu, +Thou needeth a Wet-Nurse,MNU_WETNURSE,,,,Potřěbuješ krmlici?,Du har brug for en våd sygeplejerske,Wo ist die Krankenschwester?,,Vi nutristinon bezonas,Necesitaréis una nodriza,,Tarvitseos imettäjää,Une Nourrice Vous Voulez,Süldőgyermek,Necessiti di un'infermiera per neonati,汝は乳母を欲する,그대에게는 유모가 필요하다,Waar is de verpleegster?,Du trenger en amme,Wciąż w pieluszkach,Tu precisas de uma Ama-de-Leite,Tu precisas de uma Ama-Seca,Doica are Nevoie de Mine,Нянечка надобна мне,Треба ти бабица,Du behöver en våtsjuksköterska,Islak bir hemşireye ihtiyacın var., +Yellowbellies-R-Us,MNU_YELLOWBELLIES,,,,"Nemehla, tož jsme my",,Vereinigte Waschlappen,,Malkuraĝuloj-as-ni,Somos pusilánimes,,Mameronapero,Un Trouillard-Tu-Est,Ne bántsék kend!,Codardo-tu-sei,我等こそが臆病者,장난감을 가지고 노는가,Verenigd washandje,Yellowbellies-R-Us,"Nie książę, lecz tchórz",Tu és um Amarelão,Tu és um Cobardolas,Nu Sunt Așa de Curajos,Не столь мужественен я,Ми-смо-жутица,Förenade ynkryggar,Birleşik Korkak Kediler, +Bringest Them Oneth,MNU_BRINGEST,,,,Chtějúci se práti?,Kom med dem,Her damit,,Al mi ilin kunvenigu,Traédnoslos,,Antaos tullaos,Amenez les moi!,Ide velük hinnye,Portali a me,招かれし者共,혈투를 벌일 준비하라,Geef me dat.,Kom med dem,Dawajże Ich,Podeis Virdes,Podeis Virdes,Aduceți-mi,Подайте мне их,Донеси изабраног,Ta med dem in,Onları Getir, +Thou art a Smite-Meister,MNU_SMITE,,,,Ktož jsú boží bojovníci,Du er mesterdræberen,Du bist der Meistertöter,,Vi Venkobatanto estas,Sois un regicida,,Olet lyömäherra,Tu est Maître-Meurtrier,Csapjunk bele kend!,Sei un maestro assassino,汝は芸術的殺戮者,그대야말로 타격의 대가,Jij bent de meestermoordenaar.,Du er mesterdraperen,Mistrz w swoim fachu,Tu és Mestre-de-Massacres,,Lupta mă Ispitește,Искушён я сражениями,Ти си обузети-мајстор,Du är en Mästerdödare,Sen baş sihirbazsın, +Black Plague Possesses Thee,MNU_BLACKPLAGUE,,,,Jsúci Smrtonošem morovým!,Den sorte pest besætter dig,Von der Pest besessen,,Nigra morto vin posedas,La peste negra os posee,,Musta surma on saanut sun,La Peste Noire me Possède!,Ehun gyün a pestis,La peste nera ti possiede,汝に憑した黒死病,흑사병이 그대를 저주 내리리,Geobsedeerd door de pest,Den svarte pesten besetter deg,Sługa Czarnej Plagi,A Peste Negra te Possui,A Peste Negra Possui-te,Ciuma Neagră mă Posedă,Чума овладела мной,Имаш црну кугу,Svarta pesten besitter dig,Kara Veba Seni Ele Geçirdi, +Squire,MNU_SQUIRE,,,,Panoš,Laird,Gutsherr,,Varleto,Escudero,,Aseenkantaja,Ecuyer,Apród,Scudiero,見習い騎士,향사,,Væpner,Giermek,Escudeiro,,Scutier,Оруженосец,Штитоноша,,Beyefendi, +Knight,MNU_KNIGHT,,,,Rytíř,Ridder,Ritter,Ιππότης,Kavaliro,Caballero,,Ritari,Chevalier,Lovag,Cavaliere,騎士,기사,Ridder,Ridder,Rycerz,Cavaleiro,,Cavaler,Рыцарь,Витез,Riddaren,Şövalye, +Warrior,MNU_WARRIOR,,,,Válečník,Kriger,Krieger,Πολεμιστής,Militisto,Guerrero,,Soturi,Guerrier,Katona,Guerriero,戦士,전사,Krijger,Kriger,Wojownik,Guerreiro,,Războinic,Воитель,Борац,Krigare,Savaşçı, +Berserker,MNU_BERSERKER,,,,Berserkr,,,,Frenezisto,,,Berserkkeri,,Harcos,,狂戦士,광전사,,,Szaleniec,,,Turbat,Берсерк,Делија,,, +Titan,MNU_TITAN,,,,Titán,,,Τιτάνας,Titano,Titán,,Titaani,,Titán,Titano,タイタン,철인,,,Tytan,Titã,,,Титан,Титан,,, +Altar Boy,MNU_ALTARBOY,,,,Ministrant,Alterdreng,Novize,,Messervanto,Monaguillo,,Pyhäkköpoika,Enfant de Chœur,Ministráns,Chirichetto,堂役,복사,Altaarjongen,Altergutt,Ministrant,Menino de coral,Menino do coro,Paracliser,Алтарник,Министрант,Altarpojke,Sunak Çocuğu, +Acolyte,MNU_ACOLYTE,,,,Akolyta,Akolyt,Missionar,,Akolito,Acólito,,Akoluutti,,Oltárszolga,Accolito,侍祭,시종,Acoliet,Akolytt,Akolita,Coroinha,Acólito,Acolit,Служитель,Помоћник,Akolyt,Yardımcı, +Priest,MNU_PRIEST,,,,Kněz,Præst,Priester,,Pastro,Sacerdote,,Pappi,Prêtre,Pap,Prete,司祭,사제,Priester,Prest,Kapłan,Padre,,Preot,Священник,Свештеник,Präst,Rahip, +Cardinal,MNU_CARDINAL,,,,Kardinál,Kardinal,Kardinal,,Kardinalo,Cardenal,,Kardinaali,,Bíboros,Cardinale,枢機卿,추기경,Kardinaal,Kardinal,Kardynał,Cardeal,,Cardinal,Кардинал,Кардинал,Kardinal,Kardinal, +Pope,MNU_POPE,,,,Papež,Pave,Papst,Πάπας,Papo,Papa,,Paavi,Pape,Pápa,Papa,教皇,교황,Paus,Pave,Papież,Papa,,Papă,Епископ,Папа,Påve,Papa, +Apprentice,MNU_APPRENTICE,,,,Učeň,Lærling,Lehrling,,Lernanto,Aprendiz,,Kisälli,Apprenti,Tanonc,Apprendista,入門者,조수,Leerling,Lærling,Uczeń,Aprendiz,,Ucenic,Ученик,Шегрт,Lärling,Çırak, +Enchanter,MNU_ENCHANTER,,,,Kouzelník,Fortryller,Zauberer,,Ravisto,Encantador,,Lumooja,Enchanteur,Bűvölő,Incantatore,妖術士,주술사,Betoveraar,Trollmann,Zaklinacz,Encantador,,Fermecător,Чародей,Чаробњак,Magiker,Sihirbaz, +Sorcerer,MNU_SORCERER,,,,Čaroděj,Troldmand,Hexer,,Sorĉisto,Hechicero,,Taikuri,Sorcier,Varázsló,Mago,魔術士,마법사,Tovenaar,Magiker,Mag,Feiticeiro,,Mag,Колдун,Врачар,Trollkarl,Büyücü, +Warlock,MNU_WARLOCK,,,,Zaklínač,,Hexenmeister,,Magiisto,Brujo,,Noita,Mage de Guerre,Boszorkánymester,Stregone,黒魔術士,전투술사,Tovenaar,Veiviser,Wiedźmak,Mago,,Vrăjitor,Чернокнижник,Вештац,Häxkarl,Efsuncu, +Archmage,MNU_ARCHMAGE,,,,Arcimág,Ærkemagiker,Erzmagier,,Magiantestro,Archimago,,Arkkivelho,Archimage,Főmágus,Arcimago,大魔導師,대마법사,Aartsbisschop,Erkemagiker,Arcymag,Arquimago,,Prim-Vrăjitor,Архимаг,Врховни вештац,Ärkemagiker,Başbüyücü, +Choose Class:,MNU_CHOOSECLASS,,,,Vyber třídu:,Vælg klasse:,Figurengruppe wählen:,,Elektu klason:,Elige tu clase:,,Valitse luokka:,Choissisez une Classe:,Válassz kasztot:,Scegli la classe:,クラス選抜:,영웅 선택:,Kies klasse:,Velg klasse:,Wybierz klasę:,Escolha a classe:,,Alege Clasa:,Класс:,Класа:,Välj klass:,Sınıf seç:, +Fighter,MNU_FIGHTER,,,,Bojovník,Kriger,Krieger,,Batalanto,Luchador,,Taistelija,Guerrier,Harcos,Combattente,戦士,전사,Vechter,Kriger,Wojownik,Lutador,,Luptător,Воин,Борац,Kämpe,Dövüşçü, +Cleric,MNU_CLERIC,,,,Klerik,Kleriker,Geistlicher,,Kleriko,Clérigo,,Pappi,Moine,Lelkész,Chierico,僧侶,성직자,Geestelijk,Kleriker,Kleryk,Clérigo,,,Клерик,Свештеник,Kleriker,Ruhban, +Mage,MNU_MAGE,,,,Mág,,Magier,,Magianto,Mago,,Velho,,Mágus,Mago,魔導士,마법사,Tovenaar,Magiker,Mag,Mago,,Magician,Маг,Чаробњак,Magiker,Sihirbaz, +Random,MNU_RANDOM,,,,Náhodný,Tilfældig,Zufällig,,Hazarda,Al azar,,Satunnainen,Au Hasard,Véletlenszerű,Casuale,ランダム,랜덤,Willekeurig,Tilfeldig,Losowa,Aleatório,,Aleatoriu,Наугад,Насумично,Slumpmässig,Rastgele, +Which Episode?,MNU_EPISODE,,,,Jakou epizodu?,Hvilken episode?,Welche Episode?,,Kiu epizodo?,¿Qué episodio?,,Mikä episodi?,Quel épisode?,Melyik epizód?,Quale episodio?,どのエピソードだ?,에피소드 선택:,Welke aflevering?,Hvilken episode?,Który Epizod?,Qual episódio?,,Care Episod?,Какой эпизод?,Која епизода?,Vilken episod?,Hangi Bölüm?, +Choose Campaign,MNU_EPISODE,,strife,,Vyber kampaň,Vælg kampagne,Mission auswählen,,Elektu kampanjon,Selecciona una campaña,,Valitse kampanja,Choisissez la Campagne,Válassz hadjáratot,Scegli la campagna,キャンペーンを選べ,캠페인을 고르시오:,Kies campagne,Velg kampanje,Wybierz kampanię,Escolha a campanha,,Alege Campania,Выбор кампании,Изабери кампању,Välj kampanj,Kampanyayı Seçin, +City of the Damned,MNU_COTD,,,,Město zatracených,Byen af de forbandede,Stadt der Verdammten,,Urbo de la damnitaj,Ciudad de los condenados,,Kirottuin kaupunki,La Cité des Damnés,Az átkozottak városa,Città del dannato,呪われた都,멸망한 도시,Stad van de verdoemden,De fordømtes by,Miasto Przeklętych,Cidade dos Condenados,,Orașul Blestemaților,Город проклятых,Град проклетих,De fördömdas stad,Lanetliler Şehri, +Hell's Maw,MNU_HELLSMAW,,,,Chřtán pekel,Helvedes gab,Der Schlund zur Hölle,,Faŭko de Infero,Fauces del infierno,,Hornankita,La Geule des Enfers,A Pokol bugyrai,Lo Stomaco dell'Inferno,地獄の肚,지옥의 목구멍,De slokdarm naar de hel,Helvetes gap,Paszcza Piekieł,A Boca do Inferno,,Străfundurile Infernului,Адское жерло,Чељусти пакла,Helvetets gap,Cehennem Ağzı, +The Dome of D'Sparil,MNU_DOME,,,,Báň D'Sparilova,D'Sparils kuppel,D'Sparils Dom,,La Kupolo de D'Sparil,La Cúpula de D'Sparil,El Domo de D'Sparil,D'Sparilin kupoli,Le Dôme de D'Sparil,D'Sparil kupolája,La Casa del D'Sparil,デ'スパリルの穹窿,드'스파릴의 돔,D'Sparils Kathedraal,D'Sparils kuppel,Gmach D'Sparila,A Cúpula de D'Sparil,,Domul lui D'Sparil,Купол Д'Спарила,Купола Д'Спарила,D'Sparils kupol,D'Sparil'in Kubbesi, +The Ossuary,MNU_OSSUARY,,,,Kostnice,Benhuset,Das Beinhaus,,La Ostejo,El Osario,,Luuhuone,L'Ossuaire,Csontkamra,L'Ossario,納骨堂,납골당,Het Ossuarium,Beinhuset,Kostnica,O Ossuário,O Ossário,Osuarul,Склеп,Костурница,Benhuset,Mezar Odası, +The Stagnant Demesne,MNU_DEMESNE,,,,Zatuchlé panství,Den stagnerede demesne,Das stagnierende Reich,,La Senmova Posedaĵo,La Heredad Estancada,,Seisahtunut maa,Le domaine Stagnant,A pangó birtok,La Proprietà terriera Stagnante,澱んだ荘園,침체된 영지,Het stagnerende rijk,Den stillestående herregården,Opuszczone Włości,O Reino Estagnado,,Tărâmul Stagnării,Застойная Демесна,Стагнирајући домени,Den stillastående demesnen,Durgun Diyar, +,,Gameplay menus,,,,,,,,,,,,,,,,,,,,,,,,,, +Teamplay,GMPLYMNU_TEAMPLAY,,,,Týmová hra,,Teamspiel,,Teamludado,Juego por equipos,,Joukkuepeli,Jeu en équipe,Csapatjáték,Gioco di squadra,チーム制,팀플레이,,Lagspill,Gra Drużynowa,Jogo em equipe,Jogo em Equipa,Joc în Echipă,Командная игра,Тимска игра,,Takım Oyunu, +Team damage scalar,GMPLYMNU_TEAMDAMAGE,,,,Faktor týmového poškození,Skala for holdskader,Team-Schadenfaktor,,Teamdamaĝo-skalio,Escalar de daño del equipo,,Omien tulen vahinkokerroin,Facteur de Tir Fratricide,Csapatsebzés mértéke,Fattore danno da fuoco amico,チームメンバーへのダメージ倍率,팀 데미지 배율,Teamschade scalair,Skalar for lagskade,Skalar Obrażeń Drużyny,Escala de fogo amigo,,Multiplicator daune,Множитель урона по своим,Мултипликатор пријатељске ватре,Skador i laget skalar,Takım hasar skalası, +Smart Autoaim,GMPLYMNU_SMARTAUTOAIM,,,,Chytré automatické zaměřování,Intelligent Autoaim,Intelligente Zielautomatik,,Inteligenta Celasisto,Autoapuntado inteligente,,Älykäs automaattitähtäys,Autovisée intelligente,Okos automata célzás,Mira automatica intelligente,スマートオートエイム,정확한 자동 조준,Slimme Autoaim,Smart Autoaim,Mądre Autocelowanie,Mira automática inteligente,,Asistare inteligentă la țintire,Умное автоприцеливание,Паметни нишан,Smart Autoaim,Akıllı Autoaim, +Falling damage,GMPLYMNU_FALLINGDAMAGE,,,,Zranění pádem,Faldskader,Fallschaden,,Faldamaĝo,Daño por caída,,Putoamisvahinko,Dommages de chute,Eséskor sebzés,Danno da caduta,落下ダメージ,낙하 데미지,Vallende schade,Fallende skade,Obrażenia przy upadku,Dano de queda,,Daune la căderi libere,Урон от падения,Штета од пада,Fallande skador,Düşme hasarı, Drop weapon,GMPLYMNU_DROPWEAPON,,,,Odhazování zbraní,Taber våben,Waffen fallen lassen,,Faligi armilon,Arrojar arma,,Aseen pudottaminen,Arme lâchée à la mort,Fegyver eldobása,"Arma lasciata cadere -",死亡時に武器を落とす,무기 버리기,Laat het wapen vallen,Slipp våpen,Wyrzuć broń,Largar arma,,Aruncare armă,Терять оружие,Баци оружје,Silahı bırak -Double ammo,GMPLYMNU_DOUBLEAMMO,,,,Dvojnásobná munice,Dobbelt ammunition,Doppelte Munition,,Duobla municio,Doble munición,,Tupla-ammukset,Double munitions,Dupla muníció,Doppie munizioni,弾2倍,두 배의 탄약,Dubbele munitie,Dobbel ammunisjon,Podwojona amunicja,Munição em dobro,,Muniție dublă,Удвоенные патроны,Дупла муниција,Çift cephane -Infinite ammo,GMPLYMNU_INFINITEAMMO,,,,Nekonečná munice,Uendelig ammunition,Unendlich Munition,,Senlima municio,Munición infinita,,Loppumattomat ammukset,Munitions infinies,Végtelen muníció,Infinite munizioni,弾無限,무한 탄약,Oneindige munitie,Uendelig ammunisjon,Nieskończona amunicja,Munição infinita,,Muniție infinită,Бесконечные патроны,Бесконачна муниција,Sonsuz cephane -Infinite inventory,GMPLYMNU_INFINITEINVENTORY,,,,Nekonečný inventář,Uendelig lagerbeholdning,Unendliche Gegenstände,,Senlima inventaro,Inventario infinito,,Loppumattomat varusteet,Objets infinis,Végtelen felszerelés,Infinito inventario,所持品無限,무한 인벤토리,Oneindige voorraad,Uendelig lagerbeholdning,Nieskończony ekwipunek,Inventário infinito,,Inventar infinit,Бесконечный инвентарь,Бесконачно складиштење,Sonsuz envanter -No monsters,GMPLYMNU_NOMONSTERS,,,,Bez příšer,Ingen monstre,Keine Monster,,Neniu monstro,Sin monstruos,,Ei hirviöitä,Pas de monstres,Szörnyek nélkül,Nessun mostro,モンスターを出現させない,적 제거,Geen monsters,Ingen monstre,Brak potworów,Sem monstros,,Fără monștri,Без монстров,Без чудовишта,Canavar yok -No monsters to exit,GMPLYMNU_NOMONSTERSTOEXIT,,,,Ukončení levelu pouze bez příšer,Ingen monstre for at komme ud,Keine Monster um Level zu beenden,,Neniu monstro por eliri,Sin monstruos para salir,,Ei hirviöitä tason lopettamiseksi,Rien à tuer pour sortir,Megölendő szörnyek nélkül,Nessun mostro da uccidere per uscire,モンスター全滅までMAPから脱出不可,탈출을 위한 적 제거,Geen monsters om af te sluiten,Ingen monstre å avslutte,Brak potworów do wyjścia,Sem monstros para sair da fase,Sem monstros para sair do nível,Fără monștri pentru a ieși,Убить всех монстров для выхода,Без чудовишта до излаза,Çıkacak canavar yok -Monsters respawn,GMPLYMNU_MONSTERSRESPAWN,,,,Příšery se respawnují,Monstre genopstår igen,Monster kehren zurück,,Monstroj reekaperas,Reaparecer enemigos,,Hirviöt heräävät henkiin,Monstres réapparaissent,Szörnyek újraszületnek,Respawn mostri,モンスターの自力復活,적 부활,Monsters respawn,Monstre respawn,Ponowne pojawianie się potworów,Ressurgimento de monstros,,Monștrii reapar,Монстры воскрешаются,Чудовишта се оживљавају,Canavarlar yeniden doğar -Monsters do not respawn,GMPLYMNU_NORESPAWN,,,,Příšery se nerespawnují,Monstre respawner ikke igen,Kein Zurückkehren,,Monstroj ne reekaperas,Sin reaparición,,Ei henkiinheräämistä,Pas de réapparition,Szörnyek nem születnek újra,Nessun respawn,プレイヤーの復活禁止,부활 없음,Geen respawn,Monstre respawn ikke,Brak ponownego pojawienia się,Sem ressurgimento de monstros,,Monștrii nu reapar,Монстры не воскрешаются,Без оживљавања,Canavarlar yeniden doğmaz -Items respawn,GMPLYMNU_ITEMSRESPAWN,,,,Předměty se respawnují,Genstande respawnes,Gegenstände erscheinen wieder,,Objektoj reekaperas,Reaparecer objetos,,Esineet syntyvät takaisin,Objets réapparaissent,tárgyak újrateremnek,Respawn oggetti,アイテムを復活,아이템 재생성,Items respawn,Gjenstander respawn,Ponowne pojawianie się przedmiotów,Ressurgimento de itens,,Obiectele reapar,Восстановление предметов,Предмети се ресетују,Eşyalar yeniden doğar -Big powerups respawn,GMPLYMNU_SUPERRESPAWN,,,,Bonusy se respawnují,Store powerups respawnes,Große Boni erscheinen wieder,,Grandaj plifortigaĵoj reekaperas,Reaparecer poderes grandes,,Isot tehostimet syntyvät takaisin,Powerups réapparaissent,Nagy képességek újraszületnek,Respawn grandi potenziamenti,強力なパワーアップアイテムを復活,파워업 재생성,Grote power-ups respawn,Store powerups respawn,Ponowne pojawianie się dużych wzmocnień,Ressurgimento de potencializadores,,Super bonusurile reapar,Восстановление больших усилений,Велики предмети се ресетују,Büyük güçlendiriciler yeniden doğar -Fast monsters,GMPLYMNU_FASTMONSTERS,,,,Rychlé příšery,Hurtige monstre,Schnelle Monster,,Rapidaj monstroj,Monstruos rápidos,,Nopeat hirviöt,Monstres Rapides,Gyors szörnyek,Mostri veloci,モンスター高速化,빠른 적 개체 움직임,Snelle monsters,Raske monstre,Szybkie potwory,Monstros rápidos,,Monștri rapizi,Ускоренные монстры,Брза чудовишта,Hızlı canavarlar -Monsters Nightmare Reflexes,GMPLYMNU_INSTANTREACTION,,,,Okamžité reakce příšer (obtížnost Noční můra!),Monsterrefleksioner i 'Mareridt',Monsterreflexe in 'Alptraum!'.,,Refleksoj de monstroj en Inkubo-modo,Reflejos de los monsturos en Pesadilla,,Painajaisvaikeustason hirviöiden reaktioajat,,Rémálom szintű szörny reakciók,,敵が悪夢と同じ機敏さ,,,Monstre mareritt reflekser,Refleks Potworów z Trybu Koszmar,Reflexos dos Monstros em Pesadelo,,Monștri cu Reflexe de Coșmar,Кошмарные рефлексы монстров,,Canavarlar Kabus Refleksleri -Degeneration,GMPLYMNU_DEGENERATION,,,,Degenerace,,,,Degenero,Degeneración,,Rappeutuva terveys,Dégéneration,Degeneráció,Degrado della salute,プレイヤーの自動体力減少,약화,Degeneratie,Degenerasjon,Degeneracja,Degeneração,,Degenerare,Уменьшать дополнительное здоровье,Смањење додатног здравља,Dejenerasyon -Allow Autoaim,GMPLYMNU_NOAUTOAIM,,,,Povolit automatické míření,Tillad autoaim,Zielautomatik zulassen,,Permesi cel-asiston,Permitir autoapuntar,,Salli automaattitähtäys,Autoriser Auto-visée,Autocélzás engedélyezése,Mira automatica consentita,オートエイム有効化,자동 조준 허용,Autoaim toestaan,Tillat Autoaim,Pozwól na Autocelowanie,Permitir mira automática,,Permite asistența pentru țintire,Разрешить автоприцеливание,Дозволи аутоматско циљање,Autoaim'e İzin Ver -Allow Suicide,GMPLYMNU_ALLOWSUICIDE,,,,Povolit sebevraždu,Tillad selvmord,Selbstmord zulassen,,Permesi memmortigon,Permitir suicidio,,Salli itsemurha,Autoriser Suicide,Öngyilkosság engedélyezése,Suicidio consentito,自殺コマンド有効化,자살 허용,Zelfmoord toestaan,Tillat selvmord,Pozwól na Samobójstwo,Permitir suicídio,,Permite sinuciderile,Разрешить самоубийство,Дозволи самоубиство,İntihara İzin Ver -Allow jump,GMPLYMNU_ALLOWJUMP,,,,Povolit skákání,Tillader spring,Springen zulassen,,Permesi salton,Permitir salto,,Salli hyppiminen,Autoriser Sauts,Ugrás engedélyezése,Salto consentito,ジャンプ有効化,점프 허용,Springen toestaan,Tillat hopp,Pozwól na skakanie,Permitir pulo,Permitir salto,Permite săriturile,Разрешить прыжки,Дозволи скок,Atlamaya izin ver -Allow crouch,GMPLYMNU_ALLOWCROUCH,,,,Povolit klečení,Tillader krybeøvelser,Ducken zulassen,,Permesi kaŭron,Permitir agacharse,,Salli kyyristyminen,Autoriser Acroupissement,Guggolás engedélyezése,Abbassamento consentito,しゃがみ有効化,앉기 허용,Hurken toestaan,Tillat huk,Pozwól na kucanie,Permitir agachamento,,Permite ghemuirile,Разрешить приседание,Дозволи чучање,Çömelmeye izin ver -Allow freelook,GMPLYMNU_ALLOWFREELOOK,,,,Povolit koukání nahoru/dolů,Tillader freelook,Freien Blick zulassen,,Permesi liberrigardon,Permitir visión libre,,Salli vapaa katselu,Autoriser Vue Libre,Szabad egérmozgás engedélyezése,Sguardo libero consentito,フリールック有効化,프리룩 허용,Freelook toestaan,Tillat freelook,Pozwól na swobodne rozglądanie się,Permitir visão livre,,Permite privirea în jur cu mouse-ul,Обзор мышью,Дозволи слободан поглед,Freelook'a izin ver -Allow FOV,GMPLYMNU_ALLOWFOV,,,,Povolit změnu FOV,Tillad FOV,Blickwinkeländerung zulassen,,Permesi vidkampon,Permitir FOV,,Salli näkökentän muokkaaminen,Autoriser Angles de vue,Látószög állítás engedélyezése,Campo visivo consentito,FOVの調整を有効化,FOV 허용,Laat FOV,Tillat FOV,Pozwól na Pole Widzenia,Permitir campo de visão,,Permite ajustarea câmpului vizual,Разрешить изменение поля зрения,Дозволи FOV,FOV'a İzin Ver -Allow BFG aiming,GMPLYMNU_BFGFREEAIM,,,,Povolit míření s BFG,Tillad BFG-målsætning,Zielen mit BFG zulassen,,Permesi ekceladon de BFG,Permitir apuntado de BFG,,Salli BFG-tähtäys,Autoriser Visée au BFG,BFG célzás engedélyezése,Mira BFG consentita,BFG使用時のフリールックを有効化,BFG 조준 허용,Laat BFG toe om te streven naar,Tillat BFG-sikting,Pozwól na celowanie BFG,Permitir mira de BFG,,Permite țintirea cu BFG,Разрешить прицеливание с BFG,Дозволи BFG нишање,BFG hedeflemesine izin ver -Allow automap,GMPLYMNU_ALLOWAUTOMAP,,,,Povolit automapu,Tillader automap,Automap zulassen,,Permesi aŭtomapon,Permitir automapa,,Salli automaattikartta,Autoriser Carte,Autotérkép engedélyezése,Automap consentito,オートマップ有効化,오토맵 허용,Automap toestaan,Tillat automap,Pozwól na mapę,Permitir automapa,,Permite utilizarea hărții computerizate,Разрешить использование автокарты,Дозволи мапу,Otomatik eşlemeye izin ver -Automap allies,GMPLYMNU_AUTOMAPALLIES,,,,Zobrazit na automapě spojence,Automatisk indtegning af allierede,Verbündete zulassen,,Aliancanoj en aŭtomapo,Aliados en el automapa,,Omat automaattikartalla,Alliés sur la carte,Társak mutatása a térképen,Alleati nell'automap,オートマップに味方を表示,오토맵에 아군 표시,Automap bondgenoten,Automatisk kartlegging av allierte,Sojusznicy na mapie,Permitir aliados no automapa,,Aliați pe harta computerizată,Отображение союзников на автокарте,Савезници на аутомапи,Automap müttefikleri -Allow spying,GMPLYMNU_ALLOWSPYING,,,,Povolit špehování,Tillader spionage,Spionieren zulassen,,Permesi spionadon,Permitir espiar,,Salli vakoileminen,Autoriser espionnage,Kémkedés engedélyezése,Spionaggio consentita,死亡時の他プレイヤー観戦を許可,관전 허용,Laat spionage toe,Tillat spionering,Pozwól na śledzenie,Permitir visualização de outros jogadores,,Permite vederea prin ochii altor jucători,Разрешить вид от других игроков,Дозволи поглед од другог играча,Casusluğa izin ver -Chasecam cheat,GMPLYMNU_CHASECAM,,,,Povolit kameru z třetí osoby (cheat),Chasecam snyder,Verfolgerkamera Cheat,,Trompo por ĉaskamerao,Truco de vista 3era persona,,Seurantakamerahuijaus,Cheat caméra 3ième personne,Követésőkamera csalás,Cheat camera di inseguimento,チェイスカメラチート有効化,3인칭 카메라 치트,Chasecam cheat,Chasecam juks,Oszustwo kamery śledzenia,Trapaça de câmera em terceira pessoa,Batota de câmera em terceira pessoa,Trișare pentru vedere la persoana a 3-a,Разрешить вид от 3-го лица,Дозволи чејс-кем,Chasecam hilesi -Check ammo for weapon switch,GMPLYMNU_DONTCHECKAMMO,,,,Přepnout na zbraň pouze s municí,Kontroller ammunition for våbenskift,Munition beim Waffenwechsel prüfen,,Kontroli municion por armŝanĝi,Revisar munición para cambiar armas,,Tarkista ammustilanne aseenvaihdon yhteydessä,Vérifier muni. pour changer arme,Váltáskor üres fegyver átugrása,Controlla le munizioni per il cambio arma,武器切替時に弾の有無を確認,탄약 소진 시 무기 변경,Controleer munitie op wapenschakelaars.,Sjekk ammunisjon for våpenbryter,Sprawdź amunicję przy sprawdzaniu broni,Conferir munição para troca de arma,,Verifică muniția armei pentru schimbare,Проверять патроны при переключении оружия,Проверити муницију за прекидач за оружје,Silah anahtarı için cephaneyi kontrol edin -Icon's death kills its spawns,GMPLYMNU_KILLBOSSSPAWNS,,,,Smrt Ikony zabije i její potomky,Ikonets død dræber dets spawns,,,La morto de la piktogramo mortigas siajn idojn,La muerte del icono destruye sus lacayos,La muerte del ícono destruye sus lacayos,Ikonin kuolema tappaa myös siitä siinneet hirviöt,Tuer L'Icône tue ses monstres,Az ikon halála esetén a teremtményei is meghalnak,La morte dell'Icona uccide tutti i suoi figli,最終ボスを殺した際に召喚モンスターも殺す,보스 사망시 소환된 적들도 사망,Icon's dood doodt zijn spawns,Ikonets død dreper dets gyter,Śmierć Ikony zabija stworzone przez nią potwory,Morte do Ícone mata os seus monstros,Morte do Ícone mata os seus demónios,Decesul Idolului anihilează propriile creații,Убить порождения Иконы при её смерти,Смрт Икона греха убија његова потомства,İkon'un ölümü yumurtalarını öldürür +",死亡時に武器を落とす,무기 버리기,Laat het wapen vallen,Slipp våpen,Wyrzuć broń,Largar arma,,Aruncare armă,Терять оружие,Баци оружје,Släpp vapen,Silahı bırak, +Double ammo,GMPLYMNU_DOUBLEAMMO,,,,Dvojnásobná munice,Dobbelt ammunition,Doppelte Munition,,Duobla municio,Doble munición,,Tupla-ammukset,Double munitions,Dupla muníció,Doppie munizioni,弾2倍,두 배의 탄약,Dubbele munitie,Dobbel ammunisjon,Podwojona amunicja,Munição em dobro,,Muniție dublă,Удвоенные патроны,Дупла муниција,Dubbel ammunition,Çift cephane, +Infinite ammo,GMPLYMNU_INFINITEAMMO,,,,Nekonečná munice,Uendelig ammunition,Unendlich Munition,,Senlima municio,Munición infinita,,Loppumattomat ammukset,Munitions infinies,Végtelen muníció,Infinite munizioni,弾無限,무한 탄약,Oneindige munitie,Uendelig ammunisjon,Nieskończona amunicja,Munição infinita,,Muniție infinită,Бесконечные патроны,Бесконачна муниција,Oändlig ammunition,Sonsuz cephane, +Infinite inventory,GMPLYMNU_INFINITEINVENTORY,,,,Nekonečný inventář,Uendelig lagerbeholdning,Unendliche Gegenstände,,Senlima inventaro,Inventario infinito,,Loppumattomat varusteet,Objets infinis,Végtelen felszerelés,Infinito inventario,所持品無限,무한 인벤토리,Oneindige voorraad,Uendelig lagerbeholdning,Nieskończony ekwipunek,Inventário infinito,,Inventar infinit,Бесконечный инвентарь,Бесконачно складиштење,Oändligt inventarium,Sonsuz envanter, +No monsters,GMPLYMNU_NOMONSTERS,,,,Bez příšer,Ingen monstre,Keine Monster,,Neniu monstro,Sin monstruos,,Ei hirviöitä,Pas de monstres,Szörnyek nélkül,Nessun mostro,モンスターを出現させない,적 제거,Geen monsters,Ingen monstre,Brak potworów,Sem monstros,,Fără monștri,Без монстров,Без чудовишта,Inga monster,Canavar yok, +No monsters to exit,GMPLYMNU_NOMONSTERSTOEXIT,,,,Ukončení levelu pouze bez příšer,Ingen monstre for at komme ud,Keine Monster um Level zu beenden,,Neniu monstro por eliri,Sin monstruos para salir,,Ei hirviöitä tason lopettamiseksi,Rien à tuer pour sortir,Megölendő szörnyek nélkül,Nessun mostro da uccidere per uscire,モンスター全滅までMAPから脱出不可,탈출을 위한 적 제거,Geen monsters om af te sluiten,Ingen monstre å avslutte,Brak potworów do wyjścia,Sem monstros para sair da fase,Sem monstros para sair do nível,Fără monștri pentru a ieși,Убить всех монстров для выхода,Без чудовишта до излаза,Inga monster för att ta sig ut,Çıkacak canavar yok, +Monsters respawn,GMPLYMNU_MONSTERSRESPAWN,,,,Příšery se respawnují,Monstre genopstår igen,Monster kehren zurück,,Monstroj reekaperas,Reaparecer enemigos,,Hirviöt heräävät henkiin,Monstres réapparaissent,Szörnyek újraszületnek,Respawn mostri,モンスターの自力復活,적 부활,Monsters respawn,Monstre respawn,Ponowne pojawianie się potworów,Ressurgimento de monstros,,Monștrii reapar,Монстры воскрешаются,Чудовишта се оживљавају,Monster återuppstår,Canavarlar yeniden doğar, +Monsters do not respawn,GMPLYMNU_NORESPAWN,,,,Příšery se nerespawnují,Monstre respawner ikke igen,Kein Zurückkehren,,Monstroj ne reekaperas,Sin reaparición,,Ei henkiinheräämistä,Pas de réapparition,Szörnyek nem születnek újra,Nessun respawn,プレイヤーの復活禁止,부활 없음,Geen respawn,Monstre respawn ikke,Brak ponownego pojawienia się,Sem ressurgimento de monstros,,Monștrii nu reapar,Монстры не воскрешаются,Без оживљавања,Monstren återuppstår inte,Canavarlar yeniden doğmaz, +Items respawn,GMPLYMNU_ITEMSRESPAWN,,,,Předměty se respawnují,Genstande respawnes,Gegenstände erscheinen wieder,,Objektoj reekaperas,Reaparecer objetos,,Esineet syntyvät takaisin,Objets réapparaissent,tárgyak újrateremnek,Respawn oggetti,アイテムを復活,아이템 재생성,Items respawn,Gjenstander respawn,Ponowne pojawianie się przedmiotów,Ressurgimento de itens,,Obiectele reapar,Восстановление предметов,Предмети се ресетују,Föremål återuppstår.,Eşyalar yeniden doğar, +Big powerups respawn,GMPLYMNU_SUPERRESPAWN,,,,Bonusy se respawnují,Store powerups respawnes,Große Boni erscheinen wieder,,Grandaj plifortigaĵoj reekaperas,Reaparecer poderes grandes,,Isot tehostimet syntyvät takaisin,Powerups réapparaissent,Nagy képességek újraszületnek,Respawn grandi potenziamenti,強力なパワーアップアイテムを復活,파워업 재생성,Grote power-ups respawn,Store powerups respawn,Ponowne pojawianie się dużych wzmocnień,Ressurgimento de potencializadores,,Super bonusurile reapar,Восстановление больших усилений,Велики предмети се ресетују,Stora powerups återuppstår.,Büyük güçlendiriciler yeniden doğar, +Fast monsters,GMPLYMNU_FASTMONSTERS,,,,Rychlé příšery,Hurtige monstre,Schnelle Monster,,Rapidaj monstroj,Monstruos rápidos,,Nopeat hirviöt,Monstres Rapides,Gyors szörnyek,Mostri veloci,モンスター高速化,빠른 적 개체 움직임,Snelle monsters,Raske monstre,Szybkie potwory,Monstros rápidos,,Monștri rapizi,Ускоренные монстры,Брза чудовишта,Snabba monster,Hızlı canavarlar, +Monsters Nightmare Reflexes,GMPLYMNU_INSTANTREACTION,,,,Okamžité reakce příšer (obtížnost Noční můra!),Monsterrefleksioner i 'Mareridt',Monsterreflexe in 'Alptraum!'.,,Refleksoj de monstroj en Inkubo-modo,Reflejos de los monsturos en Pesadilla,,Painajaisvaikeustason hirviöiden reaktioajat,,Rémálom szintű szörny reakciók,,敵が悪夢と同じ機敏さ,,,Monstre mareritt reflekser,Refleks Potworów z Trybu Koszmar,Reflexos dos Monstros em Pesadelo,,Monștri cu Reflexe de Coșmar,Кошмарные рефлексы монстров,,Monster mardrömsreflexer,Canavarlar Kabus Refleksleri, +Degeneration,GMPLYMNU_DEGENERATION,,,,Degenerace,,,,Degenero,Degeneración,,Rappeutuva terveys,Dégéneration,Degeneráció,Degrado della salute,プレイヤーの自動体力減少,약화,Degeneratie,Degenerasjon,Degeneracja,Degeneração,,Degenerare,Уменьшать дополнительное здоровье,Смањење додатног здравља,,Dejenerasyon, +Allow Autoaim,GMPLYMNU_NOAUTOAIM,,,,Povolit automatické míření,Tillad autoaim,Zielautomatik zulassen,,Permesi cel-asiston,Permitir autoapuntar,,Salli automaattitähtäys,Autoriser Auto-visée,Autocélzás engedélyezése,Mira automatica consentita,オートエイム有効化,자동 조준 허용,Autoaim toestaan,Tillat Autoaim,Pozwól na Autocelowanie,Permitir mira automática,,Permite asistența pentru țintire,Разрешить автоприцеливание,Дозволи аутоматско циљање,Tillåt autoaim,Autoaim'e İzin Ver, +Allow Suicide,GMPLYMNU_ALLOWSUICIDE,,,,Povolit sebevraždu,Tillad selvmord,Selbstmord zulassen,,Permesi memmortigon,Permitir suicidio,,Salli itsemurha,Autoriser Suicide,Öngyilkosság engedélyezése,Suicidio consentito,自殺コマンド有効化,자살 허용,Zelfmoord toestaan,Tillat selvmord,Pozwól na Samobójstwo,Permitir suicídio,,Permite sinuciderile,Разрешить самоубийство,Дозволи самоубиство,Tillåt självmord,İntihara İzin Ver, +Allow jump,GMPLYMNU_ALLOWJUMP,,,,Povolit skákání,Tillader spring,Springen zulassen,,Permesi salton,Permitir salto,,Salli hyppiminen,Autoriser Sauts,Ugrás engedélyezése,Salto consentito,ジャンプ有効化,점프 허용,Springen toestaan,Tillat hopp,Pozwól na skakanie,Permitir pulo,Permitir salto,Permite săriturile,Разрешить прыжки,Дозволи скок,Tillåt hopp,Atlamaya izin ver, +Allow crouch,GMPLYMNU_ALLOWCROUCH,,,,Povolit klečení,Tillader krybeøvelser,Ducken zulassen,,Permesi kaŭron,Permitir agacharse,,Salli kyyristyminen,Autoriser Acroupissement,Guggolás engedélyezése,Abbassamento consentito,しゃがみ有効化,앉기 허용,Hurken toestaan,Tillat huk,Pozwól na kucanie,Permitir agachamento,,Permite ghemuirile,Разрешить приседание,Дозволи чучање,Tillåt huk,Çömelmeye izin ver, +Allow freelook,GMPLYMNU_ALLOWFREELOOK,,,,Povolit koukání nahoru/dolů,Tillader freelook,Freien Blick zulassen,,Permesi liberrigardon,Permitir visión libre,,Salli vapaa katselu,Autoriser Vue Libre,Szabad egérmozgás engedélyezése,Sguardo libero consentito,フリールック有効化,프리룩 허용,Freelook toestaan,Tillat freelook,Pozwól na swobodne rozglądanie się,Permitir visão livre,,Permite privirea în jur cu mouse-ul,Обзор мышью,Дозволи слободан поглед,Tillåt freelook,Freelook'a izin ver, +Allow FOV,GMPLYMNU_ALLOWFOV,,,,Povolit změnu FOV,Tillad FOV,Blickwinkeländerung zulassen,,Permesi vidkampon,Permitir FOV,,Salli näkökentän muokkaaminen,Autoriser Angles de vue,Látószög állítás engedélyezése,Campo visivo consentito,FOVの調整を有効化,FOV 허용,Laat FOV,Tillat FOV,Pozwól na Pole Widzenia,Permitir campo de visão,,Permite ajustarea câmpului vizual,Разрешить изменение поля зрения,Дозволи FOV,Tillåt FOV,FOV'a İzin Ver, +Allow BFG aiming,GMPLYMNU_BFGFREEAIM,,,,Povolit míření s BFG,Tillad BFG-målsætning,Zielen mit BFG zulassen,,Permesi ekceladon de BFG,Permitir apuntado de BFG,,Salli BFG-tähtäys,Autoriser Visée au BFG,BFG célzás engedélyezése,Mira BFG consentita,BFG使用時のフリールックを有効化,BFG 조준 허용,Laat BFG toe om te streven naar,Tillat BFG-sikting,Pozwól na celowanie BFG,Permitir mira de BFG,,Permite țintirea cu BFG,Разрешить прицеливание с BFG,Дозволи BFG нишање,Tillåt BFG-målning,BFG hedeflemesine izin ver, +Allow automap,GMPLYMNU_ALLOWAUTOMAP,,,,Povolit automapu,Tillader automap,Automap zulassen,,Permesi aŭtomatan mapon,Permitir automapa,,Salli automaattikartta,Autoriser Carte,Autotérkép engedélyezése,Automap consentito,オートマップ有効化,오토맵 허용,Automap toestaan,Tillat automap,Pozwól na mapę,Permitir automapa,,Permite utilizarea hărții computerizate,Разрешить использование автокарты,Дозволи мапу,Tillåt automap,Otomatik eşlemeye izin ver, +Automap allies,GMPLYMNU_AUTOMAPALLIES,,,,Zobrazit na automapě spojence,Automatisk indtegning af allierede,Verbündete zulassen,,Aliancanoj en aŭtomata mapo,Aliados en el automapa,,Omat automaattikartalla,Alliés sur la carte,Társak mutatása a térképen,Alleati nell'automap,オートマップに味方を表示,오토맵에 아군 표시,Automap bondgenoten,Automatisk kartlegging av allierte,Sojusznicy na mapie,Permitir aliados no automapa,,Aliați pe harta computerizată,Отображение союзников на автокарте,Савезници на аутомапи,Automatiska allierade,Automap müttefikleri, +Allow spying,GMPLYMNU_ALLOWSPYING,,,,Povolit špehování,Tillader spionage,Spionieren zulassen,,Permesi spionadon,Permitir espiar,,Salli vakoileminen,Autoriser espionnage,Kémkedés engedélyezése,Spionaggio consentita,死亡時の他プレイヤー観戦を許可,관전 허용,Laat spionage toe,Tillat spionering,Pozwól na śledzenie,Permitir visualização de outros jogadores,,Permite vederea prin ochii altor jucători,Разрешить вид от других игроков,Дозволи поглед од другог играча,Tillåter spionage,Casusluğa izin ver, +Chasecam cheat,GMPLYMNU_CHASECAM,,,,Povolit kameru z třetí osoby (cheat),Chasecam snyder,Verfolgerkamera Cheat,,Trompo por ĉaskamerao,Truco de vista 3era persona,,Seurantakamerahuijaus,Cheat caméra 3ième personne,Követésőkamera csalás,Cheat camera di inseguimento,チェイスカメラチート有効化,3인칭 카메라 치트,Chasecam cheat,Chasecam juks,Oszustwo kamery śledzenia,Trapaça de câmera em terceira pessoa,Batota de câmera em terceira pessoa,Trișare pentru vedere la persoana a 3-a,Разрешить вид от 3-го лица,Дозволи чејс-кем,Fusk med Chasecam,Chasecam hilesi, +Check ammo for weapon switch,GMPLYMNU_DONTCHECKAMMO,,,,Přepnout na zbraň pouze s municí,Kontroller ammunition for våbenskift,Munition beim Waffenwechsel prüfen,,Kontroli municion por armŝanĝi,Revisar munición para cambiar armas,,Tarkista ammustilanne aseenvaihdon yhteydessä,Vérifier muni. pour changer arme,Váltáskor üres fegyver átugrása,Controlla le munizioni per il cambio arma,武器切替時に弾の有無を確認,탄약 소진 시 무기 변경,Controleer munitie op wapenschakelaars.,Sjekk ammunisjon for våpenbryter,Sprawdź amunicję przy sprawdzaniu broni,Conferir munição para troca de arma,,Verifică muniția armei pentru schimbare,Проверять патроны при переключении оружия,Проверити муницију за прекидач за оружје,Kontrollera ammunition för vapenbyte,Silah anahtarı için cephaneyi kontrol edin, +Icon's death kills its spawns,GMPLYMNU_KILLBOSSSPAWNS,,,,Smrt Ikony zabije i její potomky,Ikonets død dræber dets spawns,,,La morto de la piktogramo mortigas siajn idojn,La muerte del icono destruye sus lacayos,La muerte del ícono destruye sus lacayos,Ikonin kuolema tappaa myös siitä siinneet hirviöt,Tuer L'Icône tue ses monstres,Az ikon halála esetén a teremtményei is meghalnak,La morte dell'Icona uccide tutti i suoi figli,最終ボスを殺した際に召喚モンスターも殺す,보스 사망시 소환된 적들도 사망,Icon's dood doodt zijn spawns,Ikonets død dreper dets gyter,Śmierć Ikony zabija stworzone przez nią potwory,Morte do Ícone mata os seus monstros,Morte do Ícone mata os seus demónios,Decesul Idolului anihilează propriile creații,Убить порождения Иконы при её смерти,Смрт Икона греха убија његова потомства,Ikonens död dödar dess spawns,İkon'un ölümü yumurtalarını öldürür, End sector counts for kill %,GMPLYMNU_NOCOUNTENDMONSTER,,,,Započítávat monstra v ukončujících sektorech,Slut sektor tæller for dræber %,Monster in Level-Beenden-Sektor zählen,,Finsektoro kalkulas al nombro da mortigoj,Sector de salida cuenta para % de muertes,,Loppusektori lasketaan mukaan tappoprosenttiin,Ennemis du secteur sortie comptés,Utolsó szektornál számít az ölés %,Conteggio dei nemici da uccidere nel settore in %,最終セクターの敵もキルに含む,레벨종료 섹터의 적들도 킬 수에 포함,Eindsector telt voor kill %,Slutt sektor teller for drap i prosent,"Zliczanie potworów w sektorze kończącym poziom -",Setor de saída conta para porcentagem de mortes,Setor de saída conta para percentagem de mortes,Numărare decese monștri în sectoare finale,Засчитывать убийства монстров в секторах конца игры,Урачунај убиство чудовишта у коначним секторима,Öldürme %'si için son sektör sayıları -Deathmatch Settings,GMPLYMNU_DEATHMATCH,,,,Nastavení deathmatche,Indstillinger for Deathmatch,Deathmatcheinstellungen,,Mortmatĉo-agordoj,Configuración modo a muerte,,Kuolonotteluasetukset,Options Deathmatch,Deathmatch beállítások,Impostazioni deathmatch,デスマッチの設定,데스매치 설정,Deathmatch instellingen,Deathmatch-innstillinger,Ustawienia Deathmatchu,Configurações de Deathmatch,,Setări Deathmatch,Настройки боя насмерть,Детмеч подешавања,Ölüm Maçı Ayarları -Weapons stay,GMPLYMNU_WEAPONSSTAY,,,,Zbraně zůstávají,Våben forbliver,Waffen bleiben,,Armiloj restiĝas,Las armas se quedan,,Aseet pysyvät,Armes restent au sol quand prises,Fegyverek mindig felvehetőek,Le armi rimangono in posizione,武器を取得時も残す,습득 후 무기가 남아있기,Wapenverblijven,Våpen forblir,Bronie zostają,Armas permanecem,,Părăsire arme după selectare,Оставлять оружие после подбора,Оружје се остаје након купљења,Silahlar kalıyor -Allow powerups,GMPLYMNU_ALLOWPOWERUPS,,,,Povolit bonusy,Tillad powerups,Boni erlauben,,Permesi plifortigaĵojn,Permitir poderes,,Salli tehostimet,Autoriser powerups,Powerupok engedélyezése,Potenziamenti consentiti,パワーアップアイテムを出現させる,파워 업 허용,Power-ups toestaan,Tillat powerups,Pozwól na wzmocnienia,Permitir powerups,,Permite bonusuri,Разрешить бонусы,Дозволи бонусе,Güçlendirmelere izin ver -Allow health,GMPLYMNU_ALLOWHEALTH,,,,Povolit zdraví,Tillad sundhed,Gesundheit erlauben,,Permesi sanon,Permitir salud,,Salli terveysesineet,Autoriser objets santé,Életerő engedélyezése,Oggetti per la salute consentiti,回復アイテムを出現させる,체력 회복 아이템 허용,Gezondheid toestaan,Tillat helse,Pozwól na przedmioty zdrowotne,Permitir itens de saúde,,Permite prim-ajutor,Разрешить здоровье,Дозволи бонусе за здравље,Sağlığa izin ver -Allow armor,GMPLYMNU_ALLOWARMOR,,,Allow armour,Povolit brnění,Tillad rustning,Panzer erlauben,,Permesi kirason,Permitir armadura,,Salli panssariesineet,Autoriser objets armure,Páncél engedélyezése,Armature consentite,アーマーを出現させる,아머 허용,Pantsertoeslag toestaan,Tillat rustning,Pozwól na pancerz,Permitir itens de armadura,,Permite bonusuri de armură,Разрешить броню,Дозволи оклоп,Zırha izin ver -Spawn farthest,GMPLYMNU_SPAWNFARTHEST,,,,Spawnovat hráče co nejdále od sebe,Spawn længst væk,Am weitesten entfernten Punkt erscheinen,,Ekaperi plej fore,Aparecer más lejos,,Herää henkiin kauimpaa,Apparaître au plus loin,Legmesszebb születés,Spawn il più lontano possibile,他のプレイヤーから最遠の場所に復活,먼 곳에서 소환,Kuitschieten het verst verwijderd,Spawn lengst,Pojaw się jak najdalej,Surgimento mais longe,,Apariție cât mai departată de ceilalți,Воскрешение подальше от остальных,Оживљавање даље од других,En uzakta yumurtla -Same map,GMPLYMNU_SAMEMAP,,,,Stejná mapa,Samme kort,Gleiches Level,,Sama mapo,Mismo mapa,,Sama taso,Même Carte,Ugyanazon pálya,Stessa mappa,同じMAPを繰り返す,같은 맵 플레이,Dezelfde kaart,Samme kart,Ta sama mapa,Mesmo mapa,,Reluare nivel,Зациклить уровень,Понављање нивоа,Aynı harita -Force respawn,GMPLYMNU_FORCERESPAWN,,,,Vynutit respawn,Tvinge respawn,Zurückkehren erzwingen,,Devigi reekaperon,Forzar reaparición,,Pakota henkiinherääminen,Forcer Réapparition,Újraszületés kényszerítése,Forza il respawn,死亡後に強制復活,강제 부활,Respawn is gedwongen,Force respawn,Wymuś ponowne pojawienie się,Forçar reaparecimento,,Reapariție instantă,Моментальное воскрешение,Форсирано оживљавање,Yeniden doğmaya zorla -Allow exit,GMPLYMNU_ALLOWEXIT,,,,Povolit ukončení levelu,Tillad at forlade,Verlassen erlauben,,Permesi eliron,Permitir salir,,Salli tasosta poistuminen,Autoriser Sortie,Kijárat engedélyezése,Uscita consentita,出口の使用を許可,탈출 허용,Uitgang toestaan,Tillat utgang,Pozwól na wyjście,Permitir saída,,Permite ieșirea,Разрешить выход,Дозволи излазак из нивоа,Çıkışa izin ver -Barrels respawn,GMPLYMNU_BARRELSRESPAWN,,,,Barely se respawnují,Tønder respawner,Fässer kehren zurück,,Bareloj reekaperas,Reaparecer barriles,,Tynnyrit syntyvät takaisin,Réapparition des Tonneaux,Hordók újraszületése,Respawn barili esplosivi,爆発バレルを復活させる,폭발통 재생성,Vaten respawn,Tønner respawn,Beczki pojawiają się ponownie,Barrís reaparecem,,Butoaiele reapar,Восстановление бочек,Бурад се ресетују,Variller yeniden doğar -Respawn protection,GMPLYMNU_RESPAWNPROTECTION,,,,Ochrana po respawnu,Respawn-beskyttelse,Schutz beim Zurückkehren,,Protekto de reekapero,Reaparecer protección,,Henkiinheräämissuoja,Protection à la réapparition,Újraszületési védelem,Protezione al respawn,復活したばかりのプレイヤーを保護,부활시 무적,Respawn bescherming,Respawn-beskyttelse,Ochrona przy ponownym pojawieniu się,Proteção de reaparecimento,,Protecție la apariția pe hartă,Кратковременная защита после воскрешения,Ресетује се заштита,Yeniden doğma koruması -Lose frag if fragged,GMPLYMNU_LOSEFRAG,,,,"Hráč ztratí frag, pokud je zabit",Mister frag hvis der er en fragged,Fragabzug bei Tod,,Perdi ludmurdon se ludmurdita,Perder baja al morir,,"Frägin menettäminen, jos joutuu frägätyksi",Perdre 1 frag quand tué,Halál esetén pont veszítése,Perdere i frag se fraggato,キルされた場合は得点を失う,적에게 사망시 점수를 잃음,Verlies frag bij dood,Miste frag hvis fragged,Strać fraga jeśli jesteś sfragowany,Perder frag ao ser fragado,,Pierdere din victime la deces,Терять фраг при смерти,Изгубити гранату ако опаљена,Parçalanırsa parça kaybeder -Keep frags gained,GMPLYMNU_KEEPFRAGS,,,,Ponechávat fragy mezi levely,Beholde vundne frags,Frags zwischen Leveln behalten,,Teni ludmurdojn gajnitajn,Mantener bajas ganadas,,Pidä ansaitut frägit,Garder les frags gagnés,Megszerzett pontok megmaradnak,Mantenere i frag vinti,MAP変更後も得点を保持する,맵 변경 시 점수 유지,Houd frags opgedaan,Behold frags vunnet,Zachowaj zdobyte fragi,Manter frags ganhos,,Păstrare număr victime,Сохранять фраги между уровнями,Задржати стечене гранате,Kırıntıları kazanmaya devam edin -No team switching,GMPLYMNU_NOTEAMSWITCH,,,,Uzamknout týmy,Ingen holdskifte,Kein Teamwechsel,,Neniu teamŝanĝado,No cambiar equipos,,Ei joukkueenvaihtoa,Pas de changement d'équipe,Nincs csapatváltás,Nessun cambio di squadra,チーム変更を禁止,팀 변경 없음,Geen teamwisseling,Ingen lagbytte,Zakaz zmieniania drużyn,Desativar troca de time,Desativar troca de equipa,Nu permite schimbarea echipelor,Запретить переход между командами,Нема мешања тимова,Takım değiştirme yok -Cooperative Settings,GMPLYMNU_COOPERATIVE,,,,Nastavení co-op módu,Kooperativ indstillinger,Kooperativ-Einstellungen,,Agordoj de koopera reĝimo,Configuración de cooperativo,,Yhteispeliasetukset,Options Coopératives,Együttműködő beállítások,Impostazioni cooperativa,協力モードの設定,협동 플레이 설정,Coöperatieve instellingen,Samarbeidsinnstillinger,Ustawienia Kooperacji,Configurações de jogo cooperativo,,Setări cooperative,Настройки совместной игры,Кооперативне поставке,Kooperatif Ayarları -Spawn multiplayer weapons,GMPLYMNU_MULTIPLAYERWEAPONS,,,,Spawnovat multiplayerově zbraně,Spawn multiplayer-våben,Deathmartch Waffen sind verfügbar,,Ekaperigi armilojn por plurludanta reĝimo,Aparecer armas multi.,,Kuolonotteluaseet saatavilla,Spawns d'armes deathmatch,Többjátékos fegyverek engedélyezése,Fai apparire le armi di multigiocatore,マルチプレイ用の武器を出現させる,멀티플레이어 무기 소환,Spawn multi. wapens,Spawn flerspillervåpen,Zezwól na bronie trybu dla wielu graczy,Surgimento de armas em multijogador,,Permite apariția armelor din modul online,Появление оружия из сетевой игры,Створити мулти оружја,Çok oyunculu silahları ortaya çıkarma -Lose entire inventory,GMPLYMNU_LOSEINVENTORY,,,,Ztrácet celý inventář,Mister hele inventaret,Verliere ganzes Inventar,,Perdi tutan inventorion,Perder todo el inventario,,Menetä kaikki varusteet,Perdre l'inventaire,Teljes készlet elvesztése,Perdere l'inventario,死亡時に全ての所持品を失う,인벤토리 비우기,Verlies van de volledige inventaris,Miste hele beholdningen,Utrać cały ekwipunek,Perder todo o inventário,,Pierdere inventar,Терять весь инвентарь при смерти,Изгубити цело складиште,Tüm envanteri kaybetmek -Keep keys,GMPLYMNU_KEEPKEYS,,,,Ponechat klíče,Beholde nøgler,Schlüssel behalten,,Teni ŝlosiojn,Mantener llaves,,Pidä avaimet,Garder clés,Kulcsok megtartása,Mantenere le chiavi,死亡後もキーを保持する,열쇠들을 소지하고 시작,Sleutels bewaren,Behold nøkler,Zachowaj klucze,Manter chaves,,Păstrare chei,Сохранять ключи,Задржати кључеве,Anahtarları sakla -Keep weapons,GMPLYMNU_KEEPWEAPONS,,,,Ponechat zbraně,Behold våben,Waffen behalten,,Teni armilojn,Mantener armas,,Pidä aseet,Garder armes,Fegyverek megtartása,Mantenere le armi,死亡後も武器を保持する,무기들을 소지하고 시작,Wapens bewaren,Behold våpen,Zachowaj bronie,Manter armas,,Păstrare arme,Сохранять оружие,Задржати оружје,Silahları saklayın -Keep armor,GMPLYMNU_KEEPARMOR,,,Keep armour,Ponechat brnění,Behold rustning,Rüstung behalten,,Teni kirason,Mantener armadura,,Pidä panssari,Garder armure,Páncél megtartása,Mantenere l'armatura,死亡後もアーマーを保持する,아머를 소지하고 시작,Pantser bewaren,Behold rustning,Zachowaj pancerz,Manter armadura,,Păstrare armură,Сохранять броню,Задржати панцир,Zırhı sakla -Keep powerups,GMPLYMNU_KEEPPOWERUPS,,,,Ponechat bonusy,Beholde powerups,Behalte Boni,,Teni plifortigaĵojn,Mantener poderes,,Pidä tehostimet,Garder powerups,Powerupok megtartása,Mantenere i potenziamenti,死亡後もパワーアップを保持する,파워업을 소지하고 시작,Power-ups bewaren,Behold powerups,Zachowaj wzmocnienia,Manter powerups,,Păstrare bonusuri,Сохранять супербонусы,Задржати повећану моћ,Güçlendirmeleri sakla -Keep ammo,GMPLYMNU_KEEPAMMO,,,,Ponechat munici,Beholde ammunition,Munition behalten,,Teni municion,Mantener munición,,Pidä ammukset,Garder munitions,Muníció megtartása,Mantenere le ammunizioni,死亡後も弾薬を保持する,탄약을 소지하고 시작,Munitie bewaren,Behold ammunisjon,Zachowaj amunicję,Manter munição,,Păstrare armură,Сохранять патроны,Задржати муницију,Cephaneyi sakla -Lose half ammo,GMPLYMNU_LOSEHALFAMMO,,,,Ztratit polovinu munice,Mister halvdelen af ammunitionen,Halbe Munition verlieren,,Perdi duonon de onia municio,Perder la mitad de la munición,,Menetä puolet ammuksista,Perdre la moité des munitions,Fele muníció elvesztése,Perdere metà ammunizioni,死亡時に弾を半分失う,탄약의 반을 잃음,Verlies halve munitie,Miste halv ammunisjon,Utrać pół amunicji,Perder metade da munição,,Pierdere jumătate din armură,Терять половину патронов,Изгубити пола муниције,Cephanenin yarısını kaybet -Spawn where died,GMPLYMNU_SPAWNWHEREDIED,,,,Respawn na místě smrti,Spawn hvor du døde,Neuerscheinen wo gestorben,,Ekaperigi kie oni mortigis,Aparecer donde moriste,,Herää henkiin kuolinpaikalla,Réapparaitre sur lieu de mort,Halál helyén újraszületés,Respawn nel luogo di morte,死亡したその場で復活,죽은 곳에서 소환,Kuit waar gestorven is,Gyte der du døde,Pojaw się znów tam gdzie zginąłeś,Surgir no local da morte,Reaparecer onde morreu,Apariție la locul decesului,Воскрешение на месте смерти,Оживљавање на месту смрти,Öldüğü yerde yumurtlama -Always spawn multiplayer objects,GMPLYMNU_ALWAYSSPAWNMULTI,,,,Vždy spawnovat multiplayerové objekty,Spawn altid multiplayer-objekter,Mehrspielerobjekte immer erzeugen,,Ĉiam ekaperi plurludantajn objektojn,Siempre hacer aparecer objetos en el modo multijugador,,Aina luo moninpelioliot,Toujours créer des objets multi-joueurs,Mindig megjelennek a többjátékos tárgyak,Fai sempre apparire gli oggetti di multigiocatore,常にマルチプレイ用の物を出現,,Altijd multiplayer objecten spawnen,Alltid gyte flerspillerobjekter,Pozwól na przedmioty dla trybu wielu graczy,Permitir surgimento de objetos multijogador,,Permite apariția obiectelor din multiplayer,Появление объектов из сетевой игры,Увек стварајте објекте за више играча,Her zaman çok oyunculu nesneler oluşturun -Allow Vertical Bullet Spread,GMPLYMNU_NOVERTSPREAD,,,,Povolit svislý rozptyl střelby,Tillad lodret kuglespredning,Vertikale Streuung erlauben,,Permesi vertikalan kuglan disvastiĝon,Desparramar balas de todas las armas en vertical,,Permesu Vertikalan Kuglon Disvastiĝon ,Permettre la propagation verticale des balles,Vertikális fegyverszórás engedélyezve,Permetti la diffusione dei proiettili in verticale,垂直方向への散弾を許可,,Verticale kogelspreiding toestaan,Tillat vertikal kulespredning,Pozwól na pionowy rozrzut pocisków,Permitir espalhamento vertical das balas,,Permiteți răspândirea verticală a gloanțelor,Разрешить вертикальный разброс пуль,Дозволи вертикално ширење метака,Dikey Mermi Yayılımına İzin Ver -Weapons give extra ammo (DM),GMPLYMNU_NOEXTRAAMMO,,,,Zbraně dávají munici navíc (DM),Våben giver ekstra munition (DM),Waffen geben Extramunition,,Armiloj donas ekstran municion (DM),Las armas dan munición extra (DM),,Armiloj donas ekstran municion (DM),Les armes donnent des munitions supplémentaires (DM),A fegyverek extra lőszert adnak (DM),Le armi danno munizioni extra (DM),武器に追加弾薬を付与 (DMのみ),,Wapens geven extra munitie (DM),Våpen gir ekstra ammunisjon (DM),Broń daje dodatkową amunicję (DM),Armas dão munição extra (DM),,Armele oferă muniție suplimentară (DM),Оружие дает дополнительные патроны (DM),Оружје даје додатну муницију (ДМ),Silahlar ekstra cephane verir (DM) -Compatibility Options,OPTMNU_COMPATIBILITY,,,,Kompatibilita,Kompatibilitetsindstillinger,Kompatibilitätsoptionen,Ρυθμίσεις Συμβατότητας,Kongruo-agordoj,Opciones de compatibilidad,,Yhteensopivuusasetukset,Options de Compatibilité,Kompatibilitási beállítások,Opzioni Compatibilità,互換性 オプション,호환 설정,Compatibiliteitsopties,Kompatibilitetsalternativer,Opcje Zgodności,Opções de compatibilidade,,Setări de Compatibilitate,Настройки совместимости,Компатибилност,Uyumluluk Seçenekleri -Compatibility Options,CMPTMNU_TITLE,,,,Nastavení kompatibility,Kompatibilitetsindstillinger,Kompatibilitätsoptionen,Ρυθμίσεις Συμβατότητας,Kongruo-agordoj,Opciones de compatibilidad,,Yhteensopivuusasetukset,Options Compatibilité,Kompatibilitási beállítások,Opzioni compatibilità,互換性 オプション,호환성 설정,Compatibiliteitsopties,Kompatibilitetsalternativer,Opcje Zgodności,Opções de compatibilidade,,Setări de Compatibilitate,Настройки совместимости,Компатибилна подешавања,Uyumluluk Seçenekleri -Compatibility mode,CMPTMNU_MODE,,,,Režim kompatibility,Kompatibilitetstilstand,Kompatibilitätsmodus,,Kongruo-reĝimo,Modo de Compatibilidad,,Yhteensopivuustila,Mode de compatibilité,Kompatibilitási mód,Modalità compatibilità,互換性モード,호환 모드,Compatibiliteitsmodus,Kompatibilitetsmodus,Tryb Zgodności,Modo de compatibilidade,,Mod Compatibilitate,Режим совместимости,Компатибилни мод,Uyumluluk modu -Actor Behavior,CMPTMNU_ACTORBEHAVIOR,,,Actor Behaviour,Objekty,Skuespilleradfærd,Verhalten der Akteure,,Aktorkonduto,Comportamiento del actor,,Olioiden käyttäytyminen,Comportement des Acteurs,Actor viselkedés,Comportamento degli attori,アクターの挙動,개체 관련 설정,Gedrag van de acteur,Skuespilleroppførsel,Zachowanie Aktorów,Comportamento de atores,,Comportament actori,Поведение объектов (акторов),Понашање актора,Aktör Davranışı -Friendly monsters aren't blocked,CMPTMNU_NOBLOCKFRIENDS,,,,Spojenecké příšery nejsou blokovány,Venlige monstre er ikke blokeret,Freundliche Monster werden nicht geblockt,,Amikaj monstroj ne estas baritaj,Monstruos amistosos no son bloqueados,,Myötämielisten hirviöiden esteetön liikkuminen,Monstres amicaux non bloqués,Barátságos szörnyek nem blokkolódnak,I mostri amichevoli non sono bloccati,仲間キャラは敵通行不可ラインの影響を受けない,아군 개체는 BLOCK 선분 무시,Vriendelijke monsters worden niet geblokkeerd.,Vennlige monstre er ikke blokkert,Przyjazne potwory nie mogą być blokowane,Monstros aliados não são bloqueados,,Monștrii aliați nu pot fi blocați,Не блокировать дружественных монстров,Пријатељска чудовишта се не блокирају,Dost canavarlar engellenmez -Limit Pain Elementals' Lost Souls,CMPTMNU_LIMITPAIN,,,,Omezit počet Ztrac. duší (Lost Souls) od Živlů (Pain Elementals),Grænse for tabte sjæle,Limit für Verlorene Seelen,,Limigi Perditajn Animojn de Doloro-Elementuloj,Limitar Almas Errantes de los Elementales del Dolor,,Rajoita kivun henkien kadonneitten sielujen määrää,Limiter âmes des élémentaires,Kiköpött Elveszett Lelkek limitálása,Limita le Anime Erranti degli Elementali del dolore,ペインエレメンタルのロストソウル制限,로스트 소울 소환 21개로 제한,Beperk de Verloren Zielen van Pijn Elementairs,Begrens smertelementalers tapte sjeler,Ogranicz Zagubione Dusze Elementala Bólu,Limitar Almas Perdidas criadas por Elementais da Dor,,Limitează numărul Sufletelor Pierdute create de Elementalii Durerii,Ограничить число потерянных душ от элементалей боли,Ограничи изгубљене душе од елементала патње,Acı Elementallerinin Kayıp Ruhlarını Sınırla -Monster movement is affected by effects,CMPTMNU_MBFMONSTERMOVE,,,,Pohyb příšer je ovlivněn efekty,Monsterbevægelse er påvirket af effekter,Monsterbewegung wird von Effekten beeinflusst,,Monstromovado estas afektita per efektoj,Los efectos afectan al movimiento de los monstruos,,Tehosteet vaikuttavat hirviöiden liikkumiseen,Mouvement monstre affecté par effets,Szörny sebesség függ az effektektől,Il movimento dei mostri è affetto dagli effetti,敵の移動が床の影響を受ける,구역의 이동 효과가 개체들에 영향,Monsterbeweging wordt beïnvloed door effecten,Monsterbevegelse påvirkes av effekter,Efekty wpływają na ruch potworów,Movimento dos monstros é afetado por efeitos,,Efectele afectează deplasarea monștrilor,Эффекты влияют на движение монстров,Ефекти утицају на покретљивост чудовишта,Canavar hareketi etkilerden etkilenir -Monsters cannot cross dropoffs,CMPTMNU_CROSSDROPOFF,,,,Příšery nemohou překročit výšiny,Monstre kan ikke krydse faldgruber,Monster können Abbruchkanten nicht überqueren,,Monstroj ne povas movi trans krutaĵojn,Los monstruos no pueden cruzar declives,,Hirviöt eivät voi ylittää pudotuksia,Monstres ne passent pas les corniches,Szörnyek le tudnak esni a lejtőről,I mostri non posso attraversare gli spigoli,敵はdropoffを横切れない,개체들이 난간에서 추락 불가,Monsters kunnen geen dropoffs kruisen,Monstre kan ikke krysse dropoffs,Potwory nie mogą przekraczać spadków,Monstros não podem atravessar penhascos,,Monștrii nu pot trece peste prăpăstii,Монстрам нельзя пересекать уступы,Чудовишта не могу прећи падове,Canavarlar inişleri geçemez -Monsters get stuck over dropoffs,CMPTMNU_DROPOFF,,,,Příšery se zasekávají na výšinách,Monstre bliver hængende over faldgruber,Monster bleiben auf Abbruchkanten hängen,,Monstroj ĉesiĝi super krutaĵoj,Los monstruos se atascan sobre declives,Los monstruos se atoran sobre declives,Hirviöt joutuvat jumiin pudotusten ylle,Monstres bloqués par les corniches,Szörnyek nem mennek tovább a lejtőnél,I mostri rimangono bloccati sugli spigoli,敵がdropoffにスタックする,개체들이 난간에 끼일 수 있음,Monsters komen vast te zitten boven dropoffs,Monstre blir sittende fast over dropoffs,Potwory mogą utknąć nad spadkami,Monstros ficam presos em penhascos,,Monștrii înțepenesc peste prăpăstii,Монстры застревают на уступах,Чудовишта се заглављују на падовима,Canavarlar inişlerde sıkışıp kalıyor -Monsters see invisible players,CMPTMNU_INVISIBILITY,,,,Příšery vidí neviditelné hráče,Monstre kan se usynlige spillere,Monster können unsichtbare Spieler sehen,,Monstroj povas vidi nevideblajn ludantojn,Los monstruos ven jugadores invisibles,,Hirviöt näkevät näkymättömät pelaajat,Monstres voient joueurs invisibles,Láthatatlanság alatt is látható a játékos,I mostri vedono i giocatori invisibili,敵が透明を見破る,개체들이 투명 플레이어 감지 가능,Monsters zien onzichtbare spelers,Monstre ser usynlige spillere,Potwory widzą niewidzialnych graczy,Monstros enxergam jogadores invisíveis,,Monștrii pot vedea jucătorii invizibili,Монстры видят невидимых игроков,Чудовишта могу да виде невидљиве играче,Canavarlar görünmez oyuncuları görür -No Minotaur floor flames in water,CMPTMNU_MINOTAUR,,,,Minotauři nemohou tvořit plameny ve vodě,Ingen Minotaur gulvflammer i vand,Keine Minotaurus-Flammen im Wasser,,Neniuj plankfajroj de Mintaŭroj en akvo,Sin llamas de minotauro en el agua,,Ei minotaurien lattialiekkejä vedessä,Pas de feu de Massetaur sur l'eau,Minotaurusz égő nyom nincs a vízben,Niente fiamme da terra del Minotauro sull'acqua,ミノタウロスの攻撃が水を通過しない,수면에서는 몰로타우어 지면화염 차단,Geen Minotaurus vloer vlammen in water,Ingen Minotaur-gulvflammer i vann,Brak płomieni Minotaura w wodzie,Desativar fogo do Marretauro na água,,Minotaurii nu pot folosi atacul de foc pe apă,Минотавры не создают огонь в воде,Минотаури не пале ватру у води,Suda Minotor zemin alevleri yok -Spawn item drops on the floor,CMPTMNU_NOTOSSDROPS,,,,Spadlé předměty se objeví na zemi,Spawn-genstande falder på gulvet,Gegenstände erscheinen auf dem Fußboden,,Ekaperigi faligitajn objektojn sur la plankon,Aparecer objetos dejados en el suelo,,Synnytä esinepudotukset lattialle,Objets lâchés direct au sol,Spawnolt tárgy a földön jelenik meg,Gli oggetti allo spawn cadono a terra,アイテムドロップが床に出る,아이템이 떨어질때 지면에 즉시 착지,Paaipunt druppels op de vloer,Spawn-element faller på gulvet,Obiekty pojawiają się na podłodze,Itens surgidos caem direto no chão,,Obiectele scăpate vor apărea la nivelul podelei,Выброшенные предметы создаются на земле,Одбачени предмети се појављују на поду,Eşya yere düşer -DehackEd Behavior,CMPTMNU_DEHACKEDBEHAVIOR,,,DehackEd Behaviour,DeHackEd,DehackEd Adfærd,DehackEd Verhalten,,Konduto de DehackEd,Comportamiento de DehackEd,,DehackEd-käyttäytyminen,Comportement DeHackEd,DeHackEd viselkedés,Comportamento DehackEd,Dehackedの挙動,DehackEd 관련 설정,DehackEd Gedrag,DehackEd oppførsel,Zachowanie DehackEd,Comportamento DehackEd,,Comportament DehackEd,Поведение DeHackEd,DehackEd понашање,DehackEd Davranışı -DEH health settings like Doom2.exe,CMPTMNU_DEHHEALTH,,,,Nastavení DEH jako v Doom2.exe,DEH sundhedsindstillinger som Doom2.exe,DEH Gesundheitseinstellungen wie in Doom2.exe,,DEH sanagordoj kiel Doom2.exe,Configuración de salud DEH como en Doom2.exe,,DEH-terveysasetukset kuin Doom2.exessä,Para. santé DEH comme Doom2.EXE,DEH életerő beállítások mint a Doom2.exe esetében,Impostazioni di salute DEH come in Doom2.exe,Doom2.exe式のDehヘルス設定,DEH 자체의 체력 최댓값 사용,DEH-gezondheidsinstellingen zoals Doom2.exe,DEH helseinnstillinger som Doom2.exe,Ustawienia zrowia DEH jak w Doom2.exe,Configurações de saúde de DEH como em Doom2.exe,,Setări sănătate în DEH precum în Doom2.exe,Настройки здоровья DEH как в Doom2.exe,DEH подешавања здравља као у Doom2.exe,Doom2.exe gibi DEH sağlık ayarları -Original A_Mushroom speed in DEH mods,CMPTMNU_MUSHROOM,,,,Původní rychlost pro A_Mushroom,Original A_Mushroom hastighed i DEH mods,Originale Berechnung für A_Mushroom,,Originala A_Mushroom rapideco en DEH-modifaĵoj,Velocidad original de A_Mushroom en mods con DEH,,Alkuperäinen A_Mushroom-nopeus DEH-modeissa,Vitesse A_Mushroom originale pour DEH,Eredeti A_Mushroom sebesség a DEH modoknál,Velocità originale di A_Mushroom nei mod DEH,Deh Modでの元のA_Mushroom速度,A_Mushroom효과가 MBF 원본의 속력 사용,Originele A_Mushroom in DEH-modellen,Original A_Mushroom hastighet i DEH mods,Oryginalna prędkość A_Mushroom w modach DEH,Velocidade original do A_Mushroom em mods DEH,,Folosește viteza originală pentru A_Mushroom în DEH în moduri,Изначальная скорость A_Mushroom в мод. DEH,Оригинална брзина A_Mushroom в DEH модовима,DEH modlarında orijinal A_Mushroom hızı -Map/Action Behavior,CMPTMNU_MAPACTIONBEHAVIOR,,,Map/Action Behaviour,Levely a akce,Map/Action Adfærd,Level/Aktionsverhalten,,Mapo/Ago-Konduto,Comportamiento Mapa/Acción,,Tason/Toimintojen käyttäytyminen,Comportement Niveau/Actions,Pálya/Akció viselkedés,Comportamento Mappa/Azioni,マップ/アクションの挙動,맵/동작 관련 설정,Kaart/Actiegedrag,Kart / handling oppførsel,Zachowanie Mapy/Akcji,Comportamento de Mapa/Ação,,Comportament hartă/actori,Поведение уровней/действий,Понашање нивоа/догађаја,Harita/Eylem Davranışı -All special lines can block ,CMPTMNU_USEBLOCKING,,,,Veškeré akční čáry blokují použití hráčem,Alle specielle linjer kan blokere ,Alle Speziallinien blockieren Benutzung,,Ĉiuj el specialaj linioj povas bari je ,Todas las líneas especiales pueden bloquear ,,Kaikki erikoisviivat voivat tukkia -toiminnon,Toute ligne d'action bloque ,Minden speciális sor blokkolhatja a parancsot,Tutte le linee speciali possono bloccare il comando ,全てのSpecial Linesがをブロック,특정 선상에 겹쳐있을 시 <사용> 무력화,Alle speciale lijnen kunnen blokkeren.,Alle spesielle linjer kan blokkere ,Wszystkie specjalne linie mogą blokować ,Todas as linhas especiais podem bloquear o comando ,,Toate liniile speciale pot bloca ,Все специальные линии могут блокировать использование,Све специјалне линије могу да блокирају ,Tüm özel hatlar engelleyebilir +",Setor de saída conta para porcentagem de mortes,Setor de saída conta para percentagem de mortes,Numărare decese monștri în sectoare finale,Засчитывать убийства монстров в секторах конца игры,Урачунај убиство чудовишта у коначним секторима,Slutsektorn räknas för dödande %,Öldürme %'si için son sektör sayıları, +Deathmatch Settings,GMPLYMNU_DEATHMATCH,,,,Nastavení deathmatche,Indstillinger for Deathmatch,Deathmatcheinstellungen,,Mortmatĉo-agordoj,Configuración modo a muerte,,Kuolonotteluasetukset,Options Deathmatch,Deathmatch beállítások,Impostazioni deathmatch,デスマッチの設定,데스매치 설정,Deathmatch instellingen,Deathmatch-innstillinger,Ustawienia Deathmatchu,Configurações de Deathmatch,,Setări Deathmatch,Настройки боя насмерть,Детмеч подешавања,Inställningar för Deathmatch,Ölüm Maçı Ayarları, +Weapons stay,GMPLYMNU_WEAPONSSTAY,,,,Zbraně zůstávají,Våben forbliver,Waffen bleiben,,Armiloj restiĝas,Las armas se quedan,,Aseet pysyvät,Armes restent au sol quand prises,Fegyverek mindig felvehetőek,Le armi rimangono in posizione,武器を取得時も残す,습득 후 무기가 남아있기,Wapenverblijven,Våpen forblir,Bronie zostają,Armas permanecem,,Părăsire arme după selectare,Оставлять оружие после подбора,Оружје се остаје након купљења,Vapen stannar kvar,Silahlar kalıyor, +Allow powerups,GMPLYMNU_ALLOWPOWERUPS,,,,Povolit bonusy,Tillad powerups,Boni erlauben,,Permesi plifortigaĵojn,Permitir poderes,,Salli tehostimet,Autoriser powerups,Powerupok engedélyezése,Potenziamenti consentiti,パワーアップアイテムを出現させる,파워 업 허용,Power-ups toestaan,Tillat powerups,Pozwól na wzmocnienia,Permitir powerups,,Permite bonusuri,Разрешить бонусы,Дозволи бонусе,Tillåter powerups,Güçlendirmelere izin ver, +Allow health,GMPLYMNU_ALLOWHEALTH,,,,Povolit zdraví,Tillad sundhed,Gesundheit erlauben,,Permesi sanon,Permitir salud,,Salli terveysesineet,Autoriser objets santé,Életerő engedélyezése,Oggetti per la salute consentiti,回復アイテムを出現させる,체력 회복 아이템 허용,Gezondheid toestaan,Tillat helse,Pozwól na przedmioty zdrowotne,Permitir itens de saúde,,Permite prim-ajutor,Разрешить здоровье,Дозволи бонусе за здравље,Tillåter hälsa,Sağlığa izin ver, +Allow armor,GMPLYMNU_ALLOWARMOR,,,Allow armour,Povolit brnění,Tillad rustning,Panzer erlauben,,Permesi kirason,Permitir armadura,,Salli panssariesineet,Autoriser objets armure,Páncél engedélyezése,Armature consentite,アーマーを出現させる,아머 허용,Pantsertoeslag toestaan,Tillat rustning,Pozwól na pancerz,Permitir itens de armadura,,Permite bonusuri de armură,Разрешить броню,Дозволи оклоп,Tillåt rustning,Zırha izin ver, +Spawn farthest,GMPLYMNU_SPAWNFARTHEST,,,,Spawnovat hráče co nejdále od sebe,Spawn længst væk,Am weitesten entfernten Punkt erscheinen,,Ekaperi plej fore,Aparecer más lejos,,Herää henkiin kauimpaa,Apparaître au plus loin,Legmesszebb születés,Spawn il più lontano possibile,他のプレイヤーから最遠の場所に復活,먼 곳에서 소환,Kuitschieten het verst verwijderd,Spawn lengst,Pojaw się jak najdalej,Surgimento mais longe,,Apariție cât mai departată de ceilalți,Воскрешение подальше от остальных,Оживљавање даље од других,Spawna längst bort,En uzakta yumurtla, +Same map,GMPLYMNU_SAMEMAP,,,,Stejná mapa,Samme kort,Gleiches Level,,Sama mapo,Mismo mapa,,Sama taso,Même Carte,Ugyanazon pálya,Stessa mappa,同じMAPを繰り返す,같은 맵 플레이,Dezelfde kaart,Samme kart,Ta sama mapa,Mesmo mapa,,Reluare nivel,Зациклить уровень,Понављање нивоа,Samma karta,Aynı harita, +Force respawn,GMPLYMNU_FORCERESPAWN,,,,Vynutit respawn,Tvinge respawn,Zurückkehren erzwingen,,Devigi reekaperon,Forzar reaparición,,Pakota henkiinherääminen,Forcer Réapparition,Újraszületés kényszerítése,Forza il respawn,死亡後に強制復活,강제 부활,Respawn is gedwongen,Force respawn,Wymuś ponowne pojawienie się,Forçar reaparecimento,,Reapariție instantă,Моментальное воскрешение,Форсирано оживљавање,Tvinga till återkomst,Yeniden doğmaya zorla, +Allow exit,GMPLYMNU_ALLOWEXIT,,,,Povolit ukončení levelu,Tillad at forlade,Verlassen erlauben,,Permesi eliron,Permitir salir,,Salli tasosta poistuminen,Autoriser Sortie,Kijárat engedélyezése,Uscita consentita,出口の使用を許可,탈출 허용,Uitgang toestaan,Tillat utgang,Pozwól na wyjście,Permitir saída,,Permite ieșirea,Разрешить выход,Дозволи излазак из нивоа,Tillåter utgång,Çıkışa izin ver, +Barrels respawn,GMPLYMNU_BARRELSRESPAWN,,,,Barely se respawnují,Tønder respawner,Fässer kehren zurück,,Bareloj reekaperas,Reaparecer barriles,,Tynnyrit syntyvät takaisin,Réapparition des Tonneaux,Hordók újraszületése,Respawn barili esplosivi,爆発バレルを復活させる,폭발통 재생성,Vaten respawn,Tønner respawn,Beczki pojawiają się ponownie,Barrís reaparecem,,Butoaiele reapar,Восстановление бочек,Бурад се ресетују,Tunnor återkommer,Variller yeniden doğar, +Respawn protection,GMPLYMNU_RESPAWNPROTECTION,,,,Ochrana po respawnu,Respawn-beskyttelse,Schutz beim Zurückkehren,,Protekto de reekapero,Reaparecer protección,,Henkiinheräämissuoja,Protection à la réapparition,Újraszületési védelem,Protezione al respawn,復活したばかりのプレイヤーを保護,부활시 무적,Respawn bescherming,Respawn-beskyttelse,Ochrona przy ponownym pojawieniu się,Proteção de reaparecimento,,Protecție la apariția pe hartă,Кратковременная защита после воскрешения,Ресетује се заштита,Skydd för återstart,Yeniden doğma koruması, +Lose frag if fragged,GMPLYMNU_LOSEFRAG,,,,"Hráč ztratí frag, pokud je zabit",Mister frag hvis der er en fragged,Fragabzug bei Tod,,Perdi ludmurdon se ludmurdita,Perder baja al morir,,"Frägin menettäminen, jos joutuu frägätyksi",Perdre 1 frag quand tué,Halál esetén pont veszítése,Perdere i frag se fraggato,キルされた場合は得点を失う,적에게 사망시 점수를 잃음,Verlies frag bij dood,Miste frag hvis fragged,Strać fraga jeśli jesteś sfragowany,Perder frag ao ser fragado,,Pierdere din victime la deces,Терять фраг при смерти,Изгубити гранату ако опаљена,Förlorar frag om du blir träffad,Parçalanırsa parça kaybeder, +Keep frags gained,GMPLYMNU_KEEPFRAGS,,,,Ponechávat fragy mezi levely,Beholde vundne frags,Frags zwischen Leveln behalten,,Teni ludmurdojn gajnitajn,Mantener bajas ganadas,,Pidä ansaitut frägit,Garder les frags gagnés,Megszerzett pontok megmaradnak,Mantenere i frag vinti,MAP変更後も得点を保持する,맵 변경 시 점수 유지,Houd frags opgedaan,Behold frags vunnet,Zachowaj zdobyte fragi,Manter frags ganhos,,Păstrare număr victime,Сохранять фраги между уровнями,Задржати стечене гранате,Behåll de frags som vunnits,Kırıntıları kazanmaya devam edin, +No team switching,GMPLYMNU_NOTEAMSWITCH,,,,Uzamknout týmy,Ingen holdskifte,Kein Teamwechsel,,Neniu teamŝanĝado,No cambiar equipos,,Ei joukkueenvaihtoa,Pas de changement d'équipe,Nincs csapatváltás,Nessun cambio di squadra,チーム変更を禁止,팀 변경 없음,Geen teamwisseling,Ingen lagbytte,Zakaz zmieniania drużyn,Desativar troca de time,Desativar troca de equipa,Nu permite schimbarea echipelor,Запретить переход между командами,Нема мешања тимова,Inget byte av lag,Takım değiştirme yok, +Cooperative Settings,GMPLYMNU_COOPERATIVE,,,,Nastavení co-op módu,Kooperativ indstillinger,Kooperativ-Einstellungen,,Agordoj de koopera reĝimo,Configuración de cooperativo,,Yhteispeliasetukset,Options Coopératives,Együttműködő beállítások,Impostazioni cooperativa,協力モードの設定,협동 플레이 설정,Coöperatieve instellingen,Samarbeidsinnstillinger,Ustawienia Kooperacji,Configurações de jogo cooperativo,,Setări cooperative,Настройки совместной игры,Кооперативне поставке,Inställningar för samarbete,Kooperatif Ayarları, +Spawn multiplayer weapons,GMPLYMNU_MULTIPLAYERWEAPONS,,,,Spawnovat multiplayerově zbraně,Spawn multiplayer-våben,Deathmartch Waffen sind verfügbar,,Ekaperigi armilojn por plurludanta reĝimo,Aparecer armas multi.,,Kuolonotteluaseet saatavilla,Spawns d'armes deathmatch,Többjátékos fegyverek engedélyezése,Fai apparire le armi di multigiocatore,マルチプレイ用の武器を出現させる,멀티플레이어 무기 소환,Spawn multi. wapens,Spawn flerspillervåpen,Zezwól na bronie trybu dla wielu graczy,Surgimento de armas em multijogador,,Permite apariția armelor din modul online,Появление оружия из сетевой игры,Створити мулти оружја,Spawna flerspelarvapen,Çok oyunculu silahları ortaya çıkarma, +Lose entire inventory,GMPLYMNU_LOSEINVENTORY,,,,Ztrácet celý inventář,Mister hele inventaret,Verliere ganzes Inventar,,Perdi tutan inventorion,Perder todo el inventario,,Menetä kaikki varusteet,Perdre l'inventaire,Teljes készlet elvesztése,Perdere l'inventario,死亡時に全ての所持品を失う,인벤토리 비우기,Verlies van de volledige inventaris,Miste hele beholdningen,Utrać cały ekwipunek,Perder todo o inventário,,Pierdere inventar,Терять весь инвентарь при смерти,Изгубити цело складиште,Förlorar hela inventariet,Tüm envanteri kaybetmek, +Keep keys,GMPLYMNU_KEEPKEYS,,,,Ponechat klíče,Beholde nøgler,Schlüssel behalten,,Teni ŝlosiojn,Mantener llaves,,Pidä avaimet,Garder clés,Kulcsok megtartása,Mantenere le chiavi,死亡後もキーを保持する,열쇠들을 소지하고 시작,Sleutels bewaren,Behold nøkler,Zachowaj klucze,Manter chaves,,Păstrare chei,Сохранять ключи,Задржати кључеве,Behåll nycklar,Anahtarları sakla, +Keep weapons,GMPLYMNU_KEEPWEAPONS,,,,Ponechat zbraně,Behold våben,Waffen behalten,,Teni armilojn,Mantener armas,,Pidä aseet,Garder armes,Fegyverek megtartása,Mantenere le armi,死亡後も武器を保持する,무기들을 소지하고 시작,Wapens bewaren,Behold våpen,Zachowaj bronie,Manter armas,,Păstrare arme,Сохранять оружие,Задржати оружје,Behåll vapen,Silahları saklayın, +Keep armor,GMPLYMNU_KEEPARMOR,,,Keep armour,Ponechat brnění,Behold rustning,Rüstung behalten,,Teni kirason,Mantener armadura,,Pidä panssari,Garder armure,Páncél megtartása,Mantenere l'armatura,死亡後もアーマーを保持する,아머를 소지하고 시작,Pantser bewaren,Behold rustning,Zachowaj pancerz,Manter armadura,,Păstrare armură,Сохранять броню,Задржати панцир,Behåll rustning,Zırhı sakla, +Keep powerups,GMPLYMNU_KEEPPOWERUPS,,,,Ponechat bonusy,Beholde powerups,Behalte Boni,,Teni plifortigaĵojn,Mantener poderes,,Pidä tehostimet,Garder powerups,Powerupok megtartása,Mantenere i potenziamenti,死亡後もパワーアップを保持する,파워업을 소지하고 시작,Power-ups bewaren,Behold powerups,Zachowaj wzmocnienia,Manter powerups,,Păstrare bonusuri,Сохранять супербонусы,Задржати повећану моћ,Behåll powerups,Güçlendirmeleri sakla, +Keep ammo,GMPLYMNU_KEEPAMMO,,,,Ponechat munici,Beholde ammunition,Munition behalten,,Teni municion,Mantener munición,,Pidä ammukset,Garder munitions,Muníció megtartása,Mantenere le ammunizioni,死亡後も弾薬を保持する,탄약을 소지하고 시작,Munitie bewaren,Behold ammunisjon,Zachowaj amunicję,Manter munição,,Păstrare armură,Сохранять патроны,Задржати муницију,Behålla ammunition,Cephaneyi sakla, +Lose half ammo,GMPLYMNU_LOSEHALFAMMO,,,,Ztratit polovinu munice,Mister halvdelen af ammunitionen,Halbe Munition verlieren,,Perdi duonon de onia municio,Perder la mitad de la munición,,Menetä puolet ammuksista,Perdre la moité des munitions,Fele muníció elvesztése,Perdere metà ammunizioni,死亡時に弾を半分失う,탄약의 반을 잃음,Verlies halve munitie,Miste halv ammunisjon,Utrać pół amunicji,Perder metade da munição,,Pierdere jumătate din armură,Терять половину патронов,Изгубити пола муниције,Förlorar halva ammunitionen,Cephanenin yarısını kaybet, +Spawn where died,GMPLYMNU_SPAWNWHEREDIED,,,,Respawn na místě smrti,Spawn hvor du døde,Neuerscheinen wo gestorben,,Ekaperigi kie oni mortigis,Aparecer donde moriste,,Herää henkiin kuolinpaikalla,Réapparaitre sur lieu de mort,Halál helyén újraszületés,Respawn nel luogo di morte,死亡したその場で復活,죽은 곳에서 소환,Kuit waar gestorven is,Gyte der du døde,Pojaw się znów tam gdzie zginąłeś,Surgir no local da morte,Reaparecer onde morreu,Apariție la locul decesului,Воскрешение на месте смерти,Оживљавање на месту смрти,Spawna där du dog,Öldüğü yerde yumurtlama, +Always spawn multiplayer objects,GMPLYMNU_ALWAYSSPAWNMULTI,,,,Vždy spawnovat multiplayerové objekty,Spawn altid multiplayer-objekter,Mehrspielerobjekte immer erzeugen,,Ĉiam ekaperi plurludantajn objektojn,Siempre hacer aparecer objetos en el modo multijugador,,Aina luo moninpelioliot,Toujours créer des objets multi-joueurs,Mindig megjelennek a többjátékos tárgyak,Fai sempre apparire gli oggetti di multigiocatore,常にマルチプレイ用の物を出現,,Altijd multiplayer objecten spawnen,Alltid gyte flerspillerobjekter,Pozwól na przedmioty dla trybu wielu graczy,Permitir surgimento de objetos multijogador,,Permite apariția obiectelor din multiplayer,Появление объектов из сетевой игры,Увек стварајте објекте за више играча,Alltid spawna flerspelarobjekt,Her zaman çok oyunculu nesneler oluşturun, +Allow Vertical Bullet Spread,GMPLYMNU_NOVERTSPREAD,,,,Povolit svislý rozptyl střelby,Tillad lodret kuglespredning,Vertikale Streuung erlauben,,Permesi vertikalan kuglan disvastiĝon,Desparramar balas de todas las armas en vertical,,Permesu Vertikalan Kuglon Disvastiĝon ,Permettre la propagation verticale des balles,Vertikális fegyverszórás engedélyezve,Permetti la diffusione dei proiettili in verticale,垂直方向への散弾を許可,,Verticale kogelspreiding toestaan,Tillat vertikal kulespredning,Pozwól na pionowy rozrzut pocisków,Permitir dispersão vertical das balas,,Permiteți răspândirea verticală a gloanțelor,Разрешить вертикальный разброс пуль,Дозволи вертикално ширење метака,Tillåt vertikal kulspridning,Dikey Mermi Yayılımına İzin Ver, +Weapons give extra ammo (DM),GMPLYMNU_NOEXTRAAMMO,,,,Zbraně dávají munici navíc (DM),Våben giver ekstra munition (DM),Waffen geben Extramunition,,Armiloj donas ekstran municion (DM),Las armas dan munición extra (DM),,Armiloj donas ekstran municion (DM),Les armes donnent des munitions supplémentaires (DM),A fegyverek extra lőszert adnak (DM),Le armi danno munizioni extra (DM),武器に追加弾薬を付与 (DMのみ),,Wapens geven extra munitie (DM),Våpen gir ekstra ammunisjon (DM),Broń daje dodatkową amunicję (DM),Armas dão munição extra (DM),,Armele oferă muniție suplimentară (DM),Оружие даёт дополнительные патроны (бой насмерть),Оружје даје додатну муницију (ДМ),Vapen ger extra ammunition (DM),Silahlar ekstra cephane verir (DM), +Compatibility Options,OPTMNU_COMPATIBILITY,,,,Kompatibilita,Kompatibilitetsindstillinger,Kompatibilitätsoptionen,Ρυθμίσεις Συμβατότητας,Kongruo-agordoj,Opciones de compatibilidad,,Yhteensopivuusasetukset,Options de Compatibilité,Kompatibilitási beállítások,Opzioni Compatibilità,互換性 オプション,호환 설정,Compatibiliteitsopties,Kompatibilitetsalternativer,Opcje Zgodności,Opções de compatibilidade,,Setări de Compatibilitate,Настройки совместимости,Компатибилност,Kompatibilitetsalternativ,Uyumluluk Seçenekleri, +Compatibility Options,CMPTMNU_TITLE,,,,Nastavení kompatibility,Kompatibilitetsindstillinger,Kompatibilitätsoptionen,Ρυθμίσεις Συμβατότητας,Kongruo-agordoj,Opciones de compatibilidad,,Yhteensopivuusasetukset,Options Compatibilité,Kompatibilitási beállítások,Opzioni compatibilità,互換性 オプション,호환성 설정,Compatibiliteitsopties,Kompatibilitetsalternativer,Opcje Zgodności,Opções de compatibilidade,,Setări de Compatibilitate,Настройки совместимости,Компатибилна подешавања,Kompatibilitetsalternativ,Uyumluluk Seçenekleri, +Compatibility mode,CMPTMNU_MODE,,,,Režim kompatibility,Kompatibilitetstilstand,Kompatibilitätsmodus,,Kongruo-reĝimo,Modo de compatibilidad,,Yhteensopivuustila,Mode de compatibilité,Kompatibilitási mód,Modalità compatibilità,互換性モード,호환 모드,Compatibiliteitsmodus,Kompatibilitetsmodus,Tryb Zgodności,Modo de compatibilidade,,Mod Compatibilitate,Режим совместимости,Компатибилни мод,Kompatibilitetsläge,Uyumluluk modu, +Actor Behavior,CMPTMNU_ACTORBEHAVIOR,,,Actor Behaviour,Objekty,Skuespilleradfærd,Verhalten der Akteure,,Aktorkonduto,Comportamiento del actor,,Olioiden käyttäytyminen,Comportement des Acteurs,Actor viselkedés,Comportamento degli attori,アクターの挙動,개체 관련 설정,Gedrag van de acteur,Skuespilleroppførsel,Zachowanie Aktorów,Comportamento de atores,,Comportament actori,Поведение объектов (акторов),Понашање актора,Beteende hos skådespelare,Aktör Davranışı, +Friendly monsters aren't blocked,CMPTMNU_NOBLOCKFRIENDS,,,,Spojenecké příšery nejsou blokovány,Venlige monstre er ikke blokeret,Freundliche Monster werden nicht geblockt,,Amikaj monstroj ne estas baritaj,Monstruos amistosos no son bloqueados,,Myötämielisten hirviöiden esteetön liikkuminen,Monstres amicaux non bloqués,Barátságos szörnyek nem blokkolódnak,I mostri amichevoli non sono bloccati,仲間キャラは敵通行不可ラインの影響を受けない,아군 개체는 BLOCK 선분 무시,Vriendelijke monsters worden niet geblokkeerd.,Vennlige monstre er ikke blokkert,Przyjazne potwory nie mogą być blokowane,Monstros aliados não são bloqueados,,Monștrii aliați nu pot fi blocați,Не блокировать дружественных монстров,Пријатељска чудовишта се не блокирају,Vänliga monster blockeras inte,Dost canavarlar engellenmez, +Limit Pain Elementals' Lost Souls,CMPTMNU_LIMITPAIN,,,,Omezit počet Ztrac. duší (Lost Souls) od Živlů (Pain Elementals),Grænse for tabte sjæle,Limit für Verlorene Seelen,,Limigi Perditajn Animojn de Doloro-Elementuloj,Limitar Almas Errantes de los Elementales del Dolor,,Rajoita kivun henkien kadonneitten sielujen määrää,Limiter âmes des élémentaires,Kiköpött Elveszett Lelkek limitálása,Limita le Anime Erranti degli Elementali del dolore,ペインエレメンタルのロストソウル制限,로스트 소울 소환 21개로 제한,Beperk de Verloren Zielen van Pijn Elementairs,Begrens smertelementalers tapte sjeler,Ogranicz Zagubione Dusze Elementala Bólu,Limitar Almas Perdidas criadas por Elementais da Dor,,Limitează numărul Sufletelor Pierdute create de Elementalii Durerii,Ограничить число потерянных душ от элементалей боли,Ограничи изгубљене душе од елементала патње,Begränsa Pain Elementals förlorade själar,Acı Elementallerinin Kayıp Ruhlarını Sınırla, +Monster movement is affected by effects,CMPTMNU_MBFMONSTERMOVE,,,,Pohyb příšer je ovlivněn efekty,Monsterbevægelse er påvirket af effekter,Monsterbewegung wird von Effekten beeinflusst,,Monstromovado estas afektita per efektoj,Los efectos afectan al movimiento de los monstruos,,Tehosteet vaikuttavat hirviöiden liikkumiseen,Mouvement monstre affecté par effets,Szörny sebesség függ az effektektől,Il movimento dei mostri è affetto dagli effetti,敵の移動が床の影響を受ける,구역의 이동 효과가 개체들에 영향,Monsterbeweging wordt beïnvloed door effecten,Monsterbevegelse påvirkes av effekter,Efekty wpływają na ruch potworów,Movimento dos monstros é afetado por efeitos,,Efectele afectează deplasarea monștrilor,Эффекты влияют на движение монстров,Ефекти утицају на покретљивост чудовишта,Monsterrörelse påverkas av effekter,Canavar hareketi etkilerden etkilenir, +Monsters cannot cross dropoffs,CMPTMNU_CROSSDROPOFF,,,,Příšery nemohou překročit výšiny,Monstre kan ikke krydse faldgruber,Monster können Abbruchkanten nicht überqueren,,Monstroj ne povas movi trans krutaĵojn,Los monstruos no pueden cruzar declives,,Hirviöt eivät voi ylittää pudotuksia,Monstres ne passent pas les corniches,Szörnyek le tudnak esni a lejtőről,I mostri non posso attraversare gli spigoli,敵はdropoffを横切れない,개체들이 난간에서 추락 불가,Monsters kunnen geen dropoffs kruisen,Monstre kan ikke krysse dropoffs,Potwory nie mogą przekraczać spadków,Monstros não podem atravessar penhascos,,Monștrii nu pot trece peste prăpăstii,Монстрам нельзя пересекать уступы,Чудовишта не могу прећи падове,Monster kan inte korsa stupstockar,Canavarlar inişleri geçemez, +Monsters get stuck over dropoffs,CMPTMNU_DROPOFF,,,,Příšery se zasekávají na výšinách,Monstre bliver hængende over faldgruber,Monster bleiben auf Abbruchkanten hängen,,Monstroj ĉesiĝi super krutaĵoj,Los monstruos se atascan sobre declives,Los monstruos se atoran sobre declives,Hirviöt joutuvat jumiin pudotusten ylle,Monstres bloqués par les corniches,Szörnyek nem mennek tovább a lejtőnél,I mostri rimangono bloccati sugli spigoli,敵がdropoffにスタックする,개체들이 난간에 끼일 수 있음,Monsters komen vast te zitten boven dropoffs,Monstre blir sittende fast over dropoffs,Potwory mogą utknąć nad spadkami,Monstros ficam presos em penhascos,,Monștrii înțepenesc peste prăpăstii,Монстры застревают на уступах,Чудовишта се заглављују на падовима,Monster fastnar över stupstockar,Canavarlar inişlerde sıkışıp kalıyor, +Monsters see invisible players,CMPTMNU_INVISIBILITY,,,,Příšery vidí neviditelné hráče,Monstre kan se usynlige spillere,Monster können unsichtbare Spieler sehen,,Monstroj povas vidi nevideblajn ludantojn,Los monstruos ven jugadores invisibles,,Hirviöt näkevät näkymättömät pelaajat,Monstres voient joueurs invisibles,Láthatatlanság alatt is látható a játékos,I mostri vedono i giocatori invisibili,敵が透明を見破る,개체들이 투명 플레이어 감지 가능,Monsters zien onzichtbare spelers,Monstre ser usynlige spillere,Potwory widzą niewidzialnych graczy,Monstros enxergam jogadores invisíveis,,Monștrii pot vedea jucătorii invizibili,Монстры видят невидимых игроков,Чудовишта могу да виде невидљиве играче,Monster ser osynliga spelare,Canavarlar görünmez oyuncuları görür, +No Minotaur floor flames in water,CMPTMNU_MINOTAUR,,,,Minotauři nemohou tvořit plameny ve vodě,Ingen Minotaur gulvflammer i vand,Keine Minotaurus-Flammen im Wasser,,Neniuj plankfajroj de Mintaŭroj en akvo,Sin llamas de minotauro en el agua,,Ei minotaurien lattialiekkejä vedessä,Pas de feu de Massetaur sur l'eau,Minotaurusz égő nyom nincs a vízben,Niente fiamme da terra del Minotauro sull'acqua,ミノタウロスの攻撃が水を通過しない,수면에서는 몰로타우어 지면화염 차단,Geen Minotaurus vloer vlammen in water,Ingen Minotaur-gulvflammer i vann,Brak płomieni Minotaura w wodzie,Desativar fogo do Marretauro na água,,Minotaurii nu pot folosi atacul de foc pe apă,Минотавры не создают огонь в воде,Минотаури не пале ватру у води,Ingen Minotaur golvlåga flammar i vatten,Suda Minotor zemin alevleri yok, +Spawn item drops on the floor,CMPTMNU_NOTOSSDROPS,,,,Spadlé předměty se objeví na zemi,Spawn-genstande falder på gulvet,Gegenstände erscheinen auf dem Fußboden,,Ekaperigi faligitajn objektojn sur la plankon,Aparecer objetos dejados en el suelo,,Synnytä esinepudotukset lattialle,Objets lâchés direct au sol,Spawnolt tárgy a földön jelenik meg,Gli oggetti allo spawn cadono a terra,アイテムドロップが床に出る,아이템이 떨어질때 지면에 즉시 착지,Paaipunt druppels op de vloer,Spawn-element faller på gulvet,Obiekty pojawiają się na podłodze,Itens surgidos caem direto no chão,,Obiectele scăpate vor apărea la nivelul podelei,Выброшенные предметы создаются на земле,Одбачени предмети се појављују на поду,Spawner föremål faller på golvet.,Eşya yere düşer, +DehackEd Behavior,CMPTMNU_DEHACKEDBEHAVIOR,,,DehackEd Behaviour,DeHackEd,DehackEd Adfærd,DehackEd Verhalten,,Konduto de DehackEd,Comportamiento de DehackEd,,DehackEd-käyttäytyminen,Comportement DeHackEd,DeHackEd viselkedés,Comportamento DehackEd,DehackEdの挙動,DehackEd 관련 설정,DehackEd Gedrag,DehackEd oppførsel,Zachowanie DehackEd,Comportamento DehackEd,,Comportament DehackEd,Поведение DeHackEd,DehackEd понашање,DehackEd-beteende,DehackEd Davranışı, +DEH health settings like Doom2.exe,CMPTMNU_DEHHEALTH,,,,Nastavení DEH jako v Doom2.exe,DEH sundhedsindstillinger som Doom2.exe,DEH Gesundheitseinstellungen wie in Doom2.exe,,DEH sanagordoj kiel Doom2.exe,Configuración de salud DEH como en Doom2.exe,,DEH-terveysasetukset kuin Doom2.exessä,Para. santé DEH comme Doom2.EXE,DEH életerő beállítások mint a Doom2.exe esetében,Impostazioni di salute DEH come in Doom2.exe,Doom2.exe式のDEHヘルス設定,DEH 자체의 체력 최댓값 사용,DEH-gezondheidsinstellingen zoals Doom2.exe,DEH helseinnstillinger som Doom2.exe,Ustawienia zrowia DEH jak w Doom2.exe,Configurações de saúde de DEH como em Doom2.exe,,Setări sănătate în DEH precum în Doom2.exe,Настройки здоровья DEH как в Doom2.exe,DEH подешавања здравља као у Doom2.exe,DEH-hälsoinställningar som Doom2.exe,Doom2.exe gibi DEH sağlık ayarları, +Original A_Mushroom speed in DEH mods,CMPTMNU_MUSHROOM,,,,Původní rychlost pro A_Mushroom,Original A_Mushroom hastighed i DEH mods,Originale Berechnung für A_Mushroom,,Originala A_Mushroom rapideco en DEH-modifaĵoj,Velocidad original de A_Mushroom en mods con DEH,,Alkuperäinen A_Mushroom-nopeus DEH-modeissa,Vitesse A_Mushroom originale pour DEH,Eredeti A_Mushroom sebesség a DEH modoknál,Velocità originale di A_Mushroom nei mod DEH,DEH Modでの元のA_Mushroom速度,A_Mushroom효과가 MBF 원본의 속력 사용,Originele A_Mushroom in DEH-modellen,Original A_Mushroom hastighet i DEH mods,Oryginalna prędkość A_Mushroom w modach DEH,Velocidade original do A_Mushroom em mods DEH,,Folosește viteza originală pentru A_Mushroom în DEH în moduri,Изначальная скорость A_Mushroom в мод. DEH,Оригинална брзина A_Mushroom в DEH модовима,Ursprunglig A_Mushroom-hastighet i DEH-modifieringar,DEH modlarında orijinal A_Mushroom hızı, +Map/Action Behavior,CMPTMNU_MAPACTIONBEHAVIOR,,,Map/Action Behaviour,Levely a akce,Map/Action Adfærd,Level/Aktionsverhalten,,Mapo/Ago-Konduto,Comportamiento Mapa/Acción,,Tason/Toimintojen käyttäytyminen,Comportement Niveau/Actions,Pálya/Akció viselkedés,Comportamento Mappa/Azioni,マップ/アクションの挙動,맵/동작 관련 설정,Kaart/Actiegedrag,Kart / handling oppførsel,Zachowanie Mapy/Akcji,Comportamento de Mapa/Ação,,Comportament hartă/actori,Поведение уровней/действий,Понашање нивоа/догађаја,Beteende för kartor/handlingar,Harita/Eylem Davranışı, +All special lines can block ,CMPTMNU_USEBLOCKING,,,,Veškeré akční čáry blokují použití hráčem,Alle specielle linjer kan blokere ,Alle Speziallinien blockieren Benutzung,,Ĉiuj el specialaj linioj povas bari je ,Todas las líneas especiales pueden bloquear ,,Kaikki erikoisviivat voivat tukkia -toiminnon,Toute ligne d'action bloque ,Minden speciális sor blokkolhatja a parancsot,Tutte le linee speciali possono bloccare il comando ,全てのSpecial Linesがをブロック,특정 선상에 겹쳐있을 시 <사용> 무력화,Alle speciale lijnen kunnen blokkeren.,Alle spesielle linjer kan blokkere ,Wszystkie specjalne linie mogą blokować ,Todas as linhas especiais podem bloquear o comando ,,Toate liniile speciale pot bloca ,Все специальные линии могут блокировать использование,Све специјалне линије могу да блокирају ,Alla speciella linjer kan blockera ,Tüm özel hatlar engelleyebilir, Allow any bossdeath for level special,CMPTMNU_ANYBOSSDEATH,,,,Smrt jakéhokoli bosse může aktivovat speciální akci levelu,Tillad enhver bossdeath for level special,Jeder Boss-Tod zählt für Spezialaktionen,,Permesi iun ajn estro-morton por nivelspecialo,Permitir cualquier muerte de jefe por especial de nivel,,Mikä tahansa pomokuolema lasketaan tason erikoistoiminnossa,N'importe quel boss active actions boss,Főgonosz halála megengedett a speciális pályákon,"Qualunque morte del boss per le azioni speciali consentita -",いずれのBossdeathでもlevel specialを許可,어느 레벨에서든 BOSSDEATH 이벤트 허용,Laat een eventuele bossdood voor een speciaal niveau toe....,Tillat enhver bossdeath for nivå spesiell,Każda śmierć bossa liczy się jako akcja specjalna,Permitir qualquer morte de chefão para ação especial,Permitir qualquer morte de chefe para ação especial,Orice utilizare de A_BossDeath activează evenimente speciale în nivel,Любой вызов A_BossDeath активирует special уровня,Било који случај A_BossDeath активира special на нивоу,Özel seviye için herhangi bir boss ölümüne izin ver -Disable BOOM door light effect,CMPTMNU_NODOORLIGHT,,,,Zakázat světelný efekt dveří z BOOMu,Deaktivere BOOM dør lys effekt,Boom-Türlichteffekt deaktiviert.,,Malvalidigi pordlumo-efekton de BOOM,Desactivar efecto de luz de puerta de BOOM,,BOOM-ovivalotehoste pois käytöstä,Pas d'effet de lumière BOOM sur portes,A BOOM ajtó fény effekt kikapcsolása ,Disabilitato l'effetto Boom della luce della porta,BOOMドアライト エフェクトを無効化,붐 문간 조명보정 효과 끄기,BOOM-deurlichteffect uitschakelen,Deaktiver BOOM dør lyseffekt,Wyłącz efekt oświetlenia drzwi BOOM,Desabilitar efeito de luz de porta do BOOM,,Dezactivează efectele de lumină BOOM pentru uși,Отключить световой эффект из BOOM на дверях,Онемогући светлосни ефекат из BOOM-а на вратима,BOOM kapı ışığı efektini devre dışı bırak -Find neighboring light like Doom,CMPTMNU_LIGHT,,,Find neighbouring light like Doom,Nacházet nejbližší světlo jako Doom,Find nabo lys som Doom,Finde benachbartes Licht wie in Doom,,Trovi najbaran lumon kiel Doom,Encontrar luces vecinas como en Doom,,Etsi vierustava valo niin kuin Doom,Trouver prochaine texture comme DOOM,Szomszédos fényforrás keresése mint Doom-ban,Trova le luci vicine come in DOOM,DOOM式の最寄りライト検知,고전적인 조명추적 사용,Vind naburig licht zoals Doom,Finn nærliggende lys som Doom,Znajdź sąsiadujące światło jak w Doomie,Encontrar luz vizinha como em Doom,,Caută o sursă de lumină apropriată ca în Doom,Искать соседний источник света как в Doom,Нађи суседно светло као у Doom-у,Doom gibi komşu ışık bulun -Find shortest textures like Doom,CMPTMNU_SHORTTEX,,,,Nacházet nejkratší textury jako Doom,Find korteste teksturer som Doom,Finde kurze Texturen wie in Doom,,Trovi la plej mallongajn tekstaĵojn kiel Doom,Encontrar texturas más cortas como en Doom,,Etsi lyhyimmät pintakuvioinnit niin kuin Doom,Trouver plus petite texture comme Doom,Legkisebb textúrák keresése mint Doom-ban,Trova le texture più piccole come in DOOM,DOOM式の最短テクスチャー検知,고전적인 텍스처분류 사용,Vind de kortste texturen zoals Doom,Finn korteste teksturer som Doom,Znajdź najkrótsze tekstury jak w Doomie,Encontrar menores texturas como em Doom,,Caută cele mai scurte texturi ca în Doom,Искать кратчайшие текстуры как в Doom,Нађи најкраће текстуре као у Doom-у,Doom gibi en kısa dokuları bulun -Use buggier stair building,CMPTMNU_STAIRS,,,,Použít méně stabilní stavění schodů,Brug buggier trappe bygning,Benutze fehlerhafte Treppenbaufunktion,,Uzi pli ciman ŝtupo-konstruadon,Usar construcción defectuosa de escaleras,,Käytä viallisempaa portaanrakennusfunktiota,Construction d'escalier plus buggée,Bugosabb lépcsőépítés használata,Usa la struttura a scalinate più buggata,バグった階段生成を使用,구형 계단상승 효과 사용,Gebruik buggier trapgebouw,Bruk buggier trappebygging,Użyj wadliwej funkcji budowania schodów,Usar construção defeituosa de escadas,,Utilizare mod de ridicare al scărilor incorect,Использовать неисправленное построение лестниц,Користи непоправљено грађење степеница,Daha az doğru merdiven binası kullanın -Use Doom's floor motion behavior,CMPTMNU_FLOORMOVE,,,Use Doom's floor motion behaviour,Použít původní chování Doomu pro pohyb podlah,Brug Dooms gulv bevægelsesadfærd,Benutze Dooms Verhalten für bewegende Böden,,Uzi konduton de Doom por plankmovo-konduto,Usar comportamiento de mov. del suelo de Doom,,Lattialiike käyttäytyy kuin Doomissa,Mouvement des sols à la DOOM,Doom jellegű padló mozgás,Adotta il comportamento di DOOM per il movimento sul pavimento,DOOMでの床の動作挙動を使用,표면이나 천장이 서로 통과가 가능함,Gebruik Doom's vloer beweging vloer,Bruk Dooms gulvbevegelsesatferd,Użyj zachowanie ruchu podłogi Dooma,Usar comportamento de mov. do chão de Doom,,Utilizare comportament de mișcare al podelelor din Doom,Поведение движения по полу из Doom,Користи Doom-ово подно моционо понашање,Doom'un zemin hareketi davranışını kullanın -Use Doom's point-on-line algorithm,CMPTMNU_POINTONLINE,,,,Použít původní algoritmus bod-na-čáře z Doomu,Brug Dooms point-on-line algoritme,Benutze Dooms Punkt-auf-Linie Algorithmus,,Uzi algoritmon de Doom por trovi punkton sur linio,Usar algoritmo de punto en línea de Doom,,Käytä Doomin piste viivalla -algoritmia,Algorithme point-sur-ligne de DOOM,Doom jellegű point-on-line algoritmus,Usa l'algoritmo del 'punto giacente sulla linea' di DOOM,DOOMでのポイントライン アルゴリズム を使用,구형 선상 지점 정의법 사용,Gebruik Doom's point-on-line-algoritme,Bruk Dooms punkt-på-nett-algoritme,Użyj algorytmu punktu na linii z Dooma,Usar algorítmo de ponto-em-linha de Doom,,Utilizare algoritm point-on-line din Doom,Использовать алгоритм «точка на линии» из Doom,Користи Doom-ов point-on-line алгоритам,Doom'un point-on-line algoritmasını kullanın -Level exit can be triggered more than once,CMPTMNU_MULTIEXIT,,,,Odchod z levelu může být spuštěn vícekrát,Level exit kan udløses mere end én gang,Ausgang kann mehr als einmal aktiviert werden,,Nivelelirejo povas esti ekagigita pli ol unufoje,La salida de nivel puede ser activada más de una vez,,Tasosta poistumisen voi laukaista useammin kuin kerran,Sortie niveau utilisable plusieures fois,Pálya kijárat többször is triggerelhető,L'uscita del livello può attivarsi più di una volta,Exitを複数回起動出来る,레벨 출구 트리거 한 번 이상 작동,Niveau-uitgang kan meer dan eens worden geactiveerd,Nivåutgang kan utløses mer enn én gang,Wyjście z poziomu może być uruchomione więcej niż raz,Saída de fase pode ser ativada mais de uma vez,Saída de nível pode ser ativada mais de uma vez,Ieșirea nivelului poate fi activată de mai multe ori,Выходы могут быть активированы более одного раза,Излаз нивоа може бити активиран више пута,Seviye çıkışı birden fazla kez tetiklenebilir -Physics Behavior,CMPTMNU_PHYSICSBEHAVIOR,,,Physics Behaviour,Fyzika,Fysik-adfærd,Physik-Verhalten,,Fizikokonduto,Comportamiento de la física,,Fysiikan käyttäytyminen,Comportement Physique,Fizika viselkedés,Comportamento della fisica,物理の挙動,물리 관련 설정,Fysica gedrag,Fysikkoppførsel,Zachowanie Fizyki,Comportamento de Física,Comportamento das Físicas,Comportament fizică,Поведение физики,Физичко понашање,Fiziksel Davranış -Actors are infinitely tall,CMPTMNU_NOPASSOVER,,,,Objekty jsou nekonečně vysoké,Aktører er uendeligt høje,Akteure sind unendlich hoch,,Aktoroj estas senfine altaj,Los actores son infinitamente altos,,Oliot ovat äärettömän korkeita,Hauteur des acteurs infinie,Személyek végtelen magasak,Gli attori sono infinitamente alti,アクターの上下には入れない,무한으로 키가 큰 개체,Acteurs zijn oneindig lang,Skuespillere er uendelig høye,Aktorzy są nieskończenie wysocy,Atores são infinitamente altos,,Actorii au înălțime infinită,Объекты бесконечно высокие,Глумци су бесконачно велики,Aktörler sonsuz uzunlukta -Boom scrollers are additive,CMPTMNU_BOOMSCROLL,,,,Boom posuvníky jsou aditivní,Boom scrollers er additive,Boom-Scroller sind additiv,,Skrolantaj Teksturaj de Boom estas adicia,Los scrollers de Boom son aditivos,,Boom-vierittimet ovat additiivisia,Glisseurs BOOM additifs,Boom scroller-ek összeadódnak,Le barre di scorrimento BOOM sono additivi,BOOM型 壁スクロールを適用,붐 스크롤러 누적법 사용,Boom scrollers zijn additief,Boom scrollere er additive,Przewijane tekstury Boom są addytywne,Scrollers de Boom são aditivos,,Elementele derulante BOOM sunt aditive,Конвейеры из BOOM складываются с собой,Boom скролери су додаци,Bom kaydırıcıları katkı maddelidir -Cannot travel straight NSEW,CMPTMNU_BADANGLES,,,,Nelze se pohybovat přímo na SJVZ,Kan ikke rejse lige NSØV,Bewegungsrichtungen direkt NSOW nicht möglich,,Ne eblas veturi rekte NSEW,Emular error de mal ángulo,,Liikkuminen puhtaasti pääilmansuuntiin mahdotonta,Direction pure NSEO impossible,Nem haladhat egyenes vonalban NSEW,Non si può viaggiare esattamente nelle direzioni cardinali,テレポート時は東西南北に直進出来ない,전방위 방향으로 이동 불가,Kan niet rechtdoor reizen NZOW,Kan ikke reise rett NSØV,Pozwól na błąd złego kąta,Impossível se deslocar reto em direções cardeais,Impossível se deslocar em frente em direções cardeais,Interzice deplasarea liniară NSEW,Запрещено двигаться прямо на С/Ю/З/В,Немогуће путовати право на NSEW,Düz seyahat edemez KGDB -Enable wall running,CMPTMNU_WALLRUN,,,,Povolit wall running (běhaní pomocí zdi),Aktiver vægløb,Ermögliche Wandrennen,,Ebligi kuradon sur muroj,Activar correr por muros,,Salli seinäjuoksu,Activer Wallrunning,Falon futás engedélyezése,Wall running abilitata,壁伝い走行を許可,벽면가속이동 허용,Wandloop mogelijk maken,Aktiver veggkjøring,Włącz szybkie bieganie wzdłuż ścian,Habilitar corrida por paredes,Permitir corrida pelas paredes,Permite fuga cu ajutorul pereților (Wallrun),Включить быстрый бег вдоль стен (wallrunning),Омогући пролажење кроз зида,Duvar çalışmasını etkinleştirin -Raven scrollers use original speed,CMPTMNU_RAVENSCROLL,,,,Raven posuvníky používají původní rychlost,Raven scrollers bruger original hastighed,Raven-Scroller benutzen originale Geschwindigkeit,,Skrolantaj teksturoj de Raven uzas originalan rapidecon,Los scrollers de Raven usan la velocidad original,,Ravenin vierittimet liikkuvat alkuperäisnopeudella,Glisseurs Raven à leur vitesse originale,Raven scroller-ek eredeti sebességűek,Le barre di scorrimento Raven usano la velocità originale,Raven型 壁スクロールは元の速度を使用,구형 헤러틱/헥센 스크롤러 사용,Raven scrollers gebruiken originele snelheid,Raven scrollers bruker original hastighet,Przwijane tekstury podłogi Raven używają oryginalną prędkość,Scrollers da Raven usam velocidade original,,Elementele derulante Raven folosesc viteza originală,Конвейеры из Raven используют неизменённую скорость,Raven скролери користе оригиналну брзину,Kuzgun kaydırıcılar orijinal hızı kullanır -Self ref. sectors don't block shots,CMPTMNU_TRACE,,,,Sebe-odkazující sektory neblokují střely,Selvreflekterende sektorer blokerer ikke for skud,Selbstreferenzierende Sektoren blockieren keine Schüsse,,Sinreferencantaj sektoroj ne baras pafojn,Sectores autoreferidos no bloquean los disparos,,Itseensä viittaavat sektorit eivät estä laukauksia,Secteur autoréférencé ne bloque pas les tirs,Saját ref.sektorok nem blokkkolják a lövéseket,Settori autoreferenziati non bloccano i colpi,Self ref.セクターは射撃を阻害しない,자기 참조 섹터가 총탄을 막지 않음,Zelfreferentie sectoren blokkeren geen schoten,Selvrefererende sektorer blokkerer ikke skudd.,Sektory odnoszoce się do siebie nie blokują strzałów,Setores autorreferidos não bloqueiam tiros,,Sectoarele cu referință proprie blochează focurile,Самоссылающиеся секторы не блокируют выстрелы,Самореф. сектори не блокирају пуцњеве,Kendi kendine hakemlik yapan sektörler atışları engellemez. -Use Doom code for hitscan checks,CMPTMNU_HITSCAN,,,,Použít původní Doom kód pro kontrolu hitscanů,Brug Doom-code til hitscan-kontrol,Benutze Original-Doom-Code für Hitscan-Checks,,Uzi kodon de Doom por batskanoj-kontrolado,Usar código de Doom para revisión de hitscan,,Käytä Doomin osumislaskentakoodia,Vérification Hitscan à la DOOM,Doom kód használata a hitscan ellenőrzéshez,Usa il codice DOOM per il controllo sugli hitscan,DOOM型ヒットスキャンチェックを使用,구형 총탄 판정법 사용,Gebruik Doom-code voor hitscancontroles,Bruk Doom-kode for treffkontroll,Użyj kod Dooma dla hitscanu,Usam código de Doom para verificação de hitscan,Usar código de Doom para verificação de hitscan,Utilizează cod din Doom pentru a verifica coliziunea focurilor,Использовать код из Doom для проверок зон мгновенного попадания (hitscan),Користи Doom код за хитскен проверу,Hitscan kontrolleri için Doom kodunu kullanın -Use Doom heights for missile clipping,CMPTMNU_MISSILECLIP,,,,Použít původní výšky z Doomu pro kolizi raket,Brug Doom-højder til missilklipper,Benutze Doom-Größen für Kollisionen mit Projektilen,,Uzi altojn de Doom por misilo-tonadoj,Usar altura de Doom para desplazamiento de misiles,,Käytä Doomin korkeuksia lentokappaleiden törmäyksissä,Clipping des missiles à la DOOM,Doom féle magasság használata a rakáta találathoz,Usa le altezze di DOOM per il clipping del razzo,DOOM型ミサイルクリッピングの高さを使用,구형 발사체 판정법 사용,Gebruik Doom hoogtes voor het knippen van raketten,Bruk Doom-høyder for missilklipping,Użyj wysokości Dooma dla przenikania pocisków,Usar alturas de Doom para colisão de projéteis,,Utilizează metoda de verificare a înălțimilor din Doom,Использовать высоту из Doom для столкновения ракет,Користи Doom висине за клиповање ракета,Füze kırpma için Doom yüksekliklerini kullanın -Rendering Behavior,CMPTMNU_RENDERINGBEHAVIOR,,,Rendering Behaviour,Vykreslování,Rendering Adfærd,Renderverhalten,,Bildigado-Konduto,Comportamiento de renderizado,,Hahmonnuksen käyttäytyminen,Comportement d'affichage,Renderelés viselkedése,Comportamento della grafica,レンダリングの挙動,렌더링 관련 설정,Rendering gedrag,Gjengivelse av oppførsel,Zachowanie Renderowania,Comportamento de Renderização,,Comportament Video,Поведение отрисовки,Понашање рендовања,Rendering Davranışı -Draw polyobjects like Hexen,CMPTMNU_POLYOBJ,,,,Vykreslovat polyobjekty jako Hexen,Tegn polyobjekter som Hexen,Zeichne Polyobjekte wie in Hexen,,Desegni plurangulo-objektojn kiel Hexen,Dibujar poliobjetos como en Hexen,,Piirrä polyobjektit niin kuin Hexen,Dessiner les Polyobjets comme Hexen,Hexen féle tárgy kirajzolás,Polioggetti disegnati come Hexen,Hexen式のポリオブジェクト描画,구형 폴리오브젝트 시스템 사용,Teken polyobjecten zoals Hexen,Tegn polyobjekter som Hexen,Rysuj poliobiekty jak w Hexenie,Desenhar poliobjetos como em Hexen,,Afișează poliobiectele precum în Hexen,Отрисовка полиобъектов как в Hexen,Цртај поли-објекте као Hexen,Hexen gibi çoklu nesneler çizin -Ignore Y offsets on masked midtextures,CMPTMNU_MASKEDMIDTEX,,,,Ignorovat Y posuny na průhledných mid-texturách,Ignorer Y offsets på maskerede midtextures,Ignoriere Y-Offsets bei transparenten Mitteltexturen,,Malatenti Y-deŝovaĵojn sur maskitaj midtekstaĵoj,Ignorar offsets de eje Y en texturas medias enmascaradas,,Älä huomioi Y-siirroksia peitetyissä keskipintakuvioinneissa,Offsets Y ignorés sur les textures centrales,Függőleges mozgatás ignorálása a maszkolt midtextúráknál,Ignora gli offset Y sulle midtexture mascherate,中間テクスチャーのマスクされたYオフセットを無効,이면선분의 중앙 텍스쳐의 Y축값 무시,Negeer Y compensaties op gemaskerde middentexturen,Ignorer Y-forskyvninger på maskerte mellomteksturer,Ignoruj przesunięcia osi Y na zamaskowanych teksturach po środku,Ignorar offsets de Y em texturas centrais,,Ignoră offsetul Y de pe texturile 3D mascate,Игнорировать смещение по вертикали на средних текстурах с маской,Игнориши Y нагиб на маскиране средње текстуре,Maskelenmiş orta dokularda Y ofsetlerini yoksay -Invert sprite sorting,CMPTMNU_SPRITESORT,,,,Obrátit řazení spritů,Inverter sprite-sortering,Umgekehrte Spritesortierung,,Inversigi ordigadon de spritoj,Invertir ordenado de sprites,,Käännä spritelajittelu,Ordres des sprites inversé,Sprite rendzés megfordítása,Ordinamento sprite invertito,反転スプライトの並び替え,구형 스프라이트 겹침 판정 사용,Sprite sorteren omkeren,Inverter sprite-sortering,Odwróć sortowanie sprite'ów,Inverter ordem de sprites,,Inversare sortare sprite-uri,Обратить порядок сортировки спрайтов,Обрнуто сортирање спрајтова,Sprite sıralamasını ters çevir -Sound Behavior,CMPTMNU_SOUNDBEHAVIOR,,,Sound Behaviour,Zvuk,Adfærd med lyd,Sound-Verhalten,,Sonkonduto,Comportamiento de sonido,,Äänen käyttäytyminen,Comportement Sonore,Hang viselkedés,Comportamento suono,音の挙動,효과음 관련 설정,Geluidsgedrag,Lydoppførsel,Zachowanie dźwięku,Comportamento de Áudio,,Comportament Sunet,Поведение звуков,Понашање звука,Ses Davranışı -Cripple sound for silent BFG trick,CMPTMNU_SOUNDSLOTS,,,,Zmrzačit zvukový systém pro trik tichého BFG,Lyd forkrøblet ved lydløst BFG-trick,Amputiere Soundsystem für geräuschloses BFG,,Kripligi sonon por lertaĵo de silenta BFG,Estropear sonido para truco de BFG silencioso,,Rampauta äänijärjestelmä hiljaista BFG-temppua varten,Massacrer le son pour BFG silencieux,Bénító hang a halk BFG trükknél,Blocca il suono per il trucco del BFG silenzioso,消音BFGトリックの為にサウンドを重複させない,소음 BFG 효과 허용,Kreupel geluid voor een stille BFG-truc,Krymp lyd for stille BFG-triks,Obetnij dźwięk dla triku cichego BFG,Bloquear som para o truque da BFG silenciosa,,Taie sunetul pentru trucul BFG silențios,Ограничить звуки ради трюка бесшумной BFG,Онемогући звук за тихи ВЈП трик,Sessiz BFG numarası için sesi kısın -Don't let others hear your pickups,CMPTMNU_SILENTPICKUP,,,,Ostatní tě neslyší sbírat předměty,Lad ikke andre høre dine pickupper,Andere können deine Gegenstandsaufnahmen nicht hören,,Ne lasi aliulojn aŭdas viajn prenadojn,No dejar a otros oír tus recogidas,,"Älä anna muiden kuulla, kun poimit esineitä",Autres joueurs n'entendent pas les ramassages,Mások ne hallhassák a tárgy felvételeidet,Non consentire agli altri giocatori di sentire le tue raccolte,他人にピックアップ音を聞かせない,상대방의 습득 효과음 청음 불가,Laat anderen uw pick-ups niet horen,Ikke la andre høre pickupene dine,"Nie pozwalaj by inni słyszeli, że podnosisz przedmioty",Não permitir que outros ouçam sua coleta de itens,Não permitir que outros ouçam sua aquisição de itens,Nu permite celorlalți să audă sunetul ridicării obiectelor,Запрещать другим слышать звук подбора предметов,Не допусти да други чују ваше скупљање,Başkalarının manyetiklerinizi duymasına izin vermeyin -Inst. moving floors are not silent,CMPTMNU_SILENTINSTANTFLOORS,,,,Okamžitě pohybující se podlahy nejsou tiché,Inst. bevægelige gulve er ikke lydløse,Böden mit sofortiger Bewegung machen Geräusche,,Tujaj movantaj plankoj ne estas silentaj,Suelos inst. movibles no son silenciosos,,Silmänräpäyksellisesti liikkuvat lattiat eivät ole hiljaisia,Sols à movement instanté font du bruit,Halk isntant mozgó padló,I pavimenti istantanei in movimento non sono silenziosi,即時稼働する床の音を鳴らさない,즉발식 이동표면 소음효과 제거,Direct bewegende vloeren zijn niet geruisloos,Øyeblikkelig bevegelige gulv er ikke stille,Nagle przesuwające się podłogi nie są ciche,Pisos que se deslocam instantâneamente emitem som,,Podelele care se mișcă instant nu sunt silențioase,Мгновенно двигающиеся полы не беззвучны,Инстантно покрећући нивои нису тихи,Inst. hareketli zeminler sessiz değildir -Sector sounds use center as source,CMPTMNU_SECTORSOUNDS,,,Sector sounds use centre as source,Sektorové zvuky používají jeho střed jako zdroj,Sektorlyde bruger centrum som kilde,Sektor-Sounds benutzen den Mittelpunkt des Sektors,,Sektorsonoj uzas centron kiel fonto,Sonidos de sector usan el centro como fuente,,Sektoriäänet käyttävät keskipistettä lähteenä,Sons secteur utilisent centre comme origine,Center forrás használata a szektor hangoknál,I suoni usano il centro dei settori come punto di sorgente,セクターサウンドをフロア中央で鳴らす,섹터 중심부를 효과음의 원천으로 판정,Sectorgeluiden gebruiken centrum als bron,Sektorlyder bruker senter som kilde,Dźwięki sektorów używają środka jako źródła,Sons de setor são emitidos a partir do centro,,Sunetele sectoarelor au ca sursă centrul,Звуки секторов используют центр как источник,Секторски звукови су центрисани,Sektör sesleri kaynak olarak merkezi kullanır -Sounds stop when actor vanishes,CMPTMNU_SOUNDCUTOFF,,,,"Utnout zvuky, když jejich objekt zmizí","Lydene stopper, når aktøren forsvinder","Sounds werden beendet, wenn der Akteur verschwindet",,"Sonoj ĉesas, kiam aktoro malaperas",El sonido se detiene cuando el actor desaparece,,"Äänet lakkaavat, kun olio katoaa",Sons s'arrêtent quand acteur disparait,Hangok megszűnnek az eltűnéskor,I suoni si fermano quando gli attori svaniscono,アクター消滅で音を止める,효과음 원천 소멸 시 효과음도 중단,Geluiden stoppen wanneer de acteur verdwijnt,Lyder stopper når skuespilleren forsvinner,Dźwięki zatrzymują się kiedy aktor znika,Som para quando o ator desaparece,,Sunetele se opresc când actorul sursă dispare,Останавливать звуки при исчезновении объекта,Звукови престају кад глумац нестане,Aktör ortadan kaybolduğunda sesler kesilir -Use original sound target handling,CMPTMNU_SOUNDTARGET,,,,Použít původní chování pro uchování zvukového cíle,Brug original lydmålhåndtering,Benutze originale Behandlung für das Sound-Ziel,,Uzi originalan manipuladon por soncelo,Usar manejo de destino de sonido original,,Käytä alkuperäistä äänen kohteen käsittelyä,Ciblage des sons selon algorithme original,Eredeti hang célpont kezelés,Targeting dei suoni in base all'algoritmo originale,元のサウンドターゲット処理を使用,구형 섹터 경고음 보존법 사용,Gebruik originele geluidsdoelwitverwerking,Bruk original lydmålhåndtering,Użyj oryginalną obsługę celu dźwięku,Usar método original de destino de som,,Procesare originală pentru sursele de sunet,Неизменённая обработка источников звука,Користи оригинални звук руковања метом,Orijinal ses hedefi kullanımını kullanın -Scripted teleports don't trigger sector actions,CMPTMNU_TELEPORT,,,,Skriptované teleportace neaktivují sektorové akce,Scriptede teleporteringer udløser ikke sektorhandlinger,Teleports in Skripten lösen keine Sektoraktionen aus,,Skriptitaj teleportoj ne ekagigas sektor-agojn,Telepuertos por script no activan acciones del sector,,Käsikirjoitetut kaukosiirtimet eivät laukaise sektoritoimintoja,Téléports par scripts n'activent pas le secteur,Szkriptelt teleportok nem triggerelnek szektor műveletet,I teletrasporti scriptati non attivano le azioni del settore,スクリプトテレポートではセクターアクションを起こさない,순간이동 스크립트는 섹터 이벤트 발동 불가능,De gescripte teleports leiden niet tot acties in de sector.,Skriptede teleporter utløser ikke sektorhandlinger,Oskryptowane teleporty nie włączają akcji sektora,Teletransportes scriptados não ativam ações de setor,,Teleportările scriptate nu declanșează acțiuni în sectoare,Скриптовые телепорты не запускают действия секторов,Скриптовани телепортери не активирају секторске радње,Komut dosyası ışınlanmaları sektör eylemlerini tetiklemiyor -Non-blocking lines can be pushed,CMPTMNU_PUSHWINDOW,,,,Neblokující čáry mohou být zmáčknuty,Ikke-blokerende linjer kan skubbes,Nicht-blockende Linien können angestoßen werden,,Nehaltantaj linioj povas esti premitaj,Líneas sin bloquear pueden ser presionadas,,Ei-tukkivia viivoja voi työntää,Lignes non-bloquantes sont non-poussables,Nem blokkoló vonalak megnyomhatóak,Le linee non bloccanti possono essere spinti,Non-bloking linesを押せる,비차단 선분 밀어내기 가능,Niet-blokkerende lijnen kunnen worden geduwd,Ikke-blokkerende linjer kan skyves,Nieblokujące ściany mogą być pchnięte,Linhas não-bloqueadoras podem ser pressionadas,,Liniile care nu blochează pot fi împinse înapoi,Неблокирующие линии можно задействовать перемещением сквозь,Неблокирабе линје могу бити гурнуте,Engelleyici olmayan hatlar itilebilir -Enable buggy CheckSwitchRange behavior,CMPTMNU_CHECKSWITCHRANGE,,,,Povolit nestabilní chování pro CheckSwitchRange,Aktiver den fejlbehæftede CheckSwitchRange-adfærd,Erlaube fehlerhaftes CheckSwitchRange Verhalten,,Ebligi cimajn kondutojn por CheckSwitchRange,Permitir comportamiento viejo de CheckSwitchRange,,Ota käyttöön viallinen CheckSwitchRange-käyttäytyminen,Fonction CheckSwitchRange buggée,Bugos CheckSwitchRange mechanika bekapcsolás,Abilita il comportamento buggato del CheckSwitchRange,バグのあるCheckSwitchRangeを許可,구형 CheckSwitchRange 판정법 사용,Buggy CheckSwitchSwitchRange gedrag inschakelen,Aktiver fejlbehæftet CheckSwitchRange-adfærd,Zezwól na zepsute zachowanie CheckSwitchRange,Permitir comportamento CheckSwitchRange defeituoso,,Comportament incorect pentru CheckSwitchRange,Включить ошибочное поведение CheckSwitchRange,Омогући баговано CheckSwitchRange понашање,Hatalı CheckSwitchRange davranışını etkinleştirin -Enable buggy Strife railing,CMPTMNU_RAILINGHACK,,,,Povolit nestabilní zábradlí ze Strifu,Aktiver buggy Strife railing,Fehlerhafte Strife-Geländer,Ενεργοποιηση σπασμένης συμπεριφοράς καγκέλον για το Strife,Ebligi ciman reladon de Strife,Activar barandillas bugueadas de Strife,,Ota käyttöön Strifen vialliset kaiteet,Barrières buggées pour Strife,Bugos Strife korlát bekapcsolása,Abilita il railing buggato di Strife,バグのあるStrife railingを許可,고전 스트라이프 철책 적용,Buggy mogelijk maken Strijk-reling,Aktiver fejlbehæftet Strife rekkverk,Włącz wadliwe bariery Strife'a,Permitir railing defeituoso do Strife,Permitir railing defeituoso do Strife,Utilizare comportament grilaj Strife incorect,Вернуть ошибочные перила в Strife,Омогући непоправљену ограду у Strife-у,Yanlış Strife korkuluğunu etkinleştirin -No vertical thrust from explosions,CMPTMNU_EXPLODE1,,,,Exploze neodhazují do výšky,Ingen vertikal fremdrift fra eksplosioner,Keine vertikale Bewegung durch Explosionen,Καθόλου κατακόρυφη ώθηση απο εκρήξεις,Neniuj vertikalaj puŝoj de eksplodoj,No causar empuje vertical en explosiones,,Ei pystysuuntaista työntövoimaa räjähdyksistä,Explosions sans propulsion verticale,A robbanásnak nincs függőleges lökése,Nessuna spinta verticale dalle esplosioni,爆風は垂直方向全域に影響しない,폭발시 수직방향 반동 억제,Geen verticale stuwkracht van explosies,Ingen vertikal skyvekraft fra eksplosjoner,Brak pionowego nacisku od eksplozji,Desativar propulsão vertical das explosões,,Fără împingere verticală de la explozii,Взрывы не отбрасывают вверх/вниз,Нема вертикалног гурања од експлозија,Patlamalardan kaynaklanan dikey itme yok -Use original Doom explosion behavior,CMPTMNU_EXPLODE2,,,Use original Doom explosion behaviour,Používat původní chování explozí Doomu,Brug original Doom eksplosionsadfærd,Benutze Original Doom Explosionsverhalten,Συμπεριφορά εκρήξεων απο το πρωτότυπο Doom,Uzi originalan konduton de Doom por eksplodoj ,Usar comportamiento de explosiones del DOOM original,,Käytä Doomin alkuperäisiä räjähdysten käyttäytymissääntöjä,Utiliser comportement Doom original,Eredeti Doom robbanás mechanika használata,Usa l'originale comportamento dell'esplosione di DOOM,Doom本来の爆発動作を使用する,고전 둠의 폭발 반발력 적용,Gebruik het originele Doom explosiegedrag,Bruk original Doom-eksplosjonsatferd,Użyj oryginalnego zachowania eksplozji z Dooma,Usar comportamento original de explosões do Doom,,Utilizare comportament original pentru explozii,Использовать модель взрывов из Doom,Користи оригнално Doom понашање за експлозије,Orijinal Doom patlama davranışını kullanın -,,player,,,,,,,,,,,,,,,,,,,,,,,, -Red,PLYRMNU_RED,,,,Červená,Rød,Rot,,Ruĝo,Rojo,,Punainen,Rouge,Piros,Rosso,赤の量,빨강,Rood,Rød,Czerwony,Vermelho,,Roșu,Красный,Црвева,Kırmızı -Green,PLYRMNU_GREEN,,,,Zelená,Grøn,Grün,,Verdo,Verde,,Vihreä,Vert,Zöld,Verde,緑の量,초록,Groen,Grønn,Zielony,Verde,,Verde,Зелёный,Зелена,Yeşil -Blue,PLYRMNU_BLUE,,,,Modrá,Blå,Blau,,Bluo,Azul,,Sininen,Bleu,Kék,Blu,青の量,파랑,Blauw,Blå,Niebieski,Azul,,Albastru,Синий,Плава,Mavi -Class,PLYRMNU_PLAYERCLASS,,,,Třída,Klasse,Klasse,,Klaso,Clase,,Luokka,Classe,Kaszt,Classe,役職,클래스,Klasse,Klasse,Klasa,Classe,,Clasă,Класс,Класа,Sınıf -Skin,PLYRMNU_PLAYERSKIN,,,,Skin,Skin,Skin,,Haŭto,Piel,,Ulkoasu,,Kinézet,Skin,外装,스킨,Uiterlijk,Hud,Wygląd,Skin,,Textură,Облик,Скин,Cilt -Switch on pickup,PLYRMNU_SWITCHONPICKUP,,,,Přepnout zbraň při sebrání,Tænd for pickup,Waffenwechsel bei Aufnahme,,Ŝanĝi armon ĉe preno,Cambiar arma al recoger,,Vaihda uuteen aseeseen,Dernière arme,Felvételkor váltás,Cambio d'arma quando si riceve,武器取得時に持ち替え,무기 획득 시 바꿈,Gebruik wapen meteen na oppakken,Slå på pickup,Przełącz po podniesieniu,Mudar de arma ao pegar,,Schimbare armă la ridicare,Смена оружия при подборе,Пребаци на покупљено оружје,Elinize aldığınızda silahı değiştirin -Press \cjSPACE,PLYRMNU_PRESSSPACE,,,,Zmáčkni \cjMEZERNÍK,Tryk på \cjSPACE,\cjLeertaste,,Premu \cjSPACON,Presiona \cjEspacio,,Paina \cjVÄLI \cfnähdäk-,\cjEspace,Nyomj \cjSPACE -t,Premi \cjSPAZIO,\cjスペースキー,회전: \cjSPACE바,Druk op \cjSPACE,Trykk \cjSPACE,\cjSPACJA,Aperte \cjESPAÇO,,Apasă \cjSPACE,Нажмите \cjПРОБЕЛ,Притисните \cjSPACE,\cjSPACE tuşuna basın -to see front,PLYRMNU_SEEFRONT,,,,pro pohled zepředu,for at se forsiden,für Frontansicht,,por vidi antaŭon,Para ver de Frente,,sesi etupuolen,Pour L'Avant,Előre nézni,per vedere avanti,で前面を表示,캐릭터 앞모습,om de voorkant te zien,for å se forsiden,by widzieć przód,para ver a frente,,pentru a vedea fața,для просмотра спереди,да видите спреда,ön tarafı görmek için -to see back,PLYRMNU_SEEBACK,,,,pro pohled zezadu,for at se bagsiden,für Rückansicht,,por vidi malantaŭon,Para ver por Detrás,,sesi takapuolen,Pour l'Arrière,Hátra Nézni,per vedere dietro,で背面を表示,캐릭터 뒷모습,om terug te kijken,for å se baksiden,by widzieć tył,para ver atrás,,pentru a vedea spatele,для просмотра сзади,да видите позади,geri görmek için -Vertical Bullet Spread,PLYRMNU_VERTSPREAD,,,,Svislý rozptyl střelby,Lodret kuglespredning,Vertikale Streuung,,Vertikala Kugla Disvastiĝo,Dispersión vertical de la bala,,Pystysuora luodin leviäminen,Écartement vertical des balles,Vertikális fegyver szórás,Diffusione dei proiettili in verticale,垂直方向の散弾,,Verticale kogelspreiding,Vertikal kulespredning,Pionowy rozrzut pocisków,Espalhamento Vertical das Balas,,Recul Vertical Gloanțe,Вертикальный разброс пуль,,Dikey Mermi Yayılımı -,,controls,,,,,,,,,,,,,,,,,,,,,,,, -Weapon Zoom,CNTRLMNU_ZOOM,,,,Přiblížení zbraně,Våbenzoom,Waffenzoom,Ζοομ,Armilzumo,Zoom del arma,,Aseen kiikaritähtäys,Zoom avec Arme,Ráközelítés fegyverrel,Zoom dell'arma,ズーム,무기 조준,Wapen Zoom,Våpen Zoom,Przybliżenie Broni,Zoom da Arma,,Zoom Armă,Приближение,Зум,Silah Yakınlaştırma -Weapon State 1,CNTRLMNU_USER1,,,,Akce zbraně 1,Våbenstatus 1,Waffen-Aktion 1,Κατάσταση Όπλου 1,Armilstato 1,Estado del arma 1,,Aseen tila 1,Etat d'Arme 1,Fegyver 1. állapot,Stato dell'arma 1,武器特殊動作 1,무기 상태 1,Wapenstaat 1,Våpenstat 1,Stan Broni 1,Estado da Arma 1,,Poziție Armă 1,Функция первого оружия,Стање оружја (1),Silah Durumu 1 -Weapon State 2,CNTRLMNU_USER2,,,,Akce zbraně 2,Våbenstatus 2,Waffen-Aktion 2,Κατάσταση Όπλου 2,Armilstato 2,Estado del arma 2,,Aseen tila 2,Etat d'Arme 2,Fegyver 2. állapot,Stato dell'arma 2,武器特殊動作 2,무기 상태 2,Wapenstaat 2,Våpenstat 2,Stan Broni 2,Estado da Arma 2,,Poziție Armă 2,Функция второго оружия,Стање оружја (2),Silah Durumu 2 -Weapon State 3,CNTRLMNU_USER3,,,,Akce zbraně 3,Våbenstatus 3,Waffen-Aktion 3,Κατάσταση Όπλου 3,Armilstato 3,Estado del arma 3,,Aseen tila 3,Etat d'Arme 3,Fegyver 3. állapot,Stato dell'arma 3,武器特殊動作 3,무기 상태 3,Wapenstaat 3,Våpenstat 3,Stan Broni 3,Estado da Arma 3,,Poziție Armă 3,Функция третьего оружия,Стање оружја (3),Silah Durumu 3 -Weapon State 4,CNTRLMNU_USER4,,,,Akce zbraně 4,Våbenstatus 4,Waffen-Aktion 4,Κατάσταση Όπλου 4,Armilstato 4,Estado del arma 4,,Aseen tila 4,Etat d'Arme 4,Fegyver 4. állapot,Stato dell'arma 4,武器特殊動作 4,무기 상태 4,Wapenstaat 4,Våpentilstand 4,Stan Broni 4,Estado da Arma 4,,Poziție Armă 4,Функция четвёртого оружия,Стање оружја (4),Silah Durumu 4 -Fly / Swim up,CNTRLMNU_MOVEUP,,,,Letět / plavat vzhůru,Flyv / svøm op,Fliegen / Hochschwimmen,Πέτα/Κολύμπα πάνω,Flugi / Naĝi supren,Volar / Nadar arriba,,Lennä / Ui ylös,Voler/Nager en haut,Repülés / Felfele úszás,Vola / Nuota in alto,飛行/水泳時 上昇,위로 날기 / 해엄치기,Omhoog vliegen/zwemmen omhoog,Fly / Svøm opp,Lot / Pływanie w górę,Voar / Nadar para cima,,Zbor / Înot în Sus,Лететь/плыть вверх,Лети/пливај нагоре,Uç / Yüz yukarı -Fly / Swim down,CNTRLMNU_MOVEDOWN,,,,Letět / plavat dolů,Flyv / svøm ned,Fliegen / Runterschwimmen,Πέτα/Κολύμπα κάτω,Flugi / Naĝi malsupren,Volar / Nadar abajo,,Lennä / Ui alas,Voler/Nager en bas,Repülés / Lefele úszás,Vola / Nuota in basso,飛行/水泳時 下降,아래로 날기 / 해엄치기,Naar beneden vliegen/zwemmen,Fly / Svøm ned,Lot / Pływanie w dół,Voar / Nadar para baixo,,Zbor / Înot în Jos,Лететь/плыть вниз,Лети/пливај надоле,Uç / Yüz aşağı -Stop flying,CNTRLMNU_LAND,,,,Přestat létat,Stop flyvning,Landen,Σταμάτα πέταμα,Ĉesi flugadon,Dejar de volar,,Lopeta lentäminen,Arrêter de voler,Repülés abbahagyása,Stop al volo,飛行停止,비행 정지,Stoppen met vliegen,Slutt å fly,Przestań latać,Parar de voar,,Încetare Zbor,Приземлиться,Престани летети,Uçmayı bırak -Keyboard look,CNTRLMNU_KEYBOARDLOOK,,,,Pohled klávesnicí,Tastatur-look,Tastatur-Blick,Κατακόρυφο κοίταχμα (Πλητρoλόγιο),Klavaroregardo,Vista con teclado,,Näppäinkatselu,Vue au clavier,Billentyűzettel való nézelődés,Modalità vista con la tastiera,キー視点上下化,키보드 룩,Toetsenbordaanzicht,Tastatur utseende,Rozglądanie się klawiaturą,Vista com o teclado,,Utilizare Tastatură pentru a Privi în Jur,Обзор клавиатурой,Гледај тастатуром,Klavye görünümü -Strife Popup Screens Controls,CNTRLMNU_POPUPS_TITLE,,,,Ovládání vyskakovacích oken ve Strife,Strife Popup-skærme Kontrolelementer,Strife Popup Steuerung einstellen,,Ŝprucfenestraj Regiloj de Strife,Popups de Strife,,Strifen ponnahdusruutujen ohjausasetukset,Contrôles Popups Strife,Strife Felugró Ablak Irányítás,Controlli Schermate popup di Strife,Strifeポップアップ表示設定,스트라이프 팝업 화면 조작,Strife Popup Schermen Bediening,Strife Popup-skjermer Kontroller,Ustaw Klawisze Okienek Strife'a,Comandos de Popups do Strife,Controlos de Popups do Strife,Control pentru Mesaje Strife,Управление всплывающими окнами Strife,Искакајући прикази контроле у Strife-у,Strife Açılır Ekran Kontrolleri -Team say,CNTRLMNU_TEAMSAY,,,,Říct týmu,Team sige,Teamkommunikation,Πές στην ομάδα,Teama diro,Hablar al equipo,,Sano omille,Parler (équipe),Üzenet csapattársaknak,Parla nella squadra,チーム内発言,팀 채팅하기,Zeggen in team,Lag si,Powiedz do Drużyny,Fala (equipe),Falar à equipa,Vorbește cu Echipa Proprie,Сообщение команде,Пиши тиму,Ekip diyor ki -Drop item,CNTRLMNU_DROPITEM,,,,Odhodit předmět,Smid genstand,Gegenstand fallen lassen,Πέτα Aντικείμενο,Faligi objekton,Arrojar objeto,,Pudota varuste,Lâcher objet,Tárgy eldobása,Fai cadere l'oggetto,"アイテムを捨てる -",아이템 버리기,Item laten vallen,Slipp element,Upuść przedmiot,Largar item,,Aruncare Obiect,Бросить предмет,Баци предмет,Eşyayı bırak -Query item,CNTRLMNU_QUERYITEM,,,,Informace o předmětu,Forespørgsel element,Informationen über Gegenstand,,Informpeti objekton,Consultar objeto,,Hae varustetta,Vérifier objet,Rákérdez a tárgy eldobásnál,Indaga sull'oggetto,アイテム名を表示,아이템 정보 표시,Vraag item op,Spør om element,Zapytaj o przedmiot,Consultar item,,Cercetare Obiect,Проверить предмет,Прикажи предмет,Sorgu öğesi -Drop weapon,CNTRLMNU_DROPWEAPON,,,,Odhodit zbraň,Smid våben,Waffe fallen lassen,Πέτα Όπλο,Faligi armilon,Arrojar arma,,Pudota ase,Lâcher arme,Fegyver eldobása,Butta l'arma,武器を捨てる,무기 버리기,Wapen laten vallen,Slipp våpen,Upuść broń,Largar arma,,Aruncare Armă,Выбросить оружие,Баци оружје,Silahı bırak -Other,CNTRLMNU_OTHER,,,,Ostatní,Andre,Andere,Άλλα,Alia,Otros,,Muu,Autres,Más,Altro,その他,그 외 조작,Andere,Annet,Inne,Outro,,Altele,Прочее,Остало,Diğer -Coop spy,CNTRLMNU_COOPSPY,,,,Co-op špehování,Coop-spion,Coop Spion,,Kunlabora spiono,Espía cooperativo,,Vakoile joukkuetovereita,Espionner Coéquiper,Coop leskelődés,Spia cooperativa,他者視点,멀티플레이 카메라,Coöpspion,Coop-spion,Śledź (kooperacja),Visualização coop,,Vedere prin Ochii Altui Jucător,Вид от другого игрока,Поглед од другог играча,Coop casusu -Strife Popup Screens,CNTRLMNU_POPUPS,,,,Vyskakovací okna Strife,Strife popup-skærme,Strife Popups,,Ekmontraĵaj Ekranoj de Strife,Pop-ups de Strife,,Strifen ponnahdusruudut,Popups de Strife,Strife Felugró Ablakok,Schermate popup di Strife,Strife ポップアップ画面,스트라이프 팝업 화면,Strife Popup Schermen,Strife Popup-skjermer,Okienka Strife'a,Popup do Strife,,Mesaje Strife,Всплывающие окна Strife,Информација у Strife-у,Strife Açılır Ekranları -Mission objectives,CNTRLMNU_MISSION,,,,Úkoly mise,Mål for en mission,Missionsziele,Στόχοι Αποστολής,Misiobjektivoj,Objetivos de misión,,Tehtävätavoitteet,Objectifs de Mission,Küldetési célok,Obiettivi della missione,ミッションオブジェクト,임무 목록,Missiedoelen,Oppdragets mål,Cele misji,Objetivos da missão,,Obiectivele Misiunii,Текущее задание,Циљ мисије,Görev hedefleri -Keys list,CNTRLMNU_KEYS,,,,Seznam klíčů,Liste over nøgler,Schlüsselliste,Λίστα Κλειδιών,Ŝlosilolisto,Lista de llaves,,Avainlista,Liste des Clés,Kulcslista,Lista delle chiavi,キー類リスト,열쇠 목록,Lijst van toetsen,Liste over nøkler,Lista kluczy,Lista de teclas,,Listă Chei,Список ключей,Списка кључева,Anahtar listesi -Weapons/ammo/stats,CNTRLMNU_STATS,,,,Zbraně/munice/staty,Våben/ammo/stats,Waffen/Munition/Statistik,Οπλα/Πυρομαχικά/Στατιστικές,Armiloj/municio/stataĵoj,Armas/Munición/Estadísticas,,Aseet/ammukset/tila,"Statistiques, armes et munitions",Fegyver/lőszer/statisztika,Armi/ammunizioni/statistiche,武器 / 弾薬 / 状態,무기/탄약/통계 목록,Wapens/ammo/statistieken,Våpen/ammunisjon/statistikk,Bronie/amunicja/statystyki,Armas/munição/estatísticas,,Arme/muniție/statistici,"Оружие, патроны и показатели",Оружје/муниција/статистика,Silahlar/mühimmat/istatistikler -Toggle Scoreboard,CNTRLMNU_TOGGLESCOREBOARD,,,,Přepnout tabulku skóre,Skift Scoreboard,Punktetafel an/aus,Ενεργοποίηση Πίνακα Σκόρ,Baskuligi poentotabulon,Alternar Marcador,,Pistetaulun vaihtokytkin,Afficher Scores (alterner),Eredményjelző kapcsoló,Abilita/disabilita tabella punteggio,スコアボード切替,점수창 토글,Scorebord aan/uit,Veksle resultattavle,Włącz / Wyłącz tablicę wyników,Ativar/desativar placar,Ligar/desligar Pontuação no Ecrã,Comutator pentru Tabela de Marcaj,Таблица очков (перекл.),Табела (без држања),Skor Tablosunu Değiştir -Lookspring,MOUSEMNU_LOOKSPRING,,,,Automatické vystředění pohledu,,Automatisch zentrieren,,Rigardsalto,Mirar con ratón,,Katseenpalautin,Recentrer après Vue Souris,,,視点水平化,마우스룩 시점 초기화,Automatisch centraliseren,,Automatyczne Wyśrodkowanie,Centralizar automaticamente,Centrar automáticamente,Mișcare a jucătorului prin mouse,Передвижение мышью,Покрет мишем,Lookspring -Lookstrafe,MOUSEMNU_LOOKSTRAFE,,,,Použít myš k pohybu do stran,,Seitwärts bewegen mit der Maus,,Rigardturnmovo,Mirar con movimiento,,Sivuttaisastuntapalautin,Mouvement Latéral par Souris,,,視点横移動化,마우스룩 좌우 이동,Zijwaartse muisbeweging,,Unikanie przy użyciu myszki,Deslocamento lateral com o mouse,Deslocamento lateral com o rato,Mișcare în diagonală cu mouse,Движение боком мышью,Стрејф мишем,Lookstrafe -,,Map colors,,,,,,,,,,,,,,,,,,,,,,,, -Background,MAPCOLORMNU_BACKCOLOR,,,,Pozadí,Baggrund,Hintergrund,,Fono,Fondo,,Tausta,Fond,Háttér,Sfondo,背景,배경,Achtergrond,Bakgrunn,Tło,Fundo,,Fundal,Фон,Позадина,Arka plan -You,MAPCOLORMNU_YOURCOLOR,,,,Ty,Du,Du,,Vi,Tú,,Sinä,Votre couleur,Te,Tu,自分,당신,,Du,Ty,Você,Tu,Tu,Вы,Ти,Sen -1-sided walls,MAPCOLORMNU_WALLCOLOR,,,,Jednostranné zdi,1-sidede vægge,Einseitige Wände,,1-flankaj muroj,Paredes de 1 lado,,Yksipuoliset seinät,Murs à 1 côté,1 oldalú falak,Muri unilaterali,壁,단면 벽들,1-zijdige wanden,1-sidige vegger,Jednostronne ściany,Paredes de 1 lado,,Pereți cu o singură față,Односторонние стены,Једнострани зид,1 taraflı duvarlar -2-sided walls with different floors,MAPCOLORMNU_FDWALLCOLOR,,,,Oboustranné zdi s různými podlahami,2-sidede vægge med forskellige gulve,Zweiseitige Wände mit unterschiedlicher Bodenhöhe,,2-flankaj muroj kun malsamaj plankoj,Paredes de 2 lados con pisos distintos,,Kaksipuoliset seinät eroavilla lattiakorkeuksilla,Murs à 2 côtés avec différents sols,2 oldalú falak különböző padlókkal,Muri bilaterali con pavimenti diversi,高低差のある床,다른 층 추가된 양면 벽들,2-zijdige wanden met verschillende vloeren,2-sidige vegger med forskjellige gulv,Dwustronne ściany z innymi piętrami,Paredes de 2 lados com pisos diferentes,,Pereți cu două fețe si podele diferite,Двусторонние стены,Двострани зид са различитим нивоима,Farklı zeminlere sahip 2 taraflı duvarlar -2-sided walls with different ceilings,MAPCOLORMNU_CDWALLCOLOR,,,,Oboustranné zdi s různými stropy,2-sidede vægge med forskellige lofter,Zweiseitige Wände mit unterschiedlicher Deckenhöhe,,2-flankaj muroj kun malsamaj plafonoj,Paredes de 2 lados con techos distintos,,Kaksipuoliset seinät eroavilla kattokorkeuksilla,Murs à 2 côtés avec différents plafonds,2 oldalú falak különböző plafonnal,Muri bilaterali con soffitti diversi,高低差のある天井,다른 천장 추가된 양면 벽들,2-zijdige wanden met verschillende plafonds,2-sidige vegger med forskjellige tak,Dwustronne ściany z innymi sufitami,Paredes de 2 lados com tetos diferentes,,Pereți cu două fețe si tavane diferite,Двусторонние стены с разными потолками,Двострани зид са различитим плафонима,Farklı tavanlara sahip 2 taraflı duvarlar -2-sided walls with 3D floors,MAPCOLORMNU_EFWALLCOLOR,,,,Oboustranné zdi s 3D podlahami,2-sidede vægge med 3D-gulve,Zweiseitige Wände mit 3D-Ebenen,,2-flankaj muroj kun 3D-plankoj,Paredes de 2 lados con suelos 3D,,Kaksipuoliset seinät kolmiulotteisilla lattioilla,Murs à 2 côtés avec sols 3d,2 oldalú falak 3D-s padlókkal,Muri bilaterali con 3D floor,多重床,3D 층 추가된 양면 벽들,2-zijdige wanden met 3D-vloeren,2-sidige vegger med 3D-gulv,Dwustronne ściany z piętrami 3D,Paredes de 2 lados com pisos 3D,,Pereți cu două fețe si podele 3D,Двусторонние стены с разными полами,Двострани зид са 3D нивоима,3D zeminli 2 taraflı duvarlar -Map grid,MAPCOLORMNU_GRIDCOLOR,,,,Mřížka,Kortgitter,Kartengitter,,Mapkrado,Cuadrícula del mapa,,Kartan ruudukko,Quadrillage,Pálya szél,Griglia mappa,マップグリッド,맵 격자,Kaart raster,Kartrutenett,Siatka mapy,Grade do mapa,Grelha do mapa,Grilă hartă,Цвет сетки,Мапа координатне мреже,Harita ızgarası -Center point,MAPCOLORMNU_XHAIRCOLOR,,,Centre point,Středobod,Midterpunkt,Mittelpunkt,,Centra punkto,Punto central,,Keskipiste,Point Central,Pálya közepe,Punto centrale,中心点,중간 지점,Middenpunt,Midtpunkt,Środek,Ponto central,,Punct în centru,Курсор,Централна тачка,Merkez noktası -Not-yet-seen walls,MAPCOLORMNU_NOTSEENCOLOR,,,,Neobjevené zdi,"Vægge, der endnu ikke er synlige",Ungesehene Wände,,Vidotaj muroj,Paredes sin ver,,Tutkimattomat seinät,Murs non découvers,Még nem látott falak,Muri ancora da scoprire,未見の壁,안 본 벽들,Nog niet zichtbare wanden,Vegger som ennå ikke er sett,Jeszcze niewidziane ściany,Paredes não vistas até o momento,,Ziduri încă neobservate,Необнаруженные стены,Неоткривени зидови,Henüz görülmemiş duvarlar -Locked doors,MAPCOLORMNU_LOCKEDCOLOR,,,,Zamčené dveře,Låste døre,Verschlossene Türen,,Ŝlositaj pordoj,Puertas bloqueadas,,Lukitut ovet,Portes verouillées,Zárt ajtók,Porte bloccate,鍵の掛かったドア,잠긴 문들,Gesloten deuren,Låste dører,Zablokowane drzwi,Portas trancadas,,Uși închise,Запертые двери,Закључана врата,Kilitli kapılar -Teleporter to the same map,MAPCOLORMNU_INTRALEVELCOLOR,,,,Teleportér,Teleporter til samme kort,Teleporter,,Teleportilo al la sama mapo,Teletransporte al mismo mapa,,Kaukosiirrin samaan tasoon,Téléporteurs (même niveau),Ugyanarra a pályára teleportálás,Teletrasporto nella stessa mappa,テレポーター,같은 맵에 텔레포터 추가,Teleporter naar dezelfde niveau,Teleporter til samme kart,Teleporter do tej samej mapy,Teletransportador para o mesmo mapa,,Teleportor către aceeași hartă,Телепорт в пределах уровня,Телепортер до истог нивоа,Aynı haritaya ışınlayıcı -Teleporter to a different map,MAPCOLORMNU_INTERLEVELCOLOR,,,,Teleportér do jiného levelu,Teleporter til et andet kort,Teleporter in ein anderes Level,,Teleportilo al alia mapo,Teletransporte a un mapa diferente,,Kaukosiirrin eri tasoon,Téléporteurs (autre niveau),Másik pályára teleportálás,Teletrasporto in una mappa diversa,別マップへのテレポーター,다른 맵에 텔레포터 추가,Teleporter naar een andere niveau,Teleporter til et annet kart,Teleporter do innej mapy,Teletransportador para outro mapa,,Teleportor către altă hartă,Телепорт на другой уровень,Телепортер до различитог нивоа,Farklı bir haritaya ışınlayıcı -Secret sector,MAPCOLORMNU_SECRETSECTORCOLOR,,,,Skrýš,Hemmelig sektor,Geheimer Sektor,,Sekreta sektoro,Sector secreto,,Salasektori,Secteur Secret,Rejtekhely szektora,Settore segreto,シークレット,비밀 섹터,Geheime sector,Hemmelig sektor,Sekretny sektor,Setor secreto,,Sector secret,Тайный сектор,Тајни сектор,Gizli sektör -Unexplored secret,MAPCOLORMNU_UNEXPLOREDSECRETCOLOR,,,,Neobjevená skrýš,Uudforsket hemmelighed,nicht gefundener geheimer Sektor,,Neesplorita sekreto,Secreto sin explorar,,Tutkimaton sala,Secret non révélé,Még fel nem fedezett rejtekhely,Segreto non esplorato,未知のシークレット,발견하지 않은 비밀,Onontgonnen geheim,Uutforsket hemmelighet,Niezbadany sekret,Segredo não-explorado,,Secret neexplorat,Необнаруженный тайник,Ноткривена тајна,Keşfedilmemiş sır -Special trigger lines,MAPCOLORMNU_SPECIALWALLCOLOR,,,,Akční čáry,Særlige udløserlinjer,Spezielle Linien,,Specialaj ekagilo-linioj,Líneas especiales de activación,,Erikoislaukaisinviivat,Lignes d'actions spéciales,Speciális trigger vonalak,Linee di attivazione speciali,特殊トリガー,특수 트리거 선,Speciale trekkerlijnen,Spesielle utløserlinjer,Specjalne linie przełączników,Linhas de ativação especiais,,Linii declașatoare speciale,Специальные спусковые линии,Специјалне линије окидача,Özel tetik hatları -Cheat Mode,MAPCOLORMNU_CHEATMODE,,,,Cheatovací režim,Snyd-tilstand,Cheat-Modus,,Tromp-Reĝimo,Modo de truco,,Huijaustila,Mode Cheat,Csalás mód,Modalità cheat,チートモード時,치트 모드,Bedriegingsmodus,Juksemodus,Tryb oszustwa,Modo trapaça,Modo de Batota,Modul Trișor,Чит-режим,Чит мод,Hile Modu -Invisible 2-sided walls,MAPCOLORMNU_TSWALLCOLOR,,,,Neviditelné oboustranné zdi,Usynlige 2-sidede vægge,Unsichtbare zweiseitige Wände,,Nevideblaj 2-flankaj muroj,Paredes de 2 lados Invisibles,,Näkymättömät kaksipuoliset seinät,Murs à 2 côtés invisibles,Láthatatlan 2 oldalú falak,Muri invisibili bilaterali,表示されないline,투명한 양면 벽,Onzichtbare 2-zijdige wanden,Usynlige 2-sidige vegger,Niewidzialne dwustronne ściany,Paredes invisíveis de 2 lados,,Pereți cu două fețe invizibili,Невидимые двусторонние стены,Невидљиви двострани зидови,Görünmez 2 taraflı duvarlar -Secret walls,MAPCOLORMNU_SECRETWALLCOLOR,,,,Tajné zdi,Hemmelige vægge,Geheime Wände,,Sekretaj muroj,Paredes secretas,,Salaiset seinät,Murs Secrets,Titkos falak,Muri segreti,シークレットの壁,비밀 벽,Geheime muren,Hemmelige vegger,Sekretne ściany,Paredes secretas,,Pereți ascunși,Тайные стены,Тајни зидови,Gizli duvarlar -Actors,MAPCOLORMNU_THINGCOLOR,,,,Objekty,Skuespillere,Akteure,,Aktoroj,Actores,,Oliot,Acteurs,Játékos,Attori,アクター,개체,Acteurs,Skuespillere,Aktorzy,Atores,,Actori,Объекты,Актори,Aktörler -Monsters,MAPCOLORMNU_MONSTERCOLOR,,,,Příšery,Monstre,Monster,,Monstroj,Monstruos,,Hirviöt,Monstres,Szörnyek,Mostri,モンスター,적들,Monsters,Monstre,Potwory,Monstros,,Monștri,Монстры,Чудовишта,Canavarlar -Non-counting Monsters,MAPCOLORMNU_NONCOUNTINGMONSTERCOLOR,,,,Nepočítané příšery,Ikke-tællende monstre,nicht gezählte Monster,,Nenombradaj Monstroj,Monstruos no contados,Monstruos sin contar,Ei-laskettavat hirviöt,Monstres non comptés,Nem számolt szörnyek,Mostri non contati,非カウントモンスター,킬수에 포함 되지 않는 적들,Niet-tellende Monsters,Ikke-tellende monstre,Niezliczane Potwory,Monstros não contados,,Monștri neacoperiți de numărătoare,Неучитываемые монстры,Не рачунајући чудовишта,Sayılamayan Canavarlar -Friends,MAPCOLORMNU_FRIENDCOLOR,,,,Přátelé,Venner,Freunde,,Amikoj,Amigos,,Omat,Amis,Barátok,Amici,仲間,친구들,Vrienden,Venner,Przyjaciele,Amigos,,Prieteni,Дружественные,Пријатељи,Arkadaşlar -Items,MAPCOLORMNU_ITEMCOLOR,,,,Předměty,Genstande,Gegenstände,,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,아이템들,Artikelen,Gjenstander,Przedmioty,Itens,,Obiecte,Предметы,Предмети,Eşyalar -Count Items,MAPCOLORMNU_COUNTITEMCOLOR,,,,Počítané předměty,Tælle genstande,gezählte Gegenstände,,Nombri Objektojn,Objetos contados,Conteo de objetos,Laske esineet,Objets comptés,Tárgyak számolása,Oggetti contati,カウント対象アイテム,아이템 계산,Tellen,Telle elementer,Zlicz przedmioty,Itens contados,,Numără obiectele,Учитываемые предметы,Рачунајући предмети,Sayım Öğeleri -Overlay Mode,MAPCOLORMNU_OVERLAY,,,,Překryvný režim,Overlay-tilstand,Überlagerungsmodus,,Surmeto-Reĝimo,Modo sobrepuesto,,Projisointitila,Mode surimpression,Overlay mód,Modalità sovrapposizione,オーバーレイモード,오버레이 모드,Overlaadmodus,Overleggsmodus,Tryb Nakładki,Modo de sobreposição,,Mod acoperit,Прозрачный режим,Провидна аутомапа,Kaplama Modu -Overlay Cheat Mode,MAPCOLORMNU_OVCHEATMODE,,,,Překryvný cheatovací režim,Overlay snydetilstand,Überlagerungsmodus Cheats,,Surmeto-Tromp-Reĝimo,Sobreposición modo de truco,,Projisointihuijaustila,Mode Cheat Surimpression,overlay csaló mód,Modalità cheat sovrapposizione,オーバーレイ チートモード,치트 모드 오버레이,Overlaadmodus Cheats,Overlegg-juksemodus,Tryb Nakładki Oszustwa,Modo trapaça de sobreposição,Modo Batota de Sobreposição,Mod acoperit trișor,Прозрачный чит-режим,Провидни читови,Kaplama Hile Modu -Portal Overlays,MAPCOLORMNU_PORTAL,,,,Portálové překryvy,Portal-overlejringer,Portalüberlagerung,,Portalo-Surmetoj,Sobreposición de portal,,Portaaliprojisoinnit,Portails superposés,Portál overlay-ek,Sovrapposizioni del portale,ポータル オーバーレイ,포탈 오버레이,Portaaloverlays,Portal-overlegg,Nakładanie się Portali,Sobreposição de portais,,Acoperiri portaluri,Порталы в прозрачном режиме,Провидни портали,Portal Kaplamaları -,,Messages,,,,,,,,,,,,,,,,,,,,,,,, -Messages,MSGMNU_TITLE,,,,Nastavení oznámení,Meddelelser,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,,Üzenetek,Messaggi,メッセージ類,메시지들,Berichten,Meldinger,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке,Mesajlar -Show messages,MSGMNU_SHOWMESSAGES,,,,Zobrazit oznámení,Vis meddelelser,Zeige Nachrichten,,Montri mesaĝojn,Mostrar Mensajes,,Näytä viestit,Afficher messages,Üzenetek mutatása,Mostra messaggi,メッセージ表示,메시지 표시,Berichten tonen,Vis meldinger,Pokaż wiadomości,Exibir mensagens,,Afișare mesaje,Отображение сообщений,Прикажи поруке,Mesajları göster -Show obituaries,MSGMNU_SHOWOBITUARIES,,,,Zobrazit oznámení o smrtích,Vis dødsannoncer,Zeige Todesanzeigen,,Montri nekrologojn,Mostrar obituarios,,Näytä kuolinviestit,Afficher avis de décès,Halálok mutatása,Mostra i necrologi,訃報表示,사망 메시지 표시,Doodsbrieven tonen,Vis dødsannonser,Pokaż nekrologi,Exibir obituários,,Afișare necrologuri,Отображение некрологов,Прикажи читуље,Ölüm ilanlarını göster -Show secret notifications,MSGMNU_SHOWSECRETS,,,,Zobrazit zprávy o skrýších,Vis hemmelige meddelelser,Zeige Geheimnismeldung,,Montri sciigojn de sekretoj,Mostrar notificación de secretos,,Ilmoita salojen löytymisestä,Afficher secrets,Titkos üzenetek mutatása,Mostra le notifiche dei segreti,シークレット発見表示,비밀 알림 표시,Geheime meldingen tonen,Vis hemmelige meldinger,Pokaż wiadomości znalezienia sekretu,Exibir notificação de segredos,,Afișare notificări pentru secrete,Отображение сообщений о тайниках,Прикажи тајне нотификације,Gizli bildirimleri göster -Minimum message level,MSGMNU_MESSAGELEVEL,,,,Minimální úroveň oznámení,Mindste beskedniveau,Min. Nachrichtenanzeigestufe,,Minimuma nivelo de mesaĝoj,Nivel mínimo de mensaje,,Pienin viestintätaso,Niveau de message minimum,Milyen üzenet jelenjen meg,Numero di messaggi minimo,最小メッセージレベル,메시지 축소량,Minimaal berichtenniveau,Minste meldingsnivå,Poziom minimalnych wiadomości,Nível mínimo de mensagem,,Nivel minim de afișare mesaje,Минимальный уровень сообщений,Минимум левел порука,Minimum mesaj seviyesi -Message Colors,MSGMNU_MESSAGECOLORS,,,Message Colours,Barva oznámení,Farver på meddelelser,Nachrichtenfarben,,Mesaĝkoloroj,Colores de los Mensajes,,Viestien värit,Couleur des messages,Üzenet színek,Colore dei messaggi,メッセージ色,메시지 색상,Bericht Kleuren,Meldingsfarger,Kolory Wiadomości,Cores de mensagem,,Culori Mesaje,Цвета сообщений,Боје порука,Mesaj Renkleri -Item Pickup,MSGMNU_ITEMPICKUP,,,,Sebrání předmětu,Afhentning af varer,Genommene Gegenstände,,Objektoprenado,Toma de objetos,,Esineen poimiminen,Objets ramassés,Tárgy felvétele,Raccolta oggetti,アイテム取得,아이템 획득,Puntafhaling,Henting av element,Podniesienie Przedmiotu,Coleta de item,Aquisição de Itens,Ridicare obiecte,Подбор предмета,Покупити предмет,Bir eşyayı almak -Obituaries,MSGMNU_OBITUARIES,,,,Oznámení o úmrtí,Dødsannoncer,Todesanzeigen,,Nekrologoj,Obituarios,,Kuolinviestit,Avis de décès,Halálok,Necrologi,死亡時メッセージ,사망 메시지,Doodsbrieven,Nekrologer,Nekrologi,Obituários,,Necrologuri,Некрологи,Читуље,Ölüm İlanları -Critical Messages,MSGMNU_CRITICALMESSAGES,,,,Kritická oznámení,Kritiske meddelelser,Kritische Nachrichten,,Gravaj Mesaĝoj,Mensajes críticos,,Tärkeät viestit,Messages d'erreur,Fontos üzenetek,Messaggi critici,致命的なメッセージ,중요한 메시지,Kritische berichten,Kritiske meldinger,Wiadomości krytyczne,Mensagens críticas,,Mesaje Critice,Важные сообщения,Критичне поруке,Kritik Mesajlar -Chat Messages,MSGMNU_CHATMESSAGES,,,,Chatová oznámení,Chat-meddelelser,Chatnachrichten,,Babilmesaĝoj,Mensajes de chat,,Keskusteluviestit,Message de Chat,Chat üzenetek,Messaggi chat,チャットメッセージ,채팅 메시지,Chatberichten,Chat-meldinger,Wiadomości czatu,Mensagens de chat,,Mesaje Conversație,Сообщения в чате,Ћаскања,Sohbet Mesajları -Team Messages,MSGMNU_TEAMMESSAGES,,,,Týmová oznámení,Hold-meddelelser,Teamnachrichten,,Teammesaĝoj,Mensajes de equipo,,Joukkueen viestit,Messages d'équipe,Csapat chat üzenetek,Messaggi chat di squadra,チームメッセージ,팀 채팅 메시지,Team Berichten,Team-meldinger,Wiadomości czatu drużynowego,Mensagens de equipe,Mensagens de Equipa,Mesajele Echipei Proprii,Командные сообщения в чате,Тимске поруке,Ekip Mesajları -Centered Messages,MSGMNU_CENTEREDMESSAGES,,,Centred Messages,Oznámení na střed,Centrerede meddelelser,Zentrierte Nachrichten,,Centritaj Mesaĝoj,Mensajes centrados,,Keskitetyt viestit,Messages centrés,Üzenet középre igazítása,Messaggi centrati,スクリプトメッセージ,중간에 위치한 메시지,Gecentreerde berichten,Sentrerte meldinger,Wyśrodkowane wiadomości,Mensagens centralizadas,Mensagens Centradas,Mesaje Centrate,Центрированные сообщения,Централне поруке,Merkezli Mesajlar -Screenshot messages,MSGMNU_SCREENSHOTMESSAGES,,,,Oznámení o snímcích obrazovky,Beskeder med skærmbilleder,Screnshot-Meldungen,,Mesaĝoj de ekrankopio,Mensajes de captura de pantalla,,Kuvakaappausviestit,Messages de capture d'écran,Képernyőkép készítés visszajelzés,Messaggi di cattura schermo,スクショメッセージ,스크린샷 메시지,Screenshot berichten,Skjermbilde-meldinger,Wiadomości o zrobieniu zrzutu ekranu,Mensagens de captura de tela,Mensagen de captura de ecrã,Mesaje Capturi Ecran,Сообщения о снимках экрана,Скриншот поруке,Ekran görüntüsü mesajları -Detailed save messages,MSGMNU_LONGSAVEMESSAGES,,,,Detailní oznámení o uložené hře,Detaljerede beskeder om lagring,Detaillierte Speicher-Meldungen,,Detalaj konservmesaĝoj,Mensajes detallados de guardado,,Yksityiskohtaiset tallennusviestit,Messages de sauvegarde détailés,Részletes mentési információ,Messaggi sui dettagli di salvataggio,詳細なセーブメッセージ,자세한 저장 메시지,Gedetailleerde berichten voor op te slaan,Detaljerte lagringsmeldinger,Szczegółowe wiadomości o zapisie,Mensagens detalhadas de salvamento,Mensagens detalhadas de gravação,Mesaje detaliate pentru salvări,Подробные сообщения о сохранениях,Детаљно сачуване поруке,Ayrıntılı kaydetme mesajları -Developer message mode,MSGMNU_DEVELOPER,,,,Vývojářská oznámení,Meddelelsestilstand for udviklere,Entwickler-Modus,,Reĝimo de mesaĝoj por programistoj,Modo de mensajes de desarrollador,,Pelinkehittäjäviestitila,Mode de Développement,Fejlesztői üzenetek,Modalità messaggi per sviluppatore,開発者用モード,개발자 메시지 모드,Berichtenmodus voor ontwikkelaars,Meldingsmodus for utviklere,Tryb wiadomości deweloperskich,Modo de mensagens de desenvolvedor,,Mod mesaje pentru dezvoltator,Режим сообщений для разработчиков,Поруке девелопера,Geliştirici mesaj modu -,,Automap,,,,,,,,,,,,,,,,,,,,,,,, -Map color set,AUTOMAPMNU_COLORSET,,,Map colour set,Barevné schéma,Farvesæt til kort,Farbset,,Mapkoloro-agordaĵo,Definir colores,,Kartan värikokoelma,Set de couleurs de la carte,Pálya térkép szín séma,Colori della mappa,地図色セット,맵 색상 설정,Kaartkleurenset,Kartfargesett,Zestaw kolorów mapy,Definir cores de mapa,,Set culori hartă,Цвета автокарты,Боје за мапу,Harita renk seti -Allow map defined colors,AUTOMAPMNU_CUSTOMCOLORS,,,Allow map defined colours,Povolit barvy dle modů,Tillad kortdefinerede farver,Erlaube levelspezifische Farben,,Permesi mapdefinitajn kolorojn,Permitir colores definidos,,Salli tason määrittelemät värit,Couleurs définies par carte,Pálya orientált színséma használata,Consenti i colori definiti dalla mappa,定義したマップ色の許可,맵 정의 색상 허용,Niveau-specifieke kleuren toestaan,Tillat kartdefinerte farger,Pozwól na kolory zdefiniowne przez mapę,Permitir cores definidas por mapa,,Permite culorilor să fie definite de hartă,Разрешить определённые уровнем цвета автокарты,Дозволи дефинисане боје за мапу,Harita tanımlı renklere izin ver -Set custom colors,AUTOMAPMNU_SETCUSTOMCOLORS,,,Set custom colours,Vlastní barvy,Indstil brugerdefinerede farver,Benutzerdefinierte Farben,,Agordi laŭmendajn kolorojn,Fijar colores personalizados,,Mukauta värejä,Choisir couleurs personnalisées,Egyéni színek beállítása,Modifica i colori personalizzati,カスタム色を決める,사용자 지정 색상 설정,Aangepaste kleuren instellen,Angi egendefinerte farger,Spersonalizuj kolory,Definir cores personalizadas,,Setare culori personalizate,Задать свои цвета,Промени боје,Özel renkleri ayarlama -Customize map controls,AUTOMAPMNU_CONTROLS,,,,Ovládání mapy,Tilpas kontrolelementer til kortet,Automapsteuerung einstellen,,Adapti mapregilojn,Personalizar controles del mapa,,Kartanohjausasetukset,Choisir contrôles de la carte,Térkép irányítás testreszabása,Personalizza i controlli mappa,マップコントロール カスタマイズ,맵 조작 설정,Kaartcontroles aanpassen,Tilpass kartkontroller,Ustaw klawisze mapy,Configurar comandos de mapa,,Personalizare schemă de control a hărții,Управление автокартой,Промени контроле мапе,Harita kontrollerini özelleştirme -Overlay automap,AUTOMAPMNU_OVERLAY,,,,Překryvná mapa,Overlay automap,Überlagere Automap,,Surmeti aŭtomapon,Superponer automapa,,Projisoi automaattikartta,Carte en Surimpression,Képen felüli térkép,Copri l'automappa,オートマップを重ねる,오토맵을 오버레이,Overlay automap,Overlegg automatisk kart,Nałożenie mapy,Sobreposição de automapa,,Acoperire hartă computerizată,Прозрачная автокарта,Провидна аутомапа,Yerleşim otomatik haritası -Enable textured display,AUTOMAPMNU_TEXTURED,,,,Textury,Aktiver tekstureret visning,Texturanzeige,,Ŝalti teksturitan ekranon,Mostrar automapa texturizado,,Ota käyttöön pintakuvioinnit,Activer affichage texturé,Textúrázott térkép,Abilita la mostra texture,床テクスチャ表示を許可,텍스쳐 디스플레이 허용,Structuurweergave inschakelen,Aktiver teksturert visning,Włącz oteksturowanie mapy,Habilitar automapa texturizado,Permitir automapa texturizado,Activare mod texturat,Текстуры на автокарте,Омогући приказ текстура,Dokulu ekranı etkinleştir -Show item counts,AUTOMAPMNU_SHOWITEMS,,,,Počet předmětů,Vis tællinger af emner,Zeige Gegenstandsanzahl,,Montri nombron de objektoj,Mostrar conteo de objetos,,Näytä esineiden lukumäärä,Afficher compte d'objets,Tárgy számláló mutatása,Mostra il conteggio degli oggetti,アイテム数 表示,주운 아이템의 갯수를 표시,Toon artikeltellingen,Vis antall elementer,Pokaż liczbę przedmiotów,Exibir contagem de itens,,Afișare numărătoare obiecte,Количество предметов,Прикажи бројач за предмете,Öğe sayılarını göster -Show monster counts,AUTOMAPMNU_SHOWMONSTERS,,,,Počet příšer,Vis monstertællinger,Zeige Monsteranzahl,,Montri nombron de monstroj,Mostrar conteo de monstruos,,Näytä hirviöiden lukumäärä,Afficher compte de monstres,Szörny számláló mutatása,Mostra il conteggio dei mostri,モンスター数 表示,죽인 적의 횟수 표시,Toon monstertellingen,Vis antall monster,Pokaż liczbę potworów,Exibir contagem de monstros,,Afișare numărătoare monștri,Количество монстов,Прикажи бројач за чудовишта,Canavar sayılarını göster -Show secret counts,AUTOMAPMNU_SHOWSECRETS,,,,Počet skrýší,Vis hemmelige tællinger,Zeige Geheimnisanzahl,,Montri nombron de sekretoj,Mostrar conteo de secretos,,Näytä salojen lukumäärä,Afficher compte de secrets,Rejtekhely számláló mutatása,Mostra il conteggio dei segreti,シークレット数 表示,밝힌 비밀의 수 표시,Toon geheime tellingen,Vis hemmelige tellinger,Pokaż liczbę sekretów,Exibir contagem de segredos,,Afișare numărătoare secrete,Количество тайников,Прикажи бројач за тајне,Gizli sayıları göster -Show time elapsed,AUTOMAPMNU_SHOWTIME,,,,Uplynulý čas na mapě,Vis den forgangne tid,Zeige vergangene Zeit,,Montri pasintan tempon,Mostrar tiempo transcurrido,,Näytä kulunut aika,Afficher temps passé,Eltöltött idő mutatása,Mostra il tempo trascorso,経過時間 表示,경과한 시간 표시,Verstreken tijd tonen,Vis medgått tid,Pokaż ile czasu upłynęło,Exibir tempo decorrido,,Afișare timp petrecut pe hartă,Прошедшее время,Прикажи протекло време,Geçen süreyi göster -Show total time elapsed,AUTOMAPMNU_SHOWTOTALTIME,,,,Celkový uplynulý čas,"Vis den samlede tid, der er gået",Zeige Gesamtzeit,,Montri tutan pasintan tempon,Mostrar tiempo total transc.,,Näytä yhteensä kulunut aika,Afficher total de temps passé,Teljes eltelt idő mutatása,Mostra il tempo totale trascorso,統計時間 表示,누적 경과한 시간 표시,Toon de totale verstreken tijd,Vis total tid som har gått,"Pokaż całkowity czas, który upłynął",Exibir tempo total decorrido,,Afișare timp total petrecut în joc,Общее время,Прикажи укупно протекло време,Geçen toplam süreyi göster -Show secrets on map,AUTOMAPMNU_MAPSECRETS,,,,Zobrazit skrýše,Vis hemmeligheder på kortet,Zeige Geheimnisse auf der Karte,,Montri sekretojn sur mapo,Mostrar secretos en el mapa,,Näytä salat kartalla,Afficher secrets sur carte,Rejtekhelyek mutatása a pályán,Mostra i segreti nella mappa,シークレットを地図に表示,맵의 비밀을 표시,Toon geheimen op de kaart,Vis hemmeligheter på kartet,Pokaż sekrety na mapie,Exibir segredos no mapa,,Afișare secrete,Тайники на карте,Прикажи тајне на аутомапи,Haritada sırları göster -Show map label,AUTOMAPMNU_SHOWMAPLABEL,,,,Zobrazit název mapy,Vis kortmærke,Zeige Levelnamen,,Montri mapetikedon,Mostrar etiqueta del mapa,,Näytä tason tunniste,Afficher label de carte,Pályacím mutatása,Mostra le etichette della mappa,マップ名 表示,맵의 이름 표시,Toon kaartlabel,Vis kartetikett,Pokaż etykietę mapy,Exibir etiqueta do mapa,,Afișare etichetă hartă,Название карты,Прикажи ознаку мапе,Harita etiketini göster -Draw map background,AUTOMAPMNU_DRAWMAPBACK,,,,Pozadí mapy,Tegne kortbaggrund,Zeige Kartenhintergrund,,Desegni mapfondon,Dibujar fondo de mapa,,Piirrä tason tausta,Afficher fond d'écran carte,Térkép háttér kirajzolása,Mostra lo sfondo della mappa,マップの背景 描写,맵의 배경 출력,Teken de achtergrond van de kaart,Tegn kartbakgrunn,Rysuj tło mapy,Desenhar fundo do mapa,,Afișare fundal hartă,Отображение фона автокарты,Нацртај позадину мапе,Harita arka planı çizme -Show keys (cheat),AUTOMAPMNU_SHOWKEYS,,,,Zobrazení klíčů (podvod),Vis nøgler (snyd),Zeige Schlüssel (Cheat),,Montri klavojn (trompo),Mostrar llaves (truco),,Näytä avaimet (huijauskeino),Afficher les clés (cheat),Kulcsok mutatása,Mostra le chiavi (cheat),鍵 表示(チート時),키를 표시 (치트),Toon sleutels (valsspeler),Vis nøkler (juks),Pokaż klucze (oszustwo),Exibir chaves (trapaça),,Afișare chei (trișare),Отображение ключей (чит-коды),Прикажи кључеве (чит),Tuşları göster (hile) -Show trigger lines,AUTOMAPMNU_SHOWTRIGGERLINES,,,,Zobrazení aktivujících čar,Vis trigger-linjer,Zeige Auslöserlinien,,Montri baskulliniojn,Mostrar líneas de activación,,Näytä laukaisinviivat,Afficher lignes d'action,Trigger vonalak mutatása,Mostra le linee d'attivazione,トリガーライン 表示,트리거 선을 표시,Triggerlijnen tonen,Vis utløserlinjer,Pokaż linie przełączników,Exibir linhas de ativação,,Afișare linii declanșatoare,Отображение спусковых линий,Прикажи триггер линије,Tetik çizgilerini göster -Show things as sprites,AUTOMAPMNU_SHOWTHINGSPRITES,,,,Zobrazení objektů jako spritů,Vis ting som sprites,Zeige Dinge als Sprites,,Montri objektojn kiel spritoj,Mostrar cosas como sprites,,Näytä oliot spriteinä,Afficher objets comme sprites,Tárgyak sprite-ként megjelenítése,Mostra gli oggetti come sprite,thingsのスプライト表示,물체를 스프라이트로 표시,Toon dingen als sprites,Vis ting som sprites,Pokaż rzeczy jako sprite'y,Exibir objetos como sprites,,Afișare obiecte drept sprite,Отображение спрайтов объектов,Прикажи ствари као спрајтове,Nesneleri sprite olarak gösterme -Overlay portals,AUTOMAPMNU_PTOVERLAY,,,,Překrývat portály,Overlay portaler,Überlagere Portale,,Surmeti portalojn,Sobreponer portales,,Projisoi portaalit,Superposer les portails,Overlay portálok,Sovrapponi i portali,オーバーレイ ポータルズ,포탈을 오버레이,Overlappende portalen,Overlegg portaler,Nałóż portale,Sobreposição de portais,,Acoperire portaluri,Порталы в прозрачном режиме,Провидни портали,Yerleşim portalları -Empty space margin,AUTOMAPMNU_EMPTYSPACEMARGIN,,,,Práh prázdného prostoru,Tomrumsmargin,Breite des Randes,,Malplena spacia marĝeno,Margen de espacio vacío,,Tyhjän reunan leveys,Marge d'espace vide,Üres hely szegély,Margine dello spazio vuoto,空間の余白,빈공간 여백,Breedte van de rand,Tøm mellomromsmargen,Opróżnij margines przestrzeni,Margem de espaço vazio,,Margine spațiu gol,Край автокарты,Празна маргина,Boş alan marjı -Mark font,AUTOMAPMNU_MARKFONT,,,,Písmo značek,Marker skrifttype,Zeichensatz für Markierungen,,Marki tiparon,Fuente para marcas,,Karttamerkkien fontti,Police Marqueur,Jelzés betűtípus,Font del segnaposto,マークフォント,미니맵 마킹 폰트,Font voor markers,Merk skrifttype,Czcionka oznaczeń,Fonte das marcações,,Font marcaj,Шрифт отметок,Фонт ознака,Mark yazı tipi -Mark color,AUTOMAPMNU_MARKCOLOR,,,,Barva značek,Markere farve,Farbe für Markierungen,,Marki koloron,Color de las marcas,,Karttamerkkien väri,Couleur Marqueur,Jelzés szín,Colore del segnaposto,マーク色,미니맵 마킹 색상,Markeer kleur,Merk farge,Kolor oznaczeń,Cor das marcações,,Culoare marcaj,Цвет отметок,Боја ознака,Renk işaretle -Set mark,MAPCNTRLMNU_SETMARK,,,,Umístit značku,Indstille mærke,Setze Markierung,,Meti markon,Fijar marca,,Aseta merkki,Placer repère,Jelzés beállítása,Aggiungi segnaposto,マークを置く,마크 추가,Markering instellen,Sett merke,Ustaw znacznik,Posicionar marcação,,Marcare,Поставить отметку,Постави ознаку,İşareti ayarla -Clear mark,MAPCNTRLMNU_CLEARMARK,,,,Smazat značky,Slet markering,Lösche Markierung,,Forigi markon,Limpiar marca,,Pyyhi merkit,Enlever repères,Jelzések törlése,Pulisci il segnaposto,マーククリア,마크 삭제,Duidelijke markering,Fjern merke,Usuń znacznik,Limpar marcação,,Ștergere marcaj,Убрать отметку,Уклони ознаку,Açık işaret -,,Scoreboard,,,,,,,,,,,,,,,,,,,,,,,, -Scoreboard Options,DSPLYMNU_SCOREBOARD,,,,Tabulka skóre,Indstillinger for resultattavlen,Punktetabellenoptionen,,Poentotabulo-Agordoj,Opciones de marcador,,Pistetauluasetukset,Options Tableau des Scores,Eredményjelző beállítások,Opzioni tabella punteggio,スコアボード オプション,점수창 설정,Scorebord opties,Alternativer for resultattavlen,Opcje Tablicy Wyników,Opções de Tela de Pontuação,,Opțiuni Tabelă de Marcaj,Таблица очков,Табеларне подешавања,Skorbord Seçenekleri -Scoreboard Options,SCRBRDMNU_TITLE,,,,Nastavení tabulky skóre,Indstillinger for resultattavlen,Punktetabellenoptionen,,Poentotabulo-Agordoj,Opciones de marcador,,Pistetauluasetukset,Tableau des Scores,Eredményjelző beállítások,Opzioni per la tabella punteggio,スコアボード オプション,점수판 설정,Scorebord opties,Alternativer for resultattavlen,Opcje Tablicy Wyników,Opções de Tela de Pontuação,Opções do Ecrã de Pontuação,Setări Tabelă de Marcaj,Настройки таблицы очков,Подешавања бодовања,Skorbord Seçenekleri -Cooperative Options,SCRBRDMNU_COOPERATIVE,,,,Kooperativní mód,Samarbejdsmuligheder,Kooperativ-Optionen,,Kooperativo-Agordoj,Opciones de cooperativo,,Yhteispeliasetukset,Options Mode Coop,Együttműködő beállítása,Opzioni per il gioco cooperativo,協力モードの設定,코옵 설정,Coöperatieve Opties,Samarbeidsalternativer,Opcje Kooperacji,Opções de Jogo Cooperativo,,Setări Mod Cooperativ,Настройки для команд,Подешавања сарадње,Kooperatif Seçenekleri -Enable Scoreboard,SCRBRDMNU_ENABLE,,,,Povolit tabulku skóre,Aktiver resultattavle,Punktetabelle aktiv,,Ŝalti Poentotabulon,Activar marcador,,Ota käyttöön pistetaulu,Activer Tableau des Scores,Eredményjelző bekapcsolása,Abilita la tabella punteggio,スコアボード表示,점수판 허용,Scorebord inschakelen,Aktiver resultattavle,Zezwól na Tablicę Wyników,Habilitar Tela de Pontuação,Permitir Ecrã de Pontuação,Activare Tabelă de Marcaj,Включить таблицу очков,Омогући бодовање,Skor Tablosunu Etkinleştir -Header Color,SCRBRDMNU_HEADERCOLOR,,,Header Colour,Barva hlavičky,Overskriftsfarve,Kopfzeilenfarbe,,Kapokoloro,Color de cabecera,,Otsikon väri,Couleur du Titre,Fejléc szín,Colore della testata,ヘッダー色,헤더의 색깔,Kleur koptekst,Farge på topptekst,Kolor Nagłówka,Cor de Cabeçalho,,Culoare Antet,Цвет заголовка,Боја заглавља,Başlık Rengi -Your Player Color,SCRBRDMNU_YOURCOLOR,,,Your Player Colour,Barva tvého hráče,Din spillerfarve,Deine Spielerfarbe,,Via Ludantkoloro,Color de tu jugador,,Pelaajasi väri,Votre couleur,Játékos színe,Colore del giocatore 'Tu',自分の色,플레이어의 색깔,Uw Spelerskleur,Din spillerfarge,Twoje Kolory,Cor do Seu Jogador,Cor do teu Jogador,Culoarea Jucătorului Tău,Ваш цвет,Боја твога играча,Oyuncu Renginiz -Other Players' Color,SCRBRDMNU_OTHERPLAYERCOLOR,,,Other Players' Colour,Barva ostatních hráčů,Andre spilleres farve,Andere Spielerfarbe,,Koloro de Aliaj Ludantoj,Color de otros jugadores,,Muiden pelaajien väri,Couleur des autres joueurs,Más játékosok színe,Colore degli altri giocatori,他者の色,다른 플레이어들의 색깔,Andere spelerskleur,Andre spilleres farge,Kolory Innych Graczy,Cor de Outros Jogadores,Cor dos Outros Jogadores,Culorile Celorlalți Jucători,Цвет других игроков,Боја другог играча,Diğer Oyuncuların Rengi -Deathmatch Options,SCRBRDMNU_DEATHMATCH,,,,Deathmatch,Indstillinger for Deathmatch,Deathmatch-Optionen,,Mortmaĉo-Agordoj,Opciones modo a muerte,,Kuolonotteluasetukset,Options Deathmatch,Deathmatch Beállítások,Opzioni deathmatch,デスマッチの設定,데스매치 설정,Deathmatch opties,Deathmatch-alternativer,Opcje Deathmatchu,Opções de Deathmatch,,Setări Deathmatch,Настройки боя насмерть,Детмеч подешавања,Ölüm Maçı Seçenekleri -Team Deathmatch Options,SCRBRDMNU_TEAMDEATHMATCH,,,,Týmový deathmatch,Indstillinger for Team Deathmatch,Team-Deathmatch-Optionen,,Teamo-Mortmaĉo-Agordoj,Opciones modo a muerte por equipos,,Joukkuekuolonotteluasetukset,Options Deathmatch en équipe,Team Deathmatch Beállítások,Opzioni deathmatch a squadra,チームデスマッチの設定,팀 데스매치 설정,Team Deathmatch Opties,Lag Deathmatch-alternativer,Opcje Drużynowego Deathmatchu,Opções de Deathmatch de Equipe,Opções de Deathmatch de Equipa,Setări Deathmatch în Echipă,Настройки командного боя насмерть,Тимски детмеч подешавања,Takım Ölüm Maçı Seçenekleri -,,Alt HUD,,,,,,,,,,,,,,,,,,,,,,,, -Alternative HUD,ALTHUDMNU_TITLE,,,,Alternativní HUD,Alternativ HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH Alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternativ HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативное отображение информации,Алтернативни HUD,Alternatif HUD -Enable alternative HUD,ALTHUDMNU_ENABLE,,,,Povolit alternativní HUD,Aktiver alternativt HUD,Alternatives HUD eingeschaltet,,Ŝalti alternativan HUD,Activar HUD alternativo,,Ota käyttöön vaihtoehtoinen tilanäyttö,Activer l'ATH Alternatif,Alternatív HUD bekapcsolása,Abilita HUD alternativo,オルタナティブHUD有効,대체 HUD 사용,Alternatieve HUD inschakelen,Aktiver alternativ HUD,Włącz alternatywny HUD,Habilitar HUD alternativo,,Activează Interfața pe Timp de Joc Alternativă,Включить альтернативное отображение,Укључи алтернативни HUD,Alternatif HUD'yi etkinleştirin -Show secret count,ALTHUDMNU_SHOWSECRETS,,,,Zobrazit počet skrýší,Vis hemmelig optælling,Zeige Geheimniszähler,,Montri sekretonombron,Mostrar cont. de secretos,,Näytä salojen lukumäärä,Afficher compteur de secrets,Rejtekhely számláló mutatása,Mostra il conteggio dei segreti,シークレット数 表示,비밀 수 표시,Toon het aantal geheimen,Vis hemmelig antall,Pokaż liczbę sekretów,Exibir contagem de segredos,,Afișează numărul secretelor,Отображение обнаруженных тайников,Прикажи количину тајна,Gizli sayımı göster -Show monster count,ALTHUDMNU_SHOWMONSTERS,,,,Zobrazit počet příšer,Vis monstertælling,Zeige Monsterzähler,,Montri monstronombron,Mostrar cont. de monstruos,,Näytä hirviöiden lukumäärä,Afficher compteur de monstres,Szörny számláló mutatása,Mostra il conteggio dei mostri,モンスター数 表示,적 개체 수 표시,Toon het aantal monsters,Vis antall monstre,Pokaż liczbę zabójstw,Exibir contagem de monstros,,Afișează numărul de monștri,Отображение количества монстров,Прикажи количину чудовишта,Canavar sayısını göster -Show item count,ALTHUDMNU_SHOWITEMS,,,,Zobrazit počet předmětů,Vis optælling af genstande,Zeige Gegenstandszähler,,Montri objektonombron,Mostrar cont. de objetos,,Näytä esineiden lukumäärä,Afficher compteur d'objets,Tárgy számláló mutatása,Mostra il conteggio degli oggetti,アイテム数の表示,아이템 수 표시,Toon het aantal items,Vis antall gjenstander,Pokaż liczbę przedmiotów,Exibir contagem de itens,,Afișează numărul de obiecte,Отображение количества предметов,Прикажи количину предмета,Öğe sayısını göster -Show stamina and accuracy,ALTHUDMNU_SHOWSTATS,,,,Zobrazit výdrž a přesnost,Vis udholdenhed og nøjagtighed,Zeige Kondition und Genauigkeit,,Montri viglecon kaj akuratecon,Mostrar resistencia/precisión,,Näytä puhti ja tarkkuus,Afficher Endurance et Précision,Állóképesség és pontosság mutatása,Mostra stamina e accuratezza,スタミナと精度の表示,스테미나와 정확도를 표시,Toon uithoudingsvermogen en nauwkeurigheid,Vis utholdenhet og nøyaktighet,Pokaż wytrzymałość i precyzję,Exibir resistência e precisão,,Afișează rezistența fizică si acuratețea,Отображение выносливости и точности,Прикажи издржљивост и прецизност,Dayanıklılık ve doğruluk gösterin -Show berserk,ALTHUDMNU_SHOWBERSERK,,,,Zobrazit berserk,Vis berserk,Zeige Berserk,,Montri frenezecon,Mostrar berserker,,Näytä raivo,Afficher Berserk,Berserk mutatása,Mostra il berserk,バーサーク表示,버서크 아이템을 표시,Toon berserk,Vis berserk,Pokaż szał,Exibir berserk,,Afișează pachetul de forță mărită,Отображение берсерка,Прикажи берсерк,Berserk'i göster -Show weapons,ALTHUDMNU_SHOWWEAPONS,,,,Zobrazit zbraně,Vis våben,Zeige Waffen,,Montri armojn,Mostrar armas,,Näytä aseet,Afficher Armes,Fegyverek mutatása,Mostra le armi,武器表示,무기들을 표시,Toon wapens,Vis våpen,Pokaż bronie,Exibir armas,,Afișează armele,Отображение оружия,Прикажи оружја,Silahları göster -Show ammo for,ALTHUDMNU_SHOWAMMO,,,,Zobrazit munici pro,Vis ammunition for,Zeige Munition,,Montri municion por,Mostrar munición para,,Näytä ammukset aseelle,Afficher Munitions pour,Ammo mutatása a,Mostra le munizioni per,弾薬等の表示,탄약을 표시,Toon munitie voor,Vis ammunisjon for,Pokaż amunicję dla,Exibir munição para,,Afișează muniția pentru,Отображение патронов для,Прикажи муниције за,Cephane göster -Show time,ALTHUDMNU_SHOWTIME,,,,Zobrazit čas,Vis tid,Zeige Zeit,,Montri tempon,Mostrar tiempo,,Näytä aika,Afficher temps niveau,Idő mutatása,Mostra il tempo,時間の表示,시간 표시,Toon tijd,Vis tid,Pokaż czas,Exibir tempo,,Afișează timpul,Отображение времени,Прикажи време,Gösteri zamanı -Time color,ALTHUDMNU_TIMECOLOR,,,Time colour,Barva času,Tidens farve,Zeit-Farbe,,Tempkoloro,Color del tiempo,,Ajan väri,Couleur du timer,Idő színe,Colore del tempo,時間の字色,시간 색상,Tijdskleur,Tid farge,Kolor czasu,Cor do tempo,,Culoare timp,Цвет времени,Боја времена,Zaman rengi -Show network latency,ALTHUDMNU_SHOWLAG,,,,Zobrazit latenci sitě,Vis netværksforsinkelse,Zeige Netzwerk-Latenz,,Montri reto-respondotempon,Mostrar latencia de red,,Näytä verkon viive,Afficher latence réseau,Válaszidő mutatása,Mostra la latenza del network,ネットのラグ表示,내트워크 트래픽 표시,Toon netwerklatentie,Vis nettverksforsinkelse,Pokaż czas oczekiwania sieci,Exibir latência de rede,,Afișează perioada de întârziere a conexiunii,Отображение задержки сети,Прикажи кашњење мреже,Ağ gecikmesini göster -Ammo display order,ALTHUDMNU_AMMOORDER,,,,Pořadí zobrazení munice,Visningsrækkefølge for ammunition,Munitionsreihenfolge,,Vidiga aranĝo de municio,Orden vista de munición,,Ammusten esitysjärjestys,Ordre d'affichage des munitions,Muníció típus rendezése,Ordine mostra delle munizioni,弾薬表示順,탄약 표시 순서,Volgorde van de munitieweergave,Rekkefølge for ammunisjonsvisning,Kolejność pokazywania amunicji,Ordem de exibição de munição,,Ordine afișare muniție,Порядок отображения боеприпасов,Редослед муниција,Cephane teşhir düzeni -Red ammo display below %,ALTHUDMNU_AMMORED,,,,Červený indikátor munice pod %,Rød ammunitionsvisning under %,Rot für Munition unter %,,Ruĝa municividigo sub %,Porcent. de munición en rojo,,Punaiset ammukset ammusten alittaessa %,Compteur de munitions rouge sous,Piros muníció szín % alatt,Contatore delle munizioni di colore rosso sotto,弾薬の赤色表示%,적색 남은 탄약 밑에 표시,Rood munitieweergave onder %,Rød visning av ammunisjonsnivå under %,Wyświetl czerwoną amunicję pod ,Porcentagem de munição em vermelho até,Percentagem de munição em vermelho até,Muniția schimbă culoarea în roșu sub %,"Отображение боеприпасов красным ниже, %",Прикажи муниције црвеном испод %,Aşağıda kırmızı cephane göstergesi % -Yellow ammo display below %,ALTHUDMNU_AMMOYELLOW,,,,Žlutý indikátor munice pod %,Gul ammunitionsvisning under %,Gelb für Munition unter %,,Flava municividigo sub %,Porcent. de munición en amarillo,,Keltaiset ammukset ammusten alittaessa %,Compteur de munitions jaune sous,Sárga muníció szín % alatt,Contatore delle munizioni di colore giallo sotto,弾薬の黄色表示%,황색 남은 탄약 밑에 표시,Gele munitieweergave onder %,Gult ammunisjonsdisplay under %.,Wyświetl żółtą amunicję pod ,Porcentagem de munição em amarelo até,Percentagem de munição em amarelo até,Muniția schimbă culoarea în galben sub %,"Отображение боеприпасов жёлтым ниже, %",Прикажи муниције жутом испод %,Aşağıda sarı cephane göstergesi % -Red health display below,ALTHUDMNU_HEALTHRED,,,,Červený indikátor zdraví pod,Rødt sundhedsindikator under %,Rot für Gesundheit unter %,,Ruĝa sanvidigo sube,Porcent. de salud en rojo,,Punainen terveys terveyden alittaessa,Compteur de santé rouge sous,Piros életerő szín ezen szám alatt,Contatore della salute di colore rosso sotto,体力の赤色表示%,적색 체력 밑에 표시,Rood gezondheidsweergave beneden,Rød helsevisning under,Wyświetl czerwone zdrowie pod ,Porcentagem de saúde em vermelho até,Percentagem de saúde em vermelho até,Sănătatea schimbă culoarea în roșu sub %,"Отображение здоровья красным ниже, %",Прикажи здравље црвеном испод,Aşağıdaki kırmızı sağlık göstergesi -Yellow health display below,ALTHUDMNU_HEALTHYELLOW,,,,Žlutý indikátor zdraví pod,Gul sundhedsindikator under %,Gelb für Gesundheit unter %,,Flava sanvidigo sube,Porcent. de salud en amarillo,,Keltainen terveys terveyden alittaessa,Compteur de santé jaune sous,Sárga életerő szín ezen szám alatt,Contatore della salute di colore giallo sotto,体力の黄色表示%,황색 체력 밑에 표시,Geel gezondheidsweergave beneden,Gul helsevisning nedenfor,Wyświetl żółte zdrowie pod ,Porcentagem de saúde em amarelo até,Percentagem de saúde em amarelo até,Sănătatea schimbă culoarea în galben sub %,"Отображение здоровья жёлтым ниже, %",Прикажи здравље жутом испод,Aşağıdaki sarı sağlık göstergesi -Green health display below,ALTHUDMNU_HEALTHGREEN,,,,Zelený indikátor zdraví pod,Grønt sundhedsindikator under %,Grün für Gesundheit unter %,,Verda sanvidigo sube,Porcent. de salud en verde,,Vihreä terveys terveyden alittaessa,Compteur de santé vert sous,Zöld életerő szín ezen szám alatt,Contatore della salute di colore verde sotto,体力の緑色表示%,녹색 체력 밑에 표시,Groen gezondheidsweergave beneden,Grønn helsevisning under,Wyświetl zielone zdrowie pod ,Porcentagem de saúde em verde até,Percentagem de saúde em verde até,Sănătatea schimbă culoarea în verde sub %,"Отображение здоровья зелёным ниже, %",Прикажи здравље зеленом испод,Aşağıdaki yeşil sağlık göstergesi -Red armor display below,ALTHUDMNU_ARMORRED,,,Red armour display below,Červený indikátor brnění pod,Rødt panser display under %,Rot für Panzerung unter %,,Ruĝa kirasvidigo sube,Porcent. de blindaje en rojo,,Punainen panssari panssarin alittaessa,Compteur d' armure rouge sous,Piros páncél szín ezen szám alatt,Contatore dell'armatura di colore rosso sotto,防具の赤色表示%,적색 아머 밑에 표시,Rood pantserweergave beneden,Visning av rød rustning under,Wyświetl czerwony pancerz pod ,Porcentagem de armadura em vermelho até,Percentagem de armadura em vermelho até,Armura schimbă culoarea în galben sub %,"Отображение брони красным ниже, %",Прикажи оклоп црвеном испод,Kırmızı zırh ekranı aşağıda -Yellow armor display below,ALTHUDMNU_ARMORYELLOW,,,Yellow armour display below,Žlutý indikátor brnění pod,gul panser under displayet under %,Gelb für Panzerung unter %,,Flava kirasvidigo sube,Porcent. de blindaje en amarillo,,Keltainen panssari panssarin alittaessa,Compteur d' armure jaune sous,Sárga páncél szín ezen szám alatt,Contatore dell'armatura di colore giallo sotto,防具の黄色表示%,황색 아머 밑에 표시,Geel pantserweergave beneden,Visning av gul rustning under,Wyświetl żółty pancerz pod ,Porcentagem de armadura em amarelo até,Percentagem de armadura em amarelo até,Armura schimbă culoarea în galben sub %,"Отображение брони жёлтым ниже, %",Прикажи оклоп жутом испод,Aşağıdaki sarı zırh ekranı -Green armor display below,ALTHUDMNU_ARMORGREEN,,,Green armour display below,Zelený indikátor brnění pod,grønt panser display under %,Grün für Panzerung unter %,,Verda kirasvidigo sube,Porcent. de blindaje en verde,,Vihreä panssari panssarin alittaessa,Compteur d' armure bleu sous,Zöld páncél szín ezen szám alatt,Contatore dell'armatura di colore verde sotto,防具の緑色表示%,녹색 아머 밑에 표시,Groen pantserweergave beneden,Visning av grønn rustning under,Wyświetl zielony pancerz pod ,Porcentagem de armadura em verde até,Percentagem de armadura em verde até,Armura schimbă culoarea în verde sub %,"Отображение брони зелёным ниже, %",Прикажи оклоп зеленом испод,Aşağıdaki yeşil zırh ekranı -Alternative Automap HUD,ALTHUDMNU_AUTOMAPHUD,,,,Alternativní HUD automapy,Alternativ Automap HUD,Alternatives Automap HUD,,Alternativa HUD de Aŭtomapo,HUD alternativo del automapa,,Vaihtoehtoinen automaattikartan tilanäyttö,ATH Alternatif pour carte,Alternatív Automap HUD,HUD automappa alternativo,オルタナティブ オートマップHUD,대체 오토맵 HUD,Alternatieve Automap HUD,Alternativ Automap HUD,Alternatywny HUD mapy,HUD alternativo de automapa,,Hartă Computerizată Alternativă,Альтернативный интерфейс на автокарте,Алтернативни HUD за аутомапу,Alternatif Automap HUD -Map title color,ALTHUDMNU_TITLECOLOR,,,Map title colour,Barva názvu levelu,Farve på korttitel,Farbe für Levelnamen,,Maptitolo-koloro,Color del título del mapa,,Tason nimen väri,Couleur titre du niveau,Pálya cím szín,Colore titolo mappa,マップ名の色,맵 제목 색깔,Kleur kaarttitel,Farge på karttittel,Kolor nazwy mapy,Cor do título do fase,Cor do título do nível,Culoare titlu hartă,Цвет названия уровня,Боја назива нивоа,Harita başlık rengi -Map time color,ALTHUDMNU_MAPTIMECOLOR,,,Map time colour,Barva času levelu,Farve på kortets tid,Farbe für Level-Zeit,,Maptempo-koloro,Color del tiempo del mapa,,Tason ajan väri,Couleur temps du niveau,Pálya idő szín,Colore tempo mappa,経過時間の色,맵 시간 색깔,Kleur kaarttijd,Kartets tidsfarge,Kolor czasu na mapie,Cor do tempo da fase,Cor do tempo do nível,Culoare timp petrecut pe hartă,Цвет времени для уровней,Боја времена на нивоу,Harita zaman rengi -Hub time color,ALTHUDMNU_HUBTIMECOLOR,,,Hub time colour,Barva času hubu,Farve på hub-tid,Farbe für Hub-Zeit,,Nabtempo-koloro,Color del tiempo del nodo,,Tasokokoelman ajan väri,Couleur temps du hub,Csomópont idő szín,Colore tempo hub di mappe,区間経過時間の色,허브 시간 색깔,Kleur hubtijd,Farge for knutepunkttid,Kolor czasu w hubie,Cor do tempo no HUD,,Culoare timp petrecut în hub,Цвет времени для хабов,Боја времена на хабу,Hub zaman rengi -Total time color,ALTHUDMNU_TOTALTIMECOLOR,,,Total time colour,Barva celkového času,Farve for samlet tid,Farbe für Gesamtzeit,,Tuttempo-koloro,Color del tiempo total,,Kokonaisajan väri,Couleur temps total,Teljes idő szín,Colore tempo totale,合計経過時間の色,누적 경과한 시간 색깔,Kleur totale tijd,Farge for total tid,Kolor całkowitego czasu,Cor do tempo total,,Culoare timp total,Цвет общего времени,Боја укупног времена,Toplam zaman rengi -Coordinate color,ALTHUDMNU_COORDINATECOLOR,,,Coordinate colour,Barva souřadnic,Koordinat farve,Farbe für Koordinaten,,Kunordigi koloron,Color de coordenadas,,Koordinaattien väri,Couleur coordonnées,Koordináló szín,Colore coordinate,座標色,좌표 색깔,Kleur coördinaten,Koordinatfarge,Skoordynuj kolor,Cor das coordenadas,,Culoare coordonate,Цвет координат,Боја координата,Koordinat rengi -Coordinate mode,ALTHUDMNU_COORDINATEMODE,,,,Režim souřadnic,Koordinattilstand,Koordinatenmodus,,Kunordigi modon,Modo de coordenadas,,Koordinaattitila,Mode coordonnées,Koordináló mód,Modalità coordinate,座標モード,좌표 모드,Coördinatiemodus,Koordinat-modus,Skoordynuj tryb,Modo de coordenada,,Mod coordonate,Координаты игрока,Мод координата,Koordinat modu -Statistics name color,ALTHUDMNU_STATSNAMECOLOR,,,Statistics name colour,Barva názvu statistik,Farve på statistiknavn,Farbe für Statistik-Namen,,Statistiknomo-koloro,Color del nombre de estadísticas,,Tilastotiedon nimen väri,Couleur nom des statistiques,Statisztika név szín,Colore nome statistica,統計名の色,통계표 이름 색상,Kleur statistiekennaam,Farge på statistikknavn,Kolor nazw statystyk,Cor do nome das estatísticas,,Culoare nume statistici,Цвет имён в статистике,Боја назива статистика,İstatistik adı renk -Statistics color,ALTHUDMNU_STATSCOLOR,,,Statistics colour,Barva statistik,Statistik farve,Farbe für Statistik-Nummern,,Statistiko-koloro,Color de las estadísticas,,Tilastotiedon väri,Couleur statistiques,Statisztika szín,Colore contatore statistica,統計の色,통계표 색상,Kleur statistieken,Statistikk farge,Kolor statystyk,Cor das estatísticas,,Culoare statistici,Цвет статистики,Боја статистика,İstatistik renk -,,Display (game related),,,,,,,,,,,,,,,,,,,,,,,, -Rendering Interpolation,DSPLYMNU_CAPFPS,,,,Interpolace vykreslování,Interpolering af rendering,Renderinterpolation,,Bildigo-Interpolado,Interpolación de renderizado,,Hahmonnuksen interpolointi,Interpolation du rendu,Render animáció simítás,Interpolazione grafica,レンダリング補間,프레임 제한,Interpolatie renderen,Gjengivelse av interpolasjon,Interpolacja Renderowania,Interpolação de renderização,,Interpolare Imagine,Сглаживание рендеринга,Интерполација рендеринга,Rendering Enterpolasyonu -Transparency render mode,DSPLYMNU_BLENDMETHOD,,,,Režim vykreslování průhlednosti,Gennemsigtighedstilstand,Transparenzmodus,,Travidebleco-bildigo-reĝimo,Modo de renderizado de transparencia,,Läpinäkyvyyden hahmonnustila,Mode de Rendu transparence,Átlászóság render mód,Modalità della resa grafica della trasparenza,レンダリング透過モード,투명도 표시 모드,Transparantie render modus,Gjengivelsesmodus for gjennomsiktighet,Tryb renderowania przezroczystości,Modo de renderiz. de transparência,,Mod Transparență,Режим отрисовки прозрачности,Режим рендеринга транспарентности,Şeffaflık render modu -Screen wipe style,DSPLYMNU_WIPETYPE,,,,Styl přechodů,Skærmens aftørringsstil,Bildschirmwechseleffekt,,Stilo de ekranviŝo,Transición de pantalla,,Ruudun pyyhkiytymistyyli,Style de Fondu d'écran,Képernyőtörlődés módja,Stile della pulizia dello schermo,スクリーンワイプモード,화면 전환 방식,Schermveegstijl,Stil for skjermtørking,Styl przejścia ekranu,Tipo de transição de tela,Tipo de transição de ecrã,Stil ștergere imagine,Эффект плавной смены экранов,Ефект брисања екрана,Ekran silme stili -Show ENDOOM screen,DSPLYMNU_SHOWENDOOM,,,,Zobrazit ENDOOM obrazovku,Vis ENDOOM-skærm,Zeige ENDOOM,,Montri ENDOOM-ekranon,Mostrar pantalla ENDOOM,,Näytä ENDOOM-ruutu,Montrer la fenêtre ENDOOM,ENDOOM képernyő mutatása,Mostra la schermata ENDOOM,ENDOOM画面を表示,종료화면 표시,Toon ENDOOM scherm,Vis ENDOOM-skjerm,Pokaż ekran ENDOOM,Exibir tela ENDOOM,,Afișare fereastră ENDOOM,Показать экран ENDOOM,Прикажи ENDOOM екран,ENDOOM ekranını göster -Blood Flash Intensity,DSPLYMNU_BLOODFADE,,,,Intenzita bliknutí při zranění,Blodblinkintensitet,Intensität für Bluteffekt,,Egeco de sango-ekbrilo,Intensidad del destello al ser atacado,,Verivälähdyksen voimakkuus,Intensité du flash dommages,Sebzéskor villanás mértéke,Intensità Bagliore Sangue,血粉の濃度,피격 표시 강도,Intensiteit van de bloedflitser,Intensitet for blodblits,Intensywność Efektów Krwi,Intensidade de Flash de Sangue,,Intensitate strălucire sânge,Интенсивность вспышки при ранении,Интензивност треперења током повређивања,Kan Flaş Yoğunluğu -Pickup Flash Intensity,DSPLYMNU_PICKUPFADE,,,,Intenzita bliknutí při sebrání předmětu,Intensitet for optageeffekt,Intensität für Aufnehmen-Effekt,,Egeco de prenado-ekbrilo,Intensidad del destello al coger algo,Intensidad del destello al tomar un objeto,Poimintavälähdyksen voimakkuus,Intensité du flash objets,Fegyver felvételekor villanás mértéke,Intensità Bagliore Raccolta,取得の視界色濃度,습득 표시 강도,Intensiteit van de oppakflitser,Intensitet av opptaksblits,Intesnywność Efektów Podnoszenia Przedmiotów,Intensidade de Flash ao Pegar Itens,,Intensitate strălucire la ridicarea obiectelor,Интенсивность вспышки при подборе,Интензивност треперења током купљења,Pikap Flaş Yoğunluğu -Underwater Blend Intensity,DSPLYMNU_WATERFADE,,,,Intenzita zbarvení pod vodou,Undervandsblinkintensitet,Intensität für Unterwasser-Effekt,,Egeco de Subakva Mikso,Intensidad Color Sumergido,Intensidad Color Submarino,Vedenalaissumennuksen voimakkuus,Intensité du fondu sous l'eau,Vízalatti keverődés mértéke,Intensità Blend sott'acqua,水中反響音の濃度,수중 효과 강도,Intensiteit kleurvermenging onder water,Intensitet for undervannsblanding,Intensywność Efektów Pod Wodą,Intensidade de Efeito Debaixo d'Água,Intensidade de Efeito Debaixo de Água,Intensitate amestec culori subacvatice,Интенсивность эффекта под водой,Интензивност подводног треперења,Sualtı Karışım Yoğunluğu -Sky render mode,DSPLYMNU_SKYMODE,,,,Režim vykreslování oblohy,Himmel-renderingstilstand,Rendermodus für Himmel,,Ĉielo-bildigo-reĝimo,Modo de renderizado del cielo,,Taivaan hahmonnustila,Mode du rendu du Ciel,Égbolt render mód,Modalità resa grafica del cielo,空の表示方法,하늘 표시 모드,Luchtrendermodus,Modus for gjengivelse av himmel,Tryb renderowania nieba,Modo de renderização de céu,,Mod de vizualizare al cerului,Режим отрисовки неба,Режим рендеринга неба,Gökyüzü oluşturma modu -Linear skies,DSPLYMNU_LINEARSKY,,,,Lineární obloha,Lineære himmelstrøg,Lineare Himmel,,Linearaj ĉieloj,Cielo lineal,,Lineaariset taivaat,Ciel linéaire,Lineáris égboltok,Cieli lineari,空の歪み,선형 하늘,Lineaire lucht,Lineær himmel,Liniowe niebo,Céus lineares,,Cer rectiliniu,Линейное небо,Линеарна неба,Doğrusal gökyüzü -Fullbright overrides sector color,DSPLYMNU_GZDFULLBRIGHT,,,,Při plném jasu ignorovat barvu sektoru,Ignorer sektorfarve ved fuld lysstyrke,Ignoriere Sektorfarbe bei voller Helligkeit,,Plenbrileco tranpasas sektorkoloron,Brillo máximo anula color del sector,,Täyskirkkaat ohittavat sektorin värin,Fullbright ignore couleur secteur,Fullbright felülírja a szektor szinét,Luce piena sovrappone il colore del settore,明るさ最大時にsector color塗り替え,섹터 색상 최대밝기 우선화,Volledig helderheid overschrijft de sectorkleur,Fullbright overstyrer sektorfarge,Ignoruj kolor sektora przy pełnej jasności,Brilho máximo anula cor de setor,,Luminozitatea maximă suprascrie culoarea sectorului,Полная яркость замещает цвет сектора,Пуно осветљење премошћује боју сектора,Fullbright sektör rengini geçersiz kılar -Scale fuzz effect,DSPLYMNU_SCALEFUZZ,,,,Škálovat velikost fuzz efektu,Skala fuzz-effekt,Skaliere Fuzz-Effekt,,Skali barblano-efekton,Escala de efecto fuzz,,Skaalaa sumennustehostetta,Scaling de l'effet de bruit,Homályosodás effekt átméretezése,Scala l'effetto di fuzz,ファズエフェクトサイズ,반투명 효과 조정,Schaal fuzz effect,Skala fuzz-effekt,Skalowanie efektu szumu,Escala de efeito difuso,,Putere efect de strălucire,Масштабировать эффект шума,Повечавај шумни ефект,Ölçekli fuzz efekti -Use fuzz effect,DSPLYMNU_DRAWFUZZ,,,,Typ fuzz efektu,Brug fuzz-effekt,Benutze Fuzz-Effekt,,Uzi barblano-efekton,Usar efecto fuzz,,Käytä sumennustehostetta,Effet de bruit,Homályosodás effekt használata,Usa l'effetto di fuzz,ファズエフェクトを使用,반투명 효과 사용,Gebruik fuzz effect,Bruk fuzz-effekt,Użyj efektu szumu,Usar efeito difuso,,Mod efect de strălucire,Использовать эффект шума,Користи шумни ефект,Fuzz efekti kullanın -Classic Transparency,DSPLYMNU_OLDTRANS,,,,Klasická průhlednost,Klassisk gennemsigtighed,Klasssische Transparenz,,Klasika Travidebleco,Transp. Clásicas,,Perinteinen läpinäkyvyys,Transparence classique,Klasszikus átlátszóság,Trasparenza classica,旧式の透明度,구형 투명도,Klassieke transparantie,Klassisk gjennomsiktighet,Klasyczna Przezroczystość,Transparência Clássica,,Transparență Clasică,Классическая прозрачность,Класична транспарентност,Klasik Şeffaflık -Lost Soul translucency,DSPLYMNU_TRANSSOUL,,,,Průhlednost Ztracených duší,Fortabt sjæl-translucens,Transparenz für Verlorene Seelen,,Diafaneco de Perdita Animo,Transp. del alma perdida,,Kadonneiden sielujen läpikuultavuus,Transparence des âmes perdues,Lost soul átlátszóság,Trasparenza anima errante,ロストソウルの透明度,로스트 소울 반투명도,Verloren Ziel doorschijnendheid,Lost Soul gjennomskinnelighet,Przezroczystość Zagubionych Dusz,Translucência da Alma Perdida,Translucidez da Alma Penada,Transparență Suflete Pierdute,Прозрачность потерянных душ,Транспарентност изгубљених душа,Kayıp Ruh yarı saydamlığı -Use fake contrast,DSPLYMNU_FAKECONTRAST,,,,Použít falešný kontrast,Brug falsk kontrast,Benutze falschen Kontrast,,Uzi malveran kontraston,Usar falso contraste,,Käytä tekosävykkyyttä,Faux Contraste,Hamis kontraszt használata,Usa il falso contrasto,フェイクコントラストを使用,가명암 효과 사용,Gebruik vals contrast,Bruk falsk kontrast,Użyj sztuczny kontrast,Usar contraste falso,,Utilizare contrast fals,Имитация контрастного освещения стен,Користи фејк-контраст,Sahte kontrast kullanın -Rocket Trails,DSPLYMNU_ROCKETTRAILS,,,,Kouř raket,Raketspor,Raketenschweife,,Raketospuroj,Rastro de cohetes,,Rakettivanat,Trainées des Roquettes,Rakéta füstnyomok,Scia del razzo,ロケットの軌跡,로켓 추진 효과,Raketsporen,Rakettspor,Wiązki Rakiet,Rastro de Foguete,Rasto dos Mísseis,Dâră Rachete,Дымовой след у ракет,Траг дима код ракета,Roket Parkurları -Blood Type,DSPLYMNU_BLOODTYPE,,,,Druh krve,Blodtype,Blut-Typ,,Sangotipo,Tipo de sangre,,Verityyli,Type de particules Sang,Vér fajta,Tipo di sangue,血の種類,혈흔 효과,Bloedtype,Blodtype,Typ Krwi,Tipo de Sangue,,Tip efecte sângeroase,Тип крови,Тип крви,Kan Grubu -Bullet Puff Type,DSPLYMNU_PUFFTYPE,,,,Druh kouře nábojů,Kuglestød type,Pistolenrauch-Typ,,Tipo de Kuglopufo,Tipo de agujero de bala,,Luotien pöllähdystyyli,Type de particules Balles,Lövedék becsapódás fajtája,Tipo di sbuffo del proiettile,弾煙の種類,탄알 피격 효과,Kogelwolvertype,Bullet Puff Type,Typ Dymu,Tipo de Ricochete de Bala,,Tip efecte pentru gloanțe,Тип дыма от пуль,Тип рикошета,Mermi Puf Tipi -Number of particles,DSPLYMNU_MAXPARTICLES,,,,Množství částic,Antal partikler,Anzahl Partikel,,Nombro da partikloj,Número de partículas,,Hiukkasten lukumäärä,Nombre de particules,Részecskék száma,Numero di particelle,パーティクルの最大数,최대 입자 수,Aantal deeltjes,Antall partikler,Liczba cząsteczek,Número de partículas,,Număr particule,Количество частиц,Број честица,Parçacık sayısı -Number of decals,DSPLYMNU_MAXDECALS,,,,Množství decalů,Antal decals,Anzahl Trefferspuren,,Nombro da dekaloj,Número de calcomanías,,Siirtokuvien lukumäärä,Number de décalques,Lövésnyomok száma,Numero di decal,デカールの最大数,최대 데칼 수,Aantal stickers,Antall dekaler,Liczba kalk,Número de decalques,,Număr autocolante,Количество декалей,Број декала,Çıkartma sayısı -Show player sprites,DSPLYMNU_PLAYERSPRITES,,,,Zobrazit hráčovy sprity,Vis spiller sprites,Zeige Spieler-Sprites,,Montri ludantspritojn,Mostrar sprites del jugador,,Näytä pelaajaspritet,Montrer les sprites joueur,Játékos sprite-ok mutatása,Mostra gli sprite del giocatore,プレイヤーの武器の表示,1인칭 무기 표시,Toon speler sprites,Vis spillerens sprites,Pokaż sprite'y gracza,Exibir sprites do jogador,,Afișare arme,Отображение спрайтов игрока,Прикажи спрајтове играча,Oyuncu sprite'larını göster -Death camera,DSPLYMNU_DEATHCAM,,,,Posmrtná kamera,Dødskamera,Todeskamera,,Mortkamerao,Cámara de muerte,,Kuolonkamera,Caméra 3ème pers à la mort,Halál kamera,Telecamera all'atto della morte,死亡時の三人称視点,사망 화면 표시,Doodscamera,Dødskamera,Kamera śmierci,Câmera de morte,Câmara da morte,Cameră de Deces,Вид от 3-го лица при смерти,Смртна камера,Ölüm kamerası -Teleporter zoom,DSPLYMNU_TELEZOOM,,,,Zoom při teleportaci,Teleporter zoom,Teleporter Zoom,,Teleportila zomo,Zoom en teletransp.,,Kaukosiirrynnän kameran zoomaus ,Zoom sur téléportation,Teleporter ráközelítés,Zoom telecamera,テレポーター使用時のズーム,순간이동 효과,Teleporter zoom,Teleporter zoom,Przybliżenie teleportowania,Zoom de teletransporte,,Apropriere Cameră la Teleportare,Увеличение при телепортации,Зум током телепортације,Işınlayıcı yakınlaştırma -Earthquake shake intensity,DSPLYMNU_QUAKEINTENSITY,,,,Intenzita zemětřesení,Intensitet af jordskælv,Erdbeben Intensität,,Egeco de tertremo,Intensidad del terremoto,,Maanjäristystehosteen voimakkuus,Intensité des séismes,Földrengés erőssége,Intensità vibrazione terremoto,地震エフェクトの激しさ,지진 효과 강도,Aardbevingsschoksintensiteit,Intensitet av jordskjelvrystelser,Siła trzęsienia ziemi,Intensidade do tremor de terremoto,,Intensitate zguduire la cutremur,Интенсивность тряски землетрясений,Интенсивност земљотреса,Deprem sarsıntı şiddeti -Interpolate monster movement,DSPLYMNU_NOMONSTERINTERPOLATION,,,,Interpolovat pohyb příšer,Interpolere monsterbevægelse,Interpoliere Monsterbewegung,,Interpoli monstro-movadon,Interpolar mov. de los monstruos,,Interpoloi hirviöiden liike,Interpolation des monstres,Szörny mozgás simítása,Interpola il movimento dei mostri,モンスターの移動補間,개체 이동 보정,Interpoleer monsterbewegingen,Interpolere monsterbevegelse,Interpolacja ruchu potworów,Interpolar movimento de monstros,,Interpolare mișcare monștri (efect vizual),Сглаживание движения монстров,Интерполирај кретање чудовишта,Canavar hareketini enterpole et -Menu dim,DSPLYMNU_MENUDIM,,,,Síla barvy pozadí v menu,Menu dæmpes,Menüabdunklung,,Menuo-malheleco,Atenuación del menú,,Valikon himmennys,Assombrissement menu,Menü homályosítása,Offuscamento menu,メニュー背景,메뉴 배경색 강도,Donkere menuachtergrond,Demp meny,Mgła w menu,Atenuação do menu,,Întunecare meniu,Затемнение фона меню,Пригушивање менија,Menü loş -Dim color,DSPLYMNU_DIMCOLOR,,,Dim colour,Barva pozadí v menu,Dim farve,Abdunklungsfarbe,,Malheleca koloro,Color de la atenuación,,Himmennysväri,Couleur de l'assombrissement,Homályosítás színe,Colore offuscamento,背景色,배경색 설정,Donkere kleur,Demp farge,Kolor mgły,Cor da atenuação,,Culoare întunecare,Цвет затемнения,Боја пригушивања,Loş renk -View bob amount while moving,DSPLYMNU_MOVEBOB,,,,Pohupování pohledu při pohybu,Vis bob-beløb under bevægelse,Waffenpendeln beim Bewegen,,Vidi kvanton de kapo-balanciĝo dum movado,Cantidad de balanceo al moverse,,Aseen heilumisvoimakkuus liikkeessä,Chaloupage arme en movement,Fegyver mozgása lépés közben,Ammontare di bob di movimento,視点揺れする移動値,이동 시 화면 흔들림 강도,Bekijk bob bedrag terwijl je beweegt,Vis bob-beløp mens du beveger deg,Dygaj kiedy się ruszasz,Quantidade de balanço durante movimento,,Mișcare cameră în timpul deplasării,Покачивание камеры при движении,Тресење камере током кретања,Hareket halindeyken bob miktarını görüntüleme -View bob amount while not moving,DSPLYMNU_STILLBOB,,,,Pohupování pohledu v klidu,"Vis bob-beløbet, mens du ikke bevæger dig",Waffenpendeln bei Nichtbewegen,,Vidi kvanton de kapo-balanciĝo dum ne movado,Cantidad de balanceo al no moverse,,Aseen heilumisvoimakkuus levossa,Chaloupage arme statique,Fegyver mozgása egy helyben,Ammontare di bob di movimento da fermo,視点揺れしない移動値,정지 시 화면 움직임 강도,Bekijk bob bedrag terwijl je niet beweegt,Vis bobmengde mens du ikke beveger deg,Dygaj kiedy się nie ruszasz,Quantidade de balanço parado,,Mișcare cameră în timpul staționării,Покачивание камеры при бездействии,Тресење камере током неактивности,Hareket etmiyorken bob miktarını görüntüleme -Weapon bob speed,DSPLYMNU_BOBSPEED,,,,Rychlost pohupování zbraně,Våben bob hastighed,Waffenpendelgeschwindigkeit,,Rapido de armilo-balanciĝo,Velocidad de balanceo de Arma,,Aseen heilumisnopeus,Vitesse du chaloupage,Fegyver mozgás sebesség,Velocità di bob dell'arma,武器揺れ速度,무기 흔들림 속도,Snelheid wapenzwaaieffect,Våpen bob hastighet,Szybkość ruchu broni,Velocidade de balanço de arma,,Viteză mișcare arme,Скорость покачивания оружия,Брзина трсења оружја,Silah bob hızı -,,Scaling,,,,,,,,,,,,,,,,,,,,,,,, -Scaling Options,SCALEMNU_TITLE,,,,Nastavení škálování rozhraní,Indstillinger for skalering,Skalierungsoptionen,,Skalo-Agordoj,Opciones de escalado,,Skaalausasetukset,Option de mise à l'échelle,Méretezési Beállítások,Opzioni di scala,スケーリング オプション,배율 설정,Schaalopties,Alternativer for skalering,Opcje skalowania,Opções de Escala,,Setări Dimensiuni,Настройки масштабирования,Подешавања размере,Ölçeklendirme Seçenekleri -Overrides for above setting,SCALEMNU_OVERRIDE,,,,Potlačení nastavení výše,Overrides for ovenstående indstilling,Spezialisierungen,,Transpasoj por ĉi-supre agordo,Anular ajuste anterior,,Ohittaa asetuksen ylhäällä,Annule les paramètres au dessus,Beállítások felülírása,Sovrascritture per i settaggi sopra,設定の上書き,위 설정을 위해 무시,Overschrijdingen voor bovenstaande instelling,Overstyrer for innstillingen ovenfor,Nadpisuje dla powyższego ustawienia,Anular configurações acima,,Suprascriere pentru setările de mai sus,Задать специальные настройки,Специјална подешавања,Yukarıdaki ayar için geçersiz kılmalar -Messages,SCALEMNU_MESSAGES,,,,Oznámení,Meddelelser,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,Messages,Üzenetek,Messaggi,メッセージ類,메시지,Berichten,Meldinger,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке,Mesajlar -Console,SCALEMNU_CONSOLE,,,,Konzole,Konsol,Konsole,,Konzolo,Consola,,Konsoli,Console,Konzol,Console,コンソール,콘솔,Console,Konsoll,Konsola,Console,Consola,Consolă,Консоль,Конзола,Konsol -Status bar,SCALEMNU_STATBAR,,,,Stavový panel,Statuslinje,Statusleiste,,Stata baro,Barra de estado,,Tilapalkki,Barre d'état,Státusz sáv,Barra di stato,ステータスバー,상태 바,Statusbalk,Statuslinje,Pasek statusu,Barra de status,Barra de estado,Bară de Stare,Строка состояния,Статусна трака,Durum çubuğu -Fullscreen HUD,SCALEMNU_HUD,,,,HUD přes celou obrazovku,HUD i fuld skærm,Vollbild-HUD,,Tutekrana HUD,HUD de pantalla completa,,Täyden ruudun tilanäyttö,ATH plein écran,Teljes képernyős HUD,HUD a pieno schermo,全画面HUD,전체화면 HUD,Volle scherm HUD,HUD i fullskjerm,HUD pełnoekranowy,HUD de tela cheia,HUD de ecrã cheio,Interfață pe Timp de Joc tip Fullscreen,Полноэкранный интерфейс,HUD преко целог екрана,Tam Ekran HUD -Alternative HUD,SCALEMNU_ALTHUD,,,,Alternativní HUD,Alternativ HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternativ HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативный интерфейс,Алтернативни HUD,Alternatif HUD -HUD preserves aspect ratio,SCALEMNU_HUDASPECT,,,,HUD zachovává poměr stran,HUD bevarer formatforholdet,HUD bewahrt Seitenverhältnisse,,HUD konservas aspekto-proporcion,HUD conserva la rel. de aspecto,,Tilanäyttö säilyttää kuvasuhteen,ATH préserve le rapport d'aspect,A HUD képarány visszaállítása,HUD preserva le proporzioni,HUDのアスペクト比維持,HUD 화면 비율 보존,HUD behoudt de beeldverhouding,HUD bevarer størrelsesforholdet,HUD zachowuje współczynnik proporcji,HUD deve preservar proporções,,Interfața pe Timp de Joc își Păstrează Aspectul,Сохранение соотношения сторон интерфейса,Сачувај пропорције HUD-а,HUD en boy oranını korur -Use default scale,SCALEMNU_USEUI,,,,Použít výchozí velikost,Brug standardskala,Benutze Standardskalierung,,Uzi defaŭltskalon,Usar escalado por defecto,,Käytä oletusmittakaavaa,Défaut,Alap arányok használata,Usa la scala di default,通常サイズを使う,기본 배율 사용,Gebruik standaardweegschaal,Bruk standard skala,Użyj domyślnej skali,Usar escala padrão,,Folosește dimensiunea implicită,Размер по умолчанию,Уобичајена размера,Varsayılan ölçeği kullan -Scale to fullscreen,SCALEMNU_USEFS,,,,Škalovat přes celou obrazovku,Skaleres til fuld skærm,Skaliere auf Vollbild,,Skali al tutekrano,Escalar a pant. completa,,Skaalaa täyteen ruutuun,Plein écran,Teljes képernyőre arányítás,Scala a pieno schermo,全画面に拡大,전체화면에 맞게 축척,Schaalbaar tot volledig scherm,Skaler til fullskjerm,Przeskaluj do pełnego ekranu,Escala de tela cheia,Escalar para ecrã cheio,Dimensionare la modul Fullscreen,Масштабировать со всем экраном,Проширење преко целог екрана,Tam ekrana ölçeklendir -Adapt to screen size,SCALEMNU_ADAPT,,,,Přizpůsobit velikosti obrazovky,Tilpasning til skærmstørrelse,Passe an Bildschirmgröße an,,Adapti al ekranamplekso,Adaptar al tamaño de pantalla,,Sovita näytön kokoon,Ecran,Képernyő mérethez alkalmazkodik,Adatta alla dimensione della schermata,画面サイズに合わせる,화면 사이즈에 맞게 축척,Aanpassen aan de grootte van het scherm,Tilpass til skjermstørrelse,Dostosuj do pełnego ekranu,Adaptar ao tamanho de tela,,Adaptează la dimensiunea ecranului,Адаптироваться к размеру экрана,Прилагоди размери екрана,Ekran boyutuna uyum sağlayın -,,HUD,,,,,,,,,,,,,,,,,,,,,,,, -HUD Options,HUDMNU_TITLE,,,,Nastavení rozhraní a HUD,HUD-indstillinger,HUD Optionen,,HUD Agordoj,Opciones del HUD,,Tilanäytön asetukset,Options ATH,HUD beállításai,Opzioni HUD,HUDオプション,HUD 설정,HUD-opties,HUD-alternativer,Opcje HUD,Opções de HUD,,Setări Interfață pe Timp de Joc,Настройки отображения информации,HUD подешавања,HUD Seçenekleri -Alternative HUD,HUDMNU_ALTHUD,,,,Alternativní HUD,Alternativ HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH Alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternativ HUD,Alternatywny HUD,HUD Alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативное отображение информации,Алтернативни HUD,Alternatif HUD -Message Options,HUDMNU_MESSAGE,,,,Oznámení,Indstillinger for meddelelser,Nachrichtenoptionen,,Mesaĝo-Agordoj,Opciones de mensajes,,Viestiasetukset,Options des Messages,Üzenet beállítások,Opzioni messaggi,メッセージの設定,메시지 설정,Berichtopties,Meldingsalternativer,Opcje wiadomości,Opções de Mensagem,,Setări Mesaje,Настройки сообщений,Подешавања порука,Mesaj Seçenekleri -User interface scale,HUDMNU_UISCALE,,,,Velikost rozhraní,Skala for brugergrænseflade,Benutzerinterfaceskalierung,,Interfaco-skalo de uzanto,Escala de la interfaz de usuario,,Käyttöliittymän skaalaus,Echelle de l'interface,Felhasználó Panel mérete,Scala l'interfaccia utente,インターフェースの大きさ,인터페이스 크기 조정,Schaal gebruikersinterface,Skalering av brukergrensesnitt,Skala interfejsu,Escala de interface de usuário,Escala de interface do utilizador,Dimensiune Interfață Utilizator,Размер интерфейса,Размера интерфејса,Kullanıcı arayüzü ölçeği -Force default crosshair,HUDMNU_FORCECROSSHAIR,,,,Vynutit výchozí zaměřovač,Tvinge standard-trådkorset,Erzwinge Standard-Fadenkreuz,,Devigi defaŭltan reteton,Forzar retícula por defecto,,Pakota oletustähtäin,Forcer Viseur par défaut,Alapcélkereszt erőltetése,Forza il mirino di default,デフォルトの照準を使う,기본 조준점 강제 설정,Forceer standaard dradenkruis,Tving frem standard trådkors,Wymuś domyślny celownik,Forçar mira padrão,,Forțare țintă implicită,Всегда стандартный прицел,Форсирај уобичајени нишан,Varsayılan artı işaretini zorla -Grow crosshair when picking up items,HUDMNU_GROWCROSSHAIR,,,,Zvětšit zaměřovač při sebrání předmětu,"Vokse trådkorset, når du samler genstande op",Größeres Fadenkreuz bei Gegenstandsaufnahme,,Grandigi reteton kiam oni prenas objektojn,Aumentar retícula al obtener obj.,Crecer retícula al obtener obj.,Suurenna tähtäintä esineitä poimiessa,Agrandir viseur en prenant un objet,A célkereszt nőjön tárgyfelvételkor,Accresci il mirino quando si raccolgono oggetti,アイテム取得時に照準を大きくする,아이템 획득 시 조준점 키우기 ,Vergroot het dradenkruis bij het oppakken van items,Utvid trådkorset når du plukker opp elementer,"Powiększ celownik, gdy podnosisz przedmioty",Aumentar mira ao pegar itens,Aumentar mira ao apanhar itens,Mărește ținta la ridicarea obiectelor,Увеличение прицела при подборе,Побољшај нишан током купљења предмета,Eşyaları alırken artı işaretini büyütün -Display nametags,HUDMNU_NAMETAGS,,,,Zobrazovat jmenovky,Viser navneskilte,Zeige Gegenstandsnamen,,Montri nometikedojn,Mostrar etiquetas,,Näytä nimitunnisteet,Afficher noms des objets,Névtábla mutatása,Mostra le targhette identificative,ディスプレイネームタグ,이름표 표시,Naamlabels weergeven,Vis navnelapper,Pokazuj nazwy przedmiotów,Exibir nomes,,Indică numele obiectelor,Указание названия предметов,Прикажи имена предмета,İsim etiketlerini gösterin -Nametag color,HUDMNU_NAMETAGCOLOR,,,Nametag colour,Barva jmenovek,Farve på navneskilte,Farbe für Gegenstandsnamen,,Nometikeda koloro,Color de las etiquetas,,Nimitunnisteen väri,Couleur des noms d'objet,Névtábla szín,Colore targhetta identificativa,ネームタグ色,이름표 색깔,Kleur naamlabel,Farge på navneskilt,Kolor nazw przedmiotów,Cor dos nomes,,Culoare nume obiecte,Цвет названия предметов,Боја имена предмета,İsim etiketi rengi -Use old ouch mug shot formula,HUDMNU_OLDOUCH,,,,Použít starý vzorec pro 'ouch' portrét,"Gammel formel for ""av"" ansigt",Alte Formel für „Autsch“-Gesicht,,Uzi maljunan formulon de aj-vizaĝo-foto,Usar formula antigua de foto de daño,,Käytä vanhaa auts-naamakuvan kaavaa,Ancien code pour l' « ouch face »,Régi sebződő fej formula használata,Mostra la formula originale del viso 'ouch',旧式ouch mug shotを使用,구형 피격 표정 스프라이트 방식 사용,"Oude formule voor ""Ouch""-gezicht",Bruk formelen for gamle forbryterbilder,Używaj starej formuły twarzy przy dostaniu obrażeń,Usar fórmula original do rosto de dor,,Utilizează modul portret vechi,Старая формула для портрета,Стара формула за приказ лика,Eski ouch oyuncu yüzü formülünü kullanın -Hexen weapon flashes,HUDMNU_HEXENFLASHES,,,,Druh bliknutí zbraní v Hexenu,Hexen-våben blinker,Hexen-Waffenblitze,,Ekbriloj de Hexen-armo,Destello armas Hexen,,Hexenin asevälähdykset,Flash d'arme dans Hexen,Hexen fegyver villanások,Bagliori armi Hexen,Hexen武器の視界色,헥센 무기 반짝임,Hexen-wapen flitsen,Hexen våpen blinker,Błysk przy podnoszeniu broni z Hexena,Flash de arma do Hexen,,Tip strălucire arme Hexen,Тип вспышки оружия в Hexen,Треперење оружја у Hexen-у,Hexen silah flaşları -Poison damage flashes,HUDMNU_POISONFLASHES,,,,Druh bliknutí při otrávení,Giftskabte skader blinker,Gift-Effekt,,Ekbriloj de venondamaĝo,Destello daño por veneno,,Myrkkyvahinkovälähdykset,Flash de poison dans Hexen,Méreg sebzés villanások,Bagliori danno da veleno,毒ダメージの視界色,독데미지 반짝임,Vergiftigingsschade knippert,Giftskade blinker,Efekt obrażeń przy zatruciu,Flash de dano por veneno,,Tip strălucire efect de otrăvire,Тип вспышки яда,Треперење током тровања,Zehir hasarı flaşları -Ice death flashes,HUDMNU_ICEFLASHES,,,,Druh bliknutí při smrti umrznutím,Isdødsblink,Eis-Tod-Effekt,,Ekbriloj de glacimorto,Destello muerte por hielo,,Jääkuolemavälähdykset,Flash de morts par glace,Jéghalál villanások,Bagliori morte da ghiaccio,氷結死の視界色,동사시 반짝임,IJsdood knippert,Isdød blinker,Błysk przy śmierci poprzez zamrożenie,Flash de morte por congelamento,,Tip strălucire deces prin înghețare,Тип вспышки при смерти от льда,Треперење током смрти од леда,Buz ölüm flaşları -Poison Buildup flashes,HUDMNU_HAZARDFLASHES,,,,Druh blikání při kumulaci jedu,Gift Buildup blinker,Kumulativer Gift-Effekt,,Ekbriloj de venonamasigo,Destello acumulación de veneno,,Myrkyn kertymisvälähdykset,Flash d'accumulation de poison,Fokozatos méreg sebzés villanások,Bagliori danno accumulato da veleno,蓄積毒の視界色,독데미지 반짝임 증강,Vergiftiging Opbouw knippert,Giftoppbygging blinker,Miganie przy nasilaniu się trucizny,Flash por acúmulo de dano por veneno,,Tip strălucire acumulare de otravă,Тип вспышки при скоплении яда,Треперење током гомилања отрова,Zehir Birikimi yanıp söner -Scaling Options,HUDMNU_SCALEOPT,,,,Škálování velikosti rozhraní,Skaleringsmuligheder,Skalierungsoptionen,,Skalo-Agordoj,Opciones de escalado,,Skaalausasetukset,Option de mise à l'échelle,Méretezés Beállítások,Opzioni di scala,スケーリング オプション,배율 설정,Schaalopties,Alternativer for skalering,Opcje skalowania,Opções de Escala,,Setări Dimensiuni,Настройки масштабирования,Подешавања размере,Ölçeklendirme Seçenekleri -Show IWAD selection dialog,MISCMNU_QUERYIWAD,,,,Zobrazit dialog pro výběr IWADu,Vis IWAD-valgdialogboks,Zeige IWAD-Auswahl,,Montri elektodialogon de IWAD,Mostrar diálogo de selección de IWAD,,Näytä IWAD-valintaikkuna,Afficher la séléction d'IWAD,IWAD kiválasztó ablak mutatása,Mostra la schermata della selezione IWAD,IWADの選択画面を表示,IWAD 게임 선택창 표시,IWAD-selectiedialoogvenster weergeven,Vis IWAD-valgdialogboks,Pokaż ekran wyboru gry (IWAD),Exibir janela de seleção de IWAD,,Afișează fereastra de selectare a jocurilor,Выбор IWAD-файла при запуске,Покажи IWAD дијалог за избор,IWAD seçim iletişim kutusunu göster -Enable cheats from all games,MISCMNU_ALLCHEATS,,,,Povolit cheaty ze všech her,Aktiver snyderier fra alle spil,Ermögliche Cheats aus allen Spielen,,Ebligi trompojn el tutaj ludoj,Activar trucos de todos los juegos,,Ota käyttöön huijauskoodit kaikista peleistä,Activer cheats de tous les jeux,Minden játék csaláskódja érvényes,Abilita tutti i cheat da tutti i giochi,全ゲームでチート使用可にする,모든 게임에 치트 허용,Laat bedriegers van alle spellen toe,Aktiver juks fra alle spill,Włącz oszustwa ze wszystkich gier,Habilitar trapaças de todos os jogos,Permitir batotas de todos os jogos,Permite codurile din toate jocurile,Читы из всех игр,Омогући читове од свих игара,Tüm oyunlardan hileleri etkinleştirin -,,Option Menus,,,,,,,,,,,,,,,,,,,,,,,, -Enable making screenshots by scripts,MISCMNU_ENABLESCRIPTSCREENSHOTS,,,,Povolit skriptům pořizovat snímky obrazovky,Aktivering af skærmbilleder ved hjælp af scripts,"Erlaube Skripts, Screenshots zu machen",,Ebligi faradon de ekrankopioj per skriptoj,Habilitar captura de pantalla por scripts,,Salli komentosarjoin otetut kuvakaappaukset,Autoriser les Scripts à prendre des captures,Szkriptek is készíthetnek képernyőképet,Abilita la cattura dello schermo tramite scripts,スクリプトからのスクショ作成を有効化,저장/불러오기 확인,Screenshots maken met behulp van scripts,Gjør det mulig å lage skjermbilder av skript,Pozwól na robienie zrzutów ekranu przez skrypty,Habilitar capturas de tela por scripts,Permitir capturas de ecrã por scripts,Posibilitate de a face poze prin scripturi,Возможность делать снимки экрана через скрипты,Омогући прављење скриншотова по скрипти,Komut dosyalarıyla ekran görüntüsü almayı etkinleştirme -Load *.deh/*.bex lumps,MISCMNU_DEHLOAD,,,,Načítat *.deh/*.bex soubory,Indlæsning af *.deh/*.bex-filer,Lade *.deh/*.bex Daten,,Ŝargi je *.deh/*.bex lumpoj,Cargar archivos *.deh/*.bex,,Lataa *.deh/*.bex-lump-tiedostot,Charger fichiers *.deh/*.bex,*.deh/*.bex lump-ok betöltése,Carica i lump *.deh/*.bex,.deh/.bexファイルを読み込む,*.deh/*.bex 럼프 파일 불러오기,*.deh/*.bex laden,Last inn *.deh/*.bex-arkiver,Załaduj dane *.deh/*.bex,Carregar lumps *.deh/*.bex,,Încarcă nodurile *.deh/*.bex,Загружать файлы *.deh/*.bex,Учитај *.deh/*.bex фајлове,.deh/*.bex topaklarını yükle -Cache nodes,MISCMNU_CACHENODES,,,,Cachovat nodes,,Nodes zwischenspeichern,,Kaŝmemoraj nodoj,Caché de nodos,,Tallenna solmut välimuistiin,Mise en cache des nodes,Node-ok cache-lése,Cache dei nodi,ノードキャッシュ,캐시 노드,Cache nodes,Bufre noder,Węzły pamięci podręcznej,Cachê de nodes,Cache de nodes,Depozitare noduri cache,Кэширование узлов,Кеширани чворови,Önbellek düğümleri -Time threshold for node caching,MISCMNU_CACHETIME,,,,Časový práh pro cachování nodes,Tidsgrænse for node-cache,Zeitschwelle für das Zwischenspeichern von Nodes,,Templimo pro kaŝmemornodi,Umbral de tiempo para caché de nodos,,Kynnysaika solmujen välimuistitallennukseen,Limite cache des nodes,Időhatár node cache-hez,Soglia di tempo per il caching dei nodi,ノードキャッシュ時間の閾値,노드 캐싱을 위한 시간 임계값 계산,Tijdsdrempel voor het cachen van nodes,Tidsterskel for nodebufring,Próg czasowy buforowania węzłów,Limite de tempo para cachê de nodes,Limite de tempo para cache de nodes,Limită de timp pentru depozitare cache,Временной порог для кэширования узлов,Временски праг за кеширање чвора,Düğüm önbelleğe alma için zaman eşiği +",いずれのBossdeathでもlevel specialを許可,어느 레벨에서든 BOSSDEATH 이벤트 허용,Laat een eventuele bossdood voor een speciaal niveau toe....,Tillat enhver bossdeath for nivå spesiell,Każda śmierć bossa liczy się jako akcja specjalna,Permitir qualquer morte de chefão para ação especial,Permitir qualquer morte de chefe para ação especial,Orice utilizare de A_BossDeath activează evenimente speciale în nivel,Любой вызов A_BossDeath активирует special уровня,Било који случај A_BossDeath активира special на нивоу,Tillåt alla bossdödsfall för specialnivå,Özel seviye için herhangi bir boss ölümüne izin ver, +Disable BOOM door light effect,CMPTMNU_NODOORLIGHT,,,,Zakázat světelný efekt dveří z BOOMu,Deaktivere BOOM dør lys effekt,Boom-Türlichteffekt deaktiviert.,,Malvalidigi pordlumo-efekton de BOOM,Desactivar efecto de luz de puerta de BOOM,,BOOM-ovivalotehoste pois käytöstä,Pas d'effet de lumière BOOM sur portes,A BOOM ajtó fény effekt kikapcsolása ,Disabilitato l'effetto Boom della luce della porta,BOOMドアライト エフェクトを無効化,붐 문간 조명보정 효과 끄기,BOOM-deurlichteffect uitschakelen,Deaktiver BOOM dør lyseffekt,Wyłącz efekt oświetlenia drzwi BOOM,Desabilitar efeito de luz de porta do BOOM,,Dezactivează efectele de lumină BOOM pentru uși,Отключить световой эффект из BOOM на дверях,Онемогући светлосни ефекат из BOOM-а на вратима,Inaktivera BOOM-dörrljuseffekten,BOOM kapı ışığı efektini devre dışı bırak, +Find neighboring light like Doom,CMPTMNU_LIGHT,,,Find neighbouring light like Doom,Nacházet nejbližší světlo jako Doom,Find nabo lys som Doom,Finde benachbartes Licht wie in Doom,,Trovi najbaran lumon kiel Doom,Encontrar luces vecinas como en Doom,,Etsi vierustava valo niin kuin Doom,Trouver prochaine texture comme DOOM,Szomszédos fényforrás keresése mint Doom-ban,Trova le luci vicine come in DOOM,DOOM式の最寄りライト検知,고전적인 조명추적 사용,Vind naburig licht zoals Doom,Finn nærliggende lys som Doom,Znajdź sąsiadujące światło jak w Doomie,Encontrar luz vizinha como em Doom,,Caută o sursă de lumină apropriată ca în Doom,Искать соседний источник света как в Doom,Нађи суседно светло као у Doom-у,Hitta närliggande ljus som Doom,Doom gibi komşu ışık bulun, +Find shortest textures like Doom,CMPTMNU_SHORTTEX,,,,Nacházet nejkratší textury jako Doom,Find korteste teksturer som Doom,Finde kurze Texturen wie in Doom,,Trovi la plej mallongajn tekstaĵojn kiel Doom,Encontrar texturas más cortas como en Doom,,Etsi lyhyimmät pintakuvioinnit niin kuin Doom,Trouver plus petite texture comme Doom,Legkisebb textúrák keresése mint Doom-ban,Trova le texture più piccole come in DOOM,DOOM式の最短テクスチャー検知,고전적인 텍스처분류 사용,Vind de kortste texturen zoals Doom,Finn korteste teksturer som Doom,Znajdź najkrótsze tekstury jak w Doomie,Encontrar menores texturas como em Doom,,Caută cele mai scurte texturi ca în Doom,Искать кратчайшие текстуры как в Doom,Нађи најкраће текстуре као у Doom-у,Hitta kortaste texturer som Doom,Doom gibi en kısa dokuları bulun, +Use buggier stair building,CMPTMNU_STAIRS,,,,Použít méně stabilní stavění schodů,Brug buggier trappe bygning,Benutze fehlerhafte Treppenbaufunktion,,Uzi pli ciman ŝtupo-konstruadon,Usar construcción defectuosa de escaleras,,Käytä viallisempaa portaanrakennusfunktiota,Construction d'escalier plus buggée,Bugosabb lépcsőépítés használata,Usa la struttura a scalinate più buggata,バグだらけの階段生成を使用,구형 계단상승 효과 사용,Gebruik buggier trapgebouw,Bruk buggier trappebygging,Użyj wadliwej funkcji budowania schodów,Usar construção defeituosa de escadas,,Utilizare mod de ridicare al scărilor incorect,Использовать неисправленное построение лестниц,Користи непоправљено грађење степеница,Använda en mer buggig trappbyggnad,Daha az doğru merdiven binası kullanın, +Use Doom's floor motion behavior,CMPTMNU_FLOORMOVE,,,Use Doom's floor motion behaviour,Použít původní chování Doomu pro pohyb podlah,Brug Dooms gulv bevægelsesadfærd,Benutze Dooms Verhalten für bewegende Böden,,Uzi konduton de Doom por plankmovo-konduto,Usar comportamiento de mov. del suelo de Doom,,Lattialiike käyttäytyy kuin Doomissa,Mouvement des sols à la DOOM,Doom jellegű padló mozgás,Adotta il comportamento di DOOM per il movimento sul pavimento,DOOMでの床の動作挙動を使用,표면이나 천장이 서로 통과가 가능함,Gebruik Doom's vloer beweging vloer,Bruk Dooms gulvbevegelsesatferd,Użyj zachowanie ruchu podłogi Dooma,Usar comportamento de mov. do chão de Doom,,Utilizare comportament de mișcare al podelelor din Doom,Поведение движения по полу из Doom,Користи Doom-ово подно моционо понашање,Använd Dooms golvrörelsebeteende,Doom'un zemin hareketi davranışını kullanın, +Use Doom's point-on-line algorithm,CMPTMNU_POINTONLINE,,,,Použít původní algoritmus bod-na-čáře z Doomu,Brug Dooms point-on-line algoritme,Benutze Dooms Punkt-auf-Linie Algorithmus,,Uzi algoritmon de Doom por trovi punkton sur linio,Usar algoritmo de punto en línea de Doom,,Käytä Doomin piste viivalla -algoritmia,Algorithme point-sur-ligne de DOOM,Doom jellegű point-on-line algoritmus,Usa l'algoritmo del 'punto giacente sulla linea' di DOOM,DOOMでのポイントライン アルゴリズム を使用,구형 선상 지점 정의법 사용,Gebruik Doom's point-on-line-algoritme,Bruk Dooms punkt-på-nett-algoritme,Użyj algorytmu punktu na linii z Dooma,Usar algorítmo de ponto-em-linha de Doom,,Utilizare algoritm point-on-line din Doom,Использовать алгоритм «точка на линии» из Doom,Користи Doom-ов point-on-line алгоритам,Använda Dooms algoritm för punkt-till-linje-arbete,Doom'un point-on-line algoritmasını kullanın, +Level exit can be triggered more than once,CMPTMNU_MULTIEXIT,,,,Odchod z levelu může být spuštěn vícekrát,Level exit kan udløses mere end én gang,Ausgang kann mehr als einmal aktiviert werden,,Nivelelirejo povas esti ekagigita pli ol unufoje,La salida de nivel puede ser activada más de una vez,,Tasosta poistumisen voi laukaista useammin kuin kerran,Sortie niveau utilisable plusieures fois,Pálya kijárat többször is triggerelhető,L'uscita del livello può attivarsi più di una volta,Exitを複数回起動出来る,레벨 출구 트리거 한 번 이상 작동,Niveau-uitgang kan meer dan eens worden geactiveerd,Nivåutgang kan utløses mer enn én gang,Wyjście z poziomu może być uruchomione więcej niż raz,Saída de fase pode ser ativada mais de uma vez,Saída de nível pode ser ativada mais de uma vez,Ieșirea nivelului poate fi activată de mai multe ori,Выходы могут быть активированы более одного раза,Излаз нивоа може бити активиран више пута,Nivåutgång kan utlösas mer än en gång,Seviye çıkışı birden fazla kez tetiklenebilir, +Physics Behavior,CMPTMNU_PHYSICSBEHAVIOR,,,Physics Behaviour,Fyzika,Fysik-adfærd,Physik-Verhalten,,Fizikokonduto,Comportamiento de la física,,Fysiikan käyttäytyminen,Comportement Physique,Fizika viselkedés,Comportamento della fisica,物理の挙動,물리 관련 설정,Fysica gedrag,Fysikkoppførsel,Zachowanie Fizyki,Comportamento de Física,Comportamento das Físicas,Comportament fizică,Поведение физики,Физичко понашање,Fysikbeteende,Fiziksel Davranış, +Actors are infinitely tall,CMPTMNU_NOPASSOVER,,,,Objekty jsou nekonečně vysoké,Aktører er uendeligt høje,Akteure sind unendlich hoch,,Aktoroj estas senfine altaj,Los actores son infinitamente altos,,Oliot ovat äärettömän korkeita,Hauteur des acteurs infinie,Személyek végtelen magasak,Gli attori sono infinitamente alti,アクターの上下には入れない,무한으로 키가 큰 개체,Acteurs zijn oneindig lang,Skuespillere er uendelig høye,Aktorzy są nieskończenie wysocy,Atores são infinitamente altos,,Actorii au înălțime infinită,Объекты бесконечно высокие,Глумци су бесконачно велики,Aktörerna är oändligt höga.,Aktörler sonsuz uzunlukta, +Boom scrollers are additive,CMPTMNU_BOOMSCROLL,,,,Boom posuvníky jsou aditivní,Boom scrollers er additive,Boom-Scroller sind additiv,,Skrolantaj Teksturaj de Boom estas adicia,Los scrollers de Boom son aditivos,,Boom-vierittimet ovat additiivisia,Glisseurs BOOM additifs,Boom scroller-ek összeadódnak,Le barre di scorrimento BOOM sono additivi,BOOM型スクロール床を適用,붐 스크롤러 누적법 사용,Boom scrollers zijn additief,Boom scrollere er additive,Przewijane tekstury Boom są addytywne,Scrollers de Boom são aditivos,,Elementele derulante BOOM sunt aditive,Конвейеры из BOOM складываются с собой,Boom скролери су додаци,Boom scrollers är additiva,Bom kaydırıcıları katkı maddelidir, +Cannot travel straight NSEW,CMPTMNU_BADANGLES,,,,Nelze se pohybovat přímo na SJVZ,Kan ikke rejse lige NSØV,Bewegungsrichtungen direkt NSOW nicht möglich,,Ne eblas veturi rekte NSEW,Emular error de mal ángulo,,Liikkuminen puhtaasti pääilmansuuntiin mahdotonta,Direction pure NSEO impossible,Nem haladhat egyenes vonalban NSEW,Non si può viaggiare esattamente nelle direzioni cardinali,NSEW直進走法の不許可,전방위 방향으로 이동 불가,Kan niet rechtdoor reizen NZOW,Kan ikke reise rett NSØV,Pozwól na błąd złego kąta,Impossível se deslocar reto em direções cardeais,Impossível se deslocar em frente em direções cardeais,Interzice deplasarea liniară NSEW,Запрещено двигаться прямо на С/Ю/З/В,Немогуће путовати право на NSEW,Kan inte resa rakt NSÖV,Düz seyahat edemez KGDB, +Enable wall running,CMPTMNU_WALLRUN,,,,Povolit wall running (běhaní pomocí zdi),Aktiver vægløb,Ermögliche Wandrennen,,Ebligi kuradon sur muroj,Activar correr por muros,,Salli seinäjuoksu,Activer Wallrunning,Falon futás engedélyezése,Wall running abilitata,壁伝い走行を許可,벽면가속이동 허용,Wandloop mogelijk maken,Aktiver veggkjøring,Włącz szybkie bieganie wzdłuż ścian,Habilitar corrida por paredes,Permitir corrida pelas paredes,Permite fuga cu ajutorul pereților (Wallrun),Включить быстрый бег вдоль стен (wallrunning),Омогући пролажење кроз зида,Aktiverar väggkörning,Duvar çalışmasını etkinleştirin, +Raven scrollers use original speed,CMPTMNU_RAVENSCROLL,,,,Raven posuvníky používají původní rychlost,Raven scrollers bruger original hastighed,Raven-Scroller benutzen originale Geschwindigkeit,,Skrolantaj teksturoj de Raven uzas originalan rapidecon,Los scrollers de Raven usan la velocidad original,,Ravenin vierittimet liikkuvat alkuperäisnopeudella,Glisseurs Raven à leur vitesse originale,Raven scroller-ek eredeti sebességűek,Le barre di scorrimento Raven usano la velocità originale,Raven式スクロール床を原作準拠にする,구형 헤러틱/헥센 스크롤러 사용,Raven scrollers gebruiken originele snelheid,Raven scrollers bruker original hastighet,Przwijane tekstury podłogi Raven używają oryginalną prędkość,Scrollers da Raven usam velocidade original,,Elementele derulante Raven folosesc viteza originală,Конвейеры из Raven используют неизменённую скорость,Raven скролери користе оригиналну брзину,Raven-skrollers använder ursprunglig hastighet,Kuzgun kaydırıcılar orijinal hızı kullanır, +Self ref. sectors don't block shots,CMPTMNU_TRACE,,,,Sebe-odkazující sektory neblokují střely,Selvreflekterende sektorer blokerer ikke for skud,Selbstreferenzierende Sektoren blockieren keine Schüsse,,Sinreferencantaj sektoroj ne baras pafojn,Sectores autoreferidos no bloquean los disparos,,Itseensä viittaavat sektorit eivät estä laukauksia,Secteur autoréférencé ne bloque pas les tirs,Saját ref.sektorok nem blokkkolják a lövéseket,Settori autoreferenziati non bloccano i colpi,Self ref.Sectorsは射撃を阻害しない,자기 참조 섹터가 총탄을 막지 않음,Zelfreferentie sectoren blokkeren geen schoten,Selvrefererende sektorer blokkerer ikke skudd.,Sektory odnoszoce się do siebie nie blokują strzałów,Setores autorreferidos não bloqueiam tiros,,Sectoarele cu referință proprie blochează focurile,Самоссылающиеся секторы не блокируют выстрелы,Самореф. сектори не блокирају пуцњеве,Självbetjäningssektorer blockerar inte skott.,Kendi kendine hakemlik yapan sektörler atışları engellemez., +Use Doom code for hitscan checks,CMPTMNU_HITSCAN,,,,Použít původní Doom kód pro kontrolu hitscanů,Brug Doom-code til hitscan-kontrol,Benutze Original-Doom-Code für Hitscan-Checks,,Uzi kodon de Doom por batskanoj-kontrolado,Usar código de Doom para revisión de hitscan,,Käytä Doomin osumislaskentakoodia,Vérification Hitscan à la DOOM,Doom kód használata a hitscan ellenőrzéshez,Usa il codice DOOM per il controllo sugli hitscan,DOOM式の即着弾判定を使用,구형 총탄 판정법 사용,Gebruik Doom-code voor hitscancontroles,Bruk Doom-kode for treffkontroll,Użyj kod Dooma dla hitscanu,Usam código de Doom para verificação de hitscan,Usar código de Doom para verificação de hitscan,Utilizează cod din Doom pentru a verifica coliziunea focurilor,Использовать код из Doom для проверок зон мгновенного попадания (hitscan),Користи Doom код за хитскен проверу,Använd Doom-kod för hitscan-kontroller,Hitscan kontrolleri için Doom kodunu kullanın, +Use Doom heights for missile clipping,CMPTMNU_MISSILECLIP,,,,Použít původní výšky z Doomu pro kolizi raket,Brug Doom-højder til missilklipper,Benutze Doom-Größen für Kollisionen mit Projektilen,,Uzi altojn de Doom por misilo-tonadoj,Usar altura de Doom para desplazamiento de misiles,,Käytä Doomin korkeuksia lentokappaleiden törmäyksissä,Clipping des missiles à la DOOM,Doom féle magasság használata a rakáta találathoz,Usa le altezze di DOOM per il clipping del razzo,ミサイル通過にDOOM heightsを使用,구형 발사체 판정법 사용,Gebruik Doom hoogtes voor het knippen van raketten,Bruk Doom-høyder for missilklipping,Użyj wysokości Dooma dla przenikania pocisków,Usar alturas de Doom para colisão de projéteis,,Utilizează metoda de verificare a înălțimilor din Doom,Использовать высоту из Doom для столкновения ракет,Користи Doom висине за клиповање ракета,Använd Doom-höjder för missilklippning.,Füze kırpma için Doom yüksekliklerini kullanın, +Rendering Behavior,CMPTMNU_RENDERINGBEHAVIOR,,,Rendering Behaviour,Vykreslování,Rendering Adfærd,Renderverhalten,,Bildigado-Konduto,Comportamiento de renderizado,,Hahmonnuksen käyttäytyminen,Comportement d'affichage,Renderelés viselkedése,Comportamento della grafica,レンダリングの挙動,렌더링 관련 설정,Rendering gedrag,Gjengivelse av oppførsel,Zachowanie Renderowania,Comportamento de Renderização,,Comportament Video,Поведение обработки,Понашање рендовања,Beteende vid rendering,Rendering Davranışı, +Draw polyobjects like Hexen,CMPTMNU_POLYOBJ,,,,Vykreslovat polyobjekty jako Hexen,Tegn polyobjekter som Hexen,Zeichne Polyobjekte wie in Hexen,,Desegni plurangulo-objektojn kiel Hexen,Dibujar poliobjetos como en Hexen,,Piirrä polyobjektit niin kuin Hexen,Dessiner les Polyobjets comme Hexen,Hexen féle tárgy kirajzolás,Polioggetti disegnati come Hexen,Hexen式のPolyObjects描画,구형 폴리오브젝트 시스템 사용,Teken polyobjecten zoals Hexen,Tegn polyobjekter som Hexen,Rysuj poliobiekty jak w Hexenie,Desenhar poliobjetos como em Hexen,,Afișează poliobiectele precum în Hexen,Отрисовка полиобъектов как в Hexen,Цртај поли-објекте као Hexen,Rita polyobjekt som Hexen,Hexen gibi çoklu nesneler çizin, +Ignore Y offsets on masked midtextures,CMPTMNU_MASKEDMIDTEX,,,,Ignorovat Y posuny na průhledných mid-texturách,Ignorer Y offsets på maskerede midtextures,Ignoriere Y-Offsets bei transparenten Mitteltexturen,,Malatenti Y-deŝovaĵojn sur maskitaj midtekstaĵoj,Ignorar offsets de eje Y en texturas medias enmascaradas,,Älä huomioi Y-siirroksia peitetyissä keskipintakuvioinneissa,Offsets Y ignorés sur les textures centrales,Függőleges mozgatás ignorálása a maszkolt midtextúráknál,Ignora gli offset Y sulle midtexture mascherate,マスクされた中間テクスチャーのY軸ずれを無効,이면선분의 중앙 텍스쳐의 Y축값 무시,Negeer Y compensaties op gemaskerde middentexturen,Ignorer Y-forskyvninger på maskerte mellomteksturer,Ignoruj przesunięcia osi Y na zamaskowanych teksturach po środku,Ignorar offsets de Y em texturas centrais,,Ignoră offsetul Y de pe texturile 3D mascate,Игнорировать смещение по вертикали на средних текстурах с маской,Игнориши Y нагиб на маскиране средње текстуре,Ignorera Y-förskjutningar på maskerade midtexturer.,Maskelenmiş orta dokularda Y ofsetlerini yoksay, +Invert sprite sorting,CMPTMNU_SPRITESORT,,,,Obrátit řazení spritů,Inverter sprite-sortering,Umgekehrte Spritesortierung,,Inversigi ordigadon de mov-rastrumoj,Invertir ordenado de sprites,,Käännä spritelajittelu,Ordres des sprites inversé,Sprite rendzés megfordítása,Ordinamento sprite invertito,反転スプライトの並び替え,구형 스프라이트 겹침 판정 사용,Sprite sorteren omkeren,Inverter sprite-sortering,Odwróć sortowanie sprite'ów,Inverter ordem de sprites,,Inversare sortare sprite-uri,Обратить порядок сортировки спрайтов,Обрнуто сортирање спрајтова,Invertera sprite-sortering,Sprite sıralamasını ters çevir, +Sound Behavior,CMPTMNU_SOUNDBEHAVIOR,,,Sound Behaviour,Zvuk,Adfærd med lyd,Sound-Verhalten,,Sonkonduto,Comportamiento de sonido,,Äänen käyttäytyminen,Comportement Sonore,Hang viselkedés,Comportamento suono,音の挙動,효과음 관련 설정,Geluidsgedrag,Lydoppførsel,Zachowanie dźwięku,Comportamento de Áudio,,Comportament Sunet,Поведение звуков,Понашање звука,Ljudbeteende,Ses Davranışı, +Cripple sound for silent BFG trick,CMPTMNU_SOUNDSLOTS,,,,Zmrzačit zvukový systém pro trik tichého BFG,Lyd forkrøblet ved lydløst BFG-trick,Amputiere Soundsystem für geräuschloses BFG,,Kripligi sonon por lertaĵo de silenta BFG,Estropear sonido para truco de BFG silencioso,,Rampauta äänijärjestelmä hiljaista BFG-temppua varten,Massacrer le son pour BFG silencieux,Bénító hang a halk BFG trükknél,Blocca il suono per il trucco del BFG silenzioso,消音BFG技の為にサウンドを重複させない,소음 BFG 효과 허용,Kreupel geluid voor een stille BFG-truc,Krymp lyd for stille BFG-triks,Obetnij dźwięk dla triku cichego BFG,Bloquear som para o truque da BFG silenciosa,,Taie sunetul pentru trucul BFG silențios,Ограничить звуки ради трюка бесшумной BFG,Онемогући звук за тихи ВЈП трик,Förlamning av ljudet vid tyst BFG-trick,Sessiz BFG numarası için sesi kısın, +Don't let others hear your pickups,CMPTMNU_SILENTPICKUP,,,,Ostatní tě neslyší sbírat předměty,Lad ikke andre høre dine pickupper,Andere können deine Gegenstandsaufnahmen nicht hören,,Ne lasi aliulojn aŭdas viajn prenadojn,No dejar a otros oír tus recogidas,,"Älä anna muiden kuulla, kun poimit esineitä",Autres joueurs n'entendent pas les ramassages,Mások ne hallhassák a tárgy felvételeidet,Non consentire agli altri giocatori di sentire le tue raccolte,他人にピックアップ音を聞かせない,상대방의 습득 효과음 청음 불가,Laat anderen uw pick-ups niet horen,Ikke la andre høre pickupene dine,"Nie pozwalaj by inni słyszeli, że podnosisz przedmioty",Não permitir que outros ouçam sua coleta de itens,Não permitir que outros ouçam sua aquisição de itens,Nu permite celorlalți să audă sunetul ridicării obiectelor,Запрещать другим слышать звук подбора предметов,Не допусти да други чују ваше скупљање,Låt inte andra höra dina pickuper,Başkalarının manyetiklerinizi duymasına izin vermeyin, +Inst. moving floors are not silent,CMPTMNU_SILENTINSTANTFLOORS,,,,Okamžitě pohybující se podlahy nejsou tiché,Inst. bevægelige gulve er ikke lydløse,Böden mit sofortiger Bewegung machen Geräusche,,Tujaj movantaj plankoj ne estas silentaj,Suelos inst. movibles no son silenciosos,,Silmänräpäyksellisesti liikkuvat lattiat eivät ole hiljaisia,Sols à movement instanté font du bruit,Halk isntant mozgó padló,I pavimenti istantanei in movimento non sono silenziosi,即時稼働するFloorsの音を鳴らさない,즉발식 이동표면 소음효과 제거,Direct bewegende vloeren zijn niet geruisloos,Øyeblikkelig bevegelige gulv er ikke stille,Nagle przesuwające się podłogi nie są ciche,Pisos que se deslocam instantâneamente emitem som,,Podelele care se mișcă instant nu sunt silențioase,Мгновенно двигающиеся полы не беззвучны,Инстантно покрећући нивои нису тихи,Inst. rörliga golv är inte tysta,Inst. hareketli zeminler sessiz değildir, +Sector sounds use center as source,CMPTMNU_SECTORSOUNDS,,,Sector sounds use centre as source,Sektorové zvuky používají jeho střed jako zdroj,Sektorlyde bruger centrum som kilde,Sektor-Sounds benutzen den Mittelpunkt des Sektors,,Sektorsonoj uzas centron kiel fonto,Sonidos de sector usan el centro como fuente,,Sektoriäänet käyttävät keskipistettä lähteenä,Sons secteur utilisent centre comme origine,Center forrás használata a szektor hangoknál,I suoni usano il centro dei settori come punto di sorgente,Sectorサウンドをフロア中央で鳴らす,섹터 중심부를 효과음의 원천으로 판정,Sectorgeluiden gebruiken centrum als bron,Sektorlyder bruker senter som kilde,Dźwięki sektorów używają środka jako źródła,Sons de setor são emitidos a partir do centro,,Sunetele sectoarelor au ca sursă centrul,Звуки секторов используют центр как источник,Секторски звукови су центрисани,Sektorljud använder centrum som källa,Sektör sesleri kaynak olarak merkezi kullanır, +Sounds stop when actor vanishes,CMPTMNU_SOUNDCUTOFF,,,,"Utnout zvuky, když jejich objekt zmizí","Lydene stopper, når aktøren forsvinder","Sounds werden beendet, wenn der Akteur verschwindet",,"Sonoj ĉesas, kiam aktoro malaperas",El sonido se detiene cuando el actor desaparece,,"Äänet lakkaavat, kun olio katoaa",Sons s'arrêtent quand acteur disparait,Hangok megszűnnek az eltűnéskor,I suoni si fermano quando gli attori svaniscono,アクター消滅で音を止める,효과음 원천 소멸 시 효과음도 중단,Geluiden stoppen wanneer de acteur verdwijnt,Lyder stopper når skuespilleren forsvinner,Dźwięki zatrzymują się kiedy aktor znika,Som para quando o ator desaparece,,Sunetele se opresc când actorul sursă dispare,Останавливать звуки при исчезновении объекта,Звукови престају кад глумац нестане,Ljudet upphör när aktören försvinner,Aktör ortadan kaybolduğunda sesler kesilir, +Use original sound target handling,CMPTMNU_SOUNDTARGET,,,,Použít původní chování pro uchování zvukového cíle,Brug original lydmålhåndtering,Benutze originale Behandlung für das Sound-Ziel,,Uzi originalan manipuladon por soncelo,Usar manejo de destino de sonido original,,Käytä alkuperäistä äänen kohteen käsittelyä,Ciblage des sons selon algorithme original,Eredeti hang célpont kezelés,Targeting dei suoni in base all'algoritmo originale,元のサウンドターゲット処理を使用,구형 섹터 경고음 보존법 사용,Gebruik originele geluidsdoelwitverwerking,Bruk original lydmålhåndtering,Użyj oryginalną obsługę celu dźwięku,Usar método original de destino de som,,Procesare originală pentru sursele de sunet,Неизменённая обработка источников звука,Користи оригинални звук руковања метом,Använd original ljudmålshantering,Orijinal ses hedefi kullanımını kullanın, +Scripted teleports don't trigger sector actions,CMPTMNU_TELEPORT,,,,Skriptované teleportace neaktivují sektorové akce,Scriptede teleporteringer udløser ikke sektorhandlinger,Teleports in Skripten lösen keine Sektoraktionen aus,,Skriptitaj teleportoj ne ekagigas sektor-agojn,Telepuertos por script no activan acciones del sector,,Käsikirjoitetut kaukosiirtimet eivät laukaise sektoritoimintoja,Téléports par scripts n'activent pas le secteur,Szkriptelt teleportok nem triggerelnek szektor műveletet,I teletrasporti scriptati non attivano le azioni del settore,スクリプトテレポートではSector actionsを起こさない,순간이동 스크립트는 섹터 이벤트 발동 불가능,De gescripte teleports leiden niet tot acties in de sector.,Skriptede teleporter utløser ikke sektorhandlinger,Oskryptowane teleporty nie włączają akcji sektora,Teletransportes scriptados não ativam ações de setor,,Teleportările scriptate nu declanșează acțiuni în sectoare,Скриптовые телепорты не запускают действия секторов,Скриптовани телепортери не активирају секторске радње,Skriptbaserade teleporter utlöser inte sektoråtgärder.,Komut dosyası ışınlanmaları sektör eylemlerini tetiklemiyor, +Non-blocking lines can be pushed,CMPTMNU_PUSHWINDOW,,,,Neblokující čáry mohou být zmáčknuty,Ikke-blokerende linjer kan skubbes,Nicht-blockende Linien können angestoßen werden,,Nehaltantaj linioj povas esti premitaj,Líneas sin bloquear pueden ser presionadas,,Ei-tukkivia viivoja voi työntää,Lignes non-bloquantes sont non-poussables,Nem blokkoló vonalak megnyomhatóak,Le linee non bloccanti possono essere spinti,Non-bloking linesを押せる,비차단 선분 밀어내기 가능,Niet-blokkerende lijnen kunnen worden geduwd,Ikke-blokkerende linjer kan skyves,Nieblokujące ściany mogą być pchnięte,Linhas não-bloqueadoras podem ser pressionadas,,Liniile care nu blochează pot fi împinse înapoi,Неблокирующие линии можно задействовать перемещением сквозь,Неблокирабе линје могу бити гурнуте,Linjer som inte blockerar kan skjutas,Engelleyici olmayan hatlar itilebilir, +Enable buggy CheckSwitchRange behavior,CMPTMNU_CHECKSWITCHRANGE,,,,Povolit nestabilní chování pro CheckSwitchRange,Aktiver den fejlbehæftede CheckSwitchRange-adfærd,Erlaube fehlerhaftes CheckSwitchRange Verhalten,,Ebligi cimajn kondutojn por CheckSwitchRange,Permitir comportamiento viejo de CheckSwitchRange,,Ota käyttöön viallinen CheckSwitchRange-käyttäytyminen,Fonction CheckSwitchRange buggée,Bugos CheckSwitchRange mechanika bekapcsolás,Abilita il comportamento buggato del CheckSwitchRange,バグのあるCheckSwitchRangeを許可,구형 CheckSwitchRange 판정법 사용,Buggy CheckSwitchSwitchRange gedrag inschakelen,Aktiver fejlbehæftet CheckSwitchRange-adfærd,Zezwól na zepsute zachowanie CheckSwitchRange,Permitir comportamento CheckSwitchRange defeituoso,,Comportament incorect pentru CheckSwitchRange,Включить ошибочное поведение CheckSwitchRange,Омогући баговано CheckSwitchRange понашање,Aktivera det felsägande CheckSwitchRange-beteendet,Hatalı CheckSwitchRange davranışını etkinleştirin, +Enable buggy Strife railing,CMPTMNU_RAILINGHACK,,,,Povolit nestabilní zábradlí ze Strifu,Aktiver buggy Strife railing,Fehlerhafte Strife-Geländer,Ενεργοποιηση σπασμένης συμπεριφοράς καγκέλον για το Strife,Ebligi ciman reladon de Strife,Activar barandillas bugueadas de Strife,,Ota käyttöön Strifen vialliset kaiteet,Barrières buggées pour Strife,Bugos Strife korlát bekapcsolása,Abilita il railing buggato di Strife,バグのあるStrife railingを許可,고전 스트라이프 철책 적용,Buggy mogelijk maken Strijk-reling,Aktiver fejlbehæftet Strife rekkverk,Włącz wadliwe bariery Strife'a,Permitir railing defeituoso do Strife,Permitir railing defeituoso do Strife,Utilizare comportament grilaj Strife incorect,Вернуть ошибочные перила в Strife,Омогући непоправљену ограду у Strife-у,Aktivera felande Strife-Räcken,Yanlış Strife korkuluğunu etkinleştirin, +No vertical thrust from explosions,CMPTMNU_EXPLODE1,,,,Exploze neodhazují do výšky,Ingen vertikal fremdrift fra eksplosioner,Keine vertikale Bewegung durch Explosionen,Καθόλου κατακόρυφη ώθηση απο εκρήξεις,Neniuj vertikalaj puŝoj de eksplodoj,No causar empuje vertical en explosiones,,Ei pystysuuntaista työntövoimaa räjähdyksistä,Explosions sans propulsion verticale,A robbanásnak nincs függőleges lökése,Nessuna spinta verticale dalle esplosioni,爆風は垂直方向全域に影響しない,폭발시 수직방향 반동 억제,Geen verticale stuwkracht van explosies,Ingen vertikal skyvekraft fra eksplosjoner,Brak pionowego nacisku od eksplozji,Desativar propulsão vertical das explosões,,Fără împingere verticală de la explozii,Взрывы не отбрасывают вверх/вниз,Нема вертикалног гурања од експлозија,Ingen vertikal dragkraft från explosioner,Patlamalardan kaynaklanan dikey itme yok, +Use original Doom explosion behavior,CMPTMNU_EXPLODE2,,,Use original Doom explosion behaviour,Používat původní chování explozí Doomu,Brug original Doom eksplosionsadfærd,Benutze Original Doom Explosionsverhalten,Συμπεριφορά εκρήξεων απο το πρωτότυπο Doom,Uzi originalan konduton de Doom por eksplodoj ,Usar comportamiento de explosiones del DOOM original,,Käytä Doomin alkuperäisiä räjähdysten käyttäytymissääntöjä,Utiliser comportement Doom original,Eredeti Doom robbanás mechanika használata,Usa l'originale comportamento dell'esplosione di DOOM,Doom本来の爆発動作を使用する,고전 둠의 폭발 반발력 적용,Gebruik het originele Doom explosiegedrag,Bruk original Doom-eksplosjonsatferd,Użyj oryginalnego zachowania eksplozji z Dooma,Usar comportamento original de explosões do Doom,,Utilizare comportament original pentru explozii,Использовать модель взрывов из Doom,Користи оригнално Doom понашање за експлозије,Använd det ursprungliga Doom-explosionsbeteendet,Orijinal Doom patlama davranışını kullanın, +,,player,,,,,,,,,,,,,,,,,,,,,,,,,, +Red,PLYRMNU_RED,,,,Červená,Rød,Rot,,Ruĝo,Rojo,,Punainen,Rouge,Piros,Rosso,赤の量,빨강,Rood,Rød,Czerwony,Vermelho,,Roșu,Красный,Црвева,Röd,Kırmızı, +Green,PLYRMNU_GREEN,,,,Zelená,Grøn,Grün,,Verdo,Verde,,Vihreä,Vert,Zöld,Verde,緑の量,초록,Groen,Grønn,Zielony,Verde,,Verde,Зелёный,Зелена,Grön,Yeşil, +Blue,PLYRMNU_BLUE,,,,Modrá,Blå,Blau,,Bluo,Azul,,Sininen,Bleu,Kék,Blu,青の量,파랑,Blauw,Blå,Niebieski,Azul,,Albastru,Синий,Плава,Blå,Mavi, +Class,PLYRMNU_PLAYERCLASS,,,,Třída,Klasse,Klasse,,Klaso,Clase,,Luokka,Classe,Kaszt,Classe,役職,클래스,Klasse,Klasse,Klasa,Classe,,Clasă,Класс,Класа,Klass,Sınıf, +Skin,PLYRMNU_PLAYERSKIN,,,,,,,,Aspekto,Aspecto,,Ulkoasu,,Kinézet,,外装,스킨,Uiterlijk,Hud,Wygląd,Aparência,,Textură,Облик,Скин,Hud,Cilt, +Switch on pickup,PLYRMNU_SWITCHONPICKUP,,,,Přepnout zbraň při sebrání,Tænd for pickup,Waffenwechsel bei Aufnahme,,Ŝanĝi armon ĉe preno,Elegir arma al coger una,Elegir arma al agarrar una,Vaihda uuteen aseeseen,Dernière arme,Felvételkor váltás,Cambio d'arma quando si riceve,武器取得時に持ち替え,무기 획득 시 바꿈,Gebruik wapen meteen na oppakken,Slå på pickup,Przełącz po podniesieniu,Mudar de arma ao pegar,,Schimbare armă la ridicare,Смена оружия при подборе,Пребаци на покупљено оружје,Slå på pickupen,Elinize aldığınızda silahı değiştirin, +Press \cjSPACE,PLYRMNU_PRESSSPACE,,,,Zmáčkni \cjMEZERNÍK,Tryk på \cjSPACE,\cjLeertaste,,Premu \cjSPACON,Presiona \cjEspacio,,Paina \cjVÄLI \cfnähdäk-,\cjEspace,Nyomj \cjSPACE -t,Premi \cjSPAZIO,\cjスペースキー,회전: \cjSPACE바,Druk op \cjSPACE,Trykk \cjSPACE,\cjSPACJA,Aperte \cjESPAÇO,,Apasă \cjSPACE,Нажмите \cjПРОБЕЛ,Притисните \cjSPACE,Tryck på \cjSPACE,\cjSPACE tuşuna basın, +to see front,PLYRMNU_SEEFRONT,,,,pro pohled zepředu,for at se forsiden,für Frontansicht,,por vidi vian antaŭon,para verte de frente,,sesi etupuolen,Pour L'Avant,Előre nézni,per vedere avanti,で前面を表示,캐릭터 앞모습,om de voorkant te zien,for å se forsiden,by widzieć przód,para ver a frente,,pentru a vedea fața,для просмотра спереди,да видите спреда,för att se framsidan,ön tarafı görmek için, +to see back,PLYRMNU_SEEBACK,,,,pro pohled zezadu,for at se bagsiden,für Rückansicht,,por vidi vian malantaŭon,para verte por detrás,,sesi takapuolen,Pour l'Arrière,Hátra Nézni,per vedere dietro,で背面を表示,캐릭터 뒷모습,om terug te kijken,for å se baksiden,by widzieć tył,para ver atrás,,pentru a vedea spatele,для просмотра сзади,да видите позади,för att se baksidan,geri görmek için, +Vertical Bullet Spread,PLYRMNU_VERTSPREAD,,,,Svislý rozptyl střelby,Lodret kuglespredning,Vertikale Streuung,,Vertikala Kugla Disvastiĝo,Dispersión vertical de la bala,,Pystysuora luodin leviäminen,Écartement vertical des balles,Vertikális fegyver szórás,Diffusione dei proiettili in verticale,垂直方向の散弾,,Verticale kogelspreiding,Vertikal kulespredning,Pionowy rozrzut pocisków,Dispersão vertical das balas,,Recul Vertical Gloanțe,Вертикальный разброс пуль,,Vertikal kulspridning,Dikey Mermi Yayılımı, +,,controls,,,,,,,,,,,,,,,,,,,,,,,,,, +Weapon Zoom,CNTRLMNU_ZOOM,,,,Přiblížení zbraně,Våbenzoom,Waffenzoom,Ζοομ,Armilzumo,Zoom del arma,,Aseen kiikaritähtäys,Zoom avec Arme,Ráközelítés fegyverrel,Zoom dell'arma,ズーム,무기 조준,Wapen Zoom,Våpen Zoom,Przybliżenie Broni,Zoom da Arma,,Zoom Armă,Приближение,Зум,Vapenzoom,Silah Yakınlaştırma, +Weapon State 1,CNTRLMNU_USER1,,,,Akce zbraně 1,Våbenstatus 1,Waffen-Aktion 1,Κατάσταση Όπλου 1,Armilstato 1,Estado del arma 1,,Aseen tila 1,Etat d'Arme 1,Fegyver 1. állapot,Stato dell'arma 1,武器特殊動作 1,무기 상태 1,Wapenstaat 1,Våpenstat 1,Stan Broni 1,Estado da Arma 1,,Poziție Armă 1,Функция первого оружия,Стање оружја (1),Vapen Åtgärd 1,Silah Durumu 1, +Weapon State 2,CNTRLMNU_USER2,,,,Akce zbraně 2,Våbenstatus 2,Waffen-Aktion 2,Κατάσταση Όπλου 2,Armilstato 2,Estado del arma 2,,Aseen tila 2,Etat d'Arme 2,Fegyver 2. állapot,Stato dell'arma 2,武器特殊動作 2,무기 상태 2,Wapenstaat 2,Våpenstat 2,Stan Broni 2,Estado da Arma 2,,Poziție Armă 2,Функция второго оружия,Стање оружја (2),Vapen Åtgärd 2,Silah Durumu 2, +Weapon State 3,CNTRLMNU_USER3,,,,Akce zbraně 3,Våbenstatus 3,Waffen-Aktion 3,Κατάσταση Όπλου 3,Armilstato 3,Estado del arma 3,,Aseen tila 3,Etat d'Arme 3,Fegyver 3. állapot,Stato dell'arma 3,武器特殊動作 3,무기 상태 3,Wapenstaat 3,Våpenstat 3,Stan Broni 3,Estado da Arma 3,,Poziție Armă 3,Функция третьего оружия,Стање оружја (3),Vapen Åtgärd 3,Silah Durumu 3, +Weapon State 4,CNTRLMNU_USER4,,,,Akce zbraně 4,Våbenstatus 4,Waffen-Aktion 4,Κατάσταση Όπλου 4,Armilstato 4,Estado del arma 4,,Aseen tila 4,Etat d'Arme 4,Fegyver 4. állapot,Stato dell'arma 4,武器特殊動作 4,무기 상태 4,Wapenstaat 4,Våpentilstand 4,Stan Broni 4,Estado da Arma 4,,Poziție Armă 4,Функция четвёртого оружия,Стање оружја (4),Vapen Åtgärd 4,Silah Durumu 4, +Fly / Swim up,CNTRLMNU_MOVEUP,,,,Letět / plavat vzhůru,Flyv / svøm op,Fliegen / Hochschwimmen,Πέτα/Κολύμπα πάνω,Flugi/Naĝi supren,Volar/Nadar arriba,,Lennä / Ui ylös,Voler/Nager en haut,Repülés / Felfele úszás,Vola / Nuota in alto,飛行/水泳時 上昇,위로 날기 / 해엄치기,Omhoog vliegen/zwemmen omhoog,Fly / Svøm opp,Lot / Pływanie w górę,Voar / Nadar para cima,,Zbor / Înot în Sus,Лететь/плыть вверх,Лети/пливај нагоре,Flyga/simma upp,Uç / Yüz yukarı, +Fly / Swim down,CNTRLMNU_MOVEDOWN,,,,Letět / plavat dolů,Flyv / svøm ned,Fliegen / Runterschwimmen,Πέτα/Κολύμπα κάτω,Flugi/Naĝi malsupren,Volar/Nadar abajo,,Lennä / Ui alas,Voler/Nager en bas,Repülés / Lefele úszás,Vola / Nuota in basso,飛行/水泳時 下降,아래로 날기 / 해엄치기,Naar beneden vliegen/zwemmen,Fly / Svøm ned,Lot / Pływanie w dół,Voar / Nadar para baixo,,Zbor / Înot în Jos,Лететь/плыть вниз,Лети/пливај надоле,Flyga/simma ner,Uç / Yüz aşağı, +Stop flying,CNTRLMNU_LAND,,,,Přestat létat,Stop flyvning,Landen,Σταμάτα πέταμα,Ĉesi flugadon,Dejar de volar,,Lopeta lentäminen,Arrêter de voler,Repülés abbahagyása,Stop al volo,飛行停止,비행 정지,Stoppen met vliegen,Slutt å fly,Przestań latać,Parar de voar,,Încetare Zbor,Приземлиться,Престани летети,Sluta flyga,Uçmayı bırak, +Keyboard look,CNTRLMNU_KEYBOARDLOOK,,,,Pohled klávesnicí,Tastatur-look,Tastatur-Blick,Κατακόρυφο κοίταχμα (Πλητρoλόγιο),Klavar-rigardo,Vista con teclado,,Näppäinkatselu,Vue au clavier,Billentyűzettel való nézelődés,Modalità vista con la tastiera,キー視点上下化,키보드 룩,Toetsenbordaanzicht,Tastatur utseende,Rozglądanie się klawiaturą,Vista com o teclado,,Utilizare Tastatură pentru a Privi în Jur,Обзор клавиатурой,Гледај тастатуром,Tangentbordsutseende,Klavye görünümü, +Strife Popup Screens Controls,CNTRLMNU_POPUPS_TITLE,,,,Ovládání vyskakovacích oken ve Strife,Strife Popup-skærme Kontrolelementer,Strife Popup Steuerung einstellen,,Ŝprucfenestraĵoj de Strife,Ventanas emergentes de Strife,,Strifen ponnahdusruutujen ohjausasetukset,Contrôles Popups Strife,Strife Felugró Ablak Irányítás,Controlli Schermate popup di Strife,Strifeポップアップ表示設定,스트라이프 팝업 화면 조작,Strife Popup Schermen Bediening,Strife Popup-skjermer Kontroller,Ustaw Klawisze Okienek Strife'a,Comandos de Popups do Strife,Controlos de Popups do Strife,Control pentru Mesaje Strife,Управление всплывающими окнами Strife,Искакајући прикази контроле у Strife-у,Strife Popup-skärmar Kontroller,Strife Açılır Ekran Kontrolleri, +Team say,CNTRLMNU_TEAMSAY,,,,Říct týmu,Team sige,Teamkommunikation,Πές στην ομάδα,Teama diro,Hablar al equipo,,Sano omille,Parler (équipe),Üzenet csapattársaknak,Parla nella squadra,チーム内発言,팀 채팅하기,Zeggen in team,Lag si,Powiedz do Drużyny,Fala (equipe),Falar à equipa,Vorbește cu Echipa Proprie,Сообщение команде,Пиши тиму,Laget säger,Ekip diyor ki, +Drop item,CNTRLMNU_DROPITEM,,,,Odhodit předmět,Smid genstand,Gegenstand fallen lassen,Πέτα Aντικείμενο,Faligi objekton,Soltar objeto,,Pudota varuste,Lâcher objet,Tárgy eldobása,Fai cadere l'oggetto,"アイテムを捨てる +",아이템 버리기,Item laten vallen,Slipp element,Upuść przedmiot,Largar item,,Aruncare Obiect,Бросить предмет,Баци предмет,Släpp föremål,Eşyayı bırak, +Query item,CNTRLMNU_QUERYITEM,,,,Informace o předmětu,Forespørgsel element,Informationen über Gegenstand,,Informpeti objekton,Consultar objeto,,Hae varustetta,Vérifier objet,Rákérdez a tárgy eldobásnál,Indaga sull'oggetto,アイテム名を表示,아이템 정보 표시,Vraag item op,Spør om element,Zapytaj o przedmiot,Consultar item,,Cercetare Obiect,Проверить предмет,Прикажи предмет,Fråga efter objekt,Sorgu öğesi, +Drop weapon,CNTRLMNU_DROPWEAPON,,,,Odhodit zbraň,Smid våben,Waffe fallen lassen,Πέτα Όπλο,Faligi armilon,Soltar arma,,Pudota ase,Lâcher arme,Fegyver eldobása,Butta l'arma,武器を捨てる,무기 버리기,Wapen laten vallen,Slipp våpen,Upuść broń,Largar arma,,Aruncare Armă,Выбросить оружие,Баци оружје,Släpp vapen,Silahı bırak, +Other,CNTRLMNU_OTHER,,,,Ostatní,Andre,Andere,Άλλα,Alia,Otros,,Muu,Autres,Más,Altro,その他,그 외 조작,Andere,Annet,Inne,Outro,,Altele,Прочее,Остало,Annat,Diğer, +Coop spy,CNTRLMNU_COOPSPY,,,,Co-op špehování,Coop-spion,Coop Spion,,Kunlabora spiono,Espía cooperativo,,Vakoile joukkuetovereita,Espionner Coéquiper,Coop leskelődés,Spia cooperativa,他者視点,멀티플레이 카메라,Coöpspion,Coop-spion,Śledź (kooperacja),Visualização coop,,Vedere prin Ochii Altui Jucător,Вид от другого игрока,Поглед од другог играча,Spion för samarbete,Coop casusu, +Strife Popup Screens,CNTRLMNU_POPUPS,,,,Vyskakovací okna Strife,Strife popup-skærme,Strife Popups,,Ŝprucfenestraĵoj de Strife,Ventanas emergentes de Strife,,Strifen ponnahdusruudut,Popups de Strife,Strife Felugró Ablakok,Schermate popup di Strife,Strife ポップアップ画面,스트라이프 팝업 화면,Strife Popup Schermen,Strife Popup-skjermer,Okienka Strife'a,Popup do Strife,,Mesaje Strife,Всплывающие окна Strife,Информација у Strife-у,Strife Popup-skärmar,Strife Açılır Ekranları, +Mission objectives,CNTRLMNU_MISSION,,,,Úkoly mise,Mål for en mission,Missionsziele,Στόχοι Αποστολής,Taskoceloj,Objetivos de misión,,Tehtävätavoitteet,Objectifs de Mission,Küldetési célok,Obiettivi della missione,ミッションオブジェクト,임무 목록,Missiedoelen,Oppdragets mål,Cele misji,Objetivos da missão,,Obiectivele Misiunii,Текущее задание,Циљ мисије,Mål för uppdraget,Görev hedefleri, +Keys list,CNTRLMNU_KEYS,,,,Seznam klíčů,Liste over nøgler,Schlüsselliste,Λίστα Κλειδιών,Ŝlosilolisto,Lista de llaves,,Avainlista,Liste des Clés,Kulcslista,Lista delle chiavi,キー類リスト,열쇠 목록,Lijst van toetsen,Liste over nøkler,Lista kluczy,Lista de teclas,,Listă Chei,Список ключей,Списка кључева,Lista över nycklar,Anahtar listesi, +Weapons/ammo/stats,CNTRLMNU_STATS,,,,Zbraně/munice/staty,Våben/ammo/stats,Waffen/Munition/Statistik,Οπλα/Πυρομαχικά/Στατιστικές,Armiloj/municio/stataĵoj,Armas/Munición/Estadísticas,,Aseet/ammukset/tila,"Statistiques, armes et munitions",Fegyver/lőszer/statisztika,Armi/ammunizioni/statistiche,武器 / 弾薬 / 状態,무기/탄약/통계 목록,Wapens/ammo/statistieken,Våpen/ammunisjon/statistikk,Bronie/amunicja/statystyki,Armas/munição/estatísticas,,Arme/muniție/statistici,"Оружие, патроны и показатели",Оружје/муниција/статистика,Vapen/ammo/statistik,Silahlar/mühimmat/istatistikler, +Toggle Scoreboard,CNTRLMNU_TOGGLESCOREBOARD,,,,Přepnout tabulku skóre,Skift Scoreboard,Punktetafel an/aus,Ενεργοποίηση Πίνακα Σκόρ,Baskuligi poentotabulon,Alternar Marcador,,Pistetaulun vaihtokytkin,Afficher Scores (alterner),Eredményjelző kapcsoló,Abilita/disabilita tabella punteggio,スコアボード切替,점수창 토글,Scorebord aan/uit,Veksle resultattavle,Włącz / Wyłącz tablicę wyników,Ativar/desativar placar,Ligar/desligar Pontuação no Ecrã,Comutator pentru Tabela de Marcaj,Таблица очков (перекл.),Табела (без држања),Växla resultattavla,Skor Tablosunu Değiştir, +Lookspring,MOUSEMNU_LOOKSPRING,,,,Automatické vystředění pohledu,Centret automatisk,Automatisch zentrieren,,Rigardsalto,Mirar con ratón,,Katseenpalautin,Recentrer après Vue Souris,,,視点水平化,마우스룩 시점 초기화,Automatisch centraliseren,Sentrer automatisk,Automatyczne Wyśrodkowanie,Centralizar automaticamente,Centrar automáticamente,Mișcare a jucătorului prin mouse,Передвижение мышью,Покрет мишем,Centrum automatiskt,Merkez otomatik olarak, +Lookstrafe,MOUSEMNU_LOOKSTRAFE,,,,Použít myš k pohybu do stran,Flyt sidelæns med musen,Seitwärts bewegen mit der Maus,,Rigardturnmovo,Mirar con movimiento,,Sivuttaisastuntapalautin,Mouvement Latéral par Souris,,,視点横移動化,마우스룩 좌우 이동,Zijwaartse muisbeweging,Flytt sidelengs med musen,Unikanie przy użyciu myszki,Deslocamento lateral com o mouse,Deslocamento lateral com o rato,Mișcare în diagonală cu mouse,Движение боком мышью,Стрејф мишем,Flytta i sidled med musen,Fare ile yana doğru hareket ettirin, +,,Map colors,,,,,,,,,,,,,,,,,,,,,,,,,, +Background,MAPCOLORMNU_BACKCOLOR,,,,Pozadí,Baggrund,Hintergrund,,Fono,Fondo,,Tausta,Fond,Háttér,Sfondo,背景,배경,Achtergrond,Bakgrunn,Tło,Fundo,,Fundal,Фон,Позадина,Bakgrund,Arka plan, +You,MAPCOLORMNU_YOURCOLOR,,,,Ty,Du,Du,,Vi,Tú,,Sinä,Votre couleur,Te,Tu,自分,당신,,Du,Ty,Você,Tu,Tu,Вы,Ти,Du,Sen, +1-sided walls,MAPCOLORMNU_WALLCOLOR,,,,Jednostranné zdi,1-sidede vægge,Einseitige Wände,,1-flankaj muroj,Paredes de 1 lado,,Yksipuoliset seinät,Murs à 1 côté,1 oldalú falak,Muri unilaterali,壁,단면 벽들,1-zijdige wanden,1-sidige vegger,Jednostronne ściany,Paredes de 1 lado,,Pereți cu o singură față,Односторонние стены,Једнострани зид,1-sidiga väggar,1 taraflı duvarlar, +2-sided walls with different floors,MAPCOLORMNU_FDWALLCOLOR,,,,Oboustranné zdi s různými podlahami,2-sidede vægge med forskellige gulve,Zweiseitige Wände mit unterschiedlicher Bodenhöhe,,2-flankaj muroj kun malsamaj plankoj,Paredes de 2 lados con pisos distintos,,Kaksipuoliset seinät eroavilla lattiakorkeuksilla,Murs à 2 côtés avec différents sols,2 oldalú falak különböző padlókkal,Muri bilaterali con pavimenti diversi,高低差のある床,다른 층 추가된 양면 벽들,2-zijdige wanden met verschillende vloeren,2-sidige vegger med forskjellige gulv,Dwustronne ściany z innymi piętrami,Paredes de 2 lados com pisos diferentes,,Pereți cu două fețe si podele diferite,Двусторонние стены,Двострани зид са различитим нивоима,2-sidiga väggar med olika golv,Farklı zeminlere sahip 2 taraflı duvarlar, +2-sided walls with different ceilings,MAPCOLORMNU_CDWALLCOLOR,,,,Oboustranné zdi s různými stropy,2-sidede vægge med forskellige lofter,Zweiseitige Wände mit unterschiedlicher Deckenhöhe,,2-flankaj muroj kun malsamaj plafonoj,Paredes de 2 lados con techos distintos,,Kaksipuoliset seinät eroavilla kattokorkeuksilla,Murs à 2 côtés avec différents plafonds,2 oldalú falak különböző plafonnal,Muri bilaterali con soffitti diversi,高低差のある天井,다른 천장 추가된 양면 벽들,2-zijdige wanden met verschillende plafonds,2-sidige vegger med forskjellige tak,Dwustronne ściany z innymi sufitami,Paredes de 2 lados com tetos diferentes,,Pereți cu două fețe si tavane diferite,Двусторонние стены с разными потолками,Двострани зид са различитим плафонима,2-sidiga väggar med olika tak,Farklı tavanlara sahip 2 taraflı duvarlar, +2-sided walls with 3D floors,MAPCOLORMNU_EFWALLCOLOR,,,,Oboustranné zdi s 3D podlahami,2-sidede vægge med 3D-gulve,Zweiseitige Wände mit 3D-Ebenen,,2-flankaj muroj kun 3D-plankoj,Paredes de 2 lados con suelos 3D,,Kaksipuoliset seinät kolmiulotteisilla lattioilla,Murs à 2 côtés avec sols 3d,2 oldalú falak 3D-s padlókkal,Muri bilaterali con 3D floor,多重床,3D 층 추가된 양면 벽들,2-zijdige wanden met 3D-vloeren,2-sidige vegger med 3D-gulv,Dwustronne ściany z piętrami 3D,Paredes de 2 lados com pisos 3D,,Pereți cu două fețe si podele 3D,Двусторонние стены с разными полами,Двострани зид са 3D нивоима,2-sidiga väggar med 3D-golv,3D zeminli 2 taraflı duvarlar, +Map grid,MAPCOLORMNU_GRIDCOLOR,,,,Mřížka,Kortgitter,Kartengitter,,Mapkrado,Cuadrícula del mapa,,Kartan ruudukko,Quadrillage,Pálya szél,Griglia mappa,マップグリッド,맵 격자,Kaart raster,Kartrutenett,Siatka mapy,Grade do mapa,Grelha do mapa,Grilă hartă,Цвет сетки,Мапа координатне мреже,Kartnät,Harita ızgarası, +Center point,MAPCOLORMNU_XHAIRCOLOR,,,Centre point,Středobod,Midterpunkt,Mittelpunkt,,Centra punkto,Punto central,,Keskipiste,Point Central,Pálya közepe,Punto centrale,中心点,중간 지점,Middenpunt,Midtpunkt,Środek,Ponto central,,Punct în centru,Курсор,Централна тачка,Centrumpunkt,Merkez noktası, +Not-yet-seen walls,MAPCOLORMNU_NOTSEENCOLOR,,,,Neobjevené zdi,"Vægge, der endnu ikke er synlige",Ungesehene Wände,,Vidotaj muroj,Paredes sin ver,,Tutkimattomat seinät,Murs non découvers,Még nem látott falak,Muri ancora da scoprire,未見の壁,안 본 벽들,Nog niet zichtbare wanden,Vegger som ennå ikke er sett,Jeszcze niewidziane ściany,Paredes não vistas até o momento,,Ziduri încă neobservate,Необнаруженные стены,Неоткривени зидови,Väggar som ännu inte har setts,Henüz görülmemiş duvarlar, +Locked doors,MAPCOLORMNU_LOCKEDCOLOR,,,,Zamčené dveře,Låste døre,Verschlossene Türen,,Ŝlositaj pordoj,Puertas bloqueadas,,Lukitut ovet,Portes verouillées,Zárt ajtók,Porte bloccate,鍵の掛かったドア,잠긴 문들,Gesloten deuren,Låste dører,Zablokowane drzwi,Portas trancadas,,Uși închise,Запертые двери,Закључана врата,Låsta dörrar,Kilitli kapılar, +Teleporter to the same map,MAPCOLORMNU_INTRALEVELCOLOR,,,,Teleportér,Teleporter til samme kort,Teleporter,,Teleportilo al la sama mapo,Teletransporte al mismo mapa,,Kaukosiirrin samaan tasoon,Téléporteurs (même niveau),Ugyanarra a pályára teleportálás,Teletrasporto nella stessa mappa,テレポーター,같은 맵에 텔레포터 추가,Teleporter naar dezelfde niveau,Teleporter til samme kart,Teleporter do tej samej mapy,Teletransportador para o mesmo mapa,,Teleportor către aceeași hartă,Телепорт в пределах уровня,Телепортер до истог нивоа,Teleporter till samma karta,Aynı haritaya ışınlayıcı, +Teleporter to a different map,MAPCOLORMNU_INTERLEVELCOLOR,,,,Teleportér do jiného levelu,Teleporter til et andet kort,Teleporter in ein anderes Level,,Teleportilo al alia mapo,Teletransporte a un mapa diferente,,Kaukosiirrin eri tasoon,Téléporteurs (autre niveau),Másik pályára teleportálás,Teletrasporto in una mappa diversa,別マップへのテレポーター,다른 맵에 텔레포터 추가,Teleporter naar een andere niveau,Teleporter til et annet kart,Teleporter do innej mapy,Teletransportador para outro mapa,,Teleportor către altă hartă,Телепорт на другой уровень,Телепортер до различитог нивоа,Teleporter till en annan karta,Farklı bir haritaya ışınlayıcı, +Secret sector,MAPCOLORMNU_SECRETSECTORCOLOR,,,,Skrýš,Hemmelig sektor,Geheimer Sektor,,Sekreta sektoro,Sector secreto,,Salasektori,Secteur Secret,Rejtekhely szektora,Settore segreto,シークレット,비밀 섹터,Geheime sector,Hemmelig sektor,Sekretny sektor,Setor secreto,,Sector secret,Тайный сектор,Тајни сектор,Hemlig sektor,Gizli sektör, +Unexplored secret,MAPCOLORMNU_UNEXPLOREDSECRETCOLOR,,,,Neobjevená skrýš,Uudforsket hemmelighed,nicht gefundener geheimer Sektor,,Neesplorita sekreto,Secreto sin explorar,,Tutkimaton sala,Secret non révélé,Még fel nem fedezett rejtekhely,Segreto non esplorato,未知のシークレット,발견하지 않은 비밀,Onontgonnen geheim,Uutforsket hemmelighet,Niezbadany sekret,Segredo não-explorado,,Secret neexplorat,Необнаруженный тайник,Ноткривена тајна,Oexploaterad hemlighet,Keşfedilmemiş sır, +Special trigger lines,MAPCOLORMNU_SPECIALWALLCOLOR,,,,Akční čáry,Særlige udløserlinjer,Spezielle Linien,,Specialaj ekagilo-linioj,Líneas especiales de activación,,Erikoislaukaisinviivat,Lignes d'actions spéciales,Speciális trigger vonalak,Linee di attivazione speciali,特殊トリガー,특수 트리거 선,Speciale trekkerlijnen,Spesielle utløserlinjer,Specjalne linie przełączników,Linhas de ativação especiais,,Linii declașatoare speciale,Специальные спусковые линии,Специјалне линије окидача,Särskilda utlösningslinjer,Özel tetik hatları, +Cheat Mode,MAPCOLORMNU_CHEATMODE,,,,Cheatovací režim,Snyd-tilstand,Cheat-Modus,,Tromp-Reĝimo,Modo de truco,,Huijaustila,Mode Cheat,Csalás mód,Modalità cheat,チートモード時,치트 모드,Bedriegingsmodus,Juksemodus,Tryb oszustwa,Modo trapaça,Modo de Batota,Modul Trișor,Чит-режим,Чит мод,Fuskläge,Hile Modu, +Invisible 2-sided walls,MAPCOLORMNU_TSWALLCOLOR,,,,Neviditelné oboustranné zdi,Usynlige 2-sidede vægge,Unsichtbare zweiseitige Wände,,Nevideblaj 2-flankaj muroj,Paredes de 2 lados Invisibles,,Näkymättömät kaksipuoliset seinät,Murs à 2 côtés invisibles,Láthatatlan 2 oldalú falak,Muri invisibili bilaterali,表示されないline,투명한 양면 벽,Onzichtbare 2-zijdige wanden,Usynlige 2-sidige vegger,Niewidzialne dwustronne ściany,Paredes invisíveis de 2 lados,,Pereți cu două fețe invizibili,Невидимые двусторонние стены,Невидљиви двострани зидови,Osynliga 2-sidiga väggar,Görünmez 2 taraflı duvarlar, +Secret walls,MAPCOLORMNU_SECRETWALLCOLOR,,,,Tajné zdi,Hemmelige vægge,Geheime Wände,,Sekretaj muroj,Paredes secretas,,Salaiset seinät,Murs Secrets,Titkos falak,Muri segreti,シークレットの壁,비밀 벽,Geheime muren,Hemmelige vegger,Sekretne ściany,Paredes secretas,,Pereți ascunși,Тайные стены,Тајни зидови,Hemliga väggar,Gizli duvarlar, +Actors,MAPCOLORMNU_THINGCOLOR,,,,Objekty,Skuespillere,Akteure,,Aktoroj,Actores,,Oliot,Acteurs,Játékos,Attori,アクター,개체,Acteurs,Skuespillere,Aktorzy,Atores,,Actori,Объекты,Актори,Skådespelare,Aktörler, +Monsters,MAPCOLORMNU_MONSTERCOLOR,,,,Příšery,Monstre,Monster,,Monstroj,Monstruos,,Hirviöt,Monstres,Szörnyek,Mostri,モンスター,적들,,Monstre,Potwory,Monstros,,Monștri,Монстры,Чудовишта,Monster,Canavarlar, +Non-counting Monsters,MAPCOLORMNU_NONCOUNTINGMONSTERCOLOR,,,,Nepočítané příšery,Ikke-tællende monstre,nicht gezählte Monster,,Nenombradaj Monstroj,Monstruos no contados,Monstruos sin contar,Ei-laskettavat hirviöt,Monstres non comptés,Nem számolt szörnyek,Mostri non contati,非カウントモンスター,킬수에 포함 되지 않는 적들,Niet-tellende Monsters,Ikke-tellende monstre,Niezliczane Potwory,Monstros não contados,,Monștri neacoperiți de numărătoare,Неучитываемые монстры,Не рачунајући чудовишта,Icke-räknande monster,Sayılamayan Canavarlar, +Friends,MAPCOLORMNU_FRIENDCOLOR,,,,Přátelé,Venner,Freunde,,Amikoj,Amigos,,Omat,Amis,Barátok,Amici,仲間,친구들,Vrienden,Venner,Przyjaciele,Amigos,,Prieteni,Дружественные,Пријатељи,Vänner,Arkadaşlar, +Items,MAPCOLORMNU_ITEMCOLOR,,,,Předměty,Genstande,Gegenstände,,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,아이템들,Artikelen,Gjenstander,Przedmioty,Itens,,Obiecte,Предметы,Предмети,Föremål,Eşyalar, +Count Items,MAPCOLORMNU_COUNTITEMCOLOR,,,,Počítané předměty,Tælle genstande,gezählte Gegenstände,,Nombri Objektojn,Objetos contados,Conteo de objetos,Laske esineet,Objets comptés,Tárgyak számolása,Oggetti contati,カウント対象アイテム,아이템 계산,Tellen,Telle elementer,Zlicz przedmioty,Itens contados,,Numără obiectele,Учитываемые предметы,Рачунајући предмети,Räkna objekt,Sayım Öğeleri, +Overlay Mode,MAPCOLORMNU_OVERLAY,,,,Překryvný režim,Overlay-tilstand,Überlagerungsmodus,,Surmeto-Reĝimo,Modo sobrepuesto,,Projisointitila,Mode surimpression,Overlay mód,Modalità sovrapposizione,オーバーレイモード,오버레이 모드,Overlaadmodus,Overleggsmodus,Tryb Nakładki,Modo de sobreposição,,Mod acoperit,Прозрачный режим,Провидна аутомапа,Överlagringsläge,Kaplama Modu, +Overlay Cheat Mode,MAPCOLORMNU_OVCHEATMODE,,,,Překryvný cheatovací režim,Overlay snydetilstand,Überlagerungsmodus Cheats,,Surmeto-Tromp-Reĝimo,Sobreposición modo de truco,,Projisointihuijaustila,Mode Cheat Surimpression,overlay csaló mód,Modalità cheat sovrapposizione,オーバーレイ チートモード,치트 모드 오버레이,Overlaadmodus Cheats,Overlegg-juksemodus,Tryb Nakładki Oszustwa,Modo trapaça de sobreposição,Modo Batota de Sobreposição,Mod acoperit trișor,Прозрачный чит-режим,Провидни читови,Överlagrat fuskläge,Kaplama Hile Modu, +Portal Overlays,MAPCOLORMNU_PORTAL,,,,Portálové překryvy,Portal-overlejringer,Portalüberlagerung,,Portalo-Surmetoj,Sobreposición de portal,,Portaaliprojisoinnit,Portails superposés,Portál overlay-ek,Sovrapposizioni del portale,ポータル オーバーレイ,포탈 오버레이,Portaaloverlays,Portal-overlegg,Nakładanie się Portali,Sobreposição de portais,,Acoperiri portaluri,Порталы в прозрачном режиме,Провидни портали,Överlagringar i portalen,Portal Kaplamaları, +,,Messages,,,,,,,,,,,,,,,,,,,,,,,,,, +Messages,MSGMNU_TITLE,,,,Nastavení oznámení,Meddelelser,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,,Üzenetek,Messaggi,メッセージ類,메시지들,Berichten,Meldinger,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке,Meddelanden,Mesajlar, +Show messages,MSGMNU_SHOWMESSAGES,,,,Zobrazit oznámení,Vis meddelelser,Zeige Nachrichten,,Montri mesaĝojn,Mostrar mensajes,,Näytä viestit,Afficher messages,Üzenetek mutatása,Mostra messaggi,メッセージ表示,메시지 표시,Berichten tonen,Vis meldinger,Pokaż wiadomości,Exibir mensagens,,Afișare mesaje,Отображение сообщений,Прикажи поруке,Visa meddelanden,Mesajları göster, +Show obituaries,MSGMNU_SHOWOBITUARIES,,,,Zobrazit oznámení o smrtích,Vis dødsannoncer,Zeige Todesanzeigen,,Montri nekrologojn,Mostrar obituarios,,Näytä kuolinviestit,Afficher avis de décès,Halálok mutatása,Mostra i necrologi,訃報表示,사망 메시지 표시,Doodsbrieven tonen,Vis dødsannonser,Pokaż nekrologi,Exibir obituários,,Afișare necrologuri,Отображение некрологов,Прикажи читуље,Visa dödsannonser,Ölüm ilanlarını göster, +Show secret notifications,MSGMNU_SHOWSECRETS,,,,Zobrazit zprávy o skrýších,Vis hemmelige meddelelser,Zeige Geheimnismeldung,,Montri sciigojn de sekretoj,Mostrar notificación de secretos,,Ilmoita salojen löytymisestä,Afficher secrets,Titkos üzenetek mutatása,Mostra le notifiche dei segreti,シークレット発見表示,비밀 알림 표시,Geheime meldingen tonen,Vis hemmelige meldinger,Pokaż wiadomości znalezienia sekretu,Exibir notificação de segredos,,Afișare notificări pentru secrete,Отображение сообщений о тайниках,Прикажи тајне нотификације,Visa hemliga meddelanden,Gizli bildirimleri göster, +Minimum message level,MSGMNU_MESSAGELEVEL,,,,Minimální úroveň oznámení,Mindste beskedniveau,Min. Nachrichtenanzeigestufe,,Minimuma nivelo de mesaĝoj,Nivel mínimo de mensaje,,Pienin viestintätaso,Niveau de message minimum,Milyen üzenet jelenjen meg,Numero di messaggi minimo,最小メッセージレベル,메시지 축소량,Minimaal berichtenniveau,Minste meldingsnivå,Poziom minimalnych wiadomości,Nível mínimo de mensagem,,Nivel minim de afișare mesaje,Минимальный уровень сообщений,Минимум левел порука,Minsta nivå för meddelanden,Minimum mesaj seviyesi, +Message Colors,MSGMNU_MESSAGECOLORS,,,Message Colours,Barva oznámení,Farver på meddelelser,Nachrichtenfarben,,Mesaĝkoloroj,Colores de los mensajes,,Viestien värit,Couleur des messages,Üzenet színek,Colore dei messaggi,メッセージ色,메시지 색상,Bericht Kleuren,Meldingsfarger,Kolory Wiadomości,Cores de mensagem,,Culori Mesaje,Цвета сообщений,Боје порука,Färger för meddelanden,Mesaj Renkleri, +Item Pickup,MSGMNU_ITEMPICKUP,,,,Sebrání předmětu,Afhentning af varer,Genommene Gegenstände,,Objektoprenado,Coger objetos,Agarrar objetos,Esineen poimiminen,Objets ramassés,Tárgy felvétele,Raccolta oggetti,アイテム取得,아이템 획득,Puntafhaling,Henting av element,Podniesienie Przedmiotu,Coleta de item,Aquisição de Itens,Ridicare obiecte,Подбор предмета,Покупити предмет,Upphämtning av objekt,Bir eşyayı almak, +Obituaries,MSGMNU_OBITUARIES,,,,Oznámení o úmrtí,Dødsannoncer,Todesanzeigen,,Nekrologoj,Obituarios,,Kuolinviestit,Avis de décès,Halálok,Necrologi,死亡時メッセージ,사망 메시지,Doodsbrieven,Nekrologer,Nekrologi,Obituários,,Necrologuri,Некрологи,Читуље,Dödsannonser,Ölüm İlanları, +Critical Messages,MSGMNU_CRITICALMESSAGES,,,,Kritická oznámení,Kritiske meddelelser,Kritische Nachrichten,,Gravaj Mesaĝoj,Mensajes críticos,,Tärkeät viestit,Messages d'erreur,Fontos üzenetek,Messaggi critici,致命的なメッセージ,중요한 메시지,Kritische berichten,Kritiske meldinger,Wiadomości krytyczne,Mensagens críticas,,Mesaje Critice,Важные сообщения,Критичне поруке,Kritiska meddelanden,Kritik Mesajlar, +Chat Messages,MSGMNU_CHATMESSAGES,,,,Chatová oznámení,Chat-meddelelser,Chatnachrichten,,Babilmesaĝoj,Mensajes del chat,,Keskusteluviestit,Message de Chat,Chat üzenetek,Messaggi chat,チャットメッセージ,채팅 메시지,Chatberichten,Chat-meldinger,Wiadomości czatu,Mensagens de chat,,Mesaje Conversație,Сообщения в чате,Ћаскања,Chatt-meddelanden,Sohbet Mesajları, +Team Messages,MSGMNU_TEAMMESSAGES,,,,Týmová oznámení,Hold-meddelelser,Teamnachrichten,,Teammesaĝoj,Mensajes del equipo,,Joukkueen viestit,Messages d'équipe,Csapat chat üzenetek,Messaggi chat di squadra,チームメッセージ,팀 채팅 메시지,Team Berichten,Team-meldinger,Wiadomości czatu drużynowego,Mensagens de equipe,Mensagens de Equipa,Mesajele Echipei Proprii,Командные сообщения в чате,Тимске поруке,Meddelanden till laget,Ekip Mesajları, +Centered Messages,MSGMNU_CENTEREDMESSAGES,,,Centred Messages,Oznámení na střed,Centrerede meddelelser,Zentrierte Nachrichten,,Centritaj Mesaĝoj,Mensajes centrados,,Keskitetyt viestit,Messages centrés,Üzenet középre igazítása,Messaggi centrati,スクリプトメッセージ,중간에 위치한 메시지,Gecentreerde berichten,Sentrerte meldinger,Wyśrodkowane wiadomości,Mensagens centralizadas,Mensagens Centradas,Mesaje Centrate,Центрированные сообщения,Централне поруке,Centrerade meddelanden,Merkezli Mesajlar, +Screenshot messages,MSGMNU_SCREENSHOTMESSAGES,,,,Oznámení o snímcích obrazovky,Beskeder med skærmbilleder,Screnshot-Meldungen,,Mesaĝoj de ekrankopio,Mensajes de captura de pantalla,,Kuvakaappausviestit,Messages de capture d'écran,Képernyőkép készítés visszajelzés,Messaggi di cattura schermo,スクショメッセージ,스크린샷 메시지,Screenshot berichten,Skjermbilde-meldinger,Wiadomości o zrobieniu zrzutu ekranu,Mensagens de captura de tela,Mensagen de captura de ecrã,Mesaje Capturi Ecran,Сообщения о снимках экрана,Скриншот поруке,Meddelanden med skärmdump,Ekran görüntüsü mesajları, +Detailed save messages,MSGMNU_LONGSAVEMESSAGES,,,,Detailní oznámení o uložené hře,Detaljerede beskeder om lagring,Detaillierte Speicher-Meldungen,,Detalaj konservmesaĝoj,Mensajes detallados de guardado,,Yksityiskohtaiset tallennusviestit,Messages de sauvegarde détailés,Részletes mentési információ,Messaggi sui dettagli di salvataggio,詳細なセーブメッセージ,자세한 저장 메시지,Gedetailleerde berichten voor op te slaan,Detaljerte lagringsmeldinger,Szczegółowe wiadomości o zapisie,Mensagens detalhadas de salvamento,Mensagens detalhadas de gravação,Mesaje detaliate pentru salvări,Подробные сообщения о сохранениях,Детаљно сачуване поруке,Detaljerade meddelanden om sparande,Ayrıntılı kaydetme mesajları, +Developer message mode,MSGMNU_DEVELOPER,,,,Vývojářská oznámení,Meddelelsestilstand for udviklere,Entwickler-Modus,,Reĝimo de mesaĝoj por programistoj,Modo de mensajes de desarrollador,,Pelinkehittäjäviestitila,Mode de Développement,Fejlesztői üzenetek,Modalità messaggi per sviluppatore,開発者用モード,개발자 메시지 모드,Berichtenmodus voor ontwikkelaars,Meldingsmodus for utviklere,Tryb wiadomości deweloperskich,Modo de mensagens de desenvolvedor,,Mod mesaje pentru dezvoltator,Режим сообщений для разработчиков,Поруке девелопера,Meddelandeläge för utvecklare,Geliştirici mesaj modu, +,,Automap,,,,,,,,,,,,,,,,,,,,,,,,,, +Map color set,AUTOMAPMNU_COLORSET,,,Map colour set,Barevné schéma,Farvesæt til kort,Farbset,,Mapkoloro-agordaĵo,Definir colores,,Kartan värikokoelma,Set de couleurs de la carte,Pálya térkép szín séma,Colori della mappa,地図色セット,맵 색상 설정,Kaartkleurenset,Kartfargesett,Zestaw kolorów mapy,Definir cores de mapa,,Set culori hartă,Цвета автокарты,Боје за мапу,Färgsättning av kartan,Harita renk seti, +Allow map defined colors,AUTOMAPMNU_CUSTOMCOLORS,,,Allow map defined colours,Povolit barvy dle modů,Tillad kortdefinerede farver,Erlaube levelspezifische Farben,,Permesi mapdefinitajn kolorojn,Permitir colores definidos,,Salli tason määrittelemät värit,Couleurs définies par carte,Pálya orientált színséma használata,Consenti i colori definiti dalla mappa,定義したマップ色の許可,맵 정의 색상 허용,Niveau-specifieke kleuren toestaan,Tillat kartdefinerte farger,Pozwól na kolory zdefiniowne przez mapę,Permitir cores definidas por mapa,,Permite culorilor să fie definite de hartă,Разрешить определённые уровнем цвета автокарты,Дозволи дефинисане боје за мапу,Tillåter kartdefinierade färger,Harita tanımlı renklere izin ver, +Set custom colors,AUTOMAPMNU_SETCUSTOMCOLORS,,,Set custom colours,Vlastní barvy,Indstil brugerdefinerede farver,Benutzerdefinierte Farben,,Agordi laŭmendajn kolorojn,Fijar colores personalizados,,Mukauta värejä,Choisir couleurs personnalisées,Egyéni színek beállítása,Modifica i colori personalizzati,カスタム色を決める,사용자 지정 색상 설정,Aangepaste kleuren instellen,Angi egendefinerte farger,Spersonalizuj kolory,Definir cores personalizadas,,Setare culori personalizate,Задать свои цвета,Промени боје,Ställ in egna färger,Özel renkleri ayarlama, +Customize map controls,AUTOMAPMNU_CONTROLS,,,,Ovládání mapy,Tilpas kontrolelementer til kortet,Automapsteuerung einstellen,,Adapti mapregilojn,Personalizar controles del mapa,,Kartanohjausasetukset,Choisir contrôles de la carte,Térkép irányítás testreszabása,Personalizza i controlli mappa,マップコントロール カスタマイズ,맵 조작 설정,Kaartcontroles aanpassen,Tilpass kartkontroller,Ustaw klawisze mapy,Configurar comandos de mapa,,Personalizare schemă de control a hărții,Управление автокартой,Промени контроле мапе,Anpassa kartkontroller,Harita kontrollerini özelleştirme, +Overlay automap,AUTOMAPMNU_OVERLAY,,,,Překryvná mapa,Overlay automap,Überlagere Automap,,Surmeti aŭtomatan mapon,Superponer automapa,,Projisoi automaattikartta,Carte en Surimpression,Képen felüli térkép,Copri l'automappa,オートマップを重ねる,오토맵을 오버레이,Overlay automap,Overlegg automatisk kart,Nałożenie mapy,Sobreposição de automapa,,Acoperire hartă computerizată,Прозрачная автокарта,Провидна аутомапа,Överlagring av automap,Yerleşim otomatik haritası, +Enable textured display,AUTOMAPMNU_TEXTURED,,,,Textury,Aktiver tekstureret visning,Texturanzeige,,Ŝalti teksturitan ekranon,Mostrar automapa texturizado,,Ota käyttöön pintakuvioinnit,Activer affichage texturé,Textúrázott térkép,Abilita la mostra texture,床テクスチャ表示を許可,텍스쳐 디스플레이 허용,Structuurweergave inschakelen,Aktiver teksturert visning,Włącz oteksturowanie mapy,Habilitar automapa texturizado,Permitir automapa texturizado,Activare mod texturat,Текстуры на автокарте,Омогући приказ текстура,Aktivera texturerad visning,Dokulu ekranı etkinleştir, +Show item counts,AUTOMAPMNU_SHOWITEMS,,,,Počet předmětů,Vis tællinger af emner,Zeige Gegenstandsanzahl,,Montri nombron de objektoj,Mostrar conteo de objetos,,Näytä esineiden lukumäärä,Afficher compte d'objets,Tárgy számláló mutatása,Mostra il conteggio degli oggetti,アイテム数 表示,주운 아이템의 갯수를 표시,Toon artikeltellingen,Vis antall elementer,Pokaż liczbę przedmiotów,Exibir contagem de itens,,Afișare numărătoare obiecte,Количество предметов,Прикажи бројач за предмете,Visa antal objekt,Öğe sayılarını göster, +Show monster counts,AUTOMAPMNU_SHOWMONSTERS,,,,Počet příšer,Vis monstertællinger,Zeige Monsteranzahl,,Montri nombron de monstroj,Mostrar conteo de monstruos,,Näytä hirviöiden lukumäärä,Afficher compte de monstres,Szörny számláló mutatása,Mostra il conteggio dei mostri,モンスター数 表示,죽인 적의 횟수 표시,Toon monstertellingen,Vis antall monster,Pokaż liczbę potworów,Exibir contagem de monstros,,Afișare numărătoare monștri,Количество монстов,Прикажи бројач за чудовишта,Visa antal monster,Canavar sayılarını göster, +Show secret counts,AUTOMAPMNU_SHOWSECRETS,,,,Počet skrýší,Vis hemmelige tællinger,Zeige Geheimnisanzahl,,Montri nombron de sekretoj,Mostrar conteo de secretos,,Näytä salojen lukumäärä,Afficher compte de secrets,Rejtekhely számláló mutatása,Mostra il conteggio dei segreti,シークレット数 表示,밝힌 비밀의 수 표시,Toon geheime tellingen,Vis hemmelige tellinger,Pokaż liczbę sekretów,Exibir contagem de segredos,,Afișare numărătoare secrete,Количество тайников,Прикажи бројач за тајне,Visa antalet hemligheter,Gizli sayıları göster, +Show time elapsed,AUTOMAPMNU_SHOWTIME,,,,Uplynulý čas na mapě,Vis den forgangne tid,Zeige vergangene Zeit,,Montri pasintan tempon,Mostrar tiempo transcurrido,,Näytä kulunut aika,Afficher temps passé,Eltöltött idő mutatása,Mostra il tempo trascorso,経過時間 表示,경과한 시간 표시,Verstreken tijd tonen,Vis medgått tid,Pokaż ile czasu upłynęło,Exibir tempo decorrido,,Afișare timp petrecut pe hartă,Прошедшее время,Прикажи протекло време,Visa förfluten tid,Geçen süreyi göster, +Show total time elapsed,AUTOMAPMNU_SHOWTOTALTIME,,,,Celkový uplynulý čas,"Vis den samlede tid, der er gået",Zeige Gesamtzeit,,Montri tutan pasintan tempon,Mostrar tiempo total transc.,,Näytä yhteensä kulunut aika,Afficher total de temps passé,Teljes eltelt idő mutatása,Mostra il tempo totale trascorso,統計時間 表示,누적 경과한 시간 표시,Toon de totale verstreken tijd,Vis total tid som har gått,"Pokaż całkowity czas, który upłynął",Exibir tempo total decorrido,,Afișare timp total petrecut în joc,Общее время,Прикажи укупно протекло време,Visa total tid som förflutit,Geçen toplam süreyi göster, +Show secrets on map,AUTOMAPMNU_MAPSECRETS,,,,Zobrazit skrýše,Vis hemmeligheder på kortet,Zeige Geheimnisse auf der Karte,,Montri sekretojn sur mapo,Mostrar secretos en el mapa,,Näytä salat kartalla,Afficher secrets sur carte,Rejtekhelyek mutatása a pályán,Mostra i segreti nella mappa,シークレットを地図に表示,맵의 비밀을 표시,Toon geheimen op de kaart,Vis hemmeligheter på kartet,Pokaż sekrety na mapie,Exibir segredos no mapa,,Afișare secrete,Тайники на карте,Прикажи тајне на аутомапи,Visa hemligheter på kartan,Haritada sırları göster, +Show map label,AUTOMAPMNU_SHOWMAPLABEL,,,,Zobrazit název mapy,Vis kortmærke,Zeige Levelnamen,,Montri mapetikedon,Mostrar etiqueta del mapa,,Näytä tason tunniste,Afficher label de carte,Pályacím mutatása,Mostra le etichette della mappa,マップ名 表示,맵의 이름 표시,Toon kaartlabel,Vis kartetikett,Pokaż etykietę mapy,Exibir etiqueta do mapa,,Afișare etichetă hartă,Название карты,Прикажи ознаку мапе,Visa kartans etikett,Harita etiketini göster, +Draw map background,AUTOMAPMNU_DRAWMAPBACK,,,,Pozadí mapy,Tegne kortbaggrund,Zeige Kartenhintergrund,,Desegni mapfondon,Dibujar fondo de mapa,,Piirrä tason tausta,Afficher fond d'écran carte,Térkép háttér kirajzolása,Mostra lo sfondo della mappa,マップの背景 描写,맵의 배경 출력,Teken de achtergrond van de kaart,Tegn kartbakgrunn,Rysuj tło mapy,Desenhar fundo do mapa,,Afișare fundal hartă,Отображение фона автокарты,Нацртај позадину мапе,Rita kartans bakgrund,Harita arka planı çizme, +Show keys (cheat),AUTOMAPMNU_SHOWKEYS,,,,Zobrazení klíčů (podvod),Vis nøgler (snyd),Zeige Schlüssel (Cheat),,Montri klavojn (trompo),Mostrar llaves (truco),,Näytä avaimet (huijauskeino),Afficher les clés (cheat),Kulcsok mutatása,Mostra le chiavi (cheat),鍵 表示(チート時),키를 표시 (치트),Toon sleutels (valsspeler),Vis nøkler (juks),Pokaż klucze (oszustwo),Exibir chaves (trapaça),,Afișare chei (trișare),Отображение ключей (чит-коды),Прикажи кључеве (чит),Visa nycklar (fusk),Tuşları göster (hile), +Show trigger lines,AUTOMAPMNU_SHOWTRIGGERLINES,,,,Zobrazení aktivujících čar,Vis trigger-linjer,Zeige Auslöserlinien,,Montri baskulliniojn,Mostrar líneas de activación,,Näytä laukaisinviivat,Afficher lignes d'action,Trigger vonalak mutatása,Mostra le linee d'attivazione,トリガーライン 表示,트리거 선을 표시,Triggerlijnen tonen,Vis utløserlinjer,Pokaż linie przełączników,Exibir linhas de ativação,,Afișare linii declanșatoare,Отображение спусковых линий,Прикажи триггер линије,Visa utlösningslinjer,Tetik çizgilerini göster, +Show things as sprites,AUTOMAPMNU_SHOWTHINGSPRITES,,,,Zobrazení objektů jako spritů,Vis ting som sprites,Zeige Dinge als Sprites,,Montri aĵojn kiel mov-rastrumojn,Mostrar cosas como sprites,,Näytä oliot spriteinä,Afficher objets comme sprites,Tárgyak sprite-ként megjelenítése,Mostra gli oggetti come sprite,thingsのスプライト表示,물체를 스프라이트로 표시,Toon dingen als sprites,Vis ting som sprites,Pokaż rzeczy jako sprite'y,Exibir objetos como sprites,,Afișare obiecte drept sprite,Отображение спрайтов объектов,Прикажи ствари као спрајтове,Visa saker som sprites,Nesneleri sprite olarak gösterme, +Overlay portals,AUTOMAPMNU_PTOVERLAY,,,,Překrývat portály,Overlay portaler,Überlagere Portale,,Surmeti portalojn,Sobreponer portales,,Projisoi portaalit,Superposer les portails,Overlay portálok,Sovrapponi i portali,オーバーレイ ポータルズ,포탈을 오버레이,Overlappende portalen,Overlegg portaler,Nałóż portale,Sobreposição de portais,,Acoperire portaluri,Порталы в прозрачном режиме,Провидни портали,Överlagra portaler,Yerleşim portalları, +Empty space margin,AUTOMAPMNU_EMPTYSPACEMARGIN,,,,Práh prázdného prostoru,Tomrumsmargin,Breite des Randes,,Malplena spacia marĝeno,Margen de espacio vacío,,Tyhjän reunan leveys,Marge d'espace vide,Üres hely szegély,Margine dello spazio vuoto,空間の余白,빈공간 여백,Breedte van de rand,Tøm mellomromsmargen,Opróżnij margines przestrzeni,Margem de espaço vazio,,Margine spațiu gol,Край автокарты,Празна маргина,Marginal för tomt utrymme,Boş alan marjı, +Mark font,AUTOMAPMNU_MARKFONT,,,,Písmo značek,Marker skrifttype,Zeichensatz für Markierungen,,Marki tiparon,Fuente para marcas,,Karttamerkkien fontti,Police Marqueur,Jelzés betűtípus,Font del segnaposto,マークフォント,미니맵 마킹 폰트,Font voor markers,Merk skrifttype,Czcionka oznaczeń,Fonte das marcações,,Font marcaj,Шрифт отметок,Фонт ознака,Markera typsnitt,Mark yazı tipi, +Mark color,AUTOMAPMNU_MARKCOLOR,,,,Barva značek,Markere farve,Farbe für Markierungen,,Marki koloron,Color de las marcas,,Karttamerkkien väri,Couleur Marqueur,Jelzés szín,Colore del segnaposto,マーク色,미니맵 마킹 색상,Markeer kleur,Merk farge,Kolor oznaczeń,Cor das marcações,,Culoare marcaj,Цвет отметок,Боја ознака,Markera färg,Renk işaretle, +Set mark,MAPCNTRLMNU_SETMARK,,,,Umístit značku,Indstille mærke,Setze Markierung,,Meti markon,Fijar marca,,Aseta merkki,Placer repère,Jelzés beállítása,Aggiungi segnaposto,マークを置く,마크 추가,Markering instellen,Sett merke,Ustaw znacznik,Posicionar marcação,,Marcare,Поставить отметку,Постави ознаку,Ställ in märket,İşareti ayarla, +Clear mark,MAPCNTRLMNU_CLEARMARK,,,,Smazat značky,Slet markering,Lösche Markierung,,Forigi markon,Limpiar marca,,Pyyhi merkit,Enlever repères,Jelzések törlése,Pulisci il segnaposto,マーククリア,마크 삭제,Duidelijke markering,Fjern merke,Usuń znacznik,Limpar marcação,,Ștergere marcaj,Убрать отметку,Уклони ознаку,Rensa markeringen,Açık işaret, +,,Scoreboard,,,,,,,,,,,,,,,,,,,,,,,,,, +Scoreboard Options,DSPLYMNU_SCOREBOARD,,,,Tabulka skóre,Indstillinger for resultattavlen,Punktetabellenoptionen,,Poentotabulo-Agordoj,Opciones de marcador,,Pistetauluasetukset,Options Tableau des Scores,Eredményjelző beállítások,Opzioni tabella punteggio,スコアボード オプション,점수창 설정,Scorebord opties,Alternativer for resultattavlen,Opcje Tablicy Wyników,Opções de Tela de Pontuação,,Opțiuni Tabelă de Marcaj,Таблица очков,Табеларне подешавања,Alternativ för resultattavlan,Skorbord Seçenekleri, +Scoreboard Options,SCRBRDMNU_TITLE,,,,Nastavení tabulky skóre,Indstillinger for resultattavlen,Punktetabellenoptionen,,Poentotabulo-Agordoj,Opciones de marcador,,Pistetauluasetukset,Tableau des Scores,Eredményjelző beállítások,Opzioni per la tabella punteggio,スコアボード オプション,점수판 설정,Scorebord opties,Alternativer for resultattavlen,Opcje Tablicy Wyników,Opções de Tela de Pontuação,Opções do Ecrã de Pontuação,Setări Tabelă de Marcaj,Настройки таблицы очков,Подешавања бодовања,Alternativ för resultattavlan,Skorbord Seçenekleri, +Cooperative Options,SCRBRDMNU_COOPERATIVE,,,,Kooperativní mód,Samarbejdsmuligheder,Kooperativ-Optionen,,Kooperativo-Agordoj,Opciones de cooperativo,,Yhteispeliasetukset,Options Mode Coop,Együttműködő beállítása,Opzioni per il gioco cooperativo,協力モードの設定,코옵 설정,Coöperatieve Opties,Samarbeidsalternativer,Opcje Kooperacji,Opções de Jogo Cooperativo,,Setări Mod Cooperativ,Настройки для команд,Подешавања сарадње,Alternativ för samarbete,Kooperatif Seçenekleri, +Enable Scoreboard,SCRBRDMNU_ENABLE,,,,Povolit tabulku skóre,Aktiver resultattavle,Punktetabelle aktiv,,Ŝalti Poentotabulon,Activar marcador,,Ota käyttöön pistetaulu,Activer Tableau des Scores,Eredményjelző bekapcsolása,Abilita la tabella punteggio,スコアボード表示,점수판 허용,Scorebord inschakelen,Aktiver resultattavle,Zezwól na Tablicę Wyników,Habilitar Tela de Pontuação,Permitir Ecrã de Pontuação,Activare Tabelă de Marcaj,Включить таблицу очков,Омогући бодовање,Aktivera resultattavlan,Skor Tablosunu Etkinleştir, +Header Color,SCRBRDMNU_HEADERCOLOR,,,Header Colour,Barva hlavičky,Overskriftsfarve,Kopfzeilenfarbe,,Kapokoloro,Color de cabecera,,Otsikon väri,Couleur du Titre,Fejléc szín,Colore della testata,ヘッダー色,헤더의 색깔,Kleur koptekst,Farge på topptekst,Kolor Nagłówka,Cor de Cabeçalho,,Culoare Antet,Цвет заголовка,Боја заглавља,Färg på rubriken,Başlık Rengi, +Your Player Color,SCRBRDMNU_YOURCOLOR,,,Your Player Colour,Barva tvého hráče,Din spillerfarve,Deine Spielerfarbe,,Via ludantkoloro,Color de tu jugador,,Pelaajasi väri,Votre couleur,Játékos színe,Colore del giocatore 'Tu',自分の色,플레이어의 색깔,Uw Spelerskleur,Din spillerfarge,Twoje Kolory,Cor do Seu Jogador,Cor do teu Jogador,Culoarea Jucătorului Tău,Ваш цвет,Боја твога играча,Din spelares färg,Oyuncu Renginiz, +Other Players' Color,SCRBRDMNU_OTHERPLAYERCOLOR,,,Other Players' Colour,Barva ostatních hráčů,Andre spilleres farve,Andere Spielerfarbe,,Koloro de aliaj ludantoj,Color de otros jugadores,,Muiden pelaajien väri,Couleur des autres joueurs,Más játékosok színe,Colore degli altri giocatori,他者の色,다른 플레이어들의 색깔,Andere spelerskleur,Andre spilleres farge,Kolory Innych Graczy,Cor de Outros Jogadores,Cor dos Outros Jogadores,Culorile Celorlalți Jucători,Цвет других игроков,Боја другог играча,Andra spelares färg,Diğer Oyuncuların Rengi, +Deathmatch Options,SCRBRDMNU_DEATHMATCH,,,,Deathmatch,Indstillinger for Deathmatch,Deathmatch-Optionen,,Mortmaĉo-Agordoj,Opciones modo a muerte,,Kuolonotteluasetukset,Options Deathmatch,Deathmatch Beállítások,Opzioni deathmatch,デスマッチの設定,데스매치 설정,Deathmatch opties,Deathmatch-alternativer,Opcje Deathmatchu,Opções de Deathmatch,,Setări Deathmatch,Настройки боя насмерть,Детмеч подешавања,Alternativ för Deathmatch,Ölüm Maçı Seçenekleri, +Team Deathmatch Options,SCRBRDMNU_TEAMDEATHMATCH,,,,Týmový deathmatch,Indstillinger for Team Deathmatch,Team-Deathmatch-Optionen,,Teamo-Mortmaĉo-Agordoj,Opciones modo a muerte por equipos,,Joukkuekuolonotteluasetukset,Options Deathmatch en équipe,Team Deathmatch Beállítások,Opzioni deathmatch a squadra,チームデスマッチの設定,팀 데스매치 설정,Team Deathmatch Opties,Lag Deathmatch-alternativer,Opcje Drużynowego Deathmatchu,Opções de Deathmatch de Equipe,Opções de Deathmatch de Equipa,Setări Deathmatch în Echipă,Настройки командного боя насмерть,Тимски детмеч подешавања,Alternativ för Team Deathmatch,Takım Ölüm Maçı Seçenekleri, +,,Alt HUD,,,,,,,,,,,,,,,,,,,,,,,,,, +Alternative HUD,ALTHUDMNU_TITLE,,,,Alternativní HUD,Alternativ HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH Alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternativ HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативное отображение информации,Алтернативни HUD,Alternativ HUD,Alternatif HUD, +Enable alternative HUD,ALTHUDMNU_ENABLE,,,,Povolit alternativní HUD,Aktiver alternativt HUD,Alternatives HUD eingeschaltet,,Ŝalti alternativan HUD,Activar HUD alternativo,,Ota käyttöön vaihtoehtoinen tilanäyttö,Activer l'ATH Alternatif,Alternatív HUD bekapcsolása,Abilita HUD alternativo,オルタナティブHUD有効,대체 HUD 사용,Alternatieve HUD inschakelen,Aktiver alternativ HUD,Włącz alternatywny HUD,Habilitar HUD alternativo,,Activează Interfața pe Timp de Joc Alternativă,Включить альтернативное отображение,Укључи алтернативни HUD,Aktivera alternativ HUD,Alternatif HUD'yi etkinleştirin, +Show secret count,ALTHUDMNU_SHOWSECRETS,,,,Zobrazit počet skrýší,Vis hemmelig optælling,Zeige Geheimniszähler,,Montri sekretonombron,Mostrar cont. de secretos,,Näytä salojen lukumäärä,Afficher compteur de secrets,Rejtekhely számláló mutatása,Mostra il conteggio dei segreti,シークレット数 表示,비밀 수 표시,Toon het aantal geheimen,Vis hemmelig antall,Pokaż liczbę sekretów,Exibir contagem de segredos,,Afișează numărul secretelor,Отображение обнаруженных тайников,Прикажи количину тајна,Visa hemligt antal,Gizli sayımı göster, +Show monster count,ALTHUDMNU_SHOWMONSTERS,,,,Zobrazit počet příšer,Vis monstertælling,Zeige Monsterzähler,,Montri monstronombron,Mostrar cont. de monstruos,,Näytä hirviöiden lukumäärä,Afficher compteur de monstres,Szörny számláló mutatása,Mostra il conteggio dei mostri,モンスター数 表示,적 개체 수 표시,Toon het aantal monsters,Vis antall monstre,Pokaż liczbę zabójstw,Exibir contagem de monstros,,Afișează numărul de monștri,Отображение количества монстров,Прикажи количину чудовишта,Visa antalet monster,Canavar sayısını göster, +Show item count,ALTHUDMNU_SHOWITEMS,,,,Zobrazit počet předmětů,Vis optælling af genstande,Zeige Gegenstandszähler,,Montri objektonombron,Mostrar cont. de objetos,,Näytä esineiden lukumäärä,Afficher compteur d'objets,Tárgy számláló mutatása,Mostra il conteggio degli oggetti,アイテム数の表示,아이템 수 표시,Toon het aantal items,Vis antall gjenstander,Pokaż liczbę przedmiotów,Exibir contagem de itens,,Afișează numărul de obiecte,Отображение количества предметов,Прикажи количину предмета,Visa antalet föremål,Öğe sayısını göster, +Show stamina and accuracy,ALTHUDMNU_SHOWSTATS,,,,Zobrazit výdrž a přesnost,Vis udholdenhed og nøjagtighed,Zeige Kondition und Genauigkeit,,Montri viglecon kaj akuratecon,Mostrar resistencia/precisión,,Näytä puhti ja tarkkuus,Afficher Endurance et Précision,Állóképesség és pontosság mutatása,Mostra stamina e accuratezza,スタミナと精度の表示,스테미나와 정확도를 표시,Toon uithoudingsvermogen en nauwkeurigheid,Vis utholdenhet og nøyaktighet,Pokaż wytrzymałość i precyzję,Exibir resistência e precisão,,Afișează rezistența fizică si acuratețea,Отображение выносливости и точности,Прикажи издржљивост и прецизност,Visa uthållighet och noggrannhet,Dayanıklılık ve doğruluk gösterin, +Show berserk,ALTHUDMNU_SHOWBERSERK,,,,Zobrazit berserk,Vis berserk,Zeige Berserk,,Montri frenezecon,Mostrar berserker,,Näytä raivo,Afficher Berserk,Berserk mutatása,Mostra il berserk,バーサーク表示,버서크 아이템을 표시,Toon berserk,Vis berserk,Pokaż szał,Exibir berserk,,Afișează pachetul de forță mărită,Отображение берсерка,Прикажи берсерк,Visa berserk,Berserk'i göster, +Show weapons,ALTHUDMNU_SHOWWEAPONS,,,,Zobrazit zbraně,Vis våben,Zeige Waffen,,Montri armojn,Mostrar armas,,Näytä aseet,Afficher Armes,Fegyverek mutatása,Mostra le armi,武器表示,무기들을 표시,Toon wapens,Vis våpen,Pokaż bronie,Exibir armas,,Afișează armele,Отображение оружия,Прикажи оружја,Visa vapen,Silahları göster, +Show ammo for,ALTHUDMNU_SHOWAMMO,,,,Zobrazit munici pro,Vis ammunition for,Zeige Munition,,Montri municion por,Mostrar munición para,,Näytä ammukset aseelle,Afficher Munitions pour,Ammo mutatása a,Mostra le munizioni per,弾薬等の表示,탄약을 표시,Toon munitie voor,Vis ammunisjon for,Pokaż amunicję dla,Exibir munição para,,Afișează muniția pentru,Отображение патронов для,Прикажи муниције за,Visa ammunition för,Cephane göster, +Show time,ALTHUDMNU_SHOWTIME,,,,Zobrazit čas,Vis tid,Zeige Zeit,,Montri tempon,Mostrar tiempo,,Näytä aika,Afficher temps niveau,Idő mutatása,Mostra il tempo,時間の表示,시간 표시,Toon tijd,Vis tid,Pokaż czas,Exibir tempo,,Afișează timpul,Отображение времени,Прикажи време,Visa tid,Gösteri zamanı, +Time color,ALTHUDMNU_TIMECOLOR,,,Time colour,Barva času,Tidens farve,Zeit-Farbe,,Tempkoloro,Color del tiempo,,Ajan väri,Couleur du timer,Idő színe,Colore del tempo,時間の字色,시간 색상,Tijdskleur,Tid farge,Kolor czasu,Cor do tempo,,Culoare timp,Цвет времени,Боја времена,Tidens färg,Zaman rengi, +Show network latency,ALTHUDMNU_SHOWLAG,,,,Zobrazit latenci sitě,Vis netværksforsinkelse,Zeige Netzwerk-Latenz,,Montri reto-respondotempon,Mostrar latencia de red,,Näytä verkon viive,Afficher latence réseau,Válaszidő mutatása,Mostra la latenza del network,ネットのラグ表示,내트워크 트래픽 표시,Toon netwerklatentie,Vis nettverksforsinkelse,Pokaż czas oczekiwania sieci,Exibir latência de rede,,Afișează perioada de întârziere a conexiunii,Отображение задержки сети,Прикажи кашњење мреже,Visa nätverksfördröjning,Ağ gecikmesini göster, +Ammo display order,ALTHUDMNU_AMMOORDER,,,,Pořadí zobrazení munice,Visningsrækkefølge for ammunition,Munitionsreihenfolge,,Vidiga aranĝo de municio,Orden vista de munición,,Ammusten esitysjärjestys,Ordre d'affichage des munitions,Muníció típus rendezése,Ordine mostra delle munizioni,弾薬表示順,탄약 표시 순서,Volgorde van de munitieweergave,Rekkefølge for ammunisjonsvisning,Kolejność pokazywania amunicji,Ordem de exibição de munição,,Ordine afișare muniție,Порядок отображения боеприпасов,Редослед муниција,Ordning för visning av ammunition,Cephane teşhir düzeni, +Red ammo display below %,ALTHUDMNU_AMMORED,,,,Červený indikátor munice pod %,Rød ammunitionsvisning under %,Rot für Munition unter %,,Ruĝa municividigo sub %,Porcent. de munición en rojo,,Punaiset ammukset ammusten alittaessa %,Compteur de munitions rouge sous,Piros muníció szín % alatt,Contatore delle munizioni di colore rosso sotto,弾薬の赤色表示%,적색 남은 탄약 밑에 표시,Rood munitieweergave onder %,Rød visning av ammunisjonsnivå under %,Wyświetl czerwoną amunicję pod ,Porcentagem de munição em vermelho até,Percentagem de munição em vermelho até,Muniția schimbă culoarea în roșu sub %,"Отображение боеприпасов красным ниже, %",Прикажи муниције црвеном испод %,Röd ammunition visas under %,Aşağıda kırmızı cephane göstergesi %, +Yellow ammo display below %,ALTHUDMNU_AMMOYELLOW,,,,Žlutý indikátor munice pod %,Gul ammunitionsvisning under %,Gelb für Munition unter %,,Flava municividigo sub %,Porcent. de munición en amarillo,,Keltaiset ammukset ammusten alittaessa %,Compteur de munitions jaune sous,Sárga muníció szín % alatt,Contatore delle munizioni di colore giallo sotto,弾薬の黄色表示%,황색 남은 탄약 밑에 표시,Gele munitieweergave onder %,Gult ammunisjonsdisplay under %.,Wyświetl żółtą amunicję pod ,Porcentagem de munição em amarelo até,Percentagem de munição em amarelo até,Muniția schimbă culoarea în galben sub %,"Отображение боеприпасов жёлтым ниже, %",Прикажи муниције жутом испод %,Gul ammunition visas under %,Aşağıda sarı cephane göstergesi %, +Red health display below,ALTHUDMNU_HEALTHRED,,,,Červený indikátor zdraví pod,Rødt sundhedsindikator under %,Rot für Gesundheit unter %,,Ruĝa sanvidigo sube,Porcent. de salud en rojo,,Punainen terveys terveyden alittaessa,Compteur de santé rouge sous,Piros életerő szín ezen szám alatt,Contatore della salute di colore rosso sotto,体力の赤色表示%,적색 체력 밑에 표시,Rood gezondheidsweergave beneden,Rød helsevisning under,Wyświetl czerwone zdrowie pod ,Porcentagem de saúde em vermelho até,Percentagem de saúde em vermelho até,Sănătatea schimbă culoarea în roșu sub %,"Отображение здоровья красным ниже, %",Прикажи здравље црвеном испод,Röd hälsoindikator nedanför,Aşağıdaki kırmızı sağlık göstergesi, +Yellow health display below,ALTHUDMNU_HEALTHYELLOW,,,,Žlutý indikátor zdraví pod,Gul sundhedsindikator under %,Gelb für Gesundheit unter %,,Flava sanvidigo sube,Porcent. de salud en amarillo,,Keltainen terveys terveyden alittaessa,Compteur de santé jaune sous,Sárga életerő szín ezen szám alatt,Contatore della salute di colore giallo sotto,体力の黄色表示%,황색 체력 밑에 표시,Geel gezondheidsweergave beneden,Gul helsevisning nedenfor,Wyświetl żółte zdrowie pod ,Porcentagem de saúde em amarelo até,Percentagem de saúde em amarelo até,Sănătatea schimbă culoarea în galben sub %,"Отображение здоровья жёлтым ниже, %",Прикажи здравље жутом испод,Gul hälsoindikator nedanför,Aşağıdaki sarı sağlık göstergesi, +Green health display below,ALTHUDMNU_HEALTHGREEN,,,,Zelený indikátor zdraví pod,Grønt sundhedsindikator under %,Grün für Gesundheit unter %,,Verda sanvidigo sube,Porcent. de salud en verde,,Vihreä terveys terveyden alittaessa,Compteur de santé vert sous,Zöld életerő szín ezen szám alatt,Contatore della salute di colore verde sotto,体力の緑色表示%,녹색 체력 밑에 표시,Groen gezondheidsweergave beneden,Grønn helsevisning under,Wyświetl zielone zdrowie pod ,Porcentagem de saúde em verde até,Percentagem de saúde em verde até,Sănătatea schimbă culoarea în verde sub %,"Отображение здоровья зелёным ниже, %",Прикажи здравље зеленом испод,Grön hälsoindikator nedan,Aşağıdaki yeşil sağlık göstergesi, +Red armor display below,ALTHUDMNU_ARMORRED,,,Red armour display below,Červený indikátor brnění pod,Rødt panser display under %,Rot für Panzerung unter %,,Ruĝa kirasvidigo sube,Porcent. de blindaje en rojo,,Punainen panssari panssarin alittaessa,Compteur d' armure rouge sous,Piros páncél szín ezen szám alatt,Contatore dell'armatura di colore rosso sotto,防具の赤色表示%,적색 아머 밑에 표시,Rood pantserweergave beneden,Visning av rød rustning under,Wyświetl czerwony pancerz pod ,Porcentagem de armadura em vermelho até,Percentagem de armadura em vermelho até,Armura schimbă culoarea în galben sub %,"Отображение брони красным ниже, %",Прикажи оклоп црвеном испод,Röd rustning visas nedan,Kırmızı zırh ekranı aşağıda, +Yellow armor display below,ALTHUDMNU_ARMORYELLOW,,,Yellow armour display below,Žlutý indikátor brnění pod,gul panser under displayet under %,Gelb für Panzerung unter %,,Flava kirasvidigo sube,Porcent. de blindaje en amarillo,,Keltainen panssari panssarin alittaessa,Compteur d' armure jaune sous,Sárga páncél szín ezen szám alatt,Contatore dell'armatura di colore giallo sotto,防具の黄色表示%,황색 아머 밑에 표시,Geel pantserweergave beneden,Visning av gul rustning under,Wyświetl żółty pancerz pod ,Porcentagem de armadura em amarelo até,Percentagem de armadura em amarelo até,Armura schimbă culoarea în galben sub %,"Отображение брони жёлтым ниже, %",Прикажи оклоп жутом испод,Gul rustning visas nedan,Aşağıdaki sarı zırh ekranı, +Green armor display below,ALTHUDMNU_ARMORGREEN,,,Green armour display below,Zelený indikátor brnění pod,grønt panser display under %,Grün für Panzerung unter %,,Verda kirasvidigo sube,Porcent. de blindaje en verde,,Vihreä panssari panssarin alittaessa,Compteur d' armure bleu sous,Zöld páncél szín ezen szám alatt,Contatore dell'armatura di colore verde sotto,防具の緑色表示%,녹색 아머 밑에 표시,Groen pantserweergave beneden,Visning av grønn rustning under,Wyświetl zielony pancerz pod ,Porcentagem de armadura em verde até,Percentagem de armadura em verde até,Armura schimbă culoarea în verde sub %,"Отображение брони зелёным ниже, %",Прикажи оклоп зеленом испод,Grön rustning visas nedan,Aşağıdaki yeşil zırh ekranı, +Alternative Automap HUD,ALTHUDMNU_AUTOMAPHUD,,,,Alternativní HUD automapy,Alternativ Automap HUD,Alternatives Automap HUD,,Alternativa HUD de aŭtomata mapo,HUD alternativo del automapa,,Vaihtoehtoinen automaattikartan tilanäyttö,ATH Alternatif pour carte,Alternatív Automap HUD,HUD automappa alternativo,オルタナティブ オートマップHUD,대체 오토맵 HUD,Alternatieve Automap HUD,Alternativ Automap HUD,Alternatywny HUD mapy,HUD alternativo de automapa,,Hartă Computerizată Alternativă,Альтернативный интерфейс на автокарте,Алтернативни HUD за аутомапу,Alternativ automap HUD,Alternatif Automap HUD, +Map title color,ALTHUDMNU_TITLECOLOR,,,Map title colour,Barva názvu levelu,Farve på korttitel,Farbe für Levelnamen,,Maptitolo-koloro,Color del título del mapa,,Tason nimen väri,Couleur titre du niveau,Pálya cím szín,Colore titolo mappa,マップ名の色,맵 제목 색깔,Kleur kaarttitel,Farge på karttittel,Kolor nazwy mapy,Cor do título do fase,Cor do título do nível,Culoare titlu hartă,Цвет названия уровня,Боја назива нивоа,Färg på kartans titel,Harita başlık rengi, +Map time color,ALTHUDMNU_MAPTIMECOLOR,,,Map time colour,Barva času levelu,Farve på kortets tid,Farbe für Level-Zeit,,Maptempo-koloro,Color del tiempo del mapa,,Tason ajan väri,Couleur temps du niveau,Pálya idő szín,Colore tempo mappa,経過時間の色,맵 시간 색깔,Kleur kaarttijd,Kartets tidsfarge,Kolor czasu na mapie,Cor do tempo da fase,Cor do tempo do nível,Culoare timp petrecut pe hartă,Цвет времени для уровней,Боја времена на нивоу,Färg för kartans tid,Harita zaman rengi, +Hub time color,ALTHUDMNU_HUBTIMECOLOR,,,Hub time colour,Barva času hubu,Farve på hub-tid,Farbe für Hub-Zeit,,Nabtempo-koloro,Color del tiempo del nodo,,Tasokokoelman ajan väri,Couleur temps du hub,Csomópont idő szín,Colore tempo hub di mappe,区間経過時間の色,허브 시간 색깔,Kleur hubtijd,Farge for knutepunkttid,Kolor czasu w hubie,Cor do tempo no HUD,,Culoare timp petrecut în hub,Цвет времени для хабов,Боја времена на хабу,Färg för navets tid,Hub zaman rengi, +Total time color,ALTHUDMNU_TOTALTIMECOLOR,,,Total time colour,Barva celkového času,Farve for samlet tid,Farbe für Gesamtzeit,,Tuttempo-koloro,Color del tiempo total,,Kokonaisajan väri,Couleur temps total,Teljes idő szín,Colore tempo totale,合計経過時間の色,누적 경과한 시간 색깔,Kleur totale tijd,Farge for total tid,Kolor całkowitego czasu,Cor do tempo total,,Culoare timp total,Цвет общего времени,Боја укупног времена,Färg för total tid,Toplam zaman rengi, +Coordinate color,ALTHUDMNU_COORDINATECOLOR,,,Coordinate colour,Barva souřadnic,Koordinat farve,Farbe für Koordinaten,,Kunordigi koloron,Color de coordenadas,,Koordinaattien väri,Couleur coordonnées,Koordináló szín,Colore coordinate,座標色,좌표 색깔,Kleur coördinaten,Koordinatfarge,Skoordynuj kolor,Cor das coordenadas,,Culoare coordonate,Цвет координат,Боја координата,Färg för koordinater,Koordinat rengi, +Coordinate mode,ALTHUDMNU_COORDINATEMODE,,,,Režim souřadnic,Koordinattilstand,Koordinatenmodus,,Kunordigi modon,Modo de coordenadas,,Koordinaattitila,Mode coordonnées,Koordináló mód,Modalità coordinate,座標モード,좌표 모드,Coördinatiemodus,Koordinat-modus,Skoordynuj tryb,Modo de coordenada,,Mod coordonate,Координаты игрока,Мод координата,Koordinatläge,Koordinat modu, +Statistics name color,ALTHUDMNU_STATSNAMECOLOR,,,Statistics name colour,Barva názvu statistik,Farve på statistiknavn,Farbe für Statistik-Namen,,Statistiknomo-koloro,Color del nombre de estadísticas,,Tilastotiedon nimen väri,Couleur nom des statistiques,Statisztika név szín,Colore nome statistica,統計名の色,통계표 이름 색상,Kleur statistiekennaam,Farge på statistikknavn,Kolor nazw statystyk,Cor do nome das estatísticas,,Culoare nume statistici,Цвет имён в статистике,Боја назива статистика,Färg för statistiknamn,İstatistik adı renk, +Statistics color,ALTHUDMNU_STATSCOLOR,,,Statistics colour,Barva statistik,Statistik farve,Farbe für Statistik-Nummern,,Statistiko-koloro,Color de las estadísticas,,Tilastotiedon väri,Couleur statistiques,Statisztika szín,Colore contatore statistica,統計の色,통계표 색상,Kleur statistieken,Statistikk farge,Kolor statystyk,Cor das estatísticas,,Culoare statistici,Цвет статистики,Боја статистика,Färg för statistik,İstatistik renk, +,,Display (game related),,,,,,,,,,,,,,,,,,,,,,,,,, +Rendering Interpolation,DSPLYMNU_CAPFPS,,,,Interpolace vykreslování,Interpolering af rendering,Renderinterpolation,,Bildigo-Interpolado,Interpolación de renderizado,,Hahmonnuksen interpolointi,Interpolation du rendu,Render animáció simítás,Interpolazione grafica,レンダリング補間,프레임 제한,Interpolatie renderen,Gjengivelse av interpolasjon,Interpolacja Renderowania,Interpolação de renderização,,Interpolare Imagine,Сглаживание обработки,Интерполација рендеринга,Rendering Interpolering,Rendering Enterpolasyonu, +Transparency render mode,DSPLYMNU_BLENDMETHOD,,,,Režim vykreslování průhlednosti,Gennemsigtighedstilstand,Transparenzmodus,,Travidebleco-bildigo-reĝimo,Modo de renderizado de transparencia,,Läpinäkyvyyden hahmonnustila,Mode de Rendu transparence,Átlászóság render mód,Modalità della resa grafica della trasparenza,レンダリング透過モード,투명도 표시 모드,Transparantie render modus,Gjengivelsesmodus for gjennomsiktighet,Tryb renderowania przezroczystości,Modo de renderiz. de transparência,,Mod Transparență,Режим обработки прозрачности,Режим рендеринга транспарентности,Återgivning med transparens,Şeffaflık render modu, +Screen wipe style,DSPLYMNU_WIPETYPE,,,,Styl přechodů,Skærmens aftørringsstil,Bildschirmwechseleffekt,,Stilo de ekranviŝo,Transición de pantalla,,Ruudun pyyhkiytymistyyli,Style de Fondu d'écran,Képernyőtörlődés módja,Stile della pulizia dello schermo,スクリーンワイプモード,화면 전환 방식,Schermveegstijl,Stil for skjermtørking,Styl przejścia ekranu,Tipo de transição de tela,Tipo de transição de ecrã,Stil ștergere imagine,Эффект плавной смены экранов,Ефект брисања екрана,Stil för skärmtorkning,Ekran silme stili, +Show ENDOOM screen,DSPLYMNU_SHOWENDOOM,,,,Zobrazit ENDOOM obrazovku,Vis ENDOOM-skærm,Zeige ENDOOM,,Montri ENDOOM-ekranon,Mostrar pantalla ENDOOM,,Näytä ENDOOM-ruutu,Montrer la fenêtre ENDOOM,ENDOOM képernyő mutatása,Mostra la schermata ENDOOM,ENDOOM画面を表示,종료화면 표시,Toon ENDOOM scherm,Vis ENDOOM-skjerm,Pokaż ekran ENDOOM,Exibir tela ENDOOM,,Afișare fereastră ENDOOM,Показать экран ENDOOM,Прикажи ENDOOM екран,Visa ENDOOM-skärm,ENDOOM ekranını göster, +Blood Flash Intensity,DSPLYMNU_BLOODFADE,,,,Intenzita bliknutí při zranění,Blodblinkintensitet,Intensität für Bluteffekt,,Egeco de sango-ekbrilo,Intensidad del destello al ser atacado,,Verivälähdyksen voimakkuus,Intensité du flash dommages,Sebzéskor villanás mértéke,Intensità Bagliore Sangue,血粉の濃度,피격 표시 강도,Intensiteit van de bloedflitser,Intensitet for blodblits,Intensywność Efektów Krwi,Intensidade de Flash de Sangue,,Intensitate strălucire sânge,Интенсивность вспышки при ранении,Интензивност треперења током повређивања,Intensitet av blodblixt,Kan Flaş Yoğunluğu, +Pickup Flash Intensity,DSPLYMNU_PICKUPFADE,,,,Intenzita bliknutí při sebrání předmětu,Intensitet for optageeffekt,Intensität für Aufnehmen-Effekt,,Egeco de prenado-ekbrilo,Intensidad del destello al coger algo,Intensidad del destello al agarrar algo,Poimintavälähdyksen voimakkuus,Intensité du flash objets,Fegyver felvételekor villanás mértéke,Intensità Bagliore Raccolta,取得の視界色濃度,습득 표시 강도,Intensiteit van de oppakflitser,Intensitet av opptaksblits,Intesnywność Efektów Podnoszenia Przedmiotów,Intensidade de Flash ao Pegar Itens,,Intensitate strălucire la ridicarea obiectelor,Интенсивность вспышки при подборе,Интензивност треперења током купљења,Intensitet av pickupblink,Pikap Flaş Yoğunluğu, +Underwater Blend Intensity,DSPLYMNU_WATERFADE,,,,Intenzita zbarvení pod vodou,Undervandsblinkintensitet,Intensität für Unterwasser-Effekt,,Egeco de Subakva Mikso,Intensidad Color Sumergido,Intensidad Color Submarino,Vedenalaissumennuksen voimakkuus,Intensité du fondu sous l'eau,Vízalatti keverődés mértéke,Intensità Blend sott'acqua,水中反響音の濃度,수중 효과 강도,Intensiteit kleurvermenging onder water,Intensitet for undervannsblanding,Intensywność Efektów Pod Wodą,Intensidade de Efeito Debaixo d'Água,Intensidade de Efeito Debaixo de Água,Intensitate amestec culori subacvatice,Интенсивность эффекта под водой,Интензивност подводног треперења,Undervattensbländning Intensitet,Sualtı Karışım Yoğunluğu, +Sky render mode,DSPLYMNU_SKYMODE,,,,Režim vykreslování oblohy,Himmel-renderingstilstand,Rendermodus für Himmel,,Ĉielo-bildigo-reĝimo,Modo de renderizado del cielo,,Taivaan hahmonnustila,Mode du rendu du Ciel,Égbolt render mód,Modalità resa grafica del cielo,空の表示方法,하늘 표시 모드,Luchtrendermodus,Modus for gjengivelse av himmel,Tryb renderowania nieba,Modo de renderização de céu,,Mod de vizualizare al cerului,Режим обработки неба,Режим рендеринга неба,Läge för rendering av himmel,Gökyüzü oluşturma modu, +Linear skies,DSPLYMNU_LINEARSKY,,,,Lineární obloha,Lineære himmelstrøg,Lineare Himmel,,Linearaj ĉieloj,Cielo lineal,,Lineaariset taivaat,Ciel linéaire,Lineáris égboltok,Cieli lineari,空の歪み,선형 하늘,Lineaire lucht,Lineær himmel,Liniowe niebo,Céus lineares,,Cer rectiliniu,Линейное небо,Линеарна неба,Linjär himmel,Doğrusal gökyüzü, +Fullbright overrides sector color,DSPLYMNU_GZDFULLBRIGHT,,,,Při plném jasu ignorovat barvu sektoru,Ignorer sektorfarve ved fuld lysstyrke,Ignoriere Sektorfarbe bei voller Helligkeit,,Plenbrileco tranpasas sektorkoloron,Brillo máximo anula color del sector,,Täyskirkkaat ohittavat sektorin värin,Fullbright ignore couleur secteur,Fullbright felülírja a szektor szinét,Luce piena sovrappone il colore del settore,明るさ最大時にsector color塗り替え,섹터 색상 최대밝기 우선화,Volledig helderheid overschrijft de sectorkleur,Fullbright overstyrer sektorfarge,Ignoruj kolor sektora przy pełnej jasności,Brilho máximo anula cor de setor,,Luminozitatea maximă suprascrie culoarea sectorului,Полная яркость замещает цвет сектора,Пуно осветљење премошћује боју сектора,Fullbright åsidosätter sektorfärg,Fullbright sektör rengini geçersiz kılar, +Scale fuzz effect,DSPLYMNU_SCALEFUZZ,,,,Škálovat velikost fuzz efektu,Skala fuzz-effekt,Skaliere Fuzz-Effekt,,Skali barblano-efekton,Escala de efecto fuzz,,Skaalaa sumennustehostetta,Scaling de l'effet de bruit,Homályosodás effekt átméretezése,Scala l'effetto di fuzz,ファズエフェクトサイズ,반투명 효과 조정,Schaal fuzz effect,Skala fuzz-effekt,Skalowanie efektu szumu,Escala de efeito difuso,,Putere efect de strălucire,Масштабировать эффект шума,Повечавај шумни ефект,Skala fuzz-effekt,Ölçekli fuzz efekti, +Use fuzz effect,DSPLYMNU_DRAWFUZZ,,,,Typ fuzz efektu,Brug fuzz-effekt,Benutze Fuzz-Effekt,,Uzi barblano-efekton,Usar efecto fuzz,,Käytä sumennustehostetta,Effet de bruit,Homályosodás effekt használata,Usa l'effetto di fuzz,ファズエフェクトを使用,반투명 효과 사용,Gebruik fuzz effect,Bruk fuzz-effekt,Użyj efektu szumu,Usar efeito difuso,,Mod efect de strălucire,Использовать эффект шума,Користи шумни ефект,Använd fuzz-effekt,Fuzz efekti kullanın, +Classic Transparency,DSPLYMNU_OLDTRANS,,,,Klasická průhlednost,Klassisk gennemsigtighed,Klasssische Transparenz,,Klasika Travidebleco,Transparencia clásica,,Perinteinen läpinäkyvyys,Transparence classique,Klasszikus átlátszóság,Trasparenza classica,旧式の透明度,구형 투명도,Klassieke transparantie,Klassisk gjennomsiktighet,Klasyczna Przezroczystość,Transparência Clássica,,Transparență Clasică,Классическая прозрачность,Класична транспарентност,Klassisk genomskinlighet,Klasik Şeffaflık, +Lost Soul translucency,DSPLYMNU_TRANSSOUL,,,,Průhlednost Ztracených duší,Fortabt sjæl-translucens,Transparenz für Verlorene Seelen,,Diafaneco de Perdita Animo,Traslucidez del Alma Errante,,Kadonneiden sielujen läpikuultavuus,Transparence des âmes perdues,Lost soul átlátszóság,Trasparenza anima errante,ロストソウルの透明度,로스트 소울 반투명도,Verloren Ziel doorschijnendheid,Lost Soul gjennomskinnelighet,Przezroczystość Zagubionych Dusz,Translucência da Alma Perdida,Translucidez da Alma Penada,Transparență Suflete Pierdute,Прозрачность потерянных душ,Транспарентност изгубљених душа,Lost Soul-translucens,Kayıp Ruh yarı saydamlığı, +Use fake contrast,DSPLYMNU_FAKECONTRAST,,,,Použít falešný kontrast,Brug falsk kontrast,Benutze falschen Kontrast,,Uzi malveran kontraston,Usar falso contraste,,Käytä tekosävykkyyttä,Faux Contraste,Hamis kontraszt használata,Usa il falso contrasto,フェイクコントラストを使用,가명암 효과 사용,Gebruik vals contrast,Bruk falsk kontrast,Użyj sztuczny kontrast,Usar contraste falso,,Utilizare contrast fals,Имитация контрастного освещения стен,Користи фејк-контраст,Använd falsk kontrast,Sahte kontrast kullanın, +Rocket Trails,DSPLYMNU_ROCKETTRAILS,,,,Kouř raket,Raketspor,Raketenschweife,,Raketospuroj,Rastro de cohetes,,Rakettivanat,Trainées des Roquettes,Rakéta füstnyomok,Scia del razzo,ロケットの軌跡,로켓 추진 효과,Raketsporen,Rakettspor,Wiązki Rakiet,Rastro de foguete,Rasto dos Mísseis,Dâră Rachete,Дымовой след у ракет,Траг дима код ракета,Raketspår,Roket Parkurları, +Blood Type,DSPLYMNU_BLOODTYPE,,,,Druh krve,Blodtype,Blut-Typ,,Sangad-efekto,Sangre chorreando,,Verityyli,Type de particules Sang,Vér fajta,Tipo di sangue,血の種類,혈흔 효과,Bloedtype,Blodtype,Typ Krwi,Tipo de sangue,,Tip efecte sângeroase,Тип крови,Тип крви,Blodtyp,Kan Grubu, +Bullet Puff Type,DSPLYMNU_PUFFTYPE,,,,Druh kouře nábojů,Kuglestød type,Pistolenrauch-Typ,,Pulvo pro kolizio de kuglo,Polvo por impacto de bala,,Luotien pöllähdystyyli,Type de particules Balles,Lövedék becsapódás fajtája,Tipo di sbuffo del proiettile,弾煙の種類,탄알 피격 효과,Kogelwolvertype,Bullet Puff Type,Typ Dymu,Tipo de ricochete de bala,,Tip efecte pentru gloanțe,Тип дыма от пуль,Тип рикошета,Kulavfallstyp,Mermi Puf Tipi, +Number of particles,DSPLYMNU_MAXPARTICLES,,,,Množství částic,Antal partikler,Anzahl Partikel,,Nombro da partikloj,Número de partículas,,Hiukkasten lukumäärä,Nombre de particules,Részecskék száma,Numero di particelle,パーティクルの最大数,최대 입자 수,Aantal deeltjes,Antall partikler,Liczba cząsteczek,Número de partículas,,Număr particule,Количество частиц,Број честица,Antal partiklar,Parçacık sayısı, +Number of decals,DSPLYMNU_MAXDECALS,,,,Množství decalů,Antal decals,Anzahl Trefferspuren,,Nombro da dekaloj,Número de calcomanías,,Siirtokuvien lukumäärä,Number de décalques,Lövésnyomok száma,Numero di decal,デカールの最大数,최대 데칼 수,Aantal stickers,Antall dekaler,Liczba kalk,Número de decalques,,Număr autocolante,Количество декалей,Број декала,Antal dekaler,Çıkartma sayısı, +Show player sprites,DSPLYMNU_PLAYERSPRITES,,,,Zobrazit hráčovy sprity,Vis spiller sprites,Zeige Spieler-Sprites,,Montri ludanto-rastrumojn,Mostrar «sprites» del jugador,,Näytä pelaajaspritet,Montrer les sprites joueur,Játékos sprite-ok mutatása,Mostra gli sprite del giocatore,プレイヤーの武器の表示,1인칭 무기 표시,Toon speler sprites,Vis spillerens sprites,Pokaż sprite'y gracza,Exibir sprites do jogador,,Afișare arme,Отображение спрайтов игрока,Прикажи спрајтове играча,Visa spelarens sprites,Oyuncu sprite'larını göster, +Death camera,DSPLYMNU_DEATHCAM,,,,Posmrtná kamera,Dødskamera,Todeskamera,,Dummorta tripersona kamerao,Muerte del jugador en tercera persona,,Kuolonkamera,Caméra 3ème pers à la mort,Halál kamera,Telecamera all'atto della morte,死亡時の三人称視点,사망 화면 표시,Doodscamera,Dødskamera,Kamera śmierci,Câmera de morte,Câmara da morte,Cameră de Deces,Вид от 3-го лица при смерти,Смртна камера,Dödskamera,Ölüm kamerası, +Teleporter zoom,DSPLYMNU_TELEZOOM,,,,Zoom při teleportaci,Teleporter zoom,Teleporter Zoom,,Teleportila zomo,Zoom en teletransporte,,Kaukosiirrynnän kameran zoomaus ,Zoom sur téléportation,Teleporter ráközelítés,Zoom telecamera,テレポーター使用時のズーム,순간이동 효과,Teleporter zoom,Teleporter zoom,Przybliżenie teleportowania,Zoom de teletransporte,,Apropriere Cameră la Teleportare,Увеличение при телепортации,Зум током телепортације,Teleportörens zoom,Işınlayıcı yakınlaştırma, +Earthquake shake intensity,DSPLYMNU_QUAKEINTENSITY,,,,Intenzita zemětřesení,Intensitet af jordskælv,Erdbeben Intensität,,Egeco de tertremo,Intensidad del terremoto,,Maanjäristystehosteen voimakkuus,Intensité des séismes,Földrengés erőssége,Intensità vibrazione terremoto,地震エフェクトの激しさ,지진 효과 강도,Aardbevingsschoksintensiteit,Intensitet av jordskjelvrystelser,Siła trzęsienia ziemi,Intensidade do tremor de terremoto,,Intensitate zguduire la cutremur,Интенсивность тряски землетрясений,Интенсивност земљотреса,Intensitet av jordbävningar,Deprem sarsıntı şiddeti, +Interpolate monster movement,DSPLYMNU_NOMONSTERINTERPOLATION,,,,Interpolovat pohyb příšer,Interpolere monsterbevægelse,Interpoliere Monsterbewegung,,Interpoli monstro-movadon,Interpolar movimiento de los monstruos,,Interpoloi hirviöiden liike,Interpolation des monstres,Szörny mozgás simítása,Interpola il movimento dei mostri,モンスターの移動補間,개체 이동 보정,Interpoleer monsterbewegingen,Interpolere monsterbevegelse,Interpolacja ruchu potworów,Interpolar movimento de monstros,,Interpolare mișcare monștri (efect vizual),Сглаживание движения монстров,Интерполирај кретање чудовишта,Interpolera monsterrörelse,Canavar hareketini enterpole et, +Menu dim,DSPLYMNU_MENUDIM,,,,Síla barvy pozadí v menu,Menu dæmpes,Menüabdunklung,,Menuo-malheleco,Atenuación del menú,,Valikon himmennys,Assombrissement menu,Menü homályosítása,Offuscamento menu,メニュー背景,메뉴 배경색 강도,Donkere menuachtergrond,Demp meny,Mgła w menu,Atenuação do menu,,Întunecare meniu,Затемнение фона меню,Пригушивање менија,Dimma menyn,Menü loş, +Dim color,DSPLYMNU_DIMCOLOR,,,Dim colour,Barva pozadí v menu,Dim farve,Abdunklungsfarbe,,Malheleca koloro,Color de la atenuación,,Himmennysväri,Couleur de l'assombrissement,Homályosítás színe,Colore offuscamento,背景色,배경색 설정,Donkere kleur,Demp farge,Kolor mgły,Cor da atenuação,,Culoare întunecare,Цвет затемнения,Боја пригушивања,Dimma färgen,Loş renk, +View bob amount while moving,DSPLYMNU_MOVEBOB,,,,Pohupování pohledu při pohybu,Vis bob-beløb under bevægelse,Waffenpendeln beim Bewegen,,Vidi kvanton de kapo-balanciĝo dum movado,Cantidad de balanceo al moverse,,Aseen heilumisvoimakkuus liikkeessä,Chaloupage arme en movement,Fegyver mozgása lépés közben,Ammontare di bob di movimento,視点揺れする移動値,이동 시 화면 흔들림 강도,Bekijk bob bedrag terwijl je beweegt,Vis bob-beløp mens du beveger deg,Dygaj kiedy się ruszasz,Quantidade de balanço durante movimento,,Mișcare cameră în timpul deplasării,Покачивание камеры при движении,Тресење камере током кретања,Visa bob-mängden under förflyttning,Hareket halindeyken bob miktarını görüntüleme, +View bob amount while not moving,DSPLYMNU_STILLBOB,,,,Pohupování pohledu v klidu,"Vis bob-beløbet, mens du ikke bevæger dig",Waffenpendeln bei Nichtbewegen,,Vidi kvanton de kapo-balanciĝo dum ne movado,Cantidad de balanceo al no moverse,,Aseen heilumisvoimakkuus levossa,Chaloupage arme statique,Fegyver mozgása egy helyben,Ammontare di bob di movimento da fermo,視点揺れしない移動値,정지 시 화면 움직임 강도,Bekijk bob bedrag terwijl je niet beweegt,Vis bobmengde mens du ikke beveger deg,Dygaj kiedy się nie ruszasz,Quantidade de balanço parado,,Mișcare cameră în timpul staționării,Покачивание камеры при бездействии,Тресење камере током неактивности,Visa bob-mängden när den inte rör sig,Hareket etmiyorken bob miktarını görüntüleme, +Weapon bob speed,DSPLYMNU_BOBSPEED,,,,Rychlost pohupování zbraně,Våben bob hastighed,Waffenpendelgeschwindigkeit,,Rapido de armilo-balanciĝo,Velocidad de balanceo de Arma,,Aseen heilumisnopeus,Vitesse du chaloupage,Fegyver mozgás sebesség,Velocità di bob dell'arma,武器揺れ速度,무기 흔들림 속도,Snelheid wapenzwaaieffect,Våpen bob hastighet,Szybkość ruchu broni,Velocidade de balanço de arma,,Viteză mișcare arme,Скорость покачивания оружия,Брзина трсења оружја,Vapens hastighet,Silah bob hızı, +,,Scaling,,,,,,,,,,,,,,,,,,,,,,,,,, +Scaling Options,SCALEMNU_TITLE,,,,Nastavení škálování rozhraní,Indstillinger for skalering,Skalierungsoptionen,,Skalo-Agordoj,Opciones de escalado,,Skaalausasetukset,Option de mise à l'échelle,Méretezési Beállítások,Opzioni di scala,スケーリング オプション,배율 설정,Schaalopties,Alternativer for skalering,Opcje skalowania,Opções de escala,,Setări Dimensiuni,Настройки масштабирования,Подешавања размере,Skalningsalternativ,Ölçeklendirme Seçenekleri, +Overrides for above setting,SCALEMNU_OVERRIDE,,,,Potlačení nastavení výše,Overrides for ovenstående indstilling,Spezialisierungen,,Transpasoj por ĉi-supre agordo,Anular ajuste anterior,,Ohittaa asetuksen ylhäällä,Annule les paramètres au dessus,Beállítások felülírása,Sovrascritture per i settaggi sopra,設定の上書き,위 설정을 위해 무시,Overschrijdingen voor bovenstaande instelling,Overstyrer for innstillingen ovenfor,Nadpisuje dla powyższego ustawienia,Anular configurações acima,,Suprascriere pentru setările de mai sus,Задать специальные настройки,Специјална подешавања,Överordnar ovanstående inställningar,Yukarıdaki ayar için geçersiz kılmalar, +Messages,SCALEMNU_MESSAGES,,,,Oznámení,Meddelelser,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,,Üzenetek,Messaggi,メッセージ類,메시지,Berichten,Meldinger,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке,Meddelanden,Mesajlar, +Console,SCALEMNU_CONSOLE,,,,Konzole,Konsol,Konsole,,Konzolo,Consola,,Konsoli,,Konzol,,コンソール,콘솔,,Konsoll,Konsola,,Consola,Consolă,Консоль,Конзола,Konsol,Konsol, +Status bar,SCALEMNU_STATBAR,,,,Stavový panel,Statuslinje,Statusleiste,,Stata baro,Barra de estado,,Tilapalkki,Barre d'état,Státusz sáv,Barra di stato,ステータスバー,상태 바,Statusbalk,Statuslinje,Pasek statusu,Barra de status,Barra de estado,Bară de Stare,Строка состояния,Статусна трака,Statusfältet,Durum çubuğu, +Fullscreen HUD,SCALEMNU_HUD,,,,HUD přes celou obrazovku,HUD i fuld skærm,Vollbild-HUD,,Tutekrana HUD,HUD de pantalla completa,,Täyden ruudun tilanäyttö,ATH plein écran,Teljes képernyős HUD,HUD a pieno schermo,全画面HUD,전체화면 HUD,Volle scherm HUD,HUD i fullskjerm,HUD pełnoekranowy,HUD de tela cheia,HUD de ecrã cheio,Interfață pe Timp de Joc tip Fullscreen,Полноэкранный интерфейс,HUD преко целог екрана,HUD i fullskärm,Tam Ekran HUD, +Alternative HUD,SCALEMNU_ALTHUD,,,,Alternativní HUD,Alternativ HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternativ HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативный интерфейс,Алтернативни HUD,Alternativ HUD,Alternatif HUD, +HUD preserves aspect ratio,SCALEMNU_HUDASPECT,,,,HUD zachovává poměr stran,HUD bevarer formatforholdet,HUD bewahrt Seitenverhältnisse,,HUD konservas aspekto-proporcion,HUD conserva la rel. de aspecto,,Tilanäyttö säilyttää kuvasuhteen,ATH préserve le rapport d'aspect,A HUD képarány visszaállítása,HUD preserva le proporzioni,HUDのアスペクト比維持,HUD 화면 비율 보존,HUD behoudt de beeldverhouding,HUD bevarer størrelsesforholdet,HUD zachowuje współczynnik proporcji,HUD deve preservar proporção da tela,,Interfața pe Timp de Joc își Păstrează Aspectul,Сохранение соотношения сторон интерфейса,Сачувај пропорције HUD-а,HUD behåller bildförhållandet,HUD en boy oranını korur, +Use default scale,SCALEMNU_USEUI,,,,Použít výchozí velikost,Brug standardskala,Benutze Standardskalierung,,Uzi defaŭltskalon,Usar escalado por defecto,,Käytä oletusmittakaavaa,Défaut,Alap arányok használata,Usa la scala di default,通常サイズを使う,기본 배율 사용,Gebruik standaardweegschaal,Bruk standard skala,Użyj domyślnej skali,Usar escala padrão,,Folosește dimensiunea implicită,Размер по умолчанию,Уобичајена размера,Använder standardskalan,Varsayılan ölçeği kullan, +Scale to fullscreen,SCALEMNU_USEFS,,,,Škalovat přes celou obrazovku,Skaleres til fuld skærm,Skaliere auf Vollbild,,Skali al tutekrano,Escalar a pant. completa,,Skaalaa täyteen ruutuun,Plein écran,Teljes képernyőre arányítás,Scala a pieno schermo,全画面に拡大,전체화면에 맞게 축척,Schaalbaar tot volledig scherm,Skaler til fullskjerm,Przeskaluj do pełnego ekranu,Escala de tela cheia,Escalar para ecrã cheio,Dimensionare la modul Fullscreen,Масштабировать со всем экраном,Проширење преко целог екрана,Skala till fullskärm,Tam ekrana ölçeklendir, +Adapt to screen size,SCALEMNU_ADAPT,,,,Přizpůsobit velikosti obrazovky,Tilpasning til skærmstørrelse,Passe an Bildschirmgröße an,,Adapti al ekranamplekso,Adaptar al tamaño de pantalla,,Sovita näytön kokoon,Ecran,Képernyő mérethez alkalmazkodik,Adatta alla dimensione della schermata,画面サイズに合わせる,화면 사이즈에 맞게 축척,Aanpassen aan de grootte van het scherm,Tilpass til skjermstørrelse,Dostosuj do pełnego ekranu,Adaptar ao tamanho de tela,,Adaptează la dimensiunea ecranului,Адаптироваться к размеру экрана,Прилагоди размери екрана,Anpassas till skärmstorlek,Ekran boyutuna uyum sağlayın, +,,HUD,,,,,,,,,,,,,,,,,,,,,,,,,, +HUD Options,HUDMNU_TITLE,,,,Nastavení rozhraní a HUD,HUD-indstillinger,HUD Optionen,,HUD Agordoj,Opciones del HUD,,Tilanäytön asetukset,Options ATH,HUD beállításai,Opzioni HUD,HUDオプション,HUD 설정,HUD-opties,HUD-alternativer,Opcje HUD,Opções de HUD,,Setări Interfață pe Timp de Joc,Настройки отображения информации,HUD подешавања,Alternativ för HUD,HUD Seçenekleri, +Alternative HUD,HUDMNU_ALTHUD,,,,Alternativní HUD,Alternativ HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH Alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternativ HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативное отображение информации,Алтернативни HUD,Alternativ HUD,Alternatif HUD, +Message Options,HUDMNU_MESSAGE,,,,Oznámení,Indstillinger for meddelelser,Nachrichtenoptionen,,Mesaĝo-Agordoj,Opciones de mensajes,,Viestiasetukset,Options des Messages,Üzenet beállítások,Opzioni messaggi,メッセージの設定,메시지 설정,Berichtopties,Meldingsalternativer,Opcje wiadomości,Opções de mensagem,,Setări Mesaje,Настройки сообщений,Подешавања порука,Alternativ för meddelanden,Mesaj Seçenekleri, +User interface scale,HUDMNU_UISCALE,,,,Velikost rozhraní,Skala for brugergrænseflade,Benutzerinterfaceskalierung,,Interfaco-skalo de uzanto,Escala de la interfaz de usuario,,Käyttöliittymän skaalaus,Echelle de l'interface,Felhasználó Panel mérete,Scala l'interfaccia utente,インターフェースの大きさ,인터페이스 크기 조정,Schaal gebruikersinterface,Skalering av brukergrensesnitt,Skala interfejsu,Escala de interface de usuário,Escala de interface do utilizador,Dimensiune Interfață Utilizator,Размер интерфейса,Размера интерфејса,Skala för användargränssnittet,Kullanıcı arayüzü ölçeği, +Force default crosshair,HUDMNU_FORCECROSSHAIR,,,,Vynutit výchozí zaměřovač,Tvinge standard-trådkorset,Erzwinge Standard-Fadenkreuz,,Devigi defaŭltan reteton,Forzar retícula por defecto,,Pakota oletustähtäin,Forcer Viseur par défaut,Alapcélkereszt erőltetése,Forza il mirino di default,デフォルトの照準を使う,기본 조준점 강제 설정,Forceer standaard dradenkruis,Tving frem standard trådkors,Wymuś domyślny celownik,Forçar mira padrão,,Forțare țintă implicită,Всегда стандартный прицел,Форсирај уобичајени нишан,Forcera standardkorset,Varsayılan artı işaretini zorla, +Grow crosshair when picking up items,HUDMNU_GROWCROSSHAIR,,,,Zvětšit zaměřovač při sebrání předmětu,"Vokse trådkorset, når du samler genstande op",Größeres Fadenkreuz bei Gegenstandsaufnahme,,Grandigi reteton kiam oni prenas objektojn,Aumentar retícula al obtener obj.,Crecer retícula al obtener obj.,Suurenna tähtäintä esineitä poimiessa,Agrandir viseur en prenant un objet,A célkereszt nőjön tárgyfelvételkor,Accresci il mirino quando si raccolgono oggetti,アイテム取得時に照準を大きくする,아이템 획득 시 조준점 키우기 ,Vergroot het dradenkruis bij het oppakken van items,Utvid trådkorset når du plukker opp elementer,"Powiększ celownik, gdy podnosisz przedmioty",Aumentar mira ao pegar itens,Aumentar mira ao apanhar itens,Mărește ținta la ridicarea obiectelor,Увеличение прицела при подборе,Побољшај нишан током купљења предмета,Växer hårkorset när du plockar upp föremål,Eşyaları alırken artı işaretini büyütün, +Display nametags,HUDMNU_NAMETAGS,,,,Zobrazovat jmenovky,Viser navneskilte,Zeige Gegenstandsnamen,,Montri nometikedojn,Mostrar etiquetas,,Näytä nimitunnisteet,Afficher noms des objets,Névtábla mutatása,Mostra le targhette identificative,ディスプレイネームタグ,이름표 표시,Naamlabels weergeven,Vis navnelapper,Pokazuj nazwy przedmiotów,Exibir nomes,,Indică numele obiectelor,Указание названия предметов,Прикажи имена предмета,Visa namnbrickor,İsim etiketlerini gösterin, +Nametag color,HUDMNU_NAMETAGCOLOR,,,Nametag colour,Barva jmenovek,Farve på navneskilte,Farbe für Gegenstandsnamen,,Nometikeda koloro,Color de las etiquetas,,Nimitunnisteen väri,Couleur des noms d'objet,Névtábla szín,Colore targhetta identificativa,ネームタグ色,이름표 색깔,Kleur naamlabel,Farge på navneskilt,Kolor nazw przedmiotów,Cor dos nomes,,Culoare nume obiecte,Цвет названия предметов,Боја имена предмета,Färg på namnbrickor,İsim etiketi rengi, +Use old ouch mug shot formula,HUDMNU_OLDOUCH,,,,Použít starý vzorec pro 'ouch' portrét,"Gammel formel for ""av"" ansigt",Alte Formel für „Autsch“-Gesicht,,Uzi maljunan formulon de aj-vizaĝo-foto,Usar formula antigua de foto de daño,,Käytä vanhaa auts-naamakuvan kaavaa,Ancien code pour l' « ouch face »,Régi sebződő fej formula használata,Mostra la formula originale del viso 'ouch',旧式ouch mug shotを使用,구형 피격 표정 스프라이트 방식 사용,"Oude formule voor ""Ouch""-gezicht",Bruk formelen for gamle forbryterbilder,Używaj starej formuły twarzy przy dostaniu obrażeń,Usar fórmula original do rosto de dor,,Utilizează modul portret vechi,Старая формула для портрета,Стара формула за приказ лика,"Använd den gamla formeln med ""ouch"" foton",Eski ouch oyuncu yüzü formülünü kullanın, +Hexen weapon flashes,HUDMNU_HEXENFLASHES,,,,Druh bliknutí zbraní v Hexenu,Hexen-våben blinker,Hexen-Waffenblitze,,Ekbriloj de Hexen-armo,Destello armas Hexen,,Hexenin asevälähdykset,Flash d'arme dans Hexen,Hexen fegyver villanások,Bagliori armi Hexen,Hexen武器の視界色,헥센 무기 반짝임,Hexen-wapen flitsen,Hexen våpen blinker,Błysk przy podnoszeniu broni z Hexena,Flash de arma do Hexen,,Tip strălucire arme Hexen,Тип вспышки оружия в Hexen,Треперење оружја у Hexen-у,Hexen-vapen blinkar,Hexen silah flaşları, +Poison damage flashes,HUDMNU_POISONFLASHES,,,,Druh bliknutí při otrávení,Giftskabte skader blinker,Gift-Effekt,,Ekbriloj de venondamaĝo,Destello daño por veneno,,Myrkkyvahinkovälähdykset,Flash de poison dans Hexen,Méreg sebzés villanások,Bagliori danno da veleno,毒ダメージの視界色,독데미지 반짝임,Vergiftigingsschade knippert,Giftskade blinker,Efekt obrażeń przy zatruciu,Flash de dano por veneno,,Tip strălucire efect de otrăvire,Тип вспышки яда,Треперење током тровања,Blinkar för giftskador,Zehir hasarı flaşları, +Ice death flashes,HUDMNU_ICEFLASHES,,,,Druh bliknutí při smrti umrznutím,Isdødsblink,Eis-Tod-Effekt,,Ekbriloj de glacimorto,Destello muerte por hielo,,Jääkuolemavälähdykset,Flash de morts par glace,Jéghalál villanások,Bagliori morte da ghiaccio,氷結死の視界色,동사시 반짝임,IJsdood knippert,Isdød blinker,Błysk przy śmierci poprzez zamrożenie,Flash de morte por congelamento,,Tip strălucire deces prin înghețare,Тип вспышки при смерти от льда,Треперење током смрти од леда,Blinkar för isdöd,Buz ölüm flaşları, +Poison Buildup flashes,HUDMNU_HAZARDFLASHES,,,,Druh blikání při kumulaci jedu,Gift Buildup blinker,Kumulativer Gift-Effekt,,Ekbriloj de venonamasigo,Destello acumulación de veneno,,Myrkyn kertymisvälähdykset,Flash d'accumulation de poison,Fokozatos méreg sebzés villanások,Bagliori danno accumulato da veleno,蓄積毒の視界色,독데미지 반짝임 증강,Vergiftiging Opbouw knippert,Giftoppbygging blinker,Miganie przy nasilaniu się trucizny,Flash por acúmulo de dano por veneno,,Tip strălucire acumulare de otravă,Тип вспышки при скоплении яда,Треперење током гомилања отрова,Blinkningar för giftuppbyggnad,Zehir Birikimi yanıp söner, +Scaling Options,HUDMNU_SCALEOPT,,,,Škálování velikosti rozhraní,Skaleringsmuligheder,Skalierungsoptionen,,Skalo-Agordoj,Opciones de escalado,,Skaalausasetukset,Option de mise à l'échelle,Méretezés Beállítások,Opzioni di scala,スケーリング オプション,배율 설정,Schaalopties,Alternativer for skalering,Opcje skalowania,Opções de escala,,Setări Dimensiuni,Настройки масштабирования,Подешавања размере,Alternativ för skalning,Ölçeklendirme Seçenekleri, +Show IWAD selection dialog,MISCMNU_QUERYIWAD,,,,Zobrazit dialog pro výběr IWADu,Vis IWAD-valgdialogboks,Zeige IWAD-Auswahl,,Montri elektodialogon de IWAD,Mostrar diálogo de selección de IWAD,,Näytä IWAD-valintaikkuna,Afficher la séléction d'IWAD,IWAD kiválasztó ablak mutatása,Mostra la schermata della selezione IWAD,IWADの選択画面を表示,IWAD 게임 선택창 표시,IWAD-selectiedialoogvenster weergeven,Vis IWAD-valgdialogboks,Pokaż ekran wyboru gry (IWAD),Exibir janela de seleção de IWAD,,Afișează fereastra de selectare a jocurilor,Выбор IWAD-файла при запуске,Покажи IWAD дијалог за избор,Visa dialogrutan för val av IWAD,IWAD seçim iletişim kutusunu göster, +Enable cheats from all games,MISCMNU_ALLCHEATS,,,,Povolit cheaty ze všech her,Aktiver snyderier fra alle spil,Ermögliche Cheats aus allen Spielen,,Ebligi trompojn el tutaj ludoj,Activar trucos de todos los juegos,,Ota käyttöön huijauskoodit kaikista peleistä,Activer cheats de tous les jeux,Minden játék csaláskódja érvényes,Abilita tutti i cheat da tutti i giochi,全ゲームでチート使用可にする,모든 게임에 치트 허용,Laat bedriegers van alle spellen toe,Aktiver juks fra alle spill,Włącz oszustwa ze wszystkich gier,Habilitar trapaças de todos os jogos,Permitir batotas de todos os jogos,Permite codurile din toate jocurile,Читы из всех игр,Омогући читове од свих игара,Aktivera fusk från alla spel,Tüm oyunlardan hileleri etkinleştirin, +,,Option Menus,,,,,,,,,,,,,,,,,,,,,,,,,, +Enable making screenshots by scripts,MISCMNU_ENABLESCRIPTSCREENSHOTS,,,,Povolit skriptům pořizovat snímky obrazovky,Aktivering af skærmbilleder ved hjælp af scripts,"Erlaube Skripts, Screenshots zu machen",,Ebligi faradon de ekrankopioj per skriptoj,Habilitar captura de pantalla por scripts,,Salli komentosarjoin otetut kuvakaappaukset,Autoriser les Scripts à prendre des captures,Szkriptek is készíthetnek képernyőképet,Abilita la cattura dello schermo tramite scripts,スクリプトからのスクショ作成を有効化,저장/불러오기 확인,Screenshots maken met behulp van scripts,Gjør det mulig å lage skjermbilder av skript,Pozwól na robienie zrzutów ekranu przez skrypty,Habilitar capturas de tela por scripts,Permitir capturas de ecrã por scripts,Posibilitate de a face poze prin scripturi,Возможность делать снимки экрана через скрипты,Омогући прављење скриншотова по скрипти,Aktivera att göra skärmdumpar med hjälp av skript,Komut dosyalarıyla ekran görüntüsü almayı etkinleştirme, +Load *.deh/*.bex lumps,MISCMNU_DEHLOAD,,,,Načítat *.deh/*.bex soubory,Indlæsning af *.deh/*.bex-filer,Lade *.deh/*.bex Daten,,Ŝargi je *.deh/*.bex lumpoj,Cargar archivos *.deh/*.bex,,Lataa *.deh/*.bex-lump-tiedostot,Charger fichiers *.deh/*.bex,*.deh/*.bex lump-ok betöltése,Carica i lump *.deh/*.bex,.deh/.bexファイルを読み込む,*.deh/*.bex 럼프 파일 불러오기,*.deh/*.bex laden,Last inn *.deh/*.bex-arkiver,Załaduj dane *.deh/*.bex,Carregar lumps *.deh/*.bex,,Încarcă nodurile *.deh/*.bex,Загружать файлы *.deh/*.bex,Учитај *.deh/*.bex фајлове,Ladda *.deh/*.bex-filer,.deh/*.bex topaklarını yükle, +Cache nodes,MISCMNU_CACHENODES,,,,Cachovat nodes,,Nodes zwischenspeichern,,Kaŝmemoraj nodoj,Caché de nodos,,Tallenna solmut välimuistiin,Mise en cache des nodes,Node-ok cache-lése,Cache dei nodi,ノードキャッシュ,캐시 노드,Cache nodes,Bufre noder,Węzły pamięci podręcznej,Cachê de nodes,Cache de nodes,Depozitare noduri cache,Кэширование узлов,Кеширани чворови,Cache-noder,Önbellek düğümleri, +Time threshold for node caching,MISCMNU_CACHETIME,,,,Časový práh pro cachování nodes,Tidsgrænse for node-cache,Zeitschwelle für das Zwischenspeichern von Nodes,,Templimo pro kaŝmemornodi,Umbral de tiempo para caché de nodos,,Kynnysaika solmujen välimuistitallennukseen,Limite cache des nodes,Időhatár node cache-hez,Soglia di tempo per il caching dei nodi,ノードキャッシュ時間の閾値,노드 캐싱을 위한 시간 임계값 계산,Tijdsdrempel voor het cachen van nodes,Tidsterskel for nodebufring,Próg czasowy buforowania węzłów,Limite de tempo para cachê de nodes,Limite de tempo para cache de nodes,Limită de timp pentru depozitare cache,Временной порог для кэширования узлов,Временски праг за кеширање чвора,Tidströskel för cachelagring av noder,Düğüm önbelleğe alma için zaman eşiği, Clear node cache,MISCMNU_CLEARNODECACHE,,,,Vyčistit node cache,Ryd node-cache,Nodespeicher löschen,,Forigi kaŝmemorajn nodojn,Limpiar Caché de nodos,,Tyhjennä solmuvälimuisti,Vider le cache des nodes,Cache node ürítése,Pulisci la cache dei nodi,ノードのキャッシュをクリア,노드 캐시를 삭제,Node cache legen,Tøm nodebuffer,Wyczyść pamięć podręczną,Limpar cachê de nodes,Limpar cache de nodes,Ștergere noduri cache,Очистить кэш узлов,"Избриши кеширане чворове -",Düğüm önbelleğini temizle -Allow skipping of intermission scrollers,MISCMNU_INTERSCROLL,,,,Povolit přeskakování skrolujících obrázků,Tillad at springe over pausescrollere,Erlaube Überspringen von Intermission-Scrollern,,Permesi preterpason de intermitaj rulumoj,Permitir omisión de intermedios,,Salli vierivien väliruutujen ohittaminen,Sauter compteurs d'intermission,Pályaközi szünetek átugorhatóak,Consenti di saltare gli scorrimenti delle intermissioni,クリア結果集計のスキップを許可,인터미션 스크롤러 생략 허용,Overslaan van intermissiescrollers toestaan,Tillat å hoppe over pauserullere,Pozwól na pominięcie wstawek,Pular telas de intervalo entre fases,Saltar ecrãs de intervalo entre níveis,Permite saltul peste inserările de text,Разрешение пропуска текстовых вставок,Дозволи прескакање прелаза са текстовима,Ara kaydırıcıların atlanmasına izin ver -Network Options,NETMNU_TITLE,,,,Nastavení sítě,Netværksindstillinger,Netzwerkeinstellungen,,Reta Agordoj,Opciones de Red,,Verkkoasetukset,Options Réseau,Hálózati Beállítások,Opzioni network,ネットワーク オプション,네트워크 설정,Netwerkopties,Nettverksalternativer,Opcje Sieci,Opções de Rede,,Setări de Rețea,Настройки сети,Мрежна подешавања,Ağ Seçenekleri -Local options,NETMNU_LOCALOPTIONS,,,,Lokální nastavení,Lokale indstillinger,Lokale Einstellungen,,Lokaj agordoj,Opciones locales,,Paikallisasetukset,Options Locales,Helyi beállítások,Opzioni locali,ローカル オプション,로컬 설정,Lokale opties,Lokale alternativer,Opcje Lokalne,Opções locais,,Setări Locale,Локальные настройки,Локална подешавања,Yerel seçenekler -Movement prediction,NETMNU_MOVEPREDICTION,,,,Predikce pohybu,Forudsigelse af bevægelser,Bewegungsvorausberechnung,,Movprognozado,Predicción de Movimiento,,Liikkeen ennakoiminen,Prédiction de Mouvement,Mozgás előrejelzés,Predizione movimenti,移動予測,움직임 예측도,Voorspelling van bewegingen,Forutsigelse av bevegelse,Przewidywanie Ruchu,Previsão de movimento,,Anticipare mișcare,Предсказание движения,Предвиђање покрета,Hareket tahmini -Predict line actions,NETMNU_LINESPECIALPREDICTION,,,,Predikce čárových akcí,Forudsige linjehandlinger,Berechne Linienaktionen voraus,,Prognozi linio-agojn,Predecir acciones de línea,,Ennakoi viivasuorat toiminnat,Prédiction des actions de ligne,Előrejelzés vonal művelet,Predizione azioni di linea,line actionsを予測する,라인 움직임 감지,Voorspel lijnacties,Forutsi linjehandlinger,Przewidź akcje linii,Prever ações de linha,,Anticipează acționarea liniilor,Предсказание действий на уровне,Предвиђање линијске радње,Hat eylemlerini tahmin edin -Prediction Lerp Scale,NETMNU_PREDICTIONLERPSCALE,,,,Velikost interpolace predikce,Forudsigelse Lerp-skala,Vorberechnungs Lerp-Skalierung,,Skalo de Linia Lnterpolado,Escala de interp. lineal de predicción,,Lineaarisen interpolaatioennakoinnin skaalaus,Prédiction d'échelle LERP,Előrejelzés LERP Arány,Scala Lerp predizione,リープスケール予測,러프 예측 강도,Voorspelling Lerp Scale,Prediksjon Lerp-skala,Przewidywanie Skali Lerp,Escala de previsão de LERP,,Anticipare scară lerp,Предсказание увеличения доп. задержки,Предвиђање лерп скале,Tahmin Lerp Ölçeği -Lerp Threshold,NETMNU_LERPTHRESHOLD,,,,Práh interpolace,Lerp-tærskel,Lerp-Schwellwert,,Limito de Linia Interpolado,Umbral de interp. lineal,,Interpolaatiokynnys,Limite LERP,LERP küszöbérték,Soglia Lerp,リープしきい値,러프 계산,Lerp Threshold,Lerp-terskel,Próg Lerp,Limite de LERP,,Prag Lerp,Порог доп. задержки,Лерп праг,Lerp Eşiği -Host options,NETMNU_HOSTOPTIONS,,,,Nastavení hostitele,Værtsindstillinger,Gastoptionen,,Agordoj de Gastiganto,Opciones de Host,,Isäntäasetukset,Options Hôte,Host beállítások,Opzioni ospitante,ホスト オプション,호스트 설정,Verhuurders opties,Vertsalternativer,Opcje hosta,Opções de host,,Setări gazdă,Настройки сервера,Подешавања домаћина,Ev sahibi seçenekleri -Extra Tics,NETMNU_EXTRATICS,,,,Extra tiky,Ekstra tics,,,Ekstraj Tikoj,Tics Extra,,Lisäticit,Tics supplémentaires,Extra Tic-ek,Tics extra,予備秒数,추가 틱,,Ekstra tics,Dodatkowe tiki,Tics extras,,Ticăituri suplimentare,Дополнительные секунды,Додатни тикови,Ekstra Tikler -Latency balancing,NETMNU_TICBALANCE,,,,Vyrovnání latence,Balancering af latenstid,Latenzbalance,,Respondotempo-balancado,Balanceo de latencia,,Viiveen tasapainoitus,Equilibrage de latence,Válaszidő balanszolás,Bilanciamento latenza,レイテンシーバランス,지연 시간 조정,Latency balans,Balansering av ventetid,Balans czasu oczekiwania,Equilíbrio de latência,,Întârzierea echilibrării,Балансировка задержки,Балансирање кашњења,Gecikme dengeleme -Original,OPTVAL_ORIGINAL,,,,Původní,,,,Originala,,,Alkuperäinen,Original,Eredeti,Originale,オリジナル,원형,Origineel,,Oryginalny,Original,,,Изначальный,Оригинално,Orijinal -Optimized,OPTVAL_OPTIMIZED,,,,Optimalizovaný,Optimeret,Optimiert,,Optimumigita,Optimizado,,Optimoitu,Optimisé,Optimalizált,Ottimizzato,最適化,최적화 형,Geoptimaliseerd,Optimalisert,Zoptymalizowany,Otimizado,,Optimizat,Оптимизированный,Оптимизовано,Optimize Edilmiş -Classic (Faster),OPTVAL_CLASSIC,,,,Klasický (rychlejší),Classic (hurtigere),Klassisch (schneller),,Klasika (Pli rapide),Clásico (Más rápido),,Perinteinen (nopeampi),Classique (+ Rapide),Klasszikus (gyorsabb),Classico (più veloce),旧式(速度重視),구형 (빠르게),Klassiek (sneller),Klassisk (raskere),Klasyczny (szybszy),Clássico (Mais rápido),,Clasic (Mai rapid),Классический (быстрее),Класични (бржи),Klasik (Daha Hızlı) -Precise,OPTVAL_PRECISE,,,,Přesný,Præcist,Genau,,Preciza,Preciso,,Tarkka,Précis,Pontos,Preciso,精密,정확하게,Nauwkeurig,Presis,Dokładny,Preciso,,Precis,Точный,Прецизно,Kesin -Capped,OPTVAL_CAPPED,,,,Uzavřený,Begrænset,Limitiert,,Limitigita,Limitado,,Rajoitettu,Limité,Lekorlátozva,Limitato,上限,색상에 맞게,Afgeschermd,Begrenset,Ograniczony,Limitado,,Limitat,Ограниченный,Ограничено,Sınırlı -Particles,OPTVAL_PARTICLES,,,,Částice,Partikler,Partikel,,Partikloj,Partículas,,Hiukkasina,Particules,Részecskék,Particelle,パーティクル,입자만,Deeltjes,Partikler,Cząstki,Partículas,,Particule,Частицы,Честице,Parçacıklar -Sprites,OPTVAL_SPRITES,,,,Sprity,,Sprites,,Spritoj,,,Spriteinä,,Sprite-ok,Sprite,スプライト,스프라이트만,Sprites,Sprites,Sprite'y,Sprites,,Sprite-uri,Спрайты,Спрајтови,Sprite'lar -Sprites & Particles,OPTVAL_SPRITESPARTICLES,,,,Sprity a částice,Sprites og partikler,Sprites und Partikel,,Spritoj kaj Partikloj,Sprites y partículas,,Spriteinä ja hiukkasina,Sprites & Particules,Sprite-ok és részecskék,Sprite e particelle,スプライト & パーティクル,스프라이트+입자,Sprites & Deeltjes,Sprites og partikler,Sprite'y i cząstki,Sprites & Partículas,Sprites e Partículas,Sprite-uri & Particule,Спрайты и частицы,Спрајтови и честице,Sprite'lar ve Parçacıklar -Melt,OPTVAL_MELT,,,,Rozpuštění,Smelt,Verlauf,,Fandi,Derretir,,Sulaminen,Fondu,Olvadás,Scioglimento,メルト,녹는 효과,Smelten,Smelte,Stopienie,Derreter,,Topire,Таяние,Топљење,Eriyik -Burn,OPTVAL_BURN,,,,Oheň,Brænde,Einbrennen,,Bruli,Quemar,,Palaminen,Brûlure,Égés,Bruciamento,バーン,타는 효과,Verbranden,Brenne,Wypalenie,Queimar,,Ardere,Жжение,Спаљивање,Yanmak -Crossfade,OPTVAL_CROSSFADE,,,,Prolínačka,Crossfade,Überblenden,,Transvelki,Entrelazar,,Ristihäivytys,Fondu en croix,Átvezetés,Dissolvenza a croce,クロスフェード,화면 교차,Crossfade,Overblending,Przenikanie,Dissolver,,Ofilire,Увядание,Вењење,Crossfade -Smooth,OPTVAL_SMOOTH_1,"This setting is duplicated in order to allow for different grammatical gender endings in the Russian language (and any other language that depends on a grammatical gender system). In English, due to the lack of a grammatical gender system, both option values are the same.",,,Vyhlazený,Glat,Glatt,,Glata,Fluido,,Pehmeä,Lisse,Simítás,Liscio,スムーズ,부드럽게,Glad,Glatt,Gładki,Suavizado,,Fin,Плавная,Глатко,Pürüzsüz -Smooth,OPTVAL_SMOOTH_2,,,,Vyhlazené,Glat,Glatt,,Glata,Fluido,,Pehmeä,Lisse,Simítás,Liscio,スムーズ,부드럽게,Glad,Glatt,Gładka,Suavizado,,Fin,Плавные,Глатко,Pürüzsüz -Translucent,OPTVAL_TRANSLUCENT,,,,Průhledný,Gennemskinnelig,Transparent,,Diafana,Translúcido,,Läpikuultava,Transparent,Áttetsző,Traslucido,半透明,투명하게,Doorschijnend,Gjennomskinnelig,Przeświecający,Translúcido,,Transparent,Полупрозрачный,Прозрачно,Yarı Saydam -Fuzz,OPTVAL_FUZZ,,,,Šum,,Fuzz,,Lanugo,Borroso,,Sumeus,Bruit Blanc,Homályosítás,Annebbiato,ファズ,퍼즈 효과,Fuzz,,Szum,Difuso,,Sclipitor,Шумовой,Фаз,Fuzz -Shadow,OPTVAL_SHADOW,,,,Stín,Skygge,Schatten,,Ombro,Sombra,,Varjo,Ombre,Árnyék,Ombra,シャドウ,그림자 효과,Schaduw,Skygge,Cień,Sombra,,Umbră,Теневой,Сенка,Gölge -Items,OPTVAL_ITEMS,,,,Předměty,Varer,Gegenstände,,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,아이템들,Artikelen,Gjenstander,Przedmioty,Itens,,Obiecte,Предметы,Предмет,Eşyalar -Weapons,OPTVAL_WEAPONS,,,,Zbraně,Våben,Waffen,,Armiloj,Armas,,Aseet,Armes,Fegyverek,Armi,武器,무기들,Wapens,Våpen,Bronie,Armas,,Arme,Оружие,Оружја,Silahlar -Both,OPTVAL_BOTH,,,,Obojí,Begge,Beide,,Ambaŭ,Ambos,,Molemmat,Les Deux,Mindkettő,Entrambi,両方,둘 다,Beide,Begge,Oba,Ambos,,Ambele,Оба,Оба,Her ikisi de -ZDoom,OPTVAL_ZDOOM,,,,,,,,,,,,,,,,Z둠,,,,,,,,, -Strife,OPTVAL_STRIFE,,,,,,,,,,,,,,,,스트라이프,,,,,,,,, -Player,OPTVAL_PLAYER,,,,Hráč,Spiller,Spieler,,Ludanto,Jugador,,Pelaaja,Joueur,Játékos,Giocatore,プレイヤー,플레이어,Speler,Spiller,Gracz,Jogador,,Jucător,Игрок,Играч,Oyuncu -Map,OPTVAL_MAP,,,,Level,Kort,Level,,Mapo,Mapa,,Kartta,Niveau,Pálya,Mappa,マップ,맵,Kaart,Kart,Mapa,Mapa,,Hartă,Карта,Мапа,Harita -Scale to 640x400,OPTVAL_SCALETO640X400,,,,Zvětšit na 640x400,Skaleres til 640x400,Skaliere auf 640x400,,Skali al 640x400,Escalar a 640x400,,Skaalaa resoluutioon 640x400,Echelle 640x400,640x480-hoz arányít,Scala a 640x400,640x400スケール,640x400까지 확대,Schaal tot 640x400,Skala til 640x400,Skaluj do 640x400,Escalar para 640x400,,Dimensionare la 640x480,Масштабировать до 640x400,Скалирај на 640x400,640x400'e ölçeklendirin -Pixel double,OPTVAL_PIXELDOUBLE,,,,Zdvojení pixelů,Pixel dobbelt,Pixelverdopplung,,Bilderon duobligi,Pixel doble,,Kuvapistekaksinkertaistus,,Pixel duplázás,Pixel doppi,ピクセル2倍,2배 픽셀,Pixel dubbel,Dobbel piksel,Dwukrotnie więcej pikseli,Pixel duplo,,Dublare pixeli,Двойные пиксели,Дупли пиксел,Piksel çift -Pixel quadruple,OPTVAL_PIXELQUADRUPLE,,,,Zčtyřnásobení pixelů,Pixel firedobbelt,Pixelvervierfachung,,Bilderon kvarobligi,Pixel cuádruple,,Kuvapistenelinkertaistus,,Pixel négyszerezés,Pixel quadrupli,ピクセル4倍,4배 픽셀,Pixel viervoudig,Piksel firedoblet,Czterokrotnie więcej pikseli,Pixel quádruplo,,Împătrire pixeli,Учетверённые пиксели,Четвороструки пиксел,Piksel dörtlü -Current weapon,OPTVAL_CURRENTWEAPON,,,,Současná zbraň,Nuværende våben,Aktuelle Waffe,,Nuntempa armilo,Arma actual,,Nykyinen ase,Arme actuelle,Jelenlegi fegyver,Arma corrente,使用中の武器,현 무기,Huidig wapen,Nåværende våpen,Aktualna broń,Arma atual,,Arma curentă,текущего оружия,Тренутно оружје,Mevcut silah -Available weapons,OPTVAL_AVAILABLEWEAPONS,,,,Dostupně zbraně,Tilgængelige våben,Verfügbare Waffen,,Haveblaj armiloj,Armas disponibles,,Käytettävissä olevat aseet,Armes Disponibles,Elérhető fegyverek,Armi disponibili,所持してる武器,사용 가능한 무기들,Beschikbare wapens,Tilgjengelige våpen,Dostępne bronie,Armas disponíveis,,Arme disponibile,доступного оружия,Доступно оружје,Mevcut silahlar -All weapons,OPTVAL_ALLWEAPONS,,,,Všechny zbraně,Alle våben,Alle Waffen,,Ĉiuj armiloj,Todas las armas,,Kaikki aseet,Toutes les armes,Minden fegyver,Tutte le armi,全ての武器,모든 무기들,Alle wapens,Alle våpen,Wszystkie bronie,Todas as armas,,Toate armele,всех видов оружия,Сва оружја,Tüm silahlar -"Level, milliseconds",OPTVAL_LEVELMILLISECONDS,,,,"Level, milisekundy","Level, millisekunder","Level, Millisekunden",,"Nivelo, milisekundoj","Nivel, milisegundos",,"Taso, millisekunnit","Niveau, milisecondes","Pálya, milliszekundum","Livello, millisecondi","現場, ミリ秒","레벨, 밀리초당","Niveau, milliseconden","Nivå, millisekunder","Poziom, milisekundy","Fase, milisegundos","Nível, milisegundos","Nivel, milisecunde","Уровень, миллисекунды","Ниво, милисекунде","Seviye, milisaniye" -"Level, seconds",OPTVAL_LEVELSECONDS,,,,"Level, vteřiny","Level, sekunder","Level, Sekunden",,"Nivelo, sekundoj","Nivel, segundos",,"Taso, sekunnit","Niveau, secondes","Pálya, másodpercek","Livello, secondi","現場, 秒","레벨, 초당","Niveau, seconden","Nivå, sekunder","Poziom, sekundy","Fase, segundos","Nível, segundos","Nivel, secunde","Уровень, секунды","Ниво, секунде","Seviye, saniye" -Level,OPTVAL_LEVEL,,,,Level,,Level,,Nivelo,Nivel,,Taso,Niveau,Pálya,Livello,現場,레벨,Niveau,Nivå,Poziom,Fase,Nível,Nivel,Уровень,Ниво,Seviye -"Hub, seconds",OPTVAL_HUBSECONDS,,,,"Hub, vteřiny","Hub, sekunder","Hub, Sekunden",,"Rekontejo, sekundoj","Hub, segundos",,"Tasokokoelma, sekunnit","Hub, secondes","Csomópont, másodpercek","Hub, secondi","区間, 秒","허브, 초당","Naaf, seconden","Hub, sekunder","Hub, sekundy","Hub, segundos",,"Hub, secunde",Хаб (секунды),"Хуб, секунде","Hub, saniye" -Hub,OPTVAL_HUB,,,,Hub,,Hub,,Rekontejo,Hub,,Tasokokoelma,Hub,Csomópont,Hub,区間,허브,Naaf,,,,,,Хаб,Хуб,Hub -"Total, seconds",OPTVAL_TOTALSECONDS,,,,"Celkový, vteřiny","I alt, sekunder","Gesamt, Sekunden",,"Tuto, sekundoj","Total, segundos",,"Yhteensä, sekunnit","Total, secondes","Teljes, másodpercek","Totale, secondi","合計, 秒","누적 경과, 초당","Totaal, seconden","Totalt, sekunder","Razem, sekundy","Total, segundos",,"Total, secunde",Общее (секунды),"Тотал, секунде","Toplam, saniye" -Total,OPTVAL_TOTAL,,,,Celkový,I alt,Gesamt,,Tuto,,,Yhteensä,Total,Teljes,Totale,合計,누적 경과,Totaal,Totalt,Razem,,,Total,Общее,Тотал,Toplam -"System, seconds",OPTVAL_SYSTEMSECONDS,,,,"Systémový, vteřiny","System, sekunder","System, Sekunden",,"Sistemo, sekundoj","Sistema, segundos",,"Järjestelmä, sekunnit","Système, secondes","Rendszer, másodpercek","Sistema, secondi","PC時刻, 秒","시스템, 초당","Systeem, seconden","System, sekunder","System, sekundy","Sistema, segundos",,"Sistem, secunde",Система (секунды),"Систем, секунде","Sistem, saniye" -System,OPTVAL_SYSTEM,,,,Systémový,System,System,,Sistemo,Sistema,,Järjestelmä,Système,Rendszer,Sistema,PC時刻,시스템,Systeem,System,System,Sistema,,Sistem,Система,Систем,Sistem -Netgames only,OPTVAL_NETGAMESONLY,,,,Pouze v síťové hře,Kun netspil,Nur Netzwerkspiele,,Retludoj sole,Solo para juegos en red,,Vain verkkopelit,Parties en Ligne seulement,Csak Netgames,Solo giochi net,オンラインのみ,멀티플레이에만,Alleen Netspellen,Kun nettspill,Tylko gry sieciowe,Jogos em rede apenas,,Doar în rețea,Только сетевые игры,Мрежне игре само,Sadece net oyunlar -Image and Text,OPTVAL_AMMOIMAGETEXT,,,,Obrázek a text,Billede og tekst,Bild und Text,,Bildo kaj Teksto,Imagen y texto,,Kuva ja teksti,Image et Texte,Kép és szöveg,Immagini e testo,画像と字,이미지와 텍스트,Beeld en tekst,Bilde og tekst,Obraz i Tekst,Imagem e texto,,Imagine și Text,Изображение и текст,Слика и текст,Resim ve Metin -Text and Image,OPTVAL_AMMOTEXTIMAGE,,,,Text a obrázek,Tekst og billede,Text und Bild,,Teksto kaj Bildo,Texto e imagen,,Teksti ja kuva,Texte et Image,Szöveg és kép,Testo e immagini,字と画像,텍스트와 이미지,Tekst en beeld,Tekst og bilde,Tekst i Obraz,Texto e imagem,,Text și Imagine,Текст и изобр.,Текст и слика,Metin ve Görüntü -Scripts Only,OPTVAL_SCRIPTSONLY,,,,Pouze skripty,Kun scripts,Nur Skripte,,Skriptoj Sole,Solo scripts,,Vain komentosarjat,Scripts seulement,Csak szkript,Solo script,スクリプトのみ,스크립트에만,Alleen scripts,Bare skript,Tylko skrypty,Scripts apenas,,Numai scripturi,Только скрипты,Само скрипте,Sadece Senaryolar -All,OPTVAL_ALL,,,,Všechny,Alle,Alle,,Ĉiuj,Todos,,Kaikki,Tout,Mind,Tutti,全て,모두 작동,Alle,Alle,Wszystko,Todos,,Tot,Все,Све,Tümü -Only last one,OPTVAL_ONLYLASTONE,,,,Pouze poslední,Kun den sidste,Nur das letzte,,Nur fina unu,Solo el último,,Vain viimeinen,Dernier seulement,Csak a legutolsó,Solo l'ultimo,最後のみ,오직 마지막 것만,Alleen de laatste,Bare den siste,Tylko ostatni,Somente o último,Apenas o último,Doar ultimul,Только последнее,Само последњи,Sadece sonuncusu -Traditional Doom,OPTVAL_TRADITIONALDOOM,,,,Tradiční Doom,Traditionel Doom,Doom traditionell,,Tradicia Doom,Doom tradicional,,Perinteinen Doom,Doom Traditionnel,Tradícionális Doom,DOOM tradizionale,正式DOOM,전형적인 둠 스타일,Traditioneel Doom,Tradisjonell undergang,Tradycyjny Doom,Doom Tradicional,,Tradițional Doom,Цвета из Doom,Традиционални Doom,Geleneksel Doom -Traditional Strife,OPTVAL_TRADITIONALSTRIFE,,,,Tradiční Strife,Traditionel Strife,Strife traditionell,,Tradicia Strife,Strife tradicional,,Perinteinen Strife,Strife Traditionnel,Tradícionális Strife,Strife tradizionale,正式Strife,전형적인 스트라이프 스타일,Traditionele Strife,Tradisjonell strid,Tradycyjny Strife,Strife Tradicional,,Tradițional Strife,Цвета из Strife,Традиционални Strife,Geleneksel Strife -Traditional Raven,OPTVAL_TRADITIONALRAVEN,,,,Tradiční Raven,Traditionel Raven,Raven traditionell,,Tradicia Raven,Raven tradicional,,Perinteinen Raven,Raven Traditionnel,Tradícionális Raven,Raven tradizionale,正式Raven,전형적인 레이븐 스타일,Traditionele Raven,Tradisjonell ravn,Tradycyjny Raven,Raven Tradicional,,Tradițional Raven,Цвета из Raven,Традиционални Raven,Geleneksel Raven -Only when found,OPTVAL_ONLYWHENFOUND,,,,Pouze po nalezení,Kun når de findes,Nur wenn gefunden,,Nur kiam trovita,Una vez encontrados,,"Vain, kun löydetty",Seulement découverts,Csak ha megleled,Solo quando trovato,発見時のみ,획득했을 때만,Alleen wanneer gevonden,Bare når funnet,Tylko gdy znaleziono,Somente quando encontrado,Apenas quando encontrado,Doar la descoperire,После обнаружения,Само кад је пронађен,Sadece bulunduğunda -On for overlay only,OPTVAL_ONFOROVERLAYONLY,,,,Pouze v překryvném režimu,Kun til overlay,Nur auf Overlay,,Ŝaltita nur por surmeto,Solo para superpuesto,,Päällä vain karttaprojisoinnin kanssa,On pour Surimpression,Csak az overlayen,Solo attivo per la sovrapposizione,オーバーレイ専用,오버레이에만 작동,Alleen op voor overlay alleen voor overlay,På kun for overlegg,Włączony tylko dla nakładek,Ativado somente para sobreposição,Apenas ativado para sobreposição,Doar pentru modul transparent,Только наложенная,Укључен само за навлаку,Yalnızca kaplama için etkin -Overlay+Normal,OPTVAL_OVERLAYNORMAL,,,,Překryv + normální,Overlay+Normal,Overlay+Normal,,Surmeto+Normala,Superpuesto+Normal,,Projisointi+tavallinen,Surimpression+Normal,Overlay+Normál,Sovrapposizione+Normale,オーバーレイ+通常,오버레이+기본,Overlay+Normaal,,Nakładka+Normalnie,Sobreposição+Normal,,Transparent + Normal,Наложенная + обычная,Навлака + нормално,Yer Kaplama+Normal -Overlay Only,OPTVAL_OVERLAYONLY,,,,Pouze překryv,Kun overlay,Nur Overlay,,Nur Surmeto,Solo superpuesto,,Vain projisointi,Surimpression seulement,Csak Overlay-nél,Solo Sovrapposizione,オーバーレイのみ,오버레이만,Alleen Overlay,Kun overlegg,Tylko Nakładka,Sobreposição apenas,,Doar modul transparent,Только прозрачный,Навлак само,Yalnızca Kaplama -Not for hubs,OPTVAL_NOTFORHUBS,,,,Ne pro huby,Ikke for knudepunkter,Nicht für Hubs,,Ne por naboj,No para hubs,,Ei tasokokoelmille,Pas pour les hubs,Csomópontokhoz nem,Non per gli hub,区間では出さない,허브는 제외,Niet voor hubs,Ikke for nav,Nie dla hubów,Exceto hubs,,Nu pentru hub-uri,Кроме групп,Није за хубове,Hub'lar için değil -Front,OPTVAL_FRONT,,,,Zepředu,Forside,Frontalansicht,,Fronto,Frontal,,Etu,Devant,Előnézet,Fronte,画像,정면,Voorkant,Forside,Przód,Frente,,Înainte,Перед,Испред,Ön -Animated,OPTVAL_ANIMATED,,,,Animované,Animeret,Animiert,,Animita,Animado,,Animoitu,Animés,Animált,Animato,動作,움직임,Geanimeerd,Animert,Animowany,Animado,,Animat,Анимированные,Анимирано,Animasyonlu -Rotated,OPTVAL_ROTATED,,,,Otáčivé,Drejet,Rotiert,,Turnita,Rotado,,Kääntyvä,Tournés,Elforgatott,Ruotato,回転,회전함,Geroteerd,Rotert,Obrócony,Rotacionado,Rodado,Rotit,Повёрнутые,Ротирано,Döndürülmüş -Map defined colors only,OPTVAL_MAPDEFINEDCOLORSONLY,,,Map defined colours only,Pouze barvy definované mapou,Kun kortdefinerede farver,Nur Leveldefinierte Farben,,Nur mapaj difinitaj koloroj,Colores definidos por el usuario,,Vain kartan määrittämät värit,Couleurs définies carte seul.,Csak map orientált színek,Solo i colori definiti dalla mappa,指定した色のみ,자체 미니맵 색상 사용,Alleen gedefinieerde kleuren op de kaart,Kun kartdefinerte farger,Tylko kolory zdefiniowane przez mapę,Cores definidas por mapa apenas,,Doar culori specifice hărții,Только определённые картой цвета,Само дефинисане мапом боје,Yalnızca harita tanımlı renkler -All except doors,OPTVAL_NODOORS,,,,Všechny krom dveří,Alle undtagen døre,Alle außer Türen,,Ĉiom krom pordoj,Todo excepto puertas,,Kaikki paitsi ovet,Tout sauf portes,"Minden, kivétel az ajtók",Tutti eccetto le porte,ドア以外全て,문을 제외한 모두,Allemaal behalve deuren,Alle unntatt dører,Wszystko oprócz drzwi,Tudo exceto portas,,Cu excepția ușilor,Кроме дверей,Све осим врата,Kapılar hariç hepsi -Double,OPTVAL_DOUBLE,,,,Dvojitý,Dobbelt,Doppel,,Duobligi,Doble,,Kaksinkertainen,,Dupla,Doppio,ダブル,2배,Dubbele,Dobbel,Podwójny,Dobro,,Dublu,Двойной,Дупло,Çift -Triple,OPTVAL_TRIPLE,,,,Trojitý,Tredobbelt,Dreifach,,Triobligi,,,Kolminkertainen,,Tripla,Triplo,トリプル,3배,Drievoudig,Trippel,Potrójny,Triplo,,Triplu,Тройной,Тродупло,Üçlü -Quadruple,OPTVAL_QUADRUPLE,,,,Čtveritý,Firedobbelt,Vierfach,,Kvarobligi,Cuádruple,,Nelinkertainen,,Négyszeres,Quadruplo,クァッド,4배,Viervoudig,Firedoblet,Poczwórny,Quádruplo,,Cvadruplu,Четырёхкратный ,Четвороструко,Dörtlü -Item Pickup,OPTVAL_ITEMPICKUP,,,,Sebrání předmětu,Afhentning af varer,Gegenstand genommen,,Objektoprenado,Recogida de objetos,,Esineen poiminta,Objets Ramassés,Tárgy felvétele,Raccolta oggetto,アイテム取得,아이템 획득시,Puntafhaling,Varehenting,Podniesienie Przedmiotu,Coleta de Item,Aquisição de Itens,Obiect Ridicat,Подбор предметов,Подигнут предмет,Bir eşyayı almak -Obituaries,OPTVAL_OBITUARIES,,,,Oznámení o smrti,Dødsannoncer,Todesanzeige,,Nekrologoj,Obituarios,,Kuolinviestit,Avis de décès,Halálok,Necrologio,死亡時,사망 메시지,Doodsbrieven,Dødsannonser,Nekrologi,Obituários,,Necrologuri,Некрологи,Читуље,Ölüm İlanları -Critical Messages,OPTVAL_CRITICALMESSAGES,,,,Kritická oznámení,Kritiske meddelelser,Kritische Meldungen,,Gravaj Mesaĝoj,Mensajes críticos,,Tärkeät viestit,Messages Critiques,Fontos üzenetek,Messaggi critici,重要メッセージ,중요한 메시지,Kritische berichten,Kritiske meldinger,Wiadomości krytyczne,Mensagens Críticas,,Mesaje Critice,Важные сообщения,Критичне поруке,Kritik Mesajlar -Never friends,OPTVAL_NEVERFRIENDS,,,,Nikdy spojence,Aldrig venner,Keine Freunde,,Neniam amikoj,Nunca amigos,,Ei koskaan ystäviä,Jamais les Amis,Barátokat sose,Mai amici,フレンド以外,아군 무시,Nooit vrienden,Aldri venner,Żadnych przyjaciół,Nunca amigos,,Nu aliați,Не по союзникам,Никад за пријатеље,Asla arkadaş değil -Only monsters,OPTVAL_ONLYMONSTERS,,,,Pouze příšery,Kun monstre,Nur Monster,,Nur monstroj,Solo monstruos,,Vain hirviöt,Monstres Seulement,Csak szörnyeket,Solo i mostri,モンスターのみ,적에게만,Alleen monsters,Bare monstre,Tylko potwory,Somente monstros,Monstros apenas,Doar monștri,Для монстров,Само чудовишста,Sadece canavarlar -Hexen,OPTVAL_HEXEN,,,,,,,,,,,,Hexen,,,,헥센,,,,,,,,, -Old,OPTVAL_OLD,,,,Starý,Gamle,Alt,,Maljuna,Viejo,,Vanha,Ancien,Régi,Vecchio,旧式,구형,Oud,Gamle,Stare,Antigo,,Vechi,Старый,Стар,Eski -Doom,OPTVAL_DOOM,,,,,,,,,,,,,,,,둠,,,,,,,,, -Doom (strict),OPTVAL_DOOMSTRICT,,,,Doom (striktní),Doom (streng),Doom (strikt),,Doom (severa),Doom (estricto),,Doom (tiukka),,Doom (szigorú),Doom (rigoroso),Doom(厳密),둠 (엄격하게),Doom (streng),Doom (streng),Doom (ścisły),Doom (estritamente),Doom (estrito),,Doom (строгий),Doom (строг),Doom (katı) -Boom,OPTVAL_BOOM,,,,,,,,,,,,,,,,붐,,,,,,,,, -Boom (strict),OPTVAL_BOOMSTRICT,,,,Boom (striktní),Boom (streng),Boom (strikt),,Boom (severa),Boom (estricto),,Boom (tiukka),,Boom (szigorú),Boom (rigoroso),Boom(厳密),붐 (엄격하게),Boom (streng),Boom (streng),Boom (ścisły),Boom (estritamente),Boom (estrito),,Boom (строгий),Boom (строг),Boom (katı) -MBF,OPTVAL_MBF,,,,,,,,,,,,,,,,마린의 절친한 친구,,,,,,,,, -MBF (strict),OPTVAL_MBFSTRICT,,,,MBF (striktní),MBF (streng),MBF (strikt),,MBF (severa),MBF (estricto),,MBF (tiukka),,MBF (szigorú),MBF (rigoroso),MBF(厳密),마린의 절친한 친구 (엄격하게),MBF (streng),MBF (streng),MBF (ścisły),MBF (estritamente),MBF (estrito),,MBF (строгий),MBF (строг),MBF (katı) -ZDoom 2.0.63,OPTVAL_ZDOOM2063,,,,,,,,,,,,,,,,Z둠 2.0.63,,,,,,,,, -All unacknowledged,OPTVAL_ALLUNACKNOWLEDGED,,,,Všechny nepotrvzené,Alle ubekræftede,Alle unbestätigten,,Ĉiuj neagnoskitaj,Todos no reconocidos,,Kaikki kuittaamattomat,Tout non-acknowledged,Minden visszaigazolatlan,Tutti non riconosciuti,未確認全て,모두 미확인함,Allemaal onbekend,Alle ubekreftet,Wszystkie niepotwierdzone,Todos não-reconhecidos,,Toate necunoscute,Всё неопознанное,Све неусвојено,Tüm onaylanmamış -Errors,OPTVAL_ERRORS,,,,Chyby,Fejl,Fehler,,Eraroj,Errores,,Virheet,Erreurs,Hibák,Errori,エラー,에러,Fouten,Feil,Błędy,Erros,,Erori,Ошибки,Грешка,Hatalar -Warnings,OPTVAL_WARNINGS,,,,Varování,Advarsler,Warnungen,,Avertoj,Advertencias,,Varoitukset,Avertissements,Figyelmeztetések,Avvisi,警告,경고,Waarschuwingen,Advarsler,Ostrzeżenia,Avisos,,Atenționări,Предупреждения,Упозорење,Uyarılar -Notifications,OPTVAL_NOTIFICATIONS,,,,Oznámení,Meddelelser,Benachrichtigungen,,Sciigoj,Notificaciones,,Ilmoitukset,,Üzenetek,Notifiche,通知,알림,Kennisgevingen,Varsler,Powiadomienia,Notificações,,Notificări,Уведомления,Обавештење,Bildirimler -Everything,OPTVAL_EVERYTHING,,,,Všechno,Alt,Alles,,Ĉio,Todo,,Kaikki,Tout,Minden,Tutti,全て,전체,Alles,Alt,Wszystko,Tudo,,Tot,Всё,Све,Her şey -Hardware accelerated,OPTVAL_HWPOLY,,,,Hardwarová akcelerace,Hardware accelereret,Hardwarebeschleunigt,,Aparatara Plirapidigo,Acelerado por Hardware,,Laitteistokiihdytetty,Accéléré par Hardware,Hardveres gyorsítás,Accelerazione Hardware,ハードウェア アクセラレート,오픈지엘 가속,Hardware versneld,Maskinvareakselerert,Napędzane sprzętowo,Acelerado por hardware,,Accelerat Hardware,Аппаратный,Харвер убрзан,Hızlandırılmış donanım -Doom Software Renderer,OPTVAL_SWDOOM,,,,Doom softwarový renderer,,,,Program-bildigilo de Doom,Renderizado por Software de Doom,,Doomin ohjelmistohahmonnin,Rendu Software Doom,Doom szoftveres renderer,Rendering DOOM software,Doom ソフトウェアレンダー,둠 소프트웨어 렌더러,,,Renderer Oprogramowania Dooma,Renderizador Software do Doom,,Software,Doom-программный,Doom софтверски рендерер,Doom Yazılım Oluşturucu -True Color SW Renderer,OPTVAL_SWDOOMTC,,,,True color softwarový renderer,,,,Program-bildigilo kun Plenkoloro,Renderizado SW Color Verdadero,Renderizado SW True Color,True Color -ohjelmistohahmonnin,Rendu Software Couleurs Réeles,,Rendering software a pieni colori,トゥルーカラー SWレンダー,트루 컬러 소프트웨어 렌더러,,,Renderer True Color,Renderizador Software True Color,,Software Color Complet,Полноцветный програмный,SW рендерер праве боје,Gerçek Renk SW Oluşturucu -High-Performance,OPTVAL_DEDICATED,,,,Vysoký výkon,Højtydende,Volle Leistung,,Alta Rendimento,Alto rendimiento,,Korkea suorituskyky,Hautes Performances,Nagy teljesítmény,Prestazioni massime,ハイパフォーマンス,고 성능,Hoogwaardige prestaties,Høy ytelse,Wysoka Wydajność,Alta-Performance,,De înaltă performanță,Высокая производительность,Високо-перформанси,Yüksek Performans -Power-Saving,OPTVAL_INTEGRATED,,,,Nízká spotřeba,Strømbesparende,energiesparend,,Energikonservo,Ahorro de energía,,Virransäästö,Economie d'Energie,Energia takarékos,Risparmio energetico,パワーセービング,저전력,Energiebesparing,Strømsparende,Oszczędzanie Energii,Economia de Energia,,Economie de energie,Энергосбережение,Енергетско-штедљиви,Güç Tasarrufu -Vanilla,OPTVAL_VANILLA,,,,Původní,,,,Originala,,,Alkuperäinen,,Hagyományos,Vanilla,バニラ,바닐라,,,Czysty,,,Original,Изначальный,Ванила,Vanilya -ZDoom (Forced),OPTVAL_VTFZDOOM,,,,ZDoom (vynucený),ZDoom (tvunget),ZDoom (erzwungen),,ZDoom (Devigita),ZDoom (forzado),,ZDoom (pakotettu),ZDoom (Forcé),ZDoom (erőltetett),ZDoom (forzato),ZDoom(強制),ZDoom (강제 설정),ZDoom (Gedwongen),ZDoom (Tvunget),ZDoom (Wymuszony),ZDoom (Forçar),,ZDoom (Forțat),ZDoom (принудительно),ZDoom (присиљен),ZDoom (Zorla) -Vanilla (Forced),OPTVAL_VTFVANILLA,,,,Původní (vynucený),Vanilla (tvungen),Vanilla (erzwungen),,Originala (Devigita),Vanilla (Forzado),,Perus (pakotettu),Vanilla (Forcé),Hagyományos (erőltettt),Vanilla (forzato),バニラ(強制),바닐라 (강제 설정),Vanilla (Gedwongen),Vanilla (Tvunget),Czysty (Wymuszony),Vanilla (Forçar),DOS Original (Forçar),Original (Forțat),Изначальный (принудительно),Ванила (присиљен),Vanilya (Zorlanmış) -Auto (ZDoom Preferred),OPTVAL_VTAZDOOM,,,,Auto (preferován ZDoom),Auto (ZDoom foretrukket),Auto (ZDoom bevorzugt),,Aŭtomata (ZDoom Preferita),Auto (ZDoom preferido),,Automaattinen (ZDoomia suosiva),Auto (ZDoom Préféré),Automata (ZDoom preferált),Automatico (ZDoom preferito),自動(ZDoom優先),자동 (ZDoom 기본 설정),Auto (bij voorkeur ZDoom),Auto (ZDoom foretrukket),Automatyczny (Preferowany ZDoom),Automático (De preferência ZDoom),,Auto (ZDoom preferat),Автоматически (предпочитать ZDoom),Аутоматски (ZDoom преферијални),Otomatik (ZDoom Tercih Edilir) -Auto (Vanilla Preferred),OPTVAL_VTAVANILLA,,,,Auto (preferován původní),Auto (Vanilla foretrukket),Auto (Vanilla bevorzugt),,Aŭtomata (Originala Preferita),Auto (Vanilla preferido),,Automaattinen (alkuperäistä suosiva),Auto (Vanilla Préféré),Automata (Hagyományos preferált),Automatico (Vanilla preferito),自動(バニラ優先),자동 (바닐라 기본 설정),Auto (bij voorkeur Vanilla),Auto (Vanilla foretrukket),Automatyczny (Preferowany czysty),Automático (De preferência Vanilla),Automático (De preferência DOS Original),Auto (Original preferat),Автоматически (предпочитать изначальный),Аутоматски (ванила преферијални),Otomatik (Vanilya Tercihli) -Small,OPTVAL_SMALL,,,,Malé,Lille,Klein,,Malgranda,Pequeño,,Pieni,Petit,Kicsi,Piccolo,小,작게,Klein,Liten,Mały,Pequeno,,Mic,Мелкий,Мало,Küçük -Large,OPTVAL_LARGE,,,,Velké,Stor,Groß,,Granda,Grande,,Suuri,Grand,Nagy,Grande,大,크게,Groot,Stor,Duży,Grande,,Mare,Крупный,Велико,Büyük -Console,OPTVAL_CONSOLE,,,,Konzole,Konsol,Konsole,,Konzolo,Consola,,Konsoli,Console,Konzol,,コンソール,콘솔,Console,Konsoll,Konsola,Console,Consola,Consolă,Консольный,Конзола,Konsol -\caBrick,C_BRICK,,,,\caCihlová,\caMursten,\caZiegelrot,,\caBrikkolora,\caLadrillo,,\catiili,\cabrique,\catéglavörös,\camattone,\ca丹,\ca주홍색,\casteenrood,\caMurstein,\cacegła,\catijolo,,\caCărămiziu,\caКирпичный,\caБоја цигле,\caTuğla -\cbTan,C_TAN,,,,\cbSvětle hnědá,,\cbHellbraun,,\cbTankolora,\cbBeis,\cbTostado,\cbkeltaruskea,\cbbeige,\cbbézs,\cbabbronzatura,\cb香,\cb상아색,\cblichtbruin,\cbBrun,\cbjasnobrązowy,\cbbege,,\caBronz,\cbБежевый,\cbБеж,\cbTan -\ccGray,C_GRAY,,,\ccgrey,\ccŠedá,\ccGrå,\ccGrau,,\ccGriza,\ccGris,,\ccharmaa,\ccgris,\ccszürke,\ccgrigio,\cc灰,\cc회색,\ccgrijs,\ccGrå,\ccszary,\cccinza,,\ccGri,\ccСерый,\ccСива,\ccGri -\cdGreen,C_GREEN,,,,\cdZelená,\cdGrøn,\cdGrün,,\cdVerda,\cdVerde,,\cdvihreä,\cdvert,\cdzöld,\cdverde,\cd緑,\cd녹색,\cdgroen,\cdGrønn,\cdzielony,\cdverde,,\cdVerde,\cdЗелёный,\cdЗелена,\cdYeşil -\ceBrown,C_BROWN,,,,\ceHnědá,\ceBrun,\ceBraun,,\ceBruna,\ceMarrón,\ceCafé,\ceruskea,\cebrun,\cebarna,\cemarrone,\ce茶,\ce갈색,\cebruin,\ceBrun,\cebrązowy,\cemarrom,,\ceMaro,\ceКоричневый,\ceСмеђа,\ceKahverengi -\cfGold,C_GOLD,,,,\cfZlatá,\cfGuld,,,\cfOrkolora,\cfDorado,,\cfkulta,\cfor,\cfarany,\cforo,\cf金,\cf금색,\cfgoud,\cfGull,\cfzłoty,\cfdourado,,\cfAuriu,\cfЗолотой,\cfЗлатна,\cfAltın -\cgRed,C_RED,,,,\cgČervená,\cgRød,\cGrot,,\cfRuĝa,\cgRojo,,\cgpunainen,\cgrouge,\cgvörös,\cgrosso,\cg赤,\cg적색,\cgrood,\cgRød,\cgczerwony,\cgvermelho,,\gRoșu,\cgКрасный,\cgЦрвена,\cgKırmızı -\chBlue,C_BLUE,,,,\chModrá,\chBlå,\chBlau,,\chBlua,\chAzul,,\chsininen,\chbleu,\chkék,\chblu,\ch青,\ch청색,\chblauw,\chBlå,\chniebieski,\chazul,,\chAlbastru,\chСиний,\chПлава,\chMavi -\ciOrange,C_ORANGE,,,,\ciOranžová,,,,\ciOranĝkolora,\ciNaranja,,\cioranssi,\ciorange,\cinarancs,\ciarancione,\ci橙,\ci주황색,\cioranje,\ciOransje,\cipomarańczowy,\cilaranja,,\ciPortocaliu,\ciОранжевый,\ciНаранџаста,\ciTuruncu -\cjWhite,C_WHITE,,,,\cjBílá,\cjHvid,\cjWeiß,,\cjBlanka,\cjBlanco,,\cjvalkoinen,\cjblanc,\cjfehér,\cjbianco,\cj白,\cj흰색,\cjwit,\cjHvit,\cjbiały,\cjbranco,,\cjAlb,\cjБелый,\cjБела,\cjBeyaz -\ckYellow,C_YELLOW,,,,\ckŽlutá,\ckGul,\ckGelb,,\ckFlava,\ckAmarillo,,\ckkeltainen,\ckjaune,\cksárga,\ckgiallo,\ck黄,\ck노란색,\ckgeel,\ckGul,\ckżółty,\ckamarelo,,\ckGalben,\ckЖёлтый,\ckЖута,\ckSarı -\clDefault,C_DEFAULT,,,,\clVýchozí,\clStandard,\clStandard,,\clDefaŭlta,\clPor defecto,,\cloletus,\cldéfaut,\clalap,\cldefault,\cl初期,\cl기본 색,\clstandaard,\clStandard,\cldomyślny,\clpadrão,,\clImplicită,\clПо умолчанию,\clУобичајена,\clVarsayılan -\cmBlack,C_BLACK,,,,\cmČerná,\cmSort,\cmSchwarz,,\cmNigra,\cmNegro,,\cmmusta,\cmnoir,\cmfekete,\cmnero,\cm黒,\cm검은색,\cmzwart,\cmSvart,\cmczarny,\cmpreto,,\cmNegru,\cmЧёрный,\cmЦрна,\cmSiyah -\cnLight blue,C_LIGHTBLUE,,,,\cnSvětle modrá,\cnLyseblå,\cnHellblau,,\cnHelblua,\cnAzul claro,,\cnvaaleansininen,\cnbleu clair,\cnvilágoskék,\cnblu chiaro,\cn空,\cn하늘색,\cnlicht blauw,\cnLyseblå,\cnjasnoniebieski,\cnazul claro,,\cnAlbastru deschis,\cnГолубой,\cnСветло плава,\cnAçık mavi -\coCream,C_CREAM,,,,\coKrémová,\coCreme,\coCremefarben,,\coKremkolora,\coCrema,,\cokerma,\cocrème,\cokrémszínű,\cocrema,\co肉,\co살구색,\cocrème,\coKremfarget,\cokremowy,\cocreme,,\coCrem,\coКремовый,\coКрем,\coKrem -\cpOlive,C_OLIVE,,,,\cpOlivová,\cpOliven,\cpOliv,,\cpOlivkolora,\cpOliva,,\cpoliivi,\cpolive,\cpolíva,\cpoliva,\cp泥,\cp녹갈색,\cpolijf,\cpOliven,\cpoliwkowy,\cpoliva,,\cpMăsliniu,\cpОливковый,\cpМаслинаста,\cpZeytin -\cqDark green,C_DARKGREEN,,,,\cqTmavě zelená,\cqMørkegrøn,\cqDunkelgrün,,\cqMalhelverda,\cqVerde oscuro,,\cqtummanvihreä,\cqvert sombre,\cqsötétzöld,\cqverde scuro,\cq深,\cq암녹색,\cqdonkergroen,\cqMørkegrøn,\cqciemnozielony,\cqverde escuro,,\cqVerde închis,\cqТёмно-зелёный,\cqТамно зелена,\cqKoyu yeşil -\crDark red,C_DARKRED,,,,\crTmavě červená,\crMørkerød,\crDunkelrot,,\crMalhelruĝa,\crRojo oscuro,,\crtummanpunainen,\crrouge sombre,\crsötétvörös,\crrosso scuro,\cr朱,\cr암적색,\crdonkerrood,\crMørkerød,\crciemnoczerwony,\crvermelho escuro,,\crRoșu închis,\crТёмно-красный,\crБордо,\crKoyu kırmızı -\csDark brown,C_DARKBROWN,,,,\csTmavě hnědá,\csMørkebrun,\csDunkelbraun,,\csMalhelbruna,\csMarrón oscuro,\csCafé oscuro,\cstummanruskea,\csbrun sombre,\cssötétbarna,\csmarrone scuro,\cs焦,\cs암갈색,\csdonkerbruin,\csMørkebrun,\csciemnobrązowy,\csmarrom escuro,,\csMaro închis,\csТёмно-коричневый,\csБраон,\csKoyu kahverengi -\ctPurple,C_PURPLE,,,,\ctFialová,\ctLilla,\ctLila,,\ctPurpura,\ctMorado,,\ctpurppura,\ctviolet,\ctlila,\ctviola,\ct紫,\ct보라색,\ctpaars,\ctLilla,\ctfioletowy,\ctroxo,,\ctMov,\ctФиолетовый,\ctЉубичаста,\ctMor -\cuDark gray,C_DARKGRAY,,,\cudark grey,\cuTmavě šedá,\cuMørkegrå,\cuDunkelgrau,,\cuMalhelgriza,\cuGris oscuro,,\cutummanharmaa,\cugris sombre,\cusötétszürke,\cugrigio scuro,\cu鉛,\cu치색,\cudonkergrijs,\cuMørkegrå,\cuciemnoszary,\cucinza escuro,,\cuGri închis,\cuТёмно-серый,\cuТамно сива,\cuKoyu gri -\cvCyan,C_CYAN,,,,\cvAzurová,,\cvTürkis,,\cvCejana,\cvCián,,\cvsinivihreä,\cvcyan,\cvcián,\cvciano,\cv天,\cv청록색,\cvcyan,,\cvbłękitny,\cvciano,,\cvTurcoaz,\cvСине-зелёный,\cvЦијан,\cvCyan -\cwIce,C_ICE,,,,\cwLed,\cwIs,\cwEis,,\cwGlacikolora,\cwHielo,,\cwjää,\cwglace,\cwjég,\cwghiaccio,\cw氷,\cw구색,\cwice,\cwIs,\cwlód,\cwgelo,,\cwGheață,\cwЛедяной,\cwЛед,\cwBuz -\cxFire,C_FIRE,,,,\cxOheň,\cxIld,\cxFeuer,,\cxFajrkolora,\cxFuego,,\cxtuli,\cxfeu,\cxtűz,\cxfuoco,\cx炎,\cx자황색,\cxvuur,\cxIld,\cxogień,\cxfogo,,\cxFoc,\cxОгненный,\cxВатрена,\cxYangın -\cySapphire,C_SAPPHIRE,,,,\cySafírová,\cySafir,\cySaphirblau,,\cySafirkolora,\cyZafiro,,\cysafiiri,\cysaphir,\cyzafír,\cyzaffiro,\cy藍,\cy벽청색,\cysaffier,\cySafir,\cyszafirowy,\cysafira,,\cySafir,\cyСапфировый,\cyТамно плава,\cySafir -\czTeal,C_TEAL,,,,\czModrozelená,\czKrikand,\czBlaugrün,,\czBluverda,\czTurquesa,,\cztummansinivihreä,\czturquoise,\cztürkiz,\czverde acqua,\cz碧,\cz암청록색,\czteal,\czBlågrønn,\czmorski,\czturquesa,,\czMare,\czМорской,\czТиркизна,\czDeniz mavisi -Heretic,OPTSTR_HERETIC,,,,,,,,,,,,,,,,헤러틱 커서,,,,,,,,, -Chex,OPTSTR_CHEX,,,,,,,,,,,,,,,,첵스 커서,,,,,,,,, -No Sound,OPTSTR_NOSOUND,,,,Bez zvuku,Ingen lyd,Kein Sound,,Neniu Sono,Sin sonido,,Ei ääntä,Pas de son,Hang nélkül,Nessun suono,サウンドなし,음향 없음,Geen geluid,Ingen lyd,Brak dźwięku,Sem som,,Fără Sunet,Без звука,Без-звучни,Ses Yok -No interpolation,OPTSTR_NOINTERPOLATION,,,,Bez interpolace,Ingen interpolation,Keine Interpolation,,Neniu interpolado,Sin interpolación,,Ei interpolaatiota,Pas d'interpolation,Nincs interoláció,No interpolazione,補間無し,보간 없음,Geen interpolatie,Ingen interpolasjon,Brak interpolacji,Sem interpolação,,Fără interpolare,Без сглаживания,Нема уметања,Enterpolasyon yok -Spline,OPTSTR_SPLINE,,,,Křivka,,,,Splajno,,,Splini,,,,スプライン,스플라인,,,,,,,Сплайн,Сплајн, -OpenAL,OPTSTR_OPENAL,,,,,,,,,,,,,,,,오픈에이엘,,,,,,,,, -Hardware Renderer,DSPLYMNU_GLOPT,,,,Hardwarový renderer,,,,Aparatara Bildigilo,Renderizado por Hardware,,Laitteistohahmonnin,Moteur de Rendu Hardware,Hardver Render,Rendering Hardware,ハードウェア レンダラー,오픈지엘 렌더러,,,Renderer Sprzętowy,Renderizador Hardware,,Setări Mod OpenGL,Отрисовка с OpenGL,Хардвер рендерер,Donanım Oluşturucu -Software Renderer,DSPLYMNU_SWOPT,,,,Softwarový renderer,,,,Programa Bildigilo,Renderizado por Software,,Ohjelmistohahmonnin,Moteur de Rendu Software,Szoftver Render,Rendering Software,ソフトウェア レンダラー,소프트웨어 렌더러,,,Renderer Oprogramowania,Renderizador Software,,Setări Mod Software,Программная отрисовка,Софтвер рендерер,Yazılım Oluşturucu -Hardware Rendering Options,GLMNU_TITLE,,,,Nastavení hardwarového rendereru,Indstillinger for hardware-rendering,Hardware-Renderer Optionen,,Agordoj de La Aparatara Bildigilo,Opciones de OpenGL,,Laitteistohahmonnusasetukset,Options OpenGL,Hardver Renderelő Beállítások,Opzioni OpenGL,ハードウェアレンダリング オプション,오픈지엘 설정,Hardware Rendering Opties,Alternativer for maskinvaregjengivelse,Opcje Renderowania Sprzętowego,Opções de Renderização por Hardware,,Setări Redare OpenGL,Настройки OpenGL,Опција хардвер рендера,Donanım Oluşturma Seçenekleri -Dynamic Light Options,GLMNU_DYNLIGHT,,,,Nastavení dynamických světel,Indstillinger for dynamisk lys,Dynamisches-Licht-Optionen,,Agordoj de Dinamikaj Lumoj,Opciones de luz dinámica,,Dynaamisen valon asetukset,Options Lumières Dynamiques,Dinamikus Fény Beállítások,Opzioni Luci Dinamiche,ダイナミックライト オプション,광원 설정,Dynamische Licht Opties,Alternativer for dynamisk lys,Opcje Dynamicznego Oświetlenia,Opções de Luz Dinâmica,,Setări Lumini Dinamice,Динамическое освещение,Подешавања динамичког осветљења,Dinamik Işık Seçenekleri -Preferences,GLMNU_PREFS,,,,Možnosti,Præferencer,Einstellungen,,Preferoj,Preferencias,,Asetukset,Préférences,Preferenciák,Preferenze,環境設定,성능,Voorkeuren,Innstillinger,Preferencje,Preferências,,Preferințe,Настройки,Преференција,Tercihler -Trim sprite edges,GLTEXMNU_TRIMSPREDGE,,,,Oříznout okraje spritů,Trimme sprite-kanter,Leerraum in Sprites wegschneiden,,Ĉirkaŭtranĉi randojn de spritoj,Recortar líneas de sprite,,Siisti spritejen reunat,Nettoyer le bord des sprites,Sprite szél igazítása,Taglia gli spigoli agli sprite,スプライトの角を取る,스프라이트 모서리 다듬기,,Trim sprite kanter,Przycinanie krawędzi sprite'ów,Cortar bordas de sprites,,Tundere margini sprite-uri,Обрезание краёв спрайтов,Подсећи ивице спрајтова,Sprite kenarlarını kırpma -Sort draw lists by texture,GLTEXMNU_SORTDRAWLIST,,,,Seřadit vykreslování podle textury,Sortere tegningslister efter tekstur,Renderlisten nach Textur sortieren,,Ordigi desegnado-listojn laŭ teksturo,Ordenar tablas por textura,,Lajittele piirtotaulut pintakuvioinneittain,Ordonner liste de rendu par texture,Textúra szerinti kirajzolási lista,Ordina la lista draw per texture,テクスチャーから描画リストを分類,텍스처별로 생성 목록 정렬,Tekeninglijsten sorteren op textuur,Sorter tegningslister etter tekstur,Sortowanie list renderowania wdług tekstur,Organizar listas de renderização por textura,,Sortează listele de texturi,Сортировать списки текстур,Сортирано цртај листе од текстуре,Çizim listelerini dokuya göre sıralama -Dynamic Lights,GLLIGHTMNU_TITLE,,,,Dynamická světla,Dynamisk lys,Dynamische Lichter,,Dinamikaj Lumoj,Luces dinámicas,,Dynaamiset valot,Lumières Dynamiques,Dinamikus Fények,Luci Dinamiche,ダイナミックライト,다이나믹 라이트,Dynamische verlichting,Dynamiske lys,Dynamiczne Oświetlenie,Luzes Dinâmicas,,Lumini Dinamice,Динамическое освещение,Динамичко осветљење,Dinamik Işıklar -Dynamic Lights (Hardware),GLLIGHTMNU_LIGHTSENABLED,,,,Dynamická světla (hardware),Dynamisk lys (hardware),Dynamische Lichter (Hardware),,Dinamikaj Lumoj (Aparataro),Luces dinámicas (Hardware),,Dynaamiset valot (laitteistokiihdytys),Lumières Dynamiques (Hardware),Dinamikus Fények (hardveres),Luci Dinamiche (Hardware),ダイナミックライト(OpenGL),다이나믹 라이트(오픈지엘),Dynamische verlichting (hardware),Dynamiske lys (maskinvare),Dynamiczne Oświetlenie (Sprzętowe),Luzes Dinâmicas (Hardware),,Lumini Dinamice (OpenGL),Динамическое освещение (аппаратное),Динамичко осветљење (хардвер),Dinamik Işıklar (Donanım) -Enable light definitions,GLLIGHTMNU_LIGHTDEFS,,,,Povolit definice světel,Aktiver lysdefinitioner,Lichtdefinitionen an,,Ŝalti lumdifinojn,Activar definiciones de luz,,Ota käyttöön valomääritykset,Activer les définitions de lumière,Fény részletesség,Abilita le definizioni GLDEFS,ライト定義 許可,조명 선명도 사용,Lichtdefinities mogelijk maken,Aktiver lysdefinisjoner,Włącz definicje światła,Habilitar definições de luz,Permitir definições de luz,Activează definiții lumini,Включить определения света,Омогући светлосне дефиниције,Işık tanımlarını etkinleştirin -Lights affect sprites,GLLIGHTMNU_LIGHTSPRITES,,,,Světla ovlivňují sprity,Lys påvirker sprites,Sprites werden beleuchtet,,Lumoj efiki spritojn,Las luces afectan a los sprites,,Valot vaikuttavat spriteihin,Lumières affectent les sprites,A fény hatással van a sprite-okra,Le luci influiscono sugli sprite,ライトがスプライトに影響,조명에 영향받는 스프라이트,Lichten beïnvloeden sprites,Lys påvirker sprites,Światło ma wpływ na sprite'y,Luzes afetam sprites,,Luminile afectează sprite-urile,Освещать спрайты,Светло утиче на спрајтове,Işıklar sprite'ları etkiler -Lights affect particles,GLLIGHTMNU_LIGHTPARTICLES,,,,Světla ovlivňují částice,Lys påvirker partikler,Partikel werden beleuchtet,,Lumoj efiki partiklojn,Las luces afectan a las partículas,,Valot vaikuttavat hiukkasiin,Lumières affectent les particules,A fény hatással van a részecskékre,Le luci influiscono sulle particelle,ライトがパーティクルに影響,조명에 영향받는 입자들,Lichten beïnvloeden deeltjes,Lys påvirker partikler,Światło ma wpływ na cząsteczki,Luzes afetam partículas,,Luminile afectează particulele,Освещать частицы,Светло утиче на честице,Işıklar parçacıkları etkiler -Light shadowmaps,GLLIGHTMNU_LIGHTSHADOWMAP,,,,Mapy stínů,Lys skyggemapper,Shadowmaps für Lichter,,Lum-ombro-mapoj,Mapeo de sombra de Luz,,Valojen varjokartat,Shadowmaps,,Ombre proiettate,ライトのシャドウマッピング,조명에 영향받는 섀도우맵,Lichte schaduwkaarten,Lys skyggekart,Oświetlenie map cieni,Shadowmaps,,Umbre lumini,Карты светотеней,Светло мапе сенки,Işık gölge haritaları -Shadowmap quality,GLLIGHTMNU_LIGHTSHADOWMAPQUALITY,,,,Kvalita map stínů,Shadowmap-kvalitet,Shadowmap Qualität,,Kvalito de ombro-mapo,Calidad de Mapeo de Sombras,,Varjokarttojen laatu,Qualité Shadowmap,Shadowmap minőség,Qualità ombre proiettate,シャドウマップ 品質,섀도우맵 퀄리티,Schaduwkaart kwaliteit,Shadowmap-kvalitet,Jakość map cieni,Qualidade de shadowmap,,Calitate umbre,Качество карт светотеней,Мапа сенки квалитет,Gölge haritası kalitesi -Shadowmap filter,GLLIGHTMNU_LIGHTSHADOWMAPFILTER,,,,Filtrování map stínů,Skyggemap-filter,Shadowmap Filter,,Filtro de ombro-mapo,Filtro de Mapeo de Sombras,,Varjokarttojen suodatus,Filtre de Shadowmaps,,Filtro ombre proiettate,シャドウマップ フィルター,섀도우맵 필터,Schaduwkaart filter,Shadowmap-filter,Filtr map cieni,Filtro de shadowmap,,Filtru umbre,Фильтр карт светотеней,Мапа сенки филтер,Gölge haritası filtresi -Fog mode,GLPREFMNU_FOGMODE,,,,Režim mlhy,Tågetilstand,Nebelmodus,,Reĝimo de nebulo,Modo de niebla,,Sumutila,Mode du broullard,Köd mód,Modalità nebbia,フォグモード,안개 모드,Mistmodus,Tåke-modus,Tryb mgły,Modo de neblina,,Mod ceață,Режим тумана,Магла мод,Sis modu -Fog forces fullbright,GLPREFMNU_FOGFORCEFULLBRIGHT,,,,Mlha vynucuje plný jas,Tåge tvinger fullbright,Nebel erzwingt volle Helligkeit,,Nebulo devigas plenbrilon,Forzar brillo completo en niebla,,Sumu pakottaa täyskirkkauden,Brouillard force fullbright,Köd Fullbright-ot erőltet ki,La nebbia forza piena luce,濃霧は明るさ最大,안개를 최대한 강제로 밝힘,Mistkrachten volle lichtsterkte,Tåke styrker fullbright,Mgła wymusza pełną jasność,Neblina força brilho máximo,,Ceața forțează luminozitate maximă,Туман включает режим максимальной яркости,Магла присиљава пуну светлост,Sis fullbright'ı zorlar -Weapon light strength,GLPREFMNU_WPNLIGHTSTR,,,,Intenzita světel zbraní,Våbenlysstyrke,Waffenlichtstärke,,Lumforteco de armilo,Intensidad de luz de las armas,,Aseiden valovoima,Intensité lumineuse des armes,Fegyver lövés fényerősség,Intensità luminosa dell'arma,武器ライトの強さ,무기 빛 강도,Sterkte van het wapenlicht,Våpen lysstyrke,Natężenie światła broni,Intensidade de luz da arma,,Intensitate lumină armă,Интенсивность вспышек оружия,Блага снага оружја,Silah ışık gücü -Environment map on mirrors,GLPREFMNU_ENVIRONMENTMAPMIRROR,,,,Mapa prostředí na zrcadlech,Miljøkort på spejle,Lichteffekt auf Spiegeln,,Medimapo sur speguloj,Mapa de entorno en espejos,,Ympäristökartta peileissä,Mappage environment sur les miroirs,Környezeti mappolás a tükrökön,Ambiente mappa sui riflessi,マップオンミラーの画像表示,거울 주변의지도 활성,Milieukaart op spiegels,Omgivelseskart på speil,Mapa środowiska w lustrach,Mapa de ambiente em espelhos,,Reflecții pe oglinzi,Карта окружения на зеркалах,Околинска мапа на прозорима,Aynalar üzerinde çevre haritası -Enhanced night vision mode,GLPREFMNU_ENV,,,,Vylepšený režim nočního vidění,Forbedret nattesynstilstand,Verbesserter Nachtsichtmodus,,Plibonigita reĝimo de noktvido,Modo de visión nocturna mejorado,,Paranneltu pimeänäkötila,Mode de vision nocture amélioré,Felerősített éjjellátó mód,Modalità visione notturna migliorata,バイザーを暗視装置調にする,야시경 효과 향상,Verbeterde nachtzicht modus,Forbedret nattsynsmodus,Ulepszony tryb widzenia w ciemności,Modo de visão noturna avançada,,Vedere infraroșie avansată,Улучшенный режим ночного видения,Побољшана ноћна визија мод,Geliştirilmiş gece görüş modu -ENV shows stealth monsters,GLPREFMNU_ENVSTEALTH,,,,Vylepšené noční vidění ukazuje skryté příšery,ENV viser stealth-monstre,Nachtsichtmodus zeigt Stealth-Monster,,ENV montras kaŝiĝitajn monstrojn,ENV muestra enemigos sigilosos,,PPN näyttää näkymättömät hirviöt,VNA affiche monstres invisibles,ENV felfedi a lopakodó szörnyeket,La VNM mostra i mostri stealth ,暗視バイザーが透明を見破る,스텔스 적 개체를 감지하는 ENV,ENV toont stealth monsters,ENV viser stealth monstre,Ulepszony noktowizor pokazuje ukrywających się przeciwników,Visão noturna mostra monstros invisíveis,,PNV afișează monștri ascunși,ПНВ показывает скрытых монстров,ПНВ показује скривена чудовишта,ENV gizli canavarları gösteriyor -Adjust sprite clipping,GLPREFMNU_SPRCLIP,,,,Vyladění clippingu spritů,Juster sprite clipping,Sprite Clipping,,Agordi trairadon de spritoj,Ajustar recortado de sprites,,Spritejen asettelu,Adjusted le clipping des sprites,Sprite átlógás igazítása,Aggiusta il clipping degli sprite,スプライトのずらしを調整する,스프라이트 클리핑 조정,Sprite clipping,Juster sprite klipping,Ustaw wcięcie sprite'ów,Ajustar clipping de sprite,,Ajustare poziții sprite-uri,Режим обрезки спрайтов,Подеси спрајт клипинг,Sprite kırpmayı ayarlama -Smooth sprite edges,GLPREFMNU_SPRBLEND,,,,Vyhladit okraje spritů,Udglatte sprite-kanter,Glätte Spritekanten,,Glatigi randojn de spritoj,Suavizar bordes de sprites,,Pehmeät spritejen reunat,Adoucir bords des sprites,Sprite szélek simítása,Smussa gli angoli degli sprite,スプライトの角を丸める,부드러운 스프라이트 모서리,Gladde sprite randen,Glatte sprite kanter,Gładkie krawędzie sprite'ów,Suavizar bordas de sprites,,Netezire margini sprite-uri,Размытие краёв спрайтов,Углачати ивице спрајта,Düzgün sprite kenarları -Fuzz Style,GLPREFMNU_FUZZSTYLE,,,,Styl šumu,Fuzz-stil,Fuzz Stil,,Stilo de Lenugo,Estilo de difuminación,,Sumennustyyli,Style de bruit blanc,Homályosítás stílusa,Stile fuzz,ファズスタイル,퍼즈 스타일,Fuzz stijl,Fuzz-stil,Styl Szumu,Estilo de difusão,,Stil sclipire,Тип шума,Фаз стајл,Fuzz Tarzı -Sprite billboard,GLPREFMNU_SPRBILLBOARD,,,,Orientace spritů,,Spriteausrichtung,,Liniigi Spritojn,Alineado de sprites,,Spritetaulu,Etalage des sprites,Sprite alapú reklámtábla,,スプライト ビルボード,스프라이트 샘플링,Sprite billboard,,Wyrównanie Sprite'ów,Alinhamento de sprite,,Rotire sprite-uri,Привязка по осям спрайтов,Спрајт билборд,Sprite reklam panosu -Sprites face camera,GLPREFMNU_SPRBILLFACECAMERA,,,,Sprity čelí kameře,Sprites vender mod kameraet,Sprites zur Kamera ausrichten,,Spritoj alfronti kameraon,Los sprites miran a la cámara,,Spritet suuntaavat kameraan,Sprites font face à la caméra,Sprite alapú kamera,Gli sprite sono rivolti alla telecamera.,スプライトのフェイスカメラ,카메라를 향한 스프라이트,Sprites gezicht camera,Sprites vender mot kameraet,Sprite'y skierowane w kamerę,Sprites de frente pra câmera,,Sprite-urile privesc înspre cameră,Спрайты направлены к камере,Спрајт камера фаце,Sprite'lar kamerayla yüzleşir -Particle style,GLPREFMNU_PARTICLESTYLE,,,,Styl částic,Partikelstil,Partikelstil,,Partikla stilo,Estilo de partículas,,Hiukkastyyli,Style de particules,Részecske stílusa,Stile particelle,パーティクル スタイル,입자 스타일,Deeltjes stijl,Partikkel-stil,Styl Cząsteczek,Tipo de partícula,,Stil particule,Тип частиц,Честице стајл,Parçacık stili -Rendering quality,GLPREFMNU_RENDERQUALITY,,,,Kvalita vykreslování,Renderingskvalitet,Renderqualität,,Kvalito de bildigado,Calidad de Renderizado,,Hahmonnuslaatu,Qualité du rendu,Renderelés minősége,Qualità resa grafica,レンダリング品質,렌더링 품질,Het teruggeven van kwaliteit,Renderingskvalitet,Jakość Renderowania,Qualidade de renderização,,Calitate video,Качество отрисовки,Квалитет рендовања,Render kalitesi -Stereo 3D VR,GLPREFMNU_VRMODE,,,,,,,,Duvida 3D VR,Modo Stereo 3D VR,,,3D VR Stéréo,,,ステレオ3DのVR,VR 입체 스테레오 사용,,,,3D Estéreo (VR),,Mod VR,Стерео 3D VR-режим,Стереотоно 3D VR,Stereo 3D VR -Enable Quad Stereo,GLPREFMNU_VRQUADSTEREO,,,,Povolit Quad Stereo,Aktiver Quad Stereo,Quad Stereo aktivieren,,Ŝalti Kvaroblo-Stereon,Activar Quad Stereo,,Ota käyttöön Quad Stereo,Activer Quad Stereo,Quad Sztereó bekapcsolása,Abilita il Quad Stereo,クァッドステレオを有効,쿼드 스테레오 사용,Quad Stereo inschakelen,Aktiver Quad Stereo,Włącz Poczwórne Stereo,Habilitar Quad Stereo,Permitir Quad Stereo,Activare Quad Stereo,Четырёхкратный стереорежим,Омогући четвороструки стерео,Dörtlü Stereoyu Etkinleştir -Banded SW Lightmode,GLPREFMNU_SWLMBANDED,,,,Režim pruhovaného SW osvětlení,Båndede SW-lystilstand,Gebänderter SW-Lichtmodus,,Reĝimo de Bendiga Lumo de Programbildigo,Modo de luz por bandas de SW,,Kaistoitettu ohjelmistoväritila,Lumière bandées en Software,,Lightmode software bandata,バンデドSWライトモード,단결된 SW 라이트 모드,SW-lichtmodus met banden,Båndet SW-lysmodus,Naznaczony Tryb Oświetlenia Oprogramowania,Modo de luz por bandas em software,,Mod limitat de iluminare Software,Программный режим освещения полосами,Повезани SW режим осветљења,Bantlı SW Işık Modu -Distance Between Your Eyes,GLPREFMNU_VRIPD,,,,Vzdálenost mezi očima,Afstand mellem øjnene,Abstand zwischen den Augen,,Distanco Inter Viaj Okuloj,Distancia entre tus ojos,,Silmiesi etäisyys toisistaan,Distance entre vos yeux,Szemek közötti távolság,Distranza tra i tuoi occhi,自分の目との距離,시야 간의 거리,Afstand tussen uw ogen,Avstand mellom øynene dine,Odległość Pomiędzy Twoimi Oczami,Distância entre os olhos,,Distanța dintre ochi,Расстояние между глазами,Даљина између твојих очију,Gözleriniz Arasındaki Mesafe -Distance From Your Screen,GLPREFMNU_VRSCREENDIST,,,,Vzdálenost od obrazovky,Afstand fra din skærm,Abstand vom Bildschirm,,Distanco De Via Ekrano,Distancia desde tu pantalla,,Etäisyys ruudullesi,Distance entre vous et l'écran,Képernyőtől mért távolság,Distanza dal tuo schermo,画面からの距離,화면과의 거리,Afstand van uw scherm,Avstand fra skjermen,Odległość Od Twojego Ekranu4,Distância a partir da tela,,Distanța față de ecranul tău,Расстояние от экрана,Даљина од окрена,Ekranınızdan Uzaklık -Smart,OPTVAL_SMART,,,,Chytré,,,,Inteligenta,Inteligente,,Älykäs,Intelligent,Okos,Intelligente,スマート,자동 조정,Slim,,Mądry,Inteligente,,Inteligent,Умный,Паметно,Akıllı -Smarter,OPTVAL_SMARTER,,,,Chytřejší,Smartere,,,Pli inteligenta,Más inteligente,,Älykkäämpi,+ Intelligent,Okosabb,Ancora più intelligente,よりスマート,고급 자동 조정,Slimmer,Smartere,Mądrzejszy,Mais inteligente,,Mai inteligent,Умнее,Паметније,Daha Akıllı -Infrared only,OPTVAL_INFRAREDONLY,,,,Pouze infračervené,Kun infrarødt,Nur Infrarot,,Nur transruĝa,Solo infrarrojo,,Vain infrapuna,Vis. Noct. Seulement,Csak az infravörösnél,Solo infrarossi,赤外線のみ,야시경만,Alleen infrarood,Kun infrarød,Tylko Podczerwień,Somente infravermelho,,Doar în infraroșu,Только инфракрасный,Само инфрацрвена,Sadece kızılötesi -Infrared and torch,OPTVAL_INFRAREDANDTORCH,,,,Infračervené a pochodeň,Infrarød og lommelygte,Infrarot und Fackel,,Transruĝa kaj torĉo,Infrarrojo y antorcha,,Vain infrapuna ja soihtu,Iis Noct. & Torche,Infravörös és fáklya,Infrarossi e torcia,赤外線と松明,야시경과 횃불만,Infrarood en fakkels,Infrarød og lommelykt,Tylko Podczerwień i Pochodnie,Infravermelho e tocha,,Infraroșu si torță,Инфракрасный и факел,Инфрацрвена/бакља,Kızılötesi ve fener -Any fixed colormap,OPTVAL_ANYFIXEDCOLORMAP,,,Any fixed colourmap,Jakákoli fixní mapa barev,Alle lyseffekter,Alle Lichteffekte,,Iu ajn fiksita kolormapo,Cualquier mapa de color fijo,,Mikä tahansa kiinteä värikartta,N'importe quelle colormap,Bármely fixált colormap,Ogni colormap fissata,任意の固定カラーマップ,고정된 컬러맵만,Elke vaste colormap,Alle faste fargekart,Którekolwiek naprawione mapy kolorów,Qualquer colormap fixo,,Orice colormap,Любая заданная цветовая карта,Било која поправљена табела боја,Herhangi bir sabit renk haritası +",Rensa nodcache,Düğüm önbelleğini temizle, +Allow skipping of intermission scrollers,MISCMNU_INTERSCROLL,,,,Povolit přeskakování skrolujících obrázků,Tillad at springe over pausescrollere,Erlaube Überspringen von Intermission-Scrollern,,Permesi preterpason de intermitaj rulumoj,Permitir omisión de intermedios,,Salli vierivien väliruutujen ohittaminen,Sauter compteurs d'intermission,Pályaközi szünetek átugorhatóak,Consenti di saltare gli scorrimenti delle intermissioni,クリア結果集計のスキップを許可,인터미션 스크롤러 생략 허용,Overslaan van intermissiescrollers toestaan,Tillat å hoppe over pauserullere,Pozwól na pominięcie wstawek,Pular telas de intervalo entre fases,Saltar ecrãs de intervalo entre níveis,Permite saltul peste inserările de text,Разрешение пропуска текстовых вставок,Дозволи прескакање прелаза са текстовима,Tillåt att hoppa över rullgardiner för pauslägen.,Ara kaydırıcıların atlanmasına izin ver, +Network Options,NETMNU_TITLE,,,,Nastavení sítě,Netværksindstillinger,Netzwerkeinstellungen,,Reta Agordoj,Opciones de Red,,Verkkoasetukset,Options Réseau,Hálózati Beállítások,Opzioni network,ネットワーク オプション,네트워크 설정,Netwerkopties,Nettverksalternativer,Opcje Sieci,Opções de Rede,,Setări de Rețea,Настройки сети,Мрежна подешавања,Nätverksalternativ,Ağ Seçenekleri, +Local options,NETMNU_LOCALOPTIONS,,,,Lokální nastavení,Lokale indstillinger,Lokale Einstellungen,,Lokaj agordoj,Opciones locales,,Paikallisasetukset,Options Locales,Helyi beállítások,Opzioni locali,ローカル オプション,로컬 설정,Lokale opties,Lokale alternativer,Opcje Lokalne,Opções locais,,Setări Locale,Локальные настройки,Локална подешавања,Lokala alternativ,Yerel seçenekler, +Movement prediction,NETMNU_MOVEPREDICTION,,,,Predikce pohybu,Forudsigelse af bevægelser,Bewegungsvorausberechnung,,Movprognozado,Predicción de Movimiento,,Liikkeen ennakoiminen,Prédiction de Mouvement,Mozgás előrejelzés,Predizione movimenti,移動予測,움직임 예측도,Voorspelling van bewegingen,Forutsigelse av bevegelse,Przewidywanie Ruchu,Previsão de movimento,,Anticipare mișcare,Предсказание движения,Предвиђање покрета,Förutsägelse av rörelser,Hareket tahmini, +Predict line actions,NETMNU_LINESPECIALPREDICTION,,,,Predikce čárových akcí,Forudsige linjehandlinger,Berechne Linienaktionen voraus,,Prognozi linio-agojn,Predecir acciones de línea,,Ennakoi viivasuorat toiminnat,Prédiction des actions de ligne,Előrejelzés vonal művelet,Predizione azioni di linea,line actionsを予測する,라인 움직임 감지,Voorspel lijnacties,Forutsi linjehandlinger,Przewidź akcje linii,Prever ações de linha,,Anticipează acționarea liniilor,Предсказание действий на уровне,Предвиђање линијске радње,Förutsägelse av linjeåtgärder,Hat eylemlerini tahmin edin, +Prediction Lerp Scale,NETMNU_PREDICTIONLERPSCALE,,,,Velikost interpolace predikce,Forudsigelse Lerp-skala,Vorberechnungs Lerp-Skalierung,,Skalo de Linia Lnterpolado,Escala de interp. lineal de predicción,,Lineaarisen interpolaatioennakoinnin skaalaus,Prédiction d'échelle LERP,Előrejelzés LERP Arány,Scala Lerp predizione,リープスケール予測,러프 예측 강도,Voorspelling Lerp Scale,Prediksjon Lerp-skala,Przewidywanie Skali Lerp,Escala de previsão de LERP,,Anticipare scară lerp,Предсказание увеличения доп. задержки,Предвиђање лерп скале,Förutsägelse Lerp Scale,Tahmin Lerp Ölçeği, +Lerp Threshold,NETMNU_LERPTHRESHOLD,,,,Práh interpolace,Lerp-tærskel,Lerp-Schwellwert,,Limito de Linia Interpolado,Umbral de interp. lineal,,Interpolaatiokynnys,Limite LERP,LERP küszöbérték,Soglia Lerp,リープしきい値,러프 계산,Lerp Threshold,Lerp-terskel,Próg Lerp,Limite de LERP,,Prag Lerp,Порог доп. задержки,Лерп праг,Lerp Tröskelvärde,Lerp Eşiği, +Host options,NETMNU_HOSTOPTIONS,,,,Nastavení hostitele,Værtsindstillinger,Gastoptionen,,Agordoj de Gastiganto,Opciones de Host,,Isäntäasetukset,Options Hôte,Host beállítások,Opzioni ospitante,ホスト オプション,호스트 설정,Verhuurders opties,Vertsalternativer,Opcje hosta,Opções de host,,Setări gazdă,Настройки сервера,Подешавања домаћина,Alternativ för värdar,Ev sahibi seçenekleri, +Extra Tics,NETMNU_EXTRATICS,,,,Extra tiky,Ekstra tics,,,Ekstraj Tikoj,Tics Extra,,Lisäticit,Tics supplémentaires,Extra Tic-ek,Tics extra,予備秒数,추가 틱,,Ekstra tics,Dodatkowe tiki,Tics extras,,Ticăituri suplimentare,Дополнительные секунды,Додатни тикови,Extra tics,Ekstra Tikler, +Latency balancing,NETMNU_TICBALANCE,,,,Vyrovnání latence,Balancering af latenstid,Latenzbalance,,Respondotempo-balancado,Balanceo de latencia,,Viiveen tasapainoitus,Equilibrage de latence,Válaszidő balanszolás,Bilanciamento latenza,レイテンシーバランス,지연 시간 조정,Latency balans,Balansering av ventetid,Balans czasu oczekiwania,Equilíbrio de latência,,Întârzierea echilibrării,Балансировка задержки,Балансирање кашњења,Balansering av latenstid,Gecikme dengeleme, +Original,OPTVAL_ORIGINAL,,,,Původní,,,,Originala,,,Alkuperäinen,,Eredeti,Originale,オリジナル,원형,Origineel,,Oryginalny,,,,Изначальный,Оригинално,Ursprunglig,Orijinal, +Optimized,OPTVAL_OPTIMIZED,,,,Optimalizovaný,Optimeret,Optimiert,,Optimumigita,Optimizado,,Optimoitu,Optimisé,Optimalizált,Ottimizzato,最適化,최적화 형,Geoptimaliseerd,Optimalisert,Zoptymalizowany,Otimizado,,Optimizat,Оптимизированный,Оптимизовано,Optimerad,Optimize Edilmiş, +Classic (Faster),OPTVAL_CLASSIC,,,,Klasický (rychlejší),Classic (hurtigere),Klassisch (schneller),,Klasika (Pli rapide),Clásico (Más rápido),,Perinteinen (nopeampi),Classique (+ Rapide),Klasszikus (gyorsabb),Classico (più veloce),旧式(速度重視),구형 (빠르게),Klassiek (sneller),Klassisk (raskere),Klasyczny (szybszy),Clássico (Mais rápido),,Clasic (Mai rapid),Классический (быстрее),Класични (бржи),Classic (snabbare),Klasik (Daha Hızlı), +Precise,OPTVAL_PRECISE,,,,Přesný,Præcist,Genau,,Preciza,Preciso,,Tarkka,Précis,Pontos,Preciso,精密,정확하게,Nauwkeurig,Presis,Dokładny,Preciso,,Precis,Точный,Прецизно,Exakt,Kesin, +Capped,OPTVAL_CAPPED,,,,Uzavřený,Begrænset,Limitiert,,Limitigita,Limitado,,Rajoitettu,Limité,Lekorlátozva,Limitato,上限,색상에 맞게,Afgeschermd,Begrenset,Ograniczony,Limitado,,Limitat,Ограниченный,Ограничено,Begränsad,Sınırlı, +Particles,OPTVAL_PARTICLES,,,,Částice,Partikler,Partikel,,Partikloj,Partículas,,Hiukkasina,Particules,Részecskék,Particelle,パーティクル,입자만,Deeltjes,Partikler,Cząstki,Partículas,,Particule,Частицы,Честице,Partiklar,Parçacıklar, +Sprites,OPTVAL_SPRITES,,,,Sprity,,,,Mov-rastrumoj,,,Spriteinä,,Sprite-ok,Sprite,スプライト,스프라이트만,,,Sprite'y,,,Sprite-uri,Спрайты,Спрајтови,,Sprite'lar, +Sprites & Particles,OPTVAL_SPRITESPARTICLES,,,,Sprity a částice,Sprites og partikler,Sprites und Partikel,,Mov-rastrumoj kaj partikloj,Sprites y partículas,,Spriteinä ja hiukkasina,Sprites & Particules,Sprite-ok és részecskék,Sprite e particelle,スプライト & パーティクル,스프라이트+입자,Sprites & Deeltjes,Sprites og partikler,Sprite'y i cząstki,Sprites & Partículas,Sprites e Partículas,Sprite-uri & Particule,Спрайты и частицы,Спрајтови и честице,Sprites och partiklar,Sprite'lar ve Parçacıklar, +Melt,OPTVAL_MELT,,,,Rozpuštění,Smelt,Verlauf,,Fandi,Derretir,,Sulaminen,Fondu,Olvadás,Scioglimento,メルト,녹는 효과,Smelten,Smelte,Stopienie,Derreter,,Topire,Таяние,Топљење,Smält,Eriyik, +Burn,OPTVAL_BURN,,,,Oheň,Brænde,Einbrennen,,Bruli,Quemar,,Palaminen,Brûlure,Égés,Bruciamento,バーン,타는 효과,Verbranden,Brenne,Wypalenie,Queimar,,Ardere,Жжение,Спаљивање,Bränn,Yanmak, +Crossfade,OPTVAL_CROSSFADE,,,,Prolínačka,Crossfade,Überblenden,,Transvelki,Entrelazar,,Ristihäivytys,Fondu en croix,Átvezetés,Dissolvenza a croce,クロスフェード,화면 교차,Crossfade,Overblending,Przenikanie,Dissolver,,Ofilire,Увядание,Вењење,Crossfade,Crossfade, +Smooth,OPTVAL_SMOOTH_1,"This setting is duplicated in order to allow for different grammatical gender endings in the Russian language (and any other language that depends on a grammatical gender system). In English, due to the lack of a grammatical gender system, both option values are the same.",,,Vyhlazený,Glat,Glatt,,Glata,Fluido,,Pehmeä,Lisse,Simítás,Liscio,スムーズ,부드럽게,Glad,Glatt,Gładki,Suavizado,,Fin,Плавная,Глатко,Smidig,Pürüzsüz, +Smooth,OPTVAL_SMOOTH_2,,,,Vyhlazené,Glat,Glatt,,Glata,Fluido,,Pehmeä,Lisse,Simítás,Liscio,スムーズ,부드럽게,Glad,Glatt,Gładka,Suavizado,,Fin,Плавные,Глатко,Smidig,Pürüzsüz, +Translucent,OPTVAL_TRANSLUCENT,,,,Průhledný,Gennemskinnelig,Transparent,,Diafana,Translúcido,,Läpikuultava,Transparent,Áttetsző,Traslucido,半透明,투명하게,Doorschijnend,Gjennomskinnelig,Przeświecający,Translúcido,,Transparent,Полупрозрачный,Прозрачно,Genomskinlig,Yarı Saydam, +Fuzz,OPTVAL_FUZZ,,,,Šum,,Fuzz,,Lanugo,Borroso,,Sumeus,Bruit Blanc,Homályosítás,Annebbiato,ファズ,퍼즈 효과,Fuzz,,Szum,Difuso,,Sclipitor,Шумовой,Фаз,Fuzz,Fuzz, +Shadow,OPTVAL_SHADOW,,,,Stín,Skygge,Schatten,,Ombro,Sombra,,Varjo,Ombre,Árnyék,Ombra,シャドウ,그림자 효과,Schaduw,Skygge,Cień,Sombra,,Umbră,Теневой,Сенка,Skugga,Gölge, +Items,OPTVAL_ITEMS,,,,Předměty,Varer,Gegenstände,,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,아이템들,Artikelen,Gjenstander,Przedmioty,Itens,,Obiecte,Предметы,Предмет,Artiklar,Eşyalar, +Weapons,OPTVAL_WEAPONS,,,,Zbraně,Våben,Waffen,,Armiloj,Armas,,Aseet,Armes,Fegyverek,Armi,武器,무기들,Wapens,Våpen,Bronie,Armas,,Arme,Оружие,Оружја,Vapen,Silahlar, +Both,OPTVAL_BOTH,,,,Obojí,Begge,Beide,,Ambaŭ,Ambos,,Molemmat,Les Deux,Mindkettő,Entrambi,両方,둘 다,Beide,Begge,Oba,Ambos,,Ambele,Оба,Оба,Båda,Her ikisi de, +ZDoom,OPTVAL_ZDOOM,,,,,,,,,,,,,,,,Z둠,,,,,,,,,,, +Strife,OPTVAL_STRIFE,,,,,,,,,,,,,,,,스트라이프,,,,,,,,,,, +Player,OPTVAL_PLAYER,,,,Hráč,Spiller,Spieler,,Ludanto,Jugador,,Pelaaja,Joueur,Játékos,Giocatore,プレイヤー,플레이어,Speler,Spiller,Gracz,Jogador,,Jucător,Игрок,Играч,Spelare,Oyuncu, +Map,OPTVAL_MAP,,,,Level,Kort,Level,,Mapo,Mapa,,Kartta,Niveau,Pálya,Mappa,マップ,맵,Kaart,Kart,Mapa,Mapa,,Hartă,Карта,Мапа,Karta,Harita, +Scale to 640x400,OPTVAL_SCALETO640X400,,,,Zvětšit na 640x400,Skaleres til 640x400,Skaliere auf 640x400,,Skali al 640x400,Escalar a 640x400,,Skaalaa resoluutioon 640x400,Echelle 640x400,640x480-hoz arányít,Scala a 640x400,640x400スケール,640x400까지 확대,Schaal tot 640x400,Skala til 640x400,Skaluj do 640x400,Escalar para 640x400,,Dimensionare la 640x480,Масштабировать до 640x400,Скалирај на 640x400,Skala till 640x400,640x400'e ölçeklendirin, +Pixel double,OPTVAL_PIXELDOUBLE,,,,Zdvojení pixelů,Pixel dobbelt,Pixelverdopplung,,Bilderon duobligi,Pixel doble,,Kuvapistekaksinkertaistus,,Pixel duplázás,Pixel doppi,ピクセル2倍,2배 픽셀,Pixel dubbel,Dobbel piksel,Dwukrotnie więcej pikseli,Pixel duplo,,Dublare pixeli,Двойные пиксели,Дупли пиксел,Pixel dubbelt så mycket,Piksel çift, +Pixel quadruple,OPTVAL_PIXELQUADRUPLE,,,,Zčtyřnásobení pixelů,Pixel firedobbelt,Pixelvervierfachung,,Bilderon kvarobligi,Pixel cuádruple,,Kuvapistenelinkertaistus,,Pixel négyszerezés,Pixel quadrupli,ピクセル4倍,4배 픽셀,Pixel viervoudig,Piksel firedoblet,Czterokrotnie więcej pikseli,Pixel quádruplo,,Împătrire pixeli,Учетверённые пиксели,Четвороструки пиксел,Pixel fyrdubbel,Piksel dörtlü, +Current weapon,OPTVAL_CURRENTWEAPON,,,,Současná zbraň,Nuværende våben,Aktuelle Waffe,,Nuntempa armilo,Arma actual,,Nykyinen ase,Arme actuelle,Jelenlegi fegyver,Arma corrente,使用中の武器,현 무기,Huidig wapen,Nåværende våpen,Aktualna broń,Arma atual,,Arma curentă,текущего оружия,Тренутно оружје,Aktuellt vapen,Mevcut silah, +Available weapons,OPTVAL_AVAILABLEWEAPONS,,,,Dostupně zbraně,Tilgængelige våben,Verfügbare Waffen,,Haveblaj armiloj,Armas disponibles,,Käytettävissä olevat aseet,Armes Disponibles,Elérhető fegyverek,Armi disponibili,所持してる武器,사용 가능한 무기들,Beschikbare wapens,Tilgjengelige våpen,Dostępne bronie,Armas disponíveis,,Arme disponibile,доступного оружия,Доступно оружје,Tillgängliga vapen,Mevcut silahlar, +All weapons,OPTVAL_ALLWEAPONS,,,,Všechny zbraně,Alle våben,Alle Waffen,,Ĉiuj armiloj,Todas las armas,,Kaikki aseet,Toutes les armes,Minden fegyver,Tutte le armi,全ての武器,모든 무기들,Alle wapens,Alle våpen,Wszystkie bronie,Todas as armas,,Toate armele,всех видов оружия,Сва оружја,Alla vapen,Tüm silahlar, +"Level, milliseconds",OPTVAL_LEVELMILLISECONDS,,,,"Level, milisekundy","Level, millisekunder","Level, Millisekunden",,"Nivelo, milisekundoj","Nivel, milisegundos",,"Taso, millisekunnit","Niveau, milisecondes","Pálya, milliszekundum","Livello, millisecondi","現場, ミリ秒","레벨, 밀리초당","Niveau, milliseconden","Nivå, millisekunder","Poziom, milisekundy","Fase, milisegundos","Nível, milisegundos","Nivel, milisecunde","Уровень, миллисекунды","Ниво, милисекунде","Nivå, millisekunder","Seviye, milisaniye", +"Level, seconds",OPTVAL_LEVELSECONDS,,,,"Level, vteřiny","Level, sekunder","Level, Sekunden",,"Nivelo, sekundoj","Nivel, segundos",,"Taso, sekunnit","Niveau, secondes","Pálya, másodpercek","Livello, secondi","現場, 秒","레벨, 초당","Niveau, seconden","Nivå, sekunder","Poziom, sekundy","Fase, segundos","Nível, segundos","Nivel, secunde","Уровень, секунды","Ниво, секунде","Nivå, sekunder","Seviye, saniye", +Level,OPTVAL_LEVEL,,,,,,,,Nivelo,Nivel,,Taso,Niveau,Pálya,Livello,現場,레벨,Niveau,Nivå,Poziom,Fase,Nível,Nivel,Уровень,Ниво,Nivå,Seviye, +"Hub, seconds",OPTVAL_HUBSECONDS,,,,"Hub, vteřiny","Hub, sekunder","Hub, Sekunden",,"Rekontejo, sekundoj","Hub, segundos",,"Tasokokoelma, sekunnit","Hub, secondes","Csomópont, másodpercek","Hub, secondi","区間, 秒","허브, 초당","Naaf, seconden","Hub, sekunder","Hub, sekundy","Hub, segundos",,"Hub, secunde",Хаб (секунды),"Хуб, секунде","Hub, sekunder","Hub, saniye", +Hub,OPTVAL_HUB,,,,,,,,Rekontejo,,,Tasokokoelma,,Csomópont,,区間,허브,Naaf,,,,,,Хаб,Хуб,Nav,, +"Total, seconds",OPTVAL_TOTALSECONDS,,,,"Celkový, vteřiny","I alt, sekunder","Gesamt, Sekunden",,"Tuto, sekundoj","Total, segundos",,"Yhteensä, sekunnit","Total, secondes","Teljes, másodpercek","Totale, secondi","合計, 秒","누적 경과, 초당","Totaal, seconden","Totalt, sekunder","Razem, sekundy","Total, segundos",,"Total, secunde",Общее (секунды),"Тотал, секунде","Totalt, sekunder","Toplam, saniye", +Total,OPTVAL_TOTAL,,,,Celkový,I alt,Gesamt,,Tuto,,,Yhteensä,,Teljes,Totale,合計,누적 경과,Totaal,Totalt,Razem,,,,Общее,Тотал,Totalt,Toplam, +"System, seconds",OPTVAL_SYSTEMSECONDS,,,,"Systémový, vteřiny","System, sekunder","System, Sekunden",,"Sistemo, sekundoj","Sistema, segundos",,"Järjestelmä, sekunnit","Système, secondes","Rendszer, másodpercek","Sistema, secondi","PC時刻, 秒","시스템, 초당","Systeem, seconden","System, sekunder","System, sekundy","Sistema, segundos",,"Sistem, secunde",Система (секунды),"Систем, секунде","System, sekunder","Sistem, saniye", +System,OPTVAL_SYSTEM,,,,Systémový,,,,Sistemo,Sistema,,Järjestelmä,Système,Rendszer,Sistema,PC時刻,시스템,Systeem,,,Sistema,,Sistem,Система,Систем,,Sistem, +Netgames only,OPTVAL_NETGAMESONLY,,,,Pouze v síťové hře,Kun netspil,Nur Netzwerkspiele,,Retludoj sole,Solo para juegos en red,,Vain verkkopelit,Parties en Ligne seulement,Csak Netgames,Solo giochi net,オンラインのみ,멀티플레이에만,Alleen Netspellen,Kun nettspill,Tylko gry sieciowe,Jogos em rede apenas,,Doar în rețea,Только сетевые игры,Мрежне игре само,Endast nätspel,Sadece net oyunlar, +Image and Text,OPTVAL_AMMOIMAGETEXT,,,,Obrázek a text,Billede og tekst,Bild und Text,,Bildo kaj Teksto,Imagen y texto,,Kuva ja teksti,Image et Texte,Kép és szöveg,Immagini e testo,画像と字,이미지와 텍스트,Beeld en tekst,Bilde og tekst,Obraz i Tekst,Imagem e texto,,Imagine și Text,Изображение и текст,Слика и текст,Bild och text,Resim ve Metin, +Text and Image,OPTVAL_AMMOTEXTIMAGE,,,,Text a obrázek,Tekst og billede,Text und Bild,,Teksto kaj Bildo,Texto e imagen,,Teksti ja kuva,Texte et Image,Szöveg és kép,Testo e immagini,字と画像,텍스트와 이미지,Tekst en beeld,Tekst og bilde,Tekst i Obraz,Texto e imagem,,Text și Imagine,Текст и изобр.,Текст и слика,Text och bild,Metin ve Görüntü, +Scripts Only,OPTVAL_SCRIPTSONLY,,,,Pouze skripty,Kun scripts,Nur Skripte,,Skriptoj Sole,Solo scripts,,Vain komentosarjat,Scripts seulement,Csak szkript,Solo script,スクリプトのみ,스크립트에만,Alleen scripts,Bare skript,Tylko skrypty,Scripts apenas,,Numai scripturi,Только скрипты,Само скрипте,Endast skript,Sadece Senaryolar, +All,OPTVAL_ALL,,,,Všechny,Alle,Alle,,Ĉiuj,Todos,,Kaikki,Tout,Mind,Tutti,全て,모두 작동,Alle,Alle,Wszystko,Todos,,Tot,Все,Све,Alla,Tümü, +Only last one,OPTVAL_ONLYLASTONE,,,,Pouze poslední,Kun den sidste,Nur das letzte,,Nur fina unu,Solo el último,,Vain viimeinen,Dernier seulement,Csak a legutolsó,Solo l'ultimo,最後のみ,오직 마지막 것만,Alleen de laatste,Bare den siste,Tylko ostatni,Somente o último,Apenas o último,Doar ultimul,Только последнее,Само последњи,Endast den sista,Sadece sonuncusu, +Traditional Doom,OPTVAL_TRADITIONALDOOM,,,,Tradiční Doom,Traditionel Doom,Doom traditionell,,Tradicia Doom,Doom tradicional,,Perinteinen Doom,Doom Traditionnel,Tradícionális Doom,DOOM tradizionale,正式DOOM,전형적인 둠 스타일,Traditioneel Doom,Tradisjonell undergang,Tradycyjny Doom,Doom Tradicional,,Tradițional Doom,Цвета из Doom,Традиционални Doom,Traditionell Doom,Geleneksel Doom, +Traditional Strife,OPTVAL_TRADITIONALSTRIFE,,,,Tradiční Strife,Traditionel Strife,Strife traditionell,,Tradicia Strife,Strife tradicional,,Perinteinen Strife,Strife Traditionnel,Tradícionális Strife,Strife tradizionale,正式Strife,전형적인 스트라이프 스타일,Traditionele Strife,Tradisjonell strid,Tradycyjny Strife,Strife Tradicional,,Tradițional Strife,Цвета из Strife,Традиционални Strife,Traditionell Strife,Geleneksel Strife, +Traditional Raven,OPTVAL_TRADITIONALRAVEN,,,,Tradiční Raven,Traditionel Raven,Raven traditionell,,Tradicia Raven,Raven tradicional,,Perinteinen Raven,Raven Traditionnel,Tradícionális Raven,Raven tradizionale,正式Raven,전형적인 레이븐 스타일,Traditionele Raven,Tradisjonell ravn,Tradycyjny Raven,Raven Tradicional,,Tradițional Raven,Цвета из Raven,Традиционални Raven,Traditionell Raven,Geleneksel Raven, +Only when found,OPTVAL_ONLYWHENFOUND,,,,Pouze po nalezení,Kun når de findes,Nur wenn gefunden,,Nur kiam trovita,Una vez encontrados,,"Vain, kun löydetty",Seulement découverts,Csak ha megleled,Solo quando trovato,発見時のみ,획득했을 때만,Alleen wanneer gevonden,Bare når funnet,Tylko gdy znaleziono,Somente quando encontrado,Apenas quando encontrado,Doar la descoperire,После обнаружения,Само кад је пронађен,Endast när den hittas,Sadece bulunduğunda, +On for overlay only,OPTVAL_ONFOROVERLAYONLY,,,,Pouze v překryvném režimu,Kun til overlay,Nur auf Overlay,,Ŝaltita nur por surmeto,Solo para superpuesto,,Päällä vain karttaprojisoinnin kanssa,On pour Surimpression,Csak az overlayen,Solo attivo per la sovrapposizione,オーバーレイ専用,오버레이에만 작동,Alleen op voor overlay alleen voor overlay,På kun for overlegg,Włączony tylko dla nakładek,Ativado somente para sobreposição,Apenas ativado para sobreposição,Doar pentru modul transparent,Только наложенная,Укључен само за навлаку,Endast på för överlagring,Yalnızca kaplama için etkin, +Overlay+Normal,OPTVAL_OVERLAYNORMAL,,,,Překryv + normální,Overlay+Normal,Overlay+Normal,,Surmeto+Normala,Superpuesto+Normal,,Projisointi+tavallinen,Surimpression+Normal,Overlay+Normál,Sovrapposizione+Normale,オーバーレイ+通常,오버레이+기본,Overlay+Normaal,,Nakładka+Normalnie,Sobreposição+Normal,,Transparent + Normal,Наложенная + обычная,Навлака + нормално,Överlagring+Normal,Yer Kaplama+Normal, +Overlay Only,OPTVAL_OVERLAYONLY,,,,Pouze překryv,Kun overlay,Nur Overlay,,Nur Surmeto,Solo superpuesto,,Vain projisointi,Surimpression seulement,Csak Overlay-nél,Solo Sovrapposizione,オーバーレイのみ,오버레이만,Alleen Overlay,Kun overlegg,Tylko Nakładka,Sobreposição apenas,,Doar modul transparent,Только прозрачный,Навлак само,Endast överlagring,Yalnızca Kaplama, +Not for hubs,OPTVAL_NOTFORHUBS,,,,Ne pro huby,Ikke for knudepunkter,Nicht für Hubs,,Ne por naboj,No para hubs,,Ei tasokokoelmille,Pas pour les hubs,Csomópontokhoz nem,Non per gli hub,区間では出さない,허브는 제외,Niet voor hubs,Ikke for nav,Nie dla hubów,Exceto hubs,,Nu pentru hub-uri,Кроме групп,Није за хубове,Inte för nav,Hub'lar için değil, +Front,OPTVAL_FRONT,,,,Zepředu,Forside,Frontalansicht,,Fronto,Frontal,,Etu,Devant,Előnézet,Fronte,画像,정면,Voorkant,Forside,Przód,Frente,,Înainte,Перед,Испред,Framsida,Ön, +Animated,OPTVAL_ANIMATED,,,,Animované,Animeret,Animiert,,Animita,Animado,,Animoitu,Animés,Animált,Animato,動作,움직임,Geanimeerd,Animert,Animowany,Animado,,Animat,Анимированные,Анимирано,Animerad,Animasyonlu, +Rotated,OPTVAL_ROTATED,,,,Otáčivé,Drejet,Rotiert,,Turnita,Rotado,,Kääntyvä,Tournés,Elforgatott,Ruotato,回転,회전함,Geroteerd,Rotert,Obrócony,Rotacionado,Rodado,Rotit,Повёрнутые,Ротирано,Roterad,Döndürülmüş, +Map defined colors only,OPTVAL_MAPDEFINEDCOLORSONLY,,,Map defined colours only,Pouze barvy definované mapou,Kun kortdefinerede farver,Nur Leveldefinierte Farben,,Nur mapaj difinitaj koloroj,Colores definidos por el usuario,,Vain kartan määrittämät värit,Couleurs définies carte seul.,Csak map orientált színek,Solo i colori definiti dalla mappa,指定した色のみ,자체 미니맵 색상 사용,Alleen gedefinieerde kleuren op de kaart,Kun kartdefinerte farger,Tylko kolory zdefiniowane przez mapę,Cores definidas por mapa apenas,,Doar culori specifice hărții,Только определённые картой цвета,Само дефинисане мапом боје,Endast kartdefinierade färger,Yalnızca harita tanımlı renkler, +All except doors,OPTVAL_NODOORS,,,,Všechny krom dveří,Alle undtagen døre,Alle außer Türen,,Ĉiom krom pordoj,Todo excepto puertas,,Kaikki paitsi ovet,Tout sauf portes,"Minden, kivétel az ajtók",Tutti eccetto le porte,ドア以外全て,문을 제외한 모두,Allemaal behalve deuren,Alle unntatt dører,Wszystko oprócz drzwi,Tudo exceto portas,,Cu excepția ușilor,Кроме дверей,Све осим врата,Alla utom dörrar,Kapılar hariç hepsi, +Double,OPTVAL_DOUBLE,,,,Dvojitý,Dobbelt,Doppel,,Duobligi,Doble,,Kaksinkertainen,,Dupla,Doppio,ダブル,2배,Dubbele,Dobbel,Podwójny,Dobro,,Dublu,Двойной,Дупло,Dubbel,Çift, +Triple,OPTVAL_TRIPLE,,,,Trojitý,Tredobbelt,Dreifach,,Triobligi,,,Kolminkertainen,,Tripla,Triplo,トリプル,3배,Drievoudig,Trippel,Potrójny,Triplo,,Triplu,Тройной,Тродупло,Tredubbel,Üçlü, +Quadruple,OPTVAL_QUADRUPLE,,,,Čtveritý,Firedobbelt,Vierfach,,Kvarobligi,Cuádruple,,Nelinkertainen,,Négyszeres,Quadruplo,クァッド,4배,Viervoudig,Firedoblet,Poczwórny,Quádruplo,,Cvadruplu,Четырёхкратный ,Четвороструко,Fyrdubbel,Dörtlü, +Item Pickup,OPTVAL_ITEMPICKUP,,,,Sebrání předmětu,Afhentning af varer,Gegenstand genommen,,Objektoprenado,Coger objetos,Agarrar objetos,Esineen poiminta,Objets Ramassés,Tárgy felvétele,Raccolta oggetto,アイテム取得,아이템 획득시,Puntafhaling,Varehenting,Podniesienie Przedmiotu,Coleta de Item,Aquisição de Itens,Obiect Ridicat,Подбор предметов,Подигнут предмет,Hämtning av föremål,Bir eşyayı almak, +Obituaries,OPTVAL_OBITUARIES,,,,Oznámení o smrti,Dødsannoncer,Todesanzeige,,Nekrologoj,Obituarios,,Kuolinviestit,Avis de décès,Halálok,Necrologio,死亡時,사망 메시지,Doodsbrieven,Dødsannonser,Nekrologi,Obituários,,Necrologuri,Некрологи,Читуље,Dödsannonser,Ölüm İlanları, +Critical Messages,OPTVAL_CRITICALMESSAGES,,,,Kritická oznámení,Kritiske meddelelser,Kritische Meldungen,,Gravaj mesaĝoj,Mensajes críticos,,Tärkeät viestit,Messages Critiques,Fontos üzenetek,Messaggi critici,重要メッセージ,중요한 메시지,Kritische berichten,Kritiske meldinger,Wiadomości krytyczne,Mensagens Críticas,,Mesaje Critice,Важные сообщения,Критичне поруке,Kritiska meddelanden,Kritik Mesajlar, +Never friends,OPTVAL_NEVERFRIENDS,,,,Nikdy spojence,Aldrig venner,Keine Freunde,,Neniam amikoj,Nunca amigos,,Ei koskaan ystäviä,Jamais les Amis,Barátokat sose,Mai amici,フレンド以外,아군 무시,Nooit vrienden,Aldri venner,Żadnych przyjaciół,Nunca amigos,,Nu aliați,Не по союзникам,Никад за пријатеље,Aldrig vänner,Asla arkadaş değil, +Only monsters,OPTVAL_ONLYMONSTERS,,,,Pouze příšery,Kun monstre,Nur Monster,,Nur monstroj,Solo monstruos,,Vain hirviöt,Monstres Seulement,Csak szörnyeket,Solo i mostri,モンスターのみ,적에게만,Alleen monsters,Bare monstre,Tylko potwory,Somente monstros,Monstros apenas,Doar monștri,Для монстров,Само чудовишста,Endast monster,Sadece canavarlar, +Hexen,OPTVAL_HEXEN,,,,,,,,,,,,Hexen,,,,헥센,,,,,,,,,,, +Old,OPTVAL_OLD,,,,Starý,Gamle,Alt,,Maljuna,Viejo,,Vanha,Ancien,Régi,Vecchio,旧式,구형,Oud,Gamle,Stare,Antigo,,Vechi,Старый,Стар,Gamla,Eski, +Doom,OPTVAL_DOOM,,,,,,,,,,,,,,,,둠,,,,,,,,,,, +Doom (strict),OPTVAL_DOOMSTRICT,,,,Doom (striktní),Doom (streng),Doom (strikt),,Doom (severa),Doom (estricto),,Doom (tiukka),,Doom (szigorú),Doom (rigoroso),Doom(厳密),둠 (엄격하게),Doom (streng),Doom (streng),Doom (ścisły),Doom (estritamente),Doom (estrito),,Doom (строгий),Doom (строг),Doom (strikt),Doom (katı), +Boom,OPTVAL_BOOM,,,,,,,,,,,,,,,,붐,,,,,,,,,,, +Boom (strict),OPTVAL_BOOMSTRICT,,,,Boom (striktní),Boom (streng),Boom (strikt),,Boom (severa),Boom (estricto),,Boom (tiukka),,Boom (szigorú),Boom (rigoroso),Boom(厳密),붐 (엄격하게),Boom (streng),Boom (streng),Boom (ścisły),Boom (estritamente),Boom (estrito),,Boom (строгий),Boom (строг),Boom (strikt),Boom (katı), +MBF,OPTVAL_MBF,,,,,,,,,,,,,,,,마린의 절친한 친구,,,,,,,,,,, +MBF (strict),OPTVAL_MBFSTRICT,,,,MBF (striktní),MBF (streng),MBF (strikt),,MBF (severa),MBF (estricto),,MBF (tiukka),,MBF (szigorú),MBF (rigoroso),MBF(厳密),마린의 절친한 친구 (엄격하게),MBF (streng),MBF (streng),MBF (ścisły),MBF (estritamente),MBF (estrito),,MBF (строгий),MBF (строг),MBF (strikt),MBF (katı), +ZDoom 2.0.63,OPTVAL_ZDOOM2063,,,,,,,,,,,,,,,,Z둠 2.0.63,,,,,,,,,,, +All unacknowledged,OPTVAL_ALLUNACKNOWLEDGED,,,,Všechny nepotrvzené,Alle ubekræftede,Alle unbestätigten,,Ĉiuj neagnoskitaj,Todos no reconocidos,,Kaikki kuittaamattomat,Tout non-acknowledged,Minden visszaigazolatlan,Tutti non riconosciuti,未確認全て,모두 미확인함,Allemaal onbekend,Alle ubekreftet,Wszystkie niepotwierdzone,Todos não-reconhecidos,,Toate necunoscute,Всё неопознанное,Све неусвојено,Alla obeaktade,Tüm onaylanmamış, +Errors,OPTVAL_ERRORS,,,,Chyby,Fejl,Fehler,,Eraroj,Errores,,Virheet,Erreurs,Hibák,Errori,エラー,에러,Fouten,Feil,Błędy,Erros,,Erori,Ошибки,Грешка,Fel,Hatalar, +Warnings,OPTVAL_WARNINGS,,,,Varování,Advarsler,Warnungen,,Avertoj,Advertencias,,Varoitukset,Avertissements,Figyelmeztetések,Avvisi,警告,경고,Waarschuwingen,Advarsler,Ostrzeżenia,Avisos,,Atenționări,Предупреждения,Упозорење,Varningar,Uyarılar, +Notifications,OPTVAL_NOTIFICATIONS,,,,Oznámení,Meddelelser,Benachrichtigungen,,Sciigoj,Notificaciones,,Ilmoitukset,,Üzenetek,Notifiche,通知,알림,Kennisgevingen,Varsler,Powiadomienia,Notificações,,Notificări,Уведомления,Обавештење,Meddelanden,Bildirimler, +Everything,OPTVAL_EVERYTHING,,,,Všechno,Alt,Alles,,Ĉio,Todo,,Kaikki,Tout,Minden,Tutti,全て,전체,Alles,Alt,Wszystko,Tudo,,Tot,Всё,Све,Allt,Her şey, +Hardware accelerated,OPTVAL_HWPOLY,,,,Hardwarová akcelerace,Hardware accelereret,Hardwarebeschleunigt,,Aparatara plirapidigo,Acelerado por «hardware»,,Laitteistokiihdytetty,Accéléré par Hardware,Hardveres gyorsítás,Accelerazione Hardware,ハードウェア アクセラレート,오픈지엘 가속,Hardware versneld,Maskinvareakselerert,Napędzane sprzętowo,Acelerado por hardware,,Accelerat Hardware,Аппаратный,Харвер убрзан,Hårdvara påskyndad,Hızlandırılmış donanım, +Doom Software Renderer,OPTVAL_SWDOOM,,,,Doom softwarový renderer,,,,Programar-bildigilo de Doom,Renderizado por «software» de Doom,,Doomin ohjelmistohahmonnin,Rendu Software Doom,Doom szoftveres renderer,Rendering DOOM software,Doom ソフトウェアレンダー,둠 소프트웨어 렌더러,,,Renderer Oprogramowania Dooma,Renderizador Software do Doom,,Software,Doom-программный,Doom софтверски рендерер,Doom Mjukvarurenderare,Doom Yazılım Oluşturucu, +True Color SW Renderer,OPTVAL_SWDOOMTC,,,,True color softwarový renderer,,,,Programar-bildigilo kun plenkoloro,Renderizado Truecolor (color verdadero) del «software»,,True Color -ohjelmistohahmonnin,Rendu Software Couleurs Réeles,,Rendering software a pieni colori,トゥルーカラー SWレンダー,트루 컬러 소프트웨어 렌더러,,,Renderer True Color,Renderizador Software True Color,,Software Color Complet,Полноцветный програмный,SW рендерер праве боје,True Color Mjukvarurenderare,Gerçek Renk SW Oluşturucu, +High-Performance,OPTVAL_DEDICATED,,,,Vysoký výkon,Højtydende,Volle Leistung,,Alta rendimento,Alto rendimiento,,Korkea suorituskyky,Hautes Performances,Nagy teljesítmény,Prestazioni massime,ハイパフォーマンス,고 성능,Hoogwaardige prestaties,Høy ytelse,Wysoka Wydajność,Alta-Performance,,De înaltă performanță,Высокая производительность,Високо-перформанси,Högpresterande,Yüksek Performans, +Power-Saving,OPTVAL_INTEGRATED,,,,Nízká spotřeba,Strømbesparende,energiesparend,,Energikonservo,Ahorro de energía,,Virransäästö,Economie d'Energie,Energia takarékos,Risparmio energetico,パワーセービング,저전력,Energiebesparing,Strømsparende,Oszczędzanie Energii,Economia de Energia,,Economie de energie,Энергосбережение,Енергетско-штедљиви,Energibesparande,Güç Tasarrufu, +Vanilla,OPTVAL_VANILLA,,,,Původní,,,,Originala ludversio,,,Alkuperäinen,,Hagyományos,,バニラ,바닐라,,,Czysty,,,Original,Изначальный,Ванила,,Vanilya, +ZDoom (Forced),OPTVAL_VTFZDOOM,,,,ZDoom (vynucený),ZDoom (tvunget),ZDoom (erzwungen),,ZDoom (devigita),ZDoom (forzado),,ZDoom (pakotettu),ZDoom (Forcé),ZDoom (erőltetett),ZDoom (forzato),ZDoom(強制),ZDoom (강제 설정),ZDoom (Gedwongen),ZDoom (Tvunget),ZDoom (Wymuszony),ZDoom (Forçar),,ZDoom (Forțat),ZDoom (принудительно),ZDoom (присиљен),ZDoom (tvingad),ZDoom (Zorla), +Vanilla (Forced),OPTVAL_VTFVANILLA,,,,Původní (vynucený),Vanilla (tvungen),Vanilla (erzwungen),,Originala ludversio (devigita),Vanilla (forzado),,Perus (pakotettu),Vanilla (Forcé),Hagyományos (erőltettt),Vanilla (forzato),バニラ(強制),바닐라 (강제 설정),Vanilla (Gedwongen),Vanilla (Tvunget),Czysty (Wymuszony),Vanilla (Forçar),DOS Original (Forçar),Original (Forțat),Изначальный (принудительно),Ванила (присиљен),Vanilla (tvingad),Vanilya (Zorlanmış), +Auto (ZDoom Preferred),OPTVAL_VTAZDOOM,,,,Auto (preferován ZDoom),Auto (ZDoom foretrukket),Auto (ZDoom bevorzugt),,Aŭtomata (preferata de ZDoom),Automático (preferido por ZDoom),,Automaattinen (ZDoomia suosiva),Auto (ZDoom Préféré),Automata (ZDoom preferált),Automatico (ZDoom preferito),自動(ZDoom優先),자동 (ZDoom 기본 설정),Auto (bij voorkeur ZDoom),Auto (ZDoom foretrukket),Automatyczny (Preferowany ZDoom),Automático (De preferência ZDoom),,Auto (ZDoom preferat),Автоматически (предпочитать ZDoom),Аутоматски (ZDoom преферијални),Auto (ZDoom föredraget),Otomatik (ZDoom Tercih Edilir), +Auto (Vanilla Preferred),OPTVAL_VTAVANILLA,,,,Auto (preferován původní),Auto (Vanilla foretrukket),Auto (Vanilla bevorzugt),,Aŭtomata (preferata de la originala),Automático (preferido por Vanilla),,Automaattinen (alkuperäistä suosiva),Auto (Vanilla Préféré),Automata (Hagyományos preferált),Automatico (Vanilla preferito),自動(バニラ優先),자동 (바닐라 기본 설정),Auto (bij voorkeur Vanilla),Auto (Vanilla foretrukket),Automatyczny (Preferowany czysty),Automático (De preferência Vanilla),Automático (De preferência DOS Original),Auto (Original preferat),Автоматически (предпочитать изначальный),Аутоматски (ванила преферијални),Auto (Vanilla föredraget),Otomatik (Vanilya Tercihli), +Small,OPTVAL_SMALL,,,,Malé,Lille,Klein,,Malgranda,Pequeño,,Pieni,Petit,Kicsi,Piccolo,小,작게,Klein,Liten,Mały,Pequeno,,Mic,Мелкий,Мало,Liten,Küçük, +Large,OPTVAL_LARGE,,,,Velké,Stor,Groß,,Granda,Grande,,Suuri,Grand,Nagy,Grande,大,크게,Groot,Stor,Duży,Grande,,Mare,Крупный,Велико,Stor,Büyük, +Console,OPTVAL_CONSOLE,,,,Konzole,Konsol,Konsole,,Konzolo,Consola,,Konsoli,,Konzol,,コンソール,콘솔,,Konsoll,Konsola,,Consola,Consolă,Консольный,Конзола,Konsol,Konsol, +\caBrick,C_BRICK,,,,\caCihlová,\caMursten,\caZiegelrot,,\caBrikkolora,\caLadrillo,,\catiili,\cabrique,\catéglavörös,\camattone,\ca丹,\ca주홍색,\casteenrood,\caMurstein,\cacegła,\catijolo,,\caCărămiziu,\caКирпичный,\caБоја цигле,\caTegelsten,\caTuğla, +\cbTan,C_TAN,,,,\cbSvětle hnědá,,\cbHellbraun,,\cbTankolora,\cbBeis,\cbBeige,\cbkeltaruskea,\cbbeige,\cbbézs,\cbabbronzatura,\cb香,\cb상아색,\cblichtbruin,\cbBrun,\cbjasnobrązowy,\cbbege,,\caBronz,\cbБежевый,\cbБеж,,, +\ccGray,C_GRAY,,,\ccgrey,\ccŠedá,\ccGrå,\ccGrau,,\ccGriza,\ccGris,,\ccharmaa,\ccgris,\ccszürke,\ccgrigio,\cc灰,\cc회색,\ccgrijs,\ccGrå,\ccszary,\cccinza,,\ccGri,\ccСерый,\ccСива,\ccGrå,\ccGri, +\cdGreen,C_GREEN,,,,\cdZelená,\cdGrøn,\cdGrün,,\cdVerda,\cdVerde,,\cdvihreä,\cdvert,\cdzöld,\cdverde,\cd緑,\cd녹색,\cdgroen,\cdGrønn,\cdzielony,\cdverde,,\cdVerde,\cdЗелёный,\cdЗелена,\cdGrön,\cdYeşil, +\ceBrown,C_BROWN,,,,\ceHnědá,\ceBrun,\ceBraun,,\ceBruna,\ceMarrón,\ceMarrón/Café,\ceruskea,\cebrun,\cebarna,\cemarrone,\ce茶,\ce갈색,\cebruin,\ceBrun,\cebrązowy,\cemarrom,,\ceMaro,\ceКоричневый,\ceСмеђа,\ceBrun,\ceKahverengi, +\cfGold,C_GOLD,,,,\cfZlatá,\cfGuld,,,\cfOrkolora,\cfDorado,,\cfkulta,\cfor,\cfarany,\cforo,\cf金,\cf금색,\cfgoud,\cfGull,\cfzłoty,\cfdourado,,\cfAuriu,\cfЗолотой,\cfЗлатна,\cfGuld,\cfAltın, +\cgRed,C_RED,,,,\cgČervená,\cgRød,\cGrot,,\cfRuĝa,\cgRojo,,\cgpunainen,\cgrouge,\cgvörös,\cgrosso,\cg赤,\cg적색,\cgrood,\cgRød,\cgczerwony,\cgvermelho,,\gRoșu,\cgКрасный,\cgЦрвена,\cgRöd,\cgKırmızı, +\chBlue,C_BLUE,,,,\chModrá,\chBlå,\chBlau,,\chBlua,\chAzul,,\chsininen,\chbleu,\chkék,\chblu,\ch青,\ch청색,\chblauw,\chBlå,\chniebieski,\chazul,,\chAlbastru,\chСиний,\chПлава,\chBlå,\chMavi, +\ciOrange,C_ORANGE,,,,\ciOranžová,,,,\ciOranĝkolora,\ciNaranja,,\cioranssi,\ciorange,\cinarancs,\ciarancione,\ci橙,\ci주황색,\cioranje,\ciOransje,\cipomarańczowy,\cilaranja,,\ciPortocaliu,\ciОранжевый,\ciНаранџаста,,\ciTuruncu, +\cjWhite,C_WHITE,,,,\cjBílá,\cjHvid,\cjWeiß,,\cjBlanka,\cjBlanco,,\cjvalkoinen,\cjblanc,\cjfehér,\cjbianco,\cj白,\cj흰색,\cjwit,\cjHvit,\cjbiały,\cjbranco,,\cjAlb,\cjБелый,\cjБела,\cjVit,\cjBeyaz, +\ckYellow,C_YELLOW,,,,\ckŽlutá,\ckGul,\ckGelb,,\ckFlava,\ckAmarillo,,\ckkeltainen,\ckjaune,\cksárga,\ckgiallo,\ck黄,\ck노란색,\ckgeel,\ckGul,\ckżółty,\ckamarelo,,\ckGalben,\ckЖёлтый,\ckЖута,\ckGul,\ckSarı, +\clDefault,C_DEFAULT,,,,\clVýchozí,\clStandard,\clStandard,,\clDefaŭlta,\clPor defecto,,\cloletus,\cldéfaut,\clalap,\cldefault,\cl初期,\cl기본 색,\clstandaard,\clStandard,\cldomyślny,\clpadrão,,\clImplicită,\clПо умолчанию,\clУобичајена,\clStandard,\clVarsayılan, +\cmBlack,C_BLACK,,,,\cmČerná,\cmSort,\cmSchwarz,,\cmNigra,\cmNegro,,\cmmusta,\cmnoir,\cmfekete,\cmnero,\cm黒,\cm검은색,\cmzwart,\cmSvart,\cmczarny,\cmpreto,,\cmNegru,\cmЧёрный,\cmЦрна,\cmSvart,\cmSiyah, +\cnLight blue,C_LIGHTBLUE,,,,\cnSvětle modrá,\cnLyseblå,\cnHellblau,,\cnHelblua,\cnAzul claro,,\cnvaaleansininen,\cnbleu clair,\cnvilágoskék,\cnblu chiaro,\cn空,\cn하늘색,\cnlicht blauw,\cnLyseblå,\cnjasnoniebieski,\cnazul claro,,\cnAlbastru deschis,\cnГолубой,\cnСветло плава,\cnLjusblått,\cnAçık mavi, +\coCream,C_CREAM,,,,\coKrémová,\coCreme,\coCremefarben,,\coKremkolora,\coCrema,,\cokerma,\cocrème,\cokrémszínű,\cocrema,\co肉,\co살구색,\cocrème,\coKremfarget,\cokremowy,\cocreme,,\coCrem,\coКремовый,\coКрем,\coGrädde,\coKrem, +\cpOlive,C_OLIVE,,,,\cpOlivová,\cpOliven,\cpOliv,,\cpOlivkolora,\cpOliva,,\cpoliivi,\cpolive,\cpolíva,\cpoliva,\cp泥,\cp녹갈색,\cpolijf,\cpOliven,\cpoliwkowy,\cpoliva,,\cpMăsliniu,\cpОливковый,\cpМаслинаста,\cpOliv,\cpZeytin, +\cqDark green,C_DARKGREEN,,,,\cqTmavě zelená,\cqMørkegrøn,\cqDunkelgrün,,\cqMalhelverda,\cqVerde oscuro,,\cqtummanvihreä,\cqvert sombre,\cqsötétzöld,\cqverde scuro,\cq深,\cq암녹색,\cqdonkergroen,\cqMørkegrøn,\cqciemnozielony,\cqverde escuro,,\cqVerde închis,\cqТёмно-зелёный,\cqТамно зелена,\cqMörkgrön,\cqKoyu yeşil, +\crDark red,C_DARKRED,,,,\crTmavě červená,\crMørkerød,\crDunkelrot,,\crMalhelruĝa,\crRojo oscuro,,\crtummanpunainen,\crrouge sombre,\crsötétvörös,\crrosso scuro,\cr朱,\cr암적색,\crdonkerrood,\crMørkerød,\crciemnoczerwony,\crvermelho escuro,,\crRoșu închis,\crТёмно-красный,\crБордо,\crMörkröd,\crKoyu kırmızı, +\csDark brown,C_DARKBROWN,,,,\csTmavě hnědá,\csMørkebrun,\csDunkelbraun,,\csMalhelbruna,\csMarrón oscuro,\csMarrón/Café oscuro,\cstummanruskea,\csbrun sombre,\cssötétbarna,\csmarrone scuro,\cs焦,\cs암갈색,\csdonkerbruin,\csMørkebrun,\csciemnobrązowy,\csmarrom escuro,,\csMaro închis,\csТёмно-коричневый,\csБраон,\csMörkbrun,\csKoyu kahverengi, +\ctPurple,C_PURPLE,,,,\ctFialová,\ctLilla,\ctLila,,\ctPurpura,\ctMorado,,\ctpurppura,\ctviolet,\ctlila,\ctviola,\ct紫,\ct보라색,\ctpaars,\ctLilla,\ctfioletowy,\ctroxo,,\ctMov,\ctФиолетовый,\ctЉубичаста,\ctLila,\ctMor, +\cuDark gray,C_DARKGRAY,,,\cudark grey,\cuTmavě šedá,\cuMørkegrå,\cuDunkelgrau,,\cuMalhelgriza,\cuGris oscuro,,\cutummanharmaa,\cugris sombre,\cusötétszürke,\cugrigio scuro,\cu鉛,\cu치색,\cudonkergrijs,\cuMørkegrå,\cuciemnoszary,\cucinza escuro,,\cuGri închis,\cuТёмно-серый,\cuТамно сива,\cuMörkgrå,\cuKoyu gri, +\cvCyan,C_CYAN,,,,\cvAzurová,,\cvTürkis,,\cvCejana,\cvCian,,\cvsinivihreä,\cvcyan,\cvcián,\cvciano,\cv天,\cv청록색,\cvcyan,,\cvbłękitny,\cvciano,,\cvTurcoaz,\cvСине-зелёный,\cvЦијан,,, +\cwIce,C_ICE,,,,\cwLed,\cwIs,\cwEis,,\cwGlacikolora,\cwHielo,,\cwjää,\cwglace,\cwjég,\cwghiaccio,\cw氷,\cw구색,\cwice,\cwIs,\cwlód,\cwgelo,,\cwGheață,\cwЛедяной,\cwЛед,\cwIs,\cwBuz, +\cxFire,C_FIRE,,,,\cxOheň,\cxIld,\cxFeuer,,\cxFajrkolora,\cxFuego,,\cxtuli,\cxfeu,\cxtűz,\cxfuoco,\cx炎,\cx자황색,\cxvuur,\cxIld,\cxogień,\cxfogo,,\cxFoc,\cxОгненный,\cxВатрена,\cxEld,\cxYangın, +\cySapphire,C_SAPPHIRE,,,,\cySafírová,\cySafir,\cySaphirblau,,\cySafirkolora,\cyZafiro,,\cysafiiri,\cysaphir,\cyzafír,\cyzaffiro,\cy藍,\cy벽청색,\cysaffier,\cySafir,\cyszafirowy,\cysafira,,\cySafir,\cyСапфировый,\cyТамно плава,\cySafir,\cySafir, +\czTeal,C_TEAL,,,,\czModrozelená,\czKrikand,\czBlaugrün,,\czBluverda,\czTurquesa,,\cztummansinivihreä,\czturquoise,\cztürkiz,\czverde acqua,\cz碧,\cz암청록색,\czteal,\czBlågrønn,\czmorski,\czturquesa,,\czMare,\czМорской,\czТиркизна,,\czDeniz mavisi, +Heretic,OPTSTR_HERETIC,,,,,,,,,,,,,,,,헤러틱 커서,,,,,,,,,,, +Chex,OPTSTR_CHEX,,,,,,,,,,,,,,,,첵스 커서,,,,,,,,,,, +No Sound,OPTSTR_NOSOUND,,,,Bez zvuku,Ingen lyd,Kein Sound,,Neniu sono,Sin sonido,,Ei ääntä,Pas de son,Hang nélkül,Nessun suono,サウンドなし,음향 없음,Geen geluid,Ingen lyd,Brak dźwięku,Sem som,,Fără Sunet,Без звука,Без-звучни,Inget ljud,Ses Yok, +No interpolation,OPTSTR_NOINTERPOLATION,,,,Bez interpolace,Ingen interpolation,Keine Interpolation,,Neniu interpolado,Sin interpolación,,Ei interpolaatiota,Pas d'interpolation,Nincs interoláció,No interpolazione,補間無し,보간 없음,Geen interpolatie,Ingen interpolasjon,Brak interpolacji,Sem interpolação,,Fără interpolare,Без сглаживания,Нема уметања,Ingen interpolering,Enterpolasyon yok, +Spline,OPTSTR_SPLINE,,,,Křivka,,,,Splajno,,,Splini,,,,スプライン,스플라인,,,,,,,Сплайн,Сплајн,,, +OpenAL,OPTSTR_OPENAL,,,,,,,,,,,,,,,,오픈에이엘,,,,,,,,,,, +Hardware Renderer,DSPLYMNU_GLOPT,,,,Hardwarový renderer,,,,Aparatara bildigilo,Renderizado por «hardware»,,Laitteistohahmonnin,Moteur de Rendu Hardware,Hardver Render,Rendering Hardware,ハードウェア レンダラー,오픈지엘 렌더러,,,Renderer Sprzętowy,Renderizador Hardware,,Setări Mod OpenGL,Обработка с OpenGL,Хардвер рендерер,Hårdvaru-renderare,Donanım Oluşturucu, +Software Renderer,DSPLYMNU_SWOPT,,,,Softwarový renderer,,,,Programara bildigilo,Renderizado por «software»,,Ohjelmistohahmonnin,Moteur de Rendu Software,Szoftver Render,Rendering Software,ソフトウェア レンダラー,소프트웨어 렌더러,,,Renderer Oprogramowania,Renderizador Software,,Setări Mod Software,Программная обработка,Софтвер рендерер,Mjukvarurenderare,Yazılım Oluşturucu, +Hardware Rendering Options,GLMNU_TITLE,,,,Nastavení hardwarového rendereru,Indstillinger for hardware-rendering,Hardware-Renderer Optionen,,Agordoj de OpenGL (aparatara bildigilo),Opciones de OpenGL,,Laitteistohahmonnusasetukset,Options OpenGL,Hardver Renderelő Beállítások,Opzioni OpenGL,ハードウェアレンダリング オプション,오픈지엘 설정,Hardware Rendering Opties,Alternativer for maskinvaregjengivelse,Opcje Renderowania Sprzętowego,Opções de Renderização por Hardware,,Setări Redare OpenGL,Настройки OpenGL,Опција хардвер рендера,Alternativ för maskinvarurendering,Donanım Oluşturma Seçenekleri, +Dynamic Light Options,GLMNU_DYNLIGHT,,,,Nastavení dynamických světel,Indstillinger for dynamisk lys,Dynamisches-Licht-Optionen,,Agordoj de dinamikaj lumoj,Opciones de luz dinámica,,Dynaamisen valon asetukset,Options Lumières Dynamiques,Dinamikus Fény Beállítások,Opzioni Luci Dinamiche,ダイナミックライト オプション,광원 설정,Dynamische Licht Opties,Alternativer for dynamisk lys,Opcje Dynamicznego Oświetlenia,Opções de Luz Dinâmica,,Setări Lumini Dinamice,Динамическое освещение,Подешавања динамичког осветљења,Alternativ för dynamiskt ljus,Dinamik Işık Seçenekleri, +Preferences,GLMNU_PREFS,,,,Možnosti,Præferencer,Einstellungen,,Preferoj,Preferencias,,Asetukset,Préférences,Preferenciák,Preferenze,環境設定,성능,Voorkeuren,Innstillinger,Preferencje,Preferências,,Preferințe,Настройки,Преференција,Inställningar,Tercihler, +Trim sprite edges,GLTEXMNU_TRIMSPREDGE,,,,Oříznout okraje spritů,Trimme sprite-kanter,Leerraum in Sprites wegschneiden,,Ĉirkaŭtranĉi randojn de mov-rastrumoj,Recortar líneas de «sprite»,,Siisti spritejen reunat,Nettoyer le bord des sprites,Sprite szél igazítása,Taglia gli spigoli agli sprite,スプライトの角を取る,스프라이트 모서리 다듬기,,Trim sprite kanter,Przycinanie krawędzi sprite'ów,Cortar bordas de sprites,,Tundere margini sprite-uri,Обрезание краёв спрайтов,Подсећи ивице спрајтова,Trimma sprite-kanter,Sprite kenarlarını kırpma, +Sort draw lists by texture,GLTEXMNU_SORTDRAWLIST,,,,Seřadit vykreslování podle textury,Sortere tegningslister efter tekstur,Renderlisten nach Textur sortieren,,Ordigi desegnado-listojn laŭ teksturo,Ordenar tablas por textura,,Lajittele piirtotaulut pintakuvioinneittain,Ordonner liste de rendu par texture,Textúra szerinti kirajzolási lista,Ordina la lista draw per texture,テクスチャーから描画リストを分類,텍스처별로 생성 목록 정렬,Tekeninglijsten sorteren op textuur,Sorter tegningslister etter tekstur,Sortowanie list renderowania wdług tekstur,Organizar listas de renderização por textura,,Sortează listele de texturi,Сортировать списки текстур,Сортирано цртај листе од текстуре,Sortera ritningslistor efter textur,Çizim listelerini dokuya göre sıralama, +Dynamic Lights,GLLIGHTMNU_TITLE,,,,Dynamická světla,Dynamisk lys,Dynamische Lichter,,Dinamikaj lumoj,Luces dinámicas,,Dynaamiset valot,Lumières Dynamiques,Dinamikus Fények,Luci Dinamiche,ダイナミックライト,다이나믹 라이트,Dynamische verlichting,Dynamiske lys,Dynamiczne Oświetlenie,Luzes Dinâmicas,,Lumini Dinamice,Динамическое освещение,Динамичко осветљење,Dynamiska lampor,Dinamik Işıklar, +Dynamic Lights (Hardware),GLLIGHTMNU_LIGHTSENABLED,,,,Dynamická světla (hardware),Dynamisk lys (hardware),Dynamische Lichter (Hardware),,Dinamikaj lumoj (Aparataro),Luces dinámicas (Hardware),,Dynaamiset valot (laitteistokiihdytys),Lumières Dynamiques (Hardware),Dinamikus Fények (hardveres),Luci Dinamiche (Hardware),ダイナミックライト(OpenGL),다이나믹 라이트(오픈지엘),Dynamische verlichting (hardware),Dynamiske lys (maskinvare),Dynamiczne Oświetlenie (Sprzętowe),Luzes Dinâmicas (Hardware),,Lumini Dinamice (OpenGL),Динамическое освещение (аппаратное),Динамичко осветљење (хардвер),Dynamiska lampor (maskinvara),Dinamik Işıklar (Donanım), +Enable light definitions,GLLIGHTMNU_LIGHTDEFS,,,,Povolit definice světel,Aktiver lysdefinitioner,Lichtdefinitionen an,,Ŝalti lumdifinojn,Activar definiciones de luz,,Ota käyttöön valomääritykset,Activer les définitions de lumière,Fény részletesség,Abilita le definizioni GLDEFS,ライト定義 許可,조명 선명도 사용,Lichtdefinities mogelijk maken,Aktiver lysdefinisjoner,Włącz definicje światła,Habilitar definições de luz,Permitir definições de luz,Activează definiții lumini,Включить определения света,Омогући светлосне дефиниције,Aktivera ljusdefinitioner,Işık tanımlarını etkinleştirin, +Lights affect sprites,GLLIGHTMNU_LIGHTSPRITES,,,,Světla ovlivňují sprity,Lys påvirker sprites,Sprites werden beleuchtet,,Lumoj efikas mov-rastrumojn,Las luces afectan a los «sprites»,,Valot vaikuttavat spriteihin,Lumières affectent les sprites,A fény hatással van a sprite-okra,Le luci influiscono sugli sprite,ライトがスプライトに影響,조명에 영향받는 스프라이트,Lichten beïnvloeden sprites,Lys påvirker sprites,Światło ma wpływ na sprite'y,Luzes afetam sprites,,Luminile afectează sprite-urile,Освещать спрайты,Светло утиче на спрајтове,Ljus påverkar sprites,Işıklar sprite'ları etkiler, +Lights affect particles,GLLIGHTMNU_LIGHTPARTICLES,,,,Světla ovlivňují částice,Lys påvirker partikler,Partikel werden beleuchtet,,Lumoj efikas partiklojn,Las luces afectan a las partículas,,Valot vaikuttavat hiukkasiin,Lumières affectent les particules,A fény hatással van a részecskékre,Le luci influiscono sulle particelle,ライトがパーティクルに影響,조명에 영향받는 입자들,Lichten beïnvloeden deeltjes,Lys påvirker partikler,Światło ma wpływ na cząsteczki,Luzes afetam partículas,,Luminile afectează particulele,Освещать частицы,Светло утиче на честице,Ljus påverkar partiklar,Işıklar parçacıkları etkiler, +Light shadowmaps,GLLIGHTMNU_LIGHTSHADOWMAP,,,,Mapy stínů,Lys skyggemapper,Shadowmaps für Lichter,,Lum-ombro-mapoj,Mapeo de sombra de luz,,Valojen varjokartat,Shadowmaps,,Ombre proiettate,ライトのシャドウマッピング,조명에 영향받는 섀도우맵,Lichte schaduwkaarten,Lys skyggekart,Oświetlenie map cieni,Shadowmaps,,Umbre lumini,Карты светотеней,Светло мапе сенки,Ljusskuggor,Işık gölge haritaları, +Shadowmap quality,GLLIGHTMNU_LIGHTSHADOWMAPQUALITY,,,,Kvalita map stínů,Shadowmap-kvalitet,Shadowmap Qualität,,Kvalito de ombro-mapo,Calidad de mapeo de sombras,,Varjokarttojen laatu,Qualité Shadowmap,Shadowmap minőség,Qualità ombre proiettate,シャドウマップ 品質,섀도우맵 퀄리티,Schaduwkaart kwaliteit,Shadowmap-kvalitet,Jakość map cieni,Qualidade de shadowmap,,Calitate umbre,Качество карт светотеней,Мапа сенки квалитет,Skuggmappens kvalitet,Gölge haritası kalitesi, +Shadowmap filter,GLLIGHTMNU_LIGHTSHADOWMAPFILTER,,,,Filtrování map stínů,Skyggemap-filter,Shadowmap Filter,,Filtro de ombro-mapo,Filtro de mapeo de sombras,,Varjokarttojen suodatus,Filtre de Shadowmaps,,Filtro ombre proiettate,シャドウマップ フィルター,섀도우맵 필터,Schaduwkaart filter,Shadowmap-filter,Filtr map cieni,Filtro de shadowmap,,Filtru umbre,Фильтр карт светотеней,Мапа сенки филтер,Filter för skuggmappor,Gölge haritası filtresi, +Fog mode,GLPREFMNU_FOGMODE,,,,Režim mlhy,Tågetilstand,Nebelmodus,,Reĝimo de nebulo,Modo de niebla,,Sumutila,Mode du broullard,Köd mód,Modalità nebbia,フォグモード,안개 모드,Mistmodus,Tåke-modus,Tryb mgły,Modo de neblina,,Mod ceață,Режим тумана,Магла мод,Dimläget,Sis modu, +Fog forces fullbright,GLPREFMNU_FOGFORCEFULLBRIGHT,,,,Mlha vynucuje plný jas,Tåge tvinger fullbright,Nebel erzwingt volle Helligkeit,,Nebulo devigas plenbrilon,Forzar brillo completo en niebla,,Sumu pakottaa täyskirkkauden,Brouillard force fullbright,Köd Fullbright-ot erőltet ki,La nebbia forza piena luce,濃霧は明るさ最大,안개를 최대한 강제로 밝힘,Mistkrachten volle lichtsterkte,Tåke styrker fullbright,Mgła wymusza pełną jasność,Neblina força brilho máximo,,Ceața forțează luminozitate maximă,Туман включает режим максимальной яркости,Магла присиљава пуну светлост,Dimma tvingar fram full ljusstyrka,Sis fullbright'ı zorlar, +Weapon light strength,GLPREFMNU_WPNLIGHTSTR,,,,Intenzita světel zbraní,Våbenlysstyrke,Waffenlichtstärke,,Lumforteco de armilo,Intensidad de luz de las armas,,Aseiden valovoima,Intensité lumineuse des armes,Fegyver lövés fényerősség,Intensità luminosa dell'arma,武器ライトの強さ,무기 빛 강도,Sterkte van het wapenlicht,Våpen lysstyrke,Natężenie światła broni,Intensidade de luz da arma,,Intensitate lumină armă,Интенсивность вспышек оружия,Блага снага оружја,Vapenljusets styrka,Silah ışık gücü, +Environment map on mirrors,GLPREFMNU_ENVIRONMENTMAPMIRROR,,,,Mapa prostředí na zrcadlech,Miljøkort på spejle,Lichteffekt auf Spiegeln,,Medimapo sur speguloj,Mapa de entorno en espejos,,Ympäristökartta peileissä,Mappage environment sur les miroirs,Környezeti mappolás a tükrökön,Ambiente mappa sui riflessi,マップオンミラーの画像表示,거울 주변의지도 활성,Milieukaart op spiegels,Omgivelseskart på speil,Mapa środowiska w lustrach,Mapa de ambiente em espelhos,,Reflecții pe oglinzi,Карта окружения на зеркалах,Околинска мапа на прозорима,Miljökarta på speglar,Aynalar üzerinde çevre haritası, +Enhanced night vision mode,GLPREFMNU_ENV,,,,Vylepšený režim nočního vidění,Forbedret nattesynstilstand,Verbesserter Nachtsichtmodus,,Plibonigita reĝimo de noktvido,Modo de visión nocturna mejorado,,Paranneltu pimeänäkötila,Mode de vision nocture amélioré,Felerősített éjjellátó mód,Modalità visione notturna migliorata,バイザーを暗視装置調にする,야시경 효과 향상,Verbeterde nachtzicht modus,Forbedret nattsynsmodus,Ulepszony tryb widzenia w ciemności,Modo de visão noturna avançada,,Vedere infraroșie avansată,Улучшенный режим ночного видения,Побољшана ноћна визија мод,Förbättrat läge för mörkerseende,Geliştirilmiş gece görüş modu, +ENV shows stealth monsters,GLPREFMNU_ENVSTEALTH,,,,Vylepšené noční vidění ukazuje skryté příšery,ENV viser stealth-monstre,Nachtsichtmodus zeigt Stealth-Monster,,ENV montras kaŝiĝitajn monstrojn,ENV muestra enemigos sigilosos,,PPN näyttää näkymättömät hirviöt,VNA affiche monstres invisibles,ENV felfedi a lopakodó szörnyeket,La VNM mostra i mostri stealth ,暗視バイザーが透明を見破る,스텔스 적 개체를 감지하는 ENV,ENV toont stealth monsters,ENV viser stealth monstre,Ulepszony noktowizor pokazuje ukrywających się przeciwników,Visão noturna mostra monstros invisíveis,,PNV afișează monștri ascunși,ПНВ показывает скрытых монстров,ПНВ показује скривена чудовишта,ENV visar smygande monster,ENV gizli canavarları gösteriyor, +Adjust sprite clipping,GLPREFMNU_SPRCLIP,,,,Vyladění clippingu spritů,Juster sprite clipping,Sprite Clipping,,Agordi trairadon de mov-rastrumoj,Ajustar recortado de sprites,,Spritejen asettelu,Adjusted le clipping des sprites,Sprite átlógás igazítása,Aggiusta il clipping degli sprite,スプライトのずらしを調整する,스프라이트 클리핑 조정,Sprite clipping,Juster sprite klipping,Ustaw wcięcie sprite'ów,Ajustar clipping de sprite,,Ajustare poziții sprite-uri,Режим обрезки спрайтов,Подеси спрајт клипинг,Justera sprite clipping,Sprite kırpmayı ayarlama, +Smooth sprite edges,GLPREFMNU_SPRBLEND,,,,Vyhladit okraje spritů,Udglatte sprite-kanter,Glätte Spritekanten,,Glatigi randojn de mov-rastrumoj,Suavizar bordes de sprites,,Pehmeät spritejen reunat,Adoucir bords des sprites,Sprite szélek simítása,Smussa gli angoli degli sprite,スプライトの角を丸める,부드러운 스프라이트 모서리,Gladde sprite randen,Glatte sprite kanter,Gładkie krawędzie sprite'ów,Suavizar bordas de sprites,,Netezire margini sprite-uri,Размытие краёв спрайтов,Углачати ивице спрајта,Slätar ut sprite-kanter,Düzgün sprite kenarları, +Fuzz Style,GLPREFMNU_FUZZSTYLE,,,,Styl šumu,Fuzz-stil,Fuzz Stil,,Stilo de Lenugo,Estilo de difuminación,,Sumennustyyli,Style de bruit blanc,Homályosítás stílusa,Stile fuzz,ファズスタイル,퍼즈 스타일,Fuzz stijl,Fuzz-stil,Styl Szumu,Estilo de difusão,,Stil sclipire,Тип шума,Фаз стајл,Fuzz stil,Fuzz Tarzı, +Sprite billboard,GLPREFMNU_SPRBILLBOARD,,,,Orientace spritů,,Spriteausrichtung,,Liniigi mov-rastrumojn,Alineado de sprites,,Spritetaulu,Etalage des sprites,Sprite alapú reklámtábla,,スプライト ビルボード,스프라이트 샘플링,,,Wyrównanie Sprite'ów,Alinhamento de sprite,,Rotire sprite-uri,Привязка по осям спрайтов,Спрајт билборд,,Sprite reklam panosu, +Sprites face camera,GLPREFMNU_SPRBILLFACECAMERA,,,,Sprity čelí kameře,Sprites vender mod kameraet,Sprites zur Kamera ausrichten,,Mov-rastrumoj ĉiam rigardas vian kameraon,Los sprites miran a la cámara,,Spritet suuntaavat kameraan,Sprites font face à la caméra,Sprite alapú kamera,Gli sprite sono rivolti alla telecamera.,スプライトのフェイスカメラ,카메라를 향한 스프라이트,Sprites gezicht camera,Sprites vender mot kameraet,Sprite'y skierowane w kamerę,Sprites de frente para a câmera,,Sprite-urile privesc înspre cameră,Спрайты направлены к камере,Спрајт камера фаце,Sprites vänder sig mot kameran,Sprite'lar kamerayla yüzleşir, +Particle style,GLPREFMNU_PARTICLESTYLE,,,,Styl částic,Partikelstil,Partikelstil,,Partikla stilo,Estilo de partículas,,Hiukkastyyli,Style de particules,Részecske stílusa,Stile particelle,パーティクル スタイル,입자 스타일,Deeltjes stijl,Partikkel-stil,Styl Cząsteczek,Tipo de partícula,,Stil particule,Тип частиц,Честице стајл,Partikelstil,Parçacık stili, +Rendering quality,GLPREFMNU_RENDERQUALITY,,,,Kvalita vykreslování,Renderingskvalitet,Renderqualität,,Kvalito de bildigado,Calidad de Renderizado,,Hahmonnuslaatu,Qualité du rendu,Renderelés minősége,Qualità resa grafica,レンダリング品質,렌더링 품질,Het teruggeven van kwaliteit,Renderingskvalitet,Jakość Renderowania,Qualidade de renderização,,Calitate video,Качество обработки,Квалитет рендовања,Renderingskvalitet,Render kalitesi, +Stereo 3D VR,GLPREFMNU_VRMODE,,,,,,,,Duvida 3D VR,Modo Stereo 3D VR,,,3D VR Stéréo,,,ステレオ3DのVR,VR 입체 스테레오 사용,,,,3D Estéreo (VR),,Mod VR,Стерео 3D VR-режим,Стереотоно 3D VR,,, +Enable Quad Stereo,GLPREFMNU_VRQUADSTEREO,,,,Povolit Quad Stereo,Aktiver Quad Stereo,Quad Stereo aktivieren,,Ŝalti Kvaroblo-Stereon,Activar Quad Stereo,,Ota käyttöön Quad Stereo,Activer Quad Stereo,Quad Sztereó bekapcsolása,Abilita il Quad Stereo,クァッドステレオを有効,쿼드 스테레오 사용,Quad Stereo inschakelen,Aktiver Quad Stereo,Włącz Poczwórne Stereo,Habilitar Quad Stereo,Permitir Quad Stereo,Activare Quad Stereo,Четырёхкратный стереорежим,Омогући четвороструки стерео,Aktivera Quad Stereo,Dörtlü Stereoyu Etkinleştir, +Banded SW Lightmode,GLPREFMNU_SWLMBANDED,,,,Režim pruhovaného SW osvětlení,Båndede SW-lystilstand,Gebänderter SW-Lichtmodus,,Reĝimo de Bendiga Lumo de Programbildigo,Modo de luz por bandas de SW,,Kaistoitettu ohjelmistoväritila,Lumière bandées en Software,,Lightmode software bandata,バンデドSWライトモード,단결된 SW 라이트 모드,SW-lichtmodus met banden,Båndet SW-lysmodus,Naznaczony Tryb Oświetlenia Oprogramowania,Modo de luz por bandas em software,,Mod limitat de iluminare Software,Программный режим освещения полосами,Повезани SW режим осветљења,SW Ljusläge i bandform,Bantlı SW Işık Modu, +Distance Between Your Eyes,GLPREFMNU_VRIPD,,,,Vzdálenost mezi očima,Afstand mellem øjnene,Abstand zwischen den Augen,,Distanco Inter Viaj Okuloj,Distancia entre tus ojos,,Silmiesi etäisyys toisistaan,Distance entre vos yeux,Szemek közötti távolság,Distranza tra i tuoi occhi,自分の目との距離,시야 간의 거리,Afstand tussen uw ogen,Avstand mellom øynene dine,Odległość Pomiędzy Twoimi Oczami,Distância entre os olhos,,Distanța dintre ochi,Расстояние между глазами,Даљина између твојих очију,Avstånd mellan ögonen,Gözleriniz Arasındaki Mesafe, +Distance From Your Screen,GLPREFMNU_VRSCREENDIST,,,,Vzdálenost od obrazovky,Afstand fra din skærm,Abstand vom Bildschirm,,Distanco De Via Ekrano,Distancia desde tu pantalla,,Etäisyys ruudullesi,Distance entre vous et l'écran,Képernyőtől mért távolság,Distanza dal tuo schermo,画面からの距離,화면과의 거리,Afstand van uw scherm,Avstand fra skjermen,Odległość Od Twojego Ekranu4,Distância a partir da tela,,Distanța față de ecranul tău,Расстояние от экрана,Даљина од окрена,Avstånd från skärmen,Ekranınızdan Uzaklık, +Smart,OPTVAL_SMART,,,,Chytré,,,,Inteligenta,Inteligente,,Älykäs,Intelligent,Okos,Intelligente,スマート,자동 조정,Slim,,Mądry,Inteligente,,Inteligent,Умный,Паметно,,Akıllı, +Smarter,OPTVAL_SMARTER,,,,Chytřejší,Smartere,,,Pli inteligenta,Más inteligente,,Älykkäämpi,+ Intelligent,Okosabb,Ancora più intelligente,よりスマート,고급 자동 조정,Slimmer,Smartere,Mądrzejszy,Mais inteligente,,Mai inteligent,Умнее,Паметније,Smartare,Daha Akıllı, +Infrared only,OPTVAL_INFRAREDONLY,,,,Pouze infračervené,Kun infrarødt,Nur Infrarot,,Nur transruĝa,Solo infrarrojo,,Vain infrapuna,Vis. Noct. Seulement,Csak az infravörösnél,Solo infrarossi,赤外線のみ,야시경만,Alleen infrarood,Kun infrarød,Tylko Podczerwień,Somente infravermelho,,Doar în infraroșu,Только инфракрасный,Само инфрацрвена,Endast infrarött ljus,Sadece kızılötesi, +Infrared and torch,OPTVAL_INFRAREDANDTORCH,,,,Infračervené a pochodeň,Infrarød og lommelygte,Infrarot und Fackel,,Transruĝa kaj torĉo,Infrarrojo y antorcha,,Vain infrapuna ja soihtu,Iis Noct. & Torche,Infravörös és fáklya,Infrarossi e torcia,赤外線と松明,야시경과 횃불만,Infrarood en fakkels,Infrarød og lommelykt,Tylko Podczerwień i Pochodnie,Infravermelho e tocha,,Infraroșu si torță,Инфракрасный и факел,Инфрацрвена/бакља,Infraröd och ficklampa,Kızılötesi ve fener, +Any fixed colormap,OPTVAL_ANYFIXEDCOLORMAP,,,Any fixed colourmap,Jakákoli fixní mapa barev,Alle lyseffekter,Alle Lichteffekte,,Iu ajn fiksita kolormapo,Cualquier mapa de color fijo,,Mikä tahansa kiinteä värikartta,N'importe quelle colormap,Bármely fixált colormap,Ogni colormap fissata,任意の固定カラーマップ,고정된 컬러맵만,Elke vaste colormap,Alle faste fargekart,Którekolwiek naprawione mapy kolorów,Qualquer colormap fixo,,Orice colormap,Любая заданная цветовая карта,Било која поправљена табела боја,Alla fasta färgkartor,Herhangi bir sabit renk haritası, Use as palette,OPTVAL_USEASPALETTE,,,,Použít jako paletu,Brug som palet,Benutze als Palette,,Uzi kiel paletro,Usar como paleta,,Käytä palettina,Utiliser comme pallette,Palettaként használat,Utilizza come palette,パレットとして使用,팔레트로 적용,Gebruik als palet,Bruk som palett,"Użyj jako palety -",Usar como paleta,Usar como palete,Utilizare drept paletă,Использовать как палитру,Користи као палету,Palet olarak kullanın -Blend,OPTVAL_BLEND,,,,Míchat,Blend,Überblenden,,Miksi,Mezclar,,Sekoitus,Mélanger,Kever,Miscela,混合,혼합,Mengen,Blanding,Połącz,Mesclar,Misturar,Amestec,Смешать,Бленд,Karışım -Bright,OPTVAL_BRIGHT,,,,Světlý,Lys,Hell,,Hela,Brillante,,Kirkas,Clair,Világos,Chiara,明るい,밝은,Helder,Lys,Jasne,Claro,,Luminos,Яркий,Свијетло,Parlak -Dark,OPTVAL_DARK,,,,Tmavý,Mørk,Dunkel,,Malhela,Oscuro,,Tumma,Sombre,Sötét,Scura,暗い,어두운,Donker,Mørk,Ciemne,Escuro,,Întunecat,Тёмный,Тамно,Karanlık -Doom Legacy,OPTVAL_LEGACY,,,,,,Doom Legacy,,,,,Doom Legacy,,Hagyományos Doom,,DOOM調,둠 레거시,,,,,,,,, -Software,OPTVAL_SOFTWARE,,,,,,,,Programa bildigilo,,,Ohjelmisto,,Szoftver,,ソフトウェア,소프트웨어,,,Oprogramowanie,,,,Программный,Софтвер,Yazılım -Optimal,OPTVAL_OPTIMAL,,,,Optimální,,,,Optima,Óptimo,,Optimaalinen,Optimiser,Optimális,Ottimale,最適,최적함,Optimaal,,Optymalne,Otimizado,,Optim,Оптимальный,Оптимал,Optimal -Y Axis,OPTVAL_YAXIS,,,,Po ose Y,Y-akse,Y-Achse,,Y-Akso,Eje Y,,Y-akseli,Axe Y,Y tengely,Asse Y,縦軸,Y 축,Y-as,Y-akse,Oś Y,Eixo Y,,Axa Y,По горизонтали,Y оса,Y Ekseni -X/Y Axis,OPTVAL_XYAXIS,,,,Po osách X/Y,X/Y-akse,X/Y-Achse,,X/Y-Akso,Ejes X/Y,,X- ja Y-akselit,Axes X/Y,X/Y tengely,Asse X/Y,縦/横軸,X/Y 축,X/Y As,X/Y-akse,Oś X/Y,Eixo X/Y,,Axa Y/Z,По обеим осям,X/Y оса,X/Y Ekseni -Square,OPTVAL_SQUARE,,,,Čtvercové,Firkantet,Quadratisch,,Kvadrata,Cuadrado,,Kulmikas,Carrées,Négyzet,Quadrato,平方,정사각형,Vierkant,Firkantet,Kwadrat,Quadrado,,Pătrat,Квадратные,Квадрат,Kare -Round,OPTVAL_ROUND,,,,Kulaté,Rund,Rund,,Ronda,Redondo,,Pyöreä,Rondes,Kör,Arrotondato,円形,원형,Rond,Rund,Okrągłe,Redondo,,Rotund,Круглые,Круг,Yuvarlak -Radial,OPTVAL_RADIAL,,,,Radiální,,,Ακτινικό,Radiusa,,,Säteittäinen,,Sugaras,Radiale,放射状,방사형,Radiaal,,Promieniowe,,,Radială,Радиальный,Радијално,Radyal -Pixel fuzz,OPTVAL_PIXELFUZZ,,,,Pixelový fuzz,,Pixel,Pixel θολούρα,Bildera lanugo,Difuminado pixelado,,Kuvapistesumennus,Bruit Pixélisé,Pixeles homály,Fuzz pixelato,ピクセル ファズ,픽셀 퍼즈,Pixel fuzz,,Szum pikseli,Difuso pixelado,,Puf,Пиксельный шум,Пикселизовани фаз,Piksel fuzz -Smooth fuzz,OPTVAL_SMOOTHFUZZ,,,,Hladký fuzz,Glat fuzz,Glatt,Ομαλή θολούρα,Glata lanugo,Difuminado borroso,,Pehmeä sumennus,Bruit doux,Simított homály,Fuzz liscio,滑らかなファズ,부드러운 퍼즈,Gladde fuzz,Glatt fuzz,Wygładzony szum,Difuso suavizado,,Lin,Гладкий шум,Глатки фаз,Pürüzsüz fuzz -Swirly fuzz,OPTVAL_SWIRLYFUZZ,,,,Míchající fuzz,Svirklende fuzz,Gewirbelt,Περιστροφηκή θολούρα,Kirla lanugo,Difuminado en remolino, ,Pyörteinen sumennus,Bruit marbré,Örvénylő homály,Fuzz vorticoso,渦状ファズ,소용돌이 퍼즈,Zwerpend fuzz,Virvlende fuzz,Wirujący szum,Difuso encaracolado,,Vârtej,Кружащийся шум,Увртен фаз,Girdaplı fuzz -Translucent fuzz,OPTVAL_TRANSLUCENTFUZZ,,,,Průhledný fuzz,Gennemskinnelig fuzz,Transparent,Ημιδιαφανής θολούρα,Diafana lanugo,Difuminado Translúcido,,Läpikuultava sumennus,Bruit transparent,Áttetsző homály,Fuzz traslucido,半透明ファズ,반투명 퍼즈,Doorschijnende fuzz,Gjennomsiktig fuzz,Przezroczysty szum,Difuso translúcido,,Transparent,Прозрачный шум,Прозрачан фаз,Yarı saydam fuzz -Noise,OPTVAL_NOISE,,,,Šum,Støj,Rauschen,Ήχος,Bruo,Ruido,,Kohina,Neige,Zaj,Rumore,ノイズ,노이즈,Lawaaierige fuzz,Støy,Huk,Ruído,,Zgomot,Шум,Звук,Gürültü -Smooth Noise,OPTVAL_SMOOTHNOISE,,,,Hladký šum,Glat støj,Geglättetes Rauschen,Ομαλός ήχος,Glata Bruo,Ruido borroso,,Pehmeä kohina,Neige adoucie,Simított zaj,Rumore liscio,滑らかなノイズ,부드러운 노이즈,Gladde lawaaierige fuzz,Glatt støy,Wugładzony huk,Ruído suavizado,,Zgomot lin,Мягкий шум,Милозвучан звук,Yumuşak Gürültü -Jagged fuzz,OPTVAL_JAGGEDFUZZ,,,,Zubatý šum,Skarpt fuzz,Gezackt,Ζαρομένη θολούρα,Malglateca lanugo,Difuminado dentado,,Sahalaitainen sumennus,Neige rugeuse,Recés homály,Fuzz frastagliato,ギザギザ,들쭉날쭉한 퍼즈,Gekartelde fuzz,Takkete fuzz,Poszarpany szum,Difuso serrilhado,,Zimțat,Зазубренный шум,Назубљен фаз,Pürüzlü fuzz -Green/Magenta,OPTVAL_GREENMAGENTA,,,,Zelená/purpurová,Grøn/Magenta,Grün/Magenta,Πράσινο/Magenta,Verda/Magenta,Verde/Magenta,,Vihreä/Magenta,Vert/Magenta,Zöld/Magenta,Verde/Magenta,緑/紫,초록/심홍색,Groen/Magenta,Grønn/magenta,Zielony/Magenta,Verde/Magenta,,Verde/Purpuriu,Зелёный/пурпурный,Зелен/Магента,Yeşil/Macenta -Red/Cyan,OPTVAL_REDCYAN,,,,Červená/tyrkysová,Rød/Cyan,Rot/Cyan,Κόκινο/Κυανό,Ruĝa/Cejana,Rojo/Cian,,Punainen/Sinivihreä,Rouge/Bleu,Piros/Türkiz,Rosso/Ciano,赤/空,빨강/하늘색,Rood/Cyaan,Rød/cyan,Czerwony/Błękitny,Vermelho/Ciano,,Roșu/Turcoaz,Красный/голубой,Црвен/Цијан,Kırmızı/Mavi -Amber/Blue,OPTVAL_AMBERBLUE,,,,Oranžová/modrá,Rav/blå,Orange/Blau,Amber/Μπλέ,Sukcenokolora/Blua,Ámbar/Azul,,Ruskeankeltainen/Sininen,Ambre/Bleu,Sárga/Kék,Ambra/Blu,黄/青,황토/파랑색,Amber/Blauw,Rav/blå,Bursztynowy/Niebieski,Âmbar/Azul,,Chihlimbar/Albastru,Янтарный/синий,Ћилибарски/Плаво,Kehribar/Mavi -Left Eye,OPTVAL_LEFTEYE,,,,Levé oko,Venstre øje,Linkes Auge,Αριστερό μάτι,Maldekstra Okulo,Ojo izquierdo,,Vasen silmä,Oeil Gauche,Bal szem,Occhio sinistro,左目,왼쪽 눈,Linkeroog,Venstre øye,Lewe Oko,Olho Esquerdo,,Ochi Stâng,Левый глаз,Лево око,Sol Göz -Right Eye,OPTVAL_RIGHTEYE,,,,Pravé oko,Højre øje,Rechtes Auge,Δεξί μάτι,Dekstra Okulo,Ojo derecho,,Oikea silmä,Oeil Droit,Jobb szem,Occhio destro,右目,오른쪽 눈,Rechteroog,Høyre øye,Prawe Oko,Olho Direito,,Ochi drept,Правый глаз,Десно око,Sağ Göz -Side-by-side Full,OPTVAL_SBSFULL,,,,"Vedle sebe, plné",Side ved side i fuld bredde,Nebeneinander volle Breite,,Flank-ĉe-flanka Tuta,Lado a lado completo,,Täysi rinnakkaisasettelu,Côte-â-côte Complet,Egymás melletti Teljes,Fianco a fianco completo,両サイド フル,크게 좌우배치,Zij-aan-zij Volledig,Side-ved-side Full,Pełne Obok Siebie,Lado a lado completo,,Una lângă alta Pline,"Бок о бок, полно",Раме уз раме цело,Yan yana Tam -Side-by-side Narrow,OPTVAL_SBSNARROW,,,,"Vedle sebe, úzké",Side ved side i halv bredde,Nebeneinander halbe Breite,,Flank-ĉe-flanka Mallarĝa,Lado a lado estrecho,,Kapea rinnakkaisasettelu,Côte-â-côte étroit,Egymás melletti Szűk,Fianco a fianco stretto,両サイド ナロー,좁게 좌우배치,Zij-aan-zij smal,Side ved side Smal,Wąskie Obok Siebie,Lado a lado estreito,,Una lângă alta Înguste,"Бок о бок, узко",Раме уз раме уско,Yan yana Dar -Top/Bottom,OPTVAL_TOPBOTTOM,,,,Nad sebou,Øverst/underst,Übereinander,Πάνω/Κάτω,Supero/Subo,Superior/Inferior,,Ylä-/Alaosa,Dessus/Dessous,Fent/Lent,Sopra/Sotto,天/底,위/아래,Boven/onderkant,Topp/Bunn,Góra/Dół,Superior/Inferior,,Sus/Jos,Сверху/снизу,Врх/Дно,Üst/Alt -Row Interleaved,OPTVAL_ROWINTERLEAVED,,,,Po řádcích,Forskydning af rækker,Zeilenversetzt,,Vicoj interteksitaj,Fila intercalada,,Vaakalomitus,Entrelacement rangée,Sor beillesztés,Riga interfogliata,行インターリーブ,열 교차 배치,Rij interleaved,Rad sammenflettet,Przepleciony Szereg,Linha Intercalada,,Rând intercalat,Чередование строк,Редно прошарано,Satır Aralıklı -Column Interleaved,OPTVAL_COLUMNINTERLEAVED,,,,Po sloupcích,Forskydning af kolonner,Spaltenversetzt,,Kolonoj interteksitaj,Columna intercalada,,Pystylomitus,Entralcement colonne,Oszlop beillesztés,Colonna interfogliata,列インターリーブ,세로줄 교차 배치,Kolom Interleaved,Kolonne sammenflettet,Przepleciona Kolumna,Coluna Intercalada,,Coloană intercalată,Чередование столбцов,Колонско прошарано,Sütun Aralıklı -Checkerboard,OPTVAL_CHECKERBOARD,,,,Šachovnice,Ternet,Schachbrettmuster,,Ŝaktablo,Tablero de damas,,Shakkilautakuvio,Damier,Tábla,Scacchiere,市松模様,체크무늬,Dambord,Sjakkbrett,Szachownica,Xadrez,,Tablă de Șah,Шахматная доска,Шаховска табла,Dama Tahtası -Quad-buffered,OPTVAL_QUADBUFFERED,,,,Quad buffer,Quad-buffered,Vierfachgepuffert,,Kvarobla bufro,Cuádruple búfer,,Neloispuskurointi,Quadruple-tampon,Négyszeresen bufferelt,Quad buffer,クワッドバッファー,쿼드 버퍼,Viervoudig gebufferd,Firebufret,Poczwórnie zbuforowane,Buffer quádruplo,,Împătrit,Четырёхкратный,Квад-унапређено,Dört tamponlu -TrueColor Options,DSPLYMNU_TCOPT,,,,Nastavení True color,TrueColor-indstillinger,TrueColor Optionen,TrueColor Ρυθμίσεις,Plenkolora Agordoj,Opciones TrueColor,,TrueColor-asetukset,Options TrueColor,TrueColor Beállítások,Opzioni TrueColor,トゥルーカラー オプション,트루 컬러 설정,TrueColor Opties,TrueColor-alternativer,Opcje TrueColor,Opções de TrueColor,,Setări Mod Culori Complete,Полноцветный режим,Подешавања правих боја,TrueColor Seçenekleri -TrueColor Options,TCMNU_TITLE,,,,Nastavení True color,TrueColor-indstillinger,TrueColor Optionen,TrueColor Ρυθμίσεις,Plenkolora Agordoj,Opciones TrueColor,,TrueColor-asetukset,Options TrueColor,TrueColor Beállítások,Opzioni TrueColor,トゥルーカラー オプション,트루 컬러 설정,TrueColor Opties,TrueColor-alternativer,Opcje TrueColor,Opções de TrueColor,,Setări Mod Culori Complete,Настройки полноцветности,Подешавања правих боја,TrueColor Seçenekleri -True color output,TCMNU_TRUECOLOR,,,,Výstup True color,TrueColor-udgang,TrueColor Ausgabe,TrueColor παραγωγή,Plenkolora eligo,Salida de True color,,True color -ulostulo,Sortie Truecolor,Truecolor Kimenet,Output true color,トゥルーカラー出力,트루 컬러 출력,Ware kleurenoutput,Ekte fargeutgang,Wyjście TrueColor,Saída de true color,,Putere Mod Culori Complete,Полноцветный вывод,Излаз правих боја,Gerçek renk çıkışı -Linear filter when downscaling,TCMNU_MINFILTER,,,,Lineární filtrování při zmenšení,Lineært filter ved nedskalering,Linearer Filter beim Herunterskalieren,Γραμμικό φίλτρο για σμίκρυνση,Linia filtro kiam subskali,Filtro lineal por reducción,,Lineaarinen suodatin alas skaalatessa,Filtrage linéaire en réduction,Lineáris filterezés leméretezésnél,Filtro lineare per la riduzione,縮小時のリニアフィルター,축소시 선형 필터링함,Lineair filter voor downscaling,Lineært filter ved nedskalering,Liniowy filtr podczas zmniejszania rozmiaru,Filtro linear ao reduzir,,Filtru liniar la micșorare,Линейная фильтрация при уменьшении,Линеарни филтер током смањења,Küçültme sırasında doğrusal filtre -Linear filter when upscaling,TCMNU_MAGFILTER,,,,Lineární filtrování při zvětšení,Lineært filter ved opskalering,Linearer Filter beim Hochskalieren,Γραμμικό φίλτρο για πολυτέληση,Linia filtro kima superskali,Filtro lineal por escalado,,Lineaarinen suodatin ylös skaalatessa,Filtrage linéaire en agrandissement,Lineáris filterezés felméretezésnél,Filtro lineare per l'aumento,拡大時のリニアフィルター,확대시 선형 필터링함,Lineair filter voor upscaling,Lineært filter ved oppskalering,Liniowy filtr podczas zwiększania rozmiaru,Filtro linear ao aumentar,,Filtru liniar la mărire,Линейная фильтрация при увеличении,Линеарни филтер током повећања,Yükseltme sırasında doğrusal filtre -Use mipmapped textures,TCMNU_MIPMAP,,,,Použít mipmapy,Brug mipmapped teksturer,Benutze Textur-Mipmaps,Χρήση mipmapped υφών,Uzi mipmapajn teksturojn,Usar texturas con mipmap,,Käytä mipkartallisia pintakuviointeja,Utiliser textures mipmappées,Mipmap textúrák,Usa le texture mipmapped,ミップマップテクスチャを使用,밉맵 텍스쳐 사용,Gebruik mipmapped texturen,Bruk mipmapped teksturer,Użyj mipmapowane tekstury,Usar texturas com mipmapping,,Mip mapping pentru texturi,Применять MIP-текстурирование,Користи мипмаповане текстуре,Eşlenmiş dokular kullanın -Dynamic lights (Software),TCMNU_DYNLIGHTS,,,,Dynamická světla (software),Dynamisk lys (software),Dynamisches Licht (Software),Δυναμικά φώτα (Λογισμικό),Dinamikaj lumoj (Programbildigilo),Luces dinámicas (Software),,Dynaamiset valot (ohjelmisto),Lumières Dynamiques (Software),Dinamikus fények (szoftveres),Luci Dinamiche (Software),ダイナミックライト (ソフトウェア),다이나믹 라이트 (소프트웨어 버전),Dynamische verlichting (software),Dynamiske lys (programvare),Dynamiczne Światło (Oprogramowanie),Luzes Dinâmicas (Software),,Lumini Dinamice (Mod Software),Динамическое освещение (программное),Динамичко осветљење (софтвер),Dinamik ışıklar (Yazılım) -Option Search,OS_TITLE,,,,Vyhledávání možností,Mulighed Søg,Optionssuche,Αναζήτηση Ρυθμίσεων,Agorda Serĉo,Buscar Opciones,,Asetushaku,Recherche Option,Beállítás Keresés,Opzioni di ricerca,オプション検索,옵션 검색,Optie zoeken,Alternativt søk,Szukanie Opcji,Buscar opção,Procurar opção,Căutare Setări,Поиск настройки,Претрага,Seçenek Arama -Search for any term,OS_ANY,,,,Hledat jakékoli klíčové slovo,Søg efter et vilkårligt begreb,Suche nach beliebigem Begriff,Αναζήτηση για όποιαδηποτε λέξη,Serĉi por iu ajn termino,Buscar cualquier término,,Etsi mitä tahansa sanaa,N'importe quel mot,Bármilyen szótagra keresés,Cerca per ciascun termine,いずれかの用語を探す,용어 검색,Zoek naar eender welke term,Søk etter et vilkårlig begrep,Szukaj jakiegokolwiek wyrażenia,Buscar por qualquer termo,Procurar por um termo qualquer,Căutare după orice termen,Искать любое из слов,Тражи било коју од речи,Herhangi bir terim için arama yapın -Search for all terms,OS_ALL,,,,Hledat všechna klíčová slova,Søg efter alle udtryk,Suche nach allen Begriffen,Αναζήτηση για όλες της λέξεις,Serĉi por ĉiuj terminoj,Buscar todos los términos,,Etsi kaikki sanat,Tous les mots,Összes szótagra keresés,Cerca per tutti i termini,全ての用語を探す,모든 조건 검색,Zoek naar alle termen,Søk etter alle termer,Szukaj wszystkich wyrażeń,Buscar por todos os termos,Procurar por todos os termos,Căutare după toți termenii,Искать все слова,Тражи све речи,Tüm terimler için arama yapın -No results found.,OS_NO_RESULTS,,,,Nic nenalezeno.,Ingen resultater fundet.,Keine Resultate,Δέν βρέθηκαν αποτελέσματα,Neniuj rezultoj trovitaj.,Ningun resultado.,,Ei tuloksia.,Pas de résultat trouvé,Nincs keresési találat,Nessun risultato trovato.,見つかりませんでした。,검색 결과 없음.,Geen resultaten gevonden.,Ingen resultater funnet.,Brak wyników,Nenhum resultado encontrado.,,Niciun rezultat găsit.,Результаты не найдены.,Нема резултата.,Sonuç bulunamadı. -Search:,OS_LABEL,,,,Hledat:,Søg:,Suche:,Αναζήτηση:,Serĉi:,Buscar:,,Etsi:,Recherche:,Keresés:,Trova:,検索:,검색:,Zoeken:,Søk:,Szukaj:,Busca:,Procura:,Căutare:,Поиск:,Претрага:,Arama yapın: -Always show keys,AUTOMAPMNU_SHOWKEYS_ALWAYS,,,,Vždy zobrazit klíče,Vis altid nøgler,Zeige immer alle Schlüssel,Εμφάνιση πλήκτρων πάντα,Ĉiam montri ŝlosilojn,Mostrar llaves siempre,,Aina näytä avaimet,Toujour afficher clés,Kulcsokat mindig mutat,Mostra sempre le chiavi,常にキーを表示,항상 키들을 표시,Toon altijd de toetsen,Vis alltid nøkler,Zawsze pokazuj klucze,Sempre mostrar chaves,Exibir chaves sempre,Afișează cheile în permanență,Всегда отображать ключи,Увек приказуј кључеве,Her zaman anahtarları göster -,,Newly added content,,,,,,,,,,,,,,,,,,,,,,,, -Team changing has been disabled!,TXT_NO_TEAM_CHANGE,,,,Změna týmu je vypnuta!,Holdskift er blevet deaktiveret!,Teamwechsel ist deaktiviert!,Η αλαγγή ομάδον απαγορεύεται!,Teamŝanĝiĝo estas malvalidigita!,¡El cambio de equipo ha sido desactivado!,,Joukkueen vaihtaminen on kytketty pois päältä!,Les changements d'équipe sont désactivés!,Csapatváltás letiltva,È stato disabilitato il cambio di squadra!,チームの変更は受け付けない!,팀 변경이 불가능해짐!,Teamwisseling is uitgeschakeld!,Lagbytte har blitt deaktivert!,Zmiana drużyn została wyłączona!,Troca de equipe foi desativada!,Troca de equipa foi desativada!,Schimbarea echipelor a fost dezactivată!,Смена команды была отключена!,Мењање тима је искључено!,Takım değiştirme devre dışı bırakıldı! -%s joined the %t team,TXT_JOINED_TEAM,%s is the player and gender sensitive,,,%s se připojil@[ao_cs] k týmu %t.,%s er blevet medlem af %t-team,%s is dem %t Team beigetreten.,@[art_gr] %s έγινε μέλος τής %t ομάδας,%s aliĝis al la %t teamo,%s se unió al equipo %t,,%s liittyi joukkueeseen %t,%s a rejoint l'équipe %t.,%s belépett a %t csapatba,%s entra nel team %t,%s は %t のチームに入隊した,%s 이(가) %s 팀에 합류함,%s zijn bij het %t team gekomen.,%s ble med i %t-teamet,%s dołącza do drużyny %t,%s entrou na equipe %t,,%s s-a alăturat echipei %t,Игрок %s присоединяется к команде %t,%s је уш@[ao_2_sr] у %t тим,%s %t takımına katıldı -%s is now a loner.,TXT_LONER,,,,%s je teď @[self_cs].,%s er nu en enspænder.,%s ist jetzt ein@[e_de] Einzelgänger@[in_de].,@[art_gr] %s είναι τώρα μόνο/ς/η @[pro4_gr],%s nun estas solemulo.,%s es ahora solitari@[ao_esp].,,%s on nyt yksikseen.,%s joue maintenant tout seul.,%s immáron magányos útralépett,%s è da solo,%s は今 一匹狼だ。,%s 은(는) 혼자 남음.,%s is nu een eenling.,%s er nå en einstøing.,%s jest teraz sam@[ao_pl],%s está sozinh@[ao_ptb] agora.,,%s este singur acum,Игрок %s теперь одиночка.,%s је сада самотњак.,%s artık yalnız. +",Usar como paleta,Usar como palete,Utilizare drept paletă,Использовать как палитру,Користи као палету,Används som palett,Palet olarak kullanın, +Blend,OPTVAL_BLEND,,,,Míchat,,Überblenden,,Miksi,Mezclar,,Sekoitus,Mélanger,Kever,Miscela,混合,혼합,Mengen,Blanding,Połącz,Mesclar,Misturar,Amestec,Смешать,Бленд,Blanda,Karışım, +Bright,OPTVAL_BRIGHT,,,,Světlý,Lys,Hell,,Hela,Brillante,,Kirkas,Clair,Világos,Chiara,明るい,밝은,Helder,Lys,Jasne,Claro,,Luminos,Яркий,Свијетло,Ljusa,Parlak, +Dark,OPTVAL_DARK,,,,Tmavý,Mørk,Dunkel,,Malhela,Oscuro,,Tumma,Sombre,Sötét,Scura,暗い,어두운,Donker,Mørk,Ciemne,Escuro,,Întunecat,Тёмный,Тамно,Mörk,Karanlık, +Doom Legacy,OPTVAL_LEGACY,"This refers to the Doom Legacy port, not a legacy lighting style!",,,,,,,,,,,,,,,,,,,,,,,,,, +Software,OPTVAL_SOFTWARE,,,,,,,,Programa bildigilo,,,Ohjelmisto,,Szoftver,,ソフトウェア,소프트웨어,,,Oprogramowanie,,,,Программный,Софтвер,Programvara,Yazılım, +Optimal,OPTVAL_OPTIMAL,,,,Optimální,,,,Optima,Óptimo,,Optimaalinen,Optimiser,Optimális,Ottimale,最適,최적함,Optimaal,,Optymalne,Otimizado,,Optim,Оптимальный,Оптимал,Optimal,Optimal, +Y Axis,OPTVAL_YAXIS,,,,Po ose Y,Y-akse,Y-Achse,,Y-Akso,Eje Y,,Y-akseli,Axe Y,Y tengely,Asse Y,縦軸,Y 축,Y-as,Y-akse,Oś Y,Eixo Y,,Axa Y,По горизонтали,Y оса,Y-axeln,Y Ekseni, +X/Y Axis,OPTVAL_XYAXIS,,,,Po osách X/Y,X/Y-akse,X/Y-Achse,,X/Y-Akso,Ejes X/Y,,X- ja Y-akselit,Axes X/Y,X/Y tengely,Asse X/Y,縦/横軸,X/Y 축,X/Y As,X/Y-akse,Oś X/Y,Eixo X/Y,,Axa Y/Z,По обеим осям,X/Y оса,X/Y-axel,X/Y Ekseni, +Square,OPTVAL_SQUARE,,,,Čtvercové,Firkantet,Quadratisch,,Kvadrata,Cuadrado,,Kulmikas,Carrées,Négyzet,Quadrato,平方,정사각형,Vierkant,Firkantet,Kwadrat,Quadrado,,Pătrat,Квадратные,Квадрат,Kvadratisk,Kare, +Round,OPTVAL_ROUND,,,,Kulaté,Rund,Rund,,Ronda,Redondo,,Pyöreä,Rondes,Kör,Arrotondato,円形,원형,Rond,Rund,Okrągłe,Redondo,,Rotund,Круглые,Круг,Rund,Yuvarlak, +Radial,OPTVAL_RADIAL,,,,Radiální,,,Ακτινικό,Radiusa,,,Säteittäinen,,Sugaras,Radiale,放射状,방사형,Radiaal,,Promieniowe,,,Radială,Радиальный,Радијално,Radial,Radyal, +Pixel fuzz,OPTVAL_PIXELFUZZ,,,,Pixelový fuzz,,Pixel,Pixel θολούρα,Bildera lanugo,Difuminado pixelado,,Kuvapistesumennus,Bruit Pixélisé,Pixeles homály,Fuzz pixelato,ピクセル ファズ,픽셀 퍼즈,Pixel fuzz,,Szum pikseli,Difuso pixelado,,Puf,Пиксельный шум,Пикселизовани фаз,,Piksel fuzz, +Smooth fuzz,OPTVAL_SMOOTHFUZZ,,,,Hladký fuzz,Glat fuzz,Glatt,Ομαλή θολούρα,Glata lanugo,Difuminado borroso,,Pehmeä sumennus,Bruit doux,Simított homály,Fuzz liscio,滑らかなファズ,부드러운 퍼즈,Gladde fuzz,Glatt fuzz,Wygładzony szum,Difuso suavizado,,Lin,Гладкий шум,Глатки фаз,Slät fuzz,Pürüzsüz fuzz, +Swirly fuzz,OPTVAL_SWIRLYFUZZ,,,,Míchající fuzz,Svirklende fuzz,Gewirbelt,Περιστροφηκή θολούρα,Kirla lanugo,Difuminado en remolino, ,Pyörteinen sumennus,Bruit marbré,Örvénylő homály,Fuzz vorticoso,渦状ファズ,소용돌이 퍼즈,Zwerpend fuzz,Virvlende fuzz,Wirujący szum,Difuso encaracolado,,Vârtej,Кружащийся шум,Увртен фаз,Virvlande fuzz,Girdaplı fuzz, +Translucent fuzz,OPTVAL_TRANSLUCENTFUZZ,,,,Průhledný fuzz,Gennemskinnelig fuzz,Transparent,Ημιδιαφανής θολούρα,Diafana lanugo,Difuminado Translúcido,,Läpikuultava sumennus,Bruit transparent,Áttetsző homály,Fuzz traslucido,半透明ファズ,반투명 퍼즈,Doorschijnende fuzz,Gjennomsiktig fuzz,Przezroczysty szum,Difuso translúcido,,Transparent,Прозрачный шум,Прозрачан фаз,Genomskinlig fuzz,Yarı saydam fuzz, +Noise,OPTVAL_NOISE,,,,Šum,Støj,Rauschen,Ήχος,Bruo,Ruido,,Kohina,Neige,Zaj,Rumore,ノイズ,노이즈,Lawaaierige fuzz,Støy,Huk,Ruído,,Zgomot,Шум,Звук,Buller,Gürültü, +Smooth Noise,OPTVAL_SMOOTHNOISE,,,,Hladký šum,Glat støj,Geglättetes Rauschen,Ομαλός ήχος,Glata Bruo,Ruido borroso,,Pehmeä kohina,Neige adoucie,Simított zaj,Rumore liscio,滑らかなノイズ,부드러운 노이즈,Gladde lawaaierige fuzz,Glatt støy,Wugładzony huk,Ruído suavizado,,Zgomot lin,Мягкий шум,Милозвучан звук,Slätt brus,Yumuşak Gürültü, +Jagged fuzz,OPTVAL_JAGGEDFUZZ,,,,Zubatý šum,Skarpt fuzz,Gezackt,Ζαρομένη θολούρα,Malglateca lanugo,Difuminado dentado,,Sahalaitainen sumennus,Neige rugeuse,Recés homály,Fuzz frastagliato,ギザギザ,들쭉날쭉한 퍼즈,Gekartelde fuzz,Takkete fuzz,Poszarpany szum,Difuso serrilhado,,Zimțat,Зазубренный шум,Назубљен фаз,Skarvig fuzz,Pürüzlü fuzz, +Green/Magenta,OPTVAL_GREENMAGENTA,,,,Zelená/purpurová,Grøn/Magenta,Grün/Magenta,Πράσινο/Magenta,Verda/Magenta,Verde/Magenta,,Vihreä/Magenta,Vert/Magenta,Zöld/Magenta,Verde/Magenta,緑/紫,초록/심홍색,Groen/Magenta,Grønn/magenta,Zielony/Magenta,Verde/Magenta,,Verde/Purpuriu,Зелёный/пурпурный,Зелен/Магента,Grön/Magenta,Yeşil/Macenta, +Red/Cyan,OPTVAL_REDCYAN,,,,Červená/tyrkysová,Rød/Cyan,Rot/Cyan,Κόκινο/Κυανό,Ruĝa/Cejana,Rojo/Cian,,Punainen/Sinivihreä,Rouge/Bleu,Piros/Türkiz,Rosso/Ciano,赤/空,빨강/하늘색,Rood/Cyaan,Rød/cyan,Czerwony/Błękitny,Vermelho/Ciano,,Roșu/Turcoaz,Красный/голубой,Црвен/Цијан,Röd/Cyan,Kırmızı/Mavi, +Amber/Blue,OPTVAL_AMBERBLUE,,,,Oranžová/modrá,Rav/blå,Orange/Blau,Amber/Μπλέ,Sukcenokolora/Blua,Ámbar/Azul,,Ruskeankeltainen/Sininen,Ambre/Bleu,Sárga/Kék,Ambra/Blu,黄/青,황토/파랑색,Amber/Blauw,Rav/blå,Bursztynowy/Niebieski,Âmbar/Azul,,Chihlimbar/Albastru,Янтарный/синий,Ћилибарски/Плаво,Bärnsten/blått,Kehribar/Mavi, +Left Eye,OPTVAL_LEFTEYE,,,,Levé oko,Venstre øje,Linkes Auge,Αριστερό μάτι,Maldekstra Okulo,Ojo izquierdo,,Vasen silmä,Oeil Gauche,Bal szem,Occhio sinistro,左目,왼쪽 눈,Linkeroog,Venstre øye,Lewe Oko,Olho Esquerdo,,Ochi Stâng,Левый глаз,Лево око,Vänster öga,Sol Göz, +Right Eye,OPTVAL_RIGHTEYE,,,,Pravé oko,Højre øje,Rechtes Auge,Δεξί μάτι,Dekstra Okulo,Ojo derecho,,Oikea silmä,Oeil Droit,Jobb szem,Occhio destro,右目,오른쪽 눈,Rechteroog,Høyre øye,Prawe Oko,Olho Direito,,Ochi drept,Правый глаз,Десно око,Höger öga,Sağ Göz, +Side-by-side Full,OPTVAL_SBSFULL,,,,"Vedle sebe, plné",Side ved side i fuld bredde,Nebeneinander volle Breite,,Flank-ĉe-flanka Tuta,Lado a lado completo,,Täysi rinnakkaisasettelu,Côte-â-côte Complet,Egymás melletti Teljes,Fianco a fianco completo,両サイド フル,크게 좌우배치,Zij-aan-zij Volledig,Side-ved-side Full,Pełne Obok Siebie,Lado a lado completo,,Una lângă alta Pline,"Бок о бок, полно",Раме уз раме цело,Sidoordnat fullt ut,Yan yana Tam, +Side-by-side Narrow,OPTVAL_SBSNARROW,,,,"Vedle sebe, úzké",Side ved side i halv bredde,Nebeneinander halbe Breite,,Flank-ĉe-flanka Mallarĝa,Lado a lado estrecho,,Kapea rinnakkaisasettelu,Côte-â-côte étroit,Egymás melletti Szűk,Fianco a fianco stretto,両サイド ナロー,좁게 좌우배치,Zij-aan-zij smal,Side ved side Smal,Wąskie Obok Siebie,Lado a lado estreito,,Una lângă alta Înguste,"Бок о бок, узко",Раме уз раме уско,Sidoväggar smal,Yan yana Dar, +Top/Bottom,OPTVAL_TOPBOTTOM,,,,Nad sebou,Øverst/underst,Übereinander,Πάνω/Κάτω,Supero/Subo,Superior/Inferior,,Ylä-/Alaosa,Dessus/Dessous,Fent/Lent,Sopra/Sotto,天/底,위/아래,Boven/onderkant,Topp/Bunn,Góra/Dół,Superior/Inferior,,Sus/Jos,Сверху/снизу,Врх/Дно,Överst/underst,Üst/Alt, +Row Interleaved,OPTVAL_ROWINTERLEAVED,,,,Po řádcích,Forskydning af rækker,Zeilenversetzt,,Vicoj interteksitaj,Fila intercalada,,Vaakalomitus,Entrelacement rangée,Sor beillesztés,Riga interfogliata,行インターリーブ,열 교차 배치,Rij interleaved,Rad sammenflettet,Przepleciony Szereg,Linha Intercalada,,Rând intercalat,Чередование строк,Редно прошарано,Rad med interfolierad rad,Satır Aralıklı, +Column Interleaved,OPTVAL_COLUMNINTERLEAVED,,,,Po sloupcích,Forskydning af kolonner,Spaltenversetzt,,Kolonoj interteksitaj,Columna intercalada,,Pystylomitus,Entralcement colonne,Oszlop beillesztés,Colonna interfogliata,列インターリーブ,세로줄 교차 배치,Kolom Interleaved,Kolonne sammenflettet,Przepleciona Kolumna,Coluna Intercalada,,Coloană intercalată,Чередование столбцов,Колонско прошарано,Kolumn interfolierad,Sütun Aralıklı, +Checkerboard,OPTVAL_CHECKERBOARD,,,,Šachovnice,Ternet,Schachbrettmuster,,Ŝaktablo,Tablero de damas,,Shakkilautakuvio,Damier,Tábla,Scacchiere,市松模様,체크무늬,Dambord,Sjakkbrett,Szachownica,Xadrez,,Tablă de Șah,Шахматная доска,Шаховска табла,Tärningsbräda,Dama Tahtası, +Quad-buffered,OPTVAL_QUADBUFFERED,,,,Quad buffer,Quad-buffered,Vierfachgepuffert,,Kvarobla bufro,Cuádruple búfer,,Neloispuskurointi,Quadruple-tampon,Négyszeresen bufferelt,Quad buffer,クワッドバッファー,쿼드 버퍼,Viervoudig gebufferd,Firebufret,Poczwórnie zbuforowane,Buffer quádruplo,,Împătrit,Четырёхкратный,Квад-унапређено,Kvadratbuffrad,Dört tamponlu, +TrueColor Options,DSPLYMNU_TCOPT,,,,Nastavení True color,TrueColor-indstillinger,TrueColor Optionen,TrueColor Ρυθμίσεις,Plenkolora Agordoj,Opciones TrueColor,,TrueColor-asetukset,Options TrueColor,TrueColor Beállítások,Opzioni TrueColor,トゥルーカラー オプション,트루 컬러 설정,TrueColor Opties,TrueColor-alternativer,Opcje TrueColor,Opções de TrueColor,,Setări Mod Culori Complete,Полноцветный режим,Подешавања правих боја,TrueColor-alternativ,TrueColor Seçenekleri, +TrueColor Options,TCMNU_TITLE,,,,Nastavení True color,TrueColor-indstillinger,TrueColor Optionen,TrueColor Ρυθμίσεις,Plenkolora Agordoj,Opciones TrueColor,,TrueColor-asetukset,Options TrueColor,TrueColor Beállítások,Opzioni TrueColor,トゥルーカラー オプション,트루 컬러 설정,TrueColor Opties,TrueColor-alternativer,Opcje TrueColor,Opções de TrueColor,,Setări Mod Culori Complete,Настройки полноцветности,Подешавања правих боја,TrueColor-alternativ,TrueColor Seçenekleri, +True color output,TCMNU_TRUECOLOR,,,,Výstup True color,TrueColor-udgang,TrueColor Ausgabe,TrueColor παραγωγή,Plenkolora eligo,Salida de True color,,True color -ulostulo,Sortie Truecolor,Truecolor Kimenet,Output true color,トゥルーカラー出力,트루 컬러 출력,Ware kleurenoutput,Ekte fargeutgang,Wyjście TrueColor,Saída de true color,,Putere Mod Culori Complete,Полноцветный вывод,Излаз правих боја,Utmatning i äkta färg,Gerçek renk çıkışı, +Linear filter when downscaling,TCMNU_MINFILTER,,,,Lineární filtrování při zmenšení,Lineært filter ved nedskalering,Linearer Filter beim Herunterskalieren,Γραμμικό φίλτρο για σμίκρυνση,Linia filtro kiam subskali,Filtro lineal por reducción,,Lineaarinen suodatin alas skaalatessa,Filtrage linéaire en réduction,Lineáris filterezés leméretezésnél,Filtro lineare per la riduzione,縮小時のリニアフィルター,축소시 선형 필터링함,Lineair filter voor downscaling,Lineært filter ved nedskalering,Liniowy filtr podczas zmniejszania rozmiaru,Filtro linear ao reduzir,,Filtru liniar la micșorare,Линейная фильтрация при уменьшении,Линеарни филтер током смањења,Linjärt filter vid nedskalning,Küçültme sırasında doğrusal filtre, +Linear filter when upscaling,TCMNU_MAGFILTER,,,,Lineární filtrování při zvětšení,Lineært filter ved opskalering,Linearer Filter beim Hochskalieren,Γραμμικό φίλτρο για πολυτέληση,Linia filtro kima superskali,Filtro lineal por escalado,,Lineaarinen suodatin ylös skaalatessa,Filtrage linéaire en agrandissement,Lineáris filterezés felméretezésnél,Filtro lineare per l'aumento,拡大時のリニアフィルター,확대시 선형 필터링함,Lineair filter voor upscaling,Lineært filter ved oppskalering,Liniowy filtr podczas zwiększania rozmiaru,Filtro linear ao aumentar,,Filtru liniar la mărire,Линейная фильтрация при увеличении,Линеарни филтер током повећања,Linjärt filter vid uppskalning,Yükseltme sırasında doğrusal filtre, +Use mipmapped textures,TCMNU_MIPMAP,,,,Použít mipmapy,Brug mipmapped teksturer,Benutze Textur-Mipmaps,Χρήση mipmapped υφών,Uzi mipmapajn teksturojn,Usar texturas con mipmap,,Käytä mipkartallisia pintakuviointeja,Utiliser textures mipmappées,Mipmap textúrák,Usa le texture mipmapped,ミップマップテクスチャを使用,밉맵 텍스쳐 사용,Gebruik mipmapped texturen,Bruk mipmapped teksturer,Użyj mipmapowane tekstury,Usar texturas com mipmapping,,Mip mapping pentru texturi,Применять MIP-текстурирование,Користи мипмаповане текстуре,Använd mipmappade texturer,Eşlenmiş dokular kullanın, +Dynamic lights (Software),TCMNU_DYNLIGHTS,,,,Dynamická světla (software),Dynamisk lys (software),Dynamisches Licht (Software),Δυναμικά φώτα (Λογισμικό),Dinamikaj lumoj (Programbildigilo),Luces dinámicas (Software),,Dynaamiset valot (ohjelmisto),Lumières Dynamiques (Software),Dinamikus fények (szoftveres),Luci Dinamiche (Software),ダイナミックライト (ソフトウェア),다이나믹 라이트 (소프트웨어 버전),Dynamische verlichting (software),Dynamiske lys (programvare),Dynamiczne Światło (Oprogramowanie),Luzes Dinâmicas (Software),,Lumini Dinamice (Mod Software),Динамическое освещение (программное),Динамичко осветљење (софтвер),Dynamiskt ljus (programvara),Dinamik ışıklar (Yazılım), +Option Search,OS_TITLE,,,,Vyhledávání možností,Mulighed Søg,Optionssuche,Αναζήτηση Ρυθμίσεων,Agorda Serĉo,Buscar Opciones,,Asetushaku,Recherche Option,Beállítás Keresés,Opzioni di ricerca,オプション検索,옵션 검색,Optie zoeken,Alternativt søk,Szukanie Opcji,Buscar opção,Procurar opção,Căutare Setări,Поиск настройки,Претрага,Alternativ Sök,Seçenek Arama, +Search for any term,OS_ANY,,,,Hledat jakékoli klíčové slovo,Søg efter et vilkårligt begreb,Suche nach beliebigem Begriff,Αναζήτηση για όποιαδηποτε λέξη,Serĉi por iu ajn termino,Buscar cualquier término,,Etsi mitä tahansa sanaa,N'importe quel mot,Bármilyen szótagra keresés,Cerca per ciascun termine,いずれかの用語を探す,용어 검색,Zoek naar eender welke term,Søk etter et vilkårlig begrep,Szukaj jakiegokolwiek wyrażenia,Buscar por qualquer termo,Procurar por um termo qualquer,Căutare după orice termen,Искать любое из слов,Тражи било коју од речи,Sök efter valfri term,Herhangi bir terim için arama yapın, +Search for all terms,OS_ALL,,,,Hledat všechna klíčová slova,Søg efter alle udtryk,Suche nach allen Begriffen,Αναζήτηση για όλες της λέξεις,Serĉi por ĉiuj terminoj,Buscar todos los términos,,Etsi kaikki sanat,Tous les mots,Összes szótagra keresés,Cerca per tutti i termini,全ての用語を探す,모든 조건 검색,Zoek naar alle termen,Søk etter alle termer,Szukaj wszystkich wyrażeń,Buscar por todos os termos,Procurar por todos os termos,Căutare după toți termenii,Искать все слова,Тражи све речи,Sök efter alla termer,Tüm terimler için arama yapın, +No results found.,OS_NO_RESULTS,,,,Nic nenalezeno.,Ingen resultater fundet.,Keine Resultate,Δέν βρέθηκαν αποτελέσματα,Neniuj rezultoj trovitaj.,Ningun resultado.,,Ei tuloksia.,Pas de résultat trouvé,Nincs keresési találat,Nessun risultato trovato.,見つかりませんでした。,검색 결과 없음.,Geen resultaten gevonden.,Ingen resultater funnet.,Brak wyników,Nenhum resultado encontrado.,,Niciun rezultat găsit.,Результаты не найдены.,Нема резултата.,Inga resultat hittades.,Sonuç bulunamadı., +Search:,OS_LABEL,,,,Hledat:,Søg:,Suche:,Αναζήτηση:,Serĉi:,Buscar:,,Etsi:,Recherche:,Keresés:,Trova:,検索:,검색:,Zoeken:,Søk:,Szukaj:,Busca:,Procura:,Căutare:,Поиск:,Претрага:,Sök:,Arama yapın:, +Always show keys,AUTOMAPMNU_SHOWKEYS_ALWAYS,,,,Vždy zobrazit klíče,Vis altid nøgler,Zeige immer alle Schlüssel,Εμφάνιση πλήκτρων πάντα,Ĉiam montri ŝlosilojn,Mostrar llaves siempre,,Aina näytä avaimet,Toujour afficher clés,Kulcsokat mindig mutat,Mostra sempre le chiavi,常にキーを表示,항상 키들을 표시,Toon altijd de toetsen,Vis alltid nøkler,Zawsze pokazuj klucze,Sempre mostrar chaves,Exibir chaves sempre,Afișează cheile în permanență,Всегда отображать ключи,Увек приказуј кључеве,Visa alltid nycklar,Her zaman anahtarları göster, +,,Newly added content,,,,,,,,,,,,,,,,,,,,,,,,,, +Team changing has been disabled!,TXT_NO_TEAM_CHANGE,,,,Změna týmu je vypnuta!,Holdskift er blevet deaktiveret!,Teamwechsel ist deaktiviert!,Η αλαγγή ομάδον απαγορεύεται!,Teamŝanĝiĝo estas malvalidigita!,¡El cambio de equipo ha sido desactivado!,,Joukkueen vaihtaminen on kytketty pois päältä!,Les changements d'équipe sont désactivés!,Csapatváltás letiltva,È stato disabilitato il cambio di squadra!,チームの変更は受け付けない!,팀 변경이 불가능해짐!,Teamwisseling is uitgeschakeld!,Lagbytte har blitt deaktivert!,Zmiana drużyn została wyłączona!,Troca de equipe foi desativada!,Troca de equipa foi desativada!,Schimbarea echipelor a fost dezactivată!,Смена команды была отключена!,Мењање тима је искључено!,Lagbyte har inaktiverats!,Takım değiştirme devre dışı bırakıldı!, +%s joined the %t team,TXT_JOINED_TEAM,%s is the player and gender sensitive,,,%s se připojil@[ao_cs] k týmu %t.,%s er blevet medlem af %t-team,%s is dem %t Team beigetreten.,@[art_gr] %s έγινε μέλος τής %t ομάδας,%s aliĝis al la %t teamo,%s se unió al equipo %t,,%s liittyi joukkueeseen %t,%s a rejoint l'équipe %t.,%s belépett a %t csapatba,%s entra nel team %t,%s は %t のチームに入隊した,%s 이(가) %s 팀에 합류함,%s zijn bij het %t team gekomen.,%s ble med i %t-teamet,%s dołącza do drużyny %t,%s entrou na equipe %t,,%s s-a alăturat echipei %t,Игрок %s присоединяется к команде %t,%s је уш@[ao_2_sr] у %t тим,%s anslöt sig till %t teamet.,%s %t takımına katıldı, +%s is now a loner.,TXT_LONER,,,,%s je teď @[self_cs].,%s er nu en enspænder.,%s ist jetzt ein@[e_de] Einzelgänger@[in_de].,@[art_gr] %s είναι τώρα μόνο/ς/η @[pro4_gr],%s nun estas solemulo.,%s es ahora solitari@[ao_esp].,,%s on nyt yksikseen.,%s joue maintenant tout seul.,%s immáron magányos útralépett,%s è da solo,%s は今 一匹狼だ。,%s 은(는) 혼자 남음.,%s is nu een eenling.,%s er nå en einstøing.,%s jest teraz sam@[ao_pl],%s está sozinh@[ao_ptb] agora.,,%s este singur acum,Игрок %s теперь одиночка.,%s је сада самотњак.,%s är nu en ensamvarg.,%s artık yalnız., %s left the game with %d frags,TXT_LEFTWITHFRAGS,,,,%s opustil@[ao_cs] hru s %d fragy,%s forlod spillet med %d frags,%s hat das Spiel mit %d Frags verlassen.,@[art_gr] %s έφυγε με %d κοματιασμόυς,%s eliris el la ludo kun %d ludmurdoj,%s salió de la partida con %d bajas,,%s poistui pelistä frägimäärällä %d,%s a quitté le jeu avec %d frags.,%s kilépett %d fraggel,%s ha lasciato il gioco con %d frag,"%s が逃げ出したので %d に点が入った -",%s 이(가) 게임에서 %d 의 점수를 기록하고 퇴장 함.,%s verliet het spel met %d frags,%s forlot spillet med %d frags,%s opuścił@[ao_pl] grę z %d fragami,%s saiu do jogo com %d frags,,%s a părăsit jocul cu %d victime,Игрок %s покидает игру с количеством фрагов: %d,%s је изаш@[ao_2_sr] из игре са %d фраговима.,%s oyunu %d frag ile terk etti -%s left the game,TXT_LEFTTHEGAME,,,,%s opustil@[ao_cs] hru,%s forlod spillet,%s hat das Spiel verlassen.,@[art_gr] %s έφυγε,%s eliris el la ludo,%s salió de la partida,,%s poistui pelistä,%s a quitté le jeu.,%s kilépett,%s ha lasciato il gioco,%s は退出した,%s 이(가) 게임을 떠남.,%s verliet het spel,%s forlot spillet,%s opuścił@[ao_pl] grę,%s saiu do jogo,,%s a părăsit jocul,Игрок %s покидает игру,%s је изаш@[ao_2_sr] из игре,%s oyundan ayrıldı -Could not read savegame '%s'.,TXT_COULDNOTREAD,,,,Nepodařilo se načíst uloženou hru '%s'.,Kunne ikke læse savegame '%s'.,Konnte Spielstand '%s' nicht lesen.,Το αρχείο αποθήκευσης %s δέν μπόρε να φορτωθεί,Ne povis legi la konservitan ludon '%s'.,No se pudo leer la partida guardada '%s'.,,Pelitallennetta '%s' ei voitu lukea.,Impossible de lire la sauvegarde '%s'.,A '%s' nem tölthető be.,Non si è potuto leggere il salvataggio '%s'.,%s' のセーブデータを読み込めなかった。,저장된 게임을 불러올 수 없습니다.'%s',Kon het savegame '%s' niet lezen.,Kunne ikke lese savegame '%s'.,Nie można odczytać zapisu „%s”.,"Não foi possível ler o jogo salvo ""%s"".","Não foi possível ler o jogo guardado ""%s"".",Salvarea '%s' nu a putut fi citită.,Невозможно прочитать сохранение: «%s».,Није могуће прочитати сачувану игру %s.,%s' kayıt oyunu okunamadı. +",%s 이(가) 게임에서 %d 의 점수를 기록하고 퇴장 함.,%s verliet het spel met %d frags,%s forlot spillet med %d frags,%s opuścił@[ao_pl] grę z %d fragami,%s saiu do jogo com %d frags,,%s a părăsit jocul cu %d victime,Игрок %s покидает игру с количеством фрагов: %d,%s је изаш@[ao_2_sr] из игре са %d фраговима.,%s lämnade spelet med %d frags,%s oyunu %d frag ile terk etti, +%s left the game,TXT_LEFTTHEGAME,,,,%s opustil@[ao_cs] hru,%s forlod spillet,%s hat das Spiel verlassen.,@[art_gr] %s έφυγε,%s eliris el la ludo,%s salió de la partida,,%s poistui pelistä,%s a quitté le jeu.,%s kilépett,%s ha lasciato il gioco,%s は退出した,%s 이(가) 게임을 떠남.,%s verliet het spel,%s forlot spillet,%s opuścił@[ao_pl] grę,%s saiu do jogo,,%s a părăsit jocul,Игрок %s покидает игру,%s је изаш@[ao_2_sr] из игре,%s har lämnat spelet.,%s oyundan ayrıldı, +Could not read savegame '%s'.,TXT_COULDNOTREAD,,,,Nepodařilo se načíst uloženou hru '%s'.,Kunne ikke læse savegame '%s'.,Konnte Spielstand '%s' nicht lesen.,Το αρχείο αποθήκευσης %s δέν μπόρε να φορτωθεί,Ne povis legi la konservitan ludon '%s'.,No se pudo leer la partida guardada '%s'.,,Pelitallennetta '%s' ei voitu lukea.,Impossible de lire la sauvegarde '%s'.,A '%s' nem tölthető be.,Non si è potuto leggere il salvataggio '%s'.,%s' のセーブデータを読み込めなかった。,저장된 게임을 불러올 수 없습니다.'%s',Kon het savegame '%s' niet lezen.,Kunne ikke lese savegame '%s'.,Nie można odczytać zapisu „%s”.,"Não foi possível ler o jogo salvo ""%s"".","Não foi possível ler o jogo guardado ""%s"".",Salvarea '%s' nu a putut fi citită.,Невозможно прочитать сохранение: «%s».,Није могуће прочитати сачувану игру %s.,"Kunde inte läsa sparspelet ""%s"".",%s' kayıt oyunu okunamadı., %s' is not a valid savegame: Missing 'info.json'.,TXT_NOINFOJSON,,,,%s' není funkční uloženou hrou: Chybí 'info.json'.,%s' er ikke et gyldigt savegame: Mangler 'info.json'.,%s' ist kein gültiger Spielstand. 'info.json' fehlt.,Το %s δεν είναι ένα έγκυρο αρχείο αποθήκευσης: Το info.json λείπει,%s' ne estas valida konservita ludo: Mankante 'info.json'.,%s' no es una partida guardada válida: Falta 'info.json'.,,%s' ei ole kelvollinen pelitallenne. Puuttuva 'info.json'.,%s n'est pas une sauvegarde valide. Fichier 'info.json' manquant.,%s' nem egy valós mentés: Hiányzó 'info.json'.,%s' non è un salvataggio valido: 'info.json' mancante.,%s' は有効なセーブデータ ではない: 'info.json'が不明。,%s' 는 유효하지 않습니다: 파일이 없습니다.'info.json',"%s"" is geen geldig savegame: Ontbreekt 'info.json'.",%s' er ikke et gyldig savegame: Mangler 'info.json'.,"„%s” nie jest prawidłowym zapisem gry: Brak „info.json” ","""%s"" não é um jogo salvo válido: Está faltando ""info.json"".","""%s"" não é um jogo gravado válido: Está faltando -""info.json"".",%s' nu este o salvare validă. Lipsește 'info.json',Сохранение «%s» некорректно: отсутствует «info.json».,%s није валидно сачувана игра: Недостаје „info.json“.,%s' geçerli bir kayıt oyunu değil: Eksik 'info.json'. -Failed to access savegame info in '%s'.,TXT_FAILEDTOREADSG,,,,Nepodařilo se načíst informace v uložené hře '%s'.,Det lykkedes ikke at få adgang til savegame info i '%s'.,Konnte Spielstandinfo in '%s' nicht lesen.,Η πρόσβαση πληροφοριών του αρχείου αποθήκευσης %s δέν ήταν επιτυχής,Malsukcesis aliri informon de la konservita ludo en '%s'.,Fallo al acceder a información de partida guardada en '%s'.,,Tiedoston '%s' pelitallennetietoihin ei päästy käsiksi.,Impossible d'accéder aux infos de sauvegarde dans le fichier '%s'.,A '%s' mentésben nem sikerült fellelni a mentésinfókat.,Accesso alle informazioni sul salvataggio in '%s' fallito.,%s' のセーブデータにアクセス出来なかった。,%s'의 저장된 게임 정보에 액세스 할 수 없습니다.,Geen toegang tot de opgeslagen informatie in '%s'.,Kunne ikke få tilgang til savegame-info i '%s'.,Nie udało się dostać informacji zapisu „%s”.,"Não foi possível acessar a informação do jogo salvo em ""%s"".","Não foi possível acessar a informação do jogo gravado em ""%s"".",Nu s-au putut accesa informațiile din salvarea '%s'.,Невозможно получить информацию из сохранения «%s».,Не успешно пристопљено инфу сачуване игре %s.,%s' içindeki kayıt oyunu bilgilerine erişilemedi. -Savegame '%s' is from an incompatible version.,TXT_INCOMPATIBLESG,,,,Uložená hra '%s' je z nekompatibilní verze.,Savegame '%s' er fra en inkompatibel version.,Spielstand '%s' ist von einer inkompatiblen Version.,Το αρχείο αποθήκευσης %s είναι απο μια ασύμβατη έκδοση,Konservita ludo '%s' estas el nekongrua versio.,La partida guardada '%s' es de una versión no compatible.,,Pelitallenne '%s' on yhteensopimattomasta versiosta.,La sauvegarde '%s' vient d'une version incompatible.,A '%s' mentés egy nem kompatibilis verzió mentése.,Il salvataggio '%s' proviene da una versione incompatibile.,%s' は互換性の無いバージョンのセーブデータだ。,저장된 게임'%s'은(는) 호환되지 않는 버전입니다.,Savegame '%s' komt uit een incompatibele versie.,Savegame '%s' er fra en inkompatibel versjon.,Zapis gry „%s” jest z niekompatybilnej wersji.,"O jogo salvo ""%s"" é de uma versão incompatível.","O jogo gravado ""%s"" é de uma versão incompatível.",Salvarea '%s' este dintr-o versiune incompatibilă.,Сохранение «%s» из несовместимой версии порта.,Сачувана игра %s је из инкомпетабилне верзије.,%s' kayıt oyunu uyumsuz bir sürüme ait. -Savegame '%s' is from another ZDoom-based engine:,TXT_OTHERENGINESG,,,,Uložená hra '%s' je z jiného enginu založeného na ZDoomu:,Savegame '%s' er fra en anden ZDoom-baseret engine:,Spielstand '%s' ist von einer anderen ZDoom-basierten Engine:,Το αρχείο αποθήκευσης %s είναι απο μια άλλη ZDoom βασισμένη μηχανή,Konservita ludo '%s' estas el alia ZDoom-bazita modulo:,La partida guardada '%s' es de otro motor basado en ZDoom:,,Pelitallenne '%s' on toisesta ZDoom-pohjaisesta moottorista.,La sauvegarde '%s' vient d'un autre moteur basé sur ZDoom:,A '%s' mentés egy másik ZDoom motorhoz való:,Il salvataggio '%s' proviene da un altro motore basato su ZDoom:,%s' は別のZDoom型のセーブデータだ。,저장된 게임 '%s'은(는) 다른 Z둠 기반 엔진입니다:,Savegame '%s' is van een andere ZDoom-gebaseerde engine:,Savegame '%s' er fra en annen ZDoom-basert engine:,Zapis gry „%s” jest z innego silnika bazowanego na ZDoomie:,"O jogo salvo ""%s"" é de outra engine baseada em ZDoom:","O jogo gravado ""%s"" é de outro motor baseado em ZDoom:",Salvarea '%s' este dintr-un alt motor care are ca bază ZDoom:,"Сохранение «%s» из другого, основанного на ZDoom, движка:",Сачувана игра %s је из други ZDoom-базиран енџин:,%s' kayıt oyunu başka bir ZDoom tabanlı motordan: -Savegame '%s' is from an older version: %d (%e is the oldest supported),TXT_TOOOLDSG,,,,Uložená hra '%s' je ze starší verze: %d (%e je nejstarší podporovaná verze),Savegame '%s' er fra en ældre version: %d (%e er den ældste understøttede version),Spielstand '%s' ist von einer älteren Version: %s (%e ist die älteste noch unterstützte Version,Το αρχείο αποθήκευσης %s είναι απο την %d έκδοση (H %e είναι η παλιότερη υποστηριζώμενη),Konservita ludo '%s' estas el pli malnova versio: %d (%e estas la plej malnova subtenata),La partida guardada '%s' es de una versión anterior: %d (%e es la más anterior soportada),,Pelitallenne '%s' on vanhemmasta versiosta: %d (%e on vanhin tuettu versio),La sauvegarde '%s' vient d'une version obsolète: %d (%e est la plus ancienne supportée.),A '%s' mentés egy túl régi verzióhoz való: %d (%e a legfrissebb támogatott verzió),Il salvataggio '%s' proviene da una versione precedente: %d (%e è la più vecchia supportata),%s' はバージョンが合わないセーブデータだ: %d(%e は旧式版の物),저장된 게임'%s'은(는) 구 버전입니다: %d (%e 이 지원되는 버전 중 가장 오래된 버전),Savegame '%s' is van een oudere versie: %d (%e is de oudste ondersteunde versie).,Savegame '%s' er fra en eldre versjon: %d (%e er den eldste som støttes).,Zapis gry „%s” jest ze starszej wersji: %d (%e jest najstarszą wspieraną),"O jogo salvo ""%s"" é de uma versão mais antiga: %d (%e sendo a mais antiga suportada)","O jogo gravado ""%s"" é de uma versão mais antiga: %d (%e sendo a mais antiga suportada)",Salvarea '%s' este dintr-o versiune mai veche: %d (%e e cea mai veche suportată),Сохранение «%s» из старой версии: %d (%e — последняя совместимая).,Сачувана игра „%s“ је из старије верзије: %d (%e је најстарија подржана),%s' kayıt oyunu daha eski bir sürümden: %d (%e desteklenen en eski sürümdür) -Savegame '%s' is from an newer version: %d (%e is the highest supported),TXT_TOONEWSG,"Shouldn’t this say “%e is the newest supported”? +""info.json"".",%s' nu este o salvare validă. Lipsește 'info.json',Сохранение «%s» некорректно: отсутствует «info.json».,%s није валидно сачувана игра: Недостаје „info.json“.,"%s' är inte ett giltigt sparspel: Saknar ""info.json"".",%s' geçerli bir kayıt oyunu değil: Eksik 'info.json'., +Failed to access savegame info in '%s'.,TXT_FAILEDTOREADSG,,,,Nepodařilo se načíst informace v uložené hře '%s'.,Det lykkedes ikke at få adgang til savegame info i '%s'.,Konnte Spielstandinfo in '%s' nicht lesen.,Η πρόσβαση πληροφοριών του αρχείου αποθήκευσης %s δέν ήταν επιτυχής,Malsukcesis aliri informon de la konservita ludo en '%s'.,Fallo al acceder a información de partida guardada en '%s'.,,Tiedoston '%s' pelitallennetietoihin ei päästy käsiksi.,Impossible d'accéder aux infos de sauvegarde dans le fichier '%s'.,A '%s' mentésben nem sikerült fellelni a mentésinfókat.,Accesso alle informazioni sul salvataggio in '%s' fallito.,%s' のセーブデータにアクセス出来なかった。,%s'의 저장된 게임 정보에 액세스 할 수 없습니다.,Geen toegang tot de opgeslagen informatie in '%s'.,Kunne ikke få tilgang til savegame-info i '%s'.,Nie udało się dostać informacji zapisu „%s”.,"Não foi possível acessar a informação do jogo salvo em ""%s"".","Não foi possível acessar a informação do jogo gravado em ""%s"".",Nu s-au putut accesa informațiile din salvarea '%s'.,Невозможно получить информацию из сохранения «%s».,Не успешно пристопљено инфу сачуване игре %s.,"Misslyckades med att få tillgång till information om sparspelet i ""%s"".",%s' içindeki kayıt oyunu bilgilerine erişilemedi., +Savegame '%s' is from an incompatible version.,TXT_INCOMPATIBLESG,,,,Uložená hra '%s' je z nekompatibilní verze.,Savegame '%s' er fra en inkompatibel version.,Spielstand '%s' ist von einer inkompatiblen Version.,Το αρχείο αποθήκευσης %s είναι απο μια ασύμβατη έκδοση,Konservita ludo '%s' estas el nekongrua versio.,La partida guardada '%s' es de una versión no compatible.,,Pelitallenne '%s' on yhteensopimattomasta versiosta.,La sauvegarde '%s' vient d'une version incompatible.,A '%s' mentés egy nem kompatibilis verzió mentése.,Il salvataggio '%s' proviene da una versione incompatibile.,%s' は互換性の無いバージョンのセーブデータだ。,저장된 게임'%s'은(는) 호환되지 않는 버전입니다.,Savegame '%s' komt uit een incompatibele versie.,Savegame '%s' er fra en inkompatibel versjon.,Zapis gry „%s” jest z niekompatybilnej wersji.,"O jogo salvo ""%s"" é de uma versão incompatível.","O jogo gravado ""%s"" é de uma versão incompatível.",Salvarea '%s' este dintr-o versiune incompatibilă.,Сохранение «%s» из несовместимой версии порта.,Сачувана игра %s је из инкомпетабилне верзије.,"Sparfil ""%s"" är från en inkompatibel version.",%s' kayıt oyunu uyumsuz bir sürüme ait., +Savegame '%s' is from another ZDoom-based engine:,TXT_OTHERENGINESG,,,,Uložená hra '%s' je z jiného enginu založeného na ZDoomu:,Savegame '%s' er fra en anden ZDoom-baseret engine:,Spielstand '%s' ist von einer anderen ZDoom-basierten Engine:,Το αρχείο αποθήκευσης %s είναι απο μια άλλη ZDoom βασισμένη μηχανή,Konservita ludo '%s' estas el alia ZDoom-bazita modulo:,La partida guardada '%s' es de otro motor basado en ZDoom:,,Pelitallenne '%s' on toisesta ZDoom-pohjaisesta moottorista.,La sauvegarde '%s' vient d'un autre moteur basé sur ZDoom:,A '%s' mentés egy másik ZDoom motorhoz való:,Il salvataggio '%s' proviene da un altro motore basato su ZDoom:,%s' は別のZDoom型のセーブデータだ。,저장된 게임 '%s'은(는) 다른 Z둠 기반 엔진입니다:,Savegame '%s' is van een andere ZDoom-gebaseerde engine:,Savegame '%s' er fra en annen ZDoom-basert engine:,Zapis gry „%s” jest z innego silnika bazowanego na ZDoomie:,"O jogo salvo ""%s"" é de outra engine baseada em ZDoom:","O jogo gravado ""%s"" é de outro motor baseado em ZDoom:",Salvarea '%s' este dintr-un alt motor care are ca bază ZDoom:,"Сохранение «%s» из другого, основанного на ZDoom, движка:",Сачувана игра %s је из други ZDoom-базиран енџин:,"Sparfil ""%s"" är från en annan ZDoom-baserad motor:",%s' kayıt oyunu başka bir ZDoom tabanlı motordan:, +Savegame '%s' is from an older version: %d (%e is the oldest supported),TXT_TOOOLDSG,,,,Uložená hra '%s' je ze starší verze: %d (%e je nejstarší podporovaná verze),Savegame '%s' er fra en ældre version: %d (%e er den ældste understøttede version),Spielstand '%s' ist von einer älteren Version: %s (%e ist die älteste noch unterstützte Version,Το αρχείο αποθήκευσης %s είναι απο την %d έκδοση (H %e είναι η παλιότερη υποστηριζώμενη),Konservita ludo '%s' estas el pli malnova versio: %d (%e estas la plej malnova subtenata),La partida guardada '%s' es de una versión anterior: %d (%e es la más anterior soportada),,Pelitallenne '%s' on vanhemmasta versiosta: %d (%e on vanhin tuettu versio),La sauvegarde '%s' vient d'une version obsolète: %d (%e est la plus ancienne supportée.),A '%s' mentés egy túl régi verzióhoz való: %d (%e a legfrissebb támogatott verzió),Il salvataggio '%s' proviene da una versione precedente: %d (%e è la più vecchia supportata),%s' はバージョンが合わないセーブデータだ: %d(%e は旧式版の物),저장된 게임'%s'은(는) 구 버전입니다: %d (%e 이 지원되는 버전 중 가장 오래된 버전),Savegame '%s' is van een oudere versie: %d (%e is de oudste ondersteunde versie).,Savegame '%s' er fra en eldre versjon: %d (%e er den eldste som støttes).,Zapis gry „%s” jest ze starszej wersji: %d (%e jest najstarszą wspieraną),"O jogo salvo ""%s"" é de uma versão mais antiga: %d (%e sendo a mais antiga suportada)","O jogo gravado ""%s"" é de uma versão mais antiga: %d (%e sendo a mais antiga suportada)",Salvarea '%s' este dintr-o versiune mai veche: %d (%e e cea mai veche suportată),Сохранение «%s» из старой версии: %d (%e — последняя совместимая).,Сачувана игра „%s“ је из старије верзије: %d (%e је најстарија подржана),"Sparfil ""%s"" är från en äldre version: %d (%e är den äldsta versionen som stöds).",%s' kayıt oyunu daha eski bir sürümden: %d (%e desteklenen en eski sürümdür), +Savegame '%s' is from a newer version: %d (%e is the highest supported),TXT_TOONEWSG,"Shouldn’t this say “%e is the newest supported”? — Undead -Ask Randi: The text is old. I won't change it.",,,Uložená hra '%s' je z novější verze: %d (%e je nejvyšší podporovaná verze),Savegame '%s' er fra en nyere version: %d (%e er den højest understøttede),Spielstand '%s' ist von einer neueren Version: %s (%e ist die neueste noch unterstützte Version,Το αρχείο αποθήκευσης %s είναι απο μια πιο καινούρια έκδοση: %d (Η %e είναι η πιο καινούρια που υποστηρίζεται),Konservita ludo '%s' estas el pli nova versio: %d (%e estas la plej nova subtenata),La partida guardada '%s' es de una versión posterior: %d (%e es la más alta soportada),,Pelitallenne '%s' on uudemmasta versiosta: %d (%e on korkein tuettu versio),La sauvegarde '%s' vient d'une version plus récente: %d (%e est la plus récente supportée.),A '%s' mentés egy túl új verzióhoz való: %d (%e a legkorábbi támogatott verzió),Il salvataggio '%s' proviene da una versione recente: %d (%e è la più recente supportata),%s' はバージョンが合わないセーブデータだ: %d(%e は最新版の物),저장된 게임'%s'은(는) 새 버전입니다: %d (%e 이 지원되는 버전 중 가장 최근 버전),Savegame '%s' is van een nieuwere versie: %d (%e is de hoogst ondersteunde versie).,Savegame '%s' er fra en nyere versjon: %d (%e er den høyeste versjonen som støttes).,Zapis gry „%s” jest z nowszej wersji: %d (%e jest najwyższą wspieraną),"O jogo salvo ""%s"" é de uma versão mais nova: %d (%e sendo a mais recente suportada)","O jogo gravado ""%s"" é de uma versão mais nova: %d (%e sendo a mais recente suportada)",Salvarea '%s' e dintr-o versiune mai nouă: %d (%e este cea mai nouă suportată),Сохранение «%s» из новой версии: %d (%e — последняя совместимая).,Сачувана игра „%s“ је из новије верзије: %d (%e је најновија подржана),%s' kayıt oyunu daha yeni bir sürümden: %d (%e desteklenen en yüksek sürümdür) -Savegame '%s' is missing the current map.,TXT_NOMAPSG,,,,Uložená hra '%s' neobsahuje současný level.,Savegame '%s' mangler det aktuelle kort.,Spielstand '%s' hat keine Information über den alktuellen Level.,Το αρχείο αποθήκευσης %s δέν έχει την τωρινή πίστα,Al la konservita ludo '%s' mankas la nuna mapo.,La partida guardada '%s' carece del mapa actual.,,Pelitallenteesta '%s' puuttuu nykyinen taso.,La sauvegarde '%s' ne contient pas la carte actuelle.,A '%s' mentés hiányolja a jelenlegi pályát.,Il salvataggio '%s' non contiene la mappa corrente.,セーブデータ '%s'に現在のマップはない。,저장된 게임 '%s'에 현재 맵이 없습니다.,Savegame '%s' mist de huidige kaart.,Savegame '%s' mangler det gjeldende kartet.,W zapisie gry „%s” brakuje obecnej mapy.,"O jogo salvo ""%s"" não possui o mapa atual.","O jogo gravado ""%s"" não possui o mapa atual.",Salvării '%s' îi lipsește harta actuală.,В сохранении «%s» отсутствует текущая карта.,Сачувана игри „%s“ недостаје тренутна мапа.,%s' kayıt oyununda geçerli harita eksik. +Ask Randi: The text is old. I won't change it.",,,Uložená hra '%s' je z novější verze: %d (%e je nejvyšší podporovaná verze),Savegame '%s' er fra en nyere version: %d (%e er den højest understøttede),Spielstand '%s' ist von einer neueren Version: %s (%e ist die neueste noch unterstützte Version,Το αρχείο αποθήκευσης %s είναι απο μια πιο καινούρια έκδοση: %d (Η %e είναι η πιο καινούρια που υποστηρίζεται),Konservita ludo '%s' estas el pli nova versio: %d (%e estas la plej nova subtenata),La partida guardada '%s' es de una versión posterior: %d (%e es la más alta soportada),,Pelitallenne '%s' on uudemmasta versiosta: %d (%e on korkein tuettu versio),La sauvegarde '%s' vient d'une version plus récente: %d (%e est la plus récente supportée.),A '%s' mentés egy túl új verzióhoz való: %d (%e a legkorábbi támogatott verzió),Il salvataggio '%s' proviene da una versione recente: %d (%e è la più recente supportata),%s' はバージョンが合わないセーブデータだ: %d(%e は最新版の物),저장된 게임'%s'은(는) 새 버전입니다: %d (%e 이 지원되는 버전 중 가장 최근 버전),Savegame '%s' is van een nieuwere versie: %d (%e is de hoogst ondersteunde versie).,Savegame '%s' er fra en nyere versjon: %d (%e er den høyeste versjonen som støttes).,Zapis gry „%s” jest z nowszej wersji: %d (%e jest najwyższą wspieraną),"O jogo salvo ""%s"" é de uma versão mais nova: %d (%e sendo a mais recente suportada)","O jogo gravado ""%s"" é de uma versão mais nova: %d (%e sendo a mais recente suportada)",Salvarea '%s' e dintr-o versiune mai nouă: %d (%e este cea mai nouă suportată),Сохранение «%s» из новой версии: %d (%e — последняя совместимая).,Сачувана игра „%s“ је из новије верзије: %d (%e је најновија подржана),"Sparfil ""%s"" är från en nyare version: %d (%e är den högsta versionen som stöds).",%s' kayıt oyunu daha yeni bir sürümden: %d (%e desteklenen en yüksek sürümdür), +Savegame '%s' is missing the current map.,TXT_NOMAPSG,,,,Uložená hra '%s' neobsahuje současný level.,Savegame '%s' mangler det aktuelle kort.,Spielstand '%s' hat keine Information über den alktuellen Level.,Το αρχείο αποθήκευσης %s δέν έχει την τωρινή πίστα,Al la konservita ludo '%s' mankas la nuna mapo.,La partida guardada '%s' carece del mapa actual.,,Pelitallenteesta '%s' puuttuu nykyinen taso.,La sauvegarde '%s' ne contient pas la carte actuelle.,A '%s' mentés hiányolja a jelenlegi pályát.,Il salvataggio '%s' non contiene la mappa corrente.,セーブデータ '%s'に現在のマップはない。,저장된 게임 '%s'에 현재 맵이 없습니다.,Savegame '%s' mist de huidige kaart.,Savegame '%s' mangler det gjeldende kartet.,W zapisie gry „%s” brakuje obecnej mapy.,"O jogo salvo ""%s"" não possui o mapa atual.","O jogo gravado ""%s"" não possui o mapa atual.",Salvării '%s' îi lipsește harta actuală.,В сохранении «%s» отсутствует текущая карта.,Сачувана игри „%s“ недостаје тренутна мапа.,"Sparfil ""%s"" saknar den aktuella kartan.",%s' kayıt oyununda geçerli harita eksik., %s' is not a valid savegame: Missing 'globals.json'.,TXT_NOGLOBALSJSON,,,,%s' není funkční uloženou hrou: Chybí 'globals.json'.,%s' er ikke et gyldigt savegame: Mangler 'globals.json'.,%s' ist kein gültiger Spielstand. 'globals.json' fehlt.,Το %s δεν είναι ένα έγκυρο αρχείο αποθήκευσης: Το globals.json λείπει,%s' ne estas valida konservita ludo: Mankante 'globals.json'.,%s' no es una partida guardada válida: Falta 'globals.json'.,,%s' ei ole kelvollinen pelitallenne. Puuttuva 'globals.json'.,%s n'est pas une sauvegarde valide. Fichier 'global.json' manquant.,A '%s' nem valós mentés: Hiányzó 'globals.json'.,%s' non è un salvataggio valido: 'globals.json' mancante.,%s' は有効なセーブデータではない: 'globals.json'が不明。,%s' 는 유효하지 않습니다: 파일이 없습니다.'globals.json',%s' is geen geldig savegame: Ontbrekende 'globals.json'.,%s' er ikke et gyldig lagringsspill: Mangler 'globals.json'.,„%s” nie jest prawidłowym zapisem gry: Brak „globals.json”,"""%s"" não é um jogo salvo válido: Está faltando ""globals.json"".","""%s"" não é um jogo gravado válido: Está faltando -""globals.json"".",%s nu este o salvare validă. Lipsește 'globals.json'.,Сохранение «%s» некорректно: отсутствует «globals.json».,%s није валидно сачувана игра: Недостаје „globals.json“.,%s' geçerli bir kayıt oyunu değil: Eksik 'globals.json'. -Failed to access savegame info in '%s',TXT_SGINFOERR,,,,Nepodařilo se načíst informace v uložené hře '%s'.,Fejlslagen adgang til savegame info i '%s',Konnte Spielstandinformationen von '%s' nicht lesen.,Η πρόσβαση πληροφοριών του αρχείου αποθήκευσης %s δέν ήταν επιτυχής,Malsukcesis aliri informon de la konservita ludo en '%s',Fallo al acceder a información de partida guardada en '%s'.,,Tiedoston '%s' pelitallennetietoihin ei päästy käsiksi.,Impossible d'accéder aux infos de sauvegarde dans le fichier '%s'.,A '%s' -ban nem található mentési információ.,Accesso alle informazioni sul salvataggio in '%s' fallito,%s' のセーブデータにアクセス出来なかった,%s'의 저장된 게임 정보에 액세스 할 수 없습니다.,Geen toegang tot savegame info in '%s'.,Kunne ikke få tilgang til lagringsinformasjon i '%s'.,Nie udało się dostać informacji zapisu „%s”.,"Não foi possível acessar a informação do jogo salvo em ""%s"".","Não foi possível acessar a informação do jogo gravado em ""%s"".",Informațiile salvării '%s' nu au putut fi accesate,Невозможно получить информацию из сохранения «%s».,Не успешно приступљено саучуваној игри у %s,%s' içindeki savegame bilgisine erişilemedi -A game save is still pending.,TXT_SAVEPENDING,,,,Stále se čeká na uložení hry.,Et spilopbevaringsspil venter stadig på at blive gemt.,Das Speichern eines Spielstandes steht noch aus.,Μια αποθήκευση παιχνιδίου είναι ακόμα σε αναμονή,Konservita ludo ankoraŭ estas pritraktata.,Un guardado de partida aún está pendiente.,,Pelin tallennus on vielä kesken.,Une sauvegarde est déjà en cours.,A mentés folyamatban.,Un salvataggio di gioco è ancora in corso.,セーブ中だ,게임 저장이 아직 보류 중입니다.,Een spel opslaan is nog steeds in behandeling.,En spilloppdatering venter fortsatt.,Zapis gry jest wciąż w toku.,Jogo salvo ainda pendente.,Jogo gravado ainda pendente.,O salvare este încă în așteptare.,Сохранение в очереди.,Сачувана игра идаље чека,Bir oyun kaydı hala beklemede. -Not in a saveable game.,TXT_NOTSAVEABLE,,,,Nejsi v uložitelné hře.,"Ikke i et spil, der kan gemmes.",Kein speicherbares Spiel aktiv.,Δέν είσαι σε ένα παιχνίδει που μπορεί να αποθηκευτεί,Ne estas en konservebla ludo.,No en una partida guardable.,,Ei tallennettavassa pelissä.,Vous n'êtes pas dans une partie sauvegardable.,Nem menthető játék.,Non è in un gioco salvabile.,セーブ可能なゲームではない,저장 가능한 게임에선 불가능 합니다.,Geen opslagbaar spel actief.,Ikke i et spill som kan lagres.,Nie w grze do zapisywania.,Não está em uma partida salvável.,Não estás numa partida que possa ser gravada.,Nu ești într-un joc în care poți salva.,Не в сохранимой игре.,Није у сачувајућој игри,Kaydedilebilir bir oyunda değil. -Not in a level,TXT_NOTINLEVEL,,,,Nejsi v levelu.,Ikke i en kort,Nicht in einem Level.,Δέν ε'ισαι σε μια πίστα,Ne estas en nivelo,No en un nivel,,Ei tasossa,Vous n'êtes pas dans un niveau.,Nem menthető pályán van.,Non è in un livello,レベル内ではない,레벨 안에선 불가능 합니다.,Niet in een level,Ikke i et nivå,Nie w poziomie.,Não está em uma fase.,Não estás em nenhum nível.,Nu ești în niciun nivel,Не на уровне,Није у нивоу,Bir seviyede değil -Player is dead in a single-player game,TXT_SPPLAYERDEAD,,,,Hráč je mrtvý v singleplayer hře.,Spilleren er død i et single-player spil,Spieler ist tot in einem Einzelspieler-Spiel.,Ο παίχτης έιναι νεκρός σε ένα singleplayer παιχνίδι,Ludanto estas mortinta en sol-ludanta ludado,Jugador muerto en partida de un solo jugador,,Pelaaja on kuollut yksinpelissä,Le joueur est mort en mode solo.,Játékos meghalt egy egyjátékos módban.,Il giocatore è morto in un gioco single player,シングルプレイでプレイヤーが死んだ,플레이어가 싱글 플레이 게임에서 죽었습니다.,Speler is dood in een een-speler spel,Spilleren er død i et enspiller-spill,Gracz jest martwy w grze dla jednego gracza,Jogador está morto em partida single player.,Jogador está morto numa partida single player.,Jucătorul este mort într-un joc single-player,Игрок мёртв в одиночной игре,Играч је мртав у сингл-плејер игри,Oyuncu tek oyunculu bir oyunda öldü -Save failed,TXT_SAVEFAILED,,,,Uložení se nezdařilo.,Save mislykkedes,Speichern fehlgeschlagen.,Η αποθήκευση απέτυχε,Konservo malsukcesis,Guardado fallido,,Tallennus epäonnistui,La sauvegarde à échoué.,Mentés meghiusult,Salvataggio fallito,セーブに失敗した。,저장 실패,Opslaan mislukt,Lagring mislyktes,Nie udało się zapisać,Falha ao salvar,Falha ao gravar,Salvare eșuată,Ошибка сохранения игры,Сачување није успело,Kaydetme başarısız -Could not create screenshot.,TXT_SCREENSHOTERR,,,,Nepodařilo se pořídit snímek obrazovky.,Kunne ikke oprette et skærmbillede.,Konnte Screenshot nicht erzeugen.,Ένα screenshot δέν μπόρεσε να τραβυχτεί,Ne povis krei ekrankopion.,No se pudo crear captura de pantalla.,,Ei voitu ottaa kuvakaappausta.,La capture d'écran à échoué.,Képernyőmentés meghiusult,Non è stato possibile effettuare la cattura dello schermo.,スクリーンショットを作成できなかった。,스크린샷을 만들 수 없음.,Kon geen screenshot maken.,Kunne ikke opprette skjermbilde.,Nie można zrobić zrzutu ekranu.,Não foi possível capturar a tela.,Não foi possível capturar ecrã,Captura de ecran nu a putut fi creată.,Ошибка создания снимка экрана.,Није успело направити снимак екрана.,Ekran görüntüsü oluşturulamadı. +""globals.json"".",%s nu este o salvare validă. Lipsește 'globals.json'.,Сохранение «%s» некорректно: отсутствует «globals.json».,%s није валидно сачувана игра: Недостаје „globals.json“.,"%s"" är inte ett giltigt sparfil: Saknar ""globals.json"".",%s' geçerli bir kayıt oyunu değil: Eksik 'globals.json'., +Failed to access savegame info in '%s',TXT_SGINFOERR,,,,Nepodařilo se načíst informace v uložené hře '%s'.,Fejlslagen adgang til savegame info i '%s',Konnte Spielstandinformationen von '%s' nicht lesen.,Η πρόσβαση πληροφοριών του αρχείου αποθήκευσης %s δέν ήταν επιτυχής,Malsukcesis aliri informon de la konservita ludo en '%s',Fallo al acceder a información de partida guardada en '%s'.,,Tiedoston '%s' pelitallennetietoihin ei päästy käsiksi.,Impossible d'accéder aux infos de sauvegarde dans le fichier '%s'.,A '%s' -ban nem található mentési információ.,Accesso alle informazioni sul salvataggio in '%s' fallito,%s' のセーブデータにアクセス出来なかった,%s'의 저장된 게임 정보에 액세스 할 수 없습니다.,Geen toegang tot savegame info in '%s'.,Kunne ikke få tilgang til lagringsinformasjon i '%s'.,Nie udało się dostać informacji zapisu „%s”.,"Não foi possível acessar a informação do jogo salvo em ""%s"".","Não foi possível acessar a informação do jogo gravado em ""%s"".",Informațiile salvării '%s' nu au putut fi accesate,Невозможно получить информацию из сохранения «%s».,Не успешно приступљено саучуваној игри у %s,"Misslyckades med att få tillgång till information om sparfilet i ""%s"".",%s' içindeki savegame bilgisine erişilemedi, +A game save is still pending.,TXT_SAVEPENDING,,,,Stále se čeká na uložení hry.,Et spilopbevaringsspil venter stadig på at blive gemt.,Das Speichern eines Spielstandes steht noch aus.,Μια αποθήκευση παιχνιδίου είναι ακόμα σε αναμονή,Konservita ludo ankoraŭ estas pritraktata.,Un guardado de partida aún está pendiente.,,Pelin tallennus on vielä kesken.,Une sauvegarde est déjà en cours.,A mentés folyamatban.,Un salvataggio di gioco è ancora in corso.,セーブ中だ,게임 저장이 아직 보류 중입니다.,Een spel opslaan is nog steeds in behandeling.,En spilloppdatering venter fortsatt.,Zapis gry jest wciąż w toku.,Jogo salvo ainda pendente.,Jogo gravado ainda pendente.,O salvare este încă în așteptare.,Сохранение в очереди.,Сачувана игра идаље чека,Ett sparande av spelet väntar fortfarande.,Bir oyun kaydı hala beklemede., +Not in a saveable game.,TXT_NOTSAVEABLE,,,,Nejsi v uložitelné hře.,"Ikke i et spil, der kan gemmes.",Kein speicherbares Spiel aktiv.,Δέν είσαι σε ένα παιχνίδει που μπορεί να αποθηκευτεί,Ne estas en konservebla ludo.,No en una partida guardable.,,Ei tallennettavassa pelissä.,Vous n'êtes pas dans une partie sauvegardable.,Nem menthető játék.,Non è in un gioco salvabile.,セーブ可能なゲームではない,저장 가능한 게임에선 불가능 합니다.,Geen opslagbaar spel actief.,Ikke i et spill som kan lagres.,Nie w grze do zapisywania.,Não está em uma partida salvável.,Não estás numa partida que possa ser gravada.,Nu ești într-un joc în care poți salva.,Не в сохранимой игре.,Није у сачувајућој игри,Inte i ett spel som kan sparas.,Kaydedilebilir bir oyunda değil., +Not in a level,TXT_NOTINLEVEL,,,,Nejsi v levelu.,Ikke i en kort,Nicht in einem Level.,Δέν ε'ισαι σε μια πίστα,Ne estas en nivelo,No en un nivel,,Ei tasossa,Vous n'êtes pas dans un niveau.,Nem menthető pályán van.,Non è in un livello,レベル内ではない,레벨 안에선 불가능 합니다.,Niet in een level,Ikke i et nivå,Nie w poziomie.,Não está em uma fase.,Não estás em nenhum nível.,Nu ești în niciun nivel,Не на уровне,Није у нивоу,Inte i en nivå.,Bir seviyede değil, +Player is dead in a single-player game,TXT_SPPLAYERDEAD,,,,Hráč je mrtvý v singleplayer hře.,Spilleren er død i et single-player spil,Spieler ist tot in einem Einzelspieler-Spiel.,Ο παίχτης έιναι νεκρός σε ένα singleplayer παιχνίδι,Ludanto estas mortinta en sol-ludanta ludado,Jugador muerto en partida de un solo jugador,,Pelaaja on kuollut yksinpelissä,Le joueur est mort en mode solo.,Játékos meghalt egy egyjátékos módban.,Il giocatore è morto in un gioco single player,シングルプレイでプレイヤーが死んだ,플레이어가 싱글 플레이 게임에서 죽었습니다.,Speler is dood in een een-speler spel,Spilleren er død i et enspiller-spill,Gracz jest martwy w grze dla jednego gracza,Jogador está morto em partida single player.,Jogador está morto numa partida single player.,Jucătorul este mort într-un joc single-player,Игрок мёртв в одиночной игре,Играч је мртав у сингл-плејер игри,Spelaren är död i ett enspelarspel.,Oyuncu tek oyunculu bir oyunda öldü, +Save failed,TXT_SAVEFAILED,,,,Uložení se nezdařilo.,Save mislykkedes,Speichern fehlgeschlagen.,Η αποθήκευση απέτυχε,Konservo malsukcesis,Guardado fallido,,Tallennus epäonnistui,La sauvegarde à échoué.,Mentés meghiusult,Salvataggio fallito,セーブに失敗した。,저장 실패,Opslaan mislukt,Lagring mislyktes,Nie udało się zapisać,Falha ao salvar,Falha ao gravar,Salvare eșuată,Ошибка сохранения игры,Сачување није успело,Spara misslyckades.,Kaydetme başarısız, +Could not create screenshot.,TXT_SCREENSHOTERR,,,,Nepodařilo se pořídit snímek obrazovky.,Kunne ikke oprette et skærmbillede.,Konnte Screenshot nicht erzeugen.,Ένα screenshot δέν μπόρεσε να τραβυχτεί,Ne povis krei ekrankopion.,No se pudo crear captura de pantalla.,,Ei voitu ottaa kuvakaappausta.,La capture d'écran à échoué.,Képernyőmentés meghiusult,Non è stato possibile effettuare la cattura dello schermo.,スクリーンショットを作成できなかった。,스크린샷을 만들 수 없음.,Kon geen screenshot maken.,Kunne ikke opprette skjermbilde.,Nie można zrobić zrzutu ekranu.,Não foi possível capturar a tela.,Não foi possível capturar ecrã,Captura de ecran nu a putut fi creată.,Ошибка создания снимка экрана.,Није успело направити снимак екрана.,Kunde inte skapa en skärmdump.,Ekran görüntüsü oluşturulamadı., By %s,TXT_BY,As in paused by player %s.,,,hráčem %s,Af %s,Von %s,Απο @[pro_gr] %s,De %s,Por %s,,Pelaajan %s toimesta,Par %s,%s által,Da %s,"%s より -",%s 에 의해,Met %s,Etter %s,Przez %s,Por %s,,De către %s,игроком %s,играчем %s,Tarafından %s -Press any key or click anywhere in the window to quit.,TXT_QUITENDOOM,,,,"Pro ukončení stiskni libovolnou klávesu, nebo klikni kdekoliv v okně.",Tryk på en vilkårlig tast eller klik et vilkårligt sted i vinduet for at afslutte.,Drücke eine Taste oder klicke mit der Maus ins Fenster zum Beenden.,Πάτα οποιοδήποτε πλήκτρο ή πάτα οπουδήποτε για να κάνεις έξοδο,Premu ajnan klavon aŭ alklaku ie ajn en la fenestro por forlasi.,Presiona una tecla o haz click en cualquier lugar de la ventana para salir.,,Paina mitä tahansa näppäintä tai napsauta minne tahansa ikkunaa lopettaaksesi.,Appuyez sur une touche ou cliquez pour quitter.,Nyomjon egy billentyűt vagy kattintson bárhova a kilépéshez.,Premi un qualunque tasto o fai un click ovunque nella finestra per uscire.,何かのキーを押すか、ウィンドウのどこかをクリックすると終了する。,아무 키를 누르거나 아무 곳이나 클릭하면 종료됩니다.,Druk op een willekeurige toets of klik ergens in het venster om te stoppen.,Trykk på en hvilken som helst tast eller klikk hvor som helst i vinduet for å avslutte.,Wciśnij dowolny klawisz lub gdziekolwiek kliknij myszką aby wyjść.,Aperte qualquer tecla ou clique em qualquer lugar na janela para sair.,Carrega numa tecla ou clique em qualquer lugar na janela para sair.,Apasă orice tastă sau dă click oriunde în fereastră pentru a ieși.,"Нажмите любую клавишу или нажмите по окну, чтобы выйти.",Притисните било који тастер или кликните било где на екрану да одустанете.,Çıkmak için herhangi bir tuşa basın veya pencerede herhangi bir yere tıklayın. -Screen Blend Options,HUDMNU_FLASH,,,,Barvení obrazovky,Indstillinger for skærmblanding,Überblendoptionen,Ρυθμίσεις Ανάμειξης Οθόνης,Ekranmisko-Agordoj,Opciones de tintado de pantalla,,Näytön sekoitusasetukset,Options de blending écran,Képernyő Keverés Beállítások,Opzioni Blending dello Schermo,スクリーンブレンド オプション,화면 조합 설정,Opties voor schermmengsel,Alternativer for skjermblanding,Opcje scalania ekranu,Opções de mescla de tela,Opções de mistura de ecrã,Setări Amestec Imagine,Настройки смешивания экрана,Подешавања блед екрана,Ekran Karışım Seçenekleri -3D mode,GLMNU_3DMODE,,,,3D režim,3D-tilstand,3D Modus,3D λειτουργία,3D-reĝimo,Modo 3D,,3D-tila,Mode 3D,3D mód,Modalità 3D,3Dモード,3D 모드 적용,3D-modus,3D-modus,Tryb 3D,Modo 3D,,Mod 3D,Режим 3D,3D режим,3D modu -Crosshair,HUDMNU_CROSSHAIRON,,,,Zaměřovač,Trådkors,Fadenkreuz,Crosshair,Reteto,Retícula,,Tähtäin,Viseur,Célkereszt,Mirino,クロスヘア,조준점,Draadkruis,Trådkors,Celownik,Mira,,Țintă,Прицел,Нишан,Crosshair -Subtitles,MSGMNU_SUBTITLES,,,,Titulky,Undertekster,Untertitel,Υπότιτλοι,Subtekstoj,Subtítulos,,Tekstitys,Sous-titres,Feliratok,Sottotitoli,サブタイトル,자막,Ondertitels,Undertekster,Napisy,Legendas,,Subtitrări,Субтитры,Титлови,Altyazılar -Prevent gray shadows,GLPREFMNU_PALTONENOGREY,,,Prevent grey shadows,Předejít šedým stínům,Forebyg grå skygger,Vermeide graue Schatten,Απότρεξη γρί σκιών,Preventi grizajn ombrojn,Prevenir sombras grises,,Estä harmaat varjot,Eviter les ombres grises,Szürke árnyákok megakadályozása,Prevenire le ombre grigie,グレイシャドウを防ぐ,회색 그림자 없에기,Voorkom grijze schaduwen,Forhindre grå skygger,Zapobiegaj szarym cieniom,Prevenir sombras cinzentas,,Prevenire umbre gri,Убрать серые тени,Онемогући сиве сенке,Gri gölgeleri önleyin -Font Options,HUDMNU_FONTOPTIONS,,,,Písma,Indstillinger for skrifttyper,Zeichensatzoptionen,Ρυθμίσεις Γραμματοσειρών,Tiparo-Agordoj,Opciones de fuentes,,Fonttiasetukset,Options de police,Betű Beállítások,Opzioni per il tipo di carattere,フォント オプション,폰트 설정,Lettertype opties,Alternativer for skrifttype,Opcje czcionek,Opções de Fonte,,Setări Font,Настройки шрифта,Подешавања фонта,Yazı Tipi Seçenekleri -Use standard font for log display,FONTMNU_LOG,,,,Použít standardní font pro záznamy,Brug standardskrifttype til visning af logfiler,Benutze Standardzeichensatz für das Log,Χρησιμοποίηση πρότυπης γραμματοσειράς για προβολή ημερολόγιου,Uzi norman tiparon por protokola ekrano,Usar la fuente estándar para logs,,Käytä oletusfonttia lokinäytölle,Police standard pour affichage du log,Szabvány betűstílus használata a logokhoz,Usa il tipo di carattere di default per la visualizzazione dei messaggi di log,ログ表示に標準フォントを使用,로그 표시에서 기본 폰트 사용,Gebruik het standaardlettertype voor de weergave van logboekberichten,Bruk standard skrifttype for loggvisning,Użyj standardowej czcionki do wyświetlania dziennika,Usar fonte padrão para exibição de log,,Utilizează fontul standard pentru mesajele de tip log,Использовать стандартный шрифт для журнала,Користи стандардни фонт за приказ лога,Günlük ekranı için standart yazı tipi kullanın -Use standard font for dialogues,FONTMNU_DLG,,,,Použít standardní font pro dialogy,Brug standardskrifttype til dialoger,Benutze Standardzeichensatz für Dialoge,Χρησιμοποίηση πρότυπης γραμματοσειράς,Uzi norman tiparon por dialogoj,Usar la fuente estándar para diálogos,,Käytä oletusfonttia keskustelulle,Police standard pour dialogues,Szabvány betűstílus használata a dialógusokhoz,Usa il tipo di carattere di default per la visualizzazione dei dialoghi,ダイアログに標準フォントを使用,대화에서 기본 폰트 사용,Gebruik het standaardlettertype voor dialoogweergave,Bruk standard skrifttype for dialoger,Użyj standardowej czcionki do dialogów,Usar fonte padrão para diálogos,,Utiliează fontul standard pentru căsuțele de dialog,Использовать стандартный шрифт для диалогов,Користи стандардни фонт за дијалоге,Diyaloglar için standart yazı tipi kullanın +",%s 에 의해,Met %s,Etter %s,Przez %s,Por %s,,De către %s,игроком %s,играчем %s,Av %s,Tarafından %s, +Press any key or click anywhere in the window to quit.,TXT_QUITENDOOM,,,,"Pro ukončení stiskni libovolnou klávesu, nebo klikni kdekoliv v okně.",Tryk på en vilkårlig tast eller klik et vilkårligt sted i vinduet for at afslutte.,Drücke eine Taste oder klicke mit der Maus ins Fenster zum Beenden.,Πάτα οποιοδήποτε πλήκτρο ή πάτα οπουδήποτε για να κάνεις έξοδο,Premu ajnan klavon aŭ alklaku ie ajn en la fenestro por forlasi.,Presiona una tecla o haz click en cualquier lugar de la ventana para salir.,,Paina mitä tahansa näppäintä tai napsauta minne tahansa ikkunaa lopettaaksesi.,Appuyez sur une touche ou cliquez pour quitter.,Nyomjon egy billentyűt vagy kattintson bárhova a kilépéshez.,Premi un qualunque tasto o fai un click ovunque nella finestra per uscire.,何かのキーを押すか、ウィンドウのどこかをクリックすると終了する。,아무 키를 누르거나 아무 곳이나 클릭하면 종료됩니다.,Druk op een willekeurige toets of klik ergens in het venster om te stoppen.,Trykk på en hvilken som helst tast eller klikk hvor som helst i vinduet for å avslutte.,Wciśnij dowolny klawisz lub gdziekolwiek kliknij myszką aby wyjść.,Aperte qualquer tecla ou clique em qualquer lugar na janela para sair.,Carrega numa tecla ou clique em qualquer lugar na janela para sair.,Apasă orice tastă sau dă click oriunde în fereastră pentru a ieși.,"Нажмите любую клавишу или нажмите по окну, чтобы выйти.",Притисните било који тастер или кликните било где на екрану да одустанете.,Tryck på någon tangent eller klicka någonstans i fönstret för att avsluta.,Çıkmak için herhangi bir tuşa basın veya pencerede herhangi bir yere tıklayın., +Screen Blend Options,HUDMNU_FLASH,,,,Barvení obrazovky,Indstillinger for skærmblanding,Überblendoptionen,Ρυθμίσεις Ανάμειξης Οθόνης,Ekranmisko-Agordoj,Opciones de tintado de pantalla,,Näytön sekoitusasetukset,Options de blending écran,Képernyő Keverés Beállítások,Opzioni Blending dello Schermo,スクリーンブレンド オプション,화면 조합 설정,Opties voor schermmengsel,Alternativer for skjermblanding,Opcje scalania ekranu,Opções de mescla de tela,Opções de mistura de ecrã,Setări Amestec Imagine,Настройки смешивания экрана,Подешавања блед екрана,Alternativ för skärmblandning,Ekran Karışım Seçenekleri, +3D mode,GLMNU_3DMODE,,,,3D režim,3D-tilstand,3D Modus,3D λειτουργία,3D-reĝimo,Modo 3D,,3D-tila,Mode 3D,3D mód,Modalità 3D,3Dモード,3D 모드 적용,3D-modus,3D-modus,Tryb 3D,Modo 3D,,Mod 3D,Режим 3D,3D режим,3D-läge,3D modu, +Crosshair,HUDMNU_CROSSHAIRON,,,,Zaměřovač,Trådkors,Fadenkreuz,,Reteto,Retícula,,Tähtäin,Viseur,Célkereszt,Mirino,クロスヘア,조준점,Draadkruis,Trådkors,Celownik,Mira,,Țintă,Прицел,Нишан,Hårkors,, +Subtitles,MSGMNU_SUBTITLES,,,,Titulky,Undertekster,Untertitel,Υπότιτλοι,Subtekstoj,Subtítulos,,Tekstitys,Sous-titres,Feliratok,Sottotitoli,サブタイトル,자막,Ondertitels,Undertekster,Napisy,Legendas,,Subtitrări,Субтитры,Титлови,Undertexter,Altyazılar, +Prevent gray shadows,GLPREFMNU_PALTONENOGREY,,,Prevent grey shadows,Předejít šedým stínům,Forebyg grå skygger,Vermeide graue Schatten,Απότρεξη γρί σκιών,Preventi grizajn ombrojn,Prevenir sombras grises,,Estä harmaat varjot,Eviter les ombres grises,Szürke árnyákok megakadályozása,Prevenire le ombre grigie,グレイシャドウを防ぐ,회색 그림자 없에기,Voorkom grijze schaduwen,Forhindre grå skygger,Zapobiegaj szarym cieniom,Prevenir sombras cinzentas,,Prevenire umbre gri,Убрать серые тени,Онемогући сиве сенке,Förhindra gråa skuggor,Gri gölgeleri önleyin, +Font Options,HUDMNU_FONTOPTIONS,,,,Písma,Indstillinger for skrifttyper,Zeichensatzoptionen,Ρυθμίσεις Γραμματοσειρών,Tiparo-Agordoj,Opciones de fuentes,,Fonttiasetukset,Options de police,Betű Beállítások,Opzioni per il tipo di carattere,フォント オプション,폰트 설정,Lettertype opties,Alternativer for skrifttype,Opcje czcionek,Opções de Fonte,,Setări Font,Настройки шрифта,Подешавања фонта,Typsnittsalternativ,Yazı Tipi Seçenekleri, +Use standard font for log display,FONTMNU_LOG,,,,Použít standardní font pro záznamy,Brug standardskrifttype til visning af logfiler,Benutze Standardzeichensatz für das Log,Χρησιμοποίηση πρότυπης γραμματοσειράς για προβολή ημερολόγιου,Uzi norman tiparon por protokola ekrano,Usar la fuente estándar para logs,,Käytä oletusfonttia lokinäytölle,Police standard pour affichage du log,Szabvány betűstílus használata a logokhoz,Usa il tipo di carattere di default per la visualizzazione dei messaggi di log,ログ表示に標準フォントを使用,로그 표시에서 기본 폰트 사용,Gebruik het standaardlettertype voor de weergave van logboekberichten,Bruk standard skrifttype for loggvisning,Użyj standardowej czcionki do wyświetlania dziennika,Usar fonte padrão para exibição de log,,Utilizează fontul standard pentru mesajele de tip log,Использовать стандартный шрифт для журнала,Користи стандардни фонт за приказ лога,Använd standardtypsnitt för loggvisningen,Günlük ekranı için standart yazı tipi kullanın, +Use standard font for dialogues,FONTMNU_DLG,,,,Použít standardní font pro dialogy,Brug standardskrifttype til dialoger,Benutze Standardzeichensatz für Dialoge,Χρησιμοποίηση πρότυπης γραμματοσειράς,Uzi norman tiparon por dialogoj,Usar la fuente estándar para diálogos,,Käytä oletusfonttia keskustelulle,Police standard pour dialogues,Szabvány betűstílus használata a dialógusokhoz,Usa il tipo di carattere di default per la visualizzazione dei dialoghi,ダイアログに標準フォントを使用,대화에서 기본 폰트 사용,Gebruik het standaardlettertype voor dialoogweergave,Bruk standard skrifttype for dialoger,Użyj standardowej czcionki do dialogów,Usar fonte padrão para diálogos,,Utiliează fontul standard pentru căsuțele de dialog,Использовать стандартный шрифт для диалогов,Користи стандардни фонт за дијалоге,Använd standardtypsnitt för dialoger,Diyaloglar için standart yazı tipi kullanın, Quick Exit,MISCMNU_QUICKEXIT,,,,Rychlé ukončení,Hurtig afslutning,"Schnelles Beenden -",Γρήγορη Έξοδος,Rapida Eliro,Salida Rápida,,Pikapoistuminen,Sortie rapide,Gyors kilépés,Uscita rapida,終了メッセージ無し,빠른 종료,Snel eindigen,Hurtigavslutning,Szybkie wyjście,Saída Rápida,,Ieșire Rapidă,Быстрый выход,Брзи излаз,Hızlı Çıkış -Custom Inverse Map,DSPLYMNU_CUSTOMINVERTMAP,,,,Vlastní inverzní barvení,Brugerdefinerede omvendte farver,Benutzerdefinierte invertierte Farben,Προσαρμοσμένος Ανάποδος Χάρτης,Propra Inversa Mapo,Personalizar Filtro Invertido,,Mukautettu käänteinen kartta,Couleurs inverses personnalisées,Egyéni inverz pálya,Mappa inversa personalizzata,マップ反転色カスタム,사용자 지정 반전 맵,Aangepaste inversiekleuren,Egendefinert omvendt kart,Niestandardowe odwrócone kolory,Personalizar Cores Invertidas,,Personalizare Inverse Map,Настроить цвета при неуязвимости,Прилагођена обрнута мапа,Özel Ters Harita +",Γρήγορη Έξοδος,Rapida Eliro,Salida Rápida,,Pikapoistuminen,Sortie rapide,Gyors kilépés,Uscita rapida,終了メッセージ無し,빠른 종료,Snel eindigen,Hurtigavslutning,Szybkie wyjście,Saída Rápida,,Ieșire Rapidă,Быстрый выход,Брзи излаз,Snabbavslutning,Hızlı Çıkış, +Custom Inverse Map,DSPLYMNU_CUSTOMINVERTMAP,,,,Vlastní inverzní barvení,Brugerdefinerede omvendte farver,Benutzerdefinierte invertierte Farben,Προσαρμοσμένος Ανάποδος Χάρτης,Propra Inversa Mapo,Personalizar Filtro Invertido,,Mukautettu käänteinen kartta,Couleurs inverses personnalisées,Egyéni inverz pálya,Mappa inversa personalizzata,マップ反転色カスタム,사용자 지정 반전 맵,Aangepaste inversiekleuren,Egendefinert omvendt kart,Niestandardowe odwrócone kolory,Personalizar Cores Invertidas,,Personalizare Inverse Map,Настроить цвета при неуязвимости,Прилагођена обрнута мапа,Anpassad omvänd karta,Özel Ters Harita, "Custom Inverse Color Dark ",DSPLYMNU_CUSTOMINVERTC1,,,Custom Inverse Colour Dark,Vlastní inverzní tmavá barva,Brugerdefineret omvendt farve mørk,Dunkle Farbe für Invertierung,Προσαρμοσμένος Ανάποδο Χρώμα Σκοτεινό,Propra Inversa Koloro Malhela,"Color Oscuro de Filtro Invertido ",,Mukautettu käänteinen tumma väri,Couleur foncée pour l'inversion,Egyéni inverz sötét szín,Colore inverso personalizzato scuro,反転色カスタム 暗,사용자 지정 어두운 반전 색상,Aangepaste donkere inversiekleur,"Egendefinert invers farge mørk -",Ciemny kolor do inwersji,Personalizar Cores Invertidas - Cor escura,,Personalizare Culoare Inverse Map Închisă,Тёмный цвет,Прилагођена инверзна боја тамна,"Özel Ters Renk Koyu -" +",Ciemny kolor do inwersji,Personalizar Cores Invertidas - Cor escura,,Personalizare Culoare Inverse Map Închisă,Тёмный цвет,Прилагођена инверзна боја тамна,"Anpassad omvänd färg Mörk +","Özel Ters Renk Koyu +", Custom Inverse Color Light,DSPLYMNU_CUSTOMINVERTC2,,,Custom Inverse Colour Light,Vlastní inverzní světlá barva,Brugerdefineret omvendt farve lys,Helle Farbe für Invertierung,Προσαρμοσμένος Ανάποδο Χρώμα Φωτεινό,Propra Inversa Koloro Hela,Color Claro de Filtro Invertido,,"Mukautettu käänteinen vaalea väri -",Couleur claire pour l'inversion,Egyéni inverz világos szín,Colore inverso personalizzato chiaro,反転色カスタム 明,사용자 지정 밝은 반전 색상,Aangepaste lichte inversiekleur,Egendefinert invers farge lys,Jasny kolor do inwersji,Personalizar Cores Invertidas - Cor clara,,Personalizare Culoare Inverse Map Deschisă,Светлый цвет,Прилагођено инверзно светло у боји,Özel Ters Renkli Işık -View bob amount when firing,DSPLYMNU_BOBFIRE,,,,Pohupování pohybu při střelbě,Vis bob-beløb ved affyring,Waffenpendeln beim Schießen,,Vidi kvanton de kapo-balanciĝo dum pafado,Balanceo de pantalla al disparar,,Aseen heilumisvoimakkuus ammuttaessa,,Fegyvermozgás lövésnél,Movimento dell'arma quando si spara,攻撃時の視点揺れ値,발사 시 밥 양 보기,Op en neer tijdens schieten,Vis bob-beløp ved avfyring,Częstotliwość bujania się broni przy strzelaniu,Quantidade de balanço ao atirar,,Intensitate mișcare arme în timpul deplasării,Количество тряски экрана при стрельбе,,Ateşleme sırasında bob miktarını görüntüleme -Intermission and Screen Border Classic Scaling,SCALEMNU_SCALECLASSIC,HUD->Scaling Options,,,Klasické škálování text. obrazovek a okrajů obrazovky,Pause og skærmkant Klassisk skalering,Klassische Skalierung von Texthintergrund und Rahmen,,Klasika Skalado de Intermito kaj Ekranbordero,Escalado Clásico de Intermisión y Bordes de Pantalla,,Perinteinen väliruutujen ja ruudunreunusten skaalaus,Mise à l'échelle classique pour bordure écran et intermission,Megszakító és Képszél klasszikus arányosítása,Ridimensionamento classico dell'intermissione e del bordo dello schermo,旧式スケールのクリア結果と画面ボーダー,인터미션 및 화면 테두리 클래식 스케일링,Intermissie en schermrand schalen,Klassisk skalering av pause og skjermkant,Klasyczne skalowanie wstawek i ramek,Escala clássica para tela de intervalo e borda de tela,,Scară bordură antract și ecran,Классические размеры экрана между миссиями и границ экрана,Класично скалирање паузе и ивице екрана,Ara ve Ekran Kenarlığı Klasik Ölçeklendirme -Intermission background,SCALEMNU_INTER,,,,Pozadí textových obrazovek,Intermission baggrund,Texthintergrund,,Fono de intermito,Fondo de intermisión,,Väliruutujen tausta,Fond d'écran intermission,Megszakító háttér,Sottofondi delle intermissioni,クリア結果の背景,인터미션 배경,Intermissieachtergrond,Pause bakgrunn,Tło wstawek,Fundo da tela de intervalo,,Fundal antract,Фон экрана между миссиями,Интермиссион бацкгроунд,Devre arası arka planı -Screen border,SCALEMNU_BORDER,,,,Okraje obrazovky,Skærmbord,Rahmen,,Ekranbordero,Bordes de pantalla,,Ruudunreunus,Bordure d'écran,Kép széle,Bordo dello schermo,画面ボーダー,화면 테두리,Schermrand,Skjermkant,Ramka,Borda de tela,,Bordură ecran,Границы экрана,Граница екрана,Ekran kenarlığı -Scaling factor,SCALEMNU_FACTOR,,,,Měřítko,Skaleringsfaktor,Skalierungsfaktor,,Skalfaktoro,Factor de escalado,,Skaalauskerroin,Facteur de mise à l'échelle,Arányosító faktor,Fattore di scala,スケール倍率,스케일링 계수,Schaalfactor,Skaleringsfaktor,Współczynnik skalowania,Fator de escala,,Factor de scalare,Значение масштабирования,Фактор за скалирање,Ölçekleme faktörü -Aspect ratio,SCALEMNU_RATIO,,,,Poměr stran,Aspektforhold,Seitenverhältnis,,Proporcio,Ratio de aspecto,,Kuvasuhde,,Képarány,Proporzioni,アスペクト比,화면 비율,Beeldverhouding,Bildeforhold,Rozdzielczość,Proporção de tela,,Aspect imagine,Соотношение сторон,Однос ширине и висине,En boy oranı -Build,OPTVAL_BUILD,"as in ""Build engine"". This should not be translated unless there is a translated name for the engine",,,,,,,,,,,,,,,,,,,Build,,,,, -Show Tally Screen On Level Exit,MISCMNU_ALWAYSTALLY,sv_alwaystally,,,Zobrazit výsledky na konci mapy,"Vis resultater, når du forlader kortet",Zeige Ergebnisse beim Verlassen des Levels,,Montri Kalkulekranon Sur Niveleliro,Mostrar pantalla de conteo al salir de nivel,,Näytä pisteruutu tasosta poistuttaessa,Montrer les scores en fin de niveau,Elért pontok mutatása a megszakító képen,Mostra i punteggi alla fine del livello,Exit時にタリー画面を表示,레벨 종료 시 집계 화면 표시,Toon tellingen na eind van het level,Vis Tally-skjerm på nivåutgang,Pokazuj wyniki pod koniec poziomu,Exibir tela de pontuação no fim da fase,,Afișează Totalul la Ieșirea din Nivel,Отображение экрана статистики при выходе с уровня,Прикажи екран за израчунавање на излазу из нивоа,Seviye Çıkışında Çetele Ekranını Göster -Mod Defined,OPTVAL_MODDEFINED,this is '==0',,,Určeno mody,Mod Defineret,Mod-definiert,,Modifo Difinita,Definido por mod,,Modin määrittämä,Défini par Mod,Beállított Mod,Definito dalla mod,Mod定義,모드 정의,Volgens de mod,Mod Definert,Zdefiniowane przez modyfikację,Definir por mod,,Definit de către moduri,Определено модификацией,Мод Дефинед,Mod Tanımlı -"Always, except within hubs",OPTVAL_NOTHUBS,,,,Vždy kromě hubů,"Altid, undtagen i hubs","Immer, außer in Hubs",,"Ĉiam, krom en naboj","Siempre, excepto en hubs",,"Aina, keskustasoja lukuun ottamatta","Toujours, sauf dans les hubs","Mindig, kivétel a csomópontoknál","Sempre, tranne gli hub",区間を除き、常に,"항상, 허브 내 제외","Altijd, behalve binnen hubs","Alltid, unntatt innenfor knutepunkter","Zawsze, oprócz hubów","Sempre, exceto em hubs",,"Mereu, mai puțin în hub-uri",Всегда (кроме групп уровней),"Увек, осим унутар чворишта","Her zaman, hub'lar hariç" -"Always, even within hubs",OPTVAL_WITHHUBS,,,,Vždy včetně hubů,"Altid, også inden for hubs","Immer, auch in Hubs",,"Ĉiam, eĉ en naboj","Siempre, incluso en hubs",,"Aina, keskustasot mukaan lukien","Toujours, même dans les hubs","Mindig, még a csomópontoknál is","Sempre, inclusi gli hub",区間内でも、常に,"항상, 허브 내에서도","Altijd, zelfs binnen hubs","Alltid, også innenfor knutepunkter","Zawsze, nawet w hubach","Sempre, inclusive em hubs",,"Mereu, inclusiv în hub-uri",Всегда (включая группы уровни),"Увек, чак и унутар чворишта","Her zaman, merkezler içinde bile" -Preferred keyboard layout,CNTRLMNU_LAYOUT,,,,Preferované rozložení klávesnice,Foretrukket tastaturlayout,Bevorzugte Tastaturbelegung,,Preferita klavararanĝo,Disposición de teclado preferida,,Lempinäppäinasettelu,Organisation préférée du clavier,Preferált billentyűkiosztás,Layout della tastiera preferito,優先するキー配列,기본 키보드 레이아웃,Voorkeur toetsenbordindeling,Foretrukket tastaturoppsett,Preferowany układ klawiatury,Layout de teclado preferido,,Schemă de control preferată,Раскладка клавиатуры,Жељени распоред тастатуре,Tercih edilen klavye düzeni -Classic ZDoom,OPTVAL_CLASSICZ,,,,Klasický ZDoom,Klassisk ZDoom,ZDoom klassisch,,Klasika ZDoom,ZDoom clásico,,Perinteinen ZDoom,Zdoom Classique,Klasszikus ZDoom,ZDoom Classico,従来のZDOOM,클래식 ZDoom,Klassiek ZDoom,Klassisk ZDoom,Klasyczny ZDoom,ZDoom Clássico,,ZDoom Clasic,Классическая ZDoom,Цлассиц ЗДоом,Klasik ZDoom -Modern (WASD),OPTVAL_MODERN,,,,Moderní (WASD),Moderne (WASD),,,Moderna (WASD),Moderno (WASD),,Nykyaikainen (WASD),Moderne (ZQSD),,Moderno (WASD),現代的(WASD),모던(WASD),,Moderne (WASD),Współczesny (WSAD),Moderno (WASD),,Modernă (WASD),Современная (ЦФЫВ),модерно,Modern (WASD) -Modern (Keypad),OPTVAL_MODERNLEFT,,,,Moderní (číselník),Moderne (Keypad),,,Moderna (Cifera klavaro),Moderno (Teclado Numérico),,Nykyaikainen (numeronäppäimistö),Moderne (Pavé numérique),Modern (numpad),Moderno (tastierino numerico),現代的(Keypad),모던(키패드),Modern (nummeriek toetsenbord),Moderne (Keypad),Współczesny (klawiatura numeryczna),Moderno (Teclado numérico),,Modernă (Tastatură),Современная (цифровой блок),Модерна (тастатура),Modern (Tuş Takımı) -Strict KEYCONF Weapons/Players,MISCMNU_SETSLOTSTRICT,,,,Striktně zbraně/hráči z KEYCONF,Strenge KEYCONF Våben/spillere,Strikte KEYKONF Behandlung für Waffen und Spieler,,Strikta KEYCONF Armiloj/Ludantoj,KEYCONF de Armas/Jugadores estricto,,Pelaajien/Aseiden tiukka KEYCONF,Armes/Joueurs strictement selon KEYCONF,Szigorú KEYCONF a Fegyverek/Játékosok esetében,KEYCONF rigoroso per armi/giocatori,厳密にKEYCONFの武器/プレイヤー,엄격한 키콘프 무기/플레이어,Strikte KEYCONF Wapens/Spelers,Strenge KEYCONF-våpen/spillere,Surowe opcje KEYCONF dla broni/graczy,Armas/Jogadores estritamente de acordo com KEYCONF,,KEYCONF Strictă pentru Arme/Jucători,Строгий KEYCONF для оружия/игроков,Строго KEYKONF оружје/играчи,Sıkı KEYCONF Silahlar/Oyuncular +",Couleur claire pour l'inversion,Egyéni inverz világos szín,Colore inverso personalizzato chiaro,反転色カスタム 明,사용자 지정 밝은 반전 색상,Aangepaste lichte inversiekleur,Egendefinert invers farge lys,Jasny kolor do inwersji,Personalizar Cores Invertidas - Cor clara,,Personalizare Culoare Inverse Map Deschisă,Светлый цвет,Прилагођено инверзно светло у боји,Anpassad omvänd färg ljus,Özel Ters Renkli Işık, +Weapon bob amount when firing,DSPLYMNU_BOBFIRE,,,,Pohupování zbraně při střelbě,Våben bob-beløb ved affyring,Waffenpendeln beim Schießen,,Vidi kvanton de kapo-balanciĝo dum pafado,Balanceo de pantalla al disparar,,Aseen heilumisvoimakkuus ammuttaessa,Intensité du chaloupage lors des tirs,Fegyvermozgás lövésnél,Movimento dell'arma quando si spara,射撃時の武器スイング,사격 시 무기 스윙,Wapenzwaai bij schieten,Våben bob-beløp ved avfyring,Częstotliwość bujania się broni przy strzelaniu,Quantidade de balanço ao atirar,,Intensitate mișcare arme în timpul deplasării,Кол-во тряски экрана при стрельбе,,Vapen bob-värde vid skottlossning,Ateşleme sırasında bob miktarını görüntüleme, +Intermission and Screen Border Classic Scaling,SCALEMNU_SCALECLASSIC,HUD->Scaling Options,,,Klasické škálování text. obrazovek a okrajů obrazovky,Pause og skærmkant Klassisk skalering,Klassische Skalierung von Texthintergrund und Rahmen,,Klasika Skalado de Intermito kaj Ekranbordero,Escalado Clásico de Intermisión y Bordes de Pantalla,,Perinteinen väliruutujen ja ruudunreunusten skaalaus,Mise à l'échelle classique pour bordure écran et intermission,Megszakító és Képszél klasszikus arányosítása,Ridimensionamento classico dell'intermissione e del bordo dello schermo,旧式スケールのクリア結果と画面ボーダー,인터미션 및 화면 테두리 클래식 스케일링,Intermissie en schermrand schalen,Klassisk skalering av pause og skjermkant,Klasyczne skalowanie wstawek i ramek,Escala clássica para tela de intervalo e borda de tela,,Scară bordură antract și ecran,Классические размеры экрана между миссиями и границ экрана,Класично скалирање паузе и ивице екрана,Klassisk skalning för paus och skärmkant,Ara ve Ekran Kenarlığı Klasik Ölçeklendirme, +Intermission background,SCALEMNU_INTER,,,,Pozadí textových obrazovek,Intermission baggrund,Texthintergrund,,Fono de intermito,Fondo de intermisión,,Väliruutujen tausta,Fond d'écran intermission,Megszakító háttér,Sottofondi delle intermissioni,クリア結果の背景,인터미션 배경,Intermissieachtergrond,Pause bakgrunn,Tło wstawek,Fundo da tela de intervalo,,Fundal antract,Фон экрана между миссиями,Интермиссион бацкгроунд,Bakgrund för mellanslag,Devre arası arka planı, +Screen border,SCALEMNU_BORDER,,,,Okraje obrazovky,Skærmbord,Rahmen,,Ekranbordero,Bordes de pantalla,,Ruudunreunus,Bordure d'écran,Kép széle,Bordo dello schermo,画面ボーダー,화면 테두리,Schermrand,Skjermkant,Ramka,Borda de tela,,Bordură ecran,Границы экрана,Граница екрана,Skärmgräns,Ekran kenarlığı, +Scaling factor,SCALEMNU_FACTOR,,,,Měřítko,Skaleringsfaktor,Skalierungsfaktor,,Skalfaktoro,Factor de escalado,,Skaalauskerroin,Facteur de mise à l'échelle,Arányosító faktor,Fattore di scala,スケーリング倍率,스케일링 계수,Schaalfactor,Skaleringsfaktor,Współczynnik skalowania,Fator de escala,,Factor de scalare,Значение масштабирования,Фактор за скалирање,Skalningsfaktor,Ölçekleme faktörü, +Aspect ratio,SCALEMNU_RATIO,,,,Poměr stran,Aspektforhold,Seitenverhältnis,,Proporcio,Ratio de aspecto,,Kuvasuhde,,Képarány,Proporzioni,アスペクト比,화면 비율,Beeldverhouding,Bildeforhold,Rozdzielczość,Proporção de tela,,Aspect imagine,Соотношение сторон,Однос ширине и висине,Bildförhållande,En boy oranı, +Build,OPTVAL_BUILD,"as in ""Build engine"". This should not be translated unless there is a translated name for the engine",,,,,,,,,,,,,,,,,,,,,,,,,, +Show Tally Screen On Level Exit,MISCMNU_ALWAYSTALLY,sv_alwaystally,,,Zobrazit výsledky na konci mapy,"Vis resultater, når du forlader kortet",Zeige Ergebnisse beim Verlassen des Levels,,Montri Kalkulekranon Sur Niveleliro,Mostrar pantalla de conteo al salir de nivel,,Näytä pisteruutu tasosta poistuttaessa,Montrer les scores en fin de niveau,Elért pontok mutatása a megszakító képen,Mostra i punteggi alla fine del livello,Exit時にタリー画面を表示,레벨 종료 시 집계 화면 표시,Toon tellingen na eind van het level,Vis Tally-skjerm på nivåutgang,Pokazuj wyniki pod koniec poziomu,Exibir tela de pontuação no fim da fase,,Afișează Totalul la Ieșirea din Nivel,Отображение экрана статистики при выходе с уровня,Прикажи екран за израчунавање на излазу из нивоа,Visa Tally-skärmen på nivå Avsluta,Seviye Çıkışında Çetele Ekranını Göster, +Mod Defined,OPTVAL_MODDEFINED,this is '==0',,,Určeno mody,Mod Defineret,Mod-definiert,,Difinita per modifaĵo,Definido por mod,,Modin määrittämä,Défini par Mod,Beállított Mod,Definito dalla mod,Mod定義,모드 정의,Volgens de mod,Mod Definert,Zdefiniowane przez modyfikację,Definir por mod,,Definit de către moduri,Определено модификацией,Мод Дефинед,Mod definierad,Mod Tanımlı, +"Always, except within hubs",OPTVAL_NOTHUBS,,,,Vždy kromě hubů,"Altid, undtagen i hubs","Immer, außer in Hubs",,"Ĉiam, krom en naboj","Siempre, excepto en hubs",,"Aina, keskustasoja lukuun ottamatta","Toujours, sauf dans les hubs","Mindig, kivétel a csomópontoknál","Sempre, tranne gli hub",区間を除き、常に,"항상, 허브 내 제외","Altijd, behalve binnen hubs","Alltid, unntatt innenfor knutepunkter","Zawsze, oprócz hubów","Sempre, exceto em hubs",,"Mereu, mai puțin în hub-uri",Всегда (кроме групп уровней),"Увек, осим унутар чворишта","Alltid, utom i nav","Her zaman, hub'lar hariç", +"Always, even within hubs",OPTVAL_WITHHUBS,,,,Vždy včetně hubů,"Altid, også inden for hubs","Immer, auch in Hubs",,"Ĉiam, eĉ en naboj","Siempre, incluso en hubs",,"Aina, keskustasot mukaan lukien","Toujours, même dans les hubs","Mindig, még a csomópontoknál is","Sempre, inclusi gli hub",区間内でも、常に,"항상, 허브 내에서도","Altijd, zelfs binnen hubs","Alltid, også innenfor knutepunkter","Zawsze, nawet w hubach","Sempre, inclusive em hubs",,"Mereu, inclusiv în hub-uri",Всегда (включая группы уровни),"Увек, чак и унутар чворишта","Alltid, även inom nav","Her zaman, merkezler içinde bile", +Preferred keyboard layout,CNTRLMNU_LAYOUT,,,,Preferované rozložení klávesnice,Foretrukket tastaturlayout,Bevorzugte Tastaturbelegung,,Preferita klavararanĝo,Disposición de teclado preferida,,Lempinäppäinasettelu,Organisation préférée du clavier,Preferált billentyűkiosztás,Layout della tastiera preferito,優先するキー配列,기본 키보드 레이아웃,Voorkeur toetsenbordindeling,Foretrukket tastaturoppsett,Preferowany układ klawiatury,Layout de teclado preferido,,Schemă de control preferată,Раскладка клавиатуры,Жељени распоред тастатуре,Föredragen tangentbordslayout,Tercih edilen klavye düzeni, +Classic ZDoom,OPTVAL_CLASSICZ,,,,Klasický ZDoom,Klassisk ZDoom,ZDoom klassisch,,Klasika ZDoom,ZDoom clásico,,Perinteinen ZDoom,Zdoom Classique,Klasszikus ZDoom,ZDoom Classico,従来のZDOOM,클래식 ZDoom,Klassiek ZDoom,Klassisk ZDoom,Klasyczny ZDoom,ZDoom Clássico,,ZDoom Clasic,Классическая ZDoom,Цлассиц ЗДоом,Klassiskt ZDoom,Klasik ZDoom, +Modern (WASD),OPTVAL_MODERN,,,,Moderní (WASD),Moderne (WASD),,,Moderna (WASD),Moderno (WASD),,Nykyaikainen (WASD),Moderne (ZQSD),,Moderno (WASD),現代的(WASD),모던(WASD),,Moderne (WASD),Współczesny (WSAD),Moderno (WASD),,Modernă (WASD),Современная (ЦФЫВ),модерно,Modernt (WASD),, +Modern (Keypad),OPTVAL_MODERNLEFT,,,,Moderní (číselník),Moderne (Keypad),,,Moderna (Cifera klavaro),Moderno (Teclado Numérico),,Nykyaikainen (numeronäppäimistö),Moderne (Pavé numérique),Modern (numpad),Moderno (tastierino numerico),現代的(Keypad),모던(키패드),Modern (nummeriek toetsenbord),Moderne (Keypad),Współczesny (klawiatura numeryczna),Moderno (Teclado numérico),,Modernă (Tastatură),Современная (цифр. клавиатура),Модерна (тастатура),Modernt (tangentbord),Modern (Tuş Takımı), +Strict KEYCONF Weapons/Players,MISCMNU_SETSLOTSTRICT,,,,Striktně zbraně/hráči z KEYCONF,Strenge KEYCONF Våben/spillere,Strikte KEYKONF Behandlung für Waffen und Spieler,,Strikta KEYCONF Armiloj/Ludantoj,KEYCONF de Armas/Jugadores estricto,,Pelaajien/Aseiden tiukka KEYCONF,Armes/Joueurs strictement selon KEYCONF,Szigorú KEYCONF a Fegyverek/Játékosok esetében,KEYCONF rigoroso per armi/giocatori,厳密なKEYCONFの武器/プレイヤー,엄격한 키콘프 무기/플레이어,Strikte KEYCONF Wapens/Spelers,Strenge KEYCONF-våpen/spillere,Surowe opcje KEYCONF dla broni/graczy,Armas/Jogadores estritamente de acordo com KEYCONF,,KEYCONF Strictă pentru Arme/Jucători,Строгий KEYCONF для оружия/игроков,Строго KEYKONF оружје/играчи,Strikt KEYCONF Vapen/spelare,Sıkı KEYCONF Silahlar/Oyuncular, Classic ZDoom menu scaling,"MISCMNU_CLEANMENU -",,,,Škálování menu dle starého ZDoomu,Klassisk ZDoom-menu skalering,Alte ZDoom-Skalierung im Menü,,Klasika skalado de ZDoom-menuo,Escalado clásico de ZDoom en menús,,Perinteinen ZDoomin skaalaus valikossa,Mise à l'échelle du menu ZDoom Classique,Klasszikus ZDoom menü arányok,Fattore di scala ZDoom classico per i menu,従来のZDメニュースケール,클래식 ZDoom 메뉴 크기 조정,Klassieke ZDoom-menuschaal,Klassisk ZDoom-menyskalering,Klasyczne skalowanie menu z ZDooma,Escala clássica para menu do ZDoom,,Scară meniuri ZDoom clasică,Классический размер меню ZDoom,Класично скалирање ZDoom менија,Klasik ZDoom menü ölçeklendirme -Use percents on summary screen,MISCMNU_WIPERCENT,,,,Použít procenta ve výsledcích mapy,Brug procenter på oversigtsskærmen,Zeige Prozente auf Statistikseite,,Uzi procentojn sur resumekrano,Usar porcentajes en pantalla de sumario,,Käytä prosentteja pisteruuduilla,Utiliser pourcentages sur l'écran de fin de niveau,Százalékok használata az összefoglaló oldalon,Usa percentuali per le schermate di riepilogo,集計画面でパーセント表示,요약 화면에서 퍼센트 사용,Gebruik procenten op het overzichtsscherm,Bruk prosenter på sammendragsskjermen,Używaj procentów w ekranie wyników pod koniec poziomu,Usar porcentagem na tela de resumo,,Folosește procentaje la totaluri,Использовать проценты на экране итогов уровня,Користите проценте на екрану резимеа,Özet ekranında yüzdeleri kullanma -Classic ZDoom scaling on summary screen,MISCMNU_CLEANSTAT,,,,Škálovat obrazovky se shrnutím dle starého ZDoomu,Klassisk ZDoom-skala på oversigtsskærmen,Alte ZDoom-Skalierung auf Statistikseite,,Klasika ZDoom-skalado sur resumekrano,Escalado clásico de ZDoom en pantalla de sumario,,Perinteinen ZDoomin skaalaus pisteruudulla,Mise à l'échelle écran de fin de niveau ZDoom Classique,Klasszikus ZDoom arányok az összefoglaló oldalon,Fattore di scala ZDoom classico per le schermate di riepilogo,集計画面で従来のZDスケール,요약 화면에서 클래식 ZDoom 스케일링,Klassieke ZDoom-schaalverdeling op overzichtsscherm,Klassisk ZDoom-skalering på oppsummeringsskjermen,Klasyczne skalowanie ekranu z wynikami poziomu,Escala clássica do ZDoom na tela de resumo,,Scară ZDoom clasică a tabelei de marcaj,Классический размер ZDoom экрана итогов уровня,Класично ZDoom скалирање на екрану сажетка,Özet ekranında klasik ZDoom ölçeklendirme -Citizen,TAG_STRIFEZOMBIE,"Called ""citizens"" according to Doomwiki",,,Občan,Borger,Bürger,Πολίτης,Civilulo,Ciudadano,,Kansalainen,Citoyen,Polgár,Cittadino,住民,시민,Burger,Innbygger,Mieszkańcy,Cidadão,,Cetățean,Горожанин,грађанин,Vatandaş -Ceiling Turret,TAG_CEILINGTURRET,,,,Střílna,Tårn til loftet,Deckengeschütz,,Plafona tureto,Torreta de techo,,Kattotykkitorni,Tourelle de plafond,Plafon lövésztorony,Torretta da soffitto,警備システム,천장 터렛,Plafond torentje,Tak-tårn,Wieżyczka,Defesa Automática,,Turetă de Tavan,Потолочная турель,Цеилинг Туррет,Tavan Tareti -Crusader,TAG_CRUSADER,Names need to match the obituaries!,,,Křižák,Korsfarer,Ordensritter,,Krucisto,Cruzado,,Ristiretkeläinen,Croisé,Keresztes,Crociato,クルセーダー,성전사,Kruisvaarder,Korsfarer,Krzyżowiec,Cruzado,,Cruciat,Крестоносец,Црусадер,Haçlı -Inquisitor,TAG_INQUISITOR,,,,Inkvizitor,Inkvisitor,,,Inkvizitoro,Inquisidor,,Inkvisiittori,Inquisiteur,Inkvizítor,Inquisitore,審問官,인퀴지터,Inquisiteur,Inkvisitor,Inkwizytor,Inquisidor,,Inchizitor,Инквизитор,Инквизитор,Engizisyoncu -Peasant,TAG_PEASANT,,,,Rolník,Bonde,Bauer,Χωρικός,Kamparano,Campesino,,Maallikko,Paysan,Jobbágy,Civile,庶民,농민,Onderdaan,Bonde,Mieszczuch,Camponês,,Sărman,Рабочий,Сељак,Köylü -Reaver,TAG_REAVER,,,,Plenitel,Reaver,Plünderer,,Lerta roboto,Saqueador,,Raastaja,Reaver,Fosztogató,Saccheggiatore,リーバー,사수,,Reaver,Rozbójnik,Saqueador,,Hoț,Похититель,Реавер,Yağmacı -Sentinel,TAG_SENTINEL,,,,Strážbot,Sentinel,Wächter,,Sentinelo,Centinela,,Vartija,Sentinelle,Őrszem,Sentinella,センティネル,센티넬,,Vaktpost,Strażnik,Sentinela,,Santinelă,Страж,Сентинел,Nöbetçi -Stalker,TAG_STALKER,,,,Slídil,Stalker,Jäger,,Persekutanto,Acechador,,Vaanija,Chasseur,Lesipuskás,Cacciatore,ストーカー,스토커,,Forfølgeren,Prześladowca,Caçador,,Hărțuitor,Преследователь,Сталкер,Takipçi -The Bishop,TAG_BISHOP,,,,Biskup,Biskoppen,Bischof,,La Episkopo,El Obispo,,Piispa,Evèque,A Püspök,Vescovo,ビショップ,비숍,De Bisschop,Biskopen,Biskup,O Bispo,,Episcopul,Епископ,Бискуп,Piskopos -The One God,TAG_ENTITY,,,,Jeden Bůh,Den ene gud,Der Eine Gott,Ο ένας Θεός,La Ununura Dio,El Dios Único,,Yksi Ainoa Jumala,Le Seui Dieu,Az Egy Isten,Unico Dio,唯一神,유일신,De ene god,Den ene Gud,Jedyny Bóg,O Deus Único,,Adevăratul Zeu,Единый Бог,Једини Бог,Tek Tanrı -The Programmer,TAG_PROGRAMMER,,,,Programátor,Programmøren,Programmierer,,La Programisto,El Programador,,Ohjelmoija,Programmeur,A Programozó,Programmatore,プログラマー,프로그래머,Programmeur,Programmereren,Programista,O Programador,,Programatorul,Программист,Програмер,Programcı -The Spectre,TAG_ALIENSPECTRE,,,,Přízrak,Spøgelset,Schemen,,La Fantomo,El Espectro,,Haamu,Le spectre,A Lidérc,Spettro,スペクトル,스펙터,Het spook,Spøkelset,Widmo,O Espectro,,Spectrul,Призрак,Тхе Спецтре,Hortlak -Kneeling Guy,TAG_KNEELINGGUY,,,,Ctitel,Den knælende fyr,Kniender Typ,,Genuantulo,Tipo arrodillado,,Polvistunut mies,Homme agenouillé,Térdelő,Uomo inchinato,礼拝者,무릎 꿇은 남자,Knielende man,Den knelende fyren,Oddający pokłon,Crente,,Tip Îngenunchiat,Парень на коленях,Човек који клечи,Diz Çökmüş Adam -Spawn multiplayer things in coop,GMPLYMNU_MULTIPLAYERTHINGS,,,,Spawnovat multiplayerové předměty v co-opu,Spawn multiplayer-ting i coop,Multispielergegenstände in Coop,,Ekaperigi plurludantajn objekojn en koopera reĝimo,Hacer aparecer cosas del multijugador en cooperativo,,Luo moninpelioliot yhteispelissä,Créez des objets multijoueurs en co-op,Multiplayer tárgyak létrehozása Együttműködő módban,Fai apparire gli oggetti di multigiocatore in cooperativa,協力モードでマルチ用thingsを出す,협동 플레이에서 멀티플레이어 사물 생성,Spawnen van multiplayer dingen in coop,Spawn multiplayer ting i coop,Daj przedmioty trybu wieloosobowego w trybie kooperacji,Surgir objetos de multijogador no modo coperativo,,Afișează obiectele marcate pentru modul online,Появление вещей из сетевой игры в совместной игре,Поставите ствари за више играча у кооперацији,Coop'ta çok oyunculu şeyler ortaya çıkarma -Sprite shadows,DSPLYMNU_SPRITESHADOW,,,,Stíny spritů,Sprite skygger,Spriteschatten,,Ombroj de spritoj,Sombras de sprites,,Spritevarjot,Ombres de sprites,Sprite árnyékok,Ombre per sprite,スプライト シャドウ,스프라이트 그림자,Sprite schaduwen,Sprite skygger,Cienie sprite'ów,Sombras de sprites,,Umbre pentru sprite-uri,Тени спрайтов,Сприте схадовс,Sprite gölgeleri -Monsters and players,OPTVAL_SPRSHADALWAYS,Will enable sprite shadows for monster and player sprites,,,Monstra a hráči,Monstre og spillere,Monster und Spieler,Τέρατα και παίχτες,Monstroj kaj ludantoj,Monstruos y jugadores,,Hirviöt ja pelaajat,Monstres et joueurs,Szörnyek és játékosok,Mostri e giocatori,敵とプレイヤー,몬스터와 플레이어,Monsters en spelers,Monstre og spillere,Potwory i Gracze,Monstros e jogadores,,Monștrii și jucători,Монстров и игроков,Чудовишта и играчи,Canavarlar ve oyuncular -FOV,DSPLYMNU_FOV,the FOV slider,,,Zorné pole (FOV),,,,Vidkampo,Campo de visión,,Näkökenttä,Champ de vision,Látószög,Campo visivo,,,,,Pole Widzenia,Campo de visão,,Câmp vizual,Поле зрения,,FOV -Disable MBF21 features,CMPTMNU_NOMBF21,,,,Zakázat funkce MBF21,Deaktivere MBF21-funktioner,MBF21 Features deaktivieren,Απενεργοποίηση MBF21 λειτουργιών,Malvalidigi funkciojn de MBF21,Deshabilitar las funciones de MBF21,,Poista MBF21-ominaisuudet käytöstä,Désactiver les fonctionnalités MBF21,MBF21 vonások kikapcsolása,Disabilita le funzioni MBF21,MBF21機能を無効,MBF21 기능 비활성화,MBF21-functies uitschakelen,Deaktiver MBF21-funksjoner,Wyłącz funkcje portu MBF21,Desativar recursos do MBF21,,Dezactivare caracteristici MBF21,Отключить функции MBF21,Онемогућите функције MBF21,MBF21 özelliklerini devre dışı bırakma -Show time widget,ALTHUDMNU_SHOWTIMESTAT,,,,Zobrazit widget s časem,Vis tid widget,Zeige Zeit-Widget,,Montri tempo-fenestraĵon,Mostrar widget de tiempo,,Näytä aikatyökalu,Afficher le widget de l'heure,Óra mutatása,Mostra orario,ウィジットタイマーの表示,시간 표시 위젯,Tijdwidget tonen,Vis tid widget,Pokaż widżet czasu,Mostrar widget de tempo,,Afișare dispozitiv pt. timp,Показать виджет времени,Прикажи виџет времена,Zaman widget'ını göster -MBF21,OPTVAL_MBF21,,,,,,,,,,,,,,,,,,,,,,,,, -Crushed monsters get resurrected as ghosts,CMPTMNU_VILEGHOSTS,,,,Oživovat rozdrcené příšery jako duchy,Knuste monstre genopstår som spøgelser,Zermalmte Monster werden als Geister wiedererweckt,Συνθλιμένα τέρατα αναστήνοντε ως φαντάσματα,Dispremitaj monstroj reviviĝas kiel fantomoj,Los monstruos aplastados son resucitados como fantasmas,,Murskatut hirviöt heräävät henkiin aaveina...,Les monstres écrasés ressuscitent en fantômes,Összenyomott szörnyek szellemként születnek újra,Mostri schiacciati vengono resuscitati come fantasmi,圧死した敵が蘇生でゴースト化,분쇄된 몬스터는 유령으로 부활합니다.,Verpletterde monsters worden herrezen als geesten,Knuste monstre gjenoppstår som spøkelser,Zmiażdżone potwory wskrzeszone jako duchy,Monstros esmagados ressucitam como fantasmas,,Monștrii striviți sunt readuși la viață ca fantome.,Раздавленные монстры воскресают в виде призраков,Сломљена чудовишта васкрсавају као духови,Ezilmiş canavarlar hayalet olarak dirilir -View bobbing while flying,MISCMNU_FVIEWBOB,,,,Pohupování pohybu při létání,Vis bobbing mens du flyver,Waffenpendeln beim Fliegen,,Vidi kapo-balanciĝon dum flugado,,,,Chaloupage arme en vol,,,飛行中の視点揺れ,비행 중 흔들림 보기,Bekijk bob bedrag terwijl je vliegt,Se bobbing mens du flyr,Pokaż bujanie podczas lotu,Balanço na visão durante voo,,Mișcare cameră în timpul zborului,Покачивание камеры при полёте,Погледајте скакање током лета,Uçarken sallanmayı görüntüle \ No newline at end of file +",,,,Škálování menu dle starého ZDoomu,Klassisk ZDoom-menu skalering,Alte ZDoom-Skalierung im Menü,,Klasika skalado de ZDoom-menuo,Escalado clásico de ZDoom en menús,,Perinteinen ZDoomin skaalaus valikossa,Mise à l'échelle du menu ZDoom Classique,Klasszikus ZDoom menü arányok,Fattore di scala ZDoom classico per i menu,従来のZDメニュースケール,클래식 ZDoom 메뉴 크기 조정,Klassieke ZDoom-menuschaal,Klassisk ZDoom-menyskalering,Klasyczne skalowanie menu z ZDooma,Escala clássica para menu do ZDoom,,Scară meniuri ZDoom clasică,Классический размер меню ZDoom,Класично скалирање ZDoom менија,Skalning av Classic ZDoom-menyn,Klasik ZDoom menü ölçeklendirme, +Use percents on summary screen,MISCMNU_WIPERCENT,,,,Použít procenta ve výsledcích mapy,Brug procenter på oversigtsskærmen,Zeige Prozente auf Statistikseite,,Uzi procentojn sur resumekrano,Usar porcentajes en pantalla de sumario,,Käytä prosentteja pisteruuduilla,Utiliser pourcentages sur l'écran de fin de niveau,Százalékok használata az összefoglaló oldalon,Usa percentuali per le schermate di riepilogo,集計画面でパーセント表示,요약 화면에서 퍼센트 사용,Gebruik procenten op het overzichtsscherm,Bruk prosenter på sammendragsskjermen,Używaj procentów w ekranie wyników pod koniec poziomu,Usar porcentagem na tela de resumo,,Folosește procentaje la totaluri,Использовать проценты на экране итогов уровня,Користите проценте на екрану резимеа,Använd procentsatser på sammanfattningsskärmen,Özet ekranında yüzdeleri kullanma, +Classic ZDoom scaling on summary screen,MISCMNU_CLEANSTAT,,,,Škálovat obrazovky se shrnutím dle starého ZDoomu,Klassisk ZDoom-skala på oversigtsskærmen,Alte ZDoom-Skalierung auf Statistikseite,,Klasika ZDoom-skalado sur resumekrano,Escalado clásico de ZDoom en pantalla de sumario,,Perinteinen ZDoomin skaalaus pisteruudulla,Mise à l'échelle écran de fin de niveau ZDoom Classique,Klasszikus ZDoom arányok az összefoglaló oldalon,Fattore di scala ZDoom classico per le schermate di riepilogo,集計画面で従来のZDスケール,요약 화면에서 클래식 ZDoom 스케일링,Klassieke ZDoom-schaalverdeling op overzichtsscherm,Klassisk ZDoom-skalering på oppsummeringsskjermen,Klasyczne skalowanie ekranu z wynikami poziomu,Escala clássica do ZDoom na tela de resumo,,Scară ZDoom clasică a tabelei de marcaj,Классический размер ZDoom экрана итогов уровня,Класично ZDoom скалирање на екрану сажетка,Klassisk ZDoom-skalering på sammanfattningsskärmen,Özet ekranında klasik ZDoom ölçeklendirme, +Citizen,TAG_STRIFEZOMBIE,"Called ""citizens"" according to Doomwiki",,,Občan,Borger,Bürger,Πολίτης,Civilulo,Ciudadano,,Kansalainen,Citoyen,Polgár,Cittadino,住民,시민,Burger,Innbygger,Mieszkańcy,Cidadão,,Cetățean,Горожанин,грађанин,Medborgare,Vatandaş, +Ceiling Turret,TAG_CEILINGTURRET,,,,Střílna,Tårn til loftet,Deckengeschütz,,Plafona tureto,Torreta de techo,,Kattotykkitorni,Tourelle de plafond,Plafon lövésztorony,Torretta da soffitto,警備システム,천장 터렛,Plafond torentje,Tak-tårn,Wieżyczka,Defesa Automática,,Turetă de Tavan,Потолочная турель,Цеилинг Туррет,Tak turret,Tavan Tareti, +Crusader,TAG_CRUSADER,Names need to match the obituaries!,,,Křižák,Korsfarer,Ordensritter,,Krucisto,Cruzado,,Ristiretkeläinen,Croisé,Keresztes,Crociato,クルセーダー,성전사,Kruisvaarder,Korsfarer,Krzyżowiec,Cruzado,,Cruciat,Крестоносец,Црусадер,Korsriddar,Haçlı, +Inquisitor,TAG_INQUISITOR,,,,Inkvizitor,Inkvisitor,,,Inkvizitoro,Inquisidor,,Inkvisiittori,Inquisiteur,Inkvizítor,Inquisitore,審問官,인퀴지터,Inquisiteur,Inkvisitor,Inkwizytor,Inquisidor,,Inchizitor,Инквизитор,Инквизитор,Inkvisitor,Engizisyoncu, +Peasant,TAG_PEASANT,,,,Rolník,Bonde,Bauer,Χωρικός,Kamparano,Campesino,,Maallikko,Paysan,Jobbágy,Civile,庶民,농민,Onderdaan,Bonde,Mieszczuch,Camponês,,Sărman,Рабочий,Сељак,Bonde,Köylü, +Reaver,TAG_REAVER,,,,Plenitel,,Plünderer,,Lertulo,Saqueador,,Raastaja,,Fosztogató,Saccheggiatore,リーバー,사수,,,Rozbójnik,Saqueador,,Hoț,Похититель,Реавер,,Yağmacı, +Sentinel,TAG_SENTINEL,,,,Strážbot,,Wächter,,Sentinelo,Centinela,,Vartija,Sentinelle,Őrszem,Sentinella,センティネル,센티넬,,Vaktpost,Strażnik,Sentinela,,Santinelă,Страж,Сентинел,,Nöbetçi, +Stalker,TAG_STALKER,,,,Slídil,,Jäger,,Gvatanto,Acechador,,Vaanija,Chasseur,Lesipuskás,Cacciatore,ストーカー,스토커,,Forfølgeren,Prześladowca,Caçador,,Hărțuitor,Преследователь,Сталкер,,Takipçi, +The Bishop,TAG_BISHOP,,,,Biskup,Biskoppen,Bischof,,La Episkopo,El Obispo,,Piispa,Evèque,A Püspök,Vescovo,ビショップ,비숍,De Bisschop,Biskopen,Biskup,O Bispo,,Episcopul,Епископ,Бискуп,Biskopen,Piskopos, +The One God,TAG_ENTITY,,,,Jeden Bůh,Den ene gud,Der Eine Gott,Ο ένας Θεός,La Vera Dio,El Dios Único,,Yksi Ainoa Jumala,Le Seul Dieu,Az Egy Isten,Unico Dio,唯一神,유일신,De ene god,Den ene Gud,Jedyny Bóg,O Deus Único,,Adevăratul Zeu,Единый Бог,Једини Бог,Den ende guden,Tek Tanrı, +The Programmer,TAG_PROGRAMMER,,,,Programátor,Programmøren,Programmierer,,La Programisto,El Programador,,Ohjelmoija,Programmeur,A Programozó,Programmatore,プログラマー,프로그래머,Programmeur,Programmereren,Programista,O Programador,,Programatorul,Программист,Програмер,Programmeraren,Programcı, +The Spectre,TAG_ALIENSPECTRE,,,,Přízrak,Spøgelset,Schemen,,La Fantomo,El Espectro,,Haamu,Le spectre,A Lidérc,Spettro,スペクトル,스펙터,Het spook,Spøkelset,Widmo,O Espectro,,Spectrul,Фантом,Тхе Спецтре,Spektret,Hortlak, +Kneeling Guy,TAG_KNEELINGGUY,,,,Ctitel,Den knælende fyr,Kniender Typ,,Genuantulo,Tipo arrodillado,,Polvistunut mies,Homme agenouillé,Térdelő,Uomo inchinato,礼拝者,무릎 꿇은 남자,Knielende man,Den knelende fyren,Oddający pokłon,Crente,,Tip Îngenunchiat,Парень на коленях,Човек који клечи,Den knäböjande killen,Diz Çökmüş Adam, +Spawn multiplayer things in coop,GMPLYMNU_MULTIPLAYERTHINGS,,,,Spawnovat multiplayerové předměty v co-opu,Spawn multiplayer-ting i coop,Multispielergegenstände in Coop,,Ekaperigi plurludantajn aĵojn en koopera reĝimo,Hacer aparecer cosas del multijugador en cooperativo,,Luo moninpelioliot yhteispelissä,Objets multijoueurs en co-op,Multiplayer tárgyak létrehozása Együttműködő módban,Fai apparire gli oggetti di multigiocatore in cooperativa,協力モードでマルチ用thingsを出す,협동 플레이에서 멀티플레이어 사물 생성,Spawnen van multiplayer dingen in coop,Spawn multiplayer ting i coop,Daj przedmioty trybu wieloosobowego w trybie kooperacji,Surgir objetos de multijogador no modo coperativo,,Afișează obiectele marcate pentru modul online,Появление вещей из сетевой игры в совместной игре,Поставите ствари за више играча у кооперацији,Spawna multiplayer saker i coop,Coop'ta çok oyunculu şeyler ortaya çıkarma, +Sprite shadows,DSPLYMNU_SPRITESHADOW,,,,Stíny spritů,Sprite skygger,Spriteschatten,,Ombroj de mov-rastrumoj,Sombras de «sprites»,,Spritevarjot,Ombres de sprites,Sprite árnyékok,Ombre per sprite,スプライト シャドウ,스프라이트 그림자,Sprite schaduwen,Sprite skygger,Cienie sprite'ów,Sombras de sprites,,Umbre pentru sprite-uri,Тени спрайтов,Сприте схадовс,Sprite-skuggor,Sprite gölgeleri, +Monsters and players,OPTVAL_SPRSHADALWAYS,Will enable sprite shadows for monster and player sprites,,,Monstra a hráči,Monstre og spillere,Monster und Spieler,Τέρατα και παίχτες,Monstroj kaj ludantoj,Monstruos y jugadores,,Hirviöt ja pelaajat,Monstres et joueurs,Szörnyek és játékosok,Mostri e giocatori,敵とプレイヤー,몬스터와 플레이어,Monsters en spelers,Monstre og spillere,Potwory i Gracze,Monstros e jogadores,,Monștrii și jucători,Монстров и игроков,Чудовишта и играчи,Monster och spelare,Canavarlar ve oyuncular, +FOV,DSPLYMNU_FOV,the FOV slider,,,Zorné pole (FOV),,,,Vidkampo,Campo de visión,,Näkökenttä,Champ de vision,Látószög,Campo visivo,,,,,Pole Widzenia,Campo de visão,,Câmp vizual,Поле зрения,,,, +Disable MBF21 features,CMPTMNU_NOMBF21,,,,Zakázat funkce MBF21,Deaktivere MBF21-funktioner,MBF21 Features deaktivieren,Απενεργοποίηση MBF21 λειτουργιών,Malvalidigi funkciojn de MBF21,Deshabilitar las funciones de MBF21,,Poista MBF21-ominaisuudet käytöstä,Désactiver les fonctionnalités MBF21,MBF21 vonások kikapcsolása,Disabilita le funzioni MBF21,MBF21機能を無効,MBF21 기능 비활성화,MBF21-functies uitschakelen,Deaktiver MBF21-funksjoner,Wyłącz funkcje MBF21,Desativar recursos do MBF21,,Dezactivare caracteristici MBF21,Отключить функции MBF21,Онемогућите функције MBF21,Inaktivera MBF21-funktioner,MBF21 özelliklerini devre dışı bırakma, +Show time widget,ALTHUDMNU_SHOWTIMESTAT,,,,Zobrazit widget s časem,Vis tid widget,Zeige Zeit-Widget,,Montri tempo-fenestraĵon,Mostrar widget de tiempo,,Näytä aikatyökalu,Afficher le widget horloge,Óra mutatása,Mostra orario,ウィジットタイマーの表示,시간 표시 위젯,Tijdwidget tonen,Vis tid widget,Pokaż widżet czasu,Mostrar widget de tempo,,Afișare dispozitiv pt. timp,Показать виджет времени,Прикажи виџет времена,Visa tidswidget,Zaman widget'ını göster, +MBF21,OPTVAL_MBF21,,,,,,,,,,,,,,,,,,,,,,,,,,, +Crushed monsters get resurrected as ghosts,CMPTMNU_VILEGHOSTS,,,,Oživovat rozdrcené příšery jako duchy,Knuste monstre genopstår som spøgelser,Zermalmte Monster werden als Geister wiedererweckt,Συνθλιμένα τέρατα αναστήνοντε ως φαντάσματα,Dispremitaj monstroj reviviĝas kiel fantomojn,Los monstruos aplastados son resucitados como fantasmas,,Murskatut hirviöt heräävät henkiin aaveina...,Les monstres écrasés ressuscitent en fantômes,Összenyomott szörnyek szellemként születnek újra,Mostri schiacciati vengono resuscitati come fantasmi,圧死した敵が蘇生でゴースト化,분쇄된 몬스터는 유령으로 부활합니다.,Verpletterde monsters worden herrezen als geesten,Knuste monstre gjenoppstår som spøkelser,Zmiażdżone potwory wskrzeszone jako duchy,Monstros esmagados ressucitam como fantasmas,,Monștrii striviți sunt readuși la viață ca fantome.,Раздавленные монстры воскресают в виде призраков,Сломљена чудовишта васкрсавају као духови,Krossade monster återuppstår som spöken.,Ezilmiş canavarlar hayalet olarak dirilir, +View bobbing while flying,MISCMNU_FVIEWBOB,,,,Pohupování pohledu při létání,Vis bobbing mens du flyver,Waffenpendeln beim Fliegen,,Vidi kapo-balanciĝon dum flugado,La vista tambalea al volar,,,Chaloupage en vol,Nézet repüléskori billegése,,飛行中の視点揺れ,비행 중 흔들림 보기,Bekijk bob bedrag terwijl je vliegt,Se bobbing mens du flyr,Pokaż bujanie podczas lotu,Balanço na visão durante voo,,Mișcare cameră în timpul zborului,Покачивание камеры при полёте,Погледајте скакање током лета,Visa att det guppar när du flyger,Uçarken sallanmayı görüntüle, +%o was maimed by a Serpent.,OB_DEMON1HIT,,,,%o byl@[ao_cs] zmrzačen@[ao_cs] zlohadem.,%o blev lemlæstet af en slange.,%o wurde von einer Schlange zerfleischt.,,%o vundegiĝis de Serpento.,,,,%o a été mutilé@[e_fr] par un Serpent.,,%o è stato mutilato da un serpente.,%o はサーペントに斬り捨てられた。,,%o werd verminkt door een slang.,%o ble lemlestet av en slange.,Wąż skaleczył gracza %o,%o foi mutilad@[ao_ptb] por uma Serpente.,,,Игрок %o искалечен змеем.,,%o blev lemlästad av en orm.,"%o, bir yılan tarafından sakat bırakıldı.", +Antialias Lines,AUTOMAPMNU_LINEANTIALIASING,,,,Vyhlazovat čáry,Antialias-linjer,Linien glätten,,Glatigaj Linioj,,,,Lignes Antialias,,,Linesのアンチエイリアス,,Antialijnen,Antialias-linjer,Linie Antyaliasowe,Linhas com antiserrilhamento,,,Линии сглаживания,,Antialias Linjer,Antialias Hatları, +Move and shoot through other players,GMPLYMNU_NOPLAYERCLIP ,,,,Procházet a střílet skrz ostatní hráče,Bevæg dig og skyd gennem andre spillere,Keine Kollisionen mit anderen Spielern,,Movi kaj pafi tra aliajn ludantojn,,,,Déplacez-vous et tirez à travers les autres joueurs,,Muoversi e sparare attraverso gli altri giocatori,移動と攻撃が他プレイヤーを通過,,Beweeg en schiet door andere spelers,Beveg deg og skyt gjennom andre spillere,Brak kolizji z innymi graczami,Mover e atirar através de outros jogadores,,,Перемещение и стрельба через игроков,,Förflytta dig och skjut genom andra spelare,Diğer oyuncuların arasından geçin ve ateş edin, +Share keys with all players,GMPLYMNU_SHAREKEYS,,,,Sdílet klíče se všemi hráči,Del nøgler med alle spillere,Schlüssel mit allen Spielern teilen,,Kunhavigi ŝlosilojn kun ĉiuj ludantoj,,,,Partager les clés avec tous les joueurs,,Condividere i tasti con tutti i giocatori,全プレイヤーにキーを共有,,Deel toetsen met alle spelers,Del nøkler med alle spillere,Współdziel klucze z innymi graczami,Compartilhar chaves com todos os jogadores,,,Общие ключи игроков,,Dela nycklar med alla spelare,Anahtarları tüm oyuncularla paylaşın, +Disallow override of camera facing mode,GLPREFMNU_SPRBILLFACECAMERAFORCE,,,,,Tillad ikke tilsidesættelse af kameravendt tilstand,Änderung des Kameramodus nicht erlauben,,Malebligi transpason de kamerao-rigardado-reĝimo,,,,Interdiction de modifier le mode d'orientation de la caméra,,Disconoscimento della modalità telecamera,Facing modeのカメラをオーバーライドしない,,Overschrijven van camerastand verbieden,Tillat ikke overstyring av kameramodus,Zabroń nadpisywania trybu widoku,Forçar modo de alinhamento do sprite à câmera,,,Запретить переопределение режима поворота камеры,,Tillåt inte åsidosättande av kamerans vändläge,Kameraya bakma modunun geçersiz kılınmasına izin verme, +Swap health and armor,ALTHUDMNU_SWAPHEALTHARMOR,,,,Prohodit zdraví a brnění,Byt om på helbred og rustning,Anzeige für Gesundheit und Panzerung tauschen,,Permuti sanon kaj kirason,,,,Échanger la santé et l'armure,,Scambio di salute e armatura,体力とアーマーをスワップ,,Verwissel gezondheid en pantser,Bytt helse og rustning,Zamień zdrowie i pancerz,Trocar saúde e armadura,,,Поменять отображение здоровья и брони местами,,Byt hälsa och rustning,Sağlık ve zırhı değiştir, +Use classic HUD scaling,SCALEMNU_HUD_OLDSCALE,hud_oldscale,,,Pro HUD použít klasické škálování,Brug klassisk HUD-skalering,Klassische HUD-Skalierung,,Uzi klasikan skaladon de HUD,,,,Utiliser l'échelle classique du HUD,,Utilizzare la scalatura classica dell'HUD,旧式HUDスケーリングを使う,,Gebruik klassieke HUD-schaling,Bruk klassisk HUD-skalering,,Usar escala clássica do HUD,,,Классическое масштабирование интерфейса,,Använd klassisk HUD-skalning,Klasik HUD ölçeklendirmesini kullanın, +HUD scale factor,SCALEMNU_HUD_SCALEFACTOR,hud_scalefactor,,,Faktor HUD škálování,HUD-skaleringsfaktor,HUD-Skalierungsfaktor,,Skalfaktoro de HUD,,,,Facteur d'échelle du HUD,,Fattore di scala dell'HUD,HUDスケール倍率,,HUD-schaalfactor,HUD-skaleringsfaktor,,Fator de escala do HUD,,,Значение масштабирования интерфейса,,Skalningsfaktor för HUD,HUD ölçek faktörü, +Spawn co-op only things in multiplayer,GMPLYMNU_COOPTHINGS,Any Actor that only appears in co-op is disabled,,,Co-op věci pouze v multiplayeru,,,,Ekaperigi nurajn kooperajn aĵojn en plurludanta reĝimo,,,,,,,マルチで協力モード限定thingsを出す,,,,,,,,Появление вещей из совместной игры в сетевой игре,,,, +Spawn co-op only items in multiplayer,GMPLYMNU_COOPITEMS,Items that only appear in co-op are disabled,,,Co-op předměty pouze v multiplayeru,,,,Ekaperigi nurajn kooperajn objektojn en plurludanta reĝimo,,,,,,,マルチで協力モード限定アイテムを出す,,,,,,,,Появление предметов из совместной игры в сетевой игре,,,, +Players pick up their own copy of items in multiplayer,GMPLYMNU_LOCALITEMS,Items are picked up client-side rather than fully taken by the client who picked it up,,,V multiplayeru hráči sbírají své vlastní kopie předmětů,,,,Ludantoj prenas sian propran kopion de objektoj en plurludanta reĝimo,,,,,,,マルチでプレイヤー達は複製アイテムを拾う,,,,,,,,Игроки подбирают собственные копии предметов в сетевой игре,,,, +Disable client-side pick ups on dropped items,GMPLYMNU_NOLOCALDROP,Drops from Actors aren't picked up locally,,,Zakázat sbírání odhozených předmětů na straně klientů,,,,Malvalidigi klientflankajn prenadojn de faligitaj objektoj,,,,,,,クライアント側で落としたアイテムを拾わせない,,,,,,,,Отключить подбирание выпавших предметов на стороне клиента,,,, +Restart on Death,MISCMNU_RESTARTONDEATH,Disables autoloading save on death,,,,,,,,,,,,,,,,,,,,,,Перезапуск после смерти,,,, \ No newline at end of file diff --git a/wadsrc/static/language.def b/wadsrc/static/language.def index b2e003ad4e..e3f76de34a 100644 --- a/wadsrc/static/language.def +++ b/wadsrc/static/language.def @@ -34,6 +34,15 @@ MUSIC_E3M6 = "e3m6"; MUSIC_E3M7 = "e3m7"; MUSIC_E3M8 = "e3m8"; MUSIC_E3M9 = "e3m9"; +MUSIC_E4M1 = "e4m1"; +MUSIC_E4M2 = "e4m2"; +MUSIC_E4M3 = "e4m3"; +MUSIC_E4M4 = "e4m4"; +MUSIC_E4M5 = "e4m5"; +MUSIC_E4M6 = "e4m6"; +MUSIC_E4M7 = "e4m7"; +MUSIC_E4M8 = "e4m8"; +MUSIC_E4M9 = "e4m9"; MUSIC_INTER = "inter"; MUSIC_INTRO = "intro"; MUSIC_BUNNY = "bunny"; @@ -337,9 +346,50 @@ OPENALMNU_TITLE = "$$SNDMNU_OPENAL"; SNDMNU_TITLE = "$$OPTMNU_SOUND"; MODMNU_TITLE = "$$SNDMNU_MODREPLAYER"; MISCMNU_TITLE = "$$OPTMNU_MISCELLANEOUS"; - GLMNU_TEXOPT = "$$GLTEXMNU_TITLE"; +SCORE_ITEMS = "$$TXT_IMITEMS"; +SCORE_KILLS = "$$TXT_IMKILLS"; + +FN_ZOMBIE = "$$CC_ZOMBIE"; +FN_IMP = "$$CC_IMP"; +FN_DEMON = "$$CC_DEMON"; +FN_LOST = "$$CC_LOST"; +FN_CACO = "$$CC_CACO"; +FN_HELL = "$$CC_HELL"; +FN_BARON = "$$CC_BARON"; +FN_ARACH = "$$CC_ARACH"; +FN_PAIN = "$$CC_PAIN"; +FN_REVEN = "$$CC_REVEN"; +FN_MANCU = "$$CC_MANCU"; +FN_ARCH = "$$CC_ARCH"; + +TAG_GAUNTLETS = "$$TXT_WPNGAUNTLETS"; +TAG_GAUNTLETSP = "$$TXT_WPNGAUNTLETS"; +TAG_CROSSBOW = "$$TXT_WPNCROSSBOW"; +TAG_CROSSBOWP = "$$TXT_WPNCROSSBOW"; +TAG_STAFFP = "$$TAG_STAFF"; +TAG_GOLDWANDP = "$$TAG_GOLDWAND"; +TAG_BLASTER = "$$TXT_WPNBLASTER"; +TAG_BLASTERP = "$$TXT_WPNBLASTER"; +TAG_SKULLROD = "$$TXT_WPNSKULLROD"; +TAG_SKULLRODP = "$$TXT_WPNSKULLROD"; +TAG_PHOENIXROD = "$$TXT_WPNPHOENIXROD"; +TAG_PHOENIXRODP = "$$TXT_WPNPHOENIXROD"; +TAG_MACE = "$$TXT_WPNMACE"; +TAG_MACEP = "$$TXT_WPNMACE"; + +TAG_ARTIEGG = "$$TXT_ARTIEGG"; +TAG_ARTIFIREBOMB = "$$TXT_ARTIFIREBOMB"; +TAG_ARTIFLY = "$$TXT_ARTIFLY"; +TAG_ARTIHEALTH = "$$TXT_ARTIHEALTH"; +TAG_ARTISUPERHEALTH = "$$TXT_ARTISUPERHEALTH"; +TAG_ARTIINVISIBILITY = "$$TXT_ARTIINVISIBILITY"; +TAG_ARTIINVULNERABILITY = "$$TXT_ARTIINVULNERABILITY"; +TAG_ARTITELEPORT = "$$TXT_ARTITELEPORT"; +TAG_ARTITOMEOFPOWER = "$$TXT_ARTITOMEOFPOWER"; +TAG_ARTITORCH = "$$TXT_ARTITORCH"; + // newly added text not in the string table OPTMNU_SWRENDERER = "Software Renderer"; @@ -349,3 +399,11 @@ OPTMNU_SYSTEM = "System Options"; OPTMNU_LIGHT = "Light Options"; OPTMNU_SPRITE = "Sprite Options"; GLPREFMNU_CORONAS = "Coronas"; +DSPLYMNU_APPEARANCE = "Appearance"; +DSPLYMNU_ADVANCED = "Advanced Display Options"; +OPTVAL_SHADOWMAP = "Shadowmap"; +OPTVAL_RAYTRACE = "Raytrace"; +GLLIGHTMNU_LIGHTSHADOWS = "Light shadows"; +GLLIGHTMNU_LIGHTSHADOWFILTER = "Shadow filter"; +OPTMNU_SWRENDERER = "$$DSPLYMNU_SWOPT"; +OPTVAL_FIZZLEFADE = "Fizzlefade"; diff --git a/wadsrc/static/lmacros.csv b/wadsrc/static/lmacros.csv index af988a2c06..89ce640ce1 100644 --- a/wadsrc/static/lmacros.csv +++ b/wadsrc/static/lmacros.csv @@ -32,7 +32,9 @@ adj_3_rus,ru,ён,на,но,но irreg_1_rus,ru,ёл,ла,ло,ло irreg_2_rus,ru,,ла,ло,ло irreg_3_rus,ru,ёг,егла,егло,егло -pron_rus,ru,него,неё,него,него +irreg_4_rus,ru,ёк,екла,екло,екло +pron_rus,ru,него,неё,, +cheatpron_rus,ru,щик,щица,, ao_1_sr,sr,о,ла,ло,ло ao_2_sr,sr,ао,ла,ло,ло ao_3_sr,sr,ог,у,ог,ог @@ -44,4 +46,11 @@ pro2_gr,el,Τον,Την,Τον,Το pro3_gr,el,στον,στην,στο,στο art_gr,el,Ο,Η,Το,Το pro4_gr,el,του,της,του,του -pro_dk,da,han,hun,han,det \ No newline at end of file +pro_dk,"da, no",han,hun,han,det +pro_sv,sv,han,hon,han,den +ref_sv,sv,honom,henne,honom,den +ao_ua,ua,ий,а,о,о +adj_1_ua,ua,в,ла,ло,ло +adj_2_ua,ua,вся,лась,лось,лось +adj_3_ua,ua,,ла,ло,ло +adj_4_ua,ua,ий,та,то,то \ No newline at end of file diff --git a/wadsrc/static/mapinfo/common.txt b/wadsrc/static/mapinfo/common.txt index a67e54722f..e80a50105b 100644 --- a/wadsrc/static/mapinfo/common.txt +++ b/wadsrc/static/mapinfo/common.txt @@ -136,10 +136,16 @@ DoomEdNums 9872 = SpotLightFlickerAttenuated 9873 = SectorSpotLightAttenuated 9874 = SpotLightFlickerRandomAttenuated - 9875 = None // ZDRay light probe - 9876 = PointLightTraceAttenuated // ZDRay static point light - 9881 = SpotLightTraceAttenuated // ZDRay static spotlight - 9890 = None // ZDRayInfo + 9876 = PointLightTraceAttenuated // ZDRay lightmap point light + 9877 = PointLightPulseTraceAttenuated // ZDRay lightmap point light (pulsing) + 9878 = PointLightFlickerTraceAttenuated // ZDRay lightmap point light (flickering) + 9879 = PointLightFlickerRandomTraceAttenuated // ZDRay lightmap point light (random flickering) + 9881 = SpotLightTraceAttenuated // ZDRay lightmap spotlight + 9882 = SpotLightPulseTraceAttenuated // ZDRay lightmap spotlight (pulsing) + 9883 = SpotLightFlickerTraceAttenuated // ZDRay lightmap spotlight (flickering) + 9884 = SpotLightFlickerRandomTraceAttenuated // ZDRay lightmap spotlight (random flickering) + 9890 = None // ZDRayInfo + 9891 = Fogball 9982 = SecActEyesAboveC 9983 = SecActEyesBelowC 9988 = CustomSprite diff --git a/wadsrc/static/mapinfo/doom1.txt b/wadsrc/static/mapinfo/doom1.txt index 8d8be2295c..851171530f 100644 --- a/wadsrc/static/mapinfo/doom1.txt +++ b/wadsrc/static/mapinfo/doom1.txt @@ -408,7 +408,7 @@ map E4M1 lookup "HUSTR_E4M1" sky1 = "SKY4" cluster = 4 par = 165 - music = "$MUSIC_E3M4" + music = "$MUSIC_E4M1" } map E4M2 lookup "HUSTR_E4M2" @@ -420,7 +420,7 @@ map E4M2 lookup "HUSTR_E4M2" sky1 = "SKY4" cluster = 4 par = 255 - music = "$MUSIC_E3M2" + music = "$MUSIC_E4M2" } map E4M3 lookup "HUSTR_E4M3" @@ -432,7 +432,7 @@ map E4M3 lookup "HUSTR_E4M3" sky1 = "SKY4" cluster = 4 par = 135 - music = "$MUSIC_E3M3" + music = "$MUSIC_E4M3" } map E4M4 lookup "HUSTR_E4M4" @@ -444,7 +444,7 @@ map E4M4 lookup "HUSTR_E4M4" sky1 = "SKY4" cluster = 4 par = 150 - music = "$MUSIC_E1M5" + music = "$MUSIC_E4M4" } map E4M5 lookup "HUSTR_E4M5" @@ -456,7 +456,7 @@ map E4M5 lookup "HUSTR_E4M5" sky1 = "SKY4" cluster = 4 par = 180 - music = "$MUSIC_E2M7" + music = "$MUSIC_E4M5" } map E4M6 lookup "HUSTR_E4M6" @@ -470,7 +470,7 @@ map E4M6 lookup "HUSTR_E4M6" par = 390 e4m6special specialaction_opendoor - music = "$MUSIC_E2M4" + music = "$MUSIC_E4M6" } map E4M7 lookup "HUSTR_E4M7" @@ -482,7 +482,7 @@ map E4M7 lookup "HUSTR_E4M7" sky1 = "SKY4" cluster = 4 par = 135 - music = "$MUSIC_E2M6" + music = "$MUSIC_E4M7" } map E4M8 lookup "HUSTR_E4M8" @@ -498,7 +498,7 @@ map E4M8 lookup "HUSTR_E4M8" nosoundclipping e4m8special specialaction_lowerfloor - music = "$MUSIC_E2M5" + music = "$MUSIC_E4M8" needclustertext } @@ -511,7 +511,7 @@ map E4M9 lookup "HUSTR_E4M9" sky1 = "SKY4" cluster = 4 par = 180 - music = "$MUSIC_E1M9" + music = "$MUSIC_E4M9" } // Clusters (correspond with same-numbered episode) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index bfe6974001..270aff20c6 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -363,11 +363,7 @@ OptionMenu "OptionsMenu" protected Submenu "$OPTMNU_MULTIPLAYER", "MultiplayerMenu" Submenu "$OPTMNU_SYSTEM", "SystemMenu" StaticText " " - StaticText " " Submenu "$OS_TITLE", "os_Menu" - - StaticText " " - StaticText " " } //------------------------------------------------------------------------------------------- @@ -383,6 +379,22 @@ OptionMenu "InputMenu" protected Submenu "$OPTMNU_MOUSE", "MouseOptions" Submenu "$OPTMNU_JOYSTICK", "JoystickOptions" + IfOption(Windows) + { + StaticText "" + Option "$MISCMNU_MERGEKEYS", "k_mergekeys", "OnOff" + Option "$MISCMNU_WINFULLSCREENTOGGLE", "k_allowfullscreentoggle", "OnOff" + } + IfOption(Mac) + { + StaticText "" + Option "$MISCMNU_MACFULLSCREENTOGGLE", "k_allowfullscreentoggle", "OnOff" + } + + StaticText "" + Option "$CNTRLMNU_LAYOUT", "cl_defaultconfiguration", "Layouts" + SafeCommand "$OPTMNU_DEFAULTS", "resetb2defaults" + StaticText " " } @@ -396,6 +408,10 @@ OptionMenu "GameplayMenu" protected { Title "$OPTMNU_GAMEPLAY" + Option "$MISCMNU_NOCHEATS", "nocheats", "OnOff" + Option "$MISCMNU_ALLCHEATS", "allcheats", "OnOff" + Option "$MISCMNU_INTERSCROLL", "nointerscrollabort", "OffOn" + StaticText " " Submenu "$OPTMNU_GAMEPLAY", "GameplayOptions" Submenu "$OPTMNU_COMPATIBILITY", "CompatibilityOptions" Submenu "$OPTMNU_AUTOMAP", "AutomapOptions" @@ -581,9 +597,6 @@ OptionMenu "CustomizeControls" protected Submenu "$CNTRLMNU_OTHER" , "OtherControlsMenu" Submenu "$CNTRLMNU_POPUPS" , "StrifeControlsMenu" Submenu "$MNU_MULTIPLAYER" , "ChatControlsMenu" - StaticText "" - Option "$CNTRLMNU_LAYOUT", "cl_defaultconfiguration", "Layouts" - SafeCommand "$OPTMNU_DEFAULTS", "resetb2defaults" } OptionMenu "ActionControlsMenu" protected @@ -726,6 +739,7 @@ OptionMenu "OtherControlsMenu" protected Control "$CNTRLMNU_ADJUST_GAMMA" , "bumpgamma" StaticText "" + Control "$CNTRLMNU_OPEN_MAIN" , "menu_main" Control "$CNTRLMNU_OPEN_HELP" , "menu_help" Control "$CNTRLMNU_OPEN_SAVE" , "menu_save" Control "$CNTRLMNU_OPEN_LOAD" , "menu_load" @@ -914,6 +928,7 @@ OptionValue Wipes 1.0, "$OPTVAL_MELT" 2.0, "$OPTVAL_BURN" 3.0, "$OPTVAL_CROSSFADE" + 4.0, "$OPTVAL_FIZZLEFADE" } OptionValue Endoom @@ -956,41 +971,77 @@ OptionMenu "VideoOptions" protected { Title "$DSPLYMNU_TITLE" + Option "$VIDMNU_FULLSCREEN", "vid_fullscreen", "YesNo" + Option "$GLTEXMNU_TEXFILTER", gl_texture_filter, "FilterModes" // should only be on/off! + Option "$GLTEXMNU_ANISOTROPIC", gl_texture_filter_anisotropic, "Anisotropy" + Option "$GLPREFMNU_MULTISAMPLE", gl_multisample, "Multisample" + Option "$GLPREFMNU_SECLIGHTMODE", gl_lightmode, "LightingModes" + IfOption(SWRender) + { + Option "$VIDMNU_RENDERMODE", "vid_rendermode", "RenderMode" + } + Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" + Slider "$VIDMNU_MAXFPS", "vid_maxfps", 35, 500, 1 + StaticText " " + + Slider "$DSPLYMNU_GAMMA", "vid_gamma", 0.75, 3.0, 0.05, 2 + Slider "$DSPLYMNU_BRIGHTNESS", "vid_brightness", -0.8,0.8, 0.05,2 + Slider "$DSPLYMNU_CONTRAST", "vid_contrast", 0.1, 3.0, 0.1 + Slider "$DSPLYMNU_SATURATION", "vid_saturation", -3.0, 3.0, 0.25, 2 + + StaticText " " + ScaleSlider "$HUDMNU_UISCALE", "uiscale", 0.0, 8.0, 1.0, "$SCALEMNU_ADAPT" + Option "$SCALEMNU_HUDASPECT", "hud_aspectscale", "OnOff" + Option "$MSGMNU_SHOWMESSAGES", "show_messages", "OnOff" // needs to be on the top level because it can be disabled with a single keypress. + Submenu "$OPTMNU_VIDEO", "VideoModeMenu" + Submenu "$DSPLYMNU_APPEARANCE", "AppearOptions" + Submenu "$DSPLYMNU_ADVANCED", "AdvDisplayOptions" + Submenu "$OPTMNU_SPRITE", "SpriteOptions" + +} + +OptionMenu "AdvDisplayOptions" protected +{ + Title "$DSPLYMNU_ADVANCED" Submenu "$OPTMNU_LIGHT", "LightOptions" Submenu "$GLMNU_TEXOPT", "GLTextureGLOptions" - Submenu "$OPTMNU_SPRITE", "SpriteOptions" Submenu "$GLMNU_POSTPROCESS", "PostProcessMenu" Submenu "$GLPREFMNU_VRMODE", "VR3DMenu" IfOption(SWRender) { Submenu "$OPTMNU_SWRENDERER", "SWROptions" } +} - StaticText " " - Slider "$DSPLYMNU_SCREENSIZE", "screenblocks", 3.0, 12.0, 1.0, 0 +OptionMenu "AppearOptions" protected +{ + Title "$DSPLYMNU_APPEARANCE" - Slider "$DSPLYMNU_GAMMA", "vid_gamma", 0.75, 3.0, 0.05, 2 - Slider "$DSPLYMNU_BRIGHTNESS", "vid_brightness", -0.8,0.8, 0.05,2 - Slider "$DSPLYMNU_CONTRAST", "vid_contrast", 0.1, 3.0, 0.1 - Slider "$DSPLYMNU_SATURATION", "vid_saturation", -3.0, 3.0, 0.25, 2 - StaticText " " + Slider "$DSPLYMNU_SCREENSIZE", "screenblocks", 3.0, 12.0, 1.0, 0 Slider "$DSPLYMNU_FOV", "fov", 75.0, 120.0, 0.1, 1 StaticText " " Option "$DSPLYMNU_WIPETYPE", "wipetype", "Wipes" - Slider "$GLPREFMNU_MENUBLUR", gl_menu_blur, 0, 5.0, 0.5, 2 - StaticText " " Option "$DSPLYMNU_DEATHCAM", "r_deathcamera", "OnOff" Option "$DSPLYMNU_TELEZOOM", "telezoom", "OnOff" Slider "$DSPLYMNU_QUAKEINTENSITY", "r_quakeintensity", 0.0, 1.0, 0.05, 2 + Option "$MISCMNU_FVIEWBOB", "fviewbob", "OnOff" StaticText " " - IfOption(SWRender) - { - Option "$VIDMNU_RENDERMODE", "vid_rendermode", "RenderMode" - } - Option "$GLPREFMNU_RENDERQUALITY", gl_seamless, "Precision" + Option "$HUDMNU_CROSSHAIRON", "crosshairon", "OnOff" + Option "$HUDMNU_CROSSHAIR", "crosshair", "Crosshairs" + Option "$HUDMNU_FORCECROSSHAIR", "crosshairforce", "OnOff" + Option "$HUDMNU_GROWCROSSHAIR", "crosshairgrow", "OnOff" + ColorPicker "$HUDMNU_CROSSHAIRCOLOR", "crosshaircolor" + Option "$HUDMNU_CROSSHAIRHEALTH", "crosshairhealth", "CrosshairHealthTypes" + Slider "$HUDMNU_CROSSHAIRSCALE", "crosshairscale", 0.0, 2.0, 0.05, 2 + StaticText " " + Option "$MISCMNU_CLEANMENU", "m_cleanscale", "OffOn" + Option "$MISCMNU_CLEANSTAT", "wi_cleantextscale", "OnOff" + Option "$MISCMNU_WIPERCENT", "wi_percents", "OnOff" + } + OptionMenu "SWROptions" protected { Title "$OPTMNU_SWRENDERER" @@ -1019,9 +1070,9 @@ OptionMenu "LightOptions" protected Option "$GLLIGHTMNU_LIGHTSPRITES", gl_light_sprites, "YesNo" Option "$GLLIGHTMNU_LIGHTPARTICLES", gl_light_particles, "YesNo" StaticText " " - Option "$GLLIGHTMNU_LIGHTSHADOWMAP", gl_light_shadowmap, "YesNo" + Option "$GLLIGHTMNU_LIGHTSHADOWS", gl_light_shadows, "ShadowMode" + Option "$GLLIGHTMNU_LIGHTSHADOWFILTER", gl_light_shadow_filter, "ShadowFilter" Option "$GLLIGHTMNU_LIGHTSHADOWMAPQUALITY", gl_shadowmap_quality, "ShadowMapQuality" - Option "$GLLIGHTMNU_LIGHTSHADOWMAPFILTER", gl_shadowmap_filter, "ShadowMapFilter" StaticText " " Option "$GLPREFMNU_SWLMBANDED", gl_bandedswlight, "OnOff" Option "$GLPREFMNU_FOGFORCEFULLBRIGHT", gl_brightfog, "YesNo" @@ -1040,6 +1091,7 @@ OptionMenu "SpriteOptions" protected { Title "$OPTMNU_SPRITE" + Option "$DSPLYMNU_NOMONSTERINTERPOLATION", "nomonsterinterpolation", "NoYes" Option "$DSPLYMNU_SPRITESHADOW", "r_actorspriteshadow", "SpriteShadowModes" Option "$DSPLYMNU_OLDTRANS", "r_vanillatrans", "VanillaTrans" Option "$DSPLYMNU_ROCKETTRAILS", "cl_rockettrails", "RocketTrailTypes" @@ -1049,7 +1101,7 @@ OptionMenu "SpriteOptions" protected Slider "$DSPLYMNU_MAXDECALS", "cl_maxdecals", 0, 10000, 100, 0 Option "$DSPLYMNU_PLAYERSPRITES", "r_drawplayersprites", "OnOff" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" - + StaticText "$DSPLYMNU_GLOPT" Option "$GLPREFMNU_SPRCLIP", gl_spriteclip, "SpriteclipModes" Option "$GLPREFMNU_SPRBLEND", gl_sprite_blend, "OnOff" Option "$GLPREFMNU_FUZZSTYLE", gl_fuzztype, "FuzzStyle" @@ -1129,21 +1181,6 @@ OptionValue ZDoomStrife OptionMenu "HUDOptions" protected { Title "$HUDMNU_TITLE" - Submenu "$HUDMNU_SCALEOPT", "ScalingOptions" - Submenu "$HUDMNU_ALTHUD", "AltHudOptions" - Submenu "$HUDMNU_MESSAGE", "MessageOptions" - Submenu "$HUDMNU_FLASH", "FlashOptions" - Submenu "$DSPLYMNU_SCOREBOARD", "ScoreboardOptions" - Submenu "$HUDMNU_FONTOPTIONS", "FontOptions" - StaticText " " - Option "$HUDMNU_CROSSHAIRON", "crosshairon", "OnOff" - Option "$HUDMNU_CROSSHAIR", "crosshair", "Crosshairs" - Option "$HUDMNU_FORCECROSSHAIR", "crosshairforce", "OnOff" - Option "$HUDMNU_GROWCROSSHAIR", "crosshairgrow", "OnOff" - ColorPicker "$HUDMNU_CROSSHAIRCOLOR", "crosshaircolor" - Option "$HUDMNU_CROSSHAIRHEALTH", "crosshairhealth", "CrosshairHealthTypes" - Slider "$HUDMNU_CROSSHAIRSCALE", "crosshairscale", 0.0, 2.0, 0.05, 2 - StaticText " " Option "$HUDMNU_NAMETAGS", "displaynametags", "DisplayTagsTypes" Option "$HUDMNU_NAMETAGCOLOR", "nametagcolor", "TextColors", "displaynametags" Option "$HUDMNU_OLDOUCH", "st_oldouch", "OnOff" @@ -1155,6 +1192,13 @@ OptionMenu "HUDOptions" protected StaticText " " Slider "$DSPLYMNU_MENUDIM", "dimamount", 0, 1.0, 0.05, 2 ColorPicker "$DSPLYMNU_DIMCOLOR", "dimcolor" + StaticText " " + Submenu "$HUDMNU_SCALEOPT", "ScalingOptions" + Submenu "$HUDMNU_ALTHUD", "AltHudOptions" + Submenu "$HUDMNU_MESSAGE", "MessageOptions" + Submenu "$HUDMNU_FLASH", "FlashOptions" + Submenu "$DSPLYMNU_SCOREBOARD", "ScoreboardOptions" + Submenu "$HUDMNU_FONTOPTIONS", "FontOptions" } @@ -1257,6 +1301,7 @@ OptionMenu "AltHUDOptions" protected Option "$ALTHUDMNU_AMMOORDER", "hud_ammo_order", "AltHUDAmmoOrder" Slider "$ALTHUDMNU_AMMORED", "hud_ammo_red", 0, 100, 1, 0 Slider "$ALTHUDMNU_AMMOYELLOW", "hud_ammo_yellow", 0, 100, 1, 0 + Option "$ALTHUDMNU_SWAPHEALTHARMOR", "hud_swaphealtharmor", "OnOff" Slider "$ALTHUDMNU_HEALTHRED", "hud_health_red", 0, 100, 1, 0 Slider "$ALTHUDMNU_HEALTHYELLOW", "hud_health_yellow", 0, 100, 1, 0 Slider "$ALTHUDMNU_HEALTHGREEN", "hud_health_green", 0, 100, 1, 0 @@ -1306,21 +1351,10 @@ OptionMenu "MiscOptions" protected { Title "$MISCMNU_TITLE" //Indent 220 - IfOption(Windows) - { - Option "$MISCMNU_MERGEKEYS", "k_mergekeys", "OnOff" - Option "$MISCMNU_WINFULLSCREENTOGGLE", "k_allowfullscreentoggle", "OnOff" - } - IfOption(Mac) - { - Option "$MISCMNU_MACFULLSCREENTOGGLE", "k_allowfullscreentoggle", "OnOff" - } Option "$MISCMNU_QUERYIWAD", "queryiwad", "OnOff" StaticText " " - Option "$MISCMNU_FVIEWBOB", "fviewbob", "OnOff" - Option "$MISCMNU_NOCHEATS", "nocheats", "OnOff" - Option "$MISCMNU_ALLCHEATS", "allcheats", "OnOff" Option "$MISCMNU_ENABLEAUTOSAVES", "disableautosave", "Autosave" + Option "$MISCMNU_RESTARTONDEATH", "cl_restartondeath", "OnOff" Option "$MISCMNU_SAVELOADCONFIRMATION", "saveloadconfirmation", "OnOff" Slider "$MISCMNU_AUTOSAVECOUNT", "autosavecount", 1, 20, 1, 0 Option "$MISCMNU_QUICKSAVEROTATION", "quicksaverotation", "OnOff" @@ -1328,7 +1362,6 @@ OptionMenu "MiscOptions" protected Option "$MISCMNU_DEHLOAD", "dehload", "dehopt" Option "$MISCMNU_ENABLESCRIPTSCREENSHOTS", "enablescriptscreenshot", "OnOff" Option "$MISCMNU_SETSLOTSTRICT", "setslotstrict", "YesNo" - Option "$MISCMNU_INTERSCROLL", "nointerscrollabort", "OffOn" Option "$MISCMNU_PAUSEINBACKGROUND", "i_pauseinbackground", "OnOff" StaticText " " Option "$MISCMNU_CACHENODES", "gl_cachenodes", "OnOff" @@ -1343,11 +1376,6 @@ OptionMenu "MiscOptions" protected StaticText " " Option "$DSPLYMNU_SHOWENDOOM", "showendoom", "Endoom" - StaticText " " - Option "$MISCMNU_CLEANMENU", "m_cleanscale", "OffOn" - Option "$MISCMNU_CLEANSTAT", "wi_cleantextscale", "OnOff" - Option "$MISCMNU_WIPERCENT", "wi_percents", "OnOff" - StaticText " " Option "$MISCMNU_ALWAYSTALLY", "sv_alwaystally", "AlwaysTally" @@ -1517,10 +1545,6 @@ OptionMenu MapColorMenu protected Title "$MAPCOLORMNU_TITLE" SafeCommand "$MAPCOLORMNU_DEFAULTMAPCOLORS", "am_restorecolors" StaticText " " - Submenu "$MAPCOLORMNU_CHEATMODE", "MapColorMenuCheats" - Submenu "$MAPCOLORMNU_OVERLAY", "MapColorMenuOverlay" - Submenu "$MAPCOLORMNU_OVCHEATMODE", "MapColorMenuCheatsOverlay" - StaticText " " ColorPicker "$MAPCOLORMNU_BACKCOLOR", "am_backcolor" ColorPicker "$MAPCOLORMNU_YOURCOLOR", "am_yourcolor" ColorPicker "$MAPCOLORMNU_WALLCOLOR", "am_wallcolor" @@ -1537,6 +1561,10 @@ OptionMenu MapColorMenu protected ColorPicker "$MAPCOLORMNU_UNEXPLOREDSECRETCOLOR", "am_unexploredsecretcolor" ColorPicker "$MAPCOLORMNU_SPECIALWALLCOLOR", "am_specialwallcolor" ColorPicker "$MAPCOLORMNU_PORTAL", "am_portalcolor" + StaticText " " + Submenu "$MAPCOLORMNU_CHEATMODE", "MapColorMenuCheats" + Submenu "$MAPCOLORMNU_OVERLAY", "MapColorMenuOverlay" + Submenu "$MAPCOLORMNU_OVCHEATMODE", "MapColorMenuCheatsOverlay" } OptionMenu MapColorMenuCheats protected @@ -1565,6 +1593,7 @@ OptionMenu MapColorMenuOverlay protected ColorPicker "$MAPCOLORMNU_INTRALEVELCOLOR", "am_ovtelecolor" ColorPicker "$MAPCOLORMNU_INTERLEVELCOLOR", "am_ovinterlevelcolor" ColorPicker "$MAPCOLORMNU_SECRETSECTORCOLOR", "am_ovsecretsectorcolor" + ColorPicker "$MAPCOLORMNU_UNEXPLOREDSECRETCOLOR", "am_ovunexploredsecretcolor" ColorPicker "$MAPCOLORMNU_SPECIALWALLCOLOR", "am_ovspecialwallcolor" ColorPicker "$MAPCOLORMNU_PORTAL", "am_ovportalcolor" } @@ -1729,6 +1758,7 @@ OptionMenu GameplayOptions protected StaticText " " Option "$GMPLYMNU_SMARTAUTOAIM", "sv_smartaim", "SmartAim" StaticText " " + Option "$GMPLYMNU_PISTOLSTART", "sv_pistolstart", "YesNo" Option "$GMPLYMNU_FALLINGDAMAGE", "sv_fallingdamage", "FallingDM" Option "$GMPLYMNU_DROPWEAPON", "sv_weapondrop", "YesNo" Option "$GMPLYMNU_DOUBLEAMMO", "sv_doubleammo", "YesNo" @@ -1790,6 +1820,8 @@ OptionMenu CoopOptions protected Title "$GMPLYMNU_COOPERATIVE" Option "$GMPLYMNU_MULTIPLAYERTHINGS", "sv_nothingspawn", "NoYes" + Option "$GMPLYMNU_COOPTHINGS", "sv_nocoopthings", "NoYes" + Option "$GMPLYMNU_COOPITEMS", "sv_nocoopitems", "NoYes" Option "$GMPLYMNU_MULTIPLAYERWEAPONS", "sv_noweaponspawn", "NoYes" Option "$GMPLYMNU_LOSEINVENTORY", "sv_cooploseinventory", "YesNo" Option "$GMPLYMNU_KEEPKEYS", "sv_cooplosekeys", "NoYes" @@ -1800,6 +1832,10 @@ OptionMenu CoopOptions protected Option "$GMPLYMNU_LOSEHALFAMMO", "sv_coophalveammo", "YesNo" Option "$GMPLYMNU_SPAWNWHEREDIED", "sv_samespawnspot", "YesNo" Option "$GMPLYMNU_NOPLAYERCLIP", "sv_noplayerclip", "YesNo" + Option "$GMPLYMNU_SHAREKEYS", "sv_coopsharekeys", "YesNo" + Option "$GMPLYMNU_LOCALITEMS", "sv_localitems", "YesNo" + Option "$GMPLYMNU_NOLOCALDROP", "sv_nolocaldrops", "YesNo" + Option "$GMPLYMNU_REMEMBERWEAP", "sv_rememberlastweapon", "YesNo" Class "GameplayMenu" } @@ -2363,13 +2399,15 @@ OptionValue MaxFps 200, "$OPTVAL_200FPS" } +OptionString VKDevices +{ + // filled in by the display code +} OptionMenu VideoModeMenu protected { Title "$VIDMNU_TITLE" - Option "$VIDMNU_FULLSCREEN", "vid_fullscreen", "YesNo" - IfOption(Mac) { Option "$VIDMNU_HIDPI", "vid_hidpi", "YesNo" @@ -2380,17 +2418,10 @@ OptionMenu VideoModeMenu protected Option "$VIDMNU_SCALEMODE", "vid_scalemode", "ScaleModes" Slider "$VIDMNU_SCALEFACTOR", "vid_scalefactor", 0.25, 2.0, 0.25, 2 - StaticText " " - Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" - Slider "$VIDMNU_MAXFPS", "vid_maxfps", 35, 500, 1 - StaticText " " Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn" - Option "$DSPLYMNU_NOMONSTERINTERPOLATION", "nomonsterinterpolation", "NoYes" - - StaticText " " - Option "$GLPREFMNU_MULTISAMPLE", gl_multisample, "Multisample" Option "$VKMNU_HDR", "vk_hdr", "OnOff" + Option "$VKMNU_DEVICE", "vk_device", "VKDevices" StaticText "" StaticText "$VIDMNU_CUSTOMRES" @@ -2403,10 +2434,6 @@ OptionMenu VideoModeMenu protected StaticText "" SubMenu "$VIDMNU_RESPRESET", CustomResolutionMenu - - StaticText "" - StaticText "" - TextField "$VKMNU_DEVICE", vk_device } OptionMenu CustomResolutionMenu protected @@ -2533,6 +2560,7 @@ OptionValue "FXAAQuality" OptionValue "Anisotropy" { + 0, "$OPTVAL_DEFAULT" 1, "$OPTVAL_OFF" 2, "$OPTVAL_2X" 4, "$OPTVAL_4X" @@ -2558,14 +2586,9 @@ OptionValue "Colormaps" OptionValue "LightingModes" { - 0, "$OPTVAL_STANDARD" - 1, "$OPTVAL_BRIGHT" - 2, "$OPTVAL_DOOM" - 3, "$OPTVAL_DARK" - 4, "$OPTVAL_LEGACY" - 5, "$OPTVAL_BUILD" - 8, "$OPTVAL_SOFTWARE" - 16, "$OPTVAL_VANILLA" + 0, "$OPTVAL_CLASSIC" + 1, "$OPTVAL_SOFTWARE" + 2, "$OPTVAL_VANILLA" } OptionValue "Precision" @@ -2675,7 +2698,14 @@ OptionValue ShadowMapQuality 1024, "1024" } -OptionValue ShadowMapFilter +OptionValue ShadowMode +{ + 0, "$OPTVAL_NONE" + 1, "$OPTVAL_SHADOWMAP" + 2, "$OPTVAL_RAYTRACE" +} + +OptionValue ShadowFilter { 0, "$OPTVAL_NEAREST" 1, "$OPTVAL_PCF_LOW" @@ -2877,15 +2907,17 @@ OptionValue "os_isanyof_values" 1, "$OS_ANY" } -/*======================================= - * - * Vulkan Menu - * - *=======================================*/ - OptionValue "SpriteShadowModes" { 0, "$OPTVAL_OFF" 1, "$OPTVAL_DEFAULT" 2, "$OPTVAL_SPRSHADALWAYS" } + +// Add dummy entries for the old simple menus since some mods try to add items to them +OptionMenu "OptionsMenuSimple" protected {} +OptionMenu SoundOptionsSimple protected {} +OptionMenu VideoOptionsSimple protected {} +OptionMenu ScalingOptionsSimple protected {} +OptionMenu MiscOptionsSimple protected {} +OptionMenu "MouseOptionsSimple" protected {} diff --git a/wadsrc/static/newmenufont.license b/wadsrc/static/newmenufont.license new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/wadsrc/static/newmenufont.license @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall 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. diff --git a/wadsrc/static/newmenufont.ttf b/wadsrc/static/newmenufont.ttf new file mode 100644 index 0000000000..9f0c71b70a Binary files /dev/null and b/wadsrc/static/newmenufont.ttf differ diff --git a/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl b/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl new file mode 100644 index 0000000000..e23406f128 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl @@ -0,0 +1,69 @@ + +layout(set = 0, binding = 0) uniform Uniforms +{ + vec3 SunDir; + float Padding1; + vec3 SunColor; + float SunIntensity; +}; + +struct SurfaceInfo +{ + vec3 Normal; + float Sky; + uint PortalIndex; + int TextureIndex; + float Alpha; + float Padding0; + uint LightStart; + uint LightEnd; + uint Padding1; + uint Padding2; +}; + +struct PortalInfo +{ + mat4 Transformation; +}; + +struct LightInfo +{ + vec3 Origin; + float Padding0; + vec3 RelativeOrigin; + float Padding1; + float Radius; + float Intensity; + float InnerAngleCos; + float OuterAngleCos; + vec3 SpotDir; + float SourceRadius; + vec3 Color; + float Padding3; +}; + +layout(set = 0, binding = 1) buffer SurfaceIndexBuffer { uint surfaceIndices[]; }; +layout(set = 0, binding = 2) buffer SurfaceBuffer { SurfaceInfo surfaces[]; }; +layout(set = 0, binding = 3) buffer LightBuffer { LightInfo lights[]; }; +layout(set = 0, binding = 4) buffer LightIndexBuffer { int lightIndexes[]; }; +layout(set = 0, binding = 5) buffer PortalBuffer { PortalInfo portals[]; }; + +struct LightmapRaytracePC +{ + int SurfaceIndex; + int Padding0; + int Padding1; + int Padding2; + vec3 WorldToLocal; + float TextureSize; + vec3 ProjLocalToU; + float Padding3; + vec3 ProjLocalToV; + float Padding4; + float TileX; + float TileY; + float TileWidth; + float TileHeight; +}; + +layout(std430, set = 0, binding = 6) buffer ConstantsBuffer { LightmapRaytracePC constants[]; }; diff --git a/wadsrc/static/shaders/lightmap/binding_raytrace.glsl b/wadsrc/static/shaders/lightmap/binding_raytrace.glsl new file mode 100644 index 0000000000..88c9eeefe6 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/binding_raytrace.glsl @@ -0,0 +1,40 @@ + +#if defined(USE_RAYQUERY) + +layout(set = 1, binding = 0) uniform accelerationStructureEXT acc; + +#else + +struct CollisionNode +{ + vec3 center; + float padding1; + vec3 extents; + float padding2; + int left; + int right; + int element_index; + int padding3; +}; + +layout(std430, set = 1, binding = 0) buffer NodeBuffer +{ + int nodesRoot; + int nodebufferPadding1; + int nodebufferPadding2; + int nodebufferPadding3; + CollisionNode nodes[]; +}; + +#endif + +struct SurfaceVertex // Note: this must always match the FFlatVertex struct +{ + vec3 pos; + float lindex; + vec2 uv; + vec2 luv; +}; + +layout(std430, set = 1, binding = 1) buffer VertexBuffer { SurfaceVertex vertices[]; }; +layout(std430, set = 1, binding = 2) buffer ElementBuffer { int elements[]; }; diff --git a/wadsrc/static/shaders/lightmap/binding_textures.glsl b/wadsrc/static/shaders/lightmap/binding_textures.glsl new file mode 100644 index 0000000000..3bc436ef60 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/binding_textures.glsl @@ -0,0 +1,2 @@ + +layout(set = 2, binding = 0) uniform sampler2D textures[]; diff --git a/wadsrc/static/shaders/lightmap/frag_blur.glsl b/wadsrc/static/shaders/lightmap/frag_blur.glsl new file mode 100644 index 0000000000..26c96bf825 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/frag_blur.glsl @@ -0,0 +1,32 @@ + +layout(set = 0, binding = 0) uniform sampler2D tex; + +layout(location = 0) in vec2 TexCoord; +layout(location = 0) out vec4 fragcolor; + +vec4 centerFragColor; + +vec4 clampedSample(vec4 f) +{ + return f != vec4(0, 0, 0, 0) ? f : centerFragColor; +} + +void main() +{ + ivec2 size = textureSize(tex, 0); + vec2 texCoord = gl_FragCoord.xy / vec2(size); + + centerFragColor = textureOffset(tex, texCoord, ivec2(0, 0)); + +#if defined(BLUR_HORIZONTAL) + fragcolor = + centerFragColor * 0.5 + + clampedSample(textureOffset(tex, texCoord, ivec2( 1, 0))) * 0.25 + + clampedSample(textureOffset(tex, texCoord, ivec2(-1, 0))) * 0.25; +#else + fragcolor = + centerFragColor * 0.5 + + clampedSample(textureOffset(tex, texCoord, ivec2(0, 1))) * 0.25 + + clampedSample(textureOffset(tex, texCoord, ivec2(0,-1))) * 0.25; +#endif +} diff --git a/wadsrc/static/shaders/lightmap/frag_copy.glsl b/wadsrc/static/shaders/lightmap/frag_copy.glsl new file mode 100644 index 0000000000..77f683baba --- /dev/null +++ b/wadsrc/static/shaders/lightmap/frag_copy.glsl @@ -0,0 +1,10 @@ + +layout(set = 0, binding = 0) uniform sampler2D Tex; + +layout(location = 0) in vec2 TexCoord; +layout(location = 0) out vec4 FragColor; + +void main() +{ + FragColor = texture(Tex, TexCoord); +} diff --git a/wadsrc/static/shaders/lightmap/frag_raytrace.glsl b/wadsrc/static/shaders/lightmap/frag_raytrace.glsl new file mode 100644 index 0000000000..6607b11421 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/frag_raytrace.glsl @@ -0,0 +1,46 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +layout(location = 0) centroid in vec3 worldpos; +layout(location = 1) in flat int InstanceIndex; + +layout(location = 0) out vec4 fragcolor; + +void main() +{ + int SurfaceIndex = constants[InstanceIndex].SurfaceIndex; + uint LightStart = surfaces[SurfaceIndex].LightStart; + uint LightEnd = surfaces[SurfaceIndex].LightEnd; + + vec3 normal = surfaces[SurfaceIndex].Normal; + vec3 origin = worldpos; + +#if defined(USE_SUNLIGHT) + vec3 incoming = TraceSunLight(origin, normal); +#else + vec3 incoming = vec3(0.0); +#endif + + for (uint j = LightStart; j < LightEnd; j++) + { + incoming += TraceLight(origin, normal, lights[lightIndexes[j]], 0.0); + } + +#if defined(USE_BOUNCE) + incoming += TraceBounceLight(origin, normal); +#endif + +#if defined(USE_AO) + incoming.rgb *= TraceAmbientOcclusion(origin, normal); +#endif + + fragcolor = vec4(incoming, 1.0); +} diff --git a/wadsrc/static/shaders/lightmap/frag_resolve.glsl b/wadsrc/static/shaders/lightmap/frag_resolve.glsl new file mode 100644 index 0000000000..886778ed23 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/frag_resolve.glsl @@ -0,0 +1,46 @@ + +layout(set = 0, binding = 0) uniform sampler2DMS tex; + +layout(location = 0) in vec2 TexCoord; +layout(location = 0) out vec4 fragcolor; + +vec4 samplePixel(ivec2 pos, int count) +{ + vec4 c = vec4(0.0); + for (int i = 0; i < count; i++) + { + c += texelFetch(tex, pos, i); + } + if (c.a > 0.0) + c /= c.a; + return c; +} + +void main() +{ + int count = textureSamples(tex); + ivec2 size = textureSize(tex); + ivec2 pos = ivec2(gl_FragCoord.xy); + + vec4 c = samplePixel(pos, count); + if (c.a == 0.0) + { + for (int y = -1; y <= 1; y++) + { + for (int x = -1; x <= 1; x++) + { + if (x != 0 || y != 0) + { + ivec2 pos2; + pos2.x = clamp(pos.x + x, 0, size.x - 1); + pos2.y = clamp(pos.y + y, 0, size.y - 1); + c += samplePixel(pos2, count); + } + } + } + if (c.a > 0.0) + c /= c.a; + } + + fragcolor = c; +} diff --git a/wadsrc/static/shaders/lightmap/montecarlo.glsl b/wadsrc/static/shaders/lightmap/montecarlo.glsl new file mode 100644 index 0000000000..9a84d0af9a --- /dev/null +++ b/wadsrc/static/shaders/lightmap/montecarlo.glsl @@ -0,0 +1,30 @@ + +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10f; // / 0x100000000 +} + +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i) / float(N), RadicalInverse_VdC(i)); +} + +vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi) +{ + const float goldenAngle = radians(180.0) * (3.0 - sqrt(5.0)); + float sampleIndexF = float(sampleIndex); + float sampleCountF = float(sampleCount); + + float r = sqrt((sampleIndexF + 0.5) / sampleCountF); // Assuming index and count are positive + float theta = sampleIndexF * goldenAngle + phi; + + float sine = sin(theta); + float cosine = cos(theta); + + return vec2(cosine, sine) * r; +} diff --git a/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl b/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl new file mode 100644 index 0000000000..83f0f514a8 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl @@ -0,0 +1,281 @@ + +struct TraceResult +{ + float t; + vec3 primitiveWeights; + int primitiveIndex; +}; + +#if defined(USE_RAYQUERY) + +TraceResult TraceFirstHit(vec3 origin, float tmin, vec3 dir, float tmax) +{ + TraceResult result; + + rayQueryEXT rayQuery; + rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, dir, tmax); + + while(rayQueryProceedEXT(rayQuery)) + { + if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCommittedIntersectionTriangleEXT) + { + rayQueryConfirmIntersectionEXT(rayQuery); + } + } + + if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT) + { + result.t = rayQueryGetIntersectionTEXT(rayQuery, true); + + result.primitiveWeights.xy = rayQueryGetIntersectionBarycentricsEXT(rayQuery, true); + result.primitiveWeights.z = 1.0 - result.primitiveWeights.x - result.primitiveWeights.y; + + result.primitiveIndex = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true); + } + else + { + result.t = tmax; + result.primitiveIndex = -1; + } + + return result; +} + +/* +bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax) +{ + rayQueryEXT rayQuery; + rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, dir, tmax); + while(rayQueryProceedEXT(rayQuery)) { } + return rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT; +} +*/ + +#else + +struct RayBBox +{ + vec3 start, end; + vec3 c, w, v; +}; + +RayBBox create_ray(vec3 ray_start, vec3 ray_end) +{ + RayBBox ray; + ray.start = ray_start; + ray.end = ray_end; + ray.c = (ray_start + ray_end) * 0.5; + ray.w = ray_end - ray.c; + ray.v = abs(ray.w); + return ray; +} + +bool overlap_bv_ray(RayBBox ray, int a) +{ + vec3 v = ray.v; + vec3 w = ray.w; + vec3 h = nodes[a].extents; + vec3 c = ray.c - nodes[a].center; + + if (abs(c.x) > v.x + h.x || + abs(c.y) > v.y + h.y || + abs(c.z) > v.z + h.z) + { + return false; + } + + if (abs(c.y * w.z - c.z * w.y) > h.y * v.z + h.z * v.y || + abs(c.x * w.z - c.z * w.x) > h.x * v.z + h.z * v.x || + abs(c.x * w.y - c.y * w.x) > h.x * v.y + h.y * v.x) + { + return false; + } + + return true; +} + +#define FLT_EPSILON 1.192092896e-07F // smallest such that 1.0+FLT_EPSILON != 1.0 + +float intersect_triangle_ray(RayBBox ray, int a, out float barycentricB, out float barycentricC) +{ + int start_element = nodes[a].element_index; + + vec3 p[3]; + p[0] = vertices[elements[start_element]].pos.xyz; + p[1] = vertices[elements[start_element + 1]].pos.xyz; + p[2] = vertices[elements[start_element + 2]].pos.xyz; + + // Moeller-Trumbore ray-triangle intersection algorithm: + + vec3 D = ray.end - ray.start; + + // Find vectors for two edges sharing p[0] + vec3 e1 = p[1] - p[0]; + vec3 e2 = p[2] - p[0]; + + // Begin calculating determinant - also used to calculate u parameter + vec3 P = cross(D, e2); + float det = dot(e1, P); + + // Backface check + if (det < 0.0f) + return 1.0f; + + // If determinant is near zero, ray lies in plane of triangle + if (det > -FLT_EPSILON && det < FLT_EPSILON) + return 1.0f; + + float inv_det = 1.0f / det; + + // Calculate distance from p[0] to ray origin + vec3 T = ray.start - p[0]; + + // Calculate u parameter and test bound + float u = dot(T, P) * inv_det; + + // Check if the intersection lies outside of the triangle + if (u < 0.f || u > 1.f) + return 1.0f; + + // Prepare to test v parameter + vec3 Q = cross(T, e1); + + // Calculate V parameter and test bound + float v = dot(D, Q) * inv_det; + + // The intersection lies outside of the triangle + if (v < 0.f || u + v > 1.f) + return 1.0f; + + float t = dot(e2, Q) * inv_det; + if (t <= FLT_EPSILON) + return 1.0f; + + // Return hit location on triangle in barycentric coordinates + barycentricB = u; + barycentricC = v; + return t; +} + +bool is_leaf(int node_index) +{ + return nodes[node_index].element_index != -1; +} + +/* +bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax) +{ + if (tmax <= 0.0f) + return false; + + RayBBox ray = create_ray(origin, origin + dir * tmax); + tmin /= tmax; + + int stack[64]; + int stackIndex = 0; + stack[stackIndex++] = nodesRoot; + do + { + int a = stack[--stackIndex]; + if (overlap_bv_ray(ray, a)) + { + if (is_leaf(a)) + { + float baryB, baryC; + float t = intersect_triangle_ray(ray, a, baryB, baryC); + if (t >= tmin && t < 1.0) + { + return true; + } + } + else + { + stack[stackIndex++] = nodes[a].right; + stack[stackIndex++] = nodes[a].left; + } + } + } while (stackIndex > 0); + return false; +} +*/ + +struct TraceHit +{ + float fraction; + int triangle; + float b; + float c; +}; + +TraceHit find_first_hit(RayBBox ray) +{ + TraceHit hit; + hit.fraction = 1.0; + hit.triangle = -1; + hit.b = 0.0; + hit.c = 0.0; + + int stack[64]; + int stackIndex = 0; + stack[stackIndex++] = nodesRoot; + do + { + int a = stack[--stackIndex]; + if (overlap_bv_ray(ray, a)) + { + if (is_leaf(a)) + { + float baryB, baryC; + float t = intersect_triangle_ray(ray, a, baryB, baryC); + if (t < hit.fraction) + { + hit.fraction = t; + hit.triangle = nodes[a].element_index / 3; + hit.b = baryB; + hit.c = baryC; + } + } + else + { + stack[stackIndex++] = nodes[a].right; + stack[stackIndex++] = nodes[a].left; + } + } + } while (stackIndex > 0); + return hit; +} + +TraceResult TraceFirstHit(vec3 origin, float tmin, vec3 dir, float tmax) +{ + TraceResult result; + + // Perform segmented tracing to keep the ray AABB box smaller + vec3 ray_start = origin; + vec3 ray_end = origin + dir * tmax; + vec3 ray_dir = dir; + float tracedist = tmax; + float segmentlen = max(200.0, tracedist / 20.0); + for (float t = 0.0; t < tracedist; t += segmentlen) + { + float segstart = t; + float segend = min(t + segmentlen, tracedist); + + RayBBox ray = create_ray(ray_start + ray_dir * segstart, ray_start + ray_dir * segend); + TraceHit hit = find_first_hit(ray); + if (hit.fraction < 1.0) + { + result.t = mix(segstart, segend, hit.fraction); + result.primitiveWeights.x = hit.b; + result.primitiveWeights.y = hit.c; + result.primitiveWeights.z = 1.0 - hit.b - hit.c; + result.primitiveIndex = hit.triangle; + return result; + } + } + + result.t = tracedist; + result.primitiveIndex = -1; + return result; +} + +#endif diff --git a/wadsrc/static/shaders/lightmap/trace_ambient_occlusion.glsl b/wadsrc/static/shaders/lightmap/trace_ambient_occlusion.glsl new file mode 100644 index 0000000000..76e64aab24 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/trace_ambient_occlusion.glsl @@ -0,0 +1,59 @@ + +#include + +float TraceAORay(vec3 origin, float tmin, vec3 dir, float tmax); + +float TraceAmbientOcclusion(vec3 origin, vec3 normal) +{ + const float minDistance = 0.01; + const float aoDistance = 100; + const int SampleCount = 128; + + vec3 N = normal; + vec3 up = abs(N.x) < abs(N.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + float ambience = 0.0f; + for (uint i = 0; i < SampleCount; i++) + { + vec2 Xi = Hammersley(i, SampleCount); + vec3 H = normalize(vec3(Xi.x * 2.0f - 1.0f, Xi.y * 2.0f - 1.0f, 1.5 - length(Xi))); + vec3 L = H.x * tangent + H.y * bitangent + H.z * N; + ambience += clamp(TraceAORay(origin, minDistance, L, aoDistance) / aoDistance, 0.0, 1.0); + } + return ambience / float(SampleCount); +} + +float TraceAORay(vec3 origin, float tmin, vec3 dir, float tmax) +{ + float tcur = 0.0; + for (int i = 0; i < 3; i++) + { + TraceResult result = TraceFirstHit(origin, tmin, dir, tmax - tcur); + if (result.primitiveIndex == -1) + return tmax; + + SurfaceInfo surface = GetSurface(result.primitiveIndex); + + // Stop if hit sky portal + if (surface.Sky > 0.0) + return tmax; + + // Stop if opaque surface + if (surface.PortalIndex == 0 /*surface.TextureIndex == 0*/) + { + return tcur + result.t; + } + + // Move to surface hit point + origin += dir * result.t; + tcur += result.t; + if (tcur >= tmax) + return tmax; + + // Move through the portal, if any + TransformRay(surface.PortalIndex, origin, dir); + } + return tmax; +} diff --git a/wadsrc/static/shaders/lightmap/trace_bounce.glsl b/wadsrc/static/shaders/lightmap/trace_bounce.glsl new file mode 100644 index 0000000000..09b14b310a --- /dev/null +++ b/wadsrc/static/shaders/lightmap/trace_bounce.glsl @@ -0,0 +1,45 @@ + +#include + +vec3 TraceBounceLight(vec3 origin, vec3 normal) +{ + const float minDistance = 0.01; + const float maxDistance = 1000.0; + const int SampleCount = 8; + + vec3 N = normal; + vec3 up = abs(N.x) < abs(N.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + vec3 incoming = vec3(0.0); + + for (uint i = 0; i < SampleCount; i++) + { + vec2 Xi = Hammersley(i, SampleCount); + vec3 H = normalize(vec3(Xi.x * 2.0f - 1.0f, Xi.y * 2.0f - 1.0f, 1.5 - length(Xi))); + vec3 L = H.x * tangent + H.y * bitangent + H.z * N; + + TraceResult result = TraceFirstHit(origin, minDistance, L, maxDistance); + + // We hit nothing. + if (result.primitiveIndex == -1) + continue; + + SurfaceInfo surface = GetSurface(result.primitiveIndex); + uint LightStart = surface.LightStart; + uint LightEnd = surface.LightEnd; + vec3 surfacepos = origin + L * result.t; + + float angleAttenuation = max(dot(normal, L), 0.0); + +#if defined(USE_SUNLIGHT) + incoming += TraceSunLight(surfacepos, surface.Normal) * angleAttenuation; +#endif + + for (uint j = LightStart; j < LightEnd; j++) + { + incoming += TraceLight(surfacepos, surface.Normal, lights[lightIndexes[j]], result.t) * angleAttenuation; + } + } + return incoming / float(SampleCount); +} diff --git a/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl b/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl new file mode 100644 index 0000000000..b5f616e079 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl @@ -0,0 +1,50 @@ + +vec3 BeerLambertSimple(vec3 medium, float depth, vec3 ray_color); + +SurfaceInfo GetSurface(int primitiveIndex) +{ + return surfaces[surfaceIndices[primitiveIndex]]; +} + +vec2 GetSurfaceUV(int primitiveIndex, vec3 primitiveWeights) +{ + int index = primitiveIndex * 3; + return + vertices[elements[index + 1]].uv * primitiveWeights.x + + vertices[elements[index + 2]].uv * primitiveWeights.y + + vertices[elements[index + 0]].uv * primitiveWeights.z; +} + +vec3 PassRayThroughSurface(SurfaceInfo surface, vec2 uv, vec3 rayColor) +{ + if (surface.TextureIndex == 0) + { + return rayColor; + } + else + { + vec4 color = texture(textures[surface.TextureIndex], uv); + + // To do: currently we do not know the material/renderstyle of the surface. + // + // This means we can't apply translucency and we can't do something like BeerLambertSimple. + // In order to improve this SurfaceInfo needs additional info. + // + // return BeerLambertSimple(1.0 - color.rgb, color.a * surface.Alpha, rayColor); + + // Assume the renderstyle is basic alpha blend for now. + return rayColor * (1.0 - color.a * surface.Alpha); + } +} + +void TransformRay(uint portalIndex, inout vec3 origin, inout vec3 dir) +{ + mat4 transformationMatrix = portals[portalIndex].Transformation; + origin = (transformationMatrix * vec4(origin, 1.0)).xyz; + dir = (transformationMatrix * vec4(dir, 0.0)).xyz; +} + +vec3 BeerLambertSimple(vec3 medium, float depth, vec3 ray_color) // based on Beer-Lambert law +{ + return ray_color * exp(-medium * depth); +} diff --git a/wadsrc/static/shaders/lightmap/trace_light.glsl b/wadsrc/static/shaders/lightmap/trace_light.glsl new file mode 100644 index 0000000000..742e961e22 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/trace_light.glsl @@ -0,0 +1,92 @@ + +#include + +vec3 TracePointLightRay(vec3 origin, vec3 lightpos, float tmin, vec3 rayColor); + +vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, float extraDistance) +{ + const float minDistance = 0.01; + vec3 incoming = vec3(0.0); + float dist = distance(light.RelativeOrigin, origin) + extraDistance; + if (dist > minDistance && dist < light.Radius) + { + vec3 dir = normalize(light.RelativeOrigin - origin); + + float distAttenuation = max(1.0 - (dist / light.Radius), 0.0); + float angleAttenuation = max(dot(normal, dir), 0.0); + float spotAttenuation = 1.0; + if (light.OuterAngleCos > -1.0) + { + float cosDir = dot(dir, light.SpotDir); + spotAttenuation = smoothstep(light.OuterAngleCos, light.InnerAngleCos, cosDir); + spotAttenuation = max(spotAttenuation, 0.0); + } + + float attenuation = distAttenuation * angleAttenuation * spotAttenuation; + if (attenuation > 0.0) + { + vec3 rayColor = light.Color.rgb * (attenuation * light.Intensity); + +#if defined(USE_SOFTSHADOWS) + + if (light.SourceRadius != 0.0) + { + vec3 v = (abs(dir.x) > abs(dir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0); + vec3 xdir = normalize(cross(dir, v)); + vec3 ydir = cross(dir, xdir); + + float lightsize = light.SourceRadius; + int step_count = 10; + for (int i = 0; i < step_count; i++) + { + vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize; + vec3 pos = light.Origin + xdir * gridoffset.x + ydir * gridoffset.y; + + incoming += TracePointLightRay(origin, pos, minDistance, rayColor) / float(step_count); + } + } + else + { + incoming += TracePointLightRay(origin, light.Origin, minDistance, rayColor); + } + +#else + incoming += TracePointLightRay(origin, light.Origin, minDistance, rayColor); +#endif + } + } + + return incoming; +} + +vec3 TracePointLightRay(vec3 origin, vec3 lightpos, float tmin, vec3 rayColor) +{ + vec3 dir = normalize(lightpos - origin); + float tmax = distance(origin, lightpos); + + for (int i = 0; i < 3; i++) + { + TraceResult result = TraceFirstHit(origin, tmin, dir, tmax); + + // Stop if we hit nothing - the point light is visible. + if (result.primitiveIndex == -1) + return rayColor; + + SurfaceInfo surface = GetSurface(result.primitiveIndex); + + // Pass through surface texture + rayColor = PassRayThroughSurface(surface, GetSurfaceUV(result.primitiveIndex, result.primitiveWeights), rayColor); + + // Stop if there is no light left + if (rayColor.r + rayColor.g + rayColor.b <= 0.0) + return vec3(0.0); + + // Move to surface hit point + origin += dir * result.t; + tmax -= result.t; + + // Move through the portal, if any + TransformRay(surface.PortalIndex, origin, dir); + } + return vec3(0.0); +} diff --git a/wadsrc/static/shaders/lightmap/trace_sunlight.glsl b/wadsrc/static/shaders/lightmap/trace_sunlight.glsl new file mode 100644 index 0000000000..df230328fd --- /dev/null +++ b/wadsrc/static/shaders/lightmap/trace_sunlight.glsl @@ -0,0 +1,77 @@ + +#include + +vec3 TraceSunRay(vec3 origin, float tmin, vec3 dir, float tmax, vec3 rayColor); + +vec3 TraceSunLight(vec3 origin, vec3 normal) +{ + float angleAttenuation = max(dot(normal, SunDir), 0.0); + if (angleAttenuation == 0.0) + return vec3(0.0); + + const float minDistance = 0.01; + vec3 incoming = vec3(0.0); + const float dist = 65536.0; + + vec3 rayColor = SunColor.rgb * SunIntensity; + +#if defined(USE_SOFTSHADOWS) + + vec3 target = origin + SunDir * dist; + vec3 dir = SunDir; + vec3 v = (abs(dir.x) > abs(dir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0); + vec3 xdir = normalize(cross(dir, v)); + vec3 ydir = cross(dir, xdir); + + float lightsize = 100; + int step_count = 10; + for (int i = 0; i < step_count; i++) + { + vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize; + vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y; + incoming += TraceSunRay(origin, minDistance, normalize(pos - origin), dist, rayColor) / float(step_count); + } + +#else + + incoming = TraceSunRay(origin, minDistance, SunDir, dist, rayColor); + +#endif + + return incoming * angleAttenuation; +} + +vec3 TraceSunRay(vec3 origin, float tmin, vec3 dir, float tmax, vec3 rayColor) +{ + for (int i = 0; i < 3; i++) + { + TraceResult result = TraceFirstHit(origin, tmin, dir, tmax); + + // Stop if we hit nothing. We have to hit a sky surface to hit the sky. + if (result.primitiveIndex == -1) + return vec3(0.0); + + SurfaceInfo surface = GetSurface(result.primitiveIndex); + + // Stop if we hit the sky. + if (surface.Sky > 0.0) + return rayColor; + + // Pass through surface texture + rayColor = PassRayThroughSurface(surface, GetSurfaceUV(result.primitiveIndex, result.primitiveWeights), rayColor); + + // Stop if there is no light left + if (rayColor.r + rayColor.g + rayColor.b <= 0.0) + return vec3(0.0); + + // Move to surface hit point + origin += dir * result.t; + tmax -= result.t; + if (tmax <= tmin) + return vec3(0.0); + + // Move through the portal, if any + TransformRay(surface.PortalIndex, origin, dir); + } + return vec3(0.0); +} diff --git a/wadsrc/static/shaders/lightmap/vert_copy.glsl b/wadsrc/static/shaders/lightmap/vert_copy.glsl new file mode 100644 index 0000000000..9e2643667f --- /dev/null +++ b/wadsrc/static/shaders/lightmap/vert_copy.glsl @@ -0,0 +1,41 @@ + +layout(push_constant) uniform PushConstants +{ + int SrcTexSize; + int DestTexSize; + int Padding1; + int Padding2; +}; + +struct TileCopy +{ + ivec2 SrcPos; + ivec2 DestPos; + ivec2 TileSize; + int Padding1, Padding2; +}; + +layout(std430, set = 0, binding = 1) buffer CopyBuffer +{ + TileCopy tiles[]; +}; + +layout(location = 0) out vec2 TexCoord; + +vec2 positions[4] = vec2[]( + vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(1.0, 1.0) +); + +void main() +{ + TileCopy tile = tiles[gl_InstanceIndex]; + vec2 uv = positions[gl_VertexIndex]; + vec2 src = (vec2(tile.SrcPos) + uv * vec2(tile.TileSize)) / float(SrcTexSize); + vec2 dest = (vec2(tile.DestPos) + uv * vec2(tile.TileSize)) / float(DestTexSize); + + gl_Position = vec4(dest * 2.0 - 1.0, 0.0, 1.0); + TexCoord = src; +} diff --git a/wadsrc/static/shaders/lightmap/vert_raytrace.glsl b/wadsrc/static/shaders/lightmap/vert_raytrace.glsl new file mode 100644 index 0000000000..a872d31f7a --- /dev/null +++ b/wadsrc/static/shaders/lightmap/vert_raytrace.glsl @@ -0,0 +1,36 @@ + +#include + +layout(location = 0) in vec3 aPosition; +layout(location = 0) out vec3 worldpos; + +layout(location = 1) out flat int InstanceIndex; + +void main() +{ + vec3 WorldToLocal = constants[gl_InstanceIndex].WorldToLocal; + float TextureSize = constants[gl_InstanceIndex].TextureSize; + vec3 ProjLocalToU = constants[gl_InstanceIndex].ProjLocalToU; + vec3 ProjLocalToV = constants[gl_InstanceIndex].ProjLocalToV; + float TileX = constants[gl_InstanceIndex].TileX; + float TileY = constants[gl_InstanceIndex].TileY; + float TileWidth = constants[gl_InstanceIndex].TileWidth; + float TileHeight = constants[gl_InstanceIndex].TileHeight; + InstanceIndex = gl_InstanceIndex; + + worldpos = aPosition; + + // Project to position relative to tile + vec3 localPos = aPosition - WorldToLocal; + float x = dot(localPos, ProjLocalToU); + float y = dot(localPos, ProjLocalToV); + + // Find the position in the output texture + gl_Position = vec4(vec2(TileX + x, TileY + y) / TextureSize * 2.0 - 1.0, 0.0, 1.0); + + // Clip all surfaces to the edge of the tile (effectly we are applying a viewport/scissor to the tile) + gl_ClipDistance[0] = x; + gl_ClipDistance[1] = y; + gl_ClipDistance[2] = TileWidth - x; + gl_ClipDistance[3] = TileHeight - y; +} diff --git a/wadsrc/static/shaders/lightmap/vert_screenquad.glsl b/wadsrc/static/shaders/lightmap/vert_screenquad.glsl new file mode 100644 index 0000000000..ce33270f1b --- /dev/null +++ b/wadsrc/static/shaders/lightmap/vert_screenquad.glsl @@ -0,0 +1,20 @@ + +layout(location = 0) out vec2 TexCoord; + +vec2 positions[3] = vec2[]( + vec2(-1.0, -1.0), + vec2( 3.0, -1.0), + vec2(-1.0, 3.0) +); + +vec2 uvs[3] = vec2[]( + vec2(0.0, 0.0), + vec2(2.0, 0.0), + vec2(0.0, 2.0) +); + +void main() +{ + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + TexCoord = uvs[gl_VertexIndex]; +} diff --git a/wadsrc/static/shaders/pp/ssaocombine.fp b/wadsrc/static/shaders/pp/ssaocombine.fp index 0d592549f3..9be5f32d44 100644 --- a/wadsrc/static/shaders/pp/ssaocombine.fp +++ b/wadsrc/static/shaders/pp/ssaocombine.fp @@ -37,5 +37,5 @@ void main() else if (DebugMode == 3) FragColor = vec4(ssao.yyy / 1000.0, 1.0); else - FragColor = vec4(ssao.xyz, 1.0); + FragColor = vec4(fogColor, 1.0); } diff --git a/wadsrc/static/shaders/scene/binding_fixed.glsl b/wadsrc/static/shaders/scene/binding_fixed.glsl new file mode 100644 index 0000000000..387ed6d161 --- /dev/null +++ b/wadsrc/static/shaders/scene/binding_fixed.glsl @@ -0,0 +1,38 @@ + +layout(set = 0, binding = 0) uniform sampler2D ShadowMap; +layout(set = 0, binding = 1) uniform sampler2DArray LightMap; + +#if defined(USE_RAYTRACE) +#if defined(SUPPORTS_RAYQUERY) +layout(set = 0, binding = 2) uniform accelerationStructureEXT TopLevelAS; +#else +struct CollisionNode +{ + vec3 center; + float padding1; + vec3 extents; + float padding2; + int left; + int right; + int element_index; + int padding3; +}; +layout(std430, set = 0, binding = 2) buffer NodeBuffer +{ + int nodesRoot; + int nodebufferPadding1; + int nodebufferPadding2; + int nodebufferPadding3; + CollisionNode nodes[]; +}; +struct SurfaceVertex // Note: this must always match the FFlatVertex struct +{ + vec3 pos; + float lindex; + vec2 uv; + vec2 luv; +}; +layout(std430, set = 0, binding = 3) buffer VertexBuffer { SurfaceVertex vertices[]; }; +layout(std430, set = 0, binding = 4) buffer ElementBuffer { int elements[]; }; +#endif +#endif diff --git a/wadsrc/static/shaders/scene/binding_rsbuffers.glsl b/wadsrc/static/shaders/scene/binding_rsbuffers.glsl new file mode 100644 index 0000000000..59742e7674 --- /dev/null +++ b/wadsrc/static/shaders/scene/binding_rsbuffers.glsl @@ -0,0 +1,110 @@ + +// This must match the HWViewpointUniforms struct +layout(set = 1, binding = 0, std140) uniform ViewpointUBO +{ + mat4 ProjectionMatrix; + mat4 ViewMatrix; + mat4 NormalViewMatrix; + + vec4 uCameraPos; + vec4 uClipLine; + + float uGlobVis; // uGlobVis = R_GetGlobVis(r_visibility) / 32.0 + int uPalLightLevels; + int uViewHeight; // Software fuzz scaling + float uClipHeight; + float uClipHeightDirection; + int uShadowmapFilter; + + int uLightBlendMode; +}; + +layout(set = 1, binding = 1, std140) uniform MatricesUBO +{ + mat4 ModelMatrix; + mat4 NormalModelMatrix; + mat4 TextureMatrix; +}; + +// This must match the SurfaceUniforms struct +struct SurfaceUniforms +{ + vec4 uObjectColor; + vec4 uObjectColor2; + vec4 uDynLightColor; + vec4 uAddColor; + vec4 uTextureAddColor; + vec4 uTextureModulateColor; + vec4 uTextureBlendColor; + vec4 uFogColor; + float uDesaturationFactor; + float uInterpolationFactor; + float timer; // timer data for material shaders + int useVertexData; + vec4 uVertexColor; + vec4 uVertexNormal; + + vec4 uGlowTopPlane; + vec4 uGlowTopColor; + vec4 uGlowBottomPlane; + vec4 uGlowBottomColor; + + vec4 uGradientTopPlane; + vec4 uGradientBottomPlane; + + vec4 uSplitTopPlane; + vec4 uSplitBottomPlane; + + vec4 uDetailParms; + vec4 uNpotEmulation; + + vec2 uClipSplit; + vec2 uSpecularMaterial; + + float uLightLevel; + float uFogDensity; + float uLightFactor; + float uLightDist; + + float uAlphaThreshold; + int uTextureIndex; + float padding2; + float padding3; +}; + +#ifdef USE_LEVELMESH +layout(set = 1, binding = 2, std430) buffer SurfaceUniformsSSO +{ + SurfaceUniforms data[]; +}; +#else +layout(set = 1, binding = 2, std140) uniform SurfaceUniformsUBO +{ + SurfaceUniforms data[MAX_SURFACE_UNIFORMS]; +}; +#endif + +// light buffers +layout(set = 1, binding = 3, std140) uniform LightBufferUBO +{ + vec4 lights[MAX_LIGHT_DATA]; +}; + +struct Fogball +{ + vec3 position; + float radius; + vec3 color; + float fog; +}; + +layout(set = 1, binding = 4, std140) uniform FogballBufferUBO +{ + Fogball fogballs[MAX_FOGBALL_DATA]; +}; + +// bone matrix buffers +layout(set = 1, binding = 5, std430) buffer BoneBufferSSO +{ + mat4 bones[]; +}; diff --git a/wadsrc/static/shaders/scene/binding_textures.glsl b/wadsrc/static/shaders/scene/binding_textures.glsl new file mode 100644 index 0000000000..3ef32bc693 --- /dev/null +++ b/wadsrc/static/shaders/scene/binding_textures.glsl @@ -0,0 +1,23 @@ + +layout(set = 2, binding = 0) uniform sampler2D textures[]; + +const int tex = 0; +const int texture2 = 1; +const int texture3 = 2; +const int texture4 = 3; +const int texture5 = 4; +const int texture6 = 5; +const int texture7 = 6; +const int texture8 = 7; +const int texture9 = 8; +const int texture10 = 9; +const int texture11 = 10; +const int texture12 = 11; +const int texture13 = 12; +const int texture14 = 13; +const int texture15 = 14; +const int texture16 = 15; +const int texture17 = 16; +const int texture18 = 17; +const int texture19 = 18; +const int texture20 = 19; diff --git a/wadsrc/static/shaders/scene/bones.glsl b/wadsrc/static/shaders/scene/bones.glsl index c9edc46bd8..05e7030ea2 100644 --- a/wadsrc/static/shaders/scene/bones.glsl +++ b/wadsrc/static/shaders/scene/bones.glsl @@ -26,7 +26,7 @@ void AddWeightedBone(uint boneIndex, float weight, inout vec4 position, inout ve { mat4 transform = bones[uBoneIndexBase + int(boneIndex)]; mat3 rotation = mat3(transform); - position += (transform * aPosition) * weight; + position += (transform * vec4(aPosition.xyz, 1.0)) * weight; normal += (rotation * aNormal.xyz) * weight; } } @@ -53,7 +53,7 @@ BonesResult ApplyBones() } else { - result.Position = aPosition; + result.Position = vec4(aPosition.xyz, 1.0); result.Normal = GetAttrNormal(); } return result; @@ -64,7 +64,7 @@ BonesResult ApplyBones() BonesResult ApplyBones() { BonesResult result; - result.Position = aPosition; + result.Position = vec4(aPosition.xyz, 1.0); return result; } diff --git a/wadsrc/static/shaders/scene/fogball.glsl b/wadsrc/static/shaders/scene/fogball.glsl new file mode 100644 index 0000000000..08b4546f2d --- /dev/null +++ b/wadsrc/static/shaders/scene/fogball.glsl @@ -0,0 +1,69 @@ + +// The MIT License +// https://www.youtube.com/c/InigoQuilez +// https://iquilezles.org/ +// Copyright (c) 2015 Inigo Quilez +// +// Analytically integrating quadratically decaying participating media within a sphere. +// Related info: https://iquilezles.org/articles/spherefunctions +float FogSphereDensity(vec3 rayOrigin, vec3 rayDirection, vec3 sphereCenter, float sphereRadius, float dbuffer) +{ + // normalize the problem to the canonical sphere + float ndbuffer = dbuffer / sphereRadius; + vec3 rc = (rayOrigin - sphereCenter) / sphereRadius; + + // find intersection with sphere + float b = dot(rayDirection, rc); + float c = dot(rc, rc) - 1.0f; + float h = b * b - c; + + // not intersecting + if (h < 0.0f) return 0.0f; + + h = sqrt(h); + + //return h*h*h; + + float t1 = -b - h; + float t2 = -b + h; + + // not visible (behind camera or behind ndbuffer) + if (t2 < 0.0f || t1 > ndbuffer) return 0.0f; + + // clip integration segment from camera to ndbuffer + t1 = max(t1, 0.0f); + t2 = min(t2, ndbuffer); + + // analytical integration of an inverse squared density + float i1 = -(c * t1 + b * t1 * t1 + t1 * t1 * t1 * (1.0f / 3.0f)); + float i2 = -(c * t2 + b * t2 * t2 + t2 * t2 * t2 * (1.0f / 3.0f)); + return (i2 - i1) * (3.0f / 4.0f); +} + +// Approximate sRGB/linear conversion +vec3 ToLinear(vec3 c) { return pow(c, vec3(2.2)); } +vec3 FromLinear(vec3 c) { return pow(c, vec3(1.0 / 2.2)); } + +vec4 ProcessFogBalls(vec4 light) +{ + light.rgb = ToLinear(light.rgb); + + vec3 rayOrigin = uCameraPos.xyz; + float dbuffer = distance(pixelpos.xyz, uCameraPos.xyz); + vec3 rayDirection = normalize(pixelpos.xyz - uCameraPos.xyz); + + int first = uFogballIndex + 1; + int last = uFogballIndex + int(fogballs[uFogballIndex].position.x); + for (int i = first; i <= last; i++) + { + vec3 sphereCenter = fogballs[i].position.xzy; + float sphereRadius = fogballs[i].radius; + + vec3 fogcolor = fogballs[i].color; + float density = FogSphereDensity(rayOrigin, rayDirection, sphereCenter, sphereRadius, dbuffer) * fogballs[i].fog; + float alpha = clamp(density, 0.0, 1.0); + light.rgb = mix(light.rgb, fogcolor * density, alpha); + } + + return vec4(FromLinear(light.rgb), light.a); +} diff --git a/wadsrc/static/shaders/scene/frag_portal.glsl b/wadsrc/static/shaders/scene/frag_portal.glsl new file mode 100644 index 0000000000..355cf52820 --- /dev/null +++ b/wadsrc/static/shaders/scene/frag_portal.glsl @@ -0,0 +1,10 @@ + +void main() +{ + FragColor = vec4(0.0, 1.0, 0.0, 1.0); +#ifdef GBUFFER_PASS + FragFog = vec4(0.0, 0.0, 0.0, 1.0); + FragNormal = vec4(0.5, 0.5, 0.5, 1.0); +#endif +} + diff --git a/wadsrc/static/shaders/scene/layout_frag.glsl b/wadsrc/static/shaders/scene/layout_frag.glsl index f31d00431c..925436afd0 100644 --- a/wadsrc/static/shaders/scene/layout_frag.glsl +++ b/wadsrc/static/shaders/scene/layout_frag.glsl @@ -16,8 +16,32 @@ layout(location = 7) in vec4 ClipDistanceA; layout(location = 8) in vec4 ClipDistanceB; #endif +#if defined(USE_LEVELMESH) +layout(location = 10) in flat int uDataIndex; +#endif + layout(location=0) out vec4 FragColor; #ifdef GBUFFER_PASS layout(location=1) out vec4 FragFog; layout(location=2) out vec4 FragNormal; #endif + +vec4 texture(int index, vec2 p) +{ + return texture(textures[uTextureIndex + index], p); +} + +ivec2 textureSize(int index, int lod) +{ + return textureSize(textures[uTextureIndex + index], lod); +} + +vec4 textureGrad(int index, vec2 P, vec2 dPdx, vec2 dPdy) +{ + return textureGrad(textures[uTextureIndex + index], P, dPdx, dPdy); +} + +vec4 texelFetch(int index, ivec2 P, int lod) +{ + return texelFetch(textures[uTextureIndex + index], P, lod); +} diff --git a/wadsrc/static/shaders/scene/layout_shared.glsl b/wadsrc/static/shaders/scene/layout_shared.glsl index 7f30d3ae2c..882e11a42a 100644 --- a/wadsrc/static/shaders/scene/layout_shared.glsl +++ b/wadsrc/static/shaders/scene/layout_shared.glsl @@ -1,144 +1,19 @@ -layout(set = 0, binding = 0) uniform sampler2D ShadowMap; -layout(set = 0, binding = 1) uniform sampler2DArray LightMap; -#if defined(USE_RAYTRACE) -#if defined(SUPPORTS_RAYQUERY) -layout(set = 0, binding = 2) uniform accelerationStructureEXT TopLevelAS; -#else -struct CollisionNode -{ - vec3 center; - float padding1; - vec3 extents; - float padding2; - int left; - int right; - int element_index; - int padding3; -}; -layout(std430, set = 0, binding = 2) buffer NodeBuffer -{ - int nodesRoot; - int nodebufferPadding1; - int nodebufferPadding2; - int nodebufferPadding3; - CollisionNode nodes[]; -}; -layout(std430, set = 0, binding = 3) buffer VertexBuffer { vec4 vertices[]; }; -layout(std430, set = 0, binding = 4) buffer ElementBuffer { int elements[]; }; -#endif -#endif - -// This must match the HWViewpointUniforms struct -layout(set = 1, binding = 0, std140) uniform ViewpointUBO -{ - mat4 ProjectionMatrix; - mat4 ViewMatrix; - mat4 NormalViewMatrix; - - vec4 uCameraPos; - vec4 uClipLine; - - float uGlobVis; // uGlobVis = R_GetGlobVis(r_visibility) / 32.0 - int uPalLightLevels; - int uViewHeight; // Software fuzz scaling - float uClipHeight; - float uClipHeightDirection; - int uShadowmapFilter; - - int uLightBlendMode; -}; - -layout(set = 1, binding = 1, std140) uniform MatricesUBO -{ - mat4 ModelMatrix; - mat4 NormalModelMatrix; - mat4 TextureMatrix; -}; - -// This must match the StreamData struct -struct StreamData -{ - vec4 uObjectColor; - vec4 uObjectColor2; - vec4 uDynLightColor; - vec4 uAddColor; - vec4 uTextureAddColor; - vec4 uTextureModulateColor; - vec4 uTextureBlendColor; - vec4 uFogColor; - float uDesaturationFactor; - float uInterpolationFactor; - float timer; // timer data for material shaders - int useVertexData; - vec4 uVertexColor; - vec4 uVertexNormal; - - vec4 uGlowTopPlane; - vec4 uGlowTopColor; - vec4 uGlowBottomPlane; - vec4 uGlowBottomColor; - - vec4 uGradientTopPlane; - vec4 uGradientBottomPlane; - - vec4 uSplitTopPlane; - vec4 uSplitBottomPlane; - - vec4 uDetailParms; - vec4 uNpotEmulation; - - vec2 uClipSplit; - vec2 uSpecularMaterial; - - float uLightLevel; - float uFogDensity; - float uLightFactor; - float uLightDist; - - float uAlphaThreshold; - float padding1; - float padding2; - float padding3; -}; - -layout(set = 1, binding = 2, std140) uniform StreamUBO -{ - StreamData data[MAX_STREAM_DATA]; -}; - -// light buffers -layout(set = 1, binding = 3, std140) uniform LightBufferUBO -{ - vec4 lights[MAX_LIGHT_DATA]; -}; - -// bone matrix buffers -layout(set = 1, binding = 4, std430) buffer BoneBufferSSO -{ - mat4 bones[]; -}; - -// textures -layout(set = 2, binding = 0) uniform sampler2D tex; -layout(set = 2, binding = 1) uniform sampler2D texture2; -layout(set = 2, binding = 2) uniform sampler2D texture3; -layout(set = 2, binding = 3) uniform sampler2D texture4; -layout(set = 2, binding = 4) uniform sampler2D texture5; -layout(set = 2, binding = 5) uniform sampler2D texture6; -layout(set = 2, binding = 6) uniform sampler2D texture7; -layout(set = 2, binding = 7) uniform sampler2D texture8; -layout(set = 2, binding = 8) uniform sampler2D texture9; -layout(set = 2, binding = 9) uniform sampler2D texture10; -layout(set = 2, binding = 10) uniform sampler2D texture11; +#include "shaders/scene/binding_fixed.glsl" +#include "shaders/scene/binding_rsbuffers.glsl" +#include "shaders/scene/binding_textures.glsl" // This must match the PushConstants struct layout(push_constant) uniform PushConstants { - int uDataIndex; // streamdata index +#if defined(USE_LEVELMESH) + int unused; +#else + int uDataIndex; // surfaceuniforms index +#endif int uLightIndex; // dynamic lights int uBoneIndexBase; // bone animation - int padding; + int uFogballIndex; // fog balls }; // material types @@ -193,6 +68,7 @@ layout(push_constant) uniform PushConstants #define uLightFactor data[uDataIndex].uLightFactor #define uLightDist data[uDataIndex].uLightDist #define uAlphaThreshold data[uDataIndex].uAlphaThreshold +#define uTextureIndex data[uDataIndex].uTextureIndex #define VULKAN_COORDINATE_SYSTEM #define HAS_UNIFORM_VERTEX_DATA diff --git a/wadsrc/static/shaders/scene/layout_vert.glsl b/wadsrc/static/shaders/scene/layout_vert.glsl index d1c6357953..62ed8196b2 100644 --- a/wadsrc/static/shaders/scene/layout_vert.glsl +++ b/wadsrc/static/shaders/scene/layout_vert.glsl @@ -11,7 +11,7 @@ layout(location = 9) out vec3 vLightmap; layout(location = 3) in vec4 aVertex2; layout(location = 4) in vec4 aNormal; layout(location = 5) in vec4 aNormal2; -layout(location = 6) in vec3 aLightmap; +layout(location = 6) in vec2 aLightmap; layout(location = 7) in vec4 aBoneWeight; layout(location = 8) in uvec4 aBoneSelector; @@ -26,3 +26,8 @@ layout(location = 6) out vec4 vEyeNormal; layout(location = 7) out vec4 ClipDistanceA; layout(location = 8) out vec4 ClipDistanceB; #endif + +#if defined(USE_LEVELMESH) +layout(location = 9) in int aDataIndex; +layout(location = 10) out flat int uDataIndex; +#endif diff --git a/wadsrc/static/shaders/scene/light_shadow.glsl b/wadsrc/static/shaders/scene/light_shadow.glsl index 009fcd4175..e464213456 100644 --- a/wadsrc/static/shaders/scene/light_shadow.glsl +++ b/wadsrc/static/shaders/scene/light_shadow.glsl @@ -63,9 +63,9 @@ float intersect_triangle_ray(RayBBox ray, int a, out float barycentricB, out flo int start_element = nodes[a].element_index; vec3 p[3]; - p[0] = vertices[elements[start_element]].xyz; - p[1] = vertices[elements[start_element + 1]].xyz; - p[2] = vertices[elements[start_element + 2]].xyz; + p[0] = vertices[elements[start_element]].pos.xyz; + p[1] = vertices[elements[start_element + 1]].pos.xyz; + p[2] = vertices[elements[start_element + 2]].pos.xyz; // Moeller-Trumbore ray-triangle intersection algorithm: @@ -167,47 +167,30 @@ bool traceHit(vec3 origin, vec3 direction, float dist) #endif -vec2 softshadow[9 * 3] = vec2[]( - vec2( 0.0, 0.0), - vec2(-2.0,-2.0), - vec2( 2.0, 2.0), - vec2( 2.0,-2.0), - vec2(-2.0, 2.0), - vec2(-1.0,-1.0), - vec2( 1.0, 1.0), - vec2( 1.0,-1.0), - vec2(-1.0, 1.0), - - vec2( 0.0, 0.0), - vec2(-1.5,-1.5), - vec2( 1.5, 1.5), - vec2( 1.5,-1.5), - vec2(-1.5, 1.5), - vec2(-0.5,-0.5), - vec2( 0.5, 0.5), - vec2( 0.5,-0.5), - vec2(-0.5, 0.5), - - vec2( 0.0, 0.0), - vec2(-1.25,-1.75), - vec2( 1.75, 1.25), - vec2( 1.25,-1.75), - vec2(-1.75, 1.75), - vec2(-0.75,-0.25), - vec2( 0.25, 0.75), - vec2( 0.75,-0.25), - vec2(-0.25, 0.75) -); - -float traceShadow(vec4 lightpos, int quality) +vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi) { - vec3 origin = pixelpos.xzy; - vec3 target = lightpos.xzy + 0.01; // nudge light position slightly as Doom maps tend to have their lights perfectly aligned with planes + const float goldenAngle = radians(180.0) * (3.0 - sqrt(5.0)); + float sampleIndexF = float(sampleIndex); + float sampleCountF = float(sampleCount); + + float r = sqrt((sampleIndexF + 0.5) / sampleCountF); // Assuming index and count are positive + float theta = sampleIndexF * goldenAngle + phi; + + float sine = sin(theta); + float cosine = cos(theta); + + return vec2(cosine, sine) * r; +} + +float traceShadow(vec4 lightpos, int quality, float sourceRadius) +{ + vec3 origin = pixelpos.xyz; + vec3 target = lightpos.xyz + 0.01; // nudge light position slightly as Doom maps tend to have their lights perfectly aligned with planes vec3 direction = normalize(target - origin); float dist = distance(origin, target); - if (quality == 0) + if (quality == 0 || sourceRadius == 0) { return traceHit(origin, direction, dist) ? 0.0 : 1.0; } @@ -218,21 +201,22 @@ float traceShadow(vec4 lightpos, int quality) vec3 ydir = cross(direction, xdir); float sum = 0.0; - int step_count = quality * 9; - for (int i = 0; i <= step_count; i++) + int step_count = quality * 4; + for (int i = 0; i < step_count; i++) { - vec3 pos = target + xdir * softshadow[i].x + ydir * softshadow[i].y; + vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * sourceRadius; + vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y; sum += traceHit(origin, normalize(pos - origin), dist) ? 0.0 : 1.0; } return sum / step_count; } } -float shadowAttenuation(vec4 lightpos, float lightcolorA) +float shadowAttenuation(vec4 lightpos, float lightcolorA, float sourceRadius) { if (lightpos.w > 1000000.0) return 1.0; // Sunlight - return traceShadow(lightpos, uShadowmapFilter); + return traceShadow(lightpos, uShadowmapFilter, sourceRadius); } #elif defined(USE_SHADOWMAP) @@ -362,7 +346,7 @@ float shadowmapAttenuation(vec4 lightpos, float shadowIndex) } } -float shadowAttenuation(vec4 lightpos, float lightcolorA) +float shadowAttenuation(vec4 lightpos, float lightcolorA, float sourceRadius) { if (lightpos.w > 1000000.0) return 1.0; // Sunlight @@ -376,7 +360,7 @@ float shadowAttenuation(vec4 lightpos, float lightcolorA) #else -float shadowAttenuation(vec4 lightpos, float lightcolorA) +float shadowAttenuation(vec4 lightpos, float lightcolorA, float sourceRadius) { return 1.0; } diff --git a/wadsrc/static/shaders/scene/lightmode.glsl b/wadsrc/static/shaders/scene/lightmode.glsl index 0f138c55f8..495de69f3c 100644 --- a/wadsrc/static/shaders/scene/lightmode.glsl +++ b/wadsrc/static/shaders/scene/lightmode.glsl @@ -4,6 +4,7 @@ #include "shaders/scene/lightmode_vanilla.glsl" #include "shaders/scene/lightmode_build.glsl" #include "shaders/scene/material.glsl" +#include "shaders/scene/fogball.glsl" //=========================================================================== // @@ -87,6 +88,10 @@ vec4 getLightColor(Material material) #endif + #if defined(FOGBALLS) + frag = ProcessFogBalls(frag); + #endif + return frag; } diff --git a/wadsrc/static/shaders/scene/lightmodel_normal.glsl b/wadsrc/static/shaders/scene/lightmodel_normal.glsl index b9d25852c0..894a3d9724 100644 --- a/wadsrc/static/shaders/scene/lightmodel_normal.glsl +++ b/wadsrc/static/shaders/scene/lightmodel_normal.glsl @@ -26,7 +26,7 @@ vec3 lightContribution(int i, vec3 normal) if (attenuation > 0.0) // Skip shadow map test if possible { - attenuation *= shadowAttenuation(lightpos, lightcolor.a); + attenuation *= shadowAttenuation(lightpos, lightcolor.a, lightspot2.z); return lightcolor.rgb * attenuation; } else diff --git a/wadsrc/static/shaders/scene/lightmodel_pbr.glsl b/wadsrc/static/shaders/scene/lightmodel_pbr.glsl index 35c50bfc35..c87cbf52f1 100644 --- a/wadsrc/static/shaders/scene/lightmodel_pbr.glsl +++ b/wadsrc/static/shaders/scene/lightmodel_pbr.glsl @@ -106,7 +106,7 @@ vec3 ProcessMaterialLight(Material material, vec3 ambientLight) if (attenuation > 0.0) { - attenuation *= shadowAttenuation(lightpos, lightcolor.a); + attenuation *= shadowAttenuation(lightpos, lightcolor.a, lightspot2.z); vec3 radiance = lightcolor.rgb * attenuation; @@ -146,7 +146,7 @@ vec3 ProcessMaterialLight(Material material, vec3 ambientLight) if (attenuation > 0.0) { - attenuation *= shadowAttenuation(lightpos, lightcolor.a); + attenuation *= shadowAttenuation(lightpos, lightcolor.a, lightspot2.z); vec3 radiance = lightcolor.rgb * attenuation; diff --git a/wadsrc/static/shaders/scene/lightmodel_specular.glsl b/wadsrc/static/shaders/scene/lightmodel_specular.glsl index 12eabd33e5..b889034abc 100644 --- a/wadsrc/static/shaders/scene/lightmodel_specular.glsl +++ b/wadsrc/static/shaders/scene/lightmodel_specular.glsl @@ -20,7 +20,7 @@ vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA) attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0); if (attenuation > 0.0) // Skip shadow map test if possible - attenuation *= shadowAttenuation(lightpos, lightcolorA); + attenuation *= shadowAttenuation(lightpos, lightcolorA, lightspot2.z); if (attenuation <= 0.0) return vec2(0.0); diff --git a/wadsrc/static/shaders/scene/vert_main.glsl b/wadsrc/static/shaders/scene/vert_main.glsl index dbd1c6f0e1..fc726c2d9d 100644 --- a/wadsrc/static/shaders/scene/vert_main.glsl +++ b/wadsrc/static/shaders/scene/vert_main.glsl @@ -8,11 +8,15 @@ void main() vec2 parmTexCoord; vec4 parmPosition; +#if defined(USE_LEVELMESH) + uDataIndex = aDataIndex; +#endif + BonesResult bones = ApplyBones(); parmTexCoord = aTexCoord; parmPosition = bones.Position; - + #ifndef SIMPLE vec4 worldcoord = ModelMatrix * mix(parmPosition, aVertex2, uInterpolationFactor); #else @@ -31,7 +35,7 @@ void main() #endif #ifndef SIMPLE - vLightmap = aLightmap; + vLightmap = vec3(aLightmap, aPosition.w); pixelpos.xyz = worldcoord.xyz; pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w; diff --git a/wadsrc/static/widgets/banner.png b/wadsrc/static/widgets/banner.png new file mode 100644 index 0000000000..f9beb9d899 Binary files /dev/null and b/wadsrc/static/widgets/banner.png differ diff --git a/wadsrc/static/widgets/noto/NotoSans-Regular.ttf b/wadsrc/static/widgets/noto/NotoSans-Regular.ttf new file mode 100644 index 0000000000..fa4cff505e Binary files /dev/null and b/wadsrc/static/widgets/noto/NotoSans-Regular.ttf differ diff --git a/wadsrc/static/widgets/noto/NotoSansArmenian-Regular.ttf b/wadsrc/static/widgets/noto/NotoSansArmenian-Regular.ttf new file mode 100644 index 0000000000..097432059b Binary files /dev/null and b/wadsrc/static/widgets/noto/NotoSansArmenian-Regular.ttf differ diff --git a/wadsrc/static/widgets/noto/NotoSansGeorgian-Regular.ttf b/wadsrc/static/widgets/noto/NotoSansGeorgian-Regular.ttf new file mode 100644 index 0000000000..49163cc37e Binary files /dev/null and b/wadsrc/static/widgets/noto/NotoSansGeorgian-Regular.ttf differ diff --git a/wadsrc/static/widgets/noto/OFL.txt b/wadsrc/static/widgets/noto/OFL.txt new file mode 100644 index 0000000000..76df3b5656 --- /dev/null +++ b/wadsrc/static/widgets/noto/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/wadsrc/static/widgets/poppins/OFL.txt b/wadsrc/static/widgets/poppins/OFL.txt new file mode 100644 index 0000000000..76df3b5656 --- /dev/null +++ b/wadsrc/static/widgets/poppins/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/wadsrc/static/widgets/poppins/poppins-regular.ttf b/wadsrc/static/widgets/poppins/poppins-regular.ttf new file mode 100644 index 0000000000..9f0c71b70a Binary files /dev/null and b/wadsrc/static/widgets/poppins/poppins-regular.ttf differ diff --git a/wadsrc/static/xlat/base.txt b/wadsrc/static/xlat/base.txt index 99e5ec7324..a53119b9ea 100644 --- a/wadsrc/static/xlat/base.txt +++ b/wadsrc/static/xlat/base.txt @@ -421,7 +421,7 @@ include "xlat/defines.i" // Generalized crusher (tag, dnspeed, upspeed, silent, damage) -[Generic_Crusher] (0x2f80, 0x2fff) +[Generic_CrusherDist] (0x2f80, 0x2fff) { flags |= 0x0020 [0x0020 : MONST] arg2 = 0x0018 [0x0000 : C_SLOW, diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 409acc2e3f..8229680ca2 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,4 +1,4 @@ -version "4.10" +version "4.12" // Generic engine code #include "zscript/engine/base.zs" @@ -42,6 +42,7 @@ version "4.10" #include "zscript/destructible.zs" #include "zscript/level_postprocessor.zs" #include "zscript/level_compatibility.zs" +#include "zscript/visualthinker.zs" #include "zscript/actors/actor.zs" #include "zscript/actors/checks.zs" @@ -95,6 +96,7 @@ version "4.10" #include "zscript/actors/shared/randomspawner.zs" #include "zscript/actors/shared/dynlights.zs" #include "zscript/actors/shared/corona.zs" +#include "zscript/actors/shared/fogball.zs" #include "zscript/actors/doom/doomplayer.zs" #include "zscript/actors/doom/possessed.zs" diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 9a007dd49f..7c52030da2 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -89,7 +89,6 @@ class Actor : Thinker native const DEFMORPHTICS = 40 * TICRATE; const MELEEDELTA = 20; - // flags are not defined here, the native fields for those get synthesized from the internal tables. // for some comments on these fields, see their native representations in actor.h. @@ -202,6 +201,7 @@ class Actor : Thinker native native int DesignatedTeam; native Actor BlockingMobj; native Line BlockingLine; + native Line MovementBlockingLine; native Sector Blocking3DFloor; native Sector BlockingCeiling; native Sector BlockingFloor; @@ -217,7 +217,7 @@ class Actor : Thinker native native Inventory Inv; native uint8 smokecounter; native uint8 FriendPlayer; - native uint Translation; + native TranslationID Translation; native sound AttackSound; native sound DeathSound; native sound SeeSound; @@ -248,10 +248,11 @@ class Actor : Thinker native native double ViewAngle, ViewPitch, ViewRoll; native double RadiusDamageFactor; // Radius damage factor native double SelfDamageFactor; + native double ShadowAimFactor, ShadowPenaltyFactor; native double StealthAlpha; native int WoundHealth; // Health needed to enter wound state native readonly color BloodColor; - native readonly int BloodTranslation; + native readonly TranslationID BloodTranslation; native int RenderHidden; native int RenderRequired; native int FriendlySeeBlocks; @@ -259,6 +260,8 @@ class Actor : Thinker native native readonly int SpawnTime; private native int InventoryID; // internal counter. native uint freezetics; + native Vector2 AutomapOffsets; + native double LandingSpeed; meta String Obituary; // Player was killed by this actor meta String HitObituary; // Player was killed by this actor in melee @@ -270,7 +273,7 @@ class Actor : Thinker native meta Name BloodType2; // Bloopsplatter replacement type meta Name BloodType3; // AxeBlood replacement type meta bool DontHurtShooter; - meta int ExplosionRadius; + meta double ExplosionRadius; meta int ExplosionDamage; meta int MeleeDamage; meta Sound MeleeSound; @@ -361,6 +364,10 @@ class Actor : Thinker native property FriendlySeeBlocks: FriendlySeeBlocks; property ThruBits: ThruBits; property LightLevel: LightLevel; + property ShadowAimFactor: ShadowAimFactor; + property ShadowPenaltyFactor: ShadowPenaltyFactor; + property AutomapOffsets : AutomapOffsets; + property LandingSpeed: LandingSpeed; // need some definition work first //FRenderStyle RenderStyle; @@ -425,7 +432,7 @@ class Actor : Thinker native DefThreshold 100; BloodType "Blood", "BloodSplatter", "AxeBlood"; ExplosionDamage 128; - ExplosionRadius -1; // i.e. use ExplosionDamage value + ExplosionRadius -1.0; // i.e. use ExplosionDamage value MissileHeight 32; SpriteAngle 0; SpriteRotation 0; @@ -438,6 +445,9 @@ class Actor : Thinker native FastSpeed -1; RadiusDamageFactor 1; SelfDamageFactor 1; + ShadowAimFactor 1; + ShadowPenaltyFactor 1; + AutomapOffsets (0,0); StealthAlpha 0; WoundHealth 6; GibHealth int.min; @@ -446,6 +456,7 @@ class Actor : Thinker native RenderHidden 0; RenderRequired 0; FriendlySeeBlocks 10; // 10 (blocks) * 128 (one map unit block) + LandingSpeed -8; // landing speed from a jump with normal gravity (squats the player's view) } // Functions @@ -493,8 +504,15 @@ class Actor : Thinker native virtual native bool Slam(Actor victim); virtual void Touch(Actor toucher) {} virtual native void FallAndSink(double grav, double oldfloorz); - private native void Substitute(Actor replacement); + native bool MorphInto(Actor morph); native ui void DisplayNameTag(); + native clearscope void DisableLocalRendering(uint playerNum, bool disable); + native ui bool ShouldRenderLocally(); // Only clients get to check this, never the playsim. + + // Called when the Actor is being used within a PSprite. This happens before potentially changing PSprite + // state so that any custom actions based on things like player input can be done before moving to the next + // state of something like a weapon. + virtual void PSpriteTick(PSprite psp) {} // Called by inventory items to see if this actor is capable of touching them. // If true, the item will attempt to be picked up. Useful for things like @@ -505,6 +523,23 @@ class Actor : Thinker native return true; } + // [AA] Called by inventory items in CallTryPickup to see if this actor needs + // to process them in some way before they're received. Gets called before + // the item's TryPickup, allowing fully customized handling of all items. + virtual bool CanReceive(Inventory item) + { + return true; + } + + // [AA] Called by inventory items at the end of CallTryPickup to let actors + // do something with the items they've received. 'Item' might be null for + // items that disappear on pickup. + virtual void HasReceived(Inventory item) {} + + // Called in TryMove if the mover ran into another Actor. This isn't called on players + // if they're currently predicting. Guarantees collisions unlike CanCollideWith. + virtual void CollidedWith(Actor other, bool passive) {} + // Called by PIT_CheckThing to check if two actors actually can collide. virtual bool CanCollideWith(Actor other, bool passive) { @@ -534,7 +569,13 @@ class Actor : Thinker native // This is called before a missile gets exploded. virtual int SpecialMissileHit (Actor victim) { - return -1; + return MHIT_DEFAULT; + } + + // This is called when a missile bounces off something. + virtual int SpecialBounceHit(Actor bounceMobj, Line bounceLine, readonly bouncePlane) + { + return MHIT_DEFAULT; } // Called when the player presses 'use' and an actor is found, except if the @@ -633,8 +674,8 @@ class Actor : Thinker native virtual void PostTeleport( Vector3 destpos, double destangle, int flags ) {} native virtual bool OkayToSwitchTarget(Actor other); - native static class GetReplacement(class cls); - native static class GetReplacee(class cls); + native clearscope static class GetReplacement(class cls); + native clearscope static class GetReplacee(class cls); native static int GetSpriteIndex(name sprt); native clearscope static double GetDefaultSpeed(class type); native static class GetSpawnableType(int spawnnum); @@ -664,7 +705,7 @@ class Actor : Thinker native native void SoundAlert(Actor target, bool splash = false, double maxdist = 0); native void ClearBounce(); native TerrainDef GetFloorTerrain(); - native bool CheckLocalView(int consoleplayer = -1 /* parameter is not used anymore but needed for backward compatibilityö. */); + native bool CheckLocalView(int consoleplayer = -1 /* parameter is not used anymore but needed for backward compatibility. */); native bool CheckNoDelay(); native bool UpdateWaterLevel (bool splash = true); native bool IsZeroDamage(); @@ -693,7 +734,7 @@ class Actor : Thinker native native void CheckFakeFloorTriggers (double oldz, bool oldz_has_viewheight = false); native bool CheckFor3DFloorHit(double z, bool trigger); native bool CheckFor3DCeilingHit(double z, bool trigger); - native int CheckMonsterUseSpecials(); + native int CheckMonsterUseSpecials(Line blocking = null); native bool CheckMissileSpawn(double maxdist); native bool CheckPosition(Vector2 pos, bool actorsonly = false, FCheckPosition tm = null); @@ -741,6 +782,7 @@ class Actor : Thinker native native bool LineTrace(double angle, double distance, double pitch, int flags = 0, double offsetz = 0., double offsetforward = 0., double offsetside = 0., out FLineTraceData data = null); native bool CheckSight(Actor target, int flags = 0); native bool IsVisible(Actor other, bool allaround, LookExParams params = null); + native bool, Actor, double PerformShadowChecks (Actor other, Vector3 pos); native bool HitFriend(); native bool MonsterMove(); @@ -770,6 +812,7 @@ class Actor : Thinker native native bool CheckMissileRange(); native bool SetState(state st, bool nofunction = false); clearscope native state FindState(statelabel st, bool exact = false) const; + clearscope native state FindStateByString(string st, bool exact = false) const; bool SetStateLabel(statelabel st, bool nofunction = false) { return SetState(FindState(st), nofunction); } native action state ResolveState(statelabel st); // this one, unlike FindState, is context aware. native void LinkToWorld(LinkContext ctx = null); @@ -812,8 +855,9 @@ class Actor : Thinker native native void PlayPushSound(); native bool BounceActor(Actor blocking, bool onTop); native bool BounceWall(Line l = null); - native bool BouncePlane(SecPlane plane); + native bool BouncePlane(readonly plane); native void PlayBounceSound(bool onFloor); + native bool ReflectOffActor(Actor blocking); clearscope double PitchTo(Actor target, double zOfs = 0, double targZOfs = 0, bool absolute = false) const { @@ -1106,6 +1150,7 @@ class Actor : Thinker native void A_Fall() { A_NoBlocking(); } native void A_Look(); native void A_Chase(statelabel melee = '_a_chase_default', statelabel missile = '_a_chase_default', int flags = 0); + native void A_DoChase(State melee, State missile, int flags = 0); native void A_VileChase(); native bool A_CheckForResurrection(State state = null, Sound snd = 0); native void A_BossDeath(); @@ -1186,9 +1231,9 @@ class Actor : Thinker native native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); native void A_CustomComboAttack(class missiletype, double spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); native void A_Burst(class chunktype); - native void A_RadiusDamageSelf(int damage = 128, double distance = 128, int flags = 0, class flashtype = null); - native int GetRadiusDamage(Actor thing, int damage, int distance, int fulldmgdistance = 0, bool oldradiusdmg = false); - native int RadiusAttack(Actor bombsource, int bombdamage, int bombdistance, Name bombmod = 'none', int flags = RADF_HURTSOURCE, int fulldamagedistance = 0, name species = "None"); + native void A_RadiusDamageSelf(int damage = 128, double distance = 128.0, int flags = 0, class flashtype = null); + native int GetRadiusDamage(Actor thing, int damage, double distance, double fulldmgdistance = 0.0, bool oldradiusdmg = false, bool circular = false); + native int RadiusAttack(Actor bombsource, int bombdamage, double bombdistance, Name bombmod = 'none', int flags = RADF_HURTSOURCE, double fulldamagedistance = 0.0, name species = "None"); native void A_Respawn(int flags = 1); native void A_RestoreSpecialPosition(); @@ -1208,8 +1253,8 @@ class Actor : Thinker native deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserArray(name varname, int index, int value); deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVarFloat(name varname, double value); deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserArrayFloat(name varname, int index, double value); - native void A_Quake(double intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); - native void A_QuakeEx(double intensityX, double intensityY, double intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, int falloff = 0, int highpoint = 0, double rollIntensity = 0, double rollWave = 0); + native void A_Quake(double intensity, int duration, double damrad, double tremrad, sound sfx = "world/quake"); + native void A_QuakeEx(double intensityX, double intensityY, double intensityZ, int duration, double damrad, double tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, double falloff = 0, int highpoint = 0, double rollIntensity = 0, double rollWave = 0, double damageMultiplier = 1, double thrustMultiplier = 0.5, int damage = 0); action native void A_SetTics(int tics); native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); @@ -1265,6 +1310,46 @@ class Actor : Thinker native native bool A_AttachLight(Name lightid, int type, Color lightcolor, int radius1, int radius2, int flags = 0, Vector3 ofs = (0,0,0), double param = 0, double spoti = 10, double spoto = 25, double spotp = 0); native bool A_RemoveLight(Name lightid); + native version("4.12") void SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame= -1, int endFrame = -1, int interpolateTics = -1, int flags = 0); + native version("4.12") ui void SetAnimationUI(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int endFrame = -1, int interpolateTics = -1, int flags = 0); + + native version("4.12") void SetAnimationFrameRate(double framerate); + native version("4.12") ui void SetAnimationFrameRateUI(double framerate); + + native version("4.12") void SetModelFlag(int flag); + native version("4.12") void ClearModelFlag(int flag); + native version("4.12") void ResetModelFlags(); + + + action version("4.12") void A_SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame= -1, int interpolateTics = -1, int flags = 0) + { + invoker.SetAnimation(animName, framerate, startFrame, loopFrame, interpolateTics, flags); + } + + action version("4.12") void A_SetAnimationFrameRate(double framerate) + { + invoker.SetAnimationFrameRate(framerate); + } + + action version("4.12") void A_SetModelFlag(int flag) + { + invoker.SetModelFlag(flag); + } + + action version("4.12") void A_ClearModelFlag(int flag) + { + invoker.ClearModelFlag(flag); + } + + action version("4.12") void A_ResetModelFlags() + { + invoker.ResetModelFlags(); + } + + + + + int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0) { return ACS_Execute(-int(script), mapnum, arg1, arg2, arg3); @@ -1308,7 +1393,7 @@ class Actor : Thinker native { if (DeathSound) { - A_StartSound(DeathSound, CHAN_VOICE, CHANF_DEFAULT, 1, bBoss? ATTN_NONE : ATTN_NORM); + A_StartSound(DeathSound, CHAN_VOICE, CHANF_DEFAULT, 1, bBoss || bFullvolDeath? ATTN_NONE : ATTN_NORM); } } @@ -1330,7 +1415,7 @@ class Actor : Thinker native bool grunted; // [RH] only make noise if alive - if (self.health > 0 && self.player.morphTics == 0) + if (self.health > 0 && !Alternative) { grunted = false; // Why should this number vary by gravity? diff --git a/wadsrc/static/zscript/actors/attacks.zs b/wadsrc/static/zscript/actors/attacks.zs index edefdd24fe..188a9c0640 100644 --- a/wadsrc/static/zscript/actors/attacks.zs +++ b/wadsrc/static/zscript/actors/attacks.zs @@ -569,7 +569,7 @@ extend class Actor // //========================================================================== - int A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class pufftype = "BulletPuff", name damagetype = "none") + int A_Explode(int damage = -1, double distance = -1.0, int flags = XF_HURTSOURCE, bool alert = false, double fulldamagedistance = 0.0, int nails = 0, int naildamage = 10, class pufftype = "BulletPuff", name damagetype = "none") { if (damage < 0) // get parameters from metadata @@ -606,6 +606,9 @@ extend class Actor if (flags & XF_HURTSOURCE) pflags |= RADF_HURTSOURCE; if (flags & XF_NOTMISSILE) pflags |= RADF_SOURCEISSPOT; if (flags & XF_THRUSTZ) pflags |= RADF_THRUSTZ; + if (flags & XF_THRUSTLESS) pflags |= RADF_THRUSTLESS; + if (flags & XF_NOALLIES) pflags |= RADF_NOALLIES; + if (flags & XF_CIRCULAR) pflags |= RADF_CIRCULAR; int count = RadiusAttack (target, damage, distance, damagetype, pflags, fulldamagedistance); if (!(flags & XF_NOSPLASH)) CheckSplash(distance); @@ -623,7 +626,7 @@ extend class Actor } deprecated("2.3", "For Dehacked use only") - void A_RadiusDamage(int dam, int dist) + void A_RadiusDamage(int dam, double dist) { A_Explode(dam, dist); } @@ -634,10 +637,10 @@ extend class Actor // //========================================================================== - void A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0, name species = "None") + void A_RadiusThrust(int force = 128, double distance = -1.0, int flags = RTF_AFFECTSOURCE, double fullthrustdistance = 0.0, name species = "None") { if (force == 0) force = 128; - if (distance <= 0) distance = abs(force); + if (distance <= 0.0) distance = abs(force); bool nothrust = false; if (target) diff --git a/wadsrc/static/zscript/actors/doom/doomdecorations.zs b/wadsrc/static/zscript/actors/doom/doomdecorations.zs index 8eec812f6b..ab5bd5b4f5 100644 --- a/wadsrc/static/zscript/actors/doom/doomdecorations.zs +++ b/wadsrc/static/zscript/actors/doom/doomdecorations.zs @@ -82,7 +82,7 @@ class ShortGreenColumn : Actor Default { Radius 16; - Height 40;; + Height 40; ProjectilePassHeight -16; +SOLID } @@ -234,7 +234,7 @@ class BlueTorch : Actor Default { Radius 16; - Height 68;; + Height 68; ProjectilePassHeight -16; +SOLID } @@ -594,7 +594,7 @@ class HeadsOnAStick : Actor Default { Radius 16; - Height 64;; + Height 64; ProjectilePassHeight -16; +SOLID } diff --git a/wadsrc/static/zscript/actors/doom/doomhealth.zs b/wadsrc/static/zscript/actors/doom/doomhealth.zs index c0ecf2dc01..04909b248b 100644 --- a/wadsrc/static/zscript/actors/doom/doomhealth.zs +++ b/wadsrc/static/zscript/actors/doom/doomhealth.zs @@ -16,6 +16,33 @@ class HealthBonus : Health BON1 ABCDCB 6; Loop; } + + //=========================================================================== + // + // TryPickup + // + //=========================================================================== + + override bool TryPickup (in out Actor other) + { + PrevHealth = other.player != NULL ? other.player.health : other.health; + + // Dehacked max health is compatibility dependent because Boom interpreted this value wrong. + let maxamt = MaxAmount; + if (maxamt < 0) + { + maxamt = deh.MaxHealth; + if (!(Level.compatflags & COMPATF_DEHHEALTH)) maxamt *= 2; + } + + if (other.GiveBody(Amount, maxamt)) + { + GoAwayAndDie(); + return true; + } + return false; + } + } // Stimpack ----------------------------------------------------------------- diff --git a/wadsrc/static/zscript/actors/doom/doommisc.zs b/wadsrc/static/zscript/actors/doom/doommisc.zs index c4e800eba9..a761f94e07 100644 --- a/wadsrc/static/zscript/actors/doom/doommisc.zs +++ b/wadsrc/static/zscript/actors/doom/doommisc.zs @@ -62,7 +62,8 @@ class BulletPuff : Actor +ALLOWPARTICLES +RANDOMIZE +ZDOOMTRANS - +FORCEXYBILLBOARD + RenderStyle "Translucent"; + Alpha 0.5; VSpeed 1; Mass 5; } @@ -72,7 +73,7 @@ class BulletPuff : Actor PUFF A 4 Bright; PUFF B 4; Melee: - PUFF CD 4 A_SetRenderStyle(0.7, STYLE_Translucent); + PUFF CD 4; Stop; } } diff --git a/wadsrc/static/zscript/actors/doom/doomweapons.zs b/wadsrc/static/zscript/actors/doom/doomweapons.zs index 4d3586e054..e28cf8bf3d 100644 --- a/wadsrc/static/zscript/actors/doom/doomweapons.zs +++ b/wadsrc/static/zscript/actors/doom/doomweapons.zs @@ -31,7 +31,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; State flash = weap.FindState('Flash'); diff --git a/wadsrc/static/zscript/actors/doom/possessed.zs b/wadsrc/static/zscript/actors/doom/possessed.zs index eef344ab8e..4fa9e0f7ec 100644 --- a/wadsrc/static/zscript/actors/doom/possessed.zs +++ b/wadsrc/static/zscript/actors/doom/possessed.zs @@ -315,12 +315,12 @@ extend class Actor } } - void A_CPosAttack() + private void A_CPosAttackInternal(Sound snd) { if (target) { if (bStealth) visdir = 1; - A_StartSound(AttackSound, CHAN_WEAPON); + A_StartSound(snd, CHAN_WEAPON); A_FaceTarget(); double slope = AimLineAttack(angle, MISSILERANGE); double ang = angle + Random2[CPosAttack]() * (22.5/256); @@ -328,6 +328,17 @@ extend class Actor LineAttack(ang, MISSILERANGE, slope, damage, "Hitscan", "Bulletpuff"); } } + + void A_CPosAttack() + { + A_CPosAttackInternal(AttackSound); + } + + void A_CPosAttackDehacked() + { + A_CPosAttackInternal("chainguy/attack"); + } + void A_CPosRefire() { diff --git a/wadsrc/static/zscript/actors/doom/weaponbfg.zs b/wadsrc/static/zscript/actors/doom/weaponbfg.zs index 583688f8dc..cb9e0ae7d3 100644 --- a/wadsrc/static/zscript/actors/doom/weaponbfg.zs +++ b/wadsrc/static/zscript/actors/doom/weaponbfg.zs @@ -107,7 +107,7 @@ extend class StateProvider if (invoker != weap || stateinfo == null || stateinfo.mStateType != STATE_Psprite) weap = null; if (weap != null) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; doesautoaim = weap.bNoAutoaim; diff --git a/wadsrc/static/zscript/actors/doom/weaponchaingun.zs b/wadsrc/static/zscript/actors/doom/weaponchaingun.zs index 58a4506881..50fc5eea65 100644 --- a/wadsrc/static/zscript/actors/doom/weaponchaingun.zs +++ b/wadsrc/static/zscript/actors/doom/weaponchaingun.zs @@ -60,7 +60,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; A_StartSound ("weapons/chngun", CHAN_WEAPON); diff --git a/wadsrc/static/zscript/actors/doom/weaponpistol.zs b/wadsrc/static/zscript/actors/doom/weaponpistol.zs index 0665a67aff..b44760e7db 100644 --- a/wadsrc/static/zscript/actors/doom/weaponpistol.zs +++ b/wadsrc/static/zscript/actors/doom/weaponpistol.zs @@ -85,7 +85,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; player.SetPsprite(PSP_FLASH, weap.FindState('Flash'), true); diff --git a/wadsrc/static/zscript/actors/doom/weaponplasma.zs b/wadsrc/static/zscript/actors/doom/weaponplasma.zs index dd711484ca..d1a474e53e 100644 --- a/wadsrc/static/zscript/actors/doom/weaponplasma.zs +++ b/wadsrc/static/zscript/actors/doom/weaponplasma.zs @@ -133,7 +133,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; State flash = weap.FindState('Flash'); diff --git a/wadsrc/static/zscript/actors/doom/weaponrlaunch.zs b/wadsrc/static/zscript/actors/doom/weaponrlaunch.zs index 042b96823a..dc7cd0ff24 100644 --- a/wadsrc/static/zscript/actors/doom/weaponrlaunch.zs +++ b/wadsrc/static/zscript/actors/doom/weaponrlaunch.zs @@ -152,7 +152,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; } @@ -177,7 +177,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; } diff --git a/wadsrc/static/zscript/actors/doom/weaponshotgun.zs b/wadsrc/static/zscript/actors/doom/weaponshotgun.zs index 3b39f1d3e4..01ca8fbc1c 100644 --- a/wadsrc/static/zscript/actors/doom/weaponshotgun.zs +++ b/wadsrc/static/zscript/actors/doom/weaponshotgun.zs @@ -66,7 +66,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; player.SetPsprite(PSP_FLASH, weap.FindState('Flash'), true); diff --git a/wadsrc/static/zscript/actors/doom/weaponssg.zs b/wadsrc/static/zscript/actors/doom/weaponssg.zs index cf775bde00..1312d3c9fa 100644 --- a/wadsrc/static/zscript/actors/doom/weaponssg.zs +++ b/wadsrc/static/zscript/actors/doom/weaponssg.zs @@ -74,7 +74,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 2)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; player.SetPsprite(PSP_FLASH, weap.FindState('Flash'), true); diff --git a/wadsrc/static/zscript/actors/heretic/chicken.zs b/wadsrc/static/zscript/actors/heretic/chicken.zs index 4bc2e20def..a49418ca39 100644 --- a/wadsrc/static/zscript/actors/heretic/chicken.zs +++ b/wadsrc/static/zscript/actors/heretic/chicken.zs @@ -221,7 +221,7 @@ class ChickenPlayer : PlayerPawn pspr.y = WEAPONTOP + player.chickenPeck / 2; } } - if (player.morphTics & 15) + if ((player.MorphTics ? player.MorphTics : Random[ChickenPlayerThink]()) & 15) { return; } diff --git a/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs b/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs index d12bf2b198..b620b04b4f 100644 --- a/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs +++ b/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs @@ -66,28 +66,26 @@ Class ArtiTomeOfPower : PowerupGiver Loop; } - override bool Use (bool pickup) + override bool Use(bool pickup) { - Playerinfo p = Owner.player; - if (p && p.morphTics && (p.MorphStyle & MRF_UNDOBYTOMEOFPOWER)) - { // Attempt to undo chicken - if (!p.mo.UndoPlayerMorph (p, MRF_UNDOBYTOMEOFPOWER)) - { // Failed - if (!(p.MorphStyle & MRF_FAILNOTELEFRAG)) - { - Owner.DamageMobj (null, null, TELEFRAG_DAMAGE, 'Telefrag'); - } + EMorphFlags mStyle = Owner.GetMorphStyle(); + if (Owner.Alternative && (mStyle & MRF_UNDOBYTOMEOFPOWER)) + { + // Attempt to undo chicken. + if (!Owner.Unmorph(Owner, MRF_UNDOBYTOMEOFPOWER)) + { + if (!(mStyle & MRF_FAILNOTELEFRAG)) + Owner.DamageMobj(null, null, TELEFRAG_DAMAGE, 'Telefrag'); } - else - { // Succeeded - Owner.A_StartSound ("*evillaugh", CHAN_VOICE); + else if (Owner.player) + { + Owner.A_StartSound("*evillaugh", CHAN_VOICE); } + return true; } - else - { - return Super.Use (pickup); - } + + return Super.Use(pickup); } } diff --git a/wadsrc/static/zscript/actors/heretic/weaponphoenix.zs b/wadsrc/static/zscript/actors/heretic/weaponphoenix.zs index 3300c43d35..884db86f82 100644 --- a/wadsrc/static/zscript/actors/heretic/weaponphoenix.zs +++ b/wadsrc/static/zscript/actors/heretic/weaponphoenix.zs @@ -93,7 +93,7 @@ class PhoenixRodPowered : PhoenixRod override void EndPowerup () { - DepleteAmmo (bAltFire); + if (FlameCount > 0) DepleteAmmo (bAltFire); Owner.player.refire = 0; Owner.A_StopSound (CHAN_WEAPON); Owner.player.ReadyWeapon = SisterWeapon; @@ -178,9 +178,10 @@ class PhoenixRodPowered : PhoenixRod return; } A_StopSound (CHAN_WEAPON); - Weapon weapon = player.ReadyWeapon; + PhoenixRodPowered weapon = PhoenixRodPowered(player.ReadyWeapon); if (weapon != null) { + weapon.FlameCount = 0; weapon.DepleteAmmo (weapon.bAltFire); } } diff --git a/wadsrc/static/zscript/actors/hexen/clericholy.zs b/wadsrc/static/zscript/actors/hexen/clericholy.zs index 8f2af52a4d..e3aee9bace 100644 --- a/wadsrc/static/zscript/actors/hexen/clericholy.zs +++ b/wadsrc/static/zscript/actors/hexen/clericholy.zs @@ -346,7 +346,7 @@ class HolySpirit : Actor { if (thing.bShootable && thing != target) { - if (multiplayer && !deathmatch && thing.player && target.player) + if (multiplayer && !deathmatch && thing.player && target && target.player) { // don't attack other co-op players return true; } diff --git a/wadsrc/static/zscript/actors/hexen/demons.zs b/wadsrc/static/zscript/actors/hexen/demons.zs index 08f81b2a81..41fdf8873e 100644 --- a/wadsrc/static/zscript/actors/hexen/demons.zs +++ b/wadsrc/static/zscript/actors/hexen/demons.zs @@ -20,6 +20,7 @@ class Demon1 : Actor DeathSound "DemonDeath"; ActiveSound "DemonActive"; Obituary "$OB_DEMON1"; + HitObituary "$OB_DEMON1HIT"; Tag "$FN_DEMON1"; } @@ -230,6 +231,7 @@ class Demon2 : Demon1 Default { Obituary "$OB_DEMON2"; + HitObituary "$OB_DEMON2HIT"; Species "Demon2"; } States diff --git a/wadsrc/static/zscript/actors/hexen/magelightning.zs b/wadsrc/static/zscript/actors/hexen/magelightning.zs index 9c67b2b39a..764315ca25 100644 --- a/wadsrc/static/zscript/actors/hexen/magelightning.zs +++ b/wadsrc/static/zscript/actors/hexen/magelightning.zs @@ -147,7 +147,7 @@ class Lightning : Actor tracer = thing; } } - return 1; // lightning zaps through all sprites + return MHIT_PASS; // lightning zaps through all sprites } } @@ -417,7 +417,7 @@ class LightningZap : Actor } } } - return -1; + return MHIT_DEFAULT; } //============================================================================ diff --git a/wadsrc/static/zscript/actors/hexen/magestaff.zs b/wadsrc/static/zscript/actors/hexen/magestaff.zs index 782310c412..a0935e8c87 100644 --- a/wadsrc/static/zscript/actors/hexen/magestaff.zs +++ b/wadsrc/static/zscript/actors/hexen/magestaff.zs @@ -260,9 +260,9 @@ class MageStaffFX2 : Actor if (victim != target && !victim.player && !victim.bBoss) { victim.DamageMobj (self, target, 10, 'Fire'); - return 1; // Keep going + return MHIT_PASS; // Keep going } - return -1; + return MHIT_DEFAULT; } override bool SpecialBlastHandling (Actor source, double strength) diff --git a/wadsrc/static/zscript/actors/hexen/pig.zs b/wadsrc/static/zscript/actors/hexen/pig.zs index 45c601c4e2..95e90722e7 100644 --- a/wadsrc/static/zscript/actors/hexen/pig.zs +++ b/wadsrc/static/zscript/actors/hexen/pig.zs @@ -145,7 +145,7 @@ class PigPlayer : PlayerPawn override void MorphPlayerThink () { - if (player.morphTics & 15) + if ((player.MorphTics ? player.MorphTics : Random[PigPlayerThink]()) & 15) { return; } diff --git a/wadsrc/static/zscript/actors/inventory/inv_misc.zs b/wadsrc/static/zscript/actors/inventory/inv_misc.zs index 1d31022ad9..318d294913 100644 --- a/wadsrc/static/zscript/actors/inventory/inv_misc.zs +++ b/wadsrc/static/zscript/actors/inventory/inv_misc.zs @@ -33,6 +33,7 @@ class Key : Inventory Default { +DONTGIB; // Don't disappear due to a crusher + +INVENTORY.ISKEYITEM; Inventory.InterHubAmount 0; Inventory.PickupSound "misc/k_pkup"; } @@ -105,6 +106,7 @@ class PuzzleItem : Inventory { +NOGRAVITY +INVENTORY.INVBAR + +INVENTORY.ISKEYITEM Inventory.DefMaxAmount; Inventory.UseSound "PuzzleSuccess"; Inventory.PickupSound "misc/i_pkup"; diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 88bbd2f103..a2af103987 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -10,6 +10,10 @@ class Inventory : Actor const BLINKTHRESHOLD = (4*32); const BONUSADD = 6; + private bool bSharingItem; // Currently being shared (avoid infinite recursions). + private bool pickedUp[MAXPLAYERS]; // If items are set to local, track who already picked it up. + private bool bCreatingCopy; // Tells GoAway that it needs to return true so a new copy of the item is spawned. + deprecated("3.7") private int ItemFlags; Actor Owner; // Who owns this item? NULL if it's still a pickup. int Amount; // Amount of item this instance has @@ -65,6 +69,8 @@ class Inventory : Actor flagdef IsHealth: ItemFlags, 22; flagdef AlwaysPickup: ItemFlags, 23; flagdef Unclearable: ItemFlags, 24; + flagdef NeverLocal: ItemFlags, 25; + flagdef IsKeyItem: ItemFlags, 26; flagdef ForceRespawnInSurvival: none, 0; flagdef PickupFlash: none, 6; @@ -255,6 +261,43 @@ class Inventory : Actor } } + protected void ShareItemWithPlayers(Actor giver) + { + if (bSharingItem) + return; + + class type = GetClass(); + int skip = giver && giver.player ? giver.PlayerNumber() : -1; + + for (int i; i < MAXPLAYERS; ++i) + { + if (!playerInGame[i] || i == skip) + continue; + + let item = Inventory(Spawn(type)); + if (!item) + continue; + + item.bSharingItem = true; + if (!item.CallTryPickup(players[i].mo)) + { + item.Destroy(); + continue; + } + item.bSharingItem = false; + + if (!bQuiet) + { + PlayPickupSound(players[i].mo); + if (!bNoScreenFlash && players[i].PlayerState != PST_DEAD) + players[i].BonusCount = BONUSADD; + } + } + + if (!bQuiet && consoleplayer != skip) + PrintPickupMessage(true, PickupMessage()); + } + //=========================================================================== // // Inventory :: DoRespawn @@ -371,7 +414,10 @@ class Inventory : Actor { Inventory copy; - Amount = MIN(Amount, MaxAmount); + // Clamping this on local copy creation presents too many possible + // pitfalls (e.g. Health items). + if (!IsCreatingLocalCopy()) + Amount = MIN(Amount, MaxAmount); if (GoAway ()) { copy = Inventory(Spawn (GetClass())); @@ -597,8 +643,16 @@ class Inventory : Actor // unmorphed versions of a currently morphed actor cannot pick up anything. if (bUnmorphed) return false, null; - bool res; - if (CanPickup(toucher)) + //[AA] starting with true, so that CanReceive can unset it, + // if necessary: + bool res = true; + // [AA] CanReceive lets the actor receiving the item process it first. + if (!toucher.CanReceive(self)) + { + res = false; + } + // CanPickup processes restrictions by player class. + else if (CanPickup(toucher)) { res = TryPickup(toucher); } @@ -637,6 +691,12 @@ class Inventory : Actor } } } + // [AA] Let the toucher do something with the item they've just received: + toucher.HasReceived(self); + + // If the item can be shared, make sure every player gets a copy. + if (multiplayer && !deathmatch && sv_coopsharekeys && bIsKeyItem) + ShareItemWithPlayers(toucher); } return res, toucher; } @@ -758,12 +818,17 @@ class Inventory : Actor override void Touch (Actor toucher) { + bool localPickUp; let player = toucher.player; - - // If a voodoo doll touches something, pretend the real player touched it instead. - if (player != NULL) + if (player) { + // If a voodoo doll touches something, pretend the real player touched it instead. toucher = player.mo; + // Client already picked this up, so ignore them. + if (HasPickedUpLocally(toucher)) + return; + + localPickUp = CanPickUpLocally(toucher) && !ShouldStay() && !ShouldRespawn(); } bool localview = toucher.CheckLocalView(); @@ -771,9 +836,25 @@ class Inventory : Actor if (!toucher.CanTouchItem(self)) return; + Inventory give = self; + if (localPickUp) + { + give = CreateLocalCopy(toucher); + if (!give) + return; + + localPickUp = give != self; + } + bool res; - [res, toucher] = CallTryPickup(toucher); - if (!res) return; + [res, toucher] = give.CallTryPickup(toucher); + if (!res) + { + if (give != self) + give.Destroy(); + + return; + } // This is the only situation when a pickup flash should ever play. if (PickupFlash != NULL && !ShouldStay()) @@ -819,6 +900,9 @@ class Inventory : Actor ac.GiveSecret(true, true); } + if (localPickUp) + PickUpLocally(toucher); + //Added by MC: Check if item taken was the roam destination of any bot for (int i = 0; i < MAXPLAYERS; i++) { @@ -965,6 +1049,9 @@ class Inventory : Actor protected bool GoAway () { + if (IsCreatingLocalCopy()) + return true; + // Dropped items never stick around if (bDropped) { @@ -1004,6 +1091,53 @@ class Inventory : Actor SetStateLabel("HoldAndDestroy"); } } + + // Check if the Actor can recieve a local copy of the item instead of outright taking it. + clearscope bool CanPickUpLocally(Actor other) const + { + return other && other.player + && multiplayer && !deathmatch && sv_localitems + && !bNeverLocal && (!bDropped || !sv_nolocaldrops); + } + + // Check if a client has already picked up this item locally. + clearscope bool HasPickedUpLocally(Actor client) const + { + return pickedUp[client.PlayerNumber()]; + } + + // When items are dropped, clear their local pick ups. + void ClearLocalPickUps() + { + DisableLocalRendering(consoleplayer, false); + for (int i; i < MAXPLAYERS; ++i) + pickedUp[i] = false; + } + + // Client picked up this item. Mark it as invisible to that specific player and + // prevent them from picking it up again. + protected void PickUpLocally(Actor client) + { + int pNum = client.PlayerNumber(); + pickedUp[pNum] = true; + DisableLocalRendering(pNum, true); + } + + // Force spawn a new version of the item. This needs to use CreateCopy so that + // any transferrable properties on the item get correctly set. + Inventory CreateLocalCopy(Actor client) + { + bCreatingCopy = true; + let item = CreateCopy(client); + bCreatingCopy = false; + + return item; + } + + protected clearscope bool IsCreatingLocalCopy() const + { + return bCreatingCopy; + } //=========================================================================== // @@ -1021,6 +1155,10 @@ class Inventory : Actor //=========================================================================== virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive, Actor inflictor = null, Actor source = null, int flags = 0) {} + + virtual Vector2 ModifyBob(Vector2 Bob, double ticfrac) {return Bob;} + + virtual Vector3, Vector3 ModifyBob3D(Vector3 Translation, Vector3 Rotation, double ticfrac) {return Translation, Rotation;} virtual bool Use (bool pickup) { return false; } diff --git a/wadsrc/static/zscript/actors/inventory/powerups.zs b/wadsrc/static/zscript/actors/inventory/powerups.zs index 67983aae80..5d0f0d7daa 100644 --- a/wadsrc/static/zscript/actors/inventory/powerups.zs +++ b/wadsrc/static/zscript/actors/inventory/powerups.zs @@ -956,7 +956,7 @@ class PowerFlight : Powerup Owner.bNoGravity = true; if (Owner.pos.Z <= Owner.floorz) { - Owner.Vel.Z = 4;; // thrust the player in the air a bit + Owner.Vel.Z = 4; // thrust the player in the air a bit } if (Owner.Vel.Z <= -35) { // stop falling scream @@ -1870,19 +1870,22 @@ class PowerReflection : Powerup //=========================================================================== // // PowerMorph +// Now works with monsters too! // //=========================================================================== class PowerMorph : Powerup { - Class PlayerClass; - Class MorphFlash, UnMorphFlash; + class PlayerClass; + class MonsterClass, MorphFlash, UnmorphFlash; int MorphStyle; PlayerInfo MorphedPlayer; Default { Powerup.Duration -40; + PowerMorph.MorphFlash "TeleportFog"; + PowerMorph.UnmorphFlash "TeleportFog"; } //=========================================================================== @@ -1895,19 +1898,17 @@ class PowerMorph : Powerup { Super.InitEffect(); - if (Owner != null && Owner.player != null && PlayerClass != null) + if (!Owner) + return; + + if (Owner.Morph(Owner, PlayerClass, MonsterClass, int.max, MorphStyle, MorphFlash, UnmorphFlash)) { - let realplayer = Owner.player; // Remember the identity of the player - if (realplayer.mo.MorphPlayer(realplayer, PlayerClass, 0x7fffffff/*INDEFINITELY*/, MorphStyle, MorphFlash, UnMorphFlash)) - { - Owner = realplayer.mo; // Replace the new owner in our owner; safe because we are not attached to anything yet - bCreateCopyMoved = true; // Let the caller know the "real" owner has changed (to the morphed actor) - MorphedPlayer = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field) - } - else // morph failed - give the caller an opportunity to fail the pickup completely - { - bInitEffectFailed = true; // Let the caller know that the activation failed (can fail the pickup if appropriate) - } + bCreateCopyMoved = true; // Let the caller know the "real" owner has changed (to the morphed actor). + MorphedPlayer = Owner.player; + } + else + { + bInitEffectFailed = true; // Let the caller know that the activation failed (can fail the pickup if appropriate). } } @@ -1921,24 +1922,16 @@ class PowerMorph : Powerup { Super.EndEffect(); - // Abort if owner already destroyed or unmorphed - if (Owner == null || MorphedPlayer == null || Owner.alternative == null) - { + // Abort if owner already destroyed or unmorphed. + if (!Owner || !Owner.Alternative) return; - } // Abort if owner is dead; their Die() method will // take care of any required unmorphing on death. - if (MorphedPlayer.health <= 0) - { + if (Owner.player ? Owner.player.Health <= 0 : Owner.Health <= 0) return; - } - int savedMorphTics = MorphedPlayer.morphTics; - MorphedPlayer.mo.UndoPlayerMorph (MorphedPlayer, 0, !!(MorphedPlayer.MorphStyle & MRF_UNDOALWAYS)); + Owner.Unmorph(Owner, force: Owner.GetMorphStyle() & MRF_UNDOALWAYS); MorphedPlayer = null; } - - } - diff --git a/wadsrc/static/zscript/actors/inventory/stateprovider.zs b/wadsrc/static/zscript/actors/inventory/stateprovider.zs index 21295c315f..e022872585 100644 --- a/wadsrc/static/zscript/actors/inventory/stateprovider.zs +++ b/wadsrc/static/zscript/actors/inventory/stateprovider.zs @@ -210,7 +210,7 @@ class StateProvider : Inventory action Actor, Actor A_FireProjectile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0) { let player = self.player; - if (!player) return null; + if (!player) return null, null; let weapon = player.ReadyWeapon; @@ -220,7 +220,7 @@ class StateProvider : Inventory if (useammo && weapon && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { if (!weapon.DepleteAmmo(weapon.bAltFire, true)) - return null; // out of ammo + return null, null; // out of ammo } if (missiletype) diff --git a/wadsrc/static/zscript/actors/inventory/weapons.zs b/wadsrc/static/zscript/actors/inventory/weapons.zs index d4aa0e57da..66a7f8964c 100644 --- a/wadsrc/static/zscript/actors/inventory/weapons.zs +++ b/wadsrc/static/zscript/actors/inventory/weapons.zs @@ -39,6 +39,12 @@ class Weapon : StateProvider meta double SlotPriority; Vector3 BobPivot3D; // Pivot used for BobWeapon3D + + virtual ui Vector2 ModifyBobLayer(Vector2 Bob, int layer, double ticfrac) { return Bob; } + + virtual ui Vector3, Vector3 ModifyBobLayer3D(Vector3 Translation, Vector3 Rotation, int layer, double ticfrac) { return Translation, Rotation; } + + virtual ui Vector3 ModifyBobPivotLayer3D(int layer, double ticfrac) { return BobPivot3D; } property AmmoGive: AmmoGive1; property AmmoGive1: AmmoGive1; @@ -256,7 +262,7 @@ class Weapon : StateProvider } let psp = player.GetPSprite(PSP_WEAPON); if (!psp) return; - if (player.morphTics || player.cheats & CF_INSTANTWEAPSWITCH) + if (Alternative || player.cheats & CF_INSTANTWEAPSWITCH) { psp.y = WEAPONBOTTOM; } @@ -932,6 +938,7 @@ class Weapon : StateProvider int count1, count2; int enough, enoughmask; int lAmmoUse1; + int lAmmoUse2 = AmmoUse2; if (sv_infiniteammo || (Owner.FindInventory ('PowerInfiniteAmmo', true) != null)) { @@ -961,16 +968,17 @@ class Weapon : StateProvider { lAmmoUse1 = 0; } - else if (ammocount >= 0 && bDehAmmo) + else if (ammocount >= 0) { lAmmoUse1 = ammocount; + lAmmoUse2 = ammocount; } else { lAmmoUse1 = AmmoUse1; } - enough = (count1 >= lAmmoUse1) | ((count2 >= AmmoUse2) << 1); + enough = (count1 >= lAmmoUse1) | ((count2 >= lAmmoUse2) << 1); if (useboth) { enoughmask = 3; diff --git a/wadsrc/static/zscript/actors/inventory_util.zs b/wadsrc/static/zscript/actors/inventory_util.zs index e1820a86da..1bb9be5126 100644 --- a/wadsrc/static/zscript/actors/inventory_util.zs +++ b/wadsrc/static/zscript/actors/inventory_util.zs @@ -291,6 +291,8 @@ extend class Actor { Inventory drop = item.CreateTossable(amt); if (drop == null) return NULL; + drop.ClearLocalPickUps(); + drop.bNeverLocal = true; drop.SetOrigin(Pos + (0, 0, 10.), false); drop.Angle = Angle; drop.VelFromAngle(5.); diff --git a/wadsrc/static/zscript/actors/morph.zs b/wadsrc/static/zscript/actors/morph.zs index 1dcfb31faf..b9fdbb101f 100644 --- a/wadsrc/static/zscript/actors/morph.zs +++ b/wadsrc/static/zscript/actors/morph.zs @@ -23,8 +23,78 @@ extend class Actor { + // Blockmap, sector, and no interaction are the only relevant flags but the old ones are kept around + // for legacy reasons. + enum EPremorphProperty + { + MPROP_SOLID = 1 << 1, + MPROP_SHOOTABLE = 1 << 2, + MPROP_NO_BLOCKMAP = 1 << 3, + MPROP_NO_SECTOR = 1 << 4, + MPROP_NO_INTERACTION = 1 << 5, + MPROP_INVIS = 1 << 6, + } + + int UnmorphTime; + EMorphFlags MorphFlags; + class MorphExitFlash; + EPremorphProperty PremorphProperties; + + // Players still track these separately for legacy reasons. + void SetMorphStyle(EMorphFlags flags) + { + if (player) + player.MorphStyle = flags; + else + MorphFlags = flags; + } + + clearscope EMorphFlags GetMorphStyle() const + { + return player ? player.MorphStyle : MorphFlags; + } + + void SetMorphExitFlash(class flash) + { + if (player) + player.MorphExitFlash = flash; + else + MorphExitFlash = flash; + } + + clearscope class GetMorphExitFlash() const + { + return player ? player.MorphExitFlash : MorphExitFlash; + } + + void SetMorphTics(int dur) + { + if (player) + player.MorphTics = dur; + else + UnmorphTime = Level.Time + dur; + } + + clearscope int GetMorphTics() const + { + if (player) + return player.MorphTics; + + if (UnmorphTime <= 0) + return UnmorphTime; + + return UnmorphTime > Level.Time ? UnmorphTime - Level.Time : 0; + } + + // This function doesn't return anything anymore since allowing so would be too volatile + // for morphing management. Instead it's now a function that lets special actions occur + // when a morphed Actor dies. virtual Actor, int, int MorphedDeath() { + EMorphFlags mStyle = GetMorphStyle(); + if (mStyle & MRF_UNDOBYDEATH) + Unmorph(self, force: mStyle & MRF_UNDOBYDEATHFORCED); + return null, 0, 0; } @@ -40,16 +110,12 @@ extend class Actor // //=========================================================================== - virtual bool Morph(Actor activator, class playerclass, class monsterclass, int duration = 0, int style = 0, class morphflash = null, classunmorphflash = null) + virtual bool Morph(Actor activator, class playerClass, class monsterClass, int duration = 0, EMorphFlags style = 0, class morphFlash = "TeleportFog", class unmorphFlash = "TeleportFog") { - if (player != null && player.mo != null && playerclass != null) - { - return player.mo.MorphPlayer(activator? activator.player : null, playerclass, duration, style, morphflash, unmorphflash); - } - else - { - return MorphMonster(monsterclass, duration, style, morphflash, unmorphflash); - } + if (player) + return player.mo.MorphPlayer(activator ? activator.player : null, playerClass, duration, style, morphFlash, unmorphFlash); + + return MorphMonster(monsterClass, duration, style, morphFlash, unmorphFlash); } //=========================================================================== @@ -58,18 +124,9 @@ extend class Actor // //=========================================================================== - bool A_Morph(class type, int duration = 0, int style = 0, class morphflash = null, classunmorphflash = null) + bool A_Morph(class type, int duration = 0, EMorphFlags style = 0, class morphFlash = "TeleportFog", class unmorphFlash = "TeleportFog") { - if (self.player != null) - { - let playerclass = (class)(type); - if (playerclass && self.player.mo != null) return player.mo.MorphPlayer(self.player, playerclass, duration, style, morphflash, unmorphflash); - } - else - { - return MorphMonster(type, duration, style, morphflash, unmorphflash); - } - return false; + return Morph(self, (class)(type), type, duration, style, morphFlash, unmorphFlash); } //=========================================================================== @@ -78,21 +135,18 @@ extend class Actor // //=========================================================================== - virtual bool UnMorph(Actor activator, int flags, bool force) + virtual bool Unmorph(Actor activator, EMorphFlags flags = 0, bool force = false) { if (player) - { - return player.mo.UndoPlayerMorph(activator? activator.player : null, flags, force); - } - else - { - let morphed = MorphedMonster(self); - if (morphed) - return morphed.UndoMonsterMorph(force); - } - return false; + return player.mo.UndoPlayerMorph(activator ? activator.player : null, flags, force); + + return UndoMonsterMorph(force); } + virtual bool CheckUnmorph() + { + return UnmorphTime && UnmorphTime <= Level.Time && Unmorph(self, MRF_UNDOBYTIMEOUT); + } //--------------------------------------------------------------------------- // @@ -102,57 +156,265 @@ extend class Actor // //--------------------------------------------------------------------------- - virtual bool MorphMonster (Class spawntype, int duration, int style, Class enter_flash, Class exit_flash) + virtual bool MorphMonster(class spawnType, int duration, EMorphFlags style, class enterFlash = "TeleportFog", class exitFlash = "TeleportFog") { - if (player || spawntype == NULL || bDontMorph || !bIsMonster || !(spawntype is 'MorphedMonster')) + if (player || !bIsMonster || !spawnType || bDontMorph || Health <= 0 || spawnType == GetClass()) + return false; + + Actor morphed = Spawn(spawnType, Pos, ALLOW_REPLACE); + if (!MorphInto(morphed)) { + if (morphed) + { + morphed.ClearCounters(); + morphed.Destroy(); + } + return false; } - let morphed = MorphedMonster(Spawn (spawntype, Pos, NO_REPLACE)); - // [MC] Notify that we're just about to start the transfer. PreMorph(morphed, false); // False: No longer the current. morphed.PreMorph(self, true); // True: Becoming this actor. - Substitute (morphed); if ((style & MRF_TRANSFERTRANSLATION) && !morphed.bDontTranslate) - { morphed.Translation = Translation; - } - morphed.ChangeTid(tid); - ChangeTid(0); + morphed.Angle = Angle; - morphed.UnmorphedMe = self; morphed.Alpha = Alpha; morphed.RenderStyle = RenderStyle; - morphed.Score = Score; - - morphed.UnmorphTime = level.time + ((duration) ? duration : DEFMORPHTICS) + random[morphmonst](); - morphed.MorphStyle = style; - morphed.MorphExitFlash = (exit_flash) ? exit_flash : (class)("TeleportFog"); - morphed.FlagsSave = bSolid * 2 + bShootable * 4 + bInvisible * 0x40; // The factors are for savegame compatibility - - morphed.special = special; - morphed.args[0] = args[0]; - morphed.args[1] = args[1]; - morphed.args[2] = args[2]; - morphed.args[3] = args[3]; - morphed.args[4] = args[4]; - morphed.CopyFriendliness (self, true); morphed.bShadow |= bShadow; morphed.bGhost |= bGhost; - special = 0; - bSolid = false; - bShootable = false; - bUnmorphed = true; + morphed.Score = Score; + morphed.Special = Special; + for (int i; i < 5; ++i) + morphed.Args[i] = Args[i]; + + if (TID && (style & MRF_NEWTIDBEHAVIOUR)) + { + morphed.ChangeTID(TID); + ChangeTID(0); + } + + morphed.Tracer = Tracer; + morphed.Master = Master; + morphed.CopyFriendliness(self, true); + + // Remove all armor. + if (!(style & MRF_KEEPARMOR)) + { + for (Inventory item = morphed.Inv; item;) + { + Inventory next = item.Inv; + if (item is "Armor") + item.DepleteOrDestroy(); + + item = next; + } + } + + morphed.SetMorphTics((duration ? duration : DEFMORPHTICS) + Random[morphmonst]()); + morphed.SetMorphStyle(style); + morphed.SetMorphExitFlash(exitFlash); + morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE) + | (bNoBlockmap * MPROP_NO_BLOCKMAP) | (bNoSector * MPROP_NO_SECTOR) + | (bNoInteraction * MPROP_NO_INTERACTION) | (bInvisible * MPROP_INVIS); + + // This is just here for backwards compatibility as MorphedMonster used to be required. + let morphMon = MorphedMonster(morphed); + if (morphMon) + { + morphMon.UnmorphedMe = morphMon.Alternative; + morphMon.MorphStyle = morphMon.GetMorphStyle(); + morphMon.FlagsSave = morphMon.PremorphProperties; + } + + Special = 0; + bNoInteraction = true; + A_ChangeLinkFlags(true, true); + + // Legacy bInvisible = true; - let eflash = Spawn(enter_flash ? enter_flash : (class)("TeleportFog"), Pos + (0, 0, gameinfo.TELEFOGHEIGHT), ALLOW_REPLACE); - if (eflash) - eflash.target = morphed; + bSolid = bShootable = false; + PostMorph(morphed, false); morphed.PostMorph(self, true); + + if (enterFlash) + { + Actor fog = Spawn(enterFlash, morphed.Pos.PlusZ(GameInfo.TELEFOGHEIGHT), ALLOW_REPLACE); + if (fog) + fog.Target = morphed; + } + + return true; + } + + //---------------------------------------------------------------------------- + // + // FUNC P_UndoMonsterMorph + // + // Returns true if the monster unmorphs. + // + //---------------------------------------------------------------------------- + + virtual bool UndoMonsterMorph(bool force = false) + { + if (!Alternative || bStayMorphed || Alternative.bStayMorphed) + return false; + + Actor alt = Alternative; + alt.SetOrigin(Pos, false); + if (!force && (PremorphProperties & MPROP_SOLID)) + { + bool altSolid = alt.bSolid; + bool isSolid = bSolid; + bool isTouchy = bTouchy; + + alt.bSolid = true; + bSolid = bTouchy = false; + + bool res = alt.TestMobjLocation(); + + alt.bSolid = altSolid; + bSolid = isSolid; + bTouchy = isTouchy; + + // Didn't fit. + if (!res) + { + SetMorphTics(5 * TICRATE); + return false; + } + } + + if (!MorphInto(alt)) + return false; + + PreUnmorph(alt, false); + alt.PreUnmorph(self, true); + + // Check to see if it had a powerup that caused it to morph. + for (Inventory item = alt.Inv; item;) + { + Inventory next = item.Inv; + if (item is "PowerMorph") + item.Destroy(); + + item = next; + } + + alt.Angle = Angle; + alt.bShadow = bShadow; + alt.bGhost = bGhost; + alt.bSolid = (PremorphProperties & MPROP_SOLID); + alt.bShootable = (PremorphProperties & MPROP_SHOOTABLE); + alt.bInvisible = (PremorphProperties & MPROP_INVIS); + alt.Vel = Vel; + alt.Score = Score; + + alt.bNoInteraction = (PremorphProperties & MPROP_NO_INTERACTION); + alt.A_ChangeLinkFlags((PremorphProperties & MPROP_NO_BLOCKMAP), (PremorphProperties & MPROP_NO_SECTOR)); + + EMorphFlags style = GetMorphStyle(); + if (TID && (style & MRF_NEWTIDBEHAVIOUR)) + { + alt.ChangeTID(TID); + ChangeTID(0); + } + + alt.Special = Special; + for (int i; i < 5; ++i) + alt.Args[i] = Args[i]; + + alt.Tracer = Tracer; + alt.Master = Master; + alt.CopyFriendliness(self, true, false); + if (Health > 0 || (style & MRF_UNDOBYDEATHSAVES)) + alt.Health = alt.SpawnHealth(); + else + alt.Health = Health; + + Special = 0; + + PostUnmorph(alt, false); // From is false here: Leaving the caller's body. + alt.PostUnmorph(self, true); // True here: Entering this body from here. + + if (MorphExitFlash) + { + Actor fog = Spawn(MorphExitFlash, alt.Pos.PlusZ(GameInfo.TELEFOGHEIGHT), ALLOW_REPLACE); + if (fog) + fog.Target = alt; + } + + ClearCounters(); + Destroy(); return true; } } +//=========================================================================== +// +// +// +//=========================================================================== + +class MorphProjectile : Actor +{ + class PlayerClass; + class MonsterClass, MorphFlash, UnmorphFlash; + int Duration, MorphStyle; + + Default + { + Damage 1; + Projectile; + MorphProjectile.MorphFlash "TeleportFog"; + MorphProjectile.UnmorphFlash "TeleportFog"; + + -ACTIVATEIMPACT + -ACTIVATEPCROSS + } + + override int DoSpecialDamage(Actor victim, int dmg, Name dmgType) + { + victim.Morph(Target, PlayerClass, MonsterClass, Duration, MorphStyle, MorphFlash, UnmorphFlash); + return -1; + } +} + +//=========================================================================== +// +// This class is redundant as it's no longer necessary for monsters to +// morph but is kept here for compatibility. Its previous fields either exist +// in the base Actor now or are just a shell for the actual fields +// which either already existed and weren't used for some reason or needed a +// better name. +// +//=========================================================================== + +class MorphedMonster : Actor +{ + Actor UnmorphedMe; + EMorphFlags MorphStyle; + EPremorphProperty FlagsSave; + + Default + { + Monster; + + +FLOORCLIP + -COUNTKILL + } + + // Make sure changes to these are propogated correctly when unmorphing. This is only + // set for monsters since originally players and this class were the only ones + // that were considered valid for morphing. + override bool UndoMonsterMorph(bool force) + { + Alternative = UnmorphedMe; + SetMorphStyle(MorphStyle); + PremorphProperties = FlagsSave; + return super.UndoMonsterMorph(force); + } +} diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 5f6d0f616a..0cee7a7f32 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -40,7 +40,7 @@ class PlayerPawn : Actor double SideMove1, SideMove2; TextureID ScoreIcon; int SpawnMask; - Name MorphWeapon; + Name MorphWeapon; // This should really be a class but it's too late to change now. double AttackZOffset; // attack height, relative to player center double UseRange; // [NS] Distance at which player can +use double AirCapacity; // Multiplier for air supply underwater. @@ -48,6 +48,7 @@ class PlayerPawn : Actor color DamageFade; // [CW] Fades for when you are being damaged. double FlyBob; // [B] Fly bobbing mulitplier double ViewBob; // [SP] ViewBob Multiplier + double ViewBobSpeed; // [AA] ViewBob speed multiplier double WaterClimbSpeed; // [B] Speed when climbing up walls in water double FullHeight; double curBob; @@ -79,6 +80,7 @@ class PlayerPawn : Actor property TeleportFreezeTime: TeleportFreezeTime; property FlyBob: FlyBob; property ViewBob: ViewBob; + property ViewBobSpeed: ViewBobSpeed; property WaterClimbSpeed : WaterClimbSpeed; flagdef NoThrustWhenInvul: PlayerFlags, 0; @@ -128,6 +130,7 @@ class PlayerPawn : Actor Player.AirCapacity 1; Player.FlyBob 1; Player.ViewBob 1; + Player.ViewBobSpeed 20; Player.WaterClimbSpeed 3.5; Player.TeleportFreezeTime 18; Obituary "$OB_MPDEFAULT"; @@ -474,7 +477,7 @@ class PlayerPawn : Actor let player = self.player; if (!player) return; if ((player.WeaponState & WF_DISABLESWITCH) || // Weapon changing has been disabled. - player.morphTics != 0) // Morphed classes cannot change weapons. + Alternative) // Morphed classes cannot change weapons. { // ...so throw away any pending weapon requests. player.PendingWeapon = WP_NOCHANGE; } @@ -619,7 +622,7 @@ class PlayerPawn : Actor } else { - angle = Level.maptime / (20 * TICRATE / 35.) * 360.; + angle = Level.maptime / (ViewBobSpeed * TICRATE / 35.) * 360.; bob = player.bob * sin(angle) * (waterlevel > 1 ? 0.25f : 0.5f); } @@ -648,7 +651,7 @@ class PlayerPawn : Actor } } - if (player.morphTics) + if (Alternative) { bob = 0; } @@ -864,7 +867,7 @@ class PlayerPawn : Actor // //=========================================================================== - void FilterCoopRespawnInventory (PlayerPawn oldplayer) + void FilterCoopRespawnInventory (PlayerPawn oldplayer, Weapon curHeldWeapon = null) { // If we're losing everything, this is really simple. if (sv_cooploseinventory) @@ -873,6 +876,10 @@ class PlayerPawn : Actor return; } + // Make sure to get the real held weapon before messing with the inventory. + if (curHeldWeapon && curHeldWeapon.bPowered_Up) + curHeldWeapon = curHeldWeapon.SisterWeapon; + // Walk through the old player's inventory and destroy or modify // according to dmflags. Inventory next; @@ -885,7 +892,7 @@ class PlayerPawn : Actor // inventory amount. let defitem = FindInventory (item.GetClass()); - if (sv_cooplosekeys && defitem == NULL && item is 'Key') + if ((sv_cooplosekeys && !sv_coopsharekeys) && defitem == NULL && item is 'Key') { item.Destroy(); } @@ -954,7 +961,15 @@ class PlayerPawn : Actor ObtainInventory (oldplayer); player.ReadyWeapon = NULL; - PickNewWeapon (NULL); + if (curHeldWeapon && curHeldWeapon.owner == self && curHeldWeapon.CheckAmmo(Weapon.EitherFire, false)) + { + player.PendingWeapon = curHeldWeapon; + BringUpWeapon(); + } + else + { + PickNewWeapon (NULL); + } } @@ -1069,7 +1084,7 @@ class PlayerPawn : Actor virtual bool CanCrouch() const { - return player.morphTics == 0 || bCrouchableMorph; + return !Alternative || bCrouchableMorph; } //---------------------------------------------------------------------------- @@ -1235,7 +1250,7 @@ class PlayerPawn : Actor side *= SideMove2; } - if (!player.morphTics) + if (!Alternative) { double factor = 1.; for(let it = Inv; it != null; it = it.Inv) @@ -1248,6 +1263,12 @@ class PlayerPawn : Actor return forward, side; } + virtual void ApplyAirControl(out double movefactor, out double bobfactor) + { + movefactor *= level.aircontrol; + bobfactor *= level.aircontrol; + } + //---------------------------------------------------------------------------- // // PROC P_MovePlayer @@ -1291,8 +1312,8 @@ class PlayerPawn : Actor if (!player.onground && !bNoGravity && !waterlevel) { // [RH] allow very limited movement if not on ground. - movefactor *= level.aircontrol; - bobfactor*= level.aircontrol; + // [AA] but also allow authors to override it. + ApplyAirControl(movefactor, bobfactor); } fm = cmd.forwardmove; @@ -1525,15 +1546,15 @@ class PlayerPawn : Actor { let player = self.player; // Morph counter - if (player.morphTics) + if (Alternative) { if (player.chickenPeck) { // Chicken attack counter player.chickenPeck -= 3; } - if (!--player.morphTics) + if (player.MorphTics && !--player.MorphTics) { // Attempt to undo the chicken/pig - player.mo.UndoPlayerMorph(player, MRF_UNDOBYTIMEOUT); + Unmorph(self, MRF_UNDOBYTIMEOUT); } } } @@ -1658,7 +1679,7 @@ class PlayerPawn : Actor player.jumpTics = 0; } } - if (player.morphTics && !(player.cheats & CF_PREDICTING)) + if (Alternative && !(player.cheats & CF_PREDICTING)) { MorphPlayerThink (); } @@ -2039,9 +2060,9 @@ class PlayerPawn : Actor Inventory item, next; let p = player; - if (p.morphTics != 0) + if (Alternative) { // Undo morph - Unmorph(self, 0, true); + Unmorph(self, force: true); } // 'self' will be no longer valid from here on in case of an unmorph let me = p.mo; @@ -2111,7 +2132,7 @@ class PlayerPawn : Actor let it = toDelete[i]; if (!it.bDestroyed) { - item.DepleteOrDestroy(); + it.DepleteOrDestroy(); } } } @@ -2664,7 +2685,7 @@ class PSprite : Object native play native Bool firstTic; native bool InterpolateTic; native int Tics; - native uint Translation; + native TranslationID Translation; native bool bAddWeapon; native bool bAddBob; native bool bPowDouble; @@ -2687,13 +2708,23 @@ class PSprite : Object native play { if (processPending) { - // drop tic count and possibly change state - if (Tics != -1) // a -1 tic count never changes + if (Caller) + { + Caller.PSpriteTick(self); + if (bDestroyed) + return; + } + + if (processPending) { - Tics--; - // [BC] Apply double firing speed. - if (bPowDouble && Tics && (Owner.mo.FindInventory ("PowerDoubleFiringSpeed", true))) Tics--; - if (!Tics && Caller != null) SetState(CurState.NextState); + // drop tic count and possibly change state + if (Tics != -1) // a -1 tic count never changes + { + Tics--; + // [BC] Apply double firing speed. + if (bPowDouble && Tics && (Owner.mo.FindInventory ("PowerDoubleFiringSpeed", true))) Tics--; + if (!Tics && Caller != null) SetState(CurState.NextState); + } } } } @@ -2848,23 +2879,15 @@ struct PlayerInfo native play // self is what internally is known as player_t native clearscope bool HasWeaponsInSlot(int slot) const; // The actual implementation is on PlayerPawn where it can be overridden. Use that directly in the future. - deprecated("3.7", "MorphPlayer() should be used on a PlayerPawn object") bool MorphPlayer(playerinfo p, Class spawntype, int duration, int style, Class enter_flash = null, Class exit_flash = null) + deprecated("3.7", "MorphPlayer() should be used on a PlayerPawn object") bool MorphPlayer(PlayerInfo activator, class spawnType, int duration, EMorphFlags style, class enterFlash = "TeleportFog", class exitFlash = "TeleportFog") { - if (mo != null) - { - return mo.MorphPlayer(p, spawntype, duration, style, enter_flash, exit_flash); - } - return false; + return mo ? mo.MorphPlayer(activator, spawnType, duration, style, enterFlash, exitFlash) : false; } // This somehow got its arguments mixed up. 'self' should have been the player to be unmorphed, not the activator - deprecated("3.7", "UndoPlayerMorph() should be used on a PlayerPawn object") bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false) + deprecated("3.7", "UndoPlayerMorph() should be used on a PlayerPawn object") bool UndoPlayerMorph(PlayerInfo player, EMorphFlags unmorphFlags = 0, bool force = false) { - if (player.mo != null) - { - return player.mo.UndoPlayerMorph(self, unmorphflag, force); - } - return false; + return player.mo ? player.mo.UndoPlayerMorph(self, unmorphFlags, force) : false; } deprecated("3.7", "DropWeapon() should be used on a PlayerPawn object") void DropWeapon() @@ -2956,7 +2979,16 @@ struct PlayerSkin native struct Team native { - const NoTeam = 255; - const Max = 16; + const NOTEAM = 255; + const MAX = 16; + native String mName; + + native static bool IsValid(uint teamIndex); + + native Color GetPlayerColor() const; + native int GetTextColor() const; + native TextureID GetLogo() const; + native string GetLogoName() const; + native bool AllowsCustomPlayerColor() const; } diff --git a/wadsrc/static/zscript/actors/player/player_cheat.zs b/wadsrc/static/zscript/actors/player/player_cheat.zs index adacdfb522..c89832dca6 100644 --- a/wadsrc/static/zscript/actors/player/player_cheat.zs +++ b/wadsrc/static/zscript/actors/player/player_cheat.zs @@ -426,35 +426,40 @@ extend class PlayerPawn } - virtual String CheatMorph(class morphClass, bool quickundo) + virtual String CheatMorph(class morphClass, bool undo) { - let oldclass = GetClass(); - // Set the standard morph style for the current game - int style = MRF_UNDOBYTOMEOFPOWER; - if (gameinfo.gametype == GAME_Hexen) style |= MRF_UNDOBYCHAOSDEVICE; + EMorphFlags style = MRF_UNDOBYTOMEOFPOWER; + if (GameInfo.GameType == GAME_Hexen) + style |= MRF_UNDOBYCHAOSDEVICE; - if (player.morphTics) + if (Alternative) { - if (UndoPlayerMorph (player)) + class cls = GetClass(); + Actor mo = Alternative; + if (!undo || Unmorph(self)) { - if (!quickundo && oldclass != morphclass && MorphPlayer (player, morphclass, 0, style)) + if ((!undo && Morph(self, morphClass, null, 0, style)) + || (undo && morphClass != cls && mo.Morph(mo, morphClass, null, 0, style))) { return StringTable.Localize("$TXT_STRANGER"); } - return StringTable.Localize("$TXT_NOTSTRANGE"); + + if (undo) + return StringTable.Localize("$TXT_NOTSTRANGE"); } } - else if (MorphPlayer (player, morphclass, 0, style)) + else if (Morph(self, morphClass, null, 0, style)) { return StringTable.Localize("$TXT_STRANGE"); } + return ""; } virtual void CheatTakeWeaps() { - if (player.morphTics || health <= 0) + if (Alternative || health <= 0) { return; } diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index 77df1ef269..ff84246a16 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -1,26 +1,25 @@ extend class PlayerPawn { - private native void Substitute(PlayerPawn replacement); - //=========================================================================== // - // EndAllPowerupEffects + // InitAllPowerupEffects // - // Calls EndEffect() on every Powerup in the inventory list. + // Calls InitEffect() on every Powerup in the inventory list. Since these + // functions can be overridden it's safest to store what's next in the item + // list before calling it. // //=========================================================================== void InitAllPowerupEffects() { - let item = Inv; - while (item != null) + for (Inventory item = Inv; item;) { + Inventory next = item.Inv; let power = Powerup(item); - if (power != null) - { + if (power) power.InitEffect(); - } - item = item.Inv; + + item = next; } } @@ -34,15 +33,14 @@ extend class PlayerPawn void EndAllPowerupEffects() { - let item = Inv; - while (item != null) + for (Inventory item = Inv; item;) { + Inventory next = item.Inv; let power = Powerup(item); - if (power != null) - { + if (power) power.EndEffect(); - } - item = item.Inv; + + item = next; } } @@ -52,47 +50,37 @@ extend class PlayerPawn // //=========================================================================== - virtual void ActivateMorphWeapon () + virtual void ActivateMorphWeapon() { - class morphweaponcls = MorphWeapon; - player.PendingWeapon = WP_NOCHANGE; - - if (player.ReadyWeapon != null) + if (player.ReadyWeapon) { let psp = player.GetPSprite(PSP_WEAPON); - if (psp) - { - psp.y = WEAPONTOP; - player.ReadyWeapon.ResetPSprite(psp); - } + psp.y = WEAPONTOP; + player.ReadyWeapon.ResetPSprite(psp); } - - if (morphweaponcls == null || !(morphweaponcls is 'Weapon')) - { // No weapon at all while morphed! + + class morphWeapCls = MorphWeapon; + if (!morphWeapCls) + { player.ReadyWeapon = null; } else { - player.ReadyWeapon = Weapon(FindInventory (morphweaponcls)); - if (player.ReadyWeapon == null) + player.ReadyWeapon = Weapon(FindInventory(morphWeapCls)); + if (!player.ReadyWeapon) { - player.ReadyWeapon = Weapon(GiveInventoryType (morphweaponcls)); - if (player.ReadyWeapon != null) - { - player.ReadyWeapon.GivenAsMorphWeapon = true; // flag is used only by new beastweap semantics in UndoPlayerMorph - } + player.ReadyWeapon = Weapon(GiveInventoryType(morphWeapCls)); + if (player.ReadyWeapon) + player.ReadyWeapon.GivenAsMorphWeapon = true; // Flag is used only by new morphWeap semantics in UndoPlayerMorph } - if (player.ReadyWeapon != null) - { - player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.GetReadyState()); - } - } - if (player.ReadyWeapon != null) - { - player.SetPsprite(PSP_FLASH, null); + if (player.ReadyWeapon) + player.SetPSprite(PSP_WEAPON, player.ReadyWeapon.GetReadyState()); } + if (player.ReadyWeapon) + player.SetPSprite(PSP_FLASH, null); + player.PendingWeapon = WP_NOCHANGE; } @@ -107,125 +95,122 @@ extend class PlayerPawn // //--------------------------------------------------------------------------- - virtual bool MorphPlayer(playerinfo activator, Class spawntype, int duration, int style, Class enter_flash = null, Class exit_flash = null) + virtual bool MorphPlayer(PlayerInfo activator, class spawnType, int duration, EMorphFlags style, class enterFlash = "TeleportFog", class exitFlash = "TeleportFog") { - if (bDontMorph) + if (!player || !spawnType || bDontMorph || player.Health <= 0 + || (!(style & MRF_IGNOREINVULN) && bInvulnerable && (player != activator || !(style & MRF_WHENINVULNERABLE)))) { return false; } - if (bInvulnerable && (player != activator || !(style & MRF_WHENINVULNERABLE))) - { // Immune when invulnerable unless this is a power we activated - return false; - } - if (player.morphTics) - { // Player is already a beast - if ((GetClass() == spawntype) && bCanSuperMorph - && (player.morphTics < (((duration) ? duration : DEFMORPHTICS) - TICRATE)) - && FindInventory('PowerWeaponLevel2', true) == null) - { // Make a super chicken - GiveInventoryType ('PowerWeaponLevel2'); - } - return false; - } - if (health <= 0) - { // Dead players cannot morph - return false; - } - if (spawntype == null) - { - return false; - } - if (!(spawntype is 'PlayerPawn')) + + if (!duration) + duration = DEFMORPHTICS; + + if (spawnType == GetClass()) { + // Player is already a beast. + if (Alternative && bCanSuperMorph + && GetMorphTics() < duration - TICRATE + && !FindInventory("PowerWeaponLevel2", true)) + { + // Make a super chicken. + GiveInventoryType("PowerWeaponLevel2"); + } + return false; } - if (spawntype == GetClass()) + + let morphed = PlayerPawn(Spawn(spawnType, Pos, NO_REPLACE)); + if (!MorphInto(morphed)) { + if (morphed) + morphed.Destroy(); + return false; } - let morphed = PlayerPawn(Spawn (spawntype, Pos, NO_REPLACE)); - - // Use GetClass in the event someone actually allows replacements. PreMorph(morphed, false); morphed.PreMorph(self, true); - EndAllPowerupEffects(); - Substitute(morphed); + morphed.EndAllPowerupEffects(); + if ((style & MRF_TRANSFERTRANSLATION) && !morphed.bDontTranslate) - { morphed.Translation = Translation; - } - if (tid != 0 && (style & MRF_NEWTIDBEHAVIOUR)) - { - morphed.ChangeTid(tid); - ChangeTid(0); - } + morphed.Angle = Angle; - morphed.target = target; - morphed.tracer = tracer; - morphed.alternative = self; + morphed.Pitch = Pitch; // Allow pitch here since mouse look in GZDoom is far more common than Heretic/Hexen. + morphed.Target = Target; + morphed.Tracer = Tracer; + morphed.Master = Master; morphed.FriendPlayer = FriendPlayer; morphed.DesignatedTeam = DesignatedTeam; morphed.Score = Score; - player.PremorphWeapon = player.ReadyWeapon; - - morphed.special2 = bSolid * 2 + bShootable * 4 + bInvisible * 0x40; // The factors are for savegame compatibility - morphed.player = player; - - if (morphed.ViewHeight > player.viewheight && player.deltaviewheight == 0) - { // If the new view height is higher than the old one, start moving toward it. - player.deltaviewheight = player.GetDeltaViewHeight(); + morphed.ScoreIcon = ScoreIcon; + morphed.Health = morphed.SpawnHealth(); + if (TID && (style & MRF_NEWTIDBEHAVIOUR)) + { + morphed.ChangeTid(TID); + ChangeTid(0); } + + // special2 is no longer used here since Actors now have a proper field for it. + morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE) + | (bNoBlockmap * MPROP_NO_BLOCKMAP) | (bNoSector * MPROP_NO_SECTOR) + | (bNoInteraction * MPROP_NO_INTERACTION) | (bInvisible * MPROP_INVIS); + morphed.bShadow |= bShadow; morphed.bNoGravity |= bNoGravity; morphed.bFly |= bFly; morphed.bGhost |= bGhost; - if (enter_flash == null) enter_flash = 'TeleportFog'; - let eflash = Spawn(enter_flash, Pos + (0, 0, gameinfo.telefogheight), ALLOW_REPLACE); - let p = player; - player = null; - alternative = morphed; - bSolid = false; - bShootable = false; - bUnmorphed = true; - bInvisible = true; - - p.morphTics = (duration) ? duration : DEFMORPHTICS; - - // [MH] Used by SBARINFO to speed up face drawing - p.MorphedPlayerClass = spawntype; - - p.MorphStyle = style; - if (exit_flash == null) exit_flash = 'TeleportFog'; - p.MorphExitFlash = exit_flash; - p.health = morphed.health; - p.mo = morphed; - p.vel = (0, 0); - morphed.ObtainInventory (self); - // Remove all armor - for (Inventory item = morphed.Inv; item != null; ) + // Remove all armor. + if (!(style & MRF_KEEPARMOR)) { - let next = item.Inv; - if (item is 'Armor') + for (Inventory item = morphed.Inv; item;) { - item.DepleteOrDestroy(); + Inventory next = item.Inv; + if (item is "Armor") + item.DepleteOrDestroy(); + + item = next; } - item = next; - } - morphed.InitAllPowerupEffects(); - morphed.ActivateMorphWeapon (); - if (p.camera == self) // can this happen? - { - p.camera = morphed; } + + // Players store their morph behavior into their PlayerInfo unlike regular Actors which use the + // morph properties. This is needed for backwards compatibility and to give the HUD info. + let p = morphed.player; + morphed.SetMorphTics(duration); + morphed.SetMorphStyle(style); + morphed.SetMorphExitFlash(exitFlash); + p.MorphedPlayerClass = spawnType; + p.PremorphWeapon = p.ReadyWeapon; + p.Health = morphed.Health; + p.Vel = (0.0, 0.0); + // If the new view height is higher than the old one, start moving toward it. + if (morphed.ViewHeight > p.ViewHeight && !p.DeltaViewHeight) + p.DeltaViewHeight = p.GetDeltaViewHeight(); + + bNoInteraction = true; + A_ChangeLinkFlags(true, true); + + // Legacy + bSolid = bShootable = false; + bInvisible = true; + morphed.ClearFOVInterpolation(); - morphed.ScoreIcon = ScoreIcon; // [GRB] - if (eflash) - eflash.target = morphed; + morphed.InitAllPowerupEffects(); + morphed.ActivateMorphWeapon(); + PostMorph(morphed, false); // No longer the current body morphed.PostMorph(self, true); // This is the current body + + if (enterFlash) + { + Actor fog = Spawn(enterFlash, morphed.Pos.PlusZ(GameInfo.TelefogHeight), ALLOW_REPLACE); + if (fog) + fog.Target = morphed; + } + return true; } @@ -235,400 +220,156 @@ extend class PlayerPawn // //---------------------------------------------------------------------------- - virtual bool UndoPlayerMorph(playerinfo activator, int unmorphflag = 0, bool force = false) + virtual bool UndoPlayerMorph(PlayerInfo activator, EMorphFlags unmorphFlags = 0, bool force = false) { - if (alternative == null) + if (!Alternative || bStayMorphed || Alternative.bStayMorphed) + return false; + + if (!(unmorphFlags & MRF_IGNOREINVULN) && bInvulnerable + && (player != activator || (!(player.MorphStyle & MRF_WHENINVULNERABLE) && !(unmorphFlags & MRF_STANDARDUNDOING)))) { return false; } - let player = self.player; - bool DeliberateUnmorphIsOkay = !!(MRF_STANDARDUNDOING & unmorphflag); + let alt = PlayerPawn(Alternative); + alt.SetOrigin(Pos, false); + // Test if there's room to unmorph. + if (!force && (PremorphProperties & MPROP_SOLID)) + { + bool altSolid = alt.bSolid; + bool isSolid = bSolid; + bool isTouchy = bTouchy; - if ((bInvulnerable) // If the player is invulnerable - && ((player != activator) // and either did not decide to unmorph, - || (!((player.MorphStyle & MRF_WHENINVULNERABLE) // or the morph style does not allow it - || (DeliberateUnmorphIsOkay))))) // (but standard morph styles always allow it), - { // Then the player is immune to the unmorph. - return false; + alt.bSolid = true; + bSolid = bTouchy = false; + + bool res = alt.TestMobjLocation(); + + alt.bSolid = altSolid; + bSolid = isSolid; + bTouchy = isTouchy; + + if (!res) + { + SetMorphTics(2 * TICRATE); + return false; + } } - let altmo = PlayerPawn(alternative); - altmo.SetOrigin (Pos, false); - altmo.bSolid = true; - bSolid = false; - if (!force && !altmo.TestMobjLocation()) - { // Didn't fit - altmo.bSolid = false; - bSolid = true; - player.morphTics = 2*TICRATE; + if (!MorphInto(alt)) return false; - } - PreUnmorph(altmo, false); // This body's about to be left. - altmo.PreUnmorph(self, true); // This one's about to become current. + PreUnmorph(alt, false); // This body's about to be left. + alt.PreUnmorph(self, true); // This one's about to become current. - // No longer using tracer as morph storage. That is what 'alternative' is for. - // If the tracer has changed on the morph, change the original too. - altmo.target = target; - altmo.tracer = tracer; - self.player = null; - altmo.alternative = alternative = null; + alt.EndAllPowerupEffects(); // Remove the morph power if the morph is being undone prematurely. - for (Inventory item = Inv; item != null;) + for (Inventory item = alt.Inv; item;) { - let next = item.Inv; + Inventory next = item.Inv; if (item is "PowerMorph") - { item.Destroy(); - } + item = next; } - EndAllPowerupEffects(); - altmo.ObtainInventory (self); - Substitute(altmo); - if ((tid != 0) && (player.MorphStyle & MRF_NEWTIDBEHAVIOUR)) - { - altmo.ChangeTid(tid); - } - altmo.Angle = Angle; - altmo.player = player; - altmo.reactiontime = 18; - altmo.bSolid = !!(special2 & 2); - altmo.bShootable = !!(special2 & 4); - altmo.bInvisible = !!(special2 & 0x40); - altmo.Vel = (0, 0, Vel.Z); - player.Vel = (0, 0); - altmo.floorz = floorz; - altmo.bShadow = bShadow; - altmo.bNoGravity = bNoGravity; - altmo.bGhost = bGhost; - altmo.bUnmorphed = false; - altmo.Score = Score; - altmo.InitAllPowerupEffects(); - - let exit_flash = player.MorphExitFlash; - bool correctweapon = !!(player.MorphStyle & MRF_LOSEACTUALWEAPON); - bool undobydeathsaves = !!(player.MorphStyle & MRF_UNDOBYDEATHSAVES); - - player.morphTics = 0; - player.MorphedPlayerClass = null; - player.MorphStyle = 0; - player.MorphExitFlash = null; - player.viewheight = altmo.ViewHeight; - Inventory level2 = altmo.FindInventory("PowerWeaponLevel2", true); - if (level2 != null) - { - level2.Destroy (); - } - if ((player.health > 0) || undobydeathsaves) - { - player.health = altmo.health = altmo.SpawnHealth(); - } - else // killed when morphed so stay dead - { - altmo.health = player.health; - } + alt.Angle = Angle; + alt.Pitch = Pitch; + alt.Target = Target; + alt.Tracer = Tracer; + alt.Master = Master; + alt.FriendPlayer = FriendPlayer; + alt.DesignatedTeam = DesignatedTeam; + alt.Score = Score; + alt.ScoreIcon = ScoreIcon; + alt.ReactionTime = 18; + alt.bSolid = (PremorphProperties & MPROP_SOLID); + alt.bShootable = (PremorphProperties & MPROP_SHOOTABLE); + alt.bInvisible = (PremorphProperties & MPROP_INVIS); + alt.bShadow = bShadow; + alt.bNoGravity = bNoGravity; + alt.bGhost = bGhost; + alt.bFly = bFly; + alt.Vel = (0.0, 0.0, Vel.Z); + + alt.bNoInteraction = (PremorphProperties & MPROP_NO_INTERACTION); + alt.A_ChangeLinkFlags((PremorphProperties & MPROP_NO_BLOCKMAP), (PremorphProperties & MPROP_NO_SECTOR)); + + let p = alt.player; + class exitFlash = alt.GetMorphExitFlash(); + EMorphFlags style = alt.GetMorphStyle(); + Weapon premorphWeap = p.PremorphWeapon; + + if (TID && (style & MRF_NEWTIDBEHAVIOUR)) + { + alt.ChangeTid(TID); + ChangeTID(0); + } + + alt.SetMorphTics(0); + alt.SetMorphStyle(0); + alt.SetMorphExitFlash(null); + p.MorphedPlayerClass = null; + p.PremorphWeapon = null; + p.ViewHeight = alt.ViewHeight; + p.Vel = (0.0, 0.0); + if (p.Health > 0 || (style & MRF_UNDOBYDEATHSAVES)) + p.Health = alt.Health = alt.SpawnHealth(); + else + alt.Health = p.Health; - player.mo = altmo; - if (player.camera == self) - { - player.camera = altmo; - } - altmo.ClearFOVInterpolation(); - - // [MH] - // If the player that was morphed is the one - // taking events, reset up the face, if any; - // this is only needed for old-skool skins - // and for the original DOOM status bar. - if (player == players[consoleplayer]) - { - if (face != 'None') - { - // Assume root-level base skin to begin with - let skinindex = 0; - let skin = player.GetSkin(); - // If a custom skin was in use, then reload it - // or else the base skin for the player class. - if (skin >= PlayerClasses.Size () && skin < PlayerSkins.Size()) - { - skinindex = skin; - } - else if (PlayerClasses.Size () > 1) - { - let whatami = altmo.GetClass(); - for (int i = 0; i < PlayerClasses.Size (); ++i) - { - if (PlayerClasses[i].Type == whatami) - { - skinindex = i; - break; - } - } - } - } - } + Inventory level2 = alt.FindInventory("PowerWeaponLevel2", true); + if (level2) + level2.Destroy(); - Actor eflash = null; - if (exit_flash != null) - { - eflash = Spawn(exit_flash, Vec3Angle(20., altmo.Angle, gameinfo.telefogheight), ALLOW_REPLACE); - if (eflash) eflash.target = altmo; - } - WeaponSlots.SetupWeaponSlots(altmo); // Use original class's weapon slots. - let beastweap = player.ReadyWeapon; - if (player.PremorphWeapon != null) + let morphWeap = p.ReadyWeapon; + if (premorphWeap) { - player.PremorphWeapon.PostMorphWeapon (); + premorphWeap.PostMorphWeapon(); } else { - player.ReadyWeapon = player.PendingWeapon = null; + p.ReadyWeapon = null; + p.PendingWeapon = WP_NOCHANGE; + p.Refire = 0; } - if (correctweapon) - { // Better "lose morphed weapon" semantics - class morphweaponcls = MorphWeapon; - if (morphweaponcls != null && morphweaponcls is 'Weapon') - { - let OriginalMorphWeapon = Weapon(altmo.FindInventory (morphweapon)); - if ((OriginalMorphWeapon != null) && (OriginalMorphWeapon.GivenAsMorphWeapon)) - { // You don't get to keep your morphed weapon. - if (OriginalMorphWeapon.SisterWeapon != null) - { - OriginalMorphWeapon.SisterWeapon.Destroy (); - } - OriginalMorphWeapon.Destroy (); - } - } - } - else // old behaviour (not really useful now) - { // Assumptions made here are no longer valid - if (beastweap != null) - { // You don't get to keep your morphed weapon. - if (beastweap.SisterWeapon != null) - { - beastweap.SisterWeapon.Destroy (); - } - beastweap.Destroy (); - } - } - PostUnmorph(altmo, false); // This body is no longer current. - altmo.PostUnmorph(self, true); // altmo body is current. - Destroy (); - // Restore playerclass armor to its normal amount. - let hxarmor = HexenArmor(altmo.FindInventory('HexenArmor')); - if (hxarmor != null) - { - hxarmor.Slots[4] = altmo.HexenArmor[0]; - } - return true; - } - //=========================================================================== - // - // - // - //=========================================================================== - - override Actor, int, int MorphedDeath() - { - // Voodoo dolls should not unmorph the real player here. - if (player && (player.mo == self) && - (player.morphTics) && - (player.MorphStyle & MRF_UNDOBYDEATH) && - (alternative)) + if (style & MRF_LOSEACTUALWEAPON) { - Actor realme = alternative; - int realstyle = player.MorphStyle; - int realhealth = health; - if (UndoPlayerMorph(player, 0, !!(player.MorphStyle & MRF_UNDOBYDEATHFORCED))) + // Improved "lose morph weapon" semantics. + class morphWeapCls = MorphWeapon; + if (morphWeapCls) { - return realme, realstyle, realhealth; + let originalMorphWeapon = Weapon(alt.FindInventory(morphWeapCls)); + if (originalMorphWeapon && originalMorphWeapon.GivenAsMorphWeapon) + originalMorphWeapon.Destroy(); } } - return null, 0, 0; - } -} - -//=========================================================================== -// -// -// -//=========================================================================== - -class MorphProjectile : Actor -{ - - Class PlayerClass; - Class MonsterClass, MorphFlash, UnMorphFlash; - int Duration, MorphStyle; - - Default - { - Damage 1; - Projectile; - -ACTIVATEIMPACT - -ACTIVATEPCROSS - } - - override int DoSpecialDamage (Actor target, int damage, Name damagetype) - { - if (target.player) - { - // Voodoo dolls forward this to the real player - target.player.mo.MorphPlayer (NULL, PlayerClass, Duration, MorphStyle, MorphFlash, UnMorphFlash); - } - else + else if (morphWeap) // Old behaviour (not really useful now). { - target.MorphMonster (MonsterClass, Duration, MorphStyle, MorphFlash, UnMorphFlash); + morphWeap.Destroy(); } - return -1; - } - -} + // Reset the base AC of the player's Hexen armor back to its default. + let hexArmor = HexenArmor(alt.FindInventory("HexenArmor")); + if (hexArmor) + hexArmor.Slots[4] = alt.HexenArmor[0]; -//=========================================================================== -// -// -// -//=========================================================================== + alt.ClearFOVInterpolation(); + alt.InitAllPowerupEffects(); -class MorphedMonster : Actor -{ - Actor UnmorphedMe; - int UnmorphTime, MorphStyle; - Class MorphExitFlash; - int FlagsSave; + PostUnmorph(alt, false); // This body is no longer current. + alt.PostUnmorph(self, true); // altmo body is current. - Default - { - Monster; - -COUNTKILL - +FLOORCLIP - } - - private native void Substitute(Actor replacement); - - override void OnDestroy () - { - if (UnmorphedMe != NULL) - { - UnmorphedMe.Destroy (); - } - Super.OnDestroy(); - } - - override void Die (Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath) - { - Super.Die (source, inflictor, dmgflags, MeansOfDeath); - if (UnmorphedMe != NULL && UnmorphedMe.bUnmorphed) - { - UnmorphedMe.health = health; - UnmorphedMe.Die (source, inflictor, dmgflags, MeansOfDeath); - } - } - - override void Tick () - { - if (UnmorphTime > level.time || !UndoMonsterMorph()) + if (exitFlash) { - Super.Tick(); + Actor fog = Spawn(exitFlash, alt.Vec3Angle(20.0, alt.Angle, GameInfo.TelefogHeight), ALLOW_REPLACE); + if (fog) + fog.Target = alt; } - } - //---------------------------------------------------------------------------- - // - // FUNC P_UndoMonsterMorph - // - // Returns true if the monster unmorphs. - // - //---------------------------------------------------------------------------- - - virtual bool UndoMonsterMorph(bool force = false) - { - if (UnmorphTime == 0 || UnmorphedMe == NULL || bStayMorphed || UnmorphedMe.bStayMorphed) - { - return false; - } - let unmorphed = UnmorphedMe; - unmorphed.SetOrigin (Pos, false); - unmorphed.bSolid = true; - bSolid = false; - bool save = bTouchy; - bTouchy = false; - if (!force && !unmorphed.TestMobjLocation ()) - { // Didn't fit - unmorphed.bSolid = false; - bSolid = true; - bTouchy = save; - UnmorphTime = level.time + 5*TICRATE; // Next try in 5 seconds - return false; - } - PreUnmorph(unmorphed, false); - unmorphed.PreUnmorph(self, true); - unmorphed.Angle = Angle; - unmorphed.target = target; - unmorphed.bShadow = bShadow; - unmorphed.bGhost = bGhost; - unmorphed.bSolid = !!(flagssave & 2); - unmorphed.bShootable = !!(flagssave & 4); - unmorphed.bInvisible = !!(flagssave & 0x40); - unmorphed.health = unmorphed.SpawnHealth(); - unmorphed.Vel = Vel; - unmorphed.ChangeTid(tid); - unmorphed.special = special; - unmorphed.Score = Score; - unmorphed.args[0] = args[0]; - unmorphed.args[1] = args[1]; - unmorphed.args[2] = args[2]; - unmorphed.args[3] = args[3]; - unmorphed.args[4] = args[4]; - unmorphed.CopyFriendliness (self, true); - unmorphed.bUnmorphed = false; - PostUnmorph(unmorphed, false); // From is false here: Leaving the caller's body. - unmorphed.PostUnmorph(self, true); // True here: Entering this body from here. - UnmorphedMe = NULL; - Substitute(unmorphed); - Destroy (); - let eflash = Spawn(MorphExitFlash, Pos + (0, 0, gameinfo.TELEFOGHEIGHT), ALLOW_REPLACE); - if (eflash) - eflash.target = unmorphed; + Destroy(); return true; } - - //=========================================================================== - // - // - // - //=========================================================================== - - override Actor, int, int MorphedDeath() - { - let realme = UnmorphedMe; - if (realme != NULL) - { - if ((UnmorphTime) && - (MorphStyle & MRF_UNDOBYDEATH)) - { - int realstyle = MorphStyle; - int realhealth = health; - if (UndoMonsterMorph(!!(MorphStyle & MRF_UNDOBYDEATHFORCED))) - { - return realme, realstyle, realhealth; - } - } - if (realme.bBossDeath) - { - realme.health = 0; // make sure that A_BossDeath considers it dead. - realme.A_BossDeath(); - } - } - return null, 0, 0; - } - } - diff --git a/wadsrc/static/zscript/actors/raven/artitele.zs b/wadsrc/static/zscript/actors/raven/artitele.zs index 042ae67dfc..272ae86029 100644 --- a/wadsrc/static/zscript/actors/raven/artitele.zs +++ b/wadsrc/static/zscript/actors/raven/artitele.zs @@ -23,35 +23,32 @@ class ArtiTeleport : Inventory Loop; } - override bool Use (bool pickup) + override bool Use(bool pickup) { Vector3 dest; - int destAngle; - + double destAngle; if (deathmatch) - { - [dest, destAngle] = level.PickDeathmatchStart(); - } + [dest, destAngle] = Level.PickDeathmatchStart(); else - { - [dest, destAngle] = level.PickPlayerStart(Owner.PlayerNumber()); - } - if (!level.useplayerstartz) + [dest, destAngle] = Level.PickPlayerStart(Owner.PlayerNumber()); + + if (!Level.UsePlayerStartZ) dest.Z = ONFLOORZ; - Owner.Teleport (dest, destAngle, TELF_SOURCEFOG | TELF_DESTFOG); - bool canlaugh = true; - Playerinfo p = Owner.player; - if (p && p.morphTics && (p.MorphStyle & MRF_UNDOBYCHAOSDEVICE)) - { // Teleporting away will undo any morph effects (pig) - if (!p.mo.UndoPlayerMorph (p, MRF_UNDOBYCHAOSDEVICE) && (p.MorphStyle & MRF_FAILNOLAUGH)) - { - canlaugh = false; - } - } - if (canlaugh) - { // Full volume laugh - Owner.A_StartSound ("*evillaugh", CHAN_VOICE, CHANF_DEFAULT, 1., ATTN_NONE); + + Owner.Teleport(dest, destAngle, TELF_SOURCEFOG | TELF_DESTFOG); + + bool canLaugh = Owner.player != null; + EMorphFlags mStyle = Owner.GetMorphStyle(); + if (Owner.Alternative && (mStyle & MRF_UNDOBYCHAOSDEVICE)) + { + // Teleporting away will undo any morph effects (pig). + if (!Owner.Unmorph(Owner, MRF_UNDOBYCHAOSDEVICE) && (mStyle & MRF_FAILNOLAUGH)) + canLaugh = false; } + + if (canLaugh) + Owner.A_StartSound("*evillaugh", CHAN_VOICE, attenuation: ATTN_NONE); + return true; } diff --git a/wadsrc/static/zscript/actors/shared/corona.zs b/wadsrc/static/zscript/actors/shared/corona.zs index 82ad988e0a..7310312f28 100644 --- a/wadsrc/static/zscript/actors/shared/corona.zs +++ b/wadsrc/static/zscript/actors/shared/corona.zs @@ -9,8 +9,7 @@ * will draw the Spawn state's sprite in screen space. * * The corona will be drawn with the actor's render style and alpha. It - * defaults to the "Add" RenderStyle, but feel free to change to whatever - * you want. + * defaults to the "Add" RenderStyle, but can be changed to any render style. * * The actor's scale can also be used to influence the size of the corona * on screen. @@ -27,7 +26,7 @@ * *****************************************************************************/ -class Corona : Actor native +class Corona : Actor abstract { Default { diff --git a/wadsrc/static/zscript/actors/shared/dynlights.zs b/wadsrc/static/zscript/actors/shared/dynlights.zs index 132c78fd01..664b6d1d96 100644 --- a/wadsrc/static/zscript/actors/shared/dynlights.zs +++ b/wadsrc/static/zscript/actors/shared/dynlights.zs @@ -442,25 +442,6 @@ class SpotLightFlickerRandomAttenuated : SpotLightFlickerRandom } } -class PointLightTraceAttenuated : PointLightAttenuated -{ - Default - { - +DYNAMICLIGHT.TRACE - +DYNAMICLIGHT.DONTLIGHTMAP - } -} - -class SpotLightTraceAttenuated : SpotLightAttenuated -{ - Default - { - +DYNAMICLIGHT.TRACE - +DYNAMICLIGHT.DONTLIGHTMAP - } -} - - class VavoomLight : DynamicLight { Default @@ -501,4 +482,58 @@ class VavoomLightColor : VavoomLight } } +//========================================================================== +// +// ZDRay Lights +// +//========================================================================== + +// to reduce copy/pasting +mixin class TraceLightDefaults +{ + Default + { + +DYNAMICLIGHT.TRACE + +DYNAMICLIGHT.DONTLIGHTMAP + } +} + +class PointLightTraceAttenuated : PointLightAttenuated +{ + mixin TraceLightDefaults; +} + +class PointLightPulseTraceAttenuated : PointLightPulseAttenuated +{ + mixin TraceLightDefaults; +} + +class PointLightFlickerTraceAttenuated : PointLightFlickerAttenuated +{ + mixin TraceLightDefaults; +} + +class PointLightFlickerRandomTraceAttenuated : PointLightFlickerRandomAttenuated +{ + mixin TraceLightDefaults; +} + +class SpotLightTraceAttenuated : SpotLightAttenuated +{ + mixin TraceLightDefaults; +} +class SpotLightPulseTraceAttenuated : SpotLightPulseAttenuated +{ + mixin TraceLightDefaults; +} + +class SpotLightFlickerTraceAttenuated : SpotLightFlickerAttenuated +{ + mixin TraceLightDefaults; +} + +class SpotLightFlickerRandomTraceAttenuated : SpotLightFlickerRandomAttenuated +{ + mixin TraceLightDefaults; +} diff --git a/wadsrc/static/zscript/actors/shared/fogball.zs b/wadsrc/static/zscript/actors/shared/fogball.zs new file mode 100644 index 0000000000..9468df7c72 --- /dev/null +++ b/wadsrc/static/zscript/actors/shared/fogball.zs @@ -0,0 +1,7 @@ +class Fogball : Actor +{ + Default + { + +NOINTERACTION + } +} diff --git a/wadsrc/static/zscript/actors/strife/weaponmauler.zs b/wadsrc/static/zscript/actors/strife/weaponmauler.zs index 276402ee25..227430a909 100644 --- a/wadsrc/static/zscript/actors/strife/weaponmauler.zs +++ b/wadsrc/static/zscript/actors/strife/weaponmauler.zs @@ -62,7 +62,7 @@ class Mauler : StrifeWeapon Weapon weap = player.ReadyWeapon; if (weap != null) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 2)) + if (!weap.DepleteAmmo (weap.bAltFire, true)) return; } diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index fe44f2c3d2..cb416b3c50 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -141,6 +141,7 @@ enum EChaseFlags CHF_NOPOSTATTACKTURN = 128, CHF_STOPIFBLOCKED = 256, CHF_DONTIDLE = 512, + CHF_DONTLOOKALLAROUND = 1024, CHF_DONTTURN = CHF_NORANDOMTURN | CHF_NOPOSTATTACKTURN | CHF_STOPIFBLOCKED }; @@ -231,6 +232,8 @@ enum EMorphFlags MRF_UNDOBYTIMEOUT = 0x00001000, MRF_UNDOALWAYS = 0x00002000, MRF_TRANSFERTRANSLATION = 0x00004000, + MRF_KEEPARMOR = 0x00008000, + MRF_IGNOREINVULN = 0x00010000, MRF_STANDARDUNDOING = MRF_UNDOBYTOMEOFPOWER | MRF_UNDOBYCHAOSDEVICE | MRF_UNDOBYTIMEOUT, }; @@ -261,7 +264,9 @@ enum EExplodeFlags XF_EXPLICITDAMAGETYPE = 8, XF_NOSPLASH = 16, XF_THRUSTZ = 32, - + XF_THRUSTLESS = 64, + XF_NOALLIES = 128, + XF_CIRCULAR = 256, }; // Flags for A_RadiusThrust @@ -365,6 +370,14 @@ enum ERadiusGiveFlags RGF_EITHER = 1 << 17, }; +// SetAnimation flags +enum ESetAnimationFlags +{ + SAF_INSTANT = 1 << 0, + SAF_LOOP = 1 << 1, + SAF_NOOVERRIDE = 1 << 2, +}; + // Change model flags enum ChangeModelFlags { @@ -653,6 +666,7 @@ enum EQuakeFlags QF_GROUNDONLY = 1 << 7, QF_AFFECTACTORS = 1 << 8, QF_SHAKEONLY = 1 << 9, + QF_DAMAGEFALLOFF = 1 << 10, }; // A_CheckProximity flags @@ -690,17 +704,18 @@ enum ECheckBlockFlags enum EParticleFlags { - SPF_FULLBRIGHT = 1, - SPF_RELPOS = 1 << 1, - SPF_RELVEL = 1 << 2, - SPF_RELACCEL = 1 << 3, - SPF_RELANG = 1 << 4, - SPF_NOTIMEFREEZE = 1 << 5, - SPF_ROLL = 1 << 6, - SPF_REPLACE = 1 << 7, - SPF_NO_XY_BILLBOARD = 1 << 8, + SPF_FULLBRIGHT = 1 << 0, + SPF_RELPOS = 1 << 1, + SPF_RELVEL = 1 << 2, + SPF_RELACCEL = 1 << 3, + SPF_RELANG = 1 << 4, + SPF_NOTIMEFREEZE = 1 << 5, + SPF_ROLL = 1 << 6, + SPF_REPLACE = 1 << 7, + SPF_NO_XY_BILLBOARD = 1 << 8, + SPF_LOCAL_ANIM = 1 << 9, - SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG + SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; //Flags for A_FaceMovementDirection @@ -1145,8 +1160,9 @@ enum EPlayerCheats CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame CF_INTERPVIEWANGLES = 1 << 15, // [MR] flag for interpolating view angles without interpolating the entire frame - CF_SCALEDNOLERP = 1 << 15, // [MR] flag for applying angles changes in the ticrate without interpolating the frame CF_NOFOVINTERP = 1 << 16, // [B] Disable FOV interpolation when instantly zooming + CF_SCALEDNOLERP = 1 << 17, // [MR] flag for applying angles changes in the ticrate without interpolating the frame + CF_NOVIEWPOSINTERP = 1 << 18, // Disable view position interpolation. CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths. @@ -1227,7 +1243,10 @@ enum RadiusDamageFlags RADF_SOURCEISSPOT = 4, RADF_NODAMAGE = 8, RADF_THRUSTZ = 16, - RADF_OLDRADIUSDAMAGE = 32 + RADF_OLDRADIUSDAMAGE = 32, + RADF_THRUSTLESS = 64, + RADF_NOALLIES = 128, + RADF_CIRCULAR = 256 }; enum IntermissionSequenceType @@ -1263,6 +1282,7 @@ enum EChangeLevelFlags CHANGELEVEL_NOINTERMISSION = 16, CHANGELEVEL_RESETHEALTH = 32, CHANGELEVEL_PRERAISEWEAPON = 64, + CHANGELEVEL_NOAUTOSAVE = 128, }; enum ELevelFlags @@ -1379,6 +1399,10 @@ enum ELevelFlags LEVEL3_AVOIDMELEE = 0x00020000, // global flag needed for proper MBF support. LEVEL3_NOJUMPDOWN = 0x00040000, // only for MBF21. Inverse of MBF's dog_jumping flag. LEVEL3_LIGHTCREATED = 0x00080000, // a light had been created in the last frame + + VKDLEVELFLAG_NOUSERSAVE = 0x00000001, + VKDLEVELFLAG_NOAUTOMAP = 0x00000002, + VKDLEVELFLAG_NOAUTOSAVEONENTER = 0x00000004, // don't make an autosave when entering a map }; // [RH] Compatibility flags. @@ -1449,3 +1473,32 @@ const M_2_PI = 0.63661977236758134308; // 2/pi const M_2_SQRTPI = 1.12837916709551257390; // 2/sqrt(pi) const M_SQRT2 = 1.41421356237309504880; // sqrt(2) const M_SQRT1_2 = 0.70710678118654752440; // 1/sqrt(2) + +// Used by Actor.FallAndSink +const WATER_SINK_FACTOR = 0.125; +const WATER_SINK_SMALL_FACTOR = 0.25; +const WATER_SINK_SPEED = 0.5; +const WATER_JUMP_SPEED = 3.5; + + +// for SetModelFlag/ClearModelFlag +enum EModelFlags +{ + // [BB] Color translations for the model skin are ignored. This is + // useful if the skin texture is not using the game palette. + MDL_IGNORETRANSLATION = 1<<0, + MDL_PITCHFROMMOMENTUM = 1<<1, + MDL_ROTATING = 1<<2, + MDL_INTERPOLATEDOUBLEDFRAMES = 1<<3, + MDL_NOINTERPOLATION = 1<<4, + MDL_USEACTORPITCH = 1<<5, + MDL_USEACTORROLL = 1<<6, + MDL_BADROTATION = 1<<7, + MDL_DONTCULLBACKFACES = 1<<8, + MDL_USEROTATIONCENTER = 1<<9, + MDL_NOPERPIXELLIGHTING = 1<<10, // forces a model to not use per-pixel lighting. useful for voxel-converted-to-model objects. + MDL_SCALEWEAPONFOV = 1<<11, // scale weapon view model with higher user FOVs + MDL_MODELSAREATTACHMENTS = 1<<12, // any model index after 0 is treated as an attachment, and therefore will use the bone results of index 0 + MDL_CORRECTPIXELSTRETCH = 1<<13, // ensure model does not distort with pixel stretch when pitch/roll is applied + MDL_FORCECULLBACKFACES = 1<<14, +}; \ No newline at end of file diff --git a/wadsrc/static/zscript/destructible.zs b/wadsrc/static/zscript/destructible.zs index a7e0dc9820..84861a45a8 100644 --- a/wadsrc/static/zscript/destructible.zs +++ b/wadsrc/static/zscript/destructible.zs @@ -28,7 +28,7 @@ struct Destructible native play static native void DamageLinedef(Line def, Actor source, int damage, Name damagetype, int side, vector3 position, bool isradius); static native void GeometryLineAttack(TraceResults trace, Actor thing, int damage, Name damagetype); - static native void GeometryRadiusAttack(Actor bombspot, Actor bombsource, int bombdamage, int bombdistance, Name damagetype, int fulldamagedistance); + static native void GeometryRadiusAttack(Actor bombspot, Actor bombsource, int bombdamage, double bombdistance, Name damagetype, double fulldamagedistance); static native bool ProjectileHitLinedef(Actor projectile, Line def); static native bool ProjectileHitPlane(Actor projectile, SectorPart part); diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 0cca07c420..daaf143bf8 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -8,7 +8,8 @@ extend struct _ native readonly Array<@TerrainDef> Terrains; native int validcount; native play @DehInfo deh; - native readonly bool automapactive; + native readonly ui bool automapactive; // is automap enabled? + native readonly ui bool viewactive; // if automap is active, true = main automap, false = overlay automap. native readonly TextureID skyflatnum; native readonly int gametic; native readonly int Net_Arbitrator; @@ -51,25 +52,21 @@ extend struct Console extend struct Translation { - Color colors[256]; - - native int AddTranslation(); native static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass); - native static int GetID(Name transname); } // This is needed because Actor contains a field named 'translation' which shadows the above. struct Translate version("4.5") { - static int MakeID(int group, int num) + static TranslationID MakeID(int group, int num) { - return (group << 16) + num; + return Translation.MakeID(group, num); } static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass) { return Translation.SetPlayerTranslation(group, num, plrnum, pclass); } - static int GetID(Name transname) + static TranslationID GetID(Name transname) { return Translation.GetID(transname); } @@ -115,6 +112,7 @@ extend struct GameInfoStruct extend class Object { private native static Object BuiltinNewDoom(Class cls, int outerclass, int compatibility); + private native static TranslationID BuiltinFindTranslation(Name nm); private native static int BuiltinCallLineSpecial(int special, Actor activator, int arg1, int arg2, int arg3, int arg4, int arg5); // These really should be global functions... native static String G_SkillName(); @@ -122,11 +120,13 @@ extend class Object native static double G_SkillPropertyFloat(int p); deprecated("3.8", "Use Level.PickDeathMatchStart() instead") static vector3, int G_PickDeathmatchStart() { - return level.PickDeathmatchStart(); + let [a,b] = level.PickDeathmatchStart(); + return a, b; } deprecated("3.8", "Use Level.PickPlayerStart() instead") static vector3, int G_PickPlayerStart(int pnum, int flags = 0) { - return level.PickPlayerStart(pnum, flags); + let [a,b] = level.PickPlayerStart(pnum, flags); + return a, b; } deprecated("4.3", "Use S_StartSound() instead") native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0, float startTime = 0.0); native static void S_StartSound (Sound sound_id, int channel, int flags = 0, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0, float startTime = 0.0); @@ -137,6 +137,9 @@ extend class Object native static void MarkSound(Sound snd); native static uint BAM(double angle); native static void SetMusicVolume(float vol); + native clearscope static Object GetNetworkEntity(uint id); + native play void EnableNetworking(bool enable); + native clearscope uint GetNetworkID() const; } class Thinker : Object native play @@ -292,7 +295,7 @@ struct TraceResults native native Sector CrossedWater; // For Boom-style, Transfer_Heights-based deep water native vector3 CrossedWaterPos; // remember the position so that we can use it for spawning the splash - native Sector Crossed3DWater; // For 3D floor-based deep water + native F3DFloor Crossed3DWater; // For 3D floor-based deep water native vector3 Crossed3DWaterPos; } @@ -337,6 +340,8 @@ struct LevelInfo native native readonly int flags; native readonly int flags2; native readonly int flags3; + native readonly int vkdflags; + native readonly String LightningSound; native readonly String Music; native readonly String LevelName; native readonly String AuthorName; @@ -410,7 +415,7 @@ struct LevelLocals native native Array<@Side> Sides; native readonly Array<@Vertex> Vertexes; native readonly Array<@LinePortal> LinePortals; - native internal Array<@SectorPortal> SectorPortals; + native internal readonly Array<@SectorPortal> SectorPortals; native readonly int time; native readonly int maptime; @@ -428,6 +433,7 @@ struct LevelLocals native native readonly String F1Pic; native readonly int maptype; native readonly String AuthorName; + native String LightningSound; native readonly String Music; native readonly int musicorder; native readonly TextureID skytexture1; @@ -527,6 +533,7 @@ struct LevelLocals native native String GetChecksum() const; native void ChangeSky(TextureID sky1, TextureID sky2 ); + native void ForceLightning(int mode = 0, sound tempSound = ""); native SectorTagIterator CreateSectorTagIterator(int tag, line defline = null); native LineIdIterator CreateLineIdIterator(int tag); @@ -549,6 +556,7 @@ struct LevelLocals native native String GetEpisodeName(); native void SpawnParticle(FSpawnParticleParams p); + native VisualThinker SpawnVisualThinker(Class type); } // a few values of this need to be readable by the play code. @@ -582,10 +590,10 @@ struct State native native readonly bool bCanRaise; native readonly bool bDehacked; - native int DistanceTo(state other); - native bool ValidateSpriteFrame(); - native TextureID, bool, Vector2 GetSpriteTexture(int rotation, int skin = 0, Vector2 scale = (0,0)); - native bool InStateSequence(State base); + native int DistanceTo(state other) const; + native bool ValidateSpriteFrame() const; + native TextureID, bool, Vector2 GetSpriteTexture(int rotation, int skin = 0, Vector2 scale = (0,0), int spritenum = -1, int framenum = -1) const; + native bool InStateSequence(State base) const; } struct TerrainDef native @@ -615,6 +623,13 @@ enum EPickStart } +enum EMissileHitResult +{ + MHIT_DEFAULT = -1, + MHIT_DESTROY = 0, + MHIT_PASS = 1, +} + class SectorEffect : Thinker native { native protected Sector m_Sector; diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 7d02a9adfd..f24b71d013 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -462,6 +462,7 @@ enum DrawTextureTags DTA_Indexed, // Use an indexed texture combined with the given translation. DTA_CleanTop, // Like DTA_Clean but aligns to the top of the screen instead of the center. DTA_NoOffset, // Ignore 2D drawer's offset. + DTA_Localize, // localize drawn string, for DrawText only }; @@ -641,9 +642,9 @@ struct Font native // native Font(const Name name); native int GetCharWidth(int code); - native int StringWidth(String code); - native int GetMaxAscender(String code); - native bool CanPrint(String code); + native int StringWidth(String code, bool localize = true); + native int GetMaxAscender(String code, bool localize = true); + native bool CanPrint(String code, bool localize = true); native int GetHeight(); native int GetDisplacement(); native String GetCursor(); @@ -747,11 +748,14 @@ class Object native private native static void BuiltinRandomSeed(voidptr rng, int seed); private native static Class BuiltinNameToClass(Name nm, Class filter); private native static Object BuiltinClassCast(Object inptr, Class test); + private native static Function BuiltinFunctionPtrCast(Function inptr, voidptr newtype); native static uint MSTime(); native static double MSTimeF(); native vararg static void ThrowAbortException(String fmt, ...); + native static Function FindFunction(Class cls, Name fn); + native virtualscope void Destroy(); // This does not call into the native method of the same name to avoid problems with objects that get garbage collected late on shutdown. @@ -858,6 +862,7 @@ struct Wads // todo: make FileSystem an alias to 'Wads' native static int FindLump(string name, int startlump = 0, FindLumpNamespace ns = GlobalNamespace); native static int FindLumpFullName(string name, int startlump = 0, bool noext = false); native static string ReadLump(int lump); + native static int GetLumpLength(int lump); native static int GetNumLumps(); native static string GetLumpName(int lump); @@ -914,10 +919,11 @@ struct StringStruct native struct Translation version("2.4") { - static int MakeID(int group, int num) - { - return (group << 16) + num; - } + Color colors[256]; + + native TranslationID AddTranslation(); + native static TranslationID MakeID(int group, int num); + native static TranslationID GetID(Name transname); } // Convenient way to attach functions to Quat @@ -933,3 +939,70 @@ struct QuatStruct native // native double LengthSquared(); // native Quat Unit(); } + +struct ScriptSavedPos +{ + voidptr SavedScriptPtr; + int SavedScriptLine; +} + +class ScriptScanner native +{ + native void OpenString(String name, String script); + native void OpenLumpNum(int lump); + native void Close(); + + native void SavePos(out ScriptSavedPos pos); + native void RestorePos(out ScriptSavedPos pos); + native void UnGet(); + native bool isText(); + native int GetMessageLine(); + native void SetPrependMessage(String message); + + native vararg void ScriptError(String fmt, ...); + native vararg void ScriptMessage(String fmt, ...); + + native void SetCMode(bool cmode); + native void SetNoOctals(bool cmode); + native void SetEscape(bool esc); + native void SetNoFatalErrors(bool cmode); + native void SkipToEndOfBlock(); + native void StartBraces(out ScriptSavedPos braceend); + native bool FoundEndBrace(out ScriptSavedPos braceend); + + native bool CheckValue(bool allowfloat, bool evaluate = true); + native bool CheckBoolToken(); + native bool CheckNumber(bool evaluate = false); + native bool CheckString(String name); + native bool CheckFloat(bool evaluate = false); + + native bool GetNumber(bool evaluate = false); + native bool GetString(); + native bool GetFloat(bool evaluate = false); + + native void AddSymbol(String name, int value); + native void AddSymbolUnsigned(String name, uint value); + native void AddSymbolFloat(String name, double value); + + native void MustGetValue(bool allowfloat, bool evaluate = true); + native void MustGetFloat(bool evaluate = false); + native void MustGetNumber(bool evaluate = false); + native void MustGetString(); + native void MustGetStringName(String name); + native void MustGetBoolToken(); + + // This DOES NOT advance the parser! This returns the string the parser got. + native String GetStringContents(); + + native readonly bool End; + native readonly bool ParseError; + native readonly bool Crossed; + native readonly int Line; + native readonly int Number; + native readonly double Float; +} + +// this struct does not exist. It is just a type for being referenced by an opaque pointer. +struct VMFunction native version("4.10") +{ +} diff --git a/wadsrc/static/zscript/engine/screenjob.zs b/wadsrc/static/zscript/engine/screenjob.zs index a339def91c..dc50f55356 100644 --- a/wadsrc/static/zscript/engine/screenjob.zs +++ b/wadsrc/static/zscript/engine/screenjob.zs @@ -141,12 +141,12 @@ class BlackScreen : ScreenJob class ImageScreen : SkippableScreenJob { int tilenum; - int trans; + TranslationID trans; int waittime; // in ms. bool cleared; TextureID texid; - ScreenJob Init(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + ScreenJob Init(TextureID tile, int fade = fadein | fadeout, int wait = 3000, TranslationID translation = 0) { Super.Init(fade); waittime = wait; @@ -156,7 +156,7 @@ class ImageScreen : SkippableScreenJob return self; } - ScreenJob InitNamed(String tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + ScreenJob InitNamed(String tex, int fade = fadein | fadeout, int wait = 3000, TranslationID translation = 0) { Super.Init(fade); waittime = wait; @@ -166,12 +166,12 @@ class ImageScreen : SkippableScreenJob return self; } - static ScreenJob Create(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + static ScreenJob Create(TextureID tile, int fade = fadein | fadeout, int wait = 3000, TranslationID translation = 0) { return new("ImageScreen").Init(tile, fade, wait, translation); } - static ScreenJob CreateNamed(String tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + static ScreenJob CreateNamed(String tex, int fade = fadein | fadeout, int wait = 3000, TranslationID translation = 0) { return new("ImageScreen").InitNamed(tex, fade, wait, translation); } diff --git a/wadsrc/static/zscript/engine/service.zs b/wadsrc/static/zscript/engine/service.zs index a536cd616b..6df17f1268 100644 --- a/wadsrc/static/zscript/engine/service.zs +++ b/wadsrc/static/zscript/engine/service.zs @@ -14,67 +14,83 @@ class Service abstract } // Play variants - virtual play String GetString(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual play String GetString(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return ""; } - virtual play int GetInt(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual play int GetInt(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return 0; } - virtual play double GetDouble(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual play double GetDouble(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return 0.0; } - virtual play Object GetObject(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual play Object GetObject(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return null; } + virtual play Name GetName(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') + { + return ''; + } + + // UI variants - virtual ui String GetStringUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual ui String GetStringUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return ""; } - virtual ui int GetIntUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual ui int GetIntUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return 0; } - virtual ui double GetDoubleUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual ui double GetDoubleUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return 0.0; } - virtual ui Object GetObjectUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual ui Object GetObjectUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return null; } + virtual ui Name GetNameUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') + { + return ''; + } + // data/clearscope variants - virtual clearscope String GetStringData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual clearscope String GetStringData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return ""; } - virtual clearscope int GetIntData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual clearscope int GetIntData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return 0; } - virtual clearscope double GetDoubleData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual clearscope double GetDoubleData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return 0.0; } - virtual clearscope Object GetObjectData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null) + virtual clearscope Object GetObjectData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') { return null; } + + virtual clearscope Name GetNameData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '') + { + return ''; + } static Service Find(class serviceName){ return AllServices.GetIfExists(serviceName.GetClassName()); diff --git a/wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs b/wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs index 68a79417c9..948d9046b8 100644 --- a/wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs +++ b/wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs @@ -78,7 +78,7 @@ class CustomMessageBoxMenuBase : Menu abstract } else { - arrowFont = ConFont; + arrowFont = ((textFont && textFont.GetGlyphHeight(0xd) > 0) ? textFont : ConFont); destWidth = CleanWidth; destHeight = CleanHeight; selector = "\xd"; @@ -133,7 +133,7 @@ class CustomMessageBoxMenuBase : Menu abstract if ((MenuTime() % 8) < 6) { screen.DrawText(arrowFont, OptionMenuSettings.mFontColorSelection, - (destWidth/2 - 11) + OptionXOffset(messageSelection), y + fontheight * messageSelection, selector, DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true); + (destWidth/2 - 3 - arrowFont.StringWidth(selector)) + OptionXOffset(messageSelection), y + fontheight * messageSelection, selector, DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true); } } } diff --git a/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs b/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs index 06b412f177..206a31098c 100644 --- a/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs @@ -220,6 +220,29 @@ class OptionMenuItemInverter : OptionMenuItemOptionBase // //============================================================================= + +class OptionMenuJoyEnable : OptionMenuItemOptionBase +{ + JoystickConfig mJoy; + + OptionMenuJoyEnable Init(String label, JoystickConfig joy) + { + Super.Init(label,"none","YesNo",null,0); + mJoy = joy; + return self; + } + + override int GetSelection() + { + return mJoy.GetEnabled() ? 1 : 0; + } + + override void SetSelection(int Selection) + { + mJoy.SetEnabled(Selection); + } +} + class OptionMenuItemJoyConfigMenu : OptionMenuItemSubmenu { JoystickConfig mJoy; @@ -259,6 +282,9 @@ class OptionMenuItemJoyConfigMenu : OptionMenuItemSubmenu it = new("OptionMenuItemStaticText").Init(joy.GetName(), false); it = new("OptionMenuItemStaticText").Init("", false); + it = new("OptionMenuJoyEnable").Init("$JOYMNU_JOYENABLE", joy); + opt.mItems.Push(it); + it = new("OptionMenuSliderJoySensitivity").Init("$JOYMNU_OVRSENS", 0, 2, 0.1, 3, joy); opt.mItems.Push(it); it = new("OptionMenuItemStaticText").Init(" ", false); diff --git a/wadsrc/static/zscript/engine/ui/menu/listmenu.zs b/wadsrc/static/zscript/engine/ui/menu/listmenu.zs index 672c0ebc7d..ed3c2ef16b 100644 --- a/wadsrc/static/zscript/engine/ui/menu/listmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/listmenu.zs @@ -55,6 +55,7 @@ class ListMenuDescriptor : MenuDescriptor native native int mFontColor; native int mFontColor2; native bool mCenter; + native bool mCenterText; native bool mAnimatedTransition; native bool mAnimated; native bool mDontBlur; diff --git a/wadsrc/static/zscript/engine/ui/menu/listmenuitems.zs b/wadsrc/static/zscript/engine/ui/menu/listmenuitems.zs index 9e22578209..66a4d9338c 100644 --- a/wadsrc/static/zscript/engine/ui/menu/listmenuitems.zs +++ b/wadsrc/static/zscript/engine/ui/menu/listmenuitems.zs @@ -161,7 +161,7 @@ class ListMenuItemStaticText : ListMenuItem mText = text; mFont = desc.mFont; mColor = color >= 0? color : desc.mFontColor; - mCentered = false; + mCentered = desc.mCenterText; } void InitDirect(double x, double y, String text, Font font, int color = Font.CR_UNTRANSLATED, bool centered = false) @@ -294,7 +294,12 @@ class ListMenuItemTextItem : ListMenuItemSelectable override void Draw(bool selected, ListMenuDescriptor desc) { let font = menuDelegate.PickFont(mFont); - DrawText(desc, font, selected ? mColorSelected : mColor, mXpos, mYpos, mText); + double x = mXpos; + if (desc.mCenterText) + { + x -= font.StringWidth(mText) / 2; + } + DrawText(desc, font, selected ? mColorSelected : mColor, x, mYpos, mText); } override int GetWidth() diff --git a/wadsrc/static/zscript/engine/ui/menu/menu.zs b/wadsrc/static/zscript/engine/ui/menu/menu.zs index 1812348085..154eee82a7 100644 --- a/wadsrc/static/zscript/engine/ui/menu/menu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/menu.zs @@ -36,7 +36,7 @@ struct KeyBindings native version("2.4") { native static String NameKeys(int k1, int k2); - native static String NameAllKeys(array list); + native static String NameAllKeys(array list, bool colors = true); native int, int GetKeysForCommand(String cmd); native void GetAllKeysForCommand(out array list, String cmd); @@ -84,6 +84,9 @@ struct JoystickConfig native version("2.4") native int GetNumAxes(); native String GetAxisName(int axis); + native bool GetEnabled(); + native void SetEnabled(bool enabled); + } class Menu : Object native ui version("2.4") @@ -346,16 +349,16 @@ class Menu : Object native ui version("2.4") return OptionFont().GetHeight(); } - static int OptionWidth(String s) + static int OptionWidth(String s, bool localize = true) { - return OptionFont().StringWidth(s); + return OptionFont().StringWidth(s, localize); } - static void DrawOptionText(int x, int y, int color, String text, bool grayed = false) + static void DrawOptionText(int x, int y, int color, String text, bool grayed = false, bool localize = true) { - String label = Stringtable.Localize(text); + String label = localize ? Stringtable.Localize(text) : text; int overlay = grayed? Color(96,48,0,0) : 0; - screen.DrawText (OptionFont(), color, x, y, text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay); + screen.DrawText (OptionFont(), color, x, y, text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, DTA_Localize, localize); } @@ -377,4 +380,4 @@ class GenericMenu : Menu { Super.Init(parent); } -} \ No newline at end of file +} diff --git a/wadsrc/static/zscript/engine/ui/menu/messagebox.zs b/wadsrc/static/zscript/engine/ui/menu/messagebox.zs index 8e76cae31b..a49ff6f3f5 100644 --- a/wadsrc/static/zscript/engine/ui/menu/messagebox.zs +++ b/wadsrc/static/zscript/engine/ui/menu/messagebox.zs @@ -79,7 +79,7 @@ class MessageBoxMenu : Menu } else { - arrowFont = ConFont; + arrowFont = ((textFont && textFont.GetGlyphHeight(0xd) > 0) ? textFont : ConFont); destWidth = CleanWidth; destHeight = CleanHeight; selector = "\xd"; @@ -134,7 +134,7 @@ class MessageBoxMenu : Menu if ((MenuTime() % 8) < 6) { screen.DrawText(arrowFont, OptionMenuSettings.mFontColorSelection, - destWidth/2 - 11, y + fontheight * messageSelection, selector, DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true); + destWidth/2 - 3 - arrowFont.StringWidth(selector), y + fontheight * messageSelection, selector, DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true); } } } diff --git a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs index 4733d5b3b2..8276dda3eb 100644 --- a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs +++ b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs @@ -36,12 +36,14 @@ class OptionMenuItem : MenuItemBase { String mLabel; bool mCentered; + CVar mGrayCheck; - protected void Init(String label, String command, bool center = false) + protected void Init(String label, String command, bool center = false, CVar graycheck = null) { Super.Init(0, 0, command); mLabel = label; mCentered = center; + mGrayCheck = graycheck; } protected void drawText(int x, int y, int color, String text, bool grayed = false) @@ -61,17 +63,21 @@ class OptionMenuItem : MenuItemBase return x; } - protected void drawValue(int indent, int y, int color, String text, bool grayed = false) + protected void drawValue(int indent, int y, int color, String text, bool grayed = false, bool localize = true) { - Menu.DrawOptionText(indent + CursorSpace(), y, color, text, grayed); + Menu.DrawOptionText(indent + CursorSpace(), y, color, text, grayed, localize); } - int CursorSpace() { return (14 * CleanXfac_1); } + virtual bool IsGrayed() + { + return mGrayCheck != null && !mGrayCheck.GetInt(); + } + override bool Selectable() { return true; @@ -85,7 +91,7 @@ class OptionMenuItem : MenuItemBase } override bool MouseEvent(int type, int x, int y) -{ + { if (Selectable() && type == Menu.MOUSE_Release) { return Menu.GetCurrentMenu().MenuEvent(Menu.MKEY_Enter, true); @@ -253,16 +259,14 @@ class OptionMenuItemOptionBase : OptionMenuItem { // command is a CVAR Name mValues; // Entry in OptionValues table - CVar mGrayCheck; int mCenter; const OP_VALUES = 0x11001; protected void Init(String label, Name command, Name values, CVar graycheck, int center) { - Super.Init(label, command); + Super.Init(label, command, false, graycheck); mValues = values; - mGrayCheck = graycheck; mCenter = center; } @@ -339,11 +343,6 @@ class OptionMenuItemOptionBase : OptionMenuItem return true; } - virtual bool isGrayed() - { - return mGrayCheck != null && !mGrayCheck.GetInt(); - } - override bool Selectable() { return !isGrayed(); @@ -468,7 +467,7 @@ class EnterKey : Menu menuactive = Menu.On; SetMenuMessage(0); Close(); - mParentMenu.MenuEvent((ev.KeyScan == InputEvent.KEY_ESCAPE)? Menu.MKEY_Abort : Menu.MKEY_Input, 0); + mParentMenu.MenuEvent((ev.KeyScan == InputEvent.KEY_ESCAPE) || (ev.KeyScan == InputEvent.KEY_JOY2) ? Menu.MKEY_Abort : Menu.MKEY_Input, 0); return true; } return false; @@ -699,18 +698,16 @@ class OptionMenuSliderBase : OptionMenuItem int mShowValue; int mDrawX; int mSliderShort; - CVar mGrayCheck; protected void Init(String label, double min, double max, double step, int showval, Name command = 'none', CVar graycheck = NULL) { - Super.Init(label, command); + Super.Init(label, command, false, graycheck); mMin = min; mMax = max; mStep = step; mShowValue = showval; mDrawX = 0; mSliderShort = 0; - mGrayCheck = graycheck; } virtual double GetSliderValue() @@ -722,11 +719,6 @@ class OptionMenuSliderBase : OptionMenuItem { } - virtual bool IsGrayed(void) - { - return mGrayCheck != NULL && !mGrayCheck.GetInt(); - } - override bool Selectable(void) { return !IsGrayed(); @@ -903,9 +895,9 @@ class OptionMenuItemColorPicker : OptionMenuItem const CPF_RESET = 0x20001; - OptionMenuItemColorPicker Init(String label, Name command) + OptionMenuItemColorPicker Init(String label, Name command, CVar graycheck = null) { - Super.Init(label, command); + Super.Init(label, command, false, graycheck); CVar cv = CVar.FindCVar(command); if (cv != null && cv.GetRealType() != CVar.CVAR_Color) cv = null; mCVar = cv; @@ -915,7 +907,7 @@ class OptionMenuItemColorPicker : OptionMenuItem //============================================================================= override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { - drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor); + drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, isGrayed()); if (mCVar != null) { @@ -963,6 +955,11 @@ class OptionMenuItemColorPicker : OptionMenuItem } return false; } + + override bool Selectable() + { + return !isGrayed(); + } } //============================================================================= @@ -975,11 +972,12 @@ class OptionMenuItemColorPicker : OptionMenuItem class OptionMenuFieldBase : OptionMenuItem { + CVar mCVar; + void Init (String label, Name command, CVar graycheck = null) { - Super.Init(label, command); + Super.Init(label, command, false, graycheck); mCVar = CVar.FindCVar(mAction); - mGrayCheck = graycheck; } String GetCVarString() @@ -997,9 +995,8 @@ class OptionMenuFieldBase : OptionMenuItem override int Draw (OptionMenuDescriptor d, int y, int indent, bool selected) { - bool grayed = mGrayCheck != null && !mGrayCheck.GetInt(); - drawLabel(indent, y, selected ? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, grayed); - drawValue(indent, y, OptionMenuSettings.mFontColorValue, Represent(), grayed); + drawLabel(indent, y, selected ? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, isGrayed()); + drawValue(indent, y, OptionMenuSettings.mFontColorValue, Represent(), isGrayed(), false); return indent; } @@ -1024,11 +1021,8 @@ class OptionMenuFieldBase : OptionMenuItem override bool Selectable() { - return mGrayCheck == null || mGrayCheck.GetInt() != 0; + return !isGrayed(); } - - CVar mCVar; - CVar mGrayCheck; } //============================================================================= @@ -1068,7 +1062,7 @@ class OptionMenuItemTextField : OptionMenuFieldBase { // reposition the text so that the cursor is visible when in entering mode. String text = Represent(); - int tlen = Menu.OptionWidth(text) * CleanXfac_1; + int tlen = Menu.OptionWidth(text, false) * CleanXfac_1; int newindent = screen.GetWidth() - tlen - CursorSpace(); if (newindent < indent) indent = newindent; } @@ -1130,7 +1124,6 @@ class OptionMenuItemNumberField : OptionMenuFieldBase return String.format("%.3f", mCVar.GetFloat()); } - override bool MenuEvent (int mkey, bool fromcontroller) { if (mCVar) @@ -1176,9 +1169,9 @@ class OptionMenuItemScaleSlider : OptionMenuItemSlider String TextNegOne; int mClickVal; - OptionMenuItemScaleSlider Init(String label, Name command, double min, double max, double step, String zero, String negone = "") + OptionMenuItemScaleSlider Init(String label, Name command, double min, double max, double step, String zero, String negone = "", CVar graycheck = null) { - Super.Init(label, command, min, max, step, 0); + Super.Init(label, command, min, max, step, 0, graycheck); mCVar =CVar.FindCVar(command); TextZero = zero; TextNEgOne = negone; @@ -1195,12 +1188,12 @@ class OptionMenuItemScaleSlider : OptionMenuItemSlider if ((Selection == 0 || Selection == -1) && mClickVal <= 0) { String text = Selection == 0? TextZero : Selection == -1? TextNegOne : ""; - drawValue(indent, y, OptionMenuSettings.mFontColorValue, text); + drawValue(indent, y, OptionMenuSettings.mFontColorValue, text, isGrayed()); } else { mDrawX = indent + CursorSpace(); - DrawSlider (mDrawX, y, mMin, mMax, GetSliderValue(), mShowValue, indent); + DrawSlider (mDrawX, y, mMin, mMax, GetSliderValue(), mShowValue, indent, isGrayed()); } return indent; } @@ -1295,4 +1288,4 @@ class OptionMenuItemFlagOption : OptionMenuItemOption } } } -} \ No newline at end of file +} diff --git a/wadsrc/static/zscript/engine/ui/statusbar/statusbarcore.zs b/wadsrc/static/zscript/engine/ui/statusbar/statusbarcore.zs index b00af3fde6..30635337dd 100644 --- a/wadsrc/static/zscript/engine/ui/statusbar/statusbarcore.zs +++ b/wadsrc/static/zscript/engine/ui/statusbar/statusbarcore.zs @@ -66,6 +66,8 @@ class StatusBarCore native ui DI_ITEM_LEFT_TOP = DI_ITEM_TOP|DI_ITEM_LEFT, DI_ITEM_RIGHT_TOP = DI_ITEM_TOP|DI_ITEM_RIGHT, + DI_ITEM_LEFT_CENTER = DI_ITEM_CENTER|DI_ITEM_LEFT, + DI_ITEM_RIGHT_CENTER = DI_ITEM_CENTER|DI_ITEM_RIGHT, DI_ITEM_LEFT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_LEFT, DI_ITEM_RIGHT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_RIGHT, DI_ITEM_CENTER = DI_ITEM_VCENTER|DI_ITEM_HCENTER, diff --git a/wadsrc/static/zscript/events.zs b/wadsrc/static/zscript/events.zs index c3c10129ca..52cf3a7eb2 100644 --- a/wadsrc/static/zscript/events.zs +++ b/wadsrc/static/zscript/events.zs @@ -1,3 +1,60 @@ +enum ENetCmd +{ + NET_INT8 = 1, + NET_INT16, + NET_INT, + NET_FLOAT, + NET_DOUBLE, + NET_STRING, +} + +struct NetworkCommand native play version("4.12") +{ + native readonly int Player; + native readonly Name Command; + + native int ReadInt8(); + native int ReadInt16(); + native int ReadInt(); + native double ReadFloat(); + native double ReadDouble(); + native string ReadString(); + native bool EndOfStream(); + + // Wrappers + native Name ReadName(); + native double ReadMapUnit(); // 16.16 int -> double + native double ReadAngle(); // BAM int -> double + native Vector2 ReadVector2(); + native Vector3 ReadVector3(); + native Vector4 ReadVector4(); + native Quat ReadQuat(); + native void ReadIntArray(out Array values, ENetCmd intSize = NET_INT); + native void ReadDoubleArray(out Array values, bool doublePrecision = true); + native void ReadStringArray(out Array values, bool skipEmpty = false); +} + +class NetworkBuffer native version("4.12") +{ + native void AddInt8(int value); + native void AddInt16(int value); + native void AddInt(int value); + native void AddFloat(double value); + native void AddDouble(double value); + native void AddString(string value); + + // Wrappers + native void AddName(Name value); + native void AddMapUnit(double value); // double -> 16.16 int + native void AddAngle(double value); // double -> BAM int + native void AddVector2(Vector2 value); + native void AddVector3(Vector3 value); + native void AddVector4(Vector4 value); + native void AddQuat(Quat value); + native void AddIntArray(Array values, ENetCmd intSize = NET_INT); + native void AddDoubleArray(Array values, bool doublePrecision = true); + native void AddStringArray(Array values); +} struct RenderEvent native ui version("2.4") { @@ -127,6 +184,7 @@ class StaticEventHandler : Object native play version("2.4") virtual ui void ConsoleProcess(ConsoleEvent e) {} virtual ui void InterfaceProcess(ConsoleEvent e) {} virtual void NetworkProcess(ConsoleEvent e) {} + version("4.12") virtual void NetworkCommandProcess(NetworkCommand cmd) {} // virtual void CheckReplacement(ReplaceEvent e) {} @@ -150,5 +208,7 @@ class EventHandler : StaticEventHandler native version("2.4") { clearscope static native StaticEventHandler Find(class type); clearscope static native void SendNetworkEvent(String name, int arg1 = 0, int arg2 = 0, int arg3 = 0); + version("4.12") clearscope static native vararg bool SendNetworkCommand(Name cmd, ...); + version("4.12") clearscope static native bool SendNetworkBuffer(Name cmd, NetworkBuffer buffer); clearscope static native void SendInterfaceEvent(int playerNum, string name, int arg1 = 0, int arg2 = 0, int arg3 = 0); } diff --git a/wadsrc/static/zscript/level_compatibility.zs b/wadsrc/static/zscript/level_compatibility.zs index e88343ec2b..acecf7a448 100644 --- a/wadsrc/static/zscript/level_compatibility.zs +++ b/wadsrc/static/zscript/level_compatibility.zs @@ -1061,6 +1061,20 @@ class LevelCompatibility : LevelPostProcessor break; } + case '55BF5BFAF086C904E7258258F9700155': // Eternal Doom map02 + { + // unreachable monsters + SetThingFlags(274, GetThingFlags(274) | MTF_NOCOUNT); + SetThingFlags(275, GetThingFlags(275) | MTF_NOCOUNT); + SetThingFlags(276, GetThingFlags(276) | MTF_NOCOUNT); + SetThingFlags(277, GetThingFlags(277) | MTF_NOCOUNT); + SetThingFlags(278, GetThingFlags(278) | MTF_NOCOUNT); + SetThingFlags(279, GetThingFlags(279) | MTF_NOCOUNT); + SetThingFlags(280, GetThingFlags(280) | MTF_NOCOUNT); + SetThingFlags(281, GetThingFlags(281) | MTF_NOCOUNT); + break; + } + case '5C594C67CF7721005DE71429F9811370': // Eternal Doom map03 { // fix broken staircase. The compatibility option is not sufficient @@ -1068,8 +1082,11 @@ class LevelCompatibility : LevelPostProcessor ClearSectorTags(212); ClearSectorTags(213); ClearSectorTags(214); + // unreachable secret + SetSectorSpecial(551, 0); break; } + case '9A4615498C3451413F1CD3D15099ACC7': // Eternal Doom map05 { // an imp and two cyberdemons are located at the softlock area @@ -1078,12 +1095,20 @@ class LevelCompatibility : LevelPostProcessor SetThingFlags(274, GetThingFlags (274) | MTF_NOCOUNT); break; } + case '8B55842D5A509902738040AF10B4E787': // Eternal Doom map10 { // soulsphere at the end of the level is there merely to replicate the start of the next map SetThingFlags(548, GetThingFlags (548) | MTF_NOCOUNT); break; } + + case 'E5B4379151C2010B966CA37A9818C901': // Eternal Doom map12 + { + // unreachable baron + SetThingFlags(177, GetThingFlags(177) | MTF_NOCOUNT); + break; + } case 'DCE862393CAAA6FF1294FB7056B53057': // UAC Ultra map07 { @@ -2158,6 +2183,34 @@ class LevelCompatibility : LevelPostProcessor SetThingEdNum(59, 3); break; } + + case '3F0965ADCEB2F4A7BF46FADF6DD941B0': // phocas2.wad map01 + { + // turn map spot into teleport dest. + SetThingEdNum(699, 9044); + break; + } + + case 'C8E727FFBA0BA445666C80340BF3D0AC': // god_.WAD E1M2 + { + // fix bad skill flags for a monster that's required to be killed. + SetThingSkills(1184, 1); + break; + } + + case '3B4AAD34E46443BD505CC6053FCD842A': // pc_cp2.wad map38 + { + // Emulate the effect of the hidden Commander Keen's death + // since the Keen actor is modified by DEHACKED and doesn't work as intended: + + // 1) Replace the Keen with a zombieman + SetThingEdNum(101, 3004); + + // 2) Set its special to emulate A_KeenDie + SetThingSpecial(101, Door_Open); + SetThingArgument(101, 0, 666); + SetThingArgument(101, 1, 16); + } } } } diff --git a/wadsrc/static/zscript/mapdata.zs b/wadsrc/static/zscript/mapdata.zs index e7f3044ff6..db217e7cc7 100644 --- a/wadsrc/static/zscript/mapdata.zs +++ b/wadsrc/static/zscript/mapdata.zs @@ -17,15 +17,15 @@ struct SectorPortal native play FLAG_INSKYBOX = 2, // to avoid recursion }; - native int mType; - native int mFlags; - native uint mPartner; - native int mPlane; - native Sector mOrigin; - native Sector mDestination; - native Vector2 mDisplacement; - native double mPlaneZ; - native Actor mSkybox; + native readonly int mType; + native internal readonly int mFlags; + native readonly uint mPartner; + native readonly int mPlane; + native readonly Sector mOrigin; + native internal readonly Sector mDestination; + native readonly Vector2 mDisplacement; + native readonly double mPlaneZ; + native internal readonly Actor mSkybox; }; struct LinePortal native play @@ -58,16 +58,16 @@ struct LinePortal native play PORG_CEILING, }; - native Line mOrigin; - native Line mDestination; - native Vector2 mDisplacement; - native uint8 mType; - native uint8 mFlags; - native uint8 mDefFlags; - native uint8 mAlign; - native double mAngleDiff; - native double mSinRot; - native double mCosRot; + native readonly Line mOrigin; + native readonly Line mDestination; + native readonly Vector2 mDisplacement; + native readonly uint8 mType; + native readonly uint8 mFlags; + native readonly uint8 mDefFlags; + native readonly uint8 mAlign; + native readonly double mAngleDiff; + native readonly double mSinRot; + native readonly double mCosRot; } struct Vertex native play @@ -238,6 +238,7 @@ struct Line native play native clearscope int Index() const; native bool Activate(Actor activator, int side, int type); native bool RemoteActivate(Actor activator, int side, int type, Vector3 pos); + native bool, double, double GetMidTexturePosition (int side); clearscope int GetUDMFInt(Name nm) const { @@ -254,20 +255,23 @@ struct Line native play native clearscope int GetHealth() const; native void SetHealth(int newhealth); + + native int CountIDs() const; + native int GetID(int index) const; } struct SecPlane native play { - native Vector3 Normal; - native double D; - native double negiC; + native readonly Vector3 Normal; + native readonly double D; + native readonly double negiC; native clearscope bool isSlope() const; native clearscope int PointOnSide(Vector3 pos) const; native clearscope double ZatPoint (Vector2 v) const; native clearscope double ZatPointDist(Vector2 v, double dist) const; - native clearscope bool isEqual(Secplane other) const; - native void ChangeHeight(double hdiff); + native clearscope bool isEqual(readonly other) const; + //native void ChangeHeight(double hdiff); native clearscope double GetChangedHeight(double hdiff) const; native clearscope double HeightDiff(double oldd, double newd = 1e37) const; native clearscope double PointToDist(Vector2 xy, double z) const; @@ -336,11 +340,11 @@ struct SecSpecial play struct FColormap { - Color LightColor; - Color FadeColor; - uint8 Desaturation; - uint8 BlendFactor; - uint16 FogDensity; + readonly Color LightColor; + readonly Color FadeColor; + readonly uint8 Desaturation; + readonly uint8 BlendFactor; + readonly uint16 FogDensity; } struct Sector native play @@ -468,8 +472,8 @@ struct Sector native play native SectorAction SecActTarget; - native internal uint Portals[2]; - native readonly int PortalGroup; + native internal readonly uint Portals[2]; + native readonly int PortalGroup; native readonly int sectornum; @@ -646,6 +650,9 @@ struct Sector native play native clearscope int GetHealth(SectorPart part) const; native void SetHealth(SectorPart part, int newhealth); + + native int CountTags() const; + native int GetTag(int index) const; } class SectorTagIterator : Object native diff --git a/wadsrc/static/zscript/ui/menu/playerdisplay.zs b/wadsrc/static/zscript/ui/menu/playerdisplay.zs index d778531878..acb2f3b054 100644 --- a/wadsrc/static/zscript/ui/menu/playerdisplay.zs +++ b/wadsrc/static/zscript/ui/menu/playerdisplay.zs @@ -294,7 +294,7 @@ class ListMenuItemPlayerDisplay : ListMenuItem if (sprite.IsValid()) { - int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; + let trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; let tscale = TexMan.GetScaledSize(sprite); Scale.X *= sx * tscale.X; Scale.Y *= sy * tscale.Y; @@ -357,7 +357,7 @@ class PlayerMenuPlayerDisplay : ListMenuItemPlayerDisplay if (sprite.IsValid()) { - int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; + let trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; let tscale = TexMan.GetScaledSize(sprite); Scale.X *= CleanXfac_1 * tscale.X * 2; Scale.Y *= CleanYfac_1 * tscale.Y * 2; diff --git a/wadsrc/static/zscript/ui/menu/playermenu.zs b/wadsrc/static/zscript/ui/menu/playermenu.zs index 6404ac7133..85a4b944be 100644 --- a/wadsrc/static/zscript/ui/menu/playermenu.zs +++ b/wadsrc/static/zscript/ui/menu/playermenu.zs @@ -33,6 +33,11 @@ ** */ +extend class Menu +{ + static native void StartGameDirect(bool hasPlayerClass, bool randomPlayerClass, Class playerClass, int Episode, int Skill); +} + class PlayerMenu : ListMenu { int mRotation; diff --git a/wadsrc/static/zscript/ui/statscreen/statscreen.zs b/wadsrc/static/zscript/ui/statscreen/statscreen.zs index 500185ee08..4b50f0cf7b 100644 --- a/wadsrc/static/zscript/ui/statscreen/statscreen.zs +++ b/wadsrc/static/zscript/ui/statscreen/statscreen.zs @@ -148,7 +148,7 @@ class StatusScreen : ScreenJob abstract version("2.5") scalemode = FSMode_ScaleToFit43; scalefactorx = 1; scalefactory = 1; - wrapwidth = wrapw == -1 ? width : wrapw;; + wrapwidth = wrapw == -1 ? width : wrapw; } //==================================================================== diff --git a/wadsrc/static/zscript/ui/statusbar/alt_hud.zs b/wadsrc/static/zscript/ui/statusbar/alt_hud.zs index 69939da27b..203d55ec41 100644 --- a/wadsrc/static/zscript/ui/statusbar/alt_hud.zs +++ b/wadsrc/static/zscript/ui/statusbar/alt_hud.zs @@ -926,8 +926,12 @@ class AltHud ui DrawStatus(CPlayer, 5, hudheight-75); DrawFrags(CPlayer, 5, hudheight-70); } - DrawHealth(CPlayer, 5, hudheight-45); - DrawArmor(BasicArmor(CPlayer.mo.FindInventory('BasicArmor')), HexenArmor(CPlayer.mo.FindInventory('HexenArmor')), 5, hudheight-20); + + int armory = hud_swaphealtharmor ? hudheight-45 : hudheight-20; + int healthy = hud_swaphealtharmor ? hudheight-20 : hudheight-45; + DrawHealth(CPlayer, 5, healthy); + DrawArmor(BasicArmor(CPlayer.mo.FindInventory('BasicArmor')), HexenArmor(CPlayer.mo.FindInventory('HexenArmor')), 5, armory); + int y = DrawKeys(CPlayer, hudwidth-4, hudheight-10); y = DrawAmmo(CPlayer, hudwidth-5, y); if (hud_showweapons) DrawWeapons(CPlayer, hudwidth - 5, y); diff --git a/wadsrc/static/zscript/ui/statusbar/statusbar.zs b/wadsrc/static/zscript/ui/statusbar/statusbar.zs index 26d4bf1ada..58f2ecc3af 100644 --- a/wadsrc/static/zscript/ui/statusbar/statusbar.zs +++ b/wadsrc/static/zscript/ui/statusbar/statusbar.zs @@ -755,7 +755,7 @@ class BaseStatusBar : StatusBarCore native // //============================================================================ - int GetTranslation() const + TranslationID GetTranslation() const { if(gameinfo.gametype & GAME_Raven) return Translation.MakeID(TRANSLATION_PlayersExtra, CPlayer.mo.PlayerNumber()); diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs new file mode 100644 index 0000000000..12a8c41d6a --- /dev/null +++ b/wadsrc/static/zscript/visualthinker.zs @@ -0,0 +1,50 @@ +Class VisualThinker : Thinker native +{ + native Vector3 Pos, + Prev; + native FVector3 Vel; + native Vector2 Scale, + Offset; + native float Roll, + PrevRoll, + Alpha; + native TextureID Texture; + native TranslationID Translation; + native uint16 Flags; + native int16 LightLevel; + native bool bFlipOffsetX, + bFlipOffsetY, + bXFlip, + bYFlip, + bDontInterpolate, + bAddLightLevel; + native Color scolor; + + native Sector CurSector; // can be null! + + native void SetTranslation(Name trans); + native void SetRenderStyle(int mode); // see ERenderStyle + native bool IsFrozen(); + + static VisualThinker Spawn(Class type, TextureID tex, Vector3 pos, Vector3 vel, double alpha = 1.0, int flags = 0, + double roll = 0.0, Vector2 scale = (1,1), Vector2 offset = (0,0), int style = STYLE_Normal, TranslationID trans = 0) + { + if (!Level) return null; + + let p = level.SpawnVisualThinker(type); + if (p) + { + p.Texture = tex; + p.Pos = pos; + p.Vel = vel; + p.Alpha = alpha; + p.Roll = roll; + p.Scale = scale; + p.Offset = offset; + p.SetRenderStyle(style); + p.Translation = trans; + p.Flags = flags; + } + return p; + } +} diff --git a/wadsrc_bm/CMakeLists.txt b/wadsrc_bm/CMakeLists.txt index e0268d1a36..639c331448 100644 --- a/wadsrc_bm/CMakeLists.txt +++ b/wadsrc_bm/CMakeLists.txt @@ -1,3 +1 @@ -cmake_minimum_required( VERSION 3.1.0 ) - add_pk3(brightmaps.pk3 ${CMAKE_CURRENT_SOURCE_DIR}/static) diff --git a/wadsrc_extra/CMakeLists.txt b/wadsrc_extra/CMakeLists.txt index d9a1b272fe..964a177c6e 100644 --- a/wadsrc_extra/CMakeLists.txt +++ b/wadsrc_extra/CMakeLists.txt @@ -1,3 +1 @@ -cmake_minimum_required( VERSION 3.1.0 ) - add_pk3(game_support.pk3 ${CMAKE_CURRENT_SOURCE_DIR}/static) diff --git a/wadsrc_extra/static/filter/chex.chex3/language.csv b/wadsrc_extra/static/filter/chex.chex3/language.csv index 666a54380a..b54173fad0 100644 --- a/wadsrc_extra/static/filter/chex.chex3/language.csv +++ b/wadsrc_extra/static/filter/chex.chex3/language.csv @@ -1,62 +1,86 @@ -default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,tr -Picked up a blue flemkey.,GOTBLUEFLEM,Flem = phlegm,,,Sebrán modrý slizoklíč.,Du samlede en blå flemkey op.,Blauen Flemschlüssel genommen,,Prenis bluan mukŝlosilon.,Recogiste una flemllave azul.,,Poimit sinisen lima-avaimen,Flemclé bleue récupérée.,Kék slejmkulcs felvéve.,Raccolta una chiave-flem blu.,ブルー フレムキー をみつけた,청색 플렘열쇠 획득.,Je hebt een blauwe flemsleutel opgehaald.,Plukket opp en blå flemkey.,Zebrano niebieski flemowy klucz,Pegou uma flemchave azul.,,Ai ridicat flemcheia albastră.,Получен синий флемключ.,,Mavi bir flemkey aldım. -Picked up a yellow flemkey.,GOTYELLOWFLEM,,,,Sebrán žlutý slizoklíč.,Du samlede en gul flemkey op.,Gelben Flemschlüssel genommen,,Prenis flavan mukŝlosilon.,Recogiste una flemllave amarilla.,,Poimit keltaisen lima-avaimen,Flemclé jaune récupérée.,Sárga slejmkulcs felvéve.,Raccolta una chiave-flem gialla.,イエローフレムキー をみつけた,황색 플렘열쇠 획득.,Je hebt een gele flemsleutel opgehaald.,Plukket opp en gul flemkey.,Zebrano żółty flemowy klucz,Pegou uma flemchave amarela.,,Ai ridicat flemcheia galbenă.,Получен жёлтый флемключ.,,Sarı bir flemkey aldı. -Picked up a red flemkey.,GOTREDFLEM,,,,Sebrán červený slizoklíč.,Du samlede en rød flemkey op.,Roten Flemschlüssel genommen.,,Prenis ruĝan mukŝlosilon.,Recogiste una flemllave roja.,,Poimit punaisen lima-avaimen,Flemclé rouge récupérée.,Piros slejmkulcs felvéve.,Raccolta una chiave-flem rossa.,レッド フレムキー をみつけた,적색 플렘열쇠 획득.,Je hebt een rode flemsleutel opgehaald.,Plukket opp en rød flemkey.,Zebrano czerwony flemowy klucz,Pegou uma flemchave vermelha.,,Ai ridicat flemcheia roșie.,Получен красный флемключ.,,Kırmızı bir flemkey aldı. -Found Ultra Goggles,GOTGOGGLES,,,,Nalezeny ultrabrýle.,Fandt Ultra Goggles,Ultrasichtbrille gefunden,,Trovis Plejajn Okulvitrojn.,Ultra Gafas encontradas,Ultralentes encontrados,Löysit ultralasit,Ultra-lunettes récupérées.,Ultraszemüveg felvéve.,,ウルトラゴーグル をみつけた,울트라 고글 사용.,Ultraroggles gevonden,Fant Ultra Goggles,Znaleziono Ultra Gogle,Achou um Ultra Óculos.,,Ai găsit Ultra Ochelarii,Получены ультра-очки,,Ultra Gözlük bulundu -You need a blue key to activate this object,PD_BLUECO,,,,Potřebuješ modrý klíč pro aktivaci tohoto objektu,Du skal bruge en blå nøgle for at aktivere dette objekt,"Du brauchst einen blauen Schlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas bluan ŝlosilon por aktivigi ĉi tiun objekton.,Necesitas una llave azul para activar este objeto,,Tarvitset sinisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé bleue pour activer cet objet.,Egy kék kulcs szükséges az objektum aktiválásához.,Ti serve una chiave blu per attivare questo oggetto,このそうちは ブルー キー がひつようだ,이걸 작동하려면 청색 열쇠가 필요합니다,Je hebt een blauwe sleutel nodig om dit object te activeren.,Du trenger en blå nøkkel for å aktivere dette objektet,"Potrzebujesz niebieskiego klucza, aby aktywować ten przedmiot",Você precisa de uma chave azul para ativar este objeto,,Ai nevoie de o cheie albastră pentru a activa acest obiect,Для активации нужен синий ключ,Треба вам плави кључ да бисте активирали овај предмет,Bu nesneyi etkinleştirmek için mavi bir anahtara ihtiyacınız var -You need a red key to activate this object,PD_REDCO,,,,Potřebuješ červený klíč pro aktivaci tohoto objektu,Du skal bruge en rød nøgle for at aktivere dette objekt,"Du brauchst einen roten Schlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas ruĝan ŝlosilon por aktivigi ĉi tiun objekton.,Necesitas una llave roja para activar este objeto,,Tarvitset punaisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé rouge pour activer cet objet.,Egy piros kulcs szükséges az objektum aktiválásához.,Ti serve una chiave rossa per attivare questo oggetto,このそうちは レッド キー がひつようだ,이걸 작동하려면 적색 열쇠가 필요합니다,Je hebt een rode sleutel nodig om dit object te activeren.,Du trenger en rød nøkkel for å aktivere denne gjenstanden,"Potrzebujesz czerwonego klucza, aby aktywować ten przedmiot",Você precisa de uma chave vermelha para ativar este objeto,,Ai nevoie de o cheie roșie pentru a activa acest obiect,Для активации нужен красный ключ,Треба вам црвени кључ да бисте активирали овај предмет,Bu nesneyi etkinleştirmek için kırmızı bir anahtara ihtiyacınız var -You need a yellow key to activate this object,PD_YELLOWCO,,,,Potřebuješ žlutý klíč pro aktivaci tohoto objektu,Du skal bruge en gul nøgle for at aktivere dette objekt,"Du brauchst einen gelben Schlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas flavan ŝlosilon por aktivigi ĉi tiun objekton.,Necesitas una llave amarilla para activar este objeto,,Tarvitset keltaisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé jaune pour activer cet objet.,Egy sárga kulcs szükséges az objektum aktiválásához.,Ti serve una chiave gialla per attivare questo oggetto,このそうちは イエローキー がひつようだ,이걸 작동하려면 황색 열쇠가 필요합니다,Je hebt een gele sleutel nodig om dit object te activeren.,Du trenger en gul nøkkel for å aktivere denne gjenstanden,"Potrzebujesz żółtego klucza, aby aktywować ten przedmiot",Você precisa de uma chave amarela para ativar este objeto,,Ai nevoie de o cheie galbenă pentru a activa acest obiect,Для активации нужен жёлтый ключ,Треба вам жути кључ да бисте активирали овај предмет,Bu nesneyi etkinleştirmek için sarı bir anahtara ihtiyacınız var -You need a blue flemkey to activate this object,PD_BLUEFO,,,,Potřebuješ modrý slizoklíč pro aktivaci tohoto objektu.,Du skal bruge en blå flemkey for at aktivere dette objekt,"Du brauchst einen blauen Flemschlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas bluan mukŝlosilon por aktivigi ĉi tiun objekton.,Necesitas una flemllave azul para activar este objeto,,Tarvitset sinisen lima-avaimen aktivoidaksesi tämän kappaleen,Il vous faut une flemclé bleue pour activer cet objet.,Egy kék slejmkulcs szükséges az objektum aktiválásához.,Ti serve una chiave-flem blu per attivare questo oggetto,このそうちは ブルー キーがひつようだ,이걸 작동하려면 청색 플렘열쇠가 필요합니다,Je hebt een blauwe flemsleutel nodig om dit object te activeren.,Du trenger en blå flemkey for å aktivere denne gjenstanden.,"Potrzebujesz niebieskiego flemowego klucza, aby aktywować ten przedmiot",Você precisa de uma flemchave azul para ativar este objeto,,Ai nevoie de o flemcheie albastră pentru a activa acest obiect,Для активации нужен синий флемключ,,Bu nesneyi etkinleştirmek için mavi bir flemkey'e ihtiyacınız var -You need a red flemkey to activate this object,PD_REDFO,,,,Potřebuješ červený slizoklíč pro aktivaci tohoto objektu.,Du skal bruge en rød flemkey for at aktivere dette objekt,"Du brauchst einen roten Flemschlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas ruĝan mukŝlosilon por aktivigi ĉi tiun objekton.,Necesitas una flemllave roja para activar este objeto,,Tarvitset punaisen lima-avaimen aktivoidaksesi tämän kappaleen,Il vous faut une flemclé rouge pour activer cet objet.,Egy piros slejmkulcs szükséges az objektum aktiválásához.,Ti serve una chiave-flem rossa per attivare questo oggetto,このそうちは レッド キーがひつようだ,이걸 작동하려면 적색 플렘열쇠가 필요합니다,Je hebt een rode flemsleutel nodig om dit object te activeren.,Du trenger en rød flemkey for å aktivere dette objektet.,"Potrzebujesz czerwonego flemowego klucza, aby aktywować ten przedmiot",Você precisa de uma flemchave vermelha para ativar este objeto,,Ai nevoie de o flemcheie roșie pentru a activa acest obiect,Для активации нужен красный флемключ,,Bu nesneyi etkinleştirmek için kırmızı bir flemkey'e ihtiyacınız var -You need a yellow flemkey to activate this object,PD_YELLOWFO,,,,Potřebuješ žlutý slizoklíč pro aktivaci tohoto objektu.,Du skal bruge en gul flemkey for at aktivere dette objekt,"Du brauchst einen gelben Flemschlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas flavan mukŝlosilon por aktivigi ĉi tiun objekton.,Necesitas unaflemllave amarilla para activar este objeto,,Tarvitset keltaisen lima-avaimen aktivoidaksesi tämän kappaleen,Il vous faut une flemclé jaune pour activer cet objet.,Egy sárga slejmkulcs szükséges az objektum aktiválásához.,Ti serve una chiave-flem gialla per attivare questo oggetto,このそうちは イエローキーがひつようだ,이걸 작동하려면 황색 플렘열쇠가 필요합니다,Je hebt een gele flemsleutel nodig om dit object te activeren.,Du trenger en gul flemkey for å aktivere dette objektet.,"Potrzebujesz żółtego flemowego klucza, aby aktywować ten przedmiot",Você precisa de uma flemchave amarela para ativar este objeto,,Ai nevoie de o flemcheie galbenă pentru a activa acest obiect,Для активации нужен жёлтый флемключ,,Bu nesneyi etkinleştirmek için sarı bir flemkey'e ihtiyacınız var -Picked up a zorcher.,PICKUP_PISTOL_DROPPED,,,,Sebrán bzukr.,Du samlede en zorcher op.,Zorcher genommen.,,Prenis zorĉilon.,Recogiste un zorcher.,,Poimit zorcherin,Zorcheur récupéré.,Szörcsölő felvéve.,Ho preso uno zorcher.,ゾーチャー をひろった,자쳐 습득.,Je hebt een zorcher opgehaald.,Plukket opp en zorcher.,Zebrano Zorcher,Pegou um zorcher.,,Ai ridicat un zorcher.,Получен Зорчер.,,Bir zorcher aldım. -Zorch and keys added,STSTR_KFAADDED,,,,Bzukr a klíče přidány,Zorch og nøgler tilføjet,Zorch und Schlüssel hinzugefügt.,,Zorĉaĵo kaj ŝlosiloj aldonitaj.,Zorch y llaves añadidas,,Zorch ja avaimet lisätty,Zorch et clés ajoutées.,Szörcs és kulcsok hozzáadva.,Zorch e chiavi aggiunte,ゾーチ と キーがとどいた,저치와 열쇠,Zorch en sleutels toegevoegd,Zorch og nøkler lagt til,Dodano amunicję Zorch i klucze,Zorch e chaves adicionadas,,Zorcher și chei adăugate,Зорч и ключи получены,,Zorch ve anahtarlar eklendi -E1M1: Landing Zone,HUSTR_E1M1,,,,E1M1: Přistávací zóna,E1M1: Landingszone,E1M1: Landezone,,E1M1: Surterejo,E1M1: Zona de Aterrizaje,,E1M1: Laskeutumisalue,E1M1: Zone D'Atterissage,E1M1: Leszállópálya,E1M1: Zona di Atterraggio,E1M1: ちゃくち ちてん,E1M1: 착륙 지점,E1M1: Landingzone,E1M1: Landingssone,E1M1: Strefa Lądowania,E1M1: Zona de Pouso,,E1M1: Zona de Aterizare,E1M1: Зона высадки,,E1M1: İniş Bölgesi -E1M2: Storage Facility,HUSTR_E1M2,,,,E1M2: Skladiště,E1M2: Opbevaringsanlæg,E1M2: Lagerhalle,,E1M2: Stokejo,E1M2: Instalación de Almacenamiento,,E1M2: Varastolaitos,E1M2: Centre de Stockage,E1M2: Raktárépület,E1M2: Struttura di Immagazzinamento,E1M2: ちょぞう しせつ,E1M2: 저장 시설,E1M2: Opslagfaciliteit,E1M2: Lagringsanlegg,E1M2: Magazyn,E1M2: Depósito,,E1M2: Depozitul,E1M2: Хранилище,,E1M2: Depolama Tesisi -E1M3: Laboratory,HUSTR_E1M3,,,,E1M3: Testovací laboratoř,E1M3: Laboratorium,E1M3: Labor,,E1M3: Laboratorio,E1M3: Laboratorio,,E1M3: Laboratorio,E1M3: Laboratoire,E1M3: Laboratórium,E1M3: Laboratorio,E1M3: ラボラトリー,E1M3: 연구소,E1M3: Laboratorium,E1M3: Laboratorium,E1M3: Laboratorium,E1M3: Laboratório de Experimentos,,E1M3: Laboratorul,E1M3: Лаборатория,,E1M3: Laboratuvar -E1M4: Arboretum,HUSTR_E1M4,,,,,,,,E1M4: Arbejo,E1M4: Arboreto,,,E1M4: Arboretum,E1M4: Arborétum,E1M4: Arboreto,E1M4: じゅもく園,E1M4: 수목원,,E1M4: Arboretet,E1M4: Arboretum,E1M4: Arvoredo,,E1M4: Arboretum,E1M4: Дендрарий,, -E1M5: Caverns of Bazoik,HUSTR_E1M5,,,,E1M5: Bazoikské jeskyně,E1M5: Bazoiks grotter,E1M5: Die Höhlen von Bazoik,,E1M5: Kavernoj de Bazojko,E1M5: Cavernas de Bazoik,,E1M5: Bazoikin luolastot,E1M5: Cavernes de Bazoik,E1M5: Bazoik barlangjai,E1M5: Caverne di Bazoik,E1M5: バゾイクのどうくつ,E1M5: 바조이크의 대동굴,E1M5: Grotten van Bazoik,E1M5: Grottene i Bazoik,E1M5: Jaskinie Bazoik,E1M5: Cavernas de Bazoik,,E1M5: Cavernele lui Bazoik,E1M5: Пещеры Базоика,,E1M5: Bazoik Mağaraları -E2M1: Spaceport,HUSTR_E2M1,,,,E2M1: Kosmodrom,E2M1: Rumhavn,E2M1: Raumhafen,,E2M1: Kosmo-haveno,E2M1: Puerto Espacial,,E2M1: Avaruussatama,E2M1: Spatioport,E2M1: Űrkikötő,E2M1: Spazioporto,E2M1: スペースポート,E2M1: 우주공항,E2M1: Ruimtehaven,E2M1: Romhavn,E2M1: Port Kosmiczny,E2M1: Espaçoporto,,E2M1: Portul Spațial,E2M1: Космодром,,E2M1: Uzay Limanı -E2M2: Cinema,HUSTR_E2M2,,,,E2M2: Kino,,E2M2: Kino,,E2M2: Kinejo,E2M2: Cine,,E2M2: Elokuvateatteri,E2M2: Cinéma,E2M2: Mozi,,E2M2: シネマ,E2M2: 극장,E2M2: Bioscoop,E2M2: Kino,E2M2: Kino,E2M2: Cinema,,E2M2: Cinema,E2M2: Кинотеатр,,E2M2: Sinema -E2M3: Chex Museum,HUSTR_E2M3,,,,E2M3: Muzem Chex,,,,E2M3: Chex-muzeo,E2M3: Museo de Chex,,E2M3: Chex-museo,E2M3: Musée Chex,E2M3: Chex-múzeum,E2M3: Museo di Chex,E2M3: チェックス ミュージアム,E2M3: 첵스 박물관,,,E2M3: Muzeum Chex,E2M3: Museu Chex,,E2M3: Muzeul Chex,E2M3: Музей Chex,,E2M3: Chex Müzesi -E2M4: City Streets,HUSTR_E2M4,,,,E2M4: Městské ulice,E2M4: Byens gader,E2M4: städtische Straßen,,E2M4: Urbstratoj,E2M4: Calles de la Ciudad,,E2M4: Kaupungin kadut,E2M4: Rues de la Ville,E2M4: Városi utcák,E2M4: Strade della città,E2M4: シティーストリート,E2M4: 도시 거리,E2M4: Stadsstraten,E2M4: Byens gater,E2M4: Ulice Miasta,E2M4: Ruas da Cidade,,E2M4: Străzile Orașului,E2M4: Городские улицы,,E2M4: Şehir Sokakları -E2M5: Sewer System,HUSTR_E2M5,,,,E2M5: Kanalizace,E2M5: Kloaksystem,E2M5: Kanalisation,,E2M5: Defluilego-sistemo,E2M5: Alcantarillado,,E2M5: Viemärijärjestelmä,E2M5: Système d'égouts,E2M5: Csatornarendszer,E2M5: Rete fognaria,E2M5: サワーシステム,E2M5: 하수도,E2M5: Rioleringssysteem,E2M5: Avløpssystem,E2M5: System Ścieków,E2M5: Rede de Esgoto,,E2M5: Sistemul de Canalizare,E2M5: Канализация,,E2M5: Kanalizasyon Sistemi -E3M1: Central Command,HUSTR_E3M1,,,,E3M1: Centrální velení,E3M1: Centralkommando,E3M1: Kommandozentrale,,E3M1: Centra Komandejo,E3M1: Comando central,,E3M1: Komentokeskus,E3M1: Commandement,E3M1: Központi parancsnokság,E3M1: Comando centrale,E3M1: 中央しれいとう,E3M1: 중앙 사령부,E3M1: Centraal Commando,E3M1: Sentral kommando,E3M1: Centrum Dowodzenia,E3M1: Comando Central,,E3M1: Centrul de Comanda,E3M1: Командный центр,,E3M1: Merkez Komutanlığı -E3M2: United Cereals,HUSTR_E3M2,,,,E3M2: Spojené cereálie,,E3M2: Vereinigte Zerealien,,E3M2: Uniaj Cerealoj,E3M2: Cereales unidos,,E3M2: Yhdistyneet murot,E3M2: Céréales Unies,E3M2: Egyesült Gabonapelyhek,E3M2: Cereali uniti,E3M2: ユナイテッド シリアル,E3M2: 시리얼 연합,E3M2: Verenigde granen,,E3M2: Zjednoczone Płatki,E3M2: Cereais Unidos,,E3M2: Cereale Unite,E3M2: Организация Объединённых Хлопьев,,E3M2: Birleşik Tahıllar -E3M3: Villa Chex,HUSTR_E3M3,,,,,,,,E3M3: Vilao Chex,,,,E3M3: Villa Chex,,,E3M3: チェックスのべっそう,E3M3: 책스 주택,,,E3M3: Willa Chex,E3M3: Villa Chex,,E3M3: Vila Chex,E3M3: Вилла Chex,,E3M3: Villa Chex -E3M4: Provincial Park,HUSTR_E3M4,,,,E3M4: Provinciální park,,E3M4: Provinzpark,,E3M4: Provinca Parko,E3M4: Parque provincial,,E3M4: Provinssipuisto,E3M4: Parc Naturel,E3M4: Tartományi park,E3M4: Parco provinciale,E3M4: 州立公園,E3M4: 주립공원,E3M4: Provinciaal Park,E3M4: Provincial Park,E3M4: Prowincjonalny Park,E3M4: Parque Natural,,E3M4: Parcul Provincial,E3M4: Провинциальный парк,,E3M4: İl Parkı -E3M5: Meteor Spaceship,HUSTR_E3M5,,,,E3M5: Meteorová vesmírná loď,E3M5: Meteor rumskib,E3M5: Meteor-Raumschiff,,E3M5: Meteor-kosmoŝipo,E3M5: Nave Meteoro,,E3M5: Meteoriavaruusalus,E3M5: Vaisseau Météore,E3M5: Meteor űrhajó,E2M5: Astronave meteorica,E3M5: メテオスペースシップ,E3M5: 거대 유성호,E3M5: Ruimteschip,E3M5: Meteor-romskipet,"E3M5: Statek Kosmiczny ""Meteor""",E3M5: Espaçonave Meteoro,,E3M5: Nava Spațială Meteor,E3M5: Космический корабль «Метеор»,,E3M5: Meteor Uzay Gemisi -Commonus,CC_ZOMBIE,,,,Obecnýs,,,,Oftmukulo,,,,,Általánusz,,コモンズ,커머누스,,,Pospolitus,,,Comun,Обыкновеннус,,Commonus -Bipedicus,CC_SHOTGUN,,,,Dvojnožus,,,,Dupiedmukulo,,,,,Kétlábusz,,バイピディクス,바이피디쿠스,,,,,,Biped,Двуножка,,Bipedicus -Bipedicus with Armor,CC_IMP,,,,Dvojnožus s brněním,Bipedicus med rustning,Bipedicus mit Panzerung,,Kirasa Dupiedmukulo,Bipedicus con Armadura,,Panssaroitu bipedicus,Bipedicus avec Armure,Páncélozott kétlábusz,Bipedicus corazzato,アーマードバイピディクス,정예 바이피디쿠스,Bipedicus met harnas,Bipedicus med rustning,Opancerzony Bipedicus,Bipedicus de Armadura,,Biped cu Armură,Бронированная двуножка,,Zırhlı Bipedicus -Stridicus,CC_DEMON,,,,Běhakus,,,,Paŝmukulo,,,,,Lépkedüsz,,ステュリクス,스트리디쿠스,,,,,,Picioare-Lungi,Длинноножка,,Stridicus -Flem Mine,CC_LOST,,,,Slizná mina,,,,Muksentinelo,Flem-Mina,,Limamiina,,Slejmakna,Bomba a Flem,フレムマイン,플렘 지뢰,Flemmijn,Flem Mine,Flemowa Mina,Mina Flem,,Flem Mină,Флем-мина,,Flem Madeni -Super Cycloptis,CC_CACO,,,,Superkykloptus,,,,Supera Ciklopmukulo,,,Supercycloptis,,Szuper Kükloptisz,,スーパーサイクロプティス,슈퍼 사이클롭티스,,Supersykloptis.,Super Cykloptis,,,Super Cicloptic,Супер-циклоптис,,Süper Cycloptis -Maximus,CC_BARON,,,,,,,,Mukulestro,,,,,Maximusz,,マクシムス,맥시무스,,,,Maximus,,Maxim,Максимус,,Maximus -The Flembomination,CC_SPIDER,,,,Slizavnost,Flembominationen,Die Flembomination,,Mukabomeno,La Flembominación,,Limaoikku,La Flembomination,Slejmdormány,La Flembominio,フレンボミネーション,플렘보미네이션,De Flembominatie,Flembominationen,Flembominacja,A Flembominação,,Flembominație,Флемомерзость,,Flembomination -Lord Snotfolus,CC_CYBER,,,,Lord Hlenfujus,,,,Lordo Mukplenulo,Lord Mocofolus,,Herra Räkänokka,Seigneur Morvator,Lord Takony,,ロード スノフォールス,스놋폴러스 마왕,,,Lord Smarkofolus,Lorde Snotfolus,,Lordul Snotfolus,Лорд Соплезелёнус,,Lord Snotfolus -Chex Warrior,CC_HERO,,,,Bojovník Chex,Chex Kriger,Chex Krieger,,Chex-batalisto,,,Chex-soturi,Guerrier Chex,Chex harcos,Guerriero Chex,チェックスのせんし,첵스 전사,Chex Krijger,Chex-krigeren,Wojownik Chex,Guerreiro Chex,,Războinic Chex,Воин Chex,,Chex Savaşçısı -You need a blue key to open this door,PD_BLUEC,,,,Potřebuješ modrý klíč pro otevření těchto dveří,Du skal bruge en blå nøgle for at åbne denne dør,"Du brauchst einen blauen Schlüssel, um diese Tür zu öffnen.",,Vi bezonas bluan ŝlosilon por malfermi ĉi tiun pordon.,Necesitas una llave azul para abrir esta puerta,,Tarvitset sinisen avaimen avataksesi tämän oven,Il vous faut une clé bleue pour ouvrir cette porte.,Kell egy kék kulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave blu per aprire questa porta,このとびらは ブルー キー がひつようだ,이 문을 열려면 청색 열쇠가 필요합니다,Je hebt een blauwe sleutel nodig om deze deur te openen.,Du trenger en blå nøkkel for å åpne denne døren,"Potrzebujesz niebieskiego klucza, aby otworzyć te drzwi",Você precisa de uma chave azul para abrir essa porta,,Ai nevoie de o cheie albastră pentru a deschide ușa aceasta,"Нужен синий ключ, чтобы открыть",Треба вам плави кључ да бисте отворили ова врата,Bu kapıyı açmak için mavi bir anahtara ihtiyacın var. -You need a red key to open this door,PD_REDC,,,,Potřebuješ červený klíč pro otevření těchto dveří,Du skal bruge en rød nøgle for at åbne denne dør,"Du brauchst einen roten Schlüssel, um diese Tür zu öffnen.",,Vi bezonas ruĝan ŝlosilon por malfermi ĉi tiun pordon.,Necesitas una llave roja para abrir esta puerta,,Tarvitset punaisen avaimen avataksesi tämän oven,Il vous faut une clé rouge pour ouvrir cette porte.,Kell egy piros kulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave rossa per aprire questa porta,このとびらは レッド キー がひつようだ,이 문을 열려면 적색 열쇠가 필요합니다,Je hebt een rode sleutel nodig om deze deur te openen.,Du trenger en rød nøkkel for å åpne denne døren,"Potrzebujesz czerwonego klucza, aby otworzyć te drzwi",Você precisa de uma chave vermelha para abrir essa porta,,Ai nevoie de o cheie roșie pentru a deschide ușa aceasta,"Нужен красный ключ, чтобы открыть",Треба вам црвени кључ да бисте отворили ова врата,Bu kapıyı açmak için kırmızı bir anahtara ihtiyacın var. -You need a yellow key to open this door,PD_YELLOWC,,,,Potřebuješ žlutý klíč pro otevření těchto dveří,Du skal bruge en gul nøgle for at åbne denne dør,"Du brauchst einen gelben Schlüssel, um diese Tür zu öffnen.",,Vi bezonas flavan ŝlosilon por malfermi ĉi tiun pordon.,Necesitas una llave amarilla para abrir esta puerta,,Tarvitset keltaisen avaimen avataksesi tämän oven,Il vous faut une clé jaune pour ouvrir cette porte.,Kell egy sárga kulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave gialla per aprire questa porta,このとびらは イエローキー がひつようだ,이 문을 열려면 황색 열쇠가 필요합니다,Je hebt een gele sleutel nodig om deze deur te openen.,Du trenger en gul nøkkel for å åpne denne døren,"Potrzebujesz żółtego klucza, aby otworzyć te drzwi",Você precisa de uma chave amarela para abrir essa porta,,Ai nevoie de o cheie galbenă pentru a deschide ușa aceasta,"Нужен жёлтый ключ, чтобы открыть",Треба вам жути кључ да бисте отворили ова врата,Bu kapıyı açmak için sarı bir anahtara ihtiyacınız var -You need a blue flemkey to open this door,PD_BLUEF,,,,Potřebuješ modrý slizoklíč pro otevření těchto dveří,Du skal bruge en blå flemkey for at åbne denne dør,"Du brauchst einen blauen Flemschlüssel, um diese Tür zu öffnen.",,Vi bezonas bluan mukŝlosilon por malfermi ĉi tiun pordon.,Necesitas una flemllave azul para abrir esta puerta,,Tarvitset sinisen lima-avaimen avataksesi tämän oven,Il vous faut une flemclé bleue pour ouvrir cette porte.,Kell egy kék slejmkulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave-flem blu per aprire questa porta,このとびらは ブルー キーがひつようだ,이 문을 열려면 청색 플렘열쇠가 필요합니다,Je hebt een blauwe flemsleutel nodig om deze deur te openen.,Du trenger en blå flemkey for å åpne denne døren,"Potrzebujesz niebieskiego flemowego klucza, aby otworzyć te drzwi",Você precisa de uma flemchave azul para ativar este objeto,,Ai nevoie de o flemcheie albastră pentru a deschide ușa aceasta,"Нужен синий флемключ, чтобы открыть",,Bu kapıyı açmak için mavi bir flemkey'e ihtiyacın var. -You need a red flemkey to open this door,PD_REDF,,,,Potřebuješ červený slizoklíč pro otevření těchto dveří,Du skal bruge en rød flemkey for at åbne denne dør,"Du brauchst einen roten Flemschlüssel, um diese Tür zu öffnen.",,Vi bezonas ruĝan mukŝlosilon por malfermi ĉi tiun pordon.,Necesitas una flemllave roja para abrir esta puerta,,Tarvitset punaisen lima-avaimen avataksesi tämän oven,Il vous faut une flemclé rouge pour ouvrir cette porte.,Kell egy piros slejmkulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave-flem rossa per aprire questa porta,このとびらは レッド キーがひつようだ,이 문을 열려면 적색 플렘열쇠가 필요합니다,Je hebt een rode flemsleutel nodig om deze deur te openen.,Du trenger en rød flemkey for å åpne denne døren,"Potrzebujesz czerwonego flemowego klucza, aby otworzyć te drzwi",Você precisa de uma flemchave vermelha para ativar este objeto,,Ai nevoie de o flemcheie roșie pentru a deschide ușa aceasta,"Нужен красный флемключ, чтобы открыть",,Bu kapıyı açmak için kırmızı bir flemkey'e ihtiyacın var. -You need a yellow flemkey to open this door,PD_YELLOWF,,,,Potřebuješ žlutý slizoklíč pro otevření těchto dveří,Du har brug for en gul flemkey for at åbne denne dør,"Du brauchst einen gelben Flemschlüssel, um diese Tür zu öffnen.",,Vi bezonas flavan mukŝlosilon por malfermi ĉi tiun pordon.,Necesitas una flemllave amarilla para abrir esta puerta,,Tarvitset keltaisen lima-avaimen avataksesi tämän oven,Il vous faut une flemclé jaune pour ouvrir cette porte.,Kell egy sárga slejmkulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave-flem gialla per aprire questa porta,このとびらは イエローキーがひつようだ,이 문을 열려면 황색 플렘열쇠가 필요합니다,Je hebt een gele flemsleutel nodig om deze deur te openen.,Du trenger en gul flemkey for å åpne denne døren,"Potrzebujesz żółtego flemowego klucza, aby otworzyć te drzwi",Você precisa de uma flemchave amarela para ativar este objeto,,Ai nevoie de o flemcheie galbenă pentru a deschide ușa aceasta,"Нужен жёлтый флемключ, чтобы открыть",,Bu kapıyı açmak için sarı bir flemkey'e ihtiyacın var. -%o sinks into some slime.,OB_SLIME,,,,%o se propadl@[ao_cs] do slizu.,%o synker ned i noget slim.,%o versank im Schleim,,%o malflosas subeniras en kelkan ŝlimon.,%o se hunde en babas.,,%o uppoaa limaan,%o se noie dans la morve.,%o elsüllyedt a trutyiban.,%o affonda in qualche melma.,%o はスライムにしずんだ。,%o 는(은) 점액 속으로 가라앉았습니다.,%o zinkt in wat slijm.,%o synker ned i noe slim.,%o topi się w szlamie.,%o afundou na gosma.,,%o se scufundă în mâzgă.,Игрок %o утонул в слизи.,,%o balçığın içine battı. -%o sinks into some slime.,OB_LAVA,,,,%o se propadl@[ao_cs] do slizu.,%o synker ned i noget slim.,%o versank im Schleim,,%o malflosas subeniras en kelkan ŝlimon.,%o se hunde en babas.,,%o uppoaa limaan,%o se noie dans la morve.,%o elsüllyedt a trutyiban.,%o affonda in qualche melma.,%o はスライムにしずんだ。,%o 는(은) 질척하게 가라앉았습니다.,%o zinkt in wat slijm.,%o synker ned i noe slim.,%o topi się w szlamie.,%o afundou na gosma.,,%o se scufundă în mâzgă.,Игрок %o утонул в слизи.,,%o balçığın içine battı. -%o was hit by inter-dimensional slime!,OB_POWERSTRAND,,,,%o byl@[ao_cs] zasažen@[ao_cs] mezidimenzionálním slizem!,%o blev ramt af interdimensionalt slim!,%o wurde von interdimensionalem Schleim getroffen,,%o estas trafita de interdimensia ŝlimo!,¡%o fue alcanzad@[ao_esp] por baba interdimensional!,,%o parkaan osui interdimensionaalista limaa!,%o s'est fait@[e_fr] toucher par de la morve interdimensionelle!,%o interdimenzionális trutyi áldozata lett!,%o è stato colpito da melma interdimensionale!,%o は いじげんスライムまみれになった!,%o 는(은) 차원균열 점액에 맞았습니다!,%o werd geraakt door interdimensionaal slijm!,%o ble truffet av interdimensjonalt slim!,%o został@[ao_pl] uderzon@[adj_pl] przez międzywymiarowy szlam!,%o foi atingid@[ao_ptb] por gosma interdimensional!,,%o a fost lovit de mâzgă interdimensională!,В игрока %o попала межпространственная слизь!,,%o boyutlar arası balçık tarafından vuruldu! -%o was hit by inter-dimensional slime!,OB_KILLEDSELF,,,,%o byl@[ao_cs] zasažen@[ao_cs] mezidimenzionálním slizem!,%o blev ramt af interdimensionalt slim!,%o wurde von interdimensionalem Schleim getroffen,,%o estas trafita de interdimensia ŝlimo!,¡%o fue alcanzad@[ao_esp] por baba interdimensional!,,%o parkaan osui interdimensionaalista limaa!,%o s'est fait@[e_fr] toucher par de la morve interdimensionelle!,%o interdimenzionális trutyi áldozata lett!,%o è stato colpito da melma interdimensionale!,%o は いじげんスライムまみれになった!,%o 는(은) 모르는 사이에 점액에 당했습니다!,%o werd geraakt door interdimensionaal slijm!,%o ble truffet av interdimensjonalt slim!,%o został@[ao_pl] uderzon@[adj_pl] przez międzywymiarowy szlam!,%o foi atingid@[ao_ptb] por gosma interdimensional!,,%o a fost lovit de mâzgă interdimensională!,В игрока %o попала межпространственная слизь!,,%o boyutlar arası balçık tarafından vuruldu! -%o was boogered by a stridicus.,OB_STRIDICUS,,,,%o dostal@[ao_cs] holuby od běhakem.,%o blev buogered af en stridicus.,%o wurde von einem Stridicus bepopelt.,,%o estas mukiga de paŝmukulo.,%o fue moquead@[ao_esp] por un stridicus.,,%o joutui stridicuksen räkäämäksi.,%o s'est fait@[e_fr] engluer par un stridicus.,%o taknyos lett egy lépkedüsztől.,%o è stato colpito da uno Stridicus.,%o は ステュリクスに おびやかされた。,%o 는(은) 스트리디쿠스의 코딱지에 당했습니다.,%o werd door een stridicus gezoomd.,%o ble bæsjet av en stridicus.,%o został@[ao_pl] zaglutowan@[adj_pl] przez stridicusa.,%o foi melecad@[ao_ptb] por um stridicus.,,%o a fost speriat de către un picioare-lungi.,Игрока %o облепила соплями длинноножка. ,,%o bir stridicus tarafından avlandı. -%o was gooed by a flem mine.,OB_FLEMMINE,,,,%o byl@[ao_cs] zablácen@[ao_cs] sliznou minou.,%o blev smittet af en flem mine.,%o wurde von einer Flem-Mine beschmiert.,,%o estas ŝlimiga de muksentinelo.,%o fue pegotead@[ao_esp] por una flem-mina.,,%o joutui limamiinan mönjäämäksi.,%o s'est fait@[e_fr] éclabousser par une flem mine.,%o-t összenyálkázta egy slejmakna.,%o è stato colpito da una bomba a flem.,%o はフレムマインに ヒドいめにあった。,%o 는(은) 플렘 지뢰에 의해 점액 범벅이 됐습니다.,%o werd door een Flemmijn getreiterd.,%o ble gooed av en flem mine.,"%o został@[ao_pl] zabrejowan@[adj_pl] przez flemową minę. -",%o foi engosmad@[ao_ptb] por uma mina flem.,,%o a fost lovit de mâzga unei flem mine.,Игрока %o забрызгала флем-мина.,,%o bir flem mayını tarafından yapışkan hale getirildi. -%o was slimed by a super cycloptis.,OB_SUPERCYCLOPTIS,,,,%o byl@[ao_cs] osliznut@[ao_cs] superkykloptem.,%o blev slimet af en super cycloptis.,%o wurde von einem Super Cycloptis vollgeschleimt.,,%o estas ŝlimiga de supera ciklopmukulo.,%o fue enlodad@[ao_esp] por un super cycloptis.,,%o joutui supercycloptiksen limaamaksi.,%o s'est fait@[e_fr] gélifier par un super cycloptis.,%o-t összenyálkázta egy Szuper Kükloptisz.,%o è stato snellito da una Super Ciyloptis.,%o はスーパーサイクロプティスに とかされた。,%o 는(은) 슈퍼 사이클롭티스의 점액에 당했습니다.,%o werd afgeslankt door een Super Cycloptis.,%o ble slimet av en supersykloptis.,%o został@[ao_pl] oszlamion@[adj_pl] przez super cykloptisa.,%o foi lambuzad@[ao_ptb] por um super cyclóptis.,,%o a fost transformat în mâzgă de către un super cicloptic.,Игрока %o обслюнявил супер-циклоптис.,,%o bir süper sikloptis tarafından sümüklendi. -%o was defeated by a Maximus.,OB_MAXIMUS,,,,%o byl@[ao_cs] poražen@[ao_cs] Maximem.,%o blev besejret af en Maximus.,%o wurde von einem Maximus besiegt.,,%o estas venkita de ĉefmukulo.,%o fue derrotad@[ao_esp] por un Maximus.,,%o joutui Maximuksen päihittämäksi.,%o s'est fait@[e_fr] battre par un Maximus.,%o-t legyőzte egy Maximusz.,%o è stato sconfitto da un Maximus.,%o はマクシムスに 敗北した。,%o 는(은) 맥시무스에게 패배했습니다.,%o werd verslagen door een Maximus.,%o ble beseiret av en Maximus.,%o został@[ao_pl] pokonan@[adj_pl] przez Maximusa.,%o foi derrotad@[ao_ptb] por um Maximus.,,%o a fost înfrânt de către un Maxim.,Игрок %o проиграл Максимусу.,,%o bir Maximus tarafından yenildi. -%o was gooed by a larva.,OB_LARVA,,,,%o byl@[ao_cs] zacáknut@[ao_cs] larvou.,%o blev smurt af en larve.,%o wurde von einer Larve beschmiert.,,%o estas ŝlimiga de larvo.,%o fue pegotead@[ao_esp] por una larva.,,%o joutui toukan mönjäämäksi.,%o s'est fait@[e_fr] tacher par une larve.,%o lárvatrutyit kapott a nyakába.,%o è stato colpito da una larva.,%o はラーバに ヒドいめにあわされた。,%o 는(은) 애벌레에 의해 점액 범벅이 됐습니다.,%o werd door een Larve weggegooid.,%o ble gooed av en larve.,%o został@[ao_pl] zabrejowan@[adj_pl] przez larwę.,%o foi engosmad@[ao_ptb] por uma larva.,,%o a fost lovit de mâzga unei larve.,Игрока %o обслюнявила личинка.,,%o bir larva tarafından öldürüldü. -%o was slimed by a Quadrumpus.,OB_QUADRUMPUS,,,,%o byl@[ao_cs] zahleněn@[ao_cs] Čtyřzadkem.,%o blev slimet af en Quadrumpus.,%o wurde von einem Quadrumpus vollgeschleimt.,,%o estas ŝlimiga de kvarbrakmukulo.,%o fue enlodad@[ao_esp] por un Quadrumpus.,,%o joutui Neliperän limaamaksi.,%o s'est fait@[e_fr] morver par un quadrumpus.,%o-t összenyálkázta egy Négylábusz.,%o è stato ridotto da un Quadrumpus.,%o はクワッドロンプスに スライムにされた。,%o 는(은) 쿼드럼푸스의 점액에 당했습니다.,%o werd afgeslankt door een Quadrumpus.,%o ble slimet av en Quadrumpus.,%o został@[ao_pl] oszlamion@[adj_pl] przez Quadrumpusa.,%o foi melecad@[ao_ptb] por um Quadrumpus.,,%o a fost transformat în mâzgă de către o creatură cu patru mâini,Игрока %o обслюнявила многоручка. ,,%o bir Quadrumpus tarafından zayıflatıldı. -%o was defeated by the Flembomination.,OB_FLEMBOMINATION,,,,%o byl@[ao_cs] poražen@[ao_cs] Slizavností.,%o blev besejret af Flembomination.,%o wurde von der Flembomination besiegt.,,%o estas venkita de la Mukabomeno.,%o fue derrotad@[ao_esp] por la Flembominación.,,%o joutui Limaoikun päihittämäksi.,%o s'est fait@[e_fr] éliminer par la Flembomination.,%o-t legyőzte a Slejmdormány.,%o è stato sconfitto dalla Flembomination.,%o はフレンボミネーションに敗北した。,%o 는(은) 플렘보미네이션으로부터 벗어날 수 없었습니다.,%o werd verslagen door de Flembominatie.,%o ble beseiret av Flembominationen.,%o został@[ao_pl] pokonan@[adj_pl] przez Flembominację.,%o foi derrotad@[ao_ptb] pela Flembominação.,,%o a fost învins de către Flembominație.,Игрока %o победила Флемомерзость.,,"%o, Flembomination tarafından yenildi." -%o was defeated by Lord Snotfolus.,OB_SNOTFOLUS,,,,%o byl@[ao_cs] poražen@[ao_cs] Lordem Hlenfujem.,%o blev besejret af Lord Snotfolus.,%o wurde von Lord Snotfolus besiegt.,,%o estas venkita de Lordo Mukplenulo.,%o fue derrotad@[ao_esp] por Lord Mocofolus.,,%o joutui herra Räkänokan päihittämäksi.,%o est tombé@[e_fr] face au Seigneur Morvator.,%o legyőzetett Lord Takony által.,%o è stato sconfitto da Lord Snotfolus.,%o はロード スノフォールスに敗北した。,%o 는(은) 스놋폴러스 마왕과 싸울 준비를 제대로 하지 못했습니다.,%o werd verslagen door Lord Snotfolus.,%o ble beseiret av Lord Snotfolus.,%o został@[ao_pl] pokonan@[adj_pl] przez Lorda Smarkofolusa.,%o foi derrotad@[ao_ptb] pelo Lorde Snotfolus.,,%o a fost pus la pământ de către Lordul Snotfolus.,Игрока %o победил лорд Соплезелёнус.,,"%o, Lord Snotfolus tarafından yenildi." -%o was hit by %k's propulsor.,OB_MPR_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráče %k.,%o blev ramt af %ks propulsor.,%o wurde von %ks Propeller getroffen,,%o estas trafita de la propulsilo de %k.,%o fue alcanzad@[ao_esp] por el propulsor de %k.,,%k osui %o parkaan työntimellään.,%o s'est fait@[e_fr] propulser par %k.,%o-t eltalálta %k hajtóműve.,%o è stato colpito dal propulsore di %k.,%o に %k のロケットゾーチがとどいた。,%o 는(은) %k 의 추진력에 휘말렸습니다.,%o werd geraakt door %k's propulsor.,%o ble truffet av %ks propulsor.,%o został@[ao_pl] uderzon@[adj_pl] przez pędnik %k.,%o foi atingid@[ao_ptb] pelo propulsor de %k.,,%o a fost lovit de către propulsorul lui %k.,Игрок %o подстрелен из ускорителя Зорча %k.,,"%o, %k tarafından vuruldu." -%o was lazzed by %k.,OB_MPBFG_SPLASH,,,,%o byl@[ao_cs] odlazován@[ao_cs] hráčem %k.,%o blev lazzed af %k.,%o wurde von %o weggezorcht.,,%o estas LAZ-ita de %k.,%o fue lazead@[ao_esp] por %k.,,%k sazzasi pelaajaan %o.,%o est entré@[e_fr] dans la zone de zorchage large de %k.,%o-t szörcsölődött %k által.,%o è stato lazzato da %k.,%o は %k にとかされた。,%o 는(은) %k 에게 레이져를 쐬였습니다.,%o werd gelazzed door %k.,%o ble lazzed av %k.,%o został@[ao_pl] zLAZowan@[adj_pl] przez %k.,%o foi LAZead@[ao_ptb] por %k.,,%k a folosit dispozitivul LAZ pe %o.,Игрок %o получил заряд из «ЗБР» игрока %k.,,"%o, %k tarafından lazzlandı." +default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,sv,tr +Picked up a blue flemkey.,GOTBLUEFLEM,Flem = phlegm,,,Sebrán modrý slizoklíč.,Du samlede en blå flemkey op.,Blauen Flemschlüssel genommen,,Vi trovis bluan mukŝlosilon.,Encuentras una flemllave azul.,,Poimit sinisen lima-avaimen,Flemclé bleue récupérée.,Kék slejmkulcs felvéve.,Raccolta una chiave-flem blu.,ブルー フレムキー をみつけた,청색 플렘열쇠 획득.,Je hebt een blauwe flemsleutel opgehaald.,Plukket opp en blå flemkey.,Zebrano niebieski flemowy klucz,Pegou uma flemchave azul.,,Ai ridicat flemcheia albastră.,Получен синий флемключ.,,Plockade upp en blå flemnyckel.,Mavi bir flemkey aldım. +Picked up a yellow flemkey.,GOTYELLOWFLEM,,,,Sebrán žlutý slizoklíč.,Du samlede en gul flemkey op.,Gelben Flemschlüssel genommen,,Vi trovis flavan mukŝlosilon.,Encuentras una flemllave amarilla.,,Poimit keltaisen lima-avaimen,Flemclé jaune récupérée.,Sárga slejmkulcs felvéve.,Raccolta una chiave-flem gialla.,イエローフレムキー をみつけた,황색 플렘열쇠 획득.,Je hebt een gele flemsleutel opgehaald.,Plukket opp en gul flemkey.,Zebrano żółty flemowy klucz,Pegou uma flemchave amarela.,,Ai ridicat flemcheia galbenă.,Получен жёлтый флемключ.,,Plockade upp en gul flemnyckel.,Sarı bir flemkey aldı. +Picked up a red flemkey.,GOTREDFLEM,,,,Sebrán červený slizoklíč.,Du samlede en rød flemkey op.,Roten Flemschlüssel genommen.,,Vi trovis ruĝan mukŝlosilon.,Encuentras una flemllave roja.,,Poimit punaisen lima-avaimen,Flemclé rouge récupérée.,Piros slejmkulcs felvéve.,Raccolta una chiave-flem rossa.,レッド フレムキー をみつけた,적색 플렘열쇠 획득.,Je hebt een rode flemsleutel opgehaald.,Plukket opp en rød flemkey.,Zebrano czerwony flemowy klucz,Pegou uma flemchave vermelha.,,Ai ridicat flemcheia roșie.,Получен красный флемключ.,,Plockade upp en röd flemnyckel.,Kırmızı bir flemkey aldı. +Found Ultra Goggles,GOTGOGGLES,,,,Nalezeny ultrabrýle.,Fandt Ultra Goggles,Ultrasichtbrille gefunden,,Vi trovis plejajn okulvitrojn.,Encuentras ultragafas,Encuentras ultralentes,Löysit ultralasit,Ultra-lunettes récupérées.,Ultraszemüveg felvéve.,,ウルトラゴーグル をみつけた,울트라 고글 사용.,Ultraroggles gevonden,Fant Ultra Goggles,Znaleziono Ultra Gogle,Achou um Ultra Óculos.,,Ai găsit Ultra Ochelarii,Получены ультра-очки,,Hittade Ultra Goggles,Ultra Gözlük bulundu +You need a blue key to activate this object,PD_BLUECO,,,,Potřebuješ modrý klíč pro aktivaci tohoto objektu,Du skal bruge en blå nøgle for at aktivere dette objekt,"Du brauchst einen blauen Schlüssel, um dieses Objekt zu aktivieren.",,"Vi bezonas bluan ŝlosilon +por aktivigi ĉi tiun objekton.","Necesitas una llave azul +para activar este objeto",,Tarvitset sinisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé bleue pour activer cet objet.,Egy kék kulcs szükséges az objektum aktiválásához.,Ti serve una chiave blu per attivare questo oggetto,このそうちは ブルー キー がひつようだ,이걸 작동하려면 청색 열쇠가 필요합니다,Je hebt een blauwe sleutel nodig om dit object te activeren.,Du trenger en blå nøkkel for å aktivere dette objektet,"Potrzebujesz niebieskiego klucza, aby aktywować ten przedmiot",Você precisa de uma chave azul para ativar este objeto,,Ai nevoie de o cheie albastră pentru a activa acest obiect,Для открытия требуется синий ключ,Треба вам плави кључ да бисте активирали овај предмет,Du behöver en blå nyckel för att aktivera det här objektet.,Bu nesneyi etkinleştirmek için mavi bir anahtara ihtiyacınız var +You need a red key to activate this object,PD_REDCO,,,,Potřebuješ červený klíč pro aktivaci tohoto objektu,Du skal bruge en rød nøgle for at aktivere dette objekt,"Du brauchst einen roten Schlüssel, um dieses Objekt zu aktivieren.",,"Vi bezonas ruĝan ŝlosilon +por aktivigi ĉi tiun objekton.","Necesitas una llave roja +para activar este objeto",,Tarvitset punaisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé rouge pour activer cet objet.,Egy piros kulcs szükséges az objektum aktiválásához.,Ti serve una chiave rossa per attivare questo oggetto,このそうちは レッド キー がひつようだ,이걸 작동하려면 적색 열쇠가 필요합니다,Je hebt een rode sleutel nodig om dit object te activeren.,Du trenger en rød nøkkel for å aktivere denne gjenstanden,"Potrzebujesz czerwonego klucza, aby aktywować ten przedmiot",Você precisa de uma chave vermelha para ativar este objeto,,Ai nevoie de o cheie roșie pentru a activa acest obiect,Для открытия требуется красный ключ,Треба вам црвени кључ да бисте активирали овај предмет,Du behöver en röd nyckel för att aktivera det här objektet.,Bu nesneyi etkinleştirmek için kırmızı bir anahtara ihtiyacınız var +You need a yellow key to activate this object,PD_YELLOWCO,,,,Potřebuješ žlutý klíč pro aktivaci tohoto objektu,Du skal bruge en gul nøgle for at aktivere dette objekt,"Du brauchst einen gelben Schlüssel, um dieses Objekt zu aktivieren.",,"Vi bezonas flavan ŝlosilon +por aktivigi ĉi tiun objekton.","Necesitas una llave amarilla +para activar este objeto",,Tarvitset keltaisen avaimen aktivoidaksesi tämän kappaleen,Il vous faut une clé jaune pour activer cet objet.,Egy sárga kulcs szükséges az objektum aktiválásához.,Ti serve una chiave gialla per attivare questo oggetto,このそうちは イエローキー がひつようだ,이걸 작동하려면 황색 열쇠가 필요합니다,Je hebt een gele sleutel nodig om dit object te activeren.,Du trenger en gul nøkkel for å aktivere denne gjenstanden,"Potrzebujesz żółtego klucza, aby aktywować ten przedmiot",Você precisa de uma chave amarela para ativar este objeto,,Ai nevoie de o cheie galbenă pentru a activa acest obiect,Для открытия требуется жёлтый ключ,Треба вам жути кључ да бисте активирали овај предмет,Du behöver en gul nyckel för att aktivera det här objektet.,Bu nesneyi etkinleştirmek için sarı bir anahtara ihtiyacınız var +You need a blue flemkey to activate this object,PD_BLUEFO,,,,Potřebuješ modrý slizoklíč pro aktivaci tohoto objektu.,Du skal bruge en blå flemkey for at aktivere dette objekt,"Du brauchst einen blauen Flemschlüssel, um dieses Objekt zu aktivieren.",,"Vi bezonas bluan mukŝlosilon +por aktivigi ĉi tiun objekton.","Necesitas una flemllave azul +para activar este objeto",,Tarvitset sinisen lima-avaimen aktivoidaksesi tämän kappaleen,Il vous faut une flemclé bleue pour activer cet objet.,Egy kék slejmkulcs szükséges az objektum aktiválásához.,Ti serve una chiave-flem blu per attivare questo oggetto,このそうちは ブルー キーがひつようだ,이걸 작동하려면 청색 플렘열쇠가 필요합니다,Je hebt een blauwe flemsleutel nodig om dit object te activeren.,Du trenger en blå flemkey for å aktivere denne gjenstanden.,"Potrzebujesz niebieskiego flemowego klucza, aby aktywować ten przedmiot",Você precisa de uma flemchave azul para ativar este objeto,,Ai nevoie de o flemcheie albastră pentru a activa acest obiect,Для открытия требуется синий флемключ,,Du behöver en blå flemnyckel för att aktivera det här objektet.,Bu nesneyi etkinleştirmek için mavi bir flemkey'e ihtiyacınız var +You need a red flemkey to activate this object,PD_REDFO,,,,Potřebuješ červený slizoklíč pro aktivaci tohoto objektu.,Du skal bruge en rød flemkey for at aktivere dette objekt,"Du brauchst einen roten Flemschlüssel, um dieses Objekt zu aktivieren.",,"Vi bezonas ruĝan mukŝlosilon +por aktivigi ĉi tiun objekton.","Necesitas una flemllave roja +para activar este objeto",,Tarvitset punaisen lima-avaimen aktivoidaksesi tämän kappaleen,Il vous faut une flemclé rouge pour activer cet objet.,Egy piros slejmkulcs szükséges az objektum aktiválásához.,Ti serve una chiave-flem rossa per attivare questo oggetto,このそうちは レッド キーがひつようだ,이걸 작동하려면 적색 플렘열쇠가 필요합니다,Je hebt een rode flemsleutel nodig om dit object te activeren.,Du trenger en rød flemkey for å aktivere dette objektet.,"Potrzebujesz czerwonego flemowego klucza, aby aktywować ten przedmiot",Você precisa de uma flemchave vermelha para ativar este objeto,,Ai nevoie de o flemcheie roșie pentru a activa acest obiect,Для открытия требуется красный флемключ,,Du behöver en röd flemnyckel för att aktivera det här objektet.,Bu nesneyi etkinleştirmek için kırmızı bir flemkey'e ihtiyacınız var +You need a yellow flemkey to activate this object,PD_YELLOWFO,,,,Potřebuješ žlutý slizoklíč pro aktivaci tohoto objektu.,Du skal bruge en gul flemkey for at aktivere dette objekt,"Du brauchst einen gelben Flemschlüssel, um dieses Objekt zu aktivieren.",,"Vi bezonas flavan mukŝlosilon +por aktivigi ĉi tiun objekton.","Necesitas unaflemllave amarilla +para activar este objeto",,Tarvitset keltaisen lima-avaimen aktivoidaksesi tämän kappaleen,Il vous faut une flemclé jaune pour activer cet objet.,Egy sárga slejmkulcs szükséges az objektum aktiválásához.,Ti serve una chiave-flem gialla per attivare questo oggetto,このそうちは イエローキーがひつようだ,이걸 작동하려면 황색 플렘열쇠가 필요합니다,Je hebt een gele flemsleutel nodig om dit object te activeren.,Du trenger en gul flemkey for å aktivere dette objektet.,"Potrzebujesz żółtego flemowego klucza, aby aktywować ten przedmiot",Você precisa de uma flemchave amarela para ativar este objeto,,Ai nevoie de o flemcheie galbenă pentru a activa acest obiect,Для открытия требуется жёлтый флемключ,,Du behöver en gul flemnyckel för att aktivera det här objektet.,Bu nesneyi etkinleştirmek için sarı bir flemkey'e ihtiyacınız var +Picked up a zorcher.,PICKUP_PISTOL_DROPPED,,,,Sebrán bzukr.,Du samlede en zorcher op.,Zorcher genommen.,,Vi trovis zorĉilon.,Encuentras un zorcher.,,Poimit zorcherin,Zorcheur récupéré.,Szörcsölő felvéve.,Ho preso uno zorcher.,ゾーチャー をひろった,자쳐 습득.,Je hebt een zorcher opgehaald.,Plukket opp en zorcher.,Zebrano Zorcher,Pegou um zorcher.,,Ai ridicat un zorcher.,Получен зорчер.,,Plockade upp en zorcher.,Bir zorcher aldım. +Zorch and keys added,STSTR_KFAADDED,,,,Bzukr a klíče přidány,Zorch og nøgler tilføjet,Zorch und Schlüssel hinzugefügt.,,Zorĉaĵo kaj ŝlosiloj aldonitaj,Zorch y llaves añadidas,,Zorch ja avaimet lisätty,Zorch et clés ajoutées.,Szörcs és kulcsok hozzáadva.,Zorch e chiavi aggiunte,ゾーチ と キーがとどいた,저치와 열쇠,Zorch en sleutels toegevoegd,Zorch og nøkler lagt til,Dodano amunicję Zorch i klucze,Zorch e chaves adicionadas,,Zorcher și chei adăugate,Зорч и ключи получены,,Zorch och nycklar har lagts till,Zorch ve anahtarlar eklendi +E1M1: Landing Zone,HUSTR_E1M1,,,,E1M1: Přistávací zóna,E1M1: Landingszone,E1M1: Landezone,,E1M1: Surteriĝejo,E1M1: Zona de aterrizaje,,E1M1: Laskeutumisalue,E1M1: Zone D'Atterissage,E1M1: Leszállópálya,E1M1: Zona di Atterraggio,E1M1: ちゃくち ちてん,E1M1: 착륙 지점,E1M1: Landingzone,E1M1: Landingssone,E1M1: Strefa Lądowania,E1M1: Zona de Pouso,,E1M1: Zona de Aterizare,E1M1: Зона высадки,,E1M1: Landningszon,E1M1: İniş Bölgesi +E1M2: Storage Facility,HUSTR_E1M2,,,,E1M2: Skladiště,E1M2: Opbevaringsanlæg,E1M2: Lagerhalle,,E1M2: Stokejo,E1M2: Instalación de almacenamiento,,E1M2: Varastolaitos,E1M2: Centre de Stockage,E1M2: Raktárépület,E1M2: Struttura di Immagazzinamento,E1M2: ちょぞう しせつ,E1M2: 저장 시설,E1M2: Opslagfaciliteit,E1M2: Lagringsanlegg,E1M2: Magazyn,E1M2: Depósito,,E1M2: Depozitul,E1M2: Хранилище,,E1M2: Förvaringsanläggning,E1M2: Depolama Tesisi +E1M3: Laboratory,HUSTR_E1M3,,,,E1M3: Testovací laboratoř,E1M3: Laboratorium,E1M3: Labor,,E1M3: Laboratorio,E1M3: Laboratorio,,E1M3: Laboratorio,E1M3: Laboratoire,E1M3: Laboratórium,E1M3: Laboratorio,E1M3: ラボラトリー,E1M3: 연구소,E1M3: Laboratorium,E1M3: Laboratorium,E1M3: Laboratorium,E1M3: Laboratório de Experimentos,,E1M3: Laboratorul,E1M3: Лаборатория,,E1M3: Laboratorium,E1M3: Laboratuvar +E1M4: Arboretum,HUSTR_E1M4,,,,,,,,E1M4: Arbejo,E1M4: Arboreto,,,,E1M4: Arborétum,E1M4: Arboreto,E1M4: じゅもく園,E1M4: 수목원,,E1M4: Arboretet,E1M4: Arboretum,E1M4: Arvoredo,,,E1M4: Дендрарий,,, +E1M5: Caverns of Bazoik,HUSTR_E1M5,,,,E1M5: Bazoikské jeskyně,E1M5: Bazoiks grotter,E1M5: Die Höhlen von Bazoik,,E1M5: Kavernoj de Bazojko,E1M5: Cavernas de Bazoik,,E1M5: Bazoikin luolastot,E1M5: Cavernes de Bazoik,E1M5: Bazoik barlangjai,E1M5: Caverne di Bazoik,E1M5: バゾイクのどうくつ,E1M5: 바조이크의 대동굴,E1M5: Grotten van Bazoik,E1M5: Grottene i Bazoik,E1M5: Jaskinie Bazoik,E1M5: Cavernas de Bazoik,,E1M5: Cavernele lui Bazoik,E1M5: Пещеры Базоика,,E1M5: Bazoiks grottor,E1M5: Bazoik Mağaraları +E2M1: Spaceport,HUSTR_E2M1,,,,E2M1: Kosmodrom,E2M1: Rumhavn,E2M1: Raumhafen,,E2M1: Kosmo-haveno,E2M1: Puerto espacial,,E2M1: Avaruussatama,E2M1: Spatioport,E2M1: Űrkikötő,E2M1: Spazioporto,E2M1: スペースポート,E2M1: 우주공항,E2M1: Ruimtehaven,E2M1: Romhavn,E2M1: Port Kosmiczny,E2M1: Espaçoporto,,E2M1: Portul Spațial,E2M1: Космодром,,E2M1: Rymdflygplats,E2M1: Uzay Limanı +E2M2: Cinema,HUSTR_E2M2,,,,E2M2: Kino,,E2M2: Kino,,E2M2: Kinejo,E2M2: Cine,,E2M2: Elokuvateatteri,E2M2: Cinéma,E2M2: Mozi,,E2M2: シネマ,E2M2: 극장,E2M2: Bioscoop,E2M2: Kino,E2M2: Kino,,,,E2M2: Кинотеатр,,,E2M2: Sinema +E2M3: Chex Museum,HUSTR_E2M3,,,,E2M3: Muzem Chex,,,,E2M3: Chex-muzeo,E2M3: Museo de Chex,,E2M3: Chex-museo,E2M3: Musée Chex,E2M3: Chex-múzeum,E2M3: Museo di Chex,E2M3: チェックス ミュージアム,E2M3: 첵스 박물관,,,E2M3: Muzeum Chex,E2M3: Museu Chex,,E2M3: Muzeul Chex,E2M3: Музей Chex,,,E2M3: Chex Müzesi +E2M4: City Streets,HUSTR_E2M4,,,,E2M4: Městské ulice,E2M4: Byens gader,E2M4: städtische Straßen,,E2M4: Urbstratoj,E2M4: Calles de la ciudad,,E2M4: Kaupungin kadut,E2M4: Rues de la Ville,E2M4: Városi utcák,E2M4: Strade della città,E2M4: シティーストリート,E2M4: 도시 거리,E2M4: Stadsstraten,E2M4: Byens gater,E2M4: Ulice Miasta,E2M4: Ruas da Cidade,,E2M4: Străzile Orașului,E2M4: Городские улицы,,E2M4: Stadens gator,E2M4: Şehir Sokakları +E2M5: Sewer System,HUSTR_E2M5,,,,E2M5: Kanalizace,E2M5: Kloaksystem,E2M5: Kanalisation,,E2M5: Defluilego-sistemo,E2M5: Alcantarillado,,E2M5: Viemärijärjestelmä,E2M5: Système d'égouts,E2M5: Csatornarendszer,E2M5: Rete fognaria,E2M5: サワーシステム,E2M5: 하수도,E2M5: Rioleringssysteem,E2M5: Avløpssystem,E2M5: System Ścieków,E2M5: Rede de Esgoto,,E2M5: Sistemul de Canalizare,E2M5: Канализация,,E2M5: Avloppssystem,E2M5: Kanalizasyon Sistemi +E3M1: Central Command,HUSTR_E3M1,,,,E3M1: Centrální velení,E3M1: Centralkommando,E3M1: Kommandozentrale,,E3M1: Centra komandejo,E3M1: Comando central,,E3M1: Komentokeskus,E3M1: Commandement,E3M1: Központi parancsnokság,E3M1: Comando centrale,E3M1: 中央しれいとう,E3M1: 중앙 사령부,E3M1: Centraal Commando,E3M1: Sentral kommando,E3M1: Centrum Dowodzenia,E3M1: Comando Central,,E3M1: Centrul de Comanda,E3M1: Командный центр,,E3M1: Centrala kommandot,E3M1: Merkez Komutanlığı +E3M2: United Cereals,HUSTR_E3M2,,,,E3M2: Spojené cereálie,,E3M2: Vereinigte Zerealien,,E3M2: Uniaj Cerealoj,E3M2: Cereales Unidos,,E3M2: Yhdistyneet murot,E3M2: Céréales Unies,E3M2: Egyesült Gabonapelyhek,E3M2: Cereali uniti,E3M2: ユナイテッド シリアル,E3M2: 시리얼 연합,E3M2: Verenigde granen,,E3M2: Zjednoczone Płatki,E3M2: Cereais Unidos,,E3M2: Cereale Unite,E3M2: Организация Объединённых Хлопьев,,E3M2: United Cereals,E3M2: Birleşik Tahıllar +E3M3: Villa Chex,HUSTR_E3M3,,,,,,,,E3M3: Vilao Chex,,,,E3M3: Villa Chex,,,E3M3: チェックスのべっそう,E3M3: 책스 주택,,,E3M3: Willa Chex,,,E3M3: Vila Chex,E3M3: Вилла Chex,,, +E3M4: Provincial Park,HUSTR_E3M4,,,,E3M4: Provinciální park,,E3M4: Provinzpark,,E3M4: Provinca parko,E3M4: Parque provincial,,E3M4: Provinssipuisto,E3M4: Parc Naturel,E3M4: Tartományi park,E3M4: Parco provinciale,E3M4: 州立公園,E3M4: 주립공원,E3M4: Provinciaal Park,,E3M4: Prowincjonalny Park,E3M4: Parque Natural,,E3M4: Parcul Provincial,E3M4: Провинциальный парк,,,E3M4: İl Parkı +E3M5: Meteor Spaceship,HUSTR_E3M5,,,,E3M5: Meteorová vesmírná loď,E3M5: Meteor rumskib,E3M5: Meteor-Raumschiff,,E3M5: Meteor-kosmoŝipo,E3M5: Nave meteoro,,E3M5: Meteoriavaruusalus,E3M5: Vaisseau Météore,E3M5: Meteor űrhajó,E2M5: Astronave meteorica,E3M5: メテオスペースシップ,E3M5: 거대 유성호,E3M5: Ruimteschip,E3M5: Meteor-romskipet,"E3M5: Statek Kosmiczny ""Meteor""",E3M5: Espaçonave Meteoro,,E3M5: Nava Spațială Meteor,E3M5: Космический корабль «Метеор»,,E3M5: Rymdskeppet Meteor,E3M5: Meteor Uzay Gemisi +Commonus,CC_ZOMBIE,,,,Obecnýs,,,,Oftmukulo,Comunis,,,,Általánusz,,コモンズ,커머누스,,,Pospolitus,,,Comun,Обыкновеннус,,, +Bipedicus,CC_SHOTGUN,,,,Dvojnožus,,,,Dupiedmukulo,Bipedico,,,,Kétlábusz,,バイピディクス,바이피디쿠스,,,,,,Biped,Двуножка,,, +Bipedicus with Armor,CC_IMP,,,,Dvojnožus s brněním,Bipedicus med rustning,Bipedicus mit Panzerung,,Kirasa Dupiedmukulo,Bipedico con armadura,,Panssaroitu bipedicus,Bipedicus avec Armure,Páncélozott kétlábusz,Bipedicus corazzato,アーマードバイピディクス,정예 바이피디쿠스,Bipedicus met harnas,Bipedicus med rustning,Opancerzony Bipedicus,Bipedicus de Armadura,,Biped cu Armură,Бронированная двуножка,,Bipedicus med rustning,Zırhlı Bipedicus +Stridicus,CC_DEMON,,,,Běhakus,,,,Paŝmukulo,Zancadico,,,,Lépkedüsz,,ステュリクス,스트리디쿠스,,,,,,Picioare-Lungi,Длинноножка,,, +Flem Mine,CC_LOST,,,,Slizná mina,,,,Muksentinelo,Flem-Mina,,Limamiina,,Slejmakna,Bomba a Flem,フレムマイン,플렘 지뢰,Flemmijn,,Flemowa Mina,Mina Flem,,Flem Mină,Флем-мина,,Flem-gruva,Flem Madeni +Super Cycloptis,CC_CACO,,,,Superkykloptus,,,,Supera Ciklopmukulo,Supercícloptis,,Supercycloptis,,Szuper Kükloptisz,,スーパーサイクロプティス,슈퍼 사이클롭티스,,Supersykloptis.,Super Cykloptis,,,Super Cicloptic,Супер-циклоптис,,,Süper Cycloptis +Maximus,CC_BARON,,,,,,,,Mukulestro,Máximus,,,,Maximusz,,マクシムス,맥시무스,,,,,,Maxim,Максимус,,, +The Flembomination,CC_SPIDER,,,,Slizavnost,Flembominationen,Die Flembomination,,Mukabomeno,La Flembominación,,Limaoikku,La Flembomination,Slejmdormány,La Flembominio,フレンボミネーション,플렘보미네이션,De Flembominatie,Flembominationen,Flembominacja,A Flembominação,,Flembominație,Флемомерзость,,Flammbomineringen,Flembomination +Lord Snotfolus,CC_CYBER,,,,Lord Hlenfujus,,,,Lordo Mukplenulo,Lord Mocofolus,,Herra Räkänokka,Seigneur Morvator,Lord Takony,,ロード スノフォールス,스놋폴러스 마왕,,,Lord Smarkofolus,Lorde Snotfolus,,Lordul Snotfolus,Правитель Соплезелёнус,,, +Chex Warrior,CC_HERO,,,,Bojovník Chex,Chex Kriger,Chex Krieger,,Chex-batalisto,,,Chex-soturi,Guerrier Chex,Chex harcos,Guerriero Chex,チェックスのせんし,첵스 전사,Chex Krijger,Chex-krigeren,Wojownik Chex,Guerreiro Chex,,Războinic Chex,Воин Chex,,Chex krigare,Chex Savaşçısı +You need a blue key to open this door,PD_BLUEC,,,,Potřebuješ modrý klíč pro otevření těchto dveří,Du skal bruge en blå nøgle for at åbne denne dør,"Du brauchst einen blauen Schlüssel, um diese Tür zu öffnen.",,"Vi bezonas bluan ŝlosilon +por malfermi ĉi tiun pordon.","Necesitas una llave azul +para abrir esta puerta",,Tarvitset sinisen avaimen avataksesi tämän oven,Il vous faut une clé bleue pour ouvrir cette porte.,Kell egy kék kulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave blu per aprire questa porta,このとびらは ブルー キー がひつようだ,이 문을 열려면 청색 열쇠가 필요합니다,Je hebt een blauwe sleutel nodig om deze deur te openen.,Du trenger en blå nøkkel for å åpne denne døren,"Potrzebujesz niebieskiego klucza, aby otworzyć te drzwi",Você precisa de uma chave azul para abrir essa porta,,Ai nevoie de o cheie albastră pentru a deschide ușa aceasta,"Нужен синий ключ, чтобы открыть",Треба вам плави кључ да бисте отворили ова врата,Du behöver en blå nyckel för att öppna den här dörren.,Bu kapıyı açmak için mavi bir anahtara ihtiyacın var. +You need a red key to open this door,PD_REDC,,,,Potřebuješ červený klíč pro otevření těchto dveří,Du skal bruge en rød nøgle for at åbne denne dør,"Du brauchst einen roten Schlüssel, um diese Tür zu öffnen.",,"Vi bezonas ruĝan ŝlosilon +por malfermi ĉi tiun pordon.","Necesitas una llave roja +para abrir esta puerta",,Tarvitset punaisen avaimen avataksesi tämän oven,Il vous faut une clé rouge pour ouvrir cette porte.,Kell egy piros kulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave rossa per aprire questa porta,このとびらは レッド キー がひつようだ,이 문을 열려면 적색 열쇠가 필요합니다,Je hebt een rode sleutel nodig om deze deur te openen.,Du trenger en rød nøkkel for å åpne denne døren,"Potrzebujesz czerwonego klucza, aby otworzyć te drzwi",Você precisa de uma chave vermelha para abrir essa porta,,Ai nevoie de o cheie roșie pentru a deschide ușa aceasta,"Нужен красный ключ, чтобы открыть",Треба вам црвени кључ да бисте отворили ова врата,Du behöver en röd nyckel för att öppna den här dörren,Bu kapıyı açmak için kırmızı bir anahtara ihtiyacın var. +You need a yellow key to open this door,PD_YELLOWC,,,,Potřebuješ žlutý klíč pro otevření těchto dveří,Du skal bruge en gul nøgle for at åbne denne dør,"Du brauchst einen gelben Schlüssel, um diese Tür zu öffnen.",,"Vi bezonas flavan ŝlosilon +por malfermi ĉi tiun pordon.","Necesitas una llave amarilla +para abrir esta puerta",,Tarvitset keltaisen avaimen avataksesi tämän oven,Il vous faut une clé jaune pour ouvrir cette porte.,Kell egy sárga kulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave gialla per aprire questa porta,このとびらは イエローキー がひつようだ,이 문을 열려면 황색 열쇠가 필요합니다,Je hebt een gele sleutel nodig om deze deur te openen.,Du trenger en gul nøkkel for å åpne denne døren,"Potrzebujesz żółtego klucza, aby otworzyć te drzwi",Você precisa de uma chave amarela para abrir essa porta,,Ai nevoie de o cheie galbenă pentru a deschide ușa aceasta,"Нужен жёлтый ключ, чтобы открыть",Треба вам жути кључ да бисте отворили ова врата,Du behöver en gul nyckel för att öppna den här dörren,Bu kapıyı açmak için sarı bir anahtara ihtiyacınız var +You need a blue flemkey to open this door,PD_BLUEF,,,,Potřebuješ modrý slizoklíč pro otevření těchto dveří,Du skal bruge en blå flemkey for at åbne denne dør,"Du brauchst einen blauen Flemschlüssel, um diese Tür zu öffnen.",,"Vi bezonas bluan mukŝlosilon +por malfermi ĉi tiun pordon.","Necesitas una flemllave azul +para abrir esta puerta",,Tarvitset sinisen lima-avaimen avataksesi tämän oven,Il vous faut une flemclé bleue pour ouvrir cette porte.,Kell egy kék slejmkulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave-flem blu per aprire questa porta,このとびらは ブルー キーがひつようだ,이 문을 열려면 청색 플렘열쇠가 필요합니다,Je hebt een blauwe flemsleutel nodig om deze deur te openen.,Du trenger en blå flemkey for å åpne denne døren,"Potrzebujesz niebieskiego flemowego klucza, aby otworzyć te drzwi",Você precisa de uma flemchave azul para ativar este objeto,,Ai nevoie de o flemcheie albastră pentru a deschide ușa aceasta,"Нужен синий флемключ, чтобы открыть",,Du behöver en blå flemnyckel för att öppna den här dörren.,Bu kapıyı açmak için mavi bir flemkey'e ihtiyacın var. +You need a red flemkey to open this door,PD_REDF,,,,Potřebuješ červený slizoklíč pro otevření těchto dveří,Du skal bruge en rød flemkey for at åbne denne dør,"Du brauchst einen roten Flemschlüssel, um diese Tür zu öffnen.",,"Vi bezonas ruĝan mukŝlosilon +por malfermi ĉi tiun pordon.","Necesitas una flemllave roja +para abrir esta puerta",,Tarvitset punaisen lima-avaimen avataksesi tämän oven,Il vous faut une flemclé rouge pour ouvrir cette porte.,Kell egy piros slejmkulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave-flem rossa per aprire questa porta,このとびらは レッド キーがひつようだ,이 문을 열려면 적색 플렘열쇠가 필요합니다,Je hebt een rode flemsleutel nodig om deze deur te openen.,Du trenger en rød flemkey for å åpne denne døren,"Potrzebujesz czerwonego flemowego klucza, aby otworzyć te drzwi",Você precisa de uma flemchave vermelha para ativar este objeto,,Ai nevoie de o flemcheie roșie pentru a deschide ușa aceasta,"Нужен красный флемключ, чтобы открыть",,Du behöver en röd flemnyckel för att öppna den här dörren.,Bu kapıyı açmak için kırmızı bir flemkey'e ihtiyacın var. +You need a yellow flemkey to open this door,PD_YELLOWF,,,,Potřebuješ žlutý slizoklíč pro otevření těchto dveří,Du har brug for en gul flemkey for at åbne denne dør,"Du brauchst einen gelben Flemschlüssel, um diese Tür zu öffnen.",,"Vi bezonas flavan mukŝlosilon +por malfermi ĉi tiun pordon.","Necesitas una flemllave amarilla +para abrir esta puerta",,Tarvitset keltaisen lima-avaimen avataksesi tämän oven,Il vous faut une flemclé jaune pour ouvrir cette porte.,Kell egy sárga slejmkulcs hogy kinyisd ezt az ajtót.,Ti serve una chiave-flem gialla per aprire questa porta,このとびらは イエローキーがひつようだ,이 문을 열려면 황색 플렘열쇠가 필요합니다,Je hebt een gele flemsleutel nodig om deze deur te openen.,Du trenger en gul flemkey for å åpne denne døren,"Potrzebujesz żółtego flemowego klucza, aby otworzyć te drzwi",Você precisa de uma flemchave amarela para ativar este objeto,,Ai nevoie de o flemcheie galbenă pentru a deschide ușa aceasta,"Нужен жёлтый флемключ, чтобы открыть",,Du behöver en gul flemnyckel för att öppna den här dörren.,Bu kapıyı açmak için sarı bir flemkey'e ihtiyacın var. +%o sinks into some slime.,OB_SLIME,,,,%o se propadl@[ao_cs] do slizu.,%o synker ned i noget slim.,%o versank im Schleim,,%o sinkas en ŝlimon.,%o se hunde en babas.,,%o uppoaa limaan,%o se noie dans la morve.,%o elsüllyedt a trutyiban.,%o affonda in qualche melma.,%o はスライムにしずんだ。,%o 는(은) 점액 속으로 가라앉았습니다.,%o zinkt in wat slijm.,%o synker ned i noe slim.,%o topi się w szlamie.,%o afundou na gosma.,,%o se scufundă în mâzgă.,Игрок %o утонул в слизи.,,%o sjunker ner i lite slem.,%o balçığın içine battı. +%o sinks into some slime.,OB_LAVA,,,,%o se propadl@[ao_cs] do slizu.,%o synker ned i noget slim.,%o versank im Schleim,,%o sinkas en ŝlimon.,%o se hunde en babas.,,%o uppoaa limaan,%o se noie dans la morve.,%o elsüllyedt a trutyiban.,%o affonda in qualche melma.,%o はスライムにしずんだ。,%o 는(은) 질척하게 가라앉았습니다.,%o zinkt in wat slijm.,%o synker ned i noe slim.,%o topi się w szlamie.,%o afundou na gosma.,,%o se scufundă în mâzgă.,Игрок %o утонул в слизи.,,%o sjunker ner i lite slem.,%o balçığın içine battı. +%o was hit by inter-dimensional slime!,OB_POWERSTRAND,,,,%o byl@[ao_cs] zasažen@[ao_cs] mezidimenzionálním slizem!,%o blev ramt af interdimensionalt slim!,%o wurde von interdimensionalem Schleim getroffen,,%o estis trafita de interdimensia ŝlimo!,¡A %o l@[ao_esp] ha alcanzado baba interdimensional!,¡A %o l@[ao_esp] alcanzó baba interdimensional!,%o parkaan osui interdimensionaalista limaa!,%o s'est fait@[e_fr] toucher par de la morve interdimensionelle!,%o interdimenzionális trutyi áldozata lett!,%o è stato colpito da melma interdimensionale!,%o は いじげんスライムまみれになった!,%o 는(은) 차원균열 점액에 맞았습니다!,%o werd geraakt door interdimensionaal slijm!,%o ble truffet av interdimensjonalt slim!,%o został@[ao_pl] uderzon@[adj_pl] przez międzywymiarowy szlam!,%o foi atingid@[ao_ptb] por gosma interdimensional!,,%o a fost lovit de mâzgă interdimensională!,В игрока %o попала межпространственная слизь!,,%o träffades av interdimensionellt slem!,%o boyutlar arası balçık tarafından vuruldu! +%o was hit by inter-dimensional slime!,OB_KILLEDSELF,,,,%o byl@[ao_cs] zasažen@[ao_cs] mezidimenzionálním slizem!,%o blev ramt af interdimensionalt slim!,%o wurde von interdimensionalem Schleim getroffen,,%o estis trafita de interdimensia ŝlimo!,¡A %o l@[ao_esp] ha alcanzado baba interdimensional!,¡A %o l@[ao_esp] alcanzó baba interdimensional!,%o parkaan osui interdimensionaalista limaa!,%o s'est fait@[e_fr] toucher par de la morve interdimensionelle!,%o interdimenzionális trutyi áldozata lett!,%o è stato colpito da melma interdimensionale!,%o は いじげんスライムまみれになった!,%o 는(은) 모르는 사이에 점액에 당했습니다!,%o werd geraakt door interdimensionaal slijm!,%o ble truffet av interdimensjonalt slim!,%o został@[ao_pl] uderzon@[adj_pl] przez międzywymiarowy szlam!,%o foi atingid@[ao_ptb] por gosma interdimensional!,,%o a fost lovit de mâzgă interdimensională!,В игрока %o попала межпространственная слизь!,,%o träffades av interdimensionellt slem!,%o boyutlar arası balçık tarafından vuruldu! +%o was boogered by a stridicus.,OB_STRIDICUS,,,,%o dostal@[ao_cs] holuby od běhakem.,%o blev buogered af en stridicus.,%o wurde von einem Stridicus bepopelt.,,%o estis mukigita de Paŝmukulo.,A %o l@[ao_esp] ha moqueado un Zancadico.,A %o l@[ao_esp] moqueó un Zancadico.,%o joutui stridicuksen räkäämäksi.,%o s'est fait@[e_fr] engluer par un stridicus.,%o taknyos lett egy lépkedüsztől.,%o è stato colpito da uno Stridicus.,%o は ステュリクスに おびやかされた。,%o 는(은) 스트리디쿠스의 코딱지에 당했습니다.,%o werd door een stridicus gezoomd.,%o ble bæsjet av en stridicus.,%o został@[ao_pl] zaglutowan@[adj_pl] przez stridicusa.,%o foi melecad@[ao_ptb] por um stridicus.,,%o a fost speriat de către un picioare-lungi.,Игрока %o облепила соплями длинноножка. ,,%o blev utskälld av en stridicus.,%o bir stridicus tarafından avlandı. +%o was gooed by a flem mine.,OB_FLEMMINE,,,,%o byl@[ao_cs] zablácen@[ao_cs] sliznou minou.,%o blev smittet af en flem mine.,%o wurde von einer Flem-Mine beschmiert.,,%o estis glukovrita de Muksentinelo.,A %o l@[ao_esp] ha pegoteado una Flem-Mina.,A %o l@[ao_esp] pegoteó una Flem-Mina.,%o joutui limamiinan mönjäämäksi.,%o s'est fait@[e_fr] éclabousser par une flem mine.,%o-t összenyálkázta egy slejmakna.,%o è stato colpito da una bomba a flem.,%o はフレムマインに ヒドいめにあった。,%o 는(은) 플렘 지뢰에 의해 점액 범벅이 됐습니다.,%o werd door een Flemmijn getreiterd.,%o ble gooed av en flem mine.,"%o został@[ao_pl] zabrejowan@[adj_pl] przez flemową minę. +",%o foi engosmad@[ao_ptb] por uma mina flem.,,%o a fost lovit de mâzga unei flem mine.,Игрока %o забрызгала флем-мина.,,%o blev gooad av en loppgruva.,%o bir flem mayını tarafından yapışkan hale getirildi. +%o was slimed by a super cycloptis.,OB_SUPERCYCLOPTIS,,,,%o byl@[ao_cs] osliznut@[ao_cs] superkykloptem.,%o blev slimet af en super cycloptis.,%o wurde von einem Super Cycloptis vollgeschleimt.,,%o estis ŝlimigita de Supera Ciklopmukulo.,A %o l@[ao_esp] ha enlodado un Supercícloptis.,A %o l@[ao_esp] enlodó un Supercícloptis.,%o joutui supercycloptiksen limaamaksi.,%o s'est fait@[e_fr] gélifier par un super cycloptis.,%o-t összenyálkázta egy Szuper Kükloptisz.,%o è stato snellito da una Super Ciyloptis.,%o はスーパーサイクロプティスに とかされた。,%o 는(은) 슈퍼 사이클롭티스의 점액에 당했습니다.,%o werd afgeslankt door een Super Cycloptis.,%o ble slimet av en supersykloptis.,%o został@[ao_pl] oszlamion@[adj_pl] przez super cykloptisa.,%o foi lambuzad@[ao_ptb] por um super cyclóptis.,,%o a fost transformat în mâzgă de către un super cicloptic.,Игрока %o обслюнявил супер-циклоптис.,,%o blev slemmig av en supercykloptis.,%o bir süper sikloptis tarafından sümüklendi. +%o was defeated by a Maximus.,OB_MAXIMUS,,,,%o byl@[ao_cs] poražen@[ao_cs] Maximem.,%o blev besejret af en Maximus.,%o wurde von einem Maximus besiegt.,,%o estis venkita de Mukulestro.,A %o l@[ao_esp] ha derrotado un Máximus.,A %o l@[ao_esp] derrotó un Máximus.,%o joutui Maximuksen päihittämäksi.,%o s'est fait@[e_fr] battre par un Maximus.,%o-t legyőzte egy Maximusz.,%o è stato sconfitto da un Maximus.,%o はマクシムスに 敗北した。,%o 는(은) 맥시무스에게 패배했습니다.,%o werd verslagen door een Maximus.,%o ble beseiret av en Maximus.,%o został@[ao_pl] pokonan@[adj_pl] przez Maximusa.,%o foi derrotad@[ao_ptb] por um Maximus.,,%o a fost înfrânt de către un Maxim.,Игрок %o проиграл Максимусу.,,%o besegrades av en Maximus.,%o bir Maximus tarafından yenildi. +%o was gooed by a larva.,OB_LARVA,,,,%o byl@[ao_cs] zacáknut@[ao_cs] larvou.,%o blev smurt af en larve.,%o wurde von einer Larve beschmiert.,,%o estis glukovrita de larvo.,A %o l@[ao_esp] ha pegoteado una larva.,A %o l@[ao_esp] pegoteó una larva.,%o joutui toukan mönjäämäksi.,%o s'est fait@[e_fr] tâcher par une larve.,%o lárvatrutyit kapott a nyakába.,%o è stato colpito da una larva.,%o はラーバに ヒドいめにあわされた。,%o 는(은) 애벌레에 의해 점액 범벅이 됐습니다.,%o werd door een Larve weggegooid.,%o ble gooed av en larve.,%o został@[ao_pl] zabrejowan@[adj_pl] przez larwę.,%o foi engosmad@[ao_ptb] por uma larva.,,%o a fost lovit de mâzga unei larve.,Игрока %o обслюнявила личинка.,,%o blev göad av en larv.,%o bir larva tarafından öldürüldü. +%o was slimed by a Quadrumpus.,OB_QUADRUMPUS,,,,%o byl@[ao_cs] zahleněn@[ao_cs] Čtyřzadkem.,%o blev slimet af en Quadrumpus.,%o wurde von einem Quadrumpus vollgeschleimt.,,%o estis ŝlimigita de kvarbrakmukulo.,A %o l@[ao_esp] ha enlodado un Quadrumpus.,A %o l@[ao_esp] enlodó un Quadrumpus.,%o joutui Neliperän limaamaksi.,%o s'est fait@[e_fr] morver par un quadrumpus.,%o-t összenyálkázta egy Négylábusz.,%o è stato ridotto da un Quadrumpus.,%o はクワッドロンプスに スライムにされた。,%o 는(은) 쿼드럼푸스의 점액에 당했습니다.,%o werd afgeslankt door een Quadrumpus.,%o ble slimet av en Quadrumpus.,%o został@[ao_pl] oszlamion@[adj_pl] przez Quadrumpusa.,%o foi melecad@[ao_ptb] por um Quadrumpus.,,%o a fost transformat în mâzgă de către o creatură cu patru mâini,Игрока %o обслюнявила многоручка. ,,%o blev slemmad av en Quadrumpus.,%o bir Quadrumpus tarafından zayıflatıldı. +%o was defeated by the Flembomination.,OB_FLEMBOMINATION,,,,%o byl@[ao_cs] poražen@[ao_cs] Slizavností.,%o blev besejret af Flembomination.,%o wurde von der Flembomination besiegt.,,%o estis venkita de la Mukabomeno.,A %o l@[ao_esp] ha derrotado la Flembominación.,A %o l@[ao_esp] derrotó la Flembominación.,%o joutui Limaoikun päihittämäksi.,%o s'est fait@[e_fr] éliminer par la Flembomination.,%o-t legyőzte a Slejmdormány.,%o è stato sconfitto dalla Flembomination.,%o はフレンボミネーションに敗北した。,%o 는(은) 플렘보미네이션으로부터 벗어날 수 없었습니다.,%o werd verslagen door de Flembominatie.,%o ble beseiret av Flembominationen.,%o został@[ao_pl] pokonan@[adj_pl] przez Flembominację.,%o foi derrotad@[ao_ptb] pela Flembominação.,,%o a fost învins de către Flembominație.,Игрока %o победила Флемомерзость.,,%o besegrades av Flembomination.,"%o, Flembomination tarafından yenildi." +%o was defeated by Lord Snotfolus.,OB_SNOTFOLUS,,,,%o byl@[ao_cs] poražen@[ao_cs] Lordem Hlenfujem.,%o blev besejret af Lord Snotfolus.,%o wurde von Lord Snotfolus besiegt.,,%o estis venkita de Lordo Mukplenulo.,A %o l@[ao_esp] ha derrotado Lord Mocofolus.,A %o l@[ao_esp] derrotó Lord Mocofolus.,%o joutui herra Räkänokan päihittämäksi.,%o est tombé@[e_fr] face au Seigneur Morvator.,%o legyőzetett Lord Takony által.,%o è stato sconfitto da Lord Snotfolus.,%o はロード スノフォールスに敗北した。,%o 는(은) 스놋폴러스 마왕과 싸울 준비를 제대로 하지 못했습니다.,%o werd verslagen door Lord Snotfolus.,%o ble beseiret av Lord Snotfolus.,%o został@[ao_pl] pokonan@[adj_pl] przez Lorda Smarkofolusa.,%o foi derrotad@[ao_ptb] pelo Lorde Snotfolus.,,%o a fost pus la pământ de către Lordul Snotfolus.,Игрока %o победил правитель Соплезелёнус.,,%o besegrades av Lord Snotfolus.,"%o, Lord Snotfolus tarafından yenildi." +%o was hit by %k's propulsor.,OB_MPR_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráče %k.,%o blev ramt af %ks propulsor.,%o wurde von %ks Propeller getroffen,,%o estis trafita de la propulsilo de %k.,A %o l@[ao_esp] ha alcanzado el propulsor de %k.,A %o l@[ao_esp] alcanzó el propulsor de %k.,%k osui %o parkaan työntimellään.,%o s'est fait@[e_fr] propulser par %k.,%o-t eltalálta %k hajtóműve.,%o è stato colpito dal propulsore di %k.,%o に %k のロケットゾーチがとどいた。,%o 는(은) %k 의 추진력에 휘말렸습니다.,%o werd geraakt door %k's propulsor.,%o ble truffet av %ks propulsor.,%o został@[ao_pl] uderzon@[adj_pl] przez pędnik %k.,%o foi atingid@[ao_ptb] pelo propulsor de %k.,,%o a fost lovit de către propulsorul lui %k.,Игрок %o подстрелен из ускорителя зорча %k.,,%o träffades av %ks propulsor.,"%o, %k tarafından vuruldu." +%o was lazzed by %k.,OB_MPBFG_SPLASH,,,,%o byl@[ao_cs] odlazován@[ao_cs] hráčem %k.,%o blev lazzed af %k.,%o wurde von %o weggezorcht.,,%o estis LAZ-ita de %k.,A %o l@[ao_esp] ha «lazeado» %k.,A %o l@[ao_esp] «lazeó» %k.,%k sazzasi pelaajaan %o.,%o est entré@[e_fr] dans la zone de zorchage large de %k.,%o-t szörcsölődött %k által.,%o è stato lazzato da %k.,%o は %k にとかされた。,%o 는(은) %k 에게 레이져를 쐬였습니다.,%o werd gelazzed door %k.,%o ble lazzed av %k.,%o został@[ao_pl] zLAZowan@[adj_pl] przez %k.,%o foi LAZead@[ao_ptb] por %k.,,%k a folosit dispozitivul LAZ pe %o.,Игрок %o получил заряд из «ЗБР» игрока %k.,,%o blev lurad av %k.,"%o, %k tarafından lazzlandı." "After sending the monstrous Flembrane back to his own dimension, you free the captives. Yet flemoids are everywhere! @@ -321,7 +345,27 @@ Orașul Chex!","Изгнав чудовищную Флембрану назад К сожалению, ты оказал@[refl_rus] прав@[ao_rus]. Вернувшись домой, ты обнаружил@[ao_rus], что Флемоиды добрались и сюда. -Тебя ждёт Chex Quest 2: Террор в Городе Chex!",,"Canavar Flembrane'i kendi boyutuna +Тебя ждёт Chex Quest 2: Террор в Городе Chex!",,"Efter att ha skickat tillbaka den +monstruösa Flembrane till sin +egen dimension befriar du +fångarna. Ändå finns flemoider +överallt! +Du och fångarna gör en +utbrytning till ditt rymdskepp. +Flemoiderna slevar ditt skepp, +men du lyckas med nöd och +näppe fly i omloppsbana. +Under återresan gratuleras du +till den djärva räddningen, men +du utfärdar en varning... +Vi har inte sett det sista av +flemoiderna. + +Tyvärr har du rätt. För när du +återvänder hem upptäcker du +att Flemoiderna på något sätt +har följt dig hit. Förbered dig på +Chex Quest 2: Terror i Chex City!","Canavar Flembrane'i kendi boyutuna geri gönderdikten sonra tutsakları serbest bırakıyorsunuz. Yine de flemoidler her yerde! @@ -601,7 +645,7 @@ interdimensională gigantă, iar acum o bilă enormă de mâzgă e îndreptată drept către planeta cerealelor! -Pregătește-te pentru Chex Quest 3: Invazia!","С помощью Зорчера, ты освободил@[ao_rus] +Pregătește-te pentru Chex Quest 3: Invazia!","С помощью зорчера, ты освободил@[ao_rus] канализацию от оставшихся флемоидов. Город Chex спасён. Казалось, что с угрозой флемоидов наконец-то покончено. @@ -615,7 +659,27 @@ Pregătește-te pentru Chex Quest 3: Invazia!","С помощью Зорчера разлом в космосе. Над планетой хлопьев навис огромный шар из слизи! -Приготовься к Chex Quest 3: Вторжение!",,"Kanalizasyonda toplanmış olan kalan +Приготовься к Chex Quest 3: Вторжение!",,"Du zorch de återstående +flemoiderna som hade samlats +i kloakerna. Chex City har +räddats. Det verkar som om +Flemoid-hotet äntligen har +upphört. + +Tio år går i fred och välstånd. +Men Flemoiderna besegrades +inte och deras önskan att +kontrollera den näringsrika +spannmålsdimensionen har inte +minskat. +De har samlat alla sina styrkor, +öppnat en gigantisk inter- +dimensionell spricka i rymden +och nu är en stor boll av slem på +väg rakt mot spannmålens planet! + +Gör dig redo för +Chex Quest 3: Invasion!","Kanalizasyonda toplanmış olan kalan flemoidleri zorluyorsun. Chex Şehri kurtarıldı. Görünüşe göre Flemoid tehdidi nihayet sona erdi. @@ -818,19 +882,31 @@ Speri cu adevărat că Flemoizii și-au învățat lecția cerealelor. -Dar dacă o vor face, vei fi pregătit pentru ei!","Последним метким выстрелом из Зорчера, -лорд Снотфолус был изгнан в назад своё измерение. +Dar dacă o vor face, vei fi pregătit pentru ei!","Последним метким выстрелом из зорчера, +правитель Снотфолус был изгнан в назад своё измерение. Всем бедам вопреки, ты собственноручно покончил@[ao_rus] со вторжением! Остаётся лишь надеяться, что теперь флемоиды усвоят урок, и больше никогда не проникнут -в измерение Хлопьев. +в измерение хлопьев. Но если всё-таки проникнут, -ты уже будешь к этому готов@[ao_rus]!",,"Son bir patlamayla Lord +ты уже будешь к этому готов@[ao_rus]!",,"Med en sista smäll zorchar +du Lord Snotfolus tillbaka till +sin egen dimension! +Mot alla odds har du på egen +hand förhindrat invasionen! + +Du hoppas verkligen att +Flemoiderna äntligen har lärt sig +sin läxa och aldrig mer kommer +att återvända till +spannmålsdimensionen. + +Men om de gör det vet du att dukommer att vara redo för dem!","Son bir patlamayla Lord Snotfolus'u kendi boyutuna geri döndürüyorsunuz! Tüm olasılıklara rağmen @@ -845,6 +921,6 @@ umuyorsun. Ama dönerlerse, onlar için hazır olacağınızı biliyorsunuz!" -Rescue on Bazoik,M_EPI1,,,,Záchrana na Bazoiku,Redning på Bazoik,Rettung auf Bazoik,,Savo sur Bazojko,Rescate en Bazoik,,Pelastustehtävä Bazoikissa,Sauvetage sur Bazoik,Mentőakció a Bazoik-on,Salvataggio su Bazoik,バゾイクからのきゅうしゅつ,바조이크의 대동굴,Redding op Bazoik,Redning på Bazoik,Ratunek na Bazoik,Resgate em Bazoik,,Misiune de Salvare pe Bazoik,Спасение на Базоике,,Bazoik'te Kurtarma -Terror in Chex City,M_EPI2,,,,Hrůza v Chex City,Terror i Chex City,,,Teruro en Chex-Urbo,Terror en Chex City,,Kauhua Chex-kaupungissa,Terreur à Chex City,Terror Chexvárosban,Terrore a Chex City,チェックスシティーのきょうふ,첵스 시티의 공포,Terreur in Chex City,Terror i Chex City,Terror w Mieście Chex,Terror em Chexópolis,,Teroare în Orașul Chex,Террор в городе Chex,,Chex Şehrinde Terör -Invasion!,M_EPI3,,,,Invaze!,,,,Invado!,¡Invasión!,,Invaasio!,,Invázió!,Invasione!,しんにゅう!,대침공!,,Invasjon!,Inwazja,A Invasão!,,Invazie!,Вторжение!,,İstila! \ No newline at end of file +Rescue on Bazoik,M_EPI1,,,,Záchrana na Bazoiku,Redning på Bazoik,Rettung auf Bazoik,,Savo sur Bazojko,Rescate en Bazoik,,Pelastustehtävä Bazoikissa,Sauvetage sur Bazoik,Mentőakció a Bazoik-on,Salvataggio su Bazoik,バゾイクからのきゅうしゅつ,바조이크의 대동굴,Redding op Bazoik,Redning på Bazoik,Ratunek na Bazoik,Resgate em Bazoik,,Misiune de Salvare pe Bazoik,Спасение на Базоике,,Räddning på Bazoik,Bazoik'te Kurtarma +Terror in Chex City,M_EPI2,,,,Hrůza v Chex City,Terror i Chex City,,,Teruro en Chex-Urbo,Terror en Chex City,,Kauhua Chex-kaupungissa,Terreur à Chex City,Terror Chexvárosban,Terrore a Chex City,チェックスシティーのきょうふ,첵스 시티의 공포,Terreur in Chex City,Terror i Chex City,Terror w Mieście Chex,Terror em Chexópolis,,Teroare în Orașul Chex,Террор в городе Chex,,Terror i Chex City,Chex Şehrinde Terör +Invasion!,M_EPI3,,,,Invaze!,,,,Invado!,¡Invasión!,,Invaasio!,,Invázió!,Invasione!,しんにゅう!,대침공!,,Invasjon!,Inwazja,A Invasão!,,Invazie!,Вторжение!,,,İstila! \ No newline at end of file diff --git a/wadsrc_extra/static/filter/hacx.hacx1/after_iwad/language.csv b/wadsrc_extra/static/filter/hacx.hacx1/after_iwad/language.csv index 235cee56c5..e163f78850 100644 --- a/wadsrc_extra/static/filter/hacx.hacx1/after_iwad/language.csv +++ b/wadsrc_extra/static/filter/hacx.hacx1/after_iwad/language.csv @@ -1,122 +1,122 @@ -default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,tr -These bugs too tough for ya?,QUITMSG1,,,,Jsou ty bugy na tebe moc tvrdé?,Er disse bugs for hårde for dig?,Sind diese Bugs zu viel für dich?,,Ĉu ĉi tiuj cimoj estas tro forta por vi?,¿Son estos bichos demasiado duros para ti?,,Taitavat nämä ötökät olla liikaa sulle?,Ces bestioles sont trop fortes pour vous?,Túl erősek neked a bogarak is?,Questi errori sono troppo difficili per te?,テメェにはあんなバグ 厳しかないだろ?,고작 버그들 상대하는 것도 버거운 건가?,Zijn deze bugs te hard voor je?,Er disse insektene for tøffe for deg?,To robactwo jest za ciężkie dla ciebie?,"Tá achando difícil eliminar esses bugs, é?",,Sunt prea duri gândacii pentru tine?,Эти баги крутоваты для тебя?,,Bu böcekler senin için çok mu zor? +default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,sv,tr +These bugs too tough for ya?,QUITMSG1,,,,Jsou ty bugy na tebe moc tvrdé?,Er disse bugs for hårde for dig?,Sind diese Bugs zu viel für dich?,,Ĉu ĉi tiuj cimoj estas tro forta por vi?,¿Son estos bichos demasiado duros para ti?,,Taitavat nämä ötökät olla liikaa sulle?,Ces bestioles sont trop fortes pour vous?,Túl erősek neked a bogarak is?,Questi errori sono troppo difficili per te?,テメェにはあんなバグ 厳しかないだろ?,고작 버그들 상대하는 것도 버거운 건가?,Zijn deze bugs te hard voor je?,Er disse insektene for tøffe for deg?,To robactwo jest za twarde dla ciebie?,"Tá achando difícil eliminar esses bugs, é?",,Sunt prea duri gândacii pentru tine?,Эти баги крутоваты для тебя?,,Är dessa bugs för svåra för dig?,Bu böcekler senin için çok mu zor? Are you sure you want to\njack out of the action?,QUITMSG,,,,"Jsi si jistý, že se chceš zdáchnout z akce?","Er du sikker på, at du vil holdeop med at deltage?","Bist du sicher, dass du den\nStecker ziehen willst?",,"Ĉu vi certas, ke vi volas malkonektiĝi el la batalo?",¿Estás segur@[ao_esp] de que\nquieres desconectarte de la acción?,,Haluatko varmasti irrottaa\npiuhan toiminnasta?,Etes-vous sûr de vouloir\nvous déconnecter de l'action?,"Biztos vagy benne, hogy kihúzod a kábelt?",Sei sicuro di voler uscire?,もしかして逃げ出そうとしてないよな?,"지금 종료하겠다고? -진심이냐?",Weet je zeker dat je de actie wilt staken?,Er du sikker på at du vil trekke deg ut av handlingen?,Na pewo chcesz wyjść w środku akcji?,Tem certeza que quer se desconectar de toda a ação? ,,Ești sigur că vrei să\npărăsești acțiunea?,Ты правда хочешь улизнуть\nс поля боя?,,İşin dışında kalmak istediğine emin misin? -Trying to quit? And you call yourself a hacker?,QUITMSG2,,,,Snažíš se skončit? To si říkáš hacker?,Prøver du at holde op? Og du kalder dig selv en hacker?,Du willst gehen? Bist du wirklich ein Hacker?,,Vi provas rezigni? Kaj vi nomas vin kodrompisto?,¿Intentando salir? ¿Y te haces llamar hacker?,,Yritätkö lopettaa? Ja sinäkö muka hakkeri?,On essaye de quitter?\nvous prétendez être un hacker?,Próbálasz kilépni? És még te nevezed magad hekkernek?,Stai cercando di smettere?\nE ti definisci un hacker?,終了させる? それでハッカー自称してたのか?,그만두려고? 해커라는 이름이 아깝군그래.,Proberen te stoppen? En je noemt jezelf een hacker?,Prøver du å slutte? Og du kaller deg en hacker?,Próbujesz wyjść? I nazywasz siebie hakerem?,Tá querendo sair? E você ainda se acha um hacker?,,Încerci să ieși? Și te mai numești hacker?,Хочешь убежать? А ещё зовёшь себя хакером!,,Bırakmaya mı çalışıyorsun? Bir de kendine hacker mı diyorsun? +진심이냐?",Weet je zeker dat je de actie wilt staken?,Er du sikker på at du vil trekke deg ut av handlingen?,Na pewo chcesz wyjść w środku akcji?,Quer mesmo se desconectar de toda a ação? ,,Ești sigur că vrei să\npărăsești acțiunea?,Ты правда хочешь улизнуть\nс поля боя?,,Är du säker på att du inte vill vara med?,İşin dışında kalmak istediğine emin misin? +Trying to quit? And you call yourself a hacker?,QUITMSG2,,,,Snažíš se skončit? To si říkáš hacker?,Prøver du at holde op? Og du kalder dig selv en hacker?,Du willst gehen? Bist du wirklich ein Hacker?,,Vi provas rezigni? Kaj vi nomas vin kodrompisto?,¿Intentando salir? ¿Y te haces llamar hacker?,,Yritätkö lopettaa? Ja sinäkö muka hakkeri?,On essaye de quitter?\nvous prétendez être un hacker?,Próbálasz kilépni? És még te nevezed magad hekkernek?,Stai cercando di smettere?\nE ti definisci un hacker?,終了させる? それでハッカー自称してたのか?,그만두려고? 해커라는 이름이 아깝군그래.,Proberen te stoppen? En je noemt jezelf een hacker?,Prøver du å slutte? Og du kaller deg en hacker?,Próbujesz wyjść? I nazywasz siebie hakerem?,Tá querendo sair? E você ainda se acha um hacker?,,Încerci să ieși? Și te mai numești hacker?,Хочешь убежать? А ещё зовёшь себя хакером!,,Försöker du sluta? Och du kallar dig för hackare?,Bırakmaya mı çalışıyorsun? Bir de kendine hacker mı diyorsun? Get back here before I send a virus up your tailpipe!,QUITMSG3,,,,"Vrať se, než ti do zadku pošlu virus!","Kom tilbage, før jeg sender en virus op i dit udstødningsrør!","Komm zurück, oder ich schick dir 'nen Virus!",,"Revenu ĉi tien antaŭ ol mi sendos viruson en vian posttubon!","¡Vuelve aquí antes de que te meta un virus de través!","¡Vuelve antes de que te mande -un virus al tubo de escape!","Heti takaisin tänne, ennen kuin lähetän viruksen pitkin takaputkeasi!",Reviens ici avant que je t'envoie un virus là où ça fait mal!,"Gyere csak vissza, mielőtt feldugok neked egy vírust.",Torna indietro o ti\nmanderò un virus!,さっさと戻らねえと そのケツ穴にウィルスぶっこむぞ!,"돌아와, 네 전선에 바이러스 주입해버리기 전에!",Kom terug voordat ik een virus in je uitlaatpijp stuur!,Kom tilbake før jeg sender et virus opp eksosrøret ditt!,Wróć tu zanim wyślę ci wirusa!,Volta aqui antes que eu te mande um vírus!,,Treci înapoi aici până nu-ți trimit un virus!,"Вернись, пока я не посадил вирус тебе на хвост!",,Egzozuna bir virüs göndermeden önce buraya geri dön! +un virus al tubo de escape!","Heti takaisin tänne, ennen kuin lähetän viruksen pitkin takaputkeasi!",Reviens ici avant que je t'envoie un virus là où ça fait mal!,"Gyere csak vissza, mielőtt feldugok neked egy vírust.",Torna indietro o ti\nmanderò un virus!,さっさと戻らねえと そのケツ穴にウィルスぶっこむぞ!,"돌아와, 네 전선에 바이러스 주입해버리기 전에!",Kom terug voordat ik een virus in je uitlaatpijp stuur!,Kom tilbake før jeg sender et virus opp eksosrøret ditt!,Wróć tu zanim wyślę ci wirusa!,Volta aqui antes que eu te mande um vírus!,,Treci înapoi aici până nu-ți trimit un virus!,"Вернись, пока я не посадил вирус тебе на хвост!",,Kom tillbaka innan jag skickar ett virus upp i ditt avgasrör!,Egzozuna bir virüs göndermeden önce buraya geri dön! Real hackers never jack out of the action.,QUITMSG4,,,,Skuteční hackeři nikdy neprchají z akce.,Rigtige hackere går aldrig ud af spillet.,Echte Hacker geben nicht auf!,,"Veraj kodrompistoj neniam fuĝas el batalo.","Los verdaderos hackers no -se desconectan de la acción.",,Todelliset hakkerit eivät ikinä kytkeydy irti toiminnasta.,Un vrai hacker ne se déconnecte pas en pleine action.,Az igazi hekkerek sosem húzzák ki a kábelt.,I veri hacker non si arrendono!,本物のハッカーなら頭を銃で撃ち抜くことはしない。,진정한 해커는 이렇게 포기하지 않는다고!,Echte hackers komen nooit uit de actie.,Ekte hackere trekker seg aldri ut av kampen.,Prawdziwi hakerzy nigdy nie uciekają z akcji.,Hackers de verdade nunca vazam da ação!,,Adevărații hackeri nu fug de acțiune.,Настоящие хакеры не пытаются улизнуть с поля боя.,,Gerçek hackerlar asla aksiyondan kaçmazlar. +se desconectan de la acción.",,Todelliset hakkerit eivät ikinä kytkeydy irti toiminnasta.,Un vrai hacker ne se déconnecte pas en pleine action.,Az igazi hekkerek sosem húzzák ki a kábelt.,I veri hacker non si arrendono!,本物のハッカーなら頭を銃で撃ち抜くことはしない。,진정한 해커는 이렇게 포기하지 않는다고!,Echte hackers komen nooit uit de actie.,Ekte hackere trekker seg aldri ut av kampen.,Prawdziwi hakerzy nigdy nie uciekają z akcji.,Hackers de verdade nunca vazam da ação!,,Adevărații hackeri nu fug de acțiune.,Настоящие хакеры не пытаются улизнуть с поля боя.,,Riktiga hackare hoppar aldrig av.,Gerçek hackerlar asla aksiyondan kaçmazlar. C'mon! You haven't seen the best part yet!,QUITMSG5,,,,No tak! Ještě jsi neviděl to nejlepší!,Kom nu! Du har ikke set det bedste endnu!,Komm schon. Du hast das Beste noch gar nicht gesehen!,,"Nu! Vi ankoraŭ ne vidis la plej bonan parton!","¡Venga! ¡Aún no has visto la mejor parte!","¡Venga! ¡Aún no -viste la mejor parte!",Älä viitsi! Et ole edes vielä nähnyt parasta kohtaa!,"Allez, on arrive presque à la meilleure partie!",Nemár! Még nem is láttad a legjobb részt!,"Andiamo, forza! Non hai ancora\nvisto la parte migliore!",おいおい! お楽しみはこれからだぜ!,이봐! 아직 재밌는 부분은 시작도 안 했다고!,Kom op! Je hebt het beste deel nog niet gezien!,Kom igjen! Du har ikke sett det beste ennå!,No weź! Jeszcze nie widziałeś najlepszej części!,Qual é! Você nem viu a melhor parte ainda!,,Haide! Nu ai văzut partea cea mai bună încă!,"Да ладно, ты ещё не видел самое крутое!",,Hadi ama! Daha en iyi kısmını görmedin! +viste la mejor parte!",Älä viitsi! Et ole edes vielä nähnyt parasta kohtaa!,"Allez, on arrive presque à la meilleure partie!",Nemár! Még nem is láttad a legjobb részt!,"Andiamo, forza! Non hai ancora\nvisto la parte migliore!",おいおい! お楽しみはこれからだぜ!,이봐! 아직 재밌는 부분은 시작도 안 했다고!,Kom op! Je hebt het beste deel nog niet gezien!,Kom igjen! Du har ikke sett det beste ennå!,No weź! Jeszcze nie widziałeś najlepszej części!,Qual é! Você nem viu a melhor parte ainda!,,Haide! Nu ai văzut partea cea mai bună încă!,"Да ладно, ты ещё не видел самое крутое!",,Kom igen! Du har inte sett det bästa ännu!,Hadi ama! Daha en iyi kısmını görmedin! "Give up now, and cyberspace is toast!",QUITMSG6,,,,Vzdej se a s kyberprostorem je konec!,"Giv op nu, og cyberspace er ristet!",Wenn du jetzt aufgibst ist der Cyberspace am Ende.,,"Se vi rezignas nun, tiam Interret-spaco estos detruita!","¡Ríndete ahora y el ciberespacio -está frito!",,Luovuta nyt ja kyberavaruus kärtsää!,"Abandonne, et le cyberespace est foutu!","Ha most feladod, akkor a cyberspacenek lőttek.","Se ti arrendi ora,\nil cyberspazio è finito.",さっさと止めて、サイバースペースに乾杯だ!,포기하면 사이버 공간은 결국엔 사라질걸?,"Geef het nu op, en cyberspace is een toast!","Gi opp nå, og cyberspace er ferdig!","Poddaj się, a cyberprzestrzeń zmieni się w tosta!","Se você desistir agora, o ciberespaço já era!",,"Te dai bătut acum, și spațiul cibernetic e prăjit!","Если ты сейчас сдашься, киберпространству конец!",,"Şimdi pes edersen, siber uzay kızarır!" -"GENIE sends its best regards, scumbag!",QUITMSG7,,,,"GENIE posílá své pozdravy, hajzle!","GENIE sender dig sine bedste hilsner, skiderik!","GENIE sendet seine besten Grüße, Mistkerl!",,"ĜINIO sendas plej siajn konsiderojn, fiulo!","¡GENIE te envía saludos, desgraciado!",,"GENIE lähettää terveisensä, mäntti!","GENIE t'envoie ses salutations, salaud!","GENIE üdvözletét küldi, te mocsok!","GENIE ti manda i suoi\nmigliori saluti, bastardo!",GENIEがベストの挨拶を送るぜ、カス野郎!,어이 등신! 지니에서 안부를 전해 달라더군.,"GENIE doet je de groeten, klootzak!","GENIE sender sine beste hilsener, drittsekk!","GENIE przysyła pozdrowienia, łajzo!","GENIE manda lembranças, seu lixo!",,"GENIE își transmite condoleanțele, ticălosule!","Наилучшие пожелания от ДЖИННа, ублюдок!",,"GENIE selamlarını yolladı, pislik!" -"Hmm. So much for being a hero, Hacker.",QUITMSG8,,,,"Hmm. To by bylo pro hrdinství, Hackeře.","Hmm. Så meget for at være en helt, Hacker.","Hmm. So viel zum Thema ""Held"", Hacker.",,"Ĥaa. Kia domaĝo, ke vi estas hero, Kodrompisto.","Hmm. Poco tienes de héroe, hacker.",,"Höh, se siitä sankarina olemisesta sitten, hakkeri.","Eh bien, on est pas vraiment un héros, hacker.","Hmm. Ennyit a hős karrieredről, hekker barátom.","Hmm. E io che pensavo fossi un eroe, Hacker.",うーん。英雄とはこの程度だったのか、ハッカー。,영웅이 될 그릇은 아닌 거 같군. 안 그래? 해커 형씨.,"Hmm. Tot zover de held, Hacker.","Hmm. Så mye for å være en helt, Hacker.","Hmm. Tak wiele by być bohaterem, Hakerze.","Hmm. Não é tão herói assim, pelo visto.",,"Hmm. Asta a fost cu eroismele, Hacker.","Хм-м. Вот тебе и герой, хакер!",,"Hmm. Kahraman olmak için çok fazla, Hacker." -What? You'd rather go back to the pen?,QUITMSG9,,,,Co? Radši by ses vrátil do basy?,Hvad? Vil du hellere gå tilbage til fængslet?,Was? Du willst in den Knast zurück?,,"Kio? Ĉu vi preferas, ke vi revenu al la plumon?",¿Qué? ¿Prefieres volver al corral?,,Täh? Menisit mieluummin takaisin kynän ääreen?,Quoi? Tu préfère retourner dans ta cellule?,Hogy micsoda? inkább visszamennél a tolladhoz?,Cosa? Vuoi tornare in prigione?,何? 今更ペンで計算するのか?,펜이나 끄적거리는 인생으로 돌아가겠다. 이건가?,Wat? Ga je liever terug naar de pen?,Hva? Vil du heller tilbake til kasjotten?,Co? Wolisz wrócić do więzienia?,O quê? Prefere voltar pro xilindró?,,Ce? Vrei să te întorci la captivitate?,Что? Ты хочешь вернуться в неволю?,,Ne? Kalemine geri dönmeyi mi tercih ediyorsun? +está frito!",,Luovuta nyt ja kyberavaruus kärtsää!,"Abandonne, et le cyberespace est foutu!","Ha most feladod, akkor a cyberspacenek lőttek.","Se ti arrendi ora,\nil cyberspazio è finito.",さっさと止めて、サイバースペースに乾杯だ!,포기하면 사이버 공간은 결국엔 사라질걸?,"Geef het nu op, en cyberspace is een toast!","Gi opp nå, og cyberspace er ferdig!","Poddaj się, a cyberprzestrzeń zmieni się w tosta!","Se você desistir agora, o ciberespaço já era!",,"Te dai bătut acum, și spațiul cibernetic e prăjit!","Если ты сейчас сдашься, киберпространству конец!",,Om du ger upp nu är cyberrymden död!,"Şimdi pes edersen, siber uzay kızarır!" +"GENIE sends its best regards, scumbag!",QUITMSG7,,,,"GENIE posílá své pozdravy, hajzle!","GENIE sender dig sine bedste hilsner, skiderik!","GENIE sendet seine besten Grüße, Mistkerl!",,"ĜINIO sendas plej siajn konsiderojn, fiulo!","¡GENIE te envía saludos, desgraciado!",,"GENIE lähettää terveisensä, mäntti!","GENIE t'envoie ses salutations, salaud!","GENIE üdvözletét küldi, te mocsok!","GENIE ti manda i suoi\nmigliori saluti, bastardo!",GENIEがベストの挨拶を送るぜ、カス野郎!,어이 등신! 지니에서 안부를 전해 달라더군.,"GENIE doet je de groeten, klootzak!","GENIE sender sine beste hilsener, drittsekk!","GENIE przysyła pozdrowienia, łajzo!","GENIE manda lembranças, seu lixo!",,"GENIE își transmite condoleanțele, ticălosule!","Наилучшие пожелания от ДЖИННа, ублюдок!",,"GENIE skickar sina bästa hälsningar, skitstövel!","GENIE selamlarını yolladı, pislik!" +"Hmm. So much for being a hero, Hacker.",QUITMSG8,,,,"Hmm. To by bylo pro hrdinství, Hackeře.","Hmm. Så meget for at være en helt, Hacker.","Hmm. So viel zum Thema ""Held"", Hacker.",,"Ĥaa. Kia domaĝo, ke vi estas hero, Kodrompisto.","Hmm. Poco tienes de héroe, hacker.",,"Höh, se siitä sankarina olemisesta sitten, hakkeri.","Eh bien, on est pas vraiment un héros, hacker.","Hmm. Ennyit a hős karrieredről, hekker barátom.","Hmm. E io che pensavo fossi un eroe, Hacker.",うーん。英雄とはこの程度だったのか、ハッカー。,영웅이 될 그릇은 아닌 거 같군. 안 그래? 해커 형씨.,"Hmm. Tot zover de held, Hacker.","Hmm. Så mye for å være en helt, Hacker.","Hmm. Tak wiele by być bohaterem, Hakerze.","Hmm. Não é tão herói assim, pelo visto.",,"Hmm. Asta a fost cu eroismele, Hacker.","Хм-м. Вот тебе и герой, хакер!",,"Hmm. Så mycket för att vara en hjälte, Hacker.","Hmm. Kahraman olmak için çok fazla, Hacker." +What? You'd rather go back to the pen?,QUITMSG9,,,,Co? Radši by ses vrátil do basy?,Hvad? Vil du hellere gå tilbage til fængslet?,Was? Du willst in den Knast zurück?,,"Kio? Ĉu vi preferas, ke vi revenu al la plumon?",¿Qué? ¿Prefieres volver al corral?,,Täh? Menisit mieluummin takaisin kynän ääreen?,Quoi? Tu préfère retourner dans ta cellule?,Hogy micsoda? inkább visszamennél a tolladhoz?,Cosa? Vuoi tornare in prigione?,何? 今更ペンで計算するのか?,펜이나 끄적거리는 인생으로 돌아가겠다. 이건가?,Wat? Ga je liever terug naar de pen?,Hva? Vil du heller tilbake til kasjotten?,Co? Wolisz wrócić do więzienia?,O quê? Prefere voltar pro xilindró?,,Ce? Vrei să te întorci la captivitate?,Что? Ты хочешь вернуться в неволю?,,Vad? Vill du hellre gå tillbaka till pennan?,Ne? Kalemine geri dönmeyi mi tercih ediyorsun? Shoulda taken the blue pill.,QUITMSG10,,,,Měl sis vzít modrou pilulku.,Du skulle have taget den blå pille.,Du hättest die blaue Pille nehmen sollen...,,"Vi estus devinta preni -la bluan pilolon.",Deberías haber tomado la pastilla azul.,,Olis pitäny ottaa sininen pilleri.,T'aurais du prendre la pilule bleue.,Inkább a kék pirulát kellett volna választanod.,Avresti dovuto prendere la pillola blu ...,青いピルを採るべきではなかったな。,넌 파란 알약을 골랐어야 했어.,Je had de blauwe pil moeten nemen.,Skulle tatt den blå pillen.,Trzeba było wziąć niebieską pigułkę.,Devia ter tomado a pílula azul.,,Trebuia să iei pastila albastră.,Надо было принять синюю таблетку.,,Mavi hapı almalıydın. -The name of the game ain't Twitch n' Run!,QUITMSG11,,,,V názvu hry není napsané „uteč“!,"Spillets navn er ikke ""at flygte""!","Das Spiel heißt nicht ""wegrennen""!",,La nomo de la ludo ne estas Tiku kaj Kuru!,¡El nombre del juego no es Tirar a Correr!,,Pelin nimi ei oo Paniikkipako!,"Le jeu s'appelle pas ""Panique et cours!""",A játék neve nem Twitch n' Megfutamodás.,"Il gioco non significa ""scappare""!",ゲーム名は 萎え落ち小僧 じゃねえぞ!,"이봐, 이 게임은 때리고 도망가는 게임이 아니라고!",De naam van het spel is niet Twitch n' Run!,Navnet på spillet er ikke Twitch n' Run!,"Nazwą gry nie jest ""Drżyj i Uciekaj""!",O nome do jogo não é Trema nas Bases e Fuja!,,Numele jocului nu e Tremură și Ascunde-te!,Эта игра называется не «Дрожи и прячься»!,,Oyunun adı Twitch n' Run değil! -"No worries. Saving the world can wait, right?",QUITMSG12,,,,"Žádný problém. Záchrana světa může počkat, ne?","Det er ikke noget problem. At redde verden kan vente, ikke?","Also, die Welt zu retten kann warten, richtig?",,"Ne zorgu. Savi la mondon povas atendi, ĉu ne?","No te preocupes. Salvar el mundo puede esperar, ¿verdad?",,"Ei huolta; maailman pelastaminen voi odottaa, eikö niin?","Oh, pas de problème. Le monde peut attendre\nd'être sauvé, non?","Semmi pánik. A világmegmentés várhat, nemde?","Salvare il mondo può\naspettare, giusto?",気にはしない、世界を救うのは何時でも出来る、だろ?,걱정 말라고. 세상이 위험한데 급할 것 있나. 안 그래?,"Het redden van de wereld kan wachten, toch?","Slapp av. Å redde verden kan vente, ikke sant?","Bez obaw. Ratowanie świata może poczekać, prawda?","Sem problemas. O mundo pode esperar, não é mesmo?",,"Nicio problemă. Salvarea lumii poate aștepta, nu?","Не парься. Спасение мира подождёт, ведь так?",,"Endişelenme. Dünyayı kurtarmak bekleyebilir, değil mi?" -Guess it's time to make like the 'net and split!,QUITMSG13,,,,"Hádám, že je čas vypojit server!",Så er det vist på tide at gøre som nettet og smutte!,"Also ist es soweit, dass sich unsere Wege trennen.",,"Tempas, ke niaj vojoj agu kiel la reto kaj dividu.",¡Supongo que es hora de cortar con esta mala conexión!,,Kai sitten on aika katkaista palvelinyhteydet!,Ca doit être temps de partir comme une mauvaise connection!,Kettéváglak mint a netsplit a kapcsolatot.,Quindi è il momento per i\nnostri modi di separarsi.,ネット切断している暇は無いだろ!,벌써 서버를 다운시키는 '척' 할 시간인가?,Denk dat het tijd is om het te maken als het 'net en splitsen!,Det er vel på tide å gjøre som nettet og stikke!,"Wygląda na to, że trzeba się rozłączyć jak netsplit!","Acho que tá na hora de cair, que nem uma conexão ruim.",,Cred că e timpul de separare!,"Кажется, настало время устроить netsplit!",,Sanırım 'net gibi yapıp ayrılmanın zamanı geldi! -"Don't go off and forget about HacX, now!",QUITMSG14,,,,Ať tě nenapadne odejít a zapomenout na HacX!,Glem nu ikke HacX!,Bitte vergesse HacX nicht!,,Ne iru forgesi HacX nun!,¡Ahora no vayas y te olvides de Hacx!,,Älä nyt mene pois ja unohda HacX:ä!,Va pas oublier HacX maintenant!,"Ha elkalandozol, ne feletkezz meg a HacX-ről!","Non andartene e dimenticarti di HacX, ora!",HacXを忘れんじゃねえぞ、な!,부디 나가지 말고 HacX를 잊지 말아줘!,"Ga niet af en vergeet HacX niet, nu!","Ikke gå og glem HacX, nå!","Nie wyłączaj i nie zapominaj o HacX, teraz!","Não vai se esquecer do HacX, hein!",,Nu pleca și uita de HacX!,"Только посмей уйти и забыть про HacX, ты!",,"HacX'i unutup gitme, şimdi!" -%o deleted %hself from the universe.,OB_SUICIDE,,,,%o se smazal@[ao_cs] z vesmíru.,%o slettede sig selv fra universet.,%o entfernte sich aus dem Universum.,,%o forigis sin el la universo.,%o se borró a si mism@[ao_esp] del universo.,,%o poisti itsensä maailmankaikkeudesta.,%o s'est effacé@[e_fr] de l'univers.,%o kitörölte magát az univerzumból,%o si è cancellato dall'universo.,%o はこの宇宙から消滅した。,%o 은(는) 자기 자신의 존재를 소멸시켰다.,%o verwijderd zichzelf uit het universum.,%o slettet seg selv fra universet.,%o usun@[irreg_2_pl] się ze świata.,%o se deletou deste universo.,,%o s-a sters pe sine din univers.,Игрок %o стёр себя с лица вселенной.,,%o kendini evrenden sildi. -%o formed a crater the size of Kansas.,OB_FALLING,,,,%o utvořil@[ao_cs] kráter velikosti Kansasu.,%o dannede et krater på størrelse med Kansas.,%o wurde zu einem Krater in der Größe von Kansas.,,%o formis krateron grandan kiel Kansaso.,%o formó un cráter del tamaño de Kansas.,,%o muodosti Kansasin kokoisen kraaterin.,%o a formé un cratère de la taille du Kansas.,%o egy Kansas méretű krátert hagyott maga után.,%o ha formato un cratere delle dimensioni del Kansas.,%o はカンザス州程のクレーターを生成した。,%o 은(는) 땅바닥에 캔자스만큼 커다란 구멍을 뚫었다.,%o vormde een krater ter grootte van Kansas.,%o dannet et krater på størrelse med Kansas.,%o utworzył@[ao_pl] krater wielkości Kansas.,%o abriu uma cratera do tamanho do Kansas.,,%o a format un crater de dimensiunile statului Kansas.,На месте падения игрока %o образовался кратер размером с Канзас.,,%o Kansas büyüklüğünde bir krater oluşturdu. -%o became a human pancake.,OB_CRUSH,,,,%o se změnil@[ao_cs] v lidskou palačinku.,%o blev en menneskelig pandekage.,%o wurde zu einem menschlichen Pfannkuchen.,,%o Iĝis homa patkuko.,%o se convirtió en un crepe humano.,,%o tuli ihmispannukakun muotoiseksi.,%o est devenu@[e_fr] une crêpe.,%o palacsintává lapult,%o è diventato un pancake umano.,%o は人肉パンケーキになった。,%o 은(는) 인간 빈대떡이 되었다.,%o werd een menselijke pannenkoek.,%o ble en menneskelig pannekake.,%o stał@[ao_pl] się ludzkim plackiem.,%o virou uma panqueca humana.,,%o a devenit o clătită umană.,Игрока %o сплющило в лепешку.,,%o insan bir krep oldu. -%o tried to jack out.,OB_EXIT,,,,%o se pokusil@[ao_cs] prchnout.,%o forsøgte at stikke af.,%o hat sich ausgeloggt.,,%o provis malkonektiĝi.,%o intentó desconectarse.,,%o yritti irrottaa piuhan.,%o a tenté de se déconnecter.,%o ki akarta húzni a kábelét,%o è uscito.,%o は逃げ出そうとした。,%o 은(는) 로그아웃하려고 시도했다.,%o probeerde zich terug te trekken.,%o prøvde å jekke seg ut.,%o chciał@[ao_pl] się wydostać.,%o tentou se desconectar.,,%o a încercat să o taie.,Игрок %o хотел улизнуть.,,%o kaçmaya çalıştı. -%o swam like a brick.,OB_WATER,,,,%o uměl@[ao_cs] plavat jako cihla.,%o svømmede som en mursten.,%o schwamm wie ein Stein.,,%o naĝis kiel briko.,%o nadó como un ladrillo.,,%o ui kuin tiiliskivi.,%o nage comme une brique.,%o úgy úszik mint egy tégla.,%o nuotava come una pietra.,%o はカナヅチだった。,%o 은(는) 웹서핑을 못 하는 타입이었다.,%o zwom als een baksteen.,%o svømte som en murstein.,%o popłyn@[irreg_2_pl] jak cegła.,%o foi nadar como um tijolo.,,%o a înotat ca o cărămidă.,Игрок %o поплыл как топор.,,%o bir tuğla gibi yüzdü. -%o went nuclear.,OB_SLIME,,,,%o se rozpadl@[ao_cs] na atom.,%o blev nuklear.,%o wurde verstrahlt.,,%o iĝis nuklea,%o se volvió radioactiv@[ao_esp].,,%o kiinnostui ydinasioista.,%o s'est fait fissionner.,%o felrobbant mérgében.,%o è stato irradiato.,%o はニュークリアーと化した。,%o 은(는) 방사능 바람을 좀 쐬고 왔다.,%o werd nucleair.,%o ble nuklear.,%o został@[ao_pl] napromieniowan@[adj_pl].,%o ficou radioativ@[ao_ptb].,,%o a devenit radioactiv.,Игрок %o светится в темноте.,,%o nükleer oldu. -%o took a hot bath.,OB_LAVA,,,,%o si dal@[ao_cs] horkou koupel.,%o tog et varmt bad.,%o nahm ein heißes Bad.,,%o spertis varman banon.,%o tomó un baño caliente.,,%o otti kuuman kylvyn.,% o ha fatto un bagno caldo.,%o vett egy forró fürdőt.,%o ha fatto un bagno caldo.,%o は熱湯風呂に浸かった。,%o 은(는) 시원하게 용암 일광욕을 즐겼다.,%o nam een warm bad.,%o tok et varmt bad.,%o wzi@[irreg_2_pl] gorącą kąpiel.,%o tomou um banho bem quente.,,%o a făcut o baie fierbinte.,Игрок %o принял горячую ванну.,,%o sıcak bir banyo yaptı. -%o overdosed on nitro glycerine.,OB_BARREL,,,,%o se předávkoval@[ao_cs] nitroglycerinem.,%o fik en overdosis nitroglycerin.,%o nahm eine Überdosis Nitroglyzerin.,,%o trodozis nitroglicerinon.,%o tuvo una sobredosis de nitroglicerina.,,%o sai yliannostuksen nitroglyseriiniä.,%o a fait une overdose de nitroglycérine.,%o túladagolta a nitro-glicerint.,%o ha assunto un sovradosaggio di nitroglicerina.,%o はニトロを過剰摂取した。,%o 은(는) 니트로글리세린을 훅 가게 흡입했다.,%o overdosering op nitroglycerine.,%o tok en overdose nitroglyserin.,%o przedawkował@[ao_pl] nitroglicerynę.,%o overdosou em nitroglicerina.,,%o a luat o supradoză de nitroglicerină.,Игрок %o перебрал нитроглицерина.,,%o aşırı dozda nitro gliserin aldı. -%o is flayed into tiny little pieces.,OB_SPLASH,,,,%o byl@[ao_cs] sedřen@[ao_cs] na kousíčky.,%o er flået i småstykker.,%o wurde zerkleinert.,,%o estas senhaŭtiga en malgrandetaj pecoj.,%o es despellejad@[ao_esp] en trocitos pequeños.,,%o silpoutui riekaleiksi.,%o s'est fait éparpiller en petits morceaux.,%o ripityára szakadt szét.,%o è stato schiacciato.,%o は細かい粒をぶち撒けられた。,%o 은(는) 작은 입자로 분해되었다.,%o wordt gevild in kleine stukjes.,%o er flådd i bittesmå biter.,%o został@[ao_pl] roztrzaskan@[adj_pl] na małe kawałeczki.,%o foi detonad@[ao_ptb] em vários pedacinhos.,,%o s-a spart în mii de bucățele.,Игрока %o разодрали на мелкие клочки.,,%o küçük parçalara ayrıldı. -%o wanted to see what %g looked like inside-out.,OB_R_SPLASH,,,,"%o chtěl@[ao_cs] vědět, jak vypadá zevnitř.","%o ville se, hvordan han så ud indefra.",%o wollte @[pp_de] Innereien sehen.,,"%o volis vidi, kiel %g aspektus kun la interno ekstere.",%o quería ver que pinta tenía por dentro.,,%o halusi nähdä itsensä nurinperin.,%o voulait voir comment ses organes fonctionnent.,%o meg akarta tudni %g hogy néz ki belülről.,%o voleva vedere le sue interiora.,%o は %g が裏返しになるのを望んだ。,%o 은(는) 인체의 신비를 감상했다.,%o wilde zien hoe %g er binnenstebuiten uitzag.,%o ville se hvordan han så ut på innsiden.,%o chciał@[ao_pl] zobaczyć jak %g wygląda od środka.,%o queria ver como são os orgãos internos de %g.,,%o a vrut să vadă cum arăta %g întors pe dos.,"Игрок %o хотел посмотреть, что у него внутри.",,"%o, içinin dışının nasıl göründüğünü görmek istedi." -%o wanted to see what %g looked like inside-out.,OB_ROCKET,,,,"%o chtěl@[ao_cs] vědět, jak vypadá zevnitř.","%o ville se, hvordan han så ud indvfra.",%o wollte @[pp_de] Innereien sehen.,,"%o volis vidi, kiel %g aspektus kun la interno ekstere.",%o quería ver que pinta tenía por dentro.,,%o halusi nähdä itsensä nurinperin.,%o voulait voir comment ses organes fonctionnent.,%o meg akarta tudni %g hogy néz ki belülről.,%o voleva vedere le sue interiora.,%o は %g が裏返しになるのを望んだ。,%o 은(는) 퀀텀 여행을 즐겼다.,%o wilde zien hoe %g er binnenstebuiten uitzag.,%o ville se hvordan han så ut utenpå.,%o chciał@[ao_pl] zobaczyć jak %g wygląda od środka.,%o queria ver como são os orgãos internos de %g.,,%o a vrut să vadă cum arăta %g întors pe dos.,"Игрок %o хотел посмотреть, что у него внутри.",,%o içten dışa nasıl göründüğünü görmek istedi. -%o deleted %hself from the universe.,OB_KILLEDSELF,,,,%o se smazal@[ao_cs] z vesmíru.,%o slettede sig selv fra universet.,%o entfernte sich aus dem Universum.,,%o forigis sin el la universo.,%o se borró a si mism@[ao_esp] del universo.,,%o poisti itsensä maailmankaikkeudesta.,%o s'est effacé@[e_fr] de l'univers.,%o kitörölte magát az univerzumból,%o si è cancellato dall'universo.,%o はこの宇宙から消滅した。,%o 은(는) 자기 자신을 해킹했다.,%o schrapte zichzelf uit het universum.,%o slettet seg selv fra universet.,%o usun@[irreg_2_pl] się ze świata.,%o se deletou deste universo.,,%o s-a șters pe sine din univers.,Игрок %o стёр себя с лица вселенной.,,%o kendini evrenden sildi. -%o is no longer the dominant species.,OB_THUG,,,,%o už není vládnoucím živočichem.,%o er ikke længere den dominerende art.,%o ist nicht länger die dominante Spezies.,,%o ne estas la supera specio plu.,%o ya no es la especie dominante.,,%o ei ole enää vallitsevaa lajia.,%o n'est plus l'espèce dominante.,Már nem %o a csúcsragadozó.,%o non è più la specie dominante.,%o はもはや優性種ではなくなった。,%o 은(는) 그들의 시다바리가 아니였다.,%o is niet langer de dominante soort.,%o er ikke lenger den dominerende arten.,%o nie jest już dominującym gatunkiem.,%o não é mais a espécie dominante.,,%o nu mai e specia dominantă.,Игрок %o больше не доминантная форма жизни.,,%o artık baskın tür değil. -%o plugged in to the wrong machine.,OB_ANDROID,,,,%o se zapojil@[ao_cs] ke špatnému stroji.,%o har tilsluttet sig den forkerte maskine.,%o verband sich mit der falschen Maschine.,,%o konektiĝis en la eraran maŝinon.,%o se enchufó en la máquina equivocada.,,%o kytkeytyi väärään koneeseen.,%o s'est branché@[e_fr] à la mauvaise machine.,%o a rossz gépet dugta be.,%o connesso alla macchina sbagliata.,%o は違うマシンに接続してしまった。,%o 은(는) 잘못된 기계를 작동시켰다.,%o aangesloten op de verkeerde machine.,%o koblet seg til feil maskin.,%o podłączył@[ao_pl] się do złej maszyny.,%o se conectou na máquina errada.,,%o s-a conectat la mașina greșită.,Игрока %o подключили не к тому заряднику.,,%o yanlış makineye bağlandı. -%o got %hself a monster of a cyber-jockey-derriere-kicking.,OB_MONSTRUCT,,,,%o dostal@[ao_cs] šíleně kybernakopáno.,%o fik sig et monster af et cyber-jockey-derriere-spark.,%o bekam einen monströsen Cyber-Arschtritt verpasst.,,%o ricevis monstran cybernetik-raydist-postaĵ-piedbaton.,%o se ganó la madre de todas las patadas en el culo.,,%o sai hirviömäisen kyberlöylytyksen.,%o s'est fait@[e_fr] botter le cul de manière monumentale.,%o segge meg lett rugdosva.,% o ho avuto un mostruoso calcio cibernetico mancato.,%o は己に サイバー-ジョッキー-デリエレ-キッキング を取り入れた。,%o 은(는) 저 괴물의 슈퍼-울트라-캡쑝-파워를 맛봤다.,%o kreeg een monsterlijke cybertrap in @[zijn_haar_nl] kont.,%o fikk seg et monster av en cyber-jockey-derriere-sparking.,%o dostał@[ao_pl] cyber-kopa w dupę.,%o levou um cibercoice monstruoso nas fuças.,,%o s-a făcut praf în stil cibernetic.,Игрок %o получил поджопника от кибердиджея.,,%o kendine canavar gibi bir dayak attı. -%o got ICEd.,OB_ICE,,,,%o byl@[ao_cs] zmražen@[ao_cs] ICEm.,%o blev ICEd.,%o wurde verEISt.,,%o iĝis ICE-ita,%o fue ICEad@[ao_esp].,,%o raukkaa nyt varmaankin kICEmittää.,%o s'est fait@[e_fr] ICEr.,%o-t jégre tették.,% o è stato ghiacciato.,%o は冷えた。,%o 은(는) 지독하게 물어뜯겼다.,%o was IJS'd.,%o ble ICEd.,%o został@[ao_pl] zamrożon@[adj_pl].,%o foi peg@[ao_ptb] por um ICE. AI SE ferrou!,,%o a ÎNGHEȚat.,Игрок %o вляпался в ЛЁД.,,%o buzlandı. -%o feels a little buzzed.,OB_BUZZER,,,,%o dostal@[ao_cs] malou pecku.,%o føler sig lidt svimmel.,%o fühlt sich etwas gekitzelt.,,%o sentas sin iomete vibretita.,%o se siente algo zumbad@[ao_esp].,,%o raukan päässä hieman surisee.,%o sent le buzz.,%o-nak még mindig zúg a füle.,%o si sente solleticato un po '.,%o は少し賑やかになった。,%o 은(는) 짜릿하게 찔렸다.,%o voelt een beetje gezoemd.,%o føler seg litt beruset.,%o poczuł@[ao_pl] brzęczenie.,%o se sente meio chocad@[ao_ptb].,,%o se simte puțin șocat.,Игрок %o лёг спать в компании вертолётиков.,,%o biraz kafayı bulmuş gibi hissediyor. -%o uncovers a rather shocking development.,OB_STEALTH,,,,%o odhalil@[ao_cs] šokující informace.,%o opdager en temmelig chokerende udvikling.,%o machte eine schockierende Entdeckung.,,%o malkovras tre ŝokantan aferon.,%o descubre algo bastante chocante.,,%o raukalle paljastuu sangen sähköistävä uutinen.,%o a fait une découverte choquante.,"%o rájön, hogy az áram nem játék.",%o ha fatto una scoperta scioccante.,%o はかなり衝撃的な開発を発見した。,%o 은(는) 비밀리에 만들어진 병기를 발견했다.,%o ontdekt een nogal schokkende ontwikkeling.,%o avdekker en ganske sjokkerende utvikling.,%o odkrywa coś szokującego.,%o descobre uma revelação chocante.,,%o dezvăluie o schimbare șocantă.,Игрока %o встретил довольно серьёзный поворот событий.,,%o oldukça şok edici bir gelişmeyi ortaya çıkardı. -%o was erased from cyberspace.,OB_DMAN,,,,%o byl@[ao_cs] vymazán@[ao_cs] z kyberprostoru.,%o blev slettet fra cyberspace.,%o wurde aus dem Cyberspace gelöscht.,,%o estas viŝita el cyberspaco.,%o fue borrad@[ao_esp] del ciberespacio.,,%o poistettiin kyberavaruudesta.,%o s'est fait@[e_fr] effacer du cyberespace.,%o-t kitörölték a kibertérből.,%o è stato eliminato dal cyberspazio.,%o はサイバースペースに消去された。,%o 은(는) 영구차단을 당했다.,%o werd gewist uit cyberspace.,%o ble slettet fra cyberspace.,%o został@[ao_pl] usunięt@[adj_pl] z cyber przestrzeni.,%o foi deletad@[ao_ptb] do ciberespaço.,,%o a fost șters din spațiul cibernetic.,Игрока %o удалили из киберпространства.,,%o siber uzaydan silindi. -%o gave %hself a glass jaw.,OB_GLASS,,,,%o si přidělal@[ao_cs] skleněnou čelist.,%o gav sig selv en glaskæbe.,%o bekam ein Glaskinn.,,%o donis al si vitran makzelon.,%o se estampó contra un cristal.,,%o antoi itsellensä lasileuan.,%o s'est fait@[e_fr] vitrifier la figure.,%o állon vágta magát.,%o ha un mento di vetro.,%o は自身にグラスジョーを取り付けた。,%o 은(는) 유리창을 깨고 등장하는 액션 배우가 아니였다.,%o gaf zichzelf een glazen kaak.,%o ga seg selv en glasskjeve.,%o był@[ao_pl] zbyt delikatn@[adj_pl] ze szkłem.,%o tem um queixo de vidro.,,%o și-a făcut un maxilar de sticlă.,У игрока %o оказалась стеклянная челюсть.,,%o kendine cam çene taktı. -%o's life membership was terminated.,OB_MANIAC,,,,%o@[psn_cs] členství v klubu živých bylo přerušeno.,%os medlemskab på livstid blev opsagt.,%os Mitgliedschaft im Leben wurde beendet.,,La vivo-membrecon de %o estas finigita,%o tuvo su afiliación a la vida terminada.,,%o raukan elämänjäsenyys päätettiin.,L'abonnement à vie de %o est arrivé à sa fin.,%o elfelejtette befizetni az élők tagdíját.,L'appartenenza di %o alla vita è finita.,%o のメンバーシップ生活は終幕した。,%o 의 계정은 영원히 삭제되었다.,%o's levenslange lidmaatschap werd beëindigd.,%os livstidsmedlemskap ble avsluttet.,Członkowstwo %o w klubie żywych się skończyło.,%o não está mais afiliad@[ao_ptb] à vida.,,%o nu mai e membru al clubului celor vii.,Игрока %o исключили из клуба живых.,,%o hayata veda etti. -%o died in some random method I cannot fathom.,OB_MANIACHIT,,,,"%o umřel@[ao_cs] nějakým způsobem, který ani nemůžu pochopit.","%o døde på en eller anden tilfældig måde, som jeg ikke kan gennemskue.",%o starb auf eine unvorstellbare Art und Weise.,,"%o mortis per iu malcerta maniero, kiun mi ne povas kompreni.",%o murió de alguna manera que no llego a comprender.,,"%o kuoli jollakin sattumanvaraisella tavalla, jota en voi käsittää.",%o est mort@[e_fr] d'une manière que je n'arrive même pas à décrire.,Ötletem since hogy halt meg %o.,%o è morto in un modo inimmaginabile.,%o は計算外の乱数で死んだ。,%o 은(는) 의미불명의 이유로 잠수를 타게 되었다.,%o stierf op een of andere willekeurige manier die ik me niet kan voorstellen.,%o døde på en eller annen tilfeldig måte jeg ikke fatter.,"%o zgin@[irreg_2_pl] pod wpływem metody, której nie mogę pojąć.",%o morreu de alguma forma aleatória que nem consigo imaginar.,,%o a murit într-un mod aleatoriu pe care nu mi-l pot închipui.,Игрок %o внезапно умер по непостижимой для меня причине.,,%o anlayamadığım rastgele bir yöntemle öldü. -%o was fried by a femme fatale freak.,OB_TERMIN,,,,%o byl@[ao_cs] usmažen@[ao_cs] šílenou femme fatale.,%o blev stegt af en femme fatale freak.,%o wurde von einem Femme-Fatale Freak gebraten.,,%o estis fritita de femme-fatale-groteskulo.,%o fue tostad@[ao_esp] por una femme fatale.,,%o joutui kohtalokkaan kimman kärtsäämäksi.,%o s'est fait@[e_fr] frire par une femme fatale.,%o-t lebombázta egy bomba nő.,% o è stato fritto da una femme fatale.,%o はファム ファタル フリークに揚げられた。,%o 은(는) 미인계에 발을 들였다.,%o werd gebakken door een femme fatale freak.,%o ble stekt av en femme fatale-freak.,%o został@[ao_pl] usmażon@[adj_pl] przez szaloną femme fatale.,%o foi fritad@[ao_ptb] por uma femme fatale psicótica.,,%o a fost prăjit de către o femme fatale psihopată.,Игрока %o поджарила чокнутая роковая женщина.,,%o bir femme fatale ucubesi tarafından kızartıldı. -%o got a little close to the opposite sex.,OB_TERMINHIT,"This text is not gender neutral, obviously...",,,%o se moc přiblížil@[ao_cs] k opačnému pohlaví.,%o kom lidt tæt på det modsatte køn.,%o kam dem anderen Geschlecht zu nahe.,,%o iĝis iomete proksime al la mala sekso.,%o se acercó demasiado a la persona equivocada.,,%o meni hieman liian lähelle vastakkaista sukupuolta.,%o s'est trop rapproché@[e_fr] de la mauvaise personne.,%o túl közel került az ellenkező nemhez.,%o è arrivato troppo vicino all'altro sesso.,%o は少し異性に成り果てた。,%o 의 남자다운 자존심은 쪼그라들었다.,%o kwam een beetje in de buurt van het andere geslacht.,%o kom litt nær det motsatte kjønn.,%o pod@[irreg_1_pl] zbyt blisko do płci pięknej.,%o chegou perto demais do sexo oposto.,,%o s-a apropriat prea mult de sexul opus.,Игрок %o почти сблизился с противоположным полом.,,%o karşı cinsle biraz yakınlaştı. -%o said goodbye to an old friend.,OB_REPLI,,,,%o řekl@[ao_cs] sbohem starému příteli.,%o sagde farvel til en gammel ven.,%o verabschiedete sich von einem alten Freund.,,"%o diris ""Ĝis la revido"" al malnova amiko.",%o se despidió de un viejo amigo.,,%o sanoi hyvästit vanhalle ystävälle.,%o dit au revoir à un vieil ami.,%o búcsút intett egy régi barátjának.,%o ha detto addio a un vecchio amico.,%o は古い友人に別れを告げた。,%o 은(는) 오랜 친구와 작별인사를 했다.,%o nam afscheid van een oude vriendin.,%o tok farvel med en gammel venn.,%o pożegnał@[ao_pl] się ze starym znajomym.,%o disse adeus a um velho amigo.,,%o a spus adio unui vechi prieten.,Игрок %o распрощался со старым другом.,,%o eski bir arkadaşına veda etti. -%o was stabbed in the back by an old friend.,OB_REPLIHIT,,,,%o byl@[ao_cs] bodnuta do zad starým přítelem.,%o blev stukket i ryggen af en gammel ven.,%o wurde von einem alten Freund in den Rücken gestochen.,,%o estis pikita en la dorson de malnova amiko.,%o fue apuñalad@[ao_esp] en la espalda por un viejo amigo.,,%o joutui vanhan ystävän selkäänpuukottamaksi.,%o s'est fait@[e_fr] planter une lame dans le dos par un vieil ami.,%o-t hátba szúrta egy régi barát.,%o è stato pugnalato alla schiena da un vecchio amico.,%o は古い友人に背中を刺された。,%o 은(는) 오랜 친구에게 배신을 당했다.,%o werd in de rug gestoken door een oude vriend.,%o ble dolket i ryggen av en gammel venn.,%o został@[ao_pl] dźgnięt@[adj_pl] w plecy przez starego znajomego.,%o foi apunhalad@[ao_ptb] pelas costas por um velho amigo.,,%o a fost înjunghiat pe la spate de către un vechi prieten.,Игрок %o получил нож в спину от старого друга.,,%o eski bir arkadaşı tarafından sırtından bıçaklandı. -%o was weeded out by natural selection.,OB_PHAGE,,,,%o byl@[ao_cs] vyčištěna přirozeným výběrem.,%o blev sorteret fra ved naturlig udvælgelse.,%o fiel der natürlichen Auslese zum Opfer.,,%o estis foriga de natura elektado.,%o fue eliminad@[ao_esp] por selección natural.,,%o joutui luonnonvalinnan kitkemäksi.,%o a été éliminé@[e_fr] par la sélection naturelle.,A természetes kiválasztás áldozata lett %o.,%o cadde vittima della selezione naturale.,%o は自然淘汰によって除草された。,%o 은(는) 약육강식을 지금까진 모르고 있었다.,%o werd door natuurlijke selectie weggehaald.,%o ble luket ut av naturlig seleksjon.,%o został@[ao_pl] przesian@[adj_pl] przez naturalną selekcję.,%o foi eliminad@[ao_ptb] por seleção natural.,,%o a fost eliminat prin selecție naturală.,Игрок %o был отсеян естественным отбором.,,%o doğal seleksiyon tarafından ayıklandı. -%o couldn't escape a thorny death.,OB_THORN,,,,%o nemohl@[ao_cs] utéct bodlavé smrti.,%o kunne ikke undslippe en tornedød.,%o konnte einem dornigen Tod nicht entkommen.,,%o ne povis eskapi dornan morton.,%o no pudo escapar una muerte espinosa.,,%o ei kyennyt välttämään piikikästä kuolemaa.,%o n'a pu éviter une mort piquante.,Lyukasra szúrták %o-t a tövisek.,%o non poteva sfuggire a una morte spinosa.,%o は棘のある死から逃げられなかった。,%o 은(는) 따가운 죽음을 피할 수 없었다.,%o kon niet ontsnappen aan een netelige dood.,%o kunne ikke unnslippe en tornefull død.,%o nie m@[irreg_4_pl] uciec przed cierniową śmiercią.,%o não conseguiu escapar de uma morte espinhosa.,,%o nu a putut scăpa de o moarte spinoasă.,Игрока %o поджидала смерть на его тернистом пути.,,%o dikenli bir ölümden kaçamadı. -%o took a sumo punch to the groin.,OB_SUMATIC,,,,%o dostal@[ao_cs] sumo ránu pod pás.,%o fik et sumo-slag i lysken.,%o bekam einen Sumo-Schlag an @[pp_de] empfindlichste Stelle.,,%o prenis sumoan baton en la ingveno.,%o recibió un puñetazo de sumo en la entrepierna.,,%o otti vastaan sumoiskun nivusiin.,%o s'est pris le poing d'un sumo dans l'entrejambe.,%o szerszámjával tompította az jobb horgot.,%o ha ricevuto un soffio su un punto sensibile.,%o は股座にスモウ ハリテを食らった。,%o 은(는) 가랑이 사이에 정권을 찔렀다.,%o nam een sumo punch in de lies.,%o fikk et sumoslag i skrittet.,%o dostał@[ao_pl] cios sumo w pachwinę.,%o tomou um golpe de sumô na virilha.,,%o a primit un pumn sumo în vintre.,Игрок %o отхватил удар в пах от сумоиста.,,%o kasıklarına bir sumo yumruğu yedi. -%o didn't get %p three wishes.,OB_GENIE,,,,%o nedostal@[ao_cs] svá tři přání.,%o fik ikke sine tre ønsker.,%o bekam @[pp_de] drei Wünsche nicht erfüllt.,,%o ne ricevis siajn tri petojn.,%o no recibió sus tres deseos.,,%o ei saanut kolmea toivettaan.,%o n'a pas préparé ses trois vœux.,%o nem teljesítette %p 3 kívánságát.,%o non ha soddisfatto i suoi tre desideri.,%o は %p に三願を望まなかった。,%o 은(는) 세 가지 소원을 빌 수 없었다.,%o kreeg niet drie wensen.,%o fikk ikke oppfylt tre ønsker.,%o nie dostał@[ao_pl] swoich trzech życzeń.,%o não concedeu três desejos a %p.,,%o nu a putut să-și pună cele trei dorințe.,Игрок %o не загадает трёх желаний.,,%o üç dileğini yerine getiremedi. -%o tried to pet a mine.,OB_MINE,,,,%o se pokusil@[ao_cs] pohladit minu.,%o forsøgte at kæle for en mine.,"%o versuchte, eine Mine zu streicheln.",,%o provis glatumi minon.,%o intentó acariciar una mina.,,%o yritti silittää miinaa.,%o a essayé de caresser une mine.,%o meg akart simogatni egy aranyos aknát.,%o ha provato ad accarezzare una mina.,%o は地雷を愛撫しようとした。,%o 은(는) 기뢰와 친구가 되고 싶었다.,%o probeerde een mijn te aaien.,%o prøvde å klappe en mine.,%o próbował@[ao_pl] pogłaskać minę.,%o tentou fazer carinho numa mina.,,%o a încercat să mângâie o mină.,Игрок %o хотел погладить мину.,,%o bir mayını sevmeye çalıştı. -%o took %k's Bruce Lee fu-kick to the face.,OB_MPKICK,,,,%o dostal@[ao_cs] kopanec do obličeje od kung-fuistou %k.,%o fik %ks Bruce Lee fu-kick i ansigtet.,%o bekam einen Bruce-Lee-Fußtritt ins Gesicht.,,%o ricevis la Bruce Lee piedbaton de %k en sia vizaĝo.,%o se comió una patada de kung-fu a lo Bruce Lee de %k.,,%k potkaisi %o raukkaa päin naamaa Bruce Leen kung fu-tyyliin.,%o s'est mangé@[e_fr] un coup de pied à la Bruce Lee de la part de %k.,%o arccal vette le %k pörgőrugását.,%o ha un calcio in faccia.,%o の顔に %k のブルースリーキックを当てた。,%o 은(는) %k 의 거침없는 하이킥을 받았다.,%o nam %k's Bruce Lee fu-kick in het gezicht.,%o tok %ks Bruce Lee fu-kick i ansiktet.,%o dostał@[ao_pl] kopniakiem w stylu Bruce'a Lee od %k.,%o tomou uma voadora de %k na cara.,,%o a primit un șut în stil Bruce Lee.,"Игрок %o отхватил от игрока %k удар в лицо, достойный Брюса Ли.",,"%o, %k tarafından tekmelendi." -%o fell apart via %k's shocking revelation.,OB_MPREZNATOR,,,,%o se rozpadl@[ao_cs] šokujícím odhalením hráče %k.,%o faldt fra hinanden via %ks chokerende åbenbaring.,%o erhielt eine schockierende Enthüllung von %k.,,%o diseriĝis pro la ŝokantan revelaĉio de %k.,%o cayó ante la revelación chocante de %k.,,%o romahti käyttäjän %k sähköistävästä ilmestyksestä.,%o a été témoin de la révélation choquante de %k.,%k megrázó élmányben részesítette %o-t.,%o ricevette una scioccante rivelazione da %k.,%o は %k の衝撃的な啓示によりバラバラになった。,%o 은(는) %k 이(가) 선사한 전기 찜질을 맛봤다.,%o viel uit elkaar via %k's schokkende onthulling.,%o falt fra hverandre via %ks sjokkerende åpenbaring.,%o rozpadł@[ao_pl] się pod wpływem szokującego objawienia %k.,%o ficou arrasad@[ao_ptb] pela revelação chocante de %p.,,%o s-a făcut praf la revelația șocantă a lui %k.,Игрок %o шокирован откровениями %k.,,"%o, %k tarafından kızartıldı." -%o took a double-dose of %k's punishment.,OB_MPXPISTOL,,,,%o dostal@[ao_cs] dvojitou dávku potrestání hráče %k.,%o fik en dobbeltdosis af %ks straf.,%o bekam eine doppelte Dosis von %ks Bestrafung.,,%o duoble dozis la puno de %k.,%o recibió una doble dosis del castigo de %k.,,%o otti tupla-annoksen käyttäjän %k kuritusta.,%o a mangé une double dose de la furie de %k.,%o ólom túladagolást kapott %k-tól.,%o ha ottenuto una doppia dose della punizione di %k.,%o は %k の懲罰を二度受けた。,%o 은(는) %k 의 2총신 사격을 받았다.,%o nam een dubbele dosis van %k's straf.,%o tok en dobbel dose av %ks straff.,%o dostał@[ao_pl] podwójną dawkę kary %k.,%o tomou uma dose dupla da punição de %k.,,%o a luat o doză dublă din pedeapsa lui %k.,Игрок %o принял двойную дозу возмездия от %k.,,"%o, %k tarafından cezalandırıldı." -%o was shut down by %k's shock-stick.,OB_MPTAZER,,,,%o byl@[ao_cs] vypnut@[ao_cs] šokádou hráče %k.,%o blev lukket ned af %ks chok-stick.,%o wurde von %ks Schockstab ausgeschaltet.,,%o estis malŝaltita de la ŝokbateno de %k.,%o fue noquead@[ao_esp] por la vara eléctrica de %k.,,%o joutui käyttäjän %k sähkökepin sammuttamaksi.,%o s'est fait mettre K.O par le bâton électrique de %k.,"%o-t sokkolta a hír, hogy %k-t megölte.",%o è stato spento dalla bacchetta di %k.,%o は %k のショックスティックでシャットダウンした。,%o 은(는) %k 의 무력행사에 아예 포기했다.,%o werd uitgeschakeld door %k's schokstick.,%o ble stengt av %ks sjokkpinne.,%o został@[ao_pl] wyłączon@[adj_pl] przez szokującą pałkę %k.,%o foi desligado pelo espeto chocante de %k.,,%o a fost dezactivat de arma cu șocuri a lui %k.,Игрок %o выведен из строя электродубинкой %k.,,"%o, %k tarafından kapatıldı." -%o got a face-full of %k's ice-cold wrath.,OB_MPCRYOGUN,,,,%o se zabořil@[ao_cs] do mrazivého hněvu hráče %k.,%o fik et ansigt fuld af %ks iskolde vrede.,%o bekam eine Ladung von %ks eiskaltem Zorn ins Gesicht.,,%o ricevis la glacie malvarman koleregon de %k.,%o recibió la ira gélida de %k en toda la cara.,,%o sai saamansa täyteen käyttäjän %k jääkylmää vihaa.,%o s'est fait congeler la figure par la colère glaciale de %k.,%k jégre tette %o-t,%o ha un carico di freddo gelido di %k in faccia.,%o は %k の冷めた表情で凍った。,%o 은(는) %k 덕분에 맛있게 냉동 보존되었다.,%o kreeg een gezicht vol met %k's ijskoude toorn.,%o fikk ansiktet fullt av %ks iskalde vrede.,%o dostał@[ao_pl] wielką dawkę mroźnego gniewu %k.,%o tomou um gelo de %k. ,,%o a simțit din plin furia rece a lui %k.,Игрок %o столкнулся с ледяной ненавистью %k.,,"%o, %k tarafından donduruldu." -"%o was drilled full of holes by %k, gangsta-style.",OB_MPUZI,,,,%o byl@[ao_cs] prostřílen@[ao_cs] skrz na skrz gangsterem %k.,"%o blev boret fuld af huller af %k, på gangsta-stil.",%o wurde von %k im Gangsta-Stil perforiert.,,"%o estis borita truplena de %k, ganstere.","%o fue acribillad@[ao_esp] por %k, al estilo gangster.",,%k porasi %o raukan täyteen reikiä gangsta-tyyliin.,"%o s'est fait perforer dans tous les sens par %k, Gangsta style.",%o gengszter stílusban sajttá lyuggatta %k,%o è stato perforato da %k in stile gangsta.,%o はギャングの様な %k に蜂の巣にされた。,%o 은(는) %k 이(가) 선사한 갱스터 스타일 난사를 막지 못했다.,"%o werd vol gaten geboord met %k, in gangsta-stijl.","%o ble boret full av hull av %k, i gangsta-stil.",%o został@[ao_pl] podziurawion@[adj_pl] przez %k niczym gangster.,%o tomou pipoco de %k.,,%o a fost umplut de găuri în stil mafiot de către %k.,Игрок %o покрылся дырками после гангста-стрельбы игрока %k.,,"%o, %k tarafından gangsta tarzı delik deşik edildi." -%o ate %k's photon bomb.,OB_MPZOOKA,,,,%o sežral@[ao_cs] fotonovou bombu hráče %k.,%o spiste %ks fotobombe.,%o nahm %ks Photonenbombe.,,%o manĝis la fotonbombon de %k.,%o se comió la bomba de fotones de %k.,,%o söi käyttäjän %k fotonipommin.,%o a bouffé la bombe photonique de %k.,%o megette %k foton bombáját,%o ha preso la bomba fotonica di %k.,%o は %k のフォトンボムを食らった。,%o 은(는) %k 의 광자탄을 봤는데도 피하지 못했다.,%o at %o %k's fotonbom.,%o spiste %ks fotonbombe.,%o zjadł@[ao_pl] fotonową bombę %k.,%o engoliu a bomba de fótons de %k.,,%o a mâncat bomba fotonică a lui %k.,Игрок %o съел фотонную бомбу %k.,,"%o, %k tarafından atomize edildi." -%o was reduced to a neat pile of photons by %k.,OB_MPZ_SPLASH,,,,%o byl@[ao_cs] zredukován@[ao_cs] na hromádku fotonů hráčem %k.,%o blev reduceret til en ordentlig bunke fotoner af %k.,%o wurde von %k zu einem Haufen Photonen verarbeitet.,,%o estis reduktita en ordeman amason da fotonoj de %k.,%o fue reducid@[ao_esp] a una pila de fotones por %k.,,%k redusoi %o raukan sieväksi fotonipinoksi.,%o s'est fait@[e_fr] réduire en une jolie pile de photons par %k.,%o-ból csak egy marokni fotont hagyott hátra %k,%o è stato elaborato da %k in un mucchio di fotoni.,%o は %k によって蛍光灯にされた。,%o 은(는) %k 의 광자력을 탐냈다. 죽기 전까지는.,%o werd gereduceerd tot een nette stapel fotonen met %k.,%o ble redusert til en pen haug med fotoner av %k.,%o został@[ao_pl] zredukowan@[adj_pl] do maleńkiej kupki fotonów przez %k.,%o foi reduzido à uma bela pilha de fótons por %k.,,%o a fost transformat într-o grămadă simpatică de fotoni de către %k.,Игрок %o был разложен игроком %k в аккуратную кучку фотонов.,,"%o, %k tarafından düzgün bir foton yığınına indirgendi." -%o was reduced to antimatter by %k.,OB_MPANTIGUN,"Physically this is utter nonsense, of course.",,,%o byl@[ao_cs] zredukován@[ao_cs] na antihmotu hráčem %k.,%o blev reduceret til antimaterie af %k.,%o wurde von %k zu Antimaterie reduziert.,,%o estis reduktita en antimaterion de %k.,%o fue reducid@[ao_esp] a antimateria por %k.,,%k redusoi %o raukan antimateriaksi..,%o s'est fait inverser les atomes par %k.,%k antianyaggá lőttte %o-t,%o è stato ridotto all'antimateria da %k,%o は %k のにより反物質に変換された。,%o 은(는) %k 의 반물질의 힘에 의해 소멸되었다.,%o werd gereduceerd tot antimaterie met %k.,%o ble redusert til antimaterie av %k.,%o został@[ao_pl] zredukowan@[adj_pl] do antymaterii przez %k.,%o foi transformado em antimatéria por %k.,,%o a fost transformat în antimaterie de către %k.,Игрок %o был разложен игроком %k до антиматерии.,,"%o, %k tarafından atomlara indirgendi." -%o swallowed %k's nuke.,OB_MPNUKE,,,,%o spolkl@[ao_cs] atomovku hráče %k.,%o slugte %ks atombombe.,%o verschluckte sich an %ks Atomrakete.,,%o glutis la nuklean bombon de %k.,%o se tragó la bomba atómica de %k.,,%o nieli käyttäjän %k ydinpommin.,%o s'est pris@[e_fr] la bombe thermonucléaire de %k dans la figure.,%o megette %k atombomáját,%o soffocò sul missile nucleare di %k.,%o は %k の核を飲み干した。,%o 은(는) %k 덕분에 하늘을 뚫을 버섯구름이 되었다.,%o geslikt %o nuke %k's nuke.,%o svelget %ks atombombe.,%o połkn@[irreg_2_pl] atomówkę %k.,%o engoliu o míssil núclear de %k.,,%o a înghițit proiectilul lui %k.,Игрок %o проглотил ядерный заряд %k.,,"%o, %k tarafından bombalandı." -%o went nuclear from %k's mass destruction spree.,OB_MPNUKESPLASH,,,,%o si zkrátil@[ao_cs] svůj poločas rozpadu při zabijačce hráče %k.,%o blev atomvåben af %ks masseødelæggelser.,%o wurde von %ks Massenzerstörungsaktion verstrahlt.,,%o iĝis nuklea pro la amasdetruado de %k.,%o se volvió radioactiv@[ao_esp] por la racha de destrucción masiva de %k.,,%o muuttui radioaktiiviseksi käyttäjän %k massatuhoputken takia.,%o s'est fait@[e_fr] irradier par la folie destructrice de %k.,%o felrobbant az idegtől amikor meglátta %k bombáját,%o fu irradiato dall'azione di distruzione di massa di %k.,%o は %k の虐殺ごっこの犠牲者になった。,%o 은(는) %k 의 핵실험에 참여했다.,%o werd nucleair van de massavernietigingswoede van %k's massavernietigingswoede.,%o ble nuklear av %ks masseødeleggelse.,%o został@[ao_pl] napromieniowan@[adj_pl] przez masową destrukcję %k.,%o virou picadinho radioativo por causa da destruição em massa causada por %k.,,%o a devenit radioactiv în urma distrugerii în masă a lui %k.,Игрок %o светится в темноте от оружия массового поражения %k.,,"%o, %k tarafından bombalandı." -%o was turned inside-out by %k.,OB_MPTELEFRAG,,,,%o byl@[ao_cs] obrácen@[ao_cs] naruby hráčem %k.,%o blev vendt ud og ind af %k.,%o wurde von %k zerfetzt.,,La interno de %o estis eksteriga de %k.,%o fue puest@[ao_esp] del revés por %k.,,%k käänsi %o raukan nurinpäin.,%o s'est fait@[e_fr] inverser par %k.,%k kifordította %o-t,%o fu fatto a pezzi da %k,%o は %k に裏返しにされた。,%o 은(는) %k 에 의해 자신이 분해되는 꼴을 못 봤다.,%o werd binnenstebuiten gekeerd met %k.,%o ble snudd på hodet av %k.,%o został@[ao_pl] wywrócon@[adj_pl] na lewą stronę przez %k.,%o foi virad@[ao_ptb] ao avesso por %k.,,%o a fost întors pe dos de către %k.,Игрок %o вывернут наизнанку игроком %k.,,"%o, %k tarafından parçalandı." -%o's atomic structure was split apart.,OB_MONTELEFRAG,,,,Struktura atomů hráče %o se rozpadla.,%os atomstruktur blev splittet op.,%os Atomstruktur wurde vernichtet.,,La atoma strukturo de %o estis disfendita.,%o fue desintegrad@[ao_esp] al nivel atómico.,,%o raukan atomirakenne hajosi.,%o s'est fait@[e_fr] désassembler au niveau atomique.,%o atomjaira esett szét,La struttura atomica di %o fu distrutta.,%o の原子構造は分解された。,%o 의 원자 마디마디가 흩어졌다.,De atoomstructuur van %o werd gesplitst.,%o's atomstruktur ble splittet fra hverandre.,Atomy %o zostały od siebie oddzielone.,A estrutura atômica de %o foi separada.,,Structura atomică a lui %o a fost spulberată.,Атомная структура игрока %o разрушена.,,%o atomik düzeyde parçalara ayrıldı. -%o spontaneously expired.,OB_DEFAULT,,,,%o samovolně vypršel@[ao_cs].,%o udåndede spontant.,%o hörte spontan auf zu existieren.,,%o spontane finiĝis.,%o tuvo una muerte espontánea.,,%o spontaanisti kupsahti.,%o a spontanément expiré.,%o hirtelenjében elérte a lejárati időt,%o ha smesso spontaneamente di esistere.,%o の有効期限が自発的に切れた,%o 은(는) 파란만장하게 사라졌다.,%o is spontaan verlopen.,%o gikk spontant til grunne.,%o spontanicznie umarł@[ao_pl].,%o pereceu expontâneamente.,,%o a expirat în mod spontan.,Время игрока %o неожиданно вышло.,,%o kendiliğinden öldü. -You grab a NUKER! Suck on this!,GOTNUKER,,,,Sebral@[ao_cs] jsi ATOMOVKÁTOR! Pojď na to!,Du tager en NUKER! Sut på den!,Ein NUKER! Verschluck dich daran.,,Vi prenis NUKER! Jen havu!,¡Has pillado un NUKER! ¡Chupaos esa!,¡Has recogido un NUKER! ¡Chúpate esa!,%Kahmaiset YDÄRIN! Ime tätä!,Vous découvrez le NUKER! Ca va en chier!,Meglelted a NUKER-t! Ezt kapd ki!,Prendi un NUKER! Succhia su questo!,NUEKR を奪った! 覚悟しろ!,누커 획득! 한바탕 쓸어볼까!,Je pakt een NUKER! Zuig hier maar aan!,Ta en NUKER! Sug på denne!,Podniosłeś ATOMÓWKĘ! Ssijcie to!,Você pegou um NUKER! Chupa essa manga!,,Ai ridicat Lansatorul Nuclear! Ia de-aici!,Заполучен ЯДЕРНЫЙ ГРАНАТОМЁТ! Отсосите!,,Sen bir NÜKER kap! Bunu em! -You got an UZI!!,GOTUZI,,,,Získal@[ao_cs] jsi UZI!,Du har en UZI!!,UZI genommen!,,Vi prenis UZI!!,¡¡Has obtenido una UZI!!,,Sait UZIn!!,Vous chopez un UZI!,Meglelted az UZI-t!,Hai un UZI !!,UZI をゲットした!!,우지 기관단총 획득!,Je hebt een UZI!!,Du har en UZI!,Zdobyłeś UZI!!,Você pegou uma UZI!!,,Ai ridicat un UZI!!,Заполучен УЗИ!!,,Bir UZI'n var! -A HOIG Reznator - FRY some butt,GOTREZNATOR,,,,HOIG Reznátor - pár jich upeč,En HOIG Reznator - Fritér noget røv,Ein HOIG Reznator.,,HOIG-Reznilo - FRITU pugon!,Un Reznator HOIG. ¡Hora de freir traseros!,,HOIG-reznaattori - KÄRISTÄ takamuksia,"Un Reznator HOIG, allez frire du monde!",Egy HOIG Reznator - okozz pár megrázó élményt,Un Reignator HOIG - friggere un po 'di carne,HOIGレジネイター - ぶっ潰してやれ,HOIG 전자무력기 획득! 전기 통구이를 만들자고!,Een HOIG Reznator - FRY sommige kont,En HOIG Reznator - FRY litt rumpe!,Reznator HOIG - skop trochę tyłków,Um Reznador HOIG - Hora de fritar,,Un Rezonator HOIG - Arde-i!,ХОЙГ Резнатор,,Bir HOIG Reznator - Biraz kıç kızartın -You got a Photon 'Zooka!,GOTPHOTONZOOKA,,,,Sebral@[ao_cs] jsi Fotonovou bazuku!,Du har en Photon 'Zooka!,Photonen-'zooka genommen!,,Vi prenis Fotonbazukon!,¡Has obtenido un Bazooka de Fotones!,,Sait fotonisingon!,Vous récupérez un Bazooka Photonique!,Meglelted a Foton Ágyút!,Hai un cannone Photon!,フォトン'ゾーカ をゲットした!,광자 바주카 획득!,Je hebt een Photon 'Zooka!,Du har en Photon 'Zooka!,Zdobyłeś Fotonozukę!,Você pegou uma Bazuca de Fótons!,,Ai ridicat o Bazooka Fotonică!,Заполучена фотон-базука!,,Bir Foton 'Zooka'n var! -You carry a Big Stick!,GOTBIGSTICK,,,,Nosíš velkou bouchačku!,Du har en Big Stick!,Du trägst einen langen Stock.,,Vi portas grandan bastonon!,¡Llevas un Gran Palo!,,Kannat isoa keppiä!,Vous avez un gros bâton!,Nagy bottal jársz öcsém!,Porti un grosso bastone!,ビッグスティック を手に取った!,반물질 봉 획득!,Je draagt een Big Stick!,Du har en Big Stick!,Podnosisz Wielką Pałkę!,Você pegou um Grande Bastão!,,Ai ridicat un Băț Lung!,Заполучена длинная палка!,,Büyük bir sopa taşıyorsun! -You got a Tazer!!,GOTTAZER,,,,Získal@[ao_cs] jsi tazer!,Du har en Tazer!!,Tazer genommen!,,Vi prenis Elektropafilon!!,¡¡Has obtenido un Taser!!,,Sait etälamauttimen!!,Vous trouvez un Taser!,Meglelted a Sokkolót!,Hai un Taser !!,テイザー をゲットした!,테이져 획득!,Je hebt een Tazer!!,Du har en Tazer!,Zdobyłeś Tazer!!,Você pegou um Tazer!!,,Ai ridicat un Taser!!,Заполучен тазер!,,Bir Tazer'ın var!! -You grab a Cryogun! FREEZE!,GOTCRYOGUN,,,,Sebral@[ao_cs] jsi krypušku! ANI SE NEHNI!,Du har en Cryogun! Frys!,Cryowaffe genommen! GEFRIER!,,Vi prenis Kriogenikpafilon! FROSTIĜU!,¡Has pillado un Criogenizador!! ¡Todos quietos!,¡Has recogido un Criogenizador!! ¡Quietos todos!,Kahmaiset kryopyssyn! PYSÄHDY!,Vous prenez un Cryogun! On s'arrête!,Felkapod a Cryogun-t! Induljon a fagyasztás!,Prendi un Cryogun! CONGELARE!,クライォガン を奪った! フリーズ!,크라이로건 획득! 그대로 멈춰라!,Je pakt een Cryogun! FREEZE!,Du har en Cryogun! FREEZE!,Podniosłeś Zamrażarkę! STAĆ!,Você pegou uma Cryogun! FICA FRIO AÍ!,,Ai ridicat o Crio-armă! ÎNGHEAȚĂ!,Заполучена замораживающая пушка! НИ С МЕСТА!,,Bir Cryogun al! DONDUR! -You grab some rounds!,GOTROUNDS,,,,Sebral@[ao_cs] jsi nějaké náboje!,Du tager nogle patroner!,Munition genommen.,,Vi prenis kuglojn!,¡Has pillado unas balas!,¡Has recogido unas balas!,Kahmaiset patruunoita!,Vous prenez des balles!,Felkapsz pár lőszert!,Prendi delle munizioni!,幾つかのラウンド を奪った!,권총 탄약을 주웠다!,Je pakt wat rondes!,Du tar noen runder!,Podniosłeś trochę naboi!,Você pegou munição!,,Ai ridicat niște muniție!,Заполучена обойма патронов!,,Biraz mermi al! -You grab a case of rounds!,GOTROUNDSCASE,,,,Sebral@[ao_cs] jsi krabici nábojů!,Du tager en kasse med patroner!,Munitionskiste genommen.,,Vi prenis skatolon da kugloj!,¡Has pillado una caja de balas!,¡Has recogido una caja de balas!,Kahmaiset patruunalaatikon!,Vous prenez une bôite de balles!,Felkapsz egy doboz lőszert!,Prendi un caso di munizioni!,ケースのラウンド を奪った!,권총 탄약 상자를 주웠다!,Je pakt een kist met rondes!,Du tar en kasse med patroner!,Podniosłeś skrzynkę naboi!,Você pegou uma caixa de munição!,,Ai ridicat un cartuș de muniție!,Заполучена коробка патронов!,,Bir kutu mermi al! -You grab a Torpedo!,GOTTORPEDO,"Was ""grap"" for some reason.",,,Sebral@[ao_cs] jsi torpédo!,Du tager en Torpedo!,Torpedo genommen.,,Vi prenis Torpedon!,¡Has pillado un torpedo!,¡Has recogido un torpedo!,Kahmaiset torpedon!,Vous prenez une torpille!,Felkapsz egy Torpedót!,Prendi un siluro!,トルペード を奪った!,광자탄을 주웠다!,Je pakt een Torpedo!,Du tar en Torpedo!,Podniosłeś Torpedę!,Você pegou um Torpedo!,,Ai ridicat o Torpilă!,Заполучена торпеда!,,Bir Torpido al! -You grab a case of Torpedos!,GOTTORPEDOS,,,,Sebral@[ao_cs] jsi krabici torpéd!,Du tager en kasse med torpedoer!,Torpedokiste genommen.,,Vi prenis skatolon da Torpedoj!,¡Has pillado una caja de torpedos!,¡Has recogido una caja de torpedos!,Kahmaiset torpedolaatikon!,Vous prenez une bôite de torpilles!,Felkapsz egy doboz Torpedót!,Prendi un caso di siluri!,トルペードのケース を奪った!,광자탄 무더기를 주웠다!,Je pakt een kist Torpedo's!,Du tar en kasse med torpedoer!,Podniosłeś skrzynkę Torped!,Você pegou uma caixa de Torpedos!,,Ai ridicat o cutie de Torpile!,Заполучен ящик торпед!,,Bir kasa Torpido al! -You grab a molecule module!,GOTMOLECULES,,,,Sebral@[ao_cs] jsi molekulový modul!,Du tager et molekylmodul!,Molekülmodul genommen,,Vi prenis molekulmodulon!,¡Has pillado un módulo molecular!,¡Has recogido un módulo molecular!,Kahmaiset molekyylimoduulin!,Vous prenez un module moléculaire!,Felkapsz egy molekula modult!,Prendi un modulo molecolare!,モーレキュールモヂュール を奪った!,분자 모듈을 주웠다!,Je pakt een molecuulmodule!,Du tar en molekylmodul!,Podniosłeś molekularny moduł!,Você pegou um módulo molecular!,,Ai ridicat un modul molecular!,Заполучен молекулярный модуль!,,Bir molekül modülü kap! -You grab a tank full of molecules!,GOTMOLECULESTANK,,,,Sebral@[ao_cs] jsi sud plný molekul!,Du tager en tank fuld af molekyler!,Tank mit Molekülmodulen genommen.,,Vi prenis reservujon da molekulojn!,¡Has pillado un tanque lleno de moléculas!,¡Has recogido un tanque lleno de moléculas!,Kahmaiset tankin täynnä molekyylejä!,Vous prenez un réservoir de molécules!,Felkapsz egy teli tank molekulát!,Prendi un serbatoio pieno di molecole!,タンク満タンのモーレキュール を奪った!,분자 탱크를 주웠다!,Je pakt een tank vol met moleculen!,Du tar en tank full av molekyler!,Podniosłeś zbiornik pełen molekuł!,Você pegou um tanque cheio de moléculas!,,Ai ridicat un rezervor plin cu molecule!,Заполучен контейнер с молекулами!,,Moleküllerle dolu bir tank al! -You grab some Cartridges!,GOTCARTRIDGES,,,,Sebral@[ao_cs] jsi nějaké kazety!,Du tager nogle patroner!,Magazin genommen.,,Vi prenis iom da kartoĉoj!,¡Has pillado unos cartuchos!,¡Has recogido unos cartuchos!,Kahmaiset kasetteja!,Vous prenez des cartouches!,Felkapsz pár Töltényt!,Prendi alcune cartucce!,残弾のカートリッジ を奪った!,카트리지 한 줌을 주웠다!,Je pakt een paar patronen!,Du tar noen patroner!,Podniosłeś trochę pocisków!,Você pegou alguns Carregadores!,,Ai ridicat niște Cartușe!,Заполучены картриджи!,,Fişekleri al! -You grab a case of Cartridges!,GOTCARTRIDGESCASE,,,,Sebral@[ao_cs] jsi krabici kazet!,Du tager en kasse med patroner!,Magazinkiste genommen.,,Vi prenis skatolon da kartoĉoj!,¡Has pillado una caja de cartuchos!,¡Has recogido una caja de cartuchos!,Kahmaiset laatikollisen kasetteja!,Vous prenez une bôite de cartouches!,Felkapsz egy doboz Töltényt!,Prendi un caso di cartucce!,カートリッジケース を奪った!,카트리지 박스를 주웠다!,Je pakt een kist patronen!,Du tar en kasse med patroner!,Podniosłeś skrzynkę pocisków!,Você pegou uma caixa de Carregadores!,,Ai ridicat o cutie de Cartușe!,Заполучен ящик картриджей!,,Bir kutu fişek al! -You grab a Valise stuffed with goods!,GOTVALISE,,,,Sebral@[ao_cs] jsi kufr plný munice!,Du tager en kuffert fyldt med varer!,Munitionstasche genommen.,,Vi prenis valizon plenan de municiojn!,¡Has pillado una maleta llena de equipamiento!,¡Has recogido una maleta llena de equipamiento!,Kahmaiset laukullisen täynnä tavaraa!,Vous récupérez une valise pleine d'équipement!,Felkapsz egy Poggyásznyi Muníciót!,Prendi una Valigia piena di merci!,代物を詰めたバリス を奪った!,탄약이 든 서류 가방을 주웠다!,Je pakt een Valise gevuld met goederen!,Du tar en koffert fylt med varer!,Podniosłeś Walizkę z wieloma dobrami!,Você pegou uma Mala cheia de equipamento!,,Ai ridicat o Valiză plină cu bunătăți!,Заполучена полная сумка боеприпасов!,,İçi mal dolu bir valiz al! -Force Field!,GOTFORCEFIELD,,,,Silové pole!,Kraftfelt!,Kraftfeld!,,Fortkampo!,¡Campo de fuerza!,,Voimakenttä!,Champ de force!,Erőtér!,Campo di forza!,フォースフィールド!,방어막!,Krachtveld!,Kraftfelt!,Pole Siłowe!,Campo de Força!,,Câmp de Forță!,Силовое поле!,,Güç Alanı! -007Microtel,GOTMICROTEL,,,,,,,,007 Microtel!,Microtel 007,,,007 Microtel,,,007マイクロテル,007마이크로텔 근력 향상 칩!,,,,,,Microtel 007,Микрочип 007,,007Microtel -You are EnK Blind!,GOTENKBLIND,,,,Jsi EnK-slep@[adj_cs]!,Du er EnK Blind!,Du bist EnK-blind!,,Vi estas ENK-Blinda,¡Tienes Ceguera EnK!,,Olet EnK-sokea!,Vous êtes aveugle à l'EnK!,EnK védett lettél!,Sei EnK-cieco!,EnKブラインドみてえだ!,EnK 투명 위장 장치!,Jij bent EnK Blind!,Du er EnK Blind!,Jesteś oślepiony przez EnK!,Você está vendado por EnK!,,Acum ești nedetectabil pentru Enk!,У тебя EnK-видимость!,,Sen EnK Blind'sın! -Vulcan rubber Boots!,GOTRUBBERBOOTS,,,,Gumové boty!,Vulkaniske gummistøvler!,Gummistiefel!,,Vulkanaj Kauŭĉukaj Botoj!,¡Botas de goma vulcanizada!,,Vulkanoidut kumisaappaat!,Bottes en caoutchouc vulcanisé!,Vulkanizált gumi talp!,Stivali di gomma vulcanica!,バルカンラバーブーツ!,벌컨 방화 부츠!,Vulcan rubber Laarzen!,Vulcan gummistøvler!,Gumowe Buty Vulcan!,Botas Vulcanizadas!,,Bocanci din cauciuc Vulcan!,Резиновые сапоги!,,Vulcan lastik botları! -SI Array mapping!,GOTSIARRAY,,,,Mapa pole SI!,SI Array kortlægning!,SI-Feld Karte!,,SI-matric-mapado!,¡Mapeado de Tabla SI!,,SI-kenttäkartta!,Carte du tableau SI!,SI pálya Felderítő!,Mappatura di array SI!,SIアーレイ マッピング!,Si 어레이 지도!,,SI Array kartlegging!,Mapa Pola SI!,Mapeamento por Campo de SI!,,Hartă SI compilată!,Составлена карта SI-массива!,,SI Dizi eşlemesi! -Infrared Visor!,GOTINFRARED,,,,Infračervené brýle!,Infrarødt visir!,Infrarotbrille!,,Transruĝa Viziero!,¡Visor infrarrojo!,,Infrapunavisiiri!,Viseur infrarouge!,Infravörös Sisak!,Visore a infrarossi!,赤外線バイザー!,적외선 바이져!,Infrarood vizier!,Infrarødt visir!,Wizjer na Podczerwień!,Visor Infravermelho!,,Vedere Infraroșie!,Инфракрасный визор!,,Kızılötesi Vizör! -"Breathe deep, Inhaler!",GOTINHALER,,,,"Pořádně se nadechni, inhalátor!","Træk vejret dybt, Inhalator!","Atme tief, Inhalierer!",,"Spiru profunde, inhalo!","¡Un inhalador, inspira fuerte!",,"Hengitä syvään, inhalaattori!","Respire, inhaleur!","Mély lélegzet, Inhaláló!","Respirare profondamente, inalatore!",深呼吸だ、インヘイラー!,각성제를 주웠다. 잘 들이마셔!,"Adem diep in, inhalator!","Pust dypt, Inhalator!",Weź głęboki wdech! Inhalator!,Inalador! Respira fundo!,,"Inspiră adânc, Inhalatorule!",Ингалятор! Вдыхай глубже!,,"Derin nefes al, Inhaler!" -A dose of Hydergine from a Hypo saves you!,GOTHYPONEED,,,,Jsi zachráněn@[ao_cs] dávkou Hyderginu z Hypa!,En dosis Hydergine fra en Hypo redder dig!,Eine Dosis Hydergine rettet dich!,,,¡Una dosis de Hydergina te salva la vida!,,Hyderginepiikkiannos pelastaa sinut!,Une bonne dose d'hydergine vous sauve la vie!,Egy adag Hydergine megmenti az irhád!,Una dose di Hydergine di un Hypo ti salva!,ハイポで ヒデルギン をキメた!,하이포의 하이데르진이 당신을 살렸다!,Een dosis Hydergine van een Hypo redt je!,En dose Hydergine fra en Hypo redder deg!,Dawka Hyderginy z Hypo ratuje cię!,Uma dose de hidergina do Hypo para te salvar!,,O doză de Hidrogine dintr-o seringă te salvează!,Доза Редергина из шприца спасла тебя!,,Hypo'dan bir doz Hydergine seni kurtarır! -You grab a Hypo!,GOTHYPO,,,,Sebral@[ao_cs] jsi Hypo!,Du tager en Hypo!,Hypo!,,Vi prenis Injektilon!,¡Has pillado una jeringa hipodérmica!,,Kahmaiset piikin!,Vous prenez une seringue!,Felkapsz egy Hypo-t!,Prendi un Hypo!,ハイポ を奪った!,하이포를 주웠다!,Je pakt een Hypo!,Du tar en Hypo!,Podniosłeś Hypo!,Você pegou um Hypo!,,Ai ridicat o Seringă!,Заполучен шприц!,,Bir Hypo kaptın! -You found a KeyCard!,GOTKEYCARD,,,,Nalezl@[ao_cs] jsi přístupovou kartu!,Du har fundet et Nøglekort!,Schlüsselkarte gefunden!,,Vi trovis Ŝlosilkarton!,¡Has encontrado una Tarjeta Llave!,,Löysit avainkortin!,Vous trouvez une clé magnétique!,Leltél egy Kulcskártyát!,Hai trovato una chiave magnetica!,キーカードを見つけた!,키 카드를 찾았다!,U heeft een sleutelkaart gevonden!,Du har funnet et nøkkelkort!,Znalazłeś Kartę Dostępu!,Você achou um Cartão de Passe!,,Ai găsit un Card-Cheie!,Найдена ключ-карта!,,Bir Anahtar Kart buldun! -You found a C-Key!,GOTCKEY,,,,Nalezl@[ao_cs] jsi kyberklíč!,Du har fundet en C-nøgle!,C-Schlüssel gefunden!,,Vi trovis C-Ŝlosilon!,¡Has encontrado una Llave-C!,,Löysit C-avaimen!,Vous trouvez une C-Clé!,Leltél egy C-Kulcsot!,Hai trovato una chiave C!,C-keyを見つけた!,C-키를 찾았다!,Je hebt een C-sleutel gevonden!,Du har funnet en C-nøkkel!,Znalazłeś Klucz C!,Você achou uma Chave-C!,,Ai găsit o Cheie-C!,Найден C-образный ключ!,,Bir C-Anahtarı buldun! -You found a Password!,GOTPASSWORD,,,,Nalezl@[ao_cs] jsi heslo!,Du har fundet et kodeord!,Passwort gefunden!,,Vi trovis Pasvorton!,¡Has encontrado una Contraseña!,,Löysit salasanan!,Vous trouvez un mot de passe!,Leltél egy Jelszót!,Hai trovato una parola d'ordine!,パスワードを見つけた!,암호를 찾았다!,U heeft een wachtwoord gevonden!,Du har funnet et passord!,Znalazłeś Hasło!,Você achou uma Senha!,,Ai găsit o Parolă!,Найден пароль!,,Bir Şifre buldun! -You found a blue Z-Key!,GOTBLUEZKEY,,,,Nalezl@[ao_cs] jsi modrý Z-klíč!,Du fandt en blå Z-nøgle!,Blauen Z-Schlüssel gefunden!,,Vi trovis bluan Z-ŝlosilon!,¡Has encontrado una Llave-Z azul!,,Löysit sinisen Z-avaimen!,Vous trouvez une Z-Clé bleue!,Leltél egy kék Z-Kulcsot!,Hai trovato una chiave Z blu!,ブルー Z-Key を見つけた!,청색 Z-키를 찾았다!,Je hebt een blauwe Z-sleutel gevonden!,Du har funnet en blå Z-nøkkel!,Znalazłeś niebieski Klucz Z!,Você achou uma Chave-Z azul!,,Ai găsit o Z-Cheie albastră!,Найден синий Z-образный ключ!,,Mavi bir Z-Anahtarı buldun! -You found a yellow Z-Key!,GOTYELWZKEY,,,,Nalezl@[ao_cs] jsi žlutý Z-klíč!,Du fandt en gul Z-nøgle!,Gelben Z-Schlüssel gefunden!,,Vi trovis flavan Z-ŝlosilon!,¡Has encontrado una Llave-Z amarilla!,,Löysit keltaisen Z-avaimen!,Vous trouvez une Z-Clé jaune!,Leltél egy sárga Z-Kulcsot!,Hai trovato una chiave Z gialla!,イエローZ-Key を見つけた!,황색 Z-키를 찾았다!,Je hebt een gele Z-sleutel gevonden!,Du har funnet en gul Z-nøkkel!,Znalazłeś żółty Klucz Z!,Você achou uma Chave-Z amarela!,,Ai găsit o Z-Cheie galbenă!,Найден жёлтый Z-образный ключ!,,Sarı bir Z-Anahtarı buldun! -You found a red Z-Key!,GOTREDZKEY,,,,Nalezl@[ao_cs] jsi červený Z-klíč!,Du fandt en rød Z-nøgle!,Roten Z-Schlüssel gefunden!,,Vi trovis ruĝan Z-ŝlosilon!,¡Has encontrado una Llave-Z roja!,,Löysit punaisen Z-avaimen!,Vous trouvez une Z-Clé rouge!,Leltél egy piros Z-Kulcsot!,Hai trovato una chiave Z rossa!,レッド Z-Key を見つけた!,적색 Z-키를 찾았다!,Je hebt een rode Z-sleutel gevonden!,Du har funnet en rød Z-nøkkel!,Znalazłeś czerwony Klucz Z!,Você achou uma Chave-Z vermelha!,,Ai găsit o Z-Cheie roșie!,Найден красный Z-образный ключ!,,Kırmızı bir Z-Anahtarı buldun! -Body Armor!,GOTBODYARMOR,,,,Brnění!,Kropsrustning!,Körperpanzerung!,,Kiraso!,¡Armadura!,,Suojavarustus!,Armure!,Testpáncél!,Giubbotti antiproiettile!,ボディーアーマー!,강화복!,Kogelvrije vesten!,Skuddsikker vest!,Pancerz!,Colete a Prova de Balas!,,Armură de Corp!,Бронежилет!,,Vücut Zırhı! -Centrophenoxine,GOTCENTROPHENOXINE,,,,Centrofenoxin,Centrophenoxine,,,Centrofenoksino!,¡Centrofenoxina!,,Sentrofenoksiinia,Centrophenoxine!,,,セントロフェノキシン!,메클로페녹세이트!,,Centrophenoxine,Centrofenoxina,Centrofenoxina,,Centrofenoxine,Центрофеноксин,,Centrophenoxine -You grab a Kevlar vest!,GOTKEVLARVEST,,,,Sebral@[ao_cs] jsi kevlarovou vestu!,Du får fat i en kevlarvest!,Kevlarweste!,,Vi prenis kevlaran veŝton!,¡Has pillado un traje de Kevlar!,¡Has recogido un traje de Kevlar!,Kahmaiset Kevlar-liivit!,Veste en Kevlar!,Felkapsz egy Golyóálló Mellényt!,Prendi una maglia di kevlar!,ケブラーベスト を奪った!,방탄복을 주웠다!,Pak een Kevlar vest!,Du tar en Kevlar-vest!,Podniosłeś kamizelkę kuloodporną!,Você pegou um Colete de Kevlar!,,Ai ridicat o vestă din Kevlar!,Заполучен кевларовый жилет!,,Kevlar yeleği al! -You grab Super Kevlar vest!,GOTSKEVLARVEST,,,,Sebral@[ao_cs] jsi superkevlarovou vestu!,Du tager Super Kevlar vest!,Super-Kevlarweste!,,Vi prenis superan kevlaran veŝton!,¡Has pillado un supertraje de Kevlar!,¡Has recogido un supertraje de Kevlar!,Kahmaiset Superkevlar-liivit!,Super Veste en Kevlar!,Felkapsz egy Szuper Golyóálló Mellényt!,Prendi una maglia super kevlar!,スーパーケブラーベスト を奪った!,중 방탄복을 주웠다!,Je pakt een Super Kevlar vest!,Du tar en Super Kevlar vest!,Podniosłeś superkamizelkę kuloodporną!,Você pegou um Super Colete de Kevlar!,,Ai ridicat o Super Vestă din Kevlar!,Заполучен усиленный кевларовый жилет!,,Süper Kevlar yeleği al! -You grab a MicroKit!,GOTMICROKIT,,,,Sebral@[ao_cs] jsi mikrosadu!,Du får fat i et MicroKit!,MicroKit genommen!,,Vi prenis Kompleteton!,¡Has pillado un MicroKit!,¡Has recogido un MicroKit!,Kahmaiset Microkitin!,Microkit!,Felkapsz egy Mikorkit-et!,Prendi un MicroKit!,マイクロキット を奪った!,마이크로킷을 주웠다!,Je pakt een MicroKit!,Du tar en MicroKit!,Podniosłeś MikroZestaw!,Você pegou um MicroKit!,,Ai ridicat un MicroKit!,Заполучена мини-аптечка!,,Bir MicroKit al! -You grab a Dampener!,GOTDAMPENER,,,,Sebral@[ao_cs] jsi tlumič!,Du får fat i en Dampener!,Dämpfer genommen!,,Vi prenis Dampilon!,¡Has pillado un Amortiguador!,¡Has recogido un Amortiguador!,Kahmaiset vaimentimen!,Amortisseur!,Felkapsz egy Tompítót!,Prendi un antivento!,ダンプナー を奪った!,완충 장치를 주웠다!,Je pakt een Demper!,Du tar en Dampener!,Podniosłeś Tłumik!,Você pegou um Amortecedor!,,Ai ridicat un Amortizor!,Заполучен глушитель!,,Bir Sönümleyici al! -You need a C-Key to access this item!,PD_CKEY,,,,K přístupu potřebuješ kyberklíč!,Du skal bruge en C-nøgle for at få adgang til dette objekt!,Du brauchst einen C-Schlüssel um das hier zu bedienen.,,Vi bezonas C-ŝlosilon por aliri ĉi tiun objekton!,¡Necesitas una Llave-C para acceder a este objeto!,,Tarvitset C-avaimen saadaksesi pääsyn tähän kohteeseen!,Il vous faut une C-Clé pour accéder à cet objet!,Egy C-Kulcs szükséges a hozzáféréshez!,Hai bisogno di una chiave C per accedere a questo oggetto!,アクセスには C-key が必要だ!,C-키가 있어야 작동이 가능하다!,Je hebt een C-sleutel nodig om toegang te krijgen tot dit item!,Du trenger en C-nøkkel for å få tilgang til dette elementet!,Potrzebujesz Klucza C by uruchomić ten przedmiot.,Você precisa de uma Chave-C para acessar!,,Ai nevoie de o Cheie-C pentru a accesa acest obiect!,"Нет доступа, нужен C-образный ключ!",,Bu eşyaya erişmek için bir C-Anahtarına ihtiyacın var! -You need a KeyCard to access this item!,PD_KEYCARD,,,,K přístupu potřebuješ přístupovou kartu!,Du skal bruge et Nøglekort for at få adgang til dette objekt!,Du brauchst eine Schlüsselkarte um das hier zu bedienen.,,Vi bezonas Slosilkarton por aliri ĉi tiun objekton!,¡Necesitas una Tarjeta Llave para acceder a este objeto!,,Tarvitset avainkortin saadaksesi pääsyn tähän kohteeseen!,Il vous faut une carte magnétique pour accéder à cet objet!,Egy kulcskártya szükséges a hozzáféréshez!,Hai bisogno di una chiave magnetica per accedere a questo oggetto!,アクセスには キーカード が必要だ!,키 카드가 있어야 작동이 가능하다!,U heeft een sleutelkaart nodig om toegang te krijgen tot dit item!,Du trenger et nøkkelkort for å få tilgang til dette elementet!,Potrzebujesz Karty Dostępu by uruchomić ten przedmiot!,Você precisa de uma Chave de Passe para acessar!,,Ai nevoie de un Card-Cheie pentru a accesa acest obiect!,"Нет доступа, нужен ключ-карта!",,Bu öğeye erişmek için bir KeyCard'a ihtiyacınız var! -You need a Password to access this item!,PD_PASSWORD,,,,K přístupu potřebuješ heslo!,Du skal bruge et kodeord for at få adgang til dette objekt!,Du brauchst eine Passwort um das hier zu bedienen.,,Vi bezonas Pasvorton por aliri ĉi tiun objekton!,¡Necesitas una Contraseña para acceder a este objeto!,,Tarvitset salasanan saadaksesi pääsyn tähän kohteeseen!,Il vous faut un mot de passe pour accéder à cet objet!,Egy Jelszó szükséges a hozzáféréshez!,Hai bisogno di una parola d'ordine per accedere a questo oggetto!,アクセスには パスワード が必要だ!,암호를 입력해야 작동이 가능하다!,Je hebt een wachtwoord nodig om toegang te krijgen tot dit item!,Du trenger et passord for å få tilgang til dette elementet!,Potrzebujesz Hasła by uruchomić ten przedmiot!,Você precisa de uma Senha para acessar!,,Ai nevoie de Parolă pentru a accesa acest obiect!,"Нет доступа, нужен пароль!",,Bu öğeye erişmek için bir Şifreye ihtiyacınız var! -You need a Blue Z-Key to make this work,PD_BLUEZKEY,,,,Tohle bude fungovat jen s modrým Z-klíčem.,Du skal bruge en blå Z-nøgle for at få dette til at fungere!,Du brauchst einen blauen Z-Schlüssel um das hier zu bedienen.,,Vi bezonas Bluan Z-ŝlosilon por funkciigi ĉi tiun!,¡Necesitas una Llave-Z azul para hacer funcionar esto!,,Tarvitset sinisen Z-avaimen saadaksesi tämän toimimaan!,Il vous faut une Z-Clé bleue pour faire fonctionner cela.,Egy Kék Z-Kulcs szükséges a hozzáféréshez!,Hai bisogno di una chiave Z blu per accedere a questo oggetto!,アクセスには ブルーZ-key が必要だ!,청색 Z-키가 있어야 작동이 가능하다!,Je hebt een blauwe Z-sleutel nodig om dit te laten werken.,Du trenger en blå Z-nøkkel for å få dette til å fungere!,Potrzebujesz Niebieskiego Klucza Z by zadziałało!,Você precisa de uma Chave-Z azul para fazer isto funcionar!,,Ai nevoie de o Cheie-Z albastră pentru a face asta să funcționeze!,"Не работает, нужен синий Z-образный ключ!",,Bunu çalıştırmak için bir Mavi Z-Anahtarına ihtiyacınız var -You need a Red Z-Key to make this work!,PD_REDZKEY,,,,Tohle bude fungovat jen s červeným Z-klíčem.,Du skal bruge en rød Z-nøgle for at få dette til at fungere!,Du brauchst einen roten Z-Schlüssel um das hier zu bedienen.,,Vi bezonas Ruĝan Z-ŝlosilon por funkciigi ĉi tiun!,¡Necesitas una Llave-Z roja para hacer funcionar esto!,,Tarvitset punaisen Z-avaimen saadaksesi tämän toimimaan!,Il vous faut une Z-Clé rouge pour faire fonctionner cela.,Egy Piros Z-Kulcs szükséges a hozzáféréshez!,Hai bisogno di una chiave Z gialla per accedere a questo oggetto!,アクセスには レッドZ-key が必要だ!,적색 Z-키가 있어야 작동이 가능하다!,Je hebt een rode Z-sleutel nodig om dit te laten werken!,Du trenger en rød Z-nøkkel for å få dette til å fungere!,Potrzebujesz Czerwonego Klucza Z by zadziałało!,Você precisa de uma Chave-Z vermelha para fazer isto funcionar!,,Ai nevoie de o Cheie-Z roșie pentru a face asta să funcționeze!,"Не работает, нужен красный Z-образный ключ!",,Bunu çalıştırmak için Kırmızı Z-Anahtarına ihtiyacınız var! -You need a Yellow Z-Key to make this work!,PD_YELWZKEY,,,,Tohle bude fungovat jen se žlutým Z-klíčem.,Du skal bruge en gul Z-nøgle for at få dette til at fungere!,Du brauchst einen gelben Z-Schlüssel um das hier zu bedienen.,,Vi bezonas Flavan Z-ŝlosilon por funkciigi ĉi tiun!,¡Necesitas una Llave-Z amarilla para hacer funcionar esto!,,Tarvitset keltaisen Z-avaimen saadaksesi tämän toimimaan!,Il vous faut une Z-Clé jaune pour faire fonctionner cela.,Egy Sárga Z-Kulcs szükséges a hozzáféréshez!,Hai bisogno di una chiave Z rossa per accedere a questo oggetto!,アクセスには イエローZ-key が必要だ!,황색 Z-키가 있어야 작동이 가능하다!,Je hebt een gele Z-sleutel nodig om dit te laten werken!,Du trenger en gul Z-nøkkel for å få dette til å fungere!,Potrzebujesz Żółtego Klucza Z by zadziałało!,Você precisa de uma Chave-Z amarela para fazer isto funcionar!,,Ai nevoie de o Cheie-Z galbenă pentru a face asta să funcționeze!,"Не работает, нужен жёлтый Z-образный ключ!",,Bunu yapmak için Sarı Z-Anahtarına ihtiyacın var! +la bluan pilolon.",Deberías haber tomado la pastilla azul.,,Olis pitäny ottaa sininen pilleri.,T'aurais du prendre la pilule bleue.,Inkább a kék pirulát kellett volna választanod.,Avresti dovuto prendere la pillola blu ...,青いピルを採るべきではなかったな。,넌 파란 알약을 골랐어야 했어.,Je had de blauwe pil moeten nemen.,Skulle tatt den blå pillen.,Trzeba było wziąć niebieską pigułkę.,Devia ter tomado a pílula azul.,,Trebuia să iei pastila albastră.,Надо было принять синюю таблетку.,,Du borde ha tagit det blå pillret.,Mavi hapı almalıydın. +The name of the game ain't Twitch n' Run!,QUITMSG11,,,,V názvu hry není napsané „uteč“!,"Spillets navn er ikke ""at flygte""!","Das Spiel heißt nicht ""wegrennen""!",,La nomo de la ludo ne estas Tiku kaj Kuru!,¡El nombre del juego no es Tirar a Correr!,,Pelin nimi ei oo Paniikkipako!,"Le jeu s'appelle pas ""Panique et cours!""",A játék neve nem Twitch n' Megfutamodás.,"Il gioco non significa ""scappare""!",ゲーム名は 萎え落ち小僧 じゃねえぞ!,"이봐, 이 게임은 때리고 도망가는 게임이 아니라고!",De naam van het spel is niet Twitch n' Run!,Navnet på spillet er ikke Twitch n' Run!,"Nazwą gry nie jest ""Drżyj i Uciekaj""!",O nome do jogo não é Trema nas Bases e Fuja!,,Numele jocului nu e Tremură și Ascunde-te!,Эта игра называется не «Дрожи и прячься»!,,"Spelet heter inte ""Twitch n' Run""!",Oyunun adı Twitch n' Run değil! +"No worries. Saving the world can wait, right?",QUITMSG12,,,,"Žádný problém. Záchrana světa může počkat, ne?","Det er ikke noget problem. At redde verden kan vente, ikke?","Also, die Welt zu retten kann warten, richtig?",,"Ne zorgu. Savi la mondon povas atendi, ĉu ne?","No te preocupes. Salvar el mundo puede esperar, ¿verdad?",,"Ei huolta; maailman pelastaminen voi odottaa, eikö niin?","Oh, pas de problème. Le monde peut attendre\nd'être sauvé, non?","Semmi pánik. A világmegmentés várhat, nemde?","Salvare il mondo può\naspettare, giusto?",気にはしない、世界を救うのは何時でも出来る、だろ?,걱정 말라고. 세상이 위험한데 급할 것 있나. 안 그래?,"Het redden van de wereld kan wachten, toch?","Slapp av. Å redde verden kan vente, ikke sant?","Bez obaw. Ratowanie świata może poczekać, prawda?","Sem problemas. O mundo pode esperar, não é mesmo?",,"Nicio problemă. Salvarea lumii poate aștepta, nu?","Не парься. Спасение мира подождёт, ведь так?",,"Det är ingen fara. Att rädda världen kan vänta, eller hur?","Endişelenme. Dünyayı kurtarmak bekleyebilir, değil mi?" +Guess it's time to make like the 'net and split!,QUITMSG13,,,,"Hádám, že je čas vypojit server!",Så er det vist på tide at gøre som nettet og smutte!,"Also ist es soweit, dass sich unsere Wege trennen.",,"Tempas, ke niaj vojoj agu kiel la reto kaj dividu.",¡Supongo que es hora de cortar con esta mala conexión!,,Kai sitten on aika katkaista palvelinyhteydet!,Ca doit être temps de partir comme une mauvaise connection!,Kettéváglak mint a netsplit a kapcsolatot.,Quindi è il momento per i\nnostri modi di separarsi.,ネット切断している暇は無いだろ!,벌써 서버를 다운시키는 '척' 할 시간인가?,Denk dat het tijd is om het te maken als het 'net en splitsen!,Det er vel på tide å gjøre som nettet og stikke!,"Wygląda na to, że trzeba się rozłączyć jak netsplit!","Acho que tá na hora de cair, que nem uma conexão ruim.",,Cred că e timpul de separare!,"Кажется, настало время устроить netsplit!",,Det är nog dags att göra som nätet och dra sig ur!,Sanırım 'net gibi yapıp ayrılmanın zamanı geldi! +"Don't go off and forget about HacX, now!",QUITMSG14,,,,Ať tě nenapadne odejít a zapomenout na HacX!,Glem nu ikke HacX!,Bitte vergesse HacX nicht!,,Ne iru forgesi HacX nun!,¡Ahora no vayas y te olvides de Hacx!,,Älä nyt mene pois ja unohda HacX:ä!,Va pas oublier HacX maintenant!,"Ha elkalandozol, ne feletkezz meg a HacX-ről!","Non andartene e dimenticarti di HacX, ora!",HacXを忘れんじゃねえぞ、な!,부디 나가지 말고 HacX를 잊지 말아줘!,"Ga niet af en vergeet HacX niet, nu!","Ikke gå og glem HacX, nå!","Nie wyłączaj i nie zapominaj o HacX, teraz!","Não vai se esquecer do HacX, hein!",,Nu pleca și uita de HacX!,"Только посмей уйти и забыть про HacX, ты!",,Gå inte iväg och glömma HacX nu!,"HacX'i unutup gitme, şimdi!" +%o deleted %hself from the universe.,OB_SUICIDE,,,,%o se smazal@[ao_cs] z vesmíru.,%o slettede sig selv fra universet.,%o entfernte sich aus dem Universum.,,%o forigis sin el la universo.,%o se borró a si mism@[ao_esp] del universo.,,%o poisti itsensä maailmankaikkeudesta.,%o s'est effacé@[e_fr] de l'univers.,%o kitörölte magát az univerzumból,%o si è cancellato dall'universo.,%o はこの宇宙から消滅した。,%o 은(는) 자기 자신의 존재를 소멸시켰다.,%o verwijderd zichzelf uit het universum.,%o slettet seg selv fra universet.,%o usun@[irreg_2_pl] się ze świata.,%o se apagou deste universo.,,%o s-a sters pe sine din univers.,Игрок %o стёр себя с лица вселенной.,,%o raderade sig själv från universum.,%o kendini evrenden sildi. +%o formed a crater the size of Kansas.,OB_FALLING,,,,%o utvořil@[ao_cs] kráter velikosti Kansasu.,%o dannede et krater på størrelse med Kansas.,%o wurde zu einem Krater in der Größe von Kansas.,,%o formis krateron grandan kiel Kansaso.,%o formó un cráter del tamaño de Kansas.,,%o muodosti Kansasin kokoisen kraaterin.,%o a formé un cratère de la taille du Kansas.,%o egy Kansas méretű krátert hagyott maga után.,%o ha formato un cratere delle dimensioni del Kansas.,%o はカンザス州程のクレーターを生成した。,%o 은(는) 땅바닥에 캔자스만큼 커다란 구멍을 뚫었다.,%o vormde een krater ter grootte van Kansas.,%o dannet et krater på størrelse med Kansas.,%o utworzył@[ao_pl] krater wielkości Kansas.,%o abriu uma cratera do tamanho do Kansas.,,%o a format un crater de dimensiunile statului Kansas.,На месте падения игрока %o образовался кратер размером с Канзас.,,%o bildade en krater lika stor som Kansas.,%o Kansas büyüklüğünde bir krater oluşturdu. +%o became a human pancake.,OB_CRUSH,,,,%o se změnil@[ao_cs] v lidskou palačinku.,%o blev en menneskelig pandekage.,%o wurde zu einem menschlichen Pfannkuchen.,,%o Iĝis homa patkuko.,%o se convirtió en un crepe humano.,,%o tuli ihmispannukakun muotoiseksi.,%o est devenu@[e_fr] une crêpe.,%o palacsintává lapult,%o è diventato un pancake umano.,%o は人肉パンケーキになった。,%o 은(는) 인간 빈대떡이 되었다.,%o werd een menselijke pannenkoek.,%o ble en menneskelig pannekake.,%o stał@[ao_pl] się ludzkim plackiem.,%o virou uma panqueca humana.,,%o a devenit o clătită umană.,Игрока %o сплющило в лепешку.,,%o blev en mänsklig pannkaka.,%o insan bir krep oldu. +%o tried to jack out.,OB_EXIT,,,,%o se pokusil@[ao_cs] prchnout.,%o forsøgte at stikke af.,%o hat sich ausgeloggt.,,%o provis malkonektiĝi.,%o intentó desconectarse.,,%o yritti irrottaa piuhan.,%o a tenté de se déconnecter.,%o ki akarta húzni a kábelét,%o è uscito.,%o は逃げ出そうとした。,%o 은(는) 로그아웃하려고 시도했다.,%o probeerde zich terug te trekken.,%o prøvde å jekke seg ut.,%o chciał@[ao_pl] się wydostać.,%o tentou se desconectar.,,%o a încercat să o taie.,Игрок %o хотел улизнуть.,,%o försökte ta sig ut.,%o kaçmaya çalıştı. +%o swam like a brick.,OB_WATER,,,,%o uměl@[ao_cs] plavat jako cihla.,%o svømmede som en mursten.,%o schwamm wie ein Stein.,,%o naĝis kiel briko.,%o nadó como un ladrillo.,,%o ui kuin tiiliskivi.,%o nage comme une brique.,%o úgy úszik mint egy tégla.,%o nuotava come una pietra.,%o はカナヅチだった。,%o 은(는) 웹서핑을 못 하는 타입이었다.,%o zwom als een baksteen.,%o svømte som en murstein.,%o popłyn@[irreg_2_pl] jak cegła.,%o foi nadar como um tijolo.,,%o a înotat ca o cărămidă.,Игрок %o поплыл как топор.,,%o simmade som en tegelsten.,%o bir tuğla gibi yüzdü. +%o went nuclear.,OB_SLIME,,,,%o se rozpadl@[ao_cs] na atom.,%o blev nuklear.,%o wurde verstrahlt.,,%o iĝis nuklea,%o se volvió radioactiv@[ao_esp].,,%o kiinnostui ydinasioista.,%o s'est fait fissionner.,%o felrobbant mérgében.,%o è stato irradiato.,%o はニュークリアーと化した。,%o 은(는) 방사능 바람을 좀 쐬고 왔다.,%o werd nucleair.,%o ble nuklear.,%o został@[ao_pl] napromieniowan@[adj_pl].,%o ficou radioativ@[ao_ptb].,,%o a devenit radioactiv.,Игрок %o светится в темноте.,,%o blev kärnvapenfri.,%o nükleer oldu. +%o took a hot bath.,OB_LAVA,,,,%o si dal@[ao_cs] horkou koupel.,%o tog et varmt bad.,%o nahm ein heißes Bad.,,%o spertis varman banon.,%o tomó un baño caliente.,,%o otti kuuman kylvyn.,% prend un bain chaud.,%o vett egy forró fürdőt.,%o ha fatto un bagno caldo.,%o は熱湯風呂に浸かった。,%o 은(는) 시원하게 용암 일광욕을 즐겼다.,%o nam een warm bad.,%o tok et varmt bad.,%o wzi@[irreg_2_pl] gorącą kąpiel.,%o tomou um banho bem quente.,,%o a făcut o baie fierbinte.,Игрок %o принял горячую ванну.,,%o tog ett varmt bad.,%o sıcak bir banyo yaptı. +%o overdosed on nitro glycerine.,OB_BARREL,,,,%o se předávkoval@[ao_cs] nitroglycerinem.,%o fik en overdosis nitroglycerin.,%o nahm eine Überdosis Nitroglyzerin.,,%o trodozis nitroglicerinon.,%o tuvo una sobredosis de nitroglicerina.,,%o sai yliannostuksen nitroglyseriiniä.,%o a fait une overdose de nitroglycérine.,%o túladagolta a nitro-glicerint.,%o ha assunto un sovradosaggio di nitroglicerina.,%o はニトロを過剰摂取した。,%o 은(는) 니트로글리세린을 훅 가게 흡입했다.,%o overdosering op nitroglycerine.,%o tok en overdose nitroglyserin.,%o przedawkował@[ao_pl] nitroglicerynę.,%o teve overdose de nitroglicerina.,,%o a luat o supradoză de nitroglicerină.,Игрок %o перебрал нитроглицерина.,,%o tog en överdos av nitroglycerin.,%o aşırı dozda nitro gliserin aldı. +%o is flayed into tiny little pieces.,OB_SPLASH,,,,%o byl@[ao_cs] sedřen@[ao_cs] na kousíčky.,%o er flået i småstykker.,%o wurde zerkleinert.,,%o estas senhaŭtiga en malgrandetaj pecoj.,%o es despellejad@[ao_esp] en trocitos pequeños.,,%o silpoutui riekaleiksi.,%o s'est fait éparpiller en petits morceaux.,%o ripityára szakadt szét.,%o è stato schiacciato.,%o は細かい粒をぶち撒けられた。,%o 은(는) 작은 입자로 분해되었다.,%o wordt gevild in kleine stukjes.,%o er flådd i bittesmå biter.,%o został@[ao_pl] roztrzaskan@[adj_pl] na małe kawałeczki.,%o foi detonad@[ao_ptb] em vários pedacinhos.,,%o s-a spart în mii de bucățele.,Игрока %o разодрали на мелкие клочки.,,%o är flådd i pyttesmå bitar.,%o küçük parçalara ayrıldı. +%o wanted to see what %g looked like inside-out.,OB_R_SPLASH,,,,"%o chtěl@[ao_cs] vědět, jak vypadá zevnitř.","%o ville se, hvordan han så ud indefra.",%o wollte @[pp_de] Innereien sehen.,,"%o volis vidi, kiel %g aspektus kun la interno ekstere.",%o quería ver que pinta tenía por dentro.,,%o halusi nähdä itsensä nurinperin.,%o voulait voir comment ses organes fonctionnent.,%o meg akarta tudni %g hogy néz ki belülről.,%o voleva vedere le sue interiora.,%o は %g が裏返しになるのを望んだ。,%o 은(는) 인체의 신비를 감상했다.,%o wilde zien hoe %g er binnenstebuiten uitzag.,%o ville se hvordan han så ut på innsiden.,%o chciał@[ao_pl] zobaczyć jak %g wygląda od środka.,%o queria ver como são os orgãos internos de %g.,,%o a vrut să vadă cum arăta %g întors pe dos.,"Игрок %o хотел посмотреть, что у него внутри.",,%o ville se hur @[pro_sv] såg ut på insidan.,"%o, içinin dışının nasıl göründüğünü görmek istedi." +%o wanted to see what %g looked like inside-out.,OB_ROCKET,,,,"%o chtěl@[ao_cs] vědět, jak vypadá zevnitř.","%o ville se, hvordan han så ud indvfra.",%o wollte @[pp_de] Innereien sehen.,,"%o volis vidi, kiel %g aspektus kun la interno ekstere.",%o quería ver que pinta tenía por dentro.,,%o halusi nähdä itsensä nurinperin.,%o voulait voir comment ses organes fonctionnent.,%o meg akarta tudni %g hogy néz ki belülről.,%o voleva vedere le sue interiora.,%o は %g が裏返しになるのを望んだ。,%o 은(는) 퀀텀 여행을 즐겼다.,%o wilde zien hoe %g er binnenstebuiten uitzag.,%o ville se hvordan han så ut utenpå.,%o chciał@[ao_pl] zobaczyć jak %g wygląda od środka.,%o queria ver como são os orgãos internos de %g.,,%o a vrut să vadă cum arăta %g întors pe dos.,"Игрок %o хотел посмотреть, что у него внутри.",,%o ville se hur @[pro_sv] såg ut på insidan.,%o içten dışa nasıl göründüğünü görmek istedi. +%o deleted %hself from the universe.,OB_KILLEDSELF,,,,%o se smazal@[ao_cs] z vesmíru.,%o slettede sig selv fra universet.,%o entfernte sich aus dem Universum.,,%o forigis sin el la universo.,%o se borró a si mism@[ao_esp] del universo.,,%o poisti itsensä maailmankaikkeudesta.,%o s'est effacé@[e_fr] de l'univers.,%o kitörölte magát az univerzumból,%o si è cancellato dall'universo.,%o はこの宇宙から消滅した。,%o 은(는) 자기 자신을 해킹했다.,%o schrapte zichzelf uit het universum.,%o slettet seg selv fra universet.,%o usun@[irreg_2_pl] się ze świata.,%o se deletou deste universo.,,%o s-a șters pe sine din univers.,Игрок %o стёр себя с лица вселенной.,,%o raderade sig själv från universum.,%o kendini evrenden sildi. +%o is no longer the dominant species.,OB_THUG,,,,%o už není vládnoucím živočichem.,%o er ikke længere den dominerende art.,%o ist nicht länger die dominante Spezies.,,%o ne estas la supera specio plu.,%o ya no es la especie dominante.,,%o ei ole enää vallitsevaa lajia.,%o n'est plus l'espèce dominante.,Már nem %o a csúcsragadozó.,%o non è più la specie dominante.,%o はもはや優性種ではなくなった。,%o 은(는) 그들의 시다바리가 아니였다.,%o is niet langer de dominante soort.,%o er ikke lenger den dominerende arten.,%o nie jest już dominującym gatunkiem.,%o não é mais a espécie dominante.,,%o nu mai e specia dominantă.,Игрок %o больше не доминантная форма жизни.,,%o är inte längre den dominerande arten.,%o artık baskın tür değil. +%o plugged in to the wrong machine.,OB_ANDROID,,,,%o se zapojil@[ao_cs] ke špatnému stroji.,%o har tilsluttet sig den forkerte maskine.,%o verband sich mit der falschen Maschine.,,%o konektiĝis en la eraran maŝinon.,%o se enchufó en la máquina equivocada.,,%o kytkeytyi väärään koneeseen.,%o s'est branché@[e_fr] à la mauvaise machine.,%o a rossz gépet dugta be.,%o connesso alla macchina sbagliata.,%o は違うマシンに接続してしまった。,%o 은(는) 잘못된 기계를 작동시켰다.,%o aangesloten op de verkeerde machine.,%o koblet seg til feil maskin.,%o podłączył@[ao_pl] się do złej maszyny.,%o se conectou na máquina errada.,,%o s-a conectat la mașina greșită.,Игрока %o подключили не к тому заряднику.,,%o anslöt sig till fel maskin.,%o yanlış makineye bağlandı. +%o got %hself a monster of a cyber-jockey-derriere-kicking.,OB_MONSTRUCT,,,,%o dostal@[ao_cs] šíleně kybernakopáno.,%o fik sig et monster af et cyber-jockey-derriere-spark.,%o bekam einen monströsen Cyber-Arschtritt verpasst.,,%o ricevis monstran cybernetik-raydist-postaĵ-piedbaton.,%o se ganó la madre de todas las patadas en el culo.,,%o sai hirviömäisen kyberlöylytyksen.,%o s'est fait@[e_fr] botter le cul de manière monumentale.,%o segge meg lett rugdosva.,% o ho avuto un mostruoso calcio cibernetico mancato.,%o は己に サイバー-ジョッキー-デリエレ-キッキング を取り入れた。,%o 은(는) 저 괴물의 슈퍼-울트라-캡쑝-파워를 맛봤다.,%o kreeg een monsterlijke cybertrap in @[zijn_haar_nl] kont.,%o fikk seg et monster av en cyber-jockey-derriere-sparking.,%o dostał@[ao_pl] cyber-kopa w dupę.,%o levou um cibercoice monstruoso nas fuças.,,%o s-a făcut praf în stil cibernetic.,Игрок %o получил поджопника от кибердиджея.,,%o fick sig ett monster av en cyber-jockey-derriärspark.,%o kendine canavar gibi bir dayak attı. +%o got ICEd.,OB_ICE,,,,%o byl@[ao_cs] zmražen@[ao_cs] ICEm.,%o blev ICEd.,%o wurde verEISt.,,%o iĝis ICE-ita,%o fue ICEad@[ao_esp].,,%o raukkaa nyt varmaankin kICEmittää.,%o s'est fait@[e_fr] ICEr.,%o-t jégre tették.,% o è stato ghiacciato.,%o は冷えた。,%o 은(는) 지독하게 물어뜯겼다.,%o was IJS'd.,%o ble ICEd.,%o został@[ao_pl] zamrożon@[adj_pl].,%o foi peg@[ao_ptb] por um ICE. AI SE ferrou!,,%o a ÎNGHEȚat.,Игрок %o вляпался в ЛЁД.,,%o blev ICEd.,%o buzlandı. +%o feels a little buzzed.,OB_BUZZER,,,,%o dostal@[ao_cs] malou pecku.,%o føler sig lidt svimmel.,%o fühlt sich etwas gekitzelt.,,%o sentas sin iomete vibretita.,%o se siente algo zumbad@[ao_esp].,,%o raukan päässä hieman surisee.,%o sent le buzz.,%o-nak még mindig zúg a füle.,%o si sente solleticato un po '.,%o は少し賑やかになった。,%o 은(는) 짜릿하게 찔렸다.,%o voelt een beetje gezoemd.,%o føler seg litt beruset.,%o poczuł@[ao_pl] brzęczenie.,%o se sente meio chocad@[ao_ptb].,,%o se simte puțin șocat.,Игрок %o лёг спать в компании вертолётиков.,,%o känner sig lite uppslukad.,%o biraz kafayı bulmuş gibi hissediyor. +%o uncovers a rather shocking development.,OB_STEALTH,,,,%o odhalil@[ao_cs] šokující informace.,%o opdager en temmelig chokerende udvikling.,%o machte eine schockierende Entdeckung.,,%o malkovras tre ŝokantan aferon.,%o descubre algo bastante chocante.,,%o raukalle paljastuu sangen sähköistävä uutinen.,%o a fait une découverte choquante.,"%o rájön, hogy az áram nem játék.",%o ha fatto una scoperta scioccante.,%o はかなり衝撃的な開発を発見した。,%o 은(는) 비밀리에 만들어진 병기를 발견했다.,%o ontdekt een nogal schokkende ontwikkeling.,%o avdekker en ganske sjokkerende utvikling.,%o odkrywa coś szokującego.,%o descobre uma revelação chocante.,,%o dezvăluie o schimbare șocantă.,Игрока %o встретил довольно серьёзный поворот событий.,,%o upptäcker en ganska chockerande utveckling.,%o oldukça şok edici bir gelişmeyi ortaya çıkardı. +%o was erased from cyberspace.,OB_DMAN,,,,%o byl@[ao_cs] vymazán@[ao_cs] z kyberprostoru.,%o blev slettet fra cyberspace.,%o wurde aus dem Cyberspace gelöscht.,,%o estas viŝita el cyberspaco.,%o fue borrad@[ao_esp] del ciberespacio.,,%o poistettiin kyberavaruudesta.,%o s'est fait@[e_fr] effacer du cyberespace.,%o-t kitörölték a kibertérből.,%o è stato eliminato dal cyberspazio.,%o はサイバースペースに消去された。,%o 은(는) 영구차단을 당했다.,%o werd gewist uit cyberspace.,%o ble slettet fra cyberspace.,%o został@[ao_pl] usunięt@[adj_pl] z cyber przestrzeni.,%o foi deletad@[ao_ptb] do ciberespaço.,,%o a fost șters din spațiul cibernetic.,Игрока %o удалили из киберпространства.,,%o raderades från cyberrymden.,%o siber uzaydan silindi. +%o gave %hself a glass jaw.,OB_GLASS,,,,%o si přidělal@[ao_cs] skleněnou čelist.,%o gav sig selv en glaskæbe.,%o bekam ein Glaskinn.,,%o donis al si vitran makzelon.,%o se estampó contra un cristal.,,%o antoi itsellensä lasileuan.,%o s'est fait@[e_fr] vitrifier la figure.,%o állon vágta magát.,%o ha un mento di vetro.,%o は自身にグラスジョーを取り付けた。,%o 은(는) 유리창을 깨고 등장하는 액션 배우가 아니였다.,%o gaf zichzelf een glazen kaak.,%o ga seg selv en glasskjeve.,%o był@[ao_pl] zbyt delikatn@[adj_pl] ze szkłem.,%o tem um queixo de vidro.,,%o și-a făcut un maxilar de sticlă.,У игрока %o оказалась стеклянная челюсть.,,%o gav sig själv en glaskäke.,%o kendine cam çene taktı. +%o's life membership was terminated.,OB_MANIAC,,,,%o@[psn_cs] členství v klubu živých bylo přerušeno.,%os medlemskab på livstid blev opsagt.,%os Mitgliedschaft im Leben wurde beendet.,,La vivo-membrecon de %o estas finigita,%o tuvo su afiliación a la vida terminada.,,%o raukan elämänjäsenyys päätettiin.,L'abonnement à vie de %o est arrivé à sa fin.,%o elfelejtette befizetni az élők tagdíját.,L'appartenenza di %o alla vita è finita.,%o のメンバーシップ生活は終幕した。,%o 의 계정은 영원히 삭제되었다.,%o's levenslange lidmaatschap werd beëindigd.,%os livstidsmedlemskap ble avsluttet.,Członkowstwo %o w klubie żywych się skończyło.,%o não está mais afiliad@[ao_ptb] à vida.,,%o nu mai e membru al clubului celor vii.,Игрока %o исключили из клуба живых.,,%os medlemskap på livstid avslutades.,%o hayata veda etti. +%o died in some random method I cannot fathom.,OB_MANIACHIT,,,,"%o umřel@[ao_cs] nějakým způsobem, který ani nemůžu pochopit.","%o døde på en eller anden tilfældig måde, som jeg ikke kan gennemskue.",%o starb auf eine unvorstellbare Art und Weise.,,"%o mortis per iu malcerta maniero, kiun mi ne povas kompreni.",%o murió de alguna manera que no llego a comprender.,,"%o kuoli jollakin sattumanvaraisella tavalla, jota en voi käsittää.",%o est mort@[e_fr] d'une manière que je n'arrive même pas à décrire.,Ötletem since hogy halt meg %o.,%o è morto in un modo inimmaginabile.,%o は計算外の乱数で死んだ。,%o 은(는) 의미불명의 이유로 잠수를 타게 되었다.,%o stierf op een of andere willekeurige manier die ik me niet kan voorstellen.,%o døde på en eller annen tilfeldig måte jeg ikke fatter.,"%o zgin@[irreg_2_pl] pod wpływem metody, której nie mogę pojąć.",%o morreu de alguma forma aleatória que nem consigo imaginar.,,%o a murit într-un mod aleatoriu pe care nu mi-l pot închipui.,Игрок %o внезапно умер по непостижимой для меня причине.,,%o dog på något slumpmässigt sätt som jag inte kan förstå.,%o anlayamadığım rastgele bir yöntemle öldü. +%o was fried by a femme fatale freak.,OB_TERMIN,,,,%o byl@[ao_cs] usmažen@[ao_cs] šílenou femme fatale.,%o blev stegt af en femme fatale freak.,%o wurde von einem Femme-Fatale Freak gebraten.,,%o estis fritita de femme-fatale-groteskulo.,%o fue tostad@[ao_esp] por una femme fatale.,,%o joutui kohtalokkaan kimman kärtsäämäksi.,%o s'est fait@[e_fr] frire par une femme fatale.,%o-t lebombázta egy bomba nő.,% o è stato fritto da una femme fatale.,%o はファム ファタル フリークに揚げられた。,%o 은(는) 미인계에 발을 들였다.,%o werd gebakken door een femme fatale freak.,%o ble stekt av en femme fatale-freak.,%o został@[ao_pl] usmażon@[adj_pl] przez szaloną femme fatale.,%o foi fritad@[ao_ptb] por uma femme fatale psicótica.,,%o a fost prăjit de către o femme fatale psihopată.,Игрока %o поджарила чокнутая роковая женщина.,,%o stektes av en femme fatale-freak.,%o bir femme fatale ucubesi tarafından kızartıldı. +%o got a little close to the opposite sex.,OB_TERMINHIT,"This text is not gender neutral, obviously...",,,%o se moc přiblížil@[ao_cs] k opačnému pohlaví.,%o kom lidt tæt på det modsatte køn.,%o kam dem anderen Geschlecht zu nahe.,,%o iĝis iomete proksime al la mala sekso.,%o se acercó demasiado a la persona equivocada.,,%o meni hieman liian lähelle vastakkaista sukupuolta.,%o s'est trop rapproché@[e_fr] de la mauvaise personne.,%o túl közel került az ellenkező nemhez.,%o è arrivato troppo vicino all'altro sesso.,%o は少し異性に成り果てた。,%o 의 남자다운 자존심은 쪼그라들었다.,%o kwam een beetje in de buurt van het andere geslacht.,%o kom litt nær det motsatte kjønn.,%o pod@[irreg_1_pl] zbyt blisko do płci pięknej.,%o chegou perto demais do sexo oposto.,,%o s-a apropriat prea mult de sexul opus.,Игрок %o почти сблизился с противоположным полом.,,%o kom lite väl nära det motsatta könet.,%o karşı cinsle biraz yakınlaştı. +%o said goodbye to an old friend.,OB_REPLI,,,,%o řekl@[ao_cs] sbohem starému příteli.,%o sagde farvel til en gammel ven.,%o verabschiedete sich von einem alten Freund.,,"%o diris ""Ĝis la revido"" al malnova amiko.",%o se despidió de un viejo amigo.,,%o sanoi hyvästit vanhalle ystävälle.,%o dit au revoir à un vieil ami.,%o búcsút intett egy régi barátjának.,%o ha detto addio a un vecchio amico.,%o は古い友人に別れを告げた。,%o 은(는) 오랜 친구와 작별인사를 했다.,%o nam afscheid van een oude vriendin.,%o tok farvel med en gammel venn.,%o pożegnał@[ao_pl] się ze starym znajomym.,%o disse adeus a um velho amigo.,,%o a spus adio unui vechi prieten.,Игрок %o распрощался со старым другом.,,%o tog farväl av en gammal vän.,%o eski bir arkadaşına veda etti. +%o was stabbed in the back by an old friend.,OB_REPLIHIT,,,,%o byl@[ao_cs] bodnuta do zad starým přítelem.,%o blev stukket i ryggen af en gammel ven.,%o wurde von einem alten Freund in den Rücken gestochen.,,%o estis pikita en la dorson de malnova amiko.,%o fue apuñalad@[ao_esp] en la espalda por un viejo amigo.,,%o joutui vanhan ystävän selkäänpuukottamaksi.,%o s'est fait@[e_fr] planter une lame dans le dos par un vieil ami.,%o-t hátba szúrta egy régi barát.,%o è stato pugnalato alla schiena da un vecchio amico.,%o は古い友人に背中を刺された。,%o 은(는) 오랜 친구에게 배신을 당했다.,%o werd in de rug gestoken door een oude vriend.,%o ble dolket i ryggen av en gammel venn.,%o został@[ao_pl] dźgnięt@[adj_pl] w plecy przez starego znajomego.,%o foi apunhalad@[ao_ptb] pelas costas por um velho amigo.,,%o a fost înjunghiat pe la spate de către un vechi prieten.,Игрок %o получил нож в спину от старого друга.,,%o blev knivhuggen i ryggen av en gammal vän.,%o eski bir arkadaşı tarafından sırtından bıçaklandı. +%o was weeded out by natural selection.,OB_PHAGE,,,,%o byl@[ao_cs] vyčištěna přirozeným výběrem.,%o blev sorteret fra ved naturlig udvælgelse.,%o fiel der natürlichen Auslese zum Opfer.,,%o estis foriga de natura elektado.,%o fue eliminad@[ao_esp] por selección natural.,,%o joutui luonnonvalinnan kitkemäksi.,%o a été éliminé@[e_fr] par la sélection naturelle.,A természetes kiválasztás áldozata lett %o.,%o cadde vittima della selezione naturale.,%o は自然淘汰によって除草された。,%o 은(는) 약육강식을 지금까진 모르고 있었다.,%o werd door natuurlijke selectie weggehaald.,%o ble luket ut av naturlig seleksjon.,%o został@[ao_pl] przesian@[adj_pl] przez naturalną selekcję.,%o foi eliminad@[ao_ptb] por seleção natural.,,%o a fost eliminat prin selecție naturală.,Игрок %o был отсеян естественным отбором.,,%o blev utsorterad av det naturliga urvalet.,%o doğal seleksiyon tarafından ayıklandı. +%o couldn't escape a thorny death.,OB_THORN,,,,%o nemohl@[ao_cs] utéct bodlavé smrti.,%o kunne ikke undslippe en tornedød.,%o konnte einem dornigen Tod nicht entkommen.,,%o ne povis eskapi dornan morton.,%o no pudo escapar una muerte espinosa.,,%o ei kyennyt välttämään piikikästä kuolemaa.,%o n'a pu éviter une mort piquante.,Lyukasra szúrták %o-t a tövisek.,%o non poteva sfuggire a una morte spinosa.,%o は棘のある死から逃げられなかった。,%o 은(는) 따가운 죽음을 피할 수 없었다.,%o kon niet ontsnappen aan een netelige dood.,%o kunne ikke unnslippe en tornefull død.,%o nie m@[irreg_4_pl] uciec przed cierniową śmiercią.,%o não conseguiu escapar de uma morte espinhosa.,,%o nu a putut scăpa de o moarte spinoasă.,Игрока %o поджидала смерть на его тернистом пути.,,%o kunde inte undgå en taggig död.,%o dikenli bir ölümden kaçamadı. +%o took a sumo punch to the groin.,OB_SUMATIC,,,,%o dostal@[ao_cs] sumo ránu pod pás.,%o fik et sumo-slag i lysken.,%o bekam einen Sumo-Schlag an @[pp_de] empfindlichste Stelle.,,%o prenis sumoan baton en la ingveno.,%o recibió un puñetazo de sumo en la entrepierna.,,%o otti vastaan sumoiskun nivusiin.,%o s'est pris le poing d'un sumo dans l'entrejambe.,%o szerszámjával tompította az jobb horgot.,%o ha ricevuto un soffio su un punto sensibile.,%o は股座にスモウ ハリテを食らった。,%o 은(는) 가랑이 사이에 정권을 찔렀다.,%o nam een sumo punch in de lies.,%o fikk et sumoslag i skrittet.,%o dostał@[ao_pl] cios sumo w pachwinę.,%o tomou um golpe de sumô na virilha.,,%o a primit un pumn sumo în vintre.,Игрок %o отхватил удар в пах от сумоиста.,,%o tog emot ett sumoslag i ljumsken.,%o kasıklarına bir sumo yumruğu yedi. +%o didn't get %p three wishes.,OB_GENIE,,,,%o nedostal@[ao_cs] svá tři přání.,%o fik ikke sine tre ønsker.,%o bekam @[pp_de] drei Wünsche nicht erfüllt.,,%o ne ricevis siajn tri petojn.,%o no recibió sus tres deseos.,,%o ei saanut kolmea toivettaan.,%o n'a pas préparé ses trois vœux.,%o nem teljesítette %p 3 kívánságát.,%o non ha soddisfatto i suoi tre desideri.,%o は %p に三願を望まなかった。,%o 은(는) 세 가지 소원을 빌 수 없었다.,%o kreeg niet drie wensen.,%o fikk ikke oppfylt tre ønsker.,%o nie dostał@[ao_pl] swoich trzech życzeń.,%o não concedeu três desejos a %p.,,%o nu a putut să-și pună cele trei dorințe.,Игрок %o не загадает трёх желаний.,,%o fick inte sina tre önskningar uppfyllda.,%o üç dileğini yerine getiremedi. +%o tried to pet a mine.,OB_MINE,,,,%o se pokusil@[ao_cs] pohladit minu.,%o forsøgte at kæle for en mine.,"%o versuchte, eine Mine zu streicheln.",,%o provis glatumi minon.,%o intentó acariciar una mina.,,%o yritti silittää miinaa.,%o a essayé de caresser une mine.,%o meg akart simogatni egy aranyos aknát.,%o ha provato ad accarezzare una mina.,%o は地雷を愛撫しようとした。,%o 은(는) 기뢰와 친구가 되고 싶었다.,%o probeerde een mijn te aaien.,%o prøvde å klappe en mine.,%o próbował@[ao_pl] pogłaskać minę.,%o tentou fazer carinho numa mina.,,%o a încercat să mângâie o mină.,Игрок %o хотел погладить мину.,,%o försökte klappa en mina.,%o bir mayını sevmeye çalıştı. +%o took %k's Bruce Lee fu-kick to the face.,OB_MPKICK,,,,%o dostal@[ao_cs] kopanec do obličeje od kung-fuistou %k.,%o fik %ks Bruce Lee fu-kick i ansigtet.,%o bekam einen Bruce-Lee-Fußtritt ins Gesicht.,,%o ricevis la Bruce Lee piedbaton de %k en sia vizaĝo.,%o se comió una patada de kung-fu a lo Bruce Lee de %k.,,%k potkaisi %o raukkaa päin naamaa Bruce Leen kung fu-tyyliin.,%o s'est mangé@[e_fr] un coup de pied à la Bruce Lee de la part de %k.,%o arccal vette le %k pörgőrugását.,%o ha un calcio in faccia.,%o の顔に %k のブルースリーキックを当てた。,%o 은(는) %k 의 거침없는 하이킥을 받았다.,%o nam %k's Bruce Lee fu-kick in het gezicht.,%o tok %ks Bruce Lee fu-kick i ansiktet.,%o dostał@[ao_pl] kopniakiem w stylu Bruce'a Lee od %k.,%o tomou uma voadora de %k na cara.,,%o a primit un șut în stil Bruce Lee.,"Игрок %o отхватил от игрока %k удар в лицо, достойный Брюса Ли.",,%o tog emot %ks Bruce Lee fu-kick i ansiktet.,"%o, %k tarafından tekmelendi." +%o fell apart via %k's shocking revelation.,OB_MPREZNATOR,,,,%o se rozpadl@[ao_cs] šokujícím odhalením hráče %k.,%o faldt fra hinanden via %ks chokerende åbenbaring.,%o erhielt eine schockierende Enthüllung von %k.,,%o diseriĝis pro la ŝokantan revelaĉio de %k.,%o cayó ante la revelación chocante de %k.,,%o romahti käyttäjän %k sähköistävästä ilmestyksestä.,%o a été témoin de la révélation choquante de %k.,%k megrázó élmányben részesítette %o-t.,%o ricevette una scioccante rivelazione da %k.,%o は %k の衝撃的な啓示によりバラバラになった。,%o 은(는) %k 이(가) 선사한 전기 찜질을 맛봤다.,%o viel uit elkaar via %k's schokkende onthulling.,%o falt fra hverandre via %ks sjokkerende åpenbaring.,%o rozpadł@[ao_pl] się pod wpływem szokującego objawienia %k.,%o ficou arrasad@[ao_ptb] pela revelação chocante de %p.,,%o s-a făcut praf la revelația șocantă a lui %k.,Игрок %o шокирован откровениями %k.,,%o föll sönder genom %ks chockerande avslöjande.,"%o, %k tarafından kızartıldı." +%o took a double-dose of %k's punishment.,OB_MPXPISTOL,,,,%o dostal@[ao_cs] dvojitou dávku potrestání hráče %k.,%o fik en dobbeltdosis af %ks straf.,%o bekam eine doppelte Dosis von %ks Bestrafung.,,%o duoble dozis la puno de %k.,%o recibió una doble dosis del castigo de %k.,,%o otti tupla-annoksen käyttäjän %k kuritusta.,%o a mangé une double dose de la furie de %k.,%o ólom túladagolást kapott %k-tól.,%o ha ottenuto una doppia dose della punizione di %k.,%o は %k の懲罰を二度受けた。,%o 은(는) %k 의 2총신 사격을 받았다.,%o nam een dubbele dosis van %k's straf.,%o tok en dobbel dose av %ks straff.,%o dostał@[ao_pl] podwójną dawkę kary %k.,%o tomou uma dose dupla da punição de %k.,,%o a luat o doză dublă din pedeapsa lui %k.,Игрок %o принял двойную дозу возмездия от %k.,,%o fick en dubbel dos av %ks straff.,"%o, %k tarafından cezalandırıldı." +%o was shut down by %k's shock-stick.,OB_MPTAZER,,,,%o byl@[ao_cs] vypnut@[ao_cs] šokádou hráče %k.,%o blev lukket ned af %ks chok-stick.,%o wurde von %ks Schockstab ausgeschaltet.,,%o estis malŝaltita de la ŝokbateno de %k.,%o fue noquead@[ao_esp] por la vara eléctrica de %k.,,%o joutui käyttäjän %k sähkökepin sammuttamaksi.,%o s'est fait mettre K.O par le bâton électrique de %k.,"%o-t sokkolta a hír, hogy %k-t megölte.",%o è stato spento dalla bacchetta di %k.,%o は %k のショックスティックでシャットダウンした。,%o 은(는) %k 의 무력행사에 아예 포기했다.,%o werd uitgeschakeld door %k's schokstick.,%o ble stengt av %ks sjokkpinne.,%o został@[ao_pl] wyłączon@[adj_pl] przez szokującą pałkę %k.,%o foi desligado pelo espeto chocante de %k.,,%o a fost dezactivat de arma cu șocuri a lui %k.,Игрок %o выведен из строя электродубинкой %k.,,%o blev nedsläckt av %ks chockpinne.,"%o, %k tarafından kapatıldı." +%o got a face-full of %k's ice-cold wrath.,OB_MPCRYOGUN,,,,%o se zabořil@[ao_cs] do mrazivého hněvu hráče %k.,%o fik et ansigt fuld af %ks iskolde vrede.,%o bekam eine Ladung von %ks eiskaltem Zorn ins Gesicht.,,%o ricevis la glacie malvarman koleregon de %k.,%o recibió la ira gélida de %k en toda la cara.,,%o sai saamansa täyteen käyttäjän %k jääkylmää vihaa.,%o s'est fait congeler la figure par la colère glaciale de %k.,%k jégre tette %o-t,%o ha un carico di freddo gelido di %k in faccia.,%o は %k の冷めた表情で凍った。,%o 은(는) %k 덕분에 맛있게 냉동 보존되었다.,%o kreeg een gezicht vol met %k's ijskoude toorn.,%o fikk ansiktet fullt av %ks iskalde vrede.,%o dostał@[ao_pl] wielką dawkę mroźnego gniewu %k.,%o tomou um gelo de %k. ,,%o a simțit din plin furia rece a lui %k.,Игрок %o столкнулся с ледяной ненавистью %k.,,%o fick en ansiktsfyllning av %ks iskalla vrede.,"%o, %k tarafından donduruldu." +"%o was drilled full of holes by %k, gangsta-style.",OB_MPUZI,,,,%o byl@[ao_cs] prostřílen@[ao_cs] skrz na skrz gangsterem %k.,"%o blev boret fuld af huller af %k, på gangsta-stil.",%o wurde von %k im Gangsta-Stil perforiert.,,"%o estis borita truplena de %k, ganstere.","%o fue acribillad@[ao_esp] por %k, al estilo gangster.",,%k porasi %o raukan täyteen reikiä gangsta-tyyliin.,"%o s'est fait perforer dans tous les sens par %k, Gangsta style.",%o gengszter stílusban sajttá lyuggatta %k,%o è stato perforato da %k in stile gangsta.,%o はギャングの様な %k に蜂の巣にされた。,%o 은(는) %k 이(가) 선사한 갱스터 스타일 난사를 막지 못했다.,"%o werd vol gaten geboord met %k, in gangsta-stijl.","%o ble boret full av hull av %k, i gangsta-stil.",%o został@[ao_pl] podziurawion@[adj_pl] przez %k niczym gangster.,%o tomou pipoco de %k.,,%o a fost umplut de găuri în stil mafiot de către %k.,Игрок %o покрылся дырками после гангста-стрельбы игрока %k.,,"%o borrades full av hål av %k, på gangstermanér.","%o, %k tarafından gangsta tarzı delik deşik edildi." +%o ate %k's photon bomb.,OB_MPZOOKA,,,,%o sežral@[ao_cs] fotonovou bombu hráče %k.,%o spiste %ks fotobombe.,%o nahm %ks Photonenbombe.,,%o manĝis la fotonbombon de %k.,%o se comió la bomba de fotones de %k.,,%o söi käyttäjän %k fotonipommin.,%o a bouffé la bombe photonique de %k.,%o megette %k foton bombáját,%o ha preso la bomba fotonica di %k.,%o は %k のフォトンボムを食らった。,%o 은(는) %k 의 광자탄을 봤는데도 피하지 못했다.,%o at %o %k's fotonbom.,%o spiste %ks fotonbombe.,%o zjadł@[ao_pl] fotonową bombę %k.,%o engoliu a bomba de fótons de %k.,,%o a mâncat bomba fotonică a lui %k.,Игрок %o съел фотонную бомбу %k.,,%o åt upp %ks fotobomb.,"%o, %k tarafından atomize edildi." +%o was reduced to a neat pile of photons by %k.,OB_MPZ_SPLASH,,,,%o byl@[ao_cs] zredukován@[ao_cs] na hromádku fotonů hráčem %k.,%o blev reduceret til en ordentlig bunke fotoner af %k.,%o wurde von %k zu einem Haufen Photonen verarbeitet.,,%o estis reduktita en ordeman amason da fotonoj de %k.,%o fue reducid@[ao_esp] a una pila de fotones por %k.,,%k redusoi %o raukan sieväksi fotonipinoksi.,%o s'est fait@[e_fr] réduire en une jolie pile de photons par %k.,%o-ból csak egy marokni fotont hagyott hátra %k,%o è stato elaborato da %k in un mucchio di fotoni.,%o は %k によって蛍光灯にされた。,%o 은(는) %k 의 광자력을 탐냈다. 죽기 전까지는.,%o werd gereduceerd tot een nette stapel fotonen met %k.,%o ble redusert til en pen haug med fotoner av %k.,%o został@[ao_pl] zredukowan@[adj_pl] do maleńkiej kupki fotonów przez %k.,%o foi reduzido à uma bela pilha de fótons por %k.,,%o a fost transformat într-o grămadă simpatică de fotoni de către %k.,Игрок %o был разложен игроком %k в аккуратную кучку фотонов.,,%o reducerades till en prydlig hög fotoner av %k.,"%o, %k tarafından düzgün bir foton yığınına indirgendi." +%o was reduced to antimatter by %k.,OB_MPANTIGUN,"Physically this is utter nonsense, of course.",,,%o byl@[ao_cs] zredukován@[ao_cs] na antihmotu hráčem %k.,%o blev reduceret til antimaterie af %k.,%o wurde von %k zu Antimaterie reduziert.,,%o estis reduktita en antimaterion de %k.,%o fue reducid@[ao_esp] a antimateria por %k.,,%k redusoi %o raukan antimateriaksi..,%o s'est fait inverser les atomes par %k.,%k antianyaggá lőttte %o-t,%o è stato ridotto all'antimateria da %k,%o は %k のにより反物質に変換された。,%o 은(는) %k 의 반물질의 힘에 의해 소멸되었다.,%o werd gereduceerd tot antimaterie met %k.,%o ble redusert til antimaterie av %k.,%o został@[ao_pl] zredukowan@[adj_pl] do antymaterii przez %k.,%o foi transformado em antimatéria por %k.,,%o a fost transformat în antimaterie de către %k.,Игрок %o был разложен игроком %k до антиматерии.,,%o reducerades till antimateria av %k.,"%o, %k tarafından atomlara indirgendi." +%o swallowed %k's nuke.,OB_MPNUKE,,,,%o spolkl@[ao_cs] atomovku hráče %k.,%o slugte %ks atombombe.,%o verschluckte sich an %ks Atomrakete.,,%o glutis la nuklean bombon de %k.,%o se tragó la bomba atómica de %k.,,%o nieli käyttäjän %k ydinpommin.,%o s'est pris@[e_fr] la bombe thermonucléaire de %k dans la figure.,%o megette %k atombomáját,%o soffocò sul missile nucleare di %k.,%o は %k の核を飲み干した。,%o 은(는) %k 덕분에 하늘을 뚫을 버섯구름이 되었다.,%o geslikt %o nuke %k's nuke.,%o svelget %ks atombombe.,%o połkn@[irreg_2_pl] atomówkę %k.,%o engoliu o míssil núclear de %k.,,%o a înghițit proiectilul lui %k.,Игрок %o проглотил ядерный заряд %k.,,%o svalde %ks atombomb.,"%o, %k tarafından bombalandı." +%o went nuclear from %k's mass destruction spree.,OB_MPNUKESPLASH,,,,%o si zkrátil@[ao_cs] svůj poločas rozpadu při zabijačce hráče %k.,%o blev atomvåben af %ks masseødelæggelser.,%o wurde von %ks Massenzerstörungsaktion verstrahlt.,,%o iĝis nuklea pro la amasdetruado de %k.,%o se volvió radioactiv@[ao_esp] por la racha de destrucción masiva de %k.,,%o muuttui radioaktiiviseksi käyttäjän %k massatuhoputken takia.,%o s'est fait@[e_fr] irradier par la folie destructrice de %k.,%o felrobbant az idegtől amikor meglátta %k bombáját,%o fu irradiato dall'azione di distruzione di massa di %k.,%o は %k の虐殺ごっこの犠牲者になった。,%o 은(는) %k 의 핵실험에 참여했다.,%o werd nucleair van de massavernietigingswoede van %k's massavernietigingswoede.,%o ble nuklear av %ks masseødeleggelse.,%o został@[ao_pl] napromieniowan@[adj_pl] przez masową destrukcję %k.,%o virou picadinho radioativo por causa da destruição em massa causada por %k.,,%o a devenit radioactiv în urma distrugerii în masă a lui %k.,Игрок %o светится в темноте от оружия массового поражения %k.,,%o blev kärnvapenfri av %ks massförstörelse.,"%o, %k tarafından bombalandı." +%o was turned inside-out by %k.,OB_MPTELEFRAG,,,,%o byl@[ao_cs] obrácen@[ao_cs] naruby hráčem %k.,%o blev vendt ud og ind af %k.,%o wurde von %k zerfetzt.,,La interno de %o estis eksteriga de %k.,%o fue puest@[ao_esp] del revés por %k.,,%k käänsi %o raukan nurinpäin.,%o s'est fait@[e_fr] inverser par %k.,%k kifordította %o-t,%o fu fatto a pezzi da %k,%o は %k に裏返しにされた。,%o 은(는) %k 에 의해 자신이 분해되는 꼴을 못 봤다.,%o werd binnenstebuiten gekeerd met %k.,%o ble snudd på hodet av %k.,%o został@[ao_pl] wywrócon@[adj_pl] na lewą stronę przez %k.,%o foi virad@[ao_ptb] ao avesso por %k.,,%o a fost întors pe dos de către %k.,Игрок %o вывернут наизнанку игроком %k.,,%o vändes ut och in av %k.,"%o, %k tarafından parçalandı." +%o's atomic structure was split apart.,OB_MONTELEFRAG,,,,Struktura atomů hráče %o se rozpadla.,%os atomstruktur blev splittet op.,%os Atomstruktur wurde vernichtet.,,La atoma strukturo de %o estis disfendita.,%o fue desintegrad@[ao_esp] al nivel atómico.,,%o raukan atomirakenne hajosi.,%o s'est fait@[e_fr] désassembler au niveau atomique.,%o atomjaira esett szét,La struttura atomica di %o fu distrutta.,%o の原子構造は分解された。,%o 의 원자 마디마디가 흩어졌다.,De atoomstructuur van %o werd gesplitst.,%o's atomstruktur ble splittet fra hverandre.,Atomy %o zostały od siebie oddzielone.,A estrutura atômica de %o foi separada.,,Structura atomică a lui %o a fost spulberată.,Атомная структура игрока %o разрушена.,,%os atomstruktur splittrades.,%o atomik düzeyde parçalara ayrıldı. +%o spontaneously expired.,OB_DEFAULT,,,,%o samovolně vypršel@[ao_cs].,%o udåndede spontant.,%o hörte spontan auf zu existieren.,,%o spontane finiĝis.,%o tuvo una muerte espontánea.,,%o spontaanisti kupsahti.,%o a spontanément expiré.,%o hirtelenjében elérte a lejárati időt,%o ha smesso spontaneamente di esistere.,%o の有効期限が自発的に切れた,%o 은(는) 파란만장하게 사라졌다.,%o is spontaan verlopen.,%o gikk spontant til grunne.,%o spontanicznie umarł@[ao_pl].,%o pereceu expontâneamente.,,%o a expirat în mod spontan.,Время игрока %o неожиданно вышло.,,%o dog spontant.,%o kendiliğinden öldü. +You grab a NUKER! Suck on this!,GOTNUKER,,,,Sebral@[ao_cs] jsi ATOMOVKÁTOR! Pojď na to!,Du tager en NUKER! Sut på den!,Ein NUKER! Verschluck dich daran.,,Vi prenis NUKER! Jen havu!,¡Has pillado un NUKER! ¡Chupaos esa!,¡Has recogido un NUKER! ¡Chúpate esa!,%Kahmaiset YDÄRIN! Ime tätä!,Vous découvrez le NUKER! Ca va en chier!,Meglelted a NUKER-t! Ezt kapd ki!,Prendi un NUKER! Succhia su questo!,NUEKR を奪った! 覚悟しろ!,누커 획득! 한바탕 쓸어볼까!,Je pakt een NUKER! Zuig hier maar aan!,Ta en NUKER! Sug på denne!,Podniosłeś ATOMÓWKĘ! Ssijcie to!,Você pegou um NUKER! Chupa essa manga!,,Ai ridicat Lansatorul Nuclear! Ia de-aici!,Заполучен ЯДЕРНЫЙ ГРАНАТОМЁТ! Отсосите!,,Du tar en NUKER! Sug på den här!,Sen bir NÜKER kap! Bunu em! +You got an UZI!!,GOTUZI,,,,Získal@[ao_cs] jsi UZI!,Du har en UZI!!,UZI genommen!,,Vi prenis UZI!!,¡¡Has obtenido una UZI!!,,Sait UZIn!!,Vous chopez un UZI!,Meglelted az UZI-t!,Hai un UZI !!,UZI をゲットした!!,우지 기관단총 획득!,Je hebt een UZI!!,Du har en UZI!,Zdobyłeś UZI!!,Você pegou uma UZI!!,,Ai ridicat un UZI!!,Заполучен УЗИ!!,,Du har en UZI!!,Bir UZI'n var! +A HOIG Reznator - FRY some butt,GOTREZNATOR,,,,HOIG Reznátor - pár jich upeč,En HOIG Reznator - Fritér noget røv,Ein HOIG Reznator.,,HOIG-Reznilo - FRITU pugon!,Un Reznator HOIG. ¡Hora de freir traseros!,,HOIG-reznaattori - KÄRISTÄ takamuksia,"Un Reznator HOIG, allez frire du monde!",Egy HOIG Reznator - okozz pár megrázó élményt,Un Reignator HOIG - friggere un po 'di carne,HOIGレジネイター - ぶっ潰してやれ,HOIG 전자무력기 획득! 전기 통구이를 만들자고!,Een HOIG Reznator - FRY sommige kont,En HOIG Reznator - FRY litt rumpe!,Reznator HOIG - skop trochę tyłków,Um Reznador HOIG - Hora de fritar,,Un Rezonator HOIG - Arde-i!,ХОЙГ Резнатор,,En HOIG Reznator - FRY några rumpor,Bir HOIG Reznator - Biraz kıç kızartın +You got a Photon 'Zooka!,GOTPHOTONZOOKA,,,,Sebral@[ao_cs] jsi Fotonovou bazuku!,Du har en Photon 'Zooka!,Photonen-'zooka genommen!,,Vi prenis Fotonbazukon!,¡Has obtenido un Bazooka de Fotones!,,Sait fotonisingon!,Vous récupérez un Bazooka Photonique!,Meglelted a Foton Ágyút!,Hai un cannone Photon!,フォトン'ゾーカ をゲットした!,광자 바주카 획득!,Je hebt een Photon 'Zooka!,Du har en Photon 'Zooka!,Zdobyłeś Fotonozukę!,Você pegou uma Bazuca de Fótons!,,Ai ridicat o Bazooka Fotonică!,Заполучена фотон-базука!,,Du har en Photon 'Zooka'!,Bir Foton 'Zooka'n var! +You carry a Big Stick!,GOTBIGSTICK,,,,Nosíš velkou bouchačku!,Du har en Big Stick!,Du trägst einen langen Stock.,,Vi portas grandan bastonon!,¡Llevas un Gran Palo!,,Kannat isoa keppiä!,Vous avez un gros bâton!,Nagy bottal jársz öcsém!,Porti un grosso bastone!,ビッグスティック を手に取った!,반물질 봉 획득!,Je draagt een Big Stick!,Du har en Big Stick!,Podnosisz Wielką Pałkę!,Você pegou um Grande Bastão!,,Ai ridicat un Băț Lung!,Заполучена длинная палка!,,Du har en stor käpp!,Büyük bir sopa taşıyorsun! +You got a Tazer!!,GOTTAZER,,,,Získal@[ao_cs] jsi tazer!,Du har en Tazer!!,Tazer genommen!,,Vi prenis Elektropafilon!!,¡¡Has obtenido un Taser!!,,Sait etälamauttimen!!,Vous trouvez un Taser!,Meglelted a Sokkolót!,Hai un Taser !!,テイザー をゲットした!,테이져 획득!,Je hebt een Tazer!!,Du har en Tazer!,Zdobyłeś Tazer!!,Você pegou um Tazer!!,,Ai ridicat un Taser!!,Заполучен тазер!,,Du har en Tazer!,Bir Tazer'ın var!! +You grab a Cryogun! FREEZE!,GOTCRYOGUN,,,,Sebral@[ao_cs] jsi krypušku! ANI SE NEHNI!,Du har en Cryogun! Frys!,Cryowaffe genommen! GEFRIER!,,Vi prenis Kriogenikpafilon! FROSTIĜU!,¡Has pillado un Criogenizador!! ¡Todos quietos!,¡Has recogido un Criogenizador!! ¡Quietos todos!,Kahmaiset kryopyssyn! PYSÄHDY!,Vous prenez un Cryogun! On s'arrête!,Felkapod a Cryogun-t! Induljon a fagyasztás!,Prendi un Cryogun! CONGELARE!,クライォガン を奪った! フリーズ!,크라이로건 획득! 그대로 멈춰라!,Je pakt een Cryogun! FREEZE!,Du har en Cryogun! FREEZE!,Podniosłeś Zamrażarkę! STAĆ!,Você pegou uma Cryogun! FICA FRIO AÍ!,,Ai ridicat o Crio-armă! ÎNGHEAȚĂ!,Заполучена замораживающая пушка! НИ С МЕСТА!,,Du har en Cryogun! FRIAS!,Bir Cryogun al! DONDUR! +You grab some rounds!,GOTROUNDS,,,,Sebral@[ao_cs] jsi nějaké náboje!,Du tager nogle patroner!,Munition genommen.,,Vi prenis kuglojn!,¡Has pillado unas balas!,¡Has recogido unas balas!,Kahmaiset patruunoita!,Vous prenez des balles!,Felkapsz pár lőszert!,Prendi delle munizioni!,幾つかのラウンド を奪った!,권총 탄약을 주웠다!,Je pakt wat rondes!,Du tar noen runder!,Podniosłeś trochę naboi!,Você pegou munição!,,Ai ridicat niște muniție!,Заполучена обойма патронов!,,Du tar några patroner!,Biraz mermi al! +You grab a case of rounds!,GOTROUNDSCASE,,,,Sebral@[ao_cs] jsi krabici nábojů!,Du tager en kasse med patroner!,Munitionskiste genommen.,,Vi prenis skatolon da kugloj!,¡Has pillado una caja de balas!,¡Has recogido una caja de balas!,Kahmaiset patruunalaatikon!,Vous prenez une bôite de balles!,Felkapsz egy doboz lőszert!,Prendi un caso di munizioni!,ケースのラウンド を奪った!,권총 탄약 상자를 주웠다!,Je pakt een kist met rondes!,Du tar en kasse med patroner!,Podniosłeś skrzynkę naboi!,Você pegou uma caixa de munição!,,Ai ridicat un cartuș de muniție!,Заполучена коробка патронов!,,Du tar en låda med patroner!,Bir kutu mermi al! +You grab a Torpedo!,GOTTORPEDO,"Was ""grap"" for some reason.",,,Sebral@[ao_cs] jsi torpédo!,Du tager en Torpedo!,Torpedo genommen.,,Vi prenis Torpedon!,¡Has pillado un torpedo!,¡Has recogido un torpedo!,Kahmaiset torpedon!,Vous prenez une torpille!,Felkapsz egy Torpedót!,Prendi un siluro!,トルペード を奪った!,광자탄을 주웠다!,Je pakt een Torpedo!,Du tar en Torpedo!,Podniosłeś Torpedę!,Você pegou um Torpedo!,,Ai ridicat o Torpilă!,Заполучена торпеда!,,Du tar en torped!,Bir Torpido al! +You grab a case of Torpedos!,GOTTORPEDOS,,,,Sebral@[ao_cs] jsi krabici torpéd!,Du tager en kasse med torpedoer!,Torpedokiste genommen.,,Vi prenis skatolon da Torpedoj!,¡Has pillado una caja de torpedos!,¡Has recogido una caja de torpedos!,Kahmaiset torpedolaatikon!,Vous prenez une bôite de torpilles!,Felkapsz egy doboz Torpedót!,Prendi un caso di siluri!,トルペードのケース を奪った!,광자탄 무더기를 주웠다!,Je pakt een kist Torpedo's!,Du tar en kasse med torpedoer!,Podniosłeś skrzynkę Torped!,Você pegou uma caixa de Torpedos!,,Ai ridicat o cutie de Torpile!,Заполучен ящик торпед!,,Du tar en låda med torpeder!,Bir kasa Torpido al! +You grab a molecule module!,GOTMOLECULES,,,,Sebral@[ao_cs] jsi molekulový modul!,Du tager et molekylmodul!,Molekülmodul genommen,,Vi prenis molekulmodulon!,¡Has pillado un módulo molecular!,¡Has recogido un módulo molecular!,Kahmaiset molekyylimoduulin!,Vous prenez un module moléculaire!,Felkapsz egy molekula modult!,Prendi un modulo molecolare!,モーレキュールモヂュール を奪った!,분자 모듈을 주웠다!,Je pakt een molecuulmodule!,Du tar en molekylmodul!,Podniosłeś molekularny moduł!,Você pegou um módulo molecular!,,Ai ridicat un modul molecular!,Заполучен молекулярный модуль!,,Du tar en molekylmodul!,Bir molekül modülü kap! +You grab a tank full of molecules!,GOTMOLECULESTANK,,,,Sebral@[ao_cs] jsi sud plný molekul!,Du tager en tank fuld af molekyler!,Tank mit Molekülmodulen genommen.,,Vi prenis reservujon da molekulojn!,¡Has pillado un tanque lleno de moléculas!,¡Has recogido un tanque lleno de moléculas!,Kahmaiset tankin täynnä molekyylejä!,Vous prenez un réservoir de molécules!,Felkapsz egy teli tank molekulát!,Prendi un serbatoio pieno di molecole!,タンク満タンのモーレキュール を奪った!,분자 탱크를 주웠다!,Je pakt een tank vol met moleculen!,Du tar en tank full av molekyler!,Podniosłeś zbiornik pełen molekuł!,Você pegou um tanque cheio de moléculas!,,Ai ridicat un rezervor plin cu molecule!,Заполучен контейнер с молекулами!,,Du tar en tank full av molekyler!,Moleküllerle dolu bir tank al! +You grab some Cartridges!,GOTCARTRIDGES,,,,Sebral@[ao_cs] jsi nějaké kazety!,Du tager nogle patroner!,Magazin genommen.,,Vi prenis iom da kartoĉoj!,¡Has pillado unos cartuchos!,¡Has recogido unos cartuchos!,Kahmaiset kasetteja!,Vous prenez des cartouches!,Felkapsz pár Töltényt!,Prendi alcune cartucce!,残弾のカートリッジ を奪った!,카트리지 한 줌을 주웠다!,Je pakt een paar patronen!,Du tar noen patroner!,Podniosłeś trochę pocisków!,Você pegou alguns Carregadores!,,Ai ridicat niște Cartușe!,Заполучены картриджи!,,Du tar några patroner!,Fişekleri al! +You grab a case of Cartridges!,GOTCARTRIDGESCASE,,,,Sebral@[ao_cs] jsi krabici kazet!,Du tager en kasse med patroner!,Magazinkiste genommen.,,Vi prenis skatolon da kartoĉoj!,¡Has pillado una caja de cartuchos!,¡Has recogido una caja de cartuchos!,Kahmaiset laatikollisen kasetteja!,Vous prenez une bôite de cartouches!,Felkapsz egy doboz Töltényt!,Prendi un caso di cartucce!,カートリッジケース を奪った!,카트리지 박스를 주웠다!,Je pakt een kist patronen!,Du tar en kasse med patroner!,Podniosłeś skrzynkę pocisków!,Você pegou uma caixa de Carregadores!,,Ai ridicat o cutie de Cartușe!,Заполучен ящик картриджей!,,Du tar en låda med patroner!,Bir kutu fişek al! +You grab a Valise stuffed with goods!,GOTVALISE,,,,Sebral@[ao_cs] jsi kufr plný munice!,Du tager en kuffert fyldt med varer!,Munitionstasche genommen.,,Vi prenis valizon plenan de municiojn!,¡Has pillado una maleta llena de equipamiento!,¡Has recogido una maleta llena de equipamiento!,Kahmaiset laukullisen täynnä tavaraa!,Vous récupérez une valise pleine d'équipement!,Felkapsz egy Poggyásznyi Muníciót!,Prendi una Valigia piena di merci!,代物を詰めたバリス を奪った!,탄약이 든 서류 가방을 주웠다!,Je pakt een Valise gevuld met goederen!,Du tar en koffert fylt med varer!,Podniosłeś Walizkę z wieloma dobrami!,Você pegou uma Mala cheia de equipamento!,,Ai ridicat o Valiză plină cu bunătăți!,Заполучена полная сумка боеприпасов!,,Du tar en valise fylld med varor!,İçi mal dolu bir valiz al! +Force Field!,GOTFORCEFIELD,,,,Silové pole!,Kraftfelt!,Kraftfeld!,,Fortkampo!,¡Campo de fuerza!,,Voimakenttä!,Champ de force!,Erőtér!,Campo di forza!,フォースフィールド!,방어막!,Krachtveld!,Kraftfelt!,Pole Siłowe!,Campo de Força!,,Câmp de Forță!,Силовое поле!,,Kraftfält!,Güç Alanı! +007Microtel,GOTMICROTEL,,,,,,,,007 Microtel!,Microtel 007,,,007 Microtel,,,007マイクロテル,007마이크로텔 근력 향상 칩!,,,,,,Microtel 007,Микрочип 007,,,007Microtel +You are EnK Blind!,GOTENKBLIND,,,,Jsi EnK-slep@[adj_cs]!,Du er EnK Blind!,Du bist EnK-blind!,,Vi estas ENK-Blinda,¡Tienes Ceguera EnK!,,Olet EnK-sokea!,Vous êtes aveugle à l'EnK!,EnK védett lettél!,Sei EnK-cieco!,EnKブラインドみてえだ!,EnK 투명 위장 장치!,Jij bent EnK Blind!,Du er EnK Blind!,Jesteś oślepiony przez EnK!,Você está vendado por EnK!,,Acum ești nedetectabil pentru Enk!,У тебя EnK-видимость!,,Du är EnK Blind!,Sen EnK Blind'sın! +Vulcan rubber Boots!,GOTRUBBERBOOTS,,,,Gumové boty!,Vulkaniske gummistøvler!,Gummistiefel!,,Vulkanaj Kauŭĉukaj Botoj!,¡Botas de goma vulcanizada!,,Vulkanoidut kumisaappaat!,Bottes en caoutchouc vulcanisé!,Vulkanizált gumi talp!,Stivali di gomma vulcanica!,バルカンラバーブーツ!,벌컨 방화 부츠!,Vulcan rubber Laarzen!,Vulcan gummistøvler!,Gumowe Buty Vulcan!,Botas Vulcanizadas!,,Bocanci din cauciuc Vulcan!,Резиновые сапоги!,,Vulkaniska gummistövlar!,Vulcan lastik botları! +SI Array mapping!,GOTSIARRAY,,,,Mapa pole SI!,SI Array kortlægning!,SI-Feld Karte!,,SI-matric-mapado!,¡Mapeado de Tabla SI!,,SI-kenttäkartta!,Carte du tableau SI!,SI pálya Felderítő!,Mappatura di array SI!,SIアーレイ マッピング!,Si 어레이 지도!,,SI Array kartlegging!,Mapa Pola SI!,Mapeamento por Campo de SI!,,Hartă SI compilată!,Составлена карта SI-массива!,,SI Array kartläggning!,SI Dizi eşlemesi! +Infrared Visor!,GOTINFRARED,,,,Infračervené brýle!,Infrarødt visir!,Infrarotbrille!,,Transruĝa Viziero!,¡Visor infrarrojo!,,Infrapunavisiiri!,Viseur infrarouge!,Infravörös Sisak!,Visore a infrarossi!,赤外線バイザー!,적외선 바이져!,Infrarood vizier!,Infrarødt visir!,Wizjer na Podczerwień!,Visor Infravermelho!,,Vedere Infraroșie!,Инфракрасный визор!,,Infrarött visir!,Kızılötesi Vizör! +"Breathe deep, Inhaler!",GOTINHALER,,,,"Pořádně se nadechni, inhalátor!","Træk vejret dybt, Inhalator!","Atme tief, Inhalierer!",,"Spiru profunde, inhalo!","¡Un inhalador, inspira fuerte!",,"Hengitä syvään, inhalaattori!","Respire, inhaleur!","Mély lélegzet, Inhaláló!","Respirare profondamente, inalatore!",深呼吸だ、インヘイラー!,각성제를 주웠다. 잘 들이마셔!,"Adem diep in, inhalator!","Pust dypt, Inhalator!",Weź głęboki wdech! Inhalator!,Inalador! Respira fundo!,,"Inspiră adânc, Inhalatorule!",Ингалятор! Вдыхай глубже!,,"Andas djupt, Inhalator!","Derin nefes al, Inhaler!" +A dose of Hydergine from a Hypo saves you!,GOTHYPONEED,,,,Jsi zachráněn@[ao_cs] dávkou Hyderginu z Hypa!,En dosis Hydergine fra en Hypo redder dig!,Eine Dosis Hydergine rettet dich!,,,¡Una dosis de Hydergina te salva la vida!,,Hyderginepiikkiannos pelastaa sinut!,Une bonne dose d'hydergine vous sauve la vie!,Egy adag Hydergine megmenti az irhád!,Una dose di Hydergine di un Hypo ti salva!,ハイポで ヒデルギン をキメた!,하이포의 하이데르진이 당신을 살렸다!,Een dosis Hydergine van een Hypo redt je!,En dose Hydergine fra en Hypo redder deg!,Dawka Hyderginy z Hypo ratuje cię!,Uma dose de hidergina do Hypo para te salvar!,,O doză de Hidrogine dintr-o seringă te salvează!,Доза Редергина из шприца спасла тебя!,,En dos Hydergine från en Hypo räddar dig!,Hypo'dan bir doz Hydergine seni kurtarır! +You grab a Hypo!,GOTHYPO,,,,Sebral@[ao_cs] jsi Hypo!,Du tager en Hypo!,Hypo!,,Vi prenis Injektilon!,¡Has pillado una jeringa hipodérmica!,,Kahmaiset piikin!,Vous prenez une seringue!,Felkapsz egy Hypo-t!,Prendi un Hypo!,ハイポ を奪った!,하이포를 주웠다!,Je pakt een Hypo!,Du tar en Hypo!,Podniosłeś Hypo!,Você pegou um Hypo!,,Ai ridicat o Seringă!,Заполучен шприц!,,Du tar en Hypo!,Bir Hypo kaptın! +You found a KeyCard!,GOTKEYCARD,,,,Nalezl@[ao_cs] jsi přístupovou kartu!,Du har fundet et Nøglekort!,Schlüsselkarte gefunden!,,Vi trovis Ŝlosilkarton!,¡Has encontrado una Tarjeta Llave!,,Löysit avainkortin!,Vous trouvez une clé magnétique!,Leltél egy Kulcskártyát!,Hai trovato una chiave magnetica!,キーカードを見つけた!,키 카드를 찾았다!,U heeft een sleutelkaart gevonden!,Du har funnet et nøkkelkort!,Znalazłeś Kartę Dostępu!,Você achou um Cartão de Passe!,,Ai găsit un Card-Cheie!,Найдена ключ-карта!,,Du hittade ett nyckelkort!,Bir Anahtar Kart buldun! +You found a C-Key!,GOTCKEY,,,,Nalezl@[ao_cs] jsi kyberklíč!,Du har fundet en C-nøgle!,C-Schlüssel gefunden!,,Vi trovis C-Ŝlosilon!,¡Has encontrado una Llave-C!,,Löysit C-avaimen!,Vous trouvez une C-Clé!,Leltél egy C-Kulcsot!,Hai trovato una chiave C!,C-keyを見つけた!,C-키를 찾았다!,Je hebt een C-sleutel gevonden!,Du har funnet en C-nøkkel!,Znalazłeś Klucz C!,Você achou uma Chave-C!,,Ai găsit o Cheie-C!,Найден C-образный ключ!,,Du hittade en C-nyckel!,Bir C-Anahtarı buldun! +You found a Password!,GOTPASSWORD,,,,Nalezl@[ao_cs] jsi heslo!,Du har fundet et kodeord!,Passwort gefunden!,,Vi trovis Pasvorton!,¡Has encontrado una Contraseña!,,Löysit salasanan!,Vous trouvez un mot de passe!,Leltél egy Jelszót!,Hai trovato una parola d'ordine!,パスワードを見つけた!,암호를 찾았다!,U heeft een wachtwoord gevonden!,Du har funnet et passord!,Znalazłeś Hasło!,Você achou uma Senha!,,Ai găsit o Parolă!,Найден пароль!,,Du hittade ett lösenord!,Bir Şifre buldun! +You found a blue Z-Key!,GOTBLUEZKEY,,,,Nalezl@[ao_cs] jsi modrý Z-klíč!,Du fandt en blå Z-nøgle!,Blauen Z-Schlüssel gefunden!,,Vi trovis bluan Z-ŝlosilon!,¡Has encontrado una Llave-Z azul!,,Löysit sinisen Z-avaimen!,Vous trouvez une Z-Clé bleue!,Leltél egy kék Z-Kulcsot!,Hai trovato una chiave Z blu!,ブルー Z-Key を見つけた!,청색 Z-키를 찾았다!,Je hebt een blauwe Z-sleutel gevonden!,Du har funnet en blå Z-nøkkel!,Znalazłeś niebieski Klucz Z!,Você achou uma Chave-Z azul!,,Ai găsit o Z-Cheie albastră!,Найден синий Z-образный ключ!,,Du hittade en blå Z-nyckel!,Mavi bir Z-Anahtarı buldun! +You found a yellow Z-Key!,GOTYELWZKEY,,,,Nalezl@[ao_cs] jsi žlutý Z-klíč!,Du fandt en gul Z-nøgle!,Gelben Z-Schlüssel gefunden!,,Vi trovis flavan Z-ŝlosilon!,¡Has encontrado una Llave-Z amarilla!,,Löysit keltaisen Z-avaimen!,Vous trouvez une Z-Clé jaune!,Leltél egy sárga Z-Kulcsot!,Hai trovato una chiave Z gialla!,イエローZ-Key を見つけた!,황색 Z-키를 찾았다!,Je hebt een gele Z-sleutel gevonden!,Du har funnet en gul Z-nøkkel!,Znalazłeś żółty Klucz Z!,Você achou uma Chave-Z amarela!,,Ai găsit o Z-Cheie galbenă!,Найден жёлтый Z-образный ключ!,,Du hittade en gul Z-nyckel!,Sarı bir Z-Anahtarı buldun! +You found a red Z-Key!,GOTREDZKEY,,,,Nalezl@[ao_cs] jsi červený Z-klíč!,Du fandt en rød Z-nøgle!,Roten Z-Schlüssel gefunden!,,Vi trovis ruĝan Z-ŝlosilon!,¡Has encontrado una Llave-Z roja!,,Löysit punaisen Z-avaimen!,Vous trouvez une Z-Clé rouge!,Leltél egy piros Z-Kulcsot!,Hai trovato una chiave Z rossa!,レッド Z-Key を見つけた!,적색 Z-키를 찾았다!,Je hebt een rode Z-sleutel gevonden!,Du har funnet en rød Z-nøkkel!,Znalazłeś czerwony Klucz Z!,Você achou uma Chave-Z vermelha!,,Ai găsit o Z-Cheie roșie!,Найден красный Z-образный ключ!,,Du hittade en röd Z-nyckel!,Kırmızı bir Z-Anahtarı buldun! +Body Armor!,GOTBODYARMOR,,,,Brnění!,Kropsrustning!,Körperpanzerung!,,Kiraso!,¡Armadura!,,Suojavarustus!,Armure!,Testpáncél!,Giubbotti antiproiettile!,ボディーアーマー!,강화복!,Kogelvrije vesten!,Skuddsikker vest!,Pancerz!,Colete a Prova de Balas!,,Armură de Corp!,Бронежилет!,,Kroppspansar!,Vücut Zırhı! +Centrophenoxine,GOTCENTROPHENOXINE,,,,Centrofenoxin,Centrophenoxine,,,Centrofenoksino!,¡Centrofenoxina!,,Sentrofenoksiinia,Centrophenoxine!,,,セントロフェノキシン!,메클로페녹세이트!,,Centrophenoxine,Centrofenoxina,Centrofenoxina,,Centrofenoxine,Центрофеноксин,,, +You grab a Kevlar vest!,GOTKEVLARVEST,,,,Sebral@[ao_cs] jsi kevlarovou vestu!,Du får fat i en kevlarvest!,Kevlarweste!,,Vi prenis kevlaran veŝton!,¡Has pillado un traje de Kevlar!,¡Has recogido un traje de Kevlar!,Kahmaiset Kevlar-liivit!,Veste en Kevlar!,Felkapsz egy Golyóálló Mellényt!,Prendi una maglia di kevlar!,ケブラーベスト を奪った!,방탄복을 주웠다!,Pak een Kevlar vest!,Du tar en Kevlar-vest!,Podniosłeś kamizelkę kuloodporną!,Você pegou um Colete de Kevlar!,,Ai ridicat o vestă din Kevlar!,Заполучен кевларовый жилет!,,Du tar en kevlarväst!,Kevlar yeleği al! +You grab Super Kevlar vest!,GOTSKEVLARVEST,,,,Sebral@[ao_cs] jsi superkevlarovou vestu!,Du tager Super Kevlar vest!,Super-Kevlarweste!,,Vi prenis superan kevlaran veŝton!,¡Has pillado un supertraje de Kevlar!,¡Has recogido un supertraje de Kevlar!,Kahmaiset Superkevlar-liivit!,Super Veste en Kevlar!,Felkapsz egy Szuper Golyóálló Mellényt!,Prendi una maglia super kevlar!,スーパーケブラーベスト を奪った!,중 방탄복을 주웠다!,Je pakt een Super Kevlar vest!,Du tar en Super Kevlar vest!,Podniosłeś superkamizelkę kuloodporną!,Você pegou um Super Colete de Kevlar!,,Ai ridicat o Super Vestă din Kevlar!,Заполучен усиленный кевларовый жилет!,,Du tar tag i Super Kevlar väst!,Süper Kevlar yeleği al! +You grab a MicroKit!,GOTMICROKIT,,,,Sebral@[ao_cs] jsi mikrosadu!,Du får fat i et MicroKit!,MicroKit genommen!,,Vi prenis Kompleteton!,¡Has pillado un MicroKit!,¡Has recogido un MicroKit!,Kahmaiset Microkitin!,Microkit!,Felkapsz egy Mikorkit-et!,Prendi un MicroKit!,マイクロキット を奪った!,마이크로킷을 주웠다!,Je pakt een MicroKit!,Du tar en MicroKit!,Podniosłeś MikroZestaw!,Você pegou um MicroKit!,,Ai ridicat un MicroKit!,Заполучена мини-аптечка!,,Du tar en MicroKit!,Bir MicroKit al! +You grab a Dampener!,GOTDAMPENER,,,,Sebral@[ao_cs] jsi tlumič!,Du får fat i en Dampener!,Dämpfer genommen!,,Vi prenis Dampilon!,¡Has pillado un Amortiguador!,¡Has recogido un Amortiguador!,Kahmaiset vaimentimen!,Amortisseur!,Felkapsz egy Tompítót!,Prendi un antivento!,ダンプナー を奪った!,완충 장치를 주웠다!,Je pakt een Demper!,Du tar en Dampener!,Podniosłeś Tłumik!,Você pegou um Amortecedor!,,Ai ridicat un Amortizor!,Заполучен глушитель!,,Du tar en Dämpare!,Bir Sönümleyici al! +You need a C-Key to access this item!,PD_CKEY,,,,K přístupu potřebuješ kyberklíč!,Du skal bruge en C-nøgle for at få adgang til dette objekt!,Du brauchst einen C-Schlüssel um das hier zu bedienen.,,Vi bezonas C-ŝlosilon por aliri ĉi tiun objekton!,¡Necesitas una Llave-C para acceder a este objeto!,,Tarvitset C-avaimen saadaksesi pääsyn tähän kohteeseen!,Il vous faut une C-Clé pour accéder à cet objet!,Egy C-Kulcs szükséges a hozzáféréshez!,Hai bisogno di una chiave C per accedere a questo oggetto!,アクセスには C-key が必要だ!,C-키가 있어야 작동이 가능하다!,Je hebt een C-sleutel nodig om toegang te krijgen tot dit item!,Du trenger en C-nøkkel for å få tilgang til dette elementet!,Potrzebujesz Klucza C by uruchomić ten przedmiot.,Você precisa de uma Chave-C para acessar!,,Ai nevoie de o Cheie-C pentru a accesa acest obiect!,"Нет доступа, нужен C-образный ключ!",,Du behöver en C-nyckel för att få tillgång till detta objekt!,Bu eşyaya erişmek için bir C-Anahtarına ihtiyacın var! +You need a KeyCard to access this item!,PD_KEYCARD,,,,K přístupu potřebuješ přístupovou kartu!,Du skal bruge et Nøglekort for at få adgang til dette objekt!,Du brauchst eine Schlüsselkarte um das hier zu bedienen.,,Vi bezonas Slosilkarton por aliri ĉi tiun objekton!,¡Necesitas una Tarjeta Llave para acceder a este objeto!,,Tarvitset avainkortin saadaksesi pääsyn tähän kohteeseen!,Il vous faut une carte magnétique pour accéder à cet objet!,Egy kulcskártya szükséges a hozzáféréshez!,Hai bisogno di una chiave magnetica per accedere a questo oggetto!,アクセスには キーカード が必要だ!,키 카드가 있어야 작동이 가능하다!,U heeft een sleutelkaart nodig om toegang te krijgen tot dit item!,Du trenger et nøkkelkort for å få tilgang til dette elementet!,Potrzebujesz Karty Dostępu by uruchomić ten przedmiot!,Você precisa de uma Chave de Passe para acessar!,,Ai nevoie de un Card-Cheie pentru a accesa acest obiect!,"Нет доступа, нужен ключ-карта!",,Du behöver ett KeyCard för att komma åt det här objektet!,Bu öğeye erişmek için bir KeyCard'a ihtiyacınız var! +You need a Password to access this item!,PD_PASSWORD,,,,K přístupu potřebuješ heslo!,Du skal bruge et kodeord for at få adgang til dette objekt!,Du brauchst eine Passwort um das hier zu bedienen.,,Vi bezonas Pasvorton por aliri ĉi tiun objekton!,¡Necesitas una Contraseña para acceder a este objeto!,,Tarvitset salasanan saadaksesi pääsyn tähän kohteeseen!,Il vous faut un mot de passe pour accéder à cet objet!,Egy Jelszó szükséges a hozzáféréshez!,Hai bisogno di una parola d'ordine per accedere a questo oggetto!,アクセスには パスワード が必要だ!,암호를 입력해야 작동이 가능하다!,Je hebt een wachtwoord nodig om toegang te krijgen tot dit item!,Du trenger et passord for å få tilgang til dette elementet!,Potrzebujesz Hasła by uruchomić ten przedmiot!,Você precisa de uma Senha para acessar!,,Ai nevoie de Parolă pentru a accesa acest obiect!,"Нет доступа, нужен пароль!",,Du behöver ett lösenord för att få tillgång till detta objekt!,Bu öğeye erişmek için bir Şifreye ihtiyacınız var! +You need a Blue Z-Key to make this work,PD_BLUEZKEY,,,,Tohle bude fungovat jen s modrým Z-klíčem.,Du skal bruge en blå Z-nøgle for at få dette til at fungere!,Du brauchst einen blauen Z-Schlüssel um das hier zu bedienen.,,Vi bezonas Bluan Z-ŝlosilon por funkciigi ĉi tiun!,¡Necesitas una Llave-Z azul para hacer funcionar esto!,,Tarvitset sinisen Z-avaimen saadaksesi tämän toimimaan!,Il vous faut une Z-Clé bleue pour faire fonctionner cela.,Egy Kék Z-Kulcs szükséges a hozzáféréshez!,Hai bisogno di una chiave Z blu per accedere a questo oggetto!,アクセスには ブルーZ-key が必要だ!,청색 Z-키가 있어야 작동이 가능하다!,Je hebt een blauwe Z-sleutel nodig om dit te laten werken.,Du trenger en blå Z-nøkkel for å få dette til å fungere!,Potrzebujesz Niebieskiego Klucza Z by zadziałało!,Você precisa de uma Chave-Z azul para fazer isto funcionar!,,Ai nevoie de o Cheie-Z albastră pentru a face asta să funcționeze!,"Не работает, нужен синий Z-образный ключ!",,Du behöver en blå Z-nyckel för att få detta att fungera.,Bunu çalıştırmak için bir Mavi Z-Anahtarına ihtiyacınız var +You need a Red Z-Key to make this work!,PD_REDZKEY,,,,Tohle bude fungovat jen s červeným Z-klíčem.,Du skal bruge en rød Z-nøgle for at få dette til at fungere!,Du brauchst einen roten Z-Schlüssel um das hier zu bedienen.,,Vi bezonas Ruĝan Z-ŝlosilon por funkciigi ĉi tiun!,¡Necesitas una Llave-Z roja para hacer funcionar esto!,,Tarvitset punaisen Z-avaimen saadaksesi tämän toimimaan!,Il vous faut une Z-Clé rouge pour faire fonctionner cela.,Egy Piros Z-Kulcs szükséges a hozzáféréshez!,Hai bisogno di una chiave Z gialla per accedere a questo oggetto!,アクセスには レッドZ-key が必要だ!,적색 Z-키가 있어야 작동이 가능하다!,Je hebt een rode Z-sleutel nodig om dit te laten werken!,Du trenger en rød Z-nøkkel for å få dette til å fungere!,Potrzebujesz Czerwonego Klucza Z by zadziałało!,Você precisa de uma Chave-Z vermelha para fazer isto funcionar!,,Ai nevoie de o Cheie-Z roșie pentru a face asta să funcționeze!,"Не работает, нужен красный Z-образный ключ!",,Du behöver en röd Z-nyckel för att detta ska fungera!,Bunu çalıştırmak için Kırmızı Z-Anahtarına ihtiyacınız var! +You need a Yellow Z-Key to make this work!,PD_YELWZKEY,,,,Tohle bude fungovat jen se žlutým Z-klíčem.,Du skal bruge en gul Z-nøgle for at få dette til at fungere!,Du brauchst einen gelben Z-Schlüssel um das hier zu bedienen.,,Vi bezonas Flavan Z-ŝlosilon por funkciigi ĉi tiun!,¡Necesitas una Llave-Z amarilla para hacer funcionar esto!,,Tarvitset keltaisen Z-avaimen saadaksesi tämän toimimaan!,Il vous faut une Z-Clé jaune pour faire fonctionner cela.,Egy Sárga Z-Kulcs szükséges a hozzáféréshez!,Hai bisogno di una chiave Z rossa per accedere a questo oggetto!,アクセスには イエローZ-key が必要だ!,황색 Z-키가 있어야 작동이 가능하다!,Je hebt een gele Z-sleutel nodig om dit te laten werken!,Du trenger en gul Z-nøkkel for å få dette til å fungere!,Potrzebujesz Żółtego Klucza Z by zadziałało!,Você precisa de uma Chave-Z amarela para fazer isto funcionar!,,Ai nevoie de o Cheie-Z galbenă pentru a face asta să funcționeze!,"Не работает, нужен жёлтый Z-образный ключ!",,Du behöver en gul Z-nyckel för att detta ska fungera!,Bunu yapmak için Sarı Z-Anahtarına ihtiyacın var! "Twenty mill in gold doesn't seem worth all this aggravation, does it, hacker? Makes the pen look like a freakin' picnic! @@ -367,7 +367,13 @@ mașină în spațiul cibernetic, feliezi niște mutanți, задницы и выберись из этой чёртовой передряги! -",,"Yirmi milyon altın bu kadar +",,"Tjugo miljoner i guld verkar inte vara värt allt detta besvär, eller hur, hackare? Det får pennan att se ut som en jäkla picknick! + +Röviga biomutationer och dina medmänniskor hängde från taket som matsäckar. + +Vad i helvete är det här för GENIE? Som ingen dator du någonsin hackat! + +Det är bäst att du hittar nästa terminal, tar en tur genom c-rymden, skär några mutantrumpor och sticker härifrån!","Yirmi milyon altın bu kadar zahmete değmez, değil mi hacker? Hapishane piknik yeri gibi görünüyor! @@ -677,7 +683,15 @@ spatele...","Где все люди?! вокруг не осталось никого живого. Передай эти сведения подкомитету. И будь осторожен... -",,"Bütün insanlar nerede?! +",,"Var är alla människor?! + +Paris är en spökstad, om man inte anser att mutantbaggar är enastående medborgare. + +Du har stött på blodigt motstånd. De här insekterna kan verkligen slåss! Tur för dig att de inte är de ljusaste verandalamporna i kvarteret. + +Men ni har fått fram en del av den information som underkommittén vill ha. Och det är otäckt! + +Mänskliga neurala vätskor matar dessa insekter! Inte undra på att grannskapet börjar bli glesare. Rapportera till underkommittén. Och se upp för din rygg...","Bütün insanlar nerede?! Paris hayalet bir şehir, tabii mutant böcekleri seçkin @@ -920,7 +934,19 @@ Iar aurul? La naiba cu el, asta e din partea casei. денег. .....(продолжение следует)..... -",,"Bildiğiniz medeniyet artık yok! +",,"Civilisationen som du kände till den är nada! + +Inga vänner, ingen familj. Inga fler människor. +Inte normala människor i alla fall. + +Bara en sak kvar... GENIE! +Och om du måste gå till slutet av +universum kommer du att hitta dess muterade rumpa! +För nu är du förbannad! + +Och guldet? Det här är gratis. + +.....(fortsättning).....","Bildiğiniz medeniyet artık yok! Arkadaş yok, aile yok. Artık insan yok. @@ -1085,7 +1111,15 @@ Ești... singur.","Ты выжил! Ты... остался один. -",,"Yaşıyorsun! +",,"Du lever! + +Vad är oddsen, hackare?! +Det är en dator som är full av buggar. + +Du kan inte nå underkommittén, vilket betyder att den har blivit komprometterad. + + +Du... är ensam.","Yaşıyorsun! Bu ihtimaller nedir, hacker?! Çünkü böceklerle dolu. @@ -1096,50 +1130,52 @@ anlamına geliyor. Sen... yalnızsın." -,,,,,,,,,,,,,,,,,,,,,,,,,, -GenEmp Corp.,TXT_HACXMAP01,,,,Sídlo GenEmp,,,,Korporacio GenEmp,,,GenEmp-yhtiö,,,,GenEmpコーポ,ZONE 1: 진엠프 주식회사 본부,,,,,,Corporația GenEmp,Корпорация ГенИмп,,GenEmp Corp. -Tunnel Town,TXT_HACXMAP02,,,,Tunelové město,tunnelbyen,Tunnelstadt,,Tunelo Urbeto,Pueblo Túnel,,Tunnelikaupunki,Ville Tunnel,Kanális Község,Città del tunnel,トンネル タウン,ZONE 2: 터널 도시,Tunnelstad,Tunnelbyen,Miasto Tuneli,Cidade Túnel,,Orașul Subteran,Подземный город,,Tünel Kasabası -Lava Annex,TXT_HACXMAP03,,,,Lávová přístavba,,Lavaanbau,,Lafa Anekso,Anexo de Lava,,Laavalaajennus,Annexe de Lave,Láva Szárny,Annesso di lava,ラバ アネックス,ZONE 3: 용암 속 건물,Lava Bijlage,Lava Vedlegg,Aneks Lawy,Anexo de Lava,,Anexa de Lavă,Лавовая электростанция,,Lava Annex -Alcatraz,TXT_HACXMAP04,,,,,,,,Alkatrazo,,,,,Alkatraz,,アルカトラズ,ZONE 4: 알카트라즈,,,,,,,Алькатрас,,Alcatraz -Cyber Circus,TXT_HACXMAP05,,,,Kybercirkus,Cybercirkus,Cyberzirkus,,Cibernetika Cirko,Circo Cibernético,,Kybersirkus,,Kiber Cirkusz,Circo Cyber,サイバーサークル,ZONE 5: 사이버 서커스,,Cyber sirkus,Cyber Cyrk,Circo Cibernético,,Circ Cibernetic,Киберцирк,,Siber Sirk -Digi-Ota,TXT_HACXMAP06,,,,,,,,,,,,,,,デジ - オータ,ZONE 6: 디지-오타,,,,,,,Диджитал-Ота,,Digi-Ota -The Great Wall,TXT_HACXMAP07,,,,Velká zeď,Den store mur,Die große Mauer,,La Grandega Muro,La Gran Muralla,,Suuri muuri,La grande Muraille,A Nagy Fal,Il grande muro,ザ - グレート ウォール,ZONE 7: 만리장성,De grote muur,Den kinesiske mur,Wielka Ściana,A Grande Muralha,,Marele Zid,Великая стена,,Büyük Duvar -Garden of Delights,TXT_HACXMAP08,,,,Zahrada rozkoše,Dejlighedernes have,Lustgarten,,Ĝardeno de Ĝuoj,Jardin de las Delicias,,Nautintojen puutarha,Jardin de Délices,A Gyönyör Kertje,Giardino delle delizie,ガーデン オブ デライト,ZONE 8: 쾌락의 정원,Tuin van lekkernijen,Gledenes hage,Ogród Zachwytu,Jardim dos Prazeres,,Grădina Plăcerilor,Сад наслаждений,,Lezzet Bahçesi -Hidden Fortress,TXT_HACXMAP09,,,,Skrytá pevnost,Skjulte fæstning,Versteckte Festung,,Kaŝita Fortreso,Fortaleza Oculta,,Salainen linnoitus,Forteresse Secrète,Eltitkolt Erőd,Fortezza nascosta,ヒドゥン フォートレス,ZONE 9: 숨겨진 요새,Verborgen Vesting,Skjult festning,Ukryta Forteca,Fortaleza Oculta,,Fortăreața Ascunsă,Скрытая крепость,,Gizli Kale -Anarchist Dream,TXT_HACXMAP10,,,,Anarchistův sen,Anarkistisk drøm,Anarchistentraum,,Anarkia Sonĝo,Sueño Anarquista,,Anarkistin unelma,Rève d'Anarchiste,Anarchista Álom,Sogno anarchico,アナーキスト ドリーム,ZONE 10: 아나키스트의 꿈,Anarchistische droom,Anarkistisk drøm,Sen Anarchisty,Sonho Anarquista,,Vis Anarhist,Анархистская утопия,,Anarşist Rüya -Notus Us!,TXT_HACXMAP11,,,,,,,,,¡Notus Us!,,Pane merkille mEIdät!,,,,ワレラノ ノータス,ZONE 11: 노터스 어스!,,,,,,Nu ne vor uita!,Нас не забудут!,,Notus Us! -Gothik Gauntlet,TXT_HACXMAP12,,,,Gotický trest,,,,Gotika Spaliro,Guantelete Gótiko,,Goottinen kujanjuoksu,Gantelet Gothik,Gótikus Vesszőfutás,,ゴシック ガントレット,ZONE 12: 고딕풍 결투장,,Gothik hanske,Gotycka Rękawica,Punição Gótika,,Mănușa Gotică,Готическая перчатка,,Gothik Gauntlet -The Sewers,TXT_HACXMAP13,,,,Kanály,Kloakkerne,Die Kanäle,,La Kanaloj,Las Alcantarillas,,Viemärit,Les Egouts,A Kanális,Le fogne,ザ・サワー,ZONE 13: 하수 처리장,De Riolen,Kloakken,Ścieki,Os Esgotos,,Canale,Канализация,,Kanalizasyonlar -Trode Wars,TXT_HACXMAP14,,,,Válka elektrod,,Elektrodenkrieg,,Milito de Elektrodoj,Guerra de Electrodos,,Trodisodat,Guerre des Trodes,Trode Háborúk,Guerra degli elettrodi,トレード ウォーズ,ZONE 14: 전격의 전쟁,Trode oorlogen,Trode-krigene,Wojna Elektrod,Guerra de Eletrodos,,Război cu Electrozi,Торговые войны,,Elektrot Savaşları -Twilight of Enk's,TXT_HACXMAP15,,,,Soumrak EnKu,Enk's tusmørke,Zwielicht von EnK,,Krespusko de EnK-oj,Crepúsculo de los Enk,,EnKin illankoitto,Crépuscule des Enk's,Enk Alkonya,Crepuscolo di Enk,Enkタチ ノ トワイライト,ZONE 15: 전자황혼,Schemering van Enk's,Skumring av Enk's,Zmierzch Enk,Crepúsculo de Enk's,,Amurgul lui Enk,Сумерки EnK,,Enk'in Alacakaranlığı -Protean Cybex,TXT_HACXMAP16,,,,Proměnlivý Cybex,,Proteanischer Cybex,,Protea Cybex,Cybex Protéico,,Muuntuvainen Kybex,,,,プロテアン サイベックス,ZONE 16: 변화무쌍한 사이벡스,Proteanische Cybex,,Zmienny Cybex,Cybex Proteano,,Cybex Caleidoscopic,Многоликий Сайбэкс,,Protean Cybex -River of Blood,TXT_HACXMAP17,,,,Řeka krve,Blodets flod,Blutfluss,,Rivero de Sango,Río de Sangre,,Verivirta,Rivière de Sang,Vérfolyó,Fiume di sangue,リバー オブ ブラッド,ZONE 17: 학살의 강,Rivier van bloed,Blodets elv,Rzeka Krwi,Rio de Sangue,,Râu de Sânge,Река крови,,Kan Nehri -Bizarro,TXT_HACXMAP18,,,,Bizár,,,,,,,,,,,ビザロ,ZONE 18: 요상한 곳,,,,,,,Бизарро,,Bizarro -The War Rooms,TXT_HACXMAP19,,,,Válečné kabinety,Krigsrummene,Kriegsräume,,La Militĉambroj,Las Salas de Guerra,,Sotahuoneet,La Salle des Commandes,Háborús Terem,Le stanze della guerra,ザ・ウォー ルーム,ZONE 19: 전략 회의실,De oorlogskamers,Krigsrommene,Pokoje Wojny,As Salas de Comando,,Camerele de Control,Генеральный штаб,,Savaş Odaları -Intruder Alert!,TXT_HACXMAP20,,,,"Pozor, vetřelec!",Advarsel om ubudne gæster!,Eindringlingsalarm!,,Alarmo pri Entrudanto!,¡Alerta de Intruso!,,Murtohälytys!,"Alerte, Intrus!",Betolakodó Riadó!,Allarme intruso!,シンニュウシャ アリ!,ZONE 20: 칩입자 경보!,Inbreker alarm!,Inntrengeralarm!,Alarm Intruz!,Alerta de Intruso!,,Alertă Intrus!,Тревога! Нарушитель!,,Hırsız Alarmı! -Desiccant Room,TXT_HACXMAP31,,,,Sušící místnost,Tørremiddel-rummet,Trocknungsraum,,Ĉambro de Elsekigo,Sala del Desecante,,Kuivatesali,Salle du Desiccant,Szárító Szoba,Stanza disseccante,ダスキン ルーム,ZONE 31: 건조한 곳,Drogende kamer,Tørkerommet,Śluza Osuszająca,Sala do Dessecante,,Camera Desicanților,Сушильная комната,,Kurutucu Oda +,,,,,,,,,,,,,,,,,,,,,,,,,,, +GenEmp Corp.,TXT_HACXMAP01,,,,Sídlo GenEmp,,,,Korporacio GenEmp,,,GenEmp-yhtiö,,,,GenEmpコーポ,ZONE 1: 진엠프 주식회사 본부,,,,,,Corporația GenEmp,Корпорация «ГенИмп»,,, +Tunnel Town,TXT_HACXMAP02,,,,Tunelové město,tunnelbyen,Tunnelstadt,,Tunelo Urbeto,Pueblo Túnel,,Tunnelikaupunki,Ville Tunnel,Kanális Község,Città del tunnel,トンネル タウン,ZONE 2: 터널 도시,Tunnelstad,Tunnelbyen,Miasto Tuneli,Cidade Túnel,,Orașul Subteran,Подземный город,,Tunnelstaden,Tünel Kasabası +Lava Annex,TXT_HACXMAP03,,,,Lávová přístavba,,Lavaanbau,,Lafa Anekso,Anexo de Lava,,Laavalaajennus,Annexe de Lave,Láva Szárny,Annesso di lava,ラバ アネックス,ZONE 3: 용암 속 건물,Lava Bijlage,Lava Vedlegg,Aneks Lawy,Anexo de Lava,,Anexa de Lavă,Лавовая электростанция,,, +Alcatraz,TXT_HACXMAP04,,,,,,,,Alkatrazo,,,,,Alkatraz,,アルカトラズ,ZONE 4: 알카트라즈,,,,,,,Алькатрас,,, +Cyber Circus,TXT_HACXMAP05,,,,Kybercirkus,Cybercirkus,Cyberzirkus,,Cibernetika Cirko,Circo Cibernético,,Kybersirkus,,Kiber Cirkusz,Circo Cyber,サイバーサークル,ZONE 5: 사이버 서커스,,Cyber sirkus,Cyber Cyrk,Circo Cibernético,,Circ Cibernetic,Киберцирк,,Cybercirkus,Siber Sirk +Digi-Ota,TXT_HACXMAP06,,,,,,,,,,,,,,,デジ - オータ,ZONE 6: 디지-오타,,,,,,,Диджитал-Ота,,, +The Great Wall,TXT_HACXMAP07,,,,Velká zeď,Den store mur,Die große Mauer,,La Grandega Muro,La Gran Muralla,,Suuri muuri,La grande Muraille,A Nagy Fal,Il grande muro,ザ - グレート ウォール,ZONE 7: 만리장성,De grote muur,Den kinesiske mur,Wielka Ściana,A Grande Muralha,,Marele Zid,Великая стена,,Den stora muren,Büyük Duvar +Garden of Delights,TXT_HACXMAP08,,,,Zahrada rozkoše,Dejlighedernes have,Lustgarten,,Ĝardeno de Ĝuoj,Jardin de las Delicias,,Nautintojen puutarha,Jardin de Délices,A Gyönyör Kertje,Giardino delle delizie,ガーデン オブ デライト,ZONE 8: 쾌락의 정원,Tuin van lekkernijen,Gledenes hage,Ogród Zachwytu,Jardim dos Prazeres,,Grădina Plăcerilor,Сад наслаждений,,Lustarnas trädgård,Lezzet Bahçesi +Hidden Fortress,TXT_HACXMAP09,,,,Skrytá pevnost,Skjulte fæstning,Versteckte Festung,,Kaŝita Fortreso,Fortaleza Oculta,,Salainen linnoitus,Forteresse Secrète,Eltitkolt Erőd,Fortezza nascosta,ヒドゥン フォートレス,ZONE 9: 숨겨진 요새,Verborgen Vesting,Skjult festning,Ukryta Forteca,Fortaleza Oculta,,Fortăreața Ascunsă,Скрытая крепость,,Dolda fästningen,Gizli Kale +Anarchist Dream,TXT_HACXMAP10,,,,Anarchistův sen,Anarkistisk drøm,Anarchistentraum,,Anarkia Sonĝo,Sueño Anarquista,,Anarkistin unelma,Rève d'Anarchiste,Anarchista Álom,Sogno anarchico,アナーキスト ドリーム,ZONE 10: 아나키스트의 꿈,Anarchistische droom,Anarkistisk drøm,Sen Anarchisty,Sonho Anarquista,,Vis Anarhist,Анархистская утопия,,Anarkistisk dröm,Anarşist Rüya +Notus Us!,TXT_HACXMAP11,,,,,,,,,¡Notus Us!,,Pane merkille mEIdät!,,,,ワレラノ ノータス,ZONE 11: 노터스 어스!,,,,,,Nu ne vor uita!,Нас не забудут!,,, +Gothik Gauntlet,TXT_HACXMAP12,,,,Gotický trest,,,,Gotika Spaliro,Guantelete Gótiko,,Goottinen kujanjuoksu,Gantelet Gothik,Gótikus Vesszőfutás,,ゴシック ガントレット,ZONE 12: 고딕풍 결투장,,Gothik hanske,Gotycka Rękawica,Punição Gótika,,Mănușa Gotică,Готическая перчатка,,Gotik Utmaning, +The Sewers,TXT_HACXMAP13,,,,Kanály,Kloakkerne,Die Kanäle,,La Kanaloj,Las Alcantarillas,,Viemärit,Les Egouts,A Kanális,Le fogne,ザ・サワー,ZONE 13: 하수 처리장,De Riolen,Kloakken,Ścieki,Os Esgotos,,Canale,Канализация,,Avloppen,Kanalizasyonlar +Trode Wars,TXT_HACXMAP14,,,,Válka elektrod,,Elektrodenkrieg,,Milito de Elektrodoj,Guerra de Electrodos,,Trodisodat,Guerre des Trodes,Trode Háborúk,Guerra degli elettrodi,トレード ウォーズ,ZONE 14: 전격의 전쟁,Trode oorlogen,Trode-krigene,Wojna Elektrod,Guerra de Eletrodos,,Război cu Electrozi,Торговые войны,,Elektrodekrig,Elektrot Savaşları +Twilight of Enk's,TXT_HACXMAP15,,,,Soumrak EnKu,Enk's tusmørke,Zwielicht von EnK,,Krespusko de EnK-oj,Crepúsculo de los Enk,,EnKin illankoitto,Crépuscule des Enk's,Enk Alkonya,Crepuscolo di Enk,Enkタチ ノ トワイライト,ZONE 15: 전자황혼,Schemering van Enk's,Skumring av Enk's,Zmierzch Enk,Crepúsculo de Enk's,,Amurgul lui Enk,Сумерки EnK,,Skymning av Enks,Enk'in Alacakaranlığı +Protean Cybex,TXT_HACXMAP16,,,,Proměnlivý Cybex,,Proteanischer Cybex,,Protea Cybex,Cybex Proteico,,Muuntuvainen Kybex,,,,プロテアン サイベックス,ZONE 16: 변화무쌍한 사이벡스,Proteanische Cybex,,Zmienny Cybex,Cybex Proteano,,Cybex Caleidoscopic,Многоликий Сайбэкс,,Proteanska Cybexen, +River of Blood,TXT_HACXMAP17,,,,Řeka krve,Blodets flod,Blutfluss,,Rivero de Sango,Río de Sangre,,Verivirta,Rivière de Sang,Vérfolyó,Fiume di sangue,リバー オブ ブラッド,ZONE 17: 학살의 강,Rivier van bloed,Blodets elv,Rzeka Krwi,Rio de Sangue,,Râu de Sânge,Река крови,,Blodets flod,Kan Nehri +Bizarro,TXT_HACXMAP18,,,,Bizár,,,,,,,,,,,ビザロ,ZONE 18: 요상한 곳,,,,,,,Бизарро,,, +The War Rooms,TXT_HACXMAP19,,,,Válečné kabinety,Krigsrummene,Kriegsräume,,La Militĉambroj,Las Salas de Guerra,,Sotahuoneet,La Salle des Commandes,Háborús Terem,Le stanze della guerra,ザ・ウォー ルーム,ZONE 19: 전략 회의실,De oorlogskamers,Krigsrommene,Pokoje Wojny,As Salas de Comando,,Camerele de Control,Генеральный штаб,,Krigsrummen,Savaş Odaları +Intruder Alert!,TXT_HACXMAP20,,,,"Pozor, vetřelec!",Advarsel om ubudne gæster!,Eindringlingsalarm!,,Alarmo pri Entrudanto!,¡Alerta de Intruso!,,Murtohälytys!,"Alerte, Intrus!",Betolakodó Riadó!,Allarme intruso!,シンニュウシャ アリ!,ZONE 20: 칩입자 경보!,Inbreker alarm!,Inntrengeralarm!,Alarm Intruz!,Alerta de Intruso!,,Alertă Intrus!,Тревога! Нарушитель!,,Inkräktare!,Hırsız Alarmı! +Desiccant Room,TXT_HACXMAP31,,,,Sušící místnost,Tørremiddel-rummet,Trocknungsraum,,Ĉambro de Elsekigo,Sala del Desecante,,Kuivatesali,Salle du Desiccant,Szárító Szoba,Stanza disseccante,ダスキン ルーム,ZONE 31: 건조한 곳,Drogende kamer,Tørkerommet,Śluza Osuszająca,Sala do Dessecante,,Camera Desicanților,Сушильная комната,,Sorptionsmedel rum,Kurutucu Oda "Now Arriving At... ",STSTR_CLEV,,,,Příjezd do...,"Nu ankommer vi til... ",Angekommen bei...,,Nun Ĝisirante...,Ahora llegando a...,,Seuraavana...,On arrive maintenant à:,Következő állomás...,Arrivando a...,今到着した...,이동하는 중...,Nu we aankomen bij....,"Nå ankommer... -",Wchodzisz do...,Agora chegando em ...,,Acum Sosiți La...,Переходим на...,,"Şimdi Geliyor... +",Wchodzisz do...,Agora chegando em ...,,Acum Sosiți La...,Переходим на...,,"Nu anländer vi till... +","Şimdi Geliyor... " -...gonna fry your ass!,STSTR_CHOPPERS,"Printed when entering the idchoppers cheat, which gives the player a chainsaw",,,...ti upeče prdel!,...vil stege din røv!,...ich brate deinen Arsch!,,...fritos vian pugon!,... ¡voy a freirte el trasero!,,...kärtsää takalistosi!,...C'est l'heure de botter du cul!,...indulhat a sütögetés!,....ti friggerà il culo!,...ケツまくれ!,... 지져버리겠어!,...gaat je kont bakken!,...kommer til å steke ræva di!,...skopię ci dupę!,...vou fritar teu rabo!,,...te voi prăji!,...поджарит твою задницу!,,...kıçınızı kızartacak! -"inVuln, Str, Inviso, Rad, Allmap, or Lite-amp?",STSTR_BEHOLD,"Hacx's content here was totally useless so it got removed. However, this string has to be defined and minimally altered so that the Dehacked replacement is not being triggered.",,,"nesmrt(V), Síla, nevId, Rad, mApa nebo světLo","inVuln, Str, Inviso, Rad, Allmap, eller Lite-amp?","inVuln, Str, Inviso, Rad, Allmap, oder Lite-amp",,"inVuln, Str, Inviso, Rad, Allmap, aŭ Lite-amp?","inVuln, Str, Inviso, Rad, Allmap, o Lite-amp.",,"haavoittumattomuus (V), voima (S), näkymättömyys (I), koko kartta (A) tai valonvahvistus (L)?","in V ulnérable, S urpuissance, I nvisible, p R otection, c A rte, où L umière?","Sérthet (V), Berz (S), Láthat(i), Sugár(R), Térkép(A), vagy Fény Sisak(L)","inVuln, berSerk, Invisib, tuta anti-Rad, mAppa tutta, o amplif-Luce","V,I,S,R,A,Lのどれだ?","무적, 광전사, 투명, 보호복, 지도, 아니면 바이저?",,"inVuln, Str, Inviso, Rad, Allmap eller Lite-amp?","niezniszczalność (V), siła (S), niewidzialność (I), kombinezon (R), mapa (A) lub gogle noktowizyjne (L)","inVuln., berSerk, Invisib., anti-Rad., mApa completo ou amplificação de Luz",,"inVul, Forță ampl, Invizib, Hartă compl, sau Vedere amplificată?","Бессм. (V), берс. (S), нев. (I), кос. (R), крт. (A), виз (L).","нерањ., снага, невидљ., радиј., мапа или ноћ. визор","inVuln, Str, Inviso, Rad, Allmap veya Lite-amp?" -Let's Get Serious!,STSTR_BEHOLDX,,,,Teď je to vážné!,Lad os blive seriøse!,Es wird ernst!,,Ni Serioziĝu!,¡Vamos en Serio!,,Otetaanpa tosissaan!,Passons aux choses sérieuses!,Ennek fele sem Tréfa!,Prendiamoci sul serio!,マジになったぜ!,철들 때다!,Laten we serieus worden!,La oss bli seriøse!,Bądźmy Poważni!,Agora a Coisa Fica Séria!,,Să Devenim Serioși!,А теперь серьёзно!,,Ciddileşelim! -Cyberslicer Mode ON,STSTR_NCON,,,,Režim kybersekače ZAP,Cyberslicer tilstand TIL,Cyberschnetzelmodus AN,,Cibernetika Tranĉila Reĝimo AKTIVA,Modo Cibercorte ACTIVADO,,Kyberviipaloijatila PÄÄLLÄ,,Kibervágó Mód BE,Modalità Cyberslicer ATTIVADA,サイバースライサーモード オン,전자마귀 모드 ON,Cyberslicer-modus AAN,Cyberslicer-modus PÅ,Tryb Cybercięcia WŁĄCZONY,Cibercortador ATIVADO,,Modul Cibertăietor ACTIVAT,Режим киберрезака ВКЛЮЧЁН,,Siber dilimleyici Modu AÇIK -Cyberslicer Mode OFF,STSTR_NCOFF,,,,Režim kybersekače VYP,Cyberslicer tilstand FRA,Cyberschnetzelmodus AUS,,Cibernetika Tranĉila Reĝimo NEAKTIVA,Modo Cibercorte DESACTIVADO,,Kyberviipaloijatila POIS PÄÄLTÄ,,Kibervágó Mód KI,Modalità Cyberslicer DISATTIVADA,サイバースライサーモード オフ,전자마귀 모드 OFF,Cyberslicer-modus UIT,Cyberslicer-modus AV,Tryb Cybercięcia WYŁĄCZONY,Cibercortador DESATIVADO,,Modul Cibertăietor DEZACTIVAT,Режим киберрезака ОТКЛЮЧЁН,,Siber dilimleyici Modu KAPALI -Selection: Impossible ,STSTR_NOMUS,,,,Nemožný výběr,Forkert valg,Falsche Auswahl,,Elekto: Malebla,Selección impossible,,Valinta ei mahdollinen,Séléction Impossible!,Lehetetlen Kiválasztás,Selezione impossibile,選択: 不可能,선택 불가능,Selectie: Onmogelijk,Valg: Umulig,Niemożliwy wybór,Seleção: Impossível,,Selectare: Imposibilă,Выбор: Невозможен,НЕМОГУЋИ ИЗБОР,Seçim: İmkansız +...gonna fry your ass!,STSTR_CHOPPERS,"Printed when entering the idchoppers cheat, which gives the player a chainsaw",,,...ti upeče prdel!,...vil stege din røv!,...ich brate deinen Arsch!,,...fritos vian pugon!,... ¡voy a freirte el trasero!,,...kärtsää takalistosi!,...C'est l'heure de botter du cul!,...indulhat a sütögetés!,....ti friggerà il culo!,...ケツまくれ!,... 지져버리겠어!,...gaat je kont bakken!,...kommer til å steke ræva di!,...skopię ci dupę!,...vou fritar teu rabo!,,...te voi prăji!,...поджарит твою задницу!,,...kommer att steka ditt arsle!,...kıçınızı kızartacak! +"inVuln, Str, Inviso, Rad, Allmap, or Lite-amp?",STSTR_BEHOLD,"Hacx's content here was totally useless so it got removed. However, this string has to be defined and minimally altered so that the Dehacked replacement is not being triggered.",,,"nesmrt(V), Síla, nevId, Rad, mApa nebo světLo","inVuln, Str, Inviso, Rad, Allmap, eller Lite-amp?","inVuln, Str, Inviso, Rad, Allmap, oder Lite-amp",,"inVuln, Str, Inviso, Rad, Allmap, aŭ Lite-amp?","inVuln, Str, Inviso, Rad, Allmap, o Lite-amp.",,"haavoittumattomuus (V), voima (S), näkymättömyys (I), koko kartta (A) tai valonvahvistus (L)?","in V ulnérable, S urpuissance, I nvisible, p R otection, c A rte, où L umière?","Sérthet (V), Berz (S), Láthat(i), Sugár(R), Térkép(A), vagy Fény Sisak(L)","inVuln, berSerk, Invisib, tuta anti-Rad, mAppa tutta, o amplif-Luce","V,I,S,R,A,Lのどれだ?","무적, 광전사, 투명, 보호복, 지도, 아니면 바이저?",,"inVuln, Str, Inviso, Rad, Allmap eller Lite-amp?","niezniszczalność (V), siła (S), niewidzialność (I), kombinezon (R), mapa (A) lub gogle noktowizyjne (L)","inVuln., berSerk, Invisib., anti-Rad., mApa completo ou amplificação de Luz",,"inVul, Forță ampl, Invizib, Hartă compl, sau Vedere amplificată?","Бессм. (V), берс. (S), нев. (I), кос. (R), крт. (A), виз (L).","нерањ., снага, невидљ., радиј., мапа или ноћ. визор","inVuln, Str, Inviso, Rad, Allmap eller Lite-amp?","inVuln, Str, Inviso, Rad, Allmap veya Lite-amp?" +Let's Get Serious!,STSTR_BEHOLDX,,,,Teď je to vážné!,Lad os blive seriøse!,Es wird ernst!,,Ni Serioziĝu!,¡Vamos en Serio!,,Otetaanpa tosissaan!,Passons aux choses sérieuses!,Ennek fele sem Tréfa!,Prendiamoci sul serio!,マジになったぜ!,철들 때다!,Laten we serieus worden!,La oss bli seriøse!,Bądźmy Poważni!,Agora a Coisa Fica Séria!,,Să Devenim Serioși!,А теперь серьёзно!,,Nu blir det allvar!,Ciddileşelim! +Cyberslicer Mode ON,STSTR_NCON,,,,Režim kybersekače ZAP,Cyberslicer tilstand TIL,Cyberschnetzelmodus AN,,Cibernetika Tranĉila Reĝimo AKTIVA,Modo Cibercorte ACTIVADO,,Kyberviipaloijatila PÄÄLLÄ,,Kibervágó Mód BE,Modalità Cyberslicer ATTIVADA,サイバースライサーモード オン,전자마귀 모드 ON,Cyberslicer-modus AAN,Cyberslicer-modus PÅ,Tryb Cybercięcia WŁĄCZONY,Cibercortador ATIVADO,,Modul Cibertăietor ACTIVAT,Режим киберрезака ВКЛЮЧЁН,,Cyberslicer-läge PÅ,Siber dilimleyici Modu AÇIK +Cyberslicer Mode OFF,STSTR_NCOFF,,,,Režim kybersekače VYP,Cyberslicer tilstand FRA,Cyberschnetzelmodus AUS,,Cibernetika Tranĉila Reĝimo NEAKTIVA,Modo Cibercorte DESACTIVADO,,Kyberviipaloijatila POIS PÄÄLTÄ,,Kibervágó Mód KI,Modalità Cyberslicer DISATTIVADA,サイバースライサーモード オフ,전자마귀 모드 OFF,Cyberslicer-modus UIT,Cyberslicer-modus AV,Tryb Cybercięcia WYŁĄCZONY,Cibercortador DESATIVADO,,Modul Cibertăietor DEZACTIVAT,Режим киберрезака ОТКЛЮЧЁН,,Cyberslicer-läge AV,Siber dilimleyici Modu KAPALI +Selection: Impossible ,STSTR_NOMUS,,,,Nemožný výběr,Forkert valg,Falsche Auswahl,,Elekto: Malebla,Selección impossible,,Valinta ei mahdollinen,Séléction Impossible!,Lehetetlen Kiválasztás,Selezione impossibile,選択: 不可能,선택 불가능,Selectie: Onmogelijk,Valg: Umulig,Niemożliwy wybór,Seleção: Impossível,,Selectare: Imposibilă,Выбор: Невозможен,НЕМОГУЋИ ИЗБОР,Urval: Impossible,Seçim: İmkansız "Pump Up The Volume ",STSTR_MUS,Should probably not be translated...,,,Zesil to!,,,,,,,Nuppi kaakkoon,,Csavard Fel a Szőnyeget,,音量を上げろよ,볼륨을 올려라!,,"Pump opp volumet -",Podkręć Audio,"Som na Caixa, DJ!",,Mărește Volumul,Подкрутите громкость,,"Sesi Yükseltin +",Podkręć Audio,"Som na Caixa, DJ!",,Mărește Volumul,Подкрутите громкость,,"Pumpa upp volymen +","Sesi Yükseltin " -INIT-Twitch n'Kill Mode,STSTR_KFAADDED,,,,Inicializuji režim Twitch and Kill,INIT-Twitch n'Kill Mode,Initiiere Twitch'n Kill-Modus,,INIC-Modo de Tiku kaj Buĉu,INIT-Modo Tirar a Matar,,INIT-Nykäise ja nylje -tila,,Twitch n'Kill Mód Betöltése,Iniziare Twitch n'Kill Mode,INIT-Twitch n'Killモード,때리고 죽이는 모드 ON,,INIT-Twitch n'Kill-modus,Inicjacja Trybu Drżenia I Zabijania,Inicializando Modo Chumbo Grosso,,INIT-Modul Click-și-Elimină,ИНИЦ: режим «Дрожи и убивай»,,INIT-Twitch n'Kill Modu -"So be it, Hacker.",STSTR_FAADDED,,,,"Budiž, Hackeře.","Sådan skal det være, Hacker.","So sei es, Hacker.",,"Tiel estu, Kodrompisto.","Que así sea, Hacker.",,"Olkoon niin, hakkeri.","Qu'il en soit ainsi, hacker.","Akkor hát legyen, hekker.","Cosi' sia, Hacker.",好きにしろ、ハッカー。,"마음대로 해, 해커 양반.","Het zij zo, Hacker.","Som du vil, Hacker.","Niech tak będzie, Hakerze.","Que assim seja, Hacker.",,"Așa să fie, Hacker.","Да будет так, хакер.",,"Öyle olsun, Hacker." -Cyberpotence Mode ON,STSTR_DQDON,,,,Režim kybermoci ZAP,Cyberpotens-tilstand TIL,Cyberpotenzmodus AN,,Cibernetikpova Reĝimo AKTIVA,Modo Ciberpotencia ACTIVADO,,Kyberpotenssitila PÄÄLLÄ,,Kibererő Mód BE,Modo Cyberpotenza ATTIVADA,サイバーポテンスモード オン,전지전능 모드 ON,Cyberpotentiemodus AAN,Cyberpotensmodus PÅ,Tryb Cyberpotencji WŁĄCZONY,Ciberpotência ATIVADA,,Ciberpotență ACTIVATĂ,Режим киберулучшения ВКЛЮЧЁН,,Siber güç Modu AÇIK -Cyberpotence Mode OFF,STSTR_DQDOFF,,,,Režim kybermoci VYP,Cyberpotens-tilstand FRA,Cyberpotenzmodus AUS,,Cibernetikpova Reĝimo NEAKTIVA,Modo Ciberpotencia DESACTIVADO,,Kyberpotenssitila POIS PÄÄLTÄ,,Kibererő Mód KI,Modo Cyberpotenza DISATTIVADA,サイバーポテンスモード オフ,전지전능 모드 OFF,Cyberpotentiemodus UIT,Cyberpotensmodus AV,Tryb Cyberpotencji WYŁĄCZONY,Ciberpotência DESATIVADA,,Ciberpotență DEZACTIVATĂ,Режим киберулучшения ОТКЛЮЧЁН,,Siber güç Modu KAPALI -Tracking ON,AMSTR_FOLLOWON,,,,Sledování ZAP,Sporing TIL,Verfolgung AN,,Spurdado AKTIVA,Seguimiento ACTIVADO,,Seuranta PÄÄLLÄ,,Követés BE,Mappa scorribile DISATTIVATA,トラッキング オン,추적 모드 ON,Tracking AAN,Sporing PÅ,Namierzanie WŁĄCZONE,Seguimento ATIVADO,,Urmărire ACTIVATĂ,Сопровождение ВКЛЮЧЕНО,,İzleme AÇIK -Tracking OFF,AMSTR_FOLLOWOFF,,,,Sledování VYP,Sporing FRA,Verfolgung AUS,,Spurdado NEAKTIVA,Seguimiento DESACTIVADO,,Seuranta POIS PÄÄLTÄ,,Követés KI,Mappa scorribile ATTIVATA,トラッキング オフ,추적 모드 OFF,Tracking UIT,Sporing AV,Namierzanie WYŁĄCZONE,Seguimento DESATIVADO,,Urmărire DEZACTIVATĂ,Сопровождение ОТКЛЮЧЕНО,,İzleme KAPALI -- press Y to run away! -,DOSY,,,,- stiskni Y pro útěk! -,- Tryk på Y for at løbe væk! -,- drücke Y um wegzurennen -,,- premu Y por forkuri! -,- ¡pulsa Y para escapar! - ,,- Paina Y paetaksesi! -,-Appuie sur Y pour t'échapper!-,- nyomj Y-t a nyúlcipő felhúzáshoz -,- premere Y per scappare! -,-Y でトンズラだ!-,- 달아날려먼 Y 키를 눌러! -,- druk op Y om weg te lopen! -,- trykk Y for å stikke av! -,- wciśnij Y by uciec! -,- Aperte Y para fugir! -,- Carrega Y para fugir! -,- apasă Y pentru a fugi! -,"- нажми «Y», чтобы сбежать! -",,- Kaçmak için Y'ye basın! - +INIT-Twitch n'Kill Mode,STSTR_KFAADDED,,,,Inicializuji režim Twitch and Kill,INIT-Twitch n'Kill Mode,Initiiere Twitch'n Kill-Modus,,INIC-Modo de Tiku kaj Buĉu,INIT-Modo Tirar a Matar,,INIT-Nykäise ja nylje -tila,,Twitch n'Kill Mód Betöltése,Iniziare Twitch n'Kill Mode,INIT-Twitch n'Killモード,때리고 죽이는 모드 ON,,INIT-Twitch n'Kill-modus,Inicjacja Trybu Drżenia I Zabijania,Inicializando Modo Chumbo Grosso,,INIT-Modul Click-și-Elimină,ИНИЦ: режим «Дрожи и убивай»,,INIT-Twitch n'Kill Mode,INIT-Twitch n'Kill Modu +"So be it, Hacker.",STSTR_FAADDED,,,,"Budiž, Hackeře.","Sådan skal det være, Hacker.","So sei es, Hacker.",,"Tiel estu, Kodrompisto.","Que así sea, Hacker.",,"Olkoon niin, hakkeri.","Qu'il en soit ainsi, hacker.","Akkor hát legyen, hekker.","Cosi' sia, Hacker.",好きにしろ、ハッカー。,"마음대로 해, 해커 양반.","Het zij zo, Hacker.","Som du vil, Hacker.","Niech tak będzie, Hakerze.","Que assim seja, Hacker.",,"Așa să fie, Hacker.","Да будет так, хакер.",,"Så får det bli, Hacker.","Öyle olsun, Hacker." +Cyberpotence Mode ON,STSTR_DQDON,,,,Režim kybermoci ZAP,Cyberpotens-tilstand TIL,Cyberpotenzmodus AN,,Cibernetikpova Reĝimo AKTIVA,Modo Ciberpotencia ACTIVADO,,Kyberpotenssitila PÄÄLLÄ,,Kibererő Mód BE,Modo Cyberpotenza ATTIVADA,サイバーポテンスモード オン,전지전능 모드 ON,Cyberpotentiemodus AAN,Cyberpotensmodus PÅ,Tryb Cyberpotencji WŁĄCZONY,Ciberpotência ATIVADA,,Ciberpotență ACTIVATĂ,Режим киберулучшения ВКЛЮЧЁН,,Cyberpotens-läge PÅ,Siber güç Modu AÇIK +Cyberpotence Mode OFF,STSTR_DQDOFF,,,,Režim kybermoci VYP,Cyberpotens-tilstand FRA,Cyberpotenzmodus AUS,,Cibernetikpova Reĝimo NEAKTIVA,Modo Ciberpotencia DESACTIVADO,,Kyberpotenssitila POIS PÄÄLTÄ,,Kibererő Mód KI,Modo Cyberpotenza DISATTIVADA,サイバーポテンスモード オフ,전지전능 모드 OFF,Cyberpotentiemodus UIT,Cyberpotensmodus AV,Tryb Cyberpotencji WYŁĄCZONY,Ciberpotência DESATIVADA,,Ciberpotență DEZACTIVATĂ,Режим киберулучшения ОТКЛЮЧЁН,,Cyberpotens-läge AV,Siber güç Modu KAPALI +Tracking ON,AMSTR_FOLLOWON,,,,Sledování ZAP,Sporing TIL,Verfolgung AN,,Spurdado AKTIVA,Seguimiento ACTIVADO,,Seuranta PÄÄLLÄ,,Követés BE,Mappa scorribile DISATTIVATA,トラッキング オン,추적 모드 ON,Tracking AAN,Sporing PÅ,Namierzanie WŁĄCZONE,Seguimento ATIVADO,,Urmărire ACTIVATĂ,Сопровождение ВКЛЮЧЕНО,,Spårning PÅ,İzleme AÇIK +Tracking OFF,AMSTR_FOLLOWOFF,,,,Sledování VYP,Sporing FRA,Verfolgung AUS,,Spurdado NEAKTIVA,Seguimiento DESACTIVADO,,Seuranta POIS PÄÄLTÄ,,Követés KI,Mappa scorribile ATTIVATA,トラッキング オフ,추적 모드 OFF,Tracking UIT,Sporing AV,Namierzanie WYŁĄCZONE,Seguimento DESATIVADO,,Urmărire DEZACTIVATĂ,Сопровождение ОТКЛЮЧЕНО,,Spårning AV,İzleme KAPALI +- press Y to run away! -,DOSY,,,,- stiskni Y pro útěk! -,- Tryk på Y for at løbe væk! -,- drücke Y um wegzurennen -,,- premu Y por forkuri! -,- ¡pulsa Y para escapar! - ,,- Paina Y paetaksesi! -,-Appuie sur Y pour t'échapper!-,- nyomj Y-t a nyúlcipő felhúzáshoz -,- premere Y per scappare! -,-Y でトンズラだ!-,- 달아날려먼 Y 키를 눌러! -,- druk op Y om weg te lopen! -,- trykk Y for å stikke av! -,- wciśnij Y by uciec! -,- Aperte Y para fugir! -,- Carrega Y para fugir! -,- apasă Y pentru a fugi! -,"- нажми «Y», чтобы сбежать! -",,- Tryck på Y för att springa iväg! -,- Kaçmak için Y'ye basın! - "Are you insane or maladjusted? Well? Yes or No!",ENDGAME,,,,"Jsi blb@[adj_cs] nebo jen naveden@[adj_cs]? Tak? Jo nebo ne?","Er du sindssyg eller utilpasset? @@ -1155,7 +1191,7 @@ Nou? Ja of Nee!",Er du sinnssyk eller mistilpasset? Nå? Ja eller Nei!,"Oszalał Więc? Tak czy Nie!","Você é doido ou desregulado? Hein? Sim ou Não!",,"Ești nebun sau doar prost calibrat? Deci? Da sau Nu?","Ты дурак или родом так? -Отвечай! Да (Y) или нет (N)?",,Deli misin yoksa uyumsuz mu? Evet mi? Evet ya da hayır! +Отвечай! Да (Y) или нет (N)?",,Är du galen eller missanpassad? Nå? Ja eller nej!,Deli misin yoksa uyumsuz mu? Evet mi? Evet ya da hayır! "Are you sure? You can't handle this skill, hacker! @@ -1204,7 +1240,7 @@ Carrega Y para morrer.","Ești sigur? Nu poți face față dificultății, hacke Apasă Y ca să mori.","Ты уверен? С этим уровнем сложности ты не справишься, хакер! -Нажми «Y», чтобы умереть.",,"Emin misin? Bu yetenekle başa çıkamazsın, hacker! Ölmek için Y'ye bas." +Нажми «Y», чтобы умереть.",,"Är du säker? Du klarar inte av den här färdigheten, hackare! Tryck på Y för att dö.","Emin misin? Bu yetenekle başa çıkamazsın, hacker! Ölmek için Y'ye bas." "Quicksave over your data named '%s'? @@ -1279,7 +1315,7 @@ Apasă Y sau N.","Перезаписать файл „%s“? -Притисните Y или N.", +Притисните Y или N.",, "Do you want to quickload the data named '%s'? @@ -1352,21 +1388,21 @@ Apasă Y sau N.","Загрузить файл „%s“? -Притисните Y или N.", -Thug,CC_THUG,,,,Pobuda,Bølle,Scherge,,Perfortuloj,Matón,,Roisto,Brute,Bandatag,Tazza,チンピラ,서그,Schurk,Kjeltring,Zbir,Bandido,,Bandit,Головорез,,Eşkıya -Android,CC_ANDROID,,,,,,,,Androido,Androide,,Androidi,Androïde,,,アンドロイド,안드로이드,Androïde,,Android,Andróide,,,Андроид,,Android -ICE,CC_ICE,,,,,,,,,,,,,,,アイス,아이스,,,,,,,ЛЁД,,BUZ -Buzzer,CC_BUZZER,,,,Bzučák,,Summer,,Zumilo,Zumbador,,Surisija,,Sokkoló,Cicalino,ブザー,버저,Zoemer,Summer,Brzęczyk,,,Dronă,Летун,,Şok Uçağı -D-Man,CC_DMAN,,,,,,,,D-Vir',,,D-mies,,,,D-Man,디-맨,,,,,,,Ди-Мэн,,D-Man -Phage,CC_PHAGE,,,,Fág,,,,Faĝo,Fago,,Fagi,,Fekély,Fago,ファージ,페이지,Faag,Phage,Fag,Fago,,Mâncător,Пожиратель,,Faj -Monstruct,CC_MONSTRUCT,,,,Monstrukce,,Monstrukt,,Monstrukto,,,Keinohirviö,,Monstrum,Mostrutto,モンストラクト,몬스트럭트,Monstructie,,Monstrukt,,,,Монструкт,,Monstruct -Mecha Maniac,CC_MECH,,,,Mechamaniak,,,,Mekanika Frenezulo,Meca-Maníaco,,Mechamaanikko,Mécha-maniaque,Mecha Megszállott,Mecha Maniaco,メカマニア,메카 메니악,Mecha Maniak,,Mechaniczny Maniak,Meca-Maníaco,,Meca-Maniac,Механоман,,Meka Manyağı -Terminatrix,CC_TERMI,,,,,,,,,,,,,,,ターミネイトリクス,터미네트릭스,,,,,,,Терминатриса,,Terminatrix -Thorn Thing,CC_THORN,,,,Bodlák,Torn ting,Dornending,,Dorna Aĵo,Cosa Espinosa,,Okaolio,Truc épineux,Tövis Úrnő,,ソーンツィン,쏜 씽,Doornding,Torneting,Cierniowe Coś,Coisa Espinhosa,,Spinos,Тернистая тварь,,Dikenli Şey -Majong 7,CC_MAJONG,,,,,,,,Maĝango 7,,,Mahjong 7,,,,マージャン 7,마작 7호,,,,,,,Маджонг 7,,Majong 7 -Dan Evanger,CC_HERO,,,,,,,,Dan Evanĝer,,,,,,,ダン エブァンガー,댄 에반저,,,,,,,Дэн Эвенджер,,Dan Evanger -Please don't shoot!,SKILL_BABY,,,,"Nestřílej, prosím!",Lad være med at skyde!,Bitte schieß nicht!,,Bonvolu ne pafi!,¡Por favor no dispares!,,"Pyydän, älä ammu!","Pitié, ne tirez pas!",Kérlek ne lőj!,"Ti prego, non sparare!",撃たないでくれ!,쏘지 마세요!,"Niet schieten, alsjeblieft!","Vær så snill, ikke skyt!",Proszę nie strzelaj!,"Por favor, não atire!",,Te rog nu trage!,"Не стреляй, пожалуйста!",,Lütfen ateş etmeyin! -"Aargh, I need health!",SKILL_EASY,,,,Potřebuju zdraví!,"Aargh, jeg har brug for sundhed!",Ich brauche Gesundheit!,,"Aargh, mi bezonas sanon!","¡Aargh, necesito salud!",,"Aargh, tarvitsen terveyttä!","Aargh, des soins!","Á, kell egy kis életerő!","Aargh, ho bisogno di salute!",キメてくれ!,체력이 필요해!,"Aargh, ik heb gezondheid nodig!","Aargh, jeg trenger helse!","Ałć, potrzebuję apteczki!","Aargh, preciso de saúde!",,"Aarș, am nevoie de un medic!","А-а-ргх, аптечку!",,"Aargh, sağlığa ihtiyacım var!" -Let's rip them apart!,SKILL_NORMAL,,,,Rozsekejme je na kusy!,Lad os flå dem i stykker!,Lass uns sie zerfetzen!,,Ni disŝiru ilin!,¡Rompámoslos en pedazos!,,Revitään ne kappaleiksi!,J'en fais de la bouillie!,Tépjük csak szét őket!,Facciamoli a pezzi!,ばらまいてやれ!,갈기갈기 찢어버려!,Laten we ze uit elkaar scheuren!,La oss rive dem i filler!,Czas ich rozerwać!,Vamos despedaçá-los!,,Să-i facem zob!,Разорвём их на куски!,,Hadi onları parçalayalım! -I am immortal!,SKILL_HARD,,,,Jsem nesmrtelný!,Jeg er udødelig!,Ich bin unsterblich!,,Mi estas senmorta!,¡Soy inmortal!,,Olen kuolemation!,Je suis immortel!,Halhatatlan vagyok!,Sono immortale!,とっととくたばれ!,난 무적이다!,Ik ben onsterfelijk!,Jeg er udødelig!,Jestem nieśmiertelny!,Eu sou imortal!,,Sunt nemuritor!,Я бессмертен!,,Ben ölümsüzüm! -Insanity!,SKILL_NIGHTMARE,,,,Šílenství!,Sindssyge!,Wahnsinn!,,Frenezo!,¡Locura!,,Mielettömyys!,Folie!,Téboly!,Follia!,イカれてやがる!,코드명: 광기!,Waanzin!,Galskap!,Szaleństwo!,Insanidade!,,Demență!,Безумие!,,Delilik! \ No newline at end of file +Притисните Y или N.",, +Thug,CC_THUG,,,,Pobuda,Bølle,Scherge,,Perfortuloj,Matón,,Roisto,Brute,Bandatag,Tazza,チンピラ,서그,Schurk,Kjeltring,Zbir,Bandido,,Bandit,Головорез,,Buse,Eşkıya +Android,CC_ANDROID,,,,,,,,Androido,Androide,,Androidi,Androïde,,,アンドロイド,안드로이드,Androïde,,,Andróide,,,Андроид,,, +ICE,CC_ICE,,,,,,,,,,,,,,,アイス,아이스,,,,,,,ЛЁД,,,BUZ +Buzzer,CC_BUZZER,,,,Bzučák,,Summer,,Zumilo,Zumbador,,Surisija,,Sokkoló,Cicalino,ブザー,버저,Zoemer,Summer,Brzęczyk,,,Dronă,Летун,,Summer,Şok Uçağı +D-Man,CC_DMAN,,,,,,,,D-Vir',,,D-mies,,,,,디-맨,,,,,,,Ди-Мэн,,, +Phage,CC_PHAGE,,,,Fág,,,,Faĝo,Fago,,Fagi,,Fekély,Fago,ファージ,페이지,Faag,Phage,Fag,Fago,,Mâncător,Пожиратель,,,Faj +Monstruct,CC_MONSTRUCT,,,,Monstrukce,,Monstrukt,,Monstrukto,,,Keinohirviö,,Monstrum,Mostrutto,モンストラクト,몬스트럭트,Monstructie,,Monstrukt,,,,Монструкт,,, +Mecha Maniac,CC_MECH,,,,Mechamaniak,,,,Mekanika Frenezulo,Meca-Maníaco,,Mechamaanikko,Mécha-maniaque,Mecha Megszállott,Mecha Maniaco,メカマニア,메카 메니악,Mecha Maniak,,Mechaniczny Maniak,Meca-Maníaco,,Meca-Maniac,Механоман,,,Meka Manyağı +Terminatrix,CC_TERMI,,,,,,,,,,,,,,,ターミネイトリクス,터미네트릭스,,,,,,,Терминатриса,,, +Thorn Thing,CC_THORN,,,,Bodlák,Torn ting,Dornending,,Dorna Aĵo,Cosa Espinosa,,Okaolio,Truc épineux,Tövis Úrnő,,ソーンツィン,쏜 씽,Doornding,Torneting,Cierniowe Coś,Coisa Espinhosa,,Spinos,Тернистая тварь,,Tornen ting,Dikenli Şey +Majong 7,CC_MAJONG,,,,,,,,Maĝango 7,,,Mahjong 7,,,,マージャン 7,마작 7호,,,,,,,Маджонг 7,,, +Dan Evanger,CC_HERO,,,,,,,,Dan Evanĝer,,,,,,,ダン エブァンガー,댄 에반저,,,,,,,Дэн Эвенджер,,, +Please don't shoot!,SKILL_BABY,,,,"Nestřílej, prosím!",Lad være med at skyde!,Bitte schieß nicht!,,Bonvolu ne pafi!,¡Por favor no dispares!,,"Pyydän, älä ammu!","Pitié, ne tirez pas!",Kérlek ne lőj!,"Ti prego, non sparare!",撃たないでくれ!,쏘지 마세요!,"Niet schieten, alsjeblieft!","Vær så snill, ikke skyt!",Proszę nie strzelaj!,"Por favor, não atire!",,Te rog nu trage!,"Не стреляй, пожалуйста!",,"Snälla, skjut inte!",Lütfen ateş etmeyin! +"Aargh, I need health!",SKILL_EASY,,,,Potřebuju zdraví!,"Aargh, jeg har brug for sundhed!",Ich brauche Gesundheit!,,"Aargh, mi bezonas sanon!","¡Aargh, necesito salud!",,"Aargh, tarvitsen terveyttä!","Aargh, des soins!","Á, kell egy kis életerő!","Aargh, ho bisogno di salute!",キメてくれ!,체력이 필요해!,"Aargh, ik heb gezondheid nodig!","Aargh, jeg trenger helse!","Ałć, potrzebuję apteczki!","Aargh, preciso de saúde!",,"Aarș, am nevoie de un medic!","А-а-ргх, аптечку!",,"Aargh, jag behöver hälsa!","Aargh, sağlığa ihtiyacım var!" +Let's rip them apart!,SKILL_NORMAL,,,,Rozsekejme je na kusy!,Lad os flå dem i stykker!,Lass uns sie zerfetzen!,,Ni disŝiru ilin!,¡Rompámoslos en pedazos!,,Revitään ne kappaleiksi!,J'en fais de la bouillie!,Tépjük csak szét őket!,Facciamoli a pezzi!,ばらまいてやれ!,갈기갈기 찢어버려!,Laten we ze uit elkaar scheuren!,La oss rive dem i filler!,Czas ich rozerwać!,Vamos despedaçá-los!,,Să-i facem zob!,Разорвём их на куски!,,Låt oss slita dem i bitar!,Hadi onları parçalayalım! +I am immortal!,SKILL_HARD,,,,Jsem nesmrtelný!,Jeg er udødelig!,Ich bin unsterblich!,,Mi estas senmorta!,¡Soy inmortal!,,Olen kuolemation!,Je suis immortel!,Halhatatlan vagyok!,Sono immortale!,とっととくたばれ!,난 무적이다!,Ik ben onsterfelijk!,Jeg er udødelig!,Jestem nieśmiertelny!,Eu sou imortal!,,Sunt nemuritor!,Я бессмертен!,,Jag är odödlig!,Ben ölümsüzüm! +Insanity!,SKILL_NIGHTMARE,,,,Šílenství!,Sindssyge!,Wahnsinn!,,Frenezo!,¡Locura!,,Mielettömyys!,Folie!,Téboly!,Follia!,イカれてやがる!,코드명: 광기!,Waanzin!,Galskap!,Szaleństwo!,Insanidade!,,Demență!,Безумие!,,Galenskap!,Delilik! \ No newline at end of file diff --git a/wadsrc_extra/static/filter/harmony/decorate.txt b/wadsrc_extra/static/filter/harmony/decorate.txt index 3b3102b1f8..94178aeb4d 100644 --- a/wadsrc_extra/static/filter/harmony/decorate.txt +++ b/wadsrc_extra/static/filter/harmony/decorate.txt @@ -1274,51 +1274,6 @@ actor HarmonyBackpack : Backpack replaces Backpack scale 0.30 } -actor TimeBombWeapon : Weapon replaces BFG9000 -{ - scale 0.30 - weapon.kickback 100 - weapon.selectionorder 2800 - weapon.ammouse 1 - weapon.ammogive 2 - weapon.ammotype "TimeBombAmmo" - inventory.pickupmessage "$GOTBFG9000" - inventory.icon "BFUGA0" - +WEAPON.NOAUTOFIRE - +WEAPON.NOAUTOAIM - states - { - Select: - BFGG A 1 A_Raise - loop - Deselect: - BFGG A 1 A_Lower - loop - Ready: - BFGG A 1 A_WeaponReady - loop - Fire: - SHT2 A 3 - SHT2 A 7 A_CheckReload - SHT2 B 1 A_BFGSound - SHT2 B 7 - SHT2 C 6 - SHT2 D 7 A_FireBFG - SHT2 E 7 - SHT2 F 7 A_Light0 - SHT2 H 6 A_Light0 - SHT2 A 5 A_Refire - goto Ready - Flash: - BFGF A 11 bright A_Light1 - BFGF B 6 bright A_Light2 - SHTG E 0 A_Light0 - stop - Spawn: - BFUG A -1 - stop - } -} // The player should start with the hand grenades weapon, but no ammo. // TimeBombWeapon is used as the pickup which should only be picked up once // in multi player. diff --git a/wadsrc_extra/static/filter/harmony/language.csv b/wadsrc_extra/static/filter/harmony/language.csv index 5dea996020..2343c0cecb 100644 --- a/wadsrc_extra/static/filter/harmony/language.csv +++ b/wadsrc_extra/static/filter/harmony/language.csv @@ -1,4 +1,4 @@ -default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,tr +default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,sv,tr Do you really think you can handle that?\n\npress 'Y' or 'N'...,NIGHTMARE,,,,"Opravdu si myslíš, že to zvládneš? Zmáčkni Y nebo N.","Tror du virkelig, at du kan klare det? @@ -20,52 +20,53 @@ Y키, 아니면 N키를 누르시오...","Denk je echt dat je dat aankunt? Druk op 'Y' of 'N'...",Tror du virkelig at du kan håndtere det? Trykk 'Y' eller 'N'...,"Czy ty naprawdę myślisz, że temu podołasz? -Wciśnij 'Y' lub 'N'...",Você acha que dá conta?\n\nAperte Y ou N...,,Chiar crezi că poți face față?\n\napasă 'Y' sau 'N'...,"Уверены, что справитесь?\n\nНажмите «Y» или «N»...",,Gerçekten bununla başa çıkabileceğini düşünüyor musun? 'Y' veya 'N' tuşuna basın... -Spot marked,AMSTR_MARKEDSPOT,,,,Bod označen,Pletmærket,Punkt markiert,,Punkto markita,Punto marcado,,Paikka merkitty,Repère marqué.,Hely megjelölve.,Posizione segnata,スポットヲ マーク シタ,마커 표시함,Vlek gemarkeerd,Punkt markert,Miejsce zaznaczone,Posição marcada,,Loc marcat,Отметка,Означено место,İşaretli nokta -Requires the GREEN keycard,PD_BLUEO,,,,Vyžaduje ZELENOU kartu,Kræver det GRØNNE nøglekort,Benötigt die GRÜNE Schlüsselkarte,,Vi bezonas la VERDAN ŝlosilkarton,Requiere la tarjeta llave VERDE,,Tarvitsee VIHREÄN avainkortin,Carte VERTE demandée.,ZÖLD kulcskártya szükséges,Richiede la card d'accesso VERDE,グリーン キーカード ガ ヒツヨウダ,필요함: 초록색 키카드,Vereist de GROENE sleutelkaart,Krever det GRØNNE nøkkelkortet,Wymaga ZIELONEJ karty,Você precisa do cartão de passe VERDE,,Necesită cardul VERDE,Требуется ЗЕЛЁНАЯ ключ-карта,,YEŞİL anahtar kartı gerektirir -Requires the PURPLE keycard,PD_REDO,,,,Vyžaduje FIALOVOU kartu,Kræver det LILLA nøglekort,Benötigt die VIOLETTE Schlüsselkarte,,Vi bezonas la PURPURAN ŝlosilkarton,Requiere la tarjeta llave VIOLETA,,Tarvitsee VIOLETIN avainkortin,Carte VIOLETTE demandée.,LILA kulcskártya szükséges,Richiede la card d'accesso VIOLA,イエロー キーカード ガ ヒツヨウダ,필요함: 보라색 키카드,Vereist de PAARSE sleutelkaart,Krever det LILLA nøkkelkortet,Wymaga FIOLETOWEJ karty,Você precisa do cartão de passe ROXO,,Necesită cardul MOV,Требуется ФИОЛЕТОВАЯ ключ-карта,,MOR anahtar kartı gerektirir -Requires the YELLOW keycard,PD_YELLOWO,,,,Vyžaduje ŽLUTOU kartu,Kræver det GULLE nøglekort,Benötigt die GELBE Schlüsselkarte,,Vi bezonas la FLAVAN ŝlosilkarton,Requiere la tarjeta llave AMARILLA,,Tarvitsee KELTAISEN avainkortin,Carte JAUNE demandée.,SÁRGA kulcskártya szükséges,Richiede la card d'accesso GIALLA,パープル キーカード ガ ヒツヨウダ,필요함: 노란색 키카드,Vereist de GELE sleutelkaart,Krever det GULT nøkkelkortet,Wymaga ŻÓŁTEJ karty,Você precisa do cartão de passe AMARELO,,Necesită cardul GALBEN,Требуется ЖЁЛТАЯ ключ-карта,,SARI anahtar kartı gerektirir -Requires the GREEN key,PD_BLUEK,,,,Vyžaduje ZELENÝ klíč,Kræver den GRØNNE nøgle,Benötigt den GRÜNEN Schlüssel,,Vi bezonas la VERDAN ŝlosilon,Requiere la llave VERDE,,Tarvitsee VIHREÄN avaimen,Clé VERTE demandée.,ZÖLD kulcs szükséges,Richiede la chiave VERDE,グリーン キー ガ ヒツヨウダ,필요함: 초록색 열쇠,Vereist de GROENE sleutel,Krever den GRØNNE nøkkelen,Wymaga ZIELONEGO klucza,Você precisa da chave VERDE,,Necesită cheia VERDE,Требуется ЗЕЛЁНЫЙ ключ,,YEŞİL tuş gerektirir -Requires the YELLOW key,PD_YELLOWK,,,,Vyžaduje ŽLUTÝ klíč,Kræver den GULLE nøgle,Benötigt den GELBEN Schlüssel,,Vi bezonas la PURPURAN ŝlosilon,Requiere la llave AMARILLA,,Tarvitsee KELTAISEN avaimen,Clé JAUNE demandée.,SÁRGA kulcs szükséges,Richiede la chiave GIALLO,イエロー キー ガ ヒツヨウダ,필요함: 노란색 열쇠,Vereist de GEELE sleutel,Krever den GUL nøkkelen,Wymaga ŻÓŁTEGO klucza,Você precisa da chave AMARELA,,Necesită cheia GALBENĂ,Требуется ЖЁЛТЫЙ ключ,,SARI tuş gerektirir -Requires the PURPLE key,PD_REDK,,,,Vyžaduje FIALOVÝ klíč,Kræver den LILLA nøgle,Benötigt den VIOLETTEN Schlüssel,,Vi bezonas la FLAVAN ŝlosilon,Requiere la llave VIOLETA,,Tarvitsee VIOLETIN avaimen,Clé VIOLETTE demandée.,LILA kulcs szükséges,Richiede la chiave VIOLA,パープル キー ガ ヒツヨウダ,필요함: 보라색 열쇠,Vereist de PAARSE sleutel,Krever den LILLA nøkkelen,Wymaga FIOLETOWEGO klucza,Você precisa da chave ROXA,,Necesită cheia MOV,Требуется ФИОЛЕТОВЫЙ ключ,,MOR tuş gerektirir -Picked up armor.,GOTARMOR,,,Picked up armour.,Sebráno brnění.,Hentede rustning.,Panzer genommen.,,Vi trovis armaĵon.,Encuentras una armadura.,Hallaste una armadura.,Panssari poimittu.,Armure récupérée.,Vért felvéve,Raccolto un'armatura.,アーマー ニュウシュ,획득: 전투복.,Je hebt een harnas opgehaald.,Plukket opp rustning.,Zebrano pancerz.,Pegou uma armadura.,,Ai ridicat Armura.,Получена броня.,Покупили сте панцир.,Zırhı aldım. -Picked up Combat Armor.,GOTMEGA,,,Picked up Combat Armour.,Sebráno bojové brnění.,Samlet Combat Armor op.,Super-Panzer genommen.,,Vi trovis batal-armaĵon.,Encuentras una armadura de combate.,Hallaste una armadura de combate.,Taistelupanssari poimittu.,Armure de combat récupérée.,Harci vért felvéve,Raccolto Armatura da combattimento.,コンバット アーマー ニュウシュ,획득: 강화된 전투복.,Je hebt een gevechtsharnas opgehaald.,Plukket opp kamprustning.,Zebrano pancerz bojowy.,Pegou uma Armadura de Combate.,,Ai ridicat Armura de Luptă.,Получена боевая броня.,,Savaş Zırhı aldı. -Superhealth,GOTMSPHERE,,,,Superzdraví,Superhealth,Super-Gesundheit,,Supersano,Supersalud,,Superterveys,Super-Santé,Szuperéleterő,Super salute,スーパー ヘルス,사용: 체력강화 버섯.,,Superhelse,Superzdrowie,Superssaúde,,Supersănătate,Суперздоровье,,Süper Sağlık -Obtained the GREEN keycard.,GOTBLUECARD,,,,Sebrána ZELENÁ karta.,Opnået det GRØNNE nøglekort.,GRÜNE Schlüsselkarte erhalten,,Vi trovis la VERDAN ŝlosilkarton.,Encuentras la tarjeta llave VERDE.,Hallaste la tarjeta llave VERDE.,VIHREÄ avainkortti poimittu.,Carte VERTE obtenue.,Megszerezted a ZÖLD kulcskártyát.,Ottenuta la card d'accesso VERDE.,グリーン キーカード ニュウシュ,획득: 초록색 키카드.,GROENE sleutelkaart ontvangen,Fått det GRØNNE nøkkelkortet.,Zdobyto ZIELONĄ kartę.,Pegou o cartão de passe VERDE.,,Ai achiziționat cardul VERDE.,Получена ЗЕЛЁНАЯ ключ-карта.,,YEŞİL anahtar kartı elde edildi. -Obtained the YELLOW keycard.,GOTYELWCARD,,,,Sebrána ŽLUTÁ karta.,Opnået det GULLE nøglekort.,GELBE Schlüsselkarte erhalten,,Vi trovis la FLAVAN ŝlosilkarton.,Encuentras la tarjeta llave AMARILLA.,Hallaste la tarjeta llave AMARILLA.,KELTAINEN avainkortti poimittu.,Carte JAUNE obtenue.,Megszerezted a SÁRGA kulcskártyát.,Ottenuta la card d'accesso GIALLA.,イエロー キーカード ニュウシュ,획득: 노란색 키카드.,GELE sleutelkaart ontvangen,Fått det GUL nøkkelkortet.,Zdobyto ŻÓŁTĄ kartę.,Pegou o cartão de passe AMARELO.,,Ai achiziționat cardul GALBEN.,Получена ЖЁЛТАЯ ключ-карта.,,SARI anahtar kartı elde edildi. -Obtained the PURPLE keycard.,GOTREDCARD,,,,Sebrána FIALOVÁ karta.,Opnået det LILLA nøglekort.,VIOLETTE Schlüsselkarte erhalten,,Vi trovis la PURPURAN ŝlosilkarton.,Encuentras la tarjeta llave VIOLETA.,Hallaste la tarjeta llave VIOLETA.,VIOLETTI avainkortti poimittu.,Carte VIOLETTE obtenue.,Megszerezted a LILA kulcskártyát.,Ottenuta la card d'accesso VIOLA.,パープル キーカード ニュウシュ,획득: 보라색 키카드.,PAARSE sleutelkaart ontvangen,Fikk det LILLA nøkkelkortet.,Zdobyto FIOLETOWĄ kartę.,Pegou o cartão de passe ROXO.,,Ai achiziționat cardul MOV.,Получена ФИОЛЕТОВАЯ ключ-карта.,,MOR anahtar kartı elde edildi. -Obtained the GREEN key.,GOTBLUESKUL,,,,Sebrán ZELENÝ klíč.,Opnået den GRØNNE nøgle.,GRÜNEN Schlüssel erhalten,,Vi trovis la VERDAN ŝlosilon.,Encuentras la llave VERDE.,Hallaste la llave VERDE.,VIHREÄ avain poimittu.,Clé VERTE obtenue.,Megszerezted a ZÖLD kulcsot.,Ottenuta la chiave VERDE.,グリーン キー ニュウシュ,획득: 초록색 열쇠.,GROENE sleutel ontvangen,Fikk den GRØNNE nøkkelen.,Zdobyto ZIELONY klucz.,Pegou a chave VERDE.,,Ai achiziționat cheia VERDE.,Получен ЗЕЛЁНЫЙ ключ.,,YEŞİL anahtar elde edildi. -Obtained the YELLOW key.,GOTYELWSKUL,,,,Sebrán ŽLUTÝ klíč.,Opnået den GULLE nøgle.,GELBEN Schlüssel erhalten,,Vi trovis la FLAVAN ŝlosilon.,Encuentras la llave AMARILLA.,Hallaste la llave AMARILLA.,KELTAINEN avain poimittu.,Clé JAUNE obtenue.,Megszerezted a SÁRGA kulcsot.,Ottenuta la chiave GIALLA.,イエロー キー ニュウシュ,획득: 노란색 열쇠.,GELE sleutel ontvangen,Fikk den GULA nøkkelen.,Zdobyto ŻÓŁTY klucz.,Pegou a chave AMARELA.,,Ai achiziționat cheia GALBENĂ.,Получен ЖЁЛТЫЙ ключ.,,SARI anahtar elde edildi. -Obtained the PURPLE key.,GOTREDSKUL,,,,Sebrán FIALOVÝ klíč.,Opnået den LILLA nøgle.,VIOLETTEN Schlüssel erhalten,,Vi trovis la PURPURAN ŝlosilon.,Encuentras la llave VIOLETA.,Hallaste la llave VIOLETA.,VIOLETTI avain poimittu.,Clé VIOLETTE obtenue.,Megszerezted a LILA kulcsot.,Ottenuta la chiave VIOLA.,パープル キー ニュウシュ,획득: 보라색 열쇠.,PAARSE sleutel ontvangen,Fikk den LILLA nøkkelen.,Zdobyto FIOLETOWY klucz.,Pegou a chave ROXA.,,Ai achiziționat cheia MOV.,Получен ФИОЛЕТОВЫЙ ключ.,,MOR anahtar elde edildi. -Healing mushroom,GOTSTIM,,,,Léčivka,Helbredende svamp,Heilpilz,,Saniga fungo,Seta medicinal,Hongo medicinal,Lääkesieni,Champignon médicinal,Gyógyító gomba,Funghi curativi,ヒーリング マッシュルーム,사용: 체력회복 버섯.,Genezende paddenstoel,Helbredende sopp,Leczący grzyb,Cogumelo medicinal,,Ciupercă vindecătoare,Целебный гриб,,İyileştirici mantar -Acquired: medical kit.,GOTMEDIKIT,,,,Získána lékárnička.,Erhvervet: medicinsk kit.,Erhalten: Medikit,,Vi trovis sukurkeston.,Encuentras un botiquín.,Hallaste un botiquín.,Saatu: lääkintälaukku.,Acquis: Kit médical.,Megszerezve: orvosi csomag,Acquisito: kit medico.,シュトク: メディカルキット,사용: 의료 키트.,Verworven: medische kit.,Ervervet: medisinsk sett.,Zdobyto: apteczkę.,Pegou um kit médico.,,Ridicat: Kit de Prim-Ajutor.,Получена: Аптечка.,,Elde edilen: tıbbi kit. -Acquired: medical kit that you REALLY need.,GOTMEDINEED,,,,"Získána lékárnička, kterou OPRAVDU potřebuješ.","Erhvervet: medicinsk kit, som du VIRKELIG har brug for.","Erhalten: Medikit, das du WIRKLICH brauchst",,"Vi trovis sukurkeston, kiun vi VERE bezonas.",Encuentras un botiquín que REALMENTE necesitabas.,Hallaste un botiquín que REALMENTE necesitabas.,"Saatu: lääkintälaukku, jota TODELLA tarvitsit.",Acquis: Kit médical. Besoin critique.,Megszerezve: már NAGYON hiányzott orvosi csomag,Acquisito: kit medico di cui VERAMENTE avete bisogno.,シュトク: キンキュウジタイヲ スクウ メディカルキット,사용: 당신을 살려줄 의료 키트.,Verworven: medische kit die je ECHT nodig heeft.,Ervervet: medisinsk sett som du virkelig trenger.,"Zdobyto: apteczkę, której NAPRAWDĘ potrzebujesz.",Pegou um kit médico que você REALMENTE precisa.,,Ridicat: Kit de Prim-Ajutor de care CHIAR AI nevoie.,Получена: Аптечка (КРАЙНЕ необходимая).,,Elde edilen: GERÇEKTEN ihtiyacınız olan tıbbi kit. -Map,GOTMAP,,,,Mapa,Kort,Karte,,Vi trovis la mapon,Mapa,,Kartta,Carte,Térkép,Mappa,コノ クイキノ マップダ ,획득: 지도.,Kaart,Kart,Mapa,Mapa,,Hartă,Карта,,Harita -Acquired: case of bullets.,GOTCLIPBOX,,,,Získána krabice nábojů.,Erhvervet: kasse med kugler.,Erhalten: Munitionskiste,,Vi trovis skatolon da kugloj.,Encuentras una caja de balas.,Hallaste una caja de balas.,Saatu: luotilaatikko.,Acquis: Boîte de balles.,Megszerezve: doboznyi lőszer.,Acquisito: caso di proiettili.,シュトク: バレット ケース,획득: 회전포 탄약.,Verworven: geval van kogels.,Ervervet: tilfelle av kuler.,Zdobyto: pudełko naboi.,Pegou uma caixa de balas,,Achiziționat: Cutie de gloanțe.,Получен: Ящик с пулями.,,Elde edilen: mermi kovanı. -Acquired: Grenade.,GOTROCKET,,,,Ziskán granát.,Erhvervet: Granat.,Erhalten: Granate,,Vi trovis grenadon.,Encuentras una granada.,Hallaste una granada.,Saatu: kranaatti.,Acquis: Grenade.,Megszerezve: Gránát.,Acquisito: Granata.,シュトク: グレネード,획득: 세열탄.,Verworven: Granaat.,Ervervet: Granat.,Zdobyto: Granat.,Pegou uma granada.,,Achiziționat: Grenadă.,Получена: Граната.,,Elde edildi: El bombası. -Acquired: Grenades.,GOTROCKBOX,,,,Ziskány granáty.,Erhvervet: Granater.,Erhalten: Granaten,,Vi trovis grenadojn.,Encuentras unas granadas.,Hallaste unas granadas.,Saatu: kranaatteja.,Acquis: Grenades.,Megszerezve: Gránátok.,Acquisito: Granate.,シュトク: グレネード セット,획득: 세열탄 여러 개.,Verworven: Granaten.,Ervervet: Granater.,Zdobyto: Granaty.,Pegou granadas.,,Achiziționat: Grenade.,Получены: Гранаты.,,Elde edildi: El bombaları. -Acquired: box of shotgun shells.,GOTSHELLBOX,,,,Získána krabice broků.,Erhvervet: kasse med haglpatroner.,Erhalten: Schrotpatronen,,Vi trovis skatolon da kartoĉoj.,Encuentras una caja de cartuchos de escopeta.,Hallaste una caja de cartuchos de escopeta.,Saatu: laatikollinen haulikon patruunoita.,Acquis: Boîte de cartouches.,Megszerezve: doboznyi puska sörét,Acquisito: scatola di cartucce per fucile.,シュトク: シェル ボックス,획득: 산탄총 탄약.,Verworven: doos met shotgun schelpen.,Ervervet: eske med haglepatroner.,Zdobyto: pudełko loftek do strzelby.,Pegou uma caixa de cartuchos de espingarda.,,Achiziționat: Cutie de muniție pentru pușcă.,Получена: Коробка патронов для дробовика.,,Edinildi: Bir kutu av tüfeği fişeği. -Acquired: ammo backpack.,GOTBACKPACK,,,,Ziskán batoh s municí.,Erhvervet: ammunitionsrygsæk.,Erhalten: Munitionsrucksack,,Vi trovis tornistron da municioj.,Encuentras una mochila de municiones.,Hallaste una mochila de municiones.,Saatu: ammusreppu.,Acquis: Sac de munitions.,Megszerezve: lőszeres hátizsák,Acquisito: zaino munizioni.,シュトク: バックパック,획득: 탄약 가방.,Verworven: munitie rugzak.,Ervervet: ryggsekk med ammunisjon.,Zdobyto: plecak z amunicją.,Pegou uma mochila de munição.,,Achiziționat: Raniță.,Получен: Ранец для боеприпасов.,,Edinildi: Cephane çantası. -Acquired: Grenade.,GOTBFG9000,,,,Získán granát.,Erhvervet: Granat.,Erhalten: Granate,,Vi trovis grenadon.,Encuentras una granada.,Hallaste una granada.,Saatu: kranaatti.,Acquis: Grenade.,Megszerezve: Gránát.,Acquisito: Granata.,シュトク: グレネード,획득: 세열탄.,Verworven: Granaat.,Ervervet: Granat.,Zdobyto: Granat.,Pegou uma granada.,,Achiziționat: Grenadă.,Получена: Граната.,,Elde edildi: El bombası. -Acquired: Minigun.,GOTCHAINGUN,,,,Získán kulomet.,Erhvervet: Minigun.,Erhalten: Minigun,,Vi trovis maŝinpafilon.,Encuentras una ametralladora.,Hallaste una ametralladora.,Saatu: minigun.,Acquis: Minigun.,Megszerezve: Gépfegyver.,Acquisito: Minigun.,シュトク: ミニガン,획득: 회전포.,Verworven: Minigun.,Ervervet: Minigun.,Zdobyto: Minigun.,Pegou uma metralhadora giratória.,,Achiziționat: Minimitralieră.,Получен: Пулемёт.,,Elde edildi: Minigun. -Acquired: Grenade launcher.,GOTLAUNCHER,,,,Získán granátomet.,Erhvervet: Granatkaster.,Erhalten: Granatwerfer,,Vi trovis grenadĵetilon.,Encuentras un lanzagranadas.,Hallaste un lanzagranadas.,Saatu: kranaatinheitin.,Acquis: Lance-Grenades,Megszerezve: Gránátvető,Acquisito: Lanciagranate.,シュトク: グレネードランチャー,획득: 세열탄 추진기.,Verworven: Granaatwerper.,Ervervet: Granatkaster.,Zdobyto: Wyrzutnię granatów.,Pegou um lança-granadas.,,Achiziționat: Lansator de grenade.,Получен: Гранатомёт.,,Elde edildi: El bombası fırlatıcı. -Entropy thrower!,GOTPLASMA,,,,Vrhač entropie!,Entropi-lancer!,Entropiewerfer,,Entropi-ĵetilon!,¡Lanzador de entropía!,,Entropianheitin!,Acquis: Lanceur d'Entropie!,Entrópiavető!,Lancia entropia!,エントロピースロワー!,획득: 엔트로피 방사기!,Entropiewerper!,Entropikaster!,Miotacz Entropii!,Lançador de entropia!,,Aruncător entropic!,Энтропиемёт!,,Entropi fırlatıcı! -Acquired: Shotgun.,GOTSHOTGUN,,,,Získána brokovnice.,Erhvervet: Shotgun.,Erhalten: Schrotflinte,,Vi trovis kartoĉan fusilon.,Encuentras una escopeta.,Hallaste una escopeta.,Saatu: haulikko.,Acquis: Fusil à pompe.,Megszerezve: Sörétes puska,Acquisito: Fucile.,シュトク: ショットガン,획득: 산탄총.,Verworven: Shotgun.,Ervervet: Haglgevær.,Zdobyto: Strzelbę.,Pegou uma espingarda.,,Achiziționat: Pușcă.,Получен: Дробовик.,,Edinildi: Av tüfeği. -God Mode ON,STSTR_DQDON,,,,Nesmrtelnost ZAP,Gud-tilstand PÅ,Gott-Modus AN,,Dio-Reĝimo AKTIVA,Modo Dios ACTIVADO,,Kuolemattomuustila PÄÄLLÄ,Mode invulnérable ON,Isten mód BE,Modalità Dio ATTIVATA,ゴッドモード オン,무적 치트: ON,God Modus AAN,Gudsmodus PÅ,Tryb Boga WŁĄCZONY,Modo Deus LIGADO,,Modul Invincibil PORNIT,Режим Бога ВКЛЮЧЁН,,Tanrı Modu AÇIK -God Mode OFF,STSTR_DQDOFF,,,,Nesmrtelnost VYP,Gud-tilstand FRA,Gott-Modus AUS,,Dio-Reĝimo NEAKTIVA,Modo Dios DESACTIVADO,,Kuolemattomuustila POIS PÄÄLTÄ,Mode invulnérable OFF,Isten mód KI,Modalità Dio DISATTIVATA,ゴッドモード オフ,무적 치트: OFF,God Modus UIT,Gudsmodus AV,Tryb Boga WYŁĄCZONY,Modo Deus DESLIGADO,,Modul Invincibil OPRIT,Режим Бога ОТКЛЮЧЁН,,Tanrı Modu KAPALI -All weapons/ ammo/ keys,STSTR_KFAADDED,,,,Všechny zbraně/munice/klíče,Alle våben/ ammunition/ nøgler,"Alle Waffen, Munition und Schlüssel",,Ĉiuj armiloj/municioj/ŝlosiloj,Todas las armas/municiones/llaves,,Kaikki aseet/ ammukset/ avaimet,Toutes les armes/munitions/clés,Minden fegyver / lőszer / kulcs,Tutte le armi / munizioni / chiavi,スベテノ ブキ/カギ/ダンヤク,추가: 모든 무기/탄약/열쇠 치트,Alle wapens / munitie / sleutels,Alle våpen / ammunisjon / nøkler,Wszystkie bronie/amunicja/klucze,Todas as armas/munição/chaves,,Toate armele/muniție/chei,Всё оружие/боеприпасы/ключи,,Tüm silahlar/ cephane/ anahtarlar -All weapons and ammo,STSTR_FAADDED,,,,Všechny zbraně a munice,Alle våben og ammunition,Alle Waffen und Munition,,Ĉiuj armiloj kaj municioj,Todas las armas y municiones,,Kaikki aseet ja ammukset,Toutes les armes et munitions,Minden fegyver és lőszer,Tutte le armi e le munizioni,スベテノ ブキ/ダンヤク,추가: 모든 무기/탄약 치트,Alle wapens en munitie,Alle våpen og ammunisjon,Wszystkie bronie i amunicja,Todas as armas e munição completa,,Toate armele și muniție,Всё оружие и боеприпасы,,Tüm silahlar ve cephane -Abduction,TXT_HARMMAP01,,,,Únos,Bortførelse,Entführung,,Forkapto,Abducción,,Sieppaus,Enlèvement,Elrablás,Il rapimento,アブダクション,유괴,Ontvoering,Bortføring,Porwanie,Sequestro,,Răpire,Похищение,,Kaçırılma -Harm's Way,TXT_HARMMAP02,,,,Nebezpečí,,In Gefahr,,Vojo de danĝero,En peligro,,Vaara,Mise en Danger,Baj,La via del danno,ハーム'ズ ウェイ,해함의 길,,,Niebezpieczeństwo,No Caminho do Perigo,,Calea pericolului,Опасный путь,,Zarar Görebilecek Durumda -Owt Mood,TXT_HARMMAP03,,,,Špatný pocit,,Missstimmung,,Sentaĉo,Buen humor,,Nollatunnelma,Scontento,Túlterhelve,Scontento,ヤバイムード,이상한 분위기,,,Paskudny Nastrój,Mau Humor,,Fricțiune,Нестроение,,Kötü Ruh Hali -Megalapolis,TXT_HARMMAP04,,,,Megalopole,,Megalopolis,,Megtropolo,Megalópolis,,Megalopoli,Mégalopole,Megalopolisz,Megalapoli,メガラポリス,거대 도시,Megalopolis,,Megalapolis,Megalópole,,Megalopolis,Мегалаполис,,Megalapolis -The Hospital,TXT_HARMMAP05,,,,Nemocnice,Hospitalet,Das Hospital,,La malsanulejo,El hospital,,Sairaala,L'Hôpital,Kórház,L'ospedale,ホスピタル,병동,Het ziekenhuis,Sykehuset,Szpital,O Hospital,,Spitalul,Больница,,Hastane -The Weapons Factory,TXT_HARMMAP06,,,,Továrna na zbraně,Våbenfabrikken,Die Waffenfabrik,,La armil-fabriko,La fábrica de armas,,Asetehdas,L'Usine d'Armes,Fegyvergyár,La fabbrica di armi,ウェポンファクトリー,무기 공장,De Wapenfabriek,Våpenfabrikken,Fabryka Broni,A Fábrica de Armamentos,,Fabrica de Arme,Оружейный завод,,Silah Fabrikası -The Underwater Lab,TXT_HARMMAP07,,,,Podvodní laboratoř,Undervandslaboratoriet,Das Unterwasserlabor,,La subakva labotorio,El laboratorio submarino,,Vedenalainen laboratorio,Le Laboratoire Sous-marin,Vízalatti labor,Il laboratorio subacqueo,アンダーウォーターラボ,해저 연구소,Het onderwaterlaboratorium,Undervannslaboratoriet,Podwodne Laboratorium,O Laboratório Submarino,,Laboratorul Subacvatic,Подводная лаборатория,,Sualtı Laboratuvarı -Airstrip One,TXT_HARMMAP08,,,,Přistávací dráha jedna,Landingsbane et,Flugplatz Eins,,Surteriĝejo numero unu,Pista de aterrizaje uno,,Kiitorata Yksi,Piste D'Atterrisage Un,1-es kifutó,Pista Uno,エアーシップ ワン,활주로 1호,Vliegveld Een,Flystripe én,Lądowisko Numer Jeden,Base Aérea Um,,Pista Unu,Взлётная полоса №1,,Birinci Pist -The Launch Base,TXT_HARMMAP09,,,,Vzletová základna,Affyringsbasen,Die Startbasis,,La lanĉbazo,La base de despegue,,Laukaisutukikohta,La Base de Lancement,Kilövő Állomás,La base di lancio,ランチャーベース,발진기지,De lanceerbasis,Utskytningsbasen,Baza Startowa,A Base de Lançamento,,Baza de Lansare,Пусковая площадка,,Fırlatma Üssü -The Radioactive Zone,TXT_HARMMAP10,,,,Radioaktivní zóna,Den radioaktive zone,Die radioaktive Zone,,La radioaktiva zono,La zona radioactiva,,Radioaktiivinen vyöhyke,La Zone Radioactive,Radioaktív Zóna,La zona radioattiva,ラディオアクティブ ゾーン,방사능 처리소,De Radioactieve Zone,Den radioaktive sonen,Radioaktywna Strefa,A Zona Radioativa,,Zona Radioactivă,Заражённая зона,,Radyoaktif Bölge -Echidna,TXT_HARMMAP11,,,,,,,,Ekidno,,,Nokkasiili,,Hangyászsün,,エキドナ,에키드나,,,,Equidna,,,Ехидна,,Echidna +Wciśnij 'Y' lub 'N'...",Você acha que dá conta?\n\nAperte Y ou N...,,Chiar crezi că poți face față?\n\napasă 'Y' sau 'N'...,"Уверены, что справитесь?\n\nНажмите «Y» или «N»...",,"Tror du verkligen att du klarar av det? +Tryck på ""Y"" eller ""N""...",Gerçekten bununla başa çıkabileceğini düşünüyor musun? 'Y' veya 'N' tuşuna basın... +Spot marked,AMSTR_MARKEDSPOT,,,,Bod označen,Pletmærket,Punkt markiert,,Punkto markita,Punto marcado,,Paikka merkitty,Repère marqué.,Hely megjelölve.,Posizione segnata,スポットヲ マーク シタ,마커 표시함,Vlek gemarkeerd,Punkt markert,Miejsce zaznaczone,Posição marcada,,Loc marcat,Отметка,Означено место,Markerad punkt,İşaretli nokta +Requires the GREEN keycard,PD_BLUEO,,,,Vyžaduje ZELENOU kartu,Kræver det GRØNNE nøglekort,Benötigt die GRÜNE Schlüsselkarte,,Vi bezonas la VERDAN ŝlosilkarton,Requiere la tarjeta llave VERDE,,Tarvitsee VIHREÄN avainkortin,Carte VERTE demandée.,ZÖLD kulcskártya szükséges,Richiede la card d'accesso VERDE,グリーン キーカード ガ ヒツヨウダ,필요함: 초록색 키카드,Vereist de GROENE sleutelkaart,Krever det GRØNNE nøkkelkortet,Wymaga ZIELONEJ karty,Você precisa do cartão de passe VERDE,,Necesită cardul VERDE,Требуется ЗЕЛЁНАЯ ключ-карта,,Kräver det GRÖNA nyckelkortet.,YEŞİL anahtar kartı gerektirir +Requires the PURPLE keycard,PD_REDO,,,,Vyžaduje FIALOVOU kartu,Kræver det LILLA nøglekort,Benötigt die VIOLETTE Schlüsselkarte,,Vi bezonas la PURPURAN ŝlosilkarton,Requiere la tarjeta llave VIOLETA,,Tarvitsee VIOLETIN avainkortin,Carte VIOLETTE demandée.,LILA kulcskártya szükséges,Richiede la card d'accesso VIOLA,イエロー キーカード ガ ヒツヨウダ,필요함: 보라색 키카드,Vereist de PAARSE sleutelkaart,Krever det LILLA nøkkelkortet,Wymaga FIOLETOWEJ karty,Você precisa do cartão de passe ROXO,,Necesită cardul MOV,Требуется ФИОЛЕТОВАЯ ключ-карта,,Kräver det LILA nyckelkortet,MOR anahtar kartı gerektirir +Requires the YELLOW keycard,PD_YELLOWO,,,,Vyžaduje ŽLUTOU kartu,Kræver det GULLE nøglekort,Benötigt die GELBE Schlüsselkarte,,Vi bezonas la FLAVAN ŝlosilkarton,Requiere la tarjeta llave AMARILLA,,Tarvitsee KELTAISEN avainkortin,Carte JAUNE demandée.,SÁRGA kulcskártya szükséges,Richiede la card d'accesso GIALLA,パープル キーカード ガ ヒツヨウダ,필요함: 노란색 키카드,Vereist de GELE sleutelkaart,Krever det GULT nøkkelkortet,Wymaga ŻÓŁTEJ karty,Você precisa do cartão de passe AMARELO,,Necesită cardul GALBEN,Требуется ЖЁЛТАЯ ключ-карта,,Kräver det GULLA nyckelkortet,SARI anahtar kartı gerektirir +Requires the GREEN key,PD_BLUEK,,,,Vyžaduje ZELENÝ klíč,Kræver den GRØNNE nøgle,Benötigt den GRÜNEN Schlüssel,,Vi bezonas la VERDAN ŝlosilon,Requiere la llave VERDE,,Tarvitsee VIHREÄN avaimen,Clé VERTE demandée.,ZÖLD kulcs szükséges,Richiede la chiave VERDE,グリーン キー ガ ヒツヨウダ,필요함: 초록색 열쇠,Vereist de GROENE sleutel,Krever den GRØNNE nøkkelen,Wymaga ZIELONEGO klucza,Você precisa da chave VERDE,,Necesită cheia VERDE,Требуется ЗЕЛЁНЫЙ ключ,,Kräver det GRÖNA nyckeln,YEŞİL tuş gerektirir +Requires the YELLOW key,PD_YELLOWK,,,,Vyžaduje ŽLUTÝ klíč,Kræver den GULLE nøgle,Benötigt den GELBEN Schlüssel,,Vi bezonas la PURPURAN ŝlosilon,Requiere la llave AMARILLA,,Tarvitsee KELTAISEN avaimen,Clé JAUNE demandée.,SÁRGA kulcs szükséges,Richiede la chiave GIALLO,イエロー キー ガ ヒツヨウダ,필요함: 노란색 열쇠,Vereist de GEELE sleutel,Krever den GUL nøkkelen,Wymaga ŻÓŁTEGO klucza,Você precisa da chave AMARELA,,Necesită cheia GALBENĂ,Требуется ЖЁЛТЫЙ ключ,,Kräver den GULLA nyckeln,SARI tuş gerektirir +Requires the PURPLE key,PD_REDK,,,,Vyžaduje FIALOVÝ klíč,Kræver den LILLA nøgle,Benötigt den VIOLETTEN Schlüssel,,Vi bezonas la FLAVAN ŝlosilon,Requiere la llave VIOLETA,,Tarvitsee VIOLETIN avaimen,Clé VIOLETTE demandée.,LILA kulcs szükséges,Richiede la chiave VIOLA,パープル キー ガ ヒツヨウダ,필요함: 보라색 열쇠,Vereist de PAARSE sleutel,Krever den LILLA nøkkelen,Wymaga FIOLETOWEGO klucza,Você precisa da chave ROXA,,Necesită cheia MOV,Требуется ФИОЛЕТОВЫЙ ключ,,Kräver den LILA nyckeln,MOR tuş gerektirir +Picked up armor.,GOTARMOR,,,Picked up armour.,Sebráno brnění.,Hentede rustning.,Panzer genommen.,,Vi trovis armaĵon.,Encuentras una armadura.,,Panssari poimittu.,Armure récupérée.,Vért felvéve,Raccolto un'armatura.,アーマー ニュウシュ,획득: 전투복.,Je hebt een harnas opgehaald.,Plukket opp rustning.,Zebrano pancerz.,Pegou uma armadura.,,Ai ridicat Armura.,Получена броня.,Покупили сте панцир.,Plockade upp en rustning.,Zırhı aldım. +Picked up Combat Armor.,GOTMEGA,,,Picked up Combat Armour.,Sebráno bojové brnění.,Samlet Combat Armor op.,Super-Panzer genommen.,,Vi trovis batal-armaĵon.,Encuentras una armadura de combate.,,Taistelupanssari poimittu.,Armure de combat récupérée.,Harci vért felvéve,Raccolto Armatura da combattimento.,コンバット アーマー ニュウシュ,획득: 강화된 전투복.,Je hebt een gevechtsharnas opgehaald.,Plukket opp kamprustning.,Zebrano pancerz bojowy.,Pegou uma Armadura de Combate.,,Ai ridicat Armura de Luptă.,Получена боевая броня.,,Plockade upp kampen rustning.,Savaş Zırhı aldı. +Superhealth,GOTMSPHERE,,,,Superzdraví,,Super-Gesundheit,,Supersano,Supersalud,,Superterveys,Super-Santé,Szuperéleterő,Super salute,スーパー ヘルス,사용: 체력강화 버섯.,,Superhelse,Superzdrowie,Superssaúde,,Supersănătate,Суперздоровье,,Supersundhet,Süper Sağlık +Obtained the GREEN keycard.,GOTBLUECARD,,,,Sebrána ZELENÁ karta.,Opnået det GRØNNE nøglekort.,GRÜNE Schlüsselkarte erhalten,,Vi trovis la VERDAN ŝlosilkarton.,Encuentras la tarjeta llave VERDE.,,VIHREÄ avainkortti poimittu.,Carte VERTE obtenue.,Megszerezted a ZÖLD kulcskártyát.,Ottenuta la card d'accesso VERDE.,グリーン キーカード ニュウシュ,획득: 초록색 키카드.,GROENE sleutelkaart ontvangen,Fått det GRØNNE nøkkelkortet.,Zdobyto ZIELONĄ kartę.,Pegou o cartão de passe VERDE.,,Ai achiziționat cardul VERDE.,Получена ЗЕЛЁНАЯ ключ-карта.,,Skaffade det GRÖNA nyckelkortet.,YEŞİL anahtar kartı elde edildi. +Obtained the YELLOW keycard.,GOTYELWCARD,,,,Sebrána ŽLUTÁ karta.,Opnået det GULLE nøglekort.,GELBE Schlüsselkarte erhalten,,Vi trovis la FLAVAN ŝlosilkarton.,Encuentras la tarjeta llave AMARILLA.,,KELTAINEN avainkortti poimittu.,Carte JAUNE obtenue.,Megszerezted a SÁRGA kulcskártyát.,Ottenuta la card d'accesso GIALLA.,イエロー キーカード ニュウシュ,획득: 노란색 키카드.,GELE sleutelkaart ontvangen,Fått det GUL nøkkelkortet.,Zdobyto ŻÓŁTĄ kartę.,Pegou o cartão de passe AMARELO.,,Ai achiziționat cardul GALBEN.,Получена ЖЁЛТАЯ ключ-карта.,,Skaffade det GULLA nyckelkortet.,SARI anahtar kartı elde edildi. +Obtained the PURPLE keycard.,GOTREDCARD,,,,Sebrána FIALOVÁ karta.,Opnået det LILLA nøglekort.,VIOLETTE Schlüsselkarte erhalten,,Vi trovis la PURPURAN ŝlosilkarton.,Encuentras la tarjeta llave VIOLETA.,,VIOLETTI avainkortti poimittu.,Carte VIOLETTE obtenue.,Megszerezted a LILA kulcskártyát.,Ottenuta la card d'accesso VIOLA.,パープル キーカード ニュウシュ,획득: 보라색 키카드.,PAARSE sleutelkaart ontvangen,Fikk det LILLA nøkkelkortet.,Zdobyto FIOLETOWĄ kartę.,Pegou o cartão de passe ROXO.,,Ai achiziționat cardul MOV.,Получена ФИОЛЕТОВАЯ ключ-карта.,,Skaffade det LILA nyckelkortet.,MOR anahtar kartı elde edildi. +Obtained the GREEN key.,GOTBLUESKUL,,,,Sebrán ZELENÝ klíč.,Opnået den GRØNNE nøgle.,GRÜNEN Schlüssel erhalten,,Vi trovis la VERDAN ŝlosilon.,Encuentras la llave VERDE.,,VIHREÄ avain poimittu.,Clé VERTE obtenue.,Megszerezted a ZÖLD kulcsot.,Ottenuta la chiave VERDE.,グリーン キー ニュウシュ,획득: 초록색 열쇠.,GROENE sleutel ontvangen,Fikk den GRØNNE nøkkelen.,Zdobyto ZIELONY klucz.,Pegou a chave VERDE.,,Ai achiziționat cheia VERDE.,Получен ЗЕЛЁНЫЙ ключ.,,Skaffade den GRÖNA nyckeln.,YEŞİL anahtar elde edildi. +Obtained the YELLOW key.,GOTYELWSKUL,,,,Sebrán ŽLUTÝ klíč.,Opnået den GULLE nøgle.,GELBEN Schlüssel erhalten,,Vi trovis la FLAVAN ŝlosilon.,Encuentras la llave AMARILLA.,,KELTAINEN avain poimittu.,Clé JAUNE obtenue.,Megszerezted a SÁRGA kulcsot.,Ottenuta la chiave GIALLA.,イエロー キー ニュウシュ,획득: 노란색 열쇠.,GELE sleutel ontvangen,Fikk den GULA nøkkelen.,Zdobyto ŻÓŁTY klucz.,Pegou a chave AMARELA.,,Ai achiziționat cheia GALBENĂ.,Получен ЖЁЛТЫЙ ключ.,,Skaffade den GULLA nyckeln.,SARI anahtar elde edildi. +Obtained the PURPLE key.,GOTREDSKUL,,,,Sebrán FIALOVÝ klíč.,Opnået den LILLA nøgle.,VIOLETTEN Schlüssel erhalten,,Vi trovis la PURPURAN ŝlosilon.,Encuentras la llave VIOLETA.,,VIOLETTI avain poimittu.,Clé VIOLETTE obtenue.,Megszerezted a LILA kulcsot.,Ottenuta la chiave VIOLA.,パープル キー ニュウシュ,획득: 보라색 열쇠.,PAARSE sleutel ontvangen,Fikk den LILLA nøkkelen.,Zdobyto FIOLETOWY klucz.,Pegou a chave ROXA.,,Ai achiziționat cheia MOV.,Получен ФИОЛЕТОВЫЙ ключ.,,Skaffade den LILA nyckeln.,MOR anahtar elde edildi. +Healing mushroom,GOTSTIM,,,,Léčivka,Helbredende svamp,Heilpilz,,Saniga fungo,Seta medicinal,Hongo medicinal,Lääkesieni,Champignon médicinal,Gyógyító gomba,Funghi curativi,ヒーリング マッシュルーム,사용: 체력회복 버섯.,Genezende paddenstoel,Helbredende sopp,Leczący grzyb,Cogumelo medicinal,,Ciupercă vindecătoare,Целебный гриб,,Helande svamp,İyileştirici mantar +Acquired: medical kit.,GOTMEDIKIT,,,,Získána lékárnička.,Erhvervet: medicinsk kit.,Erhalten: Medikit,,Vi trovis sukurkeston.,Encuentras un botiquín.,,Saatu: lääkintälaukku.,Acquis: Kit médical.,Megszerezve: orvosi csomag,Acquisito: kit medico.,シュトク: メディカルキット,사용: 의료 키트.,Verworven: medische kit.,Ervervet: medisinsk sett.,Zdobyto: apteczkę.,Pegou um kit médico.,,Ridicat: Kit de Prim-Ajutor.,Получена: Аптечка.,,Förvärvad: medicinsk utrustning.,Elde edilen: tıbbi kit. +Acquired: medical kit that you REALLY need.,GOTMEDINEED,,,,"Získána lékárnička, kterou OPRAVDU potřebuješ.","Erhvervet: medicinsk kit, som du VIRKELIG har brug for.","Erhalten: Medikit, das du WIRKLICH brauchst",,"Vi trovis sukurkeston, kiun vi VERE bezonas.",Encuentras un botiquín que REALMENTE necesitabas.,,"Saatu: lääkintälaukku, jota TODELLA tarvitsit.",Acquis: Kit médical. Besoin critique.,Megszerezve: már NAGYON hiányzott orvosi csomag,Acquisito: kit medico di cui VERAMENTE avete bisogno.,シュトク: キンキュウジタイヲ スクウ メディカルキット,사용: 당신을 살려줄 의료 키트.,Verworven: medische kit die je ECHT nodig heeft.,Ervervet: medisinsk sett som du virkelig trenger.,"Zdobyto: apteczkę, której NAPRAWDĘ potrzebujesz.",Pegou um kit médico que você REALMENTE precisa.,,Ridicat: Kit de Prim-Ajutor de care CHIAR AI nevoie.,Получена: Аптечка (КРАЙНЕ необходимая).,,Förvärvad: medicinsk utrustning som du verkligen behöver.,Elde edilen: GERÇEKTEN ihtiyacınız olan tıbbi kit. +Map,GOTMAP,,,,Mapa,Kort,Karte,,Vi trovis la mapon,Mapa,,Kartta,Carte,Térkép,Mappa,コノ クイキノ マップダ ,획득: 지도.,Kaart,Kart,Mapa,Mapa,,Hartă,Карта,,Karta,Harita +Acquired: case of bullets.,GOTCLIPBOX,,,,Získána krabice nábojů.,Erhvervet: kasse med kugler.,Erhalten: Munitionskiste,,Vi trovis skatolon da kugloj.,Encuentras una caja de balas.,,Saatu: luotilaatikko.,Acquis: Boîte de balles.,Megszerezve: doboznyi lőszer.,Acquisito: caso di proiettili.,シュトク: バレット ケース,획득: 회전포 탄약.,Verworven: geval van kogels.,Ervervet: tilfelle av kuler.,Zdobyto: pudełko naboi.,Pegou uma caixa de balas,,Achiziționat: Cutie de gloanțe.,Получен: Ящик с пулями.,,Förvärvad: väska med kulor.,Elde edilen: mermi kovanı. +Acquired: Grenade.,GOTROCKET,,,,Ziskán granát.,Erhvervet: Granat.,Erhalten: Granate,,Vi trovis grenadon.,Encuentras una granada.,,Saatu: kranaatti.,Acquis: Grenade.,Megszerezve: Gránát.,Acquisito: Granata.,シュトク: グレネード,획득: 세열탄.,Verworven: Granaat.,Ervervet: Granat.,Zdobyto: Granat.,Pegou uma granada.,,Achiziționat: Grenadă.,Получена: Граната.,,Förvärvad: Granat.,Elde edildi: El bombası. +Acquired: Grenades.,GOTROCKBOX,,,,Ziskány granáty.,Erhvervet: Granater.,Erhalten: Granaten,,Vi trovis grenadojn.,Encuentras unas granadas.,,Saatu: kranaatteja.,Acquis: Grenades.,Megszerezve: Gránátok.,Acquisito: Granate.,シュトク: グレネード セット,획득: 세열탄 여러 개.,Verworven: Granaten.,Ervervet: Granater.,Zdobyto: Granaty.,Pegou granadas.,,Achiziționat: Grenade.,Получены: Гранаты.,,Förvärvad: Granater.,Elde edildi: El bombaları. +Acquired: box of shotgun shells.,GOTSHELLBOX,,,,Získána krabice broků.,Erhvervet: kasse med haglpatroner.,Erhalten: Schrotpatronen,,Vi trovis skatolon da kartoĉoj.,Encuentras una caja de cartuchos de escopeta.,,Saatu: laatikollinen haulikon patruunoita.,Acquis: Boîte de cartouches.,Megszerezve: doboznyi puska sörét,Acquisito: scatola di cartucce per fucile.,シュトク: シェル ボックス,획득: 산탄총 탄약.,Verworven: doos met shotgun schelpen.,Ervervet: eske med haglepatroner.,Zdobyto: pudełko loftek do strzelby.,Pegou uma caixa de cartuchos de espingarda.,,Achiziționat: Cutie de muniție pentru pușcă.,Получена: Коробка патронов дробовика.,,Förvärvad: låda med hagelpatroner.,Edinildi: Bir kutu av tüfeği fişeği. +Acquired: ammo backpack.,GOTBACKPACK,,,,Ziskán batoh s municí.,Erhvervet: ammunitionsrygsæk.,Erhalten: Munitionsrucksack,,Vi trovis tornistron da municioj.,Encuentras una mochila de municiones.,,Saatu: ammusreppu.,Acquis: Sac de munitions.,Megszerezve: lőszeres hátizsák,Acquisito: zaino munizioni.,シュトク: バックパック,획득: 탄약 가방.,Verworven: munitie rugzak.,Ervervet: ryggsekk med ammunisjon.,Zdobyto: plecak z amunicją.,Pegou uma mochila de munição.,,Achiziționat: Raniță.,Получен: Ранец боеприпасов.,,Förvärvad: Ammunitionsryggsäck.,Edinildi: Cephane çantası. +Acquired: Grenade.,GOTBFG9000,,,,Získán granát.,Erhvervet: Granat.,Erhalten: Granate,,Vi trovis grenadon.,Encuentras una granada.,,Saatu: kranaatti.,Acquis: Grenade.,Megszerezve: Gránát.,Acquisito: Granata.,シュトク: グレネード,획득: 세열탄.,Verworven: Granaat.,Ervervet: Granat.,Zdobyto: Granat.,Pegou uma granada.,,Achiziționat: Grenadă.,Получена: Граната.,,Förvärvad: Granat.,Elde edildi: El bombası. +Acquired: Minigun.,GOTCHAINGUN,,,,Získán kulomet.,Erhvervet: Minigun.,Erhalten: Minigun,,Vi trovis maŝinpafilon.,Encuentras una ametralladora.,,Saatu: minigun.,Acquis: Minigun.,Megszerezve: Gépfegyver.,Acquisito: Minigun.,シュトク: ミニガン,획득: 회전포.,Verworven: Minigun.,Ervervet: Minigun.,Zdobyto: Minigun.,Pegou uma metralhadora giratória.,,Achiziționat: Minimitralieră.,Получен: Пулемёт.,,Förvärvad: Minigun.,Elde edildi: Minigun. +Acquired: Grenade launcher.,GOTLAUNCHER,,,,Získán granátomet.,Erhvervet: Granatkaster.,Erhalten: Granatwerfer,,Vi trovis grenadĵetilon.,Encuentras un lanzagranadas.,,Saatu: kranaatinheitin.,Acquis: Lance-Grenades,Megszerezve: Gránátvető,Acquisito: Lanciagranate.,シュトク: グレネードランチャー,획득: 세열탄 추진기.,Verworven: Granaatwerper.,Ervervet: Granatkaster.,Zdobyto: Wyrzutnię granatów.,Pegou um lança-granadas.,,Achiziționat: Lansator de grenade.,Получен: Гранатомёт.,,Förvärvad: Granatkastare.,Elde edildi: El bombası fırlatıcı. +Entropy thrower!,GOTPLASMA,,,,Vrhač entropie!,Entropi-lancer!,Entropiewerfer,,Entropi-ĵetilon!,¡Lanzador de entropía!,,Entropianheitin!,Acquis: Lanceur d'Entropie!,Entrópiavető!,Lancia entropia!,エントロピースロワー!,획득: 엔트로피 방사기!,Entropiewerper!,Entropikaster!,Miotacz Entropii!,Lançador de entropia!,,Aruncător entropic!,Энтропиемёт!,,,Entropi fırlatıcı! +Acquired: Shotgun.,GOTSHOTGUN,,,,Získána brokovnice.,Erhvervet: Shotgun.,Erhalten: Schrotflinte,,Vi trovis kartoĉan fusilon.,Encuentras una escopeta.,,Saatu: haulikko.,Acquis: Fusil à pompe.,Megszerezve: Sörétes puska,Acquisito: Fucile.,シュトク: ショットガン,획득: 산탄총.,Verworven: Shotgun.,Ervervet: Haglgevær.,Zdobyto: Strzelbę.,Pegou uma espingarda.,,Achiziționat: Pușcă.,Получен: Дробовик.,,Förvärvad: Hagelgevär,Edinildi: Av tüfeği. +God Mode ON,STSTR_DQDON,,,,Nesmrtelnost ZAP,Gud-tilstand PÅ,Gott-Modus AN,,Dio-Reĝimo AKTIVA,Modo Dios ACTIVADO,,Kuolemattomuustila PÄÄLLÄ,Mode invulnérable ON,Isten mód BE,Modalità Dio ATTIVATA,ゴッドモード オン,무적 치트: ON,God Modus AAN,Gudsmodus PÅ,Tryb Boga WŁĄCZONY,Modo Deus LIGADO,,Modul Invincibil PORNIT,Режим Бога ВКЛЮЧЁН,,Gud läge PÅ,Tanrı Modu AÇIK +God Mode OFF,STSTR_DQDOFF,,,,Nesmrtelnost VYP,Gud-tilstand FRA,Gott-Modus AUS,,Dio-Reĝimo NEAKTIVA,Modo Dios DESACTIVADO,,Kuolemattomuustila POIS PÄÄLTÄ,Mode invulnérable OFF,Isten mód KI,Modalità Dio DISATTIVATA,ゴッドモード オフ,무적 치트: OFF,God Modus UIT,Gudsmodus AV,Tryb Boga WYŁĄCZONY,Modo Deus DESLIGADO,,Modul Invincibil OPRIT,Режим Бога ОТКЛЮЧЁН,,Gud läge AV,Tanrı Modu KAPALI +All weapons/ ammo/ keys,STSTR_KFAADDED,,,,Všechny zbraně/munice/klíče,Alle våben/ ammunition/ nøgler,"Alle Waffen, Munition und Schlüssel",,Ĉiuj armiloj/municioj/ŝlosiloj,Todas las armas/municiones/llaves,,Kaikki aseet/ ammukset/ avaimet,Toutes les armes/munitions/clés,Minden fegyver / lőszer / kulcs,Tutte le armi / munizioni / chiavi,スベテノ ブキ/カギ/ダンヤク,추가: 모든 무기/탄약/열쇠 치트,Alle wapens / munitie / sleutels,Alle våpen / ammunisjon / nøkler,Wszystkie bronie/amunicja/klucze,Todas as armas/munição/chaves,,Toate armele/muniție/chei,Всё оружие/боеприпасы/ключи,,Alla vapen/ammunition/nycklar,Tüm silahlar/ cephane/ anahtarlar +All weapons and ammo,STSTR_FAADDED,,,,Všechny zbraně a munice,Alle våben og ammunition,Alle Waffen und Munition,,Ĉiuj armiloj kaj municioj,Todas las armas y municiones,,Kaikki aseet ja ammukset,Toutes les armes et munitions,Minden fegyver és lőszer,Tutte le armi e le munizioni,スベテノ ブキ/ダンヤク,추가: 모든 무기/탄약 치트,Alle wapens en munitie,Alle våpen og ammunisjon,Wszystkie bronie i amunicja,Todas as armas e munição completa,,Toate armele și muniție,Всё оружие и боеприпасы,,Alla vapen och all ammunition,Tüm silahlar ve cephane +Abduction,TXT_HARMMAP01,,,,Únos,Bortførelse,Entführung,,Forkapto,Abducción,,Sieppaus,Enlèvement,Elrablás,Il rapimento,アブダクション,유괴,Ontvoering,Bortføring,Porwanie,Sequestro,,Răpire,Похищение,,Bortförande,Kaçırılma +Harm's Way,TXT_HARMMAP02,,,,Nebezpečí,,In Gefahr,,Vojo de danĝero,En peligro,,Vaara,Mise en Danger,Baj,La via del danno,ハーム'ズ ウェイ,해함의 길,,,Niebezpieczeństwo,No Caminho do Perigo,,Calea pericolului,Опасный путь,,Harms väg,Zarar Görebilecek Durumda +Owt Mood,TXT_HARMMAP03,,,,Špatný pocit,,Missstimmung,,Sentaĉo,Buen humor,,Nollatunnelma,Scontento,Túlterhelve,Scontento,ヤバイムード,이상한 분위기,,,Paskudny Nastrój,Mau Humor,,Fricțiune,Нестроение,,Dåligt stämning,Kötü Ruh Hali +Megalapolis,TXT_HARMMAP04,,,,Megalopole,,Megalopolis,,Megtropolo,Megalópolis,,Megalopoli,Mégalopole,Megalopolisz,Megalapoli,メガラポリス,거대 도시,Megalopolis,,Megalapolis,Megalópole,,Megalopolis,Мегалаполис,,,Megalapolis +The Hospital,TXT_HARMMAP05,,,,Nemocnice,Hospitalet,Das Hospital,,La malsanulejo,El hospital,,Sairaala,L'Hôpital,Kórház,L'ospedale,ホスピタル,병동,Het ziekenhuis,Sykehuset,Szpital,O Hospital,,Spitalul,Больница,,Sjukhuset,Hastane +The Weapons Factory,TXT_HARMMAP06,,,,Továrna na zbraně,Våbenfabrikken,Die Waffenfabrik,,La armil-fabriko,La fábrica de armas,,Asetehdas,L'Usine d'Armes,Fegyvergyár,La fabbrica di armi,ウェポンファクトリー,무기 공장,De Wapenfabriek,Våpenfabrikken,Fabryka Broni,A Fábrica de Armamentos,,Fabrica de Arme,Оружейный завод,,Vapenfabriken,Silah Fabrikası +The Underwater Lab,TXT_HARMMAP07,,,,Podvodní laboratoř,Undervandslaboratoriet,Das Unterwasserlabor,,La subakva labotorio,El laboratorio submarino,,Vedenalainen laboratorio,Le Laboratoire Sous-marin,Vízalatti labor,Il laboratorio subacqueo,アンダーウォーターラボ,해저 연구소,Het onderwaterlaboratorium,Undervannslaboratoriet,Podwodne Laboratorium,O Laboratório Submarino,,Laboratorul Subacvatic,Подводная лаборатория,,Undervattenslaboratoriet,Sualtı Laboratuvarı +Airstrip One,TXT_HARMMAP08,,,,Přistávací dráha jedna,Landingsbane et,Flugplatz Eins,,Surteriĝejo numero unu,Pista de aterrizaje uno,,Kiitorata Yksi,Piste D'Atterrisage Un,1-es kifutó,Pista Uno,エアーシップ ワン,활주로 1호,Vliegveld Een,Flystripe én,Lądowisko Numer Jeden,Base Aérea Um,,Pista Unu,Взлётная полоса №1,,Landningsbana ett,Birinci Pist +The Launch Base,TXT_HARMMAP09,,,,Vzletová základna,Affyringsbasen,Die Startbasis,,La lanĉbazo,La base de despegue,,Laukaisutukikohta,La Base de Lancement,Kilövő Állomás,La base di lancio,ランチャーベース,발진기지,De lanceerbasis,Utskytningsbasen,Baza Startowa,A Base de Lançamento,,Baza de Lansare,Пусковая площадка,,Avfyrningsbasen,Fırlatma Üssü +The Radioactive Zone,TXT_HARMMAP10,,,,Radioaktivní zóna,Den radioaktive zone,Die radioaktive Zone,,La radioaktiva zono,La zona radioactiva,,Radioaktiivinen vyöhyke,La Zone Radioactive,Radioaktív Zóna,La zona radioattiva,ラディオアクティブ ゾーン,방사능 처리소,De Radioactieve Zone,Den radioaktive sonen,Radioaktywna Strefa,A Zona Radioativa,,Zona Radioactivă,Заражённая зона,,Den radioaktiva zonen,Radyoaktif Bölge +Echidna,TXT_HARMMAP11,,,,,,,,Ekidno,Equidna,,Nokkasiili,,Hangyászsün,,エキドナ,에키드나,,,,Equidna,,,Ехидна,,,Echidna "You feel sick to your stomach... Looking in the face of the mutant queen... That thing... That used to be... @@ -368,7 +369,27 @@ Te aduni... женщиной!» = К О Н Е Ц = -",,"Kendini mutsuz hissediyorsun... +",,"Du mår illa i magen... +När du ser mutantdrottningen i ansiktet... +Den där saken... Som brukade vara... +Din vän... Amira! + +De där monstren måste ha hittat ett +sätt att mutera henne och förvandla +henne till den här avskyvärda +varelsen för att föda sin avkomma. + +-suck- + +Ta dig samman... +De kommer att få betala för att de +tvingade dig att döda din vän... + +""Helvetet har ingen vrede som +en kvinna som är föraktad!"" + + + = S L U T E T =","Kendini mutsuz hissediyorsun... Mutant kraliçenin yüzüne bakarken. O şey. O eskiden... Arkadaşın. Amira'ydı! @@ -390,12 +411,12 @@ bir kadın gibi öfke yoktur!"" = SON =" -,WI_FINISHED,This text is deliberately empty,,,,,,,,,,,,,,,,,,,,,,,, -Loading,WI_ENTERING,Yellow needs retranslation,,,Načítá se,Indlæsning,Lade,,Ŝargante,Cargando,,Ladattavana,Chargement,Betöltés,Caricamento,ローディング,불러오는 중,Laden van,Laster,Ładowanie,Carregando,,Se încarcă,Загрузка уровня,,Yükleniyor -Very Easy,SKILL_BABY,,,,Velmi snadné,Meget let,Sehr einfach,,Tre facila,Muy fácil,,Erittäin helppo,Trés facile,Nagyon könnyű,Molto facile,ベリーイージー,아주 쉬움,Zeer gemakkelijk,Veldig lett,Bardzo Łatwy,Muito fácil,,Foarte Ușor,Очень легко,,Çok Kolay -Easy,SKILL_EASY,,,,Snadný,Let,Einfach,,Facila,Fácil,,Helppo,Facile,Könnyű,Facile,イージー,쉬움,Gemakkelijk,Lett,Łatwy,Fácil,,Ușor,Легко,,Kolay -Medium,SKILL_NORMAL,,,,Střední,Middel,Mittel,,Meza,Normal,,Keskivaikea,Moyen,Normál,Medio,ミディアム,중간,Middel,Middels,Średni,Médio,,Mediu,Средне,,Orta -Hard,SKILL_HARD,,,,Obtížný,Svær,Schwer,,Malfacila,Difícil,,Vaikea,Difficile,Nehéz,Difficile,ハード,어려움,Moeilijk,Vanskelig,Trudny,Difícil,,Greu,Тяжело,,Sert -Very Hard,SKILL_NIGHTMARE,,,,Velmi obtížné,Meget svær,Sehr schwer,,Tre malfacila,Muy difícil,,Erittäin vaikea,Très difficile,Nagyon nehéz,Molto difficile,ベリーハード,아주 어려윰,Zeer moeilijk,Svært vanskelig,Bardzo Trudny,Muito difícil,,Foarte Greu,Очень тяжело,,Çok Zor -Thanks for playing,HARMQUITMSG,,,,Díky za hraní,Tak for at spille,Danke fürs Spielen,,Dankon pro ludado,Gracias por jugar,,Kiitos pelaamisesta,Merci d'avoir joué,"Köszönjük, hogy játszottál!",Grazie per aver giocato,プレイ シテクレテ カンシャスル,플레이 해주셔서 감사드립니다,Bedankt voor het spelen,Takk for at du spilte,Dziękuję za grę,Obrigado por jogar,,Mulțumim că ai jucat,"Спасибо, что сыграли в Harmony",,Oynadığınız için teşekkürler -Harmony,TXT_D2E1,,,,,,,,Harmonio,,,Harmonia,,Harmónia,,,,,,Harmonia,Harmony,,,,, \ No newline at end of file +,WI_FINISHED,This text is deliberately empty,,,,,,,,,,,,,,,,,,,,,,,,, +Loading,WI_ENTERING,Yellow needs retranslation,,,Načítá se,Indlæsning,Lade,,Ŝargante,Cargando,,Ladattavana,Chargement,Betöltés,Caricamento,ローディング,불러오는 중,Laden van,Laster,Ładowanie,Carregando,,Se încarcă,Загрузка уровня,,Laddar,Yükleniyor +Very Easy,SKILL_BABY,,,,Velmi snadné,Meget let,Sehr einfach,,Tre facila,Muy fácil,,Erittäin helppo,Trés facile,Nagyon könnyű,Molto facile,ベリーイージー,아주 쉬움,Zeer gemakkelijk,Veldig lett,Bardzo Łatwy,Muito fácil,,Foarte Ușor,Очень легко,,Mycket lätt,Çok Kolay +Easy,SKILL_EASY,,,,Snadný,Let,Einfach,,Facila,Fácil,,Helppo,Facile,Könnyű,Facile,イージー,쉬움,Gemakkelijk,Lett,Łatwy,Fácil,,Ușor,Легко,,Lätt,Kolay +Medium,SKILL_NORMAL,,,,Střední,Middel,Mittel,,Meza,Normal,,Keskivaikea,Moyen,Normál,Medio,ミディアム,중간,Middel,Middels,Średni,Médio,,Mediu,Средне,,Medel,Orta +Hard,SKILL_HARD,,,,Obtížný,Svær,Schwer,,Malfacila,Difícil,,Vaikea,Difficile,Nehéz,Difficile,ハード,어려움,Moeilijk,Vanskelig,Trudny,Difícil,,Greu,Тяжело,,Svårt,Sert +Very Hard,SKILL_NIGHTMARE,,,,Velmi obtížné,Meget svær,Sehr schwer,,Tre malfacila,Muy difícil,,Erittäin vaikea,Très difficile,Nagyon nehéz,Molto difficile,ベリーハード,아주 어려윰,Zeer moeilijk,Svært vanskelig,Bardzo Trudny,Muito difícil,,Foarte Greu,Очень тяжело,,Mycket svårt,Çok Zor +Thanks for playing,HARMQUITMSG,,,,Díky za hraní,Tak for at spille,Danke fürs Spielen,,Dankon pro ludado,Gracias por jugar,,Kiitos pelaamisesta,Merci d'avoir joué,"Köszönjük, hogy játszottál!",Grazie per aver giocato,プレイ シテクレテ カンシャスル,플레이 해주셔서 감사드립니다,Bedankt voor het spelen,Takk for at du spilte,Dziękuję za grę,Obrigado por jogar,,Mulțumim că ai jucat,"Спасибо, что сыграли в Harmony",,Tack för att du spelar,Oynadığınız için teşekkürler +Harmony,TXT_D2E1,,,,,,,,Harmonio,,,Harmonia,,Harmónia,,,,,,Harmonia,,,,,,, \ No newline at end of file diff --git a/wadsrc_extra/static/filter/harmony/zscript.txt b/wadsrc_extra/static/filter/harmony/zscript.txt index 8e78ae8c05..de34b25c0e 100644 --- a/wadsrc_extra/static/filter/harmony/zscript.txt +++ b/wadsrc_extra/static/filter/harmony/zscript.txt @@ -1,2 +1,3 @@ version "4.5" -#include "zscript/harm_sbar.zs" \ No newline at end of file +#include "zscript/harm_sbar.zs" +#include "zscript/decorate_replacement.zs" diff --git a/wadsrc_extra/static/filter/harmony/zscript/decorate_replacement.zs b/wadsrc_extra/static/filter/harmony/zscript/decorate_replacement.zs new file mode 100644 index 0000000000..24b82350a2 --- /dev/null +++ b/wadsrc_extra/static/filter/harmony/zscript/decorate_replacement.zs @@ -0,0 +1,65 @@ +class TimeBombWeapon : Weapon replaces BFG9000 +{ + default + { + scale 0.30; + weapon.kickback 100; + weapon.selectionorder 2800; + weapon.ammouse 1; + weapon.ammogive 2; + weapon.ammotype "TimeBombAmmo"; + inventory.pickupmessage "$GOTBFG9000"; + inventory.icon "BFUGA0"; + +WEAPON.NOAUTOFIRE; + +WEAPON.NOAUTOAIM; + } + + states + { + Select: + BFGG A 1 A_Raise; + loop; + Deselect: + BFGG A 1 A_Lower; + loop; + Ready: + BFGG A 1 A_WeaponReady; + loop; + Fire: + SHT2 A 3; + SHT2 A 7 A_CheckReload; + SHT2 B 1 A_BFGSound; + SHT2 B 7; + SHT2 C 6; + SHT2 D 7 A_FireGrenade; + SHT2 E 7; + SHT2 F 7 A_Light0; + SHT2 H 6 A_Light0; + SHT2 A 5 A_Refire; + goto Ready; + Flash: + BFGF A 11 bright A_Light1; + BFGF B 6 bright A_Light2; + SHTG E 0 A_Light0; + stop; + Spawn: + BFUG A -1; + stop; + } + + action void A_FireGrenade() + { + if (player == null) + { + return; + } + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, weap.ammouse1)) + return; + } + + SpawnPlayerMissile("BFGBall", angle, nofreeaim:sv_nobfgaim); + } +} diff --git a/wadsrc_extra/static/iwadinfo.txt b/wadsrc_extra/static/iwadinfo.txt index a1c419d4e0..c52f899bd6 100644 --- a/wadsrc_extra/static/iwadinfo.txt +++ b/wadsrc_extra/static/iwadinfo.txt @@ -227,6 +227,7 @@ IWad Config = "Heretic" IWADName = "blasphemer.wad" Mapinfo = "mapinfo/heretic.txt" + Compatibility = "Extended" MustContain = "E1M1", "E2M1", "TITLE", "BLASPHEM" BannerColors = "73 00 00", "00 00 00" } @@ -326,7 +327,7 @@ IWad Config = "Doom" IWADName = "doom.wad", 2 Mapinfo = "mapinfo/ultdoom.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", "E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9", "DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2", @@ -343,7 +344,7 @@ IWad Config = "Doom" IWADName = "doomunity.wad", 2 Mapinfo = "mapinfo/ultdoom.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", "E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9", "DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2", @@ -375,7 +376,7 @@ IWad Config = "Doom" IWADName = "doom.wad" Mapinfo = "mapinfo/doomxbox.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", "E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9", "DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2", "E1M10", "SEWERS" @@ -391,7 +392,7 @@ IWad Config = "Doom" IWADName = "doom.wad" Mapinfo = "mapinfo/ultdoom.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", "E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9", "DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2" @@ -407,7 +408,7 @@ IWad Config = "Doom" IWADName = "doom.wad", 1 Mapinfo = "mapinfo/doom1.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", "E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9", "DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1" @@ -422,7 +423,7 @@ IWad Game = "Doom" Config = "Doom" Mapinfo = "mapinfo/doom1.txt" - Compatibility = "Shareware", "Shorttex" + Compatibility = "Shareware", "Shorttex", "nosectionmerge" MustContain = "E1M1" BannerColors = "54 54 54", "a8 a8 a8" IgnoreTitlePatches = 1 @@ -434,7 +435,7 @@ IWad Autoname = "doom.id.doom2.tnt.unity" Game = "Doom" Config = "Doom" - IWADName = "tnt.wad" + IWADName = "tntunity.wad", 2 Mapinfo = "mapinfo/tnt.txt" Compatibility = "Shorttex", "Stairs" MustContain = "MAP01", "REDTNT2", "DMAPINFO" @@ -462,7 +463,7 @@ IWad Autoname = "doom.id.doom2.plutonia.unity" Game = "Doom" Config = "Doom" - IWADName = "plutonia.wad" + IWADName = "plutoniaunity.wad", 2 Mapinfo = "mapinfo/plutonia.txt" Compatibility = "Shorttex" MustContain = "MAP01", "CAMO1", "DMAPINFO" @@ -492,7 +493,7 @@ IWad Config = "Doom" IWADName = "doom2.wad" Mapinfo = "mapinfo/doom2bfg.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "MAP01", "DMENUPIC", "M_ACPT", "M_CAN", "M_EXITO", "M_CHG" BannerColors = "a8 00 00", "a8 a8 a8" Load = "nerve.wad" @@ -505,9 +506,9 @@ IWad Autoname = "doom.id.doom2.unity" Game = "Doom" Config = "Doom" - IWADName = "doom2unity.wad" + IWADName = "doom2unity.wad", 2 Mapinfo = "mapinfo/doom2unity.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "MAP01", "DMENUPIC" BannerColors = "00 7c 00", "a8 a8 a8" IgnoreTitlePatches = 1 @@ -522,7 +523,7 @@ IWad Config = "Doom" IWADName = "doom2.wad", 1 Mapinfo = "mapinfo/doom2xbox.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "MAP01", "MAP33", "CWILV32" BannerColors = "18 18 18", "a8 a8 a8" IgnoreTitlePatches = 1 @@ -538,7 +539,7 @@ IWad Config = "Doom" IWADName = "doom2f.wad", 1 Mapinfo = "mapinfo/doom2.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "MAP01", "WIOBJ" BannerColors = "ff ff ff", "a8 00 00" } @@ -552,7 +553,7 @@ IWad Config = "Doom" IWADName = "doom2.wad", 1 Mapinfo = "mapinfo/doom2.txt" - Compatibility = "Shorttex" + Compatibility = "Shorttex", "nosectionmerge" MustContain = "MAP01" BannerColors = "a8 00 00", "a8 a8 a8" IgnoreTitlePatches = 1 @@ -563,23 +564,22 @@ Names { "doom_complete.pk3" "doom2.wad" + "doom2unity.wad" "doom2f.wad" - "plutonia.wad" - "tnt.wad" "doomu.wad" "doom.wad" + "doomunity.wad" "doom1.wad" - "bfgdoom2.wad" - "doom2bfg.wad" "bfgdoom.wad" + "bfgdoom2.wad" "doombfg.wad" + "doom2bfg.wad" "doomxbox.wad" "doom2xbox.wad" - "doomunity.wad" - "doom2unity.wad" - "doom2f.wad" - "tntunity.wad" + "plutonia.wad" "plutoniaunity.wad" + "tnt.wad" + "tntunity.wad" "freedoom1.wad" "freedoom2.wad" "freedoomu.wad" @@ -614,18 +614,18 @@ Order // Order in the IWAD selection box "DOOM: Complete: WadSmoosh" "DOOM 2: Hell on Earth" "DOOM 2: L'Enfer sur Terre" - "Final Doom: Plutonia Experiment" - "Final Doom: TNT - Evilution" "The Ultimate DOOM" "DOOM Registered" "DOOM Shareware" - "DOOM 2: BFG Edition" "DOOM: BFG Edition" + "DOOM 2: BFG Edition" "DOOM: XBox Edition" "DOOM 2: XBox Edition" "DOOM: Unity Edition" "DOOM 2: Unity Edition" + "Final Doom: Plutonia Experiment" "Final Doom: Plutonia Experiment: Unity Edition" + "Final Doom: TNT - Evilution" "Final Doom: TNT - Evilution: Unity Edition" "Freedoom: Phase 1" "Freedoom: Phase 2" diff --git a/wadsrc_extra/static/language.csv b/wadsrc_extra/static/language.csv index 2def38e364..a4e0b00534 100644 --- a/wadsrc_extra/static/language.csv +++ b/wadsrc_extra/static/language.csv @@ -1,316 +1,316 @@ -default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,tr -,,Doom Episode names,,,,,,,,,,,,,,,,,,,"As long as there is no other Portuguese variant, the language ID should be two letters only!",,,,, -Knee-Deep in the Dead,TXT_D1E1,,,,Po kolena v mrtvých,Knæet dybt i de døde,Knietief im Tod,Βουτηγμένος στους Νεκρούς μέχρι τα γόνατα,Ĝisgenue en la Mortintoj,Hasta las Rodillas entre Muertos,,Polvia myöten vainajissa,Plongé dans la Mort,Térdig halálban,Nella morte fino al collo,膝元迫る亡者,끝없이 밀려오는 죽음,Knie-diep in de Doden,Knedyp i de døde,Po kolana w trupach,Corpos até os Joelhos,,Îngropat printre Cadavre,По колено в трупах,До колена у лешевима,Ölüme Diz Boyu -The Shores of Hell,TXT_D1E2,,,,Břehy pekla,Helvedes kyster,Die Ufer der Hölle,Οι Ακτές της Κόλασης,La Bordoj de Infero,Las Orillas del Infierno,,Hornan rannat,Les Portes de l'Enfer,A pokol tornáca,Le rive dell'Inferno,地獄の瀬戸際,지옥의 해변,De Oevers van de Hel,Helvetes kyster,Przedsionek Piekieł,As Margens do Abismo,,Țărmurile Iadului,Прибрежье преисподней,Обале пакла,Cehennem Kıyıları -Inferno,TXT_D1E3,,,,,,,Πυρ το Εξώτερον,,,,,,Alvilág,,インフェルノ,연옥,,,Piekło,,,Infernul,Инферно,Инферно,İnferno +default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,da,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,no nb,pl,pt,ptg,ro,ru,sr,sv,tr +,,Doom Episode names,,,,,,,,,,,,,,,,,,,"As long as there is no other Portuguese variant, the language ID should be two letters only!",,,,,, +Knee-Deep in the Dead,TXT_D1E1,,,,Po kolena v mrtvých,Knæet dybt i de døde,Knietief im Tod,Βουτηγμένος στους Νεκρούς μέχρι τα γόνατα,Ĝiskole inter mortintoj,Hasta el cuello entre muertos,,Polvia myöten vainajissa,Plongé dans la Mort,Térdig halálban,Nella morte fino al collo,膝元迫る亡者,끝없이 밀려오는 죽음,Knie-diep in de Doden,Knedyp i de døde,Po kolana w trupach,Corpos até os Joelhos,,Îngropat printre Cadavre,По колено в трупах,До колена у лешевима,Knä-djupt i de döda,Ölüme Diz Boyu +The Shores of Hell,TXT_D1E2,,,,Břehy pekla,Helvedes kyster,Die Ufer der Hölle,Οι Ακτές της Κόλασης,La Infer-bordoj,Las orillas del Infierno,,Hornan rannat,Les Portes de l'Enfer,A pokol tornáca,Le rive dell'Inferno,地獄の瀬戸際,지옥의 해변,De Oevers van de Hel,Helvetes kyster,Przedsionek piekieł,As Margens do Abismo,,Țărmurile Iadului,Прибрежье преисподней,Обале пакла,Helvetets stränder,Cehennem Kıyıları +Inferno,TXT_D1E3,,,,,,,Πυρ το Εξώτερον,,,,,,Alvilág,,インフェルノ,연옥,,,,,,Infernul,Инферно,Инферно,,İnferno Thy Flesh Consumed,TXT_D1E4,"The episode and levels' names in E4 are taken from the Bible. -Proverbs 5:11",,,Tvé tělo pozřeto,Dit kød er fortæret,Dein Leib verzehrt,Η Σάρκα σου θα Καταναλωθεί,Via Karno Konsumita,Tu Carne Consumida,,Lihasi kulutettu,Votre Chair Consumée,Megemésztetik a te húsod,La tua Carne Consumata,滅びし汝の身,쇠패해진 그대의 육신,Uw Vlees Geconsumeerd,Ditt kjøtt fortæres,Ciało Twe Zwiotczeje,No Consumir-se da Tua Carne,,Carnea ta Fără de Vlagă,Твоя плоть поглощена,Твоје месо строшено,Etin Tükendi -Hell On Earth,TXT_D2E1,,,,Peklo na zemi,Helvede på jorden,Hölle auf Erden,Αρμαγεδδών,Infero Sur La Tero,Infierno en la Tierra,,Helvetti maan päällä,Enfer sur Terre,Földi pokol,Inferno sulla Terra,第三惑星:地獄,지상에 강림한 지옥,Hel op Aarde,Helvete på jorden,Piekło na Ziemi,Inferno na Terra,,Iadul pe Pământ,Ад на Земле,Пакао на Земљи,Yeryüzündeki Cehennem -No Rest for the Living,TXT_D2E2,"References ""No rest for the wicked"" in Isaiah 48:22",,,Nemajíť živí pokoje,Ingen hvile for de levende,Keine Ruhe für die Lebenden,Καμία Ανάπαυση για τους Ζωντανούς,Nenia Ripozo por la Vivantoj,No hay Descanso para los Vivos,,Ei lepoa eläville,Pas de repos pour les vivants,Nincs nyugodalom az élőnek,Nessun Riposo per i Vivi,休息なき生計,산 자에게 휴식은 없다,Geen Rust voor de Levenden,Ingen hvile for de levende,Brak Wytchnienia Dla Żywych,Não Há Descanso Para os Vivos,,Cei vii Fără de Odihnă,Не будет покоя живым,Нема одмора живима,Yaşayanlara Huzur Yok -The Plutonia Experiment,TXT_PLUT_EP,,,,Experiment Plutonia,Plutonia-eksperimentet,Das Plutonia Experiment,Το Πείραμα Πλουτώνια,La Eksperimento de Plutonia,El Experimento Plutonia,,Plutoniakokemus,L'expérience Plutonia,A Plutonia-kísérlet,L'Esperimento di Plutonia,プルトニア記,플루토니아 익스페리먼트,Het Plutonia Experiment,Plutonia-eksperimentet,Eksperyment Plutonia,O Experimento Plutonia,A Experiência Plutonia,Experimentul Plutonia,Эксперимент «Плутония»,Експеримент Плутонија,Plutonia Deneyi -TNT: Evilution,TXT_TNT_EP,,,,TNT: Zlovoluce,,,ΤΝΤ: Κακοξέλιξη,TNT: Mavalucio,TNT: Diabolución,,TNT: Paholuutio,,,TNT: Malvoluzione,TNT:邪神化,TNT: 이블루션,Tnt: Evilutie,,TNT: Ewolucja Zła,TNT: Malvolução,,TNT: Diavoluția,TNT: Дьяволюция,TNT: Ђаволуција,TNT: Evilution -Chex Quest,TXT_CHEX_EP,,,,Mise Chex,,,Η Περιπέτεια του Chex,Aventuro de Chex,,,Chex-seikkailu,,,,チェックス クエスト,첵스 퀘스트,,,Misja Chex,,,,,Чекс Квест,Chex Quest -,,Level names,,,,,,,,,,,,,,,,,,,,,,,, -,,Doom 1,,,,,,,,,,,,,,,,,,,,,,,, -E1M1: Hangar,HUSTR_E1M1,,,,E1M1: Hangár,,,E1Χ1: Υπόστεγο,E1M1: Hangaro,,,E1M1: Lentoalushalli,,E1M1: Hangár,,E1M1: 格納庫,E1M1: 격납고,,,E1M1: Hangar,E1M1: Hangar,,E1M1: Hangar,E1M1: Ангар,E1M1: Хангар,E1M1: Hangar -E1M2: Nuclear Plant,HUSTR_E1M2,,,,E1M2: Jaderná elektrárna,E1M2: Atomkraftværk,E1M2: Kernkraftwerk,E1Χ2: Πυρηνικό Εργοστάσιο,E1M2: Nuklea Centralo,E1M2: Planta Nuclear,,E1M2: Ydinvoimala,E1M2: Centrale Nucléaire,E1M2: Atomerőmű,E1M2: Centrale Nucleare,E1M2: 原子力発電所,E1M2: 원자력 발전소,E1M2: Kerncentrale,E1M2: Kjernekraftverk,E1M2: Elektrownia Jądrowa,E1M2: Usina Nuclear,E1M2: Central Nuclear,E1M2: Uzina Nucleară,E1M2: Атомная электростанция,E1M2: Нуклеарна електрана,E1M2: Nükleer Santral -E1M3: Toxin Refinery,HUSTR_E1M3,,,,E1M3: Chemická rafinerie,E1M3: Giftraffinaderi,E1M3: Giftraffinerie,E1Χ3: Διυλιστήριο Τοξινών,E1M3: Toksin-Rafinejo,E1M3: Refinería de Toxinas,,E1M3: Myrkkyjalostamo,E1M3: Raffinerie de Toxines,E1M3: Méregfinomító,E1M3: Raffineria delle Tossine,E1M3: 毒素精錬所 ,E1M3: 폐기물 정제소,E1M3: Giftstofraffinaderij,E1M3: Giftraffineri,E1M3: Rafineria Toksyn,E1M3: Refinaria de Toxinas,,E1M3: Rafinăria de Toxine,E1M3: Очистной завод,E1M3: Рафинерија за токсине,E1M3: Toksin Rafinerisi -E1M4: Command Control,HUSTR_E1M4,,,,E1M4: Řídící velín,E1M4: Kommandokontrol,E1M4: Betriebssteuerung,E1Χ4: Κέντρο Ελέγχου,E1M4: Kontrolcentro,E1M4: Control de Mando,,E1M4: Komentohallinta,E1M4: Centre de Contrôle,E1M4: Parancsnoki vezérlő,E1M4: Centrale di Comando,E1M4: 指令管制塔,E1M4: 지휘 통제소,E1M4: Controlecentrum,E1M4: Kommandokontroll,E1M4: Kontrola Dowodzenia,E1M4: Controle de Comando,E1M4: Controlo de Comando,E1M4: Comandă și Control,E1M4: Пункт управления,E1M4: Заповедни центар,E1M4: Komuta Kontrol -E1M5: Phobos Lab,HUSTR_E1M5,,,,E1M5: Phobosská laboratoř,E1M5: Phobos-laboratorium,E1M5: Phobos-Labor,E1Χ5: Εργαστήριο Φόβου,E1M5: Fobo-Laboratorio,E1M5: Laboratorio de Fobos,,E1M5: Phoboksen laboratorio,E1M5: Laboratoires Phobos,E1M5: Phoboszi laboratórium,E1M5: Laboratorio di Phobos,E1M5: フォボス研究所,E1M5: 포보스 연구소,E1M5: Phobos Laboratorium,E1M5: Phobos-laboratorium,E1M5: Laboratoria Fobosa,E1M5: Laboratório de Fobos,,E1M5: Laboratorul Phobos,E1M5: Лаборатория Фобоса,E1M5: Лабораторија на Фобосу,E1M5: Phobos Laboratuvarı -E1M6: Central Processing,HUSTR_E1M6,,,,E1M6: Centrální zpracování,E1M6: Central behandling,E1M6: Zentralverarbeitung,E1Χ6: Κεντρική Επεξεργασία,E1M6: Centra Eskpedado,E1M6: Procesador Central,,E1M6: Käsittelykeskus,E1M6: Centre de Traitement,E1M6: Központi feldolgozó,E1M6: Zona Elaboratori,E1M6: 中央処理施設,E1M6: 중앙 처리 본부,E1M6: Centrale Verwerking,E1M6: Sentral prosessering,E1M6: Centralne Przetwarzanie,E1M6: Processamento Central,,E1M6: Prelucrare Centrală,E1M6: Центральный пункт обработки,E1M6: Централна обрада,E1M6: Merkezi İşlem -E1M7: Computer Station,HUSTR_E1M7,,,,E1M7: Počítačová stanice,E1M7: Computerstation,E1M7: Computerstation,E1Χ7: Σταθμός Υπολογιστών,E1M7: Komputila Stacio,E1M7: Estación de Cómputo,,E1M7: Tietokoneasema,E1M7: Station Informatique,E1M7: Számítógépes központ,E1M7: Stazione dei Computer,E1M7: コンピューターステーション,E1M7: 컴퓨터 기지,E1M7: Computerstation,E1M7: Datastasjon,E1M7: Stacja Komputerowa,E1M7: Estação de Computadores,,E1M7: Stația de Calculatoare,E1M7: Вычислительный центр,E1M7: Компјутерска станица,E1M7: Bilgisayar İstasyonu -E1M8: Phobos Anomaly,HUSTR_E1M8,,,,E1M8: Phobosská anomálie,E1M8: Phobos-anomali,E1M8: Phobos-Anomalie,E1Χ8: Ανωμαλία στον Φόβο,E1M8: Nenormalaĵo de Fobo,E1M8: Anomalía de Fobos,,E1M8: Phoboksen poikkeama,E1M8: Anomalie de Phobos,E1M8: Phoboszi anomália,E1M8: L'anomalia di Phobos,E1M8: フォボス アノマリー,E1M8: 포보스 이상거점,E1M8: Phobos Anomalie,E1M8: Phobos-anomali,E1M8: Anomalia Fobosa,E1M8: Anomalia de Fobos,,E1M8: Anomalia Phobos,E1M8: Аномалия Фобоса,E1M8: Аномалија на Фобосу,E1M8: Phobos Anomalisi -E1M9: Military Base,HUSTR_E1M9,,,,E1M9: Vojenská základna,E1M9: Militærbase,E1M9: Militärbasis,E1Χ9: Στρατιωτική Βάση,E1M9: Militbazo,E1M9: Base Militar,,E1M9: Sotilastukikohta,E1M9: Base Militaire ,E1M9: Katonai bázis,E1M9: Base militare,E1M9: 軍事基地,E1M9: 군사 기지,E1M9: Militaire Basis,E1M9: Militærbase,E1M9: Baza Wojskowa,E1M9: Base Militar,,E1M9: Baza Militară,E1M9: Военная база,E1M9: Војна база,E1M9: Askeri Üs -E1M10: Sewers,HUSTR_E1M10,,,,E1M10: Kanály,E1M10: Kloakkerne,E1M10: Kanalisation,,E1M10: Kloakoj,E1M10: Alcantarillas,,E1M10: Viemärit,E1M10: Egouts,E1M10: Kanálisok,E1M10: Le Fogne,E1M10: 下水道,E1M10: 하수구,E1M10: De Rioleringen,E1M10: Kloakk,E1M10: Ścieki,E1M10: Os Esgotos,,E1M10: Canalizarea,E1M10: Канализация,E1M10: Канализација,E1M10: Kanalizasyonlar -E2M1: Deimos Anomaly,HUSTR_E2M1,,,,E2M1: Deimosská anomálie,E2M1: Deimos Anomali,E2M1: Deimos-Anomalie,E2Χ1: Ανωμαλία στον Δείμο,E2M1: Nenormalaĵo de Dejmo,E2M1: Anomalía de Deimos,,E2M1: Deimoksen poikkeama,E2M1: Anomalie de Déimos,E2M1: Deimoszi anomália,E2M1: L'anomalia di Deimos,E2M1: 異常なるダイモス,E2M1: 데이모스 이상거점,E2M1: Deimos Anomalie,E2M1: Deimos-anomali,E2M1: Anomalia Deimosa,E2M1: Anomalia de Deimos,,E2M1: Anomalia Deimos,E2M1: Аномалия Деймоса,E2M1: Аномалија на Дејмосу,E2M1: Deimos Anomalisi -E2M2: Containment Area,HUSTR_E2M2,,,,E2M2: Skladiště,E2M2: Indespærringsområde,E2M2: Lagerhalle,E2Χ2: Ζώνη Περιορισμού,E2M2: Enhavarejo,E2M2: Área de Confinamiento,,E2M2: Säilöntäalue,E2M2: Zone de Stockage,E2M2: Raktár,E2M2: Area di contenimento,E2M2: 収容エリア,E2M2: 화물 보관구역,E2M2: Inperkingsgebied,E2M2: Innesperringsområde,E2M2: Obszar Zastrzeżony,E2M2: Area de Contenção,E2M2: Área de Confinamento,E2M2: Zona de Izolare,E2M2: Зона сдерживания,E2M2: Складишта,E2M2: Çevreleme Alanı -E2M3: Refinery,HUSTR_E2M3,,,,E2M3: Rafinerie,E2M3: Raffinaderi,E2M3: Raffinerie,E2Χ3: Διυλιστήριο,E2M3: Rafinejo,E2M3: Refinería,,E2M3: Jalostamo,E2M3: Raffinerie,E2M3: Finomító,E2M3: Raffineria,E2M3: 精製所,E2M3: 정제소,E2M3: Raffinaderij,E2M3: Raffineri,E2M3: Rafineria,E2M3: Refinaria,,E2M3: Rafinărie,E2M3: Перерабатывающий завод,E2M3: Рафинерија,E2M3: Rafineri -E2M4: Deimos Lab,HUSTR_E2M4,,,,E2M4: Deimosská laboratoř,E2M4: Deimos-laboratorium,E2M4: Deimos Labor,E2Χ4: Εργαστήριο Δείμου,E2M4: Dejmo-Laboratorio,E2M4: Laboratorio de Deimos,,E2M4: Deimoksen laboratorio,E2M4: Laboratoires Déimos,E2M4: Deimoszi laboratórium,E2M4: Laboratorio di Deimos,E2M4: ダイモス研究所,E2M4: 데이모스 연구소,E2M4: Deimos Laboratorium,E2M4: Deimos-laboratoriet,E2M4: Laboratoria Deimosa,E2M4: Laboratório de Deimos,,E2M4: Laboratorul Deimos,E2M4: Лаборатория Деймоса,E2M4: Лабораторија на Дејмосу,E2M4: Deimos Laboratuvarı -E2M5: Command Center,HUSTR_E2M5,,,,E2M5: Řídící středisko,E2M5: Kommandocentral,E2M5: Kommandozentrum,E2Χ5: Κέντρο Διοίκησης,E2M5: Komandcentro,E2M5: Centro de Mando,,E2M5: Komentokeskus,E2M5: Centre de Commandement,E2M5: Központi parancsnokság,E2M5: Centro di Comando,E2M5: 指令本部,E2M5: 사령부,E2M5: Commandocentrum,E2M5: Kommandosentralen,E2M5: Centrum Dowodzenia,E2M5: Centro de Comando,,E2M5: Centru de Comandă,E2M5: Командный центр,E2M5: Командни центар,E2M5: Komuta Merkezi -E2M6: Halls of the Damned,HUSTR_E2M6,,,,E2M6: Chodby zatracených,E2M6: De Forbandedes haller,E2M6: Säle der Verdammten,E2X6: Διάδρομοι των Κολασμένων,E2M6: Koridoroj de la Damnitaj,E2M6: Salones de los Malditos,,E2M6: Kirottujen salit,E2M6: Halls des Damnés,E2M6: Az átkozottak termei,E2M6: Sale dei Dannati,E2M6: ダムドの会堂,E2M6: 저주받은 회랑,E2M6: Zalen der Verdoemden,E2M6: De fordømtes haller,E2M6: Korytarze Przeklętych,E2M6: Salões dos Condenados,,E2M6: Camerele Blestemaților,E2M6: Залы проклятых,E2M6: Дворана проклетих,E2M6: Lanetliler Salonu -E2M7: Spawning Vats,HUSTR_E2M7,,,,E2M7: Plodné kádě,E2M7: Spirebassiner,E2M7: Materialisationskammern,E2X7: Δεξαμενές Γέννησης,E2M7: Nasko-Kuvegoj,E2M7: Silos de Materialización,,E2M7: Sikiämissammiot,E2M7: Cuves de Reproduction,E2M7: Szaporító tartályok,E2M7: Vasche di Riproduzione,E2M7: 産卵桶,E2M7: 산란독,E2M7: Materialisatietanks,E2M7: Gytekarene,E2M7: Kadzie Reprodukcyjne,E2M7: Tanques de Criação,,E2M7: Cuve de Reproducere,E2M7: Нерестилище,E2M7: Размножавалиште,E2M7: Yumurtlama Fıçıları -E2M8: Tower of Babel,HUSTR_E2M8,,,,E2M8: Babylonská věž,E2M8: Babelstårn,E2M8: Turmbau zu Babel,E2Χ8: Πύργος της Βαβέλ,E2M8: Turo de Babelo,E2M8: Torre de Babel,,E2M8: Baabelin torni,E2M8: Tour de Babel,E2M8: Bábel tornya,E2M8: Torre di Babele,E2M8: バベルの塔,E2M8: 바벨탑,E2M8: Toren van Babel,E2M8: Babels tårn,E2M8: Wieża Babel,E2M8: Torre de Babel,,E2M8: Turnul Babel,E2M8: Вавилонская башня,E2M8: Вавилонска кула,E2M8: Babil Kulesi -E2M9: Fortress of Mystery,HUSTR_E2M9,,,,E2M9: Pevnost záhad,E2M9: Mysteriets fæstning,E2M9: Geheimnisvolle Festung,E2Χ9: Φρούριο του Μυστηρίου,E2M9: Fortreso de Mistero,E2M9: Fortaleza del Misterio,,E2M9: Salaperäisyyden linnake,E2M9: Mystérieuse Forteresse,E2M9: A rejtélyek erődje,E2M9: Fortezza del Mistero,E2M9: 神秘の要塞,E2M9: 신비의 요새,E2M9: Vesting der Mysterie,E2M9: Mysteriets festning,E2M9: Forteca Tajemnic,E2M9: Fortaleza do Mistério,,E2M9: Fortăreața Misterelor,E2M9: Крепость тайн,E2M9: Тврђава тајни,E2M9: Gizem Kalesi -E3M1: Hell Keep,HUSTR_E3M1,,,,E3M1: Pekelná tvrz,E3M1: Helvedesborg,E3M1: Höllenbollwerk,E3Χ1: Ακροπύργιο της Κολάσεως,E3M1: Infera Loĝejturo,E3M1: Torreón del Infierno,E3M1: Torre del Infierno,E3M1: Hornantorni,E3M1: Donjon Infernal,E3M1: A pokol bástyái,E3M1: Bastioni dell'Inferno,E3M1: 牢獄,E3M1: 지옥 성채,E3M1: Helleslot,E3M1: Helvetes borg,E3M1: Twierdza Piekieł,E3M1: Torre do Inferno,,E3M1: Fortul Iadului,E3M1: Крепость Ада,E3M1: Тврђава пакла,E3M1: Cehennem Kalesi -E3M2: Slough of Despair,HUSTR_E3M2,,,,E3M2: Bažina zoufalství,E3M2: Fortvivlelsens sump,E3M2: Sumpf der Verzweiflung,E3Χ2: Έλος της Απελπισίας,E3M2: Ŝlimejo de Malespero,E3M2: Ciénaga de la Desesperación,,E3M2: Epätoivon räme,E3M2: Bourbier du Désespoir,E3M2: A kétségbeesés mocsara,E3M2: Palude della Disperazione,E3M2: 絶望の大地,E3M2: 절망의 심연,E3M2: Moeras der Wanhoop,E3M2: Fortvilelsens sump,E3M2: Bagno Rozpaczy,E3M2: Lamaçal do Desespero,,E3M2: Mlaștinile Disperării,E3M2: Трясина отчаяния,E3M2: Блато очајања,E3M2: Umutsuzluk Slough'u -E3M3: Pandemonium,HUSTR_E3M3,,,,,E3M3: Pandemonium,E3M3: Pandämonium,E3Χ3: Πανδαιμόνιο,E3M3: Pandemonio,E3M3: Pandemonio,,,E3M3: Pandémonium,E3M3: Zűrzavar,E3M3: Pandemonio,E3M3: 伏魔殿,E3M3: 복마전,,,E3M3: Piekło,E3M3: Pandemônio,,E3M3: Pandemoniu,E3M3: Пандемоний,E3M3: Пандемонијум,E3M3: Pandemonium -E3M4: House of Pain,HUSTR_E3M4,,,,E3M4: Dům bolesti,E3M4: Hus af smerte,E3M4: Haus des Schmerzes,E3Χ4: Σπίτι του Πόνου,E3M4: Domo de Doloro,E3M4: Casa del Dolor,,E3M4: Tuskanmaja,E3M4: Maison de la Douleur,E3M4: A kínok háza,E3M4: Casa del Dolore,E3M4: 苦痛の館,E3M4: 고통의 집,E3M4: Huis van Pijn,E3M4: Smertens hus,E3M4: Dom Bólu,E3M4: Casa da Dor,,E3M4: Casa Durerii,E3M4: Обитель боли,E3M4: Кућа патње,E3M4: Acı Evi -E3M5: Unholy Cathedral,HUSTR_E3M5,,,,E3M5: Bezbožná katedrála,E3M5: Uhellig katedral,E3M5: Unheilige Kathedrale,E3X5: Ανίερος Καθεδρικός,E3M5: Malsankta Katedralo,E3M5: Catedral Profana,,E3M5: Epäpyhä katedraali,E3M5: Cathédrale Profane,E3M5: Az istentelen katedrális ,E3M5: Cattedrale Blasfema,E3M5: 邪教の大聖堂,E3M5: 불경한 성당,E3M5: Onheilige Kathedraal,E3M5: Den vanhellige katedralen,E3M5: Bluźniercza Katedra,E3M5: Catedral Profana,,E3M5: Catedrala Necurată,E3M5: Нечестивый собор,E3M5: Несвета катедрала,E3M5: Kutsal Olmayan Katedral -E3M6: Mt. Erebus,HUSTR_E3M6,,,,E3M6: Hora Erebus,,,E3X6: Όρος Έρεβος,E3M6: Monto de Erebo,E3M6: Monte Erebus,,E3M6: Erebusvuori,E3M6: Mont Erèbe,E3M6: Erebus-hegy,E3M6: Monte Erebus,E3M6: エレボス山,E3M6: 에레버스 산,,E3M6: Erebus-fjellet,E3M6: Góra Erebus,E3M6: Monte Érebo,,E3M6: M. Erebus,E3M6: Гора Эребус,E3M6: Планина Еребус,E3M6: Erebus Dağı -E3M7: Limbo,HUSTR_E3M7,,,,E3M7: Předpeklí,,,E3Χ7: Είσοδος της Κολάσεως,,,,E3M7: Limbus,E3M7: Limbes,E3M7: Limbus,E3M7: Limbo,E3M7: 忘却の地,E3M7: 고성소,,,E3M7: Otchłań,E3M7: Limbo,,E3M7: Limb,E3M7: Чистилище,E3M7: Лимбо,E3M7: Araf -E3M8: Dis,HUSTR_E3M8,"Based on the City of Dis, located on the sixth circle of Hell, according to Dante Alighieri's The Divine Comedy",,,,,,E3Χ8: Δίτα,,,,,,,E3M8: Dite,E3M8: 死,E3M8: 디스,,,E3M8: Dis,E3M8: Dite,,E3M8: Dite,E3M8: Дит,E3M8: Дис,E3M8: Dis -E3M9: Warrens,HUSTR_E3M9,,,,E3M9: Brlohy,E3M9: Rotteboet,E3M9: Rattennest,E3X9: Λαγούμια,E3M9: Nestego,E3M9: Madrigueras,,E3M9: Sokkelot,E3M9: Clapiers,E3M9: Nyúlkert,E3M9: Le Garenne,E3M9: 兎小屋,E3M9: 토끼굴,E3M9: Doolhof,E3M9: Rottebo,E3M9: Królikarnia,E3M9: Tocas,,E3M9: Vizuini,E3M9: Изнорье,E3M9: Одгајалиште,E3M9: Sıçan yuvası -E4M1: Hell Beneath,HUSTR_E4M1,Proverbs 15:24,,,E4M1: Peklo v hlubinách,E4M1: Helvede nedenunder,E4M1: Die Hölle unterwärts,E4Χ1: Κάτω Κόσμος,E4M1: Ŝeolo Malsupre,E4M1: Bajo el Infierno,,E4M1: Tuonela alhaalla,E4M1: Le Séjour des Morts,E4M1: A holtak hazája odalent,E4M1: In Basso,E4M1: 地獄の下へ,E4M1: 지옥의 밑에서,E4M1: Hel beneden,E4M1: Helvete under,E4M1: Piekło Najgłębsze,E4M1: Inferno Abaixo,E4M1: Inferno Profundo,E4M1: Iadul de Jos,E4M1: Преисподняя под ногами,E4M1: Пакао одоздо,E4M1: Cehennem Altında -E4M2: Perfect Hatred,HUSTR_E4M2,Psalm 139:22,,,E4M2: Naprostá nenávist,E4M2: Perfekt had,E4M2: Perfekter Hass,E4Χ2: Τέλειο Μίσος,E4M2: Perfekta Malamo,E4M2: Odio Perfecto,,E4M2: Kaikella vihalla,E4M2: Une Parfaite Haine,E4M2: Teljes gyűlölettel,E4M2: Odio Perfetto,E4M2: 完全なる憎悪,E4M2: 완벽한 증오,E4M2: Perfecte Haat,E4M2: Perfekt hat,E4M2: Pełnia Nienawiści,E4M2: Ódio Perfeito,,E4M2: Ură Desăvârșită,E4M2: Полная ненависть,E4M2: Пуном мрзошћу,E4M2: Kusursuz Nefret -E4M3: Sever The Wicked,HUSTR_E4M3,Matthew 13:49,,,E4M3: Oddělit zkažené,E4M3: Afskære de onde,E4M3: Scheidet die Bösen,E4Χ3: Ξερίζωσε τους Πονηρούς,E4M3: Apartigi la Malbonulojn,E4M3: Cercena a los impíos,,E4M3: Erottavat pahat,E4M3: Séparer les Vicieux,E4M3: Felnégyelni a bűnösöket,E4M3: Separeranno I Cattivi,E4M3: 邪悪を絶つ,E4M3: 악령처단,E4M3: Scheid de goddelozen af,E4M3: Skille ut de onde,E4M3: Oddzielą Niegodziwych,E4M3: Separarão os Maus,E4M3: Separarão o Mal,E4M3: Să Desparți pe Cei Răi,E4M3: Отделить злых,E4M3: Одлучи зле,E4M3: Kötüleri Kesin -E4M4: Unruly Evil,HUSTR_E4M4,James 3:8,,,E4M4: Nezkrotitelné zlo,E4M4: Ustyrlig ondskab,E4M4: Schandbare Worte,E4X4: Ασυγκράτητο Κακό,E4M4: Neretenebla Malbono,E4M4: Maldad Incontrolable,,E4M4: Levotointa pahuutta,E4M4: Un Mal Irrépréssible,E4M4: Féktelen gonosz,E4M4: Male Senza Posa,E4M4: 手に負えない邪悪,E4M4: 광폭한 악마,E4M4: Het weerbarstige kwaad,E4M4: Uregjerlig ondskap,E4M4: Niepohamowane Zło,E4M4: Mal Irrefreável,E4M4: Mal que não Refreia,E4M4: Un Rău fără Astâmpăr,E4M4: Неудержимое зло,Е4М4: Немирно зло,E4M4: Asi Kötülük -E4M5: They Will Repent,HUSTR_E4M5,Luke 16:30,,,E4M5: Budou činit pokání,E4M5: De vil omvende sig,E4M5: Sie werden bereuen,E4X5: Θα Μετανοήσουν,E4M5: Ili Pentos,E4M5: Se Arrepentirán,,E4M5: He parannuksen tekisivät,E4M5: Ils se repentiront,E4M5: Megtérnek majd,E4M5: Si Ravvederanno,E4M5: 奴等に後悔を,E4M5: 그들은 회개할 지어다,E4M5: Ze zullen berouw hebben,E4M5: De vil omvende seg,E4M5: Nawrócą Się,E4M5: Arrepender-se,E4M5: Eles Arrepender-se-iam,E4M5: Se vor Pocăi,E4M5: Они покаются,E4M5: Покајаће се,E4M5: Tövbe Edecekler -E4M6: Against Thee Wickedly,HUSTR_E4M6,Psalm 139:20,,,E4M6: Při svých pletichách,E4M6: Mod dig ondskabsfuldt,E4M6: Feinde erheben sich,E4X6: Κακόβουλα Εναντίον Σου,E4M6: Kontraŭ Vi Malvirte,E4M6: Perversamente contra ti,,E4M6: Sinusta petollisesti,E4M6: D'une manière criminelle,E4M6: Hitványul ellened,E4M6: Contro di te Malvagiamente,E4M6: 汝への悪逆,E4M6: 그대와 짖궂게 맞서다,E4M6: Tegen de goddeloze,E4M6: Mot deg ondskapsfullt,E4M6: Podstępnie Przeciw Tobie,E4M6: Malvadamente Contra Ti,,E4M6: Te Grăiesc de Rău,E4M6: Против тебя нечестиво,E4M6: Ружно на тебе,E4M6: Sana Karşı Kötüce -E4M7: And Hell Followed,HUSTR_E4M7,Revelation 6:8,,,E4M7: A peklo šlo za ním,E4M7: Og Helvede fulgte efter,E4M7: Und die Hölle folgte,E4X7: Και η Κόλαση Ακολούθησε,E4M7: Kaj Hades Sekvis,E4M7: Y el Infierno Continuó,,E4M7: Ja Tuonela seurasi,E4M7: Et l'Enfer Suivit,E4M7: És a pokol követé azt,E4M7: E l'inferno seguitava,E4M7: そして地獄は従った,E4M7: 그리고 지옥이 뒤따른다,E4M7: En de hel volgde,E4M7: Og helvete fulgte,E4M7: A Piekło Szło Za Nim,E4M7: E o Inferno Seguia,E4M7: Inferno o Seguia,E4M7: Iadul se Ținea după El,E4M7: И последовал Ад,E4M7: И пакао иђаше,E4M7: Ve Cehennem Takip Etti -E4M8: Unto The Cruel,HUSTR_E4M8,Proverbs 5:9,,,E4M8: Ukrutníku odevzdáš,E4M8: Til de grusomme,E4M8: Deine Jahre dem Grausamen,E4X8: Προς Τους Ανελεήμονες,E4M8: Al La Kruelulo,E4M8: En lo Cruel,,E4M8: Armottomalle,E4M8: A un Homme cruel,E4M8: A kegyetlennek,E4M8: Al Crudele,E4M8: 容赦なき者へ,E4M8: 잔혹한 자에게로,E4M8: Naar de wrede,E4M8: Til de grusomme,E4M8: Kto Nie Zna Litości,E4M8: Aos Cruéis,E4M8: Entregue a Cruéis,E4M8: Unuia Fără de Milă,E4M8: К мучителю,E4M8: Немилостивоме,E4M8: Zalimlere Karşı -E4M9: Fear,HUSTR_E4M9,,,,E4M9: Strach,E4M9: Frygt,E4M9: Angst,E4Χ9: Τρόμος,E4M9: Timo,E4M9: Miedo,,E4M9: Pelko,E4M9: Terreur,E4M9: Félelem,E4M9: Paura,E4M9: 恐怖,E4M9: 공포,E4M9: Angst,E4M9: Frykt,E4M9: Strach,E4M9: Medo,,E4M9: Frica,E4M9: Страх,E4M9: Страх,E4M9: Korku -,,Doom 2,,,,,,,,,,,,,,,,,,,,,,,, -Level 1: Entryway,HUSTR_1,"Note that the ""LEVEL"" part of the string will be stripped so it shouldn't be translated",,,Level 1: Vchod,Level 1: Indgang,Level 1: Eingangshalle,Επίπεδο 1: Είσοδος,Nivelo 1: Enirejo,Nivel 1: Entrada,,Taso 1: Eteiskäytävä,NIVEAU 1: Hall D'Entrée,1. Pálya: Bejárat,Livello 1: Ingresso,Level 1: 入口,레벨 1: 초입,Level 1: Ingang,Nivå 1: Inngangen,Level 1: Wejście,Fase 1: Entrada,Nível 1: Entrada,Nivelul 1: Intrarea,Уровень №1: Вход,Level 1: Улаз,Seviye 1: Giriş Yolu -Level 2: Underhalls,HUSTR_2,,,,Level 2: Podzemí,Level 2: Underbukser,Level 2: Kellergewölbe,,Nivelo 2: Subtervojoj,Nivel 2: Salones subterráneos,,Taso 2: Maanalaiset käytävät,NIVEAU 2: Souterrains,2. Pálya: Alagutak,Livello 2: Sotterranei,Level 2: 地下堂,레벨 2: 지하수로,Level 2: Onderhallen,Nivå 2: Underhaller,Level 2: Podziemia,Fase 2: Subterrâneo,Nível 2: Subterrâneo,Nivelul 2: Pasaje subterane,Уровень №2: Подземные ходы,Level 2: Подземни ходници,Seviye 2: Tulumlar -Level 3: The Gantlet,HUSTR_3,“a form of punishment in which a person is forced to run between two lines of men facing each other and armed with clubs or whips to beat the victim”,,,Level 3: Trest,Level 3: Spidsrod,Level 3: Spießrutenlauf,,Nivelo 3: La Spaliro,Nivel 3: Las Baquetas,,Taso 3: Kujanjuoksu,NIVEAU 3: Parcours du Combatant,3. Pálya: Vesszőfutás,Livello 3: Le Forche,Level 3: ガントレット,레벨 3: 건틀릿,Level 3: De gantlet,Nivå 3: Hansken,Level 3: Praszczęta,Fase 3: A Punição,Nível 3: A Punição,Nivelul 3: Stroiul,Уровень №3: Сквозь строй,Level 3: Казна,Seviye 3: Zorluk -Level 4: The Focus,HUSTR_4,,,,Level 4: Ohnisko,Level 4: Fokus,Level 4: Der Fokus,,Nivelo 4: La Fokuso,Nivel 4: El Foco,,Taso 4: Polttopiste,NIVEAU 4: Le Focus,4. Pálya: A középpont,Livello 4: L'Epicentro,Level 4: フォーカス,레벨 4: 초점,Level 4: De focus,Nivå 4: Fokus,Level 4: Skupisko,Fase 4: O Foco,Nível 4: O Foco,Nivelul 4: Focarul,Уровень №4: Средоточие,Level 4: Средиште,Seviye 4: Odaklanma -Level 5: The Waste Tunnels,HUSTR_5,,,,Level 5: Odpadní tunely,Level 5: Affaldstunnellerne,Level 5: Die Abfall-Tunnel,Επίπεδο 5: Οι Σήραγγες Αποβλήτων,Nivelo 5: La Rubtuneloj,Nivel 5: Los Túneles de Desechos,,Taso 5: Jätetunnelit,NIVEAU 5: Les Egouts,5. Pálya: Szennyvízalagutak,Livello 5: I Tunnel dei Rifiuti,Level 5: 廃棄トンネル,레벨 5: 하수도,Level 5: De afvaltunnels,Nivå 5: Avfallstunnelene,Level 5: Kanały,Fase 5: Os Túneis de Dejetos,Nível 5: Os Túneis de Dejetos,Nivelul 5: Tuneluri de deșeuri,Уровень №5: Сточные туннели,Level 5: Отпадни тунели,Seviye 5: Atık Tünelleri -Level 6: The Crusher,HUSTR_6,,,,Level 6: Drtička,Level 6: Knuseren,Level 6: Die Presse,Επίπεδο 6: Ο Συνθλιπτής,Nivelo 6: La Dispistilo,Nivel 6: La Trituradora,,Taso 6: Murskaaja,NIVEAU 6: Le Broyeur,6. Pálya: A zúzda,Livello 6: La Pressa,Level 6: クラッシャー,레벨 6: 분쇄기,Level 6: De maalmachine,Nivå 6: Knuseren,Level 6: Zgniatarka,Fase 6: O Esmagador,Nível 6: O Esmagador,Nivelul 6: Zdrobitorul,Уровень №6: Давилка,Level 6: Разбијач,Seviye 6: Kırıcı -Level 7: Dead Simple,HUSTR_7,,,,Level 7: Smrtelně prosté,Level 7: Død simpel,Level 7: Tödlich einfach,Επίπεδο 7: Πανεύκολο,Nivelo 7: Morte Simpla,Nivel 7: Simplemente Muerto,,Taso 7: Kuolettavan yksinkertainen,NIVEAU 7: Mortellement Simple,7. Pálya: Halálegyszerű,Livello 7: Morte Pura,Level 7: 死ぬほど単純,레벨 7: 죽여주는 단순함,Level 7: Dodelijk eenvoudig,Nivå 7: Helt enkelt,Level 7: Śmiertelnie Proste,Fase 7: Mortalmente Simples,Nível 7: Simplesmente Mortal,Nivelul 7: Mortal de simplu,Уровень №7: Смертельно просто,Level 7: Смртно једноставно,Seviye 7: Ölü Basit -Level 8: Tricks and Traps,HUSTR_8,,,,Level 8: Lesti a léčky,Level 8: Tricks og fælder,Level 8: Tricks und Fallen,Επίπεδο 8: Κόλπα και Παγίδες,Nivelo 8: Trukoj kaj Kaptiloj,Nivel 8: Trucos y Trampas,,Taso 8: Metkuja ja pauloja,NIVEAU 8: Ruses et Pièges,8. Pálya: Cselek és csapdák,Livello 8: Trucchi e Trappole,Level 8: 悪戯と罠,레벨 8: 속임수와 함정들,Level 8: Trucs en vallen,Nivå 8: Triks og feller,Level 8: Sztuczki i Pułapki,Fase 8: Truques e Armadilhas,Nível 8: Truques e Armadilhas,Nivelul 9: Surprize și capcane,Уровень №8: Уловки и ловушки,Level 8: Замке и смицалице,Seviye 8: Hileler ve Tuzaklar -Level 9: The Pit,HUSTR_9,,,,Level 9: Jáma,Level 9: Gruben,Level 9: Die Grube,Επίπεδο 9: Λάκκος,Nivelo 9: La Fosaĵo,Nivel 9: El Pozo,,Taso 9: Monttu,NIVEAU 9: La Fosse,9. Pálya: A gödör,Livello 9: Il Pozzo,Level 9: 大穴,레벨 9: 구덩이,Level 9: De groeve,Nivå 9: Gropen,Level 9: Dół,Fase 9: O Fosso,Nível 9: O Fosso,Nivelul 9: Groapa,Уровень №9: Яма,Level 9: Јама,Seviye 9: Çukur -Level 10: Refueling Base,HUSTR_10,,,,Level 10: Tankovací základna,Level 10: Tankstation,Level 10: Treibstoffbunker,Επίπεδο 10: Βάση Ανεφοδιασμού,Nivelo 10: Refuelbazo,Nivel 10: Base de Reabastecimiento,,Taso 10: Tankkausasema,NIVEAU 10: Base de Ravitaillement,10. Pálya: Tankolóállomás,Livello 10: Base di Rifornimento,Level 10: 補給基地,레벨 10: 연료 충전소,Level 10: Tankstation,Nivå 10: Påfyllingsbasen,Level 10: Stacja Tankowania,Fase 10: Base de Reabastecimento,Nível 10: Base de Reabastecimento,Nivelul 10: Baza de alimentare,Уровень №10: Заправочная база,Level 10: Бензинска база,Seviye 10: Yakıt İkmal Üssü +Proverbs 5:11",,,Tvé tělo pozřeto,Dit kød er fortæret,Dein Leib verzehrt,Η Σάρκα σου θα Καταναλωθεί,Kiam konsumiĝos via karno,Cuando tu carne se consuma,,Lihasi kulutettu,Votre Chair Consumée,Megemésztetik a te húsod,La tua Carne Consumata,滅びし汝の身,쇠패해진 그대의 육신,Uw Vlees Geconsumeerd,Ditt kjøtt fortæres,Ciało twe zwiotczeje,No Consumir-se da Tua Carne,,Carnea ta Fără de Vlagă,Твоя плоть поглощена,Твоје месо строшено,Ditt kött är uppslukat,Etin Tükendi +Hell On Earth,TXT_D2E1,,,,Peklo na zemi,Helvede på jorden,Hölle auf Erden,Αρμαγεδδών,Infero sur la Tero,Infierno en la Tierra,,Helvetti maan päällä,Enfer sur Terre,Földi pokol,Inferno sulla Terra,第三惑星:地獄,지상에 강림한 지옥,Hel op Aarde,Helvete på jorden,Piekło na Ziemi,Inferno na Terra,,Iadul pe Pământ,Ад на Земле,Пакао на Земљи,Helvetet på jorden,Yeryüzündeki Cehennem +No Rest for the Living,TXT_D2E2,"References ""No rest for the wicked"" in Isaiah 48:22",,,Nemajíť živí pokoje,Ingen hvile for de levende,Keine Ruhe für die Lebenden,Καμία Ανάπαυση για τους Ζωντανούς,Nenia ripozo por la vivantoj,No hay descanso para los vivos,,Ei lepoa eläville,Pas de repos pour les vivants,Nincs nyugodalom az élőnek,Nessun Riposo per i Vivi,休息なき生計,산 자에게 휴식은 없다,Geen Rust voor de Levenden,Ingen hvile for de levende,Nie ma pokoju dla żywych,Não Há Descanso Para os Vivos,,Cei vii Fără de Odihnă,Не будет покоя живым,Нема одмора живима,Ingen vila för de levande,Yaşayanlara Huzur Yok +The Plutonia Experiment,TXT_PLUT_EP,,,,Experiment Plutonia,Plutonia-eksperimentet,Das Plutonia Experiment,Το Πείραμα Πλουτώνια,La eksperimento de Plutonia,El experimento Plutonia,,Plutoniakokemus,L'expérience Plutonia,A Plutonia-kísérlet,L'Esperimento di Plutonia,プルトニア記,플루토니아 익스페리먼트,Het Plutonia Experiment,Plutonia-eksperimentet,Eksperyment Plutonia,O Experimento Plutonia,A Experiência Plutonia,Experimentul Plutonia,Эксперимент «Плутония»,Експеримент Плутонија,Plutonia-experimentet,Plutonia Deneyi +TNT: Evilution,TXT_TNT_EP,,,,TNT: Zlovoluce,,,ΤΝΤ: Κακοξέλιξη,TNT: Mavalucio,TNT: Diabolución,,TNT: Paholuutio,,,TNT: Malvoluzione,TNT:邪神化,TNT: 이블루션,Tnt: Evilutie,,TNT: Ewolucja zła,TNT: Malvolução,,TNT: Diavoluția,TNT: Дьяволюция,TNT: Ђаволуција,, +Chex Quest,TXT_CHEX_EP,,,,Mise Chex,,,Η Περιπέτεια του Chex,Aventuro de Chex,,,Chex-seikkailu,,,,チェックス クエスト,첵스 퀘스트,,,Misja Chex,,,,,Чекс Квест,, +,,Level names,,,,,,,,,,,,,,,,,,,,,,,,, +,,Doom 1,,,,,,,,,,,,,,,,,,,,,,,,, +E1M1: Hangar,HUSTR_E1M1,,,,E1M1: Hangár,,,E1Χ1: Υπόστεγο,E1M1: Hangaro,,,E1M1: Lentoalushalli,,E1M1: Hangár,,E1M1: 格納庫,E1M1: 격납고,,,,,,,E1M1: Ангар,E1M1: Хангар,, +E1M2: Nuclear Plant,HUSTR_E1M2,,,,E1M2: Jaderná elektrárna,E1M2: Atomkraftværk,E1M2: Kernkraftwerk,E1Χ2: Πυρηνικό Εργοστάσιο,E1M2: Nuklea centralo,E1M2: Central nuclear,,E1M2: Ydinvoimala,E1M2: Centrale Nucléaire,E1M2: Atomerőmű,E1M2: Centrale Nucleare,E1M2: 原子力発電所,E1M2: 원자력 발전소,E1M2: Kerncentrale,E1M2: Kjernekraftverk,E1M2: Elektrownia Jądrowa,E1M2: Usina Nuclear,E1M2: Central Nuclear,E1M2: Uzina Nucleară,E1M2: Атомная электростанция,E1M2: Нуклеарна електрана,E1M2: Kärnkraftverk,E1M2: Nükleer Santral +E1M3: Toxin Refinery,HUSTR_E1M3,,,,E1M3: Chemická rafinerie,E1M3: Giftraffinaderi,E1M3: Giftraffinerie,E1Χ3: Διυλιστήριο Τοξινών,E1M3: Toksin-rafinejo,E1M3: Refinería de toxinas,,E1M3: Myrkkyjalostamo,E1M3: Raffinerie de Toxines,E1M3: Méregfinomító,E1M3: Raffineria delle Tossine,E1M3: 毒素精錬所 ,E1M3: 폐기물 정제소,E1M3: Giftstofraffinaderij,E1M3: Giftraffineri,E1M3: Rafineria Toksyn,E1M3: Refinaria de Toxinas,,E1M3: Rafinăria de Toxine,E1M3: Очистной завод,E1M3: Рафинерија за токсине,E1M3: Toxinraffinaderi,E1M3: Toksin Rafinerisi +E1M4: Command Control,HUSTR_E1M4,,,,E1M4: Řídící velín,E1M4: Kommandokontrol,E1M4: Betriebssteuerung,E1Χ4: Κέντρο Ελέγχου,E1M4: Komando kaj kontrolo,E1M4: Mando y control,,E1M4: Komentohallinta,E1M4: Centre de Contrôle,E1M4: Parancsnoki vezérlő,E1M4: Centrale di Comando,E1M4: 指令管制塔,E1M4: 지휘 통제소,E1M4: Controlecentrum,E1M4: Kommandokontroll,E1M4: Kontrola Dowodzenia,E1M4: Controle de Comando,E1M4: Controlo de Comando,E1M4: Comandă și Control,E1M4: Пункт управления,E1M4: Заповедни центар,E1M4: Kommandokontroll,E1M4: Komuta Kontrol +E1M5: Phobos Lab,HUSTR_E1M5,,,,E1M5: Phobosská laboratoř,E1M5: Phobos-laboratorium,E1M5: Phobos-Labor,E1Χ5: Εργαστήριο Φόβου,E1M5: Laboratorio sur Fobo,E1M5: Laboratorio de Fobos,,E1M5: Phoboksen laboratorio,E1M5: Laboratoires Phobos,E1M5: Phoboszi laboratórium,E1M5: Laboratorio di Phobos,E1M5: フォボス研究所,E1M5: 포보스 연구소,E1M5: Phobos Laboratorium,E1M5: Phobos-laboratorium,E1M5: Laboratoria Fobosa,E1M5: Laboratório de Fobos,,E1M5: Laboratorul Phobos,E1M5: Лаборатория Фобоса,E1M5: Лабораторија на Фобосу,E1M5: Phobos-laboratorium,E1M5: Phobos Laboratuvarı +E1M6: Central Processing,HUSTR_E1M6,,,,E1M6: Centrální zpracování,E1M6: Central behandling,E1M6: Zentralverarbeitung,E1Χ6: Κεντρική Επεξεργασία,E1M6: Procesorad-centralo,E1M6: Central de procesamiento,,E1M6: Käsittelykeskus,E1M6: Centre de Traitement,E1M6: Központi feldolgozó,E1M6: Zona Elaboratori,E1M6: 中央処理施設,E1M6: 중앙 처리 본부,E1M6: Centrale Verwerking,E1M6: Sentral prosessering,E1M6: Centralne Przetwarzanie,E1M6: Processamento Central,,E1M6: Prelucrare Centrală,E1M6: Центральный пункт обработки,E1M6: Централна обрада,E1M6: Central bearbetning,E1M6: Merkezi İşlem +E1M7: Computer Station,HUSTR_E1M7,,,,E1M7: Počítačová stanice,E1M7: Computerstation,E1M7: Computerstation,E1Χ7: Σταθμός Υπολογιστών,E1M7: Komputila stacio,E1M7: Estación de cómputo,,E1M7: Tietokoneasema,E1M7: Station Informatique,E1M7: Számítógépes központ,E1M7: Stazione dei Computer,E1M7: コンピューターステーション,E1M7: 컴퓨터 기지,E1M7: Computerstation,E1M7: Datastasjon,E1M7: Stacja Komputerowa,E1M7: Estação de Computadores,,E1M7: Stația de Calculatoare,E1M7: Вычислительный центр,E1M7: Компјутерска станица,E1M7: Datorstation,E1M7: Bilgisayar İstasyonu +E1M8: Phobos Anomaly,HUSTR_E1M8,,,,E1M8: Phobosská anomálie,E1M8: Phobos-anomali,E1M8: Phobos-Anomalie,E1Χ8: Ανωμαλία στον Φόβο,E1M8: Nenormalaĵo sur Fobo,E1M8: Anomalía de Fobos,,E1M8: Phoboksen poikkeama,E1M8: Anomalie de Phobos,E1M8: Phoboszi anomália,E1M8: L'anomalia di Phobos,E1M8: フォボス アノマリー,E1M8: 포보스 이상거점,E1M8: Phobos Anomalie,E1M8: Phobos-anomali,E1M8: Anomalia Fobosa,E1M8: Anomalia de Fobos,,E1M8: Anomalia Phobos,E1M8: Аномалия Фобоса,E1M8: Аномалија на Фобосу,E1M8: Phobos anomali,E1M8: Phobos Anomalisi +E1M9: Military Base,HUSTR_E1M9,,,,E1M9: Vojenská základna,E1M9: Militærbase,E1M9: Militärbasis,E1Χ9: Στρατιωτική Βάση,E1M9: Militbazo,E1M9: Base militar,,E1M9: Sotilastukikohta,E1M9: Base Militaire ,E1M9: Katonai bázis,E1M9: Base militare,E1M9: 軍事基地,E1M9: 군사 기지,E1M9: Militaire Basis,E1M9: Militærbase,E1M9: Baza Wojskowa,E1M9: Base Militar,,E1M9: Baza Militară,E1M9: Военная база,E1M9: Војна база,E1M9: Militärbas,E1M9: Askeri Üs +E1M10: Sewers,HUSTR_E1M10,,,,E1M10: Kanály,E1M10: Kloakkerne,E1M10: Kanalisation,,E1M10: Kloako,E1M10: Alcantarillas,,E1M10: Viemärit,E1M10: Egouts,E1M10: Kanálisok,E1M10: Le Fogne,E1M10: 下水道,E1M10: 하수구,E1M10: De Rioleringen,E1M10: Kloakk,E1M10: Ścieki,E1M10: Os Esgotos,,E1M10: Canalizarea,E1M10: Канализация,E1M10: Канализација,E1M10: Avloppsledningar,E1M10: Kanalizasyonlar +E2M1: Deimos Anomaly,HUSTR_E2M1,,,,E2M1: Deimosská anomálie,E2M1: Deimos Anomali,E2M1: Deimos-Anomalie,E2Χ1: Ανωμαλία στον Δείμο,E2M1: Nenormalaĵo sur Dejmo,E2M1: Anomalía de Deimos,,E2M1: Deimoksen poikkeama,E2M1: Anomalie de Déimos,E2M1: Deimoszi anomália,E2M1: L'anomalia di Deimos,E2M1: 異常なるダイモス,E2M1: 데이모스 이상거점,E2M1: Deimos Anomalie,E2M1: Deimos-anomali,E2M1: Anomalia Deimosa,E2M1: Anomalia de Deimos,,E2M1: Anomalia Deimos,E2M1: Аномалия Деймоса,E2M1: Аномалија на Дејмосу,E2M1: Deimos-anomali,E2M1: Deimos Anomalisi +E2M2: Containment Area,HUSTR_E2M2,,,,E2M2: Skladiště,E2M2: Indespærringsområde,E2M2: Lagerhalle,E2Χ2: Ζώνη Περιορισμού,E2M2: Magazeno,E2M2: Área de almacenamiento,,E2M2: Säilöntäalue,E2M2: Zone de Stockage,E2M2: Raktár,E2M2: Area di contenimento,E2M2: 収容エリア,E2M2: 화물 보관구역,E2M2: Inperkingsgebied,E2M2: Innesperringsområde,E2M2: Obszar Zastrzeżony,E2M2: Area de Contenção,E2M2: Área de Confinamento,E2M2: Zona de Izolare,E2M2: Зона сдерживания,E2M2: Складишта,E2M2: Lagringsområde,E2M2: Çevreleme Alanı +E2M3: Refinery,HUSTR_E2M3,,,,E2M3: Rafinerie,E2M3: Raffinaderi,E2M3: Raffinerie,E2Χ3: Διυλιστήριο,E2M3: Rafinejo,E2M3: Refinería,,E2M3: Jalostamo,E2M3: Raffinerie,E2M3: Finomító,E2M3: Raffineria,E2M3: 精製所,E2M3: 정제소,E2M3: Raffinaderij,E2M3: Raffineri,E2M3: Rafineria,E2M3: Refinaria,,E2M3: Rafinărie,E2M3: Перерабатывающий завод,E2M3: Рафинерија,E2M3: Raffinaderi,E2M3: Rafineri +E2M4: Deimos Lab,HUSTR_E2M4,,,,E2M4: Deimosská laboratoř,E2M4: Deimos-laboratorium,E2M4: Deimos Labor,E2Χ4: Εργαστήριο Δείμου,E2M4: Laboratorio sur Dejmo,E2M4: Laboratorio de Deimos,,E2M4: Deimoksen laboratorio,E2M4: Laboratoires Déimos,E2M4: Deimoszi laboratórium,E2M4: Laboratorio di Deimos,E2M4: ダイモス研究所,E2M4: 데이모스 연구소,E2M4: Deimos Laboratorium,E2M4: Deimos-laboratoriet,E2M4: Laboratoria Deimosa,E2M4: Laboratório de Deimos,,E2M4: Laboratorul Deimos,E2M4: Лаборатория Деймоса,E2M4: Лабораторија на Дејмосу,E2M4: Deimos Lab,E2M4: Deimos Laboratuvarı +E2M5: Command Center,HUSTR_E2M5,,,,E2M5: Řídící středisko,E2M5: Kommandocentral,E2M5: Kommandozentrum,E2Χ5: Κέντρο Διοίκησης,E2M5: Komandcentro,E2M5: Centro de mando,,E2M5: Komentokeskus,E2M5: Centre de Commandement,E2M5: Központi parancsnokság,E2M5: Centro di Comando,E2M5: 指令本部,E2M5: 사령부,E2M5: Commandocentrum,E2M5: Kommandosentralen,E2M5: Centrum Dowodzenia,E2M5: Centro de Comando,,E2M5: Centru de Comandă,E2M5: Командный центр,E2M5: Командни центар,E2M5: Kommandocentrum,E2M5: Komuta Merkezi +E2M6: Halls of the Damned,HUSTR_E2M6,,,,E2M6: Chodby zatracených,E2M6: De Forbandedes haller,E2M6: Säle der Verdammten,E2X6: Διάδρομοι των Κολασμένων,E2M6: Koridoroj de la damnitoj,E2M6: Salones de los malditos,,E2M6: Kirottujen salit,E2M6: Halls des Damnés,E2M6: Az átkozottak termei,E2M6: Sale dei Dannati,E2M6: ダムドの会堂,E2M6: 저주받은 회랑,E2M6: Zalen der Verdoemden,E2M6: De fordømtes haller,E2M6: Korytarze Przeklętych,E2M6: Salões dos Condenados,,E2M6: Camerele Blestemaților,E2M6: Залы проклятых,E2M6: Дворана проклетих,E2M6: De fördömdas salar,E2M6: Lanetliler Salonu +E2M7: Spawning Vats,HUSTR_E2M7,,,,E2M7: Plodné kádě,E2M7: Spirebassiner,E2M7: Materialisationskammern,E2X7: Δεξαμενές Γέννησης,E2M7: Nasko-kuvegoj,E2M7: Silos de materialización,,E2M7: Sikiämissammiot,E2M7: Cuves de Reproduction,E2M7: Szaporító tartályok,E2M7: Vasche di Riproduzione,E2M7: 産卵桶,E2M7: 산란독,E2M7: Materialisatietanks,E2M7: Gytekarene,E2M7: Kadzie Reprodukcyjne,E2M7: Tanques de Criação,,E2M7: Cuve de Reproducere,E2M7: Нерестилище,E2M7: Размножавалиште,E2M7: Växthus för spädning,E2M7: Yumurtlama Fıçıları +E2M8: Tower of Babel,HUSTR_E2M8,,,,E2M8: Babylonská věž,E2M8: Babelstårn,E2M8: Turmbau zu Babel,E2Χ8: Πύργος της Βαβέλ,E2M8: Turo de Babelo,E2M8: Torre de Babel,,E2M8: Baabelin torni,E2M8: Tour de Babel,E2M8: Bábel tornya,E2M8: Torre di Babele,E2M8: バベルの塔,E2M8: 바벨탑,E2M8: Toren van Babel,E2M8: Babels tårn,E2M8: Wieża Babel,E2M8: Torre de Babel,,E2M8: Turnul Babel,E2M8: Вавилонская башня,E2M8: Вавилонска кула,E2M8: Babels torn,E2M8: Babil Kulesi +E2M9: Fortress of Mystery,HUSTR_E2M9,,,,E2M9: Pevnost záhad,E2M9: Mysteriets fæstning,E2M9: Geheimnisvolle Festung,E2Χ9: Φρούριο του Μυστηρίου,E2M9: Fortreso de mistero,E2M9: Fortaleza del misterio,,E2M9: Salaperäisyyden linnake,E2M9: Mystérieuse Forteresse,E2M9: A rejtélyek erődje,E2M9: Fortezza del Mistero,E2M9: 神秘の要塞,E2M9: 신비의 요새,E2M9: Vesting der Mysterie,E2M9: Mysteriets festning,E2M9: Forteca Tajemnic,E2M9: Fortaleza do Mistério,,E2M9: Fortăreața Misterelor,E2M9: Крепость тайн,E2M9: Тврђава тајни,E2M9: Mysteriets fästning,E2M9: Gizem Kalesi +E3M1: Hell Keep,HUSTR_E3M1,,,,E3M1: Pekelná tvrz,E3M1: Helvedesborg,E3M1: Höllenbollwerk,E3Χ1: Ακροπύργιο της Κολάσεως,E3M1: Infera ĉefturo,E3M1: Torreón del Infierno,,E3M1: Hornantorni,E3M1: Donjon Infernal,E3M1: A pokol bástyái,E3M1: Bastioni dell'Inferno,E3M1: 牢獄,E3M1: 지옥 성채,E3M1: Helleslot,E3M1: Helvetes borg,E3M1: Twierdza Piekieł,E3M1: Torre do Inferno,,E3M1: Fortul Iadului,E3M1: Крепость Ада,E3M1: Тврђава пакла,E3M1: Helvetesborg,E3M1: Cehennem Kalesi +E3M2: Slough of Despair,HUSTR_E3M2,,,,E3M2: Bažina zoufalství,E3M2: Fortvivlelsens sump,E3M2: Sumpf der Verzweiflung,E3Χ2: Έλος της Απελπισίας,E3M2: Ŝlimejo de malespero,E3M2: Ciénaga de la desesperación,,E3M2: Epätoivon räme,E3M2: Bourbier du Désespoir,E3M2: A kétségbeesés mocsara,E3M2: Palude della Disperazione,E3M2: 絶望の大地,E3M2: 절망의 심연,E3M2: Moeras der Wanhoop,E3M2: Fortvilelsens sump,E3M2: Bagno Rozpaczy,E3M2: Lamaçal do Desespero,,E3M2: Mlaștinile Disperării,E3M2: Трясина отчаяния,E3M2: Блато очајања,E3M2: Förtvivlans svackor,E3M2: Umutsuzluk Slough'u +E3M3: Pandemonium,HUSTR_E3M3,,,,,E3M3: Pandemonium,E3M3: Pandämonium,E3Χ3: Πανδαιμόνιο,E3M3: Pandemonio,E3M3: Pandemonio,,,E3M3: Pandémonium,E3M3: Zűrzavar,E3M3: Pandemonio,E3M3: 伏魔殿,E3M3: 복마전,,,E3M3: Piekło,E3M3: Pandemônio,,E3M3: Pandemoniu,E3M3: Пандемоний,E3M3: Пандемонијум,E3M3: Pandemonium,E3M3: Pandemonium +E3M4: House of Pain,HUSTR_E3M4,,,,E3M4: Dům bolesti,E3M4: Hus af smerte,E3M4: Haus des Schmerzes,E3Χ4: Σπίτι του Πόνου,E3M4: Domo de doloro,E3M4: Casa del dolor,,E3M4: Tuskanmaja,E3M4: Maison de la Douleur,E3M4: A kínok háza,E3M4: Casa del Dolore,E3M4: 苦痛の館,E3M4: 고통의 집,E3M4: Huis van Pijn,E3M4: Smertens hus,E3M4: Dom Bólu,E3M4: Casa da Dor,,E3M4: Casa Durerii,E3M4: Обитель боли,E3M4: Кућа патње,E3M4: Smärtans hus,E3M4: Acı Evi +E3M5: Unholy Cathedral,HUSTR_E3M5,,,,E3M5: Bezbožná katedrála,E3M5: Uhellig katedral,E3M5: Unheilige Kathedrale,E3X5: Ανίερος Καθεδρικός,E3M5: Malsankta katedralo,E3M5: Catedral profana,,E3M5: Epäpyhä katedraali,E3M5: Cathédrale Profane,E3M5: Az istentelen katedrális ,E3M5: Cattedrale Blasfema,E3M5: 邪教の大聖堂,E3M5: 불경한 성당,E3M5: Onheilige Kathedraal,E3M5: Den vanhellige katedralen,E3M5: Bluźniercza Katedra,E3M5: Catedral Profana,,E3M5: Catedrala Necurată,E3M5: Нечестивый собор,E3M5: Несвета катедрала,E3M5: Den oheliga katedralen,E3M5: Kutsal Olmayan Katedral +E3M6: Mt. Erebus,HUSTR_E3M6,Volcano in Antarctica,,,E3M6: Hora Erebus,,,E3X6: Όρος Έρεβος,E3M6: Monto de Erebo,E3M6: Monte Erebus,,E3M6: Erebusvuori,E3M6: Mont Erèbe,E3M6: Erebus-hegy,E3M6: Monte Erebus,E3M6: エレボス山,E3M6: 에레버스 산,,E3M6: Erebus-fjellet,E3M6: Góra Erebus,E3M6: Monte Érebo,,E3M6: M. Erebus,E3M6: Гора Эребус,E3M6: Планина Еребус,,E3M6: Erebus Dağı +E3M7: Limbo,HUSTR_E3M7,,,,E3M7: Předpeklí,,,E3Χ7: Είσοδος της Κολάσεως,,,,E3M7: Limbus,E3M7: Limbes,E3M7: Limbus,,E3M7: 忘却の地,E3M7: 고성소,,,E3M7: Otchłań,,,E3M7: Limb,E3M7: Чистилище,E3M7: Лимбо,,E3M7: Araf +E3M8: Dis,HUSTR_E3M8,"Based on the City of Dis, located on the sixth circle of Hell, according to Dante Alighieri's The Divine Comedy",,,,,,E3Χ8: Δίτα,E3M8: Danteca,E3M8: Ciudad de Dite,,,E3M8: Dité,,E3M8: Dite,E3M8: 死,E3M8: 디스,,,,E3M8: Dite,,E3M8: Dite,E3M8: Дит,E3M8: Дис,, +E3M9: Warrens,HUSTR_E3M9,,,,E3M9: Brlohy,E3M9: Rotteboet,E3M9: Rattennest,E3X9: Λαγούμια,E3M9: Nestego,E3M9: Madrigueras,,E3M9: Sokkelot,E3M9: Clapiers,E3M9: Nyúlkert,E3M9: Le Garenne,E3M9: 兎小屋,E3M9: 토끼굴,E3M9: Doolhof,E3M9: Rottebo,E3M9: Królikarnia,E3M9: Tocas,,E3M9: Vizuini,E3M9: Изнорье,E3M9: Одгајалиште,E3M9: Vildmark,E3M9: Sıçan yuvası +E4M1: Hell Beneath,HUSTR_E4M1,Proverbs 15:24,,,E4M1: Peklo v hlubinách,E4M1: Helvede nedenunder,E4M1: Die Hölle unterwärts,E4Χ1: Κάτω Κόσμος,E4M1: Ŝeolo malsupre,E4M1: Seol abajo,,E4M1: Tuonela alhaalla,E4M1: Le Séjour des Morts,E4M1: A holtak hazája odalent,E4M1: In Basso,E4M1: 地獄の下へ,E4M1: 지옥의 밑에서,E4M1: Hel beneden,E4M1: Helvete under,E4M1: Piekło Najgłębsze,E4M1: Inferno Abaixo,E4M1: Inferno Profundo,E4M1: Iadul de Jos,E4M1: Преисподняя под ногами,E4M1: Пакао одоздо,E4M1: Helvetet under,E4M1: Cehennem Altında +E4M2: Perfect Hatred,HUSTR_E4M2,Psalm 139:22,,,E4M2: Naprostá nenávist,E4M2: Perfekt had,E4M2: Perfekter Hass,E4Χ2: Τέλειο Μίσος,E4M2: Ekstrema malamo,E4M2: Aborrecer por completo,,E4M2: Kaikella vihalla,E4M2: Une Parfaite Haine,E4M2: Teljes gyűlölettel,E4M2: Odio Perfetto,E4M2: 完全なる憎悪,E4M2: 완벽한 증오,E4M2: Perfecte Haat,E4M2: Perfekt hat,E4M2: Pełnia Nienawiści,E4M2: Ódio Perfeito,,E4M2: Ură Desăvârșită,E4M2: Полная ненависть,E4M2: Пуном мрзошћу,E4M2: Perfekt Hass,E4M2: Kusursuz Nefret +E4M3: Sever The Wicked,HUSTR_E4M3,Matthew 13:49,,,E4M3: Oddělit zkažené,E4M3: Afskære de onde,E4M3: Scheidet die Bösen,E4Χ3: Ξερίζωσε τους Πονηρούς,E4M3: Apartigi la malbonulojn,E4M3: Apartarán a los malos,,E4M3: Erottavat pahat,E4M3: Séparer les Vicieux,E4M3: Felnégyelni a bűnösöket,E4M3: Separeranno I Cattivi,E4M3: 邪悪を絶つ,E4M3: 악령처단,E4M3: Scheid de goddelozen af,E4M3: Skille ut de onde,E4M3: Oddzielą Niegodziwych,E4M3: Separarão os Maus,E4M3: Separarão o Mal,E4M3: Să Desparți pe Cei Răi,E4M3: Отделить злых,E4M3: Одлучи зле,E4M3: Separera de onda,E4M3: Kötüleri Kesin +E4M4: Unruly Evil,HUSTR_E4M4,James 3:8,,,E4M4: Nezkrotitelné zlo,E4M4: Ustyrlig ondskab,E4M4: Schandbare Worte,E4X4: Ασυγκράτητο Κακό,E4M4: Malkvieta malbono,E4M4: Mal irrefrenable,,E4M4: Levotointa pahuutta,E4M4: Un Mal Irrépréssible,E4M4: Féktelen gonosz,E4M4: Male Senza Posa,E4M4: 手に負えない邪悪,E4M4: 광폭한 악마,E4M4: Het weerbarstige kwaad,E4M4: Uregjerlig ondskap,E4M4: Niepohamowane Zło,E4M4: Mal Irrefreável,E4M4: Mal que não Refreia,E4M4: Un Rău fără Astâmpăr,E4M4: Неудержимое зло,Е4М4: Немирно зло,E4M4: Den oregerliga ondskan,E4M4: Asi Kötülük +E4M5: They Will Repent,HUSTR_E4M5,Luke 16:30,,,E4M5: Budou činit pokání,E4M5: De vil omvende sig,E4M5: Sie werden bereuen,E4X5: Θα Μετανοήσουν,E4M5: Ili pentos,E4M5: Se arrepentirán,,E4M5: He parannuksen tekisivät,E4M5: Ils se repentiront,E4M5: Megtérnek majd,E4M5: Si Ravvederanno,E4M5: 奴等に後悔を,E4M5: 그들은 회개할 지어다,E4M5: Ze zullen berouw hebben,E4M5: De vil omvende seg,E4M5: Nawrócą Się,E4M5: Arrepender-se,E4M5: Eles Arrepender-se-iam,E4M5: Se vor Pocăi,E4M5: Они покаются,E4M5: Покајаће се,E4M5: De kommer att ångra sig,E4M5: Tövbe Edecekler +E4M6: Against Thee Wickedly,HUSTR_E4M6,Psalm 139:20,,,E4M6: Při svých pletichách,E4M6: Mod dig ondskabsfuldt,E4M6: Feinde erheben sich,E4X6: Κακόβουλα Εναντίον Σου,E4M6: Pri Vi malice,E4M6: Blasfemias contra ti,,E4M6: Sinusta petollisesti,E4M6: D'une manière criminelle,E4M6: Hitványul ellened,E4M6: Contro di te Malvagiamente,E4M6: 汝への悪逆,E4M6: 그대와 짖궂게 맞서다,E4M6: Tegen de goddeloze,E4M6: Mot deg ondskapsfullt,E4M6: Podstępnie Przeciw Tobie,E4M6: Malvadamente Contra Ti,,E4M6: Te Grăiesc de Rău,E4M6: Против тебя нечестиво,E4M6: Ружно на тебе,E4M6: Mot dig ondskan,E4M6: Sana Karşı Kötüce +E4M7: And Hell Followed,HUSTR_E4M7,Revelation 6:8,,,E4M7: A peklo šlo za ním,E4M7: Og Helvede fulgte efter,E4M7: Und die Hölle folgte,E4X7: Και η Κόλαση Ακολούθησε,E4M7: Kaj Hades sekvis,E4M7: El Hades le seguía,E4M7: El Hades lo seguía,E4M7: Ja Tuonela seurasi,E4M7: Et l'Enfer Suivit,E4M7: És a pokol követé azt,E4M7: E l'inferno seguitava,E4M7: そして地獄は従った,E4M7: 그리고 지옥이 뒤따른다,E4M7: En de hel volgde,E4M7: Og helvete fulgte,E4M7: A Piekło Szło Za Nim,E4M7: E o Inferno Seguia,E4M7: Inferno o Seguia,E4M7: Iadul se Ținea după El,E4M7: И последовал Ад,E4M7: И пакао иђаше,E4M7: Och helvetet följde,E4M7: Ve Cehennem Takip Etti +E4M8: Unto The Cruel,HUSTR_E4M8,Proverbs 5:9,,,E4M8: Ukrutníku odevzdáš,E4M8: Til de grusomme,E4M8: Deine Jahre dem Grausamen,E4X8: Προς Τους Ανελεήμονες,E4M8: Al la kruelulo,E4M8: Tus años al cruel,,E4M8: Armottomalle,E4M8: A un Homme cruel,E4M8: A kegyetlennek,E4M8: Al Crudele,E4M8: 容赦なき者へ,E4M8: 잔혹한 자에게로,E4M8: Naar de wrede,E4M8: Til de grusomme,E4M8: Kto Nie Zna Litości,E4M8: Aos Cruéis,E4M8: Entregue a Cruéis,E4M8: Unuia Fără de Milă,E4M8: К мучителю,E4M8: Немилостивоме,E4M8: Mot de grymma,E4M8: Zalimlere Karşı +E4M9: Fear,HUSTR_E4M9,,,,E4M9: Strach,E4M9: Frygt,E4M9: Angst,E4Χ9: Τρόμος,E4M9: Timo,E4M9: Miedo,,E4M9: Pelko,E4M9: Terreur,E4M9: Félelem,E4M9: Paura,E4M9: 恐怖,E4M9: 공포,E4M9: Angst,E4M9: Frykt,E4M9: Strach,E4M9: Medo,,E4M9: Frica,E4M9: Страх,E4M9: Страх,E4M9: Rädsla,E4M9: Korku +,,Doom 2,,,,,,,,,,,,,,,,,,,,,,,,, +Level 1: Entryway,HUSTR_1,"Note that the ""LEVEL"" part of the string will be stripped so it shouldn't be translated",,,Level 1: Vchod,Level 1: Indgang,Level 1: Eingangshalle,Επίπεδο 1: Είσοδος,Nivelo 1: Enirejo,Nivel 1: Entrada,,Taso 1: Eteiskäytävä,NIVEAU 1: Hall D'Entrée,1. Pálya: Bejárat,Livello 1: Ingresso,Level 1: 入口,레벨 1: 초입,Level 1: Ingang,Nivå 1: Inngangen,Level 1: Wejście,Fase 1: Entrada,Nível 1: Entrada,Nivelul 1: Intrarea,Уровень №1: Вход,Level 1: Улаз,Nivå 1: Ingång,Seviye 1: Giriş Yolu +Level 2: Underhalls,HUSTR_2,,,,Level 2: Podzemí,Level 2: Underbukser,Level 2: Kellergewölbe,,Nivelo 2: Subteraj vojoj,Nivel 2: Salones subterráneos,,Taso 2: Maanalaiset käytävät,NIVEAU 2: Souterrains,2. Pálya: Alagutak,Livello 2: Sotterranei,Level 2: 地下堂,레벨 2: 지하수로,Level 2: Onderhallen,Nivå 2: Underhaller,Level 2: Podziemia,Fase 2: Subterrâneo,Nível 2: Subterrâneo,Nivelul 2: Pasaje subterane,Уровень №2: Подземные ходы,Level 2: Подземни ходници,Nivå 2: Underhallar,Seviye 2: Tulumlar +Level 3: The Gantlet,HUSTR_3,“a form of punishment in which a person is forced to run between two lines of men facing each other and armed with clubs or whips to beat the victim”,,,Level 3: Trest,Level 3: Spidsrod,Level 3: Spießrutenlauf,,Nivelo 3: La vergokuro,Nivel 3: Carrera de baquetas,,Taso 3: Kujanjuoksu,NIVEAU 3: Parcours du Combatant,3. Pálya: Vesszőfutás,Livello 3: Le Forche,Level 3: ガントレット,레벨 3: 건틀릿,Level 3: De gantlet,Nivå 3: Hansken,Level 3: Praszczęta,Fase 3: A Punição,Nível 3: A Punição,Nivelul 3: Stroiul,Уровень №3: Сквозь строй,Level 3: Казна,Nivå 3: Utmaningen,Seviye 3: Zorluk +Level 4: The Focus,HUSTR_4,,,,Level 4: Ohnisko,Level 4: Fokus,Level 4: Der Fokus,,Nivelo 4: La fokuso,Nivel 4: El foco,,Taso 4: Polttopiste,NIVEAU 4: Le Focus,4. Pálya: A középpont,Livello 4: L'Epicentro,Level 4: フォーカス,레벨 4: 초점,Level 4: De focus,Nivå 4: Fokus,Level 4: Skupisko,Fase 4: O Foco,Nível 4: O Foco,Nivelul 4: Focarul,Уровень №4: Средоточие,Level 4: Средиште,Nivå 4: Fokus,Seviye 4: Odaklanma +Level 5: The Waste Tunnels,HUSTR_5,,,,Level 5: Odpadní tunely,Level 5: Affaldstunnellerne,Level 5: Die Abfall-Tunnel,Επίπεδο 5: Οι Σήραγγες Αποβλήτων,Nivelo 5: La rubtuneloj,Nivel 5: Los túneles de desechos,,Taso 5: Jätetunnelit,NIVEAU 5: Les Egouts,5. Pálya: Szennyvízalagutak,Livello 5: I Tunnel dei Rifiuti,Level 5: 廃棄トンネル,레벨 5: 하수도,Level 5: De afvaltunnels,Nivå 5: Avfallstunnelene,Level 5: Kanały,Fase 5: Os Túneis de Dejetos,Nível 5: Os Túneis de Dejetos,Nivelul 5: Tuneluri de deșeuri,Уровень №5: Сточные туннели,Level 5: Отпадни тунели,Nivå 5: Avfallstunnlarna,Seviye 5: Atık Tünelleri +Level 6: The Crusher,HUSTR_6,,,,Level 6: Drtička,Level 6: Knuseren,Level 6: Die Presse,Επίπεδο 6: Ο Συνθλιπτής,Nivelo 6: La dispistilo,Nivel 6: La trituradora,,Taso 6: Murskaaja,NIVEAU 6: Le Broyeur,6. Pálya: A zúzda,Livello 6: La Pressa,Level 6: クラッシャー,레벨 6: 분쇄기,Level 6: De maalmachine,Nivå 6: Knuseren,Level 6: Zgniatarka,Fase 6: O Esmagador,Nível 6: O Esmagador,Nivelul 6: Zdrobitorul,Уровень №6: Давилка,Level 6: Разбијач,Nivå 6: krossen,Seviye 6: Kırıcı +Level 7: Dead Simple,HUSTR_7,,,,Level 7: Smrtelně prosté,Level 7: Død simpel,Level 7: Tödlich einfach,Επίπεδο 7: Πανεύκολο,Nivelo 7: Morte simpla,Nivel 7: Simplemente muerto,,Taso 7: Kuolettavan yksinkertainen,NIVEAU 7: Mortellement Simple,7. Pálya: Halálegyszerű,Livello 7: Morte Pura,Level 7: 死ぬほど単純,레벨 7: 죽여주는 단순함,Level 7: Dodelijk eenvoudig,Nivå 7: Helt enkelt,Level 7: Śmiertelnie Proste,Fase 7: Mortalmente Simples,Nível 7: Simplesmente Mortal,Nivelul 7: Mortal de simplu,Уровень №7: Смертельно просто,Level 7: Смртно једноставно,Nivå 7: Död enkel,Seviye 7: Ölü Basit +Level 8: Tricks and Traps,HUSTR_8,,,,Level 8: Lesti a léčky,Level 8: Tricks og fælder,Level 8: Tricks und Fallen,Επίπεδο 8: Κόλπα και Παγίδες,Nivelo 8: Trompoj kaj embuskoj,Nivel 8: Trucos y trampas,,Taso 8: Metkuja ja pauloja,NIVEAU 8: Ruses et Pièges,8. Pálya: Cselek és csapdák,Livello 8: Trucchi e Trappole,Level 8: 悪戯と罠,레벨 8: 속임수와 함정들,Level 8: Trucs en vallen,Nivå 8: Triks og feller,Level 8: Sztuczki i Pułapki,Fase 8: Truques e Armadilhas,Nível 8: Truques e Armadilhas,Nivelul 9: Surprize și capcane,Уровень №8: Уловки и ловушки,Level 8: Замке и смицалице,Nivå 8: Tricks och fällor,Seviye 8: Hileler ve Tuzaklar +Level 9: The Pit,HUSTR_9,,,,Level 9: Jáma,Level 9: Gruben,Level 9: Die Grube,Επίπεδο 9: Λάκκος,Nivelo 9: La fosaĵo,Nivel 9: El pozo,,Taso 9: Monttu,NIVEAU 9: La Fosse,9. Pálya: A gödör,Livello 9: Il Pozzo,Level 9: 大穴,레벨 9: 구덩이,Level 9: De groeve,Nivå 9: Gropen,Level 9: Jama,Fase 9: O Fosso,Nível 9: O Fosso,Nivelul 9: Groapa,Уровень №9: Яма,Level 9: Јама,Nivå 9: Grottan,Seviye 9: Çukur +Level 10: Refueling Base,HUSTR_10,,,,Level 10: Tankovací základna,Level 10: Tankstation,Level 10: Treibstoffbunker,Επίπεδο 10: Βάση Ανεφοδιασμού,Nivelo 10: Refuelbazo,Nivel 10: Base de reabastecimiento,,Taso 10: Tankkausasema,NIVEAU 10: Base de Ravitaillement,10. Pálya: Tankolóállomás,Livello 10: Base di Rifornimento,Level 10: 補給基地,레벨 10: 연료 충전소,Level 10: Tankstation,Nivå 10: Påfyllingsbasen,Level 10: Stacja Tankowania,Fase 10: Base de Reabastecimento,Nível 10: Base de Reabastecimento,Nivelul 10: Baza de alimentare,Уровень №10: Заправочная база,Level 10: Бензинска база,Nivå 10: Tankningsbasen,Seviye 10: Yakıt İkmal Üssü Level 11: 'O' of Destruction!,HUSTR_11,"Alternative title: -Circle of Death ",,,Level 11: Kruh smrti,Level 11: Ødelæggelsens cirkel!,Level 11: 'O' der Zerstörung!,Επίπεδο 11: Ο Κύκλος της Καταστροφής,Nivelo 11: Morta cirklo,Nivel 11: Círculo de la muerte,,Taso 11: Hävityksen 'O',NIVEAU 11: Le Cercle de la Mort!,11. Pálya: A pusztulás köre,Livello 11: Il Cerchio della Morte,Level 11: 破滅の'O'!,레벨 11: 파괴의 고리,Level 11: 'O' van vernietiging!,Nivå 11: Ødeleggelsens 'O'!,Level 11: Krąg Śmierci,Fase 11: Círculo da Morte,Nível 11: Círculo da Morte,Nivelul 11: Cercul distrugerii,Уровень №11: Круг разрушения!,Level 11: Круг уништења,Seviye 11: Yıkımın 'O'su! -Level 12: The Factory,HUSTR_12,,,,Level 12: Továrna,Level 12: Fabrikken,Level 12: Die Fabrik,Επίπεδο 12: To Εργοστάσιο,Nivelo 12: La Fabriko,Nivel 12: La Fábrica,,Taso 12: Tehdas,NIVEAU 12: L'Usine,12. Pálya: A gyár,Livello 12: La Fabbrica,Level 12: 工場,레벨 12: 공장,Level 12: De fabriek,Nivå 12: Fabrikken,Level 12: Fabryka,Fase 12: A Fábrica,Nível 12: A Fábrica,Nivelul 12: Fabrica,Уровень №12: Фабрика,Level 12: Фабрика,Seviye 12: Fabrika -Level 13: Downtown,HUSTR_13,,,,Level 13: Centrum,Level 13: Centrum,Level 13: Stadtzentrum,Επίπεδο 13: Κέντρο,Nivelo 13: Urbocentro,Nivel 13: Centro de la Ciudad,,Taso 13: Keskikaupunki,NIVEAU 13: Centre-Ville,13. Pálya: Belváros,Livello 13: Periferia,Level 13: 市内,레벨 13: 번화가,Level 13: De binnenstad,Nivå 13: Sentrum,Level 13: Śródmieście,Fase 13: Centro Urbano,Nível 13: Centro Urbano,Nivelul 13: Centru urban,Уровень №13: Центр города,Level 13: Центар града,Seviye 13: Şehir Merkezi -Level 14: The Inmost Dens,HUSTR_14,,,,Level 14: Nejhlubší doupata,Level 14: Den inderste hule,Level 14: Die innersten Bauten,Επίπεδο 14: Οι Ενδότερες Φωλιές,Nivelo 14: La Internaj Kavernoj,Nivel 14: Los Antros más Recónditos,,Taso 14: Sisimmät piilot,NIVEAU 14: Les Antres Profondes,14. Pálya: A legmélyebb rejtekek,Livello 14: Gli Antri Profondi,Level 14: 最深巣窟,레벨 14: 깊숙한 동굴들,Level 14: De binnenste gebouwen,Nivå 14: De innerste huler,Level 14: Najgłębsze Nory,Fase 14: Os Antros Profundos,Nível 14: Os Antros Profundos,Nivelul 14: Cele mai intime bârloguri,Уровень №14: Глубочайшие логовища,Level 14: Најдубље јазбине,Seviye 14: En İçteki İnler -Level 15: Industrial Zone,HUSTR_15,,,,Level 15: Průmyslová zóna,Level 15: Industriområde,Level 15: Industriegebiet,Επίπεδο 15: Βιομηχανική Ζώνη,Nivelo 15: Industria Zono,Nivel 15: Zona Industrial,,Taso 15: Teollisuusalue,NIVEAU 15: Zone Industrielle,15. Pálya: Ipari zóna,Livello 15: Zona Industriale,Level 15: 工業地帯,레벨 15: 공업 지대,Level 15: Industriegebied,Nivå 15: Industriområdet,Level 15: Strefa Przemysłowa,Fase 15: Zona Industrial,Nível 15: Zona Industrial,Nivelul 15: Zona industrială,Уровень №15: Промышленный район,Level 15: Индустријска зона,Seviye 15: Sanayi Bölgesi -Level 16: Suburbs,HUSTR_16,,,,Level 16: Předměstí,Level 16: Forstæderne,Level 16: Vororte,Επίπεδο 16: Προάστια,Nivelo 16: Antaŭurboj,Nivel 16: Suburbios,,Taso 16: Lähiö,NIVEAU 16: Banlieue,16. Pálya: Külváros,Livello 16: Sobborghi,Level 16: 郊外,레벨 16: 교외,Level 16: Buitenwijken,Nivå 16: Forstedene,Level 16: Przedmieścia,Fase 16: Subúrbios,Nível 16: Subúrbios,Nivelul 16: Suburbi,Уровень №16: Пригород,Level 16: Предграђе,Seviye 16: Banliyöler -Level 17: Tenements,HUSTR_17,,,,Level 17: Sídliště,Level 17: Lejligheder,Level 17: Wohnbezirk,Επίπεδο 17: Καταλύματα,Nivelo 17: Loĝejoj,Nivel 17: Viviendas,,Taso 17: Vuokratalot,NIVEAU 17: Immeubles,17. Pálya: Bérházak,Livello 17: Possedimenti,Level 17: 安アパート,레벨 17: 공동주택,Level 17: Huurwoningen,Nivå 17: Leiegårder,Level 17: Kamienice,Fase 17: Habitações,Nível 17: Habitações,Nivelul 17: Proprietăți,Уровень №17: Владения,Level 17: Станови,Seviye 17: Kiralık Evler -Level 18: The Courtyard,HUSTR_18,,,,Level 18: Nádvoří,Level 18: Gårdspladsen,Level 18: Der Innenhof,Επίπεδο 18: Η Αυλή,Nivelo 18: La Korto,Nivel 18: El Patio,,Taso 18: Esipiha,NIVEAU 18: La Cour,18. Pálya: Az udvar,Livello 18: Il Cortile,Level 18: 中庭,레벨 18: 중정,Level 18: De binnenplaats,Nivå 18: Gårdsplassen,Level 18: Dziedziniec,Fase 18: O Átrio,Nível 18: O Átrio,Nivelul 18: Curtea,Уровень №18: Внутренний двор,Level 18: Двориште,Seviye 18: Avlu -Level 19: The Citadel,HUSTR_19,,,,Level 19: Citadela,Level 19: Citadellet,Level 19: Die Zizadelle,Επίπεδο 19: Το Κάστρο,Nivelo 19: La Citadelo,Nivel 19: La Ciudadela,,Taso 19: Linnoitus,NIVEAU 19: La Citadelle,19. Pálya: Fellegvár,Livello 19: La Cittadella,Level 19: 要塞,레벨 19: 성채,Level 19: De citadel,Nivå 19: Citadellet,Level 19: Cytadela,Fase 19: A Cidadela,Nível 19: A Cidadela,Nivelul 19: Cetatea,Уровень №19: Цитадель,Level 19: Цитадела,Seviye 19: Hisar -Level 20: Gotcha!,HUSTR_20,,,,Level 20: Mám tě!,,Level 20: Erwischt!,Επίπεδο 20: Σ'έπιασα!,Nivelo 20: Kaptis Vin!,Nivel 20: ¡Te pillé!,Nivel 20: ¡Te tengo!,Taso 20: Sainpas sinut!,NIVEAU 20: Je t'ai eu!,20. Pálya: Megvagy!,Livello 20: Preso!,Level 20: 捉らえた!,레벨 20: 잡았다!,Level 20: Ik heb je!,Nivå 20: Fikk deg!,Level 20: Mam Cię!,Fase 20: Te Peguei!,Nível 20: Apanhei-te!,Nivelul 20: Te-am prins!,Уровень №20: Попался!,Level 20: Имају те!,Seviye 20: Yakaladım! -Level 21: Nirvana,HUSTR_21,,,,Level 21: Nirvána,,,Επίπεδο 21: Νιρβάνα,Nivelo 21: Nirvano,Nivel 21: Nirvana,,,NIVEAU 21: Nirvana,21. Pálya: Nirvána,Livello 21: Nirvana,Level 21: 涅槃,레벨 21: 열반,,,Level 21: Nirvana,Fase 21: Nirvana,Nível 21: Nirvana,Nivelul 21: Nirvana,Уровень №21: Нирвана,Level 21: Нирвана,Seviye 21: Nirvana -Level 22: The Catacombs,HUSTR_22,,,,Level 22: Katakomby,Level 22: Katakomberne,Level 22: Katakomben,Επίπεδο 22: Οι Κατακόμβες,Nivelo 22: La Katakomboj,Nivel 22: Las Catacumbas,,Taso 22: Katakombit,NIVEAU 22: Les Catacombes,22. Pálya: A katakombák,Livello 22: Le Catacombe,Level 22: 地下悪霊墓所,레벨 22: 지하 묘지,Level 22: De catacomben,Nivå 22: Katakombene,Level 22: Katakumby,Fase 22: As Catacumbas,Nível 22: Os Calabouços,Nivelul 22: Catacombe,Уровень №22: Катакомбы,Level 22: Катакомбе,Seviye 22: Yeraltı Mezarları -Level 23: Barrels O' Fun,HUSTR_23,,,,Level 23: Barely srandy,Level 23: Tønder af sjov,Level 23: Lustige Fässer,,Nivelo 23: Bareloj de Amuzo,Nivel 23: Barriles de Diversión,,Taso 23: Huvitynnyrit,NIVEAU 23: Une Tonne-eau de plaisir,23. Pálya: Mókás hordók,Livello 23: Barili da Sballo,Level 23: 戯れのバレル,레벨 23: 신나는 폭발통들,Level 23: Grappige vaten,Nivå 23: Tønner med moro,Level 23: Beczki Śmiechu,Fase 23: Barris de Diversão,Nível 23: Barris de Diversão,Nivelul 23: Butoaiele veseliei,Уровень №23: Бочки веселья,Level 23: Бачве забаве,Seviye 23: Eğlence Fıçıları -Level 24: The Chasm,HUSTR_24,,,,Level 24: Rokle,Level 24: Kløften,Level 24: Die Kluft,Επίπεδο 24: Το Χάσμα,Nivelo 24: La Fendego,Nivel 24: El Desfiladero,,Taso 24: Rotko,NIVEAU 24: Le Gouffre,24. Pálya: A szakadék,Livello 24: L'Abisso,Level 24: 裂け目,레벨 24: 협곡,Level 24: De afgrond,Nivå 24: Avgrunnen,Level 24: Przepaść,Fase 24: O Abismo,Nível 24: O Abismo,Nivelul 24: Hăul,Уровень №24: Пропасть,Level 24: Провалија,Seviye 24: Uçurum -Level 25: Bloodfalls,HUSTR_25,,,,Level 25: Krvopády,Level 25: Blodfald,Level 25: Blutfälle,Επίπεδο 25: Καταρράκτες Αίματος,Nivelo 25: Sangfaloj,Nivel 25: Cataratas de Sangre,,Taso 25: Veriputoukset,NIVEAU 25: Chutes de Sang,25. Pálya: Véresések,Livello 25: Cascate di Sangue,Level 25: 血の滝,레벨 25: 혈폭포,Level 25: Bloeddruppels,Nivå 25: Blodfall,Level 25: Wodospad Krwi,Fase 25: Cataratas de Sangue,Nível 25: Cascatas de Sangue,Nivelul 25: Cascade de sânge,Уровень №25: Кровопады,Level 25: Крвопади,Seviye 25: Kan Düşüşleri -Level 26: The Abandoned Mines,HUSTR_26,,,,Level 26: Opuštěné doly,Level 26: De forladte miner,Level 26: Die aufgegebene Mine,Επίπεδο 26: Τα Εγκαταλελειμμένα Ορυχεία,Nivelo 26: La Forlasitaj Minoj,Nivel 26: Las Minas Abandonadas,,Taso 26: Hylätyt kaivokset,NIVEAU 26: Les Mines Abandonnées,26. Pálya: Az elhagyatott bányák,Livello 26: Le Miniere Abbandonate,Level 26: 廃鉱山,레벨 26: 버려진 광산,Level 26: De verlaten mijnen,Nivå 26: De forlatte gruvene,Level 26: Opuszczone Kopalnie,Fase 26: As Minas Abandonadas,Nível 26: As Minas Abandonadas,Nivelul 26: Minele părăsite,Уровень №26: Заброшенные шахты,Level 26: Напуштени рудници,Seviye 26: Terk Edilmiş Madenler -Level 27: Monster Condo,HUSTR_27,,,,Level 27: Netvoří dům,,Level 27: Monsterbehausung,,Nivelo 27: Monstro-Domo,Nivel 27: Condominio de Monstruos,,Taso 27: Hirviöasuntola,NIVEAU 27: Monstrueuse Résidence,27. Pálya: A szörnyek háza,Livello 27: Casa dei Mostri,Level 27: モンスターマンション,레벨 27: 괴물 콘도,,Nivå 27: Monsterleiligheten,Level 27: Apartament Potworów,Fase 27: Mansão dos Monstros,Nível 27: Condomínio Monstruoso,Nivelul 27: Casa monștrilor,Уровень №27: Жилище монстров,Level 27: Боравишта монструма,Seviye 27: Canavar Dairesi -Level 28: The Spirit World,HUSTR_28,,,,Level 28: Onen svět,Level 28: Åndeverdenen,Level 28: Die Geisterwelt,Επίπεδο 28: Ο Κόσμος των Πνευμάτων,Nivelo 28: La Animo-Mondo,Nivel 28: El Mundo Espiritual,,Taso 28: Henkimaailma,NIVEAU 28: Le Monde Spirituel,28. Pálya: A lelkek világa,Livello 28: Il Mondo dello Spirito,Level 28: 悪霊の世界,레벨 28: 영령의 세계,Level 28: De geestenwereld,Nivå 28: Åndeverdenen,Level 28: Świat Dusz,Fase 28: O Mundo Espiritual,Nível 28: O Mundo Espiritual,Nivelul 28: Lumea duhurilor,Уровень №28: Мир духов,Level 28: Духовни свет,Seviye 28: Ruhlar Dünyası -Level 29: The Living End,HUSTR_29,,,,Level 29: Živoucí konec,Level 29: Den levende ende,Level 29: Das lebende Ende,Επίπεδο 29: Το Ζωντανό Τέλος,Nivelo 29: La Viva Fino,Nivel 29: El Final Viviente,,Taso 29: Elävä loppu,NIVEAU 29: La Limite,29. Pálya: Az élő Végzet,Livello 29: La Fine Imminente,Level 29: 極限の存在,레벨 29: 최종점,Level 29: Het levende einde,Nivå 29: Den levende enden,Level 29: Żywy Koniec,Fase 29: O Cúmulo da Existência,Nível 29: O Cúmulo da Existência,Nivelul 29: Sfârșitul întregii vieți,Уровень №29: Конец всего живого,Level 29: Крај живота,Seviye 29: Yaşamın Sonu -Level 30: Icon of Sin,HUSTR_30,,,,Level 30: Ikona hříchu,Level 30: Syndens ikon,Level 30: Symbol der Sünde,Επίπεδο 30: Σύμβολο της Αμαρτίας,Nivelo 30: Ikono de Peko,Nivel 30: Icono del pecado,Nivel 30: Ícono del pecado,Taso 30: Synnin ikoni,NIVEAU 30: L'Icône du Péché,30. Pálya: A megtestesült bűn,Livello 30: Icona del Peccato,Level 30: 罪の聖像,레벨 30: 죄악의 상징,Level 30: Pictogram van de zonde,Nivå 30: Syndens ikon,Level 30: Ikona Grzechu,Fase 30: Ícone do Pecado,Nível 30: Ícone do Pecado,Nivelul 30: Icoana păcatelor,Уровень №30: Икона греха,Level 30: Икона греха,Seviye 30: Günah Simgesi -Level 31: Wolfenstein,HUSTR_31,,,,,,,,Nivelo 31: Wolfenstein,Nivel 31: Wolfenstein,,,,31. Pálya: Wolfenstein,Livello 31: Wolfenstein,Level 31: ウルフェンシュタイン,레벨 31: 울펜슈타인,,,Level 31: Wolfenstein,Fase 31: Wolfenstein,Nível 31: Wolfenstein,Nivelul 31: Wolfenstein,Уровень №31: Вольфенштайн,Level 31: Волфенштајн,Seviye 31: Wolfenstein -Level 32: Grosse,HUSTR_32,,,,,,,,Nivelo 32: Grosse,Nivel 32: Grosse,,,,32. Pálya: Grosse,Livello 32: Grosse,Level 32: グローシュ,레벨 32: 그로세,,,Level 32: Grosse,Fase 32: Grosse,Nível 32: Grosse,Nivelul 32: Grosse,Уровень №32: Гросс,Level 32: Гроссе,Seviye 32: Grosse -Level 31: IDKFA,HUSTR_31B,,,,,,,,Nivelo 31: IDKFA,Nivel 31: IDKFA,,,NIVEAU 31: IDKFQ,31. Pálya: IDKFA,Livello 31: IDKFA,Level 31: IDKFA,레벨 31: IDKFA,,,Level 31: IDKFA,Fase 31: IDKFA,Nível 31: IDKFA,Nivelul 31: IDKFA,Уровень №31: IDKFA,,Seviye 31: IDKFA -Level 32: Keen,HUSTR_32B,,,,,,,,Nivelo 32: Keen,Nivel 32: Keen,,,,32. Pálya: Keen,Livello 32: Keen,Level 32: キーン,레벨 32: 킨,,,Level 32: Keen,Fase 32: Keen,Nível 32: Keen,Nivelul 32: Keen,Уровень №32: Кин,Level 32: Кин,Seviye 32: Keen -Level 33: Betray,HUSTR_33,,,,Level 33: Zraď,Level 33: Forræderi,Level 33: Verrat,,Nivelo 33: Perfido,Nivel 33: Traición,,Taso 33: Petä,NIVEAU 33: Trahison,33. Pálya: Árulás,Livello 33: Tradimento ,Level 33: 裏切り,레벨 33: 배반,Level 33: Verraad,Nivå 33: Forråde,Level 33: Zdrada,Fase 33: Traição,Nível 33: Traição,Nivelul 33: Trădare,Уровень №33: Предай,Level 33: Издаја,Seviye 33: İhanet -,,No Rest For The Living,,,,,,,,,,,,,,,,,,,,,,,, -Level 1: The Earth Base,NHUSTR_1,,,,Level 1: Pozemská základna,Level 1: Jordbasen,Level 1: Die Erd-Basis,,Nivelo 1: La Tera Bazo,Nivel 1: La Base Terrestre,,Taso 1: Maatukikohta,NIVEAU 1: La Base Terrienne,1. Pálya: A földi bázis,Livello 1: La Base Terrestre ,Level 1: 地球基地,레벨 1: 지구 기지,Level 1: De basis van de aarde,Nivå 1: Jordbasen,Level 1: Ziemska Baza,Fase 1: A Base Terrestre,Nível 1: A Base Terrestre,Nivelul 1: Baza terestră,Уровень №1: База на Земле,Level 1: Земаљска база,Seviye 1: Dünya Üssü -Level 2: The Pain Labs,NHUSTR_2,,,,Level 2: Laboratoře bolesti,Level 2: Smerte laboratorier,Level 2: Die Folterlabore,,Nivelo 2: La Doloro-Laboratorio,Nivel 2: Los Laboratorios del Dolor,,Taso 2: Tuskalaboratoriot,NIVEAU 2: Les Laboratoires de la Douleur,2. Pálya: A kínok laboratóriuma,Livello 2: I Laboratori del Dolore,Level 2: 生物工学実験室,레벨 2: 고통의 연구소,Level 2: De pijnlaboratoria,Nivå 2: Smertelaboratoriet,Level 2: Laboratoria Bólu,Fase 2: Os Laboratórios da Dor,Nível 2: Os Laboratórios da Dor,Nivelul 2: Laboratoarele durerii,Уровень №2: Лаборатории боли,Level 2: Лабораторије патње,Seviye 2: Ağrı Laboratuvarları -Level 3: Canyon of The Dead,NHUSTR_3,,,,Level 3: Kaňon mrtvých,Level 3: De dødes kløft,Level 3: Schlucht der Toten,,Nivelo 3: Kanjono de La Mortintoj,Nivel 3: Cañón de los Muertos,,Taso 3: Kalmankanjoni,NIVEAU 3: Canyon des Morts,3. Pálya: A holtak szurdoka,Livello 3: Il Canyon dei Morti,Level 3: 死の渓谷,레벨 3: 죽음의 계곡,Level 3: Canyon van de doden,Nivå 3: De dødes kløft,Level 3: Kanion Umarłych,Fase 3: Desfiladeiro dos Mortos,Nível 3: Desfiladeiro dos Mortos,Nivelul 3: Canionul morților,Уровень №3: Каньон мертвецов,Level 3: Кањон мртваца,Seviye 3: Ölüler Kanyonu -Level 4: Hell Mountain,NHUSTR_4,,,,Level 4: Pekelná hora,Level 4: Helvede bjerg,Level 4: Höllenberg,,Nivelo 4: Monto de Infero,Nivel 4: Montaña Infernal,,Taso 4: Hornanvuori,NIVEAU 4: Montagne Infernale,4. Pálya: Pokol-hegy,Livello 4: Montagna Infernale ,Level 4: 地獄山脈,레벨 4: 지옥의 산,Level 4: Helleberg,Nivå 4: Helvetesfjellet,Level 4: Piekielna Góra,Fase 4: Montanha Infernal,Nível 4: Montanha Infernal,Nivelul 4: Muntele infernal,Уровень №4: Адская гора,Level 4: Планина пакла,Seviye 4: Cehennem Dağı -Level 5: Vivisection,NHUSTR_5,,,,Level 5: Vivisekce,Level 5: Vivisektion,Level 5: Vivisektion,,Nivelo 5: Vivisekcio,Nivel 5: Vivisección,,Taso 5: Vivisektio,NIVEAU 5: Vivisection,5. Pálya: Élveboncolás,Livello 5: Vivisezione ,Level 5: 生体解剖,레벨 5: 생체 해부,Level 5: Vivisectie,Nivå 5: Viviseksjon,Level 5: Wiwisekcja,Fase 5: Vivissecção,Nível 5: Vivissecção,Nivelul 5: Vivisecție,Уровень №5: Вивисекция,Level 5: Вивисекција,Seviye 5: Canlı Kesim -Level 6: Inferno of Blood,NHUSTR_6,,,,Level 6: Krvavé inferno,Level 6: Blodets inferno,Level 6: Blutiges Inferno,,Nivelo 6: Brulego de Sango,Nivel 6: Hoguera de Sangre,,Taso 6: Veri-inferno,NIVEAU 6: Enfer Sanglant,6. Pálya: Véres alvilág,Livello 6: Inferno di Sangue ,Level 6: 血のインフェルノ,레벨 6: 연옥의 피,Level 6: Bloederige inferno,Nivå 6: Blodets inferno,Level 6: Piekło Krwi,Fase 6: Inferno de Sangue,Nível 6: Inferno de Sangue,Nivelul 6: Infern sângeriu,Уровень №6: Кровавая преисподняя,Level 6: Ватре крви,Seviye 6: Kan Cehennemi -Level 7: Baron's Banquet,NHUSTR_7,,,,Level 7: Baronova hostina,Level 7: Baron's Banquet,Level 7: Das Bankett des Barons,,Nivelo 7: Festeno de Barono,Nivel 7: Banquete del Barón,,Taso 7: Paronin pidot,NIVEAU 7: Banquet du Baron,7. Pálya: A báró bankettje,Livello 7: Il Banchetto del Barone ,Level 7: バロンの晩餐,레벨 7: 남작의 연회,Level 7: Baron's banket,Nivå 7: Baronens bankett,Level 7: Bankiet Barona,Fase 7: Banquete do Barão,Nível 7: Banquete do Barão,Nivelul 7: Banchetul baronilor,Уровень №7: Банкет у барона,Level 7: Баронова Гозба,Seviye 7: Baron'un Ziyafeti -Level 8: Tomb of Malevolence,NHUSTR_8,,,,Level 8: Hrobka zlovolnosti,Level 8: Ondskabens grav,Level 8: Feindselige Gruft,,Nivelo 8: Tombo de Malbonvolo,Nivel 8: Tumba de Malevolencia,,Taso 8: Pahantahdon hauta,NIVEAU 8: Tombe Maléfique,8. Pálya: A Gátlástalanság sírja,Livello 8: Tomba della Malevolenza,Level 8: 悪意の墓,레벨 8: 증오의 무덤,Level 8: Graf van kwaadwilligheid,Nivå 8: Ondskapens grav,Level 8: Grobowiec Zła,Fase 8: Tumba da Malevolência,Nível 8: Túmulo da Malevolência,Nivelul 8: Mormântul răutății,Уровень №8: Гробница злобы,Level 8: Гроб злобе,Seviye 8: Kötülük Mezarı -Level 9: March of The Demons,NHUSTR_9,,,,Level 9: Pochod démonů,Level 9: Dæmonernes march,Level 9: Marsch der Dämonen,,Nivelo 9: Marŝo de La Demonoj,Nivel 9: Marcha de los Demonios,,Taso 9: Demonien marssi,NIVEAU 9: Marche des Démons,9. Pálya: A démonok parádéja,Livello 9: La Marcia dei Demoni ,Level 9: デーモンの行進,레벨 9: 악마들의 행진,Level 9: Maart van de demonen,Nivå 9: Demonenes marsj,Level 9: Marsz Demonów,Fase 9: Marcha dos Demônios,Nível 9: Marcha dos Demônios,Nivelul 9: Marșul demonilor,Уровень №9: Шествие демонов,Level 9: Марш демона,Seviye 9: Şeytanların Yürüyüşü -,,Plutonia,,,,,,,,,,,,,,,,,,,,,,,, -Level 1: Congo,PHUSTR_1,,,,Level 1: Kongo,,Level 1: Kongo,,Nivelo 1: Kongo,Nivel 1: Congo,,Taso 1: Kongo,NIVEAU 1: Congo,1. Pálya: Kongó,Livello 1: Congo,Level 1: コンゴ川,레벨 1: 콩고,Level 1: Kongo,Nivå 1: Kongo,Level 1: Kongo,Fase 1: Congo,Nível 1: Congo,Nivelul 1: Congo,Уровень №1: Конго,Level 1: Конго,Seviye 1: Kongo -Level 2: Well of Souls,PHUSTR_2,,,,Level 2: Studna duší,Level 2: Sjælebrønden,Level 2: Seelenbrunnen,,Nivelo 2: Puto de Animoj,Nivel 2: Pozo de Almas,,Taso 2: Sielujen lähde,NIVEAU 2: Puits des Ames,2. Pálya: A lelkek kútja,Livello 2: Pozzo delle Anime,Level 2: 魂の井戸,레벨 2: 영혼의 우물,Level 2: Bron van zielen,Nivå 2: Sjelenes brønn,Level 2: Studnia Dusz,Fase 2: Poço das Almas,Nível 2: Poço de Almas,Nivelul 2: Fântâna sufletelor,Уровень №2: Колодец душ,Level 2: Бунар душа,Seviye 2: Ruhlar Kuyusu -Level 3: Aztec,PHUSTR_3,,,,Level 3: Azték,Level 3: Azteker,Level 3: Aztekisch,,Nivelo 3: Azteko,Nivel 3: Azteca,,Taso 3: Asteekki,NIVEAU 3: Aztèque,3. Pálya: Azték,Livello 3: Aztec,Level 3: アステカ,레벨 3: 아즈텍,Level 3: Azteken,Nivå 3: Aztekisk,Level 3: Aztek,Fase 3: Asteca,Nível 3: Asteca,Nivelul 3: Aztec,Уровень №3: Ацтек,Level 3: Астек,Seviye 3: Aztek -Level 4: Caged,PHUSTR_4,,,,Level 4: V kleci,Level 4: Låst op,Level 4: Eingesperrt,,Nivelo 4: Enkaĝigita,Nivel 4: Enjaulado,,Taso 4: Häkissä,NIVEAU 4: Enfermé,4. Pálya: Ketrecbe zárva,Livello 4: Ingabbiato,Level 4: 檻の中,레벨 4: 갇히다,Level 4: Gekooid,Nivå 4: Buret,Level 4: W Klatce,Fase 4: Na Jaula,Nível 4: Na Jaula,Nivelul 4: Încarcerat,Уровень №4: В клетке,Level 4: Заробљен,Seviye 4: Kafesli -Level 5: Ghost Town,PHUSTR_5,,,,Level 5: Město duchů,Level 5: Spøgelsesby,Level 5: Geisterstadt,,Nivelo 5: Fantomurbeto,Nivel 5: Pueblo Fantasma,,Taso 5: Aavekaupunki,NIVEAU 5: Ville Fantôme,5. Pálya: Szellemváros,Livello 5: Città Fantasma,Level 5: ゴーストタウン,레벨 5: 유령 도시,Level 5: Spookstad,Nivå 5: Spøkelsesbyen,Level 5: Miasto Duchów,Fase 5: Cidade Fantasma,Nível 5: Cidade Fantasma,Nivelul 5: Orașul fantomă,Уровень №5: Город-призрак,Level 5: Град духова,Seviye 5: Hayalet Kasaba -Level 6: Baron's Lair,PHUSTR_6,,,,Level 6: Baronovo doupě,Level 6: Baronens hule,Level 6: Lager des Barons,,Nivelo 6: Nestego de Barono,Nivel 6: Guarida del Barón,,Taso 6: Paronin luola,NIVEAU 6: Repaire du Baron,6. Pálya: A báró rejteke,Livello 6: Tana del Barone,Level 6: バロンの隠れ家,레벨 6: 남작의 은신처,Level 6: Baron's kamp,Nivå 6: Baronens hule,Level 6: Legowisko Barona,Fase 6: Covil do Barão,Nível 6: Covil do Barão,Nivelul 6: Claustrul Baronului,Уровень №6: Обитель барона,Level 6: Баронова јазбина,Seviye 6: Baron'un İni -Level 7: Caughtyard,PHUSTR_7,,,,Level 7: Karcer,,Level 7: Gehege,,Nivelo 7: Kaptkorto,Nivel 7: Campo de Concentración,,Taso 7: Posenpiha,NIVEAU 7: Pris de court,7. Pálya: A foglyok udvara,Livello 7: Cortile Prigione,Level 7: 囚われの庭,레벨 7: 포획마당,Level 7: Omheining,Nivå 7: Fangegården,Level 7: Dziedziniec Więzienny,Fase 7: Campo de Concentração,Nível 7: Campo de Concentração,Nivelul 7: Capcana curții,Уровень №7: Ловчий двор,Level 7: Замчиште,Seviye 7: Caughtyard -Level 8: Realm,PHUSTR_8,,,,Level 8: Říše,Level 8: Rige,Level 8: Bereich,,Nivelo 8: Regno,Nivel 8: Reino,,Taso 8: Valtapiiri,NIVEAU 8: Royaume,8. Pálya: Uradalom,Livello 8: Regno,Level 8: 領地,레벨 8: 왕국,Level 8: Rijk,Nivå 8: Riket,Level 8: Królestwo,Fase 8: Reino,Nível 8: Reino,Nivelul 8: Tărâm,Уровень №8: Царство,Level 8: Царство,Seviye 8: Diyar -Level 9: Abattoire,PHUSTR_9,,,,Level 9: Jatka,,Level 9: Schlachthaus,,Nivelo 9: Buĉejo,Nivel 9: Matadero,,Taso 9: Teurastamo,NIVEAU 9: Abattoir,9. Pálya: Vágóhíd,Livello 9: Mattatoio,Level 9: 屠殺場,레벨 9: 도축장,Level 9: Abattoir,Nivå 9: Slakteriet,Level 9: Rzeźnia,Fase 9: Matadouro,Nível 9: Matadouro,Nivelul 9: Abator,Уровень №9: Абатство,Level 9: Кланица,Seviye 9: Abattoire -Level 10: Onslaught,PHUSTR_10,,,,Level 10: Nájezd,Level 10: Stormløb,Level 10: Angriff,,Nivelo 10: Buĉado,Nivel 10: Arremetida,,Taso 10: Ryntäys,NIVEAU 10: Assaut,10. Pálya: Roham,Livello 10: Assalto,Level 10: 猛襲,레벨 10: 맹공격,Level 10: Aanval,Nivå 10: Angrep,Level 10: Szturm,Fase 10: Investida,Nível 10: Investida,Nivelul 10: Năvala,Уровень №10: Натиск,Level 10: Јуриш,Seviye 10: Saldırı -Level 11: Hunted,PHUSTR_11,,,,Level 11: Loven,Level 11: Jaget,Level 11: Gehetzt,,Nivelo 11: Ĉasata,Nivel 11: Cazado,,Taso 11: Metsästetty,NIVEAU 11: Traque,11. Pálya: Űzött vad,Livello 11: Braccato,Level 11: 逃走,레벨 11: 사냥당함,Level 11: Gejaagd,Nivå 11: Jaget,Level 11: Nawiedzony,Fase 11: Perseguição,Nível 11: Perseguição,Nivelul 11: Vânătoarea,Уровень №11: Преследуемый,Level 11: Уловљен,Seviye 11: Avlanmış -Level 12: Speed,PHUSTR_12,,,,Level 12: Rychlost,Level 12: Fart,Level 12: Tempo,,Nivelo 12: Rapido,Nivel 12: Velocidad,,Taso 12: Vauhti,NIVEAU 12: Vitesse,12. Pálya: Iram,Livello 12: Velocità,Level 12: スピード,레벨 12: 스피드,Level 12: Haast,Nivå 12: Hastighet,Level 12: Pęd,Fase 12: Velocidade,Nível 12: Velocidade,Nivelul 12: Viteză,Уровень №12: Скорость,Level 12: Брзина,Seviye 12: Hız -Level 13: The Crypt,PHUSTR_13,,,,Level 13: Krypta,Level 13: Krypten,Level 13: Die Gruft,,Nivelo 13: La Kripto,Nivel 13: La Cripta,,Taso 13: Krypta,NIVEAU 13: La Crypte,13. Pálya: A kripta,Livello 13: La Cripta,Level 13: 地下聖堂,레벨 13: 봉안당,Level 13: De crypte,Nivå 13: Krypten,Level 13: Krypta,Fase 13: A Cripta,Nível 13: A Cripta,Nivelul 13: Cripta,Уровень №13: Склеп,Level 13: Гробница,Seviye 13: Mahzen -Level 14: Genesis,PHUSTR_14,,,,,,,,Nivelo 14: Genezo,Nivel 14: Génesis,,Taso 14: Luominen,NIVEAU 14: Genèse,14. Pálya: Teremtés,Livello 14: Genesi,Level 14: 創世記,레벨 14: 창세기,,,Level 14: Geneza,Fase 14: Gênese,Nível 14: Gênese,Nivelul 14: Geneza,Уровень №14: Зарождение,Level 14: Постанак,Seviye 14: Yaratılış -Level 15: The Twilight,PHUSTR_15,,,,Level 15: Soumrak,Level 15: Tusmørket,Level 15: Zwielicht,,Nivelo 15: La Krepusko,Nivel 15: El Ocaso,,Taso 15: Hämärä,NIVEAU 15: Le Crépuscule,15. Pálya: Alkonyat,Livello 15: Il Crepuscolo,Level 15: 黄昏,레벨 15: 황혼,Level 15: De schemering,Nivå 15: Skumringen,Level 15: Zmierzch,Fase 15: O Crepúsculo,Nível 15: O Crepúsculo,Nivelul 15: Amurgul,Уровень №15: Сумерки,Level 15: Сумрак,Seviye 15: Alacakaranlık -Level 16: The Omen,PHUSTR_16,,,,Level 16: Znamení,Level 16: Omenet,Level 16: Das Omen,,Nivelo 16: La Aŭguro,Nivel 16: El Presagio,,Taso 16: Enne,NIVEAU 16: Le Présage,16. Pálya: Az Ómen,Livello 16: Il Presagio,Level 16: 予兆,레벨 16: 징조,Level 16: De omen,Nivå 16: Varselet,Level 16: Omen,Fase 16: O Presságio,Nível 16: O Presságio,Nivelul 16: Prevestirea,Уровень №16: Предзнаменование,Level 16: Знамење,Seviye 16: Omen -Level 17: Compound,PHUSTR_17,,,,Level 17: Ústav,Level 17: Forbindelsen,Level 17: Anlage,,Nivelo 17: Konstruaĵaro,Nivel 17: Complejo,,Taso 17: Laitos,NIVEAU 17: Installation,17. Pálya: Létesítmény,Livello 17: Recinto,Level 17: 調合,레벨 17: 복합체,Level 17: Faciliteit,Nivå 17: Forbindelsen,Level 17: Mieszanka,Fase 17: Complexo,Nível 17: Complexo,Nivelul 17: Complexul,Уровень №17: Комплекс,Level 17: Једињење,Seviye 17: Bileşik -Level 18: Neurosphere,PHUSTR_18,,,,Level 18: Neurosféra,Level 18: Neurosfæren,Level 18: Neurosphäre,,Nivelo 18: Neŭrosfero,Nivel 18: Neuroesfera,,Taso 18: Neurosfääri,NIVEAU 18: Neurosphère,18. Pálya: Neuroszféra,Livello 18: Neurosfera,Level 18: ニューロスフィア,레벨 18: 뉴로스피어,Level 18: Neurosferen,Nivå 18: Nevrosfæren,Level 18: Neurosfera,Fase 18: Neurosfera,Nível 18: Neurosfera,Nivelul 18: Neurosferă,Уровень №18: Нейросфера,Level 18: Неуросфера,Seviye 18: Nörosfer -Level 19: NME,PHUSTR_19,"“NME” read out loud means “enemy”, so translators should consider the translation of “enemy” into their language.",,,Level 19: Nepřítel,,,,Nivelo 19: Mal-BN,Nivel 19: N-MIGO,,Taso 19: VHLLNN,NIVEAU 19: NMI,19. Pálya: LNSG,Livello 19: NMIC,Level 19: 野郎,레벨 19: NOM,,,Level 19: WRG,Fase 19: N-MIGO,Nível 19: N-MIGO,Nivelul 19: INMIC,Уровень №19: В.Р.А.Г.,Level 19: Н.Е.П.Р.,Seviye 19: NME -Level 20: The Death Domain,PHUSTR_20,,,,Level 20: Panství smrti,Level 20: Dødsdomænet,Level 20: Die Todeszone,,Nivelo 20: La Regno de Morto,Nivel 20: El Dominio Mortal,,Taso 20: Kuoleman piiri,NIVEAU 20: Le Domaine de la Mort,20. Pálya: A holtak birtoka,Livello 20: Il Dominio della Morte,Level 20: 死の領域,레벨 20: 죽음의 영역,Level 20: Het domein van de dood,Nivå 20: Dødens domene,Level 20: Domena Śmierci,Fase 20: O Domínio da Morte,Nível 20: O Domínio da Morte,Nivelul 20: Domeniul morții,Уровень №20: Владения смерти,Level 20: Подручије смрти,Seviye 20: Ölüm Alanı -Level 21: Slayer,PHUSTR_21,,,,Level 21: Zabiják,Level 21: Slagter,Level 21: Töter,,Nivelo 21: Mortigisto,Nivel 21: Descuatizador,,Taso 21: Tappaja,NIVEAU 21: Pourfendeur,21. Pálya: Halálosztó,Livello 21: Assassino,Level 21: スレイヤー,레벨 21: 슬레이어,Level 21: Doder,Nivå 21: Slakteren,Level 21: Pogromca,Fase 21: Matador,Nível 21: Matador,Nivelul 21: Ucigător,Уровень №21: Истребитель,Level 21: Убица,Seviye 21: Avcı -Level 22: Impossible Mission,PHUSTR_22,,,,Level 22: Nemožná mise,Level 22: Umulig mission,Level 22: Unmögliche Mission,,Nivelo 22: Malebla Misio,Nivel 22: Misión Imposible,,Taso 22: Mahdoton tehtävä,NIVEAU 22: Mission Impossible,22. Pálya: Lehetetlen küldetés,Livello 22: Missione Impossibile,Level 22: 不可能な任務,레벨 22: 임파서블 미션,Level 22: Onmogelijke missie,Nivå 22: Umulig oppdrag,Level 22: Niemożliwa Misja,Fase 22: Missão Impossível,Nível 22: Missão Impossível,Nivelul 22: Misiune imposibilă,Уровень №22: Невыполнимое задание,Level 22: Немогућа мисија,Seviye 22: İmkansız Görev -Level 23: Tombstone,PHUSTR_23,,,,Level 23: Náhrobek,Level 23: Gravsten,Level 23: Grabstein,,Nivelo 23: Tombŝtono,Nivel 23: Lápida,,Taso 23: Hautakivi,NIVEAU 23: Pierre Tombale,23. Pálya: Sírkő,Livello 23: Pietra Tombale,Level 23: 墓石,레벨 23: 묘비,Level 23: Grafsteen,Nivå 23: Gravstein,Level 23: Nagrobek,Fase 23: Lápide,Nível 23: Lápide,Nivelul 23: Piatra de mormânt,Уровень №23: Надгробие,Level 23: Надгробни споменик,Seviye 23: Mezar Taşı -Level 24: The Final Frontier,PHUSTR_24,,,,Level 24: Poslední hranice,Level 24: Den endelige grænse,Level 24: Die letzte Grenze,,Nivelo 24: La Fina Limo,Nivel 24: La Frontera Final,Nivel 24: La Última Frontera,Taso 24: Viimeinen rajamaa,NIVEAU 24: La Frontière Finale,24. Pálya: A végső határ,Livello 24: La Frontiera Finale,Level 24: 最後のフロンティア,레벨 24: 최후의 개척지,Level 24: De eindgrens,Nivå 24: Den siste grensen,Level 24: Ostateczna Granica,Fase 24: A Fronteira Final,Nível 24: A Fronteira Final,Nivelul 24: Ultima frontieră,Уровень №24: Последний рубеж,Level 24: Коначна граница,Seviye 24: Son Sınır -Level 25: The Temple of Darkness,PHUSTR_25,,,,Level 25: Chrám temna,Level 25: Mørkets tempel,Level 25: Der Tempel der Dunkelheit,,Nivelo 25: La Idolejo de Mallumo,Nivel 25: El Templo de la Oscuridad,,Taso 25: Pimeyden temppeli,NIVEAU 25: Le Temple des Ténèbres,25. Pálya: A sötétség temploma,Livello 25: Il Tempio dell'Oscurità,Level 25: 暗黒の神殿,레벨 25: 어둠의 신전,Level 25: De tempel van de duisternis,Nivå 25: Mørkets tempel,Level 25: Świątynia Mroku,Fase 25: O Templo da Escuridão,Nível 25: O Templo da Escuridão,Nivelul 25: Templul tenebros,Уровень №25: Храм тьмы,Level 25: Храм таме,Seviye 25: Karanlığın Tapınağı -Level 26: Bunker,PHUSTR_26,,,,Level 26: Bunkr,,Level 26: Bunker,,Nivelo 26: Bunkro,Nivel 26: Búnker,,Taso 26: Bunkkeri,NIVEAU 26: Bunker,26. Pálya: Bunker,Livello 26: Bunker,Level 26: バンカー,레벨 26: 방공호,,,Level 26: Bunkier,Fase 26: Casamata,Nível 26: Bunker,Nivelul 26: Buncăr,Уровень №26: Бункер,Level 26: Бункер,Seviye 26: Sığınak -Level 27: Anti-christ,PHUSTR_27,,,,Level 27: Antikrist,,Level 27: Antichrist,,Nivelo 27: Antikristo,Nivel 27: Anti-cristo,,Taso 27: Antikristus,NIVEAU 27: Anti-Christ,27. Pálya: Antikrisztus,Livello 27: Anticristo,Level 27: アンチキリスト,레벨 27: 적그리스도,Level 27: Antichrist,Nivå 27: Antikrist,Level 27: Antychryst,Fase 27: Anticristo,Nível 27: Anticristo,Nivelul 27: Antihrist,Уровень №27: Антихрист,Level 27: Антихрист,Seviye 27: Mesih Karşıtı -Level 28: The Sewers,PHUSTR_28,,,,Level 28: Kanály,Level 28: Kloakkerne,Level 28: Kanäle,,Nivelo 28: La Kanalo,Nivel 28: Las Alcantarillas,,Taso 28: Viemärit,NIVEAU 28: Les Egouts,28. Pálya: A kanális,Livello 28: Le Fogne,Level 28: 下水道,레벨 28: 하수구,Level 28: De rioleringen,Nivå 28: Kloakken,Level 28: Ścieki,Fase 28: Os Esgotos,Nível 28: Os Esgotos,Nivelul 28: Canalizarea,Уровень №28: Канализация,Level 28: Канализација,Seviye 28: Kanalizasyonlar -Level 29: Odyssey of Noises,PHUSTR_29,,,,Level 29: Odysea křiku,Level 29: Lydenes odyssé,Level 29: Odyssee der Geräusche,,Nivelo 29: Vojaĝo de Sonoj,Nivel 29: Odisea de Ruidos,,Taso 29: Äänten harharetki,NIVEAU 29: Odysée de Bruits,29. Pálya: A moraj ösvénye,Livello 29: Odissea dei Rumori,Level 29: オデッセイのノイズ,레벨 29: 속삭임의 여정,Level 29: Odyssee van geluiden,Nivå 29: Lydenes odyssé,Level 29: Odyseja Wrzawy,Fase 29: Odisséia de Ruidos,Nível 29: Odisséia de Ruidos,Nivelul 29: Odiseea zgomotelor,Уровень №29: Одиссея шумов,Level 29: Одисеја шумова,Seviye 29: Seslerin Odyssey'i -Level 30: The Gateway of Hell,PHUSTR_30,,,,Level 30: Brána pekla,Level 30: Helvedes port,Level 30: Tor zur Hölle,,Nivelo 30: La Pordego de Inferno,Nivel 30: La Puerta del Infierno,,Taso 30: Helvetin porttikäytävä,NIVEAU 30: La Porte des Enfers,30. Pálya: Átjáró a pokolba,Livello 30: La Porta dell'Inferno,Level 30: 地獄の関門,레벨 30: 지옥의 차원문,Level 30: De poort van de hel,Nivå 30: Porten til helvete,Level 30: Brama Piekieł,Fase 30: O Portão do Inferno,Nível 30: O Portão do Inferno,Nivelul 30: Poarta spre infern,Уровень №30: Врата ада,Level 30: Пролаз пакла,Seviye 30: Cehennem Kapısı -Level 31: Cyberden,PHUSTR_31,,,,Level 31: Kyberdoupě,,Level 31: Cyberbau,,Nivelo 31: Cibernesto,Nivel 31: Ciber-guarida,,Taso 31: Kyberpesä,NIVEAU 31: Cyber-Antre,31. Pálya: Kiberodú,Livello 31: Cybergabbia,Level 31: サイバーの巣,레벨 31: 사이버소굴,,,Level 31: Cybernora,Fase 31: Ciberantro,Nível 31: Ciberantro,Nivelul 31: Cibervizuină,Уровень №31: Киберлогово,Level 31: Сајбер-јазбина,Seviye 31: Siber'in ini -Level 32: Go 2 It,PHUSTR_32,,,,Level 32: Jdi do toho,,,,Nivelo 32: Iru Al Ĝi!,Nivel 32: Ve a x ello,Nivel 32: Ve x eso,Taso 32: Iske kii,NIVEAU 32: Go 2 It,32. Pálya: Menj oda!,Livello 32: Dacci Dentro,Level 32: 逝ってこい,레벨 32: 함 해 봐,Level 32: Ga ervoor,,Level 32: Do Dzieła,Fase 32: Vai Fundo,Nível 32: Siga em Frente,Nivelul 32: Du-te la ei,Уровень №32: П0лный вп3рёд,Level 32: Иди ка њему,Seviye 32: Devam Et -,,TNT: Evilution,,,,,,,,,,,,,,,,,,,,,,,, -Level 1: System Control,THUSTR_1,,,,Level 1: Administrace,Level 1: Systemkontrol,Level 1: Systemkontrolle,,Nivelo 1: Sistema Kontrolo,Nivel 1: Control del Sistema,,Taso 1: Järjestelmäohjaamo,NIVEAU 1: Système de Contrôle,1. Pálya: Rendszervezérlő,Livello 1: Controllo del Sistema,Level 1: 制御システム,레벨 1: 시스템 제어시설,Level 1: Systeemcontrole,Nivå 1: Systemkontroll,Level 1: Kontrola Systemu,Fase 1: Controle do Sistema,Nível 1: Controlo de Sistema,Nivelul 1: Control sisteme,Уровень №1: Центр управления системой,Level 1: Контролна система,Seviye 1: Sistem Kontrolü -Level 2: Human BBQ,THUSTR_2,,,,Level 2: Člověčí grilovačka,Level 2: Menneskelig grill,Level 2: Menschliches Barbecue,,Nivelo 2: Homo-Kradrostado,Nivel 2: Barbacoa Humana,,Taso 2: Ihmisgrilli,NIVEAU 2: Barbecue Humain,2. Pálya: Emberi grill,Livello 2: Barbecue Umano,Level 2: 人肉晩餐会,레벨 2: 인간 바비큐,Level 2: Menselijke BBQ,Nivå 2: Menneskelig BBQ,Level 2: Ludzki Grill,Fase 2: Churrasco Humano,Nível 2: Churrasco Humano,Nivelul 2: Oameni la grătar,Уровень №2: Барбекю из человечины,Level 2: Људски роштиљ,Seviye 2: İnsan Barbekü -Level 3: Power Control,THUSTR_3,,,,Level 3: Napájecí vedení,Level 3: Kontrol med magten,Level 3: Energiekontrolle,,Nivelo 3: Energia Kontrolo,Nivel 3: Control de Energía,,Taso 3: Voimalan ohjaamo,NIVEAU 3: Contrôle Energétique,3. Pálya: Energiavezérlő,Livello 3: Centrale Energetica,Level 3: 制御室,레벨 3: 전력 통제소,Level 3: Machtscontrole,Nivå 3: Kraftkontroll,Level 3: Kontrola Zasilania,Fase 3: Controle de Energia,Nível 3: Controlo Energético,Nivelul 3: Uzina,Уровень №3: Центр управления питанием,Level 3: Контролна моћ,Seviye 3: Güç Kontrolü -Level 4: Wormhole,THUSTR_4,,,,Level 4: Červí díra,Level 4: Ormehul,Level 4: Wurmloch,,Nivelo 4: Vermtruo,Nivel 4: Agujero de Gusano,,Taso 4: Madonreikä,NIVEAU 4: Trou de Ver,4. Pálya: Féreglyuk,Livello 4: Wormhole,Level 4: 虫喰い穴,레벨 4: 웜홀,Level 4: Wormgat,Nivå 4: Ormehull,Level 4: Tunel,Fase 4: Buraco de Minhoca,Nível 4: Buraco de Minhoca,Nivelul 4: Gaura de vierme,Уровень №4: Червоточина,Level 4: Црвоточина,Seviye 4: Solucan Deliği -Level 5: Hanger,THUSTR_5,"Not ""Hangar""",,,Level 5: Hangár,,Level 5: Hangar,,Nivelo 5: Pendigejo,Nivel 5: Colgador,,Taso 5: Lentoalushalli,NIVEAU 5: Hangar,5. Pálya: Horog,Livello 5: Hanga,Level 5: 格納庫,레벨 5: 격납고,Level 5: Hangar,Nivå 5: Hanger,Level 5: Hangar,Fase 5: Hangar,Nível 5: Hangar,Nivelul 5: Hangar,Уровень №5: Ангар,Level 5: Вешалица,Seviye 5: Askı -Level 6: Open Season,THUSTR_6,,,,Level 6: Lovecká sezóna,Level 6: Åben sæson,Level 6: Jagdsaison,,Nivelo 6: Ĉasosezono,Nivel 6: Temporada Abierta,,Taso 6: Avoin sesonki,NIVEAU 6: La Chasse Est Ouverte,6. Pálya: Vadászszezon,Livello 6: Stagione Aperta,Level 6: 狩猟解禁,레벨 6: 사냥철,Level 6: Open seizoen,Nivå 6: Åpen sesong,Level 6: Otwarty Sezon,Fase 6: Temporada Aberta,Nível 6: Época Aberta,Nivelul 6: Sezon deschis,Уровень №6: Сезон охоты,Level 6: Отворена сезона,Seviye 6: Açık Sezon -Level 7: Prison,THUSTR_7,,,,Level 7: Vězení,Level 7: Fængsel,Level 7: Gefängnis,,Nivelo 7: Malliberejo,Nivel 7: Prisión,,Taso 7: Vankila,NIVEAU 7: Prison,7. Pálya: Börtön,Livello 7: Prigione,Level 7: 監獄,레벨 7: 감옥,Level 7: Gevangenis,Nivå 7: Fengsel,Level 7: Więzienie,Fase 7: Prisão,Nível 7: Prisão,Nivelul 7: Închisoare,Уровень №7: Тюрьма,Level 7: Затвор,Seviye 7: Hapishane -Level 8: Metal,THUSTR_8,,,,Level 8: Kov,,Level 8: Metall,,Nivelo 8: Metalo,Nivel 8: Metal,,Taso 8: Metalli,NIVEAU 8: Métal,8. Pálya: Fém,Livello 8: Metallo,Level 8: メタル,레벨 8: 강철,Level 8: Metaal,Nivå 8: Metall,Level 8: Metal,Fase 8: Metal,Nível 8: Metal,Nivelul 8: Metal,Уровень №8: Металл,Level 8: Метал,Seviye 8: Metal -Level 9: Stronghold,THUSTR_9,,,,Level 9: Pevnost,Level 9: Borgen,Level 9: Festung,,Nivelo 9: Fuorto,Nivel 9: Fortaleza,,Taso 9: Linnake,NIVEAU 9: Forteresse,9. Pálya: Erőd,Livello 9: Fortezza,Level 9: 牙城,레벨 9: 요새,Level 9: Vesting,Nivå 9: Festning,Level 9: Warownia,Fase 9: Fortaleza,Nível 9: Fortaleza,Nivelul 9: Bastion,Уровень №9: Твердыня,Level 9: Упориште,Seviye 9: Kale -Level 10: Redemption,THUSTR_10,,,,Level 10: Vykoupení,Level 10: Forløsning,Level 10: Erlösung,,Nivelo 10: Elaĉeto,Nivel 10: Redención,,Taso 10: Lunastus,NIVEAU 10: Rédemption,10. Pálya: Megváltás,Livello 10: Redenzione,Level 10: 償還,레벨 10: 구원,Level 10: Aflossing,Nivå 10: Innløsning,Level 10: Odkupienie,Fase 10: Redenção,Nível 10: Redenção,Nivelul 10: Răscumpărare,Уровень №10: Искупление,Level 10: Искупљење,Seviye 10: Kefaret -Level 11: Storage Facility,THUSTR_11,,,,Level 11: Skladiště,Level 11: Opbevaringsanlæg,Level 11: Lagerstätte,,Nivelo 11: Stokejo,Nivel 11: Complejo de Almacenes,Nivel 11: Almacenes,Taso 11: Varastolaitos,NIVEAU 11: Complexe de Stockage,11. Pálya: Raktárépület,Livello 11: Impianto di Stoccaggio,Level 11: 貯蔵施設,레벨 11: 저장소,Level 11: Opslagfaciliteit,Nivå 11: Lagringsanlegg,Level 11: Magazyn,Fase 11: Centro de Armazenamento,Nível 11: Centro de Armazenamento,Nivelul 11: Stația de depozitare,Уровень №11: Склад,Level 11: Складиште,Seviye 11: Depolama Tesisi -Level 12: Crater,THUSTR_12,,,,Level 12: Kráter,Level 12: Krater,Level 12: Krater,,Nivelo 12: Kratero,Nivel 12: Cráter,,Taso 12: Kraateri,NIVEAU 12: Cratère,12. Pálya: Kráter,Livello 12: Cratere,Level 12: 火口,레벨 12: 분화구,Level 12: Krater,Nivå 12: Krater,Level 12: Krater,Fase 12: Cratera,Nível 12: Cratera,Nivelul 12: Crater,Уровень №12: Кратер,Level 12: Кратер,Seviye 12: Krater -Level 13: Nukage Processing,THUSTR_13,,,,Level 13: Jaderné zpracování,Level 13: Nukageforarbejdning,Level 13: Nuklearverarbeitung,,Nivelo 13: Nukleaĵo-Traktejo,Nivel 13: Procesamiento de Residuos Nucleares,,Taso 13: Ydinjätekäsittely,NIVEAU 13: Traitement Nucléaire,13. Pálya: Atomhulladék-feldolgozó,Livello 13: Trattamento Nucleare,Level 13: 核廃棄物加工所,레벨 13: 폐기물 처리소,Level 13: Nucleaire verwerking,Nivå 13: Nukage-prosessering,Level 13: Przetwórstwo Jądrowe,Fase 13: Processamento Nuclear,Nível 13: Processamento Nuclear,Nivelul 13: Prelucrarea deșeurilor nucleare,Уровень №13: Переработка ядерных отходов,Level 13: Прерада нуклеарног отпада,Seviye 13: Nukage İşleme -Level 14: Steel Works,THUSTR_14,,,,Level 14: Ocelárna,Level 14: Stålværk,Level 14: Stahlwerk,,Nivelo 14: Ŝtalejo,Nivel 14: Siderúrgica,Nivel 14: Siderurgia,Taso 14: Terästehdas,NIVEAU 14: Aciérie,14. Pálya: Acélművek,Livello 14: Acciaieria,Level 14: 製鉄所,레벨 14: 제강소,Level 14: Staalfabrieken,Nivå 14: Stålverk,Level 14: Huta,Fase 14: Siderúrgica,Nível 14: Siderúrgica,Nivelul 14: Oțelărie,Уровень №14: Сталелитейный завод,Level 14: Челичана,Seviye 14: Çelik İşleri -Level 15: Dead Zone,THUSTR_15,,,,Level 15: Mrtvá zóna,Level 15: Død zone,Level 15: Tote Zone,,Nivelo 15: Senvivzono,Nivel 15: Zona Muerta,,Taso 15: Kuollut alue,NIVEAU 15: Zone Morte,15. Pálya: A holtak zónája,Livello 15: Zona Morta,Level 15: 危険地帯,레벨 15: 사각지대,Level 15: Dode zone,Nivå 15: Død sone,Level 15: Martwa Strefa,Fase 15: Zona Morta,Nível 15: Zona Morta,Nivelul 15: Zona moartă,Уровень №15: Мёртвая зона,Level 15: Зона смрти,Seviye 15: Ölü Bölge -Level 16: Deepest Reaches,THUSTR_16,,,,Level 16: Nejhlubší sluje,Level 16: De dybeste afkroge,Level 16: Tiefe,,Nivelo 16: Plejsubejo,Nivel 16: Recodos profundos,,Taso 16: Syvyydet,NIVEAU 16: Profondeurs,16. Pálya: A legmélyebb pont,Livello 16: Profondità,Level 16: 最深部,레벨 16: 깊숙한 강,Level 16: Diepste reiken,Nivå 16: De dypeste områdene,Level 16: Głębiny,Fase 16: Profundezas,Nível 16: Profundezas,Nivelul 16: În adâncuri,Уровень №16: Глубочайшие достижения,Level 16: Најдубља дубина,Seviye 16: En Derin Erişimler -Level 17: Processing Area,THUSTR_17,,,,Level 17: Kombinát,Level 17: Forarbejdningsområde,Level 17: Verarbeitungsbereich,,Nivelo 17: Traktadareo,Nivel 17: Área de Procesamiento,,Taso 17: Käsittelyalue,NIVEAU 17: Zone de Traitement,17. Pálya: Feldolgozó,Livello 17: Area di Elaborazione,Level 17: 処理地帯,레벨 17: 처리 구역,Level 17: Verwerkingsgebied,Nivå 17: Behandlingsområde,Level 17: Strefa Przerobowa,Fase 17: Área de Processamento,Nível 17: Área de Processamento,Nivelul 17: Aria de procesare,Уровень №17: Зона обработки,Level 17: Подручје обраде,Seviye 17: İşleme Alanı -Level 18: Mill,THUSTR_18,,,,Level 18: Mlýn,Level 18: Mølle,Level 18: Mühle,,Nivelo 18: Muelejo,Nivel 18: Molino,,Taso 18: Mylly,NIVEAU 18: Fonderie,18. Pálya: Malom,Livello 18: Fonderia,Level 18: 製粉所,레벨 18: 제분소,Level 18: Molen,Nivå 18: Mølle,Level 18: Młyn,Fase 18: Moinho,Nível 18: Moinho,Nivelul 18: Moara,Уровень №18: Завод,Level 18: Млин,Seviye 18: Değirmen -Level 19: Shipping/respawning,THUSTR_19,,,,Level 19: Přeprava,Level 19: Forsendelsescenter,Level 19: Versandlager,,Nivelo 19: Ekspedo/Revivado,Nivel 19: Enviando/Reapareciendo,,Taso 19: Huolinta/Ylösnostatus,NIVEAU 19: Envoi/Réapparition,19. Pálya: Szállítás/újraéledés,Livello 19: Consegna/Respawn,Level 19: 出荷と再生成,레벨 19: 운송/리스폰 장소,Level 19: Verzendingscentrum,Nivå 19: Frakt/omlasting,Level 19: Wysyłka/Reprodukcja,Fase 19: Expedição/reaparecimento,Nível 19: Expedição/reaparecimento,Nivelul 19: Livrare/reapariție,Уровень №19: Погрузка и отправка,Level 19: Отпремање/оживљавање,Seviye 19: Nakliye Merkezi -Level 20: Central Processing,THUSTR_20,,,,Level 20: Centrální zpracování,Level 20: Central forarbejdning,Level 20: Zentralverarbeitung,,Nivelo 20: Centra Eskpedado,Nivel 20: Procesamiento Central,,Taso 20: Käsittelykeskus,NIVEAU 20: Organisme Central,20. Pálya: Központi feldolgozó,Livello 20: Centrale di Elaborazione,Level 20: 中央処理所,레벨 20: 중앙 처리소,Level 20: Centrale verwerking,Nivå 20: Sentral behandling,Level 20: Centralny Proces,Fase 20: Processamento Central,Nível 20: Processamento Central,Nivelul 20: Prelucrare centrală,Уровень №20: Центральный пункт обработки,Level 20: Централна обрада,Seviye 20: Merkezi İşlem -Level 21: Administration Center,THUSTR_21,,,,Level 21: Administrativní centrum,Level 21: Administrationscenter,Level 21: Verwaltungszentrum,,Nivelo 21: Administracia Centro,Nivel 21: Centro de Administración,,Taso 21: Keskushallinto,NIVEAU 21: Centre Administratif,21. Pálya: Adminisztrációs központ,Livello 21: Centro Amministrativo,Level 21: 行政センター,레벨 21: 관리 센터,Level 21: Administratief centrum,Nivå 21: Administrasjonssenter,Level 21: Centrum Administracyjne,Fase 21: Centro de Administração,Nível 21: Centro de Administração,Nivelul 21: Centru administrativ,Уровень №21: Административный центр,Level 21: Административни центар,Seviye 21: Yönetim Merkezi -Level 22: Habitat,THUSTR_22,,,,,Level 22: Levested,,,Nivelo 22: Habitato,Nivel 22: Hábitat,,Taso 22: Asuinpaikka,NIVEAU 22: Habitat,22. Pálya: Élőhely,Livello 22: Habitat,Level 22: 生息地,레벨 22: 서식지,,Nivå 22: Habitat,Level 22: Siedlisko,Fase 22: Habitat,Nível 22: Habitat,Nivelul 22: Habitat,Уровень №22: Ареал,Level 22: Станиште,Seviye 22: Habitat -Level 23: Lunar Mining Project,THUSTR_23,,,,Level 23: Lunární těžební projekt,Level 23: Projekt for månens minedrift,Level 23: Mondbergbauprojekt,,Nivelo 23: Luna Mino-Projekto,Nivel 23: Proyecto de Minería Lunar,,Taso 23: Kuukaivosprojekti,NIVEAU 23: Projet Minier Lunaire,23. Pálya: Holdbánya-projekt,Livello 23: Progetto Minerario Lunare,Level 23: 月面探鉱計画,레벨 23: 월석 채광 계획,Level 23: Maanmijnbouw project,Nivå 23: Månegruveprosjekt,Level 23: Projekt Księżycowe Górnictwo,Fase 23: Projeto de Mineração Lunar,Nível 23: Projeto de Escavação Lunar,Nivelul 23: Proiect minier satelitar,Уровень №23: Лунный проект горной добычи,Level 23: Пројекат лунарног рударства,Seviye 23: Ay Madenciliği Projesi -Level 24: Quarry,THUSTR_24,,,,Level 24: Kamenolom,Level 24: Stenbrud,Level 24: Steinbruch,,Nivelo 24: Ŝtonejo,Nivel 24: Cantera,,Taso 24: Louhos,NIVEAU 24: Carrière,24. Pálya: Kőbánya,Livello 24: Caccia,Level 24: 採石場,레벨 24: 채석장,Level 24: Steengroeve,Nivå 24: Steinbrudd,Level 24: Kamieniołom,Fase 24: Pedreira,Nível 24: Pedreira,Nivelul 24: Carieră,Уровень №24: Карьер,Level 24: Каменолом,Seviye 24: Taş Ocağı -Level 25: Baron's Den,THUSTR_25,,,,Level 25: Baronovo doupě,Level 25: Baronens hule,Level 25: Der Bau des Barons,,Nivelo 25: Nestego de Barono,Nivel 25: Guarida del Barón,,Taso 25: Paronin pesä,NIVEAU 25: l'Antre des Barons,25. Pálya: A báró odúja,Livello 25: Antro del Barone,Level 25: バロンの巣窟,레벨 25: 남작의 소굴,Level 25: Het baron's gebouw,Nivå 25: Baronens hule,Level 25: Legowisko Barona,Fase 25: Covil do Barão,Nível 25: Covil do Barão,Nivelul 25: Cuibul Baronului,Уровень №25: Логово барона,Level 25: Баронова јазбина,Seviye 25: Baron'un İni -Level 26: Ballistyx,THUSTR_26,,,,Level 26: Balistika,,,,Nivelo 26: Balistikso,Nivel 26: Balístige,,Taso 26: Ballistyks,NIVEAU 26: Ballistyx,26. Pálya: Ballisztüx,Livello 26: Ballistige,Level 26: バリステュクス,레벨 26: 탄도스틱스,,,Level 26: Balistyka,Fase 26: Ballistige,Nível 26: Ballistige,Nivelul 26: Ballistyx,Уровень №26: Баллистикс,Level 26: Билистичкикс,Seviye 26: Balistyx -Level 27: Mount Pain,THUSTR_27,,,,Level 27: Hora bolesti,Level 27: Smertefjellet,Level 27: Berg des Schmerzes,,Nivelo 27: Monto de Doloro,Nivel 27: Monte Dolor,,Taso 27: Tuskavuori,NIVEAU 27: Mont Souffrance,27. Pálya: A Gyötrelem Hegye,Livello 27: Monte del Dolore,Level 27: 苦しみの山,레벨 27: 등신같은 등산,Level 27: Pijn in de bergen,Nivå 27: Smertefjellet,Level 27: Góra Bólu,Fase 27: Monte Dor,Nível 27: Monte Dor,Nivelul 27: Muntele Durerii,Уровень №27: Гора Боль,Level 27: Планина боли,Seviye 27: Acı Dağı -Level 28: Heck,THUSTR_28,,,,Level 28: Sakra,,Level 28: Zum Teufel,,Nivelo 28: Diable,Nivel 28: Diablos,,Taso 28: Hemmetti,NIVEAU 28: Que Diable?,28. Pálya: Rosseb,Livello 28: Al Diavolo,Level 28: 苛立ち,레벨 28: 젠장함,,Nivå 28: Helvete,Level 28: Do Diabła,Fase 28: Capeta,Nível 28: Inferno,Nivelul 28: Naiba,Уровень №28: Чертовщина,Level 28: Пакао,Seviye 28: Cehennem -Level 29: River Styx,THUSTR_29,,,,Level 29: Řeka Styx,Level 29: Floden Styx,Level 29: Fluss Styx,,Nivelo 29: Rivero de Stikso,Nivel 29: Río Estige,,Taso 29: Styksjoki,NIVEAU 29: Fleuve Styx,29. Pálya: A Sztüx folyó,Livello 29: Fiume Stige,Level 29: 三途の川,레벨 29: 스틱스 강,Level 29: Rivier Styx,Nivå 29: Elven Styx,Level 29: Styks,Fase 29: Rio Estige,Nível 29: Rio Estige,Nivelul 29: Râul Styx,Уровень №29: Река Стикс,Level 29: Река Стикс,Seviye 29: Styx Nehri -Level 30: Last Call,THUSTR_30,,,,Level 30: Poslední mise,Level 30: Sidste opkald,Level 30: Letzter Aufruf,,Nivelo 30: Fina Voko,Nivel 30: Última Llamada,,Taso 30: Viimeinen koollehuuto,NIVEAU 30: Dernier Appel,30. Pálya: Utolsó esély,Livello 30: Ultima Chiamata,Level 30: 最終指令,레벨 30: 최후의 호출,Level 30: Laatste oproep,Nivå 30: Siste innkalling,Level 30: Ostatni Zew,Fase 30: Última Chamada,Nível 30: Última Chamada,Nivelul 30: Ultimul apel,Уровень №30: Последний вызов,Level 30: Последњи позив,Seviye 30: Son Çağrı -Level 31: Pharaoh,THUSTR_31,,,,Level 31: Faraón,Level 31: Farao,Level 31: Pharao,,Nivelo 31: Faraono,Nivel 31: Faraón,,Taso 31: Faarao,NIVEAU 31: Pharaon,31. Pálya: Fáraó,Livello 31: Faraone,Level 31: ファラオ,레벨 31: 파라오,Level 31: Farao,Nivå 31: Farao,Level 31: Faraon,Fase 31: Faraó,Nível 31: Faraó,Nivelul 31: Faraon,Уровень №31: Фараон,Level 31: Фараон,Seviye 31: Firavun -Level 32: Caribbean,THUSTR_32,,,,Level 32: Karibik,Level 32: Caribien,Level 32: Karibik,,Nivelo 32: Karibio,Nivel 32: Caribeño,,Taso 32: Karibia,NIVEAU 32: Caraïbes,32. Pálya: Karib-térség,Livello 32: Caraibi,Level 32: カリビアン,레벨 32: 카리브해,Level 32: Caribisch,Nivå 32: Karibia,Level 32: Karaiby,Fase 32: Caribe,Nível 32: Caraíbas,Nivelul 32: Caraibe,Уровень №32: Карибы,Level 32: Кариби,Seviye 32: Karayipler -,,Heretic,,,,,,,,,,,,,,,,,,,,,,,, -The Docks,HHUSTR_E1M1,,,,Přístav,Havnene,Die Docks,,La Havenoj,Los Muelles,,Satamat,Les Docks,A Kikötő,Il Molo,埠頭,항구,De dokken,Havnen,Doki,As Docas,,Docul,Доки,Лука,Rıhtım -The Dungeons,HHUSTR_E1M2,,,,Žaláře,Fangehullerne,Die Kerker,,La Malliberejoj,Los Calabozos,,Tyrmät,Le Donjon,A Kazamaták,I Sotterranei,地下牢,지하감옥,De kerkers,Fangehullene,Lochy,As Masmorras,,Temnița,Темницы,Тамнице,Zindanlar -The Gatehouse,HHUSTR_E1M3,,,,Vrátnice,Portens hus,Das Pförtnerhaus,,La Pordegejo,El Cuerpo de Guardia,,Porttitalo,Le Corps de Garde,A Kapuház,L'ingresso,門塔,문루,Het poortgebouw,Porthuset,Stróżówka,O Portão de Entrada,,Casa portarului,Привратницкая,Стражарница,Kapı Evi -The Guard Tower,HHUSTR_E1M4,,,,Strážní věž,Vagttårnet,Der Wachturm,,La Gardturo,La Torre de Guardia,,Vartiotorni,La Tour de Garde,Az Őrtorony,La Torre di Guardia,監視塔,보초 누대,De wachttoren,Vakttårnet,Wieża Strażnicza,A Torre de Guarda,,Turnul de veghe,Сторожевая башня,Извидница,Muhafız Kulesi -The Citadel,HHUSTR_E1M5,,,,Citadela,Citadellet,Die Festung,,La Citadelo,La Ciudadela,,Linnake,La Citadelle,A Citadella,La Cittadella,要塞,거점,De citadel,Citadellet,Cytadela,A Cidadela,,Cetatea,Цитадель,Цитадела,Hisar -The Cathedral,HHUSTR_E1M6,,,,Katedrála,Katedralen,Die Kathedrale,,La Katedralo,La Catedral,,Katedraali,La Cathédrale,A Katedrális,La Cattedrale,大聖堂,대성당,De kathedraal,Katedralen,Katedra,A Catedral,,Catedrala,Кафедральный собор,Катедрала,Katedral -The Crypts,HHUSTR_E1M7,,,,Krypty,Krypterne,Die Krypten,,La Kriptoj,Las Criptas,,Kryptat,La Crypte,A Kripták,Le Cripte,地下聖堂,지하 묘실,De grafkelders,Kryptene,Krypty,As Criptas,,Criptele,Склепы,Крипта,Mahzenler -Hell's Maw,HHUSTR_E1M8,,,,Chřtán pekla,Helvedes gab,Der Höllenschlund,,Faŭko de Infero,Fauces del Infierno,,Helvetin kita,La Geule de l'Enfer,A Pokol Szája,La Bocca dell'Inferno,地獄の肚,지옥의 목구멍,De helmouth,Helvetes gap,Paszcza Piekieł,A Boca do Inferno,,Gura iadului,Адская утроба,Паклено ждрело,Cehennem Ağzı -The Graveyard,HHUSTR_E1M9,,,,Hřbitov,Kirkegården,Der Friedhof,,La Tombejo,El Cementerio,,Hautausmaa,Le Cimetière,A Temető,Il Cimitero,墓場,공동묘지,De begraafplaats,Kirkegården,Cmentarz,O Cemitério,,Cimitirul,Кладбище,Гробље,Mezarlık -The Crater,HHUSTR_E2M1,,,,Kráter,Krateret,Der Krater,,La Kratero,El Cráter,,Kraateri,Le Cratère,A Kráter,Il Cratere,噴火口,깊은 혈,De krater,Krateret,Krater,A Cratera,,Craterul,Кратер,Кратер,Krater -The Lava Pits,HHUSTR_E2M2,,,,Lávové jámy,Lavagruberne,Die Lavagruben,,La Lafo-Fosaĵo,Las Canteras de Lava,,Laavamontut,Les Puits de Lave,A Lávaárok,I Pozzi della Lava,溶岩の竪穴,용암 구덩이,De lavaputten,Lavagropene,Szyb Lawy,Os Fossos de Lava,,Gropile cu lavă,Лавовые очаги,Понор лаве,Lav Çukurları -The River of Fire,HHUSTR_E2M3,,,,Ohnivá řeka,Ildfloden,Der Feuerfluss,,La Rivero de Fajro,El Río de Fuego,,Tulijoki,La Rivière de Feu,A Tűzfolyó,Il Fiume di Fuoco,火の河,화염의 강,De rivier van vuur,Elven av ild,Rzeka Ognia,O Rio de Fogo,,Râul de foc,Река огня,Река од ватре,Ateş Nehri -The Ice Grotto,HHUSTR_E2M4,,,,Ledová grotta,Isgrotten,Die Eisgrotte,,La Glacigroto,La Gruta de Hielo,,Jääluola,La Grotte de Glace,A Jégbarlang,La Grotta del Ghiaccio,氷の洞窟,얼음 동굴,De ijsgrot,Isgrotten,Lodowa Grota,A Gruta de Gelo,,Grota de gheață,Ледяной грот,Ледена пећина,Buz Mağarası -The Catacombs,HHUSTR_E2M5,,,,Katakomby,Katakomberne,Die Katakomben,,La Katakomboj,Las Catacumbas,,Katakombit,Les Catacombes,A Katakombák,Le Catacombe,地下墓所,태고의 무덤,De catacomben,Katakombene,Katakumby,As Catacumbas,Os Túmulos,Catacombele,Катакомбы,Катакомбе,Yeraltı Mezarları -The Labyrinth,HHUSTR_E2M6,,,,Labyrint,Labyrinten,Das Labyrinth,,La Labirinto,El Laberinto,,Labyrintti,Le Labyrinthe,A Labirintus,Il Labirinto,迷宮,미궁,Het labyrint,Labyrinten,Labirynt,O Labirinto,,Labirintul,Лабиринт,Лавиринт,Labirent -The Great Hall,HHUSTR_E2M7,,,,Velký sál,Den store sal,Die große Halle,,La Granda Halo,El Gran Salón,,Suuri halli,Le Grand Hall,A Nagy Folyosó,La Grande Sala,大公会堂,대회관,De grote zaal,Den store salen,Wielki Hol,O Grande Salão,,Sala cea mare,Большой зал,Велика дворана,Büyük Salon -The Portals of Chaos,HHUSTR_E2M8,,,,Portály chaosu,Kaosets portaler,Das Portal des Chaos,,La Portaloj de Ĥaoso,Los Portales del Caos,,Kaaoksen portaalit,Le Portail du Chaos,A Káosz Portáljai,I Portali del Caos,混沌への門,혼돈의 차원문,De portalen van chaos,Kaosets portaler,Portale Chaosu,Os Portais do Caos,,Portalurile haosului,Порталы хаоса,Портали хаоса,Kaos Kapıları -The Glacier,HHUSTR_E2M9,,,,Ledovec,Gletsjeren,Der Gletscher,,La Glaciejo,El Glaciar,,Jäätikkö,Le Glacier,A Gleccser,Il Ghiacciaio,氷河,빙하 구역,De gletsjer,Isbreen,Lodowiec,A Geleira,O Glaciar,Ghețarul,Ледник,Глечер,Buzul -The Storehouse,HHUSTR_E3M1,,,,Skladiště,Magasinet,Die Lagerhalle,,La Stokejo,El Almacén,,Varasto,L'Entrepôt,A Raktár,Il Magazzino,倉庫,저장고,Het pakhuis,Forrådshuset,Magazyn,O Armazém,,Depozitul,Кладовая,Складиште,Depo -The Cesspool,HHUSTR_E3M2,,,,Žumpa,Kedelbassinet,Die Latrine,,La Kloako,El Pozo,,Likakaivo,Le Bourbier,A Pöcegödör,Il Pozzo Nero,汚水層,불결한 장소,De zinkput,Søledammen,Szambo,A Fossa,,Haznaua,Сточный колодец,Септичка јама,Lağım Çukuru -The Confluence,HHUSTR_E3M3,,,,Soutok,Sammenløbet,Die Vereinigung,,La Kunfluiĝo,La Confluencia,,Yhtymäkohta,La Confluence,A Kereszteződés,La Confluenza,合流点,합류점,De samenvloeiing,Sammenløpet,Spływ,A Confluência,,Confluența,Слияние,Ушће,Confluence -The Azure Fortress,HHUSTR_E3M4,,,,Azurová pevnost,Den azurblå fæstning,Die himmelblaue Festung,,La Lazurfortikaĵo,La Fortaleza de Azur,,Sininen linnoitus,La Fortresse d'Azur,Az Azúr Erőd,La Fortezza Azzurra,紺碧の要塞,청천의 요새,De azuurblauwe vesting,Den azurblå festningen,Lazurowa Forteca,A Fortaleza Azul,,Fortăreața de azur,Лазурная крепость,Азурна дврђава,Azure Kalesi -The Ophidian Lair,HHUSTR_E3M5,,,,Hadí doupě,Ophidian Hulen,Das Schlangennest,,La Nestego de Ofidia,La Guarida Ofídica,,Käärmeiden pesä,Le Repaire des Ophidiens,Az Opfidiánok Fészke,L'antro degli Ophidian,オフィディアンの塒,오피디안의 소굴,Het slangennest,Ophidian-hulen,Gniazdo Węży,A Cova dos Ofídios,,Cuibul ofidienilor,Логово офидианов,Змијска јазбина,Ophidian İni -The Halls of Fear,HHUSTR_E3M6,,,,Chodby strachu,Frygtens haller,Die Hallen der Angst,,La Koridoroj de Timo,Los Salones del Miedo,,Pelon salit,Les Couloirs de la Peur,A Félelem Folyosói,Le Sale della Paura,恐怖の館,공포의 회관,De zalen van angst,Fryktens haller,Korytarze Strachu,Os Salões do Medo,,Sălile groazei,Залы страха,Дворана страха,Korku Salonları -The Chasm,HHUSTR_E3M7,,,,Propast,Kløften,Der Abgrund,,La Fendego,El Abismo,,Rotko,Le Gouffre,A Szakadék,L'abisso,裂け目,깊은 골,De kloof,Kløften,Przepaść,O Abismo,,Prăpastia,Пропасть,Понор лаве,Uçurum -D'Sparil's Keep,HHUSTR_E3M8,,,,D'Sparilova pevnost,D'Sparils borg,D'Sparils Außenposten,,Ĉefturo de Desparilo,Guarida de D'Sparil,,D'Sparilin linna,Le Donjon de D'Sparil,D'Sparil Terme,La Dimora di D'Sparil,デ’スパリルの間,드'스파릴의 초소,D'Sparil's voorpost,D'Sparils borg,Baszta D'Sparila,Fortaleza de D'Sparil,,Palatul lui D'sparil,Крепость Д'Спарила,Д'Спарилова кула,D'Sparil'in Kalesi -The Aquifer,HHUSTR_E3M9,,,,Zvodeň,Akvifer,Der Wasserspeicher,,La Akvigilo,El Acuífero,,Akviferi,L'Aquifère,A Víztorony,L'acquedotto,帯水層,대수층,Het water reservoir,Akviferen,Wodociąg,O Aquífero,,Galerii acvifere,Водоносный слой,Водоносник,Akifer -Catafalque,HHUSTR_E4M1,,,,Katafalk,Katafalken,Katafalk,,Katafalko,Catafalco,,Katafalkki,Le Catafalque,Ravatal,Catafalco,棺台,관대,Catafalk,Katafalken,Katafalk,Catafalco,,Catafalc,Катафалк,Одар,Katafalk -Blockhouse,HHUSTR_E4M2,,,,Tvrzka,Blokhuset,Blockhaus,,Blokhaŭso,Fortín,,Linnoitus,Le Fortin,Gerendaház,Blocco di Case,丸太小屋,특화점,Blokhuis,Blokkhuset,Blokhauz,O Forte,,Fort,Блокгауз,Бункер,Blok ev -Ambulatory,HHUSTR_E4M3,,,,Ochoz,Ambulatory,Wandelgang,,Ĥorĉirkaŭirejo,Ambulatorio,,Kuorikäytävä,Le Déambulatoire,Kerengő,Ambulatorio,遊歩道,유보장,Kloostergang,Gangen,Krużganek,Ambulatório,,Clinică,Амбулатория,Амбуланта,Ambulatuvar -Sepulcher,HHUSTR_E4M4,,,,Hrobka,Graven,Grabstätte,,Tombo,Sepulcro,,Hautakammio,Le Sépulcre,Síremlék,Sepolcro,埋葬所,매장소,Grafsteen,Graven,Grób,Sepulcro,,Sepulcru,Гробница,Гробница,Mezar -Great Stair,HHUSTR_E4M5,,,,Velké schody,Den store trappe,Große Treppe,,Granda Ŝtuparo,Gran Escalera,,Suuret portaat,Le Grand Escalier,Nagy Lépcső,Grande Scala,大階段,특급 계단,Grote trap,Den store trappen,Wielka Gwiazda,Grande Escada,,Scara cea mare,Великая лестница,Велики степеник,Büyük Merdiven -Halls of the Apostate,HHUSTR_E4M6,,,,Chodby odpadlictví,Apostaternes haller,Halle des Abtrünnigen,,Haloj de la Apostato,Salas de los Apóstatas,,Luopioiden salit,Les Halls de l'Apôtre,A Hitehagyott Csarnoka,Sale dell'Apostata,背教者の館,배교자의 회관,Zalen van de afvallige,De frafalnes haller,Korytarze Odszczepieńca,Os Salões dos Apóstatas,,Sălile apostatului,Залы отступников,Дворана апостола,Mürted Salonları -Ramparts of Perdition,HHUSTR_E4M7,,,,Náspy zatracení,Fortabelsens ramper,Wälle der Verdammnis,,Muregoj de Pereo,Murallas de la Perdición,,Kadotuksen vallit,Les Remparts de la Perdition,A Kárhozat Támasza,Torrioni della Perdizione,破滅の塁壁,파멸의 성벽,Wallen van de verdoemenis,Fortapelsens voller,Wał Potępienia,Muralhas da Perdição,,Meterezele pierzaniei,Твердыни погибели,Бедем пропасти,Azap Surları -Shattered Bridge,HHUSTR_E4M8,,,,Rozbitý most,Den ødelagte bro,Zerstörte Brücke,,Frakasita Ponto,Puente Destrozado,,Särkynyt silta,Le Pont effondré,Az Összeomlott Híd,Ponte Distrutto,崩落の橋,붕괴된 다리,Verbrijzelde brug,Den knuste broen,Zniszczony Most,Ponte Despedaçada,,Podul dărâmat,Разрушенный мост,Поломљен мост,Parçalanmış Köprü -Mausoleum,HHUSTR_E4M9,,,,Mauzoleum,,,,Maŭzoleo,Mausoleo,,Mausoleumi,Le Mausolée,Mauzóleum,Mausoleo,霊廟,대영묘,,Mausoleet,Mauzoleum,Mausoléu,,Mausoleu,Мавзолей,Маузолеј,Anıt Mezar -Ochre Cliffs,HHUSTR_E5M1,,,,Okrové útesy,Okkerklipper,Ockerfarbene Klippen,,Klifoj de Okro,Acantilados Ocres,,Okrajyrkänteet,Les Falaises Ochre,Okker Szakadékok,Colline Ocra,黄土絶壁,황토 산맥,Okerkliffen,Oker-klippene,Ochrowe Klify,Penhascos Ocres,,Stâncile de ocru,Охровые утёсы,Окер брда,Ochre Kayalıkları -Rapids,HHUSTR_E5M2,,,,Peřeje,Rapider,Stromschnellen,,Rapidfluoj,Rápidos,,Koski,Les Rapides,Zuhatagok,Rapide,奔流,여울,Stroomversnellingen,Strykene,Katarakty,Corredeiras,,Ape repezi,Стремнина,Брзак,Akıntıları -Quay,HHUSTR_E5M3,,,,Nábřeží,Kaj,Kai,,Kajo,Muelle,,Satamalaituri,Le Quai,Rakpart,Banchina,岸壁,부두,Kade,Kai,Wir,Cais,,Chei,Причал,Пристаниште,Rıhtım -Courtyard,HHUSTR_E5M4,,,,Nádvoří,Slotsgården,Schlosshof,,Korto,Patio,,Linnanpiha,La Cour,Pitvar,Cortile,中庭,안마당,Binnenplaats,Gårdsplass,Dziedziniec,Pátio,,Curte,Внутренний двор,Двориште,Avlu -Hydratyr,HHUSTR_E5M5,,,,Hydratýr,,,,Akvotjr,Hydratyr,,,L'Hydratyr,Hidratáló,Hydratyr,ヒュドラテュール,식수공급처,,,Hydratyr,Reservatório,,Hidratir,Гидротир,Канализација,Hydratyr -Colonnade,HHUSTR_E5M6,,,,Kolonáda,Kolonnader,Kolonnaden,,Kolonaro,Columnata,,Pylväikkö,La Colonnade,Kolonnád,Colonnato,柱廊,열주의 길,Zuilengalerij,Kolonnade,Kolumnada,Colunata,,Colonadă,Колоннада,Колонада,Kolonat -Foetid Manse,HHUSTR_E5M7,,,,Smrdutá vila,Stinkende præstegård,Stinkendes Pfarrhaus,,Haladza Domego,Mansión Fétida,,Löyhkäävä kartano,Le Presbytère Fétide,Bűzös Parókia,Fetido Castello,悪臭の牧師館,역겨운 목사관,Stinkende pastorie,Stinkende prestegård,Cuchnąca Plebania,Mansão Fétida,,Conac Fetid,Зловонный особняк,Фетидна кућа,Foetid Manse -Field of Judgement,HHUSTR_E5M8,,,,Soudná pole,Dommervældet,Richtstätte,,Kampo de Juĝo,Campo de Juicio,,Tuomion kenttä,Les Champs du Jugement,Az Itélet Mezeje,Campo del Giudizio,審判之地,심판의 평야,Plaats van oordeelsvorming,Dømmekraftsområde,Pole Sądu,Campo de Julgamento,,Câmpul de Judecată,Поле высшего суда,Чистилиште,Yargı Alanı -Skein of D'sparil,HHUSTR_E5M9,,,,Hejno D'Sparilovo,D'sparils skein,DSparils Bau,,Fadenaro de D'Sparil,Madeja de D'Sparil,,D'Sparilin vyyhti,L'échevaux de D'Sparil,D'Sparil Káosza,Groviglio di D'Sparil,デ'スパリルの枷,드'스파릴의 타래,D'Sparil's gebouw,Garn av D'sparil,Motek D'Sparila,Meada de D'Sparil,,Jurubița lui D'Sparil,Путаница Д'Спарила,Реке Д'Спарила,D'sparil Çileği -,,Strife,,,,,,,,,,,,,,,,,,,,,,,, -AREA 1: Sanctuary,TXT_STRIFE_MAP01,,,,ZÓNA 1: Svatyně,AREA 1: Fristedet,ZONE 1: Heiligtum,,AREO 1: Sanktejo,ÁREA 1: Santuario,,ALUE 1: Pyhäkkö,ZONE 1: Sanctuaire,1. Terület: Szentély,AREA 1: Santuario,エリア 1: 聖域,구역 1: 성소,Zone 1: Heiligdom,OMRÅDE 1: Helligdom,Strefa 1: Sanktuarium,Área 1: Santuário,,ZONA 1: Sanctuar,МЕСТНОСТЬ 1: Святилище,,ALAN 1: Sığınak +Circle of Death ",,,Level 11: Kruh smrti,Level 11: Ødelæggelsens cirkel!,Level 11: 'O' der Zerstörung!,Επίπεδο 11: Ο Κύκλος της Καταστροφής,Nivelo 11: Morta cirklo,Nivel 11: Círculo de la muerte,,Taso 11: Hävityksen 'O',NIVEAU 11: Le Cercle de la Mort!,11. Pálya: A pusztulás köre,Livello 11: Il Cerchio della Morte,Level 11: 破滅の'O'!,레벨 11: 파괴의 고리,Level 11: 'O' van vernietiging!,Nivå 11: Ødeleggelsens 'O'!,Level 11: Krąg Śmierci,Fase 11: Círculo da Morte,Nível 11: Círculo da Morte,Nivelul 11: Cercul distrugerii,Уровень №11: Круг разрушения!,Level 11: Круг уништења,"Nivå 11: ""O"" av förstörelse!",Seviye 11: Yıkımın 'O'su! +Level 12: The Factory,HUSTR_12,,,,Level 12: Továrna,Level 12: Fabrikken,Level 12: Die Fabrik,Επίπεδο 12: To Εργοστάσιο,Nivelo 12: La fabriko,Nivel 12: La fábrica,,Taso 12: Tehdas,NIVEAU 12: L'Usine,12. Pálya: A gyár,Livello 12: La Fabbrica,Level 12: 工場,레벨 12: 공장,Level 12: De fabriek,Nivå 12: Fabrikken,Level 12: Fabryka,Fase 12: A Fábrica,Nível 12: A Fábrica,Nivelul 12: Fabrica,Уровень №12: Фабрика,Level 12: Фабрика,Nivå 12: Fabriken,Seviye 12: Fabrika +Level 13: Downtown,HUSTR_13,,,,Level 13: Centrum,Level 13: Centrum,Level 13: Stadtzentrum,Επίπεδο 13: Κέντρο,Nivelo 13: Urbocentro,Nivel 13: Centro de la ciudad,,Taso 13: Keskikaupunki,NIVEAU 13: Centre-Ville,13. Pálya: Belváros,Livello 13: Periferia,Level 13: 市内,레벨 13: 번화가,Level 13: De binnenstad,Nivå 13: Sentrum,Level 13: Śródmieście,Fase 13: Centro Urbano,Nível 13: Centro Urbano,Nivelul 13: Centru urban,Уровень №13: Центр города,Level 13: Центар града,Nivå 13: Centrum,Seviye 13: Şehir Merkezi +Level 14: The Inmost Dens,HUSTR_14,,,,Level 14: Nejhlubší doupata,Level 14: Den inderste hule,Level 14: Die innersten Bauten,Επίπεδο 14: Οι Ενδότερες Φωλιές,Nivelo 14: La Internaj Kavernoj,Nivel 14: Los Antros más Recónditos,,Taso 14: Sisimmät piilot,NIVEAU 14: Les Antres Profondes,14. Pálya: A legmélyebb rejtekek,Livello 14: Gli Antri Profondi,Level 14: 最深巣窟,레벨 14: 깊숙한 동굴들,Level 14: De binnenste gebouwen,Nivå 14: De innerste huler,Level 14: Najgłębsze Nory,Fase 14: Os Antros Profundos,Nível 14: Os Antros Profundos,Nivelul 14: Cele mai intime bârloguri,Уровень №14: Глубочайшие логовища,Level 14: Најдубље јазбине,Nivå 14: Den innersta täkten,Seviye 14: En İçteki İnler +Level 15: Industrial Zone,HUSTR_15,,,,Level 15: Průmyslová zóna,Level 15: Industriområde,Level 15: Industriegebiet,Επίπεδο 15: Βιομηχανική Ζώνη,Nivelo 15: Industria Zono,Nivel 15: Zona Industrial,,Taso 15: Teollisuusalue,NIVEAU 15: Zone Industrielle,15. Pálya: Ipari zóna,Livello 15: Zona Industriale,Level 15: 工業地帯,레벨 15: 공업 지대,Level 15: Industriegebied,Nivå 15: Industriområdet,Level 15: Strefa Przemysłowa,Fase 15: Zona Industrial,Nível 15: Zona Industrial,Nivelul 15: Zona industrială,Уровень №15: Промышленный район,Level 15: Индустријска зона,Nivå 15: Industriområde,Seviye 15: Sanayi Bölgesi +Level 16: Suburbs,HUSTR_16,,,,Level 16: Předměstí,Level 16: Forstæderne,Level 16: Vororte,Επίπεδο 16: Προάστια,Nivelo 16: Antaŭurboj,Nivel 16: Suburbios,,Taso 16: Lähiö,NIVEAU 16: Banlieue,16. Pálya: Külváros,Livello 16: Sobborghi,Level 16: 郊外,레벨 16: 교외,Level 16: Buitenwijken,Nivå 16: Forstedene,Level 16: Przedmieścia,Fase 16: Subúrbios,Nível 16: Subúrbios,Nivelul 16: Suburbi,Уровень №16: Пригород,Level 16: Предграђе,Nivå 16: Förorter,Seviye 16: Banliyöler +Level 17: Tenements,HUSTR_17,,,,Level 17: Sídliště,Level 17: Lejligheder,Level 17: Wohnbezirk,Επίπεδο 17: Καταλύματα,Nivelo 17: Loĝejoj,Nivel 17: Viviendas,,Taso 17: Vuokratalot,NIVEAU 17: Immeubles,17. Pálya: Bérházak,Livello 17: Possedimenti,Level 17: 安アパート,레벨 17: 공동주택,Level 17: Huurwoningen,Nivå 17: Leiegårder,Level 17: Kamienice,Fase 17: Habitações,Nível 17: Habitações,Nivelul 17: Proprietăți,Уровень №17: Владения,Level 17: Станови,Nivå 17: Hyreshus,Seviye 17: Kiralık Evler +Level 18: The Courtyard,HUSTR_18,,,,Level 18: Nádvoří,Level 18: Gårdspladsen,Level 18: Der Innenhof,Επίπεδο 18: Η Αυλή,Nivelo 18: La Korto,Nivel 18: El Patio,,Taso 18: Esipiha,NIVEAU 18: La Cour,18. Pálya: Az udvar,Livello 18: Il Cortile,Level 18: 中庭,레벨 18: 중정,Level 18: De binnenplaats,Nivå 18: Gårdsplassen,Level 18: Dziedziniec,Fase 18: O Átrio,Nível 18: O Átrio,Nivelul 18: Curtea,Уровень №18: Внутренний двор,Level 18: Двориште,Nivå 18: Gården,Seviye 18: Avlu +Level 19: The Citadel,HUSTR_19,,,,Level 19: Citadela,Level 19: Citadellet,Level 19: Die Zizadelle,Επίπεδο 19: Το Κάστρο,Nivelo 19: La Citadelo,Nivel 19: La Ciudadela,,Taso 19: Linnoitus,NIVEAU 19: La Citadelle,19. Pálya: Fellegvár,Livello 19: La Cittadella,Level 19: 要塞,레벨 19: 성채,Level 19: De citadel,Nivå 19: Citadellet,Level 19: Cytadela,Fase 19: A Cidadela,Nível 19: A Cidadela,Nivelul 19: Cetatea,Уровень №19: Цитадель,Level 19: Цитадела,Nivå 19: Citadellet,Seviye 19: Hisar +Level 20: Gotcha!,HUSTR_20,,,,Level 20: Mám tě!,,Level 20: Erwischt!,Επίπεδο 20: Σ'έπιασα!,Nivelo 20: Kaptis Vin!,Nivel 20: ¡Te pillé!,Nivel 20: ¡Te tengo!,Taso 20: Sainpas sinut!,NIVEAU 20: Je t'ai eu!,20. Pálya: Megvagy!,Livello 20: Preso!,Level 20: 捉らえた!,레벨 20: 잡았다!,Level 20: Ik heb je!,Nivå 20: Fikk deg!,Level 20: Mam Cię!,Fase 20: Te Peguei!,Nível 20: Apanhei-te!,Nivelul 20: Te-am prins!,Уровень №20: Попался!,Level 20: Имају те!,Nivå 20: Gotcha!,Seviye 20: Yakaladım! +Level 21: Nirvana,HUSTR_21,,,,Level 21: Nirvána,,,Επίπεδο 21: Νιρβάνα,Nivelo 21: Nirvano,Nivel 21: Nirvana,,,NIVEAU 21: Nirvana,21. Pálya: Nirvána,Livello 21: Nirvana,Level 21: 涅槃,레벨 21: 열반,,,,Fase 21: Nirvana,Nível 21: Nirvana,Nivelul 21: Nirvana,Уровень №21: Нирвана,Level 21: Нирвана,Nivå 21: Nirvana,Seviye 21: Nirvana +Level 22: The Catacombs,HUSTR_22,,,,Level 22: Katakomby,Level 22: Katakomberne,Level 22: Katakomben,Επίπεδο 22: Οι Κατακόμβες,Nivelo 22: La Katakombo,Nivel 22: Las Catacumbas,,Taso 22: Katakombit,NIVEAU 22: Les Catacombes,22. Pálya: A katakombák,Livello 22: Le Catacombe,Level 22: 地下悪霊墓所,레벨 22: 지하 묘지,Level 22: De catacomben,Nivå 22: Katakombene,Level 22: Katakumby,Fase 22: As Catacumbas,Nível 22: Os Calabouços,Nivelul 22: Catacombe,Уровень №22: Катакомбы,Level 22: Катакомбе,Nivå 22: Katakomberna,Seviye 22: Yeraltı Mezarları +Level 23: Barrels O' Fun,HUSTR_23,,,,Level 23: Barely srandy,Level 23: Tønder af sjov,Level 23: Lustige Fässer,,Nivelo 23: Bareloj de Amuzo,Nivel 23: Barriles de Diversión,,Taso 23: Huvitynnyrit,NIVEAU 23: Une Tonne-eau de plaisir,23. Pálya: Mókás hordók,Livello 23: Barili da Sballo,Level 23: 戯れのバレル,레벨 23: 신나는 폭발통들,Level 23: Grappige vaten,Nivå 23: Tønner med moro,Level 23: Beczki Śmiechu,Fase 23: Barris de Diversão,Nível 23: Barris de Diversão,Nivelul 23: Butoaiele veseliei,Уровень №23: Бочки веселья,Level 23: Бачве забаве,Nivå 23: Tunnor med kul,Seviye 23: Eğlence Fıçıları +Level 24: The Chasm,HUSTR_24,,,,Level 24: Rokle,Level 24: Kløften,Level 24: Die Kluft,Επίπεδο 24: Το Χάσμα,Nivelo 24: La Fendego,Nivel 24: El Desfiladero,,Taso 24: Rotko,NIVEAU 24: Le Gouffre,24. Pálya: A szakadék,Livello 24: L'Abisso,Level 24: 裂け目,레벨 24: 협곡,Level 24: De afgrond,Nivå 24: Avgrunnen,Level 24: Przepaść,Fase 24: O Abismo,Nível 24: O Abismo,Nivelul 24: Hăul,Уровень №24: Пропасть,Level 24: Провалија,Nivå 24: Klyftan,Seviye 24: Uçurum +Level 25: Bloodfalls,HUSTR_25,,,,Level 25: Krvopády,Level 25: Blodfald,Level 25: Blutfälle,Επίπεδο 25: Καταρράκτες Αίματος,Nivelo 25: Sangfaloj,Nivel 25: Cataratas de Sangre,,Taso 25: Veriputoukset,NIVEAU 25: Chutes de Sang,25. Pálya: Véresések,Livello 25: Cascate di Sangue,Level 25: 血の滝,레벨 25: 혈폭포,Level 25: Bloeddruppels,Nivå 25: Blodfall,Level 25: Wodospad Krwi,Fase 25: Cataratas de Sangue,Nível 25: Cascatas de Sangue,Nivelul 25: Cascade de sânge,Уровень №25: Кровопады,Level 25: Крвопади,Nivå 25: Blodfall,Seviye 25: Kan Düşüşleri +Level 26: The Abandoned Mines,HUSTR_26,,,,Level 26: Opuštěné doly,Level 26: De forladte miner,Level 26: Die aufgegebene Mine,Επίπεδο 26: Τα Εγκαταλελειμμένα Ορυχεία,Nivelo 26: La Forlasitaj Minoj,Nivel 26: Las Minas Abandonadas,,Taso 26: Hylätyt kaivokset,NIVEAU 26: Les Mines Abandonnées,26. Pálya: Az elhagyatott bányák,Livello 26: Le Miniere Abbandonate,Level 26: 廃鉱山,레벨 26: 버려진 광산,Level 26: De verlaten mijnen,Nivå 26: De forlatte gruvene,Level 26: Opuszczone Kopalnie,Fase 26: As Minas Abandonadas,Nível 26: As Minas Abandonadas,Nivelul 26: Minele părăsite,Уровень №26: Заброшенные шахты,Level 26: Напуштени рудници,Nivå 26: De övergivna gruvorna,Seviye 26: Terk Edilmiş Madenler +Level 27: Monster Condo,HUSTR_27,,,,Level 27: Netvoří dům,,Level 27: Monsterbehausung,,Nivelo 27: Monstro-Domo,Nivel 27: Condominio de Monstruos,,Taso 27: Hirviöasuntola,NIVEAU 27: Monstrueuse Résidence,27. Pálya: A szörnyek háza,Livello 27: Casa dei Mostri,Level 27: モンスターマンション,레벨 27: 괴물 콘도,,Nivå 27: Monsterleiligheten,Level 27: Apartament Potworów,Fase 27: Mansão dos Monstros,Nível 27: Condomínio Monstruoso,Nivelul 27: Casa monștrilor,Уровень №27: Жилище монстров,Level 27: Боравишта монструма,Nivå 27: Monster Condo,Seviye 27: Canavar Dairesi +Level 28: The Spirit World,HUSTR_28,,,,Level 28: Onen svět,Level 28: Åndeverdenen,Level 28: Die Geisterwelt,Επίπεδο 28: Ο Κόσμος των Πνευμάτων,Nivelo 28: La Animo-Mondo,Nivel 28: El Mundo Espiritual,,Taso 28: Henkimaailma,NIVEAU 28: Le Monde Spirituel,28. Pálya: A lelkek világa,Livello 28: Il Mondo dello Spirito,Level 28: 悪霊の世界,레벨 28: 영령의 세계,Level 28: De geestenwereld,Nivå 28: Åndeverdenen,Level 28: Świat Dusz,Fase 28: O Mundo Espiritual,Nível 28: O Mundo Espiritual,Nivelul 28: Lumea duhurilor,Уровень №28: Мир духов,Level 28: Духовни свет,Nivå 28: Den andliga världen,Seviye 28: Ruhlar Dünyası +Level 29: The Living End,HUSTR_29,,,,Level 29: Živoucí konec,Level 29: Den levende ende,Level 29: Das lebende Ende,Επίπεδο 29: Το Ζωντανό Τέλος,Nivelo 29: La Viva Fino,Nivel 29: El Final Viviente,,Taso 29: Elävä loppu,NIVEAU 29: La Limite,29. Pálya: Az élő Végzet,Livello 29: La Fine Imminente,Level 29: 極限の存在,레벨 29: 최종점,Level 29: Het levende einde,Nivå 29: Den levende enden,Level 29: Żywy Koniec,Fase 29: O Cúmulo da Existência,Nível 29: O Cúmulo da Existência,Nivelul 29: Sfârșitul întregii vieți,Уровень №29: Конец всего живого,Level 29: Крај живота,Nivå 29: Det levande slutet,Seviye 29: Yaşamın Sonu +Level 30: Icon of Sin,HUSTR_30,,,,Level 30: Ikona hříchu,Level 30: Syndens ikon,Level 30: Symbol der Sünde,Επίπεδο 30: Σύμβολο της Αμαρτίας,Nivelo 30: Ikono de Peko,Nivel 30: Icono del pecado,Nivel 30: Ícono del pecado,Taso 30: Synnin ikoni,NIVEAU 30: L'Icône du Péché,30. Pálya: A megtestesült bűn,Livello 30: Icona del Peccato,Level 30: 罪の聖像,레벨 30: 죄악의 상징,Level 30: Pictogram van de zonde,Nivå 30: Syndens ikon,Level 30: Ikona Grzechu,Fase 30: Ícone do Pecado,Nível 30: Ícone do Pecado,Nivelul 30: Icoana păcatelor,Уровень №30: Икона греха,Level 30: Икона греха,Nivå 30: Syndens ikon,Seviye 30: Günah Simgesi +Level 31: Wolfenstein,HUSTR_31,,,,,,,,Nivelo 31: Wolfenstein,Nivel 31: Wolfenstein,,,,31. Pálya: Wolfenstein,Livello 31: Wolfenstein,Level 31: ウルフェンシュタイン,레벨 31: 울펜슈타인,,,,Fase 31: Wolfenstein,Nível 31: Wolfenstein,Nivelul 31: Wolfenstein,Уровень №31: Вольфенштайн,Level 31: Волфенштајн,Nivå 31: Wolfenstein,Seviye 31: Wolfenstein +Level 32: Grosse,HUSTR_32,,,,,,,,Nivelo 32: Grosse,Nivel 32: Grosse,,,,32. Pálya: Grosse,Livello 32: Grosse,Level 32: グローシュ,레벨 32: 그로세,,,,Fase 32: Grosse,Nível 32: Grosse,Nivelul 32: Grosse,Уровень №32: Гросс,Level 32: Гроссе,Nivå 32: Grosse,Seviye 32: Grosse +Level 31: IDKFA,HUSTR_31B,,,,,,,,Nivelo 31: IDKFA,Nivel 31: IDKFA,,,NIVEAU 31: IDKFQ,31. Pálya: IDKFA,Livello 31: IDKFA,Level 31: IDKFA,레벨 31: IDKFA,,,,Fase 31: IDKFA,Nível 31: IDKFA,Nivelul 31: IDKFA,Уровень №31: IDKFA,,Nivå 31: IDKFA,Seviye 31: IDKFA +Level 32: Keen,HUSTR_32B,,,,,,,,Nivelo 32: Keen,Nivel 32: Keen,,,,32. Pálya: Keen,Livello 32: Keen,Level 32: キーン,레벨 32: 킨,,,,Fase 32: Keen,Nível 32: Keen,Nivelul 32: Keen,Уровень №32: Кин,Level 32: Кин,Nivå 32: Keen,Seviye 32: Keen +Level 33: Betray,HUSTR_33,,,,Level 33: Zraď,Level 33: Forræderi,Level 33: Verrat,,Nivelo 33: Perfido,Nivel 33: Traición,,Taso 33: Petä,NIVEAU 33: Trahison,33. Pálya: Árulás,Livello 33: Tradimento ,Level 33: 裏切り,레벨 33: 배반,Level 33: Verraad,Nivå 33: Forråde,Level 33: Zdrada,Fase 33: Traição,Nível 33: Traição,Nivelul 33: Trădare,Уровень №33: Предай,Level 33: Издаја,Nivå 33: Förråda,Seviye 33: İhanet +,,No Rest For The Living,,,,,,,,,,,,,,,,,,,,,,,,, +Level 1: The Earth Base,NHUSTR_1,,,,Level 1: Pozemská základna,Level 1: Jordbasen,Level 1: Die Erd-Basis,,Nivelo 1: La Tera Bazo,Nivel 1: La Base Terrestre,,Taso 1: Maatukikohta,NIVEAU 1: La Base Terrienne,1. Pálya: A földi bázis,Livello 1: La Base Terrestre ,Level 1: 地球基地,레벨 1: 지구 기지,Level 1: De basis van de aarde,Nivå 1: Jordbasen,Level 1: Ziemska Baza,Fase 1: A Base Terrestre,Nível 1: A Base Terrestre,Nivelul 1: Baza terestră,Уровень №1: База на Земле,Level 1: Земаљска база,Nivå 1: Jordbasen,Seviye 1: Dünya Üssü +Level 2: The Pain Labs,NHUSTR_2,,,,Level 2: Laboratoře bolesti,Level 2: Smerte laboratorier,Level 2: Die Folterlabore,,Nivelo 2: La Doloro-Laboratorio,Nivel 2: Los Laboratorios del Dolor,,Taso 2: Tuskalaboratoriot,NIVEAU 2: Les Laboratoires de la Douleur,2. Pálya: A kínok laboratóriuma,Livello 2: I Laboratori del Dolore,Level 2: 生物工学実験室,레벨 2: 고통의 연구소,Level 2: De pijnlaboratoria,Nivå 2: Smertelaboratoriet,Level 2: Laboratoria Bólu,Fase 2: Os Laboratórios da Dor,Nível 2: Os Laboratórios da Dor,Nivelul 2: Laboratoarele durerii,Уровень №2: Лаборатории боли,Level 2: Лабораторије патње,Nivå 2: Smärtlaboratorierna,Seviye 2: Ağrı Laboratuvarları +Level 3: Canyon of The Dead,NHUSTR_3,,,,Level 3: Kaňon mrtvých,Level 3: De dødes kløft,Level 3: Schlucht der Toten,,Nivelo 3: Kanjono de La Mortintoj,Nivel 3: Cañón de los Muertos,,Taso 3: Kalmankanjoni,NIVEAU 3: Canyon des Morts,3. Pálya: A holtak szurdoka,Livello 3: Il Canyon dei Morti,Level 3: 死の渓谷,레벨 3: 죽음의 계곡,Level 3: Canyon van de doden,Nivå 3: De dødes kløft,Level 3: Kanion Umarłych,Fase 3: Desfiladeiro dos Mortos,Nível 3: Desfiladeiro dos Mortos,Nivelul 3: Canionul morților,Уровень №3: Каньон мертвецов,Level 3: Кањон мртваца,Nivå 3: De dödas kanjon,Seviye 3: Ölüler Kanyonu +Level 4: Hell Mountain,NHUSTR_4,,,,Level 4: Pekelná hora,Level 4: Helvede bjerg,Level 4: Höllenberg,,Nivelo 4: Monto de Infero,Nivel 4: Montaña Infernal,,Taso 4: Hornanvuori,NIVEAU 4: Montagne Infernale,4. Pálya: Pokol-hegy,Livello 4: Montagna Infernale ,Level 4: 地獄山脈,레벨 4: 지옥의 산,Level 4: Helleberg,Nivå 4: Helvetesfjellet,Level 4: Piekielna Góra,Fase 4: Montanha Infernal,Nível 4: Montanha Infernal,Nivelul 4: Muntele infernal,Уровень №4: Адская гора,Level 4: Планина пакла,Nivå 4: Helvetesberget,Seviye 4: Cehennem Dağı +Level 5: Vivisection,NHUSTR_5,,,,Level 5: Vivisekce,Level 5: Vivisektion,Level 5: Vivisektion,,Nivelo 5: Vivisekcio,Nivel 5: Vivisección,,Taso 5: Vivisektio,NIVEAU 5: Vivisection,5. Pálya: Élveboncolás,Livello 5: Vivisezione ,Level 5: 生体解剖,레벨 5: 생체 해부,Level 5: Vivisectie,Nivå 5: Viviseksjon,Level 5: Wiwisekcja,Fase 5: Vivissecção,Nível 5: Vivissecção,Nivelul 5: Vivisecție,Уровень №5: Вивисекция,Level 5: Вивисекција,Nivå 5: Vivisektion,Seviye 5: Canlı Kesim +Level 6: Inferno of Blood,NHUSTR_6,,,,Level 6: Krvavé inferno,Level 6: Blodets inferno,Level 6: Blutiges Inferno,,Nivelo 6: Brulego de Sango,Nivel 6: Hoguera de Sangre,,Taso 6: Veri-inferno,NIVEAU 6: Enfer Sanglant,6. Pálya: Véres alvilág,Livello 6: Inferno di Sangue ,Level 6: 血のインフェルノ,레벨 6: 연옥의 피,Level 6: Bloederige inferno,Nivå 6: Blodets inferno,Level 6: Piekło Krwi,Fase 6: Inferno de Sangue,Nível 6: Inferno de Sangue,Nivelul 6: Infern sângeriu,Уровень №6: Кровавая преисподняя,Level 6: Ватре крви,Nivå 6: Blodets inferno,Seviye 6: Kan Cehennemi +Level 7: Baron's Banquet,NHUSTR_7,,,,Level 7: Baronova hostina,Level 7: Baron's Banquet,Level 7: Das Bankett des Barons,,Nivelo 7: Festeno de Barono,Nivel 7: Banquete del Barón,,Taso 7: Paronin pidot,NIVEAU 7: Banquet du Baron,7. Pálya: A báró bankettje,Livello 7: Il Banchetto del Barone ,Level 7: バロンの晩餐,레벨 7: 남작의 연회,Level 7: Baron's banket,Nivå 7: Baronens bankett,Level 7: Bankiet Barona,Fase 7: Banquete do Barão,Nível 7: Banquete do Barão,Nivelul 7: Banchetul baronilor,Уровень №7: Банкет у барона,Level 7: Баронова Гозба,Nivå 7: Baronens bankett,Seviye 7: Baron'un Ziyafeti +Level 8: Tomb of Malevolence,NHUSTR_8,,,,Level 8: Hrobka zlovolnosti,Level 8: Ondskabens grav,Level 8: Feindselige Gruft,,Nivelo 8: Tombo de Malbonvolo,Nivel 8: Tumba de Malevolencia,,Taso 8: Pahantahdon hauta,NIVEAU 8: Tombe Maléfique,8. Pálya: A Gátlástalanság sírja,Livello 8: Tomba della Malevolenza,Level 8: 悪意の墓,레벨 8: 증오의 무덤,Level 8: Graf van kwaadwilligheid,Nivå 8: Ondskapens grav,Level 8: Grobowiec Zła,Fase 8: Tumba da Malevolência,Nível 8: Túmulo da Malevolência,Nivelul 8: Mormântul răutății,Уровень №8: Гробница злобы,Level 8: Гроб злобе,Nivå 8: Ondskans grav,Seviye 8: Kötülük Mezarı +Level 9: March of The Demons,NHUSTR_9,,,,Level 9: Pochod démonů,Level 9: Dæmonernes march,Level 9: Marsch der Dämonen,,Nivelo 9: Marŝo de La Demonoj,Nivel 9: Marcha de los Demonios,,Taso 9: Demonien marssi,NIVEAU 9: Marche des Démons,9. Pálya: A démonok parádéja,Livello 9: La Marcia dei Demoni ,Level 9: デーモンの行進,레벨 9: 악마들의 행진,Level 9: Maart van de demonen,Nivå 9: Demonenes marsj,Level 9: Marsz Demonów,Fase 9: Marcha dos Demônios,Nível 9: Marcha dos Demônios,Nivelul 9: Marșul demonilor,Уровень №9: Шествие демонов,Level 9: Марш демона,Nivå 9: Demonernas marsch,Seviye 9: Şeytanların Yürüyüşü +,,Plutonia,,,,,,,,,,,,,,,,,,,,,,,,, +Level 1: Congo,PHUSTR_1,,,,Level 1: Kongo,,Level 1: Kongo,,Nivelo 1: Kongo,Nivel 1: Congo,,Taso 1: Kongo,NIVEAU 1: Congo,1. Pálya: Kongó,Livello 1: Congo,Level 1: コンゴ川,레벨 1: 콩고,Level 1: Kongo,Nivå 1: Kongo,Level 1: Kongo,Fase 1: Congo,Nível 1: Congo,Nivelul 1: Congo,Уровень №1: Конго,Level 1: Конго,Nivå 1: Kongo,Seviye 1: Kongo +Level 2: Well of Souls,PHUSTR_2,,,,Level 2: Studna duší,Level 2: Sjælebrønden,Level 2: Seelenbrunnen,,Nivelo 2: Puto de animoj,Nivel 2: Pozo de almas,,Taso 2: Sielujen lähde,NIVEAU 2: Puits des Ames,2. Pálya: A lelkek kútja,Livello 2: Pozzo delle Anime,Level 2: 魂の井戸,레벨 2: 영혼의 우물,Level 2: Bron van zielen,Nivå 2: Sjelenes brønn,Level 2: Studnia Dusz,Fase 2: Poço das Almas,Nível 2: Poço de Almas,Nivelul 2: Fântâna sufletelor,Уровень №2: Колодец душ,Level 2: Бунар душа,Nivå 2: Själarnas brunn,Seviye 2: Ruhlar Kuyusu +Level 3: Aztec,PHUSTR_3,,,,Level 3: Azték,Level 3: Azteker,Level 3: Aztekisch,,Nivelo 3: Azteko,Nivel 3: Azteca,,Taso 3: Asteekki,NIVEAU 3: Aztèque,3. Pálya: Azték,Livello 3: Aztec,Level 3: アステカ,레벨 3: 아즈텍,Level 3: Azteken,Nivå 3: Aztekisk,Level 3: Aztek,Fase 3: Asteca,Nível 3: Asteca,Nivelul 3: Aztec,Уровень №3: Ацтек,Level 3: Астек,Nivå 3: Azteker,Seviye 3: Aztek +Level 4: Caged,PHUSTR_4,,,,Level 4: V kleci,Level 4: Låst op,Level 4: Eingesperrt,,Nivelo 4: Enkaĝigita,Nivel 4: Enjaulado,,Taso 4: Häkissä,NIVEAU 4: Enfermé,4. Pálya: Ketrecbe zárva,Livello 4: Ingabbiato,Level 4: 檻の中,레벨 4: 갇히다,Level 4: Gekooid,Nivå 4: Buret,Level 4: W Klatce,Fase 4: Na Jaula,Nível 4: Na Jaula,Nivelul 4: Încarcerat,Уровень №4: В клетке,Level 4: Заробљен,Nivå 4: Burad,Seviye 4: Kafesli +Level 5: Ghost Town,PHUSTR_5,,,,Level 5: Město duchů,Level 5: Spøgelsesby,Level 5: Geisterstadt,,Nivelo 5: Fantoma urbeto,Nivel 5: Pueblo Fantasma,,Taso 5: Aavekaupunki,NIVEAU 5: Ville Fantôme,5. Pálya: Szellemváros,Livello 5: Città Fantasma,Level 5: ゴーストタウン,레벨 5: 유령 도시,Level 5: Spookstad,Nivå 5: Spøkelsesbyen,Level 5: Miasto Duchów,Fase 5: Cidade Fantasma,Nível 5: Cidade Fantasma,Nivelul 5: Orașul fantomă,Уровень №5: Город-призрак,Level 5: Град духова,Nivå 5: Spökstad,Seviye 5: Hayalet Kasaba +Level 6: Baron's Lair,PHUSTR_6,,,,Level 6: Baronovo doupě,Level 6: Baronens hule,Level 6: Lager des Barons,,Nivelo 6: Kaŝejo de Barono,Nivel 6: Guarida del Barón,,Taso 6: Paronin luola,NIVEAU 6: Repaire du Baron,6. Pálya: A báró rejteke,Livello 6: Tana del Barone,Level 6: バロンの隠れ家,레벨 6: 남작의 은신처,Level 6: Baron's kamp,Nivå 6: Baronens hule,Level 6: Legowisko Barona,Fase 6: Covil do Barão,Nível 6: Covil do Barão,Nivelul 6: Claustrul Baronului,Уровень №6: Обитель барона,Level 6: Баронова јазбина,Nivå 6: Baronens lya,Seviye 6: Baron'un İni +Level 7: Caughtyard,PHUSTR_7,,,,Level 7: Karcer,,Level 7: Gehege,,Nivelo 7: Kaptkorto,Nivel 7: Campo de Concentración,,Taso 7: Posenpiha,NIVEAU 7: Pris de court,7. Pálya: A foglyok udvara,Livello 7: Cortile Prigione,Level 7: 囚われの庭,레벨 7: 포획마당,Level 7: Omheining,Nivå 7: Fangegården,Level 7: Dziedziniec Więzienny,Fase 7: Campo de Concentração,Nível 7: Campo de Concentração,Nivelul 7: Capcana curții,Уровень №7: Ловчий двор,Level 7: Замчиште,Nivå 7: Fångården,Seviye 7: Caughtyard +Level 8: Realm,PHUSTR_8,,,,Level 8: Říše,Level 8: Rige,Level 8: Bereich,,Nivelo 8: Regno,Nivel 8: Reino,,Taso 8: Valtapiiri,NIVEAU 8: Royaume,8. Pálya: Uradalom,Livello 8: Regno,Level 8: 領地,레벨 8: 왕국,Level 8: Rijk,Nivå 8: Riket,Level 8: Królestwo,Fase 8: Reino,Nível 8: Reino,Nivelul 8: Tărâm,Уровень №8: Царство,Level 8: Царство,Nivå 8: Riket,Seviye 8: Diyar +Level 9: Abattoire,PHUSTR_9,,,,Level 9: Jatka,,Level 9: Schlachthaus,,Nivelo 9: Buĉejo,Nivel 9: Matadero,,Taso 9: Teurastamo,NIVEAU 9: Abattoir,9. Pálya: Vágóhíd,Livello 9: Mattatoio,Level 9: 屠殺場,레벨 9: 도축장,Level 9: Abattoir,Nivå 9: Slakteriet,Level 9: Rzeźnia,Fase 9: Matadouro,Nível 9: Matadouro,Nivelul 9: Abator,Уровень №9: Абатство,Level 9: Кланица,Nivå 9: Slakthus,Seviye 9: Abattoire +Level 10: Onslaught,PHUSTR_10,,,,Level 10: Nájezd,Level 10: Stormløb,Level 10: Angriff,,Nivelo 10: Buĉado,Nivel 10: Arremetida,,Taso 10: Ryntäys,NIVEAU 10: Assaut,10. Pálya: Roham,Livello 10: Assalto,Level 10: 猛襲,레벨 10: 맹공격,Level 10: Aanval,Nivå 10: Angrep,Level 10: Szturm,Fase 10: Investida,Nível 10: Investida,Nivelul 10: Năvala,Уровень №10: Натиск,Level 10: Јуриш,Nivå 10: Angrepp,Seviye 10: Saldırı +Level 11: Hunted,PHUSTR_11,,,,Level 11: Loven,Level 11: Jaget,Level 11: Gehetzt,,Nivelo 11: Ĉasata,Nivel 11: Cazado,,Taso 11: Metsästetty,NIVEAU 11: Traque,11. Pálya: Űzött vad,Livello 11: Braccato,Level 11: 逃走,레벨 11: 사냥당함,Level 11: Gejaagd,Nivå 11: Jaget,Level 11: Nawiedzony,Fase 11: Perseguição,Nível 11: Perseguição,Nivelul 11: Vânătoarea,Уровень №11: Преследуемый,Level 11: Уловљен,Nivå 11: Jaktad,Seviye 11: Avlanmış +Level 12: Speed,PHUSTR_12,,,,Level 12: Rychlost,Level 12: Fart,Level 12: Tempo,,Nivelo 12: Rapido,Nivel 12: Velocidad,,Taso 12: Vauhti,NIVEAU 12: Vitesse,12. Pálya: Iram,Livello 12: Velocità,Level 12: スピード,레벨 12: 스피드,Level 12: Haast,Nivå 12: Hastighet,Level 12: Pęd,Fase 12: Velocidade,Nível 12: Velocidade,Nivelul 12: Viteză,Уровень №12: Скорость,Level 12: Брзина,Nivå 12: Hastighet,Seviye 12: Hız +Level 13: The Crypt,PHUSTR_13,,,,Level 13: Krypta,Level 13: Krypten,Level 13: Die Gruft,,Nivelo 13: La kripto,Nivel 13: La cripta,,Taso 13: Krypta,NIVEAU 13: La Crypte,13. Pálya: A kripta,Livello 13: La Cripta,Level 13: 地下聖堂,레벨 13: 봉안당,Level 13: De crypte,Nivå 13: Krypten,Level 13: Krypta,Fase 13: A Cripta,Nível 13: A Cripta,Nivelul 13: Cripta,Уровень №13: Склеп,Level 13: Гробница,Nivå 13: Kryptan,Seviye 13: Mahzen +Level 14: Genesis,PHUSTR_14,,,,,,,,Nivelo 14: Genezo,Nivel 14: Génesis,,Taso 14: Luominen,NIVEAU 14: Genèse,14. Pálya: Teremtés,Livello 14: Genesi,Level 14: 創世記,레벨 14: 창세기,,,Level 14: Geneza,Fase 14: Gênese,Nível 14: Gênese,Nivelul 14: Geneza,Уровень №14: Зарождение,Level 14: Постанак,Nivå 14: Genesis,Seviye 14: Yaratılış +Level 15: The Twilight,PHUSTR_15,,,,Level 15: Soumrak,Level 15: Tusmørket,Level 15: Zwielicht,,Nivelo 15: La krepusko,Nivel 15: El ocaso,,Taso 15: Hämärä,NIVEAU 15: Le Crépuscule,15. Pálya: Alkonyat,Livello 15: Il Crepuscolo,Level 15: 黄昏,레벨 15: 황혼,Level 15: De schemering,Nivå 15: Skumringen,Level 15: Zmierzch,Fase 15: O Crepúsculo,Nível 15: O Crepúsculo,Nivelul 15: Amurgul,Уровень №15: Сумерки,Level 15: Сумрак,Nivå 15: Skymningen,Seviye 15: Alacakaranlık +Level 16: The Omen,PHUSTR_16,,,,Level 16: Znamení,Level 16: Omenet,Level 16: Das Omen,,Nivelo 16: La Aŭguro,Nivel 16: El Presagio,,Taso 16: Enne,NIVEAU 16: Le Présage,16. Pálya: Az Ómen,Livello 16: Il Presagio,Level 16: 予兆,레벨 16: 징조,Level 16: De omen,Nivå 16: Varselet,Level 16: Omen,Fase 16: O Presságio,Nível 16: O Presságio,Nivelul 16: Prevestirea,Уровень №16: Предзнаменование,Level 16: Знамење,Nivå 16: Omen,Seviye 16: Omen +Level 17: Compound,PHUSTR_17,,,,Level 17: Ústav,Level 17: Forbindelsen,Level 17: Anlage,,Nivelo 17: Konstruaĵaro,Nivel 17: Complejo,,Taso 17: Laitos,NIVEAU 17: Installation,17. Pálya: Létesítmény,Livello 17: Recinto,Level 17: 調合,레벨 17: 복합체,Level 17: Faciliteit,Nivå 17: Forbindelsen,Level 17: Mieszanka,Fase 17: Complexo,Nível 17: Complexo,Nivelul 17: Complexul,Уровень №17: Комплекс,Level 17: Једињење,Nivå 17: Förbandet,Seviye 17: Bileşik +Level 18: Neurosphere,PHUSTR_18,,,,Level 18: Neurosféra,Level 18: Neurosfæren,Level 18: Neurosphäre,,Nivelo 18: Neŭrosfero,Nivel 18: Neuroesfera,,Taso 18: Neurosfääri,NIVEAU 18: Neurosphère,18. Pálya: Neuroszféra,Livello 18: Neurosfera,Level 18: ニューロスフィア,레벨 18: 뉴로스피어,Level 18: Neurosferen,Nivå 18: Nevrosfæren,Level 18: Neurosfera,Fase 18: Neurosfera,Nível 18: Neurosfera,Nivelul 18: Neurosferă,Уровень №18: Нейросфера,Level 18: Неуросфера,Nivå 18: Neurosfären,Seviye 18: Nörosfer +Level 19: NME,PHUSTR_19,"“NME” read out loud means “enemy”, so translators should consider the translation of “enemy” into their language.",,,Level 19: Nepřítel,,,,Nivelo 19: Mal-BN,Nivel 19: N-MIGO,,Taso 19: VHLLNN,NIVEAU 19: NMI,19. Pálya: LNSG,Livello 19: NMIC,Level 19: 野郎,레벨 19: NOM,,,Level 19: WRG,Fase 19: N-MIGO,Nível 19: N-MIGO,Nivelul 19: INMIC,Уровень №19: В.Р.А.Г.,Level 19: Н.Е.П.Р.,Nivå 19: FiND,Seviye 19: NME +Level 20: The Death Domain,PHUSTR_20,,,,Level 20: Panství smrti,Level 20: Dødsdomænet,Level 20: Die Todeszone,,Nivelo 20: La morta regno,Nivel 20: El Dominio Mortal,,Taso 20: Kuoleman piiri,NIVEAU 20: Le Domaine de la Mort,20. Pálya: A holtak birtoka,Livello 20: Il Dominio della Morte,Level 20: 死の領域,레벨 20: 죽음의 영역,Level 20: Het domein van de dood,Nivå 20: Dødens domene,Level 20: Domena Śmierci,Fase 20: O Domínio da Morte,Nível 20: O Domínio da Morte,Nivelul 20: Domeniul morții,Уровень №20: Владения смерти,Level 20: Подручије смрти,Nivå 20: Dödsdomänen,Seviye 20: Ölüm Alanı +Level 21: Slayer,PHUSTR_21,,,,Level 21: Zabiják,Level 21: Slagter,Level 21: Töter,,Nivelo 21: Mortigisto,Nivel 21: Descuatizador,,Taso 21: Tappaja,NIVEAU 21: Pourfendeur,21. Pálya: Halálosztó,Livello 21: Assassino,Level 21: スレイヤー,레벨 21: 슬레이어,Level 21: Doder,Nivå 21: Slakteren,Level 21: Pogromca,Fase 21: Matador,Nível 21: Matador,Nivelul 21: Ucigător,Уровень №21: Истребитель,Level 21: Убица,Nivå 21: Jägare,Seviye 21: Avcı +Level 22: Impossible Mission,PHUSTR_22,,,,Level 22: Nemožná mise,Level 22: Umulig mission,Level 22: Unmögliche Mission,,Nivelo 22: Neebla tasko,Nivel 22: Misión imposible,,Taso 22: Mahdoton tehtävä,NIVEAU 22: Mission Impossible,22. Pálya: Lehetetlen küldetés,Livello 22: Missione Impossibile,Level 22: 不可能な任務,레벨 22: 임파서블 미션,Level 22: Onmogelijke missie,Nivå 22: Umulig oppdrag,Level 22: Niemożliwa Misja,Fase 22: Missão Impossível,Nível 22: Missão Impossível,Nivelul 22: Misiune imposibilă,Уровень №22: Невыполнимое задание,Level 22: Немогућа мисија,Nivå 22: Omöjligt uppdrag,Seviye 22: İmkansız Görev +Level 23: Tombstone,PHUSTR_23,,,,Level 23: Náhrobek,Level 23: Gravsten,Level 23: Grabstein,,Nivelo 23: Tombŝtono,Nivel 23: Lápida,,Taso 23: Hautakivi,NIVEAU 23: Pierre Tombale,23. Pálya: Sírkő,Livello 23: Pietra Tombale,Level 23: 墓石,레벨 23: 묘비,Level 23: Grafsteen,Nivå 23: Gravstein,Level 23: Nagrobek,Fase 23: Lápide,Nível 23: Lápide,Nivelul 23: Piatra de mormânt,Уровень №23: Надгробие,Level 23: Надгробни споменик,Nivå 23: Gravsten,Seviye 23: Mezar Taşı +Level 24: The Final Frontier,PHUSTR_24,,,,Level 24: Poslední hranice,Level 24: Den endelige grænse,Level 24: Die letzte Grenze,,Nivelo 24: La Fina Limo,Nivel 24: La Frontera Final,Nivel 24: La Última Frontera,Taso 24: Viimeinen rajamaa,NIVEAU 24: La Frontière Finale,24. Pálya: A végső határ,Livello 24: La Frontiera Finale,Level 24: 最後のフロンティア,레벨 24: 최후의 개척지,Level 24: De eindgrens,Nivå 24: Den siste grensen,Level 24: Ostateczna Granica,Fase 24: A Fronteira Final,Nível 24: A Fronteira Final,Nivelul 24: Ultima frontieră,Уровень №24: Последний рубеж,Level 24: Коначна граница,Nivå 24: Den sista gränsen,Seviye 24: Son Sınır +Level 25: The Temple of Darkness,PHUSTR_25,,,,Level 25: Chrám temna,Level 25: Mørkets tempel,Level 25: Der Tempel der Dunkelheit,,Nivelo 25: La Idolejo de Mallumo,Nivel 25: El Templo de la Oscuridad,,Taso 25: Pimeyden temppeli,NIVEAU 25: Le Temple des Ténèbres,25. Pálya: A sötétség temploma,Livello 25: Il Tempio dell'Oscurità,Level 25: 暗黒の神殿,레벨 25: 어둠의 신전,Level 25: De tempel van de duisternis,Nivå 25: Mørkets tempel,Level 25: Świątynia Mroku,Fase 25: O Templo da Escuridão,Nível 25: O Templo da Escuridão,Nivelul 25: Templul tenebros,Уровень №25: Храм тьмы,Level 25: Храм таме,Nivå 25: Mörkrets tempel,Seviye 25: Karanlığın Tapınağı +Level 26: Bunker,PHUSTR_26,,,,Level 26: Bunkr,,,,Nivelo 26: Bunkro,Nivel 26: Búnker,,Taso 26: Bunkkeri,NIVEAU 26: Bunker,26. Pálya: Bunker,Livello 26: Bunker,Level 26: バンカー,레벨 26: 방공호,,,Level 26: Bunkier,Fase 26: Casamata,Nível 26: Bunker,Nivelul 26: Buncăr,Уровень №26: Бункер,Level 26: Бункер,Nivå 26: Bunker,Seviye 26: Sığınak +Level 27: Anti-christ,PHUSTR_27,,,,Level 27: Antikrist,,Level 27: Antichrist,,Nivelo 27: Antikristo,Nivel 27: Anticristo,,Taso 27: Antikristus,NIVEAU 27: Anti-Christ,27. Pálya: Antikrisztus,Livello 27: Anticristo,Level 27: アンチキリスト,레벨 27: 적그리스도,Level 27: Antichrist,Nivå 27: Antikrist,Level 27: Antychryst,Fase 27: Anticristo,Nível 27: Anticristo,Nivelul 27: Antihrist,Уровень №27: Антихрист,Level 27: Антихрист,Nivå 27: Antikrist,Seviye 27: Mesih Karşıtı +Level 28: The Sewers,PHUSTR_28,,,,Level 28: Kanály,Level 28: Kloakkerne,Level 28: Kanäle,,Nivelo 28: La Kanalo,Nivel 28: Las Alcantarillas,,Taso 28: Viemärit,NIVEAU 28: Les Egouts,28. Pálya: A kanális,Livello 28: Le Fogne,Level 28: 下水道,레벨 28: 하수구,Level 28: De rioleringen,Nivå 28: Kloakken,Level 28: Ścieki,Fase 28: Os Esgotos,Nível 28: Os Esgotos,Nivelul 28: Canalizarea,Уровень №28: Канализация,Level 28: Канализација,Nivå 28: Sjukhusen,Seviye 28: Kanalizasyonlar +Level 29: Odyssey of Noises,PHUSTR_29,,,,Level 29: Odysea křiku,Level 29: Lydenes odyssé,Level 29: Odyssee der Geräusche,,Nivelo 29: Vojaĝo de Sonoj,Nivel 29: Odisea de Ruidos,,Taso 29: Äänten harharetki,NIVEAU 29: Odysée de Bruits,29. Pálya: A moraj ösvénye,Livello 29: Odissea dei Rumori,Level 29: オデッセイのノイズ,레벨 29: 속삭임의 여정,Level 29: Odyssee van geluiden,Nivå 29: Lydenes odyssé,Level 29: Odyseja Wrzawy,Fase 29: Odisséia de Ruidos,Nível 29: Odisséia de Ruidos,Nivelul 29: Odiseea zgomotelor,Уровень №29: Одиссея шумов,Level 29: Одисеја шумова,Nivå 29: Ljudets odyssé,Seviye 29: Seslerin Odyssey'i +Level 30: The Gateway of Hell,PHUSTR_30,,,,Level 30: Brána pekla,Level 30: Helvedes port,Level 30: Tor zur Hölle,,Nivelo 30: La Pordego de Inferno,Nivel 30: La Puerta del Infierno,,Taso 30: Helvetin porttikäytävä,NIVEAU 30: La Porte des Enfers,30. Pálya: Átjáró a pokolba,Livello 30: La Porta dell'Inferno,Level 30: 地獄の関門,레벨 30: 지옥의 차원문,Level 30: De poort van de hel,Nivå 30: Porten til helvete,Level 30: Brama Piekieł,Fase 30: O Portão do Inferno,Nível 30: O Portão do Inferno,Nivelul 30: Poarta spre infern,Уровень №30: Врата ада,Level 30: Пролаз пакла,Nivå 30: Helvetets port,Seviye 30: Cehennem Kapısı +Level 31: Cyberden,PHUSTR_31,,,,Level 31: Kyberdoupě,,Level 31: Cyberbau,,Nivelo 31: Cibernesto,Nivel 31: Ciber-guarida,,Taso 31: Kyberpesä,NIVEAU 31: Cyber-Antre,31. Pálya: Kiberodú,Livello 31: Cybergabbia,Level 31: サイバーの巣,레벨 31: 사이버소굴,,,Level 31: Cybernora,Fase 31: Ciberantro,Nível 31: Ciberantro,Nivelul 31: Cibervizuină,Уровень №31: Киберлогово,Level 31: Сајбер-јазбина,Nivå 31: Cyberden,Seviye 31: Siber'in ini +Level 32: Go 2 It,PHUSTR_32,,,,Level 32: Jdi do toho,,,,Nivelo 32: Iru al ĝi!,Nivel 32: Ve a x ello,Nivel 32: Ve x eso,Taso 32: Iske kii,NIVEAU 32: Go 2 It,32. Pálya: Menj oda!,Livello 32: Dacci Dentro,Level 32: 逝ってこい,레벨 32: 함 해 봐,Level 32: Ga ervoor,,Level 32: Do Dzieła,Fase 32: Vai Fundo,Nível 32: Siga em Frente,Nivelul 32: Du-te la ei,Уровень №32: П0лный вп3рёд,Level 32: Иди ка њему,Nivå 32: Gå till det,Seviye 32: Devam Et +,,TNT: Evilution,,,,,,,,,,,,,,,,,,,,,,,,, +Level 1: System Control,THUSTR_1,,,,Level 1: Administrace,Level 1: Systemkontrol,Level 1: Systemkontrolle,,Nivelo 1: Sistema Kontrolo,Nivel 1: Control del Sistema,,Taso 1: Järjestelmäohjaamo,NIVEAU 1: Système de Contrôle,1. Pálya: Rendszervezérlő,Livello 1: Controllo del Sistema,Level 1: 制御システム,레벨 1: 시스템 제어시설,Level 1: Systeemcontrole,Nivå 1: Systemkontroll,Level 1: Kontrola Systemu,Fase 1: Controle do Sistema,Nível 1: Controlo de Sistema,Nivelul 1: Control sisteme,Уровень №1: Центр управления системой,Level 1: Контролна система,Nivå 1: Systemkontroll,Seviye 1: Sistem Kontrolü +Level 2: Human BBQ,THUSTR_2,,,,Level 2: Člověčí grilovačka,Level 2: Menneskelig grill,Level 2: Menschliches Barbecue,,Nivelo 2: Homo-Kradrostado,Nivel 2: Barbacoa Humana,,Taso 2: Ihmisgrilli,NIVEAU 2: Barbecue Humain,2. Pálya: Emberi grill,Livello 2: Barbecue Umano,Level 2: 人肉晩餐会,레벨 2: 인간 바비큐,Level 2: Menselijke BBQ,Nivå 2: Menneskelig BBQ,Level 2: Ludzki Grill,Fase 2: Churrasco Humano,Nível 2: Churrasco Humano,Nivelul 2: Oameni la grătar,Уровень №2: Барбекю из человечины,Level 2: Људски роштиљ,Nivå 2: Människogrill,Seviye 2: İnsan Barbekü +Level 3: Power Control,THUSTR_3,,,,Level 3: Napájecí vedení,Level 3: Kontrol med magten,Level 3: Energiekontrolle,,Nivelo 3: Energia Kontrolo,Nivel 3: Control de Energía,,Taso 3: Voimalan ohjaamo,NIVEAU 3: Contrôle Energétique,3. Pálya: Energiavezérlő,Livello 3: Centrale Energetica,Level 3: 制御室,레벨 3: 전력 통제소,Level 3: Machtscontrole,Nivå 3: Kraftkontroll,Level 3: Kontrola Zasilania,Fase 3: Controle de Energia,Nível 3: Controlo Energético,Nivelul 3: Uzina,Уровень №3: Центр управления питанием,Level 3: Контролна моћ,Nivå 3: Maktkontroll,Seviye 3: Güç Kontrolü +Level 4: Wormhole,THUSTR_4,,,,Level 4: Červí díra,Level 4: Ormehul,Level 4: Wurmloch,,Nivelo 4: Vermtruo,Nivel 4: Agujero de Gusano,,Taso 4: Madonreikä,NIVEAU 4: Trou de Ver,4. Pálya: Féreglyuk,Livello 4: Wormhole,Level 4: 虫喰い穴,레벨 4: 웜홀,Level 4: Wormgat,Nivå 4: Ormehull,Level 4: Tunel,Fase 4: Buraco de Minhoca,Nível 4: Buraco de Minhoca,Nivelul 4: Gaura de vierme,Уровень №4: Червоточина,Level 4: Црвоточина,Nivå 4: Maskhål,Seviye 4: Solucan Deliği +Level 5: Hanger,THUSTR_5,"Not ""Hangar""",,,Level 5: Hangár,,Level 5: Hangar,,Nivelo 5: Pendigejo,Nivel 5: Colgador,,Taso 5: Lentoalushalli,NIVEAU 5: Hengar,5. Pálya: Horog,Livello 5: Hanga,Level 5: 格納庫,레벨 5: 격납고,Level 5: Hangar,Nivå 5: Hanger,Level 5: Hangar,Fase 5: Hangar,Nível 5: Hangar,Nivelul 5: Hangar,Уровень №5: Ангар,Level 5: Вешалица,Nivå 5: Hängare,Seviye 5: Askı +Level 6: Open Season,THUSTR_6,,,,Level 6: Lovecká sezóna,Level 6: Åben sæson,Level 6: Jagdsaison,,Nivelo 6: Ĉasosezono,Nivel 6: Temporada Abierta,,Taso 6: Avoin sesonki,NIVEAU 6: La Chasse Est Ouverte,6. Pálya: Vadászszezon,Livello 6: Stagione Aperta,Level 6: 狩猟解禁,레벨 6: 사냥철,Level 6: Open seizoen,Nivå 6: Åpen sesong,Level 6: Otwarty Sezon,Fase 6: Temporada Aberta,Nível 6: Época Aberta,Nivelul 6: Sezon deschis,Уровень №6: Сезон охоты,Level 6: Отворена сезона,Nivå 6: Öppen säsong,Seviye 6: Açık Sezon +Level 7: Prison,THUSTR_7,,,,Level 7: Vězení,Level 7: Fængsel,Level 7: Gefängnis,,Nivelo 7: Malliberejo,Nivel 7: Prisión,,Taso 7: Vankila,NIVEAU 7: Prison,7. Pálya: Börtön,Livello 7: Prigione,Level 7: 監獄,레벨 7: 감옥,Level 7: Gevangenis,Nivå 7: Fengsel,Level 7: Więzienie,Fase 7: Prisão,Nível 7: Prisão,Nivelul 7: Închisoare,Уровень №7: Тюрьма,Level 7: Затвор,Nivå 7: Fängelse,Seviye 7: Hapishane +Level 8: Metal,THUSTR_8,,,,Level 8: Kov,,Level 8: Metall,,Nivelo 8: Metalo,Nivel 8: Metal,,Taso 8: Metalli,NIVEAU 8: Métal,8. Pálya: Fém,Livello 8: Metallo,Level 8: メタル,레벨 8: 강철,Level 8: Metaal,Nivå 8: Metall,,Fase 8: Metal,Nível 8: Metal,Nivelul 8: Metal,Уровень №8: Металл,Level 8: Метал,Nivå 8: Metall,Seviye 8: Metal +Level 9: Stronghold,THUSTR_9,,,,Level 9: Pevnost,Level 9: Borgen,Level 9: Festung,,Nivelo 9: Fuorto,Nivel 9: Fortaleza,,Taso 9: Linnake,NIVEAU 9: Forteresse,9. Pálya: Erőd,Livello 9: Fortezza,Level 9: 牙城,레벨 9: 요새,Level 9: Vesting,Nivå 9: Festning,Level 9: Warownia,Fase 9: Fortaleza,Nível 9: Fortaleza,Nivelul 9: Bastion,Уровень №9: Твердыня,Level 9: Упориште,Nivå 9: Fästning,Seviye 9: Kale +Level 10: Redemption,THUSTR_10,,,,Level 10: Vykoupení,Level 10: Forløsning,Level 10: Erlösung,,Nivelo 10: Elaĉeto,Nivel 10: Redención,,Taso 10: Lunastus,NIVEAU 10: Rédemption,10. Pálya: Megváltás,Livello 10: Redenzione,Level 10: 償還,레벨 10: 구원,Level 10: Aflossing,Nivå 10: Innløsning,Level 10: Odkupienie,Fase 10: Redenção,Nível 10: Redenção,Nivelul 10: Răscumpărare,Уровень №10: Искупление,Level 10: Искупљење,Nivå 10: Inlösen,Seviye 10: Kefaret +Level 11: Storage Facility,THUSTR_11,,,,Level 11: Skladiště,Level 11: Opbevaringsanlæg,Level 11: Lagerstätte,,Nivelo 11: Stokejo,Nivel 11: Complejo de Almacenes,Nivel 11: Almacenes,Taso 11: Varastolaitos,NIVEAU 11: Complexe de Stockage,11. Pálya: Raktárépület,Livello 11: Impianto di Stoccaggio,Level 11: 貯蔵施設,레벨 11: 저장소,Level 11: Opslagfaciliteit,Nivå 11: Lagringsanlegg,Level 11: Magazyn,Fase 11: Centro de Armazenamento,Nível 11: Centro de Armazenamento,Nivelul 11: Stația de depozitare,Уровень №11: Склад,Level 11: Складиште,Nivå 11: Förvaringsanläggning,Seviye 11: Depolama Tesisi +Level 12: Crater,THUSTR_12,,,,Level 12: Kráter,Level 12: Krater,Level 12: Krater,,Nivelo 12: Kratero,Nivel 12: Cráter,,Taso 12: Kraateri,NIVEAU 12: Cratère,12. Pálya: Kráter,Livello 12: Cratere,Level 12: 火口,레벨 12: 분화구,Level 12: Krater,Nivå 12: Krater,Level 12: Krater,Fase 12: Cratera,Nível 12: Cratera,Nivelul 12: Crater,Уровень №12: Кратер,Level 12: Кратер,Nivå 12: Krater,Seviye 12: Krater +Level 13: Nukage Processing,THUSTR_13,,,,Level 13: Jaderné zpracování,Level 13: Nukageforarbejdning,Level 13: Nuklearverarbeitung,,Nivelo 13: Nukleaĵo-Traktejo,Nivel 13: Procesamiento de Residuos Nucleares,,Taso 13: Ydinjätekäsittely,NIVEAU 13: Traitement Nucléaire,13. Pálya: Atomhulladék-feldolgozó,Livello 13: Trattamento Nucleare,Level 13: 核廃棄物加工所,레벨 13: 폐기물 처리소,Level 13: Nucleaire verwerking,Nivå 13: Nukage-prosessering,Level 13: Przetwórstwo Jądrowe,Fase 13: Processamento Nuclear,Nível 13: Processamento Nuclear,Nivelul 13: Prelucrarea deșeurilor nucleare,Уровень №13: Переработка ядерных отходов,Level 13: Прерада нуклеарног отпада,Nivå 13: Kärnavfall Behandling,Seviye 13: Nukage İşleme +Level 14: Steel Works,THUSTR_14,,,,Level 14: Ocelárna,Level 14: Stålværk,Level 14: Stahlwerk,,Nivelo 14: Ŝtalejo,Nivel 14: Siderúrgica,Nivel 14: Siderurgia,Taso 14: Terästehdas,NIVEAU 14: Aciérie,14. Pálya: Acélművek,Livello 14: Acciaieria,Level 14: 製鉄所,레벨 14: 제강소,Level 14: Staalfabrieken,Nivå 14: Stålverk,Level 14: Huta,Fase 14: Siderúrgica,Nível 14: Siderúrgica,Nivelul 14: Oțelărie,Уровень №14: Сталелитейный завод,Level 14: Челичана,Nivå 14: Stålverk,Seviye 14: Çelik İşleri +Level 15: Dead Zone,THUSTR_15,,,,Level 15: Mrtvá zóna,Level 15: Død zone,Level 15: Tote Zone,,Nivelo 15: Senvivzono,Nivel 15: Zona Muerta,,Taso 15: Kuollut alue,NIVEAU 15: Zone Morte,15. Pálya: A holtak zónája,Livello 15: Zona Morta,Level 15: 危険地帯,레벨 15: 사각지대,Level 15: Dode zone,Nivå 15: Død sone,Level 15: Martwa Strefa,Fase 15: Zona Morta,Nível 15: Zona Morta,Nivelul 15: Zona moartă,Уровень №15: Мёртвая зона,Level 15: Зона смрти,Nivå 15: Dödszon,Seviye 15: Ölü Bölge +Level 16: Deepest Reaches,THUSTR_16,,,,Level 16: Nejhlubší sluje,Level 16: De dybeste afkroge,Level 16: Tiefe,,Nivelo 16: Plejsubejo,Nivel 16: Recodos profundos,,Taso 16: Syvyydet,NIVEAU 16: Profondeurs,16. Pálya: A legmélyebb pont,Livello 16: Profondità,Level 16: 最深部,레벨 16: 깊숙한 강,Level 16: Diepste reiken,Nivå 16: De dypeste områdene,Level 16: Głębiny,Fase 16: Profundezas,Nível 16: Profundezas,Nivelul 16: În adâncuri,Уровень №16: Глубочайшие достижения,Level 16: Најдубља дубина,Nivå 16: De djupaste hålen,Seviye 16: En Derin Erişimler +Level 17: Processing Area,THUSTR_17,,,,Level 17: Kombinát,Level 17: Forarbejdningsområde,Level 17: Verarbeitungsbereich,,Nivelo 17: Traktadareo,Nivel 17: Área de Procesamiento,,Taso 17: Käsittelyalue,NIVEAU 17: Zone de Traitement,17. Pálya: Feldolgozó,Livello 17: Area di Elaborazione,Level 17: 処理地帯,레벨 17: 처리 구역,Level 17: Verwerkingsgebied,Nivå 17: Behandlingsområde,Level 17: Strefa Przerobowa,Fase 17: Área de Processamento,Nível 17: Área de Processamento,Nivelul 17: Aria de procesare,Уровень №17: Зона обработки,Level 17: Подручје обраде,Nivå 17: Bearbetningsområde,Seviye 17: İşleme Alanı +Level 18: Mill,THUSTR_18,,,,Level 18: Mlýn,Level 18: Mølle,Level 18: Mühle,,Nivelo 18: Muelejo,Nivel 18: Molino,,Taso 18: Mylly,NIVEAU 18: Fonderie,18. Pálya: Malom,Livello 18: Fonderia,Level 18: 製粉所,레벨 18: 제분소,Level 18: Molen,Nivå 18: Mølle,Level 18: Młyn,Fase 18: Moinho,Nível 18: Moinho,Nivelul 18: Moara,Уровень №18: Завод,Level 18: Млин,Nivå 18: Kvarn,Seviye 18: Değirmen +Level 19: Shipping/respawning,THUSTR_19,,,,Level 19: Přeprava,Level 19: Forsendelsescenter,Level 19: Versandlager,,Nivelo 19: Ekspedo/Revivado,Nivel 19: Enviando/Reapareciendo,,Taso 19: Huolinta/Ylösnostatus,NIVEAU 19: Envoi/Réapparition,19. Pálya: Szállítás/újraéledés,Livello 19: Consegna/Respawn,Level 19: 出荷と再生成,레벨 19: 운송/리스폰 장소,Level 19: Verzendingscentrum,Nivå 19: Frakt/omlasting,Level 19: Wysyłka/Reprodukcja,Fase 19: Expedição/reaparecimento,Nível 19: Expedição/reaparecimento,Nivelul 19: Livrare/reapariție,Уровень №19: Погрузка и отправка,Level 19: Отпремање/оживљавање,Nivå 19: Skeppning,Seviye 19: Nakliye Merkezi +Level 20: Central Processing,THUSTR_20,,,,Level 20: Centrální zpracování,Level 20: Central forarbejdning,Level 20: Zentralverarbeitung,,Nivelo 20: Centra Eskpedado,Nivel 20: Procesamiento Central,,Taso 20: Käsittelykeskus,NIVEAU 20: Organisme Central,20. Pálya: Központi feldolgozó,Livello 20: Centrale di Elaborazione,Level 20: 中央処理所,레벨 20: 중앙 처리소,Level 20: Centrale verwerking,Nivå 20: Sentral behandling,Level 20: Centralny Proces,Fase 20: Processamento Central,Nível 20: Processamento Central,Nivelul 20: Prelucrare centrală,Уровень №20: Центральный пункт обработки,Level 20: Централна обрада,Nivå 20: Centralt bearbetningsområde,Seviye 20: Merkezi İşlem +Level 21: Administration Center,THUSTR_21,,,,Level 21: Administrativní centrum,Level 21: Administrationscenter,Level 21: Verwaltungszentrum,,Nivelo 21: Administracia Centro,Nivel 21: Centro de Administración,,Taso 21: Keskushallinto,NIVEAU 21: Centre Administratif,21. Pálya: Adminisztrációs központ,Livello 21: Centro Amministrativo,Level 21: 行政センター,레벨 21: 관리 센터,Level 21: Administratief centrum,Nivå 21: Administrasjonssenter,Level 21: Centrum Administracyjne,Fase 21: Centro de Administração,Nível 21: Centro de Administração,Nivelul 21: Centru administrativ,Уровень №21: Административный центр,Level 21: Административни центар,Nivå 21: Administrationscenter,Seviye 21: Yönetim Merkezi +Level 22: Habitat,THUSTR_22,,,,,Level 22: Levested,,,Nivelo 22: Habitato,Nivel 22: Hábitat,,Taso 22: Asuinpaikka,NIVEAU 22: Habitat,22. Pálya: Élőhely,Livello 22: Habitat,Level 22: 生息地,레벨 22: 서식지,,Nivå 22: Habitat,Level 22: Siedlisko,Fase 22: Habitat,Nível 22: Habitat,Nivelul 22: Habitat,Уровень №22: Ареал,Level 22: Станиште,Nivå 22: Livsområde,Seviye 22: Habitat +Level 23: Lunar Mining Project,THUSTR_23,,,,Level 23: Lunární těžební projekt,Level 23: Projekt for månens minedrift,Level 23: Mondbergbauprojekt,,Nivelo 23: Luna Mino-Projekto,Nivel 23: Proyecto de Minería Lunar,,Taso 23: Kuukaivosprojekti,NIVEAU 23: Projet Minier Lunaire,23. Pálya: Holdbánya-projekt,Livello 23: Progetto Minerario Lunare,Level 23: 月面探鉱計画,레벨 23: 월석 채광 계획,Level 23: Maanmijnbouw project,Nivå 23: Månegruveprosjekt,Level 23: Projekt Księżycowe Górnictwo,Fase 23: Projeto de Mineração Lunar,Nível 23: Projeto de Escavação Lunar,Nivelul 23: Proiect minier satelitar,Уровень №23: Лунный проект горной добычи,Level 23: Пројекат лунарног рударства,Nivå 23: Gruvprojekt på månen,Seviye 23: Ay Madenciliği Projesi +Level 24: Quarry,THUSTR_24,,,,Level 24: Kamenolom,Level 24: Stenbrud,Level 24: Steinbruch,,Nivelo 24: Ŝtonejo,Nivel 24: Cantera,,Taso 24: Louhos,NIVEAU 24: Carrière,24. Pálya: Kőbánya,Livello 24: Caccia,Level 24: 採石場,레벨 24: 채석장,Level 24: Steengroeve,Nivå 24: Steinbrudd,Level 24: Kamieniołom,Fase 24: Pedreira,Nível 24: Pedreira,Nivelul 24: Carieră,Уровень №24: Карьер,Level 24: Каменолом,Nivå 24: Stenbrott,Seviye 24: Taş Ocağı +Level 25: Baron's Den,THUSTR_25,,,,Level 25: Baronovo doupě,Level 25: Baronens hule,Level 25: Der Bau des Barons,,Nivelo 25: Nestego de Barono,Nivel 25: Guarida del Barón,,Taso 25: Paronin pesä,NIVEAU 25: l'Antre des Barons,25. Pálya: A báró odúja,Livello 25: Antro del Barone,Level 25: バロンの巣窟,레벨 25: 남작의 소굴,Level 25: Het baron's gebouw,Nivå 25: Baronens hule,Level 25: Legowisko Barona,Fase 25: Covil do Barão,Nível 25: Covil do Barão,Nivelul 25: Cuibul Baronului,Уровень №25: Логово барона,Level 25: Баронова јазбина,Nivå 25: Baronens lya,Seviye 25: Baron'un İni +Level 26: Ballistyx,THUSTR_26,,,,Level 26: Balistika,,,,Nivelo 26: Balistikso,Nivel 26: Balístige,,Taso 26: Ballistyks,NIVEAU 26: Ballistyx,26. Pálya: Ballisztüx,Livello 26: Ballistige,Level 26: バリステュクス,레벨 26: 탄도스틱스,,,Level 26: Balistyka,Fase 26: Ballistige,Nível 26: Ballistige,Nivelul 26: Ballistyx,Уровень №26: Баллистикс,Level 26: Билистичкикс,Nivå 26: Ballistyx,Seviye 26: Balistyx +Level 27: Mount Pain,THUSTR_27,,,,Level 27: Hora bolesti,Level 27: Smertefjellet,Level 27: Berg des Schmerzes,,Nivelo 27: Monto de Doloro,Nivel 27: Monte Dolor,,Taso 27: Tuskavuori,NIVEAU 27: Mont Souffrance,27. Pálya: A Gyötrelem Hegye,Livello 27: Monte del Dolore,Level 27: 苦しみの山,레벨 27: 등신같은 등산,Level 27: Pijn in de bergen,Nivå 27: Smertefjellet,Level 27: Góra Bólu,Fase 27: Monte Dor,Nível 27: Monte Dor,Nivelul 27: Muntele Durerii,Уровень №27: Гора Боль,Level 27: Планина боли,Nivå 27: Smärta på berget,Seviye 27: Acı Dağı +Level 28: Heck,THUSTR_28,,,,Level 28: Sakra,,Level 28: Zum Teufel,,Nivelo 28: Diable,Nivel 28: Diablos,,Taso 28: Hemmetti,NIVEAU 28: Que Diable?,28. Pálya: Rosseb,Livello 28: Al Diavolo,Level 28: 苛立ち,레벨 28: 젠장함,,Nivå 28: Helvete,Level 28: Do Diabła,Fase 28: Capeta,Nível 28: Inferno,Nivelul 28: Naiba,Уровень №28: Чертовщина,Level 28: Пакао,Nivå 28: Heck,Seviye 28: Cehennem +Level 29: River Styx,THUSTR_29,,,,Level 29: Řeka Styx,Level 29: Floden Styx,Level 29: Fluss Styx,,Nivelo 29: Rivero de Stikso,Nivel 29: Río Estige,,Taso 29: Styksjoki,NIVEAU 29: Fleuve Styx,29. Pálya: A Sztüx folyó,Livello 29: Fiume Stige,Level 29: 三途の川,레벨 29: 스틱스 강,Level 29: Rivier Styx,Nivå 29: Elven Styx,Level 29: Styks,Fase 29: Rio Estige,Nível 29: Rio Estige,Nivelul 29: Râul Styx,Уровень №29: Река Стикс,Level 29: Река Стикс,Nivå 29: Floden Styx,Seviye 29: Styx Nehri +Level 30: Last Call,THUSTR_30,,,,Level 30: Poslední mise,Level 30: Sidste opkald,Level 30: Letzter Aufruf,,Nivelo 30: Fina Voko,Nivel 30: Última Llamada,,Taso 30: Viimeinen koollehuuto,NIVEAU 30: Dernier Appel,30. Pálya: Utolsó esély,Livello 30: Ultima Chiamata,Level 30: 最終指令,레벨 30: 최후의 호출,Level 30: Laatste oproep,Nivå 30: Siste innkalling,Level 30: Ostatni Zew,Fase 30: Última Chamada,Nível 30: Última Chamada,Nivelul 30: Ultimul apel,Уровень №30: Последний вызов,Level 30: Последњи позив,Nivå 30: Sista kallelsen,Seviye 30: Son Çağrı +Level 31: Pharaoh,THUSTR_31,,,,Level 31: Faraón,Level 31: Farao,Level 31: Pharao,,Nivelo 31: Faraono,Nivel 31: Faraón,,Taso 31: Faarao,NIVEAU 31: Pharaon,31. Pálya: Fáraó,Livello 31: Faraone,Level 31: ファラオ,레벨 31: 파라오,Level 31: Farao,Nivå 31: Farao,Level 31: Faraon,Fase 31: Faraó,Nível 31: Faraó,Nivelul 31: Faraon,Уровень №31: Фараон,Level 31: Фараон,Nivå 31: Farao,Seviye 31: Firavun +Level 32: Caribbean,THUSTR_32,,,,Level 32: Karibik,Level 32: Caribien,Level 32: Karibik,,Nivelo 32: Karibio,Nivel 32: Caribeño,,Taso 32: Karibia,NIVEAU 32: Caraïbes,32. Pálya: Karib-térség,Livello 32: Caraibi,Level 32: カリビアン,레벨 32: 카리브해,Level 32: Caribisch,Nivå 32: Karibia,Level 32: Karaiby,Fase 32: Caribe,Nível 32: Caraíbas,Nivelul 32: Caraibe,Уровень №32: Карибы,Level 32: Кариби,Nivå 32: Karibien,Seviye 32: Karayipler +,,Heretic,,,,,,,,,,,,,,,,,,,,,,,,, +The Docks,HHUSTR_E1M1,,,,Přístav,Havnene,Die Docks,,La Havenoj,Los Muelles,,Satamat,Les Docks,A Kikötő,Il Molo,埠頭,항구,De dokken,Havnen,Doki,As Docas,,Docul,Доки,Лука,Hamnarna,Rıhtım +The Dungeons,HHUSTR_E1M2,,,,Žaláře,Fangehullerne,Die Kerker,,La Malliberejoj,Los Calabozos,,Tyrmät,Le Donjon,A Kazamaták,I Sotterranei,地下牢,지하감옥,De kerkers,Fangehullene,Lochy,As Masmorras,,Temnița,Темницы,Тамнице,Fästningarna,Zindanlar +The Gatehouse,HHUSTR_E1M3,,,,Vrátnice,Portens hus,Das Pförtnerhaus,,La Pordegejo,El Cuerpo de Guardia,,Porttitalo,Le Corps de Garde,A Kapuház,L'ingresso,門塔,문루,Het poortgebouw,Porthuset,Stróżówka,O Portão de Entrada,,Casa portarului,Привратницкая,Стражарница,Porthuset,Kapı Evi +The Guard Tower,HHUSTR_E1M4,,,,Strážní věž,Vagttårnet,Der Wachturm,,La Gardturo,La Torre de Guardia,,Vartiotorni,La Tour de Garde,Az Őrtorony,La Torre di Guardia,監視塔,보초 누대,De wachttoren,Vakttårnet,Wieża Strażnicza,A Torre de Guarda,,Turnul de veghe,Сторожевая башня,Извидница,Vakttornet,Muhafız Kulesi +The Citadel,HHUSTR_E1M5,,,,Citadela,Citadellet,Die Festung,,La Citadelo,La Ciudadela,,Linnake,La Citadelle,A Citadella,La Cittadella,要塞,거점,De citadel,Citadellet,Cytadela,A Cidadela,,Cetatea,Цитадель,Цитадела,Citadellet,Hisar +The Cathedral,HHUSTR_E1M6,,,,Katedrála,Katedralen,Die Kathedrale,,La Katedralo,La Catedral,,Katedraali,La Cathédrale,A Katedrális,La Cattedrale,大聖堂,대성당,De kathedraal,Katedralen,Katedra,A Catedral,,Catedrala,Кафедральный собор,Катедрала,Katedralen,Katedral +The Crypts,HHUSTR_E1M7,,,,Krypty,Krypterne,Die Krypten,,La Kriptoj,Las Criptas,,Kryptat,La Crypte,A Kripták,Le Cripte,地下聖堂,지하 묘실,De grafkelders,Kryptene,Krypty,As Criptas,,Criptele,Склепы,Крипта,Krypten,Mahzenler +Hell's Maw,HHUSTR_E1M8,,,,Chřtán pekla,Helvedes gab,Der Höllenschlund,,Faŭko de Infero,Fauces del Infierno,,Helvetin kita,La Geule de l'Enfer,A Pokol Szája,La Bocca dell'Inferno,地獄の肚,지옥의 목구멍,De helmouth,Helvetes gap,Paszcza Piekieł,A Boca do Inferno,,Gura iadului,Адская утроба,Паклено ждрело,Helvetets gap,Cehennem Ağzı +The Graveyard,HHUSTR_E1M9,,,,Hřbitov,Kirkegården,Der Friedhof,,La Tombejo,El Cementerio,,Hautausmaa,Le Cimetière,A Temető,Il Cimitero,墓場,공동묘지,De begraafplaats,Kirkegården,Cmentarz,O Cemitério,,Cimitirul,Кладбище,Гробље,Kyrkogården,Mezarlık +The Crater,HHUSTR_E2M1,,,,Kráter,Krateret,Der Krater,,La Kratero,El Cráter,,Kraateri,Le Cratère,A Kráter,Il Cratere,噴火口,깊은 혈,De krater,Krateret,Krater,A Cratera,,Craterul,Кратер,Кратер,Kratern,Krater +The Lava Pits,HHUSTR_E2M2,,,,Lávové jámy,Lavagruberne,Die Lavagruben,,La Lafo-Fosaĵo,Las Canteras de Lava,,Laavamontut,Les Puits de Lave,A Lávaárok,I Pozzi della Lava,溶岩の竪穴,용암 구덩이,De lavaputten,Lavagropene,Szyb Lawy,Os Fossos de Lava,,Gropile cu lavă,Лавовые очаги,Понор лаве,Lavagruvorna,Lav Çukurları +The River of Fire,HHUSTR_E2M3,,,,Ohnivá řeka,Ildfloden,Der Feuerfluss,,La Rivero de Fajro,El Río de Fuego,,Tulijoki,La Rivière de Feu,A Tűzfolyó,Il Fiume di Fuoco,火の河,화염의 강,De rivier van vuur,Elven av ild,Rzeka Ognia,O Rio de Fogo,,Râul de foc,Река огня,Река од ватре,Eldfloden,Ateş Nehri +The Ice Grotto,HHUSTR_E2M4,,,,Ledová grotta,Isgrotten,Die Eisgrotte,,La Glacigroto,La Gruta de Hielo,,Jääluola,La Grotte de Glace,A Jégbarlang,La Grotta del Ghiaccio,氷の洞窟,얼음 동굴,De ijsgrot,Isgrotten,Lodowa Grota,A Gruta de Gelo,,Grota de gheață,Ледяной грот,Ледена пећина,Isgrottan,Buz Mağarası +The Catacombs,HHUSTR_E2M5,,,,Katakomby,Katakomberne,Die Katakomben,,La Katakomboj,Las Catacumbas,,Katakombit,Les Catacombes,A Katakombák,Le Catacombe,地下墓所,태고의 무덤,De catacomben,Katakombene,Katakumby,As Catacumbas,Os Túmulos,Catacombele,Катакомбы,Катакомбе,Katakomberna,Yeraltı Mezarları +The Labyrinth,HHUSTR_E2M6,,,,Labyrint,Labyrinten,Das Labyrinth,,La Labirinto,El Laberinto,,Labyrintti,Le Labyrinthe,A Labirintus,Il Labirinto,迷宮,미궁,Het labyrint,Labyrinten,Labirynt,O Labirinto,,Labirintul,Лабиринт,Лавиринт,Labyrinten,Labirent +The Great Hall,HHUSTR_E2M7,,,,Velký sál,Den store sal,Die große Halle,,La Granda Halo,El Gran Salón,,Suuri halli,Le Grand Hall,A Nagy Folyosó,La Grande Sala,大公会堂,대회관,De grote zaal,Den store salen,Wielki Hol,O Grande Salão,,Sala cea mare,Большой зал,Велика дворана,Den stora hallen,Büyük Salon +The Portals of Chaos,HHUSTR_E2M8,,,,Portály chaosu,Kaosets portaler,Das Portal des Chaos,,La Portaloj de Ĥaoso,Los Portales del Caos,,Kaaoksen portaalit,Le Portail du Chaos,A Káosz Portáljai,I Portali del Caos,混沌への門,혼돈의 차원문,De portalen van chaos,Kaosets portaler,Portale Chaosu,Os Portais do Caos,,Portalurile haosului,Порталы хаоса,Портали хаоса,Kaosets portaler,Kaos Kapıları +The Glacier,HHUSTR_E2M9,,,,Ledovec,Gletsjeren,Der Gletscher,,La Glaciejo,El Glaciar,,Jäätikkö,Le Glacier,A Gleccser,Il Ghiacciaio,氷河,빙하 구역,De gletsjer,Isbreen,Lodowiec,A Geleira,O Glaciar,Ghețarul,Ледник,Глечер,Glaciären,Buzul +The Storehouse,HHUSTR_E3M1,,,,Skladiště,Magasinet,Die Lagerhalle,,La Stokejo,El Almacén,,Varasto,L'Entrepôt,A Raktár,Il Magazzino,倉庫,저장고,Het pakhuis,Forrådshuset,Magazyn,O Armazém,,Depozitul,Кладовая,Складиште,Magasinet,Depo +The Cesspool,HHUSTR_E3M2,,,,Žumpa,Kedelbassinet,Die Latrine,,La Kloako,El Pozo,,Likakaivo,Le Bourbier,A Pöcegödör,Il Pozzo Nero,汚水層,불결한 장소,De zinkput,Søledammen,Szambo,A Fossa,,Haznaua,Сточный колодец,Септичка јама,Rännstenen,Lağım Çukuru +The Confluence,HHUSTR_E3M3,,,,Soutok,Sammenløbet,Die Vereinigung,,La Kunfluiĝo,La Confluencia,,Yhtymäkohta,La Confluence,A Kereszteződés,La Confluenza,合流点,합류점,De samenvloeiing,Sammenløpet,Spływ,A Confluência,,Confluența,Слияние,Ушће,Sammanflödet,Confluence +The Azure Fortress,HHUSTR_E3M4,,,,Azurová pevnost,Den azurblå fæstning,Die himmelblaue Festung,,La Lazurfortikaĵo,La Fortaleza de Azur,,Sininen linnoitus,La Fortresse d'Azur,Az Azúr Erőd,La Fortezza Azzurra,紺碧の要塞,청천의 요새,De azuurblauwe vesting,Den azurblå festningen,Lazurowa Forteca,A Fortaleza Azul,,Fortăreața de azur,Лазурная крепость,Азурна дврђава,Den azurblå fästningen,Azure Kalesi +The Ophidian Lair,HHUSTR_E3M5,,,,Hadí doupě,Ophidian Hulen,Das Schlangennest,,La Nestego de Ofidia,La Guarida Ofídica,,Käärmeiden pesä,Le Repaire des Ophidiens,Az Opfidiánok Fészke,L'antro degli Ophidian,オフィディアンの塒,오피디안의 소굴,Het slangennest,Ophidian-hulen,Gniazdo Węży,A Cova dos Ofídios,,Cuibul ofidienilor,Логово офидианов,Змијска јазбина,Den Ophidiska hålan,Ophidian İni +The Halls of Fear,HHUSTR_E3M6,,,,Chodby strachu,Frygtens haller,Die Hallen der Angst,,La Koridoroj de Timo,Los Salones del Miedo,,Pelon salit,Les Couloirs de la Peur,A Félelem Folyosói,Le Sale della Paura,恐怖の館,공포의 회관,De zalen van angst,Fryktens haller,Korytarze Strachu,Os Salões do Medo,,Sălile groazei,Залы страха,Дворана страха,Skräckens hallar,Korku Salonları +The Chasm,HHUSTR_E3M7,,,,Propast,Kløften,Der Abgrund,,La Fendego,El Abismo,,Rotko,Le Gouffre,A Szakadék,L'abisso,裂け目,깊은 골,De kloof,Kløften,Przepaść,O Abismo,,Prăpastia,Пропасть,Понор лаве,Klyftan,Uçurum +D'Sparil's Keep,HHUSTR_E3M8,,,,D'Sparilova pevnost,D'Sparils borg,D'Sparils Außenposten,,Ĉefturo de Desparilo,Guarida de D'Sparil,,D'Sparilin linna,Le Donjon de D'Sparil,D'Sparil Terme,La Dimora di D'Sparil,デ’スパリルの間,드'스파릴의 초소,D'Sparil's voorpost,D'Sparils borg,Baszta D'Sparila,Fortaleza de D'Sparil,,Palatul lui D'sparil,Крепость Д'Спарила,Д'Спарилова кула,D'Sparils borg,D'Sparil'in Kalesi +The Aquifer,HHUSTR_E3M9,,,,Zvodeň,Akvifer,Der Wasserspeicher,,La Akvigilo,El Acuífero,,Akviferi,L'Aquifère,A Víztorony,L'acquedotto,帯水層,대수층,Het water reservoir,Akviferen,Wodociąg,O Aquífero,,Galerii acvifere,Водоносный слой,Водоносник,Akvifer,Akifer +Catafalque,HHUSTR_E4M1,,,,Katafalk,Katafalken,Katafalk,,Katafalko,Catafalco,,Katafalkki,Le Catafalque,Ravatal,Catafalco,棺台,관대,Catafalk,Katafalken,Katafalk,Catafalco,,Catafalc,Катафалк,Одар,Katafalken,Katafalk +Blockhouse,HHUSTR_E4M2,,,,Tvrzka,Blokhuset,Blockhaus,,Blokhaŭso,Fortín,,Linnoitus,Le Fortin,Gerendaház,Blocco di Case,丸太小屋,특화점,Blokhuis,Blokkhuset,Blokhauz,O Forte,,Fort,Блокгауз,Бункер,Blockhuset,Blok ev +Ambulatory,HHUSTR_E4M3,,,,Ochoz,Ambulatory,Wandelgang,,Ĥorĉirkaŭirejo,Ambulatorio,,Kuorikäytävä,Le Déambulatoire,Kerengő,Ambulatorio,遊歩道,유보장,Kloostergang,Gangen,Krużganek,Ambulatório,,Clinică,Амбулатория,Амбуланта,Ambulerande,Ambulatuvar +Sepulcher,HHUSTR_E4M4,,,,Hrobka,Graven,Grabstätte,,Tombo,Sepulcro,,Hautakammio,Le Sépulcre,Síremlék,Sepolcro,埋葬所,매장소,Grafsteen,Graven,Grób,Sepulcro,,Sepulcru,Гробница,Гробница,Gravskålen,Mezar +Great Stair,HHUSTR_E4M5,,,,Velké schody,Den store trappe,Große Treppe,,Granda Ŝtuparo,Gran Escalera,,Suuret portaat,Le Grand Escalier,Nagy Lépcső,Grande Scala,大階段,특급 계단,Grote trap,Den store trappen,Wielka Gwiazda,Grande Escada,,Scara cea mare,Великая лестница,Велики степеник,Stora trappan,Büyük Merdiven +Halls of the Apostate,HHUSTR_E4M6,,,,Chodby odpadlictví,Apostaternes haller,Halle des Abtrünnigen,,Haloj de la Apostato,Salas de los Apóstatas,,Luopioiden salit,Les Halls de l'Apôtre,A Hitehagyott Csarnoka,Sale dell'Apostata,背教者の館,배교자의 회관,Zalen van de afvallige,De frafalnes haller,Korytarze Odszczepieńca,Os Salões dos Apóstatas,,Sălile apostatului,Залы отступников,Дворана апостола,Apostaternas salar,Mürted Salonları +Ramparts of Perdition,HHUSTR_E4M7,,,,Náspy zatracení,Fortabelsens ramper,Wälle der Verdammnis,,Muregoj de Pereo,Murallas de la Perdición,,Kadotuksen vallit,Les Remparts de la Perdition,A Kárhozat Támasza,Torrioni della Perdizione,破滅の塁壁,파멸의 성벽,Wallen van de verdoemenis,Fortapelsens voller,Wał Potępienia,Muralhas da Perdição,,Meterezele pierzaniei,Твердыни погибели,Бедем пропасти,Fördärvets ramper,Azap Surları +Shattered Bridge,HHUSTR_E4M8,,,,Rozbitý most,Den ødelagte bro,Zerstörte Brücke,,Frakasita Ponto,Puente Destrozado,,Särkynyt silta,Le Pont effondré,Az Összeomlott Híd,Ponte Distrutto,崩落の橋,붕괴된 다리,Verbrijzelde brug,Den knuste broen,Zniszczony Most,Ponte Despedaçada,,Podul dărâmat,Разрушенный мост,Поломљен мост,Förstörd bro,Parçalanmış Köprü +Mausoleum,HHUSTR_E4M9,,,,Mauzoleum,,,,Maŭzoleo,Mausoleo,,Mausoleumi,Le Mausolée,Mauzóleum,Mausoleo,霊廟,대영묘,,Mausoleet,Mauzoleum,Mausoléu,,Mausoleu,Мавзолей,Маузолеј,,Anıt Mezar +Ochre Cliffs,HHUSTR_E5M1,,,,Okrové útesy,Okkerklipper,Ockerfarbene Klippen,,Klifoj de Okro,Acantilados Ocres,,Okrajyrkänteet,Les Falaises Ochre,Okker Szakadékok,Colline Ocra,黄土絶壁,황토 산맥,Okerkliffen,Oker-klippene,Ochrowe Klify,Penhascos Ocres,,Stâncile de ocru,Охровые утёсы,Окер брда,Ockerfärgade klippor,Ochre Kayalıkları +Rapids,HHUSTR_E5M2,,,,Peřeje,Rapider,Stromschnellen,,Rapidfluoj,Rápidos,,Koski,Les Rapides,Zuhatagok,Rapide,奔流,여울,Stroomversnellingen,Strykene,Katarakty,Corredeiras,,Ape repezi,Стремнина,Брзак,Forsar,Akıntıları +Quay,HHUSTR_E5M3,,,,Nábřeží,Kaj,Kai,,Kajo,Muelle,,Satamalaituri,Le Quai,Rakpart,Banchina,岸壁,부두,Kade,Kai,Wir,Cais,,Chei,Причал,Пристаниште,Kajen,Rıhtım +Courtyard,HHUSTR_E5M4,,,,Nádvoří,Slotsgården,Schlosshof,,Korto,Patio,,Linnanpiha,La Cour,Pitvar,Cortile,中庭,안마당,Binnenplaats,Gårdsplass,Dziedziniec,Pátio,,Curte,Внутренний двор,Двориште,Gården,Avlu +Hydratyr,HHUSTR_E5M5,,,,Hydratýr,,,,Akvotjr,Hydratyr,,,L'Hydratyr,Hidratáló,,ヒュドラテュール,식수공급처,,,Hydratyr,Reservatório,,Hidratir,Гидротир,Канализација,Hydratyr,Hydratyr +Colonnade,HHUSTR_E5M6,,,,Kolonáda,Kolonnader,Kolonnaden,,Kolonaro,Columnata,,Pylväikkö,La Colonnade,Kolonnád,Colonnato,柱廊,열주의 길,Zuilengalerij,Kolonnade,Kolumnada,Colunata,,Colonadă,Колоннада,Колонада,Colonnade,Kolonat +Foetid Manse,HHUSTR_E5M7,,,,Smrdutá vila,Stinkende præstegård,Stinkendes Pfarrhaus,,Haladza Domego,Mansión Fétida,,Löyhkäävä kartano,Le Presbytère Fétide,Bűzös Parókia,Fetido Castello,悪臭の牧師館,역겨운 목사관,Stinkende pastorie,Stinkende prestegård,Cuchnąca Plebania,Mansão Fétida,,Conac Fetid,Зловонный особняк,Фетидна кућа,Foetid Manse,Foetid Manse +Field of Judgement,HHUSTR_E5M8,,,,Soudná pole,Dommervældet,Richtstätte,,Kampo de Juĝo,Campo de Juicio,,Tuomion kenttä,Les Champs du Jugement,Az Itélet Mezeje,Campo del Giudizio,審判之地,심판의 평야,Plaats van oordeelsvorming,Dømmekraftsområde,Pole Sądu,Campo de Julgamento,,Câmpul de Judecată,Поле высшего суда,Чистилиште,Domarplatsen,Yargı Alanı +Skein of D'sparil,HHUSTR_E5M9,,,,Hejno D'Sparilovo,D'sparils skein,DSparils Bau,,Fadenaro de D'Sparil,Madeja de D'Sparil,,D'Sparilin vyyhti,L'échevaux de D'Sparil,D'Sparil Káosza,Groviglio di D'Sparil,デ'スパリルの枷,드'스파릴의 타래,D'Sparil's gebouw,Garn av D'sparil,Motek D'Sparila,Meada de D'Sparil,,Jurubița lui D'Sparil,Путаница Д'Спарила,Реке Д'Спарила,D'sparils skein,D'sparil Çileği +,,Strife,,,,,,,,,,,,,,,,,,,,,,,,, +AREA 1: Sanctuary,TXT_STRIFE_MAP01,,,,ZÓNA 1: Svatyně,AREA 1: Fristedet,ZONE 1: Heiligtum,,AREO 1: Sanktejo,ÁREA 1: Santuario,,ALUE 1: Pyhäkkö,ZONE 1: Sanctuaire,1. Terület: Szentély,AREA 1: Santuario,エリア 1: 聖域,구역 1: 성소,Zone 1: Heiligdom,OMRÅDE 1: Helligdom,Strefa 1: Sanktuarium,Área 1: Santuário,,ZONA 1: Sanctuar,МЕСТНОСТЬ 1: Святилище,,OMRÅDE 1: Fristad,ALAN 1: Sığınak AREA 2: Town,TXT_STRIFE_MAP02,,,,ZÓNA 2: Město,AREA 2: By,ZONE 2: Stadt,,AREO 2: Urbeto,ÁREA 2: Pueblo,,ALUE 2: Kylä,ZONE 2: Ville,2. Terület: Város,AREA 2: Città,"エリア 2: 町 -",구역 2: 마을,Zone 2: Stad,OMRÅDE 2: Byen,Strefa 2: Miasto,Área 2: Vila,,ZONA 2: Oraș,МЕСТНОСТЬ 2: Город,,ALAN 2: Şehir -AREA 3: Front Base,TXT_STRIFE_MAP03,,,,ZÓNA 3: Základna Fronty,AREA 3: Front Basis,ZONE 3: Basis der Front,,AREO 3: Front-Bazo,ÁREA 3: Base del Frente,,ALUE 3: Rintaman tukikohta,ZONE 3: Base du Front,3. Terület: Elülső bázis,AREA 3: Base del Fronte,エリア 3: フロント基地,구역 3: 프론트 기지,Zone 3: Front basis,OMRÅDE 3: Frontbase,Strefa 3: Baza Frontu,Área 3: Base da Frente,,ZONA 3: Baza Frontului,МЕСТНОСТЬ 3: База сопротивления,,ALAN 3: Ön Taban -AREA 4: Power Station,TXT_STRIFE_MAP04,,,,ZÓNA 4: Elektrárna,AREA 4: Kraftværk,ZONE 4: Kraftwerk,,AREO 4: Elektrocentralo,ÁREA 4: Central Eléctrica,,ALUE 4: Voimalaitos,ZONE 4: Centrale,4. Terület: Erőmű,AREA 4: Centrale Elettrica,エリア 4: 発電所,구역 4: 발전소,Zone 4: Energiecentrale,OMRÅDE 4: Kraftstasjon,Strefa 4: Elektrownia,Área 4: Usina de Energia,Área 4: Central Energética,ZONA 4: Centrala,МЕСТНОСТЬ 4: Электростанция,,ALAN 4: Elektrik Santrali -AREA 5: Prison,TXT_STRIFE_MAP05,,,,ZÓNA 5: Vězení,AREA 5: Fængsel,ZONE 5: Gefängnis,,AREO 5: Malliberejo,ÁREA 5: Prisión,,ALUE 5: Vankila,ZONE 5: Prison,5. Terület: Börtön,AREA 5: Carcere,エリア 5: 刑務所,구역 5: 감옥,Zone 5: Gevangenis,OMRÅDE 5: Fengsel,Strefa 5: Więzienie,Área 5: Prisão,,ZONA 5: Închisoare,МЕСТНОСТЬ 5: Тюрьма,,ALAN 5: Cezaevi -AREA 6: Sewers,TXT_STRIFE_MAP06,,,,ZÓNA 6: Stoky,AREA 6: Kloakkerne,ZONE 6: Kanalisation,,AREO 6: Kloako,ÁREA 6: Alcantarillas,,ALUE 6: Viemärit,ZONE 6: Egouts,6. Terület: Kanális,AREA 6: Fogne,エリア 6: 下水道,구역 6: 하수도,Zone 6: Riolering,OMRÅDE 6: Kloakk,Strefa 6: Kanały,Área 6: Esgoto,,ZONA 6: Canal,МЕСТНОСТЬ 6: Канализация,,ALAN 6: Kanalizasyonlar -AREA 7: Castle,TXT_STRIFE_MAP07,,,,ZÓNA 7: Hrad,AREA 7: Slot,ZONE 7: Burg,,AREO 7: Kastelo,ÁREA 7: Castillo,,ALUE 7: Linna,ZONE 7: Château,7. Terület: Vár,AREA 7: Castello,エリア 7: 城,구역 7: 성,Zone 7: Kasteel,OMRÅDE 7: Slottet,Strefa 7: Zamek,Área 7: Castelo,,ZONA 7: Castel,МЕСТНОСТЬ 7: Замок,,ALAN 7: Kale -AREA 8: Audience Chamber,TXT_STRIFE_MAP08,,,,ZÓNA 8: Audienční sál,AREA 8: Audience Chamber,ZONE 8: Audienzsaal,,AREO 8: Aŭdicencejo,ÁREA 8: Cámara de Audiencias,,ALUE 8: Yleisösali,ZONE 8: Chambre d'Audience,8. Terület: Nézőtér,AREA 8: Sala delle Udienze,エリア 8: 観客席,구역 8: 알현실,Zone 8: Auditorium,OMRÅDE 8: Audienssalen,Strefa 8: Izba Audiencji,Área 8: Câmara de Audiências,,ZONA 8: Camera de audiențe,МЕСТНОСТЬ 8: Приёмная,,ALAN 8: İzleyici Odası -AREA 9: Castle: Programmer's Keep,TXT_STRIFE_MAP09,,,,ZÓNA 9: Hrad: Programátorovo doupě,AREA 9: Slot: Programmørens værelse,ZONE 9: Burg: Unterkunft des Programmierers,,AREO 9: Kastelo: Fortikaĵo de Programisto,ÁREA 9: Castillo: Guarida del Programador,,ALUE 9: Linna: Ohjelmoitsijan linnake,ZONE 9: Château: Donjon du Programmeur,9. Terület: Vár: Programozó parcellája,AREA 9: Castello: Dimora del Programmatore,エリア 9: 城内:プログラマーの間,구역 9: 성: 프로그래머의 성채,Zone 9: Kasteel: Onderdak van de programmeur,OMRÅDE 9: Slottet: Programmørens tårn,Strefa 9: Zamek: Baszta Programisty,Área 9: Castelo: Torre do Programador,,ZONA 9: Castel: Cetatea programatorului,МЕСТНОСТЬ 9: Цитадель Программиста,,ALAN 9: Kale: Programcının Kalesi -AREA 10: New Front Base,TXT_STRIFE_MAP10,,,,ZÓNA 10: Nová základna Fronty,AREA 10: Ny frontbase,ZONE 10: Neue Basis der Front,,AREO 10: Nova Frontbazo,ÁREA 10: Nueva Base del Frente,,ALUE 10: Uusi Rintaman tukikohta,ZONE 10: Nouvelle Base du Front,10. Terület: Új első bázis,AREA 10: Nuova Base del Fronte,エリア 10: 新フロント基地,구역 10: 새 프론트 기지,Zone 10: Nieuwe Front basis,OMRÅDE 10: Den nye frontbasen,Strefa 10: Nowa Baza Frontu,Área 10: Nova Base da Frente,,ZONA 10: Noua bază a Frontului,МЕСТНОСТЬ 10: Новая база сопротивления,,ALAN 10: Yeni Ön Taban -AREA 11: Borderlands,TXT_STRIFE_MAP11,,,,ZÓNA 11: Pohraničí,AREA 11: Grænseland,ZONE 11: Grenzgebiete,,AREO 11: Limlando,ÁREA 11: Tierras Fronterizas,,ALUE 11: Rajamaat,ZONE 11: Terres Sauvages,11. Terület: Peremvidék,AREA 11: Lande di Confine,エリア 11: 国境地帯,구역 11: 접경지,Zone 11: Grensgebieden,OMRÅDE 11: Grenseland,Strefa 11: Pogranicze,Área 11: Fronteira,,ZONA 11: Frontiere,МЕСТНОСТЬ 11: Пограничье,,ALAN 11: Sınır Bölgeleri -AREA 12: The Temple of the Oracle,TXT_STRIFE_MAP12,,,,ZÓNA 12: Věštcův chrám,AREA 12: Oraklets tempel,ZONE 12: Der Tempel des Orakels,,AREO 12: La Templo de La Orakolo,ÁREA 12: El Templo del Oráculo,,ALUE 12: Oraakkelin temppeli,ZONE 12: Temple de l'Oracle,12. Terület: Az Orákulum Temploma,AREA 12: Il Tempio dell'Oracolo,エリア 12: オラクルの神殿,구역 12: 오라클의 신전,Zone 12: De tempel van het Orakel,OMRÅDE 12: Orakelets tempel,Strefa 12: Świątynia Wyroczni,Área 12: O Templo do Oráculo,,ZONA 12: Templul Oracolului,МЕСТНОСТЬ 12: Храм Оракула,,ALAN 12: Kahin Tapınağı -AREA 13: Catacombs,TXT_STRIFE_MAP13,,,,ZÓNA 13: Katakomby,AREA 13: Katakomberne,ZONE 13: Katakomben,,AREO 13: Katakombo,ÁREA 13: Catacumbas,,ALUE 13: Katakombit,ZONE 13: Catacombes,13. Terület: Katakombák,AREA 13: Catacombe,エリア 13: 地下墓所,구역 13: 고대 묘지,Zone 13: Catacomben,OMRÅDE 13: Katakombene,Strefa 13: Katakumby,Área 13: Catacumbas,Área 13: Túmulos,ZONA 13: Catacombe,МЕСТНОСТЬ 13: Катакомбы,,ALAN 13: Yeraltı Mezarları -AREA 14: Mines,TXT_STRIFE_MAP14,,,,ZÓNA 14: Doly,AREA 14: Miner,ZONE 14: Die Minen,,AREO 14: Minejo,ÁREA 14: Minas,,ALUE 14: Kaivokset,ZONE 14: Mines,14. Terület: Bánya,AREA 14: Miniere,エリア 14: 鉱山,구역 14: 광산,Zone 14: De mijnen,OMRÅDE 14: Minene,Strefa 14: Kopalnia,Área 14: Minas,,ZONA 14: Mine,МЕСТНОСТЬ 14: Шахты,,ALAN 14: Madenler -AREA 15: Fortress: Administration,TXT_STRIFE_MAP15,,,,ZÓNA 15: Pevnost: Administrace,AREA 15: Fæstning: Administration,ZONE 15: Festung: Administration,,AREO 15: Fortreso: Administrejo,ÁREA 15: Fortaleza: Administración,,ALUE 15: Linnoitus: hallinto,ZONE 15: Forteresse: Administration,15. Terület: Erőd: Elbírálás,AREA 15: Fortezza: Amministrazione,エリア 15: 要塞:管理室,구역 15: 요새: 중앙 관리소,Zone 15: Vesting: Administratieve organisatie,OMRÅDE 15: Festningen: Administrasjon,Strefa 15: Forteca: Administracja,Área 15: Fortaleza: Administração,,ZONA 15: Fortăreața: Administrația,МЕСТНОСТЬ 15: Крепость (администрация),,ALAN 15: Kale: Yönetim -AREA 16: Fortress: Bishop's Tower,TXT_STRIFE_MAP16,,,,ZÓNA 16: Pevnost: Biskupova věž,AREA 16: Fæstning: Biskoppens tårn,ZONE 16: Festung: Bischofsturm,,AREO 16: Fortreso: Turo de Episkopo,ÁREA 16: Fortaleza: Torre del Obispo,,ALUE 16: Linnoitus: Piispan torni,ZONE 16: Forteresse: Tour de l'évèque,16. Terület: Erőd: Püspök tornya,AREA 16: Fortezza: Torre del Vescovo,エリア 16: 要塞:ビショップの塔,구역 16: 요새: 비숍의 탑,Zone 16: Vesting: Bisschopstoren,OMRÅDE 16: Festningen: Biskopens tårn,Strefa 16: Forteca: Wieża Biskupa,Área 16: Fortaleza: Torre do Bispo,,ZONA 16: Fortăreața: Turnul Episcopului,МЕСТНОСТЬ 16: Крепость (башня Епископа),,ALAN 16: Kale: Piskopos Kulesi -AREA 17: Fortress: The Bailey,TXT_STRIFE_MAP17,,,,ZÓNA 17: Pevnost: Předhradí,AREA 17: Fæstning: Bailey,ZONE 17: Festung: Vorhof,,AREO 17: Fortreso: La Murego,ÁREA 17: Fortaleza: El Patio,,ALUE 17: Linnoitus: linnanpiha,ZONE 17: Forteresse: Mur d'enceinte,17. Terület: Erőd: Várfal,AREA 17: Fortezza: Bastione,エリア 17: 要塞:ベイリー,구역 17: 요새: 안뜰,Zone 17: Vesting: Voorplein,OMRÅDE 17: Festningen: Borggården,Strefa 17: Forteca: Mur Obronny,Área 17: Fortaleza: O Pátio,,ZONA 17: Fortăreața: Curte,МЕСТНОСТЬ 17: Крепость (двор),,ALAN 17: Kale: Dış avlu -AREA 18: Fortress: Stores,TXT_STRIFE_MAP18,,,,ZÓNA 18: Pevnost: Sklady,AREA 18: Fæstning: Magasiner,ZONE 18: Festung: Lager,,AREO 18: Fortreso: Stokejoj,ÁREA 18: Fortaleza: Almacenes,,ALUE 18: Linnoitus: varastot,ZONE 18: Forteresse: Réserves,18. Terület: Erőd: Üzletek,AREA 18: Fortezza: Negozi,エリア 18: 要塞:商店,구역 18: 요새: 격납고,Zone 18: Vesting: Lager,OMRÅDE 18: Festningen: Lagrene,Strefa 18: Forteca: Sklepy,Área 18: Fortaleza: Reservas,,ZONA 18: Fortăreața: Depozite,МЕСТНОСТЬ 18: Крепость (склады),,ALAN 18: Kale: Mağazalar -AREA 19: Fortress: Security Complex,TXT_STRIFE_MAP19,,,,ZÓNA 19: Pevnost: Bezpečnostní komplex,AREA 19: Fæstning: Sikkerhedskompleks,ZONE 19: Festung: Sicherheitsanlage,,AREO 19: Fortreso: Sekurkomplekso,ÁREA 19: Fortaleza: Complejo de Seguridad,,ALUE 19: Linnoitus: turvallisuuskeskus,ZONE 19: Forteresse: Complexe Sécurité,19. Terület: Erőd: Biztonsági Részleg,AREA 19: Fortezza: Complesso di Sicurezza,エリア 19: 要塞:複合警備所,구역 19: 요새: 보안 담당 기지,Zone 19: Vesting: Beveiligingssysteem,OMRÅDE 19: Festningen: Sikkerhetskomplekset,Strefa 19: Forteca: Kompleks Ochronny,Área 19: Fortaleza: Complexo de Segurança,,ZONA 19: Fortăreața: Complex de securitate,МЕСТНОСТЬ 19: Крепость (охранный комплекс),,ALAN 19: Kale: Güvenlik Kompleksi -AREA 20: Factory: Receiving,TXT_STRIFE_MAP20,,,,ZÓNA 20: Továrna: Příjem,AREA 20: Fabrik: Modtagelse,ZONE 20: Fabrik: Empfang,,AREO 20: Fabrikejo: Ricevejo,ÁREA 20: Fábrica: Recepción,,ALUE 20: Tehdas: vastaanotto,ZONE 20: Usine: Réception,20. Terület: Gyár: Beérkeztető,AREA 20: Fabbrica: Ricevimento,"エリア 20: 工場:受取所 -",구역 20: 공장: 수납구역,Zone 20: Fabriek: Ontvangst,OMRÅDE 20: Fabrikken: Mottak,Strefa 20: Fabryka: Odbiór,Área 20: Fábrica: Recebimento,,ZONA 20: Fabrica: Recepție,МЕСТНОСТЬ 20: Фабрика (приём),,ALAN 20: Fabrika: Teslim Alma -AREA 21: Factory: Manufacturing,TXT_STRIFE_MAP21,,,,ZÓNA 21: Továrna: Výroba,AREA 21: Fabrik: Fremstilling,ZONE 21: Fabrik: Herstellung,,AREO 21: Fabrikejo,ÁREA 21: Fábrica: Manufactura,,ALUE 21: Tehdas: tuotanto,ZONE 21: Usine: Manufacture,21. Terület: Gyár: Gyártósor,AREA 21: Fabbrica: Manifattura,エリア 21: 工場:製造機関,구역 21: 공장: 조립시설,Zone 21: Fabriek: Productie,OMRÅDE 21: Fabrikk: Produksjon,Strefa 21: Fabryka: Przetwórstwo,Área 21: Fábrica: Manufatura,,ZONA 21: Fabrica: Procesare,МЕСТНОСТЬ 21: Фабрика (производство),,ALAN 21: Fabrika: İmalat -AREA 22: Factory: Forge,TXT_STRIFE_MAP22,,,,ZÓNA 22: Továrna: Slévárna,AREA 22: Fabrik: Smedje,ZONE 22: Fabrik: Schmiede,,AREO 22: Fabrikejo: Forĝejo,ÁREA 22: Fábrica: Forja,,ALUE 22 Tehdas: paja,ZONE 22: Usine: Forge,22. Terület: Gyár: Kohó,AREA 22: Fabbrica: Fucina,エリア 22: 工場:鉄工所,구역 22: 공장: 제련소,Zone 22: Fabriek: Smederij,OMRÅDE 22: Fabrikk: Smie,Strefa 22: Fabryka: Kuźnia,Área 22: Fábrica: Forja,,ZONA 22: Fabrica: Forja,МЕСТНОСТЬ 22: Фабрика (кузня),,ALAN 22: Fabrika: Demirhane -AREA 23: Order Commons,TXT_STRIFE_MAP23,,,,ZÓNA 23: Náves Řádu,AREA 23: Bestillingscentral,ZONE 23: Mensa des Ordens,,AREO 23: Komunejo de La Ordeno,ÁREA 23: Condominios de la Orden,,ALUE 23: Veljeskunnan messi,ZONE 23: Mess de l'Ordre,23. Terület: Rendi köztér,AREA 23: Camera dell'Ordine,エリア 23: オーダーコモンズ,구역 23: 오더 식당가,Zone 23: Mensa van de orde,OMRÅDE 23: Bestillingsallmenning,Strefa 23: Wikt Zakonu,Área 23: Câmara da Ordem,,ZONA 23: Decontare comenzi,МЕСТНОСТЬ 23: Поселение Ордена,,ALAN 23: Siparişin ortak alanı -AREA 24: Factory: Conversion Chapel,TXT_STRIFE_MAP24,,,,ZÓNA 24: Továrna: Kaple konverze,AREA 24: Fabrik: Omdannelseskapel,ZONE 24: Umwandlungskapelle,,AREO 24: Fabrikejo: Konvert-Kapelo,ÁREA 24: Fábrica: Capilla de Conversión,,ALUE 24: Tehdas: käännytyskappeli,ZONE 24: Usine: Chapelle de Conversion,24. Terület: A megtérés kápolnája,AREA 24: Fabbrica: Cappella di Conversione,エリア 24: 工場:改宗礼拝堂,구역 24: 공장: 전향실,Zone 24: Verbouwingskapel,OMRÅDE 24: Fabrikk: Konverteringskapell,Strefa 24: Fabryka: Kaplica Przemiany,Área 24: Fábrica: Capela de Conversão,,ZONA 24: Fabrica: Capela de conversie,МЕСТНОСТЬ 24: Фабрика (часовня обращения),,ALAN 24: Fabrika: Dönüşüm Şapeli -AREA 25: Catacombs: Ruined Temple,TXT_STRIFE_MAP25,,,,ZÓNA 25: Katakomby: Zničený chrám,AREA 25: Katakomberne: Ruineret tempel,ZONE 25: Katakomben: Zerstörter Tempel,,AREO: 25: Katakombo: Ruiniga Templo,ÁREA 25: Catacumbas: Templo Arruinado,,ALUE 25: Katakombit: temppeliraunio,ZONE 25: Catacombes: Temple Ruiné,25. Terület: Katakombák: Romtemplom,AREA 25: Catacombe: Tempio in Rovina,エリア 25: 地下墓所:没落した寺院,구역 25: 고대 묘지: 무너진 사원,Zone 25: Catacomben: Vernietigde tempel,OMRÅDE 25: Katakombene: Ruinert tempel,Strefa 25: Katakumby: Zrujnowana Świątynia,Área 25: Catacumbas: Templo Arruinado,Área 25: Túmulos: Templo Arruinado,ZONA 25: Catacombe: Templu în ruine,МЕСТНОСТЬ 25: Катакомбы (руины храма),,ALAN 25: Yeraltı Mezarları: Yıkık Tapınak -AREA 26: Proving Grounds,TXT_STRIFE_MAP26,,,,ZÓNA 26: Vojenský újezd,AREA 26: Prøvesteder,ZONE 26: Testgelände,,AREO 26: Provejo,ÁREA 26: Campo de Pruebas,,ALUE 26: Koetuspaikka,ZONE 26: Terrain d'entraînement,26. Terület: Próbatételek Földje,AREA 26: Banco di Prova,エリア 26: 試練場,구역 26: 증명의 전장,Zone 26: Testgebied,OMRÅDE 26: Prøveplassen,Strefa 26: Poligon Wojskowy,Área 26: Campo de Treinamento,Área 26: Campo de Treino,ZONA 26: Tabăra de instruire,МЕСТНОСТЬ 26: Испытательный полигон,,ALAN 26: Kanıtlama Alanları -AREA 27: The Lab,TXT_STRIFE_MAP27,,,,ZÓNA 27: Laboratoř,AREA 27: Laboratoriet,ZONE 27: Das Labor,,AREO 27: La Labotorio,ÁREA 27: El Laboratorio,,ALUE 27: Laboratorio,ZONE 27: Laboratoire,27. Terület: A labor,AREA 27: Il Laboratorio,エリア 27: 研究所,구역 27: 연구소,Zone 27: Het laboratorium,OMRÅDE 27: Laboratoriet,Strefa 27: Laboratorium,Área 27: O Laboratório,,ZONA 27: Laboratorul,МЕСТНОСТЬ 27: Лаборатория,,ALAN 27: Laboratuvar -AREA 28: Alien Ship,TXT_STRIFE_MAP28,,,,ZÓNA 28: Mimozemská loď,AREA 28: Fremmed skib,ZONE 28: Außerirdisches Schiff,,AREO 28: Alilanda Ŝipo,ÁREA 28: Nave Alienígena,,ALUE 28: Muukalaisalus,ZONE 28: Vaisseau Alien,28. Terület: Idegen űrhajó,AREA 28: Nave Aliena,エリア 28: エイリアンの船,구역 28: 외계 우주선,Zone 28: Buitenaards schip,OMRÅDE 28: Det fremmede skipet,Strefa 28: Statek Obcych,Área 28: Nave Alienígena,,ZONA 28: Nava extraterestră,МЕСТНОСТЬ 28: Корабль пришельцев,,ALAN 28: Uzaylı Gemisi -AREA 29: Entity's Lair,TXT_STRIFE_MAP29,,,,ZÓNA 29: Doupě Bytosti,AREA 29: Entitetsnesten,ZONE 29: Das Nest der Entität,,AREO 29: Nestego de Estulo,ÁREA 29: Escondite de la Entidad,,ALUE 29: Tosiolevan maja,ZONE 29: Demeure de L'Entité,29. Terület: A Teremtvény Búvóhelye,AREA 29: Tana dell'Entità,エリア 29: エンティティの隠れ家,구역 29: 엔티티의 소굴,Zone 29: Het nest van de entiteit,OMRÅDE 29: Enhetens hule,Strefa 29: Leże Bytu,Área 29: Covil da Entidade,,ZONA 29: Cuibul Entității,МЕСТНОСТЬ 29: Логово Сущности,,ALAN 29: Varlığın İni -AREA 30: Abandoned Front Base,TXT_STRIFE_MAP30,,,,ZÓNA 30: Opuštěná základna Fronty,AREA 30: Forladt frontbase,ZONE 30: Verlassene Basis der Front,,AREO 30: Forlasita Front-Bazo,ÁREA 30: Base Abandonada del Frente,,ALUE 30: Hylätty Rintaman tukikohta,ZONE 30: Base Abandonnée du Front,30. Terület: Elhagyatott Előbázis,AREA 30: Base del Fronte abbandonata,エリア 30: 放棄された基地,구역 30: 버려진 프론트 기지,Zone 30: Verlaten frontbasis,OMRÅDE 30: Forlatt frontbase,Strefa 30: Opuszczona Baza Frontu,Área 30: Base da Frente Abandonada,,ZONA 30: Baza abandonată a Frontului,МЕСТНОСТЬ 30: Заброшенная база сопротивления,,ALAN 30: Terk Edilmiş Ön Üs -AREA 31: Training Facility,TXT_STRIFE_MAP31,,,,ZÓNA 31: Výcvikové zařízení,AREA 31: Træningsanlæg,ZONE 31: Trainingseinrichtung,,AREO 31: Trejnejo,ÁREA 31: Zona de entrenamiento,,ALUE 31: Koulutuslaitos,ZONE 31: Complexe d'Entraînement,31. Terület: Kiképzőbázis,AREA 31: Struttura di Addestramento,エリア 31: 研修施設,구역 31: 훈련 시설,Zone 31: Trainingsfaciliteit,OMRÅDE 31: Treningsanlegg,Strefa 31: Centrum Szkoleniowe,Área 31: Instalação de Treinamento,,ZONA 31: Spațiul de antrenament,МЕСТНОСТЬ 31: Тренировочный корпус,,ALAN 31: Eğitim Tesisi -AREA 1: Sanctuary,TXT_STRIFE_MAP32,,,,ZÓNA 1: Svatyně,AREA 1: Fristedet,ZONE 1: Heiligtum,,AREO 1: Sanktejo,ÁREA 1: Santuario,,ALUE 1: Pyhäkkö,ZONE 1: Sanctuaire,1. Terület: Szentély,AREA 1: Santuario,エリア 1: 聖域 ,구역 1: 성소,Zone 1: Heiligdom,OMRÅDE 1: Fristedet,Strefa 1: Sanktuarium,Área 1: Santuário,,ZONA 1: Sanctuar,МЕСТНОСТЬ 1: Святилище,,ALAN 1: Sığınak -AREA 2: Town,TXT_STRIFE_MAP33,,,,ZÓNA 2: Město,AREA 2: By,ZONE 2: Stadt,,AREO 2: Urbeto,ÁREA 2: Pueblo,,ALUE 2: Kylä,ZONE 2: Ville,2. Terület: Város,AREA 2: Città,エリア 2: 町,구역 2: 마을,Zone 2: Stad,OMRÅDE 2: By,Strefa 2: Miasto,Área 2: Vila,,ZONA 2: Oraș,МЕСТНОСТЬ 2: Город,,ALAN 2: Şehir -AREA 3: Movement Base,TXT_STRIFE_MAP34,,,,ZÓNA 3: Rebelská základna,AREA 3: Front Basis,ZONE 3: Rebellenbasis,,AREO 3: Movad-Bazo,ÁREA 3: Base del Movimiento,,ALUE 3: Liikkeen tukikohta,ZONE 3: Base du Front,3. Terület: Mozgalmi Bázis,AREA 3: Base del Movimento,エリア 3: 移転基地,구역 3: 반군 기지,Zone 3: Front basis,OMRÅDE 3: Bevegelsesbase,Strefa 3: Baza Ruchu Oporu,Área 3: Base do Movimento,,ZONA 3: Baza rezistenței,МЕСТНОСТЬ 3: База сопротивления,,ALAN 3: Hareket Üssü -AREA 35: Factory: Production,TXT_STRIFE_MAP35,,,,ZÓNA 35: Továrna: Produkce,AREA 35: Fabrik: Produktion,ZONE 35: Fabrik: Produktion,,AREO 35: Fabrikejo: Produktejo,ÁREA 35: Fábrica: Producción,,ALUE 35: Tehdas: tuotanto,ZONE 35: Usine: Production,35. Terület: Gyár: Termelés,AREA 35: Fabbrica: Produzione,エリア 35: 工場 : 生産ライン,구역 35: 공장: 제작실,Zone 35: Fabriek: Productie,OMRÅDE 35: Fabrikk: Produksjon,Strefa 35: Fabryka: Produkcja,Área 35: Fábrica: Produção,,ZONA 35: Fabrica: Producție,МЕСТНОСТЬ 35: Фабрика (производство),,ALAN 35: Fabrika: Üretim -AREA 36: Castle Clash,TXT_STRIFE_MAP36,,,,ZÓNA 36: Střet na hradě,AREA 36: Slotskampe,ZONE 36: Burg-Konflikt,,AREO 36: Batalo ĉe Kastelo,ÁREA 36: Ataque al Castillo,,ALUE 36: Linnayhteenotto,ZONE 36: Bataille du Château,36: Terület: Vári ütközet,AREA 36: Collisione di Castello,エリア 36: キャッスルクラッシュ,구역 36: 성채간의 충돌,Zone 36: Kasteelconflict,OMRÅDE 36: Slottskampen,Strefa 36: Potyczka w Zamku,Área 36: Ataque ao Castelo,,ZONA 36: Bătălia castelului,МЕСТНОСТЬ 36: Битва в замке,,ALAN 36: Kale Çatışması -AREA 37: Killing Grounds,TXT_STRIFE_MAP37,,,,ZÓNA 37: Popravčí zahrady,AREA 37: Drabsområder,ZONE 37: Kampfgelände,,AREO 37: Tereno de Mortigado,ÁREA 37: Campo de Matanza,,ALUE 37: Tappotanner,ZONE 37: Zone de Chasse,37. Terület: Gyilkos Vidék,AREA 37: Campi di Uccisione,エリア 37: 殺害者の地,구역 37: 살육의 전장,Zone 37: Slagveld,OMRÅDE 37: Drapsplasser,Strefa 37: Śmiercionośny Grunt,Área 37: Campo de Matança,,ZONA 37: Teren de ucis,МЕСТНОСТЬ 37: Сектора обстрела,,ALAN 37: Öldürme Alanları -AREA 38: Ordered Chaos,TXT_STRIFE_MAP38,,,,ZÓNA 38: Nařízený chaos,AREA 38: Ordnet kaos,ZONE 38: Geordnetes Chaos,,AREO 38: Orda Kaoso,ÁREA 38: Caos Ordenado,,ALUE 38: Järjestynyt kaaos,ZONE 38: Chaos Ordonné,38. Terület: Rendezett Káosz,AREA 38: Caos Ordinato,エリア 38: カオスの秩序,구역 38: 정돈된 혼란,Zone 38: Ordelijke chaos,OMRÅDE 38: Ordnet kaos,Strefa 38: Uporządkowany Chaos,Área 38: Caos Ordenado,,ZONA 38: Haos controlat,МЕСТНОСТЬ 38: Управляемый хаос,,ALAN 38: Düzenli Kaos -,,Hexen,,,,,,,,,,,,,,,,,,,,,,,, -Winnowing Hall,TXT_HEXEN_MAP01,,,,Sál prosetí,Separationshal,Trennungshalle,,Solenejo de Separado,Sala de los Vientos,,Viskaussali,Chambre de la Séparation,Huzatos Folyosó,Camera di separazione,選抜の間,바람 회관,Scheidingszaal,Vinnersalen,Hala Przesiewu,Sala de Separação,,Sala de Separare,Зал отсеивания,Предсобље просејавања,Ayrılma Salonu -Seven Portals,TXT_HEXEN_MAP02,,,,Sedmero portálů,Syv portaler,Sieben Portale,,Sep Portaloj,Siete Portales,,Seitsemän portaalia,Les Sept Portails,Hét Portál,I Sette Portali,漆之門,일곱 차원문,Zeven portalen,Syv portaler,Siedem Portali,Sete Portais,,Șapte Portaluri,Семь порталов,Седам портала,Yedi Portal -Guardian of Ice,TXT_HEXEN_MAP03,,,,Strážce ledu,Vogter af is,Wächter des Eises,,Gardanto de Glacio,Guardián de Hielo,,Jään vartija,Gardien de Glace,A Jég Őre,Guardiano del Ghiaccio,氷の守護者,얼음의 수호자,Bewaker van ijs,Isens vokter,Strażnik Lodu,Guardião de Gelo,,Străjerul Gheții,Страж льда,Чувар леда,Buz Muhafızı -Guardian of Fire,TXT_HEXEN_MAP04,,,,Strážce ohně,Vogter af ild,Wächter des Feuers,,Gardanto de Fajro,Guardián de Fuego,,Tulen vartija,Gardien de Feu,A Tűz Őre,Guardiano del Fuoco,炎の守護者,화염의 수호자,Bewaker van vuur,Ildens vokter,Strażnik Ognia,Guardião de Fogo,,Străjerul Focului,Страж огня,Чувар огња,Ateşin Koruyucusu -Guardian of Steel,TXT_HEXEN_MAP05,,,,Strážce oceli,Vogter af stål,Wächter des Stahls,,Gardanto de Ŝtalo,Guardián de Acero,,Teräksen vartija,Gardien d'Acier,Az Acél Őre,Guardiano dell'Acciaio,鋼の守護者,강철의 수호자,Bewaker van staal,Stålets vokter,Strażnik Stali,Guardião de Aço,,Străjerul Oțelului,Страж стали,Чувар челика,Çelik Muhafız -Bright Crucible,TXT_HEXEN_MAP06,,,,Světlý očistec,Lys udfordring,Glänzende Feuerprobe,,Luma Krisolo,Crisol de Luz,,Kirkas tulikoe,Creuset Radiant,Fényes Ketrec,Crogiolo Luminoso,光の坩堝,빛나는 고난,Heldere beproeving,Lys utfordring,Tygiel Światła,Crisol de Luz,,Creuzet Luminos,Горнило света,Испит светла,Parlak Pota -Shadow Wood,TXT_HEXEN_MAP13,,,,Temný hvozd,Skyggetræ,Schattenwald,,Ombro-Arbareto,Bosque de la Sombra,,Varjosalo,Forêt des Ombres,Árnyék Erdő,Foresta Oscura,陰影樹,그림자 숲,Schaduwbos,Skyggeskogen,Las Cieni,Floresta das Sombras,,Pădurea Umbrelor,Лес теней,Шума сенки,Gölge Ahşap -Darkmere,TXT_HEXEN_MAP08,,,,Černý močál,,Düstersee,,Malluma Marĉo,Pantano,,Pikiräme,Marais Noir,Fekete Mocsár,Palude Nera,暗黒の地,흙빛호수,Sombermeer,,Mroczne Bagno,Pantâno Negro,,Mlaștinile Întunecate,Болотная топь,Мочварна земља,Koyu göl -Caves of Circe,TXT_HEXEN_MAP09,,,,Kirčiny jeskyně,Circes' grotter,Circes Höhle,,Kavernoj de Circe,Cuevas de Circe,,Circeluolat,Caves de Circé,Körök Barlangja,Grotte di Circe,キルケーの洞窟,키르케의 동굴,Grotten van Circe,Circes grotter,Jaskinie Kirke,Cavernas de Circe,,Peșterile lui Circe,Пещеры Цирцеи,Киркине пећине,Kirke Mağaraları -Wastelands,TXT_HEXEN_MAP10,,,,Pustiny,Ødemarker,Ödland,,Senvivejo,Yermo,,Erämaat,Terres Ruinées,Senkiföldje,Terre in rovina,荒野,황무지,Woestenij,Ødemarken,Pustkowia,Terras Desoladas,,Tărâmurile Pustii,Пустоши,Пустоши,Çorak Topraklar -Sacred Grove,TXT_HEXEN_MAP11,,,,Posvátný háj,Helliglund,Heiliger Hain,,Sankta Bosketo,Arboleda Sagrada,,Pyhä metsikkö,Bosquet Sacré,Szent Liget,Boschetto Sacro,神聖なる園,성스러운 수풀,Heilig bosje,Hellig lund,Święty Gaj,Bosque Sagrado,,Crângul Sacru,Священная роща,Свети шумарак,Kutsal Koru -Hypostyle,TXT_HEXEN_MAP12,,,,Hypostyl,,Säulenhalle,,Kolonejo,Hipóstila,,Hypostyyli,Hypostyle,Oszlopterem,Ipostilo,多柱の間,다주실,Zuilenhal,,Hypostyl,Hipostilo,,Hipostil,Гипостильный зал,Хипостил,Hipostil -Heresiarch's Seminary,TXT_HEXEN_MAP27,,,,Arcikacířův alumnát,Heresiarkens seminarium,Seminar des Erzketzers,,Seminario de Ĉefherezulo,Seminario del Heresiarca,,Kerettiarkin seminaari,Séminaire de l'Hérésiarche,A Főeretnek Neveldéje,Seminario dell'Heresiarch,ヘレシアークの神学舎,헤러시아크의 신학교,Seminarie van ketterij,Heresiarkens seminar,Seminarium Herezjarchy,Seminário do Heresiarca,,Seminarul Ereziarhului,Семинария Ересиарха,Јересијархов семинар,Heresiark'ın Ruhban Okulu -Dragon Chapel,TXT_HEXEN_MAP28,,,,Dračí kaple,Dragekapel,Drachenkapelle,,Drakkapelo,Capilla Dragón,,Lohikäärmekappeli,Chapelle du Dragon,Sárkány Szentély,Cappella del Drago,ドラゴンの庵寺,드래곤 예배실,Drakenkapel,Dragekapell,Kaplica Smoka,Capela do Dragão,,Capela dragonilor,Часовня дракона,Капела змајева,Ejderha Şapeli -Griffin Chapel,TXT_HEXEN_MAP30,,,,Gryfova kaple,Griffinkapel,Greifenkapelle,,Grifkapelo,Capilla Grifo,,Aarnikotkakappeli,Chapelle du Grifon,Griff Szentély,Cappella del Grifone,グリフィンの庵寺,그리핀 예배실,Griffioenenkapel,Griffon kapell,Kaplica Gryfa,Capela do Grifo,,Capela grifonilor,Часовня грифона,Капела грифонова,Griffin Şapeli -Deathwind Chapel,TXT_HEXEN_MAP31,,,,Kaple mrakosmrtě,Dødens vind kapel,Todeswindkapelle,,Mortvento-Kapelo,Capilla Viento de Muerte,,Kuolontuulikappeli,Chapelle du Vent Tueur,Halál Szentély,Cappella del Vento Assassino,デスウィンドの庵寺,죽음바람 예배실,Dodenwind kapel,Dødens vind kapell,Kaplica Wiatru Śmierci,Capela do Vento da Morte,,Capela suflului morții,Часовня ветра смерти,Капела ветра смрти,Ölüm Rüzgarı Şapeli -Orchard of Lamentations,TXT_HEXEN_MAP32,,,,Sad nářků,Klagesangens frugthave,Garten der Wehklagen,,Horto de Lamentoj,Huerto de los Lamentos,,Valitusvirtten tarha,Verger des Lamentations,Siránkozás Kertje,Frutteto delle Lamentazioni,哀悼茂る園,통탄의 과수원,Boomgaard van klaagliederen,Klagesangens hage,Płaczący Sad,Pomar das Lamentações,,Livada amărăciunii,Сады плача,Воћњак плача,Ağıtlar Bahçesi -Silent Refectory,TXT_HEXEN_MAP33,,,,Tichý refektář,Stilhedens refektorium,Stilles Refektorium,,Silenta Manĝejo,Refectorio Silencioso,,Hiljainen ruokasali,Réfectoire Silencieux,Néma Refektórium,Refettorio silenzioso,寡黙なる食堂,침묵의 식당,Stil refectory,Stille refektorium,Cichy Refektarz,Refeitório Silencioso,,Refectoriul tăcerii,Безмолвная трапезная,Безгласна трпезарија,Sessiz Yemekhane -Wolf Chapel,TXT_HEXEN_MAP34,,,,Vlčí kaple,Ulvekapel,Wolfskapelle,,Lupkapelo,Capilla Lobo,,Susikappeli,Chapelle du Loup,Farkas Szentély,Cappella del Lupo,狼の庵寺,늑대 예배실,Wolvenkapel,Ulvens kapell,Kaplica Wilka,Capela do Lobo,,Capela lupilor,Часовня волка,Капела вучја,Kurt Şapeli -Forsaken Outpost,TXT_HEXEN_MAP21,,,,Opuštěné stanoviště,Forladt forpost,Verlassener Vorposten,,Forlasita Posteno,Puesto de Avanzada Abandonado,,Hylätty etuvartio,Base Abandonnée,Elhagyott Őrség,Avamposto Abbandonato,荒れ果てた前哨地,버려진 초소,Verwaarloosde buitenpost,Forlatt utpost,Opuszczony Posterunek,Posto Abandonado,,Avanpostul părăsit,Покинутая застава,Напуштена постаја,Unutulmuş Karakol -Castle of Grief,TXT_HEXEN_MAP22,,,,Hrad smutku,Sorgens slot,Leidensburg,,Kastelo de Funebro,Castillo del Pesar,,Surulinna,Château de la Souffrance,A Gyász Kastélya,Castello della Sofferenza,嘆きの城,비탄의 성,Kasteel van verdriet,Sorgens slott,Zamek Smutku,Castelo da Aflição,,Castelul întristării,Замок скорби,Замак жалости,Keder Kalesi -Gibbet,TXT_HEXEN_MAP23,,,,Šibenice,,Richtstätte,,Pendigilo,Horca,,Hirsipuu,Gibet,Akasztófa,Forca,晒し台,교수대,,Galgen,Szubienica,Forca,,Eșafodul,Виселица,Вешала,İnfaz yeri -Effluvium,TXT_HEXEN_MAP24,,,,Výpary,,Effluvium,,Efluvo,Efluvio,,Katku,Effluvium,A Bűz Börtöne,Effluvio,腐臭漂う残骸,악취,,,Odór,Eflúvio,,Efluviu,Зловонный сток,Воњави одвод,Atık Su -Dungeons,TXT_HEXEN_MAP25,,,,Žalář,Fangehuller,Kerker,,Karceroj,Calabozos,,Tyrmät,Donjons,Kazamaták,I Dungeon,地下牢,지하감옥,Kerkers,Fangehull,Lochy,Masmorras,,Temnițe,Подземелья,Лагуми,Zindanlar -Desolate Garden,TXT_HEXEN_MAP26,,,,Zpustošená zahrada,Ødelagt have,Verwildeter Garten,,Dezerta Ĝardeno,Jardín Desolado,,Autio puutarha,Jardin de la Désolation,Sivár Kert,Giardino Desolato,荒涼とした庭,황폐한 정원,Woeste tuin,Øde hage,Spustoszały Ogród,Jardim Desolado,,Grădina dezolantă,Заброшенный сад,Напуштени врт,Issız Bahçe -Necropolis,TXT_HEXEN_MAP35,,,,Nekropole,Nekropolis,Nekropole,,Nekropolo,Necrópolis,,Nekropoli,Nécropole,Nekropolisz,Necropoli,ネクロポリス,망자의 도시,,Nekropolis,Nekropolia,Necrópole,,Necropola,Некрополь,Некропола,Nekropol -Zedek's Tomb,TXT_HEXEN_MAP36,,,,Zedekova hrobka,Zedeks grav,Zedeks Gruft,,Tombo de Zedek,Tumba de Zedek,,Sedekin hauta,Tombeau de Zedek,Zedek Sírja,Tomba di Zedek,ゼデクの墓,제닥의 무덤,Zedek's graf,Zedeks grav,Grobowiec Zedeka,Tumba de Zedek,Túmulo de Zedek,Mormântul lui Zedek,Гробница Зедека,Гробница Зедекова,Zedek'in Mezarı -Menelkir's Tomb,TXT_HEXEN_MAP37,,,,Menelkirova hrobka,Menelkirs grav,Menelkirs Gruft,,Tombo de Menelkir,Tumba de Menelkir,,Menelkirin hauta,Tombeau de Menelkir,Menelkir Sírja,Tomba di Menelkir,メネルキルの墓,메넬키어의 무덤,Menelkir's graf,Menelkirs grav,Grobowiec Menelkira,Tumba de Menelkir,Túmulo de Menelkir,Mormântul lui Menelkir,Гробница Менелкира,Гробница Менелкирова,Menelkir'in Mezarı -Traductus' Tomb,TXT_HEXEN_MAP38,,,,Traduktova hrobka,Traductus' grav,Traductus' Gruft,,Tombo de Traductus,Tumba de Traductus,,Traduktuksen hauta,Tombeau de Traductus,Traductus Sírja,Tomba di Traductus,トダクティスの墓,트라닥투스의 무덤,Traductus' graf,Traductus' grav,Grobowiec Traduktusa,Tumba de Traductus,Túmulo de Traductus,Mormântul lui Traductus,Гробница Традактуса,Гробница Традуктусова,Traductus'un Mezarı -Vivarium,TXT_HEXEN_MAP39,,,,Vivárium,,Vivarium,,Vivario,Vivario,,Vivaario,Vivarium,Vivárium,Vivario,ビバリウム,사육장,,,Wiwarium,Viveiro,,Vivariu,Виварий,Виваријум,Vivarium +",구역 2: 마을,Zone 2: Stad,OMRÅDE 2: Byen,Strefa 2: Miasto,Área 2: Vila,,ZONA 2: Oraș,МЕСТНОСТЬ 2: Город,,OMRÅDE 2: Staden,ALAN 2: Şehir +AREA 3: Front Base,TXT_STRIFE_MAP03,,,,ZÓNA 3: Základna Fronty,AREA 3: Front Basis,ZONE 3: Basis der Front,,AREO 3: Front-Bazo,ÁREA 3: Base del Frente,,ALUE 3: Rintaman tukikohta,ZONE 3: Base du Front,3. Terület: Elülső bázis,AREA 3: Base del Fronte,エリア 3: フロント基地,구역 3: 프론트 기지,Zone 3: Front basis,OMRÅDE 3: Frontbase,Strefa 3: Baza Frontu,Área 3: Base da Frente,,ZONA 3: Baza Frontului,МЕСТНОСТЬ 3: База сопротивления,,OMRÅDE 3: Frontbasen,ALAN 3: Ön Taban +AREA 4: Power Station,TXT_STRIFE_MAP04,,,,ZÓNA 4: Elektrárna,AREA 4: Kraftværk,ZONE 4: Kraftwerk,,AREO 4: Elektrocentralo,ÁREA 4: Central eléctrica,,ALUE 4: Voimalaitos,ZONE 4: Centrale,4. Terület: Erőmű,AREA 4: Centrale Elettrica,エリア 4: 発電所,구역 4: 발전소,Zone 4: Energiecentrale,OMRÅDE 4: Kraftstasjon,Strefa 4: Elektrownia,Área 4: Usina de Energia,Área 4: Central Energética,ZONA 4: Centrala,МЕСТНОСТЬ 4: Электростанция,,OMRÅDE 4: Kraftverk,ALAN 4: Elektrik Santrali +AREA 5: Prison,TXT_STRIFE_MAP05,,,,ZÓNA 5: Vězení,AREA 5: Fængsel,ZONE 5: Gefängnis,,AREO 5: Malliberejo,ÁREA 5: Prisión,,ALUE 5: Vankila,ZONE 5: Prison,5. Terület: Börtön,AREA 5: Carcere,エリア 5: 刑務所,구역 5: 감옥,Zone 5: Gevangenis,OMRÅDE 5: Fengsel,Strefa 5: Więzienie,Área 5: Prisão,,ZONA 5: Închisoare,МЕСТНОСТЬ 5: Тюрьма,,OMRÅDE 5: Fängelse,ALAN 5: Cezaevi +AREA 6: Sewers,TXT_STRIFE_MAP06,,,,ZÓNA 6: Stoky,AREA 6: Kloakkerne,ZONE 6: Kanalisation,,AREO 6: Kloako,ÁREA 6: Alcantarillas,,ALUE 6: Viemärit,ZONE 6: Egouts,6. Terület: Kanális,AREA 6: Fogne,エリア 6: 下水道,구역 6: 하수도,Zone 6: Riolering,OMRÅDE 6: Kloakk,Strefa 6: Kanały,Área 6: Esgoto,,ZONA 6: Canal,МЕСТНОСТЬ 6: Канализация,,OMRÅDE 6: Avloppsledningar,ALAN 6: Kanalizasyonlar +AREA 7: Castle,TXT_STRIFE_MAP07,,,,ZÓNA 7: Hrad,AREA 7: Slot,ZONE 7: Burg,,AREO 7: Kastelo,ÁREA 7: Castillo,,ALUE 7: Linna,ZONE 7: Château,7. Terület: Vár,AREA 7: Castello,エリア 7: 城,구역 7: 성,Zone 7: Kasteel,OMRÅDE 7: Slottet,Strefa 7: Zamek,Área 7: Castelo,,ZONA 7: Castel,МЕСТНОСТЬ 7: Замок,,OMRÅDE 7: Slott,ALAN 7: Kale +AREA 8: Audience Chamber,TXT_STRIFE_MAP08,,,,ZÓNA 8: Audienční sál,AREA 8: Audience Chamber,ZONE 8: Audienzsaal,,AREO 8: Juĝejo,ÁREA 8: Sala de audiencias,,ALUE 8: Yleisösali,ZONE 8: Chambre d'Audience,8. Terület: Nézőtér,AREA 8: Sala delle Udienze,エリア 8: 観客席,구역 8: 알현실,Zone 8: Auditorium,OMRÅDE 8: Audienssalen,Strefa 8: Izba Audiencji,Área 8: Câmara de Audiências,,ZONA 8: Camera de audiențe,МЕСТНОСТЬ 8: Приёмная,,OMRÅDE 8: Publikrum,ALAN 8: İzleyici Odası +AREA 9: Castle: Programmer's Keep,TXT_STRIFE_MAP09,,,,ZÓNA 9: Hrad: Programátorovo doupě,AREA 9: Slot: Programmørens værelse,ZONE 9: Burg: Unterkunft des Programmierers,,AREO 9: Kastelo: Fortikaĵo de Programisto,ÁREA 9: Castillo: Guarida del Programador,,ALUE 9: Linna: Ohjelmoitsijan linnake,ZONE 9: Château: Donjon du Programmeur,9. Terület: Vár: Programozó parcellája,AREA 9: Castello: Dimora del Programmatore,エリア 9: 城内:プログラマーの間,구역 9: 성: 프로그래머의 성채,Zone 9: Kasteel: Onderdak van de programmeur,OMRÅDE 9: Slottet: Programmørens tårn,Strefa 9: Zamek: Baszta Programisty,Área 9: Castelo: Torre do Programador,,ZONA 9: Castel: Cetatea programatorului,МЕСТНОСТЬ 9: Цитадель Программиста,,OMRÅDE 9: Programmerarens behållning,ALAN 9: Kale: Programcının Kalesi +AREA 10: New Front Base,TXT_STRIFE_MAP10,,,,ZÓNA 10: Nová základna Fronty,AREA 10: Ny frontbase,ZONE 10: Neue Basis der Front,,AREO 10: Nova Frontbazo,ÁREA 10: Nueva base del Frente,,ALUE 10: Uusi Rintaman tukikohta,ZONE 10: Nouvelle Base du Front,10. Terület: Új első bázis,AREA 10: Nuova Base del Fronte,エリア 10: 新フロント基地,구역 10: 새 프론트 기지,Zone 10: Nieuwe Front basis,OMRÅDE 10: Den nye frontbasen,Strefa 10: Nowa Baza Frontu,Área 10: Nova Base da Frente,,ZONA 10: Noua bază a Frontului,МЕСТНОСТЬ 10: Новая база сопротивления,,OMRÅDE 10: Ny frontbas,ALAN 10: Yeni Ön Taban +AREA 11: Borderlands,TXT_STRIFE_MAP11,,,,ZÓNA 11: Pohraničí,AREA 11: Grænseland,ZONE 11: Grenzgebiete,,AREO 11: Limlando,ÁREA 11: Tierras fronterizas,,ALUE 11: Rajamaat,ZONE 11: Terres Sauvages,11. Terület: Peremvidék,AREA 11: Lande di Confine,エリア 11: 国境地帯,구역 11: 접경지,Zone 11: Grensgebieden,OMRÅDE 11: Grenseland,Strefa 11: Pogranicze,Área 11: Fronteira,,ZONA 11: Frontiere,МЕСТНОСТЬ 11: Пограничье,,OMRÅDE 11: Gränsområde,ALAN 11: Sınır Bölgeleri +AREA 12: The Temple of the Oracle,TXT_STRIFE_MAP12,,,,ZÓNA 12: Věštcův chrám,AREA 12: Oraklets tempel,ZONE 12: Der Tempel des Orakels,,AREO 12: La templo de la Orakolo,ÁREA 12: El templo del Oráculo,,ALUE 12: Oraakkelin temppeli,ZONE 12: Temple de l'Oracle,12. Terület: Az Orákulum Temploma,AREA 12: Il Tempio dell'Oracolo,エリア 12: オラクルの神殿,구역 12: 오라클의 신전,Zone 12: De tempel van het Orakel,OMRÅDE 12: Orakelets tempel,Strefa 12: Świątynia Wyroczni,Área 12: O Templo do Oráculo,,ZONA 12: Templul Oracolului,МЕСТНОСТЬ 12: Храм Оракула,,OMRÅDE 12: Oraklets tempel,ALAN 12: Kahin Tapınağı +AREA 13: Catacombs,TXT_STRIFE_MAP13,,,,ZÓNA 13: Katakomby,AREA 13: Katakomberne,ZONE 13: Katakomben,,AREO 13: Katakombo,ÁREA 13: Catacumbas,,ALUE 13: Katakombit,ZONE 13: Catacombes,13. Terület: Katakombák,AREA 13: Catacombe,エリア 13: 地下墓所,구역 13: 고대 묘지,Zone 13: Catacomben,OMRÅDE 13: Katakombene,Strefa 13: Katakumby,Área 13: Catacumbas,Área 13: Túmulos,ZONA 13: Catacombe,МЕСТНОСТЬ 13: Катакомбы,,OMRÅDE 13: Katakomberna,ALAN 13: Yeraltı Mezarları +AREA 14: Mines,TXT_STRIFE_MAP14,,,,ZÓNA 14: Doly,AREA 14: Miner,ZONE 14: Die Minen,,AREO 14: Minejo,ÁREA 14: Minas,,ALUE 14: Kaivokset,ZONE 14: Mines,14. Terület: Bánya,AREA 14: Miniere,エリア 14: 鉱山,구역 14: 광산,Zone 14: De mijnen,OMRÅDE 14: Minene,Strefa 14: Kopalnia,Área 14: Minas,,ZONA 14: Mine,МЕСТНОСТЬ 14: Шахты,,OMRÅDE 14: Gruvor,ALAN 14: Madenler +AREA 15: Fortress: Administration,TXT_STRIFE_MAP15,,,,ZÓNA 15: Pevnost: Administrace,AREA 15: Fæstning: Administration,ZONE 15: Festung: Administration,,AREO 15: Fortreso: Administrejo,ÁREA 15: Fortaleza: Administración,,ALUE 15: Linnoitus: hallinto,ZONE 15: Forteresse: Administration,15. Terület: Erőd: Elbírálás,AREA 15: Fortezza: Amministrazione,エリア 15: 要塞:管理室,구역 15: 요새: 중앙 관리소,Zone 15: Vesting: Administratieve organisatie,OMRÅDE 15: Festningen: Administrasjon,Strefa 15: Forteca: Administracja,Área 15: Fortaleza: Administração,,ZONA 15: Fortăreața: Administrația,МЕСТНОСТЬ 15: Крепость (администрация),,OMRÅDE 15: Fästning: Administration,ALAN 15: Kale: Yönetim +AREA 16: Fortress: Bishop's Tower,TXT_STRIFE_MAP16,,,,ZÓNA 16: Pevnost: Biskupova věž,AREA 16: Fæstning: Biskoppens tårn,ZONE 16: Festung: Bischofsturm,,AREO 16: Fortreso: Turo de la Episkopo,ÁREA 16: Fortaleza: Torre del Obispo,,ALUE 16: Linnoitus: Piispan torni,ZONE 16: Forteresse: Tour de l'évèque,16. Terület: Erőd: Püspök tornya,AREA 16: Fortezza: Torre del Vescovo,エリア 16: 要塞:ビショップの塔,구역 16: 요새: 비숍의 탑,Zone 16: Vesting: Bisschopstoren,OMRÅDE 16: Festningen: Biskopens tårn,Strefa 16: Forteca: Wieża Biskupa,Área 16: Fortaleza: Torre do Bispo,,ZONA 16: Fortăreața: Turnul Episcopului,МЕСТНОСТЬ 16: Крепость (башня Епископа),,OMRÅDE 16: Fästningen: Biskopens torn,ALAN 16: Kale: Piskopos Kulesi +AREA 17: Fortress: The Bailey,TXT_STRIFE_MAP17,,,,ZÓNA 17: Pevnost: Předhradí,AREA 17: Fæstning: Bailey,ZONE 17: Festung: Vorhof,,AREO 17: Fortreso: Ĉirkaŭmurigita korto,ÁREA 17: Fortaleza: Patio cerrado,,ALUE 17: Linnoitus: linnanpiha,ZONE 17: Forteresse: Mur d'enceinte,17. Terület: Erőd: Várfal,AREA 17: Fortezza: Bastione,エリア 17: 要塞:ベイリー,구역 17: 요새: 안뜰,Zone 17: Vesting: Voorplein,OMRÅDE 17: Festningen: Borggården,Strefa 17: Forteca: Mur Obronny,Área 17: Fortaleza: O Pátio,,ZONA 17: Fortăreața: Curte,МЕСТНОСТЬ 17: Крепость (двор),,OMRÅDE 17: Fästning: Bailey,ALAN 17: Kale: Dış avlu +AREA 18: Fortress: Stores,TXT_STRIFE_MAP18,,,,ZÓNA 18: Pevnost: Sklady,AREA 18: Fæstning: Magasiner,ZONE 18: Festung: Lager,,AREO 18: Fortreso: Magazeno,ÁREA 18: Fortaleza: Almacenes,,ALUE 18: Linnoitus: varastot,ZONE 18: Forteresse: Réserves,18. Terület: Erőd: Üzletek,AREA 18: Fortezza: Negozi,エリア 18: 要塞:商店,구역 18: 요새: 격납고,Zone 18: Vesting: Lager,OMRÅDE 18: Festningen: Lagrene,Strefa 18: Forteca: Sklepy,Área 18: Fortaleza: Reservas,,ZONA 18: Fortăreața: Depozite,МЕСТНОСТЬ 18: Крепость (склады),,OMRÅDE 18: Fästning: Butiker,ALAN 18: Kale: Mağazalar +AREA 19: Fortress: Security Complex,TXT_STRIFE_MAP19,,,,ZÓNA 19: Pevnost: Bezpečnostní komplex,AREA 19: Fæstning: Sikkerhedskompleks,ZONE 19: Festung: Sicherheitsanlage,,AREO 19: Fortreso: Sekurkomplekso,ÁREA 19: Fortaleza: Complejo de seguridad,,ALUE 19: Linnoitus: turvallisuuskeskus,ZONE 19: Forteresse: Complexe Sécurité,19. Terület: Erőd: Biztonsági Részleg,AREA 19: Fortezza: Complesso di Sicurezza,エリア 19: 要塞:複合警備所,구역 19: 요새: 보안 담당 기지,Zone 19: Vesting: Beveiligingssysteem,OMRÅDE 19: Festningen: Sikkerhetskomplekset,Strefa 19: Forteca: Kompleks Ochronny,Área 19: Fortaleza: Complexo de Segurança,,ZONA 19: Fortăreața: Complex de securitate,МЕСТНОСТЬ 19: Крепость (охранный комплекс),,OMRÅDE 19: Fästning: Säkerhetskomplex,ALAN 19: Kale: Güvenlik Kompleksi +AREA 20: Factory: Receiving,TXT_STRIFE_MAP20,,,,ZÓNA 20: Továrna: Příjem,AREA 20: Fabrik: Modtagelse,ZONE 20: Fabrik: Empfang,,AREO 20: Fabriko: Ricevejo,ÁREA 20: Fábrica: Recepción,,ALUE 20: Tehdas: vastaanotto,ZONE 20: Usine: Réception,20. Terület: Gyár: Beérkeztető,AREA 20: Fabbrica: Ricevimento,"エリア 20: 工場:受取所 +",구역 20: 공장: 수납구역,Zone 20: Fabriek: Ontvangst,OMRÅDE 20: Fabrikken: Mottak,Strefa 20: Fabryka: Odbiór,Área 20: Fábrica: Recebimento,,ZONA 20: Fabrica: Recepție,МЕСТНОСТЬ 20: Фабрика (приём),,OMRÅDE 20: Fabrik: Mottagning,ALAN 20: Fabrika: Teslim Alma +AREA 21: Factory: Manufacturing,TXT_STRIFE_MAP21,,,,ZÓNA 21: Továrna: Výroba,AREA 21: Fabrik: Fremstilling,ZONE 21: Fabrik: Herstellung,,AREO 21: Fabriko: Manufakturo,ÁREA 21: Fábrica: Manufactura,,ALUE 21: Tehdas: tuotanto,ZONE 21: Usine: Manufacture,21. Terület: Gyár: Gyártósor,AREA 21: Fabbrica: Manifattura,エリア 21: 工場:製造機関,구역 21: 공장: 조립시설,Zone 21: Fabriek: Productie,OMRÅDE 21: Fabrikk: Produksjon,Strefa 21: Fabryka: Przetwórstwo,Área 21: Fábrica: Manufatura,,ZONA 21: Fabrica: Procesare,МЕСТНОСТЬ 21: Фабрика (производство),,OMRÅDE 21: Fabrik: Tillverkning,ALAN 21: Fabrika: İmalat +AREA 22: Factory: Forge,TXT_STRIFE_MAP22,,,,ZÓNA 22: Továrna: Slévárna,AREA 22: Fabrik: Smedje,ZONE 22: Fabrik: Schmiede,,AREO 22: Fabriko: Forĝejo,ÁREA 22: Fábrica: Forja,,ALUE 22 Tehdas: paja,ZONE 22: Usine: Forge,22. Terület: Gyár: Kohó,AREA 22: Fabbrica: Fucina,エリア 22: 工場:鉄工所,구역 22: 공장: 제련소,Zone 22: Fabriek: Smederij,OMRÅDE 22: Fabrikk: Smie,Strefa 22: Fabryka: Kuźnia,Área 22: Fábrica: Forja,,ZONA 22: Fabrica: Forja,МЕСТНОСТЬ 22: Фабрика (кузня),,OMRÅDE 22: Fabrik: Smedja,ALAN 22: Fabrika: Demirhane +AREA 23: Order Commons,TXT_STRIFE_MAP23,,,,ZÓNA 23: Náves Řádu,AREA 23: Bestillingscentral,ZONE 23: Mensa des Ordens,,AREO 23: Komunumo de La Ordeno,ÁREA 23: Comuna de La Orden,,ALUE 23: Veljeskunnan messi,ZONE 23: Mess de l'Ordre,23. Terület: Rendi köztér,AREA 23: Camera dell'Ordine,エリア 23: オーダーコモンズ,구역 23: 오더 식당가,Zone 23: Mensa van de orde,OMRÅDE 23: Bestillingsallmenning,Strefa 23: Wikt Zakonu,Área 23: Câmara da Ordem,,ZONA 23: Decontare comenzi,МЕСТНОСТЬ 23: Поселение Ордена,,OMRÅDE 23: Beställningscentraler,ALAN 23: Siparişin ortak alanı +AREA 24: Factory: Conversion Chapel,TXT_STRIFE_MAP24,,,,ZÓNA 24: Továrna: Kaple konverze,AREA 24: Fabrik: Omdannelseskapel,ZONE 24: Umwandlungskapelle,,AREO 24: Fabriko: Konvert-kapelo,ÁREA 24: Fábrica: Capilla de conversión,,ALUE 24: Tehdas: käännytyskappeli,ZONE 24: Usine: Chapelle de Conversion,24. Terület: A megtérés kápolnája,AREA 24: Fabbrica: Cappella di Conversione,エリア 24: 工場:改宗礼拝堂,구역 24: 공장: 전향실,Zone 24: Verbouwingskapel,OMRÅDE 24: Fabrikk: Konverteringskapell,Strefa 24: Fabryka: Kaplica Przemiany,Área 24: Fábrica: Capela de Conversão,,ZONA 24: Fabrica: Capela de conversie,МЕСТНОСТЬ 24: Фабрика (часовня обращения),,OMRÅDE 24: Fabrik: Omvandlingskapell,ALAN 24: Fabrika: Dönüşüm Şapeli +AREA 25: Catacombs: Ruined Temple,TXT_STRIFE_MAP25,,,,ZÓNA 25: Katakomby: Zničený chrám,AREA 25: Katakomberne: Ruineret tempel,ZONE 25: Katakomben: Zerstörter Tempel,,AREO: 25: Katakombo: Ruina templo,ÁREA 25: Catacumbas: Templo arruinado,,ALUE 25: Katakombit: temppeliraunio,ZONE 25: Catacombes: Temple Ruiné,25. Terület: Katakombák: Romtemplom,AREA 25: Catacombe: Tempio in Rovina,エリア 25: 地下墓所:没落した寺院,구역 25: 고대 묘지: 무너진 사원,Zone 25: Catacomben: Vernietigde tempel,OMRÅDE 25: Katakombene: Ruinert tempel,Strefa 25: Katakumby: Zrujnowana Świątynia,Área 25: Catacumbas: Templo Arruinado,Área 25: Túmulos: Templo Arruinado,ZONA 25: Catacombe: Templu în ruine,МЕСТНОСТЬ 25: Катакомбы (руины храма),,OMRÅDE 25: Katakomber: Förfallet tempel,ALAN 25: Yeraltı Mezarları: Yıkık Tapınak +AREA 26: Proving Grounds,TXT_STRIFE_MAP26,,,,ZÓNA 26: Vojenský újezd,AREA 26: Prøvesteder,ZONE 26: Testgelände,,AREO 26: Provejo,ÁREA 26: Campo de pruebas,,ALUE 26: Koetuspaikka,ZONE 26: Terrain d'entraînement,26. Terület: Próbatételek Földje,AREA 26: Banco di Prova,エリア 26: 試練場,구역 26: 증명의 전장,Zone 26: Testgebied,OMRÅDE 26: Prøveplassen,Strefa 26: Poligon Wojskowy,Área 26: Campo de Treinamento,Área 26: Campo de Treino,ZONA 26: Tabăra de instruire,МЕСТНОСТЬ 26: Испытательный полигон,,OMRÅDE 26: Provningsområden,ALAN 26: Kanıtlama Alanları +AREA 27: The Lab,TXT_STRIFE_MAP27,,,,ZÓNA 27: Laboratoř,AREA 27: Laboratoriet,ZONE 27: Das Labor,,AREO 27: La laboratorio,ÁREA 27: El laboratorio,,ALUE 27: Laboratorio,ZONE 27: Laboratoire,27. Terület: A labor,AREA 27: Il Laboratorio,エリア 27: 研究所,구역 27: 연구소,Zone 27: Het laboratorium,OMRÅDE 27: Laboratoriet,Strefa 27: Laboratorium,Área 27: O Laboratório,,ZONA 27: Laboratorul,МЕСТНОСТЬ 27: Лаборатория,,OMRÅDE 27: Labbet,ALAN 27: Laboratuvar +AREA 28: Alien Ship,TXT_STRIFE_MAP28,,,,ZÓNA 28: Mimozemská loď,AREA 28: Fremmed skib,ZONE 28: Außerirdisches Schiff,,AREO 28: Aliplaneda ŝipo,ÁREA 28: Nave alienígena,,ALUE 28: Muukalaisalus,ZONE 28: Vaisseau Alien,28. Terület: Idegen űrhajó,AREA 28: Nave Aliena,エリア 28: エイリアンの船,구역 28: 외계 우주선,Zone 28: Buitenaards schip,OMRÅDE 28: Det fremmede skipet,Strefa 28: Statek Obcych,Área 28: Nave Alienígena,,ZONA 28: Nava extraterestră,МЕСТНОСТЬ 28: Корабль пришельцев,,OMRÅDE 28: Främmande skepp,ALAN 28: Uzaylı Gemisi +AREA 29: Entity's Lair,TXT_STRIFE_MAP29,,,,ZÓNA 29: Doupě Bytosti,AREA 29: Entitetsnesten,ZONE 29: Das Nest der Entität,,AREO 29: Nestego de Estulo,ÁREA 29: Escondite de la Entidad,,ALUE 29: Tosiolevan maja,ZONE 29: Demeure de L'Entité,29. Terület: A Teremtvény Búvóhelye,AREA 29: Tana dell'Entità,エリア 29: エンティティの隠れ家,구역 29: 엔티티의 소굴,Zone 29: Het nest van de entiteit,OMRÅDE 29: Enhetens hule,Strefa 29: Leże Bytu,Área 29: Covil da Entidade,,ZONA 29: Cuibul Entității,МЕСТНОСТЬ 29: Логово Сущности,,OMRÅDE 29: Väsendets lya,ALAN 29: Varlığın İni +AREA 30: Abandoned Front Base,TXT_STRIFE_MAP30,,,,ZÓNA 30: Opuštěná základna Fronty,AREA 30: Forladt frontbase,ZONE 30: Verlassene Basis der Front,,AREO 30: Forlasita Front-Bazo,ÁREA 30: Base abandonada del Frente,,ALUE 30: Hylätty Rintaman tukikohta,ZONE 30: Base Abandonnée du Front,30. Terület: Elhagyatott Előbázis,AREA 30: Base del Fronte abbandonata,エリア 30: 放棄された基地,구역 30: 버려진 프론트 기지,Zone 30: Verlaten frontbasis,OMRÅDE 30: Forlatt frontbase,Strefa 30: Opuszczona Baza Frontu,Área 30: Base da Frente Abandonada,,ZONA 30: Baza abandonată a Frontului,МЕСТНОСТЬ 30: Заброшенная база сопротивления,,OMRÅDE 30: Övergiven frontbas,ALAN 30: Terk Edilmiş Ön Üs +AREA 31: Training Facility,TXT_STRIFE_MAP31,,,,ZÓNA 31: Výcvikové zařízení,AREA 31: Træningsanlæg,ZONE 31: Trainingseinrichtung,,AREO 31: Trejnejo,ÁREA 31: Zona de entrenamiento,,ALUE 31: Koulutuslaitos,ZONE 31: Complexe d'Entraînement,31. Terület: Kiképzőbázis,AREA 31: Struttura di Addestramento,エリア 31: 研修施設,구역 31: 훈련 시설,Zone 31: Trainingsfaciliteit,OMRÅDE 31: Treningsanlegg,Strefa 31: Centrum Szkoleniowe,Área 31: Instalação de Treinamento,,ZONA 31: Spațiul de antrenament,МЕСТНОСТЬ 31: Тренировочный корпус,,OMRÅDE 31: Utbildningsanläggning,ALAN 31: Eğitim Tesisi +AREA 1: Sanctuary,TXT_STRIFE_MAP32,,,,ZÓNA 1: Svatyně,AREA 1: Fristedet,ZONE 1: Heiligtum,,AREO 1: Sanktejo,ÁREA 1: Santuario,,ALUE 1: Pyhäkkö,ZONE 1: Sanctuaire,1. Terület: Szentély,AREA 1: Santuario,エリア 1: 聖域 ,구역 1: 성소,Zone 1: Heiligdom,OMRÅDE 1: Fristedet,Strefa 1: Sanktuarium,Área 1: Santuário,,ZONA 1: Sanctuar,МЕСТНОСТЬ 1: Святилище,,OMRÅDE 1: Fristad,ALAN 1: Sığınak +AREA 2: Town,TXT_STRIFE_MAP33,,,,ZÓNA 2: Město,AREA 2: By,ZONE 2: Stadt,,AREO 2: Urbeto,ÁREA 2: Pueblo,,ALUE 2: Kylä,ZONE 2: Ville,2. Terület: Város,AREA 2: Città,エリア 2: 町,구역 2: 마을,Zone 2: Stad,OMRÅDE 2: By,Strefa 2: Miasto,Área 2: Vila,,ZONA 2: Oraș,МЕСТНОСТЬ 2: Город,,OMRÅDE 2: Stad,ALAN 2: Şehir +AREA 3: Movement Base,TXT_STRIFE_MAP34,,,,ZÓNA 3: Rebelská základna,AREA 3: Front Basis,ZONE 3: Rebellenbasis,,AREO 3: Movad-bazo,ÁREA 3: Base del Movimiento,,ALUE 3: Liikkeen tukikohta,ZONE 3: Base du Front,3. Terület: Mozgalmi Bázis,AREA 3: Base del Movimento,エリア 3: 移転基地,구역 3: 반군 기지,Zone 3: Front basis,OMRÅDE 3: Bevegelsesbase,Strefa 3: Baza Ruchu Oporu,Área 3: Base do Movimento,,ZONA 3: Baza rezistenței,МЕСТНОСТЬ 3: База сопротивления,,OMRÅDE 3: Förflyttningsbas,ALAN 3: Hareket Üssü +AREA 35: Factory: Production,TXT_STRIFE_MAP35,,,,ZÓNA 35: Továrna: Produkce,AREA 35: Fabrik: Produktion,ZONE 35: Fabrik: Produktion,,AREO 35: Fabriko: Produktejo,ÁREA 35: Fábrica: Producción,,ALUE 35: Tehdas: tuotanto,ZONE 35: Usine: Production,35. Terület: Gyár: Termelés,AREA 35: Fabbrica: Produzione,エリア 35: 工場 : 生産ライン,구역 35: 공장: 제작실,Zone 35: Fabriek: Productie,OMRÅDE 35: Fabrikk: Produksjon,Strefa 35: Fabryka: Produkcja,Área 35: Fábrica: Produção,,ZONA 35: Fabrica: Producție,МЕСТНОСТЬ 35: Фабрика (производство),,OMRÅDE 35: Fabrik: Produktion,ALAN 35: Fabrika: Üretim +AREA 36: Castle Clash,TXT_STRIFE_MAP36,,,,ZÓNA 36: Střet na hradě,AREA 36: Slotskampe,ZONE 36: Burg-Konflikt,,AREO 36: Batalo en la kastelo,ÁREA 36: Ataque al castillo,,ALUE 36: Linnayhteenotto,ZONE 36: Bataille du Château,36: Terület: Vári ütközet,AREA 36: Collisione di Castello,エリア 36: キャッスルクラッシュ,구역 36: 성채간의 충돌,Zone 36: Kasteelconflict,OMRÅDE 36: Slottskampen,Strefa 36: Potyczka w Zamku,Área 36: Ataque ao Castelo,,ZONA 36: Bătălia castelului,МЕСТНОСТЬ 36: Битва в замке,,OMRÅDE 36: Slottet Clash,ALAN 36: Kale Çatışması +AREA 37: Killing Grounds,TXT_STRIFE_MAP37,,,,ZÓNA 37: Popravčí zahrady,AREA 37: Drabsområder,ZONE 37: Kampfgelände,,AREO 37: Tereno de mortigado,ÁREA 37: Campo de matanza,,ALUE 37: Tappotanner,ZONE 37: Zone de Chasse,37. Terület: Gyilkos Vidék,AREA 37: Campi di Uccisione,エリア 37: 殺害者の地,구역 37: 살육의 전장,Zone 37: Slagveld,OMRÅDE 37: Drapsplasser,Strefa 37: Śmiercionośny Grunt,Área 37: Campo de Matança,,ZONA 37: Teren de ucis,МЕСТНОСТЬ 37: Сектора обстрела,,OMRÅDE 37: Dödsmark,ALAN 37: Öldürme Alanları +AREA 38: Ordered Chaos,TXT_STRIFE_MAP38,,,,ZÓNA 38: Nařízený chaos,AREA 38: Ordnet kaos,ZONE 38: Geordnetes Chaos,,AREO 38: Orda kaoso,ÁREA 38: Caos ordenado,,ALUE 38: Järjestynyt kaaos,ZONE 38: Chaos Ordonné,38. Terület: Rendezett Káosz,AREA 38: Caos Ordinato,エリア 38: カオスの秩序,구역 38: 정돈된 혼란,Zone 38: Ordelijke chaos,OMRÅDE 38: Ordnet kaos,Strefa 38: Uporządkowany Chaos,Área 38: Caos Ordenado,,ZONA 38: Haos controlat,МЕСТНОСТЬ 38: Управляемый хаос,,OMRÅDE 38: Ordnat kaos,ALAN 38: Düzenli Kaos +,,Hexen,,,,,,,,,,,,,,,,,,,,,,,,, +Winnowing Hall,TXT_HEXEN_MAP01,,,,Sál prosetí,Separationshal,Trennungshalle,,Solenejo de Separado,Sala de los Vientos,,Viskaussali,Chambre de la Séparation,Huzatos Folyosó,Camera di separazione,選抜の間,바람 회관,Scheidingszaal,Vinnersalen,Hala Przesiewu,Sala de Separação,,Sala de Separare,Зал отсеивания,Предсобље просејавања,Hallen för avräkning,Ayrılma Salonu +Seven Portals,TXT_HEXEN_MAP02,,,,Sedmero portálů,Syv portaler,Sieben Portale,,Sep Portaloj,Siete Portales,,Seitsemän portaalia,Les Sept Portails,Hét Portál,I Sette Portali,漆之門,일곱 차원문,Zeven portalen,Syv portaler,Siedem Portali,Sete Portais,,Șapte Portaluri,Семь порталов,Седам портала,Sju portaler,Yedi Portal +Guardian of Ice,TXT_HEXEN_MAP03,,,,Strážce ledu,Vogter af is,Wächter des Eises,,Gardanto de Glacio,Guardián de Hielo,,Jään vartija,Gardien de Glace,A Jég Őre,Guardiano del Ghiaccio,氷の守護者,얼음의 수호자,Bewaker van ijs,Isens vokter,Strażnik Lodu,Guardião de Gelo,,Străjerul Gheții,Страж льда,Чувар леда,Isens väktare,Buz Muhafızı +Guardian of Fire,TXT_HEXEN_MAP04,,,,Strážce ohně,Vogter af ild,Wächter des Feuers,,Gardanto de Fajro,Guardián de Fuego,,Tulen vartija,Gardien de Feu,A Tűz Őre,Guardiano del Fuoco,炎の守護者,화염의 수호자,Bewaker van vuur,Ildens vokter,Strażnik Ognia,Guardião de Fogo,,Străjerul Focului,Страж огня,Чувар огња,Elds väktare,Ateşin Koruyucusu +Guardian of Steel,TXT_HEXEN_MAP05,,,,Strážce oceli,Vogter af stål,Wächter des Stahls,,Gardanto de Ŝtalo,Guardián de Acero,,Teräksen vartija,Gardien d'Acier,Az Acél Őre,Guardiano dell'Acciaio,鋼の守護者,강철의 수호자,Bewaker van staal,Stålets vokter,Strażnik Stali,Guardião de Aço,,Străjerul Oțelului,Страж стали,Чувар челика,Stålets väktare,Çelik Muhafız +Bright Crucible,TXT_HEXEN_MAP06,,,,Světlý očistec,Lys udfordring,Glänzende Feuerprobe,,Luma Krisolo,Crisol de Luz,,Kirkas tulikoe,Creuset Radiant,Fényes Ketrec,Crogiolo Luminoso,光の坩堝,빛나는 고난,Heldere beproeving,Lys utfordring,Tygiel Światła,Crisol de Luz,,Creuzet Luminos,Горнило света,Испит светла,Ljus utmaning,Parlak Pota +Shadow Wood,TXT_HEXEN_MAP13,,,,Temný hvozd,Skyggetræ,Schattenwald,,Ombro-Arbareto,Bosque de la Sombra,,Varjosalo,Forêt des Ombres,Árnyék Erdő,Foresta Oscura,陰影樹,그림자 숲,Schaduwbos,Skyggeskogen,Las Cieni,Floresta das Sombras,,Pădurea Umbrelor,Лес теней,Шума сенки,Skuggskog,Gölge Ahşap +Darkmere,TXT_HEXEN_MAP08,,,,Černý močál,,Düstersee,,Malluma Marĉo,Pantano,,Pikiräme,Marais Noir,Fekete Mocsár,Palude Nera,暗黒の地,흙빛호수,Sombermeer,,Mroczne Bagno,Pantâno Negro,,Mlaștinile Întunecate,Болотная топь,Мочварна земља,Mörkträsk,Koyu göl +Caves of Circe,TXT_HEXEN_MAP09,,,,Kirčiny jeskyně,Circes' grotter,Circes Höhle,,Kavernoj de Circe,Cuevas de Circe,,Circeluolat,Caves de Circé,Körök Barlangja,Grotte di Circe,キルケーの洞窟,키르케의 동굴,Grotten van Circe,Circes grotter,Jaskinie Kirke,Cavernas de Circe,,Peșterile lui Circe,Пещеры Цирцеи,Киркине пећине,Circes grottor,Kirke Mağaraları +Wastelands,TXT_HEXEN_MAP10,,,,Pustiny,Ødemarker,Ödland,,Senvivejo,Yermo,,Erämaat,Terres Ruinées,Senkiföldje,Terre in rovina,荒野,황무지,Woestenij,Ødemarken,Pustkowia,Terras Desoladas,,Tărâmurile Pustii,Пустоши,Пустоши,Ödemarken,Çorak Topraklar +Sacred Grove,TXT_HEXEN_MAP11,,,,Posvátný háj,Helliglund,Heiliger Hain,,Sankta Bosketo,Arboleda Sagrada,,Pyhä metsikkö,Bosquet Sacré,Szent Liget,Boschetto Sacro,神聖なる園,성스러운 수풀,Heilig bosje,Hellig lund,Święty Gaj,Bosque Sagrado,,Crângul Sacru,Священная роща,Свети шумарак,Heliga lunden,Kutsal Koru +Hypostyle,TXT_HEXEN_MAP12,,,,Hypostyl,,Säulenhalle,,Kolonejo,Hipóstila,,Hypostyyli,,Oszlopterem,Ipostilo,多柱の間,다주실,Zuilenhal,,Hypostyl,Hipostilo,,Hipostil,Гипостильный зал,Хипостил,Hypostil,Hipostil +Heresiarch's Seminary,TXT_HEXEN_MAP27,,,,Arcikacířův alumnát,Heresiarkens seminarium,Seminar des Erzketzers,,Seminario de Ĉefherezulo,Seminario del Heresiarca,,Kerettiarkin seminaari,Séminaire de l'Hérésiarche,A Főeretnek Neveldéje,Seminario dell'Heresiarch,ヘレシアークの神学舎,헤러시아크의 신학교,Seminarie van ketterij,Heresiarkens seminar,Seminarium Herezjarchy,Seminário do Heresiarca,,Seminarul Ereziarhului,Семинария Ересиарха,Јересијархов семинар,Heresiarkens seminarium,Heresiark'ın Ruhban Okulu +Dragon Chapel,TXT_HEXEN_MAP28,,,,Dračí kaple,Dragekapel,Drachenkapelle,,Drakkapelo,Capilla Dragón,,Lohikäärmekappeli,Chapelle du Dragon,Sárkány Szentély,Cappella del Drago,ドラゴンの庵寺,드래곤 예배실,Drakenkapel,Dragekapell,Kaplica Smoka,Capela do Dragão,,Capela dragonilor,Часовня дракона,Капела змајева,Drakens kapell,Ejderha Şapeli +Griffin Chapel,TXT_HEXEN_MAP30,,,,Gryfova kaple,Griffinkapel,Greifenkapelle,,Grifkapelo,Capilla Grifo,,Aarnikotkakappeli,Chapelle du Grifon,Griff Szentély,Cappella del Grifone,グリフィンの庵寺,그리핀 예배실,Griffioenenkapel,Griffon kapell,Kaplica Gryfa,Capela do Grifo,,Capela grifonilor,Часовня грифона,Капела грифонова,Griffins kapell,Griffin Şapeli +Deathwind Chapel,TXT_HEXEN_MAP31,,,,Kaple mrakosmrtě,Dødens vind kapel,Todeswindkapelle,,Mortvento-Kapelo,Capilla Viento de Muerte,,Kuolontuulikappeli,Chapelle du Vent Tueur,Halál Szentély,Cappella del Vento Assassino,デスウィンドの庵寺,죽음바람 예배실,Dodenwind kapel,Dødens vind kapell,Kaplica Wiatru Śmierci,Capela do Vento da Morte,,Capela suflului morții,Часовня ветра смерти,Капела ветра смрти,Dödsblåsans kapell,Ölüm Rüzgarı Şapeli +Orchard of Lamentations,TXT_HEXEN_MAP32,,,,Sad nářků,Klagesangens frugthave,Garten der Wehklagen,,Horto de Lamentoj,Huerto de los Lamentos,,Valitusvirtten tarha,Verger des Lamentations,Siránkozás Kertje,Frutteto delle Lamentazioni,哀悼茂る園,통탄의 과수원,Boomgaard van klaagliederen,Klagesangens hage,Płaczący Sad,Pomar das Lamentações,,Livada amărăciunii,Сады плача,Воћњак плача,Klagovisornas trädgård,Ağıtlar Bahçesi +Silent Refectory,TXT_HEXEN_MAP33,,,,Tichý refektář,Stilhedens refektorium,Stilles Refektorium,,Silenta Manĝejo,Refectorio Silencioso,,Hiljainen ruokasali,Réfectoire Silencieux,Néma Refektórium,Refettorio silenzioso,寡黙なる食堂,침묵의 식당,Stil refectory,Stille refektorium,Cichy Refektarz,Refeitório Silencioso,,Refectoriul tăcerii,Безмолвная трапезная,Безгласна трпезарија,Tyst matsal,Sessiz Yemekhane +Wolf Chapel,TXT_HEXEN_MAP34,,,,Vlčí kaple,Ulvekapel,Wolfskapelle,,Lupkapelo,Capilla Lobo,,Susikappeli,Chapelle du Loup,Farkas Szentély,Cappella del Lupo,狼の庵寺,늑대 예배실,Wolvenkapel,Ulvens kapell,Kaplica Wilka,Capela do Lobo,,Capela lupilor,Часовня волка,Капела вучја,Vargkapellet,Kurt Şapeli +Forsaken Outpost,TXT_HEXEN_MAP21,,,,Opuštěné stanoviště,Forladt forpost,Verlassener Vorposten,,Forlasita Posteno,Puesto de Avanzada Abandonado,,Hylätty etuvartio,Base Abandonnée,Elhagyott Őrség,Avamposto Abbandonato,荒れ果てた前哨地,버려진 초소,Verwaarloosde buitenpost,Forlatt utpost,Opuszczony Posterunek,Posto Abandonado,,Avanpostul părăsit,Покинутая застава,Напуштена постаја,Försvunnen utpost,Unutulmuş Karakol +Castle of Grief,TXT_HEXEN_MAP22,,,,Hrad smutku,Sorgens slot,Leidensburg,,Kastelo de Funebro,Castillo del Pesar,,Surulinna,Château de la Souffrance,A Gyász Kastélya,Castello della Sofferenza,嘆きの城,비탄의 성,Kasteel van verdriet,Sorgens slott,Zamek Smutku,Castelo da Aflição,,Castelul întristării,Замок скорби,Замак жалости,Sorgens slott,Keder Kalesi +Gibbet,TXT_HEXEN_MAP23,,,,Šibenice,,Richtstätte,,Pendigilo,Horca,,Hirsipuu,Gibet,Akasztófa,Forca,晒し台,교수대,,Galgen,Szubienica,Forca,,Eșafodul,Виселица,Вешала,,İnfaz yeri +Effluvium,TXT_HEXEN_MAP24,,,,Výpary,,Effluvium,,Efluvo,Efluvio,,Katku,,A Bűz Börtöne,Effluvio,腐臭漂う残骸,악취,,,Odór,Eflúvio,,Efluviu,Зловонный сток,Воњави одвод,,Atık Su +Dungeons,TXT_HEXEN_MAP25,,,,Žalář,Fangehuller,Kerker,,Karceroj,Calabozos,,Tyrmät,Donjons,Kazamaták,I Dungeon,地下牢,지하감옥,Kerkers,Fangehull,Lochy,Masmorras,,Temnițe,Подземелья,Лагуми,Kerker,Zindanlar +Desolate Garden,TXT_HEXEN_MAP26,,,,Zpustošená zahrada,Ødelagt have,Verwildeter Garten,,Dezerta Ĝardeno,Jardín Desolado,,Autio puutarha,Jardin de la Désolation,Sivár Kert,Giardino Desolato,荒涼とした庭,황폐한 정원,Woeste tuin,Øde hage,Spustoszały Ogród,Jardim Desolado,,Grădina dezolantă,Заброшенный сад,Напуштени врт,Ödslig trädgård,Issız Bahçe +Necropolis,TXT_HEXEN_MAP35,,,,Nekropole,Nekropolis,Nekropole,,Nekropolo,Necrópolis,,Nekropoli,Nécropole,Nekropolisz,Necropoli,ネクロポリス,망자의 도시,,Nekropolis,Nekropolia,Necrópole,,Necropola,Некрополь,Некропола,Nekropolis,Nekropol +Zedek's Tomb,TXT_HEXEN_MAP36,,,,Zedekova hrobka,Zedeks grav,Zedeks Gruft,,Tombo de Zedek,Tumba de Zedek,,Sedekin hauta,Tombeau de Zedek,Zedek Sírja,Tomba di Zedek,ゼデクの墓,제닥의 무덤,Zedek's graf,Zedeks grav,Grobowiec Zedeka,Tumba de Zedek,Túmulo de Zedek,Mormântul lui Zedek,Гробница Зедека,Гробница Зедекова,Zedeks grav,Zedek'in Mezarı +Menelkir's Tomb,TXT_HEXEN_MAP37,,,,Menelkirova hrobka,Menelkirs grav,Menelkirs Gruft,,Tombo de Menelkir,Tumba de Menelkir,,Menelkirin hauta,Tombeau de Menelkir,Menelkir Sírja,Tomba di Menelkir,メネルキルの墓,메넬키어의 무덤,Menelkir's graf,Menelkirs grav,Grobowiec Menelkira,Tumba de Menelkir,Túmulo de Menelkir,Mormântul lui Menelkir,Гробница Менелкира,Гробница Менелкирова,Menelkirs grav,Menelkir'in Mezarı +Traductus' Tomb,TXT_HEXEN_MAP38,,,,Traduktova hrobka,Traductus' grav,Traductus' Gruft,,Tombo de Traductus,Tumba de Traductus,,Traduktuksen hauta,Tombeau de Traductus,Traductus Sírja,Tomba di Traductus,トダクティスの墓,트라닥투스의 무덤,Traductus' graf,Traductus' grav,Grobowiec Traduktusa,Tumba de Traductus,Túmulo de Traductus,Mormântul lui Traductus,Гробница Традактуса,Гробница Традуктусова,Traductus' grav,Traductus'un Mezarı +Vivarium,TXT_HEXEN_MAP39,,,,Vivárium,,,,Vivario,Vivario,,Vivaario,,Vivárium,Vivario,ビバリウム,사육장,,,Wiwarium,Viveiro,,Vivariu,Виварий,Виваријум,, Dark Crucible,TXT_HEXEN_MAP40,,,,Temný očistec,Mørk udfordring,Dunkle Feuerprobe,,Malluma Krisolo,Crisol de Oscuridad,,Pimeä tulikoe,Creuset Sombre,Sötét Ketrec,Crogiolo Buio,"暗黒の坩堝 -",어두운 고난,Donkere beproeving,Mørkets utfordring,Tygiel Mroku,Crisol das Trevas,,Creuzet Întunecat,Испытание тьмы,Испит таме,Karanlık Pota -,,Hexen Deathkings,,,,,,,,,,,,,,,,,,,,,,,, -Ruined Village,TXT_HEXDD_MAP41,,,,Zničená vesnice,Ødelagt landsby,Zerstörtes Dorf,,Ruiniga Vilaĝo,Pueblo en Ruinas,,Rauniokylä,Village en Ruines,Az Elpusztított Falu,Villagio in Rovine,廃村,파괴된 마을,Ruïneerd dorp,Den ødelagte landsbyen,Zrujnowana Wioska,Aldeia Destruída,Aldeia em Ruinas,Sat ruinat,Разрушенная деревня,Уништено село,Yıkık Köy -Blight,TXT_HEXDD_MAP42,,,,Pohroma,Skylle,Fäule,,Pesto,Decaimiento,,Turmelus,Peste,Penész,Peste,疫病,황폐화,Ziekte,Skade,Zaraza,Peste,,Cotropit,Упадок,Пошаст,Yanıklık -Sump,TXT_HEXDD_MAP43,,,,Žumpa,Sump,Sumpf,,Olekuvo,Pozo de Barro,,Likakaivo,Puisard,Tócsa,Pozzetto,汚水槽,웅덩이,Moeras,,Studzienka,Poço de Lama,,Joampă,Грязеотстойник,Сливник,Karter -Catacomb,TXT_HEXDD_MAP44,,,,Katakomby,Katakomb,Katakombe,,Katakombo,Catacumba,,Katakombi,Catacombe,Katakomba,Catacombe,カタコンベ,지하 묘실,Katacombe,Katakombe,Katakumba,Catacumba,,Catacombă,Катакомба,Катакомба,Katakomb -Badlands,TXT_HEXDD_MAP45,,,,Pustiny,Ødemarker,Ödland,,Badlandoj,Páramos,,Autiomaa,Terres Sauvages,Terméketlen Föld,Terre Selvagge,不毛地帯,불모지,Woestijn,Dårlige land,Pustkowia,Ermo,,Deșert,Бесплодные земли,Пустош,Çorak Topraklar -Brackenwood,TXT_HEXDD_MAP46,,,,Prales,,Moorwald,,Pteridejo,Brackenwood,,Saniaissalo,Forêt de Bracken,Páfrány Erdő,Foresta di Felce,ワラビの樹,고사리숲,Moorbos,,Las Paproci,Floresta de Samambaias,,Pădure de ferigi,Брекенвуд,Папрат,Bataklık orman -Pyre,TXT_HEXDD_MAP47,,,,Hranice,Bål,Scheiterhaufen,,Kremaciejo,Pira Funeraria,,Rovio,Brasier,Máglya,Pira,火葬薪,화장,Brandstapel,Bål,Ognisko,Pira,,Rug,Погребальный костёр,Ломача,Ateş Yakmak -Constable's Gate,TXT_HEXDD_MAP48,,,,Konstáblova brána,Vagtport,Wachtor,,Pordego de Ĝendarmo,Puerta del Alguacil,,Konstaapelin portti,Portail du Constable,Csendőr Kapu,Porta del Conestabile,城守達の門,무관장의 문,Constable's poort,Konstabelporten,Brama Posterunkowego,Portão do Condestável,,Poarta ofițerului,Комендантские врата,Чиновникова капија,Muhafız Kapısı -Treasury,TXT_HEXDD_MAP49,,,,Pokladnice,Skatkammer,Schatzkammer,,Trezorejo,Tesorería,,Rahasto,Trésorerie,Kincstár,Tesoreria,宝庫,국고,Schatkist,Skattkammeret,Skarbiec,Tesouraria,,Vistierie,Сокровищница,Трезор,Hazine Müsteşarlığı -Market Place,TXT_HEXDD_MAP50,,,,Tržnice,Markedspladsen,Marktplatz,,Foirejo,Plaza del Mercado,,Markkinat,Place du Marché,Piactér,Piazza del Mercato,市場,시장,Markt,Markedsplassen,Rynek,Feira,,Piață,Рыночная площадь,Пијаца,Pazar Yeri -Locus Requiescat,TXT_HEXDD_MAP51,,,,,,Locus Requiescat,,Locus Requiescat,Lugar de Descanso Eterno,,,Locus Requiescat,,,祈祷師の軌跡,명복의 장소,,,Locus Requiescat,,,,Место вечного упокоения,Место починка,Locus Requiescat -Ordeal,TXT_HEXDD_MAP52,,,,Utrpení,Forbandelse,Heimsuchung,,Provo Per Aflikto,Prueba,,Koettelemus,Supplice,Megpróbáltatás,Supplizio,試練,시죄의 시련,Orde,Prøvelsen,Męka,Suplício,,Supliciu,Испытание,Изазов,Çile -Armory,TXT_HEXDD_MAP53,,,Armoury,Zbrojnice,Våbenkammer,Waffenkammer,,Armilejo,Armería,,Asehuone,Amurerie,Fegyvertár,Armeria,武器庫,무기고,Wapenkamer,Våpenkammer,Zbrojownia,Arsenal,,Arsenal,Оружейная,Оружарница,Cephanelik -Nave,TXT_HEXDD_MAP54,,,,Chrámová loď,,Kirchenschiff,,Navo,La Nave,,Laiva,Nef,Templomhajó,Navata,身廊,본당,Naaf,Skipet,Nawa,,,Naos,Неф,Брод,Nef -Chantry,TXT_HEXDD_MAP55,,,,Modlitebna,Korskirke,Kantorei,,Kapelo,Capilla,,Kappeli,Chapelle,Gyászkápolna,Cappella,小礼拝堂,예배당,,Minnekapellet,Kaplica Wotywna,Capela,,Capelă,Часовня,Капела,Dua Odası -Abattoir,TXT_HEXDD_MAP56,,,,Jatka,Slagteriet,Schlachthaus,,Buĉejo,Matadero,,Teurastamo,Abbatoire,Vágóhíd,Mattatoio,屠殺場,도살장,Slachthuis,Slakteriet,Rzeźnia,Matadouro,,Abator,Бойня,Кланица,Mezbaha -Dark Watch,TXT_HEXDD_MAP57,,,,Tmavá hlídka,Mørk vagt,Dunkle Wache,,Ombra Gardisto,Guardia Oscura,,Pimeä vartio,Garde Noire,Éjjeli Őrség,Guardia Oscura,闇の刻計,어둠의 감시초소,Donkere horloge,Mørkets vakt,Ciemna Strażnica,Guarda Negra,,Gardian întunecat,Тёмный страж,Мрачни чувар,Karanlık Saat -Cloaca,TXT_HEXDD_MAP58,,,,Kloaka,,Kloake,,Kloako,Cloaca,,Kloaakki,Cloaque,Kloáka,,排泄腔,하수구,,,Kloaka,,,,Клоака,Клоака,Kloaka -Ice Hold,TXT_HEXDD_MAP59,,,,Ledová pevnost,Isrum,Eiskammer,,Fuorto el Glacio,Tierra de Hielo,,Jääsäilö,Fort de Glace,Jégtorony,Fortezza di Ghiaccio,氷結,빙고,Ijskamer,Ishall,Lodowa Twierdza,Fortaleza de Gelo,,Fort glaciar,Ледяная твердь,Ледена утврда,Buz Tutucu -Dark Citadel,TXT_HEXDD_MAP60,,,,Temná citadela,Mørkt citadel,Dunkle Festung,,Ombra Citadelo,Fortaleza Oscura,,Pimeä linnake,Citadelle Sombre,Sötét Torony,Cittadella Oscura,暗黒の城塞,어둠의 요새,Donkere citadel,Mørkets citadell,Mroczna Cytadela,Cidadela Negra,,Cetatea întunecată,Тёмная цитадель,Мрачна цитадела,Karanlık Kale -Transit,TXT_HEXDD_MAP33,,,,Převoz,,,,Vojo,Sala de Espera,,Läpikulku,Transit,Tranzit,Passaggio,変遷,통로,Doorvoer,Transitt,Tranzyt,Sala de Espera,,Tranzit,Переход,Прелаз,Transit -Over'n Under,TXT_HEXDD_MAP34,,,,Nad a Pod,,Drunter und Drüber,,Sub kaj Supre,Arriba y Abajo,,Yli ja ali,Sens Dessus Dessous,Fent és Lent,Sopra e Sotto,天と地,높낮이,Over'n under,Over og under,Nad I Pod,Sobre e Sob,,Mai sus și Mai jos,Выше и ниже,Изнад и испод,Üst ve Alt -Deathfog,TXT_HEXDD_MAP35,,,,Mha skonu,Dødens tåge,Todesnebel,,Mortnebulo,Niebla de Muerte,,Kuolonsumu,Brume Mortelle,Halálköd,Nebbia di Morte,死の霧,죽음의 안개,Dodenmist,Dødståke,Mgła Śmierci,Névoa da Morte,,Ceața morții,Туман смерти,Магла смрти,Ölüm Sisi -Castle of Pain,TXT_HEXDD_MAP36,,,,Hrad bolesti,Frygtens slot,Burg der Angst,,Kastelo de Doloro,Castillo del Dolor,,Tuskan linna,Château de la Douleur,Fájdalom Kastélya,Castello del Dolore,苦しみの城,고통의 성,Kasteel van pijn,Smertens slott,Zamek Bólu,Castelo da Dor,,Castelul durerii,Замок боли,Тврђава бола,Acı Kalesi -Sewer Pit,TXT_HEXDD_MAP37,,,,Odpadní jáma,Kloakgrube,Kanalgrube,,Fekaĵputo,Pozo de Residuos,,Viemärimonttu,Trou d'Egout,Kanális akna,Fossa della Fogna,地下溝穴,하수도,Rioolput,Kloakkgropen,Ściek,Fossa de Esgoto,,Groapa de scurgere,Сточная яма,Канализациона јама,Kanalizasyon Çukuru -The Rose,TXT_HEXDD_MAP38,,,,Růže,Rosen,Die Rose,,La Rozo,La Rosa,,Ruusu,La Rose,A Rózsa,La Rosa,薔薇,장밋빛,De roos,Rosen,Róża,A Rosa,,Roza,Роза,Ружа,Gül -,,Intermission texts,,,,,,,,,,,,,,,,,,,,,,,, +",어두운 고난,Donkere beproeving,Mørkets utfordring,Tygiel Mroku,Crisol das Trevas,,Creuzet Întunecat,Испытание тьмы,Испит таме,Mörk utmaning,Karanlık Pota +,,Hexen Deathkings,,,,,,,,,,,,,,,,,,,,,,,,, +Ruined Village,TXT_HEXDD_MAP41,,,,Zničená vesnice,Ødelagt landsby,Zerstörtes Dorf,,Ruina vilaĝo,Pueblo en ruinas,,Rauniokylä,Village en Ruines,Az Elpusztított Falu,Villagio in Rovine,廃村,파괴된 마을,Ruïneerd dorp,Den ødelagte landsbyen,Zrujnowana Wioska,Aldeia Destruída,Aldeia em Ruinas,Sat ruinat,Разрушенная деревня,Уништено село,Ruinerad by,Yıkık Köy +Blight,TXT_HEXDD_MAP42,,,,Pohroma,Skylle,Fäule,,Pesto,Decaimiento,,Turmelus,Peste,Penész,Peste,疫病,황폐화,Ziekte,Skade,Zaraza,Peste,,Cotropit,Упадок,Пошаст,Sköldpest,Yanıklık +Sump,TXT_HEXDD_MAP43,,,,Žumpa,Sump,Sumpf,,Olekuvo,Pozo de Barro,,Likakaivo,Puisard,Tócsa,Pozzetto,汚水槽,웅덩이,Moeras,,Studzienka,Poço de Lama,,Joampă,Грязеотстойник,Сливник,,Karter +Catacomb,TXT_HEXDD_MAP44,,,,Katakomby,Katakomb,Katakombe,,Katakombo,Catacumba,,Katakombi,Catacombe,Katakomba,Catacombe,カタコンベ,지하 묘실,Katacombe,Katakombe,Katakumba,Catacumba,,Catacombă,Катакомба,Катакомба,Katakomb,Katakomb +Badlands,TXT_HEXDD_MAP45,,,,Pustiny,Ødemarker,Ödland,,Badlandoj,Páramos,,Autiomaa,Terres Sauvages,Terméketlen Föld,Terre Selvagge,不毛地帯,불모지,Woestijn,Dårlige land,Pustkowia,Ermo,,Deșert,Бесплодные земли,Пустош,Dåliga marker,Çorak Topraklar +Brackenwood,TXT_HEXDD_MAP46,,,,Prales,,Moorwald,,Pteridejo,Brackenwood,,Saniaissalo,Forêt de Bracken,Páfrány Erdő,Foresta di Felce,ワラビの樹,고사리숲,Moorbos,,Las Paproci,Floresta de Samambaias,,Pădure de ferigi,Брекенвуд,Папрат,Brackenwood,Bataklık orman +Pyre,TXT_HEXDD_MAP47,,,,Hranice,Bål,Scheiterhaufen,,Kremaciejo,Pira Funeraria,,Rovio,Brasier,Máglya,Pira,火葬薪,화장,Brandstapel,Bål,Ognisko,Pira,,Rug,Погребальный костёр,Ломача,Bål,Ateş Yakmak +Constable's Gate,TXT_HEXDD_MAP48,,,,Konstáblova brána,Vagtport,Wachtor,,Pordego de Ĝendarmo,Puerta del Alguacil,,Konstaapelin portti,Portail du Constable,Csendőr Kapu,Porta del Conestabile,城守達の門,무관장의 문,Constable's poort,Konstabelporten,Brama Posterunkowego,Portão do Condestável,,Poarta ofițerului,Комендантские врата,Чиновникова капија,Konstapelns port,Muhafız Kapısı +Treasury,TXT_HEXDD_MAP49,,,,Pokladnice,Skatkammer,Schatzkammer,,Trezorejo,Tesorería,,Rahasto,Trésorerie,Kincstár,Tesoreria,宝庫,국고,Schatkist,Skattkammeret,Skarbiec,Tesouraria,,Vistierie,Сокровищница,Трезор,Skattkammaren,Hazine Müsteşarlığı +Market Place,TXT_HEXDD_MAP50,,,,Tržnice,Markedspladsen,Marktplatz,,Foirejo,Plaza del Mercado,,Markkinat,Place du Marché,Piactér,Piazza del Mercato,市場,시장,Markt,Markedsplassen,Rynek,Feira,,Piață,Рыночная площадь,Пијаца,Marknadsplats,Pazar Yeri +Locus Requiescat,TXT_HEXDD_MAP51,,,,,,Locus Requiescat,,Locus Requiescat,Lugar de Descanso Eterno,,,Locus Requiescat,,,祈祷師の軌跡,명복의 장소,,,Locus Requiescat,,,,Место вечного упокоения,Место починка,,Locus Requiescat +Ordeal,TXT_HEXDD_MAP52,,,,Utrpení,Forbandelse,Heimsuchung,,Provo Per Aflikto,Prueba,,Koettelemus,Supplice,Megpróbáltatás,Supplizio,試練,시죄의 시련,Orde,Prøvelsen,Męka,Suplício,,Supliciu,Испытание,Изазов,Rättegång,Çile +Armory,TXT_HEXDD_MAP53,,,Armoury,Zbrojnice,Våbenkammer,Waffenkammer,,Armilejo,Armería,,Asehuone,Amurerie,Fegyvertár,Armeria,武器庫,무기고,Wapenkamer,Våpenkammer,Zbrojownia,Arsenal,,Arsenal,Оружейная,Оружарница,Vapenförråd,Cephanelik +Nave,TXT_HEXDD_MAP54,,,,Chrámová loď,,Kirchenschiff,,Navo,La Nave,,Laiva,Nef,Templomhajó,Navata,身廊,본당,Naaf,Skipet,Nawa,,,Naos,Неф,Брод,,Nef +Chantry,TXT_HEXDD_MAP55,,,,Modlitebna,Korskirke,Kantorei,,Kapelo,Capilla,,Kappeli,Chapelle,Gyászkápolna,Cappella,小礼拝堂,예배당,,Minnekapellet,Kaplica Wotywna,Capela,,Capelă,Часовня,Капела,Kyrkogård,Dua Odası +Abattoir,TXT_HEXDD_MAP56,,,,Jatka,Slagteriet,Schlachthaus,,Buĉejo,Matadero,,Teurastamo,Abbatoire,Vágóhíd,Mattatoio,屠殺場,도살장,Slachthuis,Slakteriet,Rzeźnia,Matadouro,,Abator,Бойня,Кланица,Slakthus,Mezbaha +Dark Watch,TXT_HEXDD_MAP57,,,,Tmavá hlídka,Mørk vagt,Dunkle Wache,,Ombra Gardisto,Guardia Oscura,,Pimeä vartio,Garde Noire,Éjjeli Őrség,Guardia Oscura,闇の刻計,어둠의 감시초소,Donkere horloge,Mørkets vakt,Ciemna Strażnica,Guarda Negra,,Gardian întunecat,Тёмный страж,Мрачни чувар,Mörk vakt,Karanlık Saat +Cloaca,TXT_HEXDD_MAP58,,,,Kloaka,,Kloake,,Kloako,Cloaca,,Kloaakki,Cloaque,Kloáka,,排泄腔,하수구,,,Kloaka,,,,Клоака,Клоака,,Kloaka +Ice Hold,TXT_HEXDD_MAP59,,,,Ledová pevnost,Isrum,Eiskammer,,Fuorto el Glacio,Tierra de Hielo,,Jääsäilö,Fort de Glace,Jégtorony,Fortezza di Ghiaccio,氷結,빙고,Ijskamer,Ishall,Lodowa Twierdza,Fortaleza de Gelo,,Fort glaciar,Ледяная твердь,Ледена утврда,Ishållet,Buz Tutucu +Dark Citadel,TXT_HEXDD_MAP60,,,,Temná citadela,Mørkt citadel,Dunkle Festung,,Ombra Citadelo,Fortaleza Oscura,,Pimeä linnake,Citadelle Sombre,Sötét Torony,Cittadella Oscura,暗黒の城塞,어둠의 요새,Donkere citadel,Mørkets citadell,Mroczna Cytadela,Cidadela Negra,,Cetatea întunecată,Тёмная цитадель,Мрачна цитадела,Mörkt citadell,Karanlık Kale +Transit,TXT_HEXDD_MAP33,,,,Převoz,,,,Vojo,Sala de Espera,,Läpikulku,,Tranzit,Passaggio,変遷,통로,Doorvoer,Transitt,Tranzyt,Sala de Espera,,Tranzit,Переход,Прелаз,,Transit +Over'n Under,TXT_HEXDD_MAP34,,,,Nad a Pod,,Drunter und Drüber,,Sub kaj Supre,Arriba y Abajo,,Yli ja ali,Sens Dessus Dessous,Fent és Lent,Sopra e Sotto,天と地,높낮이,Over'n under,Over og under,Nad I Pod,Sobre e Sob,,Mai sus și Mai jos,Выше и ниже,Изнад и испод,Över'n Under,Üst ve Alt +Deathfog,TXT_HEXDD_MAP35,,,,Mha skonu,Dødens tåge,Todesnebel,,Mortnebulo,Niebla de Muerte,,Kuolonsumu,Brume Mortelle,Halálköd,Nebbia di Morte,死の霧,죽음의 안개,Dodenmist,Dødståke,Mgła Śmierci,Névoa da Morte,,Ceața morții,Туман смерти,Магла смрти,Dödsfog,Ölüm Sisi +Castle of Pain,TXT_HEXDD_MAP36,,,,Hrad bolesti,Frygtens slot,Burg der Angst,,Kastelo de Doloro,Castillo del Dolor,,Tuskan linna,Château de la Douleur,Fájdalom Kastélya,Castello del Dolore,苦しみの城,고통의 성,Kasteel van pijn,Smertens slott,Zamek Bólu,Castelo da Dor,,Castelul durerii,Замок боли,Тврђава бола,Slottet av smärta,Acı Kalesi +Sewer Pit,TXT_HEXDD_MAP37,,,,Odpadní jáma,Kloakgrube,Kanalgrube,,Fekaĵputo,Pozo de Residuos,,Viemärimonttu,Trou d'Egout,Kanális akna,Fossa della Fogna,地下溝穴,하수도,Rioolput,Kloakkgropen,Ściek,Fossa de Esgoto,,Groapa de scurgere,Сточная яма,Канализациона јама,Avloppsgrop,Kanalizasyon Çukuru +The Rose,TXT_HEXDD_MAP38,,,,Růže,Rosen,Die Rose,,La Rozo,La Rosa,,Ruusu,La Rose,A Rózsa,La Rosa,薔薇,장밋빛,De roos,Rosen,Róża,A Rosa,,Roza,Роза,Ружа,Rosen,Gül +,,Intermission texts,,,,,,,,,,,,,,,,,,,,,,,,, "Once you beat the big badasses and clean out the moon base you're supposed to win, aren't you? Aren't you? Where's @@ -366,48 +366,48 @@ Der einzige Weg hier raus ist durch. Um das DOOM-Erlebnis fortzusetzen, spiele „Die Ufer der Hölle“ und die erstaunliche -Fortsetzung, „Inferno“!",,"Kiam vi venkus la grandajn malbonulojn -kaj purigus la lunbazon, vi onidire -gajnus, ĉu ne? Ĉu ne? Kie estas via -granda rekompenco kaj bileto hejmen? -Kio diable estas ĉi tio? Ne devas fini tiel! +Fortsetzung, „Inferno“!",,"Post kiam vi elpurigis la bazon +en Fobo je tiuj maliculoj, vi logike +venkus, ĉu? Ĉu!? Kie estas via granda +rekompenco kaj bileto hejmen? Kio diable +okazis? Ĉi tio ne devus finiĝi ĉi tiel! -Odoraĉas kiel putra karno, sed aspektas -kiel la perdita Dejmo-bazo. Ŝajnas, ke -vi estas kaptita sur La Bordoj de Infero. -La sola eliro estas tra. +Odoras putran karnon, sed ĝi aspektas +kiel la perdita bazo en Dejmo. Ŝajnas, +ke vi estas kaptita ĉe la Infer-bordoj: +por espaki oni transiru la Inferon. Por daŭrigi la DOOM-sperton, ludu -la epizodon ""La Bordoj de Infero"" kaj -ĝian mirigan sekvon, ""Inferno""!","Una vez has vencido a los tremendos bastardos -y limpiado la base lunar se supone -que deberías ganar, ¿verdad? ¡¿Verdad?! -¿Dónde esta tu suculenta recompensa -y tu pasaje a casa? ¿Qué diablos es esto? -¡Esto no debería terminar así! - -Huele a carne podrida, pero se ve como -la base perdida de Deimos. Parece que estás -atrapad@[ao_esp] en las Orillas del Infierno. -La única forma de salir es atravesarlo. - -Para continuar la experiencia de DOOM, -juega Las Orillas del Infierno y su -sorprendente secuela, ¡Inferno!","Una vez que venciste a los tremendos bastardos -y limpiaste la base lunar se supone -que habrías ganado ¿verdad? ¡¿Verdad?! -¿Dónde esta tu suculenta recompensa -y tu pasaje a casa? ¿Qué diablos es esto? -¡No se supone que termine así! - -Huele a carne podrida, pero se ve como -la base perdida de Deimos. Parece que estás -atrapad@[ao_esp] en las orillas del infierno. -La única salida es por ahí. - -Para continuar la experiencia de DOOM, -juega Las orillas del infierno y su -sorprendente secuela, ¡Averno! ","Päihitettyäsi isot pahikset ja raivattuasi +la epizodon «La Infer-bordoj» kaj +ĝian bonegan sekvon: «Inferno»!","Tras vencer a esos perversos y +limpiar la base de Fobos se supone +que deberías ganar, ¿no?, ¿¡no!? +¿Qué diablos ha pasado?, ¿dónde están tu +suculenta recompensa y tu pasaje a casa? +¡Esto no debería terminar así! + +Huele a carne podrida, pero se ve como +la base perdida de Deimos. Pareces estar +atrapado en las orillas del Infierno: +la única forma de salir es atravesarlo. + +Para seguir con la experiencia de DOOM, +¡juega a «Las orillas del Infierno» y +a su sorprendente secuela: «Inferno»!","Tras vencer a esos perversos y +limpiar la base de Fobos se supone +que deberías ganar, ¿no?, ¿¡no!? +¿Qué diablos pasó?, ¿dónde están tu +suculenta recompensa y tu pasaje a casa? +¡Esto no debería terminar así! + +Huele a carne podrida, pero se ve como +la base perdida de Deimos. Pareces estar +atrapado en las orillas del Infierno: +la única forma de salir es atravesarlo. + +Para seguir con la experiencia de DOOM, +¡juega a «Las orillas del Infierno» y +a su sorprendente secuela: «Inferno»!","Päihitettyäsi isot pahikset ja raivattuasi kuutukikohdan sinunhan pitäisi voittaa, eikö niin? Eikö niin? Missä on mehevä palkkiosi ja paluulippusi kotiin? Mitä @@ -463,8 +463,8 @@ sulle Coste dell'Inferno. L'unica uscita ci passa in mezzo. Per continuare l'esperienza di DOOM -gioca 'The Shores of Hell' e il suo -incredibile seguito, 'Infernò! +gioca ""Le rive dell'Inferno"" e il suo +incredibile seguito: ""Inferno""! ","火星基地から巨悪をこの手で一掃し 勝利を収めたはずだ。だがこれはいったい何だ? 巨額の報酬と帰還チケットは? @@ -505,23 +505,22 @@ geweldige vervolg Inferno! Det stinker som råttent kjøtt, men ser ut som den tapte Deimos-basen. Ser ut som du sitter fast på Helvetes bredder. Den eneste veien ut er gjennom. -For å fortsette DOOM-opplevelsen, spill Helvetes kyster og dets fantastiske oppfølger, Inferno!","Kiedy już pokonałeś tych -bydlaków i wyczyściłeś bazę na -księżycu powinieneś wygrać, prawda? -Prawda? Gdzie jest twoja wielka -wygrana i bilet powrotny do domu? -Co to ma być u diabła? +For å fortsette DOOM-opplevelsen, spill Helvetes kyster og dets fantastiske oppfølger, Inferno!","Pokonałeś wielkich bydlaków +i wyczyściłeś bazę na księżycu, +więc powinieneś wygrać, prawda? +Prawda? Gdzie twoja wielka +nagroda i bilet powrotny do domu? +Co to ma być do diabła? To nie miało się tak skończyć! -Śmierdzi jak zgniłe mięso, ale wygląda -na opuszczoną bazę na Deimosie. +Śmierdzi jak zgniłe mięso, ale przypomina +opuszczoną bazę na Deimosie. Wygląda na to, że utknąłeś w -Przedsionku Piekieł. Nie ma odwrotu. +Przedsionku Piekieł. Nie ma już odwrotu. Aby kontynuować przygodę z DOOM-em, -zagraj w epizod Przedsionek Piekieł -oraz jego wspaniałą kontynuację, -Piekło!","Após derrotar essas criaturas miseráveis e +zagraj w ""Przedsionek piekieł"" +oraz jego niesamowitą kontynuację - ""Inferno""!","Após derrotar essas criaturas miseráveis e limpar a base lunar você deveria ter vencido, não é mesmo? Não é mesmo? Cadê a sua grande recompensa e a passagem de volta @@ -590,7 +589,23 @@ Iadului” și continuarea sa nemaipomenită, Да бисте наставили искуство DOOM-а, играјте Обале пакла и његов невероватни наставак, Инферно! -","Büyük belalıları yendikten ve ay +","När du har besegrat de stora +skurkarna och rensat månbasen +är det meningen att du ska vinna, +eller hur? Eller hur? Var är din feta +belöning och din biljett hem? Vad +i helvete är det här? Det är inte +meningen att det ska sluta så här! + +Det stinker som ruttet kött, men ser +ut som den förlorade Deimosbasen. +Det ser ut som om du är fast på +helvetets stränder. +Den enda vägen ut är genom. + +För att fortsätta DOOM-upplevelsen +kan du spela Helvetets stränder och +dess fantastiska uppföljare Inferno!","Büyük belalıları yendikten ve ay üssünü temizledikten sonra Kazanmak için, değil mi? Değil misin? Nerede? büyük ödülün @@ -667,36 +682,51 @@ den Bastarden schon zeigen, dass sie wünschten, nie von dir gehört zu haben. Nun geht es weiter zum letzten Kapitel von -DOOM - Inferno.",,"Vi sukcesis! La malbelega ciberdemono-lordo, -kiu regis la perditan Dejmo-lunbazon, -estis mortigita kaj vi estas triumfa! -Sed... kie vi estas? Vi suprenrampas al la +DOOM - Inferno.",,"Vi sukcesis! La malbelega Ciberdemono, +kiu regis la perditan lunbazon en Dejmo, +estis mortigita kaj vi triumfis! +Sed... Kie vi estas? Vi grimpas al la rando de la luno kaj rigardas malsupren -por vidi la malbonegan veron. +por vidi la malbonegan veron: -Dejmo flosas super Infero mem! -Vi neniam sciiĝis pri iu ajn eskapanta -el Infero, sed vi igos la bastardojn bedaŭri, -ke ili iam sciiĝis pri vi! Rapide, vi absejlas -malsupren al la surfaco de Infero. +Dejmo ŝvebas super la Infero mem! +Vi neniam sciiĝis pri eskapinto el la +Infero, sed nun tiuj aĉuloj bedaŭros, +ke ili ja sciiĝis pri vi! Vi surteriĝas +per ŝnuro sur la surfacon de la Infero. -Nun, ek al la fina ĉapitro de -DOOM! -- Inferno.","¡Lo lograste! ¡El horrendo Ciberdemonio que -regía la base lunar perdida de Deimos +Nun ek al la fina ĉapitro de +DOOM: «Inferno»!","¡Enhorabuena! ¡El horrendo Ciberdemonio +que regía la base lunar perdida de Deimos ha sido aniquilado y has triunfado! -Pero... ¿Dónde estás? Trepas hasta el -borde de la luna y miras abajo para -ver la horrorosa verdad. +Pero... ¿Y dónde estás? +Trepas hasta el borde de la luna y +miras abajo para ver la horrorosa verdad: ¡Deimos flota sobre el mismísimo Infierno! -Nunca has oído de alguien escapar del -Infierno, ¡pero harás que los bastardos -lamenten no haber escuchado sobre tí! -Rápidamente, desciendes a rapel +Nunca has escuchado de alguien escapar del +Infierno, ¡pero harás que esos malnacidos +se lamenten de sí haber oído sobre ti! +Rápidamente desciendes a rapel hacia la superficie del Infierno. -¡Ahora, estás en el capitulo final de -DOOM! -- Inferno.",,"Teit sen! Menetettyä Deimoksen kuutukikohtaa +¡Ahora al capítulo final de +DOOM: «Inferno»!","¡Lo lograste! ¡El horrendo Ciberdemonio +que regía la base lunar perdida de Deimos +fue aniquilado y saliste triunfando! +Pero... ¿Y dónde estás? +Trepas hasta el borde de la luna y +miras abajo para ver la horrorosa verdad: + +¡Deimos flota sobre el mismísimo Infierno! +Nunca has escuchado de alguien escapar del +Infierno, ¡pero harás que esos malnacidos +se lamenten de sí haber oído sobre ti! +Rápidamente desciendes a rapel +hacia la superficie del Infierno. + +¡Ahora al capítulo final de +DOOM: «Inferno»!","Teit sen! Menetettyä Deimoksen kuutukikohtaa hallinnut kauhistuttava kyberdemoni on surmattu ja olet voittoisa! Mutta... missä olet? Kapuat kuun kielekkeelle ja @@ -754,8 +784,8 @@ sentito parlare di te! Velocemente scendi verso la superficie dell'Inferno. -è ora del capitolo finale di -DOOM! - 'Infernò.","よくやった! 滅んだダイモス基地を支配していた +È ora del capitolo finale di +DOOM: ""Inferno""!","よくやった! 滅んだダイモス基地を支配していた サイバーデーモンはナマクラの鉄屑と化した! だが...ここは一体何処だ? 外壁の縁をよじ登りその鉄屑にも劣る現実に直面にした。 @@ -808,22 +838,21 @@ noen gang har hørt om deg! Fort, rappeller ned til helvetes overflate. Nå er det tid for siste kapittel i -DOOM! -- Inferno.","Udało ci się! Paskudny lord cyberdemon, +DOOM! -- Inferno.","Udało się! Zabiłeś paskudnego cyberdemona, który rządził opuszczoną bazą na -Deimosie został zabity i zwyciężyłeś! +Deimosie! Ale... gdzie jesteś? Wspinasz się na -krawędź księżyca i patrzysz w dół -aby ujrzeć straszną prawdę. +krawędź księżyca i patrzysz w dół, +by ujrzeć straszliwą prawdę. Deimos unosi się nad samym Piekłem! Jeszcze nigdy nie słyszałeś o kimś, -kto uciekł z Piekła, ale sprawisz, że -tym sukinsynom będzie przykro, że -kiedykolwiek usłyszeli o tobie! Prędko -schodzisz na powierzchnię Piekła. +kto by uciekł z Piekła. Te sukinsyny zapłacą za to, +że kiedykolwiek usłyszały o tobie! +Prędko schodzisz na powierzchnię Piekła. -Teraz czas na finałowy rozdział -DOOM-a! Piekło.","Você conseguiu! O hediondo líder +Czas na finałowy rozdział +DOOM-a: ""Inferno""!","Você conseguiu! O hediondo líder ciberdemônio que comandava a base lunar de Deimos foi morto e você triunfou! Mas... onde você está? @@ -895,7 +924,23 @@ DOOM — «Инферно».","Успели сте! Грозни сајбер-д пакла. Сада, остатак је на последњем поглављу -DOOM! -- Инферно.","Başardınız! İğrenç siber Kayıp +DOOM! -- Инферно.","Du har gjort det! Den avskyvärda +cyberdemonherren som styrde den +förlorade Deimos månbasen har +dödats och du är triumferande! Men ... +var är du? Du klättrar till månens +kant och tittar ner för att se de + hemska sanningen. + +Deimos svävar över själva helvetet! +Du har aldrig hört talas om någon +som har lyckats fly från helvetet, men +du kommer att få de jävlarna att ångra +att de någonsin hört talas om dig! +Snabbt stiger du ner till helvetets yta. + +Nu är det dags för det sista +kapitlet i DOOM! -- Inferno.","Başardınız! İğrenç siber Kayıp Deimos'u yöneten iblis lordu ay üssü öldürüldü ve sen muzafferdir! Ama ... nerede Sen mi? Kenarına @@ -1140,22 +1185,21 @@ Jorden mens du kjempet mot ondskapen sluppet løs. Det er bra at ingen helvetesyngel kunne ha kommet gjennom den døren -sammen med deg ...","Odrażający pajęczy demon, który był -mózgiem tej inwazji, dopuścił się -tylu śmierci, ale w końcu skopałeś -mu dupsko raz na zawsze. - -Przechodzisz przez ukryte drzwi. -Udowodniłeś, że jesteś za twardy by -demony mogły cię powstrzymać, a Piekło -poddało się -- wyłaniasz się z drzwi, -i widzisz zielone ziemskie pola! -W końcu dom. - -Zastanawiasz się co się działo na Ziemi, -kiedy ty walczyłeś z szerzącym się złem. -To dobrze, że żadne diabelstwo nie -mogło przejść przez te drzwi za tobą...","A detestável aranha demoníaca que +sammen med deg ...","Odrażający pajęczy demon, mózg +inwazji, odebrał życie wielu śmiałkom, +ale w końcu skopałeś mu dupsko. + +Twym oczom ukazuje się sekretne przejście. +Udowodniłeś, że jesteś za silny, by +demony mogły cię powstrzymać. Piekło +poddało się. Przechodzisz przez portal +i widzisz piękne ziemskie łąki! +Nareszcie w domu. + +Zastanawiasz się co cię ominęło na Ziemi, +kiedy walczyłeś z szerzącym się złem. +Całe szczęście, że żadne diabelstwo nie +poszło twoim tropem...","A detestável aranha demoníaca que esquematizou a invasão das bases lunares e causou tanta morte foi detonada para sempre. @@ -1229,7 +1273,23 @@ odată ce ai trecut prin acea ușă ...","Омерзительной демон док сте се борили против зла. Добро је што ниједно створење пакла не може проћи кроз та врата -с вама...","Ay üslerinin istilasını planlayan ve bu kadar çok ölüme neden olan iğrenç örümcek iblisin kıçı tüm zamanlar için tekmelendi. +с вама...","Den avskyvärda spindeldemon som +ledde invasionen av månbaserna och +orsakade så mycket död har fått +stryk för all framtid. + +En dold dörr öppnas och du går in. +Du har visat dig vara för tuff för att +helvetet skulle kunna hålla dig kvar, +och nu spelar helvetet äntligen rättvist - +för du kommer ut genom dörren och +ser jordens gröna fält! Äntligen hemma. + +Du undrar vad som har hänt på jorden +medan du har kämpat mot ondskan +som släppts lös. Det är bra att inga +demoner kunde ha kommit in genom +dörren med dig ...","Ay üslerinin istilasını planlayan ve bu kadar çok ölüme neden olan iğrenç örümcek iblisin kıçı tüm zamanlar için tekmelendi. Gizli bir kapı açılıyor ve içeri giriyorsunuz. Cehennem'in zapt edemeyeceği kadar güçlü olduğunu kanıtladın ve şimdi Cehennem nihayet adil davranıyor - çünkü kapıdan çıktığında Dünya'nın yeşil tarlalarını görüyorsun! @@ -1452,23 +1512,21 @@ smerte og lidelse spre seg foran deg når en nasjon av demoner går amok i byene våre. -Neste stopp, helvete på jorden!","Pajęczy Mistrz musiał wysłać swe +Neste stopp, helvete på jorden!","Pajęczy Mistrz wysłał swe diabelskie legiony tuż przed twym -finałowym starciem z bestią z Piekła. -Ale nie poddałeś się i przyniosłeś -wieczne potępienie i ból całej tej hordzie. -Każdy prawdziwy bohater by tak zrobił -w obliczu czegoś tak złego. +ostatecznym starciem z piekielną bestią. +Jednak nie poddałeś się i przyniosłeś +wieczne potępienie hordzie demonów, +niczym prawdziwy bohater. -No i musiał znaleźć się ktoś, kto pomści -śmierć Daisy - twego króliczka. +Ktoś musiał też pomścić +śmierć Daisy - twojego króliczka. -Widzisz szerzący się przed tobą ból -i lejącą się krew, których dopuściły się -hordy demonów biegające szaleńczo -pośród naszych miast. +Teraz rozumiesz ile bólu i zniszczenia +mogą wyrządzić demony hulające +po ulicach naszych miast. -Następny przystanek, Piekło na Ziemi!","A aranha-mestra deve ter enviado +Następny przystanek: Piekło na Ziemi!","A aranha-mestra deve ter enviado suas legiões de demônios antes do seu confronto final com aquela terrível besta do inferno. Mas você @@ -1548,7 +1606,23 @@ Următoarea oprire, Iadul pe Pământ!","Скорее всего паучиха- док се хорда демона креће међу нашим градовима. -Следећа станица: пакао на земљи!","Örümcek beyni, siz cehennemden gelen o korkunç canavarla yüzleşmeden önce cehennem lejyonlarını göndermiş olmalı. Ama sen öne çıktın. ve ebedi laneti getirdi ve gerçek bir kahraman gibi sürünün üzerine bu kadar şeytani bir şeyle yüzleşmek. +Следећа станица: пакао на земљи!","""Spindelhjärnan måste ha skickat ut +sina legioner av helvetesgudar före din +slutliga konfrontation med det +fruktansvärda odjuret från helvetet, men +du klev fram och förde fram evig +fördömelse och lidande över horden, +som en sann hjälte skulle göra inför +något så ondskefullt. + +Dessutom skulle någon få betala för vad +som hände Daisy, din husdjurskanin. + +Men nu ser du framför dig mer potentiell +smärta och död när en nation av demoner +löper amok bland våra städer. + +Nästa stopp: Helvetet på jorden!","Örümcek beyni, siz cehennemden gelen o korkunç canavarla yüzleşmeden önce cehennem lejyonlarını göndermiş olmalı. Ama sen öne çıktın. ve ebedi laneti getirdi ve gerçek bir kahraman gibi sürünün üzerine bu kadar şeytani bir şeyle yüzleşmek. Ayrıca, birileri bunun bedelini ödeyecekti. evcil tavşanınız Daisy'nin başına geldi. @@ -1702,17 +1776,16 @@ hjemsøkte hjerte og finne kontrollbryteren som holder jordens befolkning som gisler.","Wszedłeś w głąb zaatakowanego gwiezdnego portu. Ale coś jest nie tak. Potwory -sprowadziły ze sobą swoją własną -rzeczywistość i technologia portu jest -zdominowana przez ich obecność. +sprowadziły ze sobą własną +rzeczywistość i technologia portu +została przez nie opętana. -Widzisz przed sobą posterunek piekła, +Widzisz przed sobą piekielny posterunek, strzeżony niczym twierdza. Jeśli uda ci się -przez przejść, będziesz mógł spenetrować -nawiedzone serce bazy i znaleźć przycisk -kontrolny, przez który cała populacja -Ziemi jest trzymana w niewoli. -","Você entrou profundamente no +przejść, będziesz mógł dostać się do +nawiedzonego serca bazy i znaleźć panel +kontrolny, który wyzwoli populację +Ziemi.","Você entrou profundamente no espaçoporto infestado. Mas há algo errado. Os monstros trouxeram consigo a sua própria realidade, e a tecnologia @@ -1765,7 +1838,18 @@ de control care ține captivă populația Pământului.","Вы проникли кроз њега, моћи ћете да се пробијете до самог уклетог срца старбазе и да нађете контролишyће дугме које држи све -становништво земље таоце.","İstila edilmiş yıldız üssünün +становништво земље таоце.","""Du har gått djupt in i den infekterade +stjärnhamnen. Men något är fel. +Monstren har fört med sig sin egen +verklighet, och stjärnhamnens teknik +undergrävs av deras närvaro. + +Framför dig ser du en utpost av helvetet, +en befäst zon. Om du kan ta dig förbi +den kan du tränga in i stjärnbasens +hemsökta hjärta och hitta den +kontrollbrytare som håller jordens +befolkning som gisslan.","İstila edilmiş yıldız üssünün derinliklerine girdiniz. Ama yanlış giden bir şeyler var. Canavarlar kendi gerçekliklerini de @@ -2042,24 +2126,24 @@ blokkere inngangen deres. Den utenomjordiske basen ligger i hjertet av din egen hjemby, ikke langt fra stjernehavnen."""" ""Sakte og smertefullt reiser du deg og -vender tilbake til kampen.""","Wygrałeś! Twa wygrana umożliwiła -ludzkości ewakuację Ziemi i ucieczkę -z tego koszmaru. Jesteś teraz jedynym -człowiekiem, który został na powierzchni -planety. Ludożercze mutacje, mięsożerni +vender tilbake til kampen.""","Wygrałeś! Dzięki twej brawurze populacja +Ziemi mogła uciec z tego koszmaru. +Jesteś teraz jedynym +człowiekiem na planecie. +Ludożercze mutacje, krwiożerczy obcy oraz złe duchy są twymi jedynymi sąsiadami. Siadasz i czekasz na śmierć, -zadowolony z tego, że uratowałeś swój +ciesząc się, że uratowałeś swój gatunek. -Nagle, centrum dowodzenia wysyła +Nagle... Centrum dowodzenia wysyła wiadomość z kosmosu: ""Sensory -zlokalizowały źródło inwazji obcych. Jeśli -tam pójdziesz, będziesz mógł zablokować -im wejśce. Baza obcych znajduje się +zlokalizowały źródło inwazji obcych. +Pójdź tam, a zdusisz inwazję w zarodku. +Baza obcych znajduje się w centrum twojego rodzinnego miasta, -niedaleko portu kosmicznego."" -Powoli i z bólem wstajesz i wracasz do boju.","Você venceu! Sua vitória permitiu que a +niedaleko portu kosmicznego"". +Wstajesz cały obolały i wracasz do boju.","Você venceu! Sua vitória permitiu que a humanidade evacuasse a Terra e escapasse desse pesadelo. Agora você é @[ao_ptb] únic@[ao_ptb] human@[ao_ptb] que resta na face do planeta. @@ -2141,7 +2225,25 @@ la luptă.","Вы победили! Благодаря вашему триумф ванземаљска база се налази у вашем родном граду, недалеко од старпорта.“ Полако и безвољно устајете да би се вратили -у окршај.","Siz kazandınız! Zaferiniz sayesinde +у окршај.","Du har vunnit! Er seger har gjort det +möjligt för mänskligheten att eva- +kuera jorden och fly från mardrömmen. +Nu är du den enda människan som +finns kvar på planeten. Kannibalmutationer, +köttätande utomjordingar och onda andar +är dina enda grannar. Du sitter tillbaka och +väntar på döden, nöjd med att du har +räddat din art. + +Men så strålar Earth Control ner ett +meddelande från rymden: ""Sensorerna +har lokaliserat källan till den utomjordiska +invasionen."" Om du går dit kan du kanske +blockera deras inträde. Den utomjordiska +basen ligger i hjärtat av din egen +hemstad, inte långt från stjärnhamnen."" +Långsamt och smärtsamt reser du +dig upp och återvänder till striden.","Siz kazandınız! Zaferiniz sayesinde İnsanlık dünyayı boşaltıp kaçacak kabus. Şimdi tek sen varsın Gezegende insan kalmadı. @@ -2281,14 +2383,13 @@ den på den andre siden. Hva bryr det deg om du må gå gjennom helvete for å komme til den?","Jesteś w skażonym sercu miasta, otoczony -przez zwłoki twych wrogów. Nie widzisz -sposobu, by zniszczyć z tej strony -bramę potworów więc zaciskasz zęby -i postanawiasz przez nią przejść. +przez zwłoki swych wrogów. Nie wiesz +jak zniszczyć bramę więc zaciskasz zęby +i przez nią przechodzisz. Musisz jakoś ją zamknąć z drugiej -strony. A co cię obchodzi, że musisz przejść -przez piekło, by to zrobić?","Você consegue chegar no centro infestado +strony. Czy to takie straszne, +że najpierw musisz przejść przez piekło?","Você consegue chegar no centro infestado da cidade, cercado pelos cadáveres de seus inimigos. Você percebe que não há como destruir a passagem de entrada @@ -2331,7 +2432,16 @@ să o descoperi?","Вы стоите в осквернённом сердце г Мора постојати начин да се пролаз уништи са друге стране. Шта вас брига ако -морате проћи пакао да би сте га нашли?","Şehrin yozlaşmış kalbindesiniz, +морате проћи пакао да би сте га нашли?","""Du befinner dig i stadens korrupta hjärta, +omgiven av dina fienders lik. Du ser inget +sätt att förstöra varelsernas ingång på +den här sidan, så du biter ihop tänderna +och kastar dig igenom den. + +Det måste finnas ett sätt att stänga den +på andra sidan. Vad bryr du dig om du +måste gå igenom helvetet för att +komma dit?","Şehrin yozlaşmış kalbindesiniz, etrafınız düşmanlarınızın cesetleriyle çevrili. Bu taraftaki geçidi yok etmenin bir yolunu @@ -2543,21 +2653,20 @@ vandringen hjem. Det burde være mye morsommere å gjenoppbygge jorden enn å ødelegge den.","Przerażające oblicze największego demona, jakiego kiedykolwiek spotkałeś, -rozpada się po tym jak napompowałeś -rakietami jego obnażony mózg. +rozpada się po tym jak wysadziłeś +jego obnażony mózg. Potwór usycha i umiera, a jego obumierające kończyny niszczą -piekło aż po horyzont. +piekło wzdłuż i wszerz. -Udało ci się. To koniec inwazji. Ziemia +Udało ci się. Koniec inwazji. Ziemia jest uratowana. Piekło jest w rozsypce. Zastanawiasz się gdzie teraz całe zło się podzieje. Wycierając pot z czoła zaczynasz długą wedrówkę do domu. Odbudowa Ziemi powinna być większą frajdą niż jej -niszczenie. -","A visão horrenda do maior demônio que +niszczenie.","A visão horrenda do maior demônio que você já viu desmorona na sua frente depois de você lançar alguns foguetes dentro do seu cérebro exposto. Ele @@ -2627,7 +2736,21 @@ siguranță mai distractivă decât a fost ruinarea lui.","Леденящий д зној са чела, почињете дугачак пут кyћи. Поновна изградња земље би требала бити забавнија од уништења исте. -","Gördüğünüz en büyük iblisin +","""Den största demonen som du någonsin +har sett faller ihop framför dig efter att +du har pumpat in dina raketer i hans +utsatta hjärna. Monstret skrumpnar +ihop och dör, dess slående lemmar +ödelägger otaliga mil av helvetets yta. + +Du har gjort det. Invasionen är över. +Jorden är räddad. Helvetet är ett vrak. +Du undrar vart de onda människorna +tar vägen när de dör, nu. Du torkar +svetten från pannan och börjar den +långa vandringen hemåt. Att +återuppbygga jorden borde vara mycket +roligare än vad det var att förstöra den.","Gördüğünüz en büyük iblisin korkunç görüntüsü, roketlerinizi açıktaki beynine pompaladıktan sonra önünüzde parçalanıyor. @@ -2723,7 +2846,11 @@ acestuit colț de infern.","Поздравляем, вы нашли секрет в этом уголке преисподней.","Честитамо, пронашли сте скривени ниво! Изгледа да је био изграђен од стране људи, а не монструма. Размишљате ко -ће бити становници овог дела пакла.","Tebrikler. Gizli seviyeyi buldunuz! +ће бити становници овог дела пакла.","Grattis, du har hittat den hemliga nivån! +Det ser ut som om den har byggts av +människor, snarare än demoner. Du +undrar vilka de intagna i detta hörn +av helvetet kommer att vara.","Tebrikler. Gizli seviyeyi buldunuz! Şeytanlar değil de İnsanlar tarafından inşa edilmiş gibi görünüyor. Cehennemin bu @@ -2769,7 +2896,9 @@ să termini rapid cu el!","Поздравляем, вы нашли сверхс уровень! И здесь вас вновь ждут кин-о и немцы.","Честитамо, пронашли сте супер скривени ниво! -Боље да пролетите кроз ово!","Tebrikler, süper gizli seviyeyi +Боље да пролетите кроз ово!","Grattis, du har hittat den superhemliga +nivån! Det är bäst att du tar dig igenom +den här!","Tebrikler, süper gizli seviyeyi buldunuz! Bunu geçsen iyi olur!" "You gloat over the steaming carcass of the Guardian. With its death, you've wrested @@ -3012,7 +3141,18 @@ trăiești, de asemenea.","Вы злорадствуете над дымящим муке протраћене. Наставите да се крећете, наставите да се борите, наставите да убијате. -И да, наставите и да живите.","Muhafız'ın dumanı tüten leşi +И да, наставите и да живите.","Ni gläds åt Väktarens rykande kadaver. +Med dess död har du vridit Acceleratorn +ur helvetets stinkande klor. Du slappnar +av och tittar runt i rummet. Fan! Det +skulle finnas åtminstone en fungerande +prototyp, men du kan inte se den. +Demonerna måste ha tagit den. + + Du måste hitta prototypen, annars har +all din kamp varit bortkastad. Fortsätt +röra på dig, fortsätt kämpa, fortsätt +döda. Åh ja, fortsätt att leva också.","Muhafız'ın dumanı tüten leşi üzerinde kına yakıyorsunuz. Onun ölümüyle Hızlandırıcı'yı Cehennem'in kokuşmuş @@ -3138,7 +3278,13 @@ Te pricepi la chestii de genul.","Даже смертоносный лабири прототип акцелератора који ће ускоро ефикасно бити деактивиран заувек. -Добри сте у таквим стварима.","Ölümcül Baş Aşağılık labirenti bile +Добри сте у таквим стварима.","Inte ens den dödliga Ärkevild-labyrinten +kunde stoppa dig, och du har nått fram +till prototypen av Acceleratorn som +snart är effektivt och permanent +avaktiverad. + +Du är bra på den typen av saker.","Ölümcül Baş Aşağılık labirenti bile seni durduramaz, ve sen prototip Hızlandırıcı yakında etkili ve kalıcı olarak devre dışı bırakıldı. @@ -3320,7 +3466,17 @@ pregătești să-i dai o mamă de bătaie ticălosului.","С боем и гро Са злобним изразом проверавате опрему, и припремате се да дате том кучкином сину мало пакла од -сопственог стварања!","İblis kovanının kalbine giden yolda +сопственог стварања!","Du har slagit och slagit dig in i +djävulskyrkans hjärta. Dags för ett +uppdrag att söka och förstöra, +riktat mot Portvakten, vars avkommor +som sprider sig till jorden. Ja, han är +ond. Men du vet vem som är värre! + +Med ett illvilligt flin kontrollerar du din +utrustning och gör dig redo att ge +jäveln ett litet helvete som du själv +har skapat!","İblis kovanının kalbine giden yolda savaştınız. İğrenç köleleri Dünya'yı istila eden Kapı Bekçisi'ni hedef alan bir Arama ve Yok Etme @@ -3537,7 +3693,19 @@ pentru ultima dată ...","От зловещего лика Привратник Не заборавите да кажете својим унучади да вам ставе ракетни бацач у ковчег. Ако одете у пакао када умрете, треба ће вам -за последње чишћење...","Kapı Bekçisi'nin şeytani yüzü her +за последње чишћење...","Portvaktens onda ansikte är utspridd +överallt. När dess söndertrasade lik +kollapsar bildas en inverterad port +som suger ner skärvorna av den sista +prototypen av acceleratorn, för att inte +nämna de få återstående demonerna. +Du är klar. Helvetet har återgått till att +slå på dåliga döda människor i stället +för goda levande. Kom ihåg att be dina +barnbarn att lägga en raketkastare i din +kista. Om du kommer till helvetet när +du dör kommer du att behöva den +för att göra en sista städning ...","Kapı Bekçisi'nin şeytani yüzü her yerde. Parçalanmış cesedi gibi çöker, ters bir geçit oluşur ve son parçalarını emer prototip @@ -3629,7 +3797,11 @@ soldați marini maeștri.","Вы нашли второй по сложности који имамо. Надамо се да сте сачували игру ниво или два назад. Ако нисте, припремите се да умрете пуно пута. -Само за маестро маринце.","Elimizdeki en zor ikinci seviyeyi buldun. +Само за маестро маринце.","Du har hittat den näst svåraste nivån +vi har. Hoppas att du har ett sparat +spel en nivå eller två tidigare. Om inte, +var beredd på att dö i mängder. +Endast för master marines.","Elimizdeki en zor ikinci seviyeyi buldun. Umarım bir ya da iki seviye öncesine ait kayıtlı bir oyununuz vardır. Eğer yoksa, bolca ölmeye hazır olun. @@ -3689,7 +3861,10 @@ Nimeni nu scapă viu.","Вы наверняка гадали, каков же с приготовили? Ну, теперь вы знаете. Никто не уйдёт живым.","Гладимо се да сте се питали који је НАЈТЕЖИ ниво који смо спремили за -вас? Сада знате. Нико не излази жив.","Eminim elimizdeki en zor seviyenin +вас? Сада знате. Нико не излази жив.","Du undrade säkert vad som var den +svåraste nivån vi hade redo för dig? +Nu vet du det. +Ingen kommer ut levande.","Eminim elimizdeki en zor seviyenin ne olduğunu merak etmişsinizdir. Artık biliyorsunuz. Kimse canlı çıkamayacak." @@ -3804,7 +3979,7 @@ impiegati di questi tempi... Più avanti si trova il complesso militare, ora infestato da orrori malati, ansiosi di -mettere i loro denti su di te. Con un pò +mettere i loro denti su di te. Con un po' di fortuna nel complesso potrebbero ancora esserci delle armi in giro.","侵略された研究施設を抜け出すことが出来た。 UACはまたもやられてしまったようだ。 @@ -3885,7 +4060,18 @@ niște artilerie de război pe undeva.","Вам удалось вырватьс најежден мртвим хорорима који једва чекају да уроне зубе у вама. Са срећом, комплекс идаље има неко оружје које -лежи унаоколо.","İstilaya uğradığın yerden savaşarak +лежи унаоколо.","Du har kämpat dig ut ur de infekterade +experimentlaboratorierna. Det verkar +som om UAC återigen har ställt till det. +Med sin höga omsättning måste det +vara svårt för stackars UAC att köpa +en företagsförsäkring nuförtiden... + +Framför oss ligger militärkomplexet, +som nu kryllar av sjuka skräckinjagare +som är heta på att sätta tänderna i dig. +Med lite tur har komplexet fortfarande +lite krigsmateriel som ligger kvar.","İstilaya uğradığın yerden savaşarak çıktın. deneysel laboratuarlar. Görünüşe göre UAC bir kez daha yuttu. Onların yüksek ciro, yoksullar @@ -4063,7 +4249,17 @@ N-ai de gând să cazi la pământ prea ușor.","Впереди вы слыши спакована две хиљада манијака у једног побеснолог убицу. -Не планирате да паднете тако лако.","İleride ağır makinelerin gıcırtılarını +Не планирате да паднете тако лако.","Du hör slipandet av tunga maskiner i +huvudet. Du hoppas verkligen att de +inte stampar fram nya helvetesdjur, +men du är redo att slå ut en hel +hjord om du måste. +De kanske planerar en blodfest, men +du känner dig ungefär lika elak som +två tusen galningar packade i en +enda galen mördare. + +Du planerar inte att gå ner lätt.","İleride ağır makinelerin gıcırtılarını duyuyorsunuz. Yeni iblisler üretmediklerini umuyorsunuz ama gerekirse bütün bir sürüyü ortadan @@ -4227,7 +4423,16 @@ Timpul să notezi niște nume.","Открывшийся вашему взору Што више зиљите у њега, то више сте љути. Подижући своју пишку, зао кез се оформио на вашем лицу. -Време је за убијање.","İleride açılan manzara gerçekten +Време је за убијање.","Utsikten som öppnar sig framför oss +ser jävligt bekant ut. Den luktar också +bekant - som stekt avföring. Du +gillade inte det här stället förut, och +du planerar inte att gilla det nu. Ju +mer du grubblar på det, desto +argare blir du. +Du lyfter din pistol och får ett +ondskefullt flin i ansiktet. +Dags att ta några namn.","İleride açılan manzara gerçekten çok tanıdık geliyor. Kokusu da tanıdık, kızarmış dışkı gibi. Bundan hoşlanmayacağın kesin. Düşündükçe @@ -4428,7 +4633,18 @@ de demoni.","Внезапно всё умолкает, с одного края Нешто тутњи у даљини. Плава светлост почиње да светли унутар -уништене лобање избацивача демона.","Birdenbire, bir ufuktan diğerine her şey +уништене лобање избацивача демона.","Plötsligt är allt tyst, från den ena +horisonten till den andra. Helvetets +plågsamma eko bleknar bort, +mardrömshimlen blir blå, högarna av +monsterkadaver börjar avdunsta +tillsammans med den onda stanken +som fyllde luften. Jösses, du kanske +har gjort det. Har du verkligen vunnit? + +Något mullrar i fjärran. +Ett blått ljus börjar glöda inuti +demonspridarens förstörda skalle.","Birdenbire, bir ufuktan diğerine her şey sessizleşir. Cehennemin acı veren yankısı kaybolur. Kabus gökyüzü maviye döner. Canavar ceset yığınları, @@ -4528,7 +4744,13 @@ fi cel mai bine să lași zeii adormiți să zacă...","Ну что теперь овде било не може бити горе од убичајеног. Или може? Или је можда најбоље да се допусти да успавани -богови леже...","Şimdi ne oldu? Tamamen farklı +богови леже...","Vad händer nu? +Det ser helt annorlunda ut. +Ungefär som King Tut's lägenhet. +Det som finns här kan inte vara +värre än vanligt. Eller hur? +Eller så är det kanske bäst att låta +sovande gudar ligga...","Şimdi ne oldu? Tamamen farklı görünüyor. Kral Tut'un evi gibi. Burada her ne varsa normalden daha kötü olamaz. Değil mi? @@ -4715,7 +4937,18 @@ grei ai pantofilor de fier ai ciberdemonului.","Пора устроить отп зградама, и вероватно нема демона. Корачате ван својег транспорта, и чујете -удар челичног копита сајбердемона.","Tatil zamanı. Cehennemin +удар челичног копита сајбердемона.","Dags för semester. Du har sprängt +helvetets inälvor och du är redo för +en paus. Du mumlar för dig själv, +Kanske någon annan kan spöa +helvetet nästa gång. Framför dig +ligger en lugn stad, med fridfullt +rinnande vatten, pittoreska byggnader +och förmodligen inga Hellspawn. + +När du kliver av transporten hör du +stampandet av en cyberdemons +järnsko.","Tatil zamanı. Cehennemin bağırsaklarını patlattınız ve bir mola için hazırsınız. Belki bir dahaki sefere başka biri Cehennem'in kıçını @@ -5076,7 +5309,26 @@ Călătoria s-a încheiat.","Очередная заварушка намети посмртни јаук грогори из збрке од лице са којем сте га вам оставили. -Ова атракција је затворена.","En sevdiğin tatil yerinde yine sorun +Ова атракција је затворена.","""Det var återigen oroligt på din +favoritsemesterplats... Helvetet. +Någon Cyberdemon-punk trodde att +han kunde förvandla helvetet till en +personlig nöjespark och göra +jorden till biljettkassan. + +Tja, den där halvrobot-freakshowen +visste inte vem som skulle komma till +tivoli. Det finns inget bättre än en +skjutbana full av helvetesgödsel +för att få blodet att pumpa... + +Nu ekar väggarna i demonens labyrint +med ljudet av hans metalliska lemmar +som slår i golvet. Hans dödsstön gurglar +ut genom den röra du lämnade av hans +ansikte. + +Den här föreställningen är stängt.","En sevdiğin tatil yerinde yine sorun çıkıyordu... Cehennem'de. Siber iblisin teki Cehennem'i kişisel bir eğlence parkına dönüştürebileceğini ve @@ -5346,7 +5598,7 @@ outro lado. Claro que isso significa que você pode ficar pres@[ao_ptb] num lugar nada amigável, mas ninguém jamais disse que ser herége era fácil.",,"Odată cu distrugerea Cadavrelor de Fier și ai -minionilor lor, ultimii nemorți dispar din acest +minionilor, ultimii nemorți dispar din acest plan al existenței. Aceste creaturi trebuie să fii venit de undeva, și ai @@ -5385,7 +5637,24 @@ fii un eretic!","С уничтожением железных личей друге стране. Наравно то значи да ћете можда заглавити у непријатељском свету, али нико није реко да је лако бити -јеретик.","Demir cesetlerin ve yardakçılarının +јеретик.","I och med förintelsen av järnlicherna +och deras hantlangare har de sista +odöda försvunnit från det här +existensplanet. + +Dessa varelser måste dock ha +kommit någonstans ifrån, och du har +en lömsk misstanke om att den eldiga +portalen i helvetets gap öppnar sig på +deras hemdimension. + +För att se till att inte fler odöda (eller +ännu värre saker) kommer igenom +måste du försegla Helvetets gap +från andra sidan. Naturligtvis innebär +detta att du kan fastna i en mycket +ovänlig värld, men ingen har någonsin +sagt att det är lätt att vara kättare!","Demir cesetlerin ve yardakçılarının yok edilmesiyle, son yaşayan ölüler de bu âlemden uzaklaştırılmış oldu. @@ -5676,7 +5945,7 @@ crudă că au fost distruși. Poarta care era păzită de ei e acum deschisă, dezvăluind ceea ce tu sperai să fie drumul spre casă. Dar o dată ce pășești prin ea, râset batjocoritor -îți sună în urechi. +îți răsună în urechi. Să fii fost o altă forță în spatele maulotaurilor? Să fie oare creaturi și mai oribile dincolo de acest portal? @@ -5710,7 +5979,25 @@ siguranță nu e un semn bun...","Могучие избитавры поверж минотауре? Да ли су још ужасавајуће ствари кроз ову капију? Замах кристалне куполе где би требало да буде небо -сигурно није добар знак.","Kudretli maulotorlar kanıtladı seninle +сигурно није добар знак.","De mäktiga maulotaurerna har visat +sig inte vara någon match för er, och +när deras ångande lik glider ner på +marken känner du en känsla av grym +tillfredsställelse över att de har +förintats. + +Portarna som de vaktade har öppnats +och avslöjat vad du hoppas är vägen +hem. Men när du kliver igenom ringer +ett hånfullt skratt i dina öron. + +Var det någon annan kraft som +kontrollerade maulotaurerna? Kan det +finnas ännu mer hemska varelser +bakom den här porten? En +kristallkupol över himlen där himlen +borde vara är verkligen inget bra +tecken...","Kudretli maulotorlar kanıtladı seninle boy ölçüşemez, ve dumanı tüten cesetleri acımasızlık hissi uyandırır oldukları için memnuniyet yok edildi. @@ -6099,7 +6386,26 @@ Dar din nou, cu ceilalți Călăreți cum rămâne?","С гибелью Д'Сп можда је само био врисак. Али ипак, шта је са осталим јахачима -змија?","D'Sparil'in ölümü, yaratıklarını bu +змија?","D'Sparils död har lossat de magiska +band som håller hans varelser på detta +plan, deras dödliga skrik överväldigade +hans egna skrik av plågor. + +Din hämndens ed uppfylld, går du in i +portalen till din egen värld, bara några +ögonblick innan kupolen splittras i +en miljon bitar. + +Men om D'Sparils makt är bruten för +alltid, varför känner du dig då inte +trygg? Var det det sista ropet strax +före hans död, det som lät som en +förbannelse? Eller en kallelse? Du kan +inte riktigt vara säker, men det kan +ha varit ett skrik. + +Men å andra sidan, +hur är det med de andra ormryttarna?","D'Sparil'in ölümü, yaratıklarını bu alemde tutan büyülü bağları kopardı, onların ölüm çığlıkları kendi acı çığlıklarını bastırdı. @@ -6465,7 +6771,26 @@ proprii lui gardieni îți așteaptă sosirea ...","С гибелью Д'Спа нађете излаз. И негде, у најмрачнијим ћошковима Д'Спариловог поседа, његови лишни телохранитељи -чекају ваш долазак.","Kendi evine döneceğini sanıyordun. +чекају ваш долазак.","Du trodde att du skulle återvända till +din egen värld efter D'Sparils död, men +hans sista handling förvisade dig till +hans eget plan. Här gick du in i +krossade resterna av de länder som +D'Sparil erövrade. Du besegrade de +sista väktarna av dessa länder, men +nu står du framför portarna till D'Sparils +fäste. Fram till det här ögonblicket hade +du inga tvivel om din förmåga att möta +allt som du skulle kunna möta, men +bortom den här portalen ligger själva +hjärtat av den ondska som invaderade +din värld. D'Sparil må vara död, men +gropen där han föddes finns kvar. Nu +måste du gå in i den gropen i hopp om +att hitta en väg ut. Och någonstans, i +det mörkaste hörnet av D'Sparils rike, +väntar hans personliga livvakter på +din ankomst ...","Kendi evine döneceğini sanıyordun. D'Sparil öldükten sonra kendi dünyasına döndü. son eylemi seni sürgüne gönderdi kendi uçağı. İşte @@ -6809,7 +7134,25 @@ destinul.","Наблюдая с мрачным отвращением у лице очајања? Да ли имате храброст? Налазите, да у себи није да се предате без борбе. Широких очију, идете да -упознате своју судбину.","Son maulotor kükrerken ölüm acısı, +упознате своју судбину.","När den sista maulotauren ropar sin +dödsagoni inser du att du aldrig har +varit så nära din egen förintelse. Inte +ens kampen mot D'Sparil och hans +lärjungar hade varit så desperat. Grimt +stirrar du på portarna som öppnar +sig framför dig och undrar om de leder +hem eller om de öppnar sig mot någon +oanade skräck. Du finner dig själv +undra om du har styrkan att fortsätta, +om inget annat än död och smärta +väntar dig. Men vad kan man göra om +viljan att kämpa är borta? Kan du +tvinga dig själv att fortsätta när du +står inför en sådan förtvivlan? Har du +modet? Till slut upptäcker du att det +inte finns inom dig att ge upp utan strid. +Med stora ögon går du ditt öde till +mötes.","Son maulotor kükrerken ölüm acısı, fark edersin ki hiç bu kadar yaklaş- mamıştın. Yıkım. Savaş bile değil D'Sparil ve müritleri bu kadar çaresiz. @@ -7168,7 +7511,24 @@ la fiecare efort pe care îl faci.","Вы прошли семь порталов А негде далеко, у дубинама бесконачног хипостила, оживели су и сами зидови како би -оптеретили сваки Ваш корак.","Bu diyarı mühürleyen yedi kapıyı +оптеретили сваки Ваш корак.","Efter att ha passerat de sju portaler +som förseglade den här världen, +sträcker sig ett stort område med hård +vildmark framför dig. Eld, is och stål har +testat dig, men större utmaningar +återstår. Det täta virrvarret av skog +döljer säkert fientliga ögon, men det som +ligger bortom kommer att vara värre. + +Karg öken, fuktiga träsk och mossiga +grottor spärrar din väg, men du kan inte +låta något hindra dig från ditt öde, även +om du kanske önskar att det skulle +göra det. + +Och bortom, flimrande i fjärran, tycks +hypostilens ständigt skiftande +väggar håna dina ansträngningar.","Bu diyarı mühürleyen yedi kapıyı geçtikten sonra, önünüzde uçsuz bucaksız bir vahşi doğa uzanıyor. Ateş, buz ve çelik sizi sınadı ama @@ -7511,7 +7871,24 @@ cum vei putea ieși de aici vreodată?","Едва переведя дух пос О богови смрти, какво је ово место? О богови бола, како се може изићи -из њега?","Zihniniz hâlâ hipostil içindeki karşı- +из њега?","Ditt sinne är fortfarande i upplösning +efter dina möten i hypostylen. Du +vacklar mot vad du hoppas är en väg +ut. Saker och ting verkar gå snabbare +och snabbare, din syn suddas ut och +börjar blekna... +Medan världen kollapsar runt omkring +dig, uppslukas du av ljuset från en +teleportal. En ljusblixt, och sedan +klättrar du trött på dina fötter. + +Du står på toppen av ett högt torn, och +underifrån kommer de fördömdas skrik. +Du kliver fram, och genast får ljudet av +demonisk sång ditt blod att rysa. +Vid alla dödsgudar, till vilken plats har +du kommit? Vid alla smärtans gudar, +hur ska du någonsin hitta ut?","Zihniniz hâlâ hipostil içindeki karşı- laşmalarınızdan dolayı sersemlemiş durumda. Bir çıkış yolu olduğunu umduğun şeye doğru sendeliyorsun. @@ -7854,7 +8231,26 @@ tine. Undeva în interior, dușmanii te așteaptă...","Сил могущест злобних очију из таме. Непријатељи, чекајући Ваш долазак, -вребају унутра...","Kadimlerin en güçlü silahları ve eserleri +вребају унутра...","De mäktigaste vapnen och arte- +fakterna från de forntida räckte knappt +till för att besegra heresiarken och +hans hantlangare, men nu ligger deras +vidriga kvarlevor utspridda vid dina +fötter. Genom att samla dina sista +krafter förbereder du dig för att gå in i +portalen som leder från heresiarkens +inre helgedom. + +Ovanför dig skymtar vallarna till ett +enormt slott. Tysta torn och kala +väggar omger en enda spira av svart +sten, som sitter i mitten av slottet +som en grubblande jätte. Eld och +skugga vrider sig bakom gapande +fönster, dussintals ondskefulla +ögon stirrar ner på dig. +Någonstans där inne väntar dina +fiender...","Kadimlerin en güçlü silahları ve eserleri kâfir hükümdarı ve yardakçılarını yenmeye ancak yetti, ama şimdi onların iğrenç kalıntıları ayaklarınızın dibine @@ -8054,7 +8450,17 @@ Firar să fie.","«...И сойдёт он в царство мёртвых, -Проклетство.","""... ve ölüler diyarına yolculuk edecek +Проклетство.",""".... och han skall resa in i de dödas +rike och tävla med krafterna där, +till själva porten till förtvivlan. +Men om han skall återvända +till ljusets värld vet ingen."" + + + + + + Fan.","""... ve ölüler diyarına yolculuk edecek ve oradaki güçlerle umutsuzluğun kapılarına kadar mücadele edecek. Ama tekrar ışık dünyasına dönüp @@ -8217,7 +8623,15 @@ sursă de lumină din această lume.","Внезапно вас окутал ог напуњеној сабласним одјецима и грозним, непознатим сенкама. С уздигнутог положаја, близу Вас, -тече усамљено светло.","Acı dolu bir çığlıkla bu dünyadan +тече усамљено светло.","Med ett skrik av smärta slits du från +den här världen till en annan, varenda +del av din kropp är omgiven av +mystisk eld. När din syn klarnar +finner du dig själv stå i en stor hall, +fylld av spöklika ekon och hotfulla +skuggor. I fjärran kan du se en +upphöjd dais, och på den den +enda ljuskällan i den här världen.","Acı dolu bir çığlıkla bu dünyadan başka bir dünyaya savruluyorsunuz, vücudunuzun her parçası mistik bir ateşle kaplanıyor. Görüşünüz @@ -8403,7 +8817,18 @@ tabla e în mâinile tale.","Это сфера хаоса, источник си васељенску шаховску таблу, попут ништавног пешака који служи своме краљу и, издавши га, заузме -улогу краљице.","Bu sadece Korax'ın gücünün kaynağı +улогу краљице.","Detta kan bara vara kaos-sfären, +källan till Korax kraft. Med denna +kan du skapa världar... eller förstöra +dem. Genom stridens och erö- +vringens rättigheter är den din, och +med darrande händer sträcker du dig +för att ta tag i den. Kanske kommer +nu en ny spelare att ansluta sig till +det kosmiska spelet om makt. Likt +en bonde som befordras till drottning +verkar plötsligt brädans yttersta +räckvidd vara inom räckhåll för dig.","Bu sadece Korax'ın gücünün kaynağı olan kaos küresi olabilir. Bununla dünyalar yaratabilirsin... ya da onları yok edebilirsin. Savaş ve fetih @@ -8450,7 +8875,9 @@ puternici decât tine, și cine le-ar putea anticipa următoarele mișcări?","\n...Но есть более опытные игроки, и кому ведомы их дальнейшие ходы?","\nАли постоје и искуснији играчи, а коме су познати њихови даљњи -потези?","\nAma senden daha güçlü başka +потези?","Men det finns andra spelare som +är mäktigare än du, och vem kan +känna till deras nästa drag?","\nAma senden daha güçlü başka oyuncular da var. Sonraki hamleler?" "Wiping a trembling hand across your @@ -8765,12 +9192,12 @@ continuare... ...și să uiți ce ai lăsat în urmă. În depărtare, meterezele unui falnic castel par -să spintece cerul de deasupra, iar mirosul +să spintece cerul, iar mirosul decadenței se răspândește de la mormintele profanate ale nenumăraților morți. Numărând atent ce mai rămâne din artefactele tale, -încerci să te reasiguri ca vor fi suficiente. Până la +încerci să te reasiguri că vor fi suficiente. Până la urmă, vor trebui să fie de ajuns, nu-i așa? @@ -8803,7 +9230,25 @@ Nu-i așa?","Отерев кровь с лица дрожащей рукой, Пажљиво бројите шта ти је остало од артефакта и пробате се поново уверити да ће бити довољно. На крају крајева, треба да буде довољно, је ли тако? -Је ли тако?","Titreyen elinizi kanayan yüzünüze silerek, +Је ли тако?","Du stryker en darrande hand över ditt +blödande ansikte och försöker rensa +ditt sinne för det som väntar dig... + +...och glömma det som ligger bakom. + +I fjärran tycks de karga vallarna till +ett stort slottsanläggning slita sönder +himlen ovanför, och stanken av +förruttnelse vajar från de våldtagna +gravarna av oräkneliga döda. + +När du noggrant räknar det som +återstår av dina artefakter försöker du +försäkra dig själv om att det kommer +att räcka. Det måste ju räcka, eller hur? + + + eller hur?","Titreyen elinizi kanayan yüzünüze silerek, önünüzdekiler için zihninizi temizlemeye çalışıyorsunuz... @@ -9104,7 +9549,7 @@ morte fria e prolongada... -...para os fortunados.",,"Cu siguranță că sufletele blestemaților habituează +...para os fortunados.",,"Cu siguranță că sufletele blestemaților populează această lume, considerând faptul că nimic drept și bun nu poate supraviețui aici pentru multă vreme. @@ -9154,7 +9599,26 @@ lentei, reci morți... -...за срећнике.","kesinlikle lanetlenmişlerin ruhları bu +...за срећнике.","Säkert bor de fördömdas själar i denna +värld, för inget rättvist eller gott skulle +kunna överleva här länge. + + Men det som har passerat tidigare +kan bara vara en blek skugga av det +som hindrar din passage nu: själva +det mörka citadellet. + +Katedralens dystra massa blockerar +alla utom fragmentariska glimtar av +själva citadellet, men det som kan ses +talar i svischande viskningar om kall, +kvardröjande död... + + + + + + ...för de lyckligt lottade.","kesinlikle lanetlenmişlerin ruhları bu dünya, hiçbir şey için adil ya da iyi burada uzun süre hayatta kalabilirdi. @@ -9368,7 +9832,18 @@ ești urmărit de ochi ascunși... било тихо шапутање, осећај да вас неко посматра скривеним очима... -...очи које штите злобну намеру.","Kendinizi bir kez daha kaos küresinin +...очи које штите злобну намеру.","Ännu en gång befinner du dig i den +stora salen i kaos-sfären, som om +ingen tid hade gått sedan du senast +rörde dig bland dessa skuggor. + +Men något är kusligt annorlunda, +en tystnad där det en gång hade +varit mjuka viskningar, en känsla +av att bli iakttagen av dolda ögon... + +...ögon som skyddar en ondskefull +avsikt.","Kendinizi bir kez daha kaos küresinin büyük salonu üzerinden hiç zaman geçmemiş olsaydı en son bu gölgeler arasında hareket etmiştin. @@ -9632,7 +10107,21 @@ dea înlături de la o provocare...","Когда-то вы уже владели Али још увек, нисте били од оних који се повлаче од изазова... -","Bir zamanlar kaos küresini kavradın, +","En gång i tiden greppade du kaos- +sfären, höll den i darrande händer. Nu +darrar dina händer av något mer än +girighet, och rädsla förenas med +hunger efter makt. + +Om inte ens sfärens kraft är tillräcklig +för att skydda dig från mörkrets krafter +är det kanske bättre att lämna den +orörd, att inte hålla dess löfte. + + + +Men du var aldrig den som +backade från en utmaning...","Bir zamanlar kaos küresini kavradın, titreyen ellerinde tuttun. şimdi ellerin açgözlülükten daha fazla bir şeyle titriyor ve dehşet güç açlığıyla birleşiyor. @@ -9657,1069 +10146,1079 @@ lépésedre vár.",\n...e altri giocatori aspettano.,"\n...更なる挑戦者を ",\n...a inni gracze czekają.,\n...e os outros jogadores aguardam.,,\n...și alți jucători așteaptă.,"\n...В то время как другие игроки будут ждать своего часа, чтобы совершить свой ход.","\n...и други играчи вас чекају. -","\n...ve diğer oyuncular bekliyor. +",\n... och andra spelare väntar.,"\n...ve diğer oyuncular bekliyor. " -,,Hexen script texts,,,,,,,,,,,,,,,,,,,,,,,, -The door is locked,TXT_ACS_MAP01_5_THEDO,,,,Dveře jsou zamčené.,Døren er låst,Die Tür ist verschlossen,,La pordo estas ŝlosita.,La puerta está cerrada,,Ovi on lukittu,Cette porte est verouillée.,Az ajtó zárva van.,La porta è bloccata,扉は施錠されている,문이 잠겨 있다,De deur is op slot,Døren er låst,Drzwi są zablokowane,A porta está trancada,,Ușa e încuiată,Дверь заперта,Врата су закључана,Kapı kilitli -"Greetings, mortal",TXT_ACS_MAP02_9_GREET,,,,"Vítej, smrtelníče,","Vær hilset, dødelige","Sei gegrüßt, Sterblicher",,"Salutojn, mortemul'.","Saludos, mortal",,"Tervehdys, kuolevainen","Salutations, humain.","Üdvözöllek, halandó!","Salve, mortale",御機嫌よう、小僧,"환영한다, 필멸자여.","Groeten, sterfelijk","Vær hilset, dødelige",Witaj śmiertelniku,"Saudações, mortal.",,"Salutări, muritorule","Приветствую, смертный","Поздрав, смртниче","Selamlar, ölümlü" -Are you ready to die?,TXT_ACS_MAP02_11_AREYO,,,,jsi připraven@[ao_cs] zemřít?,Er du klar til at dø?,Bist du bereit zu sterben?,,Ĉu vi pretas morti?,¿Estás listo para morir?,,Oletko valmis kuolemaan?,Êtes-vous prêt à mourir?,Készen állsz a halálra?,Sei pronto a morire?,死に急ぐ仕度は整ったか?,죽을 준비는 됐는가?,Ben je klaar om te sterven?,Er du klar til å dø?,Czy jesteś gotów na śmierć?,Você está pront@[ao_ptb] para morrer?,,Ești pregătit să mori?,Готов ли ты умереть?,Јеси ли спреман да умреш?,Ölmeye hazır mısın? -A door opened on the Guardian of Ice,TXT_ACS_MAP02_20_ADOOR,,,,Ve Strážci ledu se otevřely dveře.,En dør åbnede sig på isens vogter,Eine Tür öffnet sich zum Wächter des Eises,,Pordo malfermiĝis ĉe la Gardanto de Glacia.,Se abrió una puerta en el Guardián de Hielo,,Ovi avautui jään vartijan luona,Une porte s'est ouverte dans le Gardien de Glace.,Egy ajtó kinyillott a Jég Őrzőjénél,Una porta è stata aperta sul Guardiano di Ghiaccio,氷の守護者にある扉は開かれた,얼음의 수호자에서 문이 열렸다,Een deur opende op de bewaker van ijs,En dør åpnet seg på Isens vokter,Drzwi w Strażniku Lodu otworzyły się,Uma porta se abriu no Guardião de Gelo,,O ușă s-a deschis pe Gardianul de Foc,Дверь открыта у стража льда,Врата су отворена код Чувара леда,Buz Muhafızı'nda bir kapı açıldı -This path is barred,TXT_ACS_MAP03_12_THISP,,,,Cesta je zatarasená.,Denne vej er spærret,Dieser Pfad ist blockiert,,Ĉi tiu vojo estas barita.,Este camino está atrancado,,Tämä polku on teljetty,Ce chemin est barré.,Ez az út el van torlaszolva.,Questo percorso è sbarrato,この道は塞がれている,이 통로는 빗장이 걸려있다,Dit pad is geblokkeerd,Denne veien er sperret,Ścieżka jest zablokowana,Este caminho está bloqueado,,Această cale e blocată,Сейчас этот путь закрыт,Овај пут је тренутно забрањен,Bu yol yasaklandı -One half of the puzzle has been solved,TXT_ACS_MAP04_9_ONEHA,,,,U Sedmera portálů byla vyřešena,Den ene halvdel af puslespillet er blevet løst,Eine Hälfte des Rätsels wurde gelöst,,Unu duono de la puzlo estas solvita,Una mitad del acertijo se ha resuelto,,Puolet pulmasta on ratkaistu,La moitié du puzzle à été résolu,A rejtvény egyik fele meg lett fejtve,Metà del puzzle è stato risolto,パズルの一つが解かれた,수수께끼의 절반이 풀렸다,De helft van de puzzel is opgelost,Den ene halvdelen av gåten er løst,Połowa zagadki rozwiązana,Metade do quebra-cabeça foi resolvido,,O jumătate din puzzle e rezolvată,Половина головоломки разгадана,Половина загонетке је решена,Bulmacanın bir yarısı çözüldü -on the Seven Portals,TXT_ACS_MAP04_10_ONTHE,,,,jedna třetina rébusu.,på de syv portaler,bei den Sieben Portalen,,ĉe la Sep Portaloj.,en los Siete Portales,,seitsemän portaalin luona,pour les Sept Portails.,a Hét Portálon,nei Sette Portali,漆之門に影響を与えた,... 일곱 차원문에서,op de Zeven Portalen,på de syv portaler,przy Siedmiu Portalach,nos Sete Portais,,pe cele Șapte Portaluri,на Семи порталах,на Седам портала,Yedi Portalda -One third of the puzzle has been solved,TXT_ACS_MAP04_11_ONETH,,,,U Sedmera portálů byla vyřešena,En tredjedel af gåden er blevet løst,Ein Drittel des Rätsels wurde gelöst,,Unu triono de la puzlo estas solvita,Un tercio del acertijo se ha resuelto,,Kolmannes pulmasta on ratkaistu,Un tiers du puzzle à été résolu,A rejtvény egyharmada megfejtésre került,Un terzo del puzzle è stato risolto,三種のパズルの一つが解かれた,수수께끼의 3분의 1이 풀렸다,Een derde van de puzzel is opgelost,En tredjedel av puslespillet er løst,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle a fost rezolvată,Треть головоломки разгадана,Трећина загонетке је решена,Bulmacanın üçte biri çözüldü -Stairs have risen on the Seven Portals,TXT_ACS_MAP04_12_STAIR,,,,jedna třetina rébusu.,Der er kommet en trappe op på de syv portaler,Stufen bei den Sieben Portale wurden erbaut,,Ŝtupoj leviĝis ĉe la Sep Portaloj.,Unas escaleras se han erguido en los Siete Portales,,Portaat ovat kohonneet seitsemän portaalin luona,Des escaliers sont apparus dans les Sept Portails.,A Hét Portálon belül egy lépcsősor emlekedett,Sono sorte le scale nei Sette Portali,漆之門に階段が立ち昇った,일곱 차원문에서 계단이 솟아났다,Trappen zijn gestegen op de Zeven Portalen,Trapper har reist seg på De syv portaler,Schody przy Siedmiu Portalach podniosły się,As escadas se ergueram nos Sete Portais,,S-au ridicat scări pe cele Șapte Portaluri,Лестница воздвигнулась на Семи порталах,Степенице се подижу на Седам портала,Yedi Portalda merdivenler yükseldi -One third of the puzzle has been solved,TXT_ACS_MAP05_6_ONETH,,,,U Sedmera portálů byla vyřešena,En tredjedel af puslespillet er blevet løst,Ein Drittel des Rätsels wurde gelöst,,Unu triono de la puzlo estas solvita,Un tercio del acertijo se ha resuelto,,Kolmannes pulmasta on ratkaistu,Un tiers du puzzle à été résolu,A rejtvény egyharmada megfejtésre került,Un terzo del puzzle è stato risolto,三種のパズルの一つが解かれた,수수께끼의 3분의 1이 풀렸다,Een derde van de puzzel is opgelost,En tredjedel av puslespillet er løst,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle a fost rezolvată,Треть головоломки разгадана,Трећина загонетке је решена,Bulmacanın üçte biri çözüldü -on the Seven Portals,TXT_ACS_MAP05_7_ONTHE,,,,jedna třetina rébusu.,på de syv portaler,bei den Sieben Portalen,,ĉe la Sep Portaloj.,en los Siete Portales,,seitsemän portaalin luona,pour les Sept Portails.,a Hét Portálon,nei Sette Portali,漆之門 に影響を与えた,... 일곱 차원문에서,op de Zeven Portalen,på de syv portaler,przy Siedmiu Portalach,nos Sete Portais,,pe cele Șapte Portaluri,на Семи порталах,на Седам портала,Yedi Portalda -Stairs have risen on the Seven Portals,TXT_ACS_MAP05_8_STAIR,,,,Schody se zvedly u Sedmera portálů.,Trappen er steget op på de syv portaler,Stufen bei den Sieben Portale wurden erbaut,,Ŝtupoj leviĝis ĉe la Sep Portaloj.,Unas escaleras se han erguido en los Siete Portales,,Portaat ovat kohonneet seitsemän portaalin luona,Des escaliers sont apparus dans les Sept Portails.,A Hét Portálon belül egy lépcsősor emlekedett,Sono sorte le scale nei Sette Portali,漆之門 に階段が立ち昇った,일곱 차원문에서 계단이 솟아났다,Trappen zijn gestegen op de Zeven Portalen,Trappene har reist seg på De syv portaler,Schody przy Siedmiu Portalach podniosły się,Escadas se ergueram nos Sete Portais,,S-au ridicat scări pe cele Șapte Portaluri,Лестница воздвигнулась на Семи порталах,Степенице се подижу на Седам портала,Yedi Portalda merdivenler yükseldi -You have to find another switch...,TXT_ACS_MAP05_9_YOUHA,,,,Musíš najít další spínač.,Du skal finde en anden kontakt...,Du must einen weiteren Schalter finden...,,Vi bezonas trovi alian ŝaltilon...,Debes encontrar otro interruptor...,Debes encontrar otro switch...,Sinun on löydettävä toinen vipu...,Vous devez trouver un autre bouton..,Egy másik kapcsolót kell találnod...,Devi trovare un altro interruttore...,他のスイッチも探す必要がある...,다른 개폐기를 찾아야 한다,Je moet een andere schakelaar vinden...,Du må finne en annen bryter...,Musisz znaleźć inny przełącznik...,Você precisa encontrar outro interruptor...,,Trebuie să găsești alt buton...,Остался ещё один переключатель...,Остао је још један прекидач...,Başka bir anahtar bulmalısın... -Stones grind on the Seven Portals,TXT_ACS_MAP05_10_STONE,,,,Kameny dřou u Sedmera portálů.,Stenene knirker på de syv portaler,Steine schleifen bei den Sieben Portalen,,Ŝtonoj grincas ĉe la Sep Portaloj.,Las piedras giran en los Siete Portales,,Kiviä vierii seitsemän portaalin luona,Des pierres grincent dans les Sept Portails.,Kövek örlődnek a Hét Portálnál,Le pietre si sono frantumate nei Sette Portali,漆之門 の石壁が砕かれた,일곱 차원문에서 바위 부딪히는 소리가 들려왔다,Stenen slijpen op de Zeven Portalen,Steiner knuser på De syv portaler,Kamienie przy Siedmiu Portalach zgrzytają,As pedras giram nos Sete Portais,,Pietrele încep să macine pe cele Șapte Portaluri,Каменная преграда отступила на Семи порталах,Камена препрека се повлачи,Taşlar Yedi Portalda öğütülüyor -One sixth of the puzzle has been solved,TXT_ACS_MAP08_6_ONESI,,,,V Temném hvozdu byla vyřešena,En sjettedel af puslespillet er blevet løst,Ein Sechstel des Rätsels wurde gelöst,,Unu sesono de la puzlo estas solvita,Un sexto del acertijo se ha resuelto,,Kuudennes pulmasta on ratkaistu,Un sixième du puzzle à été résolu,A feladványok egyhatoda megfejtésre került,Un sesto del puzzle è stato risolto,六種のパズルの一つが解かれた,수수께끼의 6분의 1이 풀렸다,Een zesde van de puzzel is opgelost,En sjettedel av puslespillet er løst,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена,Bulmacanın altıda biri çözüldü -on the Shadow Wood,TXT_ACS_MAP08_7_ONTHE,,,,jedna šestina rébusu.,i Skyggetræet,Im Schattenwald,,en la Ombro-Arbareto.,En el Bosque de Sombras,,Varjosalossa,dans le Bois des Ombres.,a Sötét Erdőben,Nel Bosco d'Ombra,陰影樹 に少し影響を与えた,... 그림자 숲에서,op het Schaduwbos,på Skyggeskogen,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки,Gölge Ormanı'nda -The door is barred from the inside,TXT_ACS_MAP08_10_THEDO,,,,Dveře jsou zatarasené zevnitř.,Døren er spærret indefra,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está atrancada desde el interior,,Ovi on teljetty sisältä,Cette porte est bloquée de l'intérieur.,Az ajtó be van reteszelve belülről,La porta è sbarrata da dentro,この扉は内側から塞がれている,이 문은 안에 빗장이 걸려있다,De deur is van binnenuit geblokkeerd.,Døren er sperret fra innsiden,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра,Kapı içeriden kilitli. -You hear a door open in the distance,TXT_ACS_MAP08_11_YOUHE,,,,Slyšíš v dálce otevírající se dveře.,Du hører en dør åbne i det fjerne,"Du hörst, wie sich in der Ferne eine Tür öffnet",,Vi aŭdas pordon malfermiĝantan malproksime.,Escuchas que una puerta se abre a la distancia,,Kuulet oven avautuvan etäällä,Vous entendez une porte s'ouvrir au loin.,Hallod ahogy egy ajtó kinyílik a távolban,Senti una porta aprirsi in lontananza,遠くから扉が開く音が聞こえる,멀리서 문이 열리는 소리가 들린다,In de verte hoor je een deur openstaan.,Du hører en dør åpnes i det fjerne,Słyszysz odgłos otwierających się w oddali drzwi,Você ouve de longe uma porta se abrindo,,Auzi o ușă deschizându-se în depărtare,Слышен звук открывающейся двери,Чује се звук отварања врата,Uzakta bir kapının açıldığını duyuyorsun. -One sixth of the puzzle has been solved,TXT_ACS_MAP09_6_ONESI,,,,V Temném hvozdu byla vyřešena,En sjettedel af puslespillet er blevet løst,Ein Sechstel des Rätsels wurde gelöst,,Unu sesono de la puzlo estas solvita,Un sexto del acertijo se ha resuelto,,Kuudennes pulmasta on ratkaistu,Un sixième du puzzle à été résolu,A feladványok egyhatoda megfejtésre került,Un sesto del puzzle è stato risolto,六種のパズルの一つが解かれた,수수께끼의 6분의 1이 풀렸다,Een zesde van de puzzel is opgelost,En sjettedel av gåten er løst,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена,Bulmacanın altıda biri çözüldü -on the Shadow Wood,TXT_ACS_MAP09_7_ONTHE,,,,jedna šestina rébusu.,i Skyggetræet,Im Schattenwald,,en la Ombro-Arbareto.,En el Bosque de Sombras,,Varjosalossa,dans le Bois des Ombres.,a Sötét Erdőben,Nel Bosco d'Ombra,陰影樹 に少し影響を与えた,... 그림자 숲에서,op het Schaduwbos,på Skyggeskogen,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки,Gölge Ormanı'nda -One sixth of the puzzle has been solved,TXT_ACS_MAP10_6_ONESI,,,,V Temném hvozdu byla vyřešena,En sjettedel af puslespillet er blevet løst,Ein Sechstel des Rätsels wurde gelöst,,Unu sesono de la puzlo estas solvita,Un sexto del acertijo se ha resuelto,,Kuudennes pulmasta on ratkaistu,Un sixième du puzzle à été résolu,A feladványok egyhatoda megfejtésre került,Un sesto del puzzle è stato risolto,六種のパズルの一つが解かれた,수수께끼의 6분의 1이 풀렸다,Een zesde van de puzzel is opgelost,En sjettedel av puslespillet har blitt løst,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена,Bulmacanın altıda biri çözüldü -on the Shadow Wood,TXT_ACS_MAP10_7_ONTHE,,,,jedna šestina rébusu.,i Skyggetræet,Im Schattenwald,,en la Ombro-Arbareto.,En el Bosque de Sombras,,Varjosalossa,dans le Bois des Ombres.,a Sötét Erdőben,Nel Bosco d'Ombra,陰影樹 に少し影響を与えた,... 그림자 숲에서,op het Schaduwbos,på Skyggeskogen,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки,Gölge Ormanı'nda -\ ettins left,TXT_ACS_MAP11_0_ETTIN,Yellow needs better translation,,,\ etinů zbývá.,\ ettins venstre,\ Ettins übrig,,\ gigantaĉoj ceteraj,\ Ettins restantes,,\ ettiniä jäljellä,\ ettins restants,\ ettin maradt,\ Ettins rimasti,\ 匹のエティンが残っている,\ 마리 에틴이 남았음,\ overgebleven Ettins,\ ettins igjen,\ pozostałych ettinów,\ ettins restantes,,\ etini rămași,\ оставшихся эттинов,Остало је \ еттина,\ ettins ayrıldı -"You waited too long, now you die!",TXT_ACS_MAP11_1_YOUWA,,,,"Čekal@[ao_cs] jsi moc dlouho, teď zemřeš!","Du ventede for længe, nu dør du!","Du hast zu lange gewartet, jetzt stirbst du!",,"Vi atendis tro longe, nun vi mortas!","Esperaste demasiado, ¡ahora morirás!",,"Odotit liian pitkään, nyt kuolet!","Vous avez attendu trop longtemps, maintenant, mourrez!","Túl sokáig vártál, most meghalsz!","Hai atteso troppo a lungo, ora muori!",長居をしたな、命を奪うには十分な程に!,시간을 너무 오래 끌었다. 이제 죽어라!,"Je hebt te lang gewacht, nu ga je dood!","Du ventet for lenge, nå dør du!",Czekałeś zbyt długo. Teraz giń!,Você esperou demais. Agora morrerá!,,"Ți-a luat prea mult, acum mori!",Слишком долго! Готовься к смерти!,Предуго! Припреми се за смрт!,"Çok bekledin, şimdi öleceksin!" -A door opened on the Forsaken Outpost,TXT_ACS_MAP11_7_ADOOR,,,,Dveře se otevřely na Opuštěném stanovišti.,En dør blev åbnet i forladt forpost,Eine Tür im verlassenen Vorposten hat sich geöffnet,,Pordo malfermiĝis ĉe la Forlasita Posteno.,Una puerta se abrió en el Puesto de Avanzada Abandonado,,Ovi avautui hylätyssä etuvartiossa,Une porte s'est ouverte dans la base abandonnée.,Egy ajtó kinyílik az Elátkozott Őrportyán,Una porta è stata aperta nell'Avamposto Abbandonato,荒れ果てた前哨地 への扉が開いた,버려진 초소에서 문이 열렸다,Een deur opende een deur op de Verwaarloosde buitenpost,En dør åpnet seg på den forlatte utposten,Drzwi przy Opuszczonym Posterunku otworzyły się,Uma porta se abriu no Posto Abandonado,,O ușă s-a deschis pe Avanpostul Părăsit,Дверь открылась на покинутой заставе,Врата су се отворила у Напуштеној постаји,Unutulmuş Karakol'da bir kapı açıldı -This door won't open yet,TXT_ACS_MAP12_9_THISD,,,,Tyto dveře se ještě neotevřou.,Denne dør vil ikke åbne sig endnu,Die Tür öffnet sich noch nicht,,Ĉi tiu pordo ne jam malfermiĝos.,Esta puerta no se abrirá todavía,,Tämä ovi ei aukea vielä,Cette porte ne s'ouvre pas pour l'instant.,Ez az ajtó még nem fog kitárulni.,Questa porta non è aperta ancora,扉はまだ開かない,이 문은 아직 열 수 없다,Deze deur gaat nog niet open.,Denne døren vil ikke åpne seg ennå,Te drzwi jeszcze się nie otwierają,Esta porta não se abrirá ainda,,Ușa n-o să se deschidă încă,Сейчас эта дверь закрыта,Ова врата су тренутно закључана,Bu kapı henüz açılmayacak. -"My servants can smell your blood, human",TXT_ACS_MAP13_11_MYSER,,,,"Mí služebníci cítí tvou krev, člověče.","Mine tjenere kan lugte dit blod, menneske","Meine Diener riechen dein Blut, Menschling",,"Miajn servantoj povas flari vian sangon, homo.","Mis sirvientes pueden oler tu sangre, humano",,"Palvelijani voivat haistaa veresi, ihminen","Mes servants peuvent sentir votre sang, humain.","Szolgáim érzik a véred szagát, emberfattya","I miei servi possono annusare il tuo sangue, umano",我が下僕が貴様の血を嗅ぎ付けた様だぞ、小童,"이 몸의 하인들은 네 피 냄새를 맏고 따라온다, 인간.","Mijn bedienden kunnen jouw bloed ruiken, mens","Mine tjenere kan lukte blodet ditt, menneske",Moje sługi czują twą krew śmiertelniku,"Meus servos sentem o cheiro do seu sangue, human@[ao_ptb]",,"Servitorii mei îți pot adulmeca sângele, muritorule","Мои прислужники чуют твою кровь, человек","Моје слуге миришу твоју крв, човече","Hizmetçilerim kanının kokusunu alabiliyor, insan." -A door opened in the Gibbet,TXT_ACS_MAP21_0_ADOOR,,,,Dveře se otevřely na Šibenici.,En dør blev åbnet i Gibbet,Eine Tür in der Richtstätte wurde geöffnet,,Pordo malfermiĝis ĉe la Pendigilo.,Una puerta se abrió en la horca,,Ovi avautui hirsipuulla,Une porte s'est ouverte dans le gibet.,Egy ajtó kinyílik az Akasztófánál,Una porta è stata aperta nella Forca,晒し台 への扉が開いた,교수대에서 문이 열렸다,Een deur geopend in de Gibbet,En dør åpnet seg i galgen,Drzwi przy Szubienicy otworzyły się,Uma porta se abriu na Forca,,O ușă s-a deschis pe Eșafod,Проход будет открыт возле виселицы,Пролаз је отворен код вешала,İnfaz yerinde bir kapı açıldı -The door is barred from the inside,TXT_ACS_MAP21_2_THEDO,,,,Dveře jsou zatarasené zevnitř.,Døren er spærret indefra,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está atrancada desde el interior,,Ovi on teljetty sisältä,Cette porte est bloquée de l'intérieur.,Az ajtó belülről van eltorlaszolva,La porta è sbarrata da dentro,この扉は内側から塞がれている,이 문은 안에 빗장이 걸려있다,De deur is van binnenuit geblokkeerd.,Døren er sperret fra innsiden,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра,Kapı içeriden kilitli. -A platform has lowered in the tower,TXT_ACS_MAP22_3_APLAT,,,,Plošina ve věži sjela dolů.,En platform er sænket i tårnet,Im Turm hat sich eine Plattform gesenkt,,Plataĵo malleviĝis en la turo.,Una plataforma ha bajado en la torre,,Lava on laskeutunut tornissa,Une plateforme est descendue dans la tour.,Egy platform leereszkedett a toronyban,Una piattaforma si è abbassata nella torre,塔内の昇降機が下りた,성 안에서 보행판이 내려왔다,Een platform is in de toren neergelaten in de toren,En plattform har senket seg i tårnet,Platforma w wieży obniżyła się,Uma plataforma desceu na torre,,O platformă a coborât în turn,Площадка опустилась в центральной башне,Спустио се платформ у централном торњу,Kuleye bir platform indirildi -"You have played this game too long, mortal...",TXT_ACS_MAP22_27_YOUHA,,,,"Tuhle partii jsi už hrál@[ao_cs] moc dlouho, smrtelníče,","Du har spillet dette spil for længe, dødelige...","Du spielst schon zu lange, Sterblicher...",,"Ludis ĉi tiun ludon vi tro longe, mortemul'...","Has jugado este juego demasiado tiempo, mortal...",,"Olet pelannut tätä peliä liian pitkään, kuolevainen...","Vous avez joué à ce jeu trop longtemps, mortel..","Túl sokat játszadoztál, halandó...","Ha giocato a questo gioco troppo a lungo, mortale...",遊びはここまでだ、小僧,"네 놈은 오랫동안 놀았도다, 필멸자여...","Je hebt dit spel te lang gespeeld, sterfelijke...","Du har spilt dette spillet for lenge, dødelige...",Już za długo grasz w tą grę śmiertelniku...,"Você jogou este jogo por tempo demais, mortal...",,"Ai jucat acest joc prea multă vreme, muritorule...","Ты слишком заигрался, смертный...","Превише си се заиграо, смртниче...","Bu oyunu çok uzun oynadın, ölümlü." -I think I shall remove you from the board,TXT_ACS_MAP22_29_ITHIN,,,,"myslím, že bych tě měl odstranit ze šachovnice.","Jeg tror, jeg vil fjerne dig fra brættet.",Ich denke ich sollte dich vom Brett entfernen,,"Mi kredas, ke mi vin forigos el la tabul'.",Creo que te retiraré del tablero,,Ajattelenpa poistaa sinut pelilaudalta,Je pense qu'il est l'heure de vous retirer de l'échiquier.,"Azt hiszem le kell, hogy üsselek a tábláról",Penso che ti rimuoverò dalla scacchiera,盤上から貴様を排除する,이 몸이 너를 말 치우듯이 제거하겠다.,Ik denk dat ik u van het bord zal verwijderen,Jeg tror jeg skal fjerne deg fra brettet,"Myślę, że usunę cię z planszy",Acho que irei removê-l@[ao_ptb] do tabuleiro,,Cred că e timpul să te înlătur de pe tablă,Пришло время завершить твою партию,Дошло је време да се заврши твоја партија,Sanırım seni tahtadan kaldırmalıyım. -You hear a door open upstairs,TXT_ACS_MAP23_10_YOUHE,,,,Z patra slyšíš otevírající se dveře.,Du hører en dør blive åbnet ovenpå.,"Du hörst, wie sich oben eine Tür öffnet",,Vi aŭdas pordon malfermiĝantan superŝtupare.,Escuchas una puerta que se abre arriba,,Kuulet oven avautuvat yläkerrassa,Vous entendez une porte s'ouvrir à l'étage.,Hallod ahogy egy ajtó kinyílik az emeleten,Senti una porta aprirsi al piano di sopra,上層階の扉が開いた,윗층에서 문이 열리는 소리가 들린다,Je hoort een deur boven opengaan,Du hører en dør åpnes ovenpå,Słyszysz odgłos otwierających się na górze drzwi,Você ouve uma porta se abrir lá em cima,,Auzi o ușă deschizându-se sus,Слышен звук открывающейся двери наверху,Од северне дворане зачује се звук,Üst katta bir kapının açıldığını duyuyorsun. -"Worship me, and I may yet be merciful",TXT_ACS_MAP27_8_WORSH,,,,Uctívej mě a možná ještě budu milosrdný.,"Tilbeder du mig, så er jeg måske barmhjertig.",Verehre mich und ich könnte gnädig sein,,"Kultu min, tiam mi ankoraŭ eble kompatos.","Adórame, y aun puedo ser misericordioso",,"Palvo minua, ja saatan vielä olla armahtavainen","Prosternez vous devant moi, et je pourrai considérer de vous épargner.","Hódolj be, és talán kegyelmes leszek","Venerami, e potrei essere ancora misericordioso",我を崇めろ、慈悲を残している内に,"이 몸에게 경배하라, 그럼 자비를 베풀 것이다.","Aanbid me, en ik mag dan nog genadig zijn","Tilbe meg, og jeg kan ennå være barmhjertig.","Wielb mnie, a może będę miłosierny","Venere-me, e eu poderei ser piedoso",,"Venerează-mă, și s-ar putea să mai fiu milostiv încă","Преклонись предо мной, и, может быть, я буду милосерден","Преклони се преда мноме, и можда ћу бити милостив","Bana ibadet et, belki merhamet ederim" -"Then again, maybe not",TXT_ACS_MAP27_10_THENA,,,,"Na druhou stranu, možná ne.",Men måske heller ikke,"Andererseits, vielleicht aber auch nicht",,"Tamen, eble ne.","Aunque, tal vez no",,"Mutta toisaalta, ehken sittenkään",Quoi que cela soit peu probable.,"Jól átgondolva, inkább nem",O potrei anche non esserlo,まあ、有り得ないな,허나... 그러지는 않겠지.,"Maar nogmaals, misschien niet",Men kanskje ikke,"Z drugiej strony, może nie...","Pensando melhor, talvez não",,"Dar apoi, poate că nu","А может быть, и нет",А можда и нећу,"Sonra tekrar, belki de değil" -One ninth of the puzzle has been solved,TXT_ACS_MAP28_6_ONENI,,,,V Klášteru byla vyřešena,En niende del af puslespillet er blevet løst,Ein Neuntel des Rätsels wurde gelöst,,Unu naŭono de la puzlo estas solvita,Un noveno del acertijo se ha resuelto,,Yhdeksäsosa pulmasta on ratkaistu,Un neuvième du puzzle à été résolu,A rejtvény egy kilencede megfejtésre került,Un nono del puzzle è stato risolto,九種のパズルの一つが解かれた,수수께끼의 9분의 1이 풀렸다,Een negende van de puzzel is opgelost.,En niende del av puslespillet er løst.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена,Bulmacanın dokuzda biri çözüldü -On the Monastery,TXT_ACS_MAP28_7_ONTHE,,,,jedna devítina rébusu.,På klosteret,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,på klosteret,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији,Manastır Üzerine -One ninth of the puzzle has been solved,TXT_ACS_MAP30_6_ONENI,,,,V Klášteru byla vyřešena,En niende del af puslespillet er blevet løst,Ein Neuntel des Rätsels wurde gelöst,,Unu naŭono de la puzlo estas solvita,Un noveno del acertijo se ha resuelto,,Yhdeksäsosa pulmasta on ratkaistu,Un neuvième du puzzle à été résolu,A rejtvény egy kilencede megfejtésre került,Un nono del puzzle è stato risolto,九種のパズルの一つが解かれた,수수께끼의 9분의 1이 풀렸다,Een negende van de puzzel is opgelost.,En niende del av gåten er løst.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена,Bulmacanın dokuzda biri çözüldü -On the Monastery,TXT_ACS_MAP30_7_ONTHE,,,,jedna devítina rébusu.,På klosteret,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,på klosteret,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији,Manastır Üzerine -One ninth of the puzzle has been solved,TXT_ACS_MAP34_1_ONENI,,,,V Klášteru byla vyřešena,En niende del af puslespillet er blevet løst,Ein Neuntel des Rätsels wurde gelöst,,Unu naŭono de la puzlo estas solvita,Un noveno del acertijo se ha resuelto,,Yhdeksäsosa pulmasta on ratkaistu,Un neuvième du puzzle à été résolu,A rejtvény egy kilencede megfejtésre került,Un nono del puzzle è stato risolto,九種のパズルの一つが解かれた,수수께끼의 9분의 1이 풀렸다,Een negende van de puzzel is opgelost.,En niendedel av puslespillet er løst,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена,Bulmacanın dokuzda biri çözüldü -On the Monastery,TXT_ACS_MAP34_2_ONTHE,,,,jedna devítina rébusu.,På klosteret,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,på klosteret,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији,Manastır Üzerine -The portal has been sealed,TXT_ACS_MAP35_0_THEPO,,,,Portál byl zapečeťen.,Portalen er blevet forseglet,Das Portal wurde versiegelt,,La portalo estas obturita.,El portal se ha sellado,,Portaali on sinetöity,Le portail est scellé.,Az átjáró bezárult.,Il portale è stato sigillato,ポータルは封印された,차원문은 봉인되었다,Het portaal is verzegeld,Portalen har blitt forseglet,Portal został zapieczętowany,O portal foi selado,,Portalul a fost închis,Портал закрылся,Врата су затворена,Geçit mühürlendi -Choose your fate,TXT_ACS_MAP35_1_CHOOS,,,,Vyber si svůj osud.,Vælg din skæbne,Wähle dein Schicksal,,Elektu vian fatalon.,Escoge tu destino,Escoge tú destino,Valitse kohtalosi,Choisissez votre sort.,Dönts sorsod felől,Scegli la tua sorte,運命を撰べ,그대의 운명을 정해라,Kies uw lot,Velg din skjebne,Wybierz swoje przeznaczenie,Escolha o seu destino,,Alegeți destinul,Сделай свой выбор,Донеси своју одлуку,Kaderinizi seçin -The door is barred from the inside,TXT_ACS_MAP35_3_THEDO,,,,Dveře jsou zatarasené zevnitř.,Døren er spærret indefra,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está atrancada desde el interior,,Ovi on teljetty sisältä,Cette porte est bloquée de l'intérieur.,Az ajtót belülről torlaszolták el.,La porta è sbarrata da dentro,この扉は内側から塞がれている,이 문은 안에 빗장이 걸려있다,De deur is van binnenuit geblokkeerd.,Døren er sperret fra innsiden,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра,Kapı içeriden kilitli. -Are you strong enough,TXT_ACS_MAP35_12_AREYO,,,,"Jsi dost siln@[adj_cs],",Er du stærk nok?,Bist du stark genug,,Ĉu vi estas sufiĉe forta,Eres lo suficientemente fuerte,,Olet riittävän vahva,Etes vous suffisamment fort,"Elég erős vagy,",Sei abbastanza forte,お前がどれだけ強かろうと,네 놈은 주인들을 대면할 힘이...,Ben je sterk genoeg,Er du sterk nok,Czy jesteś wystarczająco silny,Você é forte o suficiente,,Ești întradevăr suficient de puternic,"Достаточно ли ты силён,",Јеси ли довољно снажан,Yeterince güçlü müsün? -To face your own masters?,TXT_ACS_MAP35_14_TOFAC,,,,čelit svým vlastním pánům?,Til at møde dine egne mestre?,Dich deinen eigenen Meistern zu stellen?,,por stari kontraŭ viaj propraj mastroj?,¿Para enfrentarte a tus maestros?,,kohtaamaan omat mestarisi?,pour faire face à vos maîtres?,Hogy saját mestereiddel nézz szembe?,Da affrontare i tuoi stessi maestri?,お前の師に立ち向かえるのか?,진심으로 있는 것인가?,Om je eigen meesters onder ogen te komen?,Til å møte dine egne mestere?,By stawić czoła swoim mistrzom?,Para enfrentar os seus próprios mestres?,,Să îți înfrunți proprii stăpâni?,чтобы сразиться со своими наставниками?,да се суочиш са својим господарима?,Kendi efendilerinizle yüzleşmek için mi? -,,Hexen: Deathkings script texts,,,,,,,,,,,,,,,,,,,,,,,, -You dare battle in the ready room?,TXT_ACS_MAP33_6_YOUDA,,,,Ty si dovoluješ rvát se v přípravné místnosti?,Tør du kæmpe i beredskabsrummet?,Du wagst es im Bereitschaftsraum zu kämpfen?,,Vi aŭdacas batali en la pretĉambro?,¿Te atreves a luchar en la sala de preparación?,,Kuinka kehtaat taistella valmistautumishuoneessa?,Vous osez faire escarmouche dans la salle de préparation?,Hogy merészelsz harcolni a váróteremben?,Hai il coraggio di combattere in questa sala?,挑戦する準備は整ったか?,감히 준비의 방에서 전투를 벌이다니...,Durf jij te vechten in de readyroom?,Våger du å kjempe i det klare rommet?,Śmiesz walczyć w pokoju przygotowań?,Como ousa batalhar na sala de espera?,,Îndrăznești să lupți în camera de așteptare?,Ты посмел сражаться в комнате ожидания?,Усуђујеш се борити у припремној соби?,Hazırlanma odasında savaşmaya mı cüret ediyorsun? -"For that, you shall die!",TXT_ACS_MAP33_7_FORTH,,,,Pro to zemřeš!,For det skal du dø!,Dafür sollst du sterben!,,"Pro tio, vi mortos!","Por eso, ¡deberás morir!",,Siitä hyvästä kuolet!,"Pour cette insulte, vous trépasserez!",Ezért meghalsz!,"Per questo, morirai!",ならば、死へ進め!,죽어서 값을 치러라!,Daarvoor zal je sterven!,For det skal du dø!,Umrzesz za to!,Você morrerá por isso!,,"Pentru asta, vei muri!",Так умри же!,За то ћеш умрети!,Bunun için öleceksin! -The waterfall is open,TXT_ACS_MAP41_6_THEWA,,,,Vodopád je otevřen.,Vandfaldet er åbent,Der Wasserfall ist geöffnet,,La akvofalo estas malferma.,La cascada se ha abierto,,Vesiputous on auki,La cascade s'est ouverte.,A vizesés nyitva,La cascata è aperta,滝 は開いた,폭포가 멈췄다,De waterval is open,Fossen er åpen,Wodospad jest otwarty,A cascata está aberta,,Cascada e deschisă,Поток воды остановлен,Водопад је отворен,Şelale açık -The waterfall is blocked,TXT_ACS_MAP41_7_THEWA,,,,Vodopád je zatarasen.,Vandfaldet er blokeret,Der Wasserfall ist blockiert,,La akvofalo estas barita.,La cascada está bloqueada,,Vesiputous on tukittu,La cascade est bloquée.,A vizesés zárva,La cascata è bloccata,滝 は塞がっている,폭포에 의해 막혔다,De waterval is geblokkeerd,Fossen er blokkert,Wodospad jest zablokowany,A cascata está bloqueada,,Cascada e închisă,Поток воды преграждает путь,Водопад је блокиран,Şelale tıkalı -A door has opened in the chapel,TXT_ACS_MAP41_8_ADOOR,,,,Dveře se otevřely v kapli.,Der er åbnet en dør i kapellet,Eine Tür in der Kapelle hat sich geöffnet,,Pordo malfermis en la kapelo.,Una puerta se abrió en la Capilla,,Ovi on avautunut kappelissa,Une porte s'est ouverte dans la chapelle.,Egy ajtó kitárult a kápolnában,Una porta si è aperta nella cappella,庵寺 への扉が開いた,교외 근처에서 문이 열렸다,Een deur is geopend in de kapel,En dør har åpnet seg i kapellet,Drzwi w kaplicy zostały otwarte,Uma porta se abriu na capela,,O ușă s-a deschis în capelă,Дверь открылась в часовне,Врата су се отворила у катедрали,Şapelde bir kapı açıldı. -Now that's odd...,TXT_ACS_MAP42_4_NOWTH,,,,Tak to je divné...,Det er mærkeligt...,Hm. Das ist merkwürdig...,,Nun tio estas stranga...,Eso es extraño...,,Onpa kummallista...,Ca c'est étrange....,Ez felettébb különös...,Questo sì che è strano...,何かがおかしい...,무언가가 이상하다...,Dat is vreemd....,Det var merkelig...,Dziwne...,Que estranho...,,Asta e ciudat...,Как странно...,То је чудно...,İşte bu garip. -Three more parts of the puzzle remain,TXT_ACS_MAP44_1_THREE,,,,Zbývají tři části rébusu.,Der er endnu tre dele af gåden tilbage,Drei weitere Teile des Rätsels verbleiben,,Nur tri partoj de la puzlo restas.,Quedan tres partes más del acertijo,,Kolme pulman palasta jäljellä,Trois parties du puzzle restent à résoudre.,Három rész maradt a rejtvényből,Rimangono altre tre parti del puzzle,パズルの部品は残り 3つ,3개의 수수께끼가 아직 풀리지 않았다,Er blijven nog drie onderdelen van de puzzel over,Tre deler av puslespillet gjenstår,Pozostały jeszcze trzy części zagadki,Faltam mais três partes do quebra-cabeça,,Trei părți din puzzle încă rămân,Остались три части головоломки,Остају још три дела загонетке ,Bulmacanın üç parçası daha kaldı. -Two more parts of the puzzle remain,TXT_ACS_MAP44_2_TWOMO,,,,Zbývají dvě části rébusu.,Der er endnu to dele af puslespillet tilbage,Zwei weitere Teile des Rätsels verbleiben,,Nur du partoj de la puzlo restas.,Quedan dos partes más del acertijo,,Kaksi pulman palasta jäljellä,Deux parties du puzzle restent à résoudre.,Kettő rész maradt a rejtvényből,Rimangono altre due parti del puzzle,パズルの部品は残り 2つ,2개의 수수께끼가 아직 풀리지 않았다,Twee andere delen van de puzzel blijven over,To deler av puslespillet gjenstår,Pozostały jeszcze dwie części zagadki,Faltam mais duas partes do quebra-cabeça,,Două părți din puzzle încă rămân,Остались две части головоломки,Остају још два дела загонетке,Bulmacanın iki parçası daha kaldı -One more part of the puzzle remains,TXT_ACS_MAP44_3_ONEMO,,,,Zbývá jedna část rébusu.,Der er endnu en del af puslespillet tilbage,Ein weiteres Teil des Rätsels ist übrig,,Nur unu parto de la puzlo restas.,Queda una parte más del acertijo,,Yksi pulman palanen jäljellä,Il reste une partie du puzzle à résoudre.,Egy rész maradt a rejtvényből,Rimane un'altra parte del puzzle,パズルの部品は残り 1つ,마지막 수수께끼가 아직 풀리지 않았다,Nog een deel van de puzzel blijft over,En del av puslespillet gjenstår,Pozostała jeszcze jedna część zagadki,Falta mais uma parte do quebra-cabeça,,O parte din puzzle încă rămâne,Осталась одна часть головоломки,Остаје још један део загонетке,Bulmacanın bir parçası daha kaldı -The puzzle is complete,TXT_ACS_MAP44_4_THEPU,,,,Rébus je kompletní.,Puslespillet er færdigt,Das Rätsel ist abgeschlossen,,La puzlo estas kompleta.,El acertijo está completo,,Pulma on ratkaistu,Le puzzle est résolu.,A rejtvény végleg megoldódott,Il puzzle è completo,パズルは完成した,모든 수수께끼가 풀렸다,De puzzel is compleet,Puslespillet er komplett,Zagadka ukończona,O quebra-cabeça está concluído,,Puzzle-ul e rezolvat,Головоломка разгадана,Загонетка је решена,Bulmaca tamamlandı -You have not completed the puzzle,TXT_ACS_MAP44_6_YOUHA,,,,Nesplnil jsi rébus.,Du har ikke fuldført puslespillet,Du hast das Rätsel noch nicht gelöst,,Vi ne kompletis la puzlon.,No has completado el acertijo,,Et ole ratkaissut pulmaa,Vous n'avez pas résolu le puzzle.,Nem fejtetted meg a rejtvényt,Non hai completato il puzzle,パズルはまだ完成していない,모든 수수께끼를 풀지 못했다,Je hebt de puzzel nog niet voltooid.,Du har ikke fullført puslespillet,Nie ukończyłeś zagadki,Você não concluiu o quebra-cabeça,,Nu ai rezolvat puzzle-ul,Головоломка не разгадана,Нисте решили загонетку,Bulmacayı tamamlamadınız -The floor is not safe!,TXT_ACS_MAP44_8_THEFL,,,,Podlaha není bezpečná!,Gulvet er ikke sikkert!,Der Boden hier ist nicht sicher!,,La planko ne estas sendanĝera!,¡El suelo no es seguro!,,Kerros ei ole turvallinen!,Le sol est dangereux!,A padló nem biztonságos!,Il pavimento è pericoloso!,この場は安全ではない!,이 층은 안전하지 않다!,De vloer is niet veilig!,Gulvet er ikke trygt!,Ta podłoga nie jest bezpieczna!,O chão não está seguro!,,Podeaua nu e sigură!,Пол совсем прогнил!,Под није безбедан!,Zemin güvenli değil! -One third of the puzzle is solved,TXT_ACS_MAP44_10_ONETH,,,,Jedna třetina rébusu je vyřešena.,En tredjedel af puslespillet er løst,Ein Drittel des Rätsels ist gelöst,,Unu triono de la puzlo estas solvita.,Un tercio del acertijo se ha resuelto,,Kolmannes pulmasta on ratkaistu,Un tiers du puzzle à été résolu,A rejtvény egyharmada megoldásra került,Un terzo del puzzle è stato risolto,パズルの 三分の一 が解かれた,수수께끼의 3분의 1이 풀렸다,Een derde van de puzzel is opgelost.,En tredjedel av puslespillet er løst,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle e rezolvată,Одна треть головоломки разгадана,Трећина загонетке је решена,Bulmacanın üçte biri çözüldü -Two thirds of the puzzle is solved,TXT_ACS_MAP44_11_TWOTH,,,,Dvě třetiny rébusu jsou vyřešeny.,To tredjedele af puslespillet er løst,Zwei Drittel des Rätsels sind gelöst,,Du trionoj de la puzlo estas solvita.,Dos tercios del acertijo se han resuelto,,Kaksi kolmannesta pulmasta on ratkaistu,Deux tiers du puzzle ont été résolus,A rejtvény kétharmada megoldásra került,Due terzi del puzzle sono stati risolto,パズルの 三分の二 が解かれた,수수께끼의 3분의 2가 풀렸다,Tweederde van de puzzel is opgelost,To tredjedeler av puslespillet er løst.,Dwie trzecie zagadki rozwiązane,Dois terços do quebra-cabeça foi resolvido,,Două treimi din puzzle sunt rezolvate,Две трети головоломки разгаданы,Две трећине загонетке су решене,Bulmacanın üçte ikisi çözüldü +,,Hexen script texts,,,,,,,,,,,,,,,,,,,,,,,,, +The door is locked,TXT_ACS_MAP01_5_THEDO,,,,Dveře jsou zamčené.,Døren er låst,Die Tür ist verschlossen,,La pordo estas ŝlosita.,La puerta está cerrada,,Ovi on lukittu,Cette porte est verouillée.,Az ajtó zárva van.,La porta è bloccata,扉は施錠されている,문이 잠겨 있다,De deur is op slot,Døren er låst,Drzwi są zablokowane,A porta está trancada,,Ușa e încuiată,Дверь заперта,Врата су закључана,Dörren är låst,Kapı kilitli +"Greetings, mortal",TXT_ACS_MAP02_9_GREET,,,,"Vítej, smrtelníče,","Vær hilset, dødelige","Sei gegrüßt, Sterblicher",,"Salutojn, mortemul'.","Saludos, mortal",,"Tervehdys, kuolevainen","Salutations, humain.","Üdvözöllek, halandó!","Salve, mortale",御機嫌よう、小僧,"환영한다, 필멸자여.","Groeten, sterfelijk","Vær hilset, dødelige",Witaj śmiertelniku,"Saudações, mortal.",,"Salutări, muritorule","Приветствую, смертный","Поздрав, смртниче","Hälsningar, dödliga","Selamlar, ölümlü" +Are you ready to die?,TXT_ACS_MAP02_11_AREYO,,,,jsi připraven@[ao_cs] zemřít?,Er du klar til at dø?,Bist du bereit zu sterben?,,Ĉu vi pretas morti?,¿Estás listo para morir?,,Oletko valmis kuolemaan?,Êtes-vous prêt à mourir?,Készen állsz a halálra?,Sei pronto a morire?,死に急ぐ仕度は整ったか?,죽을 준비는 됐는가?,Ben je klaar om te sterven?,Er du klar til å dø?,Czy jesteś gotów na śmierć?,Você está pront@[ao_ptb] para morrer?,,Ești pregătit să mori?,Готов ли ты умереть?,Јеси ли спреман да умреш?,Är du redo att dö?,Ölmeye hazır mısın? +A door opened on the Guardian of Ice,TXT_ACS_MAP02_20_ADOOR,,,,Ve Strážci ledu se otevřely dveře.,En dør åbnede sig på isens vogter,Eine Tür öffnet sich zum Wächter des Eises,,Pordo malfermiĝis ĉe la Gardanto de Glacia.,Se abrió una puerta en el Guardián de Hielo,,Ovi avautui jään vartijan luona,Une porte s'est ouverte dans le Gardien de Glace.,Egy ajtó kinyillott a Jég Őrzőjénél,Una porta è stata aperta sul Guardiano di Ghiaccio,氷の守護者にある扉は開かれた,얼음의 수호자에서 문이 열렸다,Een deur opende op de bewaker van ijs,En dør åpnet seg på Isens vokter,Drzwi w Strażniku Lodu otworzyły się,Uma porta se abriu no Guardião de Gelo,,O ușă s-a deschis pe Gardianul de Foc,Дверь открыта у стража льда,Врата су отворена код Чувара леда,En dörr öppnades på isens väktare,Buz Muhafızı'nda bir kapı açıldı +This path is barred,TXT_ACS_MAP03_12_THISP,,,,Cesta je zatarasená.,Denne vej er spærret,Dieser Pfad ist blockiert,,Ĉi tiu vojo estas barita.,Este camino está atrancado,,Tämä polku on teljetty,Ce chemin est barré.,Ez az út el van torlaszolva.,Questo percorso è sbarrato,この道は塞がれている,이 통로는 빗장이 걸려있다,Dit pad is geblokkeerd,Denne veien er sperret,Ścieżka jest zablokowana,Este caminho está bloqueado,,Această cale e blocată,Сейчас этот путь закрыт,Овај пут је тренутно забрањен,Denna väg är spärrad,Bu yol yasaklandı +One half of the puzzle has been solved,TXT_ACS_MAP04_9_ONEHA,,,,U Sedmera portálů byla vyřešena,Den ene halvdel af puslespillet er blevet løst,Eine Hälfte des Rätsels wurde gelöst,,Unu duono de la puzlo estas solvita,Una mitad del acertijo se ha resuelto,,Puolet pulmasta on ratkaistu,La moitié du puzzle à été résolu,A rejtvény egyik fele meg lett fejtve,Metà del puzzle è stato risolto,パズルの一つが解かれた,수수께끼의 절반이 풀렸다,De helft van de puzzel is opgelost,Den ene halvdelen av gåten er løst,Połowa zagadki rozwiązana,Metade do quebra-cabeça foi resolvido,,O jumătate din puzzle e rezolvată,Половина головоломки разгадана,Половина загонетке је решена,En halva av pusslet har lösts,Bulmacanın bir yarısı çözüldü +on the Seven Portals,TXT_ACS_MAP04_10_ONTHE,,,,jedna třetina rébusu.,på de syv portaler,bei den Sieben Portalen,,ĉe la Sep Portaloj.,en los Siete Portales,,seitsemän portaalin luona,pour les Sept Portails.,a Hét Portálon,nei Sette Portali,漆之門に影響を与えた,... 일곱 차원문에서,op de Zeven Portalen,på de syv portaler,przy Siedmiu Portalach,nos Sete Portais,,pe cele Șapte Portaluri,на Семи порталах,на Седам портала,på de sju portalerna,Yedi Portalda +One third of the puzzle has been solved,TXT_ACS_MAP04_11_ONETH,,,,U Sedmera portálů byla vyřešena,En tredjedel af gåden er blevet løst,Ein Drittel des Rätsels wurde gelöst,,Unu triono de la puzlo estas solvita,Un tercio del acertijo se ha resuelto,,Kolmannes pulmasta on ratkaistu,Un tiers du puzzle à été résolu,A rejtvény egyharmada megfejtésre került,Un terzo del puzzle è stato risolto,三種のパズルの一つが解かれた,수수께끼의 3분의 1이 풀렸다,Een derde van de puzzel is opgelost,En tredjedel av puslespillet er løst,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle a fost rezolvată,Треть головоломки разгадана,Трећина загонетке је решена,En tredjedel av pusslet har lösts,Bulmacanın üçte biri çözüldü +Stairs have risen on the Seven Portals,TXT_ACS_MAP04_12_STAIR,,,,jedna třetina rébusu.,Der er kommet en trappe op på de syv portaler,Stufen bei den Sieben Portale wurden erbaut,,Ŝtupoj leviĝis ĉe la Sep Portaloj.,Unas escaleras se han erguido en los Siete Portales,,Portaat ovat kohonneet seitsemän portaalin luona,Des escaliers sont apparus dans les Sept Portails.,A Hét Portálon belül egy lépcsősor emlekedett,Sono sorte le scale nei Sette Portali,漆之門に階段が立ち昇った,일곱 차원문에서 계단이 솟아났다,Trappen zijn gestegen op de Zeven Portalen,Trapper har reist seg på De syv portaler,Schody przy Siedmiu Portalach podniosły się,As escadas se ergueram nos Sete Portais,,S-au ridicat scări pe cele Șapte Portaluri,Лестница воздвигнулась на Семи порталах,Степенице се подижу на Седам портала,En trappa har stigit upp i de sju portalerna,Yedi Portalda merdivenler yükseldi +One third of the puzzle has been solved,TXT_ACS_MAP05_6_ONETH,,,,U Sedmera portálů byla vyřešena,En tredjedel af puslespillet er blevet løst,Ein Drittel des Rätsels wurde gelöst,,Unu triono de la puzlo estas solvita,Un tercio del acertijo se ha resuelto,,Kolmannes pulmasta on ratkaistu,Un tiers du puzzle à été résolu,A rejtvény egyharmada megfejtésre került,Un terzo del puzzle è stato risolto,三種のパズルの一つが解かれた,수수께끼의 3분의 1이 풀렸다,Een derde van de puzzel is opgelost,En tredjedel av puslespillet er løst,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle a fost rezolvată,Треть головоломки разгадана,Трећина загонетке је решена,En tredjedel av pusslet har lösts,Bulmacanın üçte biri çözüldü +on the Seven Portals,TXT_ACS_MAP05_7_ONTHE,,,,jedna třetina rébusu.,på de syv portaler,bei den Sieben Portalen,,ĉe la Sep Portaloj.,en los Siete Portales,,seitsemän portaalin luona,pour les Sept Portails.,a Hét Portálon,nei Sette Portali,漆之門 に影響を与えた,... 일곱 차원문에서,op de Zeven Portalen,på de syv portaler,przy Siedmiu Portalach,nos Sete Portais,,pe cele Șapte Portaluri,на Семи порталах,на Седам портала,på de sju portalerna,Yedi Portalda +Stairs have risen on the Seven Portals,TXT_ACS_MAP05_8_STAIR,,,,Schody se zvedly u Sedmera portálů.,Trappen er steget op på de syv portaler,Stufen bei den Sieben Portale wurden erbaut,,Ŝtupoj leviĝis ĉe la Sep Portaloj.,Unas escaleras se han erguido en los Siete Portales,,Portaat ovat kohonneet seitsemän portaalin luona,Des escaliers sont apparus dans les Sept Portails.,A Hét Portálon belül egy lépcsősor emlekedett,Sono sorte le scale nei Sette Portali,漆之門 に階段が立ち昇った,일곱 차원문에서 계단이 솟아났다,Trappen zijn gestegen op de Zeven Portalen,Trappene har reist seg på De syv portaler,Schody przy Siedmiu Portalach podniosły się,Escadas se ergueram nos Sete Portais,,S-au ridicat scări pe cele Șapte Portaluri,Лестница воздвигнулась на Семи порталах,Степенице се подижу на Седам портала,Trappor har stigit upp på de sju portalerna,Yedi Portalda merdivenler yükseldi +You have to find another switch...,TXT_ACS_MAP05_9_YOUHA,,,,Musíš najít další spínač.,Du skal finde en anden kontakt...,Du must einen weiteren Schalter finden...,,Vi bezonas trovi alian ŝaltilon...,Debes encontrar otro interruptor...,Debes encontrar otro switch...,Sinun on löydettävä toinen vipu...,Vous devez trouver un autre bouton..,Egy másik kapcsolót kell találnod...,Devi trovare un altro interruttore...,他のスイッチも探す必要がある...,다른 개폐기를 찾아야 한다,Je moet een andere schakelaar vinden...,Du må finne en annen bryter...,Musisz znaleźć inny przełącznik...,Você precisa encontrar outro interruptor...,,Trebuie să găsești alt buton...,Остался ещё один переключатель...,Остао је још један прекидач...,Du måste hitta en annan omkopplare...,Başka bir anahtar bulmalısın... +Stones grind on the Seven Portals,TXT_ACS_MAP05_10_STONE,,,,Kameny dřou u Sedmera portálů.,Stenene knirker på de syv portaler,Steine schleifen bei den Sieben Portalen,,Ŝtonoj grincas ĉe la Sep Portaloj.,Las piedras giran en los Siete Portales,,Kiviä vierii seitsemän portaalin luona,Des pierres grincent dans les Sept Portails.,Kövek örlődnek a Hét Portálnál,Le pietre si sono frantumate nei Sette Portali,漆之門 の石壁が砕かれた,일곱 차원문에서 바위 부딪히는 소리가 들려왔다,Stenen slijpen op de Zeven Portalen,Steiner knuser på De syv portaler,Kamienie przy Siedmiu Portalach zgrzytają,As pedras giram nos Sete Portais,,Pietrele încep să macine pe cele Șapte Portaluri,Каменная преграда отступила на Семи порталах,Камена препрека се повлачи,Stenar slipar på de sju portalerna,Taşlar Yedi Portalda öğütülüyor +One sixth of the puzzle has been solved,TXT_ACS_MAP08_6_ONESI,,,,V Temném hvozdu byla vyřešena,En sjettedel af puslespillet er blevet løst,Ein Sechstel des Rätsels wurde gelöst,,Unu sesono de la puzlo estas solvita,Un sexto del acertijo se ha resuelto,,Kuudennes pulmasta on ratkaistu,Un sixième du puzzle à été résolu,A feladványok egyhatoda megfejtésre került,Un sesto del puzzle è stato risolto,六種のパズルの一つが解かれた,수수께끼의 6분의 1이 풀렸다,Een zesde van de puzzel is opgelost,En sjettedel av puslespillet er løst,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена,En sjättedel av pusslet har lösts,Bulmacanın altıda biri çözüldü +on the Shadow Wood,TXT_ACS_MAP08_7_ONTHE,,,,jedna šestina rébusu.,i Skyggetræet,Im Schattenwald,,en la Ombro-Arbareto.,En el Bosque de Sombras,,Varjosalossa,dans le Bois des Ombres.,a Sötét Erdőben,Nel Bosco d'Ombra,陰影樹 に少し影響を与えた,... 그림자 숲에서,op het Schaduwbos,på Skyggeskogen,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки,i skuggskogen,Gölge Ormanı'nda +The door is barred from the inside,TXT_ACS_MAP08_10_THEDO,,,,Dveře jsou zatarasené zevnitř.,Døren er spærret indefra,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está atrancada desde el interior,,Ovi on teljetty sisältä,Cette porte est bloquée de l'intérieur.,Az ajtó be van reteszelve belülről,La porta è sbarrata da dentro,この扉は内側から塞がれている,이 문은 안에 빗장이 걸려있다,De deur is van binnenuit geblokkeerd.,Døren er sperret fra innsiden,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра,Dörren är spärrad från insidan,Kapı içeriden kilitli. +You hear a door open in the distance,TXT_ACS_MAP08_11_YOUHE,,,,Slyšíš v dálce otevírající se dveře.,Du hører en dør åbne i det fjerne,"Du hörst, wie sich in der Ferne eine Tür öffnet",,Vi aŭdas pordon malfermiĝantan malproksime.,Escuchas que una puerta se abre a la distancia,,Kuulet oven avautuvan etäällä,Vous entendez une porte s'ouvrir au loin.,Hallod ahogy egy ajtó kinyílik a távolban,Senti una porta aprirsi in lontananza,遠くから扉が開く音が聞こえる,멀리서 문이 열리는 소리가 들린다,In de verte hoor je een deur openstaan.,Du hører en dør åpnes i det fjerne,Słyszysz odgłos otwierających się w oddali drzwi,Você ouve de longe uma porta se abrindo,,Auzi o ușă deschizându-se în depărtare,Слышен звук открывающейся двери,Чује се звук отварања врата,Du hör en dörr som öppnas i fjärran,Uzakta bir kapının açıldığını duyuyorsun. +One sixth of the puzzle has been solved,TXT_ACS_MAP09_6_ONESI,,,,V Temném hvozdu byla vyřešena,En sjettedel af puslespillet er blevet løst,Ein Sechstel des Rätsels wurde gelöst,,Unu sesono de la puzlo estas solvita,Un sexto del acertijo se ha resuelto,,Kuudennes pulmasta on ratkaistu,Un sixième du puzzle à été résolu,A feladványok egyhatoda megfejtésre került,Un sesto del puzzle è stato risolto,六種のパズルの一つが解かれた,수수께끼의 6분의 1이 풀렸다,Een zesde van de puzzel is opgelost,En sjettedel av gåten er løst,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена,En sjättedel av pusslet har lösts.,Bulmacanın altıda biri çözüldü +on the Shadow Wood,TXT_ACS_MAP09_7_ONTHE,,,,jedna šestina rébusu.,i Skyggetræet,Im Schattenwald,,en la Ombro-Arbareto.,En el Bosque de Sombras,,Varjosalossa,dans le Bois des Ombres.,a Sötét Erdőben,Nel Bosco d'Ombra,陰影樹 に少し影響を与えた,... 그림자 숲에서,op het Schaduwbos,på Skyggeskogen,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки,i skuggskogen,Gölge Ormanı'nda +One sixth of the puzzle has been solved,TXT_ACS_MAP10_6_ONESI,,,,V Temném hvozdu byla vyřešena,En sjettedel af puslespillet er blevet løst,Ein Sechstel des Rätsels wurde gelöst,,Unu sesono de la puzlo estas solvita,Un sexto del acertijo se ha resuelto,,Kuudennes pulmasta on ratkaistu,Un sixième du puzzle à été résolu,A feladványok egyhatoda megfejtésre került,Un sesto del puzzle è stato risolto,六種のパズルの一つが解かれた,수수께끼의 6분의 1이 풀렸다,Een zesde van de puzzel is opgelost,En sjettedel av puslespillet har blitt løst,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена,En sjättedel av pusslet har lösts.,Bulmacanın altıda biri çözüldü +on the Shadow Wood,TXT_ACS_MAP10_7_ONTHE,,,,jedna šestina rébusu.,i Skyggetræet,Im Schattenwald,,en la Ombro-Arbareto.,En el Bosque de Sombras,,Varjosalossa,dans le Bois des Ombres.,a Sötét Erdőben,Nel Bosco d'Ombra,陰影樹 に少し影響を与えた,... 그림자 숲에서,op het Schaduwbos,på Skyggeskogen,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки,i skuggskogen,Gölge Ormanı'nda +\ ettins left,TXT_ACS_MAP11_0_ETTIN,Yellow needs better translation,,,\ etinů zbývá.,\ ettins venstre,\ Ettins übrig,,\ gigantaĉoj ceteraj,\ Ettins restantes,,\ ettiniä jäljellä,\ ettins restants,\ ettin maradt,\ Ettins rimasti,\ 匹のエティンが残っている,\ 마리 에틴이 남았음,\ overgebleven Ettins,\ ettins igjen,\ pozostałych ettinów,\ ettins restantes,,\ etini rămași,\ оставшихся эттинов,Остало је \ еттина,\ ettins lämnade,\ ettins ayrıldı +"You waited too long, now you die!",TXT_ACS_MAP11_1_YOUWA,,,,"Čekal@[ao_cs] jsi moc dlouho, teď zemřeš!","Du ventede for længe, nu dør du!","Du hast zu lange gewartet, jetzt stirbst du!",,"Vi atendis tro longe, nun vi mortas!","Esperaste demasiado, ¡ahora morirás!",,"Odotit liian pitkään, nyt kuolet!","Vous avez attendu trop longtemps, maintenant, mourrez!","Túl sokáig vártál, most meghalsz!","Hai atteso troppo a lungo, ora muori!",長居をしたな、命を奪うには十分な程に!,시간을 너무 오래 끌었다. 이제 죽어라!,"Je hebt te lang gewacht, nu ga je dood!","Du ventet for lenge, nå dør du!",Czekałeś zbyt długo. Teraz giń!,Você esperou demais. Agora morrerá!,,"Ți-a luat prea mult, acum mori!",Слишком долго! Готовься к смерти!,Предуго! Припреми се за смрт!,"Du väntade för länge, nu dör du!","Çok bekledin, şimdi öleceksin!" +A door opened on the Forsaken Outpost,TXT_ACS_MAP11_7_ADOOR,,,,Dveře se otevřely na Opuštěném stanovišti.,En dør blev åbnet i forladt forpost,Eine Tür im verlassenen Vorposten hat sich geöffnet,,Pordo malfermiĝis ĉe la Forlasita Posteno.,Una puerta se abrió en el Puesto de Avanzada Abandonado,,Ovi avautui hylätyssä etuvartiossa,Une porte s'est ouverte dans la base abandonnée.,Egy ajtó kinyílik az Elátkozott Őrportyán,Una porta è stata aperta nell'Avamposto Abbandonato,荒れ果てた前哨地 への扉が開いた,버려진 초소에서 문이 열렸다,Een deur opende een deur op de Verwaarloosde buitenpost,En dør åpnet seg på den forlatte utposten,Drzwi przy Opuszczonym Posterunku otworzyły się,Uma porta se abriu no Posto Abandonado,,O ușă s-a deschis pe Avanpostul Părăsit,Дверь открылась на покинутой заставе,Врата су се отворила у Напуштеној постаји,En dörr har öppnats på försvunnen utposten,Unutulmuş Karakol'da bir kapı açıldı +This door won't open yet,TXT_ACS_MAP12_9_THISD,,,,Tyto dveře se ještě neotevřou.,Denne dør vil ikke åbne sig endnu,Die Tür öffnet sich noch nicht,,Ĉi tiu pordo ne jam malfermiĝos.,Esta puerta no se abrirá todavía,,Tämä ovi ei aukea vielä,Cette porte ne s'ouvre pas pour l'instant.,Ez az ajtó még nem fog kitárulni.,Questa porta non è aperta ancora,扉はまだ開かない,이 문은 아직 열 수 없다,Deze deur gaat nog niet open.,Denne døren vil ikke åpne seg ennå,Te drzwi jeszcze się nie otwierają,Esta porta não se abrirá ainda,,Ușa n-o să se deschidă încă,Сейчас эта дверь закрыта,Ова врата су тренутно закључана,Den här dörren kommer inte att öppnas än.,Bu kapı henüz açılmayacak. +"My servants can smell your blood, human",TXT_ACS_MAP13_11_MYSER,,,,"Mí služebníci cítí tvou krev, člověče.","Mine tjenere kan lugte dit blod, menneske","Meine Diener riechen dein Blut, Menschling",,"Miajn servantoj povas flari vian sangon, homo.","Mis sirvientes pueden oler tu sangre, humano",,"Palvelijani voivat haistaa veresi, ihminen","Mes servants peuvent sentir votre sang, humain.","Szolgáim érzik a véred szagát, emberfattya","I miei servi possono annusare il tuo sangue, umano",我が下僕が貴様の血を嗅ぎ付けた様だぞ、小童,"이 몸의 하인들은 네 피 냄새를 맏고 따라온다, 인간.","Mijn bedienden kunnen jouw bloed ruiken, mens","Mine tjenere kan lukte blodet ditt, menneske",Moje sługi czują twą krew śmiertelniku,"Meus servos sentem o cheiro do seu sangue, human@[ao_ptb]",,"Servitorii mei îți pot adulmeca sângele, muritorule","Мои прислужники чуют твою кровь, человек","Моје слуге миришу твоју крв, човече","Mina tjänare kan känna lukten av ditt blod, människa.","Hizmetçilerim kanının kokusunu alabiliyor, insan." +A door opened in the Gibbet,TXT_ACS_MAP21_0_ADOOR,,,,Dveře se otevřely na Šibenici.,En dør blev åbnet i Gibbet,Eine Tür in der Richtstätte wurde geöffnet,,Pordo malfermiĝis ĉe la Pendigilo.,Una puerta se abrió en la horca,,Ovi avautui hirsipuulla,Une porte s'est ouverte dans le gibet.,Egy ajtó kinyílik az Akasztófánál,Una porta è stata aperta nella Forca,晒し台 への扉が開いた,교수대에서 문이 열렸다,Een deur geopend in de Gibbet,En dør åpnet seg i galgen,Drzwi przy Szubienicy otworzyły się,Uma porta se abriu na Forca,,O ușă s-a deschis pe Eșafod,Проход будет открыт возле виселицы,Пролаз је отворен код вешала,En dörr öppnades i Gibbet,İnfaz yerinde bir kapı açıldı +The door is barred from the inside,TXT_ACS_MAP21_2_THEDO,,,,Dveře jsou zatarasené zevnitř.,Døren er spærret indefra,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está atrancada desde el interior,,Ovi on teljetty sisältä,Cette porte est bloquée de l'intérieur.,Az ajtó belülről van eltorlaszolva,La porta è sbarrata da dentro,この扉は内側から塞がれている,이 문은 안에 빗장이 걸려있다,De deur is van binnenuit geblokkeerd.,Døren er sperret fra innsiden,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра,Dörren är spärrad från insidan,Kapı içeriden kilitli. +A platform has lowered in the tower,TXT_ACS_MAP22_3_APLAT,,,,Plošina ve věži sjela dolů.,En platform er sænket i tårnet,Im Turm hat sich eine Plattform gesenkt,,Plataĵo malleviĝis en la turo.,Una plataforma ha bajado en la torre,,Lava on laskeutunut tornissa,Une plateforme est descendue dans la tour.,Egy platform leereszkedett a toronyban,Una piattaforma si è abbassata nella torre,塔内の昇降機が下りた,성 안에서 보행판이 내려왔다,Een platform is in de toren neergelaten in de toren,En plattform har senket seg i tårnet,Platforma w wieży obniżyła się,Uma plataforma desceu na torre,,O platformă a coborât în turn,Площадка опустилась в центральной башне,Спустио се платформ у централном торњу,En plattform har sänkts i tornet,Kuleye bir platform indirildi +"You have played this game too long, mortal...",TXT_ACS_MAP22_27_YOUHA,,,,"Tuhle partii jsi už hrál@[ao_cs] moc dlouho, smrtelníče,","Du har spillet dette spil for længe, dødelige...","Du spielst schon zu lange, Sterblicher...",,"Ludis ĉi tiun ludon vi tro longe, mortemul'...","Has jugado este juego demasiado tiempo, mortal...",,"Olet pelannut tätä peliä liian pitkään, kuolevainen...","Vous avez joué à ce jeu trop longtemps, mortel..","Túl sokat játszadoztál, halandó...","Ha giocato a questo gioco troppo a lungo, mortale...",遊びはここまでだ、小僧,"네 놈은 오랫동안 놀았도다, 필멸자여...","Je hebt dit spel te lang gespeeld, sterfelijke...","Du har spilt dette spillet for lenge, dødelige...",Już za długo grasz w tą grę śmiertelniku...,"Você jogou este jogo por tempo demais, mortal...",,"Ai jucat acest joc prea multă vreme, muritorule...","Ты слишком заигрался, смертный...","Превише си се заиграо, смртниче...","Du har spelat det här spelet för länge, dödlig...","Bu oyunu çok uzun oynadın, ölümlü." +I think I shall remove you from the board,TXT_ACS_MAP22_29_ITHIN,,,,"myslím, že bych tě měl odstranit ze šachovnice.","Jeg tror, jeg vil fjerne dig fra brættet.",Ich denke ich sollte dich vom Brett entfernen,,"Mi kredas, ke mi vin forigos el la tabul'.",Creo que te retiraré del tablero,,Ajattelenpa poistaa sinut pelilaudalta,Je pense qu'il est l'heure de vous retirer de l'échiquier.,"Azt hiszem le kell, hogy üsselek a tábláról",Penso che ti rimuoverò dalla scacchiera,盤上から貴様を排除する,이 몸이 너를 말 치우듯이 제거하겠다.,Ik denk dat ik u van het bord zal verwijderen,Jeg tror jeg skal fjerne deg fra brettet,"Myślę, że usunę cię z planszy",Acho que irei removê-l@[ao_ptb] do tabuleiro,,Cred că e timpul să te înlătur de pe tablă,Пришло время завершить твою партию,Дошло је време да се заврши твоја партија,Jag tror att jag ska ta bort dig från spelplanen.,Sanırım seni tahtadan kaldırmalıyım. +You hear a door open upstairs,TXT_ACS_MAP23_10_YOUHE,,,,Z patra slyšíš otevírající se dveře.,Du hører en dør blive åbnet ovenpå.,"Du hörst, wie sich oben eine Tür öffnet",,Vi aŭdas pordon malfermiĝantan superŝtupare.,Escuchas una puerta que se abre arriba,,Kuulet oven avautuvat yläkerrassa,Vous entendez une porte s'ouvrir à l'étage.,Hallod ahogy egy ajtó kinyílik az emeleten,Senti una porta aprirsi al piano di sopra,上層階の扉が開いた,윗층에서 문이 열리는 소리가 들린다,Je hoort een deur boven opengaan,Du hører en dør åpnes ovenpå,Słyszysz odgłos otwierających się na górze drzwi,Você ouve uma porta se abrir lá em cima,,Auzi o ușă deschizându-se sus,Слышен звук открывающейся двери наверху,Од северне дворане зачује се звук,Du hör en dörr öppnas på övervåningen.,Üst katta bir kapının açıldığını duyuyorsun. +"Worship me, and I may yet be merciful",TXT_ACS_MAP27_8_WORSH,,,,Uctívej mě a možná ještě budu milosrdný.,"Tilbeder du mig, så er jeg måske barmhjertig.",Verehre mich und ich könnte gnädig sein,,"Kultu min, tiam mi ankoraŭ eble kompatos.","Adórame, y aun puedo ser misericordioso",,"Palvo minua, ja saatan vielä olla armahtavainen","Prosternez vous devant moi, et je pourrai considérer de vous épargner.","Hódolj be, és talán kegyelmes leszek","Venerami, e potrei essere ancora misericordioso",我を崇めろ、慈悲を残している内に,"이 몸에게 경배하라, 그럼 자비를 베풀 것이다.","Aanbid me, en ik mag dan nog genadig zijn","Tilbe meg, og jeg kan ennå være barmhjertig.","Wielb mnie, a może będę miłosierny","Venere-me, e eu poderei ser piedoso",,"Venerează-mă, și s-ar putea să mai fiu milostiv încă","Преклонись предо мной, и, может быть, я буду милосерден","Преклони се преда мноме, и можда ћу бити милостив","Dyrka mig, så kanske jag är barmhärtig.","Bana ibadet et, belki merhamet ederim" +"Then again, maybe not",TXT_ACS_MAP27_10_THENA,,,,"Na druhou stranu, možná ne.",Men måske heller ikke,"Andererseits, vielleicht aber auch nicht",,"Tamen, eble ne.","Aunque, tal vez no",,"Mutta toisaalta, ehken sittenkään",Quoi que cela soit peu probable.,"Jól átgondolva, inkább nem",O potrei anche non esserlo,まあ、有り得ないな,허나... 그러지는 않겠지.,"Maar nogmaals, misschien niet",Men kanskje ikke,"Z drugiej strony, może nie...","Pensando melhor, talvez não",,"Dar apoi, poate că nu","А может быть, и нет",А можда и нећу,"Men å andra sidan, kanske inte.","Sonra tekrar, belki de değil" +One ninth of the puzzle has been solved,TXT_ACS_MAP28_6_ONENI,,,,V Klášteru byla vyřešena,En niende del af puslespillet er blevet løst,Ein Neuntel des Rätsels wurde gelöst,,Unu naŭono de la puzlo estas solvita,Un noveno del acertijo se ha resuelto,,Yhdeksäsosa pulmasta on ratkaistu,Un neuvième du puzzle à été résolu,A rejtvény egy kilencede megfejtésre került,Un nono del puzzle è stato risolto,九種のパズルの一つが解かれた,수수께끼의 9분의 1이 풀렸다,Een negende van de puzzel is opgelost.,En niende del av puslespillet er løst.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена,En niondel av pusslet har lösts.,Bulmacanın dokuzda biri çözüldü +On the Monastery,TXT_ACS_MAP28_7_ONTHE,,,,jedna devítina rébusu.,På klosteret,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,på klosteret,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији,På klostret,Manastır Üzerine +One ninth of the puzzle has been solved,TXT_ACS_MAP30_6_ONENI,,,,V Klášteru byla vyřešena,En niende del af puslespillet er blevet løst,Ein Neuntel des Rätsels wurde gelöst,,Unu naŭono de la puzlo estas solvita,Un noveno del acertijo se ha resuelto,,Yhdeksäsosa pulmasta on ratkaistu,Un neuvième du puzzle à été résolu,A rejtvény egy kilencede megfejtésre került,Un nono del puzzle è stato risolto,九種のパズルの一つが解かれた,수수께끼의 9분의 1이 풀렸다,Een negende van de puzzel is opgelost.,En niende del av gåten er løst.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена,En niondel av pusslet har lösts.,Bulmacanın dokuzda biri çözüldü +On the Monastery,TXT_ACS_MAP30_7_ONTHE,,,,jedna devítina rébusu.,På klosteret,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,på klosteret,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији,På klostret,Manastır Üzerine +One ninth of the puzzle has been solved,TXT_ACS_MAP34_1_ONENI,,,,V Klášteru byla vyřešena,En niende del af puslespillet er blevet løst,Ein Neuntel des Rätsels wurde gelöst,,Unu naŭono de la puzlo estas solvita,Un noveno del acertijo se ha resuelto,,Yhdeksäsosa pulmasta on ratkaistu,Un neuvième du puzzle à été résolu,A rejtvény egy kilencede megfejtésre került,Un nono del puzzle è stato risolto,九種のパズルの一つが解かれた,수수께끼의 9분의 1이 풀렸다,Een negende van de puzzel is opgelost.,En niendedel av puslespillet er løst,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена,En nionde del av pusslet har lösts.,Bulmacanın dokuzda biri çözüldü +On the Monastery,TXT_ACS_MAP34_2_ONTHE,,,,jedna devítina rébusu.,På klosteret,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,på klosteret,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији,På klostret,Manastır Üzerine +The portal has been sealed,TXT_ACS_MAP35_0_THEPO,,,,Portál byl zapečeťen.,Portalen er blevet forseglet,Das Portal wurde versiegelt,,La portalo estas obturita.,El portal se ha sellado,,Portaali on sinetöity,Le portail est scellé.,Az átjáró bezárult.,Il portale è stato sigillato,ポータルは封印された,차원문은 봉인되었다,Het portaal is verzegeld,Portalen har blitt forseglet,Portal został zapieczętowany,O portal foi selado,,Portalul a fost închis,Портал закрылся,Врата су затворена,Portalen har förseglats.,Geçit mühürlendi +Choose your fate,TXT_ACS_MAP35_1_CHOOS,,,,Vyber si svůj osud.,Vælg din skæbne,Wähle dein Schicksal,,Elektu vian fatalon.,Escoge tu destino,Escoge tú destino,Valitse kohtalosi,Choisissez votre sort.,Dönts sorsod felől,Scegli la tua sorte,運命を撰べ,그대의 운명을 정해라,Kies uw lot,Velg din skjebne,Wybierz swoje przeznaczenie,Escolha o seu destino,,Alegeți destinul,Сделай свой выбор,Донеси своју одлуку,Välj ditt öde,Kaderinizi seçin +The door is barred from the inside,TXT_ACS_MAP35_3_THEDO,,,,Dveře jsou zatarasené zevnitř.,Døren er spærret indefra,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está atrancada desde el interior,,Ovi on teljetty sisältä,Cette porte est bloquée de l'intérieur.,Az ajtót belülről torlaszolták el.,La porta è sbarrata da dentro,この扉は内側から塞がれている,이 문은 안에 빗장이 걸려있다,De deur is van binnenuit geblokkeerd.,Døren er sperret fra innsiden,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра,Dörren är spärrad från insidan,Kapı içeriden kilitli. +Are you strong enough,TXT_ACS_MAP35_12_AREYO,,,,"Jsi dost siln@[adj_cs],",Er du stærk nok?,Bist du stark genug,,Ĉu vi estas sufiĉe forta,Eres lo suficientemente fuerte,,Olet riittävän vahva,Etes vous suffisamment fort,"Elég erős vagy,",Sei abbastanza forte,お前がどれだけ強かろうと,네 놈은 주인들을 대면할 힘이...,Ben je sterk genoeg,Er du sterk nok,Czy jesteś wystarczająco silny,Você é forte o suficiente,,Ești întradevăr suficient de puternic,"Достаточно ли ты силён,",Јеси ли довољно снажан,Är du stark nog?,Yeterince güçlü müsün? +To face your own masters?,TXT_ACS_MAP35_14_TOFAC,,,,čelit svým vlastním pánům?,Til at møde dine egne mestre?,Dich deinen eigenen Meistern zu stellen?,,por stari kontraŭ viaj propraj mastroj?,¿Para enfrentarte a tus maestros?,,kohtaamaan omat mestarisi?,pour faire face à vos maîtres?,Hogy saját mestereiddel nézz szembe?,Da affrontare i tuoi stessi maestri?,お前の師に立ち向かえるのか?,진심으로 있는 것인가?,Om je eigen meesters onder ogen te komen?,Til å møte dine egne mestere?,By stawić czoła swoim mistrzom?,Para enfrentar os seus próprios mestres?,,Să îți înfrunți proprii stăpâni?,чтобы сразиться со своими наставниками?,да се суочиш са својим господарима?,För att möta dina egna mästare?,Kendi efendilerinizle yüzleşmek için mi? +,,Hexen: Deathkings script texts,,,,,,,,,,,,,,,,,,,,,,,,, +You dare battle in the ready room?,TXT_ACS_MAP33_6_YOUDA,,,,Ty si dovoluješ rvát se v přípravné místnosti?,Tør du kæmpe i beredskabsrummet?,Du wagst es im Bereitschaftsraum zu kämpfen?,,Vi aŭdacas batali en la pretĉambro?,¿Te atreves a luchar en la sala de preparación?,,Kuinka kehtaat taistella valmistautumishuoneessa?,Vous osez faire escarmouche dans la salle de préparation?,Hogy merészelsz harcolni a váróteremben?,Hai il coraggio di combattere in questa sala?,挑戦する準備は整ったか?,감히 준비의 방에서 전투를 벌이다니...,Durf jij te vechten in de readyroom?,Våger du å kjempe i det klare rommet?,Śmiesz walczyć w pokoju przygotowań?,Como ousa batalhar na sala de espera?,,Îndrăznești să lupți în camera de așteptare?,Ты посмел сражаться в комнате ожидания?,Усуђујеш се борити у припремној соби?,Vågar du slåss i det färdiga rummet?,Hazırlanma odasında savaşmaya mı cüret ediyorsun? +"For that, you shall die!",TXT_ACS_MAP33_7_FORTH,,,,Pro to zemřeš!,For det skal du dø!,Dafür sollst du sterben!,,"Pro tio, vi mortos!","Por eso, ¡deberás morir!",,Siitä hyvästä kuolet!,"Pour cette insulte, vous trépasserez!",Ezért meghalsz!,"Per questo, morirai!",ならば、死へ進め!,죽어서 값을 치러라!,Daarvoor zal je sterven!,For det skal du dø!,Umrzesz za to!,Você morrerá por isso!,,"Pentru asta, vei muri!",Так умри же!,За то ћеш умрети!,För det ska du dö!,Bunun için öleceksin! +The waterfall is open,TXT_ACS_MAP41_6_THEWA,,,,Vodopád je otevřen.,Vandfaldet er åbent,Der Wasserfall ist geöffnet,,La akvofalo estas malferma.,La cascada se ha abierto,,Vesiputous on auki,La cascade s'est ouverte.,A vizesés nyitva,La cascata è aperta,滝 は開いた,폭포가 멈췄다,De waterval is open,Fossen er åpen,Wodospad jest otwarty,A cascata está aberta,,Cascada e deschisă,Поток воды остановлен,Водопад је отворен,Vattenfallet är öppet,Şelale açık +The waterfall is blocked,TXT_ACS_MAP41_7_THEWA,,,,Vodopád je zatarasen.,Vandfaldet er blokeret,Der Wasserfall ist blockiert,,La akvofalo estas barita.,La cascada está bloqueada,,Vesiputous on tukittu,La cascade est bloquée.,A vizesés zárva,La cascata è bloccata,滝 は塞がっている,폭포에 의해 막혔다,De waterval is geblokkeerd,Fossen er blokkert,Wodospad jest zablokowany,A cascata está bloqueada,,Cascada e închisă,Поток воды преграждает путь,Водопад је блокиран,Vattenfallet är blockerat,Şelale tıkalı +A door has opened in the chapel,TXT_ACS_MAP41_8_ADOOR,,,,Dveře se otevřely v kapli.,Der er åbnet en dør i kapellet,Eine Tür in der Kapelle hat sich geöffnet,,Pordo malfermis en la kapelo.,Una puerta se abrió en la Capilla,,Ovi on avautunut kappelissa,Une porte s'est ouverte dans la chapelle.,Egy ajtó kitárult a kápolnában,Una porta si è aperta nella cappella,庵寺 への扉が開いた,교외 근처에서 문이 열렸다,Een deur is geopend in de kapel,En dør har åpnet seg i kapellet,Drzwi w kaplicy zostały otwarte,Uma porta se abriu na capela,,O ușă s-a deschis în capelă,Дверь открылась в часовне,Врата су се отворила у катедрали,En dörr har öppnats i kapellet.,Şapelde bir kapı açıldı. +Now that's odd...,TXT_ACS_MAP42_4_NOWTH,,,,Tak to je divné...,Det er mærkeligt...,Hm. Das ist merkwürdig...,,Nun tio estas stranga...,Eso es extraño...,,Onpa kummallista...,Ca c'est étrange....,Ez felettébb különös...,Questo sì che è strano...,何かがおかしい...,무언가가 이상하다...,Dat is vreemd....,Det var merkelig...,Dziwne...,Que estranho...,,Asta e ciudat...,Как странно...,То је чудно...,Det där är konstigt...,İşte bu garip. +Three more parts of the puzzle remain,TXT_ACS_MAP44_1_THREE,,,,Zbývají tři části rébusu.,Der er endnu tre dele af gåden tilbage,Drei weitere Teile des Rätsels verbleiben,,Nur tri partoj de la puzlo restas.,Quedan tres partes más del acertijo,,Kolme pulman palasta jäljellä,Trois parties du puzzle restent à résoudre.,Három rész maradt a rejtvényből,Rimangono altre tre parti del puzzle,パズルの部品は残り 3つ,3개의 수수께끼가 아직 풀리지 않았다,Er blijven nog drie onderdelen van de puzzel over,Tre deler av puslespillet gjenstår,Pozostały jeszcze trzy części zagadki,Faltam mais três partes do quebra-cabeça,,Trei părți din puzzle încă rămân,Остались три части головоломки,Остају још три дела загонетке ,Det återstår tre delar av pusslet.,Bulmacanın üç parçası daha kaldı. +Two more parts of the puzzle remain,TXT_ACS_MAP44_2_TWOMO,,,,Zbývají dvě části rébusu.,Der er endnu to dele af puslespillet tilbage,Zwei weitere Teile des Rätsels verbleiben,,Nur du partoj de la puzlo restas.,Quedan dos partes más del acertijo,,Kaksi pulman palasta jäljellä,Deux parties du puzzle restent à résoudre.,Kettő rész maradt a rejtvényből,Rimangono altre due parti del puzzle,パズルの部品は残り 2つ,2개의 수수께끼가 아직 풀리지 않았다,Twee andere delen van de puzzel blijven over,To deler av puslespillet gjenstår,Pozostały jeszcze dwie części zagadki,Faltam mais duas partes do quebra-cabeça,,Două părți din puzzle încă rămân,Остались две части головоломки,Остају још два дела загонетке,Ytterligare två delar av pusslet återstår,Bulmacanın iki parçası daha kaldı +One more part of the puzzle remains,TXT_ACS_MAP44_3_ONEMO,,,,Zbývá jedna část rébusu.,Der er endnu en del af puslespillet tilbage,Ein weiteres Teil des Rätsels ist übrig,,Nur unu parto de la puzlo restas.,Queda una parte más del acertijo,,Yksi pulman palanen jäljellä,Il reste une partie du puzzle à résoudre.,Egy rész maradt a rejtvényből,Rimane un'altra parte del puzzle,パズルの部品は残り 1つ,마지막 수수께끼가 아직 풀리지 않았다,Nog een deel van de puzzel blijft over,En del av puslespillet gjenstår,Pozostała jeszcze jedna część zagadki,Falta mais uma parte do quebra-cabeça,,O parte din puzzle încă rămâne,Осталась одна часть головоломки,Остаје још један део загонетке,Ytterligare en del av pusslet återstår,Bulmacanın bir parçası daha kaldı +The puzzle is complete,TXT_ACS_MAP44_4_THEPU,,,,Rébus je kompletní.,Puslespillet er færdigt,Das Rätsel ist abgeschlossen,,La puzlo estas kompleta.,El acertijo está completo,,Pulma on ratkaistu,Le puzzle est résolu.,A rejtvény végleg megoldódott,Il puzzle è completo,パズルは完成した,모든 수수께끼가 풀렸다,De puzzel is compleet,Puslespillet er komplett,Zagadka ukończona,O quebra-cabeça está concluído,,Puzzle-ul e rezolvat,Головоломка разгадана,Загонетка је решена,Pusslet är komplett,Bulmaca tamamlandı +You have not completed the puzzle,TXT_ACS_MAP44_6_YOUHA,,,,Nesplnil jsi rébus.,Du har ikke fuldført puslespillet,Du hast das Rätsel noch nicht gelöst,,Vi ne kompletis la puzlon.,No has completado el acertijo,,Et ole ratkaissut pulmaa,Vous n'avez pas résolu le puzzle.,Nem fejtetted meg a rejtvényt,Non hai completato il puzzle,パズルはまだ完成していない,모든 수수께끼를 풀지 못했다,Je hebt de puzzel nog niet voltooid.,Du har ikke fullført puslespillet,Nie ukończyłeś zagadki,Você não concluiu o quebra-cabeça,,Nu ai rezolvat puzzle-ul,Головоломка не разгадана,Нисте решили загонетку,Du har inte fullbordat pusslet,Bulmacayı tamamlamadınız +The floor is not safe!,TXT_ACS_MAP44_8_THEFL,,,,Podlaha není bezpečná!,Gulvet er ikke sikkert!,Der Boden hier ist nicht sicher!,,La planko ne estas sendanĝera!,¡El suelo no es seguro!,,Kerros ei ole turvallinen!,Le sol est dangereux!,A padló nem biztonságos!,Il pavimento è pericoloso!,この場は安全ではない!,이 층은 안전하지 않다!,De vloer is niet veilig!,Gulvet er ikke trygt!,Ta podłoga nie jest bezpieczna!,O chão não está seguro!,,Podeaua nu e sigură!,Пол совсем прогнил!,Под није безбедан!,Golvet är inte säkert!,Zemin güvenli değil! +One third of the puzzle is solved,TXT_ACS_MAP44_10_ONETH,,,,Jedna třetina rébusu je vyřešena.,En tredjedel af puslespillet er løst,Ein Drittel des Rätsels ist gelöst,,Unu triono de la puzlo estas solvita.,Un tercio del acertijo se ha resuelto,,Kolmannes pulmasta on ratkaistu,Un tiers du puzzle à été résolu,A rejtvény egyharmada megoldásra került,Un terzo del puzzle è stato risolto,パズルの 三分の一 が解かれた,수수께끼의 3분의 1이 풀렸다,Een derde van de puzzel is opgelost.,En tredjedel av puslespillet er løst,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle e rezolvată,Одна треть головоломки разгадана,Трећина загонетке је решена,En tredjedel av pusslet är löst,Bulmacanın üçte biri çözüldü +Two thirds of the puzzle is solved,TXT_ACS_MAP44_11_TWOTH,,,,Dvě třetiny rébusu jsou vyřešeny.,To tredjedele af puslespillet er løst,Zwei Drittel des Rätsels sind gelöst,,Du trionoj de la puzlo estas solvita.,Dos tercios del acertijo se han resuelto,,Kaksi kolmannesta pulmasta on ratkaistu,Deux tiers du puzzle ont été résolus,A rejtvény kétharmada megoldásra került,Due terzi del puzzle sono stati risolto,パズルの 三分の二 が解かれた,수수께끼의 3분의 2가 풀렸다,Tweederde van de puzzel is opgelost,To tredjedeler av puslespillet er løst.,Dwie trzecie zagadki rozwiązane,Dois terços do quebra-cabeça foi resolvido,,Două treimi din puzzle sunt rezolvate,Две трети головоломки разгаданы,Две трећине загонетке су решене,Två tredjedelar av pusslet är löst.,Bulmacanın üçte ikisi çözüldü You hear a platform moving in the distance,TXT_ACS_MAP45_1_YOUHE,,,,Slyšíš v dálce pohybující se plošinu.,Du hører en platform bevæge sig i det fjerne,"Du hörst, wie sich in der Ferne eine Platform bewegt",,Vi aŭdas plataĵon movantan malproksime.,Escuchas una plataforma moverse a la distancia,,Kuulet lavan liikkuvan etäällä,Vous entendez une plateforme se déplacer au loin,Egy emelvény mozgását hallod a távolban,Senti una piattaforma muoversi in lontananza,昇降機の音が遠くで聞こえる,멀리서 보행판이 움직이는 소리가 들려왔다,Je hoort een platform bewegen in de verte,Du hører en plattform bevege seg i det fjerne,Słyszysz odgłos poruszającej się w oddali platformy,Você ouve de longe uma plataforma se movendo,,Auzi o platformă mișcându-se în depărtare,"Неподалёку раздаётся звук -движущейся деревянной площадки",Чујете како се платформа помера у даљини,Uzakta bir platformun hareket ettiğini duyuyorsunuz. +движущейся деревянной площадки",Чујете како се платформа помера у даљини,Du hör en plattform som rör sig på avstånd.,Uzakta bir platformun hareket ettiğini duyuyorsunuz. It is done...,TXT_ACS_MAP46_0_ITISD,,,,Je to dokonáno...,Det er gjort...,Es ist getan...,,Ĝi estas farita...,Está terminado...,,Se on tehty...,C'est terminé...,Készen van...,È fatto...,これで完了だ...,이제 끝났다...,Het is gebeurd,Det er gjort...,"Zrobione... -",Pronto...,,E gata...,Готово...,Готово је...,Bitti... -You have not completed the puzzle,TXT_ACS_MAP46_1_YOUHA,,,,Nesplnil@[ao_cs] jsi rébus.,Du har ikke løst puslespillet,Du hast das Rätsel noch nicht gelöst,,Vi ne kompletis la puzlon.,No has completado el acertijo,,Et ole ratkaissut pulmaa,Vous n'avez pas résolu le puzzle.,Nem fejtetted meg a rejtvényt.,Non hai completato il puzzle,パズルはまだ完成していない,모든 수수께끼를 풀지 못했다,Je hebt de puzzel nog niet voltooid...,Du har ikke fullført puslespillet,Nie ukończyłeś zagadki,Você não terminou o quebra-cabeça,,Nu ai rezolvat puzzle-ul,Головоломка не разгадана,Ниси решио загонетку,Bulmacayı tamamlamadınız -I'm warning you...,TXT_ACS_MAP46_2_IMWAR,,,,Varuju tě...,Jeg advarer dig...,Ich warne dich...,,Mi avertas vin...,Te lo advierto...,,Varoitan sinua...,Je vous avertis...,Figyelmeztetlek...,Ti avverto...,お前に警告しよう...,나는 경고했다...,Ik waarschuw je...,Jeg advarer deg...,Ostrzegam cię...,Estou te avisando...,,Te avertizez...,Я тебя предупреждаю...,Упозоравам те...,Seni uyarıyorum. -"Stubborn, aren't you?",TXT_ACS_MAP46_3_STUBB,,,,"Ty jsi ale tvrdohlav@[adj_cs], ne?","Du er stædig, ikke sandt?","Du bist aber stur, was?",,"Vi estas obstina, ĉu ne?","Eres obstinado, ¿verdad?",,Oletpa itsepäinen,"Obstiné, n'est-ce pas?","Makacs vagy, ugye?",Sei proprio così testardo?,頑固だと、自らも思わないか?,정말 끈질기군.,"Koppig, nietwaar?","Du er sta, ikke sant?","Jesteś uparty, prawda?","Você é teimos@[ao_ptb], não é mesmo?",,"Încăpățânat, nu-i așa?",Не слишком ли ты упрямый?,"Тврдоглав си, зар не?","İnatçısın, değil mi?" -"And stupid, too",TXT_ACS_MAP46_4_ANDST,,,,A taky hloup@[adj_cs].,Og også dum,Und auch noch dumm,,Kaj ankaŭ stulta.,"Y estúpido, también",,Ja vieläpä tyhmä,"Et stupide, aussi.",És oktondi is.,"E stupido, pure",そして、あまりにも愚か者だ,어리석기도 하고.,En ook dom,Og dum også.,Głupi też,E estúpid@[ao_ptb] também,,"Și prost, pe deasupra",И не слишком-то разумный!,А још си и глуп,Ve de aptal. -One fourth of this puzzle is complete,TXT_ACS_MAP46_8_ONEFO,,,,Jedna čtvrtina rébusu je vyřešena.,En fjerdedel af dette puslespil er fuldført,Ein Viertel des Rätsels ist gelöst,,Unu kvarono de la puzlo estas kompleta.,Un cuarto del acertijo se ha resuelto,,Neljännes pulmasta on ratkaistu,Un quart du puzzle à été résolu,Egy negyede e rejtvénynek megvan.,Un quarto del puzzle è completo,パズルの 四分の一 が解かれた,수수께끼의 4분의 1만 풀렸다,Een vierde van deze puzzel is compleet,En fjerdedel av dette puslespillet er ferdig,Jedna czwarta tej zagadki ukończona,Um quarto deste quebra-cabeça está completo,,O pătrime din puzzle e rezolvată,Одна четвёртая этой головоломки разгадана,Четвртина загонетке је решена,Bu bulmacanın dörtte biri tamamlandı -Bad choice...,TXT_ACS_MAP46_9_BADCH,,,,Špatná volba.,Dårligt valg...,Falsche Wahl...,,Malbona elekto...,Mala decisión...,,Huono valinta...,Mauvaise décision...,Rossz választás...,Scelta sbagliata...,拙い選択だ...,서투른 선택이다...,Slechte keuze....,Dårlig valg...,Zły wybór...,Péssima escolha...,,Proastă alegere...,Плохой выбор...,Лош избор...,Kötü seçim... -The symbols are not aligned,TXT_ACS_MAP47_2_THESY,,,,Symboly nejsou zarovnány.,Symbolerne er ikke på linje med hinanden.,Die Symbole sind nicht ausgerichtet,,La simboloj ne estas liniiga.,Los símbolos no están alineados,,Symbolit eivät ole järjestyksessä,Les symboles ne sont pas alignés.,A jelek nincsenek vonalban,I simboli non sono allineati,シンボルが揃っていない,상징이 정렬되지 않았다,De symbolen zijn niet uitgelijnd,Symbolene er ikke på linje.,Symbole nie są wyrównane,Os símbolos não estão alinhados,,Simbolurile nu sunt aliniate,Символы не совпадают,Симболи нису поравнати,Semboller aynı hizada değil -The door won't open from this side,TXT_ACS_MAP48_2_THEDO,,,,Dveře se z této strany neotevřou.,Døren kan ikke åbnes fra denne side.,Die Tür kann sich von dieser Seite nicht öffnen,,La pordo ne malfermiĝas.,La puerta no abrirá por este lado,,Ovi ei aukea tältä puolelta,La porte ne s'ouvre pas de ce côté.,Az ajtó nem fog kinyílni innen.,La porta non si apre da questo lato,扉はこちら側から開けられない,이 문은 이 방향으로는 열리지 않는다,De deur gaat niet open van deze kant,Døren kan ikke åpnes fra denne siden,Drzwi nie otworzą się z tej strony,A porta não se abrirá deste lado,,Ușile nu se vor deschide de pe partea asta,С этой стороны дверь не открыть,Врата неће да се отворе са стране,Kapı bu taraftan açılmıyor. -The door is barred from the outside,TXT_ACS_MAP50_1_THEDO,,,,Dveře jsou zatarasené zvenku.,Døren er spærret udefra,Die Tür ist von außen verriegelt,,La pordo estas barita ekstere.,La puerta está atrancada por fuera,,Ovi on teljetty ulkopuolelta,Cette porte est bloquée de l'extérieur.,Az ajtó kívülről van eltorlaszolva.,La porta è sbarrata da fuori,この扉は外側から塞がれている,이 문은 바깥에 빗장이 걸려있다,De deur is van buitenaf uitgesloten,Døren er sperret fra utsiden,Drzwi są zabarykadowane od zewnątrz,A porta está barrada por fora,,Ușa e încuiată pe dinafară,Дверь заблокирована снаружи,Врата су блокирана споља,Kapı dışarıdan parmaklıklı. -Sacrilege !,TXT_ACS_MAP51_5_SACRI,,,,Svatokrádež!,Helligbrøde!,Gotteslästerung!,,Sakrilegio !,¡Sacrilegio!,,Pyhäinhäväistys !,Sacrilège!,Szentségtörés!,Sacrilegio !,罰当たりが!,신성모독이다!,Heiligschennis!,Helligbrøde!,Świętokradztwo !,Sacrilégio!,,Sacrilegiu!,Святотатство!,Светогрђе !,Kutsala saygısızlık! -You have defiled Eric's tomb !!,TXT_ACS_MAP51_6_YOUHA,,,,Znesvětil@[ao_cs] jsi Erikovu hrobku!!,Du har besudlet Erics grav!!,Du hast Erics Gruft entehrt!!,,Vi malpurigis la tombon de Eric !!,¡Has profanado la tumba de Erick!,,Olet turmellut Ericin haudan !!,Vous avez vandalisé la tombe d'Eric!,Megszentségtelenítetted Eric sírját!,Hai profanato la tomba di Eric !!,貴様はエリックの墓を荒らしたな!!,네 놈은 성 에릭의 무덤을 더렵혔다!!,Je hebt Eric's graf bevlekt!!,Du har vanhelliget Erics grav !!!,Zhańbiłeś grób Erica !!,Você violou a tumba de Eric!,,Ai profanat mormântul lui Eric!!,Ты осквернил@[ao_rus] могилу Эрика!!,Оскрнавио си Ерикову гробницу !!,Eric'in mezarını kirlettin! -And now you die !!!,TXT_ACS_MAP51_7_ANDNO,,,,Teď zemřeš!!!,Og nu skal du dø!!!!,Und nun stirbst du!,,Kaj nun vi mortas !!!,¡Y ahora morirás!,,Ja nyt sinä kuolet !!!,"Pour cela, vous allez mourir!",És most meghalsz!,E ora muori !!!,万死に値する!!!,그 댓가로 목숨을 바쳐라!!!,En nu ga je dood!!!!!,Og nå dør du!!!,I teraz zginiesz !!!,E agora você morrerá!!!,,"Iar acum, mori!!",И умрёшь за это страшной смертью!!!,И због тога ћеш умрети !!!,Ve şimdi öleceksin!!! -One third of the puzzle is solved,TXT_ACS_MAP51_8_ONETH,,,,Jedna třetina rébusu je vyřešena.,En tredjedel af gåden er løst,Ein Drittel des Rätsels ist gelöst,,Unu triono de la puzlo estas solvita.,Un tercio del acertijo se ha resuelto,,Kolmannes pulmasta on ratkaistu,Un tiers du puzzle à été résolu,A rejtvény egyharmada megoldásra került.,Un terzo del puzzle è stato risolto,パズルの 三分の一 が解かれた,수수께끼의 3분의 1이 풀렸다,Een derde van de puzzel is opgelost.,En tredjedel av gåten er løst,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle e rezolvată,Одна треть головоломки разгадана,Трећина загонетке је решена,Bulmacanın üçte biri çözüldü. -Two thirds of the puzzle is solved,TXT_ACS_MAP51_9_TWOTH,,,,Dvě třetiny rébusu jsou vyřešeny.,To tredjedele af gåden er løst,Zwei Drittel des Rätsels sind gelöst,,Du trionoj de la puzlo estas solvita.,Dos tercios del acertijo se han resuelto,,Kaksi kolmannesta pulmasta on ratkaistu,deux tiers du puzzle ont été résolus,A rejtvény kétharmada megoldásra került.,Due terzi del puzzle è stato risolto,パズルの 三分の二 が解かれた,수수께끼의 3분의 2가 풀렸다,Tweederde van de puzzel is opgelost,To tredjedeler av puslespillet er løst.,Dwie trzecie zagadki rozwiązane,Dois terços do quebra-cabeça foi resolvido,,Două treimi din puzzle sunt rezolvate,Две трети головоломки разгаданы,Две трећине загонетке су решене,Bulmacanın üçte ikisi çözüldü -The crypt is open,TXT_ACS_MAP51_10_THECR,,,,Krypta je otevřena.,Krypten er åben,Die Gruft ist offen,,La kripto estas malfermita.,La cripta ahora está abierta,,Krypta on auki,La crypte est ouverte,A kripta kinyílt.,La cripta è aperta,地下聖堂 が開いた,지하 묘실의 입구가 열렸다.,De crypte is open,Krypten er åpen,Krypta jest otwarta,A cripta está aberta,,Cripta e deschisă,Склеп открыт,Гробница је отворена,Mahzen açık -Beware the spider's tomb,TXT_ACS_MAP51_11_BEWAR,,,,Vyvaruj se pavoučí hrobky.,Pas på edderkoppens grav,Hüte dich vor dem Grab der Spinne,,Singardu en la tombo de la araneo.,Cuidado con la tumba de la araña,,Varo hämähäkin hautaa,Attention à la tombe de l'araignée.,Óvakodj a pók sírjától!,Attento alla tomba del ragno,スパイダーの墓,거미의 무덤을 조심하라,Pas op voor het graf van de spin,Se opp for edderkoppens grav,Strzeż się grobowca pająków,Cuidado com a tumba da aranha,,Păzește-te de mormântul păianjenului,Опасайся гробницы паука,Чувај се паукове гробнице,Örümceğin mezarına dikkat edin +",Pronto...,,E gata...,Готово...,Готово је...,Det är gjort...,Bitti... +You have not completed the puzzle,TXT_ACS_MAP46_1_YOUHA,,,,Nesplnil@[ao_cs] jsi rébus.,Du har ikke løst puslespillet,Du hast das Rätsel noch nicht gelöst,,Vi ne kompletis la puzlon.,No has completado el acertijo,,Et ole ratkaissut pulmaa,Vous n'avez pas résolu le puzzle.,Nem fejtetted meg a rejtvényt.,Non hai completato il puzzle,パズルはまだ完成していない,모든 수수께끼를 풀지 못했다,Je hebt de puzzel nog niet voltooid...,Du har ikke fullført puslespillet,Nie ukończyłeś zagadki,Você não terminou o quebra-cabeça,,Nu ai rezolvat puzzle-ul,Головоломка не разгадана,Ниси решио загонетку,Du har inte fullbordat pusslet.,Bulmacayı tamamlamadınız +I'm warning you...,TXT_ACS_MAP46_2_IMWAR,,,,Varuju tě...,Jeg advarer dig...,Ich warne dich...,,Mi avertas vin...,Te lo advierto...,,Varoitan sinua...,Je vous avertis...,Figyelmeztetlek...,Ti avverto...,お前に警告しよう...,나는 경고했다...,Ik waarschuw je...,Jeg advarer deg...,Ostrzegam cię...,Estou te avisando...,,Te avertizez...,Я тебя предупреждаю...,Упозоравам те...,Jag varnar dig...,Seni uyarıyorum. +"Stubborn, aren't you?",TXT_ACS_MAP46_3_STUBB,,,,"Ty jsi ale tvrdohlav@[adj_cs], ne?","Du er stædig, ikke sandt?","Du bist aber stur, was?",,"Vi estas obstina, ĉu ne?","Eres obstinado, ¿verdad?",,Oletpa itsepäinen,"Obstiné, n'est-ce pas?","Makacs vagy, ugye?",Sei proprio così testardo?,頑固だと、自らも思わないか?,정말 끈질기군.,"Koppig, nietwaar?","Du er sta, ikke sant?","Jesteś uparty, prawda?","Você é teimos@[ao_ptb], não é mesmo?",,"Încăpățânat, nu-i așa?",Не слишком ли ты упрямый?,"Тврдоглав си, зар не?","Du är envis, eller hur?","İnatçısın, değil mi?" +"And stupid, too",TXT_ACS_MAP46_4_ANDST,,,,A taky hloup@[adj_cs].,Og også dum,Und auch noch dumm,,Kaj ankaŭ stulta.,"Y estúpido, también",,Ja vieläpä tyhmä,"Et stupide, aussi.",És oktondi is.,"E stupido, pure",そして、あまりにも愚か者だ,어리석기도 하고.,En ook dom,Og dum også.,Głupi też,E estúpid@[ao_ptb] também,,"Și prost, pe deasupra",И не слишком-то разумный!,А још си и глуп,Och dum också.,Ve de aptal. +One fourth of this puzzle is complete,TXT_ACS_MAP46_8_ONEFO,,,,Jedna čtvrtina rébusu je vyřešena.,En fjerdedel af dette puslespil er fuldført,Ein Viertel des Rätsels ist gelöst,,Unu kvarono de la puzlo estas kompleta.,Un cuarto del acertijo se ha resuelto,,Neljännes pulmasta on ratkaistu,Un quart du puzzle à été résolu,Egy negyede e rejtvénynek megvan.,Un quarto del puzzle è completo,パズルの 四分の一 が解かれた,수수께끼의 4분의 1만 풀렸다,Een vierde van deze puzzel is compleet,En fjerdedel av dette puslespillet er ferdig,Jedna czwarta tej zagadki ukończona,Um quarto deste quebra-cabeça está completo,,O pătrime din puzzle e rezolvată,Одна четвёртая этой головоломки разгадана,Четвртина загонетке је решена,En fjärdedel av pusslet är klart.,Bu bulmacanın dörtte biri tamamlandı +Bad choice...,TXT_ACS_MAP46_9_BADCH,,,,Špatná volba.,Dårligt valg...,Falsche Wahl...,,Malbona elekto...,Mala decisión...,,Huono valinta...,Mauvaise décision...,Rossz választás...,Scelta sbagliata...,拙い選択だ...,서투른 선택이다...,Slechte keuze....,Dårlig valg...,Zły wybór...,Péssima escolha...,,Proastă alegere...,Плохой выбор...,Лош избор...,Dåligt val...,Kötü seçim... +The symbols are not aligned,TXT_ACS_MAP47_2_THESY,,,,Symboly nejsou zarovnány.,Symbolerne er ikke på linje med hinanden.,Die Symbole sind nicht ausgerichtet,,La simboloj ne estas liniiga.,Los símbolos no están alineados,,Symbolit eivät ole järjestyksessä,Les symboles ne sont pas alignés.,A jelek nincsenek vonalban,I simboli non sono allineati,シンボルが揃っていない,상징이 정렬되지 않았다,De symbolen zijn niet uitgelijnd,Symbolene er ikke på linje.,Symbole nie są wyrównane,Os símbolos não estão alinhados,,Simbolurile nu sunt aliniate,Символы не совпадают,Симболи нису поравнати,Symbolerna är inte i linje med varandra.,Semboller aynı hizada değil +The door won't open from this side,TXT_ACS_MAP48_2_THEDO,,,,Dveře se z této strany neotevřou.,Døren kan ikke åbnes fra denne side.,Die Tür kann sich von dieser Seite nicht öffnen,,La pordo ne malfermiĝas.,La puerta no abrirá por este lado,,Ovi ei aukea tältä puolelta,La porte ne s'ouvre pas de ce côté.,Az ajtó nem fog kinyílni innen.,La porta non si apre da questo lato,扉はこちら側から開けられない,이 문은 이 방향으로는 열리지 않는다,De deur gaat niet open van deze kant,Døren kan ikke åpnes fra denne siden,Drzwi nie otworzą się z tej strony,A porta não se abrirá deste lado,,Ușile nu se vor deschide de pe partea asta,С этой стороны дверь не открыть,Врата неће да се отворе са стране,Dörren öppnas inte från den här sidan.,Kapı bu taraftan açılmıyor. +The door is barred from the outside,TXT_ACS_MAP50_1_THEDO,,,,Dveře jsou zatarasené zvenku.,Døren er spærret udefra,Die Tür ist von außen verriegelt,,La pordo estas barita ekstere.,La puerta está atrancada por fuera,,Ovi on teljetty ulkopuolelta,Cette porte est bloquée de l'extérieur.,Az ajtó kívülről van eltorlaszolva.,La porta è sbarrata da fuori,この扉は外側から塞がれている,이 문은 바깥에 빗장이 걸려있다,De deur is van buitenaf uitgesloten,Døren er sperret fra utsiden,Drzwi są zabarykadowane od zewnątrz,A porta está barrada por fora,,Ușa e încuiată pe dinafară,Дверь заблокирована снаружи,Врата су блокирана споља,Dörren är spärrad från utsidan,Kapı dışarıdan parmaklıklı. +Sacrilege !,TXT_ACS_MAP51_5_SACRI,,,,Svatokrádež!,Helligbrøde!,Gotteslästerung!,,Sakrilegio !,¡Sacrilegio!,,Pyhäinhäväistys !,Sacrilège!,Szentségtörés!,Sacrilegio !,罰当たりが!,신성모독이다!,Heiligschennis!,Helligbrøde!,Świętokradztwo !,Sacrilégio!,,Sacrilegiu!,Святотатство!,Светогрђе !,Helgerån!,Kutsala saygısızlık! +You have defiled Eric's tomb !!,TXT_ACS_MAP51_6_YOUHA,,,,Znesvětil@[ao_cs] jsi Erikovu hrobku!!,Du har besudlet Erics grav!!,Du hast Erics Gruft entehrt!!,,Vi malpurigis la tombon de Eric !!,¡Has profanado la tumba de Erick!,,Olet turmellut Ericin haudan !!,Vous avez vandalisé la tombe d'Eric!,Megszentségtelenítetted Eric sírját!,Hai profanato la tomba di Eric !!,貴様はエリックの墓を荒らしたな!!,네 놈은 성 에릭의 무덤을 더렵혔다!!,Je hebt Eric's graf bevlekt!!,Du har vanhelliget Erics grav !!!,Zhańbiłeś grób Erica !!,Você violou a tumba de Eric!,,Ai profanat mormântul lui Eric!!,Ты осквернил@[ao_rus] могилу Эрика!!,Оскрнавио си Ерикову гробницу !!,Du har besudlat Erics grav!!,Eric'in mezarını kirlettin! +And now you die !!!,TXT_ACS_MAP51_7_ANDNO,,,,Teď zemřeš!!!,Og nu skal du dø!!!!,Und nun stirbst du!,,Kaj nun vi mortas !!!,¡Y ahora morirás!,,Ja nyt sinä kuolet !!!,"Pour cela, vous allez mourir!",És most meghalsz!,E ora muori !!!,万死に値する!!!,그 댓가로 목숨을 바쳐라!!!,En nu ga je dood!!!!!,Og nå dør du!!!,I teraz zginiesz !!!,E agora você morrerá!!!,,"Iar acum, mori!!",И умрёшь за это страшной смертью!!!,И због тога ћеш умрети !!!,Och nu dör du !!!,Ve şimdi öleceksin!!! +One third of the puzzle is solved,TXT_ACS_MAP51_8_ONETH,,,,Jedna třetina rébusu je vyřešena.,En tredjedel af gåden er løst,Ein Drittel des Rätsels ist gelöst,,Unu triono de la puzlo estas solvita.,Un tercio del acertijo se ha resuelto,,Kolmannes pulmasta on ratkaistu,Un tiers du puzzle à été résolu,A rejtvény egyharmada megoldásra került.,Un terzo del puzzle è stato risolto,パズルの 三分の一 が解かれた,수수께끼의 3분의 1이 풀렸다,Een derde van de puzzel is opgelost.,En tredjedel av gåten er løst,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle e rezolvată,Одна треть головоломки разгадана,Трећина загонетке је решена,En tredjedel av pusslet är löst,Bulmacanın üçte biri çözüldü. +Two thirds of the puzzle is solved,TXT_ACS_MAP51_9_TWOTH,,,,Dvě třetiny rébusu jsou vyřešeny.,To tredjedele af gåden er løst,Zwei Drittel des Rätsels sind gelöst,,Du trionoj de la puzlo estas solvita.,Dos tercios del acertijo se han resuelto,,Kaksi kolmannesta pulmasta on ratkaistu,deux tiers du puzzle ont été résolus,A rejtvény kétharmada megoldásra került.,Due terzi del puzzle è stato risolto,パズルの 三分の二 が解かれた,수수께끼의 3분의 2가 풀렸다,Tweederde van de puzzel is opgelost,To tredjedeler av puslespillet er løst.,Dwie trzecie zagadki rozwiązane,Dois terços do quebra-cabeça foi resolvido,,Două treimi din puzzle sunt rezolvate,Две трети головоломки разгаданы,Две трећине загонетке су решене,Två tredjedelar av pusslet är löst.,Bulmacanın üçte ikisi çözüldü +The crypt is open,TXT_ACS_MAP51_10_THECR,,,,Krypta je otevřena.,Krypten er åben,Die Gruft ist offen,,La kripto estas malfermita.,La cripta ahora está abierta,,Krypta on auki,La crypte est ouverte,A kripta kinyílt.,La cripta è aperta,地下聖堂 が開いた,지하 묘실의 입구가 열렸다.,De crypte is open,Krypten er åpen,Krypta jest otwarta,A cripta está aberta,,Cripta e deschisă,Склеп открыт,Гробница је отворена,Kryptan är öppen.,Mahzen açık +Beware the spider's tomb,TXT_ACS_MAP51_11_BEWAR,,,,Vyvaruj se pavoučí hrobky.,Pas på edderkoppens grav,Hüte dich vor dem Grab der Spinne,,Singardu en la tombo de la araneo.,Cuidado con la tumba de la araña,,Varo hämähäkin hautaa,Attention à la tombe de l'araignée.,Óvakodj a pók sírjától!,Attento alla tomba del ragno,スパイダーの墓,거미의 무덤을 조심하라,Pas op voor het graf van de spin,Se opp for edderkoppens grav,Strzeż się grobowca pająków,Cuidado com a tumba da aranha,,Păzește-te de mormântul păianjenului,Опасайся гробницы паука,Чувај се паукове гробнице,Akta dig för spindelns grav,Örümceğin mezarına dikkat edin You hear a platform rise outside,TXT_ACS_MAP51_13_YOUHE,,,,Slyšíš zvenku zvedající se platformu.,Du hører en platform rejse sig udenfor,"Du hörst, wie sich draußen eine Plattform erhebt",,Vi aŭdas plataĵon leviĝantan ekstere.,Escuchas una plataforma erguirse afuera,,Kuulet lavan kohoavan ulkopuolella,Vous entendez une platforme s'élever dehors,Egy emelvényt hallasz emelkedni odakinn,Senti una piattaforma alzarsi in lontananza,外で昇降機の音が聞こえる,밖에서 보행판이 올라오는 소리가 들려왔다,Je hoort een platform buiten opstijgen,Du hører en plattform stige utenfor,Słyszysz odgłos unoszącej się na zewnątrz platformy,Você ouve uma plataforma subir lá fora,,Auzi o platformă ridicându-se afară,"Снаружи слышен звук -поднимающегося камня",Чујете како се платформа диже споља,Dışarıda bir platformun yükseldiğini duyarsınız -Do you feel lucky?,TXT_ACS_MAP51_14_DOYOU,,,,"Zdá se ti, že máš štěstí?",Føler du dig heldig?,Denkst du das heute dein Glückstag ist?,,Ĉu vi sentas vin bonŝanca?,¿Te sientes afortunado?,,Tunnetko olosi onnekkaaksi?,Vous pensez être chanceux?,Szerencsésnek érzed magad?,Ti senti fortunato?,運が良かったと思うか?,그대는 운수가 좋은가?,Heb je geluk?,Føler du deg heldig?,Masz szczęście?,Está se sentindo com sorte?,,Te simți norocos?,Чувствуешь ли ты себя везучим?,Да ли се осећаш срећним?,Kendinizi şanslı mı hissediyorsunuz? -You guessed wrong!,TXT_ACS_MAP51_15_YOUGU,,,,To máš smůlu!,Du gættede forkert!,Du hast falsch geraten!,,Vi divenis malĝuste!,¡Adivinaste incorrectamente!,,Arvasi väärin!,Et bien non!,Hát rosszul érzed!,Non hai indovinato!,それは違うな!,잘못된 판단이다!,Je hebt het verkeerd geraden!,Du gjettet feil!,Źle zgadłeś!,Adivinhou errado!,,N-ai ghicit!,Неправильное предположение!,Погрешно си погодио!,Yanlış tahmin ettin! -Good guess,TXT_ACS_MAP51_16_GOODG,,,,Dobré zdání.,Godt gættet.,Gut geraten,,Bona diveno.,Buena elección,,Hyvä arvaus,Vous avez deviné!,Jól sejtetted,Hai indovinato,良い推測だ,옳은 판단이다,Goede gok,Godt gjettet,Dobrze zgadłeś,Certa resposta,,Ai ghicit,Правильное предположение,Добар погодак,İyi tahmin -Can you do all the scripting for my level?,TXT_ACS_MAP51_17_CANYO,,,,Můžeš všechno skriptování udělat za mě?,Kan du lave alt scripting til mit niveau?,Kannst du die Skripte für all meine Level schreiben?,,Ĉu vi povas fari ĉiom da la skriptoj por mia nivelo?,¿Podrías hacer todo el script para mi nivel?,,Voitko tehdä kaikki tasoni skriptaukset?,Vous pouvez faire tout le script de mon niveau?,Meg tudnád csinálni az egészt scriptelést a pályámhoz?,Puoi fare tutto lo scripting per il mio livello?,この階層を全て書き換える事は可能かな?,어쩔 수 없이 살아간다. 태어났기 때문에...,Kun je al het scripten doen voor mijn niveau?,Kan du gjøre alt skriptet for mitt nivå?,Czy możesz zrobić cały skrypt do mojego poziomu?,Poderia fazer todo o scripting da minha fase?,,Te poți ocupa de scripting pentru nivelul meu?,"Может, напишешь за меня все скрипты для моего уровня?",Можеш ли да напишеш све скриптове за мој ниво?,Benim seviyem için tüm senaryoyu yazabilir misin? -Don't touch my gloppy,TXT_ACS_MAP51_18_DONTT,,,,Nesahej mi na slimáka!,Rør ikke ved min gloppy,Berühr mein Ding nicht!,,Ne tuŝas mian gloppy-on.,No toques mi gloppy,,Älä koske mönjääni,Ne touche pas mon gloppy,Ne nyúlj a bizémhez,Non toccare la mia caramella,汚らしい手で触れるな,"에틴을 쳐죽인 것까지 신경 쓰다간, 걸을 수도 없을걸.",Raak mijn gloppy niet aan,Ikke rør min gloppy,Nie ruszaj moich słodyczy,Não toca no meu docinho!,,Nu-mi atinge bomboana,Не трогай мою вкусняшку,Не дирај мој слаткиш,Benim cıvıklığıma dokunma. -Vorpal ?!?!?!,TXT_ACS_MAP51_19_VORPA,,,,Šaršoun?!?!?!,,Tödlich ?!?!?!,,Vorpal ?!?!?!,¡¿¡¿¡¿ Vorpal ?!?!?!,,Tappava ?!?!?!,,,,ボーパル ?!?!?!,드래곤 슬레이어 인가?!,,,Śmiercionośny ?!?!?!,Vorpal?!?!?!,,Vorpal?!?!?!,Остренько???!!!,Вајтолни мач ?!?!?!,Vorpal?!?!?! -"Gimme some sugar, baby",TXT_ACS_MAP51_20_GIMME,,,,"Dej mi trochu cukru, zlato.","Giv mig noget sukker, baby","Gib mir etwas Zucker, Baby",,"Donu al mi iom da sukeron, knanjo.","Dame un poco de azúcar, baby","Dame algo de azúcar, bebe","Anna vähän sokeria, beibi",,"Tégy magadévá, kislány!",,砂糖が欲しいかい、ベイビー,등짝을 보자!...,"Geef me wat suiker, schatje.","Gi meg litt sukker, baby",Daj mi całusa skarbie,"Me dá um pouco de açúcar, baby",,"Dă-mi niște zahăr, dulceață","Подай-ка мне сахар, детка","Дај ми мало шећера, душо","Bana biraz şeker ver, bebeğim." -Duh-uhhh...,TXT_ACS_MAP51_21_DUHUH,,,,A jéje.,,,,Da-aaaa...,,,Daa-aaa....,,Nyílván...,,えぇーとぉー...,낙원이란 있을 수 없는거야.,,,Oooooo...,Dãããã-ããã...,,,Ага-а-а-а...,Дух-уххх...,Duh-uhhh... -Film in an hour?,TXT_ACS_MAP51_22_FILMI,,,,Film za hodinu?,Film om en time?,Film in einer Stunde?,,Kino post horo?,¿Película en una hora?,¿Una película en una hora?,Filmi tunnissa?,Un film dans une heure?,Egy film egy óra múlva?,Un film in un'ora?,数時間のフィルム?,신은 운명을 주셨죠. 만남이라는 운명을.,Film in een uur?,Film på en time?,Za godzinę film?,Quer ver um filme daqui a pouco?,,Film într-o oră?,Фильм за час?,Снимамо за сат времена?,Bir saat içinde film mi? -I don't even get my own tombstone - cf,TXT_ACS_MAP51_23_IDONT,,,,Ani nemám svůj vlastní náhrobek. -CF,Jeg får ikke engang min egen gravsten - cf,Ich bekomme noch nicht einmal meinen eigenen Grabstein - cf,,Mi ne eĉ ekhavis mian propran tombŝtonon. - cf,Ni siquiera tengo mi propia lápida - cf,,En saa edes omaa hautakiveäni - cf,J'ai même pas le droit à ma propre tombe - cf,Még saját sírt sem kaptam - cf,Non ho potuto avere la mia pietra tombale - cf,私は自分の墓標すら得られない - cf,내 묘비를 세우지도 않았네 -cf,Ik krijg niet eens mijn eigen grafsteen - cf,Jeg får ikke engang min egen gravstein - cf...,Nawet nie dostałem swojego nagrobka - cf,Eu nem ganhei a minha própria lápide - cf,,Nici măcar nu primesc propria piatră de mormânt - cf,У меня даже нет своего надгробия (К. Ф.),Ја ни немам свој надгробни споменик - cf,Kendi mezar taşımı bile alamıyorum - cf -Let no blood be spilt,TXT_ACS_MAP51_24_LETNO,,,,Nechť není prolita žádná krev.,Lad intet blod blive spildt,Lass kein Blut vergossen sein,,Lasu neniom da sango elflui.,Que no se derrame sangre,,Älköön yhtään verta vuodatettako,Qu'aucune goutte de sang ne soit tirée,Ne ontsunk ki vért,Si cerchi di non spargere sangue,血を零さないように,피 한 방울도 흘리지 말라,Laat geen bloed worden vergoten,La ikke noe blod bli spilt,Nie pozwól by krew została przelana,Que sangue nenhum seja derramado,,Fie ca sângele să nu fie vărsat,Да не прольётся кровь,Нека се не пролије крв,Kan dökülmesin -Let no hand be raised in anger,TXT_ACS_MAP51_25_LETNO,,,,Nechť není žádná ruka hněvem zvednuta.,Lad ingen hånd blive løftet i vrede,Lass keine Hand in Wut erhoben sein,,Lasu nenion manon estas levita pro kolero.,Que ninguna mano se levante con ira,,Ei yhtäkään kättä kohotettako vihassa,Qu'aucune main de se lève avec colère,Ne emeljünk kezet haragból,Si cerchi di non alzare le mani per rabbia,怒りで拳を振るわないように,분노하여 주먹을 휘두르지 말라,Laat geen hand worden opgestoken in woede...,La ingen hånd bli løftet i sinne,Nie pozwól by ręka została uniesiona w gniewie,Que mão nenhuma seja erguida por raiva,,Fie ca nicio mână să nu fie ridicată în furie,И да не поднимется рука во гневе,Нека се ни рука из беса не подигне,Öfkeyle el kaldırmayın -Who dares disturb our slumber?,TXT_ACS_MAP52_9_WHODA,,,,Kdo se opovažuje narušit náš spánek?,Hvem vover at forstyrre vores slummer?,Wer wagt es unseren Schlummer zu stören?,,Kiu aŭdacas interrompi nian dormon? ,¿Quién se atreve a perturbar nuestro sueño?,,Kuka kehtaa häiritä untamme?,Qui ose troubler notre sommeil?,Ki meri megzavarni a szunyókálásunkat?,Chi osa disturbare il nostro riposo?,誰が、我々の眠りを妨げる勇気があるかな?,감히 우리의 숙면을 방해하는가?,Wie durft onze slaap te verstoren?,Hvem våger å forstyrre vår søvn?,Kto śmie przeszkadzać nam w drzemce?,Quem ousa perturbar o nosso descanso?,,Cine cutează să-mi perturbe odihna?,Кто осмелился потревожить наш покой?,Ко се усуђује узнемиравати наш спокој?,Uykumuzu bölmeye kim cüret eder? -The way is open,TXT_ACS_MAP52_10_THEWA,,,,Cesta je otevřena.,Vejen er åben,Der Weg ist offen,,La vojo estas malfermita.,El camino está abierto,,Tie on auki,Le chemin est ouvert.,Az út kinyílt,La via è aperta,道は開いた,길이 열렸다,De weg is open,Veien er åpen,Droga jest otwarta,O caminho está aberto,,Calea e deschisă,Путь открыт,Пролаз је отворен,Yol açık -You have ,TXT_ACS_MAP53_2_YOUHA,,,,Zbývají ti ,Du har,Du hast,,Vi havas,Tienes,,Sinulla on,Vous avez,Már csak,Hai,スイッチはまだ,지금 ,Je hebt,Du har,Masz,Restam ainda,,Mai ai,Осталось,Остало је , -\x20switches left,TXT_ACS_MAP53_3_SWITC,,,,\x20spínače.,\x20kontakter tilbage,\x20Schalter übrig,,\x20ŝaltilojn ceterajn.,\x20interruptores restantes,\x20switches restantes,\x20vipua jäljellä,\x20boutons à trouver,\x20kallantyú van hátra,\x20interuttori rimanenti,残っている,개의 개폐기들이 남았다,\x20schakelaars over,\x20brytere igjen,\x20pozostałych przełączników,\x20interruptores,,\x20butoane rămase,\x20переключателей,\x20прекидача,\x20anahtarınız kaldı -You have only ,TXT_ACS_MAP53_4_YOUHA,,,,Zbývá ti jen ,Du har kun,Du hast nur,,Vi nur havas,Tienes solo,,Sinulla on vain,Vous avez seulement,Már csak,Hai solamente,スイッチは,이제 오로지 ,Je hebt alleen,Du har bare,Masz tylko,Resta somente,,Mai ai doar,Остался всего,Остао је само , +поднимающегося камня",Чујете како се платформа диже споља,Du hör en plattform stiga upp utanför.,Dışarıda bir platformun yükseldiğini duyarsınız +Do you feel lucky?,TXT_ACS_MAP51_14_DOYOU,,,,"Zdá se ti, že máš štěstí?",Føler du dig heldig?,Denkst du das heute dein Glückstag ist?,,Ĉu vi sentas vin bonŝanca?,¿Te sientes afortunado?,,Tunnetko olosi onnekkaaksi?,Vous pensez être chanceux?,Szerencsésnek érzed magad?,Ti senti fortunato?,運が良かったと思うか?,그대는 운수가 좋은가?,Heb je geluk?,Føler du deg heldig?,Masz szczęście?,Está se sentindo com sorte?,,Te simți norocos?,Чувствуешь ли ты себя везучим?,Да ли се осећаш срећним?,Känner du dig lycklig?,Kendinizi şanslı mı hissediyorsunuz? +You guessed wrong!,TXT_ACS_MAP51_15_YOUGU,,,,To máš smůlu!,Du gættede forkert!,Du hast falsch geraten!,,Vi divenis malĝuste!,¡Adivinaste incorrectamente!,,Arvasi väärin!,Et bien non!,Hát rosszul érzed!,Non hai indovinato!,それは違うな!,잘못된 판단이다!,Je hebt het verkeerd geraden!,Du gjettet feil!,Źle zgadłeś!,Adivinhou errado!,,N-ai ghicit!,Неправильное предположение!,Погрешно си погодио!,Du gissade fel!,Yanlış tahmin ettin! +Good guess,TXT_ACS_MAP51_16_GOODG,,,,Dobré zdání.,Godt gættet.,Gut geraten,,Bona diveno.,Buena elección,,Hyvä arvaus,Vous avez deviné!,Jól sejtetted,Hai indovinato,良い推測だ,옳은 판단이다,Goede gok,Godt gjettet,Dobrze zgadłeś,Certa resposta,,Ai ghicit,Правильное предположение,Добар погодак,Bra gissning,İyi tahmin +Can you do all the scripting for my level?,TXT_ACS_MAP51_17_CANYO,,,,Můžeš všechno skriptování udělat za mě?,Kan du lave alt scripting til mit niveau?,Kannst du die Skripte für all meine Level schreiben?,,Ĉu vi povas fari ĉiom da la skriptoj por mia nivelo?,¿Podrías hacer todo el script para mi nivel?,,Voitko tehdä kaikki tasoni skriptaukset?,Vous pouvez faire tout le script de mon niveau?,Meg tudnád csinálni az egészt scriptelést a pályámhoz?,Puoi fare tutto lo scripting per il mio livello?,この階層を全て書き換える事は可能かな?,어쩔 수 없이 살아간다. 태어났기 때문에...,Kun je al het scripten doen voor mijn niveau?,Kan du gjøre alt skriptet for mitt nivå?,Czy możesz zrobić cały skrypt do mojego poziomu?,Poderia fazer todo o scripting da minha fase?,,Te poți ocupa de scripting pentru nivelul meu?,"Может, напишешь за меня все скрипты для моего уровня?",Можеш ли да напишеш све скриптове за мој ниво?,Kan du göra alla skript för min nivå?,Benim seviyem için tüm senaryoyu yazabilir misin? +Don't touch my gloppy,TXT_ACS_MAP51_18_DONTT,,,,Nesahej mi na slimáka!,Rør ikke ved min gloppy,Berühr mein Ding nicht!,,Ne tuŝas mian gloppy-on.,No toques mi gloppy,,Älä koske mönjääni,Ne touche pas mon gloppy,Ne nyúlj a bizémhez,Non toccare la mia caramella,汚らしい手で触れるな,"에틴을 쳐죽인 것까지 신경 쓰다간, 걸을 수도 없을걸.",Raak mijn gloppy niet aan,Ikke rør min gloppy,Nie ruszaj moich słodyczy,Não toca no meu docinho!,,Nu-mi atinge bomboana,Не трогай мою вкусняшку,Не дирај мој слаткиш,Rör inte min glittriga,Benim cıvıklığıma dokunma. +Vorpal ?!?!?!,TXT_ACS_MAP51_19_VORPA,,,,Šaršoun?!?!?!,,Tödlich ?!?!?!,,Vorpal ?!?!?!,¡¿¡¿¡¿ Vorpal ?!?!?!,,Tappava ?!?!?!,,,,ボーパル ?!?!?!,드래곤 슬레이어 인가?!,,,Śmiercionośny ?!?!?!,Vorpal?!?!?!,,Vorpal?!?!?!,Остренько???!!!,Вајтолни мач ?!?!?!,,Vorpal?!?!?! +"Gimme some sugar, baby",TXT_ACS_MAP51_20_GIMME,,,,"Dej mi trochu cukru, zlato.","Giv mig noget sukker, baby","Gib mir etwas Zucker, Baby",,"Donu al mi iom da sukeron, knanjo.","Dame un poco de azúcar, baby","Dame algo de azúcar, bebe","Anna vähän sokeria, beibi",,"Tégy magadévá, kislány!",,砂糖が欲しいかい、ベイビー,등짝을 보자!...,"Geef me wat suiker, schatje.","Gi meg litt sukker, baby",Daj mi całusa skarbie,"Me dá um pouco de açúcar, baby",,"Dă-mi niște zahăr, dulceață","Подай-ка мне сахар, детка","Дај ми мало шећера, душо","Ge mig lite socker, baby","Bana biraz şeker ver, bebeğim." +Duh-uhhh...,TXT_ACS_MAP51_21_DUHUH,,,,A jéje.,,,,Da-aaaa...,,,Daa-aaa....,,Nyílván...,,えぇーとぉー...,낙원이란 있을 수 없는거야.,,,Oooooo...,Dãããã-ããã...,,,Ага-а-а-а...,Дух-уххх...,,Duh-uhhh... +Film in an hour?,TXT_ACS_MAP51_22_FILMI,,,,Film za hodinu?,Film om en time?,Film in einer Stunde?,,Kino post horo?,¿Película en una hora?,¿Una película en una hora?,Filmi tunnissa?,Un film dans une heure?,Egy film egy óra múlva?,Un film in un'ora?,数時間のフィルム?,신은 운명을 주셨죠. 만남이라는 운명을.,Film in een uur?,Film på en time?,Za godzinę film?,Quer ver um filme daqui a pouco?,,Film într-o oră?,Фильм за час?,Снимамо за сат времена?,Filma om en timme?,Bir saat içinde film mi? +I don't even get my own tombstone - cf,TXT_ACS_MAP51_23_IDONT,,,,Ani nemám svůj vlastní náhrobek. -CF,Jeg får ikke engang min egen gravsten - cf,Ich bekomme noch nicht einmal meinen eigenen Grabstein - cf,,Mi ne eĉ ekhavis mian propran tombŝtonon. - cf,Ni siquiera tengo mi propia lápida - cf,,En saa edes omaa hautakiveäni - cf,J'ai même pas le droit à ma propre tombe - cf,Még saját sírt sem kaptam - cf,Non ho potuto avere la mia pietra tombale - cf,私は自分の墓標すら得られない - cf,내 묘비를 세우지도 않았네 -cf,Ik krijg niet eens mijn eigen grafsteen - cf,Jeg får ikke engang min egen gravstein - cf...,Nawet nie dostałem swojego nagrobka - cf,Eu nem ganhei a minha própria lápide - cf,,Nici măcar nu primesc propria piatră de mormânt - cf,У меня даже нет своего надгробия (К. Ф.),Ја ни немам свој надгробни споменик - cf,Jag får inte ens min egen gravsten - cf,Kendi mezar taşımı bile alamıyorum - cf +Let no blood be spilt,TXT_ACS_MAP51_24_LETNO,,,,Nechť není prolita žádná krev.,Lad intet blod blive spildt,Lass kein Blut vergossen sein,,Lasu neniom da sango elflui.,Que no se derrame sangre,,Älköön yhtään verta vuodatettako,Qu'aucune goutte de sang ne soit tirée,Ne ontsunk ki vért,Si cerchi di non spargere sangue,血を零さないように,피 한 방울도 흘리지 말라,Laat geen bloed worden vergoten,La ikke noe blod bli spilt,Nie pozwól by krew została przelana,Que sangue nenhum seja derramado,,Fie ca sângele să nu fie vărsat,Да не прольётся кровь,Нека се не пролије крв,Låt inget blod spillas,Kan dökülmesin +Let no hand be raised in anger,TXT_ACS_MAP51_25_LETNO,,,,Nechť není žádná ruka hněvem zvednuta.,Lad ingen hånd blive løftet i vrede,Lass keine Hand in Wut erhoben sein,,Lasu nenion manon estas levita pro kolero.,Que ninguna mano se levante con ira,,Ei yhtäkään kättä kohotettako vihassa,Qu'aucune main de se lève avec colère,Ne emeljünk kezet haragból,Si cerchi di non alzare le mani per rabbia,怒りで拳を振るわないように,분노하여 주먹을 휘두르지 말라,Laat geen hand worden opgestoken in woede...,La ingen hånd bli løftet i sinne,Nie pozwól by ręka została uniesiona w gniewie,Que mão nenhuma seja erguida por raiva,,Fie ca nicio mână să nu fie ridicată în furie,И да не поднимется рука во гневе,Нека се ни рука из беса не подигне,Låt ingen hand höjas i ilska,Öfkeyle el kaldırmayın +Who dares disturb our slumber?,TXT_ACS_MAP52_9_WHODA,,,,Kdo se opovažuje narušit náš spánek?,Hvem vover at forstyrre vores slummer?,Wer wagt es unseren Schlummer zu stören?,,Kiu aŭdacas interrompi nian dormon? ,¿Quién se atreve a perturbar nuestro sueño?,,Kuka kehtaa häiritä untamme?,Qui ose troubler notre sommeil?,Ki meri megzavarni a szunyókálásunkat?,Chi osa disturbare il nostro riposo?,誰が、我々の眠りを妨げる勇気があるかな?,감히 우리의 숙면을 방해하는가?,Wie durft onze slaap te verstoren?,Hvem våger å forstyrre vår søvn?,Kto śmie przeszkadzać nam w drzemce?,Quem ousa perturbar o nosso descanso?,,Cine cutează să-mi perturbe odihna?,Кто осмелился потревожить наш покой?,Ко се усуђује узнемиравати наш спокој?,Vem vågar störa vår slummer?,Uykumuzu bölmeye kim cüret eder? +The way is open,TXT_ACS_MAP52_10_THEWA,,,,Cesta je otevřena.,Vejen er åben,Der Weg ist offen,,La vojo estas malfermita.,El camino está abierto,,Tie on auki,Le chemin est ouvert.,Az út kinyílt,La via è aperta,道は開いた,길이 열렸다,De weg is open,Veien er åpen,Droga jest otwarta,O caminho está aberto,,Calea e deschisă,Путь открыт,Пролаз је отворен,Vägen är öppen,Yol açık +You have ,TXT_ACS_MAP53_2_YOUHA,,,,Zbývají ti ,Du har,Du hast,,Vi havas,Tienes,,Sinulla on,Vous avez,Már csak,Hai,スイッチはまだ,지금 ,Je hebt,Du har,Masz,Restam ainda,,Mai ai,Осталось,Остало је ,Du har, +\x20switches left,TXT_ACS_MAP53_3_SWITC,,,,\x20spínače.,\x20kontakter tilbage,\x20Schalter übrig,,\x20ŝaltilojn ceterajn.,\x20interruptores restantes,\x20switches restantes,\x20vipua jäljellä,\x20boutons à trouver,\x20kallantyú van hátra,\x20interuttori rimanenti,残っている,개의 개폐기들이 남았다,\x20schakelaars over,\x20brytere igjen,\x20pozostałych przełączników,\x20interruptores,,\x20butoane rămase,\x20переключателей,\x20прекидача,\x20växlar kvar,\x20anahtarınız kaldı +You have only ,TXT_ACS_MAP53_4_YOUHA,,,,Zbývá ti jen ,Du har kun,Du hast nur,,Vi nur havas,Tienes solo,,Sinulla on vain,Vous avez seulement,Már csak,Hai solamente,スイッチは,이제 오로지 ,Je hebt alleen,Du har bare,Masz tylko,Resta somente,,Mai ai doar,Остался всего,Остао је само ,Du har bara, \x20switch left,TXT_ACS_MAP53_5_SWITC,,,,\x20spínač.,\x20kontakter tilbage,\x20Schalter übrig,,\x20ŝaltilon ceteran.,\x20interruptor restante,\x20switch restante,\x20vipu jäljellä,\x20outon à trouver,\x20kallantyú van hátra,\x20interruttore rimanente,"だけ残っている -",개의 개폐기가 남았다,\x20schakelaar over,\x20bryter igjen,\x20przełącznik,\x20interruptor,,\x20buton rămas,\x20переключатель,\x20прекидач,\x20anahtarınız kaldı -The exit is open,TXT_ACS_MAP53_6_THEEX,,,,Východ je otevřen.,Udgangen er åben,Der Ausgang ist offen,,La elirejo estas malfermita,La salida está abierta,,Ulospääsy on auki,La sortie est ouverte,A kijárat kinyílt,L'uscita è aperta,出口が開いた,출구가 열렸다,De uitgang is open,Utgangen er åpen,Wyjście jest otwarte,A saída está aberta,,Ieșirea e deschisă,Выход открыт,Излаз је отворен,Çıkış açık -The doors won't open from this side,TXT_ACS_MAP54_1_THEDO,,,,Dveře se z této strany neotevřou.,Dørene kan ikke åbnes fra denne side,Die Türen werden sich nicht von dieser Seite öffnen,,La pordo ne malfermos de ĉi tio flanko.,Las puertas no se abren desde este lado,,Ovet eivät aukea tältä puolelta,Les portes ne s'ouvrent pas de ce côté,Az ajtó nem nyílik erről az oldalról,Le porte non si aprono da questo lato,扉はこちらから開けない,이 문들은 이 방향으로는 열리지 않는다,De deuren gaan niet open van deze kant....,Dørene kan ikke åpnes fra denne siden,Drzwi nie otworzą się z tej strony,As portas não se abrirão deste lado,,Ușile nu se vor deschide de pe partea asta,С этой стороны дверь не открыть,Врата неће да се отворе са стране,Kapılar bu taraftan açılmıyor. -The doors are open...,TXT_ACS_MAP54_4_THEDO,,,,Dveře jsou otevřené...,Dørene er åbne...,Die Türen sind offen,,La pordoj estas malfermitaj...,Las puertas están abiertas...,,Ovet ovat auki...,Les portes sont ouvertes...,Az ajtók kitárultak...,Le porte sono aperte...,ドアは開いている...,문이 열렸다...,De deuren zijn open....,Dørene er åpne...,Drzwi są otwarte...,As portas estão abertas...,,Ușile sunt deschise...,Двери открыты...,Врата су отворена...,Kapılar açık. -...if you are ready,TXT_ACS_MAP54_5_IFYOU,,,,...jestli jsi připraven@[ao_cs].,...hvis du er klar,...Wenn du bereit bist,,...se vi pretas.,...si estás listo,,...jos olet valmis,...si vous êtes prêt.,...csak rád várunk.,...Se sei pronto,...準備が良いなら,... 준비 되었다면,...als je er klaar voor bent...,...hvis du er klar,...jeśli jesteś gotów,...se você estiver preparad@[ao_ptb],,...dacă ești pregătit,...осмелишься ли ты войти?,...ако си спреман,...eğer hazırsanız -A door has opened,TXT_ACS_MAP54_9_ADOOR,,,,Dveře se otevřely,En dør er blevet åbnet,Eine Tür hat sich geöffnet,,Pordo malfermiĝis,Se ha abierto una puerta,Se abrió una puerta,Ovi on auennut,Une porte est ouverte,Egy ajtó kinyílt,Una porta è stata aperta,先へ進むドアは開いた,지금 문이 열렸다...,Een deur is geopend,En dør har åpnet seg,Drzwi otworzyły się,Uma porta se abriu,,O ușă s-a deschis,Дверь открылась,Врата су се отворила,Bir kapı açıldı -on the Chantry,TXT_ACS_MAP54_10_ONTHE,,,,v Modlitebně.,på Kirkerummet,In der Kantorei,,en la Kapelo.,En la capilla,,kappelissa,dans la chapelle.,a kápolnánál,Nella Cappella,小礼拝堂 へ向かえ,... 예배당에서,op de Chantry,på Minnekapellet,w Kaplicy Wotywnej,na Capela,,la Capelă,в часовне,у Капели,Chantry'de -A bridge has been built,TXT_ACS_MAP54_11_ABRID,,,,Most byl postaven,En bro er blevet bygget,Eine Brücke wurde errichtet,,Ponto estis konstruita,Se ha construido un puente,Se construyó un puente,Silta on rakennettu,Une pont a été construit,Egy hidat támasztottak fel,È stato costruito un ponte,先へ進む橋が架かった,다리가 건설되었다...,Er is een brug gebouwd,En bro har blitt bygget,Most został utworzony,Uma ponte foi construída,,Un pod a fost construit,Мост воздвигнут,Мост се саградио,Bir köprü inşa edildi -on the Abattoir,TXT_ACS_MAP54_12_ONTHE,,,,na Jatkách.,på Slagteriet,Im Schlachthaus,,en la Buĉejo.,En el matadero,,teurastamolla,dans l'abbatoir.,a vágóhídnál,Nella Macelleria, 屠殺場 へ向かえ,... 도살장에서,op het slachthuis,på slakteriet,w Rzeźni,no Matadouro,,pe Abator,у аббатства,на Кланици,Mezbahada -A stair has been built,TXT_ACS_MAP54_13_ASTAI,,,,Schody byly postaveny,Der er bygget en trappe,Eine Treppe wurde errichtet,,Ŝtuparo estis konstruita,Se ha construido una escalera,Se construyó una escalera,Portaat on rakennettu,Un escalier a été construit,Lépcső emelkedett ki,È stata costruita una scalinata,先へ進む階段が出来た,계단이 건설되었다...,Er is een trap gebouwd,En trapp har blitt bygget,Schody zostały utworzone,Uma escada foi construída,,O scară a fost construită,Лестница воздвигнута,Степенице су се саградиле,Bir merdiven inşa edildi -on the Dark Watch,TXT_ACS_MAP54_14_ONTHE,,,,na Temné hlídce.,på den mørke vagt,auf der Dunklen Wache,,en la Gardisto Ombra.,En la guardia oscura,,pimeällä vartiolla,dans la Garde Noire.,a Sötét Őrségnél,Nella Guardia Oscura, 闇の刻計 へ向かえ,... 어둠의 감시초소에서,op de donkere wacht,på den mørke vakten,w Ciemnej Strażnicy,na Guarda Negra,,pe Gardianul Întunecat,у тёмной стражи,на Црној стражи,Karanlık Nöbet'te -One gear has been placed,TXT_ACS_MAP54_15_ONEGE,,,,Jedno kolo bylo umístěno.,Der er blevet placeret et redskab,Ein Zahnrad wurde eingesetzt,,Dentrado estis metita.,Un engranaje en su lugar,,Ratas on asetettu,Un engrenage a été placé,Egy fogaskerék a helyére került,Un ingranaggio è stato piazzato,歯車を一つ配置した,톱니바퀴 1개가 배치되었다,Een tandwiel is geplaatst,Ett tannhjul har blitt plassert,Jedna zębatka została umieszczona,Uma engrenagem foi colocada,,Un mecanism a fost introdus,Шестерня установлена,Један зупчаник је постављен,Bir dişli yerleştirildi -\x20gears have been placed,TXT_ACS_MAP54_16_GEARS,,,,\x20kola byla umístěna.,\x20gear er blevet placeret,\x20Zahnräder wurden eingesetzt,,\x20dentradoj estis metitaj.,\x20engranajes en su lugar,,\x20ratasta on asetettu,\x20engrenages ont été placés,\x20fogaskerék a helyére került,\x20ingranaggi sono stati piazzati,歯車を配置した,톱니바퀴들이 배치되었다,\x20tandwielen zijn geplaatst,\x20 tannhjul har blitt plassert,\x20zębatki zostały umieszczone,\x20engrenagens foram colocadas,,\x20mecanisme au fost introduse,\x20шестерней установлено,\x20зупчаника су постављена,\x20dişliler yerleştirildi -A barricade has opened,TXT_ACS_MAP54_17_ABARR,,,,V Kloace se otevřela barikáda.,En barrikade er blevet åbnet,Eine Barrikade wurde geöffnet,,Barikado malfermiĝis,La barricada se ha abierto,Se abrió la barricada,Tiesulku on auennut,Une barricade s'est ouverte,Egy barikád megszűnt,Una barricata è stata aperta,バリケードは開かれた,방벽이 열렸다...,Er is een barricade geopend,En barrikade har åpnet seg,Barykada została otwarta,Uma barricada se abriu,,O baricadă s-a deschis,Преграда опустилась,Барикада је отворена,Bir barikat açıldı -On the Cloaca,TXT_ACS_MAP54_18_ONTHE,,,,V Kloace se otevřela barikáda.,På Cloaca,In der Kloake,,En la Kloako.,En la Cloaca,,kloaakilla,dans le cloaque,a Kloákánál,Nella Cloaca,排泄腔 へ向かえ,... 하수구에서,Op de Cloaca,på Cloaca,W Kloace,Na Cloaca,,pe Cloaca,в клоаке,у клоаци,Kloaka Üzerine -The way back is open,TXT_ACS_MAP54_20_THEWA,,,,Cesta zpět je otevřena.,Vejen tilbage er åben,Der Weg zurück ist offen,,La vojo reen estas malfermita.,El camino está abierto,,Tie takaisin on auki,Un chemin s'est ouvert,A visszavezető út kinyílt,La via del ritorno è aperta,裏口は開いた,돌아가는 길이 열렸다,De terugweg is open,Veien tilbake er åpen,Droga powrotna jest otwarta,O caminho de volta está aberto,,Calea e deschisă,Путь назад открыт,Пролаз назад је отворен,Dönüş yolu açık -The door is barred from the inside,TXT_ACS_MAP55_9_THEDO,,,,Dveře jsou zatarasené zevnitř.,Døren er spærret indefra,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está trabada desde el otro lado,,Ovi on teljetty sisältä,La porte est bloquée de ce côté,Az ajtó bentről van bereteszelve,La porta è stata aperta da dentro,この扉は内側から塞がれている,이 문은 안에 빗장이 걸려있다,De deur is van binnenuit geblokkeerd.,Døren er sperret fra innsiden,Drzwi są zabarykadowane od wewnątrz,A porta está barrada por dentro,,Ușa e încuiată din interior,Дверь заблокирована изнутри,Врата су забрављена изнутра,Kapı içeriden kilitli. -You dare plunder the tomb,TXT_ACS_MAP56_0_YOUDA,,,,Ty se opovažuješ rabovat,Du vover at plyndre graven,Wagst du es,,Ĉu vi aŭdacas rabi de la tombo,¿Te atreves a saquear la tumba,,Kuinka kehtaat ryöstää,Vous osez piller la tombe,A hóhér sírját,Osi saccheggiare la tomba,お前はあえて 執行人達の墓を,배짱이 두둑하구나...,Je durft de graftombe te plunderen,Våger du å plyndre graven,Śmiesz plądrować grobowiec,Como ousa saquear a tumba,,Cutezi să jefuiești mormântul,Ты посмел ограбить могилу,Усуђујеш се пљачкати,Mezarı yağmalamaya cüret ediyorsun -of the executioner?,TXT_ACS_MAP56_1_OFTHE,,,,hrobku popravčího?,af bødlen?,das Grab des Henkers zu plündern?,,de la ekzekutisto?,del ejecutor?,,teloittajan haudan?,du bourreau?,próbálod fosztogatni?,dell'esecutore?,荒らすつもりか?,사형 집행자의 무덤을 도굴하다니.,van de beul?,til bøddelen?,kata?,do executor?,,călăului?,верховного палача?,желатову гробницу?,Celladın mı? -Prepare to die,TXT_ACS_MAP56_2_PREPA,,,,Připrav se zemřít.,Forbered dig på at dø,Bereite dich vor zu sterben,,Pretiĝu por morti!,¡Prepárate para morir!,,Valmistaudu kuolemaan,Préparez vous à mourir!,Készülj a halálra,Preparati a morire,死ぬ準備をしろ,죽어서 회계하라.,Bereid je voor om te sterven,Forbered deg på å dø,Przygotuj się na śmierć,Prepare-se para morrer,,Pregătește-te să mori,Готовься к смерти,Припреми се да умреш,Ölmeye hazırlanın -You have ,TXT_ACS_MAP59_1_YOUHA,,,,Zbývají ti ,Du har,Du musst,,Vi ankoraŭ havas,Aún tienes,,Sinulla on,Vous avez,Még kell találnod,Hai ancora altri,スイッチはまだ,당신은,Je hebt,Du har,Masz,Faltam mais,,Mai ai,Осталось,Остало је ,Bulmanız gereken\x20 -\x20more switches to find,TXT_ACS_MAP59_2_MORES,,,,\x20spínače k nalezení.,\x20flere kontakter at finde,\x20weitere Schalter finden,,\x20trovindajn ŝaltilojn.,\x20interruptores más que encontrar,,\x20lisää vipua löydettävänä,\x20boutons à trouver,\x20darab kallantyút,\x20interruttori da trovare,残っている,개의 개폐기들을 더 찾아야 한다,\x20meer schakelaars te vinden,\x20 brytere til å finne,\x20przełączników do znalezienia,\x20interruptores para encontrar,,\x20butoane de găsit,\x20переключателей,\x20прекидача да се нађе,\x20anahtar daha var. -You have only ,TXT_ACS_MAP59_3_YOUHA,,,,Zbývá ti jen ,Du har kun,Du musst nur,,Vi nur havas,Tienes solo,,Sinulla on vain,Vous avez seulement,Már csak,Hai solamente,スイッチは,이제 당신은 ,Je hebt alleen,Du har bare,Masz tylko,Falta somente,,Mai ai doar,Остался всего,Oстао је само ,Bulmanız gereken\x20 +",개의 개폐기가 남았다,\x20schakelaar over,\x20bryter igjen,\x20przełącznik,\x20interruptor,,\x20buton rămas,\x20переключатель,\x20прекидач,\x20växel kvar,\x20anahtarınız kaldı +The exit is open,TXT_ACS_MAP53_6_THEEX,,,,Východ je otevřen.,Udgangen er åben,Der Ausgang ist offen,,La elirejo estas malfermita,La salida está abierta,,Ulospääsy on auki,La sortie est ouverte,A kijárat kinyílt,L'uscita è aperta,出口が開いた,출구가 열렸다,De uitgang is open,Utgangen er åpen,Wyjście jest otwarte,A saída está aberta,,Ieșirea e deschisă,Выход открыт,Излаз је отворен,Utgången är öppen,Çıkış açık +The doors won't open from this side,TXT_ACS_MAP54_1_THEDO,,,,Dveře se z této strany neotevřou.,Dørene kan ikke åbnes fra denne side,Die Türen werden sich nicht von dieser Seite öffnen,,La pordo ne malfermos de ĉi tio flanko.,Las puertas no se abren desde este lado,,Ovet eivät aukea tältä puolelta,Les portes ne s'ouvrent pas de ce côté,Az ajtó nem nyílik erről az oldalról,Le porte non si aprono da questo lato,扉はこちらから開けない,이 문들은 이 방향으로는 열리지 않는다,De deuren gaan niet open van deze kant....,Dørene kan ikke åpnes fra denne siden,Drzwi nie otworzą się z tej strony,As portas não se abrirão deste lado,,Ușile nu se vor deschide de pe partea asta,С этой стороны дверь не открыть,Врата неће да се отворе са стране,Dörrarna öppnas inte från den här sidan,Kapılar bu taraftan açılmıyor. +The doors are open...,TXT_ACS_MAP54_4_THEDO,,,,Dveře jsou otevřené...,Dørene er åbne...,Die Türen sind offen,,La pordoj estas malfermitaj...,Las puertas están abiertas...,,Ovet ovat auki...,Les portes sont ouvertes...,Az ajtók kitárultak...,Le porte sono aperte...,ドアは開いている...,문이 열렸다...,De deuren zijn open....,Dørene er åpne...,Drzwi są otwarte...,As portas estão abertas...,,Ușile sunt deschise...,Двери открыты...,Врата су отворена...,Dörrarna är öppna...,Kapılar açık. +...if you are ready,TXT_ACS_MAP54_5_IFYOU,,,,...jestli jsi připraven@[ao_cs].,...hvis du er klar,...Wenn du bereit bist,,...se vi pretas.,...si estás listo,,...jos olet valmis,...si vous êtes prêt.,...csak rád várunk.,...Se sei pronto,...準備が良いなら,... 준비 되었다면,...als je er klaar voor bent...,...hvis du er klar,...jeśli jesteś gotów,...se você estiver preparad@[ao_ptb],,...dacă ești pregătit,...осмелишься ли ты войти?,...ако си спреман,...om du är redo,...eğer hazırsanız +A door has opened,TXT_ACS_MAP54_9_ADOOR,,,,Dveře se otevřely,En dør er blevet åbnet,Eine Tür hat sich geöffnet,,Pordo malfermiĝis,Se ha abierto una puerta,Se abrió una puerta,Ovi on auennut,Une porte est ouverte,Egy ajtó kinyílt,Una porta è stata aperta,先へ進むドアは開いた,지금 문이 열렸다...,Een deur is geopend,En dør har åpnet seg,Drzwi otworzyły się,Uma porta se abriu,,O ușă s-a deschis,Дверь открылась,Врата су се отворила,En dörr har öppnats,Bir kapı açıldı +on the Chantry,TXT_ACS_MAP54_10_ONTHE,,,,v Modlitebně.,på Kirkerummet,In der Kantorei,,en la Kapelo.,En la capilla,,kappelissa,dans la chapelle.,a kápolnánál,Nella Cappella,小礼拝堂 へ向かえ,... 예배당에서,op de Chantry,på Minnekapellet,w Kaplicy Wotywnej,na Capela,,la Capelă,в часовне,у Капели,på Chantry,Chantry'de +A bridge has been built,TXT_ACS_MAP54_11_ABRID,,,,Most byl postaven,En bro er blevet bygget,Eine Brücke wurde errichtet,,Ponto estis konstruita,Se ha construido un puente,Se construyó un puente,Silta on rakennettu,Une pont a été construit,Egy hidat támasztottak fel,È stato costruito un ponte,先へ進む橋が架かった,다리가 건설되었다...,Er is een brug gebouwd,En bro har blitt bygget,Most został utworzony,Uma ponte foi construída,,Un pod a fost construit,Мост воздвигнут,Мост се саградио,En bro har byggts,Bir köprü inşa edildi +on the Abattoir,TXT_ACS_MAP54_12_ONTHE,,,,na Jatkách.,på Slagteriet,Im Schlachthaus,,en la Buĉejo.,En el matadero,,teurastamolla,dans l'abbatoir.,a vágóhídnál,Nella Macelleria, 屠殺場 へ向かえ,... 도살장에서,op het slachthuis,på slakteriet,w Rzeźni,no Matadouro,,pe Abator,у аббатства,на Кланици,på slakthuset,Mezbahada +A stair has been built,TXT_ACS_MAP54_13_ASTAI,,,,Schody byly postaveny,Der er bygget en trappe,Eine Treppe wurde errichtet,,Ŝtuparo estis konstruita,Se ha construido una escalera,Se construyó una escalera,Portaat on rakennettu,Un escalier a été construit,Lépcső emelkedett ki,È stata costruita una scalinata,先へ進む階段が出来た,계단이 건설되었다...,Er is een trap gebouwd,En trapp har blitt bygget,Schody zostały utworzone,Uma escada foi construída,,O scară a fost construită,Лестница воздвигнута,Степенице су се саградиле,En trappa har byggts,Bir merdiven inşa edildi +on the Dark Watch,TXT_ACS_MAP54_14_ONTHE,,,,na Temné hlídce.,på den mørke vagt,auf der Dunklen Wache,,en la Gardisto Ombra.,En la guardia oscura,,pimeällä vartiolla,dans la Garde Noire.,a Sötét Őrségnél,Nella Guardia Oscura, 闇の刻計 へ向かえ,... 어둠의 감시초소에서,op de donkere wacht,på den mørke vakten,w Ciemnej Strażnicy,na Guarda Negra,,pe Gardianul Întunecat,у тёмной стражи,на Црној стражи,på den mörka vakten,Karanlık Nöbet'te +One gear has been placed,TXT_ACS_MAP54_15_ONEGE,,,,Jedno kolo bylo umístěno.,Der er blevet placeret et redskab,Ein Zahnrad wurde eingesetzt,,Dentrado estis metita.,Un engranaje en su lugar,,Ratas on asetettu,Un engrenage a été placé,Egy fogaskerék a helyére került,Un ingranaggio è stato piazzato,歯車を一つ配置した,톱니바퀴 1개가 배치되었다,Een tandwiel is geplaatst,Ett tannhjul har blitt plassert,Jedna zębatka została umieszczona,Uma engrenagem foi colocada,,Un mecanism a fost introdus,Шестерня установлена,Један зупчаник је постављен,En kugghjul har placerats,Bir dişli yerleştirildi +\x20gears have been placed,TXT_ACS_MAP54_16_GEARS,,,,\x20kola byla umístěna.,\x20gear er blevet placeret,\x20Zahnräder wurden eingesetzt,,\x20dentradoj estis metitaj.,\x20engranajes en su lugar,,\x20ratasta on asetettu,\x20engrenages ont été placés,\x20fogaskerék a helyére került,\x20ingranaggi sono stati piazzati,歯車を配置した,톱니바퀴들이 배치되었다,\x20tandwielen zijn geplaatst,\x20 tannhjul har blitt plassert,\x20zębatki zostały umieszczone,\x20engrenagens foram colocadas,,\x20mecanisme au fost introduse,\x20шестерней установлено,\x20зупчаника су постављена,\x20 kugghjul har placerats,\x20dişliler yerleştirildi +A barricade has opened,TXT_ACS_MAP54_17_ABARR,,,,V Kloace se otevřela barikáda.,En barrikade er blevet åbnet,Eine Barrikade wurde geöffnet,,Barikado malfermiĝis,La barricada se ha abierto,Se abrió la barricada,Tiesulku on auennut,Une barricade s'est ouverte,Egy barikád megszűnt,Una barricata è stata aperta,バリケードは開かれた,방벽이 열렸다...,Er is een barricade geopend,En barrikade har åpnet seg,Barykada została otwarta,Uma barricada se abriu,,O baricadă s-a deschis,Преграда опустилась,Барикада је отворена,En barrikad har öppnats,Bir barikat açıldı +On the Cloaca,TXT_ACS_MAP54_18_ONTHE,,,,V Kloace se otevřela barikáda.,På Cloaca,In der Kloake,,En la Kloako.,En la Cloaca,,kloaakilla,dans le cloaque,a Kloákánál,Nella Cloaca,排泄腔 へ向かえ,... 하수구에서,Op de Cloaca,på Cloaca,W Kloace,Na Cloaca,,pe Cloaca,в клоаке,у клоаци,På Cloaca,Kloaka Üzerine +The way back is open,TXT_ACS_MAP54_20_THEWA,,,,Cesta zpět je otevřena.,Vejen tilbage er åben,Der Weg zurück ist offen,,La vojo reen estas malfermita.,El camino está abierto,,Tie takaisin on auki,Un chemin s'est ouvert,A visszavezető út kinyílt,La via del ritorno è aperta,裏口は開いた,돌아가는 길이 열렸다,De terugweg is open,Veien tilbake er åpen,Droga powrotna jest otwarta,O caminho de volta está aberto,,Calea e deschisă,Путь назад открыт,Пролаз назад је отворен,Vägen tillbaka är öppen,Dönüş yolu açık +The door is barred from the inside,TXT_ACS_MAP55_9_THEDO,,,,Dveře jsou zatarasené zevnitř.,Døren er spærret indefra,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está trabada desde el otro lado,,Ovi on teljetty sisältä,La porte est bloquée de ce côté,Az ajtó bentről van bereteszelve,La porta è stata aperta da dentro,この扉は内側から塞がれている,이 문은 안에 빗장이 걸려있다,De deur is van binnenuit geblokkeerd.,Døren er sperret fra innsiden,Drzwi są zabarykadowane od wewnątrz,A porta está barrada por dentro,,Ușa e încuiată din interior,Дверь заблокирована изнутри,Врата су забрављена изнутра,Dörren är spärrad från insidan,Kapı içeriden kilitli. +You dare plunder the tomb,TXT_ACS_MAP56_0_YOUDA,,,,Ty se opovažuješ rabovat,Du vover at plyndre graven,Wagst du es,,Ĉu vi aŭdacas rabi de la tombo,¿Te atreves a saquear la tumba,,Kuinka kehtaat ryöstää,Vous osez piller la tombe,A hóhér sírját,Osi saccheggiare la tomba,お前はあえて 執行人達の墓を,배짱이 두둑하구나...,Je durft de graftombe te plunderen,Våger du å plyndre graven,Śmiesz plądrować grobowiec,Como ousa saquear a tumba,,Cutezi să jefuiești mormântul,Ты посмел ограбить могилу,Усуђујеш се пљачкати,Du vågar plundra graven,Mezarı yağmalamaya cüret ediyorsun +of the executioner?,TXT_ACS_MAP56_1_OFTHE,,,,hrobku popravčího?,af bødlen?,das Grab des Henkers zu plündern?,,de la ekzekutisto?,del ejecutor?,,teloittajan haudan?,du bourreau?,próbálod fosztogatni?,dell'esecutore?,荒らすつもりか?,사형 집행자의 무덤을 도굴하다니.,van de beul?,til bøddelen?,kata?,do executor?,,călăului?,верховного палача?,желатову гробницу?,av bödeln?,Celladın mı? +Prepare to die,TXT_ACS_MAP56_2_PREPA,,,,Připrav se zemřít.,Forbered dig på at dø,Bereite dich vor zu sterben,,Pretiĝu por morti!,¡Prepárate para morir!,,Valmistaudu kuolemaan,Préparez vous à mourir!,Készülj a halálra,Preparati a morire,死ぬ準備をしろ,죽어서 회계하라.,Bereid je voor om te sterven,Forbered deg på å dø,Przygotuj się na śmierć,Prepare-se para morrer,,Pregătește-te să mori,Готовься к смерти,Припреми се да умреш,Förbered dig på att dö,Ölmeye hazırlanın +You have ,TXT_ACS_MAP59_1_YOUHA,,,,Zbývají ti ,Du har,Du musst,,Vi ankoraŭ havas,Aún tienes,,Sinulla on,Vous avez,Még kell találnod,Hai ancora altri,スイッチはまだ,당신은,Je hebt,Du har,Masz,Faltam mais,,Mai ai,Осталось,Остало је ,Du har,Bulmanız gereken\x20 +\x20more switches to find,TXT_ACS_MAP59_2_MORES,,,,\x20spínače k nalezení.,\x20flere kontakter at finde,\x20weitere Schalter finden,,\x20trovindajn ŝaltilojn.,\x20interruptores más que encontrar,,\x20lisää vipua löydettävänä,\x20boutons à trouver,\x20darab kallantyút,\x20interruttori da trovare,残っている,개의 개폐기들을 더 찾아야 한다,\x20meer schakelaars te vinden,\x20 brytere til å finne,\x20przełączników do znalezienia,\x20interruptores para encontrar,,\x20butoane de găsit,\x20переключателей,\x20прекидача да се нађе,\x20fler växlar att hitta.,\x20anahtar daha var. +You have only ,TXT_ACS_MAP59_3_YOUHA,,,,Zbývá ti jen ,Du har kun,Du musst nur,,Vi nur havas,Tienes solo,,Sinulla on vain,Vous avez seulement,Már csak,Hai solamente,スイッチは,이제 당신은 ,Je hebt alleen,Du har bare,Masz tylko,Falta somente,,Mai ai doar,Остался всего,Oстао је само ,Du har bara,Bulmanız gereken\x20 \x20switch left,TXT_ACS_MAP59_4_SWITC,,,,\x20spínač.,\x20kontakter tilbage,\x20Schalter finden,,\x20ŝaltilon ceteran.,\x20interruptor restante,,\x20vipu jäljellä,\x20bouton a trouver,\x20darab kallantyút kell találnod,\x20interruttore rimanente,"だけ残っている -",개의 개폐기만 찾으면 된다,\x20schakelaar over,1 bryter igjen,\x20przełącznik,\x20interruptor,,\x20buton rămas,\x20переключатель,\x20прекидач,\x20anahtar daha var. -The way to the tower is open,TXT_ACS_MAP59_5_THEWA,,,,Cesta do věže je otevřena.,Vejen til tårnet er åben,Der Weg zum Turm ist offen,,La vojo al la turo estas malfermita.,El camino a la torre está abierto,,Tie tornin luo on auki,Le chemin vers la tour est ouvert.,A toronyba vezető út kinyílt,La via alla torre è stata aperta,塔への道 が開いた,탑으로 가는 길이 열렸다,De weg naar de toren is open,Veien til tårnet er åpen,Droga do wieży jest otwarta,O caminho para a torre está aberto,,Calea către turn e deschisă,Путь к башне открыт,Пут до куле је отворен,Kuleye giden yol açık. -The way is open,TXT_ACS_MAP60_3_THEWA,,,,Cesta je otevřena.,Vejen er åben,Der Weg ist offen,,La vojo estas malfermita.,El camino está abierto,,Tie on auki,Le chemin est ouvert.,Az út kinyílt,La via è aperta,道は開いた,길이 열렸다,De weg is open,Veien er åpen,Droga jest otwarta,O caminho está aberto,,Calea e deschisă,Портал открыт,Портал је отворен,Yol açık -,,Strife dialogue,,,,,,,,,,,,,,,,,,,,,,,, -"I don't want any trouble, stay away from me. I've had enough trouble with what that bastard Harris did to me. He promised me money, instead I get to look forward to being Questioned by the Programmer.",TXT_DLG_SCRIPT01_D0_IDONT,MAP01: Beldin.,,,"Nechci žádný trable, jdi ode mě. Už tak mám dost potíží s tím, co mi ten hajzl Harris provedl. Slíbil mi peníze a místo toho se můžu těšit na výslech od Programátora.","Jeg vil ikke have ballade, hold dig væk fra mig. Jeg har haft nok problemer med det, den skiderik Harris gjorde mod mig. Han lovede mig penge, men i stedet skal jeg se frem til at blive udspurgt af programmøren.","Ich möchte keinen Ärger, bleib weg von mir. Ich hatte genug Ärger mit dem was der Bastard Harris mir angetan hat. Er hat mir Geld versprochen, stattdessen musste ich mich darauf vorbereiten von dem Programmierer ausgefragt zu werden.",,"Malproksimiĝu de mi; mi ne volas pliajn problemojn. Mi jam havis sufiĉajn pro tio, kion Harris faris: li promesis monon al mi, kaj anstataŭ tio mi nun atendas, ke La Progamisto pridemandu min.","No te me acerques, que ya no quiero más problemas. He tenido suficientes con lo que me hizo Harris: me prometió dinero, y en lugar de eso, ahora me toca esperar a ser interrogado por El Programador.",,"En kaipaa ikävyyksiä; pysy pois luotani. Olen saanut kärsiä jo riittävästi vaivaa Harris-paskiaisen tekosista. Hän lupasi minulle rahaa, mutta sen sijaan pääsenkin Ohjelmoitsijan kuulusteltavaksi.","Je ne veux pas d'embrouilles. Laissez moi tranquille. J'ai déjà assez de problèmes avec ce que ce salaud d'Harris ma fait. Il m'a promis de l'argent, maintenant, je risque de me faire interroger par le Programmeur.","Én nem akarok semmi problémát, maradj távol tőlem. Elég baj nekem az amit az a barom Harris okozott. Pénzt ígért, ehelyett az vár rám, hogy a Programozó ki fog kérdezni.","Non voglio problemi, stai alla larga. Ho già avuto abbastanza problemi con quello che quel bastardo di mi ha fatto. Mi aveva promesso soldi, invece mi ritrovo ad avere l'opportunità di essere interrogato dal Programmatore.","もう面倒事には御免だ、私に近づくな。 +",개의 개폐기만 찾으면 된다,\x20schakelaar over,1 bryter igjen,\x20przełącznik,\x20interruptor,,\x20buton rămas,\x20переключатель,\x20прекидач,1 växel kvar,\x20anahtar daha var. +The way to the tower is open,TXT_ACS_MAP59_5_THEWA,,,,Cesta do věže je otevřena.,Vejen til tårnet er åben,Der Weg zum Turm ist offen,,La vojo al la turo estas malfermita.,El camino a la torre está abierto,,Tie tornin luo on auki,Le chemin vers la tour est ouvert.,A toronyba vezető út kinyílt,La via alla torre è stata aperta,塔への道 が開いた,탑으로 가는 길이 열렸다,De weg naar de toren is open,Veien til tårnet er åpen,Droga do wieży jest otwarta,O caminho para a torre está aberto,,Calea către turn e deschisă,Путь к башне открыт,Пут до куле је отворен,Vägen till tornet är öppen.,Kuleye giden yol açık. +The way is open,TXT_ACS_MAP60_3_THEWA,,,,Cesta je otevřena.,Vejen er åben,Der Weg ist offen,,La vojo estas malfermita.,El camino está abierto,,Tie on auki,Le chemin est ouvert.,Az út kinyílt,La via è aperta,道は開いた,길이 열렸다,De weg is open,Veien er åpen,Droga jest otwarta,O caminho está aberto,,Calea e deschisă,Портал открыт,Портал је отворен,Vägen är öppen.,Yol açık +,,Strife dialogue,,,,,,,,,,,,,,,,,,,,,,,,, +"I don't want any trouble, stay away from me. I've had enough trouble with what that bastard Harris did to me. He promised me money, instead I get to look forward to being Questioned by the Programmer.",TXT_DLG_SCRIPT01_D0_IDONT,MAP01: Beldin.,,,"Nechci žádný trable, jdi ode mě. Už tak mám dost potíží s tím, co mi ten hajzl Harris provedl. Slíbil mi peníze a místo toho se můžu těšit na výslech od Programátora.","Jeg vil ikke have ballade, hold dig væk fra mig. Jeg har haft nok problemer med det, den skiderik Harris gjorde mod mig. Han lovede mig penge, men i stedet skal jeg se frem til at blive udspurgt af programmøren.","Ich möchte keinen Ärger, bleib weg von mir. Ich hatte genug Ärger mit dem was der Bastard Harris mir angetan hat. Er hat mir Geld versprochen, stattdessen musste ich mich darauf vorbereiten von dem Programmierer ausgefragt zu werden.",,"Malproksimiĝu de mi; mi ne volas pliajn problemojn. Mi jam havis sufiĉajn pro tio, kion Harriso faris: li promesis monon al mi, kaj anstataŭ tio mi nun atendas, ke La Progamisto pridemandu min.","No te me acerques, que ya no quiero más problemas. He tenido suficientes con lo que me hizo Harris: me prometió dinero, y en lugar de eso, ahora me toca esperar a ser interrogado por El Programador.",,"En kaipaa ikävyyksiä; pysy pois luotani. Olen saanut kärsiä jo riittävästi vaivaa Harris-paskiaisen tekosista. Hän lupasi minulle rahaa, mutta sen sijaan pääsenkin Ohjelmoitsijan kuulusteltavaksi.","Je ne veux pas d'embrouilles. Laissez moi tranquille. J'ai déjà assez de problèmes avec ce que ce salaud d'Harris ma fait. Il m'a promis de l'argent, maintenant, je risque de me faire interroger par le Programmeur.","Én nem akarok semmi problémát, maradj távol tőlem. Elég baj nekem az amit az a barom Harris okozott. Pénzt ígért, ehelyett az vár rám, hogy a Programozó ki fog kérdezni.","Non voglio problemi, stai alla larga. Ho già avuto abbastanza problemi con quello che quel bastardo di mi ha fatto. Mi aveva promesso soldi, invece mi ritrovo ad avere l'opportunità di essere interrogato dal Programmatore.","もう面倒事には御免だ、私に近づくな。 あのハリスのクズのせいでもう十分面倒な目に 遭ったんだ。ヤツは私に金を渡すと約束したのに、 裏切られて私がプログラマーに尋問されることに なってしまったんだ。","난 문제를 더 일으키고 싶지 않아, 나에게서 떨어져! 해리스 그 자식이 나를 속였어. 녀석이 돈을 준다고 해서 도와줬더니 도망치고 없었고 결국엔 붙잡혀서 프로그래머에게 심문을 받을 처지에 놓였다고!","Ik wil geen problemen, blijf uit mijn buurt. Ik heb genoeg problemen gehad met wat die klootzak Harris me heeft aangedaan. Hij beloofde me geld, maar in plaats daarvan kan ik me verheugen op een Ondervraging door de programmeur.","Jeg vil ikke ha trøbbel. Hold deg unna meg. Jeg har hatt nok trøbbel med det den jævelen Harris gjorde mot meg. Han lovet meg penger, i stedet kan jeg se frem til å bli avhørt av programmereren.","Nie chcę żadnych kłopotów, zostaw mnie w spokoju. Miałem już wystarczająco dużo problemów z tym co ten drań Harris mi zrobił. Obiecał mi pieniądze, ale zamiast tego muszę czekać na to, by być Przesłuchanym przez Programistę.","Não quero me meter em problemas, fique longe de mim. Já tive problemas demais com o que aquele desgraçado do Harris fez comigo. Ele me prometeu dinheiro, mas ao invés disso vou ser Questionado pelo Programador.",,"Nu vreau să am probleme, stai departe de mine. Am avut suficiente probleme din cauza a ceea ce -mi-a făcut ticălosul de Harris. Mi-a promis niște bani, dar în schimb, acum aștept cu nerăbdare să fiu interogat de către Programator.","Не подходи ко мне — мне не нужны неприятности! У меня их и так достаточно из-за этого мерзавца Харриса. Он обещал мне деньги, а вместо этого меня ожидает «допрос» у Программиста.",,"Bela istemiyorum, benden uzak dur. O piç Harris'in bana yaptıkları yüzünden yeterince sorun yaşadım. Bana para sözü verdi, onun yerine Programcı tarafından sorgulanmayı dört gözle bekliyorum." -I'll help you if you help me. Five pieces of gold and I'll tell all I know.,TXT_DLG_SCRIPT02_D0_ILLHE,MAP02: Guy next to Norwall Prison.,,,"Pomůžu ti, když pomůžeš ty mě. Pět zlaťáků a řeknu ti vše, co vím.","Jeg vil hjælpe dig, hvis du hjælper mig. Fem guldmønter, og jeg fortæller alt, hvad jeg ved.",Ich helfe dir wenn du mir hilfst. Fünf Goldstücke und ich erzähle alles was ich weiß.,,"Mi helpos vin se vi helpos min. Donu kvin da oro kaj mi rakontos ĉion, kion mi scias.",Te ayudo si me ayudas. Cinco piezas de oro y te cuento todo lo que sé.,,"Autan sinua, jos autat minua. Viidestä kultakolikosta kerron kaiken, minkä tiedän.","Tu m'aide, je t'aide. Cinq pièces et je te dis ce que je sais.","Segítek, ha segítesz. 5 arany és mindent elmondok, amit tudok.",Ti aiuterò se tu aiuti me. Cinque pezzi d'oro e ti dirò tutto quello che so.,"助けてくれるなら援助する。 +mi-a făcut ticălosul de Harris. Mi-a promis niște bani, dar în schimb, acum aștept cu nerăbdare să fiu interogat de către Programator.","Не подходи ко мне — мне не нужны неприятности! У меня их и так достаточно из-за этого мерзавца Харриса. Он обещал мне деньги, а вместо этого меня ожидает «допрос» у Программиста.",,"Jag vill inte ha några problem, håll dig borta från mig. Jag har haft tillräckligt med problem med vad den jäveln Harris gjorde mot mig. Han lovade mig pengar, istället får jag se fram emot att bli förhörd av Programmeraren.","Bela istemiyorum, benden uzak dur. O piç Harris'in bana yaptıkları yüzünden yeterince sorun yaşadım. Bana para sözü verdi, onun yerine Programcı tarafından sorgulanmayı dört gözle bekliyorum." +I'll help you if you help me. Five pieces of gold and I'll tell all I know.,TXT_DLG_SCRIPT02_D0_ILLHE,MAP02: Guy next to Norwall Prison.,,,"Pomůžu ti, když pomůžeš ty mě. Pět zlaťáků a řeknu ti vše, co vím.","Jeg vil hjælpe dig, hvis du hjælper mig. Fem guldmønter, og jeg fortæller alt, hvad jeg ved.",Ich helfe dir wenn du mir hilfst. Fünf Goldstücke und ich erzähle alles was ich weiß.,,"Mi helpos vin se vi helpos min. Donu kvin da oro kaj mi rakontos ĉion, kion mi scias.",Te ayudo si me ayudas. Cinco monedas de oro y te cuento todo lo que sé.,,"Autan sinua, jos autat minua. Viidestä kultakolikosta kerron kaiken, minkä tiedän.","Tu m'aide, je t'aide. Cinq pièces et je te dis ce que je sais.","Segítek, ha segítesz. 5 arany és mindent elmondok, amit tudok.",Ti aiuterò se tu aiuti me. Cinque pezzi d'oro e ti dirò tutto quello che so.,"助けてくれるなら援助する。 5ゴールドで知っている情報を全て教えよう",저를 도와준다면 당신을 돕겠습니다. 5 골드를 줌으로써 말이죠.,Ik zal je helpen als je me helpt. Vijf goudstukken en ik vertel alles wat ik weet.,"Jeg hjelper deg hvis du hjelper meg. Fem gullstykker, så forteller jeg alt jeg vet.",Pomogę ci jeśli ty mi pomożesz. Pięć sztuk złota i powiem ci wszytsko co wiem.,Eu te ajudo se você me ajudar. Cinco moedas de ouro e te digo tudo que eu sei.,,"O să te ajut dacă și tu mă ajuți. Cinci bucăți de aur -și-ți voi spune tot ce știu.","Я помогу тебе, если ты поможешь мне. Пять золотых, и я расскажу всё, что знаю.",,Bana yardım edersen ben de sana yardım ederim. Beş altın ve tüm bildiklerimi anlatacağım. -Here's the gold.,TXT_RPLY0_SCRIPT02_D0_HERES,〃,,,Tady jsou.,Her er guldet.,Hier ist dein Gold.,,Jen la oro.,Aquí está el oro.,,Tässä on kulta.,Voilà l'argent.,Itt az arany.,Ecco l'oro.,金はこれだ。,여기 골드입니다.,Hier is het goud.,Her er gullet.,Oto złoto.,Aqui está o ouro.,,Poftiți aurul.,Вот золото.,,İşte altın. +și-ți voi spune tot ce știu.","Я помогу тебе, если ты поможешь мне. Пять золотых, и я расскажу всё, что знаю.",,Jag hjälper dig om du hjälper mig. Fem guldmynt och jag berättar allt jag vet.,Bana yardım edersen ben de sana yardım ederim. Beş altın ve tüm bildiklerimi anlatacağım. +Here's the gold.,TXT_RPLY0_SCRIPT02_D0_HERES,〃,,,Tady jsou.,Her er guldet.,Hier ist dein Gold.,,Jen la oro.,Aquí está el oro.,,Tässä on kulta.,Voilà l'argent.,Itt az arany.,Ecco l'oro.,金はこれだ。,여기 골드입니다.,Hier is het goud.,Her er gullet.,Oto złoto.,Aqui está o ouro.,,Poftiți aurul.,Вот золото.,,Här är guldet.,İşte altın. "Be stealthy when you kill, you won't set off alarms.",TXT_RYES0_SCRIPT02_D0_BESTE,〃,,,"Když zabíjíš, dělej to potichu - nespustíš tak poplach.","Vær snigende når du dræber, så du ikke udløser alarmer.","Sei leise, wenn du jemanden tötest, damit du keinen Alarm auslöst.",,"Mortigu silente por ne ekagigi alarmojn.","Sé sigiloso al matar para -no activar las alarmas.",,"Jos tapat vihollisesi salaa, vältyt hälytyksiltä.",Tuez discrètement et vous n'aurez pas de problème avec les alarmes.,"Lopakodva, halkan gyilkolj, kézzel, így nem indul be a riasztó.","Sii furtivo quando uccidi, non farai scattare l'allarme.",始末する際は隠密に、警報を鳴らさないように。,"조용히 은신해서 암살만 한다면, 경보를 울리지 않을 겁니다.","Wees sluipend als je doodt, je zult geen alarmbellen laten afgaan.","Vær snikende når du dreper, så du ikke utløser alarmer.","Bądź cicho kiedy zabijasz, nie włączysz wtedy alarmu.",Seja cauteloso quando for matar e não ativará os alarmes.,,"Fii discret când ucizi, nu vei declanșa alarma astfel.","Убивай бесшумно, чтобы не поднять тревогу.",,"Öldürürken gizli ol, alarmları çalıştırmazsın." -"Well, I won't be telling you anything for free!",TXT_RNO0_SCRIPT02_D0_WELLI,〃,,,Zadarmo ti nic říkat nebudu!,Jeg vil ikke fortælle dig noget gratis!,"Na ja, für umsonst werde ich dir nichts erzählen!",,"Nu, mi ne parolos senpage!","Bueno, ¡no te diré nada gratis!","Bueno, ¡no voy a decir nada gratis!","No, en aio kertoa mitään ilmaiseksi!",Je ne vous dirai rien si vous ne me donnez rien!,"Figyelj, ingyen semmit sem mondok el neked.","Beh, io non ti dirò un bel niente senza compenso!",いや、タダで情報は渡せない!,세상에 공짜가 어딨습니까? 먼저 돈을 주세요!,"Nou, ik zal je niets gratis vertellen!","Vel, jeg vil ikke fortelle deg noe gratis!","Cóż, nie będę ci mówił niczego za darmo!","Bom, não vou te dar informação de graça!",,"Păi, n-o să-ți zic nimic pe gratis!","Что ж, я ничего не скажу даром!",,Sana bedavaya hiçbir şey anlatmayacağım! -Have you by any chance got another 5 gold on you?,TXT_DLG_SCRIPT02_D1516_HAVEY,〃,,,Neměl bys u sebe náhodou dalších pět zlatek?,Har du tilfældigvis fem guldstykker mere på dig?,Hast du vielleicht 5 weitere Goldmünzen dabei?,,Ĉu eble vi havas aliajn 5 da oro?,"¿No tendrás otros 5 de oro, por casualidad?",,Sattuisiko sinulla olemaan toiset viisi kolikkoa?,T'aurais pas 5 pièces en plus sur toi?,Nincs véletlenül nálad még 5 arany?,Hai per caso altri 5 pezzi d'oro con te?,もしかして5ゴールド稼いだのか?,5 골드 더 있습니까? 그러면 아주 좋을 텐데.,Heb je toevallig nog 5 goud bij je?,Har du tilfeldigvis fem gull til på deg?,Czy przypadkiem masz może kolejne 5 monet przy sobie?,Por acaso teria mais 5 de ouro aí?,,"Ai cumva, din întâmplare, 5 monezi de aur?",У тебя случайно не найдётся ещё 5 монеток?,,Yanında 5 altın daha var mı acaba? -5 gold.,TXT_RPLY0_SCRIPT02_D1516_5GOLD,〃,,,Pět zlatých.,5 guld.,5 Gold.,,5 da oro.,5 de oro.,,5 kolikkoa.,5 pièces.,5 arany.,5 pezzi d'oro.,5ゴールドだ。,5 골드.,5 goud.,5 gull.,5 monet.,5 de ouro.,,5 monezi de aur.,5 золотых.,,5 altın. +no activar las alarmas.",,"Jos tapat vihollisesi salaa, vältyt hälytyksiltä.",Tuez discrètement et vous n'aurez pas de problème avec les alarmes.,"Lopakodva, halkan gyilkolj, kézzel, így nem indul be a riasztó.","Sii furtivo quando uccidi, non farai scattare l'allarme.",始末する際は隠密に、警報を鳴らさないように。,"조용히 은신해서 암살만 한다면, 경보를 울리지 않을 겁니다.","Wees sluipend als je doodt, je zult geen alarmbellen laten afgaan.","Vær snikende når du dreper, så du ikke utløser alarmer.","Bądź cicho kiedy zabijasz, nie włączysz wtedy alarmu.",Seja cauteloso quando for matar e não ativará os alarmes.,,"Fii discret când ucizi, nu vei declanșa alarma astfel.","Убивай бесшумно, чтобы не поднять тревогу.",,"Var smygande när du dödar, du kommer inte att utlösa larm.","Öldürürken gizli ol, alarmları çalıştırmazsın." +"Well, I won't be telling you anything for free!",TXT_RNO0_SCRIPT02_D0_WELLI,〃,,,Zadarmo ti nic říkat nebudu!,Jeg vil ikke fortælle dig noget gratis!,"Na ja, für umsonst werde ich dir nichts erzählen!",,"Nu, mi ne parolos senpage!","Bueno, ¡no te diré +nada gratis!","Bueno, ¡no voy a decir +nada gratis!","No, en aio kertoa mitään ilmaiseksi!",Je ne vous dirai rien si vous ne me donnez rien!,"Figyelj, ingyen semmit sem mondok el neked.","Beh, io non ti dirò un bel niente senza compenso!",いや、タダで情報は渡せない!,세상에 공짜가 어딨습니까? 먼저 돈을 주세요!,"Nou, ik zal je niets gratis vertellen!","Vel, jeg vil ikke fortelle deg noe gratis!","Cóż, nie będę ci mówił niczego za darmo!","Bom, não vou te dar informação de graça!",,"Păi, n-o să-ți zic nimic pe gratis!","Что ж, я ничего не скажу даром!",,Jag kommer inte att berätta något gratis!,Sana bedavaya hiçbir şey anlatmayacağım! +Have you by any chance got another 5 gold on you?,TXT_DLG_SCRIPT02_D1516_HAVEY,〃,,,Neměl bys u sebe náhodou dalších pět zlatek?,Har du tilfældigvis fem guldstykker mere på dig?,Hast du vielleicht 5 weitere Goldmünzen dabei?,,Ĉu eble vi havas aliajn kvin da oro?,"¿No tendrás otros cinco de oro, por casualidad?",,Sattuisiko sinulla olemaan toiset viisi kolikkoa?,T'aurais pas 5 pièces en plus sur toi?,Nincs véletlenül nálad még 5 arany?,Hai per caso altri 5 pezzi d'oro con te?,もしかして5ゴールド稼いだのか?,5 골드 더 있습니까? 그러면 아주 좋을 텐데.,Heb je toevallig nog 5 goud bij je?,Har du tilfeldigvis fem gull til på deg?,Czy przypadkiem masz może kolejne 5 monet przy sobie?,Por acaso teria mais 5 de ouro aí?,,"Ai cumva, din întâmplare, 5 monezi de aur?",У тебя случайно не найдётся ещё 5 монеток?,,Har du av en slump 5 guldpengar till på dig?,Yanında 5 altın daha var mı acaba? +5 gold.,TXT_RPLY0_SCRIPT02_D1516_5GOLD,〃,,,Pět zlatých.,5 guld.,5 Gold.,,Kvin da oro.,Cinco de oro.,,5 kolikkoa.,5 pièces.,5 arany.,5 pezzi d'oro.,5ゴールドだ。,5 골드.,5 goud.,5 gull.,5 monet.,5 de ouro.,,5 monezi de aur.,5 золотых.,,Fem guld.,5 altın. "Well, poison bolts can kill the guards instantly and won't set off the alarms.",TXT_RYES0_SCRIPT02_D1516_WELLP,〃,,,"No, otrávené šípy okamžitě zabijí stráže a nikdo nevyhlásí poplach.","Nå, giftpile kan dræbe vagterne med det samme og vil ikke udløse alarmen.",Also Giftpfeile können die Wachen sofort töten und lösen keinen Alarm aus.,,"Mortigi per venenaj sagoj estas tuje kaj silente.","Matar con flechas envenenadas es instantáneo y sin alarmas.",,No niin; myrkkynuolilla voi tappaa vartijat välittömästi hälytystä laukaisematta.,Les carreaux empoisonnés tuent les gardes instantanément et discrètement.,"Hát, a mérgező nyilak azonnal a túlvilágra küldik az őröket, és a riasztó sem kapcsol be.",Le frecce avvelenate possono uccidere le guardie istantaneamente e non faranno scattare l'allarme.,"そうだな、ポイズンボルトは警備員を簡単に殺せるし、 警報を作動させることもない。",아시나요? 맹독 볼트만 있으면 경보를 울리지 않고 경비병을 죽일 수 있다는거?,"Nou, gifbouten kunnen de bewakers onmiddellijk doden en zullen het alarm niet laten afgaan.","Vel, giftbolter kan drepe vaktene øyeblikkelig og vil ikke utløse alarmen.","Więc, zatrute bełty mogą od razu zabić strażników i nie włączą alarmu.","Bem, setas venenosas podem matar guardas na hora e não disparam alarmes.",,"Păi, bolțurile otrăvite pot omorâ gardienii instant -și nu vor declanșa alarma.","Что ж, отравленными болтами можно убивать охранников быстро и бесшумно.",,Zehirli oklar muhafızları anında öldürebilir ve alarmı çalıştırmaz. -"No sir, I won't be telling you anything for free!",TXT_RNO0_SCRIPT02_D1516_NOSIR,〃,,,"Ne, ne, zadarmo ti nic říkat nebudu!","Nej, sir, jeg vil ikke fortælle dig noget gratis!","Nein, ich werde dir nichts für umsonst erzählen!",,"Ne, mi diros nenion senpage!","¡No, no diré nada gratis!","¡No, no voy a decir nada gratis!","Ehei, en kerro mitään ilmaiseksi!","Non, monsieur, je ne vous dirai rien si je ne me fais pas payer!","Nem uram, nem árulok el semmit ingyen!","No signore, non ti dirò nulla senza avere qualcosa in cambio!",いやいや、タダでは話せないな!,"죄송합니다만, 전 아무것도 무료로 말해주지 않을 겁니다!","Nee meneer, ik zal u niets gratis vertellen!","Nei, sir, jeg vil ikke fortelle deg noe gratis!","Nie panie, nie będę ci mówił niczego za darmo!","Nada disso, senhor, não vou te dizer nada de graça!",,"Nu domnule, n-o să-ți zic nimic pe gratis!","Нет, товарищ! Даром — только за амбаром!",,"Hayır efendim, size bedava bir şey söylemeyeceğim!" -You've wrung the last bit of gossip out of me already!,TXT_DLG_SCRIPT02_D3032_YOUVE,〃,,,"Už jsi ze mě vyždímal všechny klepy, co jsem měl!",Du har allerede vredet den sidste smule sladder ud af mig!,Du hast bereits das letzte bisschen Klatsch aus mir herausgequetscht!,,Vi jam eltiris de mi eĉ la lastan klaĉon.,Ya me has sacado hasta el último cotilleo.,Ya me sacaste hasta el último chisme.,Olet jo puristanut minusta kaikki juorut!,Vous m'avez tiré tous les vers du nez!,Már a legutolsó pletykát is kiszedted belőlem.,Mi hai già spremuto fino all'ultimo pettegolezzo! ,既にイキのいい噂は聞かせたぞ!,가십거리를 이미 다 털어놓았습니다. 더 뭘 바랍니까?,Je hebt de laatste roddels al uit me uitgewrongen!,Du har allerede vrengt det siste sladderet ut av meg!,Wyciągnąłeś już ze mnie ostatnią plotkę!,Você já ouviu todos os boatos que posso te contar!,,Ai stors ultimele bârfe din mine deja!,"Ты уже вытянул из меня всё, что только можно!",,Benden son dedikodumu da aldınız zaten! -What can I get for you?,TXT_DLG_SCRIPT02_D4548_WHATC,MAP02: Irale.,,,Co si budeš přát?,Hvad kan jeg få for dig?,Was kann ich für dich tun?,,Kion mi donu al vi?,¿Qué puedo ofrecerte?,,Mitä saisi olla?,Qu'est ce que je peux pour vous?,Mit tehetnék érted?,Cosa posso offrirti?,何か必要か?,무엇을 구매하고 싶어?,Wat kan ik voor u halen?,Hva vil du ha?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot să-ți aduc?,Что я могу тебе предложить?,,Sizin için ne alabilirim? -Assault gun,TXT_RPLY0_SCRIPT02_D4548_ASSAU,〃,,,Útočnou pušku,En pistol til angreb,Sturmgewehr,,Sturmofusilon,Fusil de asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,En automatpistol.,Karabin Szturmowy,Fuzil de assalto,,Pușcă de asalt,Штурмовую винтовку,,Saldırı silahı. -Here you go.,TXT_RYES0_SCRIPT02_D4548_HEREY,〃,,,Tu máš.,Værsgo.,Bitte sehr!,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Tessék,Ecco a te.,毎度あり。,여기 있어.,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи.,,Al bakalım. +și nu vor declanșa alarma.","Что ж, отравленными болтами можно убивать охранников быстро и бесшумно.",,"Tja, giftbultar kan döda vakterna omedelbart och kommer inte att utlösa larmen.",Zehirli oklar muhafızları anında öldürebilir ve alarmı çalıştırmaz. +"No sir, I won't be telling you anything for free!",TXT_RNO0_SCRIPT02_D1516_NOSIR,〃,,,"Ne, ne, zadarmo ti nic říkat nebudu!","Nej, sir, jeg vil ikke fortælle dig noget gratis!","Nein, ich werde dir nichts für umsonst erzählen!",,"Ne, mi diros nenion senpage!","¡No, no diré nada gratis!","¡No, no voy a decir nada gratis!","Ehei, en kerro mitään ilmaiseksi!","Non, monsieur, je ne vous dirai rien si je ne me fais pas payer!","Nem uram, nem árulok el semmit ingyen!","No signore, non ti dirò nulla senza avere qualcosa in cambio!",いやいや、タダでは話せないな!,"죄송합니다만, 전 아무것도 무료로 말해주지 않을 겁니다!","Nee meneer, ik zal u niets gratis vertellen!","Nei, sir, jeg vil ikke fortelle deg noe gratis!","Nie panie, nie będę ci mówił niczego za darmo!","Nada disso, senhor, não vou te dizer nada de graça!",,"Nu domnule, n-o să-ți zic nimic pe gratis!","Нет, товарищ! Даром — только за амбаром!",,"Nej, sir, jag tänker inte berätta något gratis för dig!","Hayır efendim, size bedava bir şey söylemeyeceğim!" +You've wrung the last bit of gossip out of me already!,TXT_DLG_SCRIPT02_D3032_YOUVE,〃,,,"Už jsi ze mě vyždímal všechny klepy, co jsem měl!",Du har allerede vredet den sidste smule sladder ud af mig!,Du hast bereits das letzte bisschen Klatsch aus mir herausgequetscht!,,Vi jam eltiris de mi eĉ la lastan klaĉon.,Ya me has sacado hasta el último cotilleo.,Ya me sacaste hasta el último chisme.,Olet jo puristanut minusta kaikki juorut!,Vous m'avez tiré tous les vers du nez!,Már a legutolsó pletykát is kiszedted belőlem.,Mi hai già spremuto fino all'ultimo pettegolezzo! ,既にイキのいい噂は聞かせたぞ!,가십거리를 이미 다 털어놓았습니다. 더 뭘 바랍니까?,Je hebt de laatste roddels al uit me uitgewrongen!,Du har allerede vrengt det siste sladderet ut av meg!,Wyciągnąłeś już ze mnie ostatnią plotkę!,Você já ouviu todos os boatos que posso te contar!,,Ai stors ultimele bârfe din mine deja!,"Ты уже вытянул из меня всё, что только можно!",,Du har redan pressat ut det sista skvallret ur mig!,Benden son dedikodumu da aldınız zaten! +What can I get for you?,TXT_DLG_SCRIPT02_D4548_WHATC,MAP02: Irale.,,,Co si budeš přát?,Hvad kan jeg få for dig?,Was kann ich für dich tun?,,Kion mi donu al vi?,¿Qué puedo ofrecerte?,,Mitä saisi olla?,Qu'est ce que je peux pour vous?,Mit tehetnék érted?,Cosa posso offrirti?,何か必要か?,무엇을 구매하고 싶어?,Wat kan ik voor u halen?,Hva vil du ha?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot să-ți aduc?,Что я могу тебе предложить?,,Vad kan jag få för dig?,Sizin için ne alabilirim? +Assault gun,TXT_RPLY0_SCRIPT02_D4548_ASSAU,〃,,,Útočnou pušku,En pistol til angreb,Sturmgewehr,,Sturmofusilon,Fusil de asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,En automatpistol.,Karabin Szturmowy,Fuzil de assalto,,Pușcă de asalt,Штурмовую винтовку,,En attackpistol,Saldırı silahı. +Here you go.,TXT_RYES0_SCRIPT02_D4548_HEREY,〃,,,Tu máš.,Værsgo.,Bitte sehr!,,Jen.,Toma.,,"Tässä, ole hyvä.",Voilà pour vous.,Tessék,Ecco a te.,毎度あり。,여기 있어.,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи.,,Här får du.,Al bakalım. You can't afford that right now.,TXT_RNO0_SCRIPT02_D4548_YOUCA,〃,,,Tu si teď nemůžeš dovolit.,Det har du ikke råd til lige nu.,Das kannst du dir momentan nicht leisten.,,"Vi nun ne havas -sufiĉe da oro.",No te alcanza por ahora.,,Sinulla ei ole siihen juuri nyt varaa.,Vous n'avez pas assez d'argent.,Erre most nincs pénzed.,Non hai abbastanza soldi.,今それを買える余裕は無い。,그걸 사기엔 여유가 없는 것 같네.,Dat kunt je zich nu niet veroorloven.,Det har du ikke råd til akkurat nå.,Nie możesz teraz tego kupić.,Você não pode comprar isso no momento.,,Nu-ți poți permite asta încă.,Ты пока не можешь себе это позволить.,,Şu anda bunu karşılayamazsın. -Clip of bullets,TXT_RPLY1_SCRIPT02_D4548_CLIPO,〃,,,Zásobník nábojů,Et magasin med kugler,Gewehrmunition.,,Magazenon,Un cargador,,Luotilipas,Chargeur de balles,Egy tár töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler.,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов,,Mermi şarjörü -Thanks.,TXT_RYES1_SCRIPT02_D4548_THANK,〃,,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고맙다!,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Teşekkürler. -"Come on, 10 gold.",TXT_RNO1_SCRIPT02_D4548_COMEO,〃,,,"No tak, jen deset zlatých.","Kom nu, 10 guld.","Na komm, 10 Gold.",,"Nu, ĝi kostas 10 da oro.","Vamos, que son 10 de oro.",,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Gyerünk, 10 arany.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,10 골드만 있으면 되는데...,"Kom op, 10 goud.","Kom igjen, 10 gull.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.",,"Hadi, 10 altın." -Ammo box,TXT_RPLY2_SCRIPT02_D4548_AMMOB,〃,,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Municikesto,Caja de municiones,,Ammuslaatikko,Bôite de balles,Egy doboz lőszer,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Ammunisjonsboks,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов,,Cephane kutusu -Here's your ammo.,TXT_RYES2_SCRIPT02_D4548_HERES,〃,,,Tady je tvá munice.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,탄약 여기 있어!,Hier is je munitie.,Her er ammunisjonen din.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны.,,İşte cephanen. +sufiĉe da oro.",No te alcanza por ahora.,,Sinulla ei ole siihen juuri nyt varaa.,Vous n'avez pas assez d'argent.,Erre most nincs pénzed.,Non hai abbastanza soldi.,今それを買える余裕は無い。,그걸 사기엔 여유가 없는 것 같네.,Dat kunt je zich nu niet veroorloven.,Det har du ikke råd til akkurat nå.,Nie możesz teraz tego kupić.,Você não pode comprar isso no momento.,,Nu-ți poți permite asta încă.,Ты пока не можешь себе это позволить.,,Du har inte råd med den just nu.,Şu anda bunu karşılayamazsın. +Clip of bullets,TXT_RPLY1_SCRIPT02_D4548_CLIPO,〃,,,Zásobník nábojů,Et magasin med kugler,Gewehrmunition.,,Magazenon,Un cargador,,Luotilipas,Chargeur de balles,Egy tár töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler.,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов,,Kulor.,Mermi şarjörü +Thanks.,TXT_RYES1_SCRIPT02_D4548_THANK,〃,,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고맙다!,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Tack.,Teşekkürler. +"Come on, 10 gold.",TXT_RNO1_SCRIPT02_D4548_COMEO,〃,,,"No tak, jen deset zlatých.","Kom nu, 10 guld.","Na komm, 10 Gold.",,"Nu, ĝi kostas dek da oro.","Vamos, que son diez de oro.",,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Gyerünk, 10 arany.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,10 골드만 있으면 되는데...,"Kom op, 10 goud.","Kom igjen, 10 gull.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.",,"Kom igen, 10 guld.","Hadi, 10 altın." +Ammo box,TXT_RPLY2_SCRIPT02_D4548_AMMOB,〃,,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Munici-keston,Caja de municiones,,Ammuslaatikko,Bôite de balles,Egy doboz lőszer,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Ammunisjonsboks,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов,,Ammunitionslåda,Cephane kutusu +Here's your ammo.,TXT_RYES2_SCRIPT02_D4548_HERES,〃,,,Tady je tvá munice.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,탄약 여기 있어!,Hier is je munitie.,Her er ammunisjonen din.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны.,,Här är din ammunition.,İşte cephanen. Maybe some other time.,TXT_RNO2_SCRIPT02_D4548_MAYBE,〃,,,Možná někdy jindy.,Måske en anden gang.,Vielleicht ein anderes Mal.,,Eble alimomente.,"Puede que en -otro momento.",,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán majd máskor.,Magari un'altra volta.,また後でな。,아마도 나중에...,Misschien een andere keer.,Kanskje en annen gang.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.",,Belki başka bir zaman. +otro momento.",,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán majd máskor.,Magari un'altra volta.,また後でな。,아마도 나중에...,Misschien een andere keer.,Kanskje en annen gang.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.",,Kanske en annan gång.,Belki başka bir zaman. Good news from the Front for a change. Macil sent you for a reward and training. He's instructed me to give them to you.,TXT_DLG_SCRIPT02_D6064_GOODN,〃 (After destroying the crystal in the Power Station),,,"Pro jednou dobré zprávy od Fronty. Macil tě poslal pro odměnu a trénink. Řekl mi, že ti to mám předat.",Gode nyheder fra fronten til en forandring. Macil har sendt dig for at få en belønning og træning. Han har instrueret mig om at give dig dem.,"Gute Nachrichten von der Front zur Abwechslung. Macil lässt dir eine Belohnung und Training zukommen. Er hat mir aufgetragen, es dir zu geben.",,"Estas bonaj novaĵoj el la Fronto, laŭ la kutimo. Macil sendis oron kaj trejniĝon por vi. Li instrukciis, ke mi donu ilin al vi.","Buenas noticias desde el Frente, para variar. Macil te manda oro y entrenamiento. Me ha solicitado dártelos.","Buenas noticias desde el Frente, para variar. Macil te manda oro y entrenamiento. Me solicitó dártelos.",Hyviä uutisia Rintamalta vaihteeksi. Macil kutsui sinut saamaan minun kauttani palkkion ja koulutusta.,Des bonnes nouvelles du Front pour une fois. Macil t'a envoyé pour une récompense et de l'entraînement. Il m'a instruit de te les procurer.,"Jó hírekkel szolgálhatok a frontról a változatosság kedvéért. Macil érted küldött egy kis jutalommal a kiképzésért cserébe. Azt parancsolta, hogy adjam oda őket.",Buone notizie dal Fronte per una volta. Macil ti ha inviato una ricompensa e predisposto per l'addestramento. Mi ha raccomandato di procurarteli.,"フロントから朗報だ。 マシルは貴方に報酬と訓練の許可を送った。 -私はそれらを貴方に渡す為に持って来た。","프론트로부터 좋은 소식을 들었어. 마실 사령관님이 보상과 훈련받을 특권을 당신에게 전해주라는군. 이미 준비된 것 같으니, 시작할까?",Goed nieuws van het Front voor de verandering. Macil heeft je gestuurd voor een beloning en training. Hij heeft me geïnstrueerd om ze aan jou te geven.,Gode nyheter fra fronten til en forandring. Macil sendte deg for belønning og trening. Han ba meg gi dem til deg.,"Dobre wieści od Frontu dla odmiany. Macil wysłał cię po nagrodę i na trening. Poinstruował mnie, aby ci je dostarczyć.",Boas notícias da Frente pra variar. O Macil enviou uma recompensa e treinamento para você. Ele me deu ordens para passá-los a você.,,"În sfârșit, niște vești bune venite de pe Front. Ai venit de la Macil pentru o recompensă și niste instruire este? Mi-a ordonat ca eu să ți le ofer.","Наконец-то, хорошие новости от Сопротивления. Ты пришёл от Мэйсила за наградой и обучением. Он распорядился, чтобы я дал тебе их.",,Değişiklik olsun diye cepheden iyi haberler var. Macil seni ödül ve eğitim için gönderdi. Onları sana vermemi emretti. -Thanks.,TXT_RPLY0_SCRIPT02_D6064_THANK,〃 (〃),,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,ありがとう。,고맙습니다.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Спасибо.,,Teşekkürler. -Glad to be of service.,TXT_RYES0_SCRIPT02_D6064_GLADT,〃 (〃),,,Rád jsem pomohl.,Glad for at være til tjeneste.,Es war mir eine Freude dir zu Diensten zu sein,,Estas plezuro esti serva.,Un placer atenderte.,,Onneksi voin olla avuksi.,Ravi de vous avoir servi.,Szíves örömest segítek.,Felice di essere utile.,感謝する。,도와줄 수 있어서 영광이야.,Blij om van dienst te zijn.,Glad for å stå til tjeneste.,"Cieszę się, że mogłem pomóc.",É um prazer serví-los.,,Mă bucur să fiu util.,Рад помочь.,,Hizmet edebildiğime sevindim. +私はそれらを貴方に渡す為に持って来た。","프론트로부터 좋은 소식을 들었어. 마실 사령관님이 보상과 훈련받을 특권을 당신에게 전해주라는군. 이미 준비된 것 같으니, 시작할까?",Goed nieuws van het Front voor de verandering. Macil heeft je gestuurd voor een beloning en training. Hij heeft me geïnstrueerd om ze aan jou te geven.,Gode nyheter fra fronten til en forandring. Macil sendte deg for belønning og trening. Han ba meg gi dem til deg.,"Dobre wieści od Frontu dla odmiany. Macil wysłał cię po nagrodę i na trening. Poinstruował mnie, aby ci je dostarczyć.",Boas notícias da Frente pra variar. O Macil enviou uma recompensa e treinamento para você. Ele me deu ordens para passá-los a você.,,"În sfârșit, niște vești bune venite de pe Front. Ai venit de la Macil pentru o recompensă și niste instruire este? Mi-a ordonat ca eu să ți le ofer.","Наконец-то, хорошие новости от Сопротивления. Ты пришёл от Мэйсила за наградой и обучением. Он распорядился, чтобы я дал тебе их.",,Goda nyheter från fronten för en gångs skull. Macil skickade dig för en belöning och utbildning. Han har instruerat mig att ge dig dem.,Değişiklik olsun diye cepheden iyi haberler var. Macil seni ödül ve eğitim için gönderdi. Onları sana vermemi emretti. +Thanks.,TXT_RPLY0_SCRIPT02_D6064_THANK,〃 (〃),,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,ありがとう。,고맙습니다.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Спасибо.,,Tack.,Teşekkürler. +Glad to be of service.,TXT_RYES0_SCRIPT02_D6064_GLADT,〃 (〃),,,Rád jsem pomohl.,Glad for at være til tjeneste.,Es war mir eine Freude dir zu Diensten zu sein,,Estas plezuro esti serva.,Un placer atenderte.,,Onneksi voin olla avuksi.,Ravi de vous avoir servi.,Szíves örömest segítek.,Felice di essere utile.,感謝する。,도와줄 수 있어서 영광이야.,Blij om van dienst te zijn.,Glad for å stå til tjeneste.,"Cieszę się, że mogłem pomóc.",É um prazer serví-los.,,Mă bucur să fiu util.,Рад помочь.,,Glad att vara till tjänst.,Hizmet edebildiğime sevindim. "All right, here's a few pointers on what to do: don't get in the way of Crusaders: firing short bursts from your assault gun keeps it on target.",TXT_DLG_SCRIPT02_D7580_ALLRI,〃 (〃),,,"Jistě, tady je pár rad, co dělat: Nepleť se do cesty Křižákům. Střílení krátkých dávek z pušky ti zaručí přesnost.",,"Also, hier hast du ein paar Hinweise: Gerate nicht ins Visier der Ordensritter: Wenn du kurze Feuerstöße mit deinem Sturmgewehr abgibst, triffst du besser.",,"Bone, jen kelkaj konsiloj. Ne staru antaŭ Krucistoj; pafi mallongajn ŝprucojn per la sturmofusilo estas sufiĉe por teni vian celon.","Muy bien, aquí algunos consejos. No te pongas frente a los Cruzados: disparar ráfagas cortas con el fusil de asalto basta para mantenerte en el blanco.",,"No niin, ihan vain ohjeeksi: Pysy pois ristiretkeläisten tieltä; hallituilla rynnäkkökiväärin sarjoilla pidät kiväärin tähtäimissäsi.","Bon, voilà quelques conseils sur ce que tu devrais faire: Ne vas pas te mêler aux croisés. Tirer en courte rafales avec le fusil d'assaut te permet de rester sur ta cible.","Na jól van, itt egy kis útbaigazítás neked: Ne kerülj a keresztesek útjába: Gépfegyveredből rövid sorozatokat leadva pontosabban tudsz célozni.","Bene, ecco alcuni consigli sul da farsi: non metterti davanti ai Crociati: sparare singole raffiche con il tuo fucile d'assalto fa si che l'arma rimane sul bersaglio.","オーライ、 それで何をすべきかについて説明がある :クルセイダーの斜線に立つな -:アサルトガンを遠くから的に向かって撃て",좋아. 먼저 배워둬야 할 것은: 크루세이더를 제압하기 위해선 가능한 한 멀리서 상대해야 해. 그리고 돌격소총의 방아쇠를 한 번 누르면 정확한 3 점발사격이 가능하지. ,"Oké, hier zijn een paar tips over wat je moet doen: sta kruisvaarders niet in de weg: korte uitbarstingen van je aanvalsgeweer houden het doelwit.","Greit, her er noen tips om hva du skal gjøre: Ikke kom i veien for korsfarerne. Korte salver fra angrepsgeværet holder det på målet.","W porządku, oto kilka wskazówek co trzeba robić: nie wchodzić w drogę Krzyżowcom: strzelanie krótkimi seriami z karabinu szturmowego utrzymuje cel.","Muito bem, tenho alguns conselhos pra te dar: não se meta na frente dos Cruzados: atire rajadas curtas com o seu fuzil de assalto para ter mais precisão.",,"În regulă, uite niște puncte de reper: Nu te băga în calea Cruciaților: Focurile scurte ale armei tale de asalt sunt cele mai eficiente.","Отлично, вот несколько советов: не попадайся под ноги крестоносцам; из штурмовой винтовки лучше всего стрелять короткими очередями.",,"Pekala, işte size ne yapmanız gerektiğine dair birkaç ipucu: Haçlıların yoluna çıkmayın: saldırı silahınızla kısa aralıklarla ateş etmek onu hedefte tutar." -Is that it?,TXT_RPLY0_SCRIPT02_D7580_ISTHA,〃 (〃),,,To je všechno?,Er det det?,War es das?,,Ĉu nenio alia?,¿Eso es todo?,,Siinä kaikki?,C'est tout?,Ennyi?,Tutto qui?,そうなのか?,그게 답니까?,Is dat het?,Var det alt?,To wszystko?,Só isso?,,Asta e?,И всё?,,Bu kadar mı? +:アサルトガンを遠くから的に向かって撃て",좋아. 먼저 배워둬야 할 것은: 크루세이더를 제압하기 위해선 가능한 한 멀리서 상대해야 해. 그리고 돌격소총의 방아쇠를 한 번 누르면 정확한 3 점발사격이 가능하지. ,"Oké, hier zijn een paar tips over wat je moet doen: sta kruisvaarders niet in de weg: korte uitbarstingen van je aanvalsgeweer houden het doelwit.","Greit, her er noen tips om hva du skal gjøre: Ikke kom i veien for korsfarerne. Korte salver fra angrepsgeværet holder det på målet.","W porządku, oto kilka wskazówek co trzeba robić: nie wchodzić w drogę Krzyżowcom: strzelanie krótkimi seriami z karabinu szturmowego utrzymuje cel.","Muito bem, tenho alguns conselhos pra te dar: não se meta na frente dos Cruzados: atire rajadas curtas com o seu fuzil de assalto para ter mais precisão.",,"În regulă, uite niște puncte de reper: Nu te băga în calea Cruciaților: Focurile scurte ale armei tale de asalt sunt cele mai eficiente.","Отлично, вот несколько советов: не попадайся под ноги крестоносцам; из штурмовой винтовки лучше всего стрелять короткими очередями.",,"Okej, här är några tips om vad du ska göra: Ställ dig inte i vägen för korsfarare: Genom att avfyra korta salvor från ditt stormgevär håller du det i mål.","Pekala, işte size ne yapmanız gerektiğine dair birkaç ipucu: Haçlıların yoluna çıkmayın: saldırı silahınızla kısa aralıklarla ateş etmek onu hedefte tutar." +Is that it?,TXT_RPLY0_SCRIPT02_D7580_ISTHA,〃 (〃),,,To je všechno?,Er det det?,War es das?,,Ĉu nenio alia?,¿Eso es todo?,,Siinä kaikki?,C'est tout?,Ennyi?,Tutto qui?,そうなのか?,그게 답니까?,Is dat het?,Var det alt?,To wszystko?,Só isso?,,Asta e?,И всё?,,Är det så?,Bu kadar mı? "Look, you'll learn more later.",TXT_RYES0_SCRIPT02_D7580_LOOKY,〃 (〃),,,"Hele, víc se toho naučíš pak.","Hør, du vil få mere at vide senere.",Fürs Erste ja. Du wirst später noch mehr lernen.,,"Nu, vi lernos pli poste.","Ya aprenderás más después.","Ya vas a aprender -más después.",Saat oppia kyllä lisää myöhemmin.,Tu en apprendras davantage plus tard.,"Nézd, később majd többet fogsz megtudni.","Guarda, imparerai di più dopo.",良し、後でもっと学べるぞ。,나중에 알려줄게.,"Kijk, je komt er later meer over te weten.",Du får vite mer senere.,"Zobacz, później nauczysz się więcej.","Olha, você vai aprender mais depois.",,"Uite, o să afli mai multe mai târziu.","Позже узнаешь больше, хорошо?",,"Bak, daha sonra daha fazlasını öğreneceksin." -"I think I can convert a flamethrower from one of the Crusaders for use by a human. Oh, anything else I can get you?",TXT_DLG_SCRIPT02_D9096_ITHIN,〃 (〃),,,"Myslím, že bych mohl předělat plamenomet z jednoho z těch Křižáků pro použití člověkem. No, budeš si ještě něco přát?","Jeg tror, jeg kan omdanne en flammekaster fra en af korsfarerne til brug for et menneske. Er der andet, jeg kan skaffe dig?","Ich denke ich kann einen Flammenwerfer von einen der Ordensritter umbauen, damit ein Mensch ihn benutzen kann. Oh, kann ich dir sonst noch etwas besorgen?",,"Mi kredas, ke mi povas modifi la flamĵetilon de Krucisto, por ke homo povu uzi ĝin. Ha, ĉu io alia, kion mi povas doni al vi?","Creo que puedo modificar el lanzallamas de alguno de los Cruzados para que lo pueda usar un humano. Ah, ¿algo más para ofrecerte?",,Luulen pystyväni tekemään ristiretkeläisen liekinheittimestä ihmiskäyttöisen. Voinko olla vielä jotenkin muuten avuksi?,Je crois que je peux convertir un lance-flammes de croisé pour être utilisé par un humain. Je peux faire quelque chose d'autre pour vous?,"Azt hiszem, ha az egyik keresztesről leszednénk egy lángszórót, azt át tudnám alakítani emberi használatra. Ó, még valamit tehetek érted?","Penso di poter convertire un lanciafiamme da uno dei Crociati per essere usato da un umano. Oh, desideri qualcos'altro?","俺ならクルセイダー専用の火炎放射器を +más después.",Saat oppia kyllä lisää myöhemmin.,Tu en apprendras davantage plus tard.,"Nézd, később majd többet fogsz megtudni.","Guarda, imparerai di più dopo.",良し、後でもっと学べるぞ。,나중에 알려줄게.,"Kijk, je komt er later meer over te weten.",Du får vite mer senere.,"Zobacz, później nauczysz się więcej.","Olha, você vai aprender mais depois.",,"Uite, o să afli mai multe mai târziu.","Позже узнаешь больше, хорошо?",,Du kommer att få veta mer senare.,"Bak, daha sonra daha fazlasını öğreneceksin." +"I think I can convert a flamethrower from one of the Crusaders for use by a human. Oh, anything else I can get you?",TXT_DLG_SCRIPT02_D9096_ITHIN,〃 (〃),,,"Myslím, že bych mohl předělat plamenomet z jednoho z těch Křižáků pro použití člověkem. No, budeš si ještě něco přát?","Jeg tror, jeg kan omdanne en flammekaster fra en af korsfarerne til brug for et menneske. Er der andet, jeg kan skaffe dig?","Ich denke ich kann einen Flammenwerfer von einen der Ordensritter umbauen, damit ein Mensch ihn benutzen kann. Oh, kann ich dir sonst noch etwas besorgen?",,"Mi kredas, ke mi povas modifi la flamĵetilon de Krucisto, por ke homo povu uzi ĝin. Ha, ĉu io alia, kion mi povas doni al vi?","Creo poder modificar el lanzallamas de alguno de los Cruzados para que lo pueda usar un humano. Ah, ¿algo más para ofrecerte?",,Luulen pystyväni tekemään ristiretkeläisen liekinheittimestä ihmiskäyttöisen. Voinko olla vielä jotenkin muuten avuksi?,Je crois que je peux convertir un lance-flammes de croisé pour être utilisé par un humain. Je peux faire quelque chose d'autre pour vous?,"Azt hiszem, ha az egyik keresztesről leszednénk egy lángszórót, azt át tudnám alakítani emberi használatra. Ó, még valamit tehetek érted?","Penso di poter convertire un lanciafiamme da uno dei Crociati per essere usato da un umano. Oh, desideri qualcos'altro?","俺ならクルセイダー専用の火炎放射器を 誰でも使える様に作り変えられるだろう。 ああ、他に何か必要か?",크루세이더가 사용하는 화염방사기를 사람들이 다룰 수 있도록 개조할 수 있을 것 같아. 그래서... 뭘 원해?,"Ik denk dat ik een vlammenwerper van een van de kruisvaarders kan bekeren voor gebruik door een mens. Oh, kan ik nog iets anders voor je halen?",Jeg tror jeg kan konvertere en flammekaster fra en av korsfarerne til å brukes av et menneske. Noe annet jeg kan gi deg?,"Myślę, że mogę przerobić miotacz ognia jednego z Krzyżowców, by mógł z niego korzystać człowiek. Oh, czy mogę coś jeszcze dla ciebie zrobić?","Acho que eu consigo converter o lança-chamas de um dos Cruzados para ser usado por um humano. Ah, posso te ajudar com mais alguma coisa?",,"Cred că pot converti aruncătorul de flăcări de la un Cruciat pentru a putea fi folosit de oameni. Oh, mai pot să-ți aduc ceva?","Думаю, я смогу приспособить огнемёт для ручного использования. А, ты что-то ещё хотел? -",,Sanırım Haçlılardan birinin alev silahını bir insan tarafından kullanılmak üzere dönüştürebilirim. Sana verebileceğim başka bir şey var mı? -Flamethrower.,TXT_RPLY0_SCRIPT02_D9096_FLAME,〃 (〃),,,Plamenomet.,Flammekaster.,Flammenwerfer,,Flamĵetilon,Lanzallamas.,,Liekinheitin.,Lance-flammes.,Lángszóró.,Lanciafiamme.,火炎放射器,화염방사기?,Vlammenwerper.,Flammekaster.,Miotacz Ognia,Lança-chamas.,,Aruncător de flăcări.,Огнемёт.,,Alev makinesi. +",,"Jag tror att jag kan konvertera en eldkastare från en av korsfararna så att den kan användas av en människa. Åh, något annat jag kan ge dig?",Sanırım Haçlılardan birinin alev silahını bir insan tarafından kullanılmak üzere dönüştürebilirim. Sana verebileceğim başka bir şey var mı? +Flamethrower.,TXT_RPLY0_SCRIPT02_D9096_FLAME,〃 (〃),,,Plamenomet.,Flammekaster.,Flammenwerfer,,Flamĵetilon,Lanzallamas.,,Liekinheitin.,Lance-flammes.,Lángszóró.,Lanciafiamme.,火炎放射器,화염방사기?,Vlammenwerper.,Flammekaster.,Miotacz Ognia,Lança-chamas.,,Aruncător de flăcări.,Огнемёт.,,Flamkastare,Alev makinesi. "I knew that'd work! Here you go, take her for a spin!",TXT_RYES0_SCRIPT02_D9096_IKNEW,〃 (〃),,,"Věděl jsem, že to bude fungovat! Tady máš, pořádně ho rozpal!","Jeg vidste, at det ville virke! Værsgo, tag en tur med hende!","Ich wusste das würde funktionieren! Bitte sehr, probiere ihn mal aus!",,"Mi sciis, ke tio sukcesus! Jen ĝi. Provu ĝin!","¡Sabía que iba a resultar! -Aquí tienes. ¡Pruébalo!",,"Tiesin sen toimivan! Anna palaa, vie se kierrokselle!",Je savais que ça marcherait! Prends-le et va donc l'essayer!,"Tudtam, hogy ez működni fog! Nesze vidd el egy körre!",Lo sapevo che avrebbe funzionato! Prendilo e vai a provarlo!,よくやってくれた! どうよ、このアツアツな子を!,"역시 잘 작동할 줄 알았어! 여기, 화염방사기야. 한번 놈들에게 사용해봐!","Ik wist dat dat zou werken! Alsjeblieft, neem haar mee voor een ritje!","Jeg visste det ville fungere! Vær så god, ta en tur med den!","Wiedziałem, że zadziała! Masz, przetestuj ją!","Eu sabia que daria certo! Toma, leva pra testar!",,"Stiam că va funcționa! Uite, ia-o la o tură!","Я и не сомневался, что всё получится! Держи, испробуй его на ком-нибудь!",,"Bunun işe yarayacağını biliyordum! Al bakalım, bir tur at!" +Toma. ¡Pruébalo!",,"Tiesin sen toimivan! Anna palaa, vie se kierrokselle!",Je savais que ça marcherait! Prends-le et va donc l'essayer!,"Tudtam, hogy ez működni fog! Nesze vidd el egy körre!",Lo sapevo che avrebbe funzionato! Prendilo e vai a provarlo!,よくやってくれた! どうよ、このアツアツな子を!,"역시 잘 작동할 줄 알았어! 여기, 화염방사기야. 한번 놈들에게 사용해봐!","Ik wist dat dat zou werken! Alsjeblieft, neem haar mee voor een ritje!","Jeg visste det ville fungere! Vær så god, ta en tur med den!","Wiedziałem, że zadziała! Masz, przetestuj ją!","Eu sabia que daria certo! Toma, leva pra testar!",,"Stiam că va funcționa! Uite, ia-o la o tură!","Я и не сомневался, что всё получится! Держи, испробуй его на ком-нибудь!",,"Jag visste att det skulle fungera! Varsågod, ta en sväng med henne!","Bunun işe yarayacağını biliyordum! Al bakalım, bir tur at!" "Listen, I can't make anything without the right parts!",TXT_RNO0_SCRIPT02_D9096_LISTE,〃 (〃),,,"Poslyš, bez použitelných součástek ti nic nepostavím!","Hør, jeg kan ikke lave noget uden de rigtige dele!","Hör zu, ohne die richtigen Teile kann ich dir nichts machen!",,"Nu, mi povas fari nenion sen la ĝustaj partoj!","A ver, ¡no puedo hacer nada -sin las partes correctas!",,"Kuules, ilman oikeita osia en pysty tekemään mitään!","Ecoute, je ne peux pas faire quoi que ce soit si je n'ai pas les pièces dont j'ai besoin!","Figyu, a megfelelő alkatrészek nélkül semmit sem tudok tenni.","Senti, non posso creare nulla senza i pezzi che mi servono!",部品が無ければ何も出来ない!,"이봐, 제대로 된 부품 없이는 아무 것도 할 수 없다고!","Luister, ik kan niets maken zonder de juiste onderdelen!",Jeg kan ikke lage noe uten de rette delene!,"Słuchaj, nie mogę nic zrobić bez właściwych części!","Escuta, eu não consigo fazer qualquer coisa sem as peças certas!",,"Ascultă, nu pot face nimic fără părțile corespunzătoare!","Слушай, у меня нет нужных деталей!",,"Dinle, doğru parçalar olmadan hiçbir şey yapamam!" -Assault gun,TXT_RPLY1_SCRIPT02_D9096_ASSAU,〃 (〃),,,Útočnou pušku,Angrebsvåben,Sturmgewehr,,Sturmofusilon,Fusil de asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,Flammekaster.,Karabin Szturmowy,Fuzil de assalto,,Armă de asalt,Штурмовую винтовку,,Saldırı silahı -"Well, here you go sir!",TXT_RYES1_SCRIPT02_D9096_WELLH,〃 (〃),,,"Tak tady máte, pane!","Værsgo, sir!","Alles klar, bitteschön!",,"Nu, jen, sinjoro!","¡Bueno, aquí tiene, caballero!",,"Kas tässä, hyvä herra!","Voilà pour vous, monsieur!","Nos, parancsoljon!","Bene, ecco qua signore!",ほら、毎度あり!,여기 대령이요!,"Nou, alsjeblieft, meneer!",Vær så god!,Oto jest proszę pana!,"Bem, aqui está, senhor!",,"Poftiți, domnule!",Забирай!,,Buyurun efendim! +sin las partes correctas!",,"Kuules, ilman oikeita osia en pysty tekemään mitään!","Ecoute, je ne peux pas faire quoi que ce soit si je n'ai pas les pièces dont j'ai besoin!","Figyu, a megfelelő alkatrészek nélkül semmit sem tudok tenni.","Senti, non posso creare nulla senza i pezzi che mi servono!",部品が無ければ何も出来ない!,"이봐, 제대로 된 부품 없이는 아무 것도 할 수 없다고!","Luister, ik kan niets maken zonder de juiste onderdelen!",Jeg kan ikke lage noe uten de rette delene!,"Słuchaj, nie mogę nic zrobić bez właściwych części!","Escuta, eu não consigo fazer qualquer coisa sem as peças certas!",,"Ascultă, nu pot face nimic fără părțile corespunzătoare!","Слушай, у меня нет нужных деталей!",,"Lyssna, jag kan inte göra något utan rätt delar!","Dinle, doğru parçalar olmadan hiçbir şey yapamam!" +Assault gun,TXT_RPLY1_SCRIPT02_D9096_ASSAU,〃 (〃),,,Útočnou pušku,Angrebsvåben,Sturmgewehr,,Sturmofusilon,Fusil de asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,Flammekaster.,Karabin Szturmowy,Fuzil de assalto,,Armă de asalt,Штурмовую винтовку,,Anfallspistol,Saldırı silahı +"Well, here you go sir!",TXT_RYES1_SCRIPT02_D9096_WELLH,〃 (〃),,,"Tak tady máte, pane!","Værsgo, sir!","Alles klar, bitteschön!",,"Nu, jen, sinjoro!","¡Bueno, aquí tiene, caballero!",,"Kas tässä, hyvä herra!","Voilà pour vous, monsieur!","Nos, parancsoljon!","Bene, ecco qua signore!",ほら、毎度あり!,여기 대령이요!,"Nou, alsjeblieft, meneer!",Vær så god!,Oto jest proszę pana!,"Bem, aqui está, senhor!",,"Poftiți, domnule!",Забирай!,,"Här har du, sir!",Buyurun efendim! "Obviously, you can't afford that right now.",TXT_RNO1_SCRIPT02_D9096_OBVIO,〃 (〃),,,Tu si teď opravdu nemůžeš dovolit.,Du har tydeligvis ikke råd til den lige nu.,Offensichtlich kannst du dir das im Moment nicht leisten.,,"Evidente vi nun ne havas sufiĉe da mono.","Obviamente no te -alcanza por ahora.",,Sinulla ei selvästikään ole siihen nyt varaa.,"Manifestement, vous ne pouvez pas vous l'offrir.","Egyértelmű, hogy ezt nem tudod most kifizetni.","Ovviamente, ora non te lo puoi permettere.",明らかに、今買える余裕は無い。,"당연하겠지만, 아직 가질 수가 없겠네.",Dat kunt je zich natuurlijk nu niet veroorloven.,Det har du selvsagt ikke råd til akkurat nå!,"Oczywiście, nie możesz teraz tego kupić.",Obviamente você não pode comprar isso agora.,,"Evident, nu-ți poți permite asta chiar acum.","Похоже, тебе это не по карману.",,Belli ki şu anda bunu karşılayamazsınız. -Clip of bullets,TXT_RPLY2_SCRIPT02_D9096_CLIPO,〃 (〃),,,Zásobník nábojů,Et patron-klip,Gewehrmunition.,,Magazenon,Un cargador,,Luotilipas,Chargeur de balles,Egy tár töltény.,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler.,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов,,Mermi şarjörü -Thanks.,TXT_RYES2_SCRIPT02_D9096_THANK,〃 (〃),,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고마워.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Teşekkürler. -"Come on, 10 gold.",TXT_RNO2_SCRIPT02_D9096_COMEO,〃 (〃),,,"No tak, jen deset zlatých.","Kom nu, 10 guld.","Na komm, 10 Gold.",,"Nu, ĝi kostas 10 da oro.","Vamos, que son 10 de oro.",,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Rajta, 10 aranyat.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,"이봐, 그건 10 골드짜리라고.","Kom op, 10 goud.","Kom igjen, 10 gull.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.",,"Hadi, 10 altın." -Ammo box,TXT_RPLY3_SCRIPT02_D9096_AMMOB,〃 (〃),,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Municikeston,Caja de municiones,,Ammuslaatikko,Bôite de balles,Lőszeres doboz.,Scatola di munizioni,弾薬箱,돌격소총 탄약 박스,Munitie doos,Ammunisjonsboks,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов,,Cephane kutusu -Here's your ammo.,TXT_RYES3_SCRIPT02_D9096_HERES,〃 (〃),,,Tady je tvá munice.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 탄약.,Hier is je munitie.,Her er ammunisjonen din.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны.,,İşte cephanen. +alcanza por ahora.",,Sinulla ei selvästikään ole siihen nyt varaa.,"Manifestement, vous ne pouvez pas vous l'offrir.","Egyértelmű, hogy ezt nem tudod most kifizetni.","Ovviamente, ora non te lo puoi permettere.",明らかに、今買える余裕は無い。,"당연하겠지만, 아직 가질 수가 없겠네.",Dat kunt je zich natuurlijk nu niet veroorloven.,Det har du selvsagt ikke råd til akkurat nå!,"Oczywiście, nie możesz teraz tego kupić.",Obviamente você não pode comprar isso agora.,,"Evident, nu-ți poți permite asta chiar acum.","Похоже, тебе это не по карману.",,Uppenbarligen har du inte råd med den just nu.,Belli ki şu anda bunu karşılayamazsınız. +Clip of bullets,TXT_RPLY2_SCRIPT02_D9096_CLIPO,〃 (〃),,,Zásobník nábojů,Et patron-klip,Gewehrmunition.,,Magazenon,Un cargador,,Luotilipas,Chargeur de balles,Egy tár töltény.,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler.,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов,,Kulor i ett klipp,Mermi şarjörü +Thanks.,TXT_RYES2_SCRIPT02_D9096_THANK,〃 (〃),,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고마워.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Tack.,Teşekkürler. +"Come on, 10 gold.",TXT_RNO2_SCRIPT02_D9096_COMEO,〃 (〃),,,"No tak, jen deset zlatých.","Kom nu, 10 guld.","Na komm, 10 Gold.",,"Nu, ĝi kostas dek da oro.","Vamos, que son diez de oro.",,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Rajta, 10 aranyat.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,"이봐, 그건 10 골드짜리라고.","Kom op, 10 goud.","Kom igjen, 10 gull.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.",,"Kom igen, 10 guld.","Hadi, 10 altın." +Ammo box,TXT_RPLY3_SCRIPT02_D9096_AMMOB,〃 (〃),,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Munici-keston,Caja de municiones,,Ammuslaatikko,Bôite de balles,Lőszeres doboz.,Scatola di munizioni,弾薬箱,돌격소총 탄약 박스,Munitie doos,Ammunisjonsboks,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов,,Ammunitionslåda,Cephane kutusu +Here's your ammo.,TXT_RYES3_SCRIPT02_D9096_HERES,〃 (〃),,,Tady je tvá munice.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 탄약.,Hier is je munitie.,Her er ammunisjonen din.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны.,,Här är din ammunition.,İşte cephanen. Maybe some other time. Goodbye!,TXT_RNO3_SCRIPT02_D9096_MAYBE,〃 (〃),,,Možná někdy jindy. Nashledanou!,Måske en anden gang. Farvel!,Vielleicht ein anderes mal. Auf Wiedersehen!,,Eble alimomente. Ĝis!,"Puede que en otro momento. ¡Adiós!","Puede que en otro -momento. ¡Nos vemos!",Ehkä jokin toinen aika. Näkemiin!,"Peut être une autre fois, au revoir!",Talán majd valamikor máskor. Viszlát!,Sarà per un'altra volta. Arrivederci!,またの機会に、じゃあな!,다음번에 돈을 챙기고 예기하자. 잘 가!,Misschien een andere keer. Tot ziens!,Kanskje en annen gang. Adjø!,Może innym razem. Do widzenia!,Talvez outra hora. Até mais!,,Poate altădată. La revedere!,"Может, в другой раз. Пока!",,Belki başka bir zaman. Güle güle! +momento. ¡Nos vemos!",Ehkä jokin toinen aika. Näkemiin!,"Peut être une autre fois, au revoir!",Talán majd valamikor máskor. Viszlát!,Sarà per un'altra volta. Arrivederci!,またの機会に、じゃあな!,다음번에 돈을 챙기고 예기하자. 잘 가!,Misschien een andere keer. Tot ziens!,Kanskje en annen gang. Adjø!,Może innym razem. Do widzenia!,Talvez outra hora. Até mais!,,Poate altădată. La revedere!,"Может, в другой раз. Пока!",,Kanske en annan gång. Adjö!,Belki başka bir zaman. Güle güle! "Now that you have the flamethrower, is there anything else I can get you?",TXT_DLG_SCRIPT02_D10612_NOWTH,〃 (With flamethrower),,,"Teď když máš ten plamenomet, můžu pro tebe udělat něco jiného?","Nu hvor du har flammekasteren, er der så noget andet, jeg kan skaffe dig?","Jetzt wo du den Flammenwerfer hast, gibt es etwas anderes was ich dir besorgen kann?",,"Nun kiam vi havas la flamĵetilon, ĉu estas io alia, kion mi povus doni al vi?","Ahora que tienes el lanzallamas, ¿hay algo más que pueda ofrecerte?",,"Voisinko vielä jotenkin auttaa, nyt kun sinulla on liekinheitin?","Maintenant que vous avez le lance-flammes, est-ce que je peux faire quelque chose pour vous?","Most, hogy megkaptad a lángszórót is, tehetek még valamit érted?","Ora che hai il lanciafiamme, c'è qualcos'altro che ti posso dare?","火炎放射器を手に入れたが、 -他に必要な物はあるか?","이제 화염방사기를 얻었으니, 더 원하는 물품이 있나?","Nu je de vlammenwerper hebt, is er nog iets anders dat ik je kan bezorgen?","Nå som du har flammekasteren, er det noe annet jeg kan skaffe deg?","Jak już masz miotacz ognia, mogę coś jeszcze dla ciebie zrobić?",Agora que você tem o lança-chamas. Deseja mais alguma coisa?,,"Acum că ai aruncătorul de flăcări, mai pot să-ți aduc ceva?","Ну, огнемёт у тебя теперь есть. Могу я ещё чем-нибудь помочь?",,"Artık alev makinen olduğuna göre, sana verebileceğim başka bir şey var mı?" -Assault gun,TXT_RPLY0_SCRIPT02_D10612_ASSAU,〃 (〃),,,Útočnou pušku,Angrebsvåben,Sturmgewehr,,Sturmofusilon,Fusil de asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,Stormgevær.,Karabin Szturmowy,Fuzil de assalto,,Armă de asalt,Штурмовую винтовку,,Saldırı silahı -Here you go.,TXT_RYES0_SCRIPT02_D10612_HEREY,〃 (〃),,,Tu máš.,Værsgo.,Bitte sehr!,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Itt is van!,Ecco a te.,毎度あり。,여기 있어.,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Poftiți.,Забирай!,,Al bakalım. +他に必要な物はあるか?","이제 화염방사기를 얻었으니, 더 원하는 물품이 있나?","Nu je de vlammenwerper hebt, is er nog iets anders dat ik je kan bezorgen?","Nå som du har flammekasteren, er det noe annet jeg kan skaffe deg?","Jak już masz miotacz ognia, mogę coś jeszcze dla ciebie zrobić?",Agora que você tem o lança-chamas. Deseja mais alguma coisa?,,"Acum că ai aruncătorul de flăcări, mai pot să-ți aduc ceva?","Ну, огнемёт у тебя теперь есть. Могу я ещё чем-нибудь помочь?",,"Nu när du har flamkastaren, finns det något annat jag kan ge dig?","Artık alev makinen olduğuna göre, sana verebileceğim başka bir şey var mı?" +Assault gun,TXT_RPLY0_SCRIPT02_D10612_ASSAU,〃 (〃),,,Útočnou pušku,Angrebsvåben,Sturmgewehr,,Sturmofusilon,Fusil de asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,Stormgevær.,Karabin Szturmowy,Fuzil de assalto,,Armă de asalt,Штурмовую винтовку,,Anfallspistol,Saldırı silahı +Here you go.,TXT_RYES0_SCRIPT02_D10612_HEREY,〃 (〃),,,Tu máš.,Værsgo.,Bitte sehr!,,Jen.,Toma.,,Ole hyvä.,Voilà pour vous.,Itt is van!,Ecco a te.,毎度あり。,여기 있어.,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Poftiți.,Забирай!,,Varsågod.,Al bakalım. You can't afford that right now.,TXT_RNO0_SCRIPT02_D10612_YOUCA,〃 (〃),,,Tu si teď nemůžeš dovolit.,Den har du ikke råd til lige nu.,Das kannst du dir im Moment nicht leisten.,,"Vi nun ne havas -sufiĉe da oro.",No te alcanza por ahora.,,Sinulla ei ole siihen juuri nyt varaa.,Vous n'avez pas assez d'argent.,Erre jelenleg nincs pénzed.,Non hai abbastanza soldi.,今それを買える余裕は無い。,그럴 여유가 전혀 없는 것 같은데 말이지.,Dat kunt u zich nu niet veroorloven.,Det har du ikke råd til akkurat nå.,Nie możesz teraz tego kupić.,Você não pode comprar isso no momento.,,Nu-ți poți permite asta încă.,"Похоже, тебе это не по карману.",,Şu anda bunu karşılayamazsın. -Clip of bullets,TXT_RPLY1_SCRIPT02_D10612_CLIPO,〃 (〃),,,Zásobník nábojů,Et patron-klip,Gewehrmunition.,,Magazenon,Un cargador,,Luotilipas,Chargeur de balles,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler.,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов,,Mermi şarjörü -Thanks.,TXT_RYES1_SCRIPT02_D10612_THANK,〃 (〃),,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고마워.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Teşekkürler. -"Come on, 10 gold.",TXT_RNO1_SCRIPT02_D10612_COMEO,〃 (〃),,,"No tak, jen deset zlatých.","Kom nu, 10 guld.","Komm schon, 10 Gold.",,"Nu, ĝi kostas 10 da oro.","Vamos, que son 10 de oro.",,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Gyerünk, 10 aranyat.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,"이봐, 10 골드를 먼저 달라고.","Kom op, 10 goud.","Kom igjen, 10 gull.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.",,"Hadi, 10 altın." -Ammo box,TXT_RPLY2_SCRIPT02_D10612_AMMOB,〃 (〃),,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Municikeston,Caja de municiones,,Ammuslaatikko,Boîte de balles,Töltényes doboz,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Ammunisjonsboks,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов,,Cephane kutusu -Here's your ammo.,TXT_RYES2_SCRIPT02_D10612_HERES,〃 (〃),,,Tady je tvá munice.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a töltényed.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 네 탄약이야.,Hier is je munitie.,Her er ammunisjonen din.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны.,,İşte cephanen. +sufiĉe da oro.",No te alcanza por ahora.,,Sinulla ei ole siihen juuri nyt varaa.,Vous n'avez pas assez d'argent.,Erre jelenleg nincs pénzed.,Non hai abbastanza soldi.,今それを買える余裕は無い。,그럴 여유가 전혀 없는 것 같은데 말이지.,Dat kunt u zich nu niet veroorloven.,Det har du ikke råd til akkurat nå.,Nie możesz teraz tego kupić.,Você não pode comprar isso no momento.,,Nu-ți poți permite asta încă.,"Похоже, тебе это не по карману.",,Du har inte råd med den just nu.,Şu anda bunu karşılayamazsın. +Clip of bullets,TXT_RPLY1_SCRIPT02_D10612_CLIPO,〃 (〃),,,Zásobník nábojů,Et patron-klip,Gewehrmunition.,,Magazenon,Un cargador,,Luotilipas,Chargeur de balles,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler.,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов,,Kulor.,Mermi şarjörü +Thanks.,TXT_RYES1_SCRIPT02_D10612_THANK,〃 (〃),,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고마워.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Tack.,Teşekkürler. +"Come on, 10 gold.",TXT_RNO1_SCRIPT02_D10612_COMEO,〃 (〃),,,"No tak, jen deset zlatých.","Kom nu, 10 guld.","Komm schon, 10 Gold.",,"Nu, ĝi kostas dek da oro.","Vamos, que son diez de oro.",,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Gyerünk, 10 aranyat.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,"이봐, 10 골드를 먼저 달라고.","Kom op, 10 goud.","Kom igjen, 10 gull.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.",,"Kom igen, 10 guld.","Hadi, 10 altın." +Ammo box,TXT_RPLY2_SCRIPT02_D10612_AMMOB,〃 (〃),,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Munici-keston,Caja de municiones,,Ammuslaatikko,Boîte de balles,Töltényes doboz,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Ammunisjonsboks,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов,,Ammunitionslåda,Cephane kutusu +Here's your ammo.,TXT_RYES2_SCRIPT02_D10612_HERES,〃 (〃),,,Tady je tvá munice.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a töltényed.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 네 탄약이야.,Hier is je munitie.,Her er ammunisjonen din.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны.,,Här är din ammunition.,İşte cephanen. Maybe some other time.,TXT_RNO2_SCRIPT02_D10612_MAYBE,〃 (〃),,,Možná někdy jindy.,Måske en anden gang.,Vielleicht ein anderes mal.,,Eble alimomente.,"Puede que en -otro momento.",,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán Máskor.,Magari un'altra volta.,また後でな。,지금 말고. 아마도 나중에?,Misschien een andere keer.,Kanskje en annen gang.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.",,Belki başka bir zaman. +otro momento.",,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán Máskor.,Magari un'altra volta.,また後でな。,지금 말고. 아마도 나중에?,Misschien een andere keer.,Kanskje en annen gang.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.",,Kanske en annan gång.,Belki başka bir zaman. "Now that you have the flamethrower, is there anything else I can get you?",TXT_DLG_SCRIPT02_D12128_NOWTH,〃 (〃),,,"Teď, když máš ten plamenomet, můžu pro tebe udělat něco jiného?","Nu hvor du har flammekasteren, er der så noget andet, jeg kan give dig?","Jetzt wo du den Flammenwerfer hast, gibt es etwas anderes was ich dir besorgen kann?",,"Nun kiam vi havas la flamĵetilon, ĉu estas io alia, kion mi povus doni al vi?","Ahora que tienes el lanzallamas, ¿hay algo más que pueda ofrecerte?",,"Nyt kun sinulla on liekinheitin, saisiko sinulle vielä olla jotain muuta?","Maintenant que vous avez le lance-flammes, est-ce que je peux faire quelque chose pour vous?","Most, hogy van egy lángszóród, van bármi más, amivel szolgáhatok?","Ora che hai il lanciafiamme, c'è qualcos'altro che ti posso dare?","火炎放射器を手に入れたが、 -他に必要な物はあるか?","이제 화염방사기를 얻었으니, 더 원하는 물품이 있나?","Nu je de vlammenwerper hebt, is er nog iets anders dat ik je kan bezorgen?","Nå som du har flammekasteren, er det noe annet jeg kan gi deg?","Jak już masz miotacz ognia, mogę coś jeszcze dla ciebie zrobić?",Agora que você tem o lança-chamas. Deseja mais alguma coisa?,,"Acum că ai aruncătorul de flăcări, mai pot să-ți aduc ceva?","Ну, огнемёт у тебя теперь есть. Могу я ещё чем-нибудь помочь?",,"Artık alev silahın olduğuna göre, sana verebileceğim başka bir şey var mı?" -Clip of bullets,TXT_RPLY0_SCRIPT02_D12128_CLIPO,〃 (〃),,,Zásobník nábojů,Et patron-klip,Gewehrmunition.,,Magazenon,Un cargador,,Luotilipas,Chargeur de balles,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler.,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов,,Bir şarjör mermi -Thanks.,TXT_RYES0_SCRIPT02_D12128_THANK,〃 (〃),,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm,Grazie.,どうも。,고맙네.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Teşekkürler. -"Come on, 10 gold.",TXT_RNO0_SCRIPT02_D12128_COMEO,〃 (〃),,,"No tak, jen deset zlatých.","Kom nu, 10 guld.","Na komm, 10 Gold.",,"Nu, ĝi kostas 10 da oro.","Vamos, que son 10 de oro.",,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Gyerünk már, 10 aranyat.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,"이봐, 그건 10 골드라고.","Kom op, 10 goud.","Kom igjen, 10 gull.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.",,"Hadi, 10 altın." -Ammo box,TXT_RPLY1_SCRIPT02_D12128_AMMOB,〃 (〃),,,Krabici nábojů,Ammo box,Munitionsschachtel,,Municikeston,Caja de municiones,,Ammuslaatikko,Bôite de balles,Lőszeres doboz.,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Ammunisjonsboks,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов,,Cephane kutusu -Here's your ammo.,TXT_RYES1_SCRIPT02_D12128_HERES,〃 (〃),,,Tady je tvá munice.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 탄약이야.,Hier is je munitie.,Her er ammunisjonen din.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны.,,İşte cephanen. +他に必要な物はあるか?","이제 화염방사기를 얻었으니, 더 원하는 물품이 있나?","Nu je de vlammenwerper hebt, is er nog iets anders dat ik je kan bezorgen?","Nå som du har flammekasteren, er det noe annet jeg kan gi deg?","Jak już masz miotacz ognia, mogę coś jeszcze dla ciebie zrobić?",Agora que você tem o lança-chamas. Deseja mais alguma coisa?,,"Acum că ai aruncătorul de flăcări, mai pot să-ți aduc ceva?","Ну, огнемёт у тебя теперь есть. Могу я ещё чем-нибудь помочь?",,"Nu när du har flamkastaren, finns det något annat jag kan ge dig?","Artık alev silahın olduğuna göre, sana verebileceğim başka bir şey var mı?" +Clip of bullets,TXT_RPLY0_SCRIPT02_D12128_CLIPO,〃 (〃),,,Zásobník nábojů,Et patron-klip,Gewehrmunition.,,Magazenon,Un cargador,,Luotilipas,Chargeur de balles,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler.,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов,,Magasin med kulor,Bir şarjör mermi +Thanks.,TXT_RYES0_SCRIPT02_D12128_THANK,〃 (〃),,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm,Grazie.,どうも。,고맙네.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Tack.,Teşekkürler. +"Come on, 10 gold.",TXT_RNO0_SCRIPT02_D12128_COMEO,〃 (〃),,,"No tak, jen deset zlatých.","Kom nu, 10 guld.","Na komm, 10 Gold.",,"Nu, ĝi kostas dek da oro.","Vamos, que son diez de oro.",,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Gyerünk már, 10 aranyat.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,"이봐, 그건 10 골드라고.","Kom op, 10 goud.","Kom igjen, 10 gull.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.",,"Kom igen, 10 guld.","Hadi, 10 altın." +Ammo box,TXT_RPLY1_SCRIPT02_D12128_AMMOB,〃 (〃),,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Munici-keston,Caja de municiones,,Ammuslaatikko,Bôite de balles,Lőszeres doboz.,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Ammunisjonsboks,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов,,Ammunitionslåda,Cephane kutusu +Here's your ammo.,TXT_RYES1_SCRIPT02_D12128_HERES,〃 (〃),,,Tady je tvá munice.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 탄약이야.,Hier is je munitie.,Her er ammunisjonen din.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны.,,Här är din ammunition.,İşte cephanen. Maybe some other time.,TXT_RNO1_SCRIPT02_D12128_MAYBE,〃 (〃),,,Možná někdy jindy.,Måske en anden gang.,Vielleicht ein anderes Mal.,,Eble alimomente.,"Puede que en -otro momento.",,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán majd máskor.,Magari un'altra volta.,また後でな。,다음 번에 찾아와서 알려줘.,Misschien een andere keer.,Kanskje en annen gang.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.",,Belki başka bir zaman. -Phosphor grenades,TXT_RPLY2_SCRIPT02_D12128_PHOSP,,,,Fosforové granáty,Phosphor granater,Phosphorgranaten,,Fosforajn grenadojn,Granadas de fósforo,,Fosforikranaatteja,Grenades phosphoriques,Foszforgránátok,Granate al Fosforo.,白リングレネード弾,소이 유탄,Fosforgranaten,Fosforgranater,Fosforowe granaty,Granadas de fósforo,,Grenade cu fosfor,Фосфорные гранаты,,Fosfor bombaları -Thanks.,TXT_RYES2_SCRIPT02_D12128_THANK,,,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,どうも。,고마워.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Teşekkürler. -You don't have enough,TXT_RNO2_SCRIPT02_D12128_YOUDO,,,,Nemáš u sebe dost.,Du har ikke nok,Du hast nicht genug,,Vi ne havas sufiĉe da mono.,No te alcanza.,,Sinulla ei ole riittävästi,Vous n'avez pas assez d'argent.,Nincs elég pénzed,Non hai abbastanza soldi.,十分な額じゃない,충분치 않아.,Je hebt niet genoeg...,Du har ikke nok,Nie wystarczy ci.,Você não tem o suficiente.,,Nu ai suficiente,Тебе не хватает на них.,,Sende yeterince -Poison bolts,TXT_RPLY3_SCRIPT02_D12128_POISO,,,,Otrávené šípy,Giftbolte,Giftbolzen,,Venenajn sagojn,Flechas envenenadas,,Myrkkynuolia,Carreaux Empoisonnés,Mérgezett nyilak,Frecce avvelenate.,ポイズンボルト,맹독 볼트,Giftige bouten,Giftbolter,Zatrute bełty,Setas venenosas,,Bolțuri cu otravă,Отравленные болты,,Zehirli cıvatalar -Worth every gold!,TXT_RYES3_SCRIPT02_D12128_WORTH,,,,Ty se vyplatí!,Hvert et guld værd!,Jedes Goldstück wert!,,Ili valoras ĉiu monero!,¡Valen cada moneda de oro!,,Joka kolikon väärti!,Ca vaut son prix!,Minden aranyat megér,Ne vale la pena!,値段に合う価値だぜ!,아주 가치가 있는 것이지!,Elk goud waard!,Verdt hvert gull!,Warte każdych pieniędzy!,Vale cada moeda de ouro!,,Merită fiecare bănuț!,Они того стоят!,,Her altına değer! -"Come on, 200 gold!",TXT_RNO3_SCRIPT02_D12128_COMEO,,,,"No tak, 200 zlatých!","Kom nu, 200 guld!","Na komm, 200 Gold!",,"Nu, ili kostas 200 da oro.","Vamos, que son 200 de oro.",,"Antaa tulla, 200 kolikkoa!","Allez, 200 pièces!","Rajta, 200 arany!","Avanti, 200 pezzi d'oro!",頼むぜ、200ゴールドだぞ!,"이봐, 이건 200 골드라고!","Kom op, 200 goud!","Kom igjen, 200 gull!","No weź, 200 monet!","Vamos lá, 200 de ouro!",,"Haide, 200 monezi de aur!","Ну же, 200 золотых!",,"Hadi, 200 altın!" -I can't believe that I got stuck with this duty. They say that something evil came up out of this sewer gate... Now I get to stand here until it comes up again!,TXT_DLG_SCRIPT02_D13644_ICANT,MAP02: Between governor's mansion and town hall.,,,"Nemůžu uvěřit, že jsem zkysnul s touhle prací. Řekli mi, že z téhle brány vylezlo něco zlého... A teď tady mám stát, dokud to znovu nevyleze!","Jeg kan ikke tro, at jeg blev sat til at have denne opgave. De siger, at noget ondt kom op af denne kloakport... Nu skal jeg stå her, indtil det kommer op igen!","Ich kann's nicht glauben dass ich diesen Dienst hier machen muss. Sie haben gesagt, dass etwas Böses aus dem Kanalisationstor gekommen ist... Nun muss ich hier stehen, bis es wieder kommt!",,"Mi ne povas kredi, ke mi estas blokita kun ĉi tiu tasko: Oni diras, ke malbonaĵo aperis el ĉi tiu pordo... kaj mi nun devas resti ĉi tie ĝis ĝi reaperu!",No puedo creer que haya quedado esclavizado con esta tarea: Dicen que algo maligno salió de esta compuerta... ¡y ahora tengo que quedarme aquí hasta que salga de nuevo!,,"Uskomatonta, että minulle tungettiin tämä tehtävä. Sanovat, että jokin paha nousi ylös tästä viemäriluukusta... Ja minä saan seistä tässä, kunnes se nousee jälleen!",J'arrive pas à croire que je me retrouve coincé ici. On me raconte qu'une chose maléfique est sortie de cette barrière des égouts.. Maintenant je me retrouve planté ici jusqu'a ce qu'elle revienne!,"Nem hiszem el, hogy én kaptam ezt a melót. Úgy hírlik, hogy valami gonosz bukkant fel itt a csatorna kapuja felől... Most addig fogok itt állni, amíg újra fel nem bukkan.",Non posso credere di aver accettato questo lavoro. Dicono che qualcosa di malvagio sia sbucato dalla chiusa delle fogne... E io devo stare qui finché non ritorna! ,"私がこの勤務で足止めとは信じられん。 +otro momento.",,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán majd máskor.,Magari un'altra volta.,また後でな。,다음 번에 찾아와서 알려줘.,Misschien een andere keer.,Kanskje en annen gang.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.",,Kanske en annan gång.,Belki başka bir zaman. +Phosphor grenades,TXT_RPLY2_SCRIPT02_D12128_PHOSP,,,,Fosforové granáty,Phosphor granater,Phosphorgranaten,,Fosforajn grenadojn,Granadas de fósforo,,Fosforikranaatteja,Grenades phosphoriques,Foszforgránátok,Granate al Fosforo.,白リングレネード弾,소이 유탄,Fosforgranaten,Fosforgranater,Fosforowe granaty,Granadas de fósforo,,Grenade cu fosfor,Фосфорные гранаты,,Fosforgranater,Fosfor bombaları +Thanks.,TXT_RYES2_SCRIPT02_D12128_THANK,,,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,どうも。,고마워.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю.,,Tack.,Teşekkürler. +You don't have enough,TXT_RNO2_SCRIPT02_D12128_YOUDO,,,,Nemáš u sebe dost.,Du har ikke nok,Du hast nicht genug,,Vi ne havas sufiĉe da mono.,No te alcanza.,,Sinulla ei ole riittävästi,Vous n'avez pas assez d'argent.,Nincs elég pénzed,Non hai abbastanza soldi.,十分な額じゃない,충분치 않아.,Je hebt niet genoeg...,Du har ikke nok,Nie wystarczy ci.,Você não tem o suficiente.,,Nu ai suficiente,Тебе не хватает на них.,,Du har inte tillräckligt med,Sende yeterince +Poison bolts,TXT_RPLY3_SCRIPT02_D12128_POISO,,,,Otrávené šípy,Giftbolte,Giftbolzen,,Venenajn sagojn,Flechas envenenadas,,Myrkkynuolia,Carreaux Empoisonnés,Mérgezett nyilak,Frecce avvelenate.,ポイズンボルト,맹독 볼트,Giftige bouten,Giftbolter,Zatrute bełty,Setas venenosas,,Bolțuri cu otravă,Отравленные болты,,Giftbultar.,Zehirli cıvatalar +Worth every gold!,TXT_RYES3_SCRIPT02_D12128_WORTH,,,,Ty se vyplatí!,Hvert et guld værd!,Jedes Goldstück wert!,,"Ili valoras po +ĉiu monero!","¡Lo vale cada +moneda de oro!",,Joka kolikon väärti!,Ca vaut son prix!,Minden aranyat megér,Ne vale la pena!,値段に合う価値だぜ!,아주 가치가 있는 것이지!,Elk goud waard!,Verdt hvert gull!,Warte każdych pieniędzy!,Vale cada moeda de ouro!,,Merită fiecare bănuț!,Они того стоят!,,Värda varje guld!,Her altına değer! +"Come on, 200 gold!",TXT_RNO3_SCRIPT02_D12128_COMEO,,,,"No tak, 200 zlatých!","Kom nu, 200 guld!","Na komm, 200 Gold!",,"Nu, ili kostas 200 da oro.","Vamos, que son 200 de oro.",,"Antaa tulla, 200 kolikkoa!","Allez, 200 pièces!","Rajta, 200 arany!","Avanti, 200 pezzi d'oro!",頼むぜ、200ゴールドだぞ!,"이봐, 이건 200 골드라고!","Kom op, 200 goud!","Kom igjen, 200 gull!","No weź, 200 monet!","Vamos lá, 200 de ouro!",,"Haide, 200 monezi de aur!","Ну же, 200 золотых!",,"Kom igen, 200 guld!","Hadi, 200 altın!" +I can't believe that I got stuck with this duty. They say that something evil came up out of this sewer gate... Now I get to stand here until it comes up again!,TXT_DLG_SCRIPT02_D13644_ICANT,MAP02: Between governor's mansion and town hall.,,,"Nemůžu uvěřit, že jsem zkysnul s touhle prací. Řekli mi, že z téhle brány vylezlo něco zlého... A teď tady mám stát, dokud to znovu nevyleze!","Jeg kan ikke tro, at jeg blev sat til at have denne opgave. De siger, at noget ondt kom op af denne kloakport... Nu skal jeg stå her, indtil det kommer op igen!","Ich kann's nicht glauben dass ich diesen Dienst hier machen muss. Sie haben gesagt, dass etwas Böses aus dem Kanalisationstor gekommen ist... Nun muss ich hier stehen, bis es wieder kommt!",,"Mi ne povas kredi, ke mi estas blokita kun ĉi tiu tasko: Oni diras, ke malbonaĵo aperis el ĉi tiu pordo... kaj mi nun devas resti ĉi tie ĝis ĝi reaperos!",No puedo creer que haya quedado esclavizado con esta tarea: Dicen que algo maligno salió de esta compuerta... ¡y ahora tengo que quedarme aquí hasta que salga de nuevo!,,"Uskomatonta, että minulle tungettiin tämä tehtävä. Sanovat, että jokin paha nousi ylös tästä viemäriluukusta... Ja minä saan seistä tässä, kunnes se nousee jälleen!",J'arrive pas à croire que je me retrouve coincé ici. On me raconte qu'une chose maléfique est sortie de cette barrière des égouts.. Maintenant je me retrouve planté ici jusqu'a ce qu'elle revienne!,"Nem hiszem el, hogy én kaptam ezt a melót. Úgy hírlik, hogy valami gonosz bukkant fel itt a csatorna kapuja felől... Most addig fogok itt állni, amíg újra fel nem bukkan.",Non posso credere di aver accettato questo lavoro. Dicono che qualcosa di malvagio sia sbucato dalla chiusa delle fogne... E io devo stare qui finché non ritorna! ,"私がこの勤務で足止めとは信じられん。 皆が下水ゲートから悪しきものが来たと言う。 -再びドアが開くまで、ここで立ち往生だ!",내가 이 임무에 얽매였다는 게 믿기지 않아요. 사람들이 하수도 입구에서 뭔가 나타났다고 하던데... 이제 그게 다시 올 때까지 여기에서 서 있어야 한다니!,Ik kan niet geloven dat ik met deze plicht vast kwam te zitten. Ze zeggen dat er iets kwaadaardigs uit deze rioolpoort is gekomen.... Nu mag ik hier blijven staan tot het weer opduikt!,Jeg kan ikke tro at jeg ble sittende fast med denne plikten. De sier at noe ondt kom opp av denne kloakkporten... Nå må jeg stå her til det kommer opp igjen!,"Nie mogę uwierzyć, że zostałem z tym obowiązkiem. Mówią, że coś złego wyszło z tej bramy do kanałów... Teraz muszę tu stać aż się znów pojawi.",Não acredito que fiquei com essa tarefa. Dizem que algo horrível saiu dessa comporta de esgoto... Agora tenho que ficar aqui até que saia de novo!,,Nu-mi vine să cred că am rămas blocat cu meseria asta. Se zvonește că ceva malefic a ieșit la suprafată prin poarta canalului... Acum am ocazia să stau aici până se întoarce!,"Не могу поверить, что застрял на дежурстве. Они говорят, что какая-то пакость поднялась из этого люка... и теперь я должен стоять тут и ждать, пока она не появится снова!",,Bu görevin bana kaldığına inanamıyorum. Bu kanalizasyon kapısından kötü bir şeyin çıktığını söylüyorlar. Şimdi o şey tekrar ortaya çıkana kadar burada duracağım! -What gate?,TXT_RPLY0_SCRIPT02_D13644_WHATG,〃,,,Jaké brány?,Hvilken port?,Welches Tor?,,Kio estas post la pordo?,¿De qué es la compuerta?,,Mikä luukku?,Quelle barrière?,Milyen Kapu?,Quale chiusa? ,何のゲートだ?,무슨 입구?,Welk hek?,Hvilken port?,Jakiej bramy?,Que comporta?,,Care poartă?,Какого люка?,,Ne kapısı? +再びドアが開くまで、ここで立ち往生だ!",내가 이 임무에 얽매였다는 게 믿기지 않아요. 사람들이 하수도 입구에서 뭔가 나타났다고 하던데... 이제 그게 다시 올 때까지 여기에서 서 있어야 한다니!,Ik kan niet geloven dat ik met deze plicht vast kwam te zitten. Ze zeggen dat er iets kwaadaardigs uit deze rioolpoort is gekomen.... Nu mag ik hier blijven staan tot het weer opduikt!,Jeg kan ikke tro at jeg ble sittende fast med denne plikten. De sier at noe ondt kom opp av denne kloakkporten... Nå må jeg stå her til det kommer opp igjen!,"Nie mogę uwierzyć, że zostałem z tym obowiązkiem. Mówią, że coś złego wyszło z tej bramy do kanałów... Teraz muszę tu stać aż się znów pojawi.",Não acredito que fiquei com essa tarefa. Dizem que algo horrível saiu dessa comporta de esgoto... Agora tenho que ficar aqui até que saia de novo!,,Nu-mi vine să cred că am rămas blocat cu meseria asta. Se zvonește că ceva malefic a ieșit la suprafată prin poarta canalului... Acum am ocazia să stau aici până se întoarce!,"Не могу поверить, что застрял на дежурстве. Они говорят, что какая-то пакость поднялась из этого люка... и теперь я должен стоять тут и ждать, пока она не появится снова!",,Jag kan inte fatta att jag fick den här uppgiften. Det sägs att något ondskefullt kom upp ur den här kloakporten... Nu får jag stå här tills det kommer upp igen!,Bu görevin bana kaldığına inanamıyorum. Bu kanalizasyon kapısından kötü bir şeyin çıktığını söylüyorlar. Şimdi o şey tekrar ortaya çıkana kadar burada duracağım! +What gate?,TXT_RPLY0_SCRIPT02_D13644_WHATG,〃,,,Jaké brány?,Hvilken port?,Welches Tor?,,Kio estas post la pordo?,¿De qué es la compuerta?,,Mikä luukku?,Quelle barrière?,Milyen Kapu?,Quale chiusa? ,何のゲートだ?,무슨 입구?,Welk hek?,Hvilken port?,Jakiej bramy?,Que comporta?,,Care poartă?,Какого люка?,,Vilken port?,Ne kapısı? The sewer overflow gate.,TXT_RYES0_SCRIPT02_D13644_THESE,〃,,,Odpadní přepadové brány.,Kloakoverløbsporten.,Das Überlauftor der Kanalisation.,,"La elflua truo -de la kloakoj.","Del pozo de desagüe -del alcantarillado.",,Viemärin ylivuotoluukku.,La barrière de débordement des égouts.,A csatorna kiárasztó kapuja.,La chiusa di contenimento delle fogne. ,下水道の溢水ゲートだ。,하수도 입구 말이에요.,Het riooloverloophek.,Kloakkoverløpsporten.,Bramy do kanałów.,A comporta de transborda de esgoto.,,Poarta de revărsare.,Канализационного люка перелива.,,Kanalizasyon taşma kapısı. -Hello friend. What can I get for you?,TXT_DLG_SCRIPT02_D15160_HELLO,MAP02: Weapons.,,,"Zdravím, příteli. Co pro vás můžu udělat?","Hej, min ven. Hvad kan jeg hjælpe dig med?","Hallo, Freund. Was darf es sein?",,"Saluton, amiko. Kion mi donu al vi?","Saludos, amigo. ¿Qué puedo ofrecerte?",,"Tervehdys, ystävä. Mitä saisi olla?","Bonjour mon ami, que puis-je faire pour vous?","Szervusz barátom, mit tehetnék érted?",Ehilà amico. Che posso darti? ,どうも同士よ。何か必要か?,안녕하십니까. 뭘 드릴까요?,Hallo vriend. Wat kan ik voor je halen?,"Hallo, min venn. Hva vil du ha?",Witaj kolego. Co mogę dla ciebie zrobić?,"Olá, amigo. Como posso ajudá-lo?",,Salut prietene. Ce pot să-ți aduc?,Здравствуй. Что-нибудь интересует?,,Merhaba dostum. Senin için ne yapabilirim? -Electric bolts,TXT_RPLY0_SCRIPT02_D15160_ELECT,〃,,,Elektrické šípy,Elektriske bolte,Elektrische Bolzen,,Elektrajn sagojn,Flechas eléctricas,,Sähkönuolia,Carreaux électriques,Elektromos nyilak.,Dardi elettrificati ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektriske bolter.,Elektryczne bełty,Setas elétricas,,Bolțuri electrice,Электрические болты,,Elektrikli cıvata. -You got the electric bolts.,TXT_RYES0_SCRIPT02_D15160_YOUGO,〃,,,Tady je máte.,Du fik de elektriske bolte.,Du hast die elektrischen Bolzen erhalten.,,Jen la sagoj.,Aquí están las flechas.,,Sait sähkönuolet.,Vous recevez les carreaux électriques.,Megkaptad az elektromos nyilakat.,Hai preso dei dardi elettrificati ,エレクトリックボルト 入手。,전격 볼트를 받았습니다.,Je hebt de elektrische bouten.,Du har de elektriske boltene.,Masz elektryczne bełty.,Você pegou as setas elétricas,,Ai ridicat bolțurile electrice.,Вот твои электрические болты.,,Elektrikli cıvatalar sende. -Ammo satchel,TXT_RPLY1_SCRIPT02_D15160_AMMOS,〃,,,Brašnu na munici,Ammotaske,Munitionstasche,,Sako da municioj,Bolso de municiones,,Ammusreppu,Sacoche de Munitions,Lőszeres táska.,Sacca di munizioni ,弾薬鞄,탄약 배낭,Munitie tasje,Ammunisjonsveske,Torba z amunicją,Mochila de munição,,Sacoșă cu muniție,Ранец для боеприпасов,,Cephane çantası +de la kloako.",Del pozo de la red cloacal.,,Viemärin ylivuotoluukku.,La barrière de débordement des égouts.,A csatorna kiárasztó kapuja.,La chiusa di contenimento delle fogne. ,下水道の溢水ゲートだ。,하수도 입구 말이에요.,Het riooloverloophek.,Kloakkoverløpsporten.,Bramy do kanałów.,A comporta de transborda de esgoto.,,Poarta de revărsare.,Канализационного люка перелива.,,Kloakens överflödsgrind.,Kanalizasyon taşma kapısı. +Hello friend. What can I get for you?,TXT_DLG_SCRIPT02_D15160_HELLO,MAP02: Weapons.,,,"Zdravím, příteli. Co pro vás můžu udělat?","Hej, min ven. Hvad kan jeg hjælpe dig med?","Hallo, Freund. Was darf es sein?",,"Saluton, amiko. Kion mi donu al vi?","Saludos, amigo. ¿Qué puedo ofrecerte?",,"Tervehdys, ystävä. Mitä saisi olla?","Bonjour mon ami, que puis-je faire pour vous?","Szervusz barátom, mit tehetnék érted?",Ehilà amico. Che posso darti? ,どうも同士よ。何か必要か?,안녕하십니까. 뭘 드릴까요?,Hallo vriend. Wat kan ik voor je halen?,"Hallo, min venn. Hva vil du ha?",Witaj kolego. Co mogę dla ciebie zrobić?,"Olá, amigo. Como posso ajudá-lo?",,Salut prietene. Ce pot să-ți aduc?,Здравствуй. Что-нибудь интересует?,,"Hej, min vän. Vad kan jag ge dig?",Merhaba dostum. Senin için ne yapabilirim? +Electric bolts,TXT_RPLY0_SCRIPT02_D15160_ELECT,〃,,,Elektrické šípy,Elektriske bolte,Elektrische Bolzen,,Elektrajn sagojn,Flechas eléctricas,,Sähkönuolia,Carreaux électriques,Elektromos nyilak.,Dardi elettrificati ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektriske bolter.,Elektryczne bełty,Setas elétricas,,Bolțuri electrice,Электрические болты,,Elektriska bultar,Elektrikli cıvata. +You got the electric bolts.,TXT_RYES0_SCRIPT02_D15160_YOUGO,〃,,,Tady je máte.,Du fik de elektriske bolte.,Du hast die elektrischen Bolzen erhalten.,,Jen la sagoj.,Aquí están las flechas.,,Sait sähkönuolet.,Vous recevez les carreaux électriques.,Megkaptad az elektromos nyilakat.,Hai preso dei dardi elettrificati ,エレクトリックボルト 入手。,전격 볼트를 받았습니다.,Je hebt de elektrische bouten.,Du har de elektriske boltene.,Masz elektryczne bełty.,Você pegou as setas elétricas,,Ai ridicat bolțurile electrice.,Вот твои электрические болты.,,Du fick elektriska bultar.,Elektrikli cıvatalar sende. +Ammo satchel,TXT_RPLY1_SCRIPT02_D15160_AMMOS,〃,,,Brašnu na munici,Ammotaske,Munitionstasche,,Sako da municioj,Bolso de municiones,,Ammusreppu,Sacoche de Munitions,Lőszeres táska.,Sacca di munizioni ,弾薬鞄,탄약 배낭,Munitie tasje,Ammunisjonsveske,Torba z amunicją,Mochila de munição,,Sacoșă cu muniție,Ранец боеприпасов,,Ammunitionsväska,Cephane çantası No. You don't have what I want for the electric bolts!,TXT_RNO0_SCRIPT02_D15160_NOYOU,〃,,,"Ne. Nemáte, co za ně chci!","Nej. Du har ikke det, jeg vil have for de elektriske bolte!","Nein. Du hast nicht das, was ich für die elektrischen Pfeile haben möchte!",,"Ne, vi ne havas tiom, -kiom mi petas.","No, no tienes lo que pido.",,"Ei. Sinulla ei ole, mitä haluan sähkönuolista!","Non, vous n'avez pas ce qu'il me faut pour les carreaux électriques!","Nem. Neked nincs olyanod, ami nekem kéne az elektromos nyilakért.",No. Non hai quello che mi serve per i dardi elettrificati! ,いや。エレクトリックボルトに必要な物が足りない!,전격 볼트의 가격에 해당하는 게 전혀 없구먼!,Nee. Je hebt niet wat ik wil voor de elektrische bouten!,Nei. Du har ikke det jeg vil ha for de elektriske boltene!,"Nie. Nie masz tego co ja chcę, by dać ci elektryczne bełty.",Não. Você não tem o que eu quero pelas setas elétricas!,,Nu. Nu ai ceea ce doresc pentru bolțurile electrice!,Нет. У тебя нет денег на электрические болты!,,Hayır. Elektrikli cıvatalar için istediğim şey sizde yok! +kiom mi petas.","No, no tienes lo que pido.",,"Ei. Sinulla ei ole, mitä haluan sähkönuolista!","Non, vous n'avez pas ce qu'il me faut pour les carreaux électriques!","Nem. Neked nincs olyanod, ami nekem kéne az elektromos nyilakért.",No. Non hai quello che mi serve per i dardi elettrificati! ,いや。エレクトリックボルトに必要な物が足りない!,전격 볼트의 가격에 해당하는 게 전혀 없구먼!,Nee. Je hebt niet wat ik wil voor de elektrische bouten!,Nei. Du har ikke det jeg vil ha for de elektriske boltene!,"Nie. Nie masz tego co ja chcę, by dać ci elektryczne bełty.",Não. Você não tem o que eu quero pelas setas elétricas!,,Nu. Nu ai ceea ce doresc pentru bolțurile electrice!,Нет. У тебя нет денег на электрические болты!,,"Nej, du har inte det jag vill ha för elbultarna!",Hayır. Elektrikli cıvatalar için istediğim şey sizde yok! No. You don't have what I want for the electric bolts!,TXT_RNO0_SCRIPT02_D16676_NOYOU,〃,,,"Ne. Nemáte, co za ně chci!","Nej. Du har ikke det, jeg vil have til de elektriske bolte!","Nein. Du hast nicht das, was ich für die elektrischen Pfeile haben möchte!",,"Ne, vi ne havas tiom, -kiom mi petas.","No, no tienes lo que pido.",,"Ei. Sinulla ei ole, mitä haluan sähkönuolista!","Non, vous n'avez pas ce qu'il me faut pour les carreaux électriques!","Nem. Neked nincs olyanod, ami nekem kéne az elektromos nyilakért.",No. Non hai quello che mi serve per i dardi elettrificati! ,いや。エレクトリックボルトに必要な物が足りない!,전격 볼트의 가격에 맞춰서 흥정하시길.,Nee. Je hebt niet wat ik wil voor de elektrische bouten!,Nei. Du har ikke det jeg vil ha for de elektriske boltene!,"Nie. Nie masz tego co ja chcę, by dać ci elektryczne bełty.",Não. Você não tem o que eu quero pelas setas elétricas!,,Nu. Nu ai ceea ce doresc pentru bolțurile electrice!,Нет. У тебя нет денег на электрические болты!,,Hayır. Elektrikli cıvatalar için istediğim şey sizde yok! -Thank you. Anything else?,TXT_RYES1_SCRIPT02_D15160_THANK,〃,,,Děkuji. Něco dalšího?,Tak. Er der andet?,Danke. Sonst noch etwas?,,Dankon. Ĉu ion alian?,Gracias. ¿Algo más?,,Kiitos. Jotain muuta?,"Merci, Autre chose?",Köszönöm. Még valamit?,Grazie. Qualcos'altro? ,ありがとう。 他に何か?,감사합니다. 다른 건 없나요?,"Bedankt, nog iets anders?",Takk skal du ha. Var det noe mer?,Dziękuję. Coś jeszcze?,Agradeço. Mais alguma coisa?,,Mulțumesc. Mai dorești ceva?,Благодарю. Что-нибудь ещё?,,Teşekkür ederim. Başka bir şey var mı? +kiom mi petas.","No, no tienes lo que pido.",,"Ei. Sinulla ei ole, mitä haluan sähkönuolista!","Non, vous n'avez pas ce qu'il me faut pour les carreaux électriques!","Nem. Neked nincs olyanod, ami nekem kéne az elektromos nyilakért.",No. Non hai quello che mi serve per i dardi elettrificati! ,いや。エレクトリックボルトに必要な物が足りない!,전격 볼트의 가격에 맞춰서 흥정하시길.,Nee. Je hebt niet wat ik wil voor de elektrische bouten!,Nei. Du har ikke det jeg vil ha for de elektriske boltene!,"Nie. Nie masz tego co ja chcę, by dać ci elektryczne bełty.",Não. Você não tem o que eu quero pelas setas elétricas!,,Nu. Nu ai ceea ce doresc pentru bolțurile electrice!,Нет. У тебя нет денег на электрические болты!,,"Nej, du har inte det jag vill ha för elbultarna!",Hayır. Elektrikli cıvatalar için istediğim şey sizde yok! +Thank you. Anything else?,TXT_RYES1_SCRIPT02_D15160_THANK,〃,,,Děkuji. Něco dalšího?,Tak. Er der andet?,Danke. Sonst noch etwas?,,Dankon. Ĉu ion alian?,Gracias. ¿Algo más?,,Kiitos. Jotain muuta?,"Merci, Autre chose?",Köszönöm. Még valamit?,Grazie. Qualcos'altro? ,ありがとう。 他に何か?,감사합니다. 다른 건 없나요?,"Bedankt, nog iets anders?",Takk skal du ha. Var det noe mer?,Dziękuję. Coś jeszcze?,Agradeço. Mais alguma coisa?,,Mulțumesc. Mai dorești ceva?,Благодарю. Что-нибудь ещё?,,Tack. Något annat?,Teşekkür ederim. Başka bir şey var mı? "You can't afford that, good day.",TXT_RNO1_SCRIPT02_D15160_YOUCA,〃,,,"To si nemůžete dovolit, přeji hezký den.","Det har du ikke råd til, god dag.",Das kannst du dir nicht leisten. Guten Tag.,,"Vi ne povas sen mono. Havu bonan tagon!","No te alcanza. -¡Ten un buen día!",,"Sinulla ei ole siihen varaa, hyvää päivänjatkoa.",Vous n'avez pas assez d'argent. Bonne journée.,Ezt most nem tudod kifizetni. Szép napot!,Non puoi permettertelo. Buona giornata. ,それを買える余裕は無い、また今度。,가질 수가 없는 것 같으니... 그럼 이만!,"Dat kun je je je niet veroorloven, goede dag.","Det har du ikke råd til, adjø.","Nie możesz tego kupić, miłego dnia.",Você não pode comprar isso. Tenha um bom dia.,,Nu îți permiți asta. O zi bună.,У тебя не хватает денег. Всего доброго.,,"Bunu karşılayamazsınız, iyi günler." -What can I get for you?,TXT_DLG_SCRIPT02_D16676_WHATC,〃,,,Co vám mohu nabídnout?,Hvad kan jeg skaffe til dig?,Was darf es sein?,,Kion mi donu al vi?,¿Qué puedo ofrecerte?,,Mitä saisi olla?,Que puis-je faire pour vous?,Mivel szolgáhatok?,Che cosa posso darti? ,何か必要か?,"무엇을 구매하고 싶으신가요, 좋은 친구여?",Wat kan ik voor je halen?,Hva vil du ha?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot să-ți aduc?,Чем могу быть полезен?,,Sizin için ne alabilirim? -Electric bolts,TXT_RPLY0_SCRIPT02_D16676_ELECT,〃,,,Elektrické šípy,Elektriske bolte,Elektrische Bolzen,,Elektrajn sagojn,Flechas eléctricas,,Sähkönuolia,Carreaux électriques,Elektromos nyilak.,Dardi elettrificati ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektriske bolter.,Elektryczne bełty,Setas elétricas,,Bolțuri electrice,Электрические болты,,Elektrikli cıvatalar. -You got the electric bolts.,TXT_RYES0_SCRIPT02_D16676_YOUGO,〃,,,Tady je máte.,Du fik de elektriske bolte.,Du hast die elektrischen Bolzen erhalten.,,Jen la sagoj.,Aquí están las flechas.,,Sait sähkönuolet.,Vous recevez les carreaux électriques.,Elektromos nyilakra tettél szert.,Hai preso dei dardi elettrificati ,エレクトリックボルト 入手。,전격 볼트를 구매했습니다.,Je hebt de elektrische bouten.,Du har elektriske bolter.,Masz elektryczne bełty.,Você pegou as setas elétricas,,Ai ridicat bolțurile electrice.,Вот твои электрические болты.,,Elektrikli cıvatalar sende. -Ammo satchel,TXT_RPLY1_SCRIPT02_D16676_AMMOS,〃,,,Brašnu na munici,Ammotaske.,Munitionstasche,,Sako da municioj,Bolso de municiones,,Ammusreppu,Sacoche de Munitions,Lőszeres hátizsák,Sacca di munizioni ,弾薬鞄,탄약 배낭,Munitie tasje,Ammunisjonsveske.,Torba z amunicją,Mochila de munição,,Sacoșă cu muniție,Ранец для боеприпасов,,Cephane çantası -"Thank you, anything else?",TXT_RYES1_SCRIPT02_D16676_THANK,〃,,,Děkuji. Něco dalšího?,"Tak, andet?",Danke. Sonst noch etwas?,,Dankon. Ĉu ion alian?,Gracias. ¿Algo más?,,Kiitos. Jotain muuta?,"Merci, Autre chose?","Köszönöm, bármi mást?","Grazie, ti serve qualcos'altro?",ありがとう。 他に何か?,감사합니다. 다른 건 더 없나요?,"Bedankt, nog iets anders?","Takk, noe mer?","Dziękuję, coś jeszcze?",Agradeço. Mais alguma coisa?,,"Mulțumesc, mai dorești ceva?",Благодарю. Что-нибудь ещё?,,"Teşekkürler, başka bir şey var mı?" +¡Ten un buen día!",,"Sinulla ei ole siihen varaa, hyvää päivänjatkoa.",Vous n'avez pas assez d'argent. Bonne journée.,Ezt most nem tudod kifizetni. Szép napot!,Non puoi permettertelo. Buona giornata. ,それを買える余裕は無い、また今度。,가질 수가 없는 것 같으니... 그럼 이만!,"Dat kun je je je niet veroorloven, goede dag.","Det har du ikke råd til, adjø.","Nie możesz tego kupić, miłego dnia.",Você não pode comprar isso. Tenha um bom dia.,,Nu îți permiți asta. O zi bună.,У тебя не хватает денег. Всего доброго.,,"Du har inte råd med det, god dag.","Bunu karşılayamazsınız, iyi günler." +What can I get for you?,TXT_DLG_SCRIPT02_D16676_WHATC,〃,,,Co vám mohu nabídnout?,Hvad kan jeg skaffe til dig?,Was darf es sein?,,Kion mi donu al vi?,¿Qué puedo ofrecerte?,,Mitä saisi olla?,Que puis-je faire pour vous?,Mivel szolgáhatok?,Che cosa posso darti? ,何か必要か?,"무엇을 구매하고 싶으신가요, 좋은 친구여?",Wat kan ik voor je halen?,Hva vil du ha?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot să-ți aduc?,Чем могу быть полезен?,,Vad kan jag ge dig?,Sizin için ne alabilirim? +Electric bolts,TXT_RPLY0_SCRIPT02_D16676_ELECT,〃,,,Elektrické šípy,Elektriske bolte,Elektrische Bolzen,,Elektrajn sagojn,Flechas eléctricas,,Sähkönuolia,Carreaux électriques,Elektromos nyilak.,Dardi elettrificati ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektriske bolter.,Elektryczne bełty,Setas elétricas,,Bolțuri electrice,Электрические болты,,Elektriska bultar,Elektrikli cıvatalar. +You got the electric bolts.,TXT_RYES0_SCRIPT02_D16676_YOUGO,〃,,,Tady je máte.,Du fik de elektriske bolte.,Du hast die elektrischen Bolzen erhalten.,,Jen la sagoj.,Aquí están las flechas.,,Sait sähkönuolet.,Vous recevez les carreaux électriques.,Elektromos nyilakra tettél szert.,Hai preso dei dardi elettrificati ,エレクトリックボルト 入手。,전격 볼트를 구매했습니다.,Je hebt de elektrische bouten.,Du har elektriske bolter.,Masz elektryczne bełty.,Você pegou as setas elétricas,,Ai ridicat bolțurile electrice.,Вот твои электрические болты.,,Du har elektriska bultar.,Elektrikli cıvatalar sende. +Ammo satchel,TXT_RPLY1_SCRIPT02_D16676_AMMOS,〃,,,Brašnu na munici,Ammotaske.,Munitionstasche,,Sako da municioj,Bolso de municiones,,Ammusreppu,Sacoche de Munitions,Lőszeres hátizsák,Sacca di munizioni ,弾薬鞄,탄약 배낭,Munitie tasje,Ammunisjonsveske.,Torba z amunicją,Mochila de munição,,Sacoșă cu muniție,Ранец боеприпасов,,Ammunitionsväska,Cephane çantası +"Thank you, anything else?",TXT_RYES1_SCRIPT02_D16676_THANK,〃,,,Děkuji. Něco dalšího?,"Tak, andet?",Danke. Sonst noch etwas?,,Dankon. Ĉu ion alian?,Gracias. ¿Algo más?,,Kiitos. Jotain muuta?,"Merci, Autre chose?","Köszönöm, bármi mást?","Grazie, ti serve qualcos'altro?",ありがとう。 他に何か?,감사합니다. 다른 건 더 없나요?,"Bedankt, nog iets anders?","Takk, noe mer?","Dziękuję, coś jeszcze?",Agradeço. Mais alguma coisa?,,"Mulțumesc, mai dorești ceva?",Благодарю. Что-нибудь ещё?,,"Tack, något annat?","Teşekkürler, başka bir şey var mı?" "You can't afford that, good day to you!",TXT_RNO1_SCRIPT02_D16676_YOUCA,〃,,,"To si nemůžete dovolit, přeji hezký den.","Det har du ikke råd til, god dag til dig!",Das kannst du dir nicht leisten. Guten Tag!,,"Vi ne povas sen mono. Havu bonan tagon!","No te alcanza. -¡Ten un buen día!",,"Sinulla ei ole siihen varaa, hyvää päivänjatkoa.",Vous n'avez pas assez d'argent. Bonne journée.,"Nincs elég pénzed arra, további jó napot neked!",Non puoi permettertelo. Buona giornata a te!,それを買える余裕は無い、また今度。,살 돈이 부족하신가요? 그럼 갈 길 가시길!,"Dat kunt u zich niet veroorloven, een goede dag voor je!","Det har du ikke råd til, ha en god dag!","Nie możesz tego kupić, życzę miłego dnia!",Você não pode comprar isso. Um bom dia pra você!,,Nu-ți poți permite asta. O zi bună îți doresc!,У тебя не хватает денег. Всего доброго!,,"Bunu karşılayamazsınız, size iyi günler!" +¡Ten un buen día!",,"Sinulla ei ole siihen varaa, hyvää päivänjatkoa.",Vous n'avez pas assez d'argent. Bonne journée.,"Nincs elég pénzed arra, további jó napot neked!",Non puoi permettertelo. Buona giornata a te!,それを買える余裕は無い、また今度。,살 돈이 부족하신가요? 그럼 갈 길 가시길!,"Dat kunt u zich niet veroorloven, een goede dag voor je!","Det har du ikke råd til, ha en god dag!","Nie możesz tego kupić, życzę miłego dnia!",Você não pode comprar isso. Um bom dia pra você!,,Nu-ți poți permite asta. O zi bună îți doresc!,У тебя не хватает денег. Всего доброго!,,"Du har inte råd med det, god dag till dig!","Bunu karşılayamazsınız, size iyi günler!" Welcome. What may I show you?,TXT_DLG_SCRIPT02_D18192_WELCO,MAP02: Armory.,,,Vítejte. Co vám mohu nabídnout?,Velkommen. Hvad må jeg vise dig?,Willkommen. Was kann ich dirZeigen.,,Bonvenon. Kion mi montru al vi?,Bienvenido. ¿Qué te muestro?,,Tervetuloa. Mitä haluaisitte vilkaista?,"Bienvenue, que souhaitez vous?",Üdvözletem! Miben segíthetek?,Benvenuto. Cosa posso mostrarti?,ようこそ、何を見ていきますか?,환영합니다! 보여드릴 게 아주 많아요.,Welkom. Wat kan ik je laten zien?,Velkommen. Hva kan jeg vise deg?,"Witaj. Co mogę ci pokazać? -",Saudações. O que posso te mostrar?,,Bun venit. Ce aș putea să-ți arăt?,Здравствуй. Что-нибудь интересует?,,Hoş geldiniz. Size ne gösterebilirim? -Environmental suit,TXT_RPLY0_SCRIPT02_D18192_ENVIR,〃,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje de protección ambiental,,Ympäristösuojapuku,Combinaison hazmat,Természetálló öltözet,Tuta ambientale,耐環境スーツ,환경 방호복,Milieupak,Miljødrakt,Skafander Ochronny,Traje de proteção,,Costum de protecție,Защитный костюм,,Çevre kıyafeti. -"Well, here you are.",TXT_RYES0_SCRIPT02_D18192_WELLH,〃,,,"Tak, tady to je.","Nå, værsgo.",Bitte sehr.,,"Nu, jen.","Bueno, aquí tienes.",,"Kas tässä, olkaa hyvä.",Voilà pour vous.,"Nos, tessék.","Bene, ecco a te.",はい、これをどうぞ。,"자, 여기있습니다.","Nou, hier ben je dan.",Vær så god.,"Proszę, masz.","Muito bem, aqui está.",,Poftiți.,"Хорошо, бери.",,İşte buradasın. +",Saudações. O que posso te mostrar?,,Bun venit. Ce aș putea să-ți arăt?,Здравствуй. Что-нибудь интересует?,,Välkommen. Vad får jag visa dig?,Hoş geldiniz. Size ne gösterebilirim? +Environmental suit,TXT_RPLY0_SCRIPT02_D18192_ENVIR,〃,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje NBQ,,Ympäristösuojapuku,Combinaison hazmat,Természetálló öltözet,Tuta ambientale,耐環境スーツ,환경 방호복,Milieupak,Miljødrakt,Skafander Ochronny,Traje de proteção,,Costum de protecție,Защитный костюм,,Miljödräkt,Çevre kıyafeti. +"Well, here you are.",TXT_RYES0_SCRIPT02_D18192_WELLH,〃,,,"Tak, tady to je.","Nå, værsgo.",Bitte sehr.,,"Nu, jen.","Bueno, toma.",,"Kas tässä, olkaa hyvä.",Voilà pour vous.,"Nos, tessék.","Bene, ecco a te.",はい、これをどうぞ。,"자, 여기있습니다.","Nou, hier ben je dan.",Vær så god.,"Proszę, masz.","Muito bem, aqui está.",,Poftiți.,"Хорошо, бери.",,"Ja, här är du.",İşte buradasın. I'm sorry but you don't have enough money for that.,TXT_RNO0_SCRIPT02_D18192_IMSOR,〃,,,"Promiňte, ale na ten nemáte dost peněz.","Jeg beklager, men du har ikke penge nok til det.","Es tut mir Leid, aber du hast nicht genug Geld dabei.",,"Pardonon, sed vi ne -havas sufiĉe da mono.","Lo siento, pero no te alcanza.",,Valitettavasti teillä ei ole siihen riittävästi rahaa.,Je suis désolé mais vous n'avez pas assez d'argent.,"Sajnálom, de nincs elég pénzed erre.","Mi spiace, ma non hai abbastanza soldi per questo.",すみませんが、貴方は十分なお金を持っていません。,"죄송합니다만, 그걸 사기엔 돈이 부족해 보입니다.","Het spijt me, maar daar heb je niet genoeg geld voor.","Beklager, men du har ikke nok penger til det.","Przepraszam, ale nie masz wystarczająco dużo monet, aby to kupić.","Sinto muito, mas você não tem dinheiro suficiente para isso.",,"Îmi pare rău, dar nu ai suficienți bani pentru asta.","Извини, но у тебя не хватает денег.",,Üzgünüm ama bunun için yeterli paranız yok. -Leather armor,TXT_RPLY1_SCRIPT02_D18192_LEATH,〃,,Leather armour,Kožené brnění,Læderrustning,Lederrüstung,,Ledan armaĵon,Armadura de cuero,,Nahkasuojus,Armure en cuir,Bőr páncél,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren pantser,Skinnpanser,Skórzany Pancerz,Armadura de couro,,Armură din piele,Кожаная броня,,Deri zırh -Here you are.,TXT_RYES1_SCRIPT02_D18192_HEREY,〃,,,Tady máte.,Værsgo.,Bitte sehr.,,Jen.,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Tessék.,Ecco qua.,これをどうぞ。,여기 있습니다.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи.,,Buyurun. -Perhaps some other time?,TXT_RNO1_SCRIPT02_D18192_PERHA,〃,,,Možná někdy jindy?,Måske en anden gang?,Vielleicht ein anderes Mal?,,Ĉu eble alian fojon?,¿Quizás en otra ocasión?,¿Tal vez en otra ocasión?,Ehkä joskus toiste?,Peut être une autre fois?,Esetleg talán máskor?,"Magari un'altra volta, va bene?",また別の機会に?,아마 나중에 사야 할 것 같은데?,Misschien een andere keer?,Kanskje en annen gang?,Może innym razem?,Talvez uma outra hora?,,Poate altădată?,"Может, в следующий раз?",,Belki başka bir zaman? -Metal armor,TXT_RPLY2_SCRIPT02_D18192_METAL,〃,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure en Métal,Fémpáncél,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowy Pancerz,Armadura de metal,,Armură din metal,Металлическая броня,,Metal zırh +havas sufiĉe da mono.","Lo siento, pero no te alcanza.",,Valitettavasti teillä ei ole siihen riittävästi rahaa.,Je suis désolé mais vous n'avez pas assez d'argent.,"Sajnálom, de nincs elég pénzed erre.","Mi spiace, ma non hai abbastanza soldi per questo.",すみませんが、貴方は十分なお金を持っていません。,"죄송합니다만, 그걸 사기엔 돈이 부족해 보입니다.","Het spijt me, maar daar heb je niet genoeg geld voor.","Beklager, men du har ikke nok penger til det.","Przepraszam, ale nie masz wystarczająco dużo monet, aby to kupić.","Sinto muito, mas você não tem dinheiro suficiente para isso.",,"Îmi pare rău, dar nu ai suficienți bani pentru asta.","Извини, но у тебя не хватает денег.",,Jag är ledsen men du har inte tillräckligt med pengar för det.,Üzgünüm ama bunun için yeterli paranız yok. +Leather armor,TXT_RPLY1_SCRIPT02_D18192_LEATH,〃,,Leather armour,Kožené brnění,Læderrustning,Lederrüstung,,Ledan armaĵon,Armadura de cuero,,Nahkasuojus,Armure en cuir,Bőr páncél,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren pantser,Skinnpanser,Skórzany Pancerz,Armadura de couro,,Armură din piele,Кожаная броня,,Läderrustning,Deri zırh +Here you are.,TXT_RYES1_SCRIPT02_D18192_HEREY,〃,,,Tady máte.,Værsgo.,Bitte sehr.,,Jen.,Toma.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Tessék.,Ecco qua.,これをどうぞ。,여기 있습니다.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи.,,Här har du.,Buyurun. +Perhaps some other time?,TXT_RNO1_SCRIPT02_D18192_PERHA,〃,,,Možná někdy jindy?,Måske en anden gang?,Vielleicht ein anderes Mal?,,Ĉu eble alian fojon?,¿Quizás en otra ocasión?,¿Tal vez en otra ocasión?,Ehkä joskus toiste?,Peut être une autre fois?,Esetleg talán máskor?,"Magari un'altra volta, va bene?",また別の機会に?,아마 나중에 사야 할 것 같은데?,Misschien een andere keer?,Kanskje en annen gang?,Może innym razem?,Talvez uma outra hora?,,Poate altădată?,"Может, в следующий раз?",,Kanske en annan gång?,Belki başka bir zaman? +Metal armor,TXT_RPLY2_SCRIPT02_D18192_METAL,〃,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure en Métal,Fémpáncél,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowy Pancerz,Armadura de metal,,Armură din metal,Металлическая броня,,Metallrustning,Metal zırh Wear it in good health.,TXT_RYES2_SCRIPT02_D18192_WEARI,"〃 -(in good health = enjoy)",,,Noste jej ve zdraví.,Bær den ved godt helbred.,Trage sie mit Stolz.,,Ĝuu ĝin.,Disfrútala.,,Kaikin voimin pukeutukaa.,Portez la en bonne santé.,Viseld jó egészséggel!,Che possa esserti utile!,着ると安心しますよ。,건강하게 입으세요.,Draag het in goede gezondheid.,Bruk den med god helse.,Bądź zdrów nosząc go.,Vista ela com orgulho.,,Să o porți sănătos.,Носи на здоровье.,,Sağlıkla giy. +(in good health = enjoy)",,,Noste jej ve zdraví.,Bær den ved godt helbred.,Trage sie mit Stolz.,,Ĝuu ĝin.,Disfrútala.,,Kaikin voimin pukeutukaa.,Portez la bien.,Viseld jó egészséggel!,Che possa esserti utile!,着ると安心しますよ。,건강하게 입으세요.,Draag het in goede gezondheid.,Bruk den med god helse.,Bądź zdrów nosząc go.,Vista ela com orgulho.,,Să o porți sănătos.,Носи на здоровье.,,Bär den vid god hälsa.,Sağlıkla giy. Come back when you can afford to buy something you lout!,TXT_RNO2_SCRIPT02_D18192_COMEB,〃,,,"Vrať se, až si budeš moct něco dovolit, troubo!","Kom tilbage, når du har råd til at købe noget, din slyngel!","Komm zurück wenn du dir etwas leisten kannst, du Rüpel!",,"Revenu kiam vi povos aĉeti ion, stultulo!","¡Vuelve cuando puedas -comprar algo, zopenco! ",,"Palataan asiaan, kun teidän on mahdollista ostaa jotain himoitsemaanne.","Revenez quand vous avez de l'argent, rustre!","Majd akkor gyere vissza, ha lesz pénzed megvenni bármit is, te fajankó!","Ritorna quando potrai permetterti di comprare le cose, cafone!",余裕がある時にまたどうぞ!,뭔가를 살 여유가 있을 때 오세요!,Kom terug wanneer je het je kunt veroorloven om iets te kopen wat je louteren kunt!,"Kom tilbake når du har råd til å kjøpe noe, din lømmel!",Wróć kiedy będziesz mógł coś kupić prostaku!,"Volte quando você puder comprar algo, seu caloteiro!",,"Revin-o când o să ai bani să poți cumpăra ceva, secătură!","Возвращайся, когда сможешь позволить себе купить что-нибудь, придурок!",,Bir şeyler almaya gücün yettiğinde geri gel! +comprar algo, zopenco! ",,"Palataan asiaan, kun teidän on mahdollista ostaa jotain himoitsemaanne.","Revenez quand vous avez de l'argent, rustre!","Majd akkor gyere vissza, ha lesz pénzed megvenni bármit is, te fajankó!","Ritorna quando potrai permetterti di comprare le cose, cafone!",余裕がある時にまたどうぞ!,뭔가를 살 여유가 있을 때 오세요!,Kom terug wanneer je het je kunt veroorloven om iets te kopen wat je louteren kunt!,"Kom tilbake når du har råd til å kjøpe noe, din lømmel!",Wróć kiedy będziesz mógł coś kupić prostaku!,"Volte quando você puder comprar algo, seu caloteiro!",,"Revin-o când o să ai bani să poți cumpăra ceva, secătură!","Возвращайся, когда сможешь позволить себе купить что-нибудь, придурок!",,"Kom tillbaka när du har råd att köpa något, din tölp!",Bir şeyler almaya gücün yettiğinde geri gel! Welcome. What may I show you?,TXT_DLG_SCRIPT02_D19708_WELCO,,,,Vítejte. Co vám mohu nabídnout?,Velkommen. Hvad må jeg vise dig?,Willkommen. Was kann ich dir zeigen.,,Bonvenon. Kion mi montru al vi?,Bienvenido. ¿Qué te muestro?,,Tervetuloa. Mitä haluaisitte vilkaista?,"Bienvenue, que souhaitez vous?","Üdvözlet, mire volnál kíváncsi?",Benvenuto. Cosa posso mostrarti?,ようこそ、何をお探しで?,어서 오십시오. 어떤 걸 보여드릴까요?,Welkom. Wat kan ik je laten zien?,Velkommen. Hva kan jeg vise deg?,"Witaj. Co mogę ci pokazać? -",Saudações. O que posso te mostrar?,,Bun venit. Ce aș putea să-ți arăt?,Здравствуй. Что-нибудь интересует?,,Hoş geldiniz. Size ne gösterebilirim? -Environmental suit,TXT_RPLY0_SCRIPT02_D19708_ENVIR,,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje de protección ambiental,,Ympäristösuojapuku,Combinaison hazmat,Természetálló öltözet,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Miljødrakt,Skafander Ochronny,Traje de proteção,,Costum de protecție,Защитный костюм,,Çevre kıyafeti -"Well, here you are.",TXT_RYES0_SCRIPT02_D19708_WELLH,,,,"Tak, tady to je.","Nå, værsgo.",Bitte sehr.,,"Nu, jen.","Bueno, aquí tienes.",,"Kas tässä, olkaa hyvä.",Voilà pour vous.,"Nos, íme.","Bene, ecco a te.",では、これをどうぞ。,"자, 여기 있습니다.","Nou, hier ben je dan.",Vær så god.,"Proszę, masz.","Muito bem, aqui está.",,Poftiți.,"Хорошо, бери.",,İşte buradasın. +",Saudações. O que posso te mostrar?,,Bun venit. Ce aș putea să-ți arăt?,Здравствуй. Что-нибудь интересует?,,Välkommen. Vad får jag visa dig?,Hoş geldiniz. Size ne gösterebilirim? +Environmental suit,TXT_RPLY0_SCRIPT02_D19708_ENVIR,,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje NBQ,,Ympäristösuojapuku,Combinaison hazmat,Természetálló öltözet,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Miljødrakt,Skafander Ochronny,Traje de proteção,,Costum de protecție,Защитный костюм,,Miljödräkt,Çevre kıyafeti +"Well, here you are.",TXT_RYES0_SCRIPT02_D19708_WELLH,,,,"Tak, tady to je.","Nå, værsgo.",Bitte sehr.,,"Nu, jen.","Bueno, toma.",,"Kas tässä, olkaa hyvä.",Voilà pour vous.,"Nos, íme.","Bene, ecco a te.",では、これをどうぞ。,"자, 여기 있습니다.","Nou, hier ben je dan.",Vær så god.,"Proszę, masz.","Muito bem, aqui está.",,Poftiți.,"Хорошо, бери.",,"Ja, här är du.",İşte buradasın. I'm sorry but you don't have enough money for that.,TXT_RNO0_SCRIPT02_D19708_IMSOR,,,,"Promiňte, ale na ten nemáte dost peněz.","Jeg beklager, men du har ikke penge nok til det.","Es tut mir Leid, aber du hast nicht genug Geld dabei.",,"Pardonon, sed vi ne -havas sufiĉe da mono.","Lo siento, pero no te alcanza.",,Valitettavasti teillä ei ole siihen riittävästi rahaa.,Je suis désolé mais vous n'avez pas assez d'argent.,"Sajnálom, de Önnek nem áll módjában kifizetni ezt.","Mi spiace, ma non hai abbastanza soldi per questo.",すみませんが、貴方は十分なお金を持っていません。,"미안하지만, 구매하기 위한 돈이 부족하신 것 같군요.","Het spijt me, maar daar heb je niet genoeg geld voor.","Beklager, men du har ikke nok penger til det.","Przepraszam, ale nie masz wystarczająco dużo monet, aby to kupić.","Sinto muito, mas você não tem dinheiro suficiente para isso.",,"Îmi pare rău, dar nu ai suficienți bani pentru asta.","Извини, но у тебя не хватает денег.",,Üzgünüm ama bunun için yeterli paranız yok. -Leather armor,TXT_RPLY1_SCRIPT02_D19708_LEATH,,,Leather armour,Kožené brnění,Læderrustning,Lederrüstung,,Ledan armaĵon,Armadura de cuero,,Nahkasuojus,Armure en cuir,Bőr páncél,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Lær rustning,Skórzany Pancerz,Armadura de couro,,Armură din piele,Кожаная броня,,Deri zırh -Here you are.,TXT_RYES1_SCRIPT02_D19708_HEREY,,,,Tady máte.,Værsgo.,Bitte sehr.,,Jen.,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Tessék,Ecco qua.,これをどうぞ。,여기 있습니다.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи.,,Buyurun. -Perhaps some other time?,TXT_RNO1_SCRIPT02_D19708_PERHA,,,,Možná někdy jindy?,Måske en anden gang?,Vielleicht ein anderes Mal?,,Ĉu eble alian fojon?,¿Quizás en otra ocasión?,¿Tal vez en otra ocasión?,Ehkä joskus toiste?,Peut être une autre fois?,Talán majd máskor?,"Magari un'altra volta, va bene?",また別の機会に?,나중에 돈을 모아서 구매하세요.,Misschien een andere keer?,Kanskje en annen gang?,Może innym razem?,Talvez uma outra hora?,,Poate altădată?,"Может, в следующий раз?",,Belki başka bir zaman? -Metal armor,TXT_RPLY2_SCRIPT02_D19708_METAL,,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure en Métal,Fém páncél,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowy Pancerz,Armadura de metal,,Armură din metal,Металлическая броня,,Metal zırh -Wear it in good health.,TXT_RYES2_SCRIPT02_D19708_WEARI,(in good health = enjoy),,,Noste jej ve zdraví.,Bær den ved godt helbred.,Trage sie mit Stolz.,,Ĝuu ĝin.,Disfrútala.,,Käyttäkää hyvällä omallatunnolla.,Portez la en bonne santé.,Viseld jó egészséggel!,Che possa esserti utile!,着ると安心しますよ。,믿고 입으셔도 됩니다.,Draag het in goede gezondheid.,Bruk den med god helse.,Bądź zdrów nosząc go.,Vista ela com orgulho.,,Să o porți sănătos.,Носи на здоровье.,,Sağlıkla giy. +havas sufiĉe da mono.","Lo siento, pero no te alcanza.",,Valitettavasti teillä ei ole siihen riittävästi rahaa.,Je suis désolé mais vous n'avez pas assez d'argent.,"Sajnálom, de Önnek nem áll módjában kifizetni ezt.","Mi spiace, ma non hai abbastanza soldi per questo.",すみませんが、貴方は十分なお金を持っていません。,"미안하지만, 구매하기 위한 돈이 부족하신 것 같군요.","Het spijt me, maar daar heb je niet genoeg geld voor.","Beklager, men du har ikke nok penger til det.","Przepraszam, ale nie masz wystarczająco dużo monet, aby to kupić.","Sinto muito, mas você não tem dinheiro suficiente para isso.",,"Îmi pare rău, dar nu ai suficienți bani pentru asta.","Извини, но у тебя не хватает денег.",,"Jag är ledsen, men du har inte tillräckligt med pengar för det.",Üzgünüm ama bunun için yeterli paranız yok. +Leather armor,TXT_RPLY1_SCRIPT02_D19708_LEATH,,,Leather armour,Kožené brnění,Læderrustning,Lederrüstung,,Ledan armaĵon,Armadura de cuero,,Nahkasuojus,Armure en cuir,Bőr páncél,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Lær rustning,Skórzany Pancerz,Armadura de couro,,Armură din piele,Кожаная броня,,Läderrustning,Deri zırh +Here you are.,TXT_RYES1_SCRIPT02_D19708_HEREY,,,,Tady máte.,Værsgo.,Bitte sehr.,,Jen.,Toma.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Tessék,Ecco qua.,これをどうぞ。,여기 있습니다.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи.,,Här har du.,Buyurun. +Perhaps some other time?,TXT_RNO1_SCRIPT02_D19708_PERHA,,,,Možná někdy jindy?,Måske en anden gang?,Vielleicht ein anderes Mal?,,Ĉu eble alian fojon?,¿Quizás en otra ocasión?,¿Tal vez en otra ocasión?,Ehkä joskus toiste?,Peut être une autre fois?,Talán majd máskor?,"Magari un'altra volta, va bene?",また別の機会に?,나중에 돈을 모아서 구매하세요.,Misschien een andere keer?,Kanskje en annen gang?,Może innym razem?,Talvez uma outra hora?,,Poate altădată?,"Может, в следующий раз?",,Kanske en annan gång?,Belki başka bir zaman? +Metal armor,TXT_RPLY2_SCRIPT02_D19708_METAL,,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure en Métal,Fém páncél,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowy Pancerz,Armadura de metal,,Armură din metal,Металлическая броня,,Metallrustning,Metal zırh +Wear it in good health.,TXT_RYES2_SCRIPT02_D19708_WEARI,(in good health = enjoy),,,Noste jej ve zdraví.,Bær den ved godt helbred.,Trage sie mit Stolz.,,Ĝuu ĝin.,Disfrútala.,,Käyttäkää hyvällä omallatunnolla.,Portez la bien.,Viseld jó egészséggel!,Che possa esserti utile!,着ると安心しますよ。,믿고 입으셔도 됩니다.,Draag het in goede gezondheid.,Bruk den med god helse.,Bądź zdrów nosząc go.,Vista ela com orgulho.,,Să o porți sănătos.,Носи на здоровье.,,Bär den vid god hälsa.,Sağlıkla giy. Come back when you can afford to buy something you lout!,TXT_RNO2_SCRIPT02_D19708_COMEB,,,,"Vrať se, až si budeš moct něco dovolit, troubo!","Kom tilbage, når du har råd til at købe noget, din slyngel!","Komm zurück wenn du dir etwas leisten kannst, du Rüpel!",,"Revenu kiam vi povos aĉeti ion, stultulo!","¡Vuelve cuando puedas -comprar algo, zopenco! ",,"Palataan asiaan, kun teidän on mahdollista ostaa jotain himoitsemaanne.","Revenez quand vous avez de l'argent, rustre!","Majd akkor gyere vissza, ha lesz pénzed megvenni bármit is, te fajankó!","Ritorna quando potrai permetterti di comprare le cose, cafone!",余裕がある時にまたどうぞ!,이런 거래는 못 하겠습니다. 돈을 모아서 다시 찾아오시길!,Kom terug wanneer je het je kunt veroorloven om iets te kopen wat je louteren kunt!,"Kom tilbake når du har råd til å kjøpe noe, din lømmel!",Wróć kiedy będziesz mógł coś kupić prostaku!,"Volte quando você puder comprar algo, seu caloteiro!",,"Revin-o când o să ai bani să poți cumpăra ceva, secătură!","Возвращайся, когда сможешь позволить себе купить что-нибудь, придурок!",,Bir şeyler satın almaya gücün yettiğinde geri gel! -How may I assist you?,TXT_DLG_SCRIPT02_D21224_HOWMA,MAP02: Hospital.,,,Jak vám mohu pomoci?,Hvordan kan jeg hjælpe dig?,Wie kann ich dir helfen?,,Kiel mi helpu vin?,¿Cómo puedo ayudarte?,,Kuinka voin olla avuksi?,Comment puis-je vous assister?,Miben segíthetek?,Come posso aiutarti?,何かお困りですか?,제가 어떻게 도와드릴까요?,Hoe kan ik u helpen?,Hva kan jeg hjelpe deg med?,Jak mogę ci pomóc?,Como posso ajudar?,,Cu ce vă pot ajuta?,Чем могу помочь?,,Size nasıl yardımcı olabilirim? -Med patch,TXT_RPLY0_SCRIPT02_D21224_MEDPA,〃,,,Obvaz,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekääre,Pansement,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинтами,,Tıbbi yama -Here's your patch.,TXT_RYES0_SCRIPT02_D21224_HERES,〃,,,Jeden obvaz.,Her er dit plaster.,Hier ist deine Bandage,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä kääreenne.,Voilà votre pansement.,Itt a tapaszod,Ecco le bende.,これをどうぞ。,의료 붕대 여깄습니다.,Hier is je patch.,Her er medisinplasteret ditt.,Oto twój bandaż.,Aqui está sua compressa.,,Poftiți trusa.,Вот они.,,İşte yamanız. -You need 10 gold for that.,TXT_RNO0_SCRIPT02_D21224_YOUNE,〃,,,Na ten potřebujete deset zlatých.,Du skal bruge 10 guld for det.,Dafür brauchst du 10 Gold.,,Vi bezonas 10 da oro.,Necesitas 10 de oro.,,Siihen tarvitset 10 kolikkoa.,Il vous faut 10 pièces pour cela.,10 Aranyra lesz szükséged ehhez.,Ti servono 10 pezzi d'oro per quello.,10 ゴールド必要です。,10 골드가 필요합니다.,Daar heb je 10 goud voor nodig.,Du trenger 10 gull for det.,Potrzebujesz 10 monet aby to kupić.,Você precisa de 10 de ouro para isso.,,Ai nevoie de 10 monezi de aur pentru asta.,Тебе не хватает 10 золотых.,,Bunun için 10 altına ihtiyacın var. -Medical kit,TXT_RPLY1_SCRIPT02_D21224_MEDIC,〃,,,Lékárničku,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku,Kit médical,Elsősegély készlet,Kit medico,医療用キット,구급 키트,Medische kit,Medisinsk utstyr,Apteczka,Kit médico,,Kit de Prim-Ajutor,Аптечкой,,Tıbbi kit -Thank you.,TXT_RYES1_SCRIPT02_D21224_THANK,〃,,,Děkuji.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm,Grazie.,ありがとうございます。,이용 감사드려요.,Bedankt.,Takk skal du ha.,Dziękuję.,Agradeço.,,Mulțumesc.,Спасибо.,,Teşekkür ederim. +comprar algo, zopenco! ",,"Palataan asiaan, kun teidän on mahdollista ostaa jotain himoitsemaanne.","Revenez quand vous avez de l'argent, rustre!","Majd akkor gyere vissza, ha lesz pénzed megvenni bármit is, te fajankó!","Ritorna quando potrai permetterti di comprare le cose, cafone!",余裕がある時にまたどうぞ!,이런 거래는 못 하겠습니다. 돈을 모아서 다시 찾아오시길!,Kom terug wanneer je het je kunt veroorloven om iets te kopen wat je louteren kunt!,"Kom tilbake når du har råd til å kjøpe noe, din lømmel!",Wróć kiedy będziesz mógł coś kupić prostaku!,"Volte quando você puder comprar algo, seu caloteiro!",,"Revin-o când o să ai bani să poți cumpăra ceva, secătură!","Возвращайся, когда сможешь позволить себе купить что-нибудь, придурок!",,"Kom tillbaka när du har råd att köpa något, din tölp!",Bir şeyler satın almaya gücün yettiğinde geri gel! +How may I assist you?,TXT_DLG_SCRIPT02_D21224_HOWMA,MAP02: Hospital.,,,Jak vám mohu pomoci?,Hvordan kan jeg hjælpe dig?,Wie kann ich dir helfen?,,Kiel mi helpu vin?,¿Cómo puedo ayudarte?,,Kuinka voin olla avuksi?,Comment puis-je vous assister?,Miben segíthetek?,Come posso aiutarti?,何かお困りですか?,제가 어떻게 도와드릴까요?,Hoe kan ik u helpen?,Hva kan jeg hjelpe deg med?,Jak mogę ci pomóc?,Como posso ajudar?,,Cu ce vă pot ajuta?,Чем могу помочь?,,Hur kan jag hjälpa dig?,Size nasıl yardımcı olabilirim? +Med patch,TXT_RPLY0_SCRIPT02_D21224_MEDPA,〃,,,Obvaz,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekääre,Pansement,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинтами,,Medicinsk plåster,Tıbbi yama +Here's your patch.,TXT_RYES0_SCRIPT02_D21224_HERES,〃,,,Jeden obvaz.,Her er dit plaster.,Hier ist deine Bandage,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä kääreenne.,Voilà votre pansement.,Itt a tapaszod,Ecco le bende.,これをどうぞ。,의료 붕대 여깄습니다.,Hier is je patch.,Her er medisinplasteret ditt.,Oto twój bandaż.,Aqui está sua compressa.,,Poftiți trusa.,Вот они.,,Här är ditt plåster.,İşte yamanız. +You need 10 gold for that.,TXT_RNO0_SCRIPT02_D21224_YOUNE,〃,,,Na ten potřebujete deset zlatých.,Du skal bruge 10 guld for det.,Dafür brauchst du 10 Gold.,,Vi bezonas dek da oro.,Necesitas diez de oro.,,Siihen tarvitset 10 kolikkoa.,Il vous faut 10 pièces pour cela.,10 Aranyra lesz szükséged ehhez.,Ti servono 10 pezzi d'oro per quello.,10 ゴールド必要です。,10 골드가 필요합니다.,Daar heb je 10 goud voor nodig.,Du trenger 10 gull for det.,Potrzebujesz 10 monet aby to kupić.,Você precisa de 10 de ouro para isso.,,Ai nevoie de 10 monezi de aur pentru asta.,Тебе не хватает 10 золотых.,,Du behöver 10 guld för den.,Bunun için 10 altına ihtiyacın var. +Medical kit,TXT_RPLY1_SCRIPT02_D21224_MEDIC,〃,,,Lékárničku,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku,Kit médical,Elsősegély készlet,Kit medico,医療用キット,구급 키트,Medische kit,Medisinsk utstyr,Apteczka,Kit médico,,Kit de Prim-Ajutor,Аптечкой,,Medicinsk utrustning,Tıbbi kit +Thank you.,TXT_RYES1_SCRIPT02_D21224_THANK,〃,,,Děkuji.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm,Grazie.,ありがとうございます。,이용 감사드려요.,Bedankt.,Takk skal du ha.,Dziękuję.,Agradeço.,,Mulțumesc.,Спасибо.,,Tack.,Teşekkür ederim. "I wish I could give them away, but they cost 25 gold.",TXT_RNO1_SCRIPT02_D21224_IWISH,〃,,,"Přál bych si je dávat zadarmo, ale stojí 25 zlatých.","Jeg ville ønske, jeg kunne give dem væk, men de koster 25 guld.","Ich wünschte ich könnte sie weggeben, aber sie kosten 25 Gold.",,"Mi donacus ĝin, sed ĝi kostas 25 da oro.","Ojalá pudiera regalarlo, -pero cuesta 25 de oro.",,"Mielelläni antaisin ilmaiseksi, mutta ne maksavat 25 kultakolikkoa.","J'aimerais vraiment les donner gratuitement, mais cela côute 25 pièces.","Bárcsak ingyen osztogathatnám, de 25 aranyba kerül.","Mi piacerebbe darli via, ma costano 25 pezzi d'oro.",譲渡したい所ですが、25 ゴールド必要です。,"주고 싶지만, 이것의 가격은 25 골드입니다.","Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.","Jeg skulle ønske jeg kunne gi dem bort, men de koster 25 gull.","Chciałbym móc je rozdać, ale one kosztują 25 monet.","Bem que eu queria poder dar de graça, mas custam 25 de ouro.",,"Mi-aș dori să le pot da pe gratis, dar costă 25 de monezi de aur.","С радостью бы отдал, но они по 25 золотых.",,Keşke onları verebilseydim ama 25 altına mal oluyorlar. -Field surgery kit,TXT_RPLY2_SCRIPT02_D21224_FIELD,〃,,,Chirurgickou soupravu,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Kirurgisett,Polowy zestaw chirurga,Kit de cirurgia,,Trusă de chirurgie de teren,Медкомплектом,,Saha ameliyat kiti -There you go. Take care now.,TXT_RYES2_SCRIPT02_D21224_THERE,〃,,,Tady máte. Buďte opatrný.,Værsgo. Pas godt på dig selv nu.,Bitte schön. Mach's gut.,,Jen. Estu atenta.,Aquí tienes. Cuídate.,,Olkaa hyvä. Pitäkää itsestänne huoli.,Voilà pour vous. Faites attention à vous maintenant.,"Tessék, minden jót!",Ecco qua. Stammi bene.,こちらになります、お気をつけて。,여기 있습니다. 잘 쓰세요.,Daar ga je. Pas goed op jezelf.,Vær så god. Ta vare på deg selv.,Proszę bardzo. Trzymaj się.,Aqui está. Se cuida.,,Poftiți. Aveți grijă.,Пожалуйста. Береги себя!,,Al bakalım. Kendine iyi bak. +pero cuesta 25 de oro.",,"Mielelläni antaisin ilmaiseksi, mutta ne maksavat 25 kultakolikkoa.","J'aimerais vraiment les donner gratuitement, mais cela côute 25 pièces.","Bárcsak ingyen osztogathatnám, de 25 aranyba kerül.","Mi piacerebbe darli via, ma costano 25 pezzi d'oro.",譲渡したい所ですが、25 ゴールド必要です。,"주고 싶지만, 이것의 가격은 25 골드입니다.","Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.","Jeg skulle ønske jeg kunne gi dem bort, men de koster 25 gull.","Chciałbym móc je rozdać, ale one kosztują 25 monet.","Bem que eu queria poder dar de graça, mas custam 25 de ouro.",,"Mi-aș dori să le pot da pe gratis, dar costă 25 de monezi de aur.","С радостью бы отдал, но они по 25 золотых.",,"Jag önskar att jag kunde ge bort dem, men de kostar 25 guld.",Keşke onları verebilseydim ama 25 altına mal oluyorlar. +Field surgery kit,TXT_RPLY2_SCRIPT02_D21224_FIELD,〃,,,Chirurgickou soupravu,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Kirurgisett,Polowy zestaw chirurga,Kit de cirurgia,,Trusă de chirurgie de teren,Медкомплектом,,Fältkirurgisk utrustning,Saha ameliyat kiti +There you go. Take care now.,TXT_RYES2_SCRIPT02_D21224_THERE,〃,,,Tady máte. Buďte opatrný.,Værsgo. Pas godt på dig selv nu.,Bitte schön. Mach's gut.,,Jen. Estu atenta.,Toma. Cuídate.,,Olkaa hyvä. Pitäkää itsestänne huoli.,Voilà pour vous. Faites attention à vous maintenant.,"Tessék, minden jót!",Ecco qua. Stammi bene.,こちらになります、お気をつけて。,여기 있습니다. 잘 쓰세요.,Daar ga je. Pas goed op jezelf.,Vær så god. Ta vare på deg selv.,Proszę bardzo. Trzymaj się.,Aqui está. Se cuida.,,Poftiți. Aveți grijă.,Пожалуйста. Береги себя!,,Här har du det. Ta hand om dig nu.,Al bakalım. Kendine iyi bak. "Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT02_D21224_WELLM,〃,,,"No, spíš byste si mohl dovolit nějaké obvazy?","Nå, måske har du råd til nogle medicinske plastre?","Nun, vielleicht kannst du dir ein paar medizinische Bandagen leisten?",,"Nu, ĉu vi eble povas aĉeti kuracbendojn?","Bueno, ¿quizás tengas para comprar tiritas?","Bueno, ¿tal vez tengas -para comprar curitas?",Olisiko teillä kuitenkin sidekääreisiin ehkä varaa?,"Eh bien, peut être que vous pouvez vous acheter quelques pansements?",Talán némi ragtapaszra tudnál költeni?,"Niente da fare, ma forse puoi permetterti delle bende?",ところで、医薬パッチを買う余裕はありますか?,"글쎄요, 아마 의료 붕대 정돈 살 수 있을걸요?","Nou ja, misschien kunt je zich wat med-patches veroorloven?",Kanskje du har råd til noen medisinplaster?,"Cóż, może stać cię na jakieś bandaże?","Bem, talvez você possa comprar algumas compressas?",,"Păi, poate îți permiți niște truse de prim-ajutor?","Тогда, может быть, купишь несколько бинтов?",,Belki ilaç yamalarını karşılayabilirsin? -"I hope Macil knows what he's doing. If the Order finds out I'm helping the Front I'm as good as dead... Not that this matters to you any. The Front's medic gave me an upgrade chip for you, are you ready? ",TXT_DLG_SCRIPT02_D22740_IHOPE,〃 (After destroying the crystal in the Power Station),,,"Doufám, že Macil ví, co dělá. Jestli Řád zjistí, že pomáhám Frontě, jsem mrtvý... Ne, že by vás to mělo trápit. Medik Fronty mi pro vás dal vylepšovací čip, připraven?","Jeg håber, at Macil ved, hvad han laver. Hvis Ordenen finder ud af, at jeg hjælper fronten, er jeg så godt som død... Ikke at det har nogen betydning for dig. Frontens læge gav mig en opgraderingschip til dig, er du klar?","Ich hoffe Macil weiß was er tut. Wenn der Orden herausfindet das ich der Front helfe, bin ich so gut wie tot... auch wenn es für dich keine Rolle spielt. Ein Sanitäter der Front hat mir einen Verbesserungschip für dich mitgegeben, bist du bereit?",,"Mi esperas, ke Macil scias tion, kion li faras. Se La Ordono malkovras, ke mi helpas la Fronton, mi estos sufiĉe mortinta... Ne kvazaŭ vi zorgus pri tio. La kuracisto de la Fronto donis al mi plibonigan icon por vi. Ĉu vi estas preta?","Espero que Macil sepa lo que está haciendo. Si La Orden se entera de que estoy ayudando al Frente, estoy bien muerto... No es como si te importara. El médico del Frente me dio un chip de mejora para ti. ¿Estás listo?",,"Toivottavasti Macil tietää, mitä tekee. Jos Veljeskunta saa kuulla minun auttavan Rintamaa, olen mennyttä... Ei siinä, että tieto sinua mitenkään kiinnostaisi. Sain Rintaman lääkintämieheltä sinulle päivityssirun; oletko valmis?","J'espère que Macil sait ce qu'il fait. Si l'Ordre se rend compte que j'aide le Front, c'est comme si j'étais mort.. bon, cela ne vous importe pas. Le médecin du Front m'a donné une puce d'augmentation pour vous. Etes vous prêt?","Remélem Macil tudja, mit csinál. Ha a Rend rájön, hogy a Frontot segítem, alulról szagolom majd az ibolyát...Nem mintha ez számítana számodra. A Front orvosa egy fejlesztési chipet küldött neked. Készen állsz?","Spero che Macil sappia quello che sta facendo. Se l'Ordine scopre che sto aiutando il Fronte sarò bello che morto... Non che questo importi ormai. Il medico del Fronte mi ha dato un upgrade chip per te, sei pronto?","マシルの行いが正しければ良いですが。 +para comprar curitas?",Olisiko teillä kuitenkin sidekääreisiin ehkä varaa?,"Eh bien, peut être que vous pouvez vous acheter quelques pansements?",Talán némi ragtapaszra tudnál költeni?,"Niente da fare, ma forse puoi permetterti delle bende?",ところで、医薬パッチを買う余裕はありますか?,"글쎄요, 아마 의료 붕대 정돈 살 수 있을걸요?","Nou ja, misschien kunt je zich wat med-patches veroorloven?",Kanskje du har råd til noen medisinplaster?,"Cóż, może stać cię na jakieś bandaże?","Bem, talvez você possa comprar algumas compressas?",,"Păi, poate îți permiți niște truse de prim-ajutor?","Тогда, может быть, купишь несколько бинтов?",,Du kanske har råd med några medicinska plåster?,Belki ilaç yamalarını karşılayabilirsin? +"I hope Macil knows what he's doing. If the Order finds out I'm helping the Front I'm as good as dead... Not that this matters to you any. The Front's medic gave me an upgrade chip for you, are you ready? ",TXT_DLG_SCRIPT02_D22740_IHOPE,〃 (After destroying the crystal in the Power Station),,,"Doufám, že Macil ví, co dělá. Jestli Řád zjistí, že pomáhám Frontě, jsem mrtvý... Ne, že by vás to mělo trápit. Medik Fronty mi pro vás dal vylepšovací čip, připraven?","Jeg håber, at Macil ved, hvad han laver. Hvis Ordenen finder ud af, at jeg hjælper fronten, er jeg så godt som død... Ikke at det har nogen betydning for dig. Frontens læge gav mig en opgraderingschip til dig, er du klar?","Ich hoffe Macil weiß was er tut. Wenn der Orden herausfindet das ich der Front helfe, bin ich so gut wie tot... auch wenn es für dich keine Rolle spielt. Ein Sanitäter der Front hat mir einen Verbesserungschip für dich mitgegeben, bist du bereit?",,"Mi esperas, ke Macil scias tion, kion li faras. Se La Ordeno malkovras, ke mi helpas la Fronton, mi estos sufiĉe mortinta... Ne kvazaŭ vi zorgus pri tio. La kuracisto de la Fronto donis al mi plibonigan icon por vi. Ĉu vi estas preta?","Espero que Macil sepa lo que está haciendo. Si La Orden se entera de que estoy ayudando al Frente, estoy bien muerto... No es como si te importara. El médico del Frente me dio un chip de mejora para ti. ¿Estás listo?",,"Toivottavasti Macil tietää, mitä tekee. Jos Veljeskunta saa kuulla minun auttavan Rintamaa, olen mennyttä... Ei siinä, että tieto sinua mitenkään kiinnostaisi. Sain Rintaman lääkintämieheltä sinulle päivityssirun; oletko valmis?","J'espère que Macil sait ce qu'il fait. Si l'Ordre se rend compte que j'aide le Front, c'est comme si j'étais mort.. bon, cela ne vous importe pas. Le médecin du Front m'a donné une puce d'augmentation pour vous. Etes vous prêt?","Remélem Macil tudja, mit csinál. Ha a Rend rájön, hogy a Frontot segítem, alulról szagolom majd az ibolyát...Nem mintha ez számítana számodra. A Front orvosa egy fejlesztési chipet küldött neked. Készen állsz?","Spero che Macil sappia quello che sta facendo. Se l'Ordine scopre che sto aiutando il Fronte sarò bello che morto... Non che questo importi ormai. Il medico del Fronte mi ha dato un upgrade chip per te, sei pronto?","マシルの行いが正しければ良いですが。 私がフロントを援助しているとオーダーが 知ったら、私は...これは貴方には関係無いか。 フロントのメディックが貴方へ アップグレードチップを送ってくれました、 装着しますか? ",마실 사령관님이 하는 일이 무엇인지 알고 있기를... 만약 오더가 내가 프론트를 위해 일한다는 걸 눈치챈다면 절 죽일 거예요. 물론 당신이 알 바는 아니지만. 프론트 의무관님이 업그레이드 칩을 당신에게 이식하라고 여기까지 가져왔더군요. 준비되셨습니까?,"Ik hoop dat Macil weet wat hij doet. Als de Orde erachter komt dat ik het Front help, ben ik zo goed als dood.... Niet dat dit belangrijk voor je is. De dokter van het Front heeft me een upgradechip voor je gegeven, ben je er klaar voor?","Jeg håper Macil vet hva han gjør. Hvis Ordenen finner ut at jeg hjelper Fronten, er jeg så godt som død... Ikke at det betyr noe for deg. Frontens lege ga meg en oppgraderingsbrikke til deg. Er du klar?","Mam nadzieję, że Macil wie co robi. Jeśli Zakon odkryje, że pomagam Frontowi, będę martwy... Nie to, że kogokolwiek to obchodzi. Medyk frontu dał mi czip ulepszający dla ciebie, jesteś gotowy?","Espero que Macil saiba o que está fazendo. Se a Ordem descobrir que estou ajudando a Frente, estou morto... Não que isso importe para vocês. O médico da Frente me passou um chip de upgrade pra você, está preparado?",,"Sper că Macil știe ce face. Dacă Ordinul află că ajut Frontul sunt ca și mort. Nu-i ca și cum te-ar interesa asta. Medicul Frontului mi-a dat un cip pentru upgrade, ești pregătit?","Надеюсь, Мэйсил знает, что делает. Если Орден обнаружит, что я помогаю повстанцам, я не жилец... хотя тебе-то какое дело. Медик Сопротивления передал мне этот чип для тебя. Ты готов? -",,"Umarım Macil ne yaptığını biliyordur. Tarikat Cephe'ye yardım ettiğimi öğrenirse ölmüş sayılırım. Bu senin için önemli değil. Cephe'nin doktoru bana senin için bir yükseltme çipi verdi, hazır mısın?" -"Yes, I'm ready.",TXT_RPLY0_SCRIPT02_D22740_YESIM,〃,,,"Ano, jsem připravený.","Ja, jeg er klar.","Ja, ich bin bereit.",,"Jes, mi estas preta.","Sí, estoy listo.",,"Kyllä, olen valmis.","Oui, je suis prêt.","Igen, készen állok.","Sì, sono pronto.",ああ、準備良しだ。,"좋아요, 준비 됐습니다.","Ja, ik ben er klaar voor.","Ja, jeg er klar.","Tak, jestem gotowy.","Sim, estou preparado.",,"Da, sunt pregătit.","Да, готов.",,"Evet, hazırım." +",,"Jag hoppas att Macil vet vad han gör. Om Orden får reda på att jag hjälper fronten är jag så gott som död... Inte för att det spelar någon roll för dig. Frontens läkare gav mig ett uppgraderingschip till dig, är du redo?","Umarım Macil ne yaptığını biliyordur. Tarikat Cephe'ye yardım ettiğimi öğrenirse ölmüş sayılırım. Bu senin için önemli değil. Cephe'nin doktoru bana senin için bir yükseltme çipi verdi, hazır mısın?" +"Yes, I'm ready.",TXT_RPLY0_SCRIPT02_D22740_YESIM,〃,,,"Ano, jsem připravený.","Ja, jeg er klar.","Ja, ich bin bereit.",,"Jes, mi estas preta.","Sí, estoy listo.",,"Kyllä, olen valmis.","Oui, je suis prêt.","Igen, készen állok.","Sì, sono pronto.",ああ、準備良しだ。,"좋아요, 준비 됐습니다.","Ja, ik ben er klaar voor.","Ja, jeg er klar.","Tak, jestem gotowy.","Sim, estou preparado.",,"Da, sunt pregătit.","Да, готов.",,"Ja, jag är redo.","Evet, hazırım." "Well then, this won't take but a second. There, done already.",TXT_RYES0_SCRIPT02_D22740_WELLT,〃,,,"Tak dobře, měla by to být jen vteřinka. Tak, a je hotovo.","Nå, så tager det kun et øjeblik. Sådan, det er allerede gjort.","Nun dann, das wird nicht mal eine Sekunde dauern. So, bereits erledigt.",,"Bone, mi bezonos nur unu sekundon... kaj finite.","Muy bien, solo un -segundo... Y listo.",,"Siinä tapauksessa tähän ei mene paria sekuntia pidempään. Kas näin, valmista jo.","Bon, cela ne prendra qu'une seconde. Voilà, c'est fait.","Jól van hát, nem fog csak egy pár másodpercig tartani... És kész is.","Bene, non ci vorrà molto. Ecco fatto.",それでは、これに時間は掛かりません。はい、完了しました。,"그럼 잠깐이면 됩니다. 자, 다 됐어요.","Nou dan, dit duurt maar een seconde. Daar, al klaar.","Da tar det bare et øyeblikk. Sånn, ferdig.","Dobrze więc, to zajmie tylko sekundę. Już, gotowe.","Muito bem, isso vai levar um segundo. Pronto, já terminei.",,"Bine atunci, va dura doar o secundă. Așa, e gata deja.","Хорошо. Секундочку... Всё, готово.",,"O zaman bir saniye bile sürmez. İşte, bitti bile." -How may I assist you?,TXT_DLG_SCRIPT02_D24256_HOWMA,〃,,,Jak vám mohu pomoci?,Hvordan kan jeg hjælpe dig?,Wie kann ich dir helfen?,,Kiel mi helpu vin?,¿Cómo puedo ayudarte?,,Kuinka voin olla avuksi?,Comment puis-je vous assister?,Miben segíthetek?,Come posso aiutarti?,何かお困りですか?,어떻게 도와드릴까요?,Hoe kan ik je helpen?,Hva kan jeg hjelpe deg med?,Jak mogę ci pomóc?,Como posso ajudar?,,Cu ce vă pot ajuta?,Чем могу тебе помочь?,,Size nasıl yardımcı olabilirim? -Med patch,TXT_RPLY0_SCRIPT02_D24256_MEDPA,〃,,,Obvaz,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekääre,Pansement,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster.,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинтами,,Tıbbi yama -Here's your patch.,TXT_RYES0_SCRIPT02_D24256_HERES,〃,,,Jeden obvaz.,Her er dit plaster.,Hier ist deine Bandage,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä kääreenne.,Voilà votre pansement.,Itt a tapaszod.,Ecco le bende.,これをどうぞ。,여기 의료 붕대입니다.,Hier is je patch.,Her er plasteret ditt.,Oto twój bandaż.,Aqui está sua compressa.,,Poftiți trusa.,Вот они.,,İşte yamanız. -You need 10 gold for that.,TXT_RNO0_SCRIPT02_D24256_YOUNE,〃,,,Na ten potřebujete deset zlatých.,Du skal bruge 10 guld for det.,Dafür brauchst du 10 Gold.,,Vi bezonas 10 da oro.,Necesitas 10 de oro.,,Tarvitset siihen 10 kolikkoa.,Il vous faut 10 pièces pour cela.,10 aranyra van szükséged ehhez.,Ti servono 10 pezzi d'oro per quello.,10 ゴールド必要です。,10 골드가 필요한데.,Daar heb je 10 goud voor nodig.,Du trenger 10 gull for det.,Potrzebujesz 10 monet aby to kupić.,Você precisa de 10 de ouro pra isso.,,Ai nevoie de 10 monezi de aur pentru asta.,Тебе не хватает 10 золотых.,,Bunun için 10 altına ihtiyacın var. -Medical kit,TXT_RPLY1_SCRIPT02_D24256_MEDIC,〃,,,Lékárničku,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku,Kit médical,Orvosi csomag.,Kit medico,医療用キット,구급 키트,Medische kit,Medisinsk utstyr,Apteczka,Kit médico,,Kit de Prim-Ajutor,Аптечкой,,Tıbbi kit -Thank you.,TXT_RYES1_SCRIPT02_D24256_THANK,〃,,,Děkuji.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm.,Grazie.,ありがとうございます。,또 오세요.,Bedankt.,Takk skal du ha.,Dziękuję.,Agradeço.,,Mulțumesc.,Спасибо.,,Teşekkür ederim. +segundo... Y listo.",,"Siinä tapauksessa tähän ei mene paria sekuntia pidempään. Kas näin, valmista jo.","Bon, cela ne prendra qu'une seconde. Voilà, c'est fait.","Jól van hát, nem fog csak egy pár másodpercig tartani... És kész is.","Bene, non ci vorrà molto. Ecco fatto.",それでは、これに時間は掛かりません。はい、完了しました。,"그럼 잠깐이면 됩니다. 자, 다 됐어요.","Nou dan, dit duurt maar een seconde. Daar, al klaar.","Da tar det bare et øyeblikk. Sånn, ferdig.","Dobrze więc, to zajmie tylko sekundę. Już, gotowe.","Muito bem, isso vai levar um segundo. Pronto, já terminei.",,"Bine atunci, va dura doar o secundă. Așa, e gata deja.","Хорошо. Секундочку... Всё, готово.",,"Då tar det här bara en sekund. Där, redan gjort.","O zaman bir saniye bile sürmez. İşte, bitti bile." +How may I assist you?,TXT_DLG_SCRIPT02_D24256_HOWMA,〃,,,Jak vám mohu pomoci?,Hvordan kan jeg hjælpe dig?,Wie kann ich dir helfen?,,Kiel mi helpu vin?,¿Cómo puedo ayudarte?,,Kuinka voin olla avuksi?,Comment puis-je vous assister?,Miben segíthetek?,Come posso aiutarti?,何かお困りですか?,어떻게 도와드릴까요?,Hoe kan ik je helpen?,Hva kan jeg hjelpe deg med?,Jak mogę ci pomóc?,Como posso ajudar?,,Cu ce vă pot ajuta?,Чем могу тебе помочь?,,Hur kan jag hjälpa dig?,Size nasıl yardımcı olabilirim? +Med patch,TXT_RPLY0_SCRIPT02_D24256_MEDPA,〃,,,Obvaz,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekääre,Pansement,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster.,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинтами,,Med patch,Tıbbi yama +Here's your patch.,TXT_RYES0_SCRIPT02_D24256_HERES,〃,,,Jeden obvaz.,Her er dit plaster.,Hier ist deine Bandage,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä kääreenne.,Voilà votre pansement.,Itt a tapaszod.,Ecco le bende.,これをどうぞ。,여기 의료 붕대입니다.,Hier is je patch.,Her er plasteret ditt.,Oto twój bandaż.,Aqui está sua compressa.,,Poftiți trusa.,Вот они.,,Här är ditt plåster.,İşte yamanız. +You need 10 gold for that.,TXT_RNO0_SCRIPT02_D24256_YOUNE,〃,,,Na ten potřebujete deset zlatých.,Du skal bruge 10 guld for det.,Dafür brauchst du 10 Gold.,,Vi bezonas dek da oro.,Necesitas diez de oro.,,Tarvitset siihen 10 kolikkoa.,Il vous faut 10 pièces pour cela.,10 aranyra van szükséged ehhez.,Ti servono 10 pezzi d'oro per quello.,10 ゴールド必要です。,10 골드가 필요한데.,Daar heb je 10 goud voor nodig.,Du trenger 10 gull for det.,Potrzebujesz 10 monet aby to kupić.,Você precisa de 10 de ouro pra isso.,,Ai nevoie de 10 monezi de aur pentru asta.,Тебе не хватает 10 золотых.,,Du behöver 10 guld för det.,Bunun için 10 altına ihtiyacın var. +Medical kit,TXT_RPLY1_SCRIPT02_D24256_MEDIC,〃,,,Lékárničku,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku,Kit médical,Orvosi csomag.,Kit medico,医療用キット,구급 키트,Medische kit,Medisinsk utstyr,Apteczka,Kit médico,,Kit de Prim-Ajutor,Аптечкой,,Medicinsk utrustning,Tıbbi kit +Thank you.,TXT_RYES1_SCRIPT02_D24256_THANK,〃,,,Děkuji.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm.,Grazie.,ありがとうございます。,또 오세요.,Bedankt.,Takk skal du ha.,Dziękuję.,Agradeço.,,Mulțumesc.,Спасибо.,,Tack.,Teşekkür ederim. "I wish I could give them away, but they cost 25 gold.",TXT_RNO1_SCRIPT02_D24256_IWISH,〃,,,"Přál bych si je dávat zadarmo, ale stojí 25 zlatých.","Jeg ville ønske, jeg kunne give dem væk, men de koster 25 guld.","Ich wünschte ich könnte sie weggeben, aber sie kosten 25 Gold.",,"Mi donacus ĝin, sed ĝi kostas 25 da oro.","Ojalá pudiera regalarlo, -pero cuesta 25 de oro.",,"Kunpa voisinkin antaa niitä ilmaiseksi, mutta ne maksavat 25 kultakolikkoa.","J'aimerais vraiment les donner gratuitement, mais cela côute 25 pièces.","Bárcsak ingyen osztogathatnám, de 25 aranyba kerül.","Mi piacerebbe darli via, ma costano 25 pezzi d'oro.",譲渡したい所ですが、25 ゴールド必要です。,25 골드만 있다면 이건 당신 것인데 말이죠.,"Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.","Jeg skulle ønske jeg kunne gi dem bort, men de koster 25 gull.","Chciałbym móc je rozdać, ale one kosztują 25 monet.","Bem que eu queria poder dar de graça, mas custam 25 de ouro.",,"Mi-aș dori să le pot da pe gratis, dar costă 25 de monezi de aur.","С радостью бы отдал, но они по 25 золотых.",,Keşke onları verebilseydim ama 25 altına mal oluyorlar. -Field surgery kit,TXT_RPLY2_SCRIPT02_D24256_FIELD,〃,,,Chirurgickou soupravu,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Kirurgisett,Polowy zestaw chirurga,Kit de cirurgia,,Trusă de chirurgie de teren,Медкомплект,,Saha ameliyat kiti -There you go. Take care now.,TXT_RYES2_SCRIPT02_D24256_THERE,〃,,,Tady máte. Buďte opatrný.,Værsgo. Pas godt på dig selv nu.,Bitte schön. Mach's gut.,,Jen. Estu atenta.,Aquí tienes. Cuídate.,,Olkaa hyvä. Pitäkää itsestänne huoli.,Voilà pour vous. Faites attention à vous maintenant.,Parancsolj! Aztán vigyázz magadra!,Ecco qua. Stammi bene.,こちらになります、お気をつけて。,여기 있습니다. 잘 쓰세요.,Daar ga je. Pas goed op jezelf.,Vær så god. Ta vare på deg selv.,Proszę bardzo. Trzymaj się.,Aqui está. Se cuida.,,Poftiți. Aveți grijă.,Пожалуйста. Береги себя!,,Al bakalım. Kendine iyi bak. +pero cuesta 25 de oro.",,"Kunpa voisinkin antaa niitä ilmaiseksi, mutta ne maksavat 25 kultakolikkoa.","J'aimerais vraiment les donner gratuitement, mais cela côute 25 pièces.","Bárcsak ingyen osztogathatnám, de 25 aranyba kerül.","Mi piacerebbe darli via, ma costano 25 pezzi d'oro.",譲渡したい所ですが、25 ゴールド必要です。,25 골드만 있다면 이건 당신 것인데 말이죠.,"Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.","Jeg skulle ønske jeg kunne gi dem bort, men de koster 25 gull.","Chciałbym móc je rozdać, ale one kosztują 25 monet.","Bem que eu queria poder dar de graça, mas custam 25 de ouro.",,"Mi-aș dori să le pot da pe gratis, dar costă 25 de monezi de aur.","С радостью бы отдал, но они по 25 золотых.",,"Jag önskar att jag kunde ge bort dem, men de kostar 25 guld.",Keşke onları verebilseydim ama 25 altına mal oluyorlar. +Field surgery kit,TXT_RPLY2_SCRIPT02_D24256_FIELD,〃,,,Chirurgickou soupravu,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Kirurgisett,Polowy zestaw chirurga,Kit de cirurgia,,Trusă de chirurgie de teren,Медкомплект,,Fältkirurgisk utrustning,Saha ameliyat kiti +There you go. Take care now.,TXT_RYES2_SCRIPT02_D24256_THERE,〃,,,Tady máte. Buďte opatrný.,Værsgo. Pas godt på dig selv nu.,Bitte schön. Mach's gut.,,Jen. Estu atenta.,Toma. Cuídate.,,Olkaa hyvä. Pitäkää itsestänne huoli.,Voilà pour vous. Faites attention à vous maintenant.,Parancsolj! Aztán vigyázz magadra!,Ecco qua. Stammi bene.,こちらになります、お気をつけて。,여기 있습니다. 잘 쓰세요.,Daar ga je. Pas goed op jezelf.,Vær så god. Ta vare på deg selv.,Proszę bardzo. Trzymaj się.,Aqui está. Se cuida.,,Poftiți. Aveți grijă.,Пожалуйста. Береги себя!,,Här har du det. Ta hand om dig nu.,Al bakalım. Kendine iyi bak. "Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT02_D24256_WELLM,〃,,,"No, spíš byste si mohl dovolit nějaké obvazy?","Nå, måske har du råd til nogle medicinske plastre?","Nun, vielleicht kannst du dir ein paar medizinische Bandagen leisten?",,"Nu, ĉu vi eble povas aĉeti kuracbendojn?","Bueno, ¿quizás tengas para comprar tiritas?","Bueno, ¿tal vez tengas -para comprar curitas?",Olisiko teillä ehkä varaa sidekääreisiin?,"Eh bien, peut être que vous pouvez vous acheter quelques pansements?","Nos, talán telik pár ragtapaszra is?","Niente da fare, ma forse puoi permetterti delle bende?",ところで、医薬パッチを買う余裕はありますか?,글쎄요... 의료 붕대는 어떻습니까?,"Nou ja, misschien kunt je zich wat med-patches veroorloven?",Kanskje du har råd til noen medisinplaster?,"Cóż, może stać cię na jakieś bandaże?","Bem, talvez você possa comprar algumas compressas?",,"Păi, poate îți permiți niște truse de prim-ajutor?","Тогда, может быть, купишь несколько бинтов?",,Belki birkaç ilaç yamasını karşılayabilirsin? -"Hello stranger, I haven't seen you around here before. Let me give you a piece of free advice. I'd be careful if I were you. The Order does not tolerate free will, and their justice is swift.",TXT_DLG_SCRIPT02_D25772_HELLO,MAP02: Barkeep.,,,"Vítejte, cizinče, vás jsem tu ještě neviděl. Dám vám drobnou radu na začátek grátis: Být vámi, byl bych opatrný. Řád netoleruje svobodnou vůli a jejich spravedlnost je hbitá. ","Hej fremmede, jeg har ikke set dig her før. Lad mig give dig et gratis råd. Jeg ville være forsigtig, hvis jeg var dig. Ordenen tolererer ikke fri vilje, og deres retfærdighed er hurtig.","Hallo, Fremder. Ich habe dich hier vorher noch nie gesehen. Lass mich dir einen kostenlosen Rat geben. An deiner Stelle wäre ich vorsichtig. Der Orden duldet keinen freien Willen und sie greifen hart durch.",,"Saluton, fremdulo, mi ne vidis vin ĉi tie antaŭe. Jen senpaga konsilo: mi estus atenta se mi estus vi; La Ordono ne toleras liberan volon kaj havas rapidan «juston».","Hola, extranjero, no te he visto por aquí antes. Te daré un consejo gratis: tendría cuidado si fuera tú; La Orden no tolera el libre albedrío y su justicia es veloz.","Hola, extranjero, es la primera vez que te veo por aquí. Te voy a dar un consejo gratis: tendría cuidado si fuera tú; La Orden no tolera el libre albedrío y su justicia es veloz.","Päivää. En olekaan nähnyt teitä täällä ennen. Teinä neuvoisin olemaan varuillanne. Veljeskunta ei suvaitse vapaata tahtoa, ja heidän tuomionsa ovat pikaiset.","Bien le bonjour, étranger. On ne vous a pas encore vu dans ce coin. Laissez-moi vous donner un petit conseil. Je ferais attention si j'étais vous. L'Ordre ne tolère pas le libre arbitre et leur justice est fulgurante.","Üdvözöllek idegen, nem láttalak még itt a környéken. Hadd adjak egy ingyen tanácsot. Én óvatos lennék a helyedben. A Rend nem tolerálja a szabad akaratot, és elég fürge az igazságszolgáltatás.","Salve straniero, non ti ho mai visto da queste parti prima. Lascia che ti dia un consiglio. Io starei attento se fossi in te. L'Ordine non tollera il libero arbitrio, e la loro ""giustizia"" è repentina.","どうも余所者、この辺では見かけない顔だな。 +para comprar curitas?",Olisiko teillä ehkä varaa sidekääreisiin?,"Eh bien, peut être que vous pouvez vous acheter quelques pansements?","Nos, talán telik pár ragtapaszra is?","Niente da fare, ma forse puoi permetterti delle bende?",ところで、医薬パッチを買う余裕はありますか?,글쎄요... 의료 붕대는 어떻습니까?,"Nou ja, misschien kunt je zich wat med-patches veroorloven?",Kanskje du har råd til noen medisinplaster?,"Cóż, może stać cię na jakieś bandaże?","Bem, talvez você possa comprar algumas compressas?",,"Păi, poate îți permiți niște truse de prim-ajutor?","Тогда, может быть, купишь несколько бинтов?",,Du kanske har råd med några medicinska plåster?,Belki birkaç ilaç yamasını karşılayabilirsin? +"Hello stranger, I haven't seen you around here before. Let me give you a piece of free advice. I'd be careful if I were you. The Order does not tolerate free will, and their justice is swift.",TXT_DLG_SCRIPT02_D25772_HELLO,MAP02: Barkeep.,,,"Vítejte, cizinče, vás jsem tu ještě neviděl. Dám vám drobnou radu na začátek grátis: Být vámi, byl bych opatrný. Řád netoleruje svobodnou vůli a jejich spravedlnost je hbitá. ","Hej fremmede, jeg har ikke set dig her før. Lad mig give dig et gratis råd. Jeg ville være forsigtig, hvis jeg var dig. Ordenen tolererer ikke fri vilje, og deres retfærdighed er hurtig.","Hallo, Fremder. Ich habe dich hier vorher noch nie gesehen. Lass mich dir einen kostenlosen Rat geben. An deiner Stelle wäre ich vorsichtig. Der Orden duldet keinen freien Willen und sie greifen hart durch.",,"Saluton, fremdulo, mi ne vidis vin ĉi tie antaŭe. Jen senpaga konsilo: mi estus atenta se mi estus vi; La Ordeno ne toleras liberan volon kaj havas rapidan «juston».","Hola, extranjero, no te he visto por aquí antes. Te daré un consejo gratis: tendría cuidado si fuera tú; La Orden no tolera el libre albedrío y su justicia es veloz.","Hola, extranjero, es la primera vez que te veo por aquí. Te voy a dar un consejo gratis: tendría cuidado si fuera tú; La Orden no tolera el libre albedrío y su justicia es veloz.","Päivää. En olekaan nähnyt teitä täällä ennen. Teinä neuvoisin olemaan varuillanne. Veljeskunta ei suvaitse vapaata tahtoa, ja heidän tuomionsa ovat pikaiset.","Bien le bonjour, étranger. On ne vous a pas encore vu dans ce coin. Laissez-moi vous donner un petit conseil. Je ferais attention si j'étais vous. L'Ordre ne tolère pas le libre arbitre et leur justice est fulgurante.","Üdvözöllek idegen, nem láttalak még itt a környéken. Hadd adjak egy ingyen tanácsot. Én óvatos lennék a helyedben. A Rend nem tolerálja a szabad akaratot, és elég fürge az igazságszolgáltatás.","Salve straniero, non ti ho mai visto da queste parti prima. Lascia che ti dia un consiglio. Io starei attento se fossi in te. L'Ordine non tollera il libero arbitrio, e la loro ""giustizia"" è repentina.","どうも余所者、この辺では見かけない顔だな。 では一杯アドバイスをおごろう。この付近が 自由な発言を許さないからって下手な真似は するなよ。オーダーという自警団がすぐに -駆けつけてくるぞ。","안녕하신가 이방인이여, 자네는 이곳에서 처음 보는 얼굴이군. 내가 자네에게 공짜 조언을 해주지. 내가 자네라면 조심할 거야. 오더는 자유의지를 용납하지 않아. 그리고 그들의 정의는 신속하지.","Hallo vreemdeling, ik heb je hier nog niet eerder gezien. Laat me je een stukje gratis advies geven. Ik zou voorzichtig zijn als ik jou was. De Orde tolereert geen vrije wil en hun gerechtigheid is snel.","Hei, fremmede, jeg har ikke sett deg her før. La meg gi deg et gratis råd. Jeg ville vært forsiktig hvis jeg var deg. Ordenen tolererer ikke fri vilje, og deres rettferdighet er rask.","Witaj nieznajomy, nigdy cie tu wcześniej nie widziałem. Dam ci darmową radę. Na twoim miejscu bym uważał. Zakon nie toleruje wolnej woli, a ich prawo działa prędko.","Olá, forasteiro. Nunca vi você por aqui antes. Deixa eu te dar um conselho de graça. Eu tomaria cuidado se eu fosse você. A Ordem não tolera livre arbítrio e a justiça deles é rápida.",,"Salutări străine, nu te-am mai văzut pe-aici. Permite-mi să-ți dau un sfat. Aș fi grijuliu în locul tău. Ordinul nu tolerează voința liberă, iar justiția lor e rapidă.","Привет, незнакомец. Что-то я не видел тебя тут раньше. Позволь дать тебе бесплатный совет: я на твоём месте был бы поосторожнее. Орден не терпит неповиновения, и они скоры на суд.",,"Merhaba yabancı, seni daha önce buralarda görmemiştim. Sana bedava bir tavsiye vereyim. Yerinde olsam dikkatli olurdum. Tarikat'ın özgür iradeye tahammülü yoktur ve adaletleri çok hızlıdır." -What's the word?,TXT_RPLY0_SCRIPT02_D25772_WHATS,〃,,,Nějaké zvěsti?,Hvad er ordet?,Was erzählt man sich so?,,Kion oni diras ĉi tie?,¿Qué se dice por aquí?,,Mikä on päivän sana?,C'est quoi la rumeur?,Mi a hír?,Che si dice in giro?,他には?,무슨 뜻이죠?,Wat is het woord?,Hva heter det?,Jakieś wieści?,Quais são as últimas?,,Ai vreo veste?,Есть новости?,,Neydi o kelime? -The word is... The sewers hold more than just rats and robots.,TXT_RYES0_SCRIPT02_D25772_THEWO,〃,,,Kolují zvěsti... že stoky ukrývají víc než jen krysy a roboty.,Ordet er... Kloakkerne rummer mere end bare rotter og robotter.,"Man erzählt sich, dass die Kanalisation mehr als Ratten und Roboter zu bieten hat.",,"Oni diras... ke en la kloakoj +駆けつけてくるぞ。","안녕하신가 이방인이여, 자네는 이곳에서 처음 보는 얼굴이군. 내가 자네에게 공짜 조언을 해주지. 내가 자네라면 조심할 거야. 오더는 자유의지를 용납하지 않아. 그리고 그들의 정의는 신속하지.","Hallo vreemdeling, ik heb je hier nog niet eerder gezien. Laat me je een stukje gratis advies geven. Ik zou voorzichtig zijn als ik jou was. De Orde tolereert geen vrije wil en hun gerechtigheid is snel.","Hei, fremmede, jeg har ikke sett deg her før. La meg gi deg et gratis råd. Jeg ville vært forsiktig hvis jeg var deg. Ordenen tolererer ikke fri vilje, og deres rettferdighet er rask.","Witaj nieznajomy, nigdy cie tu wcześniej nie widziałem. Dam ci darmową radę. Na twoim miejscu bym uważał. Zakon nie toleruje wolnej woli, a ich prawo działa prędko.","Olá, forasteiro. Nunca vi você por aqui antes. Deixa eu te dar um conselho de graça. Eu tomaria cuidado se eu fosse você. A Ordem não tolera livre arbítrio e a justiça deles é rápida.",,"Salutări străine, nu te-am mai văzut pe-aici. Permite-mi să-ți dau un sfat. Aș fi grijuliu în locul tău. Ordinul nu tolerează voința liberă, iar justiția lor e rapidă.","Привет, незнакомец. Что-то я не видел тебя тут раньше. Позволь дать тебе бесплатный совет: я на твоём месте был бы поосторожнее. Орден не терпит неповиновения, и они скоры на суд.",,"Hej främling, jag har inte sett dig här förut. Låt mig ge dig ett gratis råd. Jag skulle vara försiktig om jag var du. Orden tolererar inte fri vilja och deras rättvisa är snabb.","Merhaba yabancı, seni daha önce buralarda görmemiştim. Sana bedava bir tavsiye vereyim. Yerinde olsam dikkatli olurdum. Tarikat'ın özgür iradeye tahammülü yoktur ve adaletleri çok hızlıdır." +What's the word?,TXT_RPLY0_SCRIPT02_D25772_WHATS,〃,,,Nějaké zvěsti?,Hvad er ordet?,Was erzählt man sich so?,,Kion oni diras ĉi tie?,¿Qué se dice por aquí?,,Mikä on päivän sana?,C'est quoi la rumeur?,Mi a hír?,Che si dice in giro?,他には?,무슨 뜻이죠?,Wat is het woord?,Hva heter det?,Jakieś wieści?,Quais são as últimas?,,Ai vreo veste?,Есть новости?,,Vad heter det?,Neydi o kelime? +The word is... The sewers hold more than just rats and robots.,TXT_RYES0_SCRIPT02_D25772_THEWO,〃,,,Kolují zvěsti... že stoky ukrývají víc než jen krysy a roboty.,Ordet er... Kloakkerne rummer mere end bare rotter og robotter.,"Man erzählt sich, dass die Kanalisation mehr als Ratten und Roboter zu bieten hat.",,"Oni diras... ke en la kloako ne estas nur ratoj kaj robotoj.","Se dice... que en las alcantarillas -hay más que solo ratas y robots.",,Sana on... että viemärit pitävät sisällään muutakin kuin vain rottia ja robotteja.,La rumeur est.. Que les égouts cachent quelque chose de plus gros que des rats et des robots.,Az a hír...hogy a kanális nem csak patkányokat és robotokat rejteget.,In giro si dice che... Le fogne contengono molto di più che ratti e robot.,他は...下水道には鼠やロボが沢山だ。,"무슨 말이냐 하면, 하수도 안에는 시궁쥐만 있는 게 아니라 로봇들도 숨어 있다는 거지.",Het woord is.... De riolen bevatten meer dan alleen ratten en robots.,Ordet er... Kloakken rommer mer enn bare rotter og roboter.,"Wieści są takie, że... kanały skrywają coś więcej niż tylko szczury i roboty.",As últimas são... Que os esgotos abrigam mais do que apenas ratos e robôs.,,Vestea e că... Canalele ascund mai mult decât roboți și șoareci.,"Говорят, в канализации водятся не только крысы и роботы.",,Kelime şu. Lağımlarda fareler ve robotlardan daha fazlası var. -What can I do for you now?,TXT_DLG_SCRIPT02_D27288_WHATC,〃,,,Co pro vás můžu udělat teď?,Hvad kan jeg gøre for dig nu?,Was kann ich jetzt für dich tun?,,Kion mi faru por vi?,¿Qué puedo hacer por ti?,,"No niin, miten voin olla teille avuksi?",Que puis-je faire pour vous?,Mit tehetek ma Önért?,E ora cosa posso fare per te?,何か用か?,이제 자네에게 무엇을 해드릴까?,Wat kan ik nu voor je doen?,Hva kan jeg gjøre for deg nå?,Co mogę dla ciebie zrobić?,O que posso fazer por você agora?,,Cu ce te mai pot ajuta?,Тебе что-нибудь нужно?,,Şimdi senin için ne yapabilirim? -More info.,TXT_RPLY0_SCRIPT02_D27288_MOREI,〃,,,Další informace,Mere info.,Mehr Informationen.,,Pliaj informoj,Más información,,Muuta tietoa.,Plus d'infos.,Több információt.,Altre informazioni.,話のネタ。,더 많은 정보를 주세요.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multe informații.,Расскажи больше,,Daha fazla bilgi. -The Governor is a simple reminder to us that we aren't free people anymore.,TXT_RYES0_SCRIPT02_D27288_THEGO,〃,,,"Náš guvernér je hezkou přípomínkou toho, že už nejsme svobodní.","Guvernøren er en simpel påmindelse til os om, at vi ikke længere er frie mennesker.","Der Gouverneur ist eine einfache Erinnerung daran, das wir keine freien Menschen mehr sind.",,"La registo estas simpla memorigaĵo -pri tio, ke ne plu estas libero.","El gobernador es un -simple recordatorio de -que ya no somos libres.",,"Kuvernööri toimii meille pienenä muistutuksena, ettemme ole enää vapaita ihmisiä.",Le gouverneur n'est qu'un exemple parmi d'autres pour nous montrer que ne nous somme plus un peuple libre.,"A Kormányzó egy egyszerű emlékeztető számunkra, hogy többé nem vagyunk szabad emberek.",Il governatore serve solo a farci ricordare che non siamo più delle persone libere.,知事は俺達に自由はないと思い出させる象徴さ。,모렐 총독은 우리들이 자유롭게 남들을 도울 수 없는 이유 중 하나이기도 하다네.,De gouverneur herinnert ons er eenvoudigweg aan dat we geen vrije mensen meer zijn.,Guvernøren er en enkel påminnelse om at vi ikke er frie mennesker lenger.,"Gubernator jest dla nas przypomnieniem, że już nie jesteśmy wolnymi ludźmi.",O Governador é um simples lembrete para nós de que não somos mais um povo livre.,,Guvernatorul e un simplu memento că nu mai suntem oameni liberi.,"Губернатор — живое напоминание, что мы больше не свободные люди.",,Vali bize artık özgür insanlar olmadığımızı hatırlatıyor. -Come back when you get some gold.,TXT_RNO0_SCRIPT02_D27288_COMEB,〃,,,"Vrať se, až budeš mít trochu zlata.","Kom tilbage, når du får noget guld.","Komm zurück, wenn du etwas Gold hast.",,Revenu kiam vi havos sufiĉe da oro.,Vuelve cuando tengas suficiente oro.,,"Palatkaa takaisin, kun teillä on kultaa.",Revenez quand vous avez de l'argent.,"Majd akkor térj vissza, ha szeretél egy kis aranyat.",Ritorna quando avrai più oro.,銭を一杯分持って戻ってきな。,골드가 더 있다면 더 알려주지.,Kom terug als je wat goud krijgt.,Kom tilbake når du har gull.,Wróć kiedy będziesz miał więcej monet.,Volte quando tiver ouro.,,Revin-o când ai niște aur.,"Возвращайся, когда у тебя будет золото.",,Biraz altın bulduğunda geri gel. +hay más que solo ratas y robots.",,Sana on... että viemärit pitävät sisällään muutakin kuin vain rottia ja robotteja.,La rumeur est.. Que les égouts cachent quelque chose de plus gros que des rats et des robots.,Az a hír...hogy a kanális nem csak patkányokat és robotokat rejteget.,In giro si dice che... Le fogne contengono molto di più che ratti e robot.,他は...下水道には鼠やロボが沢山だ。,"무슨 말이냐 하면, 하수도 안에는 시궁쥐만 있는 게 아니라 로봇들도 숨어 있다는 거지.",Het woord is.... De riolen bevatten meer dan alleen ratten en robots.,Ordet er... Kloakken rommer mer enn bare rotter og roboter.,"Wieści są takie, że... kanały skrywają coś więcej niż tylko szczury i roboty.",As últimas são... Que os esgotos abrigam mais do que apenas ratos e robôs.,,Vestea e că... Canalele ascund mai mult decât roboți și șoareci.,"Говорят, в канализации водятся не только крысы и роботы.",,Ordet är... Kloakerna innehåller mer än bara råttor och robotar.,Kelime şu. Lağımlarda fareler ve robotlardan daha fazlası var. +What can I do for you now?,TXT_DLG_SCRIPT02_D27288_WHATC,〃,,,Co pro vás můžu udělat teď?,Hvad kan jeg gøre for dig nu?,Was kann ich jetzt für dich tun?,,Kion mi faru por vi?,¿Qué puedo hacer por ti?,,"No niin, miten voin olla teille avuksi?",Que puis-je faire pour vous?,Mit tehetek ma Önért?,E ora cosa posso fare per te?,何か用か?,이제 자네에게 무엇을 해드릴까?,Wat kan ik nu voor je doen?,Hva kan jeg gjøre for deg nå?,Co mogę dla ciebie zrobić?,O que posso fazer por você agora?,,Cu ce te mai pot ajuta?,Тебе что-нибудь нужно?,,Vad kan jag göra för dig nu?,Şimdi senin için ne yapabilirim? +More info.,TXT_RPLY0_SCRIPT02_D27288_MOREI,〃,,,Další informace,Mere info.,Mehr Informationen.,,Pliaj informoj,Más información,,Muuta tietoa.,Plus d'infos.,Több információt.,Altre informazioni.,話のネタ。,더 많은 정보를 주세요.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multe informații.,Расскажи больше,,Mer information.,Daha fazla bilgi. +The Governor is a simple reminder to us that we aren't free people anymore.,TXT_RYES0_SCRIPT02_D27288_THEGO,〃,,,"Náš guvernér je hezkou přípomínkou toho, že už nejsme svobodní.","Guvernøren er en simpel påmindelse til os om, at vi ikke længere er frie mennesker.","Der Gouverneur ist eine einfache Erinnerung daran, das wir keine freien Menschen mehr sind.",,"La registo ekzistas +nur por memorigi, ke +ne plu estas libereco.","El gobernador solo es +un recordatorio de +que ya no somos libres.",,"Kuvernööri toimii meille pienenä muistutuksena, ettemme ole enää vapaita ihmisiä.",Le gouverneur n'est qu'un exemple parmi d'autres pour nous montrer que ne nous somme plus un peuple libre.,"A Kormányzó egy egyszerű emlékeztető számunkra, hogy többé nem vagyunk szabad emberek.",Il governatore serve solo a farci ricordare che non siamo più delle persone libere.,知事は俺達に自由はないと思い出させる象徴さ。,모렐 총독은 우리들이 자유롭게 남들을 도울 수 없는 이유 중 하나이기도 하다네.,De gouverneur herinnert ons er eenvoudigweg aan dat we geen vrije mensen meer zijn.,Guvernøren er en enkel påminnelse om at vi ikke er frie mennesker lenger.,"Gubernator jest dla nas przypomnieniem, że już nie jesteśmy wolnymi ludźmi.",O Governador é um simples lembrete para nós de que não somos mais um povo livre.,,Guvernatorul e un simplu memento că nu mai suntem oameni liberi.,"Губернатор — живое напоминание, что мы больше не свободные люди.",,Guvernören är en enkel påminnelse om att vi inte längre är fria människor.,Vali bize artık özgür insanlar olmadığımızı hatırlatıyor. +Come back when you get some gold.,TXT_RNO0_SCRIPT02_D27288_COMEB,〃,,,"Vrať se, až budeš mít trochu zlata.","Kom tilbage, når du får noget guld.","Komm zurück, wenn du etwas Gold hast.",,"Revenu kiam vi havos +sufiĉe da oro.","Vuelve cuando +tengas suficiente oro.",,"Palatkaa takaisin, kun teillä on kultaa.",Revenez quand vous avez de l'argent.,"Majd akkor térj vissza, ha szeretél egy kis aranyat.",Ritorna quando avrai più oro.,銭を一杯分持って戻ってきな。,골드가 더 있다면 더 알려주지.,Kom terug als je wat goud krijgt.,Kom tilbake når du har gull.,Wróć kiedy będziesz miał więcej monet.,Volte quando tiver ouro.,,Revin-o când ai niște aur.,"Возвращайся, когда у тебя будет золото.",,Kom tillbaka när du får lite guld.,Biraz altın bulduğunda geri gel. "Well, you're asking a lot of questions for someone who's not trying to die. Make sure you don't go and get yourself killed, or worse.",TXT_DLG_SCRIPT02_D28804_WELLY,〃,,,"Na někoho, kdo se nesnaží zemřít, se hodně ptáš. Dej si pozor a nenech se zabít, nebo něco horšího.","Du stiller mange spørgsmål af en, der ikke prøver at dø. Sørg for, at du ikke går hen og bliver dræbt, eller det der er værre.","Hmm, du stellst aber ziemlich viele Fragen für jemand der nicht versucht zu sterben. Lass dich nicht umbringen, oder schlimmeres.",,"Nu, vi faras multe da demandoj por esti iu, kiu ne intencas morti. Certiĝu, ke vi ne kaŭzos al vi mortigon... aŭ ion pli malbonan.","Bueno, estás haciendo muchas preguntas para ser alguien que no está tratando de morir. Asegúrate de que no vayas a hacer que te maten... o algo peor.",,"Kylläpäs te kysytte paljon ollaksenne joku, joka ei yritä tappaa itsensä. Pitäkää vain huoli, ettei niin edelleenkään käy, tai pahemmin.","Vous posez beaucoup de questions pour quelqu'un qui n'essaie pas de se faire tuer. Essayez donc de ne pas vous faire descendre, ou pire.","Figyelj, elég sok kérdést teszel fel, ahhoz képest, hogy elvileg nem akarsz meghalni. Igyekezz nem kinyiratni magad a továbbiakban, vagy rosszabb.","Lo sai, fai davvero tante domande per uno che cerca di sopravvivere. Fai attenzione a non farti uccidere, o peggio...","所で、アンタは死に行かない人達に 聞き回ってる様だが。悪いことは言わねえ、 -あんまし死に急ぐんじゃねえぞ。",죽지 않으려고 발버둥 치듯이 질문을 많이 하는구먼. 무장한 곳에 무모하게 가서 죽지나 말게.,"Nou, je stelt veel vragen voor iemand die niet probeert te sterven. Zorg ervoor dat je niet gaat en jezelf niet dood laat gaan, of erger nog.",Du stiller mange spørsmål til å være en som ikke prøver å dø. Pass på at du ikke blir drept eller det som verre er.,"Cóż, zadajesz dużo pytań jak na kogoś, kto próbuje nie zginąć. Upewnij się, że nie dasz się zabić jak pójdziesz. Lub gorzej.","Bom, você está fazendo um monte de perguntas pra alguém que não está tentando morrer. Procure não acabar sendo morto por aí, ou coisa pior.",,"Păi, pui multe întrebări pentru cineva care încearcă să nu moară. Ai grijă să nu ajungi un om mort, sau mai rău.","Ты задаёшь слишком много вопросов для того, кто не хочет сдохнуть. Убедись, что не идёшь на верную смерть или чего похуже.",,Ölmeye çalışmayan biri için çok fazla soru soruyorsun. Gidip kendini öldürtmediğinden ya da daha kötüsünü yapmadığından emin ol. -More info.,TXT_RPLY0_SCRIPT02_D28804_MOREI,〃,,,Další informace,Mere info.,Mehr Informationen.,,Pliaj informoj,Más información,,Muuta tietoa.,Plus d'infos.,Több infót.,Altre informazioni.,話のネタ。,정보를 좀 더 알려주시오.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multe informații.,Говори дальше.,,Daha fazla bilgi. -There's more to the Order than meets the eye.,TXT_RYES0_SCRIPT02_D28804_THERE,〃,,,"Za Řádem se toho skrývá víc, než se zdá.","Der er mere i Ordenen, end man umiddelbart tror.",An dem Orden ist mehr dran als man auf den ersten Blick denkt.,,"Estas pli pri La Ordono, +あんまし死に急ぐんじゃねえぞ。",죽지 않으려고 발버둥 치듯이 질문을 많이 하는구먼. 무장한 곳에 무모하게 가서 죽지나 말게.,"Nou, je stelt veel vragen voor iemand die niet probeert te sterven. Zorg ervoor dat je niet gaat en jezelf niet dood laat gaan, of erger nog.",Du stiller mange spørsmål til å være en som ikke prøver å dø. Pass på at du ikke blir drept eller det som verre er.,"Cóż, zadajesz dużo pytań jak na kogoś, kto próbuje nie zginąć. Upewnij się, że nie dasz się zabić jak pójdziesz. Lub gorzej.","Bom, você está fazendo um monte de perguntas pra alguém que não está tentando morrer. Procure não acabar sendo morto por aí, ou coisa pior.",,"Păi, pui multe întrebări pentru cineva care încearcă să nu moară. Ai grijă să nu ajungi un om mort, sau mai rău.","Ты задаёшь слишком много вопросов для того, кто не хочет сдохнуть. Убедись, что не идёшь на верную смерть или чего похуже.",,"Du ställer många frågor för någon som inte försöker dö. Se till att du inte går och blir dödad, eller värre.",Ölmeye çalışmayan biri için çok fazla soru soruyorsun. Gidip kendini öldürtmediğinden ya da daha kötüsünü yapmadığından emin ol. +More info.,TXT_RPLY0_SCRIPT02_D28804_MOREI,〃,,,Další informace,Mere info.,Mehr Informationen.,,Pliaj informoj,Más información,,Muuta tietoa.,Plus d'infos.,Több infót.,Altre informazioni.,話のネタ。,정보를 좀 더 알려주시오.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multe informații.,Говори дальше.,,Mer information.,Daha fazla bilgi. +There's more to the Order than meets the eye.,TXT_RYES0_SCRIPT02_D28804_THERE,〃,,,"Za Řádem se toho skrývá víc, než se zdá.","Der er mere i Ordenen, end man umiddelbart tror.",An dem Orden ist mehr dran als man auf den ersten Blick denkt.,,"Estas pli pri La Ordeno, ol kiom ili ŝajnigas.","Hay más de La Orden -de lo que aparenta.",,"Veljeskunta ei ole sitä, miltä päältä päin näyttää.",L'Ordre cache bien son jeu.,"Több van a Rend mögött, mint ami a külső sejtet.",C'è sotto molto di più sull'Ordine rispetto a come possa sembrare.,オーダーは見えてる以上に強大だ。,오더의 뒤에는 더 많은 것들이 숨겨져 있다네. 비밀 같은 것들 말일세.,De Orde heeft meer te bieden dan je op het eerste gezicht zou denken.,Det er mer ved Ordenen enn det som møter øyet.,"Zakonu jest więcej, niż się wydaje.",Há mais sobre a Ordem do que aparenta.,,Este ceva mai mult la Ordin decât ceea ce se poate vedea cu ochiul liber.,"Орден больше, чем кажется.",,Tarikat'ta göründüğünden daha fazlası var. +de lo que aparenta.",,"Veljeskunta ei ole sitä, miltä päältä päin näyttää.",L'Ordre cache bien son jeu.,"Több van a Rend mögött, mint ami a külső sejtet.",C'è sotto molto di più sull'Ordine rispetto a come possa sembrare.,オーダーは見えてる以上に強大だ。,오더의 뒤에는 더 많은 것들이 숨겨져 있다네. 비밀 같은 것들 말일세.,De Orde heeft meer te bieden dan je op het eerste gezicht zou denken.,Det er mer ved Ordenen enn det som møter øyet.,"Zakonu jest więcej, niż się wydaje.",Há mais sobre a Ordem do que aparenta.,,Este ceva mai mult la Ordin decât ceea ce se poate vedea cu ochiul liber.,"Орден больше, чем кажется.",,Det finns mer i Orden än vad man kan tro.,Tarikat'ta göründüğünden daha fazlası var. We'll talk when you get gold!,TXT_RNO0_SCRIPT02_D28804_WELLT,〃,,,"Popovídáme si, když budeš mít zlato!","Vi taler sammen, når du får guld!","Wir werden reden, wenn du Gold hast!",,"Ni parolos kiam -vi alportos oron!",¡Hablamos cuando traigas oro!,,"Puhutaan, kun sinulla on kultaa.",On parlera quand tu auras des sous!,"Majd beszélünk, ha lesz aranyad.",Ne parleremo quando avrai più soldi!,銭を持ってたら話すさ!,골드를 더 가져오면 의논을 시작해보지.,We praten wel als je goud krijgt!,Vi snakkes når du får gull!,Pomówimy jeśli masz złoto.,Conversaremos quando você tiver ouro!,,Vorbim când aduci aur!,"Поговорим, когда принесёшь золото!",,Altın aldığında konuşuruz! -"That's it friend, the well of knowledge has run dry. I've told you more than I should have anyway. Good luck... And don't come back.",TXT_DLG_SCRIPT02_D30320_THATS,〃,,,"A to je vše, příteli, studnice mé moudrosti vyschla. Stejně jsem ti řekl víc, než jsem měl. Hodně štěstí... a už se nevracej.","Det var det, ven, vidensbrønden er tørlagt. Jeg har alligevel fortalt dig mere, end jeg burde have gjort. Held og lykke... Og kom ikke tilbage.","Das war's mein Freund, der Brunnen der Weisheit ist versiegt. Ich habe dir sowieso mehr erzählt als ich sollte. Viel Glück... und komm nicht zurück.",,"Jen ĉio, amiko; la fonto de scio sekiĝis. Malgraŭ tio, mi diris al vi pli ol tiom, kiom mi devus. Ŝancon... kaj ne revenu.","Ya está, amigo; el pozo del conocimiento ya se ha secado. De todas formas ya te he dicho más de lo que debería. Suerte... y no vuelvas.","Ya está, amigo; el pozo del conocimiento ya se secó. De todas formas ya te dije más de lo que debería. Suerte... y no vuelvas.","Siinä kaikki, ystävä; tiedon lähde on ehtynyt. Olen kertonut sinulle enemmän kuin olisin edes saanutkaan. Onnea matkaan... äläkä tule takaisin.","Eh bien voilà, mon ami, le puits de la connaîssance s'est enfin asséché.. Je t'en ai dit plus que je n'aurai du, de toutes manières! Bonne chance.. Et ne reviens pas!","Ez az, barátom. A tudás kútja kiszáradt. Többször mondtam neked kelleténél amúgyis. Sok szerencsét... És ne gyere vissza.","È tutto, amico, ho esaurito le cose che avevo da dirti. Ti ho già detto più di quanto avrei dovuto. Buona fortuna... e non tornare più.","これはこれは親友、心得の瓶は切らしてるぞ。 +vi alportos oron!",¡Hablamos cuando traigas oro!,,"Puhutaan, kun sinulla on kultaa.",On parlera quand tu auras des sous!,"Majd beszélünk, ha lesz aranyad.",Ne parleremo quando avrai più soldi!,銭を持ってたら話すさ!,골드를 더 가져오면 의논을 시작해보지.,We praten wel als je goud krijgt!,Vi snakkes når du får gull!,Pomówimy jeśli masz złoto.,Conversaremos quando você tiver ouro!,,Vorbim când aduci aur!,"Поговорим, когда принесёшь золото!",,Vi pratar när du får guld!,Altın aldığında konuşuruz! +"That's it friend, the well of knowledge has run dry. I've told you more than I should have anyway. Good luck... And don't come back.",TXT_DLG_SCRIPT02_D30320_THATS,〃,,,"A to je vše, příteli, studnice mé moudrosti vyschla. Stejně jsem ti řekl víc, než jsem měl. Hodně štěstí... a už se nevracej.","Det var det, ven, vidensbrønden er tørlagt. Jeg har alligevel fortalt dig mere, end jeg burde have gjort. Held og lykke... Og kom ikke tilbage.","Das war's mein Freund, der Brunnen der Weisheit ist versiegt. Ich habe dir sowieso mehr erzählt als ich sollte. Viel Glück... und komm nicht zurück.",,"Jen ĉio, amiko, la fonto de scio sekiĝis. Malgraŭ tio, mi diris al vi pli ol tiom, kiom mi devus. Ŝancon... kaj ne revenu.","Ya está, amigo, el pozo del conocimiento ya se ha secado. De todas formas ya te he dicho más de lo que debería. Suerte... y no vuelvas.","Ya está, amigo, el pozo del conocimiento ya se secó. De todas formas ya te dije más de lo que debería. Suerte... y no vuelvas.","Siinä kaikki, ystävä; tiedon lähde on ehtynyt. Olen kertonut sinulle enemmän kuin olisin edes saanutkaan. Onnea matkaan... äläkä tule takaisin.","Eh bien voilà, mon ami, le puits de la connaîssance s'est enfin asséché.. Je t'en ai dit plus que je n'aurai du, de toutes manières! Bonne chance.. Et ne reviens pas!","Ez az, barátom. A tudás kútja kiszáradt. Többször mondtam neked kelleténél amúgyis. Sok szerencsét... És ne gyere vissza.","È tutto, amico, ho esaurito le cose che avevo da dirti. Ti ho già detto più di quanto avrei dovuto. Buona fortuna... e non tornare più.","これはこれは親友、心得の瓶は切らしてるぞ。 とにかく俺が知ってる話はこれで全部だ。 -頑張りな...それともう来なくていいぞ。","친구여... 안타깝게도 지식의 우물은 이제 고갈됐다네. 내가 알려줄 수 있는 걸 다 알려줬거든. 건투를 빌겠네, 그리고 다시 돌아오지는 말고.","Dat is het vriend, de bron van kennis is uitgeput. Ik heb je meer verteld dan ik zou moeten hebben. Veel succes.... En kom niet terug.","Det var det, min venn. Kunnskapens brønn har tørket ut. Jeg har fortalt deg mer enn jeg burde uansett. Lykke til... Og ikke kom tilbake.","To wszystko kolego, studnia wiedzy wyschła. Powiedziałem ci więcej niż powinienem. Powodzenia... I nie wracaj.","Isso é tudo, camarada. O poço de conhecimento está seco. Já te contei tudo o que eu deveria, de qualquer forma. Boa sorte... E não volte mais aqui.",,"Asta a fost prietene, fântâna cunoștiințelor a secat. Ți-am spus mai multe decât ar fi trebuit oricum. Baftă... Și nu te întoarce.","Это всё, дружище. Кладезь мудрости исчерпана. Я и так рассказал тебе больше, чем следовало. Удачи... и не возвращайся.",,"Bu kadar dostum, bilgi kuyusu kurudu. Zaten sana söylemem gerekenden fazlasını söyledim. İyi şanslar. Ve sakın geri gelme." -"Hey, I'm only here in case of an emergency. If the core breaches, then I make sure no one gets in... or out.",TXT_DLG_SCRIPT02_D31836_HEYIM,MAP02: Power Station guard.,,,"Hej, já jsem tu jen pro případ nouze. Jestli se něco stane s jádrem, jsem tu, abych zajistil, že se nikdo nedostane dovnitř... ani ven.","Hey, jeg er her kun i nødstilfælde. Hvis kernen bryder sammen, så sørger jeg for, at ingen kommer ind... eller ud.","Hey, ich bin nur für den Fall eines Notfalls hier. Im Falle eines Kernbruchs sorge ich dafür das niemand rein kommt... oder raus.",,"Mi estas nur krizokaza gardisto: se la kerno rompiĝus, mi certiĝus, ke neniu eniru... aŭ eliru.","Solo estoy aquí en caso de emergencia: si el núcleo se rompe, me aseguro de que nadie entre... o salga.",,"Hei, olen täällä vain hätätilanteen varalta. Jos ytimeen tulee murtuma, tehtäväni on varmistaa, ettei kukaan pääse sisään... tai ulos.","Hé, je ne suis là qu'en cas d'urgence. Si le coeur a une brèche, il faut que je fasse en sorte que rien ne rentre.. Ou ne sorte.","Hé, én csak vészhelyzet esetére vagyok itt. Ha a mag kitör, akkor elintézem, hogy senki ne jöjjön be... vagy ki.","Ehi, io sono qua solo in caso di emergenza. Se c'è una falla nel nucleo, allora mi assicuro che nessuno possa entrare... o uscire.","おう、俺は緊急時の為にここにいる。 +頑張りな...それともう来なくていいぞ。","친구여... 안타깝게도 지식의 우물은 이제 고갈됐다네. 내가 알려줄 수 있는 걸 다 알려줬거든. 건투를 빌겠네, 그리고 다시 돌아오지는 말고.","Dat is het vriend, de bron van kennis is uitgeput. Ik heb je meer verteld dan ik zou moeten hebben. Veel succes.... En kom niet terug.","Det var det, min venn. Kunnskapens brønn har tørket ut. Jeg har fortalt deg mer enn jeg burde uansett. Lykke til... Og ikke kom tilbake.","To wszystko kolego, studnia wiedzy wyschła. Powiedziałem ci więcej niż powinienem. Powodzenia... I nie wracaj.","Isso é tudo, camarada. O poço de conhecimento está seco. Já te contei tudo o que eu deveria, de qualquer forma. Boa sorte... E não volte mais aqui.",,"Asta a fost prietene, fântâna cunoștiințelor a secat. Ți-am spus mai multe decât ar fi trebuit oricum. Baftă... Și nu te întoarce.","Это всё, дружище. Кладезь мудрости исчерпана. Я и так рассказал тебе больше, чем следовало. Удачи... и не возвращайся.",,"Det var det vän, kunskapsbrunnen har tagit slut. Jag har berättat mer än jag borde ha gjort i alla fall. Lycka till... Och kom inte tillbaka.","Bu kadar dostum, bilgi kuyusu kurudu. Zaten sana söylemem gerekenden fazlasını söyledim. İyi şanslar. Ve sakın geri gelme." +"Hey, I'm only here in case of an emergency. If the core breaches, then I make sure no one gets in... or out.",TXT_DLG_SCRIPT02_D31836_HEYIM,MAP02: Power Station guard.,,,"Hej, já jsem tu jen pro případ nouze. Jestli se něco stane s jádrem, jsem tu, abych zajistil, že se nikdo nedostane dovnitř... ani ven.","Hey, jeg er her kun i nødstilfælde. Hvis kernen bryder sammen, så sørger jeg for, at ingen kommer ind... eller ud.","Hey, ich bin nur für den Fall eines Notfalls hier. Im Falle eines Kernbruchs sorge ich dafür das niemand rein kommt... oder raus.",,"Mi nur estas krizokaza gardisto: se la kerno rompiĝus, mi certiĝus, ke neniu eniru... aŭ eliru.","Solo estoy aquí en caso de emergencia: si el núcleo se rompe, me aseguro de que nadie entre... o salga.",,"Hei, olen täällä vain hätätilanteen varalta. Jos ytimeen tulee murtuma, tehtäväni on varmistaa, ettei kukaan pääse sisään... tai ulos.","Hé, je ne suis là qu'en cas d'urgence. Si le coeur a une brèche, il faut que je fasse en sorte que rien ne rentre.. Ou ne sorte.","Hé, én csak vészhelyzet esetére vagyok itt. Ha a mag kitör, akkor elintézem, hogy senki ne jöjjön be... vagy ki.","Ehi, io sono qua solo in caso di emergenza. Se c'è una falla nel nucleo, allora mi assicuro che nessuno possa entrare... o uscire.","おう、俺は緊急時の為にここにいる。 コアが破壊されないか、誰が入っているかを -確認している...出ていくのもな。","이봐, 난 비상사태를 대비해서 여기에 있는 거라고. 만약 중심부가 파괴되면, 그 누구도 들어올 수 없게 막을 거야... 도망치는 사람도 포함해서.","Hé, ik ben hier alleen in geval van nood. Als de kern breekt, dan zorg ik ervoor dat er niemand binnenkomt... of buitenkomt.","Hei, jeg er bare her i nødstilfeller. Hvis kjernen brister, sørger jeg for at ingen kommer inn... eller ut.","Hej, jestem tu tylko w razie wypadku. Jeśli rdzeń zostanie naruszony, wtedy upewniam się, że nikt tam nie wejdzie... lub stamtąd nie wyjdzie.","Ei, só estou aqui em caso de uma emergência. Se o núcleo se romper, preciso garantir que ninguém entre... ou saia.",,"Hei, sunt aici doar în caz de urgență. Dacă apare o breșă în nucleu, mă asigur că nimeni nu intră... sau iese.","Слушай, меня сюда поставили на всякий случай. Если целостность ядра нарушится, я позабочусь, чтобы никто не вошёл... и не вышел.",,"Hey, ben sadece acil bir durumda buradayım. Çekirdek kırılırsa, kimsenin içeri girmediğinden emin olurum... ya da dışarı." +確認している...出ていくのもな。","이봐, 난 비상사태를 대비해서 여기에 있는 거라고. 만약 중심부가 파괴되면, 그 누구도 들어올 수 없게 막을 거야... 도망치는 사람도 포함해서.","Hé, ik ben hier alleen in geval van nood. Als de kern breekt, dan zorg ik ervoor dat er niemand binnenkomt... of buitenkomt.","Hei, jeg er bare her i nødstilfeller. Hvis kjernen brister, sørger jeg for at ingen kommer inn... eller ut.","Hej, jestem tu tylko w razie wypadku. Jeśli rdzeń zostanie naruszony, wtedy upewniam się, że nikt tam nie wejdzie... lub stamtąd nie wyjdzie.","Ei, só estou aqui em caso de uma emergência. Se o núcleo se romper, preciso garantir que ninguém entre... ou saia.",,"Hei, sunt aici doar în caz de urgență. Dacă apare o breșă în nucleu, mă asigur că nimeni nu intră... sau iese.","Слушай, меня сюда поставили на всякий случай. Если целостность ядра нарушится, я позабочусь, чтобы никто не вошёл... и не вышел.",,"Jag är bara här i nödfall. Om kärnan bryter igenom, ser jag till att ingen kommer in... eller ut.","Hey, ben sadece acil bir durumda buradayım. Çekirdek kırılırsa, kimsenin içeri girmediğinden emin olurum... ya da dışarı." "Watch your step, peasant!",TXT_DLG_SCRIPT02_D33352_WATCH,MAP02: Rust guards.,,,"Dávej si na sebe pozor, poddaný! -","Pas på hvor du træder, bonde!","Pass auf wo du hintrittst, Bauer!",,"Atentu tie, kie vi piediras, kampulo!","¡Cuida por donde caminas, campesino!","¡Cuidado por donde caminas, campesino!","Katso, mihin astut, maallikko!","Regarde où tu va, paysan!","Nézz a lábad elé, paraszt!",Guarda dove metti i piedi!,気を付けろ、田舎モン!,"똑바로 보고 다녀라, 시민!","Kijk uit waar je loopt, boer!","Se deg for, bonde!",Uważaj jak leziesz kmiocie!,"Cuida por onde anda, plebeu!",,"Ai grijă pe unde calci, plebeule!","Смотри, куда прёшь, холоп!",,"Adımına dikkat et, köylü!" -We're going to kill you! ,TXT_DLG_SCRIPT02_D34868_WEREG,MAP02: Gray guards.,,,Zabijeme tě!,Vi slår dig ihjel!,Wir werden dich umbringen!,,Ni mortigos vin!,"¡Vamos a matarte! -",¡Te vamos a matar!,Tapamme sinut!,On va te descendre!,Megdöglesz!,Adesso ti ammazziamo!,お前を粛正する!,우린 널 죽일거야!,We gaan je vermoorden!,Vi skal drepe deg!,Zabijemy cię!,Vamos matar você!,,O să te omorâm!,Готовься к смерти!,,Seni öldüreceğiz! +","Pas på hvor du træder, bonde!","Pass auf wo du hintrittst, Bauer!",,"Atentu tie, kie vi piediras, kampulo!","¡Cuida por donde caminas, campesino!","¡Cuidado por donde caminas, campesino!","Katso, mihin astut, maallikko!","Regarde où tu va, paysan!","Nézz a lábad elé, paraszt!",Guarda dove metti i piedi!,気を付けろ、田舎モン!,"똑바로 보고 다녀라, 시민!","Kijk uit waar je loopt, boer!","Se deg for, bonde!",Uważaj jak leziesz kmiocie!,"Cuida por onde anda, plebeu!",,"Ai grijă pe unde calci, plebeule!","Смотри, куда прёшь, холоп!",,"Se upp, bonde!","Adımına dikkat et, köylü!" +We're going to kill you! ,TXT_DLG_SCRIPT02_D34868_WEREG,MAP02: Gray guards.,,,Zabijeme tě!,Vi slår dig ihjel!,Wir werden dich umbringen!,,Ni mortigos vin!,¡Te vamos a matar!,,Tapamme sinut!,On va te descendre!,Megdöglesz!,Adesso ti ammazziamo!,お前を粛正する!,우린 널 죽일거야!,We gaan je vermoorden!,Vi skal drepe deg!,Zabijemy cię!,Vamos matar você!,,O să te omorâm!,Готовься к смерти!,,Vi kommer att döda dig!,Seni öldüreceğiz! Who in the blazes are you? No one's supposed to be loitering about in this area!,TXT_DLG_SCRIPT02_D36384_WHOIN,MAP02: Green guard.,,,Kdo k čertu jsi? Tady se nikdo nemá potloukat!,Hvem i helvede er du? Ingen skal slentre rundt i dette område!,Wer zum Teufel bist du? Hier soll doch eigentlich niemand rumschnüffeln!,,Kiu diable vi estas? Neniu supozeble devas vagi ĉi tie!,¿Quién diantres eres tú? ¡Se supone que nadie tiene que estar merodeando por esta área!,¿Quién demonios eres tú? ¡Se supone que nadie tiene que estar curioseando por esta zona!,Kuka ihme sinä olet? Kenelläkään ei ole lupaa kuljeksia tällä alueella!,Qu'est ce que c'est ça? Que faites vous ici? Personne n'est sensé se trouver dans cette zone!,Te meg ki az Isten nyila vagy? Senki sem csavaroghat ebben a körzetben.,E tu chi diavolo saresti? Nessuno dovrebbe aggirarsi in quest'area!,"誰だお前は?この区域を立ち入ることは 許されていないぞ! -",너는 누구지? 아무도 이 지역에서 어슬렁거릴 수 없다!,Wie ben jij in vredesnaam? Niemand wordt verondersteld op dit gebied rond te hangen!,Hvem i all verden er du? Ingen har lov til å drive rundt i dette området!,Kim u diaska jesteś? Nikt nie powinien się tu włóczyć!,Mas quem é você? Não pode ficar perambulando por aqui!,,Cine naiba mai ești tu? Nimeni nu ar trebui să zăbovească în zona asta!,"Кто ты, чёрт побери, такой? Никому не разрешено тут шляться!",,Sen de kimsin be? Kimsenin bu bölgede dolaşmaması gerekiyor! -"You there, nobody's allowed in here. Move along!",TXT_DLG_SCRIPT02_D37900_YOUTH,MAP02: Golden guards.,,,"Hej ty, sem nikdo nesmí. Jdi dál!","Du der, ingen må komme ind her. Af sted med jer!","Hey, du da. Hier darfst du nicht rein. Geh weiter!",,"He, neniu rajtas esti ĉi tie. Plue movu vin!","Oye, este lugar está restringido. ¡Sigue moviéndote!",,"Sinä siellä, tämä on kielletty alue. Tiehesi!","Vous, là, personne n'est autorisé à traîner ici, dégagez!","Te ott, ide senki sem jöhet be, kotródj!","Ehi, tu! A nessuno è permesso di stare qua. Vai via!",お前は許可していないぞ。立ち去れ!,"거기 너, 아무도 이곳에 지나갈 수 없다. 가던 길이나 가!","Jij daar, niemand mag hier naar binnen. Ga verder!","Du der, ingen har lov til å være her. Gå videre!","Ty tutaj, nikt nie ma prawa tu przebywać. Wynocha!","Ei, você, não pode ficar aqui. Vá embora!",,"Tu, nimeni nu are voie aici. Mișcă-te!","Эй, ты! Никому не позволено тут ошиваться. Проваливай!",,"Sen oradaki, kimsenin buraya girmesine izin yok. İlerleyin!" -Irale will set you right up!,TXT_DLG_SCRIPT02_D39416_IRALE,MAP02: Irale's shop.,,,Irale tě hned vyzbrojí!,Irale vil sætte dig på plads!,Irale wird sich darum kümmern!,,"Irale vendos al vi ĉion, kion vi bezonas!",¡Irale te venderá lo necesario!,¡Irale te va a vender lo necesario!,Irale järkkää sinulle varusteet!,Irale a ce qu'il te faut!,Irale majd ellát.,Irale ti darà quello che ti serve!,イラールが貴方を手助けします!,여기 이롤리가 중요한 물품을 판매할 거야.,Irale zal je er goed in luizen!,Irale skal ordne opp for deg!,Irale dobrze cię przygotuje!,O Irale vai te ajudar!,,Irale te va pregăti adecvat!,Ирэйл снабдит тебя всем необходимым!,,İrale seni hemen ayarlayacak! -I'm kinda a talent broker for the rebels. A guy who's as good as you could make a lot of gold... if you hooked up with the right people.,TXT_DLG_SCRIPT02_D40932_IMKIN,MAP02: Harris.,,,Jsem takový hledač talentů pro rebely. Někdo tak dobrý jako ty by si mohl vydělat hodně zlata... pokud by se spojil s těmi správnými lidmi.,"Jeg er en slags talentmægler for oprørerne. En fyr, der er lige så god som dig, kan tjene en masse guld ... hvis du kommer i kontakt med de rigtige folk.","Ich bin sowas wie ein Talentsucher für die Rebellen. Jemand, der so gut ist wie du kann hier eine Menge Gold verdienen... wenn du mit den richtigen Leuten in Verbindung stehst.",,"Mi estas speco de talentul-serĉanto por la ribelantoj. Iu tiel lerta, kiel vi povus gajni multe da oro… se vi ligas vin kun la ĝustaj homoj.",Soy algo así como un buscador de talento para los rebeldes. Alguien tan bueno como tú podría ganar mucho oro... Si te juntas con las personas adecuadas.,,Olen eräänlainen kykyjenvälittäjä kapinallisille. Kaltaisesi kaveri voisi tienata paljon kultaa... oikeiden kumppaneiden kanssa.,"Je suis une sorte de chasseur de têtes pour les rebelles. Un type comme toi pourrait se faire pas mal de fric... Avec les bons contacts, bien entendu.","Egyfajta toborzó vagyok a lázadóknál. Egy ürge aki ilyen jó mint te, elég sok aranyat kereshet...ha megfelelő emberekkel jösz össze.",Sono sempre alla ricerca di persone talentuose per i ribelli. Una persona come te potrebbe ricevere molto oro... se fosse in contatto con le persone giuste.,"俺は反乱者への斡旋屋さ。才能を生かして +",너는 누구지? 아무도 이 지역에서 어슬렁거릴 수 없다!,Wie ben jij in vredesnaam? Niemand wordt verondersteld op dit gebied rond te hangen!,Hvem i all verden er du? Ingen har lov til å drive rundt i dette området!,Kim u diaska jesteś? Nikt nie powinien się tu włóczyć!,Mas quem é você? Não pode ficar perambulando por aqui!,,Cine naiba mai ești tu? Nimeni nu ar trebui să zăbovească în zona asta!,"Кто ты, чёрт побери, такой? Никому не разрешено тут шляться!",,Vem i helvete är du? Det är inte meningen att någon ska gå omkring i det här området!,Sen de kimsin be? Kimsenin bu bölgede dolaşmaması gerekiyor! +"You there, nobody's allowed in here. Move along!",TXT_DLG_SCRIPT02_D37900_YOUTH,MAP02: Golden guards.,,,"Hej ty, sem nikdo nesmí. Jdi dál!","Du der, ingen må komme ind her. Af sted med jer!","Hey, du da. Hier darfst du nicht rein. Geh weiter!",,"He, neniu rajtas esti ĉi tie. Plue movu vin!","Oye, este lugar está restringido. ¡Sigue moviéndote!",,"Sinä siellä, tämä on kielletty alue. Tiehesi!","Vous, là, personne n'est autorisé à traîner ici, dégagez!","Te ott, ide senki sem jöhet be, kotródj!","Ehi, tu! A nessuno è permesso di stare qua. Vai via!",お前は許可していないぞ。立ち去れ!,"거기 너, 아무도 이곳에 지나갈 수 없다. 가던 길이나 가!","Jij daar, niemand mag hier naar binnen. Ga verder!","Du der, ingen har lov til å være her. Gå videre!","Ty tutaj, nikt nie ma prawa tu przebywać. Wynocha!","Ei, você, não pode ficar aqui. Vá embora!",,"Tu, nimeni nu are voie aici. Mișcă-te!","Эй, ты! Никому не позволено тут ошиваться. Проваливай!",,"Du där, ingen får komma in här. Flytta på er!","Sen oradaki, kimsenin buraya girmesine izin yok. İlerleyin!" +Irale will set you right up!,TXT_DLG_SCRIPT02_D39416_IRALE,MAP02: Irale's shop.,,,Irale tě hned vyzbrojí!,Irale vil sætte dig på plads!,Irale wird sich darum kümmern!,,"Irale vendos al vi ĉion, kion vi bezonas!",¡Irale te venderá lo necesario!,¡Irale te va a vender lo necesario!,Irale järkkää sinulle varusteet!,Irale a ce qu'il te faut!,Irale majd ellát.,Irale ti darà quello che ti serve!,イラールが貴方を手助けします!,여기 이롤리가 중요한 물품을 판매할 거야.,Irale zal je er goed in luizen!,Irale skal ordne opp for deg!,Irale dobrze cię przygotuje!,O Irale vai te ajudar!,,Irale te va pregăti adecvat!,Ирэйл снабдит тебя всем необходимым!,,Irale kommer att sätta dig på plats!,İrale seni hemen ayarlayacak! +I'm kinda a talent broker for the rebels. A guy who's as good as you could make a lot of gold... if you hooked up with the right people.,TXT_DLG_SCRIPT02_D40932_IMKIN,MAP02: Harris.,,,Jsem takový hledač talentů pro rebely. Někdo tak dobrý jako ty by si mohl vydělat hodně zlata... pokud by se spojil s těmi správnými lidmi.,"Jeg er en slags talentmægler for oprørerne. En fyr, der er lige så god som dig, kan tjene en masse guld ... hvis du kommer i kontakt med de rigtige folk.","Ich bin sowas wie ein Talentsucher für die Rebellen. Jemand, der so gut ist wie du kann hier eine Menge Gold verdienen... wenn du mit den richtigen Leuten in Verbindung stehst.",,"Mi estas speco de talentul-serĉanto por la ribelantoj. Iu tiel lerta, kiel vi povus gajni multe da oro… se vi ligas vin kun la ĝustaj homoj.",Soy algo así como un cazatalentos para los rebeldes. Alguien tan bueno como tú podría ganar mucho oro... Si te juntas con las personas adecuadas.,,Olen eräänlainen kykyjenvälittäjä kapinallisille. Kaltaisesi kaveri voisi tienata paljon kultaa... oikeiden kumppaneiden kanssa.,"Je suis une sorte de chasseur de têtes pour les rebelles. Un type comme toi pourrait se faire pas mal de fric... Avec les bons contacts, bien entendu.","Egyfajta toborzó vagyok a lázadóknál. Egy ürge aki ilyen jó mint te, elég sok aranyat kereshet...ha megfelelő emberekkel jösz össze.",Sono sempre alla ricerca di persone talentuose per i ribelli. Una persona come te potrebbe ricevere molto oro... se fosse in contatto con le persone giuste.,"俺は反乱者への斡旋屋さ。才能を生かして 誰よりも儲けたいと思ってるなら... 相応しい人と関係を持つことさ。 -",난 반란군을 위한 일종의 재능 중개인이야. 당신만큼 좋은 사람이라면 많은 돈을 벌 수 있겠지... 당신이 제대로 된 사람들과 연결되어 있다면.,Ik ben een soort van een talent makelaar voor de rebellen. Een man die zo goed is als je zou kunnen maken veel goud .... als je aangesloten met de juiste mensen.,Jeg er en slags talentmegler for opprørerne. En fyr som er så god som deg kan tjene mye gull... hvis du kommer i kontakt med de rette folkene.,Jestem tak jakby pośrednikiem rebeliantów. Człowiek tak dobry jak ty może zarobić dużo pieniędzy... jeśli trzymasz z właściwymi ludźmi.,Sou tipo um olheiro de talentos para rebeldes. Um cara tão bom quanto você poderia fazer bastante grana... se você se juntar às pessoas certas.,,Sunt un fel de broker de talent pentru rebeli. Un tip la fel de priceput precum ești tu ar putea face bani frumoși... dacă s-ar lega de cine trebuie.,"Я, скажем так, вербовщик повстанцев. Такой парень, как ты, может неплохо заработать... если состыкуется с нужными людьми.",,Ben asiler için yetenek simsarı sayılırım. Senin kadar iyi bir adam çok altın kazanabilir... eğer doğru insanlarla bağlantı kurarsan. -I'm interested.,TXT_RPLY0_SCRIPT02_D40932_IMINT,〃,,,Mám zájem.,Jeg er interesseret.,Ich bin interessiert.,,Tio interesas min.,Me interesa.,,Olen kiinnostunut.,Je suis intéressé.,Érdekel.,Sono interessato.,興味ある。,흥미롭군.,Ik ben geïnteresseerd.,Jeg er interessert.,Jestem zainteresowany.,Tenho interesse.,,Sunt interesat.,Я заинтригован.,,İlgileniyorum. -Screw the rebels!,TXT_RPLY1_SCRIPT02_D40932_SCREW,〃,,,Kašlu na rebely!,Skide være med rebellerne!,Scheiß auf die Rebellen!,,Fi al la ribelantoj!,¡Al demonio los rebeldes!,,Paskat kapinallisista!,Je m'en fous des rebelles!,Francba a lázadókkal!,Fanculo i ribelli!,何が反逆だ!,반란군은 집어치워!,De pot op met de rebellen!,Til helvete med opprørerne!,Pieprzyć rebeliantów!,Que se danem os rebeldes!,,La naiba cu rebelii!,К чёрту повстанцев!,,Asilerin canı cehenneme! +",난 반란군을 위한 일종의 재능 중개인이야. 당신만큼 좋은 사람이라면 많은 돈을 벌 수 있겠지... 당신이 제대로 된 사람들과 연결되어 있다면.,Ik ben een soort van een talent makelaar voor de rebellen. Een man die zo goed is als je zou kunnen maken veel goud .... als je aangesloten met de juiste mensen.,Jeg er en slags talentmegler for opprørerne. En fyr som er så god som deg kan tjene mye gull... hvis du kommer i kontakt med de rette folkene.,Jestem tak jakby pośrednikiem rebeliantów. Człowiek tak dobry jak ty może zarobić dużo pieniędzy... jeśli trzymasz z właściwymi ludźmi.,Sou tipo um olheiro de talentos para rebeldes. Um cara tão bom quanto você poderia fazer bastante grana... se você se juntar às pessoas certas.,,Sunt un fel de broker de talent pentru rebeli. Un tip la fel de priceput precum ești tu ar putea face bani frumoși... dacă s-ar lega de cine trebuie.,"Я, скажем так, вербовщик повстанцев. Такой парень, как ты, может неплохо заработать... если состыкуется с нужными людьми.",,Jag är en slags talangmäklare för rebellerna. En kille som är lika bra som du kan tjäna en massa guld... om du kopplar ihop dig med rätt personer.,Ben asiler için yetenek simsarı sayılırım. Senin kadar iyi bir adam çok altın kazanabilir... eğer doğru insanlarla bağlantı kurarsan. +I'm interested.,TXT_RPLY0_SCRIPT02_D40932_IMINT,〃,,,Mám zájem.,Jeg er interesseret.,Ich bin interessiert.,,Tio interesas min.,Me interesa.,,Olen kiinnostunut.,Je suis intéressé.,Érdekel.,Sono interessato.,興味ある。,흥미롭군.,Ik ben geïnteresseerd.,Jeg er interessert.,Jestem zainteresowany.,Tenho interesse.,,Sunt interesat.,Я заинтригован.,,Jag är intresserad.,İlgileniyorum. +Screw the rebels!,TXT_RPLY1_SCRIPT02_D40932_SCREW,〃,,,Kašlu na rebely!,Skide være med rebellerne!,Scheiß auf die Rebellen!,,Fi al la ribelantoj!,¡Al demonio los rebeldes!,¡Al carajo los rebeldes!,Paskat kapinallisista!,Je m'en fous des rebelles!,Francba a lázadókkal!,Fanculo i ribelli!,何が反逆だ!,반란군은 집어치워!,De pot op met de rebellen!,Til helvete med opprørerne!,Pieprzyć rebeliantów!,Que se danem os rebeldes!,,La naiba cu rebelii!,К чёрту повстанцев!,,Skit i rebellerna!,Asilerin canı cehenneme! "No, no second chance. Oh guards, kill him.",TXT_DLG_SCRIPT02_D42448_NONOS,〃,,,"Druhou šanci už nedostaneš. Á, stráže, zabte ho.","Nej, ingen ny chance. Åh vagter, dræb ham.","Nein, keine zweite Chance. Oh, Wachen, tötet ihn.",,"Ne, ne estas alia ŝanco. Gardistoj, mortigu lin!","No, no hay otra oportunidad. ¡Guardias, matadlo!","No, no hay otra oportunidad. ¡Guardias, mátenlo!","Ei, ei toista mahdollisuutta. Vartijat, tappakaa hänet.","Non, non, pas de deuxième chance. Gardes, tuez-le.","Nem, nincs második esély. Őrök, intézzétek el!","Nessuna seconda chance. Guardie, uccidetelo.","次はねえな。おぅガードの旦那、 -やっちゃってくだせえ。","안 돼, 두 번째 기회는 없어. 경비원, 저놈을 죽여.","Nee, geen tweede kans. Oh bewakers, dood hem.","Nei, ingen ny sjanse. Vakter, drep ham.","Nie, nie będzie drugiej szansy. Oh... strażnicy, zabijcie go.","Não, sem segundas chances. Ah, guardas, matem ele.",,"Nu, nici o altă șansă. Oh gardienilor, omorâți-l.","Нет, никакого второго шанса. Эй, стража, убейте его.",,"Hayır, ikinci bir şans yok. Muhafızlar, öldürün onu." -Good choice. The Order's sanctuary by the river is their unofficial torture chamber. Hidden inside there's a golden chalice. You swipe it and reap your reward.,TXT_DLG_SCRIPT02_D43964_GOODC,〃,,,Dobrá volba. Svatyně Řádu u řeky je jejich tajná mučírna. Uvnitř je skrytý zlatý kalich. Ukradni ho a převezmi si svou odměnu.,Godt valg. Ordenens fristed ved floden er deres uofficielle torturkammer. Der er en gylden bæger gemt derinde. Du tager den og høster din belønning.,Gute Wahl. Das Heiligtum des Ordens bei dem Fluss ist ihre inoffiziele Folterkammer. Darin versteckt ist ein goldener Kelch. Du klaust ihn und erntest deinen Lohn.,,Bona elekto. La sanktejo de La Ordono ĉe la rivero estas ĝia neoficiala torturejo. En ĝi estas kaŝita ora kaliko. Alportu ĝin al mi kaj vi havos rekompencon.,Buena elección. El santuario de La Orden junto al río es su cámara de tortura extraoficial. Dentro hay un cáliz dorado escondido. Tráemelo y tendrás tu recompensa.,"Buena elección. El santuario de La Orden junto al río es su cámara de tortura extraoficial. Adentro hay un cáliz dorado escondido. Si me lo traes, tu recompensa.","Viisas päätös. Veljeskunnan pyhäkkö joen varrella on heidän epävirallinen kidutuskammionsa, jonka kätköissä piilee kultakalkki. Kähvellä se ja saat vaivannäöstäsi palkan.",Bon choix. Le sanctuaire de l'ordre près de la rivière est leur chambre torture.. officieusement. A l'intérieur se trouve un calice en or. Récupérez le et venez prendre votre récompense.,"Jó választás. A Rend Szentélye a folyónál a nem hivatalos kínzókamrájuk. Odabent elrejtve található egy arany kehely. Elcsened, és learatod a dicsőséged.",Ottima scelta. Il santuario dell'Ordine vicino al fiume è la loro camera della tortura. Vi è un calice d'oro nascosto là dentro. Prendilo e avrai una lauta ricompensa.,"良い判断だ。川沿いにあるオーダーの聖域は +やっちゃってくだせえ。","안 돼, 두 번째 기회는 없어. 경비원, 저놈을 죽여.","Nee, geen tweede kans. Oh bewakers, dood hem.","Nei, ingen ny sjanse. Vakter, drep ham.","Nie, nie będzie drugiej szansy. Oh... strażnicy, zabijcie go.","Não, sem segundas chances. Ah, guardas, matem ele.",,"Nu, nici o altă șansă. Oh gardienilor, omorâți-l.","Нет, никакого второго шанса. Эй, стража, убейте его.",,"Nej, ingen andra chans. Åh vakter, döda honom.","Hayır, ikinci bir şans yok. Muhafızlar, öldürün onu." +Good choice. The Order's sanctuary by the river is their unofficial torture chamber. Hidden inside there's a golden chalice. You swipe it and reap your reward.,TXT_DLG_SCRIPT02_D43964_GOODC,〃,,,Dobrá volba. Svatyně Řádu u řeky je jejich tajná mučírna. Uvnitř je skrytý zlatý kalich. Ukradni ho a převezmi si svou odměnu.,Godt valg. Ordenens fristed ved floden er deres uofficielle torturkammer. Der er en gylden bæger gemt derinde. Du tager den og høster din belønning.,Gute Wahl. Das Heiligtum des Ordens bei dem Fluss ist ihre inoffiziele Folterkammer. Darin versteckt ist ein goldener Kelch. Du klaust ihn und erntest deinen Lohn.,,Bona elekto. La sanktejo de La Ordeno ĉe la rojo estas ĝia neoficiala torturejo. En ĝi estas kaŝita ora kaliko. Alportu ĝin al mi kaj vi havos rekompencon.,Buena elección. El santuario de La Orden junto al arroyo es su cámara de tortura extraoficial. Dentro hay un cáliz dorado escondido. Tráemelo y tendrás tu recompensa.,"Buena elección. El santuario de La Orden junto al río es su cámara de tortura extraoficial. Adentro hay un cáliz dorado escondido. Si me lo traes, tu recompensa.","Viisas päätös. Veljeskunnan pyhäkkö joen varrella on heidän epävirallinen kidutuskammionsa, jonka kätköissä piilee kultakalkki. Kähvellä se ja saat vaivannäöstäsi palkan.",Bon choix. Le sanctuaire de l'ordre près de la rivière est leur chambre torture.. officieusement. A l'intérieur se trouve un calice en or. Récupérez le et venez prendre votre récompense.,"Jó választás. A Rend Szentélye a folyónál a nem hivatalos kínzókamrájuk. Odabent elrejtve található egy arany kehely. Elcsened, és learatod a dicsőséged.",Ottima scelta. Il santuario dell'Ordine vicino al fiume è la loro camera della tortura. Vi è un calice d'oro nascosto là dentro. Prendilo e avrai una lauta ricompensa.,"良い判断だ。川沿いにあるオーダーの聖域は あいつらの非公式の拷問室だ。中には黄金の 聖杯が隠してある。そいつを持ってくれば 報酬をやるぜ。 -",좋은 선택이야. 강가 근처에 있는 성소가 바로 오더의 비공식적인 고문실이야. 그리고 그 안에는 숨겨진 금색 성배가 있지. 넌 그것을 훔치고 보상을 받으면 돼.,Goede keuze. Het heiligdom van de Orde bij de rivier is hun onofficiële martelkamer. Verborgen in de kelk zit een gouden kelk. Je haalt hem weg en plukt je beloning.,Godt valg. Ordenens helligdom ved elven er deres uoffisielle torturkammer. Gjemt der inne er det et gyllent beger. Ta det og høste belønningen din.,Dobry wybór. Sanktuarium Zakonu nad rzeką to ich nieoficjalna sala tortur. Jest w niej ukryty złoty kielich. Zwijasz go i dostajesz swoją nagrodę.,Boa escolha. O santuário da Ordem perto do rio é a câmara de tortura não-oficial deles. Há um cálice dourado escondido dentro. Pegue-o e você recebe a sua recompensa.,,Bună alegere. Sanctuarul Ordinului de lângă râu e camera lor de tortură neoficială. Ascuns în interior e un potir auriu. Îl înhați și culegi recompensa.,Правильный выбор. В святилище Ордена у реки — там у них негласная камера пыток — спрятана золотая чаша. Ты крадёшь её и получаешь свою награду.,,İyi seçim. Tarikat'ın nehir kenarındaki sığınağı onların gayri resmi işkence odası. İçinde altın bir kadeh saklı. Onu araklarsın ve ödülünü alırsın. -How am I supposed to do that?,TXT_RPLY0_SCRIPT02_D43964_HOWAM,〃,,,Jak to mám udělat?,Hvordan skal jeg gøre det?,Wie soll ich das anstellen?,,Kiel mi faru tion?,¿Cómo se supone que debo hacer eso?,,Miten ihmeessä minä sen teen?,Comment est-ce que je suis sensé faire ça?,Mégis hogy kéne hozzálássak ehhez?,E come posso fare tutto ciò?,どうすればいい?,내가 그걸 어떻게 하지?,Hoe moet ik dat doen?,Hvordan skal jeg gjøre det?,Jak powinienem to zrobić?,E como eu vou fazer isso?,,Și cum ar trebui să fac asta?,И как я это сделаю?,,Bunu nasıl yapacağım? -"Here's a crossbow, just aim straight and --splat--. Remember, grab the fancy cup and get to the tavern.",TXT_DLG_SCRIPT02_D45480_HERES,〃,,,"Tady máš kuši, prostě zamiř rovně a --plesk--. Ještě jednou: popadni fešný hrnek a přijď do taverny.","Her er en armbrøst, bare sigt lige ud og -splat--. Husk, tag det fine bæger og gå til tavernaen.","Hier ist eine Armbust, einfach gerade zielen und --Platsch--. Denk dran, schnapp dir den schicken Kelch und dann ab zur Taverne.",,Jen arbalesto. Vi nur celu laŭ rekta linio kaj «gut». Ne forgesu preni la belan pokalon kaj tiam reveni al la taverno.,Aquí tengo una ballesta. Solo apunta en línea recta y «ploc». Recuerda: toma la bonita copa y luego vuelve aquí a la taberna.,,"Tässä sinulle jousipyssy; tähtää vain eteenpäin ja ""pläts""! Tärkeintä vain, että muistat kahmaista fiinin maljan ja sitten palata kapakkaan.",Voilà une arbalète. Vous avez juste à viser droit et paf! Souvenez-vous. Prenez le goblet et ramenez le à la taverne.,"Itt a számszeríj. Csak célozz előre és -placcs- . Vésd az eszedbe, fogd a pofás kis csészét és menj a fogadóba!","Ecco una balestra, basta mirare e --splat--. Ricorda, prendi il calice e ritorna alla taverna.","このクロスボウを使いな、狙いを定めて +",좋은 선택이야. 강가 근처에 있는 성소가 바로 오더의 비공식적인 고문실이야. 그리고 그 안에는 숨겨진 금색 성배가 있지. 넌 그것을 훔치고 보상을 받으면 돼.,Goede keuze. Het heiligdom van de Orde bij de rivier is hun onofficiële martelkamer. Verborgen in de kelk zit een gouden kelk. Je haalt hem weg en plukt je beloning.,Godt valg. Ordenens helligdom ved elven er deres uoffisielle torturkammer. Gjemt der inne er det et gyllent beger. Ta det og høste belønningen din.,Dobry wybór. Sanktuarium Zakonu nad rzeką to ich nieoficjalna sala tortur. Jest w niej ukryty złoty kielich. Zwijasz go i dostajesz swoją nagrodę.,Boa escolha. O santuário da Ordem perto do rio é a câmara de tortura não-oficial deles. Há um cálice dourado escondido dentro. Pegue-o e você recebe a sua recompensa.,,Bună alegere. Sanctuarul Ordinului de lângă râu e camera lor de tortură neoficială. Ascuns în interior e un potir auriu. Îl înhați și culegi recompensa.,Правильный выбор. В святилище Ордена у реки — там у них негласная камера пыток — спрятана золотая чаша. Ты крадёшь её и получаешь свою награду.,,Bra val. Ordens helgedom vid floden är deras inofficiella tortyrkammare. Gömd inuti finns en gyllene kalk. Du tar den och skördar din belöning.,İyi seçim. Tarikat'ın nehir kenarındaki sığınağı onların gayri resmi işkence odası. İçinde altın bir kadeh saklı. Onu araklarsın ve ödülünü alırsın. +How am I supposed to do that?,TXT_RPLY0_SCRIPT02_D43964_HOWAM,〃,,,Jak to mám udělat?,Hvordan skal jeg gøre det?,Wie soll ich das anstellen?,,Kiel mi supozeble faru tion?,¿Cómo se supone que debo hacer eso?,,Miten ihmeessä minä sen teen?,Comment est-ce que je suis sensé faire ça?,Mégis hogy kéne hozzálássak ehhez?,E come posso fare tutto ciò?,どうすればいい?,내가 그걸 어떻게 하지?,Hoe moet ik dat doen?,Hvordan skal jeg gjøre det?,Jak powinienem to zrobić?,E como eu vou fazer isso?,,Și cum ar trebui să fac asta?,И как я это сделаю?,,Hur ska jag göra det?,Bunu nasıl yapacağım? +"Here's a crossbow, just aim straight and --splat--. Remember, grab the fancy cup and get to the tavern.",TXT_DLG_SCRIPT02_D45480_HERES,〃,,,"Tady máš kuši, prostě zamiř rovně a --plesk--. Ještě jednou: popadni fešný hrnek a přijď do taverny.","Her er en armbrøst, bare sigt lige ud og -splat--. Husk, tag det fine bæger og gå til tavernaen.","Hier ist eine Armbust, einfach gerade zielen und --Platsch--. Denk dran, schnapp dir den schicken Kelch und dann ab zur Taverne.",,Jen arbalesto. Vi nur celu laŭ rekta linio kaj «pum». Ne forgesu preni la belan pokalon kaj tiam reveni al la taverno.,Aquí tengo una ballesta. Solo apunta en línea recta y «plaf». Recuerda: toma la bonita copa y luego vuelve aquí a la taberna.,,"Tässä sinulle jousipyssy; tähtää vain eteenpäin ja ""pläts""! Tärkeintä vain, että muistat kahmaista fiinin maljan ja sitten palata kapakkaan.",Voilà une arbalète. Vous avez juste à viser droit et paf! Souvenez-vous. Prenez le goblet et ramenez le à la taverne.,"Itt a számszeríj. Csak célozz előre és -placcs- . Vésd az eszedbe, fogd a pofás kis csészét és menj a fogadóba!","Ecco una balestra, basta mirare e --splat--. Ricorda, prendi il calice e ritorna alla taverna.","このクロスボウを使いな、狙いを定めて --シュッとな。覚えておけ、 -ファンシーなカップを持ってここに戻ってこい。","여기 석궁이야, 똑바로 겨냥해, 그리고... '철퍼덕'. 기억해, 멋진 컵을 들고 선술집에 와.","Hier is een kruisboog, mik gewoon recht en --splat--. Vergeet niet, pak de mooie beker en ga naar de herberg.","Her er en armbrøst, bare sikt rett og --splat--. Husk å ta det fine begeret og gå til vertshuset.","Oto kusza, tylko wyceluj i --plask--. Pamiętaj, weź ozdobny puchar i wróć do tawerny.","Aqui está uma besta. Só mirar reto e --splat--. Lembre-se, pegue o copo bonito e vá pra taverna.",,"Uite o arbaletă, doar țintești drept și --pleoșc--. Ține minte, ia cana scumpă și du-te la tavernă.",Вот арбалет — просто прицеливаешься и «шлёп!» Запомни — хватаешь чашку и возвращаешься в таверну.,,"İşte bir arbalet, sadece düz nişan al ve --splat--. Unutma, süslü kupayı al ve tavernaya git." +ファンシーなカップを持ってここに戻ってこい。","여기 석궁이야, 똑바로 겨냥해, 그리고... '철퍼덕'. 기억해, 멋진 컵을 들고 선술집에 와.","Hier is een kruisboog, mik gewoon recht en --splat--. Vergeet niet, pak de mooie beker en ga naar de herberg.","Her er en armbrøst, bare sikt rett og --splat--. Husk å ta det fine begeret og gå til vertshuset.","Oto kusza, tylko wyceluj i --plask--. Pamiętaj, weź ozdobny puchar i wróć do tawerny.","Aqui está uma besta. Só mirar reto e --splat--. Lembre-se, pegue o copo bonito e vá pra taverna.",,"Uite o arbaletă, doar țintești drept și --pleoșc--. Ține minte, ia cana scumpă și du-te la tavernă.",Вот арбалет — просто прицеливаешься и «шлёп!» Запомни — хватаешь чашку и возвращаешься в таверну.,,"Här är ett armborst, sikta bara rakt och --splat--. Kom ihåg att ta den fina bägaren och gå till tavernan.","İşte bir arbalet, sadece düz nişan al ve --splat--. Unutma, süslü kupayı al ve tavernaya git." Cool. I'll get it.,TXT_RPLY0_SCRIPT02_D45480_COOLI,〃,,,"Fajn, přinesu ho.",Det er fedt. Jeg henter den.,Cool. Ich werde ihn holen.,,Bonege. Mi trovos ĝin.,Genial. Ya lo traigo.,,Selvä. Saan sen.,Ok. Je m'en occupe.,Király. Meglesz majd.,Va bene. Vado a prenderlo.,良い物だ、貰っとく。,"멋지군, 이해 했어.",Cool. Ik zal het krijgen.,Kult. Jeg henter den.,Fajnie. Wchodzę w to.,Beleza. Vou lá pegar.,,Tare. O voi lua.,"Класс. Я достану её. -",,Güzel. Ben alırım. -What are you waiting for? Bring me that chalice.,TXT_DLG_SCRIPT02_D46996_WHATA,〃,,,Na co čekáš? Přines mi ten kalich.,Hvad venter du på? Giv mig det bæger.,Worauf wartest du noch? Bring mir den Kelch.,,Kion vi atendas? Alportu tiun kalikon.,¿A qué estás esperando? Tráeme ese cáliz.,¿Qué estás esperando? Tráeme ese cáliz.,Mitä oikein jahkailet? Tuo minulle se kalkki.,Qu'attendez vous? Récupérez-moi ce calice.,Mire vársz? Hozd ide azt a kelyhet.,Cosa stai aspettando? Portami il calice.,何ボーっとしてんだ?とっとと聖杯を持ってこい。,뭘 기다리는 거야? 가서 성배를 찾아.,Waar wacht je nog op? Breng me die kelk.,Hva venter du på? Gi meg det begeret.,Na co czekasz? Przynieś mi ten kielich.,Está esperando o quê? Me traga o cálice.,,Ce mai aștepți? Adu-mi potirul acela.,Чего ты ждёшь? Принеси мне эту чашу.,,Ne bekliyorsun? Bana o kadehi getir. +",,Coolt. Jag hämtar den.,Güzel. Ben alırım. +What are you waiting for? Bring me that chalice.,TXT_DLG_SCRIPT02_D46996_WHATA,〃,,,Na co čekáš? Přines mi ten kalich.,Hvad venter du på? Giv mig det bæger.,Worauf wartest du noch? Bring mir den Kelch.,,Kion vi atendas? Alportu tiun kalikon.,¿A qué estás esperando? Tráeme ese cáliz.,¿Qué estás esperando? Tráeme ese cáliz.,Mitä oikein jahkailet? Tuo minulle se kalkki.,Qu'attendez vous? Récupérez-moi ce calice.,Mire vársz? Hozd ide azt a kelyhet.,Cosa stai aspettando? Portami il calice.,何ボーっとしてんだ?とっとと聖杯を持ってこい。,뭘 기다리는 거야? 가서 성배를 찾아.,Waar wacht je nog op? Breng me die kelk.,Hva venter du på? Gi meg det begeret.,Na co czekasz? Przynieś mi ten kielich.,Está esperando o quê? Me traga o cálice.,,Ce mai aștepți? Adu-mi potirul acela.,Чего ты ждёшь? Принеси мне эту чашу.,,Vad väntar du på? Ge mig den där bägaren.,Ne bekliyorsun? Bana o kadehi getir. "Hey, I know, kinda looks like a set-up. I would never do that to such a great killing machine. Got the item? Great! Now get ready, gold and glory just like I promised. Take this key and the Governor will reward you.",TXT_DLG_SCRIPT02_D48512_HEYIK,〃,,,"Hej, já vím, že tohle vypadá jako bouda. Takovému zabijákovi jako ty bych nikdy nic takového neudělal! Máš ten kalich? Fajn! Tak teď se připrav, zlato a sláva, jak jsem slíbil. Vem si tenhle klíč a samotný guvernér tě odmění.","Jeg ved det godt, det ligner en fælde. Jeg ville aldrig gøre det mod sådan en stor dræbermaskine. Har du genstanden? Fedt! Gør dig nu klar, guld og ære, som jeg lovede. Tag denne nøgle, og guvernøren vil belønne dig.","Hey, ich weiß, es sieht anscheinend wie eine Falle aus, aber so etwas würde ich einer so großeartigen Tötungsmaschine nicht antun. Hast du ddas Ding? Großartig! Nun mach dich bereit, Geld und Ruhm, genau wie ich es dir versprochen habe. Nimm diesen Schlüssel und der Gouverneur wird dich belohnen.",,"Jes, mi scias, ĉi tio ŝajnas trompo, sed mi neniam farus tion al bonega mortig-maŝino. Ĉu vi havas la kalikon? Bonege! Pretiĝu: oro kaj gloro, tiel, kiel mi promesis. Prenu ĉi tiun ŝlosilon kaj la registo rekompencos vin.","Sí, ya lo sé, esto parece un timo, pero nunca le haría eso a una gran máquina de matar. ¿Tienes el cáliz? ¡Genial! Ahora prepárate: oro y gloria, tal y como he prometido. Toma esta llave y el gobernador te recompensará.","Sí, ya lo sé, esto parece una estafa, pero nunca le haría eso a una gran máquina de matar. ¿Tienes el cáliz? ¡Genial! Ahora prepárate: oro y gloria, tal y como prometí. Toma esta llave y el gobernador te va a recompensar.","Joo joo, tiedän, että on vähän väijytyksen makua. En kuitenkaan ikinä tekisi sellaista niin kovalle tappokoneelle. Saitko tavaran? Loistavaa! No niin, valmistaudu kultaan ja kunniaan, juuri niin kuin lupasinkin. Ota tämä avain ja kuvernööri palkitsee sinut.","Hé, je sais que ça à l'air d'être un coup monté, mais je ne ferais jamais ça à une aussi bonne machine à tuer. Vous avez le butin? Excellent! Préparez vous, l'or et la gloire vous attend, comme promis. Prenez cette clé et le gouverneur vous récompensera.","Tudom, hogy olyan szaga van mint egy csapdának. Sosem tennék ilyet egy ilyen kiváló gyilkológéppel. Megvan a cuccos? Zsír! Most készülj fel, arany és hírnév, mint ahogy ígértem. Vidd ezt a kulcsot és a kormányzó megjutalmaz.","Ehi, so che può sembrare una trappola. Ma io non tradirei mai a un killer abile come te. Hai il calice? Benissimo! Ora preparati, oro e gloria ti aspettano come promesso. Prendi questa chiave e il Governatore in persona ti ricompenserà.","おう、罠みたいだと思ったか。 俺に暴れん坊みたいな芸当出来るわきゃねえ。 ブツはあるか?そりゃいい!じゃあ準備しな。 金と栄光は約束された。この鍵で知事に合えば 報酬をありったけくれるさ。 -","이봐, 알겠어. 확실히 뭔가 꾸며 놓은 것 같다는 거. 난 훌륭한 학살 기계에게 그런 짓을 할 사람이 아니야. 그래서 그걸 가져왔나? 좋아! 그럼 약속한 대로 골드와 영광을 줄 테니 준비해. 이 열쇠를 총독에게 가져다주면 보상해 줄 거야.","Hé, ik weet het, het ziet er een beetje uit als een valstrik. Dat zou ik nooit met zo'n grote moordmachine doen. Heb je het item? Geweldig! Maak je nu klaar, goud en glorie, net zoals ik beloofd heb. Neem deze sleutel en de gouverneur zal je belonen.","Jeg vet at det ser ut som en felle. Jeg ville aldri gjort det mot en så flott drapsmaskin. Har du gjenstanden? Flott! Gjør deg klar. Gull og ære, som jeg lovte. Ta denne nøkkelen, så vil guvernøren belønne deg.","Hej, wiem, wygląda to jak zasadzka. Nigdy bym czegoś takiego nie zrobił wspaniałej maszynie do zabijania. Masz przedmiot? Wspaniale! Przygotuj się teraz, złoto i chwała tak jak obiecywałem. Weź ten klucz, a Gubernator cię nagrodzi.","Olha, eu sei, meio que parece uma cilada. Eu nunca faria aquilo a uma grande máquina mortífera. Conseguiu o item? Ótimo! Agora se prepare, ouro e glória conforme prometido. Pegue esta chave e o Governador irá te recompensar.",,"Hei, știu că pare o capcană. Nu aș face așa ceva niciodată unei mașini ucigașe atât de tare. Ai obiectul? Perfect! Acum pregătește-te, aur și glorie cum ți-am promis. Ia cheia asta și Guvernatorul te va răsplătii.","Слушай, я знаю, о чём ты думаешь. Ты думаешь, что это подстава. Но я бы никогда не сделал этого с такой машиной для убийств, как ты. Достал то, что я просил? Отлично! Тебя ждёт золото и слава, как я и обещал. Возьми этот ключ — губернатор лично наградит тебя.",,"Hey, biliyorum, biraz tuzağa benziyor. Böyle büyük bir ölüm makinesine bunu asla yapmazdım. Eşyayı aldın mı? Harika! Şimdi hazır ol, söz verdiğim gibi altın ve şan. Bu anahtarı al ve Vali seni ödüllendirecek." -He'd better. For your sake!,TXT_RPLY0_SCRIPT02_D48512_HEDBE,〃,,,"To by tedy měl, pro tvoje vlastní dobro!",Det har han bare at gøre. For din skyld!,Das macht er besser. Deinetwillen!,,Li devus. Por via bono!,Más le vale. ¡Por tu propio bien!,,Parasta palkitakin! Sinun kannaltasi!,"Il a intérêt, pour votre bien!",Jobban teszi. A Te érdekedben!,È meglio che lo faccia... per il tuo bene!,戻せ、お前の為だ!,"살고 싶으면, 이 말이 사실이야 할 거다!",Dat is hem maar beter gelukt. Voor uw eigen bestwil!,Det bør han. For din skyld!,Mam nadzieję. Dla twojego dobra!,Acho bom mesmo. Pro seu bem!,,Ar face bine. De dragul tău!,Надеюсь. Это в твоих интересах!,,Öyle olsa iyi olur. Senin hatırın için! -What! Where's my money?,TXT_RPLY1_SCRIPT02_D48512_WHATW,〃,,,Cože? Kde jsou moje peníze?,Hvad! Hvor er mine penge?,Was! Wo ist mein Geld?,,Kio!? Kie estas mia mono?,¿¡Qué!? ¿Y mi dinero?,,Mitä! Missä on rahani?,Quoi? Où est mon argent!,Mi a túró! Hol van a pénzem?,Aspetta! Dove sono i miei soldi?,何だと! 金はどこだ?,뭐라고! 내 돈은 어디있지?,Wat! Waar is mijn geld?,Hva! Hvor er pengene mine?,Co! Gdzie moje pieniądze?,Como é? Cadê o meu dinheiro?,,Ce! Unde sunt banii mei?,Что? Где мои деньги?,,Ne! Param nerede? -"Get lost kid, you bother me.",TXT_DLG_SCRIPT02_D50028_GETLO,〃,,,"Odprejskni, mladej, otravuješ mě.","Forsvind, knægt, du generer mig.","Verzieh dich Jungchen, du störst mich.",,"Foriru, junulo; vi ĝenas min.","Ya vete, chaval, que eres pesado.","Ya vete de una vez, que eres pesado.","Häivy nulikka, häiritset minua.","Dégage, gamin, tu m'agaces.","Kopj le kölyök, ne itt lábatlankodj.","Sparisci, ragazzo, mi stai infastidendo.",失せろ、うざってえ。,사라져. 신경 거슬리게 하지 말고.,"Rot op, jongen, je stoort me.","Forsvinn, gutt, du plager meg.","Spadaj mały, przeszkadzasz mi.","Some daqui, garoto. Você está me incomodando.",,"Cară-te puștiule, mă deranjezi.","Пропади, малой. Ты меня раздражаешь.",,"Kaybol evlat, beni rahatsız ediyorsun." +","이봐, 알겠어. 확실히 뭔가 꾸며 놓은 것 같다는 거. 난 훌륭한 학살 기계에게 그런 짓을 할 사람이 아니야. 그래서 그걸 가져왔나? 좋아! 그럼 약속한 대로 골드와 영광을 줄 테니 준비해. 이 열쇠를 총독에게 가져다주면 보상해 줄 거야.","Hé, ik weet het, het ziet er een beetje uit als een valstrik. Dat zou ik nooit met zo'n grote moordmachine doen. Heb je het item? Geweldig! Maak je nu klaar, goud en glorie, net zoals ik beloofd heb. Neem deze sleutel en de gouverneur zal je belonen.","Jeg vet at det ser ut som en felle. Jeg ville aldri gjort det mot en så flott drapsmaskin. Har du gjenstanden? Flott! Gjør deg klar. Gull og ære, som jeg lovte. Ta denne nøkkelen, så vil guvernøren belønne deg.","Hej, wiem, wygląda to jak zasadzka. Nigdy bym czegoś takiego nie zrobił wspaniałej maszynie do zabijania. Masz przedmiot? Wspaniale! Przygotuj się teraz, złoto i chwała tak jak obiecywałem. Weź ten klucz, a Gubernator cię nagrodzi.","Olha, eu sei, meio que parece uma cilada. Eu nunca faria aquilo a uma grande máquina mortífera. Conseguiu o item? Ótimo! Agora se prepare, ouro e glória conforme prometido. Pegue esta chave e o Governador irá te recompensar.",,"Hei, știu că pare o capcană. Nu aș face așa ceva niciodată unei mașini ucigașe atât de tare. Ai obiectul? Perfect! Acum pregătește-te, aur și glorie cum ți-am promis. Ia cheia asta și Guvernatorul te va răsplătii.","Слушай, я знаю, о чём ты думаешь. Ты думаешь, что это подстава. Но я бы никогда не сделал этого с такой машиной для убийств, как ты. Достал то, что я просил? Отлично! Тебя ждёт золото и слава, как я и обещал. Возьми этот ключ — губернатор лично наградит тебя.",,"Jag vet, det ser ut som en uppställning. Jag skulle aldrig göra det mot en så stor mördarmaskin. Har du föremålet? Bra! Gör dig nu redo, guld och ära precis som jag lovade. Ta den här nyckeln och guvernören kommer att belöna dig.","Hey, biliyorum, biraz tuzağa benziyor. Böyle büyük bir ölüm makinesine bunu asla yapmazdım. Eşyayı aldın mı? Harika! Şimdi hazır ol, söz verdiğim gibi altın ve şan. Bu anahtarı al ve Vali seni ödüllendirecek." +He'd better. For your sake!,TXT_RPLY0_SCRIPT02_D48512_HEDBE,〃,,,"To by tedy měl, pro tvoje vlastní dobro!",Det har han bare at gøre. For din skyld!,Das macht er besser. Deinetwillen!,,Li devus. Por via bono!,Más le vale. ¡Por tu propio bien!,,Parasta palkitakin! Sinun kannaltasi!,"Il a intérêt, pour votre bien!",Jobban teszi. A Te érdekedben!,È meglio che lo faccia... per il tuo bene!,戻せ、お前の為だ!,"살고 싶으면, 이 말이 사실이야 할 거다!",Dat is hem maar beter gelukt. Voor uw eigen bestwil!,Det bør han. For din skyld!,Mam nadzieję. Dla twojego dobra!,Acho bom mesmo. Pro seu bem!,,Ar face bine. De dragul tău!,Надеюсь. Это в твоих интересах!,,Det är bäst att han gör det. För din skull!,Öyle olsa iyi olur. Senin hatırın için! +What! Where's my money?,TXT_RPLY1_SCRIPT02_D48512_WHATW,〃,,,Cože? Kde jsou moje peníze?,Hvad! Hvor er mine penge?,Was! Wo ist mein Geld?,,Kio!? Kie estas mia mono?,¿¡Qué!? ¿Y mi dinero?,,Mitä! Missä on rahani?,Quoi? Où est mon argent!,Mi a túró! Hol van a pénzem?,Aspetta! Dove sono i miei soldi?,何だと! 金はどこだ?,뭐라고! 내 돈은 어디있지?,Wat! Waar is mijn geld?,Hva! Hvor er pengene mine?,Co! Gdzie moje pieniądze?,Como é? Cadê o meu dinheiro?,,Ce! Unde sunt banii mei?,Что? Где мои деньги?,,Vad! Var är mina pengar?,Ne! Param nerede? +"Get lost kid, you bother me.",TXT_DLG_SCRIPT02_D50028_GETLO,〃,,,"Odprejskni, mladej, otravuješ mě.","Forsvind, knægt, du generer mig.","Verzieh dich Jungchen, du störst mich.",,"Foriru, junulo; vi ĝenas min.","Ya vete, chaval, que eres pesado.","Ya vete de una vez, que eres pesado.","Häivy nulikka, häiritset minua.","Dégage, gamin, tu m'agaces.","Kopj le kölyök, ne itt lábatlankodj.","Sparisci, ragazzo, mi stai infastidendo.",失せろ、うざってえ。,사라져. 신경 거슬리게 하지 말고.,"Rot op, jongen, je stoort me.","Forsvinn, gutt, du plager meg.","Spadaj mały, przeszkadzasz mi.","Some daqui, garoto. Você está me incomodando.",,"Cară-te puștiule, mă deranjezi.","Пропади, малой. Ты меня раздражаешь.",,"Stick, grabben, du stör mig.","Kaybol evlat, beni rahatsız ediyorsun." "No second chance. Oh guards, kill him.",TXT_DLG_SCRIPT02_D51544_NOSEC,〃,,,"Žádná druhá šance. Á, stráže, zabte ho.","Ingen ny chance. Åh vagter, dræb ham.","Keine zweite Chance. Oh Wachen, tötet ihn.",,"Ne estas alia ŝanco. Gardistoj, mortigu lin!","No hay otra oportunidad. ¡Guardias, matadlo!","No hay otra oportunidad. ¡Guardias, mátenlo!","Ei uutta tilaisuutta. Vartijat, tappakaa hänet.","Pas de deuxième chance. Gardes, tuez-le.","Nincs második esély. Ó, őrök, öljétek meg.","Nessuna seconda chance. Guardie, uccidetelo.","次はねえな。おぅガードの旦那、 -やっちゃってくだせえ。","너에게는 기회 따윈 없었어. 경비원, 저놈을 죽여.","Geen tweede kans. Oh bewakers, dood hem.","Ingen ny sjanse. Vakter, drep ham.","Nie będzie drugiej szansy. Oh... strażnicy, zabijcie go.","Sem segunda chance. Ah, guardas, matem ele.",,"Nicio altă șansă. Oh gardienilor, omorâți-l.","Нет, никакого второго шанса. Эй, стража, убейте его.",,"İkinci bir şans yok. Muhafızlar, öldürün onu." -"First they slaughter thousands, now they want all able-bodied peasants for unspecified 'tests'. How does the Order expect me to keep the peace? What the hell do you want?",TXT_DLG_SCRIPT02_D53060_FIRST,MAP02: Mourel.,,,"Tak oni nejdříve povraždí tisíce a teď po mě chtějí všechny schopné poddané pro neupřesněné 'testování'. Jak Řád očekává, že mám zachovat mír? Co ty sakra chceš?","Først slagter de tusinder, nu vil de have alle raske bønder til uspecificerede ""tests"". Hvordan forventer ordenen, at jeg skal opretholde freden? Hvad fanden vil du?",Zuerst metzeln sie Tausende nieder und nun wollen sie alle gesunden Bauern für unspezifierte „Tests“. Wie kann es der Orden nur so von mir verlangen Frieden zu bewahren? Was zum Teufel willst du?,,"Ili unue buĉis milojn, kaj nun volas ĉiujn sanegajn kamparanojn por nespecifaj «provoj». Kiel La Ordono esperas, ke mi ankoraŭ povos teni la pacon?... Kion diable vi volas?",Primero matan a miles y ahora quieren a todos los campesinos sanos para «pruebas» no especificadas. ¿Cómo espera La Orden que yo pueda seguir manteniendo la paz?... ¿Y tú qué demonios quieres?,Primero matan a miles y ahora quieren a todos los campesinos sanos para «pruebas» no especificadas. ¿Cómo espera La Orden que yo pueda seguir manteniendo la paz?... ¿Y tú qué carajo quieres?,"Ensiksi ne lahtaavat tuhansia, nyt ne haluavat kaikki kynnelle kykenevät maallikot määrittelemättömiin ""kokeisiin""'. Miten veljeskunta odottaa minun pitävän järjestystä? Mitä helvettiä sinä haluat?","D'abord ils en massacrent des miliers, maintenant ils veulent tous les paysans en bonne santé pour leur « tests » dont personne ne sait rien. Comment est-ce que l'ordre veut que je garde la paix? Qu'est-ce que vous voulez?","Először ezreket kaszabolnak le, most meg minden ép testű jobbágyot ismeretlen ""kísérletekhez"" akarnak. Hogy várhatja el a Rend, hogy fenntartsam a békét? Mi a francot akarsz?","Prima massacrano migliaia di persone, poi vogliono cittadini in buona condizione fisica per ""test"" non meglio specificati. Come può l'Ordine aspettarsi che io riesca a mantenere la pace? E tu che diavolo vuoi?","あいつら散々大量虐殺しといて、今度は'実験' +やっちゃってくだせえ。","너에게는 기회 따윈 없었어. 경비원, 저놈을 죽여.","Geen tweede kans. Oh bewakers, dood hem.","Ingen ny sjanse. Vakter, drep ham.","Nie będzie drugiej szansy. Oh... strażnicy, zabijcie go.","Sem segunda chance. Ah, guardas, matem ele.",,"Nicio altă șansă. Oh gardienilor, omorâți-l.","Нет, никакого второго шанса. Эй, стража, убейте его.",,"Ingen andra chans. Åh vakter, döda honom.","İkinci bir şans yok. Muhafızlar, öldürün onu." +"First they slaughter thousands, now they want all able-bodied peasants for unspecified 'tests'. How does the Order expect me to keep the peace? What the hell do you want?",TXT_DLG_SCRIPT02_D53060_FIRST,MAP02: Mourel.,,,"Tak oni nejdříve povraždí tisíce a teď po mě chtějí všechny schopné poddané pro neupřesněné 'testování'. Jak Řád očekává, že mám zachovat mír? Co ty sakra chceš?","Først slagter de tusinder, nu vil de have alle raske bønder til uspecificerede ""tests"". Hvordan forventer ordenen, at jeg skal opretholde freden? Hvad fanden vil du?",Zuerst metzeln sie Tausende nieder und nun wollen sie alle gesunden Bauern für unspezifierte „Tests“. Wie kann es der Orden nur so von mir verlangen Frieden zu bewahren? Was zum Teufel willst du?,,"Ili unue buĉis milojn, kaj nun volas ĉiujn sanegajn kamparanojn por nespecifaj «provoj». Kiel La Ordeno esperas, ke mi ankoraŭ povos teni la pacon?... Kion diable vi volas?",Primero matan a miles y ahora quieren a todos los campesinos sanos para «pruebas» no especificadas. ¿Cómo espera La Orden que yo pueda seguir manteniendo la paz?... ¿Y tú qué demonios quieres?,Primero matan a miles y ahora quieren a todos los campesinos sanos para «pruebas» no especificadas. ¿Cómo espera La Orden que yo pueda seguir manteniendo la paz?... ¿Y tú qué carajo quieres?,"Ensiksi ne lahtaavat tuhansia, nyt ne haluavat kaikki kynnelle kykenevät maallikot määrittelemättömiin ""kokeisiin""'. Miten veljeskunta odottaa minun pitävän järjestystä? Mitä helvettiä sinä haluat?","D'abord ils en massacrent des miliers, maintenant ils veulent tous les paysans en bonne santé pour leur « tests » dont personne ne sait rien. Comment est-ce que l'ordre veut que je garde la paix? Qu'est-ce que vous voulez?","Először ezreket kaszabolnak le, most meg minden ép testű jobbágyot ismeretlen ""kísérletekhez"" akarnak. Hogy várhatja el a Rend, hogy fenntartsam a békét? Mi a francot akarsz?","Prima massacrano migliaia di persone, poi vogliono cittadini in buona condizione fisica per ""test"" non meglio specificati. Come può l'Ordine aspettarsi che io riesca a mantenere la pace? E tu che diavolo vuoi?","あいつら散々大量虐殺しといて、今度は'実験' の為に健康な庶民を用意しろとか。オーダーは 本当に平和を維持してくれるのか? で、君は何用で来たのかね? -","먼저 오더가 수천 명을 죽여놓고, 이젠 힘 좋은 시민들을 불러서 생각지도 않은 시험을 하라고 시키는구먼. 그놈들이 나한테 바라는 게 뭔지 전혀 모르겠네. 넌 원하는 게 뭐야?","Eerst slachten ze duizenden mensen af, nu willen ze alle valide boeren voor ongespecificeerde 'tests'. Hoe verwacht de Orde dat ik de vrede bewaar? Wat wil je verdomme?","Først slakter de tusenvis, og nå vil de ha alle arbeidsføre bønder til uspesifiserte ""tester"". Hvordan forventer ordenen at jeg skal bevare freden? Hva i helvete vil du ha?","Najpierw mordują tysiące, a teraz chcą wszystkich krzepkich chłopów do nieokreślonych ""testów"". Jak Zakon oczekuje ode mnie abym utrzymywał pokój? Czego chcesz u diabła?","Primeiro eles massacram milhares, agora querem que todos os plebeus saudáveis façam ""provas"" não especificadas. Como que a Ordem quer que eu mantenha a paz? Que diabos você quer?",,"Mai întâi măcelăresc cu miile, apoi vor toți sărmanii capabili de muncă pentru 'teste' nespecificate. Cum se așteaptă Ordinul să mențin pacea? Ce naiba vrei?","Сначала они убивают людей тысячами, а теперь им нужны все пригодные рабочие для каких-то «экспериментов»! И Орден ещё хочет, чтобы я поддерживал мир? Какого чёрта тебе нужно?",,"Önce binlercesini katlettiler, şimdi de tüm sağlıklı köylüleri belirsiz 'testler' için istiyorlar. Tarikat benden barışı korumamı nasıl bekler? Ne halt istiyorsun?" -"A prison pass, let's deal.",TXT_RPLY0_SCRIPT02_D53060_APRIS,〃,,,"Propustku do vězení, udělejme dohodu.","Et fængselskort, lad os lave en aftale.",Ein Gefängnispass. Lassen Sie uns verhandeln.,,Malliberejan paspermeson. Ni intertraktu.,Un pase a la prisión. Negociemos.,,Vankilan pääsyluvan; hierotaan diili.,Un passe de la prison. Faisons affaires.,Egy börtön belépő. Üzleteljünk.,"Un pass per la prigione, trattiamo.",刑務所の許可証だ、取引をしよう。,감옥 통행증만 있으면 돼.,"Een gevangenispasje, laten we dealen.","Et fengselspass, la oss gjøre en avtale.","Przepustkę do więzienia, ponegocjujmy.","Um passe da prisão, vamos negociar.",,O legitimație pentru închisoare. Să facem un târg.,Пропуск в тюрьму. Заключим сделку.,,"Bir hapishane izni, anlaşalım." -"I like you already. I have two chores that I don't want to do myself. One is messy, the other bloody.",TXT_DLG_SCRIPT02_D54576_ILIKE,〃,,,"Už teď se mi líbíš. Mám dvě prácičky, které nechci dělat sám. Jedna je špinavá, druhá je krvavá.","Jeg kan allerede godt lide dig. Jeg har to pligter, som jeg ikke selv vil gøre. Den ene er rodet, den anden er blodig.","Du gefällst mir bereits. Ich habe zwei lästige Angelegenheiten, um die ich mich nicht selber kümmern möchte. Die eine davon ist dreckig, die andere blutig.",,"Mi jam ŝatas vin. Estas du farotaĵoj, kiujn mi mem ne volas fari: unu estas malpura kaj la alia estas sanga.",Ya me caes bien. Hay dos tareas que no quiero hacer por mi cuenta: una es sucia y la otra sangrienta.,,"Minähän pidän sinusta. Minulla olisi kyllä pari askaretta, joita en itse haluaisi tehdä. Yksi niistä on sotkuinen, toinen hurmeinen.","Vous me plaisez déjà. J'ai deux corvées que je n'ai pas envie de faire. Une est.. Sale, l'autre est sanglante.","Kedvellek már most. Van két feladatom, amit nem akarok magam végezni. Az egyik a koszos, a másik a véres.","Già mi piaci. Ho due faccende da sbrigare che non voglio fare di persona. Una è un pò complicata, e l'altra da risolvere col sangue.","いいだろう。仕事は二つあるのだが -一つは面倒で、もう一つは血を見ることになる。",이제야 말길이 가네. 지금 너에게 맡을 시험이 두 가지 있거든. 더러운 거랑... 잔인한 거.,"Ik vind je nu al leuk. Ik heb twee taken die ik zelf niet wil doen. De ene is rommelig, de andere bloedig.","Jeg liker deg allerede. Jeg har to plikter jeg ikke vil gjøre selv. Det ene er rotete, det andre blodig.","Już cię lubię. Mam dwa zadania, których sam nie chcę wykonać. Jedno jest brudne, a drugie krwawe.","Estou gostando de você. Tenho mais duas tarefas chatas que eu particularmente não estou a fim de fazer. Uma é suja, a outra sangrenta.",,"Deja îmi placi. Am două treburi nasoale pe care nu vreau să le fac eu însumi. Una e haotică, cealalta sângeroasă.","Мне нравится твой настрой! У меня есть два неприятных дела, которыми я не хочу заниматься сам. Одно грязное, а другое кровавое.",,"Seni şimdiden sevdim. Kendi başıma yapmak istemediğim iki işim var. Biri pis, diğeri kanlı." -Call me the cleaner,TXT_RPLY0_SCRIPT02_D54576_CALLM,〃,,,Říkej mi pan uklízeč.,Kald mig rengøringsmanden.,Nennen Sie mich den Säuberer,,Purigado estas mia specialo.,Limpiar es mi especialidad.,,Olen siivoojasi,Appelez-moi le nettoyeur.,Hívj csak takarítónak.,Risolvere problemi è la mia specialità,まだ手は汚したくない,청소부라 불러줘.,Noem me de schoonmaakster,Kall meg renholderen.,Nazywaj mnie czyścicielem.,Pode me chamar de faxineiro,,Spune-mi curățătorul,Я — лучший чистильщик!,,Bana temizlikçi de. -I'm not squeamish,TXT_RPLY1_SCRIPT02_D54576_IMNOT,〃,,,Mám silný žaludek.,Jeg er ikke squeamish,Ich bin nicht zimperlich.,,Sango estas nenio.,La sangre no es nada.,,En ole heikkohermoinen,J'ai pas peur de me tacher les mains.,Nem vagyok finnyás,Non mi impressiono facilmente,汚れ仕事でも構わない,나는 비위가 약하지 않아.,Ik ben niet katholiek.,Jeg er ikke pysete,Nie jestem wybredny.,Não sou muito escrupuloso,,Nu sunt mofturos,Я не боюсь крови.,,Ben alıngan değilim. +","먼저 오더가 수천 명을 죽여놓고, 이젠 힘 좋은 시민들을 불러서 생각지도 않은 시험을 하라고 시키는구먼. 그놈들이 나한테 바라는 게 뭔지 전혀 모르겠네. 넌 원하는 게 뭐야?","Eerst slachten ze duizenden mensen af, nu willen ze alle valide boeren voor ongespecificeerde 'tests'. Hoe verwacht de Orde dat ik de vrede bewaar? Wat wil je verdomme?","Først slakter de tusenvis, og nå vil de ha alle arbeidsføre bønder til uspesifiserte ""tester"". Hvordan forventer ordenen at jeg skal bevare freden? Hva i helvete vil du ha?","Najpierw mordują tysiące, a teraz chcą wszystkich krzepkich chłopów do nieokreślonych ""testów"". Jak Zakon oczekuje ode mnie abym utrzymywał pokój? Czego chcesz u diabła?","Primeiro eles massacram milhares, agora querem que todos os plebeus saudáveis façam ""provas"" não especificadas. Como que a Ordem quer que eu mantenha a paz? Que diabos você quer?",,"Mai întâi măcelăresc cu miile, apoi vor toți sărmanii capabili de muncă pentru 'teste' nespecificate. Cum se așteaptă Ordinul să mențin pacea? Ce naiba vrei?","Сначала они убивают людей тысячами, а теперь им нужны все пригодные рабочие для каких-то «экспериментов»! И Орден ещё хочет, чтобы я поддерживал мир? Какого чёрта тебе нужно?",,"Först slaktar de tusentals, nu vill de ha alla dugliga bönder för ospecificerade ""tester"". Hur förväntar sig orden att jag ska kunna upprätthålla freden? Vad i helvete vill ni?","Önce binlercesini katlettiler, şimdi de tüm sağlıklı köylüleri belirsiz 'testler' için istiyorlar. Tarikat benden barışı korumamı nasıl bekler? Ne halt istiyorsun?" +"A prison pass, let's deal.",TXT_RPLY0_SCRIPT02_D53060_APRIS,〃,,,"Propustku do vězení, udělejme dohodu.","Et fængselskort, lad os lave en aftale.",Ein Gefängnispass. Lassen Sie uns verhandeln.,,Malliberejan enirpermeson. Ni intertraktu.,Un pase a la prisión. Negociemos.,,Vankilan pääsyluvan; hierotaan diili.,Un passe de la prison. Faisons affaires.,Egy börtön belépő. Üzleteljünk.,"Un pass per la prigione, trattiamo.",刑務所の許可証だ、取引をしよう。,감옥 통행증만 있으면 돼.,"Een gevangenispasje, laten we dealen.","Et fengselspass, la oss gjøre en avtale.","Przepustkę do więzienia, ponegocjujmy.","Um passe da prisão, vamos negociar.",,O legitimație pentru închisoare. Să facem un târg.,Пропуск в тюрьму. Заключим сделку.,,"Ett fängelsepass, låt oss göra upp.","Bir hapishane izni, anlaşalım." +"I like you already. I have two chores that I don't want to do myself. One is messy, the other bloody.",TXT_DLG_SCRIPT02_D54576_ILIKE,〃,,,"Už teď se mi líbíš. Mám dvě prácičky, které nechci dělat sám. Jedna je špinavá, druhá je krvavá.","Jeg kan allerede godt lide dig. Jeg har to pligter, som jeg ikke selv vil gøre. Den ene er rodet, den anden er blodig.","Du gefällst mir bereits. Ich habe zwei lästige Angelegenheiten, um die ich mich nicht selber kümmern möchte. Die eine davon ist dreckig, die andere blutig.",,"Mi jam ŝatas vin. Estas du farotaĵoj, kiujn mi mem ne volas fari: unu estas malpura kaj la alia estas sanga.",Ya me caes bien. Hay dos tareas que no quiero hacer por mi cuenta: una es sucia y la otra sangrienta.,,"Minähän pidän sinusta. Minulla olisi kyllä pari askaretta, joita en itse haluaisi tehdä. Yksi niistä on sotkuinen, toinen hurmeinen.","Vous me plaisez déjà. J'ai deux corvées que je n'ai pas envie de faire. Une est.. Sale, l'autre est sanglante.","Kedvellek már most. Van két feladatom, amit nem akarok magam végezni. Az egyik a koszos, a másik a véres.","Già mi piaci. Ho due faccende da sbrigare che non voglio fare di persona. Una è un po' complicata, e l'altra da risolvere col sangue.","いいだろう。仕事は二つあるのだが +一つは面倒で、もう一つは血を見ることになる。",이제야 말길이 가네. 지금 너에게 맡을 시험이 두 가지 있거든. 더러운 거랑... 잔인한 거.,"Ik vind je nu al leuk. Ik heb twee taken die ik zelf niet wil doen. De ene is rommelig, de andere bloedig.","Jeg liker deg allerede. Jeg har to plikter jeg ikke vil gjøre selv. Det ene er rotete, det andre blodig.","Już cię lubię. Mam dwa zadania, których sam nie chcę wykonać. Jedno jest brudne, a drugie krwawe.","Estou gostando de você. Tenho mais duas tarefas chatas que eu particularmente não estou a fim de fazer. Uma é suja, a outra sangrenta.",,"Deja îmi placi. Am două treburi nasoale pe care nu vreau să le fac eu însumi. Una e haotică, cealalta sângeroasă.","Мне нравится твой настрой! У меня есть два неприятных дела, которыми я не хочу заниматься сам. Одно грязное, а другое кровавое.",,"Jag gillar dig redan. Jag har två sysslor som jag inte vill göra själv. Den ena är smutsig, den andra är blodig.","Seni şimdiden sevdim. Kendi başıma yapmak istemediğim iki işim var. Biri pis, diğeri kanlı." +Call me the cleaner,TXT_RPLY0_SCRIPT02_D54576_CALLM,〃,,,Říkej mi pan uklízeč.,Kald mig rengøringsmanden.,Nennen Sie mich den Säuberer,,Purigado estas mia specialo.,Limpiar es mi especialidad.,,Olen siivoojasi,Appelez-moi le nettoyeur.,Hívj csak takarítónak.,Risolvere problemi è la mia specialità,まだ手は汚したくない,청소부라 불러줘.,Noem me de schoonmaakster,Kall meg renholderen.,Nazywaj mnie czyścicielem.,Pode me chamar de faxineiro,,Spune-mi curățătorul,Я — лучший чистильщик!,,Kalla mig städaren.,Bana temizlikçi de. +I'm not squeamish,TXT_RPLY1_SCRIPT02_D54576_IMNOT,〃,,,Mám silný žaludek.,Jeg er ikke squeamish,Ich bin nicht zimperlich.,,Sango estas nenio.,La sangre no es nada.,,En ole heikkohermoinen,J'ai pas peur de me tacher les mains.,Nem vagyok finnyás,Non mi impressiono facilmente,汚れ仕事でも構わない,나는 비위가 약하지 않아.,Ik ben niet katholiek.,Jeg er ikke pysete,Nie jestem wybredny.,Não sou muito escrupuloso,,Nu sunt mofturos,Я не боюсь крови.,,Jag är inte känslig.,Ben alıngan değilim. One of my minions is stealing power with a tap on the mains somewhere. Find it and truncate his supply and I'll provide you with what you want. Bring me something as a token.,TXT_DLG_SCRIPT02_D56092_ONEOF,"〃 -(""messy"" chore)",,,"Jeden z mých poddaných stáčedlem někde z hlavního vedení krade energii. Najdi jej a odřízni dotyčného od zásoby a já ti dám, co chceš. Přines mi něco jako důkaz.","En af mine håndlangere stjæler strøm med en vandhane et sted. Find den og afbryd hans forsyning, så skal jeg give dig, hvad du vil have. Bring mig noget som et symbol.","Einer meiner Untertanen zapft irgendwo Strom ab. Finde die Anzapfung und kappe sie. Falls du Erfolg hast, kriegst du was du brauchst. Aber bring mir einen Beweis mit!",,"Unu el miaj sbiroj metis konektilon ien por ŝteli energion de la elektriza sistemo. Ĝin trovu kaj detruu, kaj mi donos al vi tion, kion vi petis. Alportu pruvon kiam vi finos.","Uno de mis secuaces puso en algún lado una toma en la red eléctrica para robar energía. Encuéntralo, trunca su suministro y te daré lo que pides. Tráeme algo como prueba una vez que termines.","Uno de mis secuaces puso en algún lado una toma en la red eléctrica para robar energía. Encuéntralo, destruye su suministro y te voy a dar lo que pides. Tráeme algo como prueba una vez que termines.","Yksi alamaisistani varastaa verkkovirtaa jossakin sijaitsevalla salaisella kytkennällä. Löydä se ja katkaise hänen jakelunsa, niin annan sinulle haluamasi. Tuo minulle jotain todisteeksi.",Un de mes larbins pompe de l'électricité avec une connection pirate dans les transformateurs là haut. Trouvez là et coupez sa connection. Je vous donnerai ce que vous voulez. Ramenez moi une preuve.,"Az egyik alattvalóm áramot lop egy dugasszal a központi hálózatnál valahol. Találd meg, majd válaszd el az ellátását, és én adok neked amit akarsz. Hozz nekem valamit bizonyítékként","Uno dei miei tirapiedi sta rubando energia con un suo aggeggio attaccato alla rete elettrica da qualche parte. Trova questo aggeggio e staccalo dalla rete, e ti darò quello che desideri. Portami qualcosa come prova.","私の手下の一人が水力発電から電力を盗んで +(""messy"" chore)",,,"Jeden z mých poddaných stáčedlem někde z hlavního vedení krade energii. Najdi jej a odřízni dotyčného od zásoby a já ti dám, co chceš. Přines mi něco jako důkaz.","En af mine håndlangere stjæler strøm med en vandhane et sted. Find den og afbryd hans forsyning, så skal jeg give dig, hvad du vil have. Bring mig noget som et symbol.","Einer meiner Untertanen zapft irgendwo Strom ab. Finde die Anzapfung und kappe sie. Falls du Erfolg hast, kriegst du was du brauchst. Aber bring mir einen Beweis mit!",,"Unu el miaj sbiroj metis konektilon ien por ŝteli energion de la elektriza sistemo. Ĝin trovu kaj detruu, kaj mi donos al vi tion, kion vi petis. Alportu pruvon kiam vi finos.","Uno de mis secuaces puso en algún lado una toma en la red eléctrica para robar energía. Encuéntrala, trunca su suministro y te daré lo que pides. Tráeme algo como prueba una vez que termines.","Uno de mis secuaces puso en algún lado una toma en la red eléctrica para robar energía. Encuéntrala, destruye su suministro y te voy a dar lo que pides. Tráeme algo como prueba una vez que termines.","Yksi alamaisistani varastaa verkkovirtaa jossakin sijaitsevalla salaisella kytkennällä. Löydä se ja katkaise hänen jakelunsa, niin annan sinulle haluamasi. Tuo minulle jotain todisteeksi.",Un de mes larbins pompe de l'électricité avec une connection pirate dans les transformateurs là haut. Trouvez là et coupez sa connection. Je vous donnerai ce que vous voulez. Ramenez moi une preuve.,"Az egyik alattvalóm áramot lop egy dugasszal a központi hálózatnál valahol. Találd meg, majd válaszd el az ellátását, és én adok neked amit akarsz. Hozz nekem valamit bizonyítékként","Uno dei miei tirapiedi sta rubando energia con un suo aggeggio attaccato alla rete elettrica da qualche parte. Trova questo aggeggio e staccalo dalla rete, e ti darò quello che desideri. Portami qualcosa come prova.","私の手下の一人が水力発電から電力を盗んで いるらしい。それを見つけ供給を切って くれれば君の望む物をやろう。 -その象徴となるのも持ってきてほしい。",내 부하 중 한 명이 어딘가에 있는 동력선에 추출기를 꽂아 동력을 훔치고 있다는군. 그것을 찾아내서 그의 공급을 자르면 네가 원하는 것을 제공하지. 증거가 될만한 그것을 가져와.,Een van mijn acolieten steelt stroom met een kraan op het lichtnet ergens. Zoek het en snoei zijn aansluiting in en ik zal je voorzien van wat je wilt. Breng me iets als teken.,"En av håndlangerne mine stjeler strøm med en kran på strømnettet et sted. Finn den og kutt forsyningen hans, så gir jeg deg det du vil ha. Gi meg noe som et symbol.","Jeden z moich sług kradnie gdzieś moc w przewodach za pomocą przełącznika. Znajdź go i odetnij jego dostawę mocy, a dam ci co chcesz. Przynieś mi coś jako dowód.",Um dos meus capangas está roubando energia por uma ligação clandestina em algum lugar. Encontre e corte essa ligação e conseguirei o que você quer. Traga algo como prova.,,"Unul dintre slujitorii mei fură electricitate cu robinetul pe undeva. Află cum face asta, distruge-i proviziile, și îți voi oferi ceea ce vrei. Adu-mi și ceva ca dovadă.","Кто-то из моих подчинённых отводит энергию откуда-то из питающей сети. Найди и отключи эту установку — тогда получишь то, за чем пришёл. И принеси мне что-нибудь в качестве доказательства.",,"Kölelerimden biri bir yerdeki şebekeden güç çalıyor. Onu bul ve kaynağını kes, ben de sana istediğini vereyim. Bana simge olarak bir şey getir." +その象徴となるのも持ってきてほしい。",내 부하 중 한 명이 어딘가에 있는 동력선에 추출기를 꽂아 동력을 훔치고 있다는군. 그것을 찾아내서 그의 공급을 자르면 네가 원하는 것을 제공하지. 증거가 될만한 그것을 가져와.,Een van mijn acolieten steelt stroom met een kraan op het lichtnet ergens. Zoek het en snoei zijn aansluiting in en ik zal je voorzien van wat je wilt. Breng me iets als teken.,"En av håndlangerne mine stjeler strøm med en kran på strømnettet et sted. Finn den og kutt forsyningen hans, så gir jeg deg det du vil ha. Gi meg noe som et symbol.","Jeden z moich sług kradnie gdzieś moc w przewodach za pomocą przełącznika. Znajdź go i odetnij jego dostawę mocy, a dam ci co chcesz. Przynieś mi coś jako dowód.",Um dos meus capangas está roubando energia por uma ligação clandestina em algum lugar. Encontre e corte essa ligação e conseguirei o que você quer. Traga algo como prova.,,"Unul dintre slujitorii mei fură electricitate cu robinetul pe undeva. Află cum face asta, distruge-i proviziile, și îți voi oferi ceea ce vrei. Adu-mi și ceva ca dovadă.","Кто-то из моих подчинённых отводит энергию откуда-то из питающей сети. Найди и отключи эту установку — тогда получишь то, за чем пришёл. И принеси мне что-нибудь в качестве доказательства.",,En av mina hantlangare stjäl ström med en kran på elnätet någonstans. Hitta den och avbryta hans leverans så ska jag förse dig med det du vill ha. Ta med dig något som ett tecken.,"Kölelerimden biri bir yerdeki şebekeden güç çalıyor. Onu bul ve kaynağını kes, ben de sana istediğini vereyim. Bana simge olarak bir şey getir." Where do I find this tap?,TXT_RPLY0_SCRIPT02_D56092_WHERE,"〃 -(〃)",,,Kde najdu to stáčedlo?,Hvor kan jeg finde denne vandhane?,Wo finde ich die Anzapfung?,,Kie estas la konektilo?,¿Dónde está la toma?,,Mistä tämä kytkentä löytyy?,Où est-ce que je trouve cette connection?,Hol találom ezt a dugaszt?,E dove lo trovo questo aggeggio?,どうやって突き止めたらいい?,그 추출기는 어디에 찾을 수 있지?,Waar vind ik deze kraan?,Hvor finner jeg denne kranen?,Gdzie znajdę ten przełącznik?,Onde encontro essa ligação clandestina?,,Unde-i găsesc robinetul?,Где может находиться эта установка?,,Bu musluğu nerede bulabilirim? +(〃)",,,Kde najdu to stáčedlo?,Hvor kan jeg finde denne vandhane?,Wo finde ich die Anzapfung?,,Kie estas la konektilo?,¿Dónde está la toma?,,Mistä tämä kytkentä löytyy?,Où est-ce que je trouve cette connection?,Hol találom ezt a dugaszt?,E dove lo trovo questo aggeggio?,どうやって突き止めたらいい?,그 추출기는 어디에 찾을 수 있지?,Waar vind ik deze kraan?,Hvor finner jeg denne kranen?,Gdzie znajdę ten przełącznik?,Onde encontro essa ligação clandestina?,,Unde-i găsesc robinetul?,Где может находиться эта установка?,,Var hittar jag den här kranen?,Bu musluğu nerede bulabilirim? "If I knew, it wouldn't be a chore now would it? Use your charm, but shut off his supply.",TXT_DLG_SCRIPT02_D57608_IFIKN,"〃 (〃)",,,"Kdybych věděl, nebyla by to práce, ne? Použij svůj šarm, ale vypni dotyčnému přívod.","Hvis jeg vidste det, ville det ikke være så besværligt, vel? Brug din charme, men luk for hans forsyning.","Wenn ich das wüsste, wäre das keine lästige Angelegenheit, nicht wahr? Benutze deinen Charme, aber schalte seine Versorgung aus.",,"Se mi scius tion, mi ne petus ĉi tion al vi, ĉu ne? Uzu vian ĉarmon, sed interrompu lian provizadon.","Si lo supiera no te lo estaría pidiendo, ¿no? Usa tu encanto, pero corta su suministro. ",,"Jos tietäisin sen, eihän se silloin enää olisi askare, eihän? Käytä sulokkuutasi, mutta katkaise hänen sähkönsä.","Si je le savais, ce ne serait pas une corvée, non? Utiliser votre charme si il le faut, mais coupez cette connection.","Ha tudnám, nem lenne ez a feladat már. Használd a bájodat, de állítsd le az ellátást.","E se lo sapessi, non sarebbe mica una faccenda scomoda! Usa il tuo fascino, ma metti fine al suo schema.","私が知っていたら、こんな雑用はさせない だろう?誰かをでっちあげるか、 聞き込みでもするんだ。","만약 내가 그 위치를 알았다면 지루한 심부름이 됐겠지, 그렇지 않아? 네 머리를 써! 그리고 그 추출기를 찾아. - \cy배부른 돼지 같은 녀석. 난 이 추출기에 대해서 아무것도 몰라. 너무 급하게 하지 말자.","Als ik het wist, zou het nu geen karwei zijn, toch? Gebruik je charme, maar schakel zijn voorraad uit.","Hvis jeg visste det, ville det ikke være et ork, ville det vel? Bruk sjarmen din, men steng av tilførselen hans.","Gdybym wiedział, to nie byłby problem, prawda? Wykorzystaj swój spryt, ale pamiętaj by odciąć mu dostawę.","Se eu soubesse, não seria uma tarefa chata, não é mesmo? Use seu charme, mas corte essa ligação.",,"Dacă știam, n-ar mai fi fost o corvoadă, este? Folosește-ți farmecul, dar distruge-i proviziile.","Если бы я знал, то справился бы с этим сам, как считаешь? Пусти в ход свои таланты, но прекрати утечку энергии.",,"Eğer bilseydim, bu bir angarya olmazdı, değil mi? Cazibeni kullan ama onun kaynağını kapat." + \cy배부른 돼지 같은 녀석. 난 이 추출기에 대해서 아무것도 몰라. 너무 급하게 하지 말자.","Als ik het wist, zou het nu geen karwei zijn, toch? Gebruik je charme, maar schakel zijn voorraad uit.","Hvis jeg visste det, ville det ikke være et ork, ville det vel? Bruk sjarmen din, men steng av tilførselen hans.","Gdybym wiedział, to nie byłby problem, prawda? Wykorzystaj swój spryt, ale pamiętaj by odciąć mu dostawę.","Se eu soubesse, não seria uma tarefa chata, não é mesmo? Use seu charme, mas corte essa ligação.",,"Dacă știam, n-ar mai fi fost o corvoadă, este? Folosește-ți farmecul, dar distruge-i proviziile.","Если бы я знал, то справился бы с этим сам, как считаешь? Пусти в ход свои таланты, но прекрати утечку энергии.",,"Om jag visste det skulle det inte vara så jobbigt, eller hur? Använd din charm, men stäng av hans förråd.","Eğer bilseydim, bu bir angarya olmazdı, değil mi? Cazibeni kullan ama onun kaynağını kapat." "Tell you what, there's a lying sack named Derwin who has been selling children to the Order. I won't tolerate that kind of depravity. Not without my cut. Derwin works in the warehouse. Kill him and bring me his, ear, and I'll see what I can do.",TXT_DLG_SCRIPT02_D59124_TELLY,"〃 -(""bloody"" chore)",,,"Mám problém s pupkáčem jménem Derwin, který Řádu prodává děti. Takovou odpornost nemůžu tolerovat, ne bez mého podílu. Derwin pracuje ve skladišti. Zab ho a přines mi jeho ucho a já uvidím, co pro tebe budu moci udělat.","Ved du hvad, der er en løgnagtig sæk ved navn Derwin, der har solgt børn til Ordenen. Jeg vil ikke tolerere den slags fordærv. Ikke uden min andel. Derwin arbejder i lageret. Dræb ham og giv mig hans øre, så skal jeg se, hvad jeg kan gøre.","Ich sag dir was, da gibt es so einen lügenden Kerl namens Derwin, der Kinder an den Orden verkauft hat. Ich kann so eine Verdorbenheit nicht tolerieren. Nicht ohne meinen Anteil. Derwin arbeitet im Lagerhaus. Töte ihn und bring mir sein Ohr und ich werde sehen was ich tun kann.",,"Aŭskultu ĉi tion. Estas fimensogulo nomata Derwin, kiu kutimas vendi infanojn al La Ordono, kaj mi ne toleros tian perversecon: ne se li ne donos parton de la gajnoj. Derwin laboras en la magazeno. Mortigu lin, alportu lian orelon kaj mi vidos tion, kion mi povas fari.","A ver, te cuento. Hay un sucio mentiroso llamado Derwin que ha estado vendiendo niños a La Orden, y no toleraré ese tipo de perversión: no si no me da mi parte. Derwin trabaja en el almacén. Mátalo, tráeme su oreja y veré qué puedo hacer.","A ver, te cuento. Hay un sucio mentiroso llamado Derwin que ha estado vendiendo niños a La Orden, y no puedo tolerar ese tipo de perversión: no si no me da mi parte. Derwin trabaja en el almacén. Mátalo, tráeme su oreja y voy a ver qué puedo hacer.","Annapa, kun kerron valepukista nimeltä Derwin, joka myy lapsia Veljeskunnalle. En voi suvaita sellaista turmeltuneisuutta... jossa en pääse itse osingoille. Derwin työskentelee varastolla. Tapa hänet ja tuo minulle hänen... korvansa, ja katson sitten, jos voin olla avuksi.","Eh bien, il y a une raclure appelée Derwin qui vend des enfants à l'Ordre. Je ne tolère pas ce type d'atrocité, du moins pas sans ma part des frais. Derwin travaille dans l'entrepôt. Tuez-le et ramenez moi son oreille, je verrais ce que je peux faire pour vous.","Na figyusz, van egy Derwin nevű hazug genya, aki gyerekeket árul a Rend számára. Nem tolerálom az ilyen romlottságot. Legalábbis a részesedésem nélkül. Derwin a raktárban dolgozik. Intézd el, és hozdd el a fülét, meglátom mit tehetek érted.","Senti questa, ci sta questo sporco bugiardo chiamato Derwin che sta vendendo bambini all'Ordine. Non tollero queste azioni depravate. Non senza che io riceva una fetta dei soldi. Derwin lavora al magazzino. Fallo fuori e portami un suo, orecchio, e vedrò cosa posso fare.","教えよう、ダーウィンとかいう恥知らずが +(""bloody"" chore)",,,"Mám problém s pupkáčem jménem Derwin, který Řádu prodává děti. Takovou odpornost nemůžu tolerovat, ne bez mého podílu. Derwin pracuje ve skladišti. Zab ho a přines mi jeho ucho a já uvidím, co pro tebe budu moci udělat.","Ved du hvad, der er en løgnagtig sæk ved navn Derwin, der har solgt børn til Ordenen. Jeg vil ikke tolerere den slags fordærv. Ikke uden min andel. Derwin arbejder i lageret. Dræb ham og giv mig hans øre, så skal jeg se, hvad jeg kan gøre.","Ich sag dir was, da gibt es so einen lügenden Kerl namens Derwin, der Kinder an den Orden verkauft hat. Ich kann so eine Verdorbenheit nicht tolerieren. Nicht ohne meinen Anteil. Derwin arbeitet im Lagerhaus. Töte ihn und bring mir sein Ohr und ich werde sehen was ich tun kann.",,"Aŭskultu ĉi tion. Estas fimensogulo nomata Derwin, kiu kutimas vendi infanojn al La Ordeno, kaj mi ne toleros tian perversecon: ne se li ne donos parton de la gajnoj. Derwin laboras en la magazeno. Mortigu lin, alportu lian orelon kaj mi vidos tion, kion mi povas fari.","A ver, te cuento. Hay un sucio mentiroso llamado Derwin que ha estado vendiendo niños a La Orden, y no toleraré ese tipo de perversión: no si no me da mi parte. Derwin trabaja en el almacén. Mátalo, tráeme su oreja y veré qué puedo hacer.","A ver, te cuento. Hay un sucio mentiroso llamado Derwin que ha estado vendiendo niños a La Orden, y no puedo tolerar ese tipo de perversión: no si no me da mi parte. Derwin trabaja en el almacén. Mátalo, tráeme su oreja y voy a ver qué puedo hacer.","Annapa, kun kerron valepukista nimeltä Derwin, joka myy lapsia Veljeskunnalle. En voi suvaita sellaista turmeltuneisuutta... jossa en pääse itse osingoille. Derwin työskentelee varastolla. Tapa hänet ja tuo minulle hänen... korvansa, ja katson sitten, jos voin olla avuksi.","Eh bien, il y a une raclure appelée Derwin qui vend des enfants à l'Ordre. Je ne tolère pas ce type d'atrocité, du moins pas sans ma part des frais. Derwin travaille dans l'entrepôt. Tuez-le et ramenez moi son oreille, je verrais ce que je peux faire pour vous.","Na figyusz, van egy Derwin nevű hazug genya, aki gyerekeket árul a Rend számára. Nem tolerálom az ilyen romlottságot. Legalábbis a részesedésem nélkül. Derwin a raktárban dolgozik. Intézd el, és hozdd el a fülét, meglátom mit tehetek érted.","Senti questa, ci sta questo sporco bugiardo chiamato Derwin che sta vendendo bambini all'Ordine. Non tollero queste azioni depravate. Non senza che io riceva una fetta dei soldi. Derwin lavora al magazzino. Fallo fuori e portami un suo, orecchio, e vedrò cosa posso fare.","教えよう、ダーウィンとかいう恥知らずが 子供をオーダーへ売りつけているようだ。 私に分け前無しに、そんな恥ずべき行為を 許すわけには行かん。ダーウィンは倉庫で 勤務している。殺った証拠として奴の、耳を、 -持ってきたまえ。","그렇담, 더윈이라는 뚱땡이가 지금 아이들을 붙잡아 오더에 팔아넘기는 짓을 일삼고 있어. 너무나도 괘씸해... 내게 이득이 전혀 없으니. 더윈은 발전소 주변 창고에서 일하고 있어. 그를 죽이고, 그의, 귀를 뜯어서 가져와. 그럼 거래를 진행하지.","Weet je wat, er is een leugenachtige zak genaamd Derwin die kinderen aan de Orde heeft verkocht. Dat soort verdorvenheid tolereer ik niet. Niet zonder mijn deel. Derwin werkt in het magazijn. Dood hem en breng me zijn oor, en ik zal zien wat ik kan doen.","Det er en løgnhals ved navn Derwin som har solgt barn til Ordenen. Jeg tolererer ikke den slags fordervelse. Ikke uten min andel. Derwin jobber på lageret. Drep ham og gi meg hans øre, så skal jeg se hva jeg kan gjøre.","Słuchaj, jest tu pewien worek kłamstw, który nazywa się Derwin. Sprzedaje on Zakonowi dzieci. Nie będę tolerował takiego zepsucia. Nie bez moich udziałów. Derwin pracuje w magazynie. Zabij go i przynieś mi jego... ucho, a zobaczę co da się zrobić.","É o seguinte, tem um mentiroso desgraçado chamado Derwin que anda vendendo crianças para a Ordem. Não vou tolerar esse tipo de depravação. Não sem a minha parte. Derwin trabalha no depósito. Mate-o e traga a...orelha dele e verei o que posso fazer.",,"Să-ți zic ceva, un gunoi mincinos pe nume Derwin vinde copii Ordinului. Nu tolerez ceva atât de depravat. Nu fără să primesc și eu ceva. Derwin lucrează în depozit. Omoară-l și adu-mi... urechea lui, și-o să văd ce pot face.","Лживый мешок дерьма по имени Дервин продаёт Ордену детей. Я не терплю такой безнравственности, особенно когда меня не берут в долю. Дервин работает в складе. Убей его и принеси мне его ухо, и я посмотрю, чем можно помочь.",,"Bak ne diyeceğim, Tarikat'a çocuk satan Derwin adında yalancı bir çuval var. Bu tür bir ahlaksızlığa müsamaha göstermeyeceğim. Benim payım olmadan olmaz. Derwin depoda çalışıyor. Onu öldürüp kulağını bana getir, ne yapabileceğime bakarım." +持ってきたまえ。","그렇담, 더윈이라는 뚱땡이가 지금 아이들을 붙잡아 오더에 팔아넘기는 짓을 일삼고 있어. 너무나도 괘씸해... 내게 이득이 전혀 없으니. 더윈은 발전소 주변 창고에서 일하고 있어. 그를 죽이고, 그의, 귀를 뜯어서 가져와. 그럼 거래를 진행하지.","Weet je wat, er is een leugenachtige zak genaamd Derwin die kinderen aan de Orde heeft verkocht. Dat soort verdorvenheid tolereer ik niet. Niet zonder mijn deel. Derwin werkt in het magazijn. Dood hem en breng me zijn oor, en ik zal zien wat ik kan doen.","Det er en løgnhals ved navn Derwin som har solgt barn til Ordenen. Jeg tolererer ikke den slags fordervelse. Ikke uten min andel. Derwin jobber på lageret. Drep ham og gi meg hans øre, så skal jeg se hva jeg kan gjøre.","Słuchaj, jest tu pewien worek kłamstw, który nazywa się Derwin. Sprzedaje on Zakonowi dzieci. Nie będę tolerował takiego zepsucia. Nie bez moich udziałów. Derwin pracuje w magazynie. Zabij go i przynieś mi jego... ucho, a zobaczę co da się zrobić.","É o seguinte, tem um mentiroso desgraçado chamado Derwin que anda vendendo crianças para a Ordem. Não vou tolerar esse tipo de depravação. Não sem a minha parte. Derwin trabalha no depósito. Mate-o e traga a...orelha dele e verei o que posso fazer.",,"Să-ți zic ceva, un gunoi mincinos pe nume Derwin vinde copii Ordinului. Nu tolerez ceva atât de depravat. Nu fără să primesc și eu ceva. Derwin lucrează în depozit. Omoară-l și adu-mi... urechea lui, și-o să văd ce pot face.","Лживый мешок дерьма по имени Дервин продаёт Ордену детей. Я не терплю такой безнравственности, особенно когда меня не берут в долю. Дервин работает в складе. Убей его и принеси мне его ухо, и я посмотрю, чем можно помочь.",,"Vet du vad, det finns en ljugande säck vid namn Derwin som har sålt barn till Orden. Jag tolererar inte den sortens fördärv. Inte utan min andel. Derwin arbetar i lagret. Döda honom och ge mig hans öra så ska jag se vad jag kan göra.","Bak ne diyeceğim, Tarikat'a çocuk satan Derwin adında yalancı bir çuval var. Bu tür bir ahlaksızlığa müsamaha göstermeyeceğim. Benim payım olmadan olmaz. Derwin depoda çalışıyor. Onu öldürüp kulağını bana getir, ne yapabileceğime bakarım." How do I get in?,TXT_RPLY0_SCRIPT02_D59124_HOWDO,"〃 -(〃)",,,Jak se dostanu dovnitř?,Hvordan kommer jeg ind?,Wie komme ich hinein?,,Kiel mi eniru tien?,¿Cómo entro?,,Miten pääsen sisään?,Comment j'y rentre?,Hogy jutok be?,Come ci arrivo?,どうすれば入れる?,어떻게 들어가지?,Hoe kom ik binnen?,Hvordan kommer jeg inn?,Jak się tam dostanę?,Como faço para entrar?,,Cum ajung înăuntru?,Как мне туда попасть?,,İçeri nasıl gireceğim? +(〃)",,,Jak se dostanu dovnitř?,Hvordan kommer jeg ind?,Wie komme ich hinein?,,Kiel mi eniru tien?,¿Cómo entro?,,Miten pääsen sisään?,Comment j'y rentre?,Hogy jutok be?,Come ci arrivo?,どうすれば入れる?,어떻게 들어가지?,Hoe kom ik binnen?,Hvordan kommer jeg inn?,Jak się tam dostanę?,Como faço para entrar?,,Cum ajung înăuntru?,Как мне туда попасть?,,Hur kommer jag in?,İçeri nasıl gireceğim? "This key will get you into the power station. On second thought, cut off the ear and then kill him. Much better.",TXT_DLG_SCRIPT02_D60640_THISK,"〃 -(〃)",,,"Tímhle klíčem se dostaneš do elektrárny. Víš ty co, nejprve mu uřízni ucho, až pak ho zabij. Mnohem lepší.","Med denne nøgle kan du komme ind i kraftværket. Ved nærmere eftertanke, skær øret af og dræb ham så. Det er meget bedre.","Dieser Schlüssel wird dich ins Kraftwerk bringen. Andererseits, schneide ihm erst das Ohr ab und dann töte ihn. Viel besser.",,"Jen ŝlosilo de la elektra centralo. Repensante pri tio, fortranĉu lian orelon kaj tiam mortigu lin. Multe plibone.","Aquí tengo una llave de la central eléctrica. Pensándolo bien, córtale la oreja y luego mátalo. Mucho mejor.",,"Tällä avaimella pääset voimalaitokseen. Nyt, kun tarkemmin ajattelen, niin sivalla ensin hänen korvansa, ja sitten tapa hänet. Paljon parempi.","Cette clé vous laissera entrer dans la centrale électrique. Maintenant que j'y pense, coupez-lui l'oreille, puis tuez-le. Ca me plaît plus comme ça.","Ezzel a kulccsal bejuthatsz az erőműbe. Jobban átgondolva, vádg le a fülét és öld meg. Sokkal jobb. ","Questa chiave ti farà entrare nella centrale energetica. Ora che ci penso, prima tagliagli l'orecchio, e poi uccidilo. Molto meglio.","この鍵で発電所に入るんだ。出来れば、 +(〃)",,,"Tímhle klíčem se dostaneš do elektrárny. Víš ty co, nejprve mu uřízni ucho, až pak ho zabij. Mnohem lepší.","Med denne nøgle kan du komme ind i kraftværket. Ved nærmere eftertanke, skær øret af og dræb ham så. Det er meget bedre.","Dieser Schlüssel wird dich ins Kraftwerk bringen. Andererseits, schneide ihm erst das Ohr ab und dann töte ihn. Viel besser.",,"Jen ŝlosilo de la elektrocentralo. Repensante pri tio, fortranĉu lian orelon kaj tiam mortigu lin. Multe plibone.","Aquí tengo una llave de la central eléctrica. Pensándolo bien, córtale la oreja y luego mátalo. Mucho mejor.",,"Tällä avaimella pääset voimalaitokseen. Nyt, kun tarkemmin ajattelen, niin sivalla ensin hänen korvansa, ja sitten tapa hänet. Paljon parempi.","Cette clé vous laissera entrer dans la centrale électrique. Maintenant que j'y pense, coupez-lui l'oreille, puis tuez-le. Ca me plaît plus comme ça.","Ezzel a kulccsal bejuthatsz az erőműbe. Jobban átgondolva, vádg le a fülét és öld meg. Sokkal jobb. ","Questa chiave ti farà entrare nella centrale energetica. Ora che ci penso, prima tagliagli l'orecchio, e poi uccidilo. Molto meglio.","この鍵で発電所に入るんだ。出来れば、 先に耳を切り落としてから殺してくれ。 -その方が良い。","이 열쇠만 있으면 발전소에 들어갈 수 있을 거야. 그리고 다시 생각해보니, 그 자식을 죽이기 전에, 먼저 귀를 뜯어. 그럼 더 나을 거 같군.","Met deze sleutel kom je in de centrale. Bij nader inzien, snij je het oor eraf en vermoord je hem. Veel beter.","Denne nøkkelen får deg inn i kraftstasjonen. Ved nærmere ettertanke, skjær av øret og drep ham. Mye bedre.","Ten klucz pozwoli ci wejść do elektrowni. Z drugiej strony, najpierw odetnij mu ucho, a potem go zabij. Tak będzie lepiej.","Esta chave vai te ajudar a entrar na usina de energia. Pensando melhor, corte fora a orelha e depois mate ele. Muito melhor.",,"Cheia asta îți va oferi acces la stația electrică. Dacă mă gândesc mai bine, mai întâi taie-i urechea și abia apoi omoară-l. Mult mai bine.","С этим ключом ты пройдёшь на электростанцию. А, да, я тут подумал — сначала отрежь ему ухо, а затем убей. Так будет намного лучше.",,"Bu anahtar seni elektrik santraline sokacak. Bir daha düşündüm de, kulağını kes ve sonra onu öldür. Çok daha iyi olur." +その方が良い。","이 열쇠만 있으면 발전소에 들어갈 수 있을 거야. 그리고 다시 생각해보니, 그 자식을 죽이기 전에, 먼저 귀를 뜯어. 그럼 더 나을 거 같군.","Met deze sleutel kom je in de centrale. Bij nader inzien, snij je het oor eraf en vermoord je hem. Veel beter.","Denne nøkkelen får deg inn i kraftstasjonen. Ved nærmere ettertanke, skjær av øret og drep ham. Mye bedre.","Ten klucz pozwoli ci wejść do elektrowni. Z drugiej strony, najpierw odetnij mu ucho, a potem go zabij. Tak będzie lepiej.","Esta chave vai te ajudar a entrar na usina de energia. Pensando melhor, corte fora a orelha e depois mate ele. Muito melhor.",,"Cheia asta îți va oferi acces la stația electrică. Dacă mă gândesc mai bine, mai întâi taie-i urechea și abia apoi omoară-l. Mult mai bine.","С этим ключом ты пройдёшь на электростанцию. А, да, я тут подумал — сначала отрежь ему ухо, а затем убей. Так будет намного лучше.",,"Den här nyckeln tar dig in i kraftverket. Vid närmare eftertanke, skär av örat och döda honom sedan. Mycket bättre.","Bu anahtar seni elektrik santraline sokacak. Bir daha düşündüm de, kulağını kes ve sonra onu öldür. Çok daha iyi olur." "Oh, I just love souvenirs. Here, this will get you into the prison. Talk to Warden Montag. Whatever you do after that, I don't want to know.",TXT_DLG_SCRIPT02_D62156_OHIJU,"〃 (after completing ""messy"" chore)",,,"Ó, já prostě zbožňuju suvenýry. Tady, tohle tě dostane do vězení. Promluv si s dozorčím Montagem. Co máš v plánu dělat potom, to už vědět nechci.","Åh, jeg elsker souvenirs. Her, med den her kan du komme ind i fængslet. Tal med fængselsinspektør Montag. Hvad du end gør efter det, vil jeg ikke vide det.","Oh, ich liebe Souvenirs. Hier, damit kommst du in das Gefängnis. Sprich mit Direktor Montag. Was du danach machen musst, weiß ich nicht.",,"Ha, mi ŝategas memoraĵojn. Havu ĉi tion, kio ebligos al vi eniri la malliberejon. Parolu kun la provoso Montag. Tion ajn, kion vi faros poste, mi ne volas scii.","Ah, me encantan los recuerdos. Ten, con esto podrás entrar en la prisión. Habla con el carcelero Montag. Lo que hagas después de eso no quiero saberlo.","Ah, me encantan los recuerdos. Toma, con esto vas a poder entrar a la prisión. Habla con el carcelero Montag. Lo que hagas después de eso no quiero saberlo.","Minä siis niin rakastan matkamuistoja. Kas näin, pääset tällä vankilaan. Puhu vankilanjohtaja Montagin kanssa. Mitä teetkään sen jälkeen, en halua tietää.","Oh, j'adore les souvenirs. Voilà, ça vous laissera entrer dans la prison. Parlez au gardien Montag. Ce que vous faites après, je m'en fous complètement.","Oh, imádom az ajándékokat. Nesze, ezzel be fogsz tudni jutni a börtönbe. Beszélj Mondtag igazgatóval. Nem akarok tudni arról, mit teszel utána.","Ah, adoro i souvenir! Ecco qua, con questo potrai entrare nella prigione. Parla con Montag, il direttore del carcere. Quello che farai dopo, a me non interessa.","嬉しい手土産だ。では、これがあれば 刑務所に入れる。モンターグ所長と話すんだ。 -君がそこで何をしようが、私の管轄外だ。","오오, 난 기념품이 정말 좋아. 여기, 네가 원했던 감옥 통행증이야. 감옥으로 가서 몬탕 간수장에게 이야기해봐. 네가 어떤 짓을 저지르든, 그 후엔 절대로 알고 싶지 않아!","Oh, ik hou gewoon van souvenirs. Hier, dit zal je in de gevangenis brengen. Spreek met directeur Montag. Wat je daarna ook doet, ik wil het niet weten.","Jeg elsker suvenirer. Denne får deg inn i fengselet. Snakk med fengselsdirektør Montag. Uansett hva du gjør etter det, vil jeg ikke vite det.","Oh, po prostu kocham pamiątki. Masz, to pozwoli ci wejść do więzienia. Pogadaj z Naczelnikiem Montagiem. Nie chcę wiedzieć co potem zrobisz.","Ah, eu simplesmente adoro suvenires. Tome, isto vai te ajudar a entrar na prisão. Fale com o carcereiro, Montag. O que você for fazer depois não me interessa.",,"Oh, ce mai ador suvenirurile. Aici, asta îți va permite să ajungi în interiorul închisorii. Vorbește cu gardianul Montag. Ce faci după aceea, nu vreau să știu.","О, как я люблю сувениры! Вот твой пропуск в тюрьму. Обратись к тюремщику Монтагу, а что ты будешь делать потом, я и знать не желаю.",,"Hatıra eşyalarına bayılırım. İşte, bu seni hapishaneye sokacak. Müdür Montag ile konuş. Ondan sonra ne yaparsan yap, bilmek istemiyorum." +君がそこで何をしようが、私の管轄外だ。","오오, 난 기념품이 정말 좋아. 여기, 네가 원했던 감옥 통행증이야. 감옥으로 가서 몬탕 간수장에게 이야기해봐. 네가 어떤 짓을 저지르든, 그 후엔 절대로 알고 싶지 않아!","Oh, ik hou gewoon van souvenirs. Hier, dit zal je in de gevangenis brengen. Spreek met directeur Montag. Wat je daarna ook doet, ik wil het niet weten.","Jeg elsker suvenirer. Denne får deg inn i fengselet. Snakk med fengselsdirektør Montag. Uansett hva du gjør etter det, vil jeg ikke vite det.","Oh, po prostu kocham pamiątki. Masz, to pozwoli ci wejść do więzienia. Pogadaj z Naczelnikiem Montagiem. Nie chcę wiedzieć co potem zrobisz.","Ah, eu simplesmente adoro suvenires. Tome, isto vai te ajudar a entrar na prisão. Fale com o carcereiro, Montag. O que você for fazer depois não me interessa.",,"Oh, ce mai ador suvenirurile. Aici, asta îți va permite să ajungi în interiorul închisorii. Vorbește cu gardianul Montag. Ce faci după aceea, nu vreau să știu.","О, как я люблю сувениры! Вот твой пропуск в тюрьму. Обратись к тюремщику Монтагу, а что ты будешь делать потом, я и знать не желаю.",,"Jag älskar souvenirer. Här, den här tar dig in i fängelset. Prata med fängelsedirektör Montag. Vad du än gör efter det vill jag inte veta.","Hatıra eşyalarına bayılırım. İşte, bu seni hapishaneye sokacak. Müdür Montag ile konuş. Ondan sonra ne yaparsan yap, bilmek istemiyorum." Thanks.,TXT_RPLY0_SCRIPT02_D62156_THANK,"〃 -(〃)",,,Díky.,Jeg vil ikke vide det. Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,고마워.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Спасибо.,,Teşekkürler. -"Give you a hint. When I stop talking to you, you leave.",TXT_DLG_SCRIPT02_D63672_GIVEY,〃,,,"Dám ti radu: Když s tebou přestanu mluvit, znamená to odchod.","Jeg giver dig et hint. Når jeg holder op med at tale med dig, går du.","Hier mal ein Tipp. Wenn ich aufgehört habe mit dir zu reden, dann gehst du.",,"Jen konsilo: Kiam mi ĉesas paroli al vi, vi foriras.","Un consejo: Cuando dejo de hablarte, te vas.",,"Pienenä vinkkinä, että kun lakkaan puhumasta sinulle, sinä lähdet.","Petit conseil. Quand j'arrète de vous parler, vous sortez d'ici.","Csak egy tanács. Amikor már nem beszélek hozzád, húzz el.","Ti do un consiglio. Quando io smetto di parlare, tu vai via.",ヒントを出そう。話すのを止めたら去りたまえ。,"힌트를 하나 주지. 나랑 대화가 끝났으면, 넌 떠나는 거야.","Ik geef je een hint. Als ik niet meer met je praat, ga je weg.","Jeg skal gi deg et hint. Når jeg slutter å snakke med deg, drar du.",Dam ci wskazówkę. Jak przestanę mówić to wyjdź.,"Uma dica. Quando eu terminar de falar contigo, você vai embora.",,"Îți dau un sfat. Când termin de discutat cu tine, pleci.","Дам тебе подсказку: когда я закончу говорить, ты уходишь.",,"Sana bir ipucu vereyim. Seninle konuşmayı bıraktığımda, gideceksin." +(〃)",,,Díky.,Jeg vil ikke vide det. Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,고마워.,Bedankt.,Takk skal du ha.,Dzięki.,Agradeço.,,Mulțumesc.,Спасибо.,,Jag vill inte veta. Tack.,Teşekkürler. +"Give you a hint. When I stop talking to you, you leave.",TXT_DLG_SCRIPT02_D63672_GIVEY,〃,,,"Dám ti radu: Když s tebou přestanu mluvit, znamená to odchod.","Jeg giver dig et hint. Når jeg holder op med at tale med dig, går du.","Hier mal ein Tipp. Wenn ich aufgehört habe mit dir zu reden, dann gehst du.",,"Jen konsilo: Kiam mi ĉesas paroli al vi, vi foriras.","Un consejo: Cuando dejo de hablarte, te vas.",,"Pienenä vinkkinä, että kun lakkaan puhumasta sinulle, sinä lähdet.","Petit conseil. Quand j'arrète de vous parler, vous sortez d'ici.","Csak egy tanács. Amikor már nem beszélek hozzád, húzz el.","Ti do un consiglio. Quando io smetto di parlare, tu vai via.",ヒントを出そう。話すのを止めたら去りたまえ。,"힌트를 하나 주지. 나랑 대화가 끝났으면, 넌 떠나는 거야.","Ik geef je een hint. Als ik niet meer met je praat, ga je weg.","Jeg skal gi deg et hint. Når jeg slutter å snakke med deg, drar du.",Dam ci wskazówkę. Jak przestanę mówić to wyjdź.,"Uma dica. Quando eu terminar de falar contigo, você vai embora.",,"Îți dau un sfat. Când termin de discutat cu tine, pleci.","Дам тебе подсказку: когда я закончу говорить, ты уходишь.",,"Jag ger dig en ledtråd. När jag slutar prata med dig, går du.","Sana bir ipucu vereyim. Seninle konuşmayı bıraktığımda, gideceksin." Do you have good news for me? I'm all ears.,TXT_DLG_SCRIPT02_D65188_DOYOU,"〃 -(after completing ""bloody"" chore)",,,Máš pro mě dobré zprávy? Uši mám nastražené.,Har du gode nyheder til mig? Jeg er lutter ører.,Hast du gute Neuigkeiten für mich? Ich bin ganz Ohr.,,Ĉu vi alportas bonajn novaĵojn? Mi estas tute aŭskultema.,¿Tienes buenas noticias para mí? Soy todo oídos.,,Onko sinulla minulle hyviä uutisia? Olen pelkkänä korvana.,De bonnes nouvelles? Mes oreilles sont à vous.,Van valami jó híred számomra? Csupa fül vagyok.,Hai buone notizie per me? Sono tutto orecchi...,私の耳に吉報を伝えに来たかね?,날 위한 좋은 소식이 있나? 열심히 듣고 있다구.,Heb je goed nieuws voor mij? Ik ben een en al oor.,Har du gode nyheter til meg? Jeg er lutter øre.,Masz dobre wieści dla mnie? Zamieniam się w słuch.,Alguma notícia boa pra mim? Sou todo ouvidos.,,Ai vești bune pentru mine? Sunt numai urechi.,Есть для меня хорошие новости? Слушаю во все уши.,,Benim için iyi haberlerin var mı? Can kulağıyla dinliyorum. +(after completing ""bloody"" chore)",,,Máš pro mě dobré zprávy? Uši mám nastražené.,Har du gode nyheder til mig? Jeg er lutter ører.,Hast du gute Neuigkeiten für mich? Ich bin ganz Ohr.,,Ĉu vi alportas bonajn novaĵojn? Mi estas tute aŭskultema.,¿Tienes buenas noticias para mí? Soy todo oídos.,,Onko sinulla minulle hyviä uutisia? Olen pelkkänä korvana.,De bonnes nouvelles? Mes oreilles sont à vous.,Van valami jó híred számomra? Csupa fül vagyok.,Hai buone notizie per me? Sono tutto orecchi...,私の耳に吉報を伝えに来たかね?,날 위한 좋은 소식이 있나? 열심히 듣고 있다구.,Heb je goed nieuws voor mij? Ik ben een en al oor.,Har du gode nyheter til meg? Jeg er lutter øre.,Masz dobre wieści dla mnie? Zamieniam się w słuch.,Alguma notícia boa pra mim? Sou todo ouvidos.,,Ai vești bune pentru mine? Sunt numai urechi.,Есть для меня хорошие новости? Слушаю во все уши.,,Har du goda nyheter till mig? Jag är alldeles nyfiken.,Benim için iyi haberlerin var mı? Can kulağıyla dinliyorum. The deed is done!,TXT_RPLY0_SCRIPT02_D65188_THEDE,"〃 -(〃)",,,Skutek je dokonán!,Det er gjort!,Es ist geschehen!,,Interkonsento plenumita!,¡El trato está hecho!,,Se on tehty!,C'est bel est bien fait.,Véghezvittem a büntettet.,È fatta!,やることはヤった,임무 완료!,De daad is gedaan!,Gjerningen er utført!,Wszystko zrobione!,Está feito!,,Fapta e făcută.,Дело сделано!,,İş tamamdır! +(〃)",,,Skutek je dokonán!,Det er gjort!,Es ist geschehen!,,Interkonsento plenumita!,¡El trato está hecho!,,Se on tehty!,C'est bel est bien fait.,Véghezvittem a büntettet.,È fatta!,やることはヤった,임무 완료!,De daad is gedaan!,Gjerningen er utført!,Wszystko zrobione!,Está feito!,,Fapta e făcută.,Дело сделано!,,Det är gjort!,İş tamamdır! "Oh, I just love souvenirs. Here, this will get you into the prison. Talk to Warden Montag. Whatever you do after that, I don't want to know.",TXT_DLG_SCRIPT02_D66704_OHIJU,"〃 (〃)",,,"Ó, já prostě zbožňuju suvenýry. Tady, tohle tě dostane do vězení. Promluv si s dozorčím Montagem. Co máš v plánu dělat po tom, to už vědět nechci.","Åh, jeg elsker bare souvenirs. Her, det her vil få dig ind i fængslet. Tal med fængselsinspektør Montag. Hvad du end gør efter det, vil jeg ikke vide det.","Oh, ich liebe Souvenirs. Hier, damit kommst du in das Gefängnis. Sprich mit Direktor Montag. Was du danach machen musst, weiß ich nicht.",,"Ha, mi ŝategas memoraĵojn. Havu ĉi tion, kio ebligos al vi eniri la malliberejon. Parolu kun la provoso Montag. Tion ajn, kion vi faros poste, mi ne volas scii.","Ah, me encantan los recuerdos. Ten, con esto podrás entrar en la prisión. Habla con el carcelero Montag. Lo que hagas después de eso no quiero saberlo.","Ah, me encantan los recuerdos. Toma, con esto vas a poder entrar a la prisión. Habla con el carcelero Montag. Lo que hagas después de eso no quiero saberlo.","Voi, kun minä rakastan matkamuistoja. Kas näin, pääset tällä vankilaan. Puhu vankilanjohtaja Montagin kanssa. Mitä teetkään sen jälkeen, en halua tietää.","Oh, j'adore les souvenirs. Voilà, ça vous laissera entrer dans la prison. Parlez au gardien Montag. Ce que vous faites après, je m'en fous complètement.","Oh, imádom az ajándékokat. Nesze, ezzel be fogsz tudni jutni a börtönbe. Beszélj Mondtag igazgatóval. Nem akarok tudni arról, mit teszel utána.","Ah, adoro i souvenir! Ecco qua, con questo potrai entrare nella prigione. Parla con Montag, il direttore del carcere. Quello che farai dopo, a me non interessa.","嬉しい手土産だ。では、これがあれば 刑務所に入れる。モンターグ所長と話すんだ。 -君がそこで何をしようが、私の管轄外だ。","오오, 난 기념품이 정말 좋아. 여기, 네가 원했던 감옥 통행증이야. 감옥으로 가서 몬탕 간수장에게 이야기해봐. 네가 어떤 짓을 저지르든, 그 후엔 절대로 알고 싶지 않아!","Oh, ik hou gewoon van souvenirs. Hier, dit zal je in de gevangenis brengen. Praat met directeur Montag. Wat je daarna ook doet, ik wil het niet weten.","Jeg elsker suvenirer. Denne får deg inn i fengselet. Snakk med fengselsdirektør Montag. Uansett hva du gjør etter det, vil jeg ikke vite det.","Oh, po prostu kocham pamiątki. Masz, to pozwoli ci wejść do więzienia. Pogadaj z Naczelnikiem Montagiem. Nie chcę wiedzieć co potem zrobisz.","Ah, eu simplesmente adoro suvenires. Tome, isto vai te ajudar a entrar na prisão. Fale com o carcereiro, Montag. O que você for fazer depois não me interessa.",,"Oh, ce mai ador suvenirurile. Aici, asta îți va permite să ajungi în interiorul închisorii. Vorbește cu gardianul Montag. Ce faci după aceea, nu vreau să știu.","О, как я люблю сувениры! Вот твой пропуск в тюрьму. Обратись к тюремщику Монтагу, а что ты будешь делать потом, я и знать не желаю.",,"Hatıra eşyalarına bayılırım. İşte, bu seni hapishaneye sokacak. Müdür Montag ile konuş. Ondan sonra ne yaparsan yap, bilmek istemiyorum." +君がそこで何をしようが、私の管轄外だ。","오오, 난 기념품이 정말 좋아. 여기, 네가 원했던 감옥 통행증이야. 감옥으로 가서 몬탕 간수장에게 이야기해봐. 네가 어떤 짓을 저지르든, 그 후엔 절대로 알고 싶지 않아!","Oh, ik hou gewoon van souvenirs. Hier, dit zal je in de gevangenis brengen. Praat met directeur Montag. Wat je daarna ook doet, ik wil het niet weten.","Jeg elsker suvenirer. Denne får deg inn i fengselet. Snakk med fengselsdirektør Montag. Uansett hva du gjør etter det, vil jeg ikke vite det.","Oh, po prostu kocham pamiątki. Masz, to pozwoli ci wejść do więzienia. Pogadaj z Naczelnikiem Montagiem. Nie chcę wiedzieć co potem zrobisz.","Ah, eu simplesmente adoro suvenires. Tome, isto vai te ajudar a entrar na prisão. Fale com o carcereiro, Montag. O que você for fazer depois não me interessa.",,"Oh, ce mai ador suvenirurile. Aici, asta îți va permite să ajungi în interiorul închisorii. Vorbește cu gardianul Montag. Ce faci după aceea, nu vreau să știu.","О, как я люблю сувениры! Вот твой пропуск в тюрьму. Обратись к тюремщику Монтагу, а что ты будешь делать потом, я и знать не желаю.",,"Jag älskar souvenirer. Här, den här tar dig in i fängelset. Prata med Warden Montag. Vad du än gör efter det vill jag inte veta.","Hatıra eşyalarına bayılırım. İşte, bu seni hapishaneye sokacak. Müdür Montag ile konuş. Ondan sonra ne yaparsan yap, bilmek istemiyorum." Fine by me.,TXT_RPLY0_SCRIPT02_D66704_FINEB,"〃 -(〃)",,,To je dobře.,Det er fint med mig.,Ist mir recht.,,Mi ne malkonsentas.,Por mí está bien.,,Sopii minulle.,Ca me convient.,Felőlem rendben van.,Per me va bene.,良好だ。,난 괜찮아.,Ik vind het prima.,Greit for meg.,"Jak dla mnie, w porządku.","Por mim, sem problemas.",,Mie-mi convine.,По рукам!,,Bana uyar. -"So you're the fool who stole the chalice? I'm going to have you arrested as a rebel thief... Thereby enhancing my position with the Order. How does it feel to be an unwitting pawn? I'll give you a hint, it's gonna hurt. ",TXT_DLG_SCRIPT02_D68220_SOYOU,〃,,,"Tak ty jsi ten blázen, který ukradl kalich? Teď tě nechám zatknout jako rebelského zloděje... a tím si upevním svou pozici s Řádem. Jaký je to pocit, být bezděčnou figurkou? Dám ti radu: Bude to bolet.","Så du er det fjols, der stjal bægeret? Jeg vil få dig arresteret som oprørstyv... og derved forbedre min position i ordenen. Hvordan føles det at være en uvidende brik? Jeg skal give dig et hint, det kommer til at gøre ondt.","So, du bist also der Narr der den Kelch gestohlen hat? Ich werde dich als Dieb der Rebellen verhaften lassen und dadurch meine Position im Orden verbessern. Wie fühlt es sich an als ahnungslose Schachfigur? Ich geb' dir einen Tipp: Es wird wehtun.",,"Vi do estas la stultulo, kiu ŝtelis la kalikon, ĉu? Mi kaptos vin kiel ribelan ŝteliston, tiel mi plibonigos mian statuson kun La Ordono. Kiel vi sentas, ke vi estas nevola marioneto? Jen aludeto: tio doloros vin.","¿Así que tú eres el necio que ha robado el cáliz? Te capturaré como ladrón rebelde, mejorando así mi posición con La Orden. ¿Qué se siente ser un peón involuntario? Una pista: te dolerá.","¿Así que tú eres el tonto que se robó el cáliz? Te voy a capturar como ladrón rebelde, mejorando así mi posición con La Orden. ¿Qué se siente ser un peón involuntario? Una pista: te va a doler.","Vai sinä olet se houkka, joka varasti kalkin? Pidätytän sinut kapinallisvarkaana, siten parantaen asemaani Veljeskunnassa. Miltäpä tuntuu olla tahaton pelinappula? Annanpa vihjeen, se tulee sattumaan.","Vous êtes l'abruti qui a volé le calice? Maintenant il faut que je vous arrète comme voleur rebelle.. Ca va aider ma position dans l'Ordre. Comment ça fait d'être un pion ignorant? Petite idée, ça va faire mal.",Szóval te vagy az isten barma aki ellopta a kelyhet? Jól letartóztatlak mint lázadó tolvaj...ezzel megerősítve a pozíciómat a Rendben. Milyen érzés egy tudatlan parasztnak lenni? Adok egy tippet: marhára fájni fog.,"Quindi sei tu il folle che ha rubato il calice? Ti farò arrestare come un ladro ribelle... E così facendo salirò nei ranghi dell'Ordine. Come ci si sente ad essere un'inconsapevole pedina? Ti do un consiglio, farà male.","それで、お前が聖杯を盗んだ愚か者か? +(〃)",,,To je dobře.,Det er fint med mig.,Ist mir recht.,,Mi ne malkonsentas.,Por mí está bien.,,Sopii minulle.,Ca me convient.,Felőlem rendben van.,Per me va bene.,良好だ。,난 괜찮아.,Ik vind het prima.,Greit for meg.,"Jak dla mnie, w porządku.","Por mim, sem problemas.",,Mie-mi convine.,По рукам!,,Det är okej för mig.,Bana uyar. +"So you're the fool who stole the chalice? I'm going to have you arrested as a rebel thief... Thereby enhancing my position with the Order. How does it feel to be an unwitting pawn? I'll give you a hint, it's gonna hurt. ",TXT_DLG_SCRIPT02_D68220_SOYOU,〃,,,"Tak ty jsi ten blázen, který ukradl kalich? Teď tě nechám zatknout jako rebelského zloděje... a tím si upevním svou pozici s Řádem. Jaký je to pocit, být bezděčnou figurkou? Dám ti radu: Bude to bolet.","Så du er det fjols, der stjal bægeret? Jeg vil få dig arresteret som oprørstyv... og derved forbedre min position i ordenen. Hvordan føles det at være en uvidende brik? Jeg skal give dig et hint, det kommer til at gøre ondt.","So, du bist also der Narr der den Kelch gestohlen hat? Ich werde dich als Dieb der Rebellen verhaften lassen und dadurch meine Position im Orden verbessern. Wie fühlt es sich an als ahnungslose Schachfigur? Ich geb' dir einen Tipp: Es wird wehtun.",,"Vi do estas la stultulo, kiu ŝtelis la kalikon, ĉu? Mi kaptos vin kiel ribelan ŝteliston, tiel mi plibonigos mian statuson kun La Ordeno. Kiel vi sentas, ke vi estas nevola marioneto? Jen aludeto: tio doloros vin.","¿Así que tú eres el necio que ha robado el cáliz? Te capturaré como ladrón rebelde, mejorando así mi posición con La Orden. ¿Qué se siente ser un peón involuntario? Una pista: te dolerá.","¿Así que tú eres el tonto que se robó el cáliz? Te voy a capturar como ladrón rebelde, mejorando así mi posición con La Orden. ¿Qué se siente ser un peón involuntario? Una pista: te va a doler.","Vai sinä olet se houkka, joka varasti kalkin? Pidätytän sinut kapinallisvarkaana, siten parantaen asemaani Veljeskunnassa. Miltäpä tuntuu olla tahaton pelinappula? Annanpa vihjeen, se tulee sattumaan.","Vous êtes l'abruti qui a volé le calice? Maintenant il faut que je vous arrète comme voleur rebelle.. Ca va aider ma position dans l'Ordre. Comment ça fait d'être un pion ignorant? Petite idée, ça va faire mal.",Szóval te vagy az isten barma aki ellopta a kelyhet? Jól letartóztatlak mint lázadó tolvaj...ezzel megerősítve a pozíciómat a Rendben. Milyen érzés egy tudatlan parasztnak lenni? Adok egy tippet: marhára fájni fog.,"Quindi sei tu il folle che ha rubato il calice? Ti farò arrestare come un ladro ribelle... E così facendo salirò nei ranghi dell'Ordine. Come ci si sente ad essere un'inconsapevole pedina? Ti do un consiglio, farà male.","それで、お前が聖杯を盗んだ愚か者か? 私は反賊としてお前を逮捕するつもりだ... そうすればオーダーの地位は上がる。 捨て駒に成るというのはどんな感じだ? ヒントを教えよう、お前はもう助からない。","그래서 네가 그 성배를 훔친 바보로군? 반군 절도범으로 체포해주지... 오더에서의 내 위치도 올리는 겸. 모르는 사이에 장물아비가 된 기분이 어떤가? 힌트를 주지, 정말 아플 거야.","Dus jij bent de dwaas die de kelk heeft gestolen? Ik ga je laten arresteren als een rebellendief.... Daardoor verbeter ik mijn positie bij de Orde. Hoe voelt het om een onwetende pion te zijn? Ik zal je een hint geven, het gaat pijn doen.","Så du er idioten som stjal begeret? Jeg skal få deg arrestert som en opprørsk tyv... Og dermed styrke min posisjon i Ordenen. Hvordan føles det å være en uvitende brikke? Jeg skal gi deg et hint, det kommer til å gjøre vondt.","Więc... to ty jesteś tym głupcem, który ukradł kielich? Aresztuję cię jako złodzieja-buntownika... A tym samym zwiększając swe uznanie u Zakonu. Jakie to uczucie jak się jest nieświadomym pionkiem? Podpowiedź, będzie bolało.",Então você é o imbecil que roubou o cálice? Eu vou mandar prender você como um ladrão rebelde... E assim a minha posição na Ordem vai melhorar. Como se sente sendo um plebeu ignorante? Só pra te dar uma ideia: vai doer.,,"Deci tu ești prostul care a furat potirul? Te voi aresta, hoț rebel... Prin urmare avansând în rangurile Ordinului. Cum e să fii un pion neștiutor? Îți dau un indiciu, o șă doară.","Так это ты тот недоумок, что украл чашу? Я передам тебя Ордену, как вора повстанцев... Это укрепит мои отношения с ним. Каково чувствовать себя безмозглой пешкой? Дам тебе подсказку: очень больно! -",,"Demek kadehi çalan aptal sensin? Seni asi bir hırsız olarak tutuklatacağım. Böylece Tarikat'taki konumumu güçlendireceğim. Farkında olmadan bir piyon olmak nasıl bir duygu? Sana bir ipucu vereyim, acıtacak." -It sucks!,TXT_RPLY0_SCRIPT02_D68220_ITSUC,〃,,,Je to na hovno!,Det stinker!,Scheiße!,,Tio estas aĉa!,¡Apesta!,,Ihan syvältä!,Quelle merde!,Szopás!,È uno schifo!,クソが!,이거 정말 난감한데?,Het is klote!,Det suger!,Cholera!,Que merda!,,E nașpa!,Это отстой!,,Berbat bir şey! -For you it does.,TXT_RYES0_SCRIPT02_D68220_FORYO,〃,,,Pro tebe určitě.,For dig gør det.,Du steckst ganz tief drin.,,Por vi ja.,Para ti sí.,,"Kyllä, sinun tilanteesi.","Pour vous, en effet.","Igen, neked.",A te lo farà.,私もそう思う。,너한테는 더욱 그럴걸.,Voor jou wel.,For deg gjør det det.,Dla ciebie tak.,"Pra você, sim.",,"Pentru tine, cu siguranță.",Для тебя — да.,,Senin için öyle. -Harris promised me money!,TXT_RPLY1_SCRIPT02_D68220_HARRI,〃,,,Harris mi slíbil peníze!,Harris lovede mig penge!,Harris hat mir Geld versprochen!,,Harris promesis monon al mi!,¡Harris me prometió dinero!,,Harris lupasi minulle rahaa!,Harris m'a promis de l'argent!,Harris pénzt igért!,Harris mi ha promesso dei soldi!,ハリスは俺に金を渡すと約束したのに!,해리스는 내게 돈을 약속했어!,Harris beloofde me geld!,Harris lovet meg penger!,Harris obiecał mi pieniądze!,O Harris prometeu me pagar!,,Harris mi-a promis bani!,Харрис обещал мне деньги!,,Harris bana para sözü verdi! +",,"Så du är idioten som stal kalken? Jag ska låta arrestera dig som en upprorisk tjuv... och på så sätt förbättra min ställning i orden. Hur känns det att vara en ovetande bricka? Jag ska ge dig en ledtråd, det kommer att göra ont.","Demek kadehi çalan aptal sensin? Seni asi bir hırsız olarak tutuklatacağım. Böylece Tarikat'taki konumumu güçlendireceğim. Farkında olmadan bir piyon olmak nasıl bir duygu? Sana bir ipucu vereyim, acıtacak." +It sucks!,TXT_RPLY0_SCRIPT02_D68220_ITSUC,〃,,,Je to na hovno!,Det stinker!,Scheiße!,,Tio estas aĉa!,¡Apesta!,,Ihan syvältä!,Quelle merde!,Szopás!,È uno schifo!,クソが!,이거 정말 난감한데?,Het is klote!,Det suger!,Cholera!,Que merda!,,E nașpa!,Это отстой!,,Det suger!,Berbat bir şey! +For you it does.,TXT_RYES0_SCRIPT02_D68220_FORYO,〃,,,Pro tebe určitě.,For dig gør det.,Du steckst ganz tief drin.,,Por vi ja.,Para ti sí.,,"Kyllä, sinun tilanteesi.","Pour vous, en effet.","Igen, neked.",A te lo farà.,私もそう思う。,너한테는 더욱 그럴걸.,Voor jou wel.,For deg gjør det det.,Dla ciebie tak.,"Pra você, sim.",,"Pentru tine, cu siguranță.",Для тебя — да.,,För dig gör det det.,Senin için öyle. +Harris promised me money!,TXT_RPLY1_SCRIPT02_D68220_HARRI,〃,,,Harris mi slíbil peníze!,Harris lovede mig penge!,Harris hat mir Geld versprochen!,,Harris promesis monon al mi!,¡Harris me prometió dinero!,,Harris lupasi minulle rahaa!,Harris m'a promis de l'argent!,Harris pénzt igért!,Harris mi ha promesso dei soldi!,ハリスは俺に金を渡すと約束したのに!,해리스는 내게 돈을 약속했어!,Harris beloofde me geld!,Harris lovet meg penger!,Harris obiecał mi pieniądze!,O Harris prometeu me pagar!,,Harris mi-a promis bani!,Харрис обещал мне деньги!,,Harris lovade mig pengar!,Harris bana para sözü verdi! Too bad. The only thing you're getting is dead!,TXT_RYES1_SCRIPT02_D68220_TOOBA,〃,,,"Smůla. Jediné, co dostaneš, je smrt.","Det var ærgerligt. Det eneste, du får, er død!",Jammerschade. Das Einzige was du bekommen wirst ist der Tod!,,"Kiel domaĝe. Ĉio, kion vi havos estas morto!","Qué mal. ¡Lo único que tendrás es la muerte!","Qué mal. ¡Lo único que -vas a tener es la muerte!","Voi voi. Sen kyllä voin sinulle luvata, että kuolet!","C'est dommage. Tout ce que vous gagnez, c'est une mort rapide!","Sajna, inkább ólmot kapsz helyette!",Peccato. L'unica cosa che otterrai è la morte!,残念だな、お前にやれるものは死のみだ!,그거 안됐네. 네가 얻는 거라곤 죽음뿐이니까!,Wat jammer. Het enige dat je zult krijgen is de dood!,"Synd for deg. Det eneste du får, er død!",Szkoda. Jedyne co dostaniesz to śmierć!,Que pena. A única coisa que você vai receber é a morte!,,Păcat. Tot ceea ce primești e moarte!,"Увы. Всё, что ты получишь — это смерть!",,Çok yazık. Elde edeceğin tek şey ölüm! -"In a small world, word travels fast. I hear you just removed some obstacles from your path. Nice work. Are you interested in some more lucrative projects?",TXT_DLG_SCRIPT02_D69736_INASM,MAP02: Rowan.,,,"V malém světě se zprávy šíří rychle. Slyšel jsem, že sis právě odstranil z cesty pár překážek. Pěkná práce. Měl bys zájem o nějaké lukrativnější zakázky?","I en lille verden spreder ordet sig hurtigt. Jeg hører, at du lige har fjernet nogle forhindringer fra din vej. Godt arbejde. Er du interesseret i nogle mere lukrative projekter?","Mir sind da Gerüchte zu Ohren gekommen, dass du gerade ein paar Hindernisse aus dem Weg geräumt hast. Gute Arbeit. Bist du an lukrativeren Angeboten interessiert?",,"En malgranda mondo novaĵoj vojaĝas rapide. Mi aŭdis, ke vi ĵus forigis kelkajn obstaklojn de via vojo. Bone farite. Ĉu interesas vin partopreni pli lukrajn projektojn?","En un mundo pequeño, las noticias vuelan. He oido que acabas de quitarte un par de obstáculos de encima. Bien hecho. ¿Te interesaría participar en proyectos más lucrativos?","En un mundo pequeño, las noticias vuelan. Oí que acabas de quitarte un par de obstáculos de encima. Bien hecho. ¿Te interesaría participar en proyectos más lucrativos?","Pienessä maailmassa sana kiirii nopeasti. Sana kuuluu, että olet juuri poistanut esteitä tieltäsi. Hyvin tehty. Olisitko kiinnostunut tuottoisammista projekteista?","Dans un petit monde, les rumeurs courent vite. J'entends que vous avez.. enlevé certains obstacles de votre chemin. Bon travail. Vous seriez intéressé par des projets plus lucratifs?",Ilyen kis helyen gyorsan terjednek a hírek. Úgy hírlik eltávolítottál pár akadályt az utadból. Szép munka. Nem érdekel valami jövedelmezőbb projekt?,"In un piccolo mondo, le voci si spargono in fretta... Ho sentito che hai appena rimosso alcuni ostacoli dal tuo percorso. Ottimo lavoro. Sei interessato a progetti un pò più lucrativi?","この小さな世界では噂が広まるのは早いもんだ。 +vas a tener es la muerte!","Voi voi. Sen kyllä voin sinulle luvata, että kuolet!","C'est dommage. Tout ce que vous gagnez, c'est une mort rapide!","Sajna, inkább ólmot kapsz helyette!",Peccato. L'unica cosa che otterrai è la morte!,残念だな、お前にやれるものは死のみだ!,그거 안됐네. 네가 얻는 거라곤 죽음뿐이니까!,Wat jammer. Het enige dat je zult krijgen is de dood!,"Synd for deg. Det eneste du får, er død!",Szkoda. Jedyne co dostaniesz to śmierć!,Que pena. A única coisa que você vai receber é a morte!,,Păcat. Tot ceea ce primești e moarte!,"Увы. Всё, что ты получишь — это смерть!",,Det var synd. Det enda du får är en död!,Çok yazık. Elde edeceğin tek şey ölüm! +"In a small world, word travels fast. I hear you just removed some obstacles from your path. Nice work. Are you interested in some more lucrative projects?",TXT_DLG_SCRIPT02_D69736_INASM,MAP02: Rowan.,,,"V malém světě se zprávy šíří rychle. Slyšel jsem, že sis právě odstranil z cesty pár překážek. Pěkná práce. Měl bys zájem o nějaké lukrativnější zakázky?","I en lille verden spreder ordet sig hurtigt. Jeg hører, at du lige har fjernet nogle forhindringer fra din vej. Godt arbejde. Er du interesseret i nogle mere lukrative projekter?","Mir sind da Gerüchte zu Ohren gekommen, dass du gerade ein paar Hindernisse aus dem Weg geräumt hast. Gute Arbeit. Bist du an lukrativeren Angeboten interessiert?",,"En malgranda mondo novaĵoj vojaĝas rapide. Mi aŭdis, ke vi ĵus forigis kelkajn obstaklojn de via vojo. Bone farite. Ĉu interesas vin partopreni pli lukrajn projektojn?",El mundo es un pañuelo y las noticias vuelan. He oido que acabas de quitarte un par de obstáculos de encima. Bien hecho. ¿Te interesaría participar en proyectos más lucrativos?,El mundo es un pañuelo y las noticias vuelan. Oí que acabas de quitarte un par de obstáculos de encima. Bien hecho. ¿Te interesaría participar en proyectos más lucrativos?,"Pienessä maailmassa sana kiirii nopeasti. Sana kuuluu, että olet juuri poistanut esteitä tieltäsi. Hyvin tehty. Olisitko kiinnostunut tuottoisammista projekteista?","Dans un petit monde, les rumeurs courent vite. J'entends que vous avez.. enlevé certains obstacles de votre chemin. Bon travail. Vous seriez intéressé par des projets plus lucratifs?",Ilyen kis helyen gyorsan terjednek a hírek. Úgy hírlik eltávolítottál pár akadályt az utadból. Szép munka. Nem érdekel valami jövedelmezőbb projekt?,"In un piccolo mondo, le voci si spargono in fretta... Ho sentito che hai appena rimosso alcuni ostacoli dal tuo percorso. Ottimo lavoro. Sei interessato a progetti un po' più lucrativi?","この小さな世界では噂が広まるのは早いもんだ。 あんたが素早く厄介事を片付けたと聞いたぞ。 もっと儲かる仕事をやってみる気はないかね?","이처럼 작은 세상엔, 소문이 빨리 전해지지. 방금 자네가 장애물들을 처리한 걸 들었다네. 수고했어. 수익이 아주 짭짤한 일자리에 관심이 있나? -",In een kleine wereld gaat het woord snel. Ik hoor dat je net wat obstakels van je pad hebt verwijderd. Goed werk. Ben je geïnteresseerd in wat lucratievere projecten?,I en liten verden sprer rykter seg fort. Jeg hører du har fjernet noen hindringer fra veien din. Bra jobbet. Er du interessert i flere lukrative prosjekter?,"W małym świecie wieści szybko się rozchodzą. Usłyszałem, że właśnie usunąłeś parę rzeczy ze swojej drogi. Dobra robota. Jesteś zainteresowany jakimiś bardziej korzystnymi projektami?","Neste mundo pequeno, as notícias viajam rápido. Fiquei sabendo que você tirou alguns obstáculos de seu caminho. Bom trabalho. Está interessado em alguns projetos mais lucrativos?",,"Într-o lume mică, vorba circulă repede. Aud că tocmai ai înlăturat niște obstacole din drum. Bună treabă. Mai ești interesat de alte proiecte profitabile?","Мир тесен, и новости разлетаются быстро. Я слышал, как ты только что убрал пару препятствий со своего пути. Хорошая работа. Заинтересован в более прибыльных занятиях?",,"Küçük bir dünyada, laf çabuk yayılır. Yolundaki bazı engelleri kaldırdığını duydum. İyi iş çıkardın. Daha kazançlı projelerle ilgileniyor musun?" -"Sure, why not.",TXT_RPLY0_SCRIPT02_D69736_SUREW,〃,,,"Klidně, proč ne.","Selvfølgelig, hvorfor ikke.","Sicher, warum nicht.",,"Jes, kial ne?","Por supuesto, ¿por qué no?","Claro, ¿por qué no?",Miksipä ei.,"Ouais, pourquoi pas.","Persze, miért is ne.","Certo, perché no.",ああ、もちろんだ。,그거 좋군요.,"Tuurlijk, waarom niet.","Ja, hvorfor ikke.","Jasne, czemu nie.","Claro, por que não?",,"Da, de ce nu.","Конечно, почему бы и нет.",,"Elbette, neden olmasın." -No thanks.,TXT_RPLY1_SCRIPT02_D69736_NOTHA,〃,,,"Ne, díky.",Nej tak.,Nein danke.,,"Ne, dankon.","No, gracias.",,Ei kiitos.,Non merci.,Nem kösz.,"No, grazie.",やめとくよ。,필요 없어요.,"Nee, dank je wel.",Nei takk.,"Nie, dziękuję.","Não, obrigado.",,Nu mulțumesc.,"Нет, спасибо.",,"Hayır, teşekkürler." -Then get lost!,TXT_RYES1_SCRIPT02_D69736_THENG,,,,Tak vypadni!,Så forsvind!,Dann verzieh dich!,,Tiuokaze malaperu!,¡Entonces piérdete!,,Sitten häivy!,Alors dégage!,Akkor húzz el innen!,E allora sparisci!,じゃあ失せるんだな!,그럼 꺼져!,Dan verdwalen!,Så stikk!,W takim razie spadaj!,Então suma daqui!,,Atunci valea!,Тогда проваливай!,,O zaman kaybol! +",In een kleine wereld gaat het woord snel. Ik hoor dat je net wat obstakels van je pad hebt verwijderd. Goed werk. Ben je geïnteresseerd in wat lucratievere projecten?,I en liten verden sprer rykter seg fort. Jeg hører du har fjernet noen hindringer fra veien din. Bra jobbet. Er du interessert i flere lukrative prosjekter?,"W małym świecie wieści szybko się rozchodzą. Usłyszałem, że właśnie usunąłeś parę rzeczy ze swojej drogi. Dobra robota. Jesteś zainteresowany jakimiś bardziej korzystnymi projektami?","Neste mundo pequeno, as notícias viajam rápido. Fiquei sabendo que você tirou alguns obstáculos de seu caminho. Bom trabalho. Está interessado em alguns projetos mais lucrativos?",,"Într-o lume mică, vorba circulă repede. Aud că tocmai ai înlăturat niște obstacole din drum. Bună treabă. Mai ești interesat de alte proiecte profitabile?","Мир тесен, и новости разлетаются быстро. Я слышал, как ты только что убрал пару препятствий со своего пути. Хорошая работа. Заинтересован в более прибыльных занятиях?",,I en liten värld går ryktet fort. Jag hörde att du just avlägsnade några hinder från din väg. Bra jobbat. Är du intresserad av några mer lukrativa projekt?,"Küçük bir dünyada, laf çabuk yayılır. Yolundaki bazı engelleri kaldırdığını duydum. İyi iş çıkardın. Daha kazançlı projelerle ilgileniyor musun?" +"Sure, why not.",TXT_RPLY0_SCRIPT02_D69736_SUREW,〃,,,"Klidně, proč ne.","Selvfølgelig, hvorfor ikke.","Sicher, warum nicht.",,"Jes, kial ne?","Por supuesto, ¿por qué no?","Claro, ¿por qué no?",Miksipä ei.,"Ouais, pourquoi pas.","Persze, miért is ne.","Certo, perché no.",ああ、もちろんだ。,그거 좋군요.,"Tuurlijk, waarom niet.","Ja, hvorfor ikke.","Jasne, czemu nie.","Claro, por que não?",,"Da, de ce nu.","Конечно, почему бы и нет.",,"Visst, varför inte.","Elbette, neden olmasın." +No thanks.,TXT_RPLY1_SCRIPT02_D69736_NOTHA,〃,,,"Ne, díky.",Nej tak.,Nein danke.,,"Ne, dankon.","No, gracias.",,Ei kiitos.,Non merci.,Nem kösz.,"No, grazie.",やめとくよ。,필요 없어요.,"Nee, dank je wel.",Nei takk.,"Nie, dziękuję.","Não, obrigado.",,Nu mulțumesc.,"Нет, спасибо.",,Nej tack.,"Hayır, teşekkürler." +Then get lost!,TXT_RYES1_SCRIPT02_D69736_THENG,,,,Tak vypadni!,Så forsvind!,Dann verzieh dich!,,Tiuokaze malaperu!,¡Entonces piérdete!,,Sitten häivy!,Alors dégage!,Akkor húzz el innen!,E allora sparisci!,じゃあ失せるんだな!,그럼 꺼져!,Dan verdwalen!,Så stikk!,W takim razie spadaj!,Então suma daqui!,,Atunci valea!,Тогда проваливай!,,Försvinn då!,O zaman kaybol! "Fool! Guards, rid me of this meddlesome peon.",TXT_DLG_SCRIPT02_D71252_FOOLG,Rowan.,,,"Blázne! Stráže, zbavte se tohohle zbytečného nuzáka.","Fjols! Vagter, befri mig for denne uopmærksomme bondeknold.","Du Narr! Wachen, entledigt mich dieses lästigen Tagelöhners.",,"Stultulo! Gardistoj, liberigu min de ĉi tiu entrudiĝema peono.","¡Insensato! Guardias, libérenme de este entrometido peón.","¡Tonto! Guardias, libérenme de este entrometido peón.","Sinä mieletön! Vartijat, hankkiutukaa eroon tästä tungettelevasta moukasta.","Idiot! Gardes, débarassez-moi de ce pion embêtant!","Barom! Őrök, takarítsátok el a színem elől ezt a kotnyeleskedő pondrót!","Sciocco! Guardie, liberatemi da questo ficcanaso.","なんと愚かな! -衛兵、この厄介な奴を始末してくれ。","멍청한 것! 경비병, 이 걸리적거리는 난동꾼을 치워라.","Dwaas! Bewakers, bevrijd me van deze bemoeizuchtige pioen.","Idiot! Vakter, kvitt meg med denne innpåslitne trellen.","Głupcze! Straż, uwolnijcie mnie od tego wścibskiego robola.","Idiota! Guardas, tirem esse peão intrometido daqui.",,"Prostule! Gardieni, scăpați-mă de acest pion băgăreț.","Глупец! Стража, избавьте меня от этого недоумка.",,"Aptal! Muhafızlar, beni bu işgüzar piyondan kurtarın." -"Good. Some uh, friends of mine need someone silenced. Beldin is being held by the Order in their sanctuary. There's a rarely used entrance by a small pier off the river which is unguarded. Get in, shut him up, and bring his ring back to me as proof.",TXT_DLG_SCRIPT02_D72768_GOODS,〃,,,"Dobře. Někteří mí... přátelé potřebují někoho umlčet. Beldin je držen Řádem v jejich svatyni. Na malém molu u řeky je málo používaný vchod, který nikdo nehlídá. Dostaň se dovnitř, umlč ho a přines mi jeho prsten jako důkaz.","Godt. Nogle af mine venner har brug for at få nogen til at tie stille. Beldin bliver tilbageholdt af Ordenen i deres fristed. Der er en sjældent brugt indgang ved en lille mole ud for floden, som er ubevogtet. Gå ind, luk munden på ham, og giv mig hans ring som bevis.","Gut. Einige, äh, Freunde von mir müssen zum Schweigen gebracht werden. Beldin wird vom Orden im Heiligtum gefangen gehalten. Es gibt dort einen selten benutzen Eingang bei einem kleinen Pier am Fluss, welcher unbewacht ist. Geh rein, mach ihn kalt und bringe mir seinen Ring als Beweis zurück.",,"Bone. Kelkaj... hm, amikoj bezonas silentemulon. Beldin estas retenita en la sanktejo de La Ordono. Estas malofte uzata enirejo ĉe malgranda kajo sen viglado apud la rivero. Eniru tien, silentigu lin kaj alportu lian ringon kiel pruvon.","Bien. Algunos... este, amigos míos necesitan a alguien sigiloso. Beldin es retenido por La Orden en su santuario. Hay una entrada rara vez utilizada por un pequeño muelle junto al río que está sin vigilancia. Entra, cállalo y tráeme su anillo como prueba.",,"Hyvä. Eräät, öh, ystäväni kaipaavat erään henkilön hiljentämistä. Veljeskunta pitää Beldiniä vankinaan pyhäkössään. Jokea vierustavalta vartioimattomalta pikkulaiturilta on harvoin käytetty sisäänkäynti. Mene sisään, vaienna hänet ja tuo hänen sormuksensa takaisin todisteena.","Bien. Certains... amis à moi demandent à ce que quelqu'un arrète de parler. Beldin est retenu par l'Ordre dans leur sanctuaire. Il y a une entrée rarement utilisée près d'un ponton près de la rivière qui n'est pas gardée. Entrez, coupez-lui le sifflet et ramenez moi son anneau comme preuve.","Kiváló. Néhány barátom el akar valakit némítani. Beldint a Rend szentélyében tartják fogva. Van egy ritkán használt bejárat egy kis mólónál, amit nem védenek katonák. Hatolj be, csitícsd el örökre, és hozdd el a gyűrűjét bizonyítékként.","Ottimo. Alcuni uh, amici miei hanno bisogno che qualcuno venga messo a tacere. Beldin è sotto custodia dell'Ordine nel loro santuario. C'è un ingresso poco utilizzato e non sorvegliato tramite un piccolo molo accanto al fiume. Entra, fallo tacere, e portami il suo anello come prova.","それでいい。ええと、私の友人がある人物を +衛兵、この厄介な奴を始末してくれ。","멍청한 것! 경비병, 이 걸리적거리는 난동꾼을 치워라.","Dwaas! Bewakers, bevrijd me van deze bemoeizuchtige pioen.","Idiot! Vakter, kvitt meg med denne innpåslitne trellen.","Głupcze! Straż, uwolnijcie mnie od tego wścibskiego robola.","Idiota! Guardas, tirem esse peão intrometido daqui.",,"Prostule! Gardieni, scăpați-mă de acest pion băgăreț.","Глупец! Стража, избавьте меня от этого недоумка.",,"Dumbom! Vakter, gör mig av med den här besvärliga pingsten.","Aptal! Muhafızlar, beni bu işgüzar piyondan kurtarın." +"Good. Some uh, friends of mine need someone silenced. Beldin is being held by the Order in their sanctuary. There's a rarely used entrance by a small pier off the river which is unguarded. Get in, shut him up, and bring his ring back to me as proof.",TXT_DLG_SCRIPT02_D72768_GOODS,〃,,,"Dobře. Někteří mí... přátelé potřebují někoho umlčet. Beldin je držen Řádem v jejich svatyni. Na malém molu u řeky je málo používaný vchod, který nikdo nehlídá. Dostaň se dovnitř, umlč ho a přines mi jeho prsten jako důkaz.","Godt. Nogle af mine venner har brug for at få nogen til at tie stille. Beldin bliver tilbageholdt af Ordenen i deres fristed. Der er en sjældent brugt indgang ved en lille mole ud for floden, som er ubevogtet. Gå ind, luk munden på ham, og giv mig hans ring som bevis.","Gut. Einige, äh, Freunde von mir müssen zum Schweigen gebracht werden. Beldin wird vom Orden im Heiligtum gefangen gehalten. Es gibt dort einen selten benutzen Eingang bei einem kleinen Pier am Fluss, welcher unbewacht ist. Geh rein, mach ihn kalt und bringe mir seinen Ring als Beweis zurück.",,"Bone. Kelkaj... hm, amikoj bezonas «silentigi» iun. Beldin estas retenita en la sanktejo de La Ordeno. Estas malofte uzata enirejo ĉe malgranda kajo sen viglado apud la rojo. Eniru tien, silentigu lin kaj alportu lian ringon kiel pruvon.","Bien. Algunos... este, amigos míos necesitan «silenciar» a alguien. Beldin es retenido por La Orden en su santuario. Hay una entrada rara vez utilizada por un pequeño muelle junto al arroyo que está sin vigilancia. Entra, cállalo y tráeme su anillo como prueba.",,"Hyvä. Eräät, öh, ystäväni kaipaavat erään henkilön hiljentämistä. Veljeskunta pitää Beldiniä vankinaan pyhäkössään. Jokea vierustavalta vartioimattomalta pikkulaiturilta on harvoin käytetty sisäänkäynti. Mene sisään, vaienna hänet ja tuo hänen sormuksensa takaisin todisteena.","Bien. Certains... amis à moi demandent à ce que quelqu'un arrète de parler. Beldin est retenu par l'Ordre dans leur sanctuaire. Il y a une entrée rarement utilisée près d'un ponton près de la rivière qui n'est pas gardée. Entrez, coupez-lui le sifflet et ramenez moi son anneau comme preuve.","Kiváló. Néhány barátom el akar valakit némítani. Beldint a Rend szentélyében tartják fogva. Van egy ritkán használt bejárat egy kis mólónál, amit nem védenek katonák. Hatolj be, csitícsd el örökre, és hozdd el a gyűrűjét bizonyítékként.","Ottimo. Alcuni uh, amici miei hanno bisogno che qualcuno venga messo a tacere. Beldin è sotto custodia dell'Ordine nel loro santuario. C'è un ingresso poco utilizzato e non sorvegliato tramite un piccolo molo accanto al fiume. Entra, fallo tacere, e portami il suo anello come prova.","それでいい。ええと、私の友人がある人物を 黙らせて欲しいと望んでいるんだ。 ベルディンはオーダーの連中の聖域に 囚われている。建物への入り口は川に掛かった 桟橋の先にあり、そこは誰も警備してないし ほぼ使われていない。潜入してヤツを黙らせて、 -仕事をした証拠としてヤツの指輪を見せてくれ。","좋구만... 그래서, 내 지인이 말하기를 벨딘이라는 사람의 입을 다물게 만들라는군. 그는 지금 오더에 의해 성소에 감금됐네. 그 근처 강가에 있는 작은 부두 옆에 자주 쓰이지 않는 입구가 있다네. 거기로 향해서, 그의 입을 막게. 그리고 그의 반지를 증거로 가져오게.","Goed. Sommige uh, vrienden van mij hebben iemand nodig die het zwijgen oplegt. Beldin wordt vastgehouden door de Orde in hun heiligdom. Er is een zelden gebruikte ingang bij een kleine pier van de rivier die onbewaakt is. Stap in, sluit hem op en breng zijn ring terug als bewijs.","Fint. Noen venner av meg trenger å få noen til å tie. Beldin holdes av Ordenen i deres helligdom. Det er en sjelden brukt inngang ved en liten brygge ved elven som er ubevoktet. Gå inn, få ham til å holde kjeft, og gi meg ringen hans som bevis.","Dobrze. Paru moich... ehmm... przyjaciół potrzebuje kogoś uciszyć. Beldin jest trzymany przez Zakon w ich sanktuarium. Jest tu gdzieś rzadko używane wejście przy małej przystani przy rzece, które jest niestrzeżone. Wejdź tam, ucisz go i przynieś mi jego pierścień jako dowód.","Ótimo. Alguns hã... amigos meus precisam silenciar alguém. Beldin foi detido pela Ordem no santuário deles. Há uma entrada pouco usada perto de um pequeno pier pelo rio que está sem guardas. Entre lá, cale a boca dele e traga o seu anel de volta pra mim como prova.",,"Bun. Niște um... prieteni de-ai mei au nevoie de cineva redus la tăcere. Beldin e ținut de Ordin în sanctuarul lor. E o intrare rar folosită pe niște chei lângă râu care e nepăzită. Intră, fă-l să tacă pe veci, și adu-mi inelul lui ca dovadă.","Хорошо. Некоторые мои, э-э-э, приятели, хотят, чтобы кое-кто замолчал. Орден держит Белдина в своём святилище. У небольшого пира рядом с рекой есть редко используемый вход, что не охраняется. Проберись внутрь, заставь его замолчать навсегда и принеси мне его кольцо в качестве доказательства.",,"Güzel. Bazı arkadaşlarımın birinin susturulmasına ihtiyacı var. Beldin, Tarikat tarafından sığınaklarında tutuluyor. Nehir kıyısındaki küçük iskelede korumasız, nadiren kullanılan bir giriş var. İçeri gir, onu sustur ve yüzüğünü kanıt olarak bana geri getir." -Will it be worth the effort?,TXT_RPLY0_SCRIPT02_D72768_WILLI,〃,,,Bude mi to stát za to?,Vil det være indsatsen værd?,Wird es die Mühe denn wert sein?,,Ĉu la strebo estos valora?,¿Valdrá la pena el esfuerzo?,¿Va a valer la pena el esfuerzo?,Onko väärti vaivannäköni?,Est-ce que ça en vaudra l'effort?,Megéri az erőfeszítést?,Ne varrà la pena?,苦労に見合った報酬だろうな?,노력할만한 가치가 있나요?,Zal het de moeite waard zijn?,Er det verdt innsatsen?,Czy będzie to warte moich starań?,Será que vale a pena o esforço?,,O să merite efortul?,Оно того стоит?,,Bu çabaya değecek mi? -"I'll guarantee 50 gold and if you return without setting off every alarm in town, there's the chance to earn much, much more, and here's a little helper that should give you an edge.",TXT_DLG_SCRIPT02_D74284_ILLGU,〃,,,"Garantuji ti padesát zlatých a jestliže se vrátíš bez toho, abys spustil každý poplach ve městě, je tu šance vydělat si mnohem, mnohem víc. Tady je malý pomocník, který by ti měl pomoci.","Jeg garanterer dig 50 guld, og hvis du vender tilbage uden at udløse alle alarmer i byen, er der mulighed for at tjene meget, meget mere, og her er en lille hjælper, der burde give dig en fordel.","Ich garantiere dir 50 Gold und wenn du zurückkehrst ohne den Alarm in der Stadt ausgelöst zu haben, dann hast du noch die Chance, viel, viel mehr zu verdienen und hier ist noch ein kleiner Helfer der dir einen Vorteil verschaffen wird.",,"Mi garantias al vi 50 monerojn da oro, kaj se vi revenos sen ekagigi ĉiun alarmon en la urbo, estas eblo gajni multe, multe pliajn. Kaj jen malgranda «helpanto» por faciligi vian takson.","Te garantizo 50 de oro, y si vuelves sin activar todas las alarmas del pueblo, existe la posibilidad de ganar mucho, mucho más. Y aquí hay un pequeño ayudante que debería darte una ventaja.",,"Takaan sinulle 50 kultakolikkoa, ja jos palaat ilman, että soitatat jokaista kaupungin hälytyskelloa, voit mahdollisesti tienata paljon paljon enemmän. Tässä vielä pikkuapuri, jonka pitäisi antaa sinulle pienen kilpailuedun.","Je vous garantis 50 pièces et si vous revenez sans déclencher toutes les alarmes de la ville, vous avez la possibilité de gagner bien plus. Voilà une petite avance qui pourra vous aider.","50 arany garantáltan a markodat üti, és ha nem indítod be a riasztót a városban, akkor esélyed van többet is kapni, sokkal többet. Itt van egy kis segítség, hogy előnyhöz juss.","Ti garantisco 50 pezzi d'oro e se ritorni qua senza far scattare ogni allarme in città, ci sarà l'opportunità di guadagnare molto, molto di più, ed ecco qua anche un piccolo aggeggio che ti aiuterà.","50ゴールドは保証するし街の警報を鳴らさず +仕事をした証拠としてヤツの指輪を見せてくれ。","좋구만... 그래서, 내 지인이 말하기를 벨딘이라는 사람의 입을 다물게 만들라는군. 그는 지금 오더에 의해 성소에 감금됐네. 그 근처 강가에 있는 작은 부두 옆에 자주 쓰이지 않는 입구가 있다네. 거기로 향해서, 그의 입을 막게. 그리고 그의 반지를 증거로 가져오게.","Goed. Sommige uh, vrienden van mij hebben iemand nodig die het zwijgen oplegt. Beldin wordt vastgehouden door de Orde in hun heiligdom. Er is een zelden gebruikte ingang bij een kleine pier van de rivier die onbewaakt is. Stap in, sluit hem op en breng zijn ring terug als bewijs.","Fint. Noen venner av meg trenger å få noen til å tie. Beldin holdes av Ordenen i deres helligdom. Det er en sjelden brukt inngang ved en liten brygge ved elven som er ubevoktet. Gå inn, få ham til å holde kjeft, og gi meg ringen hans som bevis.","Dobrze. Paru moich... ehmm... przyjaciół potrzebuje kogoś uciszyć. Beldin jest trzymany przez Zakon w ich sanktuarium. Jest tu gdzieś rzadko używane wejście przy małej przystani przy rzece, które jest niestrzeżone. Wejdź tam, ucisz go i przynieś mi jego pierścień jako dowód.","Ótimo. Alguns hã... amigos meus precisam silenciar alguém. Beldin foi detido pela Ordem no santuário deles. Há uma entrada pouco usada perto de um pequeno pier pelo rio que está sem guardas. Entre lá, cale a boca dele e traga o seu anel de volta pra mim como prova.",,"Bun. Niște um... prieteni de-ai mei au nevoie de cineva redus la tăcere. Beldin e ținut de Ordin în sanctuarul lor. E o intrare rar folosită pe niște chei lângă râu care e nepăzită. Intră, fă-l să tacă pe veci, și adu-mi inelul lui ca dovadă.","Хорошо. Некоторые мои, э-э-э, приятели, хотят, чтобы кое-кто замолчал. Орден держит Белдина в своём святилище. У небольшого пира рядом с рекой есть редко используемый вход, что не охраняется. Проберись внутрь, заставь его замолчать навсегда и принеси мне его кольцо в качестве доказательства.",,"Jag är glad att du är här. Några av mina vänner behöver få någon tystad. Beldin hålls av orden i deras helgedom. Det finns en sällan använd ingång vid en liten brygga vid floden som är obevakad. Gå in, få tyst på honom och ge mig hans ring som bevis.","Güzel. Bazı arkadaşlarımın birinin susturulmasına ihtiyacı var. Beldin, Tarikat tarafından sığınaklarında tutuluyor. Nehir kıyısındaki küçük iskelede korumasız, nadiren kullanılan bir giriş var. İçeri gir, onu sustur ve yüzüğünü kanıt olarak bana geri getir." +Will it be worth the effort?,TXT_RPLY0_SCRIPT02_D72768_WILLI,〃,,,Bude mi to stát za to?,Vil det være indsatsen værd?,Wird es die Mühe denn wert sein?,,Ĉu la strebo estos valora?,¿Valdrá la pena el esfuerzo?,¿Va a valer la pena el esfuerzo?,Onko väärti vaivannäköni?,Est-ce que ça en vaudra l'effort?,Megéri az erőfeszítést?,Ne varrà la pena?,苦労に見合った報酬だろうな?,노력할만한 가치가 있나요?,Zal het de moeite waard zijn?,Er det verdt innsatsen?,Czy będzie to warte moich starań?,Será que vale a pena o esforço?,,O să merite efortul?,Оно того стоит?,,Kommer det att vara värt besväret?,Bu çabaya değecek mi? +"I'll guarantee 50 gold and if you return without setting off every alarm in town, there's the chance to earn much, much more, and here's a little helper that should give you an edge.",TXT_DLG_SCRIPT02_D74284_ILLGU,〃,,,"Garantuji ti padesát zlatých a jestliže se vrátíš bez toho, abys spustil každý poplach ve městě, je tu šance vydělat si mnohem, mnohem víc. Tady je malý pomocník, který by ti měl pomoci.","Jeg garanterer dig 50 guld, og hvis du vender tilbage uden at udløse alle alarmer i byen, er der mulighed for at tjene meget, meget mere, og her er en lille hjælper, der burde give dig en fordel.","Ich garantiere dir 50 Gold und wenn du zurückkehrst ohne den Alarm in der Stadt ausgelöst zu haben, dann hast du noch die Chance, viel, viel mehr zu verdienen und hier ist noch ein kleiner Helfer der dir einen Vorteil verschaffen wird.",,"Mi garantias al vi 50 monerojn da oro, kaj se vi revenos ne ekagiginte ĉiun alarmon en la urbo, estas eblo gajni multe, multe pliajn. Kaj jen malgranda helpilo por faciligi vian takson.","Te garantizo 50 de oro, y si vuelves sin activar todas las alarmas del pueblo, existe la posibilidad de ganar mucho, mucho más. Y aquí hay un pequeño ayudante que debería darte una ventaja.",,"Takaan sinulle 50 kultakolikkoa, ja jos palaat ilman, että soitatat jokaista kaupungin hälytyskelloa, voit mahdollisesti tienata paljon paljon enemmän. Tässä vielä pikkuapuri, jonka pitäisi antaa sinulle pienen kilpailuedun.","Je vous garantis 50 pièces et si vous revenez sans déclencher toutes les alarmes de la ville, vous avez la possibilité de gagner bien plus. Voilà une petite avance qui pourra vous aider.","50 arany garantáltan a markodat üti, és ha nem indítod be a riasztót a városban, akkor esélyed van többet is kapni, sokkal többet. Itt van egy kis segítség, hogy előnyhöz juss.","Ti garantisco 50 pezzi d'oro e se ritorni qua senza far scattare ogni allarme in città, ci sarà l'opportunità di guadagnare molto, molto di più, ed ecco qua anche un piccolo aggeggio che ti aiuterà.","50ゴールドは保証するし街の警報を鳴らさず 戻ってこれたら、もっと金を得られる機会が あるぞ。それと、お前の力となる物も渡そう。","만약 이 마을의 경보를 울리지 않고 조용히 완수하면 50 골드를 보상으로 주지. 이 외에도 더 많은 보상을 받을 수 있는 일들이 아주 많이 있다네. 그리고 여기, 모험에 도움이 될 만한 무기를 가져가게.","Ik garandeer 50 goud en als je terugkeert zonder elke alarmbel in de stad af te laten gaan, is er de kans om veel, veel meer te verdienen, en hier is een kleine helper die je een voordeel zou moeten geven.","Jeg garanterer 50 gull, og hvis du kommer tilbake uten å utløse alle alarmer i byen, kan du tjene mye, mye mer, og her er en liten hjelper som bør gi deg en fordel.","Gwarantuję 50 monet, a jeśli wrócisz bez włączania wszystkich alarmów w mieście, jest szansa, że mógłbyś dostać więcej. Znacznie więcej. Oto mały pomocnik, który da ci przewagę.","Garanto que você receberá 50 de ouro e se você retornar sem ativar todos os alarmes na cidade haverá uma chance de ganhar muito, muito mais. E aqui tem algo que pode te ajudar um pouco.",,"Garantez 50 de monezi de aur, și dacă nu declanșezi vreo alarmă în oraș, e o șansă de câștig mult, mult mai mare, iar aici e un mic ajutător care să-ți facă treaba mai ușoară.","Я обещаю тебе 50 золотых. И ты сможешь заработать куда больше, если выполнишь задание, не переполошив всю стражу в городе. А чтобы у тебя было некоторое преимущество, вот тебе небольшой помощник. -",,"50 altın garanti ediyorum ve eğer kasabadaki tüm alarmları çalıştırmadan geri dönerseniz, çok daha fazlasını kazanma şansınız var ve işte size avantaj sağlayacak küçük bir yardımcı." -"Thanks, I'll need it.",TXT_RPLY0_SCRIPT02_D74284_THANK,〃,,,"Díky, budu ho potřebovat.","Tak, jeg får brug for den.","Danke, das werde ich brauchen.",,Dankon. Mi bezonos ĝin.,Gracias. Lo necesitaré.,Gracais. Lo voy a necesitar.,"Kiitos, tarvitsen sitä.","Merci, j'en aurais besoin.","Köszönöm, kelleni is fog.","Grazie, ne avrò bisogno.",ありがとよ、これは後々必要になるな。,고마워요. 도움이 될 것 같습니다.,"Bedankt, ik zal het nodig hebben.","Takk, jeg trenger det.",Dzięki. Będę go potrzebował.,"Obrigado, vou precisar.",,"Merci, voi avea nevoie de el.",Спасибо. Он мне пригодится.,,"Teşekkürler, ihtiyacım olacak." -"Good. Remember, his silence is golden.",TXT_DLG_SCRIPT02_D75800_GOODR,〃,,,"Dobře. Pamatuj, že jeho mlčení má cenu zlata.","Godt. Husk, at hans tavshed er guld.",Gut. Denke dran. Sein Schweigen ist Gold wert.,,Bone. Memoru: lia silento estas el oro.,Bien. Recuerda: su silencio es de oro.,,"Hyvä. Muista, että hänen vaikenemisensa on kultaa.",Bien. Souvenez-vous. Le silence est d'or.,"Remek, a hallgatása arany.","Bene. Ricorda, il suo silenzio è d'oro.",いいぞ。覚えておけ、彼が沈黙したら金だ。,천만에. 그리고 기억하게. 그를 입막음하는 게 유일한 희망일세.,"Goed. Vergeet niet, zijn stilte is goud waard.",Bra. Husk at hans taushet er gull verdt.,"Dobrze. Pamiętaj, jego cisza jest cenna.","Ótimo. Lembre-se, o silêncio dele vale ouro.",,"Bun. Reține, tăcerea e de aur.","Превосходно. Запомни, его молчание — золото.",,"Güzel. Unutma, onun sessizliği altındır." -I'll get him.,TXT_RPLY0_SCRIPT02_D75800_ILLGE,〃,,,Dostanu ho.,Jeg henter ham.,Ich krieg ihn.,,Mi trovos lin.,Lo encontraré.,Lo voy a encontrar.,Saan hänet.,Je m'occupe de lui.,Elintézem.,Lo vado a prendere.,始末してみせる。,그를 잡겠어요.,Ik krijg hem wel.,Jeg skal ta ham.,Dorwę go.,Vou pegá-lo.,,O să-l aduc.,Я прикончу его.,,Onu yakalayacağım. -Mission accomplished? You have the ring of the traitor?,TXT_DLG_SCRIPT02_D77316_MISSI,〃,,,Mise splněna? Máš zrádcův prsten?,Mission fuldført? Har du forræderens ring?,Mission ausgeführt? Hast du den Ring des Verräters?,,Ĉu vi plenumis la mision? Ĉu vi havas la ringon de la perfidulo?,¿Misión cumplida? ¿Tienes el anillo del traidor?,,Tehtävä suoritettu? Sinulla on petturin sormus?,Mission accomplie? Vous avez l'anneau du traître?,Sikeres küldetés? Nálad van az áruló gyűrűje?,Missione compiuta? Hai l'anello del traditore?,"任務完了か? -あの裏切り者の指輪は持っているんだろうな?",임무를 완수 한 건가? 배신자의 반지를 가지고 있어?,Missie volbracht? Heb je de ring van de verrader?,Oppdrag utført? Har du forræderens ring?,Misja ukończona? Masz pierścień zdrajcy?,Missão cumprida? Está com o anel do traidor?,,Misiune îndeplinită? Ai inelul trădătorului?,Задание выполнено? Ты принёс кольцо предателя?,,Görev tamamlandı mı? Hainin yüzüğü sende mi? -"He's dead, where's my money?",TXT_RPLY0_SCRIPT02_D77316_HESDE,〃,,,"Je mrtvý, kde jsou moje peníze?","Han er død, hvor er mine penge?","Er ist tot, wo ist mein Geld?",,Mi mortigis lin. Kie estas mia mono?,Ya está muerto. ¿Y mi dinero?,,"Hän on kuollut, missä on rahani?","Il est mort, où est mon argent?","Meghalt, hol a pénzem?","Lui è morto, dove sono i miei soldi?",奴は死んだ、報酬はあるんだろうな?,"그는 죽었습니다, 제 보상은요?","Hij is dood, waar is mijn geld?","Han er død, hvor er pengene mine?",Jest martwy. Gdzie moje pieniądze?,"Ele está morto, cadê o meu dinheiro?",,"E mort, unde sunt banii?",Он мёртв. Где мои деньги?,,"O öldü, param nerede?" +",,"Jag garanterar 50 guld och om du återvänder utan att utlösa alla larm i staden finns chansen att tjäna mycket, mycket mer, och här är en liten hjälpreda som borde ge dig en fördel.","50 altın garanti ediyorum ve eğer kasabadaki tüm alarmları çalıştırmadan geri dönerseniz, çok daha fazlasını kazanma şansınız var ve işte size avantaj sağlayacak küçük bir yardımcı." +"Thanks, I'll need it.",TXT_RPLY0_SCRIPT02_D74284_THANK,〃,,,"Díky, budu ho potřebovat.","Tak, jeg får brug for den.","Danke, das werde ich brauchen.",,Dankon. Mi bezonos ĝin.,Gracias. Lo necesitaré.,Gracias. Lo voy a necesitar.,"Kiitos, tarvitsen sitä.","Merci, j'en aurais besoin.","Köszönöm, kelleni is fog.","Grazie, ne avrò bisogno.",ありがとよ、これは後々必要になるな。,고마워요. 도움이 될 것 같습니다.,"Bedankt, ik zal het nodig hebben.","Takk, jeg trenger det.",Dzięki. Będę go potrzebował.,"Obrigado, vou precisar.",,"Merci, voi avea nevoie de el.",Спасибо. Он мне пригодится.,,"Tack, jag kommer att behöva den.","Teşekkürler, ihtiyacım olacak." +"Good. Remember, his silence is golden.",TXT_DLG_SCRIPT02_D75800_GOODR,〃,,,"Dobře. Pamatuj, že jeho mlčení má cenu zlata.","Godt. Husk, at hans tavshed er guld.",Gut. Denke dran. Sein Schweigen ist Gold wert.,,Bone. Memoru: lia silento estas el oro.,Bien. Recuerda: su silencio es de oro.,,"Hyvä. Muista, että hänen vaikenemisensa on kultaa.",Bien. Souvenez-vous. Le silence est d'or.,"Remek, a hallgatása arany.","Bene. Ricorda, il suo silenzio è d'oro.",いいぞ。覚えておけ、彼が沈黙したら金だ。,천만에. 그리고 기억하게. 그를 입막음하는 게 유일한 희망일세.,"Goed. Vergeet niet, zijn stilte is goud waard.",Bra. Husk at hans taushet er gull verdt.,"Dobrze. Pamiętaj, jego cisza jest cenna.","Ótimo. Lembre-se, o silêncio dele vale ouro.",,"Bun. Reține, tăcerea e de aur.","Превосходно. Запомни, его молчание — золото.",,Bra. Kom ihåg att hans tystnad är av guld.,"Güzel. Unutma, onun sessizliği altındır." +I'll get him.,TXT_RPLY0_SCRIPT02_D75800_ILLGE,〃,,,Dostanu ho.,Jeg henter ham.,Ich krieg ihn.,,Mi trovos lin.,Lo encontraré.,Lo voy a encontrar.,Saan hänet.,Je m'occupe de lui.,Elintézem.,Lo vado a prendere.,始末してみせる。,그를 잡겠어요.,Ik krijg hem wel.,Jeg skal ta ham.,Dorwę go.,Vou pegá-lo.,,O să-l aduc.,Я прикончу его.,,Jag hämtar honom.,Onu yakalayacağım. +Mission accomplished? You have the ring of the traitor?,TXT_DLG_SCRIPT02_D77316_MISSI,〃,,,Mise splněna? Máš zrádcův prsten?,Mission fuldført? Har du forræderens ring?,Mission ausgeführt? Hast du den Ring des Verräters?,,Ĉu vi finis? Ĉu vi havas la ringon de la perfidulo?,¿Misión cumplida? ¿Tienes el anillo del traidor?,,Tehtävä suoritettu? Sinulla on petturin sormus?,Mission accomplie? Vous avez l'anneau du traître?,Sikeres küldetés? Nálad van az áruló gyűrűje?,Missione compiuta? Hai l'anello del traditore?,"任務完了か? +あの裏切り者の指輪は持っているんだろうな?",임무를 완수 한 건가? 배신자의 반지를 가지고 있어?,Missie volbracht? Heb je de ring van de verrader?,Oppdrag utført? Har du forræderens ring?,Misja ukończona? Masz pierścień zdrajcy?,Missão cumprida? Está com o anel do traidor?,,Misiune îndeplinită? Ai inelul trădătorului?,Задание выполнено? Ты принёс кольцо предателя?,,Uppdraget slutfört? Har du förrädarens ring?,Görev tamamlandı mı? Hainin yüzüğü sende mi? +"He's dead, where's my money?",TXT_RPLY0_SCRIPT02_D77316_HESDE,〃,,,"Je mrtvý, kde jsou moje peníze?","Han er død, hvor er mine penge?","Er ist tot, wo ist mein Geld?",,Mi mortigis lin. Kie estas mia mono?,Ya está muerto. ¿Y mi dinero?,,"Hän on kuollut, missä on rahani?","Il est mort, où est mon argent?","Meghalt, hol a pénzem?","Lui è morto, dove sono i miei soldi?",奴は死んだ、報酬はあるんだろうな?,"그는 죽었습니다, 제 보상은요?","Hij is dood, waar is mijn geld?","Han er død, hvor er pengene mine?",Jest martwy. Gdzie moje pieniądze?,"Ele está morto, cadê o meu dinheiro?",,"E mort, unde sunt banii?",Он мёртв. Где мои деньги?,,"Han är död, var är mina pengar?","O öldü, param nerede?" Liar! Go get the ring!,TXT_RNO0_SCRIPT02_D77316_LIARG,〃,,,Lháři! Jdi pro jeho prsten!,Løgner! Hent ringen!,Lügner! Hol' den Ring!,,"Ne mensongu! Forprenu lian ringon!","¡Mentiroso! ¡Ve a por el anillo!","¡Mentiroso! -¡Ve por el anillo!",Valehtelija! Mene hakemaan sormus!,Mensonges! Ramenez-moi l'anneau!,Hazug! Menj és szerezd meg a gyűrűt!,Bugiardo! Vai a prendere l'anello!,嘘をつくな、指輪を取ってこい!,거짓말쟁이! 가서 반지를 가져오게!,Leugenaar! Ga de ring halen!,Løgner! Hent ringen!,Kłamca! Idź po pierścień!,Mentiroso! Vá pegar o anel!,,Mincinos! Adu inelul!,Лжец! Принеси мне кольцо!,,Yalancı! Git yüzüğü al! +¡Ve por el anillo!",Valehtelija! Mene hakemaan sormus!,Mensonges! Ramenez-moi l'anneau!,Hazug! Menj és szerezd meg a gyűrűt!,Bugiardo! Vai a prendere l'anello!,嘘をつくな、指輪を取ってこい!,거짓말쟁이! 가서 반지를 가져오게!,Leugenaar! Ga de ring halen!,Løgner! Hent ringen!,Kłamca! Idź po pierścień!,Mentiroso! Vá pegar o anel!,,Mincinos! Adu inelul!,Лжец! Принеси мне кольцо!,,Lögnare! Hämta ringen!,Yalancı! Git yüzüğü al! "Here, you earned it. The traitor you killed was about to reveal the location of the Front. You saved lives. How would you like to earn more gold, and a future free from tyranny?",TXT_DLG_SCRIPT02_D78832_HEREY,〃,,,"Tady máš, zasloužil sis je. Zrádce, kterého jsi zabil, by vyzradil lokaci Fronty. Zachránil jsi životy. Jak by se ti líbilo vydělat si víc zlata spolu s budoucností bez tyranie?","Her, du har fortjent det. Den forræder, du dræbte, var ved at afsløre frontens placering. Du reddede liv. Hvad ville du sige til at tjene mere guld og en fremtid uden tyranni?","Hier, das hast du dir verdient. Der Verräter den du getötet hast war dabei über die Position der Front auszupacken. Du hast Leben gerettet. Wie würde es dir gefallen noch mehr Gold zu verdienen und eine tyrannenfreie Zukunft zu haben?",,"Jen ĝi, vi gajnis ĝin. La perfidulo, kiun vi mortigis, estis malkaŝonta la pozicion de la Fronto. Vi savis vivojn. Ĉu vi ŝatus gajni plian oron kaj estontecon liberan de tiranio?","Toma, te lo ganaste. El traidor que has matado estaba a punto de revelar la ubicación del Frente. Has salvado vidas. ¿Te gustaría ganar más oro y un futuro libre de tiranía?","Toma, te lo ganaste. El traidor que mataste estaba a punto de revelar la ubicación del Frente. Salvaste vidas. ¿Te gustaría ganar más oro y un futuro libre de tiranía?","Tässä, olet sen ansainnut. Tappamasi petturi oli lähellä paljastaa Rintaman sijainnin. Pelastit henkiä. Haluaisitko tienata lisää kultaa, ja tyranniasta vapaan tulevaisuuden?","Voilà, vous l'avez bien mérité. Ce traître que vous avez tué allait révéler la base du Front. Vous avez sauvé de nombreuses vies. Est-ce que ça vous intéresserait de vous faire plus d'argent et garantir un futur libre de la tyrannie?","Tessék, megérdemelted. Az áruló akit eltettél láb alól közel járt ahhoz, hogy felfedje a Front bázisát. Életeket mentettél. Mit szólnál ahhoz, ha még több arany is ütné a mancsod, és még egy zsarnok mentes jövőd is lenne?","Ecco qua, te li sei guadagnati. Il traditore che hai ucciso stava per rivelare il nascondiglio del Fronte. Hai salvato molte vite. Che ne diresti di guadagnare altro oro, e un futuro libero dalla tirannia?","よし、報酬はお前のものだ。お前が殺した あの裏切り者は、フロントの隠れ家をバラそうと していたんだ。おかげで大勢の命が救われた。 もっと多くの金と、奴等の支配から解放された -未来を得たいとは思わないか?",여기 보상일세. 그는 프론트의 비밀장소를 알리려던 참이었네. 자네가 우리들의 목숨을 구했어. 폭정을 타도해서 이처럼 더 많은 보상을 얻을 준비가 되어있나?,"Hier heb je het verdiend. De verrader die je vermoordde stond op het punt om de locatie van het Front te onthullen. Je hebt levens gered. Hoe zou je het vinden om meer goud te verdienen, en een toekomst vrij van tirannie?","Her, du har fortjent den. Forræderen du drepte var i ferd med å avsløre hvor Fronten er. Du reddet liv. Hva sier du til å tjene mer gull og en fremtid uten tyranni?","Masz, zasłużyłeś sobie. Zdrajca, którego zabiłeś zamierzał ujawnić gdzie znajduje się baza Frontu. Uratowałeś wiele żyć. Chcesz zarobić więcej pieniędzy i mieć przyszłość wolną od tyranii?","Tome, você merece. O traidor que você matou estava prestes a revelar a localização da Frente. Você salvou vidas. Que tal ganhar mais ouro e um futuro livre de tirania?",,"Aici, o meriți. Trădătorul pe care l-ai omorât urma să dezvăluie locația Frontului. Ai salvat vieți. Cum ai vrea să câștigi mai mult aur, și un viitor fără tiranie?","Вот, ты их заслужил. Убитый тобой предатель мог выдать Ордену местоположение базы Сопротивления. Ты спас много жизней. Тебе бы не хотелось ещё золота и будущего, свободного от тирании?",,"İşte, onu hak ettin. Öldürdüğün hain Cephe'nin yerini açıklamak üzereydi. Hayat kurtardın. Daha fazla altın ve zorbalıktan uzak bir gelecek kazanmaya ne dersin?" -Tell me more.,TXT_RPLY0_SCRIPT02_D78832_TELLM,〃,,,Řekni mi víc.,Fortæl mig mere.,Erzähl mir mehr.,,Mi aŭskultas vin.,Dime más.,,Kerro lisää.,Dites-moi en plus.,Mesélj még.,Dimmi di più.,もっと教えてくれ。,더 말해주시오.,Vertel me meer.,Fortell meg mer.,Mów dalej.,Me conte mais.,,Spune-mi mai multe.,Расскажи мне больше.,,Biraz daha anlat. -Not my style.,TXT_RPLY1_SCRIPT02_D78832_NOTMY,〃,,,To není můj styl.,Ikke min stil.,Nicht mein Stil.,,Tio ne estas mia stilo.,No es mi estilo.,,Ei kuulu tyyliini.,Pas mon genre.,Nem az Én stílusom.,Non fa per me.,俺の趣味じゃないな。,내 취향은 아닌데.,Niet mijn stijl.,Ikke min stil.,To nie w moim stylu.,Não faz o meu estilo.,,Nu-i genul meu.,Не в моём вкусе.,,Benim tarzım değil. -"I have a business relationship with the Front's leader, Macil. I know he needs an incisive fellow like yourself, and he pays well. Take this recovered com unit and you'll be led to, shall we say, opportunities.",TXT_DLG_SCRIPT02_D80348_IHAVE,〃,,,"Mám obchodní vztah s vůdcem Fronty, Macilem. Vím, že potřebuje schopného člověka jako ty a dobře platí. Vem si tenhle spravený komunikátor; zavede tě k, řekněme, příležitostem.","Jeg har et forretningsmæssigt forhold til frontens leder, Macil. Jeg ved, han har brug for en skarp fyr som dig, og han betaler godt. Tag denne genvundne com-enhed, og du vil blive ført til, skal vi sige, muligheder.","Ich habe Geschäftsbeziehungen mit dem Anführer der Front, Macil. Er braucht einen pfiffigen Typen wie dich und er bezahlt gut. Nimm dieses erbeutete Kommunikationsgerät und es wird dich zu, sagen wir mal, Möglichkeiten führen.",,"Mi havas negoco-ligon kun Macil, la frontestro. Mi scias, ke li bezonas lertan kunulon kiel vi, aldone al tio, ke li pagas bone. Prenu ĉi tiun rekuperitan interfonon kaj vi havos la vojon al... ni diru, ŝancoj.","Tengo una relación de negocios con Macil, el líder del Frente. Sé que necesita un compañero hábil como tú, además de que paga bien. Toma este intercomunicador recuperado para que te guíe a... digamos, oportunidades.",,"Minulla on liikesuhteita Rintaman johtaja Maciliin. Tiedän hänen tarvitsevan kaltaistasi terävää kaveria, ja hän maksaa hyvin. Ota tämä talteenkerätty viestintälaite, ja tiesi johtaa, sanottaisiinko, mahdollisuuksien äärelle.","J'ai une relation d'affaires avec le leader du Front, Macil. Je sais qu'il a besoin de quelqu'un d'incisif comme vous, et il paye bien. Prenez ce communicateur avec vous, et vous serez mené à des.. on va dire des opportunités.","Van egy üzleti megállapodásom Macil-lal, a Front vezetőjével. pont egy ilyen belevaló embert keres mint te, és kiváló fizetést is adna. Használd ezt a kommunikációs egységet és - mondjuk úgy - odavezet a lehetőségekhez.","Ho dei rapporti d'affari col capo del Fronte, Macil. So che è alla ricerca di una persona diretta e precisa come te, e lui paga molto bene. Tieni questa unità di comunicazione che abbiamo recuperato, e sarai condotto verso, come dire, nuove opportunità.","私はフロントのリーダー、マシルと取引を +未来を得たいとは思わないか?",여기 보상일세. 그는 프론트의 비밀장소를 알리려던 참이었네. 자네가 우리들의 목숨을 구했어. 폭정을 타도해서 이처럼 더 많은 보상을 얻을 준비가 되어있나?,"Hier heb je het verdiend. De verrader die je vermoordde stond op het punt om de locatie van het Front te onthullen. Je hebt levens gered. Hoe zou je het vinden om meer goud te verdienen, en een toekomst vrij van tirannie?","Her, du har fortjent den. Forræderen du drepte var i ferd med å avsløre hvor Fronten er. Du reddet liv. Hva sier du til å tjene mer gull og en fremtid uten tyranni?","Masz, zasłużyłeś sobie. Zdrajca, którego zabiłeś zamierzał ujawnić gdzie znajduje się baza Frontu. Uratowałeś wiele żyć. Chcesz zarobić więcej pieniędzy i mieć przyszłość wolną od tyranii?","Tome, você merece. O traidor que você matou estava prestes a revelar a localização da Frente. Você salvou vidas. Que tal ganhar mais ouro e um futuro livre de tirania?",,"Aici, o meriți. Trădătorul pe care l-ai omorât urma să dezvăluie locația Frontului. Ai salvat vieți. Cum ai vrea să câștigi mai mult aur, și un viitor fără tiranie?","Вот, ты их заслужил. Убитый тобой предатель мог выдать Ордену местоположение базы Сопротивления. Ты спас много жизней. Тебе бы не хотелось ещё золота и будущего, свободного от тирании?",,"Här, du har förtjänat den. Förrädaren du dödade skulle avslöja var fronten finns. Du räddade liv. Hur skulle du vilja tjäna mer guld och en framtid fri från tyranni?","İşte, onu hak ettin. Öldürdüğün hain Cephe'nin yerini açıklamak üzereydi. Hayat kurtardın. Daha fazla altın ve zorbalıktan uzak bir gelecek kazanmaya ne dersin?" +Tell me more.,TXT_RPLY0_SCRIPT02_D78832_TELLM,〃,,,Řekni mi víc.,Fortæl mig mere.,Erzähl mir mehr.,,Mi aŭskultas vin.,Dime más.,,Kerro lisää.,Dites-moi en plus.,Mesélj még.,Dimmi di più.,もっと教えてくれ。,더 말해주시오.,Vertel me meer.,Fortell meg mer.,Mów dalej.,Me conte mais.,,Spune-mi mai multe.,Расскажи мне больше.,,Berätta mer.,Biraz daha anlat. +Not my style.,TXT_RPLY1_SCRIPT02_D78832_NOTMY,〃,,,To není můj styl.,Ikke min stil.,Nicht mein Stil.,,Tio ne estas mia stilo.,No es mi estilo.,,Ei kuulu tyyliini.,Pas mon genre.,Nem az Én stílusom.,Non fa per me.,俺の趣味じゃないな。,내 취향은 아닌데.,Niet mijn stijl.,Ikke min stil.,To nie w moim stylu.,Não faz o meu estilo.,,Nu-i genul meu.,Не в моём вкусе.,,Inte min stil.,Benim tarzım değil. +"I have a business relationship with the Front's leader, Macil. I know he needs an incisive fellow like yourself, and he pays well. Take this recovered com unit and you'll be led to, shall we say, opportunities.",TXT_DLG_SCRIPT02_D80348_IHAVE,〃,,,"Mám obchodní vztah s vůdcem Fronty, Macilem. Vím, že potřebuje schopného člověka jako ty a dobře platí. Vem si tenhle spravený komunikátor; zavede tě k, řekněme, příležitostem.","Jeg har et forretningsmæssigt forhold til frontens leder, Macil. Jeg ved, han har brug for en skarp fyr som dig, og han betaler godt. Tag denne genvundne com-enhed, og du vil blive ført til, skal vi sige, muligheder.","Ich habe Geschäftsbeziehungen mit dem Anführer der Front, Macil. Er braucht einen pfiffigen Typen wie dich und er bezahlt gut. Nimm dieses erbeutete Kommunikationsgerät und es wird dich zu, sagen wir mal, Möglichkeiten führen.",,"Mi havas negoco-ligon kun Macil la frontestro. Mi scias, ke li bezonas lertan kunulon kiel vi, aldone al tio, ke li pagas bone. Prenu ĉi tiun rekuperitan interfonon kaj vi havos la vojon al... ni diru, ŝancoj.","Tengo una relación de negocios con Macil el líder del Frente. Sé que necesita un compañero hábil como tú, además de que paga bien. Toma este intercomunicador recuperado para que te guíe a... digamos, oportunidades.",,"Minulla on liikesuhteita Rintaman johtaja Maciliin. Tiedän hänen tarvitsevan kaltaistasi terävää kaveria, ja hän maksaa hyvin. Ota tämä talteenkerätty viestintälaite, ja tiesi johtaa, sanottaisiinko, mahdollisuuksien äärelle.","J'ai une relation d'affaires avec le leader du Front, Macil. Je sais qu'il a besoin de quelqu'un d'incisif comme vous, et il paye bien. Prenez ce communicateur avec vous, et vous serez mené à des.. on va dire des opportunités.","Van egy üzleti megállapodásom Macil-lal, a Front vezetőjével. pont egy ilyen belevaló embert keres mint te, és kiváló fizetést is adna. Használd ezt a kommunikációs egységet és - mondjuk úgy - odavezet a lehetőségekhez.","Ho dei rapporti d'affari col capo del Fronte, Macil. So che è alla ricerca di una persona diretta e precisa come te, e lui paga molto bene. Tieni questa unità di comunicazione che abbiamo recuperato, e sarai condotto verso, come dire, nuove opportunità.","私はフロントのリーダー、マシルと取引を しているんだ。彼は君のような切れる人物を 必要としていて、金払いも良い。 この修理された無線機を持っていけば、 -好機に出会えるだろう。","나는 프론트의 사령관, 마실과 깊은 관계를 가지고 있다네. 그리고 그는 자네를 비롯한 예리한 사람들을 원하고 말이지. 그리고 보상도 아주 잘 준다네. 이 수리된 통신기를 받고 이동하게나. 그럼 희망은 물론 기회가 아주 많아질 거야.","Ik heb een zakelijke relatie met de leider van het Front, Macil. Ik weet dat hij een scherpzinnige kerel als jij nodig heeft, en hij betaalt goed. Neem deze herstelde com-unit en u zult worden geleid tot, laten we zeggen, kansen.","Jeg har et forretningsforhold til Frontens leder, Macil. Jeg vet at han trenger en skarp fyr som deg, og han betaler godt. Ta denne gjenfunne kommunikasjonsenheten og du vil bli ledet til, skal vi si, muligheter.","Mam relacje biznesowe z dowódcą Frontu, Macilem. Wiem, że potrzebuje on kogoś z takim zapałem jak ty, i dobrze płaci. Weź ten komunikator, a poprowadzi cię do, powiedzmy, pewnych korzyści.","Tenho uma relação de negócios com o líder da Frente, Macil. Eu sei que ele anda precisando de um sujeito incisivo como você e ele paga bem. Leve este comunicador e você será conduzido para, digamos, oportunidades.",,"Fac afaceri cu liderul Frontului, Macil. Știu că are nevoie de băieți deștepți ca tine, și plătește bine. Ia acest emițător recuperat și vei fi dus, să zicem, spre oportunități.","Я веду дела c лидером повстанцев, Мэйсилом. Я знаю, что ему нужны толковые парни вроде тебя, и он неплохо платит. Возьми этот передатчик, и перед тобой откроются, скажем так, новые перспективы.",,"Cephe'nin lideri Macil ile bir iş ilişkim var. Senin gibi keskin zekalı bir adama ihtiyacı olduğunu biliyorum ve iyi para ödüyor. Bu kurtarılmış iletişim birimini alın ve size, diyelim ki, fırsatlar sunulacak." -Thanks.,TXT_RPLY0_SCRIPT02_D80348_THANK,〃,,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,알겠어요.,Bedankt.,Takk skal du ha.,Dzięki.,Obrigado.,,Mulțumesc.,Спасибо.,,Teşekkürler. +好機に出会えるだろう。","나는 프론트의 사령관, 마실과 깊은 관계를 가지고 있다네. 그리고 그는 자네를 비롯한 예리한 사람들을 원하고 말이지. 그리고 보상도 아주 잘 준다네. 이 수리된 통신기를 받고 이동하게나. 그럼 희망은 물론 기회가 아주 많아질 거야.","Ik heb een zakelijke relatie met de leider van het Front, Macil. Ik weet dat hij een scherpzinnige kerel als jij nodig heeft, en hij betaalt goed. Neem deze herstelde com-unit en u zult worden geleid tot, laten we zeggen, kansen.","Jeg har et forretningsforhold til Frontens leder, Macil. Jeg vet at han trenger en skarp fyr som deg, og han betaler godt. Ta denne gjenfunne kommunikasjonsenheten og du vil bli ledet til, skal vi si, muligheter.","Mam relacje biznesowe z dowódcą Frontu, Macilem. Wiem, że potrzebuje on kogoś z takim zapałem jak ty, i dobrze płaci. Weź ten komunikator, a poprowadzi cię do, powiedzmy, pewnych korzyści.","Tenho uma relação de negócios com o líder da Frente, Macil. Eu sei que ele anda precisando de um sujeito incisivo como você e ele paga bem. Leve este comunicador e você será conduzido para, digamos, oportunidades.",,"Fac afaceri cu liderul Frontului, Macil. Știu că are nevoie de băieți deștepți ca tine, și plătește bine. Ia acest emițător recuperat și vei fi dus, să zicem, spre oportunități.","Я веду дела c лидером повстанцев, Мэйсилом. Я знаю, что ему нужны толковые парни вроде тебя, и он неплохо платит. Возьми этот передатчик, и перед тобой откроются, скажем так, новые перспективы.",,"Jag har en affärsrelation med frontens ledare, Macil. Jag vet att han behöver en skarpsinnig kille som du, och han betalar bra. Ta den här återvunna kom-enheten och du kommer att ledas till, ska vi säga, möjligheter.","Cephe'nin lideri Macil ile bir iş ilişkim var. Senin gibi keskin zekalı bir adama ihtiyacı olduğunu biliyorum ve iyi para ödüyor. Bu kurtarılmış iletişim birimini alın ve size, diyelim ki, fırsatlar sunulacak." +Thanks.,TXT_RPLY0_SCRIPT02_D80348_THANK,〃,,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,알겠어요.,Bedankt.,Takk skal du ha.,Dzięki.,Obrigado.,,Mulțumesc.,Спасибо.,,Tack.,Teşekkürler. "Get going. If you hang around here, we're both dead.",TXT_DLG_SCRIPT02_D81864_GETGO,〃,,,"Měl bys jít. Jestli se tu budeš potloukat, jsme mrtví oba.","Kom i gang. Hvis du bliver hængende her, er vi begge døde.","Beweg dich. Wenn wir beide hier rumhängen, dann sind wir beide tot.",,"Ekmovu vin. Se vi restos ĉi tie, ni ambaŭ mortos.","Ponte en marcha. Si te quedas por aquí, los dos estamos muertos.",,"Jatka matkaasi. Jos viivyttelet täällä, kuolemme molemmat.","Partez maintenant, si vous traînez ici, nous serons morts tous les deux.","Mozgás! Ha sokáig lébucolsz itt, mindkettőnket megölnek.","Ti conviene andartene. Se bazzichi troppo qua, siamo entrambi morti.","うまくやれよ。こんな所でもたもたしていると -二人揃ってお陀仏だ。","어서 가게. 여기에 계속 있으면, 우리 둘 다 죽는다네.","Ga aan de slag. Als je hier rondhangt, zijn we allebei dood.","Sett i gang. Hvis du blir her, er vi begge døde.",Rusz się. Jak będziesz się tu kręcił to obaj będziemy martwi.,"Ande logo. Se você ficar por aqui, nós dois seremos mortos.",,"Timpul să pleci. Dacă mai stai pe-aici, o să fim amândoi morți.","Двигай. Если продолжишь тут ошиваться, нас обоих убьют.",,"Gidin hadi. Eğer burada takılırsan, ikimiz de ölürüz." +二人揃ってお陀仏だ。","어서 가게. 여기에 계속 있으면, 우리 둘 다 죽는다네.","Ga aan de slag. Als je hier rondhangt, zijn we allebei dood.","Sett i gang. Hvis du blir her, er vi begge døde.",Rusz się. Jak będziesz się tu kręcił to obaj będziemy martwi.,"Ande logo. Se você ficar por aqui, nós dois seremos mortos.",,"Timpul să pleci. Dacă mai stai pe-aici, o să fim amândoi morți.","Двигай. Если продолжишь тут ошиваться, нас обоих убьют.",,Sätt igång. Om du stannar här är vi båda döda.,"Gidin hadi. Eğer burada takılırsan, ikimiz de ölürüz." "A pity, but now that you know about my friends, I must kill you. Guards, take out this trash!",TXT_DLG_SCRIPT02_D83380_APITY,〃,,,"Škoda. Teď, když víš o mých známých, tě ale musím zabít. Stráže, zbavte mě tohohle smetí!","En skam, men nu hvor du kender til mine venner, må jeg slå dig ihjel. Vagter, tag det affald ud!","Ein Jammer, aber nun, da du über meine Freunde Bescheid weißt, muss ich dich umbringen. Wachen? Entsorgt ihn!",,"Nun kiam vi scias pri miaj amikoj, mi bedaŭrinde devas mortigi vin. Gardistoj, forprenu ĉi tiun rubon!","Una lástima, pero ahora que sabes de mis amigos, no me queda de otra que matarte. ¡Guardias, a sacar la basura!","Una pena, pero ahora que sabes de mis amigos, no me queda de otra que matarte. ¡Guardias, a sacar la basura!","Sääli, mutta nyt, kun tiedät ystävistäni, minun on tapettava sinut. Vartijat, heittäkää tämä roska ulos!","Dommage. Mais maintenant que vous savez qui sont mes amis, je dois me débarasser de vous. Garde, débarassez moi de mes ordures!","Kár érted, de sajnos miután kiderítetted a barátaim kilétét, meg kell hogy halj. Őrök, vigyétek ki ezt a szemetet!","Un vero peccato, ma ora che sai dei miei amici, non posso certo lasciarti vivo. Guardie, buttate via questa spazzatura!","残念だ、だがお前は私の友の事を知った以上 生きて帰す事はできない。 -衛兵、このゴミを片付けてくれ!","유감이군. 내 친구들을 이제 알고 있으니, 어쩔 수 없이 죽어줘야겠군. 경비병! 이 인간을 체포하라!","Jammer, maar nu je van mijn vrienden weet, moet ik je vermoorden. Bewakers, haal dit vuilnis eruit!","Synd, men nå som du vet om vennene mine, må jeg drepe deg. Vakter, ta ut dette søppelet!","Szkoda, ale skoro wiesz coś o moich przyjaciołach, muszę cię zabić. Straż, wyrzućcie tego śmiecia!","É uma pena, mas agora que você sabe sobre os meus amigos, preciso matar você. Guardas, levem esse lixo daqui!",,"Păcat, dar acum că-mi cunoști prietenii, voi fi nevoit să te omor. Gardieni, duceți gunoiul!","Жаль, но раз уж ты узнал о моих друзьях, мне придётся тебя убить. Стража, уберите его!",,"Yazık, ama artık arkadaşlarımı bildiğine göre, seni öldürmeliyim. Muhafızlar, şu çöpü dışarı çıkarın!" -Fool. Guards! Rid me of meddlesome peon.,TXT_DLG_SCRIPT02_D84896_FOOLG,〃,,,"Blázne! Stráže, zbavte se tohohle zbytečného nuzáka.",Fjols. Vagter! Fjern den besværlige bondeknold fra mig.,Du Narr! Wachen! Entledigt mich von diesem lästigen Tagelöhner.,,"Stultulo! Gardistoj, liberigu min de ĉi tiu entrudiĝema peono.","¡Insensato! Guardias, libérenme de este entrometido peón.","¡Tonto! Guardias, libérenme de este entrometido peón.",Järjetöntä. Vartijat! Hankkiutukaa eroon tästä tungettelevasta moukasta.,"Idiot! Gardes, débarassez-moi de ce pion embêtant!","Barom! Őrök, takarítsátok el a színem elől ezt a kotnyeleskedő pondrót!","Sciocco! Guardie, liberatemi da questo ficcanaso.","愚かな。 -衛兵!この厄介な奴を始末してくれ。","한심한 놈! 경비병, 이 소동피우는 불량배를 잡아라.",Dwaas. Bewakers! Verloste me van bemoeizuchtige pioen.,Idiot. Vakter! Kvitt meg med den innpåslitne bondetampen.,Głupcze! Straż! Uwolnijcie mnie od tego wścibskiego robola.,"Idiota! Guardas, tirem esse peão intrometido daqui.",,"Prostule! Gardieni, scăpați-mă de acest pion băgăreț.","Глупец! Стража, избавьте меня от этого недоумка.",,Aptal. Muhafızlar! Beni işgüzar piyondan kurtarın. -"Walk away, boy, just walk away.",TXT_DLG_SCRIPT02_D86412_WALKA,Geoff.,,,"Jdi pryč, chlapče, prostě odejdi.","Gå væk, dreng, bare gå væk.","Geh weg Jungchen, geh einfach weg.",,"Foriru, ulo. Vi nur foriru.","Vete, chaval. Solo vete.","Vete, muchacho. Solo vete.","Kävele pois vain, poju, kävele pois.","Pars, gamin, pars.","Csak sétálj el innen, sétálj el szépen.","Muoviti, ragazzo, muoviti...",どっか行け、若造、とっとと行け。,"지나가라고 친구, 그냥 지나가.","Loop weg, jongen, loop gewoon weg.","Gå vekk, gutt, bare gå vekk.","Odejdź stąd mały, po prostu odejdź.","Suma daqui, garoto. Apenas suma daqui.",,"Pleacă, băiete, pleacă.","Иди своей дорогой, парень, иди.",,"Yürü git evlat, yürü git." -What are you doing here?,TXT_DLG_SCRIPT02_D87928_WHATA,〃,,,Co ty tu děláš?,Hvad laver du her?,Was machst du hier?,,Kion vi volas ĉi tie?,¿Qué es lo que quieres?,,Mitäs sinä täällä teet?,Qu'est-ce que vous foutez ici?,Mit művelsz itt?,Che cosa fai qua?,ここで何をしている?,여기서 뭘 하는거야?,Wat doe jij hier?,Hva gjør du her?,Co ty tu robisz?,O que você está fazendo aqui?,,Ce cauți aici?,Что ты тут делаешь?,,Ne yapıyorsun burada? -"Hey, I need gold!",TXT_RPLY0_SCRIPT02_D87928_HEYIN,〃,,,"Hej, potřeboval bych zlato!","Hey, jeg har brug for guld!","Hey, ich brauche Gold!",,"Saluton, mi bezonas oron!","¡Buenas, necesito oro!",,"Hei, tarvitsen kultaa!","Hé, j'ai besoin de sous!","Héj, nekem arany kell!","Ehi, mi serve dell'oro!",よう、金が必要だ!,"이봐, 난 골드가 필요해!","Hé, ik heb goud nodig!",Jeg trenger gull!,"Hej, potrzebuję złota!","Ei, eu preciso de ouro!",,"Hei, am nevoie de aur!","Эй, мне нужно золото!",,"Hey, altına ihtiyacım var!" -"Blackbird told you the code, huh? Let me shut off the alarm. Macil is one flight down.",TXT_DLG_SCRIPT02_D89444_BLACK,〃,,,"Straka ti řekla heslo, co? Jen vypnu alarmy. Macil je o podlaží níž.","Blackbird fortalte dig koden, hva'? Lad mig slukke for alarmen. Macil er en etage længere nede.","Blackbird hat dir den Code gegeben, wie? Lass mich mal eben den Alarm abschalten. Macil ist eine Etage tiefer.",,"BlackBird diris la pasfrazon al vi, ĉu? Tiuokaze mi sensonorigos la alarmon. Macil estas malsupre.","Conque BlackBird te ha dado la clave, ¿eh? Ya apago la alarma, entonces. Macil está bajando las escaleras.","Así que BlackBird te dio la clave, ¿eh? Ya apago la alarma, entonces. Macil está bajando las escaleras.","Vai että Blackbird kertoi sinulle koodin? Anna, kun kytken hälyttimen pois päältä. Macil on yhdet rappuset alas.","Blackbird t'as donné le code, hein? Bon, laisse moi désactiver l'alarme. Macil est en bas des escaliers.","Feketerigó mondta el a kódot, mi? Hadd kapcosljam ki a riasztót. macil egy kőhajintásra van innen.","Blackbird ti ha detto qual'è il codice, eh? Fammi disattivare l'allarme. Macil è oltre le scale.","ブラックバードに教えてもらったんだな? -警報は切っておこう。マシルはこの先だ。","블랙버드가 암호를 알려줬나 보군? 흠, 그럼 경보를 꺼둬야겠군. 마실은 계단 저 밑에 있어.","Blackbird vertelde je de code, huh? Laat me de wekker uitzetten. Macil is een vlucht naar beneden.",Fortalte Blackbird deg koden? La meg slå av alarmen. Macil er en etasje ned.,"Blackbird podała ci hasło, co? Pozwól, że wyłączę alarm. Macil jest piętro niżej.","A Blackbird te passou o código, é? Deixa eu desligar o alarme. Macil está no andar debaixo.",,"Blackbird ți-a spus codul, huh? Permite-mi să opresc alarma, Macil e cu un etaj mai jos.","«Чёрный дрозд» сообщила тебе пароль, так? Давай я отключу сигнализацию. Мэйсил этажом ниже.",,"Karatavuk sana kodu söyledi, ha? Alarmı kapatayım. Macil bir kat aşağıda." -Thanks.,TXT_RPLY0_SCRIPT02_D89444_THANK,〃,,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,고맙다.,Bedankt.,Takk skal du ha.,Dzięki.,Obrigado.,,Mulțumesc.,Спасибо.,,Teşekkürler. -"Walk away, boy, just walk away.",TXT_DLG_SCRIPT02_D90960_WALKA,〃,,,"Jdi pryč, chlapče, prostě odejdi.","Gå væk, knægt, bare gå væk.","Geh weg Jungchen, geh einfach weg.",,"Foriru, ulo. Vi nur foriru.","Vete, chaval. Solo vete.","Vete, muchacho. Solo vete.","Kävele pois vain, poju, kävele pois.","Pars, gamin, pars.","Csak sétálj el innen, sétálj el szépen.","Muoviti, ragazzo, muoviti...",向こうへ行け、新入り、急ぐんだ。,"지나가라고 친구, 그냥 지나가.","Loop weg, jongen, loop gewoon weg.","Gå vekk, gutt. Bare gå vekk.","Odejdź stąd mały, po prostu odejdź.","Suma daqui, garoto. Apenas suma daqui.",,"Pleacă, băiete, pleacă.","Иди своей дорогой, парень, иди.",,"Yürü git evlat, yürü git." -Do you have an appointment with the Governor? ,TXT_DLG_SCRIPT02_D92476_DOYOU,Arion.,,,Máte domluvený termín schůzky s guvernérem?,Har du en aftale med guvernøren?,Hast du einen Termin bei dem Gouverneur?,,Ĉu vi supozeble havas rendevuon kun la registo?,¿Acaso tienes una cita con el gobernador?,,Onko teillä varattu tapaaminen kuvernöörin kanssa?,Avez-vous un rendez-vous avec le gouverneur?,Van időpontod a kormányzóval?,Hai un appuntamento con il governatore?,知事とアポイントメントは取ってますか?,총독과 약속이 있으십니까?,Heb je een afspraak met de gouverneur?,Har du en avtale med guvernøren?,Masz spotkanie z Gubernatorem?,Você tem hora marcada com o Governador?,,Ai o programare cu Guvernatorul?,У Вас назначена встреча с губернатором?,,Vali ile randevunuz var mı? -Of course!,TXT_RPLY0_SCRIPT02_D92476_OFCOU,〃,,,Samozřejmě!,"Ja, selvfølgelig!",Natürlich!,,Kompreneble!,¡Por supuesto!,,Totta kai!,Bien sûr!,Persze!,Certo!,問題ない!,당연하지!,Natuurlijk!,Selvsagt!,Oczywiście!,Claro que sim!,,Desigur!,Конечно!,,Tabii ki var! -"No, and I don't need one!",TXT_RPLY1_SCRIPT02_D92476_NOAND,〃,,,Ne a žádný nepotřebuju!,"Nej, og jeg har ikke brug for en!","Nein, und ich brauche auch keinen!",,"Ne, kaj mi ne bezonas ĝin!",¡No y no la necesito!,,"Ei, enkä sellaista tarvitsekaan!","Non, et j'en ai pas besoin!","Nincs, és nem is kell!","No, e non ne ho bisogno!",いや、必要ない!,아니. 없는데?,"Nee, en die heb ik niet nodig!","Nei, og jeg trenger ingen!","Nie mam, i nie chcę mieć!",Não e eu não preciso de hora marcada!,,"Nu, nici n-am nevoie de una!","Нет, и я в ней не нуждаюсь!",,"Hayır, ihtiyacım da yok!" -Sorry! I didn't mean... Please go right up.,TXT_DLG_SCRIPT02_D93992_SORRY,〃,,,"Pardon! Nechtěl jsem... jeďte tady nahoru, prosím.",Undskyld! Jeg mente ikke... Vær venlig at gå op.,Entschuldigung! Das war nicht so gemeint... Bitte geh durch.,,"Ha, pardonon; mi ne intencis... Uzu la lifton.","Ah, perdón; no quería... Ve al piso de arriba.",,"Pahoittelut! En tarkoittanut... Menkää suoraan ylös, olkaa hyvä.","Désolé, je.. Vous pouvez monter, bien sûr.",Elnézést! Nem akartam...kérem menjen fel az emeletre.,Scusa! Non intendevo... Vai al piano di sopra.,"すいません!知らずに... -そのまま上がって下さい。",이런! 기다리게 할 생각은 없었는데... 부디 위로 올라가시길 바랍니다.,Sorry! Ik bedoelde niet.... Ga alsjeblieft meteen naar boven.,Unnskyld! Unnskyld! Jeg mente ikke... Vær så snill å gå opp.,"Przepraszam! Nie chciałem... Proszę, idź na górę.",Desculpe! Eu não queria... Por favor pode subir.,,"Scuze! Te rog, poftește sus.","Простите! Я не думал... Пожалуйста, проходите наверх.",,Özür dilerim! Öyle demek istemedim. Lütfen yukarı çıkın. -I knew you'd say that.,TXT_RPLY0_SCRIPT02_D93992_IKNEW,〃,,,"Věděl jsem, že to řekneš.","Jeg vidste, at du ville sige det.","Ich dachte mir schon, das du das sagen würdest.",,"Mi sciis, ke vi dirus tion.",Sabía que dirías eso.,Sabía que ibas a decir eso.,"Arvasin, että sanoisit noin.",Je savais que vous diriez ceci.,"Tudtam, hogy ezt mondod.",Sapevo che l'avresti detto.,そう言うと思った。,그렇게 말할 줄 알았어.,Ik wist dat je dat zou zeggen.,Jeg visste du ville si det.,"Wiedziałem, że to powiesz.",Eu sabia que você diria isso.,,Știam că vei spune asta.,"Я знал, что ты это скажешь.",,Bunu söyleyeceğini biliyordum. +衛兵、このゴミを片付けてくれ!","유감이군. 내 친구들을 이제 알고 있으니, 어쩔 수 없이 죽어줘야겠군. 경비병! 이 인간을 체포하라!","Jammer, maar nu je van mijn vrienden weet, moet ik je vermoorden. Bewakers, haal dit vuilnis eruit!","Synd, men nå som du vet om vennene mine, må jeg drepe deg. Vakter, ta ut dette søppelet!","Szkoda, ale skoro wiesz coś o moich przyjaciołach, muszę cię zabić. Straż, wyrzućcie tego śmiecia!","É uma pena, mas agora que você sabe sobre os meus amigos, preciso matar você. Guardas, levem esse lixo daqui!",,"Păcat, dar acum că-mi cunoști prietenii, voi fi nevoit să te omor. Gardieni, duceți gunoiul!","Жаль, но раз уж ты узнал о моих друзьях, мне придётся тебя убить. Стража, уберите его!",,"Synd, men nu när du vet om mina vänner måste jag döda dig. Vakter, ta ut det här skräpet!","Yazık, ama artık arkadaşlarımı bildiğine göre, seni öldürmeliyim. Muhafızlar, şu çöpü dışarı çıkarın!" +Fool. Guards! Rid me of meddlesome peon.,TXT_DLG_SCRIPT02_D84896_FOOLG,〃,,,"Blázne! Stráže, zbavte se tohohle zbytečného nuzáka.",Fjols. Vagter! Fjern den besværlige bondeknold fra mig.,Du Narr! Wachen! Entledigt mich von diesem lästigen Tagelöhner.,,"Stultulo! Gardistoj, liberigu min de ĉi tiu entrudiĝema peono.","¡Insensato! Guardias, libérenme de este entrometido peón.","¡Idiota! Guardias, libérenme de este entrometido peón.",Järjetöntä. Vartijat! Hankkiutukaa eroon tästä tungettelevasta moukasta.,"Idiot! Gardes, débarassez-moi de ce pion embêtant!","Barom! Őrök, takarítsátok el a színem elől ezt a kotnyeleskedő pondrót!","Sciocco! Guardie, liberatemi da questo ficcanaso.","愚かな。 +衛兵!この厄介な奴を始末してくれ。","한심한 놈! 경비병, 이 소동피우는 불량배를 잡아라.",Dwaas. Bewakers! Verloste me van bemoeizuchtige pioen.,Idiot. Vakter! Kvitt meg med den innpåslitne bondetampen.,Głupcze! Straż! Uwolnijcie mnie od tego wścibskiego robola.,"Idiota! Guardas, tirem esse peão intrometido daqui.",,"Prostule! Gardieni, scăpați-mă de acest pion băgăreț.","Глупец! Стража, избавьте меня от этого недоумка.",,Dumbom. Vakter! Befria mig från den besvärliga pingsten.,Aptal. Muhafızlar! Beni işgüzar piyondan kurtarın. +"Walk away, boy, just walk away.",TXT_DLG_SCRIPT02_D86412_WALKA,Geoff.,,,"Jdi pryč, chlapče, prostě odejdi.","Gå væk, dreng, bare gå væk.","Geh weg Jungchen, geh einfach weg.",,"Foriru, ulo. Vi nur foriru.","Vete, chaval. Solo vete.","Vete, muchacho. Solo vete.","Kävele pois vain, poju, kävele pois.","Pars, gamin, pars.","Csak sétálj el innen, sétálj el szépen.","Muoviti, ragazzo, muoviti...",どっか行け、若造、とっとと行け。,"지나가라고 친구, 그냥 지나가.","Loop weg, jongen, loop gewoon weg.","Gå vekk, gutt, bare gå vekk.","Odejdź stąd mały, po prostu odejdź.","Suma daqui, garoto. Apenas suma daqui.",,"Pleacă, băiete, pleacă.","Иди своей дорогой, парень, иди.",,"Gå iväg, pojke, bara gå iväg.","Yürü git evlat, yürü git." +What are you doing here?,TXT_DLG_SCRIPT02_D87928_WHATA,〃,,,Co ty tu děláš?,Hvad laver du her?,Was machst du hier?,,Kion vi volas ĉi tie?,¿Qué es lo que quieres?,,Mitäs sinä täällä teet?,Qu'est-ce que vous foutez ici?,Mit művelsz itt?,Che cosa fai qua?,ここで何をしている?,여기서 뭘 하는거야?,Wat doe jij hier?,Hva gjør du her?,Co ty tu robisz?,O que você está fazendo aqui?,,Ce cauți aici?,Что ты тут делаешь?,,Vad gör du här?,Ne yapıyorsun burada? +"Hey, I need gold!",TXT_RPLY0_SCRIPT02_D87928_HEYIN,〃,,,"Hej, potřeboval bych zlato!","Hey, jeg har brug for guld!","Hey, ich brauche Gold!",,"Saluton, mi bezonas oron!","¡Buenas, necesito oro!",,"Hei, tarvitsen kultaa!","Hé, j'ai besoin de sous!","Héj, nekem arany kell!","Ehi, mi serve dell'oro!",よう、金が必要だ!,"이봐, 난 골드가 필요해!","Hé, ik heb goud nodig!",Jeg trenger gull!,"Hej, potrzebuję złota!","Ei, eu preciso de ouro!",,"Hei, am nevoie de aur!","Эй, мне нужно золото!",,Jag behöver guld!,"Hey, altına ihtiyacım var!" +"Blackbird told you the code, huh? Let me shut off the alarm. Macil is one flight down.",TXT_DLG_SCRIPT02_D89444_BLACK,〃,,,"Straka ti řekla heslo, co? Jen vypnu alarmy. Macil je o podlaží níž.","Blackbird fortalte dig koden, hva'? Lad mig slukke for alarmen. Macil er en etage længere nede.","Blackbird hat dir den Code gegeben, wie? Lass mich mal eben den Alarm abschalten. Macil ist eine Etage tiefer.",,"Merlo diris la pasfrazon al vi, ĉu? Tiuokaze mi sensonigos la alarmon. Macil estas malsupre.","Conque Blackbird te ha dado la clave, ¿eh? Ya apago la alarma, entonces. Macil está bajando las escaleras.","Así que Blackbird te dio la clave, ¿eh? Ya apago la alarma, entonces. Macil está bajando las escaleras.","Vai että Blackbird kertoi sinulle koodin? Anna, kun kytken hälyttimen pois päältä. Macil on yhdet rappuset alas.","Blackbird t'as donné le code, hein? Bon, laisse moi désactiver l'alarme. Macil est en bas des escaliers.","Feketerigó mondta el a kódot, mi? Hadd kapcosljam ki a riasztót. macil egy kőhajintásra van innen.","Blackbird ti ha detto qual'è il codice, eh? Fammi disattivare l'allarme. Macil è oltre le scale.","ブラックバードに教えてもらったんだな? +警報は切っておこう。マシルはこの先だ。","블랙버드가 암호를 알려줬나 보군? 흠, 그럼 경보를 꺼둬야겠군. 마실은 계단 저 밑에 있어.","Blackbird vertelde je de code, huh? Laat me de wekker uitzetten. Macil is een vlucht naar beneden.",Fortalte Blackbird deg koden? La meg slå av alarmen. Macil er en etasje ned.,"Blackbird podała ci hasło, co? Pozwól, że wyłączę alarm. Macil jest piętro niżej.","A Blackbird te passou o código, é? Deixa eu desligar o alarme. Macil está no andar debaixo.",,"Blackbird ți-a spus codul, huh? Permite-mi să opresc alarma, Macil e cu un etaj mai jos.","«Чёрный дрозд» сообщила тебе пароль, так? Давай я отключу сигнализацию. Мэйсил этажом ниже.",,"Blackbird berättade koden för dig, va? Låt mig stänga av larmet. Macil är en trappa ner.","Karatavuk sana kodu söyledi, ha? Alarmı kapatayım. Macil bir kat aşağıda." +Thanks.,TXT_RPLY0_SCRIPT02_D89444_THANK,〃,,,Díky.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,고맙다.,Bedankt.,Takk skal du ha.,Dzięki.,Obrigado.,,Mulțumesc.,Спасибо.,,Tack.,Teşekkürler. +"Walk away, boy, just walk away.",TXT_DLG_SCRIPT02_D90960_WALKA,〃,,,"Jdi pryč, chlapče, prostě odejdi.","Gå væk, knægt, bare gå væk.","Geh weg Jungchen, geh einfach weg.",,"Foriru, ulo. Vi nur foriru.","Vete, chaval. Solo vete.","Vete, muchacho. Solo vete.","Kävele pois vain, poju, kävele pois.","Pars, gamin, pars.","Csak sétálj el innen, sétálj el szépen.","Muoviti, ragazzo, muoviti...",向こうへ行け、新入り、急ぐんだ。,"지나가라고 친구, 그냥 지나가.","Loop weg, jongen, loop gewoon weg.","Gå vekk, gutt. Bare gå vekk.","Odejdź stąd mały, po prostu odejdź.","Suma daqui, garoto. Apenas suma daqui.",,"Pleacă, băiete, pleacă.","Иди своей дорогой, парень, иди.",,"Gå iväg, pojke, bara gå iväg.","Yürü git evlat, yürü git." +Do you have an appointment with the Governor? ,TXT_DLG_SCRIPT02_D92476_DOYOU,Arion.,,,Máte domluvený termín schůzky s guvernérem?,Har du en aftale med guvernøren?,Hast du einen Termin bei dem Gouverneur?,,Ĉu vi supozeble havas rendevuon kun la registo?,¿Acaso tienes una cita con el gobernador?,,Onko teillä varattu tapaaminen kuvernöörin kanssa?,Avez-vous un rendez-vous avec le gouverneur?,Van időpontod a kormányzóval?,Hai un appuntamento con il governatore?,知事とアポイントメントは取ってますか?,총독과 약속이 있으십니까?,Heb je een afspraak met de gouverneur?,Har du en avtale med guvernøren?,Masz spotkanie z Gubernatorem?,Você tem hora marcada com o Governador?,,Ai o programare cu Guvernatorul?,У Вас назначена встреча с губернатором?,,Har du ett möte med guvernören?,Vali ile randevunuz var mı? +Of course!,TXT_RPLY0_SCRIPT02_D92476_OFCOU,〃,,,Samozřejmě!,"Ja, selvfølgelig!",Natürlich!,,Kompreneble!,¡Por supuesto!,,Totta kai!,Bien sûr!,Persze!,Certo!,問題ない!,당연하지!,Natuurlijk!,Selvsagt!,Oczywiście!,Claro que sim!,,Desigur!,Конечно!,,Självklart!,Tabii ki var! +"No, and I don't need one!",TXT_RPLY1_SCRIPT02_D92476_NOAND,〃,,,Ne a žádný nepotřebuju!,"Nej, og jeg har ikke brug for en!","Nein, und ich brauche auch keinen!",,"Ne, kaj mi ne bezonas ĝin!",¡No y no la necesito!,,"Ei, enkä sellaista tarvitsekaan!","Non, et j'en ai pas besoin!","Nincs, és nem is kell!","No, e non ne ho bisogno!",いや、必要ない!,아니. 없는데?,"Nee, en die heb ik niet nodig!","Nei, og jeg trenger ingen!","Nie mam, i nie chcę mieć!",Não e eu não preciso de hora marcada!,,"Nu, nici n-am nevoie de una!","Нет, и я в ней не нуждаюсь!",,"Nej, och jag behöver ingen!","Hayır, ihtiyacım da yok!" +Sorry! I didn't mean... Please go right up.,TXT_DLG_SCRIPT02_D93992_SORRY,〃,,,"Pardon! Nechtěl jsem... jeďte tady nahoru, prosím.",Undskyld! Jeg mente ikke... Vær venlig at gå op.,Entschuldigung! Das war nicht so gemeint... Bitte geh durch.,,"Ha, pardonon, mi ne intencis... Uzu la lifton.","Ah, perdón, no quería... Ve al piso de arriba.",,"Pahoittelut! En tarkoittanut... Menkää suoraan ylös, olkaa hyvä.","Désolé, je.. Vous pouvez monter, bien sûr.",Elnézést! Nem akartam...kérem menjen fel az emeletre.,Scusa! Non intendevo... Vai al piano di sopra.,"すいません!知らずに... +そのまま上がって下さい。",이런! 기다리게 할 생각은 없었는데... 부디 위로 올라가시길 바랍니다.,Sorry! Ik bedoelde niet.... Ga alsjeblieft meteen naar boven.,Unnskyld! Unnskyld! Jeg mente ikke... Vær så snill å gå opp.,"Przepraszam! Nie chciałem... Proszę, idź na górę.",Desculpe! Eu não queria... Por favor pode subir.,,"Scuze! Te rog, poftește sus.","Простите! Я не думал... Пожалуйста, проходите наверх.",,Jag är ledsen! Jag menade inte... Var snäll och gå upp.,Özür dilerim! Öyle demek istemedim. Lütfen yukarı çıkın. +I knew you'd say that.,TXT_RPLY0_SCRIPT02_D93992_IKNEW,〃,,,"Věděl jsem, že to řekneš.","Jeg vidste, at du ville sige det.","Ich dachte mir schon, das du das sagen würdest.",,"Mi sciis, ke vi dirus tion.",Sabía que dirías eso.,Sabía que ibas a decir eso.,"Arvasin, että sanoisit noin.",Je savais que vous diriez ceci.,"Tudtam, hogy ezt mondod.",Sapevo che l'avresti detto.,そう言うと思った。,그렇게 말할 줄 알았어.,Ik wist dat je dat zou zeggen.,Jeg visste du ville si det.,"Wiedziałem, że to powiesz.",Eu sabia que você diria isso.,,Știam că vei spune asta.,"Я знал, что ты это скажешь.",,Jag visste att du skulle säga det.,Bunu söyleyeceğini biliyordum. "If you're in such a hurry, don't waste your time with me.",TXT_DLG_SCRIPT02_D95508_IFYOU,〃,,,"Jestli tolik spěcháte, neztrácejte čas se mnou.","Hvis du har så travlt, skal du ikke spilde din tid med mig.","Wenn du so in Eile bist, dann verschwende deine Zeit nicht mit mir.",,"Se vi vere hastas renkonti lin, ne perdu vian tempo kun mi.","Si realmente tienes tanta prisa, no pierdas el tiempo conmigo.","Si realmente estás tan apurado, no pierdas el tiempo conmigo.","Jos kerta olet niin kovassa kiireessä, älä haaskaa aikaasi minun kanssani.","Si vous êtes tellement pressé, ne perdez pas votre temps avec moi.","Ha ennyire sietsz, ne pocsékold az idődet velem.","Se vai così di fretta, non sprecare il tuo tempo con me.","そんなに急いでいるなら、 -お互い時間を大切にしましょう。","아주 급하시다면, 저하고 예기하는 건 시간 낭비일 뿐이에요.","Als je zo'n haast hebt, verspil dan geen tijd met mij.","Hvis du har det så travelt, ikke kast bort tiden din på meg.","Jeśli się tak spieszysz, nie marnuj czasu tu ze mną.","Se você está com tanta pressa, não gaste seu tempo comigo.",,"Dacă te grăbești așa tare, nu-ți pierde vremea cu mine.","Если вы так торопитесь, не тратьте на меня время.",,"Madem bu kadar aceleniz var, benimle vakit kaybetmeyin." -"Release me, leave an old man alone.",TXT_DLG_SCRIPT02_D97024_RELEA,MAP02: MacGuffin,,,"Drž se dál, nech starce na pokoji.","Slip mig fri, lad en gammel mand være i fred.","Pack mich nicht an, lass einen alten Mann in Ruhe",,"Sufiĉe, ne ĝenu maljunulon.",Déjame en paz. No molestes a un anciano.,,"Päästä minut, jätä vanha mies rauhaan.","Laissez moi tranquille, un vieil homme a le droit d'être seul.","Engedj el, hagyd békén öreg csontjaimat.","Lasciami stare, non inquietare un vecchio.",ほっといてくれ、年寄り一人にしてくれ。,부탁일세. 이 노인을 내버려 두게.,"Laat me vrij, laat een oude man met rust.","Slipp meg, la en gammel mann være i fred.","Nie zbliżaj się, zostaw starca w spokoju.","Me solte, deixe um velho em paz.",,"Lasă-mă, lasă bătrânii în pace.",Оставь старика в покое!,,"Bırak beni, yaşlı bir adamı yalnız bırak." -"You seek wisdom, my son? The order has seen to it that we only ask one question, 'Why?'",TXT_DLG_SCRIPT02_D98540_YOUSE,"〃 (after accepting ""messy"" chore)",,,"Hledáš moudrost, chlapče? Řád dohlédl na to, abychom se ptali jen na jedno: „Proč?“","Søger du visdom, min søn? Ordenen har sørget for, at vi kun stiller ét spørgsmål: ""Hvorfor?","Du suchst Weisheit, mein Sohn? Der Orden hat zugesehen das wir nur noch eine Frage stellen, „Warum?“",,"Ĉu vi serĉas saĝon, filo? La Ordono certiĝis, ke ni nur faru unu demandon: «Kial?».","¿Buscas sabiduría, hijo mío? La Orden se ha asegurado de que hagamos solo una pregunta: «¿Por qué?».",,"Etsitkö viisautta, poikani? Veljeskunta on pitänyt huolen, että ainoa kysymys, jonka kysymme, on ""Miksi"".","Vous cherchez ma sagesse, jeune homme? L'Ordre ne pose qu'une seule question: « Pourquoi? »","Tudásra vágsz, fiam? A Rend gondoskodott róla, hogy az egyetlen kérdés amit felteszünk a 'Miért?'","Cerchi saggezza, figliolo? L'Ordine ha fatto si che noi possiamo chiedere una sola domanda. ""Perché?""","知恵が欲しそうだな、ボウズ? +お互い時間を大切にしましょう。","아주 급하시다면, 저하고 예기하는 건 시간 낭비일 뿐이에요.","Als je zo'n haast hebt, verspil dan geen tijd met mij.","Hvis du har det så travelt, ikke kast bort tiden din på meg.","Jeśli się tak spieszysz, nie marnuj czasu tu ze mną.","Se você está com tanta pressa, não gaste seu tempo comigo.",,"Dacă te grăbești așa tare, nu-ți pierde vremea cu mine.","Если вы так торопитесь, не тратьте на меня время.",,"Om du har så bråttom, slösa inte bort din tid med mig.","Madem bu kadar aceleniz var, benimle vakit kaybetmeyin." +"Release me, leave an old man alone.",TXT_DLG_SCRIPT02_D97024_RELEA,MAP02: MacGuffin,,,"Drž se dál, nech starce na pokoji.","Slip mig fri, lad en gammel mand være i fred.","Pack mich nicht an, lass einen alten Mann in Ruhe",,"Sufiĉe, ne ĝenu maljunulon.",Déjame en paz. No molestes a un anciano.,,"Päästä minut, jätä vanha mies rauhaan.","Laissez moi tranquille, un vieil homme a le droit d'être seul.","Engedj el, hagyd békén öreg csontjaimat.","Lasciami stare, non inquietare un vecchio.",ほっといてくれ、年寄り一人にしてくれ。,부탁일세. 이 노인을 내버려 두게.,"Laat me vrij, laat een oude man met rust.","Slipp meg, la en gammel mann være i fred.","Nie zbliżaj się, zostaw starca w spokoju.","Me solte, deixe um velho em paz.",,"Lasă-mă, lasă bătrânii în pace.",Оставь старика в покое!,,"Släpp mig, låt en gammal man vara ifred.","Bırak beni, yaşlı bir adamı yalnız bırak." +"You seek wisdom, my son? The order has seen to it that we only ask one question, 'Why?'",TXT_DLG_SCRIPT02_D98540_YOUSE,"〃 (after accepting ""messy"" chore)",,,"Hledáš moudrost, chlapče? Řád dohlédl na to, abychom se ptali jen na jedno: „Proč?“","Søger du visdom, min søn? Ordenen har sørget for, at vi kun stiller ét spørgsmål: ""Hvorfor?","Du suchst Weisheit, mein Sohn? Der Orden hat zugesehen das wir nur noch eine Frage stellen, „Warum?“",,"Ĉu vi serĉas saĝon, filo? La Ordeno certiĝis, ke ni nur faru unu demandon: «Kial?».","¿Buscas sabiduría, hijo mío? La Orden se ha asegurado de que hagamos solo una pregunta: «¿Por qué?».",,"Etsitkö viisautta, poikani? Veljeskunta on pitänyt huolen, että ainoa kysymys, jonka kysymme, on ""Miksi"".","Vous cherchez ma sagesse, jeune homme? L'Ordre ne pose qu'une seule question: « Pourquoi? »","Tudásra vágsz, fiam? A Rend gondoskodott róla, hogy az egyetlen kérdés amit felteszünk a 'Miért?'","Cerchi saggezza, figliolo? L'Ordine ha fatto si che noi possiamo chiedere una sola domanda. ""Perché?""","知恵が欲しそうだな、ボウズ? オーダーが勘付かないよう一つだけ質問しよう、 -'何故?'","지혜를 찾고 싶은가, 젊은이여? 오더도 이 사실을 알고 있어서 우리들을 '왜?' 하고 묻게 했다네. 자네도 '왜' 그러나?","Je zoekt wijsheid, mijn zoon? De orde heeft ervoor gezorgd dat we maar één vraag stellen: 'Waarom?","Søker du visdom, min sønn? Ordenen har sørget for at vi bare stiller ett spørsmål. Hvorfor?","Poszukujesz wiedzy mój synu? Zakon stara się dopilnować nas abyśmy zadawali sobie tylko jedno pytanie, ""Czemu?""","Está atrás de sabedoria, meu filho? A ordem se certificou de que a gente só fizesse uma única pergunta, ""por quê?""",,"Cauți înțelepciune, fiul meu? Ordinul a avut grijă ca noi să putem fi în stare să punem o singură întrebare: 'De ce?'","Ищешь совета, сын мой? Орден заботится о том, чтобы нас занимал только один вопрос: «За что?»",,"Bilgelik mi istiyorsun, oğlum? Düzen sadece tek bir soru sormamızı sağladı, ""Neden?" -Where's the power coupling?,TXT_RPLY0_SCRIPT02_D98540_WHERE,〃 (〃),,,Kde je elektrická spojka?,Hvor er kraftkoblingen?,Wo ist der Stromabnehmer?,,Kie estas la elektra kuplado?,¿Dónde está el acoplamiento eléctrico?,,Missä virtaliitin on?,Où est le coupleur énergétique?,Hol van az áram kapcsoló?,Dov'è il giunto dell'impianto energetico?,配電機 は何処だ?,동력선은 어디있나요?,Waar is de krachtkoppeling?,Hvor er kraftkoblingen?,Gdzie jest odbierak prądu?,Cadê a conexão de energia?,,Unde e cuplajul energiei?,Где соединительная муфта?,,Güç bağlantısı nerede? -Where's the Order's main?,TXT_RPLY1_SCRIPT02_D98540_WHERE,〃 (〃),,,Kde má Řád napájecí síť?,Hvor er ordenens vigtigste?,Wo ist die Stromleitung des Ordens?,,Kie estas la elektriza sistemo de La Ordono?,¿Dónde está la red eléctrica de La Orden?,,Missä on Veljeskunnan pääsähkölinja?,Où est le transformateur de l'Ordre?,Hol a Rend fővonala?,Dov'è il giunto dell'Ordine?,オーダーの本管 は何処だ?,오더의 동력 공급 시설은 어디있나요?,Waar is de hoofdopdracht van de Orde?,Hvor er Ordenens hovedledning?,Gdzie jest przewód Zakonu?,Cadê o transformador da Ordem?,,Unde e linia electrică a Ordinului?,Где линия электропередачи Ордена?,,Tarikat'ın ana hattı nerede? -Where's the illegal tap?,TXT_RPLY2_SCRIPT02_D98540_WHERE,〃 (〃),,,Kde je nelegální stáčedlo?,Hvor er den ulovlige aftapning?,Wo ist die illegale Anzapfung?,,Kie estas la kontraŭleĝa konektilo?,¿Dónde está la toma eléctrica ilegal?,,Missä laiton kytkentä on?,Où est la connection pirate?,Hol az illegális lék?,Dov'è l'aggeggio illegale che sta rubando l'energia?,違法供給源 は何処だ?,불법 추출기는 어디있나요?,Waar is de illegale kraan?,Hvor er den ulovlige kranen?,Gdzie jest nielegalny przełącznik prądu?,Cadê a ligação clandestina?,,Unde e conexiunea ilegală?,Где нелегальное подключение?,,Yasadışı musluk nerede? +'何故?'","지혜를 찾고 싶은가, 젊은이여? 오더도 이 사실을 알고 있어서 우리들을 '왜?' 하고 묻게 했다네. 자네도 '왜' 그러나?","Je zoekt wijsheid, mijn zoon? De orde heeft ervoor gezorgd dat we maar één vraag stellen: 'Waarom?","Søker du visdom, min sønn? Ordenen har sørget for at vi bare stiller ett spørsmål. Hvorfor?","Poszukujesz wiedzy mój synu? Zakon stara się dopilnować nas abyśmy zadawali sobie tylko jedno pytanie, ""Czemu?""","Está atrás de sabedoria, meu filho? A ordem se certificou de que a gente só fizesse uma única pergunta, ""por quê?""",,"Cauți înțelepciune, fiul meu? Ordinul a avut grijă ca noi să putem fi în stare să punem o singură întrebare: 'De ce?'","Ищешь совета, сын мой? Орден заботится о том, чтобы нас занимал только один вопрос: «За что?»",,"Du söker visdom, min son? Ordern har sett till att vi bara ställer en fråga: ""Varför?","Bilgelik mi istiyorsun, oğlum? Düzen sadece tek bir soru sormamızı sağladı, ""Neden?" +Where's the power coupling?,TXT_RPLY0_SCRIPT02_D98540_WHERE,〃 (〃),,,Kde je elektrická spojka?,Hvor er kraftkoblingen?,Wo ist der Stromabnehmer?,,Kie estas la elektra kuplado?,¿Dónde está el acoplamiento eléctrico?,,Missä virtaliitin on?,Où est le coupleur énergétique?,Hol van az áram kapcsoló?,Dov'è il giunto dell'impianto energetico?,配電機 は何処だ?,동력선은 어디있나요?,Waar is de krachtkoppeling?,Hvor er kraftkoblingen?,Gdzie jest odbierak prądu?,Cadê a conexão de energia?,,Unde e cuplajul energiei?,Где соединительная муфта?,,Var är kraftkopplingen?,Güç bağlantısı nerede? +Where's the Order's main?,TXT_RPLY1_SCRIPT02_D98540_WHERE,〃 (〃),,,Kde má Řád napájecí síť?,Hvor er ordenens vigtigste?,Wo ist die Stromleitung des Ordens?,,Kie estas la elektriza sistemo de La Ordeno?,¿Dónde está la red eléctrica de La Orden?,,Missä on Veljeskunnan pääsähkölinja?,Où est le transformateur de l'Ordre?,Hol a Rend fővonala?,Dov'è il giunto dell'Ordine?,オーダーの本管 は何処だ?,오더의 동력 공급 시설은 어디있나요?,Waar is de hoofdopdracht van de Orde?,Hvor er Ordenens hovedledning?,Gdzie jest przewód Zakonu?,Cadê o transformador da Ordem?,,Unde e linia electrică a Ordinului?,Где линия электропередачи Ордена?,,Var är orderns huvudledning?,Tarikat'ın ana hattı nerede? +Where's the illegal tap?,TXT_RPLY2_SCRIPT02_D98540_WHERE,〃 (〃),,,Kde je nelegální stáčedlo?,Hvor er den ulovlige aftapning?,Wo ist die illegale Anzapfung?,,Kie estas la kontraŭleĝa konektilo?,¿Dónde está la toma eléctrica ilegal?,,Missä laiton kytkentä on?,Où est la connection pirate?,Hol az illegális lék?,Dov'è l'aggeggio illegale che sta rubando l'energia?,違法供給源 は何処だ?,불법 추출기는 어디있나요?,Waar is de illegale kraan?,Hvor er den ulovlige kranen?,Gdzie jest nielegalny przełącznik prądu?,Cadê a ligação clandestina?,,Unde e conexiunea ilegală?,Где нелегальное подключение?,,Var är den olagliga kranen?,Yasadışı musluk nerede? "I'll tell you where it is, but I don't know whose coupling you'll be tampering with. It's right here in the sewage plant.",TXT_DLG_SCRIPT02_D100056_ILLTE,〃 (〃),,,"Řeknu ti kde je, ale nevím s čí spojkou budeš manipulovat. Je přímo tady v čističce.","Jeg skal fortælle dig, hvor den er, men jeg ved ikke, hvis kobling du vil pille ved. Den er lige her i kloakanlægget.","Ich sage dir wo er ist, aber ich weiß nicht, an wessen Anzapfung du herummanipulieren willst. Er ist genau hier in der Kläranlage.",,"Mi respondos, sed mi ne scias, kies elektrizan sistemon vi intencas perturbi. Ĝi estas ĉi tie, en la kloakpurigejo.","Te diré donde, aunque no sé de quién será la red eléctrica que quieres manipular. Está justo aquí en la planta de aguas residuales.","Te voy a decir, aunque no sé de quién será la red eléctrica que quieres manipular. Está justo aquí en la planta de aguas residuales.","Kerron kyllä, missä se on, mutten tiedä, kenen kytkentään aiot sekaantua. Se on täällä jätelaitoksella.","Je peux vous dire où il est, mais je ne peux pas vous dire à qui il appartient. Il se trouve dans le traitement des égouts.","Elárom hol van, de pontosan nem tudom kinek a kapcsolójával fogsz babrálni. Itt van rögtön a szennyvíz tisztítóban.","Ti dirò dov'è, ma non so con quale giunto in particolare tu voglia maneggiare. Sta proprio qua nell'impianto fognario.","それが何処にあるかは話そう、だがオレには どれをイジるかまでは知らん。 -配電機はここの下水処理場にある。",그게 어딨는지 말해주지. 왜 그 동력선에 손을 대려고 하는지는 모르겠지마는. 저 앞 하수도 안에 있다네.,"Ik zal je vertellen waar hij is, maar ik weet niet met wie je met de koppeling zult knoeien. Het is hier in de rioolwaterzuiveringsinstallatie.","Jeg skal si deg hvor den er, men jeg vet ikke hvem sin kobling du skal tukle med. Den er her i kloakkanlegget.","Powiem ci gdzie jest, ale nie wiem czyj to odbierak, przy którym będziesz majstrować. Jest w oczyszczalni ścieków.","Vou te dizer onde está, mas não sei em qual ligação você vai acabar mexendo. Fica bem aqui na usina de tratamento de esgoto.",,"Îți voi spune unde este, dar nu știu de care cuplaj te vei lega. Este chiar aici, în sistemul de canalizare.","Я скажу тебе, где она, но не знаю, которая тебе нужна. Она прямо здесь, в очистной системе.",,"Nerede olduğunu söyleyeceğim, ama kimin bağlantılarını kurcalayacağınızı bilmiyorum. Tam burada, kanalizasyon tesisinde." -Thanks,TXT_RPLY0_SCRIPT02_D100056_THANK,〃 (〃),,,Díky.,Tak,Danke,,Dankon.,Gracias.,,Kiitos,Merci.,Kösz.,Grazie,ありがとう。,그렇군요.,Bedankt,Takk skal du ha.,Dzięki,Obrigado,,Mulțumesc,Спасибо.,,Teşekkürler. -That's right here in the sewage plant. But it's the Front's coupling. Whoever told you that it was the Order's was wrong.,TXT_DLG_SCRIPT02_D101572_THATS,〃 (〃),,,"Síť je přímo tady, v čističce. Ale je to spojka Fronty. Kdo ti řekl, že je Řádu, se mýlil.","Det er lige her i kloakanlægget. Men det er Fronts kobling. Den, der fortalte dig, at det var Ordenens, tog fejl.","Genau hier, in der Kläranlage. Aber sie gehört der Front. Wer auch immer dir gesagt hat, sie gehöre dem Orden, hat gelogen.",,"Ĝi estas ĉi tie, en la kloakpurigejo, sed ĝi estas la kuplado de la Fronto. Tiu ajn, kiu diris, ke ĝi estas de La Ordono, eraris.","Está justo aquí en la planta de aguas residuales, pero es el acoplamiento del Frente. Quien te haya dicho que era de La Orden se ha equivocado. +配電機はここの下水処理場にある。",그게 어딨는지 말해주지. 왜 그 동력선에 손을 대려고 하는지는 모르겠지마는. 저 앞 하수도 안에 있다네.,"Ik zal je vertellen waar hij is, maar ik weet niet met wie je met de koppeling zult knoeien. Het is hier in de rioolwaterzuiveringsinstallatie.","Jeg skal si deg hvor den er, men jeg vet ikke hvem sin kobling du skal tukle med. Den er her i kloakkanlegget.","Powiem ci gdzie jest, ale nie wiem czyj to odbierak, przy którym będziesz majstrować. Jest w oczyszczalni ścieków.","Vou te dizer onde está, mas não sei em qual ligação você vai acabar mexendo. Fica bem aqui na usina de tratamento de esgoto.",,"Îți voi spune unde este, dar nu știu de care cuplaj te vei lega. Este chiar aici, în sistemul de canalizare.","Я скажу тебе, где она, но не знаю, которая тебе нужна. Она прямо здесь, в очистной системе.",,"Jag ska berätta var den är, men jag vet inte vems koppling du kommer att mixtra med. Den finns här i reningsverket.","Nerede olduğunu söyleyeceğim, ama kimin bağlantılarını kurcalayacağınızı bilmiyorum. Tam burada, kanalizasyon tesisinde." +Thanks,TXT_RPLY0_SCRIPT02_D100056_THANK,〃 (〃),,,Díky.,Tak,Danke,,Dankon.,Gracias.,,Kiitos,Merci.,Kösz.,Grazie,ありがとう。,그렇군요.,Bedankt,Takk skal du ha.,Dzięki,Obrigado,,Mulțumesc,Спасибо.,,Tack,Teşekkürler. +That's right here in the sewage plant. But it's the Front's coupling. Whoever told you that it was the Order's was wrong.,TXT_DLG_SCRIPT02_D101572_THATS,〃 (〃),,,"Síť je přímo tady, v čističce. Ale je to spojka Fronty. Kdo ti řekl, že je Řádu, se mýlil.","Det er lige her i kloakanlægget. Men det er Fronts kobling. Den, der fortalte dig, at det var Ordenens, tog fejl.","Genau hier, in der Kläranlage. Aber sie gehört der Front. Wer auch immer dir gesagt hat, sie gehöre dem Orden, hat gelogen.",,"Ĝi estas ĉi tie, en la kloakpurigejo, sed ĝi estas la kuplado de la Fronto. Tiu ajn, kiu diris, ke ĝi estas de La Ordeno, eraris.","Está justo aquí en la planta de aguas residuales, pero es el acoplamiento del Frente. Quien te haya dicho que era de La Orden se ha equivocado. ","Está justo aquí en la planta de aguas residuales, pero es el acoplamiento del Frente. Quien te haya dicho que era de La Orden te dijo mal. ","Se on täällä jätelaitoksella. Mutta se on Rintaman kytkentä. Kuka sinulle kertoikaan sen kuuluvan Veljeskunnalle, oli väärässä.","Il se trouve ici dans le traitement des égouts, mais c'est le coupleur du Front . Celui qui vous a dit qu'il appartient à l'Ordre se plante.","Igen, jól hallottad, a szennyvíz tisztítóban. Ez azonban a Front kapcsolója. Akárki mondta, hogy a Rendé, hazudott neked.",È proprio qui nell'impianto fognario. Ma è il giunto del Fronte. Chiunque ti abbia detto che fosse il giunto dell'Ordine si sbagliava.,"正にここの下水処理場にあるさ。 だがそれはフロントにも繋いでいる。 そいつがオーダーの所有物と言われてたが、 そりゃ間違いだ。",저 앞 하수도 안에 있다네. 프론트가 설치한 동력선일세. 저게 오더 소유라고 우기던 사람은 거짓말을 한 게야.,"Dat is hier in de rioolwaterzuiveringsinstallatie. Maar het is de koppeling van de voorkant. Degene die je vertelde dat het de Order's waren, had het mis.","Det er her i kloakkanlegget. Men det er Fronts kobling. Den som sa at det var Ordenens, tok feil.","Jest w oczyszczalni ścieków. Ale to jest odbierak Frontu. Ktokolwiek ci powiedział, że należy do Zakonu, był w błędzie.",Fica bem aqui na usina de tratamento de esgoto. Mas é a ligação da Frente. Quem te falou que era da Ordem estava enganado.,,Este chiar aici în sistemul de canalizare. Dar este cuplajul Frontului. Oricine ți-a spus că e al Ordinului a greșit.,"Она прямо здесь, в очистном сооружении. Но это линия Сопротивления. Тот, кто сказал тебе, что она принадлежит Ордену, ошибся. -",,"Tam burada, kanalizasyon tesisinde. Ama bu Cephe'nin bağlantısı. Size kim Tarikat'ın olduğunu söylediyse yanılmış." -Thanks,TXT_RPLY0_SCRIPT02_D101572_THANK,〃 (〃),,,Díky.,Tak,Danke.,,Dankon.,Gracias.,,Kiitos,Merci.,Kösz.,Grazie,ありがとう。,고맙습니다.,Bedankt,Takk.,Dzięki,Obrigado,,Mulțumesc,Спасибо.,,Teşekkürler. +",,Det är precis här i reningsverket. Men det är Fronts koppling. Den som sa till dig att det var ordens koppling hade fel.,"Tam burada, kanalizasyon tesisinde. Ama bu Cephe'nin bağlantısı. Size kim Tarikat'ın olduğunu söylediyse yanılmış." +Thanks,TXT_RPLY0_SCRIPT02_D101572_THANK,〃 (〃),,,Díky.,Tak,Danke.,,Dankon.,Gracias.,,Kiitos,Merci.,Kösz.,Grazie,ありがとう。,고맙습니다.,Bedankt,Takk.,Dzięki,Obrigado,,Mulțumesc,Спасибо.,,Tack,Teşekkürler. If you say it's illegal I want nothing to do with you. I have enough trouble as it is.,TXT_DLG_SCRIPT02_D103088_IFYOU,〃 (〃),,,"Jestli říkáš nelegální, nechci s tebou nic mít. Už tak mám svých problémů dost.","Hvis du siger, det er ulovligt, vil jeg ikke have noget med dig at gøre. Jeg har problemer nok i forvejen.","Wenn du sagst, es sei illegal, möchte ich nichts damit zu tun haben. Ich habe schon genug Probleme.",,"Se vi diras, ke ĝi estas kontraŭleĝa, mi volas nenian rilaton kun vi. Mi jam havas sufiĉe da problemoj.",Si dices que es ilegal no quiero tener nada que ver contigo. Ya tengo suficientes problemas.,,"Jos sanot sen olevan laiton, en halua olla kanssasi missään tekemisissä. On jo riitämiin pärjäämistä nykyhuolteni kanssa.","Si vous dites que c'est un truc illégal, alors je ne veux pas m'en mêler. J'ai déjà assez de problèmes.","Ha azt mondod, hogy illegális, nem akarok benne lenni. Van már így is elég bajom.","Se dici che è illegale, non voglio averci nulla a che fare. Ho già abbastanza problemi di mio.","それが違法だっつうんならオレには関係無い。 -トラブルは御免だ。",저게 불법이라고 말한다면 난 이제 더는 모른다네. 관련 문제도 원치 않고 말일세.,"Als je zegt dat het illegaal is, wil ik niets met je te maken hebben. Ik heb al genoeg problemen.","Hvis du sier det er ulovlig, vil jeg ikke ha noe med deg å gjøre. Jeg har nok problemer som det er.","Jeśli mówisz, że jest nielegalny, to nie chcę mieć z tobą nic wspólnego. Mam wystarczająco dużo kłopotów.",Se você diz que isso é ilegal então eu não quero envolvimento nenhum contigo. Já tenho problemas o suficiente.,,"Dacă zici că e ilegal, nu vreau să am nimic de-aface cu tine. Am destule probleme deja.","Раз ты говоришь, что оно нелегально, я не хочу иметь с тобой дел. Мне и так хватает проблем.",,"Eğer bunun yasadışı olduğunu söylüyorsanız, sizinle hiçbir şey yapmak istemiyorum. Başımda yeterince bela var zaten." -Thanks,TXT_RPLY0_SCRIPT02_D103088_THANK,〃 (〃),,,Díky.,Tak,Danke,,Dankon.,Gracias.,,Kiitos,Merci.,Kösz,Grazie,ありがとう。,감사합니다.,Bedankt,Takk.,Dzięki,Obrigado,,Mulțumesc,Спасибо.,,Teşekkürler. -"Release me, leave an old man alone.",TXT_DLG_SCRIPT02_D104604_RELEA,〃 (〃),,,"Drž se dál, nech starce na pokoji.","Slip mig fri, lad en gammel mand være i fred.",Bitte lass einen alten Mann in Ruhe,,"Sufiĉe, ne ĝenu maljunulon.",Déjame en paz. No molestes a un anciano.,,"Päästä minut, jätä vanha mies rauhaan.","Laissez moi tranquille, un vieil homme a le droit d'être seul.","Engedj el, hagyd békén öreg csontjaimat.","Lasciami stare, non inquietare un vecchio.",ほっといてくれ、年寄り一人にしてくれ。,보내주게. 이 노인은 이제 아무것도 몰라.,"Laat me vrij, laat een oude man met rust.","Slipp meg fri, la en gammel mann være i fred.","Nie zbliżaj się, zostaw starca w spokoju.","Me solte, deixe um velho em paz.",,"Lasă-mă, lasă bătrânii în pace.",Оставь старика в покое!,,"Bırakın beni, yaşlı bir adamı yalnız bırakın." -"Welcome to the last flicker of hope. Only we have the free will to oppose the Order. We have the sharpest scientific minds, and many able bodies, but we lack that one real, uh... Problemsolver, who will give us the edge we need. Help us.",TXT_DLG_SCRIPT03_D0_WELCO,MAP03: Macil.,,,"Vítej u posledního plamínku naděje. Jen my máme svobodnou vůli vzdorovat Řádu. Máme sice nejčilejší vědecké génie a mnoho schopných vojáků, ale chybí nám ten jeden... pomocník, který by nás posunul vpřed. Pomoz nám.","Velkommen til det sidste lille håb. Kun vi har den frie vilje til at modsætte os Ordenen. Vi har de skarpeste videnskabelige hjerner og mange dygtige kroppe, men vi mangler den ene rigtige, øh... Problemløser, som vil give os den fordel, vi har brug for. Hjælp os.","Wilkommen beim letzten Hoffnungsschimmer. Nur wir haben noch den freien Willen, um gegen den Orden zu arbeiten. Wir haben die besten Wissenschaftler und viele fähige Kämpfer aber was uns fehlt ist ein spezieller... äh... Problemlöser, der uns den nötigen Vorteil verschafft. Bitte hilf uns.",,"Bonvenon en la lasta fajrero da espero. Nur ni havas liberan volon por kontraŭstari al La Ordono. Ni havas la plej inteligentajn mensojn kaj multe da kapablaj homoj, sed mankas tiu, kiu estus, hm... vera problem-solvanto, por ke li donu al ni la necesan avantaĝon. Helpu nin.","Bienvenido al último destello de esperanza. Solo nosotros tenemos el libre albedrío para oponernos a La Orden. Tenemos las mentes científicas más brillantes y muchas personas capaces, pero nos falta el que sería, este... todo un solucionador de problemas para que nos dé la ventaja que necesitamos. Ayúdanos.",,"Tervetuloa viimeisen toivonpilkahduksen äärelle. Ainoastaan meillä on vapaa tahto vastustaa Veljeskuntaa. Meillä on tieteen terävimmät mielet ja monia ruumiiltaan vahvoja, mutta meiltä puuttuu se yksi todellinen, sanottaisiinko, Ongelmanratkoja, joka antaisi meille kaipaamamme etulyöntiaseman. Auta meitä.","Bienvenue au dernier lieu d'espoir. Nous seuls avons la liberté d'esprit pour opposer l'Ordre. Nous avons les esprits scientifiques les plus aiguisés et de nombreux hommes habiles et sains.. Mais il nous manque quelqu'un qui pourrait.. résoudre nos problèmes. Nous donner un peu d'aide, nous permettre de prendre l'avantage.","Köszöntelek a remény utolsó pislákoló fényénél. Már csak mi merünk szembeszállni a Renddel. Itt vannak a legélesebb elmék, életerős emberek, de hiányzik egy igazi...probléma megoldó, aki előnyt szerez számunkra. Segíts nekünk!","Benvenuto nell'ultimo barlume di speranza. Noi siamo i soli ad avere la determinazione per combattere l'Ordine. Abbiamo brillanti scienziati e molti soldati capaci, ma ci manca quel vero e proprio... risolutore di problemi, che ci può dare quel vantaggio che cerchiamo. Aiutaci!","ようこそ、ここは我々の僅かな希望が集まる +トラブルは御免だ。",저게 불법이라고 말한다면 난 이제 더는 모른다네. 관련 문제도 원치 않고 말일세.,"Als je zegt dat het illegaal is, wil ik niets met je te maken hebben. Ik heb al genoeg problemen.","Hvis du sier det er ulovlig, vil jeg ikke ha noe med deg å gjøre. Jeg har nok problemer som det er.","Jeśli mówisz, że jest nielegalny, to nie chcę mieć z tobą nic wspólnego. Mam wystarczająco dużo kłopotów.",Se você diz que isso é ilegal então eu não quero envolvimento nenhum contigo. Já tenho problemas o suficiente.,,"Dacă zici că e ilegal, nu vreau să am nimic de-aface cu tine. Am destule probleme deja.","Раз ты говоришь, что оно нелегально, я не хочу иметь с тобой дел. Мне и так хватает проблем.",,Om du säger att det är olagligt vill jag inte ha något med dig att göra. Jag har tillräckligt med problem som det är.,"Eğer bunun yasadışı olduğunu söylüyorsanız, sizinle hiçbir şey yapmak istemiyorum. Başımda yeterince bela var zaten." +Thanks,TXT_RPLY0_SCRIPT02_D103088_THANK,〃 (〃),,,Díky.,Tak,Danke,,Dankon.,Gracias.,,Kiitos,Merci.,Kösz,Grazie,ありがとう。,감사합니다.,Bedankt,Takk.,Dzięki,Obrigado,,Mulțumesc,Спасибо.,,Tack,Teşekkürler. +"Release me, leave an old man alone.",TXT_DLG_SCRIPT02_D104604_RELEA,〃 (〃),,,"Drž se dál, nech starce na pokoji.","Slip mig fri, lad en gammel mand være i fred.",Bitte lass einen alten Mann in Ruhe,,"Sufiĉe, ne ĝenu maljunulon.",Déjame en paz. No molestes a un anciano.,,"Päästä minut, jätä vanha mies rauhaan.","Laissez moi tranquille, un vieil homme a le droit d'être seul.","Engedj el, hagyd békén öreg csontjaimat.","Lasciami stare, non inquietare un vecchio.",ほっといてくれ、年寄り一人にしてくれ。,보내주게. 이 노인은 이제 아무것도 몰라.,"Laat me vrij, laat een oude man met rust.","Slipp meg fri, la en gammel mann være i fred.","Nie zbliżaj się, zostaw starca w spokoju.","Me solte, deixe um velho em paz.",,"Lasă-mă, lasă bătrânii în pace.",Оставь старика в покое!,,"Släpp mig, låt en gammal man vara ifred.","Bırakın beni, yaşlı bir adamı yalnız bırakın." +"Welcome to the last flicker of hope. Only we have the free will to oppose the Order. We have the sharpest scientific minds, and many able bodies, but we lack that one real, uh... Problemsolver, who will give us the edge we need. Help us.",TXT_DLG_SCRIPT03_D0_WELCO,MAP03: Macil.,,,"Vítej u posledního plamínku naděje. Jen my máme svobodnou vůli vzdorovat Řádu. Máme sice nejčilejší vědecké génie a mnoho schopných vojáků, ale chybí nám ten jeden... pomocník, který by nás posunul vpřed. Pomoz nám.","Velkommen til det sidste lille håb. Kun vi har den frie vilje til at modsætte os Ordenen. Vi har de skarpeste videnskabelige hjerner og mange dygtige kroppe, men vi mangler den ene rigtige, øh... Problemløser, som vil give os den fordel, vi har brug for. Hjælp os.","Wilkommen beim letzten Hoffnungsschimmer. Nur wir haben noch den freien Willen, um gegen den Orden zu arbeiten. Wir haben die besten Wissenschaftler und viele fähige Kämpfer aber was uns fehlt ist ein spezieller... äh... Problemlöser, der uns den nötigen Vorteil verschafft. Bitte hilf uns.",,"Bonvenon en la lasta fajrero da espero. Nur ni havas liberan volon por kontraŭstari al La Ordeno. Ni havas la plej inteligentajn mensojn kaj multe da kapablaj homoj, sed mankas tiu, kiu estus, hm... vera problem-solvanto, por ke li donu al ni la necesan avantaĝon. Helpu nin.","Bienvenido al último destello de esperanza. Solo nosotros tenemos el libre albedrío para oponernos a La Orden. Tenemos las mentes científicas más brillantes y muchas personas capaces, pero nos falta el que sería, este... todo un solucionador de problemas para que nos dé la ventaja que necesitamos. Ayúdanos.",,"Tervetuloa viimeisen toivonpilkahduksen äärelle. Ainoastaan meillä on vapaa tahto vastustaa Veljeskuntaa. Meillä on tieteen terävimmät mielet ja monia ruumiiltaan vahvoja, mutta meiltä puuttuu se yksi todellinen, sanottaisiinko, Ongelmanratkoja, joka antaisi meille kaipaamamme etulyöntiaseman. Auta meitä.","Bienvenue au dernier lieu d'espoir. Nous seuls avons la liberté d'esprit pour opposer l'Ordre. Nous avons les esprits scientifiques les plus aiguisés et de nombreux hommes habiles et sains.. Mais il nous manque quelqu'un qui pourrait.. résoudre nos problèmes. Nous donner un peu d'aide, nous permettre de prendre l'avantage.","Köszöntelek a remény utolsó pislákoló fényénél. Már csak mi merünk szembeszállni a Renddel. Itt vannak a legélesebb elmék, életerős emberek, de hiányzik egy igazi...probléma megoldó, aki előnyt szerez számunkra. Segíts nekünk!","Benvenuto nell'ultimo barlume di speranza. Noi siamo i soli ad avere la determinazione per combattere l'Ordine. Abbiamo brillanti scienziati e molti soldati capaci, ma ci manca quel vero e proprio... risolutore di problemi, che ci può dare quel vantaggio che cerchiamo. Aiutaci!","ようこそ、ここは我々の僅かな希望が集まる 最後の場所だ。オーダーへと立ち向かう意思を 持っているのは我々くらいだ。 ここには素晴らしい頭脳を持つ学者たち、そして 丈夫な体を持った戦士たちがいる。 だがしかし、我々には問題解決に優れた者、 つまり私達の力となる者が足りていないんだ。 -我々に手を貸してくれ。","최후의 희망 한 가닥을 잡은 것을 환영합니다. 우리만이 오더를 거부할 수 있는 의지를 갖추고 있죠. 뛰어난 과학력과 전투력은 다 갖추고 있습니다만, 정작 '해결사' 몫을 해주는 인물이 없어서 말입니다... 부디 우리를 도와주시길 바랍니다.","Welkom bij het laatste sprankje hoop. Alleen wij hebben de vrije wil om ons te verzetten tegen de Orde. We hebben de scherpste wetenschappelijke geesten en veel bekwame lichamen, maar we missen die ene echte, uh.... probleemoplosser, die ons de voorsprong zal geven die we nodig hebben. Help ons.","Velkommen til det siste glimt av håp. Bare vi har den frie viljen til å motsette oss Ordenen. Vi har de skarpeste vitenskapelige hodene, og mange dyktige kropper, men vi mangler den ene virkelige... problemløseren, som vil gi oss det forspranget vi trenger. Hjelp oss.","Witaj w ostatniej iskierce nadziei. Tylko my mamy wolną wolę, aby sprzeciwić się Zakonowi. Mamy najmądrzejszych naukowców i wielu ludzi, ale brakuje nam kogoś porządnego by, ehmm... rozwiązać parę problemów, kogoś kto da nam przewagę, której potrzebujemy. Pomóż nam.","Seja bem-vindo à última ponta de esperança. Somente nós temos o livre arbítrio para combater a Ordem. Temos as mentes científicas mais afiadas e muitas pessoas capazes, mas nos falta aquele verdadeiro, hã... quebra-galho, que nos dará o impulso que precisamos. Ajude-nos.",,"Bun venit la ultima fărâmă de speranță. Numai noi avem voința liberă necesară pentru a ne opune Ordinului. Avem cele mai ascuțite minți științifice, și mulți oameni capabili de muncă, dar ne lipsește acel um... adevărat Salvator de la probleme, care să ne ofere avantajul de care avem nevoie. Ajută-ne.","Добро пожаловать в последний оплот надежды. Только мы обладаем свободной волей, чтобы противостоять Ордену. С нами лучшие учёные умы, и у нас есть много толковых людей, но нам не хватает одного-единственного, э... «решателя проблем», который поможет нам получить необходимое преимущество. Помоги нам.",,"Son umut ışığına hoş geldiniz. Tarikat'a karşı koyacak özgür irade sadece bizde var. En keskin bilimsel zihinlere ve birçok yetenekli bedene sahibiz, ancak bize ihtiyacımız olan avantajı sağlayacak gerçek bir Problem Çözücüden yoksunuz. Bize yardım edin." -"All right, I accept.",TXT_RPLY0_SCRIPT03_D0_ALLRI,〃,,,"Dobře, příjimám.","Okay, jeg accepterer.","Klar, ich bin dabei.",,"Bone, mi akceptas.","Muy bien, acepto.",,"Hyvä on, suostun auttamaan.",Très bien. J'accepte.,"Rendben, elfogadom.","Va bene, accetto.",いいぞ、引き受けよう。,좋아요. 받아들이죠.,"Oké, ik accepteer het.","Greit, jeg aksepterer.","Dobrze, zgadzam się.","Tá certo, eu aceito.",,"În regulă, accept.",Хорошо. Я согласен.,,"Pekala, kabul ediyorum." -No thanks!,TXT_RPLY1_SCRIPT03_D0_NOTHA,〃,,,"Ne, díky.",Nej tak!,"Nein, danke!",,"Ne, dankon!","¡No, gracias!",,Ei kiitos!,Non merci.,Nem kösz!,"No, grazie!",断る!,사양할게요!,"Nee, dank je wel!",Nei takk!,"Nie, dziękuję!","Não, obrigado!",,Nu merci!,"Нет уж, спасибо!",,"Hayır, teşekkürler!" +我々に手を貸してくれ。","최후의 희망 한 가닥을 잡은 것을 환영합니다. 우리만이 오더를 거부할 수 있는 의지를 갖추고 있죠. 뛰어난 과학력과 전투력은 다 갖추고 있습니다만, 정작 '해결사' 몫을 해주는 인물이 없어서 말입니다... 부디 우리를 도와주시길 바랍니다.","Welkom bij het laatste sprankje hoop. Alleen wij hebben de vrije wil om ons te verzetten tegen de Orde. We hebben de scherpste wetenschappelijke geesten en veel bekwame lichamen, maar we missen die ene echte, uh.... probleemoplosser, die ons de voorsprong zal geven die we nodig hebben. Help ons.","Velkommen til det siste glimt av håp. Bare vi har den frie viljen til å motsette oss Ordenen. Vi har de skarpeste vitenskapelige hodene, og mange dyktige kropper, men vi mangler den ene virkelige... problemløseren, som vil gi oss det forspranget vi trenger. Hjelp oss.","Witaj w ostatniej iskierce nadziei. Tylko my mamy wolną wolę, aby sprzeciwić się Zakonowi. Mamy najmądrzejszych naukowców i wielu ludzi, ale brakuje nam kogoś porządnego by, ehmm... rozwiązać parę problemów, kogoś kto da nam przewagę, której potrzebujemy. Pomóż nam.","Seja bem-vindo à última ponta de esperança. Somente nós temos o livre arbítrio para combater a Ordem. Temos as mentes científicas mais afiadas e muitas pessoas capazes, mas nos falta aquele verdadeiro, hã... quebra-galho, que nos dará o impulso que precisamos. Ajude-nos.",,"Bun venit la ultima fărâmă de speranță. Numai noi avem voința liberă necesară pentru a ne opune Ordinului. Avem cele mai ascuțite minți științifice, și mulți oameni capabili de muncă, dar ne lipsește acel um... adevărat Salvator de la probleme, care să ne ofere avantajul de care avem nevoie. Ajută-ne.","Добро пожаловать в последний оплот надежды. Только мы обладаем свободной волей, чтобы противостоять Ордену. С нами лучшие учёные умы, и у нас есть много толковых людей, но нам не хватает одного-единственного, э... «решателя проблем», который поможет нам получить необходимое преимущество. Помоги нам.",,"Välkommen till den sista flimret av hopp. Endast vi har den fria viljan att motsätta oss Orden. Vi har de skarpaste vetenskapliga hjärnorna och många dugliga kroppar, men vi saknar den där riktiga... Problemlösaren, som kan ge oss det övertag vi behöver. Hjälp oss.","Son umut ışığına hoş geldiniz. Tarikat'a karşı koyacak özgür irade sadece bizde var. En keskin bilimsel zihinlere ve birçok yetenekli bedene sahibiz, ancak bize ihtiyacımız olan avantajı sağlayacak gerçek bir Problem Çözücüden yoksunuz. Bize yardım edin." +"All right, I accept.",TXT_RPLY0_SCRIPT03_D0_ALLRI,〃,,,"Dobře, příjimám.","Okay, jeg accepterer.","Klar, ich bin dabei.",,"Bone, mi akceptas.","Muy bien, acepto.",,"Hyvä on, suostun auttamaan.",Très bien. J'accepte.,"Rendben, elfogadom.","Va bene, accetto.",いいぞ、引き受けよう。,좋아요. 받아들이죠.,"Oké, ik accepteer het.","Greit, jeg aksepterer.","Dobrze, zgadzam się.","Tá certo, eu aceito.",,"În regulă, accept.",Хорошо. Я согласен.,,"Okej, jag accepterar.","Pekala, kabul ediyorum." +No thanks!,TXT_RPLY1_SCRIPT03_D0_NOTHA,〃,,,"Ne, díky.",Nej tak!,"Nein, danke!",,"Ne, dankon!","¡No, gracias!",,Ei kiitos!,Non merci.,Nem kösz!,"No, grazie!",断る!,사양할게요!,"Nee, dank je wel!",Nei takk!,"Nie, dziękuję!","Não, obrigado!",,Nu merci!,"Нет уж, спасибо!",,"Nej, tack!","Hayır, teşekkürler!" "You might want to reconsider, seeing that you're surrounded by heavily armed angry rebels.",TXT_DLG_SCRIPT03_D1516_YOUMI,〃,,,"Možná bys o tom měl popřemýšlet, soudě podle toho, že jsi obklopen po zuby ozbrojenými, naštvanými rebely.","Du bør måske genoverveje det, når du er omgivet af tungt bevæbnede vrede oprørere.","Bitte überdenke das nochmal, angesichts der Tatsache, dass du von befaffneten und zornigen Rebellen umgeben bist.",,"Vi eble volos rekonsideri tion, se ni konsideras, ke vi estas ĉirkaŭita de ege armitaj kaj koleraj ribelantoj.","Puede que quieras reconsiderarlo, ya que estás rodeado de rebeldes ya hartos y bien armados.",,"Haluannet ehkä harkita uudelleen, ottaen huomioon, että ympärilläsi on vihainen joukko raskaasti aseistettuja kapinallisia.","J'espère que vous pouvez y réfléchir. Après tout, vous êtes entouré de rebelles lourdement armés et prêts à se défendre.","Azt ajánlanám, hogy gondold újra, lévén hogy mérges fegyveres lázadók vesznek körbe.","Forse faresti meglio a ripensarci, considerato che sei circondato da ribelli arrabbiati e armati.","少し考え直したほうが良さそうだぞ、 君が重装備の怒れる兵士たちに -囲まれているのはわかるだろう?",다시... 생각을 해보는 게 좋을 것 같군요. 우리 병사들을 당황하게 만든 것 같은데 말이죠.,"Misschien wil je er nog eens over nadenken, aangezien je omringd wordt door zwaar bewapende, boze rebellen.","Du bør kanskje revurdere det, siden du er omringet av tungt bevæpnede, sinte opprørere.","Może zmienisz zdanie, kiedy zauważysz, że jesteś otoczony przez ciężko uzbrojonych, wściekłych rebeliantów.","Talvez você queira reconsiderar, já que está cercado de rebeldes furiosos armados até os dentes.",,"S-ar putea să vrei să reconsideri, având în vedere că ești înconjurat de rebeli nervoși înarmați până în dinți.","Возможно, при виде нервных и вооружённых до зубов повстанцев ты передумаешь.",,Etrafınız ağır silahlı kızgın asilerle çevrili olduğuna göre tekrar düşünmek isteyebilirsiniz. -"All right, I'm in!",TXT_RPLY0_SCRIPT03_D1516_ALLRI,〃,,,"Dobře, jdu do toho!","Okay, jeg er med!","Na gut, ich bin dabei.",,"Bone, mi aliĝos!","De acuerdo, ¡quiero entrar!",,"Hyvä on, olen messissä!","Ok, d'accord, j'accepte!","Rendben, benne vagyok!","Va bene, vi aiuterò!",わかった、乗ろう!,그럼 도와주도록 하죠.,"Oké, ik doe mee!","Greit, jeg er med!","Dobra, wchodzę w to!","Tá certo, estou dentro!",,"Bine, mă bag!","Хорошо, я с вами!",,"Pekala, ben varım!" -No thanks.,TXT_RPLY1_SCRIPT03_D1516_NOTHA,〃,,,"Ne, díky.",Nej tak.,"Nein, danke!",,"Ne, dankon.","No, gracias.",,Ei kiitos.,Non merci.,Nem kösz.,No grazie.,断る。,싫어요! 당신은 낯선 사람이잖아요!,"Nee, bedankt.",Nei takk.,"Nie, dziękuję.","Não, obrigado.",,Nu merci.,"Нет, спасибо.",,"Hayır, teşekkürler." -Then die in shame and dishonor.,TXT_DLG_SCRIPT03_D3032_THEND,〃,,Then die in shame and dishonour.,Pak zemři v hanbě a potupě!,Så dø i skam og vanære.,Dann wirst du in Schande und Unehre sterben.,,Tiuokaze mortu honte kaj senhonore.,Entonces muere en vergüenza y deshonra.,,Sitten kuole häpeässä vailla kunniaa.,Périssez dans la honte et le déshonneur.,Akkor szégyenteljes halál vár rád.,"E allora muori, con vergogna e disonore!",では、恥と不名誉と共に死ぬがいい。,그럼 불명예스럽고 초라하게 죽어버리시길!,Sterf dan in schaamte en oneer.,Så dø i skam og vanære.,Więc giń we wstydzie i hańbie.,Então morra com desonra e vergonha!,,Atunci mori în rușine și dezonoare.,Тогда умри в бесчестии и позоре.,,O zaman utanç ve onursuzluk içinde öl. -"Good, Blackbird will continue to be your guide. She's taken quite a shine to you. Together you've got to unlock the secrets of the Order and their inhuman servants. Get inside and take them down.",TXT_DLG_SCRIPT03_D4548_GOODB,〃,,,"Dobře, Straka ti bude dále dávat pokyny. Docela ses jí zalíbil. Společně budete muset odkrýt tajemství Řádu a jeho nelidských služebníků. Pronikněte dovnitř a sejměte je.","Godt, Blackbird vil fortsat være din guide. Hun er blevet ret glad for dig. Sammen skal I løse hemmelighederne om Ordenen og deres umenneskelige tjenere. Kom ind og nedlæg dem.","Gut so! Blackbird wird weiter deine Leiterin sein, sie scheint dich zu mögen. Zusammen müsst ihr die Geheimnisse des Ordens und ihrer unmenschlichen Diener ergründen. Dann haben wir eine Chance, sie niederzuringen.",,"Bone. BlackBird plue estos via gvidanto; ŝajnas, ke ŝi jam simpatias vin. Vi kune devas malkaŝi la sekretojn de La Ordono kaj de ĝiaj nehomaj servantoj. Enŝoviĝu en la kastelon kaj detruu ilin.",Bien. BlackBird seguirá siendo tu guía; parece que ya le caes bien. Juntos debéis descubrir los secretos de La Orden y de sus sirvientes inhumanos. Infiltraos en el castillo y acabad con ellos.,Bien. BlackBird va a seguir siendo tu guía; parece que ya le caes bien. Juntos deben descubrir los secretos de La Orden y de sus sirvientes inhumanos. Infíltrense al castillo y destrúyanlos.,Hyvä; Blackbird jatkaa opastajanasi. Hän vaikuttaa pitävän sinusta. Teidän on yhdessä paljastettava Veljeskunnan ja heidän epäinhimillisten palvelijoinsa salat. Murtaudu sisään ja aja heidät alas.,"Parfait. Blackbird continuera à être votre guide. Elle semble vous apprécier. Ensemble, vous allez découvrir les secrets de l'Ordre et leurs servants inhumains. Infiltrez-les et détruisez-les.","Helyes, Feketerigó továbbra is az irányítód lesz. Eléggé megtetszettél neki. Együtt meg fogjátok fejteni a Rend és kegyetlen szolgáinak titkait. Hatoljatok be és intézzétek el őket.",Bene. Blackbird continuerà ad essere la tua guida. Sembra ti abbia preso in simpatia. Insieme dovrete scoprire i segreti dell'Ordine e dei loro servi inumani. Bisognerà infiltrarlo e distruggerlo.,"よし、君のガイドをブラックバードが今後務める +囲まれているのはわかるだろう?",다시... 생각을 해보는 게 좋을 것 같군요. 우리 병사들을 당황하게 만든 것 같은데 말이죠.,"Misschien wil je er nog eens over nadenken, aangezien je omringd wordt door zwaar bewapende, boze rebellen.","Du bør kanskje revurdere det, siden du er omringet av tungt bevæpnede, sinte opprørere.","Może zmienisz zdanie, kiedy zauważysz, że jesteś otoczony przez ciężko uzbrojonych, wściekłych rebeliantów.","Talvez você queira reconsiderar, já que está cercado de rebeldes furiosos armados até os dentes.",,"S-ar putea să vrei să reconsideri, având în vedere că ești înconjurat de rebeli nervoși înarmați până în dinți.","Возможно, при виде нервных и вооружённых до зубов повстанцев ты передумаешь.",,"Du kanske vill tänka om, eftersom du är omgiven av tungt beväpnade arga rebeller.",Etrafınız ağır silahlı kızgın asilerle çevrili olduğuna göre tekrar düşünmek isteyebilirsiniz. +"All right, I'm in!",TXT_RPLY0_SCRIPT03_D1516_ALLRI,〃,,,"Dobře, jdu do toho!","Okay, jeg er med!","Na gut, ich bin dabei.",,"Bone, mi aliĝos!","De acuerdo, ¡quiero entrar!",,"Hyvä on, olen messissä!","Ok, d'accord, j'accepte!","Rendben, benne vagyok!","Va bene, vi aiuterò!",わかった、乗ろう!,그럼 도와주도록 하죠.,"Oké, ik doe mee!","Greit, jeg er med!","Dobra, wchodzę w to!","Tá certo, estou dentro!",,"Bine, mă bag!","Хорошо, я с вами!",,"Okej, jag är med!","Pekala, ben varım!" +No thanks.,TXT_RPLY1_SCRIPT03_D1516_NOTHA,〃,,,"Ne, díky.",Nej tak.,"Nein, danke!",,"Ne, dankon.","No, gracias.",,Ei kiitos.,Non merci.,Nem kösz.,No grazie.,断る。,싫어요! 당신은 낯선 사람이잖아요!,"Nee, bedankt.",Nei takk.,"Nie, dziękuję.","Não, obrigado.",,Nu merci.,"Нет, спасибо.",,"Nej, tack.","Hayır, teşekkürler." +Then die in shame and dishonor.,TXT_DLG_SCRIPT03_D3032_THEND,〃,,Then die in shame and dishonour.,Pak zemři v hanbě a potupě!,Så dø i skam og vanære.,Dann wirst du in Schande und Unehre sterben.,,Tiuokaze mortu honte kaj senhonore.,Entonces muere en vergüenza y deshonra.,,Sitten kuole häpeässä vailla kunniaa.,Périssez dans la honte et le déshonneur.,Akkor szégyenteljes halál vár rád.,"E allora muori, con vergogna e disonore!",では、恥と不名誉と共に死ぬがいい。,그럼 불명예스럽고 초라하게 죽어버리시길!,Sterf dan in schaamte en oneer.,Så dø i skam og vanære.,Więc giń we wstydzie i hańbie.,Então morra com desonra e vergonha!,,Atunci mori în rușine și dezonoare.,Тогда умри в бесчестии и позоре.,,Dö då i skam och vanära.,O zaman utanç ve onursuzluk içinde öl. +"Good, Blackbird will continue to be your guide. She's taken quite a shine to you. Together you've got to unlock the secrets of the Order and their inhuman servants. Get inside and take them down.",TXT_DLG_SCRIPT03_D4548_GOODB,〃,,,"Dobře, Straka ti bude dále dávat pokyny. Docela ses jí zalíbil. Společně budete muset odkrýt tajemství Řádu a jeho nelidských služebníků. Pronikněte dovnitř a sejměte je.","Godt, Blackbird vil fortsat være din guide. Hun er blevet ret glad for dig. Sammen skal I løse hemmelighederne om Ordenen og deres umenneskelige tjenere. Kom ind og nedlæg dem.","Gut so! Blackbird wird weiter deine Leiterin sein, sie scheint dich zu mögen. Zusammen müsst ihr die Geheimnisse des Ordens und ihrer unmenschlichen Diener ergründen. Dann haben wir eine Chance, sie niederzuringen.",,"Bone. Merlo plue estos via gvidanto; ŝajnas, ke ŝi jam simpatias vin. Vi kune devas malkaŝi la sekretojn de La Ordeno kaj de ĝiaj nehomaj servantoj. Enŝoviĝu kaj detruu ilin.",Bien. Blackbird seguirá siendo tu guía; parece que ya le caes bien. Juntos debéis descubrir los secretos de La Orden y de sus sirvientes inhumanos. Infiltraos y acabad con ellos.,Bien. Blackbird va a seguir siendo tu guía; parece que ya le caes bien. Juntos deben descubrir los secretos de La Orden y de sus sirvientes inhumanos. Infíltrense y destrúyanlos.,Hyvä; Blackbird jatkaa opastajanasi. Hän vaikuttaa pitävän sinusta. Teidän on yhdessä paljastettava Veljeskunnan ja heidän epäinhimillisten palvelijoinsa salat. Murtaudu sisään ja aja heidät alas.,"Parfait. Blackbird continuera à être votre guide. Elle semble vous apprécier. Ensemble, vous allez découvrir les secrets de l'Ordre et leurs servants inhumains. Infiltrez-les et détruisez-les.","Helyes, Feketerigó továbbra is az irányítód lesz. Eléggé megtetszettél neki. Együtt meg fogjátok fejteni a Rend és kegyetlen szolgáinak titkait. Hatoljatok be és intézzétek el őket.",Bene. Blackbird continuerà ad essere la tua guida. Sembra ti abbia preso in simpatia. Insieme dovrete scoprire i segreti dell'Ordine e dei loro servi inumani. Bisognerà infiltrarlo e distruggerlo.,"よし、君のガイドをブラックバードが今後務める 彼女は君に感心しているようだぞ。 君達の二人で、オーダーとその人間離れした 手下たちが持っている秘密を暴いてもらいたい。 奴等の基地に潜り込んで、倒すんだ。","좋군요. 블랙버드가 당신에게 지시를 계속 내려줄 겁니다. 당신을 꽤 신뢰하는 듯하더군요. 우리는 오더와 그들의 잔혹한 심복들의 실체를 파헤치고 폭로할 겁니다. 비밀을 헤집고 그들을 몰락시켜 버리세요. - \cy듣기만 해도 꿈에 그리던 일만 같네, 그렇지?","Goed, Blackbird zal je gids blijven. Ze heeft een behoorlijke glans aan je genomen. Samen moeten jullie de geheimen van de Orde en hun onmenselijke dienaren ontrafelen. Ga naar binnen en haal ze naar beneden.","Bra, Blackbird vil fortsette å være din guide. Hun har blitt ganske betatt av deg. Sammen må dere avsløre hemmelighetene til Ordenen og deres umenneskelige tjenere. Gå inn og ta dem.","Dobrze, Blackbird dalej będzie twoją przewodniczką. Chyba przepada za tobą. Wspólnie musicie odkryć sekrety zakonu i ich nieludzkich sług. Idź tam i załatw ich.",Ótimo. Blackbird continuará sendo a sua guia. Parece que ela vai com a sua cara. Juntos vocês desvendarão os segredos da Ordem e de seus discípulos desumanos. Entre lá e elimine eles.,,"Bun, Blackbird va fi ghidul tău în continuare. A luat ceva înteres în tine. Împreună trebuie să descoperiți secretele Ordinului și slujitorii lor inumani. Dați buzna ți puneții la pământ.",Хорошо. Чёрный дрозд останется твоим проводником. Она тебе несколько симпатизирует. Вместе вы раскроете секреты Ордена и его нечеловеческих слуг. Проникни туда и покончи с ними! ,,"Güzel, Karatavuk rehberiniz olmaya devam edecek. Senden oldukça hoşlandı. Birlikte Tarikat'ın ve insanlık dışı hizmetkârlarının sırlarını çözmelisiniz. İçeri gir ve onları alaşağı et." -Where do I start?,TXT_RPLY0_SCRIPT03_D4548_WHERE,〃,,,Kde mám začít?,Hvor skal jeg begynde?,Wo fange ich an?,,Kie mi komencu?,¿Por dónde empiezo?,,Mistä aloitan?,Où est-ce que je commence?,Hol kezdjem?,Da dove comincio?,どこから始めればいいんだ?,어디서부터 시작하면 되죠?,Waar moet ik beginnen?,Hvor skal jeg begynne?,Gdzie zaczynam?,Por onde eu começo?,,Unde încep?,С чего мне начать?,,Nereden başlayacağım? -Frankly the situation is a mess. You must accomplish several missions to prepare the way for more attacks on the Order. Our last raid was a disaster and most of our troops were captured. I need you to free these prisoners.,TXT_DLG_SCRIPT03_D6064_FRANK,〃 (Prison mission),,,"Upřímně, současná situace je úděsná. Musíš splnit několik misí před dalšími útoky na Řád. Náš poslední nájezd byla katastrofa a většina našich vojáků byla zajata. Potřebuju, abys tyto vězně vysvobodil.","Helt ærligt, situationen er et rod. Du skal udføre flere missioner for at bane vejen for flere angreb på Ordenen. Vores sidste angreb var en katastrofe, og de fleste af vores tropper blev taget til fange. Jeg har brug for, at du befrier disse fanger.","Ehrlich gesagt, die Situation ist eine Sauerei. Du musst mehrere Aufgaben erfüllen um den Weg für weitere Angriffe vorzubereiten. Der letzte Überfall war ein Desaster und die meisten unserer Leute wurden gefangengenommen. Du musst sie wieder befreien.",,"Sincere la situacio estas malordo. Vi devas plenumi diversajn misiojn, por ke ni povu prepari pliajn atakojn kontraŭ La Ordono. Ni malvenkis la lastan kaj tial La Ordono kaptis la plimulton de niaj trupoj; mi bezonas, ke vi liberigu ilin.","La situación es un lío, a decir verdad. Debes completar varias misiones para poder preparar más ataques contra La Orden. Nuestra última incursión fue un desastre y la mayoría de nuestras tropas fueron capturadas; necesito que las liberes.",,"Rehellisesti sanoen tilanne on sekasortoinen. Sinun on suoritettava lukuisia tehtäviä valmistaaksesi tien lisähyökkäyksille Veljeskuntaa vastaan. Viimeisin hyökkäyksemme oli katastrofi, ja suurin osa joukoistamme vangittiin. Tarvitsen sinua vapauttamaan nämä vangit.","Franchement, nous sommes dans un bazar sans précédent. Vous devez accomplir de nombreuses missions pour préparer nos futures attaques contre l'Ordre. Notre dernier raid à été un désastre et la majorité de nos troupes ont été capturées. Il faut que vous les libérez.","Őszintén szólva a szituáció elég zűrzavaros. Több küldetést is véghez kell vinned, hogy előkészítsd a támadás következő hullámát a Rend ellen. A legutolsó portyánk egy óriási kudarc volt, és a legtöbb egységünket elfogták. Ki kell, hogy engedd őket!","Francamente, la situazione è critica. Dovrai completare diverse missioni per far si da poter preparare nuovi attacchi contro l'Ordine. La nostra ultima incursione è stata in disastro, e la maggiorparte delle nostre truppe sono state catturate. Ho bisogno che tu liberi questi prigionieri.","はっきり言えば、今の状況は全く良くない。 + \cy듣기만 해도 꿈에 그리던 일만 같네, 그렇지?","Goed, Blackbird zal je gids blijven. Ze heeft een behoorlijke glans aan je genomen. Samen moeten jullie de geheimen van de Orde en hun onmenselijke dienaren ontrafelen. Ga naar binnen en haal ze naar beneden.","Bra, Blackbird vil fortsette å være din guide. Hun har blitt ganske betatt av deg. Sammen må dere avsløre hemmelighetene til Ordenen og deres umenneskelige tjenere. Gå inn og ta dem.","Dobrze, Blackbird dalej będzie twoją przewodniczką. Chyba przepada za tobą. Wspólnie musicie odkryć sekrety zakonu i ich nieludzkich sług. Idź tam i załatw ich.",Ótimo. Blackbird continuará sendo a sua guia. Parece que ela vai com a sua cara. Juntos vocês desvendarão os segredos da Ordem e de seus discípulos desumanos. Entre lá e elimine eles.,,"Bun, Blackbird va fi ghidul tău în continuare. A luat ceva înteres în tine. Împreună trebuie să descoperiți secretele Ordinului și slujitorii lor inumani. Dați buzna ți puneții la pământ.",Хорошо. Чёрный дрозд останется твоим проводником. Она тебе несколько симпатизирует. Вместе вы раскроете секреты Ордена и его нечеловеческих слуг. Проникни туда и покончи с ними! ,,"Bra, Blackbird kommer att fortsätta att vara din guide. Hon har blivit ganska förtjust i dig. Tillsammans måste ni avslöja hemligheterna om Orden och deras omänskliga tjänare. Gå in och ta ner dem.","Güzel, Karatavuk rehberiniz olmaya devam edecek. Senden oldukça hoşlandı. Birlikte Tarikat'ın ve insanlık dışı hizmetkârlarının sırlarını çözmelisiniz. İçeri gir ve onları alaşağı et." +Where do I start?,TXT_RPLY0_SCRIPT03_D4548_WHERE,〃,,,Kde mám začít?,Hvor skal jeg begynde?,Wo fange ich an?,,Kie mi komencu?,¿Por dónde empiezo?,,Mistä aloitan?,Où est-ce que je commence?,Hol kezdjem?,Da dove comincio?,どこから始めればいいんだ?,어디서부터 시작하면 되죠?,Waar moet ik beginnen?,Hvor skal jeg begynne?,Gdzie zaczynam?,Por onde eu começo?,,Unde încep?,С чего мне начать?,,Var börjar jag?,Nereden başlayacağım? +Frankly the situation is a mess. You must accomplish several missions to prepare the way for more attacks on the Order. Our last raid was a disaster and most of our troops were captured. I need you to free these prisoners.,TXT_DLG_SCRIPT03_D6064_FRANK,〃 (Prison mission),,,"Upřímně, současná situace je úděsná. Musíš splnit několik misí před dalšími útoky na Řád. Náš poslední nájezd byla katastrofa a většina našich vojáků byla zajata. Potřebuju, abys tyto vězně vysvobodil.","Helt ærligt, situationen er et rod. Du skal udføre flere missioner for at bane vejen for flere angreb på Ordenen. Vores sidste angreb var en katastrofe, og de fleste af vores tropper blev taget til fange. Jeg har brug for, at du befrier disse fanger.","Ehrlich gesagt, die Situation ist eine Sauerei. Du musst mehrere Aufgaben erfüllen um den Weg für weitere Angriffe vorzubereiten. Der letzte Überfall war ein Desaster und die meisten unserer Leute wurden gefangengenommen. Du musst sie wieder befreien.",,"Sincere la situacio estas malordo. Vi devas plenumi diversajn misiojn, por ke ni povu prepari pliajn atakojn kontraŭ La Ordeno. Ni malvenkis la lastan kaj tial La Ordeno kaptis la plimulton de niaj trupoj; mi bezonas, ke vi liberigu ilin.","La situación es un lío, a decir verdad. Debes completar varias misiones para poder preparar más ataques contra La Orden. Nuestra última incursión fue un desastre y la mayoría de nuestras tropas fueron capturadas; necesito que las liberes.",,"Rehellisesti sanoen tilanne on sekasortoinen. Sinun on suoritettava lukuisia tehtäviä valmistaaksesi tien lisähyökkäyksille Veljeskuntaa vastaan. Viimeisin hyökkäyksemme oli katastrofi, ja suurin osa joukoistamme vangittiin. Tarvitsen sinua vapauttamaan nämä vangit.","Franchement, nous sommes dans un bazar sans précédent. Vous devez accomplir de nombreuses missions pour préparer nos futures attaques contre l'Ordre. Notre dernier raid à été un désastre et la majorité de nos troupes ont été capturées. Il faut que vous les libérez.","Őszintén szólva a szituáció elég zűrzavaros. Több küldetést is véghez kell vinned, hogy előkészítsd a támadás következő hullámát a Rend ellen. A legutolsó portyánk egy óriási kudarc volt, és a legtöbb egységünket elfogták. Ki kell, hogy engedd őket!","Francamente, la situazione è critica. Dovrai completare diverse missioni per far si da poter preparare nuovi attacchi contro l'Ordine. La nostra ultima incursione è stata in disastro, e la maggiorparte delle nostre truppe sono state catturate. Ho bisogno che tu liberi questi prigionieri.","はっきり言えば、今の状況は全く良くない。 君は複数の任務をこなし、オーダーへの 攻撃態勢を整える必要がある。 我々が行ったこの前の襲撃は大失敗で、 ほとんどの兵たちは捕らえられてしまった。 君にはその捕らえられた者たちを -救助してもらいたい。","애석하게도, 현재 상황은 엉망입니다. 우리가 오더를 공습하기 전에 당신이 수행해야 할 일이 몇 가지 있습니다. 몇 주 전 공습은 비참한 결과로 끝났고, 대부분의 병사가 감금당했습니다. 그들을 풀어주어야만 합니다.",Eerlijk gezegd is de situatie een puinhoop. Je moet verschillende missies volbrengen om de weg te bereiden voor meer aanvallen op de Orde. Onze laatste inval was een ramp en de meeste van onze troepen werden gevangen genomen. Ik heb je nodig om deze gevangenen te bevrijden.,"Ærlig talt er situasjonen et rot. Du må utføre flere oppdrag for å bane vei for flere angrep på Ordenen. Vårt siste angrep var en katastrofe, og de fleste av våre tropper ble tatt til fange. Du må befri disse fangene.","Szczerze to mamy tu bałagan. Musisz ukończyć kilka misji, by przygotować drogę na więcej ataków na Zakon. Nasz ostatni nalot był porażką i większość naszych żołnierzy została złapana. Potrzebuję cię, byś uwolnił tych więźniów.",Sinceramente a situação é uma bagunça. Você precisa cumprir algumas missões para preparar o caminho para mais ataques contra a Ordem. Nossa última invasão foi um desastre e muitas das nossas tropas foram capturadas. Preciso que você liberte esses prisioneiros.,,Sincer situația e nasoală. Trebuie să îndepliniți câteva misiune pentru a pregătii calea pentru mai multe atacuri asupra Ordinului. Ultimul nostru raid a fost un dezastru și majoritatea trupelor noastre au fost capturate. Am nevoie ca voi să eliberați prizonierii.,"Честно говоря, наши дела идут не лучшим образом. Тебе предстоит выполнить несколько заданий, чтобы подготовить почву для дальнейших атак на Орден. Наша последняя вылазка обернулась катастрофой, и большинство наших бойцов были схвачены. Мне нужно, чтобы ты освободил их.",,Açıkçası durum tam bir karmaşa. Tarikat'a daha fazla saldırının yolunu hazırlamak için birkaç görevi tamamlamalısınız. Son baskınımız bir felaketti ve askerlerimizin çoğu esir alındı. Bu esirleri serbest bırakmanı istiyorum. -I think I can handle it.,TXT_RPLY0_SCRIPT03_D6064_ITHIN,〃 (〃),,,"Myslím, že to zvládnu.","Jeg tror, jeg kan klare det.","Ich denke, das kann ich schaffen.",,"Mi pensas, ke mi povos fari tion.",Creo poder hacerlo.,,Eiköhän se onnistu.,Je pense pouvoir m'en occuper.,Azt hiszem el tudom intézni.,Penso di potercela fare.,俺ならできるはずだ。,아마도 제가 할 수 있을 것 같군요.,Ik denk dat ik het aankan.,Jeg tror jeg kan klare det.,"Myślę, że dam sobie z tym radę.",Acho que eu posso dar conta disso.,,Cred că mă pot descurca.,"Думаю, справлюсь.",,Sanırım ben halledebilirim. -"Take this money and visit Irale who supplies our weapons. Then, this key will get you in to see the Governor. He's a corrupt puppet of the Order, but he loves to make deals. Do whatever you need to free our brothers in arms.",TXT_DLG_SCRIPT03_D7580_TAKET,〃 (〃),,,"Vem si tohle zlato a navštiv Iraleho, který nás zásobuje zbraněmi. Tento klíč tě pak dostane ke guvernérovi. Je to jen zkorumpovaná loutka Řádu, ale zbožňuje nabídky. Udělej cokoliv je třeba, abys osvobodil naše bratry ve zbrani.","Tag disse penge og besøg Irale, som leverer vores våben. Så vil denne nøgle give dig adgang til guvernøren. Han er en korrupt marionet af Ordenen, men han elsker at lave aftaler. Gør hvad du skal gøre for at befri vores våbenbrødre.","Nimm das Geld hier und geh zu Irale, der und mit Waffen versorgt. Und dieser Schlüssel erlaubt die Zutritt zum Haus des Gouverneurs. Er ist eine korrupte Marionette des Ordens aber er liebt es, Deals zu machen. Mach was nötig ist um unsere Waffenbrüder zu befreien.",,"Prenu ĉi tiun monon kaj renkontu Irale, la provizanto de niaj armiloj. Poste ĉi tiu ŝlosilo ebligos al vi renkonti la registon. Li estas koruptita marioneto de La Ordono, sed li ŝategas intertraktadojn. Faru tion ajn, kion vi bezonas por liberigi niajn soldatojn.","Ten este dinero y ve a ver a Irale, que suministra nuestras armas. Después, esta llave te servirá para ver al gobernador. Es una marioneta corrupta de La Orden, pero le encantan los tratos. Haz lo que creas necesario para liberar a nuestros conmilitones.","Toma este dinero y ve a ver a Irale, que suministra nuestras armas. Después, esta llave te va a servir para ver al gobernador. Es una marioneta corrupta de La Orden, pero le encantan los tratos. Haz lo que creas necesario para liberar a nuestros conmilitones.","Ota tästä rahaa ja käväise Iralen luona, joka toimittaa meidän aseemme. Sitten tällä avaimella pääset tapaamaan kuvernööriä. Hän on Veljeskunnan läpimätä sätkynukke, mutta hän rakastaa tehdä kauppoja. Tee kaikkesi vapauttaaksesi aseveljemme.",Prenez cet argent et allez voir Irale qui nous approvisionne en armes. Utilisez ensuite cette clé pour aller voir le gouverneur. Il est un pantin de l'Ordre mais il adore faire affaires. Faites ce qu'il faut pour libérer nos compatriotes.,"Fogd ezt a pénzt, és látogasd meg Irale-t a fegyverellátónkat. Azután, ezzel a kulccsal be tudsz jutni a kormányzóhoz. Ő a Rend egy korrupt bábja, de imád üzletet kötni. Tegyél meg mindent, hogy kiszabadítsd a bajtársainkat.","Prendi questo denaro e vai da Irale, uno dei nostri fornitori d'armi. Dopodiché, con questa chiave potrai entrare nella dimora del governatore. È un pupazzo corrotto dell'Ordine, ma adora trattare sottobanco. Fai tutto il necessario per liberare i nostri compagni d'arme.","この金で、我らの武器を調達してくれている +救助してもらいたい。","애석하게도, 현재 상황은 엉망입니다. 우리가 오더를 공습하기 전에 당신이 수행해야 할 일이 몇 가지 있습니다. 몇 주 전 공습은 비참한 결과로 끝났고, 대부분의 병사가 감금당했습니다. 그들을 풀어주어야만 합니다.",Eerlijk gezegd is de situatie een puinhoop. Je moet verschillende missies volbrengen om de weg te bereiden voor meer aanvallen op de Orde. Onze laatste inval was een ramp en de meeste van onze troepen werden gevangen genomen. Ik heb je nodig om deze gevangenen te bevrijden.,"Ærlig talt er situasjonen et rot. Du må utføre flere oppdrag for å bane vei for flere angrep på Ordenen. Vårt siste angrep var en katastrofe, og de fleste av våre tropper ble tatt til fange. Du må befri disse fangene.","Szczerze to mamy tu bałagan. Musisz ukończyć kilka misji, by przygotować drogę na więcej ataków na Zakon. Nasz ostatni nalot był porażką i większość naszych żołnierzy została złapana. Potrzebuję cię, byś uwolnił tych więźniów.",Sinceramente a situação é uma bagunça. Você precisa cumprir algumas missões para preparar o caminho para mais ataques contra a Ordem. Nossa última invasão foi um desastre e muitas das nossas tropas foram capturadas. Preciso que você liberte esses prisioneiros.,,Sincer situația e nasoală. Trebuie să îndepliniți câteva misiune pentru a pregătii calea pentru mai multe atacuri asupra Ordinului. Ultimul nostru raid a fost un dezastru și majoritatea trupelor noastre au fost capturate. Am nevoie ca voi să eliberați prizonierii.,"Честно говоря, наши дела идут не лучшим образом. Тебе предстоит выполнить несколько заданий, чтобы подготовить почву для дальнейших атак на Орден. Наша последняя вылазка обернулась катастрофой, и большинство наших бойцов были схвачены. Мне нужно, чтобы ты освободил их.",,Ärligt talat är situationen en enda röra. Du måste utföra flera uppdrag för att bereda vägen för fler attacker mot Orden. Vår senaste räd var en katastrof och de flesta av våra trupper blev tillfångatagna. Jag behöver dig för att befria dessa fångar.,Açıkçası durum tam bir karmaşa. Tarikat'a daha fazla saldırının yolunu hazırlamak için birkaç görevi tamamlamalısınız. Son baskınımız bir felaketti ve askerlerimizin çoğu esir alındı. Bu esirleri serbest bırakmanı istiyorum. +I think I can handle it.,TXT_RPLY0_SCRIPT03_D6064_ITHIN,〃 (〃),,,"Myslím, že to zvládnu.","Jeg tror, jeg kan klare det.","Ich denke, das kann ich schaffen.",,"Mi pensas, ke mi povos fari tion.",Creo poder hacerlo.,,Eiköhän se onnistu.,Je pense pouvoir m'en occuper.,Azt hiszem el tudom intézni.,Penso di potercela fare.,俺ならできるはずだ。,아마도 제가 할 수 있을 것 같군요.,Ik denk dat ik het aankan.,Jeg tror jeg kan klare det.,"Myślę, że dam sobie z tym radę.",Acho que eu posso dar conta disso.,,Cred că mă pot descurca.,"Думаю, справлюсь.",,Jag tror att jag klarar av det.,Sanırım ben halledebilirim. +"Take this money and visit Irale who supplies our weapons. Then, this key will get you in to see the Governor. He's a corrupt puppet of the Order, but he loves to make deals. Do whatever you need to free our brothers in arms.",TXT_DLG_SCRIPT03_D7580_TAKET,〃 (〃),,,"Vem si tohle zlato a navštiv Iraleho, který nás zásobuje zbraněmi. Tento klíč tě pak dostane ke guvernérovi. Je to jen zkorumpovaná loutka Řádu, ale zbožňuje nabídky. Udělej cokoliv je třeba, abys osvobodil naše bratry ve zbrani.","Tag disse penge og besøg Irale, som leverer vores våben. Så vil denne nøgle give dig adgang til guvernøren. Han er en korrupt marionet af Ordenen, men han elsker at lave aftaler. Gør hvad du skal gøre for at befri vores våbenbrødre.","Nimm das Geld hier und geh zu Irale, der und mit Waffen versorgt. Und dieser Schlüssel erlaubt die Zutritt zum Haus des Gouverneurs. Er ist eine korrupte Marionette des Ordens aber er liebt es, Deals zu machen. Mach was nötig ist um unsere Waffenbrüder zu befreien.",,"Prenu ĉi tiun monon kaj renkontu Irale-n, la provizanto de niaj armiloj. Poste ĉi tiu ŝlosilo ebligos al vi renkonti la registon. Li estas koruptita marioneto de La Ordeno, sed li ŝategas intertraktadojn. Faru tion ajn, kion vi bezonas por liberigi niajn soldatojn.","Toma este dinero y ve a ver a Irale, que suministra nuestras armas. Después, esta llave te servirá para ver al gobernador. Es una marioneta corrupta de La Orden, pero le encantan los tratos. Haz lo que creas necesario para liberar a nuestros conmilitones.","Toma este dinero y ve a ver a Irale, que suministra nuestras armas. Después, esta llave te va a servir para ver al gobernador. Es una marioneta corrupta de La Orden, pero le encantan los tratos. Haz lo que creas necesario para liberar a nuestros conmilitones.","Ota tästä rahaa ja käväise Iralen luona, joka toimittaa meidän aseemme. Sitten tällä avaimella pääset tapaamaan kuvernööriä. Hän on Veljeskunnan läpimätä sätkynukke, mutta hän rakastaa tehdä kauppoja. Tee kaikkesi vapauttaaksesi aseveljemme.",Prenez cet argent et allez voir Irale qui nous approvisionne en armes. Utilisez ensuite cette clé pour aller voir le gouverneur. Il est un pantin de l'Ordre mais il adore faire affaires. Faites ce qu'il faut pour libérer nos compatriotes.,"Fogd ezt a pénzt, és látogasd meg Irale-t a fegyverellátónkat. Azután, ezzel a kulccsal be tudsz jutni a kormányzóhoz. Ő a Rend egy korrupt bábja, de imád üzletet kötni. Tegyél meg mindent, hogy kiszabadítsd a bajtársainkat.","Prendi questo denaro e vai da Irale, uno dei nostri fornitori d'armi. Dopodiché, con questa chiave potrai entrare nella dimora del governatore. È un pupazzo corrotto dell'Ordine, ma adora trattare sottobanco. Fai tutto il necessario per liberare i nostri compagni d'arme.","この金で、我らの武器を調達してくれている イラールの元を訪ねて行け。 その次に、この鍵を使って知事に会え。 知事はオーダーの腐敗した傀儡だが取引には 興味を持ってくれる。我々の仲間を助けるために どんな手でも使ってくれ。","이 돈을 가지고 마을의 무기상인 이롤리를 찾아가시길 바랍니다. 그리고 이 열쇠만 있으면 모렐 총독을 쉽게 만날 수 있을 겁니다. 그는 부패한 오더의 앞잡이지만, 거래에 미쳐있죠. 우리 요원들을 풀어줄 무슨 수단이든 강구해 보시길. - \cy그리고 내가 너와 함께 있어 줄께.","Neem dit geld en bezoek Irale die onze wapens levert. Dan zal deze sleutel je naar binnen brengen om de Gouverneur te zien. Hij is een corrupte marionet van de Orde, maar hij houdt ervan om deals te sluiten. Doe alles wat je nodig hebt om onze broeders te bevrijden.","Ta disse pengene og besøk Irale som leverer våpnene våre. Med denne nøkkelen kommer du inn til guvernøren. Han er en korrupt nikkedukke for Ordenen, men han elsker å inngå avtaler. Gjør det du må for å befri våre våpenbrødre.","Weź te pieniądze i idź do Irale, który dostarcza nam bronie. Potem, ten klucz pozwoli ci spotkać się z Gubernatorem. Jest on skorumpowaną marionetką Zakonu, ale lubi robić interesy. Rób co musisz by uwolnić naszych towarzyszy broni.","Pegue este dinheiro e visite o Irale, nosso fornecedor de armas. Depois use esta chave para entrar e falar com o Governador. Ele é um fantoche corrupto da Ordem mas ele adora negociar. Faça o que for necessário para libertar os nossos irmãos de armas.",,"Ia acești bani și vizitează pe Irale, cel care ne aprovizionează cu arme. Apoi, cheia asta îți va permite să intri să îl vezi pe Guvernator. El este o marionetă coruptă a Ordinului, dar adoră să facă târguri. Fă orice e necesar pentru a ne putea elibera frații.","Возьми эти деньги и посети Ирэйла, нашего поставщика оружия. Затем, с этим ключом, ты пройдёшь к губернатору. Он продажная марионетка Ордена, но обожает торговаться. Делай всё, что сочтёшь нужным, но освободи наших братьев по оружию.",,"Bu parayı al ve silahlarımızı tedarik eden İrale'yi ziyaret et. Sonra, bu anahtar seni valiyi görmeye götürecek. Tarikat'ın yozlaşmış bir kuklasıdır ama anlaşma yapmayı sever. Silah arkadaşlarımızı serbest bırakmak için ne gerekiyorsa yap." -I'll see to it.,TXT_RPLY0_SCRIPT03_D7580_ILLSE,〃 (〃),,,Dohlédnu na to.,Jeg skal nok sørge for det.,"Ich seh, was ich machen kann.",,"Mi vidos tion, kion mi faru.",Veré qué hacer.,Voy a ver qué hacer.,Hoidan asian.,Je m'y attelle.,Megteszem.,Mi darò da fare.,了解した。,한 번 확인하러 가보겠습니다.,Ik zal ervoor zorgen.,Jeg skal sørge for det.,Zajmę się tym.,Vou dar um jeito nisso.,,O să mă ocup.,Я позабочусь об этом.,,Ben halledeceğim. -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D9096_FIGHT,〃 (〃),,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Batalu pro la Fronto kaj liberigota lando. Ekagu.,Lucha por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het Front en vrijheid. Verhuizen.,Kjemp for Fronten og friheten. Av sted.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Выдвигайся.,,Cephe ve özgürlük için savaşın. Dışarı çıkın. -"The prisoners have been welcomed back, thanks to you. Here's some gold, go visit the medic and the weapons trainer and then, I have higher goals for you.",TXT_DLG_SCRIPT03_D10612_THEPR,〃 (Crystal mission),,,"Vězně jsme, díky tobě, přivítali zpět. Tady je nějaké zlato, jdi navštívit zdravotníka a zbraňmistra. Pak mám pro tebe vyšší cíle.","Fangerne er blevet budt velkommen tilbage, takket være dig. Her er lidt guld, besøg lægen og våbentræneren, og så har jeg højere mål for dig.","Die Gefangenen sind zu uns zrückgekehrt, dank dir. Hier hast du etwas Gold, schau mal beim Sanitäter und beim Waffentrainer rein, danach sind höhere Ziele in Aussicht.",,"Ni povis ribonveni la ekskaptitojn danke al vi. Jen iom da oro; iru renkonti la kuraciston kaj la armilan trejniston, kaj tiam mi havas pli altajn celojn por vi.","Los prisioneros ya han sido bienvenidos de vuelta gracias a ti. Aquí tienes algo de oro; ve a ver al médico y al entrenador de armas, y después... tengo mayores metas para ti.","Los prisioneros ya fueron bienvenidos de vuelta gracias a ti. Aquí tienes algo de oro; ve a ver al médico y al entrenador de armas, y después... tengo mayores metas para ti.","Vangit on otettu takaisin vastaan, kiitos sinun. Tässä kultaa; mene tapaamaan lääkintämiestä ja asekouluttajaa, minkä jälkeen minulla on sinulle korkeampia tavoitteita.","Les prisonniers sont revenus à bon port, grâce à vous. Voici de l'argent, allez voir le médecin et le maître d'armes, puis j'aurais d'autres missions pour vous.","A foglyok visszatértek hála neked. Itt van valamennyi arany, látogasd meg a szanitécot és a fegyverkereskedőt, aztán térj vissza mert nagy céljaim vannak veled.","I prigionieri sono stati riportati sani e salvi, grazie a te. Ecco dell'oro. Visita il dottore e l'istruttore d'armi, e poi, ho altri obiettivi per te.","逃げ出した囚人たちを迎え入れた。 + \cy그리고 내가 너와 함께 있어 줄께.","Neem dit geld en bezoek Irale die onze wapens levert. Dan zal deze sleutel je naar binnen brengen om de Gouverneur te zien. Hij is een corrupte marionet van de Orde, maar hij houdt ervan om deals te sluiten. Doe alles wat je nodig hebt om onze broeders te bevrijden.","Ta disse pengene og besøk Irale som leverer våpnene våre. Med denne nøkkelen kommer du inn til guvernøren. Han er en korrupt nikkedukke for Ordenen, men han elsker å inngå avtaler. Gjør det du må for å befri våre våpenbrødre.","Weź te pieniądze i idź do Irale, który dostarcza nam bronie. Potem, ten klucz pozwoli ci spotkać się z Gubernatorem. Jest on skorumpowaną marionetką Zakonu, ale lubi robić interesy. Rób co musisz by uwolnić naszych towarzyszy broni.","Pegue este dinheiro e visite o Irale, nosso fornecedor de armas. Depois use esta chave para entrar e falar com o Governador. Ele é um fantoche corrupto da Ordem mas ele adora negociar. Faça o que for necessário para libertar os nossos irmãos de armas.",,"Ia acești bani și vizitează pe Irale, cel care ne aprovizionează cu arme. Apoi, cheia asta îți va permite să intri să îl vezi pe Guvernator. El este o marionetă coruptă a Ordinului, dar adoră să facă târguri. Fă orice e necesar pentru a ne putea elibera frații.","Возьми эти деньги и посети Ирэйла, нашего поставщика оружия. Затем, с этим ключом, ты пройдёшь к губернатору. Он продажная марионетка Ордена, но обожает торговаться. Делай всё, что сочтёшь нужным, но освободи наших братьев по оружию.",,"Ta de här pengarna och besök Irale som levererar våra vapen. Sedan kommer den här nyckeln att ge dig tillträde till guvernören. Han är en korrupt marionett för Orden, men han älskar att göra affärer. Gör vad du behöver för att befria våra vapenbröder.","Bu parayı al ve silahlarımızı tedarik eden İrale'yi ziyaret et. Sonra, bu anahtar seni valiyi görmeye götürecek. Tarikat'ın yozlaşmış bir kuklasıdır ama anlaşma yapmayı sever. Silah arkadaşlarımızı serbest bırakmak için ne gerekiyorsa yap." +I'll see to it.,TXT_RPLY0_SCRIPT03_D7580_ILLSE,〃 (〃),,,Dohlédnu na to.,Jeg skal nok sørge for det.,"Ich seh, was ich machen kann.",,"Mi vidos tion, kion mi faru.",Veré qué hacer.,Voy a ver qué hacer.,Hoidan asian.,Je m'y attelle.,Megteszem.,Mi darò da fare.,了解した。,한 번 확인하러 가보겠습니다.,Ik zal ervoor zorgen.,Jeg skal sørge for det.,Zajmę się tym.,Vou dar um jeito nisso.,,O să mă ocup.,Я позабочусь об этом.,,Jag ska se till det.,Ben halledeceğim. +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D9096_FIGHT,〃 (〃),,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Bataladu pro la Fronto kaj libereco. Ekagu.,Pelea por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het Front en vrijheid. Verhuizen.,Kjemp for Fronten og friheten. Av sted.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Выдвигайся.,,Kämpa för fronten och friheten. Gå ut.,Cephe ve özgürlük için savaşın. Dışarı çıkın. +"The prisoners have been welcomed back, thanks to you. Here's some gold, go visit the medic and the weapons trainer and then, I have higher goals for you.",TXT_DLG_SCRIPT03_D10612_THEPR,〃 (Crystal mission),,,"Vězně jsme, díky tobě, přivítali zpět. Tady je nějaké zlato, jdi navštívit zdravotníka a zbraňmistra. Pak mám pro tebe vyšší cíle.","Fangerne er blevet budt velkommen tilbage, takket være dig. Her er lidt guld, besøg lægen og våbentræneren, og så har jeg højere mål for dig.","Die Gefangenen sind zu uns zrückgekehrt, dank dir. Hier hast du etwas Gold, schau mal beim Sanitäter und beim Waffentrainer rein, danach sind höhere Ziele in Aussicht.",,"Ni povis rebonveni la ekskaptitojn danke al vi. Jen iom da oro; iru renkonti la kuraciston kaj la armilan trejniston, kaj tiam mi havas pli altajn celojn por vi.","Los prisioneros ya han sido bienvenidos de vuelta gracias a ti. Toma este oro, ve a ver al médico y al entrenador de armas, y después... tengo mayores metas para ti.","Los prisioneros ya fueron bienvenidos de vuelta gracias a ti. Toma este oro, ve a ver al médico y al entrenador de armas, y después... tengo mayores metas para ti.","Vangit on otettu takaisin vastaan, kiitos sinun. Tässä kultaa; mene tapaamaan lääkintämiestä ja asekouluttajaa, minkä jälkeen minulla on sinulle korkeampia tavoitteita.","Les prisonniers sont revenus à bon port, grâce à vous. Voici de l'argent, allez voir le médecin et le maître d'armes, puis j'aurais d'autres missions pour vous.","A foglyok visszatértek hála neked. Itt van valamennyi arany, látogasd meg a szanitécot és a fegyverkereskedőt, aztán térj vissza mert nagy céljaim vannak veled.","I prigionieri sono stati riportati sani e salvi, grazie a te. Ecco dell'oro. Visita il dottore e l'istruttore d'armi, e poi, ho altri obiettivi per te.","逃げ出した囚人たちを迎え入れた。 君の活躍に感謝する。幾つか報酬を与えよう。 それとメディックと訓練師も訪ねるといい、 -その後に頼みたいことがある。",감금된 병사들이 당신 덕에 다시 돌아왔습니다. 정말 감사드립니다! 이 보상을 받으시고 의무관이랑 무기 담당관을 찾아뵈시길 바랍니다. 또 다른 임무가 기다리고 있으니까요.,"De gevangenen zijn dankzij u weer welkom teruggekomen. Hier is wat goud, ga naar de dokter en de wapentrainer en dan heb ik hogere doelen voor je.","Fangene har blitt ønsket velkommen tilbake, takket være deg. Her er litt gull, gå og besøk saniteten og våpentreneren, og så har jeg høyere mål for deg.","Więźniowie zostali ponownie powitani, wszystko dzięki tobie. Masz tu trochę złota, idź do medyka i instruktora broni, a potem powiem ci jakie większe zadania mam dla ciebie.","Recebemos os prisioneiros de volta, graças a você. Pegue este dinheiro, visite o médico, o treinador de armas e depois eu vou te dar uns objetivos mais importantes.",,"Prizonierii au fost primiți înapoi, mulțumită ție. Uite niște aur, vizitează medicul și antrenorul de arme, după aceea, am planuri mai mărețe pentru tine.","Благодаря тебе, пленники вернулись к нам. Вот немного золота. Посети медика и инструктора по стрельбе, а потом тебя ждут ещё более ответственные задания.",,"Sayende mahkumlar geri döndü. İşte biraz altın, sıhhiyeciyi ve silah eğitmenini ziyaret et ve sonra, senin için daha yüksek hedeflerim var." -I will. What's next?,TXT_RPLY0_SCRIPT03_D10612_IWILL,〃 (〃),,,Půjdu. Co dál?,Det vil jeg gøre. Hvad er det næste?,"Alles klar, was gibt's als Nächstes?",,Mi faros tion. Kio sekvas?,Lo haré. ¿Qué sigue?,Claro. ¿Qué sigue?,Menen. Mitä seuraavaksi on luvassa?,"Très bien, quoi maintenant?",Így teszek. Mi a következő lépés?,Lo farò. Qual'è la prossima mossa?,次は何だ?,그렇군요. 그 다음은 뭐죠?,Dat zal ik doen. Wat is het volgende?,Det skal jeg gjøre. Hva er det neste?,Dobrze. Co dalej?,Farei isso. Qual a próxima missão?,,Mă voi conforma. Ce facem mai departe?,Хорошо. Что дальше?,,Yapacağım. Sırada ne var? -"A single crystal runs the power grid which drives the Order's shields. Destroy that crystal and you will punch huge holes in the Order's defenses. Blackbird will lead you to a spy who has a way in, good luck.",TXT_DLG_SCRIPT03_D12128_ASING,〃 (〃),,,"Elektrická síť, kterou jsou poháněné štíty Řádu, je napájena z jednoho krystalu. Znič ten krystal a zasaď tak obří ránu obranám Řádu. Straka tě navede ke špiónovi, který zná cestu dovnitř. Hodně štěstí.","En enkelt krystal driver det kraftnet, der driver ordenens skjolde. Ødelæg det krystal, og du vil slå store huller i Ordenens forsvar. Blackbird vil føre dig til en spion, der har en vej ind, held og lykke.","Ein einziger Kristall kontrolliert das gesamte Energiesystem für die Kraftschilde des Ordens. Zerstöre diesen Kristall und du wirst riesige Löcher in die Verteidigungsanlagen des Ordens schlagen. Blackbird führt dich zu einem Spion, der dir Einlass verschaffen kann. Viel Glück.",,"Ununura kristalo nutras la elektrizan sistemon, kiu tenas la ŝildojn de la kastelo. Detruu ĝin por fari grandegan «breĉon» en la defendojn de La Ordono. BlackBird gvidos vin al spiono, kiu havas manieron eniri. Ŝancon.",Un único cristal alimenta la red eléctrica que mantiene los escudos del castillo. Destruye ese cristal y abrirás grandes brechas en las defensas de La Orden. BlackBird te guiará hacia un espía que tiene una forma de entrar. Buena suerte.,Un único cristal alimenta la red eléctrica que mantiene los escudos del castillo. Destruye ese cristal para abrir grandes brechas en las defensas de La Orden. BlackBird te va a guiar hacia un espía que tiene una forma de entrar. Buena suerte.,"Kaupungin sähköverkon voimanlähteenä toimii yksittäinen kristalli, jonka voimaa Veljeskunnan kilvet käyttävät. Tuhoamalla kristallin puhkot valtavia reikiä Veljeskunnan puolustuksiin. Blackbird opastaa sinut vakoojan luo, jolla on sisäänpääsykeino. Lykkyä tykö.",Un seul cristal fait fonctionner la grille énergétique qui alimente les boucliers de l'Ordre. Détruisez ce cristal et vous créez des énormes failles dans les défenses de l'Ordre. Blackbird va vous mener à un espion qui a un moyen de vous faire rentrer. Bonne chance.,"Egyetlen krisztály hajtja az energia hálózatot, erre van rákötve a Rend pajzsa. Semmisítsd meg ezt a kristályt, és hatalmas lyukakat fogsz vágni a Rend védelmébe. Feketerigó elvezet egy spionhoz, aki tudja hogyan kell bejutni, sok sikert.","Un singolo cristallo alimenta l'impianto energetico che controlla gli scudi dell'Ordine. Distruggendo quel cristallo causerai enormi danni alle difese dell'Ordine. Blackbird ti porterà da una spia che ha indicazioni su come accedere al cristallo, buona fortuna.","とあるパワークリスタルがオーダー基地の +その後に頼みたいことがある。",감금된 병사들이 당신 덕에 다시 돌아왔습니다. 정말 감사드립니다! 이 보상을 받으시고 의무관이랑 무기 담당관을 찾아뵈시길 바랍니다. 또 다른 임무가 기다리고 있으니까요.,"De gevangenen zijn dankzij u weer welkom teruggekomen. Hier is wat goud, ga naar de dokter en de wapentrainer en dan heb ik hogere doelen voor je.","Fangene har blitt ønsket velkommen tilbake, takket være deg. Her er litt gull, gå og besøk saniteten og våpentreneren, og så har jeg høyere mål for deg.","Więźniowie zostali ponownie powitani, wszystko dzięki tobie. Masz tu trochę złota, idź do medyka i instruktora broni, a potem powiem ci jakie większe zadania mam dla ciebie.","Recebemos os prisioneiros de volta, graças a você. Pegue este dinheiro, visite o médico, o treinador de armas e depois eu vou te dar uns objetivos mais importantes.",,"Prizonierii au fost primiți înapoi, mulțumită ție. Uite niște aur, vizitează medicul și antrenorul de arme, după aceea, am planuri mai mărețe pentru tine.","Благодаря тебе, пленники вернулись к нам. Вот немного золота. Посети медика и инструктора по стрельбе, а потом тебя ждут ещё более ответственные задания.",,"Fångarna har välkomnats tillbaka, tack vare dig. Här är lite guld, besök läkaren och vapentränaren och sedan har jag högre mål för dig.","Sayende mahkumlar geri döndü. İşte biraz altın, sıhhiyeciyi ve silah eğitmenini ziyaret et ve sonra, senin için daha yüksek hedeflerim var." +I will. What's next?,TXT_RPLY0_SCRIPT03_D10612_IWILL,〃 (〃),,,Půjdu. Co dál?,Det vil jeg gøre. Hvad er det næste?,"Alles klar, was gibt's als Nächstes?",,Kompreneble. Kio sekvas?,Lo haré. ¿Qué sigue?,Claro. ¿Qué sigue?,Menen. Mitä seuraavaksi on luvassa?,"Très bien, quoi maintenant?",Így teszek. Mi a következő lépés?,Lo farò. Qual'è la prossima mossa?,次は何だ?,그렇군요. 그 다음은 뭐죠?,Dat zal ik doen. Wat is het volgende?,Det skal jeg gjøre. Hva er det neste?,Dobrze. Co dalej?,Farei isso. Qual a próxima missão?,,Mă voi conforma. Ce facem mai departe?,Хорошо. Что дальше?,,Det kommer jag att göra. Vad kommer härnäst?,Yapacağım. Sırada ne var? +"A single crystal runs the power grid which drives the Order's shields. Destroy that crystal and you will punch huge holes in the Order's defenses. Blackbird will lead you to a spy who has a way in, good luck.",TXT_DLG_SCRIPT03_D12128_ASING,〃 (〃),,,"Elektrická síť, kterou jsou poháněné štíty Řádu, je napájena z jednoho krystalu. Znič ten krystal a zasaď tak obří ránu obranám Řádu. Straka tě navede ke špiónovi, který zná cestu dovnitř. Hodně štěstí.","En enkelt krystal driver det kraftnet, der driver ordenens skjolde. Ødelæg det krystal, og du vil slå store huller i Ordenens forsvar. Blackbird vil føre dig til en spion, der har en vej ind, held og lykke.","Ein einziger Kristall kontrolliert das gesamte Energiesystem für die Kraftschilde des Ordens. Zerstöre diesen Kristall und du wirst riesige Löcher in die Verteidigungsanlagen des Ordens schlagen. Blackbird führt dich zu einem Spion, der dir Einlass verschaffen kann. Viel Glück.",,"Ununura kristalo nutras la elektrizan sistemon, kiu tenas la ŝildojn de la kastelo. Detruu ĝin por fari grandegan «breĉon» en la defendojn de La Ordeno. Merlo gvidos vin al spiono, kiu havas manieron eniri. Ŝancon.",Un único cristal alimenta la red eléctrica que mantiene los escudos del castillo. Destruye ese cristal para abrir grandes brechas en las defensas de La Orden. Blackbird te guiará hacia un espía que tiene una forma de entrar. Buena suerte.,Un único cristal alimenta la red eléctrica que mantiene los escudos del castillo. Destruye ese cristal para abrir grandes brechas en las defensas de La Orden. Blackbird te va a guiar hacia un espía que tiene una forma de entrar. Buena suerte.,"Kaupungin sähköverkon voimanlähteenä toimii yksittäinen kristalli, jonka voimaa Veljeskunnan kilvet käyttävät. Tuhoamalla kristallin puhkot valtavia reikiä Veljeskunnan puolustuksiin. Blackbird opastaa sinut vakoojan luo, jolla on sisäänpääsykeino. Lykkyä tykö.",Un seul cristal fait fonctionner la grille énergétique qui alimente les boucliers de l'Ordre. Détruisez ce cristal et vous créez des énormes failles dans les défenses de l'Ordre. Blackbird va vous mener à un espion qui a un moyen de vous faire rentrer. Bonne chance.,"Egyetlen krisztály hajtja az energia hálózatot, erre van rákötve a Rend pajzsa. Semmisítsd meg ezt a kristályt, és hatalmas lyukakat fogsz vágni a Rend védelmébe. Feketerigó elvezet egy spionhoz, aki tudja hogyan kell bejutni, sok sikert.","Un singolo cristallo alimenta l'impianto energetico che controlla gli scudi dell'Ordine. Distruggendo quel cristallo causerai enormi danni alle difese dell'Ordine. Blackbird ti porterà da una spia che ha indicazioni su come accedere al cristallo, buona fortuna.","とあるパワークリスタルがオーダー基地の シールドを維持している。それを破壊して 奴等の防壁に巨大な穴を開けるのだ。 潜入する為の情報を持ったスパイを ブラックバードが導いてくれる。","오더의 방어막을 생성하는 수정체가 그들의 발전소 안에 있습니다. 그것을 파괴할 수만 있다면, 오더의 방어 체계를 약화할 수 있을 겁니다. 블랙버드가 길을 알려줄 첩자의 위치를 알려줄 것입니다. 건투를 빌어요. - \cy워너는 우리가 모집한 첩자야. 그는 발전소 창고에 있어.","Een enkel kristal loopt over het elektriciteitsnet dat de schilden van de Orde aandrijft. Vernietig dat kristal en je zult grote gaten slaan in de verdediging van de Orde. Blackbird leidt je naar een spion die een weg naar binnen heeft, veel geluk.","En enkelt krystall driver kraftnettet som driver Ordenens skjold. Ødelegg den krystallen, og du vil slå store hull i Ordenens forsvar. Blackbird vil føre dere til en spion som har en vei inn. Lykke til.","Pojedynczy kryształ napędza sieć energetyczną, która zasila osłony Zakonu. Zniszcz kryształ, a Zakon będzie miał ogromne luki w ochronie. Blackbird zaprowadzi cię do szpiega, który ma sposób, aby się tam dostać, powodzenia.",Há um cristal que fornece energia à rede elétrica que mantém os escudos da Ordem em funcionamento. Destrua esse cristal e você abrirá brechas grandes nas defesas da Ordem. Blackbird guiará você a um espião que sabe como entrar lá. Boa sorte.,,"Un cristal unic alimentează grila de putere care acționează scuturile Ordiului. Distruge cristalul și veți provoca daune imense sistemului de apărare al Ordinului. Blackbird vă va introduce unui spion care să vă ofere o cale în interior, multă baftă.","Энергосеть, которая питает щиты Ордена, работает от одного кристалла. Уничтожь этот кристалл, и ты пробьёшь огромную брешь в их обороне. «Чёрный дрозд» приведёт тебя к шпиону, который знает, как проникнуть на станцию. Удачи!",,"Tarikat'ın kalkanlarını çalıştıran güç şebekesini tek bir kristal çalıştırıyor. O kristali yok edersen Tarikat'ın savunmasında büyük delikler açacaksın. Karatavuk seni içeri girmenin bir yolunu bulan bir casusa götürecek, iyi şanslar." -We'll get it.,TXT_RPLY0_SCRIPT03_D12128_WELLG,〃 (〃),,,Zničíme jej.,Vi skal nok få fat i den.,Das werden wir hinkriegen.,,Ni sukcesos.,Lo conseguiremos.,Lo vamos a lograr.,Saamme sen.,Je m'en occupe.,Megszerezzük.,Ce la faremo.,すぐ始めよう。,그 수정체를 파괴하겠습니다.,We krijgen het wel.,Vi får tak i den.,Poradzimy sobie.,Vamos conseguir.,,Vom ajunge în interior.,Мы справимся.,,Onu yakalayacağız. -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D13644_FIGHT,〃 (〃),,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Batalu pro la Fronto kaj liberigota lando. Ekagu.,Lucha por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Kjemp for Fronten og friheten. Av sted.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptați pentru Front și libertate. Acum plecați.,Сражайся за свободу и справедливость. Выдвигайся.,,Cephe ve özgürlük için savaşın. Çıkın. -"You've exceeded all of our expectations. Because of your daring our troops are on the move. I want you two to join the assault, with a specific target. Take out the Programmer. It's time to reveal what we've found out about this layer of the Order.",TXT_DLG_SCRIPT03_D15160_YOUVE,〃 (Progammer mission),,,"Překonal jsi všechny naše představy. Díky tvé odvaze se naše vojska vydala na pochod. Chci, abyste se vy dva připojili k útoku se zvláštním cílem: zabít Programátora. Je čas odhalit, co jsme se dozvěděli o Řádu.","Du har overgået alle vores forventninger. På grund af jeres mod er vores tropper på vej. Jeg vil have jer to til at deltage i angrebet, med et specifikt mål. Udrydd programmereren. Det er tid til at afsløre, hvad vi har fundet ud af om dette lag af Ordenen.","Du hast alle unsere Erwartungen übertroffen. Dank dir sind unsere Truppen auf dem Vormarsch. Ich möchte, dass du auch an dem Angriff teilnimmst, aber mit einer Spezialmission. Eliminiere den Programmierer. Es ist Zeit zu enthüllen, was wir über dien Teil des Ordens herausgefunden haben.",,"Vi superis ĉiujn el niaj atendoj. Pro viaj heroaĵoj, niaj trupoj jam ekagis. Mi volas, ke vi ambaŭ aliĝu al la sturmo kun specifa celo: mortigi La Programiston. Estas tempo malkaŝi tion, kion ni malkovris pri tiu aspekto de La Ordono.",Has superado todas nuestras expectativas. Por tu hazaña nuestras tropas ya están en movimiento. Quiero que los dos os unáis al asalto con un objetivo específico: acabar con el Programador. Ya es hora de revelar lo que hemos descubierto sobre ese lado de La Orden.,Superaste todas nuestras expectativas. Por tu hazaña nuestras tropas ya están en movimiento. Quiero que los dos se unan al asalto con un objetivo específico: matar al Programador. Ya es hora de revelar lo que descubrimos sobre ese lado de La Orden.,"Olet ylittänyt kaikki odotuksemme. Rohkeutesi ansiosta joukkomme ovat liikkeellä. Haluan teidän molempien osallistuvan hyökkäykseen erityistehtävällä: Tuhotkaa Ohjelmoitsija. On aika paljastaa, mitä olemme saaneet selville Veljeskunnan tästä kerroksesta.","Vous avez dépassé toutes nos attentes. Grâce à votre audace, nos troupes sont sur le pied de guerre. Je que vous rejoignez l'assaut tous les deux, avec une cible précise. Eliminez le Programmeur. Il est l'heure de révéler ce que nous avons découvert sur cette facette de l'Ordre.",Túltettetek az elvárásaimon. Merész tetteitek inspirálóan hatottak katonáinkra. Mindkettőtöket szánok egy speciális feladatot a roham során. Iktassátok ki a Programozót. Ideje világosságra hozni amit találtunk a Rend ezen ágáról.,"Hai superato tutte le nostre aspettative. Grazie al vostro coraggio, le nostre truppe sono in movimento. Voglio che voi due vi uniate all'assalto, con un obiettivo specifico. Elimina il Programmatore. È giunto il momento di rivelare quello che abbiamo scoperto di questo strato dell'Ordine.","君達は我々の期待を超える活躍を行ってくれた。 + \cy워너는 우리가 모집한 첩자야. 그는 발전소 창고에 있어.","Een enkel kristal loopt over het elektriciteitsnet dat de schilden van de Orde aandrijft. Vernietig dat kristal en je zult grote gaten slaan in de verdediging van de Orde. Blackbird leidt je naar een spion die een weg naar binnen heeft, veel geluk.","En enkelt krystall driver kraftnettet som driver Ordenens skjold. Ødelegg den krystallen, og du vil slå store hull i Ordenens forsvar. Blackbird vil føre dere til en spion som har en vei inn. Lykke til.","Pojedynczy kryształ napędza sieć energetyczną, która zasila osłony Zakonu. Zniszcz kryształ, a Zakon będzie miał ogromne luki w ochronie. Blackbird zaprowadzi cię do szpiega, który ma sposób, aby się tam dostać, powodzenia.",Há um cristal que fornece energia à rede elétrica que mantém os escudos da Ordem em funcionamento. Destrua esse cristal e você abrirá brechas grandes nas defesas da Ordem. Blackbird guiará você a um espião que sabe como entrar lá. Boa sorte.,,"Un cristal unic alimentează grila de putere care acționează scuturile Ordiului. Distruge cristalul și veți provoca daune imense sistemului de apărare al Ordinului. Blackbird vă va introduce unui spion care să vă ofere o cale în interior, multă baftă.","Энергосеть, которая питает щиты Ордена, работает от одного кристалла. Уничтожь этот кристалл, и ты пробьёшь огромную брешь в их обороне. «Чёрный дрозд» приведёт тебя к шпиону, который знает, как проникнуть на станцию. Удачи!",,"En enda kristall driver kraftnätet som driver ordens sköldar. Förstör den kristallen och du kommer att slå enorma hål i ordens försvar. Blackbird kommer att leda dig till en spion som har en väg in, lycka till.","Tarikat'ın kalkanlarını çalıştıran güç şebekesini tek bir kristal çalıştırıyor. O kristali yok edersen Tarikat'ın savunmasında büyük delikler açacaksın. Karatavuk seni içeri girmenin bir yolunu bulan bir casusa götürecek, iyi şanslar." +We'll get it.,TXT_RPLY0_SCRIPT03_D12128_WELLG,〃 (〃),,,Zničíme jej.,Vi skal nok få fat i den.,Das werden wir hinkriegen.,,Ni sukcesos.,Lo conseguiremos.,Lo vamos a lograr.,Saamme sen.,Je m'en occupe.,Megszerezzük.,Ce la faremo.,すぐ始めよう。,그 수정체를 파괴하겠습니다.,We krijgen het wel.,Vi får tak i den.,Poradzimy sobie.,Vamos conseguir.,,Vom ajunge în interior.,Мы справимся.,,Vi kommer att hitta den.,Onu yakalayacağız. +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D13644_FIGHT,〃 (〃),,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Bataladu pro la Fronto kaj libereco. Ekagu.,Pelea por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Kjemp for Fronten og friheten. Av sted.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptați pentru Front și libertate. Acum plecați.,Сражайся за свободу и справедливость. Выдвигайся.,,Kämpa för fronten och friheten. Gå ut.,Cephe ve özgürlük için savaşın. Çıkın. +"You've exceeded all of our expectations. Because of your daring our troops are on the move. I want you two to join the assault, with a specific target. Take out the Programmer. It's time to reveal what we've found out about this layer of the Order.",TXT_DLG_SCRIPT03_D15160_YOUVE,〃 (Progammer mission),,,"Překonal jsi všechny naše představy. Díky tvé odvaze se naše vojska vydala na pochod. Chci, abyste se vy dva připojili k útoku se zvláštním cílem: zabít Programátora. Je čas odhalit, co jsme se dozvěděli o Řádu.","Du har overgået alle vores forventninger. På grund af jeres mod er vores tropper på vej. Jeg vil have jer to til at deltage i angrebet, med et specifikt mål. Udrydd programmereren. Det er tid til at afsløre, hvad vi har fundet ud af om dette lag af Ordenen.","Du hast alle unsere Erwartungen übertroffen. Dank dir sind unsere Truppen auf dem Vormarsch. Ich möchte, dass du auch an dem Angriff teilnimmst, aber mit einer Spezialmission. Eliminiere den Programmierer. Es ist Zeit zu enthüllen, was wir über dien Teil des Ordens herausgefunden haben.",,"Vi superis ĉiujn niajn atendojn. Pro viaj heroaĵoj, niaj trupoj jam ekagis. Mi volas, ke vi ambaŭ aliĝu al la sturmo kun specifa celo: mortigi La Programiston. Estas tempo malkaŝi tion, kion ni malkovris pri tiu aspekto de La Ordeno.",Has superado todas nuestras expectativas. Por tu hazaña nuestras tropas ya están en movimiento. Quiero que los dos os unáis al asalto con un objetivo específico: acabar con el Programador. Ya es hora de revelar lo que hemos descubierto sobre ese lado de La Orden.,Superaste todas nuestras expectativas. Por tu hazaña nuestras tropas ya están en movimiento. Quiero que los dos se unan al asalto con un objetivo específico: matar al Programador. Ya es hora de revelar lo que descubrimos sobre ese lado de La Orden.,"Olet ylittänyt kaikki odotuksemme. Rohkeutesi ansiosta joukkomme ovat liikkeellä. Haluan teidän molempien osallistuvan hyökkäykseen erityistehtävällä: Tuhotkaa Ohjelmoitsija. On aika paljastaa, mitä olemme saaneet selville Veljeskunnan tästä kerroksesta.","Vous avez dépassé toutes nos attentes. Grâce à votre audace, nos troupes sont sur le pied de guerre. Je que vous rejoignez l'assaut tous les deux, avec une cible précise. Eliminez le Programmeur. Il est l'heure de révéler ce que nous avons découvert sur cette facette de l'Ordre.",Túltettetek az elvárásaimon. Merész tetteitek inspirálóan hatottak katonáinkra. Mindkettőtöket szánok egy speciális feladatot a roham során. Iktassátok ki a Programozót. Ideje világosságra hozni amit találtunk a Rend ezen ágáról.,"Hai superato tutte le nostre aspettative. Grazie al vostro coraggio, le nostre truppe sono in movimento. Voglio che voi due vi uniate all'assalto, con un obiettivo specifico. Elimina il Programmatore. È giunto il momento di rivelare quello che abbiamo scoperto di questo strato dell'Ordine.","君達は我々の期待を超える活躍を行ってくれた。 君の勇猛さに私の部隊が動き出した。 今度は君達二人にある目的の為、強襲部隊に 加わって欲しい。プログラマーを討ち取るのだ。 オーダーに纏わる様々な事情について -明らかにする時が来た。",당신의 성과는 우리가 예상했던 것보다 훨씬 굉장하더군요. 당신의 노고 덕에 이제 우리가 활동을 본격적으로 개시할 수 있게 되었습니다. 자네와 블랙버드가 이번 공격에 참여했으면 합니다. 그리고 프로그래머를 없애버리세요. 지금이야말로 오더의 실체가 어떠한지를 폭로할 절호의 기회입니다.,"Je hebt al onze verwachtingen overtroffen. Door jouw durf zijn onze troepen in beweging. Ik wil dat jullie twee zich bij de aanval aansluiten, met een specifiek doelwit. Schakel de programmeur uit. Het is tijd om te onthullen wat we hebben ontdekt over deze laag van de Orde.","Du har overgått alle våre forventninger. På grunn av deres dristighet er troppene våre i bevegelse. Jeg vil at dere to skal bli med på angrepet, med et spesifikt mål. Drep programmereren. Det er på tide å avsløre hva vi har funnet ut om dette laget av Ordenen.","Przekroczyłeś nasze wszelkie oczekiwania. Dzięki twej odwadze nasi żołnierze są w drodze. Chciałbym, abyście razem dołączyli do szturmu, mając konkretny cel. Zabijcie Programistę. Czas pokazać co odkryliśmy na temat tego pionka Zakonu.","Você superou todas as nossas expectativas. Graças à sua audácia as nossas tropas estão em movimento. Quero que vocês dois participem do ataque, com um alvo específico. Elimine o Programador. Já está na hora de revelar o que descobrimos a respeito dessa parte da Ordem. ",,"Ne-ați depășit toate așteptările. Datorită îndrăznelii voastre trupele noastre s-au putut pune în mișcare. Vreau să vă alăturați asaltului, cu o țintă specifică. Eliminați-l pe Programator. E timpul să dezvăluim ce am descoperit despre acest nivel al Ordinului.","Ты превзошёл все наши ожидания. Благодаря твоей отваге наши войска уже в пути. Я хочу, чтобы вы двое присоединились к атаке, с особой целью — уничтожить Программиста. Настало время рассказать всё, что мы смогли узнать об этом уровне власти в Ордене.",,"Tüm beklentilerimizi aştınız. Cesaretiniz sayesinde birliklerimiz harekete geçti. İkinizin saldırıya katılmanızı istiyorum, belirli bir hedefle. Programcıyı ortadan kaldırın. Tarikat'ın bu katmanı hakkında ne bulduğumuzu açıklamanın zamanı geldi." -Tell me what we know.,TXT_RPLY0_SCRIPT03_D15160_TELLM,〃 (〃),,,"Řekni mi, co víme.","Fortæl mig, hvad vi ved.",Sag mir was du weißt.,,"Diru tion, kion ni scias.",Dime lo que sabemos.,,"Kerro, mitä tiedämme.",Donnez-moi ce que vous savez.,Mondd el mit tudtunk meg.,Dimmi cosa sappiamo.,こちらに知っている事を教えてくれ。,그 비밀에 대해서 알려주세요.,Vertel me wat we weten.,Fortell meg hva vi vet.,Powiedz co wiadomo.,Conte-me o que sabemos.,,Spune-mi ce știi.,Расскажи мне всё.,,Bana ne bildiğimizi söyle. -"The Programmer's lair is in the castle. Now, see the medic, grab some ammo and go get him.",TXT_DLG_SCRIPT03_D16676_THEPR,〃 (〃),,,"Programátorovo doupě je v hradu. Jdi navštívit zdravotníka, vem si munici a jdi ho dostat.","Programmørens hule er i slottet. Gå hen til lægen, tag noget ammunition og hent ham.",Der Programmierer hät sich irgendwo in der Burg auf. Und nun gehe bitter zum Sanitäter und beschaff dir neue Munition - und dann mach ihn fertig.,,"La kaŝejo de la Programisto estas en la kastelo. Vi nun renkontu la kuraciston, prenu municiojn kaj iru mortigi lin.","La guarida del Programador está en el castillo. Ahora ve a ver al médico, coge munición y ve a por él.","La guarida del Programador está en el castillo. Ahora ve a ver al médico, toma munición y ve por él.","Ohjelmoitsijan piilopaikka on linnassa. Käy nyt tapaamassa lääkintämiestä, ota panoksia matkaan ja napatkaa hänet.","Le repaire du Programmeur est dans le château. Allez voir le médecin, rechargez vos armes, et allez vous occuper de lui.","A Programozó búvóhelye a kastélyban található. Látogasd meg a szanitécot, vegyél magadhoz egy kis ammot, és irány a kastély.","La tana del Programmatore è nel castello. Ora, fai una visita al medico, prendi un pò di munizione, e vallo a predendere.","プログラマーの居場所は城内だ。それと、 +明らかにする時が来た。",당신의 성과는 우리가 예상했던 것보다 훨씬 굉장하더군요. 당신의 노고 덕에 이제 우리가 활동을 본격적으로 개시할 수 있게 되었습니다. 자네와 블랙버드가 이번 공격에 참여했으면 합니다. 그리고 프로그래머를 없애버리세요. 지금이야말로 오더의 실체가 어떠한지를 폭로할 절호의 기회입니다.,"Je hebt al onze verwachtingen overtroffen. Door jouw durf zijn onze troepen in beweging. Ik wil dat jullie twee zich bij de aanval aansluiten, met een specifiek doelwit. Schakel de programmeur uit. Het is tijd om te onthullen wat we hebben ontdekt over deze laag van de Orde.","Du har overgått alle våre forventninger. På grunn av deres dristighet er troppene våre i bevegelse. Jeg vil at dere to skal bli med på angrepet, med et spesifikt mål. Drep programmereren. Det er på tide å avsløre hva vi har funnet ut om dette laget av Ordenen.","Przekroczyłeś nasze wszelkie oczekiwania. Dzięki twej odwadze nasi żołnierze są w drodze. Chciałbym, abyście razem dołączyli do szturmu, mając konkretny cel. Zabijcie Programistę. Czas pokazać co odkryliśmy na temat tego pionka Zakonu.","Você superou todas as nossas expectativas. Graças à sua audácia as nossas tropas estão em movimento. Quero que vocês dois participem do ataque, com um alvo específico. Elimine o Programador. Já está na hora de revelar o que descobrimos a respeito dessa parte da Ordem. ",,"Ne-ați depășit toate așteptările. Datorită îndrăznelii voastre trupele noastre s-au putut pune în mișcare. Vreau să vă alăturați asaltului, cu o țintă specifică. Eliminați-l pe Programator. E timpul să dezvăluim ce am descoperit despre acest nivel al Ordinului.","Ты превзошёл все наши ожидания. Благодаря твоей отваге наши войска уже в пути. Я хочу, чтобы вы двое присоединились к атаке, с особой целью — уничтожить Программиста. Настало время рассказать всё, что мы смогли узнать об этом уровне власти в Ордене.",,"Du har överträffat alla våra förväntningar. På grund av er djärvhet är våra trupper på väg. Jag vill att ni två ansluter er till anfallet, med ett specifikt mål. Ta ut programmeraren. Det är dags att avslöja vad vi har kommit fram till om det här skiktet av Orden.","Tüm beklentilerimizi aştınız. Cesaretiniz sayesinde birliklerimiz harekete geçti. İkinizin saldırıya katılmanızı istiyorum, belirli bir hedefle. Programcıyı ortadan kaldırın. Tarikat'ın bu katmanı hakkında ne bulduğumuzu açıklamanın zamanı geldi." +Tell me what we know.,TXT_RPLY0_SCRIPT03_D15160_TELLM,〃 (〃),,,"Řekni mi, co víme.","Fortæl mig, hvad vi ved.",Sag mir was du weißt.,,"Diru tion, kion vi scias.",Dime lo que se sabe.,,"Kerro, mitä tiedämme.",Donnez-moi ce que vous savez.,Mondd el mit tudtunk meg.,Dimmi cosa sappiamo.,こちらに知っている事を教えてくれ。,그 비밀에 대해서 알려주세요.,Vertel me wat we weten.,Fortell meg hva vi vet.,Powiedz co wiadomo.,Conte-me o que sabemos.,,Spune-mi ce știi.,Расскажи мне всё.,,Berätta vad vi vet.,Bana ne bildiğimizi söyle. +"The Programmer's lair is in the castle. Now, see the medic, grab some ammo and go get him.",TXT_DLG_SCRIPT03_D16676_THEPR,〃 (〃),,,"Programátorovo doupě je v hradu. Jdi navštívit zdravotníka, vem si munici a jdi ho dostat.","Programmørens hule er i slottet. Gå hen til lægen, tag noget ammunition og hent ham.",Der Programmierer hät sich irgendwo in der Burg auf. Und nun gehe bitter zum Sanitäter und beschaff dir neue Munition - und dann mach ihn fertig.,,"La kaŝejo de la Programisto estas en la kastelo. Vi nun renkontu la kuraciston, prenu municiojn kaj iru mortigi lin.","La guarida del Programador está en el castillo. Ahora ve a ver al médico, coge munición y ve a por él.","La guarida del Programador está en el castillo. Ahora ve a ver al médico, toma munición y ve por él.","Ohjelmoitsijan piilopaikka on linnassa. Käy nyt tapaamassa lääkintämiestä, ota panoksia matkaan ja napatkaa hänet.","Le repaire du Programmeur est dans le château. Allez voir le médecin, rechargez vos armes, et allez vous occuper de lui.","A Programozó búvóhelye a kastélyban található. Látogasd meg a szanitécot, vegyél magadhoz egy kis ammot, és irány a kastély.","La tana del Programmatore è nel castello. Ora, fai una visita al medico, prendi un po' di munizione, e vallo a predendere.","プログラマーの居場所は城内だ。それと、 メディックと訓練士に会い弾薬を補給したら 奴を倒せ。","프로그래머가 거주하는 곳은 성채 안에 있습니다. 의무관과 무기 담당관을 찾아뵈서 준비를 당당히 하시길 바랍니다. - \cy일생일대의 격전에 대비해. 돈 아끼지 말고 있는 대로 다 써.","Het hol van de programmeur is in het kasteel. Ga nu naar de dokter, pak wat munitie en ga hem halen.","Programmererens skjulested er i slottet. Gå til legen, hent ammunisjon og hent ham.","Kryjówka Programisty jest w zamku. Teraz idź do medyka, weź trochę amunicji i załatw go.","O covil do Programador fica no castelo. Agora vá ver o médico, pegue munição e vá atrás dele.",,"Bârlogul Programatorului e în castel. Acum, dute la medic, ia niște muniție, și prindeți-l.","Программист устроил себе логово в замке. Теперь наведайся к врачу, пополни боезапас, и расправься с ним.",,"Programcı'nın sığınağı kalenin içinde. Şimdi, doktoru gör, biraz cephane al ve gidip onu getir." -Let me at 'em!,TXT_RPLY0_SCRIPT03_D16676_LETME,〃 (〃),,,Pusť mě na ně!,Lad mig tage dem!,Lass mich das nur machen.,,Mi faros tion!,¡Voy a por ellos!,¡Voy por ellos!,Päästä minut niiden kimppuun!,Je vais me le faire!,Elkapom mindet!,Lasciali a me!,任せろ!,한 번 저질러 봅시다!,Laat me er naartoe gaan!,La meg ta dem!,Niech ja go dorwę!,Pode deixar!,,Le voi arăta eu lor!,Я им покажу!,,Bana bırakın! -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D18192_FIGHT,〃 (〃),,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Batalu pro la Fronto kaj liberigota lando. Ekagu.,Lucha por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Kjemp for Fronten og friheten. Kom igjen.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Выдвигайся.,,Cephe ve özgürlük için savaşın. Dışarı çıkın. + \cy일생일대의 격전에 대비해. 돈 아끼지 말고 있는 대로 다 써.","Het hol van de programmeur is in het kasteel. Ga nu naar de dokter, pak wat munitie en ga hem halen.","Programmererens skjulested er i slottet. Gå til legen, hent ammunisjon og hent ham.","Kryjówka Programisty jest w zamku. Teraz idź do medyka, weź trochę amunicji i załatw go.","O covil do Programador fica no castelo. Agora vá ver o médico, pegue munição e vá atrás dele.",,"Bârlogul Programatorului e în castel. Acum, dute la medic, ia niște muniție, și prindeți-l.","Программист устроил себе логово в замке. Теперь наведайся к врачу, пополни боезапас, и расправься с ним.",,"Programmerarens gömställe finns i slottet. Gå till läkaren, ta lite ammunition och hämta honom.","Programcı'nın sığınağı kalenin içinde. Şimdi, doktoru gör, biraz cephane al ve gidip onu getir." +Let me at 'em!,TXT_RPLY0_SCRIPT03_D16676_LETME,〃 (〃),,,Pusť mě na ně!,Lad mig tage dem!,Lass mich das nur machen.,,Mi faros tion!,¡Voy a por ellos!,¡Voy por ellos!,Päästä minut niiden kimppuun!,Je vais me le faire!,Elkapom mindet!,Lasciali a me!,任せろ!,한 번 저질러 봅시다!,Laat me er naartoe gaan!,La meg ta dem!,Niech ja go dorwę!,Pode deixar!,,Le voi arăta eu lor!,Я им покажу!,,Låt mig ta dem!,Bana bırakın! +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D18192_FIGHT,〃 (〃),,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Bataladu pro la Fronto kaj libereco. Ekagu.,Pelea por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Kjemp for Fronten og friheten. Kom igjen.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Выдвигайся.,,Kämpa för fronten och friheten. Gå ut.,Cephe ve özgürlük için savaşın. Dışarı çıkın. Remember what the town hall looked like? That's a gentle reminder of what they're willing to do to get at us. Be careful.,TXT_DLG_SCRIPT03_D19708_REMEM,MAP03: Barracks.,,,"Pamatuješ si, jak dřív vypadala radnice? To je jemná přípomínka toho, co jsou schopni nám udělat. Buď opatrný.","Kan du huske, hvordan rådhuset så ud? Det er en blid påmindelse om, hvad de er villige til at gøre for at få fat i os. Vær forsigtig.","Denk daran, wie unser Rathaus aussieht. Das ist nur ein Dankzettel dafür, wie weit sie gehen würden um uns zu finden. Sei vorsichtig.",,"Ĉu vi memoras, kiel la urbodomo aspektis antaŭe? Ĝi nun estas afabla ekzemplo de tio, kion ili estas pretaj fari por forigi nin. Estu atenta.",¿Recuerdas como era antes el ayuntamiento? Ahora es una muestra amable de lo que son capaces de hacer contra nosotros. Ten cuidado.,,"Muistatko, miltä kaupungintalo näytti? Se on hienovarainen muistutus siitä, mitä he ovat valmiita tekemään saadakseen meidät. Ole varuillasi.",Souvenez-vous de l'hôtel de ville avant tout cela? C'est une manière gentille de nous montrer ce qu'ils sont capables de faire pour se débarasser de nous. Faites attention.,"Emlékszel, hogy nézett ki a vársoháza? Jó példa arra, hogy mire képesek, hogy elintézzenek minket. Légy óvatos.",Ti ricordi com'era il municipio una volta? Adesso è un piccolo ricordo di cosa sono disposti a fare per attaccarci. Fai attenzione.,"市庁舎の外観を見たか?あれが我々に対する -奴等の所業を思い出させる。気をつけろ。",시청이 박살난 걸 보았지? 저건 오더의 심기를 무모하게 건드린 결과같은 거야. 그러니 조심해.,Weet je nog hoe het stadhuis eruit zag? Dat is een vriendelijke herinnering aan wat ze bereid zijn te doen om ons te pakken te krijgen. Wees voorzichtig.,Husker du hvordan rådhuset så ut? Det er en påminnelse om hva de er villige til å gjøre for å ta oss. Vær forsiktig.,"Pamiętasz jak ratusz wyglądał? To delikatne przypomnienie co chcą zrobić, aby nas dorwać. Uważaj na siebie.",Lembra como era a prefeitura? Aquilo é um simples lembrete do que eles estão dispostos a fazer para nos pegar. Tome cuidado.,,Mai ții minte cum arăta primăria? Asta e o reamintire ușoară de ceea ce sunt dispuși să facă pentru a ajunge la noi. Ai grijă.,"Видел, что стало с городской ратушей? Это мягкий намёк на то, что они сделают, если доберутся до нас. Будь осторожен.",,Belediye binasının neye benzediğini hatırlıyor musun? Bu bize ulaşmak için neler yapabileceklerini hatırlatıyor. Dikkatli olun. -Talk to Macil. He'll be able to help you.,TXT_DLG_SCRIPT03_D21224_TALKT,"MAP03: Upstairs, corridor.",,,Promluv si s Macilem. On ti pomůže.,Tal med Macil. Han vil kunne hjælpe dig.,Rede mit Macil. Er kann dir helfen.,,Parolu kun Macil. Li povos helpi vin.,Habla con Macil. Él te podrá ayudar.,Habla con Macil. Él te va a poder ayudar.,Puhu Macilille. Hän pystyy auttamaan sinua.,Parlez à Macil. Il pourra vous aider.,Beszélj Macil-lal. Ő tud segíteni neked.,Parla con Macil. Sarà in grado di aiutarti.,マシルと話すんだ。彼から援助が得られるはず。,도움이 필요한가? 그럼 마실 사령관님을 찾아.,Praat met Macil. Hij zal je kunnen helpen.,Snakk med Macil. Han kan hjelpe deg.,Porozmawiaj z Macilem. Pomoże ci.,Fale com Macil. Ele vai poder te ajudar.,,Discută cu Macil. Te va ajuta el.,Поговори с Мэйсилом. Он сможет тебе помочь.,,Macil ile konuş. Sana yardım edebilir. +奴等の所業を思い出させる。気をつけろ。",시청이 박살난 걸 보았지? 저건 오더의 심기를 무모하게 건드린 결과같은 거야. 그러니 조심해.,Weet je nog hoe het stadhuis eruit zag? Dat is een vriendelijke herinnering aan wat ze bereid zijn te doen om ons te pakken te krijgen. Wees voorzichtig.,Husker du hvordan rådhuset så ut? Det er en påminnelse om hva de er villige til å gjøre for å ta oss. Vær forsiktig.,"Pamiętasz jak ratusz wyglądał? To delikatne przypomnienie co chcą zrobić, aby nas dorwać. Uważaj na siebie.",Lembra como era a prefeitura? Aquilo é um simples lembrete do que eles estão dispostos a fazer para nos pegar. Tome cuidado.,,Mai ții minte cum arăta primăria? Asta e o reamintire ușoară de ceea ce sunt dispuși să facă pentru a ajunge la noi. Ai grijă.,"Видел, что стало с городской ратушей? Это мягкий намёк на то, что они сделают, если доберутся до нас. Будь осторожен.",,Minns du hur stadshuset såg ut? Det är en mild påminnelse om vad de är villiga att göra för att komma åt oss. Var försiktig.,Belediye binasının neye benzediğini hatırlıyor musun? Bu bize ulaşmak için neler yapabileceklerini hatırlatıyor. Dikkatli olun. +Talk to Macil. He'll be able to help you.,TXT_DLG_SCRIPT03_D21224_TALKT,"MAP03: Upstairs, corridor.",,,Promluv si s Macilem. On ti pomůže.,Tal med Macil. Han vil kunne hjælpe dig.,Rede mit Macil. Er kann dir helfen.,,Parolu kun Macil. Li povos helpi vin.,Habla con Macil. Él te podrá ayudar.,Habla con Macil. Él te va a poder ayudar.,Puhu Macilille. Hän pystyy auttamaan sinua.,Parlez à Macil. Il pourra vous aider.,Beszélj Macil-lal. Ő tud segíteni neked.,Parla con Macil. Sarà in grado di aiutarti.,マシルと話すんだ。彼から援助が得られるはず。,도움이 필요한가? 그럼 마실 사령관님을 찾아.,Praat met Macil. Hij zal je kunnen helpen.,Snakk med Macil. Han kan hjelpe deg.,Porozmawiaj z Macilem. Pomoże ci.,Fale com Macil. Ele vai poder te ajudar.,,Discută cu Macil. Te va ajuta el.,Поговори с Мэйсилом. Он сможет тебе помочь.,,Prata med Macil. Han kan hjälpa dig.,Macil ile konuş. Sana yardım edebilir. I've heard that Macil's got a plan to subvert the Order. It had better be good. One more failure and we're all just dead meat.,TXT_DLG_SCRIPT03_D22740_IVEHE,"MAP03: Barracks. -(dead meat = corpse)",,,"Slyšel jsem, že Macil má plán, jak porazit Řád. Doufejme, že dobrý. Ještě jeden nezdar a všichni jsme mrtví.","Jeg har hørt, at Macil har en plan om at undergrave Ordenen. Den har bare at være god. En fiasko mere, og vi er alle bare dødt kød.","Ich habe gehört, Macil hätte einen Plan um den Orden zu unterwandern. Ich hoffe mal, er taugt was. Noch ein Fehlschlag und wir können uns gleich begraben lassen.",,"Mi aŭdis, ke Macil havas planon por malstabiligi La Ordonon. Pli bone, ke ĝi estas bona. Unu plua eraro kaj ni estos kadavroj.",He oído que Macil tiene un plan para desestabilizar a La Orden. Más vale que sea bueno. Un fallo más y somos fiambres.,Oí que Macil tiene un plan para desestabilizar a La Orden. Más vale que sea bueno. Un fallo más y somos fiambres.,"Kuulin, että Macililla on suunnitelma kukistaa Veljeskunta. Parasta ollakin hyvä. Vielä yksikin epäonnistuminen, ja olemme kaikki mennyttä.",J'ai entendu que Macil a un plan pour repousser l'Ordre. Il a intérêt à être bon. Une erreur de plus et nous sommes tous morts.,"Úgy tudom Macilnak van valami terve a Rend felforgatására. Remélem valami ütős terv. Még egy kudarc, és nekünk lőttek.",Ho sentito che Macil ha un piano per sovvertire l'Ordine. E spero proprio che sia un buon piano. Un altro fallimento e saremo tutti carne morta.,"私はマシルがオーダーを転覆させる計画を +(dead meat = corpse)",,,"Slyšel jsem, že Macil má plán, jak porazit Řád. Doufejme, že dobrý. Ještě jeden nezdar a všichni jsme mrtví.","Jeg har hørt, at Macil har en plan om at undergrave Ordenen. Den har bare at være god. En fiasko mere, og vi er alle bare dødt kød.","Ich habe gehört, Macil hätte einen Plan um den Orden zu unterwandern. Ich hoffe mal, er taugt was. Noch ein Fehlschlag und wir können uns gleich begraben lassen.",,"Mi aŭdis, ke Macil havas planon por malstabiligi La Ordenon. Pli bone, ke ĝi estas bona. Unu plua eraro kaj ni estos kadavroj.",He oído que Macil tiene un plan para desestabilizar a La Orden. Más vale que sea bueno. Un fallo más y somos fiambres.,Oí que Macil tiene un plan para desestabilizar a La Orden. Más vale que sea bueno. Un fallo más y somos fiambres.,"Kuulin, että Macililla on suunnitelma kukistaa Veljeskunta. Parasta ollakin hyvä. Vielä yksikin epäonnistuminen, ja olemme kaikki mennyttä.",J'ai entendu que Macil a un plan pour repousser l'Ordre. Il a intérêt à être bon. Une erreur de plus et nous sommes tous morts.,"Úgy tudom Macilnak van valami terve a Rend felforgatására. Remélem valami ütős terv. Még egy kudarc, és nekünk lőttek.",Ho sentito che Macil ha un piano per sovvertire l'Ordine. E spero proprio che sia un buon piano. Un altro fallimento e saremo tutti carne morta.,"私はマシルがオーダーを転覆させる計画を 持っていると聞いた。そうだと良かったが。 -我々は一度大敗し全滅しかけた。",오더를 괴멸할 방법을 마실 사령관님이 찾아냈대. 잘 먹혀야 하는데 말이야... 안 그럼 우리들이 잡아먹힐 거라고.,Ik heb gehoord dat Macil een plan heeft om de Orde te ondermijnen. Het kan maar beter goed zijn. Nog een mislukking en we zijn allemaal gewoon dood vlees.,"Jeg har hørt at Macil har en plan for å undergrave Ordenen. Den bør være god. Én fiasko til, og vi er ferdige.","Słyszałem, że Macil ma plan obalenia Zakonu. Oby był dobry. Jeszcze jedna porażka, a będziemy martwi.",Fiquei sabendo que Macil tem um plano para desestabilizar a Ordem. Espero que seja bom. Mais um fracasso e estaremos todos mortos.,,Am auzit că Macil are un plan pentru a submina Ordinul. Ar face bine să fie grozav. Încă un eșec și vom fi toți carne ambalată.,"Я слышал, что Мэйсил разработал план свержения Ордена. Лучше бы он сработал. Ещё одна ошибка, и мы все покойники.",,Macil'in Tarikat'ı yıkmak için bir planı olduğunu duydum. İyi olsa iyi olur. Bir başarısızlık daha olursa hepimiz ölürüz. -A few of these barrels dumped into their water supply should even the odds a little.,TXT_DLG_SCRIPT03_D24256_AFEWO,〃,,,Pár těhle sudů v jejich zásobách vody by nám mělo alespoň trochu pomoct.,Et par af disse tønder dumpet i deres vandforsyning burde udligne oddsene lidt.,"Wenn wir ein paar von diesen Fässern in die Wasserversorgung kippen, sollte das unsere Chancen etwas verbessern.",,Ĵeti kelkajn el ĉi tiuj bareloj en ilian akvo-provizadon devus egaligi iomete la eblojn.,Tirar unos cuantos de estos barriles a su suministro de agua debería igualar un poco las probabilidades.,,Muutaman tällaisen tynnyrin kaataminen heidän vedenjakeluunsa varmaankin hieman tasoittaisi tilannetta.,Quelques uns de ces tonneaux vidés dans leur réserve d'eau devrait équilibrer le terrain de jeu.,Ezzel a pár víztározóba borított hordóval kiegyenlítjük az erőviszonyokat.,Un paio di questi barili rovesciati dentro la loro fornitura d'acqua dovrebbero bilanciare un pò le cose.,"ここの樽は捨てられていた物で -彼らの給水を補っている。",그들의 배수관에서 버려진 이 통들 일부는 분명히 약간의 승산이 있을거야.,"Een paar van deze vaten die in hun waterleiding gedumpt zijn, zullen de kans dat ze een beetje gelijk zijn.",Et par av disse tønnene dumpet i vannforsyningen deres burde jevne ut oddsen litt.,Parę tych beczek wrzuconcyh do ich zapasu wody powinno narobić wiele kłopotów.,"Se despejarmos alguns destes barris no estoque de água deles, vamos igualar as chances um pouco. ",,Câteva butoaie vărsate în rezerva lor de apă ar trebui să echilibreze balanța.,"Несколько таких бочек, сброшенных в их водоснабжение, немного уровняют шансы.",,Bu varillerden birkaçı su kaynaklarına atılırsa ihtimaller biraz olsun eşitlenir. +我々は一度大敗し全滅しかけた。",오더를 괴멸할 방법을 마실 사령관님이 찾아냈대. 잘 먹혀야 하는데 말이야... 안 그럼 우리들이 잡아먹힐 거라고.,Ik heb gehoord dat Macil een plan heeft om de Orde te ondermijnen. Het kan maar beter goed zijn. Nog een mislukking en we zijn allemaal gewoon dood vlees.,"Jeg har hørt at Macil har en plan for å undergrave Ordenen. Den bør være god. Én fiasko til, og vi er ferdige.","Słyszałem, że Macil ma plan obalenia Zakonu. Oby był dobry. Jeszcze jedna porażka, a będziemy martwi.",Fiquei sabendo que Macil tem um plano para desestabilizar a Ordem. Espero que seja bom. Mais um fracasso e estaremos todos mortos.,,Am auzit că Macil are un plan pentru a submina Ordinul. Ar face bine să fie grozav. Încă un eșec și vom fi toți carne ambalată.,"Я слышал, что Мэйсил разработал план свержения Ордена. Лучше бы он сработал. Ещё одна ошибка, и мы все покойники.",,Jag har hört att Macil har en plan för att omstörta Orden. Det är bäst att den är bra. Ett misslyckande till och vi är alla bara döda kött.,Macil'in Tarikat'ı yıkmak için bir planı olduğunu duydum. İyi olsa iyi olur. Bir başarısızlık daha olursa hepimiz ölürüz. +A few of these barrels dumped into their water supply should even the odds a little.,TXT_DLG_SCRIPT03_D24256_AFEWO,〃,,,Pár těhle sudů v jejich zásobách vody by nám mělo alespoň trochu pomoct.,Et par af disse tønder dumpet i deres vandforsyning burde udligne oddsene lidt.,"Wenn wir ein paar von diesen Fässern in die Wasserversorgung kippen, sollte das unsere Chancen etwas verbessern.",,Ĵeti kelkajn el ĉi tiuj bareloj en ilian akvo-provizadon devus egaligi iomete la eblojn.,Tirar unos cuantos de estos barriles a su suministro de agua debería igualar un poco las probabilidades.,,Muutaman tällaisen tynnyrin kaataminen heidän vedenjakeluunsa varmaankin hieman tasoittaisi tilannetta.,Quelques uns de ces tonneaux vidés dans leur réserve d'eau devrait équilibrer le terrain de jeu.,Ezzel a pár víztározóba borított hordóval kiegyenlítjük az erőviszonyokat.,Un paio di questi barili rovesciati dentro la loro fornitura d'acqua dovrebbero bilanciare un po' le cose.,"ここの樽は捨てられていた物で +彼らの給水を補っている。",그들의 배수관에서 버려진 이 통들 일부는 분명히 약간의 승산이 있을거야.,"Een paar van deze vaten die in hun waterleiding gedumpt zijn, zullen de kans dat ze een beetje gelijk zijn.",Et par av disse tønnene dumpet i vannforsyningen deres burde jevne ut oddsen litt.,Parę tych beczek wrzuconcyh do ich zapasu wody powinno narobić wiele kłopotów.,"Se despejarmos alguns destes barris no estoque de água deles, vamos igualar as chances um pouco. ",,Câteva butoaie vărsate în rezerva lor de apă ar trebui să echilibreze balanța.,"Несколько таких бочек, сброшенных в их водоснабжение, немного уровняют шансы.",,Några av de här tunnorna dumpade i deras vattenförsörjning borde jämna ut oddsen lite.,Bu varillerden birkaçı su kaynaklarına atılırsa ihtimaller biraz olsun eşitlenir. "So you're the new operative? Thanks, without you, we'd all be dead right now.",TXT_DLG_SCRIPT03_D25772_SOYOU,〃,,,"Takže ty jsi ten nový agent? Díky, bez tebe bychom všichni byli mrtví.","Så du er den nye agent? Tak, uden dig ville vi alle være døde lige nu.","So, du bist der neue Agent? Danke, ohne dich wären wir schon alle tot.",,"Do ĉu vi estas la nova ano? Dankon. Sen vi, ni ĉiuj jam estus mortintaj.",¿O sea que tú eres el nuevo miembro? Gracias. Sin ti ya estaríamos todos muertos.,,Sinä siis olet se uusi agentti? Kiitos; ilman sinua olisimme nyt kaikki kuolleita.,"Vous êtes le nouvel agent? Merci, sans vous, nous serions tous morts.","Szóval te vagy az új kolléga? Köszi, nélküled már mind alulról szagolnánk az ibolyát.","Quindi sei tu il nuovo agente? Grazie, se non fosse per te, saremo tutti morti ora.","貴方が新しい工作員かい? それはありがたい、 -貴方がいなければ皆死んでいた所だ。","그래서, 네가 그 요원이지? 고맙다. 네가 없었으면 우리들은 이미 죽고 없었을걸.","Dus jij bent de nieuwe agent? Bedankt, zonder jou waren we nu allemaal dood geweest.","Så du er den nye agenten? Takk, uten deg ville vi alle vært døde nå.","Więc jesteś tu nowy? Dzięki, bez ciebie bylibyśmy już martwi.","Então você é o novo agente? Obrigado. Sem você, estaríamos todos mortos neste momento.",,"Deci tu ești noul operator? Merci, dacă nu erai tu, am fi fost cu toții morți deja.","Так это ты наш новый оперативник? Спасибо. Если бы не ты, мы бы все уже были мертвы.",,"Demek yeni ajan sensin? Teşekkürler, sen olmasaydın şu anda hepimiz ölmüş olurduk." -I'm working on something that will give us an edge. It will increase your stamina and completely jack you up. I've almost got all the bugs worked out. Can I do something for you?,TXT_DLG_SCRIPT03_D27288_IMWOR,MAP03: Gerald (no implant),,,"Pracuju na něčem, co by nám mělo pomoci. Přidá ti to výdrž a naprosto tě to nakopne. Už jsem skoro vychytal všechny mouchy. Co pro tebe mohu udělat?","Jeg arbejder på noget, der vil give os en fordel. Det vil øge din udholdenhed og gøre dig helt oppe at køre. Jeg har næsten fået styr på alle fejlene. Må jeg gøre noget for dig?","Ich arbeite an etwas, das uns einen Vorteil verschaffen kann. Es würde deine Ausdauer erhöhen und dir Superkräfte verleihen. Kann ich was für dich tun?",,"Mi laboras super io, kio donos avantaĝon al ni: ĝi pliigos vian energion kaj korpan forton. Mi jam korektis la plimulton de la difektoj. Ĉu mi povas fari ion por vi?",Estoy trabajando en algo que nos dará una ventaja: aumentará tu aguante y fuerza física. Ya casi tengo todos los fallos corregidos. ¿Puedo hacer algo por ti?,Estoy trabajando en algo que nos va a dar una ventaja: va a aumentar tu aguante y fuerza física. Ya casi tengo todos los fallos corregidos. ¿Puedo hacer algo por ti?,"Olen paraikaa työstämässä jotain, joka antaa meille etulyöntiaseman. Se kasvattaa kuntoasi ja täydellisesti virittää lihaksesi. Olen melkein saanut hiottua kaikki viat. Voinko olla jotenkin avuksi?",Je travaille sur quelque chose qui nous donnera un peu d'avance. Ca devrait augmenter votre endurance et vous donner un sacré coup de jus. Je crois que j'ai corrigé presque tous les bugs. Je peux vous aider?,"Dolgozok valamin, ami egy jelentősebb előnyhöz juttat minket. Megerősíti az állóképességedet és teljesen felpumpálja a tested. Már majdnem kiküszöböltem a hibákat. Amúgy tudok valamiben segíteni?",Sto lavorando a qualcosa che ci darà un notevole vantaggio. Aumenterà la tua resistenza e ti farà sentire molto più forte. Ho quasi risolto tutti gli effetti collaterali. Posso fare qualcosa per te?,"私は研究にも取り組んでいる。貴方のスタミナを +貴方がいなければ皆死んでいた所だ。","그래서, 네가 그 요원이지? 고맙다. 네가 없었으면 우리들은 이미 죽고 없었을걸.","Dus jij bent de nieuwe agent? Bedankt, zonder jou waren we nu allemaal dood geweest.","Så du er den nye agenten? Takk, uten deg ville vi alle vært døde nå.","Więc jesteś tu nowy? Dzięki, bez ciebie bylibyśmy już martwi.","Então você é o novo agente? Obrigado. Sem você, estaríamos todos mortos neste momento.",,"Deci tu ești noul operator? Merci, dacă nu erai tu, am fi fost cu toții morți deja.","Так это ты наш новый оперативник? Спасибо. Если бы не ты, мы бы все уже были мертвы.",,"Så du är den nya agenten? Tack, utan dig hade vi alla varit döda nu.","Demek yeni ajan sensin? Teşekkürler, sen olmasaydın şu anda hepimiz ölmüş olurduk." +I'm working on something that will give us an edge. It will increase your stamina and completely jack you up. I've almost got all the bugs worked out. Can I do something for you?,TXT_DLG_SCRIPT03_D27288_IMWOR,MAP03: Gerald (no implant),,,"Pracuju na něčem, co by nám mělo pomoci. Přidá ti to výdrž a naprosto tě to nakopne. Už jsem skoro vychytal všechny mouchy. Co pro tebe mohu udělat?","Jeg arbejder på noget, der vil give os en fordel. Det vil øge din udholdenhed og gøre dig helt oppe at køre. Jeg har næsten fået styr på alle fejlene. Må jeg gøre noget for dig?","Ich arbeite an etwas, das uns einen Vorteil verschaffen kann. Es würde deine Ausdauer erhöhen und dir Superkräfte verleihen. Kann ich was für dich tun?",,"Mi laboras super io, kio donos avantaĝon al ni: ĝi pliigos vian energion kaj korpan forton. Mi jam korektis la plimulton de la cimoj. Ĉu mi povas fari ion por vi?",Estoy trabajando en algo que nos dará una ventaja: aumentará tu aguante y fuerza física. Ya casi tengo todos los fallos corregidos. ¿Puedo hacer algo por ti?,Estoy trabajando en algo que nos va a dar una ventaja: va a aumentar tu aguante y fuerza física. Ya casi tengo todos los fallos corregidos. ¿Puedo hacer algo por ti?,"Olen paraikaa työstämässä jotain, joka antaa meille etulyöntiaseman. Se kasvattaa kuntoasi ja täydellisesti virittää lihaksesi. Olen melkein saanut hiottua kaikki viat. Voinko olla jotenkin avuksi?",Je travaille sur quelque chose qui nous donnera un peu d'avance. Ca devrait augmenter votre endurance et vous donner un sacré coup de jus. Je crois que j'ai corrigé presque tous les bugs. Je peux vous aider?,"Dolgozok valamin, ami egy jelentősebb előnyhöz juttat minket. Megerősíti az állóképességedet és teljesen felpumpálja a tested. Már majdnem kiküszöböltem a hibákat. Amúgy tudok valamiben segíteni?",Sto lavorando a qualcosa che ci darà un notevole vantaggio. Aumenterà la tua resistenza e ti farà sentire molto più forte. Ho quasi risolto tutti gli effetti collaterali. Posso fare qualcosa per te?,"私は研究にも取り組んでいる。貴方のスタミナを 増強し完璧な体にすることも可能だ。 そのインプラントのバグも殆ど取り除かれている -ところで何か必要かい?","지금 우리들에게 승산이 갈 만한 연구를 하고 있습니다. 지구력 향상 이식 칩인데, 이 것만 있으면 당신의 체력과 힘을 더 불어넣어줄 겁니다. 오류를 거의 잡기도 했구요. 이제, 뭘 도와드릴까요?",Ik werk aan iets dat ons een voorsprong geeft. Het zal je uithoudingsvermogen verhogen en je volledig opkrikken. Ik heb bijna alle bugs uitgewerkt. Kan ik iets voor je doen?,Jeg jobber med noe som vil gi oss en fordel. Det vil øke utholdenheten din og løfte deg helt opp. Jeg har nesten funnet ut av alle problemene. Kan jeg gjøre noe for deg?,"Pracuję nad czymś dla ciebie co da nam przewagę. Zwiększy ci to wytrzymałość i sprawi, że poczujesz się lepiej. Już prawie naprawiłem wszystkie błędy. Mogę coś dla ciebie zrobić?",Estou trabalhando em algo que vai nos dar um impulso. É algo que vai aumentar sua resistência e te deixar bem mais forte. Estou com quase todos os bugs resolvidos. Posso te ajudar com algo?,,Lucrez la ceva care ne va oferi un avantaj. Îți va mării rezistența fizică și întări. Aproape am rezolvat toate problemele. Pot face ceva pentru tine?,"Я работаю кое над чем, что может нам пригодиться. Оно увеличит твою выносливость и улучшит самочувствие. Я уже исправил почти все дефекты. Что тебе нужно?",,Bize avantaj sağlayacak bir şey üzerinde çalışıyorum. Dayanıklılığını arttıracak ve seni tamamen uçuracak. Neredeyse tüm hataları çözdüm. Senin için bir şey yapabilir miyim? -Patch me up.,TXT_RPLY0_SCRIPT03_D27288_PATCH,〃 (〃),,,Dej mě dohromady.,Giv mig et plaster på såret.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Hoida minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lappe meg sammen.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Подлатай меня.,,Beni yamala. +ところで何か必要かい?","지금 우리들에게 승산이 갈 만한 연구를 하고 있습니다. 지구력 향상 이식 칩인데, 이 것만 있으면 당신의 체력과 힘을 더 불어넣어줄 겁니다. 오류를 거의 잡기도 했구요. 이제, 뭘 도와드릴까요?",Ik werk aan iets dat ons een voorsprong geeft. Het zal je uithoudingsvermogen verhogen en je volledig opkrikken. Ik heb bijna alle bugs uitgewerkt. Kan ik iets voor je doen?,Jeg jobber med noe som vil gi oss en fordel. Det vil øke utholdenheten din og løfte deg helt opp. Jeg har nesten funnet ut av alle problemene. Kan jeg gjøre noe for deg?,"Pracuję nad czymś dla ciebie co da nam przewagę. Zwiększy ci to wytrzymałość i sprawi, że poczujesz się lepiej. Już prawie naprawiłem wszystkie błędy. Mogę coś dla ciebie zrobić?",Estou trabalhando em algo que vai nos dar um impulso. É algo que vai aumentar sua resistência e te deixar bem mais forte. Estou com quase todos os bugs resolvidos. Posso te ajudar com algo?,,Lucrez la ceva care ne va oferi un avantaj. Îți va mării rezistența fizică și întări. Aproape am rezolvat toate problemele. Pot face ceva pentru tine?,"Я работаю кое над чем, что может нам пригодиться. Оно увеличит твою выносливость и улучшит самочувствие. Я уже исправил почти все дефекты. Что тебе нужно?",,Jag jobbar på något som kommer att ge oss en fördel. Det kommer att öka din uthållighet och göra dig helt upprymd. Jag har nästan löst alla buggar. Kan jag göra något för dig?,Bize avantaj sağlayacak bir şey üzerinde çalışıyorum. Dayanıklılığını arttıracak ve seni tamamen uçuracak. Neredeyse tüm hataları çözdüm. Senin için bir şey yapabilir miyim? +Patch me up.,TXT_RPLY0_SCRIPT03_D27288_PATCH,〃 (〃),,,Dej mě dohromady.,Giv mig et plaster på såret.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Hoida minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lappe meg sammen.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Подлатай меня.,,Laga mig.,Beni yamala. "Boy, you're a real mess. I'll see what I can do.",TXT_RYES0_SCRIPT03_D27288_BOYYO,〃 (〃),,,"Tebe teda zřídili, kluku. Uvidím, co s tebou.","Du er et rigtigt rod. Jeg skal se, hvad jeg kan gøre.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,"Ulo, vi estas iomege en malordo. Mi vidos tion, kion mi faru.","Tío, estás hecho un desastre. A ver qué puedo hacer.","Chico, estás hecho un desastre. -A ver qué puedo hacer.","Voi pojat, oletpa hajalla. Katsotaan, mihin pystyn.","Mon petit, vous êtes dans un sale état. Je vais voir ce que je peux faire.","Öregem, elég rossz passzban vagy. Megnézem mit tudok tenni.","Ragazzo, sei messo proprio male. Vediamo cosa posso fare.",君、滅茶苦茶だな。なんとかしよう。,"당신, 정말 엉망이네요... 어떻게든 치료해줄게요.","Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","Jøss, du ser forferdelig ut. Jeg skal se hva jeg kan gjøre.","Chłopie, ależ ty jesteś poszarpany. Zobaczę co da się zrobić.","Rapaz, você está arrebentado. Vou ver o que posso fazer.",,"Măi să fie, ești un dezastru. O să văd ce pot face.","Парень, да на тебя смотреть страшно. Приступим...",,"Evlat, gerçekten berbat durumdasın. Ne yapabileceğime bir bakayım." -Stamina implant?,TXT_RPLY1_SCRIPT03_D27288_STAMI,〃 (〃),,,Implantát pro výdrž?,Udholdenhedsimplantat?,Ausdauerimplantat?,,Ĉu energidona enplantaĵo?,¿Implante de aguante?,,Kuntoistute?,Implant d'endurance?,Állóképesség implantátum?,Impianto stamina?,スタミナインプラント?,지구력 향상 이식?,Stamina implantaat?,Utholdenhetsimplantat?,Implant zwiększający wytrzymałość?,Implante de resistência?,,Implant pentru rezistență?,Выносливостный имплант?,,Dayanıklılık implantı mı? +A ver qué puedo hacer.","Voi pojat, oletpa hajalla. Katsotaan, mihin pystyn.","Mon petit, vous êtes dans un sale état. Je vais voir ce que je peux faire.","Öregem, elég rossz passzban vagy. Megnézem mit tudok tenni.","Ragazzo, sei messo proprio male. Vediamo cosa posso fare.",君、滅茶苦茶だな。なんとかしよう。,"당신, 정말 엉망이네요... 어떻게든 치료해줄게요.","Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","Jøss, du ser forferdelig ut. Jeg skal se hva jeg kan gjøre.","Chłopie, ależ ty jesteś poszarpany. Zobaczę co da się zrobić.","Rapaz, você está arrebentado. Vou ver o que posso fazer.",,"Măi să fie, ești un dezastru. O să văd ce pot face.","Парень, да на тебя смотреть страшно. Приступим...",,Du är en riktig röra. Jag ska se vad jag kan göra.,"Evlat, gerçekten berbat durumdasın. Ne yapabileceğime bir bakayım." +Stamina implant?,TXT_RPLY1_SCRIPT03_D27288_STAMI,〃 (〃),,,Implantát pro výdrž?,Udholdenhedsimplantat?,Ausdauerimplantat?,,Ĉu energidona enplantaĵo?,¿Implante de aguante?,,Kuntoistute?,Implant d'endurance?,Állóképesség implantátum?,Impianto stamina?,スタミナインプラント?,지구력 향상 이식?,Stamina implantaat?,Utholdenhetsimplantat?,Implant zwiększający wytrzymałość?,Implante de resistência?,,Implant pentru rezistență?,Выносливостный имплант?,,Ett uthållighetsimplantat?,Dayanıklılık implantı mı? "All right, this won't take but a moment.",TXT_RYES1_SCRIPT03_D27288_ALLRI,〃 (〃),,,"Dobře, tohle potrvá jen chvilku.","Okay, det tager kun et øjeblik.","Alles klar, das haben wir sofort.",,"Bonege, ĉi tio estos rapidega.","Muy bien, solo tomará un momento.","Muy bien, solo va a -tomar un momento.","Hyvä on, tähän ei mene hetkeä pidempään.","Pas de problème, ça ne prendra qu'un moment.","Rendben, egy pillanat és kész.","Va bene, ci vorrà solo un momento.",いいでしょう、これは時間を取りません。,좋습니다. 시간이 오래 걸리진 않을 거예요.,"Oké, dit duurt maar een momentje.",Dette tar bare et øyeblikk.,"Dobra, to zajmie tylko chwilę.","Ok, só um momento.",,"În regulă, va dura doar un moment.","Отлично, это займёт всего пару секунд.",,"Pekala, bu bir dakikadan fazla sürmez." +tomar un momento.","Hyvä on, tähän ei mene hetkeä pidempään.","Pas de problème, ça ne prendra qu'un moment.","Rendben, egy pillanat és kész.","Va bene, ci vorrà solo un momento.",いいでしょう、これは時間を取りません。,좋습니다. 시간이 오래 걸리진 않을 거예요.,"Oké, dit duurt maar een momentje.",Dette tar bare et øyeblikk.,"Dobra, to zajmie tylko chwilę.","Ok, só um momento.",,"În regulă, va dura doar un moment.","Отлично, это займёт всего пару секунд.",,"Okej, det här tar bara ett ögonblick.","Pekala, bu bir dakikadan fazla sürmez." It's not done yet.,TXT_RNO1_SCRIPT03_D27288_ITSNO,〃 (〃),,,Ještě není hotový.,Det er ikke færdigt endnu.,Es ist noch nicht soweit.,,"Mi ankoraŭ -prilaboras ĝin.",Aún no está listo.,,Se ei ole valmis vielä.,Ce n'est pas encore terminé.,Még nincs kész.,Non è ancora pronto.,まだ完成していません。,아직 완료되지는 않았어요.,Het is nog niet klaar.,Det er ikke ferdig ennå.,Jeszcze nie jest gotowy.,Ainda não terminei.,,Încă nu e gata.,Он ещё не готов.,,Henüz bitmedi. +prilaboras ĝin.",Aún no está listo.,,Se ei ole valmis vielä.,Ce n'est pas encore terminé.,Még nincs kész.,Non è ancora pronto.,まだ完成していません。,아직 완료되지는 않았어요.,Het is nog niet klaar.,Det er ikke ferdig ennå.,Jeszcze nie jest gotowy.,Ainda não terminei.,,Încă nu e gata.,Он ещё не готов.,,Det är inte klart än.,Henüz bitmedi. "Hey, I'm working on an updated version of your implant. Is there anything else I can do?",TXT_DLG_SCRIPT03_D28804_HEYIM,〃 (one upgrade),,,"Hej, pracuju na vylepšené verzi tvého implantátu. Můžu pro tebe udělat něco jiného?","Jeg arbejder på en opdateret version af dit implantat. Er der andet, jeg kan gøre?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,"Mi laboras super plibonigita versio de via enplantaĵo. Ĉu estas io alia, kion mi povas fari por vi?",Estoy trabajando en una versión mejorada de tu implante. ¿Hay algo más que pueda hacer?,,"Hei, olen työstämässä päivitettyä versiota istutteestasi. Voinko olla muuten avuksi?","Hé, je travaille sur une version améliorée de l'implant. Qu'est-ce que je peux faire pour vous?",Az implantátum újabb verzióján dolgozok. Tudok még valamiben segíteni?,"Ehi, sto lavorando ad un aggiornamento per l'impianto stamina. Posso fare qualcos'altro per te?","どうも、私は今最新版のインプラントに -取り組んでいる。何か用かな?","당신의 이식 칩을 위한 향상 개조가 준비되었습니다. 그런 이유로 온게 아니면, 무엇을 도와드릴까요?","Hé, ik ben bezig met een bijgewerkte versie van je implantaat. Is er nog iets anders dat ik kan doen?",Jeg jobber med en oppdatert versjon av implantatet ditt. Er det noe annet jeg kan gjøre?,"Hej, pracuję nad ulepszoną wersją twojego implantu. Mogę coś jeszcze dla ciebie zrobić?",E aí. Estou trabalhando numa versão aprimorada do seu implante. Posso te ajudar com algo?,,"Hei, lucrez la o variantă îmbunătățită a implantului tău. Mai pot să te ajut cu ceva?","Я работаю над улучшенной версией твоего импланта. А пока, что-нибудь ещё?",,"Hey, implantının güncellenmiş bir versiyonu üzerinde çalışıyorum. Yapabileceğim başka bir şey var mı?" -Patch me up.,TXT_RPLY0_SCRIPT03_D28804_PATCH,〃 (〃),,,Dej mě dohromady.,Gør mig klar.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Pistä minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lappe meg sammen.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Подлатай меня.,,Yama yap. +取り組んでいる。何か用かな?","당신의 이식 칩을 위한 향상 개조가 준비되었습니다. 그런 이유로 온게 아니면, 무엇을 도와드릴까요?","Hé, ik ben bezig met een bijgewerkte versie van je implantaat. Is er nog iets anders dat ik kan doen?",Jeg jobber med en oppdatert versjon av implantatet ditt. Er det noe annet jeg kan gjøre?,"Hej, pracuję nad ulepszoną wersją twojego implantu. Mogę coś jeszcze dla ciebie zrobić?",E aí. Estou trabalhando numa versão aprimorada do seu implante. Posso te ajudar com algo?,,"Hei, lucrez la o variantă îmbunătățită a implantului tău. Mai pot să te ajut cu ceva?","Я работаю над улучшенной версией твоего импланта. А пока, что-нибудь ещё?",,Jag jobbar på en uppdaterad version av ditt implantat. Finns det något annat jag kan göra?,"Hey, implantının güncellenmiş bir versiyonu üzerinde çalışıyorum. Yapabileceğim başka bir şey var mı?" +Patch me up.,TXT_RPLY0_SCRIPT03_D28804_PATCH,〃 (〃),,,Dej mě dohromady.,Gør mig klar.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Pistä minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lappe meg sammen.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Подлатай меня.,,Laga mig.,Yama yap. Well at least your seeing action.,TXT_RYES0_SCRIPT03_D28804_WELLA,〃 (〃),,,"No, alespoň se nenudíš.",I det mindste kan du se noget.,"Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,"Nu, almenaŭ vi ne havas -enuigajn misiojn.","Bueno, al menos estás -teniendo algo de acción.",,"No, ainakin näet toimintaa.","Eh bien, au moins vous en voyez, de l'action.",Legalább neked jut valami akció.,"Beh, almeno ti stai dando da fare.",貴方の働きは聞き届いてるよ。,이제 전장에 힘을 발휘해보세요!,"Nou ja, in ieder geval uw zien actie.",Du ser i det minste noe.,Przynajmniej będziesz mógł wrócić do akcji.,"Bem, pelo menos tá tendo um pouco de ação.",,"Eh, măcar tu ai parte de acțiune.","Что ж, зато ты участвуешь в операциях.",,En azından hareket görüyorsun. -Implant upgrade?,TXT_RPLY1_SCRIPT03_D28804_IMPLA,〃 (〃),,,Vylepšený implantát?,Opgradering af implantater?,Implantatsupgrade?,,Ĉu plibonigo de enplantaĵo?,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Implantatoppgradering?,Ulepszenie implantu?,Versão aprimorada do implante?,,Upgrade pentru implant?,Улучшение импланта?,,İmplant güncellemesi mi? +enuigajn komisiojn.","Bueno, al menos estás +teniendo algo de acción.",,"No, ainakin näet toimintaa.","Eh bien, au moins vous en voyez, de l'action.",Legalább neked jut valami akció.,"Beh, almeno ti stai dando da fare.",貴方の働きは聞き届いてるよ。,이제 전장에 힘을 발휘해보세요!,"Nou ja, in ieder geval uw zien actie.",Du ser i det minste noe.,Przynajmniej będziesz mógł wrócić do akcji.,"Bem, pelo menos tá tendo um pouco de ação.",,"Eh, măcar tu ai parte de acțiune.","Что ж, зато ты участвуешь в операциях.",,Du får åtminstone se handling.,En azından hareket görüyorsun. +Implant upgrade?,TXT_RPLY1_SCRIPT03_D28804_IMPLA,〃 (〃),,,Vylepšený implantát?,Opgradering af implantater?,Implantatsupgrade?,,Ĉu plibonigo de enplantaĵo?,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Implantatoppgradering?,Ulepszenie implantu?,Versão aprimorada do implante?,,Upgrade pentru implant?,Улучшение импланта?,,Implantatuppgradering?,İmplant güncellemesi mi? "Good thing, never can be too safe.",TXT_RYES1_SCRIPT03_D28804_GOODT,〃 (〃),,,"Dobrá věcička, nikdy si nemůžeš být moc jistý.","Godt nok, man kan aldrig være for sikker.","Alles klar, das haben wir sofort.",,"Bone. Neniam estas sufiĉe da sekureco.","Bien. Nunca se puede -estar del todo seguro.",,"Hyvä, koskaan ei voi olla liian turvallista.",Bonne idée. On ne peut jamais être trop sûr.,"Helyes, sosem lehetünk elég elővigyázatosak.","Ottimo, non si può mai essere troppo al sicuro.",良いことだ、安全すぎることはない。,좋은 선택입니다. 이거 없이는 안전할 수가 없죠.,"Goede zaak, kan nooit te veilig zijn.","Bra, man kan aldri være for sikker.","Dobra rzecz, nigdy za mało bezpieczeństwa.",Boa idéia. Segurança nunca é demais.,,"Recomand cu mare drag, nu poți fi niciodată prea sigur.","Очень советую, ни в чём нельзя быть уверенным до конца.",,"İyi bir şey, asla çok güvenli olamaz." +estar del todo seguro.",,"Hyvä, koskaan ei voi olla liian turvallista.",Bonne idée. On ne peut jamais être trop sûr.,"Helyes, sosem lehetünk elég elővigyázatosak.","Ottimo, non si può mai essere troppo al sicuro.",良いことだ、安全すぎることはない。,좋은 선택입니다. 이거 없이는 안전할 수가 없죠.,"Goede zaak, kan nooit te veilig zijn.","Bra, man kan aldri være for sikker.","Dobra rzecz, nigdy za mało bezpieczeństwa.",Boa idéia. Segurança nunca é demais.,,"Recomand cu mare drag, nu poți fi niciodată prea sigur.","Очень советую, ни в чём нельзя быть уверенным до конца.",,"Bra, man kan aldrig vara för säker.","İyi bir şey, asla çok güvenli olamaz." "I'm almost finished, but not quite.",TXT_RNO1_SCRIPT03_D28804_IMALM,〃 (〃),,,"Už je skoro hotový, ale ne úplně.","Jeg er næsten færdig, men ikke helt.",Es ist noch nicht soweit.,,"Mi preskaŭ finis, sed ne tute.","Casi he terminado, -pero no del todo.",,"Olen melkein valmis, mutten ihan vielä.","Presque fini, mais pas encore.","Már majdnem végeztem, még egy kicsi híja van.","Ho quasi finito, ma non ancora.",もうすぐ出来上がる、それほど掛からない。,"거의 다 돼가지만, 아직 완성된 게 아니에요.","Ik ben bijna klaar, maar niet helemaal.","Jeg er nesten ferdig, men ikke helt.","Prawie skończyłem, ale nie do końca.",Estou quase terminando. Só mais um pouco.,,"Sunt aproape gata, dar nu tocmai.",Я почти закончил. Ещё немного.,,Neredeyse bitirdim ama tam olarak değil. +pero no del todo.",,"Olen melkein valmis, mutten ihan vielä.","Presque fini, mais pas encore.","Már majdnem végeztem, még egy kicsi híja van.","Ho quasi finito, ma non ancora.",もうすぐ出来上がる、それほど掛からない。,"거의 다 돼가지만, 아직 완성된 게 아니에요.","Ik ben bijna klaar, maar niet helemaal.","Jeg er nesten ferdig, men ikke helt.","Prawie skończyłem, ale nie do końca.",Estou quase terminando. Só mais um pouco.,,"Sunt aproape gata, dar nu tocmai.",Я почти закончил. Ещё немного.,,"Jag är nästan klar, men inte riktigt.",Neredeyse bitirdim ama tam olarak değil. "All right, I've almost got everything working perfectly. There were a few problems left to get rid of. Do you need anything else? ",TXT_DLG_SCRIPT03_D30320_ALLRI,〃 (two upgrades),,,"Tak dobře, už mi skoro všechno perfektně funguje. Ještě tam bylo pár problémů. Potřebuješ ještě něco?","Okay, jeg har næsten fået det hele til at fungere perfekt. Der var et par problemer tilbage at slippe af med. Har du brug for noget andet?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,"Bone, preskaŭ ĉio funkcias perfekte. Restis nur kelkaj korektindaj problemoj. Ĉu vi bezonas ion alian?","Muy bien, tengo casi todo funcionando a la perfección. Solo quedaban algunos problemas que corregir. ¿Necesitas algo más?",,"No niin, olen melkein saanut kaiken toimimaan täydellisesti. Vain muutamia vikoja oli enää jäljellä. Tarvitsetko mitään muuta?","Très bien, je crois que j'ai réussi à tout faire marcher parfaitement. Il y avait quelques problèmes dont je devais me débarrasser. Vous voulez quelque chose?","Nos, már majdnem minden tökéletesen működik. Volt néhány kijavítandó hiba. Tudok még valamiben segíteni?","Allora, sono riuscito a far funzionare quasi tutto benissimo. C'erano giusto un paio di problemi rimasti da risolvere. Ti serve qualcos'altro?","大丈夫、全て順調だ。残っていた問題も -全て取り除かれた。他に何が必要かな?",연구가 거의 다 끝나갑니다. 연구 도중에 오류를 좀 잡았어요. 기다리는 동안 뭐 필요한 게 있나요?,"Oke, ik heb bijna alles wat perfect werkt. Er waren nog een paar problemen over om van af te komen. Heeft u nog iets anders nodig?",Jeg har nesten fått alt til å fungere perfekt. Det var et par problemer igjen å bli kvitt. Trenger du noe mer?,"Dobra, prawie wszystko działa dobrze. Zostało jeszcze parę rzeczy do zrobienia. Czy coś jeszcze potrzebujesz?","Ok, tenho quase tudo funcionando perfeitamente. Ainda faltam alguns probleminhas para tirar de você. Precisa de mais alguma coisa?",,"În regulă, totul funcționează aproape perfect. Au mai fost niște probleme care trebuiau rezolvate. Mai ai nevoie de altceva?","Итак, тут оставалась пара проблем, но теперь всё работает почти идеально. Что-нибудь ещё?",,"Pekala, neredeyse her şey mükemmel çalışıyor. Kurtulmam gereken birkaç sorun kaldı. Başka bir şeye ihtiyacın var mı?" -Patch me up.,TXT_RPLY0_SCRIPT03_D30320_PATCH,〃 (〃),,,Dej mě dohromady.,Lav mig om.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Paikkaa minut.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lapp meg sammen.,Opatrz mnie.,Trate meus ferimentos.,,Tratează-mă.,Подлатай меня.,,Beni yamala. +全て取り除かれた。他に何が必要かな?",연구가 거의 다 끝나갑니다. 연구 도중에 오류를 좀 잡았어요. 기다리는 동안 뭐 필요한 게 있나요?,"Oke, ik heb bijna alles wat perfect werkt. Er waren nog een paar problemen over om van af te komen. Heeft u nog iets anders nodig?",Jeg har nesten fått alt til å fungere perfekt. Det var et par problemer igjen å bli kvitt. Trenger du noe mer?,"Dobra, prawie wszystko działa dobrze. Zostało jeszcze parę rzeczy do zrobienia. Czy coś jeszcze potrzebujesz?","Ok, tenho quase tudo funcionando perfeitamente. Ainda faltam alguns probleminhas para tirar de você. Precisa de mais alguma coisa?",,"În regulă, totul funcționează aproape perfect. Au mai fost niște probleme care trebuiau rezolvate. Mai ai nevoie de altceva?","Итак, тут оставалась пара проблем, но теперь всё работает почти идеально. Что-нибудь ещё?",,"Okej, jag har nästan fått allt att fungera perfekt. Det fanns några problem kvar att bli av med. Behöver du något annat?","Pekala, neredeyse her şey mükemmel çalışıyor. Kurtulmam gereken birkaç sorun kaldı. Başka bir şeye ihtiyacın var mı?" +Patch me up.,TXT_RPLY0_SCRIPT03_D30320_PATCH,〃 (〃),,,Dej mě dohromady.,Lav mig om.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Paikkaa minut.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lapp meg sammen.,Opatrz mnie.,Trate meus ferimentos.,,Tratează-mă.,Подлатай меня.,,Laga mig.,Beni yamala. What have you been trying to do? Go head to head with a Crusader?,TXT_RYES0_SCRIPT03_D30320_WHATH,〃 (〃),,,Co jsi dělal? Šel zmlátit Křižáka?,Hvad har du forsøgt at gøre? At gå i kamp mod en korsfarer?,"Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,"Kion vi intencis fari? Ĉu piki Kruciston?","¿Qué has intentado hacer? ¿Ir cara a cara con un Cruzado?","¿Qué anduviste haciendo? ¿Ir cara a cara con un Cruzado?",Mitä olet oikein yrittänyt tehdä? Mennä nokittain ristiretkeläisen kanssa?,Qu'est-ce que vous avez fait? Vous avez essayé de faire ami avec un Croisé?,Mi a francot képzeltél? Egymagad nekimész egy keresztesnek?,Ma cosa hai cercato di fare? Lottare da solo contro un Crociato?,"今度は何を始めるんだ? -クルセイダーと向かい合うのか?",뭘 하다 왔나요? 크루세이더랑 한판 뜨기라도 했나요?,Wat heb je geprobeerd te doen? Hoofd aan hoofd gaan met een kruisvaarder?,Hva har du prøvd å gjøre? Kjempe mot en korsfarer?,Co ty próbowałeś zrobić? Walczyć oko w oko z Krzyżowcem?,O que você andou tentando fazer? Partiu pro soco contra um Cruzado?,,Ce ai încercat să faci? Să dai cap în cap cu un Cruciat?,Что было у тебя на уме? Биться один на один с крестоносцем?,,Ne yapmaya çalışıyordun? Bir Crusader ile kafa kafaya mı? -Implant upgrade?.,TXT_RPLY1_SCRIPT03_D30320_IMPLA,〃 (〃),,,Vylepšený implantát?,Implantat opgradering?,Implantatsupgrade?,,Ĉu plibonigo de enplantaĵo?,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Implantatoppgradering?,Ulepszenie implantu?,Melhoria de implante?,,Upgrade pentru implant?,Улучшение импланта?,,İmplant yükseltmesi mi? -That should do it for you.,TXT_RYES1_SCRIPT03_D30320_THATS,〃 (〃),,,Tohle by mělo fungovat.,Det burde gøre det for dig.,"Alles klar, das haben wir sofort.",,Ĉi tio devus esti sufiĉa.,Con esto debería estar.,,Eiköhän tällä ala tepsiä.,Ca devrait faire l'affaire.,Ez már így jó lesz.,Questo dovrebbe andare.,今取り掛かっている。,이것만 있음 될 겁니다.,Dat zou het voor u moeten doen.,Det burde gjøre det for deg.,To powinno ci wystarczyć.,Isso deve funcionar.,,Ar trebui să fie bine acum.,Вот оно.,,Bu senin işini görür. +クルセイダーと向かい合うのか?",뭘 하다 왔나요? 크루세이더랑 한판 뜨기라도 했나요?,Wat heb je geprobeerd te doen? Hoofd aan hoofd gaan met een kruisvaarder?,Hva har du prøvd å gjøre? Kjempe mot en korsfarer?,Co ty próbowałeś zrobić? Walczyć oko w oko z Krzyżowcem?,O que você andou tentando fazer? Partiu pro soco contra um Cruzado?,,Ce ai încercat să faci? Să dai cap în cap cu un Cruciat?,Что было у тебя на уме? Биться один на один с крестоносцем?,,Vad har du försökt göra? Gå mot en korsriddare?,Ne yapmaya çalışıyordun? Bir Haçlı ile kafa kafaya mı? +Implant upgrade?.,TXT_RPLY1_SCRIPT03_D30320_IMPLA,〃 (〃),,,Vylepšený implantát?,Implantat opgradering?,Implantatsupgrade?,,Ĉu plibonigo de enplantaĵo?,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Implantatoppgradering?,Ulepszenie implantu?,Melhoria de implante?,,Upgrade pentru implant?,Улучшение импланта?,,Implantatuppgradering?,İmplant yükseltmesi mi? +That should do it for you.,TXT_RYES1_SCRIPT03_D30320_THATS,〃 (〃),,,Tohle by mělo fungovat.,Det burde gøre det for dig.,"Alles klar, das haben wir sofort.",,Ĉi tio devus esti sufiĉa.,Con esto debería estar.,,Eiköhän tällä ala tepsiä.,Ca devrait faire l'affaire.,Ez már így jó lesz.,Questo dovrebbe andare.,今取り掛かっている。,이것만 있음 될 겁니다.,Dat zou het voor u moeten doen.,Det burde gjøre det for deg.,To powinno ci wystarczyć.,Isso deve funcionar.,,Ar trebui să fie bine acum.,Вот оно.,,Det borde göra det för dig.,Bu senin işini görür. Let me run some more tests first.,TXT_RNO1_SCRIPT03_D30320_LETME,〃 (〃),,,Ještě ho musím dál otestovat.,Lad mig køre nogle flere tests først.,Es ist noch nicht soweit.,,"Unue mi faru kelkajn provojn.","Déjame hacer algunas -pruebas primero.",,Anna minun ajaa muutamia kokeita ensin.,Laissez moi faire quelques tests d'abord.,Hadd futtassak pár tesztet előtte.,Devo fare ancora qualche test.,もう少しテストしてからにしよう。,"우선, 시험을 좀 거쳐야 해요.",Laat me eerst nog wat testen doen.,La meg kjøre noen flere tester først.,Pozwól mi zrobić jeszcze parę testów.,Deixe eu fazer alguns testes primeiro.,,Lasă-mă să mai fac niște teste mai întâi.,Дай мне ещё времени на тесты.,,Önce birkaç test daha yapayım. +pruebas primero.",,Anna minun ajaa muutamia kokeita ensin.,Laissez moi faire quelques tests d'abord.,Hadd futtassak pár tesztet előtte.,Devo fare ancora qualche test.,もう少しテストしてからにしよう。,"우선, 시험을 좀 거쳐야 해요.",Laat me eerst nog wat testen doen.,La meg kjøre noen flere tester først.,Pozwól mi zrobić jeszcze parę testów.,Deixe eu fazer alguns testes primeiro.,,Lasă-mă să mai fac niște teste mai întâi.,Дай мне ещё времени на тесты.,,Låt mig köra några fler tester först.,Önce birkaç test daha yapayım. That's all I can do on the implant right now. Maybe some healing?,TXT_DLG_SCRIPT03_D31836_THATS,〃 (?),,,"Tak, to je všechno co teď můžu s tím implantátem udělat. Potřebuješ léčení?","Det er alt, hvad jeg kan gøre på implantatet lige nu. Måske noget healing?","Das ist alles, was ich im Moment mit dem Implantat machen kann. Vielleicht etwas medizinische Versorgung?",,"Tio estas ĉio, kion mi momente povas fari super la enplantaĵo. Ĉu vi bezonas kuracon?",Eso es todo lo que puedo hacer con el implante por ahora. ¿Necesitas curarte?,,Tätä enempää en voi istutteelle enää juuri nyt tehdä. Mutta oletko hoidon tarpeessa?,C'est tout ce que je peux faire pour l'implant. Vous voulez que je vous soigne?,Csak ennyit tudok most kezdeni az implantátummal. Talán egy kis gyógyítás?,È tutto per quanto riguarda l'impianto. Però posso sempre curarti.,"インプラントはこれ以上ない程完成した。 -それとも治療か?",지구력 향상 관련은 이게 다입니다. 이제 치료가 좀 필요하신가요?,Dat is alles wat ik nu kan doen op het implantaat. Misschien wat genezing?,Det er alt jeg kan gjøre med implantatet akkurat nå. Kanskje litt helbredelse?,To wszystko co mogę zrobić w sprawie implantu. Może chcesz się podleczyć?,Isso é tudo que posso fazer com o implante no momento. Não quer um tratamento nesses ferimentos?,,Asta e tot ce îi pot face implantului pentru moment. Poate niște tratament?,Пока что я больше ничего не могу сделать с имплантом. Как насчёт лечения?,,Şu anda implant üzerinde yapabileceğim tek şey bu. Belki biraz iyileşme? -Yeah.,TXT_RPLY0_SCRIPT03_D31836_YEAH,〃 (〃),,,Jo.,Ja.,Ja.,,Jes.,Sí.,,Kyllä.,Ouais.,Igen.,Sì.,ああ。,네.,Ja.,Ja.,Pewnie.,Pode ser.,,Da.,Давай.,,"Evet, belki." +それとも治療か?",지구력 향상 관련은 이게 다입니다. 이제 치료가 좀 필요하신가요?,Dat is alles wat ik nu kan doen op het implantaat. Misschien wat genezing?,Det er alt jeg kan gjøre med implantatet akkurat nå. Kanskje litt helbredelse?,To wszystko co mogę zrobić w sprawie implantu. Może chcesz się podleczyć?,Isso é tudo que posso fazer com o implante no momento. Não quer um tratamento nesses ferimentos?,,Asta e tot ce îi pot face implantului pentru moment. Poate niște tratament?,Пока что я больше ничего не могу сделать с имплантом. Как насчёт лечения?,,Det är allt jag kan göra med implantatet just nu. Kanske lite läkning?,Şu anda implant üzerinde yapabileceğim tek şey bu. Belki biraz iyileşme? +Yeah.,TXT_RPLY0_SCRIPT03_D31836_YEAH,〃 (〃),,,Jo.,Ja.,Ja.,,Jes.,Sí.,,Kyllä.,Ouais.,Igen.,Sì.,ああ。,네.,Ja.,Ja.,Pewnie.,Pode ser.,,Da.,Давай.,,"Ja, det är det.","Evet, belki." "Boy, you're a real mess. I'll see what I can do.",TXT_RYES0_SCRIPT03_D31836_BOYYO,〃 (〃),,,"Tebe teda zřídili, kluku. Uvidím, co s tebou.","Mand, du er et rigtigt rod. Jeg skal se, hvad jeg kan gøre.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,"Ulo, vi estas iomege en malordo. Mi vidos tion, kion mi faru.","Tío, estás hecho un desastre. A ver qué puedo hacer.","Chico, estás hecho un desastre. -A ver qué puedo hacer.","Kylläpä olet huonossa jamassa. Katsotaan, mitä voin tehdä.","Mon petit, vous êtes dans un sale état. Je vais voir ce que je peux faire.","Öregem, elég rossz passzban vagy. Megnézem mit tudok tenni.","Ragazzo, sei messo proprio male. Vediamo cosa posso fare.",君、滅茶苦茶だな。なんとかしよう。,심각한 부상을 입은 것 같군요. 치료하겠습니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","Jøss, du er et skikkelig rot. Jeg skal se hva jeg kan gjøre.","Chłopie, ależ ty jesteś poszarpany. Zobaczę co da się zrobić.","Rapaz, você está arrebentado. Vou ver o que posso fazer.",,"Mamă, ești un dezastru. O să văd ce pot face.","Парень, да на тебя смотреть страшно. Приступим...",,Çok dağınıksın. Ne yapabileceğime bir bakayım. -What can I do for you?,TXT_DLG_SCRIPT03_D33352_WHATC,MAP03: Feris (no training).,,,Co pro tebe můžu udělat?,Hvad kan jeg gøre for dig?,Was kann ich für dich tun?,,Kion mi faru por vi?,¿Qué puedo hacer por ti?,,Mitä voin tehdä sinulle?,Que puis-je faire pour vous?,Miben segíthetek?,Cosa posso fare per te?,どういったご用件で?,필요한 게 있으면 말씀하세요.,Wat kan ik voor je doen?,Hva kan jeg gjøre for deg?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot face pentru tine?,Чем я могу тебе помочь?,,Senin için ne yapabilirim? -I'm out of bullets.,TXT_RPLY0_SCRIPT03_D33352_IMOUT,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi estas sen kugloj.,No me quedan balas.,,Minulta on luodit loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Nie mam nabojów.,Estou sem balas.,,Nu mai am gloanțe.,У меня кончились патроны.,,Mermim bitti. +A ver qué puedo hacer.","Kylläpä olet huonossa jamassa. Katsotaan, mitä voin tehdä.","Mon petit, vous êtes dans un sale état. Je vais voir ce que je peux faire.","Öregem, elég rossz passzban vagy. Megnézem mit tudok tenni.","Ragazzo, sei messo proprio male. Vediamo cosa posso fare.",君、滅茶苦茶だな。なんとかしよう。,심각한 부상을 입은 것 같군요. 치료하겠습니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","Jøss, du er et skikkelig rot. Jeg skal se hva jeg kan gjøre.","Chłopie, ależ ty jesteś poszarpany. Zobaczę co da się zrobić.","Rapaz, você está arrebentado. Vou ver o que posso fazer.",,"Mamă, ești un dezastru. O să văd ce pot face.","Парень, да на тебя смотреть страшно. Приступим...",,Du är en riktig röra. Jag ska se vad jag kan göra.,Çok dağınıksın. Ne yapabileceğime bir bakayım. +What can I do for you?,TXT_DLG_SCRIPT03_D33352_WHATC,MAP03: Feris (no training).,,,Co pro tebe můžu udělat?,Hvad kan jeg gøre for dig?,Was kann ich für dich tun?,,Kion mi faru por vi?,¿Qué puedo hacer por ti?,,Mitä voin tehdä sinulle?,Que puis-je faire pour vous?,Miben segíthetek?,Cosa posso fare per te?,どういったご用件で?,필요한 게 있으면 말씀하세요.,Wat kan ik voor je doen?,Hva kan jeg gjøre for deg?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot face pentru tine?,Чем я могу тебе помочь?,,Vad kan jag göra för dig?,Senin için ne yapabilirim? +I'm out of bullets.,TXT_RPLY0_SCRIPT03_D33352_IMOUT,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi ne havas kuglojn.,No me quedan balas.,,Minulta on luodit loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Nie mam nabojów.,Estou sem balas.,,Nu mai am gloanțe.,У меня кончились патроны.,,Jag har slut på kulor.,Mermim bitti. Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D33352_HERES,〃 (〃),,,"Tady máš nějakou munici, neplýtvej s ní.",Her er noget ammunition til dig. Spild det ikke.,Hier hast du welche. Verschwende sie nicht.,,"Jen iom da municio. Ne malŝparu ĝin.","Aquí tienes algo de munición. -No la desperdicies.",,Tässä sinulle panoksia. Älä tuhlaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van egy kis muníció számodra. Ne pazarold el.,Ecco un pò di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,여기 조금의 탄약을 나눠줄게요. 낭비하지 마시길.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,Al sana biraz mermi. Boşa harcama. -Teach me.,TXT_RPLY1_SCRIPT03_D33352_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. +No la desperdicies.",,Tässä sinulle panoksia. Älä tuhlaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van egy kis muníció számodra. Ne pazarold el.,Ecco un po' di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,여기 조금의 탄약을 나눠줄게요. 낭비하지 마시길.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,Här är lite ammunition till dig. Slösa inte bort den.,Al sana biraz mermi. Boşa harcama. +Teach me.,TXT_RPLY1_SCRIPT03_D33352_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. "All right, I'll just show you a few little pointers.",TXT_RYES1_SCRIPT03_D33352_ALLRI,〃 (〃),,,"Dobře, ukážu ti pár triků.","Okay, jeg vil bare vise dig et par små tips.","Alles klar, ich zeige dir ein paar Kniffe.",,"Bone, jen kelkaj konsiletoj...","Muy bien, aquí van -un par de consejos...",,"Hyvä on, annan sinulle vain muutamia pikkuvinkkejä.",Pas de problème. Laissez moi vous montrer quelques trucs.,Akkor addok pár hasznos tanácsot.,"Va bene, ti darò un paio di dritte molto utili.",わかった、貴方にやり方を幾つか教えよう。,좋아요. 훈련에 도움이 될 만한 표적을 보여주겠습니다.,"Oké, ik zal je gewoon een paar kleine tips laten zien.","Greit, jeg skal bare vise deg noen små tips.","Dobrze, podam ci parę wskazówek.","Ok, vou te dar algumas dicas.",,"În regulă, o să îți arăt niște repere.",Хорошо. Покажу тебе пару приёмов.,,"Pekala, sana birkaç küçük ipucu göstereceğim." +un par de consejos...",,"Hyvä on, annan sinulle vain muutamia pikkuvinkkejä.",Pas de problème. Laissez moi vous montrer quelques trucs.,Akkor addok pár hasznos tanácsot.,"Va bene, ti darò un paio di dritte molto utili.",わかった、貴方にやり方を幾つか教えよう。,좋아요. 훈련에 도움이 될 만한 표적을 보여주겠습니다.,"Oké, ik zal je gewoon een paar kleine tips laten zien.","Greit, jeg skal bare vise deg noen små tips.","Dobrze, podam ci parę wskazówek.","Ok, vou te dar algumas dicas.",,"În regulă, o să îți arăt niște repere.",Хорошо. Покажу тебе пару приёмов.,,"Okej, jag ska bara visa dig några små tips.","Pekala, sana birkaç küçük ipucu göstereceğim." You're not ready yet.,TXT_RNO1_SCRIPT03_D33352_YOURE,〃 (〃),,,Ještě nejsi připravený.,Du er ikke klar endnu.,Du bist noch nicht so weit.,,"Vi ankoraŭ -ne estas preta.",Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Még nem állsz készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,아직 준비가 안 됐어요.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze gotowy.,Você ainda não está pronto.,,Nu ești pregătit încă.,Ты ещё не готов.,,Henüz hazır değilsin. -Back again? What do you need?,TXT_DLG_SCRIPT03_D34868_BACKA,〃 (one training),,,Zase zpátky? Co potřebuješ?,Tilbage igen? Hvad har du brug for?,Scxhon zurück? Was brauchst du?,,Do vi revenis. Kion vi bezonas?,¿Ya de vuelta? ¿Qué necesitas?,,Täällä taas? Mitä tarvitset?,Déjà de retour? De quoi avez-vous besoin?,Már vissza is tértél? Mire van szükséged?,Già di ritorno? Che cosa ti serve?,もう戻りましたか?何が必要ですか?,또 왔네? 뭐가 필요합니까?,Weer terug? Wat heb je nodig?,Tilbake igjen? Hva trenger du?,Wróciłeś? Czego chcesz?,Você novamente? Do que precisa?,,Te-ai întors iar? De ce ai nevoie?,Ты вернулся? Что тебе нужно?,,Yine mi? Neye ihtiyacın var? -I'm out of bullets.,TXT_RPLY0_SCRIPT03_D34868_IMOUT,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi estas sen kugloj.,No me quedan balas.,,Minulta on ammukset loppu.,Je suis à cours de munitions.,Kifogytam a golyókból.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Nie mam nabojów.,Estou sem balas.,,Nu mai am gloanțe.,У меня кончились патроны.,,Mermim bitti. +ne estas preta.",Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Még nem állsz készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,아직 준비가 안 됐어요.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze gotowy.,Você ainda não está pronto.,,Nu ești pregătit încă.,Ты ещё не готов.,,Du är inte redo än.,Henüz hazır değilsin. +Back again? What do you need?,TXT_DLG_SCRIPT03_D34868_BACKA,〃 (one training),,,Zase zpátky? Co potřebuješ?,Tilbage igen? Hvad har du brug for?,Scxhon zurück? Was brauchst du?,,Do vi revenis. Kion vi bezonas?,¿Ya de vuelta? ¿Qué necesitas?,,Täällä taas? Mitä tarvitset?,Déjà de retour? De quoi avez-vous besoin?,Már vissza is tértél? Mire van szükséged?,Già di ritorno? Che cosa ti serve?,もう戻りましたか?何が必要ですか?,또 왔네? 뭐가 필요합니까?,Weer terug? Wat heb je nodig?,Tilbake igjen? Hva trenger du?,Wróciłeś? Czego chcesz?,Você novamente? Do que precisa?,,Te-ai întors iar? De ce ai nevoie?,Ты вернулся? Что тебе нужно?,,Tillbaka igen? Vad behöver du?,Yine mi? Neye ihtiyacın var? +I'm out of bullets.,TXT_RPLY0_SCRIPT03_D34868_IMOUT,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi ne havas kuglojn.,No me quedan balas.,,Minulta on ammukset loppu.,Je suis à cours de munitions.,Kifogytam a golyókból.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Nie mam nabojów.,Estou sem balas.,,Nu mai am gloanțe.,У меня кончились патроны.,,Jag har slut på kulor.,Mermim bitti. Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D34868_HERES,〃 (〃),,,"Tady máš nějakou munici, neplýtvej s ní.",Her er lidt ammunition til dig. Spild det ikke.,Hier hast du welche. Verschwende sie nicht.,,"Jen iom da municio. Ne malŝparu ĝin.","Aquí tienes algo de munición. -No la desperdicies.",,Tässä vähän lisää. Älä haaskaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van egy kis muníció számodra. Ne pazarold el.,Ecco un pò di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,뭘 하다 탄약을 낭비한 겁니까? 여기 조금 줄게요.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,İşte sana biraz cephane. Boşa harcama. -You've got enough ammo.,TXT_RNO0_SCRIPT03_D34868_YOUVE,〃 (〃),,,Vždyť jich máš dost.,Du har ammunition nok.,Du hast genug.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ma veramente ne hai a sufficienza.,弾は十分に見えます。,당신은 충분한 탄약을 가졌어요.,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz już wystarczająco dużo amunicji.,Você já tem munição o suficiente.,,Au destulă muniție.,У тебя их достаточно.,,Yeterince mermin var. -Teach me.,TXT_RPLY1_SCRIPT03_D34868_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. +No la desperdicies.",,Tässä vähän lisää. Älä haaskaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van egy kis muníció számodra. Ne pazarold el.,Ecco un po' di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,뭘 하다 탄약을 낭비한 겁니까? 여기 조금 줄게요.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,Här är lite ammunition till dig. Slösa inte bort den.,İşte sana biraz cephane. Boşa harcama. +You've got enough ammo.,TXT_RNO0_SCRIPT03_D34868_YOUVE,〃 (〃),,,Vždyť jich máš dost.,Du har ammunition nok.,Du hast genug.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ma veramente ne hai a sufficienza.,弾は十分に見えます。,당신은 충분한 탄약을 가졌어요.,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz już wystarczająco dużo amunicji.,Você já tem munição o suficiente.,,Au destulă muniție.,У тебя их достаточно.,,Du har tillräckligt med ammunition.,Yeterince mermin var. +Teach me.,TXT_RPLY1_SCRIPT03_D34868_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. "All right, this should keep you going for a while.",TXT_RYES1_SCRIPT03_D34868_ALLRI,〃 (〃),,,"Dobře, tohle by ti mělo pomoct.","Okay, det her burde holde dig i gang et stykke tid.","Alles klar, das sollte fürs erste reichen.",,"Bone, ĉi tio devus esti sufiĉe utila nuntempe.","Muy bien, esto debería -servirte por el momento.",,"Selvä on, tällä sinun pitäisi pötkiä aika pitkälle.","Bien, ça devrait vous suffir pour un bon moment.","Rendben van, ezzel el leszel egy darabig.","Va bene, con questo dovresti andare sul sicuro per un pò.",わかりました、これで長くやり合えるでしょう。,그렇군요. 가능한 오래 싸울 수 있을겁니다.,"Oké, dit zou je een tijdje op de been moeten houden.","Greit, dette burde holde deg gående en stund.","Dobrze, to powinno ci pomóc na pewien czas.","Ok, isso deve te ajudar no momento.",,"În regulă, asta ar trebui să te ajute pentru moment.","Хорошо, это не раз спасёт тебе жизнь.",,"Pekala, bu seni bir süre idare eder." +servirte por el momento.",,"Selvä on, tällä sinun pitäisi pötkiä aika pitkälle.","Bien, ça devrait vous suffir pour un bon moment.","Rendben van, ezzel el leszel egy darabig.","Va bene, con questo dovresti andare sul sicuro per un po'.",わかりました、これで長くやり合えるでしょう。,그렇군요. 가능한 오래 싸울 수 있을겁니다.,"Oké, dit zou je een tijdje op de been moeten houden.","Greit, dette burde holde deg gående en stund.","Dobrze, to powinno ci pomóc na pewien czas.","Ok, isso deve te ajudar no momento.",,"În regulă, asta ar trebui să te ajute pentru moment.","Хорошо, это не раз спасёт тебе жизнь.",,"Okej, det här borde hålla dig igång ett tag.","Pekala, bu seni bir süre idare eder." "Sorry, can't. I'm just following Macil's orders.",TXT_RNO1_SCRIPT03_D34868_SORRY,〃 (〃),,,"Promiň, nemůžu. Řídím se rozkazy od Macila.","Beklager, jeg kan ikke. Jeg følger bare Macils ordrer.","Tut mir leid, aber ich kann nicht. Ich folge nur Macils Befehlen.",,"Pardonon, mi ne rajtas. Mi nur observas Macil-on.","Lo siento, no puedo. -Solo sigo órdenes de Macil.",,Valitettavasti en voi. Noudatan vain Macilin käskyjä.,"Désolé, pas possible. Je ne fais que suivre les ordres de Macil.","Sajnálom, de nem tehetem. Macil utasítása.","Mi spiace, ma non posso. Ordini dall'alto.",すまないが、できません。マシルの命令です。,미안합니다. 마실 사령관님의 명령을 따라야해요.,"Sorry, dat kan niet. Ik volg gewoon de orders van Macil op.","Beklager, jeg kan ikke. Jeg følger bare Macils ordre.","Przepraszam, ale nie mogę. Ja tylko wykonuję rozkazy Macila.",Desculpe mas não posso. Estou apenas seguindo as ordens de Macil.,,"Scuze, nu merge. Doar urmez ordinele lui Macil.","Увы, не могу. Я подчиняюсь Мэйсилу.",,"Üzgünüm, yapamam. Macil'in emirlerini uyguluyorum." -"Well which is it, bullets or training? I can't wait to get my hands on those new weapons we captured. A little bit of training and then a lot of revenge.",TXT_DLG_SCRIPT03_D36384_WELLW,〃 (two trainings),,,"Tak co to bude, náboje nebo trénink? Nemůžu se dočkat, až se dostanu k těm novým zbraním, které jsme zabavili. Trocha cvičení a pak hodně odplaty.","Nå, hvad er det, kugler eller træning? Jeg kan ikke vente med at få fingrene i de nye våben, vi har taget til fange. En lille smule træning og så en masse hævn.","Also, was willst du? Munition oder Training? Ich kann kaum erwarten, diese neuen Waffen, die wir erbeutet haben, in die Finger zu kriegen. ein bisschen Training und dann jede Menge Vergeltung.",,"Nu, ĉu kugloj aŭ trejnado ĉi-foje? Mi sopire atendas provi tiujn novajn kaptitajn armilojn. Iom da trejnado kaj tiam multe da venĝo.","Bueno, ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a poner mis manos en esas nuevas armas que hemos capturado. Un poco de entrenamiento y luego mucha venganza.","Bueno, ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a poner mis manos en esas nuevas armas que capturamos. Un poco de entrenamiento y luego mucha venganza.","No niin, kumpaa saisi olla: luoteja vai koulutusta? En voi malttaa olla tarttumasta vasta kaappaamiimme aseisiin. Hieman perehdytystä, ja sitten paljon kostamista.","Qu'est-ce qu'il vous faut? Des munitions ou de l'entraînement? J'ai hâte d'essayer ces nouvelles armes que l'on a capturé, un peu d'entraînement et beaucoup de vengeance.","Akkor döntsd el, lőszer vagy kiképzés? Már alig várom hogy rátegyem a kezem a lefoglalt fegyverekre. Egy kis kiképzés, és jó sok bosszú.","Bene, che cosa ti serve, munizioni o addestramento? Non vedo l'ora di mettere le mani su quelle nuove armi che abbiamo preso. Un pò di addestramento e poi molta vendetta.","弾薬と訓練、どっちの用件ですか? +Solo sigo órdenes de Macil.",,Valitettavasti en voi. Noudatan vain Macilin käskyjä.,"Désolé, pas possible. Je ne fais que suivre les ordres de Macil.","Sajnálom, de nem tehetem. Macil utasítása.","Mi spiace, ma non posso. Ordini dall'alto.",すまないが、できません。マシルの命令です。,미안합니다. 마실 사령관님의 명령을 따라야해요.,"Sorry, dat kan niet. Ik volg gewoon de orders van Macil op.","Beklager, jeg kan ikke. Jeg følger bare Macils ordre.","Przepraszam, ale nie mogę. Ja tylko wykonuję rozkazy Macila.",Desculpe mas não posso. Estou apenas seguindo as ordens de Macil.,,"Scuze, nu merge. Doar urmez ordinele lui Macil.","Увы, не могу. Я подчиняюсь Мэйсилу.",,"Tyvärr, jag kan inte. Jag följer bara Macils order.","Üzgünüm, yapamam. Macil'in emirlerini uyguluyorum." +"Well which is it, bullets or training? I can't wait to get my hands on those new weapons we captured. A little bit of training and then a lot of revenge.",TXT_DLG_SCRIPT03_D36384_WELLW,〃 (two trainings),,,"Tak co to bude, náboje nebo trénink? Nemůžu se dočkat, až se dostanu k těm novým zbraním, které jsme zabavili. Trocha cvičení a pak hodně odplaty.","Nå, hvad er det, kugler eller træning? Jeg kan ikke vente med at få fingrene i de nye våben, vi har taget til fange. En lille smule træning og så en masse hævn.","Also, was willst du? Munition oder Training? Ich kann kaum erwarten, diese neuen Waffen, die wir erbeutet haben, in die Finger zu kriegen. ein bisschen Training und dann jede Menge Vergeltung.",,"Nu, ĉu kugloj aŭ trejnado ĉi-foje? Mi sopire atendas provi tiujn novajn kaptitajn armilojn. Iom da trejnado kaj tiam multe da venĝo.","Bueno, ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a poner mis manos en esas nuevas armas que hemos capturado. Un poco de entrenamiento y luego mucha venganza.","Bueno, ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a poner mis manos en esas nuevas armas que capturamos. Un poco de entrenamiento y luego mucha venganza.","No niin, kumpaa saisi olla: luoteja vai koulutusta? En voi malttaa olla tarttumasta vasta kaappaamiimme aseisiin. Hieman perehdytystä, ja sitten paljon kostamista.","Qu'est-ce qu'il vous faut? Des munitions ou de l'entraînement? J'ai hâte d'essayer ces nouvelles armes que l'on a capturé, un peu d'entraînement et beaucoup de vengeance.","Akkor döntsd el, lőszer vagy kiképzés? Már alig várom hogy rátegyem a kezem a lefoglalt fegyverekre. Egy kis kiképzés, és jó sok bosszú.","Bene, che cosa ti serve, munizioni o addestramento? Non vedo l'ora di mettere le mani su quelle nuove armi che abbiamo preso. Un po' di addestramento e poi molta vendetta.","弾薬と訓練、どっちの用件ですか? 奪った新しい武器が届くのを待ち切れないです。 -少しの訓練でデカい復讐を。","무엇을 원하십니까? 보급? 아니면 훈련? 방금 전달된 새로운 무기들을 만지고 싶습니다! 아무튼, 훈련을 거치면 복수를 멋지게 해내실 거에요.","Wat is het dan wel, kogels of training? Ik kan niet wachten om die nieuwe wapens in handen te krijgen die we gevangen genomen hebben. Een beetje training en dan veel wraak.","Hva er det, kuler eller trening? Jeg gleder meg til å få tak i de nye våpnene vi tok. Litt trening, og så mye hevn.","Więc czego chcesz, naboje czy trening? Nie mogę się doczekać, aż dostanę jedną z tych nowych broni, które udało nam się przejąć. Trochę treningu, a potem zemsta.","Bem, o que vai ser? Munição ou treinamento? Mal posso esperar para pegar nessas novas armas que capturamos. Um pouquinho de treinamento e depois muita vingança.",,"Deci ce alegi, gloanțe sau antrenament? Abia aștept să pun mâna pe noile arme pe care le-am capturat. Puțin antrenament, iar apoi multă răzbunare.","Что скажешь, патроны или тренировка? Мне не терпится опробовать это новое трофейное оружие. Небольшая подготовка, и они за всё заплатят.",,"Hangisi, mermi mi eğitim mi? Yakaladığımız yeni silahları elime almak için sabırsızlanıyorum. Biraz eğitim ve sonra bolca intikam." -I'm out of ammo.,TXT_RPLY0_SCRIPT03_D36384_IMOUT,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for ammunition.,Ich habe keine Munition mehr.,,Mi estas sen municio.,No me queda munición.,,Minulta on panokset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 떨어졌어요.,Ik heb geen munitie meer.,Jeg er tom for ammunisjon.,Nie mam amunicji.,Estou sem munição.,,Nu mai am muniție.,У меня кончились боеприпасы.,,Cephanem bitti. +少しの訓練でデカい復讐を。","무엇을 원하십니까? 보급? 아니면 훈련? 방금 전달된 새로운 무기들을 만지고 싶습니다! 아무튼, 훈련을 거치면 복수를 멋지게 해내실 거에요.","Wat is het dan wel, kogels of training? Ik kan niet wachten om die nieuwe wapens in handen te krijgen die we gevangen genomen hebben. Een beetje training en dan veel wraak.","Hva er det, kuler eller trening? Jeg gleder meg til å få tak i de nye våpnene vi tok. Litt trening, og så mye hevn.","Więc czego chcesz, naboje czy trening? Nie mogę się doczekać, aż dostanę jedną z tych nowych broni, które udało nam się przejąć. Trochę treningu, a potem zemsta.","Bem, o que vai ser? Munição ou treinamento? Mal posso esperar para pegar nessas novas armas que capturamos. Um pouquinho de treinamento e depois muita vingança.",,"Deci ce alegi, gloanțe sau antrenament? Abia aștept să pun mâna pe noile arme pe care le-am capturat. Puțin antrenament, iar apoi multă răzbunare.","Что скажешь, патроны или тренировка? Мне не терпится опробовать это новое трофейное оружие. Небольшая подготовка, и они за всё заплатят.",,"Vad är det, kulor eller träning? Jag kan inte vänta på att få ta del av de nya vapnen som vi tog till fånga. Lite träning och sedan en massa hämnd.","Hangisi, mermi mi eğitim mi? Yakaladığımız yeni silahları elime almak için sabırsızlanıyorum. Biraz eğitim ve sonra bolca intikam." +I'm out of ammo.,TXT_RPLY0_SCRIPT03_D36384_IMOUT,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for ammunition.,Ich habe keine Munition mehr.,,Mi estas sen municio.,No me queda munición.,,Minulta on panokset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 떨어졌어요.,Ik heb geen munitie meer.,Jeg er tom for ammunisjon.,Nie mam amunicji.,Estou sem munição.,,Nu mai am muniție.,У меня кончились боеприпасы.,,Jag har slut på ammunition.,Cephanem bitti. Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D36384_HERES,〃 (〃),,,"Tady máš nějakou munici, neplýtvej s ní.",Her er noget ammunition til dig. Spild det ikke.,Hier hast du welche. Verschwende sie nicht.,,"Jen iom da municio. Ne malŝparu ĝin.","Aquí tienes algo de munición. -No la desperdicies.",,Tässä ammuksia. Älä tuhlaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van egy kis muníció számodra. Ne pazarold el.,Ecco un pò di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,여기 탄약입니다. 부디 열심히 싸우고 정확하게 쏘시길.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,İşte sana biraz cephane. Boşa harcama. -You've got enough ammo.,TXT_RNO0_SCRIPT03_D36384_YOUVE,〃 (〃),,,Vždyť jich máš dost.,Du har ammunition nok.,Du hast genug.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ma veramente ne hai a sufficienza.,弾は十分に見えます。,거짓말. 탄약을 충분히 가졌잖아요.,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz już wystarczająco dużo amunicji.,Você já tem munição o suficiente.,,Ai destulă muniție.,У тебя хватает патронов.,,Yeterince cephanen var. -Teach me.,TXT_RPLY1_SCRIPT03_D36384_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. +No la desperdicies.",,Tässä ammuksia. Älä tuhlaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van egy kis muníció számodra. Ne pazarold el.,Ecco un po' di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,여기 탄약입니다. 부디 열심히 싸우고 정확하게 쏘시길.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,Här är lite ammunition till dig. Slösa inte bort den.,İşte sana biraz cephane. Boşa harcama. +You've got enough ammo.,TXT_RNO0_SCRIPT03_D36384_YOUVE,〃 (〃),,,Vždyť jich máš dost.,Du har ammunition nok.,Du hast genug.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ma veramente ne hai a sufficienza.,弾は十分に見えます。,거짓말. 탄약을 충분히 가졌잖아요.,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz już wystarczająco dużo amunicji.,Você já tem munição o suficiente.,,Ai destulă muniție.,У тебя хватает патронов.,,Du har tillräckligt med ammunition.,Yeterince cephanen var. +Teach me.,TXT_RPLY1_SCRIPT03_D36384_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. O.K. Take what you've learned here and show those Order clods the way to hell.,TXT_RYES1_SCRIPT03_D36384_OKTAK,〃 (〃),,,"Oukej. Pamatuj, co ses tady naučil, a ukaž těm hajzlům z Řádu kudy do pekla.","O.K. Tag det, du har lært her, og vis de ordensklodser vejen til helvede.","OK. Nutze, was du hier gelernt hast um diesen Tölpeln vom Orden den Weg in die Hölle zu zeigen.",,"Bone. Uzu ĉi tion por gvidi tiujn -aĉulojn de La Ordono al la infero.","Bien. Usa lo aprendido para guiar a esos +aĉulojn de La Ordeno al la infero.","Bien. Usa lo aprendido para guiar a esos majaderos de La Orden al infierno.","Bien. Usa lo aprendido para guiar a esos desgraciados de La Orden al infierno.","OK. Hyödynnä täällä oppimaasi, ja näytä niille Veljeskunnan valopäille tie helvettiin.",OK. Utilisez ce que vous avez appris et envoyez ces abrutis de l'Ordre en enfer.,Akkor rendben is vagyunk. Mutasd meg a Rend barmainak hol lakik az isten.,O.K. Usa ciò che hai imparato qua per mostrare all'Ordine la via dell'Inferno.,"オーケー、ここで学んだ事を生かして -オーダー共を地獄に送って上げなさい。",좋아요! 훈련을 통해서 얻은 실력으로 저 오더 돌대가리들을 박살을 내버려요!,"Oké, neem wat je hier geleerd hebt en laat die Ordekluiten de weg naar de hel zien.","OK. Ta det du har lært her, og vis de ordenstullingene veien til helvete.",Ok. Bierz to czego się nauczyłeś i pokaż tym durniom z Zakonu drogę do piekła.,Ok. Use o que você aprendeu aqui para mostrar o caminho pro inferno a esses desgraçados da Ordem.,,În regulă. Folosește ce ai învățat aici si aratăle nătărăilor din Ordin calea spre infern.,"Запоминай внимательно, покажешь этим прихвостням Ордена быструю дорогу в ад.",,Tamam. Burada öğrendiklerini al ve o tarikatçılara cehenneme giden yolu göster. +オーダー共を地獄に送って上げなさい。",좋아요! 훈련을 통해서 얻은 실력으로 저 오더 돌대가리들을 박살을 내버려요!,"Oké, neem wat je hier geleerd hebt en laat die Ordekluiten de weg naar de hel zien.","OK. Ta det du har lært her, og vis de ordenstullingene veien til helvete.",Ok. Bierz to czego się nauczyłeś i pokaż tym durniom z Zakonu drogę do piekła.,Ok. Use o que você aprendeu aqui para mostrar o caminho pro inferno a esses desgraçados da Ordem.,,În regulă. Folosește ce ai învățat aici si aratăle nătărăilor din Ordin calea spre infern.,"Запоминай внимательно, покажешь этим прихвостням Ордена быструю дорогу в ад.",,O.K. Ta det du lärt dig här och visa de där ordenskloddarna vägen till helvetet.,Tamam. Burada öğrendiklerini al ve o tarikatçılara cehenneme giden yolu göster. "Come back later, when Macil says it's time.",TXT_RNO1_SCRIPT03_D36384_COMEB,〃 (〃),,,"Přijď někdy jindy, až řekne Macil.","Kom tilbage senere, når Macil siger, det er tid.","Komm wieder, wenn Macil dir Bescheid gibt.",,"Revenu post kiam Macil ordonis tion.","Vuelve más tarde cuando -Macil diga que ya es la hora.",,"Palaa asiaan myöhemmin, kun Macil näyttää vihreää valoa.",Revenez plus tard quand Macil décide qu'il est temps.,"Gyere vissza akkor, ha azt mondja Macil hogy ideje van.","Ritorna più tardi, quando Macil dirà che è il momento.",マシルの命令を受けてから、また来なさい。,사령관님은 인내심이 많은 분입니다. 나중에 확인해주시길.,"Kom later terug, als Macil zegt dat het tijd is.","Kom tilbake senere, når Macil sier det er på tide.","Przyjdź później, kiedy Macil powie, że już czas.","Volte mais tarde, quando Macil disser que está na hora.",,"Revin-o mai târziu, când Macil spune că e timpul.","Приходи позже, когда прикажет Мэйсил.",,Macil zamanı geldiğini söylediğinde geri gel. -I've taught you everything I can right now. Give me some time to put the new weapons through their paces. That is unless you're out of bullets.,TXT_DLG_SCRIPT03_D37900_IVETA,〃 (three trainings),,,"Naučil jsem tě vše, co teď můžu. Dej mi nějaký čas, abych vyzkoušel ty nové zbraně. Jedině, že bys potřeboval náboje.","Jeg har lært dig alt, hvad jeg kan lige nu. Giv mig lidt tid til at sætte de nye våben på prøve. Medmindre du er løbet tør for kugler.","Ich habe dir alles gezeigt, was ich momentan kann. Gib mir etwas Zeit um die neuen Waffen zu testen. Munition kriegst du natürlich auch so.",,"Mi instruis al vi ĉion, kion mi povas. Donu tempon al mi por elprovi la novajn armilojn... krom se vi nur bezonas pliajn kuglojn.","Te he enseñado todo lo que puedo por ahora. Dame tiempo para probar al 100% las nuevas armas... a menos que solo necesites más balas, claro.","Ya te enseñé todo lo que puedo por ahora. Dame tiempo para probar al 100% las nuevas armas... a menos que solo necesites más balas, claro.","Olen opettanut sinulle kaiken, mitä itse juuri nyt osaan. Anna minulle vähän aikaa käydä läpi uusien aseiden askelkuvioita. Ellei sinulla sitten ole luodit lopussa.","Je vous ai enseigné tout ce que je sais. Laissez moi un peu de temps pour tester ces nouvelles armes. Sauf si vous n'avez plus de munitions, bien sûr.","Megtanítottam mindent amit jelenleg tudtam. Adj egy kis időt, hogy leteszteljem a fegyvereket. Kivétel persze ha lőszer kell.",Ti ho insegnato tutto quello che potevo per ora. Dammi dell'altro tempo per mettere le nuove armi alla prova. A meno che non ti servano altre munizioni.,"私が教えられる事はもうありません。 +Macil diga que ya es la hora.",,"Palaa asiaan myöhemmin, kun Macil näyttää vihreää valoa.",Revenez plus tard quand Macil décide qu'il est temps.,"Gyere vissza akkor, ha azt mondja Macil hogy ideje van.","Ritorna più tardi, quando Macil dirà che è il momento.",マシルの命令を受けてから、また来なさい。,사령관님은 인내심이 많은 분입니다. 나중에 확인해주시길.,"Kom later terug, als Macil zegt dat het tijd is.","Kom tilbake senere, når Macil sier det er på tide.","Przyjdź później, kiedy Macil powie, że już czas.","Volte mais tarde, quando Macil disser que está na hora.",,"Revin-o mai târziu, când Macil spune că e timpul.","Приходи позже, когда прикажет Мэйсил.",,"Kom tillbaka senare, när Macil säger att det är dags.",Macil zamanı geldiğini söylediğinde geri gel. +I've taught you everything I can right now. Give me some time to put the new weapons through their paces. That is unless you're out of bullets.,TXT_DLG_SCRIPT03_D37900_IVETA,〃 (three trainings),,,"Naučil jsem tě vše, co teď můžu. Dej mi nějaký čas, abych vyzkoušel ty nové zbraně. Jedině, že bys potřeboval náboje.","Jeg har lært dig alt, hvad jeg kan lige nu. Giv mig lidt tid til at sætte de nye våben på prøve. Medmindre du er løbet tør for kugler.","Ich habe dir alles gezeigt, was ich momentan kann. Gib mir etwas Zeit um die neuen Waffen zu testen. Munition kriegst du natürlich auch so.",,"Mi instruis al vi ĉion, kion mi ĉi-momente povas. Donu tempon al mi por elprovi la novajn armilojn... krom se vi nur bezonas pliajn kuglojn.","Te he enseñado todo lo que puedo por ahora. Dame tiempo para probar al 100% las nuevas armas... a menos que solo necesites más balas, claro.","Ya te enseñé todo lo que puedo por ahora. Dame tiempo para probar al 100% las nuevas armas... a menos que solo necesites más balas, claro.","Olen opettanut sinulle kaiken, mitä itse juuri nyt osaan. Anna minulle vähän aikaa käydä läpi uusien aseiden askelkuvioita. Ellei sinulla sitten ole luodit lopussa.","Je vous ai enseigné tout ce que je sais. Laissez moi un peu de temps pour tester ces nouvelles armes. Sauf si vous n'avez plus de munitions, bien sûr.","Megtanítottam mindent amit jelenleg tudtam. Adj egy kis időt, hogy leteszteljem a fegyvereket. Kivétel persze ha lőszer kell.",Ti ho insegnato tutto quello che potevo per ora. Dammi dell'altro tempo per mettere le nuove armi alla prova. A meno che non ti servano altre munizioni.,"私が教えられる事はもうありません。 今後新しい武器は時間が掛かるが自分のペースで -学びなさい。弾切れでなければの話ですが。",제가 제공할 수 있을 만큼의 훈련을 배우셨습니다. 부디 무기를 다룰 시간을 주세요. 보급 때문에 찾아오신 게 아니라면 말이죠.,Ik heb je alles geleerd wat ik nu kan. Geef me wat tijd om de nieuwe wapens op de proef te stellen. Tenzij je geen kogels meer hebt.,Jeg har lært deg alt jeg kan nå. Gi meg litt tid til å teste de nye våpnene. Med mindre du er tom for kuler.,"Nauczyłem cię wszystkiego co mogę na chwilę obecną. Daj mi trochę czasu, aby przetestować nowe bronie. No chyba, że brakuje ci nabojów.",Já te ensinei tudo o que pude. Me dê um tempo para eu testar as novas armas. A não ser que você esteja sem munição.,,Te-am învățat tot ce stiu. Dă-mi niște timp să pun noile arme la treabă. Asta dacă nu ai rămas fără gloanțe.,Пока что я не могу научить тебя ничему новому. Дай мне время разобраться в этом новом оружии. Или у тебя закончились патроны?,,Şu anda sana öğretebileceğim her şeyi öğrettim. Yeni silahları denemem için bana biraz zaman ver. Tabii mermin bitmediyse. -Yes I am.,TXT_RPLY0_SCRIPT03_D37900_YESIA,〃 (〃),,,"Ano, potřebuju.","Ja, det er jeg.","Ja, bin ich.",,Ĝuste.,Eso mismo.,,Kyllä on.,"En effet, je le suis.","Igen, az vagyok.",Sì che mi servono.,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.","Ja, det er jeg.",Zgadza się.,"Sim, estou.",,"Da, am rămas fără.","Да, закончились.",,"Evet, bitti." -Here you go.,TXT_RYES0_SCRIPT03_D37900_HEREY,〃 (〃),,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Ecco qua.,どうぞ。,여기 있어요!,Alsjeblieft.,Vær så god.,Masz.,Aqui está.,,Iată.,Держи.,,Al bakalım. +学びなさい。弾切れでなければの話ですが。",제가 제공할 수 있을 만큼의 훈련을 배우셨습니다. 부디 무기를 다룰 시간을 주세요. 보급 때문에 찾아오신 게 아니라면 말이죠.,Ik heb je alles geleerd wat ik nu kan. Geef me wat tijd om de nieuwe wapens op de proef te stellen. Tenzij je geen kogels meer hebt.,Jeg har lært deg alt jeg kan nå. Gi meg litt tid til å teste de nye våpnene. Med mindre du er tom for kuler.,"Nauczyłem cię wszystkiego co mogę na chwilę obecną. Daj mi trochę czasu, aby przetestować nowe bronie. No chyba, że brakuje ci nabojów.",Já te ensinei tudo o que pude. Me dê um tempo para eu testar as novas armas. A não ser que você esteja sem munição.,,Te-am învățat tot ce stiu. Dă-mi niște timp să pun noile arme la treabă. Asta dacă nu ai rămas fără gloanțe.,Пока что я не могу научить тебя ничему новому. Дай мне время разобраться в этом новом оружии. Или у тебя закончились патроны?,,Jag har lärt dig allt jag kan just nu. Ge mig lite tid att sätta de nya vapnen på prov. Det vill säga om du inte har slut på kulor.,Şu anda sana öğretebileceğim her şeyi öğrettim. Yeni silahları denemem için bana biraz zaman ver. Tabii mermin bitmediyse. +Yes I am.,TXT_RPLY0_SCRIPT03_D37900_YESIA,〃 (〃),,,"Ano, potřebuju.","Ja, det er jeg.","Ja, bin ich.",,Ĝuste.,Eso mismo.,,Kyllä on.,"En effet, je le suis.","Igen, az vagyok.",Sì che mi servono.,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.","Ja, det er jeg.",Zgadza się.,"Sim, estou.",,"Da, am rămas fără.","Да, закончились.",,"Ja, det är jag.","Evet, bitti." +Here you go.,TXT_RYES0_SCRIPT03_D37900_HEREY,〃 (〃),,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Toma.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Ecco qua.,どうぞ。,여기 있어요!,Alsjeblieft.,Vær så god.,Masz.,Aqui está.,,Iată.,Держи.,,Här har du.,Al bakalım. Don't get trigger happy in the town. You'll set off the alarm and they'll start sending in guards from the castle. ,TXT_DLG_SCRIPT03_D39416_DONTG,MAP03: Upstairs.,,,Ať tě nenapadne střílet ve městě. Spustil bys poplach a přivolal stráže z hradu.,"Bliv ikke skydeglad i byen. Du vil udløse alarmen, og de vil sende vagter fra slottet.","Fang nicht an, hier in der Stadt herumzuballern. Wenn du hier den Alarm auslöst, senden sie gleich die Truppen aus der Burg.",,Ne uzu pafilon en la urbo; vi ekagigus la alarmon kaj ili eksendus gardistojn el la kastelo.,"No te líes a tiros en el pueblo, que activarás la alarma y empezarán a enviar guardias desde el castillo.","No andes a los tiros en el pueblo, que vas a activar la alarma y van a empezar a mandar guardias desde el castillo.","Älä ala turhan liipaisinherkäksi kaupungilla. Aiheutat vielä hälytyksen, ja ne alkavat lähettää linnasta vartijoita.",Ne tirez pas partout en ville. Vous risquez de déclencher l'alarme et ils enverront tous les gardes du château à vos trousses.,"Ne keresd a bajt a városban. Beindítod a riasztót, és kiküldik érted a kastély őröket.",Non ti consiglio di avere il grilletto facile in città. Finiresti per attivare l'allarme e inizierebbero a mandare guardie dal castello.,"街の中で銃をバンバン撃ったりするんじゃないぞ 警報を鳴らしてしまえば、奴等が衛兵共を -城から送り込んでくるぞ。","아무 마을에서나 총을 갈겨대지 마세요. 알람을 울릴 거고, 성안에 있는 병력을 다 끄집어내서라도 당신을 잡을 테니까요.",Laat de trekker niet gelukkig worden in de stad. Je laat het alarm afgaan en ze sturen bewakers van het kasteel naar binnen.,"Ikke bli skyteglad i byen. Du utløser alarmen, og de vil sende inn vakter fra slottet.",Nie bądź taki impulsywny na mieście. Włączysz alarm i zaczną po ciebie wysyłać straże z zamku.,Não fique atirando por toda parte na cidade. Você vai ativar o alarme e eles mandarão os guardas do castelo.,,Nu deveni încântat să apeși pe trăgaci în oraș. Vor declanșa alarma și vor trimite gardieni din castel.,"Когда будешь в городе, не стреляй направо и налево. Если ты поднимешь тревогу, они вызовут подкрепление из замка.",,Kasabada tetiğe basma. Alarmı çalıştırırsın ve kaleden muhafızlar göndermeye başlarlar. -"Welcome, we can always use more help.",TXT_DLG_SCRIPT03_D40932_WELCO,MAP03: Near Macil.,,,"Vítej, pomoc se nám vždycky hodí.","Velkommen, vi kan altid bruge mere hjælp.","Willkommen, wir können immer etwas Hilfe gebrauchen.",,Bonvenon. Plia helpo ĉiam estas utilega.,"Bienvenido, siempre nos viene bien algo más de ayuda.",,Tervetuloa; voisimme aina kaivata lisää apua.,Bienvenue. Nous apprécions toute l'aide que nous pouvons recevoir.,"Üdv nálunk, mindig jól jön a segítség.","Benvenuto, ci serve tutto l'aiuto che possiamo ottenere.",ようこそ、我々が貴方の助けに成ります。,환영합니다. 당신 같은 사람들이 더 있었더라면...,"Welkom, we kunnen altijd meer hulp gebruiken.","Velkommen, vi kan alltid trenge mer hjelp.","Witaj, każda pomoc się przyda.",Seja bem-vindo. Qualquer ajuda é sempre bem-vinda.,,"Bun venit, mereu putem primi o mână de ajutor.",Добро пожаловать. Нам всегда пригодится помощь.,,"Hoş geldiniz, her zaman daha fazla yardıma ihtiyacımız olabilir." +城から送り込んでくるぞ。","아무 마을에서나 총을 갈겨대지 마세요. 알람을 울릴 거고, 성안에 있는 병력을 다 끄집어내서라도 당신을 잡을 테니까요.",Laat de trekker niet gelukkig worden in de stad. Je laat het alarm afgaan en ze sturen bewakers van het kasteel naar binnen.,"Ikke bli skyteglad i byen. Du utløser alarmen, og de vil sende inn vakter fra slottet.",Nie bądź taki impulsywny na mieście. Włączysz alarm i zaczną po ciebie wysyłać straże z zamku.,Não fique atirando por toda parte na cidade. Você vai ativar o alarme e eles mandarão os guardas do castelo.,,Nu deveni încântat să apeși pe trăgaci în oraș. Vor declanșa alarma și vor trimite gardieni din castel.,"Когда будешь в городе, не стреляй направо и налево. Если ты поднимешь тревогу, они вызовут подкрепление из замка.",,Bli inte skjutglad i stan. Du kommer att utlösa larmet och de kommer att skicka in vakter från slottet.,Kasabada tetiğe basma. Alarmı çalıştırırsın ve kaleden muhafızlar göndermeye başlarlar. +"Welcome, we can always use more help.",TXT_DLG_SCRIPT03_D40932_WELCO,MAP03: Near Macil.,,,"Vítej, pomoc se nám vždycky hodí.","Velkommen, vi kan altid bruge mere hjælp.","Willkommen, wir können immer etwas Hilfe gebrauchen.",,Bonvenon. Plia helpo ĉiam estas utilega.,"Bienvenido, siempre nos viene bien algo más de ayuda.",,Tervetuloa; voisimme aina kaivata lisää apua.,Bienvenue. Nous apprécions toute l'aide que nous pouvons recevoir.,"Üdv nálunk, mindig jól jön a segítség.","Benvenuto, ci serve tutto l'aiuto che possiamo ottenere.",ようこそ、我々が貴方の助けに成ります。,환영합니다. 당신 같은 사람들이 더 있었더라면...,"Welkom, we kunnen altijd meer hulp gebruiken.","Velkommen, vi kan alltid trenge mer hjelp.","Witaj, każda pomoc się przyda.",Seja bem-vindo. Qualquer ajuda é sempre bem-vinda.,,"Bun venit, mereu putem primi o mână de ajutor.",Добро пожаловать. Нам всегда пригодится помощь.,,"Välkommen, vi kan alltid behöva mer hjälp.","Hoş geldiniz, her zaman daha fazla yardıma ihtiyacımız olabilir." "When I was still in action we had the chance to examine an acolyte before the reinforcements arrived. Listen, they're not human.",TXT_DLG_SCRIPT03_D42448_WHENI,〃,,,"Když jsem byl ještě v akci, měli jsme možnost prozkoumat mrtvého akolytu předtím, než přišly posily. Poslyš, nejsou to lidé.","Da jeg stadig var i aktion, havde vi mulighed for at undersøge en akolyt, inden forstærkningerne ankom. Hør, de er ikke menneskelige.","Als ich noch aktiv war, hatten wir mal die Möglichkeit, einen der Ministranten zu untersuchen, bevor Verstärkung eintraf. Hör zu, sie sind nicht menschlich!",,"Kiam mi ankoraŭ estis en misio, ni havis okazon ekzameni akoliton antaŭ ol pliaj malamikoj alvenis. Aŭskultu, ili ne estas homoj.","Cuando aún estaba en acción tuvimos la oportunidad de examinar a un acólito antes de que llegaran los refuerzos. Escucha, no son humanos.",,"Kun itse olin vielä mukana taistelemassa, saimme tilaisuuden tutkia akoluuttia ennen lisäjoukkojen saapumista. Ja kuule tarkkaan, ne eivät ole ihmisiä.","Quand j'étais encore en service, j'ai eu l'opportunité d'examiner un acolyte avant que les renforts n'arrivent. Vous savez, ils ne sont pas humains.","A harc után volt alkalmunk megvizsgálni egy oltárszolgát még mielőtt megjelent volna az erősítés. Esküszöm, hogy ezek nem emberek.","Quando ero ancora sul campo di battaglia, abbiamo avuto l'occasione di esaminare uno degli accoliti prima che arrivassero i rinforzi. Ascoltami, non sono umani.","私がまだ活動していた時、我々が増援に 囲まれる前にアコライトを調べる機会が あったんだ。聞いてくれ、奴等は人間では -なかったんだ。","제가 임무 수행 중이었을 때, 생포한 아콜라이트들을 조사한 적이 있었어요. 요점은, 그 들은 인간이 절대로 아닙니다.","Toen ik nog in actie was hadden we de kans om een acoliet te onderzoeken voordat de versterkingen kwamen. Luister, ze zijn niet menselijk.","Da jeg fortsatt var i tjeneste, fikk vi sjansen til å undersøke en akolytt før forsterkningene kom. Hør her, de er ikke mennesker.","Kiedy byłem jeszcze na chodzie, mieliśmy szansę się przyjrzeć akolitom zanim wezwano posiłki. Słuchaj, to nie są ludzie.","Quando eu estava na ativa, tivemos a oportunidade de examinar um acólito antes dos reforços chegarem. Ouça bem, eles não são humanos.",,"Când încă eram în acțiune am avut șansa de a examina un acolit până să apară întăririle. Ascultă, nu sunt oameni.","Пока я был в оперативной группе, нам удалось изучить одного из служителей, прежде чем прибыло подкрепление. Так вот, они не люди.",,"Ben hala görevdeyken, takviye birlikler gelmeden önce bir yardımcı inceleme şansımız oldu. Dinle, onlar insan değil." -"We're trying to find where the castle gate mechanisms are, but so far we've had no luck.",TXT_DLG_SCRIPT03_D43964_WERET,MAP03: Downstairs.,,,"Snažíme se zjistit, kde jsou mechanismy hradní brány, ale zatím jsme nic nenašli.","Vi prøver at finde ud af hvor slottets portmekanismer er, men indtil videre har vi ikke haft held.","Wir versuchen herauszufinden, von wo das Burgtor kontrolliert wird, aber bisher hatten wir kein Glück.",,"Ni provas malkovri, kie troviĝas la mekanismoj de la kastelpordo, sed ni ankoraŭ ne sukcesis.","Estamos intentando descubrir la ubicación de los mecanismos de la puerta del castillo, pero de momento no ha habido suerte.","Estamos tratando de descubrir la ubicación de los mecanismos de la puerta del castillo, pero por ahora no hubo suerte.","Yritämme löytää linnanportin koneistoa, mutta toistaiseksi laihoin tuloksin.","On essaie de trouver où se trouvent les contrôles de la porte du château, mais pour l'instant, on les a pas encore localisés.","Próbáljuk megtalálni a kastély kapu irányító mechanikáját, de eddig nem jártunk sikerrel.","Stiamo cercando di capire dove si trovano i meccanismi di apertura dell'entrata del castello, ma ancora niente.","我々は城門のメカニズムが何処にあるか -探し続けているが、あまり良い結果は出ていない","성의 정문이 어떻게 작동하는지, 어떻게 하면 열 수 있는지 연구를 했습니다만... 아직은 희망이 없어요.","We proberen te vinden waar de mechanismen van de kasteelpoort zich bevinden, maar tot nu toe hebben we geen geluk gehad.","Vi prøver å finne ut hvor slottets portmekanismer er, men så langt har vi ikke hatt noe hell.","Próbowaliśmy znaleźć mechanizm bramy zamku, ale nam się nie udało.","Estamos tentando localizar os mecanismos do portão do castelo, mas até agora não tivemos sorte.",,"Încercăm să găsim mecanismele castelului, dar până acum nu am avut noroc.","Мы ищем механизм управления воротами замка, но пока безуспешно.",,Kalenin kapı mekanizmalarının nerede olduğunu bulmaya çalışıyoruz ama şu ana kadar şansımız yaver gitmedi. -Don't get caught. I've heard horror stories about what they do to our people after they're imprisoned. They just disappear... Without a trace.,TXT_DLG_SCRIPT03_D45480_DONTG,〃,,,"Nenech se chytit. Slyšel jsem děsivé příběhy o tom, co dělají našim lidem, když je uvězní. Prostě zmizí... beze stopy.","Bliv ikke fanget. Jeg har hørt skrækhistorier om, hvad de gør ved vores folk, når de er blevet fængslet. De forsvinder bare... Uden et spor.","Lass dich nicht erwischen. Ich habe Horrorgeschichten darüber gehört, was sie unseren Leuten antun, die sie gefangengenommen haben. Sie verschwinden einfach... ohne jede Spur.",,"Oni ne kaptu vin. Mi aŭdis terurajn historiojn pri tio, kio okazas al niaj homoj post ilia aresto: ili simple malaperas sen lasi nenian restaĵon.",Que no te atrapen. He oído historias terroríficas de lo que hacen con nuestros hombres una vez detenidos: simplemente desaparecen sin dejar rastro alguno.,,"Älä jää kiinni. Olen kuullut kauhukertomuksia siitä, mitä ne tekevät meidän omillemme, kun he jäävät vangiksi. He yksinkertaisesti katoavat, jälkeä jättämättä.",Ne vous faites pas avoir. J'ai entendu des choses horribles sur ce qu'ils font à ceux qu'ils emprisonnent. Ils disparaîssent... Sans laisser de trace.,Csak ne fogasd el magad. Hallottam horror történténeteket azokról akiket mégis elfognak. Csak úgy eltünnek...mindenféle nyom nélkül.,Non farti prendere. Ho sentito storie orribili su quello che fanno alle persone dopo che le catturano. Spariscono... senza traccia.,"決して捕まるな。投獄されると奴等が +なかったんだ。","제가 임무 수행 중이었을 때, 생포한 아콜라이트들을 조사한 적이 있었어요. 요점은, 그 들은 인간이 절대로 아닙니다.","Toen ik nog in actie was hadden we de kans om een acoliet te onderzoeken voordat de versterkingen kwamen. Luister, ze zijn niet menselijk.","Da jeg fortsatt var i tjeneste, fikk vi sjansen til å undersøke en akolytt før forsterkningene kom. Hør her, de er ikke mennesker.","Kiedy byłem jeszcze na chodzie, mieliśmy szansę się przyjrzeć akolitom zanim wezwano posiłki. Słuchaj, to nie są ludzie.","Quando eu estava na ativa, tivemos a oportunidade de examinar um acólito antes dos reforços chegarem. Ouça bem, eles não são humanos.",,"Când încă eram în acțiune am avut șansa de a examina un acolit până să apară întăririle. Ascultă, nu sunt oameni.","Пока я был в оперативной группе, нам удалось изучить одного из служителей, прежде чем прибыло подкрепление. Так вот, они не люди.",,"När jag fortfarande var i aktion hade vi chansen att undersöka en akolyt innan förstärkningarna kom. Lyssna, de är inte mänskliga.","Ben hala görevdeyken, takviye birlikler gelmeden önce bir yardımcı inceleme şansımız oldu. Dinle, onlar insan değil." +"We're trying to find where the castle gate mechanisms are, but so far we've had no luck.",TXT_DLG_SCRIPT03_D43964_WERET,MAP03: Downstairs.,,,"Snažíme se zjistit, kde jsou mechanismy hradní brány, ale zatím jsme nic nenašli.","Vi prøver at finde ud af hvor slottets portmekanismer er, men indtil videre har vi ikke haft held.","Wir versuchen herauszufinden, von wo das Burgtor kontrolliert wird, aber bisher hatten wir kein Glück.",,"Ni provas malkovri, kie troviĝas la mekanismoj de la pordo de la kastelo, sed ni ankoraŭ ne sukcesis.","Estamos intentando descubrir la ubicación de los mecanismos de la puerta del castillo, pero de momento no ha habido suerte.","Estamos tratando de descubrir la ubicación de los mecanismos de la puerta del castillo, pero por ahora no hubo suerte.","Yritämme löytää linnanportin koneistoa, mutta toistaiseksi laihoin tuloksin.","On essaie de trouver où se trouvent les contrôles de la porte du château, mais pour l'instant, on les a pas encore localisés.","Próbáljuk megtalálni a kastély kapu irányító mechanikáját, de eddig nem jártunk sikerrel.","Stiamo cercando di capire dove si trovano i meccanismi di apertura dell'entrata del castello, ma ancora niente.","我々は城門のメカニズムが何処にあるか +探し続けているが、あまり良い結果は出ていない","성의 정문이 어떻게 작동하는지, 어떻게 하면 열 수 있는지 연구를 했습니다만... 아직은 희망이 없어요.","We proberen te vinden waar de mechanismen van de kasteelpoort zich bevinden, maar tot nu toe hebben we geen geluk gehad.","Vi prøver å finne ut hvor slottets portmekanismer er, men så langt har vi ikke hatt noe hell.","Próbowaliśmy znaleźć mechanizm bramy zamku, ale nam się nie udało.","Estamos tentando localizar os mecanismos do portão do castelo, mas até agora não tivemos sorte.",,"Încercăm să găsim mecanismele castelului, dar până acum nu am avut noroc.","Мы ищем механизм управления воротами замка, но пока безуспешно.",,"Vi försöker ta reda på var slottets portmekanismer finns, men hittills har vi inte haft någon tur.",Kalenin kapı mekanizmalarının nerede olduğunu bulmaya çalışıyoruz ama şu ana kadar şansımız yaver gitmedi. +Don't get caught. I've heard horror stories about what they do to our people after they're imprisoned. They just disappear... Without a trace.,TXT_DLG_SCRIPT03_D45480_DONTG,〃,,,"Nenech se chytit. Slyšel jsem děsivé příběhy o tom, co dělají našim lidem, když je uvězní. Prostě zmizí... beze stopy.","Bliv ikke fanget. Jeg har hørt skrækhistorier om, hvad de gør ved vores folk, når de er blevet fængslet. De forsvinder bare... Uden et spor.","Lass dich nicht erwischen. Ich habe Horrorgeschichten darüber gehört, was sie unseren Leuten antun, die sie gefangengenommen haben. Sie verschwinden einfach... ohne jede Spur.",,"Oni ne kaptu vin. Mi aŭdis terurajn historiojn pri tio, kio okazas al niaj homoj post ilia aresto: ili simple malaperas, lasinte nenian restaĵon.",Que no te atrapen. He oído historias terroríficas de lo que hacen con nuestros hombres una vez detenidos: simplemente desaparecen sin dejar rastro alguno.,,"Älä jää kiinni. Olen kuullut kauhukertomuksia siitä, mitä ne tekevät meidän omillemme, kun he jäävät vangiksi. He yksinkertaisesti katoavat, jälkeä jättämättä.",Ne vous faites pas avoir. J'ai entendu des choses horribles sur ce qu'ils font à ceux qu'ils emprisonnent. Ils disparaîssent... Sans laisser de trace.,Csak ne fogasd el magad. Hallottam horror történténeteket azokról akiket mégis elfognak. Csak úgy eltünnek...mindenféle nyom nélkül.,Non farti prendere. Ho sentito storie orribili su quello che fanno alle persone dopo che le catturano. Spariscono... senza traccia.,"決して捕まるな。投獄されると奴等が 何をしでかすか怪談として聞く程だ。 -跡形もなく...消される。",절대로 붙잡히지 마세요. 그 녀석들이 수감된 사람들에게 한 일에 대한 무서운 이야기를 들었어요. 흔적도 없이 그냥 사라져 버린 겁니다.,Laat je niet vangen. Ik heb horrorverhalen gehoord over wat ze onze mensen na hun gevangenschap aandoen. Ze verdwijnen gewoon.... Zonder een spoor.,Ikke bli tatt. Jeg har hørt skrekkhistorier om hva de gjør med folket vårt etter at de blir fengslet. De bare forsvinner... Sporløst.,"Nie daj się złapać. Słyszałem straszne historie co robią naszym ludziom, kiedy ich złapią. Oni po prostu znikają... Bez śladu.",Não deixe eles te pegarem. Ouvi histórias de terror sobre o que eles fazem com o nosso pessoal depois que são aprisionados. Eles desaparecem... sem deixar rastros.,,Să nu te prindă. Am auzit povești de groază despre ce le fac oamenilor în închisoare. Dispar pur și simplu... fără nicio urmă.,"Не дай себя схватить. Я слышал ужасные истории о том, что они делают с арестованными. Те просто исчезают... без следа.",,Sakın yakalanmayın. Hapsedildikten sonra insanlarımıza ne yaptıklarına dair korku hikayeleri duydum. Öylece ortadan kayboluyorlar. İz bırakmadan. -"Here's some advice, if you ever see any of the Order's Tinsoldiers go in the other direction. They're fast and brutal.",TXT_DLG_SCRIPT03_D46996_HERES,〃,,,"Dám ti radu: Jestli někdy uvidíš jednoho z plecháčků Řádu, otoč se a utíkej. Jsou rychlí a suroví.",Her er et godt råd: Hvis du nogensinde ser nogen af Ordenens Tinsoldater gå i den anden retning. De er hurtige og brutale.,"Hier ist ein guter Rat, falls du jemals einen dieser Zinnsoldaten des Ordens vorbeigehen siehst. Sie sind schnell und brutal. ",,Jen konsilo: estu ĉiam fore de la artefaritaj soldatoj de La Ordono. Ili estas rapidaj kaj brutalaj.,Un consejo: mantente siempre alejado de los soldados artificiales de La Orden. Son rápidos y brutales.,,"Annan pienen vinkin: Jos koskaan näet Veljeskunnan tinasotilaita, mene toiseen suuntaan. Ne ovat nopeita ja raakoja.","Voilà un conseil. Si vous voyez un des soldats mécanisés de l'Ordre, retournez vous et courez. Ils sont rapides et brutaux.","Az a tanácsom számodra, hogy ha meglátod a Rend ólomkatonáit, vedd az utad az ellentétes irányba. Gyorsak és brutálisak.","Ecco un consiglio. Se vedi uno dei soldatini di latta dell'Ordine, vai nella direzione opposta. Sono veloci e brutali.","伝えておく、オーダーの錫兵は +跡形もなく...消される。",절대로 붙잡히지 마세요. 그 녀석들이 수감된 사람들에게 한 일에 대한 무서운 이야기를 들었어요. 흔적도 없이 그냥 사라져 버린 겁니다.,Laat je niet vangen. Ik heb horrorverhalen gehoord over wat ze onze mensen na hun gevangenschap aandoen. Ze verdwijnen gewoon.... Zonder een spoor.,Ikke bli tatt. Jeg har hørt skrekkhistorier om hva de gjør med folket vårt etter at de blir fengslet. De bare forsvinner... Sporløst.,"Nie daj się złapać. Słyszałem straszne historie co robią naszym ludziom, kiedy ich złapią. Oni po prostu znikają... Bez śladu.",Não deixe eles te pegarem. Ouvi histórias de terror sobre o que eles fazem com o nosso pessoal depois que são aprisionados. Eles desaparecem... sem deixar rastros.,,Să nu te prindă. Am auzit povești de groază despre ce le fac oamenilor în închisoare. Dispar pur și simplu... fără nicio urmă.,"Не дай себя схватить. Я слышал ужасные истории о том, что они делают с арестованными. Те просто исчезают... без следа.",,Bli inte fångade. Jag har hört skräckhistorier om vad de gör med vårt folk efter att de blivit fängslade. De bara försvinner... Utan ett spår.,Sakın yakalanmayın. Hapsedildikten sonra insanlarımıza ne yaptıklarına dair korku hikayeleri duydum. Öylece ortadan kayboluyorlar. İz bırakmadan. +"Here's some advice, if you ever see any of the Order's Tinsoldiers go in the other direction. They're fast and brutal.",TXT_DLG_SCRIPT03_D46996_HERES,〃,,,"Dám ti radu: Jestli někdy uvidíš jednoho z plecháčků Řádu, otoč se a utíkej. Jsou rychlí a suroví.",Her er et godt råd: Hvis du nogensinde ser nogen af Ordenens Tinsoldater gå i den anden retning. De er hurtige og brutale.,"Hier ist ein guter Rat, falls du jemals einen dieser Zinnsoldaten des Ordens vorbeigehen siehst. Sie sind schnell und brutal. ",,Jen konsilo: estu ĉiam fore de la artefaritaj soldatoj de La Ordeno. Ili estas rapidaj kaj brutalaj.,Un consejo: mantente siempre alejado de los soldados artificiales de La Orden. Son rápidos y brutales.,,"Annan pienen vinkin: Jos koskaan näet Veljeskunnan tinasotilaita, mene toiseen suuntaan. Ne ovat nopeita ja raakoja.","Voilà un conseil. Si vous voyez un des soldats mécanisés de l'Ordre, retournez vous et courez. Ils sont rapides et brutaux.","Az a tanácsom számodra, hogy ha meglátod a Rend ólomkatonáit, vedd az utad az ellentétes irányba. Gyorsak és brutálisak.","Ecco un consiglio. Se vedi uno dei soldatini di latta dell'Ordine, vai nella direzione opposta. Sono veloci e brutali.","伝えておく、オーダーの錫兵は 他方から呼び出され押し寄せてくる。 -奴等は素早く残忍だ。","조언 하나 하겠습니다. 만약 오더 출신의 깡통로봇들이 당신에게 향하고 있다면, 얼른 피하세요. 그놈들은 훨씬 무섭고 잔혹합니다.","Hier is een advies, als je ooit een van de Tinsoldiers van de Orde de andere kant op ziet gaan. Ze zijn snel en wreed.","Her er noen råd, hvis du noen gang ser noen av Ordenens Tinsoldater gå i den andre retningen. De er raske og brutale.","Dam ci radę. Jeśli zobaczysz jakiegokolwiek Blaszanego Żołnierza Zakonu, idź w przeciwnym kierunku. Są szybcy i brutalni.","Tenho um conselho pra você. Se você ver algum soldadinho da Ordem, vá para outra direção. Eles são rápidos e brutais.",,Uite un sfat: Dacă vezi vreun soldat din staniu du-te în direcția opusă. Sunt rapizi și brutali.,"Небольшой совет: если увидишь «оловянных солдатиков» Ордена, сворачивай в другую сторону. Они быстры и жестоки.",,"İşte size bir tavsiye, eğer Tarikat'ın teneke askerlerinden birini görürseniz diğer yöne gidin. Hızlı ve acımasızdırlar." +奴等は素早く残忍だ。","조언 하나 하겠습니다. 만약 오더 출신의 깡통로봇들이 당신에게 향하고 있다면, 얼른 피하세요. 그놈들은 훨씬 무섭고 잔혹합니다.","Hier is een advies, als je ooit een van de Tinsoldiers van de Orde de andere kant op ziet gaan. Ze zijn snel en wreed.","Her er noen råd, hvis du noen gang ser noen av Ordenens Tinsoldater gå i den andre retningen. De er raske og brutale.","Dam ci radę. Jeśli zobaczysz jakiegokolwiek Blaszanego Żołnierza Zakonu, idź w przeciwnym kierunku. Są szybcy i brutalni.","Tenho um conselho pra você. Se você ver algum soldadinho da Ordem, vá para outra direção. Eles são rápidos e brutais.",,Uite un sfat: Dacă vezi vreun soldat din staniu du-te în direcția opusă. Sunt rapizi și brutali.,"Небольшой совет: если увидишь «оловянных солдатиков» Ордена, сворачивай в другую сторону. Они быстры и жестоки.",,"Här är ett råd, om du någonsin ser någon av Ordens Tinsoldater gå åt andra hållet. De är snabba och brutala.","İşte size bir tavsiye, eğer Tarikat'ın teneke askerlerinden birini görürseniz diğer yöne gidin. Hızlı ve acımasızdırlar." Leave me be. I'm doing something for Macil.,TXT_DLG_SCRIPT03_D48512_LEAVE,〃,,,"Teď mě nech, dělám něco pro Macila.",Lad mig være. Jeg gør noget for Macil.,Lass mich in Ruhe. Ich muss etwas für Macil erledigen.,,Lasu min. Mi faras ion por Macil.,"Déjame, que estoy haciendo algo para Macil.",,Anna minun olla. Palvelen parhaillani Macilia.,Laissez moi. Je suis en train de faire quelque chose pour Macil.,Hagyj békén. Épp macil számára csinálok valamit.,"Ora non ho tempo, sto sbrigando un incarico per Macil.","すまないが忙しい。 私はマシルの雑用を請け負っている。",방해하지 마세요. 사령관님을 위해 중요한 일을 하고 있으니.,Laat me met rust. Ik doe iets voor Macil.,La meg være i fred. Jeg gjør noe for Macil.,Zostaw mnie. Robię coś dla Macila.,Me deixe em paz. Estou fazendo algo pro Macil.,,Lasă-mă. Fac ceva pentru Macil.,"Не отвлекай меня. Я выполняю поручение Мэйсила. -",,Beni rahat bırak. Macil için bir şey yapıyorum. -"Sorry, no. You do not have clearance.",TXT_DLG_SCRIPT04_D0_SORRY,MAP04: Reactor Core red guard.,,,"Pardon, ne. Sem nemůžete.","Beklager, nej. Du har ikke tilladelse.","Tut mir leid, aber Sie haben keine Berechtigung.",,"Pardonon, sed ne, vi ne rajtas eniri.","Lo siento, pero no, no tienes permiso.",,"Anteeksi, ei. Sinulla ei ole kulkulupaa.","Non, désolé. Vous n'avez pas d'autorisation.",Sajnálom de nem. Nincs hozzá jogosultságod.,"Mi spiace, ma non hai l'autorizzazione.",すまないが、お前にクリアランスはない。,"유감이지만, 신분 휘장 없이는 보내줄 수 없어.","Sorry, nee. Je hebt geen toestemming.","Beklager, nei. Du har ikke klarering.","Wybacz, ale nie. Nie masz zezwolenia.",Desculpe mas não. Você não tem permissão.,,"Scuze, nu. Nu ai acces.","Увы, нет. У тебя нет пропуска.",,"Üzgünüm, olmaz. Yetkiniz yok." -Stop! Show me your ID badge.,TXT_DLG_SCRIPT04_D1516_STOPS,〃,,,Stát! Ukažte mi svůj identifikační průkaz.,Stop! Vis mig dit ID-skilt.,Halt. Zeigen Sie mir Ihre Identitätskarte.,,Haltu! Montru vian identigilon de la centralo.,¡Alto! Muéstrame tu identificación de la central.,,Seis! Näytä minulle henkilötunnisteesi.,Stop! Montrez moi votre carte d'identité.,Állj! Mutasd az igazolványod.,Fermo! Mostrami il tesserino d'identificazione.,待て! IDバッジを見せろ。,멈춰라! 너의 신분 휘장을 보여줘.,Stop! Laat me je ID-badge zien.,Stopp! Vis meg ID-kortet ditt.,Stój! Pokaż mi swoją odznakę identyfikacyjną.,Alto! Mostre a sua identificação.,,Stop! Arată-mi cardul de identitate.,Стой! Покажи мне своё удостоверение.,,Dur! Bana kimliğini göster. -Here's my I.D.,TXT_RPLY0_SCRIPT04_D1516_HERES,〃,,,Tady je moje průkazka.,Her er mit id-kort.,Hier ist sie.,,Jen la identigilo.,Aquí está mi identificación.,,Tässä.,La voilà.,Itt az igazolványom.,Eccolo qua.,これだ。,"여기, 휘장.",Hier is mijn ID.,Her er legitimasjonen min.,Oto ona.,Aqui está ela.,,Aici e cardul.,Вот оно.,,İşte kimliğim. -"Oh, ok. Sure go ahead. Have a nice day.",TXT_DLG_SCRIPT04_D3032_OHOKS,〃,,,"Aha, dobře. Jistě, jděte dál. Přeji hezký den.","Åh, okay. Selvfølgelig, værsgo. Hav en god dag.","Alles klar, ich wünsche einen schönen Tag.",,"Ha, bone. Kompreneble, eniru. Havu bonan tagon.","Ah, vale. Claro, adelante. Ten un buen día.","Ah, bueno. Claro, adelante. Ten un buen día.","Aa, hyvä. Selvä, voit mennä. Hyvää päivänjatkoa.","Bon, ok. Allez-y. Passez une bonne journée.","Oh, rendben. Mehetsz is tovább. További szép napot.","Ah, va bene. Vai pure avanti. Buona giornata.",あぁ、宜しい。通れ。良い一日を。,"오, 정말이네. 환영한다. 좋은 하루 보내고.","Oh, oké. Ga je gang. Nog een prettige dag.","Å, ok. Vær så god. Ha en fin dag.","Oh, ok. Proszę, wchodź. Miłego dnia.","Ah, ok. Pode passar. Tenha um bom dia.",,"Ah, în regulă. Mergi mai departe. O zi bună.","Ладно, проходи. Всего доброго.",,"Oh, tamam. Tabii, devam edin. İyi günler dilerim." -"Derwin? Yeah, he's down in the warehouse, but you're not getting in unless you're cleared.",TXT_DLG_SCRIPT04_D4548_DERWI,MAP04: Warehouse red guard.,,,"Derwin? Jo, ten je dole ve skladu, ale ty nikam nejdeš jestliže nemáš povolení.","Derwin? Ja, han er nede i lageret, men du kommer ikke ind, medmindre du er godkendt.","Derwin? Ja, der ist unten im Lagerhaus, aber da kommst du nicht rein ohne Berechtigung.",,"Ĉu Derwin? Jes, li estas en la magazeno en la malsupra etaĝo, sed vi ne rajtas iri tien, krom se vi havas paspermeson.","¿Derwin? Sí, está abajo en el almacén, pero no puedes entrar a menos que tengas permiso.",,"Derwin? Joo, hän on varastolla, muttet pääse sisään ilman kulkulupaa.","Derwin? Ouais, il est dans l'entrepôt. Vous ne pouvez pas y entrer sans autorisation.","Derwin? Igen, Ő épp a raktárban van, de jogosultság nélkül nem jutsz be oda.","Derwin? Sì, è giù nel magazzino, ma non puoi entrare senza autorizzazione.","ダーウィン? ああ、奴はこの倉庫内にいるが、 -片付かない限りお前は入れん。",더윈? 녀석은 저 창고 밑에 있다. 그러나 허가 없이는 못 보내준다.,"Derwin? Ja, hij is in het magazijn, maar je komt er niet in tenzij je vrij bent.","Derwin? Ja, han er nede på lageret, men du kommer ikke inn med mindre du er klarert.","Derwin? Tak, jest w magazynie, ale tam nie wejdziesz bez zgody.","Derwin? Sim, ele está lá embaixo no depósito, mas você não pode entrar enquanto não tiver permissão.",,"Darwin? Da, e în depozit, dar nu intri înăuntru dacă nu ai acces.","Дервин? Да, он внизу, на складе, но тебя туда не пустят, если у тебя нет пропуска.",,"Derwin? Evet, depoda ama izin almadan içeri giremezsin." -I've got clearance.,TXT_RPLY0_SCRIPT04_D4548_IVEGO,〃,,,Mám povolení.,Jeg har fået tilladelse.,Ich habe eine Berechtigung.,,Mi havas ĝin.,Tengo permiso.,,Minulla on lupa.,J'ai une autorisation.,Van jogosultságom.,Ce l'ho l'autorizzazione.,クリアランスはある。,허가를 받았어.,Ik heb toestemming.,Jeg har klarering.,Mam zezwolenie.,Eu tenho permissão.,,Am acces.,У меня есть пропуск.,,İznim var. -Go on.,TXT_DLG_SCRIPT04_D6064_GOON,〃,,,Tak jdi.,Jeg har tilladelse.,Alles klar.,,Tiuokaze daŭrigu.,Entonces ve.,,Jatkakaa.,Allez-y.,Mesélj csak.,Va pure.,続けろ。,그럼 가도 좋다.,Ga door.,Jeg har klarering.,Wchodź.,Pode passar.,,Intră.,Проходи.,,Devam et. -Do you know where he is?,TXT_RPLY0_SCRIPT04_D6064_DOYOU,〃,,,"Nevíš, kde je?","Ved du, hvor han er?","Weißt du, wo er ist?",,"Ĉu vi scias, kie li estas?",¿Sabes dónde está?,,"Tiedätkö, missä hän on?",Vous savez où il est?,Tudod hol találom meg?,Sai dov'è?,ソイツが何処にいるか知っているか?,그가 어디 있는지 아는가?,Weet je waar hij is?,Vet du hvor han er?,Wiesz gdzie on jest?,Você sabe onde ele está?,,Știi unde e?,"Вы знаете, где Дервин?",,Nerede olduğunu biliyor musun? -I don't know where anybody is. I just keep the lid on the rat trap.,TXT_DLG_SCRIPT04_D7580_IDONT,〃,,,Já nevím kde kdo je. Já jen dohlížím na pastičku na myši.,"Jeg ved ikke, hvor nogen er. Jeg holder bare låget på rottefælden.","Ich weiß von niemandem, wo er ist. Ich kümmere mich nur um die Rattenfalle.",,"Mi ne scias, kie iu ajn estas. Mi nur estas komisiito de la ŝtopiloj de ĉi tiu ratkaptilo.",No me sé la ubicación de nadie. Solo estoy a cargo de las tapas de esta ratonera.,,"En tiedä, missä kukaan on. Huolehdin vain rotanloukun kannesta.",Je ne sais pas où se trouve qui que ce soit. Je ne fais que garder le couvercle de ce trou à rats.,Ötletem sincs merre vannak az emberek. Én csak a patkány csapda tetejéért vagyok felelős.,Non so dove sia nessuno di quelli che stanno nel magazzino. A me interessa solo che non scappino.,"俺には何処にいるかは分からない。 -俺はただネズミ捕りにフタを被せているだけだ。",그가 정확히 어디 있는지는 모른다. 난 도망자를 그냥 감시할 뿐이다.,Ik weet niet waar iemand is. Ik hou gewoon het deksel op de rattenval.,Jeg vet ikke hvor noen er. Jeg holder bare lokket på rottefella.,Nie wiem gdzie kto jest. Ja tylko plinuję tej pułapki na szczury.,Não sei onde ninguém está. Apenas mantenho a tampa neste bueiro.,,"Nu știu unde e nimeni, eu doar țin ochii pe capcana pentru șoareci.","Ничего я не знаю. Я просто слежу, чтобы никто из них не сбежал из западни.",,Kimsenin nerede olduğunu bilmiyorum. Ben sadece fare kapanının kapağını tutuyorum. -You are an unpleasant distraction.,TXT_DLG_SCRIPT04_D9096_YOUAR,〃,,,Jsi nepříjemná otrava.,Du er en ubehagelig distraktion.,Du bist eine unerwünschte Ablenkung,,Vi estas malagrabla distraĵo.,Eres una distracción incómoda.,,Oletpa epämiellyttävä häiriötekijä.,Vous êtes une distraction déplaisante.,Egy kellemetlen zavaró tényező vagy.,Sei una sgradevole distazione.,お前は不快で目障りだ。,당신은 지금 내 감시일을 방해하고 있다.,Je bent een onaangename afleiding.,Du er en ubehagelig distraksjon.,Bardzo mnie rozpraszasz.,Você é uma distração bem incômoda.,,Ești o distragere neplăcută.,Ты — досадная помеха.,,Hoş olmayan bir dikkat dağıtıcısın. -Move along or taste metal.,TXT_DLG_SCRIPT04_D10612_MOVEA,MAP04: Reactor Core gray guard.,,,"Jdi dál, nebo okus ocel.",Gå videre eller smag på metal.,Beweg dich oder du schmeckst Metall.,,Plue movu vin aŭ gustumu metalon.,Muévete o prueba metal.,,"Ala vetää, tai maista metallia.",Circulez ou préparez vous à manger de l'acier.,"Haladj tovább, vagy ízleld meg a kardom.",Sparisci o ti finisce male.,同行か鉄を味わうかだ。,어서 움직여. 총알 먹기 싫으면.,Ga verder of proef metaal.,Gå videre eller smak på metall.,Odejdź stąd albo posmakujesz mojej pukawki.,Vá embora ou vai tomar chumbo grosso.,,Mșcă-te sau înghiți metal.,"Прочь, или отведаешь металла.",,İlerle yoksa metalin tadına bakarsın. -Pass your ID through here for access.,TXT_DLG_SCRIPT04_D12128_PASSY,,,,Pro přístup tady nahrajte svou legitimaci.,Giv dit ID her igennem for at få adgang.,Reichen Sie Ihre Identitätskarte hier durch!,,Ŝovu vian identigilon sur la legilon por eniri.,Pasa tu identificación por aquí para acceder.,,Vedä tunnisteesi tästä päästäksesi läpi.,Faites passer votre carte d'identité ici pour continuer.,Add le az igazolványod itt a belépéshez.,Mostra il tesserino per accedere.,彼方のI.D.をここに提示してください。,신분증을 보여줘. 입장하고 싶으면.,Geef je ID hier door voor toegang.,Før legitimasjonen din gjennom her for å få adgang.,"Pokaż tu swój identyfikator, aby otrzymać dostęp.",Passe a sua identificação por aqui para acessar.,,Trece cardul de acces pe aici.,"Покажи своё удостоверение, чтобы получить допуск.",,Giriş için kimliğinizi buradan geçirin. -"Get back to work, now!",TXT_DLG_SCRIPT04_D13644_GETBA,MAP04: Green guard.,,,"Vrať se do práce, hned!","Tilbage til arbejdet, nu!",Gehen Sie sofort zurück an die Arbeit!,,"Reiru al via laborposteno, tuje!","Vuelve al trabajo, ¡ahora!",,"No niin, takaisin töihisi!","Retournez au boulot, maintenant!",Nyomás vissza dolgozni!,Ora torna a lavoro!,仕事へ戻れ、今すぐ!,당장 일해. 어서.,"Ga terug aan het werk, nu!","Tilbake til arbeidet, nå!","Do roboty, już!","Volte ao trabalho, agora!",,"Treci înapoi la muncă, acum!",Немедленно за работу!,,"İşinizin başına dönün, hemen!" -"Get back to work, now!",TXT_DLG_SCRIPT04_D15160_GETBA,〃,,,"Vrať se do práce, hned!","Tilbage til arbejdet, nu!",Gehen Sie sofort zurück an die Arbeit!,,"Reiru al via laborposteno, tuje!","Vuelve al trabajo, ¡ahora!",,"No niin, takaisin töihisi!","Retournez au boulot, maintenant!",Nyomás vissza dolgozni!,Ora torna a lavoro!,今すぐ仕事へ戻れ!,쉬면 알지? 어서 일해.,"Ga terug aan het werk, nu!","Tilbake til arbeidet, nå!","Do roboty, już!","Volte ao trabalho, agora!",,"Treci înapoi la muncă, acum!",Немедленно за работу!,,"İşinizin başına dönün, hemen!" -We've been running around the clock for weeks with no down time. I'd say that the Order is planning a suppression raid on the Front.,TXT_DLG_SCRIPT04_D16676_WEVEB,MAP04: Warehouse → Northeast (worker in red),,,"Celé týdny makáme bez přestávek. Řekl bych, že Řád má v plánu nějaký útok na Frontu.","Vi har kørt døgnet rundt i ugevis uden at have nogen pause. Jeg vil sige, at Ordenen planlægger et undertrykkelsesangreb på fronten.","Die Station hier läuft seit Wochen ohne Stillstand. Ich vermute mal, der Orden bereitet einen großen Schlag gegen die Front vor.",,"Ni senhalte laboras 24 horojn ĉiutage de antaŭ semajnoj. Mi dirus, ke La Ordono planas atakon por subpremi la Fronton.",Llevamos semanas trabajando 24 horas al día sin parar. Diría que La Orden está planeando una incursión para suprimir al Frente.,,"Olemme työskennelleet viikkoja kellon ympäri ilman silmällistäkään. Sanoisin, että Veljeskunta on suunnittelemassa ehkäisevää iskua Rintamaa vastaan.",J'ai fait le tour de l'horloge depuis des semaines sans temps de repos. Je pense que l'Ordre prépare un raid de suppression sur le Front.,"A nap minden órájában dolgoztunk szünet nélkül. Az a gyanúm, hogy a Rend sorsdöntő támadást akar indítani a Front ellen.",Stiamo lavorando senza sosta per settimane oramai. Secondo me l'Ordine sta preparando un nuovo attacco contro il Fronte.,"もう数週間も休日返上で働いているんだ。 +",,Låt mig vara. Jag gör något för Macil.,Beni rahat bırak. Macil için bir şey yapıyorum. +"Sorry, no. You do not have clearance.",TXT_DLG_SCRIPT04_D0_SORRY,MAP04: Reactor Core red guard.,,,"Pardon, ne. Sem nemůžete.","Beklager, nej. Du har ikke tilladelse.","Tut mir leid, aber Sie haben keine Berechtigung.",,"Pardonon, sed ne, vi ne rajtas eniri.","Lo siento, pero no, no tienes permiso.",,"Anteeksi, ei. Sinulla ei ole kulkulupaa.","Non, désolé. Vous n'avez pas d'autorisation.",Sajnálom de nem. Nincs hozzá jogosultságod.,"Mi spiace, ma non hai l'autorizzazione.",すまないが、お前にクリアランスはない。,"유감이지만, 신분 휘장 없이는 보내줄 수 없어.","Sorry, nee. Je hebt geen toestemming.","Beklager, nei. Du har ikke klarering.","Wybacz, ale nie. Nie masz zezwolenia.",Desculpe mas não. Você não tem permissão.,,"Scuze, nu. Nu ai acces.","Увы, нет. У тебя нет пропуска.",,"Tyvärr, nej. Du har inget tillstånd.","Üzgünüm, olmaz. Yetkiniz yok." +Stop! Show me your ID badge.,TXT_DLG_SCRIPT04_D1516_STOPS,〃,,,Stát! Ukažte mi svůj identifikační průkaz.,Stop! Vis mig dit ID-skilt.,Halt. Zeigen Sie mir Ihre Identitätskarte.,,Haltu! Montru vian identigilon de la centralo.,¡Alto! Muéstrame tu identificación de la central.,,Seis! Näytä minulle henkilötunnisteesi.,Stop! Montrez moi votre carte d'identité.,Állj! Mutasd az igazolványod.,Fermo! Mostrami il tesserino d'identificazione.,待て! IDバッジを見せろ。,멈춰라! 너의 신분 휘장을 보여줘.,Stop! Laat me je ID-badge zien.,Stopp! Vis meg ID-kortet ditt.,Stój! Pokaż mi swoją odznakę identyfikacyjną.,Alto! Mostre a sua identificação.,,Stop! Arată-mi cardul de identitate.,Стой! Покажи мне своё удостоверение.,,Stopp! Visa mig din ID-bricka.,Dur! Bana kimliğini göster. +Here's my I.D.,TXT_RPLY0_SCRIPT04_D1516_HERES,〃,,,Tady je moje průkazka.,Her er mit id-kort.,Hier ist sie.,,Jen la identigilo.,Aquí está mi identificación.,,Tässä.,La voilà.,Itt az igazolványom.,Eccolo qua.,これだ。,"여기, 휘장.",Hier is mijn ID.,Her er legitimasjonen min.,Oto ona.,Aqui está ela.,,Aici e cardul.,Вот оно.,,Här är mitt ID-kort.,İşte kimliğim. +"Oh, ok. Sure go ahead. Have a nice day.",TXT_DLG_SCRIPT04_D3032_OHOKS,〃,,,"Aha, dobře. Jistě, jděte dál. Přeji hezký den.","Åh, okay. Selvfølgelig, værsgo. Hav en god dag.","Alles klar, ich wünsche einen schönen Tag.",,"Ha, bone. Kompreneble, eniru. Havu bonan tagon.","Ah, vale. Claro, adelante. Ten un buen día.","Ah, bueno. Claro, adelante. Ten un buen día.","Aa, hyvä. Selvä, voit mennä. Hyvää päivänjatkoa.","Bon, ok. Allez-y. Passez une bonne journée.","Oh, rendben. Mehetsz is tovább. További szép napot.","Ah, va bene. Vai pure avanti. Buona giornata.",あぁ、宜しい。通れ。良い一日を。,"오, 정말이네. 환영한다. 좋은 하루 보내고.","Oh, oké. Ga je gang. Nog een prettige dag.","Å, ok. Vær så god. Ha en fin dag.","Oh, ok. Proszę, wchodź. Miłego dnia.","Ah, ok. Pode passar. Tenha um bom dia.",,"Ah, în regulă. Mergi mai departe. O zi bună.","Ладно, проходи. Всего доброго.",,"Åh, okej. Visst, fortsätt. Ha en trevlig dag.","Oh, tamam. Tabii, devam edin. İyi günler dilerim." +"Derwin? Yeah, he's down in the warehouse, but you're not getting in unless you're cleared.",TXT_DLG_SCRIPT04_D4548_DERWI,MAP04: Warehouse red guard.,,,"Derwin? Jo, ten je dole ve skladu, ale ty nikam nejdeš jestliže nemáš povolení.","Derwin? Ja, han er nede i lageret, men du kommer ikke ind, medmindre du er godkendt.","Derwin? Ja, der ist unten im Lagerhaus, aber da kommst du nicht rein ohne Berechtigung.",,"Ĉu Derwin? Jes, li estas malsupre en la magazeno, sed vi ne rajtas iri tien, krom se vi havas paspermeson.","¿Derwin? Sí, está abajo en el almacén, pero no puedes entrar a menos que tengas permiso.",,"Derwin? Joo, hän on varastolla, muttet pääse sisään ilman kulkulupaa.","Derwin? Ouais, il est dans l'entrepôt. Vous ne pouvez pas y entrer sans autorisation.","Derwin? Igen, Ő épp a raktárban van, de jogosultság nélkül nem jutsz be oda.","Derwin? Sì, è giù nel magazzino, ma non puoi entrare senza autorizzazione.","ダーウィン? ああ、奴はこの倉庫内にいるが、 +片付かない限りお前は入れん。",더윈? 녀석은 저 창고 밑에 있다. 그러나 허가 없이는 못 보내준다.,"Derwin? Ja, hij is in het magazijn, maar je komt er niet in tenzij je vrij bent.","Derwin? Ja, han er nede på lageret, men du kommer ikke inn med mindre du er klarert.","Derwin? Tak, jest w magazynie, ale tam nie wejdziesz bez zgody.","Derwin? Sim, ele está lá embaixo no depósito, mas você não pode entrar enquanto não tiver permissão.",,"Darwin? Da, e în depozit, dar nu intri înăuntru dacă nu ai acces.","Дервин? Да, он внизу, на складе, но тебя туда не пустят, если у тебя нет пропуска.",,"Derwin? Ja, han är nere i lagret, men du kommer inte in om du inte har fått tillstånd.","Derwin? Evet, depoda ama izin almadan içeri giremezsin." +I've got clearance.,TXT_RPLY0_SCRIPT04_D4548_IVEGO,〃,,,Mám povolení.,Jeg har fået tilladelse.,Ich habe eine Berechtigung.,,Mi havas ĝin.,Tengo permiso.,,Minulla on lupa.,J'ai une autorisation.,Van jogosultságom.,Ce l'ho l'autorizzazione.,クリアランスはある。,허가를 받았어.,Ik heb toestemming.,Jeg har klarering.,Mam zezwolenie.,Eu tenho permissão.,,Am acces.,У меня есть пропуск.,,Jag har tillstånd.,İznim var. +Go on.,TXT_DLG_SCRIPT04_D6064_GOON,〃,,,Tak jdi.,Jeg har tilladelse.,Alles klar.,,Vi rajtas iri.,Entonces ve.,,Jatkakaa.,Allez-y.,Mesélj csak.,Va pure.,続けろ。,그럼 가도 좋다.,Ga door.,Jeg har klarering.,Wchodź.,Pode passar.,,Intră.,Проходи.,,Fortsätt.,Devam et. +Do you know where he is?,TXT_RPLY0_SCRIPT04_D6064_DOYOU,〃,,,"Nevíš, kde je?","Ved du, hvor han er?","Weißt du, wo er ist?",,"Ĉu vi scias, kie li estas?",¿Sabes dónde está?,,"Tiedätkö, missä hän on?",Vous savez où il est?,Tudod hol találom meg?,Sai dov'è?,ソイツが何処にいるか知っているか?,그가 어디 있는지 아는가?,Weet je waar hij is?,Vet du hvor han er?,Wiesz gdzie on jest?,Você sabe onde ele está?,,Știi unde e?,"Вы знаете, где Дервин?",,Vet du var han är?,Nerede olduğunu biliyor musun? +I don't know where anybody is. I just keep the lid on the rat trap.,TXT_DLG_SCRIPT04_D7580_IDONT,〃,,,Já nevím kde kdo je. Já jen dohlížím na pastičku na myši.,"Jeg ved ikke, hvor nogen er. Jeg holder bare låget på rottefælden.","Ich weiß von niemandem, wo er ist. Ich kümmere mich nur um die Rattenfalle.",,Mi scias nenies pozicion. Mi nur estas komisiito de la pordoj de ĉi tiu ratkaptilo.,No me sé la ubicación de nadie. Solo estoy a cargo de las puertas de esta ratonera.,,"En tiedä, missä kukaan on. Huolehdin vain rotanloukun kannesta.",Je ne sais pas où se trouve qui que ce soit. Je ne fais que garder le couvercle de ce trou à rats.,Ötletem sincs merre vannak az emberek. Én csak a patkány csapda tetejéért vagyok felelős.,Non so dove sia nessuno di quelli che stanno nel magazzino. A me interessa solo che non scappino.,"俺には何処にいるかは分からない。 +俺はただネズミ捕りにフタを被せているだけだ。",그가 정확히 어디 있는지는 모른다. 난 도망자를 그냥 감시할 뿐이다.,Ik weet niet waar iemand is. Ik hou gewoon het deksel op de rattenval.,Jeg vet ikke hvor noen er. Jeg holder bare lokket på rottefella.,Nie wiem gdzie kto jest. Ja tylko plinuję tej pułapki na szczury.,Não sei onde ninguém está. Apenas mantenho a tampa neste bueiro.,,"Nu știu unde e nimeni, eu doar țin ochii pe capcana pentru șoareci.","Ничего я не знаю. Я просто слежу, чтобы никто из них не сбежал из западни.",,Jag vet inte var någon är. Jag håller bara locket på råttfällan.,Kimsenin nerede olduğunu bilmiyorum. Ben sadece fare kapanının kapağını tutuyorum. +You are an unpleasant distraction.,TXT_DLG_SCRIPT04_D9096_YOUAR,〃,,,Jsi nepříjemná otrava.,Du er en ubehagelig distraktion.,Du bist eine unerwünschte Ablenkung,,Vi estas malagrabla distraĵo.,Eres una distracción incómoda.,,Oletpa epämiellyttävä häiriötekijä.,Vous êtes une distraction déplaisante.,Egy kellemetlen zavaró tényező vagy.,Sei una sgradevole distazione.,お前は不快で目障りだ。,당신은 지금 내 감시일을 방해하고 있다.,Je bent een onaangename afleiding.,Du er en ubehagelig distraksjon.,Bardzo mnie rozpraszasz.,Você é uma distração bem incômoda.,,Ești o distragere neplăcută.,Ты — досадная помеха.,,Du är en obehaglig distraktion.,Hoş olmayan bir dikkat dağıtıcısın. +Move along or taste metal.,TXT_DLG_SCRIPT04_D10612_MOVEA,MAP04: Reactor Core gray guard.,,,"Jdi dál, nebo okus ocel.",Gå videre eller smag på metal.,Beweg dich oder du schmeckst Metall.,,Plue movu vin aŭ gustumu kuglojn.,Esfúmate o come plomo.,,"Ala vetää, tai maista metallia.",Circulez ou préparez vous à manger de l'acier.,"Haladj tovább, vagy ízleld meg a kardom.",Sparisci o ti finisce male.,同行か鉄を味わうかだ。,어서 움직여. 총알 먹기 싫으면.,Ga verder of proef metaal.,Gå videre eller smak på metall.,Odejdź stąd albo posmakujesz mojej pukawki.,Vá embora ou vai tomar chumbo grosso.,,Mșcă-te sau înghiți metal.,"Прочь, или отведаешь металла.",,Gå vidare eller smaka på metall.,İlerle yoksa metalin tadına bakarsın. +Pass your ID through here for access.,TXT_DLG_SCRIPT04_D12128_PASSY,,,,Pro přístup tady nahrajte svou legitimaci.,Giv dit ID her igennem for at få adgang.,Reichen Sie Ihre Identitätskarte hier durch!,,Ŝovu vian identigilon sur la legilon por eniri.,Pasa tu identificación por aquí para acceder.,,Vedä tunnisteesi tästä päästäksesi läpi.,Faites passer votre carte d'identité ici pour continuer.,Add le az igazolványod itt a belépéshez.,Mostra il tesserino per accedere.,彼方のI.D.をここに提示してください。,신분증을 보여줘. 입장하고 싶으면.,Geef je ID hier door voor toegang.,Før legitimasjonen din gjennom her for å få adgang.,"Pokaż tu swój identyfikator, aby otrzymać dostęp.",Passe a sua identificação por aqui para acessar.,,Trece cardul de acces pe aici.,"Покажи своё удостоверение, чтобы получить допуск.",,Ge ditt ID-kort här för att få tillträde.,Giriş için kimliğinizi buradan geçirin. +"Get back to work, now!",TXT_DLG_SCRIPT04_D13644_GETBA,MAP04: Green guard.,,,"Vrať se do práce, hned!","Tilbage til arbejdet, nu!",Gehen Sie sofort zurück an die Arbeit!,,"Reiru al via laborposteno, tuje!","Vuelve al trabajo, ¡ahora!",,"No niin, takaisin töihisi!","Retournez au boulot, maintenant!",Nyomás vissza dolgozni!,Ora torna a lavoro!,仕事へ戻れ、今すぐ!,당장 일해. 어서.,"Ga terug aan het werk, nu!","Tilbake til arbeidet, nå!","Do roboty, już!","Volte ao trabalho, agora!",,"Treci înapoi la muncă, acum!",Немедленно за работу!,,"Tillbaka till arbetet, nu!","İşinizin başına dönün, hemen!" +"Get back to work, now!",TXT_DLG_SCRIPT04_D15160_GETBA,〃,,,"Vrať se do práce, hned!","Tilbage til arbejdet, nu!",Gehen Sie sofort zurück an die Arbeit!,,"Reiru al via laborposteno, tuje!","Vuelve al trabajo, ¡ahora!",,"No niin, takaisin töihisi!","Retournez au boulot, maintenant!",Nyomás vissza dolgozni!,Ora torna a lavoro!,今すぐ仕事へ戻れ!,쉬면 알지? 어서 일해.,"Ga terug aan het werk, nu!","Tilbake til arbeidet, nå!","Do roboty, już!","Volte ao trabalho, agora!",,"Treci înapoi la muncă, acum!",Немедленно за работу!,,"Tillbaka till arbetet, nu!","İşinizin başına dönün, hemen!" +We've been running around the clock for weeks with no down time. I'd say that the Order is planning a suppression raid on the Front.,TXT_DLG_SCRIPT04_D16676_WEVEB,MAP04: Warehouse → Northeast (worker in red),,,"Celé týdny makáme bez přestávek. Řekl bych, že Řád má v plánu nějaký útok na Frontu.","Vi har kørt døgnet rundt i ugevis uden at have nogen pause. Jeg vil sige, at Ordenen planlægger et undertrykkelsesangreb på fronten.","Die Station hier läuft seit Wochen ohne Stillstand. Ich vermute mal, der Orden bereitet einen großen Schlag gegen die Front vor.",,"Ni senhalte laboras 24 horojn ĉiutage de antaŭ semajnoj. Mi dirus, ke La Ordeno planas atakon por subpremi la Fronton.",Llevamos semanas trabajando 24 horas al día sin parar. Diría que La Orden está planeando una incursión para suprimir al Frente.,,"Olemme työskennelleet viikkoja kellon ympäri ilman silmällistäkään. Sanoisin, että Veljeskunta on suunnittelemassa ehkäisevää iskua Rintamaa vastaan.",J'ai fait le tour de l'horloge depuis des semaines sans temps de repos. Je pense que l'Ordre prépare un raid de suppression sur le Front.,"A nap minden órájában dolgoztunk szünet nélkül. Az a gyanúm, hogy a Rend sorsdöntő támadást akar indítani a Front ellen.",Stiamo lavorando senza sosta per settimane oramai. Secondo me l'Ordine sta preparando un nuovo attacco contro il Fronte.,"もう数週間も休日返上で働いているんだ。 オーダーがまたフロントを攻撃する準備を -しているんだろうな。","일주일 동안 쉬지도 않고 일하느라 정신이 날아갈 것 같아요... 아무튼, 오더가 프론트 저항군을 제압할 작전을 준비한다는군요.","We rennen al weken rond de klok, zonder uitvaltijd. Ik zou zeggen dat de Orde een onderdrukkingsinval aan de voorkant plant.",Vi har kjørt døgnet rundt i ukevis uten pause. Jeg vil si at Ordenen planlegger et undertrykkelsesangrep på Fronten.,"Od kilku tygodni pracujemy przez całą dobę bez przerwy. Powiedziałbym, że Zakon planuje zniszczyć Front.",Estamos trabalhando noite e dia por semanas sem descanso. Eu diria que a Ordem está planjeando um ataque para suprimir a Frente.,,Muncim non-stop de săptămăni fără niciun fel de pauză. Aș zice că Ordinul plănuiește un atac de reprimare asupra Frontului.,"Мы работаем круглые сутки без перерыва уже несколько недель. Мне кажется, Орден готовит решительный рейд, чтобы окончательно покончить с Сопротивлением.",,Haftalardır hiç ara vermeden gece gündüz çalışıyoruz. Tarikat'ın Cephe'ye bir baskın planladığını söyleyebilirim. -"Oh, damn. The governor sent you. I was going to give him his cut, really I was. OK, listen. I've got a bundle stashed. It's yours if you look the other way.",TXT_DLG_SCRIPT04_D18192_OHDAM,MAP04: Derwin.,,,"A sakra. Guvernér tě poslal. Měl jsem v plánu dát mu jeho podíl, opravdu. Dobře, poslouchej. Mám schované nějaké zlaťáky, můžou být tvoje, když přimhouříš oko.","Åh, for pokker. Guvernøren har sendt dig. Jeg ville give ham sin andel, det ville jeg virkelig. Okay, hør her. Jeg har en bunke gemt. Det er dit, hvis du ser den anden vej.","Verdammt, der Gouverneur hat dich geschickt. Ich wollte ihm seinen Anteil geben - wirklich ich wollte das. Hör zu, ich habe hier was zur Seite geschafft, es gehört die wenn du die Sache auf sich beruhen läßt.",,"Ha, fek, la registo sendis vin. Mi estis pagonta lin, serioze. Nu, aŭskultu, mi havas kelke da kaŝita mono; ĝi estas via se vi rigardos aliloken.","Ah, maldición, el gobernador te ha enviado; iba a darle su parte, en serio. Bueno, escucha, tengo un puñado escondido; es tuyo si miras para otro lado.","Ah, no puede ser, te manda el gobernador; iba a darle su parte, en serio. Bueno, escucha, tengo un puñado escondido; es tuyo si miras para otro lado.","Voi helvetti, kuvernööri on lähettänyt sinut. Meinasin antaa hänelle hänen siivunsa, ihan totta. Hei, kuuntele. Minulla on jemma kätkettynä. Se on sinun, jos katsot asiaa läpi sormiesi.","Oh, merde. Le gouverneur t'a envoyé? J'allais lui donner sa part, si, vraiment. Ok, écoute. J'en ai un paquet de mis de côté. Si tu veux, tu peux le prendre, si tu m'oublies.","Szóval a kormányzó küldött...francba. Oda akartam adni a megillető részét, hidd el tényleg. Figyelj, itt egy köteg eldugva. A tied ha képes vagy szemet hunyni felette.","Ah, dannazione... Ti ha mandato il governatore. Gli avrei dato la sua parte, giuro che l'avrei fatto. Ok, ascolta. Ho una parcella qua con me. È tua se chiudi un occhio.","クソッ、知事の回し者だな。 +しているんだろうな。","일주일 동안 쉬지도 않고 일하느라 정신이 날아갈 것 같아요... 아무튼, 오더가 프론트 저항군을 제압할 작전을 준비한다는군요.","We rennen al weken rond de klok, zonder uitvaltijd. Ik zou zeggen dat de Orde een onderdrukkingsinval aan de voorkant plant.",Vi har kjørt døgnet rundt i ukevis uten pause. Jeg vil si at Ordenen planlegger et undertrykkelsesangrep på Fronten.,"Od kilku tygodni pracujemy przez całą dobę bez przerwy. Powiedziałbym, że Zakon planuje zniszczyć Front.",Estamos trabalhando noite e dia por semanas sem descanso. Eu diria que a Ordem está planjeando um ataque para suprimir a Frente.,,Muncim non-stop de săptămăni fără niciun fel de pauză. Aș zice că Ordinul plănuiește un atac de reprimare asupra Frontului.,"Мы работаем круглые сутки без перерыва уже несколько недель. Мне кажется, Орден готовит решительный рейд, чтобы окончательно покончить с Сопротивлением.",,Vi har kört dygnet runt i flera veckor utan några avbrott. Jag skulle säga att Orden planerar en attack mot fronten.,Haftalardır hiç ara vermeden gece gündüz çalışıyoruz. Tarikat'ın Cephe'ye bir baskın planladığını söyleyebilirim. +"Oh, damn. The governor sent you. I was going to give him his cut, really I was. OK, listen. I've got a bundle stashed. It's yours if you look the other way.",TXT_DLG_SCRIPT04_D18192_OHDAM,MAP04: Derwin.,,,"A sakra. Guvernér tě poslal. Měl jsem v plánu dát mu jeho podíl, opravdu. Dobře, poslouchej. Mám schované nějaké zlaťáky, můžou být tvoje, když přimhouříš oko.","Åh, for pokker. Guvernøren har sendt dig. Jeg ville give ham sin andel, det ville jeg virkelig. Okay, hør her. Jeg har en bunke gemt. Det er dit, hvis du ser den anden vej.","Verdammt, der Gouverneur hat dich geschickt. Ich wollte ihm seinen Anteil geben - wirklich ich wollte das. Hör zu, ich habe hier was zur Seite geschafft, es gehört die wenn du die Sache auf sich beruhen läßt.",,"Ha, fek, la registo venigis vin; mi estis pagonta lin, serioze. Nu, aŭskultu, mi havas kelke da kaŝita mono; ĝi estas via se vi rigardos aliloken.","Ah, maldición, el gobernador te ha enviado; iba a darle su parte, en serio. Bueno, escucha, tengo un puñado escondido; es tuyo si miras para otro lado.","Ah, no puede ser, te manda el gobernador; iba a darle su parte, en serio. Bueno, escucha, tengo un puñado escondido; es tuyo si miras para otro lado.","Voi helvetti, kuvernööri on lähettänyt sinut. Meinasin antaa hänelle hänen siivunsa, ihan totta. Hei, kuuntele. Minulla on jemma kätkettynä. Se on sinun, jos katsot asiaa läpi sormiesi.","Oh, merde. Le gouverneur t'a envoyé? J'allais lui donner sa part, si, vraiment. Ok, écoute. J'en ai un paquet de mis de côté. Si tu veux, tu peux le prendre, si tu m'oublies.","Szóval a kormányzó küldött...francba. Oda akartam adni a megillető részét, hidd el tényleg. Figyelj, itt egy köteg eldugva. A tied ha képes vagy szemet hunyni felette.","Ah, dannazione... Ti ha mandato il governatore. Gli avrei dato la sua parte, giuro che l'avrei fatto. Ok, ascolta. Ho una parcella qua con me. È tua se chiudi un occhio.","クソッ、知事の回し者だな。 本当はあいつに分け前を渡そうとしてたんだがな。 よし、聞いてくれ。金はあるから、 -見逃してくれりゃお前にも分けてやる。","이런 제길... 총독 새끼가 널 보낸 거지? 하필 그 녀석의 몫을 보내기 전에. 좋아, 잘 들어. 날 살려주면 내가 숨긴 비상금을 줄게!","Oh, verdomme. De gouverneur heeft je gestuurd. Ik wilde hem zijn deel geven, echt waar. Oké, luister. Ik heb een bundel verstopt. Het is van jou als je de andere kant op kijkt.","Å, pokker. Guvernøren sendte deg. Jeg skulle gi ham hans andel, det skulle jeg virkelig. OK, hør her. Jeg har gjemt en bunke. Den er din hvis du ser den andre veien.","Kurde. Przysłał cię gubernator. Chciałem się z nim podzielić udziałami, naprawdę. Ok, słuchaj. Mam tu ukryty pewien pakunek. Będzie twój jeśli zawrócisz.","Ah, merda. O governador enviou você. Eu ja ia passar a parte dele, sério mesmo. Ok, ouça. Eu tenho um pacote escondido aqui. Ele é seu se você deixar passar.",,"Of, firar. Guvernatorul te-a trimis. Urma să îi dau partea lui din câștig, chiar urma, pe cuvânt. În regulă, ascultă. Am un pachet ascuns. E al tău dacă alegi să ignori ceea ce s-a întâmplat.","Ох, чёрт. Ты от губернатора. Я собирался отдать ему его долю — нет, правда. Слушай, я поднакопил изрядно денег — они твои, если найдёшь иной выход из ситуации.",,"Oh, kahretsin. Seni vali gönderdi. Ona payını verecektim, gerçekten. Tamam, dinle. Sakladığım bir paket var. Diğer tarafa bakarsan senindir." -"All right, I'll let you go.",TXT_RPLY0_SCRIPT04_D18192_ALLRI,〃,,,"Dobře, nechám tě jít.","Okay, jeg lader dig gå.","Ok, ich lass dich gehen.",,"Bone, vi rajtas foriri.","Muy bien, te dejaré ir.","Muy bien, te dejo ir.","Hyvä on, päästän sinut.","D'accord, tu peux y aller.","Rendben, elengedlek.","Va bene, ti lascerò andare.",分かった、見逃そう。,좋아. 그럼 널 살려주지.,"Oké, ik laat je gaan.","Greit, jeg skal la deg gå.","Dobra, zostawię cię w spokoju.","Ok, vou te deixar em paz.",,"În regulă, te las în pace.","Ладно, я дам тебе уйти.",,"Pekala, gitmene izin vereceğim." -"Sorry, nothing personal.",TXT_RPLY1_SCRIPT04_D18192_SORRY,〃,,,"Promiň, nic osobního.","Undskyld, det er ikke personligt.","Tut mir leid, nimm es nicht persönlich",,"Pardonon, mi nur laboras.","Lo siento, no es nada personal.",,"Pahoittelut, ei mitään henkilökohtaista.","Désolé, rien de personnel.","Sajnálom, nem személyes.","Mi spiace, nulla di personale.",悪いが、仕事なんでね。,"미안해, 사적인 건 아니야.","Sorry, niets persoonlijks.","Unnskyld, ikke ta det personlig.","Wybacz, nic osobistego.",Desculpe. Não é nada pessoal.,,"Scuze, nimic personal.","Прости, ничего личного.",,"Üzgünüm, kişisel bir şey değil." +見逃してくれりゃお前にも分けてやる。","이런 제길... 총독 새끼가 널 보낸 거지? 하필 그 녀석의 몫을 보내기 전에. 좋아, 잘 들어. 날 살려주면 내가 숨긴 비상금을 줄게!","Oh, verdomme. De gouverneur heeft je gestuurd. Ik wilde hem zijn deel geven, echt waar. Oké, luister. Ik heb een bundel verstopt. Het is van jou als je de andere kant op kijkt.","Å, pokker. Guvernøren sendte deg. Jeg skulle gi ham hans andel, det skulle jeg virkelig. OK, hør her. Jeg har gjemt en bunke. Den er din hvis du ser den andre veien.","Kurde. Przysłał cię gubernator. Chciałem się z nim podzielić udziałami, naprawdę. Ok, słuchaj. Mam tu ukryty pewien pakunek. Będzie twój jeśli zawrócisz.","Ah, merda. O governador enviou você. Eu ja ia passar a parte dele, sério mesmo. Ok, ouça. Eu tenho um pacote escondido aqui. Ele é seu se você deixar passar.",,"Of, firar. Guvernatorul te-a trimis. Urma să îi dau partea lui din câștig, chiar urma, pe cuvânt. În regulă, ascultă. Am un pachet ascuns. E al tău dacă alegi să ignori ceea ce s-a întâmplat.","Ох, чёрт. Ты от губернатора. Я собирался отдать ему его долю — нет, правда. Слушай, я поднакопил изрядно денег — они твои, если найдёшь иной выход из ситуации.",,"Fan också. Guvernören skickade dig. Jag tänkte ge honom hans andel, verkligen. Okej, lyssna. Jag har en bunt gömt. Det är ditt om du tittar åt andra hållet.","Oh, kahretsin. Seni vali gönderdi. Ona payını verecektim, gerçekten. Tamam, dinle. Sakladığım bir paket var. Diğer tarafa bakarsan senindir." +"All right, I'll let you go.",TXT_RPLY0_SCRIPT04_D18192_ALLRI,〃,,,"Dobře, nechám tě jít.","Okay, jeg lader dig gå.","Ok, ich lass dich gehen.",,"Bone, vi rajtas foriri.","Muy bien, te dejaré ir.","Muy bien, te dejo ir.","Hyvä on, päästän sinut.","D'accord, tu peux y aller.","Rendben, elengedlek.","Va bene, ti lascerò andare.",分かった、見逃そう。,좋아. 그럼 널 살려주지.,"Oké, ik laat je gaan.","Greit, jeg skal la deg gå.","Dobra, zostawię cię w spokoju.","Ok, vou te deixar em paz.",,"În regulă, te las în pace.","Ладно, я дам тебе уйти.",,"Okej, jag låter dig gå.","Pekala, gitmene izin vereceğim." +"Sorry, nothing personal.",TXT_RPLY1_SCRIPT04_D18192_SORRY,〃,,,"Promiň, nic osobního.","Undskyld, det er ikke personligt.","Tut mir leid, nimm es nicht persönlich",,"Pardonon, mi nur laboras.","Lo siento, no es nada personal.",,"Pahoittelut, ei mitään henkilökohtaista.","Désolé, rien de personnel.","Sajnálom, nem személyes.","Mi spiace, nulla di personale.",悪いが、仕事なんでね。,"미안해, 사적인 건 아니야.","Sorry, niets persoonlijks.","Unnskyld, ikke ta det personlig.","Wybacz, nic osobistego.",Desculpe. Não é nada pessoal.,,"Scuze, nimic personal.","Прости, ничего личного.",,"Ledsen, inget personligt.","Üzgünüm, kişisel bir şey değil." "Nuts, if I'm going down, then so are you. Guards!!",TXT_DLG_SCRIPT04_D19708_NUTSI,〃,,,"K čertu, jestli mám zemřít, tak ty taky. Stráže!","Fandens, hvis jeg ryger ned, så ryger du også ned. Vagter!!","Scheiße, aber wenn ich dran bin, bist du es auch. Wärter!",,"Al mil diabloj. Se mi falos, ankaŭ vi. Gardistoj!!","A tomar por saco. Si yo caigo, tú también. ¡¡Guardias!!","Al carajo. Si yo caigo, tú también. ¡¡Guardias!!","Vittu, jos kuolen nyt, niin sinäkin. Vartijat!!","Putain, si je crève ici, alors tu y passe aussi! Gardes!","Őrület! Ha Én lebukok, akkor rántalak magammal. Őrök!","Al diavolo, se devo andare al fondo, ti porterò con me. Guardie!!","社会の厳しさを分けてやるよ、お前もそうなれ。 -ガード!","썅! 아니야, 네가 가질 수 있는 건 전혀 없어! 경비병!!","Noten, als ik naar beneden ga, dan ben jij dat ook. Bewakers!!","Faen, hvis jeg går ned, så gjør du det også. Vakter!","Szlag, jeśli mam zginąć, to ty też. Straże!!","Porra, se eu vou morrer então você também vai. Guardas!!",,"Nebunie - dacă o iau la vale, atunci o să te iau cu mine. Gardieni!!","К чёрту — раз уж я сдохну, то и ты со мной. Стража!",,"Fındık, eğer ben batıyorsam, sen de batacaksın. Gardiyanlar!!" +ガード!","썅! 아니야, 네가 가질 수 있는 건 전혀 없어! 경비병!!","Noten, als ik naar beneden ga, dan ben jij dat ook. Bewakers!!","Faen, hvis jeg går ned, så gjør du det også. Vakter!","Szlag, jeśli mam zginąć, to ty też. Straże!!","Porra, se eu vou morrer então você também vai. Guardas!!",,"Nebunie - dacă o iau la vale, atunci o să te iau cu mine. Gardieni!!","К чёрту — раз уж я сдохну, то и ты со мной. Стража!",,"Nuts, om jag åker ner, så gör du det också. Vakter!","Fındık, eğer ben batıyorsam, sen de batacaksın. Gardiyanlar!!" "Business my ass. Help, guards, I've got a live one.",TXT_DLG_SCRIPT04_D21224_BUSIN,〃,,,"Do hajzlu s nabídkami. Pomoc, stráže, mám tu živého!","Skide være med forretningen! Hjælp, vagter, jeg har en indtrængende.","Scheiß' aufs Geschäft. Wärter, ich habe hier einen Eindringling.",,"«Intertraktadoj», kia feka ŝerco. Helpu min, gardistoj, estas viva ribelanto!","«Negocios» mis cojones. ¡Ayuda, guardias, tengo uno vivo!","«Negocios» las pelotas. ¡Ayuda, guardias, tengo uno vivo!","Ja paskat mitään kauppoja. Vartijat, apua. Tämä elää vielä.","Une affaire, mon cul! Gardes, à l'aide, j'en ai un de vivant ici!","Francokat üzlet. Segítség, őrök, itt van egy.","Alla faccia degli affari. Aiuto, guardie, c'è un intruso.","クソ野郎が、タダでは死なねえ。 助けてくれガード!イカれた奴がいる!","사적인 건 지랄하네. 경비병! 여기 노예가 도망친다! - \cy실례지만, 이거 좀 골때리겠는데?","Zaken mijn kont. Help, bewakers, ik heb een levende.","Drit i forretningene. Hjelp, vakter, jeg har en inntrenger!","Do dupy z takim biznesem. Pomocy, straże, mamy tu kogoś żywego.","Negócios coisa nenhuma. Guardas, me ajudem, tenho um vivo aqui.",,"Afaceri pe naiba. Ajutor, gardieni, am prins unul.","Дело дрянь. Стража, на помощь! Тут живой повстанец.",,"Kıçımın işi. Yardım edin gardiyanlar, canlı bir tane var." -"Ah, I got word from Macil that you'd be coming. I have a way to get you inside the power station, but it's on the risky side.",TXT_DLG_SCRIPT04_D22740_AHIGO,MAP04: Worner.,,,"Á, doneslo se mi od Macila, že přijdeš. Mám pro tebe cestu, jak se dostat do elektrárny, ale je trochu riskantní.","Jeg fik besked fra Macil om, at du ville komme. Jeg har en måde at få dig ind i kraftværket på, men det er lidt risikabelt.","Ah, Macil hat mir mitgeteilt, dass du kommst. Ich kenne einen Weg, um in das Werk reinzukommen, aber es ist etwas riskant.",,"Ha, Macil diris al mi, ke vi venus. Mi havas manieron meti vin en la centralon, sed ĝi estas riska.","Ah, Macil me ha dicho que ibas a venir. Tengo una forma de meterte en la central eléctrica, pero es algo arriesgada.","Ah, Macil me dijo que ibas a venir. Tengo una forma de meterte a la central eléctrica, pero es algo arriesgada.","Aah, sainkin Macililta viestin, että olisit tulossa. Minulla on keino saada sinut sisään voimalaitokseen, mutta se ei ole varmimmasta päästä.","Ah, Macil m'a prévenu que vous viendriez. J'ai une entrée dans la centrale pour vous mais elle est un peu risquée.","Ah, kaptam infót Maciltól hogy érkezni fogsz. Igazából van egy mód bejutni az erőműbe, de elég rizikós.","Ah, ho sentito da Macil che saresti arrivato. Ho un modo per farti entrare nella centrale energetica, ma è rischioso.","ああ、マシルから話は聞いたよ。 + \cy실례지만, 이거 좀 골때리겠는데?","Zaken mijn kont. Help, bewakers, ik heb een levende.","Drit i forretningene. Hjelp, vakter, jeg har en inntrenger!","Do dupy z takim biznesem. Pomocy, straże, mamy tu kogoś żywego.","Negócios coisa nenhuma. Guardas, me ajudem, tenho um vivo aqui.",,"Afaceri pe naiba. Ajutor, gardieni, am prins unul.","Дело дрянь. Стража, на помощь! Тут живой повстанец.",,"Affärer i min röv. Hjälp, vakter, jag har en levande.","Kıçımın işi. Yardım edin gardiyanlar, canlı bir tane var." +"Ah, I got word from Macil that you'd be coming. I have a way to get you inside the power station, but it's on the risky side.",TXT_DLG_SCRIPT04_D22740_AHIGO,MAP04: Worner.,,,"Á, doneslo se mi od Macila, že přijdeš. Mám pro tebe cestu, jak se dostat do elektrárny, ale je trochu riskantní.","Jeg fik besked fra Macil om, at du ville komme. Jeg har en måde at få dig ind i kraftværket på, men det er lidt risikabelt.","Ah, Macil hat mir mitgeteilt, dass du kommst. Ich kenne einen Weg, um in das Werk reinzukommen, aber es ist etwas riskant.",,"Ha, Macil diris al mi, ke vi estis venonta. Mi havas manieron meti vin en la centralon, sed ĝi estas riska.","Ah, Macil me ha dicho que ibas a venir. Tengo una forma de meterte en la central eléctrica, pero es algo arriesgada.","Ah, Macil me dijo que ibas a venir. Tengo una forma de meterte a la central eléctrica, pero es algo arriesgada.","Aah, sainkin Macililta viestin, että olisit tulossa. Minulla on keino saada sinut sisään voimalaitokseen, mutta se ei ole varmimmasta päästä.","Ah, Macil m'a prévenu que vous viendriez. J'ai une entrée dans la centrale pour vous mais elle est un peu risquée.","Ah, kaptam infót Maciltól hogy érkezni fogsz. Igazából van egy mód bejutni az erőműbe, de elég rizikós.","Ah, ho sentito da Macil che saresti arrivato. Ho un modo per farti entrare nella centrale energetica, ma è rischioso.","ああ、マシルから話は聞いたよ。 君を発電所に入れてやれるが -かなりリスキーな方法だぞ。","아! 마실 사령관님으로부터 당신이 여기로 온다는 소식을 들었습니다. 발전소로 깊숙이 향하는 지름길을 알고 있어요. 다만, 좀 위험하답니다.","Ah, ik heb van Macil gehoord dat je zou komen. Ik heb een manier om je in de centrale te krijgen, maar het is aan de riskante kant.","Jeg fikk beskjed fra Macil om at du ville komme. Jeg har en måte å få deg inn i kraftverket på, men det er risikabelt.","Ah, słyszałem od Macila, że przyjdziesz. Mam sposób, aby cię przedostać do środka elektrowni, ale jest to ryzykowne.","Ah, Macil me contou que você viria. Tenho um jeito de fazer você entrar na usina elétrica, mas é bem arriscado.",,"Ah, am primit știrea de la Macil că urma să vii. Am o cale de a te infiltra în uzină, dar e riscantă.","А-а, мне сообщили, что ты от Мэйсила. Я знаю способ проникнуть на станцию, но он довольно рискованный.",,Macil'den geleceğin haberini aldım. Seni güç istasyonuna sokmanın bir yolunu buldum ama biraz riskli. -I'll take my chances.,TXT_RPLY0_SCRIPT04_D22740_ILLTA,〃,,,Já to zkusím.,Jeg tager mine chancer.,Ich riskiere es.,,Mi povas preni sur min la riskon.,Puedo asumir el riesgo.,,Kokeilen onneani.,Je suis prêt à prendre ces risques.,Vállalom a kockázatot.,Correrò il rischio.,大丈夫だ。,그 정도야 각오하고 있습니다.,Ik neem mijn kansen.,Jeg tar sjansen.,Zaryzykuję.,Estou disposto a arriscar.,,Voi risca.,Я рискну.,,Şansımı deneyeceğim. +かなりリスキーな方法だぞ。","아! 마실 사령관님으로부터 당신이 여기로 온다는 소식을 들었습니다. 발전소로 깊숙이 향하는 지름길을 알고 있어요. 다만, 좀 위험하답니다.","Ah, ik heb van Macil gehoord dat je zou komen. Ik heb een manier om je in de centrale te krijgen, maar het is aan de riskante kant.","Jeg fikk beskjed fra Macil om at du ville komme. Jeg har en måte å få deg inn i kraftverket på, men det er risikabelt.","Ah, słyszałem od Macila, że przyjdziesz. Mam sposób, aby cię przedostać do środka elektrowni, ale jest to ryzykowne.","Ah, Macil me contou que você viria. Tenho um jeito de fazer você entrar na usina elétrica, mas é bem arriscado.",,"Ah, am primit știrea de la Macil că urma să vii. Am o cale de a te infiltra în uzină, dar e riscantă.","А-а, мне сообщили, что ты от Мэйсила. Я знаю способ проникнуть на станцию, но он довольно рискованный.",,"Macil berättade att du skulle komma. Jag har ett sätt att få in dig i kraftverket, men det är lite riskabelt.",Macil'den geleceğin haberini aldım. Seni güç istasyonuna sokmanın bir yolunu buldum ama biraz riskli. +I'll take my chances.,TXT_RPLY0_SCRIPT04_D22740_ILLTA,〃,,,Já to zkusím.,Jeg tager mine chancer.,Ich riskiere es.,,Mi povas preni sur min la riskon.,Puedo asumir el riesgo.,,Kokeilen onneani.,Je suis prêt à prendre ces risques.,Vállalom a kockázatot.,Correrò il rischio.,大丈夫だ。,그 정도야 각오하고 있습니다.,Ik neem mijn kansen.,Jeg tar sjansen.,Zaryzykuję.,Estou disposto a arriscar.,,Voi risca.,Я рискну.,,Jag tar mina chanser.,Şansımı deneyeceğim. "All right, I stole an I.D. from the corpse of some fool who fell into the reactor's coolant pit. --blat-- instant deep fry.",TXT_DLG_SCRIPT04_D24256_ALLRI,〃,,,"Tak dobře. Ukradl jsem identifikační kartu z mrtvoly nějakého chudáka, co spadl do reaktorové nádrže s chladivem. --Plesk--, okamžitě ho to upeklo.","Okay, jeg stjal et ID fra liget af et fjols, der faldt ned i reaktorens kølemiddelgrav. --blat-- øjeblikkelig friturestegning.","Alles klar. Ich habe hier die Identitätskarte von so 'nem Trottel, der in die Kühlanlage des Reaktors reingefallen ist. --platsch-- hat ihn schockgefrostet.",,"Bone. Mi ŝtelis la identigilon de la kadavro de stultulo, kiu falis en la malvarmigan truon de la reaktoro; «blat», tuje fritita.","Muy bien. He robado la identificación del cadáver de un inútil que cayó en el pozo refrigerante del reactor; «blat», frito al instante.","Muy bien. Me robé la identificación del cadáver de un inútil que se cayó al pozo refrigerante del reactor; «blat», frito al instante.","Hyvä on, varastin henkilötunnisteen joltain idiootilta, joka oli pudonnut reaktorin jäähdytyskuiluun. Pläts, pikauppopaisto.",Très vien. J'ai volé la carte d'identité d'un idiot qui est tombé dans le puits de refroidissement du réacteur. Plouf! Instantanément frit.,"Rendben van, elcsórtam egy szerencsétlen hullájáról az igazolványt aki beleesett a reaktor hűtőfolyadékába. --placcs-- rögtön ropogósra sült.","Molto bene allora, ho rubato una tessera d'identificazione da uno sciocco che è caduto nel pozzo refrigerante del reattore. --blat-- fritto instantaneamente.","わかった、このIDを受け取れ。 これはリアクターの冷却炉に落ちた間抜けが 持っていたものだ。 -バチッ!と一瞬で黒焦げになっちまったよ。",좋습니다. 이 신분증은 조심하지도 못하고 냉각 회로로 떨어진 한 불쌍한 녀석에게서 훔쳐온 겁니다. “뿌직”! 완전히 터졌죠.,"Oké, ik heb een I.D. gestolen van het lijk van een dwaas die in de koelvloeistofput van de reactor is gevallen. --Blat-- onmiddellijk frituren.",Jeg stjal et ID-kort fra liket til en idiot som falt ned i reaktorens kjølegrop. --...blat... øyeblikkelig frityrsteking.,"Dobra, ukradłem identyfikator ze zwłok pewnego durnia, który wpadł do chłodnicy reaktora. --puf-- i się usmażył.",Beleza. Eu roubei uma identificação do cadáver de algum otário que caiu no poço de refrigeração do reator. Pluft! Frito na hora. ,,Bine. Am furat un card de acces de pe cadavrul unui nătăfleț care a căzut în groapa sistemului de răcire al reactorului. --pleoșc--făcut scrum instant.,"Очень хорошо. Я украл удостоверение с трупа одного идиота, который упал прямо в охлаждающий бассейн реактора. «Шмяк!» — моментальное прожаривание до костей.",,"Pekala, reaktörün soğutucu çukuruna düşen bir aptalın cesedinden kimliğini çaldım. --Anında derin kızartma." -What should I do once I'm in?,TXT_RPLY0_SCRIPT04_D24256_WHATS,〃,,,Co mám udělat uvnitř?,"Hvad skal jeg gøre, når jeg er inde?","Was soll ich machen, wenn ich drin bin?",,Kion mi faru post mia eniro?,¿Qué debo hacer una vez dentro?,¿Qué hago una vez adentro?,Mitä teen päästyäni sisään?,Qu'est ce que je fais une fois que je suis rentré?,Mit tegyek amikor bejutottam?,E cosa devo fare una volta dentro?,中に入ったらどうすればいい?,그곳으로 들어간 후엔 뭘 해야 하죠?,Wat moet ik doen als ik eenmaal binnen ben?,Hva skal jeg gjøre når jeg er inne?,Co mam zrobić jak wejdę?,O que devo fazer depois de entrar?,,Ce trebuie să fac odată ce ajung în interior?,И что дальше?,,İçeri girdiğimde ne yapmalıyım? -"Tell whoever asks that you're the replacement worker for Mr. Crispy. It's just dumb enough to work. Oh, and you might want to check out the storeroom that's right above us.",TXT_DLG_SCRIPT04_D25772_TELLW,〃,,,"Řekni komukoliv, kdo se zeptá, že jsi náhrada za pana Pečínku. Je to dost pitomé na to, aby to fungovalo. Jo, a možná bys mohl mít zájem podívat se do skladu, který je přímo nad námi.","Fortæl dem, der spørger, at du er afløseren for Mr Crispy. Det er lige dumt nok til at virke. Åh, og du vil måske tjekke lagerrummet lige over os.","Sage jedem, der dich fragt, dass du der Ersatz für Mister Crispy bist. Es ist idiotisch genug, um zu funktionieren. Oh, du solltest auch mal einen Blick in den Lagerraum auf der oberen Etage werfen.",,"Diru al tiu, kiu demandos, ke vi estas la anstataŭanto de la S-ro Krakulo; li estas sufiĉe stulta por kredi tion. Ha, kaj vi eble volas trarigardi la stokejon super ni.","A quien pregunte, dile que eres el sustituto del Sr. Crujiente; es lo bastante estúpido como para que funcione. Ah, y puede que quieras revisar el cuarto de almacenamiento que está justo sobre nosotros.",,"Jos joku kysyy, kerro olevasi herra Crispyn korvaaja. Saattaa olla jo niin tyhmä idea, että jopa toimii. Ai niin, ja saattanet haluta vilkaista varastohuonetta, joka sijaitsee suoraan yläpuolellamme.","Expliquez à qui veut l'entrendre que vous remplacez Mr. Frite. C'et suffisamment stupide pour marcher. Oh, et pensez à fouiller la salle de stockage au dessus de nous.","Akárki is kérdezi, mondd azt, hogy Kétszersült úr helyettesítése vagy. Akkora böszmeség, hogy még müködhet is. Ja, és érdemes lenne körbenézned a fölöttünk levő tárolóban.","Basta che tu dica a chiunque lo chieda che tu sei il rimpiazzo per il Signor Fritto. È abbastanza stupido da funzionare. Ah, e potrebbe anche interessarti il deposito che si trova proprio sopra di noi.","誰かに聞かれたら、クリスピーの代わりに来た +バチッ!と一瞬で黒焦げになっちまったよ。",좋습니다. 이 신분증은 조심하지도 못하고 냉각 회로로 떨어진 한 불쌍한 녀석에게서 훔쳐온 겁니다. “뿌직”! 완전히 터졌죠.,"Oké, ik heb een I.D. gestolen van het lijk van een dwaas die in de koelvloeistofput van de reactor is gevallen. --Blat-- onmiddellijk frituren.",Jeg stjal et ID-kort fra liket til en idiot som falt ned i reaktorens kjølegrop. --...blat... øyeblikkelig frityrsteking.,"Dobra, ukradłem identyfikator ze zwłok pewnego durnia, który wpadł do chłodnicy reaktora. --puf-- i się usmażył.",Beleza. Eu roubei uma identificação do cadáver de algum otário que caiu no poço de refrigeração do reator. Pluft! Frito na hora. ,,Bine. Am furat un card de acces de pe cadavrul unui nătăfleț care a căzut în groapa sistemului de răcire al reactorului. --pleoșc--făcut scrum instant.,"Очень хорошо. Я украл удостоверение с трупа одного идиота, который упал прямо в охлаждающий бассейн реактора. «Шмяк!» — моментальное прожаривание до костей.",,Jag stal ett ID från en dåre som föll ner i reaktorns kylvattengrop. --blat-- omedelbar fritering.,"Pekala, reaktörün soğutucu çukuruna düşen bir aptalın cesedinden kimliğini çaldım. --Anında derin kızartma." +What should I do once I'm in?,TXT_RPLY0_SCRIPT04_D24256_WHATS,〃,,,Co mám udělat uvnitř?,"Hvad skal jeg gøre, når jeg er inde?","Was soll ich machen, wenn ich drin bin?",,Kion mi faru post mia eniro?,¿Qué debo hacer una vez dentro?,¿Qué hago una vez adentro?,Mitä teen päästyäni sisään?,Qu'est ce que je fais une fois que je suis rentré?,Mit tegyek amikor bejutottam?,E cosa devo fare una volta dentro?,中に入ったらどうすればいい?,그곳으로 들어간 후엔 뭘 해야 하죠?,Wat moet ik doen als ik eenmaal binnen ben?,Hva skal jeg gjøre når jeg er inne?,Co mam zrobić jak wejdę?,O que devo fazer depois de entrar?,,Ce trebuie să fac odată ce ajung în interior?,И что дальше?,,Vad ska jag göra när jag väl är inne?,İçeri girdiğimde ne yapmalıyım? +"Tell whoever asks that you're the replacement worker for Mr. Crispy. It's just dumb enough to work. Oh, and you might want to check out the storeroom that's right above us.",TXT_DLG_SCRIPT04_D25772_TELLW,〃,,,"Řekni komukoliv, kdo se zeptá, že jsi náhrada za pana Pečínku. Je to dost pitomé na to, aby to fungovalo. Jo, a možná bys mohl mít zájem podívat se do skladu, který je přímo nad námi.","Fortæl dem, der spørger, at du er afløseren for Mr Crispy. Det er lige dumt nok til at virke. Åh, og du vil måske tjekke lagerrummet lige over os.","Sage jedem, der dich fragt, dass du der Ersatz für Mister Crispy bist. Es ist idiotisch genug, um zu funktionieren. Oh, du solltest auch mal einen Blick in den Lagerraum auf der oberen Etage werfen.",,"Diru al tiu, kiu demandos, ke vi estas la anstataŭanto de la S-ro Krakulo; li estas sufiĉe stulta por kredi tion. Ha, kaj vi eble volas trarigardi la deponejon super ni.","A quien pregunte, dile que eres el sustituto del Sr. Crujiente; es lo bastante estúpido como para que funcione. Ah, y puede que quieras revisar el cuarto de almacenamiento que está justo sobre nosotros.",,"Jos joku kysyy, kerro olevasi herra Crispyn korvaaja. Saattaa olla jo niin tyhmä idea, että jopa toimii. Ai niin, ja saattanet haluta vilkaista varastohuonetta, joka sijaitsee suoraan yläpuolellamme.","Expliquez à qui veut l'entrendre que vous remplacez Mr. Frite. C'et suffisamment stupide pour marcher. Oh, et pensez à fouiller la salle de stockage au dessus de nous.","Akárki is kérdezi, mondd azt, hogy Kétszersült úr helyettesítése vagy. Akkora böszmeség, hogy még müködhet is. Ja, és érdemes lenne körbenézned a fölöttünk levő tárolóban.","Basta che tu dica a chiunque lo chieda che tu sei il rimpiazzo per il Signor Fritto. È abbastanza stupido da funzionare. Ah, e potrebbe anche interessarti il deposito che si trova proprio sopra di noi.","誰かに聞かれたら、クリスピーの代わりに来た と言え。皆疑うことなく信じるだろうさ。 あと、上の階にある倉庫も行けるなら 見てみた方がいいぞ。","누군가가 물어보면 통구이 씨의 후임으로 들어왔다고 하시면 됩니다. 별로 어려운 일은 아닐 거에요. 아, 그리고 우리 바로 위에 있는 창고도 한번 확인해보세요. - \cy으음. 왠지 무기 같은데. 화력이야 더 많으면 좋지.","Vertel degene die vraagt of jij de vervanger bent van Mr. Crispy. Het is net dom genoeg om te werken. Oh, en misschien wilt je eens kijken naar het magazijn dat vlak boven ons is.",Si til alle som spør at du er vikar for Mr. Crispy. Det er dumt nok til å fungere. Og du vil kanskje sjekke lageret som er rett over oss.,"Jak ktoś się będzie pytał, powiedz, że przyszedłeś na zastępstwo za Pana Chrupka. Jest to tak głupie, ale zadziała. Oh, i na pewno chciałbyś sprawdzić co jest w magazynie nad nami.","Diga pra quem perguntar que você é o substituto do Sr. Fritinho. É idiota o suficiente pra funcionar. Ah, e talvez você queira dar uma olhada no depósito lá em cima.",,"Spune-i oricui te întreabă că ești înlocuitorul dl. Crispy. E suficient de stupid cât să funcționeze. Ah, și probabil vrei să verifici depozitul care se află chiar deasupra noastră.","Говори всем, что тебя прислали заменить г-на Поджаренного. Это так глупо, что должно сработать. И ещё, наверное, тебе захочется наведаться на склад, прямо над нами.",,"Soran kişiye Bay Çıtır'ın yerine gelen işçi olduğunu söyle. İşe yarayacak kadar aptalca. Oh, ve hemen üstümüzdeki depoya bakmak isteyebilirsin." -Boy I hope this I.D. Works.,TXT_RPLY0_SCRIPT04_D25772_BOYIH,〃,,,Snad tahle karta funguje.,"Jeg håber, at det her ID virker.","Mann, ich hoffe, dass diese Karte auch funktioniert.",,Espereble ĉi tiu identigilo funkcios.,"Vaya, espero que esta identificación funcione.",,"Toivon todellakin, että tämä tunniste toimii.","Eh bien, j'espère que cette carte fonctionnera.",Merem remélni hogy ez az igazolvány működni fog.,Spero proprio che questo tesserino funzioni.,このIDで上手くいけばいいが。,이 방법이 통했으면 좋겠네요.,"Jongen, ik hoop dat deze I.D. werkt.",Jeg håper denne legitimasjonen virker.,"Mam nadzieję, że ten identyfikator zadziała.","Olha, espero que esta identificação funcione.",,Mamă frate sper ca legitimația să funcționeze.,"Ох. Надеюсь, это сработает.",,Umarım bu kimlik işe yarar. + \cy으음. 왠지 무기 같은데. 화력이야 더 많으면 좋지.","Vertel degene die vraagt of jij de vervanger bent van Mr. Crispy. Het is net dom genoeg om te werken. Oh, en misschien wilt je eens kijken naar het magazijn dat vlak boven ons is.",Si til alle som spør at du er vikar for Mr. Crispy. Det er dumt nok til å fungere. Og du vil kanskje sjekke lageret som er rett over oss.,"Jak ktoś się będzie pytał, powiedz, że przyszedłeś na zastępstwo za Pana Chrupka. Jest to tak głupie, ale zadziała. Oh, i na pewno chciałbyś sprawdzić co jest w magazynie nad nami.","Diga pra quem perguntar que você é o substituto do Sr. Fritinho. É idiota o suficiente pra funcionar. Ah, e talvez você queira dar uma olhada no depósito lá em cima.",,"Spune-i oricui te întreabă că ești înlocuitorul dl. Crispy. E suficient de stupid cât să funcționeze. Ah, și probabil vrei să verifici depozitul care se află chiar deasupra noastră.","Говори всем, что тебя прислали заменить г-на Поджаренного. Это так глупо, что должно сработать. И ещё, наверное, тебе захочется наведаться на склад, прямо над нами.",,"Säg till den som frågar att du är ersättare för Mr Crispy. Det är tillräckligt dumt för att fungera. Åh, och du kanske vill kolla in förrådet som ligger precis ovanför oss.","Soran kişiye Bay Çıtır'ın yerine gelen işçi olduğunu söyle. İşe yarayacak kadar aptalca. Oh, ve hemen üstümüzdeki depoya bakmak isteyebilirsin." +Boy I hope this I.D. Works.,TXT_RPLY0_SCRIPT04_D25772_BOYIH,〃,,,Snad tahle karta funguje.,"Jeg håber, at det her ID virker.","Mann, ich hoffe, dass diese Karte auch funktioniert.",,Espereble ĉi tiu identigilo funkcios.,"Vaya, espero que esta identificación funcione.",,"Toivon todellakin, että tämä tunniste toimii.","Eh bien, j'espère que cette carte fonctionnera.",Merem remélni hogy ez az igazolvány működni fog.,Spero proprio che questo tesserino funzioni.,このIDで上手くいけばいいが。,이 방법이 통했으면 좋겠네요.,"Jongen, ik hoop dat deze I.D. werkt.",Jeg håper denne legitimasjonen virker.,"Mam nadzieję, że ten identyfikator zadziała.","Olha, espero que esta identificação funcione.",,Mamă frate sper ca legitimația să funcționeze.,"Ох. Надеюсь, это сработает.",,Jag hoppas att det här ID-kortet fungerar.,Umarım bu kimlik işe yarar. "Get out of here, unless you want to end up Mr. Dead.",TXT_DLG_SCRIPT04_D27288_GETOU,〃,,,"Vypadni odsud, leda že by z tebe chtěl být pan Mrtvý.","Forsvind herfra, medmindre du vil ende som Mr. Død.","Und nun verschwinde, wenn du nicht als Mister Tot enden willst.",,"Foriru, krom se vi volas iĝi S-ro Mortinto.","Ya vete, a menos que quieras ser el Sr. Muerto.",,"Ala liikkua, ellet sitten mieluummin halua ryhtyä herra Kalmon korvaajaksi.","Sortez de là, sauf si vous voulez être Mr. Mort.","Na húzz innen, ha nem akarod úgy végezni mint Halott úr.","Ora ti conviene andare, a meno che tu non voglia diventare Signor Morto.","ここを離れた方がいい、君がミスターポックリに -成らない為に。",어서 가세요. 여기 계속 있다간 고인이 될 겁니다.,"Maak dat je wegkomt, tenzij je wilt eindigen als meneer de Dood.","Kom deg ut herfra, med mindre du vil ende opp som Mr. Død.","Idź stąd, jeśli nie chcesz skończyć jako Pan Truposz.","Saia daqui, a não ser que você queria comer capim pela raiz.",,"Valea de aici, dacă nu vrei să devii dl. Mort.","Уходи сейчас же, если не хочешь стать «г-ном покойником».",,Sonunun Bay Ölü olmasını istemiyorsan git buradan. +成らない為に。",어서 가세요. 여기 계속 있다간 고인이 될 겁니다.,"Maak dat je wegkomt, tenzij je wilt eindigen als meneer de Dood.","Kom deg ut herfra, med mindre du vil ende opp som Mr. Død.","Idź stąd, jeśli nie chcesz skończyć jako Pan Truposz.","Saia daqui, a não ser que você queria comer capim pela raiz.",,"Valea de aici, dacă nu vrei să devii dl. Mort.","Уходи сейчас же, если не хочешь стать «г-ном покойником».",,"Försvinn härifrån, om du inte vill bli herr Död.",Sonunun Bay Ölü olmasını istemiyorsan git buradan. "Hey, leave me alone. If they catch us wasting time we get dead, or extra work.",TXT_DLG_SCRIPT04_D28804_HEYLE,MAP04: Warehouse → Dock Worker.,,,"Hej, nech mě bejt. Jestli nás chytěj ztrácet čas, dostanem kulku, nebo práci navíc.","Hey, lad mig være. Hvis de fanger os i at spilde tiden, bliver vi dræbt eller får ekstra arbejde.","Lass mich in Ruhe. Wenn sie uns beim Quatschen erwischen, sind wir entweder beide tot oder kriegen Extraarbeit aufgebrummt.",,"He, ne distru min. Se ili vidas, ke ni perdas tempon, ni estos mortigitaj... aŭ kun plia laboro.","Oye, déjame en paz. Si nos pillan perdiendo el tiempo nos matan... o nos dan más trabajo.","Oye, déjame en paz. Si nos ven perdiendo el tiempo nos matan... o nos dan más trabajo.","Hei, jätä minut rauhaan. Jos ne äkkäävät meidän tuhlaavan aikaa, saamme kuolla, tai lisää työtä.","Hé, foutez-moi la paix, si ils nous attrappent ici à nous tourner les pouces, on y passe où c'est le travail forcé.","Héj, hagyj engem békén. Ha meglátják, hogy itt lopjuk a napot, akkor vagy elintéznek vagy túlórát sóznak ránk.","Ehi, lasciami stare. Se ci beccano a perdere tempo ci ammazzano, o ci danno lavoro extra.","話しかけないでくれ、 -奴等にバレたら処分されるか、残業させられる。","이봐, 나 좀 내버려 둬. 우리가 이렇게 농땡이 치는 걸 들키면 둘 다 죽는다고... 아님 추가 근무를 받는다든지!","Hé, laat me met rust. Als ze ons betrappen op tijdverspilling worden we dood, of extra werk.","Hei, la meg være i fred. Hvis de tar oss i å kaste bort tid, blir vi drept, eller får ekstraarbeid.","Hej, zostaw mnie. Jeśli nas przyłapią na marnowaniu czasu to nas zabiją lub dadzą więcej pracy.","Ei, me deixe em paz. Se eles pegarem a gente fazendo corpo mole, a gente vai morrer ou receber trabalho extra.",,"Hei, lasă-mă în pace. Dacă ne prind pierzând vremea fie primim muncă în plus, fie moarte.","Эй, оставь меня в покое. Если они увидят, что мы болтаем, нас убьют, или добавят работы.",,"Hey, beni yalnız bırak. Bizi boşa zaman harcarken yakalarlarsa ya ölürüz ya da fazladan iş alırız." -"Such pressure, at this rate we'll be back to normal shifts soon. We're pumping tons of power to the castle and I'm almost finished logging those new weapons.",TXT_DLG_SCRIPT04_D30320_SUCHP,MAP04: Reactor Core → Northern alarm green door → Level 2 door,,,"Takový tlak, tímhle tempem brzy budeme zase pracovat normální směny. Lijeme takové množství energie do hradu a já už jsem skoro hotov se zapisováním těch nových zbraní.","Sikke et pres, i dette tempo er vi snart tilbage på normale vagter. Vi pumper tonsvis af strøm til slottet, og jeg er næsten færdig med at logge de nye våben.","So viel Druck. Wenn es so weiter geht, gibt es bald wieder normale Schichten. Wir pumpen Tonnen von Energie in die Burg und ich habe die neuen Waffen fast alle verstaut.",,"Kia premo; laŭ ĉi tia kadenco, la normalaj deĵoroj baldaŭ revenos. Ni pumpas tunojn da energio al la kastelo kaj mi preskaŭ finis registri tiujn novajn armilojn.","Cuanta presión, a este ritmo volveremos pronto a turnos normales. Estamos dándole toneladas de energía al castillo y ya casi termino de registrar esas nuevas armas.","Cuanta presión, a este ritmo vamos a volver pronto a turnos normales. Estamos dándole toneladas de energía al castillo y ya casi termino de registrar esas nuevas armas.","Kovat paineet. Tällä tahdilla palaamme tuota pikaa normaaleihin työvuoroihin. Pumppaamme rutkasti voimaa linnaan, ja olen melkein saanut kirjattua uudet aseet.","Quelle pression. Si ça continue, on devrait revenir au rhytme de travail de base. On pompe des tonnes d'énergies pour le château et j'ai presque fini d'enregistrer toutes ces nouvelles armes.","Micsoda nyomás, ezzel az irammal vissza fogunk tudni térni a régi műszakba. Iszonyat áramot pumpálunk a kastélyba, és majdnem végeztem az új fegyverek nyílvántartásával. is.","Che pressione, a questo punto ritorneremo presto ai normali turni di lavoro. Stiamo indirizzando molta energia verso il castello, e ho quasi finito di catalogare quelle nuove armi.","この圧力、この速さならすぐ通常のシフトに +奴等にバレたら処分されるか、残業させられる。","이봐, 나 좀 내버려 둬. 우리가 이렇게 농땡이 치는 걸 들키면 둘 다 죽는다고... 아님 추가 근무를 받는다든지!","Hé, laat me met rust. Als ze ons betrappen op tijdverspilling worden we dood, of extra werk.","Hei, la meg være i fred. Hvis de tar oss i å kaste bort tid, blir vi drept, eller får ekstraarbeid.","Hej, zostaw mnie. Jeśli nas przyłapią na marnowaniu czasu to nas zabiją lub dadzą więcej pracy.","Ei, me deixe em paz. Se eles pegarem a gente fazendo corpo mole, a gente vai morrer ou receber trabalho extra.",,"Hei, lasă-mă în pace. Dacă ne prind pierzând vremea fie primim muncă în plus, fie moarte.","Эй, оставь меня в покое. Если они увидят, что мы болтаем, нас убьют, или добавят работы.",,Lämna mig ifred. Om de kommer på oss med att slösa tid blir vi dödade eller får extra arbete.,"Hey, beni yalnız bırak. Bizi boşa zaman harcarken yakalarlarsa ya ölürüz ya da fazladan iş alırız." +"Such pressure, at this rate we'll be back to normal shifts soon. We're pumping tons of power to the castle and I'm almost finished logging those new weapons.",TXT_DLG_SCRIPT04_D30320_SUCHP,MAP04: Reactor Core → Northern alarm green door → Level 2 door,,,"Takový tlak, tímhle tempem brzy budeme zase pracovat normální směny. Lijeme takové množství energie do hradu a já už jsem skoro hotov se zapisováním těch nových zbraní.","Sikke et pres, i dette tempo er vi snart tilbage på normale vagter. Vi pumper tonsvis af strøm til slottet, og jeg er næsten færdig med at logge de nye våben.","So viel Druck. Wenn es so weiter geht, gibt es bald wieder normale Schichten. Wir pumpen Tonnen von Energie in die Burg und ich habe die neuen Waffen fast alle verstaut.",,"Kia premo. Laŭ ĉi tia kadenco, la normalaj deĵoroj baldaŭ revenos. Ni pumpas tunojn da energio al la kastelo kaj mi preskaŭ finis registri tiujn novajn armilojn.",Cuanta presión. A este ritmo volveremos pronto a turnos normales. Estamos dándole toneladas de energía al castillo y ya casi termino de registrar esas nuevas armas.,Cuanta presión. A este ritmo vamos a volver pronto a turnos normales. Estamos dándole toneladas de energía al castillo y ya casi termino de registrar esas nuevas armas.,"Kovat paineet. Tällä tahdilla palaamme tuota pikaa normaaleihin työvuoroihin. Pumppaamme rutkasti voimaa linnaan, ja olen melkein saanut kirjattua uudet aseet.","Quelle pression. Si ça continue, on devrait revenir au rhytme de travail de base. On pompe des tonnes d'énergies pour le château et j'ai presque fini d'enregistrer toutes ces nouvelles armes.","Micsoda nyomás, ezzel az irammal vissza fogunk tudni térni a régi műszakba. Iszonyat áramot pumpálunk a kastélyba, és majdnem végeztem az új fegyverek nyílvántartásával. is.","Che pressione, a questo punto ritorneremo presto ai normali turni di lavoro. Stiamo indirizzando molta energia verso il castello, e ho quasi finito di catalogare quelle nuove armi.","この圧力、この速さならすぐ通常のシフトに 戻るだろう。私達は城へ大量の電気を供給して -いるし、新しい武器の切り出しも殆ど済んだ。","이런 압박감 속에 있다가는 다시 일반 교대 조로 복귀될 것 같아. 우린 지금 성 쪽으로 막대한 동력을 공급하고 있고, 난 저 신무기에 관한 일지를 거의 다 썼어.","Zulke druk, in dit tempo zullen we snel weer terug zijn bij normale diensten. We pompen tonnen energie naar het kasteel en ik ben bijna klaar met het kappen van die nieuwe wapens.","Med dette presset er vi snart tilbake til normale skift. Vi pumper masse strøm til slottet, og jeg er nesten ferdig med de nye våpnene.","Tyle nacisku, w ten sposób wkrótce będziemy mieli znów normalne zmiany. Pompujemy tony energii do zamku, a ja prawie skończyłem załadowywać te nowe bronie.",Quanta pressão. Desse jeito voltaremos a fazer turnos normais logo. Estamos mandando bastante energia para o castelo e estou quase terminando de registrar essas novas armas.,,"Ce presiuni, în ritmul ăsta o să revenim la turele obișnuite curând. Pompăm o tonă de energie către castel și aproape că am terminat să înregistrez aceste arme noi.","Такая нагрузка! С такими темпами мы вернёмся к нормальному графику совсем скоро. Мы направляем массу энергии в замок, и я почти закончил с погрузкой нового оружия.",,"Ne baskı ama, bu gidişle yakında normal vardiyaya döneceğiz. Kaleye tonlarca güç pompalıyoruz ve yeni silahları kaydetmeyi neredeyse bitirdim." -Weapons?,TXT_RPLY0_SCRIPT04_D30320_WEAPO,〃,,,Zbraní?,Våben?,Waffen?,,Ĉu armiloj?,¿Armas?,,Aseet?,Des armes?,Fegyverek?,Armi?,武器?,신무기?,Wapens?,Våpen?,Bronie?,Armas?,,Arme?,Оружия?,,Silahlar mı? +いるし、新しい武器の切り出しも殆ど済んだ。","이런 압박감 속에 있다가는 다시 일반 교대 조로 복귀될 것 같아. 우린 지금 성 쪽으로 막대한 동력을 공급하고 있고, 난 저 신무기에 관한 일지를 거의 다 썼어.","Zulke druk, in dit tempo zullen we snel weer terug zijn bij normale diensten. We pompen tonnen energie naar het kasteel en ik ben bijna klaar met het kappen van die nieuwe wapens.","Med dette presset er vi snart tilbake til normale skift. Vi pumper masse strøm til slottet, og jeg er nesten ferdig med de nye våpnene.","Tyle nacisku, w ten sposób wkrótce będziemy mieli znów normalne zmiany. Pompujemy tony energii do zamku, a ja prawie skończyłem załadowywać te nowe bronie.",Quanta pressão. Desse jeito voltaremos a fazer turnos normais logo. Estamos mandando bastante energia para o castelo e estou quase terminando de registrar essas novas armas.,,"Ce presiuni, în ritmul ăsta o să revenim la turele obișnuite curând. Pompăm o tonă de energie către castel și aproape că am terminat să înregistrez aceste arme noi.","Такая нагрузка! С такими темпами мы вернёмся к нормальному графику совсем скоро. Мы направляем массу энергии в замок, и я почти закончил с погрузкой нового оружия.",,"Vilken press, i den här takten är vi snart tillbaka på normala skift. Vi pumpar tonvis med ström till slottet och jag är nästan klar med att logga de nya vapnen.","Ne baskı ama, bu gidişle yakında normal vardiyaya döneceğiz. Kaleye tonlarca güç pompalıyoruz ve yeni silahları kaydetmeyi neredeyse bitirdim." +Weapons?,TXT_RPLY0_SCRIPT04_D30320_WEAPO,〃,,,Zbraní?,Våben?,Waffen?,,Ĉu armiloj?,¿Armas?,,Aseet?,Des armes?,Fegyverek?,Armi?,武器?,신무기?,Wapens?,Våpen?,Bronie?,Armas?,,Arme?,Оружия?,,Vapen?,Silahlar mı? "What do you think, we're backed up on socks?",TXT_DLG_SCRIPT04_D31836_WHATD,〃,,,"Co si myslíš, že ve zbrojnici máme ponožky?","Hvad tror du, vi er bagud med sokker?","Was dachtest du denn, glaubst du wir verteidigen uns mit Socken?",,Kion vi pensas? Ĉu ke ni agos per ŝtrumpetoj?,"¿Qué crees?, ¿que vamos con calcetines?","¿Qué crees?, ¿que vamos con medias o calcetines?","No mitä luulet meidän varastoineen, sukkia?",Vous croyez quoi? Qu'on a un surplus de chausettes?,"Mit gondolsz, zoknikkal vagyunk felfegyverkezve?","E che pensi, che ci difendiamo con dei calzini?",どう思う、ズボンがずり落ちないか?,"무슨 생각해? 양말 더 지급 받는 거? - \cy쉬운 일은 아니겠지만, 일단 한번 해보자고.","Wat denk je, dat we op sokken staan?","Hva tror du, at vi har sokker?","Co ty myślisz, że wysyłamy skarpetki?","Ora, você acha que usamos só as nossas meias?",,"Ce crezi, că suntem apărați pe șosete?","А ты думал, мы носки грузим?",,"Ne düşünüyorsun, çorapları yedekledik mi?" -What kind of weapons?,TXT_RPLY0_SCRIPT04_D31836_WHATK,〃,,,Jaké zbraně?,Hvilken slags våben?,Was für Waffen?,,Kiu speco de armiloj?,¿Qué clase de armas?,,Minkälaisia aseita?,Quel type d'armes?,Miféle fegyverek?,Che tipo di armi?,どんな武器だ?,어떤 신무기?,Wat voor wapens?,Hva slags våpen?,Jakie bronie?,Que tipo de armas?,,Ce fel de arme?,Какое оружие?,,Ne tür silahlar? -Are you deaf? I just told you how busy I am. Get back to work.,TXT_DLG_SCRIPT04_D33352_AREYO,〃,,,"Jsi hluchý? Už jsem ti řekl, jak jsem zaneprázdněný. Vrať se do práce.","Er du døv? Jeg har lige fortalt dig, hvor travlt jeg har. Kom tilbage til arbejdet.","Bist du taub? Ich hab dir dock gerade gesagt, wie beschäftigt ich bin. Geh zurück an die Arbeit.",,"Ĉu vi estas surda? Mi ĵus diris, kiel okupata mi estas. Reiru al via laboro.",¿Estás sordo? Ya te he dicho lo ocupado que estoy. Vuelve al trabajo.,¿Estás sordo? Ya te dije lo ocupado que estoy. Vuelve al trabajo.,"Kuuroko olet? Juurihan kerroin, kuinka kiire minulla on. Mene takaisin töihisi.","Vous êtes sourd? Je viens de vous dire que je suis occupé, retournez au travail!",Süket vagy? Most mondtam el mennyire elfoglalt vagyok. Húzz vissza dolgozni!,Ma sei sordo? Ti ho appena detto quanto sono occupato. Torna al lavoro.,難聴か? 私は、忙しい、から、仕事に、戻れ。,귀머거리야? 조금 전에 내가 얼마나 바쁜지 설명 했을 텐데? 일이나 해.,Ben je doof? Ik heb je net verteld hoe druk ik het heb. Ga terug aan het werk.,Er du døv? Jeg sa nettopp hvor opptatt jeg er. Tilbake til arbeidet.,"Głuchy jesteś? Mówiłem ci, że jestem zajęty. Wracaj do pracy.",Você é surdo? Já te disse que estou bem ocupado. Volte ao trabalho.,,Ești surd? Tocmai ți-am spus că sunt ocupat. Întoarce-te la muncă.,"Ты глухой, что ли? Я же сказал тебе, что я занят. Иди работать!",,Sağır mısın sen? Sana ne kadar meşgul olduğumu söyledim. İşinin başına dön. + \cy쉬운 일은 아니겠지만, 일단 한번 해보자고.","Wat denk je, dat we op sokken staan?","Hva tror du, at vi har sokker?","Co ty myślisz, że wysyłamy skarpetki?","Ora, você acha que usamos só as nossas meias?",,"Ce crezi, că suntem apărați pe șosete?","А ты думал, мы носки грузим?",,"Vad tror du, vi har inte tillräckligt med strumpor?","Ne düşünüyorsun, çorapları yedekledik mi?" +What kind of weapons?,TXT_RPLY0_SCRIPT04_D31836_WHATK,〃,,,Jaké zbraně?,Hvilken slags våben?,Was für Waffen?,,Kiu speco de armiloj?,¿Qué clase de armas?,,Minkälaisia aseita?,Quel type d'armes?,Miféle fegyverek?,Che tipo di armi?,どんな武器だ?,어떤 신무기?,Wat voor wapens?,Hva slags våpen?,Jakie bronie?,Que tipo de armas?,,Ce fel de arme?,Какое оружие?,,Vilken typ av vapen?,Ne tür silahlar? +Are you deaf? I just told you how busy I am. Get back to work.,TXT_DLG_SCRIPT04_D33352_AREYO,〃,,,"Jsi hluchý? Už jsem ti řekl, jak jsem zaneprázdněný. Vrať se do práce.","Er du døv? Jeg har lige fortalt dig, hvor travlt jeg har. Kom tilbage til arbejdet.","Bist du taub? Ich hab dir dock gerade gesagt, wie beschäftigt ich bin. Geh zurück an die Arbeit.",,"Ĉu vi estas surda? Mi ĵus diris, kiel okupata mi estas. Reiru al via laboro.",¿Estás sordo? Ya te he dicho lo ocupado que estoy. Vuelve al trabajo.,¿Estás sordo? Ya te dije lo ocupado que estoy. Vuelve al trabajo.,"Kuuroko olet? Juurihan kerroin, kuinka kiire minulla on. Mene takaisin töihisi.","Vous êtes sourd? Je viens de vous dire que je suis occupé, retournez au travail!",Süket vagy? Most mondtam el mennyire elfoglalt vagyok. Húzz vissza dolgozni!,Ma sei sordo? Ti ho appena detto quanto sono occupato. Torna al lavoro.,難聴か? 私は、忙しい、から、仕事に、戻れ。,귀머거리야? 조금 전에 내가 얼마나 바쁜지 설명 했을 텐데? 일이나 해.,Ben je doof? Ik heb je net verteld hoe druk ik het heb. Ga terug aan het werk.,Er du døv? Jeg sa nettopp hvor opptatt jeg er. Tilbake til arbeidet.,"Głuchy jesteś? Mówiłem ci, że jestem zajęty. Wracaj do pracy.",Você é surdo? Já te disse que estou bem ocupado. Volte ao trabalho.,,Ești surd? Tocmai ți-am spus că sunt ocupat. Întoarce-te la muncă.,"Ты глухой, что ли? Я же сказал тебе, что я занят. Иди работать!",,Är du döv? Jag berättade precis hur upptagen jag är. Fortsätt jobba.,Sağır mısın sen? Sana ne kadar meşgul olduğumu söyledim. İşinin başına dön. Who are you? Only clearance level two personnel are permitted in this area.,TXT_DLG_SCRIPT04_D34868_WHOAR,MAP04: Reactor Core → Southern alarm green door,,,Kdo jsi? Pouze pracovníci druhé úrovně sem mají povolen přístup.,Hvem er du? Kun personale på sikkerhedsniveau to har adgang til dette område.,Wer bist du? Nur Personal mit Zugangsstufe 2 hst hier Zutritt.,,Kiu vi estas? Nur dunivelaj laboristoj estas permesataj ĉi tie.,¿Quién eres? Solo el personal con permiso de nivel dos puede estar aquí.,,Kuka sinä olet? Vain kakkoskulkuluvan omaavalla henkilöstöllä on pääsy tälle alueelle.,Qui êtes vous? Seuls les personnes avec un niveau d'autorisation deux peuvent accéder à cette zone.,Te meg ki vagy? Csak kettes szintű engedéllyel rendekezők jöhetnek be ide.,Chi sei? Solo il personale con l'autorizzazione di livello due può stare in questa sezione.,"誰だ? レベル2のクリアランスを持たない者は -ここに来てはいけないが。",넌 누구지? 이곳은 2급 인원만이 출입할 수 있다.,Wie ben jij? Alleen ontruimingsniveau twee personeel is toegestaan in dit gebied.,Hvem er du? Bare personell med klareringsnivå to har adgang til dette området.,Kim jesteś? Tylko personel posiadający zezwolenie poziomu drugiego może tu przebywać.,Quem é você? Só funcionários com permissão nível 2 podem entrar nesta área.,,Cine ești? Doar personalul cu nivel 2 de acces are voie în zona aceasta.,Ты кто такой? Только персоналу второго уровня допуска разрешено находиться в этой зоне.,,Kimsin sen? Bu bölgeye sadece ikinci seviye personel girebilir. -I'm the replacement worker.,TXT_RPLY0_SCRIPT04_D34868_IMTHE,〃,,,Jsem náhradník.,Jeg er afløseren.,Ich bin der Ersatzarbeiter.,,Mi estas la anstataŭanto.,Soy el sustituto.,,Olen täydennystyöntekijä.,Je suis le remplaçant.,Én vagyok a helyettes.,Sono il lavoratore sostitutivo.,代替要員だ。,후임 근무자로 왔습니다.,Ik ben de vervanger.,Jeg er vikaren.,Jestem tu na zastępstwo.,Eu sou o operário substituto.,,Sunt înlocuitorul muncitorului.,Я замещаю рабочего.,,Ben yedek işçiyim. +ここに来てはいけないが。",넌 누구지? 이곳은 2급 인원만이 출입할 수 있다.,Wie ben jij? Alleen ontruimingsniveau twee personeel is toegestaan in dit gebied.,Hvem er du? Bare personell med klareringsnivå to har adgang til dette området.,Kim jesteś? Tylko personel posiadający zezwolenie poziomu drugiego może tu przebywać.,Quem é você? Só funcionários com permissão nível 2 podem entrar nesta área.,,Cine ești? Doar personalul cu nivel 2 de acces are voie în zona aceasta.,Ты кто такой? Только персоналу второго уровня допуска разрешено находиться в этой зоне.,,Vem är du? Endast personal på nivå två får vistas i det här området.,Kimsin sen? Bu bölgeye sadece ikinci seviye personel girebilir. +I'm the replacement worker.,TXT_RPLY0_SCRIPT04_D34868_IMTHE,〃,,,Jsem náhradník.,Jeg er afløseren.,Ich bin der Ersatzarbeiter.,,Mi estas la anstataŭanto.,Soy el sustituto.,,Olen täydennystyöntekijä.,Je suis le remplaçant.,Én vagyok a helyettes.,Sono il lavoratore sostitutivo.,代替要員だ。,후임 근무자로 왔습니다.,Ik ben de vervanger.,Jeg er vikaren.,Jestem tu na zastępstwo.,Eu sou o operário substituto.,,Sunt înlocuitorul muncitorului.,Я замещаю рабочего.,,Jag är ersättningsarbetaren.,Ben yedek işçiyim. "About time you showed up. Go talk with Ketrick in the core. Oh, and take this key card. Don't want you getting shot on your first day, huh?",TXT_DLG_SCRIPT04_D36384_ABOUT,〃,,,"Už bylo na čase, aby ses objevil. Jdi si promluvit s Ketrickem v jádře. A vezmi si tuhle kartu. Přece by ses nechtěl nechat zastřelit hned svůj první den, ne?","Det var på tide, du dukkede op. Gå hen og snak med Ketrick i kernen. Åh, og tag dette nøglekort. Du skal ikke blive skudt på din første dag, hva'?","Wird auch Zeit, dass du hier erscheinst. Rede mit Ketrick im Reaktorkern, Und nimm diesen Schlüssel. Du willst ja wohl nicht gleich am ersten Tag erschossen werden, oder?",,"Vi finfine aperis. Iru paroli kun Ketrick en la kerno. Ha, kaj prenu ĉi tiun ŝlosil-karton; vi ne volas ricevi pafon dum via unua tago, ĉu?","Ya era hora. Ve a hablar con Ketrick en el núcleo. Ah, y toma esta tarjeta llave; no querrás que te peguen un tiro en tu primer día, ¿eh?",,"Jo oli aikakin ilmaantua. Mene ytimeen puhumaan Ketrickin kanssa. Ai niin, ja ota tämä avainkortti. Ei parane joutua ammutuksi heti ensimmäisenä työpäivänä, eikö niin?","Ah. Enfin. Il vous en a fallu, du temps! Allez parler avec Ketrick dans la section du cœur. Oh, et prenez ce passe. Vous ne voulez pas vous faire tirer dessus lors de votre premier jour, non?","Már ideje volt. Menj és beszélj Kettickkel a magban. Ja, és vidd magaddal ezt a mágneskártyát. Gondolom nem akarod magadat agyonlövetni az első napodon.","Finalmente sei arrivato. Vai a parlare a Ketrick nel nucleo. Ah, e prendi questa tessera chiave. Non è il caso di farsi sparare il primo giorno di lavoro, eh?","そろそろ来ると思っていたよ。コアにいる ケトリックに話しかけてくれ。 あとこのキーカードを受け取ってくれ。 -初日で撃たれたくないならな。","마침 잘 와주었군. 중심부에 있는 케트릭에게 가서 얘기하라. 아, 그리고 여기 키카드를 받아라. 첫날부터 총에 맞고 싶지는 않겠지, 응?","Het werd tijd dat je kwam opdagen. Ga praten met Ketrick in de kern. Oh, en neem deze sleutelkaart. Wil je niet dat je op je eerste dag wordt neergeschoten, huh?",På tide du dukket opp. Gå og snakk med Ketrick i kjernen. Og ta dette nøkkelkortet. Du vil vel ikke bli skutt på din første dag?,"W końcu jesteś. Idź, porozmawiaj z Ketrickiem przy rdzeniu. Oh, weź tą kartę-klucz. Nie chcesz chyba być zastrzelony podczas pierwszego dnia w pracy, co?","Já era hora de você aparecer. Vá falar com o Ketrick lá no núcleo. Ah, e leve este cartão de acesso. Você não vai querer levar um tiro no primeiro dia, hein?",,"Era și timpul. Du-te și vorbește cu Ketrick în interiorul nucleului. Ah, și ia și cardul ăsta. Nu cred că vrei să fii împușcat în prima zi de lucru, eh?","Как раз вовремя. Иди поговори с Кетриком возле ядра реактора. О, и возьми эту карточку. Мы ведь не хотим, чтобы тебя подстрелили в первый же рабочий день?",,"Tam zamanında geldin. Git merkezdeki Ketrick ile konuş. Bu anahtar kartını da al. İlk gününde vurulmanı istemeyiz, değil mi?" -Where's the power crystal?,TXT_RPLY0_SCRIPT04_D36384_WHERE,〃,,,Kde je energetický krystal?,Hvor er kraftkrystallen?,Wo ist der Energiekristall?,,Kie estas la energia kristalo?,¿Dónde está el cristal de poder?,,Missä voimakristalli on?,Où se trouve le cristal du réacteur?,Hol van az erőkristály?,Dov'è il cristallo?,パワークリスタルは何処だ?,동력 수정체는 어디에 있죠?,Waar is het energiekristal?,Hvor er kraftkrystallen?,Gdzie jest kryształ mocy?,Onde fica o cristal de energia?,,Unde e cristalul de alimentare?,Где энергетический кристалл?,,Güç kristali nerede? -"If you don't get to work, you'll get shot anyway. Move your tunic.",TXT_DLG_SCRIPT04_D37900_IFYOU,〃,,,"Jestli se nepustíš do práce, zastřelí tě tak jako tak. Pohni tunikou!","Hvis du ikke går på arbejde, bliver du skudt alligevel. Flyt din kittel.","Wenn du nicht arbeitest, wirst du eh erschossen. Und nun beweg deinen Arsch!",,Vi ricevos pafon ankaŭ se vi ne eklaboras. Movu vian tunikon.,"Si no te pones a trabajar, te pegarán igual un tiro. Mueve tu túnica.","Si no te pones a trabajar, te van a pegar igual un tiro. Mueve tu túnica.","Jos et ryhdy töihin, sinut ammutaan kumminkin. Liikuta sitä ruhoasi.","Si vous ne partez pas travailler, vous allez vous faire tirer dessus de toutes manières. Bougez-vous les miches.","Ha nem dolgozol így is, úgy is agyonlőnek. Haladj már!","Se non ti metti subito a lavorare, ti spareranno ugualmente. Muovi la tua tuta.","今すぐ作業しないと奴等にバレて撃たれるぞ。 -さあ行け。",근무하러 안 가면 어차피 총살이야. 어서 일하러 가!,"Als je niet aan het werk gaat, wordt je toch al neergeschoten. Verplaats je tuniek.","Hvis du ikke kommer deg på jobb, blir du skutt uansett. Flytt tunikaen din.","Jeśli się nie weźmiesz do roboty, to tak czy siak cię zastrzelą. Rusz się.","Se você não trabalhar, você vai levar um tiro de qualquer jeito. Mexa-se.",,"Dacă nu te apuci de muncă, o să fii împuscat oricum. Miscă-ți tunica.","Если ты не приступишь к работе, тебя всё равно пристрелят. Шевелись!",,İşe gitmezsen zaten vurulacaksın. Tuniğini çek. +初日で撃たれたくないならな。","마침 잘 와주었군. 중심부에 있는 케트릭에게 가서 얘기하라. 아, 그리고 여기 키카드를 받아라. 첫날부터 총에 맞고 싶지는 않겠지, 응?","Het werd tijd dat je kwam opdagen. Ga praten met Ketrick in de kern. Oh, en neem deze sleutelkaart. Wil je niet dat je op je eerste dag wordt neergeschoten, huh?",På tide du dukket opp. Gå og snakk med Ketrick i kjernen. Og ta dette nøkkelkortet. Du vil vel ikke bli skutt på din første dag?,"W końcu jesteś. Idź, porozmawiaj z Ketrickiem przy rdzeniu. Oh, weź tą kartę-klucz. Nie chcesz chyba być zastrzelony podczas pierwszego dnia w pracy, co?","Já era hora de você aparecer. Vá falar com o Ketrick lá no núcleo. Ah, e leve este cartão de acesso. Você não vai querer levar um tiro no primeiro dia, hein?",,"Era și timpul. Du-te și vorbește cu Ketrick în interiorul nucleului. Ah, și ia și cardul ăsta. Nu cred că vrei să fii împușcat în prima zi de lucru, eh?","Как раз вовремя. Иди поговори с Кетриком возле ядра реактора. О, и возьми эту карточку. Мы ведь не хотим, чтобы тебя подстрелили в первый же рабочий день?",,"Det var på tiden att du dök upp. Gå och prata med Ketrick i kärnan. Och ta det här nyckelkortet. Jag vill inte att du blir skjuten på din första dag, va?","Tam zamanında geldin. Git merkezdeki Ketrick ile konuş. Bu anahtar kartını da al. İlk gününde vurulmanı istemeyiz, değil mi?" +Where's the power crystal?,TXT_RPLY0_SCRIPT04_D36384_WHERE,〃,,,Kde je energetický krystal?,Hvor er kraftkrystallen?,Wo ist der Energiekristall?,,Kie estas la energia kristalo?,¿Dónde está el cristal de poder?,,Missä voimakristalli on?,Où se trouve le cristal du réacteur?,Hol van az erőkristály?,Dov'è il cristallo?,パワークリスタルは何処だ?,동력 수정체는 어디에 있죠?,Waar is het energiekristal?,Hvor er kraftkrystallen?,Gdzie jest kryształ mocy?,Onde fica o cristal de energia?,,Unde e cristalul de alimentare?,Где энергетический кристалл?,,Var är kraftkristallen?,Güç kristali nerede? +"If you don't get to work, you'll get shot anyway. Move your tunic.",TXT_DLG_SCRIPT04_D37900_IFYOU,〃,,,"Jestli se nepustíš do práce, zastřelí tě tak jako tak. Pohni tunikou!","Hvis du ikke går på arbejde, bliver du skudt alligevel. Flyt din kittel.","Wenn du nicht arbeitest, wirst du eh erschossen. Und nun beweg deinen Arsch!",,Vi ricevos pafon ankaŭ se vi ne eklaboras. Movu vian tunikon.,"Si no te pones a trabajar, te pegarán igual un tiro. Mueve el culo.","Si no te pones a trabajar, te van a pegar igual un tiro. Ya muévete.","Jos et ryhdy töihin, sinut ammutaan kumminkin. Liikuta sitä ruhoasi.","Si vous ne partez pas travailler, vous allez vous faire tirer dessus de toutes manières. Bougez-vous les miches.","Ha nem dolgozol így is, úgy is agyonlőnek. Haladj már!","Se non ti metti subito a lavorare, ti spareranno ugualmente. Muovi la tua tuta.","今すぐ作業しないと奴等にバレて撃たれるぞ。 +さあ行け。",근무하러 안 가면 어차피 총살이야. 어서 일하러 가!,"Als je niet aan het werk gaat, wordt je toch al neergeschoten. Verplaats je tuniek.","Hvis du ikke kommer deg på jobb, blir du skutt uansett. Flytt tunikaen din.","Jeśli się nie weźmiesz do roboty, to tak czy siak cię zastrzelą. Rusz się.","Se você não trabalhar, você vai levar um tiro de qualquer jeito. Mexa-se.",,"Dacă nu te apuci de muncă, o să fii împuscat oricum. Miscă-ți tunica.","Если ты не приступишь к работе, тебя всё равно пристрелят. Шевелись!",,Om du inte börjar jobba blir du skjuten ändå. Flytta din tunika.,İşe gitmezsen zaten vurulacaksın. Tuniğini çek. "I don't mean to sound alarmist, but if they keep pushing the power crystal this hard it's gonna flaw, and then shatter, and then *boom*! ...Just a thought.",TXT_DLG_SCRIPT04_D39416_IDONT,MAP04: Reactor Core → Northern alarm green door,,,"Nechci plašit, ale jestli budou krystal dál takhle protěžovat, tak se nalomí a pak roztříští a pak BUM! ...Jen tak přemýšlím.","Jeg vil ikke lyde alarmerende, men hvis de bliver ved med at presse energikrystallen så hårdt, så vil den flække, og så splintre, og så *bum*! ...Bare en tanke.","Ich will ja nicht herumunken, aber wenn sie den Kristall weiter so überstrapazieren, nimmt er Schaden, und dann *bumm*! ...nur so ein Gedanke.",,"Mi ne intencas soni alarme, sed se ili plue superŝargas la energian kristalon tiel multe, ĝi misfunkcios, poste ĝi rompiĝos kaj tiam «Bum!»... Por ke vi havu ian ideon.","No quiero sonar alarmante, pero si siguen forzando tanto el cristal de poder, primero fallará, luego se partirá y luego «¡Pum!»... Para que te hagas una idea.","No quiero sonar alarmante, pero si siguen forzando tanto el cristal de poder, primero va a fallar, luego se va a partir y luego «¡Pum!»... Para que te hagas una idea.","En halua kuulostaa pelon lietsojalta, mutta jos ne vaan jatkavat voimakristallin ajamista näin lujille, se säröytyy, sitten pirstoutuu, ja sitten pam! Ihan vain heittona.","Je n'ai pas envie d'être alarmiste, mais si ils continuent de mettre autant de tension sur le cristal du réacteur, il risque d'être endommagé, éclater, et puis boum! Enfin, c'est juste ce que je pense.","Nem akarok vészmadár lenni, de ha ennyire hajtják az erőkristályt, akkor megreped és eltörik, aztán meg *bumm*!...csak egy gondolat.","Non voglio sembrare un allarmista, ma se continuano a sovraccaricare il cristallo così tanto, ci sarà un errore, e il cristallo si spaccherà, e poi *boom*! ...Solo un pensiero.","オーダーがもしパワークリスタルに負荷を かけ続けていたら、いずれ限界でヒビが入って、 -砕けて、*ボーン*!...だと思うよ。","불안감을 조장하긴 싫지만, 동력 수정체를 지금처럼 심하게 다루면, 갑자기 균열이 나고, 조각나면서, 그리고 '쾅!' ... 그냥 그렇다고.","Ik wil geen paniekzaaier zijn, maar als ze zo hard op het energiekristal blijven duwen, gaat het scheuren, en dan versplinteren, en dan *boom*! ...Gewoon een gedachte.","Jeg mener ikke å høres alarmistisk ut, men hvis de fortsetter å presse kraftkrystallen så hardt, vil den sprekke, og så *boom*! ...Bare en tanke.","Nie chcę brzmieć jak panikarz, ale jeśli dalej tak bardzo będą zużywać kryształ mocy, to się zepsuje, pęknie, a potem *bum*! ...Tak myślę.","Não quero parecer alarmista, mas se eles continuarem pressionando tanto esse cristal de energia ele vai falhar, depois vai quebrar e então bum! ...Só minha opinião.",,"Nu vreau să par alarmist, dar... dacă o să continui să împingi cristalul atât de tare o să se crape, apoi sparge, iar apoi *bum*! ...Doar ziceam.","Не хочу показаться паникёром, но если продолжать так же сильно нагружать кристалл, он треснет, потом расколется, а потом «бум!».. Просто подумалось.",,"Endişeli görünmek istemem ama güç kristalini bu kadar zorlamaya devam ederlerse kusurlu olacak, sonra paramparça olacak ve sonra *boom*! ...Sadece bir düşünce." -"Let me be quite clear. If this terminal locks up again, the coolant level will drop and we'll all have to answer to the Programmer. If we survive.",TXT_DLG_SCRIPT04_D40932_LETME,MAP04: Reactor Core → Southern alarm green door,,,"Vyjádřím se jasně: Jestli tenhle terminál znovu zamrzne, hladina chladiva poklesne a všichni se budeme muset zodpovídat Programátorovi. Pokud přežijeme.","Lad mig gøre det helt klart. Hvis denne terminal låser sig igen, vil kølevæskeniveauet falde, og vi vil alle skulle stå til ansvar over for programmøren. Hvis vi overlever.","Lass es mich klar und deutlich sagen. Wenn dieses Terminal nochmal abstürzt, sinkt der Kühlungsflüssigkeitspegel und wir dürfen uns vor dem Programmierer verantworten - wenn wir überleben.",,"Mi klagiru: se ĉi tiu terminalo paneas denove, la malvarmiga nivelo falos kaj ni ĉiuj devos respondeci pri tio al la Programisto... se ni supervivis.","Que quede claro: si esta terminal vuelve a colgarse, el nivel de refrigerante caerá y todos tendremos que dar la cara ante el Programador... si no morimos antes.","Que quede claro: si esta terminal vuelve a bloquearse, el nivel de refrigerante va a caer y todos vamos a tener que dar la cara ante el Programador... si no morimos antes.","Tehdäänpä asia selväksi. Jos tämä pääte vielä hyytyy, jäähdytysnestetaso laskee ja meillä on vähän selittelemistä Ohjelmoitsijalle. Sillä ehdolla, että selviämme.","Je vais être clair. Si ce terminal plante encore, les niveaux de liquide de refroidissement vont descendre et on aura tous à faire face au Programmeur. Si on survit, bien entendu.","Lényegretörő leszek. Ha a terminál még egyszer lezár, a hűtő folyadék szintje visszaesik, és felelülnek kell majd a Programozó színe előtt. Már ha túléljük.","Voglio essere chiaro su questo. Se questa console si blocca di nuovo, il livello di refrigerazione calerà bruscamente e dovremo risponderne di ciò al Programmtore. Se sopravviveremo.","万が一このターミナルがフリーズしたら、 +砕けて、*ボーン*!...だと思うよ。","불안감을 조장하긴 싫지만, 동력 수정체를 지금처럼 심하게 다루면, 갑자기 균열이 나고, 조각나면서, 그리고 '쾅!' ... 그냥 그렇다고.","Ik wil geen paniekzaaier zijn, maar als ze zo hard op het energiekristal blijven duwen, gaat het scheuren, en dan versplinteren, en dan *boom*! ...Gewoon een gedachte.","Jeg mener ikke å høres alarmistisk ut, men hvis de fortsetter å presse kraftkrystallen så hardt, vil den sprekke, og så *boom*! ...Bare en tanke.","Nie chcę brzmieć jak panikarz, ale jeśli dalej tak bardzo będą zużywać kryształ mocy, to się zepsuje, pęknie, a potem *bum*! ...Tak myślę.","Não quero parecer alarmista, mas se eles continuarem pressionando tanto esse cristal de energia ele vai falhar, depois vai quebrar e então bum! ...Só minha opinião.",,"Nu vreau să par alarmist, dar... dacă o să continui să împingi cristalul atât de tare o să se crape, apoi sparge, iar apoi *bum*! ...Doar ziceam.","Не хочу показаться паникёром, но если продолжать так же сильно нагружать кристалл, он треснет, потом расколется, а потом «бум!».. Просто подумалось.",,"Jag vill inte låta alarmistisk, men om de fortsätter att trycka på kraftkristallen så här hårt kommer den att flaga, och sedan splittras, och sedan *boom*! ...Bara en tanke.","Endişeli görünmek istemem ama güç kristalini bu kadar zorlamaya devam ederlerse kusurlu olacak, sonra paramparça olacak ve sonra *boom*! ...Sadece bir düşünce." +"Let me be quite clear. If this terminal locks up again, the coolant level will drop and we'll all have to answer to the Programmer. If we survive.",TXT_DLG_SCRIPT04_D40932_LETME,MAP04: Reactor Core → Southern alarm green door,,,"Vyjádřím se jasně: Jestli tenhle terminál znovu zamrzne, hladina chladiva poklesne a všichni se budeme muset zodpovídat Programátorovi. Pokud přežijeme.","Lad mig gøre det helt klart. Hvis denne terminal låser sig igen, vil kølevæskeniveauet falde, og vi vil alle skulle stå til ansvar over for programmøren. Hvis vi overlever.","Lass es mich klar und deutlich sagen. Wenn dieses Terminal nochmal abstürzt, sinkt der Kühlungsflüssigkeitspegel und wir dürfen uns vor dem Programmierer verantworten - wenn wir überleben.",,"Mi klarigu: se ĉi tiu terminalo paneas denove, la malvarmiga nivelo falos kaj ni ĉiuj devos respondeci pri tio al la Programisto... se ni supervivis.","Que quede claro: si esta terminal vuelve a colgarse, el nivel de refrigerante caerá y todos tendremos que dar la cara ante el Programador... si no morimos antes.","Que quede claro: si esta terminal vuelve a bloquearse, el nivel de refrigerante va a caer y todos vamos a tener que dar la cara ante el Programador... si no morimos antes.","Tehdäänpä asia selväksi. Jos tämä pääte vielä hyytyy, jäähdytysnestetaso laskee ja meillä on vähän selittelemistä Ohjelmoitsijalle. Sillä ehdolla, että selviämme.","Je vais être clair. Si ce terminal plante encore, les niveaux de liquide de refroidissement vont descendre et on aura tous à faire face au Programmeur. Si on survit, bien entendu.","Lényegretörő leszek. Ha a terminál még egyszer lezár, a hűtő folyadék szintje visszaesik, és felelülnek kell majd a Programozó színe előtt. Már ha túléljük.","Voglio essere chiaro su questo. Se questa console si blocca di nuovo, il livello di refrigerazione calerà bruscamente e dovremo risponderne di ciò al Programmtore. Se sopravviveremo.","万が一このターミナルがフリーズしたら、 冷却液の水位が下がってプログラマーと 対面しなければならないだろうな。 メルトダウンから生還すればの話だが。","이거 하나만 확실히 말하지. 이 시설이 또 고장 난다면, 냉각수 수치가 떨어질 거고 우리 둘 다 프로그래머에게 문책을 받을 거야. 만약 살아남는다면 말이지. - \cy어쩌라고. 아무도 프로그래머들 이야기는 안 듣는데.","Laat ik heel duidelijk zijn. Als deze terminal weer vastloopt, zal het koelmiddelniveau dalen en zullen we ons allemaal moeten verantwoorden tegenover de programmeur. Als we het overleven.","La meg gjøre det helt klart. Hvis denne terminalen låser seg igjen, vil kjølevæskenivået synke, og vi må alle stå til ansvar for programmereren. Hvis vi overlever.","Wyrażę się jasno. Jeśli terminal znów się zablokuje, to poziom płynu w chłodnicy spadnie i będziemy musieli za to odpowiadać przed Programistą. Jeśli wogóle przeżyjemy.","Só pra ficar bem claro. Se este terminal travar de novo, o nível de refrigeração vai cair e vamos nos ver com o Programador. Se nós sobrevivermos.",,"Ca să fiu înțeles. Dacă terminalul ăsta se blochează iar, nivelul răcirii va scădea și vom fi trași la răspundere de Programator. Dacă supraviețuim.","Давай говорить начистоту. Если этот терминал опять заклинит, то уровень охлаждения упадёт, и нам всем придётся отвечать перед Программистом — если выживем.",,"Açık konuşayım. Eğer bu terminal tekrar kilitlenirse, soğutma sıvısı seviyesi düşecek ve hepimiz Programcı'ya hesap vermek zorunda kalacağız. Eğer hayatta kalırsak." + \cy어쩌라고. 아무도 프로그래머들 이야기는 안 듣는데.","Laat ik heel duidelijk zijn. Als deze terminal weer vastloopt, zal het koelmiddelniveau dalen en zullen we ons allemaal moeten verantwoorden tegenover de programmeur. Als we het overleven.","La meg gjøre det helt klart. Hvis denne terminalen låser seg igjen, vil kjølevæskenivået synke, og vi må alle stå til ansvar for programmereren. Hvis vi overlever.","Wyrażę się jasno. Jeśli terminal znów się zablokuje, to poziom płynu w chłodnicy spadnie i będziemy musieli za to odpowiadać przed Programistą. Jeśli wogóle przeżyjemy.","Só pra ficar bem claro. Se este terminal travar de novo, o nível de refrigeração vai cair e vamos nos ver com o Programador. Se nós sobrevivermos.",,"Ca să fiu înțeles. Dacă terminalul ăsta se blochează iar, nivelul răcirii va scădea și vom fi trași la răspundere de Programator. Dacă supraviețuim.","Давай говорить начистоту. Если этот терминал опять заклинит, то уровень охлаждения упадёт, и нам всем придётся отвечать перед Программистом — если выживем.",,Låt mig vara helt tydlig. Om terminalen låser sig igen kommer kylvattennivån att sjunka och vi kommer alla att få stå till svars inför programmeraren. Om vi överlever.,"Açık konuşayım. Eğer bu terminal tekrar kilitlenirse, soğutma sıvısı seviyesi düşecek ve hepimiz Programcı'ya hesap vermek zorunda kalacağız. Eğer hayatta kalırsak." "You! Yeah, you. You aren't cleared for this area. Let me have your key card, fast. I'm in such a bad mood!",TXT_DLG_SCRIPT04_D42448_YOUYE,MAP04: Ketrick.,,,"Ty! Jo, ty. Pro tuhle oblast nemáš povolení. Ukaž mi svou kartu, hned. Mám hodně špatnou náladu!","Dig! Ja, dig. Du er ikke godkendt til dette område. Giv mig dit nøglekort, hurtigt. Jeg er i så dårligt humør!","Du da! Ja, du. Du hast keine Berechtigung für diesen Bereich. Gib mir deine Schlüsselkarte, und zwar schnell! Ich bin ja sowas von sauer!",,"Vi! Jes, vi! Vi ne laboras en ĉi tiu sektoro. Montru vian ŝlosil-karton, rapide! Mi estas en tre malbona humoro!","¡Tú! Sí, tú. No tienes permiso en esta área. A ver tu tarjeta llave, ¡y rápido, que estoy de muy mal humor!",,"Sinä! Niin, sinä. Sinulla ei ole lupaa tälle alueelle. Anna minulle avainkorttisi, joutuin. Olen niin huonolla päällä!","Vous! Oui, vous, vous, vous n'avez pas l'autorisation d'être dans cette zone! Donnez moi votre passe maintenant, et vite, je suis de sale humeur aujourd'hui!","Te! Igen, Te. Nincs jogod itt lenni. Add csak ide az igazolványodat. Nem jó kedvemben találtál meg.","Tu! Si, tu. Non hai l'autorizzazione per quest'area. Dammi la tua chiave tessera, presto! Ho un diavolo per capello!","お前!そうだお前だ。ここは立入禁止だ。 -IDカードを見せろ、早く。今機嫌が悪いんだ!","너! 그래, 너 말이야. 넌 여기에 들어올 수 있는 권한이 없어. 당장 네 키카드를 내놔. 나 지금 기분 더럽다고!","Jij! Ja, jij. Je bent niet vrij voor dit gebied. Geef me je sleutelkaart, snel. Ik ben in zo'n slecht humeur!","Du! Ja, du. Du er ikke klarert for dette området. Gi meg nøkkelkortet ditt, fort. Jeg er i så dårlig humør!","Ty! Tak, ty. Nie masz pozwolenia, aby tu przebywać. Pokaż mi swoją kartę-klucz, szybko. Nie jestem dziś w dobrym nastroju!","Você aí! É, você mesmo. Você não tem permissão para estar aqui. Me passa esse cartão logo de uma vez. Estou de péssimo humor.",,"Tu! Da, tu! Nu ai acces în zona asta. Dă-mi cardul tău, rapid. Sunt extrem de indispus!","Ты! Да, ты. У тебя нет сюда допуска. Давай свою карточку, быстро. Я сегодня в плохом настроении!",,"Sen! Evet, sen. Bu bölgeye giriş iznin yok. Anahtar kartını ver, çabuk. Çok kötü bir ruh halindeyim!" -"Here, here's my card.",TXT_RPLY0_SCRIPT04_D42448_HEREH,〃,,,"Tady, to je moje karta.","Her, her er mit kort.","Hier, hier ist meine Karte.",,Jen mia karto.,"Toma, aquí está mi tarjeta.",,Tässä on minun korttini.,Voilà mon passe.,"Parancsolj, itt a kártyám.",Ecco qua la mia tessera.,ほら、これがカードだ。,"자, 카드 여기 있어요.","Hier, hier is mijn kaart.","Her, her er kortet mitt.",Oto moja karta.,"Tome, aqui está o cartão.",,"Aici, aici e cardul.","Вот, вот моя карта.",,"İşte, işte kartım." +IDカードを見せろ、早く。今機嫌が悪いんだ!","너! 그래, 너 말이야. 넌 여기에 들어올 수 있는 권한이 없어. 당장 네 키카드를 내놔. 나 지금 기분 더럽다고!","Jij! Ja, jij. Je bent niet vrij voor dit gebied. Geef me je sleutelkaart, snel. Ik ben in zo'n slecht humeur!","Du! Ja, du. Du er ikke klarert for dette området. Gi meg nøkkelkortet ditt, fort. Jeg er i så dårlig humør!","Ty! Tak, ty. Nie masz pozwolenia, aby tu przebywać. Pokaż mi swoją kartę-klucz, szybko. Nie jestem dziś w dobrym nastroju!","Você aí! É, você mesmo. Você não tem permissão para estar aqui. Me passa esse cartão logo de uma vez. Estou de péssimo humor.",,"Tu! Da, tu! Nu ai acces în zona asta. Dă-mi cardul tău, rapid. Sunt extrem de indispus!","Ты! Да, ты. У тебя нет сюда допуска. Давай свою карточку, быстро. Я сегодня в плохом настроении!",,"Du! Ja, du. Du är inte godkänd för det här området. Ge mig ditt nyckelkort, snabbt. Jag är på så dåligt humör!","Sen! Evet, sen. Bu bölgeye giriş iznin yok. Anahtar kartını ver, çabuk. Çok kötü bir ruh halindeyim!" +"Here, here's my card.",TXT_RPLY0_SCRIPT04_D42448_HEREH,〃,,,"Tady, to je moje karta.","Her, her er mit kort.","Hier, hier ist meine Karte.",,Jen mia karto.,"Toma, aquí está mi tarjeta.",,Tässä on minun korttini.,Voilà mon passe.,"Parancsolj, itt a kártyám.",Ecco qua la mia tessera.,ほら、これがカードだ。,"자, 카드 여기 있어요.","Hier, hier is mijn kaart.","Her, her er kortet mitt.",Oto moja karta.,"Tome, aqui está o cartão.",,"Aici, aici e cardul.","Вот, вот моя карта.",,"Här, här är mitt kort.","İşte, işte kartım." This is garbage! Wait here. Oh screw it. Guards kill this intruder!,TXT_DLG_SCRIPT04_D43964_THISI,〃,,,"Blbost! Počkej tady. Á, kašlu na to. Stráže, zabte tohohle vetřelce!","Det her er affald! Vent her. Åh, pis. Vagter dræber denne ubudne gæst!","Das ist ja wohl die Höhe! Warte hier. Ach was. Wärter, tötet hn!",,"Ĉi tio estas rubaĵo! Atendu ĉi tie... Ba, al mil diabloj. Gardistoj, mortigu ĉi tiun entrudiĝanton!","¡Esto es basura! Espera aquí... Bah, ¿que más da? ¡Guardias, maten a este intruso!","¡Esto es basura! Espera aquí... Bah, al carajo. ¡Guardias, maten a este intruso!","Mitä pötyä tämä on? Odota tässä. Äh, ja paskat. Vartijat, tappakaa tämä tunkeilija!","C'est quoi cette blague? Attendez ici. Non, en fait, Gardes! Descendez cet intrus!","Ez egy szemét! Várj meg itt. Najó, nem kínlódok vele. Őrök nyírjátok ki a behatolót!","Questa è spazzatura! Aspetta qui. Ah, dannazione. Guardie, uccidete questo intruso!","なんだこのゴミは! いや待て。ああ、畜生。 -ガード、侵入者を殺せ!","이게 뭐야?! 잠깐... 이런 젠장. 경비, 여기 침입자를 쏴버려!","Dit is vuilnis! Wacht hier. Oh, laat maar. Bewakers doden deze indringer!","Dette er søppel! Vent her. Drit i det. Vakter, drep inntrengeren!","To nie karta, to śmieć! Czekaj. Pieprzyć to. Straże zabijcie tego intruza!","Que merda é essa? Fique aqui. Ah, que se dane. Guardas, matem este intruso!",,"Ăsta e gunoi! Așteaptă aici. Oh las-o baltă. Gardieni, ucideți intrusul!","Этой карточкой можно только подтереться! Жди здесь. А, к чёрту. Стража, здесь нарушитель! Убейте его!",,Bu çöp! Burada bekle. Siktir et. Gardiyanlar bu davetsiz misafiri öldürün! -"Work, sleep, get tortured, what a life. Say, you the replacement for the careless pit diver?",TXT_DLG_SCRIPT04_D45480_WORKS,MAP04: Reactor Core → Sammis,,,"Práce, spánek, poležení si na skřipci, dobrej život. Hele, ty jsi ta náhrada za toho neopatrného skokana?","Arbejde, sove, blive tortureret. Sikke et liv. Er du afløseren for den skødesløse pit dykker?","Arbeiten, schlafen, gefoltert werden, was für ein Leben. Sag mal, bist du der Ersatz für diesen sorglosen Grubentaucher?",,"Labori, dormi, esti torturata; kia vivo. Do ĉu vi venis anstataŭi la senatentan tru-plonĝinton?","Trabajar, dormir, ser torturado; qué vida. A ver, ¿eres el sustituto del distraído que hizo un clavado al pozo?",,"Raada, nuku, joudu kidutetuksi, mikä elämä. Sanopa, sinäkö olet sen huolimattoman kuilusukeltajan korvaaja?","Travail, sommeil, torture, quelle vie! Dites, vous êtes le remplaçant de l'unfortuné plongeur?","Munka, alvás, kínzás, milyen jó kis élet is ez. Figyelj csak, Te nem a figyelmetlen akna búvár helyettese vagy?","Lavoro, dormire e venire torturati, che vita. Dì un pò, sei tu il sostituto per l'incauto palombaro del pozzo?","働いて、寝て、処罰されて、なんて人生だ。 +ガード、侵入者を殺せ!","이게 뭐야?! 잠깐... 이런 젠장. 경비, 여기 침입자를 쏴버려!","Dit is vuilnis! Wacht hier. Oh, laat maar. Bewakers doden deze indringer!","Dette er søppel! Vent her. Drit i det. Vakter, drep inntrengeren!","To nie karta, to śmieć! Czekaj. Pieprzyć to. Straże zabijcie tego intruza!","Que merda é essa? Fique aqui. Ah, que se dane. Guardas, matem este intruso!",,"Ăsta e gunoi! Așteaptă aici. Oh las-o baltă. Gardieni, ucideți intrusul!","Этой карточкой можно только подтереться! Жди здесь. А, к чёрту. Стража, здесь нарушитель! Убейте его!",,"Det här är skräp! Vänta här. Åh, skit i det. Vakterna dödar den här inkräktaren!",Bu çöp! Burada bekle. Siktir et. Gardiyanlar bu davetsiz misafiri öldürün! +"Work, sleep, get tortured, what a life. Say, you the replacement for the careless pit diver?",TXT_DLG_SCRIPT04_D45480_WORKS,MAP04: Reactor Core → Sammis,,,"Práce, spánek, poležení si na skřipci, dobrej život. Hele, ty jsi ta náhrada za toho neopatrného skokana?","Arbejde, sove, blive tortureret. Sikke et liv. Er du afløseren for den skødesløse pit dykker?","Arbeiten, schlafen, gefoltert werden, was für ein Leben. Sag mal, bist du der Ersatz für diesen sorglosen Grubentaucher?",,"Labori, dormi, esti torturata; kia vivo. Do ĉu vi venis anstataŭi la senatentan tru-plonĝinton?","Trabajar, dormir, ser torturado; qué vida. A ver, ¿eres el sustituto del distraído que hizo un clavado al pozo?",,"Raada, nuku, joudu kidutetuksi, mikä elämä. Sanopa, sinäkö olet sen huolimattoman kuilusukeltajan korvaaja?","Travail, sommeil, torture, quelle vie! Dites, vous êtes le remplaçant de l'unfortuné plongeur?","Munka, alvás, kínzás, milyen jó kis élet is ez. Figyelj csak, Te nem a figyelmetlen akna búvár helyettese vagy?","Lavoro, dormire e venire torturati, che vita. Dì un po', sei tu il sostituto per l'incauto palombaro del pozzo?","働いて、寝て、処罰されて、なんて人生だ。 で、お前はあの冷却炉に落ちたアイツの -代替要員か?","일하고, 자고, 고문받고, 인생 참 멋지네. 자, 네가 그 부주의하게 추락사한 친구의 후임 맞지?","Werk, slaap, word gemarteld, wat een leven. Zeg, ben jij de vervanger van de onzorgvuldige pitduiker?","Jobbe, sove, bli torturert, for et liv! Er du avløseren for den uforsiktige dykkeren?","Spanie, praca, tortury, co za życie. Więc, jesteś tu na zastępstwo za tego co skoczył w przepaść?","Trabalhar, dormir, ser torturado. Que vida. Me diz uma coisa, você é o substituto daquele mergulhador de poço distraído?",,"Muncă, odihnă, tortură, ce mai viață. Și, zici că ești înlocuitorul înotătorului neatent?","Работа, сон и пытки, что за жизнь. Так ты заменяешь нашего беспечного ныряльщика?",,"Çalış, uyu, işkence gör, ne hayat ama. Söylesene, dikkatsiz çukur dalgıcının yerine sen mi geldin?" -"Yeah, can't wait to start.",TXT_RPLY0_SCRIPT04_D45480_YEAHC,〃,,,"Jo, už se nemůžu dočkat.","Ja, jeg kan ikke vente med at begynde.","Ja, ich kanns kaum erwarten, hier anzufangen.",,"Yes, kaj mi vere volas komenci.","Sí, y tengo ganas de empezar.",,"Kyllä, en malta odottaa.","Oui, j'ai hâte de commencer.","Igen, már alig várom, hogy kezdhessek.","Sì, non vedo l'ora di iniziare.",そうだ、もう待てない。,"네, 일이 정말 기대됩니다.","Ja, ik kan niet wachten om te beginnen.","Ja, jeg gleder meg til å begynne.","Tak, nie mogę się już doczekać.","É, mal posso esperar pra começar.",,"Deah, abia aștept să încep.","Да, поскорей бы уже за дело.",,"Evet, başlamak için sabırsızlanıyorum." -"Yeah, right. OK, get your ass to work.",TXT_DLG_SCRIPT04_D46996_YEAHR,〃,,,"Jo, jasně. Dobře, začni makat.","Ja, det er rigtigt. OK, få din røv på arbejde.","Na gut, schwing deinen Arsch zur Arbeit.",,"Jes, kompreneble. Nu, eklaboru.","Sí, claro. Bueno, ponte a trabajar.",,"Just joo. Selvä, raahaa ahterisi töiden ääreen.","Ouais, bien sûr. OK, allez bosser.","Ja persze már. Na, húzzál dolgozni inkább.","Già, certo. OK, muovi il culo e vai a lavorare.",わかった。さっさと働け。,"그래, 좋아. 일이나 하라고.","Ja, juist. Oké, ga aan het werk.","Ja, sikkert. OK, få ræva di på jobb.","Dobra. Ok, rusz swoją dupę do roboty.","Sim, sei. Tá, comece a trabalhar de uma vez.",,"Deah, sigur. Bine, hai, la muncă.","Да, конечно. Ладно, шуруй работать.",,"Evet, doğru. Tamam, kıçını kaldır da işe koyul." -Where's the crystal?,TXT_RPLY0_SCRIPT04_D46996_WHERE,〃,,,Kde je krystal?,Hvor er krystallen?,Wo ist der Kristall?,,Kie estas la kristalo?,¿Dónde está el cristal?,,Missä kristalli on?,Où est le cristal?,Hol van a kristály?,Dov'è il cristallo?,クリスタルは何処だ?,수정체는 어디에 있죠?,Waar is het kristal?,Hvor er krystallen?,Gdzie kryształ?,Onde fica o cristal?,,Unde e cristalul?,Где кристалл?,,Kristal nerede? +代替要員か?","일하고, 자고, 고문받고, 인생 참 멋지네. 자, 네가 그 부주의하게 추락사한 친구의 후임 맞지?","Werk, slaap, word gemarteld, wat een leven. Zeg, ben jij de vervanger van de onzorgvuldige pitduiker?","Jobbe, sove, bli torturert, for et liv! Er du avløseren for den uforsiktige dykkeren?","Spanie, praca, tortury, co za życie. Więc, jesteś tu na zastępstwo za tego co skoczył w przepaść?","Trabalhar, dormir, ser torturado. Que vida. Me diz uma coisa, você é o substituto daquele mergulhador de poço distraído?",,"Muncă, odihnă, tortură, ce mai viață. Și, zici că ești înlocuitorul înotătorului neatent?","Работа, сон и пытки, что за жизнь. Так ты заменяешь нашего беспечного ныряльщика?",,"Jobba, sova, bli torterad, vilket liv. Säg, är du ersättaren för den slarviga gropdykaren?","Çalış, uyu, işkence gör, ne hayat ama. Söylesene, dikkatsiz çukur dalgıcının yerine sen mi geldin?" +"Yeah, can't wait to start.",TXT_RPLY0_SCRIPT04_D45480_YEAHC,〃,,,"Jo, už se nemůžu dočkat.","Ja, jeg kan ikke vente med at begynde.","Ja, ich kanns kaum erwarten, hier anzufangen.",,"Yes, kaj mi vere volas komenci.","Sí, y tengo ganas de empezar.",,"Kyllä, en malta odottaa.","Oui, j'ai hâte de commencer.","Igen, már alig várom, hogy kezdhessek.","Sì, non vedo l'ora di iniziare.",そうだ、もう待てない。,"네, 일이 정말 기대됩니다.","Ja, ik kan niet wachten om te beginnen.","Ja, jeg gleder meg til å begynne.","Tak, nie mogę się już doczekać.","É, mal posso esperar pra começar.",,"Deah, abia aștept să încep.","Да, поскорей бы уже за дело.",,"Ja, jag längtar efter att få börja.","Evet, başlamak için sabırsızlanıyorum." +"Yeah, right. OK, get your ass to work.",TXT_DLG_SCRIPT04_D46996_YEAHR,〃,,,"Jo, jasně. Dobře, začni makat.","Ja, det er rigtigt. OK, få din røv på arbejde.","Na gut, schwing deinen Arsch zur Arbeit.",,"Jes, kompreneble. Nu, eklaboru.","Sí, claro. Bueno, ponte a trabajar.",,"Just joo. Selvä, raahaa ahterisi töiden ääreen.","Ouais, bien sûr. OK, allez bosser.","Ja persze már. Na, húzzál dolgozni inkább.","Già, certo. OK, muovi il culo e vai a lavorare.",わかった。さっさと働け。,"그래, 좋아. 일이나 하라고.","Ja, juist. Oké, ga aan het werk.","Ja, sikkert. OK, få ræva di på jobb.","Dobra. Ok, rusz swoją dupę do roboty.","Sim, sei. Tá, comece a trabalhar de uma vez.",,"Deah, sigur. Bine, hai, la muncă.","Да, конечно. Ладно, шуруй работать.",,"Ja, visst. Okej, sätt dig i arbete.","Evet, doğru. Tamam, kıçını kaldır da işe koyul." +Where's the crystal?,TXT_RPLY0_SCRIPT04_D46996_WHERE,〃,,,Kde je krystal?,Hvor er krystallen?,Wo ist der Kristall?,,Kie estas la kristalo?,¿Dónde está el cristal?,,Missä kristalli on?,Où est le cristal?,Hol van a kristály?,Dov'è il cristallo?,クリスタルは何処だ?,수정체는 어디에 있죠?,Waar is het kristal?,Hvor er krystallen?,Gdzie kryształ?,Onde fica o cristal?,,Unde e cristalul?,Где кристалл?,,Var är kristallen?,Kristal nerede? "Go talk to Ketrick. Bring the walkway up using the switches, then use this I.D. For the elevator.",TXT_DLG_SCRIPT04_D48512_GOTAL,〃,,,Promluv si s Ketrickem. Tlačítkem zvedni schodiště a ve výtahu pak použij tuhle kartu.,"Gå hen og snak med Ketrick. Få gangbroen op ved hjælp af kontakterne, og brug så dette ID til elevatoren.","Rede mit Ketrick. Hebe den Steg mit den Schaltern an, dann benutze dies ID für den Lift.",,Parolu al Ketrick. Levu la ponton per ĉi tiuj ŝaltiloj kaj tiam ekagigu la lifton per ĉi tiu identigilo.,Habla con Ketrick. Usa estos interruptores para alzar la pasarela y luego esta identificación con el ascensor.,,Mene puhumaan Ketrickin kanssa. Tuo kulkusilta vivuilla ylös ja sitten käytä hissiin tätä tunnistetta.,"Parlez à Ketrick. Vous pouvez étendre la coursive avec les boutons, puis utilisez ce passe pour l'ascenseur.","Menj és beszélj Ketrickkel. A kapcoslókkal emeld meg a szerelőhidat, majd használd ezt az igazolványt a lifthez.","Devi parlare con Ketrick. Usa i pulsanti per alzare la passarella, dopodiché usa questa tessera d'identificazione per l'ascensore. ","ケトリックと話をしろ。 隣のスイッチで道を上げこのカードで -エレベーターに乗るんだ。","케트릭에게 물어봐. 스위치를 눌러서 진입로를 올리고, 이 신분증을 써서 승강기를 타고 올라가.",Ga met Ketrick praten. Breng de loopbrug naar boven met behulp van de schakelaars en gebruik dan deze I.D. voor de lift.,"Snakk med Ketrick. Få gangbroen opp med bryterne, og bruk dette kortet til heisen.","Idź porozmawiać z Ketrickiem. Podnieś chodnik za pomocą przełączników, potem użyj tego identyfikatora do windy.",Fale com o Ketrick. Use os interruptores para fazer a passarela subir e depois use esta identificação para o elevador.,,"Discută cu Ketrick. Ridică pasarela cu ajutorul butoanelor, apoi folosește legitimația asta pentru lift.","Сходи поговори с Кетриком. Используй переключатели на стене, чтобы подняться наверх, потом запусти лифт этой карточкой.",,"Git Ketrick'le konuş. Anahtarları kullanarak geçidi yukarı getir, sonra asansör için bu kimliği kullan." -Where's the crystal again?,TXT_RPLY0_SCRIPT04_D48512_WHERE,〃,,,"Můžeš mi znovu říct, kde je krystal?",Hvor er krystallen igen?,"Wo ist der Kristall, nochmal?",,"Mi demandis, kie estas la kristalo.","De nuevo, ¿dónde está el cristal?",,Missä kristalli olikaan?,Mais où est le cristal?,Hol is van a kristály?,E il cristallo dov'è?,いいからクリスタルは何処だ?,수정체가 어디에 있다고요?,Waar is het kristal ook alweer?,Hvor er krystallen igjen?,"Jeszcze raz, gdzie kryształ?",Onde fica o cristal mesmo?,,Unde ziceai că e cristalul?,Ещё раз: где кристалл?,,Kristal yine nerede? -"None of your business, go talk to Ketrick.",TXT_DLG_SCRIPT04_D50028_NONEO,〃,,,"Do toho ti nic není, jdi si promluvit s Ketrickem.","Det rager ikke dig, gå hen og snak med Ketrick.","Geht dich nichts an, und jetzt rede mit Ketrick.",,Tio ne estas via afero. Iru paroli al Ketrick.,No es asunto tuyo. Ve a hablar con Ketrick.,,"Ei kuulu sinulle, puhu Ketrickille.",Ca ne vous concerne pas. Allez voir Ketrick.,"Semmi közöd hozzá, menj beszélj Ketrickkel.","Non sono affari tuoi, vai a parlare con Ketrick.",大きなお世話だ、ケトリックと話をしろ。,"상관 말고, 케트릭에게 물어봐.","Gaat je niets aan, ga met Ketrick praten.",Ikke din sak. Snakk med Ketrick.,"Nie twój interes, idź porozmawiać z Ketrickiem.",Não é da sua conta. Vá falar com o Ketrick.,,Nu-i treaba ta. Discută cu Ketrick.,Не твоё дело. Иди поговори с Кетриком.,,"Seni ilgilendirmez, git Ketrick'le konuş." -Ok.,TXT_RPLY0_SCRIPT04_D50028_OK,〃,,,Dobře.,Ok.,Ok.,,Bone.,Bueno.,,OK.,OK.,OK.,OK.,オーケー,알겠습니다.,OKÉ.,GREIT.,Ok.,Ok.,,Bine.,Понял.,,TAMAM. +エレベーターに乗るんだ。","케트릭에게 물어봐. 스위치를 눌러서 진입로를 올리고, 이 신분증을 써서 승강기를 타고 올라가.",Ga met Ketrick praten. Breng de loopbrug naar boven met behulp van de schakelaars en gebruik dan deze I.D. voor de lift.,"Snakk med Ketrick. Få gangbroen opp med bryterne, og bruk dette kortet til heisen.","Idź porozmawiać z Ketrickiem. Podnieś chodnik za pomocą przełączników, potem użyj tego identyfikatora do windy.",Fale com o Ketrick. Use os interruptores para fazer a passarela subir e depois use esta identificação para o elevador.,,"Discută cu Ketrick. Ridică pasarela cu ajutorul butoanelor, apoi folosește legitimația asta pentru lift.","Сходи поговори с Кетриком. Используй переключатели на стене, чтобы подняться наверх, потом запусти лифт этой карточкой.",,"Gå och prata med Ketrick. Ta upp gångvägen med hjälp av växlarna, använd sedan det här ID-kortet för hissen.","Git Ketrick'le konuş. Anahtarları kullanarak geçidi yukarı getir, sonra asansör için bu kimliği kullan." +Where's the crystal again?,TXT_RPLY0_SCRIPT04_D48512_WHERE,〃,,,"Můžeš mi znovu říct, kde je krystal?",Hvor er krystallen igen?,"Wo ist der Kristall, nochmal?",,"Mi demandis, kie estas la kristalo.","De nuevo, ¿dónde está el cristal?",,Missä kristalli olikaan?,Mais où est le cristal?,Hol is van a kristály?,E il cristallo dov'è?,いいからクリスタルは何処だ?,수정체가 어디에 있다고요?,Waar is het kristal ook alweer?,Hvor er krystallen igjen?,"Jeszcze raz, gdzie kryształ?",Onde fica o cristal mesmo?,,Unde ziceai că e cristalul?,Ещё раз: где кристалл?,,Var är kristallen igen?,Kristal yine nerede? +"None of your business, go talk to Ketrick.",TXT_DLG_SCRIPT04_D50028_NONEO,〃,,,"Do toho ti nic není, jdi si promluvit s Ketrickem.","Det rager ikke dig, gå hen og snak med Ketrick.","Geht dich nichts an, und jetzt rede mit Ketrick.",,Tio ne estas via afero. Iru paroli al Ketrick.,No es asunto tuyo. Ve a hablar con Ketrick.,,"Ei kuulu sinulle, puhu Ketrickille.",Ca ne vous concerne pas. Allez voir Ketrick.,"Semmi közöd hozzá, menj beszélj Ketrickkel.","Non sono affari tuoi, vai a parlare con Ketrick.",大きなお世話だ、ケトリックと話をしろ。,"상관 말고, 케트릭에게 물어봐.","Gaat je niets aan, ga met Ketrick praten.",Ikke din sak. Snakk med Ketrick.,"Nie twój interes, idź porozmawiać z Ketrickiem.",Não é da sua conta. Vá falar com o Ketrick.,,Nu-i treaba ta. Discută cu Ketrick.,Не твоё дело. Иди поговори с Кетриком.,,"Det angår inte dig, gå och prata med Ketrick.","Seni ilgilendirmez, git Ketrick'le konuş." +Ok.,TXT_RPLY0_SCRIPT04_D50028_OK,〃,,,Dobře.,,,,Bone.,Bueno.,,OK.,OK.,OK.,OK.,オーケー,알겠습니다.,OKÉ.,GREIT.,,,,Bine.,Понял.,,OKEJ.,TAMAM. "If it's busy work you want, go stare at that screen for a while, it'll bore you to tears.",TXT_DLG_SCRIPT04_D51544_IFITS,"〃 -(bored to tears = extremely bored)",,,"Jestli chceš tvrdou práci, jdi na chvíli zírat na tamtu obrazovku. Unudí tě to k pláči.","Hvis det er travlt arbejde du vil have, så gå hen og stirr på den skærm i et stykke tid, den vil kede dig til tårer.","Wenn du richtige Arbeit willst, dann starre mal für längere Zeit auf den Bildschirm. Das langweilt zu Tränen.",,"Se penigan laboron vi serĉas, iru rigardi tiun ekranon dum momento: vi mortos de enuo.","Si es trabajo duro lo que buscas, ve a mirar esa pantalla un rato: te morirás de aburrimiento.",,"Jos puuhastelua kaipaat, niin mene tuijottamaan tuota ruutua joksikin aikaa. Eiköhän se ikävystytä sinut kuoliaaksi.","Si vous voulez un boulot éreintant, allez fixer cet écran pour quelques heures. Ca va vous ennuyer jusqu'a en pleurer.","Ha nagyon el akarod magad foglalni, akkor bámuld azt a monitort egy darabig. Halálra fog untatni.","Se vuoi un lavoro pesante, ti basta guardare quello schermo per un pò, e ti annoierai a morte.","忙しい仕事を望んでいるなら、 +(bored to tears = extremely bored)",,,"Jestli chceš tvrdou práci, jdi na chvíli zírat na tamtu obrazovku. Unudí tě to k pláči.","Hvis det er travlt arbejde du vil have, så gå hen og stirr på den skærm i et stykke tid, den vil kede dig til tårer.","Wenn du richtige Arbeit willst, dann starre mal für längere Zeit auf den Bildschirm. Das langweilt zu Tränen.",,"Se penigan laboron vi serĉas, iru rigardi tiun ekranon dum momento: vi mortos de enuo.","Si es trabajo duro lo que buscas, ve a mirar esa pantalla un rato: te morirás de aburrimiento.","Si es trabajo duro lo que buscas, ve a mirar esa pantalla un rato: te vas a morir de aburrimiento.","Jos puuhastelua kaipaat, niin mene tuijottamaan tuota ruutua joksikin aikaa. Eiköhän se ikävystytä sinut kuoliaaksi.","Si vous voulez un boulot éreintant, allez fixer cet écran pour quelques heures. Ca va vous ennuyer jusqu'a en pleurer.","Ha nagyon el akarod magad foglalni, akkor bámuld azt a monitort egy darabig. Halálra fog untatni.","Se vuoi un lavoro pesante, ti basta guardare quello schermo per un po', e ti annoierai a morte.","忙しい仕事を望んでいるなら、 そのスクリーンをしばらく見ていなさい、 -飽きて涙が浮かぶでしょう。",만약 더 쉬운 일을 원한다면 저 차단기를 계속 쳐다봐봐. 눈물 나도록 지루해 죽을걸.,"Als het druk werk is dat je wilt, ga dan een tijdje naar dat scherm staren, het zal je tot tranen toe vervelen.","Hvis du vil ha mye å gjøre, kan du stirre på skjermen en stund. Den kjeder deg i hjel.","Jeśli szukasz ciężkiej pracy, to idź pogapić się przez chwilę w ten ekran, zanudzi cię to na śmierć.","Se você quer ficar bem ocupado, fique olhando para essa tela por um tempo. Você vai morrer de tédio.",,"Dacă vrei treabă pe bune, du-te holbează-te la ecranul ăla o vreme, te va plictisii până la lacrimi.","Если ты хочешь работы от ушей до пят, попялься какое-то время на тот экран... Наскучит до слёз.",,"Eğer meşgul olmak istiyorsan, git bir süre şu ekrana bak, seni gözyaşlarına boğacak." +飽きて涙が浮かぶでしょう。",만약 더 쉬운 일을 원한다면 저 차단기를 계속 쳐다봐봐. 눈물 나도록 지루해 죽을걸.,"Als het druk werk is dat je wilt, ga dan een tijdje naar dat scherm staren, het zal je tot tranen toe vervelen.","Hvis du vil ha mye å gjøre, kan du stirre på skjermen en stund. Den kjeder deg i hjel.","Jeśli szukasz ciężkiej pracy, to idź pogapić się przez chwilę w ten ekran, zanudzi cię to na śmierć.","Se você quer ficar bem ocupado, fique olhando para essa tela por um tempo. Você vai morrer de tédio.",,"Dacă vrei treabă pe bune, du-te holbează-te la ecranul ăla o vreme, te va plictisii până la lacrimi.","Если ты хочешь работы от ушей до пят, попялься какое-то время на тот экран... Наскучит до слёз.",,"Om du vill ha ett arbete, gå och stirra på den där skärmen ett tag, den kommer att tråka ut dig till tårar.","Eğer meşgul olmak istiyorsan, git bir süre şu ekrana bak, seni gözyaşlarına boğacak." The almighty Programmer is so paranoid of infiltration that he's locked up the computer core. How am I supposed to get my work done? The only way in is the suicide run.,TXT_DLG_SCRIPT04_D53060_THEAL,MAP04: Reactor Core → Southern alarm green door,,,"Náš všemocný Programátor je tak paranoidní, že uzamknul počítačové jádro. Jak mám takhle pracovat? Jediná cesta tam je skrz běh pro sebevrahy.","Den almægtige programmør er så paranoid over for infiltration, at han har låst computerkernen inde. Hvordan skal jeg få mit arbejde gjort? Den eneste vej ind er selvmordsruten.","Der allmächtige Programmierer ist so paranoid, dass er den Computer blockiert hat. Wie soll ich so meine Arbeit machen? Der einzige weg wäre über den Selbstmordpfad.",,"La ĉiopova Programisto estas tiel paranoja pri ebla enŝoviĝo, ke li ŝlosis la komputilan kernon. Kiel mi supozeble laboros? La ununura ŝlosilo estas la vivo-riska vojo.",El todopoderoso Programador tiene tanta paranoia de infiltración que hasta ha cerrado el núcleo del ordenador. ¿Cómo se supone que voy a hacer mi trabajo? La única forma es por la vía suicida.,El todopoderoso Programador tiene tanta paranoia de infiltración que hasta cerró el núcleo de la computadora. ¿Cómo se supone que voy a hacer mi trabajo? La única forma es por la vía suicida.,"Kaikkivoipa Ohjelmoitsija on niin vainoharhainen soluttautujista, että on lukinnut tietokoneen ytimen. Miten minä muka työni saan tehdyksi? Ainoa tie sisään on itsemurhareitti.","Ce tout-puissant Programmeur est tellement paranoïaque au sujet des infiltrations qu'il a mis le cœur informatique sous les verrous. Comment je peux faire mon travail maintenant? Si je veux essayer d'y entrer, faut que j'utilise le couloir du suicide!","A mindenható Programozó annyira tart a behatolóktól, hogy elzárta a számítógép magot. Hogy kéne így végeznem a munkámat. Az egyetlen lehetőség a halál inga.","L'onnipotente Programmatore è così paranoico per le infiltrazioni che ha bloccato l'ingresso al nucleo del computer. Come posso finire il mio lavoro? L'unico modo per entrare è tramite il ""percorso suicida"".","プログラマー様は潜入されるのを 非常に恐れているらしく、コンピューターコアの ロックを厳重にするよう命じたんだ。 -どうやってあんな危ない所で仕事するんだ?",위대하신 프로그래머님이 침입에 대해 너무나도 불안해하셔서 컴퓨터 중심부를 락다운 시켰어. 일이 점점 더 어려워지고 있는 것 같아. 내 생각엔 자살기행을 또 해봐야겠어.,De almachtige Programmeur is zo paranoïde van infiltratie dat hij de computerkern heeft afgesloten. Hoe moet ik mijn werk gedaan krijgen? De enige manier om binnen te komen is de zelfmoordactie.,Den allmektige programmereren er så paranoid for infiltrasjon at han har låst datakjernen. Hvordan skal jeg få arbeidet mitt gjort? Den eneste veien inn er selvmordsløpet.,"Wszechmocny Programista ma paranoję na punkcie infiltracji tak bardzo, że zamknął rdzeń komputera. Jakim cudem mam skończyć pracę? Jedyną drogą, by tam się dostać jest ścieżka samobójców.",O todo-poderoso Programador é tão paranóico com infiltração que ele travou o núcleo de computação. Como que eu vou fazer o meu trabalho? A único jeito é a maneira suicida.,,Atotputernicul Programator e atât de paranoic în privința infiltrărilor încât a încuiat nucleul calculatorului. Cum mi-aș putea face treaba? Singura cale de intrare e sinucidere.,"Всемогущий Программист настолько боится проникновения, что закрыл компьютерную комнату. И как мне теперь выполнять свою работу? Есть один способ пройти туда, но это чистое самоубийство.",,Yüce Programcı sızma konusunda o kadar paranoyak ki bilgisayar çekirdeğini kilitledi. İşimi nasıl yapacağım? İçeri girmenin tek yolu intihar koşusu. -Suicide run? What's that?,TXT_RPLY0_SCRIPT04_D53060_SUICI,〃,,,Běh pro sebevrahy? Co to je?,Selvmordsruten? Hvad er det?,"Selbstmordpfad, was ist das?",,Ĉu vivo-riska vojo? Kio estas tio?,¿Vía suicida? ¿Cómo es eso?,,Itsemurhareitti? Mikä se on?,Couloir du suicide? Comment ça?,Halál inga? Az meg mi a fene?,"""Percorso suicida""? Che roba è?",危ない?どういう事だ?,자살기행? 그건 뭡니까?,Zelfmoordactie? Wat is dat?,Selvmordsløp? Hva er det?,Ścieżka samobójców? Co to?,Maneira suicida? O que é isso?,,O cale sinucigașă? Cum așa?,Самоубийство? О чём ты?,,İntihar koşusu mu? O da ne? +どうやってあんな危ない所で仕事するんだ?",위대하신 프로그래머님이 침입에 대해 너무나도 불안해하셔서 컴퓨터 중심부를 락다운 시켰어. 일이 점점 더 어려워지고 있는 것 같아. 내 생각엔 자살기행을 또 해봐야겠어.,De almachtige Programmeur is zo paranoïde van infiltratie dat hij de computerkern heeft afgesloten. Hoe moet ik mijn werk gedaan krijgen? De enige manier om binnen te komen is de zelfmoordactie.,Den allmektige programmereren er så paranoid for infiltrasjon at han har låst datakjernen. Hvordan skal jeg få arbeidet mitt gjort? Den eneste veien inn er selvmordsløpet.,"Wszechmocny Programista ma paranoję na punkcie infiltracji tak bardzo, że zamknął rdzeń komputera. Jakim cudem mam skończyć pracę? Jedyną drogą, by tam się dostać jest ścieżka samobójców.",O todo-poderoso Programador é tão paranóico com infiltração que ele travou o núcleo de computação. Como que eu vou fazer o meu trabalho? A único jeito é a maneira suicida.,,Atotputernicul Programator e atât de paranoic în privința infiltrărilor încât a încuiat nucleul calculatorului. Cum mi-aș putea face treaba? Singura cale de intrare e sinucidere.,"Всемогущий Программист настолько боится проникновения, что закрыл компьютерную комнату. И как мне теперь выполнять свою работу? Есть один способ пройти туда, но это чистое самоубийство.",,Den allsmäktige programmeraren är så paranoid för infiltration att han har låst in datorkärnan. Hur ska jag kunna få mitt arbete gjort? Den enda vägen in är självmordsresan.,Yüce Programcı sızma konusunda o kadar paranoyak ki bilgisayar çekirdeğini kilitledi. İşimi nasıl yapacağım? İçeri girmenin tek yolu intihar koşusu. +Suicide run? What's that?,TXT_RPLY0_SCRIPT04_D53060_SUICI,〃,,,Běh pro sebevrahy? Co to je?,Selvmordsruten? Hvad er det?,"Selbstmordpfad, was ist das?",,Ĉu vivo-riska vojo? Kio estas tio?,¿Vía suicida? ¿Cómo es eso?,,Itsemurhareitti? Mikä se on?,Couloir du suicide? Comment ça?,Halál inga? Az meg mi a fene?,"""Percorso suicida""? Che roba è?",危ない?どういう事だ?,자살기행? 그건 뭡니까?,Zelfmoordactie? Wat is dat?,Selvmordsløp? Hva er det?,Ścieżka samobójców? Co to?,Maneira suicida? O que é isso?,,O cale sinucigașă? Cum așa?,Самоубийство? О чём ты?,,Självmordslopp? Vad är det för något?,İntihar koşusu mu? O da ne? "It's a sure-fire way to get killed, but that's not important right now. Go down the lift if you're so inclined.",TXT_DLG_SCRIPT04_D54576_ITSAS,〃,,,"Je to zaručený způsob, jak zemřít, ale to teď není důležité. Sjeď výtahem dolů, jestli tě to tak zajímá.","Det er en sikker måde at blive dræbt på, men det er ikke vigtigt lige nu. Gå ned i elevatoren, hvis du har lyst til det.","Es ist ein todsicherer Weg um das Zeitliche zu segnen, aber das ist jetzt nicht wichtig. Nimm den Lift da drüben, wenn du Lust hast,und sieh selbst unten nach.",,"Ĝi estas neeraripova maniero morti, sed tio nun ne estas grava. Iru malsupren per la lifto se vi estas inklina al tio.","Es una forma segura de matarte, pero eso no importa ahora. Baja por el ascensor si te apetece.",,"Se on taattu keino tapattaa itsensä, mutta sillä ei ole nyt väliä. Mene hissillä alas, jos niin haluat.",C'est un moyen garanti de se tuer. Mais ce n'est pas important pour l'instant. Descendez avec l'acsenseur si vous voulez absolument essayer.,"Egy holtbiztos módja, hogy kinyírasd magadat, de ez most nem lényeges. Menj le a lifttel, ha annyira érdekel.","È un ottimo metodo per rimanere uccisi, ma questo non è importante al momento. Scendi con l'ascensore, se sei così incline.","下手に立ち入ると射殺されるが、 今それどころではない。 そんなに行きたいならリフトを降りるんだな。","말 그대로 죽기 쉬운 방법인데, 더 알 필요는 없어. 궁금해 미치겠다면 밑으로 내려가 봐. - \cy오, 내가 숨어있어서 다행이야. 무슨 뜻인지 알겠지?","Het is een zekere manier om gedood te worden, maar dat is nu niet belangrijk. Ga de lift af als je zo geneigd bent.","Det er en sikker måte å bli drept på, men det er ikke viktig akkurat nå. Ta heisen hvis du vil.","To jest niezawodna droga, by dać się zabić, ale to nie jest teraz ważne. Zjedź windą, jeśli jesteś w stanie to zrobić.","É uma forma garantida de ser morto, mas isso não importa agora. Desça pelo elevador se você está tão curioso.",,"E un mod garantat de a muri, dar nu contează acum. Ia liftul jos dacă ești curios.","Сунуться туда — верная гибель, но на данный момент это не важно. Спускайся на лифте, если не боишься.",,Öldürülmek için kesin bir yol ama şu an bunun bir önemi yok. İstiyorsan asansörden aşağı in. + \cy오, 내가 숨어있어서 다행이야. 무슨 뜻인지 알겠지?","Het is een zekere manier om gedood te worden, maar dat is nu niet belangrijk. Ga de lift af als je zo geneigd bent.","Det er en sikker måte å bli drept på, men det er ikke viktig akkurat nå. Ta heisen hvis du vil.","To jest niezawodna droga, by dać się zabić, ale to nie jest teraz ważne. Zjedź windą, jeśli jesteś w stanie to zrobić.","É uma forma garantida de ser morto, mas isso não importa agora. Desça pelo elevador se você está tão curioso.",,"E un mod garantat de a muri, dar nu contează acum. Ia liftul jos dacă ești curios.","Сунуться туда — верная гибель, но на данный момент это не важно. Спускайся на лифте, если не боишься.",,"Det är ett säkert sätt att bli dödad, men det är inte viktigt just nu. Gå ner i hissen om du vill.",Öldürülmek için kesin bir yol ama şu an bunun bir önemi yok. İstiyorsan asansörden aşağı in. Halt. No one gets through here without authorization from the Warden or the Governor.,TXT_DLG_SCRIPT05_D0_HALTN,MAP05: Door Guard.,,,Stát. Nikdo tudy nesmí projít bez povolení dozorce nebo guvernéra.,Stop. Ingen kommer igennem her uden tilladelse fra direktøren eller guvernøren.,Halt. Niemand kommt hier ohne Autorisierung des Direktors durch.,,Haltu. Neniu eniras sen permeso el la provoso aŭ la registo.,Alto. Nadie entra aquí sin autorización del carcelero o del gobernador.,,Seis. Kukaan ei pääse tästä läpi ilman vankilanjohtajan tai kuvernöörin lupaa.,Halte! Personne ne passe sans autorisation du gardien ou du gouverneur.,Áljj! Nem haladhat át senki sem az Igazgató vagy Kormányzó engedélye nélkül.,Fermo lì. Nessuno passa qua senza l'autorizzazione del direttore o del governatore.,"止まれ。所長か知事の許可が無い限り -立ち入る事は許さん。",멈춰라. 총독이나 간수장의 허락을 받지 않은 이상 그 누구도 입장할 수 없다.,Stop. Niemand komt hier door zonder toestemming van de directeur of de gouverneur.,Stopp. Ingen kommer gjennom her uten tillatelse fra direktøren eller guvernøren.,Stop. Nikt tu nie wejdzie bez zgody Naczelnika lub Gubernatora.,Alto. Ninguém passa por aqui sem autorização do Carcereiro ou do Governador.,,Stop. Nimeni nu trece pe aici fără autorizație de la Director sau Guvernator.,Стой. Никто не может пройти сюда без разрешения от тюремщика или губернатора.,,Durun. Müdür ya da Vali'nin izni olmadan kimse buradan geçemez. -"Here's my pass, let me in.",TXT_RPLY0_SCRIPT05_D0_HERES,〃,,,"Tady je moje propustka, pusť mě dál.","Her er mit pas, luk mig ind.","Hier is mein Pass, lassen Sie mich rein.",,Jen mia paspermeso; lasu min eniri.,Aquí está mi pase; déjeme entrar.,,Tässä lupani; päästäkää minut sisään.,Voilà mon passe. Laissez-moi entrer.,"Itt az igazolásom, engedj be.","Ecco la mia autorizzazione, fammi entrare.",これが許可証だ、入れてくれ。,여기 통행증입니다. 들여보내 주세요.,"Hier is mijn pas, laat me binnen.","Her er passet mitt, slipp meg inn.",Oto moja przepustka. Wpuść mnie.,Aqui está o meu passe. Deixe-me entrar.,,"Aici e legitimația, lasă-mă să intru.",Вот мой пропуск. Дай войти.,,"İşte kartım, beni içeri alın." +立ち入る事は許さん。",멈춰라. 총독이나 간수장의 허락을 받지 않은 이상 그 누구도 입장할 수 없다.,Stop. Niemand komt hier door zonder toestemming van de directeur of de gouverneur.,Stopp. Ingen kommer gjennom her uten tillatelse fra direktøren eller guvernøren.,Stop. Nikt tu nie wejdzie bez zgody Naczelnika lub Gubernatora.,Alto. Ninguém passa por aqui sem autorização do Carcereiro ou do Governador.,,Stop. Nimeni nu trece pe aici fără autorizație de la Director sau Guvernator.,Стой. Никто не может пройти сюда без разрешения от тюремщика или губернатора.,,Halt. Ingen kommer igenom här utan tillstånd från föreståndaren eller guvernören.,Durun. Müdür ya da Vali'nin izni olmadan kimse buradan geçemez. +"Here's my pass, let me in.",TXT_RPLY0_SCRIPT05_D0_HERES,〃,,,"Tady je moje propustka, pusť mě dál.","Her er mit pas, luk mig ind.","Hier is mein Pass, lassen Sie mich rein.",,Jen mia enirpermeso; lasu min eniri.,Aquí está mi pase; déjeme entrar.,,Tässä lupani; päästäkää minut sisään.,Voilà mon passe. Laissez-moi entrer.,"Itt az igazolásom, engedj be.","Ecco la mia autorizzazione, fammi entrare.",これが許可証だ、入れてくれ。,여기 통행증입니다. 들여보내 주세요.,"Hier is mijn pas, laat me binnen.","Her er passet mitt, slipp meg inn.",Oto moja przepustka. Wpuść mnie.,Aqui está o meu passe. Deixe-me entrar.,,"Aici e legitimația, lasă-mă să intru.",Вот мой пропуск. Дай войти.,,"Här är mitt passerkort, släpp in mig.","İşte kartım, beni içeri alın." "OK, but talk only to the Warden.",TXT_DLG_SCRIPT05_D1516_OKBUT,〃,,,"Dobře, ale mluvte pouze s dozorcem.","Okay, men tal kun med direktøren.","Ok, aber reden Sie nur mit dem Direktor.",,"Bone, sed limu vin paroli kun la provoso.","Entendido, pero limítate a hablar con el carcelero.",,"Selvä, mutta puhu ainoastaan vankilanjohtajan kanssa.","D'accord, mais vous ne vous pouvez parler qu'au gardien.","OK, de csak az igazgatóval beszélj.","OK, ma parla solo con il direttore.",良いだろう、ただし話すのは所長とだけだ。,"알겠다. 하지만 간수장에게만 대화해라. - \cy뭐가 이리 불만이야. 나중에 얘 좀 꼭 처리해줘.","OK, maar praat alleen met de directeur.","OK, men snakk bare med direktøren.","Ok, ale rozmawiaj tylko z Naczelnikiem.","Ok, mas você só pode falar com o Carcereiro.",,"Bine, dar vorbești doar cu Directorul.","Проходи, но говори только с тюремщиком.",,"Tamam, ama sadece müdürle konuş." + \cy뭐가 이리 불만이야. 나중에 얘 좀 꼭 처리해줘.","OK, maar praat alleen met de directeur.","OK, men snakk bare med direktøren.","Ok, ale rozmawiaj tylko z Naczelnikiem.","Ok, mas você só pode falar com o Carcereiro.",,"Bine, dar vorbești doar cu Directorul.","Проходи, но говори только с тюремщиком.",,"Okej, men prata bara med fängelsedirektören.","Tamam, ama sadece müdürle konuş." "Do I look like the Warden to you? Keep moving, this area's off limits.",TXT_DLG_SCRIPT05_D3032_DOILO,〃 (After killing Montag),,,"Vypadám snad jako dozorce? Pokračuj dál, do této oblasti je vstup zakázán.","Ligner jeg direktøren? Fortsæt, dette område er forbudt område.","Sehe ich wie ein Direktor aus? Beweg dich, du hast hier nichts zu suchen.",,"Ĉu mi aspektas kiel la provoso laŭ vi? Foriru, ĉi tiu zono estas ekster la limoj.","¿Te parezco el carcelero? Ya vete, que esta área está fuera de los límites.",,Näytänkö minä sinulle vankilanjohtajalta? Jatka matkaasi; tähän alueeseen on pääsy kielletty.,"Je ressemble au gardien, à ton avis? Bouge, cette zone est hors-limites!","Úgy nézek ki, mint egy igazgató? Haladj tovább, ez a terület nem látogatható.","Ti sembro forse il direttore? Non stare fermo qua, quest'area è riservata al personale autorizzato.","俺がワーデンに見えるか? どっか行け、 この区域は立入禁止だ。","내가 친히 나서서 간수장을 찾아야겠나? 어서 움직여. 이곳은 통행 금지야. - \cy“이곳은 통행 금지야!” 웃기고 앉아있네.","Zie ik eruit als de directeur? Blijf bewegen, dit gebied is verboden terrein.","Ser jeg ut som direktøren? Gå videre, dette området er forbudt område.","Czy według ciebie wyglądam na Naczelnika? Rusz się, nikt nie ma wstępu na ten obszar.",Está achando que eu sou o Carcereiro? Suma daqui. Você não pode andar por aqui.,,"Ți se pare că eu sunt Directorul? Continuă să mergi, asta e o zonă fără acces.","Я что, похож на тюремщика? Двигай отсюда. Здесь закрытая территория!",,"Sana Müdür gibi mi görünüyorum? Devam edin, bu bölge yasak bölge." -The Order's wrath will rain down on these servants until they beg for death.,TXT_DLG_SCRIPT05_D4548_THEOR,MAP05: Prison Guard.,,,Hněv Řádu dopadne na ty služebníky dokud nebudou prosit o smrt.,"Ordenens vrede vil regne ned over disse tjenere, indtil de tigger om at dø.","Der Zorn des Ordens wird auf diese Untergebenen herabregnen, bis sie um den Tod betteln.",,La tondro de La Ordono pluvos sur tiujn servantojn ĝis ili petegos pri morto.,La ira de La Orden caerá sobre estos sirvientes hasta que supliquen por su muerte.,La ira de La Orden va a caer sobre estos sirvientes hasta que supliquen por su muerte.,"Veljeskunnan viha säilyy näiden palvelijoiden yllä siihen asti, kunnes rukoilevat kuolemaa.",La colère de l'Ordre s'abattrera sur ces serviles miséreux jusqu'a ce qu'ils pleurent pour leur propre mort.,"A Rend haragja fog lesújtani ezekre a szolgákra, egészen addig amíg nem könyörögnek a halálért.",La furia dell'Ordine si riverserà su questi servi finché non chiederanno pietà!,"オーダーの怒りは、奴等が死を望むまで + \cy“이곳은 통행 금지야!” 웃기고 앉아있네.","Zie ik eruit als de directeur? Blijf bewegen, dit gebied is verboden terrein.","Ser jeg ut som direktøren? Gå videre, dette området er forbudt område.","Czy według ciebie wyglądam na Naczelnika? Rusz się, nikt nie ma wstępu na ten obszar.",Está achando que eu sou o Carcereiro? Suma daqui. Você não pode andar por aqui.,,"Ți se pare că eu sunt Directorul? Continuă să mergi, asta e o zonă fără acces.","Я что, похож на тюремщика? Двигай отсюда. Здесь закрытая территория!",,"Ser jag ut som fängelsedirektören? Fortsätt gå, det här området är förbjudet område.","Sana Müdür gibi mi görünüyorum? Devam edin, bu bölge yasak bölge." +The Order's wrath will rain down on these servants until they beg for death.,TXT_DLG_SCRIPT05_D4548_THEOR,MAP05: Prison Guard.,,,Hněv Řádu dopadne na ty služebníky dokud nebudou prosit o smrt.,"Ordenens vrede vil regne ned over disse tjenere, indtil de tigger om at dø.","Der Zorn des Ordens wird auf diese Untergebenen herabregnen, bis sie um den Tod betteln.",,La tondro de La Ordeno pluvos sur tiujn servantojn ĝis ili petegos pri morto.,La ira de La Orden caerá sobre estos sirvientes hasta que supliquen por su muerte.,La ira de La Orden va a caer sobre estos sirvientes hasta que supliquen por su muerte.,"Veljeskunnan viha säilyy näiden palvelijoiden yllä siihen asti, kunnes rukoilevat kuolemaa.",La colère de l'Ordre s'abattrera sur ces serviles miséreux jusqu'a ce qu'ils pleurent pour leur propre mort.,"A Rend haragja fog lesújtani ezekre a szolgákra, egészen addig amíg nem könyörögnek a halálért.",La furia dell'Ordine si riverserà su questi servi finché non chiederanno pietà!,"オーダーの怒りは、奴等が死を望むまで 止む事はない。","이 죄인들이 죽음을 바라기 전까지는 오더의 심판과 응징을 받을 것이다. - \cy아주 들떠있는 녀석이네.",De toorn van de Orde zal op deze bedienden neerdalen tot ze om de dood smeken.,Ordenens vrede vil regne over disse tjenerne til de trygler om å dø.,Gniew Zakonu spadnie jak deszcz na te sługi dopóki nie będą błagać o śmierć.,A ira da Ordem descerá a esses servos até eles implorarem pela morte.,,Furia Ordinului se va năpusti asupra servitorilor aceștia până vor cerși după moarte.,"Гнев Ордена обрушится на этих рабов, и они будут молить о смерти.",,"Tarikat'ın gazabı, ölüm için yalvarana kadar bu hizmetkarların üzerine yağacak." -"I don't care if Mourel gave you a pass. This is my prison. My key is the only way in or out, and I'm not taking any chances. The Order does not tolerate mistakes.",TXT_DLG_SCRIPT05_D6064_IDONT,MAP05: Montag.,,,"Mě je jedno, že ti Mourel dal propustku. Tohle je moje vězení. Můj klíč je jediná cesta dovnitř a ven a já nehodlám nic riskovat. Řád netoleruje chyby.","Jeg er ligeglad med, om Mourel gav dig et fripas. Dette er mit fængsel. Min nøgle er den eneste vej ind eller ud, og jeg tager ingen chancer. Ordenen tolererer ikke fejltagelser.","Es ist mir egal ob Mourel Ihnen einen Pass gegeben hat. Das ist mein Gefängnis. Mein Schlüssel ist die einzige Möglichkeit, herein- oder herauszukommen, und ich riskiere da gar nichts. Der Orden toleriert keine Fehler.",,"Mi ne zorgas, ke Mourel donis paspermeson al vi. Ĉi tiu estas mia malliberejo; mia ŝlosilo estas la ununura maniero eniri aŭ eliri, kaj mi ne riskos min. La Ordono toleras nenian eraron.","No me importa que Mourel te haya dado un pase. Esta es mi prisión; mi llave es la única forma de entrar o salir, y no me arriesgaré. La Orden no tolera los fallos.","No me importa que Mourel te haya dado un pase. Esta es mi prisión; mi llave es la única forma de entrar o salir, y no me voy a arriesgar. La Orden no tolera los fallos.","En välitä mistään Mourelin luvista. Tämä on minun vankilani. Vain minun avaimellani pääsee sisään tai ulos, enkä aio ottaa yhtäkään riskiä. Veljeskunta ei suvaitse virheitä.","Je m'en fous que Mourel t'ai donné un passe. C'est ma prison. Ma clé est la seule façon d'entrer ou de sortir, et je ne prends pas de risques. L'Ordre ne tolère pas les erreurs.","Az sem érdekel ha Mourel adta a belépőt. Ez az Én börtönöm. Az Én kulcsom az egyetlen ami ki és bejutást enged, nem kockáztatok. A Rend nem igazán tolerálja a hibákat.","Non mi interessa se Mourel ti ha fatto entrare qua. Questa è la mia prigione. La mia chiave è l'unico modo per entrare o per uscire, e non ho intenzione di lasciare nulla al caso. L'Ordine non tollera errori.","モーレルが許可しようが構わん。 + \cy아주 들떠있는 녀석이네.",De toorn van de Orde zal op deze bedienden neerdalen tot ze om de dood smeken.,Ordenens vrede vil regne over disse tjenerne til de trygler om å dø.,Gniew Zakonu spadnie jak deszcz na te sługi dopóki nie będą błagać o śmierć.,A ira da Ordem descerá a esses servos até eles implorarem pela morte.,,Furia Ordinului se va năpusti asupra servitorilor aceștia până vor cerși după moarte.,"Гнев Ордена обрушится на этих рабов, и они будут молить о смерти.",,Ordens vrede kommer att regna över dessa tjänare tills de ber om döden.,"Tarikat'ın gazabı, ölüm için yalvarana kadar bu hizmetkarların üzerine yağacak." +"I don't care if Mourel gave you a pass. This is my prison. My key is the only way in or out, and I'm not taking any chances. The Order does not tolerate mistakes.",TXT_DLG_SCRIPT05_D6064_IDONT,MAP05: Montag.,,,"Mě je jedno, že ti Mourel dal propustku. Tohle je moje vězení. Můj klíč je jediná cesta dovnitř a ven a já nehodlám nic riskovat. Řád netoleruje chyby.","Jeg er ligeglad med, om Mourel gav dig et fripas. Dette er mit fængsel. Min nøgle er den eneste vej ind eller ud, og jeg tager ingen chancer. Ordenen tolererer ikke fejltagelser.","Es ist mir egal ob Mourel Ihnen einen Pass gegeben hat. Das ist mein Gefängnis. Mein Schlüssel ist die einzige Möglichkeit, herein- oder herauszukommen, und ich riskiere da gar nichts. Der Orden toleriert keine Fehler.",,"Mi ne zorgas, ke Mourel donis enirpermeson al vi. Ĉi tiu estas mia malliberejo; mia ŝlosilo estas la ununura maniero eniri aŭ eliri, kaj mi ne riskos min. La Ordeno toleras nenian eraron.","No me importa que Mourel te haya dado un pase. Esta es mi prisión; mi llave es la única forma de entrar o salir, y no me arriesgaré. La Orden no tolera los fallos.","No me importa que Mourel te haya dado un pase. Esta es mi prisión; mi llave es la única forma de entrar o salir, y no me voy a arriesgar. La Orden no tolera los fallos.","En välitä mistään Mourelin luvista. Tämä on minun vankilani. Vain minun avaimellani pääsee sisään tai ulos, enkä aio ottaa yhtäkään riskiä. Veljeskunta ei suvaitse virheitä.","Je m'en fous que Mourel t'ai donné un passe. C'est ma prison. Ma clé est la seule façon d'entrer ou de sortir, et je ne prends pas de risques. L'Ordre ne tolère pas les erreurs.","Az sem érdekel ha Mourel adta a belépőt. Ez az Én börtönöm. Az Én kulcsom az egyetlen ami ki és bejutást enged, nem kockáztatok. A Rend nem igazán tolerálja a hibákat.","Non mi interessa se Mourel ti ha fatto entrare qua. Questa è la mia prigione. La mia chiave è l'unico modo per entrare o per uscire, e non ho intenzione di lasciare nulla al caso. L'Ordine non tollera errori.","モーレルが許可しようが構わん。 ここは私の刑務所だ。この鍵でしか絶対出入りは 出来ないし、渡すつもりも無い。 オーダーは失敗を許さないからな。 -",모렐 녀석이 너에게 통행증을 줬다 해도 신경 안 써. 이곳은 이 몸이 통치하는 감옥이다! 내가 가지고 있는 열쇠만 있으면 죄인들의 자유를 맘껏 조종할 수 있지. 오더는 절대로 실수 같은걸 용납하지 않아!,Het kan me niet schelen of Mourel je een pasje heeft gegeven. Dit is mijn gevangenis. Mijn sleutel is de enige weg naar binnen of buiten en ik neem geen enkel risico. De Orde tolereert geen fouten.,"Jeg blåser i om Mourel ga deg et passerseddel. Dette er mitt fengsel. Min nøkkel er den eneste veien inn eller ut, og jeg tar ingen sjanser. Ordenen tolererer ikke feil.","Nie obchodzi mnie to, że Mourel dał ci przepustkę. To moje więzienie. Tylko mój klucz pozwala wejść lub wyjść, i nie mam zamiaru ryzykować. Zakon nie toleruje błędów.",Eu não estou nem aí se o Mourel te deu um passe. Esta é a minha prisão. A única forma de entrar ou sair é com a minha chave e eu não estou a fim de arriscar. A Ordem não tolera erros.,,"Nu-mi pasă că Mourel ți-a dat o legitimație. Asta e închisoarea mea. Cheia mea e singura cale de intrare sau ieșire, și nu risc nimic. Ordinul nu tolerează greșeli.","Мне плевать, дал ли тебе Морел пропуск или нет. Это моя тюрьма, и без моего ключа не войти и не выйти. И я не хочу рисковать — Орден не прощает ошибок!",,Mourel'in sana izin vermesi umurumda değil. Burası benim hapishanem. İçeri girip çıkmanın tek yolu benim anahtarım ve işimi şansa bırakmayacağım. Tarikatın hataya tahammülü yoktur. -Give me the damn key!,TXT_RPLY0_SCRIPT05_D6064_GIVEM,〃,,,Dej mi ten zatracený klíč!,Giv mig den forbandede nøgle!,Geben Sie mir den verdammten Schlüssel!,,Donu la fekan ŝlosilon!,¡Dame la maldita llave!,,Anna minulle se pahuksen avain!,Donne moi cette putain de clé!,Add ide az istenverte kulcsot!,Dammi quella dannata chiave!,いいからとっととキーを寄越せ!,그 망할 놈의 키를 건네!,Geef me die verdomde sleutel!,Gi meg den jævla nøkkelen!,Daj mi ten cholerny klucz!,Me dê a droga da chave!,,Dă-mi afurisita de cheie!,Дай мне чёртов ключ!,,Ver şu lanet anahtarı bana! +",모렐 녀석이 너에게 통행증을 줬다 해도 신경 안 써. 이곳은 이 몸이 통치하는 감옥이다! 내가 가지고 있는 열쇠만 있으면 죄인들의 자유를 맘껏 조종할 수 있지. 오더는 절대로 실수 같은걸 용납하지 않아!,Het kan me niet schelen of Mourel je een pasje heeft gegeven. Dit is mijn gevangenis. Mijn sleutel is de enige weg naar binnen of buiten en ik neem geen enkel risico. De Orde tolereert geen fouten.,"Jeg blåser i om Mourel ga deg et passerseddel. Dette er mitt fengsel. Min nøkkel er den eneste veien inn eller ut, og jeg tar ingen sjanser. Ordenen tolererer ikke feil.","Nie obchodzi mnie to, że Mourel dał ci przepustkę. To moje więzienie. Tylko mój klucz pozwala wejść lub wyjść, i nie mam zamiaru ryzykować. Zakon nie toleruje błędów.",Eu não estou nem aí se o Mourel te deu um passe. Esta é a minha prisão. A única forma de entrar ou sair é com a minha chave e eu não estou a fim de arriscar. A Ordem não tolera erros.,,"Nu-mi pasă că Mourel ți-a dat o legitimație. Asta e închisoarea mea. Cheia mea e singura cale de intrare sau ieșire, și nu risc nimic. Ordinul nu tolerează greșeli.","Мне плевать, дал ли тебе Морел пропуск или нет. Это моя тюрьма, и без моего ключа не войти и не выйти. И я не хочу рисковать — Орден не прощает ошибок!",,"Jag bryr mig inte om Mourel gav dig ett passerkort. Det här är mitt fängelse. Min nyckel är den enda vägen in eller ut, och jag tar inga risker. Orden tolererar inga misstag.",Mourel'in sana izin vermesi umurumda değil. Burası benim hapishanem. İçeri girip çıkmanın tek yolu benim anahtarım ve işimi şansa bırakmayacağım. Tarikatın hataya tahammülü yoktur. +Give me the damn key!,TXT_RPLY0_SCRIPT05_D6064_GIVEM,〃,,,Dej mi ten zatracený klíč!,Giv mig den forbandede nøgle!,Geben Sie mir den verdammten Schlüssel!,,Donu la fekan ŝlosilon!,¡Dame la maldita llave!,,Anna minulle se pahuksen avain!,Donne moi cette putain de clé!,Add ide az istenverte kulcsot!,Dammi quella dannata chiave!,いいからとっととキーを寄越せ!,그 망할 놈의 키를 건네!,Geef me die verdomde sleutel!,Gi meg den jævla nøkkelen!,Daj mi ten cholerny klucz!,Me dê a droga da chave!,,Dă-mi afurisita de cheie!,Дай мне чёртов ключ!,,Ge mig den förbannade nyckeln!,Ver şu lanet anahtarı bana! Over my dead body!,TXT_DLG_SCRIPT05_D7580_OVERM,〃,,,Jen přes mou mrtvolu!,Over mit lig!,Nur über meine Leiche!,,Nur post mia morto!,¡Primero muerto!,,Vain kuolleen ruumiini yli!,Il faudra me passer sur le corps!,Csak a holttestemen át!,Sul mio cadavere!,欲しけりゃ取りに来い。,"내 시체를 밟고 얻어라! - \cy아마 네가 “부탁”을 안 해서 이러나 봐.",Over mijn lijk!,Over mitt lik!,Po moim trupie!,Só sobre o meu cadáver!,,Doar peste cadavrul meu!,Только через мой труп!,,Cesedimi çiğneyin! -Great idea!,TXT_RPLY0_SCRIPT05_D7580_GREAT,〃,,,Skvělý nápad!,God idé!,Gute Idee!,,Bonega ideo!,¡Qué buena idea!,,Loistoidea!,Excellente idée!,Kiváló ötlet!,Ottima idea!,良い案だ!,좋은 생각이야!,Geweldig idee!,God idé!,Dobry pomysł!,Boa idéia!,,Grozavă idee!,Хорошая мысль!,,Harika bir fikir! -"Shackles or chains, I want you to hang around.",TXT_DLG_SCRIPT05_D9096_SHACK,〃,,,"Pouta či řetězy, chci tě tu vidět viset.","Lænker eller kæder, jeg vil have dig til at blive hængende.",Fesseln oder Ketten - ich will dich hier herumhängen sehen.,,"Ĉu vi volas katenojn aŭ ŝeklojn? Mi volas, ke vi ĝuu vian restadon.",¿Grilletes o cadenas? Quiero que disfrutes de tu estancia.,,"Olipa sitten kahleissa tai ketjuissa, haluan sinun jäävän pysyäksesi.",Chaînes ou menottes? J'ai vraiment envie de vous retenir!,"Mindegy hogy béklyó vagy lánc, csak lógj itt szépen.","Ferri o catene, potrai starci benissimo qua!",鎖や手錠で、繋いだ方が良いな。,"동아줄, 아님 쇠사슬... 네 목에 잘 어울리겠네. 으하하하!","Sluitingen of kettingen, ik wil dat je blijft hangen.","Lenker eller lenker, jeg vil at du skal bli her.",Kajdany czy łańcuchy? Chcę byś na chwilę tu został.,Algemas ou correntes? Quero que você fique aqui por um tempo.,,"Cătușe sau lanțuri, vreau să rămăi pe-aici.","Кандалы или цепи? Я хочу, чтобы ты подольше тут задержался.",,"Kelepçe ya da zincir, buralarda olmanı istiyorum." + \cy아마 네가 “부탁”을 안 해서 이러나 봐.",Over mijn lijk!,Over mitt lik!,Po moim trupie!,Só sobre o meu cadáver!,,Doar peste cadavrul meu!,Только через мой труп!,,Över min döda kropp!,Cesedimi çiğneyin! +Great idea!,TXT_RPLY0_SCRIPT05_D7580_GREAT,〃,,,Skvělý nápad!,God idé!,Gute Idee!,,Bonega ideo!,¡Qué buena idea!,,Loistoidea!,Excellente idée!,Kiváló ötlet!,Ottima idea!,良い案だ!,좋은 생각이야!,Geweldig idee!,God idé!,Dobry pomysł!,Boa idéia!,,Grozavă idee!,Хорошая мысль!,,Bra idé!,Harika bir fikir! +"Shackles or chains, I want you to hang around.",TXT_DLG_SCRIPT05_D9096_SHACK,〃,,,"Pouta či řetězy, chci tě tu vidět viset.","Lænker eller kæder, jeg vil have dig til at blive hængende.",Fesseln oder Ketten - ich will dich hier herumhängen sehen.,,"Ĉu vi volas katenojn aŭ ŝeklojn? Mi volas, ke vi ĝuu vian restadon.",¿Grilletes o cadenas? Quiero que disfrutes de tu estancia.,,"Olipa sitten kahleissa tai ketjuissa, haluan sinun jäävän pysyäksesi.",Chaînes ou menottes? J'ai vraiment envie de vous retenir!,"Mindegy hogy béklyó vagy lánc, csak lógj itt szépen.","Ferri o catene, potrai starci benissimo qua!",鎖や手錠で、繋いだ方が良いな。,"동아줄, 아님 쇠사슬... 네 목에 잘 어울리겠네. 으하하하!","Sluitingen of kettingen, ik wil dat je blijft hangen.","Lenker eller lenker, jeg vil at du skal bli her.",Kajdany czy łańcuchy? Chcę byś na chwilę tu został.,Algemas ou correntes? Quero que você fique aqui por um tempo.,,"Cătușe sau lanțuri, vreau să rămăi pe-aici.","Кандалы или цепи? Я хочу, чтобы ты подольше тут задержался.",,"Fängsel eller kedjor, jag vill att du stannar kvar.","Kelepçe ya da zincir, buralarda olmanı istiyorum." "I don't know how you managed to get past the guards and the Warden, but I hope you like the decor, because you just moved in.",TXT_DLG_SCRIPT05_D10612_IDONT,MAP05: Wolenick.,,,"Nemám tušení, jak se ti podařilo dostat se přes stráže a dozorce, ale doufám že se ti líbí naše výzdoba, protože jsi se právě nastěhoval.","Jeg ved ikke, hvordan det lykkedes dig at komme forbi vagterne og direktøren, men jeg håber, du kan lide indretningen, for du er lige flyttet ind.","Ich habe keine Ahnung, wie du an den Wachen und dem Direktor vorbeigekommen bist, aber ich hoffe du magst das Dekor, denn du bist gerade eingezogen.",,"Mi ne komprenas, kiel vi superis la gardistojn kaj la provoson, sed mi esperas, ke vi ŝatas la dekoracion, ĉar vi ĵus transloĝiĝis.","No sé cómo habrás pasado por los guardias y el carcelero, pero espero que te guste la decoración, porque te acabas de mudar aquí.",,"En tiedä, miten onnistuit pääsemään vartijoiden ja vankilanjohtajan läpi, mutta toivon, että pidät sisustuksesta; olethan sentään tänne juuri muuttanut.","Je ne sais pas comment vous êtes passé à travers les gardes et le gardien, mais j'espère que vous aimez le décor car ceci sera votre nouveau domicile.","Nem tudom, hogyan jutottál át az őrökön és az igazgatón, de remélem szimpatikus a hely, mert még sokáig leszel itt.","Non so come tu abbia fatto a superare il direttore o le guardie, ma spero che tu apprezzi l'ambiente, perché adesso questa sarà anche la tua prigione.","どうやってガードやセキュリティを 抜けてきたかは知らんが、私の部署に移れば、 -この素晴らしい装飾を堪能できるぞ。","그 많은 경비와 간수장을 어떻게 해서 격파한 건지는 모르겠다만, 빠른 재판을 추천하겠네. 왜냐하면 자네는 헛수고했으니까.","Ik weet niet hoe je langs de bewakers en de directeur bent gekomen, maar ik hoop dat je het decor leuk vindt, want je bent er net ingetrokken.","Jeg vet ikke hvordan du kom deg forbi vaktene og direktøren, men jeg håper du liker innredningen, for du har nettopp flyttet inn.","Nie wiem jak ominąłeś strażników i Naczelnika, ale mam nadzieję, że podoba ci się wystrój, bo właśnie tu zostaniesz.","Eu não sei como você conseguiu passar pelos guardas e pelo Carcereiro, mas espero que goste da decoração, porque você acabou de se mudar pra cá.",,"Nu știu cum ai reușit să treci de gardieni și de Director, dar sper că îți place noul decor, pentru că tocmai te-ai mutat aici.","Не знаю, как тебе удалось миновать стражу и Монтага, но, я надеюсь, тебе нравится интерьер? Потому что отсюда ты уже не выйдешь.",,Muhafızları ve Müdür'ü nasıl atlattın bilmiyorum ama umarım dekoru beğenmişsindir çünkü yeni taşındın. -Free my comrades or die!,TXT_RPLY0_SCRIPT05_D10612_FREEM,〃,,,"Osvoboď mé druhy, nebo zemři!",Befri mine kammerater eller dø!,Befreien Sie meine Kameraden oder sterben Sie!,,Liberigu miajn samideanojn aŭ mortu!,¡Libera a mis camaradas o muere!,¡Libera a mis compañeros o muere!,Vapauta toverini tai kuole!,Libère mes camarades ou meurs!,"Engedd el a társaimat, vagy meghalsz!",Libera i miei compagni o muori!,命が惜しければ仲間を解放しろ!,"내 전우를 풀어주든지, 죽든지!",Bevrijd mijn kameraden of sterf!,Befri kameratene mine eller dø!,Uwolnij moich towarzyszy lub giń!,Liberte meus companheiros ou morra!,,"Eliberează-mi camarazii, sau mori!","Освободи моих товарищей, или ты умрёшь!",,Yoldaşlarımı serbest bırak ya da öl! +この素晴らしい装飾を堪能できるぞ。","그 많은 경비와 간수장을 어떻게 해서 격파한 건지는 모르겠다만, 빠른 재판을 추천하겠네. 왜냐하면 자네는 헛수고했으니까.","Ik weet niet hoe je langs de bewakers en de directeur bent gekomen, maar ik hoop dat je het decor leuk vindt, want je bent er net ingetrokken.","Jeg vet ikke hvordan du kom deg forbi vaktene og direktøren, men jeg håper du liker innredningen, for du har nettopp flyttet inn.","Nie wiem jak ominąłeś strażników i Naczelnika, ale mam nadzieję, że podoba ci się wystrój, bo właśnie tu zostaniesz.","Eu não sei como você conseguiu passar pelos guardas e pelo Carcereiro, mas espero que goste da decoração, porque você acabou de se mudar pra cá.",,"Nu știu cum ai reușit să treci de gardieni și de Director, dar sper că îți place noul decor, pentru că tocmai te-ai mutat aici.","Не знаю, как тебе удалось миновать стражу и Монтага, но, я надеюсь, тебе нравится интерьер? Потому что отсюда ты уже не выйдешь.",,"Jag vet inte hur du lyckades ta dig förbi vakterna och fängelsedirektören, men jag hoppas att du gillar inredningen, för du har just flyttat in.",Muhafızları ve Müdür'ü nasıl atlattın bilmiyorum ama umarım dekoru beğenmişsindir çünkü yeni taşındın. +Free my comrades or die!,TXT_RPLY0_SCRIPT05_D10612_FREEM,〃,,,"Osvoboď mé druhy, nebo zemři!",Befri mine kammerater eller dø!,Befreien Sie meine Kameraden oder sterben Sie!,,Liberigu miajn samideanojn aŭ mortu!,¡Libera a mis camaradas o muere!,¡Libera a mis compañeros o muere!,Vapauta toverini tai kuole!,Libère mes camarades ou meurs!,"Engedd el a társaimat, vagy meghalsz!",Libera i miei compagni o muori!,命が惜しければ仲間を解放しろ!,"내 전우를 풀어주든지, 죽든지!",Bevrijd mijn kameraden of sterf!,Befri kameratene mine eller dø!,Uwolnij moich towarzyszy lub giń!,Liberte meus companheiros ou morra!,,"Eliberează-mi camarazii, sau mori!","Освободи моих товарищей, или ты умрёшь!",,Befria mina kamrater eller dö!,Yoldaşlarımı serbest bırak ya da öl! Kill me and you'll never set anyone free. I possess the only pattern key that will unlock the cells.,TXT_DLG_SCRIPT05_D12128_KILLM,〃,,,"Zab mě a neosvobodíš nikoho. Jenom já mám vzor, který otevře cely.","Dræb mig, og du vil aldrig sætte nogen fri. Jeg besidder den eneste mønsternøgle, der kan låse cellerne op.","Töte mich und du befreist niemanden. Ich bin der einzige, der autorisiert ist, die Gefangenen freizulassen.",,"Vi liberigos neniun se vi mortigos min: mi havas la ununuran manspuron, kiu ebligas malŝlosi la ĉelojn.",Mátame y no liberarás a nadie: poseo la única huella digital que abre las celdas.,Mátame y no vas a liberar a nadie: poseo la única huella digital que abre las celdas.,Tappamalla minut et vapauta ketään. Vain minun käsissäni ovat avaimet sellien avaamiseen.,Tuez moi et personne ne sera libéré. Je suis le seul qui possède la clé qui peut ouvrir les cellules.,"Ha megölsz, akkor senkit sem fogsz tudni kiszabadítani. Az egyetlen biztonsági kulcs az Én tulajdonomban van.",Uccidi e non libererai proprio nessuno. Posseggo l'unica chiave d'identificazione che può aprire le celle.,"私を殺せば誰も助かる事はない。 -私の指紋だけが檻を開けられるからな。",날 죽이면 일이 더 최악으로 변질될 것일세. 나에게 감옥 문을 열 수 있는 유일한 지문이 있으니 말이지.,Dood me en je zult nooit iemand vrijlaten. Ik bezit de enige patroonsleutel die de cellen zal ontsluiten.,"Dreper du meg, får du aldri satt noen fri. Jeg har den eneste mønsternøkkelen som låser opp cellene.","Zabij mnie, a już nigdy nikogo nie uwolnisz. Tylko ja mam klucz do ich cel.",Mate-me e você nunca libertará ninguém. Eu possuo a única chave que destranca as celas.,,Omoară-mă și nu vei elibera pe nimeni în veci. Eu posed singura cheie care poate deschide celulele.,"Убив меня, ты никого не освободишь. Только у меня есть ключ, которым можно открыть камеры.",,Beni öldürürsen kimseyi özgür bırakamazsın. Hücrelerin kilidini açacak tek desen anahtarı bende. -Can you lend me a hand then?,TXT_RPLY0_SCRIPT05_D12128_CANYO,〃,,,Mohl bys mi tedy půjčit ruku?,Kan du så give mig en hånd med?,Können Sie mir Ihre Hand leihen?,,Tiuokaze mi «enmanigos» ilin al vi.,"¿Me echas una mano, entonces?","¿Me das una mano, entonces?",Voisitko sitten ojentaa auttavaa kättäsi?,"Tu peux me prêter main forte, alors?",Tudsz nekem segíteni?,"Che ne dici di darmi una mano, allora?",じゃあ 手を貸して くれるか?,그럼 네 손길이 좀 필요할 것 같아...,Kun je me dan een handje helpen?,"Kan du hjelpe meg, da?",Więc może podasz mi pomocną dłoń?,Pode me dar uma mão então?,,Poți da o mână de ajutor atunci?,"Может быть, ты протянешь мне руку помощи?",,O zaman bana yardım edebilir misin? -Move along or join your friends.,TXT_DLG_SCRIPT05_D13644_MOVEA,〃,,,"Jdi, nebo se přidej ke svým kamarádům.",Gå videre eller slut dig til dine venner.,Hau ab oder zieh bei deinen Freunden ein.,,Foriru aŭ alliĝu al viaj amikoj.,Vete o únete a tus amigos.,,"Jatka eteenpäin, tai liity ystäviesi joukkoon.",Bougez ou rejoignez vos amis.,"Mozogj tovább, vagy csatlakozz a barátaidhoz.","Togliti dai piedi, o ti unirai ai tuoi amici.",共に行こう友よ。,"무죄, 아니면 사형 선고. 정하시게.",Ga mee of sluit je aan bij je vrienden.,Gå videre eller bli med vennene dine.,Idź stąd lub dołączysz do swoich przyjaciół.,Suma daqui ou junte-se aos seus amigos.,,Cară-te sau te vei alătura prietenilor tăi.,"Не подходи ко мне, или присоединишься к своим друзьям.",,İlerleyin ya da arkadaşlarınıza katılın. -"Don't just stand there, get us out of here!",TXT_DLG_SCRIPT05_D15160_DONTJ,MAP05: Prisoner.,,,"Nestůj tam tak, dostaň nás odsud!","Stå ikke bare der, få os ud herfra!","Steh da nicht so rum, hol uns raus!",,"Ne staru tie, liberigu nin!","No te quedes ahí, ¡sácanos de aquí!",,Älä vain siinä seisoskele; päästä meidät ulos täältä!,"Ne vous tenez pas là, sortez nous d'ici!","Ne csak bámészkodj, szabadíts ki minket!","Non stare lì fermo, facci uscire da qui!",もう待てない、早くここを出よう!,"거기 서 있지 말고, 어서 우릴 내보내 줘!","Blijf daar niet staan, haal ons hier weg!","Ikke bare stå der, få oss ut herfra!","Nie stój tak, uwolnij nas stąd!",Não fique parado aí. Nos tire daqui!,,"Nu sta acolo, scoate-ne de aici!",Не стой просто так. Вытащи нас отсюда!,,"Orada öylece durmayın, bizi buradan çıkarın!" -"The sky, I want to see the sky.",TXT_DLG_SCRIPT05_D16676_THESK,〃,,,"Nebe, chci vidět nebe.","Himlen, jeg vil se himlen.","Der Himmel, ich möchte den Himmel sehen.",,"La ĉielon, mi volas vidi la ĉielon.","El cielo, quiero ver el cielo.",,"Taivas, haluan nähdä taivaan.","Le ciel, je veux voir le ciel!","Az eget, szeretném újra látni az eget.","Il cielo, voglio vedere il cielo.",空を、空を見たい。,"하늘, 하늘을 보고 싶어.","De lucht, ik wil de lucht zien.","Himmelen, jeg vil se himmelen.",Niebo... tak bardzo chcę zobaczyć niebo.,O céu. Eu quero ver o céu.,,"Cerul, vreau să văd cerul!",Небо. Я хочу увидеть небо.,,"Gökyüzü, gökyüzünü görmek istiyorum." +私の指紋だけが檻を開けられるからな。",날 죽이면 일이 더 최악으로 변질될 것일세. 나에게 감옥 문을 열 수 있는 유일한 지문이 있으니 말이지.,Dood me en je zult nooit iemand vrijlaten. Ik bezit de enige patroonsleutel die de cellen zal ontsluiten.,"Dreper du meg, får du aldri satt noen fri. Jeg har den eneste mønsternøkkelen som låser opp cellene.","Zabij mnie, a już nigdy nikogo nie uwolnisz. Tylko ja mam klucz do ich cel.",Mate-me e você nunca libertará ninguém. Eu possuo a única chave que destranca as celas.,,Omoară-mă și nu vei elibera pe nimeni în veci. Eu posed singura cheie care poate deschide celulele.,"Убив меня, ты никого не освободишь. Только у меня есть ключ, которым можно открыть камеры.",,Om du dödar mig kommer du aldrig att befria någon. Jag besitter den enda mönsternyckeln som kan låsa upp cellerna.,Beni öldürürsen kimseyi özgür bırakamazsın. Hücrelerin kilidini açacak tek desen anahtarı bende. +Can you lend me a hand then?,TXT_RPLY0_SCRIPT05_D12128_CANYO,〃,,,Mohl bys mi tedy půjčit ruku?,Kan du så give mig en hånd med?,Können Sie mir Ihre Hand leihen?,,Tiuokaze mi «enmanigos» ilin al vi.,"¿Me echas una mano, entonces?","¿Me das una mano, entonces?",Voisitko sitten ojentaa auttavaa kättäsi?,"Tu peux me prêter main forte, alors?",Tudsz nekem segíteni?,"Che ne dici di darmi una mano, allora?",じゃあ 手を貸して くれるか?,그럼 네 손길이 좀 필요할 것 같아...,Kun je me dan een handje helpen?,"Kan du hjelpe meg, da?",Więc może podasz mi pomocną dłoń?,Pode me dar uma mão então?,,Poți da o mână de ajutor atunci?,"Может быть, ты протянешь мне руку помощи?",,Kan du ge mig en hand med det då?,O zaman bana yardım edebilir misin? +Move along or join your friends.,TXT_DLG_SCRIPT05_D13644_MOVEA,〃,,,"Jdi, nebo se přidej ke svým kamarádům.",Gå videre eller slut dig til dine venner.,Hau ab oder zieh bei deinen Freunden ein.,,Foriru aŭ alliĝu al viaj amikoj.,Vete o únete a tus amigos.,,"Jatka eteenpäin, tai liity ystäviesi joukkoon.",Bougez ou rejoignez vos amis.,"Mozogj tovább, vagy csatlakozz a barátaidhoz.","Togliti dai piedi, o ti unirai ai tuoi amici.",共に行こう友よ。,"무죄, 아니면 사형 선고. 정하시게.",Ga mee of sluit je aan bij je vrienden.,Gå videre eller bli med vennene dine.,Idź stąd lub dołączysz do swoich przyjaciół.,Suma daqui ou junte-se aos seus amigos.,,Cară-te sau te vei alătura prietenilor tăi.,"Не подходи ко мне, или присоединишься к своим друзьям.",,Gå vidare eller gå till dina vänner.,İlerleyin ya da arkadaşlarınıza katılın. +"Don't just stand there, get us out of here!",TXT_DLG_SCRIPT05_D15160_DONTJ,MAP05: Prisoner.,,,"Nestůj tam tak, dostaň nás odsud!","Stå ikke bare der, få os ud herfra!","Steh da nicht so rum, hol uns raus!",,"Ne staru tie, liberigu nin!","No te quedes ahí, ¡sácanos de aquí!",,Älä vain siinä seisoskele; päästä meidät ulos täältä!,"Ne vous tenez pas là, sortez nous d'ici!","Ne csak bámészkodj, szabadíts ki minket!","Non stare lì fermo, facci uscire da qui!",もう待てない、早くここを出よう!,"거기 서 있지 말고, 어서 우릴 내보내 줘!","Blijf daar niet staan, haal ons hier weg!","Ikke bare stå der, få oss ut herfra!","Nie stój tak, uwolnij nas stąd!",Não fique parado aí. Nos tire daqui!,,"Nu sta acolo, scoate-ne de aici!",Не стой просто так. Вытащи нас отсюда!,,"Stå inte bara där, ta oss härifrån!","Orada öylece durmayın, bizi buradan çıkarın!" +"The sky, I want to see the sky.",TXT_DLG_SCRIPT05_D16676_THESK,〃,,,"Nebe, chci vidět nebe.","Himlen, jeg vil se himlen.","Der Himmel, ich möchte den Himmel sehen.",,"La ĉielon, mi volas vidi la ĉielon.","El cielo, quiero ver el cielo.",,"Taivas, haluan nähdä taivaan.","Le ciel, je veux voir le ciel!","Az eget, szeretném újra látni az eget.","Il cielo, voglio vedere il cielo.",空を、空を見たい。,"하늘, 하늘을 보고 싶어.","De lucht, ik wil de lucht zien.","Himmelen, jeg vil se himmelen.",Niebo... tak bardzo chcę zobaczyć niebo.,O céu. Eu quero ver o céu.,,"Cerul, vreau să văd cerul!",Небо. Я хочу увидеть небо.,,"Himlen, jag vill se himlen.","Gökyüzü, gökyüzünü görmek istiyorum." "Five feet by four feet, five feet by four feet, five feet by four feet.",TXT_DLG_SCRIPT05_D18192_FIVEF,〃,,,"Pět kroků, čtyři kroky, pět kroků, čtyři kroky, pět kroků, čtyři kroky.","Fem fod gange fire fod, fem fod gange fire fod, fem fod gange fire fod...","Fünf Fuß mal vier Fuß, fünf Fuß mal vier Fuß, fünf Fuß mal vier Fuß...",,"1,2 oble 1,5 metroj. 1,2 oble 1,5 metroj. 1,2 oble 1,5 metroj...","Un metro y medio por un metro veinte. Un metro y medio por un metro veinte. Un metro y medio por un metro veinte...",,"Viisi kertaa neljä jalkaa, viisi kertaa neljä jalkaa, viisi kertaa neljä jalkaa.",Un mètre cinquante par un mètre trente. Un mètre cinquante par un mètre trente. Un mètre cinquante par un mètre trente.,"Öt lábszor négy láb, öt lábszor négy láb, öt lábszor négy láb.",Un metro e cinquanta per un metro e trenta. Un metro e cinquanta per un metro e trenta. Un metro e cinquanta per un metro e trenta.,"ファイブフィート バイ フォーフィート、 ファイブフィート バイ フォーフィート、 -ファイブフィート バイ フォーフィート。",나가려면 나갈 생각을 하고 나갈 준비를 해야 되는데 나갈 수가 없어 왜냐하면 나가는 걸 막는 놈들이...,"Vijf voet bij vier voet, vijf voet bij vier voet, vijf voet bij vier voet, vijf voet bij vier voet.","Fem fot ganger fire fot, fem fot ganger fire fot, fem fot ganger fire fot!","Pięć stóp na cztery, pięć stóp na cztery, pięć stóp na cztery.",Um metro e meio por um metro e vinte. Um metro e meio por um metro e vinte. Um metro e meio por um metro e vinte. ,,"Din 5 pași 4, din 5 pași 4, din 5 pași 4.","Пять футов на четыре, пять футов на четыре, пять футов на четыре.",,"Bir metreye bir metre, bir metreye bir metre, bir metreye bir metre." -Don't release me if the Order's still in charge. I can't stand the terror.,TXT_DLG_SCRIPT05_D19708_DONTR,〃,,,"Nevysvobozuj mě, jestli ještě vládne Řád. Tu hrůzu nemůžu snést.","Slip mig ikke fri, hvis Ordenen stadig har kommandoen. Jeg kan ikke klare terroren.","Bitte befreie mich nicht, wenn der Orden hier noch herrscht, ich halte den Horror nicht aus.",,Ne liberigu min se La Ordono ankoraŭ regas: mi ne eltenas la teruron.,No me sueltes si La Orden sigue al mando: no soporto el terror.,,"Älä vapauta minua, jos Veljeskunta on vielä vallassa. En kestä enää sitä hirveyttä.",Laissez moi ici si l'Ordre est toujours au pouvoir. Je ne veux pas voir cette horreur.,Ne engedj ki míg a Rend hatalmon van. Nem bírom ezt az elnyomást.,Non liberarmi se l'Ordine è ancora al potere. Non voglio vedere questo orrore.,"まだオーダーがいる内は出たくない。 -恐怖に打ち拉がれそうだ。",오더 놈들이 아직도 설치고 있다면 절 내보내지 마세요. 죽을까 봐 두려워요...,Laat me niet los als de Orde nog steeds de leiding heeft. Ik kan niet tegen de terreur.,Ikke slipp meg ut hvis Ordenen fortsatt har kommandoen. Jeg holder ikke ut terroren.,Nie uwalniaj mnie jeśli Zakon jest wciąż u władzy. Nie mogę znieść tego terroru.,Não me solte se a Ordem ainda estiver no comando. Eu não suporto o horror.,,Nu mă elibera dacă Ordinul incă e tot la putere.,"Не освобождай меня, если Орден всё ещё у власти. Я не вынесу устрашения.",,Tarikat hâlâ yetkiliyse beni bırakmayın. Dehşete dayanamıyorum. -"I don't want to bitch, but it's about time Macil sent someone to get us out.",TXT_DLG_SCRIPT05_D21224_IDONT,〃,,,"Nechci nadávat, ale už bylo na čase, aby Macil někoho poslal nás vysvobodit.","Jeg vil ikke brokke mig, men det er på tide, at Macil sender nogen ud for at få os ud.","Ich möchte ja nicht meckern, aber es wurde auch Zeit, dass Macil jemanden schickt, der uns hier rausholt",,"Mi ne intencas plendi, sed Macil finfine sendis iun por liberigi nin.","No quiero quejarme, pero ya era hora de que Macil enviara a alguien a sacarnos.",,"En halua ruikuttaa, mutta jo oli aikakin, että Macil lähetti jonkun päästämään meidät pois.","J'ai pas envie de me plaindre, mais Macil a vraiment pris son temps pour envoyer quelqu'un nous sortir d'ici!","Nem akarnék picsogni, de már ideje volt hogy Macil küldött értünk valakit.","Non è che voglio lamentarmi, però era ora che Macil mandasse qualcuno a liberarci.","意地が悪いな、だがマシルが解放の為に -誰か送ったのは大体わかる。","투정부리기는 싫지만, 드디어 사령관님이 구출작전을 실시한 것 같군요.","Ik wil niet zeuren, maar het wordt tijd dat Macil iemand stuurt om ons eruit te krijgen.","Jeg vil ikke klage, men det er på tide at Macil sender noen for å få oss ut.","Nie chcę psioczyć, ale najwyższa pora, aby Macil wysłał kogoś, by nas uwolnić.","Não quero encher o saco, mas já era hora do Macil enviar alguém para nos tirar daqui.",,"Nu vreau să mă smiorcăi, dar era și timpul ca Macil să trimită pe cineva să ne scoată afară.","Не хочу ныть, но Мэйсил мог бы и пораньше послать кого-нибудь освободить нас.",,Şikâyet etmek istemiyorum ama Macil'in bizi çıkarması için birini göndermesinin zamanı gelmişti. +ファイブフィート バイ フォーフィート。",나가려면 나갈 생각을 하고 나갈 준비를 해야 되는데 나갈 수가 없어 왜냐하면 나가는 걸 막는 놈들이...,"Vijf voet bij vier voet, vijf voet bij vier voet, vijf voet bij vier voet, vijf voet bij vier voet.","Fem fot ganger fire fot, fem fot ganger fire fot, fem fot ganger fire fot!","Pięć stóp na cztery, pięć stóp na cztery, pięć stóp na cztery.",Um metro e meio por um metro e vinte. Um metro e meio por um metro e vinte. Um metro e meio por um metro e vinte. ,,"Din 5 pași 4, din 5 pași 4, din 5 pași 4.","Пять футов на четыре, пять футов на четыре, пять футов на четыре.",,"Fem fot på fyra fot, fem fot på fyra fot, fem fot på fyra fot, fem fot på fyra fot.","Bir metreye bir metre, bir metreye bir metre, bir metreye bir metre." +Don't release me if the Order's still in charge. I can't stand the terror.,TXT_DLG_SCRIPT05_D19708_DONTR,〃,,,"Nevysvobozuj mě, jestli ještě vládne Řád. Tu hrůzu nemůžu snést.","Slip mig ikke fri, hvis Ordenen stadig har kommandoen. Jeg kan ikke klare terroren.","Bitte befreie mich nicht, wenn der Orden hier noch herrscht, ich halte den Horror nicht aus.",,Ne liberigu min se La Ordeno ankoraŭ regas: mi ne eltenas la teruron.,No me sueltes si La Orden sigue al mando: no soporto el terror.,,"Älä vapauta minua, jos Veljeskunta on vielä vallassa. En kestä enää sitä hirveyttä.",Laissez moi ici si l'Ordre est toujours au pouvoir. Je ne veux pas voir cette horreur.,Ne engedj ki míg a Rend hatalmon van. Nem bírom ezt az elnyomást.,Non liberarmi se l'Ordine è ancora al potere. Non voglio vedere questo orrore.,"まだオーダーがいる内は出たくない。 +恐怖に打ち拉がれそうだ。",오더 놈들이 아직도 설치고 있다면 절 내보내지 마세요. 죽을까 봐 두려워요...,Laat me niet los als de Orde nog steeds de leiding heeft. Ik kan niet tegen de terreur.,Ikke slipp meg ut hvis Ordenen fortsatt har kommandoen. Jeg holder ikke ut terroren.,Nie uwalniaj mnie jeśli Zakon jest wciąż u władzy. Nie mogę znieść tego terroru.,Não me solte se a Ordem ainda estiver no comando. Eu não suporto o horror.,,Nu mă elibera dacă Ordinul incă e tot la putere.,"Не освобождай меня, если Орден всё ещё у власти. Я не вынесу устрашения.",,Släpp inte ut mig om Orden fortfarande har befälet. Jag står inte ut med skräcken.,Tarikat hâlâ yetkiliyse beni bırakmayın. Dehşete dayanamıyorum. +"I don't want to bitch, but it's about time Macil sent someone to get us out.",TXT_DLG_SCRIPT05_D21224_IDONT,〃,,,"Nechci nadávat, ale už bylo na čase, aby Macil někoho poslal nás vysvobodit.","Jeg vil ikke brokke mig, men det er på tide, at Macil sender nogen ud for at få os ud.","Ich möchte ja nicht meckern, aber es wurde auch Zeit, dass Macil jemanden schickt, der uns hier rausholt",,"Mi ne intencas plendi, sed Macil finfine venigis iun por liberigi nin.","No es por quejarme, pero ya era hora de que Macil enviara alguien a sacarnos.",,"En halua ruikuttaa, mutta jo oli aikakin, että Macil lähetti jonkun päästämään meidät pois.","J'ai pas envie de me plaindre, mais Macil a vraiment pris son temps pour envoyer quelqu'un nous sortir d'ici!","Nem akarnék picsogni, de már ideje volt hogy Macil küldött értünk valakit.","Non è che voglio lamentarmi, però era ora che Macil mandasse qualcuno a liberarci.","意地が悪いな、だがマシルが解放の為に +誰か送ったのは大体わかる。","투정부리기는 싫지만, 드디어 사령관님이 구출작전을 실시한 것 같군요.","Ik wil niet zeuren, maar het wordt tijd dat Macil iemand stuurt om ons eruit te krijgen.","Jeg vil ikke klage, men det er på tide at Macil sender noen for å få oss ut.","Nie chcę psioczyć, ale najwyższa pora, aby Macil wysłał kogoś, by nas uwolnić.","Não quero encher o saco, mas já era hora do Macil enviar alguém para nos tirar daqui.",,"Nu vreau să mă smiorcăi, dar era și timpul ca Macil să trimită pe cineva să ne scoată afară.","Не хочу ныть, но Мэйсил мог бы и пораньше послать кого-нибудь освободить нас.",,"Jag vill inte vara taskig, men det är på tiden att Macil skickar någon för att få ut oss.",Şikâyet etmek istemiyorum ama Macil'in bizi çıkarması için birini göndermesinin zamanı gelmişti. I'd give anything for just a crust of bread. I'm so hungry.,TXT_DLG_SCRIPT05_D22740_IDGIV,〃,,,Dal bych cokoliv jen za kůrku chleba. Mám takový hlad.,Jeg ville give alt for bare en brødskorpe. Jeg er så sulten.,Ich gäbe alles für eine Brotkruste. Ich habe so einen Hunger.,,Mi interŝanĝus ion ajn kontraŭ panero. Mi malsategas.,Daría lo que fuera por una migaja de pan. Tengo tanta hambre.,Daría lo que fuera por una miga de pan. Tengo tanta hambre.,Antaisin mitä vain yhdestäkin leivän murenesta. Minulla on niin nälkä.,Je donnerai n'importe quoi pour une bouchée de pain. J'ai tellement faim!,"Bármit megadnék egy falat kenyérért, annyira nagyon éhes vagyok.",Darei qualsiasi cosa per una crosta di pane. Ho una grande fame.,"いつもパンの耳ばかりだったんだ。 -すごく腹減った。",빵 한 조각이라도 먹고 싶습니다... 너무 배고파요...,Ik zou alles geven voor een korstje brood. Ik heb zo'n honger.,Jeg ville gitt hva som helst for en brødskive. Jeg er så sulten.,Oddałbym wszystko za kromkę chleba. Jestem taki głodny.,Eu daria qualquer coisa por uma migalha de pão. Estou tão faminto.,,Aș da orice pentru o coajă de pâine. Sunt așa flămând.,Я бы всё отдал просто за ломоть хлеба. Я так голоден.,,Bir lokma ekmek için her şeyimi verirdim. Çok acıktım. -"Ah, a surfacer in need of a favor. Down here you do a favor to get a favor and I need the town entrance that is our path to food opened. The Order has it sealed and guarded.",TXT_DLG_SCRIPT06_D0_AHASU,MAP06: Weran.,,"Ah, a surfacer in need of a favour. Down here you do a favour to get a favour and I need the town entrance that is our path to food opened. The Order has it sealed and guarded.","Á, nadzemník, který potřebuje službu. Tady dole prokazuješ službu, abys dostal službu, a já potřebuju otevřít vchod do města, abychom měli cestu k jídlu. Řád ji nechal zapečetit a hlídat.","Ah, en overfladebeboer, der har brug for en tjeneste. Her nede gør man en tjeneste for at få en tjeneste, og jeg har brug for at få åbnet byens indgang, som er vores vej til mad. Ordenen har den forseglet og bevogtet.","Oh, ein Oberflächler, der Hilfe braucht. Hier unten musst du uns einen Gefallen erweisen, bevor wir dir helfen können. Der Ausgang zur Stadt, der unser Zugang zu Nahrung ist, muss wieder freigemacht werden. Der Orden hat ihn verschlossen und lässt ihn bewachen.",,"Ha, surfaco-loĝanto bezonas komplezon. Ĉi-malsupre oni faras servon por gajni reservon, kaj mi bezonas la enirejon al la urbo, kiu estas nia fonto de manĝaĵoj, malfermitan: La Ordono ĝin ŝlosis kaj gardas.","Ah, alguien de la superficie que necesita un favor. Aquí abajo se ofrece un favor a cambio de otro, y necesito abierta la entrada al pueblo que es nuestro camino a la comida: La Orden la tiene cerrada y con vigilancia.",,"Jaahas, maanpintalainen palveluksen tarpeessa. Täällä alhaalla on tapana tehdä palvelus palveluksesta, ja minä haluan, että kaupungin sisäänkäynti, tiemme ruuan pariin, avataan. Se on salvattu ja vartioitu Veljeskunnan toimesta.","Ah, quelqu'un de la surface qui a besoin d'une faveur. Ici, on en fait une pour en avoir une, et j'ai besoin que l'entrée de la ville qui est notre chemin pour les vivres ouverte. L'Ordre l'a scellée et mise sous garde.","Nahát, egy felszínlakó aki szívességet kér. Itt az a szokás, hogy egy szívességért cserébe szívesség dukál. Ahhoz, hogy elérhetővé válljon mindenki számára a élelem, kell egy biztonságos belépő a városba. A Rend nagy biztonságban őrzi.","Ah, un abitante della superficie che ha bisogno di un favore. Quaggiù tu fai un favore per ottenere un favore, e io ho bisogno che l'ingresso alla città venga aperto visto che è il nostro accesso al cibo. L'Ordine l'ha chiuso e lo sorveglia.","あー、何か用があって上から来たんだな。 +すごく腹減った。",빵 한 조각이라도 먹고 싶습니다... 너무 배고파요...,Ik zou alles geven voor een korstje brood. Ik heb zo'n honger.,Jeg ville gitt hva som helst for en brødskive. Jeg er så sulten.,Oddałbym wszystko za kromkę chleba. Jestem taki głodny.,Eu daria qualquer coisa por uma migalha de pão. Estou tão faminto.,,Aș da orice pentru o coajă de pâine. Sunt așa flămând.,Я бы всё отдал просто за ломоть хлеба. Я так голоден.,,Jag skulle ge vad som helst för bara en skorpa bröd. Jag är så hungrig.,Bir lokma ekmek için her şeyimi verirdim. Çok acıktım. +"Ah, a surfacer in need of a favor. Down here you do a favor to get a favor and I need the town entrance that is our path to food opened. The Order has it sealed and guarded.",TXT_DLG_SCRIPT06_D0_AHASU,MAP06: Weran.,,"Ah, a surfacer in need of a favour. Down here you do a favour to get a favour and I need the town entrance that is our path to food opened. The Order has it sealed and guarded.","Á, nadzemník, který potřebuje službu. Tady dole prokazuješ službu, abys dostal službu, a já potřebuju otevřít vchod do města, abychom měli cestu k jídlu. Řád ji nechal zapečetit a hlídat.","Ah, en overfladebeboer, der har brug for en tjeneste. Her nede gør man en tjeneste for at få en tjeneste, og jeg har brug for at få åbnet byens indgang, som er vores vej til mad. Ordenen har den forseglet og bevogtet.","Oh, ein Oberflächler, der Hilfe braucht. Hier unten musst du uns einen Gefallen erweisen, bevor wir dir helfen können. Der Ausgang zur Stadt, der unser Zugang zu Nahrung ist, muss wieder freigemacht werden. Der Orden hat ihn verschlossen und lässt ihn bewachen.",,"Ha, surfaco-loĝanto bezonas komplezon. Ĉi-malsupre oni faras servon por gajni reservon, kaj mi bezonas remalfermi la enirejon al la urbo, kiu estas nia fonto de manĝaĵoj: La Ordeno ĝin ŝlosis kaj gardas.","Ah, alguien de la superficie que necesita un favor. Aquí abajo se ofrece un favor a cambio de otro, y necesito abierta la entrada al pueblo que es nuestro camino a la comida: La Orden la tiene cerrada y con vigilancia.",,"Jaahas, maanpintalainen palveluksen tarpeessa. Täällä alhaalla on tapana tehdä palvelus palveluksesta, ja minä haluan, että kaupungin sisäänkäynti, tiemme ruuan pariin, avataan. Se on salvattu ja vartioitu Veljeskunnan toimesta.","Ah, quelqu'un de la surface qui a besoin d'une faveur. Ici, on en fait une pour en avoir une, et j'ai besoin que l'entrée de la ville qui est notre chemin pour les vivres ouverte. L'Ordre l'a scellée et mise sous garde.","Nahát, egy felszínlakó aki szívességet kér. Itt az a szokás, hogy egy szívességért cserébe szívesség dukál. Ahhoz, hogy elérhetővé válljon mindenki számára a élelem, kell egy biztonságos belépő a városba. A Rend nagy biztonságban őrzi.","Ah, un abitante della superficie che ha bisogno di un favore. Quaggiù tu fai un favore per ottenere un favore, e io ho bisogno che l'ingresso alla città venga aperto visto che è il nostro accesso al cibo. L'Ordine l'ha chiuso e lo sorveglia.","あー、何か用があって上から来たんだな。 だがここでは物々交換が常識だ、 オーダーが町の出口を封鎖しやがったから -メシが手に入り辛くなったんだ。","아아... 도움이 필요한 지상인이구려. 도움을 받고 싶으면, 우리에게 도움이 되어야 할 것이야. 식량을 구할 수 있는 마을로 향하는 입구가 오더에 의해 막혔거단.","Ah, een verharder die een gunst nodig heeft. Hier beneden doe je een gunst om een gunst te krijgen en ik heb de stadstoegang nodig die onze weg naar eten is geopend. De Orde heeft het verzegeld en bewaakt.","Ah, en overflateboer som trenger en tjeneste. Her nede gjør man en tjeneste for å få en tjeneste, og jeg må få åpnet inngangen til byen som er vår vei til mat. Ordenen har den forseglet og bevoktet.","Ah, powierzchniowiec potrzebujący pomocy. Tutaj na dole robi się to tak: przysługa za przysługę, a ja potrzebuję otworzyć wyjście do miasta, które jest naszą jedyną drogą by zdobyć jedzenie. Zakon je zablokował i pilnie go strzeże.","Ah, um cara da superfície precisando de um favor. Aqui embaixo você faz um favor para conseguir um favor e eu preciso da entrada da cidade aberta para pegar a nossa comida. A Ordem mantém ela fechada e guardada.",,"Ah, un locuitor de la suprafață care are nevoie de o favoare. Aici jos faci o favoare, primești o favoare, iar eu am nevoie de o cale pentru a ajunge la intrarea din oraș, să putem avea acces la provizii. Ordinul a închis-o și acum e bine păzită.","А-а, гостю с поверхности нужно одолжение. Здесь, внизу, ты должен что-то сделать, прежде чем о чём-то попросить, и мне нужно, чтобы дверь в город, наш путь к пище, была открыта. Орден закрыл её и поставил охрану.",,İyiliğe ihtiyacı olan bir yüzey araştırmacısı. Burada bir iyilik için bir iyilik yaparsın ve ben de yiyecek yolumuz olan kasaba girişinin açılmasını istiyorum. Tarikat orayı mühürledi ve koruyor. -Where is the gate mechanism?,TXT_RPLY0_SCRIPT06_D0_WHERE,〃,,,Kde je mechanismus brány?,Hvor er portmekanismen?,Wo ist der Tormechanismus?,,Kie estas la mekanismo de la kastelpordo?,¿Dónde está el mecanismo de la puerta?,,Missä on portin koneisto?,Où se trouve le mécanisme d'ouverture de la porte?,Hol van a kapu szerkezet?,Dov'è il meccanismo per il cancello?,ゲートメカニズムは何処だ?,성문 관리 장치는 어딨지?,Waar is het poortmechanisme?,Hvor er portmekanismen?,Gdzie jest mechanizm sterujący bramą?,Onde fica o mecanismo do portão?,,Unde e mecanismul de acționare al porții?,Где механизм управления воротами?,,Kapı mekanizması nerede? +メシが手に入り辛くなったんだ。","아아... 도움이 필요한 지상인이구려. 도움을 받고 싶으면, 우리에게 도움이 되어야 할 것이야. 식량을 구할 수 있는 마을로 향하는 입구가 오더에 의해 막혔거단.","Ah, een verharder die een gunst nodig heeft. Hier beneden doe je een gunst om een gunst te krijgen en ik heb de stadstoegang nodig die onze weg naar eten is geopend. De Orde heeft het verzegeld en bewaakt.","Ah, en overflateboer som trenger en tjeneste. Her nede gjør man en tjeneste for å få en tjeneste, og jeg må få åpnet inngangen til byen som er vår vei til mat. Ordenen har den forseglet og bevoktet.","Ah, powierzchniowiec potrzebujący pomocy. Tutaj na dole robi się to tak: przysługa za przysługę, a ja potrzebuję otworzyć wyjście do miasta, które jest naszą jedyną drogą by zdobyć jedzenie. Zakon je zablokował i pilnie go strzeże.","Ah, um cara da superfície precisando de um favor. Aqui embaixo você faz um favor para conseguir um favor e eu preciso da entrada da cidade aberta para pegar a nossa comida. A Ordem mantém ela fechada e guardada.",,"Ah, un locuitor de la suprafață care are nevoie de o favoare. Aici jos faci o favoare, primești o favoare, iar eu am nevoie de o cale pentru a ajunge la intrarea din oraș, să putem avea acces la provizii. Ordinul a închis-o și acum e bine păzită.","А-а, гостю с поверхности нужно одолжение. Здесь, внизу, ты должен что-то сделать, прежде чем о чём-то попросить, и мне нужно, чтобы дверь в город, наш путь к пище, была открыта. Орден закрыл её и поставил охрану.",,"Ah, en ytmänniska i behov av en tjänst. Här nere gör man en tjänst för att få en tjänst och jag behöver öppna stadens ingång som är vår väg till mat. Orden har förseglat och bevakat den.",İyiliğe ihtiyacı olan bir yüzey araştırmacısı. Burada bir iyilik için bir iyilik yaparsın ve ben de yiyecek yolumuz olan kasaba girişinin açılmasını istiyorum. Tarikat orayı mühürledi ve koruyor. +Where is the gate mechanism?,TXT_RPLY0_SCRIPT06_D0_WHERE,〃,,,Kde je mechanismus brány?,Hvor er portmekanismen?,Wo ist der Tormechanismus?,,Kie estas la mekanismo de la pordo de la kastelo?,¿Dónde está el mecanismo de la puerta?,,Missä on portin koneisto?,Où se trouve le mécanisme d'ouverture de la porte?,Hol van a kapu szerkezet?,Dov'è il meccanismo per il cancello?,ゲートメカニズムは何処だ?,성문 관리 장치는 어딨지?,Waar is het poortmechanisme?,Hvor er portmekanismen?,Gdzie jest mechanizm sterujący bramą?,Onde fica o mecanismo do portão?,,Unde e mecanismul de acționare al porții?,Где механизм управления воротами?,,Var är grindmekanismen?,Kapı mekanizması nerede? "Do my favor first, or you'll get squat from me.",TXT_DLG_SCRIPT06_D1516_DOMYF,〃,,"Do my favour first, or you'll get squat from me.","Prokaž mi službu, nebo ode mne nedostaneš nic.","Gør mig en tjeneste først, ellers får du ikke en skid af mig.",Tu erst mir einen Gefallen oder ich sage gar nichts.,,Vi unue faru mian komplezon se vi volas ricevi ion de mi.,Cumple mi favor primero o no tendrás nada de mí.,Cumple mi favor primero o no vas a tener nada de mí.,"Tee minun palveluspyyntöni ensin, tai et saa minulta mitään.",Faites moi une faveur ou vous n'aurez rien.,"Jobban jársz ha az én szívességemet teljesíted, mert különben lópikulát se kapsz.","Fai il mio favore prima, o da me non otterrai nulla.",俺の言った問題が先だ、でないと手助けできねえ。,"나를 도와주려, 아니면 너를 도륙할 거랴! - \cy다들 참 궁색하게 사네.","Doe me eerst een plezier, of je krijgt een hurkzitje van mij.","Gjør meg en tjeneste først, ellers får du ikke en dritt av meg.",Zrób najpierw to o co cię prosiłem lub figę dostaniesz.,"Faça o meu favor primeiro, ou você não recebe coisa nenhuma de mim.",,"Fă-mi favoarea mai întâi, sau nu-ți zic nimic.","Сначала выполни мою просьбу, или ты ничего не получишь.",,"Önce benim iyiliğimi yap, yoksa benden hiçbir şey alamazsın." -How will you know it's open?,TXT_RPLY0_SCRIPT06_D1516_HOWWI,〃,,,"Jak budeš vědět, že je otevřená?","Hvordan vil du vide, at den er åben?","Wodurch wirst du wissen, ob er offen ist?",,Kiel vi scios ĉu mi malfermis ĝin?,¿Cómo sabrás si está abierta?,¿Cómo vas a comprobar si la abrí?,"Mistä tiedät, että se on auki?",Comment est-ce que je saurais qu'elle est ouverte?,"Honnan tudod, hogy nyitva lesz?",Come farai a sapere che è aperto?,開放を知らせるには?,어떻게 도와주면 방법을 알 수 있지?,Hoe weet je dat het open is?,Hvordan vet du at den er åpen?,"Skąd będziesz wiedział, że jest już otwarta?",Como você vai saber que ela está aberta?,,Cum vei știi că e deschisă?,"Как ты узнаешь, что дверь открыта?",,Açık olduğunu nereden bileceksin? + \cy다들 참 궁색하게 사네.","Doe me eerst een plezier, of je krijgt een hurkzitje van mij.","Gjør meg en tjeneste først, ellers får du ikke en dritt av meg.",Zrób najpierw to o co cię prosiłem lub figę dostaniesz.,"Faça o meu favor primeiro, ou você não recebe coisa nenhuma de mim.",,"Fă-mi favoarea mai întâi, sau nu-ți zic nimic.","Сначала выполни мою просьбу, или ты ничего не получишь.",,"Gör mig en tjänst först, annars får du inget från mig.","Önce benim iyiliğimi yap, yoksa benden hiçbir şey alamazsın." +How will you know it's open?,TXT_RPLY0_SCRIPT06_D1516_HOWWI,〃,,,"Jak budeš vědět, že je otevřená?","Hvordan vil du vide, at den er åben?","Wodurch wirst du wissen, ob er offen ist?",,Kiel vi scios ĉu mi malfermis ĝin?,¿Cómo sabrás si está abierta?,¿Cómo vas a comprobar si la abrí?,"Mistä tiedät, että se on auki?",Comment est-ce que je saurais qu'elle est ouverte?,"Honnan tudod, hogy nyitva lesz?",Come farai a sapere che è aperto?,開放を知らせるには?,어떻게 도와주면 방법을 알 수 있지?,Hoe weet je dat het open is?,Hvordan vet du at den er åpen?,"Skąd będziesz wiedział, że jest już otwarta?",Como você vai saber que ela está aberta?,,Cum vei știi că e deschisă?,"Как ты узнаешь, что дверь открыта?",,Hur vet du att den är öppen?,Açık olduğunu nereden bileceksin? Bring me back the guard's uniform. That way one of my ratfellows can wear it and no one will try to shut the door again.,TXT_DLG_SCRIPT06_D3032_BRING,〃,,,"Přines mi uniformu stráže, pak ji jeden z mých krysaříků může nosit a nikdo se už nepokusí ty dveře zavřít.","Giv mig vagtens uniform tilbage. På den måde kan en af mine rottefæller bære den, og ingen vil forsøge at lukke døren igen.","Bring mir die Uniform des Wächters. So kann einer meiner Rattenkumpel sie tragen und niemand wird wieder versuchen, die Tür zu schließen.",,"Alportu la uniformon de la gardisto, tiel unu el miaj «kamaratoj» surhavos ĝin kaj tiam neniu provos reŝlosi la pordon.","Tráeme el uniforme del guardia, así uno de mis «camarratas» podrá ponérselo para que nadie intente cerrarla de nuevo.","Tráeme el uniforme del guardia, así uno de mis «camarratas» va a poder ponérselo para que nadie intente cerrarla de nuevo.","Tuo minulle vartijan univormu. Silloin yksi rottakumppaneistani voi pitää sitä yllään, eikä kukaan yritä sulkea ovea enää uudelleen.","Ramenez moi l'uniforme du garde. Comme ça, un de mes amis rats pourra le porter et personne n'essaiera de fermer cette porte.","Hozd nekem vissza az őr egyenruháját. Az egyik besúgom felveszi, és nem lesz többé zárt ajtó előtte.",Portami l'uniforme della guardia. In questo modo uno dei nostri può indossarla e nessuno proverà più a chiudere la porta.,"ガードの制服を持ってくればいい。 そうすりゃ成り代わったラットの仲間が もう封鎖されないよう監視するだろうさ。 ","오더 병사가 입고 있는 전투복을 가져오려. 내 걸인 동료가 그걸 입고 입구를 걱정 없이 영원히 열 수 있게. - \cy끝내준다. 이제 시궁쥐 왕의 심부름도 해야 한다니.",Breng me het uniform van de bewaker terug. Op die manier kan een van mijn rattenvrienden het dragen en niemand zal proberen de deur weer te sluiten.,"Gi meg vaktuniformen. På den måten kan en av mine rottekamerater ha den på seg, og ingen vil prøve å lukke døren igjen.",Przynieś mi mundur strażnika. Tym sposobem jeden z moich szczurokolegów będzie mógł go założyć i nikt nie spróbuje znowu zamknąć drzwi.,Me traga de volta o uniforme do guarda. Dessa forma um dos meus companheiros pode vestí-la e ninguém vai tentar fechar a porta novamente.,,"Adu-mi uniforma gardianului. Așa, unui dintre noi o va putea purta și nimeni nu va încerca să mai închidă poata vreodată.","Принеси мне униформу стражника. Тогда один из моих приятелей сможет носить её, и никто не попытается снова закрыть дверь.",,Bana muhafız üniformasını geri getir. Böylece hain dostlarımdan biri onu giyebilir ve kimse kapıyı tekrar kapatmaya çalışmaz. -You want his uniform?,TXT_RPLY0_SCRIPT06_D3032_YOUWA,〃,,,Ty chceš jeho uniformu?,Vil du have hans uniform?,Du möchtest seine Uniform haben?,,Ĉu vi volas lian uniformon?,¿Quieres su uniforme?,,Haluat siis tämän univormun?,Vous voulez son uniforme?,Kell az egyenruhája?,Vuoi la sua uniforme?,あんたに制服を渡せばいいか?,그 전투복이 정말로 필요한가?,Wil je zijn uniform?,Vil du ha uniformen hans?,Chcesz jego mundur?,Você quer o uniforme dele?,,Vrei uniforma lui?,Тебе нужна его форма?,,Üniformasını mı istiyorsun? + \cy끝내준다. 이제 시궁쥐 왕의 심부름도 해야 한다니.",Breng me het uniform van de bewaker terug. Op die manier kan een van mijn rattenvrienden het dragen en niemand zal proberen de deur weer te sluiten.,"Gi meg vaktuniformen. På den måten kan en av mine rottekamerater ha den på seg, og ingen vil prøve å lukke døren igjen.",Przynieś mi mundur strażnika. Tym sposobem jeden z moich szczurokolegów będzie mógł go założyć i nikt nie spróbuje znowu zamknąć drzwi.,Me traga de volta o uniforme do guarda. Dessa forma um dos meus companheiros pode vestí-la e ninguém vai tentar fechar a porta novamente.,,"Adu-mi uniforma gardianului. Așa, unui dintre noi o va putea purta și nimeni nu va încerca să mai închidă poata vreodată.","Принеси мне униформу стражника. Тогда один из моих приятелей сможет носить её, и никто не попытается снова закрыть дверь.",,Ge mig vaktens uniform. På så sätt kan en av mina råttföljeslagare bära den och ingen kommer att försöka stänga dörren igen.,Bana muhafız üniformasını geri getir. Böylece hain dostlarımdan biri onu giyebilir ve kimse kapıyı tekrar kapatmaya çalışmaz. +You want his uniform?,TXT_RPLY0_SCRIPT06_D3032_YOUWA,〃,,,Ty chceš jeho uniformu?,Vil du have hans uniform?,Du möchtest seine Uniform haben?,,Ĉu vi volas lian uniformon?,¿Quieres su uniforme?,,Haluat siis tämän univormun?,Vous voulez son uniforme?,Kell az egyenruhája?,Vuoi la sua uniforme?,あんたに制服を渡せばいいか?,그 전투복이 정말로 필요한가?,Wil je zijn uniform?,Vil du ha uniformen hans?,Chcesz jego mundur?,Você quer o uniforme dele?,,Vrei uniforma lui?,Тебе нужна его форма?,,Vill du ha hans uniform?,Üniformasını mı istiyorsun? "Open the door, bring me the uniform and we trade. Otherwise, piss off.",TXT_DLG_SCRIPT06_D4548_OPENT,〃,,,"Otevři dveře, přines mi uniformu a budeme obchodovat. Jinak se jdi vycpat.","Åbn døren, giv mig uniformen, og vi bytter. Ellers skal du gå ud.","Öffne die Tür, bring mir die Uniform und wir können handeln. Ansonsten verschwinde.",,"Malfermu la pordon, alportu la uniformon kaj tiam ni intertraktos. Alie, malaperu.","Abre la puerta, tráeme el uniforme y negociamos. Si no, pírate.","Abre la puerta, tráeme el uniforme y negociamos. Caso contrario, esfúmate.","Avaa ovi, tuo minulle univormu ja teemme vaihtokaupan. Muuten suksi suohon.","Ouvrez la porte, ramenez moi l'uniforme et nous ferons affaire. Sinon, barrez-vous.","Nyisd k iaz ajtót, add ide az egyenruhát és üzletelhetünk. Ha nem, akkor húzz a túróba.","Apri l'ingresso, portami l'uniforme e allora possiamo trattare. Altrimenti, non abbiamo nulla da dirci.","そうだ、ゲートを開いて制服を奪うんだ。 それまで戻ってくるんじゃねえぞ。","입구를 열고, 전투복을 구해서, 교환 하자구려! 아님... 꺼지시라. - \cy얘도 분명 냄새 하나는 죽여줄 거야.","Open de deur, breng me het uniform en we handelen. Anders, piss off.","Åpne døra, gi meg uniformen, så bytter vi. Ellers kan du dra til helvete.",Otwórz drzwi i przynieś mundur to się dogadamy. Jeśli nie to spadaj.,"Abra a porta, traga o uniforme e nós negociaremos. Caso contrário, vaza daqui.",,"Deschide poarta, adu-mi uniforma, și facem schimbul. Altfel, șterge-o de aici.","Открой эту дверь, принеси мне униформу и мы сторгуемся. Иначе, отвали.",,"Kapıyı aç, bana üniformayı getir ve takas edelim. Yoksa defol git." -Have you brought me what I want?,TXT_DLG_SCRIPT06_D6064_HAVEY,〃,,,"Přinesl jsi mi, co chci?","Har du bragt mig det, jeg vil have?",Hast du mir was mitgebracht?,,"Ĉu vi alportis tion, kion mi volas?",¿Me has traído lo que quiero?,¿Trajiste lo que quiero?,"Oletko tuonut minulle sen, mitä haluan?",Avez-vous ramené ce dont j'ai besoin?,"Elhoztad, amit kértem?",Mi hai portato ciò che volevo?,必要な物は持ってきたか?,내가 원하는 것을 가지고 왔나랴?,Heb je me gebracht wat ik wil?,Har du det jeg vil ha?,Przyniosłeś to o co cię prosiłem?,Você trouxe o que eu quero?,,Mi-ai adus ceea ce doresc?,"Ты принёс мне то, что я просил?",,İstediğim şeyi getirdin mi? -How about this uniform?,TXT_RPLY0_SCRIPT06_D6064_HOWAB,〃,,,Co tahle uniforma?,Hvad med denne uniform?,Wie findest du diese Uniform?,,Kion pri ĉi tiu uniformo?,¿Qué tal este uniforme?,¿Qué hay de este uniforme?,Miten olisi tämä univormu?,"Il vous convient, cet uniforme?",És mi az újság ezzel az egyenruhával?,Che ne dici di questa uniforme?,この制服はどうだ?,이 전투복은 어때?,Hoe zit het met dit uniform?,Hva med denne uniformen?,Może być ten mundur?,Que tal este uniforme?,,Ce zici de uniforma asta?,Эта униформа подойдёт?,,Bu üniformaya ne dersin? -Bring me the uniform.,TXT_RNO0_SCRIPT06_D6064_BRING,,,,Přines mi tu uniformu.,Giv mig hans uniform.,Bring mir seine Uniform.,,Alportu la uniformon.,Tráeme el uniforme.,,Tuo univormu minulle.,Amenez moi l'uniforme.,Hozdd ide az egyenruhát.,Portami l'uniforme.,制服を持ってこい。,전투복을 가져와랴...,Breng me het uniform.,Gi meg uniformen.,Przynieś mi mundur.,Me traga o uniforme.,,Adu-mi uniforma.,Принеси мне униформу.,,Bana üniformayı getir. + \cy얘도 분명 냄새 하나는 죽여줄 거야.","Open de deur, breng me het uniform en we handelen. Anders, piss off.","Åpne døra, gi meg uniformen, så bytter vi. Ellers kan du dra til helvete.",Otwórz drzwi i przynieś mundur to się dogadamy. Jeśli nie to spadaj.,"Abra a porta, traga o uniforme e nós negociaremos. Caso contrário, vaza daqui.",,"Deschide poarta, adu-mi uniforma, și facem schimbul. Altfel, șterge-o de aici.","Открой эту дверь, принеси мне униформу и мы сторгуемся. Иначе, отвали.",,"Öppna dörren, ge mig uniformen och vi byter. Annars kan du dra åt helvete.","Kapıyı aç, bana üniformayı getir ve takas edelim. Yoksa defol git." +Have you brought me what I want?,TXT_DLG_SCRIPT06_D6064_HAVEY,〃,,,"Přinesl jsi mi, co chci?","Har du bragt mig det, jeg vil have?",Hast du mir was mitgebracht?,,"Ĉu vi alportis tion, kion mi volas?",¿Me has traído lo que quiero?,¿Trajiste lo que quiero?,"Oletko tuonut minulle sen, mitä haluan?",Avez-vous ramené ce dont j'ai besoin?,"Elhoztad, amit kértem?",Mi hai portato ciò che volevo?,必要な物は持ってきたか?,내가 원하는 것을 가지고 왔나랴?,Heb je me gebracht wat ik wil?,Har du det jeg vil ha?,Przyniosłeś to o co cię prosiłem?,Você trouxe o que eu quero?,,Mi-ai adus ceea ce doresc?,"Ты принёс мне то, что я просил?",,Har du gett mig det jag vill ha?,İstediğim şeyi getirdin mi? +How about this uniform?,TXT_RPLY0_SCRIPT06_D6064_HOWAB,〃,,,Co tahle uniforma?,Hvad med denne uniform?,Wie findest du diese Uniform?,,Kion pri ĉi tiu uniformo?,¿Qué tal este uniforme?,¿Qué hay de este uniforme?,Miten olisi tämä univormu?,"Il vous convient, cet uniforme?",És mi az újság ezzel az egyenruhával?,Che ne dici di questa uniforme?,この制服はどうだ?,이 전투복은 어때?,Hoe zit het met dit uniform?,Hva med denne uniformen?,Może być ten mundur?,Que tal este uniforme?,,Ce zici de uniforma asta?,Эта униформа подойдёт?,,Vad sägs om den här uniformen?,Bu üniformaya ne dersin? +Bring me the uniform.,TXT_RNO0_SCRIPT06_D6064_BRING,,,,Přines mi tu uniformu.,Giv mig hans uniform.,Bring mir seine Uniform.,,Alportu la uniformon.,Tráeme el uniforme.,,Tuo univormu minulle.,Amenez moi l'uniforme.,Hozdd ide az egyenruhát.,Portami l'uniforme.,制服を持ってこい。,전투복을 가져와랴...,Breng me het uniform.,Gi meg uniformen.,Przynieś mi mundur.,Me traga o uniforme.,,Adu-mi uniforma.,Принеси мне униформу.,,Ge mig uniformen.,Bana üniformayı getir. "Good. Here's something extra. My fellows tore this off of a fallen Crusader, it's the parts that make up a flamethrower. Now Irale can make one for you. You can have such fun.",TXT_DLG_SCRIPT06_D7580_GOODH,MAP06: Weran.,,,"Dobře. Tady je něco navíc. Mí stoupenci tohle urvali ze zničeného Křižáka, jsou to části, ze kterých se skládá plamenomet. Teď ti jeden může Irale postavit. Můžeš mít takové legrace.","Godt. Her er noget ekstra. Mine kammerater rev den af en faldet korsfarer, det er de dele, der udgør en flammekaster. Nu kan Irale lave en til dig. Du kan have det så sjovt.",Gut so. Hier ist ein kleiner Bonus. Meine Kumpel haben das hier von einem gefallenen Ordensritter abgerissen. Es sind die Teile seines Flammenwerfers. Jetzt kann Irale dir auch einen machen. Du kannst so viel Spaß damit haben...,,Bone. Jen aldonaĵo; miaj kamaradoj deŝiris ĝin de venkita Krucisto: ili estas partoj de flamĵetilo; Irale nun povos krei unu por vi. Vi vere amuziĝos.,Genial. Aquí tienes algo extra; mis compañeros lo arrancaron de un Cruzado caído: son las partes de un lanzallamas; ahora Irale puede hacer uno para ti. Te vas a divertir cantidad.,,"Hyvä. Tässä vielä jotain vähän lisäksi. Toverini repivät tämän kaatuneesta ristiretkeläisestä. Ne ovat liekinheittimen osia. Nyt Irale voi väsätä sinulle seillaisen. Ajattele sitä, kuinka hauskaa sinulla tulee olemaan.",Bien. Voilà un petit bonus. Mes amis ont arraché ceci à un croisé. C'est les pièces nécessaires à monter un lance-flammes. Irale peut en assembler un pour vous. Vous allez vraiment vous amuser.,"Helyes. Itt van egy kis érdekesség. Egyik bajtársam letörte ezeket az egyik keresztesről, igazából egy lángszórót lehetne összerakni belőle. Irale össze tudna rakni egyet neked. Tuti örömteli pörkölő pillanatokat fog okozni.","Eccellente. Ecco, ho qualcosa per te. I miei compagni hanno staccato questo da un Crociato distrutto, sono le parti che costituiscono il lanciafiamme. Adesso Irale ne può creare uno per te. Ti potrai divertire un sacco.","良し。礼は果たそう。 それと仲間が倒れたクルセイダーからこれを 奪ってきた、火炎放射器の部品らしい。 イラールに渡せば作り上げるはずだ。 -楽しみだろう。","아주 좋은 겨! 여기, 추가 보답을 받으라. 내 걸인 동료가 크루세이더의 잔해 속에서 이걸 구해냈다네에. 아주 좋은 화염방사기를 만들어낼 수 있을 거야. 이걸 들고 이롤리를 찾아가 바. 그리고... 요리를 즐기는 거쟈.","Goed. Hier is iets extra's. Mijn vrienden scheurden dit af van een gevallen kruisvaarder, het zijn de onderdelen die een vlammenwerper vormen. Nu kan Irale er een voor je maken. Je kunt zoveel plezier hebben.",Bra. Her er noe ekstra. Mine karer rev dette av en falne korsfarer. Det er delene til en flammekaster. Nå kan Irale lage en til deg. Du kan ha det så gøy.,"Dobrze. Oto mały bonus dla ciebie. Moi koledzy wyciągnęli to ze zniszczonego Krzyżowca, są to części do miotacza ognia. Teraz Irale będzie mógł taki dla ciebie zrobić. Będziesz miał dużo frajdy.",Muito bom. Aqui tem um brinde. Meus companheiros arrancaram isso de um Cruzado destruído. São peças para lança-chamas. Agora o Irale vai poder montar um pra você. Vai se divertir bastante.,,"Bun. Uite aici ceva în plus. Tovarășii mei au smuls asta de pe un Cruciat răpus, sunt părți ale unui aruncător de flăcări. Acum Irale îți poate construi unul. Te poți distra de minune.","Хорошо. Я могу предложить тебе кое-что сверх уговора. Мои приятели сняли это с подбитого крестоносца. Это детали огнемёта. Ирэйл соберёт его для тебя, и ты сможешь повеселиться от души.",,Güzel. Burada ekstra bir şey var. Arkadaşlarım bunu düşmüş bir Haçlı'dan kopardılar. Alev silahını oluşturan parçalar. Şimdi İrale senin için bir tane yapabilir. Çok eğlenebilirsiniz. -Where's the gate mechanism?,TXT_RPLY0_SCRIPT06_D7580_WHERE,〃,,,Kde je mechanismus brány?,Hvor er portmekanismen?,Wo ist der Tormechanismus?,,Kie estas la mekanismo de la kastelpordo?,¿Dónde está el mecanismo de la puerta?,,Missä portin koneisto on?,Où se trouve le mécanisme d'ouverture de la porte?,Hol van a kapu szerkezet?,Dov'è il meccanismo per il cancello?,ゲートメカニズムは何処だ?,관리 장치는 이제 어디있지?,Waar is het poortmechanisme?,Hvor er portmekanismen?,Gdzie jest mechanizm sterujący bramą?,Onde fica o mecanismo do portão?,,Unde e mecanismul de acționare al porții?,Где механизм управления воротами?,,Kapı mekanizması nerede? +楽しみだろう。","아주 좋은 겨! 여기, 추가 보답을 받으라. 내 걸인 동료가 크루세이더의 잔해 속에서 이걸 구해냈다네에. 아주 좋은 화염방사기를 만들어낼 수 있을 거야. 이걸 들고 이롤리를 찾아가 바. 그리고... 요리를 즐기는 거쟈.","Goed. Hier is iets extra's. Mijn vrienden scheurden dit af van een gevallen kruisvaarder, het zijn de onderdelen die een vlammenwerper vormen. Nu kan Irale er een voor je maken. Je kunt zoveel plezier hebben.",Bra. Her er noe ekstra. Mine karer rev dette av en falne korsfarer. Det er delene til en flammekaster. Nå kan Irale lage en til deg. Du kan ha det så gøy.,"Dobrze. Oto mały bonus dla ciebie. Moi koledzy wyciągnęli to ze zniszczonego Krzyżowca, są to części do miotacza ognia. Teraz Irale będzie mógł taki dla ciebie zrobić. Będziesz miał dużo frajdy.",Muito bom. Aqui tem um brinde. Meus companheiros arrancaram isso de um Cruzado destruído. São peças para lança-chamas. Agora o Irale vai poder montar um pra você. Vai se divertir bastante.,,"Bun. Uite aici ceva în plus. Tovarășii mei au smuls asta de pe un Cruciat răpus, sunt părți ale unui aruncător de flăcări. Acum Irale îți poate construi unul. Te poți distra de minune.","Хорошо. Я могу предложить тебе кое-что сверх уговора. Мои приятели сняли это с подбитого крестоносца. Это детали огнемёта. Ирэйл соберёт его для тебя, и ты сможешь повеселиться от души.",,"Jag har den. Här är något extra. Mina kamrater slet av den här från en stupad korsriddare, det är delarna som utgör en flamkastare. Nu kan Irale göra en åt dig. Du kan ha så roligt.",Güzel. Burada ekstra bir şey var. Arkadaşlarım bunu düşmüş bir Haçlı'dan kopardılar. Alev silahını oluşturan parçalar. Şimdi İrale senin için bir tane yapabilir. Çok eğlenebilirsiniz. +Where's the gate mechanism?,TXT_RPLY0_SCRIPT06_D7580_WHERE,〃,,,Kde je mechanismus brány?,Hvor er portmekanismen?,Wo ist der Tormechanismus?,,Kie estas la mekanismo de la pordo de la kastelo?,¿Dónde está el mecanismo de la puerta?,,Missä portin koneisto on?,Où se trouve le mécanisme d'ouverture de la porte?,Hol van a kapu szerkezet?,Dov'è il meccanismo per il cancello?,ゲートメカニズムは何処だ?,관리 장치는 이제 어디있지?,Waar is het poortmechanisme?,Hvor er portmekanismen?,Gdzie jest mechanizm sterujący bramą?,Onde fica o mecanismo do portão?,,Unde e mecanismul de acționare al porții?,Где механизм управления воротами?,,Var är grindmekanismen?,Kapı mekanizması nerede? "You have to enter another part of the sewers. To get there you must enter the castle from a sewer maintenance door and drain the fluid reclamation tank. At the bottom is the hidden entrance to sewers, and right beyond that is the manual gate control.",TXT_DLG_SCRIPT06_D9096_YOUHA,"〃 -https://en.wikipedia.org/wiki/Reclaimed_water",,,Musíš vejít do jiné části stok. K tomu se potřebuješ údržbovými dveřmi dostat do hradu a vypustit záchytnou nádrž. Na dně je schovaný vchod do stok a hned za ním je manuální ovládání brány.,"Du skal ind i en anden del af kloakkerne. For at komme derhen skal du gå ind i slottet fra en dør til vedligeholdelse af kloakken og tømme væskegenvindingsbeholderen. Nederst er den skjulte indgang til kloakkerne, og lige bagved er den manuelle portkontrol.","Du musst in einen anderen Teil der Kanalisation. Um dort hinzukommen, musst du durch einen Wartungsgang in die Burg und den Wasserrückgewinnungstank entleeren. Am Boden des Tanks ist der versteckte Eingang zur Kanalisation und gleich dahinter die manuelle Torkontrolle.",,"Vi devas iri al alia parto de la kloakoj. Por atingi tien, vi devas eniri la kastelon tra pordo de ĉambro pri kloaka bontenado kaj dreni la rezervujon de akvoreuzo; en ĝia fundo estas kaŝita enirejo al la kloakoj, kaj ie tie estas la mana regilo de la pordo.",Tienes que adentrarte en otra parte de las cloacas. Para llegar ahí debes entrar en el castillo por la puerta de mantenimiento de las cloacas y drenar el tanque de recuperación de agua; al fondo está la entrada oculta a las cloacas y por ahí mismo el control manual de la puerta.,Tienes que ir a otra parte de las cloacas. Para llegar ahí debes entrar al castillo por la puerta de mantenimiento de las cloacas y drenar el tanque de recuperación de agua; al fondo está la entrada oculta a las cloacas y por ahí mismo el control manual de la puerta.,"Sinun on mentävä viemäreiden eri osioon. Päästäksesi sinne sinun on mentävä linnaan viemäreiden huolto-oven kautta ja tyhjennettävä nesteentalteenottoallas. Altaan pohjalla on viemärin salainen sisäänkäynti, ja suoraan sen jäljessä on portin käsiohjain.","Vous devez entrer dans une autre section des égouts. Quand vous y êtes, vous devez entrer dans le château à partir de la porte de maintenance des égouts, et drainer le réservoir de recyclage d'eau. Au fond se trouve l'entrée cachée des égouts, et juste après elle, les contrôles manuels de la porte.","A kanális egy másik részébe kell menned. Ehhez egy szervízajtón keresztül kell behatolnod a kastélyba, úgy hogy leereszted a szárító tartályból. Az alján található a titkos kanális bejárat, és rögtön utána a kézi kapu irányító.","Devi andare in un'altra sezione delle fogne. Per raggiungerla, devi entrare nel castello da una porta di manutenzione delle fogne e svuotare la vasca di recupero fluidi. Al fondo di questa vasca c'è l'uscita nascosta per le fogne, e subito dopo c'è il controllo manuale dei cancelli.","下水道の別の部分に入る必要がある。 +https://en.wikipedia.org/wiki/Reclaimed_water",,,Musíš vejít do jiné části stok. K tomu se potřebuješ údržbovými dveřmi dostat do hradu a vypustit záchytnou nádrž. Na dně je schovaný vchod do stok a hned za ním je manuální ovládání brány.,"Du skal ind i en anden del af kloakkerne. For at komme derhen skal du gå ind i slottet fra en dør til vedligeholdelse af kloakken og tømme væskegenvindingsbeholderen. Nederst er den skjulte indgang til kloakkerne, og lige bagved er den manuelle portkontrol.","Du musst in einen anderen Teil der Kanalisation. Um dort hinzukommen, musst du durch einen Wartungsgang in die Burg und den Wasserrückgewinnungstank entleeren. Am Boden des Tanks ist der versteckte Eingang zur Kanalisation und gleich dahinter die manuelle Torkontrolle.",,"Vi devas iri al alia parto de la kloako. Por atingi tien, vi devas eniri la kastelon tra pordo de ĉambro pri kloaka bontenado kaj dreni la rezervujon de akvoreuzo; en ĝia fundo estas kaŝita enirejo al la kloako, kaj ie tie estas la mana regilo de la pordo.",Tienes que adentrarte en otra parte de las cloacas. Para llegar ahí debes entrar en el castillo por la puerta de mantenimiento de las cloacas y drenar el tanque de recuperación de agua; al fondo está la entrada oculta a las cloacas y por ahí mismo el control manual de la puerta.,Tienes que ir a otra parte de las cloacas. Para llegar ahí debes entrar al castillo por la puerta de mantenimiento de las cloacas y drenar el tanque de recuperación de agua; al fondo está la entrada oculta a las cloacas y por ahí mismo el control manual de la puerta.,"Sinun on mentävä viemäreiden eri osioon. Päästäksesi sinne sinun on mentävä linnaan viemäreiden huolto-oven kautta ja tyhjennettävä nesteentalteenottoallas. Altaan pohjalla on viemärin salainen sisäänkäynti, ja suoraan sen jäljessä on portin käsiohjain.","Vous devez entrer dans une autre section des égouts. Quand vous y êtes, vous devez entrer dans le château à partir de la porte de maintenance des égouts, et drainer le réservoir de recyclage d'eau. Au fond se trouve l'entrée cachée des égouts, et juste après elle, les contrôles manuels de la porte.","A kanális egy másik részébe kell menned. Ehhez egy szervízajtón keresztül kell behatolnod a kastélyba, úgy hogy leereszted a szárító tartályból. Az alján található a titkos kanális bejárat, és rögtön utána a kézi kapu irányító.","Devi andare in un'altra sezione delle fogne. Per raggiungerla, devi entrare nel castello da una porta di manutenzione delle fogne e svuotare la vasca di recupero fluidi. Al fondo di questa vasca c'è l'uscita nascosta per le fogne, e subito dopo c'è il controllo manuale dei cancelli.","下水道の別の部分に入る必要がある。 そこへ行くには下水道の整備室から 城の浄水施設に入りタンクを排水する必要がある その下には隠された入り口があり、 その先に手動ゲートコントロールがあるはずだ。","하수도로 통하는 또 다른 입구로 가야 혀. 들어가려면 성안에 위치한 하수도 정비소에서 수조에 있는 오물을 배출해야 해. 그 수조 밑에는 하수도로 향하는 숨겨진 입구가 있고, 그곳으로 향하면, 정문의 장치를 찾을 수 있을 게야. - \cy또 하수도라... 끝내준다. 저 아래에 또 뭐가 살고 있을까?","Je moet een ander deel van de riolering betreden. Om daar te komen moet je het kasteel binnengaan via een deur voor het onderhoud van de riolering en de vloeistoftank aftappen. Onderaan is de verborgen toegang tot de riolering, en net daarachter is de handmatige poortbesturing.","Du må gå inn i en annen del av kloakken. For å komme dit må du gå inn i slottet fra en kloakkvedlikeholdsdør og tømme væskegjenvinningstanken. Nederst er den skjulte inngangen til kloakken, og rett bortenfor den er den manuelle portkontrollen.","Musisz wejść do innej części kanałów. Aby się tam dostać musisz wejść do zamku przez drzwi sekcji konserwacji ścieków i osuszyć zbiornik rekultywacyjny. Na dole znajduje się ukryte przejście do kanałów, a za nim jest mechanizm bramy.",Você precisa entrar em outra parte do esgoto. Para chegar até lá você deve entrar no castelo por uma porte de manutenção de esgoto e drenar o tanque de recuperação de fluído. Lá no fundo fica a entrada oculta do esgoto e logo adiante fica o controle manual do portão.,,"Va trebui să intrăm pe altă parte a canalelor. Ca să ajungi acolo trebuie să intri în castel printr-o ușa de mentenanță a canalului și să drenezi rezervorul. La bază e intrarea în canale, și imediat după aceea e controlul manual al porții.","Это в другой части канализации. Чтобы попасть туда, пройди в замок через дверь обслуживания канализации и слей жидкость из бака для переработки. На его дне есть скрытый вход в стоки, и прямо за ним — ручной механизм управления воротами.",,Kanalizasyonun başka bir bölümüne girmelisin. Oraya ulaşmak için kaleye bir kanalizasyon bakım kapısından girmeli ve sıvı geri kazanım tankını boşaltmalısınız. En altta kanalizasyonun gizli girişi ve onun hemen ötesinde de manuel kapı kontrolü var. -Anything else you can do?,TXT_RPLY0_SCRIPT06_D9096_ANYTH,〃,,,Mohl bys udělat ještě něco?,"Er der andet, du kan gøre?",Kannst du sonst noch was für mich tun?,,"Ĉu estas io alia, kion vi povas fari?",¿Algo más que puedas hacer?,,Voitko olla vielä jotenkin muuten avuksi?,Que pouvez vous faire d'autre?,Tudsz még valamit tenni?,C'è qualcos'altro che puoi fare?,他に出来ることは?,그 외에 당신이 할 수 있는 일은?,Kun je nog iets anders doen?,Noe annet du kan gjøre?,Czy coś jeszcze możesz zrobić?,Algo mais que você possa fazer?,,Mai poți face altceva?,Можешь помочь мне чем-нибудь ещё?,,Yapabileceğin başka bir şey var mı? + \cy또 하수도라... 끝내준다. 저 아래에 또 뭐가 살고 있을까?","Je moet een ander deel van de riolering betreden. Om daar te komen moet je het kasteel binnengaan via een deur voor het onderhoud van de riolering en de vloeistoftank aftappen. Onderaan is de verborgen toegang tot de riolering, en net daarachter is de handmatige poortbesturing.","Du må gå inn i en annen del av kloakken. For å komme dit må du gå inn i slottet fra en kloakkvedlikeholdsdør og tømme væskegjenvinningstanken. Nederst er den skjulte inngangen til kloakken, og rett bortenfor den er den manuelle portkontrollen.","Musisz wejść do innej części kanałów. Aby się tam dostać musisz wejść do zamku przez drzwi sekcji konserwacji ścieków i osuszyć zbiornik rekultywacyjny. Na dole znajduje się ukryte przejście do kanałów, a za nim jest mechanizm bramy.",Você precisa entrar em outra parte do esgoto. Para chegar até lá você deve entrar no castelo por uma porte de manutenção de esgoto e drenar o tanque de recuperação de fluído. Lá no fundo fica a entrada oculta do esgoto e logo adiante fica o controle manual do portão.,,"Va trebui să intrăm pe altă parte a canalelor. Ca să ajungi acolo trebuie să intri în castel printr-o ușa de mentenanță a canalului și să drenezi rezervorul. La bază e intrarea în canale, și imediat după aceea e controlul manual al porții.","Это в другой части канализации. Чтобы попасть туда, пройди в замок через дверь обслуживания канализации и слей жидкость из бака для переработки. На его дне есть скрытый вход в стоки, и прямо за ним — ручной механизм управления воротами.",,"Du måste gå in i en annan del av kloakerna. För att komma dit måste du gå in i slottet från en dörr för underhåll av kloakerna och tömma vätskereklamationstanken. Längst ner finns den dolda ingången till kloakerna, och precis bakom den finns den manuella grindmekanismen.",Kanalizasyonun başka bir bölümüne girmelisin. Oraya ulaşmak için kaleye bir kanalizasyon bakım kapısından girmeli ve sıvı geri kazanım tankını boşaltmalısınız. En altta kanalizasyonun gizli girişi ve onun hemen ötesinde de manuel kapı kontrolü var. +Anything else you can do?,TXT_RPLY0_SCRIPT06_D9096_ANYTH,〃,,,Mohl bys udělat ještě něco?,"Er der andet, du kan gøre?",Kannst du sonst noch was für mich tun?,,"Ĉu estas io alia, kion vi povas fari?",¿Algo más que puedas hacer?,,Voitko olla vielä jotenkin muuten avuksi?,Que pouvez vous faire d'autre?,Tudsz még valamit tenni?,C'è qualcos'altro che puoi fare?,他に出来ることは?,그 외에 당신이 할 수 있는 일은?,Kun je nog iets anders doen?,Noe annet du kan gjøre?,Czy coś jeszcze możesz zrobić?,Algo mais que você possa fazer?,,Mai poți face altceva?,Можешь помочь мне чем-нибудь ещё?,,Finns det något annat du kan göra?,Yapabileceğin başka bir şey var mı? "Good luck. I've opened several of our tunnels for you. It should make your task easier. Oh, size ten, perfect! ...But dreadful colors.",TXT_DLG_SCRIPT06_D10612_GOODL,〃,,,"Hodně štěstí. Otevřel jsem pro tebe několik našich tunelů. To by ti mělo tvůj úkol usnadnit. Ó, velikost deset, perfektní! ...Ale barva je hrozná.","Held og lykke. Jeg har åbnet flere af vores tunneler for dig. Det burde gøre din opgave lettere. Åh, størrelse ti, perfekt! ...Men forfærdelige farver.","Viel Glück. Ich habe mehrere von unseren Tunnels für dich geöffnet. Es sollte deine Aufgabe vereinfachen. Oh, Größe 10. Perfekt! Aber scheußliche Farben...",,"Ŝancon. Mi malfermis diversajn el niaj tuneloj. Tio devus faciligi la taskon por vi. -Ha, la uniformo havas M-an talion. Perfekte!... Sed ĝiaj koloroj estas aĉaj.","Buena suerte. Te he abierto varios de nuestros túneles; eso debería facilitarte las cosas. +Ha, la uniformo havas M-an talion. Perfekte!... Sed aĉkolora.","Buena suerte. Te he abierto varios de nuestros túneles; eso debería facilitarte las cosas. Ah, es de talla 40. ¡Perfecto!... Aunque de colores espantosos.","Buena suerte. Te abrimos varios de nuestros túneles; eso debería facilitarte las cosas. Ah, es de talle M. ¡Perfecto!... Aunque de colores espantosos.","Lykkyä tykö. Olen aukaissut useita tunneleistamme sinulle, minkä pitäisi helpottaa tehtävääsi. Kas, kokoa kymmenen, prikulleen sopiva! ...Mutta aivan hirveän värinen.","Bonne chance. J'ai ouvert plusieurs de nos tunnels pour vous. Ca devrait rendre votre travail plus facile. Oh! Taille dix? Parfait! Les couleurs sont immondes, par contre.","Sok sikert. Kinyitottam számos alagutat neked. Meg kell, hogy könnyítse a dolgodat. Oh, tízes méret, tökéletes!...de milyen okádék színek.","Buona fortuna. Ho aperto diversi dei nostri tunnel per te. Così dovrebbe essere più facile per te. Ah, taglia dieci, perfetto! ...Ma pessimi colori.","頑張れよ。それとアンタの為に俺達は幾つか トンネルを開けといた。多少はやり易くなるだろ。 おぅ、サイズは10型か、ピッタリだ! -...だが、おっかねえ色してんな。","행운을 빈다. 지름길을 좀 열어놨어야. 덕분에 과제가 좀 쉬워질 거다. 오, 딱맞는 치수구먼! 완벽해... 그런데 색상이 별로다.","Veel succes. Ik heb een aantal van onze tunnels voor u geopend. Het moet uw taak gemakkelijker maken. Oh, maat tien, perfect! ...Maar vreselijke kleuren.","Lykke til. Jeg har åpnet flere av tunnelene våre for deg. Det burde gjøre oppgaven din lettere. Å, størrelse ti, perfekt! ...men forferdelige farger.","Powodzenia. Otworzyłem kilka naszych tuneli dla ciebie. To powinno ci ułatwić zadanie. Oh, rozmiar dziesięć, idealnie! ...Ale paskudne kolory.","Boa sorte. Eu abri alguns de nossos túneis pra você. Acho que vai facilitar o seu trabalho. Ah, tamanho M, perfeito! ...Mas as cores são um horror.",,"Noroc. Am deschis câteva canale pentru tine. Ar trebui să îți ușureze munca. Ah, mărimea zece, perfect! ...Dar cumplite culori.","Разве что пожелать удачи. Я открыл для тебя несколько наших туннелей, это может сделать твою задачу чуть проще. О, десятый размер! Как раз впору!.. Но остойные цвета.",,"İyi şanslar. Sizin için birkaç tünelimizi açtım. İşinizi kolaylaştıracaktır. Oh, 10 numara, mükemmel! ...Ama korkunç renkler." -Thanks for your help.,TXT_RPLY0_SCRIPT06_D10612_THANK,〃,,,Díky za pomoc.,Tak for din hjælp.,Danke für deine Hilfe.,,Dankon pro la helpo.,Gracias por la ayuda.,,Kiitos avustasi.,Merci pour votre aide.,Köszi a segítséget.,Grazie del tuo aiuto.,協力ありがとう。,도움 정말 고마워.,Bedankt voor je hulp.,Takk for hjelpen.,Dzięki za twoją pomoc.,Obrigado pela ajuda.,,Merci de ajutor.,Спасибо за помощь.,,Yardımınız için teşekkürler. -"You give me nothing, you get nothing.",TXT_DLG_SCRIPT06_D12128_YOUGI,〃,,,"Ty mi nic nedáš, já ti nic nedám.","Hvis du ikke giver mig noget, får du intet.","Du gibst mir nichts, ich gebe dir nichts.",,"Se vi donos nenion, vi ricevos nenion.","No me das nada, no recibes nada.",,"Jos et anna minulle mitään, et vastavuoroin mitään saakaan.","Vous ne me donnez rien, je ne vous donne rien.","Nem adsz semmit, nem kapsz semmit.","Se non mi dai niente, non ricevi niente!",何も無ければ、何も渡すモンは無い。,헤헤... 아무 일도 없는 거니 괜찮야!,"Je geeft me niets, je krijgt niets.","Du gir meg ingenting, du får ingenting.","Nic mi nie dajesz, nic nie dostajesz.","Você não me dá nada, não ganha nada.",,"Nu dai nimic, primești nimic.",Ничего не даёшь — ничего не получаешь.,,"Bana bir şey vermezsen, hiçbir şey alamazsın." +...だが、おっかねえ色してんな。","행운을 빈다. 지름길을 좀 열어놨어야. 덕분에 과제가 좀 쉬워질 거다. 오, 딱맞는 치수구먼! 완벽해... 그런데 색상이 별로다.","Veel succes. Ik heb een aantal van onze tunnels voor u geopend. Het moet uw taak gemakkelijker maken. Oh, maat tien, perfect! ...Maar vreselijke kleuren.","Lykke til. Jeg har åpnet flere av tunnelene våre for deg. Det burde gjøre oppgaven din lettere. Å, størrelse ti, perfekt! ...men forferdelige farger.","Powodzenia. Otworzyłem kilka naszych tuneli dla ciebie. To powinno ci ułatwić zadanie. Oh, rozmiar dziesięć, idealnie! ...Ale paskudne kolory.","Boa sorte. Eu abri alguns de nossos túneis pra você. Acho que vai facilitar o seu trabalho. Ah, tamanho M, perfeito! ...Mas as cores são um horror.",,"Noroc. Am deschis câteva canale pentru tine. Ar trebui să îți ușureze munca. Ah, mărimea zece, perfect! ...Dar cumplite culori.","Разве что пожелать удачи. Я открыл для тебя несколько наших туннелей, это может сделать твою задачу чуть проще. О, десятый размер! Как раз впору!.. Но остойные цвета.",,"Lycka till. Jag har öppnat flera av våra tunnlar åt dig. Det borde göra din uppgift lättare. Åh, storlek tio, perfekt! ...men hemska färger.","İyi şanslar. Sizin için birkaç tünelimizi açtım. İşinizi kolaylaştıracaktır. Oh, 10 numara, mükemmel! ...Ama korkunç renkler." +Thanks for your help.,TXT_RPLY0_SCRIPT06_D10612_THANK,〃,,,Díky za pomoc.,Tak for din hjælp.,Danke für deine Hilfe.,,Dankon pro la helpo.,Gracias por la ayuda.,,Kiitos avustasi.,Merci pour votre aide.,Köszi a segítséget.,Grazie del tuo aiuto.,協力ありがとう。,도움 정말 고마워.,Bedankt voor je hulp.,Takk for hjelpen.,Dzięki za twoją pomoc.,Obrigado pela ajuda.,,Merci de ajutor.,Спасибо за помощь.,,Tack för hjälpen.,Yardımınız için teşekkürler. +"You give me nothing, you get nothing.",TXT_DLG_SCRIPT06_D12128_YOUGI,〃,,,"Ty mi nic nedáš, já ti nic nedám.","Hvis du ikke giver mig noget, får du intet.","Du gibst mir nichts, ich gebe dir nichts.",,"Se vi donos nenion, vi ricevos nenion.","No me das nada, no recibes nada.",,"Jos et anna minulle mitään, et vastavuoroin mitään saakaan.","Vous ne me donnez rien, je ne vous donne rien.","Nem adsz semmit, nem kapsz semmit.","Se non mi dai niente, non ricevi niente!",何も無ければ、何も渡すモンは無い。,헤헤... 아무 일도 없는 거니 괜찮야!,"Je geeft me niets, je krijgt niets.","Du gir meg ingenting, du får ingenting.","Nic mi nie dajesz, nic nie dostajesz.","Você não me dá nada, não ganha nada.",,"Nu dai nimic, primești nimic.",Ничего не даёшь — ничего не получаешь.,,"Du ger mig inget, du får inget.","Bana bir şey vermezsen, hiçbir şey alamazsın." Weran will save us. He's never failed us yet.,TXT_DLG_SCRIPT06_D13644_WERAN,MAP06: Beggar.,,,Weran nás zachrání. Ještě nás nezklamal.,Weran vil redde os. Han har aldrig svigtet os endnu.,Weran wird uns retten. Er hat uns noch nie enttäuscht.,,Weran savos nin: li neniam desapontis nin.,Weran nos salvará: nunca nos ha fallado.,Weran nos va a salvar: nunca nos ha fallado.,Weran pelastaa meidät. Hän ei ole vielä kertaakaan pettänyt meitä.,Weran nous sauvera. Il ne nous a jamais failli.,Weran majd megment minket. Eddig sosem hagyott minket cserben.,Weran ci salverà. Non ci ha mai deluso fin'ora.,"ウェランは皆を保護してくれている。 -彼は誰も見捨てたことはない。",워렌이 우리들을 구원해 줄 겁니다. 그는 아직 믿어도 되니까요.,Weran zal ons redden. Hij heeft ons nog nooit teleurgesteld.,Weran vil redde oss. Han har aldri sviktet oss før.,Weran nas uratuje. Jeszcze nigdy nas nie zawiódł.,Weran vai nos salvar. Ele nunca nos deixou na mão.,,Weran ne va salva. Nu ne-a dezamăgit până acum.,Уэран поможет нам. Он ещё ни разу не подводил нас.,,Weran bizi kurtaracak. Şimdiye kadar bizi hiç hayal kırıklığına uğratmadı. +彼は誰も見捨てたことはない。",워렌이 우리들을 구원해 줄 겁니다. 그는 아직 믿어도 되니까요.,Weran zal ons redden. Hij heeft ons nog nooit teleurgesteld.,Weran vil redde oss. Han har aldri sviktet oss før.,Weran nas uratuje. Jeszcze nigdy nas nie zawiódł.,Weran vai nos salvar. Ele nunca nos deixou na mão.,,Weran ne va salva. Nu ne-a dezamăgit până acum.,Уэран поможет нам. Он ещё ни разу не подводил нас.,,Weran kommer att rädda oss. Han har aldrig svikit oss än.,Weran bizi kurtaracak. Şimdiye kadar bizi hiç hayal kırıklığına uğratmadı. "If you seek an answer to your problem, find Weran. ",TXT_DLG_SCRIPT06_D15160_IFYOU,〃,,,"Jestli hledáš odpověď na svou otázku, najdi Werana.","Hvis du søger et svar på dit problem, så find Weran.","Wenn du Lösungen für deine Probleme suchst, frag Weran.",,"Se vi serĉas respondon al via problemo, renkontu Weran-on.","Si buscas una respuesta a tu problema, ve con Weran.",,"Jos haet vastausta ongelmaasi, etsi Weran.","Si vous avez besoin d'une réponse à vos problèmes, allez voir Weran.","Ha választ keresel a problémádra, akkor keresd fel Werant.","Se cerchi una soluzione al tuo problema, torva Weran.","君の問題の答えが欲しいなら、 -ウェランに会うといい。","문제를 해결할 해답을 찾고 계신다면, 워렌을 찾아가세요.","Als je een antwoord zoekt op je probleem, vind Weran.","Hvis du søker et svar på problemet ditt, finn Weran.","Jeśli szukasz rozwiązania swojego problemu, poszukaj Werana.","Se você precisa de um resposta para o seu problema, procure Weran.",,"Dacă ești în căutarea unor răspunsuri, găsește-l pe Weran.",Тебе нужен ответ? Найди Уэрана.,,"Eğer sorununuza bir cevap arıyorsanız, Weran'ı bulun." +ウェランに会うといい。","문제를 해결할 해답을 찾고 계신다면, 워렌을 찾아가세요.","Als je een antwoord zoekt op je probleem, vind Weran.","Hvis du søker et svar på problemet ditt, finn Weran.","Jeśli szukasz rozwiązania swojego problemu, poszukaj Werana.","Se você precisa de um resposta para o seu problema, procure Weran.",,"Dacă ești în căutarea unor răspunsuri, găsește-l pe Weran.",Тебе нужен ответ? Найди Уэрана.,,"Om du söker ett svar på ditt problem, hitta Weran.","Eğer sorununuza bir cevap arıyorsanız, Weran'ı bulun." Long live the Front? That's all crap. We're all just waiting to die. ,TXT_DLG_SCRIPT06_D16676_LONGL,〃,,,Ať žije Fronta? To je blbost. Všichni jen čekáme na smrt.,Længe leve fronten? Det er alt sammen noget lort. Vi venter alle bare på at dø.,Lang lebe die Front? Was für ein Mist. Wir warten doch nur auf den Tod.,,Ĉu vivu la Fronto? Kia fekaĵo. Ni ĉiuj atendas morton.,¿Que viva el Frente? Menuda mierda. A todos nos espera la muerte.,¿Que viva el Frente? Pura mierda. A todos nos espera la muerte.,Kauan eläköön Rintama? Täyttä puppua. Me kaikki vain odotamme kuolemaa.,Longue vie au Front? Quelles conneries! On est tous en train d'attendre de mourir!,"Éljen a Front? Mekkora baromság. Csak arra várunk, hogy meghaljunk.",Lunga vita al Fronte? Sono tutte idiozie. Stiamo tutti in attesa di morire.,"フロントに入れ? 馬鹿げてる。 -死ねと言ってるようなもんだ。",프론트와 자유를 향하여... 는 개뿔. 때문에 우리들만 죽게 생겼어요.,Lang leve het Front? Dat is allemaal onzin. We wachten allemaal op de dood.,Lenge leve Fronten? Det er bare tull. Vi venter bare på å dø.,Niech żyje Front? To wszystko to gówno. My po prostu czekamy na śmierć.,Viva a Frente? Isso é besteira. Todos nós estamos esperando a morte.,,Să trăiască Frontul? Aiureli. Doar așteptăm să murim.,Да здравствует Сопротивление? Это всё чушь. Мы все просто ждём смерти.,,Cephe çok yaşa mı? Bunların hepsi saçmalık. Hepimiz ölmeyi bekliyoruz. +死ねと言ってるようなもんだ。",프론트와 자유를 향하여... 는 개뿔. 때문에 우리들만 죽게 생겼어요.,Lang leve het Front? Dat is allemaal onzin. We wachten allemaal op de dood.,Lenge leve Fronten? Det er bare tull. Vi venter bare på å dø.,Niech żyje Front? To wszystko to gówno. My po prostu czekamy na śmierć.,Viva a Frente? Isso é besteira. Todos nós estamos esperando a morte.,,Să trăiască Frontul? Aiureli. Doar așteptăm să murim.,Да здравствует Сопротивление? Это всё чушь. Мы все просто ждём смерти.,,Länge leve fronten? Det är bara skit. Vi väntar bara på att dö.,Cephe çok yaşa mı? Bunların hepsi saçmalık. Hepimiz ölmeyi bekliyoruz. "With our passage to the surface sealed, we can't even feed ourselves.",TXT_DLG_SCRIPT06_D18192_WITHO,〃,,,"Když je cesta na povrch uzavřená, nemůžeme se ani nakrmit.","Med vores passage til overfladen forseglet, kan vi ikke engang brødføde os selv.","Da unser Zugang zur Oberfläche verschlossen ist, haben wir nichts mehr zu essen.",,"Ĉar nia irado al la surfaco estas ŝlosita, ni eĉ ne povas nutri nin.","Con nuestro pasaje a la superficie cerrado, no podemos ni alimentarnos.",,Pääsymme maanpinnalle ollessa salvattuna emme voi edes ruokkia itseämme.,"Avec notre passage vers la surface scellé, on ne peut même plus se nourrir.","Mivel a felszínre vezető átjáró el van zárva, még ételhez sem jutunk.","Con il passaggio verso la superfice chiuso, non possiamo neanche mangiare.","外への出入口が封鎖されてるから、 飯が調達できないんだ。 -","오더가 지상으로 향하는 입구를 막은 이상, 우리는 굶어 죽어야 할 운명에 시달려야 해요.","Met onze doorgang naar de oppervlakte afgesloten, kunnen we onszelf niet eens voeden.","Nå som passasjen til overflaten er stengt, kan vi ikke engang få mat.",Z zamkniętą naszą drogą na powierzchnię nie możemy się nawet nakarmić.,"Com a nossa passagem para a superfície selada, não somos capazes nem de nos alimentar.",,"Cu calea spre suprafață sigilată, nici măcar nu ne putem hrănii.","Пока выход на поверхность закрыт, мы не можем даже прокормить себя.",,Yüzeye geçişimiz mühürlü olduğu için kendimizi bile besleyemiyoruz. -"Food, do you have any food? Please help us.",TXT_DLG_SCRIPT06_D19708_FOODD,〃,,,"Jídlo, nemáš nějaké jídlo? Pomoz nám, prosím.","Mad, har du noget mad? Vær sød at hjælpe os.","Essen, hast du was zu essen? Bitte hilf uns.",,Manĝaĵoj... Ĉu vi havas manĝaĵojn? Bonvolu helpi nin.,"Comida... ¿No tendrás algo de comida? Ayúdanos, por favor.",,"Ruokaa, onko sinulla yhtään ruokaa? Pyydän, auta meitä.","A manger, vous avez à manger? Aidez-nous, s'il vous plaît.","Étel, van nálad valami étel? Kérlek segíts nekünk.","Cibo, hai del cibo? Per favore aiutaci.",食い物、食い物を恵んでくれないか? 頼むよ。,굶어 죽을 것 같습니다... 부디 음식 찌꺼기라도 괜찮으니까 음식을...,"Eten, heb je eten? Help ons alstublieft.","Mat, har du noe mat? Vær så snill, hjelp oss.","Jedzenie, masz może jakieś jedzenie? Proszę pomóż nam.",Comida. Você tem alguma comida? Por favor nos ajude.,,"Mâncare, ai mâncare? Te rog ajută-ne.","Еда. У тебя есть еда? Пожалуйста, помоги нам.",,"Yiyecek, hiç yiyeceğiniz var mı? Lütfen bize yardım edin." -"This is my reward for letting prisoners escape, guarding the sewers. If I ever find the guy who broke them out, I'll slaughter him.",TXT_DLG_SCRIPT06_D21224_THISI,MAP06: Gray acolyte.,,,"Tohle je má odměna za to, že jsem nechal utéct vězně: hlídání stok. Jestli někdy najdu toho hajzla, který je pustil, zabiju ho.","Dette er min belønning for at lade fanger flygte og bevogte kloakkerne. Hvis jeg nogensinde finder den fyr, der brød dem ud, vil jeg slagte ham.","Das ist meine Belohnung dafür, dass ich die Gefangenen entkommen lassen habe. Jetzt darf ich die Kanalisation bewachen. Wenn ich jemals den Kerl finde, der das gemacht hat, mache ich Hackfleisch aus ihm!",,"Jen mia rekompenco pro tio, ke mi ne evitis la liberigon de la ekskaptitoj: gardi la kloakojn. Se mi iam trovas la liberiginton, mi mortigos lin.","Esta es mi recompensa por dejar escapar a los prisioneros: vigilar las cloacas. Si llego a encontrar al tipo que los ha liberado, me lo cargo.","Esta es mi recompensa por dejar escapar a los prisioneros: vigilar las cloacas. Si llego a encontrar al tipo que los liberó, lo asesino.","Tämä on minun palkkani siitä hyvästä, että päästin vangit pakenemaan: viemäreiden vartiointi. Jos ikinä saan käsiini sen tyypin, joka päästi ne pakoon, lahtaan sen.","Voici ma récompense pour avoir laissé les prisonniers s'évader: garder les égouts. Si je trouve celui qui les a libéré, je l'étripe.","Ez a jutalmam amiért hagytam elszökni a foglyokat. Ha meglelem az ürgét aki kiszabadította őket, biztosan kicsinálom.","Ecco la mia ricompensa per aver fatto scappare i prigionieri, fare la guardia alle fogne. Se mai trovo chi li ha liberati, lo faccio a pezzi.","この下水道から囚人を脱走させた奴を探す為、 +","오더가 지상으로 향하는 입구를 막은 이상, 우리는 굶어 죽어야 할 운명에 시달려야 해요.","Met onze doorgang naar de oppervlakte afgesloten, kunnen we onszelf niet eens voeden.","Nå som passasjen til overflaten er stengt, kan vi ikke engang få mat.",Z zamkniętą naszą drogą na powierzchnię nie możemy się nawet nakarmić.,"Com a nossa passagem para a superfície selada, não somos capazes nem de nos alimentar.",,"Cu calea spre suprafață sigilată, nici măcar nu ne putem hrănii.","Пока выход на поверхность закрыт, мы не можем даже прокормить себя.",,Med vår passage till ytan förseglad kan vi inte ens föda oss själva.,Yüzeye geçişimiz mühürlü olduğu için kendimizi bile besleyemiyoruz. +"Food, do you have any food? Please help us.",TXT_DLG_SCRIPT06_D19708_FOODD,〃,,,"Jídlo, nemáš nějaké jídlo? Pomoz nám, prosím.","Mad, har du noget mad? Vær sød at hjælpe os.","Essen, hast du was zu essen? Bitte hilf uns.",,Manĝaĵoj... Ĉu vi havas manĝaĵojn? Bonvolu helpi nin.,"Comida... ¿No tendrás algo de comida? Ayúdanos, por favor.",,"Ruokaa, onko sinulla yhtään ruokaa? Pyydän, auta meitä.","A manger, vous avez à manger? Aidez-nous, s'il vous plaît.","Étel, van nálad valami étel? Kérlek segíts nekünk.","Cibo, hai del cibo? Per favore aiutaci.",食い物、食い物を恵んでくれないか? 頼むよ。,굶어 죽을 것 같습니다... 부디 음식 찌꺼기라도 괜찮으니까 음식을...,"Eten, heb je eten? Help ons alstublieft.","Mat, har du noe mat? Vær så snill, hjelp oss.","Jedzenie, masz może jakieś jedzenie? Proszę pomóż nam.",Comida. Você tem alguma comida? Por favor nos ajude.,,"Mâncare, ai mâncare? Te rog ajută-ne.","Еда. У тебя есть еда? Пожалуйста, помоги нам.",,"Mat, har ni någon mat? Snälla, hjälp oss.","Yiyecek, hiç yiyeceğiniz var mı? Lütfen bize yardım edin." +"This is my reward for letting prisoners escape, guarding the sewers. If I ever find the guy who broke them out, I'll slaughter him.",TXT_DLG_SCRIPT06_D21224_THISI,MAP06: Gray acolyte.,,,"Tohle je má odměna za to, že jsem nechal utéct vězně: hlídání stok. Jestli někdy najdu toho hajzla, který je pustil, zabiju ho.","Dette er min belønning for at lade fanger flygte og bevogte kloakkerne. Hvis jeg nogensinde finder den fyr, der brød dem ud, vil jeg slagte ham.","Das ist meine Belohnung dafür, dass ich die Gefangenen entkommen lassen habe. Jetzt darf ich die Kanalisation bewachen. Wenn ich jemals den Kerl finde, der das gemacht hat, mache ich Hackfleisch aus ihm!",,"Jen mia rekompenco pro tio, ke mi ne evitis la liberigon de la ekskaptitoj: gardi la kloakon. Se mi iam trovas la liberiginton, mi mortigos lin.","Esta es mi recompensa por dejar escapar a los prisioneros: vigilar las cloacas. Si llego a encontrar al tío que los ha liberado, me lo cargo.","Esta es mi recompensa por dejar escapar a los prisioneros: vigilar las cloacas. Si llego a encontrar al tipo que los liberó, lo asesino.","Tämä on minun palkkani siitä hyvästä, että päästin vangit pakenemaan: viemäreiden vartiointi. Jos ikinä saan käsiini sen tyypin, joka päästi ne pakoon, lahtaan sen.","Voici ma récompense pour avoir laissé les prisonniers s'évader: garder les égouts. Si je trouve celui qui les a libéré, je l'étripe.","Ez a jutalmam amiért hagytam elszökni a foglyokat. Ha meglelem az ürgét aki kiszabadította őket, biztosan kicsinálom.","Ecco la mia ricompensa per aver fatto scappare i prigionieri, fare la guardia alle fogne. Se mai trovo chi li ha liberati, lo faccio a pezzi.","この下水道から囚人を脱走させた奴を探す為、 下水道を監視している。首謀者を見つけたら、 -その命を持って報いを受けてもらう。","수감자들의 탈옥을 막지 못해서 하수도를 지키게 되었어. 만약 탈옥하게 만든 녀석을 만난다면, 녀석이 죽을 때 까지 내장을 천천히 끄집어낼 거다.","Dit is mijn beloning voor het laten ontsnappen van gevangenen, het bewaken van de riolering. Als ik ooit de man vind die ze heeft uitgebroken, zal ik hem afslachten.","Dette er belønningen min for å la fanger rømme og vokte kloakken. Hvis jeg finner fyren som slapp dem ut, skal jeg slakte ham.","To moja nagroda za pozwolenie więźniom uciec, pilnowanie ścieków. Jeśli kiedyklowiek dorwę tego, kto pomógł im uciec, to go zamorduję.","Essa é a minha recompensa por deixar os prisioneiros escaparem. Vigiar o esgoto. Se algum dia eu encontrar o cara que soltou eles, eu vou arrancar os seus pedaços.",,"Asta e răsplata mea pentru că am lăsat prizonieri să scape, apărarea canalelor. Dacă îl prind pe cel care i-a lăsat să scape, îl masacrez.","Я отбываю наказание за то, что не остановил побег из тюрьмы: охраняю канализацию. Если я когда-нибудь найду того парня, что освободил пленников, я его на куски порву.",,"Mahkumların kaçmasına izin verip kanalizasyonları koruduğum için ödülüm bu. Eğer onları kaçıran adamı bulursam, onu katledeceğim." +その命を持って報いを受けてもらう。","수감자들의 탈옥을 막지 못해서 하수도를 지키게 되었어. 만약 탈옥하게 만든 녀석을 만난다면, 녀석이 죽을 때 까지 내장을 천천히 끄집어낼 거다.","Dit is mijn beloning voor het laten ontsnappen van gevangenen, het bewaken van de riolering. Als ik ooit de man vind die ze heeft uitgebroken, zal ik hem afslachten.","Dette er belønningen min for å la fanger rømme og vokte kloakken. Hvis jeg finner fyren som slapp dem ut, skal jeg slakte ham.","To moja nagroda za pozwolenie więźniom uciec, pilnowanie ścieków. Jeśli kiedyklowiek dorwę tego, kto pomógł im uciec, to go zamorduję.","Essa é a minha recompensa por deixar os prisioneiros escaparem. Vigiar o esgoto. Se algum dia eu encontrar o cara que soltou eles, eu vou arrancar os seus pedaços.",,"Asta e răsplata mea pentru că am lăsat prizonieri să scape, apărarea canalelor. Dacă îl prind pe cel care i-a lăsat să scape, îl masacrez.","Я отбываю наказание за то, что не остановил побег из тюрьмы: охраняю канализацию. Если я когда-нибудь найду того парня, что освободил пленников, я его на куски порву.",,Det här är min belöning för att jag lät fångarna rymma och vaktade kloakerna. Om jag någonsin hittar killen som bröt ut dem ska jag slakta honom.,"Mahkumların kaçmasına izin verip kanalizasyonları koruduğum için ödülüm bu. Eğer onları kaçıran adamı bulursam, onu katledeceğim." "We've got those little beggars just where we want them. Few more days of this, and they'll have starved themselves into oblivion.",TXT_DLG_SCRIPT06_D22740_WEVEG,MAP06: Red acolyte.,,,"Máme ty žebráčky přesně tam, kde chceme. Ještě pár dní a vyhladoví se do zapomnění.","Vi har de små tiggere lige hvor vi vil have dem. Et par dage mere af dette, og de vil have sultet sig selv til ukendelighed.","Wir haben diese armseligen Bettler doch genau da, wo wir sie haben wollen. Noch ein paar Tage und sie wären verhungert.",,"Tiuj almozuloj estas precize tie, kie ni volas: ankoraŭ kelkajn tagojn en tia situo kaj ili ne plu eltenos la inanicion.",Tenemos a esos indigentes justo donde los queremos: unos cuantos días más así y se habrán consumido por el hambre.,Tenemos a esos mendigos justo donde los queremos: un par de días más así y ya no van a poder más del hambre.,"Olemme ajaneet ne pikku kerjäläiset juuri sinne, minne haluammekin. Vielä muutama päivä tätä, ja ovat varmaankin nääntyneet unholaan.",On a enfin ces sales clodos là où on veut qu'ils soient. Quelques jours de plus et il seront tous morts de faim.,"Pont ott vannak ezek a koldusok ahol akarjuk. Még néhány nap, és halálra fognak éhezni.","Abbiamo quei piccoli mendicanti proprio dove vogliamo. Un paio di altri giorni di questo trattamento, e saranno tutti morti di fame.","この辺の何処かに乞食共がいるはずだ。 -数日もすれば忘れ去られ飢え死するだろうな。",저 빌어먹을 거지들이 밖으로 나가지 못하게 우리들이 입구를 꼼꼼히 막아뒀지. 천천히 굶어 죽는 순간을 재밌게 즐기고 있을걸?,We hebben die kleine bedelaars precies waar we ze willen hebben. Nog maar een paar dagen en ze zullen zich in de vergetelheid hebben laten hongeren.,"Vi har de små tiggerne akkurat der vi vil ha dem. Et par dager til, så har de sultet seg selv i hjel.","Trzymamy tych małych żebraków tam gdzie chcemy, żeby byli. Jeszcze kilka dni i zagłodzą się na śmierć.",Esses mendigos estão bem onde a gente quer que estejam. Só mais alguns dias e eles vão morrer de fome.,,"Îi avem pe sărmanii ăștia exact acolo unde vrem. Încă câteva zile, și vor muri de foame.","Мы загнали этих жалких нищих туда, где им самое место. Ещё несколько дней, и все они подохнут с голоду.",,"O küçük dilencileri tam istediğimiz yere getirdik. Birkaç gün daha böyle devam ederlerse, kendilerini açlıktan öldürmüş olacaklar." +数日もすれば忘れ去られ飢え死するだろうな。",저 빌어먹을 거지들이 밖으로 나가지 못하게 우리들이 입구를 꼼꼼히 막아뒀지. 천천히 굶어 죽는 순간을 재밌게 즐기고 있을걸?,We hebben die kleine bedelaars precies waar we ze willen hebben. Nog maar een paar dagen en ze zullen zich in de vergetelheid hebben laten hongeren.,"Vi har de små tiggerne akkurat der vi vil ha dem. Et par dager til, så har de sultet seg selv i hjel.","Trzymamy tych małych żebraków tam gdzie chcemy, żeby byli. Jeszcze kilka dni i zagłodzą się na śmierć.",Esses mendigos estão bem onde a gente quer que estejam. Só mais alguns dias e eles vão morrer de fome.,,"Îi avem pe sărmanii ăștia exact acolo unde vrem. Încă câteva zile, și vor muri de foame.","Мы загнали этих жалких нищих туда, где им самое место. Ещё несколько дней, и все они подохнут с голоду.",,"Vi har de små tiggarna precis där vi vill ha dem. Några dagar till av detta, och de kommer att ha svultit sig själva till glömska.","O küçük dilencileri tam istediğimiz yere getirdik. Birkaç gün daha böyle devam ederlerse, kendilerini açlıktan öldürmüş olacaklar." What's your clearance? There's no unauthorized personnel allowed up here.,TXT_DLG_SCRIPT06_D24256_WHATS,MAP06: Near storage.,,,Máš oprávnění? Žádná nepovolená osoba tady nahoře nemá co dělat!,Hvad er din tilladelse? Der er ingen uautoriseret personale tilladt heroppe.,Wo ist deine Berechtigung? Unautorisiertes Personal darf hier nicht rein.,,Kiun paspermeson vi havas? Nerajtigita personaro ne estas permesata ĉi tie.,¿Qué permiso tienes? No se permite al personal no autorizado aquí.,,Mikä on kulkuoikeutesi? Henkilöstöllä ei ole tänne pääsyä ilman lupaa.,Où est votre autorisation? Aucun personnel non autorisé ne peut venir ici.,Milyen engedélyed van? Nem léphet be engedély nélkül ide egy alkalmazott sem.,Hai l'autorizzazione per essere qui? Non è assolutamente permesso al personale non autorizzato di stare qua sopra.,"お前のクリアランスは何だ? -ここは許可の無い者は立入を禁じている。",승인을 받지 않은 것 같은데. 여긴 출입금지 구역이다.,Wat is uw toelating? Er is hier geen onbevoegd personeel toegestaan.,Hva er din klarering? Uautorisert personell er ikke tillatt her oppe.,Gdzie twoje zezwolenie? Nieautoryzowany personel nie ma tu wstępu.,Onde está a sua permissão? Ninguém sem permissão pode ficar aqui.,,Care e nivelul tău de acces? Niciun personal neautorizat nu are voie aici.,Где твой пропуск? Здесь нечего делать неуполномоченным лицам.,,Yetkiniz nedir? Buraya yetkisiz personel giremez. +ここは許可の無い者は立入を禁じている。",승인을 받지 않은 것 같은데. 여긴 출입금지 구역이다.,Wat is uw toelating? Er is hier geen onbevoegd personeel toegestaan.,Hva er din klarering? Uautorisert personell er ikke tillatt her oppe.,Gdzie twoje zezwolenie? Nieautoryzowany personel nie ma tu wstępu.,Onde está a sua permissão? Ninguém sem permissão pode ficar aqui.,,Care e nivelul tău de acces? Niciun personal neautorizat nu are voie aici.,Где твой пропуск? Здесь нечего делать неуполномоченным лицам.,,Vad har du för tillstånd? Ingen obehörig personal tillåts här uppe.,Yetkiniz nedir? Buraya yetkisiz personel giremez. What the hell? Who opened the gates? Sound the alarm!!!,TXT_DLG_SCRIPT07_D0_WHATT,MAP07: Red acolyte at the main entrance.,,,Co to sakra? Kdo otevřel bránu? Volej na poplach!,Hvad fanden? Hvem åbnede portene? Slå alarm!!!!,Was zur Hölle? Wer hat die Tore geöffne? Alarm!,,Kio diable? Kiu malfermis la pordojn? Sonorigu la alarmon!!!,¿Qué demonios? ¿Quién ha abierto las puertas? ¡¡¡Activad la alarma!!!,¿Qué carajo? ¿Quién abrió las puertas? ¡¡¡Activen la alarma!!!,Mitä helvettiä? Kuka avasi portit? Laukaise hälytys!!!,Qu'est-ce que c'est que ce bordel? Qui a ouvert les portes? Faites sonner l'alarme!,Mi a franc? Ki nyitotta ki a kaput? Indítsátok be a riasztót!,Ma che diavolo? Chi ha aperto i cancelli? Suonate l'allarme!!!,"何をしやがった? -誰がゲートを開けた? 警報を鳴らせ!",누가 성문을 열어놨어? 경보! 알람을 울려라!,Wat de hel? Wie heeft de poorten geopend? Laat alarm slaan!!!,Hva i helvete? Hvem åpnet porten? Slå alarm!,Co u diabła? Kto otworzył bramy? Włączyć alarm!!!,Mas que diabos? Quem abriu os portões? Ativem o alarme!!!,,Ce naiba? Cine a deschis porțile? Sună alarma!!!,Что за чертовщина? Кто открыл ворота? Бейте тревогу!,,Ne oluyor be? Kapıları kim açtı? Alarmı çalın!!! -"There's another way into the sewers, throw that switch and then go up and purge the reclamation tank.",TXT_DLG_SCRIPT07_D1516_THERE,MAP07,,,"Do stok vede další cesta, zatáhni za tuhle páku a pak jdi nahoru a vypusť obnovnou nádrž.","Der er en anden vej ind i kloakkerne, smid kontakten og gå så op og tøm genvindingstanken.",Da ist ein anderer Weg in die Kanalisation. Drück den Schalter da und leere den Rückgewinnungstank.,,"Estas alia enirejo al la kloakoj: enŝaltu ĉi tiun ŝaltilon, tiam reiru supren laŭ la ŝtuparo kaj drenu la rezervujon de akvoreuzo.",Hay otra entrada a las cloacas: activa este interruptor y luego ve a drenar el tanque de recuperación de agua subiendo las escaleras.,,Viemäreihin on toinen reitti. Käännä tuota vipua ja mene sitten ylös tyhjentämään talteenottoallas.,Il y a une autre entrée pour les égouts. Utilisez ce bouton et montez purger le réservoir de recyclage.,"Van egy másik módja is bejutni a kanálisba. Kapcsold fel azt a kapcsolót, aztán menj fel és ereszd le a szárító tartályt.","C'è un altro ingresso per le fogne, attiva quella leva e poi sali per svuotare la vasca di recupero fluidi.","下水道に別の入り口がある、スイッチを入れ -次に昇って浄水タンクを空にするんだ。",하수도로 향하는 또 다른 길이 있어. 저 스위치를 켜고 위로 올라가서 수조의 오물을 비워봐.,"Er is nog een andere weg in de riolering, gooi die schakelaar naar boven en ga dan naar boven om de terugwinnings tank te zuiveren.","Det er en annen vei inn i kloakken, trykk på bryteren og gå opp og rens tanken.","Jest jeszcze inna droga do kanałów, wciśnij ten przełącznik, idź na górę i opróżnij zbiornik rekultywacyjny.","Há outra maneira de entrar no esgoto. Use esse interruptor, suba e esvazie o tanque de recuperação.",,"Mai e o cale de acces către canale, folosește butonul apoi du-te sus și scurge lichidul din rezervor.","Есть другой путь в канализацию. Переведи этот рычаг, затем иди наверх и слей жидность из бака для переработки.",,"Kanalizasyona giden başka bir yol var, o düğmeyi at ve sonra yukarı çıkıp ıslah tankını temizle." +誰がゲートを開けた? 警報を鳴らせ!",누가 성문을 열어놨어? 경보! 알람을 울려라!,Wat de hel? Wie heeft de poorten geopend? Laat alarm slaan!!!,Hva i helvete? Hvem åpnet porten? Slå alarm!,Co u diabła? Kto otworzył bramy? Włączyć alarm!!!,Mas que diabos? Quem abriu os portões? Ativem o alarme!!!,,Ce naiba? Cine a deschis porțile? Sună alarma!!!,Что за чертовщина? Кто открыл ворота? Бейте тревогу!,,Vad i helvete? Vem öppnade grindarna? Slå larm!,Ne oluyor be? Kapıları kim açtı? Alarmı çalın!!! +"There's another way into the sewers, throw that switch and then go up and purge the reclamation tank.",TXT_DLG_SCRIPT07_D1516_THERE,MAP07,,,"Do stok vede další cesta, zatáhni za tuhle páku a pak jdi nahoru a vypusť obnovnou nádrž.","Der er en anden vej ind i kloakkerne, smid kontakten og gå så op og tøm genvindingstanken.",Da ist ein anderer Weg in die Kanalisation. Drück den Schalter da und leere den Rückgewinnungstank.,,"Estas alia enirejo al la kloako: enŝaltu ĉi tiun ŝaltilon, tiam reiru supren laŭ la ŝtuparo kaj drenu la rezervujon de akvoreuzo.",Hay otra entrada a las cloacas: activa este interruptor y luego ve a drenar el tanque de recuperación de agua subiendo las escaleras.,,Viemäreihin on toinen reitti. Käännä tuota vipua ja mene sitten ylös tyhjentämään talteenottoallas.,Il y a une autre entrée pour les égouts. Utilisez ce bouton et montez purger le réservoir de recyclage.,"Van egy másik módja is bejutni a kanálisba. Kapcsold fel azt a kapcsolót, aztán menj fel és ereszd le a szárító tartályt.","C'è un altro ingresso per le fogne, attiva quella leva e poi sali per svuotare la vasca di recupero fluidi.","下水道に別の入り口がある、スイッチを入れ +次に昇って浄水タンクを空にするんだ。",하수도로 향하는 또 다른 길이 있어. 저 스위치를 켜고 위로 올라가서 수조의 오물을 비워봐.,"Er is nog een andere weg in de riolering, gooi die schakelaar naar boven en ga dan naar boven om de terugwinnings tank te zuiveren.","Det er en annen vei inn i kloakken, trykk på bryteren og gå opp og rens tanken.","Jest jeszcze inna droga do kanałów, wciśnij ten przełącznik, idź na górę i opróżnij zbiornik rekultywacyjny.","Há outra maneira de entrar no esgoto. Use esse interruptor, suba e esvazie o tanque de recuperação.",,"Mai e o cale de acces către canale, folosește butonul apoi du-te sus și scurge lichidul din rezervor.","Есть другой путь в канализацию. Переведи этот рычаг, затем иди наверх и слей жидность из бака для переработки.",,"Det finns en annan väg in i kloakerna, slå om den strömbrytaren och gå sedan upp och rensa återvinningstanken.","Kanalizasyona giden başka bir yol var, o düğmeyi at ve sonra yukarı çıkıp ıslah tankını temizle." "What the hell's your problem. If the Programmer comes up from his audience chamber, you're dead.",TXT_DLG_SCRIPT07_D3032_WHATT,MAP07: Hospital.,,,"Co máš sakra za problém? Jestli Programátor vyjde ze svého sálu, jsi mrtvý.","Hvad fanden er dit problem? Hvis programmøren kommer op fra sit publikumskammer, er du død.","Was, verdammt, ist dein Problem? Wenn der Programmierer seine Audienzkammer verläßt, bist du tot.",,"Kion diable vi faras!? Se la Programisto revenos de sia juĝejo, vi mortos.","¿¡Qué demonios te pasa!? Si el Programador vuelve de su sala de audiencias, estás muerto.","¿¡Qué carajo te pasa!? Si el Programador vuelve de su sala de audiencias, estás muerto.","Mikä helvetti sinussa on vialla. Jos ohjelmoitsija tulee valtaistuinsaliltaan, olet mennyttä.","C'est quoi votre problème? Si le Programmeur sort de sa chambre d'audience, vous êtes mort.","Mi az isten bajod van? Ha a Programozó feljön a kihallgató kamrájábó, akkor neked annyi.","Ma quale diavolo è il tuo problema. Se il Programmatore arriva dalla sua camera delle udienze, sei morto.","一体何をしに来た。プログラマーが オーディエンスチャンバーから来たら -死んでいた所だ。","너희들 제정신이야? 프로그래머님이 알현실에서 뛰쳐나오는 순간, 네 놈은 죽게 될 거라고!","Wat de hel is jouw probleem? Als de programmeur uit zijn publiekskamer komt, ben je dood.","Hva i helvete er problemet ditt? Hvis programmereren kommer opp fra audiensrommet, er du død.",Jaki masz problem do diaska? Jeśli Programista wyjdzie ze swojej sali audiencji będziesz martwy.,"Qual é o seu problema? Se o Programador vier até aqui de sua câmara de audiências, você estará morto.",,"Care mai e problema ta? Dacă Programatorul vine sus din camera sa de audiență, ești mort.","Проклятье, что с тобой не так? Если Программист поднимется из приёмного зала, ты покойник!",,"Senin sorunun ne? Eğer Programcı seyirci odasından çıkarsa, öldün demektir." +死んでいた所だ。","너희들 제정신이야? 프로그래머님이 알현실에서 뛰쳐나오는 순간, 네 놈은 죽게 될 거라고!","Wat de hel is jouw probleem? Als de programmeur uit zijn publiekskamer komt, ben je dood.","Hva i helvete er problemet ditt? Hvis programmereren kommer opp fra audiensrommet, er du død.",Jaki masz problem do diaska? Jeśli Programista wyjdzie ze swojej sali audiencji będziesz martwy.,"Qual é o seu problema? Se o Programador vier até aqui de sua câmara de audiências, você estará morto.",,"Care mai e problema ta? Dacă Programatorul vine sus din camera sa de audiență, ești mort.","Проклятье, что с тобой не так? Если Программист поднимется из приёмного зала, ты покойник!",,Vad i helvete är ditt problem. Om Programmeraren kommer upp från sin publikrum är du död.,"Senin sorunun ne? Eğer Programcı seyirci odasından çıkarsa, öldün demektir." "Hey, you're not cleared to go down there.",TXT_DLG_SCRIPT07_D4548_HEYYO,,,,"Hej, nemáš povolení jít tam dolů.",Du har ikke tilladelse til at gå derned.,"He, du darfst da nicht runtergehen.",,"He, vi ne rajtas iri malsupren.","Oye, no tienes permiso para bajar aquí.",,"Hei, sinulla ei ole lupaa mennä alas sinne.","Hé, vous n'avez pas le droit d'être ici.","Héj, nincs engedélyed oda lemenni.","Ehi, non hai l'autorizzazione per andare laggiù.","おい、あんたはここを降りる事は -許可されてないぞ。",잠깐. 너는 밑으로 내려갈 허가를 받지 않았다.,"Hé, je hebt geen toestemming om naar beneden te gaan.","Hei, du er ikke klarert til å gå ned dit.","Hej, nie masz zgody na zejście tam.","Ei, você não tem permissão para descer aí.",,"Hei, n-ai acces să mergi acolo jos.","Эй, у тебя нет разрешения спускаться туда.",,"Hey, oraya inme iznin yok." +許可されてないぞ。",잠깐. 너는 밑으로 내려갈 허가를 받지 않았다.,"Hé, je hebt geen toestemming om naar beneden te gaan.","Hei, du er ikke klarert til å gå ned dit.","Hej, nie masz zgody na zejście tam.","Ei, você não tem permissão para descer aí.",,"Hei, n-ai acces să mergi acolo jos.","Эй, у тебя нет разрешения спускаться туда.",,Du har inte tillstånd att gå ner dit.,"Hey, oraya inme iznin yok." Programmer? Who told you that? There is no Programmer. That story was spread ages ago. Don't tell me the Front actually believed that crap. Idiots.,TXT_DLG_SCRIPT07_D6064_PROGR,MAP07: Computer room (northwest building).,,,"Programátor? Kdo ti to řekl? Není žádný Programátor. To je stará pověra. Neříkej mi, že tomu Fronta doopravdy věřila. Idioti.","Programmør? Hvem har fortalt dig det? Der er ingen programmør. Den historie blev spredt for længe siden. Fortæl mig ikke, at fronten troede på det lort. Idioter.","Programmierer? Wer hat dir das erzählt? Es gibt keinen Programmierer. Das ist eine alte Legende. Sag mir nicht, dass die Front an diesen Blödsinn glaubt. Idioten.",,"Ĉu Programisto? Kie vi aŭdis tion? Ne estas Programisto; tiu storio ekdisvastiĝis antaŭ jaroj. Ne diru, ke la Fronto kredis tian fekaĵon. Kiel stultaj.",¿Programador? ¿De dónde sacas eso? No hay Programador; esa historia se ha extendido desde hace años. No me digas que el Frente realmente se ha creído el cuentito. Qué idiotas.,,"Ohjelmoitsija? Kuka sinulle on kertonut? Ei ole mitään Ohjelmoitsijaa. Tarina oli laitettu liikkeelle ajat sitten. Älä vain kerro, että Rintama oikeasti uskoi siihen höpöpuheeseen. Mitä idiootteja.",Programmeur? Qui vous a raconté ça? Il n'y a pas de Programmeur. Cette rumeur a commencé il y a des années. J'arrive pas à croire que ces abrutis du Front y croient. Idiots.,"Programozó? Ki mondta ezt neked? Nincs semmiféle programozó. Ez egy ezer éves történet. Azt ne mondd már, hogy a Front elhitte ezt a maszlagot. Idióták.",Programmatore? Ma chi te l'ha detto? Non c'è nessun Programmatore. Quella storia è stata diffusa un sacco di tempo fa. Non dirmi che il Fronte ha creduto a queste scempiaggini. Che idioti.,"プログラマー?誰ガそんなことヲ言った? ここにプログラマーハいない。 その噂ハ何年も前ニ広まったものダ。 そんな下らない事ヲ未だニ信じていたとは。 白痴モいいとこだ。","프로그래머? 누가 알려준 거야? 프로그래머 따위는 존재하지 않아. 이 소문이 몇 년 동안 계속 퍼졌다는 게 믿기지 않아. 프론트도 그 잡소문을 아직도 믿고 있던 모양이었고. 한심하네. - \cy여기가 아닌가 봐. 다른 곳을 찾아봐야겠어.",Programmeur? Wie heeft je dat verteld? Er is geen programmeur. Dat verhaal is eeuwen geleden verspreid. Vertel me niet dat het Front die onzin echt geloofde. Idioten.,Programmerer? Hvem har sagt det? Det finnes ingen programmerer. Den historien ble spredt for lenge siden. Ikke fortell meg at Fronten faktisk trodde på den dritten. Idioter.,"Programista? Kto ci to powiedział? Nie ma żadnego Programisty. Ta historia została wymyślona wiele lat temu. Tylko mi nie mów, że Front wierzy w te bzdury. Idioci.",Programador? Quem te disse isso? Não existe nenhum Programador. Essa história anda se espalhando desde muito tempo. Não me diga que a Frente acreditou mesmo nessa bobagem. Otários.,,Programator? Cine ți-a spus asta? Nu e niciun Programator. Povestea asta a fost răspândită acum multă vreme. Nu-mi spune că Frontul chiar a crezut prostia asta. Idioți.,"Программист? Кто тебе это сказал? Нет никакого программиста. Этой байке уже сто лет. Только не говори мне, что Сопротивление и правда поверило в эту чушь. Идиоты.",,Programcı mı? Bunu sana kim söyledi? Programcı diye biri yok. Bu hikaye yıllar önce yayıldı. Bana Cephe'nin bu saçmalığa gerçekten inandığını söyleme. Aptallar. -"Well, what's the truth then?",TXT_RPLY0_SCRIPT07_D6064_WELLW,〃,,,Kde je tedy pravda?,"Nå, hvad er sandheden så?","Nun, was ist denn die Wahrheit?",,"Tiuokaze, kiu estas la vero?",¿Entonces cuál es la verdad?,,"No, mikä totuus sitten on?","Quelle est la vérité, alors?","Nos, mi az igazság akkor?",E allora qual'è la verità?,それなら、本当の事は何だ?,"그럼, 진실이 뭐야?","Nou, wat is de waarheid dan?","Hva er sannheten, da?",Więc co jest prawdą?,"Bem, qual é a verdade?",,"Păi, care e adevărul atunci?","Ладно, и что же тогда правда?",,"Peki, gerçek ne o zaman?" + \cy여기가 아닌가 봐. 다른 곳을 찾아봐야겠어.",Programmeur? Wie heeft je dat verteld? Er is geen programmeur. Dat verhaal is eeuwen geleden verspreid. Vertel me niet dat het Front die onzin echt geloofde. Idioten.,Programmerer? Hvem har sagt det? Det finnes ingen programmerer. Den historien ble spredt for lenge siden. Ikke fortell meg at Fronten faktisk trodde på den dritten. Idioter.,"Programista? Kto ci to powiedział? Nie ma żadnego Programisty. Ta historia została wymyślona wiele lat temu. Tylko mi nie mów, że Front wierzy w te bzdury. Idioci.",Programador? Quem te disse isso? Não existe nenhum Programador. Essa história anda se espalhando desde muito tempo. Não me diga que a Frente acreditou mesmo nessa bobagem. Otários.,,Programator? Cine ți-a spus asta? Nu e niciun Programator. Povestea asta a fost răspândită acum multă vreme. Nu-mi spune că Frontul chiar a crezut prostia asta. Idioți.,"Программист? Кто тебе это сказал? Нет никакого программиста. Этой байке уже сто лет. Только не говори мне, что Сопротивление и правда поверило в эту чушь. Идиоты.",,Programmerare? Vem har sagt det? Det finns ingen programmerare. Den historien spreds för länge sedan. Säg inte att fronten verkligen trodde på den skiten. Idioter.,Programcı mı? Bunu sana kim söyledi? Programcı diye biri yok. Bu hikaye yıllar önce yayıldı. Bana Cephe'nin bu saçmalığa gerçekten inandığını söyleme. Aptallar. +"Well, what's the truth then?",TXT_RPLY0_SCRIPT07_D6064_WELLW,〃,,,Kde je tedy pravda?,"Nå, hvad er sandheden så?","Nun, was ist denn die Wahrheit?",,"Tiuokaze, kiu estas la vero?",¿Entonces cuál es la verdad?,,"No, mikä totuus sitten on?","Quelle est la vérité, alors?","Nos, mi az igazság akkor?",E allora qual'è la verità?,それなら、本当の事は何だ?,"그럼, 진실이 뭐야?","Nou, wat is de waarheid dan?","Hva er sannheten, da?",Więc co jest prawdą?,"Bem, qual é a verdade?",,"Păi, care e adevărul atunci?","Ладно, и что же тогда правда?",,Vad är sanningen då?,"Peki, gerçek ne o zaman?" I told you all I know. You are wasting your time.,TXT_DLG_SCRIPT07_D7580_ITOLD,〃,,,"Řekl jsem ti vše, co vím. Ztrácíš tu čas.","Jeg har fortalt dig alt, hvad jeg ved. Du spilder din tid.","Ich habe alles gesagt, was ich weiß. Du verschwendest deine Zeit.",,"Mi diris ĉion, kion mi scias. Vi perdas tempon.",Te he dicho todo lo que sé. Estás perdiendo el tiempo.,Ya te dije todo lo que sé. Estás perdiendo el tiempo.,"Minä kerroin jo kaiken, mitä tiedän. Tuhlaat aikaasi.",Je t'ai dit tous ce que je sais. Tu perds ton temps.,"Elmondtam mindent, amit tudtam. Csak az idődet vesztegeted.",Ti ho detto tutto quello che so. Stai sprecando il tuo tempo.,"私ハ知っていることヲ教えた。 -これ以上ハ互いニ時間ノ無駄ダ。",다 알려줬어. 시간 낭비하지 마.,Ik heb je alles verteld wat ik weet. Je verspilt je tijd.,Jeg har sagt alt jeg vet. Dere kaster bort tiden deres.,Powiedziałem ci wszystko co wiem. Marnujesz swój czas.,Eu já contei tudo o que eu sei. Você está perdendo tempo.,,"Ți-am spus tot ce știu, îți pierzi vremea.","Я рассказал всё, что знаю. Ты попусту тратишь время.",,Size tüm bildiklerimi anlattım. Zamanınızı boşa harcıyorsunuz. +これ以上ハ互いニ時間ノ無駄ダ。",다 알려줬어. 시간 낭비하지 마.,Ik heb je alles verteld wat ik weet. Je verspilt je tijd.,Jeg har sagt alt jeg vet. Dere kaster bort tiden deres.,Powiedziałem ci wszystko co wiem. Marnujesz swój czas.,Eu já contei tudo o que eu sei. Você está perdendo tempo.,,"Ți-am spus tot ce știu, îți pierzi vremea.","Я рассказал всё, что знаю. Ты попусту тратишь время.",,Jag har berättat allt jag vet. Du slösar bort din tid.,Size tüm bildiklerimi anlattım. Zamanınızı boşa harcıyorsunuz. "Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D9096_FIGHT,MAP07: Font soldier.,,,"Bojuj dál, však my zvítězíme! Dnešek bude patřit nám!","Kæmp videre, vi vil triumfere. Denne dag vil tilhøre os!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,La batalo daŭru; ni venkos. Ĉi tiu tago estas nia!,"A seguir peleando, que hoy vamos a triunfar. ¡Este día es nuestro!",,"Jatkakaa taistoa, voitto on meidän. Tämä päivä kuuluu meille!","Continuez à vous battre, nous allons triompher! Ce jour nous appartient!",Előre a győzelembe! Mi leszünk a nap győztesei!,"Continuate a combattere, trionferemo. Questo è il nostro giorno!","我々は勝利を志し、戦う。 -この日は我々と共に在る!","같이 싸우자! 우리들이 이길 거고, 밝은 날이 찾아올 거야!","Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" +この日は我々と共に在る!","같이 싸우자! 우리들이 이길 거고, 밝은 날이 찾아올 거야!","Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Kämpa vidare, vi kommer att triumfera. Den här dagen kommer att tillhöra oss!","Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" "Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D10612_FIGHT,〃,,,"Bojuj dál, však my zvítězíme! Dnešek bude patřit nám!","Kæmp videre, vi vil triumfere. Denne dag vil tilhøre os!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,La batalo daŭru; ni venkos. Ĉi tiu tago estas nia!,"A seguir peleando, que hoy vamos a triunfar. ¡Este día es nuestro!",,"Jatkakaa taistoa, voitto on meidän. Tämä päivä kuuluu meille!","Continuez à vous battre, nous allons triompher! Ce jour nous appartient!",Előre a győzelembe! Mi leszünk a nap győztesei!,"Continuate a combattere, trionferemo. Questo è il nostro giorno!","我々は勝利を志し、戦う。 -この日は我々と共に在る!",오늘이야말로 결전의 시간이야. 우리들이 바랬던 날을 위해!!,"Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" +この日は我々と共に在る!",오늘이야말로 결전의 시간이야. 우리들이 바랬던 날을 위해!!,"Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Kämpa vidare, vi kommer att triumfera. Den här dagen kommer att tillhöra oss!","Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" "Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D12128_FIGHT,〃,,,"Bojuj dál, však my zvítězíme! Dnešek bude patřit nám!","Kæmp videre, vi vil triumfere. Denne dag vil tilhøre os!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,La batalo daŭru; ni venkos. Ĉi tiu tago estas nia!,"A seguir peleando, que hoy vamos a triunfar. ¡Este día es nuestro!",,"Jatkakaa taistoa, voitto on meidän. Tämä päivä kuuluu meille!","Continuez à vous battre, nous allons triompher! Ce jour nous appartient!",Előre a győzelembe! Mi leszünk a nap győztesei!,"Continuate a combattere, trionferemo. Questo è il nostro giorno!","我々は勝利を志し、戦う。 -この日は我々と共に在る!","우리들 중 한 명이 죽는다 해도, 승리는 확신해. 잃을 게 없어!","Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" +この日は我々と共に在る!","우리들 중 한 명이 죽는다 해도, 승리는 확신해. 잃을 게 없어!","Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Kämpa vidare, vi kommer att triumfera. Den här dagen kommer att tillhöra oss!","Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" "Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D13644_FIGHT,〃,,,"Bojuj dál, však my zvítězíme! Dnešek bude patřit nám!","Kæmp videre, vi vil triumfere. Denne dag vil tilhøre os!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,La batalo daŭru; ni venkos. Ĉi tiu tago estas nia!,"A seguir peleando, que hoy vamos a triunfar. ¡Este día es nuestro!",,"Jatkakaa taistoa, voitto on meidän. Tämä päivä kuuluu meille!","Continuez à vous battre, nous allons triompher! Ce jour nous appartient!",Előre a győzelembe! Mi leszünk a nap győztesei!,"Continuate a combattere, trionferemo. Questo è il nostro giorno!","我々は勝利を志し、戦う。 -この日は我々と共に在る!","오더에 패배와 몰락을, 프론트에 인류와 영원한 자유를!","Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" +この日は我々と共に在る!","오더에 패배와 몰락을, 프론트에 인류와 영원한 자유를!","Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Kämpa vidare, vi kommer att triumfera. Den här dagen kommer att tillhöra oss!","Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" "Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D15160_FIGHT,〃,,,"Bojuj dál, však my zvítězíme! Dnešek bude patřit nám!","Kæmp videre, vi vil triumfere. Denne dag vil tilhøre os!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,La batalo daŭru; ni venkos. Ĉi tiu tago estas nia!,"A seguir peleando, que hoy vamos a triunfar. ¡Este día es nuestro!",,"Jatkakaa taistoa, voitto on meidän. Tämä päivä kuuluu meille!","Continuez à vous battre, nous allons triompher! Ce jour nous appartient!",Előre a győzelembe! Mi leszünk a nap győztesei!,"Continuate a combattere, trionferemo. Questo è il nostro giorno!","我々は勝利を志し、戦う。 -この日は我々と共に在る!",희망 한가닥 작전을 위해! 오더여! 내가 돌아왔다!!,"Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" +この日は我々と共に在る!",희망 한가닥 작전을 위해! 오더여! 내가 돌아왔다!!,"Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Kämpa vidare, vi kommer att triumfera. Den här dagen kommer att tillhöra oss!","Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" "Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D16676_FIGHT,〃,,,"Bojuj dál, však my zvítězíme! Dnešek bude patřit nám!","Kæmp videre, vi vil triumfere. Denne dag vil tilhøre os!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,La batalo daŭru; ni venkos. Ĉi tiu tago estas nia!,"A seguir peleando, que hoy vamos a triunfar. ¡Este día es nuestro!",,"Jatkakaa taistoa, voitto on meidän. Tämä päivä kuuluu meille!","Continuez à vous battre, nous allons triompher! Ce jour nous appartient!",Előre a győzelembe! Mi leszünk a nap győztesei!,"Continuate a combattere, trionferemo. Questo è il nostro giorno!","我々は勝利を志し、戦う。 -この日は我々と共に在る!","슬프지만, 이 것은 전쟁이잖아.","Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" +この日は我々と共に在る!","슬프지만, 이 것은 전쟁이잖아.","Vecht verder, we zullen zegevieren. Deze dag zal van ons zijn!","Kjemp videre, vi vil seire. Denne dagen vil tilhøre oss!","Walcz dalej, i tak zwyciężymy. Dzień należy do nas!","Continue lutando, nós iremos triunfar. Este dia pertence a nós!",,"Continuă lupta, vom triumfa. Ziua asta ne aparține!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!",,"Kämpa vidare, vi kommer att triumfera. Den här dagen kommer att tillhöra oss!","Savaşmaya devam edin, zafere ulaşacağız. Bu gün bize ait olacak!" "You killed all the guards. Don't hurt me. I told him this was a dumb idea. The real Programmer's in the keep. Here, take this key.",TXT_DLG_SCRIPT08_D0_YOUKI,MAP08: Northeast room.,,,"Tys zabil všechny stráže! Neubližuj mi. Já mu říkal, že to je hloupý nápad. Skutečný Programátor je v pevnosti. Tady, vem si tenhle klíč.","Du dræbte alle vagterne. Gør mig ikke noget. Jeg sagde til ham, at det var en dum idé. Den rigtige programmør er i tårnet. Her, tag denne nøgle.","Du hast alle Wächter getötet. Bitte tu mir nichts. Ich habe ihm gesagt, es wäre eine dumme Idee. Der Programmierer ist in seiner Unterkunft. Hier nimm diesen Schlüssel.",,"Vi mortigis ĉiujn gardistojn. Ne vundu min. Mi diris al li, ke ĉi tiu estas stulta ideo; la vera Programisto estas en la ĉefturo. Jen la ŝlosilo.","Has matado a todos los guardias. No me hagas nada. Le dije que era una idea estúpida; el verdadero Programador está en el torreón. Ten, toma esta llave.","Mataste a todos los guardias. No me hagas nada. Le dije que era una idea estúpida; el verdadero Programador está en el torreón. Ten, toma esta llave.","Tapoit kaikki vartijat. Älä satuta minua. Sanoin hänelle, että tämä oli tyhmä idea. Oikea Ohjelmoitsija on linnakkeessa. Tässä, ota tämä avain.",Vous avez tué tous les gardes. Ne me faites pas de mal. Je lui ai dit que c'était une idée stupide. Le vrai Programmeur se trouve dans le donjon. Prenez cette clé.,"Te ölted meg az összes őrt. Kérlek ne bánts. Én megmondtam, hogy ez egy rossz ötlet. Az igazi Programozó a vártoronyban van. Vidd ezt a kulcsot.","Hai ucciso tutte le guardie. Ho cercato di fargli capire che era un'idea stupida. Il vero Programmatore è nella fortezza. Ecco, prendi questa chiave.","君がガードを全員殺したノカ。 私ハ傷つけないでくれ。 私ハ望んでこんなふざけた事をしたワケではない。 本当のプログラマーはこのキーの場所ニいる。 -ほら、受け取れ。",경비들을 모조리 죽이시다니! 해치지 말아주세요. 제가 그분께 어리석은 짓이라고 제안을 했었는데... 진짜 프로그래머님은 성채에 있습니다. 이 열쇠를 쓰세요.,"Je hebt alle bewakers gedood. Doe me geen pijn. Ik zei hem dat dit een dom idee was. De echte programmeur is in de donjon. Hier, pak deze sleutel.","Du drepte alle vaktene. Ikke gjør meg noe. Jeg sa at dette var en dum idé. Den virkelige programmereren er i borgen. Her, ta denne nøkkelen.","Zabiłeś wszystkich strażników. Nie krzywdź mnie. Mówiłem mu, że to głupi pomysł. Prawdziwy Programista jest w twierdzy. Masz, weź ten klucz.","Você matou todos os guardas. Não me machuque. Eu disse a ele que isso era uma idéia besta. O verdadeiro Programador está na fortaleza. Aqui, pegue esta chave.",,Ai omorât toți gardienii. Nu mă rănii. I-am spus că e o idee proastă. Adevăratul Programator e înăuntru. Ia cheia asta.,"Ты убил всех стражников. Не трогай меня! Я говорил ему, что это глупая идея. Настоящий Программист в цитадели. Вот, возьми этот ключ.",,"Bütün muhafızları öldürdün. Bana zarar vermeyin. Ona bunun aptalca bir fikir olduğunu söyledim. Gerçek Programcı kalede. İşte, al şu anahtarı." -You're the Programmer!,TXT_RPLY0_SCRIPT08_D0_YOURE,〃,,,Ty jsi Programátor!,"Det er dig, der er programmøren!",Du bist der Programmierer!,,Vi estas la Programisto!,¡Tú eres el Programador!,,Sinä olet Ohjelmoitsija!,Vous êtes le Programmeur!,Te vagy a Programozó!,Sei tu il Programmatore!,アンタがプログラマーだろ!,넌 프로그래머잖아!,Jij bent de programmeur!,Du er programmereren!,To ty jesteś Programistą!,Você é o Programador!,,Tu ești Programatorul!,Ты Программист!,,Programcı sensin! -"Do I look like I wield ultimate power? The Order uses us all. Now go, I'm dead already.",TXT_DLG_SCRIPT08_D1516_DOILO,〃,,,"Vypadám snad jako bych se měl pyšnit nesmírnou mocí? Řád nás všechny využívá. Teď jdi, já jsem už teď mrtvý.","Ser jeg ud, som om jeg udøver den ultimative magt? Ordenen bruger os alle. Gå nu, jeg er allerede død.","Sehe ich so aus, als ob ich unendliche Macht hätte? Der Orden benutzt uns alle. Nun geh, ich bin ohnehin schon tot.",,"Ĉu mi aspektas kiel posedanto de absoluta povo? La Ordono uzas nin ĉiujn. Foriru, mi jam estas mortinta.","¿Te parezco poseer el poder absoluto? La Orden nos usa a todos. Ya vete, que yo ya estoy muerto.",,"Näytänkö muka sellaiselta, joka pitää hallussaan täyttä valtaa? Veljeskunta käyttää hyväkseen meitä kaikkia. Mene, olen jo yhtä kuin kuollut.","Est-ce que j'ai l'air d'avoir le pouvoir suprême? L'Ordre nous utilise tous. Partez, je suis déjà mort.","Úgy nézek ki, mint aki mindenki felett erőt gyakorol? A Rend kihasznál mindannyiunkat. Menj tovább, Én már amúgyis halott vagyok.","Davvero ti sembro uno che possiede poteri sovrumani? L'Ordine ci usa tutti. Adesso vai, tanto io sono spacciato ormai.","私ガそんな凄まじい力ヲ振舞っていると思うか? +ほら、受け取れ。",경비들을 모조리 죽이시다니! 해치지 말아주세요. 제가 그분께 어리석은 짓이라고 제안을 했었는데... 진짜 프로그래머님은 성채에 있습니다. 이 열쇠를 쓰세요.,"Je hebt alle bewakers gedood. Doe me geen pijn. Ik zei hem dat dit een dom idee was. De echte programmeur is in de donjon. Hier, pak deze sleutel.","Du drepte alle vaktene. Ikke gjør meg noe. Jeg sa at dette var en dum idé. Den virkelige programmereren er i borgen. Her, ta denne nøkkelen.","Zabiłeś wszystkich strażników. Nie krzywdź mnie. Mówiłem mu, że to głupi pomysł. Prawdziwy Programista jest w twierdzy. Masz, weź ten klucz.","Você matou todos os guardas. Não me machuque. Eu disse a ele que isso era uma idéia besta. O verdadeiro Programador está na fortaleza. Aqui, pegue esta chave.",,Ai omorât toți gardienii. Nu mă rănii. I-am spus că e o idee proastă. Adevăratul Programator e înăuntru. Ia cheia asta.,"Ты убил всех стражников. Не трогай меня! Я говорил ему, что это глупая идея. Настоящий Программист в цитадели. Вот, возьми этот ключ.",,"Du dödade alla vakter. Gör mig inte illa. Jag sa till honom att detta var en dum idé. Den riktiga programmeraren är i fängelset. Här, ta den här nyckeln.","Bütün muhafızları öldürdün. Bana zarar vermeyin. Ona bunun aptalca bir fikir olduğunu söyledim. Gerçek Programcı kalede. İşte, al şu anahtarı." +You're the Programmer!,TXT_RPLY0_SCRIPT08_D0_YOURE,〃,,,Ty jsi Programátor!,"Det er dig, der er programmøren!",Du bist der Programmierer!,,Vi estas la Programisto!,¡Tú eres el Programador!,,Sinä olet Ohjelmoitsija!,Vous êtes le Programmeur!,Te vagy a Programozó!,Sei tu il Programmatore!,アンタがプログラマーだろ!,넌 프로그래머잖아!,Jij bent de programmeur!,Du er programmereren!,To ty jesteś Programistą!,Você é o Programador!,,Tu ești Programatorul!,Ты Программист!,,Du är programmeraren!,Programcı sensin! +"Do I look like I wield ultimate power? The Order uses us all. Now go, I'm dead already.",TXT_DLG_SCRIPT08_D1516_DOILO,〃,,,"Vypadám snad jako bych se měl pyšnit nesmírnou mocí? Řád nás všechny využívá. Teď jdi, já jsem už teď mrtvý.","Ser jeg ud, som om jeg udøver den ultimative magt? Ordenen bruger os alle. Gå nu, jeg er allerede død.","Sehe ich so aus, als ob ich unendliche Macht hätte? Der Orden benutzt uns alle. Nun geh, ich bin ohnehin schon tot.",,"Ĉu mi aspektas kiel posedanto de absoluta povo? La Ordeno uzas nin ĉiujn. Foriru, mi jam estas mortinta.","¿Te parezco poseer el poder absoluto? La Orden nos usa a todos. Ya vete, que yo ya estoy muerto.",,"Näytänkö muka sellaiselta, joka pitää hallussaan täyttä valtaa? Veljeskunta käyttää hyväkseen meitä kaikkia. Mene, olen jo yhtä kuin kuollut.","Est-ce que j'ai l'air d'avoir le pouvoir suprême? L'Ordre nous utilise tous. Partez, je suis déjà mort.","Úgy nézek ki, mint aki mindenki felett erőt gyakorol? A Rend kihasznál mindannyiunkat. Menj tovább, Én már amúgyis halott vagyok.","Davvero ti sembro uno che possiede poteri sovrumani? L'Ordine ci usa tutti. Adesso vai, tanto io sono spacciato ormai.","私ガそんな凄まじい力ヲ振舞っていると思うか? オーダーハ私達全員を利用している。 -私ハもう死人同然だ。さあ行け。","제가 신적인 힘을 갖고 있다고 생각하나요? 오더는 어차피 모두를 부려먹습니다. 떠나세요, 전 이미 죽은 목숨이에요.","Zie ik eruit alsof ik de ultieme macht heb? De Orde gebruikt ons allemaal. Ga nu, ik ben al dood.","Ser jeg ut som om jeg har den ultimate makten? Ordenen bruker oss alle. Gå nå, jeg er allerede død.","Czy wyglądam jakbym był we władaniu niesamowitej mocy? Zakon wykorzystuje nas wszystkich. Idź stąd, i tak już jestem martwy.",Você acha que eu pareço alguém que possui um poder tremendo? A Ordem manipula a todos nós. Agora vá. Eu já estou morto.,,"Ți se pare că controlez puterea supremă? Ordinul ne folosește pe toți. Acum pleacă, sunt mort deja.",Разве я похож на обладателя невероятной мощи? Орден использует нас всех. Теперь иди. Я уже всё равно мёртв.,,"Nihai güce sahipmişim gibi mi görünüyorum? Tarikat hepimizi kullanır. Şimdi git, ben zaten ölüyüm." -Power is the key!,TXT_DLG_SCRIPT08_D3032_POWER,,,,Moc je tím klíčem!,Magt er nøglen!,Macht ist der Schlüssel!,,Povo estas la ŝlosilo!,¡El poder es la clave!,,Valta on avain!,Le pouvoir est la clé!,Az erő a kulcs!,Il potere è la chiave!,キーが力だ!,힘이 곧 열쇠다!,Kracht is de sleutel!,Makt er nøkkelen!,Moc jest kluczem!,O poder é a chave!,,Puterea e cheia!,В силе — всё!,,Güç anahtardır! +私ハもう死人同然だ。さあ行け。","제가 신적인 힘을 갖고 있다고 생각하나요? 오더는 어차피 모두를 부려먹습니다. 떠나세요, 전 이미 죽은 목숨이에요.","Zie ik eruit alsof ik de ultieme macht heb? De Orde gebruikt ons allemaal. Ga nu, ik ben al dood.","Ser jeg ut som om jeg har den ultimate makten? Ordenen bruker oss alle. Gå nå, jeg er allerede død.","Czy wyglądam jakbym był we władaniu niesamowitej mocy? Zakon wykorzystuje nas wszystkich. Idź stąd, i tak już jestem martwy.",Você acha que eu pareço alguém que possui um poder tremendo? A Ordem manipula a todos nós. Agora vá. Eu já estou morto.,,"Ți se pare că controlez puterea supremă? Ordinul ne folosește pe toți. Acum pleacă, sunt mort deja.",Разве я похож на обладателя невероятной мощи? Орден использует нас всех. Теперь иди. Я уже всё равно мёртв.,,"Ser jag ut som om jag har den ultimata makten? Orden använder oss alla. Gå nu, jag är redan död.","Nihai güce sahipmişim gibi mi görünüyorum? Tarikat hepimizi kullanır. Şimdi git, ben zaten ölüyüm." +Power is the key!,TXT_DLG_SCRIPT08_D3032_POWER,,,,Moc je tím klíčem!,Magt er nøglen!,Macht ist der Schlüssel!,,Povo estas la ŝlosilo!,¡El poder es la clave!,,Valta on avain!,Le pouvoir est la clé!,Az erő a kulcs!,Il potere è la chiave!,キーが力だ!,힘이 곧 열쇠다!,Kracht is de sleutel!,Makt er nøkkelen!,Moc jest kluczem!,O poder é a chave!,,Puterea e cheia!,В силе — всё!,,Makt är nyckeln!,Güç anahtardır! "Good, you're conscious again. When you grabbed that item the Programmer dropped, you let loose some terrible secrets.",TXT_DLG_SCRIPT10_D0_GOODY,MAP10: Macil.,,,"Už jsi vzhůru, dobře. Když jsi sebral tu věc, kterou Programátor upustil, odhalil jsi děsivá tajemství.","Godt, du er ved bevidsthed igen. Da du greb den genstand, som programmøren tabte, slap du nogle frygtelige hemmeligheder løs.","Gut, du bist wieder wach. Als du das Ding, das der Programmierer fallengelassen hat, packtest, hast du einige schlimme Geheimnisse enthüllt.",,"Bone, vi jam rekonsciiĝis. Kelkaj teruraj sekretoj malkovriĝis kiam vi prenis tiun objekton, kiu elfalis el la Programisto.","Bien, ya has despertado. Se han revelado un par de secretos terribles en cuanto has cogido el objeto ese que se le ha caído al Programador.","Bien, ya despertaste. Se revelaron un par de secretos terribles en cuanto agarraste el objeto ese que se le cayó al Programador.","Hyvä, olet jälleen tajuissasi. Kaapattuasi esineen, jonka Ohjelmoitsija oli pudottanut, toit valoon kauhistuttavia salaisuuksia.","Bien. Vous êtes conscient. Quand vous avez pris ceci au Programmeur, vous avez libéré de terrible secrets.","Remek, magadhoz tértél. Amikor megmarkoltad a tárgyat amit a Programozó elejtett, elég sok titokra fény derült.","Meno male, sei di nuovo conscio. Quando hai preso quell'oggetto dal Programmatore, hai scoperchiato dei terribili segreti.","良し、意識が戻ったか。 君がプログラマーの遺品を拾った時に -恐ろしい秘密が解放されたのだ。","아, 드디어 깨어났군요. 프로그래머가 죽고 나서 얻은 저 물건을 쥐는 동안 우리는 그것에 대한 끔찍한 비밀을 밝혀냈습니다...","Goed, je bent weer bij bewustzijn. Toen je dat item pakte, liet de programmeur je een aantal vreselijke geheimen los.","Bra, du er ved bevissthet igjen. Da du tok den gjenstanden programmereren mistet, slapp du løs noen forferdelige hemmeligheter.","Dobrze, znów jesteś przytomny. Kiedy podniosłeś ten przedmiot, który upuścił Programista, uwolnniłeś wiele strasznych sekretów.","Ótimo, já está consciente de novo. Quando você pegou o item que o Programador largou você deixou escapar alguns segredos terríveis.",,"Bun, ești conștient din nou. Când ai pus mâna pe obiectul ăla Programatorul ți-a dat drumul ca să elibereze niște secrete oribile.","Хорошо, ты пришёл в себя. Взяв в руки артефакт, который выронил Программист, ты раскрыл страшные тайны.",,"Güzel, tekrar kendine geldin. Programcı'nın düşürdüğü o eşyayı aldığında, bazı korkunç sırları açığa çıkardın." -What kind of secrets. ,TXT_RPLY0_SCRIPT10_D0_WHATK,〃,,,Jaká tajemství?,Hvilken slags hemmeligheder?,Was für Geheimnisse?,,Kiaj sekretoj?,¿Qué clase de secretos?,,Minkälaisia salaisuuksia?,De quels secrets parlez-vous?,Miféle titkok?,Che tipo di segreti.,その秘密とは。,어떤 비밀인가요?,Wat voor geheimen.,Hva slags hemmeligheter?,Jakich sekretów?,Que tipos de segredos?,,Ce fel de secrete?,Какие тайны?,,Ne tür sırlar? -"We have no idea where this weapon came from, but we must find out. You have wrested one from the Order, but we must have all five. We have reached the limits of my knowledge. Seek out the Oracle and ask it for help.",TXT_DLG_SCRIPT10_D1516_WEHAV,〃,,,"Nemáme tušení, odkud se tato zbraň vzala, ale musíme to zjistit. Jednu část jsi z rukou Řádu už umanul, ale musíme najít všech pět. Dosáhli jsme hranic mých vědomostí. Vyhledej Věštce a požádej jej o pomoc.","Vi har ingen anelse om, hvor dette våben kommer fra, men vi må finde ud af det. Du har vristet en fra Ordenen, men vi skal have alle fem. Vi har nået grænserne for min viden. Opsøg Oraklet og bed det om hjælp.","Wir haben keine Ahnung, wo diese Waffe herkommt, aber wir müssen es herausfinden. Du hast ein Teil dem Orden entrungen aber wir brauchen alle fünf. Wir haben die Grenzen meines Wissens erreicht. Suche das Orakel und frage es um Hilfe.",,"Ĝi estas armilo; ni ne konas ĝian originon, sed ni devas malkovri ĝin. Vi jam prenis pecon el La Ordono, sed ni bezonas ĉiujn kvin. Ĝis ĉi tie ĉio, kion mi scias. Serĉu la Orakolon kaj petu lin pri helpo.","Se trata de un arma; no sabemos su origen, pero hay que averiguarlo. Ya le has quitado una pieza a La Orden, pero necesitamos las cinco. Hasta ahí todo lo que sé. Busca al Oráculo y pídele ayuda.","Se trata de un arma; no sabemos su origen, pero hay que averiguarlo. Ya le quitaste una pieza a La Orden, pero necesitamos las cinco. Hasta ahí todo lo que sé. Busca al Oráculo y pídele ayuda.","Meillä ei ole aavistustakaan tämän aseen alkuperästä, mutta se on selvitettävä. Olet nyt riistänyt Veljeskunnan käsistä yhden, mutta meidän on saatava kaikki viisi. Oma tietämykseni päättyy tähän. Etsi apua Oraakkelilta.","Je n'ai aucune idée d'où vient cette arme, mais il faut que nous le découvrions. Vous en avez arraché une à l'Ordre, mais il faut trouver toutes les cinq. C'est tout ce que je sais pour l'instant. Allez voir l'Oracle et demandez son aide.","Nem tudjuk mi ennek a fegyvernek az eredete, de ki kell derítenünk. Elcsentél egyet a Rendtől, de meg kell szereznünk mind az ötöt. Elértük a tudásom határát. Keresd fel az Orákulumot, és kérdd a segítségét.","Non abbiamo alcuna idea su dove quest'arma provenga, ma dobbiamo scoprirlo. Ne hai sottratto una all'Ordine, ma dobbiamo ottenerle tutte e cinque. E qui abbiamo raggiunto il limite della mia conoscienza. Devi raggiungere l'Oracolo e chiedergli aiuto.","この武器が何処で造られたかは分からないが、 +恐ろしい秘密が解放されたのだ。","아, 드디어 깨어났군요. 프로그래머가 죽고 나서 얻은 저 물건을 쥐는 동안 우리는 그것에 대한 끔찍한 비밀을 밝혀냈습니다...","Goed, je bent weer bij bewustzijn. Toen je dat item pakte, liet de programmeur je een aantal vreselijke geheimen los.","Bra, du er ved bevissthet igjen. Da du tok den gjenstanden programmereren mistet, slapp du løs noen forferdelige hemmeligheter.","Dobrze, znów jesteś przytomny. Kiedy podniosłeś ten przedmiot, który upuścił Programista, uwolnniłeś wiele strasznych sekretów.","Ótimo, já está consciente de novo. Quando você pegou o item que o Programador largou você deixou escapar alguns segredos terríveis.",,"Bun, ești conștient din nou. Când ai pus mâna pe obiectul ăla Programatorul ți-a dat drumul ca să elibereze niște secrete oribile.","Хорошо, ты пришёл в себя. Взяв в руки артефакт, который выронил Программист, ты раскрыл страшные тайны.",,"Bra, du är vid medvetande igen. När du tog tag i föremålet som programmeraren tappade släppte du lös några hemska hemligheter.","Güzel, tekrar kendine geldin. Programcı'nın düşürdüğü o eşyayı aldığında, bazı korkunç sırları açığa çıkardın." +What kind of secrets. ,TXT_RPLY0_SCRIPT10_D0_WHATK,〃,,,Jaká tajemství?,Hvilken slags hemmeligheder?,Was für Geheimnisse?,,Kiaj sekretoj?,¿Qué clase de secretos?,,Minkälaisia salaisuuksia?,De quels secrets parlez-vous?,Miféle titkok?,Che tipo di segreti.,その秘密とは。,어떤 비밀인가요?,Wat voor geheimen.,Hva slags hemmeligheter?,Jakich sekretów?,Que tipos de segredos?,,Ce fel de secrete?,Какие тайны?,,Vad för slags hemligheter.,Ne tür sırlar? +"We have no idea where this weapon came from, but we must find out. You have wrested one from the Order, but we must have all five. We have reached the limits of my knowledge. Seek out the Oracle and ask it for help.",TXT_DLG_SCRIPT10_D1516_WEHAV,〃,,,"Nemáme tušení, odkud se tato zbraň vzala, ale musíme to zjistit. Jednu část jsi z rukou Řádu už umanul, ale musíme najít všech pět. Dosáhli jsme hranic mých vědomostí. Vyhledej Věštce a požádej jej o pomoc.","Vi har ingen anelse om, hvor dette våben kommer fra, men vi må finde ud af det. Du har vristet en fra Ordenen, men vi skal have alle fem. Vi har nået grænserne for min viden. Opsøg Oraklet og bed det om hjælp.","Wir haben keine Ahnung, wo diese Waffe herkommt, aber wir müssen es herausfinden. Du hast ein Teil dem Orden entrungen aber wir brauchen alle fünf. Wir haben die Grenzen meines Wissens erreicht. Suche das Orakel und frage es um Hilfe.",,"Ni ne konas la originon de ĉi tiu armilo, sed ni devas malkovri ĝin. Vi jam prenis pecon el La Ordeno kaj ni bezonas la aliajn kvar. Ĝis ĉi tie ĉio, kion mi scias. Serĉu la Orakolon kaj petu lin pri helpo.","No sabemos de dónde habrá salido esta arma, pero hay que averiguarlo. Ya le has quitado una pieza a La Orden y nos estarían faltando las otras cuatro. Hasta ahí todo lo que sé. Busca al Oráculo y pídele ayuda.","No sabemos de dónde habrá salido esta arma, pero hay que averiguarlo. Ya le quitaste una pieza a La Orden y nos estarían faltando las otras cuatro. Hasta ahí todo lo que sé. Busca al Oráculo y pídele ayuda.","Meillä ei ole aavistustakaan tämän aseen alkuperästä, mutta se on selvitettävä. Olet nyt riistänyt Veljeskunnan käsistä yhden, mutta meidän on saatava kaikki viisi. Oma tietämykseni päättyy tähän. Etsi apua Oraakkelilta.","Je n'ai aucune idée d'où vient cette arme, mais il faut que nous le découvrions. Vous en avez arraché une à l'Ordre, mais il faut trouver toutes les cinq. C'est tout ce que je sais pour l'instant. Allez voir l'Oracle et demandez son aide.","Nem tudjuk mi ennek a fegyvernek az eredete, de ki kell derítenünk. Elcsentél egyet a Rendtől, de meg kell szereznünk mind az ötöt. Elértük a tudásom határát. Keresd fel az Orákulumot, és kérdd a segítségét.","Non abbiamo alcuna idea su dove quest'arma provenga, ma dobbiamo scoprirlo. Ne hai sottratto una all'Ordine, ma dobbiamo ottenerle tutte e cinque. E qui abbiamo raggiunto il limite della mia conoscienza. Devi raggiungere l'Oracolo e chiedergli aiuto.","この武器が何処で造られたかは分からないが、 我々はそれを突き止める必要がある様だ。 どうやら全部で5つあり、君はオーダーから 1つ手に入れている。我々の理解を超える存在だ -オラクルを探し何か情報を得なければ。","이 무기가 어디서 왔는지는 모르겠다만, 얼른 찾아내야만 합니다. 그 한 조각을 비롯한 나머지 '다섯' 조각도 필요합니다. 제가 알고 있는 건 이게 다입니다. 오라클이라는 자를 만나서 도움을 요청해보세요.","We hebben geen idee waar dit wapen vandaan komt, maar we moeten erachter komen. Je hebt er een uit de Orde weggehaald, maar we moeten ze alle vijf hebben. We hebben de grenzen van mijn kennis bereikt. Zoek het Orakel op en vraag het om hulp.","Vi aner ikke hvor våpenet kom fra, men vi må finne det ut. Du har vristet ett fra Ordenen, men vi må ha alle fem. Vi har nådd grensen for min kunnskap. Oppsøk oraklet og be det om hjelp.","Nie mamy pojęcia skąd ta broń pochodzi, ale musimy się dowiedzieć. Wyrwałeś jedną z łap Zakonu, ale musimy zdobyć wszystkie pięć. Osiągnęliśmy szczyt tego co wiem. Poszukaj Wyroczni i poproś ją o pomoc.","Não fazemos idéia de onde esta arma veio, mas precisamos descobrir. Você conseguiu roubar um deles da Ordem, mas precisamos de todos os cinco. Já atingimos os limites do meu conhecimento. Procure o Oráculo e peça a ajuda dele.",,"Nu avem nicio idee în legătură cu proveniența armei, dar trebuie să aflăm. Ai luat una de la Ordin, dar avem nevoie de toate 5. Am ajuns la capătul cunoștiințelor mele. Mergi în căutarea Oracolului, și cere-i ajutorul.","Мы понятия не имеем, откуда взялось это оружие, но обязаны выяснить. Ты отбил один фрагмент у Ордена, но нам нужны все пять. Я рассказал тебе всё, что знал. Найди Оракула и попроси его о помощи.",,Bu silahın nereden geldiğini bilmiyoruz ama öğrenmeliyiz. Tarikat'tan bir tane aldınız ama beşini de almalıyız. Bilgimin sınırlarına ulaştık. Kahin'i ara ve ondan yardım iste. -I'm gonna need more supplies.,TXT_RPLY0_SCRIPT10_D1516_IMGON,〃,,,Budu potřebovat zásoby.,Jeg får brug for flere forsyninger.,Ich brauche mehr Ausrüstung.,,Mi bezonos pliajn provizojn.,Voy a necesitar más suministros.,,Tarvitsen lisää varusteita.,Il me faut de l'équipment.,Szükségem lesz még felszerelésre.,Mi serviranno più provviste.,それには補給がもっと必要だ。,물자가 좀 필요할 것 같은데.,Ik zal meer voorraden nodig hebben.,Jeg trenger flere forsyninger.,Będę potrzebować więcej zaopatrzenia.,Vou precisar de mais equipmento.,,O să am nevoie de mai multe provizii.,Мне потребуются ещё припасы.,,Daha fazla malzemeye ihtiyacım olacak. +オラクルを探し何か情報を得なければ。","이 무기가 어디서 왔는지는 모르겠다만, 얼른 찾아내야만 합니다. 그 한 조각을 비롯한 나머지 '다섯' 조각도 필요합니다. 제가 알고 있는 건 이게 다입니다. 오라클이라는 자를 만나서 도움을 요청해보세요.","We hebben geen idee waar dit wapen vandaan komt, maar we moeten erachter komen. Je hebt er een uit de Orde weggehaald, maar we moeten ze alle vijf hebben. We hebben de grenzen van mijn kennis bereikt. Zoek het Orakel op en vraag het om hulp.","Vi aner ikke hvor våpenet kom fra, men vi må finne det ut. Du har vristet ett fra Ordenen, men vi må ha alle fem. Vi har nådd grensen for min kunnskap. Oppsøk oraklet og be det om hjelp.","Nie mamy pojęcia skąd ta broń pochodzi, ale musimy się dowiedzieć. Wyrwałeś jedną z łap Zakonu, ale musimy zdobyć wszystkie pięć. Osiągnęliśmy szczyt tego co wiem. Poszukaj Wyroczni i poproś ją o pomoc.","Não fazemos idéia de onde esta arma veio, mas precisamos descobrir. Você conseguiu roubar um deles da Ordem, mas precisamos de todos os cinco. Já atingimos os limites do meu conhecimento. Procure o Oráculo e peça a ajuda dele.",,"Nu avem nicio idee în legătură cu proveniența armei, dar trebuie să aflăm. Ai luat una de la Ordin, dar avem nevoie de toate 5. Am ajuns la capătul cunoștiințelor mele. Mergi în căutarea Oracolului, și cere-i ajutorul.","Мы понятия не имеем, откуда взялось это оружие, но обязаны выяснить. Ты отбил один фрагмент у Ордена, но нам нужны все пять. Я рассказал тебе всё, что знал. Найди Оракула и попроси его о помощи.",,"Vi har ingen aning om var det här vapnet kom ifrån, men vi måste ta reda på det. Du har vridit en från Orden, men vi måste få alla fem. Vi har nått gränsen för min kunskap. Sök upp Oraklet och be det om hjälp.",Bu silahın nereden geldiğini bilmiyoruz ama öğrenmeliyiz. Tarikat'tan bir tane aldınız ama beşini de almalıyız. Bilgimin sınırlarına ulaştık. Kahin'i ara ve ondan yardım iste. +I'm gonna need more supplies.,TXT_RPLY0_SCRIPT10_D1516_IMGON,〃,,,Budu potřebovat zásoby.,Jeg får brug for flere forsyninger.,Ich brauche mehr Ausrüstung.,,Mi bezonos pliajn provizojn.,Voy a necesitar más suministros.,,Tarvitsen lisää varusteita.,Il me faut de l'équipment.,Szükségem lesz még felszerelésre.,Mi serviranno più provviste.,それには補給がもっと必要だ。,물자가 좀 필요할 것 같은데.,Ik zal meer voorraden nodig hebben.,Jeg trenger flere forsyninger.,Będę potrzebować więcej zaopatrzenia.,Vou precisar de mais equipmento.,,O să am nevoie de mai multe provizii.,Мне потребуются ещё припасы.,,Jag kommer att behöva mer förnödenheter.,Daha fazla malzemeye ihtiyacım olacak. "Here's some gold. Go visit the medic and the weapons trainer and then, move out!",TXT_DLG_SCRIPT10_D3032_HERES,〃,,,"Tady je nějaké zlato. Jdi navštívit zdravotníka a zbraňmistra, a pak odchod!","Her er noget guld. Besøg lægen og våbentræneren, og så af sted!",Hier ist etwas Gold. Geh zum Sanitäter und zum Waffentrainer und dann los!,,"Jen iom da oro. Iru renkonti la kuraciston kaj la armilan trejniston, kaj tiam ekagu!","Aquí tienes algo de oro. Ve a ver al médico y al entrenador de armas y luego, ¡en marcha!",,"Tässä vähän kultaa. Tapaa lääkintämiestä ja asekouluttajaa, ja sen jälkeen lähde matkaan!","Voilà de l'argent. Allez voir le médecin et le maître d'armes, puis partez!","Itt van egy kis arany. Keresd fel a szanitécot és a fegyvermestert, aztán indulás!","Ecco dell'oro. Visita il dottore e l'istruttore d'armi, e poi, è tempo di muoversi!","資金を提供しよう。 そしてメディックと訓練士に会い装備を整えて、 -向かいたまえ!",골드를 좀 받으세요. 의무관이랑 무기 담당관을 찾아뵈시고 이동하시길!,Hier is wat goud. Ga naar de dokter en de wapentrainer en ga dan weg!,"Her er litt gull. Gå til legen og våpentreneren, og så drar vi!","Masz tu trochę złota. Odwiedź medyka i trenera od broni, a potem wykonać!",Pegue este dinheiro. Vá ver o médico e o treinador de armas e depois parta para a missão.,,"Uite niște aur. Vizitează medicul și antrenorul de arme iar apoi, dă-i drumul!","Вот немного золота. Посети медика и инструктора по стрельбе, и выдвигайся!",,İşte biraz altın. Sıhhiyeciyi ve silah eğitmenini ziyaret et ve sonra yola çık! -Right!,TXT_RPLY0_SCRIPT10_D3032_RIGHT,〃,,,Ano!,Så går vi.,Ja.,,Kompreneble!,¡A la orden!,,Selvä!,Bien!,Igenis!,Sarà fatto!,わかった!,네!,Juist!,Skal bli!,Dobrze!,Certo!,,Într-adevăr!,Есть!,,Tamamdır! -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D4548_FIGHT,〃,,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Batalu pro la Fronto kaj liberigota lando. Ekagu.,Lucha por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Kjemp for fronten og friheten. Av sted med dere.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Выдвигайся.,,Cephe ve özgürlük için savaşın. Dışarı çıkın. -"What prompts your return? Are you hurt? There's no time to lose, continue with your mission. Complete the Sigil.",TXT_DLG_SCRIPT10_D6064_WHATP,,,,"Co přimělo tvůj návrát? Jsi zraněný? Není času nazbyt, pokračuj ve své misi. Dokonči Pečeť.","Hvad får dig til at vende tilbage? Er du såret? Der er ingen tid at spilde, fortsæt med din mission. Færdiggør sigilet.","Warum kommst du zurück? Bist du verletzt? Wir haben keine Zeit zu verlieren, du musst deine Mission fortsetzen. Vervollständige das Sigil.",,,"¿A qué se debe tu retorno? ¿Estás herido? No hay tiempo que perder, continua con tu misión. Completa el Emblema.",,Miksi olet palannut? Oletko loukkaantunut? Aikaa ei ole menetettävänä; jatka tehtävääsi. Kokoa Sinetti.,"Qu'est ce qui vous amène? Vous avez mal? Il n'y a pas de temps à perdre. Continuez votre mission, complétez le Sigil.","Hogyhogy ilyen hamar visszatértél? Megsebesültél? Nem vesztegethetjük az időt, folytasd a küldetésed. Fejezd be a pecsétet.","Come mai già di ritorno? Sei ferito? Non c'è tempo da perdere, continua la tua missione. Completa il Sigillo.","何が帰還を促した?怪我をしたのか? +向かいたまえ!",골드를 좀 받으세요. 의무관이랑 무기 담당관을 찾아뵈시고 이동하시길!,Hier is wat goud. Ga naar de dokter en de wapentrainer en ga dan weg!,"Her er litt gull. Gå til legen og våpentreneren, og så drar vi!","Masz tu trochę złota. Odwiedź medyka i trenera od broni, a potem wykonać!",Pegue este dinheiro. Vá ver o médico e o treinador de armas e depois parta para a missão.,,"Uite niște aur. Vizitează medicul și antrenorul de arme iar apoi, dă-i drumul!","Вот немного золота. Посети медика и инструктора по стрельбе, и выдвигайся!",,"Här är lite guld. Gå och besök läkaren och vapentränaren och sedan, sätt fart!",İşte biraz altın. Sıhhiyeciyi ve silah eğitmenini ziyaret et ve sonra yola çık! +Right!,TXT_RPLY0_SCRIPT10_D3032_RIGHT,〃,,,Ano!,Så går vi.,Ja.,,Kompreneble!,¡A la orden!,,Selvä!,Bien!,Igenis!,Sarà fatto!,わかった!,네!,Juist!,Skal bli!,Dobrze!,Certo!,,Într-adevăr!,Есть!,,Okej!,Tamamdır! +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D4548_FIGHT,〃,,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Bataladu pro la Fronto kaj libereco. Ekagu.,Pelea por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Kjemp for fronten og friheten. Av sted med dere.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Выдвигайся.,,Kämpa för fronten och friheten. Gå ut.,Cephe ve özgürlük için savaşın. Dışarı çıkın. +"What prompts your return? Are you hurt? There's no time to lose, continue with your mission. Complete the Sigil.",TXT_DLG_SCRIPT10_D6064_WHATP,MAP10: Macil → The Oracle said to kill him,,,"Co přimělo tvůj návrát? Jsi zraněný? Není času nazbyt, pokračuj ve své misi. Dokonči Pečeť.","Hvad får dig til at vende tilbage? Er du såret? Der er ingen tid at spilde, fortsæt med din mission. Færdiggør sigilet.","Warum kommst du zurück? Bist du verletzt? Wir haben keine Zeit zu verlieren, du musst deine Mission fortsetzen. Vervollständige das Sigil.",,"Kial vi revenis? Ĉu vi estas vundita? Ne estas perdinda tempo, reiru al via komisio: kompletigu la Sigelon.","¿A qué has vuelto?, ¿estás herido? No hay tiempo que perder, continúa con la misión: completa el Emblema.","¿A qué volviste?, ¿estás herido? No hay tiempo que perder, continúa con la misión: completa el Emblema.",Miksi olet palannut? Oletko loukkaantunut? Aikaa ei ole menetettävänä; jatka tehtävääsi. Kokoa Sinetti.,"Qu'est ce qui vous amène? Vous avez mal? Il n'y a pas de temps à perdre. Continuez votre mission, complétez le Sigil.","Hogyhogy ilyen hamar visszatértél? Megsebesültél? Nem vesztegethetjük az időt, folytasd a küldetésed. Fejezd be a pecsétet.","Come mai già di ritorno? Sei ferito? Non c'è tempo da perdere, continua la tua missione. Completa il Sigillo.","何が帰還を促した?怪我をしたのか? 屈している場合ではない。 -シジルを完成させる使命を果たすんだ。",돌아왔습니까? 상처라도 입었나요? 시간이 없으니 임무를 속행하고 시질 조각을 마저 모으시길 바랍니다.,"Wat zet je ertoe aan om terug te keren? Ben je gewond? Er is geen tijd te verliezen, ga verder met je missie. Voltooi de Sigil.","Hvorfor kommer du tilbake? Er du såret? Det er ingen tid å miste, fortsett med oppdraget ditt. Fullfør sigillet.","Co skłoniło cię do powrotu? Jesteś ranny? Nie ma czasu do stracenia, kontynuuj swą misję. Uzupełnij Pieczęć.",O que fez você retornar? Você está ferido? Não há tempo a perder. Continue com a sua missão. Complete o Sigilo.,,"Ce te aduce înapoi? Nu avem timp de pierdut, continuă-ți misiunea. Asamblează Sigiliul.",С какой целью ты вернулся? Ты ранен? Нельзя терять ни минуты. Продолжай выполнение задания. Собери Печать!,,"Geri dönmene ne sebep oldu? Yaralandın mı? Kaybedecek zaman yok, görevinize devam edin. Sigil'i tamamla." -The Oracle says you must die!,TXT_RPLY0_SCRIPT10_D6064_THEOR,,,,"Věštec říká, že musíš zemřít!","Oraklet siger, at du skal dø!","Das Orakel sagt, du musst sterben.",,,¡El Oráculo dice que debes morir!,,"Oraakkeli sanoo, että sinun pitää kuoleman!",L'Oracle dit que vous devez mourir!,"Az Orákulum azt üzeni, hogy meg kell halnod!",L'Oracolo mi ha detto che devi morire!,オラクルは死ぬべきだと言った!,오라클의 이름으로 넌 죽어야 해!,Het Orakel zegt dat je moet sterven!,Oraklet sier at du må dø!,Wyrocznia mówi że musisz zginąć!,O Oráculo diz que você deve morrer!,,Oracolul spune că trebuie să mori!,"Оракул сказал, что я должен убить тебя!",,Kahin ölmen gerektiğini söylüyor! -I have sworn myself to freedom. It is the Oracle who holds the third piece. There's your traitor.,TXT_DLG_SCRIPT10_D7580_IHAVE,,,,"Já jsem zapřísáhnut svobodě! Věštec je ten, kdo má u sebe třetí díl. On je ten zrádce.","Jeg har svoret mig selv til frihed. Det er Oraklet, der har den tredje del. Der er din forræder.",Ich habe mich der Freiheit verpflichtet. Das Orakel besitzt das dritte Teilstück. Dort ist dein Verräter.,,,He hecho un juramento por la libertad. Es el Oráculo quien tiene la tercera pieza. Ahí tienes a tu traidor.,,Olen vannonut itseni vapauteen. Kolmas osanen on Oraakkelin hallussa. Siinä on petturisi.,J'ai juré donner ma vie à la liberté. C'est l'Oracle qui porte la troisième pièce. Voilà votre traître.,Felesküdtem a szabadságra. Az Orákulumnál van a harmadik darab. Ő lesz az árulód.,Io ho dedicato tutto me stesso alla libertà. È l'Oracolo che tiene il terzo pezzo. Ecco chi è il traditore.,"私は皆の自由を誓った。 +シジルを完成させる使命を果たすんだ。",돌아왔습니까? 상처라도 입었나요? 시간이 없으니 임무를 속행하고 시질 조각을 마저 모으시길 바랍니다.,"Wat zet je ertoe aan om terug te keren? Ben je gewond? Er is geen tijd te verliezen, ga verder met je missie. Voltooi de Sigil.","Hvorfor kommer du tilbake? Er du såret? Det er ingen tid å miste, fortsett med oppdraget ditt. Fullfør sigillet.","Co skłoniło cię do powrotu? Jesteś ranny? Nie ma czasu do stracenia, kontynuuj swą misję. Uzupełnij Pieczęć.",O que fez você retornar? Você está ferido? Não há tempo a perder. Continue com a sua missão. Complete o Sigilo.,,"Ce te aduce înapoi? Nu avem timp de pierdut, continuă-ți misiunea. Asamblează Sigiliul.",С какой целью ты вернулся? Ты ранен? Нельзя терять ни минуты. Продолжай выполнение задания. Собери Печать!,,"Vad föranleder din återkomst? Är du skadad? Det finns ingen tid att förlora, fortsätt med ditt uppdrag. Slutför Sigillet.","Geri dönmene ne sebep oldu? Yaralandın mı? Kaybedecek zaman yok, görevinize devam edin. Sigil'i tamamla." +The Oracle says you must die!,TXT_RPLY0_SCRIPT10_D6064_THEOR,〃,,,"Věštec říká, že musíš zemřít!","Oraklet siger, at du skal dø!","Das Orakel sagt, du musst sterben.",,"La Orakolo diras, ke vi devas morti!",¡El Oráculo dice que debes morir!,,"Oraakkeli sanoo, että sinun pitää kuoleman!",L'Oracle dit que vous devez mourir!,"Az Orákulum azt üzeni, hogy meg kell halnod!",L'Oracolo mi ha detto che devi morire!,オラクルは死ぬべきだと言った!,오라클의 이름으로 넌 죽어야 해!,Het Orakel zegt dat je moet sterven!,Oraklet sier at du må dø!,Wyrocznia mówi że musisz zginąć!,O Oráculo diz que você deve morrer!,,Oracolul spune că trebuie să mori!,"Оракул сказал, что я должен убить тебя!",,Oraklet säger att du måste dö!,Kahin ölmen gerektiğini söylüyor! +I have sworn myself to freedom. It is the Oracle who holds the third piece. There's your traitor.,TXT_DLG_SCRIPT10_D7580_IHAVE,〃,,,"Já jsem zapřísáhnut svobodě! Věštec je ten, kdo má u sebe třetí díl. On je ten zrádce.","Jeg har svoret mig selv til frihed. Det er Oraklet, der har den tredje del. Der er din forræder.",Ich habe mich der Freiheit verpflichtet. Das Orakel besitzt das dritte Teilstück. Dort ist dein Verräter.,,"Mi faris ĵuron de libereco. La Orakolo estas tiu, kiu havas la trian pecon: tie estas via perfidulo.",Hice un juramento por la libertad. Es el Oráculo quien tiene la tercera pieza: ahí está tu traidor.,,Olen vannonut itseni vapauteen. Kolmas osanen on Oraakkelin hallussa. Siinä on petturisi.,J'ai juré donner ma vie à la liberté. C'est l'Oracle qui porte la troisième pièce. Voilà votre traître.,Felesküdtem a szabadságra. Az Orákulumnál van a harmadik darab. Ő lesz az árulód.,Io ho dedicato tutto me stesso alla libertà. È l'Oracolo che tiene il terzo pezzo. Ecco chi è il traditore.,"私は皆の自由を誓った。 三つ目の部品を持つのはオラクルだ。 -君は裏切るつもりか。",전 자유를 지키겠다고 맹세했습니다. 오라클이 세 번째 조각을 가지고 있단 말입니다. 그자가 바로 배신자입니다!,Ik heb mezelf gezworen tot vrijheid. Het is het Orakel dat het derde deel vasthoudt. Daar is je verrader.,Jeg har sverget meg til frihet. Det er oraklet som har den tredje biten. Der er forræderen din.,Przysiągłem sobie wolność. To Wyrocznia ma trzeci fragment. Masz tu swego zdrajcę.,Eu fiz um juramento à liberdade. É o Oráculo que possui a terceira peça. Ele é o seu traidor.,,Am jurat pentru libertate. Oracolul deține a treia piesă. Iată trădătorul.,Я присягнул борьбе за свободу. Третий фрагмент хранится у Оракула. Он и есть предатель.,,Özgürlük için yemin ettim. Üçüncü parça Kahin'de. İşte hainin. -The Oracle will die then!,TXT_RPLY0_SCRIPT10_D7580_THEOR,,,,Pak Věštec zemře!,Så dør Oraklet!,Dann wird das Orakel sterben.,,,¡El Oráculo morirá entonces!,,Siinä tapauksessa Oraakkeli kuolkoon!,L'Oracle va donc mourir!,Akkor meghal az Orákulum!,E allora l'Oracolo morirà!,オラクルは後で仕留める!,그럼 오라클을 죽여야겠군.,Het Orakel zal dan sterven!,Da skal oraklet dø!,A więc to Wyrocznia zginie!,O Oráculo morrerá então!,,Oracolul va pieri atunci!,Тогда умрёт Оракул!,,O zaman Kahin ölecek! -I think you're the traitor!,TXT_RPLY1_SCRIPT10_D7580_ITHIN,,,,"Myslím, že ty jsi ten zrádce!","Jeg tror, du er forræderen!","Ich denke, du bist der Verräter.",,,¡Creo que tú eres el traidor!,,"Luulen, että petturi olet sinä!","Je pense que c'est vous, le traître!",Azt hiszem inkább te vagy az áruló!,Io penso che sia tu il traditore!,裏切り者はお前の方だ!,배신자는 바로 당신이야!,Ik denk dat jij de verrader bent!,Jeg tror du er forræderen!,Według mnie to ty jesteś zdrajcą!,Eu acho que você que é o traidor!,,Eu cred că tu ești trădătorul!,"Я думаю, что предатель — это ты!",,Bence hain sensin! -Spirit of the One God avenge me and turn this world into dust.,TXT_DLG_SCRIPT10_D9096_SPIRI,,,,Duše Jednoho boha nechť mě pomstí a promění tento svět v prach!,Den ene Guds ånd hævner mig og gør denne verden til støv.,"Geist des einen Gottes, räche mich und verwandle diese Welt zu Staub.",,,Espíritu del Dios Único véngame y convierte este mundo en polvo.,,Yhden Ainoan Jumalan Henki kostakoon puolestani ja muuttakoon tämän maailman tuhaksi.,Que le Saint Esprit du Seul Dieu me venge et brûle ce monde jusqu'au cendres.,"Az egy igaz isten lelke bosszúljon meg, és zúzza porrá ezt a világot.","Spirito dell'Unico Dio, vendicami e trasforma questo mondo in cenere!","唯一神の魂が私を討てば -この世界を塵に変えるだろう。","유일신의 혼이여, 이 세계를 잿더미로 만듦으로써 저를 위해 복수하심이!!",De geest van de Ene God wreekt me en maakt deze wereld tot stof.,"Ånd av den ene Gud, hevn meg og gjør denne verden til støv.",Duchu Jedynego Boga pomścij mnie i zrównaj ten świat z ziemią.,"Ó, Espírito do Deus Único. Vingue-me e transforme este mundo em pó.",,Spiritul Adevăratului Zeu să mă răzbune și să facă lumea asta cenușă.,Дух Единого Бога отомстит за меня и обратит этот мир в прах.,,Tek Tanrı'nın Ruhu intikamımı al ve bu dünyayı toza çevir. -You have made the right decision. Its clear that the Oracle is controlled by whatever evil is driving the Order. Return to it and claim the third piece of the Sigil.,TXT_DLG_SCRIPT10_D10612_YOUHA,,,,"Učinil jsi správné rozhodnutí. Je zřejmé, že Věštec je ovládán tím zlem, které vede Řád. Vrať se k němu a přivlastni si třetí díl Pečetě.","Du har truffet den rigtige beslutning. Det er tydeligt, at Oraklet er kontrolleret af den ondskab, der driver ordenen. Vend tilbage til det og hæv den tredje del af sigilet.","Du hast die richtige Wahl getroffen. Es ist offensichtlich, dass das Orakel von demselben Übel kontrolliert wird, das den Orden antreibt. Kehre zu ihm zurück und hol dir das dritte Teilstück.",,,Has tomado la decisión correcta. Está claro que el Oráculo está siendo controlado por el mal que está detras de la Orden. Vuelve ante él y reclama la tercera pieza del Emblema.,,"Olet tehnyt oikean päätöksen. Mikä tahansa paha vallitseekaan Veljeskuntaa, selvästi myös hallitsee Oraakkelia. Palaa sen luokse ja lunasta Sinetti.",Vous avez fait le bon choix. Il est clair que l'Oracle est contrôlé par le mal qui est derrière l'Ordre. Retournez le voir et récupérez la troisième pièce du Sigil.,"A megfelelő döntést hoztad. Biztos, hogy az Orákulumot is az a gonosz hajtja, ami a Rendet. Térj vissza hozzá, és követeld tőle a Pecsét harmadik darabját.",Hai fatto la scelta giusta. È chiaro che l'Oracolo è controllato dallo stesso male che guida l'Ordine. Ritorna dall'Oracolo e reclama il terzo pezzo del Sigillo.,"君は正しい決断をした。 +君は裏切るつもりか。",전 자유를 지키겠다고 맹세했습니다. 오라클이 세 번째 조각을 가지고 있단 말입니다. 그자가 바로 배신자입니다!,Ik heb mezelf gezworen tot vrijheid. Het is het Orakel dat het derde deel vasthoudt. Daar is je verrader.,Jeg har sverget meg til frihet. Det er oraklet som har den tredje biten. Der er forræderen din.,Przysiągłem sobie wolność. To Wyrocznia ma trzeci fragment. Masz tu swego zdrajcę.,Eu fiz um juramento à liberdade. É o Oráculo que possui a terceira peça. Ele é o seu traidor.,,Am jurat pentru libertate. Oracolul deține a treia piesă. Iată trădătorul.,Я присягнул борьбе за свободу. Третий фрагмент хранится у Оракула. Он и есть предатель.,,Jag har svurit på frihet. Det är Oraklet som har den tredje delen. Där är din förrädare.,Özgürlük için yemin ettim. Üçüncü parça Kahin'de. İşte hainin. +The Oracle will die then!,TXT_RPLY0_SCRIPT10_D7580_THEOR,〃,,,Pak Věštec zemře!,Så dør Oraklet!,Dann wird das Orakel sterben.,,Tiuokaze la Orakolo mortos!,"¡El Oráculo morirá, entonces!","¡El Oráculo se muere, entonces!",Siinä tapauksessa Oraakkeli kuolkoon!,L'Oracle va donc mourir!,Akkor meghal az Orákulum!,E allora l'Oracolo morirà!,オラクルは後で仕留める!,그럼 오라클을 죽여야겠군.,Het Orakel zal dan sterven!,Da skal oraklet dø!,A więc to Wyrocznia zginie!,O Oráculo morrerá então!,,Oracolul va pieri atunci!,Тогда умрёт Оракул!,,Oraklet kommer att dö då!,O zaman Kahin ölecek! +I think you're the traitor!,TXT_RPLY1_SCRIPT10_D7580_ITHIN,〃,,,"Myslím, že ty jsi ten zrádce!","Jeg tror, du er forræderen!","Ich denke, du bist der Verräter.",,Eble vi estas la perfidulo!,¡Creo que tú eres el traidor!,,"Luulen, että petturi olet sinä!","Je pense que c'est vous, le traître!",Azt hiszem inkább te vagy az áruló!,Io penso che sia tu il traditore!,裏切り者はお前の方だ!,배신자는 바로 당신이야!,Ik denk dat jij de verrader bent!,Jeg tror du er forræderen!,Według mnie to ty jesteś zdrajcą!,Eu acho que você que é o traidor!,,Eu cred că tu ești trădătorul!,"Я думаю, что предатель — это ты!",,Jag tror att du är förrädaren!,Bence hain sensin! +Spirit of the One God avenge me and turn this world into dust.,TXT_DLG_SCRIPT10_D9096_SPIRI,MAP10: Macil → You chose to kill Macil,,,Duše Jednoho boha nechť mě pomstí a promění tento svět v prach!,Den ene Guds ånd hævner mig og gør denne verden til støv.,"Geist des einen Gottes, räche mich und verwandle diese Welt zu Staub.",,"Spirito de la Vera Dio, venĝu min kaj polvigu ĉi tiun mondon.","Espíritu del Dios Único, véngame y convierte este mundo en polvo.",,Yhden Ainoan Jumalan Henki kostakoon puolestani ja muuttakoon tämän maailman tuhaksi.,Que le Saint Esprit du Seul Dieu me venge et brûle ce monde jusqu'au cendres.,"Az egy igaz isten lelke bosszúljon meg, és zúzza porrá ezt a világot.","Spirito dell'Unico Dio, vendicami e trasforma questo mondo in cenere!","唯一神の魂が私を討てば +この世界を塵に変えるだろう。","유일신의 혼이여, 이 세계를 잿더미로 만듦으로써 저를 위해 복수하심이!!",De geest van de Ene God wreekt me en maakt deze wereld tot stof.,"Ånd av den ene Gud, hevn meg og gjør denne verden til støv.",Duchu Jedynego Boga pomścij mnie i zrównaj ten świat z ziemią.,"Ó, Espírito do Deus Único. Vingue-me e transforme este mundo em pó.",,Spiritul Adevăratului Zeu să mă răzbune și să facă lumea asta cenușă.,Дух Единого Бога отомстит за меня и обратит этот мир в прах.,,Den ende gudens ande hämnas mig och förvandlar den här världen till stoft.,Tek Tanrı'nın Ruhu intikamımı al ve bu dünyayı toza çevir. +You have made the right decision. Its clear that the Oracle is controlled by whatever evil is driving the Order. Return to it and claim the third piece of the Sigil.,TXT_DLG_SCRIPT10_D10612_YOUHA,MAP10: Macil → You chose to kill the Oracle,,,"Učinil jsi správné rozhodnutí. Je zřejmé, že Věštec je ovládán tím zlem, které vede Řád. Vrať se k němu a přivlastni si třetí díl Pečetě.","Du har truffet den rigtige beslutning. Det er tydeligt, at Oraklet er kontrolleret af den ondskab, der driver ordenen. Vend tilbage til det og hæv den tredje del af sigilet.","Du hast die richtige Wahl getroffen. Es ist offensichtlich, dass das Orakel von demselben Übel kontrolliert wird, das den Orden antreibt. Kehre zu ihm zurück und hol dir das dritte Teilstück.",,"Vi prenis la ĝustan decidon. Estas evidente, ke la Orakolo estas regata per ia malbono de La Ordeno. Reiru al ĝi kaj akiru la trian pecon de la Sigelo.",Has tomado la decisión correcta. Está claro que el Oráculo está siendo controlado por el mal que está detrás de La Orden. Vuelve ante él y reclama la tercera pieza del Emblema.,Tomaste la decisión correcta. Está claro que el Oráculo está siendo controlado por el mal que está detrás de La Orden. Vuelve ante él y reclama la tercera pieza del Emblema.,"Olet tehnyt oikean päätöksen. Mikä tahansa paha vallitseekaan Veljeskuntaa, selvästi myös hallitsee Oraakkelia. Palaa sen luokse ja lunasta Sinetti.",Vous avez fait le bon choix. Il est clair que l'Oracle est contrôlé par le mal qui est derrière l'Ordre. Retournez le voir et récupérez la troisième pièce du Sigil.,"A megfelelő döntést hoztad. Biztos, hogy az Orákulumot is az a gonosz hajtja, ami a Rendet. Térj vissza hozzá, és követeld tőle a Pecsét harmadik darabját.",Hai fatto la scelta giusta. È chiaro che l'Oracolo è controllato dallo stesso male che guida l'Ordine. Ritorna dall'Oracolo e reclama il terzo pezzo del Sigillo.,"君は正しい決断をした。 オラクルがオーダーに悪しき支配をしているのは 明白だ。戻って三番目のシジルを手に入れろ。","좋은 선택입니다. 아무래도 오더가 이끄는 악에서 오라클을 조종하는 것이 명백해졌으니, 녀석을 찾아가 시질의 세 번째 조각을 회수하세요. - \cy어서 가자, 나의 영웅. 그 못생긴 녀석에게 본때를 보여주자고.",Je hebt de juiste keuze gemaakt. Het is duidelijk dat het Orakel wordt beheerst door het kwaad dat de Orde drijft. Keer ernaar terug en claim het derde deel van de Sigil.,Du har tatt den rette avgjørelsen. Det er tydelig at oraklet styres av den ondskapen som driver ordenen. Vend tilbake til det og gjør krav på den tredje delen av sigillet.,"Postąpiłeś słusznie. To oczywiste, że Wyrocznia jest kontrolowana przez to zło które rządzi Zakonem. Wróć tam i odbierz jej trzeci fragment Pieczęci.",Você fez a decisão certa. Está claro que o Oráculo está sendo controlado por alguma força maligna por trás da Ordem. Volte para lá e pegue a terceira peça do Sigilo.,,Ai făcut alegerea corectă. E limpede că Oracolul e controlat de orice rău conduce și Ordinul. Întoarce-te la el și pune mâna pe cea de-a treia piesă a Sigiliului.,"Ты сделал правильный выбор. Ясно, что Оракулом управляет то же самое зло, что стоит за Орденом. Вернись к Оракулу и потребуй отдать тебе третий фрагмент Печати!",,"Doğru kararı verdin. Kahin'in, Düzen'i yönlendiren şeytan tarafından kontrol edildiği çok açık. Ona dön ve Sigil'in üçüncü parçasını al." -"There seems no end to the horror we face. We have found out that the Order is not killing our people. It is transforming them, into bio-mechanical soldiers. Find the facility where this is being done and close it, permanently.",TXT_DLG_SCRIPT10_D12128_THERE,,,,"Zdá se, že zlo, kterému čelíme, nemá konce. Zjistili jsme, že Řád nezabíjí naše lidi, ale přeměňuje je na biomechanické vojáky. Najdi továrnu, kde se tohle děje, a zavři ji, natrvalo.","Der synes ikke at være nogen ende på den rædsel, vi står over for. Vi har fundet ud af, at ordenen ikke dræber vores folk. Den forvandler dem til biomekaniske soldater. Find det anlæg, hvor dette sker, og luk det for altid.","Der Horror, dem wir ausgesetzt sind, scheint kein Ende zu nehmen. Wir haben herausgefunden, dass der Orden unsere Leute nicht tötet, sondern sie transformiert - int biomechanische Soldaten.Finde die Einrichtung, wo dies passiert und schließe sie - endgültig.",,,"Parece que no hay fin para el horror al que nos enfrentamos. Hemos descubierto que la Orden no solo mata a nuestra gente. La está transformando, en soldados bio-mecánicos. Encuentra la instalación donde esto se hace y clausúrala, permanentemente.",,"Meitä kohdanneelle kauhulle ei näytä olevan loppua. Olemme saaneet selville, että Veljeskunta ei tapa meidän omiamme, vaan muuntelee heitä biomekaanisiksi sotilaiksi. Etsi laitos, jossa tätä tehdään, ja lakkauta se, pysyvästi.","Il semble qu'il n'y ait pas de fin aux horreurs auxquelles nous devons faire face. Nous venons de découvrir que l'Ordre n'exécute pas notre peuple, il le transforme en soldats biomécaniques. Trouvez l'usine qui gère ce processus et fermez la pour toujours.","Úgy néz ki, már soha nem lesz vége ennek a horrornak. Mint kiderült, a Rend nem megöli az embereinket, hanem bio-mechanikus robotokká alakítják át. Keresd meg a létesítményt, ahol ez folyik, és azonnal zárdd be.","Sembra che non ci sia limite agli orrori che affrontiamo. Abbiamo scoperto che l'Ordine non solo uccide la nostra gente, ma li trasforma anche in soldati bio-meccanici. Devi trovare lo stabilimento dove questo sta avvenendo e chiuderlo, permanentemente.","どうやら我々の直面する恐怖は + \cy어서 가자, 나의 영웅. 그 못생긴 녀석에게 본때를 보여주자고.",Je hebt de juiste keuze gemaakt. Het is duidelijk dat het Orakel wordt beheerst door het kwaad dat de Orde drijft. Keer ernaar terug en claim het derde deel van de Sigil.,Du har tatt den rette avgjørelsen. Det er tydelig at oraklet styres av den ondskapen som driver ordenen. Vend tilbake til det og gjør krav på den tredje delen av sigillet.,"Postąpiłeś słusznie. To oczywiste, że Wyrocznia jest kontrolowana przez to zło które rządzi Zakonem. Wróć tam i odbierz jej trzeci fragment Pieczęci.",Você fez a decisão certa. Está claro que o Oráculo está sendo controlado por alguma força maligna por trás da Ordem. Volte para lá e pegue a terceira peça do Sigilo.,,Ai făcut alegerea corectă. E limpede că Oracolul e controlat de orice rău conduce și Ordinul. Întoarce-te la el și pune mâna pe cea de-a treia piesă a Sigiliului.,"Ты сделал правильный выбор. Ясно, что Оракулом управляет то же самое зло, что стоит за Орденом. Вернись к Оракулу и потребуй отдать тебе третий фрагмент Печати!",,Du har fattat rätt beslut. Det är uppenbart att Oraklet kontrolleras av den ondska som driver Orden. Återvänd till det och kräv den tredje delen av Sigillet.,"Doğru kararı verdin. Kahin'in, Düzen'i yönlendiren şeytan tarafından kontrol edildiği çok açık. Ona dön ve Sigil'in üçüncü parçasını al." +"There seems no end to the horror we face. We have found out that the Order is not killing our people. It is transforming them, into bio-mechanical soldiers. Find the facility where this is being done and close it, permanently.",TXT_DLG_SCRIPT10_D12128_THERE,MAP10: Macil → After killing the Oracle,,,"Zdá se, že zlo, kterému čelíme, nemá konce. Zjistili jsme, že Řád nezabíjí naše lidi, ale přeměňuje je na biomechanické vojáky. Najdi továrnu, kde se tohle děje, a zavři ji, natrvalo.","Der synes ikke at være nogen ende på den rædsel, vi står over for. Vi har fundet ud af, at ordenen ikke dræber vores folk. Den forvandler dem til biomekaniske soldater. Find det anlæg, hvor dette sker, og luk det for altid.","Der Horror, dem wir ausgesetzt sind, scheint kein Ende zu nehmen. Wir haben herausgefunden, dass der Orden unsere Leute nicht tötet, sondern sie transformiert - int biomechanische Soldaten.Finde die Einrichtung, wo dies passiert und schließe sie - endgültig.",,"Ŝajnas, ke la teruraĵo, kiun ni alfrontas, estas senlima. Ni malkovris, ke La Ordeno ne nur mortigas niajn homojn: ĝi transformas ilin en biomekanikajn soldatojn. Trovu la instalaĵon, kie tio okazas, kaj fermu ĝin por ĉiam.","Parece que no hay fin para el horror al que nos enfrentamos. Hemos descubierto que La Orden no solo mata a nuestra gente, sino que la está transformando en soldados biomecánicos. Encuentra la instalación donde hacen eso y clausúrala permanentemente.","Parece que no hay fin para el horror al que nos enfrentamos. Descubrimos que La Orden no solo mata a nuestra gente, sino que la está transformando en soldados biomecánicos. Encuentra la instalación donde hacen eso y clausúrala permanentemente.","Meitä kohdanneelle kauhulle ei näytä olevan loppua. Olemme saaneet selville, että Veljeskunta ei tapa meidän omiamme, vaan muuntelee heitä biomekaanisiksi sotilaiksi. Etsi laitos, jossa tätä tehdään, ja lakkauta se, pysyvästi.","Il semble qu'il n'y ait pas de fin aux horreurs auxquelles nous devons faire face. Nous venons de découvrir que l'Ordre n'exécute pas notre peuple, il le transforme en soldats biomécaniques. Trouvez l'usine qui gère ce processus et fermez la pour toujours.","Úgy néz ki, már soha nem lesz vége ennek a horrornak. Mint kiderült, a Rend nem megöli az embereinket, hanem bio-mechanikus robotokká alakítják át. Keresd meg a létesítményt, ahol ez folyik, és azonnal zárdd be.","Sembra che non ci sia limite agli orrori che affrontiamo. Abbiamo scoperto che l'Ordine non solo uccide la nostra gente, ma li trasforma anche in soldati bio-meccanici. Devi trovare lo stabilimento dove questo sta avvenendo e chiuderlo, permanentemente.","どうやら我々の直面する恐怖は まだ終わらない様だ。オーダーが民を無意味に 殺害しているだけではなく、サイボーグ兵へ改造 していることが解かった。その施設を探し出し 機能を停止させるのだ。永久的に。 ","우리가 마주하는 공포의 끝이 없는 것 같군요... 최근 오더가 우리를 학살하는 게 아닌 일종의 강화 인간으로 개조시키고 있었던 것이라고 소식을 들었습니다. 개조가 시행되고 있는 시설을 찾아가서 그곳을 영구적으로 정지시키세요. - \cy인간개조? 음, 이거 때문에 녀석들이 끊임없이 나오는 거였어! 녀석들 성질 더러운 것도 그렇고.","Er lijkt geen einde te komen aan de verschrikking waar we voor staan. We hebben ontdekt dat de Orde onze mensen niet doodt. Het transformeert hen, in bio-mechanische soldaten. Zoek de faciliteit waar dit gebeurt en sluit deze permanent.","Det ser ikke ut til å være noen ende på skrekken vi står overfor. Vi har funnet ut at Ordenen ikke dreper folket vårt. Den forvandler dem til biomekaniske soldater. Finn anlegget der dette gjøres og steng det, permanent.","Wygląda na to, że naszym koszmarom nie ma końca. Dowiedzieliśmy się, że Zakon nie zabija naszych ludzi. Tylko zmienia ich w biomechanicznych żołnierzy. Znajdź ośrodek, w którym to robią i zamknij go na dobre.","Parece que os horrores que enfrentamos não têm fim. Descobrimos que a Ordem não está matando o nosso pessoal. Está os transformando em soldados biomecânicos. Ache a instalação onde isso é feito e feche-a, de uma vez por todas.",,"Pare să nu existe limite pentru răul pe care îl înfruntăm. Îi transformă, în soldați bio-mecanici. Găsește fabrica unde se întâmplă asta și închide-o, permanent.","Иногда кажется, что эти ужасы никогда не закончатся. Мы узнали, что Орден не убивает наших людей. Он перерабатывает их в биомеханических солдат. Найди фабрику, где происходит это, и закрой её раз и навсегда!",,Karşılaştığımız dehşetin sonu yok gibi görünüyor. Tarikat'ın insanlarımızı öldürmediğini öğrendik. Onları biyo-mekanik askerlere dönüştürüyor. Bunun yapıldığı tesisi bulun ve kalıcı olarak kapatın. -Where is this located?,TXT_RPLY0_SCRIPT10_D12128_WHERE,,,,Kde ji najdu?,Hvor er det placeret?,Wo finde ich sie?,,,¿Dónde se encuentra?,,Missä se sijaitsee?,Où se trouve-elle?,Hol van ez?,Dove si trova?,手掛かりは何処にある?,이 장소는 어디에 있죠?,Waar bevindt deze faciliteit zich?,Hvor ligger det?,Gdzie się znajduje?,Onde se encontra?,,Unde este localizată?,Где она находится?,,Burası nerede? -"One of our captains, Richter, is waiting for you by the waterfall in the commons. He has seen the facility and can guide you inside. Stop this atrocity, now.",TXT_DLG_SCRIPT10_D13644_ONEOF,,,,"Jeden z našich kapitánů, Richter, na tebe čeká u vodopádů na návsi. Továrnu už viděl a může ti poradit, jak dovnitř. Zastav tuhle ohavnost, ihned.","En af vores kaptajner, Richter, venter på dig ved vandfaldet i fællesrummet. Han har set anlægget og kan guide dig indenfor. Stop denne grusomhed, nu.","Einer unserer Anführer, Rickter warted auf dich, am Wasserfall bei der Mensa. Er hat es gesehen und kann dich dort hinführen. Stope dieses Gräuel - sofort.",,,"Uno de nuestros capitanes, Richter, está esperándote junto a la cascada en los comunes. Ha visto la instalación y puede guiarte dentro. Detén esta atrocidad, ahora.",,"Richter, yksi kapteeneistamme, odottaa sinua messissä vesiputouksen äärellä. Hän on nähnyt laitoksen ja voi opastaa sinut sisälle. Lopeta tämä kauhistus, heti paikalla.","Un de nos capitaines, Richter, vous attend près de la cascade dans le réfectoire. Il a vu l'usine et peut vous guider jusqu'a l'intérieur. Arrêtez cette atrocité maintenant.","Richter - az egyik kapitányunk - a vízesés melletti étkezdénél fog várni rád. Ő látta ezt a létesítményt, és be tud vinni. Állítsd meg ezt a borzalmat azonnal.","Uno dei nostri capitani, Richter, ti sta aspettando vicino alla cascata nei comuni. Lui ha visto la fabbrica e ti può guidare dentro. Devi fermare quest'atrocità al più presto.","キャプテンの一人、リヒターが + \cy인간개조? 음, 이거 때문에 녀석들이 끊임없이 나오는 거였어! 녀석들 성질 더러운 것도 그렇고.","Er lijkt geen einde te komen aan de verschrikking waar we voor staan. We hebben ontdekt dat de Orde onze mensen niet doodt. Het transformeert hen, in bio-mechanische soldaten. Zoek de faciliteit waar dit gebeurt en sluit deze permanent.","Det ser ikke ut til å være noen ende på skrekken vi står overfor. Vi har funnet ut at Ordenen ikke dreper folket vårt. Den forvandler dem til biomekaniske soldater. Finn anlegget der dette gjøres og steng det, permanent.","Wygląda na to, że naszym koszmarom nie ma końca. Dowiedzieliśmy się, że Zakon nie zabija naszych ludzi. Tylko zmienia ich w biomechanicznych żołnierzy. Znajdź ośrodek, w którym to robią i zamknij go na dobre.","Parece que os horrores que enfrentamos não têm fim. Descobrimos que a Ordem não está matando o nosso pessoal. Está os transformando em soldados biomecânicos. Ache a instalação onde isso é feito e feche-a, de uma vez por todas.",,"Pare să nu existe limite pentru răul pe care îl înfruntăm. Îi transformă, în soldați bio-mecanici. Găsește fabrica unde se întâmplă asta și închide-o, permanent.","Иногда кажется, что эти ужасы никогда не закончатся. Мы узнали, что Орден не убивает наших людей. Он перерабатывает их в биомеханических солдат. Найди фабрику, где происходит это, и закрой её раз и навсегда!",,Det verkar inte finnas något slut på den skräck vi står inför. Vi har fått reda på att Orden inte dödar vårt folk. Den förvandlar dem till biomekaniska soldater. Hitta anläggningen där detta sker och stäng den för gott.,Karşılaştığımız dehşetin sonu yok gibi görünüyor. Tarikat'ın insanlarımızı öldürmediğini öğrendik. Onları biyo-mekanik askerlere dönüştürüyor. Bunun yapıldığı tesisi bulun ve kalıcı olarak kapatın. +Where is this located?,TXT_RPLY0_SCRIPT10_D12128_WHERE,〃,,,Kde ji najdu?,Hvor er det placeret?,Wo finde ich sie?,,Kie ĝi estas?,¿Dónde queda?,,Missä se sijaitsee?,Où se trouve-elle?,Hol van ez?,Dove si trova?,手掛かりは何処にある?,이 장소는 어디에 있죠?,Waar bevindt deze faciliteit zich?,Hvor ligger det?,Gdzie się znajduje?,Onde se encontra?,,Unde este localizată?,Где она находится?,,Var finns den?,Burası nerede? +"One of our captains, Richter, is waiting for you by the waterfall in the commons. He has seen the facility and can guide you inside. Stop this atrocity, now.",TXT_DLG_SCRIPT10_D13644_ONEOF,〃,,,"Jeden z našich kapitánů, Richter, na tebe čeká u vodopádů na návsi. Továrnu už viděl a může ti poradit, jak dovnitř. Zastav tuhle ohavnost, ihned.","En af vores kaptajner, Richter, venter på dig ved vandfaldet i fællesrummet. Han har set anlægget og kan guide dig indenfor. Stop denne grusomhed, nu.","Einer unserer Anführer, Rickter warted auf dich, am Wasserfall bei der Mensa. Er hat es gesehen und kann dich dort hinführen. Stope dieses Gräuel - sofort.",,"Unu el niaj kapitanoj, Rikter, atendas vin en la komunumo en la limlando. Li vidis la instalaĵon kaj scias eniri ĝin. Ĉesu tuj ĉi tiun teruraĵon.","Uno de nuestros capitanes, Richter, está esperándote en la comuna de las tierras fronterizas. Ha visto la instalación y sabe como entrar. Detén esta atrocidad ahora.","Uno de nuestros capitanes, Richter, está esperándote en la comuna de las tierras fronterizas. Vio la instalación y sabe como entrar. Detén esta atrocidad ahora.","Richter, yksi kapteeneistamme, odottaa sinua messissä vesiputouksen äärellä. Hän on nähnyt laitoksen ja voi opastaa sinut sisälle. Lopeta tämä kauhistus, heti paikalla.","Un de nos capitaines, Richter, vous attend près de la cascade dans le réfectoire. Il a vu l'usine et peut vous guider jusqu'a l'intérieur. Arrêtez cette atrocité maintenant.","Richter - az egyik kapitányunk - a vízesés melletti étkezdénél fog várni rád. Ő látta ezt a létesítményt, és be tud vinni. Állítsd meg ezt a borzalmat azonnal.","Uno dei nostri capitani, Richter, ti sta aspettando vicino alla cascata nei comuni. Lui ha visto la fabbrica e ti può guidare dentro. Devi fermare quest'atrocità al più presto.","キャプテンの一人、リヒターが コモンズの滝で待っている。 彼は施設を発見し生還した者だ。 -早急にそのふざけた行為を止めさせろ。","우리 군의 한 대대장인 릭터가 식당가에 위치한 폭포 근처에서 당신을 기다리고 있습니다. 그는 그 끔찍한 시설을 보았다고 했으며, 침투할 수 있게 도와주고 싶다는군요. 부디 이 잔혹 행위를 멈출 수 있기를 바랍니다.","Een van onze kapiteins, Richter, wacht u op bij de waterval in het Lagerhuis. Hij heeft het gebouw gezien en kan je naar binnen leiden. Stop deze gruweldaad, nu.","En av våre kapteiner, Richter, venter på deg ved fossen i allmenningen. Han har sett anlegget og kan lede dere inn. Stopp denne grusomheten, nå.","Jeden z naszych kapitanów, Richter, czeka na ciebie przy wodospadzie przy błoniach. Widział ten ośrodek i pomoże ci się tam dostać. Skończ z tym okrucieństwem.","Um dos nossos capitães, Richter, está te esperando perto da cascata próxima ao refeitório. Ele conhece a instalação e pode te ajudar a infiltrá-la. Detenha essa atrocidade o quanto antes.",,"Unul dintre căpitanii noștri, Richter, te așteaptă lângă cascadă. A văzut fabrica și te poate conduce în interiorul ei. Încheie atrocitatea asta, acum.","Один из наших капитанов, Рихтер, ожидает тебя возле водопада в поселении Ордена. Он уже проникал на фабрику, и он скажет тебе, как туда попасть. Положи конец этим зверствам, немедленно!",,"Kaptanlarımızdan biri, Richter, ortak kullanım alanındaki şelalenin yanında sizi bekliyor. Tesisi gördü ve size içeride rehberlik edebilir. Bu vahşeti durdurun, hemen." -They'll pay for this!,TXT_RPLY0_SCRIPT10_D13644_THEYL,,,,Za tohle budou pykat!,De vil betale for dette!,Dafür werden sie bezahlen.,,,¡Pagarán por esto!,,Ne saavat maksaa tästä!,Ils paieront pour cela!,Megfizetnek ezért!,La pagheranno per questo!,奴等に対価を払わせてやるさ!,그놈들은 죗값을 치를 것입니다!,Zij zullen hiervoor betalen!,De skal få svi for dette!,Zapłacą za to!,Eles pagarão por isso!,,Vor plătii pentru asta!,Они за всё заплатят!,,Bunun bedelini ödeyecekler! -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D15160_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Batalu pro la Fronto kaj liberigota lando. Ekagu.,Lucha por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het Front en vrijheid. Ga weg.,Kjemp for fronten og friheten. Av sted!,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Выдвигайся.,,Cephe ve özgürlük için savaşın. Dışarı çıkın. -"I am the One God... I need his spirit to be free so that I can leave my body, and join him in flight. You have no idea what you possess... And what terror you face... The One God must be free... And he will reward me... I will be one...",TXT_DLG_SCRIPT10_D16676_IAMTH,,,,"Já jsem Jedním bohem... Potřebuju jeho duši abych se osvobodil a opustil své tělo a mohl se k němu připojit na nebesích. Nemáš ani tušení, co držíš v rukách... a jaké hrůze čelíš... Jeden bůh musí být svobodný... odmění mě... Budu jeden...","Jeg er den eneste Gud... Jeg har brug for, at hans ånd bliver fri, så jeg kan forlade min krop og slutte mig til ham i flugten. Du har ingen idé om, hvad du besidder... Og hvilken terror du står over for... Den ene Gud skal være fri... Og han vil belønne mig... Jeg vil være én...","Ich bin der Eine Gott... Sein Geist muss frei sein so dass ich seinen Körper verlassen und mit ihm fliegen kann. Du hast keine Ahnung, was du besitzt... And welcher Terror die bevorsteht... Der Eine Gott muss frei sein... Und er wird mich belohnen... Ich werde eins...",,,"Soy el Dios Único... Necesito que su espíritu sea libre para poder abandonar mi cuerpo, y unirme a él en vuelo. No tienes ni idea de lo que posees... Y de el terror al que te enfrentas... El Dios Único debe ser libre... Y me recompensará... Seré uno...",,"Minä olen Yksi Ainoa Jumala... Tarvitsen hänen henkeään ollakseni vapaa ja poistuakseni ruumiistani, jotta voisin paeta hänen kanssaan. Et käsitäkään, mitä omaat... ja mitä kauhua olet kohtaava... Yhden Ainoan Jumalan on päästävä vapaaksi... Ja hän palkitsee minut... Tulen olemaan yksi...","Je suis le Seul Dieu.. Il me faut libérer son esprit pour qu'il puisse sortir de mon corps, et le rejoindre dans sa fuite. Vous ne savez pas ce que vous possédez.. Et la terreur à laquelle vous devrez faire face... Le Seul Dieu doit être libre.. Et il me récompensera.. Je serais un avec lui..","Én vagyok az egy Igaz Isten...ki akarom szabadítani a lelkét, hogy elhagyhassam a testemet és társuljak mellé a harcban. Ötleted sincs miféle erővel rendelkezel...és miféle terroral nézel szemben...az egy Igaz Istennek szabadnak kell lennie...és majd megjutalmaz...eggyé válok majd...","Io sono l'Unico Dio... Ho bisogno che il suo spirito sia libero così che io possa lasciare il mio corpo, e unirmi a lui in volo. Non hai idea di cosa possiedi... E di quale terrore vai ad affrontare... L'Unico Dio deve essere libero... E mi ricompenserà... E sarò io...","我が唯一神だ...我は己の肉体を離れ +早急にそのふざけた行為を止めさせろ。","우리 군의 한 대대장인 릭터가 식당가에 위치한 폭포 근처에서 당신을 기다리고 있습니다. 그는 그 끔찍한 시설을 보았다고 했으며, 침투할 수 있게 도와주고 싶다는군요. 부디 이 잔혹 행위를 멈출 수 있기를 바랍니다.","Een van onze kapiteins, Richter, wacht u op bij de waterval in het Lagerhuis. Hij heeft het gebouw gezien en kan je naar binnen leiden. Stop deze gruweldaad, nu.","En av våre kapteiner, Richter, venter på deg ved fossen i allmenningen. Han har sett anlegget og kan lede dere inn. Stopp denne grusomheten, nå.","Jeden z naszych kapitanów, Richter, czeka na ciebie przy wodospadzie przy błoniach. Widział ten ośrodek i pomoże ci się tam dostać. Skończ z tym okrucieństwem.","Um dos nossos capitães, Richter, está te esperando perto da cascata próxima ao refeitório. Ele conhece a instalação e pode te ajudar a infiltrá-la. Detenha essa atrocidade o quanto antes.",,"Unul dintre căpitanii noștri, Richter, te așteaptă lângă cascadă. A văzut fabrica și te poate conduce în interiorul ei. Încheie atrocitatea asta, acum.","Один из наших капитанов, Рихтер, ожидает тебя возле водопада в поселении Ордена. Он уже проникал на фабрику, и он скажет тебе, как туда попасть. Положи конец этим зверствам, немедленно!",,"En av våra kaptener, Richter, väntar på dig vid vattenfallet i allmänningen. Han har sett anläggningen och kan guida dig in. Stoppa denna grymhet, nu.","Kaptanlarımızdan biri, Richter, ortak kullanım alanındaki şelalenin yanında sizi bekliyor. Tesisi gördü ve size içeride rehberlik edebilir. Bu vahşeti durdurun, hemen." +They'll pay for this!,TXT_RPLY0_SCRIPT10_D13644_THEYL,〃,,,Za tohle budou pykat!,De vil betale for dette!,Dafür werden sie bezahlen.,,Ili pentos!,¡Se arrepentirán!,¡Se van a arrepentir!,Ne saavat maksaa tästä!,Ils paieront pour cela!,Megfizetnek ezért!,La pagheranno per questo!,奴等に対価を払わせてやるさ!,그놈들은 죗값을 치를 것입니다!,Zij zullen hiervoor betalen!,De skal få svi for dette!,Zapłacą za to!,Eles pagarão por isso!,,Vor plătii pentru asta!,Они за всё заплатят!,,De kommer att få betala för detta!,Bunun bedelini ödeyecekler! +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D15160_FIGHT,〃,,,Bojuj za Frontu a svobodu! Odchod.,Kæmp for fronten og friheden. Af sted.,Kämpfe für die Front und die Freiheit. Nun geh.,,Bataladu pro la Fronto kaj libereco. Ekagu.,Pelea por el Frente y la libertad. En marcha.,,Taistele Rintaman ja vapauden puolesta. Liikkeelle mars.,Battez vous pour le Front et pour la liberté. Repos.,Együtt a Frontért és a szabadságért! Indulás!,"Lotta, per il Fronte e per la libertà! E ora, al lavoro.",フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het Front en vrijheid. Ga weg.,Kjemp for fronten og friheten. Av sted!,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Выдвигайся.,,Kämpa för fronten och friheten. Gå ut.,Cephe ve özgürlük için savaşın. Dışarı çıkın. +"I am the One God... I need his spirit to be free so that I can leave my body, and join him in flight. You have no idea what you possess... And what terror you face... The One God must be free... And he will reward me... I will be one...",TXT_DLG_SCRIPT10_D16676_IAMTH,MAP10: Macil → After destroying the converter in MAP24.,,,"Já jsem Jedním bohem... Potřebuju jeho duši abych se osvobodil a opustil své tělo a mohl se k němu připojit na nebesích. Nemáš ani tušení, co držíš v rukách... a jaké hrůze čelíš... Jeden bůh musí být svobodný... odmění mě... Budu jeden...","Jeg er den eneste Gud... Jeg har brug for, at hans ånd bliver fri, så jeg kan forlade min krop og slutte mig til ham i flugten. Du har ingen idé om, hvad du besidder... Og hvilken terror du står over for... Den ene Gud skal være fri... Og han vil belønne mig... Jeg vil være én...","Ich bin der Eine Gott... Sein Geist muss frei sein so dass ich seinen Körper verlassen und mit ihm fliegen kann. Du hast keine Ahnung, was du besitzt... And welcher Terror die bevorsteht... Der Eine Gott muss frei sein... Und er wird mich belohnen... Ich werde eins...",,"Mi estas la Vera Dio. Mi bezonas liberigi lian spiriton, tiam mi povos forlasi mian korpon kaj aliĝi al li en la flugo! Vi ne havas ideon pri tio, kion vi posedas... nek pri la teruraĵo, kiun vi alfrontas. La Vera Dio devas esti libera! Kaj li rekompencos min... Ni estos la sama!",Soy el Dios Único. ¡Necesito liberar su espíritu para poder abandonar mi cuerpo y unirme a él en vuelo! No tienes ni idea de lo que posees... ni del terror al que te enfrentas. ¡El Dios Único debe ser libre! Y me recompensará... ¡Seremos el mismo!,Soy el Dios Único. ¡Necesito liberar su espíritu para poder abandonar mi cuerpo y unirme a él en vuelo! No tienes ni idea de lo que posees... ni del terror al que te enfrentas. ¡El Dios Único debe ser libre! Y me va a recompensar... ¡Vamos a ser el mismo!,"Minä olen Yksi Ainoa Jumala... Tarvitsen hänen henkeään ollakseni vapaa ja poistuakseni ruumiistani, jotta voisin paeta hänen kanssaan. Et käsitäkään, mitä omaat... ja mitä kauhua olet kohtaava... Yhden Ainoan Jumalan on päästävä vapaaksi... Ja hän palkitsee minut... Tulen olemaan yksi...","Je suis le Seul Dieu.. Il me faut libérer son esprit pour qu'il puisse sortir de mon corps, et le rejoindre dans sa fuite. Vous ne savez pas ce que vous possédez.. Et la terreur à laquelle vous devrez faire face... Le Seul Dieu doit être libre.. Et il me récompensera.. Je serais un avec lui..","Én vagyok az egy Igaz Isten...ki akarom szabadítani a lelkét, hogy elhagyhassam a testemet és társuljak mellé a harcban. Ötleted sincs miféle erővel rendelkezel...és miféle terroral nézel szemben...az egy Igaz Istennek szabadnak kell lennie...és majd megjutalmaz...eggyé válok majd...","Io sono l'Unico Dio... Ho bisogno che il suo spirito sia libero così che io possa lasciare il mio corpo, e unirmi a lui in volo. Non hai idea di cosa possiedi... E di quale terrore vai ad affrontare... L'Unico Dio deve essere libero... E mi ricompenserà... E sarò io...","我が唯一神だ...我は己の肉体を離れ 自由となり、神の魂と共に飛び立てる。 貴様には何も分かりもしないだろう... そして垣間見る恐怖もな... 唯一神は解放されるのだ... そして神は我を表彰するだろう... 我は一つとなる...","유일신... 그분의 영혼의 힘으로... 나의 육신을 버리고... 그분과 자유롭게 날아가리라... 그대가 소유한 것, 그대가 직면할 운명... 모두 모를 것이다... 유일신이 자유가 되면... 나에게 보답하시매, 그와 하나가 되리라!! - \cy역겨운 자식... 죽여버려!","Ik ben de enige God.... Ik heb zijn geest nodig om vrij te zijn, zodat ik mijn lichaam kan verlaten en met hem mee kan vliegen. Je hebt geen idee wat je bezit.... En welke terreur je onder ogen ziet.... De Ene God moet vrij zijn.... En hij zal mij belonen.... Ik zal er een zijn....","Jeg er den ene Gud... Jeg trenger hans ånd for å være fri, så jeg kan forlate kroppen min og bli med ham på flukt. Du aner ikke hva du besitter... Og hvilken skrekk du står overfor... Den ene Gud må være fri... Og han vil belønne meg... Jeg vil bli en...",Jam jest Jedyny Bóg... potrzebuję uwolnić jego duszę abym opuścił swe ciało i dołączył do niego. Nie masz pojęcia co ty posiadłeś... I z jakim terrorem się spotykasz... Jedyny Bóg musi być wolny... I on mnie nagrodzi... To ja będę tym jednym...,"Eu sou o Deus Único... Eu preciso desse espírito para ser livre, poder abandonar este corpo e unir-me a ele na fuga. Você não tem idéia do que possui... E o horror que você enfrenta... O Deus Único deve ser livre... E ele me recompensará... Eu serei um...",,"Eu sunt adevăratul Zeu.... Am nevoie de sufletul lui ca să pot să-mi părăsesc corpul, și să mă alătur lui în zbor. Nu ai idee despre ceea ce posezi... Și ce teroare înfrunți... Adevăratul Zeu trebuie să fie liber... Și mă va răsplătii... Voi fi unul...","Я Единый Бог... Я должен высвободить его дух, тогда я смогу покинуть бренную оболочку моего тела и воссоединиться с ним в полёте. Ты и понятия не имеешь, чем обладаешь... и с какому кошмару смотришь в лицо... Единый Бог должен быть освобождён... И он вознаградит меня... Это сделаю я!",,"Ben Tek Tanrı'yım. Onun ruhunun özgür olmasına ihtiyacım var, böylece bedenimi terk edebilir ve uçuşta ona katılabilirim. Neye sahip olduğunuz hakkında hiçbir fikriniz yok. Ve nasıl bir dehşetle karşı karşıya olduğunuzu. Tek Tanrı özgür olmalı. Ve o beni ödüllendirecek. Ben bir olacağım." -I will destroy you!,TXT_RPLY0_SCRIPT10_D16676_IWILL,,,,Zničím tě!,Jeg vil ødelægge dig!,Ich werde dich zerstören!,,,¡Te destruiré!,,Tuhoan sinut!,L'heure est venue de vous détruire!,Megsemmisítelek!,Ti distruggerò!,お前を滅ぼす!,당신을 처단하겠어!,Ik zal je vernietigen!,Jeg skal tilintetgjøre deg!,Zniszczę cię!,Eu vou destruir você!,,Te voi distruge!,Я уничтожу тебя!,,Seni yok edeceğim! -Glad to see you made it. What do you need? ,TXT_DLG_SCRIPT10_D18192_GLADT,MAP10: Gerald (no upgrade).,,,"Jsem rád, žes to zvládnul. Co bys potřeboval?","Godt at se, at du klarede den. Hvad har du brug for?","Gut, dass du es geschafft hast. Was brauchst du?",,,Me alegro de verte de una pieza. ¿Qué necesitas?,,"Hienoa, että selvisit. Mitä tarvitset?",Ravi de voir que vous vous en êtes sorti. Que puis-je faire pour vous?,"Örömmel látom, hogy túlélted. Miben segíthetek?",Lieto di vederti qui. Di che hai bisogno?,お会いできて光栄です。何が必要ですか?,여기까지 오시다니 놀랍군요. 뭔가 필요한 게?,Blij te zien dat je het gehaald hebt. Wat heb je nodig?,Godt å se at du kom. Hva trenger du?,"Dobrze widzieć, że udało ci się. Czego ci potrzeba?",Que bom que você conseguiu. O que você precisa?,,Mă bucur să văd că ai reușit. De ce ai nevoie?,"Я рад, что ты справился. Чем могу помочь?",,Gelebilmene sevindim. Neye ihtiyacın var? -Heal me.,TXT_RPLY0_SCRIPT10_D18192_HEALM,〃,,,Potřebuju ošetřit.,Helbrede mig.,Mach mich gesund.,,,Cúrame.,,Hoida minua.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료해주세요.,Genees me.,Helbred meg.,Ulecz mnie.,Me cure.,,Bandajează-mă.,Подлечи меня.,,İyileştir beni. -"Well, lets get you fixed up.",TXT_RYES0_SCRIPT10_D18192_WELLL,〃,,,"Dobře, tak tě dáme dohromady.","Nå, lad os få dig ordnet.","Gut, das hier sollte helfen.",,,"Bien, vamos a hacerte unos arreglos.",,"Selvä, pistetään sinut kuntoon.","Allez, on va vous remettre sur pied.","Na, akkor pofozzunk helyre.","Molto bene, ti darò una sistemata.",では、すぐ治療しましょう。,그럼 긴급 치료하겠습니다.,"Nou, laten we je opknappen.","Vel, la oss få deg fikset opp.","Dobra, pozbieram cię do kupy.","Ok, vamos dar um jeito em você.",,"Păi, să te aranjăm.","Ну, давай приведём тебя в порядок.",,"Pekala, seni iyileştirelim." -You're fine.,TXT_RNO0_SCRIPT10_D18192_YOURE,〃,,,Jsi v pořádku.,Du har det fint.,Die geht es gut.,,,Estás bien.,,Olet kunnossa.,Vous allez bien.,Rendben is vagy.,Stai bene.,貴方は大丈夫です。,괜찮아 보이는데.,Je bent in orde.,Det går bra med deg.,Jesteś zdrowy.,Você está bem.,,Ești în regulă.,Ты здоров.,,İyisin. -Anything new?,TXT_RPLY1_SCRIPT10_D18192_ANYTH,〃,,,Něco nového?,Noget nyt?,Irgend etwas Neues?,,,¿Algo nuevo?,,Onko mitään uutta?,Quoi de neuf?,Valami újdonság?,Novità?,何か新しいのは?,특별한 거 없나요?,Iets nieuws?,Noe nytt?,Coś nowego?,Alguma novidade?,,Ceva nou?,Есть что-нибудь новое?,,Yeni bir şey var mı? -"Yes, I've got some new hardware for you.",TXT_RYES1_SCRIPT10_D18192_YESIV,〃,,,"Ano, mám pro tebe novou mašinku.","Ja, jeg har noget nyt hardware til dig.","Ja, ich habe neue Hardware für dich.",,,"Sí, tengo nuevo hardware para ti.",,"Kyllä, minulla on sinulle uutta rautaa.","Ah, j'ai du nouveau matériel pour vous.","Igen, van pár új fegyverem számodra.","Si, ho delle nuove attrezzature per te.",貴方の為に幾つか新しいハードウェアを見つけました。,네! 사용 가능한 하드웨어가 하나 있습니다.,"Ja, ik heb wat nieuwe hardware voor je.","Ja, jeg har noe nytt utstyr til deg.","Tak, mam dla ciebie nowe oprogramowanie.","Sim, tenho equipamento novo pra você.",,"Da, am ceva hardware nou pentru tine.",Да. Новая аппаратура для тебя.,,"Evet, senin için yeni bir donanımım var." -"Nope, I'm working on it though.",TXT_RNO1_SCRIPT10_D18192_NOPEI,〃,,,"Ne, ale pracuju na tom.","Nej, men jeg arbejder på det.","Nein, ich arbeite noch daran.",,,"No, pero estoy trabajando en ello.",,Ei; on kyllä työn alla.,"Rien, mais j'y travaille.","Nem, de már dolgozom rajta.","No, ma ci sto lavorando.",いえ、只今探しています。,아뇨. 아직 작업 진행 중입니다.,"Nee, maar ik ben er wel mee bezig.","Nei, men jeg jobber med det.","Nie, jeszcze nad tym pracuję.","Não, mas estou trabalhando nisso.",,"Nu, încă lucrez la asta.","Нет, но я работаю над ним.",,"Hayır, üzerinde çalışıyorum." -"What can I do for you now? Feris is decrypting some really complex files, but it's all worth it. There's already some information that I'll be able to apply to the next version of the stamina implant.",TXT_DLG_SCRIPT10_D19708_WHATC,〃 (one upgrade),,,"Co pro tebe můžu udělat teď? Feris pracuje na dešifrování hodně složitých souborů, ale bude to stát za to. Už teď máme informace, které budu moct použít v nové verzi tvého implantátu.","Hvad kan jeg gøre for dig nu? Feris er ved at dekryptere nogle virkelig komplekse filer, men det er det hele værd. Der er allerede nogle oplysninger, som jeg vil kunne anvende til den næste version af udholdenhedsimplantatet.","Was kann ich für dich tun? Feris entschlüsselt gerade einige sehr komplexe Dateien, aber es ist den Aufwand wert. Einige dieser Informationen kann ich für die nächste Version deines Implantats anwenden.",,,"¿Qué puedo hacer por ti? Feris está desencriptando unos archivos bastante complejos, pero valdrá la pena. Ya hay algo de información que puedo aplicar a la próxima version del implante de aguante.",,"Miten voin olla avuksi? Feris on purkamassa joidenkin todella monimutkaisten tiedostojen salausta, mutta se on sen vaivan väärti.","Que puis-je faire pour vous? Feris est en train de décrypter des fichiers très complexes, mais ça à l'air d'en valoir la peine. Il y a déjà des informations très intéressantes que l'on va pouvoir utiliser pour la prochaine version de l'implant d'endurance.","Mit tehetek érted most? Feris elég komplex fájlokat próbál épp dekódolni, de ha sikerül meg fogja érni. Már van pár információm, amit fel tudok használni az állóképesség implantátum fejlesztésére.","Che cosa posso fare per te ora? Feris sta decriptando alcuni file molto complessi, ma ne varrà la pena. Abbiamo già delle informazioni che potrò applicare nella prossima versione dell'impianto stamina.","何か御用かい?幾つかの複雑に複合化された + \cy역겨운 자식... 죽여버려!","Ik ben de enige God.... Ik heb zijn geest nodig om vrij te zijn, zodat ik mijn lichaam kan verlaten en met hem mee kan vliegen. Je hebt geen idee wat je bezit.... En welke terreur je onder ogen ziet.... De Ene God moet vrij zijn.... En hij zal mij belonen.... Ik zal er een zijn....","Jeg er den ene Gud... Jeg trenger hans ånd for å være fri, så jeg kan forlate kroppen min og bli med ham på flukt. Du aner ikke hva du besitter... Og hvilken skrekk du står overfor... Den ene Gud må være fri... Og han vil belønne meg... Jeg vil bli en...",Jam jest Jedyny Bóg... potrzebuję uwolnić jego duszę abym opuścił swe ciało i dołączył do niego. Nie masz pojęcia co ty posiadłeś... I z jakim terrorem się spotykasz... Jedyny Bóg musi być wolny... I on mnie nagrodzi... To ja będę tym jednym...,"Eu sou o Deus Único... Eu preciso desse espírito para ser livre, poder abandonar este corpo e unir-me a ele na fuga. Você não tem idéia do que possui... E o horror que você enfrenta... O Deus Único deve ser livre... E ele me recompensará... Eu serei um...",,"Eu sunt adevăratul Zeu.... Am nevoie de sufletul lui ca să pot să-mi părăsesc corpul, și să mă alătur lui în zbor. Nu ai idee despre ceea ce posezi... Și ce teroare înfrunți... Adevăratul Zeu trebuie să fie liber... Și mă va răsplătii... Voi fi unul...","Я Единый Бог... Я должен высвободить его дух, тогда я смогу покинуть бренную оболочку моего тела и воссоединиться с ним в полёте. Ты и понятия не имеешь, чем обладаешь... и с какому кошмару смотришь в лицо... Единый Бог должен быть освобождён... И он вознаградит меня... Это сделаю я!",,Jag är den ende guden... Jag behöver att hans ande är fri så att jag kan lämna min kropp och ansluta mig till honom i flykten. Du har ingen aning om vad du äger... Och vilken skräck ni står inför... Den ende guden måste vara fri... Och han kommer att belöna mig... Jag kommer att bli en...,"Ben Tek Tanrı'yım. Onun ruhunun özgür olmasına ihtiyacım var, böylece bedenimi terk edebilir ve uçuşta ona katılabilirim. Neye sahip olduğunuz hakkında hiçbir fikriniz yok. Ve nasıl bir dehşetle karşı karşıya olduğunuzu. Tek Tanrı özgür olmalı. Ve o beni ödüllendirecek. Ben bir olacağım." +I will destroy you!,TXT_RPLY0_SCRIPT10_D16676_IWILL,〃,,,Zničím tě!,Jeg vil ødelægge dig!,Ich werde dich zerstören!,,Mi detruos vin!,¡Te destruiré!,¡Te voy a destruir!,Tuhoan sinut!,L'heure est venue de vous détruire!,Megsemmisítelek!,Ti distruggerò!,お前を滅ぼす!,당신을 처단하겠어!,Ik zal je vernietigen!,Jeg skal tilintetgjøre deg!,Zniszczę cię!,Eu vou destruir você!,,Te voi distruge!,Я уничтожу тебя!,,Jag ska förgöra dig!,Seni yok edeceğim! +Glad to see you made it. What do you need? ,TXT_DLG_SCRIPT10_D18192_GLADT,MAP10: Gerald (no upgrade).,,,"Jsem rád, žes to zvládnul. Co bys potřeboval?","Godt at se, at du klarede den. Hvad har du brug for?","Gut, dass du es geschafft hast. Was brauchst du?",,Feliĉe vi supervivis. Kion vi bezonas?,Me alegra verte en una pieza. ¿Qué necesitas?,,"Hienoa, että selvisit. Mitä tarvitset?",Ravi de voir que vous vous en êtes sorti. Que puis-je faire pour vous?,"Örömmel látom, hogy túlélted. Miben segíthetek?",Lieto di vederti qui. Di che hai bisogno?,お会いできて光栄です。何が必要ですか?,여기까지 오시다니 놀랍군요. 뭔가 필요한 게?,Blij te zien dat je het gehaald hebt. Wat heb je nodig?,Godt å se at du kom. Hva trenger du?,"Dobrze widzieć, że udało ci się. Czego ci potrzeba?",Que bom que você conseguiu. O que você precisa?,,Mă bucur să văd că ai reușit. De ce ai nevoie?,"Я рад, что ты справился. Чем могу помочь?",,Det gläder mig att se att du klarade dig. Vad behöver du?,Gelebilmene sevindim. Neye ihtiyacın var? +Heal me.,TXT_RPLY0_SCRIPT10_D18192_HEALM,〃,,,Potřebuju ošetřit.,Helbrede mig.,Mach mich gesund.,,Kuracu min.,Cúrame.,,Hoida minua.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료해주세요.,Genees me.,Helbred meg.,Ulecz mnie.,Me cure.,,Bandajează-mă.,Подлечи меня.,,Laga mig.,İyileştir beni. +"Well, lets get you fixed up.",TXT_RYES0_SCRIPT10_D18192_WELLL,〃,,,"Dobře, tak tě dáme dohromady.","Nå, lad os få dig ordnet.","Gut, das hier sollte helfen.",,"Bone, mi pretigu vin.","Bueno, hora de +arreglarte un poco.",,"Selvä, pistetään sinut kuntoon.","Allez, on va vous remettre sur pied.","Na, akkor pofozzunk helyre.","Molto bene, ti darò una sistemata.",では、すぐ治療しましょう。,그럼 긴급 치료하겠습니다.,"Nou, laten we je opknappen.","Vel, la oss få deg fikset opp.","Dobra, pozbieram cię do kupy.","Ok, vamos dar um jeito em você.",,"Păi, să te aranjăm.","Ну, давай приведём тебя в порядок.",,Vi får fixa till dig.,"Pekala, seni iyileştirelim." +You're fine.,TXT_RNO0_SCRIPT10_D18192_YOURE,〃,,,Jsi v pořádku.,Du har det fint.,Die geht es gut.,,Vi estas en ordo.,Estás bien.,,Olet kunnossa.,Vous allez bien.,Rendben is vagy.,Stai bene.,貴方は大丈夫です。,괜찮아 보이는데.,Je bent in orde.,Det går bra med deg.,Jesteś zdrowy.,Você está bem.,,Ești în regulă.,Ты здоров.,,Du är okej.,İyisin. +Anything new?,TXT_RPLY1_SCRIPT10_D18192_ANYTH,〃,,,Něco nového?,Noget nyt?,Irgend etwas Neues?,,Ĉu io nova?,¿Algo nuevo?,,Onko mitään uutta?,Quoi de neuf?,Valami újdonság?,Novità?,何か新しいのは?,특별한 거 없나요?,Iets nieuws?,Noe nytt?,Coś nowego?,Alguma novidade?,,Ceva nou?,Есть что-нибудь новое?,,Något nytt?,Yeni bir şey var mı? +"Yes, I've got some new hardware for you.",TXT_RYES1_SCRIPT10_D18192_YESIV,〃,,,"Ano, mám pro tebe novou mašinku.","Ja, jeg har noget nyt hardware til dig.","Ja, ich habe neue Hardware für dich.",,"Jes, mi havas novan +aparataron por vi.","Sí, tengo nuevo +«hardware» para ti.",,"Kyllä, minulla on sinulle uutta rautaa.","Ah, j'ai du nouveau matériel pour vous.","Igen, van pár új fegyverem számodra.","Si, ho delle nuove attrezzature per te.",貴方の為に幾つか新しいハードウェアを見つけました。,네! 사용 가능한 하드웨어가 하나 있습니다.,"Ja, ik heb wat nieuwe hardware voor je.","Ja, jeg har noe nytt utstyr til deg.","Tak, mam dla ciebie nowe oprogramowanie.","Sim, tenho equipamento novo pra você.",,"Da, am ceva hardware nou pentru tine.",Да. Новая аппаратура для тебя.,,"Ja, jag har lite ny hårdvara till dig.","Evet, senin için yeni bir donanımım var." +"Nope, I'm working on it though.",TXT_RNO1_SCRIPT10_D18192_NOPEI,〃,,,"Ne, ale pracuju na tom.","Nej, men jeg arbejder på det.","Nein, ich arbeite noch daran.",,"Ne, sed mi +prilaboradas ĝin.","No, aunque estoy +trabajando en ello.",,Ei; on kyllä työn alla.,"Rien, mais j'y travaille.","Nem, de már dolgozom rajta.","No, ma ci sto lavorando.",いえ、只今探しています。,아뇨. 아직 작업 진행 중입니다.,"Nee, maar ik ben er wel mee bezig.","Nei, men jeg jobber med det.","Nie, jeszcze nad tym pracuję.","Não, mas estou trabalhando nisso.",,"Nu, încă lucrez la asta.","Нет, но я работаю над ним.",,"Nej, men jag jobbar på det.","Hayır, üzerinde çalışıyorum." +"What can I do for you now? Feris is decrypting some really complex files, but it's all worth it. There's already some information that I'll be able to apply to the next version of the stamina implant.",TXT_DLG_SCRIPT10_D19708_WHATC,〃 (one upgrade: Mission to talk to the Oracle),,,"Co pro tebe můžu udělat teď? Feris pracuje na dešifrování hodně složitých souborů, ale bude to stát za to. Už teď máme informace, které budu moct použít v nové verzi tvého implantátu.","Hvad kan jeg gøre for dig nu? Feris er ved at dekryptere nogle virkelig komplekse filer, men det er det hele værd. Der er allerede nogle oplysninger, som jeg vil kunne anvende til den næste version af udholdenhedsimplantatet.","Was kann ich für dich tun? Feris entschlüsselt gerade einige sehr komplexe Dateien, aber es ist den Aufwand wert. Einige dieser Informationen kann ich für die nächste Version deines Implantats anwenden.",,"Kion mi povas fari por vi? Feriso nun malĉifras kelkajn tre malsimplajn dosierojn, sed tio estos valora. Jam estas kelkaj informoj, kiujn mi povos apliki al la sekva versio de la energidona enplantaĵo.","¿Qué puedo hacer por ti? Feris está descifrando unos archivos bastante complejos, pero valdrá la pena. Ya hay algo de información que puedo aplicar a la próxima versión del implante de aguante.","¿Qué puedo hacer por ti? Feris está descifrando unos archivos bastante complejos, pero va a valer la pena. Ya hay algo de información que puedo aplicar a la próxima versión del implante de aguante.","Miten voin olla avuksi? Feris on purkamassa joidenkin todella monimutkaisten tiedostojen salausta, mutta se on sen vaivan väärti.","Que puis-je faire pour vous? Feris est en train de décrypter des fichiers très complexes, mais ça à l'air d'en valoir la peine. Il y a déjà des informations très intéressantes que l'on va pouvoir utiliser pour la prochaine version de l'implant d'endurance.","Mit tehetek érted most? Feris elég komplex fájlokat próbál épp dekódolni, de ha sikerül meg fogja érni. Már van pár információm, amit fel tudok használni az állóképesség implantátum fejlesztésére.","Che cosa posso fare per te ora? Feris sta decriptando alcuni file molto complessi, ma ne varrà la pena. Abbiamo già delle informazioni che potrò applicare nella prossima versione dell'impianto stamina.","何か御用かい?幾つかの複雑に複合化された フェリスのファイルにはそれだけの価値はあった スタミナインプラントの次期バージョンに 適用できる情報を少しばかり見つけたんだ。","무엇을 도와드릴까요? 페리스가 아주 복잡한 파일들을 천천히 해독하는 중입니다만, 기다리는 보람이 많이 있을 거예요. 나머지 정보를 다 해독한 뒤면 진보된 지구력 향상 이식을 받으실 수 있을 겁니다.","Wat kan ik nu voor je doen? Feris ontcijfert enkele zeer complexe bestanden, maar het is het allemaal de moeite waard. Er is al wat informatie die ik kan toepassen op de volgende versie van het stamina implantaat.","Hva kan jeg gjøre for deg nå? Feris dekrypterer noen komplekse filer, men det er verdt det. Jeg har allerede informasjon som jeg kan bruke i neste versjon av utholdenhetsimplantatet.","Co mogę dla ciebie teraz zrobić? Feris @@ -10728,13 +11227,17 @@ dokumenty, ale mówię ci... warto było. Już mamy trochę informacji, które będę mógł wykorzystać w nowszej wersji implantu zwiększającego -wytrzymałość.","Como posso te ajudar no momento? Feris está decriptando uns arquivos bem complexos, mas valerá a pena. Já temos informações que vou poder usar na próxima versão do implante de resistência.",,"Ce pot face pentru tine acum? Feris decriptează niște fișiere extrem de complexe, dar merită. Deja avem niște informații care le voi putea aplica urmatoarei versiuni ale implantului tău pentru rezistență.","Чем я могу тебе помочь? Ферис сейчас расшифровывает файлы Ордена. Это нелегко, но результат стоит того. Я уже получил кое-какие новые данные, которые помогут мне при разработке новой версии твоего импланта.",,Şimdi senin için ne yapabilirim? Feris bazı karmaşık dosyaların şifresini çözüyor ama buna değer. Dayanıklılık implantının bir sonraki versiyonuna uygulayabileceğim bazı bilgiler var. -Heal me.,TXT_RPLY0_SCRIPT10_D19708_HEALM,〃,,,Potřebuju ošetřit.,Helbred mig.,Mach mich gesund.,,Kuracu min.,Cúrame.,,Hoida minua.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료해주세요.,Genees mij.,Helbred meg.,Ulecz mnie.,Me cure.,,Bandajează-mă.,Подлечи меня.,,İyileştir beni. -You should learn to be a little more careful.,TXT_RYES0_SCRIPT10_D19708_YOUSH,〃,,,Měl bys být trochu opatrnější.,Du burde lære at være lidt mere forsigtig.,Du solltest wirklich etwas vorsichtiger sein.,,,Deberías aprender a tener un poco más de cuidado.,,Sinun pitäisi oppia olemaan hieman varovaisempi.,Vous devriez faire plus attention à vous.,Meg kéne tanulnod óvatosabbnak lenni.,Dovresti imparare ad essere un pò più attento.,もう少し慎重にやるべきでは。,몸 간수 잘하시고 싸우세요.,Je moet leren om wat voorzichtiger te zijn.,Du burde lære deg å være litt mer forsiktig.,Powinieneś być bardziej ostrożny.,Você precisa aprender a tomar mais cuidado.,,Ar trebui să fii mai grijuliu.,В следующий раз тебе стоит быть поосторожнее.,,Biraz daha dikkatli olmayı öğrenmelisin. -When will that be ready?,TXT_RPLY1_SCRIPT10_D19708_WHENW,〃,,,Kdy bude hotov?,Hvornår er den klar?,Wann ist es soweit?,,,¿Cuándo estará eso listo?,,Milloin se on valmis?,Quand-est-ce que t'il sera prêt?,Mikor lesz kész?,Quando sarà pronto?,出来ているか?,이식 준비는 다 됐습니까?,Wanneer is dat klaar?,Når er det klart?,Kiedy to będzie gotowe?,Quando isso vai estar pronto?,,Când va fi gata?,Когда он будет готов?,,Ne zaman hazır olacak? -It's ready now. This won't take but a moment.,TXT_RYES1_SCRIPT10_D19708_ITSRE,〃,,,Už je hotový. Nepotrvá to ani chvilku.,Det er klar nu. Det vil kun tage et øjeblik.,"Es ist fertig. Einen kurzen Moment, bitte.",,,Ya está listo. Ésto solo tomará un momento.,,Se on valmis nyt. Tähän ei mene kuin vain hetki.,"Il est déjà prêt, çe ne prendra qu'un moment.","Készen van, csak pár másodperc.",È pronto ora. Ci vorrà solo un momento.,用意出来ている。すぐ終わるさ。,다 됐습니다! 이제 이식을 시작하죠!,Het is nu klaar. Dit duurt niet langer dan een moment.,Det er klart nå. Dette tar bare et øyeblikk.,Już jest gotowe. To zajęło tylko chwilę.,Já está pronto. Isso não vai demorar.,,E gata. Va dura doar un moment.,Уже готово. Это не займёт много времени.,,Şimdi hazır. Bir dakika bile sürmez. -Soon.,TXT_RNO1_SCRIPT10_D19708_SOON,〃,,,Brzy.,Det er snart.,Bald.,,Baldaŭ.,Pronto.,,Pian.,Bientôt.,Hamarosan.,Presto.,間もなくだ。,곧 완성되요.,Binnenkort.,Snart.,Niedługo.,Logo logo.,,Curând.,Скоро.,,Çok yakında. -I think I found a glitch in your implant hardware. Feris is helping me design a retrofit that will take care of it and boost the speed of your hardware a little. Is there something I can do for you?,TXT_DLG_SCRIPT10_D21224_ITHIN,,,,"Myslím, že jsem našel vadu v tvém implantátu. Feris mi pomáhá navrhnout doplněk, který se o ni postará a zvýší jeho výkon. Můžu pro tebe něco udělat?","Jeg tror, jeg har fundet en fejl i dit implantathardware. Feris hjælper mig med at designe en eftermontering, der vil løse problemet og øge hastigheden på din hardware en smule. Er der noget, jeg kan gøre for dig?","Ich glaube ich habe eine Fehlfunktion in deinem Implantat gefunden. Feris hilft mir, einen Nachrüstsatz zu bauen und seine Funktion nochmal zu verbessern. Gibt es sonst etwas, das ich für dich tun kann?",,,Creo haber encontrado un defecto en el «hardware» de tu implante. Feris me está ayudando a diseñar una modernización para arreglarlo y aumentarle un poco la velocidad. ¿Hay algo que pueda hacer por ti?,,"Luulen löytäneeni vian istutteesi laitteistossa. Feris auttaa minua kehittämään jälkiasennuskappaleen, joka korjaa vian ja nopeuttaa laitteistoasi vähäsen. Miten voin olla muuten avuksi?",Je crois que j'ai découvert un bug dans votre implant. Feris m'aide à concevoir une mise à jour qui la corrigera et rendra le matériel encore plus rapide. Je peux faire quelque chose pour vous?,"Azt hiszem találtam egy hibát az implantátumban. Feris segít nekem áttervezni, hogy kiküszöböljük a hibát, és kicsit fel is gyorsítsuk a hardvert. Segíthetek valami másban?",Credo di aver trovato un problema nel tuo impianto. Feris mi sta aiutando a creare un ammodernamento che lo sistemerà e migliorerà un poco la velocità del tuo impianto. C'è qualcosa che posso fare per te?,"インプラントハードウェアに不具合が見つかった +wytrzymałość.","Como posso te ajudar no momento? Feris está decriptando uns arquivos bem complexos, mas valerá a pena. Já temos informações que vou poder usar na próxima versão do implante de resistência.",,"Ce pot face pentru tine acum? Feris decriptează niște fișiere extrem de complexe, dar merită. Deja avem niște informații care le voi putea aplica urmatoarei versiuni ale implantului tău pentru rezistență.","Чем я могу тебе помочь? Ферис сейчас расшифровывает файлы Ордена. Это нелегко, но результат стоит того. Я уже получил кое-какие новые данные, которые помогут мне при разработке новой версии твоего импланта.",,"Vad kan jag göra för dig nu? Feris dekrypterar några riktigt komplicerade filer, men det är värt det. Det finns redan en del information som jag kommer att kunna tillämpa på nästa version av uthållighetsimplantatet.",Şimdi senin için ne yapabilirim? Feris bazı karmaşık dosyaların şifresini çözüyor ama buna değer. Dayanıklılık implantının bir sonraki versiyonuna uygulayabileceğim bazı bilgiler var. +Heal me.,TXT_RPLY0_SCRIPT10_D19708_HEALM,〃,,,Potřebuju ošetřit.,Helbred mig.,Mach mich gesund.,,Kuracu min.,Cúrame.,,Hoida minua.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료해주세요.,Genees mij.,Helbred meg.,Ulecz mnie.,Me cure.,,Bandajează-mă.,Подлечи меня.,,Laga mig.,İyileştir beni. +You should learn to be a little more careful.,TXT_RYES0_SCRIPT10_D19708_YOUSH,〃,,,Měl bys být trochu opatrnější.,Du burde lære at være lidt mere forsigtig.,Du solltest wirklich etwas vorsichtiger sein.,,"Vi devus lerni esti +pli singardema.","Deberías aprender a tener +un poco más de cuidado.",,Sinun pitäisi oppia olemaan hieman varovaisempi.,Vous devriez faire plus attention à vous.,Meg kéne tanulnod óvatosabbnak lenni.,Dovresti imparare ad essere un po' più attento.,もう少し慎重にやるべきでは。,몸 간수 잘하시고 싸우세요.,Je moet leren om wat voorzichtiger te zijn.,Du burde lære deg å være litt mer forsiktig.,Powinieneś być bardziej ostrożny.,Você precisa aprender a tomar mais cuidado.,,Ar trebui să fii mai grijuliu.,В следующий раз тебе стоит быть поосторожнее.,,Du borde lära dig att vara lite mer försiktig.,Biraz daha dikkatli olmayı öğrenmelisin. +When will that be ready?,TXT_RPLY1_SCRIPT10_D19708_WHENW,〃,,,Kdy bude hotov?,Hvornår er den klar?,Wann ist es soweit?,,Kiam ĝi estos preta?,¿Cuándo estará listo?,¿Cuándo va a estar listo?,Milloin se on valmis?,Quand-est-ce que t'il sera prêt?,Mikor lesz kész?,Quando sarà pronto?,出来ているか?,이식 준비는 다 됐습니까?,Wanneer is dat klaar?,Når er det klart?,Kiedy to będzie gotowe?,Quando isso vai estar pronto?,,Când va fi gata?,Когда он будет готов?,,När kommer den att vara klar?,Ne zaman hazır olacak? +It's ready now. This won't take but a moment.,TXT_RYES1_SCRIPT10_D19708_ITSRE,〃,,,Už je hotový. Nepotrvá to ani chvilku.,Det er klar nu. Det vil kun tage et øjeblik.,"Es ist fertig. Einen kurzen Moment, bitte.",,"Mi jam finis. Atendu +nur unu momenton...","Ya lo está. Dame +solo un momento...",,Se on valmis nyt. Tähän ei mene kuin vain hetki.,"Il est déjà prêt, çe ne prendra qu'un moment.","Készen van, csak pár másodperc.",È pronto ora. Ci vorrà solo un momento.,用意出来ている。すぐ終わるさ。,다 됐습니다! 이제 이식을 시작하죠!,Het is nu klaar. Dit duurt niet langer dan een moment.,Det er klart nå. Dette tar bare et øyeblikk.,Już jest gotowe. To zajęło tylko chwilę.,Já está pronto. Isso não vai demorar.,,E gata. Va dura doar un moment.,Уже готово. Это не займёт много времени.,,Det är klart nu. Det här tar bara ett ögonblick.,Şimdi hazır. Bir dakika bile sürmez. +Soon.,TXT_RNO1_SCRIPT10_D19708_SOON,〃,,,Brzy.,Det er snart.,Bald.,,Baldaŭ.,Pronto.,,Pian.,Bientôt.,Hamarosan.,Presto.,間もなくだ。,곧 완성되요.,Binnenkort.,Snart.,Niedługo.,Logo logo.,,Curând.,Скоро.,,Snart.,Çok yakında. +I think I found a glitch in your implant hardware. Feris is helping me design a retrofit that will take care of it and boost the speed of your hardware a little. Is there something I can do for you?,TXT_DLG_SCRIPT10_D21224_ITHIN,〃 (two upgrades: Mission to decide between Macil or the Oracle),,,"Myslím, že jsem našel vadu v tvém implantátu. Feris mi pomáhá navrhnout doplněk, který se o ni postará a zvýší jeho výkon. Můžu pro tebe něco udělat?","Jeg tror, jeg har fundet en fejl i dit implantathardware. Feris hjælper mig med at designe en eftermontering, der vil løse problemet og øge hastigheden på din hardware en smule. Er der noget, jeg kan gøre for dig?","Ich glaube ich habe eine Fehlfunktion in deinem Implantat gefunden. Feris hilft mir, einen Nachrüstsatz zu bauen und seine Funktion nochmal zu verbessern. Gibt es sonst etwas, das ich für dich tun kann?",,"Ŝajnas, ke mi trovis cimeton en la aparataro de via enplantaĵo. Feriso helpas al mi dezajni modernigon por ripari ĝin kaj iomete pliigi ĝian rapidon. Ĉu mi povas fari ion por vi?",Creo haber encontrado un defecto en el «hardware» de tu implante. Feris me está ayudando a diseñar una modernización para arreglarlo y aumentarle un poco la velocidad. ¿Hay algo que pueda hacer por ti?,,"Luulen löytäneeni vian istutteesi laitteistossa. Feris auttaa minua kehittämään jälkiasennuskappaleen, joka korjaa vian ja nopeuttaa laitteistoasi vähäsen. Miten voin olla muuten avuksi?",Je crois que j'ai découvert un bug dans votre implant. Feris m'aide à concevoir une mise à jour qui la corrigera et rendra le matériel encore plus rapide. Je peux faire quelque chose pour vous?,"Azt hiszem találtam egy hibát az implantátumban. Feris segít nekem áttervezni, hogy kiküszöböljük a hibát, és kicsit fel is gyorsítsuk a hardvert. Segíthetek valami másban?",Credo di aver trovato un problema nel tuo impianto. Feris mi sta aiutando a creare un ammodernamento che lo sistemerà e migliorerà un poco la velocità del tuo impianto. C'è qualcosa che posso fare per te?,"インプラントハードウェアに不具合が見つかった フェリスがそれを修正してハードウェアの性能を 上げる為の後付け機能を手伝ってくれた。 何か必要かい?","전에 이식한 지구력 향상 칩에 오류가 좀 발견되었더군요. 그 오류를 잡은 최근 버전을 페리스랑 같이 만드는 참입니다. 아무튼, 원하시는 게 있나요?",Ik denk dat ik een storing in uw implantaathardware heb gevonden. Feris helpt me bij het ontwerpen van een retrofit die de snelheid van uw hardware een beetje zal verhogen. Kan ik iets voor u doen?,Jeg tror jeg har funnet en feil i implantatets maskinvare. Feris hjelper meg med å designe en oppgradering som vil ta seg av det og øke hastigheten på maskinvaren din litt. Er det noe jeg kan gjøre for deg?,"Chyba znalazłem błąd w @@ -10743,14 +11246,16 @@ Feris próbuje mi pomóc stworzyć ulepszenie do niego, które naprawi ten błąd i ulepszy trochę twoją szybkość. Czy coś jeszcze mogę -dla ciebie zrobić?",Acho que encontrei um defeito no seu implante. Feris está me ajudando a desenvolver um aprimoramento que resolverá esse problema e também vai aumentar um pouco a velocidade. Precisa de alguma coisa?,,Cred că am găsit o problemă în implantul tău. Feris mă ajută la implementarea unor îmbunătățiri care vor avea grijă de el și vor crește viteza puțin. E ceva ce pot face pentru tine?,"Кажется, я обнаружил неполадку в устройстве твоего импланта. Ферис помогает мне в разработке модификации, которая исправит её и немного ускорит работу устройства. Чем я могу тебе помочь?",,Sanırım implant donanımında bir hata buldum. Feris bunu halledecek ve donanımınızın hızını biraz artıracak bir güçlendirme tasarlamama yardım ediyor. Senin için yapabileceğim bir şey var mı? -Patch me up.,TXT_RPLY0_SCRIPT10_D21224_PATCH,,,,Potřebuju ošetřit.,Giv mig en besked.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Kasaa minut takaisin kokoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Verbind me met elkaar.,Lappe meg sammen.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Подлатай меня.,,Bana yama yap. -"There, as good as new I guess.",TXT_RYES0_SCRIPT10_D21224_THERE,,,,"Tak, a jsi jako nový.","Sådan, så god som ny, tror jeg.","So, fast wie neu, würde ich sagen.",,,"Ya está, como nuevo, supongo.",,"Kas niin, kuin uudenveroinen, luulisin.","Voilà, comme neuf, je crois.","Parancsolj, jobb mint új korában.","Ecco qua, come nuovo.",ほら、新鮮な気分だろう。,"자, 갓 태어난 것처럼 멀쩡할 겁니다!","Daar, zo goed als nieuw denk ik.","Sånn, så god som ny, antar jeg.",Proszę. Jak nowy. Chyba.,"Pronto. Novinho em folha, eu acho.",,"Gata, ca și nou bănuiesc.","Ну вот, прям как новенький.",,"İşte, yeni kadar iyi sanırım." -Retrofit?,TXT_RPLY1_SCRIPT10_D21224_RETRO,,,,Doplněk?,Eftermontering?,Nachrüstsatz?,,,¿Modernización?,,Jälkiasennuskappale?,Mise à jour de l'implant?,Áttervezni?,Ammodernamento?,後付け?,향상 칩 최근 버전?,Retrofit?,Oppgradering?,Ulepszenie?,Aprimoramento?,,Îmbunătățiri?,Модернизация?,,Güçlendirme mi? -"Ah, now we're cooking.",TXT_RYES1_SCRIPT10_D21224_AHNOW,,,,"Ahá, a už to jede.","Ah, nu er vi i gang.","Ah, jetzt bist du bei der Sache.",,,"Ah, ahora sí que sí.",,No nyt päästiin asiaan.,"Ah, on va s'amuser.",Ez a beszéd!,"Ah, ora ci siamo.",ああ、早速取り掛かろう。,이제야 좀 멋져 보이는군요.,"Ah, nu zijn we aan het koken.",Nå er vi i gang.,"Ah, no i to rozumiem.","Ah, agora sim.",,"Ah, acum discutăm.",Да. Мы славно поработали над ней.,,İşte şimdi pişiyoruz. -I'll have it as soon as Feris finishes it.,TXT_RNO1_SCRIPT10_D21224_ILLHA,,,,"Budu ho mít hned, co ho Feris dokončí.","Jeg får den, så snart Feris er færdig.","Ich gebe es dir, sobald Feris fertig ist.",,,"La tendré lista en cuanto -Feris la termine.",,"Asennan sen heti, kun Feris saa sen valmiiksi.",Je l'aurai dès que Feris l'a terminée.,"Meglesz egyből, amikor Feris végez vele.",Te lo farò avere non appena Feris lo finisce.,完了次第フェリスから私が送ろう。,페리스가 작업을 마치는 순간 보여드리겠습니다.,Ik heb het zodra Feris het klaar heeft.,Jeg får den så snart Feris er ferdig.,Będzie gotowe jak Feris je skończy.,Eu consigo ele assim que o Feris terminar.,,Îl voi avea imediat ce termină Feris cu el.,"Она будет у меня, как только Ферис закончит.",,Feris bitirir bitirmez getireceğim. -"How's it going? Man, some of this new technology is simply amazing. This should also help with your implant. I've got a couple ideas that I'm sketching out and I'll have them ready soon. What can I do for you, maybe some healing?",TXT_DLG_SCRIPT10_D22740_HOWSI,,,,"Jak se vede? Sakra, některé tychle nové technologie jsou prostě úžasné. Mělo by ti to taky pomoct s tvým implantátem. Mám už pár nápadů, teď je dávám na papír a brzy by měly být hotové. Co pro tebe mohu udělat, nějaké ošetření?","Hvordan går det? Mand, noget af denne nye teknologi er simpelthen fantastisk. Det burde også hjælpe med dit implantat. Jeg har et par idéer, som jeg skitserer, og jeg har dem snart klar. Hvad kan jeg gøre for dig? Måske noget healing?","Wie läuft es? Mann, einiges von dieser Technologie ist einfach erstaunlich. Da sollte auch mit deinem Implantat helfen. Ich habe da schon einige Ideen, die ich noch ausarbeiten muss, aber sie werden bald fertig sein. Was kann ich sonst für dich tun?",,,"¿Cómo te va? Tío, algunas de estas nuevas tecnologías son realmente sorprendentes. Esto debería ayudar con tu implante. Tengo unas cuantas ideas que voy planeando y las tendré listas pronto. ¿Qué puedo hacer por ti?, ¿tal vez una cura?","¿Cómo te va? Hombre, algunas de estas nuevas tecnologías son realmente sorprendentes. Esto debería ayudar con tu implante. Tengo unas cuantas ideas que voy planeando y las tendré listas pronto. ¿Qué puedo hacer por ti?, ¿tal vez una curación?","Kuinka sujuu? Ei hitsi, osa tästä uudesta teknologiasta on yksinkertaisesti hämmästyttävää. Sen pitäisi auttaa myös istutteesi kanssa. Luonnostelen tässä paria ideaa, jotka saan toteutettua pian. Mutta, miten voisin olla avuksi; sairaanhoidon tarpeessa kenties?","Comment ça va? La vache, cete nouvelle technologie est simplement géniale. Elle devrait également aider pour le dévelopment de votre implant. J'ai quelques idées que je suis en train de tester et elles devraient être bientôt prêtes. Que puis-je faire pour vous? Des soins, peut être?","Hogy ityeg? Némely új technológia egyszerűen csodálatos. Ez kicsit feljavítja az implantátumodat is ha minden igaz. Van pár ötletem amit még most jegyzetelek ki, de hamarosan meglesz. Node mit tehetek érted, esetleg valami gyógyítás?","Come ti va? Te lo devo dire, alcune di queste nuove tecnologie sono semplicemente fantastiche. Questo dovrebbe anche aiutarti con il tuo impianto. Ho un paio di idee che sto elaborando e dovrei averle pronte presto. Cosa posso fare nel frattempo, hai bisogno di cure?","調子はどうだ?この新技術は素晴らしいものだ。 +dla ciebie zrobić?",Acho que encontrei um defeito no seu implante. Feris está me ajudando a desenvolver um aprimoramento que resolverá esse problema e também vai aumentar um pouco a velocidade. Precisa de alguma coisa?,,Cred că am găsit o problemă în implantul tău. Feris mă ajută la implementarea unor îmbunătățiri care vor avea grijă de el și vor crește viteza puțin. E ceva ce pot face pentru tine?,"Кажется, я обнаружил неполадку в устройстве твоего импланта. Ферис помогает мне в разработке модификации, которая исправит её и немного ускорит работу устройства. Чем я могу тебе помочь?",,Jag tror att jag har hittat ett glapp i din implantathårdvara. Feris hjälper mig att utforma en eftermontering som kommer att ta hand om det och öka hastigheten på din hårdvara lite. Finns det något jag kan göra för dig?,Sanırım implant donanımında bir hata buldum. Feris bunu halledecek ve donanımınızın hızını biraz artıracak bir güçlendirme tasarlamama yardım ediyor. Senin için yapabileceğim bir şey var mı? +Patch me up.,TXT_RPLY0_SCRIPT10_D21224_PATCH,〃,,,Potřebuju ošetřit.,Giv mig en besked.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Kasaa minut takaisin kokoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Verbind me met elkaar.,Lappe meg sammen.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Подлатай меня.,,Laga mig.,Bana yama yap. +"There, as good as new I guess.",TXT_RYES0_SCRIPT10_D21224_THERE,〃,,,"Tak, a jsi jako nový.","Sådan, så god som ny, tror jeg.","So, fast wie neu, würde ich sagen.",,"Farite, kiel nova, mi kredas.","Ya está, como nuevo, supongo.",,"Kas niin, kuin uudenveroinen, luulisin.","Voilà, comme neuf, je crois.","Parancsolj, jobb mint új korában.","Ecco qua, come nuovo.",ほら、新鮮な気分だろう。,"자, 갓 태어난 것처럼 멀쩡할 겁니다!","Daar, zo goed als nieuw denk ik.","Sånn, så god som ny, antar jeg.",Proszę. Jak nowy. Chyba.,"Pronto. Novinho em folha, eu acho.",,"Gata, ca și nou bănuiesc.","Ну вот, прям как новенький.",,"Så där, så gott som ny antar jag.","İşte, yeni kadar iyi sanırım." +Retrofit?,TXT_RPLY1_SCRIPT10_D21224_RETRO,〃,,,Doplněk?,Eftermontering?,Nachrüstsatz?,,Ĉu modernigo?,¿Modernización?,,Jälkiasennuskappale?,Mise à jour de l'implant?,Áttervezni?,Ammodernamento?,後付け?,향상 칩 최근 버전?,Retrofit?,Oppgradering?,Ulepszenie?,Aprimoramento?,,Îmbunătățiri?,Модернизация?,,Eftermontering?,Güçlendirme mi? +"Ah, now we're cooking.",TXT_RYES1_SCRIPT10_D21224_AHNOW,〃 (during sad/bad ending),,,"Ahá, a už to jede.","Ah, nu er vi i gang.","Ah, jetzt bist du bei der Sache.",,"Ha, ĉi tio iĝas serioza.","Ah, ahora sí que sí.",,No nyt päästiin asiaan.,"Ah, on va s'amuser.",Ez a beszéd!,"Ah, ora ci siamo.",ああ、早速取り掛かろう。,이제야 좀 멋져 보이는군요.,"Ah, nu zijn we aan het koken.",Nå er vi i gang.,"Ah, no i to rozumiem.","Ah, agora sim.",,"Ah, acum discutăm.",Да. Мы славно поработали над ней.,,"Ah, nu börjar det bli spännande.",İşte şimdi pişiyoruz. +I'll have it as soon as Feris finishes it.,TXT_RNO1_SCRIPT10_D21224_ILLHA,〃,,,"Budu ho mít hned, co ho Feris dokončí.","Jeg får den, så snart Feris er færdig.","Ich gebe es dir, sobald Feris fertig ist.",,"Mi havos ĝin tuj +kiam Feriso finos.","La tendré lista en cuanto +Feris la termine.","La voy a tener lista +en cuanto Feris la termine.","Asennan sen heti, kun Feris saa sen valmiiksi.",Je l'aurai dès que Feris l'a terminée.,"Meglesz egyből, amikor Feris végez vele.",Te lo farò avere non appena Feris lo finisce.,完了次第フェリスから私が送ろう。,페리스가 작업을 마치는 순간 보여드리겠습니다.,Ik heb het zodra Feris het klaar heeft.,Jeg får den så snart Feris er ferdig.,Będzie gotowe jak Feris je skończy.,Eu consigo ele assim que o Feris terminar.,,Îl voi avea imediat ce termină Feris cu el.,"Она будет у меня, как только Ферис закончит.",,Jag har den så snart Feris är klar.,Feris bitirir bitirmez getireceğim. +"How's it going? Man, some of this new technology is simply amazing. This should also help with your implant. I've got a couple ideas that I'm sketching out and I'll have them ready soon. What can I do for you, maybe some healing?",TXT_DLG_SCRIPT10_D22740_HOWSI,〃 (three upgrades: Mission to kill the Loremaster with the Oracle alive).,,,"Jak se vede? Sakra, některé tychle nové technologie jsou prostě úžasné. Mělo by ti to taky pomoct s tvým implantátem. Mám už pár nápadů, teď je dávám na papír a brzy by měly být hotové. Co pro tebe mohu udělat, nějaké ošetření?","Hvordan går det? Mand, noget af denne nye teknologi er simpelthen fantastisk. Det burde også hjælpe med dit implantat. Jeg har et par idéer, som jeg skitserer, og jeg har dem snart klar. Hvad kan jeg gøre for dig? Måske noget healing?","Wie läuft es? Mann, einiges von dieser Technologie ist einfach erstaunlich. Da sollte auch mit deinem Implantat helfen. Ich habe da schon einige Ideen, die ich noch ausarbeiten muss, aber sie werden bald fertig sein. Was kann ich sonst für dich tun?",,"Kiel vi fartas? Ulo, kelkaj el ĉi tiuj novaj teknologioj estas nekredeblaj; ili devus helpi al via enplantaĵo. Mi havas kelkajn planatajn ideojn, kiuj baldaŭ estos pretaj. Kion mi povas fari por vi? Ĉu eble kuraci vin?","¿Cómo te va? Tío, algunas de estas nuevas tecnologías son realmente sorprendentes; deberían ayudar con tu implante. Tengo unas cuantas ideas que voy planeando y las tendré listas pronto. ¿Qué puedo hacer por ti?, ¿tal vez curarte?","¿Cómo te va? Hombre, algunas de estas nuevas tecnologías son realmente sorprendentes; deberían ayudar con tu implante. Tengo unas cuantas ideas que voy planeando y las voy a tener listas pronto. ¿Qué puedo hacer por ti?, ¿tal vez curarte?","Kuinka sujuu? Ei hitsi, osa tästä uudesta teknologiasta on yksinkertaisesti hämmästyttävää. Sen pitäisi auttaa myös istutteesi kanssa. Luonnostelen tässä paria ideaa, jotka saan toteutettua pian. Mutta, miten voisin olla avuksi; sairaanhoidon tarpeessa kenties?","Comment ça va? La vache, cete nouvelle technologie est simplement géniale. Elle devrait également aider pour le dévelopment de votre implant. J'ai quelques idées que je suis en train de tester et elles devraient être bientôt prêtes. Que puis-je faire pour vous? Des soins, peut être?","Hogy ityeg? Némely új technológia egyszerűen csodálatos. Ez kicsit feljavítja az implantátumodat is ha minden igaz. Van pár ötletem amit még most jegyzetelek ki, de hamarosan meglesz. Node mit tehetek érted, esetleg valami gyógyítás?","Come ti va? Te lo devo dire, alcune di queste nuove tecnologie sono semplicemente fantastiche. Questo dovrebbe anche aiutarti con il tuo impianto. Ho un paio di idee che sto elaborando e dovrei averle pronte presto. Cosa posso fare nel frattempo, hai bisogno di cure?","調子はどうだ?この新技術は素晴らしいものだ。 そちらのインプラントにも役立つ様な アイディアも幾つか思いついてあるぞ。 すぐ準備しよう。それとも治療か何か必要かな?","별일 없으시죠? 세상에나, 오더의 과학력은 세계 제일이군요! 이식한 칩이랑 추가 설치가 가능한데, 성능을 향상해줄 거에요. 현재 부품을 더 설계하고 있습니다. 만약 준비가 되면 불러줄게요. 아무튼, 치료가 필요하신가요?","Hoe gaat het? Man, sommige van deze nieuwe technologie is gewoonweg verbazingwekkend. Dit zou ook moeten helpen bij uw implantaat. Ik heb een paar ideeën die ik aan het schetsen ben en ik zal ze binnenkort klaar hebben. Wat kan ik voor je doen, misschien wat genezing?","Hvordan går det? Noe av denne nye teknologien er helt utrolig. Dette burde også hjelpe med implantatet ditt. Jeg har et par ideer som jeg skisserer, og de er snart klare. Hva kan jeg gjøre for deg, kanskje litt healing?","Jak się masz? Człowieku... Te nowe @@ -10759,13 +11264,14 @@ To powinno poprawić twój implant. Mam parę pomysłów w zanadrzu i niedługo postaram się je zrealizować. Co mogę dla ciebie zrobić? Może -trochę podleczyć?","Qual é a boa? Cara, essa tecnologia nova é simplesmente incrível. Isto também deve ajudar com o seu implante. Estou projetando umas idéias novas e logo mais devo ter elas prontas. Precisa de alguma coisa? Talvez cura?",,"Cum merge? Frate, noua tehnologie e pur și simplu uimitoare. Asta ar trebui să îți ajute și implantul. Am câteva idei pe hârtie și le voi pune în aplicare curând. Ce pot face pentru tine, poate să te bandajez?","Как дела? О, среди этих новых технологий есть просто изумительные! Их можно применить при усовершенствовании твоего импланта. Я сейчас воплощаю в жизнь парочку идей, и скоро всё будет готово. Чем я могу тебе помочь, лечением?",,"Nasıl gidiyor? Dostum, bu yeni teknolojinin bazıları tek kelimeyle inanılmaz. Bu implantına da yardımcı olacaktır. Taslağını çizdiğim birkaç fikir var, yakında hazır ederim. Senin için ne yapabilirim, belki biraz şifa?" -"Yes, heal me.",TXT_RPLY0_SCRIPT10_D22740_YESHE,,,,"Ano, ošetři mě.","Ja, helbrede mig.","Ja, mach mich gesund.",,,"Sí, cúrame.",,"Kyllä, paranna minut.","Oui, soignez-moi.","Igen, gyógyíts fel.","Sì, curami.",ああ、治してくれ。,네. 치료해주세요.,"Ja, genees me.","Ja, helbrede meg.","Tak, ulecz mnie.","Sim, me cure.",,"Da, bandajează-mă.","Да, полечи меня.",,"Evet, iyileştir beni." -"All right, here you go.",TXT_RYES0_SCRIPT10_D22740_ALLRI,,,,"Dobře, to by bylo.","Okay, værsgo.",Alles klar soweit.,,,"Muy bien, ya está.",,"Hyvä on, tästä se lähtee.","Très bien, bous pouvez y aller.","Rendben, parancsolj.","Va bene, ecco fatto.",了解、始めましょう。,더욱 더 건강하게 치료했습니다.,"Oké, alsjeblieft.","Greit, vær så god.",Proszę bardzo.,"Ok, pronto.",,Gata.,Хорошо. Уже готово.,,"Pekala, al bakalım." -How about that new tech?,TXT_RPLY1_SCRIPT10_D22740_HOWAB,,,,Co ta nová technologie?,Hvad med den nye teknologi?,Was ist mit der neuen Technologie?,,,¿Qué tal la nueva tecnología?,,Miten olisi se uusi teknologia?,Quoi de nouveau pour cette technologie?,Mi újság azzal az új technológiával?,E riguardo queste nuove technologie?,その新しい技術はどうだ?,세계 제일의 부품은 어떻습니까?,Hoe zit het met die nieuwe technologie?,Hva med den nye teknologien?,Co z tymi nowymi technologiami?,Me fale sobre essa nova tecnologia.,,Ce zici de tehnologia aceea nouă?,Как там с новыми технологиями?,,Şu yeni teknolojiye ne dersin? -Let me know how this works.,TXT_RYES1_SCRIPT10_D22740_LETME,,,,"Dej mi vědět, jak to funguje.","Lad mig vide, hvordan den virker.","Erklär mir, wie es funktioniert.",,,Cuéntame que tal funciona.,,"Kerro sitten, miten se toimii.",Dites-moi si ça fonctionne.,"Majd mondd meg, hogy hogyan szuperál.",Fammi sapere come funziona.,これでどんな調子か教えてくれ。,잘 작동되면 알려주시길!,Laat me weten hoe dit werkt.,Fortell meg hvordan den virker.,Daj znać czy działa.,Me conte como funciona.,,Să-mi spui cum funcționează asta.,"Дай мне знать, если будут неполадки.",,Nasıl çalıştığını bana anlat. -I'm not done designing it yet.,TXT_RNO1_SCRIPT10_D22740_IMNOT,,,,Ještě s ní nejsem hotový.,Jeg er ikke færdig med at designe den endnu.,Ich bin noch nicht fertig damit.,,,Aún no he terminado de diseñarla.,,Se on vielä kehitteillä.,Je n'ai pas fini mon concept pour l'instant.,Még nem végeztem a tervezéssel.,Non ho ancora finito il progetto.,まだ完成していない。,설계가 아직 끝나지 않았어요.,Ik ben nog niet klaar met het ontwerpen ervan.,Jeg er ikke ferdig med å designe den ennå.,Skończyłem już projektować.,Ainda não terminei de desenvolvê-la.,,Încă nu am terminat să o construiesc.,Я ещё не закончил с ними.,,Henüz tasarlamayı bitirmedim. -"Back again, don't you ever tire of this? I've got some good news, Feris found a way to increase the output of your implant. He gave the specs to me and I'm trying to get it to blend with your physiology. I'm force growing some tissue, totally new stuff here, I hope it takes. Do you need healing?",TXT_DLG_SCRIPT10_D24256_BACKA,,,,"Zase zpátky, nezmáhá tě to? Mám pro tebe dobrou zprávu, Feris našel způsob, jak zvýšit výkon tvého implantátu. Dal mi specifikace a snažím se je teď seřídit s tvou fyziologií. Nechávám růst nějaké tkáně, je to úplně nová technologie, snad to zabere. Potřebuješ ošetřit?","Tilbage igen, bliver du aldrig træt af det her? Jeg har gode nyheder. Feris har fundet en måde at øge dit implantats effekt på. Han gav mig specifikationerne, og jeg forsøger at få det til at passe ind i din fysiologi. Jeg tvinger noget væv til at vokse, helt nye ting her, jeg håber, det virker. Har du brug for healing?","Schon wieder zurück, wird das nicht langweilig? Ivh habe gute Nachrichten. Feris hat eine Methode gefunden, um dein Implantat zu optimieren. Er hat mir die Spezifikationen gegeben und ich versuche, sie mit deiner Physiologie zu kombinieren. Ich lasse hier etwas Gewebe wachsen, völlig neues Zeug. Brauchst du medizinische Versorgung?",,,"¿De vuelta otra vez?, ¿nunca te cansas de esto? Tengo buenas noticias, Feris ha encontrado una forma de potenciar la salida de tu implante. Me ha dado las especificaciones y estoy intentando que se mezcle con tu fisiología. Estoy forzando el crecimiento de algunos tejidos, totalmente nuevos, espero que sirva. ¿Necesitas una cura?",,"Täällä taas? Eikö tämä ala jo kyllästyttää? No, minulla on hyviä uutisia: Feris keksi keinon parantaa istutteesi tehoa. Hän antoi minulle tekniset määritelmät, jotka yritän sovittaa sinun fysiologiaasi. Tehokasvatan tässä vähän kudosta; ihan huipputekniikasta siis kyse. Toivottavasti toimii. Tarvitsetko sairaanhoitoa?","Déjà de retour? Vous n'êtes jamais fatigué, hein? J'ai de bonnes nouvelles. Feris à trouvé un moyen d'augementer la capacité de votre implant. Il m'a donné les spécifications et j'essaie de les faire correspondre à votre physiologie. Je suis en train de forcer la croissance de tissus, quelque chose de totalement nouveau. J'espère que ça fonctionnera. Vous avez besoin de soins?","Máris visszajöttél...nem fáradtál még bele? Van amúgy jó hírem, Feris kitalálta, hogyan növeljük az implantátum hatékonyságát. Ide adta a specifikációkat, és most próbálom a testformádra szabni. Épp próbálok mesterségesen szövetet növeszteni, elég új ez nekem, remélem működni fog. Kell valami gyógyítás?","Di nuovo qua, non ti stanchi mai? Ho delle buone notizie, Feris ha trovato un modo per migliorare la performance del tuo impianto. Mi ha dato le schematiche, adesso devo adattarle alla tua fisiologia. Sto creando del nuovo tessuto qua nel laboratorio, spero vada bene. Comunque, hai bisogno di cure?","戻ったか、まだ疲れてないか?なら幾らか +trochę podleczyć?","Qual é a boa? Cara, essa tecnologia nova é simplesmente incrível. Isto também deve ajudar com o seu implante. Estou projetando umas idéias novas e logo mais devo ter elas prontas. Precisa de alguma coisa? Talvez cura?",,"Cum merge? Frate, noua tehnologie e pur și simplu uimitoare. Asta ar trebui să îți ajute și implantul. Am câteva idei pe hârtie și le voi pune în aplicare curând. Ce pot face pentru tine, poate să te bandajez?","Как дела? О, среди этих новых технологий есть просто изумительные! Их можно применить при усовершенствовании твоего импланта. Я сейчас воплощаю в жизнь парочку идей, и скоро всё будет готово. Чем я могу тебе помочь, лечением?",,"Hur går det? En del av den här nya tekniken är helt enkelt fantastisk. Det här borde också hjälpa dig med ditt implantat. Jag har några idéer som jag skissar på och jag har dem klara snart. Vad kan jag göra för dig, kanske lite healing?","Nasıl gidiyor? Dostum, bu yeni teknolojinin bazıları tek kelimeyle inanılmaz. Bu implantına da yardımcı olacaktır. Taslağını çizdiğim birkaç fikir var, yakında hazır ederim. Senin için ne yapabilirim, belki biraz şifa?" +"Yes, heal me.",TXT_RPLY0_SCRIPT10_D22740_YESHE,〃,,,"Ano, ošetři mě.","Ja, helbrede mig.","Ja, mach mich gesund.",,"Jes, kuracu min.","Sí, cúrame.",,"Kyllä, paranna minut.","Oui, soignez-moi.","Igen, gyógyíts fel.","Sì, curami.",ああ、治してくれ。,네. 치료해주세요.,"Ja, genees me.","Ja, helbrede meg.","Tak, ulecz mnie.","Sim, me cure.",,"Da, bandajează-mă.","Да, полечи меня.",,"Ja, bota mig.","Evet, iyileştir beni." +"All right, here you go.",TXT_RYES0_SCRIPT10_D22740_ALLRI,〃,,,"Dobře, to by bylo.","Okay, værsgo.",Alles klar soweit.,,"Bone, farite.","Muy bien, ya está.",,"Hyvä on, tästä se lähtee.","Très bien, bous pouvez y aller.","Rendben, parancsolj.","Va bene, ecco fatto.",了解、始めましょう。,더욱 더 건강하게 치료했습니다.,"Oké, alsjeblieft.","Greit, vær så god.",Proszę bardzo.,"Ok, pronto.",,Gata.,Хорошо. Уже готово.,,"Okej, varsågod.","Pekala, al bakalım." +How about that new tech?,TXT_RPLY1_SCRIPT10_D22740_HOWAB,〃,,,Co ta nová technologie?,Hvad med den nye teknologi?,Was ist mit der neuen Technologie?,,Kio pri la nova teknologio?,¿Qué tal la nueva tecnología?,,Miten olisi se uusi teknologia?,Quoi de nouveau pour cette technologie?,Mi újság azzal az új technológiával?,E riguardo queste nuove technologie?,その新しい技術はどうだ?,세계 제일의 부품은 어떻습니까?,Hoe zit het met die nieuwe technologie?,Hva med den nye teknologien?,Co z tymi nowymi technologiami?,Me fale sobre essa nova tecnologia.,,Ce zici de tehnologia aceea nouă?,Как там с новыми технологиями?,,Vad sägs om den nya tekniken?,Şu yeni teknolojiye ne dersin? +Let me know how this works.,TXT_RYES1_SCRIPT10_D22740_LETME,〃,,,"Dej mi vědět, jak to funguje.","Lad mig vide, hvordan den virker.","Erklär mir, wie es funktioniert.",,Sciigu min vi mem.,Cuéntame que tal funciona.,,"Kerro sitten, miten se toimii.",Dites-moi si ça fonctionne.,"Majd mondd meg, hogy hogyan szuperál.",Fammi sapere come funziona.,これでどんな調子か教えてくれ。,잘 작동되면 알려주시길!,Laat me weten hoe dit werkt.,Fortell meg hvordan den virker.,Daj znać czy działa.,Me conte como funciona.,,Să-mi spui cum funcționează asta.,"Дай мне знать, если будут неполадки.",,Låt mig veta hur den fungerar.,Nasıl çalıştığını bana anlat. +I'm not done designing it yet.,TXT_RNO1_SCRIPT10_D22740_IMNOT,〃,,,Ještě s ní nejsem hotový.,Jeg er ikke færdig med at designe den endnu.,Ich bin noch nicht fertig damit.,,"Mi ankoraŭ +ne finis dezajni ĝin.",Aún no termino de diseñarla.,,Se on vielä kehitteillä.,Je n'ai pas fini mon concept pour l'instant.,Még nem végeztem a tervezéssel.,Non ho ancora finito il progetto.,まだ完成していない。,설계가 아직 끝나지 않았어요.,Ik ben nog niet klaar met het ontwerpen ervan.,Jeg er ikke ferdig med å designe den ennå.,Skończyłem już projektować.,Ainda não terminei de desenvolvê-la.,,Încă nu am terminat să o construiesc.,Я ещё не закончил с ними.,,Jag är inte klar med designen än.,Henüz tasarlamayı bitirmedim. +"Back again, don't you ever tire of this? I've got some good news, Feris found a way to increase the output of your implant. He gave the specs to me and I'm trying to get it to blend with your physiology. I'm force growing some tissue, totally new stuff here, I hope it takes. Do you need healing?",TXT_DLG_SCRIPT10_D24256_BACKA,〃 (four upgrades).,,,"Zase zpátky, nezmáhá tě to? Mám pro tebe dobrou zprávu, Feris našel způsob, jak zvýšit výkon tvého implantátu. Dal mi specifikace a snažím se je teď seřídit s tvou fyziologií. Nechávám růst nějaké tkáně, je to úplně nová technologie, snad to zabere. Potřebuješ ošetřit?","Tilbage igen, bliver du aldrig træt af det her? Jeg har gode nyheder. Feris har fundet en måde at øge dit implantats effekt på. Han gav mig specifikationerne, og jeg forsøger at få det til at passe ind i din fysiologi. Jeg tvinger noget væv til at vokse, helt nye ting her, jeg håber, det virker. Har du brug for healing?","Schon wieder zurück, wird das nicht langweilig? Ivh habe gute Nachrichten. Feris hat eine Methode gefunden, um dein Implantat zu optimieren. Er hat mir die Spezifikationen gegeben und ich versuche, sie mit deiner Physiologie zu kombinieren. Ich lasse hier etwas Gewebe wachsen, völlig neues Zeug. Brauchst du medizinische Versorgung?",,"Ĉu denove ĉi tie? Ĉu vi ne estas laca pri ĉi tio? Mi havas bonajn novaĵojn: Feriso trovis manieron pliigi la eligon de via enplantaĵo; li donis al mi la specifojn kaj mi provas miksi ĝin kun via fiziologio. Mi forcas kelkajn histojn, io tute nova, tio espereble prosperos. Ĉu vi bezonas kuraci vin?","¿De vuelta otra vez?, ¿no te cansas de esto? Tengo buenas noticias: Feris ha encontrado una forma de potenciar la salida de tu implante; me ha dado las especificaciones y estoy intentando mezclarlo con tu fisiología. Estoy forzando el crecimiento de algunos tejidos, algo totalmente nuevo, a ver si sirve. ¿Necesitas curarte?","¿De vuelta otra vez?, ¿no te cansas de esto? Tengo buenas noticias: Feris encontró una forma de potenciar la salida de tu implante; me dio las especificaciones y estoy tratando de mezclarlo con tu fisiología. Estoy forzando el crecimiento de algunos tejidos, algo totalmente nuevo, a ver si sirve. ¿Necesitas curarte?","Täällä taas? Eikö tämä ala jo kyllästyttää? No, minulla on hyviä uutisia: Feris keksi keinon parantaa istutteesi tehoa. Hän antoi minulle tekniset määritelmät, jotka yritän sovittaa sinun fysiologiaasi. Tehokasvatan tässä vähän kudosta; ihan huipputekniikasta siis kyse. Toivottavasti toimii. Tarvitsetko sairaanhoitoa?","Déjà de retour? Vous n'êtes jamais fatigué, hein? J'ai de bonnes nouvelles. Feris à trouvé un moyen d'augementer la capacité de votre implant. Il m'a donné les spécifications et j'essaie de les faire correspondre à votre physiologie. Je suis en train de forcer la croissance de tissus, quelque chose de totalement nouveau. J'espère que ça fonctionnera. Vous avez besoin de soins?","Máris visszajöttél...nem fáradtál még bele? Van amúgy jó hírem, Feris kitalálta, hogyan növeljük az implantátum hatékonyságát. Ide adta a specifikációkat, és most próbálom a testformádra szabni. Épp próbálok mesterségesen szövetet növeszteni, elég új ez nekem, remélem működni fog. Kell valami gyógyítás?","Di nuovo qua, non ti stanchi mai? Ho delle buone notizie, Feris ha trovato un modo per migliorare la performance del tuo impianto. Mi ha dato le schematiche, adesso devo adattarle alla tua fisiologia. Sto creando del nuovo tessuto qua nel laboratorio, spero vada bene. Comunque, hai bisogno di cure?","戻ったか、まだ疲れてないか?なら幾らか 良いニュースが届いた、フェリスが君の インプラント機能を増幅させる方法を見つけた。 彼がそのスペックを見せてくれたが、 @@ -10779,13 +11285,18 @@ staram się dostosować go do twojej fizjologii. Wymuszam tworzenie nowej tkanki. To zupełnie nowa technologia. Mam nadzieję, że -zadziała. Potrzebujesz leczenia?","De volta mais uma vez. Você não se cansa disso? Tenho boas novas, Feris acho um jeito de aumentar o rendimento do seu implante. Ele me passou as especificações e estou tentando fazer ele se mesclar com a sua fisiologia. Estou criando tecidos novos, novidade total. Espero que sirva bem. Precisa de cura?",,"Te-ai întors din nou, nu te plictisești niciodată? Am niște vești bune, Feris a descoperit o metodă de a îți îmbunătății implantul. Mi-a dat specificațiile și acum încerc să îl combin cu fizicul tău. Cresc forțat niște țesut, ceva complet nou. Ai nevoie de asistență?","Ты снова ранен? Тебе самому ещё не надоело? У меня для тебя хорошие новости: Ферис нашёл способ увеличить эффективность твоего импланта. Он дал мне схемы, и я пытаюсь подогнать имплант под твою физиологию. Я сейчас выращиваю кое-какие ткани. Раньше я никогда этого не делал, но надеюсь, что это сработает. Итак, тебе нужно лечение?",,"Yine başladık, bundan hiç bıkmadın mı? İyi haberlerim var. Feris implantının gücünü arttırmanın bir yolunu buldu. Özellikleri bana verdi ve ben de senin fizyolojinle uyumlu hale getirmeye çalışıyorum. Biraz doku büyütmeye zorluyorum, tamamen yeni şeyler, umarım tutar. İyileşmeye ihtiyacın var mı?" -"Yes, heal me.",TXT_RPLY0_SCRIPT10_D24256_YESHE,,,,"Ano, ošetři mě.","Ja, helbrede mig.","Ja, mach mich gesund.",,,"Sí, cúrame.",,"Kyllä, paranna minut.","Oui, soignez-moi.","Igen, gyógyíts fel.","Sì, curami.",ああ、治してくれ。,네. 치료해주세요.,"Ja, genees me.","Ja, helbred meg.","Tak, ulecz mnie.","Sim, me cure.",,"Da, bandajează-mă.","Да, полечи меня.",,"Evet, iyileştir beni." -"Done, now take care of yourself.",TXT_RYES0_SCRIPT10_D24256_DONEN,,,,"Hotovo, dávej na sebe pozor.",Færdig. Pas nu på dig selv.,"Alles klar, und nun pass auf dich auf.",,,"Hecho, ahora ve con cuidado.",,Noin. Pidä itsestäsi huoli.,"Fini, faites attention à vous.","Kész is, vigyázz magadra.","Fatto, abbi cura di te.",完了した、御気を付けて。,치료 끝. 이제 가까이서 불장난하지 마시길!,"Klaar, zorg nu voor jezelf.","Ferdig, ta vare på deg selv.",Gotowe. Uważaj na siebie.,Pronto. Agora vê se toma cuidado.,,"Gata, acum ai grijă de tine.",Сделано. Береги себя.,,"Bitti, şimdi kendine iyi bak." -When will you be done?,TXT_RPLY1_SCRIPT10_D24256_WHENW,,,,Kdy s tím budeš hotov?,Hvornår er du færdig?,Wann wird es fertig sein?,,,¿Cuándo habrás terminado?,,Milloin kudos on valmis?,Quand aurez-vous fini?,Mikor leszel kész?,Quando avrai finito?,いつ増幅できる?,칩 조정이 언제 끝나는지요?,Wanneer ben je klaar?,Når er du ferdig?,Kiedy skończysz?,Quando você vai terminar?,,Când vei fi gata?,Когда он будет готов?,,İşin ne zaman bitecek? -"Now. Hey great, it worked!",TXT_RYES1_SCRIPT10_D24256_NOWHE,,,,"Teď. No ne, funguje to skvěle!","Når du er færdig? Nu. Hej, godt, det virkede!","Oh, klasse. Es funktioniert.",,,"Ahora. Mira que bien, ¡Ha funcionado!",,"Nyt. Hei, sehän toimii; hienoa!","Maintenant. Hé, super, ça à fonctionné!","Épp most. Marha jó, működik!","Adesso. Ehi, fantastico, ha funzionato!",すぐにでも。素晴らしい、上手くいった!,"세상에나, 정말로 작동하는군요!","Nu. Hé, geweldig, het heeft gewerkt!","Nå. Flott, det virket!",Już. Hej! Udało się! Działa!,"Agora. Opa, beleza! Funcionou!",,"Acum. Hei grozav, a mers!","Секунду. Отлично, он работает!",,"Şimdi. Hey harika, işe yaradı!" -I'm waiting on the tissue to finish its growth cycle.,TXT_RNO1_SCRIPT10_D24256_IMWAI,,,,"Čekám, než dorostou ty tkáně.","Jeg venter på, at vævet afslutter sin vækstcyklus.","Ich muss warten, bis das Gewebe fertig gewachsen ist. ",,,Estoy esperando a que los tejidos terminen su ciclo de desarrollo.,,Odotan kudoksen kasvusyklin päättymistä.,J'attends que le tissu ait fini son cycle de croissance.,"Épp arra várok, hogy a szövet a növekedési ütemet elérje.",Sto aspettando che i tessuti finiscano la crescita per questo ciclo.,生体組織が成長しきるまで待つんだ。,조직이 다 자라날 때까지 기다리는 중입니다.,Ik wacht op het weefsel om de groeicyclus af te ronden.,Jeg venter på at vevet skal fullføre vekstsyklusen.,Czekam aż cykl odrastania tkanki się skończy.,Estou esperando que o tecido termine seu ciclo de desenvolvimento.,,Aștept ca țesutul să își continue ciclul de dezvoltare.,Подожди. Я жду коца цикла роста клеток ткани.,,Dokunun büyüme döngüsünü tamamlamasını bekliyorum. -"Well, I'm back up to my old tricks again, I'm still working on your implants. Did you know that Macil has now authorized them for everyone? No, huh? It's because you turned out so well. Anything I can do for you?",TXT_DLG_SCRIPT10_D25772_WELLI,,,,"Zase dělám to, co mi jde nejlépe, pracuju na tvých implantátech. Slyšel jsi, že Macil povolil jejich použití na všech vojácích? Ne? Je to protože u tebe fungují tak dobře. Můžu pro tebe něco udělat?","Nå, jeg er tilbage til mine gamle tricks igen, jeg arbejder stadig på dine implantater. Vidste du, at Macil nu har godkendt dem til alle? Nej, hva'? Det er fordi du blev så godt. Er der noget, jeg kan gøre for dig?","Ich arbeite immer noch an deinem Implantat. Wußtest du schon, dass Macil sie für alle autorisiert hat? Nein, was? Hat er getan, weil es bei dir so gut funktioniert hat. Kann ich sonst was für dich tun?",,,"Bueno, vuelvo a las andadas otra vez, sigo trabajando en tus implantes. ¿Sabías que Macil ahora los ha autorizado para todos? No, ¿eh? Es por lo bien que te ha salido. ¿Algo que pueda hacer por ti?",,"Olen taas palannut kyhäilyjeni pariin; työstän edelleenkin istutteitasi. Tiesitkö muuten, että Macil on valtuuttanut ne nyt kaikille? Ai et? No, ihan sen takia, kun sinä satuit onnistumaan niin hyvin. Mutta, mitä saisi olla?","Eh bien, je suis de retour à mes vieux violons, je suis toujours en train de travailler sur vos implants. Vous saviez que Macil les a autorisé pour tous les soldats? Non, hein? C'est parce que vous vous en êtes tellement bien sorti. Que puis-je faire pour vous?","Visszatértem a régi kerékvágásba, és újból fejlesztgetem az implantátumodat. Tudtad, hogy Macil mindenki számára engedélyezte őket? Nem, mi? Azért mert a Te esetedben nagyon jól bevállt. Segíthetek még neked valamiben?","Ebbene, sono di nuovo alle prese con questi impianti, inclusi i tuoi. Lo sapevi che Macil adesso li ha autorizzati per tutti? No, eh? È poiché sei venuto fuori così bene. Posso fare qualcosa per te?","さて、私は古い技術をバックアップして、 +zadziała. Potrzebujesz leczenia?","De volta mais uma vez. Você não se cansa disso? Tenho boas novas, Feris acho um jeito de aumentar o rendimento do seu implante. Ele me passou as especificações e estou tentando fazer ele se mesclar com a sua fisiologia. Estou criando tecidos novos, novidade total. Espero que sirva bem. Precisa de cura?",,"Te-ai întors din nou, nu te plictisești niciodată? Am niște vești bune, Feris a descoperit o metodă de a îți îmbunătății implantul. Mi-a dat specificațiile și acum încerc să îl combin cu fizicul tău. Cresc forțat niște țesut, ceva complet nou. Ai nevoie de asistență?","Ты снова ранен? Тебе самому ещё не надоело? У меня для тебя хорошие новости: Ферис нашёл способ увеличить эффективность твоего импланта. Он дал мне схемы, и я пытаюсь подогнать имплант под твою физиологию. Я сейчас выращиваю кое-какие ткани. Раньше я никогда этого не делал, но надеюсь, что это сработает. Итак, тебе нужно лечение?",,"Tillbaka igen, tröttnar du aldrig på det här? Jag har goda nyheter, Feris har hittat ett sätt att öka effekten av ditt implantat. Han gav specifikationerna till mig och jag försöker få det att smälta in i din fysiologi. Jag tvångsodlar lite vävnad, helt nya saker här, jag hoppas att det fungerar. Behöver du läkning?","Yine başladık, bundan hiç bıkmadın mı? İyi haberlerim var. Feris implantının gücünü arttırmanın bir yolunu buldu. Özellikleri bana verdi ve ben de senin fizyolojinle uyumlu hale getirmeye çalışıyorum. Biraz doku büyütmeye zorluyorum, tamamen yeni şeyler, umarım tutar. İyileşmeye ihtiyacın var mı?" +"Yes, heal me.",TXT_RPLY0_SCRIPT10_D24256_YESHE,〃,,,"Ano, ošetři mě.","Ja, helbrede mig.","Ja, mach mich gesund.",,"Jes, kuracu min.","Sí, cúrame.",,"Kyllä, paranna minut.","Oui, soignez-moi.","Igen, gyógyíts fel.","Sì, curami.",ああ、治してくれ。,네. 치료해주세요.,"Ja, genees me.","Ja, helbred meg.","Tak, ulecz mnie.","Sim, me cure.",,"Da, bandajează-mă.","Да, полечи меня.",,"Ja, bota mig.","Evet, iyileştir beni." +"Done, now take care of yourself.",TXT_RYES0_SCRIPT10_D24256_DONEN,〃,,,"Hotovo, dávej na sebe pozor.",Færdig. Pas nu på dig selv.,"Alles klar, und nun pass auf dich auf.",,"Farite, nun estu singarda.","Hecho, ahora ve con cuidado.",,Noin. Pidä itsestäsi huoli.,"Fini, faites attention à vous.","Kész is, vigyázz magadra.","Fatto, abbi cura di te.",完了した、御気を付けて。,치료 끝. 이제 가까이서 불장난하지 마시길!,"Klaar, zorg nu voor jezelf.","Ferdig, ta vare på deg selv.",Gotowe. Uważaj na siebie.,Pronto. Agora vê se toma cuidado.,,"Gata, acum ai grijă de tine.",Сделано. Береги себя.,,"Klart, ta hand om dig själv nu.","Bitti, şimdi kendine iyi bak." +When will you be done?,TXT_RPLY1_SCRIPT10_D24256_WHENW,〃,,,Kdy s tím budeš hotov?,Hvornår er du færdig?,Wann wird es fertig sein?,,Kiam vi finos?,¿Cuándo habrás terminado?,,Milloin kudos on valmis?,Quand aurez-vous fini?,Mikor leszel kész?,Quando avrai finito?,いつ増幅できる?,칩 조정이 언제 끝나는지요?,Wanneer ben je klaar?,Når er du ferdig?,Kiedy skończysz?,Quando você vai terminar?,,Când vei fi gata?,Когда он будет готов?,,När är du klar?,İşin ne zaman bitecek? +"Now. Hey great, it worked!",TXT_RYES1_SCRIPT10_D24256_NOWHE,〃,,,"Teď. No ne, funguje to skvěle!","Når du er færdig? Nu. Hej, godt, det virkede!","Oh, klasse. Es funktioniert.",,"Nun. Bonege, +ĝi funkciis!","Ahora. Mira qué bien, +¡ha funcionado!","Ahora. Mira qué bien, +¡funcionó!","Nyt. Hei, sehän toimii; hienoa!","Maintenant. Hé, super, ça à fonctionné!","Épp most. Marha jó, működik!","Adesso. Ehi, fantastico, ha funzionato!",すぐにでも。素晴らしい、上手くいった!,"세상에나, 정말로 작동하는군요!","Nu. Hé, geweldig, het heeft gewerkt!","Nå. Flott, det virket!",Już. Hej! Udało się! Działa!,"Agora. Opa, beleza! Funcionou!",,"Acum. Hei grozav, a mers!","Секунду. Отлично, он работает!",,"Nu. Bra, det fungerade!","Şimdi. Hey harika, işe yaradı!" +I'm waiting on the tissue to finish its growth cycle.,TXT_RNO1_SCRIPT10_D24256_IMWAI,〃,,,"Čekám, než dorostou ty tkáně.","Jeg venter på, at vævet afslutter sin vækstcyklus.","Ich muss warten, bis das Gewebe fertig gewachsen ist. ",,"Mi atendas, ke la disvolviĝa +ciklo de la histoj finiĝos.","Estoy esperando a que los tejidos +terminen su ciclo de desarrollo.",,Odotan kudoksen kasvusyklin päättymistä.,J'attends que le tissu ait fini son cycle de croissance.,"Épp arra várok, hogy a szövet a növekedési ütemet elérje.",Sto aspettando che i tessuti finiscano la crescita per questo ciclo.,生体組織が成長しきるまで待つんだ。,조직이 다 자라날 때까지 기다리는 중입니다.,Ik wacht op het weefsel om de groeicyclus af te ronden.,Jeg venter på at vevet skal fullføre vekstsyklusen.,Czekam aż cykl odrastania tkanki się skończy.,Estou esperando que o tecido termine seu ciclo de desenvolvimento.,,Aștept ca țesutul să își continue ciclul de dezvoltare.,Подожди. Я жду коца цикла роста клеток ткани.,,Jag väntar på att vävnaden ska avsluta sin tillväxtcykel.,Dokunun büyüme döngüsünü tamamlamasını bekliyorum. +"Well, I'm back up to my old tricks again, I'm still working on your implants. Did you know that Macil has now authorized them for everyone? No, huh? It's because you turned out so well. Anything I can do for you?",TXT_DLG_SCRIPT10_D25772_WELLI,〃 (five upgrades).,,,"Zase dělám to, co mi jde nejlépe, pracuju na tvých implantátech. Slyšel jsi, že Macil povolil jejich použití na všech vojácích? Ne? Je to protože u tebe fungují tak dobře. Můžu pro tebe něco udělat?","Nå, jeg er tilbage til mine gamle tricks igen, jeg arbejder stadig på dine implantater. Vidste du, at Macil nu har godkendt dem til alle? Nej, hva'? Det er fordi du blev så godt. Er der noget, jeg kan gøre for dig?","Ich arbeite immer noch an deinem Implantat. Wußtest du schon, dass Macil sie für alle autorisiert hat? Nein, was? Hat er getan, weil es bei dir so gut funktioniert hat. Kann ich sonst was für dich tun?",,"Nu, mi refalas miajn malnovajn trompojn: mi ankoraŭ prilaboras viajn enplantaĵojn. Ĉu vi sciiĝis, ke Macil nun rajtigis ilian uzadon al ĉiuj? Ne, ĉu? Danke al viaj bonegaj rezultoj. Ĉu mi povas fari ion por vi?","Bueno, vuelvo a las andadas otra vez: sigo trabajando en tus implantes. ¿Sabías que Macil ahora los ha autorizado para todos? No, ¿eh? Es por lo bien que te ha salido. ¿Algo que pueda hacer por ti?","Bueno, vuelvo a las andadas otra vez: sigo trabajando en tus implantes. ¿Sabías que Macil ahora los autorizó para todos? No, ¿eh? Es por lo bien que te ha salido. ¿Algo que pueda hacer por ti?","Olen taas palannut kyhäilyjeni pariin; työstän edelleenkin istutteitasi. Tiesitkö muuten, että Macil on valtuuttanut ne nyt kaikille? Ai et? No, ihan sen takia, kun sinä satuit onnistumaan niin hyvin. Mutta, mitä saisi olla?","Eh bien, je suis de retour à mes vieux violons, je suis toujours en train de travailler sur vos implants. Vous saviez que Macil les a autorisé pour tous les soldats? Non, hein? C'est parce que vous vous en êtes tellement bien sorti. Que puis-je faire pour vous?","Visszatértem a régi kerékvágásba, és újból fejlesztgetem az implantátumodat. Tudtad, hogy Macil mindenki számára engedélyezte őket? Nem, mi? Azért mert a Te esetedben nagyon jól bevállt. Segíthetek még neked valamiben?","Ebbene, sono di nuovo alle prese con questi impianti, inclusi i tuoi. Lo sapevi che Macil adesso li ha autorizzati per tutti? No, eh? È poiché sei venuto fuori così bene. Posso fare qualcosa per te?","さて、私は古い技術をバックアップして、 インプラントに更なる取り組みを試している。 マシルがそれを全員に着けるのを承認したのは 聞いたか?まだ?君が上手くやってくれたからな。 @@ -10796,13 +11307,19 @@ Macil udostępnił je dla wszystkich? Nie wiesz? Wszystko dzięki temu, że sobie poradziłeś. Mogę coś jeszcze dla ciebie zrobić? -","Bem, estou de volta aos meus velhos truques novamente. Ainda estou trabalhando nos seus implantes. Você sabia que Macil os autorizou pra todo mundo? Ah não? É porque eles funcionaram muito bem em você. Precisa de alguma coisa?",,"Păi, m-am întors la treburile mele vechi, încă lucrez la implanturile tale. Știi că Macil a vrut să le autorizeze pentru toată lumea? Nu, așa-i? E din cauză că ai ieșit prea bine. Pot face ceva pentru tine?","Я снова вернулся к старым занятиям и по-прежнему работаю над твоим имплантом. Ты знаешь, что Мэйсил теперь всем разрешил использовать импланты? Нет? Это потому, что ты так хорошо показал себя. Могу я чем-нибудь тебе помочь?",,"Yine eski numaralarıma döndüm. Hâlâ implantların üzerinde çalışıyorum. Macil'in artık herkes için onay verdiğini biliyor muydun? Hayır, ha? Bu kadar iyi olduğun için. Senin için yapabileceğim bir şey var mı?" -Help me out here.,TXT_RPLY0_SCRIPT10_D25772_HELPM,,,,Pomoz mi.,Hjælp mig lige her.,Hilf mir mal.,,,Ayúdame.,,Autatko vähän.,Aidez moi.,Segíts nekem egy kicsit.,Aiutami.,ここで治してくれ。,나 좀 치료해줘요.,Help me hier.,Hjelp meg her.,Pomóż mi.,Preciso de uma ajuda aqui.,,Dă-mi o mână de ajutor.,Помоги мне вот с этим.,,Bana yardım et. -That's all I can do.,TXT_RYES0_SCRIPT10_D25772_THATS,,,,"To je vše, co mohu udělat.","Det er det eneste, jeg kan gøre.","Da ist alles, was ich tun kann.",,,Eso es todo lo que puedo hacer.,,"Tässä kaikki, mitä voin tehdä.",C'est tout ce que je peux faire.,Csak ennyit tudtam tenni.,È tutto quello che posso fare.,私が出来る事はここまでだ。,좀 치료해줬습니다. 이제 어떠신가요?,Dat is alles wat ik kan doen.,Det er alt jeg kan gjøre.,To wszystko co mogę zrobić.,Isso é tudo o que posso fazer.,,Asta e tot ceea ce pot face.,"Это всё, что я могу сделать.",,Tek yapabileceğim bu. -New implant?,TXT_RPLY1_SCRIPT10_D25772_NEWIM,,,,Nový implantát?,Nyt implantat?,Neues Implantat?,,,¿Nuevo implante?,,Uusi istute?,Un nouvel implant?,Új implantátum?,Nuovo impianto?,新しいインプラントは?,새로운 이식 칩?,Een nieuw implantaat?,Nytt implantat?,Nowy implant?,Implante novo?,,Implant nou?,Новый имплант?,,Yeni implant mı? -"Yep, my best one yet.",TXT_RYES1_SCRIPT10_D25772_YEPMY,,,,"Jo, můj zatím nejlepší.","Ja, mit bedste endnu.","Ja, mein bestes bisher.",,,"Si, el mejor que tengo.",,"Jep, tähänastisista istutteistani paras.","Oui, le meilleur que j'ai jamais conçu.","Igen, az egyik legjobb változat eddig.","Si, il migliore che ho creato fin'ora.",よし、これは傑作だ。,있죠. 제 생각엔 아주 좋은 품질인 것 같아요.,"Ja, mijn beste tot nu toe.","Ja, mitt beste hittil.",Tak. Najlepszy jaki dotychczas zrobiłem.,Isso mesmo. O melhor que já fiz até agora.,,"Da, cel mai bun, momentan.",Да. Моё лучшее творение.,,"Evet, şimdiye kadarki en iyisi." -"Sorry, but you just have to wait.",TXT_RNO1_SCRIPT10_D25772_SORRY,,,,"Promiň, ještě budeš muset počkat.","Beklager, men du må bare vente.","Tut mir leid, du musst noch warten.",,,"Lo siento, pero tendrás que esperar.",,"Pahoittelen, sinun täytyy vain vielä vähän odottaa.","Désolé, il faudra attendre encore.","Sajnálom, de várnod kell egy kicsit.","Mi spiace, ma devi attendere un poco.",すまない、だがもうすぐ出来そうだ。,시간을 좀 더 주신다면...,"Sorry, maar je moet gewoon wachten.","Beklager, men du må bare vente.","Wybacz, ale musisz poczekać.","Desculpe, mas você vai ter que esperar.",,"Scuze, dar trebuie să mai aștepți.","Прости, но тебе придётся подождать.",,Üzgünüm ama beklemek zorundasın. -"This is it, Feris has managed to drain everything he could out of all the data we have, this will be the best, and last implant upgrade. It will be sort of depressing, seeing my best creation reach its peak. Well, at least the rest of this crew will keep me occupied.",TXT_DLG_SCRIPT10_D27288_THISI,,,,"A je to, Feris vyždímal všechno, co mohl, z dat, která máme. Tohle bude poslední a nejlepší implantátový upgrade. Bude mi trochu smutno, vidět můj výtvor dosáhnout vrcholu. No, alespoň budu zaneprázdněný zbytkem armády.","Det er nu, Feris har formået at dræne alt hvad han kunne ud af alle de data vi har, dette bliver den bedste, og sidste implantatopgradering. Det bliver lidt deprimerende at se min bedste skabelse nå sit højdepunkt. I det mindste vil resten af besætningen holde mig beskæftiget.","Das ist es, Feris hat aus den Daten alles herausgeholt, was möglich war. Das wird das beste und letzte Upgrade sein. Irgendwie deprimierend zu sehen, dass meine beste Erfindung ihren Höhepunkt erreicht hat. Nun ja, wenigstens wird der Rest dieser Truppe mich lange genug beschäftigen.",,,"Ya está, Feris ha conseguido exprimir todo lo que ha podido de los datos que tenemos, este va a ser la mejor, y última mejora del implante. Es un poco triste ver mi mejor creación llegar a su cima. Bueno, al menos el resto del personal me mantendrá ocupado.",,"Tässä se nyt on; Feriksen on onnistunut puristaa kaiken ulos kaikesta käsissämme olevasta datasta. Tämä tulee olemaan istutteen paras ja viimeinen kehitysaskel. Vähän jotenkin masentavaa nähdä parhaan luomuksensa saavuttavan huippunsa. No, saanpahan sentään edes puuhaa lopuista tästä miehistöstä.","C'est fini, Feris a réussi à tirer tout ce qu'on pouvait des données que l'on a récupéré. Ce sera la dernière, et meilleure mise à jour. C'est un peu déprimant, de savoir que ma meilleure invention à déjà atteint son pinnacle.. Bon, au moins, le reste de l'équipe me gardera occupé.","Ez lesz a végkifejlett, Ferisnek sikerült kipréselni minden adatot, ez lesz a legjobb és egyben utolsó implantátum fejlesztés. Kicsit hervasztó érzés látni munkám gyümölcsének végkifejlettségét. Na de legalább a csapat többi része le fog foglalni.","Ecco qua, Feris è riuscito ad estrarre tutto quello che poteva dai dati che possediamo, e questo sarà il migliore, nonché l'ultimo, aggiornamento dell'impianto. In un certo senso sarà un pò deprimente, vedere la mia migliore creazione raggiungere l'apice. Se non altro, il resto di questa squadra mi terrà occupato.","いよいよだ、フェリスが我々の保管していた +","Bem, estou de volta aos meus velhos truques novamente. Ainda estou trabalhando nos seus implantes. Você sabia que Macil os autorizou pra todo mundo? Ah não? É porque eles funcionaram muito bem em você. Precisa de alguma coisa?",,"Păi, m-am întors la treburile mele vechi, încă lucrez la implanturile tale. Știi că Macil a vrut să le autorizeze pentru toată lumea? Nu, așa-i? E din cauză că ai ieșit prea bine. Pot face ceva pentru tine?","Я снова вернулся к старым занятиям и по-прежнему работаю над твоим имплантом. Ты знаешь, что Мэйсил теперь всем разрешил использовать импланты? Нет? Это потому, что ты так хорошо показал себя. Могу я чем-нибудь тебе помочь?",,"Jag är tillbaka till mina gamla tricks igen, jag jobbar fortfarande på dina implantat. Visste du att Macil nu har godkänt dem för alla? Nej, va? Det är för att du blev så bra. Är det något jag kan göra för dig?","Yine eski numaralarıma döndüm. Hâlâ implantların üzerinde çalışıyorum. Macil'in artık herkes için onay verdiğini biliyor muydun? Hayır, ha? Bu kadar iyi olduğun için. Senin için yapabileceğim bir şey var mı?" +Help me out here.,TXT_RPLY0_SCRIPT10_D25772_HELPM,〃,,,Pomoz mi.,Hjælp mig lige her.,Hilf mir mal.,,Helpu min.,Ayúdame.,,Autatko vähän.,Aidez moi.,Segíts nekem egy kicsit.,Aiutami.,ここで治してくれ。,나 좀 치료해줘요.,Help me hier.,Hjelp meg her.,Pomóż mi.,Preciso de uma ajuda aqui.,,Dă-mi o mână de ajutor.,Помоги мне вот с этим.,,Hjälp mig här.,Bana yardım et. +That's all I can do.,TXT_RYES0_SCRIPT10_D25772_THATS,〃,,,"To je vše, co mohu udělat.","Det er det eneste, jeg kan gøre.","Da ist alles, was ich tun kann.",,"Tio estas ĉio, +kion mi povas fari.","Eso es todo +lo que puedo hacer.",,"Tässä kaikki, mitä voin tehdä.",C'est tout ce que je peux faire.,Csak ennyit tudtam tenni.,È tutto quello che posso fare.,私が出来る事はここまでだ。,좀 치료해줬습니다. 이제 어떠신가요?,Dat is alles wat ik kan doen.,Det er alt jeg kan gjøre.,To wszystko co mogę zrobić.,Isso é tudo o que posso fazer.,,Asta e tot ceea ce pot face.,"Это всё, что я могу сделать.",,Det är allt jag kan göra.,Tek yapabileceğim bu. +New implant?,TXT_RPLY1_SCRIPT10_D25772_NEWIM,〃,,,Nový implantát?,Nyt implantat?,Neues Implantat?,,Ĉu nova enplantaĵo?,¿Nuevo implante?,,Uusi istute?,Un nouvel implant?,Új implantátum?,Nuovo impianto?,新しいインプラントは?,새로운 이식 칩?,Een nieuw implantaat?,Nytt implantat?,Nowy implant?,Implante novo?,,Implant nou?,Новый имплант?,,Nytt implantat?,Yeni implant mı? +"Yep, my best one yet.",TXT_RYES1_SCRIPT10_D25772_YEPMY,〃,,,"Jo, můj zatím nejlepší.","Ja, mit bedste endnu.","Ja, mein bestes bisher.",,"Jes, la plej bona, +kiun mi havas.","Sí, el mejor que tengo.",,"Jep, tähänastisista istutteistani paras.","Oui, le meilleur que j'ai jamais conçu.","Igen, az egyik legjobb változat eddig.","Si, il migliore che ho creato fin'ora.",よし、これは傑作だ。,있죠. 제 생각엔 아주 좋은 품질인 것 같아요.,"Ja, mijn beste tot nu toe.","Ja, mitt beste hittil.",Tak. Najlepszy jaki dotychczas zrobiłem.,Isso mesmo. O melhor que já fiz até agora.,,"Da, cel mai bun, momentan.",Да. Моё лучшее творение.,,"Japp, mitt bästa hittills.","Evet, şimdiye kadarki en iyisi." +"Sorry, but you just have to wait.",TXT_RNO1_SCRIPT10_D25772_SORRY,〃,,,"Promiň, ještě budeš muset počkat.","Beklager, men du må bare vente.","Tut mir leid, du musst noch warten.",,"Pardonon, sed +vi devas atendi.","Lo siento, pero +tendrás que esperar.","Lo siento, pero +vas a tener que esperar.","Pahoittelen, sinun täytyy vain vielä vähän odottaa.","Désolé, il faudra attendre encore.","Sajnálom, de várnod kell egy kicsit.","Mi spiace, ma devi attendere un poco.",すまない、だがもうすぐ出来そうだ。,시간을 좀 더 주신다면...,"Sorry, maar je moet gewoon wachten.","Beklager, men du må bare vente.","Wybacz, ale musisz poczekać.","Desculpe, mas você vai ter que esperar.",,"Scuze, dar trebuie să mai aștepți.","Прости, но тебе придётся подождать.",,"Ledsen, men du måste vänta.",Üzgünüm ama beklemek zorundasın. +"This is it, Feris has managed to drain everything he could out of all the data we have, this will be the best, and last implant upgrade. It will be sort of depressing, seeing my best creation reach its peak. Well, at least the rest of this crew will keep me occupied.",TXT_DLG_SCRIPT10_D27288_THISI,〃 (six upgrades).,,,"A je to, Feris vyždímal všechno, co mohl, z dat, která máme. Tohle bude poslední a nejlepší implantátový upgrade. Bude mi trochu smutno, vidět můj výtvor dosáhnout vrcholu. No, alespoň budu zaneprázdněný zbytkem armády.","Det er nu, Feris har formået at dræne alt hvad han kunne ud af alle de data vi har, dette bliver den bedste, og sidste implantatopgradering. Det bliver lidt deprimerende at se min bedste skabelse nå sit højdepunkt. I det mindste vil resten af besætningen holde mig beskæftiget.","Das ist es, Feris hat aus den Daten alles herausgeholt, was möglich war. Das wird das beste und letzte Upgrade sein. Irgendwie deprimierend zu sehen, dass meine beste Erfindung ihren Höhepunkt erreicht hat. Nun ja, wenigstens wird der Rest dieser Truppe mich lange genug beschäftigen.",,"Jen ĉio, Feriso jam ekspluatis kiel eble plej multe de niaj havataj datenoj: tiu estis la lasta kaj plej bona versio de la enplantaĵo. Estas iom malfeliĉige vidi, ke mia plej bona kreaĵo atingis la supron. Nu, almenaŭ la resto de la personaro tenos min okupata.","Ya está, Feris ya ha exprimido todo lo que se podía de los datos que tenemos: esa ha sido la mejor y última versión del implante. Es un poco triste ver mi mejor creación llegar a su cima. Bueno, al menos el resto del personal me mantendrá ocupado.","Ya está, Feris ya exprimió todo lo que se podía de los datos que tenemos: esa fue la mejor y última versión del implante. Es un poco triste ver mi mejor creación llegar a su cima. Bueno, al menos el resto del personal me va a mantener ocupado.","Tässä se nyt on; Feriksen on onnistunut puristaa kaiken ulos kaikesta käsissämme olevasta datasta. Tämä tulee olemaan istutteen paras ja viimeinen kehitysaskel. Vähän jotenkin masentavaa nähdä parhaan luomuksensa saavuttavan huippunsa. No, saanpahan sentään edes puuhaa lopuista tästä miehistöstä.","C'est fini, Feris a réussi à tirer tout ce qu'on pouvait des données que l'on a récupéré. Ce sera la dernière, et meilleure mise à jour. C'est un peu déprimant, de savoir que ma meilleure invention à déjà atteint son pinnacle.. Bon, au moins, le reste de l'équipe me gardera occupé.","Ez lesz a végkifejlett, Ferisnek sikerült kipréselni minden adatot, ez lesz a legjobb és egyben utolsó implantátum fejlesztés. Kicsit hervasztó érzés látni munkám gyümölcsének végkifejlettségét. Na de legalább a csapat többi része le fog foglalni.","Ecco qua, Feris è riuscito ad estrarre tutto quello che poteva dai dati che possediamo, e questo sarà il migliore, nonché l'ultimo, aggiornamento dell'impianto. In un certo senso sarà un po' deprimente, vedere la mia migliore creazione raggiungere l'apice. Se non altro, il resto di questa squadra mi terrà occupato.","いよいよだ、フェリスが我々の保管していた 全てのデータから全力を尽くして編み出した、 これが最高で最後のインプラント アップグレードだ。が、私にこれ以上の創造に @@ -10813,1316 +11330,1412 @@ najlepsze i ostatnie ulepszenie implantu. To trochę smutne, że moje dzieło tak szybko osiągnęło szczyt możliwości. Cóż... przynajmniej będę -mógł zająć się resztą załogi.","É isso aí, Feris conseguiu tirar tudo que foi possível dos dados que temos. Este será a melhor e a última aprimoração do implante. Vai ser meio triste, vendo minha melhor criação chegar no seu ápice. Bom, pelo menos o resto do pessoal vai me manter ocupado.",,"Asta e, Feris a reușit să stoarcă tot din datele pe care le avem, acesta e ultimul, și cel mai bun upgrade pentru implant. Va fi oarecum deprimant, să-mi văd creația ajungând în vârf. Măcar restul echipajului mă va ține ocupat.","Вот и всё. Из тех данных, которыми мы располагаем, Ферису удалось вытянуть всё, что только можно. Это лучшая и последняя модификация импланта. Немного грустно видеть, что твоё творение достигло своего предела. Ну, по крайней мере, я всё ещё нужен остальной части команды.",,"İşte bu, Feris elimizdeki tüm verilerden çekebildiği her şeyi çekmeyi başardı, bu en iyi ve son implant güncellemesi olacak. En iyi eserimin zirveye ulaştığını görmek biraz iç karartıcı olacak. En azından bu mürettebatın geri kalanı beni meşgul edecek." -Could you heal me?,TXT_RPLY0_SCRIPT10_D27288_COULD,,,,Mohl bys mě ošetřit?,Kan du helbrede mig?,Kannst du mich gesund machen?,,,¿Podrías curarme?,,Voisitko hoitaa minua?,Vous pouvez me soigner?,Fel tudnál gyógyítani?,Puoi curarmi?,治してくれるか?,절 치료해줄 수 있나요?,Kunt je me genezen?,Kan du helbrede meg?,Możesz mnie uleczyć?,Poderia me curar?,,Mă poți bandaja?,Вылечишь меня?,,Beni iyileştirebilir misin? -"There, you're all set now.",TXT_RYES0_SCRIPT10_D27288_THERE,,,,"Tak, a jsi hotov.","Sådan, du er klar nu.","So, das wär's dann.",,,"Ya está, listo.",,"Siinä, kaikki kunnossa.","Voilà, vous pouvez y aller.","Parancsolj, harcra kész vagy.","Certo, ora sei apposto.",これで、準備完了だ。,"자, 이제 안전할 겁니다.",Daar ben je nu helemaal klaar.,"Sånn, nå er du klar.",Proszę. Wszystko gotowe.,Feito. Tudo certo agora.,,"Gata, ești pregătit.",Конечно. Теперь ты в норме.,,"İşte, şimdi hazırsın." -It's the hero. Great job! What can I get for you? We've got a little larger selection now that we have all the ordinance from the castle. If you need to buy some ammo talk to Justin. He'll take care of you. ,TXT_DLG_SCRIPT10_D28804_ITSTH,MAP10: Feris (no training).,,,"Je to náš hrdina. Skvělá práce! Co ti můžu sehnat? Máme trochu větší výběr, když teď máme přístup ke všemu vybavení z hradu. Jestli potřebuješ munici, zeptej se Justina, on si s tebou poradí.","Det er helten. Godt gået! Hvad kan jeg skaffe til dig? Vi har et lidt større udvalg nu, hvor vi har alle ordinationerne fra slottet. Hvis du har brug for at købe noget ammunition, så tal med Justin. Han vil tage sig af dig.","Das ist der Held. Guter Job! Was kann ich für dich tun. Wir haben jetzt eine größere Auswahl nachdem wir die Burg geplündert haben. Wenn du noch Munition brauchst, wende dich an Justin. Er kümmert sich darum.",,,Es el héroe. ¡Buen trabajo! ¿Qué puedo ofrecerte? Tenemos una selección un poco más amplia ahora que tenemos todo el arsenal del castillo. Si necesitas comprar municiones habla con Justin. Él se ocupará de ti.,,"Sankarimmehan se siinä; hyvää työtä! Miten voin olla avuksi? Meillä on hieman suurempi valikoima nyt, kun olemme saaneet käsiimme linnan kaikki asetarvikkeet. Jos sinun tarvitsee ostaa ammuksia, puhu Justinille. Hän hoitaa tarpeesi.","Voilà notre héros! Fantastique travail! Que puis-je faire pour vous? Nous avons étendu notre séléction maintenant que nous avons l'arsenal du château à notre disposition. Si vous avez besoin de munitions, parlez à Justin. Il s'occupera de vous.","Itt a hősünk. Kiváló munka! Mit adhatok? Kicsivel nagyobb a választék, most hogy megvan az összes leírás a kastélyból. Ha akarsz lőszert venni, beszélj Justinnal. Majd Ő gondoskodik rólad.","È l'eroe, ottimo lavoro! Che posso procurarti? Abbiamo una selezione un pò più grande dopo aver saccheggiato i depositi del castello. Se ti servono altre munizioni parla con Justin. Ci penserà lui a te.","正に英雄、流石です! +mógł zająć się resztą załogi.","É isso aí, Feris conseguiu tirar tudo que foi possível dos dados que temos. Este será a melhor e a última aprimoração do implante. Vai ser meio triste, vendo minha melhor criação chegar no seu ápice. Bom, pelo menos o resto do pessoal vai me manter ocupado.",,"Asta e, Feris a reușit să stoarcă tot din datele pe care le avem, acesta e ultimul, și cel mai bun upgrade pentru implant. Va fi oarecum deprimant, să-mi văd creația ajungând în vârf. Măcar restul echipajului mă va ține ocupat.","Вот и всё. Из тех данных, которыми мы располагаем, Ферису удалось вытянуть всё, что только можно. Это лучшая и последняя модификация импланта. Немного грустно видеть, что твоё творение достигло своего предела. Ну, по крайней мере, я всё ещё нужен остальной части команды.",,"Det här är det, Feris har lyckats dränera allt han kunde ur all data vi har, det här kommer att bli den bästa, och sista implantatuppgraderingen. Det kommer att bli lite deprimerande att se min bästa skapelse nå sin höjdpunkt. Tja, resten av besättningen kommer åtminstone att hålla mig sysselsatt.","İşte bu, Feris elimizdeki tüm verilerden çekebildiği her şeyi çekmeyi başardı, bu en iyi ve son implant güncellemesi olacak. En iyi eserimin zirveye ulaştığını görmek biraz iç karartıcı olacak. En azından bu mürettebatın geri kalanı beni meşgul edecek." +Could you heal me?,TXT_RPLY0_SCRIPT10_D27288_COULD,〃,,,Mohl bys mě ošetřit?,Kan du helbrede mig?,Kannst du mich gesund machen?,,Ĉu vi kuracus min?,¿Podrías curarme?,,Voisitko hoitaa minua?,Vous pouvez me soigner?,Fel tudnál gyógyítani?,Puoi curarmi?,治してくれるか?,절 치료해줄 수 있나요?,Kunt je me genezen?,Kan du helbrede meg?,Możesz mnie uleczyć?,Poderia me curar?,,Mă poți bandaja?,Вылечишь меня?,,Kan du läka mig?,Beni iyileştirebilir misin? +"There, you're all set now.",TXT_RYES0_SCRIPT10_D27288_THERE,〃,,,"Tak, a jsi hotov.","Sådan, du er klar nu.","So, das wär's dann.",,"Farite, vi nun +estas en ordo.","Ya está, listo.",,"Siinä, kaikki kunnossa.","Voilà, vous pouvez y aller.","Parancsolj, harcra kész vagy.","Certo, ora sei apposto.",これで、準備完了だ。,"자, 이제 안전할 겁니다.",Daar ben je nu helemaal klaar.,"Sånn, nå er du klar.",Proszę. Wszystko gotowe.,Feito. Tudo certo agora.,,"Gata, ești pregătit.",Конечно. Теперь ты в норме.,,"Så där, du är redo nu.","İşte, şimdi hazırsın." +It's the hero. Great job! What can I get for you? We've got a little larger selection now that we have all the ordinance from the castle. If you need to buy some ammo talk to Justin. He'll take care of you. ,TXT_DLG_SCRIPT10_D28804_ITSTH,MAP10: Feris (no training).,,,"Je to náš hrdina. Skvělá práce! Co ti můžu sehnat? Máme trochu větší výběr, když teď máme přístup ke všemu vybavení z hradu. Jestli potřebuješ munici, zeptej se Justina, on si s tebou poradí.","Det er helten. Godt gået! Hvad kan jeg skaffe til dig? Vi har et lidt større udvalg nu, hvor vi har alle ordinationerne fra slottet. Hvis du har brug for at købe noget ammunition, så tal med Justin. Han vil tage sig af dig.","Das ist der Held. Guter Job! Was kann ich für dich tun. Wir haben jetzt eine größere Auswahl nachdem wir die Burg geplündert haben. Wenn du noch Munition brauchst, wende dich an Justin. Er kümmert sich darum.",,"La heroo. Bonege farite! Kion mi donu al vi? Estas elektaĵo iomete pli granda nun kiam ni havas la tutan arsenalon de la kastelo. Se vi bezonas plian municion, parolu kun Justin: li solvos tion.","Es el héroe. ¡Muy bien hecho! ¿Qué puedo ofrecerte? Hay una selección un poco más amplia ahora que tenemos todo el arsenal del castillo. Si necesitas comprar munición, habla con Justin: él se ocupará de ti.","Es el héroe. ¡Muy bien hecho! ¿Qué puedo ofrecerte? Hay una selección un poco más amplia ahora que tenemos todo el arsenal del castillo. Si necesitas comprar munición, habla con Justin: él se va a ocupar de ti.","Sankarimmehan se siinä; hyvää työtä! Miten voin olla avuksi? Meillä on hieman suurempi valikoima nyt, kun olemme saaneet käsiimme linnan kaikki asetarvikkeet. Jos sinun tarvitsee ostaa ammuksia, puhu Justinille. Hän hoitaa tarpeesi.","Voilà notre héros! Fantastique travail! Que puis-je faire pour vous? Nous avons étendu notre séléction maintenant que nous avons l'arsenal du château à notre disposition. Si vous avez besoin de munitions, parlez à Justin. Il s'occupera de vous.","Itt a hősünk. Kiváló munka! Mit adhatok? Kicsivel nagyobb a választék, most hogy megvan az összes leírás a kastélyból. Ha akarsz lőszert venni, beszélj Justinnal. Majd Ő gondoskodik rólad.","È l'eroe, ottimo lavoro! Che posso procurarti? Abbiamo una selezione un po' più grande dopo aver saccheggiato i depositi del castello. Se ti servono altre munizioni parla con Justin. Ci penserà lui a te.","正に英雄、流石です! 何か必要ですか?城の全兵器が揃っております。 弾薬が必要ならジャスティンに頼めば大丈夫ですよ",그 프론트의 인기 많은 영웅 아닌가요? 잘하셨습니다! 무엇을 도와드릴까요? 성안에서 특이하고 질 좋은 보급물자들을 긁어모아 왔어요. 만약 탄약 보급을 위해서 오신 거라면 저스틴에게 물어보세요.,"Het is de held. Goed werk! Wat kan ik voor je halen? We hebben een iets grotere selectie nu we alle verordeningen van het kasteel hebben. Als je wat munitie moet kopen, praat dan met Justin. Hij zal voor je zorgen.","Det er helten. Bra jobbet! Hva vil du ha? Vi har et litt større utvalg nå som vi har alle ordrene fra slottet. Hvis du trenger å kjøpe ammunisjon, snakk med Justin. Han tar seg av deg.","Oto bohater. Dobra robota! Co mogę dla ciebie zrobić? Mamy teraz większy wybór towaru dzięki rozporządzeniu z zamku. Jeśli potrzebujesz amunicji to porozmawiaj z Justinem. Zajmie -się tobą.",Nosso herói. Bom trabalho! Como posso te ajudar? Temos uma seleção um pouco maior agora que conseguimos todo o equipamento do castelo. Se você precisar comprar munição é só falar com o Justin. Ele pode te ajudar.,,"E eroul. Bună treabă! Ce pot să-ți aduc? Avem o selecție mai largă acum, din moment ce am primit toate ordonanțele de la castel. Dacă ai nevoie de muniție vorbește cu Justin, se va ocupa de tine.","А вот и наш герой. Отлично сработано! Чем я могу тебе помочь? Теперь в нашем распоряжении всё оружие из замка, так что выбор стал побогаче. Если тебе нужны боеприпасы, обратись к Джастину: он тебе поможет.",,Bu kahraman. İyi iş çıkardın! Size ne getireyim? Kaledeki tüm teçhizat elimizde olduğu için biraz daha geniş bir seçkimiz var. Cephane almak istersen Justin'le konuş. O seninle ilgilenir. -I'm out of bullets.,TXT_RPLY0_SCRIPT10_D28804_IMOUT,〃,,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi estas sen kugloj.,No me quedan balas.,,Luodit on loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się naboje.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны.,,Mermim bitti. +się tobą.",Nosso herói. Bom trabalho! Como posso te ajudar? Temos uma seleção um pouco maior agora que conseguimos todo o equipamento do castelo. Se você precisar comprar munição é só falar com o Justin. Ele pode te ajudar.,,"E eroul. Bună treabă! Ce pot să-ți aduc? Avem o selecție mai largă acum, din moment ce am primit toate ordonanțele de la castel. Dacă ai nevoie de muniție vorbește cu Justin, se va ocupa de tine.","А вот и наш герой. Отлично сработано! Чем я могу тебе помочь? Теперь в нашем распоряжении всё оружие из замка, так что выбор стал побогаче. Если тебе нужны боеприпасы, обратись к Джастину: он тебе поможет.",,Det är hjälten. Bra jobbat! Vad kan jag ge dig? Vi har ett lite större urval nu när vi har alla ordinationer från slottet. Om du behöver köpa lite ammunition så prata med Justin. Han tar hand om dig.,Bu kahraman. İyi iş çıkardın! Size ne getireyim? Kaledeki tüm teçhizat elimizde olduğu için biraz daha geniş bir seçkimiz var. Cephane almak istersen Justin'le konuş. O seninle ilgilenir. +I'm out of bullets.,TXT_RPLY0_SCRIPT10_D28804_IMOUT,〃,,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi ne havas kuglojn.,No me quedan balas.,,Luodit on loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się naboje.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны.,,Jag har slut på kulor.,Mermim bitti. Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT10_D28804_HERES,〃,,,"Tady máš nějakou munici, neplýtvej s ní.",Her er noget ammunition til dig. Spild det ikke.,Hier hast du welche. Verschwende sie nicht.,,"Jen iom da municio. Ne malŝparu ĝin.","Aquí tienes algo de munición. -No la desperdicies.",,Tässä sinulle vähän ammuksia. Älä tuhlaa niitä.,Voilà des munitions. Ne les gaspillez pas.,Itt van egy kis lőszer. Ne pazarold el.,Ecco un pò di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,그렇게 계속 쏘아대면 탄약이 낭비됩니다. 여기 탄약이에요.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Tylko jej nie zmarnuj.,Leve um pouco desta munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,İşte sana biraz cephane. Ziyan etme. -Teach me.,TXT_RPLY1_SCRIPT10_D28804_TEACH,〃,,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. -"Now, a few tips on the big guns.",TXT_RYES1_SCRIPT10_D28804_NOWAF,〃,,,"Tak jo, pár tipů, jak na velké zbraně.",Nu et par tips om de store våben.,Nun einige Ratschläge für die großen Waffen,,,"Ahora, unos cuantos consejos sobre las armas pesadas.",,Voin antaa muutamia vinkkejä isojen aseiden käyttöön.,"Bon, voilà quelques conseils pour les armes plus grosses.","És most, pár tipp a nagyobb fegyverekhez.",Ecco qui un paio di consigli sulle armi pesanti.,では、大きい銃の扱い方を教えます。,중화기 다루는 훈련을 시작하겠습니다!,"Nu, een paar tips over de grote geweren.","Nå, noen tips om de store kanonene.",Proszę. Kilka wskazówek dotyczących używania większych broni.,"Ok, algumas dicas sobre as armas pesadas.",,"Acum, niște sfaturi pentru armele mari.",А теперь пара советов насчёт больших пушек.,,"Şimdi, büyük silahlar hakkında birkaç ipucu." -You're not ready yet.,TXT_RNO1_SCRIPT10_D28804_YOURE,〃,,,Ještě nejsi připraven.,Du er ikke klar endnu.,Du bist noch nicht soweit,,,Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,준비가 아직 안됐습니다.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов.,,Henüz hazır değilsin. -"How's the war effort? Nevermind, if we're still here, it must be going fine. What can I do for you?",TXT_DLG_SCRIPT10_D30320_HOWST,〃 (one training),,,"Jak jde válečné úsilí? To je jedno, jestliže tu stále jsi, musí to jít dobře. Co pro tebe můžu udělat?","Hvordan går det med krigsindsatsen? Glem det, hvis vi stadig er her, må det gå fint. Hvad kan jeg gøre for dig?","Wie geht der Krieg voran? Egal, solange wir noch hier sind, kann es nicht schlecht laufen. Was kann ich für dich tun?",,,"¿Cómo va la guerra? No importa, si seguimos aquí, debe de ir bien. ¿Qué puedo hacer por ti?",,"Kuinkas sotaponnistelut sujuvat? Tai ei mitään, varmaankin hyvin sujuvat, jos kerran vielä olemme tässä. Miten voin palvella?","Comment va l'effort de guerre? Non, oubliez. Si vous êtes ici, ça veut dire que tout va bien. Que puis-je faire pour vous?","Hogy áll a harc? Mindegyis, ha még mindig itt vagyunk, akkor jól haladunk. Mit tehetek érted?","Come sta procedendo la guerra? Vabbè, lascia stare, siamo ancora qua, quindi deve procedere bene. Cosa posso fare per te?","奮闘してますか?気にしないで、 +No la desperdicies.",,Tässä sinulle vähän ammuksia. Älä tuhlaa niitä.,Voilà des munitions. Ne les gaspillez pas.,Itt van egy kis lőszer. Ne pazarold el.,Ecco un po' di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,그렇게 계속 쏘아대면 탄약이 낭비됩니다. 여기 탄약이에요.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Tylko jej nie zmarnuj.,Leve um pouco desta munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,Här är lite ammunition till dig. Slösa inte bort den.,İşte sana biraz cephane. Ziyan etme. +Teach me.,TXT_RPLY1_SCRIPT10_D28804_TEACH,〃,,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. +"Now, a few tips on the big guns.",TXT_RYES1_SCRIPT10_D28804_NOWAF,〃,,,"Tak jo, pár tipů, jak na velké zbraně.",Nu et par tips om de store våben.,Nun einige Ratschläge für die großen Waffen,,"Nun kelkaj konsiloj +pri pezaj armiloj...","Ahora unos cuantos consejos +sobre las armas pesadas...",,Voin antaa muutamia vinkkejä isojen aseiden käyttöön.,"Bon, voilà quelques conseils pour les armes plus grosses.","És most, pár tipp a nagyobb fegyverekhez.",Ecco qui un paio di consigli sulle armi pesanti.,では、大きい銃の扱い方を教えます。,중화기 다루는 훈련을 시작하겠습니다!,"Nu, een paar tips over de grote geweren.","Nå, noen tips om de store kanonene.",Proszę. Kilka wskazówek dotyczących używania większych broni.,"Ok, algumas dicas sobre as armas pesadas.",,"Acum, niște sfaturi pentru armele mari.",А теперь пара советов насчёт больших пушек.,,"Nu, några tips om de stora vapnen.","Şimdi, büyük silahlar hakkında birkaç ipucu." +You're not ready yet.,TXT_RNO1_SCRIPT10_D28804_YOURE,〃,,,Ještě nejsi připraven.,Du er ikke klar endnu.,Du bist noch nicht soweit,,"Vi ankoraŭ +ne estas preta.",Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,준비가 아직 안됐습니다.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов.,,Du är inte redo än.,Henüz hazır değilsin. +"How's the war effort? Nevermind, if we're still here, it must be going fine. What can I do for you?",TXT_DLG_SCRIPT10_D30320_HOWST,〃 (one training),,,"Jak jde válečné úsilí? To je jedno, jestliže tu stále jsi, musí to jít dobře. Co pro tebe můžu udělat?","Hvordan går det med krigsindsatsen? Glem det, hvis vi stadig er her, må det gå fint. Hvad kan jeg gøre for dig?","Wie geht der Krieg voran? Egal, solange wir noch hier sind, kann es nicht schlecht laufen. Was kann ich für dich tun?",,"Kiel la milito iras? Nu, ne estas grave, ni estas ankoraŭ vivaj, do ĝi certe iras bone. Kion mi faru por vi?","¿Cómo va la guerra? Bueno, no importa, si seguimos aquí es porque debe de ir bien. ¿Qué puedo hacer por ti?",,"Kuinkas sotaponnistelut sujuvat? Tai ei mitään, varmaankin hyvin sujuvat, jos kerran vielä olemme tässä. Miten voin palvella?","Comment va l'effort de guerre? Non, oubliez. Si vous êtes ici, ça veut dire que tout va bien. Que puis-je faire pour vous?","Hogy áll a harc? Mindegyis, ha még mindig itt vagyunk, akkor jól haladunk. Mit tehetek érted?","Come sta procedendo la guerra? Vabbè, lascia stare, siamo ancora qua, quindi deve procedere bene. Cosa posso fare per te?","奮闘してますか?気にしないで、 ここにいるなら上手くやってるのは分かります。 どういうご用件ですか?",전쟁 상황은 어떻게 되어가나요? 상관은 없지만. 우리들이 아직 살아있는 한 물어볼 필요도 없죠. 무엇을 원하시나요?,"Hoe gaat het met de oorlogsinspanning? Maakt niet uit, als we hier nog steeds zijn, moet het wel goed gaan. Wat kan ik voor je doen?","Hvordan går det med krigsinnsatsen? Glem det, hvis vi fortsatt er her, må det gå bra. Hva kan jeg gjøre for deg?","Jak tam wojna idzie? Nieważne. Jeśli cały czas żyjemy to chyba dobrze. -Co mogę dla ciebie zrobić?","Como está indo a guerra? Deixa pra lá, se nós ainda estamos aqui é porque deve estar indo bem. Como posso te ajudar?",,"Cum merge efortul de război? Nu mai contează, dacă suntem încă aici înseamnă că e bine. Ce pot face pentru tine?","Как дела на фронте? Впрочем, неважно. Наверняка всё хорошо, раз мы ещё живы. Что я могу для тебя сделать?",,"Savaş çabaları nasıl gidiyor? Boşver, hala burada olduğumuza göre, iyi gidiyor olmalı. Senin için ne yapabilirim?" -I ran out of bullets.,TXT_RPLY0_SCRIPT10_D30320_IRANO,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Mir ist die Munition ausgegangen.,,,Me he quedado sin balas.,,Minulta loppuivat luodit.,Je suis à court de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾を使い果たした。,탄약이 바닥났어요.,De kogels zijn op.,Jeg gikk tom for kuler.,Skończyły mi się naboje.,Fiquei sem munição.,,Am rămas fără gloanțe.,У меня кончились патроны.,,Mermim bitti. -That should help.,TXT_RYES0_SCRIPT10_D30320_THATS,〃 (〃),,,Tohle by mělo pomoci.,Det burde hjælpe.,Das hier sollte helfen.,,,Esto debería ayudar.,,Tämän pitäisi auttaa.,Cela devrait aider.,Ez majd segít.,Questo dovrebbe aiutarti.,これが助けになるでしょう。,좀 도움이 될 겁니다.,Dat zou moeten helpen.,Det burde hjelpe.,To powinno pomóc.,Isto deve ajudar.,,Asta ar trebui să ajute.,"Вот, пожалуйста.",,Bunun yardımı olur. -You've got enough ammo.,TXT_RNO0_SCRIPT10_D30320_YOUVE,〃 (〃),,,Máš jich dost.,Du har nok ammunition.,Du hast genug Munition.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ne hai a sufficienza.,弾は十分に見えます。,탄약을 충분히 소지한 것 같은데.,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai destulă.,Вполне достаточно.,,Yeterince cephanen var. -Teach me.,TXT_RPLY1_SCRIPT10_D30320_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. -"Here, I'll show you a few tricks of the trade.",TXT_RYES1_SCRIPT10_D30320_HEREI,〃 (〃),,,Ukážu ti pár triků mého řemesla.,"Her, jeg skal vise dig et par tricks.","Hier, ich zeige dir mal ein paar Geheimtricks.",,,"Bien, te mostraré algunos trucos de oficio.",,"No niin, valotan sinulle vähän alan saloja.",Voilà quelques conseils dont vous pouvez faire usage.,"Nézdd csak, mutatok neked pár trükköt.",Ora ti mostro un paio di trucchi del mestiere.,では、幾つかのコツを教えましょう。,저항군의 참된 기술들을 좀 가르쳐드리죠!,Hier zal ik je een paar trucjes van het vak laten zien.,Jeg skal vise deg noen triks.,Proszę. Oto kilka wskazówek o handlu.,"Certo, vou te mostrar alguns truques do ofício.",,"Iată, am să te învăț niște trucuri.","Давай, я покажу тебе пару секретных приёмчиков.",,Sana işin birkaç püf noktasını göstereceğim. -You're not ready yet.,TXT_RNO1_SCRIPT10_D30320_YOURE,〃 (〃),,,Ještě nejsi připraven.,Du er ikke klar endnu.,Du bist noch nicht soweit,,,Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,당신은 아직 준비가 안됐어요.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов.,,Henüz hazır değilsin. -Well have you come for tutelage or is it some ammo you're looking for? Don't think that I'm done with you yet. I've still got a few tricks up my sleeve.,TXT_DLG_SCRIPT10_D31836_WELLH,〃 (two trainings),,,"Tak co, přišel jsi sem kvůli další lekci nebo potřebuješ náboje? Nemysli si, že jsme tu skončili. Ještě mám pár triků v rukávu.","Er du kommet for at få undervisning, eller er det ammunition du leder efter? Du skal ikke tro, at jeg er færdig med dig endnu. Jeg har stadig et par tricks i ærmet.","Also, bist du zum Lernen gekommen, oder weil du mal wieder Munition brauchst? Denk bloß nicht, dass ich mit dir fertig bin. Ich habe noch ein paar Tricks auf Lager.",,,"Bien, ¿has venido a por tutela o buscas municiones? No creas que he terminado contigo. Aun tengo algunos trucos bajo la manga.",,"Oletko koulutuksen tarpeessa vai ammuksiako kaipaat? Älä luulekaan, etteikö hihassani olisi sinulle vielä muutamaa ässää jaettavana.","Vous êtes venu pour des leçons ou avez-vous besoin de munitions? Je n'ai pas encore fini avec vous, ne vous inquiétez-pas. J'ai encore des tours dans mon sac.","Valami kiképzés érdekel, vagy csak lőszerért jöttél? nehogy azt hidd, hogy végeztem veled. Még mindig rejt a tarsolyom új trükköket.","Allora, sei venuto per imparare qualcosa di nuovo o stai solo cercando munizioni? Non pensare che io abbia finito con te. Ho ancora qualche trucco da impartirti.","指導の受講か、弾薬の受け取りですか? +Co mogę dla ciebie zrobić?","Como está indo a guerra? Deixa pra lá, se nós ainda estamos aqui é porque deve estar indo bem. Como posso te ajudar?",,"Cum merge efortul de război? Nu mai contează, dacă suntem încă aici înseamnă că e bine. Ce pot face pentru tine?","Как дела на фронте? Впрочем, неважно. Наверняка всё хорошо, раз мы ещё живы. Что я могу для тебя сделать?",,"Hur går det med krigsinsatsen? Strunt samma, om vi fortfarande är här måste det gå bra. Vad kan jag göra för dig?","Savaş çabaları nasıl gidiyor? Boşver, hala burada olduğumuza göre, iyi gidiyor olmalı. Senin için ne yapabilirim?" +I ran out of bullets.,TXT_RPLY0_SCRIPT10_D30320_IRANO,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Mir ist die Munition ausgegangen.,,Mi eluzis la kuglojn.,Me he quedado sin balas.,Me quedé sin balas.,Minulta loppuivat luodit.,Je suis à court de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾を使い果たした。,탄약이 바닥났어요.,De kogels zijn op.,Jeg gikk tom for kuler.,Skończyły mi się naboje.,Fiquei sem munição.,,Am rămas fără gloanțe.,У меня кончились патроны.,,Jag fick slut på kulor.,Mermim bitti. +That should help.,TXT_RYES0_SCRIPT10_D30320_THATS,〃 (〃),,,Tohle by mělo pomoci.,Det burde hjælpe.,Das hier sollte helfen.,,Ĉi tiom devus helpi.,A ver si esto ayuda.,,Tämän pitäisi auttaa.,Cela devrait aider.,Ez majd segít.,Questo dovrebbe aiutarti.,これが助けになるでしょう。,좀 도움이 될 겁니다.,Dat zou moeten helpen.,Det burde hjelpe.,To powinno pomóc.,Isto deve ajudar.,,Asta ar trebui să ajute.,"Вот, пожалуйста.",,Det borde hjälpa.,Bunun yardımı olur. +You've got enough ammo.,TXT_RNO0_SCRIPT10_D30320_YOUVE,〃 (〃),,,Máš jich dost.,Du har nok ammunition.,Du hast genug Munition.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ne hai a sufficienza.,弾は十分に見えます。,탄약을 충분히 소지한 것 같은데.,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai destulă.,Вполне достаточно.,,Du har tillräckligt med ammunition.,Yeterince cephanen var. +Teach me.,TXT_RPLY1_SCRIPT10_D30320_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. +"Here, I'll show you a few tricks of the trade.",TXT_RYES1_SCRIPT10_D30320_HEREI,〃 (〃),,,Ukážu ti pár triků mého řemesla.,"Her, jeg skal vise dig et par tricks.","Hier, ich zeige dir mal ein paar Geheimtricks.",,"Nu, mi montros kelkajn +trompojn por spertuloj...","Bien, te mostraré +un par de trucos del oficio...","Bien, te voy a mostrar +un par de trucos del oficio.","No niin, valotan sinulle vähän alan saloja.",Voilà quelques conseils dont vous pouvez faire usage.,"Nézdd csak, mutatok neked pár trükköt.",Ora ti mostro un paio di trucchi del mestiere.,では、幾つかのコツを教えましょう。,저항군의 참된 기술들을 좀 가르쳐드리죠!,Hier zal ik je een paar trucjes van het vak laten zien.,Jeg skal vise deg noen triks.,Proszę. Oto kilka wskazówek o handlu.,"Certo, vou te mostrar alguns truques do ofício.",,"Iată, am să te învăț niște trucuri.","Давай, я покажу тебе пару секретных приёмчиков.",,"Här, jag ska visa dig några knep.",Sana işin birkaç püf noktasını göstereceğim. +You're not ready yet.,TXT_RNO1_SCRIPT10_D30320_YOURE,〃 (〃),,,Ještě nejsi připraven.,Du er ikke klar endnu.,Du bist noch nicht soweit,,"Vi ankoraŭ +ne estas preta.",Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,당신은 아직 준비가 안됐어요.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов.,,Du är inte redo än.,Henüz hazır değilsin. +Well have you come for tutelage or is it some ammo you're looking for? Don't think that I'm done with you yet. I've still got a few tricks up my sleeve.,TXT_DLG_SCRIPT10_D31836_WELLH,〃 (two trainings),,,"Tak co, přišel jsi sem kvůli další lekci nebo potřebuješ náboje? Nemysli si, že jsme tu skončili. Ještě mám pár triků v rukávu.","Er du kommet for at få undervisning, eller er det ammunition du leder efter? Du skal ikke tro, at jeg er færdig med dig endnu. Jeg har stadig et par tricks i ærmet.","Also, bist du zum Lernen gekommen, oder weil du mal wieder Munition brauchst? Denk bloß nicht, dass ich mit dir fertig bin. Ich habe noch ein paar Tricks auf Lager.",,"Nu, ĉu vi serĉas trejnadon aŭ municion? Ne kredu, ke mi finis kun vi: mi rezervas kelkajn sekretajn krizokazajn trompojn.","Bueno, ¿has venido a por tutela o por municiones? No creas que he terminado contigo: aún tengo un par de trucos bajo la manga.","Bueno, ¿viniste por tutela o por municiones? No creas que ya terminé contigo: aún tengo un par de trucos bajo la manga.","Oletko koulutuksen tarpeessa vai ammuksiako kaipaat? Älä luulekaan, etteikö hihassani olisi sinulle vielä muutamaa ässää jaettavana.","Vous êtes venu pour des leçons ou avez-vous besoin de munitions? Je n'ai pas encore fini avec vous, ne vous inquiétez-pas. J'ai encore des tours dans mon sac.","Valami kiképzés érdekel, vagy csak lőszerért jöttél? nehogy azt hidd, hogy végeztem veled. Még mindig rejt a tarsolyom új trükköket.","Allora, sei venuto per imparare qualcosa di nuovo o stai solo cercando munizioni? Non pensare che io abbia finito con te. Ho ancora qualche trucco da impartirti.","指導の受講か、弾薬の受け取りですか? まだ全て終わったわけではありません。 私の袖口に若干技術を忍ばせております。","무엇을 원하시나요? 훈련? 아니면 탄약 보급? 그리고 훈련은 아직 끝난 게 아니니까 끝날 걱정도, 다칠 고민도 하지 마시길 바랍니다.",Ben je gekomen voor voogdij of ben je op zoek naar munitie? Denk niet dat ik nog niet klaar ben met jou. Ik heb nog een paar trucjes in mijn mouw.,"Har du kommet for å få veiledning, eller er det ammunisjon du er ute etter? Ikke tro at jeg er ferdig med deg ennå. Jeg har fortsatt noen triks i ermet.","Chcesz się czegoś nauczyć czy raczej przyszedłeś po trochę amunicji? Nie myśl, że z tobą skończyłem. Wciąż mam jeszcze parę sztuczek -w zanadrzu.","Muito bem, você veio para aprender algo ou está precisando de munição? Não pense que aquilo é tudo, ainda tenho alguns truques na manga.",,"Ai venit pentru a învăța ceva sau doar pentru muniție? Să nu crezi că am terminat cu tine, încă mai am niste ași în mânecă.","Итак, ты пришёл за напутствием? Или тебе нужны боеприпасы? Не думай, что твоё обучение окончено. У меня ещё есть кое-какие козыри в рукаве!",,Özel ders için mi geldin yoksa cephane mi arıyorsun? Seninle işimin bittiğini sanma. Hala birkaç numaram var. -It's ammo for now.,TXT_RPLY0_SCRIPT10_D31836_ITSAM,〃 (〃),,,Teď tu jsem jen pro náboje.,Det er ammunition for nu.,Im Moment ist es Munition.,,,Es munición por ahora.,,Ammuksia tähän hätään.,Munitions pour l'instant.,Csak lőszer lesz most.,"Per il momento, solo munizioni.",今のところ弾薬だ。,탄약이 필요하겠네요.,Het is voorlopig munitie.,Det er ammunisjon for nå.,Tym razem chodzi o amunicję.,No momento preciso de munição.,,Muniție pentru moment.,Мне нужны боеприпасы.,,Şimdilik cephane. +w zanadrzu.","Muito bem, você veio para aprender algo ou está precisando de munição? Não pense que aquilo é tudo, ainda tenho alguns truques na manga.",,"Ai venit pentru a învăța ceva sau doar pentru muniție? Să nu crezi că am terminat cu tine, încă mai am niste ași în mânecă.","Итак, ты пришёл за напутствием? Или тебе нужны боеприпасы? Не думай, что твоё обучение окончено. У меня ещё есть кое-какие козыри в рукаве!",,Har du kommit för att få undervisning eller är det ammunition du letar efter? Tro inte att jag är klar med dig än. Jag har fortfarande några knep i ärmen.,Özel ders için mi geldin yoksa cephane mi arıyorsun? Seninle işimin bittiğini sanma. Hala birkaç numaram var. +It's ammo for now.,TXT_RPLY0_SCRIPT10_D31836_ITSAM,〃 (〃),,,Teď tu jsem jen pro náboje.,Det er ammunition for nu.,Im Moment ist es Munition.,,"Ĉi-momente, municion.","Por ahora, munición.",,Ammuksia tähän hätään.,Munitions pour l'instant.,Csak lőszer lesz most.,"Per il momento, solo munizioni.",今のところ弾薬だ。,탄약이 필요하겠네요.,Het is voorlopig munitie.,Det er ammunisjon for nå.,Tym razem chodzi o amunicję.,No momento preciso de munição.,,Muniție pentru moment.,Мне нужны боеприпасы.,,Det är ammunition för tillfället.,Şimdilik cephane. Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT10_D31836_HERES,〃 (〃),,,"Tady nějaké máš, neplýtvej s nimi.",Her er lidt ammunition til dig. Spild det ikke.,Hier hast du welche. Verschwende sie nicht.,,"Jen iom da municio. Ne malŝparu ĝin.","Aquí tienes algo de munición. -No la desperdicies.",,Tässä sinulle vähän kuteja. Älä haaskaa niitä.,Voilà des munitions. Ne les gaspillez pas.,Itt van egy kis lőszer. Ne pazarold el.,Ecco un pò di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,"좋은 병사에겐, 좋은 품질의 탄약을.",Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Tylko jej nie zmarnuj.,Leve um pouco desta munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,İşte sana biraz cephane. Boşa harcama. -You've got enough ammo.,TXT_RNO0_SCRIPT10_D31836_YOUVE,〃 (〃),,,Máš jich dost.,Du har ammunition nok.,Du hast genug Munition.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ne hai a sufficienza.,弾は十分に見えます。,아직 당신에게 탄약이 남아있는 것 같습니다만...,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai destulă muniție.,У тебя хватает патронов.,,Yeterince cephanen var. -Teach me.,TXT_RPLY1_SCRIPT10_D31836_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. -Time for the advanced lessons.,TXT_RYES1_SCRIPT10_D31836_TIMEF,〃 (〃),,,Čas na pokročilé lekce.,Tid til de avancerede lektioner.,Zeit für fortgeschrittene Lektionen.,,,Es hora de las lecciones avanzadas.,,Aika aloittaa syventävät opinnot.,Il est temps de passer à des leçons plus avancées.,Jöjjön valami komolyabb lecke.,È arrivato il momento delle lezioni avanzate.,上級レッスンの時間です。,심화학습을 할 시간이군요!,Tijd voor de gevorderde lessen voor gevorderden.,På tide med de avanserte leksjonene.,Czas na lekcje dla zaawansowanych.,Hora das aulas avançadas.,,Timpul pentru lecțiile avansate.,Пришло время для углублённого изучения оружия!,,İleri seviye ders zamanı. -You're not ready yet.,TXT_RNO1_SCRIPT10_D31836_YOURE,〃 (〃),,,Ještě nejsi připraven.,Du er ikke klar endnu.,Du bist noch nicht soweit.,,,Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,넌 아직 준비가 안됐어.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов.,,Henüz hazır değilsin. -"Well, what is it now? Don't you ever take a break? I'm glad that you're still breathing. I'd hate for my favorite student to come back looking out from the inside of a body bag.",TXT_DLG_SCRIPT10_D33352_WELLW,〃 (three trainings),,"Well, what is it now? Don't you ever take a break? I'm glad that you're still breathing. I'd hate for my favourite student to come back looking out from the inside of a body bag.","Tak, o co jde teď? Nechceš si někdy dát oraz? Jsem rád, že ještě dýcháš. Nechtěl bych, aby se mi můj oblíbený student vrátil v rakvi.","Hvad er det så nu? Tager du aldrig en pause? Jeg er glad for, at du stadig trækker vejret. Jeg ville hade, hvis min yndlingselev skulle komme tilbage og se ud fra en ligpose.","Also, was ist es dieses Mal? Machst du jemals eine Pause? Bin ich froh, dass du noch atmest.Gefiele mir nicht, meinen Lieblingschüler in einem Leichensack zurückkommen zu sehen.",,,"Bien, ¿Qué es ahora? ¿Es que nunca descansas? Me alegra que sigas respirando. Odiaría ver a mi estudiante favorito volver asomándose de dentro de una bolsa para cadáveres.",,Mikä nyt on? Etkö koskaan pidä taukoa? Onneksi henki vielä pihisee. En haluaisi lempioppilaani palaavan takaisin ruumissäkissä.,"Eh bien, comment allez vous? Vous prenez une pause de temps en temps? Je suis content de voir que vous êtes toujours vivant, çe me ferait mal de voir mon apprenti préféré dans un sac mortuaire.","Már megint mi van? Te sosem tartasz szünetet? Örülök, hogy még mindig lélegzel. Nem örülnék neki ha a kedvenc tanoncomat egy hullazsákban látnám viszont.","Ah, e adesso cosa c'è? Non ti prendi mai una pausa? Mi fa piacere vederti ancora respirare. Sarebbe tragico vedere il mio studente preferito ritornare in una sacca per cadaveri.","さて、調子はどうですか?休憩しませんか? +No la desperdicies.",,Tässä sinulle vähän kuteja. Älä haaskaa niitä.,Voilà des munitions. Ne les gaspillez pas.,Itt van egy kis lőszer. Ne pazarold el.,Ecco un po' di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,"좋은 병사에겐, 좋은 품질의 탄약을.",Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Masz tu trochę amunicji. Tylko jej nie zmarnuj.,Leve um pouco desta munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну.,,Här är lite ammunition till dig. Slösa inte bort den.,İşte sana biraz cephane. Boşa harcama. +You've got enough ammo.,TXT_RNO0_SCRIPT10_D31836_YOUVE,〃 (〃),,,Máš jich dost.,Du har ammunition nok.,Du hast genug Munition.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ne hai a sufficienza.,弾は十分に見えます。,아직 당신에게 탄약이 남아있는 것 같습니다만...,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai destulă muniție.,У тебя хватает патронов.,,Du har tillräckligt med ammunition.,Yeterince cephanen var. +Teach me.,TXT_RPLY1_SCRIPT10_D31836_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. +Time for the advanced lessons.,TXT_RYES1_SCRIPT10_D31836_TIMEF,〃 (〃),,,Čas na pokročilé lekce.,Tid til de avancerede lektioner.,Zeit für fortgeschrittene Lektionen.,,"Estas tempo por la +superaj lecionoj...","Hora de las +lecciones avanzadas...",,Aika aloittaa syventävät opinnot.,Il est temps de passer à des leçons plus avancées.,Jöjjön valami komolyabb lecke.,È arrivato il momento delle lezioni avanzate.,上級レッスンの時間です。,심화학습을 할 시간이군요!,Tijd voor de gevorderde lessen voor gevorderden.,På tide med de avanserte leksjonene.,Czas na lekcje dla zaawansowanych.,Hora das aulas avançadas.,,Timpul pentru lecțiile avansate.,Пришло время для углублённого изучения оружия!,,Dags för avancerade lektioner.,İleri seviye ders zamanı. +You're not ready yet.,TXT_RNO1_SCRIPT10_D31836_YOURE,〃 (〃),,,Ještě nejsi připraven.,Du er ikke klar endnu.,Du bist noch nicht soweit.,,"Vi ankoraŭ +ne estas preta.",Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,넌 아직 준비가 안됐어.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов.,,Du är inte redo än.,Henüz hazır değilsin. +"Well, what is it now? Don't you ever take a break? I'm glad that you're still breathing. I'd hate for my favorite student to come back looking out from the inside of a body bag.",TXT_DLG_SCRIPT10_D33352_WELLW,〃 (three trainings),,"Well, what is it now? Don't you ever take a break? I'm glad that you're still breathing. I'd hate for my favourite student to come back looking out from the inside of a body bag.","Tak, o co jde teď? Nechceš si někdy dát oraz? Jsem rád, že ještě dýcháš. Nechtěl bych, aby se mi můj oblíbený student vrátil v rakvi.","Hvad er det så nu? Tager du aldrig en pause? Jeg er glad for, at du stadig trækker vejret. Jeg ville hade, hvis min yndlingselev skulle komme tilbage og se ud fra en ligpose.","Also, was ist es dieses Mal? Machst du jemals eine Pause? Bin ich froh, dass du noch atmest.Gefiele mir nicht, meinen Lieblingschüler in einem Leichensack zurückkommen zu sehen.",,"Nu, kion ĉi-foje? Ĉu vi neniam ripozas? Ĝojigas min, ke vi ankoraŭ spiras; mi malamus, ke mia plej ŝatata studanto revenus en kadavro-sako.","Bueno, ¿qué es ahora?, ¿es que nunca descansas? Me alegra que sigas respirando; odiaría ver a mi estudiante favorito volver asomándose en una bolsa para cadáveres.",,Mikä nyt on? Etkö koskaan pidä taukoa? Onneksi henki vielä pihisee. En haluaisi lempioppilaani palaavan takaisin ruumissäkissä.,"Eh bien, comment allez vous? Vous prenez une pause de temps en temps? Je suis content de voir que vous êtes toujours vivant, çe me ferait mal de voir mon apprenti préféré dans un sac mortuaire.","Már megint mi van? Te sosem tartasz szünetet? Örülök, hogy még mindig lélegzel. Nem örülnék neki ha a kedvenc tanoncomat egy hullazsákban látnám viszont.","Ah, e adesso cosa c'è? Non ti prendi mai una pausa? Mi fa piacere vederti ancora respirare. Sarebbe tragico vedere il mio studente preferito ritornare in una sacca per cadaveri.","さて、調子はどうですか?休憩しませんか? 貴方がまだ息をしているのが喜ばしい事です。 お気に入りの生徒が死体袋から天を仰ぐ様に なるのは嫌なのです。",이번엔 또 뭔가요? 휴식을 제대로 취하지 않는 성격인가요? 그래도 몸은 멀쩡히 움직이는 것 같군요! 그토록 가르침을 받던 우수한 제자가 사체로 돌아오면 정말 슬플 테니.,"Nou, wat is het nu? Neem je nooit een pauze? Ik ben blij dat je nog steeds ademt. Ik zou het vreselijk vinden als mijn favoriete student terug zou komen met het oog op de binnenkant van een lijkzak.",Hva er det nå? Tar du aldri en pause? Jeg er glad for at du fortsatt puster. Jeg vil ikke at yndlingseleven min skal komme tilbake og se ut fra innsiden av en likpose.,"Dobra. Co tym razem? Czy ty w ogóle robisz sobie jakieś przerwy? Cieszę się, że wciąż żyjesz. Przykro by mi się zrobiło gdyby mój ulubiony uczeń -wrócił w trumnie.","Bem, o que vai ser desta vez? Será que você não descansa nunca? Ainda bem que você ainda está respirando. Eu detestaria ver meu aluno favorito voltando num saco de cadáver.",,Ce mai este? Nu iei niciodată pauză? Mă bucur că încă mai respiri. Ar fi păcat dacă cel mai bun student al meu ar veni într-un sac.,"Итак, ты справился? У тебя было время передохнуть? Рад видеть, что ты всё ещё дышишь. Мне бы не хотелось, чтобы мой лучший ученик вернулся в мешке для трупов.",,"Peki, şimdi ne var? Hiç ara vermez misin? Hâlâ nefes alıyor olmana sevindim. En sevdiğim öğrencimin bir ceset torbasının içinden bakarak geri gelmesini istemem." -I need some more bullets.,TXT_RPLY0_SCRIPT10_D33352_INEED,〃 (〃),,,Potřebuju nějaké další náboje.,Jeg har brug for flere kugler.,Ich brauche mehr Munition.,,,Necesito más balas.,,Tarvitsen lisää luoteja.,J'ai besoin de munitions.,Még több lőszerre lesz szükségem.,Ho bisogno di altre munizioni.,もっと弾が必要だ。,총알이 좀 더 필요해.,Ik heb meer kogels nodig.,Jeg trenger flere kuler.,Potrzebuję trochę naboi.,Preciso de mais munição.,,Am nevoie de niște gloanțe.,Мне нужны патроны.,,Biraz daha mermiye ihtiyacım var. -"There, don't waste it.",TXT_RYES0_SCRIPT10_D33352_THERE,〃 (〃),,,"Tady máš, neplýtvej s nimi.","Sådan, lad være med at spilde den.","Hier, verschwende sie nicht.",,,"Toma, no las desperdicies.",,"Kas tässä, älä tuhlaa niitä.","Voilà, ne les gaspillez pas.","Parancsolj, ne pazarold el.","Ecco qua, non sprecarle.",大切にして下さいね。,여기 있습니다. 낭비하지 말고 아껴 쓰세요.,"Daar, verspil het niet.","Sånn, ikke sløs dem bort.",Proszę. Nie zmarnuj ich.,Pegue. Não desperdice.,,"Iată, n-o risipi.",Вот. Не трать их попусту.,,"İşte, boşa harcama." -You have enough.,TXT_RNO0_SCRIPT10_D33352_YOUHA,〃 (〃),,,Máš jich dost.,Du har nok.,Du hast genug.,,,Tienes suficientes.,,Sinulla on tarpeeksi.,Vous en avez assez.,Már van elég.,Ne hai a sufficienza.,十分そうです。,지금도 충분한 것 같은데요.,Je hebt genoeg.,Du har nok.,Masz już ich wystarczająco dużo.,Você já tem o suficiente.,,Ai destulă.,Тебе хватает.,,Sende yeterince var. -What can you teach me?,TXT_RPLY1_SCRIPT10_D33352_WHATC,〃 (〃),,,Co mě můžeš naučit?,Hvad kan du lære mig?,Was kannst du mir beibringen?,,,¿Qué puedes enseñarme?,,Mitä voit opettaa minulle?,Que pouvez-vous m'apprendre.,Mit tudsz tanítani?,Che cosa mi puoi insegnare?,何か教えてくれないか?,나에게 뭘 가르쳐 줄 수 있죠?,Wat kun je me leren?,Hva kan du lære meg?,Czego możesz mnie nauczyć?,O que você tem pra me ensinar?,,Ce mă poți învăța?,Чему ты можешь меня научить?,,Bana ne öğretebilirsin? -"Don't get snippy, you've still some room to grow.",TXT_RYES1_SCRIPT10_D33352_DONTG,〃 (〃),,,Nebuď moc domýšlivý; ještě se máš co učit.,"Du skal ikke blive snerpet, du har stadig plads til at vokse.","Werd nicht leichtsinnig, du kannst noch einiges dazulernen.",,,"No seas insolente, aún tienes mucho que aprender.",,"Äläs rupea nokkavaksi, sinulla on vielä kasvun varaa.","Ne faites pas l'orgeuilleux, vous avez encore de quoi apprendre.","Ne hordd úgy fennt az orrod, van még mit tanulnod.","Non essere brusco, ci sono ancora cose che puoi imparare.",ぶっきらぼうにならないで、まだ成長の余地はあります。,너무 자만하지 마세요. 아직 더 배울 게 많으니까.,"Wordt niet snipperig, je hebt nog wat ruimte om te groeien.","Ikke vær frekk, du har fortsatt litt å gå på.",Nie wychylaj się. Przed tobą jeszcze długa droga.,"Vai devagar, rapaz. Você ainda tem muito o que aprender.",,"Nu fi impetinent, încă mai ai ce învăța.",Не задирай нос. Тебе ещё есть куда расти.,,"Kibirlenme, hala büyümek için yerin var." -Nothing until you're ready.,TXT_RNO1_SCRIPT10_D33352_NOTHI,〃 (〃),,,"Nic, dokud nebudeš připraven.","Intet, før du er klar.","Nichts, bevor diu nicht bereit bist.",,,Nada hasta que estés listo.,,"Ei mitään, kunnes olet valmis.",Pas avant que vous ne soyez prêt.,"Semmi, míg nem állsz készen.","Nulla al momento, finché non sarai pronto",準備が整うまで何も出来ません。,준비가 안 된 것 같으니 나중에 배웁시다.,Niets totdat je er klaar voor bent.,Ingenting før du er klar.,Na razie nic póki nie jesteś gotowy.,Nada até que você esteja preparado.,,"Nimic, până nu ești pregătit.","Ничему, пока ты не готов.",,Hazır olana kadar hiçbir şey. -"Look who's back, what's on your mind? I know it's been hard, but all of us appreciate your efforts, believe me.",TXT_DLG_SCRIPT10_D34868_LOOKW,〃 (four trainings),,,"No ne, kdopak to je? Jak se vede? Vím, že je to těžké, ale všichni si tě vážíme, věř mi.","Se, hvem der er tilbage. Hvad har du på hjerte? Jeg ved, det har været svært, men vi sætter alle pris på din indsats, tro mig.","Sieh mal an, wer zurück ist. Was gibt es? Ich weiß, es ist schwierig, aber wir alle wissen deine Arbeit zu würdigen, glaub mir.",,,"Mira quien ha vuelto, ¿Qué tienes en mente? Se que es duro, pero todos apreciamos tus esfuerzos, créeme.",,"Kukas se siinä; mitä on mielessäsi? Tiedän, että sinulla on ollut rankkaa, mutta uskothan, että me kaikki arvostamme vaivannäköäsi.","Regardez qui revient! Comment ça va? Je sais que les temps sont durs mais nous apprécions vos efforts, vraiment.","Nézzenek oda kit látnak szemeim, mi újság van veled? Tudom, hogy nem könnyű, de hidd el mindannyian értékeljük a fáradozásaidat.","Guarda chi si vede, a cosa stai pensando? Lo so che son tempi duri, ma noi tutti apprezziamo i tuoi sforzi, credimi.","誰が戻って来たかについて、貴方の考えとは? +wrócił w trumnie.","Bem, o que vai ser desta vez? Será que você não descansa nunca? Ainda bem que você ainda está respirando. Eu detestaria ver meu aluno favorito voltando num saco de cadáver.",,Ce mai este? Nu iei niciodată pauză? Mă bucur că încă mai respiri. Ar fi păcat dacă cel mai bun student al meu ar veni într-un sac.,"Итак, ты справился? У тебя было время передохнуть? Рад видеть, что ты всё ещё дышишь. Мне бы не хотелось, чтобы мой лучший ученик вернулся в мешке для трупов.",,Vad är det nu då? Tar du aldrig en paus? Jag är glad att du fortfarande andas. Jag vill inte att min favoritelev ska komma tillbaka och titta ut från insidan av en liksäck.,"Peki, şimdi ne var? Hiç ara vermez misin? Hâlâ nefes alıyor olmana sevindim. En sevdiğim öğrencimin bir ceset torbasının içinden bakarak geri gelmesini istemem." +I need some more bullets.,TXT_RPLY0_SCRIPT10_D33352_INEED,〃 (〃),,,Potřebuju nějaké další náboje.,Jeg har brug for flere kugler.,Ich brauche mehr Munition.,,Mi bezonas pliajn kuglojn.,Necesito más balas.,,Tarvitsen lisää luoteja.,J'ai besoin de munitions.,Még több lőszerre lesz szükségem.,Ho bisogno di altre munizioni.,もっと弾が必要だ。,총알이 좀 더 필요해.,Ik heb meer kogels nodig.,Jeg trenger flere kuler.,Potrzebuję trochę naboi.,Preciso de mais munição.,,Am nevoie de niște gloanțe.,Мне нужны патроны.,,Jag behöver fler kulor.,Biraz daha mermiye ihtiyacım var. +"There, don't waste it.",TXT_RYES0_SCRIPT10_D33352_THERE,〃 (〃),,,"Tady máš, neplýtvej s nimi.","Sådan, lad være med at spilde den.","Hier, verschwende sie nicht.",,"Jen, ne malŝparu ĝin.","Toma, no las desperdicies.",,"Kas tässä, älä tuhlaa niitä.","Voilà, ne les gaspillez pas.","Parancsolj, ne pazarold el.","Ecco qua, non sprecarle.",大切にして下さいね。,여기 있습니다. 낭비하지 말고 아껴 쓰세요.,"Daar, verspil het niet.","Sånn, ikke sløs dem bort.",Proszę. Nie zmarnuj ich.,Pegue. Não desperdice.,,"Iată, n-o risipi.",Вот. Не трать их попусту.,,Slösa inte bort den.,"İşte, boşa harcama." +You have enough.,TXT_RNO0_SCRIPT10_D33352_YOUHA,〃 (〃),,,Máš jich dost.,Du har nok.,Du hast genug.,,Vi havas sufiĉe.,Tienes suficientes.,,Sinulla on tarpeeksi.,Vous en avez assez.,Már van elég.,Ne hai a sufficienza.,十分そうです。,지금도 충분한 것 같은데요.,Je hebt genoeg.,Du har nok.,Masz już ich wystarczająco dużo.,Você já tem o suficiente.,,Ai destulă.,Тебе хватает.,,Du har tillräckligt.,Sende yeterince var. +What can you teach me?,TXT_RPLY1_SCRIPT10_D33352_WHATC,〃 (〃),,,Co mě můžeš naučit?,Hvad kan du lære mig?,Was kannst du mir beibringen?,,Kion vi povas instrui al mi?,¿Qué puedes enseñarme?,,Mitä voit opettaa minulle?,Que pouvez-vous m'apprendre.,Mit tudsz tanítani?,Che cosa mi puoi insegnare?,何か教えてくれないか?,나에게 뭘 가르쳐 줄 수 있죠?,Wat kun je me leren?,Hva kan du lære meg?,Czego możesz mnie nauczyć?,O que você tem pra me ensinar?,,Ce mă poți învăța?,Чему ты можешь меня научить?,,Vad kan du lära mig?,Bana ne öğretebilirsin? +"Don't get snippy, you've still some room to grow.",TXT_RYES1_SCRIPT10_D33352_DONTG,〃 (〃),,,Nebuď moc domýšlivý; ještě se máš co učit.,"Du skal ikke blive snerpet, du har stadig plads til at vokse.","Werd nicht leichtsinnig, du kannst noch einiges dazulernen.",,"Paciencon, vi ankoraŭ +havas multajn lernotaĵojn.","Paciencia, que aún tienes +mucho que aprender.",,"Äläs rupea nokkavaksi, sinulla on vielä kasvun varaa.","Ne faites pas l'orgeuilleux, vous avez encore de quoi apprendre.","Ne hordd úgy fennt az orrod, van még mit tanulnod.","Non essere brusco, ci sono ancora cose che puoi imparare.",ぶっきらぼうにならないで、まだ成長の余地はあります。,너무 자만하지 마세요. 아직 더 배울 게 많으니까.,"Wordt niet snipperig, je hebt nog wat ruimte om te groeien.","Ikke vær frekk, du har fortsatt litt å gå på.",Nie wychylaj się. Przed tobą jeszcze długa droga.,"Vai devagar, rapaz. Você ainda tem muito o que aprender.",,"Nu fi impetinent, încă mai ai ce învăța.",Не задирай нос. Тебе ещё есть куда расти.,,"Bli inte snäsig, du har fortfarande utrymme att växa.","Kibirlenme, hala büyümek için yerin var." +Nothing until you're ready.,TXT_RNO1_SCRIPT10_D33352_NOTHI,〃 (〃),,,"Nic, dokud nebudeš připraven.","Intet, før du er klar.","Nichts, bevor diu nicht bereit bist.",,"Nenion ĝis +vi estos preta.",Nada hasta que estés listo.,,"Ei mitään, kunnes olet valmis.",Pas avant que vous ne soyez prêt.,"Semmi, míg nem állsz készen.","Nulla al momento, finché non sarai pronto",準備が整うまで何も出来ません。,준비가 안 된 것 같으니 나중에 배웁시다.,Niets totdat je er klaar voor bent.,Ingenting før du er klar.,Na razie nic póki nie jesteś gotowy.,Nada até que você esteja preparado.,,"Nimic, până nu ești pregătit.","Ничему, пока ты не готов.",,Ingenting förrän du är redo.,Hazır olana kadar hiçbir şey. +"Look who's back, what's on your mind? I know it's been hard, but all of us appreciate your efforts, believe me.",TXT_DLG_SCRIPT10_D34868_LOOKW,〃 (four trainings),,,"No ne, kdopak to je? Jak se vede? Vím, že je to těžké, ale všichni si tě vážíme, věř mi.","Se, hvem der er tilbage. Hvad har du på hjerte? Jeg ved, det har været svært, men vi sætter alle pris på din indsats, tro mig.","Sieh mal an, wer zurück ist. Was gibt es? Ich weiß, es ist schwierig, aber wir alle wissen deine Arbeit zu würdigen, glaub mir.",,"Vi revenis! Pri kio vi pensas? Mi scias, ke nenio estis facila, sed ni ĉiuj taksas viajn strebojn, kredu min.","Mira quien ha vuelto. ¿En qué estás pensando? Sé que son tiempos difíciles, pero todos apreciamos tus esfuerzos, créeme.","Mira quien volvió. ¿En qué estás pensando? Sé que son tiempos difíciles, pero todos apreciamos tus esfuerzos, créeme.","Kukas se siinä; mitä on mielessäsi? Tiedän, että sinulla on ollut rankkaa, mutta uskothan, että me kaikki arvostamme vaivannäköäsi.","Regardez qui revient! Comment ça va? Je sais que les temps sont durs mais nous apprécions vos efforts, vraiment.","Nézzenek oda kit látnak szemeim, mi újság van veled? Tudom, hogy nem könnyű, de hidd el mindannyian értékeljük a fáradozásaidat.","Guarda chi si vede, a cosa stai pensando? Lo so che son tempi duri, ma noi tutti apprezziamo i tuoi sforzi, credimi.","誰が戻って来たかについて、貴方の考えとは? 困難な事だとわかっています。しかし私達全員は -貴方の努力には感謝しています。","다시 돌아오다니. 어쩐 일이십니까? 견디기 힘든 고역이었겠지만, 지금 당신은 우리들을 위해 잘 싸우고 계십니다. 믿어주세요!","Kijk eens wie er terug is, waar denk je aan? Ik weet dat het moeilijk is geweest, maar we waarderen allemaal je inspanningen, geloof me.","Se hvem som er tilbake. Hva har du på hjertet? Jeg vet at det har vært vanskelig, men vi setter pris på innsatsen din, tro meg.","Patrzcie, kto wrócił, co wam chodzi po głowie? Wiem, że było ciężko, ale wszyscy doceniamy twoje wysiłki, uwierz mi.","Olha só quem voltou. Como vai? Eu sei que tem sido difícil, mas todos nós agradecemos pelos seus esforços, vai por mim.",,"Uite cine s-a întors? La ce te gândești? Știu că a fost greu, dar toți îți apreciem eforturile, crede-mă.","Посмотрите-ка, кто вернулся. Что у тебя стряслось? Я знаю, твои задания сложны, но, поверь, мы все ценим твои усилия.",,"Bak kim gelmiş, aklında ne var? Zor olduğunu biliyorum ama hepimiz çabalarını takdir ediyoruz, inan bana." -I've run out of bullets.,TXT_RPLY0_SCRIPT10_D34868_IVERU,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Mir ist die Munition ausgegangen.,,,Me he quedado sin balas.,,Minulta on luodit loppu.,Je suis à court de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾が無くなった。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się naboje.,Fiquei sem munição.,,Am rămas fără gloanțe.,Мне нужны патроны.,,Mermim bitti. -"What else is new, here you go.",TXT_RYES0_SCRIPT10_D34868_WHATE,〃 (〃),,,Něco jiného nového? Tady máš.,"Hvad er der ellers nyt, værsgo.",Kennen wir das nicht? Hier hast du welche.,,,"Que más es nuevo, aquí tienes.",,Olipas uutinen; kas tässä.,"Rien de nouveau, voilà pour vous.","Már meg sem lepődök, parancsolj.","Nulla di nuovo sotto il sole, ecco qua.",新しい試みですか、どうぞ。,여기 탄약. 그리고 더 필요한게?,"Wat is er nog meer nieuw, alsjeblieft.",Vær så god.,"Co jeszcze jest nowe, proszę bardzo.",Que novidade. Aqui está.,,"Ce mai e nou, iată.","Знаю, знаю. Вот, держи!",,"Başka yeni ne var, al bakalım." -You have more than I can give you.,TXT_RNO0_SCRIPT10_D34868_YOUHA,〃 (〃),,,"Máš víc, než kolik ti můžu dát.","Du har mere, end jeg kan give dig.","Du hast mehr, als ich dir geben könnte.",,,Tienes más de las que podría darte.,,Sinulla on enemmän kuin voin antaa.,Vous avez plus que je ne suis autorisé à vous donner.,"Több van nálad, mint amennyit tudnék adni.",Ne hai più di quante te ne possa dare.,今渡せる以上に持ってますよ。,내가 줄 수 있는 탄약의 양보다 큰데?,Je hebt meer dan ik je kan geven.,Du har mer enn jeg kan gi deg.,Masz więcej niż mogę ci dać.,Você tem o suficiente.,,Ai mai multe decât ți-aș putea oferi.,"Да у тебя их больше, чем на нашем складе.",,Sana verebileceğimden daha fazlasına sahipsin. -Teach me what you can.,TXT_RPLY1_SCRIPT10_D34868_TEACH,〃 (〃),,,"Uč mě, co můžeš.","Lær mig, hvad du kan.",Zeig mir was du weißt.,,,Enseñame lo que puedas.,,"Opeta minulle, mitä voit.",Enseignez-moi ce que vous pouvez.,Tanítsd meg amit tudsz.,Potresti insegnarmi ciò che puoi.,可能な限り教えてくれ。,가르칠 수 있는 걸 가르쳐주세요.,Leer me wat je kunt.,Lær meg det du kan.,"Naucz mnie tego, co potrafisz.",O que você pode me ensinar?,,Învață-mă ce poți.,"Научи меня, чему можешь.",,Bana öğretebileceğin kadarını öğret. -"All right, here's some pointers.",TXT_RYES1_SCRIPT10_D34868_ALLRI,〃 (〃),,,"Dobře, tady je pár tipů.","Okay, her er nogle tips.","Ok, ich erklär dir ein paar Tricks.",,,"Muy bien, aquí tienes unos consejos.",,"Hyvä on, tässä muutama vinkki.",Voilà deux ou trois trucs.,"Rendben, itt van pár tanács.","Va bene, ecco qualche dritta.",わかりました、貴方に幾つかやり方を教ましょう。,알겠습니다. 여기 과녁을 보여주지.,"Oké, hier zijn wat aanwijzingen.","Greit, her har du noen tips.","W porządku, oto kilka wskazówek.","Tá legal, aqui vai algumas dicas.",,"În regulă, uite niște repere.",Ну хорошо. Вот пара советов.,,"Pekala, işte birkaç ipucu." -Not right now.,TXT_RNO1_SCRIPT10_D34868_NOTRI,〃 (〃),,,Zrovna teď ne.,Ikke lige nu.,Nicht jetzt.,,Ne nun.,Ahora no.,,Ei juuri nyt.,Pas maintenant.,Most nem érek rá.,Non adesso.,今はまだです。,지금은 안 돼요.,Niet op dit moment.,Ikke akkurat nå.,Nie teraz.,Agora não.,,Nu chiar acum.,Не сейчас.,,Şimdi olmaz. -What is it you need? I hope that you're giving the Order a taste of the kind of pain that we have been feeling for years.,TXT_DLG_SCRIPT10_D36384_WHATI,〃 (five trainings),,,"Copak potřebuješ? Doufám, že oplácíš Řádu to, co nám celé ty roky dělali.","Hvad er det, du har brug for? Jeg håber, at du giver Ordenen en smagsprøve på den slags smerte, som vi har følt i årevis.","Was brauchst du? Ich hoffe, du gibst dem Orden etwas von dem Schmerz zurück, den sie und allen haben zukommen lassen.",,,¿Qué necesitas? Espero que le estés dando a la Orden un poco del tipo de dolor que hemos estado sufriendo durante años.,,"Mitä tarvitset? Toivottavasti annat Veljeskunnan maistaa sitä tuskaa, jota me olemme tunteneet vuosia.",De quoi avez-vous besoin? J'espère que vous donnez à l'Ordre une idée de la douleur que nous avons ressenti pendant des années.,"Miben segíthetek? Remélem megízlettetted a Rendet ugyanazzal a fájdalommal, amit mi éreztünk eddig.",Di che cosa hai bisogno? Spero che tu stia dando all'Ordine un assaggio del tipo di dolore che noi abbiamo tollerato per anni.,"必要な物は何ですか?私達が何年も前から感じた +貴方の努力には感謝しています。","다시 돌아오다니. 어쩐 일이십니까? 견디기 힘든 고역이었겠지만, 지금 당신은 우리들을 위해 잘 싸우고 계십니다. 믿어주세요!","Kijk eens wie er terug is, waar denk je aan? Ik weet dat het moeilijk is geweest, maar we waarderen allemaal je inspanningen, geloof me.","Se hvem som er tilbake. Hva har du på hjertet? Jeg vet at det har vært vanskelig, men vi setter pris på innsatsen din, tro meg.","Patrzcie, kto wrócił, co wam chodzi po głowie? Wiem, że było ciężko, ale wszyscy doceniamy twoje wysiłki, uwierz mi.","Olha só quem voltou. Como vai? Eu sei que tem sido difícil, mas todos nós agradecemos pelos seus esforços, vai por mim.",,"Uite cine s-a întors? La ce te gândești? Știu că a fost greu, dar toți îți apreciem eforturile, crede-mă.","Посмотрите-ка, кто вернулся. Что у тебя стряслось? Я знаю, твои задания сложны, но, поверь, мы все ценим твои усилия.",,"Titta vem som är tillbaka, vad tänker du på? Jag vet att det har varit svårt, men alla uppskattar dina ansträngningar, tro mig.","Bak kim gelmiş, aklında ne var? Zor olduğunu biliyorum ama hepimiz çabalarını takdir ediyoruz, inan bana." +I've run out of bullets.,TXT_RPLY0_SCRIPT10_D34868_IVERU,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Mir ist die Munition ausgegangen.,,Mi eluzis la kuglojn.,Me he quedado sin balas.,Me quedé sin balas.,Minulta on luodit loppu.,Je suis à court de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾が無くなった。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się naboje.,Fiquei sem munição.,,Am rămas fără gloanțe.,Мне нужны патроны.,,Jag har slut på kulor.,Mermim bitti. +"What else is new, here you go.",TXT_RYES0_SCRIPT10_D34868_WHATE,〃 (〃),,,Něco jiného nového? Tady máš.,"Hvad er der ellers nyt, værsgo.",Kennen wir das nicht? Hier hast du welche.,,Nenio nova. Jen.,Qué novedad. Toma.,,Olipas uutinen; kas tässä.,"Rien de nouveau, voilà pour vous.","Már meg sem lepődök, parancsolj.","Nulla di nuovo sotto il sole, ecco qua.",新しい試みですか、どうぞ。,여기 탄약. 그리고 더 필요한게?,"Wat is er nog meer nieuw, alsjeblieft.",Vær så god.,"Co jeszcze jest nowe, proszę bardzo.",Que novidade. Aqui está.,,"Ce mai e nou, iată.","Знаю, знаю. Вот, держи!",,"Vad mer är nytt, här har du.","Başka yeni ne var, al bakalım." +You have more than I can give you.,TXT_RNO0_SCRIPT10_D34868_YOUHA,〃 (〃),,,"Máš víc, než kolik ti můžu dát.","Du har mere, end jeg kan give dig.","Du hast mehr, als ich dir geben könnte.",,"Vi havas pli ol tiom, +kiom mi povas doni.","Tienes más de +las que podría darte.",,Sinulla on enemmän kuin voin antaa.,Vous avez plus que je ne suis autorisé à vous donner.,"Több van nálad, mint amennyit tudnék adni.",Ne hai più di quante te ne possa dare.,今渡せる以上に持ってますよ。,내가 줄 수 있는 탄약의 양보다 큰데?,Je hebt meer dan ik je kan geven.,Du har mer enn jeg kan gi deg.,Masz więcej niż mogę ci dać.,Você tem o suficiente.,,Ai mai multe decât ți-aș putea oferi.,"Да у тебя их больше, чем на нашем складе.",,Du har mer än vad jag kan ge dig.,Sana verebileceğimden daha fazlasına sahipsin. +Teach me what you can.,TXT_RPLY1_SCRIPT10_D34868_TEACH,〃 (〃),,,"Uč mě, co můžeš.","Lær mig, hvad du kan.",Zeig mir was du weißt.,,Instruu ion ajn al mi.,Enséñame lo que puedas.,,"Opeta minulle, mitä voit.",Enseignez-moi ce que vous pouvez.,Tanítsd meg amit tudsz.,Potresti insegnarmi ciò che puoi.,可能な限り教えてくれ。,가르칠 수 있는 걸 가르쳐주세요.,Leer me wat je kunt.,Lær meg det du kan.,"Naucz mnie tego, co potrafisz.",O que você pode me ensinar?,,Învață-mă ce poți.,"Научи меня, чему можешь.",,Lär mig vad du kan.,Bana öğretebileceğin kadarını öğret. +"All right, here's some pointers.",TXT_RYES1_SCRIPT10_D34868_ALLRI,〃 (〃),,,"Dobře, tady je pár tipů.","Okay, her er nogle tips.","Ok, ich erklär dir ein paar Tricks.",,"Bone, jen kelkaj konsiloj...","Muy bien, ahí van +unos consejos...",,"Hyvä on, tässä muutama vinkki.",Voilà deux ou trois trucs.,"Rendben, itt van pár tanács.","Va bene, ecco qualche dritta.",わかりました、貴方に幾つかやり方を教ましょう。,알겠습니다. 여기 과녁을 보여주지.,"Oké, hier zijn wat aanwijzingen.","Greit, her har du noen tips.","W porządku, oto kilka wskazówek.","Tá legal, aqui vai algumas dicas.",,"În regulă, uite niște repere.",Ну хорошо. Вот пара советов.,,"Okej, här är några tips.","Pekala, işte birkaç ipucu." +Not right now.,TXT_RNO1_SCRIPT10_D34868_NOTRI,〃 (〃),,,Zrovna teď ne.,Ikke lige nu.,Nicht jetzt.,,Ne nun.,Ahora no.,,Ei juuri nyt.,Pas maintenant.,Most nem érek rá.,Non adesso.,今はまだです。,지금은 안 돼요.,Niet op dit moment.,Ikke akkurat nå.,Nie teraz.,Agora não.,,Nu chiar acum.,Не сейчас.,,Inte just nu.,Şimdi olmaz. +What is it you need? I hope that you're giving the Order a taste of the kind of pain that we have been feeling for years.,TXT_DLG_SCRIPT10_D36384_WHATI,〃 (five trainings),,,"Copak potřebuješ? Doufám, že oplácíš Řádu to, co nám celé ty roky dělali.","Hvad er det, du har brug for? Jeg håber, at du giver Ordenen en smagsprøve på den slags smerte, som vi har følt i årevis.","Was brauchst du? Ich hoffe, du gibst dem Orden etwas von dem Schmerz zurück, den sie und allen haben zukommen lassen.",,"Kion vi bezonas? Mi esperas, ke vi redonas al La Ordeno tian doloron, kian ni suferis dum jaroj.",¿Qué necesitas? Espero que le estés devolviendo a La Orden parte del dolor que hemos estado sufriendo durante años.,,"Mitä tarvitset? Toivottavasti annat Veljeskunnan maistaa sitä tuskaa, jota me olemme tunteneet vuosia.",De quoi avez-vous besoin? J'espère que vous donnez à l'Ordre une idée de la douleur que nous avons ressenti pendant des années.,"Miben segíthetek? Remélem megízlettetted a Rendet ugyanazzal a fájdalommal, amit mi éreztünk eddig.",Di che cosa hai bisogno? Spero che tu stia dando all'Ordine un assaggio del tipo di dolore che noi abbiamo tollerato per anni.,"必要な物は何ですか?私達が何年も前から感じた 多くの苦痛の味をオーダーに与えることを -願っています。",필요한 게 있습니까? 수 년 동안 고통을 안겨 온 오더 놈들에게 복수를 해줬으면 하는 바입니다. 끝날 때까지!,Wat heb je nodig? Ik hoop dat je de Orde een voorproefje geeft van het soort pijn dat we al jaren voelen.,Hva er det du trenger? Jeg håper du gir Ordenen en forsmak på den smerten vi har følt i årevis.,"Czego potrzebujesz? Mam nadzieję, że dajesz Zakonowi przedsmak bólu, który odczuwamy od lat.",O que está precisando? Espero que você esteja fazendo a Ordem sentir um pouco do sofrimento que nós estivemos passando por anos.,,De ce ai nevoie? Sper că îi dai Ordinului aceeași durere pe care și el ne-a oferit-o în toți acești ani.,"Что тебе нужно? Надеюсь, ты даёшь Ордену почувствовать ту боль, что мы терпели годами.",,Neye ihtiyacın var? Umarım Tarikat'a yıllardır hissettiğimiz acıyı tattırıyorsundur. -Some ammo.,TXT_RPLY0_SCRIPT10_D36384_SOMEA,〃 (〃),,,Nějakou munici.,Lidt ammunition.,Etwas Munition.,,,Algo de munición.,,Vähän ammuksia.,Des munitions.,Valamennyi lőszer.,Un poco di munizioni.,弾を幾つか。,탄약 좀...,Wat munitie.,Litt ammunisjon.,Trochę amunicji.,Um pouco de munição.,,Niște muniție.,Боеприпасы.,,Biraz cephane. -"There you go, don't waste it.",TXT_RYES0_SCRIPT10_D36384_THERE,〃 (〃),,,"Tady máš, neplýtvej s ní.","Værsgo, lad være med at spilde den.",Hier hast du welche. Verschwende sie nicht.,,Jen. Ne malŝparu ĝin.,"Toma, no las desperdicies.",,"Ole hyvä, älä tuhlaa niitä.",Voilà pour vous. Ne les gaspillez pas.,"Parancsolj, ne pazarold el.","Ecco delle munizioni, non sprecarle.",はいどうぞ、無駄にしないように。,전장을 자주 누비나 보군요. 여기 탄약!,"Daar ga je, verspil het niet.","Vær så god, ikke sløs den bort.","Proszę bardzo, nie marnuj jej.",Aqui está. Não desperdice.,,"Iată, n-o risipi.",Вот. Не трать их попусту.,,"Al bakalım, boşa harcama." -You've got enough ammo.,TXT_RNO0_SCRIPT10_D36384_YOUVE,〃 (〃),,,Máš jí dost.,Du har nok ammunition.,Du hast genug Munition.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ne hai a sufficienza.,弾は十分に見えます。,당신의 남은 탄약이 눈에 보이는군요. 줄 수 없습니다!,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczająco dużo amunicji.,Você tem munição suficiente.,,Ai destulă muniție.,У тебя хватает патронов.,,Yeterince cephanen var. -Teach me.,TXT_RPLY1_SCRIPT10_D36384_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. -A few more lessons and you'll know all that I can teach.,TXT_RYES1_SCRIPT10_D36384_AFEWM,〃 (〃),,,"Pár dalších lekcí a budeš vědět všechno, co vím.","Et par lektioner mere, og du vil vide alt, hvad jeg kan lære dig.","Ein paar mehr Lektionen, und du weißt alles, was ich weiß.",,,Unas cuantas lecciones más y sabrás todo lo que puedo enseñar.,,"Enää vain muutama oppitunti ja tiedät kaiken, mitä voin opettaa.",Quelque leçons en plus et vous saurez tout ce que je peux vous enseigner.,"Még pár lecke, és mindent tudni fogsz amit Én.",Tra un paio di lezioni saprai tutto quello che conosco.,もう少しで私の教えられる事が全てわかるはずです。,제가 가르칠 만한 훈련을 배우면 좀 똑똑해질 겁니다.,Nog een paar lessen en je weet alles wat ik je kan leren.,"Et par leksjoner til, så vet du alt jeg kan lære deg.","Jeszcze kilka lekcji i będziesz wiedział wszystko, czego mogę nauczyć.",Mais algumas aulas e você já saberá tudo o que consigo ensinar.,,"Câteva lecții, și vei știi tot ce știu si eu.","Ещё немного, и ты будешь знать всё, что знаю я.",,Birkaç ders daha ve öğretebileceğim her şeyi öğreneceksin. -You're not ready yet.,TXT_RNO1_SCRIPT10_D36384_YOURE,〃 (〃),,,Ještě nejsi připraven.,Du er ikke klar endnu.,Du bist noch nicht soweit.,,,Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,훈련받기엔 가깝지만서도... 먼 것 같습니다.,Je bent er nog niet klaar voor.,Du er ikke klar ennå.,Nie jesteś jeszcze gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов.,,Henüz hazır değilsin. -"I can't believe that we're still around, you and I. There's just too many of us that have passed since the beginning. What can I do for you friend?",TXT_DLG_SCRIPT10_D37900_ICANT,〃 (six trainings),,,"Nemůžu uvěřit, že tu my dva stále ještě jsme. Hrozně moc z nás za tu dobu zahynulo. Co pro tebe mohu udělat, příteli?","Jeg kan ikke tro, at vi stadig er her, du og jeg. Der er bare for mange af os, der er gået siden begyndelsen. Hvad kan jeg gøre for dig, min ven?","Ich kann kaum glauben, dass wir immer noch da sind, du und ich. Es sind so viele, die uns verlassen haben, seit alles anfing. Was kann ich für dich tun, Freund?",,,"No puedo creer que sigamos aquí tú y yo. Hemos perdidos a tantos desde que todo empezó... ¿Qué puedo hacer por ti, amigo?",,"En voi uskoa, että olemme vielä kuvioissa, sinä ja minä. Aivan liian moni on poistunut keskuudestamme sitten, kun kaikki tämä alkoi. Miten voin olla avuksi, ystäväni?","J'arrive pas a croire que vous êtes toujours avec nous. Tellement de nos camarades ont disparu depuis que tout a commencé. Que puis-je faire pour vous, mon ami?","Nem hiszem el, hogy eddig túléltük ezt. Sokan vesztették életüket a kezdetek óta. Mit tehetek érted barátom?","Non posso credere che siamo ancora vivi, tu e io. Ce ne sono così tanti che sono morti da quando è iniziata questa faccenda. Che cosa posso fare per te, amico?","私達はまだ貴方の護衛をし続けられるとは +願っています。",필요한 게 있습니까? 수 년 동안 고통을 안겨 온 오더 놈들에게 복수를 해줬으면 하는 바입니다. 끝날 때까지!,Wat heb je nodig? Ik hoop dat je de Orde een voorproefje geeft van het soort pijn dat we al jaren voelen.,Hva er det du trenger? Jeg håper du gir Ordenen en forsmak på den smerten vi har følt i årevis.,"Czego potrzebujesz? Mam nadzieję, że dajesz Zakonowi przedsmak bólu, który odczuwamy od lat.",O que está precisando? Espero que você esteja fazendo a Ordem sentir um pouco do sofrimento que nós estivemos passando por anos.,,De ce ai nevoie? Sper că îi dai Ordinului aceeași durere pe care și el ne-a oferit-o în toți acești ani.,"Что тебе нужно? Надеюсь, ты даёшь Ордену почувствовать ту боль, что мы терпели годами.",,Vad är det du behöver? Jag hoppas att du ger Orden en smak av den typ av smärta som vi har känt i åratal.,Neye ihtiyacın var? Umarım Tarikat'a yıllardır hissettiğimiz acıyı tattırıyorsundur. +Some ammo.,TXT_RPLY0_SCRIPT10_D36384_SOMEA,〃 (〃),,,Nějakou munici.,Lidt ammunition.,Etwas Munition.,,Iom da municio.,Algo de munición.,,Vähän ammuksia.,Des munitions.,Valamennyi lőszer.,Un poco di munizioni.,弾を幾つか。,탄약 좀...,Wat munitie.,Litt ammunisjon.,Trochę amunicji.,Um pouco de munição.,,Niște muniție.,Боеприпасы.,,Lite ammunition.,Biraz cephane. +"There you go, don't waste it.",TXT_RYES0_SCRIPT10_D36384_THERE,〃 (〃),,,"Tady máš, neplýtvej s ní.","Værsgo, lad være med at spilde den.",Hier hast du welche. Verschwende sie nicht.,,Jen. Ne malŝparu ĝin.,"Toma, no las desperdicies.",,"Ole hyvä, älä tuhlaa niitä.",Voilà pour vous. Ne les gaspillez pas.,"Parancsolj, ne pazarold el.","Ecco delle munizioni, non sprecarle.",はいどうぞ、無駄にしないように。,전장을 자주 누비나 보군요. 여기 탄약!,"Daar ga je, verspil het niet.","Vær så god, ikke sløs den bort.","Proszę bardzo, nie marnuj jej.",Aqui está. Não desperdice.,,"Iată, n-o risipi.",Вот. Не трать их попусту.,,"Varsågod, slösa inte bort den.","Al bakalım, boşa harcama." +You've got enough ammo.,TXT_RNO0_SCRIPT10_D36384_YOUVE,〃 (〃),,,Máš jí dost.,Du har nok ammunition.,Du hast genug Munition.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ne hai a sufficienza.,弾は十分に見えます。,당신의 남은 탄약이 눈에 보이는군요. 줄 수 없습니다!,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczająco dużo amunicji.,Você tem munição suficiente.,,Ai destulă muniție.,У тебя хватает патронов.,,Du har tillräckligt med ammunition.,Yeterince cephanen var. +Teach me.,TXT_RPLY1_SCRIPT10_D36384_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. +A few more lessons and you'll know all that I can teach.,TXT_RYES1_SCRIPT10_D36384_AFEWM,〃 (〃),,,"Pár dalších lekcí a budeš vědět všechno, co vím.","Et par lektioner mere, og du vil vide alt, hvad jeg kan lære dig.","Ein paar mehr Lektionen, und du weißt alles, was ich weiß.",,"Ankoraŭ unu leciono kaj +vi lernis ĉion, kion mi scias.","Una lección más y +sabrás todo lo que sé.","Una lección más y +vas a saber todo lo que sé.","Enää vain muutama oppitunti ja tiedät kaiken, mitä voin opettaa.",Quelque leçons en plus et vous saurez tout ce que je peux vous enseigner.,"Még pár lecke, és mindent tudni fogsz amit Én.",Tra un paio di lezioni saprai tutto quello che conosco.,もう少しで私の教えられる事が全てわかるはずです。,제가 가르칠 만한 훈련을 배우면 좀 똑똑해질 겁니다.,Nog een paar lessen en je weet alles wat ik je kan leren.,"Et par leksjoner til, så vet du alt jeg kan lære deg.","Jeszcze kilka lekcji i będziesz wiedział wszystko, czego mogę nauczyć.",Mais algumas aulas e você já saberá tudo o que consigo ensinar.,,"Câteva lecții, și vei știi tot ce știu si eu.","Ещё немного, и ты будешь знать всё, что знаю я.",,Några lektioner till och du kommer att veta allt jag kan lära dig.,Birkaç ders daha ve öğretebileceğim her şeyi öğreneceksin. +You're not ready yet.,TXT_RNO1_SCRIPT10_D36384_YOURE,〃 (〃),,,Ještě nejsi připraven.,Du er ikke klar endnu.,Du bist noch nicht soweit.,,"Vi ankoraŭ +ne estas preta.",Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,貴方の準備がまだ整ってないように思えます。,훈련받기엔 가깝지만서도... 먼 것 같습니다.,Je bent er nog niet klaar voor.,Du er ikke klar ennå.,Nie jesteś jeszcze gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов.,,Du är inte redo än.,Henüz hazır değilsin. +"I can't believe that we're still around, you and I. There's just too many of us that have passed since the beginning. What can I do for you friend?",TXT_DLG_SCRIPT10_D37900_ICANT,〃 (six trainings),,,"Nemůžu uvěřit, že tu my dva stále ještě jsme. Hrozně moc z nás za tu dobu zahynulo. Co pro tebe mohu udělat, příteli?","Jeg kan ikke tro, at vi stadig er her, du og jeg. Der er bare for mange af os, der er gået siden begyndelsen. Hvad kan jeg gøre for dig, min ven?","Ich kann kaum glauben, dass wir immer noch da sind, du und ich. Es sind so viele, die uns verlassen haben, seit alles anfing. Was kann ich für dich tun, Freund?",,"Estas nekredeble, ke vi kaj ni estas ankoraŭ vivaj. Ni perdis tiom multe da homoj de kiam ĉio ekis... Kion mi povas fari por vi, amiko?","No puedo creer que sigamos aquí tú y yo. Hemos perdidos a tantos desde que todo empezó... ¿Qué puedo hacer por ti, amigo?",,"En voi uskoa, että olemme vielä kuvioissa, sinä ja minä. Aivan liian moni on poistunut keskuudestamme sitten, kun kaikki tämä alkoi. Miten voin olla avuksi, ystäväni?","J'arrive pas a croire que vous êtes toujours avec nous. Tellement de nos camarades ont disparu depuis que tout a commencé. Que puis-je faire pour vous, mon ami?","Nem hiszem el, hogy eddig túléltük ezt. Sokan vesztették életüket a kezdetek óta. Mit tehetek érted barátom?","Non posso credere che siamo ancora vivi, tu e io. Ce ne sono così tanti che sono morti da quando è iniziata questa faccenda. Che cosa posso fare per te, amico?","私達はまだ貴方の護衛をし続けられるとは 思えません。昔からの仲間は殆ど去って しまいました。貴方の友人の為に -何がしてあげられますか?",아직도 살아 숨 쉬고 있다니 믿기지 않네요... 당신이 싸우고 생존하는 동안 살아 돌아온 병사들은 그렇게 많지 않아요. 원하는 게 있습니까?,"Ik kan niet geloven dat we er nog steeds zijn, jij en ik. Er zijn er gewoon te veel van ons die sinds het begin zijn overleden. Wat kan ik voor je doen, vriend?","Jeg kan ikke tro at vi fortsatt er her, du og jeg. Det er for mange av oss som har gått bort siden begynnelsen. Hva kan jeg gjøre for deg, min venn?","Nie mogę uwierzyć, że jeszcze żyjemy, ty i ja. Zbyt wielu z nas przeszło od początku. Co mogę dla ciebie zrobić, przyjacielu?","Mal consigo acreditar que ainda estamos vivos, você e eu. Perdemos muitos companheiros desde o início. O que posso fazer por você, meu amigo?",,"Nu-mi vine că cred că încă mai rezistăm, tu și eu. Sunt prea mulți cei care au murit de la început. Ce pot face pentru tine, prietene?","Не могу поверить, что мы всё ещё живы, ты и я. За всё это время уже стольких из нас не стало. Что я могу сделать для тебя, дружище?",,"Hala buralarda olduğumuza inanamıyorum, sen ve ben. Başlangıçtan bu yana çok fazla insan geçti. Senin için ne yapabilirim dostum?" -I'm out of bullets.,TXT_RPLY0_SCRIPT10_D37900_IMOUT,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi estas sen kugloj.,No me quedan balas.,,Minulta on luodit loppu.,Je suis à court de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się kule.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны.,,Mermim bitti. +何がしてあげられますか?",아직도 살아 숨 쉬고 있다니 믿기지 않네요... 당신이 싸우고 생존하는 동안 살아 돌아온 병사들은 그렇게 많지 않아요. 원하는 게 있습니까?,"Ik kan niet geloven dat we er nog steeds zijn, jij en ik. Er zijn er gewoon te veel van ons die sinds het begin zijn overleden. Wat kan ik voor je doen, vriend?","Jeg kan ikke tro at vi fortsatt er her, du og jeg. Det er for mange av oss som har gått bort siden begynnelsen. Hva kan jeg gjøre for deg, min venn?","Nie mogę uwierzyć, że jeszcze żyjemy, ty i ja. Zbyt wielu z nas przeszło od początku. Co mogę dla ciebie zrobić, przyjacielu?","Mal consigo acreditar que ainda estamos vivos, você e eu. Perdemos muitos companheiros desde o início. O que posso fazer por você, meu amigo?",,"Nu-mi vine că cred că încă mai rezistăm, tu și eu. Sunt prea mulți cei care au murit de la început. Ce pot face pentru tine, prietene?","Не могу поверить, что мы всё ещё живы, ты и я. За всё это время уже стольких из нас не стало. Что я могу сделать для тебя, дружище?",,"Jag kan inte tro att vi fortfarande finns kvar, du och jag. Det är bara för många av oss som har passerat sedan början. Vad kan jag göra för dig, min vän?","Hala buralarda olduğumuza inanamıyorum, sen ve ben. Başlangıçtan bu yana çok fazla insan geçti. Senin için ne yapabilirim dostum?" +I'm out of bullets.,TXT_RPLY0_SCRIPT10_D37900_IMOUT,〃 (〃),,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi ne havas kuglojn.,No me quedan balas.,,Minulta on luodit loppu.,Je suis à court de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się kule.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны.,,Jag har slut på kulor.,Mermim bitti. "Here, use them to keep you in good health.",TXT_RYES0_SCRIPT10_D37900_HEREU,"〃 (〃) (in good health = enjoy)",,,"Tady, používej je, abys zůstal ve zdraví.","Her, brug dem til at holde dig sund og rask.","Hier, benutze sie um gesund zu bleiben,",,"Jen iom da municio. Ŝancon kaj ĝuu ĝin.","Aquí tienes algo de munición. -Suerte y disfrútala.",,"Tässä, pidä niillä itsesi terveenä.","Voilà, gardez vous en bonne santé.","Parancsolj, használd őket az egészséged érdekében.","Ecco qua, usale per tenerti in buona salute.",どうぞ、これで体の調子を保って下さい。,건강하고 집중됬을 때 소모하시길.,"Hier, gebruik ze om je in goede gezondheid te houden.","Her, bruk dem til å holde deg ved god helse.","Użyj ich, by utrzymać cię w dobrym zdrowiu.",Pode pegar. Use essa munição para se manter saudável.,,"Aici, folosește-le ca să te menții în formă.","Вот. Используй их, чтобы сохранить себя.",,"Al, onları sağlığını korumak için kullan." -You have enough.,TXT_RNO0_SCRIPT10_D37900_YOUHA,〃 (〃),,,Máš jich dost.,Du har nok.,Du hast genug.,,Vi havas sufiĉe.,Tienes suficientes.,,Sinulla on tarpeeksi.,Vous en avez assez.,Van elég.,Ne hai a sufficienza.,十分に持っています。,충분히 있으면 더 안 줘요.,Je hebt genoeg.,Du har nok.,Masz wystarczająco dużo.,Você tem o suficiente.,,Ai destule.,Тебе хватает.,,Sende yeterince var. -Teach me.,TXT_RPLY1_SCRIPT10_D37900_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. -"Well, that's it, you're done. I can teach no more.",TXT_RYES1_SCRIPT10_D37900_WELLT,〃 (〃),,,"Tak, a je to, jsme hotovi. Víc tě naučit nemůžu.","Nå, det var det, du er færdig. Jeg kan ikke undervise mere.","So, das war's. Ich kann dir nicht mehr beibringen.",,,"Bueno, eso es todo, estás listo. No tengo más que enseñar.",,"No, se oli siinä, olet valmis. Minulla ei ole sinulle enää opetettavaa.","Eh bien, voilà. Vous savez tout. Je n'ai rien de plus pour vous!","Elérkeztünk oda, hogy nem tudok többet tanítani neked.","Beh, ecco fatto, oramai hai concluso. Non c'è null'altro che ti possa insegnare.",これで全てです。これ以上は教える事がありません。,"흐음, 이게 다입니다. 훈련을 다 마쳤어요.","Nou, dat is het dan, je bent klaar. Ik kan geen les meer geven.","Vel, det var det, du er ferdig. Jeg kan ikke lære deg mer.","No cóż, to już koniec. Nie mogę więcej uczyć.","Bom, é isso. Você já sabe de tudo. Não consigo ensinar mais nada.",,"Asta e, gata, nu mai am ce să te învăț.","Что ж, это всё. Твоё обучение закончено. Больше я ничему не могу тебя научить.",,"Pekala, bu kadar, işin bitti. Daha fazla öğretemem." -Return after Macil tells you it's time.,TXT_RNO1_SCRIPT10_D37900_RETUR,〃 (〃),,,"Vrať se až ti Macil řekne, že je čas.","Vend tilbage, når Macil siger, at det er tid.","Komm wieder, wenn Macil sagt, dass es Zeit ist.",,,Vuelve cuando Macil diga que es la hora.,,"Palaa sitten, kun Macil kertoo sinulle ajan koittaneen.",Revenez quand Macil vous dit qu'il est temps.,"Ha Macil szól hogy idő van, akkor fordulj vissza.",Ritorna quando Macil dice che è arrivato il momento.,マシルに許可を貰わないとなりません。,사령관님의 말씀을 듣고 찾아와주시길.,Keer terug nadat Macil je vertelt dat het tijd is.,Kom tilbake når Macil sier det er på tide.,"Wróć, gdy Macil powie ci, że już czas.",Volte depois que Macil te disser que está na hora.,,Întoarce-te după ce Macil îți spune că e vremea.,"Возвращайся, когда скажет Мэйсил.",,Macil sana zamanın geldiğini söylediğinde geri dön. -"I've taught you everything I can right now. I've given you all that you should ever need, unless you're out of bullets. Those I can still help you with.",TXT_DLG_SCRIPT10_D39416_IVETA,〃 (seven trainings),,,"Naučil jsem tě vše, co teď můžu. Dal jsem ti vše, co bys měl potřebovat, ledaže by ti došly náboje. S těmi ti stále můžu pomoci.","Jeg har lært dig alt, hvad jeg kan lige nu. Jeg har givet dig alt, hvad du nogensinde skulle få brug for, medmindre du er løbet tør for kugler. Dem kan jeg stadig hjælpe dig med.","Ich habe dir alles beigebracht, was ich weiß. Das sollte alles sein, was du brauchen wirst, es sei denn, du brauchst wieder mal Munition. Damit kann ich dir jederzeit helfen.",,,"Te he enseñado todo lo que puedo por ahora. Te he dado todo lo que puedas necesitar, a menos que te hayas quedado sin balas. Con eso si que te puedo ayudar todavía.",,"Olen opettanut sinulle kaiken osaamani. Olen antanut sinulle kaiken, mitä ikinä voisit tarvita, ellei sinulta sitten ole luodit loppu. Niiden suhteen voin vielä olla avuksi.","Je vous ai enseigné tout ce que je sais, et tout ce qu'il vous faudra, sauf si n'avez plus de munitions.. Et je peux vous aider pour ça, aussi.","Megtanítottam neked mindent amire most képes vagyok. Mindent megadtam neked amire valaha szükséged lehet, kivétel persze ha kifogysz a golyókból. Azt még mindig tudok adni.","Ti ho insegnato tutto quello che conosco. Ti ho dato tutto ciò di cui avrai mai bisogno, a meno che non hai finito le munizioni. Con quelle ti posso ancora essere d'aiuto.","私が教えられる事はもうありません。 +Suerte y disfrútala.",,"Tässä, pidä niillä itsesi terveenä.","Voilà, gardez vous en bonne santé.","Parancsolj, használd őket az egészséged érdekében.","Ecco qua, usale per tenerti in buona salute.",どうぞ、これで体の調子を保って下さい。,건강하고 집중됬을 때 소모하시길.,"Hier, gebruik ze om je in goede gezondheid te houden.","Her, bruk dem til å holde deg ved god helse.","Użyj ich, by utrzymać cię w dobrym zdrowiu.",Pode pegar. Use essa munição para se manter saudável.,,"Aici, folosește-le ca să te menții în formă.","Вот. Используй их, чтобы сохранить себя.",,"Här, använd dem för att hålla dig vid god hälsa.","Al, onları sağlığını korumak için kullan." +You have enough.,TXT_RNO0_SCRIPT10_D37900_YOUHA,〃 (〃),,,Máš jich dost.,Du har nok.,Du hast genug.,,Vi havas sufiĉe.,Tienes suficientes.,,Sinulla on tarpeeksi.,Vous en avez assez.,Van elég.,Ne hai a sufficienza.,十分に持っています。,충분히 있으면 더 안 줘요.,Je hebt genoeg.,Du har nok.,Masz wystarczająco dużo.,Você tem o suficiente.,,Ai destule.,Тебе хватает.,,Du har tillräckligt.,Sende yeterince var. +Teach me.,TXT_RPLY1_SCRIPT10_D37900_TEACH,〃 (〃),,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. +"Well, that's it, you're done. I can teach no more.",TXT_RYES1_SCRIPT10_D37900_WELLT,〃 (〃),,,"Tak, a je to, jsme hotovi. Víc tě naučit nemůžu.","Nå, det var det, du er færdig. Jeg kan ikke undervise mere.","So, das war's. Ich kann dir nicht mehr beibringen.",,"Nu, jen ĉio, vi estas preta. +Mi havas nenion alian por instrui.","Bueno, eso es todo, estás listo. +No tengo más que enseñar.",,"No, se oli siinä, olet valmis. Minulla ei ole sinulle enää opetettavaa.","Eh bien, voilà. Vous savez tout. Je n'ai rien de plus pour vous!","Elérkeztünk oda, hogy nem tudok többet tanítani neked.","Beh, ecco fatto, oramai hai concluso. Non c'è null'altro che ti possa insegnare.",これで全てです。これ以上は教える事がありません。,"흐음, 이게 다입니다. 훈련을 다 마쳤어요.","Nou, dat is het dan, je bent klaar. Ik kan geen les meer geven.","Vel, det var det, du er ferdig. Jeg kan ikke lære deg mer.","No cóż, to już koniec. Nie mogę więcej uczyć.","Bom, é isso. Você já sabe de tudo. Não consigo ensinar mais nada.",,"Asta e, gata, nu mai am ce să te învăț.","Что ж, это всё. Твоё обучение закончено. Больше я ничему не могу тебя научить.",,"Det var det, du är klar. Jag kan inte undervisa mer.","Pekala, bu kadar, işin bitti. Daha fazla öğretemem." +Return after Macil tells you it's time.,TXT_RNO1_SCRIPT10_D37900_RETUR,〃 (〃),,,"Vrať se až ti Macil řekne, že je čas.","Vend tilbage, når Macil siger, at det er tid.","Komm wieder, wenn Macil sagt, dass es Zeit ist.",,"Revenu kiam Macil diros, +ke vi estas preta.","Vuelve cuando Macil +diga que es la hora.",,"Palaa sitten, kun Macil kertoo sinulle ajan koittaneen.",Revenez quand Macil vous dit qu'il est temps.,"Ha Macil szól hogy idő van, akkor fordulj vissza.",Ritorna quando Macil dice che è arrivato il momento.,マシルに許可を貰わないとなりません。,사령관님의 말씀을 듣고 찾아와주시길.,Keer terug nadat Macil je vertelt dat het tijd is.,Kom tilbake når Macil sier det er på tide.,"Wróć, gdy Macil powie ci, że już czas.",Volte depois que Macil te disser que está na hora.,,Întoarce-te după ce Macil îți spune că e vremea.,"Возвращайся, когда скажет Мэйсил.",,Återvänd när Macil säger att det är dags.,Macil sana zamanın geldiğini söylediğinde geri dön. +"I've taught you everything I can right now. I've given you all that you should ever need, unless you're out of bullets. Those I can still help you with.",TXT_DLG_SCRIPT10_D39416_IVETA,〃 (seven trainings),,,"Naučil jsem tě vše, co teď můžu. Dal jsem ti vše, co bys měl potřebovat, ledaže by ti došly náboje. S těmi ti stále můžu pomoci.","Jeg har lært dig alt, hvad jeg kan lige nu. Jeg har givet dig alt, hvad du nogensinde skulle få brug for, medmindre du er løbet tør for kugler. Dem kan jeg stadig hjælpe dig med.","Ich habe dir alles beigebracht, was ich weiß. Das sollte alles sein, was du brauchen wirst, es sei denn, du brauchst wieder mal Munition. Damit kann ich dir jederzeit helfen.",,"Mi instruis ĉion, kion mi scias, kaj mi donis ĉion, kion vi povus bezoni, krom se vi ne plu havas municion: mi certe ankoraŭ povas helpi pri tio.","Te he enseñado todo lo que puedo y te he dado todo lo que podrías necesitar, a menos que te hayas quedado sin balas, claro: con eso sí te puedo seguir ayudando.","Ya te enseñé todo lo que puedo y te di todo lo que podrías necesitar, a menos que te hayas quedado sin balas, claro: con eso sí te puedo seguir ayudando.","Olen opettanut sinulle kaiken osaamani. Olen antanut sinulle kaiken, mitä ikinä voisit tarvita, ellei sinulta sitten ole luodit loppu. Niiden suhteen voin vielä olla avuksi.","Je vous ai enseigné tout ce que je sais, et tout ce qu'il vous faudra, sauf si n'avez plus de munitions.. Et je peux vous aider pour ça, aussi.","Megtanítottam neked mindent amire most képes vagyok. Mindent megadtam neked amire valaha szükséged lehet, kivétel persze ha kifogysz a golyókból. Azt még mindig tudok adni.","Ti ho insegnato tutto quello che conosco. Ti ho dato tutto ciò di cui avrai mai bisogno, a meno che non hai finito le munizioni. Con quelle ti posso ancora essere d'aiuto.","私が教えられる事はもうありません。 今後新しい武器は時間が掛かるが自分のペースで -学びなさい。弾切れでなければの話ですが。",모든 훈련을 배우고 마치셨잖아요. 당신이 알아둬야 할 건 그게 전부입니다. 그 외에는 탄약이 필요하신가요?,"Ik heb je nu alles geleerd wat ik kan. Ik heb je alles gegeven wat je ooit nodig zou moeten hebben, tenzij je geen kogels meer hebt. Degenen waarmee ik je nog steeds kan helpen.","Jeg har lært deg alt jeg kan akkurat nå. Jeg har gitt deg alt du trenger, med mindre du er tom for kuler. De kan jeg fortsatt hjelpe deg med.","Nauczyłem cię wszystkiego, co mogę teraz. Dałem ci wszystko, co powinno ci być potrzebne, chyba że zabraknie ci naboi. Z tymi mogę ci jeszcze pomóc.","Eu te ensinei tudo o que eu consigo neste momento. Já te passei tudo o que você pode precisar, a não ser que esteja sem munição. Ainda posso te ajudar com isso.",,"Te-am învățat tot ce știu pentru moment. Ți-am dat tot ceea ce ai putea avea avea nevoie vreodată, decât dacă nu ai rămas cumva fără gloanțe. Cu astea te pot ajuta încă.","Я обучил тебя всему, что умею сам. Всему, что тебе может когда-нибудь пригодиться. Больше я ничем не могу тебе помочь... если, конечно, у тебя патроны не кончились.",,Şu anda sana öğretebileceğim her şeyi öğrettim. Mermin bitmediği sürece ihtiyacın olan her şeyi verdim. Onlar için sana hala yardım edebilirim. -Yes I am.,TXT_RPLY0_SCRIPT10_D39416_YESIA,〃 (〃),,,"Ano, došly.","Ja, det er jeg.","Ja, bin ich.",,Vi trafis.,Has acertado.,Acertaste.,Kyllä on.,"Oui, j'en ai besoin.",Igen.,"Sì, ho bisogno di munizioni.",ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.","Ja, det er jeg.","Tak, jestem.",Estou mesmo.,,Da sunt.,"Да, кончились.",,"Evet, ediyorum." -Here you go. ,TXT_RYES0_SCRIPT10_D39416_HEREY,〃 (〃),,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,どうぞ。,탄약 대령이요!,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Iată.,Держи.,,Al bakalım. -"Check out what's new, the teleporter beacon. When you use the beacon, we'll track the signal and send help. Is there something I can get you?",TXT_DLG_SCRIPT10_D40932_CHECK,MAP10: Justin.,,,"Podívej se na tohle, teleportační maják. Když ho použiješ, vystopujeme jeho signál a pošleme pomoc. Co ti můžu nabídnout?","Se det nye, teleporterfyret. Når du bruger fyret, sporer vi signalet og sender hjælp. Er der noget, jeg kan skaffe dig?","Sieh mal, was ich Neues habe, das Teleportersignal. Wenn du es benutzt können wir das Signal anpeilen und dir Hilfe schicken. Gibt es sonst was, was ich tun kann?",,,"Mira qué novedad, el faro de teletransporte. Cuando uses el faro, trazaremos la señal y enviaremos ayuda. ¿Hay algo que pueda ofrecerte?",,"Vilkaisepa tätä uutta kaukosiirrinmajakkaa. Kun käytät majakkaa, jäljitämme signaalin ja lähetämme apua. Saisiko sinulle olla jotain?","Regardez ce qu'on vient de sortir: L'antenne de téléporteur. Quand vous l'utilisez, on traque le signal et on envoie des renforts. Que puis-je faire pour vous?","Nézdd csak mit újítottunk be, egy teleport követőt. Amikor aktiválod, behatároljuk a jelet és kiküldjük a segítséget. Segítségedre lehetek még valamiben?","Guarda un pò questo nuovo aggeggio, il radiofaro per teletrasporto. Quando lo usi, identificheremo il tuo segnale e mandaremo rinforzi. C'è qualcosa che ti posso dare?","何を見つけたと思う、テレポータービーコンだ。 +学びなさい。弾切れでなければの話ですが。",모든 훈련을 배우고 마치셨잖아요. 당신이 알아둬야 할 건 그게 전부입니다. 그 외에는 탄약이 필요하신가요?,"Ik heb je nu alles geleerd wat ik kan. Ik heb je alles gegeven wat je ooit nodig zou moeten hebben, tenzij je geen kogels meer hebt. Degenen waarmee ik je nog steeds kan helpen.","Jeg har lært deg alt jeg kan akkurat nå. Jeg har gitt deg alt du trenger, med mindre du er tom for kuler. De kan jeg fortsatt hjelpe deg med.","Nauczyłem cię wszystkiego, co mogę teraz. Dałem ci wszystko, co powinno ci być potrzebne, chyba że zabraknie ci naboi. Z tymi mogę ci jeszcze pomóc.","Eu te ensinei tudo o que eu consigo neste momento. Já te passei tudo o que você pode precisar, a não ser que esteja sem munição. Ainda posso te ajudar com isso.",,"Te-am învățat tot ce știu pentru moment. Ți-am dat tot ceea ce ai putea avea avea nevoie vreodată, decât dacă nu ai rămas cumva fără gloanțe. Cu astea te pot ajuta încă.","Я обучил тебя всему, что умею сам. Всему, что тебе может когда-нибудь пригодиться. Больше я ничем не могу тебе помочь... если, конечно, у тебя патроны не кончились.",,"Jag har lärt dig allt jag kan just nu. Jag har gett dig allt du någonsin skulle behöva, om du inte har slut på kulor. De kan jag fortfarande hjälpa dig med.",Şu anda sana öğretebileceğim her şeyi öğrettim. Mermin bitmediği sürece ihtiyacın olan her şeyi verdim. Onlar için sana hala yardım edebilirim. +Yes I am.,TXT_RPLY0_SCRIPT10_D39416_YESIA,〃 (〃),,,"Ano, došly.","Ja, det er jeg.","Ja, bin ich.",,Vi trafis.,Has acertado.,Acertaste.,Kyllä on.,"Oui, j'en ai besoin.",Igen.,"Sì, ho bisogno di munizioni.",ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.","Ja, det er jeg.","Tak, jestem.",Estou mesmo.,,Da sunt.,"Да, кончились.",,"Ja, det gör jag.","Evet, ediyorum." +Here you go. ,TXT_RYES0_SCRIPT10_D39416_HEREY,〃 (〃),,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Toma.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,どうぞ。,탄약 대령이요!,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Iată.,Держи.,,Här har du.,Al bakalım. +"Check out what's new, the teleporter beacon. When you use the beacon, we'll track the signal and send help. Is there something I can get you?",TXT_DLG_SCRIPT10_D40932_CHECK,MAP10: Justin.,,,"Podívej se na tohle, teleportační maják. Když ho použiješ, vystopujeme jeho signál a pošleme pomoc. Co ti můžu nabídnout?","Se det nye, teleporterfyret. Når du bruger fyret, sporer vi signalet og sender hjælp. Er der noget, jeg kan skaffe dig?","Sieh mal, was ich Neues habe, das Teleportersignal. Wenn du es benutzt können wir das Signal anpeilen und dir Hilfe schicken. Gibt es sonst was, was ich tun kann?",,"Kia novaĵo: la teleportil-signalilo. Post kiam vi uzos ĝin, ni spuros la signalon kaj sendos helpotrupojn. Ĉu estas io, kion mi donu al vi?","Mira qué novedad: la baliza de teletransporte. Cuando la uses, rastrearemos la señal y enviaremos refuerzos. ¿Hay algo que pueda ofrecerte?","Mira qué novedad: la baliza de teletransporte. Cuando la uses, vamos a rastrear la señal y a mandarte refuerzos. ¿Hay algo que pueda ofrecerte?","Vilkaisepa tätä uutta kaukosiirrinmajakkaa. Kun käytät majakkaa, jäljitämme signaalin ja lähetämme apua. Saisiko sinulle olla jotain?","Regardez ce qu'on vient de sortir: L'antenne de téléporteur. Quand vous l'utilisez, on traque le signal et on envoie des renforts. Que puis-je faire pour vous?","Nézdd csak mit újítottunk be, egy teleport követőt. Amikor aktiválod, behatároljuk a jelet és kiküldjük a segítséget. Segítségedre lehetek még valamiben?","Guarda un po' questo nuovo aggeggio, il radiofaro per teletrasporto. Quando lo usi, identificheremo il tuo segnale e mandaremo rinforzi. C'è qualcosa che ti posso dare?","何を見つけたと思う、テレポータービーコンだ。 ビーコンを使用すると信号を追跡して増援を送る -ことができるぞ。必要な物はあるか?","이 녀석을 확인해보세요! 텔레포터 비컨이라는 건데, 사용해서 신호를 전송하면 병력을 보내겠습니다. 그 외에 원하는 게 있어요?","Kijk eens wat er nieuw is, het teleporterbaken. Als je het baken gebruikt, volgen we het signaal en sturen we hulp. Is er iets dat ik je kan krijgen?","Se hva som er nytt, teleportersignalet. Når du bruker den, sporer vi signalet og sender hjelp. Er det noe jeg kan hente til deg?","Zobaczcie, co nowego - teleporter. Kiedy użyjesz nadajnika, namierzymy sygnał i wyślemy pomoc. Czy jest coś, co mogę ci dać?","Veja só esta novidade, o sinalizador de teletransporte. Quando você usa o sinalizador, nós rastreamos o sinal e enviamos reforços. Posso te ajudar com alguma coisa?",,"Iată ce e nou, un far. Când folosești farul, ne ghidăm după el și trimitem întăriri. E ceva ce ți-aș putea aduce?","Посмотри на эту новинку: телепортационный маяк. Когда ты его включишь, мы проследим сигнал и вышлем подмогу. Итак, что я могу тебе предложить?",,"Yeni olan şeye bak, ışınlayıcı işaret. İşareti kullandığında, sinyali takip edip yardım göndereceğiz. Size getirebileceğim bir şey var mı?" -Box of rockets,TXT_RPLY0_SCRIPT10_D40932_BOXOF,〃,,,Bednu raket,En kasse med raketter,Kiste Raketen.,,,Caja de cohetes.,,Rakettilaatikko.,Boîte de roquettes.,Egy doboz rakéta kellene.,Cassa di razzi,ロケット箱,미니 미사일 한 박스,Doos met raketten,En eske med raketter.,Pudełko z rakietami,Caixa de foguetes,,Cutie de rachete.,Коробку ракет,,Roket kutusu -There you go.,TXT_RYES0_SCRIPT10_D40932_THERE,〃,,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Ahí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,はい、どうぞ。,여기 있어!,Daar ga je.,Vær så god.,No i proszę.,Aqui está.,,Iată.,Бери.,,Al bakalım. -You can't afford that!,TXT_RNO0_SCRIPT10_D40932_YOUCA,〃,,,Tu si nemůžeš dovolit!,Det har du ikke råd til!,Das kannst du dir nicht leisten.,,,¡No puedes adquirir eso!,,Sinulla ei ole siihen varaa!,Vous n'avez pas assez d'argent.,Arra neked aztán nem tellik.,Non hai abbastanza soldi.,買うだけの余裕が無い!,돈이 부족한 것 같은데!,Dat kan je je niet betalen!,Det har du ikke råd til!,Nie stać cię na to!,Você não pode comprar isto!,,Nu-ți poți permite asta!,Ты не можешь себе этого позволить!,,Bunu karşılayamazsın! -H-E grenades.,TXT_RPLY1_SCRIPT10_D40932_HEGRE,〃,,,Výbušné granáty,H-E granater.,HE-Granaten.,,,Granadas HE.,,Räjähdekranaatteja.,Grenades explosives.,Robbanó gránátot.,Granate ad alto potenziale esplosivo,HEグレネード,고폭 유탄,H-E-granaten.,H-E-granater.,Granaty H-E.,Granadas explosivas.,,Grenade.,Осколочные гранаты,,H-E el bombaları. -Here you go.,TXT_RYES1_SCRIPT10_D40932_HEREY,〃,,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Eccole qua.,どうぞ。,거래 감사드립니다!,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Iată.,Держи.,,Al bakalım. -Come back when you have enough money.,TXT_RNO1_SCRIPT10_D40932_COMEB,〃,,,Vrať se až budeš mít dost peněz.,"Kom tilbage, når du har penge nok.","Komm wieder, wenn du genug Gold hast.",,,Vuelve cuando tengas suficiente dinero.,,"Palataan asiaan sitten, kun sinulla on riittävästi rahaa.",Revenez quand vous avez assez d'argent.,"Gyere vissza, ha már van elég pénzed.",Ritorna quando avrai i soldi.,十分持ってたらまた来い。,돈이 충분할 때 다시와요.,Kom terug als je genoeg geld hebt.,Kom tilbake når du har nok penger.,"Wróć, gdy będziesz miał wystarczająco dużo pieniędzy.",Volte quando tiver dinheiro suficiente.,,Întoarce-te când ai destui bani.,"Возвращайся, когда у тебя будут деньги.",,Yeterli paran olduğunda geri gel. -Energy pod,TXT_RPLY2_SCRIPT10_D40932_ENERG,〃,,,Energetický kokón,Energibælg,Energiezelle.,,,Vaina de energía,,Energia-akku.,Cellule énergétique.,Energia cella.,Nucleo energetico,エネルギーポッド,에너지 포드,Energiecapsule,Energikapsel,Statyw energetyczny.,Célula de energia.,,Capsulă energetică.,Энергоячейку,,Enerji kapsülü -Here's your energy pod,TXT_RYES2_SCRIPT10_D40932_HERES,〃,,,Tady ho máš.,Her er din energibælg.,Hier hast du deine Energiezele.,,,Aquí tienes tu vaina de energía,,Tässä energia-akkusi.,Voilà votre cellule.,Itt van az energia cellád.,Ecco il tuo nucleo energetico.,これがエネルギーポッドだ。,에너지 포드 한 개 대령이요!,Hier is je energiecapsule...,Her er energikapselen din.,Oto twój pojemnik na energię.,Aqui está a sua célula de energia.,,Iată capsula energetică.,Вот твоя энергоячейка.,,İşte enerji kapsülün. -You don't have enough for that.,TXT_RNO2_SCRIPT10_D40932_YOUDO,〃,,,Na ten nemáš dost.,Du har ikke nok til det.,"Nein, du hast nicht genug Gold dafür.",,,No tienes suficiente para eso.,,Sinulla ei ole tarpeeksi sitä varten.,Vous n'avez pas assez d'argent pour ça.,"Nincs elég nálad, hogy megvedd.",Non hai abbastanza soldi per quello.,それでは足りない。,이 물품은 비싸죠. 저도 압니다.,Daar heb je niet genoeg voor.,Du har ikke nok til det.,Nie masz na to wystarczająco dużo.,Você não tem o suficiente para isto.,,Nu ai suficiente fonduri pentru asta.,У тебя недостаточно денег.,,Bunun için yeterince paran yok. -Teleporter beacon,TXT_RPLY3_SCRIPT10_D40932_TELEP,〃,,,Teleportační maják,Teleportørfyr,Teleportersignal.,,,Faro de teletransporte,,Kaukosiirrinmajakka,Antenne de téléporteur.,Teleport követő,Radiofaro per teletrasporto.,テレポータービーコン,텔레포터 비콘,Teleporter baken,Teleporteringssignal,Teleporter beacon,Sinalizador de teletransporte,,Far pentru teleportare.,Телепортационный маяк,,Işınlayıcı işaretçisi -"Help, when and where you need it.",TXT_RYES3_SCRIPT10_D40932_HELPW,〃,,,Pomoc kdekoliv a kdykoliv je třeba.,"Hjælp, når og hvor du har brug for det.","Hilfe, wenn und wo sie gebraucht wird.",,,"Ayuda, cuando y donde la necesites.",,"Apua, missä ja milloin ikinä tarvitsetkaan.","De l'aide, quand il vous en faut.","Segítség, amikor és ahol akarod.",Con questo riceverai aiuto dove e quando ti servirà.,助けが必要になったら使うんだ。,위급한 상황에서만 사용하시길.,"Help, waar en wanneer je het nodig hebt.","Hjelp, når og hvor du trenger det.","Pomoc, kiedy i gdzie jej potrzebujesz.","Reforços, quando e onde você precisar.",,"Ajutor, acolo și când ai nevoie de el.",Теперь ты сможешь получить помощь всегда и везде.,,İhtiyacınız olduğu zaman ve yerde yardım. -"Sorry, no charity.",TXT_RNO3_SCRIPT10_D40932_SORRY,〃,,,"Promiň, nejsme charita.","Beklager, ingen velgørenhed.","Tut mir leid, wir sind keine Wohltätigkeitsveranstaltung.",,,"Lo siento, no es caridad.",,"Valitan, ei hyväntekeväisyyttä.","Désolé, on n'est pas une charité.","Sajnálom, ez nem jótékonyság.","Mi spiace, ma niente beneficienza.",すまない、チャリティーじゃないんだ。,"미안하지만, 여긴 자선단체가 아니에요.","Sorry, geen liefdadigheid.","Beklager, ingen veldedighet.","Przykro mi, ale nie ma mowy o dobroczynności.","Sinto muito, mas não fazemos caridade.",,"Scuze, nu e caritate.",Прости. Никакой благотворительности.,,"Üzgünüm, hayırseverlik yok." -"Now that we actually have the castle under control, we have to be extra vigilant to keep it. The Order's probably getting ready to strike back right now.",TXT_DLG_SCRIPT10_D42448_NOWTH,MAP10: Rebels in Macil's room.,,,"Teď když máme hrad pod kontrolou, musíme být ještě obezřetnější. Řád se pravděpodobně právě teď připravuje zaútočit.","Nu hvor vi faktisk har slottet under kontrol, skal vi være ekstra opmærksomme for at holde det. Ordenen er sikkert ved at gøre sig klar til at slå tilbage lige nu.","Jetzt, wo wir die Burg unter Kontrolle haben, müssen wir besonders wachsam sein, um sie nicht wieder zu verlieren. Der Orden bereitet womöglich gerade jetze einen Gegenschlag vor.",,,Ahora que realmente tenemos el castillo bajo control tenemos que estar bien alerta para guardarlo. La Orden probablemente se esté preparando para contraatacar ahora mismo.,,"Nyt, kun linna on todellakin meidän hallinnassamme, meidän on oltava erityisen valppaita pitääksemme sen. Veljeskunta on luultavasti parhaillaan valmistautumassa vastahyökkäykseen.","Maintenant que le château est sous notre contrôle, nous devons être très vigilants pour le conserver. L'Ordre se prépare sans doute à riposter maintenant.","Most, hogy már az egész kastély az irányításunk alatt van, még szemfülesebbnek kell lennünk, hogy megtarthassuk. A Rend valószínű, hogy a visszavételre készül.","Adesso che abbiamo il castello sotto controllo, dobbiamo essere ancora più vigili per tenerlo sotto controllo. L'Ordine sicuramente starà preparando un contrattacco.","城が管理下に入った今、維持させるためには +ことができるぞ。必要な物はあるか?","이 녀석을 확인해보세요! 텔레포터 비컨이라는 건데, 사용해서 신호를 전송하면 병력을 보내겠습니다. 그 외에 원하는 게 있어요?","Kijk eens wat er nieuw is, het teleporterbaken. Als je het baken gebruikt, volgen we het signaal en sturen we hulp. Is er iets dat ik je kan krijgen?","Se hva som er nytt, teleportersignalet. Når du bruker den, sporer vi signalet og sender hjelp. Er det noe jeg kan hente til deg?","Zobaczcie, co nowego - teleporter. Kiedy użyjesz nadajnika, namierzymy sygnał i wyślemy pomoc. Czy jest coś, co mogę ci dać?","Veja só esta novidade, o sinalizador de teletransporte. Quando você usa o sinalizador, nós rastreamos o sinal e enviamos reforços. Posso te ajudar com alguma coisa?",,"Iată ce e nou, un far. Când folosești farul, ne ghidăm după el și trimitem întăriri. E ceva ce ți-aș putea aduce?","Посмотри на эту новинку: телепортационный маяк. Когда ты его включишь, мы проследим сигнал и вышлем подмогу. Итак, что я могу тебе предложить?",,"Kolla in vad som är nytt, teleporterfyren. När du använder fyren spårar vi signalen och skickar hjälp. Finns det något jag kan ge dig?","Yeni olan şeye bak, ışınlayıcı işaret. İşareti kullandığında, sinyali takip edip yardım göndereceğiz. Size getirebileceğim bir şey var mı?" +Box of rockets,TXT_RPLY0_SCRIPT10_D40932_BOXOF,〃,,,Bednu raket,En kasse med raketter,Kiste Raketen.,,Misilet-keston,Caja de minimisiles,,Rakettilaatikko.,Boîte de roquettes.,Egy doboz rakéta kellene.,Cassa di razzi,ロケット箱,미니 미사일 한 박스,Doos met raketten,En eske med raketter.,Pudełko z rakietami,Caixa de foguetes,,Cutie de rachete.,Коробку ракет,,En låda med raketer.,Roket kutusu +There you go.,TXT_RYES0_SCRIPT10_D40932_THERE,〃,,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Toma.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,はい、どうぞ。,여기 있어!,Daar ga je.,Vær så god.,No i proszę.,Aqui está.,,Iată.,Бери.,,Här har du.,Al bakalım. +You can't afford that!,TXT_RNO0_SCRIPT10_D40932_YOUCA,〃,,,Tu si nemůžeš dovolit!,Det har du ikke råd til!,Das kannst du dir nicht leisten.,,Vi ne povas sen mono!,¡No te alcanza!,,Sinulla ei ole siihen varaa!,Vous n'avez pas assez d'argent.,Arra neked aztán nem tellik.,Non hai abbastanza soldi.,買うだけの余裕が無い!,돈이 부족한 것 같은데!,Dat kan je je niet betalen!,Det har du ikke råd til!,Nie stać cię na to!,Você não pode comprar isto!,,Nu-ți poți permite asta!,Ты не можешь себе этого позволить!,,Du har inte råd med det!,Bunu karşılayamazsın! +H-E grenades.,TXT_RPLY1_SCRIPT10_D40932_HEGRE,〃,,,Výbušné granáty,H-E granater.,HE-Granaten.,,Eksplodeg-povajn grenadojn,Granadas de conmoción,,Räjähdekranaatteja.,Grenades explosives.,Robbanó gránátot.,Granate ad alto potenziale esplosivo,HEグレネード,고폭 유탄,H-E-granaten.,H-E-granater.,Granaty H-E.,Granadas explosivas.,,Grenade.,Осколочные гранаты,,H-E-granater.,H-E el bombaları. +Here you go.,TXT_RYES1_SCRIPT10_D40932_HEREY,〃,,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Toma.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Eccole qua.,どうぞ。,거래 감사드립니다!,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Iată.,Держи.,,Varsågod.,Al bakalım. +Come back when you have enough money.,TXT_RNO1_SCRIPT10_D40932_COMEB,〃,,,Vrať se až budeš mít dost peněz.,"Kom tilbage, når du har penge nok.","Komm wieder, wenn du genug Gold hast.",,"Revenu kiam vi havos +sufiĉe da mono.","Vuelve cuando tengas +suficiente dinero.",,"Palataan asiaan sitten, kun sinulla on riittävästi rahaa.",Revenez quand vous avez assez d'argent.,"Gyere vissza, ha már van elég pénzed.",Ritorna quando avrai i soldi.,十分持ってたらまた来い。,돈이 충분할 때 다시와요.,Kom terug als je genoeg geld hebt.,Kom tilbake når du har nok penger.,"Wróć, gdy będziesz miał wystarczająco dużo pieniędzy.",Volte quando tiver dinheiro suficiente.,,Întoarce-te când ai destui bani.,"Возвращайся, когда у тебя будут деньги.",,Kom tillbaka när du har tillräckligt med pengar.,Yeterli paran olduğunda geri gel. +Energy pod,TXT_RPLY2_SCRIPT10_D40932_ENERG,〃,,,Energetický kokón,Energibælg,Energiezelle.,,Energi-kapsulon,Cápsula de energía,,Energia-akku.,Cellule énergétique.,Energia cella.,Nucleo energetico,エネルギーポッド,에너지 포드,Energiecapsule,Energikapsel,Statyw energetyczny.,Célula de energia.,,Capsulă energetică.,Энергоячейку,,Energipod.,Enerji kapsülü +Here's your energy pod,TXT_RYES2_SCRIPT10_D40932_HERES,〃,,,Tady ho máš.,Her er din energibælg.,Hier hast du deine Energiezele.,,Jen ĝi.,Aquí la tienes.,,Tässä energia-akkusi.,Voilà votre cellule.,Itt van az energia cellád.,Ecco il tuo nucleo energetico.,これがエネルギーポッドだ。,에너지 포드 한 개 대령이요!,Hier is je energiecapsule...,Her er energikapselen din.,Oto twój pojemnik na energię.,Aqui está a sua célula de energia.,,Iată capsula energetică.,Вот твоя энергоячейка.,,Här är din energipodd.,İşte enerji kapsülün. +You don't have enough for that.,TXT_RNO2_SCRIPT10_D40932_YOUDO,〃,,,Na ten nemáš dost.,Du har ikke nok til det.,"Nein, du hast nicht genug Gold dafür.",,"Vi ne havas +sufiĉe da mono.",No te alcanza para eso.,,Sinulla ei ole tarpeeksi sitä varten.,Vous n'avez pas assez d'argent pour ça.,"Nincs elég nálad, hogy megvedd.",Non hai abbastanza soldi per quello.,それでは足りない。,이 물품은 비싸죠. 저도 압니다.,Daar heb je niet genoeg voor.,Du har ikke nok til det.,Nie masz na to wystarczająco dużo.,Você não tem o suficiente para isto.,,Nu ai suficiente fonduri pentru asta.,У тебя недостаточно денег.,,Du har inte tillräckligt för det.,Bunun için yeterince paran yok. +Teleporter beacon,TXT_RPLY3_SCRIPT10_D40932_TELEP,〃,,,Teleportační maják,Teleportørfyr,Teleportersignal.,,Teleportil-signalilon,Baliza de teletransporte,,Kaukosiirrinmajakka,Antenne de téléporteur.,Teleport követő,Radiofaro per teletrasporto.,テレポータービーコン,텔레포터 비콘,Teleporter baken,Teleporteringssignal,Teleporter beacon,Sinalizador de teletransporte,,Far pentru teleportare.,Телепортационный маяк,,Teleporterfyren,Işınlayıcı işaretçisi +"Help, when and where you need it.",TXT_RYES3_SCRIPT10_D40932_HELPW,〃,,,Pomoc kdekoliv a kdykoliv je třeba.,"Hjælp, når og hvor du har brug for det.","Hilfe, wenn und wo sie gebraucht wird.",,"Helpo kiam kaj kie +vi bezonos ĝin.","Refuerzos cuando y +donde los necesites.",,"Apua, missä ja milloin ikinä tarvitsetkaan.","De l'aide, quand il vous en faut.","Segítség, amikor és ahol akarod.",Con questo riceverai aiuto dove e quando ti servirà.,助けが必要になったら使うんだ。,위급한 상황에서만 사용하시길.,"Help, waar en wanneer je het nodig hebt.","Hjelp, når og hvor du trenger det.","Pomoc, kiedy i gdzie jej potrzebujesz.","Reforços, quando e onde você precisar.",,"Ajutor, acolo și când ai nevoie de el.",Теперь ты сможешь получить помощь всегда и везде.,,"Hjälp, när och var du behöver den.",İhtiyacınız olduğu zaman ve yerde yardım. +"Sorry, no charity.",TXT_RNO3_SCRIPT10_D40932_SORRY,〃,,,"Promiň, nejsme charita.","Beklager, ingen velgørenhed.","Tut mir leid, wir sind keine Wohltätigkeitsveranstaltung.",,"Pardonon, ĉi tio +ne estas almozulejo.","Lo siento, no es caridad.",,"Valitan, ei hyväntekeväisyyttä.","Désolé, on n'est pas une charité.","Sajnálom, ez nem jótékonyság.","Mi spiace, ma niente beneficienza.",すまない、チャリティーじゃないんだ。,"미안하지만, 여긴 자선단체가 아니에요.","Sorry, geen liefdadigheid.","Beklager, ingen veldedighet.","Przykro mi, ale nie ma mowy o dobroczynności.","Sinto muito, mas não fazemos caridade.",,"Scuze, nu e caritate.",Прости. Никакой благотворительности.,,"Tyvärr, ingen välgörenhet.","Üzgünüm, hayırseverlik yok." +"Now that we actually have the castle under control, we have to be extra vigilant to keep it. The Order's probably getting ready to strike back right now.",TXT_DLG_SCRIPT10_D42448_NOWTH,MAP10: Rebels in Macil's room.,,,"Teď když máme hrad pod kontrolou, musíme být ještě obezřetnější. Řád se pravděpodobně právě teď připravuje zaútočit.","Nu hvor vi faktisk har slottet under kontrol, skal vi være ekstra opmærksomme for at holde det. Ordenen er sikkert ved at gøre sig klar til at slå tilbage lige nu.","Jetzt, wo wir die Burg unter Kontrolle haben, müssen wir besonders wachsam sein, um sie nicht wieder zu verlieren. Der Orden bereitet womöglich gerade jetze einen Gegenschlag vor.",,"Nun kiam ni regas la kastelon, ni devas esti duoble atentaj por konservi ĝin; La Ordeno verŝajne pretiĝas kontraŭataki iam ajn.",Ahora que ya tenemos el castillo bajo control hay que estar el doble de alertas para cuidarlo; La Orden de seguro se está preparando para contraatacar en cualquier momento.,,"Nyt, kun linna on todellakin meidän hallinnassamme, meidän on oltava erityisen valppaita pitääksemme sen. Veljeskunta on luultavasti parhaillaan valmistautumassa vastahyökkäykseen.","Maintenant que le château est sous notre contrôle, nous devons être très vigilants pour le conserver. L'Ordre se prépare sans doute à riposter maintenant.","Most, hogy már az egész kastély az irányításunk alatt van, még szemfülesebbnek kell lennünk, hogy megtarthassuk. A Rend valószínű, hogy a visszavételre készül.","Adesso che abbiamo il castello sotto controllo, dobbiamo essere ancora più vigili per tenerlo sotto controllo. L'Ordine sicuramente starà preparando un contrattacco.","城が管理下に入った今、維持させるためには 更なる警戒網が必要になるだろう。オーダーは -反撃の準備をしているはずだ。",성을 공격해 점령한 이후로 화력과 병력 등을 많이 증가시킬 수 있게 되었습니다. 오더 놈들은 분명히 이를 대비한 역습을 준비하고 있을 거예요.,"Nu we het kasteel daadwerkelijk onder controle hebben, moeten we extra waakzaam zijn om het onder controle te houden. De Orde maakt zich waarschijnlijk klaar om nu meteen terug te slaan.","Nå som vi faktisk har slottet under kontroll, må vi være ekstra årvåkne for å beholde det. Ordenen gjør seg nok klar til å slå tilbake nå.","Teraz, gdy mamy zamek pod kontrolą, musimy być bardzo czujni, by go utrzymać. Zakon pewnie szykuje się do ataku.","Agora que temos o castelo sob controle, precisamos estar mais alertas para mantê-lo assim. A Ordem provavelmente está se preparando para contra-atacar neste momento.",,"Acum că avem castelul sub control, va trebui să fim și mai vigilenți pentru a-l păstra. Ordinul probabil se pregătește pentru un atac de recuperare chiar acum.","Замок теперь наш, но если хотим его удержать, нужно не терять бдительности. Быть может, именно сейчас Орден готовит контратаку.",,"Artık kaleyi kontrol altına aldığımıza göre, onu korumak için daha dikkatli olmalıyız. Tarikat muhtemelen şu anda geri saldırmaya hazırlanıyor." -Be careful out there.,TXT_DLG_SCRIPT10_D43964_BECAR,MAP10: Castle's entrance.,,,Buď tam venku opatrný.,Vær forsigtig derude.,Sei vorsichtig da draußen.,,,Ten cuidado ahí fuera.,,Pidä varasi siellä.,Faites attention à vous.,Vigyázz magadra odakinnt.,Sii cauto la fuori.,外は気を付けろ。,부디 조심하시길.,Wees voorzichtig daarbuiten.,Vær forsiktig der ute.,Bądźcie ostrożni.,Tome cuidado.,,Ai grijă afară.,Будь настороже.,,Dışarıda dikkatli olun. -"Keep up the great work, we couldn't have done it without you.",TXT_DLG_SCRIPT10_D45480_KEEPU,MAP10: Rebel in Hospital.,,,"Jen tak dál, bez tebe bychom to nedokázali.","Fortsæt det gode arbejde, vi kunne ikke have gjort det uden jer.","Großartige Arbeit, mach weiter so. Ohne dich hätten wir es nicht schaffen können.",,,"Sigue así, no podríamos haberlo logrado sin ti.",,Jatka samaan malliin; emme olisi pärjänneet näin hyvin ilman sinua.,"Continuez votre magnifique travail, nous n'aurions jamais réussi sans vous.","Csak így tovább, nélküled sosem tudtuk volna véghezvinni.","Continua così, non ce l'avremmo fatta senza di te.","我々は貴方無くして成し遂げる事は出来なかった -素晴らしい働きをしてくれてます。",부디 건투를 빕니다. 당신 덕에 희망을 잃지 않는 거니까!,"Ga zo door, we hadden het zonder jou niet kunnen doen.","Fortsett med det flotte arbeidet, vi kunne ikke ha gjort det uten deg.","Kontynuujcie wspaniałą pracę, bez was nie dalibyśmy rady.",Continue assim. Nós não teríamos conseguido sem você.,,"Continuă să faci treabă bună, n-am fi reușit fără tine.",Продолжай в том же духе. Без тебя мы бы не справились.,,"Harika iş çıkarmaya devam edin, siz olmadan bunu başaramazdık." -I'm the keymaster.,TXT_DLG_SCRIPT11_D0_IMTHE,MAP11: Commons (no token).,,,Já jsem tu klíčníkem.,Jeg er nøglemesteren.,Ich bin der Schlüsselmeister.,,,Soy el amo de llaves.,,Olen avainmestari.,Je suis le maître des clés.,Én vagyok a kulcsmester.,Io sono il mastro delle chiavi.,僕がキーマスターだ。,전 열쇠지기에요.,Ik ben de sleutelbeheerder.,Jeg er nøkkelmesteren.,Jestem mistrzem kluczy.,Eu sou o mestre das chaves.,,Sunt stăpânul cheilor.,Я ключник.,,Ben anahtar yöneticisiyim. -"A lot of people would say this is a thankless and insignificant job. But it's not, in fact...",TXT_DLG_SCRIPT11_D1516_ALOTO,〃 (Oracle's token),,,"Většina lidí by řekla, že tohle je nevděčná a nedůležitá práce, ale není, naopak...","Mange ville sige, at det er et utaknemmeligt og ubetydeligt job. Men det er det ikke, faktisk...","Eine Menge Leute würden sagen, dies sei eine undankbare Aufgabe, aber das ist es nicht, in Wirklichkeit...",,,"Mucha gente diría que este es un trabajo ingrato e insignificante, pero no, de hecho...",,Monet väittäisivät tehtäväni olevan epäkiitollinen ja vähäpätöinen. Mutta oikeasti se ei ole.,"Beaucoup de gens diraient que c'est un travail insignifiant et ingrat.. Mais en fait, ce n'est vraiment pas le cas.","Sokan azt mondják, hogy ez egy hálátlan és jelentéktelen munka. Ám nem is állhatnának messzebb az igazságtól...","Molte persone direbbero che questo è un lavoro ingrato e insignificante. Ma non lo è, infatti...","皆、この仕事が報われないと思っているが -実際はそうでもないんだ...","많은 사람이 이 직업을 감사해야 하고 놀라운 일이라 말하겠죠. 하지만 아닌데, 사실은...","Veel mensen zouden zeggen dat dit een ondankbare en onbeduidende klus is. Maar dat is het niet, in feite....",Mange vil si at dette er en utakknemlig og ubetydelig jobb. Men det er det faktisk ikke...,"Wielu ludzi powiedziałoby, że to niewdzięczna i mało znacząca praca. Ale tak nie jest, w rzeczywistości...",Muita gente diria que este é um trabalho ingrato e insignificante. Mas na verdade não é...,,"O grămadă de oameni ar spune că e o muncă fără mulțumiri și insignifiantă. În realitate, nu este...","Многие скажут, что это неблагодарная и незначительная работа, но это не так. На самом деле...",,"Birçok insan bunun nankör ve önemsiz bir iş olduğunu söyleyebilir. Ama değil, aslında..." -Give me the key!,TXT_RPLY0_SCRIPT11_D1516_GIVEM,〃,,,Dej mi klíč!,Giv mig nøglen!,Gib mir den Schlüssel.,,,¡Dame la llave!,,Anna minulle avain!,Donne moi la clé!,Add ide a kulcsot!,Dammi la chiave!,鍵をくれ!,그냥 망할 열쇠를 줘!,Geef me de sleutel!,Gi meg nøkkelen!,Daj mi klucz!,Me dê a chave!,,Dă-mi cheia!,Дай мне ключ!,,Anahtarı bana ver! -"OK, but remember, I'm the keymaster.",TXT_DLG_SCRIPT11_D3032_OKBUT,〃,,,"Dobře, ale nezapomeň, že klíčník jsem já.","OK, men husk, jeg er nøglemesteren.","Ok, aber vergiß nicht, dass ICH der Schlüsselmeister bin.",,,"Bueni, pero recuerda: soy el amo de llaves.",,"Selvä, mutta muista: minä olen avainmestari.","Ok, mais souviens-toi, je suis le maître des clés.","OK, de emlékezz arra, hogy Én vagyok a kulcsmester.","OK, ma ricorda, io sono il mastro delle chiavi.",オーケー、なんせ僕は、キーマスターだしな。,"좋아요, 하지만 기억해요. 전 열쇠지기랍니다!","Oké, maar onthoud, ik ben de sleutelbeheerder.","OK, men husk at jeg er nøkkelmesteren.","OK, ale pamiętaj, że to ja jestem klucznikiem.","Ok, mas lembre-se, eu sou o mestre das chaves.",,"Bine, dar ține minte, eu sunt stăpânul cheilor.","Держи, но помни: я ключник!",,"Tamam, ama unutma, anahtar ustası benim." -"OK pal, whatever.",TXT_RPLY0_SCRIPT11_D3032_OKPAL,〃,,,"Jasně, kámo, klidně.","Okay, kammerat.","Was auch immer, Kumpel.",,,"Sí, colega, lo que tú digas.","Sí, amigo, como tú digas.","Joo joo, ihan sama.","Comme tu veux, mon ami.","OK öreg, nem hat meg.","Sì, certo, come no.",わかった、何なりと。,"그래, 알 게 뭐야...","Oké, vriend, wat dan ook.","OK, kompis, samme det.","OK kolego, nieważne.","Ok, amigo. Que seja.",,"Bine amice, cum spui tu.",Ага. Без проблем.,,"Tamam dostum, her neyse." -I'm the keymaster.,TXT_DLG_SCRIPT11_D4548_IMTHE,〃,,,Já jsem tu klíčníkem.,Jeg er nøglemesteren.,Ich bin der Schlüsselmeister.,,,Soy el amo de llaves.,,Minä olen avainmestari.,Je suis le maître des clés.,Én vagyok a kulcsmester.,Io sono il mastro delle chiavi.,僕がキーマスターだ。,열쇠지기. 그게 바로 저죠!,Ik ben de sleutelbeheerder.,Jeg er nøkkelmesteren.,Ja jestem klucznikiem.,Eu sou o mestre das chaves.,,Sunt stăpânul cheilor.,Я ключник.,,Anahtar ustası benim. -Die traitor!,TXT_DLG_SCRIPT11_D6064_DIETR,MAP11: Red acolyte at temple's entrance.,,,"Zemři, zrádče!","Dø, forræder!","Stirb, Verräter.",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,死ね、反逆者!,"죽어라, 배신자!","Sterf, verrader.",Dø forræder!,Giń zdrajco!,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!",,Geber hain! -Die traitor!,TXT_DLG_SCRIPT11_D7580_DIETR,〃,,,"Zemři, zrádče!","Dø, forræder!","Stirb, Verräter.",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,死ね、反逆者!,"뒈져라, 배신자!","Sterf, verrader.",Dø forræder!,Giń zdrajco!,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!",,Geber hain! -"Have you come to gloat? Even though we're behind these bars, as long as we hold on, you still lose.",TXT_DLG_SCRIPT11_D9096_HAVEY,MAP11: Prisoner.,,,"Přišel ses nám vysmívat? I když jsme za mřížemi, dokud jsme na nohou, ty zůstáváš poražený.","Er du kommet for at fryde dig? Selvom vi er bag disse tremmer, så længe vi holder fast, taber du stadig.","Bist du zum Glotzen gekommen? Auch wenn wir hinter Gittern sind, solange wir nicht aufgeben wirst du immer noch verlieren.",,,"¿Has venido a regodearte? Aunque estemos entre rejas, mientras sigamos en pie, has perdido.",,"Oletko tullut meitä pilkkaamaan? Vaikka olemmekin näiden kaltereiden takansa, niin kunhan vain pidämme pintamme, sinä silti häviät.","Vous êtes venu vous moquer de nous? Même si on est derrière les barreaux, du moment que l'on reste en vie, vous allez perdre.","Dicsekedni jöttél ide? Habár itt rohadunk a rács mögött, amíg kitartunk miénk a győzelem.","Sei venuto a gongolare? Anche se siamo dietro queste sbarre, finché resisteremo, voi perderete.","何睨んでるんだ?この棒が俺達を囲んでる限り、 -お前は未だに負けている。","거들먹거리러 온 거냐? 비록 우리가 이 철창에 갇히긴 했지만, 계속 여기 있으면 넌 아직도 질 거라고.","Ben je gekomen om je te verkneukelen? Ook al zitten we achter deze tralies, zolang we ons vasthouden, verlies je nog steeds.","Har du kommet for å hovere? Selv om vi er bak gitteret, taper du så lenge vi holder fast.","Przyszliście się napawać? Nawet jeśli jesteśmy za tymi kratami, to dopóki się trzymamy, ty wciąż przegrywasz.","Você veio se gabar? Mesmo que a gente esteja atrás destas grades, enquanto resistirmos, você ainda perde.",,"Ai venit să te lauzi? Chiar dacă suntem în spatele gratilor, cât timp rezistăm, tu pierzi.","Пришёл поглумиться? Пусть мы и за этими решётками, но пока мы живы, вам не победить.",,"Kına yakmaya mı geldin? Bu parmaklıkların arkasında olsak bile, biz dayandığımız sürece siz kaybedersiniz." -Let us out of here!,TXT_DLG_SCRIPT11_D10612_LETUS,〃,,,Pusť nás odsud!,Lad os komme ud herfra!,Lass uns hier raus!,,,¡Sácanos de aquí!,,Päästä meidät pois täältä!,Sortez nous de là!,Engedj ki minket!,Facci uscire da qua!,ここから出してくれ!,우릴 여기서 내보내 줘!,Laat ons hier uit!,Slipp oss ut herfra!,Wypuść nas stąd!,Nos tire daqui!,,Scoate-ne de aici!,Выпусти нас отсюда!,,Çıkarın bizi buradan! -Leave me alone!,TXT_DLG_SCRIPT11_D12128_LEAVE,〃,,,Nech mě být!,Lad mig være i fred!,Lass mich in Ruhe!,,,¡Déjame en paz!,,Jätä minut rauhaan!,Foutez moi la paix!,Hagyj békén!,Lasciami in pace!,ほっといてくれ!,날 좀 내버려 둬!,Laat me met rust!,La meg være i fred!,Zostawcie mnie w spokoju!,Me deixe em paz!,,Lasă-mă în pace!,Оставь меня в покое!,,Beni yalnız bırakın! -"What is the wisdom you seek, simple one?",TXT_DLG_SCRIPT12_D0_WHATI,MAP12: Oracle.,,,"Jaké moudro hledáš, jednoduchý?","Hvad er det for en visdom du søger, simple en?","Welche Weisheit suchst du, Menschling?",,,"¿Cuál es la sabiduría que buscas, simple criatura?",,"Mitä viisautta etsit, sinä tietämätön?","Quelle est la sagesse que vous recherchez, simple humain?","Miféle bölcsességet kutatsz, egyszerű barátom?","Qual è la saggezza che cerchi, ottenebrato ?",迷える者よ、如何なる知識を求めに来た。,그대가 찾고 있는 지혜는 어떤 것인가? 평범한 자여?,"Wat is de wijsheid die je zoekt, eenvoudige wijsheid?","Hva er visdommen du søker, enfoldige?","Jakiej mądrości szukasz, prosty?","Qual é a sabedoria que você procura, simples criatura?",,"Ce întelepciune cauți, om simplu?","Какой мудрости ты ищешь, непосвящённый?",,"Aradığın bilgelik nedir, basit olan?" -The Sigil of the One God.,TXT_RPLY0_SCRIPT12_D0_THESI,〃,,,Pečeť Jednoho boha.,Sigilet af den ene Gud.,Das Sigil des Einen Gottes.,,,El Emblema del Dios Único.,,Yhden Ainoan Jumalan Sinettiä.,Le Sigil du Seul Dieu.,Az egy Igaz Isten pecsétjét.,Il Sigillo dell'Unico Dio.,唯一神のシジルだ。,"유일신의 인장, 시질이다.",De Sigil van de Ene God.,Den ene Guds sigill.,Sigil Jedynego Boga.,O Sigilo do Deus Único.,,Sigiliul Adevăratului Zeu.,Печать Единого Бога.,,Tek Tanrı'nın Mührü. -"I feel one fragment resonate within you. The second lies at the heart of the crimson and obsidian tower. There you must combat the Bishop, who is aware, and awaits you. You will find him by following his symbol of power. Take this token to the keymaster. Return to me after you have slain the beast.",TXT_DLG_SCRIPT12_D1516_IFEEL,〃,,,"Cítím z tebe rezonovat jeden díl. Druhý leží v srdci věže karmíno-obsidiánové. Tam musíš poraziti Biskupa, který si je tě vědom a očekává tě. Najdeš ho následováním symbolu jeho moci. Přijmi tuto známku pro klíčníka. Vrať se ke mě, až skolíš bestii.","Jeg føler et fragment resonere i dig. Det andet ligger i hjertet af det purpurfarvede og obsidian tårn. Der skal du bekæmpe biskoppen, som er klar over det og venter på dig. Du finder ham ved at følge hans symbol for magt. Tag dette symbol med til nøglemesteren. Vend tilbage til mig, når du har dræbt udyret.","Ich fühle, wie ein Fragment in dir pulsiert, Das zweite Teilstück des Sigils befindet sich im Herzen des Turms aus Purpur und Obsidian. Dort wartet der Bischof auf dich, den du bekämpfen musst. Er weiß von dir und wartet. Du findest ihn, wenn du seinem Symbol der Macht folgst. Nimm dieses Zeichen und gebe es dem Schlüsselmeister. Kehr zu mir zurück, nachdem du die Bestie vernichtet hast.",,,"Siento un fragmento resonar en ti. El segundo se encuentra en el corazón de la torre carmesí y obsidiana. Ahí debes combatir con el Obispo, quien sabe, y espera tu llegada. Lo encontrarás siguiendo su símbolo de poder. Lleva este vale al amo de llaves. Vuelve a mí tras haber matado a la bestia.",,"Minä tunnen yhden osasen väräjävän sisälläsi. Toinen piilee purppuranpunaisen laavalasisen tornin sydämessä. Siellä pitää sinun taisteleman Piispaa vastaan, joka on tietoinen ja sinua odottava. Löydät hänet seuraamalla hänen valtansa tunnuskuvaa. Toimita tämä merkki avainmestarille. Palaa tyköni surmattuasi pedon.","Je sens un fragment résonner en toi. Le deuxième repose au cœur de la tour d'obsidienne et d'écarlate. Ici, vous devrez défaire l'évêque, qui connaît déjà votre statut, et vous attend patiemment. Vous le trouverez en suivant son symbole de pouvoir. Prenez ce jeton et amenez le au maître des clés. Retournez à moi après que vous ayez vaincu la bête.","Érzem rajta az egyik darabot. A másodikat a karmazsin és obszidián toronyban találod meg. Ott viszont már várni fog rád a Püspök. Meg fogod lelni őt, ha követed a jelét. Vidd ezt a zálogot a kulcsmesterhez. Térj vissza hozzám, ha legyűrted a szörnyet.","Avverto che possiedi uno dei frammenti. Il secondo si trova nel cuore della torre cremisina e ossidiana. Lì dovrai combattere contro il Vescovo, che già ti attende. Lo troverai seguendo il suo simbolo del potere. Prendi questo gettone per il mastro delle chiavi. Ritorna da me dopo che avrai ucciso la bestia.","お主の持つ欠片が共鳴しているのを感受出来る。 +反撃の準備をしているはずだ。",성을 공격해 점령한 이후로 화력과 병력 등을 많이 증가시킬 수 있게 되었습니다. 오더 놈들은 분명히 이를 대비한 역습을 준비하고 있을 거예요.,"Nu we het kasteel daadwerkelijk onder controle hebben, moeten we extra waakzaam zijn om het onder controle te houden. De Orde maakt zich waarschijnlijk klaar om nu meteen terug te slaan.","Nå som vi faktisk har slottet under kontroll, må vi være ekstra årvåkne for å beholde det. Ordenen gjør seg nok klar til å slå tilbake nå.","Teraz, gdy mamy zamek pod kontrolą, musimy być bardzo czujni, by go utrzymać. Zakon pewnie szykuje się do ataku.","Agora que temos o castelo sob controle, precisamos estar mais alertas para mantê-lo assim. A Ordem provavelmente está se preparando para contra-atacar neste momento.",,"Acum că avem castelul sub control, va trebui să fim și mai vigilenți pentru a-l păstra. Ordinul probabil se pregătește pentru un atac de recuperare chiar acum.","Замок теперь наш, но если хотим его удержать, нужно не терять бдительности. Быть может, именно сейчас Орден готовит контратаку.",,Nu när vi faktiskt har slottet under kontroll måste vi vara extra vaksamma för att behålla det. Ordern gör sig förmodligen redo att slå tillbaka just nu.,"Artık kaleyi kontrol altına aldığımıza göre, onu korumak için daha dikkatli olmalıyız. Tarikat muhtemelen şu anda geri saldırmaya hazırlanıyor." +Be careful out there.,TXT_DLG_SCRIPT10_D43964_BECAR,MAP10: Castle's entrance.,,,Buď tam venku opatrný.,Vær forsigtig derude.,Sei vorsichtig da draußen.,,Agu singarde tie ekstere.,Ten cuidado ahí fuera.,Ten cuidado ahí afuera.,Pidä varasi siellä.,Faites attention à vous.,Vigyázz magadra odakinnt.,Sii cauto là fuori.,外は気を付けろ。,부디 조심하시길.,Wees voorzichtig daarbuiten.,Vær forsiktig der ute.,Bądźcie ostrożni.,Tome cuidado.,,Ai grijă afară.,Будь настороже.,,Var försiktig där ute.,Dışarıda dikkatli olun. +"Keep up the great work, we couldn't have done it without you.",TXT_DLG_SCRIPT10_D45480_KEEPU,MAP10: Rebel in Hospital.,,,"Jen tak dál, bez tebe bychom to nedokázali.","Fortsæt det gode arbejde, vi kunne ikke have gjort det uden jer.","Großartige Arbeit, mach weiter so. Ohne dich hätten wir es nicht schaffen können.",,"Daŭrigu tiel, ni ne estus sukcesintaj sen vi.","Sigue así, no podríamos haberlo logrado sin ti.",,Jatka samaan malliin; emme olisi pärjänneet näin hyvin ilman sinua.,"Continuez votre magnifique travail, nous n'aurions jamais réussi sans vous.","Csak így tovább, nélküled sosem tudtuk volna véghezvinni.","Continua così, non ce l'avremmo fatta senza di te.","我々は貴方無くして成し遂げる事は出来なかった +素晴らしい働きをしてくれてます。",부디 건투를 빕니다. 당신 덕에 희망을 잃지 않는 거니까!,"Ga zo door, we hadden het zonder jou niet kunnen doen.","Fortsett med det flotte arbeidet, vi kunne ikke ha gjort det uten deg.","Kontynuujcie wspaniałą pracę, bez was nie dalibyśmy rady.",Continue assim. Nós não teríamos conseguido sem você.,,"Continuă să faci treabă bună, n-am fi reușit fără tine.",Продолжай в том же духе. Без тебя мы бы не справились.,,"Fortsätt med ert fantastiska arbete, vi hade inte kunnat göra det utan er.","Harika iş çıkarmaya devam edin, siz olmadan bunu başaramazdık." +I'm the keymaster.,TXT_DLG_SCRIPT11_D0_IMTHE,MAP11: Commons (no token).,,,Já jsem tu klíčníkem.,Jeg er nøglemesteren.,Ich bin der Schlüsselmeister.,,Mi estas la ŝlosilestro.,Soy el amo de llaves.,,Olen avainmestari.,Je suis le maître des clés.,Én vagyok a kulcsmester.,Io sono il mastro delle chiavi.,僕がキーマスターだ。,전 열쇠지기에요.,Ik ben de sleutelbeheerder.,Jeg er nøkkelmesteren.,Jestem mistrzem kluczy.,Eu sou o mestre das chaves.,,Sunt stăpânul cheilor.,Я ключник.,,Jag är nyckelmästaren.,Ben anahtar yöneticisiyim. +"A lot of people would say this is a thankless and insignificant job. But it's not, in fact...",TXT_DLG_SCRIPT11_D1516_ALOTO,〃 (Oracle's token),,,"Většina lidí by řekla, že tohle je nevděčná a nedůležitá práce, ale není, naopak...","Mange ville sige, at det er et utaknemmeligt og ubetydeligt job. Men det er det ikke, faktisk...","Eine Menge Leute würden sagen, dies sei eine undankbare Aufgabe, aber das ist es nicht, in Wirklichkeit...",,"Multaj homoj dirus, ke ĉi tiu estas sendanka kaj sensignifa laboro, sed ne, fakte...","Mucha gente diría que este es un trabajo ingrato e insignificante, pero no, de hecho...",,Monet väittäisivät tehtäväni olevan epäkiitollinen ja vähäpätöinen. Mutta oikeasti se ei ole.,"Beaucoup de gens diraient que c'est un travail insignifiant et ingrat.. Mais en fait, ce n'est vraiment pas le cas.","Sokan azt mondják, hogy ez egy hálátlan és jelentéktelen munka. Ám nem is állhatnának messzebb az igazságtól...","Molte persone direbbero che questo è un lavoro ingrato e insignificante. Ma non lo è, infatti...","皆、この仕事が報われないと思っているが +実際はそうでもないんだ...","많은 사람이 이 직업을 감사해야 하고 놀라운 일이라 말하겠죠. 하지만 아닌데, 사실은...","Veel mensen zouden zeggen dat dit een ondankbare en onbeduidende klus is. Maar dat is het niet, in feite....",Mange vil si at dette er en utakknemlig og ubetydelig jobb. Men det er det faktisk ikke...,"Wielu ludzi powiedziałoby, że to niewdzięczna i mało znacząca praca. Ale tak nie jest, w rzeczywistości...",Muita gente diria que este é um trabalho ingrato e insignificante. Mas na verdade não é...,,"O grămadă de oameni ar spune că e o muncă fără mulțumiri și insignifiantă. În realitate, nu este...","Многие скажут, что это неблагодарная и незначительная работа, но это не так. На самом деле...",,"Många skulle säga att det är ett otacksamt och obetydligt jobb. Men det är det inte, i själva verket...","Birçok insan bunun nankör ve önemsiz bir iş olduğunu söyleyebilir. Ama değil, aslında..." +Give me the key!,TXT_RPLY0_SCRIPT11_D1516_GIVEM,〃,,,Dej mi klíč!,Giv mig nøglen!,Gib mir den Schlüssel.,,Donu al mi la ŝlosilon!,¡Dame la llave!,,Anna minulle avain!,Donne moi la clé!,Add ide a kulcsot!,Dammi la chiave!,鍵をくれ!,그냥 망할 열쇠를 줘!,Geef me de sleutel!,Gi meg nøkkelen!,Daj mi klucz!,Me dê a chave!,,Dă-mi cheia!,Дай мне ключ!,,Ge mig nyckeln!,Anahtarı bana ver! +"OK, but remember, I'm the keymaster.",TXT_DLG_SCRIPT11_D3032_OKBUT,〃,,,"Dobře, ale nezapomeň, že klíčník jsem já.","OK, men husk, jeg er nøglemesteren.","Ok, aber vergiß nicht, dass ICH der Schlüsselmeister bin.",,"Bone, sed memoru: mi estas la ŝlosilestro.","Bueno, pero recuerda: soy el amo de llaves.",,"Selvä, mutta muista: minä olen avainmestari.","Ok, mais souviens-toi, je suis le maître des clés.","OK, de emlékezz arra, hogy Én vagyok a kulcsmester.","OK, ma ricorda, io sono il mastro delle chiavi.",オーケー、なんせ僕は、キーマスターだしな。,"좋아요, 하지만 기억해요. 전 열쇠지기랍니다!","Oké, maar onthoud, ik ben de sleutelbeheerder.","OK, men husk at jeg er nøkkelmesteren.","OK, ale pamiętaj, że to ja jestem klucznikiem.","Ok, mas lembre-se, eu sou o mestre das chaves.",,"Bine, dar ține minte, eu sunt stăpânul cheilor.","Держи, но помни: я ключник!",,"Okej, men kom ihåg att jag är nyckelmästaren.","Tamam, ama unutma, anahtar ustası benim." +"OK pal, whatever.",TXT_RPLY0_SCRIPT11_D3032_OKPAL,〃,,,"Jasně, kámo, klidně.","Okay, kammerat.","Was auch immer, Kumpel.",,"Jes, ulo, mi kredas vin.","Sí, colega, lo que tú digas.","Sí, amigo, como tú digas.","Joo joo, ihan sama.","Comme tu veux, mon ami.","OK öreg, nem hat meg.","Sì, certo, come no.",わかった、何なりと。,"그래, 알 게 뭐야...","Oké, vriend, wat dan ook.","OK, kompis, samme det.","OK kolego, nieważne.","Ok, amigo. Que seja.",,"Bine amice, cum spui tu.",Ага. Без проблем.,,"Okej kompis, vad som helst.","Tamam dostum, her neyse." +I'm the keymaster.,TXT_DLG_SCRIPT11_D4548_IMTHE,〃,,,Já jsem tu klíčníkem.,Jeg er nøglemesteren.,Ich bin der Schlüsselmeister.,,Mi estas la ŝlosilestro.,Soy el amo de llaves.,,Minä olen avainmestari.,Je suis le maître des clés.,Én vagyok a kulcsmester.,Io sono il mastro delle chiavi.,僕がキーマスターだ。,열쇠지기. 그게 바로 저죠!,Ik ben de sleutelbeheerder.,Jeg er nøkkelmesteren.,Ja jestem klucznikiem.,Eu sou o mestre das chaves.,,Sunt stăpânul cheilor.,Я ключник.,,Jag är nyckelmästaren.,Anahtar ustası benim. +Die traitor!,TXT_DLG_SCRIPT11_D6064_DIETR,MAP11: Red acolyte at temple's entrance.,,,"Zemři, zrádče!","Dø, forræder!","Stirb, Verräter.",,"Mortu, perfidulo!","¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,死ね、反逆者!,"죽어라, 배신자!","Sterf, verrader.",Dø forræder!,Giń zdrajco!,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!",,"Dö, förrädare!",Geber hain! +Die traitor!,TXT_DLG_SCRIPT11_D7580_DIETR,〃,,,"Zemři, zrádče!","Dø, forræder!","Stirb, Verräter.",,"Mortu, perfidulo!","¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,死ね、反逆者!,"뒈져라, 배신자!","Sterf, verrader.",Dø forræder!,Giń zdrajco!,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!",,"Dö, förrädare!",Geber hain! +"Have you come to gloat? Even though we're behind these bars, as long as we hold on, you still lose.",TXT_DLG_SCRIPT11_D9096_HAVEY,MAP11: Prisoner.,,,"Přišel ses nám vysmívat? I když jsme za mřížemi, dokud jsme na nohou, ty zůstáváš poražený.","Er du kommet for at fryde dig? Selvom vi er bag disse tremmer, så længe vi holder fast, taber du stadig.","Bist du zum Glotzen gekommen? Auch wenn wir hinter Gittern sind, solange wir nicht aufgeben wirst du immer noch verlieren.",,"Ĉu vi venis rikani? Eĉ se ni estas malliberaj, dum ni eltenos, vi perdos.","¿Has venido a regodearte? Aunque estemos entre rejas, mientras sigamos en pie, vosotros perdéis.","¿Viniste a burlarte? Aunque estemos entre rejas, mientras sigamos en pie, ustedes pierden.","Oletko tullut meitä pilkkaamaan? Vaikka olemmekin näiden kaltereiden takansa, niin kunhan vain pidämme pintamme, sinä silti häviät.","Vous êtes venu vous moquer de nous? Même si on est derrière les barreaux, du moment que l'on reste en vie, vous allez perdre.","Dicsekedni jöttél ide? Habár itt rohadunk a rács mögött, amíg kitartunk miénk a győzelem.","Sei venuto a gongolare? Anche se siamo dietro queste sbarre, finché resisteremo, voi perderete.","何睨んでるんだ?この棒が俺達を囲んでる限り、 +お前は未だに負けている。","거들먹거리러 온 거냐? 비록 우리가 이 철창에 갇히긴 했지만, 계속 여기 있으면 넌 아직도 질 거라고.","Ben je gekomen om je te verkneukelen? Ook al zitten we achter deze tralies, zolang we ons vasthouden, verlies je nog steeds.","Har du kommet for å hovere? Selv om vi er bak gitteret, taper du så lenge vi holder fast.","Przyszliście się napawać? Nawet jeśli jesteśmy za tymi kratami, to dopóki się trzymamy, ty wciąż przegrywasz.","Você veio se gabar? Mesmo que a gente esteja atrás destas grades, enquanto resistirmos, você ainda perde.",,"Ai venit să te lauzi? Chiar dacă suntem în spatele gratilor, cât timp rezistăm, tu pierzi.","Пришёл поглумиться? Пусть мы и за этими решётками, но пока мы живы, вам не победить.",,"Har du kommit för att skryta? Även om vi är bakom dessa galler, så länge vi håller ut, förlorar du ändå.","Kına yakmaya mı geldin? Bu parmaklıkların arkasında olsak bile, biz dayandığımız sürece siz kaybedersiniz." +Let us out of here!,TXT_DLG_SCRIPT11_D10612_LETUS,〃,,,Pusť nás odsud!,Lad os komme ud herfra!,Lass uns hier raus!,,Liberigu nin!,¡Sácanos de aquí!,,Päästä meidät pois täältä!,Sortez nous de là!,Engedj ki minket!,Facci uscire da qua!,ここから出してくれ!,우릴 여기서 내보내 줘!,Laat ons hier uit!,Slipp oss ut herfra!,Wypuść nas stąd!,Nos tire daqui!,,Scoate-ne de aici!,Выпусти нас отсюда!,,Släpp ut oss härifrån!,Çıkarın bizi buradan! +Leave me alone!,TXT_DLG_SCRIPT11_D12128_LEAVE,〃,,,Nech mě být!,Lad mig være i fred!,Lass mich in Ruhe!,,Ne ĝenu min!,¡Déjame en paz!,,Jätä minut rauhaan!,Foutez moi la paix!,Hagyj békén!,Lasciami in pace!,ほっといてくれ!,날 좀 내버려 둬!,Laat me met rust!,La meg være i fred!,Zostawcie mnie w spokoju!,Me deixe em paz!,,Lasă-mă în pace!,Оставь меня в покое!,,Lämna mig ifred!,Beni yalnız bırakın! +"What is the wisdom you seek, simple one?",TXT_DLG_SCRIPT12_D0_WHATI,MAP12: Oracle.,,,"Jaké moudro hledáš, jednoduchý?","Hvad er det for en visdom du søger, simple en?","Welche Weisheit suchst du, Menschling?",,"Kiun saĝecon vi serĉas, simplulo?","¿Qué sabiduría buscas, simplón?",,"Mitä viisautta etsit, sinä tietämätön?","Quelle est la sagesse que vous recherchez, simple humain?","Miféle bölcsességet kutatsz, egyszerű barátom?","Qual è la saggezza che cerchi, ottenebrato ?",迷える者よ、如何なる知識を求めに来た。,그대가 찾고 있는 지혜는 어떤 것인가? 평범한 자여?,"Wat is de wijsheid die je zoekt, eenvoudige wijsheid?","Hva er visdommen du søker, enfoldige?","Jakiej mądrości szukasz, prosty?","Qual é a sabedoria que você procura, simples criatura?",,"Ce întelepciune cauți, om simplu?","Какой мудрости ты ищешь, непосвящённый?",,"Vad är det för visdom du söker, enkla man?","Aradığın bilgelik nedir, basit olan?" +The Sigil of the One God.,TXT_RPLY0_SCRIPT12_D0_THESI,〃,,,Pečeť Jednoho boha.,Sigilet af den ene Gud.,Das Sigil des Einen Gottes.,,La Sigelon de la Vera Dio.,El Emblema del Dios Único.,,Yhden Ainoan Jumalan Sinettiä.,Le Sigil du Seul Dieu.,Az egy Igaz Isten pecsétjét.,Il Sigillo dell'Unico Dio.,唯一神のシジルだ。,"유일신의 인장, 시질이다.",De Sigil van de Ene God.,Den ene Guds sigill.,Sigil Jedynego Boga.,O Sigilo do Deus Único.,,Sigiliul Adevăratului Zeu.,Печать Единого Бога.,,Den ende gudens signum.,Tek Tanrı'nın Mührü. +"I feel one fragment resonate within you. The second lies at the heart of the crimson and obsidian tower. There you must combat the Bishop, who is aware, and awaits you. You will find him by following his symbol of power. Take this token to the keymaster. Return to me after you have slain the beast.",TXT_DLG_SCRIPT12_D1516_IFEEL,〃,,,"Cítím z tebe rezonovat jeden díl. Druhý leží v srdci věže karmíno-obsidiánové. Tam musíš poraziti Biskupa, který si je tě vědom a očekává tě. Najdeš ho následováním symbolu jeho moci. Přijmi tuto známku pro klíčníka. Vrať se ke mě, až skolíš bestii.","Jeg føler et fragment resonere i dig. Det andet ligger i hjertet af det purpurfarvede og obsidian tårn. Der skal du bekæmpe biskoppen, som er klar over det og venter på dig. Du finder ham ved at følge hans symbol for magt. Tag dette symbol med til nøglemesteren. Vend tilbage til mig, når du har dræbt udyret.","Ich fühle, wie ein Fragment in dir pulsiert, Das zweite Teilstück des Sigils befindet sich im Herzen des Turms aus Purpur und Obsidian. Dort wartet der Bischof auf dich, den du bekämpfen musst. Er weiß von dir und wartet. Du findest ihn, wenn du seinem Symbol der Macht folgst. Nimm dieses Zeichen und gebe es dem Schlüsselmeister. Kehr zu mir zurück, nachdem du die Bestie vernichtet hast.",,"Mi sentas, ke fragmento resonas en vi. La dua situas en la koro de la turo karmezina kaj obsidiankolora: tie vi devas batali kontraŭ la Episkopo, kiu antaŭsciis ĉi tion kaj atendas vin; vi trovos lin sekvante lian povsimbolon. Donu ĉi tiun paspermeson al la ŝlosilestro. Mortiginte la beston, revenu ĉi tien.",Siento un fragmento resonar en ti. El segundo se encuentra en el corazón de la torre carmesí y obsidiana: ahí debes combatir con el Obispo que sabe y espera tu llegada; lo encontrarás siguiendo su símbolo de poder. Llévale este pase al amo de llaves. Vuelve a mí después de matar a la bestia.,Siento un fragmento resonar en ti. El segundo se encuentra en el corazón de la torre carmesí y obsidiana: ahí debes combatir con el Obispo que sabe y espera tu llegada; lo vas a encontrar siguiendo su símbolo de poder. Llévale este pase al amo de llaves. Vuelve a mí después de matar a la bestia.,"Minä tunnen yhden osasen väräjävän sisälläsi. Toinen piilee purppuranpunaisen laavalasisen tornin sydämessä. Siellä pitää sinun taisteleman Piispaa vastaan, joka on tietoinen ja sinua odottava. Löydät hänet seuraamalla hänen valtansa tunnuskuvaa. Toimita tämä merkki avainmestarille. Palaa tyköni surmattuasi pedon.","Je sens un fragment résonner en toi. Le deuxième repose au cœur de la tour d'obsidienne et d'écarlate. Ici, vous devrez défaire l'évêque, qui connaît déjà votre statut, et vous attend patiemment. Vous le trouverez en suivant son symbole de pouvoir. Prenez ce jeton et amenez le au maître des clés. Retournez à moi après que vous ayez vaincu la bête.","Érzem rajta az egyik darabot. A másodikat a karmazsin és obszidián toronyban találod meg. Ott viszont már várni fog rád a Püspök. Meg fogod lelni őt, ha követed a jelét. Vidd ezt a zálogot a kulcsmesterhez. Térj vissza hozzám, ha legyűrted a szörnyet.","Avverto che possiedi uno dei frammenti. Il secondo si trova nel cuore della torre cremisina e ossidiana. Lì dovrai combattere contro il Vescovo, che già ti attende. Lo troverai seguendo il suo simbolo del potere. Prendi questo gettone per il mastro delle chiavi. Ritorna da me dopo che avrai ucciso la bestia.","お主の持つ欠片が共鳴しているのを感受出来る。 二つ目の欠片は紅と黒曜の塔だ。 そこでお主を待ち構えているビショップと戦え。 その者が持つシンボルを辿れば見つかるだろう。 このトークンをキーマスターに渡せ。 魔物を討伐した後、此処へ戻るのだ。",그대에게서 시질의 조각 중 하나가 느껴지는군. 두 번째 조각은 진홍빛 흑요석 탑의 심장부에 있다. 거기서 기다리고 있는 비숍과 싸워야 한다. 그 자의 권력을 상징하는 문양을 따라가면 만날 수 있을 것이다. 열쇠지기에게 이 통행증을 전해주어라. 그리고 괴물을 처치하면 다시 나에게로 오라.,"Ik voel een fragment in je resoneren. Het tweede fragment ligt in het hart van de karmozijnrode en obsidiaan toren. Daar moet je de bisschop bestrijden, die zich bewust is van de situatie en op je wacht. Je zult hem vinden door zijn machtssymbool te volgen. Neem dit teken mee naar de sleutelbeheerder. Keer naar mij terug nadat je het beest hebt gedood.","Jeg føler et fragment resonere i deg. Det andre ligger i hjertet av det purpurfargede og obsidianske tårnet. Der må du bekjempe biskopen, som vet og venter på deg. Du finner ham ved å følge hans maktsymbol. Ta dette symbolet til nøkkelmesteren. Kom tilbake til meg etter at du har drept udyret.","Czuję, że jeden fragment rezonuje w tobie. Drugi leży w sercu karmazynowej i obsydianowej wieży. Tam musisz walczyć z Biskupem, który jest świadomy i czeka na ciebie. Znajdziesz go podążając za jego symbolem mocy. Zanieś ten żeton do klucznika. Wróć do mnie po zabiciu bestii.","Posso sentir um fragmento ressoar de dentro de você. O segundo está na torre carmesim e obsidiana. Lá você deverá combater o Bispo, que está acordado e te aguarda. Você o encontrará seguindo o seu símbolo de poder. Leve esta ensígnia ao mestre das chaves. Volte depois de eliminar a besta.",,"Simt un fragment care rezonează în tine. Al doilea e în inima turnului purpuriu, din obsidian. Acolo îl vei înfrunta pe Episcop, care e conștient, și în așteptare. Îl vei găsi urmându-i simbolul puterii. Du asta la stăpânul cheilor. Întoarce-te după ce ai înfrânt fiara.","Я чувствую один фрагмент, настроенный на тебя. Второй лежит в сердце багрово-обсидиановой башни. Там тебе предстоит сразиться с Епископом — он знает о тебе и ждёт твоего появления. Его символ власти приведёт тебя прямо к нему. Отнеси этот жетон ключнику. Срази чудовище и возвращайся ко мне. -",,"Bir parçanın içinde yankılandığını hissediyorum. İkincisi kızıl ve obsidyen kulenin kalbinde yatıyor. Orada, farkında olan ve seni bekleyen Piskopos'la savaşmalısın. Onu güç sembolünü takip ederek bulacaksın. Bu simgeyi anahtar ustasına götür. Canavarı öldürdükten sonra bana dön." -I'll be back.,TXT_RPLY0_SCRIPT12_D1516_ILLBE,〃,,,Vrátím se.,Jeg kommer tilbage.,Ich werde zurückkommen.,,Mi revenos.,Volveré.,,Tulen takaisin.,Je reviendrai.,Visszatérek még.,Ritornerò.,すぐ戻ってくる。,금방 돌아올게.,Ik kom terug.,Jeg kommer tilbake.,Wrócę.,Eu voltarei.,,Mă voi întoarce.,Я вернусь.,,Geri geleceğim. -"Although the Bishop is formidable, this quest is slight. Return to me when you possess the next fragment.",TXT_DLG_SCRIPT12_D3032_ALTHO,〃,,,"I přes Biskupovu hrozivost je tento úkol drobný. Vrať se, až budeš vlastnit další díl.","Selv om biskoppen er formidabel, er denne søgen let. Vend tilbage til mig, når du er i besiddelse af det næste fragment.","Auch wenn der Bischof ein schwerer Gegner ist, diese Aufgabe ist geringfügig. Komm zu mir zurück, wenn du das nächste Fragment besitzt.",,,"Aunque el Obispo es formidable, esta misión es leve. Vuelve a mí cuando poseas el siguiente fragmento.",,"Vaikka suuri onkin Piispa, pieni kuitenkin on tämä tehtävä. Palaa tyköni, kun seuraava osanen on hallussasi.","Bien que l'évêque soit un puissant adversaire, cette quête n'est qu'une courte aventure. Revenez à moi quand vous possédez le deuxième fragment.","Habár a Püspök méltó ellenfél lesz, a küldetésed könnyű. Térj vissza, ha megvan a következő darabka.","Anche se il Vescovo è formidabile, questa sfida è leggera. Ritorna da me non appena possiedi il prossimo frammento.","ビショップは手強く、この使命は困難であろう。 +",,"Jag känner ett fragment resonera inom dig. Det andra ligger i hjärtat av det karmosinröda och obsidianska tornet. Där måste du bekämpa biskopen, som är medveten och väntar på dig. Du hittar honom genom att följa hans maktsymbol. Ta den här symbolen till nyckelmästaren. Återvänd till mig när du har dödat odjuret.","Bir parçanın içinde yankılandığını hissediyorum. İkincisi kızıl ve obsidyen kulenin kalbinde yatıyor. Orada, farkında olan ve seni bekleyen Piskopos'la savaşmalısın. Onu güç sembolünü takip ederek bulacaksın. Bu simgeyi anahtar ustasına götür. Canavarı öldürdükten sonra bana dön." +I'll be back.,TXT_RPLY0_SCRIPT12_D1516_ILLBE,〃,,,Vrátím se.,Jeg kommer tilbage.,Ich werde zurückkommen.,,Mi revenos.,Volveré.,,Tulen takaisin.,Je reviendrai.,Visszatérek még.,Ritornerò.,すぐ戻ってくる。,금방 돌아올게.,Ik kom terug.,Jeg kommer tilbake.,Wrócę.,Eu voltarei.,,Mă voi întoarce.,Я вернусь.,,Jag kommer tillbaka.,Geri geleceğim. +"Although the Bishop is formidable, this quest is slight. Return to me when you possess the next fragment.",TXT_DLG_SCRIPT12_D3032_ALTHO,〃,,,"I přes Biskupovu hrozivost je tento úkol drobný. Vrať se, až budeš vlastnit další díl.","Selv om biskoppen er formidabel, er denne søgen let. Vend tilbage til mig, når du er i besiddelse af det næste fragment.","Auch wenn der Bischof ein schwerer Gegner ist, diese Aufgabe ist geringfügig. Komm zu mir zurück, wenn du das nächste Fragment besitzt.",,"Kvankam la Episkopo estas timindega, ĉi tiu tasko estas sensignifa. Revenu al mi kiam vi havos la sekvan fragmenton.","Aunque el Obispo es formidable, esta misión es leve. Vuelve a mí cuando poseas el siguiente fragmento.",,"Vaikka suuri onkin Piispa, pieni kuitenkin on tämä tehtävä. Palaa tyköni, kun seuraava osanen on hallussasi.","Bien que l'évêque soit un puissant adversaire, cette quête n'est qu'une courte aventure. Revenez à moi quand vous possédez le deuxième fragment.","Habár a Püspök méltó ellenfél lesz, a küldetésed könnyű. Térj vissza, ha megvan a következő darabka.","Anche se il Vescovo è formidabile, questa sfida è leggera. Ritorna da me non appena possiedi il prossimo frammento.","ビショップは手強く、この使命は困難であろう。 次の欠片を手にしたら此処へ戻るのだ。 -","비숍은 만만치 않은 상대지만, 이보다 더한 일들이 기다리고 있다. 두 번째 조각을 찾고 다시 돌아오라.","Hoewel de bisschop formidabel is, is deze zoektocht gering. Keer terug naar mij als je het volgende fragment bezit.","Selv om biskopen er formidabel, er dette oppdraget lett. Kom tilbake til meg når du har det neste fragmentet.","Choć Biskup jest potężny, to zadanie jest niewielkie. Wróć do mnie, gdy posiądziesz kolejny fragment.","Embora o Bispo seja poderoso, esta missão é simples. Retorne para mim quando você possuir o próximo fragmento.",,"Deși Episocopul e formidabil, misiunea asta e ușoara. Întoarce-te când ai cel de-al doilea fragment.","Каким бы страшным Епископ ни был, это задание не доставит тебе хлопот. Достань следующий фрагмент и возвращайся ко мне.",,"Piskopos zorlu olsa da, bu görev hafif. Bir sonraki parçayı ele geçirdiğinde bana geri dön." -Your next challenge will test your spirit. The third piece is held by your own leader. He is the same as that which he sends you to kill.,TXT_DLG_SCRIPT12_D4548_YOURN,,,,"Tvá další výzva pokusí tvou vůli. Třetí díl je držen tvým vlastním vůdcem. Je stejný, jako ti, které tě posílá zabít.","Din næste udfordring vil sætte din ånd på prøve. Det tredje stykke er i din egen leders besiddelse. Han er den samme som den, han sender dig ud for at dræbe.","Die nächste Herausforderung wird deinen Geist prüfen. Das dritte Teilstück wird von deinem eigenen Anführer, Macil, gehalten. Er ist das Gleiche, was er dich töten lässt.",,,Tu próximo desafío pondrá a prueba tu espíritu. El tercer fragmento está en manos de tu propio líder. Él es igual que aquello que te envía a matar.,,"Seuraava haasteesi koettelee sinua henkisesti. Kolmatta osasta pitää hallussaan oma päämiehesi. Hän on sama kuin se, jonka hän lähettää sinut surmaamaan.",Le prochain défi testera votre esprit. Le troisième fragment est possédé par votre leader. Il est le même que celui qu'il vous a envoyé tuer.,"A következő kihívás próbára fogja tenni a lelked. A harmadik darab a saját vezetődnél van. Ő maga ugyanaz, mint akiért elküldött.",La tua prossima sfida metterà alla prova il tuo spirito. Il terzo frammento è posseduto dal tuo stesso capo. Lui è uguale a quelli che ti manda ad uccidere.,"次の挑戦はお主の精神が試されるだろう。 +","비숍은 만만치 않은 상대지만, 이보다 더한 일들이 기다리고 있다. 두 번째 조각을 찾고 다시 돌아오라.","Hoewel de bisschop formidabel is, is deze zoektocht gering. Keer terug naar mij als je het volgende fragment bezit.","Selv om biskopen er formidabel, er dette oppdraget lett. Kom tilbake til meg når du har det neste fragmentet.","Choć Biskup jest potężny, to zadanie jest niewielkie. Wróć do mnie, gdy posiądziesz kolejny fragment.","Embora o Bispo seja poderoso, esta missão é simples. Retorne para mim quando você possuir o próximo fragmento.",,"Deși Episocopul e formidabil, misiunea asta e ușoara. Întoarce-te când ai cel de-al doilea fragment.","Каким бы страшным Епископ ни был, это задание не доставит тебе хлопот. Достань следующий фрагмент и возвращайся ко мне.",,Även om biskopen är formidabel är detta uppdrag lätt. Återvänd till mig när du besitter nästa fragment.,"Piskopos zorlu olsa da, bu görev hafif. Bir sonraki parçayı ele geçirdiğinde bana geri dön." +Your next challenge will test your spirit. The third piece is held by your own leader. He is the same as that which he sends you to kill.,TXT_DLG_SCRIPT12_D4548_YOURN,MAP12: Oracle → After killing the Bishop,,,"Tvá další výzva pokusí tvou vůli. Třetí díl je držen tvým vlastním vůdcem. Je stejný, jako ti, které tě posílá zabít.","Din næste udfordring vil sætte din ånd på prøve. Det tredje stykke er i din egen leders besiddelse. Han er den samme som den, han sender dig ud for at dræbe.","Die nächste Herausforderung wird deinen Geist prüfen. Das dritte Teilstück wird von deinem eigenen Anführer, Macil, gehalten. Er ist das Gleiche, was er dich töten lässt.",,"Via sekva defio provos vian spiriton. Via propra estro posedas la trian pecon; li estas egala al tio, kion mortigi li sendas vin.",Tu próximo desafío pondrá a prueba tu espíritu. El tercer fragmento está en manos de tu propio líder; él es igual a aquello que te envía a matar.,Tu próximo desafío va a poner a prueba tu espíritu. El tercer fragmento está en manos de tu propio líder; él es igual a aquello que te manda a matar.,"Seuraava haasteesi koettelee sinua henkisesti. Kolmatta osasta pitää hallussaan oma päämiehesi. Hän on sama kuin se, jonka hän lähettää sinut surmaamaan.",Le prochain défi testera votre esprit. Le troisième fragment est possédé par votre leader. Il est le même que celui qu'il vous a envoyé tuer.,"A következő kihívás próbára fogja tenni a lelked. A harmadik darab a saját vezetődnél van. Ő maga ugyanaz, mint akiért elküldött.",La tua prossima sfida metterà alla prova il tuo spirito. Il terzo frammento è posseduto dal tuo stesso capo. Lui è uguale a quelli che ti manda ad uccidere.,"次の挑戦はお主の精神が試されるだろう。 三つ目の欠片はお主の指導者が所持している。 彼奴はお主の死を望むが為 -戦場へ送り込んでいるのだ。",다음 도전은 그대의 정신을 시험할 것이다. 세 번째 조각은 바로 그대의 지도자가 가지고 있다. 그는 그대를 시켜서 죽였던 괴물들과 마찬가지인 존재다.,Je volgende uitdaging zal je geest testen. Het derde stuk is in handen van je eigen leider. Hij is hetzelfde als wat hij je stuurt om te doden.,Din neste utfordring vil sette din ånd på prøve. Den tredje brikken holdes av din egen leder. Han er den samme som han sender deg for å drepe.,"Twoje kolejne wyzwanie będzie testem dla twojego ducha. Trzeci kawałek jest w posiadaniu waszego przywódcy. Jest taki sam jak ten, którego wysyła, byś zabił.",Seu próximo desafio testará o seu espírito. A terceira peça está com o seu próprio líder. Ele é a mesma pessoa que ele quer que você mate.,,Următoarea provocare îți va testa spiritul. A treia piesă e deținută de liderul tău. A celași care te trimite să omori.,"Следующее задание испытает силу твоего духа. Третий фрагмент у вашего лидера. Он сам — один из тех, кого вы убиваете по его приказу.",,Bir sonraki mücadeleniz ruhunuzu sınayacak. Üçüncü parça kendi lideriniz tarafından tutuluyor. Seni öldürmen için gönderdiğiyle aynı kişi. -Macil? A traitor?,TXT_RPLY0_SCRIPT12_D4548_MACIL,,,,Macil? Zrádce?,Macil? En forræder?,Macil? Ein Verräter?,,,¿Macil? ¿Un traidor?,,Macil? Petturiko?,Macil? Un traître?,Macil? Egy áruló volna?,Macil? Un traditore?,マシル?彼が裏切者?,마실이 배신자라고?,Macil? Een verrader?,Macil? En forræder?,Macil? Zdrajca?,Macil? Um traidor?,,Macil? Un trădător?,Мэйсил? Предатель?,,Macil mi? Bir hain mi? -Your blind faith has allowed him to advance to his goals with each piece you gain. Confront him and resolve your fate.,TXT_DLG_SCRIPT12_D6064_YOURB,,,,"Tvá slepá víra mu dovolila přiblížit se k jeho cíli s každým dalším dílem, jenž získáš. Postav se mu a rozhodni svůj osud.","Din blinde tro har gjort det muligt for ham at komme videre til sine mål med hver brik, du får. Konfronter ham, og afklar din skæbne.","Deine blinde Treue hat es ihm erlaubt, seine eigenen Ziele voranzutreiben - mit jedem Fragment, das du findest. Konfrontiere ihn und kläre dein Schicksal.",,,Tu fé ciega le ha permitido avanzar en sus objetivos con cada pieza que ganas. Confróntalo y resuelve tu destino.,,Sokea uskosi on sallinut hänen edistää omia tavoitteitaan jokaisen saavuttamasi osasen myötä. Kohtaa hänet ja päätä kohtalosi.,"Votre dévotion aveugle lui a permis d'avancer vers ses fins. Avec chaque fragment que vous récupérez, il s'en rapproche encore. Confrontez le et faites-face à votre destinée.","A vakon belé vetett hited segített számára, hogy minden darabkával közelebb jusson a céljához. Szembesítsd vele, és tisztázd le magadban a hited.",La tua fede cieca gli ha permesso di raggiungere i suoi obiettivi con ogni pezzo che ottieni. Affrontalo e risolvi il tuo destino.,"彼を妄信するお主の活躍によって、 +戦場へ送り込んでいるのだ。",다음 도전은 그대의 정신을 시험할 것이다. 세 번째 조각은 바로 그대의 지도자가 가지고 있다. 그는 그대를 시켜서 죽였던 괴물들과 마찬가지인 존재다.,Je volgende uitdaging zal je geest testen. Het derde stuk is in handen van je eigen leider. Hij is hetzelfde als wat hij je stuurt om te doden.,Din neste utfordring vil sette din ånd på prøve. Den tredje brikken holdes av din egen leder. Han er den samme som han sender deg for å drepe.,"Twoje kolejne wyzwanie będzie testem dla twojego ducha. Trzeci kawałek jest w posiadaniu waszego przywódcy. Jest taki sam jak ten, którego wysyła, byś zabił.",Seu próximo desafio testará o seu espírito. A terceira peça está com o seu próprio líder. Ele é a mesma pessoa que ele quer que você mate.,,Următoarea provocare îți va testa spiritul. A treia piesă e deținută de liderul tău. A celași care te trimite să omori.,"Следующее задание испытает силу твоего духа. Третий фрагмент у вашего лидера. Он сам — один из тех, кого вы убиваете по его приказу.",,Din nästa utmaning kommer att sätta din själ på prov. Den tredje biten innehas av din egen ledare. Han är densamma som den som han skickar dig att döda.,Bir sonraki mücadeleniz ruhunuzu sınayacak. Üçüncü parça kendi lideriniz tarafından tutuluyor. Seni öldürmen için gönderdiğiyle aynı kişi. +Macil? A traitor?,TXT_RPLY0_SCRIPT12_D4548_MACIL,〃,,,Macil? Zrádce?,Macil? En forræder?,Macil? Ein Verräter?,,Ĉu Macil? Ĉu perfidulo?,"¿Macil?, ¿un traidor?",,Macil? Petturiko?,Macil? Un traître?,Macil? Egy áruló volna?,Macil? Un traditore?,マシル?彼が裏切者?,마실이 배신자라고?,Macil? Een verrader?,Macil? En forræder?,Macil? Zdrajca?,Macil? Um traidor?,,Macil? Un trădător?,Мэйсил? Предатель?,,Macil? En förrädare?,Macil mi? Bir hain mi? +Your blind faith has allowed him to advance to his goals with each piece you gain. Confront him and resolve your fate.,TXT_DLG_SCRIPT12_D6064_YOURB,〃,,,"Tvá slepá víra mu dovolila přiblížit se k jeho cíli s každým dalším dílem, jenž získáš. Postav se mu a rozhodni svůj osud.","Din blinde tro har gjort det muligt for ham at komme videre til sine mål med hver brik, du får. Konfronter ham, og afklar din skæbne.","Deine blinde Treue hat es ihm erlaubt, seine eigenen Ziele voranzutreiben - mit jedem Fragment, das du findest. Konfrontiere ihn und kläre dein Schicksal.",,"Via blinda fido ebligis al li progresi en siaj celoj per ĉiu peco, kiun vi gajnas. Alfrontu lin por solvi vian destinon.",Tu fe ciega le ha permitido avanzar en sus objetivos con cada pieza que ganas. Confróntalo y resuelve tu destino.,,Sokea uskosi on sallinut hänen edistää omia tavoitteitaan jokaisen saavuttamasi osasen myötä. Kohtaa hänet ja päätä kohtalosi.,"Votre dévotion aveugle lui a permis d'avancer vers ses fins. Avec chaque fragment que vous récupérez, il s'en rapproche encore. Confrontez le et faites-face à votre destinée.","A vakon belé vetett hited segített számára, hogy minden darabkával közelebb jusson a céljához. Szembesítsd vele, és tisztázd le magadban a hited.",La tua fede cieca gli ha permesso di raggiungere i suoi obiettivi con ogni pezzo che ottieni. Affrontalo e risolvi il tuo destino.,"彼を妄信するお主の活躍によって、 彼奴の目的が果たされる間近だ。 -彼奴に立ち向かい、運命を切り開くのだ。",그대의 맹목적인 믿음이 조각들을 하나하나 찾으면서 그자의 목표를 이뤄주고 있다. 그를 상대하고 구속된 운명에서 벗어나라.,Jouw blinde geloof heeft hem in staat gesteld om met elk stuk dat je wint zijn doelen te bereiken. Confronteer hem en los je lot op.,Din blinde tro har gjort det mulig for ham å nå sine mål for hver brikke du vinner. Konfronter ham og avgjør din skjebne.,Twoja ślepa wiara pozwoliła mu na osiągnięcie celu z każdym zdobytym kawałkiem. Skonfrontuj się z nim i rozstrzygnij swój los.,Sua fé cega permitiu que ele avance em suas metas com cada peça que você adquire. Vá confrontá-lo e resolva o seu destino.,,"Credința ta oarbă i-a permis să-și avanseze planurile, cu fiecare piesă pe care o obții. Înfruntă-l și împlinește-ți destinul.","Твоя слепая вера приближала его к цели каждый раз, как ты находил фрагмент. Сразись с ним и исполни своё предназначение.",,"Kör inancınız, kazandığınız her parçayla hedeflerine ilerlemesine izin verdi. Onunla yüzleş ve kaderini çöz." -"All right, it is Macil.",TXT_RPLY0_SCRIPT12_D6064_ALLRI,,,,"Tak dobře, je to Macil.","Okay, det er Macil.","Na gut, es ist Macil.",,,"Muy bien, es Macil.",,"Niin se on, se on Macil.",Très bien. C'est le tour de Macil.,"Igazad volt, Macil az.","Va bene, è Macil.",わかった、それがマシルか。,역시... 마실이였군.,"Oké, het is Macil.","Greit, det er Macil.","W porządku, to Macil.",Certo. Então é o Macil.,,"Bine, Macil să fie.",Понятно. Я убью Мэйсила.,,"Pekala, bu Macil." -It's you I don't trust.,TXT_RPLY1_SCRIPT12_D6064_ITSYO,,,,Ale já nevěřím tobě.,"Det er dig, jeg ikke stoler på.","Du bist es, dem ich nicht vertraue.",,,Eres tú de quien no me fío.,,Sinuun en minä luota.,C'est vous à qui je ne fais pas confiance.,"Te vagy az, akiben nem bízok.",Sei tu quello di cui non mi fido.,信用できん。,내가 믿지 않는 건 네놈이다.,Ik vertrouw jou niet.,Det er deg jeg ikke stoler på.,To tobie nie ufam.,É você em quem eu não confio.,,Tu ești cel în care nu am încredere.,"Я думаю, что это ты лжешь!",,Güvenmediğim sensin. -Whatever choice you make your kind shall perish under the will of the One God.,TXT_DLG_SCRIPT12_D7580_WHATE,,,,"Nehledě na tvé rozhodnutí, tvůj druh skoná vůlí Jednoho boha.","Uanset hvilket valg du træffer, vil din slags gå under under den ene Guds vilje.","Welche Wahl du auch triffst, deine Spezies wird unter dem Willen des Einen Gottes zugrunde gehen.",,,Cualquiera que sea tu elección tu especie perecerá bajo la voluntad del Dios Único.,,"Teitpä minkä hyvänsä päätöksen, lajisi pitää hukkuman Yhden Ainoan Jumalan tahdon alle.","Quel que soit le choix que vous faites, votre espèce périra par la volonté du Seul Dieu.","Mindegy mire döntesz, az egy igaz isten szigora lesúlyt rád és fajtádra.","Qualunque scelta tu faccia, la tua specie perirà per il volere dell'Unico Dio.","如何なる選択でも、人類は大いなる神の元で -浄化されるだろう。","그대가 어떤 선택을 하더라도, 그대를 비롯한 종족은 유일신의 의지에 의해 멸망할 뿐이다.","Welke keuze je ook maakt, jouw soort zal vergaan onder de wil van de Ene God.","Uansett hvilket valg du tar, vil din art gå til grunne under den ene Guds vilje.","Jakiegokolwiek wyboru dokonasz, twój rodzaj zginie z woli Jedynego Boga.","Seja qual for a escolha que você fizer, sua espécie irá perecer sob a vontade do Deus Único.",,"Indiferent de alegerea ta, neamul tău va pieri sub voința Adevăratului Zeu.","Что бы ты ни выбрал, твой род исчезнет по воле Единого Бога.",,"Yaptığın seçim ne olursa olsun, türün Tek Tanrı'nın iradesi altında yok olacak." -I'll be back when Macil's dead.,TXT_RPLY0_SCRIPT12_D7580_ILLBE,,,,"Vrátím se, až bude Macil mrtev.","Jeg kommer tilbage, når Macil er død.","Ich komme wieder, wenn Macil tot ist.",,,Volveré cuando Macil esté muerto.,,"Tulen takaisin, kun Macil on kuollut.",Je reviendrai quand Macil sera mort.,"Visszajövök, ha Macil már halott.",Tornerò quando Macil sarà morto.,マシルの死と共に戻る。,마실을 죽이고 돌아오겠다.,Ik kom terug als Macil dood is.,Jeg kommer tilbake når Macil er død.,"Wrócę, gdy Macil będzie martwy.",Voltarei quando Macil estiver morto.,,Am să mă întorc odată ce Macil e mort.,Я вернусь после смерти Мэйсила.,,Macil öldüğünde geri döneceğim. -I can't let that happen.,TXT_RPLY1_SCRIPT12_D7580_ICANT,,,,To nemůžu dopustit.,Jeg kan ikke lade det ske.,Das darf nicht passieren.,,,No pienso permitirlo.,,En voi antaa sen tapahtua.,Je ne peux pas vous laisser faire ça.,Nem hagyhatom ezt.,Non posso permetterlo.,そうはさせん。,그렇게 할 순 없어.,Dat kan ik niet laten gebeuren.,Jeg kan ikke la det skje.,Nie mogę na to pozwolić.,Não posso deixar isso acontecer.,,Nu voi permite asta.,Я не могу этого допустить.,,Bunun olmasına izin veremem. -"The river of time moves forever onward, while you stand still.",TXT_DLG_SCRIPT12_D9096_THERI,,,,Řeka času plyne stále vpřed zatímco ty zůstáváš stát.,"Tidens flod bevæger sig for evigt fremad, mens du står stille.","Der Fluss der Zeit bewegt sich immer vorwärts, während du stillstehst.",,,"La corriente del tiempo sigue adelante, mientras tú sigues quieto.",,"Ajan virta liikkuu alati eteenpäin, samalla kun itse pysyt aloillasi.","La rivière du temps continue à couler, tandis que vous restez immobile.","Az idő folyója folyamat halad tovább, miközben te csak álldogállsz.","Il fiume del tempo scorre inesorabilmente, mentre tu rimani fermo.",事を措いても、時の河は永遠の先に進む。,"그대가 가만히 있어도, 시간의 강은 계속 흐를 뿐이다.","De rivier van de tijd beweegt voor altijd verder, terwijl je stilstaat.","Tidens elv beveger seg evig videre, mens du står stille.","Rzeka czasu płynie wiecznie do przodu, podczas gdy ty stoisz w miejscu.","O corrente do tempo se movimenta sempre adiante, enquanto você fica imóvel.",,"Râul timpului curge în permanență, în timp ce tu stai pe loc.","Река времени непрестанно течёт вперёд, в то время как ты стоишь без движения.",,"Sen dururken, zaman nehri sonsuza dek ilerliyor." -"You have cut the cancer from your body, but your heart still beats. Next you must find the surgeon who butchers and controls your people, the Loremaster. Stop him, and the next piece will be yours.",TXT_DLG_SCRIPT12_D10612_YOUHA,,,,"Vyřízl jsi rakovinu ze svého těla, tvé srdce však stále bije. Dále musíš najít doktora, jenž vraždí a ovládá tvé druhy, Dějepisce. Učiň mu přítrž a další díl bude tvůj.","Du har skåret kræften ud af din krop, men dit hjerte slår stadig. Nu skal du finde den kirurg, der slagter og kontrollerer dit folk, Loremesteren. Stop ham, og det næste stykke vil være dit.","Du hast das Geschwür aus deinem Körper entferrnt, aber dein Herz schlägt noch. Als Nächstes musst du den Wissensmeister finden, der deine Leute kontrolliert und abschlachtet. Stoppe ihn und das nächste Teilstück ist Dein.",,,"Has cortado el cáncer de tu cuerpo, pero tu corazón aún late. Lo siguiente es encontrar al cirujano que destroza y controla a tu gente, el Maestro del Conocimiento. Deténlo, y la próxima pieza será tuya.",,"Olet erottanut syövän ruumiistasi, mutta sydämesi silti sykkii. Seuraavaksi pitää sinun löytämän kirugin, joka teurastaa ja hallitsee kansaasi: Oppi-Isän. Pysäytä hänet, ja seuraava osanen on oleva sinun.","Vous avez arraché le cancer de votre corps, mais le cœur bat encore. Vous devez maintenant trouver le chirurgien qui massacre votre peuple, le Maître des traditions. Arrètez-le, et le fragment suivant sera le vôtre.","Kioperáltad a rákos sejteket a testedből, de a szíved még mindig ver. Most meg kell találnod azt a sebészt, aki lemészárolja és kontrollálja a néped. Ő nem más, mint a Tanmester. Állítsd meg, és a következő darabka a tied.","Hai eliminato il cancro dal tuo corpo, ma il tuo cuore batte ancora. Adesso devi trovare il chirurgo che macella e controlla la tua gente, il Sapiente. Fermalo e il prossimo pezzo sarà tuo.","心に動揺が見られるな、だがお主は己の体から +彼奴に立ち向かい、運命を切り開くのだ。",그대의 맹목적인 믿음이 조각들을 하나하나 찾으면서 그자의 목표를 이뤄주고 있다. 그를 상대하고 구속된 운명에서 벗어나라.,Jouw blinde geloof heeft hem in staat gesteld om met elk stuk dat je wint zijn doelen te bereiken. Confronteer hem en los je lot op.,Din blinde tro har gjort det mulig for ham å nå sine mål for hver brikke du vinner. Konfronter ham og avgjør din skjebne.,Twoja ślepa wiara pozwoliła mu na osiągnięcie celu z każdym zdobytym kawałkiem. Skonfrontuj się z nim i rozstrzygnij swój los.,Sua fé cega permitiu que ele avance em suas metas com cada peça que você adquire. Vá confrontá-lo e resolva o seu destino.,,"Credința ta oarbă i-a permis să-și avanseze planurile, cu fiecare piesă pe care o obții. Înfruntă-l și împlinește-ți destinul.","Твоя слепая вера приближала его к цели каждый раз, как ты находил фрагмент. Сразись с ним и исполни своё предназначение.",,Din blinda tro har gjort det möjligt för honom att avancera mot sina mål med varje bit du vinner. Konfrontera honom och lös ditt öde.,"Kör inancınız, kazandığınız her parçayla hedeflerine ilerlemesine izin verdi. Onunla yüzleş ve kaderini çöz." +"All right, it is Macil.",TXT_RPLY0_SCRIPT12_D6064_ALLRI,〃,,,"Tak dobře, je to Macil.","Okay, det er Macil.","Na gut, es ist Macil.",,Komprenite: nun Macil.,"Muy bien, sigue Macil.",,"Niin se on, se on Macil.",Très bien. C'est le tour de Macil.,"Igazad volt, Macil az.","Va bene, è Macil.",わかった、それがマシルか。,역시... 마실이였군.,"Oké, het is Macil.","Greit, det er Macil.","W porządku, to Macil.",Certo. Então é o Macil.,,"Bine, Macil să fie.",Понятно. Я убью Мэйсила.,,"Okej, det är Macil.","Pekala, bu Macil." +It's you I don't trust.,TXT_RPLY1_SCRIPT12_D6064_ITSYO,〃,,,Ale já nevěřím tobě.,"Det er dig, jeg ikke stoler på.","Du bist es, dem ich nicht vertraue.",,"Vi estas tiu, kiun mi ne fidas.",Eres tú de quien no me fío.,Eres tú en quien no confío.,Sinuun en minä luota.,C'est vous à qui je ne fais pas confiance.,"Te vagy az, akiben nem bízok.",Sei tu quello di cui non mi fido.,信用できん。,내가 믿지 않는 건 네놈이다.,Ik vertrouw jou niet.,Det er deg jeg ikke stoler på.,To tobie nie ufam.,É você em quem eu não confio.,,Tu ești cel în care nu am încredere.,"Я думаю, что это ты лжешь!",,Det är dig jag inte litar på.,Güvenmediğim sensin. +Whatever choice you make your kind shall perish under the will of the One God.,TXT_DLG_SCRIPT12_D7580_WHATE,〃,,,"Nehledě na tvé rozhodnutí, tvůj druh skoná vůlí Jednoho boha.","Uanset hvilket valg du træffer, vil din slags gå under under den ene Guds vilje.","Welche Wahl du auch triffst, deine Spezies wird unter dem Willen des Einen Gottes zugrunde gehen.",,"Tio ajn, kion vi elektos, via specio malaperos laŭ la volo de la Vera Dio.",Cualquiera que sea tu elección tu especie perecerá bajo la voluntad del Dios Único.,Cualquiera que sea tu elección tu especie va a perecer bajo la voluntad del Dios Único.,"Teitpä minkä hyvänsä päätöksen, lajisi pitää hukkuman Yhden Ainoan Jumalan tahdon alle.","Quel que soit le choix que vous faites, votre espèce périra par la volonté du Seul Dieu.","Mindegy mire döntesz, az egy igaz isten szigora lesúlyt rád és fajtádra.","Qualunque scelta tu faccia, la tua specie perirà per il volere dell'Unico Dio.","如何なる選択でも、人類は大いなる神の元で +浄化されるだろう。","그대가 어떤 선택을 하더라도, 그대를 비롯한 종족은 유일신의 의지에 의해 멸망할 뿐이다.","Welke keuze je ook maakt, jouw soort zal vergaan onder de wil van de Ene God.","Uansett hvilket valg du tar, vil din art gå til grunne under den ene Guds vilje.","Jakiegokolwiek wyboru dokonasz, twój rodzaj zginie z woli Jedynego Boga.","Seja qual for a escolha que você fizer, sua espécie irá perecer sob a vontade do Deus Único.",,"Indiferent de alegerea ta, neamul tău va pieri sub voința Adevăratului Zeu.","Что бы ты ни выбрал, твой род исчезнет по воле Единого Бога.",,Vilket val du än gör kommer din sort att förgås under den ende Gudens vilja.,"Yaptığın seçim ne olursa olsun, türün Tek Tanrı'nın iradesi altında yok olacak." +I'll be back when Macil's dead.,TXT_RPLY0_SCRIPT12_D7580_ILLBE,MAP12: Choose to kill Macil.,,,"Vrátím se, až bude Macil mrtev.","Jeg kommer tilbage, når Macil er død.","Ich komme wieder, wenn Macil tot ist.",,Mi revenos kiam Macil estos mortinta.,Volveré cuando Macil esté muerto.,Voy a volver cuando Macil esté muerto.,"Tulen takaisin, kun Macil on kuollut.",Je reviendrai quand Macil sera mort.,"Visszajövök, ha Macil már halott.",Tornerò quando Macil sarà morto.,マシルの死と共に戻る。,마실을 죽이고 돌아오겠다.,Ik kom terug als Macil dood is.,Jeg kommer tilbake når Macil er død.,"Wrócę, gdy Macil będzie martwy.",Voltarei quando Macil estiver morto.,,Am să mă întorc odată ce Macil e mort.,Я вернусь после смерти Мэйсила.,,Jag kommer tillbaka när Macil är död.,Macil öldüğünde geri döneceğim. +I can't let that happen.,TXT_RPLY1_SCRIPT12_D7580_ICANT,MAP12: Choose to not kill Macil.,,,To nemůžu dopustit.,Jeg kan ikke lade det ske.,Das darf nicht passieren.,,Mi ne povas permesi tion.,No puedo permitirlo.,,En voi antaa sen tapahtua.,Je ne peux pas vous laisser faire ça.,Nem hagyhatom ezt.,Non posso permetterlo.,そうはさせん。,그렇게 할 순 없어.,Dat kan ik niet laten gebeuren.,Jeg kan ikke la det skje.,Nie mogę na to pozwolić.,Não posso deixar isso acontecer.,,Nu voi permite asta.,Я не могу этого допустить.,,Jag kan inte låta det hända.,Bunun olmasına izin veremem. +"The river of time moves forever onward, while you stand still.",TXT_DLG_SCRIPT12_D9096_THERI,MAP12: You chose to kill Macil.,,,Řeka času plyne stále vpřed zatímco ty zůstáváš stát.,"Tidens flod bevæger sig for evigt fremad, mens du står stille.","Der Fluss der Zeit bewegt sich immer vorwärts, während du stillstehst.",,La tempofluo eterne iras antaŭen dum vi restas senmova.,La corriente del tiempo sigue adelante mientras tú sigues quieto.,,"Ajan virta liikkuu alati eteenpäin, samalla kun itse pysyt aloillasi.","La rivière du temps continue à couler, tandis que vous restez immobile.","Az idő folyója folyamat halad tovább, miközben te csak álldogállsz.","Il fiume del tempo scorre inesorabilmente, mentre tu rimani fermo.",事を措いても、時の河は永遠の先に進む。,"그대가 가만히 있어도, 시간의 강은 계속 흐를 뿐이다.","De rivier van de tijd beweegt voor altijd verder, terwijl je stilstaat.","Tidens elv beveger seg evig videre, mens du står stille.","Rzeka czasu płynie wiecznie do przodu, podczas gdy ty stoisz w miejscu.","O corrente do tempo se movimenta sempre adiante, enquanto você fica imóvel.",,"Râul timpului curge în permanență, în timp ce tu stai pe loc.","Река времени непрестанно течёт вперёд, в то время как ты стоишь без движения.",,"Tidens flod rör sig för evigt framåt, medan du står stilla.","Sen dururken, zaman nehri sonsuza dek ilerliyor." +"You have cut the cancer from your body, but your heart still beats. Next you must find the surgeon who butchers and controls your people, the Loremaster. Stop him, and the next piece will be yours.",TXT_DLG_SCRIPT12_D10612_YOUHA,MAP12: Oracle → After killing Macil,,,"Vyřízl jsi rakovinu ze svého těla, tvé srdce však stále bije. Dále musíš najít doktora, jenž vraždí a ovládá tvé druhy, Dějepisce. Učiň mu přítrž a další díl bude tvůj.","Du har skåret kræften ud af din krop, men dit hjerte slår stadig. Nu skal du finde den kirurg, der slagter og kontrollerer dit folk, Loremesteren. Stop ham, og det næste stykke vil være dit.","Du hast das Geschwür aus deinem Körper entferrnt, aber dein Herz schlägt noch. Als Nächstes musst du den Wissensmeister finden, der deine Leute kontrolliert und abschlachtet. Stoppe ihn und das nächste Teilstück ist Dein.",,"Vi saniĝis de via kancero, sed via koro ankoraŭ batas. Vi nun devas trovi la kirurgon, kiu buĉas kaj regas viajn homojn: la Folkloristo; haltigu lin kaj la sekva peco estos via.","Te has curado del cáncer, pero tu corazón aún late. Ahora toca encontrar al cirujano que destroza y controla a tu gente: al Maestro del Conocimiento; detenlo y la próxima pieza será tuya.",,"Olet erottanut syövän ruumiistasi, mutta sydämesi silti sykkii. Seuraavaksi pitää sinun löytämän kirugin, joka teurastaa ja hallitsee kansaasi: Oppi-Isän. Pysäytä hänet, ja seuraava osanen on oleva sinun.","Vous avez arraché le cancer de votre corps, mais le cœur bat encore. Vous devez maintenant trouver le chirurgien qui massacre votre peuple, le Maître des traditions. Arrètez-le, et le fragment suivant sera le vôtre.","Kioperáltad a rákos sejteket a testedből, de a szíved még mindig ver. Most meg kell találnod azt a sebészt, aki lemészárolja és kontrollálja a néped. Ő nem más, mint a Tanmester. Állítsd meg, és a következő darabka a tied.","Hai eliminato il cancro dal tuo corpo, ma il tuo cuore batte ancora. Adesso devi trovare il chirurgo che macella e controlla la tua gente, il Sapiente. Fermalo e il prossimo pezzo sarà tuo.","心に動揺が見られるな、だがお主は己の体から 癌を取り除いた。次の欠片は 人々を虐殺で支配するロアマスター外科医が -所持している。彼奴を止め、欠片を得るのだ。","그대 몸 안의 암 덩어리를 잘라냈건만, 심장은 여전히 뛰고 있구나. 다음은 네 종족의 도살과 지배를 책임졌던 로어마스터다. 그를 막아내면, 다음 조각은 너의 것이다.","Je hebt de kanker uit je lichaam gesneden, maar je hart klopt nog steeds. Vervolgens moet je de chirurg vinden die je volk afslacht en controleert, de Loremaster. Stop hem, en het volgende stuk zal van jou zijn.","Du har fjernet kreften fra kroppen din, men hjertet ditt slår fortsatt. Nå må du finne kirurgen som slakter og kontrollerer folket ditt, Loremesteren. Stopp ham, og det neste stykket blir ditt.","Wyciąłeś raka ze swojego ciała, ale twoje serce wciąż bije. Następnie musisz znaleźć chirurga, który rzeźbi i kontroluje twój lud, Loremastera. Powstrzymaj go, a następny kawałek będzie twój.","Você arrancou o câncer do seu corpo, mas seu coração ainda bate. Agora você deve encontrar o cirurgião que mutila e controla o seu povo, o Mestre do Conhecimento. Detenha-o e a próxima peça será sua.",,"Ai scăpat de cancerul din corp, dar inima ta încă bate. Mai departe, trebuie să îl găsești pe chirurgul care îți controlează și măcelărește oamenii, Stăpânul Învățăturilor. Oprește-l, și următoarea piesă va fi a ta.","Ты вырезал опухоль из своего тела, но твоё сердце всё ещё бьётся. Теперь тебе предстоит найти хирурга, который вскрывает твоих людей и управляет ими: Хранителя мудрости. Останови его, и следующий фрагмент твой.",,"Kanseri vücudunuzdan attınız ama kalbiniz hala atıyor. Şimdi halkını katleden ve kontrol eden cerrahı, Loremaster'ı bulmalısın. Onu durdurursan, bir sonraki parça senin olacak." -Where do I find him?,TXT_RPLY0_SCRIPT12_D10612_WHERE,,,,Kde ho najdu?,Hvor kan jeg finde ham?,Wo finde ich ihn?,,,¿Dónde lo encuentro?,,Mistä löydän hänet?,Où puis-je le trouver?,Hol találom meg?,Dove lo trovo.,そいつはどうやって見つける?,어디를 가야 그를 발견할 수 있지?,Waar vind ik hem?,Hvor finner jeg ham?,Gdzie go znajdę?,Onde encontro ele?,,Unde îl găsesc?,Где мне искать его?,,Onu nerede bulabilirim? -"Use the teleporter behind the door I just opened to reach the Loremaster. When he is dead, use the same device to return to me.",TXT_DLG_SCRIPT12_D12128_USETH,,,,"Dostaň se k Dějepisci pomocí teleportéru za dveřmi, které jsem právě otevřel. Když je mrtev, použij stejné zařízení k návratu ke mě.","Brug teleporteren bag den dør, jeg lige har åbnet, for at nå Loremesteren. Når han er død, skal du bruge den samme anordning til at vende tilbage til mig.","Benutze den Teleporter hinter der Tür, die ich gerade geöffnet habe. Wenn er tot ist, benutze dasselbe Gerät, um zu mir zurückzukehren.",,,"Usa el teleportador tras la puerta que he abierto para llegar hasta el Maestro del Conocimiento. Cuando esté muerto, usa el mismo dispositivo para volver a mí.",,"Käytä juuri avaamani oven takana olevaa kaukosiirrintä tavoittaaksesi Oppi-Isän. Kun hän on kuollut, käytä samaa laitetta palataksesi tyköni.","Utilisez le téléporteur derrière la porte que je viens d'ouvrir pour trouver le Maître des traditions. Quand il sera mort, utilisez ce même téléporteur pour revenir ici.","Használd a kinyílt ajtó mögötti portált a Tanmesterhez. Ha meghalt, használd a visszaútra is.","Usa il teletrasporto dietro la porta che ho appena sbloccato per raggiungere il Sapiente. Quando è morto, usa lo stesso teletrasporto per tornare da me.","我の傍にあるテレポーターの扉を開いた。 +所持している。彼奴を止め、欠片を得るのだ。","그대 몸 안의 암 덩어리를 잘라냈건만, 심장은 여전히 뛰고 있구나. 다음은 네 종족의 도살과 지배를 책임졌던 로어마스터다. 그를 막아내면, 다음 조각은 너의 것이다.","Je hebt de kanker uit je lichaam gesneden, maar je hart klopt nog steeds. Vervolgens moet je de chirurg vinden die je volk afslacht en controleert, de Loremaster. Stop hem, en het volgende stuk zal van jou zijn.","Du har fjernet kreften fra kroppen din, men hjertet ditt slår fortsatt. Nå må du finne kirurgen som slakter og kontrollerer folket ditt, Loremesteren. Stopp ham, og det neste stykket blir ditt.","Wyciąłeś raka ze swojego ciała, ale twoje serce wciąż bije. Następnie musisz znaleźć chirurga, który rzeźbi i kontroluje twój lud, Loremastera. Powstrzymaj go, a następny kawałek będzie twój.","Você arrancou o câncer do seu corpo, mas seu coração ainda bate. Agora você deve encontrar o cirurgião que mutila e controla o seu povo, o Mestre do Conhecimento. Detenha-o e a próxima peça será sua.",,"Ai scăpat de cancerul din corp, dar inima ta încă bate. Mai departe, trebuie să îl găsești pe chirurgul care îți controlează și măcelărește oamenii, Stăpânul Învățăturilor. Oprește-l, și următoarea piesă va fi a ta.","Ты вырезал опухоль из своего тела, но твоё сердце всё ещё бьётся. Теперь тебе предстоит найти хирурга, который вскрывает твоих людей и управляет ими: Хранителя мудрости. Останови его, и следующий фрагмент твой.",,"Du har skurit bort cancern från din kropp, men ditt hjärta slår fortfarande. Nu måste du hitta kirurgen som slaktar och kontrollerar ditt folk, Läromästaren. Stoppa honom och nästa bit kommer att bli din.","Kanseri vücudunuzdan attınız ama kalbiniz hala atıyor. Şimdi halkını katleden ve kontrol eden cerrahı, Loremaster'ı bulmalısın. Onu durdurursan, bir sonraki parça senin olacak." +Where do I find him?,TXT_RPLY0_SCRIPT12_D10612_WHERE,〃,,,Kde ho najdu?,Hvor kan jeg finde ham?,Wo finde ich ihn?,,Kie mi trovos lin?,¿Dónde lo encuentro?,,Mistä löydän hänet?,Où puis-je le trouver?,Hol találom meg?,Dove lo trovo?,そいつはどうやって見つける?,어디를 가야 그를 발견할 수 있지?,Waar vind ik hem?,Hvor finner jeg ham?,Gdzie go znajdę?,Onde encontro ele?,,Unde îl găsesc?,Где мне искать его?,,Var hittar jag honom?,Onu nerede bulabilirim? +"Use the teleporter behind the door I just opened to reach the Loremaster. When he is dead, use the same device to return to me.",TXT_DLG_SCRIPT12_D12128_USETH,〃,,,"Dostaň se k Dějepisci pomocí teleportéru za dveřmi, které jsem právě otevřel. Když je mrtev, použij stejné zařízení k návratu ke mě.","Brug teleporteren bag den dør, jeg lige har åbnet, for at nå Loremesteren. Når han er død, skal du bruge den samme anordning til at vende tilbage til mig.","Benutze den Teleporter hinter der Tür, die ich gerade geöffnet habe. Wenn er tot ist, benutze dasselbe Gerät, um zu mir zurückzukehren.",,"Uzu la teleportilon tra la ĵus malfermita pordo maldekstre de vi por atingi la Folkloriston. Mortiginte lin, reuzu tiun aparaton por reveni ĉi tien.","Usa el teletransportador de la puerta que acabo de abrir a tu izquierda para llegar hasta el Maestro del Conocimiento. Una vez muerto, usa el mismo dispositivo para volver a mí.",,"Käytä juuri avaamani oven takana olevaa kaukosiirrintä tavoittaaksesi Oppi-Isän. Kun hän on kuollut, käytä samaa laitetta palataksesi tyköni.","Utilisez le téléporteur derrière la porte que je viens d'ouvrir pour trouver le Maître des traditions. Quand il sera mort, utilisez ce même téléporteur pour revenir ici.","Használd a kinyílt ajtó mögötti portált a Tanmesterhez. Ha meghalt, használd a visszaútra is.","Usa il teletrasporto dietro la porta che ho appena sbloccato per raggiungere il Sapiente. Quando è morto, usa lo stesso teletrasporto per tornare da me.","我の傍にあるテレポーターの扉を開いた。 それがロアマスターの元に通ずる。 彼奴に死を伝えた後、再び扉を通るがよい。","내가 로어마스터로 향하는 순간이동 장치를 열어두었다. 그 자가 죽으면, 똑같은 장치를 써서 다시 나에게 오라. - \cy못생기긴 했어도, 이 양반 우리 편인 것 같네.","Gebruik de teleporter achter de deur die ik net heb geopend om de Loremaster te bereiken. Als hij dood is, gebruik je hetzelfde apparaat om terug te keren naar mij.","Bruk teleporteren bak døren jeg nettopp åpnet for å nå Loremaster. Når han er død, bruk samme apparat for å komme tilbake til meg.","Użyj teleportera za drzwiami, które właśnie otworzyłem, aby dotrzeć do Loremastera. Gdy będzie martwy, użyj tego samego urządzenia, by wrócić do mnie.","Use o teletransportador atrás da porta que eu acabei de abrir para chegar até o Mestre do Conhecimento. Quando ele morrer, use o mesmo dispositivo e retorne a mim.",,"Folosește teleportoul din spatele ușii pe care tocmai am deschis-o. După ce e mort, folosește același dispozitiv pentru a te întoarce la mine.","Используй телепорт за той дверью, что я только что открыл, чтобы добраться до Хранителя. Когда он умрёт, найди другой телепорт, чтобы вернуться ко мне.",,"Loremaster'a ulaşmak için az önce açtığım kapının arkasındaki ışınlayıcıyı kullan. O öldüğünde, bana dönmek için aynı cihazı kullan." -"I'll be back, with his piece!",TXT_RPLY0_SCRIPT12_D12128_ILLBE,,,,Vrátím se s jeho dílem!,Jeg kommer tilbage med hans brik!,"Ich komme wieder, mit dem Teilstück.",,,"Volveré, ¡con su pieza!",,Tulen takaisin hänen osasensa kanssa!,"Je reviendrai, avec son fragment!","Visszatérek, mégpedig a darabkájával!","Ritornerò, con il suo pezzo!",欠片を持ってすぐ戻る!,녀석의 조각을 가지고 다시 올게!,"Ik kom terug, met zijn stuk!","Jeg kommer tilbake, med hans del!",Wrócę z jego kawałkiem!,"Eu voltarei, com a peça dele!",,"Mă voi întoarce, cu piesa lui.",Я достану его фрагмент!,,Onun parçasıyla geri döneceğim! -"The river of time moves forever onward, while you stand still.",TXT_DLG_SCRIPT12_D13644_THERI,,,,Řeka času plyne stále vpřed zatímco ty zůstáváš stát.,"Tidens flod bevæger sig for evigt fremad, mens du står stille.","Der Fluss der Zeit bewegt sich immer vorwärts, während du stillstehst.",,,"La corriente del tiempo sigue adelante, mientras tú sigues quieto.",,"Ajan virta liikkuu alati eteenpäin, samalla kun itse pysyt aloillasi.","La rivière du temps continue à couler, tandis que vous restez immobile.","Az idő folyója folyamat halad tovább, miközben te csak álldogállsz.","Il fiume del tempo scorre inesorabilmente, mentre tu rimani fermo.",事を措いても、時の河は永遠の先に進む。,"발버둥을 친다해도, 시간의 강은 계속 흐를 뿐.","De rivier van de tijd beweegt voor altijd verder, terwijl je stilstaat.","Tidens elv beveger seg evig fremover, mens du står stille.","Rzeka czasu płynie wiecznie, podczas gdy ty stoisz w miejscu.","O corrente do tempo se movimenta sempre adiante, enquanto você fica imóvel.",,"Râul timpului curge în permanență, în timp ce tu stai pe loc.","Река времени непрестанно течёт вперёд, в то время как ты стоишь без движения.",,Zaman nehri sonsuza dek ilerlerken sen duruyorsun. -"Pitiful man, you have done what thousands have failed to do... You bring me the power of the Sigil, the voice of the One God.",TXT_DLG_SCRIPT12_D15160_PITIF,,,,"Ubohý člověče, dokázal jsi to, co tisíce před tebou ne... Přinášíš mi moc Pečetě, hlas Jednoho boha.","Ynkelige mand, du har gjort, hvad tusindvis af mennesker ikke har formået... Du bringer mig Sigilets kraft, den ene Guds stemme.","Armseliger Wurm, du hast getan woran Tausende gescheitert sind... Du brachtest mir die Macht des Sigils, die Stimme des Einen Gottes.",,,"Despreciable humano, has hecho lo que miles no han podido... Traes ante mí el poder del Emblema, la voz del Dios Único.",,"Kurja ihminen, olet tehnyt sen, missä tuhannet ovat epäonnistuneet: Olet tuonut minulle Sinetin voiman, Yhden Ainoan Jumalan äänen.","Pathétique mortel, vous avez réussi là où des milliers ont failli.. Vous m'amenez le pouvoir du Sigil, la voix du Seul Dieu.","Szánalmas kis pondró, megtetted amit emberek ezrei sem tudtak megtenni...elhoztad számomra a Pecsét erejét, az egy igaz isten hangját.","Patetico umano, sei riuscito a fare ciò che in migliaia hanno fallito nel compiere... Mi hai portato il potere del Sigillo, la voce dell'Unico Dio.","気の毒な者よ、お主は幾千の者達が + \cy못생기긴 했어도, 이 양반 우리 편인 것 같네.","Gebruik de teleporter achter de deur die ik net heb geopend om de Loremaster te bereiken. Als hij dood is, gebruik je hetzelfde apparaat om terug te keren naar mij.","Bruk teleporteren bak døren jeg nettopp åpnet for å nå Loremaster. Når han er død, bruk samme apparat for å komme tilbake til meg.","Użyj teleportera za drzwiami, które właśnie otworzyłem, aby dotrzeć do Loremastera. Gdy będzie martwy, użyj tego samego urządzenia, by wrócić do mnie.","Use o teletransportador atrás da porta que eu acabei de abrir para chegar até o Mestre do Conhecimento. Quando ele morrer, use o mesmo dispositivo e retorne a mim.",,"Folosește teleportoul din spatele ușii pe care tocmai am deschis-o. După ce e mort, folosește același dispozitiv pentru a te întoarce la mine.","Используй телепорт за той дверью, что я только что открыл, чтобы добраться до Хранителя. Когда он умрёт, найди другой телепорт, чтобы вернуться ко мне.",,Använd teleportern bakom dörren som jag just öppnade för att nå Läromästaren. När han är död använder du samma anordning för att återvända till mig.,"Loremaster'a ulaşmak için az önce açtığım kapının arkasındaki ışınlayıcıyı kullan. O öldüğünde, bana dönmek için aynı cihazı kullan." +"I'll be back, with his piece!",TXT_RPLY0_SCRIPT12_D12128_ILLBE,〃,,,Vrátím se s jeho dílem!,Jeg kommer tilbage med hans brik!,"Ich komme wieder, mit dem Teilstück.",,Mi revenos... kun lia peco!,Volveré... ¡con su pieza!,,Tulen takaisin hänen osasensa kanssa!,"Je reviendrai, avec son fragment!","Visszatérek, mégpedig a darabkájával!","Ritornerò, con il suo pezzo!",欠片を持ってすぐ戻る!,녀석의 조각을 가지고 다시 올게!,"Ik kom terug, met zijn stuk!","Jeg kommer tilbake, med hans del!",Wrócę z jego kawałkiem!,"Eu voltarei, com a peça dele!",,"Mă voi întoarce, cu piesa lui.",Я достану его фрагмент!,,Jag kommer tillbaka med hans pjäs!,Onun parçasıyla geri döneceğim! +"The river of time moves forever onward, while you stand still.",TXT_DLG_SCRIPT12_D13644_THERI,〃,,,Řeka času plyne stále vpřed zatímco ty zůstáváš stát.,"Tidens flod bevæger sig for evigt fremad, mens du står stille.","Der Fluss der Zeit bewegt sich immer vorwärts, während du stillstehst.",,La tempofluo eterne iras antaŭen dum vi restas senmova.,La corriente del tiempo sigue adelante mientras tú sigues quieto.,,"Ajan virta liikkuu alati eteenpäin, samalla kun itse pysyt aloillasi.","La rivière du temps continue à couler, tandis que vous restez immobile.","Az idő folyója folyamat halad tovább, miközben te csak álldogállsz.","Il fiume del tempo scorre inesorabilmente, mentre tu rimani fermo.",事を措いても、時の河は永遠の先に進む。,"발버둥을 친다해도, 시간의 강은 계속 흐를 뿐.","De rivier van de tijd beweegt voor altijd verder, terwijl je stilstaat.","Tidens elv beveger seg evig fremover, mens du står stille.","Rzeka czasu płynie wiecznie, podczas gdy ty stoisz w miejscu.","O corrente do tempo se movimenta sempre adiante, enquanto você fica imóvel.",,"Râul timpului curge în permanență, în timp ce tu stai pe loc.","Река времени непрестанно течёт вперёд, в то время как ты стоишь без движения.",,"Tidens flod rör sig för evigt framåt, medan du står stilla.",Zaman nehri sonsuza dek ilerlerken sen duruyorsun. +"Pitiful man, you have done what thousands have failed to do... You bring me the power of the Sigil, the voice of the One God.",TXT_DLG_SCRIPT12_D15160_PITIF,MAP12: Oracle → After killing the Loremaster with Macil dead.,,,"Ubohý člověče, dokázal jsi to, co tisíce před tebou ne... Přinášíš mi moc Pečetě, hlas Jednoho boha.","Ynkelige mand, du har gjort, hvad tusindvis af mennesker ikke har formået... Du bringer mig Sigilets kraft, den ene Guds stemme.","Armseliger Wurm, du hast getan woran Tausende gescheitert sind... Du brachtest mir die Macht des Sigils, die Stimme des Einen Gottes.",,"Malestiminda homo, vi faris tion, kion miloj ne povis: vi portas ĉe mi la povon de la Sigelo, la voĉo de la Vera Dio.","Despreciable humano, has hecho lo que miles no han podido: traes ante mí el poder del Emblema, la voz del Dios Único.","Despreciable humano, lograste lo que miles no han podido: traes ante mí el poder del Emblema, la voz del Dios Único.","Kurja ihminen, olet tehnyt sen, missä tuhannet ovat epäonnistuneet: Olet tuonut minulle Sinetin voiman, Yhden Ainoan Jumalan äänen.","Pathétique mortel, vous avez réussi là où des milliers ont failli.. Vous m'amenez le pouvoir du Sigil, la voix du Seul Dieu.","Szánalmas kis pondró, megtetted amit emberek ezrei sem tudtak megtenni...elhoztad számomra a Pecsét erejét, az egy igaz isten hangját.","Patetico umano, sei riuscito a fare ciò che in migliaia hanno fallito nel compiere... Mi hai portato il potere del Sigillo, la voce dell'Unico Dio.","気の毒な者よ、お主は幾千の者達が 遂げられなかった行いを果たした... -お主は我にシジルの力を、唯一神の声を届けた。","애처로운 자여, 지금껏 수천 명이 이루지 못했던 일을 해내었다... 나에게 시질의 힘을, 유일신의 목소리를 전해주는구나.","Jammer man, je hebt gedaan wat duizenden mensen niet hebben gedaan.... Je brengt me de kracht van de Sigil, de stem van de Ene God.","Stakkars mann, du har gjort det tusener har mislyktes med... Du gir meg sigillets kraft, stemmen til den ene guden.","Żałosny człowieku, dokonałeś tego, czego nie udało się zrobić tysiącom... Przynosisz mi moc Sigil, głos Jedynego Boga.","Que homem patético. Você fez o que milhares não conseguiram... Você me trouxe o poder do Sigilo, a voz do Deus Único.",,"Om jalnic, ai reușit ceea ce nu a reușit nimeni să facă.... Îmi aduci puterea Sigiliului, vocea Adevăratului Zeu.","Ничтожный человечишка, тебе удалось сделать то, с чем не справились тысячи... Ты принёс мне мощь Печати, глас Единого Бога.",,"Zavallı adam, binlerce kişinin yapamadığını yaptın. Bana Sigil'in gücünü, Tek Tanrı'nın sesini getirdin." -I don't understand.,TXT_RPLY0_SCRIPT12_D15160_IDONT,,,,Nerozumím ti.,Jeg forstår ikke.,Ich verstehe nicht.,,Mi ne komprenas.,No entiendo.,,En ymmärrä.,Je ne comprends pas.,Nem értem.,Non capisco.,わからないな。,무슨 소리야?,Ik begrijp het niet.,Jeg forstår ikke.,Nie rozumiem.,Eu não entendo.,,Nu înțeleg.,Я не понимаю.,,Anlamıyorum. -The Sigil will open the door and free the spirit which will cleanse this planet and let me live forever. I will strip this world of its energies and find new worlds to conquer.,TXT_DLG_SCRIPT12_D16676_THESI,,,,"Pečeť otevře brány a uvolní duši, která očistí tuto planetu a dovolí mi žít navěky. Vysaju tento svět jeho sil a najdu další světy k podmanutí.","Sigilet vil åbne døren og frigøre ånden, som vil rense denne planet og lade mig leve for evigt. Jeg vil fratage denne verden dens energier og finde nye verdener at erobre.","Das Sigil wird die Tür öffnen und den Geist befreien, den Planeten läutern und mich für immer leben lassen. Ich werde dieser Welt alle Energie entziehen und neue Welten finden, um sie zu erobern.",,,El Emblema abrirá la puerta y liberará el espíritu que limpiará éste planeta y me dejará vivir eternamente. Despojaré a este mundo de su energía y buscaré otros que conquistar.,,"Sinetti aukaisee portin ja vapauttaa hengen, joka puhdistaa tämän planeetan ja antaa minun elää ikuisesti. Riisun tämän maailman sen energioista ja etsin uusia maailmoja vallattavaksi.",Le Sigil ouvrira la porte et libérera l'âme qui purifiera cette planète et me donnera la vie éternelle. J'arracherai toutes les énergies de ce monde et en trouverai d'autres à conquérir.,"A pecsét kinyitja az ajtót a lélek előtt, ami megtisztítja ezt a bolygót és örök életet biztosít számomra. Megfosztom ezt a világot az energiáitól, és továbblépek más világokba ha végeztem vele.",Il Sigillo aprirà la porta e libererà lo spirito che purificherà questo pianeta e mi lascerà vivere per sempre. Spoglierò questo mondo delle sue energie e troverò nuovi mondi da conquistare.,"シジルは門を開き、この惑星の魂を浄化し +お主は我にシジルの力を、唯一神の声を届けた。","애처로운 자여, 지금껏 수천 명이 이루지 못했던 일을 해내었다... 나에게 시질의 힘을, 유일신의 목소리를 전해주는구나.","Jammer man, je hebt gedaan wat duizenden mensen niet hebben gedaan.... Je brengt me de kracht van de Sigil, de stem van de Ene God.","Stakkars mann, du har gjort det tusener har mislyktes med... Du gir meg sigillets kraft, stemmen til den ene guden.","Żałosny człowieku, dokonałeś tego, czego nie udało się zrobić tysiącom... Przynosisz mi moc Sigil, głos Jedynego Boga.","Que homem patético. Você fez o que milhares não conseguiram... Você me trouxe o poder do Sigilo, a voz do Deus Único.",,"Om jalnic, ai reușit ceea ce nu a reușit nimeni să facă.... Îmi aduci puterea Sigiliului, vocea Adevăratului Zeu.","Ничтожный человечишка, тебе удалось сделать то, с чем не справились тысячи... Ты принёс мне мощь Печати, глас Единого Бога.",,"Du har gjort vad tusentals har misslyckats med att göra... Du ger mig Sigillets kraft, den ende Gudens röst.","Zavallı adam, binlerce kişinin yapamadığını yaptın. Bana Sigil'in gücünü, Tek Tanrı'nın sesini getirdin." +I don't understand.,TXT_RPLY0_SCRIPT12_D15160_IDONT,〃,,,Nerozumím ti.,Jeg forstår ikke.,Ich verstehe nicht.,,Mi ne komprenas.,No entiendo.,,En ymmärrä.,Je ne comprends pas.,Nem értem.,Non capisco.,わからないな。,무슨 소리야?,Ik begrijp het niet.,Jeg forstår ikke.,Nie rozumiem.,Eu não entendo.,,Nu înțeleg.,Я не понимаю.,,Jag förstår inte.,Anlamıyorum. +The Sigil will open the door and free the spirit which will cleanse this planet and let me live forever. I will strip this world of its energies and find new worlds to conquer.,TXT_DLG_SCRIPT12_D16676_THESI,〃,,,"Pečeť otevře brány a uvolní duši, která očistí tuto planetu a dovolí mi žít navěky. Vysaju tento svět jeho sil a najdu další světy k podmanutí.","Sigilet vil åbne døren og frigøre ånden, som vil rense denne planet og lade mig leve for evigt. Jeg vil fratage denne verden dens energier og finde nye verdener at erobre.","Das Sigil wird die Tür öffnen und den Geist befreien, den Planeten läutern und mich für immer leben lassen. Ich werde dieser Welt alle Energie entziehen und neue Welten finden, um sie zu erobern.",,"La Sigelo malfermos la pordon kaj liberigos la spiriton, kiu elpurigos ĉi tiun planedon kaj ebligos al mi vivi eterne. Mi senigos ĉi tiun mondon je ĝia energio kaj mi trovos aliajn konkerotajn.",El Emblema abrirá la puerta y liberará al espíritu que limpiará este planeta y me dejará vivir eternamente. Despojaré este mundo de su energía y buscaré otros que conquistar.,El Emblema va a abrir la puerta y a liberar al espíritu que va a limpiar este planeta y a dejarme vivir eternamente. Voy a despojar este mundo de su energía y a buscar otros que conquistar.,"Sinetti aukaisee portin ja vapauttaa hengen, joka puhdistaa tämän planeetan ja antaa minun elää ikuisesti. Riisun tämän maailman sen energioista ja etsin uusia maailmoja vallattavaksi.",Le Sigil ouvrira la porte et libérera l'âme qui purifiera cette planète et me donnera la vie éternelle. J'arracherai toutes les énergies de ce monde et en trouverai d'autres à conquérir.,"A pecsét kinyitja az ajtót a lélek előtt, ami megtisztítja ezt a bolygót és örök életet biztosít számomra. Megfosztom ezt a világot az energiáitól, és továbblépek más világokba ha végeztem vele.",Il Sigillo aprirà la porta e libererà lo spirito che purificherà questo pianeta e mi lascerà vivere per sempre. Spoglierò questo mondo delle sue energie e troverò nuovi mondi da conquistare.,"シジルは門を開き、この惑星の魂を浄化し 我に永遠の命を授け給うのだ。我はこの世の 生命力を剥ぎ取り、新たなる星への征服に -駆り出すのだ。","시질은 잠겨저 있던 문을 열고, 이 세상을 정화할 혼령을 깨울 것이며, 나에게 영생을 선사할 것이다. 내가 이 세상의 기운을 모두 쓸어 담아 새로 정복할 세계를 찾아 나설 힘을 모을 것이다.",De Sigil zal de deur openen en de geest bevrijden die deze planeet zal reinigen en me voor altijd zal laten leven. Ik zal deze wereld van zijn energie ontdoen en nieuwe werelden vinden om te veroveren.,Sigllet vil åpne døren og frigjøre ånden som vil rense denne planeten og la meg leve evig. Jeg vil strippe denne verden for dens energier og finne nye verdener å erobre.,"Sigil otworzy drzwi i uwolni ducha, który oczyści tę planetę i pozwoli mi żyć wiecznie. Pozbawię ten świat jego energii i znajdę nowe światy do podbicia.",O Sigilo abrirá a porta e libertará o espirito que purificará este planeta e permitirá que eu viva para sempre. Arrancarei as energias deste mundo e encontrar novos mundos para conquistar.,,Sigiuliul va deschide ușa și elibera spiritul care va curăța planeta și mă va face nemuritor. Voi stoarce energia din planetă iar apoi voi găsi alte lumi de cucerit.,"Печать распахнёт дверь и высвободит сущность, что очистит эту планету и дарует мне вечную жизнь. Я выкраду всю энергию этого мира и отправлюсь на завоевание следующих.",,Sigil kapıyı açacak ve bu gezegeni temizleyecek ruhu serbest bırakacak ve sonsuza dek yaşamama izin verecek. Bu dünyayı enerjilerinden arındırıp fethedecek yeni dünyalar bulacağım. -I can't let you do that.,TXT_RPLY0_SCRIPT12_D16676_ICANT,,,,To ti nemůžu dovolit.,Det kan jeg ikke lade dig gøre.,Ich kann das nicht erlauben.,,,No puedo dejarte hacer eso.,,En voi antaa sinun tehdä sitä.,Je ne peux pas vous laisser faire ça.,Csak a holttestemen keresztül.,Non te lo posso permettere.,そんな真似はさせられないな。,네 놈의 음모를 막겠다!,Dat kan ik je niet laten doen.,Jeg kan ikke la deg gjøre det.,Nie mogę ci na to pozwolić.,Não vou deixar você fazer isso.,,Nu te pot lăsa să faci asta.,Я не могу этого допустить.,,Bunu yapmana izin veremem. -You can if you're dead.,TXT_DLG_SCRIPT12_D18192_YOUCA,,,,"Můžeš, když zemřeš.","Det kan du, hvis du er død.","Du kannst, wenn du tot bist.",,,"Puedes, si estás muerto.",,"Kyllä voit, jos olet kuollut.","Vous pouvez, une fois que vous êtes mort.",Ez megoldható.,Puoi... se sei morto!,お主の破滅は免れぬぞ。,네가 죽으면 될 것이다...,Dat kan je wel als je dood bent.,Du kan hvis du er død.,"Możesz, jeśli będziesz martwy.",Deixará se você estiver morto.,,"Poți, dacă ești mort.","Сможешь, когда умрёшь.",,Ölürsen izin verebilirsin. -"Are you here to free us? Because I've been good, they took my implant out. I still have to stay down here and wipe up the drool though.",TXT_DLG_SCRIPT14_D0_AREYO,,,,"Jsi tu, abys nás vysvobodil? Za dobré chování mi můj implantát vyndali. Stále tu ale musím zůstat a utírat sliny.","Er du her for at befri os? Fordi jeg har været god, tog de mit implantat ud. Jeg er dog stadig nødt til at blive hernede og tørre savlen op.","Bist du hier, um uns zu befreien? Ich war gut, sie haben mein Implasntat herasusgenommen. Ich muss aber hier bleiben und den Sabber aufwischen.",,,"¿Estás aquí para liberarnos? Porque he sido bueno, me han quitado el implante. Aunque aún tengo que quedarme aquí abajo y limpiar la saliva.",,"Oletko tullut vapauttamaan meidät? Koska olen käyttäytynyt kiltisti, he poistivat istutteeni. Minun kuitenkin on jäätävä tänne pyyhkimään kuolaa.","Vous êtes venus nous libérer? Je me suis bien comporté! Il m'on retiré mon implant, il faut que je reste ici et que j'essuie la bave, par contre.","Azért vagy itt, hogy felszabadíts minket? Jó voltam, és elvették az implantátumomat. Mégis itt kell rohadnom és takarítanom ezt a nyálkát.","Sei qui per liberarci? Dato che mi sono comportato bene, mi hanno tolto l'impianto. Però devo ancora restare quaggiù a pulire.","俺達を解放しに来たのか?あいつらに +駆り出すのだ。","시질은 잠겨저 있던 문을 열고, 이 세상을 정화할 혼령을 깨울 것이며, 나에게 영생을 선사할 것이다. 내가 이 세상의 기운을 모두 쓸어 담아 새로 정복할 세계를 찾아 나설 힘을 모을 것이다.",De Sigil zal de deur openen en de geest bevrijden die deze planeet zal reinigen en me voor altijd zal laten leven. Ik zal deze wereld van zijn energie ontdoen en nieuwe werelden vinden om te veroveren.,Sigllet vil åpne døren og frigjøre ånden som vil rense denne planeten og la meg leve evig. Jeg vil strippe denne verden for dens energier og finne nye verdener å erobre.,"Sigil otworzy drzwi i uwolni ducha, który oczyści tę planetę i pozwoli mi żyć wiecznie. Pozbawię ten świat jego energii i znajdę nowe światy do podbicia.",O Sigilo abrirá a porta e libertará o espirito que purificará este planeta e permitirá que eu viva para sempre. Arrancarei as energias deste mundo e encontrar novos mundos para conquistar.,,Sigiuliul va deschide ușa și elibera spiritul care va curăța planeta și mă va face nemuritor. Voi stoarce energia din planetă iar apoi voi găsi alte lumi de cucerit.,"Печать распахнёт дверь и высвободит сущность, что очистит эту планету и дарует мне вечную жизнь. Я выкраду всю энергию этого мира и отправлюсь на завоевание следующих.",,Sigillet kommer att öppna dörren och frigöra anden som kommer att rena den här planeten och låta mig leva för evigt. Jag kommer att beröva den här världen dess energier och hitta nya världar att erövra.,Sigil kapıyı açacak ve bu gezegeni temizleyecek ruhu serbest bırakacak ve sonsuza dek yaşamama izin verecek. Bu dünyayı enerjilerinden arındırıp fethedecek yeni dünyalar bulacağım. +I can't let you do that.,TXT_RPLY0_SCRIPT12_D16676_ICANT,〃,,,To ti nemůžu dovolit.,Det kan jeg ikke lade dig gøre.,Ich kann das nicht erlauben.,,"Mi ne povas lasi, ke vi faru tion.",No puedo dejarte hacer eso.,,En voi antaa sinun tehdä sitä.,Je ne peux pas vous laisser faire ça.,Csak a holttestemen keresztül.,Non te lo posso permettere.,そんな真似はさせられないな。,네 놈의 음모를 막겠다!,Dat kan ik je niet laten doen.,Jeg kan ikke la deg gjøre det.,Nie mogę ci na to pozwolić.,Não vou deixar você fazer isso.,,Nu te pot lăsa să faci asta.,Я не могу этого допустить.,,Jag kan inte låta dig göra det.,Bunu yapmana izin veremem. +You can if you're dead.,TXT_DLG_SCRIPT12_D18192_YOUCA,MAP12: Oracle → Fight with the Oracle.,,,"Můžeš, když zemřeš.","Det kan du, hvis du er død.","Du kannst, wenn du tot bist.",,Vi povas... se vi estas mortinta.,Puedes... si estás muerto.,,"Kyllä voit, jos olet kuollut.","Vous pouvez, une fois que vous êtes mort.",Ez megoldható.,Puoi... se sei morto!,お主の破滅は免れぬぞ。,네가 죽으면 될 것이다...,Dat kan je wel als je dood bent.,Du kan hvis du er død.,"Możesz, jeśli będziesz martwy.",Deixará se você estiver morto.,,"Poți, dacă ești mort.","Сможешь, когда умрёшь.",,Det kan du om du är död.,Ölürsen izin verebilirsin. +"Are you here to free us? Because I've been good, they took my implant out. I still have to stay down here and wipe up the drool though.",TXT_DLG_SCRIPT14_D0_AREYO,MAP14: James,,,"Jsi tu, abys nás vysvobodil? Za dobré chování mi můj implantát vyndali. Stále tu ale musím zůstat a utírat sliny.","Er du her for at befri os? Fordi jeg har været god, tog de mit implantat ud. Jeg er dog stadig nødt til at blive hernede og tørre savlen op.","Bist du hier, um uns zu befreien? Ich war gut, sie haben mein Implasntat herasusgenommen. Ich muss aber hier bleiben und den Sabber aufwischen.",,"Ĉu vi venis liberigi nin? Ili forprenis la enplantaĵon de mi ĉar mi estis obeema. Malgraŭ tio, mi devas resti ĉi-malsupre purigi.","¿Has venido a liberarnos? Como he sido bueno, me quitaron el implante, pero aun así tengo que quedarme aquí abajo a limpiar.","¿Viniste a liberarnos? Como he sido bueno, me quitaron el implante, pero aun así tengo que quedarme aquí abajo a limpiar.","Oletko tullut vapauttamaan meidät? Koska olen käyttäytynyt kiltisti, he poistivat istutteeni. Minun kuitenkin on jäätävä tänne pyyhkimään kuolaa.","Vous êtes venus nous libérer? Je me suis bien comporté! Il m'on retiré mon implant, il faut que je reste ici et que j'essuie la bave, par contre.","Azért vagy itt, hogy felszabadíts minket? Jó voltam, és elvették az implantátumomat. Mégis itt kell rohadnom és takarítanom ezt a nyálkát.","Sei qui per liberarci? Dato che mi sono comportato bene, mi hanno tolto l'impianto. Però devo ancora restare quaggiù a pulire.","俺達を解放しに来たのか?あいつらに インプラントを外されたが、俺は大丈夫だ。 -まだ少し留まって涎を拭き取らないとならない。","저희를 구출하기 위해서 찾아오셨나요? 그들이 제가 성실하게 일을 한 사례로 세뇌 장치를 때어갔어요. 그런데... 아직도 위험한 것 같은데, 좀 흘린 침 자국을 좀 닦아야 할 것 같아요.","Ben je hier om ons te bevrijden? Omdat ik goed ben geweest, hebben ze mijn implantaat eruit gehaald. Ik moet nog steeds hier beneden blijven en de kwijl echter wegvegen.",Er du her for å befri oss? Fordi jeg har vært snill. De fjernet implantatet mitt. Men jeg må fortsatt bli her nede og tørke opp siklet.,"Jesteś tu, by nas uwolnić? Ponieważ byłem dobry, wyjęli mi implant. Ale nadal muszę tu zostać i wytrzeć ślinę.","Você está aqui para nos libertar? Por eu ter me comportado bem, eles tiraram o meu implante. Mas ainda tenho que ficar aqui para limpar a saliva.",,"Ai venit ca să ne eliberezi? Pentru că am fost cuminte, mi-au scos implantul. Dar tot trebuie să rămân aici și să fac curățenie însă.","Ты пришёл спасти нас? Я был послушным, так что они вынули мой имплант. И всё равно я вынужден оставаться тут, внизу, и подтирать слюни.",,Bizi özgür bırakmak için mi buradasın? İyi olduğum için implantımı çıkardılar. Yine de burada kalıp salyamı silmem gerekiyor. -"Yes, I'm here to free you.",TXT_RPLY0_SCRIPT14_D0_YESIM,,,,"Ano, jsem tu, abych vás osvobodil.","Ja, jeg er her for at befri jer.","Ja, ich werde eiuch befreien.",,,"Sí, estoy aquí para liberarte.",,"Kyllä, tulin vapauttamaan teidät.","Oui, je viens vous libérer.","Igen, azért jöttem hogy kiszabadítsalak.","Sì, sono qui per liberarvi.",そうだ、助けに来た。,"그래, 난 널 구하러 왔어.","Ja, ik ben hier om je te bevrijden.","Ja, jeg er her for å befri dere.","Tak, jestem tu, żeby was uwolnić.","Sim, estou aqui para libertar vocês.",,"Da, am venit să te eliberez.","Да, я здесь, чтобы спасти вас.",,"Evet, sizi kurtarmak için buradayım." -You mean it?,TXT_RYES0_SCRIPT14_D0_YOUME,,,,To myslíš doopravdy?,Mener du det?,Wirklich?,,,¿En serio?,,Todellako?,Vraiment?,Tényleg?,Veramente?,そういう意味か?,정말인가요?,Je meent het?,Mener du det?,Mówisz poważnie?,Sério mesmo?,,Pe bune?,Правда?,,Ciddi misin? -I can't help nobody else. Not until you blow up the transmitter. That's what's behind the forcefield upstairs. My job is to check on the conveyors to make sure they aren't jammed. Not anymore!,TXT_DLG_SCRIPT14_D1516_ICANT,,,,"Nemůžu nikomu jinému pomoct, ne dokud neodpálíš vysílačku, to je ta věc nahoře za silovým polem. Já mám za úkol kontrolovat pásy a dávat pozor, aby se nezasekly. Teď už ani náhodou!","Jeg kan ikke hjælpe nogen andre. Ikke før du sprænger senderen i luften. Det er det, der er bag kraftfeltet ovenpå. Mit job er at tjekke transportbåndene for at sikre mig, at de ikke er blokeret. Ikke længere!","Ich kann niemandem helfen. Nich bevor jemand den Transmitter hochjagt. Er ist hinter dem Kraftfeld da oben. Meine Aufgabe ist es, die Förderbänder zu prüfen um sicherzustellen, dass sie nicht blockieren. Jetzt nicht mehr!",,,No puedo ayudar a nadie más. No hasta que destruyas el transmisor. Eso es lo que está tras el campo de fuerza escaleras arriba. Mi trabajo es comprobar los transportadores para asegurarme de que no esten atascados. ¡Nunca más!,No puedo ayudar a nadie más. No hasta que destruyas el transmisor. Eso es lo que está detrás del campo de fuerza escaleras arriba. Mi trabajo es comprobar los transportadores para asegurarme de que no esten atascados. ¡Ya no más!,"En voi auttaa ketään muuta. En, ennen kuin räjäytät lähettimen. Se se on, joka sijaitsee yläkerran voimakentän takana. Työni on pitää silmällä ja varmistaa, etteivät liukuhihnat jumiudu, enää!","Je ne peux pas aider qui que ce soit d'autre, du moins pas avant que vous détruisez le transmetteur. C'est la chose derrière le champ de force à l'étage. Mon travail est de faire en sorte que les tapis roulants ne se coincent pas, mais plus maintenant!","Nem tudok már másnak segíteni. Legalábbis nem amíg nem robbantod fel az adóállomást. Ez áll az erőpajzs mögött. Az Én feladatom, hogy ellenőrizzem a futószalagot nem akadt e be. Többé aztán nem!",Non posso aiutare nessun'altro. Non finché non fai saltare in aria il trasmettitore. È questo che c'è dietro il campo di forza di sopra. Il mio compito è asicurarmi che i nastri trasportatori non si intoppino. Non più!,"まだ俺は手伝うことが出来ない。 +まだ少し留まって涎を拭き取らないとならない。","저희를 구출하기 위해서 찾아오셨나요? 그들이 제가 성실하게 일을 한 사례로 세뇌 장치를 때어갔어요. 그런데... 아직도 위험한 것 같은데, 좀 흘린 침 자국을 좀 닦아야 할 것 같아요.","Ben je hier om ons te bevrijden? Omdat ik goed ben geweest, hebben ze mijn implantaat eruit gehaald. Ik moet nog steeds hier beneden blijven en de kwijl echter wegvegen.",Er du her for å befri oss? Fordi jeg har vært snill. De fjernet implantatet mitt. Men jeg må fortsatt bli her nede og tørke opp siklet.,"Jesteś tu, by nas uwolnić? Ponieważ byłem dobry, wyjęli mi implant. Ale nadal muszę tu zostać i wytrzeć ślinę.","Você está aqui para nos libertar? Por eu ter me comportado bem, eles tiraram o meu implante. Mas ainda tenho que ficar aqui para limpar a saliva.",,"Ai venit ca să ne eliberezi? Pentru că am fost cuminte, mi-au scos implantul. Dar tot trebuie să rămân aici și să fac curățenie însă.","Ты пришёл спасти нас? Я был послушным, так что они вынули мой имплант. И всё равно я вынужден оставаться тут, внизу, и подтирать слюни.",,Är du här för att befria oss? För att jag har varit snäll tog de bort mitt implantat. Jag måste ändå stanna här nere och torka upp dreglet.,Bizi özgür bırakmak için mi buradasın? İyi olduğum için implantımı çıkardılar. Yine de burada kalıp salyamı silmem gerekiyor. +"Yes, I'm here to free you.",TXT_RPLY0_SCRIPT14_D0_YESIM,〃,,,"Ano, jsem tu, abych vás osvobodil.","Ja, jeg er her for at befri jer.","Ja, ich werde eiuch befreien.",,"Jes, mi venis liberigi vin.","Sí, he venido a liberaros.","Sí, vine a liberarlos.","Kyllä, tulin vapauttamaan teidät.","Oui, je viens vous libérer.","Igen, azért jöttem hogy kiszabadítsalak.","Sì, sono qui per liberarvi.",そうだ、助けに来た。,"그래, 난 널 구하러 왔어.","Ja, ik ben hier om je te bevrijden.","Ja, jeg er her for å befri dere.","Tak, jestem tu, żeby was uwolnić.","Sim, estou aqui para libertar vocês.",,"Da, am venit să te eliberez.","Да, я здесь, чтобы спасти вас.",,"Ja, jag är här för att befria er.","Evet, sizi kurtarmak için buradayım." +You mean it?,TXT_RYES0_SCRIPT14_D0_YOUME,〃,,,To myslíš doopravdy?,Mener du det?,Wirklich?,,Ĉu vere?,¿En serio?,,Todellako?,Vraiment?,Tényleg?,Veramente?,そういう意味か?,정말인가요?,Je meent het?,Mener du det?,Mówisz poważnie?,Sério mesmo?,,Pe bune?,Правда?,,Menar du det?,Ciddi misin? +I can't help nobody else. Not until you blow up the transmitter. That's what's behind the forcefield upstairs. My job is to check on the conveyors to make sure they aren't jammed. Not anymore!,TXT_DLG_SCRIPT14_D1516_ICANT,"〃 +(conveyors = conveyor belts)",,,"Nemůžu nikomu jinému pomoct, ne dokud neodpálíš vysílačku, to je ta věc nahoře za silovým polem. Já mám za úkol kontrolovat pásy a dávat pozor, aby se nezasekly. Teď už ani náhodou!","Jeg kan ikke hjælpe nogen andre. Ikke før du sprænger senderen i luften. Det er det, der er bag kraftfeltet ovenpå. Mit job er at tjekke transportbåndene for at sikre mig, at de ikke er blokeret. Ikke længere!","Ich kann niemandem helfen. Nich bevor jemand den Transmitter hochjagt. Er ist hinter dem Kraftfeld da oben. Meine Aufgabe ist es, die Förderbänder zu prüfen um sicherzustellen, dass sie nicht blockieren. Jetzt nicht mehr!",,"Mi povas helpi neniun alian, ne dum la transmisiilo ne estos detruita; ĝi estas post la supretaĝa fortokampo. Mia laboro estas kontroli la transportajn bendojn por certiĝi, ke ili ne blokiĝis. Ne plu!","No puedo ayudar a nadie más, no hasta que destruyas el transmisor; eso es lo que está tras el campo de fuerza del piso de arriba. Mi trabajo es revisar las cintas transportadoras para asegurarme de que no estén atoradas. ¡Ya no más!",,"En voi auttaa ketään muuta. En, ennen kuin räjäytät lähettimen. Se se on, joka sijaitsee yläkerran voimakentän takana. Työni on pitää silmällä ja varmistaa, etteivät liukuhihnat jumiudu, enää!","Je ne peux pas aider qui que ce soit d'autre, du moins pas avant que vous détruisez le transmetteur. C'est la chose derrière le champ de force à l'étage. Mon travail est de faire en sorte que les tapis roulants ne se coincent pas, mais plus maintenant!","Nem tudok már másnak segíteni. Legalábbis nem amíg nem robbantod fel az adóállomást. Ez áll az erőpajzs mögött. Az Én feladatom, hogy ellenőrizzem a futószalagot nem akadt e be. Többé aztán nem!",Non posso aiutare nessun'altro. Non finché non fai saltare in aria il trasmettitore. È questo che c'è dietro il campo di forza di sopra. Il mio compito è asicurarmi che i nastri trasportatori non si intoppino. Non più!,"まだ俺は手伝うことが出来ない。 トランスミッターを壊さなければバレてしまう。 そいつは上の階のフォースフィールドを越えた所 にいる。コンベアーの詰まりをチェックする -だけの仕事だったが、もう辞任だな!",전송기를 파괴하기 전까지는 세뇌된 사람들을 도와줄 수가 없어요. 저 위층에 방어막에 보호받고 있는 채로 있습니다. 제 원래 업무는 광석이 끼지 않게 운반 벨트를 확인하는 거였어요... 이젠 일할 필요도 없지만!,Ik kan niemand anders helpen. Niet voordat je de zender hebt opgeblazen. Dat is wat er achter het krachtveld boven is. Het is mijn taak om de transportbanden te controleren om er zeker van te zijn dat ze niet vastzitten. Nu niet meer!,Jeg kan ikke hjelpe noen andre. Ikke før du sprenger senderen. Det er det som er bak kraftfeltet der oppe. Jobben min er å sjekke at transportbåndene ikke er blokkert. Ikke nå lenger!,"Nie mogę pomóc nikomu innemu. Nie, dopóki nie wysadzisz nadajnika. To jest to, co jest za polem siłowym na górze. Moim zadaniem jest sprawdzanie, czy przenośniki nie są zablokowane. Już nie!",Não posso ajudar mais ninguém. Não até que você detone o transmissor. É isso que mantém o campo de força lá em cima. Meu trabalho é conferir as esteiras para que não fiquem emperradas. Nunca mais!,,"Nu pot ajuta pe nimeni. Nu până ce transmițătorul nu e aruncat în aer. Asta e la etaj, în spatele scuturilor. Treaba mea e să mă uit după conveioare, să mă asigur că nu sunt defecte. Numai!","Я не могу помочь другим, пока ты не взорвёшь передатчик. Он находится за силовым полем наверху. Моя работа — проверять, не заклинило ли конвейеры. Теперь уже нет!",,"Başka kimseye yardım edemem. Vericiyi patlatana kadar olmaz. Üst kattaki güç alanının arkasında bu var. Benim işim, sıkışmadıklarından emin olmak için konveyörleri kontrol etmek. Artık değil!" -"That's right, you're saved!",TXT_RPLY0_SCRIPT14_D1516_THATS,,,,"Ano, jsi zachráněn!","Det er rigtigt, du er reddet!","Das ist richtig, du bist in Sicherheit!",,,"Correcto, ¡estás salvado!",,"Näin on, olet pelastettu!","C'est ça, vous êtes sauvé!","Így van, meg van mentve.","Esatto, sei salvo!",そうだ、救われたぞ!,당연하지. 너는 자유야!,"Dat klopt, je bent gered!","Det stemmer, du er reddet!","Tak jest, jesteś uratowany!",Isso mesmo. Vocês estão salvos!,,"Așa e, ești salvat!","Да, это так! Вы спасены!",,"Bu doğru, kurtuldun!" -"Oh, thank you!",TXT_RYES0_SCRIPT14_D1516_OHTHA,,,,"Oh, děkuju!","Åh, tak!","Oh, danke sehr!",,"Ho, dankon.","Oh, ¡gracias!",,"Voi, kiitos!","Oh, merci!","Oh, köszönöm!","Oh, grazie!",おう、ありがとよ!,"오, 고마워요!","Oh, dank je wel!",Takk skal du ha!,"Och, dziękuję!","Ah, muito obrigado!",,"Oh, mulțumesc!",Ура! Спасибо тебе!,,"Oh, teşekkürler!" -We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D3032_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,Vi er fri!! Vi er fri!! Vi er fri!!!,Wir sind frei! Wir sind frei! Wir sind frei!,,,¡¡Somos libres!! ¡¡Somos libres!! ¡¡Somos libres!!,,Olemme vapaat!! Olemme vapaat!! Olemme vapaat!!,On est libres! Libres! Libres!,Szabadok vagyunk!! Szabadok vagyunk!! Szabadok vagyunk!!,Siamo liberi!! Siamo liberi!! Siamo liberi!!,自由だ!!俺達は自由だ!!俺達は自由だ!!,우린 자유야! 우린 자유라고!,We zijn vrij!! We zijn vrij!! We zijn vrij!!,Vi er fri! Vi er fri!! Vi er fri!!,Jesteśmy wolni!!! Jesteśmy wolni!!! Jesteśmy wolni!!!,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!,,Özgürüz! Özgürüz! Özgürüz! -Must mine more ore!,TXT_DLG_SCRIPT14_D4548_MUSTM,,,,Muset těžit další rudu!,Vi må udvinde mere malm!,Muss Erz abbauen.,,,¡Debo picar más mineral!,,Täytyy louhia lisää malmia!,Faut que je trouve plus de minerai!,Még több ércet kell bányászni!,Devo estrarre più minerale!,もっと掘らねえといけねえんだ!,광석을... 캐내야 해...,Moet erts meer of meer ontginnen!,Må utvinne mer malm!,Musimy wydobyć więcej rudy!,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!,,Daha fazla maden çıkarmalıyız! -We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D6064_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,Vi er frie!! Vi er frie!!! Vi er frie!!,Wir sind frei! Wir sind frei! Wir sind frei!,,,¡¡Somos libres!! ¡¡Somos libres!! ¡¡Somos libres!!,,Olemme vapaat!! Olemme vapaat!! Olemme vapaat!!,On est libres! Libres! Libres!,Szabadok vagyunk!! Szabadok vagyunk!! Szabadok vagyunk!!,Siamo liberi!! Siamo liberi!! Siamo liberi!!,自由だ!!オレらは自由だ!!オレらは自由だ!!,프론트가 해냈다! 자유를 거의 되찾았어!,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,Vi er fri!! Vi er frie!! Vi er fri!!,Jesteśmy wolni! Jesteśmy wolni!!! Jesteśmy wolni!!!,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!,,Özgürüz! Özgürüz! Özgürüz! -Must mine more ore!,TXT_DLG_SCRIPT14_D7580_MUSTM,,,,Muset těžit další rudu!,Skal udvinde mere malm!,Muss Erz abbauen.,,,¡Debo picar más mineral!,,Täytyy louhia lisää malmia!,Faut que je trouve plus de minerai!,Még több ércet kell bányászni!,Devo estrarre più minerale!,鉱石がもっと必要なんだ!,광석... 데그닌... 캔다...,Moet meer erts ontginnen!,Må utvinne mer malm!,Musimy wydobyć więcej rudy!,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!,,Daha fazla maden çıkarmalıyız! -We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D9096_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,Vi er frie!!! Vi er frie!!! Vi er frie!!,Wir sind frei! Wir sind frei! Wir sind frei!,,,¡¡Somos libres!! ¡¡Somos libres!! ¡¡Somos libres!!,,Olemme vapaat!! Olemme vapaat!! Olemme vapaat!!,On est libres! Libres! Libres!,Szabadok vagyunk!! Szabadok vagyunk!! Szabadok vagyunk!!,Siamo liberi!! Siamo liberi!! Siamo liberi!!,自由だ!!私達は自由だ!!私達は自由だ!!,살았군요. 이제 저항군 기지로 향하는 일 밖엔 남지 않은 것 같아요.,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,Vi er fri!! Vi er frie!! Vi er fri!!,Jesteśmy wolni!!! Jesteśmy wolni!!! Jesteśmy wolni!!!,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!,,Özgürüz! Özgürüz! Özgürüz! -Must mine more ore!,TXT_DLG_SCRIPT14_D10612_MUSTM,,,,Muset těžit další rudu!,Skal udvinde mere malm!,Muss Erz abbauen.,,,¡Debo picar más mineral!,,Täytyy louhia lisää malmia!,Faut que je trouve plus de minerai!,Még több ércet kell bányászni!,Devo estrarre più minerale!,いつまで採掘しなければならない!,캐고... 캐고... 또 캔다...,Moet meer erts ontginnen!,Må utvinne mer malm!,Musimy wydobyć więcej rudy!,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!,,Daha fazla maden çıkarmalıyız! -We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D12128_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,Vi er frie!!! Vi er frie!!! Vi er frie!!,Wir sind frei! Wir sind frei! Wir sind frei!,,,¡¡Somos libres!! ¡¡Somos libres!! ¡¡Somos libres!!,,Olemme vapaat!! Olemme vapaat!! Olemme vapaat!!,On est libres! Libres! Libres!,Szabadok vagyunk!! Szabadok vagyunk!! Szabadok vagyunk!!,Siamo liberi!! Siamo liberi!! Siamo liberi!!,僕らは自由だ!!僕らは自由だ!!僕らは自由だ!!,살았다! 이제 그 놈들이 죽이기 전에 도망쳐야해요!,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,Vi er fri!! Vi er frie!! Vi er frie!!,Jesteśmy wolni!!! Jesteśmy wolni!!! Jesteśmy wolni!!!,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!,,Özgürüz! Özgürüz! Özgürüz! -What are you doing here?,TXT_DLG_SCRIPT15_D0_WHATA,MAP15: Red acolytes.,,,Co tady děláte?,Hvad laver du her?,Was machst du hier?,,,¿Qué haces aquí?,,Mitä teette täällä?,Qu'est ce que vous faites ici?,Mit csinálsz itt?,Che cosa fai qui?,ここで何をしている?,여기서 뭘 하는거지?,Wat doe je hier?,Hva gjør dere her?,Co ty tu robisz?,O que você está fazendo aqui?,,Ce cauți aici?,По какому делу ты здесь?,,Ne yapıyorsunuz burada? -Routine inspection.,TXT_RPLY0_SCRIPT15_D0_ROUTI,〃,,,Rutinní kontrola.,Rutinemæssig inspektion.,Eine Routineinspektion.,,,Inspección rutinaria.,,Rutiinitarkastus.,Inspection de routine.,Rutin ellenőrzés.,Ispezione ordinaria.,見回りだ。,정기적 검사요.,Routine-inspectie.,Rutinemessig inspeksjon.,Rutynowa inspekcja.,Inspeção de rotina.,,Inspecție de rutină.,Плановая проверка.,,Rutin teftiş. -"All right, carry on.",TXT_RYES0_SCRIPT15_D0_ALLRI,〃,,,"Dobře, pokračujte.","Okay, fortsæt.","In Ordnung, mach weiter.",,,"Muy bien, continúa.",,"Selvä on, jatkakaa.","D'accord, continuez.","Renben, folytasd csak.","Va bene, vai pure avanti.",わかった、続けろ。,"좋아, 계속해.","Oké, ga door.","Greit, fortsett.","W porządku, kontynuuj.","Muito bem, continue.",,"Bine, mergi mai departe.",Понятно. Продолжай.,,"Pekala, devam edin." -"Nothing to report here. Everything is working fine. If anything goes wrong, I'll be sure to report it.",TXT_DLG_SCRIPT15_D1516_NOTHI,MAP15: Red acolytes + Technician at the beginning.,,,"Tady nic k nahlášení není. Všechno funguje dobře. Pokud se něco pokazí, nahlásím to.","Der er intet at rapportere her. Alt fungerer fint. Hvis noget går galt, skal jeg nok rapportere det.","Keine besonderen Vorkommnisse. Alles funktioniert wie es soll. Wenn irgendetwas schief geht, werde ich es sofort melden.",,,"Nada que reportar aquí. Todo está funcionando bien. Si cualquier cosa sale mal, me aseguraré de reportarlo.",,"Ei mitään raportoitavaa. Kaikki toimii hyvin. Jo mikään menee vialle, raportoin siitä varmasti.","Rien à signaler ici. Tout fonctionne comme prévu. Si quelque chose tombe en panne, je ferai un rapport.","Nincs semmi bejelentenivaló. Minden prímán működik. Ha esetleg valami meghibásodik, rögtön jelezni fogom.","Nulla da riportare qua. Tutto funziona come dovrebbe. Se qualcosa non dovesse funzionare, lo riporterò subito.","報告することはない。全て順調だ。 -何か問題が起きたら報告する。","보고할 게 전혀 없어. 모든 장치, 시설, 인력 모두 이상 무. 만약 하나라도 문제가 생기면 나에게 알려줘.","Hier valt niets te melden. Alles werkt prima. Als er iets misgaat, zal ik het zeker melden.","Ingenting å rapportere her. Alt fungerer som det skal. Hvis noe går galt, skal jeg rapportere det.","Nie ma o czym mówić. Wszystko działa jak należy. Jeśli coś będzie nie tak, na pewno to zgłoszę.","Não há nada de errado aqui. Tudo está funcionando perfeitamente. Se algo parar de funcionar, pode ter certeza que eu vou avisar.",,"Nimic de raportat aici. Dacă e ceva, cu siguranță că voi da raportul.","Тут не о чём докладывать. Всё работает превосходно. Если что-нибудь пойдёт не так, я обязательно доложу об этом.",,"Burada rapor edilecek bir şey yok. Her şey yolunda gidiyor. Eğer bir sorun çıkarsa, rapor edeceğimden emin olabilirsiniz." -"Sir, there was a problem earlier, but it was taken care of.",TXT_DLG_SCRIPT15_D3032_SIRTH,MAP15: Technician at the beginning.,,,"Pane, předtím tu byl problém, ale vyřešili jsme jej.","Sir, der var et problem tidligere, men det blev ordnet.","Vor kurzem gab es ein Problem, aber das wurde bereits gelöst.",,,"Señor, hubo un problema antes, pero ha sido solucionado.",,"Tässä aiemmin oli ongelma, mutta se ratkaistiin.","Monsieur, il y a eu un problème récemment mais nous l'avons corrigé.","Uram, volt korábban egy probléma, de megoldásra került.","Signore, c'era un problema prima, ma è stato risolto.","上官殿、以前より問題があったが、 -もう心配はいらない。",안녕하십니까. 조금 전에 문제가 있었습니다만 경마한 문제였고 지금 해결됐습니다.,"Meneer, er was eerder een probleem, maar het is opgelost.","Sir, det var et problem tidligere, men det ble tatt hånd om.","Sir, wcześniej był problem, ale już się nim zajęto.","Senhor, havia um problema antes, mas já foi resolvido.",,"Domnule, a fost o problemă adineauri, dar s-a rezolvat.","Сэр, тут была одна неполадка, но её уже устранили.",,"Efendim, daha önce bir sorun vardı, ama halledildi." -Move along or taste metal.,TXT_DLG_SCRIPT17_D0_MOVEA,MAP17: Bailey (if you don't have Order's key),,,"Jdi dál, nebo okus ocel.",Fortsæt eller smag på metal.,Beweg dich oder spüre meinen Stahl.,,,Sigue caminando o prueba metal.,,"Jatka matkaasi, tai maista metallia.",Bougez ou préparez-vous à goûter de l'acier.,"Haladj tovább, vagy ízleld meg a kardom.",Sparisci o ti finisce male.,同行か鉄を味わうかだ。,탄창으로 맞고 싶지 않으면 움직여.,Ga verder of proef metaal.,Gå videre eller smak på metall.,Ruszaj się albo skosztuj metalu.,Vá embora ou vai tomar chumbo grosso.,,Mișcă-te sau mănânci metal.,"Прочь, или отведаешь металла.",,İlerleyin ya da metalin tadına bakın. -I.D. check.,TXT_DLG_SCRIPT17_D1516_IDCHE,〃 (if you have it),,,Doklady.,ID-tjek.,Ausweisüberprüfung.,,,Comprobación de identificación.,,Henkilöllisyystarkastus.,Vérification de carte d'identité.,Igazolvány ellenőrzés.,Verifica d'identità.,I.D.チェックだ。,신분증 확인.,I.D. check.,Legitimasjonskontroll.,Sprawdzenie tożsamości.,Verificação de identidade.,,Verificare card de identitate.,Ваши документы.,,Kimlik kontrolü. -"Here, I'm in a hurry.",TXT_RPLY0_SCRIPT17_D1516_HEREI,〃 (〃),,,"Tady, spěchám.","Her, jeg har travlt.","Hier, ich hab's eilig.",,,"Ten, tengo prisa.",,"Tässä, minulla on kiire.","Voilà, je suis pressé.","Nesze, nem érek rá.","Ecco qua, vado di fretta.",ほら、急いでるんだ。,여기요. 급하니 빨리 확인해주세요.,Hier heb ik haast.,"Her, jeg har dårlig tid.",Spieszę się.,"Pegue, estou com pressa.",,"Aici, mă grăbesc.",Вот. Я тороплюсь.,,"Al, acelem var." -Stop waving your ID in my face and go in.,TXT_DLG_SCRIPT17_D3032_STOPW,〃 (〃),,,Přestaň mi tu mávat tou kartou a jdi dovnitř.,Hold op med at vifte med dit ID i mit ansigt og gå ind.,Hör auf mit deinem Ausweis vor meinem Gesicht herumzufuchteln und geh hinein.,,,Deja de agitar tu identificación en mi cara y entra.,,Lakkaa heiluttelemasta tunnistettasi päin naamaa ja mene sisään.,Arrêtez de l'agiter dans ma figure et passez.,Ne lobogtasd az igazolványodat az arcomba és menj be.,Smettila di sventolarmela in faccia e vai avanti.,目前まで近づけるな、さっさと行け。,얼굴 앞에서 신분증 그만 흔들고 얼른 들어가.,Stop met je ID in mijn gezicht te zwaaien en ga naar binnen.,Slutt å vifte med legitimasjonen og gå inn.,Przestań machać mi przed nosem swoim dowodem i wejdź.,Pare de sacudir a sua identificação e entre logo.,,Nu mai flutura cardul în fața mea și intră.,Прекрати махать своей карточкой перед моим лицом и проходи.,,Kimliğini yüzüme karşı sallamayı bırak ve içeri gir. -Nothing to see here. Move along.,TXT_DLG_SCRIPT17_D4548_NOTHI,MAP17: Green guards.,,,Nic k vidění. Jdi dál.,Der er intet at se her. Gå videre.,Hier gibt es nichts zu sehen. Geh weiter.,,,Nada que ver aquí. Sigue caminando.,,Täällä ei ole mitään nähtävää. Jatkakaa matkaa.,Rien à voir ici. Bougez.,Nincs itt semmi látnivaló. Mozgás tovább.,Non c'è niente da vedere qui. Gira al largo.,何事も無い。進め。,아무 일도 안 일어났다. 어서 움직여.,Hier is niets te zien. Ga verder.,Ingenting å se her. Gå videre.,Nie ma tu nic do oglądania. Ruszaj się.,Nada pra ver aqui. Vá embora.,,Nimic aici. Mișcă.,Тут не на что смотреть. Проваливай.,,Burada görecek bir şey yok. İlerleyin. -"What a healthy specimen. You don't need my help, do you?",TXT_DLG_SCRIPT17_D6064_WHATA,MAP17: Hospital → Quincy,,,"Takový zdravý exemplář! Moji pomoc nepotřebujete, že ne?","Sikke et sundt eksemplar. Du har ikke brug for min hjælp, vel?","Was für ein schönes Exemplar. Du brauchst meine Hilfe nicht, oder?",,,"Que espécimen más saludable. No necesitas mi ayuda, ¿verdad?",,No siinäpä vasta mallitapaus. Et sattumoisin ole avun tarpeessa?,"Quel magnifique spécimen! Vous n'avez pas besoin de mon aide, si?","Micsoda jó erőben levő példány. Neked nem kell segítség, ugye?","Che esemplare sano. Non hai bisogno del mio aiuto, vero?","なんて活きの良い標本だ。 -手当なんて必要なさそうだな、で何だ?","정말 건강한 표본이군. 아마 넌 내 도움이 필요하지 않을 거야, 그렇지?","Wat een gezond exemplaar. Je hebt mijn hulp niet nodig, of wel?",For et sunt eksemplar. Du trenger vel ikke min hjelp?,"Co za zdrowy okaz. Nie potrzebujesz mojej pomocy, prawda?","Mas que espécime mais saudável. Você não precisa da minha ajuda, precisa?",,"Ce specimen sănătos. Nu ai nevoie de ajutorul meu, nu?","Какой прекрасный образец. Тебе не нужна моя помощь, или нужна?",,"Ne kadar sağlıklı bir örnek. Yardımıma ihtiyacın yok, değil mi?" -"Well, yes. Macil sent me.",TXT_RPLY0_SCRIPT17_D6064_WELLY,〃,,,Potřebuju. Poslal mě Macil.,"Jo, jo. Macil har sendt mig.","Nun, doch. Macil hat mich geschickt.",,,"Bueno, sí. Macil me ha enviado.",,"Itse asiassa, kyllä. Macil lähetti minut.","Eh bien, si, Macil m'envoie.","Nos, igen. Macil küldött.","Ecco, si. Mi ha mandato Macil.",そうだ。マシルの使者だ。,"뭐, 그렇지. 마실이 날 보냈으니까.","Nou, ja. Macil heeft me gestuurd.",Jo. Macil sendte meg.,No tak. Macil mnie przysłał.,"Bem, sim. Macil me enviou.",,Ba da. Macil m-a trimis.,"Ну, нужна. Я от Мэйсила.",,"Evet, var. Beni Macil gönderdi." -"Shhhh... Keep it quiet, unless you want us both killed. Now, what can I do for you?",TXT_DLG_SCRIPT17_D7580_SHHHH,〃,,,"Pššš... Buď potichu, leda že bys nás oba chtěl nechat popravit. Tak, co pro tebe můžu udělat?","Shhhh... Hold det stille, medmindre du vil have os begge dræbt. Hvad kan jeg gøre for dig?","Psst... sei leise, oder willst du uns beide umbringen? Nun, was kann ich für dich tun?",,,"Shhhh... No tan alto, a menos que quieras que nos maten a ambos. Bueno, ¿Qué puedo hacer por ti?",,"Hyss, suuta soukemmalle, ellet halua tapattaa meitä molempia. No niin, miten voin auttaa?","Silence! Baissez de ton, sauf si vous voulez que l'on se fasse descendre tous le deux.. Que puis-je faire pour vous?","Shhhh...csak csendben, különben mindkettőnket megöletsz. Akkor, miben is segíthetek?","Shhhh... Fai piano, a meno che non vuoi farci ammazzare tutti e due. Ora, che posso fare per te?","シーッ...静かに、 -殺されるかもしれないんだぞ。それで何か用か?","쉿... 죽기 싫으면 조용히 해. 자, 내가 뭘 도와줄까?","Shhhhhh.... Hou het stil, tenzij je wilt dat we allebei gedood worden. Wat kan ik nu voor u doen?","Vær stille, hvis du ikke vil at vi begge skal bli drept. Hva kan jeg gjøre for deg?","Cicho, chyba że chcesz nas obu zabić. Co mogę dla ciebie zrobić?","Shhhh... Fale baixo, a não ser que queira que nos matem. Agora, como posso te ajudar?",,"Șhhhh... Mai încet, dacă nu vrei să murim amândoi. Acum, ce pot face pentru tine?","Тсс... Тише, если не хочешь, чтобы нас обоих убили. Итак, чем я могу тебе помочь?",,"İkimizin de ölmesini istemiyorsan sessiz ol. Şimdi, senin için ne yapabilirim?" -Tell me how to find the Bishop.,TXT_RPLY0_SCRIPT17_D7580_TELLM,〃,,,"Řekni mi, jak najít Biskupa.","Fortæl mig, hvordan jeg finder biskoppen.","Sage mir, wie ich den Bischof finde.",,,Dime como encontrar al Obispo.,,"Kerro, miten löydän Piispan.",Où puis-je trouver l'évêque?,"Áruld el, hol találom meg a Püspököt.",Dimmi dove trovare il Vescovo.,ビショップは何処か聞きたい。,비숍을 어떻게 찾아야 하는지 알려줘.,Vertel me hoe ik de bisschop kan vinden.,Fortell meg hvordan jeg finner biskopen.,Powiedz mi jak znaleźć biskupa.,Diga onde eu encontro o Bispo.,,Spune-mi cum găsesc Episcopul.,"Скажи, как мне найти Епископа.",,Bana Piskopos'u nasıl bulacağımı söyle. -"Ohhh, I knew you would ask me for that. Look behind you. That's the entrance to the Bishop's citadel. It's guarded by a force field that is only shut off for official visitors, not you.",TXT_DLG_SCRIPT17_D9096_OHHHI,〃,,,"Ohó, já věděl, že se mě na tohle zeptáš. Podívej se za sebe. To je vchod do Biskupovy citadely. Je střežená silovým polem, které se vypíná pouze kvůli oficiálním návštěvám, ne tobě.","Jeg vidste, du ville spørge mig om det. Se bag dig. Det er indgangen til biskoppens citadel. Den er bevogtet af et kraftfelt, der kun er lukket for officielle besøgende, ikke dig.","Oh, hab ich's doch geahnt, dass du mich das fragen würdest. Schau mal hinter dich. Dort ist der Eingang zu der Festung des Bischofs. Er ist durch ein Kraftfeld geschützt, welches sich nur für offizielle Besucher abschaltet und nicht für dich.",,,"Ohhh, sabía que me preguntarías eso. Mira detrás de ti. Esa es la entrada a la ciudadela del Obispo. Está guardada por un campo de fuerza que solo se apaga para visitantes oficiales, no tú.",,"Oo, arvasin, että kysyisit sitä minulta. Katso taaksesi. Siellä on sisäänkäynti Piispan linnoitukseen. Sitä turvaa voimakenttä, joka kytketään pois päältä ainoastaan virallisille vieraille, ei sinulle.","Ohh, je savais que vous me demanderiez cela. Regardez derrière vous. C'est l'entrée de la citadelle de l'évêque. Elle est gardée par un champ de force qui ne s'ouvre que pour les visites officielles, pas vous.","Ohhh, tudtam, hogy ezt fogod kérdezni. Nézz csak magad mögé. Ez a püspök fellegvárához a bejárat. Egy erőpajzs védi, és csak hivatalos látogatóknak nyitják ki, aminek valljuk be Te nem igazán felelsz meg.","Ohhh, sapevo che me l'avresti chiesto. Guarda dietro di te. Quello è l'ingresso per la cittadella del Vescovo. È protetta da un campo di forza che viene disattivato solo per le visite ufficiali, quindi non per la tua.","おおぅ、そういう事だろうと思った。 +だけの仕事だったが、もう辞任だな!",전송기를 파괴하기 전까지는 세뇌된 사람들을 도와줄 수가 없어요. 저 위층에 방어막에 보호받고 있는 채로 있습니다. 제 원래 업무는 광석이 끼지 않게 운반 벨트를 확인하는 거였어요... 이젠 일할 필요도 없지만!,Ik kan niemand anders helpen. Niet voordat je de zender hebt opgeblazen. Dat is wat er achter het krachtveld boven is. Het is mijn taak om de transportbanden te controleren om er zeker van te zijn dat ze niet vastzitten. Nu niet meer!,Jeg kan ikke hjelpe noen andre. Ikke før du sprenger senderen. Det er det som er bak kraftfeltet der oppe. Jobben min er å sjekke at transportbåndene ikke er blokkert. Ikke nå lenger!,"Nie mogę pomóc nikomu innemu. Nie, dopóki nie wysadzisz nadajnika. To jest to, co jest za polem siłowym na górze. Moim zadaniem jest sprawdzanie, czy przenośniki nie są zablokowane. Już nie!",Não posso ajudar mais ninguém. Não até que você detone o transmissor. É isso que mantém o campo de força lá em cima. Meu trabalho é conferir as esteiras para que não fiquem emperradas. Nunca mais!,,"Nu pot ajuta pe nimeni. Nu până ce transmițătorul nu e aruncat în aer. Asta e la etaj, în spatele scuturilor. Treaba mea e să mă uit după conveioare, să mă asigur că nu sunt defecte. Numai!","Я не могу помочь другим, пока ты не взорвёшь передатчик. Он находится за силовым полем наверху. Моя работа — проверять, не заклинило ли конвейеры. Теперь уже нет!",,Jag kan inte hjälpa någon annan. Inte förrän du spränger sändaren. Det är det som finns bakom kraftfältet på övervåningen. Mitt jobb är att kontrollera transportörerna så att de inte fastnar. Inte längre!,"Başka kimseye yardım edemem. Vericiyi patlatana kadar olmaz. Üst kattaki güç alanının arkasında bu var. Benim işim, sıkışmadıklarından emin olmak için konveyörleri kontrol etmek. Artık değil!" +"That's right, you're saved!",TXT_RPLY0_SCRIPT14_D1516_THATS,〃,,,"Ano, jsi zachráněn!","Det er rigtigt, du er reddet!","Das ist richtig, du bist in Sicherheit!",,"Ĝuste, vi estas savitaj!","Correcto, ¡estáis a salvo!","Correcto, ¡están a salvo!","Näin on, olet pelastettu!","C'est ça, vous êtes sauvé!","Így van, meg van mentve.","Esatto, sei salvo!",そうだ、救われたぞ!,당연하지. 너는 자유야!,"Dat klopt, je bent gered!","Det stemmer, du er reddet!","Tak jest, jesteś uratowany!",Isso mesmo. Vocês estão salvos!,,"Așa e, ești salvat!","Да, это так! Вы спасены!",,"Det stämmer, du är räddad!","Bu doğru, kurtuldun!" +"Oh, thank you!",TXT_RYES0_SCRIPT14_D1516_OHTHA,〃,,,"Oh, děkuju!","Åh, tak!","Oh, danke sehr!",,"Ho, dankon!","¡Ah, gracias!",,"Voi, kiitos!","Oh, merci!","Oh, köszönöm!","Oh, grazie!",おう、ありがとよ!,"오, 고마워요!","Oh, dank je wel!",Takk skal du ha!,"Och, dziękuję!","Ah, muito obrigado!",,"Oh, mulțumesc!",Ура! Спасибо тебе!,,"Åh, tack!","Oh, teşekkürler!" +We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D3032_WEREF,〃,,,Jsme volní! Jsme volní! Jsme volní!,Vi er fri!! Vi er fri!! Vi er fri!!!,Wir sind frei! Wir sind frei! Wir sind frei!,,Ni estas liberaj!! Liberaj!! Liberaj!!,¡¡Somos libres!! ¡¡Somos libres!! ¡¡Somos libres!!,,Olemme vapaat!! Olemme vapaat!! Olemme vapaat!!,On est libres! Libres! Libres!,Szabadok vagyunk!! Szabadok vagyunk!! Szabadok vagyunk!!,Siamo liberi!! Siamo liberi!! Siamo liberi!!,自由だ!!俺達は自由だ!!俺達は自由だ!!,우린 자유야! 우린 자유라고!,We zijn vrij!! We zijn vrij!! We zijn vrij!!,Vi er fri! Vi er fri!! Vi er fri!!,Jesteśmy wolni!!! Jesteśmy wolni!!! Jesteśmy wolni!!!,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!,,Vi är fria!! Vi är fria! Vi är fria!!,Özgürüz! Özgürüz! Özgürüz! +Must mine more ore!,TXT_DLG_SCRIPT14_D4548_MUSTM,MAP14: Drone,,,Muset těžit další rudu!,Vi må udvinde mere malm!,Muss Erz abbauen.,,Mi elfosu pliajn minaĵojn!,¡Debo picar más mineral!,,Täytyy louhia lisää malmia!,Faut que je trouve plus de minerai!,Még több ércet kell bányászni!,Devo estrarre più minerale!,もっと掘らねえといけねえんだ!,광석을... 캐내야 해...,Moet erts meer of meer ontginnen!,Må utvinne mer malm!,Musimy wydobyć więcej rudy!,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!,,Måste bryta mer malm!,Daha fazla maden çıkarmalıyız! +We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D6064_WEREF,MAP14: Peasant (ex-drone),,,Jsme volní! Jsme volní! Jsme volní!,Vi er frie!! Vi er frie!!! Vi er frie!!,Wir sind frei! Wir sind frei! Wir sind frei!,,Ni estas liberaj!! Liberaj!! Liberaj!!,¡¡Somos libres!! ¡¡Somos libres!! ¡¡Somos libres!!,,Olemme vapaat!! Olemme vapaat!! Olemme vapaat!!,On est libres! Libres! Libres!,Szabadok vagyunk!! Szabadok vagyunk!! Szabadok vagyunk!!,Siamo liberi!! Siamo liberi!! Siamo liberi!!,自由だ!!オレらは自由だ!!オレらは自由だ!!,프론트가 해냈다! 자유를 거의 되찾았어!,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,Vi er fri!! Vi er frie!! Vi er fri!!,Jesteśmy wolni! Jesteśmy wolni!!! Jesteśmy wolni!!!,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!,,Vi är fria!! Vi är fria!! Vi är fria!!,Özgürüz! Özgürüz! Özgürüz! +Must mine more ore!,TXT_DLG_SCRIPT14_D7580_MUSTM,〃,,,Muset těžit další rudu!,Skal udvinde mere malm!,Muss Erz abbauen.,,Mi elfosu pliajn minaĵojn!,¡Debo picar más mineral!,,Täytyy louhia lisää malmia!,Faut que je trouve plus de minerai!,Még több ércet kell bányászni!,Devo estrarre più minerale!,鉱石がもっと必要なんだ!,광석... 데그닌... 캔다...,Moet meer erts ontginnen!,Må utvinne mer malm!,Musimy wydobyć więcej rudy!,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!,,Måste bryta mer malm!,Daha fazla maden çıkarmalıyız! +We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D9096_WEREF,〃,,,Jsme volní! Jsme volní! Jsme volní!,Vi er frie!!! Vi er frie!!! Vi er frie!!,Wir sind frei! Wir sind frei! Wir sind frei!,,Ni estas liberaj!! Liberaj!! Liberaj!!,¡¡Somos libres!! ¡¡Somos libres!! ¡¡Somos libres!!,,Olemme vapaat!! Olemme vapaat!! Olemme vapaat!!,On est libres! Libres! Libres!,Szabadok vagyunk!! Szabadok vagyunk!! Szabadok vagyunk!!,Siamo liberi!! Siamo liberi!! Siamo liberi!!,自由だ!!私達は自由だ!!私達は自由だ!!,살았군요. 이제 저항군 기지로 향하는 일 밖엔 남지 않은 것 같아요.,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,Vi er fri!! Vi er frie!! Vi er fri!!,Jesteśmy wolni!!! Jesteśmy wolni!!! Jesteśmy wolni!!!,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!,,Vi är fria!! Vi är fria!! Vi är fria!!,Özgürüz! Özgürüz! Özgürüz! +Must mine more ore!,TXT_DLG_SCRIPT14_D10612_MUSTM,〃,,,Muset těžit další rudu!,Skal udvinde mere malm!,Muss Erz abbauen.,,Mi elfosu pliajn minaĵojn!,¡Debo picar más mineral!,,Täytyy louhia lisää malmia!,Faut que je trouve plus de minerai!,Még több ércet kell bányászni!,Devo estrarre più minerale!,いつまで採掘しなければならない!,캐고... 캐고... 또 캔다...,Moet meer erts ontginnen!,Må utvinne mer malm!,Musimy wydobyć więcej rudy!,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!,,Måste bryta mer malm!,Daha fazla maden çıkarmalıyız! +We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D12128_WEREF,〃,,,Jsme volní! Jsme volní! Jsme volní!,Vi er frie!!! Vi er frie!!! Vi er frie!!,Wir sind frei! Wir sind frei! Wir sind frei!,,Ni estas liberaj!! Liberaj!! Liberaj!!,¡¡Somos libres!! ¡¡Somos libres!! ¡¡Somos libres!!,,Olemme vapaat!! Olemme vapaat!! Olemme vapaat!!,On est libres! Libres! Libres!,Szabadok vagyunk!! Szabadok vagyunk!! Szabadok vagyunk!!,Siamo liberi!! Siamo liberi!! Siamo liberi!!,僕らは自由だ!!僕らは自由だ!!僕らは自由だ!!,살았다! 이제 그 놈들이 죽이기 전에 도망쳐야해요!,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,Vi er fri!! Vi er frie!! Vi er frie!!,Jesteśmy wolni!!! Jesteśmy wolni!!! Jesteśmy wolni!!!,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!,,Vi är fria!! Vi är fria!! Vi är fria!!,Özgürüz! Özgürüz! Özgürüz! +What are you doing here?,TXT_DLG_SCRIPT15_D0_WHATA,MAP15: Red acolytes.,,,Co tady děláte?,Hvad laver du her?,Was machst du hier?,,Kial vi estas ĉi tie?,¿Qué haces aquí?,,Mitä teette täällä?,Qu'est ce que vous faites ici?,Mit csinálsz itt?,Che cosa fai qui?,ここで何をしている?,여기서 뭘 하는거지?,Wat doe je hier?,Hva gjør dere her?,Co ty tu robisz?,O que você está fazendo aqui?,,Ce cauți aici?,По какому делу ты здесь?,,Vad gör du här?,Ne yapıyorsunuz burada? +Routine inspection.,TXT_RPLY0_SCRIPT15_D0_ROUTI,〃,,,Rutinní kontrola.,Rutinemæssig inspektion.,Eine Routineinspektion.,,Rutina inspektado.,Inspección de rutina.,,Rutiinitarkastus.,Inspection de routine.,Rutin ellenőrzés.,Ispezione ordinaria.,見回りだ。,정기적 검사요.,Routine-inspectie.,Rutinemessig inspeksjon.,Rutynowa inspekcja.,Inspeção de rotina.,,Inspecție de rutină.,Плановая проверка.,,Rutininspektion.,Rutin teftiş. +"All right, carry on.",TXT_RYES0_SCRIPT15_D0_ALLRI,〃,,,"Dobře, pokračujte.","Okay, fortsæt.","In Ordnung, mach weiter.",,"Bone, daŭrigu.","Muy bien, continúa.",,"Selvä on, jatkakaa.","D'accord, continuez.","Renben, folytasd csak.","Va bene, vai pure avanti.",わかった、続けろ。,"좋아, 계속해.","Oké, ga door.","Greit, fortsett.","W porządku, kontynuuj.","Muito bem, continue.",,"Bine, mergi mai departe.",Понятно. Продолжай.,,"Okej, fortsätt.","Pekala, devam edin." +"Nothing to report here. Everything is working fine. If anything goes wrong, I'll be sure to report it.",TXT_DLG_SCRIPT15_D1516_NOTHI,MAP15: Red acolytes + Technician at the beginning.,,,"Tady nic k nahlášení není. Všechno funguje dobře. Pokud se něco pokazí, nahlásím to.","Der er intet at rapportere her. Alt fungerer fint. Hvis noget går galt, skal jeg nok rapportere det.","Keine besonderen Vorkommnisse. Alles funktioniert wie es soll. Wenn irgendetwas schief geht, werde ich es sofort melden.",,"Nenio raportinda ĉi tie; ĉio funkcias ĝuste. Se io ajn malsukcesos, mi certe raportos ĝin.","Nada que reportar aquí; todo está funcionando bien. Si algo sale mal, me aseguraré de reportarlo.","Nada que reportar aquí; todo está funcionando bien. Si algo sale mal, me voy a asegurar de reportarlo.","Ei mitään raportoitavaa. Kaikki toimii hyvin. Jo mikään menee vialle, raportoin siitä varmasti.","Rien à signaler ici. Tout fonctionne comme prévu. Si quelque chose tombe en panne, je ferai un rapport.","Nincs semmi bejelentenivaló. Minden prímán működik. Ha esetleg valami meghibásodik, rögtön jelezni fogom.","Nulla da riportare qua. Tutto funziona come dovrebbe. Se qualcosa non dovesse funzionare, lo riporterò subito.","報告することはない。全て順調だ。 +何か問題が起きたら報告する。","보고할 게 전혀 없어. 모든 장치, 시설, 인력 모두 이상 무. 만약 하나라도 문제가 생기면 나에게 알려줘.","Hier valt niets te melden. Alles werkt prima. Als er iets misgaat, zal ik het zeker melden.","Ingenting å rapportere her. Alt fungerer som det skal. Hvis noe går galt, skal jeg rapportere det.","Nie ma o czym mówić. Wszystko działa jak należy. Jeśli coś będzie nie tak, na pewno to zgłoszę.","Não há nada de errado aqui. Tudo está funcionando perfeitamente. Se algo parar de funcionar, pode ter certeza que eu vou avisar.",,"Nimic de raportat aici. Dacă e ceva, cu siguranță că voi da raportul.","Тут не о чём докладывать. Всё работает превосходно. Если что-нибудь пойдёт не так, я обязательно доложу об этом.",,Inget att rapportera här. Allt fungerar bra. Om något går fel ska jag rapportera det.,"Burada rapor edilecek bir şey yok. Her şey yolunda gidiyor. Eğer bir sorun çıkarsa, rapor edeceğimden emin olabilirsiniz." +"Sir, there was a problem earlier, but it was taken care of.",TXT_DLG_SCRIPT15_D3032_SIRTH,MAP15: Technician at the beginning.,,,"Pane, předtím tu byl problém, ale vyřešili jsme jej.","Sir, der var et problem tidligere, men det blev ordnet.","Vor kurzem gab es ein Problem, aber das wurde bereits gelöst.",,"Sinjoro, estis problemo, sed ni jam solvis ĝin.","Señor, ha habido un problema antes, pero ya lo hemos solucionado.","Señor, hubo un problema antes, pero ya lo solucionamos.","Tässä aiemmin oli ongelma, mutta se ratkaistiin.","Monsieur, il y a eu un problème récemment mais nous l'avons corrigé.","Uram, volt korábban egy probléma, de megoldásra került.","Signore, c'era un problema prima, ma è stato risolto.","上官殿、以前より問題があったが、 +もう心配はいらない。",안녕하십니까. 조금 전에 문제가 있었습니다만 경마한 문제였고 지금 해결됐습니다.,"Meneer, er was eerder een probleem, maar het is opgelost.","Sir, det var et problem tidligere, men det ble tatt hånd om.","Sir, wcześniej był problem, ale już się nim zajęto.","Senhor, havia um problema antes, mas já foi resolvido.",,"Domnule, a fost o problemă adineauri, dar s-a rezolvat.","Сэр, тут была одна неполадка, но её уже устранили.",,"Sir, det var ett problem tidigare, men det har tagits om hand.","Efendim, daha önce bir sorun vardı, ama halledildi." +Move along or taste metal.,TXT_DLG_SCRIPT17_D0_MOVEA,MAP17: Bailey (if you don't have Order's key),,,"Jdi dál, nebo okus ocel.",Fortsæt eller smag på metal.,Beweg dich oder spüre meinen Stahl.,,Plue movu vin aŭ gustumu kuglojn.,Esfúmate o come plomo.,,"Jatka matkaasi, tai maista metallia.",Bougez ou préparez-vous à goûter de l'acier.,"Haladj tovább, vagy ízleld meg a kardom.",Sparisci o ti finisce male.,同行か鉄を味わうかだ。,탄창으로 맞고 싶지 않으면 움직여.,Ga verder of proef metaal.,Gå videre eller smak på metall.,Ruszaj się albo skosztuj metalu.,Vá embora ou vai tomar chumbo grosso.,,Mișcă-te sau mănânci metal.,"Прочь, или отведаешь металла.",,Gå vidare eller smaka på metall.,İlerleyin ya da metalin tadına bakın. +I.D. check.,TXT_DLG_SCRIPT17_D1516_IDCHE,〃 (if you have it),,,Doklady.,ID-tjek.,Ausweisüberprüfung.,,Kontrolo de identigilo.,Comprobación de identificación.,,Henkilöllisyystarkastus.,Vérification de carte d'identité.,Igazolvány ellenőrzés.,Verifica d'identità.,I.D.チェックだ。,신분증 확인.,I.D. check.,Legitimasjonskontroll.,Sprawdzenie tożsamości.,Verificação de identidade.,,Verificare card de identitate.,Ваши документы.,,ID-kontroll.,Kimlik kontrolü. +"Here, I'm in a hurry.",TXT_RPLY0_SCRIPT17_D1516_HEREI,〃 (〃),,,"Tady, spěchám.","Her, jeg har travlt.","Hier, ich hab's eilig.",,"Jen, mi hastas.","Toma, que tengo prisa.","Toma, que estoy apurado.","Tässä, minulla on kiire.","Voilà, je suis pressé.","Nesze, nem érek rá.","Ecco qua, vado di fretta.",ほら、急いでるんだ。,여기요. 급하니 빨리 확인해주세요.,Hier heb ik haast.,"Her, jeg har dårlig tid.",Spieszę się.,"Pegue, estou com pressa.",,"Aici, mă grăbesc.",Вот. Я тороплюсь.,,"Här, jag har bråttom.","Al, acelem var." +Stop waving your ID in my face and go in.,TXT_DLG_SCRIPT17_D3032_STOPW,〃 (〃),,,Přestaň mi tu mávat tou kartou a jdi dovnitř.,Hold op med at vifte med dit ID i mit ansigt og gå ind.,Hör auf mit deinem Ausweis vor meinem Gesicht herumzufuchteln und geh hinein.,,Ĉesu skui vian identigilon super mia vizaĝo kaj eniru.,Ya deja de sacudirme la identificación en la cara y entra.,,Lakkaa heiluttelemasta tunnistettasi päin naamaa ja mene sisään.,Arrêtez de l'agiter dans ma figure et passez.,Ne lobogtasd az igazolványodat az arcomba és menj be.,Smettila di sventolarmela in faccia e vai avanti.,目前まで近づけるな、さっさと行け。,얼굴 앞에서 신분증 그만 흔들고 얼른 들어가.,Stop met je ID in mijn gezicht te zwaaien en ga naar binnen.,Slutt å vifte med legitimasjonen og gå inn.,Przestań machać mi przed nosem swoim dowodem i wejdź.,Pare de sacudir a sua identificação e entre logo.,,Nu mai flutura cardul în fața mea și intră.,Прекрати махать своей карточкой перед моим лицом и проходи.,,Sluta vifta med ditt ID-kort i ansiktet på mig och gå in.,Kimliğini yüzüme karşı sallamayı bırak ve içeri gir. +Nothing to see here. Move along.,TXT_DLG_SCRIPT17_D4548_NOTHI,MAP17: Green guards.,,,Nic k vidění. Jdi dál.,Der er intet at se her. Gå videre.,Hier gibt es nichts zu sehen. Geh weiter.,,Nenio vidinda ĉi tie. Plue movu vin.,Nada que ver aquí. Sigue caminando.,,Täällä ei ole mitään nähtävää. Jatkakaa matkaa.,Rien à voir ici. Bougez.,Nincs itt semmi látnivaló. Mozgás tovább.,Non c'è niente da vedere qui. Gira al largo.,何事も無い。進め。,아무 일도 안 일어났다. 어서 움직여.,Hier is niets te zien. Ga verder.,Ingenting å se her. Gå videre.,Nie ma tu nic do oglądania. Ruszaj się.,Nada pra ver aqui. Vá embora.,,Nimic aici. Mișcă.,Тут не на что смотреть. Проваливай.,,Det finns inget att se här. Gå vidare.,Burada görecek bir şey yok. İlerleyin. +"What a healthy specimen. You don't need my help, do you?",TXT_DLG_SCRIPT17_D6064_WHATA,MAP17: Hospital → Quincy,,,"Takový zdravý exemplář! Moji pomoc nepotřebujete, že ne?","Sikke et sundt eksemplar. Du har ikke brug for min hjælp, vel?","Was für ein schönes Exemplar. Du brauchst meine Hilfe nicht, oder?",,"Kia sana specimeno. Vi ne bezonas mian helpon, ĉu?","Que espécimen más saludable. No necesitarás mi ayuda, ¿verdad?",,No siinäpä vasta mallitapaus. Et sattumoisin ole avun tarpeessa?,"Quel magnifique spécimen! Vous n'avez pas besoin de mon aide, si?","Micsoda jó erőben levő példány. Neked nem kell segítség, ugye?","Che esemplare sano. Non hai bisogno del mio aiuto, vero?","なんて活きの良い標本だ。 +手当なんて必要なさそうだな、で何だ?","정말 건강한 표본이군. 아마 넌 내 도움이 필요하지 않을 거야, 그렇지?","Wat een gezond exemplaar. Je hebt mijn hulp niet nodig, of wel?",For et sunt eksemplar. Du trenger vel ikke min hjelp?,"Co za zdrowy okaz. Nie potrzebujesz mojej pomocy, prawda?","Mas que espécime mais saudável. Você não precisa da minha ajuda, precisa?",,"Ce specimen sănătos. Nu ai nevoie de ajutorul meu, nu?","Какой прекрасный образец. Тебе не нужна моя помощь, или нужна?",,"Vilket friskt exemplar. Du behöver inte min hjälp, eller hur?","Ne kadar sağlıklı bir örnek. Yardımıma ihtiyacın yok, değil mi?" +"Well, yes. Macil sent me.",TXT_RPLY0_SCRIPT17_D6064_WELLY,〃,,,Potřebuju. Poslal mě Macil.,"Jo, jo. Macil har sendt mig.","Nun, doch. Macil hat mich geschickt.",,"Nu, jes. Macil venigis min.","Bueno, sí. Macil me ha enviado.","Bueno, sí. Me manda Macil.","Itse asiassa, kyllä. Macil lähetti minut.","Eh bien, si, Macil m'envoie.","Nos, igen. Macil küldött.","Ecco, si. Mi ha mandato Macil.",そうだ。マシルの使者だ。,"뭐, 그렇지. 마실이 날 보냈으니까.","Nou, ja. Macil heeft me gestuurd.",Jo. Macil sendte meg.,No tak. Macil mnie przysłał.,"Bem, sim. Macil me enviou.",,Ba da. Macil m-a trimis.,"Ну, нужна. Я от Мэйсила.",,"Jo, jo. Macil skickade mig.","Evet, var. Beni Macil gönderdi." +"Shhhh... Keep it quiet, unless you want us both killed. Now, what can I do for you?",TXT_DLG_SCRIPT17_D7580_SHHHH,〃,,,"Pššš... Buď potichu, leda že bys nás oba chtěl nechat popravit. Tak, co pro tebe můžu udělat?","Shhhh... Hold det stille, medmindre du vil have os begge dræbt. Hvad kan jeg gøre for dig?","Psst... sei leise, oder willst du uns beide umbringen? Nun, was kann ich für dich tun?",,"Ŝŝ! Ne tiel laŭte se vi ne intencas, ke ni ambaŭ estu mortigitaj. Nu, kion mi faru por vi?","Shhhh... No tan alto, a menos que quieras que nos maten a ambos. Y bueno, ¿qué puedo hacer por ti?",,"Hyss, suuta soukemmalle, ellet halua tapattaa meitä molempia. No niin, miten voin auttaa?","Silence! Baissez de ton, sauf si vous voulez que l'on se fasse descendre tous le deux.. Que puis-je faire pour vous?","Shhhh...csak csendben, különben mindkettőnket megöletsz. Akkor, miben is segíthetek?","Shhhh... Fai piano, a meno che non vuoi farci ammazzare tutti e due. Ora, che posso fare per te?","シーッ...静かに、 +殺されるかもしれないんだぞ。それで何か用か?","쉿... 죽기 싫으면 조용히 해. 자, 내가 뭘 도와줄까?","Shhhhhh.... Hou het stil, tenzij je wilt dat we allebei gedood worden. Wat kan ik nu voor u doen?","Vær stille, hvis du ikke vil at vi begge skal bli drept. Hva kan jeg gjøre for deg?","Cicho, chyba że chcesz nas obu zabić. Co mogę dla ciebie zrobić?","Shhhh... Fale baixo, a não ser que queira que nos matem. Agora, como posso te ajudar?",,"Șhhhh... Mai încet, dacă nu vrei să murim amândoi. Acum, ce pot face pentru tine?","Тсс... Тише, если не хочешь, чтобы нас обоих убили. Итак, чем я могу тебе помочь?",,"Shhhh... Håll tyst, om du inte vill att vi båda ska dödas. Vad kan jag göra för dig?","İkimizin de ölmesini istemiyorsan sessiz ol. Şimdi, senin için ne yapabilirim?" +Tell me how to find the Bishop.,TXT_RPLY0_SCRIPT17_D7580_TELLM,〃,,,"Řekni mi, jak najít Biskupa.","Fortæl mig, hvordan jeg finder biskoppen.","Sage mir, wie ich den Bischof finde.",,Diru kiel mi trovu la Episkopon.,Dime como encontrar al Obispo.,,"Kerro, miten löydän Piispan.",Où puis-je trouver l'évêque?,"Áruld el, hol találom meg a Püspököt.",Dimmi dove trovare il Vescovo.,ビショップは何処か聞きたい。,비숍을 어떻게 찾아야 하는지 알려줘.,Vertel me hoe ik de bisschop kan vinden.,Fortell meg hvordan jeg finner biskopen.,Powiedz mi jak znaleźć biskupa.,Diga onde eu encontro o Bispo.,,Spune-mi cum găsesc Episcopul.,"Скажи, как мне найти Епископа.",,Berätta hur jag hittar biskopen.,Bana Piskopos'u nasıl bulacağımı söyle. +"Ohhh, I knew you would ask me for that. Look behind you. That's the entrance to the Bishop's citadel. It's guarded by a force field that is only shut off for official visitors, not you.",TXT_DLG_SCRIPT17_D9096_OHHHI,〃,,,"Ohó, já věděl, že se mě na tohle zeptáš. Podívej se za sebe. To je vchod do Biskupovy citadely. Je střežená silovým polem, které se vypíná pouze kvůli oficiálním návštěvám, ne tobě.","Jeg vidste, du ville spørge mig om det. Se bag dig. Det er indgangen til biskoppens citadel. Den er bevogtet af et kraftfelt, der kun er lukket for officielle besøgende, ikke dig.","Oh, hab ich's doch geahnt, dass du mich das fragen würdest. Schau mal hinter dich. Dort ist der Eingang zu der Festung des Bischofs. Er ist durch ein Kraftfeld geschützt, welches sich nur für offizielle Besucher abschaltet und nicht für dich.",,"Ho, mi sciis, ke vi estis petonta tion. Rigardu malantaŭen tra la fenestro: tie estas la enirejo al la citadelo de la Episkopo. Ĝin baras fortokampo malŝaltinda nur por oficialaj vizitantoj, ne vi, ekzemple.","Ah, imaginaba que me ibas a pedir eso. Mira detrás de ti por la ventana: ahí está la entrada a la ciudadela del Obispo. La bloquea un campo de fuerza que solo se apaga para visitas oficiales, no tú, por ejemplo.",,"Oo, arvasin, että kysyisit sitä minulta. Katso taaksesi. Siellä on sisäänkäynti Piispan linnoitukseen. Sitä turvaa voimakenttä, joka kytketään pois päältä ainoastaan virallisille vieraille, ei sinulle.","Ohh, je savais que vous me demanderiez cela. Regardez derrière vous. C'est l'entrée de la citadelle de l'évêque. Elle est gardée par un champ de force qui ne s'ouvre que pour les visites officielles, pas vous.","Ohhh, tudtam, hogy ezt fogod kérdezni. Nézz csak magad mögé. Ez a püspök fellegvárához a bejárat. Egy erőpajzs védi, és csak hivatalos látogatóknak nyitják ki, aminek valljuk be Te nem igazán felelsz meg.","Ohhh, sapevo che me l'avresti chiesto. Guarda dietro di te. Quello è l'ingresso per la cittadella del Vescovo. È protetta da un campo di forza che viene disattivato solo per le visite ufficiali, quindi non per la tua.","おおぅ、そういう事だろうと思った。 後ろを見ろ。そこがビショップの大聖堂だ。 しかし要人以外は入れないよう フォースフィールドが張ってある、 -君には通れないな。","호오오, 난 네가 그걸 물어볼 줄 알았어. 뒤를 돌아봐. 저건 비숍의 성채로 향하는 입구야. 방어막으로 덮여있는데 저걸 끌 수 있는 건 허가된 방문자뿐이야. 네가 아니라.","Ohhhh, ik wist dat je me dat zou vragen. Kijk achter je. Dat is de ingang van de bisschopsburcht. Het wordt bewaakt door een krachtveld dat alleen afgesloten is voor officiële bezoekers, niet voor jou.","Jeg visste du ville spørre om det. Se bak deg. Det er inngangen til biskopens citadell. Den er bevoktet av et kraftfelt som bare er stengt for offisielle besøkende, ikke deg.","Ohhh, wiedziałem, że mnie o to poprosisz. Spójrz za siebie. To wejście do cytadeli biskupa. Jest strzeżone przez pole siłowe, które jest wyłączane tylko dla oficjalnych gości, nie dla ciebie.","Ahhh, eu sabia que você me perguntaria isso. Olhe atrás de você. Essa é a entrada para a cidadela do Bispo. Ela é protegida por um campo de força que é desligada somente para visitantes oficiais, para você não.",,"Ohhh, știam eu că asta urma să mă întrebi. Aia e intrarea către citadela Episcopului. E apărată de un scut care se oprește numai pentru vizitatorii autorizați, nu pentru tine.","А-а-а, я знал, что ты спросишь об этом. Оглянись: это вход в цитадель Епископа. Он защищён силовым полем, которое отключается только для официальных посетителей, не для тебя.",,"Benden bunu isteyeceğini biliyordum. Arkana bak. Bu Piskopos'un kalesinin girişi. Sadece resmi ziyaretçiler için kapatılan bir güç alanı tarafından korunuyor, sen değil." -I must kill the Bishop.,TXT_RPLY0_SCRIPT17_D9096_IMUST,〃,,,Musím zabít Biskupa.,Jeg må dræbe biskoppen.,Ich muss den Bischof töten.,,,Debo matar al Obispo.,,Minun on tapettava Piispa.,Je dois tuer l'évêque.,Meg kell ölnöm a Püspököt.,Devo uccidere il Vescovo.,ビショップを殺さなければならないんだ。,난 비숍을 죽여야만 해.,Ik moet de bisschop vermoorden.,Jeg må drepe biskopen.,Muszę zabić biskupa.,Preciso matar o Bispo.,,Trebuie să-l omor pe Episcop.,Я должен убить Епископа.,,Piskoposu öldürmeliyim. -"Oh, sure you do. First, fight your way into the security complex and use the teleporter. And this might be more to your liking, destroy the computer in central administration. No computer, no force field.",TXT_DLG_SCRIPT17_D10612_OHSUR,〃,,,"No jistě že! Nejprve se probojuj do bezpečnostního komplexu a použij teleportér. A tohle by se ti mohlo více zamlouvat: Znič počítač v ústřední administraci. Žádný počítač, žádné pole.","Selvfølgelig skal du det. Først skal du kæmpe dig ind i sikkerhedskomplekset og bruge teleporteren. Og dette er måske mere efter din smag, ødelæg computeren i centraladministrationen. Ingen computer, intet kraftfelt.","Oh, aber klar doch. Erst kämpf dich bis zum Sicherheitskomplex durch und benutze den Teleporter. Und er nächste Schritt dürfte dir gefallen: zerstöre den Computer in der Hauptverwaltung. Kein Computer, kein Kraftfeld.",,,"Oh, seguro que sí. Primero, lucha camino adentro del complejo de seguridad y usa el teletransporte. Y esto puede que sea de tu agrado, destruye la computadora en administración central. Sin computadora, no hay campo de fuerza.","Oh, seguro que sí. Primero, pelea para entrar al complejo de seguridad y usa el teletransporte. Y esto puede que sea de tu agrado, destruye la computadora en administración central. Sin computadora, no hay campo de fuerza.","Niinpä tietysti. Ensiksi taistele tiesi turvallisuuskeskukseen ja käytä kaukosiirrintä. Ja tämä saattaa olla ehkä enemmän sinun mieleesi: tuhoa tietokone keskushallinnossa. Ei tietokonetta, ei voimakenttää.","Oh, oui, bien sûr que vous devez. D'abord il faudra forcer le chemin vers le complexe de sécurité, puis utiliser le téléporteur. Ce qui vous plaira aussi, détruisez l'ordinateur dans le centre d'administration. Pas d'ordinateur, pas de champ de force.","Oh, persze persze. Előszöris, küzdd magad át a biztonsági komplexumig és használd a teleportert. Aztán - ami talán jobban fog tetszeni - tedd tönkre a számítógépet a központi adminisztráción. Ha nincs számítógép, nincs erőpajzs.","Oh, come no. Per cominciare, devi andare nel complesso di sicurezza e usare il teletrasporto là. E questo penso ti piacerà, devi distruggere il computer nell'amministrazione centrale. Niente computer, niente campo di forza.","ああ、だろうな。先にまず複合警備施設を +君には通れないな。","호오오, 난 네가 그걸 물어볼 줄 알았어. 뒤를 돌아봐. 저건 비숍의 성채로 향하는 입구야. 방어막으로 덮여있는데 저걸 끌 수 있는 건 허가된 방문자뿐이야. 네가 아니라.","Ohhhh, ik wist dat je me dat zou vragen. Kijk achter je. Dat is de ingang van de bisschopsburcht. Het wordt bewaakt door een krachtveld dat alleen afgesloten is voor officiële bezoekers, niet voor jou.","Jeg visste du ville spørre om det. Se bak deg. Det er inngangen til biskopens citadell. Den er bevoktet av et kraftfelt som bare er stengt for offisielle besøkende, ikke deg.","Ohhh, wiedziałem, że mnie o to poprosisz. Spójrz za siebie. To wejście do cytadeli biskupa. Jest strzeżone przez pole siłowe, które jest wyłączane tylko dla oficjalnych gości, nie dla ciebie.","Ahhh, eu sabia que você me perguntaria isso. Olhe atrás de você. Essa é a entrada para a cidadela do Bispo. Ela é protegida por um campo de força que é desligada somente para visitantes oficiais, para você não.",,"Ohhh, știam eu că asta urma să mă întrebi. Aia e intrarea către citadela Episcopului. E apărată de un scut care se oprește numai pentru vizitatorii autorizați, nu pentru tine.","А-а-а, я знал, что ты спросишь об этом. Оглянись: это вход в цитадель Епископа. Он защищён силовым полем, которое отключается только для официальных посетителей, не для тебя.",,"Jag visste att du skulle be mig om det. Titta bakom dig. Det är ingången till biskopens citadell. Den är bevakad av ett kraftfält som bara stängs av för officiella besökare, inte för dig.","Benden bunu isteyeceğini biliyordum. Arkana bak. Bu Piskopos'un kalesinin girişi. Sadece resmi ziyaretçiler için kapatılan bir güç alanı tarafından korunuyor, sen değil." +I must kill the Bishop.,TXT_RPLY0_SCRIPT17_D9096_IMUST,〃,,,Musím zabít Biskupa.,Jeg må dræbe biskoppen.,Ich muss den Bischof töten.,,Mi devas mortigi la Episkopon.,Tengo que matar al Obispo.,,Minun on tapettava Piispa.,Je dois tuer l'évêque.,Meg kell ölnöm a Püspököt.,Devo uccidere il Vescovo.,ビショップを殺さなければならないんだ。,난 비숍을 죽여야만 해.,Ik moet de bisschop vermoorden.,Jeg må drepe biskopen.,Muszę zabić biskupa.,Preciso matar o Bispo.,,Trebuie să-l omor pe Episcop.,Я должен убить Епископа.,,Jag måste döda biskopen.,Piskoposu öldürmeliyim. +"Oh, sure you do. First, fight your way into the security complex and use the teleporter. And this might be more to your liking, destroy the computer in central administration. No computer, no force field.",TXT_DLG_SCRIPT17_D10612_OHSUR,〃,,,"No jistě že! Nejprve se probojuj do bezpečnostního komplexu a použij teleportér. A tohle by se ti mohlo více zamlouvat: Znič počítač v ústřední administraci. Žádný počítač, žádné pole.","Selvfølgelig skal du det. Først skal du kæmpe dig ind i sikkerhedskomplekset og bruge teleporteren. Og dette er måske mere efter din smag, ødelæg computeren i centraladministrationen. Ingen computer, intet kraftfelt.","Oh, aber klar doch. Erst kämpf dich bis zum Sicherheitskomplex durch und benutze den Teleporter. Und er nächste Schritt dürfte dir gefallen: zerstöre den Computer in der Hauptverwaltung. Kein Computer, kein Kraftfeld.",,"Ho, vi certe devas. Vi unue trabatu al vi la vojon en la sekurkomplekso kaj uzu la teleportilon. Vi eble pli ŝatos la duan parton: detruu la komputilon en la centra administrejo. Sen komputilo ne estas fortokampo.","Ah, seguro que sí. Primero ábrete camino por el complejo de seguridad y usa el teletransportador. Lo segundo puede que sea más de tu agrado: destruye el ordenador en la oficina de la administración central. Sin ordenador no hay campo de fuerza.","Ah, seguro que sí. Primero ábrete camino por el complejo de seguridad y usa el teletransportador. Lo segundo puede que sea más de tu agrado: destruye la computadora en la oficina de la administración central. Sin computadora no hay campo de fuerza.","Niinpä tietysti. Ensiksi taistele tiesi turvallisuuskeskukseen ja käytä kaukosiirrintä. Ja tämä saattaa olla ehkä enemmän sinun mieleesi: tuhoa tietokone keskushallinnossa. Ei tietokonetta, ei voimakenttää.","Oh, oui, bien sûr que vous devez. D'abord il faudra forcer le chemin vers le complexe de sécurité, puis utiliser le téléporteur. Ce qui vous plaira aussi, détruisez l'ordinateur dans le centre d'administration. Pas d'ordinateur, pas de champ de force.","Oh, persze persze. Előszöris, küzdd magad át a biztonsági komplexumig és használd a teleportert. Aztán - ami talán jobban fog tetszeni - tedd tönkre a számítógépet a központi adminisztráción. Ha nincs számítógép, nincs erőpajzs.","Oh, come no. Per cominciare, devi andare nel complesso di sicurezza e usare il teletrasporto là. E questo penso ti piacerà, devi distruggere il computer nell'amministrazione centrale. Niente computer, niente campo di forza.","ああ、だろうな。先にまず複合警備施設を 制圧してそこにあるテレポーターを使え。 君に合った方法だと思うが、テレポーター先の 中央管理部にあるコンピューターを潰せ。 コンピューターが無けれは、フォースも無しだ。 ","아, 그렇겠지. 먼저 보안단지에 들어가서 텔레포터를 이용해. 그리고 어쩌면 이건 네 취향일지도 모르겠군. 중앙 관리소에서 컴퓨터를 파괴해. 컴퓨터도 없애고, 방어막도 없애버리라고. - \cy최근 상황을 보건대, 잠입 작전은 힘들 것 같아.","Oh, zeker weten. Vecht je eerst een weg naar het veiligheidscomplex en gebruik de teleporter. En dit kan meer naar uw zin zijn, vernietig de computer in de centrale administratie. Geen computer, geen krachtveld.","Klart du må. Først må du kjempe deg inn i sikkerhetskomplekset og bruke teleporteren. Og dette er kanskje mer etter din smak. Ødelegg datamaskinen i sentraladministrasjonen. Ingen datamaskin, intet kraftfelt.","Oczywiście, że tak. Najpierw pokonaj drogę do kompleksu bezpieczeństwa i użyj teleportera. A to może bardziej ci się spodoba, zniszcz komputer w centralnej administracji. Nie ma komputera, nie ma pola siłowego.","Ah, mas é claro que precisa. Primeiro, lute até o complexo de segurança e use o teletransportador. E acho que você vai gostar disto: destrua o computador na administração central. Sem computador, sem campo de força.",,"Oh, normal. Mai întâi, trebuie să te zbați să ajungi în complexul de securitate și să folosești teleportorul. Și asta s-ar putea să îți placă mai mult, distruge calculatorul din camera de administrare centrală. Niciun calculator, niciun câmp de forță.","О, не сомневаюсь. Для начала проберись в охранный комплекс и используй телепорт. И, что тебе должно больше понравиться, уничтожь компьютер в центральной администрации. Нет компьютера — нет силового поля.",,"Tabii ki öldürmelisin. İlk olarak, güvenlik kompleksine girmek için savaş ve ışınlayıcıyı kullan. Ve bu daha çok hoşuna gidebilir, merkezi yönetimdeki bilgisayarı yok et. Bilgisayar yoksa, güç alanı da yok." -"Great, that sounds easy.",TXT_RPLY0_SCRIPT17_D10612_GREAT,〃,,,"Super, to zní snadně.","Fint, det lyder nemt.","Großartig, das klingt doch einfach.",,,"Genial, suena fácil.",,"Loistavaa, kuulostaa helpolta.","Bien, ça à l'air facile.","Remek, ez könnyűnek hangzik.","Ottimo, sembra facile.",そりゃいい、簡単そうだな。,"좋아, 쉬운 일인 것 같군.","Geweldig, dat klinkt gemakkelijk.","Flott, det høres enkelt ut.","Wspaniale, to brzmi łatwo.",Ótimo. Isso parece fácil.,,"Grozav, sună simplu.","Здорово, звучит легко.",,"Harika, kulağa kolay geliyor." -"There's an advantage to destroying the computer, that's where the plans to the tower are kept. Can you say, five finger discount? Heh heh!",TXT_DLG_SCRIPT17_D12128_THERE,〃,,,Zničení toho počítače má výhodu: Na tom samém místě jsou uschovány plány věže. Co říkáš na takovou koupi za pět prstů? Haha!,"Der er en fordel ved at ødelægge computeren, det er der, hvor planerne til tårnet opbevares. Kan du sige, fem fingre rabat? Heh heh!","Es hätte sein Gutes, den Computer zu zerstören, denn dort sind auch die Pläne für den Turm. Kannst du sagen: Mitgehen lassen? Hehe!",,,"Hay una ventaja al destruir la computadora, ahí se guardan los planos de la torre. Puedes decir... ¿descuento a cinco dedos? ¡je je!",,"Tietokoneen tuhoamisessa on etunsa; siinä pidetään tornin piirustuksia. Sanottaisiinko, kaupanpäällisinä? Hehheh!",Ce serait avantageux de détruire l'ordinateur car c'est là qu'ils gardent les plans de la tour. C'est facile d'avoir ça gratuitement quand on peut juste les prendre comme ça!,"Van amúgy egy előnye a számítógép szobának, ott tartják ugyanis a torony terveit ott tárolják. Mi lenne mondjuk ha véletlen magaddal hoznád őket? heh heh!",Sarebbe vantaggioso distruggere il computer perché è lì che tengono i piani per la torre. È facile ottenerli gratuitamente quando puoi prenderli in questo modo! Heh heh!,"コンピューターを潰す利点はな、 + \cy최근 상황을 보건대, 잠입 작전은 힘들 것 같아.","Oh, zeker weten. Vecht je eerst een weg naar het veiligheidscomplex en gebruik de teleporter. En dit kan meer naar uw zin zijn, vernietig de computer in de centrale administratie. Geen computer, geen krachtveld.","Klart du må. Først må du kjempe deg inn i sikkerhetskomplekset og bruke teleporteren. Og dette er kanskje mer etter din smak. Ødelegg datamaskinen i sentraladministrasjonen. Ingen datamaskin, intet kraftfelt.","Oczywiście, że tak. Najpierw pokonaj drogę do kompleksu bezpieczeństwa i użyj teleportera. A to może bardziej ci się spodoba, zniszcz komputer w centralnej administracji. Nie ma komputera, nie ma pola siłowego.","Ah, mas é claro que precisa. Primeiro, lute até o complexo de segurança e use o teletransportador. E acho que você vai gostar disto: destrua o computador na administração central. Sem computador, sem campo de força.",,"Oh, normal. Mai întâi, trebuie să te zbați să ajungi în complexul de securitate și să folosești teleportorul. Și asta s-ar putea să îți placă mai mult, distruge calculatorul din camera de administrare centrală. Niciun calculator, niciun câmp de forță.","О, не сомневаюсь. Для начала проберись в охранный комплекс и используй телепорт. И, что тебе должно больше понравиться, уничтожь компьютер в центральной администрации. Нет компьютера — нет силового поля.",,"Javisst, det måste du. Kämpa dig först in i säkerhetskomplexet och använd teleportern. Och det här kanske är mer till din smak, förstör datorn i centralförvaltningen. Ingen dator, inget kraftfält.","Tabii ki öldürmelisin. İlk olarak, güvenlik kompleksine girmek için savaş ve ışınlayıcıyı kullan. Ve bu daha çok hoşuna gidebilir, merkezi yönetimdeki bilgisayarı yok et. Bilgisayar yoksa, güç alanı da yok." +"Great, that sounds easy.",TXT_RPLY0_SCRIPT17_D10612_GREAT,〃,,,"Super, to zní snadně.","Fint, det lyder nemt.","Großartig, das klingt doch einfach.",,"Bonege, tio ŝajnas facila.","Genial, suena fácil.",,"Loistavaa, kuulostaa helpolta.","Bien, ça à l'air facile.","Remek, ez könnyűnek hangzik.","Ottimo, sembra facile.",そりゃいい、簡単そうだな。,"좋아, 쉬운 일인 것 같군.","Geweldig, dat klinkt gemakkelijk.","Flott, det høres enkelt ut.","Wspaniale, to brzmi łatwo.",Ótimo. Isso parece fácil.,,"Grozav, sună simplu.","Здорово, звучит легко.",,"Bra, det låter enkelt.","Harika, kulağa kolay geliyor." +"There's an advantage to destroying the computer, that's where the plans to the tower are kept. Can you say, five finger discount? Heh heh!",TXT_DLG_SCRIPT17_D12128_THERE,"〃 +(five-finger discount = theft)",,,Zničení toho počítače má výhodu: Na tom samém místě jsou uschovány plány věže. Co říkáš na takovou koupi za pět prstů? Haha!,"Der er en fordel ved at ødelægge computeren, det er der, hvor planerne til tårnet opbevares. Kan du sige, fem fingre rabat? Heh heh!","Es hätte sein Gutes, den Computer zu zerstören, denn dort sind auch die Pläne für den Turm. Kannst du sagen: Mitgehen lassen? Hehe!",,"Detrui la komputilon havas profiton: en ĝi estas konservitaj la planoj de la turo. Estus bedaŭrinde, ke ili malaperus... Ha ha!","Hay una ventaja al destruir el ordenador: ahí se guardan los planos de la torre. Suena ideal para gente con las manos largas... ¡Je, je!","Hay una ventaja al destruir la computadora: ahí se guardan los planos de la torre. Suena ideal para gente con las manos largas... ¡Je, je!","Tietokoneen tuhoamisessa on etunsa; siinä pidetään tornin piirustuksia. Sanottaisiinko, kaupanpäällisinä? Hehheh!",Ce serait avantageux de détruire l'ordinateur car c'est là qu'ils gardent les plans de la tour. C'est facile d'avoir ça gratuitement quand on peut juste les prendre comme ça!,"Van amúgy egy előnye a számítógép szobának, ott tartják ugyanis a torony terveit ott tárolják. Mi lenne mondjuk ha véletlen magaddal hoznád őket? heh heh!",Sarebbe vantaggioso distruggere il computer perché è lì che tengono i piani per la torre. È facile ottenerli gratuitamente quando puoi prenderli in questo modo! Heh heh!,"コンピューターを潰す利点はな、 奴等の塔へ送られる情報もそれに保管されている。 -それを万引き、とも言えるな?へヘッ!","컴퓨터를 파괴할 승산이 있을거야, 성채로 향하는 계획서가 있는 곳이니까. 물건 좀 빼돌려 본 적 있나? 헤헷!","Er is een voordeel aan het vernietigen van de computer, dat is waar de plannen om de toren te vernietigen worden bewaard. Kunt je zeggen, vijf vingers korting? Heh heh heh!","Det er en fordel med å ødelegge datamaskinen, det er der planene til tårnet er oppbevart. Kan du si, fem-finger-rabatt? Heh heh!","Jest jeszcze jedna zaleta zniszczenia komputera, to tam trzymane są plany wieży. Czy można powiedzieć, zniżka na pięć palców? Heh heh!","Há uma vantagem em destruir o computador. É nele onde ficam os planos da torre. É pegar e levar, hehehe!",,"Există un avantaj în distrugerea calculatorului, acolo sunt ținute schemele turnului. Poți spune, reducere la cinci degete? Ha ha!","В уничтожении компьютера есть ещё один плюс: планы башни хранятся там. Можно сказать, скидка на все сто? Хе-хе!",,"Bilgisayarı yok etmenin bir avantajı var, kulenin planları orada tutuluyor. Beş parmak indirimi diyebilir misin? Heh heh!" -Anything else?,TXT_RPLY0_SCRIPT17_D12128_ANYTH,〃,,,Ještě něco dalšího?,Er der andet?,Noch etwas?,,,¿Algo más?,,Onko jotain muuta?,Quoi d'autre?,Valami más még?,C'è dell'altro?,他にあるか?,뭐 다른건 없나?,Nog iets anders?,Noe annet?,Co jeszcze?,Mais alguma coisa?,,Altceva?,Что-нибудь ещё?,,Başka bir şey var mı? -"Oh well, word has it that the bailey's warehouse received a shipment of maulers, that's the weapon that vaporizes.",TXT_DLG_SCRIPT17_D13644_OHWEL,〃,,,"No, špitá se, že skladiště v opevnění obdrželo zásilku trhačů. To je ta zbraň, která vypařuje.","Nå ja, det siges, at Baileys lager har modtaget en sending maulers, det er det våben, der fordamper.","Nun, man sagt, dass im Lagerhaus eine Ladung Vernichter abgeliefert wurde, die Waffe die verdampft.",,,"Oh bueno, se dice que el almacén de la muralla ha recibido un envío de trituradores, es el arma que vaporiza.",,"No, tarina kertoo, että linnanpihan varastoon on saapunut erä moukareita; sitä asetta, joka haihduttaa.",Oh. La rumeur court que le dépôt du mur d'enceinte a reçu une cargaison de broyeurs. C'est l'arme qui vaporise les gens.,"Hát, az a hír járja, hogy érkezett pár közelharci fegyver a várfalnál levő raktárba. Ez az a fegyver ami rögtön elporlaszt.","Oh beh, ho sentito dire che il magazzino del bastione ha appena ricevuto un carico di Mauler, è l'arma che vaporizza.","そうだな、中庭の倉庫にマウラーが納品されたと +それを万引き、とも言えるな?へヘッ!","컴퓨터를 파괴할 승산이 있을거야, 성채로 향하는 계획서가 있는 곳이니까. 물건 좀 빼돌려 본 적 있나? 헤헷!","Er is een voordeel aan het vernietigen van de computer, dat is waar de plannen om de toren te vernietigen worden bewaard. Kunt je zeggen, vijf vingers korting? Heh heh heh!","Det er en fordel med å ødelegge datamaskinen, det er der planene til tårnet er oppbevart. Kan du si, fem-finger-rabatt? Heh heh!","Jest jeszcze jedna zaleta zniszczenia komputera, to tam trzymane są plany wieży. Czy można powiedzieć, zniżka na pięć palców? Heh heh!","Há uma vantagem em destruir o computador. É nele onde ficam os planos da torre. É pegar e levar, hehehe!",,"Există un avantaj în distrugerea calculatorului, acolo sunt ținute schemele turnului. Poți spune, reducere la cinci degete? Ha ha!","В уничтожении компьютера есть ещё один плюс: планы башни хранятся там. Можно сказать, скидка на все сто? Хе-хе!",,"Det finns en fördel med att förstöra datorn, det är där ritningarna till tornet förvaras. Kan du säga femfingerrabatt? Heh heh!","Bilgisayarı yok etmenin bir avantajı var, kulenin planları orada tutuluyor. Beş parmak indirimi diyebilir misin? Heh heh!" +Anything else?,TXT_RPLY0_SCRIPT17_D12128_ANYTH,〃,,,Ještě něco dalšího?,Er der andet?,Noch etwas?,,Ĉu io alia?,¿Algo más?,,Onko jotain muuta?,Quoi d'autre?,Valami más még?,C'è dell'altro?,他にあるか?,뭐 다른건 없나?,Nog iets anders?,Noe annet?,Co jeszcze?,Mais alguma coisa?,,Altceva?,Что-нибудь ещё?,,Något annat?,Başka bir şey var mı? +"Oh well, word has it that the bailey's warehouse received a shipment of maulers, that's the weapon that vaporizes.",TXT_DLG_SCRIPT17_D13644_OHWEL,〃,,,"No, špitá se, že skladiště v opevnění obdrželo zásilku trhačů. To je ta zbraň, která vypařuje.","Nå ja, det siges, at Baileys lager har modtaget en sending maulers, det er det våben, der fordamper.","Nun, man sagt, dass im Lagerhaus eine Ladung Vernichter abgeliefert wurde, die Waffe die verdampft.",,"Nu, oni diras, ke la ĉi-loka magazeno ricevis mendon de polvigiloj, neniigaj armiloj.","Bueno, se dice que el almacén de por aquí ha recibido un envío de trituradores, que son unas armas que pulverizan.","Bueno, se dice que el almacén de por aquí recibió un envío de trituradores, que son unas armas que pulverizan.","No, tarina kertoo, että linnanpihan varastoon on saapunut erä moukareita; sitä asetta, joka haihduttaa.",Oh. La rumeur court que le dépôt du mur d'enceinte a reçu une cargaison de broyeurs. C'est l'arme qui vaporise les gens.,"Hát, az a hír járja, hogy érkezett pár közelharci fegyver a várfalnál levő raktárba. Ez az a fegyver ami rögtön elporlaszt.","Oh beh, ho sentito dire che il magazzino del bastione ha appena ricevuto un carico di Mauler, è l'arma che vaporizza.","そうだな、中庭の倉庫にマウラーが納品されたと 聞いた。その威力は相手を消滅させられる程だと。","음, 듣자 하니 성안 쪽 격납고에 마울러가 입고되었다더군. 뭐든지 날려버리는 무기 말이야. - \cy흠. 이유 없이 그런 소문이 났을 리는 없을 테고... 나도 그 무기 하나만 가져다줘.","Nou ja, er wordt gezegd dat het magazijn van de bailey een zending maulers heeft ontvangen, dat is het wapen dat verdampt.",Ryktene sier at Borggårdens lager har fått en sending maulere. Det er våpenet som fordamper.,"Podobno do magazynu Bailey'a dotarła dostawa maulerów, czyli broni, która paruje.","Bem, dizem que o depósito recebeu um envio de desintegradores. Aquela arma que...desintegra.",,"Păi, vorba spune că depozitul din curtea interioară a primit un pachet de schiloditoare, asta e arma care vapozirează.","Скажем так: есть слух, что склад крепости получил партию Истязателей: оружия, которое «испепеляет».",,"Bailey'nin deposuna parçalayıcı sevkiyatı yapıldığı söyleniyor, buharlaştıran bir silah." -"Is that it, now?",TXT_RPLY0_SCRIPT17_D13644_ISTHA,〃,,,Je to už všechno?,Er det det nu?,War es das jetzt?,,,"Con que eso es, ¿eh?",,Ja onko siinä nyt kaikki?,Vraiment?,Mi van már megint?,Tutto qui?,それはまだあるんだな?,이게 전부지?,"Is dat het, nu?",Er det alt?,"To wszystko, teraz?",Só isso?,,"Asta e, deci?",Теперь всё?,,Bu kadar mı yani? -"Don't you know the meaning of the words ""get lost""?",TXT_DLG_SCRIPT17_D15160_DONTY,〃,,,Neznáš význam slova „zmizni“?,"Kender du ikke betydningen af ordene ""forsvind""?",Sagen dir die Worte „Verzieh dich“ etwas?,,,¿No sabes lo que significa la palabra Piérdete?,,"Etkö tunne sanojen ""ala laputtaa"" merkitystä?",Vous ne connaîssez pas le sens du mot: « Dégage?»,"Melyik részét nem érted a ""húzz el""-nek?","Non conosci il significato delle parole, ""ora di andare""?",次の話はバレる前に'去れ'か?,"자네, “꺼져.”가 무슨 뜻인지는 알지?","Weet je niet wat de betekenis is van de woorden ""verdwalen""?","Vet du ikke hva som menes med ""stikk""?","Nie znasz znaczenia słowa ""zgubić się""?","Você não sabe o que significa a expressão ""se manda""?",,"Nu cunoști semnificația cuvântului ""dispari""?",Ты не знаешь значения слова «исчезни»?,,Kaybol kelimesinin anlamını bilmiyor musun? -Talk to Quincy first. I'm not allowed to help anyone unless he says it's ok.,TXT_DLG_SCRIPT17_D16676_TALKT,MAP17: Hospital → Assistant,,,Promluvte si nejprve s Quincym. Já nemůžu nikomu pomáhat dokud to nepovolí.,"Tal med Quincy først. Jeg må ikke hjælpe nogen, medmindre han siger, at det er i orden.","Rede erst mit Quincy. Ich darf mit niemanden reden, solange er nicht sein OK gegeben hat.",,,Habla con Quincy primero. No se me permite ayudar a nadie a menos que él lo diga.,,"Puhu ensin Quincylle. En saa auttaa ketään, ellei hän anna siihen lupaa.",Parlez à Quincy d'abord. Je ne suis pas autorisé à aider qui que ce soit sans son autorisation.,"Beszélj Quincyvel először. Nem beszélhetek senkivel, amíg nem engedélyezi.",Parla con Quincy prima. Non sono autorizzato ad aiutare nessuno se prima lui non da il permesso.,"先にクインシーと話を。彼から許可を -得られない限りお助けすることは出来ません。",퀸시에게 먼저 물어보세요. 전 그가 괜찮다 하지 않는다면 아무것도 도울 수 없습니다.,"Praat eerst met Quincy. Ik mag niemand helpen, tenzij hij zegt dat het goed is.",Snakk med Quincy først. Jeg har ikke lov til å hjelpe noen med mindre han sier det er ok.,"Najpierw porozmawiaj z Quincy. Nie wolno mi nikomu pomagać, dopóki on nie powie, że to jest w porządku.",Fale com o Quincy primeiro. Não posso ajudar ninguém enquanto ele não autorizar.,,Vorbește cu Quincy mai întâi. Nu am permisiunea să ajut pe nimeni până nu spune că e în regulă.,"Сперва поговори с Куинси. Мне не позволено помогать кому-либо, пока он не разрешит.",,Önce Quincy ile konuş. O izin vermedikçe kimseye yardım edemem. -How how can I help you today?,TXT_DLG_SCRIPT17_D18192_HOWHO,〃,,,Jak vám mohu dnes pomoci?,Hvordan kan jeg hjælpe dig i dag?,Wie kann ich dir heute helfen?,,Kiel mi helpu vin hodiaŭ?,¿Cómo puedo ayudarte hoy?,,Miten voin olla avuksi tänään?,Comment puis-je vous aider aujourd'hui?,Ma miben segíthetek?,Come posso aiutarti oggi?,本日は何かお困りで?,오늘은 어떻게 도와드릴까요?,Hoe kan ik je vandaag helpen?,Hvordan kan jeg hjelpe deg i dag?,Jak mogę ci dzisiaj pomóc?,Como posso ajudá-lo hoje?,,Cu ce te pot ajuta azi?,Чем могу быть полезен?,,Bugün sana nasıl yardım edebilirim? -Med patch,TXT_RPLY0_SCRIPT17_D18192_MEDPA,〃,,,Obvazy,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekäärettä.,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster,Bandaż,Compressa médica,,Trusă de prim-ajutor.,Бинтами,,Med yama -Here's your patch.,TXT_RYES0_SCRIPT17_D18192_HERES,〃,,,Tady jsou.,Her er dit plaster.,Hier ist deine Bandage.,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä kääreesi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これをどうぞ。,"의료 붕대 하나, 여기 있습니다.",Hier is je patch.,Her er lappen din.,Oto twój bandaż.,Aqui está sua compressa.,,Aici e trusa.,Вот твой набор бинтов.,,İşte yaman. -That is 15 gold my friend.,TXT_RNO0_SCRIPT17_D18192_THATI,〃,,,"To je patnáct zlatých, příteli.","Det er 15 guld, min ven.","Das macht 15 Gold, mein Freund.",,"Vi bezonas 15 pecojn, amiko.","Son 15 de oro, amigo.",,"Se saisi olla 15 kolikkoa, ystäväiseni.","15 pièces pour ça, mon ami.",Az bizony 15 arany lesz barátom.,Sono 15 pezzi d'oro amico mio.,15 ゴールド必要です。,"그건 15 골드입니다, 친구.","Dat is 15 goud, mijn vriend.","Det er 15 gull, min venn.","To jest 15 złota, mój przyjacielu.","Custa 15 moedas de ouro, meu amigo.",,Costă 15 monezi amice.,"Они стоят 15 золотых, друг.",,Bu 15 altın dostum. -Medical kit,TXT_RPLY1_SCRIPT17_D18192_MEDIC,〃,,,Lékárničku,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku.,Kit médical.,Elsősegély doboz.,Kit medico,医療用キット,구급 키트,Medische kit,Medisinsk utstyr,Zestaw medyczny,Kit médico,,Kit de prim-ajutor.,Аптечкой,,Tıbbi kit -Here's your medical kit.,TXT_RYES1_SCRIPT17_D18192_HERES,〃,,,Tady je.,Her er dit medicinske kit.,Hier ist dein Verbandskasten,,Jen via sukurkesto.,Aquí tienes tu botiquín.,,Tässä lääkintälaukkusi.,Voilà votre kit médical.,Itt az elsősegélydobozod.,Ecco il tuo kit medico.,こちらが 医療用キットです。,구급 키트입니다. 잘 쓰시길.,Hier is je medische uitrusting.,Her er førstehjelpsskrinet ditt.,Oto twój zestaw medyczny.,Aqui está o seu kit médico,,Aici e kitul.,Вот твоя аптечка.,,İşte tıbbi çantan. -You're a bit low on funds for that.,TXT_RNO1_SCRIPT17_D18192_YOURE,〃,,,Tu si nemůžete dovolit.,Du har lidt for få midler til det.,Du hast zu wenig Geld dafür.,,Mankas mono al vi.,Estás algo falto de dinero.,,Sinulla on varat hieman vähissä siihen.,Vous manquez d'argent pour ça.,Nincs elég pénzed ehhez.,Sei un pò a corto di fondi per quello.,その為の資金が少し足りません。,그거 사기엔 자금이 부족한 듯.,Je hebt daar een beetje weinig geld voor.,Du har litt lite penger til det.,Masz na to trochę mało funduszy.,Você está um pouco mal de dinheiro pra isso.,,Cam puțini bani pentru aia.,Тебе на это не хватает средств.,,Bunun için biraz az paran var. -Field surgery kit,TXT_RPLY2_SCRIPT17_D18192_FIELD,〃,,,Chirurgickou soupravu,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku.,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트.,Veld chirurgie kit,Kirurgisett,Zestaw do chirurgii polowej,Kit de cirurgia,,Kit chirurgical de teren.,Медкомплектом,,Saha ameliyat kiti -"One field surgery kit, done.",TXT_RYES2_SCRIPT17_D18192_ONEFI,〃,,,"Jedna souprava, zde.","Et kirurgisæt, færdig.","Ein Erste-Hilfe-Kasten, kommt sofort.",,Kirurgia kesto. Farite.,Un kit quirúrgico. Listo.,,"Yksi kirurgilaukku, noin.","Un kit de chirurgie, voilà.",Egy műtő felszerelés itt is van.,"Un kit chirurgico, eccolo qua.",野外用手術キット一丁。,수술 키트 하나 여기있습니다.,"Eén veldoperatiekit, klaar.","Ett kirurgisk sett, ferdig.","Jeden zestaw do chirurgii polowej, zrobione.",Um kit de cirurgia saindo,,"Un kit chirurgical de teren, gata.",Один медкомплект. Держи.,,"Bir saha ameliyat kiti, tamamdır." + \cy흠. 이유 없이 그런 소문이 났을 리는 없을 테고... 나도 그 무기 하나만 가져다줘.","Nou ja, er wordt gezegd dat het magazijn van de bailey een zending maulers heeft ontvangen, dat is het wapen dat verdampt.",Ryktene sier at Borggårdens lager har fått en sending maulere. Det er våpenet som fordamper.,"Podobno do magazynu Bailey'a dotarła dostawa maulerów, czyli broni, która paruje.","Bem, dizem que o depósito recebeu um envio de desintegradores. Aquela arma que...desintegra.",,"Păi, vorba spune că depozitul din curtea interioară a primit un pachet de schiloditoare, asta e arma care vapozirează.","Скажем так: есть слух, что склад крепости получил партию Истязателей: оружия, которое «испепеляет».",,"Nåja, ryktet säger att Baileys lager har fått en leverans av maulers, det är vapnet som förångar.","Bailey'nin deposuna parçalayıcı sevkiyatı yapıldığı söyleniyor, buharlaştıran bir silah." +"Is that it, now?",TXT_RPLY0_SCRIPT17_D13644_ISTHA,〃,,,Je to už všechno?,Er det det nu?,War es das jetzt?,,"Temas pri tio, ĉu?","Conque eso es, ¿eh?",,Ja onko siinä nyt kaikki?,Vraiment?,Mi van már megint?,Tutto qui?,それはまだあるんだな?,이게 전부지?,"Is dat het, nu?",Er det alt?,"To wszystko, teraz?",Só isso?,,"Asta e, deci?",Теперь всё?,,Är det allt?,Bu kadar mı yani? +"Don't you know the meaning of the words ""get lost""?",TXT_DLG_SCRIPT17_D15160_DONTY,〃,,,Neznáš význam slova „zmizni“?,"Kender du ikke betydningen af ordene ""forsvind""?",Sagen dir die Worte „Verzieh dich“ etwas?,,Ĉu vi ne scias la signifon de «malaperu»?,¿No sabes lo que significa la palabra «esfúmate»?,,"Etkö tunne sanojen ""ala laputtaa"" merkitystä?",Vous ne connaîssez pas le sens du mot: « Dégage?»,"Melyik részét nem érted a ""húzz el""-nek?","Non conosci il significato delle parole, ""ora di andare""?",次の話はバレる前に'去れ'か?,"자네, “꺼져.”가 무슨 뜻인지는 알지?","Weet je niet wat de betekenis is van de woorden ""verdwalen""?","Vet du ikke hva som menes med ""stikk""?","Nie znasz znaczenia słowa ""zgubić się""?","Você não sabe o que significa a expressão ""se manda""?",,"Nu cunoști semnificația cuvântului ""dispari""?",Ты не знаешь значения слова «исчезни»?,,"Vet du inte vad ordet ""försvinna"" betyder?",Kaybol kelimesinin anlamını bilmiyor musun? +Talk to Quincy first. I'm not allowed to help anyone unless he says it's ok.,TXT_DLG_SCRIPT17_D16676_TALKT,MAP17: Hospital → Assistant,,,Promluvte si nejprve s Quincym. Já nemůžu nikomu pomáhat dokud to nepovolí.,"Tal med Quincy først. Jeg må ikke hjælpe nogen, medmindre han siger, at det er i orden.","Rede erst mit Quincy. Ich darf mit niemanden reden, solange er nicht sein OK gegeben hat.",,Vi unue parolu al Kvincio. Mi rajtas helpi neniun ĝis li aprobos tion.,Habla con Quincy primero. No se me permite ayudar a nadie a menos que él lo diga.,,"Puhu ensin Quincylle. En saa auttaa ketään, ellei hän anna siihen lupaa.",Parlez à Quincy d'abord. Je ne suis pas autorisé à aider qui que ce soit sans son autorisation.,"Beszélj Quincyvel először. Nem beszélhetek senkivel, amíg nem engedélyezi.",Parla con Quincy prima. Non sono autorizzato ad aiutare nessuno se prima lui non dà il permesso.,"先にクインシーと話を。彼から許可を +得られない限りお助けすることは出来ません。",퀸시에게 먼저 물어보세요. 전 그가 괜찮다 하지 않는다면 아무것도 도울 수 없습니다.,"Praat eerst met Quincy. Ik mag niemand helpen, tenzij hij zegt dat het goed is.",Snakk med Quincy først. Jeg har ikke lov til å hjelpe noen med mindre han sier det er ok.,"Najpierw porozmawiaj z Quincy. Nie wolno mi nikomu pomagać, dopóki on nie powie, że to jest w porządku.",Fale com o Quincy primeiro. Não posso ajudar ninguém enquanto ele não autorizar.,,Vorbește cu Quincy mai întâi. Nu am permisiunea să ajut pe nimeni până nu spune că e în regulă.,"Сперва поговори с Куинси. Мне не позволено помогать кому-либо, пока он не разрешит.",,Prata med Quincy först. Jag får inte hjälpa någon om inte han säger att det är okej.,Önce Quincy ile konuş. O izin vermedikçe kimseye yardım edemem. +How how can I help you today?,TXT_DLG_SCRIPT17_D18192_HOWHO,〃,,,Jak vám mohu dnes pomoci?,Hvordan kan jeg hjælpe dig i dag?,Wie kann ich dir heute helfen?,,Kiel mi helpu vin hodiaŭ?,¿Cómo puedo ayudarte hoy?,,Miten voin olla avuksi tänään?,Comment puis-je vous aider aujourd'hui?,Ma miben segíthetek?,Come posso aiutarti oggi?,本日は何かお困りで?,오늘은 어떻게 도와드릴까요?,Hoe kan ik je vandaag helpen?,Hvordan kan jeg hjelpe deg i dag?,Jak mogę ci dzisiaj pomóc?,Como posso ajudá-lo hoje?,,Cu ce te pot ajuta azi?,Чем могу быть полезен?,,Hur kan jag hjälpa dig idag?,Bugün sana nasıl yardım edebilirim? +Med patch,TXT_RPLY0_SCRIPT17_D18192_MEDPA,〃,,,Obvazy,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekäärettä.,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster,Bandaż,Compressa médica,,Trusă de prim-ajutor.,Бинтами,,Medicinsk plåster,Med yama +Here's your patch.,TXT_RYES0_SCRIPT17_D18192_HERES,〃,,,Tady jsou.,Her er dit plaster.,Hier ist deine Bandage.,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä kääreesi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これをどうぞ。,"의료 붕대 하나, 여기 있습니다.",Hier is je patch.,Her er lappen din.,Oto twój bandaż.,Aqui está sua compressa.,,Aici e trusa.,Вот твой набор бинтов.,,Här är ditt plåster.,İşte yaman. +That is 15 gold my friend.,TXT_RNO0_SCRIPT17_D18192_THATI,〃,,,"To je patnáct zlatých, příteli.","Det er 15 guld, min ven.","Das macht 15 Gold, mein Freund.",,"Ili kostas dek kvin +da oro, amiko.","Son quince de oro, amigo.",,"Se saisi olla 15 kolikkoa, ystäväiseni.","15 pièces pour ça, mon ami.",Az bizony 15 arany lesz barátom.,Sono 15 pezzi d'oro amico mio.,15 ゴールド必要です。,"그건 15 골드입니다, 친구.","Dat is 15 goud, mijn vriend.","Det er 15 gull, min venn.","To jest 15 złota, mój przyjacielu.","Custa 15 moedas de ouro, meu amigo.",,Costă 15 monezi amice.,"Они стоят 15 золотых, друг.",,"Det är 15 guld, min vän.",Bu 15 altın dostum. +Medical kit,TXT_RPLY1_SCRIPT17_D18192_MEDIC,〃,,,Lékárničku,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku.,Kit médical.,Elsősegély doboz.,Kit medico,医療用キット,구급 키트,Medische kit,Medisinsk utstyr,Zestaw medyczny,Kit médico,,Kit de prim-ajutor.,Аптечкой,,Medicinsk utrustning,Tıbbi kit +Here's your medical kit.,TXT_RYES1_SCRIPT17_D18192_HERES,〃,,,Tady je.,Her er dit medicinske kit.,Hier ist dein Verbandskasten,,Jen via sukurkesto.,Aquí tienes tu botiquín.,,Tässä lääkintälaukkusi.,Voilà votre kit médical.,Itt az elsősegélydobozod.,Ecco il tuo kit medico.,こちらが 医療用キットです。,구급 키트입니다. 잘 쓰시길.,Hier is je medische uitrusting.,Her er førstehjelpsskrinet ditt.,Oto twój zestaw medyczny.,Aqui está o seu kit médico,,Aici e kitul.,Вот твоя аптечка.,,Här är ditt medicinska utrustning.,İşte tıbbi çantan. +You're a bit low on funds for that.,TXT_RNO1_SCRIPT17_D18192_YOURE,〃,,,Tu si nemůžete dovolit.,Du har lidt for få midler til det.,Du hast zu wenig Geld dafür.,,Mankas mono al vi.,Estás algo falto de dinero.,,Sinulla on varat hieman vähissä siihen.,Vous manquez d'argent pour ça.,Nincs elég pénzed ehhez.,Sei un po' a corto di fondi per quello.,その為の資金が少し足りません。,그거 사기엔 자금이 부족한 듯.,Je hebt daar een beetje weinig geld voor.,Du har litt lite penger til det.,Masz na to trochę mało funduszy.,Você está um pouco mal de dinheiro pra isso.,,Cam puțini bani pentru aia.,Тебе на это не хватает средств.,,Du har lite ont om pengar för det.,Bunun için biraz az paran var. +Field surgery kit,TXT_RPLY2_SCRIPT17_D18192_FIELD,〃,,,Chirurgickou soupravu,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku.,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트.,Veld chirurgie kit,Kirurgisett,Zestaw do chirurgii polowej,Kit de cirurgia,,Kit chirurgical de teren.,Медкомплектом,,Fältkirurgisk utrustning,Saha ameliyat kiti +"One field surgery kit, done.",TXT_RYES2_SCRIPT17_D18192_ONEFI,〃,,,"Jedna souprava, zde.","Et kirurgisæt, færdig.","Ein Erste-Hilfe-Kasten, kommt sofort.",,Kirurgia kesto. Farite.,Un kit quirúrgico. Listo.,,"Yksi kirurgilaukku, noin.","Un kit de chirurgie, voilà.",Egy műtő felszerelés itt is van.,"Un kit chirurgico, eccolo qua.",野外用手術キット一丁。,수술 키트 하나 여기있습니다.,"Eén veldoperatiekit, klaar.","Ett kirurgisk sett, ferdig.","Jeden zestaw do chirurgii polowej, zrobione.",Um kit de cirurgia saindo,,"Un kit chirurgical de teren, gata.",Один медкомплект. Держи.,,"Ett fältkirurgiskt utrustning, klart.","Bir saha ameliyat kiti, tamamdır." Come back when you have money!,TXT_RNO2_SCRIPT17_D18192_COMEB,〃,,,"Vrať se, až budeš mít peníze!","Kom tilbage, når du har penge!","Komm wieder, wenn du etwas Geld hast.",,"Revenu kiam vi havos monon!","¡Vuelve cuando -tengas dinero!",,"Tule takaisin, kun sinulla on rahaa!",Revenez quand vous avez des sous!,"Gyere vissza, ha már van elég pénzed.",Torna quando avrai del denaro!,余裕がある時にまたどうぞ!,돈이 좀 있을 때 돌아와요!,Kom terug als je geld hebt!,Kom tilbake når du har penger!,"Wróć, gdy będziesz miał pieniądze!",Volte quando tiver dinheiro!,,Întoarce-te când ai destui bani!,Возвращайся с деньгами!,,Paran olduğunda geri gel! -What is it?,TXT_DLG_SCRIPT18_D0_WHATI,MAP18: Yellow guard,,,Co je?,Hvad er det?,Was gibt es?,,,¿Qué pasa?,,Mikä on?,Vous voulez quoi?,Az meg mi?,Che cos'è?,何事だ?,무슨 일이냐?,Wat is het?,Hva er det?,Co to jest?,O que foi?,,Ce e?,Что тебе нужно?,,Ne oldu? -Just looking around.,TXT_RPLY0_SCRIPT18_D0_JUSTL,〃,,,Jen se poohlížím.,Jeg kigger bare rundt.,Ich schaue mich bloß um.,,,Solo estoy mirando.,,Ihan vain katselen.,Je fais juste un tour.,Csak nézelődök.,Sto soltando guardando.,見周りしている。,그냥 둘러보는 중이었습니다.,Gewoon rondkijken.,Jeg ser meg bare rundt.,Rozglądam się.,Só dando uma olhada.,,Doar mă uit împrejur.,Просто осматриваюсь.,,Sadece etrafa bakıyorum. -Just keep out of the way.,TXT_RYES0_SCRIPT18_D0_JUSTK,〃,,,Prostě se drž z cesty.,Bare hold dig ude af vejen.,Sei einfach niemandem im Weg.,,,Mantente fuera de mi camino.,,Kunhan vain pysyt pois tieltä.,Restez hors du chemin.,Csak ne legyél láb alatt.,Basta che non ti metti in mezzo.,この先は立入禁止だ。,그럼 방해하지마.,Blijf gewoon uit de weg.,Bare hold deg unna.,Trzymaj się z dala od drogi.,Apenas fique fora do caminho.,,Doar nu sta în cale.,Просто не путайся под ногами.,,Yoldan uzak dur. -The Templars will be here soon to pick up their new maulers. If you get in their way you're a dead man.,TXT_DLG_SCRIPT18_D1516_THETE,〃,,,"Templáři tu brzy budou vyzvednout si své nové trhače. Jestli se jim připleteš pod nohy, jsi mrtvý.","Tempelridderne kommer snart og henter deres nye maulere. Hvis du kommer i vejen for dem, er du en død mand.","Die Templer werden bald hier sein, um ihre neuen Vernichter abzuholen. Wenn du ihnen im Weg bist, dann bist du ein toter Mann.",,,Los templarios estarán aquí pronto para recoger sus nuevos trituradores. Si te interpones en su camino eres hombre muerto.,,"Temppeliherrat tulevat tänne pian noutamaan uudet moukarinsa. Jos menet heidän tielleen, olet mennyttä.","Les templiers vont venier chercher les nouveaux broyeurs. Si vous les gênez, vous êtes mort.","A Keresztesek rögtön itt lesznek a kézi fegyvereikért. Ha az utukba állsz, halál fia vagy.",I Templari arriveranno presto qui a prendere i loro nuovi Mauler. Se ti trovano qui sei un uomo morto.,"新しいマウラーズを得たテンプル騎士団が +tengas dinero!",,"Tule takaisin, kun sinulla on rahaa!",Revenez quand vous avez des sous!,"Gyere vissza, ha már van elég pénzed.",Torna quando avrai del denaro!,余裕がある時にまたどうぞ!,돈이 좀 있을 때 돌아와요!,Kom terug als je geld hebt!,Kom tilbake når du har penger!,"Wróć, gdy będziesz miał pieniądze!",Volte quando tiver dinheiro!,,Întoarce-te când ai destui bani!,Возвращайся с деньгами!,,Kom tillbaka när du har pengar!,Paran olduğunda geri gel! +What is it?,TXT_DLG_SCRIPT18_D0_WHATI,MAP18: Yellow guard,,,Co je?,Hvad er det?,Was gibt es?,,Kio okazas?,¿Qué pasa?,,Mikä on?,Vous voulez quoi?,Az meg mi?,Che cos'è?,何事だ?,무슨 일이냐?,Wat is het?,Hva er det?,Co to jest?,O que foi?,,Ce e?,Что тебе нужно?,,Vad är det för nåt?,Ne oldu? +Just looking around.,TXT_RPLY0_SCRIPT18_D0_JUSTL,〃,,,Jen se poohlížím.,Jeg kigger bare rundt.,Ich schaue mich bloß um.,,Mi nur pririgardas.,Solo estoy mirando.,,Ihan vain katselen.,Je fais juste un tour.,Csak nézelődök.,Sto soltando guardando.,見周りしている。,그냥 둘러보는 중이었습니다.,Gewoon rondkijken.,Jeg ser meg bare rundt.,Rozglądam się.,Só dando uma olhada.,,Doar mă uit împrejur.,Просто осматриваюсь.,,Jag tittar bara runt.,Sadece etrafa bakıyorum. +Just keep out of the way.,TXT_RYES0_SCRIPT18_D0_JUSTK,〃,,,Prostě se drž z cesty.,Bare hold dig ude af vejen.,Sei einfach niemandem im Weg.,,Vi nur ne ĝenu nin.,Pero no nos estorbes.,,Kunhan vain pysyt pois tieltä.,Restez hors du chemin.,Csak ne legyél láb alatt.,Basta che non ti metti in mezzo.,この先は立入禁止だ。,그럼 방해하지마.,Blijf gewoon uit de weg.,Bare hold deg unna.,Trzymaj się z dala od drogi.,Apenas fique fora do caminho.,,Doar nu sta în cale.,Просто не путайся под ногами.,,Håll dig bara ur vägen.,Yoldan uzak dur. +The Templars will be here soon to pick up their new maulers. If you get in their way you're a dead man.,TXT_DLG_SCRIPT18_D1516_THETE,〃,,,"Templáři tu brzy budou vyzvednout si své nové trhače. Jestli se jim připleteš pod nohy, jsi mrtvý.","Tempelridderne kommer snart og henter deres nye maulere. Hvis du kommer i vejen for dem, er du en død mand.","Die Templer werden bald hier sein, um ihre neuen Vernichter abzuholen. Wenn du ihnen im Weg bist, dann bist du ein toter Mann.",,"La templanoj baldaŭ venos por ricevi siajn novajn polvigilojn; se vi miksos vin, vi mortos.",Los templarios estarán aquí pronto para recibir sus nuevos trituradores; si los molestas eres hombre muerto.,Los templarios van a estar aquí pronto para recibir sus nuevos trituradores; si los molestas eres hombre muerto.,"Temppeliherrat tulevat tänne pian noutamaan uudet moukarinsa. Jos menet heidän tielleen, olet mennyttä.","Les templiers vont venier chercher les nouveaux broyeurs. Si vous les gênez, vous êtes mort.","A Keresztesek rögtön itt lesznek a kézi fegyvereikért. Ha az utukba állsz, halál fia vagy.",I Templari arriveranno presto qui a prendere i loro nuovi Mauler. Se ti trovano qui sei un uomo morto.,"新しいマウラーズを得たテンプル騎士団が すぐにでもここに来る。長生きしたければ -邪魔をしようと思わない方がいい。",템플러가 곧 새 마울러를 가지러 올 거야. 그들을 방해하면 넌 죽은 목숨이야.,"De Tempeliers zullen hier binnenkort zijn om hun nieuwe maulers op te halen. Als je hen in de weg staat, ben je een dode man.","Tempelridderne kommer snart for å hente sine nye maulere. Kommer du i veien for dem, er du en død mann.","Templariusze będą tu niedługo po swoje nowe maulery. Jeśli wejdziesz im w drogę, będziesz martwy.","Os Templários estarão aqui logo para pegar seus novos desintegradores. Se você se meter no caminho deles, você é um homem morto.",,Templierii vor fi curând aici pentru a ridica schiloditoarele. Dacă le stai în cale ești mort.,"Храмовники скоро придут сюда забрать свои новые истязатели. Если попадёшься им на пути, станешь покойником.",,Tapınakçılar yeni parçalayıcılarını almak için yakında burada olacaklar. Eğer yollarına çıkarsan ölürsün. -Maulers?,TXT_RPLY0_SCRIPT18_D1516_MAULE,〃,,,Trhače?,Maulers?,Vernichter?,,,¿Trituradores?,,Moukarit?,Des broyeurs?,Kézi fegyver?,Mauler?,マウラーズ?,마울러?,Maulers?,Maulere?,Maulery?,Desintegradores?,,Schiloditoare?,Истязатели?,,Parçalayıcılar? -The Templar's favorite weapon.,TXT_RYES0_SCRIPT18_D1516_THETE,〃,,The templar's favourite weapon.,Oblíbená zbraň templářů.,Tempelriddernes yndlingsvåben.,Die Lieblingswaffe der Templer.,,,El arma favorita de los templarios.,,Temppeliherrojen lempiase.,L'arme favorite du templier.,A keresztesek kedvenc fegyvere.,È l'arma preferita dei Templari.,騎士団に人気の兵器だ。,템플러가 제일 좋아하는 무기야.,Het favoriete wapen van de Tempeliers.,Tempelriddernes favorittvåpen.,Ulubiona broń Templariuszy.,A arma favorita dos Templários.,,Arma preferată a Templierilor.,Их любимое оружие.,,Tapınakçıların en sevdiği silah. -They came in earlier. That's what all the security's about. I got a chance to look at them when I locked up. Nobody's supposed to go in or out of there until the rest of the platoon comes to claim their weapons.,TXT_DLG_SCRIPT18_D3032_THEYC,〃,,,"Dorazily už dřív, proto ta ochranka. Měl jsem možnost se na ně podívat, když jsem zamykal. Nikdo nesmí vejít dovnitř ani ven dokud si zbytek čety nepřijde pro zbraně.","De kom ind tidligere. Det er derfor, der er så meget sikkerhed. Jeg fik en chance for at se dem, da jeg låste af. Ingen må gå ind eller ud derfra, før resten af delingen kommer for at hente deres våben.","Die sind heute früh hier eingetroffen. Daher all die Wachen. Ich konnte aber mal einen Blick darauf werfen. Niemand darf da rein, bevor die Waffen an die Truppen verteilt worden sind.",,,Vinieron antes. Para eso toda esta seguridad. Tuve una oportunidad de verlos cuando cerraba. Se supone que nadie puede entrar o salir hasta que el resto del pelotón venga a pedir sus armas.,,"He kävivät aiemmin. Siitä näissä kaikissa turvatoimissa on kyse. Sain mahdollisuuden vilkaista niitä, kun lukitsin paikkoja. Kukaan ei saa kulkea sisään eikä ulos, ennen kuin loput joukkueesta tulee noutamaan aseensa.",Ils sont passés plus tôt. C'est pour ça qu'il y a autant de personnel de sécurité. J'ai eu l'opportunité de les voire quand je suis parti verouiller les accès. Personne n'est sensé entrer ou sortir tant que la section n'a pas fini de récupérer leur armes.,"Most hamarabb jöttek. Emiatt van akkora biztonsági cécó. Jó megnéztem magamnak őket amikor bezártam. Senki nem mehet se ki se be, míg a szakasz be nem megy a fegyvereiért.",Sono arrivati da poco. Ecco perché c'è così tanta sicurezza. Ho avuto l'opportunità di vederli quando sono uscito per bloccare gli accessi. Nessuno dovrebbe entrare o uscire finché il plotone non ha finito di raccogliere le armi.,"以前所属したばかりだ。 +邪魔をしようと思わない方がいい。",템플러가 곧 새 마울러를 가지러 올 거야. 그들을 방해하면 넌 죽은 목숨이야.,"De Tempeliers zullen hier binnenkort zijn om hun nieuwe maulers op te halen. Als je hen in de weg staat, ben je een dode man.","Tempelridderne kommer snart for å hente sine nye maulere. Kommer du i veien for dem, er du en død mann.","Templariusze będą tu niedługo po swoje nowe maulery. Jeśli wejdziesz im w drogę, będziesz martwy.","Os Templários estarão aqui logo para pegar seus novos desintegradores. Se você se meter no caminho deles, você é um homem morto.",,Templierii vor fi curând aici pentru a ridica schiloditoarele. Dacă le stai în cale ești mort.,"Храмовники скоро придут сюда забрать свои новые истязатели. Если попадёшься им на пути, станешь покойником.",,Templarna kommer snart att vara här för att hämta sina nya maulers. Om du kommer i deras väg är du en död man.,Tapınakçılar yeni parçalayıcılarını almak için yakında burada olacaklar. Eğer yollarına çıkarsan ölürsün. +Maulers?,TXT_RPLY0_SCRIPT18_D1516_MAULE,〃,,,Trhače?,Maulers?,Vernichter?,,Ĉu polvigiloj?,¿Trituradores?,,Moukarit?,Des broyeurs?,Kézi fegyver?,Mauler?,マウラーズ?,마울러?,Maulers?,Maulere?,Maulery?,Desintegradores?,,Schiloditoare?,Истязатели?,,Maulers?,Parçalayıcılar? +The Templar's favorite weapon.,TXT_RYES0_SCRIPT18_D1516_THETE,〃,,The templar's favourite weapon.,Oblíbená zbraň templářů.,Tempelriddernes yndlingsvåben.,Die Lieblingswaffe der Templer.,,"La preferata armilo +de la templanoj.","El arma favorita +de los templarios.",,Temppeliherrojen lempiase.,L'arme favorite du templier.,A keresztesek kedvenc fegyvere.,È l'arma preferita dei Templari.,騎士団に人気の兵器だ。,템플러가 제일 좋아하는 무기야.,Het favoriete wapen van de Tempeliers.,Tempelriddernes favorittvåpen.,Ulubiona broń Templariuszy.,A arma favorita dos Templários.,,Arma preferată a Templierilor.,Их любимое оружие.,,Tempelriddarens favoritvapen.,Tapınakçıların en sevdiği silah. +They came in earlier. That's what all the security's about. I got a chance to look at them when I locked up. Nobody's supposed to go in or out of there until the rest of the platoon comes to claim their weapons.,TXT_DLG_SCRIPT18_D3032_THEYC,〃,,,"Dorazily už dřív, proto ta ochranka. Měl jsem možnost se na ně podívat, když jsem zamykal. Nikdo nesmí vejít dovnitř ani ven dokud si zbytek čety nepřijde pro zbraně.","De kom ind tidligere. Det er derfor, der er så meget sikkerhed. Jeg fik en chance for at se dem, da jeg låste af. Ingen må gå ind eller ud derfra, før resten af delingen kommer for at hente deres våben.","Die sind heute früh hier eingetroffen. Daher all die Wachen. Ich konnte aber mal einen Blick darauf werfen. Niemand darf da rein, bevor die Waffen an die Truppen verteilt worden sind.",,"Ili alvenis antaŭ nelonge, tial estas ĉi tiom da sekureco; mi havis la ŝancon vidi ilin kiam mi enŝlosis ilin. Neniu supozeble devas iri nek en tiun deponejon nek el ĝi ĝis la resto de la plotono venos peti siajn armilojn.","Han llegado hace poco, para eso toda esta seguridad; he tenido la oportunidad de verlos al cerrar el depósito. Se supone que nadie puede entrar o salir hasta que el resto del pelotón venga a pedir sus armas.","Llegaron hace poco, para eso toda esta seguridad; tuve la oportunidad de verlos al cerrar el depósito. Se supone que nadie puede entrar o salir hasta que el resto del pelotón venga a pedir sus armas.","He kävivät aiemmin. Siitä näissä kaikissa turvatoimissa on kyse. Sain mahdollisuuden vilkaista niitä, kun lukitsin paikkoja. Kukaan ei saa kulkea sisään eikä ulos, ennen kuin loput joukkueesta tulee noutamaan aseensa.",Ils sont passés plus tôt. C'est pour ça qu'il y a autant de personnel de sécurité. J'ai eu l'opportunité de les voire quand je suis parti verouiller les accès. Personne n'est sensé entrer ou sortir tant que la section n'a pas fini de récupérer leur armes.,"Most hamarabb jöttek. Emiatt van akkora biztonsági cécó. Jó megnéztem magamnak őket amikor bezártam. Senki nem mehet se ki se be, míg a szakasz be nem megy a fegyvereiért.",Sono arrivati da poco. Ecco perché c'è così tanta sicurezza. Ho avuto l'opportunità di vederli quando sono uscito per bloccare gli accessi. Nessuno dovrebbe entrare o uscire finché il plotone non ha finito di raccogliere le armi.,"以前所属したばかりだ。 彼等は全て警備に周るだろう。 門を閉める時に見る機会があったからな。 残りの小隊が兵器を請求するまで -誰も入れる事はできない。","최신 에너지 무기지. 이 무기를 보호하기 위해서 경비가 아주 삼엄하다고. 다만 시간 날 때 맨눈으로 보기는 했지만. 모든 템플러 분대가 이것들을 집어가기 전까지는 그 누구도 절대로 만질 수도, 볼 수도 없어.",Ze kwamen eerder binnen. Dat is waar de beveiliging over gaat. Ik kreeg de kans om naar ze te kijken toen ik ze opsloot. Niemand wordt verondersteld daar naar binnen of buiten te gaan totdat de rest van het peloton zijn wapens komt halen.,De kom inn tidligere. Det er det all sikkerheten handler om. Jeg fikk en sjanse til å se på dem da jeg låste meg inn. Ingen skal gå inn eller ut før resten av troppen kommer for å hente våpnene sine.,"Przyszły wcześniej. To o to chodzi w tej całej ochronie. Miałem okazję przyjrzeć się im przy zamykaniu. Nikt nie może tam wchodzić ani wychodzić, dopóki reszta plutonu nie przyjdzie po swoją broń.",Eles vieram aqui antes. Por isso toda essa segurança. Tive a oportunidade de dar uma olhada neles quando eu estava fechando. Ninguém pode entrar ou sair até que o resto do pelotão venha pegar suas armas.,,Au venit mai devreme. Asta e treaba cu toată securitatea. Am avut șansa să îi privesc când închideam. Nimeni nu intră sau iese până ce tot platonul vine să își ia armele.,"Его привезли раньше, поэтому здесь столько охраны. Я заглянул в хранилище, когда запирал его. Пока весь отряд храмовников не получит своё оружие, никому не позволено входить или выходить.",,Daha erken geldiler. Bütün güvenlik bunun için. Kapıyı kilitlediğimde onlara bakma şansım oldu. Müfrezenin geri kalanı silahlarını almaya gelene kadar kimsenin oraya girip çıkmaması gerekiyor. -This is where you get the plans for the central administration.,TXT_DLG_SCRIPT19_D0_THISI,"Appears in MAP19 and is supposed to be spoken by the Peasant1 actor (named “Security Comple”). However, no such actor is spawned in the map, rendering this line unused.",,,Tady se nachází plány pro ústřední administraci.,"Det er her, du får planerne for den centrale administration.",Dort bekommst du die Pläne für die Hauptverwaltung.,,,Aquí es donde obtienes los planos de la administración central.,,Täältä saat keskushallinnon piirustukset.,C'est ici que vous pouvez récuperer les plans du centre d'administration.,,Qui è dove prendi i piani per l'amministrazione centrale,,이곳은 중앙 관리소에 전술이나 계획을 보고하기 위한 곳이야.,Hier krijg je de plannen voor de centrale administratie.,Det er her du får planene for sentraladministrasjonen.,To tutaj dostajecie plany dla administracji centralnej.,É aqui onde você pega os planos da administração central.,,De aici vei lua schemele pentru camera de administrare centrală.,Здесь ты добудешь схему центральной администрации.,,Burası merkezi yönetimin planlarını aldığınız yer. -"I run this place. My job is to build the raw parts needed for the Loremaster's robot designs. If you're not here on official business, then I'm afraid I don't have time to talk.",TXT_DLG_SCRIPT22_D0_IRUNT,,,,"Já jsem ten, kdo to tu řídí. Mým úkolem je konstruovat části pro Dějepiscovy návrhy robotů. Jestli tu nejsi kvůli oficiálním záležitostem, pak se obávám, že nemám čas s tebou mluvit.","Jeg styrer stedet her. Mit job er at bygge de rådele, der er nødvendige for Loremesterens robotdesigns. Hvis du ikke er her i officielt ærinde, så har jeg desværre ikke tid til at tale.","Ich leite dieses Unternehmen. Meine Aufgabe ist es, die Teile für die neuen Roboterdesigns des Wissensmeisters zu konstruieren. Wenn du hier nicht dienstlich hier bist, habe ich keine Zeit für dich.",,,"Yo manejo este sitio. Mi trabajo es contruir las partes necesarias para los diseños de robot del Maestro del Conocimiento. Si no estás aquí por asuntos oficiales, entonces me temo que no tengo tiempo para hablar.",,"Minä vedän tätä paikkaa. Työni on valmistaa osat, joita tarvitaan Oppi-Isän robottikehitelmiin. Jos et ole täällä virallisilla asioilla, sitten minulla valitettavasti ei ole aikaa puhua.","Je suis le chef de cet endroit. Mon travail est de faire fabriquer les pièces brutes utilisées pour les robots du Maître des traditions. Si vous n'êtes pas ici en visite officielle, je n'ai pas le temps de vous parler.","Én vezetem ezt a kócerájt. Az én feladatom, hogy a Tanmester robotjának alkatrészeit összerakjam. Ha nem hivatalos ügyben jöttél, akkor sajnos nincs időm rád.","Sono io a gestire questo posto. Il mio lavoro è costruire i materiali necessari per i progetti dei robot del Sapiente. A meno che tu non sia qua per discutere affari, mi spiace ma non ho tempo per parlare.","私がこの場所の主任者だ。 +誰も入れる事はできない。","최신 에너지 무기지. 이 무기를 보호하기 위해서 경비가 아주 삼엄하다고. 다만 시간 날 때 맨눈으로 보기는 했지만. 모든 템플러 분대가 이것들을 집어가기 전까지는 그 누구도 절대로 만질 수도, 볼 수도 없어.",Ze kwamen eerder binnen. Dat is waar de beveiliging over gaat. Ik kreeg de kans om naar ze te kijken toen ik ze opsloot. Niemand wordt verondersteld daar naar binnen of buiten te gaan totdat de rest van het peloton zijn wapens komt halen.,De kom inn tidligere. Det er det all sikkerheten handler om. Jeg fikk en sjanse til å se på dem da jeg låste meg inn. Ingen skal gå inn eller ut før resten av troppen kommer for å hente våpnene sine.,"Przyszły wcześniej. To o to chodzi w tej całej ochronie. Miałem okazję przyjrzeć się im przy zamykaniu. Nikt nie może tam wchodzić ani wychodzić, dopóki reszta plutonu nie przyjdzie po swoją broń.",Eles vieram aqui antes. Por isso toda essa segurança. Tive a oportunidade de dar uma olhada neles quando eu estava fechando. Ninguém pode entrar ou sair até que o resto do pelotão venha pegar suas armas.,,Au venit mai devreme. Asta e treaba cu toată securitatea. Am avut șansa să îi privesc când închideam. Nimeni nu intră sau iese până ce tot platonul vine să își ia armele.,"Его привезли раньше, поэтому здесь столько охраны. Я заглянул в хранилище, когда запирал его. Пока весь отряд храмовников не получит своё оружие, никому не позволено входить или выходить.",,De kom in tidigare. Det är det som är orsaken till all säkerhet. Jag fick en chans att titta på dem när jag låste in dem. Ingen får gå in eller ut därifrån förrän resten av plutonen kommer för att hämta sina vapen.,Daha erken geldiler. Bütün güvenlik bunun için. Kapıyı kilitlediğimde onlara bakma şansım oldu. Müfrezenin geri kalanı silahlarını almaya gelene kadar kimsenin oraya girip çıkmaması gerekiyor. +This is where you get the plans for the central administration.,TXT_DLG_SCRIPT19_D0_THISI,"Appears in MAP19 and is supposed to be spoken by the Peasant1 actor (named “Security Comple”). However, no such actor is spawned in the map, rendering this line unused.",,,Tady se nachází plány pro ústřední administraci.,"Det er her, du får planerne for den centrale administration.",Dort bekommst du die Pläne für die Hauptverwaltung.,,Ĉi tie oni akiras la planojn de la centra administrejo.,Aquí es donde se consiguen los planos de la administración central.,,Täältä saat keskushallinnon piirustukset.,C'est ici que vous pouvez récuperer les plans du centre d'administration.,"Ez az a rész, ahol megszerezheted a terveket a központi irányításhoz.",Qui è dove prendi i piani per l'amministrazione centrale,,이곳은 중앙 관리소에 전술이나 계획을 보고하기 위한 곳이야.,Hier krijg je de plannen voor de centrale administratie.,Det er her du får planene for sentraladministrasjonen.,To tutaj dostajecie plany dla administracji centralnej.,É aqui onde você pega os planos da administração central.,,De aici vei lua schemele pentru camera de administrare centrală.,Здесь ты добудешь схему центральной администрации.,,Det är här du får planerna för den centrala administrationen.,Burası merkezi yönetimin planlarını aldığınız yer. +"I run this place. My job is to build the raw parts needed for the Loremaster's robot designs. If you're not here on official business, then I'm afraid I don't have time to talk.",TXT_DLG_SCRIPT22_D0_IRUNT,"SVE.WAD +MAP22: C-shaped building → Master Smithy.",,,"Já jsem ten, kdo to tu řídí. Mým úkolem je konstruovat části pro Dějepiscovy návrhy robotů. Jestli tu nejsi kvůli oficiálním záležitostem, pak se obávám, že nemám čas s tebou mluvit.","Jeg styrer stedet her. Mit job er at bygge de rådele, der er nødvendige for Loremesterens robotdesigns. Hvis du ikke er her i officielt ærinde, så har jeg desværre ikke tid til at tale.","Ich leite dieses Unternehmen. Meine Aufgabe ist es, die Teile für die neuen Roboterdesigns des Wissensmeisters zu konstruieren. Wenn du hier nicht dienstlich hier bist, habe ich keine Zeit für dich.",,"Mi estras ĉi tiun lokon. Mia laboro estas konstrui la necesajn partojn por la dezajnoj de la robotoj de la Folkloristo. Se vi ne venis por oficialaj aferoj, mi timas, ke mi ne havas tempon babili.","Yo manejo este sitio. Mi trabajo es contruir las partes necesarias para los diseños de los robots del Maestro del Conocimiento. Si no estás aquí por asuntos oficiales, entonces me temo que no tengo tiempo para hablar.",,"Minä vedän tätä paikkaa. Työni on valmistaa osat, joita tarvitaan Oppi-Isän robottikehitelmiin. Jos et ole täällä virallisilla asioilla, sitten minulla valitettavasti ei ole aikaa puhua.","Je suis le chef de cet endroit. Mon travail est de faire fabriquer les pièces brutes utilisées pour les robots du Maître des traditions. Si vous n'êtes pas ici en visite officielle, je n'ai pas le temps de vous parler.","Én vezetem ezt a kócerájt. Az én feladatom, hogy a Tanmester robotjának alkatrészeit összerakjam. Ha nem hivatalos ügyben jöttél, akkor sajnos nincs időm rád.","Sono io a gestire questo posto. Il mio lavoro è costruire i materiali necessari per i progetti dei robot del Sapiente. A meno che tu non sia qua per discutere affari, mi spiace ma non ho tempo per parlare.","私がこの場所の主任者だ。 私の仕事は、ロアマスターのロボットの デザインに必要な原料パーツを生産することだ。 もしあなたが公用で来たのではないのなら、 -申し訳ないが話すための時間はないのだ。","난 이곳의 책임자야. 로어마스터님의 로봇 설계를 돕기 위해 일하고 있지. 만약 공식 업무 외에 온 거라면, 바쁘니까 돌아가 줘야 되겠는걸?","Ik run deze plek. Mijn taak is om de ruwe onderdelen te bouwen die nodig zijn voor de robotontwerpen van de Kennismeester. Als je hier niet bent voor officiële zaken, dan ben ik bang dat ik geen tijd heb om te praten.","Jeg driver dette stedet. Min jobb er å bygge rådelene som trengs til Loremesterens robotdesign. Hvis du ikke er her i offisielt ærend, har jeg ikke tid til å snakke.","Ja prowadzę to miejsce. Moim zadaniem jest budowanie części potrzebnych do projektów robotów Loremastera. Jeśli nie jesteś tu w oficjalnej sprawie, to obawiam się, że nie mam czasu na rozmowę.","Eu sou o chefe daqui deste lugar. Meu trabalho é construir as peças necessárias para os robôs do Mestre do Conhecimento. Se você não está aqui para assuntos oficiais, então receio que não temos tempo para conversa.",,"Eu conduc locul ăsta. Treaba mea e să produc materia primă pentru designul roboților Stăpânului Cunoștiințelor. Dacă nu ești aici cu treabă oficială, atunci nu am timp de vorbă.","Я здесь главный. Моя работа — изготавливать детали роботов для Хранителя мудрости. Если ты здесь не по служебным делам, то, боюсь, мне некогда с тобой болтать.",,"Burayı ben yönetiyorum. Benim işim Loremaster'ın robot tasarımları için gereken ham parçaları üretmek. Eğer resmi bir iş için burada değilseniz, korkarım ki konuşacak vaktim yok." -I am on official business.,TXT_RPLY0_SCRIPT22_D0_IAMON,,,,Jsem tu kvůli oficiálním záležitostem.,Jeg er i officielt ærinde.,Ich bin dienstlich hier.,,,Estoy por asuntos oficiales.,,Olen virallisilla asioilla.,Je suis en visite officielle.,Hivatalos ügyben jöttem.,Sono qua per discutere affari.,私は公用で来た。,공식 업무로 왔어.,Ik ben voor officiële zaken.,Jeg er her i offisielt ærend.,Jestem w oficjalnej sprawie.,Estou aqui para tratar de assuntos oficiais.,,Sunt cu treburi oficiale.,Я по служебным делам.,,Resmi bir iş için buradayım. -"So you've spoken with Timothy, I see. He and I have worked together to try to unravel the mysteries of the Order, before it's too late for us all. Maybe you can help us. I've opened the door to the production sector.",TXT_DLG_SCRIPT22_D1516_SOYOU,,,,"Vidím, že sis promluvil s Timothym. Pracovali jsme spolu na odkrytí tajemství Řádu, dřív, než pro nás bude pozdě. Možná nám můžeš pomoct. Otevřel jsem dveře do výrobního sektoru.","Så du har talt med Timothy, kan jeg se. Han og jeg har arbejdet sammen for at forsøge at løse ordenens mysterier, før det er for sent for os alle. Måske kan du hjælpe os. Jeg har åbnet døren til produktionssektoren.","Du hast mit Timothy gesprochen, ich verstehe. Er und ich haben zusammengearbeitet und versucht die Mysterien des Ordens ergründen, bevor es für uns alle zu spät ist. Vielleicht kannst du uns helfen. Ich habe die Tür zum Produktionsektor geöffnet.",,,"Así que has ablado con Timothy, ya veo. Él y yo hemos trabajado juntos para intentar desenredar los misterios de la Orden, antes de que sea demasiado tarde para todos nosotros. Tal vez puedas ayudarnos. He abierto la puerta al sector de producción.",,"Olet siis näköjään puhunut Timothyn kanssa. Olemme yhteistyössä koettaneet ratkoa Veljeskunnan saloja, ennen kuin on liian myöhäistä meidän kaikkien kannalta. Ehkä voit auttaa meitä. Avasin oven tuotantolaitokselle.",Je vois que vous avez parlé à Timothy. Nous avons travaillé ensemble pour dénouer les mystères de l'Ordre avant qu'il soit trop tard. Peut être que vous pouvez nous aider. J'ai ouvert l'accès vers le secteur de production.,"Úgy látom már beszéltél Timothyval. Ő és Én már korábban is próbáltuk felderíteni a Rend rejtélyét, mielőtt még mindannyiunknak túl késő nem lesz. Talán tudsz segíteni. Kinyitottam az ajtót a gyártó részleghez.",Vedo che hai parlato con Timothy. Io e lui abbiamo lavorato insieme per cercare di svelare i misteri dell'Ordine prima che sia troppo tardi per tutti noi. Forse ci puoi aiutare. Ho aperto la porta che conduce al settore di produzione.,"ということは、ティモシーと話したのだな。 +申し訳ないが話すための時間はないのだ。","난 이곳의 책임자야. 로어마스터님의 로봇 설계를 돕기 위해 일하고 있지. 만약 공식 업무 외에 온 거라면, 바쁘니까 돌아가 줘야 되겠는걸?","Ik run deze plek. Mijn taak is om de ruwe onderdelen te bouwen die nodig zijn voor de robotontwerpen van de Kennismeester. Als je hier niet bent voor officiële zaken, dan ben ik bang dat ik geen tijd heb om te praten.","Jeg driver dette stedet. Min jobb er å bygge rådelene som trengs til Loremesterens robotdesign. Hvis du ikke er her i offisielt ærend, har jeg ikke tid til å snakke.","Ja prowadzę to miejsce. Moim zadaniem jest budowanie części potrzebnych do projektów robotów Loremastera. Jeśli nie jesteś tu w oficjalnej sprawie, to obawiam się, że nie mam czasu na rozmowę.","Eu sou o chefe daqui deste lugar. Meu trabalho é construir as peças necessárias para os robôs do Mestre do Conhecimento. Se você não está aqui para assuntos oficiais, então receio que não temos tempo para conversa.",,"Eu conduc locul ăsta. Treaba mea e să produc materia primă pentru designul roboților Stăpânului Cunoștiințelor. Dacă nu ești aici cu treabă oficială, atunci nu am timp de vorbă.","Я здесь главный. Моя работа — изготавливать детали роботов для Хранителя мудрости. Если ты здесь не по служебным делам, то, боюсь, мне некогда с тобой болтать.",,Jag styr det här stället. Mitt jobb är att bygga de rådelar som behövs för Läromästarens robotkonstruktioner. Om du inte är här i officiellt ärende har jag tyvärr inte tid att prata.,"Burayı ben yönetiyorum. Benim işim Loremaster'ın robot tasarımları için gereken ham parçaları üretmek. Eğer resmi bir iş için burada değilseniz, korkarım ki konuşacak vaktim yok." +I am on official business.,TXT_RPLY0_SCRIPT22_D0_IAMON,〃,,,Jsem tu kvůli oficiálním záležitostem.,Jeg er i officielt ærinde.,Ich bin dienstlich hier.,,Mi venis por oficialaj aferoj.,Estoy por asuntos oficiales.,,Olen virallisilla asioilla.,Je suis en visite officielle.,Hivatalos ügyben jöttem.,Sono qua per discutere affari.,私は公用で来た。,공식 업무로 왔어.,Ik ben voor officiële zaken.,Jeg er her i offisielt ærend.,Jestem w oficjalnej sprawie.,Estou aqui para tratar de assuntos oficiais.,,Sunt cu treburi oficiale.,Я по служебным делам.,,Jag är i officiellt ärende.,Resmi bir iş için buradayım. +"So you've spoken with Timothy, I see. He and I have worked together to try to unravel the mysteries of the Order, before it's too late for us all. Maybe you can help us. I've opened the door to the production sector.",TXT_DLG_SCRIPT22_D1516_SOYOU,〃 (After giving the blue chalice to Timothy).,,,"Vidím, že sis promluvil s Timothym. Pracovali jsme spolu na odkrytí tajemství Řádu, dřív, než pro nás bude pozdě. Možná nám můžeš pomoct. Otevřel jsem dveře do výrobního sektoru.","Så du har talt med Timothy, kan jeg se. Han og jeg har arbejdet sammen for at forsøge at løse ordenens mysterier, før det er for sent for os alle. Måske kan du hjælpe os. Jeg har åbnet døren til produktionssektoren.","Du hast mit Timothy gesprochen, ich verstehe. Er und ich haben zusammengearbeitet und versucht die Mysterien des Ordens ergründen, bevor es für uns alle zu spät ist. Vielleicht kannst du uns helfen. Ich habe die Tür zum Produktionsektor geöffnet.",,Do vi parolis kun Timoteo. Li kaj mi kunlaboris kun la intenco penetri la misterojn de La Ordeno. Vi eble povas helpi nin; mi malfermis la pordon de la produktejo.,"Así que has hablado con Timothy, ya veo. Él y yo hemos trabajado juntos para intentar desentrañar los misterios de La Orden antes de que sea demasiado tarde para todos nosotros. Tal vez puedas ayudarnos; he abierto la puerta al sector de producción.","Así que hablaste con Timothy, ya veo. Él y yo hemos trabajado juntos para tratar de descifrar los misterios de La Orden antes de que sea demasiado tarde para todos nosotros. Tal vez puedas ayudarnos; acabo de abrir la puerta al sector de producción.","Olet siis näköjään puhunut Timothyn kanssa. Olemme yhteistyössä koettaneet ratkoa Veljeskunnan saloja, ennen kuin on liian myöhäistä meidän kaikkien kannalta. Ehkä voit auttaa meitä. Avasin oven tuotantolaitokselle.",Je vois que vous avez parlé à Timothy. Nous avons travaillé ensemble pour dénouer les mystères de l'Ordre avant qu'il soit trop tard. Peut être que vous pouvez nous aider. J'ai ouvert l'accès vers le secteur de production.,"Úgy látom már beszéltél Timothyval. Ő és Én már korábban is próbáltuk felderíteni a Rend rejtélyét, mielőtt még mindannyiunknak túl késő nem lesz. Talán tudsz segíteni. Kinyitottam az ajtót a gyártó részleghez.",Vedo che hai parlato con Timothy. Io e lui abbiamo lavorato insieme per cercare di svelare i misteri dell'Ordine prima che sia troppo tardi per tutti noi. Forse ci puoi aiutare. Ho aperto la porta che conduce al settore di produzione.,"ということは、ティモシーと話したのだな。 彼と私は、取り返しのつかない事態に陥る前に オーダーの秘密を解き明かすために 一緒に働いてきた。もしかすると、 君は私達に手を貸せるかもしれない。 -私は今、生産セクターへの扉を開いたぞ。","티모시와 이야기를 나눴구나, 그렇지? 티모시랑 같이 한발 늦기 전에 오더의 비밀을 파헤치려고 열심히 노력했지. 아마도 우리들을 도와줄 수 있을 것 같은데 말이야. 방금 제조 공간의 문을 열어놨어.","Dus je hebt met Timothy gesproken, zie ik. Hij en ik hebben samengewerkt om te proberen de mysteries van de Orde te ontrafelen, voordat het voor ons allemaal te laat is. Misschien kunt u ons helpen. Ik heb de deur geopend naar de productiesector.","Så du har snakket med Timothy, ser jeg. Han og jeg har jobbet sammen for å løse Ordenens mysterier før det er for sent for oss alle. Kanskje du kan hjelpe oss. Jeg har åpnet døren til produksjonssektoren.","Widzę, że rozmawiałaś z Timothym. Razem z nim próbujemy rozwikłać tajemnice Zakonu, zanim będzie za późno dla nas wszystkich. Może ty możesz nam pomóc. Otworzyłem drzwi do sektora produkcyjnego.","Então você andou falando com o Timothy, pelo visto. Eu e ele trabalhamos juntos para tentar desvendar os mistérios da Ordem antes que seja tarde para todos nós. Talvez você possa nos ajudar. Eu abri a porta para o setor de produção.",,"Ai vorbit cu Timotei, să înțeleg. Noi am lucrat împreună în încercarea de a descoperii misterele Ordinului, înainte să fie prea târziu pentru noi toți. Poate ne poți ajuta. Am deschis ușa la sectorul de producție.","Итак, ты уже поговорил с Тимоти. Мы с ним вместе пытаемся раскрыть тайны Ордена, пока не стало слишком поздно. Возможно, ты сможешь нам помочь. Я открыл дверь в производственный сектор.",,"Gördüğüm kadarıyla Timothy ile konuşmuşsunuz. O ve ben, hepimiz için çok geç olmadan Tarikat'ın gizemlerini çözmeye çalışmak için birlikte çalıştık. Belki bize yardım edebilirsin. Üretim sektörünün kapısını açtım." -Do you know what's inside?,TXT_RPLY0_SCRIPT22_D1516_DOYOU,,,,"Víš, co je uvnitř?","Ved du, hvad der er indenfor?",Weißt du was da drin ist?,,,¿Sabes que hay adentro?,,"Tiedätkö, mitä sisällä on?",Vous savez ce qu'il y à dedans?,Tudod mi van bent?,Che cosa c'è oltre la porta?,中に何があるのかを知っているのか?,그 안에 무엇이 있는지 아나?,Weet je wat er in zit?,Vet du hva som er der inne?,"Wiesz, co jest w środku?",Você sabe o que tem lá dentro?,,Știi cumva ce e înăuntru?,"Ты знаешь, что там?",,İçeride ne olduğunu biliyor musun? -"It's a top secret area. Not only is the Order breeding some kind of... creature in there, I've seen with my own eyes a strange artifact called a Talisman. nobody's allowed near it. Rumor is that it holds great power if united with two others of its kind.",TXT_DLG_SCRIPT22_D3032_ITSAT,,,,"Je to přísně tajná oblast. Nejenže se tam Řád snaží zplodit nějakou... příšeru, ale na vlastní oči jsem tam viděl zvláštní artefakt jménem Talisman. Nikdo k němu nesmí. Říká se, že skrývá nesmírnou moc pokud se spojí s dalšími dvěma svého druhu.","Det er et tophemmeligt område. Ikke alene avler Ordenen en slags... væsen derinde, jeg har også set med mine egne øjne en mærkelig artefakt kaldet en Talisman. Ingen må komme i nærheden af den. Rygterne siger, at den har stor magt, hvis den forenes med to andre af sin slags.","Das ist alles streng geheim. Dort wird nicht nur irgendeine Art von... Kreatur vom Orden gezüchtet, sondern es gibt dort auch ein merkwürdiges Artefakt, ein Talisman. Keiner darf in auch nur in die Nähe davon. Gerüchten zufolge erhält man große Macht, wenn man es mit zwei anderen vereint.",,,"Es un área de alto secreto. No solo está la Orden criando una especie de... Criatura ahí, he visto con mis propios ojos un extraño artefacto llamado Talismán. No se permite a nadie acercarse a él. Se rumorea que posee un gran poder si se reune con otros dos de su tipo.",,"Se on huippusalainen alue. Vielä sen lisäksi, että Veljeskunta on luomassa siellä jonkinlaista... oliota, olen omin silmin nähnyt oudon esineen, jota kutsutaan Talismaaniksi. Ketään ei sallita sen lähelle. Huhutaan, että sen sisällä piilee suuri voima, jos sen yhdistää kahden toisen sen kaltaisen kanssa.",C'est une zone top secrète. L'Ordre essaie de.. faire une sorte de créature là dedans. J'ai vu avec mes yeux un artéfact étrange qu'ils appellent un Talisman. Personne n'a le droit de l'approcher. Les rumeurs disent qu'il contient un pouvoir phénoménal si il est réuni avec deux autres du même type.,"Egy totál titkos terület. Nem elég hogy valamiféle...lényeket tenyésztenek odabent, láttam valamiféle leletet is, amit Talizmán néven emlegettek. Senkit se engednek a közelébe. A legenda szerint hatalmas erő birtokosa lehet, aki egyesíti még két másik darabbal.","È un'area a cui quasi nessuno è permesso entrare. L'Ordine non solo sta crescendo una specie di... creatura là dentro, ma inoltre ho anche visto uno strano artefatto che chiamano Talismano. Nessuno ci si può avvicinare. Dicono che se unito a due altri talismani, sprigioni un enorme potere.","あの場所は極秘エリアだ。 +私は今、生産セクターへの扉を開いたぞ。","티모시와 이야기를 나눴구나, 그렇지? 티모시랑 같이 한발 늦기 전에 오더의 비밀을 파헤치려고 열심히 노력했지. 아마도 우리들을 도와줄 수 있을 것 같은데 말이야. 방금 제조 공간의 문을 열어놨어.","Dus je hebt met Timothy gesproken, zie ik. Hij en ik hebben samengewerkt om te proberen de mysteries van de Orde te ontrafelen, voordat het voor ons allemaal te laat is. Misschien kunt u ons helpen. Ik heb de deur geopend naar de productiesector.","Så du har snakket med Timothy, ser jeg. Han og jeg har jobbet sammen for å løse Ordenens mysterier før det er for sent for oss alle. Kanskje du kan hjelpe oss. Jeg har åpnet døren til produksjonssektoren.","Widzę, że rozmawiałaś z Timothym. Razem z nim próbujemy rozwikłać tajemnice Zakonu, zanim będzie za późno dla nas wszystkich. Może ty możesz nam pomóc. Otworzyłem drzwi do sektora produkcyjnego.","Então você andou falando com o Timothy, pelo visto. Eu e ele trabalhamos juntos para tentar desvendar os mistérios da Ordem antes que seja tarde para todos nós. Talvez você possa nos ajudar. Eu abri a porta para o setor de produção.",,"Ai vorbit cu Timotei, să înțeleg. Noi am lucrat împreună în încercarea de a descoperii misterele Ordinului, înainte să fie prea târziu pentru noi toți. Poate ne poți ajuta. Am deschis ușa la sectorul de producție.","Итак, ты уже поговорил с Тимоти. Мы с ним вместе пытаемся раскрыть тайны Ордена, пока не стало слишком поздно. Возможно, ты сможешь нам помочь. Я открыл дверь в производственный сектор.",,"Så du har talat med Timothy, ser jag. Han och jag har arbetat tillsammans för att försöka lösa Ordens mysterier innan det är för sent för oss alla. Du kanske kan hjälpa oss. Jag har öppnat dörren till produktionssektorn.","Gördüğüm kadarıyla Timothy ile konuşmuşsunuz. O ve ben, hepimiz için çok geç olmadan Tarikat'ın gizemlerini çözmeye çalışmak için birlikte çalıştık. Belki bize yardım edebilirsin. Üretim sektörünün kapısını açtım." +Do you know what's inside?,TXT_RPLY0_SCRIPT22_D1516_DOYOU,〃,,,"Víš, co je uvnitř?","Ved du, hvad der er indenfor?",Weißt du was da drin ist?,,"Ĉu vi scias, kio estas en ĝi?",¿Sabes qué hay dentro?,¿Sabes qué hay adentro?,"Tiedätkö, mitä sisällä on?",Vous savez ce qu'il y à dedans?,Tudod mi van bent?,Che cosa c'è oltre la porta?,中に何があるのかを知っているのか?,그 안에 무엇이 있는지 아나?,Weet je wat er in zit?,Vet du hva som er der inne?,"Wiesz, co jest w środku?",Você sabe o que tem lá dentro?,,Știi cumva ce e înăuntru?,"Ты знаешь, что там?",,Vet du vad som finns där inne?,İçeride ne olduğunu biliyor musun? +"It's a top secret area. Not only is the Order breeding some kind of... creature in there, I've seen with my own eyes a strange artifact called a Talisman. nobody's allowed near it. Rumor is that it holds great power if united with two others of its kind.",TXT_DLG_SCRIPT22_D3032_ITSAT,〃,,,"Je to přísně tajná oblast. Nejenže se tam Řád snaží zplodit nějakou... příšeru, ale na vlastní oči jsem tam viděl zvláštní artefakt jménem Talisman. Nikdo k němu nesmí. Říká se, že skrývá nesmírnou moc pokud se spojí s dalšími dvěma svého druhu.","Det er et tophemmeligt område. Ikke alene avler Ordenen en slags... væsen derinde, jeg har også set med mine egne øjne en mærkelig artefakt kaldet en Talisman. Ingen må komme i nærheden af den. Rygterne siger, at den har stor magt, hvis den forenes med to andre af sin slags.","Das ist alles streng geheim. Dort wird nicht nur irgendeine Art von... Kreatur vom Orden gezüchtet, sondern es gibt dort auch ein merkwürdiges Artefakt, ein Talisman. Keiner darf in auch nur in die Nähe davon. Gerüchten zufolge erhält man große Macht, wenn man es mit zwei anderen vereint.",,"Ĝi estas tute konfidenca sektoro. Ne nur La Ordeno estigas specon de... vivaĵo tie, mi vidis per miaj propraj okuloj strangan artefakton nomatan talismano. Neniu rajtas aliri ĝin. Oni diras, ke ĝi posedas grandan povon se ĝi estas proksime de aliaj du el sia speco.","Es un área de alto secreto. No solo está La Orden criando a una especie de... criatura ahí, he visto con mis propios ojos un artefacto extraño llamado talismán. No se le permite a nadie acercarse a él. Se rumorea que posee un gran poder si se reúne con otros dos de su especie.",,"Se on huippusalainen alue. Vielä sen lisäksi, että Veljeskunta on luomassa siellä jonkinlaista... oliota, olen omin silmin nähnyt oudon esineen, jota kutsutaan Talismaaniksi. Ketään ei sallita sen lähelle. Huhutaan, että sen sisällä piilee suuri voima, jos sen yhdistää kahden toisen sen kaltaisen kanssa.",C'est une zone top secrète. L'Ordre essaie de.. faire une sorte de créature là dedans. J'ai vu avec mes yeux un artéfact étrange qu'ils appellent un Talisman. Personne n'a le droit de l'approcher. Les rumeurs disent qu'il contient un pouvoir phénoménal si il est réuni avec deux autres du même type.,"Egy totál titkos terület. Nem elég hogy valamiféle...lényeket tenyésztenek odabent, láttam valamiféle leletet is, amit Talizmán néven emlegettek. Senkit se engednek a közelébe. A legenda szerint hatalmas erő birtokosa lehet, aki egyesíti még két másik darabbal.","È un'area a cui quasi nessuno è permesso entrare. L'Ordine non solo sta crescendo una specie di... creatura là dentro, ma inoltre ho anche visto uno strano artefatto che chiamano Talismano. Nessuno ci si può avvicinare. Dicono che se unito a due altri talismani, sprigioni un enorme potere.","あの場所は極秘エリアだ。 オーダーはある種の生物のようなものを そこで繁殖させているし、それだけではなく 私はタリスマンと呼ばれる奇妙な アーティファクトをこの目で見た。 誰もそれには近づくことが許されていないのだ。 噂では、タリスマンはほかの2つのタリスマンと -つながることで強大なパワーを発揮できるらしい。",아주 중요한 기밀 공간이야. 난 오더가 거기에서 각종... 생물들을 만드는 거랑 부적이라는 희한한 유물을 보호하는 모습을 봤지. 그런 이유로 그 누구도 못 들어가. 그리고 이와 똑같은 다른 유물을 합치면 초월한 힘을 발휘한다는 소문도 들었어.,"Het is een topgeheim gebied. Niet alleen is de Orde daar een soort.... schepsel aan het kweken, ik heb met mijn eigen ogen een vreemd artefact gezien dat een Talisman wordt genoemd. niemand mag er in de buurt komen. Het gerucht gaat dat hij grote macht heeft als hij zich verenigt met twee anderen van zijn soort.","Det er et topphemmelig område. Ikke bare avler Ordenen en slags... skapning der inne, jeg har selv sett en merkelig gjenstand kalt en Talisman. Ingen får komme nær den. Ryktene sier at den har stor makt hvis den forenes med to andre av sitt slag.","To ściśle tajny obszar. Nie dość, że Zakon hoduje tam jakieś... stworzenia, to na własne oczy widziałem dziwny artefakt zwany Talizmanem. nikomu nie wolno się do niego zbliżać. Plotka głosi, że posiada on wielką moc, jeśli połączy się go z dwoma innymi tego rodzaju.","É uma área ultrassecreta. Não só a Ordem está criando um tipo de...criatura lá dentro, eu vi com meus próprios olhos um artefato estranho chamado de Talismã. Ninguém tem permissão para chegar perto. Dizem que ele tem um grande poder ao se unir com outros dois do mesmo tipo.",,"E o zonă secretă. Nu numai că Ordinul crește un fel de... creatură acolo, am văzut cu proprii mei ochi un fel de artefact numit Talisman, nimeni nu e lăsat să se apropie.. Zvonurile zic că e un artefact de o putere imensă dacă e unit cu celelalte două părți ale lui.","Это совершенно секретно. Во-первых, Орден разводит там каких-то... существ. Во-вторых, я своими глазами видел странный артефакт — «Талисман». К нему никого и близко не подпускают. Говорят, если объединить его с двумя другими, можно получить огромную силу.",,"Çok gizli bir bölge. Tarikat orada bir tür yaratık yetiştirmekle kalmıyor, Tılsım denen garip bir eseri kendi gözlerimle gördüm. Kimsenin ona yaklaşmasına izin verilmiyor. Söylentiye göre türünün diğer iki örneğiyle birleştiğinde büyük bir güce sahip oluyormuş." -I suppose you want this thing?,TXT_RPLY0_SCRIPT22_D3032_ISUPP,,,,"Předpokládám, že jej chceš?","Jeg formoder, at du vil have denne tingest?","Ich denke mal, du willst dieses Ding haben?",,,¿Supongo que quieres esto?,,Sinä varmaankin haluat tämän esineen?,Je suppose que vous le voulez?,Gondolom kell neked az a tárgy.,Immagino tu voglia questo?,それが欲しいということか?,내 생각엔 그걸 원하나 보지?,Ik neem aan dat je dit ding wilt?,Jeg antar at du vil ha den?,"Przypuszczam, że chcesz tego czegoś?",Imagino que você quer essa coisa?,,Presupun că vrei chestia asta?,"Похоже, ты и сам хочешь этот артефакт?",,Sanırım bu şeyi istiyorsun? -"No! If you can find it, it's yours to keep. Maybe you can use it to help free us from our oppression. I'd wish you luck, but you're going to need a lot more than that if you go in there...",TXT_DLG_SCRIPT22_D4548_NOIFY,,,,"Ne! Jestli ho najdeš, je tvůj. Možná by ti mohl pomoct osvobodit nás od nadvlády. Přál bych ti štěstí, ale jestli tam půjdeš, budeš potřebovat mnohem víc než to...","Nej! Hvis du kan finde den, kan du beholde den. Måske kan du bruge den til at hjælpe os med at befri os fra vores undertrykkelse. Jeg ville ønske dig held og lykke, men du får brug for meget mere end det, hvis du går derind...","Nein! Wenn du es findest, darfst du es behalten. Vielleicht kannst du es benutzen, um uns von unserer Unterdrückung zu befreien. Ich würde dir Glück wünschen, aber du wirst viel mehr brauchen, wenn du dort hinein gehst.",,,"¡No! Si lo encuentras, quédatelo. Tal vez puedas usarlo para ayudar a librarnos de nuestra opresión. Te desearía suerte, pero vas a necesitar más que eso si vas ahí...",,"Ei! Jos löydät sen, saat pitää omanasi. Voit ehkä käyttää sitä auttaaksesi vapauttamaan meidät sorrostamme. Toivottaisin sinulle onnea, mutta tarvitset paljon enemmän kuin sitä, jos menet sinne.","Non! Si vous le trouvez, gardez le pour vous. Peut être qu'il vous aidera à nous débarasser de nos oppresseurs.. Je vous souhaiterais bonne chance, mais vous allez avoir besoin de beaucoup plus que ça si vous y entrez..","Dehogyis! Ha megleled, a tied lehet. Talán fel tudod használni annak érdekében, hogy felszabadíts minket az elnyomás alól. Szerencsét kívánnék, de annál sokkal többre lesz szükséged odabent...","No! Se lo trovi, te lo puoi tenere. Forse lo puoi utilizzare per liberarci dalla nostra oppressione. Ti augurerei buona fortuna, ma ti servirebbe molto più che fortuna se vai là dentro...","そうではない!もし見つけたら +つながることで強大なパワーを発揮できるらしい。",아주 중요한 기밀 공간이야. 난 오더가 거기에서 각종... 생물들을 만드는 거랑 부적이라는 희한한 유물을 보호하는 모습을 봤지. 그런 이유로 그 누구도 못 들어가. 그리고 이와 똑같은 다른 유물을 합치면 초월한 힘을 발휘한다는 소문도 들었어.,"Het is een topgeheim gebied. Niet alleen is de Orde daar een soort.... schepsel aan het kweken, ik heb met mijn eigen ogen een vreemd artefact gezien dat een Talisman wordt genoemd. niemand mag er in de buurt komen. Het gerucht gaat dat hij grote macht heeft als hij zich verenigt met twee anderen van zijn soort.","Det er et topphemmelig område. Ikke bare avler Ordenen en slags... skapning der inne, jeg har selv sett en merkelig gjenstand kalt en Talisman. Ingen får komme nær den. Ryktene sier at den har stor makt hvis den forenes med to andre av sitt slag.","To ściśle tajny obszar. Nie dość, że Zakon hoduje tam jakieś... stworzenia, to na własne oczy widziałem dziwny artefakt zwany Talizmanem. nikomu nie wolno się do niego zbliżać. Plotka głosi, że posiada on wielką moc, jeśli połączy się go z dwoma innymi tego rodzaju.","É uma área ultrassecreta. Não só a Ordem está criando um tipo de...criatura lá dentro, eu vi com meus próprios olhos um artefato estranho chamado de Talismã. Ninguém tem permissão para chegar perto. Dizem que ele tem um grande poder ao se unir com outros dois do mesmo tipo.",,"E o zonă secretă. Nu numai că Ordinul crește un fel de... creatură acolo, am văzut cu proprii mei ochi un fel de artefact numit Talisman, nimeni nu e lăsat să se apropie.. Zvonurile zic că e un artefact de o putere imensă dacă e unit cu celelalte două părți ale lui.","Это совершенно секретно. Во-первых, Орден разводит там каких-то... существ. Во-вторых, я своими глазами видел странный артефакт — «Талисман». К нему никого и близко не подпускают. Говорят, если объединить его с двумя другими, можно получить огромную силу.",,"Det är ett topphemligt område. Inte nog med att Orden föder upp någon sorts... varelse där inne, jag har med egna ögon sett en märklig artefakt som kallas för en Talisman. Ingen får komma i närheten av den. Ryktet säger att den har stor kraft om den förenas med två andra av samma slag.","Çok gizli bir bölge. Tarikat orada bir tür yaratık yetiştirmekle kalmıyor, Tılsım denen garip bir eseri kendi gözlerimle gördüm. Kimsenin ona yaklaşmasına izin verilmiyor. Söylentiye göre türünün diğer iki örneğiyle birleştiğinde büyük bir güce sahip oluyormuş." +I suppose you want this thing?,TXT_RPLY0_SCRIPT22_D3032_ISUPP,〃,,,"Předpokládám, že jej chceš?","Jeg formoder, at du vil have denne tingest?","Ich denke mal, du willst dieses Ding haben?",,"Mi supozas, ke vi volas ĝin.",Y supongo que lo quieres.,,Sinä varmaankin haluat tämän esineen?,Je suppose que vous le voulez?,Gondolom kell neked az a tárgy.,Immagino tu voglia questo?,それが欲しいということか?,내 생각엔 그걸 원하나 보지?,Ik neem aan dat je dit ding wilt?,Jeg antar at du vil ha den?,"Przypuszczam, że chcesz tego czegoś?",Imagino que você quer essa coisa?,,Presupun că vrei chestia asta?,"Похоже, ты и сам хочешь этот артефакт?",,Jag antar att du vill ha den här?,Sanırım bu şeyi istiyorsun? +"No! If you can find it, it's yours to keep. Maybe you can use it to help free us from our oppression. I'd wish you luck, but you're going to need a lot more than that if you go in there...",TXT_DLG_SCRIPT22_D4548_NOIFY,〃,,,"Ne! Jestli ho najdeš, je tvůj. Možná by ti mohl pomoct osvobodit nás od nadvlády. Přál bych ti štěstí, ale jestli tam půjdeš, budeš potřebovat mnohem víc než to...","Nej! Hvis du kan finde den, kan du beholde den. Måske kan du bruge den til at hjælpe os med at befri os fra vores undertrykkelse. Jeg ville ønske dig held og lykke, men du får brug for meget mere end det, hvis du går derind...","Nein! Wenn du es findest, darfst du es behalten. Vielleicht kannst du es benutzen, um uns von unserer Unterdrückung zu befreien. Ich würde dir Glück wünschen, aber du wirst viel mehr brauchen, wenn du dort hinein gehst.",,"Ne! Se vi trovos ĝin, konservu ĝin. Ĝi eble estos utila por ke vi liberigu nin ĉiujn de ĉi tiu opresado. Mi dezirus bonŝancon, sed vi bezonos multe pli ol tion se vi iros tien...","¡No! Si lo encuentras, quédatelo. Quizá te sirva para intentar librarnos de esta opresión. Te desearía suerte, pero necesitarás mucho más que eso si vas ahí...","¡No! Si lo encuentras, quédatelo. Puede que te sirva para tratar de librarnos de esta opresión. Te desearía suerte, pero vas a necesitar mucho más que eso si vas ahí...","Ei! Jos löydät sen, saat pitää omanasi. Voit ehkä käyttää sitä auttaaksesi vapauttamaan meidät sorrostamme. Toivottaisin sinulle onnea, mutta tarvitset paljon enemmän kuin sitä, jos menet sinne.","Non! Si vous le trouvez, gardez le pour vous. Peut être qu'il vous aidera à nous débarasser de nos oppresseurs.. Je vous souhaiterais bonne chance, mais vous allez avoir besoin de beaucoup plus que ça si vous y entrez..","Dehogyis! Ha megleled, a tied lehet. Talán fel tudod használni annak érdekében, hogy felszabadíts minket az elnyomás alól. Szerencsét kívánnék, de annál sokkal többre lesz szükséged odabent...","No! Se lo trovi, te lo puoi tenere. Forse lo puoi utilizzare per liberarci dalla nostra oppressione. Ti augurerei buona fortuna, ma ti servirebbe molto più che fortuna se vai là dentro...","そうではない!もし見つけたら それは自分のものにしてくれ。もしかすれば、 それを私達をオーダーから解放するために 使えるかもしれない。幸運を祈ってはいるが、 もしあの場所に行こうとしているなら、 -もっと多くの力が必要となるぞ...","아니야! 만약 네가 가질 수만 있다면, 그건 네 거야. 아마도 우리들을 탄압으로부터 구해줄 수 있겠네. 부디 행운을 빌어. 왜냐하면 많은 걸 준비 한 뒤 각오하고 들어가야 하거든.","Nee, als je het kunt vinden, is het aan jou om het te houden. Misschien kunt je het gebruiken om ons te bevrijden van onze onderdrukking. Ik zou je veel geluk wensen, maar je zult veel meer nodig hebben als je daar naar binnen gaat....","Nei! Hvis du finner den, kan du beholde den. Kanskje du kan bruke den til å frigjøre oss fra undertrykkelsen. Jeg skulle ønske deg lykke til, men du trenger mer enn det hvis du går inn dit...","Nie! Jeśli go znajdziesz, zatrzymasz go dla siebie. Może użyjesz jej, by pomóc nam uwolnić się od ucisku. Życzyłbym ci szczęścia, ale będziesz potrzebował o wiele więcej, jeśli tam wejdziesz...","Não! Se você conseguir achá-lo, fique com ele. Talvez você possa usá-lo para nos libertar dessa opressão. Eu te desejaria sorte, mas você vai precisar de muito mais do que isso se você entrar lá dentro...",,"Nu! Dacă o găsești, e a ta. Poate o poți folosi ca să ne ajuți să scăpăm de oprimare. Ți-aș ura noroc, dar o să ai noroc de mult mai mult decât atât dacă mergi acolo...","Нет! Если ты его найдёшь, он твой. Может быть, он поможет тебе освободить нас от гнёта. Я бы пожелал тебе удачи, но, если ты пойдёшь туда, простой удачи будет недостаточно...",,"Hayır! Eğer onu bulabilirsen, sende kalabilir. Belki onu bizi zulmümüzden kurtarmak için kullanabilirsin. Sana şans dilerdim, ama oraya girersen bundan çok daha fazlasına ihtiyacın olacak..." -What's all this about the past?,TXT_RPLY0_SCRIPT22_D4548_WHATS,,,,Cos to říkal o minulosti?,Hvad er alt det her med fortiden?,Was ist dieses ganze Gerede über die Vergangenheit?,,,¿Qué es todo esto sobre el pasado?,,Mistä tässä kaikessa menneessä oikein on kyse?,Qu'est-ce que j'entends au sujet du passé?,És mi köze ennek a múlthoz?,E che mi dici riguardo a tutte ste storie del passato?,過去に何があったというんだ?,그 과거에 대해서 뭐가 어떻길레?,Wat is dit alles over het verleden?,Hva er alt dette om fortiden?,O co chodzi z tą przeszłością?,Que história é essa sobre o passado?,,Care e treaba cu trecutul ăsta?,Что такого творилось здесь в прошлом?,,Geçmişle ilgili tüm bu şeyler de ne? -"You've surely seen the other ruins nearby. It seems that the Comet which crashed on our planet is actually a space ship, and believe it or not, it originated on this very world a long time ago.",TXT_DLG_SCRIPT22_D6064_YOUVE,,,,"Určitě jsi zahlédnul ty zříceniny tady v okolí. Zdá se, že ta kometa, která narazila do naší planety, je ve skutečnosti vesmírná loď, která, věř nebo ne, kdysi dávno pocházela z tohoto světa.","Du har sikkert set de andre ruiner i nærheden. Det ser ud til, at den komet, der styrtede ned på vores planet, faktisk er et rumskib, og tro det eller ej, men det stammer fra denne verden for længe siden.","Du hast doch sicherlich die Ruinen hier in der Nähe gesehen. Es scheint als wäre der Komet, der hier auf dem Planeten aufgeschlagen ist, eigentlich ein Raumschiff, und ob du es glaubst oder nicht, aber es kam vor langer Zeit sogar von dieser Welt.",,,"Seguramente has visto las otras ruinas cercanas. Al parecer el cometa que se estrelló sobre nuestro planeta es en realidad una nave espacial, y lo creas o no, es originaria de este mundo hace mucho tiempo.",,"Olet varmastikin nähnyt lähistön muut rauniot. Vaikuttaa siltä, että komeetta, joka törmäsi planeettaamme, on oikeasti avaruusalus; ja usko tai älä, se on alkuaan peräisin tästä samaisesta maailmasta kauan sitten.","Vous avez sans doute vu toutes ces ruines aux alentours. Il semble que la comète qui s'est écrasée sur notre planète était en fait un vaisseau spatial, et.. du moins si vous y croyez, venait aussi de notre planète, il y a très, très longtemps.","Bizonyára láttad a többi romot is. Úgy néz ki, a lehulló üstökös valójában egy űrhajó volt, és hiszed vagy sem, eredetileg erről a bolygóról indult sok évvel ezelőtt.","Sicuramente avrai visto le rovine qua vicino. Sembra che la cometa dell'impatto verso il nostro pianeta fosse in realtà una navicella spaziale, e so che può sembrare incredibile, ma nave è originaria di questo mondo, di molto tempo fa.","君はこの周りの廃墟群を見てきたはずだ。 +もっと多くの力が必要となるぞ...","아니야! 만약 네가 가질 수만 있다면, 그건 네 거야. 아마도 우리들을 탄압으로부터 구해줄 수 있겠네. 부디 행운을 빌어. 왜냐하면 많은 걸 준비 한 뒤 각오하고 들어가야 하거든.","Nee, als je het kunt vinden, is het aan jou om het te houden. Misschien kunt je het gebruiken om ons te bevrijden van onze onderdrukking. Ik zou je veel geluk wensen, maar je zult veel meer nodig hebben als je daar naar binnen gaat....","Nei! Hvis du finner den, kan du beholde den. Kanskje du kan bruke den til å frigjøre oss fra undertrykkelsen. Jeg skulle ønske deg lykke til, men du trenger mer enn det hvis du går inn dit...","Nie! Jeśli go znajdziesz, zatrzymasz go dla siebie. Może użyjesz jej, by pomóc nam uwolnić się od ucisku. Życzyłbym ci szczęścia, ale będziesz potrzebował o wiele więcej, jeśli tam wejdziesz...","Não! Se você conseguir achá-lo, fique com ele. Talvez você possa usá-lo para nos libertar dessa opressão. Eu te desejaria sorte, mas você vai precisar de muito mais do que isso se você entrar lá dentro...",,"Nu! Dacă o găsești, e a ta. Poate o poți folosi ca să ne ajuți să scăpăm de oprimare. Ți-aș ura noroc, dar o să ai noroc de mult mai mult decât atât dacă mergi acolo...","Нет! Если ты его найдёшь, он твой. Может быть, он поможет тебе освободить нас от гнёта. Я бы пожелал тебе удачи, но, если ты пойдёшь туда, простой удачи будет недостаточно...",,"Nej! Om du kan hitta den, får du behålla den. Du kanske kan använda den för att befria oss från vårt förtryck. Jag skulle önska dig lycka till, men du kommer att behöva mycket mer än så om du går in där...","Hayır! Eğer onu bulabilirsen, sende kalabilir. Belki onu bizi zulmümüzden kurtarmak için kullanabilirsin. Sana şans dilerdim, ama oraya girersen bundan çok daha fazlasına ihtiyacın olacak..." +What's all this about the past?,TXT_RPLY0_SCRIPT22_D4548_WHATS,〃,,,Cos to říkal o minulosti?,Hvad er alt det her med fortiden?,Was ist dieses ganze Gerede über die Vergangenheit?,,"Kio pri tiuj misteroj, kiujn vi menciis?",¿Qué hay de esos misterios que has mencionado?,¿Qué hay de esos misterios que mencionaste?,Mistä tässä kaikessa menneessä oikein on kyse?,Qu'est-ce que j'entends au sujet du passé?,És mi köze ennek a múlthoz?,E che mi dici riguardo a tutte ste storie del passato?,過去に何があったというんだ?,그 과거에 대해서 뭐가 어떻길레?,Wat is dit alles over het verleden?,Hva er alt dette om fortiden?,O co chodzi z tą przeszłością?,Que história é essa sobre o passado?,,Care e treaba cu trecutul ăsta?,Что такого творилось здесь в прошлом?,,Vad är allt det här om det förflutna?,Geçmişle ilgili tüm bu şeyler de ne? +"You've surely seen the other ruins nearby. It seems that the Comet which crashed on our planet is actually a space ship, and believe it or not, it originated on this very world a long time ago.",TXT_DLG_SCRIPT22_D6064_YOUVE,〃,,,"Určitě jsi zahlédnul ty zříceniny tady v okolí. Zdá se, že ta kometa, která narazila do naší planety, je ve skutečnosti vesmírná loď, která, věř nebo ne, kdysi dávno pocházela z tohoto světa.","Du har sikkert set de andre ruiner i nærheden. Det ser ud til, at den komet, der styrtede ned på vores planet, faktisk er et rumskib, og tro det eller ej, men det stammer fra denne verden for længe siden.","Du hast doch sicherlich die Ruinen hier in der Nähe gesehen. Es scheint als wäre der Komet, der hier auf dem Planeten aufgeschlagen ist, eigentlich ein Raumschiff, und ob du es glaubst oder nicht, aber es kam vor langer Zeit sogar von dieser Welt.",,"Vi eble vidis la proksimajn ruinojn. Ŝajnas, ke la kometo, kiu koliziis kontraŭ nia planedo, fakte estas kosmoŝipo, kaj kredeble aŭ ne, ĝi originis en ĉi tiu sama mondo antaŭ longe.","De seguro habrás visto las ruinas cerca de aquí. Al parecer el cometa que se estrelló en nuestro planeta es en realidad una nave espacial, y lo creas o no, se originó en este mismo mundo hace mucho.",,"Olet varmastikin nähnyt lähistön muut rauniot. Vaikuttaa siltä, että komeetta, joka törmäsi planeettaamme, on oikeasti avaruusalus; ja usko tai älä, se on alkuaan peräisin tästä samaisesta maailmasta kauan sitten.","Vous avez sans doute vu toutes ces ruines aux alentours. Il semble que la comète qui s'est écrasée sur notre planète était en fait un vaisseau spatial, et.. du moins si vous y croyez, venait aussi de notre planète, il y a très, très longtemps.","Bizonyára láttad a többi romot is. Úgy néz ki, a lehulló üstökös valójában egy űrhajó volt, és hiszed vagy sem, eredetileg erről a bolygóról indult sok évvel ezelőtt.","Sicuramente avrai visto le rovine qua vicino. Sembra che la cometa dell'impatto verso il nostro pianeta fosse in realtà una navicella spaziale, e so che può sembrare incredibile, ma la nave è originaria di questo mondo, di molto tempo fa.","君はこの周りの廃墟群を見てきたはずだ。 この星に衝突した彗星は、実は宇宙船だったのだ 信じられないかもしれないが、 -それは遥か前のこの乱世の始まりとも言える。","주변을 돌아다니면서 각종 폐허를 봤을 거야. 믿기지는 않겠지만, 하늘에서 갑자기 추락한 혜성은 정말로 혜성이 아니라 외계인들이 타고 내려온 우주선이라는 거야. 그리고 더 놀라운 사실은, 이 녀석들은 다 이곳에서 태어났데.","Je hebt zeker de andere ruïnes in de buurt gezien. Het lijkt erop dat de komeet die op onze planeet is neergestort, eigenlijk een ruimteschip is, en geloof het of niet, het is al lang geleden op deze wereld ontstaan.","Du har sikkert sett de andre ruinene i nærheten. Det ser ut til at kometen som krasjet på planeten vår faktisk er et romskip, og tro det eller ei, det kom fra denne verdenen for lenge siden.","Na pewno widziałeś inne ruiny w pobliżu. Wygląda na to, że Kometa, która rozbiła się na naszej planecie jest tak naprawdę statkiem kosmicznym i wierzcie lub nie, pochodziła z tego właśnie świata dawno temu.","Você certamente viu as outras ruínas aqui perto. Parece que o Cometa que caiu neste planeta é na verdade uma espaçonave e, acredite se quiser, ela veio deste nosso mundo há muito tempo atrás.",,"Cu siguranță ai vazut ruinele din apropiere. Se pare că Cometa care a căzut e de fapt o navă spațială, și crezi sau nu, e originară din lumea asta, de acum mult timp.","Скорее всего, ты уже видел эти руины. Тот метеорит, который упал на нашу планету, — на самом деле это космический корабль. Веришь или нет, его построили на этой самой планете, давным-давно.",,"Yakındaki diğer kalıntıları görmüşsünüzdür. Görünüşe göre gezegenimize çarpan Kuyruklu Yıldız aslında bir uzay gemisi ve ister inanın ister inanmayın, uzun zaman önce tam da bu dünyada ortaya çıkmış." -"So the spectres, the One God...",TXT_RPLY0_SCRIPT22_D6064_SOTHE,,,,"Takže přízraky, Jeden bůh...","Så spøgelserne, den ene gud...","Also die Schemen, der Eine Gott...",,,"O sea que los espectros, el Dios Único...",,"Joten aaveet, Yksi Ainoa Jumala...","Donc, les Spectres, le Seul Dieu..","Szóval a kísértetek, az egy isten...","Quindi gli spettri, l'Unico Dio..",だから霊の、唯一神...,그래서 그 스펙터들과 유일신이...,"Dus de schrikbeelden, de Ene God....","Så spøkelsene, den ene Gud...","Więc widma, Jedyny Bóg...","Então os espectros, o Deus Único...",,"Deci spectrele, Adevăratul Zeu...",Так фантомы и Единый Бог...,,"Yani hayaletler, Tek Tanrı." -"They are creatures who once ruled this world and are bent on consuming its life. The ancients managed to seal them away, but gave their lives in the process. I'm afraid that's all I know.",TXT_DLG_SCRIPT22_D7580_THEYA,,,,"Jsou stvoření, která dříve vládla tomuto světu a teď usilují o zničení všeho živého. Kdosi před námi byl schopen je zapečetit a přišel během toho o život. To je vše, co vím.","De er væsener, der engang herskede over denne verden og er opsat på at fortære dens liv. Det lykkedes de gamle at forsegle dem, men de gav deres liv i processen. Jeg er bange for, at det er alt, hvad jeg ved.","Das sind Wesen, die einst diese Welt regiert haben und sie ausbeuten wollen. Die Alten haben es geschafft, sie wegzusperren aber verloren ihr Leben dabei. Tut mir leid, das ist alles, was ich weiß",,,"Son criaturas que una vez dominaron este mundo e insisten en consumir su vida. Los antiguos consiguieron sellarlos, pero dieron sus vidas en el proceso. Me temo que eso es todo lo que sé.",,"Ne ovat olentoja, jotka kerran hallitsivat tätä maailmaa ja ovat nyt päättäneet hävittää sen elämästä. Muinaisten onnistui teljetä heidät ulos, mutta siinä samassa uhrasivat henkensä. Valitettavasti en tiedä tämän enempää.","Ce sont des créatures qui régnaient sur cette planète il y a longtemps, et étaient bornées à détruire toute vie sur sa surface, mais les anciens ont réussi à les sceller. Ils sont morts pour cela, j'ai peur que ce soit tout ce que je sais.","Ezek olyan lények, akik korábban a világot uralták, és mindenek felett meg akarják enni a világ életerejét. Az ősöknek sikerült őket elzárni, de bele is pusztultak a procedúrába. Attól félek, csak ennyit tudok mondani.","Sono tutte creature che una volta controllavano questo mondo e hanno come obiettivo consumarne la vita. Gli antichi riuscirono a isolarli, al costo della loro vita. Purtroppo è tutto quello che so.","奴等はかつてこの世界を支配していた生物で +それは遥か前のこの乱世の始まりとも言える。","주변을 돌아다니면서 각종 폐허를 봤을 거야. 믿기지는 않겠지만, 하늘에서 갑자기 추락한 혜성은 정말로 혜성이 아니라 외계인들이 타고 내려온 우주선이라는 거야. 그리고 더 놀라운 사실은, 이 녀석들은 다 이곳에서 태어났데.","Je hebt zeker de andere ruïnes in de buurt gezien. Het lijkt erop dat de komeet die op onze planeet is neergestort, eigenlijk een ruimteschip is, en geloof het of niet, het is al lang geleden op deze wereld ontstaan.","Du har sikkert sett de andre ruinene i nærheten. Det ser ut til at kometen som krasjet på planeten vår faktisk er et romskip, og tro det eller ei, det kom fra denne verdenen for lenge siden.","Na pewno widziałeś inne ruiny w pobliżu. Wygląda na to, że Kometa, która rozbiła się na naszej planecie jest tak naprawdę statkiem kosmicznym i wierzcie lub nie, pochodziła z tego właśnie świata dawno temu.","Você certamente viu as outras ruínas aqui perto. Parece que o Cometa que caiu neste planeta é na verdade uma espaçonave e, acredite se quiser, ela veio deste nosso mundo há muito tempo atrás.",,"Cu siguranță ai vazut ruinele din apropiere. Se pare că Cometa care a căzut e de fapt o navă spațială, și crezi sau nu, e originară din lumea asta, de acum mult timp.","Скорее всего, ты уже видел эти руины. Тот метеорит, который упал на нашу планету, — на самом деле это космический корабль. Веришь или нет, его построили на этой самой планете, давным-давно.",,"Du har säkert sett de andra ruinerna i närheten. Det verkar som om kometen som kraschade på vår planet faktiskt är ett rymdskepp, och tro det eller ej, den härstammar från just den här världen för länge sedan.","Yakındaki diğer kalıntıları görmüşsünüzdür. Görünüşe göre gezegenimize çarpan Kuyruklu Yıldız aslında bir uzay gemisi ve ister inanın ister inanmayın, uzun zaman önce tam da bu dünyada ortaya çıkmış." +"So the spectres, the One God...",TXT_RPLY0_SCRIPT22_D6064_SOTHE,〃,,,"Takže přízraky, Jeden bůh...","Så spøgelserne, den ene gud...","Also die Schemen, der Eine Gott...",,"Do la fantomoj, la Vera Dio...","O sea que los espectros, el Dios Único...",,"Joten aaveet, Yksi Ainoa Jumala...","Donc, les Spectres, le Seul Dieu..","Szóval a kísértetek, az egy isten...","Quindi gli spettri, l'Unico Dio..",だから霊の、唯一神...,그래서 그 스펙터들과 유일신이...,"Dus de schrikbeelden, de Ene God....","Så spøkelsene, den ene Gud...","Więc widma, Jedyny Bóg...","Então os espectros, o Deus Único...",,"Deci spectrele, Adevăratul Zeu...",Так фантомы и Единый Бог...,,"Så spökena, den enda guden...","Yani hayaletler, Tek Tanrı." +"They are creatures who once ruled this world and are bent on consuming its life. The ancients managed to seal them away, but gave their lives in the process. I'm afraid that's all I know.",TXT_DLG_SCRIPT22_D7580_THEYA,〃,,,"Jsou stvoření, která dříve vládla tomuto světu a teď usilují o zničení všeho živého. Kdosi před námi byl schopen je zapečetit a přišel během toho o život. To je vše, co vím.","De er væsener, der engang herskede over denne verden og er opsat på at fortære dens liv. Det lykkedes de gamle at forsegle dem, men de gav deres liv i processen. Jeg er bange for, at det er alt, hvad jeg ved.","Das sind Wesen, die einst diese Welt regiert haben und sie ausbeuten wollen. Die Alten haben es geschafft, sie wegzusperren aber verloren ihr Leben dabei. Tut mir leid, das ist alles, was ich weiß",,"Ili estas estaĵoj, kiuj iam dominis la mondon kaj insistas pri detrui ĝian vivon. La antikvuloj sukcese sigelfermis ilin koste de siaj vivoj. Mi timas, ke mi scias nenion plian.",Son criaturas que alguna vez dominaron el mundo e insisten en destruir toda forma de vida. Los antiguos lograron sellarlos a costa de sus vidas. Me temo que ya no sé más.,,"Ne ovat olentoja, jotka kerran hallitsivat tätä maailmaa ja ovat nyt päättäneet hävittää sen elämästä. Muinaisten onnistui teljetä heidät ulos, mutta siinä samassa uhrasivat henkensä. Valitettavasti en tiedä tämän enempää.","Ce sont des créatures qui régnaient sur cette planète il y a longtemps, et étaient bornées à détruire toute vie sur sa surface, mais les anciens ont réussi à les sceller. Ils sont morts pour cela, j'ai peur que ce soit tout ce que je sais.","Ezek olyan lények, akik korábban a világot uralták, és mindenek felett meg akarják enni a világ életerejét. Az ősöknek sikerült őket elzárni, de bele is pusztultak a procedúrába. Attól félek, csak ennyit tudok mondani.","Sono tutte creature che una volta controllavano questo mondo e hanno come obiettivo consumarne la vita. Gli antichi riuscirono a isolarli, al costo della loro vita. Purtroppo è tutto quello che so.","奴等はかつてこの世界を支配していた生物で 生命力をひたすら吸収する存在だった。 古代人が辛うじて封印したが、 その過程で彼らの命は奪われた。 -私が知っているのはそれだけだ。","한때 이 생물들은 이 세상을 지배했던 존재였어. 초월한 힘을 계속 유지하기 위해 온갖 생명력을 빨아먹어 왔던 거지. 태초의 사람들이 어떻게든 이 들을 봉인하긴 했지만, 많은 희생이 뒤따라야만 했지... 이게 내가 알고 있는 전부야.","Het zijn wezens die ooit over deze wereld heersten en die er op uit zijn om haar leven te consumeren. De Ouden slaagden erin om ze af te sluiten, maar gaven hun leven in het proces. Ik ben bang dat dat alles is wat ik weet.","De er vesener som en gang styrte denne verden og er oppsatt på å fortære dens liv. De gamle klarte å stenge dem inne, men ga sine liv i prosessen. Jeg er redd det er alt jeg vet.","To istoty, które kiedyś rządziły tym światem i mają zamiar pochłonąć jego życie. Starożytni zdołali je zapieczętować, ale oddali za to życie. Obawiam się, że to wszystko, co wiem.","São criaturas que uma vez dominavam este mundo e querem consumir toda a vida daqui. Os antigos conseguiram selá-los, mas deram suas vidas no processo. Infelizmente isso é tudo o que eu sei.",,"Sunt creaturi care au condus cândva lumea asta și sunt determinați să-i consume toată viața. Cei antici au reușit să-i alunge, dar și-au dat viața pentru a reuși. Mă tem că asta e tot ce știu.","Эти существа когда-то правили этим миром и стремились выжать из него все соки. Древние смогли запечатать и изгнать их, пожертвовав своими жизнями. Больше, боюсь, я ничего не знаю.",,Onlar bir zamanlar bu dünyaya hükmetmiş ve yaşamı tüketmeye kararlı yaratıklar. Eskiler onları mühürlemeyi başardılar ama bu süreçte canlarını verdiler. Korkarım tüm bildiğim bu. -Thanks... I'll do what I can.,TXT_RPLY0_SCRIPT22_D7580_THANK,,,,"Díky... Uvidím, co budu moct.","Tak... Jeg vil gøre, hvad jeg kan.",Danke. Ich werde tun was ich kann.,,,Gracias... Haré lo que pueda.,,"Kiitos; teen, minkä pystyn.",Merci.. Je vais faire ce que je peux.,Kösz...megteszem amit tudok.,Grazie... farò il possibile.,ありがとう...精一杯の事をしよう。,고... 고마워. 내가 할 수 있는 것을 찾아보지.,Bedankt... Ik zal doen wat ik kan.,Takk skal du ha... Jeg skal gjøre hva jeg kan.,"Dzięki... Zrobię, co w mojej mocy.",Obrigado... Farei o possível.,,Merci... O să fac ce pot.,"Спасибо... Я сделаю всё, что смогу.",,Teşekkürler. Elimden geleni yapacağım. -"Godspeed, friend.",TXT_DLG_SCRIPT22_D9096_GODSP,,,,"Zlom vaz, příteli.","Held og lykke, min ven.","Viel Erfolg, Freund.",,,"Buena suerte, amigo.",,"Onnea matkaan, ystävä.","Bonne chance, mon ami.","Isten veled, barátom.","Ti auguro davvero di farcela, amico mio.",急ぎたまえ、同志よ。,"행운을 비네, 친구.","Goeie reis, vriend.","Lykke til, min venn.","Powodzenia, przyjacielu.","Boa sorte, amigo.",,"Noroc, prietene.","Удачи, друг.",,"Yolun açık olsun, dostum." -Talk to the master Smithy if you have questions. All I do is put labels on the crates.,TXT_DLG_SCRIPT22_D10612_TALKT,,,,"Promluv si s mistrem Smithym, jestli se chceš na něco zeptat. Já jenom dávám štítky na krabice.","Tal med mester Smithy, hvis du har spørgsmål. Jeg sætter bare etiketter på kasserne.","Sprich mit dem Meister Smithy, wenn du Fragen hast. Ich versehe die Kisten nur mit Etiketten.",,,Habla con el maestro Smithy si tienes preguntas. Lo único que hago yo es etiquetar las cajas.,,"Puhu pajamestarin kanssa, jos sinulla on kysyttävää. Minä vain leimaan laatikoita.","Parlez au maître Smithy si vous avez des questions. Tout ce que je fais, c'est mettre des étiquettes sur des caisses.",Beszélj Smithy mesterrel ha van kérdésed. Én csak címkéket rakok a hordókra.,Parla con il mastro Smithy se hai delle domande. Il mio unico compito è catalogare gli scatoli.,"相談がある場合は鍛冶屋のマスターに仰って -下さい。私は箱にラベルを張っているだけです。",궁금한 게 있으면 스미시 제조장관님에게 물어봐. 내 업무는 상자에 표를 붙이는 것밖엔 없어.,Praat met meester Smithy als je vragen hebt. Het enige wat ik doe is etiketten op de kratten plakken.,"Snakk med smedmesteren hvis du har spørsmål. Alt jeg gjør, er å sette etiketter på kassene.","Porozmawiaj z mistrzem Smithy, jeśli masz pytania. Ja tylko naklejam etykiety na skrzyniach.",Fale com o mestre Smithy se tiver dúvidas. Tudo o que eu faço aqui é colocar etiquetas nas caixas.,,Vorbește cu maestrul Smithy dacă ai întrebări. Tot ce fac eu e să pun embleme pe cutii.,"Если у тебя есть какие-то вопросы, обратись к мастеру-кузнецу. Я просто клею ярлыки на ящики.",,Sorunuz olursa Demirci Usta ile konuşun. Tek yaptığım kasaların üzerine etiket yapıştırmak. -"What can I get you, citizen?",TXT_DLG_SCRIPT23_D0_WHATC,,,,"Co vám mohu nabídnout, občane?","Hvad kan jeg skaffe dig, borger?","Was darf es sein, Bürger?",,,"¿Qué puedo ofrecerte, ciudadano?",,"Mitä saisi olla, kansalainen?","Qu'est-ce que je peux faire pour vous, citoyen?","Miben segíthetek, polgártárs?","Che ti serve, cittadino?",何が入り用だ、お客さん?,"무엇을 줄까요, 형씨?","Wat kan ik voor je halen, burger?","Hva vil du ha, borger?","Co mogę ci dać, obywatelu?","Como posso ajudá-lo, cidadão?",,"Ce pot să-ți aduc, cetățeanule?","Что я могу тебе предложить, гражданин?",,"Sana ne verebilirim, vatandaş?" -Ammo box,TXT_RPLY0_SCRIPT23_D0_AMMOB,,,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Municikesto,Caja de municiones,,Ammuslaatikko,Boîte de munitions.,Lőszer doboz,Scatola di munizioni,銃弾倉,돌격소총 탄약 박스,Munitiedoos,En ammunisjonskasse.,Skrzynia z amunicją,Caixa de munição,,Cutie cu muniție,Коробку патронов,,Cephane kutusu -Here's your ammo.,TXT_RYES0_SCRIPT23_D0_HERES,,,,Tady je.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでソチラのブツだ。,탄약을 구매해줘서 고마워요.,Hier is je munitie.,Her er ammunisjonen din.,To twoja amunicja.,Aqui está a sua munição.,,Aici e muniția.,Вот твои патроны.,,İşte cephanen. -You don't have enough for that!,TXT_RNO0_SCRIPT23_D0_YOUDO,,,,Na tu nemáš dost peněz!,Du har ikke nok til det!,Du hast nich genug Gold!,,,¡No tienes suficiente para eso!,,Sinulla ei riitä rahat sitä varten!,Vous n'avez pas assez d'argent.,Nincs elég ehhez nálad!,Non hai abbastanza soldi per quello!,そんだけの金持ってないぞ!,가격에 맞게 돈을 가져오세요!,Daar heb je niet genoeg voor!,Du har ikke nok til det!,Nie masz na to dość!,Você não tem o suficiente para isto.,,Nu ai suficiente fonduri pentru asta.,У тебя недостаточно денег!,,Bunun için yeterince cephanen yok! -Crate of missiles,TXT_RPLY1_SCRIPT23_D0_CRATE,,,,Bednu raket,Kasse med missiler,Raketenkiste,,,Caja de misiles,,Ohjuslaatikko,Caisse de missiles.,Ládányi rakéta,Cassa di razzi,ミサイル箱,미니 미사일 박스,Krat van raketten,Kasse med raketter,Skrzynia z pociskami,Caixa de mísseis,,Cutie de rachete.,Коробку ракет,,Füze sandığı -"Here, citizen.",TXT_RYES1_SCRIPT23_D0_HEREC,,,,"Tady, občane.","Her, borger.","Hier, Bürger.",,,"Toma, ciudadano.",,"Tässä, kansalainen.","Voilà, citoyen.","Parancsolj, polgártárs.","Ecco qua, cittadino",どうぞ、お客さん。,여기 있습니다.,"Hier, burger.","Her, borger.","Proszę, obywatelu.","Aqui, cidadão.",,"Aici, orășene.","Вот, гражданин.",,"Buyur, vatandaş." -"It's 85 gold, citizen!",TXT_RNO1_SCRIPT23_D0_ITS85,,,,"Ta stojí 85 zlatých, občane!","Det koster 85 guld, borger!","Das macht 85 Gold, Bürger!",,,"¡Son 85 de oro, ciudadano!",,"Se maksaa 85 kolikkoa, kansalainen!","Cela coûte 85 pièces, citoyen!","85 arany lesz, polgártárs.","Sono 85 pezzi d'oro, cittadino!",85ゴールドだぜ、お客さん!,그건 85골드입니다.,"Het is 85 goud, burger!","Det er 85 gull, borger!","To 85 złotych, obywatelu!","Custa 85 moedas de ouro, cidadão!",,"E 85 de monezi, orășene!","Гражданин, это стоит 85 золотых!",,"85 altın, vatandaş!" -H-E grenades,TXT_RPLY2_SCRIPT23_D0_HEGRE,,,,Výbušné granáty,H-E granater,HE-Granaten,,,Granadas HE,,Räjähdekranaatteja,Grenades explosives.,Robbanó gránátok,Granate ad alto potenziale esplosivo,HEグレネード,고폭 유탄,H-E-granaten,H-E-granater,Granaty H-E,Granadas explosivas,,Grenade.,Осколочные гранаты,,H-E el bombaları -Here are your grenades.,TXT_RYES2_SCRIPT23_D0_HEREA,,,,Tady jsou.,Her er dine granater.,Hier sind deine Granaten.,,,Aquí tienes tus granadas.,,Tässä kranaattisi.,Voilà vos grenades.,Itt vannak a gránátaid.,Ecco le tue granate.,これでソチラのブツだ。,여기 유탄입니다.,Hier zijn je granaten.,Her er granatene dine.,Oto twoje granaty.,Aqui estão as suas granadas,,Aici sunt grenadele.,Забирай свои гранаты.,,İşte el bombaların. -"They are 100 gold, friend.",TXT_RNO2_SCRIPT23_D0_THEYA,,,,"Ty stojí sto zlatých, příteli.","De koster 100 guld, ven.","Sie kosten 100 Gold, mein Freund.",,,"Son 100 de oro, amigo.",,"Ne maksavat 100 kolikkoa, ystäväiseni.","Cela coûte 100 pièces, mon ami.",100 aranyba kerülnek polgártársam.,"Ti servono 100 pezzi d'oro, amico.",100ゴールドだぜ、旦那!,"그건 100 골드야, 친구.","Ze zijn 100 goud, vriend.","De koster 100 gull, min venn.","Kosztują 100 złota, przyjacielu.","Custam 100 moedas, amigo.",,"Costă 100 de monezi, prietene.","Они по 100 золотых, друг.",,"Onlar 100 altın, dostum." -Energy pod,TXT_RPLY3_SCRIPT23_D0_ENERG,,,,Energetický kokón,Energibælg,Energiezelle.,,,Vaina de energía,,Energia-akku,Cellule énergetique.,Energia cella,Nucleo energetico,エネルギーポッド,에너지 포드,Energiecapsule,Energikapsel,Strąk energii,Célula de energia.,,Capsulă energetică.,Энергоячейку,,Enerji kapsülü -Here you are.,TXT_RYES3_SCRIPT23_D0_HEREY,,,,Tady je.,Værsgo.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Eccolo qua.,どうぞ。,여기 있습니다.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici este.,Получай.,,Buyurun. -"That's 135 gold, sorry.",TXT_RNO3_SCRIPT23_D0_THATS,,,,"Ten stojí 135 zlatých, je mi líto.","Den koster 135 guld, beklager.","Entschuldigung, aber das macht 135 Gold.",,,"Son 135 de oro, lo siento.",,"Se 135 kolikkoa, valitan.","Cela coûte 135 pièces, désolé.","Sajnálom, de az 135 arany.","Mi spiace, ma costa 135 pezzi d'oro.",135ゴールドなんだ、ワリィ!,"미안하지만, 그건 135 골드입니다.","Dat is 135 goud, sorry.","Det er 135 gull, beklager.","To 135 złota, przepraszam.",Custa 135 moedas. Sinto muito.,,"Costă 135 de monezi, scuze.",Она стоит 135 золотых. Извини.,,"Bu 135 altın, üzgünüm." -What can I assist you with?,TXT_DLG_SCRIPT23_D1516_WHATC,,,,S čím vám mohu pomoci?,Hvad kan jeg hjælpe dig med?,Wie kann ich dir behilflich sein?,,Kiel mi helpu vin?,¿Con qué puedo ayudarte?,,Miten voin auttaa?,Commen puis-je vous assister?,Miben segíthetek?,Come posso esserti utile?,何か手伝いましょうか?,어떤 걸 도와드릴까요?,Waarmee kan ik je helpen?,Hva kan jeg hjelpe deg med?,W czym mogę ci pomóc?,Como posso ajudá-lo?,,Cu ce te pot ajuta?,Чем я могу тебе помочь?,,Size nasıl yardımcı olabilirim? -Leather armor,TXT_RPLY0_SCRIPT23_D1516_LEATH,,,Leather armour,Kožené brnění,Læder rustning,Lederrüstung,,Leda armaĵo,Armadura de cuero,,Nahkasuojus,Armure de cuir.,Bőr vért,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Skinnrustning.,Skórzana zbroja.,Armadura de couro,,Armură de piele,Кожаной бронёй,,Deri zırh -Here it is citizen.,TXT_RYES0_SCRIPT23_D1516_HEREI,,,,"Tady je, občane.","Her er den, borger.","Hier ist sie, Bürger.",,"Jen ĝi, civitano.","Aquí está, ciudadano.",,"Tässä on, kansalainen.","Voilà pour vous, citoyen.",Parancsolj.,"Ecco qua, cittadino.",どうぞ、お客さん。,"여기 있어요, 형씨.",Hier is het een burger.,"Her er den, borger.","Oto ona, obywatelu.","Aqui está, cidadão.",,Aici e orășene.,"Вот она, гражданин.",,İşte vatandaş. -There's no charity given here!,TXT_RNO0_SCRIPT23_D1516_THERE,,,,Nejsme charita!,Der gives ingen velgørenhed her!,Hier gibt es nichts umsonst!,,"Ĉi tio ne estas -almozulejo!",¡Aquí no damos limosna!,,Täällä ei harrasteta hyväntekeväisyyttä!,On n'est pas une charité ici.,"Sajnálom, ez nem jótékonyság.",Non facciamo beneficienza!,これはチャリティーじゃない!,돈이 부족하면 다른 곳을 알아봐! 여긴 자선단체가 아니라고!,Er wordt hier geen liefdadigheid gegeven!,Det er ingen veldedighet her!,Nie ma tu żadnej dobroczynności!,Aqui não é local de caridade!,,Nu facem caritate aici!,Я благотворительностью не занимаюсь!,,Burada sadaka verilmez! -Metal armor,TXT_RPLY1_SCRIPT23_D1516_METAL,,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metala armaĵo,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowa zbroja.,Armadura de metal,,Armură de metal,Металлической бронёй,,Metal zırh -An excellent choice citizen.,TXT_RYES1_SCRIPT23_D1516_ANEXC,,,,"Výborná volba, občane.","Et glimrende valg, borger.","Eine exzellente Wahl, Bürger.",,"Bonega elekto, civitano.","Excelente elección, -ciudadano.",,"Erinomainen valinta, kansalainen.","Un excellent choix, citoyen.",Kiváló választás polgártárs.,"Ottima scelta, cittadino.",良い選択です。,"탁월한 선택이십니다, 형씨.","Een uitstekende keuze, burger.","Et utmerket valg, borger.","Doskonały wybór, obywatelu.","Excelente escolha, cidadão.",,Excelentă alegere orășene.,"Отличный выбор, гражданин.",,Mükemmel bir seçim vatandaş. -You don't have enough for this!,TXT_RNO1_SCRIPT23_D1516_YOUDO,,,,Na to nemáte dost peněz!,Du har ikke nok til dette!,Du hast nich genug Gold dafür!,,"Vi ne havas -sufiĉe da mono!",¡No te alcanza!,,Rahasi ei riitä siihen!,Vous n'avez pas assez d'argent.,Nincs elég ehhez nálad!,Non hai abbastanza soldi per questo!,これでは足りない!,이것을 구입하기엔 돈이 부족합니다!,Je hebt hier niet genoeg voor!,Du har ikke nok til dette!,Nie masz na to dość!,Você não tem o suficiente para isto!,,Nu ai suficiente fonduri pentru asta!,У тебя недостаточно денег!,,Bunun için yeterli değilsin! -Environmental suit,TXT_RPLY2_SCRIPT23_D1516_ENVIR,,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirma vesto,Traje de protección ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védőruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Miljødrakt,Kombinezon ekologiczny,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитным костюмом,,Çevre kıyafeti -Here you are.,TXT_RYES2_SCRIPT23_D1516_HEREY,,,,Tady máte.,Værsgo.,Bitteschön.,,Jen.,Aquí tienes.,,Kas tässä.,Voilà pour vous.,"Itt van, parancsolj.",Eccola qua.,どうぞ。,여기 있습니다.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici este.,Держи.,,İşte buradasın. -"No money, no suit.",TXT_RNO2_SCRIPT23_D1516_NOMON,,,,Bez peněz pro oděvy nelez.,"Ingen penge, ingen dragt.","Kein Geld, kein Anzug.",,"Sen mono -ne estas vesto.",Sin dinero no hay traje.,,"Ei rahaa, ei pukua.","Pas d'argent, pas de combi.","Ha nincs pénz, nincs védőruha.","Niente denaro, niente completo.",金が無いならスーツは無しだ。,돈이 없다면 방호복을 줄 수 없습니다.,"Geen geld, geen pak.","Ingen penger, ingen drakt.","Nie ma pieniędzy, nie ma kombinezonu.","Sem dinheiro, sem traje.",,"Niciun ban, niciun costum.","Нет денег, нет костюма.",,"Para yok, takım elbise yok." -Something different?,TXT_RPLY3_SCRIPT23_D1516_SOMET,,,,Něco jiného?,Noget andet?,Irgendetwas anderes?,,,¿Algo distinto?,,Jotain erilaista?,Quelque chose d'autre?,Valami mást esetleg?,Qualcos'altro?,何か別のやつは?,뭔가 다른 거는?,Iets anders?,Noe annet?,Coś innego?,Algo diferente?,,Ceva diferit?,Что-нибудь ещё?,,Farklı bir şey mi var? -Go through the door down the hall.,TXT_RYES3_SCRIPT23_D1516_GOTHR,,,,Jděte dveřmi dole na chodbě.,Gå gennem døren nede ad gangen.,Geh durch die Tür zur Halle.,,,Ve por la puerta pasillo abajo.,,Mene ovesta käytävän päässä.,"Passez par la porte, vers le hall.",Menj át a csarnok végén levő ajtón.,Vai oltre la porta alla fine della stanza.,ホールのドアを通るんだ。,복도를 따라 문을 향해 가보세요.,Ga door de deur aan het einde van de gang.,Gå gjennom døren i gangen.,Przejdź przez drzwi na końcu korytarza.,Passe pela porta lá no salão.,,Intră pe ușa din josul holului.,"Дальше по коридору, за дверью.",,Koridorun sonundaki kapıdan geç. -You must pay if you want to play.,TXT_RNO3_SCRIPT23_D1516_YOUMU,,,,Chceš si hrát? Zaplať.,"Du skal betale, hvis du vil spille.","Du musst bezahlen, wenn du spielen willst.",,,Debes pagar si quieres jugar.,,"Ken leikkiin ryhtyy, se leikistä maksakoon.",Vous devez payer si vous voulez jouer.,Fizetned kell hogy játszhass.,Devi pagare se vuoi giocare.,プレイするなら支払うべきだ。,할려면 돈을 먼저 주세요.,Je moet betalen als je wilt spelen.,Du må betale hvis du vil spille.,"Musisz zapłacić, jeśli chcesz grać.",Você precisa pagar se quiser jogar.,,Trebuie să plătești dacă vrei să joci.,"Любишь играть, люби и платить!",,Oynamak istiyorsan ödeme yapmalısın. -What can I get you?,TXT_DLG_SCRIPT23_D3032_WHATC,,,,Co vám mohu nabídnout?,Hvad kan jeg give dig?,Was darf es sein?,,Kion mi donu al vi?,¿Qué puedo ofrecerte?,,Mitä teille saisi olla?,Que puis-je pour vous?,Mit adhatok?,Cosa ti porto?,何をお求めで?,무엇을 드릴까요?,Wat kan ik voor je halen?,Hva vil du ha?,Co mogę ci dać?,O que gostaria?,,Ce pot să-ți aduc?,Что я могу тебе предложить?,,Sana ne verebilirim? -Leather armor,TXT_RPLY0_SCRIPT23_D3032_LEATH,,,Leather armour,Kožené brnění,En læderrustning,Lederrüstung,,Ledan armaĵon,Armadura de cuero,,Nahkasuojus,Armure de cuir.,Bőr vért,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,En skinnrustning.,Skórzaną zbroję.,Armadura de couro,,Armură de piele,Кожаную броню,,Deri zırh. -"Here it is, citizen.",TXT_RYES0_SCRIPT23_D3032_HEREI,,,,"Tady je, občane.","Her er den, borger.","Hier ist sie, Bürger.",,"Jen ĝi, civitano.","Aquí está, ciudadano.",,"Tästä saat, kansalainen.","Voilà pour vous, citoyen.","Parancsolj, polgártárs.","Ecco qua, cittadino.",どうぞ、お客さん。,"적절히 입으세요, 시민.","Hier is het, burger.","Vær så god, borger.","Oto ona, obywatelu.","Aqui está, cidadão.",,"Aici este, orășene.","Вот она, гражданин.",,"İşte burada, vatandaş." -There's no charity given here!,TXT_RNO0_SCRIPT23_D3032_THERE,,,,Nejsme charita!,Der gives ingen velgørenhed her!,Hier gibt es nichts umsonst!,,"Ĉi tio ne estas -almozulejo!",¡Aquí no damos limosna!,,Tämä ei ole mikään hyväntekeväisyyspulju!,On n'est pas une charité ici.,"Sajnálom, ez nem jótékonyság.",Non facciamo beneficienza!,これはチャリティーじゃない!,딴 데 가서 구걸하세요!,Er wordt hier geen liefdadigheid gegeven!,Det er ingen veldedighet her!,Nie ma tu dobroczynności!,Aqui não é local de caridade!,,Nu facem caritate aici!,Я благотворительностью не занимаюсь!,,Burada sadaka verilmez! -Metal armor,TXT_RPLY1_SCRIPT23_D3032_METAL,,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowa zbroja.,Armadura de metal,,Armură de metal,Металлическую броню,,Metal zırh -An excellent choice citizen.,TXT_RYES1_SCRIPT23_D3032_ANEXC,,,,"Výborná volba, občane.","Et fremragende valg, borger.","Eine exzellente Wahl, Bürger.",,"Bonega elekto, civitano.","Excelente elección, -ciudadano.",,"Erinomainen valinta, kansalainen.","Un excellent choix, citoyen.",Kiváló választás polgártárs.,"Ottima scelta, cittadino.",良い選択だ。,탄탄한 게 잘 보호해준답니다.,Een uitstekende keuze voor de burger.,"Et utmerket valg, borger.",Doskonały wybór obywatelu.,"Excelente escolha, cidadão.",,Excelentă alegere orășene.,"Отличный выбор, гражданин.",,Mükemmel bir seçim vatandaş. -You don't have enough for this!,TXT_RNO1_SCRIPT23_D3032_YOUDO,,,,Na to nemáte dost peněz!,Du har ikke nok til dette!,Du hast nich genug Gold dafür!,,"Vi ne havas -sufiĉe da mono!",¡No te alcanza!,,Sinulla ei rahat riitä siihen!,Vous n'avez pas assez d'argent.,Nincs elég ehhez nálad!,Non hai abbastanza soldi per questo!,これでは足りない!,돈이 부족합니다. 다른 건 어떠신가요?,Je hebt hier niet genoeg voor!,Du har ikke nok til dette!,Nie masz na to dość!,Você não tem o suficiente para isto!,,Nu ai suficiente fonduri pentru asta!,У тебя недостаточно денег!,,Bunun için yeterli değilsin! -Environmental suit,TXT_RPLY2_SCRIPT23_D3032_ENVIR,,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje de protección ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védő ruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Miljødrakt,Kombinezon ekologiczny,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитный костюм,,Çevre kıyafeti -Here you are.,TXT_RYES2_SCRIPT23_D3032_HEREY,,,,Tady máte.,Her er du.,Bitteschön.,,Jen.,Aquí tienes.,,Olkaa hyvä.,Voilà pour vous.,Parancsolj.,Eccoti qui.,どうぞ。,여기 받으세요!,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici este.,Держи.,,İşte buradasın. -"No money, no suit.",TXT_RNO2_SCRIPT23_D3032_NOMON,,,,Bez peněz pro oděvy nelez.,"Ingen penge, ingen dragt.","Kein Geld, kein Anzug.",,"Sen mono -ne estas vesto.",Sin dinero no hay traje.,,"Ei rahaa, ei pukua.","Pas d'argent, pas de combi.","Ha nincs pénz, nincs védőruha.","Niente denaro, niente completo.",金が無いならスーツは無しだ。,방호복을 사기엔 돈이 부족합니다.,"Geen geld, geen pak.","Ingen penger, ingen drakt.","Nie ma pieniędzy, nie ma kombinezonu.","Sem dinheiro, sem traje.",,"Niciun ban, niciun costum.","Нет денег, нет костюма.",,"Para yok, takım elbise yok." -How can I help you today?,TXT_DLG_SCRIPT23_D4548_HOWCA,,,,S čím vám mohu dnes pomoci?,Hvordan kan jeg hjælpe dig i dag?,Wie kann ich dir heute weiterhelfen?,,Kiel mi helpu vin hodiaŭ?,¿Cómo puedo ayudarte hoy?,,Miten voin tänään olla avuksi?,Comment puis-je vous aider aujourd'hui?,Miben segíthetek ezen a szép napon?,Come posso aiutarti oggi?,本日は何の用で?,환영합니다. 뭔가 필요하신지요?,Hoe kan ik u vandaag helpen?,Hvordan kan jeg hjelpe deg i dag?,Jak mogę ci dziś pomóc?,Como posso ajudá-lo hoje?,,Cu ce te pot ajuta azi?,Чем я могу тебе помочь сегодня?,,Bugün size nasıl yardımcı olabilirim? -Med patch,TXT_RPLY0_SCRIPT23_D4548_MEDPA,,,,Obvazy,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekäärettä,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster,Bandaż,Compressa médica,,Bandaj medical,Бинтами,,İlaç yaması -Here's your patch.,TXT_RYES0_SCRIPT23_D4548_HERES,,,,Tady jsou.,Her er dit plaster.,Hier ist deine Bandage.,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä kääreesi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これが貴方のパッチです。,의료 붕대 하나. 경마한 부상에 쓰시길.,Hier is je patch.,Her er plasteret ditt.,Oto twój bandaż.,Aqui está sua compressa.,,Aici e bandajul.,Вот твой набор бинтов.,,İşte yaman. -That is 15 gold my friend.,TXT_RNO0_SCRIPT23_D4548_THATI,,,,"Ty stojí patnáct zlatých, příteli.","Det er 15 guld, min ven.","Das macht 15 Gold, mein Freund.",,"Ili kostas 15 da oro, amiko.","Son 15 de oro, amigo.",,"Se maksaa 15 kolikkoa, ystäväiseni.","15 pièces pour ça, mon ami.",15 arany lesz barátocskám.,Sono 15 pezzi d'oro amico mio.,これは15ゴールドですよ。,15 골드가 없습니까? 유감이군요.,"Dat is 15 goud, mijn vriend.","Det er 15 gull, min venn.","To jest 15 złota, mój przyjacielu.","Custa 15 moedas de ouro, meu amigo.",,E 15 monezi prietene.,"Они стоят 15 монет, друг.",,Bu 15 altın dostum. -Medical kit,TXT_RPLY1_SCRIPT23_D4548_MEDIC,,,,Lékárničku,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku,Kit médical.,Elsősegély doboz,Kit medico,医療用キット,구급 키트,Medische kit,Medisinsk utstyr,Zestaw medyczny,Kit médico,,Kit medical,Аптечкой,,Tıbbi kit -Here's your medical kit.,TXT_RYES1_SCRIPT23_D4548_HERES,,,,Tady je.,Her er dit medicinske kit.,Hier ist dein Verbandskasten,,Jen via sukurkesto.,Aquí tienes tu botiquín.,,Tässä lääkintälaukkusi.,Voilà votre kit médical.,Itt az elsősegély dobozod.,Ecco il tuo kid medico.,これが貴方のキットです。,구급 키트는 아주 유용하죠. 잘 쓰시길!,Hier is je medische uitrusting.,Her er medisinskrinet ditt.,Oto twój zestaw medyczny.,Aqui está o seu kit médico,,Aici e kitul medical.,Вот твоя аптечка.,,İşte tıbbi çantan. -Your a bit low on funds for that.,TXT_RNO1_SCRIPT23_D4548_YOURA,,,,Na tu nemáte dost.,Du har lidt for få midler til det.,Du hast zu wenig Geld dafür.,,Mankas mono al vi.,Estás algo falto de dinero.,,Rahasi eivät ihan riitä siihen.,Vous manquez d'argent pour ça.,Kevés lesz a pénzed ehhez most.,Sei un pò a corto di fondi per quello.,お金が少し足りませんよ。,돈이 부족하군요. 못 줍니다!,Je hebt daar een beetje weinig geld voor.,Du har litt lite penger til det.,Trochę brakuje ci na to funduszy.,Você está um pouco mal de dinheiro pra isso.,,Cam puțini bani pentru aia.,Тебе на это не хватает средств.,,Bunun için biraz az paran var. -Field surgery kit,TXT_RPLY2_SCRIPT23_D4548_FIELD,,,,Chirurgickou soupravu,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Kirurgisett,Zestaw do chirurgii polowej,Kit de cirurgia,,Kit chirurgical de teren.,Медкомплектом,,Saha ameliyat kiti -One field surgery kit.,TXT_RYES2_SCRIPT23_D4548_ONEFI,,,,Jedna souprava.,Et kirurgisæt.,"Eine Erste-Hilfe-Kasten, kommt sofort.",,Kirurgia kesto. Farite.,Un kit quirúrgico. Listo.,,"Yksi kirurgilaukku, tässä.","Un kit de chirurgie, voilà.","Parancsolj, egy műtéti felszerelés.","Un kit chirurgico, eccolo qua.",手術キット一丁。,아주 위박한 상황에 쓰시길. 여기 수술 키트입니다!,Een veldoperatiekit.,Ett kirurgisk sett.,Jeden zestaw do chirurgii polowej.,Um kit de cirurgia.,,"Un kit chirurgical de teren, gata.",Один медкомплект. Держи.,,Bir saha ameliyat kiti. -Come back when you have money!,TXT_RNO2_SCRIPT23_D4548_COMEB,,,,"Vrať se, až budeš mít peníze!","Kom tilbage, når du har penge!","Komm wieder, wenn du etwas Geld hast.",,"Revenu kiam vi +私が知っているのはそれだけだ。","한때 이 생물들은 이 세상을 지배했던 존재였어. 초월한 힘을 계속 유지하기 위해 온갖 생명력을 빨아먹어 왔던 거지. 태초의 사람들이 어떻게든 이 들을 봉인하긴 했지만, 많은 희생이 뒤따라야만 했지... 이게 내가 알고 있는 전부야.","Het zijn wezens die ooit over deze wereld heersten en die er op uit zijn om haar leven te consumeren. De Ouden slaagden erin om ze af te sluiten, maar gaven hun leven in het proces. Ik ben bang dat dat alles is wat ik weet.","De er vesener som en gang styrte denne verden og er oppsatt på å fortære dens liv. De gamle klarte å stenge dem inne, men ga sine liv i prosessen. Jeg er redd det er alt jeg vet.","To istoty, które kiedyś rządziły tym światem i mają zamiar pochłonąć jego życie. Starożytni zdołali je zapieczętować, ale oddali za to życie. Obawiam się, że to wszystko, co wiem.","São criaturas que uma vez dominavam este mundo e querem consumir toda a vida daqui. Os antigos conseguiram selá-los, mas deram suas vidas no processo. Infelizmente isso é tudo o que eu sei.",,"Sunt creaturi care au condus cândva lumea asta și sunt determinați să-i consume toată viața. Cei antici au reușit să-i alunge, dar și-au dat viața pentru a reuși. Mă tem că asta e tot ce știu.","Эти существа когда-то правили этим миром и стремились выжать из него все соки. Древние смогли запечатать и изгнать их, пожертвовав своими жизнями. Больше, боюсь, я ничего не знаю.",,"De är varelser som en gång styrde den här världen och är fast beslutna att förtära dess liv. De gamla lyckades försegla dem, men gav sina liv i processen. Jag är rädd att det är allt jag vet.",Onlar bir zamanlar bu dünyaya hükmetmiş ve yaşamı tüketmeye kararlı yaratıklar. Eskiler onları mühürlemeyi başardılar ama bu süreçte canlarını verdiler. Korkarım tüm bildiğim bu. +Thanks... I'll do what I can.,TXT_RPLY0_SCRIPT22_D7580_THANK,〃,,,"Díky... Uvidím, co budu moct.","Tak... Jeg vil gøre, hvad jeg kan.",Danke. Ich werde tun was ich kann.,,Dankon... Mi faros ĉion eblan.,Gracias... Haré lo que pueda.,Gracias... Voy a hacer lo que pueda.,"Kiitos; teen, minkä pystyn.",Merci.. Je vais faire ce que je peux.,Kösz...megteszem amit tudok.,Grazie... farò il possibile.,ありがとう...精一杯の事をしよう。,고... 고마워. 내가 할 수 있는 것을 찾아보지.,Bedankt... Ik zal doen wat ik kan.,Takk skal du ha... Jeg skal gjøre hva jeg kan.,"Dzięki... Zrobię, co w mojej mocy.",Obrigado... Farei o possível.,,Merci... O să fac ce pot.,"Спасибо... Я сделаю всё, что смогу.",,Tack... Jag ska göra vad jag kan.,Teşekkürler. Elimden geleni yapacağım. +"Godspeed, friend.",TXT_DLG_SCRIPT22_D9096_GODSP,〃,,,"Zlom vaz, příteli.","Held og lykke, min ven.","Viel Erfolg, Freund.",,"Ŝancon, amiko.","Buena suerte, amigo.",,"Onnea matkaan, ystävä.","Bonne chance, mon ami.","Isten veled, barátom.","Ti auguro davvero di farcela, amico mio.",急ぎたまえ、同志よ。,"행운을 비네, 친구.","Goeie reis, vriend.","Lykke til, min venn.","Powodzenia, przyjacielu.","Boa sorte, amigo.",,"Noroc, prietene.","Удачи, друг.",,"Lycka till, min vän.","Yolun açık olsun, dostum." +Talk to the master Smithy if you have questions. All I do is put labels on the crates.,TXT_DLG_SCRIPT22_D10612_TALKT,"SVE.WAD +MAP22: C-shaped building → Apprentice.",,,"Promluv si s mistrem Smithym, jestli se chceš na něco zeptat. Já jenom dávám štítky na krabice.","Tal med mester Smithy, hvis du har spørgsmål. Jeg sætter bare etiketter på kasserne.","Sprich mit dem Meister Smithy, wenn du Fragen hast. Ich versehe die Kisten nur mit Etiketten.",,Parolu kun la majstro Smithy se vi havas demandojn. Mi limas min etiketi skatolojn.,Habla con el maestro Smithy si tienes preguntas. Lo único que hago yo es etiquetar las cajas.,,"Puhu pajamestarin kanssa, jos sinulla on kysyttävää. Minä vain leimaan laatikoita.","Parlez au maître Smithy si vous avez des questions. Tout ce que je fais, c'est mettre des étiquettes sur des caisses.",Beszélj Smithy mesterrel ha van kérdésed. Én csak címkéket rakok a hordókra.,Parla con il mastro Smithy se hai delle domande. Il mio unico compito è catalogare gli scatoli.,"相談がある場合は鍛冶屋のマスターに仰って +下さい。私は箱にラベルを張っているだけです。",궁금한 게 있으면 스미시 제조장관님에게 물어봐. 내 업무는 상자에 표를 붙이는 것밖엔 없어.,Praat met meester Smithy als je vragen hebt. Het enige wat ik doe is etiketten op de kratten plakken.,"Snakk med smedmesteren hvis du har spørsmål. Alt jeg gjør, er å sette etiketter på kassene.","Porozmawiaj z mistrzem Smithy, jeśli masz pytania. Ja tylko naklejam etykiety na skrzyniach.",Fale com o mestre Smithy se tiver dúvidas. Tudo o que eu faço aqui é colocar etiquetas nas caixas.,,Vorbește cu maestrul Smithy dacă ai întrebări. Tot ce fac eu e să pun embleme pe cutii.,"Если у тебя есть какие-то вопросы, обратись к мастеру-кузнецу. Я просто клею ярлыки на ящики.",,Prata med mästersmeden om du har frågor. Allt jag gör är att sätta etiketter på lådorna.,Sorunuz olursa Demirci Usta ile konuşun. Tek yaptığım kasaların üzerine etiket yapıştırmak. +"What can I get you, citizen?",TXT_DLG_SCRIPT23_D0_WHATC,MAP23: Weapons,,,"Co vám mohu nabídnout, občane?","Hvad kan jeg skaffe dig, borger?","Was darf es sein, Bürger?",,"Kion mi donu al vi, civitano?","¿Qué puedo ofrecerte, ciudadano?",,"Mitä saisi olla, kansalainen?","Qu'est-ce que je peux faire pour vous, citoyen?","Miben segíthetek, polgártárs?","Che ti serve, cittadino?",何が入り用だ、お客さん?,"무엇을 줄까요, 형씨?","Wat kan ik voor je halen, burger?","Hva vil du ha, borger?","Co mogę ci dać, obywatelu?","Como posso ajudá-lo, cidadão?",,"Ce pot să-ți aduc, cetățeanule?","Что я могу тебе предложить, гражданин?",,"Vad vill du ha, medborgare?","Sana ne verebilirim, vatandaş?" +Ammo box,TXT_RPLY0_SCRIPT23_D0_AMMOB,〃,,,Krabici nábojů,Ammo kasse,Munitionsschachtel,,Munici-keston,Caja de municiones,,Ammuslaatikko,Boîte de munitions.,Lőszer doboz,Scatola di munizioni,銃弾倉,돌격소총 탄약 박스,Munitiedoos,En ammunisjonskasse.,Skrzynia z amunicją,Caixa de munição,,Cutie cu muniție,Коробку патронов,,Ammunitionslåda,Cephane kutusu +Here's your ammo.,TXT_RYES0_SCRIPT23_D0_HERES,〃,,,Tady je.,Her er din ammunition.,Hier ist deine Munition.,,Jen via municio.,Aquí está tu munición.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでソチラのブツだ。,탄약을 구매해줘서 고마워요.,Hier is je munitie.,Her er ammunisjonen din.,To twoja amunicja.,Aqui está a sua munição.,,Aici e muniția.,Вот твои патроны.,,Här är din ammunition.,İşte cephanen. +You don't have enough for that!,TXT_RNO0_SCRIPT23_D0_YOUDO,〃,,,Na tu nemáš dost peněz!,Du har ikke nok til det!,Du hast nich genug Gold!,,"Vi ne havas +sufiĉe da mono!",¡No te alcanza para eso!,,Sinulla ei riitä rahat sitä varten!,Vous n'avez pas assez d'argent.,Nincs elég ehhez nálad!,Non hai abbastanza soldi per quello!,そんだけの金持ってないぞ!,가격에 맞게 돈을 가져오세요!,Daar heb je niet genoeg voor!,Du har ikke nok til det!,Nie masz na to dość!,Você não tem o suficiente para isto.,,Nu ai suficiente fonduri pentru asta.,У тебя недостаточно денег!,,Du har inte tillräckligt med ammunition för det!,Bunun için yeterince cephanen yok! +Crate of missiles,TXT_RPLY1_SCRIPT23_D0_CRATE,〃,,,Bednu raket,Kasse med missiler,Raketenkiste,,Misilet-keston,Caja de minimisiles,,Ohjuslaatikko,Caisse de missiles.,Ládányi rakéta,Cassa di razzi,ミサイル箱,미니 미사일 박스,Krat van raketten,Kasse med raketter,Skrzynia z pociskami,Caixa de mísseis,,Cutie de rachete.,Коробку ракет,,Låda med missiler,Füze sandığı +"Here, citizen.",TXT_RYES1_SCRIPT23_D0_HEREC,〃,,,"Tady, občane.","Her, borger.","Hier, Bürger.",,"Jen, civitano.","Toma, ciudadano.",,"Tässä, kansalainen.","Voilà, citoyen.","Parancsolj, polgártárs.","Ecco qua, cittadino",どうぞ、お客さん。,여기 있습니다.,"Hier, burger.","Her, borger.","Proszę, obywatelu.","Aqui, cidadão.",,"Aici, orășene.","Вот, гражданин.",,"Här, medborgare.","Buyur, vatandaş." +"It's 85 gold, citizen!",TXT_RNO1_SCRIPT23_D0_ITS85,〃,,,"Ta stojí 85 zlatých, občane!","Det koster 85 guld, borger!","Das macht 85 Gold, Bürger!",,"Ĝi kostas 85 da oro, +civitano!","¡Son 85 de oro, ciudadano!",,"Se maksaa 85 kolikkoa, kansalainen!","Cela coûte 85 pièces, citoyen!","85 arany lesz, polgártárs.","Sono 85 pezzi d'oro, cittadino!",85ゴールドだぜ、お客さん!,그건 85골드입니다.,"Het is 85 goud, burger!","Det er 85 gull, borger!","To 85 złotych, obywatelu!","Custa 85 moedas de ouro, cidadão!",,"E 85 de monezi, orășene!","Гражданин, это стоит 85 золотых!",,"Det är 85 guld, medborgare!","85 altın, vatandaş!" +H-E grenades,TXT_RPLY2_SCRIPT23_D0_HEGRE,〃,,,Výbušné granáty,H-E granater,HE-Granaten,,Eksplodeg-povajn grenadojn,Granadas de conmoción,,Räjähdekranaatteja,Grenades explosives.,Robbanó gránátok,Granate ad alto potenziale esplosivo,HEグレネード,고폭 유탄,H-E-granaten,H-E-granater,Granaty H-E,Granadas explosivas,,Grenade.,Осколочные гранаты,,H-E-granater,H-E el bombaları +Here are your grenades.,TXT_RYES2_SCRIPT23_D0_HEREA,〃,,,Tady jsou.,Her er dine granater.,Hier sind deine Granaten.,,Jen viaj grenadoj.,Aquí tienes tus granadas.,,Tässä kranaattisi.,Voilà vos grenades.,Itt vannak a gránátaid.,Ecco le tue granate.,これでソチラのブツだ。,여기 유탄입니다.,Hier zijn je granaten.,Her er granatene dine.,Oto twoje granaty.,Aqui estão as suas granadas,,Aici sunt grenadele.,Забирай свои гранаты.,,Här är dina granater.,İşte el bombaların. +"They are 100 gold, friend.",TXT_RNO2_SCRIPT23_D0_THEYA,〃,,,"Ty stojí sto zlatých, příteli.","De koster 100 guld, ven.","Sie kosten 100 Gold, mein Freund.",,"Ili kostas cent da oro, +amiko!","Son cien de oro, amigo.",,"Ne maksavat 100 kolikkoa, ystäväiseni.","Cela coûte 100 pièces, mon ami.",100 aranyba kerülnek polgártársam.,"Ti servono 100 pezzi d'oro, amico.",100ゴールドだぜ、旦那!,"그건 100 골드야, 친구.","Ze zijn 100 goud, vriend.","De koster 100 gull, min venn.","Kosztują 100 złota, przyjacielu.","Custam 100 moedas, amigo.",,"Costă 100 de monezi, prietene.","Они по 100 золотых, друг.",,"De kostar 100 guld, vän.","Onlar 100 altın, dostum." +Energy pod,TXT_RPLY3_SCRIPT23_D0_ENERG,〃,,,Energetický kokón,Energibælg,Energiezelle.,,Energi-kapsulon,Cápsula de energía,,Energia-akku,Cellule énergetique.,Energia cella,Nucleo energetico,エネルギーポッド,에너지 포드,Energiecapsule,Energikapsel,Strąk energii,Célula de energia.,,Capsulă energetică.,Энергоячейку,,Energipod,Enerji kapsülü +Here you are.,TXT_RYES3_SCRIPT23_D0_HEREY,〃,,,Tady je.,Værsgo.,Bitteschön.,,Jen.,Toma.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Eccolo qua.,どうぞ。,여기 있습니다.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici este.,Получай.,,Här är den.,Buyurun. +"That's 135 gold, sorry.",TXT_RNO3_SCRIPT23_D0_THATS,〃,,,"Ten stojí 135 zlatých, je mi líto.","Den koster 135 guld, beklager.","Entschuldigung, aber das macht 135 Gold.",,"Ĝi kostas 135 da oro. +Pardonon.","Son 135 de oro, lo siento.",,"Se 135 kolikkoa, valitan.","Cela coûte 135 pièces, désolé.","Sajnálom, de az 135 arany.","Mi spiace, ma costa 135 pezzi d'oro.",135ゴールドなんだ、ワリィ!,"미안하지만, 그건 135 골드입니다.","Dat is 135 goud, sorry.","Det er 135 gull, beklager.","To 135 złota, przepraszam.",Custa 135 moedas. Sinto muito.,,"Costă 135 de monezi, scuze.",Она стоит 135 золотых. Извини.,,"Den kostar 135 guld, tyvärr.","Bu 135 altın, üzgünüm." +What can I assist you with?,TXT_DLG_SCRIPT23_D1516_WHATC,MAP23: Armory (with Tevick locked).,,,S čím vám mohu pomoci?,Hvad kan jeg hjælpe dig med?,Wie kann ich dir behilflich sein?,,Kion vi bezonas?,¿Con qué puedo ayudarte?,,Miten voin auttaa?,Commen puis-je vous assister?,Miben segíthetek?,Come posso esserti utile?,何か手伝いましょうか?,어떤 걸 도와드릴까요?,Waarmee kan ik je helpen?,Hva kan jeg hjelpe deg med?,W czym mogę ci pomóc?,Como posso ajudá-lo?,,Cu ce te pot ajuta?,Чем я могу тебе помочь?,,Vad kan jag hjälpa dig med?,Size nasıl yardımcı olabilirim? +Leather armor,TXT_RPLY0_SCRIPT23_D1516_LEATH,〃,,Leather armour,Kožené brnění,Læder rustning,Lederrüstung,,Ledan armaĵon,Armadura de cuero,,Nahkasuojus,Armure de cuir.,Bőr vért,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Skinnrustning.,Skórzana zbroja.,Armadura de couro,,Armură de piele,Кожаной бронёй,,Läderrustning,Deri zırh +Here it is citizen.,TXT_RYES0_SCRIPT23_D1516_HEREI,〃,,,"Tady je, občane.","Her er den, borger.","Hier ist sie, Bürger.",,"Jen, civitano.","Toma, ciudadano.",,"Tässä on, kansalainen.","Voilà pour vous, citoyen.",Parancsolj.,"Ecco qua, cittadino.",どうぞ、お客さん。,"여기 있어요, 형씨.",Hier is het een burger.,"Her er den, borger.","Oto ona, obywatelu.","Aqui está, cidadão.",,Aici e orășene.,"Вот она, гражданин.",,"Här är den, medborgare.",İşte vatandaş. +There's no charity given here!,TXT_RNO0_SCRIPT23_D1516_THERE,〃,,,Nejsme charita!,Der gives ingen velgørenhed her!,Hier gibt es nichts umsonst!,,"Ĉi tio ne estas +almozulejo!",¡Aquí no damos limosna!,,Täällä ei harrasteta hyväntekeväisyyttä!,On n'est pas une charité ici.,"Sajnálom, ez nem jótékonyság.",Non facciamo beneficienza!,これはチャリティーじゃない!,돈이 부족하면 다른 곳을 알아봐! 여긴 자선단체가 아니라고!,Er wordt hier geen liefdadigheid gegeven!,Det er ingen veldedighet her!,Nie ma tu żadnej dobroczynności!,Aqui não é local de caridade!,,Nu facem caritate aici!,Я благотворительностью не занимаюсь!,,Det finns ingen välgörenhet här!,Burada sadaka verilmez! +Metal armor,TXT_RPLY1_SCRIPT23_D1516_METAL,〃,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowa zbroja.,Armadura de metal,,Armură de metal,Металлической бронёй,,Metall rustning,Metal zırh +An excellent choice citizen.,TXT_RYES1_SCRIPT23_D1516_ANEXC,〃,,,"Výborná volba, občane.","Et glimrende valg, borger.","Eine exzellente Wahl, Bürger.",,"Bonega elekto, civitano.","Excelente elección, +ciudadano.",,"Erinomainen valinta, kansalainen.","Un excellent choix, citoyen.",Kiváló választás polgártárs.,"Ottima scelta, cittadino.",良い選択です。,"탁월한 선택이십니다, 형씨.","Een uitstekende keuze, burger.","Et utmerket valg, borger.","Doskonały wybór, obywatelu.","Excelente escolha, cidadão.",,Excelentă alegere orășene.,"Отличный выбор, гражданин.",,"Ett utmärkt val, medborgare.",Mükemmel bir seçim vatandaş. +You don't have enough for this!,TXT_RNO1_SCRIPT23_D1516_YOUDO,〃,,,Na to nemáte dost peněz!,Du har ikke nok til dette!,Du hast nich genug Gold dafür!,,"Vi ne havas +sufiĉe da mono!",¡No te alcanza!,,Rahasi ei riitä siihen!,Vous n'avez pas assez d'argent.,Nincs elég ehhez nálad!,Non hai abbastanza soldi per questo!,これでは足りない!,이것을 구입하기엔 돈이 부족합니다!,Je hebt hier niet genoeg voor!,Du har ikke nok til dette!,Nie masz na to dość!,Você não tem o suficiente para isto!,,Nu ai suficiente fonduri pentru asta!,У тебя недостаточно денег!,,Du har inte tillräckligt för detta!,Bunun için yeterli değilsin! +Environmental suit,TXT_RPLY2_SCRIPT23_D1516_ENVIR,〃,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje NBQ,,Ympäristösuojapuku,Combinaison Hazmat.,Védőruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Miljødrakt,Kombinezon ekologiczny,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитным костюмом,,Miljödräkt,Çevre kıyafeti +Here you are.,TXT_RYES2_SCRIPT23_D1516_HEREY,〃,,,Tady máte.,Værsgo.,Bitteschön.,,Jen.,Toma.,,Kas tässä.,Voilà pour vous.,"Itt van, parancsolj.",Eccola qua.,どうぞ。,여기 있습니다.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici este.,Держи.,,Här är du.,İşte buradasın. +"No money, no suit.",TXT_RNO2_SCRIPT23_D1516_NOMON,〃,,,Bez peněz pro oděvy nelez.,"Ingen penge, ingen dragt.","Kein Geld, kein Anzug.",,"Sen mono +ne estas vesto.",Sin dinero no hay traje.,,"Ei rahaa, ei pukua.","Pas d'argent, pas de combi.","Ha nincs pénz, nincs védőruha.","Niente denaro, niente completo.",金が無いならスーツは無しだ。,돈이 없다면 방호복을 줄 수 없습니다.,"Geen geld, geen pak.","Ingen penger, ingen drakt.","Nie ma pieniędzy, nie ma kombinezonu.","Sem dinheiro, sem traje.",,"Niciun ban, niciun costum.","Нет денег, нет костюма.",,"Inga pengar, ingen dräkt.","Para yok, takım elbise yok." +Something different?,TXT_RPLY3_SCRIPT23_D1516_SOMET,〃,,,Něco jiného?,Noget andet?,Irgendetwas anderes?,,Ion alian...?,¿Algo distinto?,,Jotain erilaista?,Quelque chose d'autre?,Valami mást esetleg?,Qualcos'altro?,何か別のやつは?,뭔가 다른 거는?,Iets anders?,Noe annet?,Coś innego?,Algo diferente?,,Ceva diferit?,Что-нибудь ещё?,,Något annat?,Farklı bir şey mi var? +Go through the door down the hall.,TXT_RYES3_SCRIPT23_D1516_GOTHR,〃,,,Jděte dveřmi dole na chodbě.,Gå gennem døren nede ad gangen.,Geh durch die Tür zur Halle.,,"Iru ĉe Tevick en la +dekstra ĉambro.","Con Tevick en la +habitación a la derecha.",,Mene ovesta käytävän päässä.,"Passez par la porte, vers le hall.",Menj át a csarnok végén levő ajtón.,Vai oltre la porta alla fine della stanza.,ホールのドアを通るんだ。,복도를 따라 문을 향해 가보세요.,Ga door de deur aan het einde van de gang.,Gå gjennom døren i gangen.,Przejdź przez drzwi na końcu korytarza.,Passe pela porta lá no salão.,,Intră pe ușa din josul holului.,"Дальше по коридору, за дверью.",,Gå genom dörren i korridoren.,Koridorun sonundaki kapıdan geç. +You must pay if you want to play.,TXT_RNO3_SCRIPT23_D1516_YOUMU,〃,,,Chceš si hrát? Zaplať.,"Du skal betale, hvis du vil spille.","Du musst bezahlen, wenn du spielen willst.",,Nenio estas senpaga.,Nada es gratis.,,"Ken leikkiin ryhtyy, se leikistä maksakoon.",Vous devez payer si vous voulez jouer.,Fizetned kell hogy játszhass.,Devi pagare se vuoi giocare.,プレイするなら支払うべきだ。,할려면 돈을 먼저 주세요.,Je moet betalen als je wilt spelen.,Du må betale hvis du vil spille.,"Musisz zapłacić, jeśli chcesz grać.",Você precisa pagar se quiser jogar.,,Trebuie să plătești dacă vrei să joci.,"Любишь играть, люби и платить!",,Du måste betala om du vill spela.,Oynamak istiyorsan ödeme yapmalısın. +What can I get you?,TXT_DLG_SCRIPT23_D3032_WHATC,MAP23: Armory (with Tevick unlocked).,,,Co vám mohu nabídnout?,Hvad kan jeg give dig?,Was darf es sein?,,Kion mi donu al vi?,¿Qué puedo ofrecerte?,,Mitä teille saisi olla?,Que puis-je pour vous?,Mit adhatok?,Cosa ti porto?,何をお求めで?,무엇을 드릴까요?,Wat kan ik voor je halen?,Hva vil du ha?,Co mogę ci dać?,O que gostaria?,,Ce pot să-ți aduc?,Что я могу тебе предложить?,,Vad kan jag ge dig?,Sana ne verebilirim? +Leather armor,TXT_RPLY0_SCRIPT23_D3032_LEATH,〃,,Leather armour,Kožené brnění,En læderrustning,Lederrüstung,,Ledan armaĵon,Armadura de cuero,,Nahkasuojus,Armure de cuir.,Bőr vért,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,En skinnrustning.,Skórzaną zbroję.,Armadura de couro,,Armură de piele,Кожаную броню,,En läderrustning,Deri zırh. +"Here it is, citizen.",TXT_RYES0_SCRIPT23_D3032_HEREI,〃,,,"Tady je, občane.","Her er den, borger.","Hier ist sie, Bürger.",,"Jen, civitano.","Toma, ciudadano.",,"Tästä saat, kansalainen.","Voilà pour vous, citoyen.","Parancsolj, polgártárs.","Ecco qua, cittadino.",どうぞ、お客さん。,"적절히 입으세요, 시민.","Hier is het, burger.","Vær så god, borger.","Oto ona, obywatelu.","Aqui está, cidadão.",,"Aici este, orășene.","Вот она, гражданин.",,"Här är den, medborgare.","İşte burada, vatandaş." +There's no charity given here!,TXT_RNO0_SCRIPT23_D3032_THERE,〃,,,Nejsme charita!,Der gives ingen velgørenhed her!,Hier gibt es nichts umsonst!,,"Ĉi tio ne estas +almozulejo!",¡Aquí no damos limosna!,,Tämä ei ole mikään hyväntekeväisyyspulju!,On n'est pas une charité ici.,"Sajnálom, ez nem jótékonyság.",Non facciamo beneficienza!,これはチャリティーじゃない!,딴 데 가서 구걸하세요!,Er wordt hier geen liefdadigheid gegeven!,Det er ingen veldedighet her!,Nie ma tu dobroczynności!,Aqui não é local de caridade!,,Nu facem caritate aici!,Я благотворительностью не занимаюсь!,,Det finns ingen välgörenhet här!,Burada sadaka verilmez! +Metal armor,TXT_RPLY1_SCRIPT23_D3032_METAL,〃,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metall rustning,Metalowa zbroja.,Armadura de metal,,Armură de metal,Металлическую броню,,Metallrustning,Metal zırh +An excellent choice citizen.,TXT_RYES1_SCRIPT23_D3032_ANEXC,〃,,,"Výborná volba, občane.","Et fremragende valg, borger.","Eine exzellente Wahl, Bürger.",,"Bonega elekto, civitano.","Excelente elección, +ciudadano.",,"Erinomainen valinta, kansalainen.","Un excellent choix, citoyen.",Kiváló választás polgártárs.,"Ottima scelta, cittadino.",良い選択だ。,탄탄한 게 잘 보호해준답니다.,Een uitstekende keuze voor de burger.,"Et utmerket valg, borger.",Doskonały wybór obywatelu.,"Excelente escolha, cidadão.",,Excelentă alegere orășene.,"Отличный выбор, гражданин.",,"Ett utmärkt val, medborgare.",Mükemmel bir seçim vatandaş. +You don't have enough for this!,TXT_RNO1_SCRIPT23_D3032_YOUDO,〃,,,Na to nemáte dost peněz!,Du har ikke nok til dette!,Du hast nich genug Gold dafür!,,"Vi ne havas +sufiĉe da mono!",¡No te alcanza!,,Sinulla ei rahat riitä siihen!,Vous n'avez pas assez d'argent.,Nincs elég ehhez nálad!,Non hai abbastanza soldi per questo!,これでは足りない!,돈이 부족합니다. 다른 건 어떠신가요?,Je hebt hier niet genoeg voor!,Du har ikke nok til dette!,Nie masz na to dość!,Você não tem o suficiente para isto!,,Nu ai suficiente fonduri pentru asta!,У тебя недостаточно денег!,,Du har inte tillräckligt för detta!,Bunun için yeterli değilsin! +Environmental suit,TXT_RPLY2_SCRIPT23_D3032_ENVIR,〃,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje NBQ,,Ympäristösuojapuku,Combinaison Hazmat.,Védő ruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Miljødrakt,Kombinezon ekologiczny,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитный костюм,,Miljödräkt,Çevre kıyafeti +Here you are.,TXT_RYES2_SCRIPT23_D3032_HEREY,〃,,,Tady máte.,Her er du.,Bitteschön.,,Jen.,Toma.,,Olkaa hyvä.,Voilà pour vous.,Parancsolj.,Eccoti qui.,どうぞ。,여기 받으세요!,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici este.,Держи.,,Här är du.,İşte buradasın. +"No money, no suit.",TXT_RNO2_SCRIPT23_D3032_NOMON,〃,,,Bez peněz pro oděvy nelez.,"Ingen penge, ingen dragt.","Kein Geld, kein Anzug.",,"Sen mono +ne estas vesto.",Sin dinero no hay traje.,,"Ei rahaa, ei pukua.","Pas d'argent, pas de combi.","Ha nincs pénz, nincs védőruha.","Niente denaro, niente completo.",金が無いならスーツは無しだ。,방호복을 사기엔 돈이 부족합니다.,"Geen geld, geen pak.","Ingen penger, ingen drakt.","Nie ma pieniędzy, nie ma kombinezonu.","Sem dinheiro, sem traje.",,"Niciun ban, niciun costum.","Нет денег, нет костюма.",,"Inga pengar, ingen dräkt.","Para yok, takım elbise yok." +How can I help you today?,TXT_DLG_SCRIPT23_D4548_HOWCA,MAP23: Hospital,,,S čím vám mohu dnes pomoci?,Hvordan kan jeg hjælpe dig i dag?,Wie kann ich dir heute weiterhelfen?,,Kiel mi helpu vin hodiaŭ?,¿Cómo puedo ayudarte hoy?,,Miten voin tänään olla avuksi?,Comment puis-je vous aider aujourd'hui?,Miben segíthetek ezen a szép napon?,Come posso aiutarti oggi?,本日は何の用で?,환영합니다. 뭔가 필요하신지요?,Hoe kan ik u vandaag helpen?,Hvordan kan jeg hjelpe deg i dag?,Jak mogę ci dziś pomóc?,Como posso ajudá-lo hoje?,,Cu ce te pot ajuta azi?,Чем я могу тебе помочь сегодня?,,Hur kan jag hjälpa dig i dag?,Bugün size nasıl yardımcı olabilirim? +Med patch,TXT_RPLY0_SCRIPT23_D4548_MEDPA,〃,,,Obvazy,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekäärettä,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster,Bandaż,Compressa médica,,Bandaj medical,Бинтами,,Medicinsk plåster,İlaç yaması +Here's your patch.,TXT_RYES0_SCRIPT23_D4548_HERES,〃,,,Tady jsou.,Her er dit plaster.,Hier ist deine Bandage.,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä kääreesi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これが貴方のパッチです。,의료 붕대 하나. 경마한 부상에 쓰시길.,Hier is je patch.,Her er plasteret ditt.,Oto twój bandaż.,Aqui está sua compressa.,,Aici e bandajul.,Вот твой набор бинтов.,,Här är ditt plåster.,İşte yaman. +That is 15 gold my friend.,TXT_RNO0_SCRIPT23_D4548_THATI,〃,,,"Ty stojí patnáct zlatých, příteli.","Det er 15 guld, min ven.","Das macht 15 Gold, mein Freund.",,"Ili kostas dek kvin +da oro, amiko.","Son quince de oro, amigo.",,"Se maksaa 15 kolikkoa, ystäväiseni.","15 pièces pour ça, mon ami.",15 arany lesz barátocskám.,Sono 15 pezzi d'oro amico mio.,これは15ゴールドですよ。,15 골드가 없습니까? 유감이군요.,"Dat is 15 goud, mijn vriend.","Det er 15 gull, min venn.","To jest 15 złota, mój przyjacielu.","Custa 15 moedas de ouro, meu amigo.",,E 15 monezi prietene.,"Они стоят 15 монет, друг.",,"Det är 15 guld, min vän.",Bu 15 altın dostum. +Medical kit,TXT_RPLY1_SCRIPT23_D4548_MEDIC,〃,,,Lékárničku,Medicinsk kit,Verbandskasten,,Sukurkesto,Botiquín,,Lääkintälaukku,Kit médical.,Elsősegély doboz,Kit medico,医療用キット,구급 키트,Medische kit,Medisinsk utstyr,Zestaw medyczny,Kit médico,,Kit medical,Аптечкой,,Medicinsk utrustning,Tıbbi kit +Here's your medical kit.,TXT_RYES1_SCRIPT23_D4548_HERES,〃,,,Tady je.,Her er dit medicinske kit.,Hier ist dein Verbandskasten,,Jen via sukurkesto.,Aquí tienes tu botiquín.,,Tässä lääkintälaukkusi.,Voilà votre kit médical.,Itt az elsősegély dobozod.,Ecco il tuo kid medico.,これが貴方のキットです。,구급 키트는 아주 유용하죠. 잘 쓰시길!,Hier is je medische uitrusting.,Her er medisinskrinet ditt.,Oto twój zestaw medyczny.,Aqui está o seu kit médico,,Aici e kitul medical.,Вот твоя аптечка.,,Här är ditt medicinska utrustning.,İşte tıbbi çantan. +Your a bit low on funds for that.,TXT_RNO1_SCRIPT23_D4548_YOURA,〃,,,Na tu nemáte dost.,Du har lidt for få midler til det.,Du hast zu wenig Geld dafür.,,Mankas mono al vi.,Estás algo falto de dinero.,,Rahasi eivät ihan riitä siihen.,Vous manquez d'argent pour ça.,Kevés lesz a pénzed ehhez most.,Sei un po' a corto di fondi per quello.,お金が少し足りませんよ。,돈이 부족하군요. 못 줍니다!,Je hebt daar een beetje weinig geld voor.,Du har litt lite penger til det.,Trochę brakuje ci na to funduszy.,Você está um pouco mal de dinheiro pra isso.,,Cam puțini bani pentru aia.,Тебе на это не хватает средств.,,Du har inte så mycket pengar för det.,Bunun için biraz az paran var. +Field surgery kit,TXT_RPLY2_SCRIPT23_D4548_FIELD,〃,,,Chirurgickou soupravu,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Kirurgisett,Zestaw do chirurgii polowej,Kit de cirurgia,,Kit chirurgical de teren.,Медкомплектом,,Fältkirurgisk utrustning,Saha ameliyat kiti +One field surgery kit.,TXT_RYES2_SCRIPT23_D4548_ONEFI,〃,,,Jedna souprava.,Et kirurgisæt.,"Eine Erste-Hilfe-Kasten, kommt sofort.",,Kirurgia kesto. Farite.,Un kit quirúrgico. Listo.,,"Yksi kirurgilaukku, tässä.","Un kit de chirurgie, voilà.","Parancsolj, egy műtéti felszerelés.","Un kit chirurgico, eccolo qua.",手術キット一丁。,아주 위박한 상황에 쓰시길. 여기 수술 키트입니다!,Een veldoperatiekit.,Ett kirurgisk sett.,Jeden zestaw do chirurgii polowej.,Um kit de cirurgia.,,"Un kit chirurgical de teren, gata.",Один медкомплект. Держи.,,Ett fältkirurgiskt utrustning.,Bir saha ameliyat kiti. +Come back when you have money!,TXT_RNO2_SCRIPT23_D4548_COMEB,〃,,,"Vrať se, až budeš mít peníze!","Kom tilbage, når du har penge!","Komm wieder, wenn du etwas Geld hast.",,"Revenu kiam vi havos monon!","¡Vuelve cuando -tengas dinero!",,"Tule takaisin, kun sinulla on rahaa!",Revenez quand vous avez des sous?,"Akkor gyere vissza, ha pénzed is lesz!",Torna quando avrai del denaro!,お金が有る時にまた!,"돈이 많이 있으면 모를까, 살 수 없을겁니다!",Kom terug als je geld hebt!,Kom tilbake når du har penger!,"Wróć, gdy będziesz miał pieniądze!",Volte quando tiver dinheiro!,,Revino când o să ai bani!,Возвращайся с деньгами!,,Paran olduğunda geri gel! -"Hello friend, what can I get you?",TXT_DLG_SCRIPT23_D6064_HELLO,,,,"Zdravím, příteli, co pro vás mohu udělat?","Hej ven, hvad kan jeg give dig?","Hallo Freund, was darf es sein?",,,"Hola amigo, ¿Qué puedo ofrecerte?",,"Tervehdys, ystävä; miten voin olla avuksi?","Bienvenu, l'ami, que puis-je pour vous?","Szevasz barátom, miben segíthetek?","Salve amico, cosa posso darti?",よう旦那、何が必要だ?,좋은 하루! 뭐 필요한거라도?,"Hallo vriend, wat kan ik voor je halen?","Hei venn, hva kan jeg gi deg?","Witaj przyjacielu, co mogę ci dać?","Olá amigo, como posso te ajudar?",,"Bună prietene, ce pot să-ți aduc?","Привет, друг. Могу я тебе что-нибудь предложить?",,"Merhaba arkadaşım, sana ne getirebilirim?" -Information,TXT_RPLY0_SCRIPT23_D6064_INFOR,,,,Informace,Information,Informationen,,,Información,,Tietoa.,Des infos.,Információ,Informazioni,情報,정보 있습니까?,Informatie,Informasjon.,Informacje,Informações,,Informație,Информацию,,Bilgi -"I've never seen anyone go in or out of the factory, the forcefield's always up.",TXT_RYES0_SCRIPT23_D6064_IVENE,,,,Nikdy jsem nikoho neviděl vcházet do ani vycházet z továrny. Silové pole je vždycky zapnuté.,"Jeg har aldrig set nogen gå ind eller ud af fabrikken, kraftfeltet er altid oppe.","Ich habe noch niemanden gesehen, der die Fabrik betreten oder verlassen hat. Das Kraftfeld ist immer aktiv.",,,"Nunca he visto a nadie entrar o salir de la fábrica, el campo de fuerza siempre está encendido.",,En ole nähnyt kenenkään koskaan menevän tai tulevan tehtaasta; voimakenttä on aina päällä.,Je n'ai jamais vu quelqu'un rentrer dans l'usine. Les champs de force sont toujours en ligne.,"Nem láttam még senkit ki- vagy be menni a gyárból, az erőpajzs mindig be van kapcsolva.","Non ho mai visto nessuno entrare o uscire dalla fabbrica, il campo di forza è sempre attivo.","誰も工場を出入りしている所を見ていない、 -フォースフィールドがずっと付いてる。",공장에서 나오는 사람들을 전혀 못 봤어. 방어막이 꺼지는 일이 없었으니까.,"Ik heb nog nooit iemand in of uit de fabriek zien gaan, het krachtveld is altijd in orde.","Jeg har aldri sett noen gå inn eller ut av fabrikken, kraftfeltet er alltid oppe.","Nigdy nie widziałem nikogo wchodzącego ani wychodzącego z fabryki, pole siłowe jest zawsze podniesione.",Nunca vi alguém entrar ou sair da fábrica. O campo de força está sempre ativado.,,"N-am văzut niciodată pe cineva intrând sau ieșind din fabrică, câmpul de forță e mereu activ.","Никогда не видел, чтобы кто-нибудь приходил или уходил с фабрики. Поле всегда включено.",,"Kimsenin fabrikaya girip çıktığını görmedim, güç alanı her zaman açık." -"No money, no info.",TXT_RNO0_SCRIPT23_D6064_NOMON,,,,"Žádné peníze, žádné informace.","Ingen penge, ingen info.","Kein Geld, keine Informationen.",,,Sin dinero no hay información.,,"Ei tuohta, ei tietoa.","Pas d'argent, pas d'infos.","Ha nincs pénz, nincs infó.","Niente denaro, niente informazioni.",金が無いなら情報は無しだ。,"돈 없으면, 정보도 없다네.","Geen geld, geen informatie.","Ingen penger, ingen informasjon.","Nie ma pieniędzy, nie ma informacji.","Sem grana, nada de informações.",,"Niciun ban, nicio informație.",Нет денег — нет сведений.,,"Para yok, bilgi yok." -"Yes, what would you like?",TXT_DLG_SCRIPT23_D7580_YESWH,,,,"Ano, co byste si přál?","Ja, hvad vil du gerne have?","Ja, was darf es sein?",,,"Sí, ¿Qué quieres?",,"Niin, mitä saisi olla?","Oui, que voulez-vous?","Igen, milyen érdekelne?","Sì, che posso darti?",はい、どうしたい?,"아, 무엇을 원하는가?","Ja, wat wil je graag?","Ja, hva vil du ha?","Tak, czego chcesz?","Sim, o que você gostaria?",,"Da, ce ai dori?",Да? Что ты хотел?,,"Evet, ne istiyorsunuz?" -More info.,TXT_RPLY0_SCRIPT23_D7580_MOREI,,,,Další informace.,Mere info.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Più informazioni.,更なる情報,정보가 필요해요.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multă informație.,Ещё сведений.,,Daha fazla bilgi. -The factory's built on the comet's impact site. I don't think it's by chance.,TXT_RYES0_SCRIPT23_D7580_THEFA,,,,"Továrnu postavili na místě dopadu komety. Nemyslím si, že to je náhoda.","Fabrikken er bygget på kometens nedslagssted. Jeg tror ikke, det er tilfældigt.","Die Fabrik wurde dort gebaut, wo der Komet eingeschlagen ist. Ich denke nicht, dass das Zufall ist.",,,La fábrica está construida sobre el lugar de impacto del cometa. No creo que sea casualidad.,,"Tehdas on rakennettu komeetan törmäyspaikalle; enkä usko, että sattumalta.",L'usine est construite sur le site d'impact de la comète. Je ne crois pas que c'est une coïncidence.,A gyár a becsapódott üstökösre épült. Biztosan nem lehet véletlen.,La fabbrica è stata costruita sopra il sito d'impatto della cometa. Non credo sia una coincidenza.,"工場は彗星の衝突地点に建っている。 -これは偶然だと思えない。",공장은 혜성이 충돌한 지점에서 건설되었다네. 우연으로 건설된 게 아니라고 생각해.,De fabriek is gebouwd op de impact van de komeet site. Ik denk niet dat het toeval is.,Fabrikken er bygget på kometens nedslagssted. Jeg tror ikke det er tilfeldig.,"Fabryka została zbudowana na miejscu uderzenia komety. Nie sądzę, żeby to był przypadek.",A fábrica foi construída no local de impacto do cometa. Não acho que tenha sido por acaso.,,Fabrica e construită pe locul de prăbușire al cometei. Nu cred că e o coincidență.,"Фабрика была построена в кратере от падения метеорита. Не думаю, что это случайность.",,Fabrika kuyruklu yıldızın çarpma alanına inşa edildi. Bunun tesadüf olduğunu sanmıyorum. -"Come on, it's a measly 5 gold.",TXT_RNO0_SCRIPT23_D7580_COMEO,,,,"No tak, chci pouhých pět zlatých.","Kom nu, det er sølle 5 guld.","Komm schon, es sind doch nur 5 mickrige Goldstücke.",,,"Venga, solo 5 míseras monedas de oro.",,"Hei, antaisit nyt vaivaiset viisi kolikkoa.","Allez, ça ne coûte que 5 pièces!","Nemár, francos 5 arany.","Andiamo, sono solo 5 pezzi d'oro.",頼むぜ、たった5ゴールドだぞ。,5 골드 정도 하는데 말이지.,"Kom op, het is een miezerige 5 goud.","Kom igjen, det er sølle fem gull.","Daj spokój, to marne 5 złotych.","Vamos lá, custa só 5 moedinhas.",,"Haide, sunt 5 bănuți amărâți.","Ну же, всего-то 5 золотых.",,"Hadi ama, sadece 5 altın." -"Hello again, what'll it be?",TXT_DLG_SCRIPT23_D9096_HELLO,,,,"Opět zdravím, co to bude?","Hej igen, hvad bliver det?",Willkommen zurück. Was darf es sein?,,,"Hola otra vez, ¿Qué va a ser?",,"Hei taas, mitä kaipaat?","Rebonjour, que puis-je pour vous?","Üdv újra itt, mit kérsz?","Chi si rivede, che cosa c'è?",また来たな、何か頼むか?,다시 만났군. 오늘은 어떤 걸?,"Hallo nogmaals, wat zal het zijn?","Hallo igjen, hva skal det være?","Witam ponownie, co to będzie?",Olá de novo. O que vai ser desta vez?,,"Bună din nou, ce dorești?",И снова привет. Что на этот раз?,,"Tekrar merhaba, ne alırdınız?" -More info.,TXT_RPLY0_SCRIPT23_D9096_MOREI,,,,Další informace.,Mere info.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,更なる情報,더 많은 정보를 원해요.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multă informație.,Ещё информацию.,,Daha fazla bilgi. -The factory closed when the Order unveiled its new horror: the Inquisitor.,TXT_RYES0_SCRIPT23_D9096_THEFA,,,,Továrnu zavřeli když Řád odkryl svou novou hrůzu: Inkvizitora.,"Fabrikken lukkede, da Ordenen afslørede sin nye rædsel: Inquisitoren.","Die Fabrik wurde geschlossen, als der Orden seinen neuesten Horror enthült hat: Den Inquisitor.",,,La fábrica cerró cuando la Orden desveló su nuevo horror: el inquisidor.,,"Tehdas suljettiin, kun Veljeskunta paljasti sen uuden kauhistuksen: inkvisiittorin.","L'usine a été fermée quand l'Ordre a révélé sa nouvelle atrocité, L'inquisiteur.","A gyár bezárt, amikor a Rend leleplezte a nagyközönség előtt az új horrorát: az Inkvizítort.",La fabbrica è stata chiusa quando l'Ordine ha rivelato il suo nuovo orrore: l'Inquisitore,"工場はオーダーの「新審問官」が来てから -恐ろしい雰囲気を纏った。",오더가 획기적이고 무서운 병기들을 생산한 후 공장의 문을 닫았다네. 그것들의 이름은 '인퀴지터'지.,De fabriek werd gesloten toen de Orde haar nieuwe horror onthulde: de inquisiteur.,Fabrikken stengte da Ordenen avduket sin nye skrekk: Inkvisitoren.,"Fabryka została zamknięta, gdy Zakon zaprezentował swój nowy horror: Inkwizytora.",A fábrica fechou quando a Ordem revelou o seu novo horror: o Inquisidor.,,Fabrica s-a închis când Ordinul a dezvăluit noua sa oroare: Inchizitorul.,"Фабрика закрылась, когда Орден показал своё новое страшилище — инквизитора.",,"Fabrika, Tarikat yeni dehşeti Cezacı'yı tanıttığında kapandı." -5 gold please.,TXT_RNO0_SCRIPT23_D9096_5GOLD,,,,"Pět zlatých, prosim.","5 guld, tak.","5 Gold, bitte.",,,5 de oro por favor.,,"5 kolikkoa, kiitos.","5 pièces, s'il vous plaît.",5 arany lesz.,"Sono 5 pezzi d'oro, prego.",5ゴールドかかるぜ。,먼저 5 골드를 주게나.,5 goud alsjeblieft.,"5 gull, takk.",Proszę o 5 sztuk złota.,5 moedas por favor.,,5 bani te rog.,"5 золотых, пожалуйста.",,5 altın lütfen. -"That's all I know. Even bartenders run out of stuff to say, sorry.",TXT_DLG_SCRIPT23_D10612_THATS,,,,"To je vše, co vím. I barmani občas nemají, co dál říct, promiňte.","Det er alt, hvad jeg ved. Selv bartendere løber tør for ting at sige, undskyld.","Das ist alles was ich weiß. Selbst ein Barkeeper hat irgendwann keine Neugikeiten mehr, tut mir Leid.",,,"Eso es todo lo que sé. Incluso los taberneros se quedan sin cosas que decir, lo siento.",,"Siinä kaikki, mitä tiedän. Jopa baarimikoilta loppuvat jutun aiheet, pahoittelen.","C'est tout ce que je sais. Même les barmans peuvent arriver à court d'infos, désolé.","Ennyit tudok. Még a bárpultos tudása sem végtelen, sajnálom.","È tutto ciò che so. Anche i baristi hanno un limite alla loro conoscienza, mi spiace.","知ってることはこれで全部だ。 -バーテンダーの噂は売切れだ、すまない。",이 바텐더는 꺼낼 수 있는 모든 조언을 꺼냈다네. 미안.,"Dat is alles wat ik weet. Zelfs de barmannen hebben niet veel meer te zeggen, sorry.","Det er alt jeg vet. Selv bartendere går tom for ting å si, beklager.","To wszystko, co wiem. Nawet barmanom kończy się to, co można powiedzieć, przepraszam.","Isso é tudo o que eu sei. Até donos de bar acabam ficando sem algo pra dizer uma hora, sinto muito.",,"Asta e tot ce știu, până și barmanii rămân fără chestii de zis.","Это всё, что я знаю. Даже у хозяев таверн заканчиваются темы для болтовни, увы.",,"Tek bildiğim bu. Barmenlerin bile söyleyecek bir şeyleri kalmadı, üzgünüm." -Hello.,TXT_DLG_SCRIPT23_D12128_HELLO,,,,Ahoj.,Hej.,Hallo.,,Saluton.,Hola.,,Hei.,Bonjour.,Helló.,Ciao.,こんにちは。,안녕하세요.,Hallo.,Hallo.,Witam.,Olá.,,Salut.,Привет.,,Merhaba. -What are you doing?,TXT_RPLY0_SCRIPT23_D12128_WHATA,,,,Co tady děláš?,Hvad laver du?,Was machst du?,,Kion vi faras?,¿Qué estás haciendo?,,Mitä teet?,Qu'est-ce que vous faites?,Mit csinálsz?,Che cosa stai facendo?,何してるんだ?,뭐하는 거죠?,Wat ben je aan het doen?,Hva driver du med?,Co robisz?,O que você está fazendo?,,Ce faci?,Чем ты занимаешься?,,Ne yapıyorsun? -"I'm doing stuff, go away!",TXT_RYES0_SCRIPT23_D12128_IMDOI,,,,"Dělám věci, vypadni!","Jeg laver noget, gå væk!","Ich mach' halt was, geh weg!",,,"Estoy haciendo cosas, ¡Lárgate!",,"Teen juttuja, mene pois!","Je suis occupé, laissez-moi tranquille!","Épp elfoglalt vagyok, tünj innen!","Sto sbrigando delle cose, vattene!",今は立て込んでる、離れなさい!,별거 아닙니다. 방해하지 말고 저리 가세요!,"Ik doe dingen, ga weg!","Jeg gjør ting, gå vekk!","Robię różne rzeczy, odejdź!","Estou fazendo coisas, vá embora!",,"Am treabă, pleacă!",Ерундой всякой. Отвали!,,"Bir şeyler yapıyorum, git başımdan!" -"Now, what can I help you with?",TXT_DLG_SCRIPT23_D13644_NOWWH,,,,"Tak, s čím ti mohu pomoci?",Hvad kan jeg hjælpe dig med?,"Nun, wie kann ich dir weiterhelfen?",,,"Ahora, ¿En qué puedo ayudarte?",,"No niin, miten voin palvella?","Bon, que puis-je pour vous?","Na, miben segíthetek?","E ora, come posso aiutarti?",今手伝ってくれるか?,"자, 제가 뭘 도와드릴까요?","Nu, waar kan ik je mee helpen?",Hva kan jeg hjelpe deg med?,"A teraz, w czym mogę ci pomóc?","Então, como posso ajudá-lo?",,"Acum, cu ce te pot ajuta?","Итак, чем я могу быть тебе полезен?",,"Şimdi, sana nasıl yardımcı olabilirim?" -Shadow armor?,TXT_RPLY0_SCRIPT23_D13644_SHADO,,,Shadow armour?,Stínové brnění?,Skygge rustning?,Schattenrüstung?,,,¿Armadura de sombra?,,Varjohaarniska?,Armure des ombres?,Árnyék vért?,Armatura Ombra?,シャドウアーマー?,그림자 갑옷?,Schaduw harnas?,Skyggepanser?,Zbroja cieni?,Armadura das sombras?,,Armura umbrei?,Теневой бронёй?,,Gölge zırhı mı? -"Ahh, to be heard, but not seen!",TXT_RYES0_SCRIPT23_D13644_AHHTO,,,,"Áha, být slyšen, ne viděn!","Ahh, at blive hørt, men ikke set!","Ah, um gehört zu werden, aber ungesehen zu bleiben.",,,"Ah, ¡para ser oído, pero no visto!",,"Aah, tulla kuulluksi, muttei nähdyksi!","Ah, pour se faire entendre, sans se faire voir!","Csak hallani, de nem látni.","Ahh, per essere sentiti, ma non visti!",ああ、声はすれど姿は見えず。,하하하... 아주 조용하고 보이지 않는 도구죠!,"Ahhh, om gehoord, maar niet gezien te worden!","Å bli hørt, men ikke sett!","Ahh, być słyszanym, ale nie widzianym!","Ahh, ser ouvido mas não ser visto!",,"Ahh, să fii auzit, dar nu văzut!","Ах, чтобы быть услышанным, но не увиденным!",,"Ahh, duyulmak ama görülmemek!" -"Get out of here, come back when you have some cash.",TXT_RNO0_SCRIPT23_D13644_GETOU,,,,"Vypadni a vrať se, když budeš mít peníze.","Forsvind herfra, kom tilbage når du har nogle penge.","Verzieh dich, komm wieder, wenn du etwas Geld hast.",,,"Vete de aquí, vuelve cuando tengas algo de efectivo.",,"Antaa vetää; tule takaisin, kun sinulla on käteistä.","Sortez de là, revenez quand vous avez de l'argent!","Na kotródj innen, csak akkor lássalak ha van nálad pénz is.","Fuori di qui, ritorna quando avrai del denaro.",ここを出て、稼いでからまた来てくれ!,"저리 가, 돈이 있을 때나 여길 찾으라고요.","Ga hier weg, kom terug als je wat geld hebt.","Kom deg ut herfra, kom tilbake når du har penger.","Wynoś się stąd, wróć jak będziesz miał trochę kasy.",Vá embora daqui. Volte quando tiver dinheiro.,,"Cară-te, întoarce-te când ai bani.","Выметайся вон. Вернёшься, когда раздобудешь наличности.",,"Git buradan, biraz paran olduğunda geri gel." -"Thank Deus you got here. To enter the factory you need a key. We stole it but our agent is missing in the web of catacombs under the Order's stronghold. I have sent ten good men into those tunnels to find him, and none have returned. Something is down there!",TXT_DLG_SCRIPT23_D15160_THANK,,,,"Díky bohu, žes přišel. Aby ses dostal do továrny, potřebuješ klíč. Ten jsme ukradli, ale náš agent se ztratil v sítí katakomb pod pevností Řádu. Poslal jsem do těch tunelů deset dobrých mužů a žádný se nevrátil. Něco tam dole je!","Tak Deus for at du kom her. For at komme ind på fabrikken skal du bruge en nøgle. Vi stjal den, men vores agent er forsvundet i katakomberne under ordenens højborg. Jeg har sendt ti gode mænd ned i disse tunneller for at finde ham, men ingen er vendt tilbage. Der er noget dernede!","Deus sei dank bist du hier. Um die Fabrik zu betreten, brauchst du einen Schlüssel. Wir haben ihn gestohlen, aber unser Agent ist in den Irrwegen der Katakomben unter der Festung des Ordens verschollen. Ich habe zehn gute Männer da hinunter geschickt um ihn zu finden, aber niemand ist zurückgekehrt. Irgendetwas ist da unten!",,,"Gracias a deus que estás aquí. Para entrar en la fábrica necesitas una llave. La robamos, pero nuestro agente está perdido en la red de catacumbas debajo de la fortaleza de la Orden. He enviado diez buenos hombres a esos túneles para encontrarlo, y ninguno ha regresado. ¡Hay algo ahí abajo!",,"Luojan kiitos, että selvisit perille. Päästäksesi sisälle tehtaaseen tarvitset avaimen. Varastimme sen, mutta vakoojamme on eksynyt Veljeskunnan linnakkeen alapuolella sijaitsevaan katakombiverkostoon. Olen lähettänyt tunneleihin 10 kelpoa miestä etsimään häntä, eikä kukaan ole palannut. Jokin on siellä alla!","Merci Dieu, vous êtes là. Pour entrer dans l'usine, il vous faut une clé. On l'a volé, mais notre agent a disparu dans le dédale de catacombes sous la forteresse de l'Ordre. On a envoyé dix hommes dans ces tunnels pour le retrouver mais personne n'est revenu. Il doit y avoir quelque chose, là dedans!","Hála Deusnak, ideértél.Ahhoz, hogy bejuthass a gyárba kell majd egy kulcs. Habár sikerült ellopnunk a kulcsot, az ügynökünk elveszett a katakombák sűrűjében a Rend erődítménye alatt. Leküldtem tíz jó emberemet utána, de egyikük sem tért vissza. Valami borzasztó lehet ott lent!","Grazie a Dio sei arrivato. Per entrare nella fabbrica ti servirà una chiave. L'abbiamo rubata ma l'agente che l'ha presa è sparito nelle catacombe sotto la fortezza dell'Ordine. Ho mandato dieci uomini in quei tunnel a trovarlo, e nessuno è ritornato. C'è qualcosa là sotto!","ようやく来てくれたか。 +tengas dinero!",,"Tule takaisin, kun sinulla on rahaa!",Revenez quand vous avez des sous?,"Akkor gyere vissza, ha pénzed is lesz!",Torna quando avrai del denaro!,お金が有る時にまた!,"돈이 많이 있으면 모를까, 살 수 없을겁니다!",Kom terug als je geld hebt!,Kom tilbake når du har penger!,"Wróć, gdy będziesz miał pieniądze!",Volte quando tiver dinheiro!,,Revino când o să ai bani!,Возвращайся с деньгами!,,Kom tillbaka när du har pengar!,Paran olduğunda geri gel! +"Hello friend, what can I get you?",TXT_DLG_SCRIPT23_D6064_HELLO,MAP23: Barkeep.,,,"Zdravím, příteli, co pro vás mohu udělat?","Hej ven, hvad kan jeg give dig?","Hallo Freund, was darf es sein?",,"Saluton, amiko. Kion mi donu al vi?","Hola, amigo. ¿Qué puedo ofrecerte?",,"Tervehdys, ystävä; miten voin olla avuksi?","Bienvenu, l'ami, que puis-je pour vous?","Szevasz barátom, miben segíthetek?","Salve amico, cosa posso darti?",よう旦那、何が必要だ?,좋은 하루! 뭐 필요한거라도?,"Hallo vriend, wat kan ik voor je halen?","Hei venn, hva kan jeg gi deg?","Witaj przyjacielu, co mogę ci dać?","Olá amigo, como posso te ajudar?",,"Bună prietene, ce pot să-ți aduc?","Привет, друг. Могу я тебе что-нибудь предложить?",,"Hej vän, vad vill du ha?","Merhaba arkadaşım, sana ne getirebilirim?" +Information,TXT_RPLY0_SCRIPT23_D6064_INFOR,〃,,,Informace,,Informationen,,Informojn,Información,,Tietoa.,Des infos.,Információ,Informazioni,情報,정보 있습니까?,Informatie,Informasjon.,Informacje,Informações,,Informație,Информацию,,,Bilgi +"I've never seen anyone go in or out of the factory, the forcefield's always up.",TXT_RYES0_SCRIPT23_D6064_IVENE,〃,,,Nikdy jsem nikoho neviděl vcházet do ani vycházet z továrny. Silové pole je vždycky zapnuté.,"Jeg har aldrig set nogen gå ind eller ud af fabrikken, kraftfeltet er altid oppe.","Ich habe noch niemanden gesehen, der die Fabrik betreten oder verlassen hat. Das Kraftfeld ist immer aktiv.",,"Mi neniam vidis, ke iu iris en la fabrikon +aŭ el ĝi: la fortokampo ĉiam estas ŝaltita.","Jamás he visto a nadie entrar o salir +de la fábrica: nunca apagan la barrera.",,En ole nähnyt kenenkään koskaan menevän tai tulevan tehtaasta; voimakenttä on aina päällä.,Je n'ai jamais vu quelqu'un rentrer dans l'usine. Les champs de force sont toujours en ligne.,"Nem láttam még senkit ki- vagy be menni a gyárból, az erőpajzs mindig be van kapcsolva.","Non ho mai visto nessuno entrare o uscire dalla fabbrica, il campo di forza è sempre attivo.","誰も工場を出入りしている所を見ていない、 +フォースフィールドがずっと付いてる。",공장에서 나오는 사람들을 전혀 못 봤어. 방어막이 꺼지는 일이 없었으니까.,"Ik heb nog nooit iemand in of uit de fabriek zien gaan, het krachtveld is altijd in orde.","Jeg har aldri sett noen gå inn eller ut av fabrikken, kraftfeltet er alltid oppe.","Nigdy nie widziałem nikogo wchodzącego ani wychodzącego z fabryki, pole siłowe jest zawsze podniesione.",Nunca vi alguém entrar ou sair da fábrica. O campo de força está sempre ativado.,,"N-am văzut niciodată pe cineva intrând sau ieșind din fabrică, câmpul de forță e mereu activ.","Никогда не видел, чтобы кто-нибудь приходил или уходил с фабрики. Поле всегда включено.",,"Jag har aldrig sett någon gå in eller ut ur fabriken, kraftfältet är alltid uppe.","Kimsenin fabrikaya girip çıktığını görmedim, güç alanı her zaman açık." +"No money, no info.",TXT_RNO0_SCRIPT23_D6064_NOMON,〃,,,"Žádné peníze, žádné informace.","Ingen penge, ingen info.","Kein Geld, keine Informationen.",,Sen mono ne estas informoj,Sin dinero no hay información.,,"Ei tuohta, ei tietoa.","Pas d'argent, pas d'infos.","Ha nincs pénz, nincs infó.","Niente denaro, niente informazioni.",金が無いなら情報は無しだ。,"돈 없으면, 정보도 없다네.","Geen geld, geen informatie.","Ingen penger, ingen informasjon.","Nie ma pieniędzy, nie ma informacji.","Sem grana, nada de informações.",,"Niciun ban, nicio informație.",Нет денег — нет сведений.,,"Inga pengar, ingen information.","Para yok, bilgi yok." +"Yes, what would you like?",TXT_DLG_SCRIPT23_D7580_YESWH,〃,,,"Ano, co byste si přál?","Ja, hvad vil du gerne have?","Ja, was darf es sein?",,"Jes, kion vi ŝatus?","Sí, ¿qué quieres?",,"Niin, mitä saisi olla?","Oui, que voulez-vous?","Igen, milyen érdekelne?","Sì, che posso darti?",はい、どうしたい?,"아, 무엇을 원하는가?","Ja, wat wil je graag?","Ja, hva vil du ha?","Tak, czego chcesz?","Sim, o que você gostaria?",,"Da, ce ai dori?",Да? Что ты хотел?,,"Ja, vad vill du ha?","Evet, ne istiyorsunuz?" +More info.,TXT_RPLY0_SCRIPT23_D7580_MOREI,〃 (dot not recommended),,,Další informace.,Mere info.,Mehr Informationen.,,Pliajn informojn,Más información,,Lisää tietoa.,Plus d'infos.,Több információ.,Più informazioni.,更なる情報,정보가 필요해요.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multă informație.,Ещё сведений.,,Mer information.,Daha fazla bilgi. +The factory's built on the comet's impact site. I don't think it's by chance.,TXT_RYES0_SCRIPT23_D7580_THEFA,〃,,,"Továrnu postavili na místě dopadu komety. Nemyslím si, že to je náhoda.","Fabrikken er bygget på kometens nedslagssted. Jeg tror ikke, det er tilfældigt.","Die Fabrik wurde dort gebaut, wo der Komet eingeschlagen ist. Ich denke nicht, dass das Zufall ist.",,"Ili konstruis la fabrikon en la kometa +kratero, kvazaŭ tio estis hazarda koincido.","Construyeron la fábrica en el cráter +que dejó el cometa. No puede ser casualidad.",,"Tehdas on rakennettu komeetan törmäyspaikalle; enkä usko, että sattumalta.",L'usine est construite sur le site d'impact de la comète. Je ne crois pas que c'est une coïncidence.,A gyár a becsapódott üstökösre épült. Biztosan nem lehet véletlen.,La fabbrica è stata costruita sopra il sito d'impatto della cometa. Non credo sia una coincidenza.,"工場は彗星の衝突地点に建っている。 +これは偶然だと思えない。",공장은 혜성이 충돌한 지점에서 건설되었다네. 우연으로 건설된 게 아니라고 생각해.,De fabriek is gebouwd op de impact van de komeet site. Ik denk niet dat het toeval is.,Fabrikken er bygget på kometens nedslagssted. Jeg tror ikke det er tilfeldig.,"Fabryka została zbudowana na miejscu uderzenia komety. Nie sądzę, żeby to był przypadek.",A fábrica foi construída no local de impacto do cometa. Não acho que tenha sido por acaso.,,Fabrica e construită pe locul de prăbușire al cometei. Nu cred că e o coincidență.,"Фабрика была построена в кратере от падения метеорита. Не думаю, что это случайность.",,Fabriken är byggd på kometens nedslagsplats. Jag tror inte att det är en slump.,Fabrika kuyruklu yıldızın çarpma alanına inşa edildi. Bunun tesadüf olduğunu sanmıyorum. +"Come on, it's a measly 5 gold.",TXT_RNO0_SCRIPT23_D7580_COMEO,〃,,,"No tak, chci pouhých pět zlatých.","Kom nu, det er sølle 5 guld.","Komm schon, es sind doch nur 5 mickrige Goldstücke.",,"Ulo, mi petas nur kvin +mizerajn monerojn.","Venga, solo cinco míseras +monedas de oro.","Vamos, solo cinco míseras +monedas de oro.","Hei, antaisit nyt vaivaiset viisi kolikkoa.","Allez, ça ne coûte que 5 pièces!","Nemár, francos 5 arany.","Andiamo, sono solo 5 pezzi d'oro.",頼むぜ、たった5ゴールドだぞ。,5 골드 정도 하는데 말이지.,"Kom op, het is een miezerige 5 goud.","Kom igjen, det er sølle fem gull.","Daj spokój, to marne 5 złotych.","Vamos lá, custa só 5 moedinhas.",,"Haide, sunt 5 bănuți amărâți.","Ну же, всего-то 5 золотых.",,"Kom igen, det är bara 5 guld.","Hadi ama, sadece 5 altın." +"Hello again, what'll it be?",TXT_DLG_SCRIPT23_D9096_HELLO,〃,,,"Opět zdravím, co to bude?","Hej igen, hvad bliver det?",Willkommen zurück. Was darf es sein?,,Saluton denove. Kion vi petos?,Hola otra vez. ¿Qué va a ser?,,"Hei taas, mitä kaipaat?","Rebonjour, que puis-je pour vous?","Üdv újra itt, mit kérsz?","Chi si rivede, che cosa c'è?",また来たな、何か頼むか?,다시 만났군. 오늘은 어떤 걸?,"Hallo nogmaals, wat zal het zijn?","Hallo igjen, hva skal det være?","Witam ponownie, co to będzie?",Olá de novo. O que vai ser desta vez?,,"Bună din nou, ce dorești?",И снова привет. Что на этот раз?,,"Hej igen, vad vill du ha?","Tekrar merhaba, ne alırdınız?" +More info.,TXT_RPLY0_SCRIPT23_D9096_MOREI,〃 (dot not recommended),,,Další informace.,Mere info.,Mehr Informationen.,,Pliajn informojn,Más información,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,更なる情報,더 많은 정보를 원해요.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multă informație.,Ещё информацию.,,Mer information.,Daha fazla bilgi. +The factory closed when the Order unveiled its new horror: the Inquisitor.,TXT_RYES0_SCRIPT23_D9096_THEFA,〃,,,Továrnu zavřeli když Řád odkryl svou novou hrůzu: Inkvizitora.,"Fabrikken lukkede, da Ordenen afslørede sin nye rædsel: Inquisitoren.","Die Fabrik wurde geschlossen, als der Orden seinen neuesten Horror enthült hat: Den Inquisitor.",,"La fabriko fermis post la malkaŝo de la lasta +teruraĵo de La Ordeno: la Inkvizitoro.","La fábrica cerró cuando La Orden +reveló su nuevo horror: el Inquisidor.",,"Tehdas suljettiin, kun Veljeskunta paljasti sen uuden kauhistuksen: inkvisiittorin.","L'usine a été fermée quand l'Ordre a révélé sa nouvelle atrocité, L'inquisiteur.","A gyár bezárt, amikor a Rend leleplezte a nagyközönség előtt az új horrorát: az Inkvizítort.",La fabbrica è stata chiusa quando l'Ordine ha rivelato il suo nuovo orrore: l'Inquisitore,"工場はオーダーの「新審問官」が来てから +恐ろしい雰囲気を纏った。",오더가 획기적이고 무서운 병기들을 생산한 후 공장의 문을 닫았다네. 그것들의 이름은 '인퀴지터'지.,De fabriek werd gesloten toen de Orde haar nieuwe horror onthulde: de inquisiteur.,Fabrikken stengte da Ordenen avduket sin nye skrekk: Inkvisitoren.,"Fabryka została zamknięta, gdy Zakon zaprezentował swój nowy horror: Inkwizytora.",A fábrica fechou quando a Ordem revelou o seu novo horror: o Inquisidor.,,Fabrica s-a închis când Ordinul a dezvăluit noua sa oroare: Inchizitorul.,"Фабрика закрылась, когда Орден показал своё новое страшилище — инквизитора.",,Fabriken stängdes när Orden presenterade sin nya skräck: Inkvisitorn.,"Fabrika, Tarikat yeni dehşeti Cezacı'yı tanıttığında kapandı." +5 gold please.,TXT_RNO0_SCRIPT23_D9096_5GOLD,〃,,,"Pět zlatých, prosim.","5 guld, tak.","5 Gold, bitte.",,"Kvin da oro, bonvolu.","Cinco de oro, por favor.",,"5 kolikkoa, kiitos.","5 pièces, s'il vous plaît.",5 arany lesz.,"Sono 5 pezzi d'oro, prego.",5ゴールドかかるぜ。,먼저 5 골드를 주게나.,5 goud alsjeblieft.,"5 gull, takk.",Proszę o 5 sztuk złota.,5 moedas por favor.,,5 bani te rog.,"5 золотых, пожалуйста.",,"5 guld, tack.",5 altın lütfen. +"That's all I know. Even bartenders run out of stuff to say, sorry.",TXT_DLG_SCRIPT23_D10612_THATS,"STRIFE1.WAD +MAP23: Barkeep",,,"To je vše, co vím. I barmani občas nemají, co dál říct, promiňte.","Det er alt, hvad jeg ved. Selv bartendere løber tør for ting at sige, undskyld.","Das ist alles was ich weiß. Selbst ein Barkeeper hat irgendwann keine Neugikeiten mehr, tut mir Leid.",,Mi scias nenion plian. Eĉ drinkejestroj restas sen dirindaĵoj. Pardonon.,Eso es todo lo que sé. Incluso los taberneros se quedan sin cosas que decir. Lo siento.,,"Siinä kaikki, mitä tiedän. Jopa baarimikoilta loppuvat jutun aiheet, pahoittelen.","C'est tout ce que je sais. Même les barmans peuvent arriver à court d'infos, désolé.","Ennyit tudok. Még a bárpultos tudása sem végtelen, sajnálom.","È tutto ciò che so. Anche i baristi hanno un limite alla loro conoscienza, mi spiace.","知ってることはこれで全部だ。 +バーテンダーの噂は売切れだ、すまない。",이 바텐더는 꺼낼 수 있는 모든 조언을 꺼냈다네. 미안.,"Dat is alles wat ik weet. Zelfs de barmannen hebben niet veel meer te zeggen, sorry.","Det er alt jeg vet. Selv bartendere går tom for ting å si, beklager.","To wszystko, co wiem. Nawet barmanom kończy się to, co można powiedzieć, przepraszam.","Isso é tudo o que eu sei. Até donos de bar acabam ficando sem algo pra dizer uma hora, sinto muito.",,"Asta e tot ce știu, până și barmanii rămân fără chestii de zis.","Это всё, что я знаю. Даже у хозяев таверн заканчиваются темы для болтовни, увы.",,"Det är allt jag vet. Till och med bartender får slut på saker att säga, tyvärr.","Tek bildiğim bu. Barmenlerin bile söyleyecek bir şeyleri kalmadı, üzgünüm." +Hello.,TXT_DLG_SCRIPT23_D12128_HELLO,"STRIFE1.WAD +MAP23: Timothy",,,Ahoj.,Hej.,Hallo.,,Saluton.,Hola.,,Hei.,Bonjour.,Helló.,Ciao.,こんにちは。,안녕하세요.,Hallo.,Hallo.,Witam.,Olá.,,Salut.,Привет.,,Hej.,Merhaba. +What are you doing?,TXT_RPLY0_SCRIPT23_D12128_WHATA,〃,,,Co tady děláš?,Hvad laver du?,Was machst du?,,Kion vi faras?,¿Qué estás haciendo?,,Mitä teet?,Qu'est-ce que vous faites?,Mit csinálsz?,Che cosa stai facendo?,何してるんだ?,뭐하는 거죠?,Wat ben je aan het doen?,Hva driver du med?,Co robisz?,O que você está fazendo?,,Ce faci?,Чем ты занимаешься?,,Vad gör du?,Ne yapıyorsun? +"I'm doing stuff, go away!",TXT_RYES0_SCRIPT23_D12128_IMDOI,〃,,,"Dělám věci, vypadni!","Jeg laver noget, gå væk!","Ich mach' halt was, geh weg!",,Mi umas. Foriru!,Cosas. ¡Ya vete!,,"Teen juttuja, mene pois!","Je suis occupé, laissez-moi tranquille!","Épp elfoglalt vagyok, tünj innen!","Sto sbrigando delle cose, vattene!",今は立て込んでる、離れなさい!,별거 아닙니다. 방해하지 말고 저리 가세요!,"Ik doe dingen, ga weg!","Jeg gjør ting, gå vekk!","Robię różne rzeczy, odejdź!","Estou fazendo coisas, vá embora!",,"Am treabă, pleacă!",Ерундой всякой. Отвали!,,"Jag gör saker, försvinn!","Bir şeyler yapıyorum, git başımdan!" +"Now, what can I help you with?",TXT_DLG_SCRIPT23_D13644_NOWWH,"STRIFE1.WAD +MAP23: Tevick.",,,"Tak, s čím ti mohu pomoci?",Hvad kan jeg hjælpe dig med?,"Nun, wie kann ich dir weiterhelfen?",,"Nu, kion mi povas doni al vi?","Y bueno, ¿en qué puedo ayudarte?",,"No niin, miten voin palvella?","Bon, que puis-je pour vous?","Na, miben segíthetek?","E ora, come posso aiutarti?",今手伝ってくれるか?,"자, 제가 뭘 도와드릴까요?","Nu, waar kan ik je mee helpen?",Hva kan jeg hjelpe deg med?,"A teraz, w czym mogę ci pomóc?","Então, como posso ajudá-lo?",,"Acum, cu ce te pot ajuta?","Итак, чем я могу быть тебе полезен?",,Vad kan jag hjälpa dig med?,"Şimdi, sana nasıl yardımcı olabilirim?" +Shadow armor?,TXT_RPLY0_SCRIPT23_D13644_SHADO,〃,,Shadow armour?,Stínové brnění?,Skygge rustning?,Schattenrüstung?,,Ĉu ombran armaĵon?,¿Armadura de sombra?,,Varjohaarniska?,Armure des ombres?,Árnyék vért?,Armatura Ombra?,シャドウアーマー?,그림자 갑옷?,Schaduw harnas?,Skyggepanser?,Zbroja cieni?,Armadura das sombras?,,Armura umbrei?,Теневой бронёй?,,Skuggarmering?,Gölge zırhı mı? +"Ahh, to be heard, but not seen!",TXT_RYES0_SCRIPT23_D13644_AHHTO,〃,,,"Áha, být slyšen, ne viděn!","Ahh, at blive hørt, men ikke set!","Ah, um gehört zu werden, aber ungesehen zu bleiben.",,"Ha, por esti aŭdata, +sed ne vidata!","Ah, ¡para ser oído, +pero no visto!",,"Aah, tulla kuulluksi, muttei nähdyksi!","Ah, pour se faire entendre, sans se faire voir!","Csak hallani, de nem látni.","Ahh, per essere sentiti, ma non visti!",ああ、声はすれど姿は見えず。,하하하... 아주 조용하고 보이지 않는 도구죠!,"Ahhh, om gehoord, maar niet gezien te worden!","Å bli hørt, men ikke sett!","Ahh, być słyszanym, ale nie widzianym!","Ahh, ser ouvido mas não ser visto!",,"Ahh, să fii auzit, dar nu văzut!","Ах, чтобы быть услышанным, но не увиденным!",,"Ahh, att höras men inte ses!","Ahh, duyulmak ama görülmemek!" +"Get out of here, come back when you have some cash.",TXT_RNO0_SCRIPT23_D13644_GETOU,〃,,,"Vypadni a vrať se, když budeš mít peníze.","Forsvind herfra, kom tilbage når du har nogle penge.","Verzieh dich, komm wieder, wenn du etwas Geld hast.",,"Foriru. Revenu kiam +vi havos monon.","Vete. Vuelve cuando +tengas efectivo.",,"Antaa vetää; tule takaisin, kun sinulla on käteistä.","Sortez de là, revenez quand vous avez de l'argent!","Na kotródj innen, csak akkor lássalak ha van nálad pénz is.","Fuori di qui, ritorna quando avrai del denaro.",ここを出て、稼いでからまた来てくれ!,"저리 가, 돈이 있을 때나 여길 찾으라고요.","Ga hier weg, kom terug als je wat geld hebt.","Kom deg ut herfra, kom tilbake når du har penger.","Wynoś się stąd, wróć jak będziesz miał trochę kasy.",Vá embora daqui. Volte quando tiver dinheiro.,,"Cară-te, întoarce-te când ai bani.","Выметайся вон. Вернёшься, когда раздобудешь наличности.",,"Försvinn härifrån, kom tillbaka när du har lite pengar.","Git buradan, biraz paran olduğunda geri gel." +"Thank Deus you got here. To enter the factory you need a key. We stole it but our agent is missing in the web of catacombs under the Order's stronghold. I have sent ten good men into those tunnels to find him, and none have returned. Something is down there!",TXT_DLG_SCRIPT23_D15160_THANK,"STRIFE1.WAD +MAP23: Richter.",,,"Díky bohu, žes přišel. Aby ses dostal do továrny, potřebuješ klíč. Ten jsme ukradli, ale náš agent se ztratil v sítí katakomb pod pevností Řádu. Poslal jsem do těch tunelů deset dobrých mužů a žádný se nevrátil. Něco tam dole je!","Tak Deus for at du kom her. For at komme ind på fabrikken skal du bruge en nøgle. Vi stjal den, men vores agent er forsvundet i katakomberne under ordenens højborg. Jeg har sendt ti gode mænd ned i disse tunneller for at finde ham, men ingen er vendt tilbage. Der er noget dernede!","Deus sei dank bist du hier. Um die Fabrik zu betreten, brauchst du einen Schlüssel. Wir haben ihn gestohlen, aber unser Agent ist in den Irrwegen der Katakomben unter der Festung des Ordens verschollen. Ich habe zehn gute Männer da hinunter geschickt um ihn zu finden, aber niemand ist zurückgekehrt. Irgendetwas ist da unten!",,"Danke al Dio vi alvenis. Ŝlosilo estas necesa por eniri la fabrikon; ni ŝtelis ĝin, sed nia agento estas perdita en la katakomba sistemo sub la fortreso de La Ordeno. Mi sendis dek bonajn virojn al tiuj tuneloj por serĉi lin kaj neniu revenis. Estas io tie malsupre!","Gracias a Dios, has llegado. Para entrar en la fábrica se necesita una llave; la hemos robado, pero nuestro agente está perdido en la red de catacumbas debajo de la fortaleza de La Orden. He enviado a diez buenos hombres a esos túneles a buscarlo y ninguno ha regresado. ¡Hay algo ahí abajo!","Gracias a Dios, llegaste. Para entrar a la fábrica se necesita una llave; la robamos, pero nuestro agente se perdió en la red de catacumbas debajo de la fortaleza de La Orden. Mandé a diez buenos hombres a esos túneles a buscarlo y ninguno volvió. ¡Hay algo ahí abajo!","Luojan kiitos, että selvisit perille. Päästäksesi sisälle tehtaaseen tarvitset avaimen. Varastimme sen, mutta vakoojamme on eksynyt Veljeskunnan linnakkeen alapuolella sijaitsevaan katakombiverkostoon. Olen lähettänyt tunneleihin 10 kelpoa miestä etsimään häntä, eikä kukaan ole palannut. Jokin on siellä alla!","Merci Dieu, vous êtes là. Pour entrer dans l'usine, il vous faut une clé. On l'a volé, mais notre agent a disparu dans le dédale de catacombes sous la forteresse de l'Ordre. On a envoyé dix hommes dans ces tunnels pour le retrouver mais personne n'est revenu. Il doit y avoir quelque chose, là dedans!","Hála Deusnak, ideértél.Ahhoz, hogy bejuthass a gyárba kell majd egy kulcs. Habár sikerült ellopnunk a kulcsot, az ügynökünk elveszett a katakombák sűrűjében a Rend erődítménye alatt. Leküldtem tíz jó emberemet utána, de egyikük sem tért vissza. Valami borzasztó lehet ott lent!","Grazie a Dio sei arrivato. Per entrare nella fabbrica ti servirà una chiave. L'abbiamo rubata ma l'agente che l'ha presa è sparito nelle catacombe sotto la fortezza dell'Ordine. Ho mandato dieci uomini in quei tunnel a trovarlo, e nessuno è ritornato. C'è qualcosa là sotto!","ようやく来てくれたか。 工場に入るためには鍵が必要だ。 鍵は盗んだのだが、我々の密偵が砦地下にある 地下墓所で行方不明になった。 彼を探すため10名派遣したのだが、 誰一人帰ってこなかった。 -地下墓地で何か異変が起こっているに違いない。","데우스님 감사합니다, 지원군이 왔군! 공장에 들어가려면 열쇠가 필요합니다. 그 열쇠를 가진 한 요원이 오더의 요새가 있는 고대 무덤에서 길을 잃었습니다. 지원군 10 명을 보내긴 했으나 돌아오지 못했습니다. 그곳에 무언가가 있는 것 같아요!","Bedankt Deus dat je hier bent gekomen. Om de fabriek binnen te komen heb je een sleutel nodig. We hebben het gestolen maar onze agent ontbreekt in het web van de catacomben onder het bolwerk van de Orde. Ik heb tien goede mannen in die tunnels gestuurd om hem te vinden, en niemand is teruggekomen. Er is daar beneden iets!","Takk Gud for at du kom hit. For å komme inn i fabrikken trenger du en nøkkel. Vi stjal den, men agenten vår er forsvunnet i katakombene under Ordenens festning. Jeg har sendt ti gode menn ned i tunnelene for å finne ham, men ingen har kommet tilbake. Det er noe der nede!","Dziękuję Deusowi, że tu trafiłeś. Aby wejść do fabryki potrzebny jest klucz. Ukradliśmy go, ale nasz agent zaginął w sieci katakumb pod twierdzą Zakonu. Wysłałem dziesięciu dobrych ludzi do tych tuneli, by go znaleźli, ale żaden nie wrócił. Coś jest tam na dole!",Graças a Deus que você está aqui. Para entrar na fábrica você precisa de uma chave. Nós a roubamos mas nosso agente desapareceu na rede de catacumbas debaixo da fortaleza da Ordem. Mandei dez homens capazes pra dentro desses túneis para encontrá-lo e ninguém retornou. Tem alguma coisa lá embaixo!,,"Slavă Domnului că ești aici. Ca să intri în fabrică ai nevoie de o cheie. Am furat-o dar agentul nostru a dispărut în rețeaua catacombelor fortăreței Ordinului. Am trimis zece oameni pricepuți după el, dar niciunul nu s-a întors. Ceva se întâmplă acolo!","Хвала господу, ты добрался сюда. Тебе нужен ключ, чтобы проникнуть на фабрику. Мы выкрали его, но наш агент пропал в сети катакомб под крепостью Ордена. Чтобы разыскать его, я послал в эти туннели десять хороших бойцов, и ни один не вернулся. Там внизу что-то есть!",,Buraya geldiğin için Deus'a şükret. Fabrikaya girmek için bir anahtara ihtiyacınız var. Onu çaldık ama ajanımız Tarikat'ın kalesinin altındaki yeraltı mezarlarında kayıp. Onu bulmaları için o tünellere on iyi adam gönderdim ama hiçbiri geri dönmedi. Aşağıda bir şey var! -What is it? Human or... ?,TXT_RPLY0_SCRIPT23_D15160_WHATI,,,,"Co to je? Člověk, nebo...?",Hvad er det? Menneske eller... ?,Was ist es? Mensch oder...?,,,¿Qué es? ¿Humano o...?,,Mikä se on? Ihminen vai...,"Qu'est-ce que c'est? Un humain, où...",Mi lehet? Ember vagy...?,Che cosa è? Umano o... ?,それは一体?人間か...?,그게 뭐죠? 사람? 아니면... ?,Wat is het? Menselijk of.... ?,Hva er det? Menneskelig eller... ?,Co to jest? Człowiek czy... ?,O que é? É humano ou... ?,,Ce e? Uman sau... ?,Что это? Человек или...?,,Ne var orada? İnsan mı yoksa... ? -"Not. Definitely not. Whatever it is, you must fight it to retrieve the key. I'll open the catacombs' entrance. When you've got it, the factory is next to the mines. Hurry, each second counts.",TXT_DLG_SCRIPT23_D16676_NOTDE,,,,"Ne. Rozhodně ne. Ať je to cokoliv, musíš se s tím utkat, abys získal ten klíč zpět. Otevřu ti vchod do katakomb. Až ho budeš mít, továrna je vedle dolů. Pospěš si, každá vteřina se počítá.","Nej. Helt sikkert ikke. Uanset hvad det er, skal du kæmpe mod det for at få nøglen tilbage. Jeg åbner katakombernes indgang. Når du har fået den, er fabrikken ved siden af minerne. Skynd dig, hvert sekund tæller.","Nein. Definitiv nicht. Was auch immer es ist, du musst es bekämpfen, um an den Schlüssel zu kommen. Ich werde den Eingang zu den Katakomben öffnen. Wenn du ihn hast, die Fabrik ist direkt neben den Minen. Beeil dich, jede Sekunde zählt.",,,"No. Definitivamente no. Sea lo que sea, debes luchar contra eso para recuperar la llave. Abriré la entrada a las catacumbas. Cuando la tengas, la fábrica está junto a las minas. Date prisa, cada segundo cuenta.",,"Ei, ei varmana. Mikä ikinä se onkaan, sinun on kohdattava se noutaaksesi avaimen. Avaan katakombien sisäänkäynnin. Kun se on hallussasi, tehdas on kaivoksen vieressä. Pidä kiirettä, jokainen sekunti merkitsee.","Non, absolument pas. Je ne sais pas ce que c'est, mais il faudra s'en débarasser pour récupérer la clé. Je vais ouvrir l'entrée des catacombes. Quand vous êtes à l'intérieur, l'usine est près des ruines. Vite, chaque seconde compte.","Nem. Biztos, hogy nem. Akármi is az, meg kell majd küzdened vele a kulcsért. Kinyitom a katakomba bejáratát. Ha megszerezted, a gyár ott lesz a bánya mellett. Siess, minden másodperc számít.","No. Sicuramente no. Qualsiasi cosa sia, dovrai lottare per riavere la chiave. Adesso aprirò l'entrata per le catacombe. Quando avrai ripreso la chiave, potrai accedere alla fabbrica, che si trova accanto alle miniere. Sbrigati, ogni secondo può fare la differenza.","いや。人間の仕業だとはとても思えない。 +地下墓地で何か異変が起こっているに違いない。","데우스님 감사합니다, 지원군이 왔군! 공장에 들어가려면 열쇠가 필요합니다. 그 열쇠를 가진 한 요원이 오더의 요새가 있는 고대 무덤에서 길을 잃었습니다. 지원군 10 명을 보내긴 했으나 돌아오지 못했습니다. 그곳에 무언가가 있는 것 같아요!","Bedankt Deus dat je hier bent gekomen. Om de fabriek binnen te komen heb je een sleutel nodig. We hebben het gestolen maar onze agent ontbreekt in het web van de catacomben onder het bolwerk van de Orde. Ik heb tien goede mannen in die tunnels gestuurd om hem te vinden, en niemand is teruggekomen. Er is daar beneden iets!","Takk Gud for at du kom hit. For å komme inn i fabrikken trenger du en nøkkel. Vi stjal den, men agenten vår er forsvunnet i katakombene under Ordenens festning. Jeg har sendt ti gode menn ned i tunnelene for å finne ham, men ingen har kommet tilbake. Det er noe der nede!","Dziękuję Deusowi, że tu trafiłeś. Aby wejść do fabryki potrzebny jest klucz. Ukradliśmy go, ale nasz agent zaginął w sieci katakumb pod twierdzą Zakonu. Wysłałem dziesięciu dobrych ludzi do tych tuneli, by go znaleźli, ale żaden nie wrócił. Coś jest tam na dole!",Graças a Deus que você está aqui. Para entrar na fábrica você precisa de uma chave. Nós a roubamos mas nosso agente desapareceu na rede de catacumbas debaixo da fortaleza da Ordem. Mandei dez homens capazes pra dentro desses túneis para encontrá-lo e ninguém retornou. Tem alguma coisa lá embaixo!,,"Slavă Domnului că ești aici. Ca să intri în fabrică ai nevoie de o cheie. Am furat-o dar agentul nostru a dispărut în rețeaua catacombelor fortăreței Ordinului. Am trimis zece oameni pricepuți după el, dar niciunul nu s-a întors. Ceva se întâmplă acolo!","Хвала господу, ты добрался сюда. Тебе нужен ключ, чтобы проникнуть на фабрику. Мы выкрали его, но наш агент пропал в сети катакомб под крепостью Ордена. Чтобы разыскать его, я послал в эти туннели десять хороших бойцов, и ни один не вернулся. Там внизу что-то есть!",,"Tacka Deus för att du kom hit. För att komma in i fabriken behöver du en nyckel. Vi stal den, men vår agent saknas i katakomberna under Ordensfästet. Jag har skickat tio goda män in i tunnlarna för att hitta honom, men ingen har återvänt. Något finns där nere!",Buraya geldiğin için Deus'a şükret. Fabrikaya girmek için bir anahtara ihtiyacınız var. Onu çaldık ama ajanımız Tarikat'ın kalesinin altındaki yeraltı mezarlarında kayıp. Onu bulmaları için o tünellere on iyi adam gönderdim ama hiçbiri geri dönmedi. Aşağıda bir şey var! +What is it? Human or... ?,TXT_RPLY0_SCRIPT23_D15160_WHATI,〃,,,"Co to je? Člověk, nebo...?",Hvad er det? Menneske eller... ?,Was ist es? Mensch oder...?,,Kia ĝi estas? Ĉu homa aŭ...?,"¿Qué es?, ¿humano o...?",,Mikä se on? Ihminen vai...,"Qu'est-ce que c'est? Un humain, où...",Mi lehet? Ember vagy...?,Che cosa è? Umano o... ?,それは一体?人間か...?,그게 뭐죠? 사람? 아니면... ?,Wat is het? Menselijk of.... ?,Hva er det? Menneskelig eller... ?,Co to jest? Człowiek czy... ?,O que é? É humano ou... ?,,Ce e? Uman sau... ?,Что это? Человек или...?,,Vad är det? Mänskligt eller... ?,Ne var orada? İnsan mı yoksa... ? +"Not. Definitely not. Whatever it is, you must fight it to retrieve the key. I'll open the catacombs' entrance. When you've got it, the factory is next to the mines. Hurry, each second counts.",TXT_DLG_SCRIPT23_D16676_NOTDE,〃,,,"Ne. Rozhodně ne. Ať je to cokoliv, musíš se s tím utkat, abys získal ten klíč zpět. Otevřu ti vchod do katakomb. Až ho budeš mít, továrna je vedle dolů. Pospěš si, každá vteřina se počítá.","Nej. Helt sikkert ikke. Uanset hvad det er, skal du kæmpe mod det for at få nøglen tilbage. Jeg åbner katakombernes indgang. Når du har fået den, er fabrikken ved siden af minerne. Skynd dig, hvert sekund tæller.","Nein. Definitiv nicht. Was auch immer es ist, du musst es bekämpfen, um an den Schlüssel zu kommen. Ich werde den Eingang zu den Katakomben öffnen. Wenn du ihn hast, die Fabrik ist direkt neben den Minen. Beeil dich, jede Sekunde zählt.",,"Ne, neniel. Tio ajn, kio ĝi estas, vi devas batali kontraŭ ĝi por rekuperi la ŝlosilon. Farinte tion, la fabriko estas flanke de la minejo. Hastu, ĉiu sekundo estas gravega.","No, definitivamente no. Sea lo que sea, debes pelear contra eso para recuperar la llave; abriré la entrada a las catacumbas. Cuando la tengas, la fábrica está junto a la mina. Date prisa, que cada segundo cuenta.","No, definitivamente no. Sea lo que sea, debes pelear contra eso para recuperar la llave; voy a abrir la entrada a las catacumbas. Cuando la tengas, la fábrica está junto a la mina. Apúrate, que cada segundo cuenta.","Ei, ei varmana. Mikä ikinä se onkaan, sinun on kohdattava se noutaaksesi avaimen. Avaan katakombien sisäänkäynnin. Kun se on hallussasi, tehdas on kaivoksen vieressä. Pidä kiirettä, jokainen sekunti merkitsee.","Non, absolument pas. Je ne sais pas ce que c'est, mais il faudra s'en débarasser pour récupérer la clé. Je vais ouvrir l'entrée des catacombes. Quand vous êtes à l'intérieur, l'usine est près des ruines. Vite, chaque seconde compte.","Nem. Biztos, hogy nem. Akármi is az, meg kell majd küzdened vele a kulcsért. Kinyitom a katakomba bejáratát. Ha megszerezted, a gyár ott lesz a bánya mellett. Siess, minden másodperc számít.","No. Sicuramente no. Qualsiasi cosa sia, dovrai lottare per riavere la chiave. Adesso aprirò l'entrata per le catacombe. Quando avrai ripreso la chiave, potrai accedere alla fabbrica, che si trova accanto alle miniere. Sbrigati, ogni secondo può fare la differenza.","いや。人間の仕業だとはとても思えない。 それが何であれ君は鍵を取り戻せ。 地下墓所への入り口は開けておこう。 鍵を手に入れたら、工場は採掘所の隣にある。 -時間はあまり無いから急ぐのだ。","아냐. 사람 같은 건 절대로 아니라고. 그게 무엇이든, 당신은 어떻게든 싸워서 열쇠를 돌려받아야 합니다. 고대 무덤의 입구를 열어두겠습니다. 만약 열쇠를 얻으셨다면, 광산 옆에 있는 공장으로 향하시길 바랍니다. 시간이 얼마 남지 않았습니다!","Niet. Zeker niet. Wat het ook is, je moet ertegen vechten om de sleutel terug te krijgen. Ik zal de ingang van de catacomben openen. Als je hem hebt, staat de fabriek naast de mijnen. Schiet op, elke seconde telt.","Nei. Definitivt ikke. Uansett hva det er, må du kjempe mot det for å få tak i nøkkelen. Jeg åpner inngangen til katakombene. Når du har den, er fabrikken ved siden av gruvene. Skynd deg, hvert sekund teller.","Nie. Zdecydowanie nie. Cokolwiek to jest, musisz z tym walczyć, aby odzyskać klucz. Ja otworzę wejście do katakumb. Gdy go zdobędziesz, fabryka jest obok kopalni. Spiesz się, liczy się każda sekunda.","Não. Definitivamente não é. Seja lá o que for, você deve enfrentá-lo para recuperar a chave. Vou abrir a entrada das catacumbas. Quando você pegar a chave, vá para a fábrica próxima às minas. Depressa, cada segundo é importante.",,"Nu. Cu siguranță nu. Orice ar fi, va trebui să o înfrunți pentru a recupera cheia. Voi deschide intrarea catacombelor. Când o ai, fabrica e vizavi de mine. Grăbește-te, orice secundă contează.","Нет. Определённо нет. Что бы это ни было, ты должен сразиться с ним, чтобы заполучить ключ. Я открою вход в катакомбы. Когда добудешь его, направляйся на фабрику: она находится рядом со входом в шахты. Торопись! Дорога каждая секунда!",,"İnsan değil. Kesinlikle değil. O her neyse, anahtarı almak için onunla savaşmalısın. Yeraltı mezarlarının girişini açacağım. Anahtarı aldığında, fabrika madenlerin yanında. Acele et, her saniye önemli." -"Something inhuman, eh?, great.",TXT_RPLY0_SCRIPT23_D16676_SOMET,,,,"Něco nelidského, co? Skvělý.","Noget umenneskeligt, hva'?, fedt.",Irgendetwas unmenschliches? Na großartig.,,,"Algo inhumano, ¿eh?, genial.",,"Jotain epäinhimillistä, vai? Hienoa.","Quelque chose d'inhumain, hein? Parfait.","Valami nem emberi, mi? Csodás.","Qualcosa di inumano, eh? Fantastico.",非人道的な何か?流石だな。,비인간적인 녀석인가요? 좋군요.,"Iets onmenselijks, eh?, geweldig.","Noe umenneskelig, hva? Flott!","Coś nieludzkiego, ech, świetnie.","Algo não-humano, é? Que ótimo.",,"Ceva inuman, ei? Grozav.",Что-то иное? Просто отлично.,,"İnsanlık dışı bir şey, ha? Harika." -You're wasting time and lives! Move!,TXT_DLG_SCRIPT23_D18192_YOURE,,,,Plýtváš časem i životy! Jdi!,Du spilder tid og liv! Af sted!,Du verschwendest Zeit und Leben! Beweg dich!,,,¡Estás perdiendo tiempo y vidas! ¡Muévete!,,Haaskaat aikaa ja henkiä! Liikkuu jo!,Vous perdez votre temps et des vies! Bougez!,Időt és életeket pazarolsz! Mozgás!,"Stai sprecando tempo, e vite. Sbrigati!","こうしてる間にも君は時間と人命を -無駄にしている。行け!",시간과 생명이 위협받고 있다고! 서두르세요!!,Je verspilt tijd en levens! Vooruit!,Du kaster bort tid og liv! Skynd dere!,Marnujesz czas i życie! Ruszać się!,Você está desperdiçando tempo e vidas! Ande logo!,,"Pierzi timp și vieți, mișcă-te!",Ты тратишь время и жизни! Шевелись!,,Zamanınızı ve hayatlarınızı boşa harcıyorsunuz! Çekilin! -Can I be of more help?,TXT_DLG_SCRIPT23_D10612_CANIB,,,,Můžu vám dál pomocI?,Kan jeg være til mere hjælp?,Kann ich dir sonst noch irgendwie helfen?,,,¿Puedo ser de más ayuda?,,Voinko vielä olla avuksi?,Je peux vous aider?,Lehetek még a segítségedre?,Posso aiutarti ancora?,何かお困りでも?,당신의 도움이 더 되어줄 수 있겠습니까?,Kan ik meer hulp bieden?,Kan jeg være til mer hjelp?,Czy mogę być bardziej pomocny?,Posso ajudar com mais alguma coisa?,,Pot fi mai de ajutor?,Могу ли я чем-нибудь помочь?,,Daha fazla yardımcı olabilir miyim? -More info.,TXT_RPLY0_SCRIPT23_D10612_MOREI,,,,Další informace.,Mere info.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Più informazioni.,更なる情報。,정보 더 있습니까?,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multă informație.,Информацией.,,Daha fazla bilgi. -Look for Timothy. I've heard he knows some of the Order's secrets.,TXT_RYES0_SCRIPT23_D10612_LOOKF,,,,"Najděte Timothyho. Slyšel jsem, že ví nějaká tajemství Řádu.","Kig efter Timothy. Jeg har hørt, at han kender nogle af Ordenens hemmeligheder.","Suche Timothy. Ich habe gehört, das er etwas über die Geheimnisse des Ordens weiß.",,,Busca a Timothy. He oído que sabe algo sobre los secretos de la Orden.,,Etsi Timothy. Hän kuulemma tietää joitain Veljeskunnan salaisuuksia.,"Cherchez Timothy, j'entends qu'il sait des secrets de l'Ordre.","Keresd Timothyt. Azt hallotam, Ő tud pár Rend titkot.",Cerca Timothy. Ho sentito che conosce alcuni dei segreti dell'Ordine.,"ティモシーを探せ。彼がオーダーの秘密を -知っていると聞いた。",티모시를 찾아보세요. 제가 듣기론 그가 오더의 비밀들을 알고 있다던데.,Zoek Timothy. Ik heb gehoord dat hij enkele van de geheimen van de Orde kent.,Se etter Timothy. Jeg har hørt at han kjenner noen av Ordenens hemmeligheter.,"Poszukaj Timothy'ego. Słyszałem, że zna niektóre sekrety Zakonu.",Procure por Timothy. Fiquei sabendo que ele conhece alguns segredos da Ordem.,,Uită-te după Timotei. Am auzit că ar cunoaște mai multe secrete ale Ordinului.,"Найди Тимоти. Я слышал, он знает какие-то секреты Ордена.",,Timothy'i ara. Tarikat'ın bazı sırlarını bildiğini duydum. -Just another 5 gold.,TXT_RNO0_SCRIPT23_D10612_JUSTA,,,,Jen dalších pět zlatých.,Bare 5 guld mere.,Nur 5 weitere Goldstücke.,,,Solo otros 5 de oro.,,Vain 5 kolikkoa lisää.,Juste 5 pièces.,Még 5 arany kell.,Giusto altri 5 pezzi d'oro.,たった5ゴールドだぞ。,5 골드만 주세요.,Gewoon nog eens 5 goud.,Bare fem gull til.,Jeszcze tylko 5 złotych.,Só mais 5 moedas.,,Alte 5 monezi.,Всего лишь ещё 5 золотых!,,Sadece 5 altın daha. -"That's all I know. Even bartenders run out of stuff to say, sorry.",TXT_DLG_SCRIPT23_D12128_THATS,,,,"To je vše, co vím. I barmani občas nemají, co dál říct, promiňte.","Det er alt, hvad jeg ved. Selv bartendere løber tør for ting at sige, undskyld.","Das ist alles was ich weiß. Selbst ein Wirt hat irgendwann keine Neugikeiten mehr, tut mir Leid.",,,"Eso es todo lo que sé. Incluso los taberneros se quedan sin cosas que decir, lo siento.",,"Siinä kaikki tietämäni. Jopa baarimikkojen sanaiset arkut ehtyvät, valitan.","C'est tout ce que je sais. Même les barmans peuvent arriver à court d'infos, désolé.","Ennyit tudok. Még a bárpultos tudása sem végtelen, sajnálom.","È tutto ciò che so. Anche i baristi hanno un limite alla loro conoscienza, mi spiace.","知ってることはこれで全部だ。 -バーテンダーの噂は売切れだ、すまない。",내가 아는 건 그것뿐입니다. 바텐더라도 할 말이 떨어질 수 있다고. 미안해요.,"Dat is alles wat ik weet. Zelfs de barmannen hebben niet veel meer te zeggen, sorry.","Det er alt jeg vet. Selv bartendere går tom for ting å si, beklager.","To wszystko, co wiem. Nawet barmanom kończą się rzeczy do powiedzenia, przepraszam.","Isso é tudo o que eu sei. Até donos de bar acabam ficando sem algo pra dizer uma hora, sinto muito.",,"Asta e tot ce știu, până și barmanii rămân fără chestii de zis.","Это всё, что я знаю. Даже у хозяев таверн заканчиваются темы для болтовни, увы.",,"Tüm bildiğim bu. Barmenlerin bile söyleyecek şeyleri bitiyor, üzgünüm." -Hello.,TXT_DLG_SCRIPT23_D13644_HELLO,,,,Ahoj.,Hej.,Hallo.,,Saluton.,Hola.,,Hei.,Bonjour.,Helló.,Salve.,どうも。,안녕하세요.,Hallo.,Hallo.,Witam.,Olá.,,Salut.,Привет.,,Merhaba. -What are you doing?,TXT_RPLY0_SCRIPT23_D13644_WHATA,,,,Co tady děláš?,Hvad laver du?,Was machst du?,,Kion vi faras?,¿Qué estás haciendo?,,Mitä teet?,Qu'est-ce que vous faites?,Mit művelsz?,Cosa stai facendo?,何してるんだ?,무슨 일을 하고 있는거죠?,Wat ben je aan het doen?,Hva holder du på med?,Co robisz?,O que você está fazendo?,,Ce faci?,Чем ты занимаешься?,,Ne yapıyorsun? -"I'm doing stuff, go away!",TXT_RYES0_SCRIPT23_D13644_IMDOI,,,,"Dělám věci, vypadni!","Jeg laver noget, gå væk!","Ich mach' halt was, geh weg!",,,"Estoy haciendo cosas, ¡Lárgate!",,"Teen juttuja, mene pois!","Je suis occupé, laissez-moi tranquille!","Csinálom a dolgom, menj innen!","Sto sbrigando delle cose, vattene!",今は立て込んでる、離れろ!,그냥 뭘 하고 있습니다. 저리가세요!,"Ik doe dingen, ga weg!","Jeg gjør ting, gå vekk!","Robię różne rzeczy, odejdź!","Estou fazendo coisas, vá embora!",,"Am treabă, pleacă!",Ерундой всякой. Отвали!,,"Bir şeyler yapıyorum, git başımdan!" -"If you have this much time to waste, see if you can find the blue chalice. My studies on the Order suggest they have hidden it somewhere in the manufacturing sector of the factory. This artifact would be of great value to me, so, bring it to me, and I'll help you out.",TXT_DLG_SCRIPT23_D15160_IFYOU,,,,"Jestli máš takového volného času, zkus najít modrý kalich. Má pátraní o Řádu naznačují, že je schovaný někde ve výrobním sektoru továrny. Tenhle artifakt by pro mě byl nesmírně cenný, takže jestli mi ho přineseš, pomůžu ti.","Hvis du har så meget tid at spilde, så se om du kan finde den blå bæger. Mine undersøgelser af Ordenen tyder på, at de har gemt den et sted i fabrikkens produktionssektor. Denne artefakt ville være af stor værdi for mig, så bring den til mig, og jeg vil hjælpe dig.","Wenn du so viel Zeit zu verschwenden hast, dann sieh zu, dass du den blauen Kelch finden kannst. Meine Studien über den Orden deuten an, dass er irgendwo im Produktionssektor der Fabrik versteckt sein muss. Dieses Artefakt würde mir viel bedeuten, also bring es mir, und ich werde dir weiterhelfen.",,,"Si tienes tanto tiempo que perder, ve si puedes encontrar el cáliz azul. Mis estudios sobre la Orden sugieren que lo tienen oculto en alguna parte del sector de producción de la fábrica. Este artefacto sería de gran valor para mi, así que, tráemelo, y te ayudaré.",,"Jos sinulla on näin paljon aikaa tuhlattavana, pidä silmäsi auki sinisen uhrimaljan varalta. Tutkimukseni Veljeskunnasta viittaavat siihen, että he ovat kätkeneet sen jonnekin tehtaan tuotanto-osastolla. Esine olisi minulle hyvin arvokas, joten tuo se minulle, ja autan sinua.","Si vous avez autant de temps à perdre, allez voir si vous pouvez récupérer le Calice Bleu. Mes études sur l'Ordre suggèrent qu'ils l'ont caché dans le secteur de manufacture de l'usine. Cet artéfact serait de grande valeur pour moi, amenez-le moi et je vous aiderai.","Ha ilyen őrülten sok időd van, akkor próbáld megkeresni a kék serleget. A kutatásaim azt mutatják, hogy a gyár gyártósoránál van elrejtve. Ez az ereklye nagyon fontos lenne számomra, ha elhozod nekem segítek rajtad.","Se proprio hai così tanto tempo da perdere, vedi se riesci a trovare il calice blu. I miei studi sull'Ordine indiano che lo hanno nascosto da qualche parte del settore manufatturiero della Fabbrica. Questo artifatto mi sarebbe molto utile, quindi se me lo porti, ti potrò aiutare.","アンタがもし時間を浪費するつもりじゃないなら +時間はあまり無いから急ぐのだ。","아냐. 사람 같은 건 절대로 아니라고. 그게 무엇이든, 당신은 어떻게든 싸워서 열쇠를 돌려받아야 합니다. 고대 무덤의 입구를 열어두겠습니다. 만약 열쇠를 얻으셨다면, 광산 옆에 있는 공장으로 향하시길 바랍니다. 시간이 얼마 남지 않았습니다!","Niet. Zeker niet. Wat het ook is, je moet ertegen vechten om de sleutel terug te krijgen. Ik zal de ingang van de catacomben openen. Als je hem hebt, staat de fabriek naast de mijnen. Schiet op, elke seconde telt.","Nei. Definitivt ikke. Uansett hva det er, må du kjempe mot det for å få tak i nøkkelen. Jeg åpner inngangen til katakombene. Når du har den, er fabrikken ved siden av gruvene. Skynd deg, hvert sekund teller.","Nie. Zdecydowanie nie. Cokolwiek to jest, musisz z tym walczyć, aby odzyskać klucz. Ja otworzę wejście do katakumb. Gdy go zdobędziesz, fabryka jest obok kopalni. Spiesz się, liczy się każda sekunda.","Não. Definitivamente não é. Seja lá o que for, você deve enfrentá-lo para recuperar a chave. Vou abrir a entrada das catacumbas. Quando você pegar a chave, vá para a fábrica próxima às minas. Depressa, cada segundo é importante.",,"Nu. Cu siguranță nu. Orice ar fi, va trebui să o înfrunți pentru a recupera cheia. Voi deschide intrarea catacombelor. Când o ai, fabrica e vizavi de mine. Grăbește-te, orice secundă contează.","Нет. Определённо нет. Что бы это ни было, ты должен сразиться с ним, чтобы заполучить ключ. Я открою вход в катакомбы. Когда добудешь его, направляйся на фабрику: она находится рядом со входом в шахты. Торопись! Дорога каждая секунда!",,"Inte. Definitivt inte. Vad det än är måste du slåss mot det för att få tag på nyckeln. Jag öppnar katakombernas ingång. När du har fått den är fabriken bredvid gruvorna. Skynda dig, varje sekund räknas.","İnsan değil. Kesinlikle değil. O her neyse, anahtarı almak için onunla savaşmalısın. Yeraltı mezarlarının girişini açacağım. Anahtarı aldığında, fabrika madenlerin yanında. Acele et, her saniye önemli." +"Something inhuman, eh?, great.",TXT_RPLY0_SCRIPT23_D16676_SOMET,〃,,,"Něco nelidského, co? Skvělý.","Noget umenneskeligt, hva'?, fedt.",Irgendetwas unmenschliches? Na großartig.,,"Nehomaĵo, ĉu? Bonege.","Algo inhumano, ¿eh? Genial.",,"Jotain epäinhimillistä, vai? Hienoa.","Quelque chose d'inhumain, hein? Parfait.","Valami nem emberi, mi? Csodás.","Qualcosa di inumano, eh? Fantastico.",非人道的な何か?流石だな。,비인간적인 녀석인가요? 좋군요.,"Iets onmenselijks, eh?, geweldig.","Noe umenneskelig, hva? Flott!","Coś nieludzkiego, ech, świetnie.","Algo não-humano, é? Que ótimo.",,"Ceva inuman, ei? Grozav.",Что-то иное? Просто отлично.,,"Något omänskligt, va?, bra.","İnsanlık dışı bir şey, ha? Harika." +You're wasting time and lives! Move!,TXT_DLG_SCRIPT23_D18192_YOURE,〃,,,Plýtváš časem i životy! Jdi!,Du spilder tid og liv! Af sted!,Du verschwendest Zeit und Leben! Beweg dich!,,Vi perdas tempon kaj vivojn! Agu!,¡Estás perdiendo tiempo y vidas! ¡Muévete!,,Haaskaat aikaa ja henkiä! Liikkuu jo!,Vous perdez votre temps et des vies! Bougez!,Időt és életeket pazarolsz! Mozgás!,"Stai sprecando tempo, e vite. Sbrigati!","こうしてる間にも君は時間と人命を +無駄にしている。行け!",시간과 생명이 위협받고 있다고! 서두르세요!!,Je verspilt tijd en levens! Vooruit!,Du kaster bort tid og liv! Skynd dere!,Marnujesz czas i życie! Ruszać się!,Você está desperdiçando tempo e vidas! Ande logo!,,"Pierzi timp și vieți, mișcă-te!",Ты тратишь время и жизни! Шевелись!,,Du slösar tid och liv! Flytta på dig!,Zamanınızı ve hayatlarınızı boşa harcıyorsunuz! Çekilin! +Can I be of more help?,TXT_DLG_SCRIPT23_D10612_CANIB,"SVE.WAD +MAP23: Barkeep.",,,Můžu vám dál pomocI?,Kan jeg være til mere hjælp?,Kann ich dir sonst noch irgendwie helfen?,,Ĉu mi povas esti pli helpa?,¿Puedo ser de más ayuda?,,Voinko vielä olla avuksi?,Je peux vous aider?,Lehetek még a segítségedre?,Posso aiutarti ancora?,何かお困りでも?,당신의 도움이 더 되어줄 수 있겠습니까?,Kan ik meer hulp bieden?,Kan jeg være til mer hjelp?,Czy mogę być bardziej pomocny?,Posso ajudar com mais alguma coisa?,,Pot fi mai de ajutor?,Могу ли я чем-нибудь помочь?,,Kan jag vara till mer hjälp?,Daha fazla yardımcı olabilir miyim? +More info.,TXT_RPLY0_SCRIPT23_D10612_MOREI,〃 (dot not recommended),,,Další informace.,Mere info.,Mehr Informationen.,,Pliajn informojn,Más información,,Lisää tietoa.,Plus d'infos.,Több információ.,Più informazioni.,更なる情報。,정보 더 있습니까?,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multă informație.,Информацией.,,Mer information.,Daha fazla bilgi. +Look for Timothy. I've heard he knows some of the Order's secrets.,TXT_RYES0_SCRIPT23_D10612_LOOKF,〃,,,"Najděte Timothyho. Slyšel jsem, že ví nějaká tajemství Řádu.","Kig efter Timothy. Jeg har hørt, at han kender nogle af Ordenens hemmeligheder.","Suche Timothy. Ich habe gehört, das er etwas über die Geheimnisse des Ordens weiß.",,"Serĉu Timoteon. Mi aŭdis, +ke li scias ion pri La Ordeno.","Busca a Timothy. Oí que +sabe algo sobre La Orden.",,Etsi Timothy. Hän kuulemma tietää joitain Veljeskunnan salaisuuksia.,"Cherchez Timothy, j'entends qu'il sait des secrets de l'Ordre.","Keresd Timothyt. Azt hallotam, Ő tud pár Rend titkot.",Cerca Timothy. Ho sentito che conosce alcuni dei segreti dell'Ordine.,"ティモシーを探せ。彼がオーダーの秘密を +知っていると聞いた。",티모시를 찾아보세요. 제가 듣기론 그가 오더의 비밀들을 알고 있다던데.,Zoek Timothy. Ik heb gehoord dat hij enkele van de geheimen van de Orde kent.,Se etter Timothy. Jeg har hørt at han kjenner noen av Ordenens hemmeligheter.,"Poszukaj Timothy'ego. Słyszałem, że zna niektóre sekrety Zakonu.",Procure por Timothy. Fiquei sabendo que ele conhece alguns segredos da Ordem.,,Uită-te după Timotei. Am auzit că ar cunoaște mai multe secrete ale Ordinului.,"Найди Тимоти. Я слышал, он знает какие-то секреты Ордена.",,Leta efter Timothy. Jag har hört att han känner till några av ordens hemligheter.,Timothy'i ara. Tarikat'ın bazı sırlarını bildiğini duydum. +Just another 5 gold.,TXT_RNO0_SCRIPT23_D10612_JUSTA,〃,,,Jen dalších pět zlatých.,Bare 5 guld mere.,Nur 5 weitere Goldstücke.,,"Nur ankoraŭ +kvin da oro.",Solo otros cinco de oro.,,Vain 5 kolikkoa lisää.,Juste 5 pièces.,Még 5 arany kell.,Giusto altri 5 pezzi d'oro.,たった5ゴールドだぞ。,5 골드만 주세요.,Gewoon nog eens 5 goud.,Bare fem gull til.,Jeszcze tylko 5 złotych.,Só mais 5 moedas.,,Alte 5 monezi.,Всего лишь ещё 5 золотых!,,Bara ytterligare 5 guld.,Sadece 5 altın daha. +"That's all I know. Even bartenders run out of stuff to say, sorry.",TXT_DLG_SCRIPT23_D12128_THATS,〃,,,"To je vše, co vím. I barmani občas nemají, co dál říct, promiňte.","Det er alt, hvad jeg ved. Selv bartendere løber tør for ting at sige, undskyld.","Das ist alles was ich weiß. Selbst ein Wirt hat irgendwann keine Neugikeiten mehr, tut mir Leid.",,Mi scias nenion plian. Eĉ drinkejestroj restas sen dirindaĵoj. Pardonon.,Eso es todo lo que sé. Incluso los taberneros se quedan sin cosas que decir. Lo siento.,,"Siinä kaikki tietämäni. Jopa baarimikkojen sanaiset arkut ehtyvät, valitan.","C'est tout ce que je sais. Même les barmans peuvent arriver à court d'infos, désolé.","Ennyit tudok. Még a bárpultos tudása sem végtelen, sajnálom.","È tutto ciò che so. Anche i baristi hanno un limite alla loro conoscienza, mi spiace.","知ってることはこれで全部だ。 +バーテンダーの噂は売切れだ、すまない。",내가 아는 건 그것뿐입니다. 바텐더라도 할 말이 떨어질 수 있다고. 미안해요.,"Dat is alles wat ik weet. Zelfs de barmannen hebben niet veel meer te zeggen, sorry.","Det er alt jeg vet. Selv bartendere går tom for ting å si, beklager.","To wszystko, co wiem. Nawet barmanom kończą się rzeczy do powiedzenia, przepraszam.","Isso é tudo o que eu sei. Até donos de bar acabam ficando sem algo pra dizer uma hora, sinto muito.",,"Asta e tot ce știu, până și barmanii rămân fără chestii de zis.","Это всё, что я знаю. Даже у хозяев таверн заканчиваются темы для болтовни, увы.",,"Det är allt jag vet. Till och med bartender får slut på saker att säga, tyvärr.","Tüm bildiğim bu. Barmenlerin bile söyleyecek şeyleri bitiyor, üzgünüm." +Hello.,TXT_DLG_SCRIPT23_D13644_HELLO,"SVE.WAD +MAP23: Timothy (Talking with him for the very first time without the chalice).",,,Ahoj.,Hej.,Hallo.,,Saluton.,Hola.,,Hei.,Bonjour.,Helló.,Salve.,どうも。,안녕하세요.,Hallo.,Hallo.,Witam.,Olá.,,Salut.,Привет.,,Hej.,Merhaba. +What are you doing?,TXT_RPLY0_SCRIPT23_D13644_WHATA,〃,,,Co tady děláš?,Hvad laver du?,Was machst du?,,Kion vi faras?,¿Qué estás haciendo?,,Mitä teet?,Qu'est-ce que vous faites?,Mit művelsz?,Cosa stai facendo?,何してるんだ?,무슨 일을 하고 있는거죠?,Wat ben je aan het doen?,Hva holder du på med?,Co robisz?,O que você está fazendo?,,Ce faci?,Чем ты занимаешься?,,Vad gör du?,Ne yapıyorsun? +"I'm doing stuff, go away!",TXT_RYES0_SCRIPT23_D13644_IMDOI,〃,,,"Dělám věci, vypadni!","Jeg laver noget, gå væk!","Ich mach' halt was, geh weg!",,Mi umas. Foriru!,Cosas. ¡Ya vete!,,"Teen juttuja, mene pois!","Je suis occupé, laissez-moi tranquille!","Csinálom a dolgom, menj innen!","Sto sbrigando delle cose, vattene!",今は立て込んでる、離れろ!,그냥 뭘 하고 있습니다. 저리가세요!,"Ik doe dingen, ga weg!","Jeg gjør ting, gå vekk!","Robię różne rzeczy, odejdź!","Estou fazendo coisas, vá embora!",,"Am treabă, pleacă!",Ерундой всякой. Отвали!,,"Jag gör saker, försvinn!","Bir şeyler yapıyorum, git başımdan!" +"If you have this much time to waste, see if you can find the blue chalice. My studies on the Order suggest they have hidden it somewhere in the manufacturing sector of the factory. This artifact would be of great value to me, so, bring it to me, and I'll help you out.",TXT_DLG_SCRIPT23_D15160_IFYOU,〃,,,"Jestli máš takového volného času, zkus najít modrý kalich. Má pátraní o Řádu naznačují, že je schovaný někde ve výrobním sektoru továrny. Tenhle artifakt by pro mě byl nesmírně cenný, takže jestli mi ho přineseš, pomůžu ti.","Hvis du har så meget tid at spilde, så se om du kan finde den blå bæger. Mine undersøgelser af Ordenen tyder på, at de har gemt den et sted i fabrikkens produktionssektor. Denne artefakt ville være af stor værdi for mig, så bring den til mig, og jeg vil hjælpe dig.","Wenn du so viel Zeit zu verschwenden hast, dann sieh zu, dass du den blauen Kelch finden kannst. Meine Studien über den Orden deuten an, dass er irgendwo im Produktionssektor der Fabrik versteckt sein muss. Dieses Artefakt würde mir viel bedeuten, also bring es mir, und ich werde dir weiterhelfen.",,"Se vi estas tiel senokupa, provu trovi la bluan kalikon. Miaj studoj pri La Ordeno sugestas, ke ili kaŝis ĝin ien en la manufakturo de la fabriko. Tiu artefakto estus tre valora por mi, do alportu ĝin kaj mi helpos vin.","Si tan aburrido estás, ve a ver si puedes encontrar el cáliz azul. Mis estudios sobre La Orden sugieren que está oculto en alguna parte del sector de manufactura de la fábrica. Ese artefacto me sería de gran valor, así que tráemelo y te ayudaré.","Si tan aburrido estás, ve a ver si puedes encontrar el cáliz azul. Mis estudios sobre La Orden sugieren que está oculto en alguna parte del sector de manufactura de la fábrica. Ese artefacto me sería de gran valor, así que tráemelo y te voy a ayudar.","Jos sinulla on näin paljon aikaa tuhlattavana, pidä silmäsi auki sinisen uhrimaljan varalta. Tutkimukseni Veljeskunnasta viittaavat siihen, että he ovat kätkeneet sen jonnekin tehtaan tuotanto-osastolla. Esine olisi minulle hyvin arvokas, joten tuo se minulle, ja autan sinua.","Si vous avez autant de temps à perdre, allez voir si vous pouvez récupérer le Calice Bleu. Mes études sur l'Ordre suggèrent qu'ils l'ont caché dans le secteur de manufacture de l'usine. Cet artéfact serait de grande valeur pour moi, amenez-le moi et je vous aiderai.","Ha ilyen őrülten sok időd van, akkor próbáld megkeresni a kék serleget. A kutatásaim azt mutatják, hogy a gyár gyártósoránál van elrejtve. Ez az ereklye nagyon fontos lenne számomra, ha elhozod nekem segítek rajtad.","Se proprio hai così tanto tempo da perdere, vedi se riesci a trovare il calice blu. I miei studi sull'Ordine indiano che lo hanno nascosto da qualche parte del settore manufatturiero della Fabbrica. Questo artifatto mi sarebbe molto utile, quindi se me lo porti, ti potrò aiutare.","アンタがもし時間を浪費するつもりじゃないなら 青の聖杯を見つけられるかどうかを確かめる。 その骨董品は俺にとって非常に価値がある。 -持ってきたら協力しよう。","만약 시간이 남아돈다면, 푸른 성배를 찾아보러 가시는 게 어떤가요? 오더에 대한 제 연구가 맞아떨어진다면, 그것은 분명히 공장의 조립시설에 숨겨져 있을 겁니다. 그 보물은 더 할 말 없이 아주 진귀할 거에요. 그걸 찾아주면, 딱 맞는 보답을 해주지요.","Als je zoveel tijd te verliezen hebt, kijk dan of je de blauwe kelk kunt vinden. Mijn studies over de Orde suggereren dat ze het ergens in de productiesector van de fabriek verborgen hebben. Dit artefact zou van grote waarde zijn voor mij, dus, breng het naar mij, en ik zal je helpen.","Hvis du har så mye tid å kaste bort, se om du kan finne det blå begeret. Mine studier om Ordenen tyder på at de har gjemt det et sted i fabrikkens produksjonssektor. Denne gjenstanden vil være av stor verdi for meg, så ta den med til meg, så skal jeg hjelpe deg.","Jeśli masz tyle czasu do stracenia, sprawdź, czy znajdziesz niebieski kielich. Moje badania nad Zakonem sugerują, że ukryli go gdzieś w sektorze produkcyjnym fabryki. Ten artefakt miałby dla mnie ogromną wartość, więc, przynieś go do mnie, a pomogę ci.","Se você tem tanto tempo livre assim, veja se você consegue achar o cálice azul. Pelo que pesquisei sobre a Ordem, eles o esconderam em algum lugar no setor de manufatura da fábrica. Esse artefato seria de grande valor pra mim, então traga ele para mim e eu te ajudarei.",,"Dacă ai atât de mult timp de pierdut, vezi dacă poți găsi pocalul albastru. Studiile mele indică faptul că Ordinul l-a ascuns undeva în sectorul de manufactură al fabricii. Artefactul mi-ar fi de mare folos, așa că, adu-mi-l, și o să te ajut.","Если тебе не жаль времени, найди синюю чашу. Я изучал Орден и узнал, что они спрятали её где-то в обрабатывающем секторе фабрики. Мне очень нужен этот артефакт. Принеси его мне, и я помогу тебе.",,"Kaybedecek bu kadar zamanın varsa, mavi kadehi bulmaya çalış. Tarikat üzerine yaptığım çalışmalar, onu fabrikanın üretim bölümünde bir yere sakladıklarını gösteriyor. Bu obje benim için çok değerli, bu yüzden onu bana getir, ben de sana yardım edeyim." -"You found the blue chalice! OK, give it to me first, and we'll trade.",TXT_DLG_SCRIPT23_D16676_YOUFO,,,,"Tys našel modrý kalich! Dobře, nejprv mi ho dej a vyrovnáme se.","Du har fundet den blå bæger! OK, giv mig den først, så kan vi bytte.","Du hast den blauen Kelch gefunden! Ok, erst gibst du ihn mir, dann handeln wir.",,,"¡Has encontrado el cáliz azul! Ok, dámelo primero, y negociamos.",,"Löysit sinisen maljan! No niin, anna se ensin minulle, niin tehdään vaihtokaupat.","Vous avez le Calice Bleu! Ok, donnez le moi et nous échangerons.","Megszerezted a kék serleget! OK, add ide gyorsan először, aztán üzletelhetünk.","Hai trovato il calice blu! OK, dammelo, e poi possiamo trattare.","青の聖杯を見つけたのか! -良し、それをくれたら取引に応じよう。",푸른 성배를 정말로 찾으셨군요! 저에게 주세요. 그럼 거래를 시작하죠!,"Je hebt de blauwe kelk gevonden! Oké, geef hem eerst aan mij, dan ruilen we hem.","Du fant det blå begeret! OK, gi det til meg først, så bytter vi.","Znalazłeś niebieski kielich! OK, daj mi go najpierw, a wymienimy się.","Você achou o cálice azul! Ok, me dê ele primeiro e aí a gente negocia.",,"Ai găsit pocalul albastru! OK, dă-mi-l, și o să facem schimb.","Ты нашёл синюю чашу! Отдай её мне, и я исполню свою часть договора.",,"Mavi kadehi bulmuşsun! Tamam, önce onu bana ver, sonra takas ederiz." -"Take it, it's bad luck anyway.",TXT_RPLY0_SCRIPT23_D16676_TAKEI,,,,"Vem si ho, stejně přináší jen smůlu.","Tag den, den bringer alligevel uheld.","Nimm ihn, er bringt sowieso Unglück.",,,"Toma, de todos modos da mala suerte.",,"Ota se, epäonnenkalu se kuitenkin on.","Gardez le, je parie qu'il file malchance.","Vidd nyugodtan, rossz szerencsét hoz amúgyis.","Prendilo, tanto porta sfortuna.",渡そう、兎に角運が悪かった。,여기 받아요. 재수 없어 보이니까.,"Neem het, het is toch al pech.","Ta det, det bringer ulykke uansett.","Weź go, to i tak przynosi pecha.",Pode pegar. Isso atrai azar de qualquer forma.,,"Ia-l, poartă ghinion oricum.",Держи. Она всё равно приносит несчастье.,,"Al, zaten kötü şans getirir." -"Screw you, I'm keeping it.",TXT_RPLY1_SCRIPT23_D16676_SCREW,,,,"Jdi se vycpat, nechám si ho.","Rend mig, jeg beholder den.","Ach, was soll's. Ich behalte ihn.",,,"Que te zurzan, me lo quedo.","Al diablo, me lo quedo.","Vedä käteen, pidän sen itselläni.","Allez vous faire voir, il est à moi maintenant.","Nagy francot, inkább megtartom.",E invece me lo tengo!,ふざけるな、俺の物だ。,"배 째시지, 이건 이제 제거에요.","Krijg de klere, ik hou het.","Faen ta deg, jeg beholder det.","Wal się, zatrzymuję go.","Vá se ferrar, ele é meu.",,"Du-te naibi, îl păstrez.",Пошёл ты! Я оставлю её себе.,,"Siktir git, bende kalacak." -Then I'm not giving you anything. Get lost!,TXT_RYES1_SCRIPT23_D16676_THENI,,,,Pak ti nic nedám. Zmizni!,Så giver jeg dig ikke noget. Forsvind!,Dann bekommst du auch nichts von mir. Verzieh dich!,,,Entonces no te voy a dar nada. ¡Piérdete!,,Sitten en anna sinulle mitään. Antaa vetää!,"Rien pour vous, alors, dégagez!",Akkor meg tudod mikor adok neked bármit is. Húzzál elfelé!,E allora non ti darò niente. Sparisci!,何もやるモンは無いぞ。失せな!,이런 식으로 나가시겠다? 그럼 거래를 취소하죠. 사라지세요!,Dan geef ik je niets. Donder op!,Da gir jeg deg ingenting. Forsvinn!,Więc nic ci nie dam. Spadaj!,Então não te darei nada. Se manda!,,Atunci nu îți dau nimic. Valea!,Тогда я тебе ничего не скажу. Убирайся!,,O zaman sana hiçbir şey vermiyorum. Kaybol! -Locate the forge. The information I just gave you should help you enter a secretive sector of the factory. One of the forge workers can open the door.,TXT_DLG_SCRIPT23_D18192_LOCAT,,,,"Najdi slévárnu. Informace, které jsem ti právě dal, ti pomůžou vstoupit do tajného sektoru továrny. Jeden z pracovníků slévárny ti otevře dveře.","Find smedjen. De oplysninger, jeg lige har givet dig, skulle hjælpe dig med at komme ind i en hemmelig sektor af fabrikken. En af smediearbejderne kan åbne døren.","Finde die Schmiede. Die Informationen, die ich dir gegeben habe, sollten dir helfen einen geheimen Sektor der Fabrik zu betreten. Einer der Schmiedearbeiter kann dir helfen die Tür zu öffnen.",,,Localiza la forja. La información que te he dado debería ayudarte a entrar a un sector secreto de la fábrica. Uno de los trabajadores de la forja puede abrir la puerta.,,Suunnista pajalle. Juuri antamani tiedon pitäisi auttaa sinua pääsemään salamyhkäiseen osastoon tehtaalla. Yksi pajan työntekijöistä voi avata oven.,Localisez la forge. L'information que je vous ai donnée devrait vous aider à entrer dans une section secrète de l'usine. L'un des travailleurs de la forge peut ouvrir la porte pour vous.,"Keresd meg a kohót. Az információ amit adtam, segíteni fog abban, hogy megleld a gyár titkos részét. Az egyik kohóban dolgozó ki tudja nyitni az ajtót.",Trova la fucina. Le informazioni che ti ho appena dato ti dovrebbero aiutare a trovare una sezione segreta della Fabbrica. Uno dei lavoratori della fucina ti potrà aprire la porta.,"工場の鉄工所を探せ。俺が与えた情報は +持ってきたら協力しよう。","만약 시간이 남아돈다면, 푸른 성배를 찾아보러 가시는 게 어떤가요? 오더에 대한 제 연구가 맞아떨어진다면, 그것은 분명히 공장의 조립시설에 숨겨져 있을 겁니다. 그 보물은 더 할 말 없이 아주 진귀할 거에요. 그걸 찾아주면, 딱 맞는 보답을 해주지요.","Als je zoveel tijd te verliezen hebt, kijk dan of je de blauwe kelk kunt vinden. Mijn studies over de Orde suggereren dat ze het ergens in de productiesector van de fabriek verborgen hebben. Dit artefact zou van grote waarde zijn voor mij, dus, breng het naar mij, en ik zal je helpen.","Hvis du har så mye tid å kaste bort, se om du kan finne det blå begeret. Mine studier om Ordenen tyder på at de har gjemt det et sted i fabrikkens produksjonssektor. Denne gjenstanden vil være av stor verdi for meg, så ta den med til meg, så skal jeg hjelpe deg.","Jeśli masz tyle czasu do stracenia, sprawdź, czy znajdziesz niebieski kielich. Moje badania nad Zakonem sugerują, że ukryli go gdzieś w sektorze produkcyjnym fabryki. Ten artefakt miałby dla mnie ogromną wartość, więc, przynieś go do mnie, a pomogę ci.","Se você tem tanto tempo livre assim, veja se você consegue achar o cálice azul. Pelo que pesquisei sobre a Ordem, eles o esconderam em algum lugar no setor de manufatura da fábrica. Esse artefato seria de grande valor pra mim, então traga ele para mim e eu te ajudarei.",,"Dacă ai atât de mult timp de pierdut, vezi dacă poți găsi pocalul albastru. Studiile mele indică faptul că Ordinul l-a ascuns undeva în sectorul de manufactură al fabricii. Artefactul mi-ar fi de mare folos, așa că, adu-mi-l, și o să te ajut.","Если тебе не жаль времени, найди синюю чашу. Я изучал Орден и узнал, что они спрятали её где-то в обрабатывающем секторе фабрики. Мне очень нужен этот артефакт. Принеси его мне, и я помогу тебе.",,"Om du har så mycket tid att slösa, se om du kan hitta den blå bägaren. Mina studier om orden tyder på att de har gömt den någonstans i fabrikens tillverkningssektor. Denna artefakt skulle vara av stort värde för mig, så, ta med den till mig så ska jag hjälpa dig.","Kaybedecek bu kadar zamanın varsa, mavi kadehi bulmaya çalış. Tarikat üzerine yaptığım çalışmalar, onu fabrikanın üretim bölümünde bir yere sakladıklarını gösteriyor. Bu obje benim için çok değerli, bu yüzden onu bana getir, ben de sana yardım edeyim." +"You found the blue chalice! OK, give it to me first, and we'll trade.",TXT_DLG_SCRIPT23_D16676_YOUFO,〃,,,"Tys našel modrý kalich! Dobře, nejprv mi ho dej a vyrovnáme se.","Du har fundet den blå bæger! OK, giv mig den først, så kan vi bytte.","Du hast den blauen Kelch gefunden! Ok, erst gibst du ihn mir, dann handeln wir.",,"Vi trovis la bluan kalikon! Bone, vi unue donu ĝin kaj tiam ni interkonsentos.","¡Has encontrado el cáliz azul! Bueno, dámelo primero y negociamos.","¡Encontraste el cáliz azul! Bueno, dámelo primero y negociamos.","Löysit sinisen maljan! No niin, anna se ensin minulle, niin tehdään vaihtokaupat.","Vous avez le Calice Bleu! Ok, donnez le moi et nous échangerons.","Megszerezted a kék serleget! OK, add ide gyorsan először, aztán üzletelhetünk.","Hai trovato il calice blu! OK, dammelo, e poi possiamo trattare.","青の聖杯を見つけたのか! +良し、それをくれたら取引に応じよう。",푸른 성배를 정말로 찾으셨군요! 저에게 주세요. 그럼 거래를 시작하죠!,"Je hebt de blauwe kelk gevonden! Oké, geef hem eerst aan mij, dan ruilen we hem.","Du fant det blå begeret! OK, gi det til meg først, så bytter vi.","Znalazłeś niebieski kielich! OK, daj mi go najpierw, a wymienimy się.","Você achou o cálice azul! Ok, me dê ele primeiro e aí a gente negocia.",,"Ai găsit pocalul albastru! OK, dă-mi-l, și o să facem schimb.","Ты нашёл синюю чашу! Отдай её мне, и я исполню свою часть договора.",,"Du har hittat den blå bägaren! Okej, ge den till mig först så byter vi.","Mavi kadehi bulmuşsun! Tamam, önce onu bana ver, sonra takas ederiz." +"Take it, it's bad luck anyway.",TXT_RPLY0_SCRIPT23_D16676_TAKEI,〃,,,"Vem si ho, stejně přináší jen smůlu.","Tag den, den bringer alligevel uheld.","Nimm ihn, er bringt sowieso Unglück.",,"Havu, ĝi alportas misfortunon.","Toma, de todos modos da mala suerte.",,"Ota se, epäonnenkalu se kuitenkin on.","Gardez le, je parie qu'il file malchance.","Vidd nyugodtan, rossz szerencsét hoz amúgyis.","Prendilo, tanto porta sfortuna.",渡そう、兎に角運が悪かった。,여기 받아요. 재수 없어 보이니까.,"Neem het, het is toch al pech.","Ta det, det bringer ulykke uansett.","Weź go, to i tak przynosi pecha.",Pode pegar. Isso atrai azar de qualquer forma.,,"Ia-l, poartă ghinion oricum.",Держи. Она всё равно приносит несчастье.,,"Ta den, den betyder ändå otur.","Al, zaten kötü şans getirir." +"Screw you, I'm keeping it.",TXT_RPLY1_SCRIPT23_D16676_SCREW,〃,,,"Jdi se vycpat, nechám si ho.","Rend mig, jeg beholder den.","Ach, was soll's. Ich behalte ihn.",,"Al la diablo, mi konservos ĝin.","Que te zurzan, me lo quedo.","Al diablo, me lo quedo.","Vedä käteen, pidän sen itselläni.","Allez vous faire voir, il est à moi maintenant.","Nagy francot, inkább megtartom.",E invece me lo tengo!,ふざけるな、俺の物だ。,"배 째시지, 이건 이제 제거에요.","Krijg de klere, ik hou het.","Faen ta deg, jeg beholder det.","Wal się, zatrzymuję go.","Vá se ferrar, ele é meu.",,"Du-te naibi, îl păstrez.",Пошёл ты! Я оставлю её себе.,,"Dra åt helvete, jag behåller den.","Siktir git, bende kalacak." +Then I'm not giving you anything. Get lost!,TXT_RYES1_SCRIPT23_D16676_THENI,〃 (If you keep the chalice),,,Pak ti nic nedám. Zmizni!,Så giver jeg dig ikke noget. Forsvind!,Dann bekommst du auch nichts von mir. Verzieh dich!,,"Tiuokaze mi donos +nenion al vi. Foriru!","Entonces +no te doy nada. ¡Vete!",,Sitten en anna sinulle mitään. Antaa vetää!,"Rien pour vous, alors, dégagez!",Akkor meg tudod mikor adok neked bármit is. Húzzál elfelé!,E allora non ti darò niente. Sparisci!,何もやるモンは無いぞ。失せな!,이런 식으로 나가시겠다? 그럼 거래를 취소하죠. 사라지세요!,Dan geef ik je niets. Donder op!,Da gir jeg deg ingenting. Forsvinn!,Więc nic ci nie dam. Spadaj!,Então não te darei nada. Se manda!,,Atunci nu îți dau nimic. Valea!,Тогда я тебе ничего не скажу. Убирайся!,,Då ger jag dig ingenting. Försvinn!,O zaman sana hiçbir şey vermiyorum. Kaybol! +Locate the forge. The information I just gave you should help you enter a secretive sector of the factory. One of the forge workers can open the door.,TXT_DLG_SCRIPT23_D18192_LOCAT,〃 (If you give the chalice away),,,"Najdi slévárnu. Informace, které jsem ti právě dal, ti pomůžou vstoupit do tajného sektoru továrny. Jeden z pracovníků slévárny ti otevře dveře.","Find smedjen. De oplysninger, jeg lige har givet dig, skulle hjælpe dig med at komme ind i en hemmelig sektor af fabrikken. En af smediearbejderne kan åbne døren.","Finde die Schmiede. Die Informationen, die ich dir gegeben habe, sollten dir helfen einen geheimen Sektor der Fabrik zu betreten. Einer der Schmiedearbeiter kann dir helfen die Tür zu öffnen.",,"Iru al la forĝejo. La informoj, kiujn mi donis, devus permesi al vi eniri sekretan sektoron en la fabriko. Unu el la laboristoj en la forĝejo povas malfermi la pordon.",Ve a la forja. La información que te he dado debería permitirte entrar en un sector secreto de la fábrica. Uno de los trabajadores de la forja puede abrir la puerta.,Ve a la forja. La información que te di debería permitirte entrar a un sector secreto de la fábrica. Uno de los trabajadores de la forja puede abrir la puerta.,Suunnista pajalle. Juuri antamani tiedon pitäisi auttaa sinua pääsemään salamyhkäiseen osastoon tehtaalla. Yksi pajan työntekijöistä voi avata oven.,Localisez la forge. L'information que je vous ai donnée devrait vous aider à entrer dans une section secrète de l'usine. L'un des travailleurs de la forge peut ouvrir la porte pour vous.,"Keresd meg a kohót. Az információ amit adtam, segíteni fog abban, hogy megleld a gyár titkos részét. Az egyik kohóban dolgozó ki tudja nyitni az ajtót.",Trova la fucina. Le informazioni che ti ho appena dato ti dovrebbero aiutare a trovare una sezione segreta della Fabbrica. Uno dei lavoratori della fucina ti potrà aprire la porta.,"工場の鉄工所を探せ。俺が与えた情報は そこの隠された区域に入る為に必要だ。 -偽の作業員がドアを開けるだろう。",공장의 제련소로 찾아가세요. 제가 제공한 정보만 있으면 그곳으로 향하는 비밀구역을 쉽게 찾을 수 있을 겁니다. 제련소 직원 중 한 명이 그곳으로 향하는 문을 열 수 있어요.,Zoek de smederij. De informatie die ik je net heb gegeven zou je moeten helpen om een geheime sector van de fabriek te betreden. Een van de smidsewerkers kan de deur openen.,Finn smia. Informasjonen jeg nettopp ga deg bør hjelpe deg å komme inn i en hemmelig sektor av fabrikken. En av smiearbeiderne kan åpne døren.,"Zlokalizuj kuźnię. Informacje, które przed chwilą podałem, powinny pomóc ci wejść do tajnego sektora fabryki. Jeden z pracowników kuźni może otworzyć drzwi.",Localize a forja. A informação que acabei de te passar deve ajudar para entrar em um setor secreto da fábrica. Um dos operários da forja pode abrir a porta.,,Găsește forja. Informațiile pe care ți le-am oferit ar trebui să te ajute să intri într-un sector secret al fabricii. Unul dintre făurari poate deschide ușa.,"Найди кузню. Сведения, которые я передал тебе, помогут тебе пройти в секретный сектор фабрики. Один из работников в кузне откроет тебе дверь.",,Demirhaneyi bulun. Sana verdiğim bilgiler fabrikanın gizli bir bölümüne girmene yardımcı olacaktır. Demirci işçilerinden biri kapıyı açabilir. -What can I find there?,TXT_RPLY0_SCRIPT23_D18192_WHATC,,,,Co tam můžu najít?,Hvad kan jeg finde der?,Was kann ich dort finden?,,,¿Qué puedo encontrar allí?,,Mitä löydän sieltä?,Qu'est ce que je peux y trouver?,Mit fogok ott találni?,Che cosa troverò là?,そこには何がある?,그곳을 어떻게 찾을 수 있죠?,Wat kan ik daar vinden?,Hva kan jeg finne der?,Co mogę tam znaleźć?,O que vou encontrar lá?,,Ce pot găsi acolo?,Что там находится?,,Orada ne bulabilirim? -My research suggests that some dark power from the ancient past is hidden there. Be careful!,TXT_DLG_SCRIPT23_D19708_MYRES,,,,"Můj výzkum naznačuje, že se tam schovává nějaká starověká temná síla. Buď opatrný!","Min forskning tyder på, at der er gemt en mørk magt fra den gamle fortid der. Vær forsigtig!","Meine Nachforschungen lassen vermuten, dass dort eine dunkle Macht aus längst vergangenen Zeiten versteckt ist. Sei vorsichtig!",,,Mi investigación sugiere que algún poder oscuro de la antigüedad se oculta allí. ¡Ten cuidado!,,"Tutkimukseni viittaa siihen, että jokin pimeä voima muinaismenneisyydestä on kätketty sinne. Ole varuillasi!",Mes recherches suggèrent qu'il y a un pouvoir sombre ancien qui s'y cache. Faites attention!,"A kutatásaim azt mutatják, hogy az ősidőkből maradt sötét erő bújik meg ott. Légy óvatos!","Dopo attente ricerche sul materiale che ho, ho stabilito che un oscuro e antico potere è nascosto lì. Fai attenzione!","俺の調査では、古代の災厄がそこに隠されている -という話だ。注意しろよ!","제가 연구를 좀 더 해봤는데, 그곳에서 사악한 고대의 기운이 솟아난다는군요. 조심하시길!",Mijn onderzoek suggereert dat daar een duistere kracht uit het oude verleden verborgen ligt. Wees voorzichtig!,Forskningen min tyder på at en mørk kraft fra fortiden er skjult der. Vær forsiktig!,"Moje badania sugerują, że ukryta jest tam jakaś mroczna moc z zamierzchłej przeszłości. Bądź ostrożny!",Minha pesquisa sugere que há algum poder sombrio do passado antigo escondido naquele lugar. Tome cuidado!,,Investigațiile mele indică faptul că ceva putere întunecată din trecutul antic e ascunsă acolo. Ai grijă!,"Судя по результатам исследования, какая-то тёмная сила из далёкого прошлого. Будь осторожен!",,"Araştırmalarım, kadim geçmişten gelen karanlık bir gücün orada saklı olduğunu gösteriyor. Dikkatli ol!" -"That blue chalice, how'd you come by it? I've been researching the Order and their links to the distant past, and that artifact would help me. Let's make a deal. Give me the chalice, and I'll give you some info.",TXT_DLG_SCRIPT23_D21224_THATB,,,,"Ten modrý kalich, jak jsi k němu přišel? Zkoumal jsem Řád a jeho pojítka k dávné minulosti a ten artefakt by mi pomohl. Udělejme dohodu: Ty mi dáš ten kalich a já ti dám nějaké informace.","Den blå bæger, hvordan er du kommet til den? Jeg har forsket i Ordenen og deres forbindelser til den fjerne fortid, og denne artefakt ville hjælpe mig. Lad os lave en aftale. Giv mig bægeret, og jeg giver dig nogle oplysninger.","Dieser blaue Kelch, wie bist du da ran gekommen? Ich habe bereits über den Orden und deren Verbindung zur fernen Vergangenheit recherchiert, und dieses Artefakt könnte mir weiterhelfen. Ich schlage dir etwas vor: Gib mir den Kelch und ich gebe dir Informationen.",,,"Ese cáliz azul, ¿Cómo lo has encontrado? He estado investigando a La Orden y sus conexiones con el pasado distante, y ese artefacto me ayudaría. Hagamos un trato. Dame el cáliz, y te daré algo de información.",,"Tuo sininen uhrimalja, miten onnistuit saamaan sen? Olen tutkinut Veljeskuntaa ja sen kytköksiä kaukaiseen menneisyyteen, ja tuo esine auttaisi minua. Tehdäänpä kauppa: Sinä annat minulle maljan, ja minä annan sinulle tietoa.","Ce calice bleu, comment l'avez vous trouvé? Je fais des recherches sur l'Ordre et leurs liens avec le passé. Cet artéfact m'aiderait beaucoup. Faisons affaires: donnez le moi et je vous aiderai.","Hogyan sikerült megszerened azt a kék serleget? Kutattam a Rendet és kapcsolatukat a messzi múlttal, és ez az ereklye nagy segítség lenne. Kössünk üzletet. Add ide a serleget, és cserébe kapsz információt.","Quel calice blu, come lo hai trovato? Ho passato molto tempo a ricercare l'Ordine e i suoi legami con il lontano passato, e quell'artifatto mi aiuterebbe. Facciamo una cosa. Se mi dai il calice, io ti darò delle informazioni.","その青い聖杯はどうした? +偽の作業員がドアを開けるだろう。",공장의 제련소로 찾아가세요. 제가 제공한 정보만 있으면 그곳으로 향하는 비밀구역을 쉽게 찾을 수 있을 겁니다. 제련소 직원 중 한 명이 그곳으로 향하는 문을 열 수 있어요.,Zoek de smederij. De informatie die ik je net heb gegeven zou je moeten helpen om een geheime sector van de fabriek te betreden. Een van de smidsewerkers kan de deur openen.,Finn smia. Informasjonen jeg nettopp ga deg bør hjelpe deg å komme inn i en hemmelig sektor av fabrikken. En av smiearbeiderne kan åpne døren.,"Zlokalizuj kuźnię. Informacje, które przed chwilą podałem, powinny pomóc ci wejść do tajnego sektora fabryki. Jeden z pracowników kuźni może otworzyć drzwi.",Localize a forja. A informação que acabei de te passar deve ajudar para entrar em um setor secreto da fábrica. Um dos operários da forja pode abrir a porta.,,Găsește forja. Informațiile pe care ți le-am oferit ar trebui să te ajute să intri într-un sector secret al fabricii. Unul dintre făurari poate deschide ușa.,"Найди кузню. Сведения, которые я передал тебе, помогут тебе пройти в секретный сектор фабрики. Один из работников в кузне откроет тебе дверь.",,Leta upp smedjan. Informationen jag just gav dig ska hjälpa dig att komma in i en hemlig sektor av fabriken. En av smidesarbetarna kan öppna dörren.,Demirhaneyi bulun. Sana verdiğim bilgiler fabrikanın gizli bir bölümüne girmene yardımcı olacaktır. Demirci işçilerinden biri kapıyı açabilir. +What can I find there?,TXT_RPLY0_SCRIPT23_D18192_WHATC,〃,,,Co tam můžu najít?,Hvad kan jeg finde der?,Was kann ich dort finden?,,Kion mi trovos tien?,¿Qué puedo encontrar allí?,,Mitä löydän sieltä?,Qu'est ce que je peux y trouver?,Mit fogok ott találni?,Che cosa troverò là?,そこには何がある?,그곳을 어떻게 찾을 수 있죠?,Wat kan ik daar vinden?,Hva kan jeg finne der?,Co mogę tam znaleźć?,O que vou encontrar lá?,,Ce pot găsi acolo?,Что там находится?,,Vad kan jag hitta där?,Orada ne bulabilirim? +My research suggests that some dark power from the ancient past is hidden there. Be careful!,TXT_DLG_SCRIPT23_D19708_MYRES,〃,,,"Můj výzkum naznačuje, že se tam schovává nějaká starověká temná síla. Buď opatrný!","Min forskning tyder på, at der er gemt en mørk magt fra den gamle fortid der. Vær forsigtig!","Meine Nachforschungen lassen vermuten, dass dort eine dunkle Macht aus längst vergangenen Zeiten versteckt ist. Sei vorsichtig!",,"Mia esplorado sugestas, ke malluma povo de la antikveco estas kaŝita tie. Gardu vin!",Mi investigación sugiere que un poder oscuro de la antigüedad se oculta allí. ¡Ten cuidado!,,"Tutkimukseni viittaa siihen, että jokin pimeä voima muinaismenneisyydestä on kätketty sinne. Ole varuillasi!",Mes recherches suggèrent qu'il y a un pouvoir sombre ancien qui s'y cache. Faites attention!,"A kutatásaim azt mutatják, hogy az ősidőkből maradt sötét erő bújik meg ott. Légy óvatos!","Dopo attente ricerche sul materiale che ho, ho stabilito che un oscuro e antico potere è nascosto lì. Fai attenzione!","俺の調査では、古代の災厄がそこに隠されている +という話だ。注意しろよ!","제가 연구를 좀 더 해봤는데, 그곳에서 사악한 고대의 기운이 솟아난다는군요. 조심하시길!",Mijn onderzoek suggereert dat daar een duistere kracht uit het oude verleden verborgen ligt. Wees voorzichtig!,Forskningen min tyder på at en mørk kraft fra fortiden er skjult der. Vær forsiktig!,"Moje badania sugerują, że ukryta jest tam jakaś mroczna moc z zamierzchłej przeszłości. Bądź ostrożny!",Minha pesquisa sugere que há algum poder sombrio do passado antigo escondido naquele lugar. Tome cuidado!,,Investigațiile mele indică faptul că ceva putere întunecată din trecutul antic e ascunsă acolo. Ai grijă!,"Судя по результатам исследования, какая-то тёмная сила из далёкого прошлого. Будь осторожен!",,Min forskning tyder på att någon mörk kraft från det forntida förflutna är gömd där. Var försiktig!,"Araştırmalarım, kadim geçmişten gelen karanlık bir gücün orada saklı olduğunu gösteriyor. Dikkatli ol!" +"That blue chalice, how'd you come by it? I've been researching the Order and their links to the distant past, and that artifact would help me. Let's make a deal. Give me the chalice, and I'll give you some info.",TXT_DLG_SCRIPT23_D21224_THATB,"SVE.WAD +MAP23: Timothy (Talking with him for the very first time with the chalice).",,,"Ten modrý kalich, jak jsi k němu přišel? Zkoumal jsem Řád a jeho pojítka k dávné minulosti a ten artefakt by mi pomohl. Udělejme dohodu: Ty mi dáš ten kalich a já ti dám nějaké informace.","Den blå bæger, hvordan er du kommet til den? Jeg har forsket i Ordenen og deres forbindelser til den fjerne fortid, og denne artefakt ville hjælpe mig. Lad os lave en aftale. Giv mig bægeret, og jeg giver dig nogle oplysninger.","Dieser blaue Kelch, wie bist du da ran gekommen? Ich habe bereits über den Orden und deren Verbindung zur fernen Vergangenheit recherchiert, und dieses Artefakt könnte mir weiterhelfen. Ich schlage dir etwas vor: Gib mir den Kelch und ich gebe dir Informationen.",,"Tiu blua kaliko, kiel vi trovis ĝin? Mi esploradis La Ordenon kaj ĝiajn rilatojn kun la fora pasinteco, kaj tiu artefakto helpus min. Ni intertraktu: donu al mi la kalikon kaj mi donos informojn al vi.","Ese cáliz azul, ¿de dónde lo has sacado? He estado investigando a La Orden y sus conexiones con el pasado lejano, y ese artefacto me serviría. Hagamos un trato: dame el cáliz y te daré algo de información.","Ese cáliz azul, ¿de dónde lo sacaste? He estado investigando a La Orden y sus conexiones con el pasado lejano, y ese artefacto me serviría. Hagamos un trato: dame el cáliz y te doy algo de información.","Tuo sininen uhrimalja, miten onnistuit saamaan sen? Olen tutkinut Veljeskuntaa ja sen kytköksiä kaukaiseen menneisyyteen, ja tuo esine auttaisi minua. Tehdäänpä kauppa: Sinä annat minulle maljan, ja minä annan sinulle tietoa.","Ce calice bleu, comment l'avez vous trouvé? Je fais des recherches sur l'Ordre et leurs liens avec le passé. Cet artéfact m'aiderait beaucoup. Faisons affaires: donnez le moi et je vous aiderai.","Hogyan sikerült megszerened azt a kék serleget? Kutattam a Rendet és kapcsolatukat a messzi múlttal, és ez az ereklye nagy segítség lenne. Kössünk üzletet. Add ide a serleget, és cserébe kapsz információt.","Quel calice blu, come lo hai trovato? Ho passato molto tempo a ricercare l'Ordine e i suoi legami con il lontano passato, e quell'artifatto mi aiuterebbe. Facciamo una cosa. Se mi dai il calice, io ti darò delle informazioni.","その青い聖杯はどうした? 私はオーダーの遥か過去の関係について調査 していた、その骨董品が手掛かりになりそうだ。 -取引しよう、聖杯をくれれば幾つか情報を渡す。","저 푸른 성배... 어떻게 찾으신 거죠? 오더와 그들의 과거를 좀 조사하던 참이었습니다. 저 보물만 있으면 아주 커다란 도움이 될 것입니다. 그 성배를 주신다면, 좋은 정보를 알려주겠습니다.","Die blauwe kelk, hoe kom je eraan? Ik heb de Orde en hun verbanden met het verre verleden onderzocht, en dat artefact zou me helpen. Laten we een deal sluiten. Geef me de kelk en ik zal je wat informatie geven.","Det blå begeret, hvordan fikk du tak i det? Jeg har forsket på Ordenen og deres forbindelser til en fjern fortid, og den gjenstanden kan hjelpe meg. La oss gjøre en avtale. Gi meg begeret, så gir jeg deg informasjon.","Ten niebieski kielich, skąd go masz? Badałem Zakon i ich powiązania z odległą przeszłością, a ten artefakt mógłby mi pomóc. Zawrzyjmy układ. Daj mi kielich, a ja dam ci trochę informacji.","Esse cálice azul, como você o encontrou? Estive pesquisando sobre a Ordem e o seu vínculo com o passado distante e esse artefato me ajudaria. Vamos fazer um trato. Me dê o cálice e eu te dou informações.",,"Acel potir albastru, cum l-ai găsit? Am cercetat Ordinul și legăturile lor cu trecutul, iar acel artefact mă poate ajuta. Să facem un târg, Îmi dai potirul, iar eu îți dau informații.","Эта синяя чаша... откуда она у тебя? Мои исследования Ордена связаны с событиями далёкого прошлого, и мне очень нужен этот артефакт. Давай заключим сделку: ты мне чашу, а я тебе — информацию.",,"O mavi kadehi nereden buldun? Tarikat'ı ve uzak geçmişle bağlantılarını araştırıyordum ve bu eser bana yardımcı olabilir. Bir anlaşma yapalım. Kadehi bana ver, ben de sana biraz bilgi vereyim." -"Take it, it's bad luck anyway.",TXT_RPLY0_SCRIPT23_D21224_TAKEI,,,,"Vem si ho, stejně přináší jen smůlu.","Tag den, den bringer alligevel uheld.","Nimm ihn, er bringt sowieso Unglück.",,,"Toma, de todos modos da mala suerte.",,"Ota se, epäonnenkalu se kuitenkin on.","Gardez le, je parie qu'il file malchance.","Vidd nyugodtan, rossz szerencsét hoz amúgyis.","Prendilo, tanto porta sfortuna.",渡そう、兎に角運が悪かった。,"값어치도 없을 것 같은데, 그냥 가져가세요.","Neem het, het is toch al pech.","Ta det, det bringer ulykke uansett.","Weź go, to i tak przynosi pecha.",Pode pegar. Isso atrai azar de qualquer forma.,,"Ia-l, poartă ghinion oricum.",Держи. Она всё равно приносит несчастье.,,"Al, zaten kötü şans getirir." -"Screw you, I'm keeping it.",TXT_RPLY1_SCRIPT23_D21224_SCREW,,,,"Jdi se vycpat, nechám si ho.","Rend mig, jeg beholder den.","Ach, was soll's. Ich behalte ihn.",,,"Que te zurzan, me lo quedo.","Al diablo, me lo quedo.","Vedä käteen, pidän sen itselläni.","Allez vous faire voir, il est à moi maintenant.","Nagy francot, inkább megtartom.",E invece me lo tengo!,ふざけるな、俺の物だ。,뭔 개소리야? 이제 이건 내 것이라고!,"Krijg de klere, ik hou hem.","Faen ta deg, jeg beholder det.","Wal się, zatrzymam go.","Vá se ferrar, ele é meu.",,"Du-te naibi, îl păstrez.",Пошёл ты! Я оставлю её себе.,,"Siktir git, bende kalacak." -Then I'm not giving you anything. Get lost!,TXT_RYES1_SCRIPT23_D21224_THENI,,,,Pak ti nic nedám. Zmizni!,Så giver jeg dig ikke noget. Forsvind!,Dann bekommst du auch nichts von mir. Verzieh dich!,,,Entonces no te voy a dar nada. ¡Piérdete!,,Sitten en anna sinulle mitään. Antaa vetää!,"Rien pour vous, alors, dégagez!",Akkor meg tudod mikor adok neked bármit is. Húzzál elfelé!,E allora non ti darò niente. Sparisci!,何もやるモンは無いぞ。失せな!,아주 좋은 기회를 다 날려버리시는군. 꺼져요!,Dan geef ik je niets. Donder op!,Da gir jeg deg ingenting. Forsvinn!,Więc nic ci nie dam. Spadaj!,Então não te darei nada. Se manda!,,Atunci nu îți dau nimic. Valea!,Тогда я тебе ничего не скажу. Убирайся!,,O zaman sana hiçbir şey vermiyorum. Kaybol! -"Now, what can I help you with?",TXT_DLG_SCRIPT23_D22740_NOWWH,,,,"Tak, s čím ti mohu pomoci?",Hvad kan jeg hjælpe dig med?,"Nun, wie kann ich dir weiterhelfen?",,,"Ahora, ¿En qué puedo ayudarte?",,"No niin, miten voin palvella?","Bon, que puis-je pour vous?",Akkor miben segíthetek?,"E ora, come posso aiutarti?",今手伝ってくれるか?,"그럼, 뭘 더 도와드릴까요?","Nu, waar kan ik je mee helpen?",Hva kan jeg hjelpe deg med?,"A teraz, w czym mogę ci pomóc?","Então, como posso ajudá-lo?",,"Acum, cu ce te pot ajuta?","Итак, чем я могу быть тебе полезен?",,"Şimdi, sana nasıl yardım edebilirim?" -Shadow armor?,TXT_RPLY0_SCRIPT23_D22740_SHADO,,,Shadow armour?,Stínové brnění?,Skygge rustning?,Schattenrüstung?,,,¿Armadura de sombra?,,Varjohaarniska?,Armure des ombres?,Árnyék vért?,Armatura Ombra?,シャドウアーマー?,그림자 갑옷?,Schaduw pantser?,Skyggepanser?,Zbroja cieni?,Armadura das sombras?,,Armura umbrei?,Теневой бронёй?,,Gölge zırhı mı? -"Ahh, to be heard, but not seen!",TXT_RYES0_SCRIPT23_D22740_AHHTO,,,,"Áha, být slyšen, ne viděn!","Ahh, at blive hørt, men ikke set!","Ah, um gehört zu werden, aber ungesehen zu bleiben.",,,"Ahh, ¡Para ser oído, pero no visto!",,"Aah, tulla kuulluksi, muttei nähdyksi!","Ah, pour se faire entendre, sans se faire voir!","Csak hallani, de nem látni.","Ahh, per essere sentiti, ma non visti!",ああ、声はすれど姿は見えず。,들켜도 당신을 계속 맞추진 못할 거요!,"Ahhh, om gehoord, maar niet gezien te worden!","Å bli hørt, men ikke sett!","Ahh, być słyszanym, ale nie widzianym!","Ahh, ser ouvido mas não ser visto!",,"Ahh, să fii auzit, dar nu văzut!","Ах, чтобы быть услышанным, но не увиденным!",,"Ahh, duyulmak ama görülmemek!" -"Get out of here, come back when you have some cash.",TXT_RNO0_SCRIPT23_D22740_GETOU,,,,"Vypadni a vrať se, když budeš mít peníze.","Forsvind herfra, og kom tilbage, når du har nogle penge.","Verzieh dich, komm wieder, wenn du etwas Geld hast.",,,"Vete de aquí, vuelve cuando tengas algo de efectivo.",,"Antaa vetää; tule takaisin, kun sinulla on käteistä.","Sortez de là, revenez quand vous avez de l'argent!","Na kotródj innen, csak akkor lássalak ha van nálad pénz is.","Fuori di qui, ritorna quando avrai del denaro.",ここを出て、稼いでからまた来てくれ!,이 유용한 도구를 공짜로 주기엔 영 그렇군요.,"Ga hier weg, kom terug als je wat geld hebt.","Kom deg ut herfra, og kom tilbake når du har penger.","Wynoś się stąd, wróć jak będziesz miał trochę kasy.",Vá embora daqui. Volte quando tiver dinheiro.,,"Cară-te, întoarce-te când ai bani.","Выметайся вон. Вернёшься, когда раздобудешь наличности.",,"Git buradan, biraz paran olduğunda geri gel." -"Thank Deus you got here. To enter the factory you need a key. We stole it but our agent is missing in the web of catacombs under the Order's stronghold. I have sent ten good men into those tunnels to find him, and none have returned. Something is down there!",TXT_DLG_SCRIPT23_D24256_THANK,,,,"Díky bohu, žes přišel. Aby ses dostal do továrny, potřebuješ klíč. Ten jsme ukradli, ale náš agent se ztratil v sítí katakomb pod pevností Řádu. Poslal jsem do těch tunelů deset dobrých mužů a žádný se nevrátil. Něco tam dole je!","Tak Deus for at du kom her. For at komme ind på fabrikken skal du bruge en nøgle. Vi stjal den, men vores agent er forsvundet i katakomberne under ordenens højborg. Jeg har sendt ti gode mænd ned i disse tunneller for at finde ham, men ingen er vendt tilbage. Der er noget dernede!","Deus sei dank bist du hier. Um die Fabrik zu betreten, brauchst du einen Schlüssel. Wir haben ihn gestohlen, aber unser Agent ist in den Irrwegen der Katakomben unter Festung des Ordens verschwunden. Ich habe zehn gute Männer da hinunter geschickt um ihn zu finden, aber niemand ist zurückgekehrt. Irgendetwas ist da unten!",,,"Gracias a deus que estás aquí. Para entrar en la fábrica necesitas una llave. La robamos, pero nuestro agente está perdido en la red de catacumbas debajo de la fortaleza de la Orden. He enviado diez buenos hombres a esos túneles para encontrarlo, y ninguno ha regresado. ¡Hay algo ahí abajo!",,"Luojan kiitos, että selvisit perille. Päästäksesi sisälle tehtaaseen tarvitset avaimen. Varastimme sen, mutta vakoojamme on eksynyt Veljeskunnan linnakkeen alapuolella sijaitsevaan katakombiverkostoon. Olen lähettänyt tunneleihin 10 kelpoa miestä etsimään häntä, eikä kukaan ole palannut. Jokin on siellä alla!","Merci Dieu, vous êtes là. Pour entrer dans l'usine, il vous faut une clé. On l'a volé, mais notre agent a disparu dans le dédale de catacombes sous la forteresse de l'Ordre. On a envoyé dix hommes dans ces tunnels pour le retrouver mais personne n'est revenu. Il doit y avoir quelque chose, là dedans!","Hála Deusnak, ideértél.Ahhoz, hogy bejuthass a gyárba kell majd egy kulcs. Habár sikerült ellopnunk a kulcsot, az ügynökünk elveszett a katakombák sűrűjében a Rend erődítménye alatt. Leküldtem tíz jó emberemet utána, de egyikük sem tért vissza. Valami borzasztó lehet ott lent!","Grazie a Dio sei arrivato. Per entrare nella fabbrica ti servirà una chiave. L'abbiamo rubata ma l'agente che l'ha presa è sparito nelle catacombe sotto la fortezza dell'Ordine. Ho mandato dieci uomini in quei tunnel a trovarlo, e nessuno è ritornato. C'è qualcosa là sotto!","ようやく来てくれたか。 +取引しよう、聖杯をくれれば幾つか情報を渡す。","저 푸른 성배... 어떻게 찾으신 거죠? 오더와 그들의 과거를 좀 조사하던 참이었습니다. 저 보물만 있으면 아주 커다란 도움이 될 것입니다. 그 성배를 주신다면, 좋은 정보를 알려주겠습니다.","Die blauwe kelk, hoe kom je eraan? Ik heb de Orde en hun verbanden met het verre verleden onderzocht, en dat artefact zou me helpen. Laten we een deal sluiten. Geef me de kelk en ik zal je wat informatie geven.","Det blå begeret, hvordan fikk du tak i det? Jeg har forsket på Ordenen og deres forbindelser til en fjern fortid, og den gjenstanden kan hjelpe meg. La oss gjøre en avtale. Gi meg begeret, så gir jeg deg informasjon.","Ten niebieski kielich, skąd go masz? Badałem Zakon i ich powiązania z odległą przeszłością, a ten artefakt mógłby mi pomóc. Zawrzyjmy układ. Daj mi kielich, a ja dam ci trochę informacji.","Esse cálice azul, como você o encontrou? Estive pesquisando sobre a Ordem e o seu vínculo com o passado distante e esse artefato me ajudaria. Vamos fazer um trato. Me dê o cálice e eu te dou informações.",,"Acel potir albastru, cum l-ai găsit? Am cercetat Ordinul și legăturile lor cu trecutul, iar acel artefact mă poate ajuta. Să facem un târg, Îmi dai potirul, iar eu îți dau informații.","Эта синяя чаша... откуда она у тебя? Мои исследования Ордена связаны с событиями далёкого прошлого, и мне очень нужен этот артефакт. Давай заключим сделку: ты мне чашу, а я тебе — информацию.",,"Den blå kalken, hur kom du över den? Jag har forskat om orden och deras kopplingar till det förflutna, och den artefakten skulle hjälpa mig. Låt oss göra en överenskommelse. Ge mig bägaren, så ger jag dig lite information.","O mavi kadehi nereden buldun? Tarikat'ı ve uzak geçmişle bağlantılarını araştırıyordum ve bu eser bana yardımcı olabilir. Bir anlaşma yapalım. Kadehi bana ver, ben de sana biraz bilgi vereyim." +"Take it, it's bad luck anyway.",TXT_RPLY0_SCRIPT23_D21224_TAKEI,〃,,,"Vem si ho, stejně přináší jen smůlu.","Tag den, den bringer alligevel uheld.","Nimm ihn, er bringt sowieso Unglück.",,"Havu, ĝi alportas misfortunon.","Toma, de todos modos da mala suerte.",,"Ota se, epäonnenkalu se kuitenkin on.","Gardez le, je parie qu'il file malchance.","Vidd nyugodtan, rossz szerencsét hoz amúgyis.","Prendilo, tanto porta sfortuna.",渡そう、兎に角運が悪かった。,"값어치도 없을 것 같은데, 그냥 가져가세요.","Neem het, het is toch al pech.","Ta det, det bringer ulykke uansett.","Weź go, to i tak przynosi pecha.",Pode pegar. Isso atrai azar de qualquer forma.,,"Ia-l, poartă ghinion oricum.",Держи. Она всё равно приносит несчастье.,,"Ta den, den betyder ändå otur.","Al, zaten kötü şans getirir." +"Screw you, I'm keeping it.",TXT_RPLY1_SCRIPT23_D21224_SCREW,〃,,,"Jdi se vycpat, nechám si ho.","Rend mig, jeg beholder den.","Ach, was soll's. Ich behalte ihn.",,"Al la diablo, mi konservos ĝin.","Que te zurzan, me lo quedo.","Al diablo, me lo quedo.","Vedä käteen, pidän sen itselläni.","Allez vous faire voir, il est à moi maintenant.","Nagy francot, inkább megtartom.",E invece me lo tengo!,ふざけるな、俺の物だ。,뭔 개소리야? 이제 이건 내 것이라고!,"Krijg de klere, ik hou hem.","Faen ta deg, jeg beholder det.","Wal się, zatrzymam go.","Vá se ferrar, ele é meu.",,"Du-te naibi, îl păstrez.",Пошёл ты! Я оставлю её себе.,,"Dra åt helvete, jag behåller den.","Siktir git, bende kalacak." +Then I'm not giving you anything. Get lost!,TXT_RYES1_SCRIPT23_D21224_THENI,〃,,,Pak ti nic nedám. Zmizni!,Så giver jeg dig ikke noget. Forsvind!,Dann bekommst du auch nichts von mir. Verzieh dich!,,"Tiuokaze mi donos +nenion al vi. Foriru!","Entonces +no te doy nada. ¡Vete!",,Sitten en anna sinulle mitään. Antaa vetää!,"Rien pour vous, alors, dégagez!",Akkor meg tudod mikor adok neked bármit is. Húzzál elfelé!,E allora non ti darò niente. Sparisci!,何もやるモンは無いぞ。失せな!,아주 좋은 기회를 다 날려버리시는군. 꺼져요!,Dan geef ik je niets. Donder op!,Da gir jeg deg ingenting. Forsvinn!,Więc nic ci nie dam. Spadaj!,Então não te darei nada. Se manda!,,Atunci nu îți dau nimic. Valea!,Тогда я тебе ничего не скажу. Убирайся!,,Då ger jag dig ingenting. Försvinn!,O zaman sana hiçbir şey vermiyorum. Kaybol! +"Now, what can I help you with?",TXT_DLG_SCRIPT23_D22740_NOWWH,"SVE.WAD +MAP23: Tevick.",,,"Tak, s čím ti mohu pomoci?",Hvad kan jeg hjælpe dig med?,"Nun, wie kann ich dir weiterhelfen?",,"Nu, kion mi povas doni al vi?","Y bueno, ¿en qué puedo ayudarte?",,"No niin, miten voin palvella?","Bon, que puis-je pour vous?",Akkor miben segíthetek?,"E ora, come posso aiutarti?",今手伝ってくれるか?,"그럼, 뭘 더 도와드릴까요?","Nu, waar kan ik je mee helpen?",Hva kan jeg hjelpe deg med?,"A teraz, w czym mogę ci pomóc?","Então, como posso ajudá-lo?",,"Acum, cu ce te pot ajuta?","Итак, чем я могу быть тебе полезен?",,Vad kan jag hjälpa dig med?,"Şimdi, sana nasıl yardım edebilirim?" +Shadow armor?,TXT_RPLY0_SCRIPT23_D22740_SHADO,〃,,Shadow armour?,Stínové brnění?,Skygge rustning?,Schattenrüstung?,,Ĉu ombran armaĵon?,¿Armadura de sombra?,,Varjohaarniska?,Armure des ombres?,Árnyék vért?,Armatura Ombra?,シャドウアーマー?,그림자 갑옷?,Schaduw pantser?,Skyggepanser?,Zbroja cieni?,Armadura das sombras?,,Armura umbrei?,Теневой бронёй?,,Skuggarmering?,Gölge zırhı mı? +"Ahh, to be heard, but not seen!",TXT_RYES0_SCRIPT23_D22740_AHHTO,〃,,,"Áha, být slyšen, ne viděn!","Ahh, at blive hørt, men ikke set!","Ah, um gehört zu werden, aber ungesehen zu bleiben.",,"Ha, por esti aŭdata, +sed ne vidata!","Ah, ¡para ser oído, +pero no visto!",,"Aah, tulla kuulluksi, muttei nähdyksi!","Ah, pour se faire entendre, sans se faire voir!","Csak hallani, de nem látni.","Ahh, per essere sentiti, ma non visti!",ああ、声はすれど姿は見えず。,들켜도 당신을 계속 맞추진 못할 거요!,"Ahhh, om gehoord, maar niet gezien te worden!","Å bli hørt, men ikke sett!","Ahh, być słyszanym, ale nie widzianym!","Ahh, ser ouvido mas não ser visto!",,"Ahh, să fii auzit, dar nu văzut!","Ах, чтобы быть услышанным, но не увиденным!",,"Ahh, att höras men inte ses!","Ahh, duyulmak ama görülmemek!" +"Get out of here, come back when you have some cash.",TXT_RNO0_SCRIPT23_D22740_GETOU,〃,,,"Vypadni a vrať se, když budeš mít peníze.","Forsvind herfra, og kom tilbage, når du har nogle penge.","Verzieh dich, komm wieder, wenn du etwas Geld hast.",,"Foriru. Revenu kiam +vi havos monon.","Vete. Vuelve cuando +tengas efectivo.",,"Antaa vetää; tule takaisin, kun sinulla on käteistä.","Sortez de là, revenez quand vous avez de l'argent!","Na kotródj innen, csak akkor lássalak ha van nálad pénz is.","Fuori di qui, ritorna quando avrai del denaro.",ここを出て、稼いでからまた来てくれ!,이 유용한 도구를 공짜로 주기엔 영 그렇군요.,"Ga hier weg, kom terug als je wat geld hebt.","Kom deg ut herfra, og kom tilbake når du har penger.","Wynoś się stąd, wróć jak będziesz miał trochę kasy.",Vá embora daqui. Volte quando tiver dinheiro.,,"Cară-te, întoarce-te când ai bani.","Выметайся вон. Вернёшься, когда раздобудешь наличности.",,Stick härifrån och kom tillbaka när du har pengar.,"Git buradan, biraz paran olduğunda geri gel." +"Thank Deus you got here. To enter the factory you need a key. We stole it but our agent is missing in the web of catacombs under the Order's stronghold. I have sent ten good men into those tunnels to find him, and none have returned. Something is down there!",TXT_DLG_SCRIPT23_D24256_THANK,"SVE.WAD +MAP23: Richter.",,,"Díky bohu, žes přišel. Aby ses dostal do továrny, potřebuješ klíč. Ten jsme ukradli, ale náš agent se ztratil v sítí katakomb pod pevností Řádu. Poslal jsem do těch tunelů deset dobrých mužů a žádný se nevrátil. Něco tam dole je!","Tak Deus for at du kom her. For at komme ind på fabrikken skal du bruge en nøgle. Vi stjal den, men vores agent er forsvundet i katakomberne under ordenens højborg. Jeg har sendt ti gode mænd ned i disse tunneller for at finde ham, men ingen er vendt tilbage. Der er noget dernede!","Deus sei dank bist du hier. Um die Fabrik zu betreten, brauchst du einen Schlüssel. Wir haben ihn gestohlen, aber unser Agent ist in den Irrwegen der Katakomben unter Festung des Ordens verschwunden. Ich habe zehn gute Männer da hinunter geschickt um ihn zu finden, aber niemand ist zurückgekehrt. Irgendetwas ist da unten!",,"Danke al Dio vi alvenis. Ŝlosilo estas necesa por eniri la fabrikon; ni ŝtelis ĝin, sed nia agento estas perdita en la katakomba sistemo sub la fortreso de La Ordeno. Mi sendis dek bonajn virojn al tiuj tuneloj por serĉi lin kaj neniu revenis. Estas io tie malsupre!","Gracias a Dios, has llegado. Para entrar en la fábrica se necesita una llave; la hemos rodado, pero nuestro agente está perdido en la red de catacumbas debajo de la fortaleza de La Orden. He enviado a diez buenos hombres a esos túneles a buscarlo y ninguno ha regresado. ¡Hay algo ahí abajo!","Gracias a Dios, llegaste. Para entrar a la fábrica se necesita una llave; la robamos, pero nuestro agente está perdido en la red de catacumbas debajo de la fortaleza de La Orden. Mandé a diez buenos hombres a esos túneles a buscarlo y ninguno volvió. ¡Hay algo ahí abajo!","Luojan kiitos, että selvisit perille. Päästäksesi sisälle tehtaaseen tarvitset avaimen. Varastimme sen, mutta vakoojamme on eksynyt Veljeskunnan linnakkeen alapuolella sijaitsevaan katakombiverkostoon. Olen lähettänyt tunneleihin 10 kelpoa miestä etsimään häntä, eikä kukaan ole palannut. Jokin on siellä alla!","Merci Dieu, vous êtes là. Pour entrer dans l'usine, il vous faut une clé. On l'a volé, mais notre agent a disparu dans le dédale de catacombes sous la forteresse de l'Ordre. On a envoyé dix hommes dans ces tunnels pour le retrouver mais personne n'est revenu. Il doit y avoir quelque chose, là dedans!","Hála Deusnak, ideértél.Ahhoz, hogy bejuthass a gyárba kell majd egy kulcs. Habár sikerült ellopnunk a kulcsot, az ügynökünk elveszett a katakombák sűrűjében a Rend erődítménye alatt. Leküldtem tíz jó emberemet utána, de egyikük sem tért vissza. Valami borzasztó lehet ott lent!","Grazie a Dio sei arrivato. Per entrare nella fabbrica ti servirà una chiave. L'abbiamo rubata ma l'agente che l'ha presa è sparito nelle catacombe sotto la fortezza dell'Ordine. Ho mandato dieci uomini in quei tunnel a trovarlo, e nessuno è ritornato. C'è qualcosa là sotto!","ようやく来てくれたか。 工場に入るためには鍵が必要だ。 鍵は盗んだのだが、我々の密偵が砦地下にある 地下墓所で行方不明になった。 彼を探すため10名派遣したのだが、 誰一人帰ってこなかった。 -地下墓地で何か異変が起こっているに違いない。","데우스님 감사합니다, 지원군이 왔군! 공장에 들어가려면 열쇠가 필요합니다. 그 열쇠를 가진 한 요원이 오더의 요새가 있는 고대 무덤에서 길을 잃었습니다. 지원군 10 명을 보내긴 했으나 돌아오지 못했습니다. 그곳에 무언가가 있는 것 같아요!","Bedankt deus dat je hier bent gekomen. Om de fabriek binnen te komen heb je een sleutel nodig. We hebben het gestolen maar onze agent ontbreekt in het web van de catacomben onder het bolwerk van de Orde. Ik heb tien goede mannen in die tunnels gestuurd om hem te vinden, en niemand is teruggekomen. Er is daar beneden iets!","Takk Gud for at du kom hit. For å komme inn i fabrikken trenger du en nøkkel. Vi stjal den, men agenten vår er forsvunnet i katakombene under Ordenens festning. Jeg har sendt ti gode menn ned i tunnelene for å finne ham, men ingen har kommet tilbake. Det er noe der nede!","Dzięki Deusowi, że tu trafiłeś. Aby wejść do fabryki potrzebny jest klucz. Ukradliśmy go, ale nasz agent zaginął w sieci katakumb pod twierdzą Zakonu. Wysłałem dziesięciu dobrych ludzi do tych tuneli, by go znaleźli, ale żaden nie wrócił. Coś jest tam na dole!",Graças a Deus que você está aqui. Para entrar na fábrica você precisa de uma chave. Nós a roubamos mas nosso agente desapareceu na rede de catacumbas debaixo da fortaleza da Ordem. Mandei dez homens capazes pra dentro desses túneis para encontrá-lo e ninguém retornou. Tem alguma coisa lá embaixo!,,"Slavă Domnului că ești aici. Ca să intri în fabrică ai nevoie de o cheie. Am furat-o dar agentul nostru a dispărut în rețeaua catacombelor fortăreței Ordinului. Am trimis zece oameni pricepuți după el, dar niciunul nu s-a întors. Ceva se întâmplă acolo!","Хвала господу, ты добрался сюда. Тебе нужен ключ, чтобы проникнуть на фабрику. Мы выкрали его, но наш агент пропал в сети катакомб под крепостью Ордена. Чтобы разыскать его, я послал в эти туннели десять хороших бойцов, и ни один не вернулся. Там внизу что-то есть!",,Buraya geldiğin için Deus'a şükret. Fabrikaya girmek için bir anahtara ihtiyacınız var. Onu çaldık ama ajanımız Tarikat'ın kalesinin altındaki yeraltı mezarlarında kayıp. Onu bulmaları için o tünellere on iyi adam gönderdim ama hiçbiri geri dönmedi. Aşağıda bir şey var! -What is it? Human or... ?,TXT_RPLY0_SCRIPT23_D24256_WHATI,,,,"Co to je? Člověk, nebo...?",Hvad er det? Menneske eller... ?,Was ist es? Mensch oder...?,,,¿Qué es? ¿Humano ó...?,,Mikä se on? Ihminen vai...,"Qu'est-ce que c'est? Un humain, où...",Mi lehet? Ember vagy...?,Che cosa è? Umano o... ?,それは一体?人間か...?,이게 뭐지? 사람? 아니면... ?,Wat is het? Menselijk of.... ?,Hva er det? Menneskelig eller... ?,Co to jest? Człowiek czy... ?,O que é? É humano ou... ?,,Ce e? Uman sau... ?,Что это? Человек или...?,,Ne var orada? İnsan mı yoksa... ? -"Not. Definitely not. Whatever it is, you must fight it to retrieve the key. I'll open the catacombs' entrance. When you've got it, the factory is next to the mines. Hurry, each second counts.",TXT_DLG_SCRIPT23_D25772_NOTDE,,,,"Ne. Rozhodně ne. Ať je to cokoliv, musíš se s tím utkat, abys získal ten klíč zpět. Otevřu ti vchod do katakomb. Až ho budeš mít, továrna je vedle dolů. Pospěš si, každá vteřina se počítá.","Nej. Helt sikkert ikke. Uanset hvad det er, skal du kæmpe mod det for at få nøglen tilbage. Jeg åbner katakombernes indgang. Når du har fået den, er fabrikken ved siden af minerne. Skynd dig, hvert sekund tæller.","Nein. Definitiv nicht. Was auch immer es ist, du musst es bekämpfen, um an den Schlüssel zu kommen. Ich werde den Eingang zu den Katakomben öffnen. Wenn du ihn hast, die Fabrik ist direkt neben den Minen. Beeil dich, jede Sekunde zählt.",,,"No. Definitivamente no. Sea lo que sea, debes luchar contra eso para recuperar la llave. Abriré la entrada a las catacumbas. Cuando la tengas, la fábrica está junto a las minas. Date prisa, cada segundo cuenta.",,"Ei, ei varmana. Mikä ikinä se onkaan, sinun on kohdattava se noutaaksesi avaimen. Avaan katakombien sisäänkäynnin. Kun se on hallussasi, tehdas on kaivoksen vieressä. Pidä kiirettä, jokainen sekunti merkitsee.","Non, absolument pas. Je ne sais pas ce que c'est, mais il faudra s'en débarasser pour récupérer la clé. Je vais ouvrir l'entrée des catacombes. Quand vous êtes à l'intérieur, l'usine est près des ruines. Vite, chaque seconde compte.","Nem. Biztos, hogy nem. Akármi is az, meg kell majd küzdened vele a kulcsért. Kinyitom a katakomba bejáratát. Ha megszerezted, a gyár ott lesz a bánya mellett. Siess, minden másodperc számít.","No. Sicuramente no. Qualsiasi cosa sia, dovrai lottare per riavere la chiave. Adesso aprirò l'entrata per le catacombe. Quando avrai ripreso la chiave, potrai accedere alla fabbrica, che si trova accanto alle miniere. Sbrigati, ogni secondo può fare la differenza.","いや。人間の仕業だとはとても思えない。 +地下墓地で何か異変が起こっているに違いない。","데우스님 감사합니다, 지원군이 왔군! 공장에 들어가려면 열쇠가 필요합니다. 그 열쇠를 가진 한 요원이 오더의 요새가 있는 고대 무덤에서 길을 잃었습니다. 지원군 10 명을 보내긴 했으나 돌아오지 못했습니다. 그곳에 무언가가 있는 것 같아요!","Bedankt deus dat je hier bent gekomen. Om de fabriek binnen te komen heb je een sleutel nodig. We hebben het gestolen maar onze agent ontbreekt in het web van de catacomben onder het bolwerk van de Orde. Ik heb tien goede mannen in die tunnels gestuurd om hem te vinden, en niemand is teruggekomen. Er is daar beneden iets!","Takk Gud for at du kom hit. For å komme inn i fabrikken trenger du en nøkkel. Vi stjal den, men agenten vår er forsvunnet i katakombene under Ordenens festning. Jeg har sendt ti gode menn ned i tunnelene for å finne ham, men ingen har kommet tilbake. Det er noe der nede!","Dzięki Deusowi, że tu trafiłeś. Aby wejść do fabryki potrzebny jest klucz. Ukradliśmy go, ale nasz agent zaginął w sieci katakumb pod twierdzą Zakonu. Wysłałem dziesięciu dobrych ludzi do tych tuneli, by go znaleźli, ale żaden nie wrócił. Coś jest tam na dole!",Graças a Deus que você está aqui. Para entrar na fábrica você precisa de uma chave. Nós a roubamos mas nosso agente desapareceu na rede de catacumbas debaixo da fortaleza da Ordem. Mandei dez homens capazes pra dentro desses túneis para encontrá-lo e ninguém retornou. Tem alguma coisa lá embaixo!,,"Slavă Domnului că ești aici. Ca să intri în fabrică ai nevoie de o cheie. Am furat-o dar agentul nostru a dispărut în rețeaua catacombelor fortăreței Ordinului. Am trimis zece oameni pricepuți după el, dar niciunul nu s-a întors. Ceva se întâmplă acolo!","Хвала господу, ты добрался сюда. Тебе нужен ключ, чтобы проникнуть на фабрику. Мы выкрали его, но наш агент пропал в сети катакомб под крепостью Ордена. Чтобы разыскать его, я послал в эти туннели десять хороших бойцов, и ни один не вернулся. Там внизу что-то есть!",,"Tacka Deus för att du kom hit. För att komma in i fabriken behöver du en nyckel. Vi stal den, men vår agent saknas i katakomberna under Ordensfästet. Jag har skickat tio goda män in i tunnlarna för att hitta honom, men ingen har återvänt. Något finns där nere!",Buraya geldiğin için Deus'a şükret. Fabrikaya girmek için bir anahtara ihtiyacınız var. Onu çaldık ama ajanımız Tarikat'ın kalesinin altındaki yeraltı mezarlarında kayıp. Onu bulmaları için o tünellere on iyi adam gönderdim ama hiçbiri geri dönmedi. Aşağıda bir şey var! +What is it? Human or... ?,TXT_RPLY0_SCRIPT23_D24256_WHATI,〃,,,"Co to je? Člověk, nebo...?",Hvad er det? Menneske eller... ?,Was ist es? Mensch oder...?,,Kia ĝi estas? Ĉu homa aŭ...?,"¿Qué es?, ¿humano o...?",,Mikä se on? Ihminen vai...,"Qu'est-ce que c'est? Un humain, où...",Mi lehet? Ember vagy...?,Che cosa è? Umano o... ?,それは一体?人間か...?,이게 뭐지? 사람? 아니면... ?,Wat is het? Menselijk of.... ?,Hva er det? Menneskelig eller... ?,Co to jest? Człowiek czy... ?,O que é? É humano ou... ?,,Ce e? Uman sau... ?,Что это? Человек или...?,,Vad är det? Människor eller... ?,Ne var orada? İnsan mı yoksa... ? +"Not. Definitely not. Whatever it is, you must fight it to retrieve the key. I'll open the catacombs' entrance. When you've got it, the factory is next to the mines. Hurry, each second counts.",TXT_DLG_SCRIPT23_D25772_NOTDE,〃,,,"Ne. Rozhodně ne. Ať je to cokoliv, musíš se s tím utkat, abys získal ten klíč zpět. Otevřu ti vchod do katakomb. Až ho budeš mít, továrna je vedle dolů. Pospěš si, každá vteřina se počítá.","Nej. Helt sikkert ikke. Uanset hvad det er, skal du kæmpe mod det for at få nøglen tilbage. Jeg åbner katakombernes indgang. Når du har fået den, er fabrikken ved siden af minerne. Skynd dig, hvert sekund tæller.","Nein. Definitiv nicht. Was auch immer es ist, du musst es bekämpfen, um an den Schlüssel zu kommen. Ich werde den Eingang zu den Katakomben öffnen. Wenn du ihn hast, die Fabrik ist direkt neben den Minen. Beeil dich, jede Sekunde zählt.",,"Ne, neniel. Tio ajn, kio ĝi estas, vi devas batali kontraŭ ĝi por rekuperi la ŝlosilon. Farinte tion, la fabriko estas flanke de la minejo. Hastu, ĉiu sekundo estas gravega.","No, definitivamente no. Sea lo que sea, debes pelear contra eso para recuperar la llave; abriré la entrada a las catacumbas. Cuando la tengas, la fábrica está junto a la mina. Date prisa, que cada segundo cuenta.","No, definitivamente no. Sea lo que sea, debes pelear contra eso para recuperar la llave; voy a abrir la entrada a las catacumbas. Cuando la tengas, la fábrica está junto a la mina. Apúrate, que cada segundo cuenta.","Ei, ei varmana. Mikä ikinä se onkaan, sinun on kohdattava se noutaaksesi avaimen. Avaan katakombien sisäänkäynnin. Kun se on hallussasi, tehdas on kaivoksen vieressä. Pidä kiirettä, jokainen sekunti merkitsee.","Non, absolument pas. Je ne sais pas ce que c'est, mais il faudra s'en débarasser pour récupérer la clé. Je vais ouvrir l'entrée des catacombes. Quand vous êtes à l'intérieur, l'usine est près des ruines. Vite, chaque seconde compte.","Nem. Biztos, hogy nem. Akármi is az, meg kell majd küzdened vele a kulcsért. Kinyitom a katakomba bejáratát. Ha megszerezted, a gyár ott lesz a bánya mellett. Siess, minden másodperc számít.","No. Sicuramente no. Qualsiasi cosa sia, dovrai lottare per riavere la chiave. Adesso aprirò l'entrata per le catacombe. Quando avrai ripreso la chiave, potrai accedere alla fabbrica, che si trova accanto alle miniere. Sbrigati, ogni secondo può fare la differenza.","いや。人間の仕業だとはとても思えない。 それが何であれ君は鍵を取り戻せ。 地下墓所への入り口は開けておこう。 鍵を手に入れたら、工場は採掘所の隣にある。 -時間はあまり無いから急ぐのだ。","아냐. 사람 같은 건 절대로 아니라고. 그게 무엇이든, 당신은 어떻게든 싸워서 열쇠를 돌려받아야 합니다. 고대 무덤의 입구를 열어두겠습니다. 만약 열쇠를 얻으셨다면, 광산 옆에 있는 공장으로 향하시길 바랍니다. 시간이 얼마 남지 않았습니다!","Niet. Zeker niet. Wat het ook is, je moet ertegen vechten om de sleutel terug te krijgen. Ik zal de ingang van de catacomben openen. Als je hem hebt, staat de fabriek naast de mijnen. Schiet op, elke seconde telt.","Nei. Definitivt ikke. Uansett hva det er, må du kjempe mot det for å få tak i nøkkelen. Jeg åpner inngangen til katakombene. Når du har den, er fabrikken ved siden av gruvene. Skynd deg, hvert sekund teller.","Nie. Zdecydowanie nie. Cokolwiek to jest, musisz z tym walczyć, aby odzyskać klucz. Ja otworzę wejście do katakumb. Gdy go zdobędziesz, fabryka jest obok kopalni. Spiesz się, liczy się każda sekunda.","Não. Definitivamente não é. Seja lá o que for, você deve enfrentá-lo para recuperar a chave. Vou abrir a entrada das catacumbas. Quando você pegar a chave, vá para a fábrica próxima às minas. Depressa, cada segundo é importante.",,"Nu. Cu siguranță nu. Orice ar fi, va trebui să o înfrunți pentru a recupera cheia. Voi deschide intrarea catacombelor. Când o ai, fabrica e vizavi de mine. Grăbește-te, orice secundă contează.","Нет. Определённо нет. Что бы это ни было, ты должен сразиться с ним, чтобы заполучить ключ. Я открою вход в катакомбы. Когда добудешь его, направляйся на фабрику: она находится рядом со входом в шахты. Торопись! Дорога каждая секунда!",,"İnsan değil. Kesinlikle değil. O her neyse, anahtarı almak için onunla savaşmalısın. Yeraltı mezarlarının girişini açacağım. Anahtarı aldığında, fabrika madenlerin yanında. Acele et, her saniye önemli." -"Something inhuman, eh?, great.",TXT_RPLY0_SCRIPT23_D25772_SOMET,,,,"Něco nelidského, co? Skvělý.","Noget umenneskeligt, hva'?, fantastisk.",Irgendetwas unmenschliches? Na großartig.,,,"Algo inhumano, ¿eh? Genial.",,"Jotain epäinhimillistä, vai? Hienoa.","Quelque chose d'inhumain, hein? Parfait.","Valami nem emberi, mi? Csodás.","Qualcosa di inumano, eh? Fantastico.",非人道的な何か?流石だな。,비인간적인 녀석인가요? 좋군요.,"Iets onmenselijks, eh?, geweldig.","Noe umenneskelig, hva? Flott!","Coś nieludzkiego, ech, świetnie.","Algo não-humano, é? Que ótimo.",,"Ceva inuman, ei? Grozav.",Что-то иное? Просто отлично.,,"İnsanlık dışı bir şey, ha? Harika." -You're wasting time and lives! Move!,TXT_DLG_SCRIPT23_D27288_YOURE,,,,Plýtváš časem i životy! Jdi!,Du spilder tid og liv! Af sted!,Du verschwendest Zeit und Leben! Beweg dich!,,,¡Estás perdiendo tiempo y vidas! ¡Muévete!,,Haaskaat aikaa ja henkiä! Liikkuu jo!,Vous perdez votre temps et des vies! Bougez!,Időt és életeket pazarolsz! Mozgás!,"Stai sprecando tempo, e vite. Sbrigati!","こうしてる間にも君は時間と人命を -無駄にしている。行け!",시간과 생명이 위협받고 있다고! 서두르세요!!,Je verspilt tijd en levens! Vooruit!,Du kaster bort tid og liv! Skynd dere!,Marnujesz czas i życie! Ruszać się!,Você está desperdiçando tempo e vidas! Ande logo!,,"Pierzi timp și vieți, mișcă-te!",Ты тратишь время и жизни! Вперёд!,,Zamanınızı ve hayatlarınızı boşa harcıyorsunuz! Çekilin! -"The master doesn't like visitors. He likes all of his work to remain undisturbed. I've got to go get fresh parts from the storage room. I think he said a leg and an arm. Oh, well no time to talk anymore. I'd leave before he finds you.",TXT_DLG_SCRIPT27_D0_THEMA,,,,"Pán nemá rád návštěvy. Má rád, když ho nic neruší od práce. Musím dojít pro čerstvé části ze skladu. Myslím, že chtěl nohu a ruku. Tak, na mluvení není čas. Být tebou, odešel bych dřív, než tě najde.","Mesteren kan ikke lide besøgende. Han kan lide, at alt hans arbejde forbliver uforstyrret. Jeg skal hente nye dele fra lagerrummet. Jeg tror, han sagde et ben og en arm. Nå, men vi har ikke tid til at snakke mere. Jeg ville gå, før han finder dig.","Der Meister mag keine Besucher. Er hat es gern, wenn er bei der Arbeit nicht gestört wird. Ich muss gehen und neue Teile aus dem Lagerraum holen. Ich glaube er sagte ein Bein und eine Arm. Naja, keine Zeit mehr zum Reden. Du solltest gehen, bevor er dich findet.",,,"Al maestro no le gustan las visitas. Le gusta que su trabajo permanezca ininterrumpido. Tengo que ir a recoger partes frescas del almacén. Creo que dijo una pierna y un brazo. Ah, bueno, no hay tiempo para hablar. Yo me iría antes de que te encuentre.",,"Mestari ei pidä vieraista. Hän haluaa kaikkien töittensä säilyä koskemattomina. Minun on mentävä noutamaan tuoreita osia varastosta. Hän taisi puhua jalasta ja käsivarresta. No, ei enempää aikaa puhua. Sinuna lähtisin, ennen kuin hän löytää sinut.","Le Maître n'aime pas les visiteurs. Il préfère que son travail se déroule dans le calme. Il faut que j'aille chercher des pièces dans la salle de stockage. Il m'a demandé une jambe et un bras, je crois. Bon, plus de temps pour parler. Je partirais si j'étais vous.","A gazda nem szereti a látogatókat. Úgy szereti, ha nem zavarja senki a munkájában. Mennem kell új darabokért a tárolóba. Azt hiszem egy lábat és egy kart említett. Hát, sajnos nincs időm beszélgetni már. A helyedben elmennék, mielőtt megtalál.","Al padrone non piacciono i visitatori. Vuole che tutto il suo lavoro rimanga indisturbato. Ho qua le parti nuove dal magazzino. Mi pare abbia detto una gamba e un braccio. Ah, non ho più tempo per parlare. Io me ne andrei prima che si accorga che tu sei qui.","マスターは訪問者ヲ嫌っている。 +時間はあまり無いから急ぐのだ。","아냐. 사람 같은 건 절대로 아니라고. 그게 무엇이든, 당신은 어떻게든 싸워서 열쇠를 돌려받아야 합니다. 고대 무덤의 입구를 열어두겠습니다. 만약 열쇠를 얻으셨다면, 광산 옆에 있는 공장으로 향하시길 바랍니다. 시간이 얼마 남지 않았습니다!","Niet. Zeker niet. Wat het ook is, je moet ertegen vechten om de sleutel terug te krijgen. Ik zal de ingang van de catacomben openen. Als je hem hebt, staat de fabriek naast de mijnen. Schiet op, elke seconde telt.","Nei. Definitivt ikke. Uansett hva det er, må du kjempe mot det for å få tak i nøkkelen. Jeg åpner inngangen til katakombene. Når du har den, er fabrikken ved siden av gruvene. Skynd deg, hvert sekund teller.","Nie. Zdecydowanie nie. Cokolwiek to jest, musisz z tym walczyć, aby odzyskać klucz. Ja otworzę wejście do katakumb. Gdy go zdobędziesz, fabryka jest obok kopalni. Spiesz się, liczy się każda sekunda.","Não. Definitivamente não é. Seja lá o que for, você deve enfrentá-lo para recuperar a chave. Vou abrir a entrada das catacumbas. Quando você pegar a chave, vá para a fábrica próxima às minas. Depressa, cada segundo é importante.",,"Nu. Cu siguranță nu. Orice ar fi, va trebui să o înfrunți pentru a recupera cheia. Voi deschide intrarea catacombelor. Când o ai, fabrica e vizavi de mine. Grăbește-te, orice secundă contează.","Нет. Определённо нет. Что бы это ни было, ты должен сразиться с ним, чтобы заполучить ключ. Я открою вход в катакомбы. Когда добудешь его, направляйся на фабрику: она находится рядом со входом в шахты. Торопись! Дорога каждая секунда!",,"Inte. Definitivt inte. Vad det än är måste du slåss mot det för att få tag på nyckeln. Jag öppnar katakombernas ingång. När du har fått den är fabriken bredvid gruvorna. Skynda dig, varje sekund räknas.","İnsan değil. Kesinlikle değil. O her neyse, anahtarı almak için onunla savaşmalısın. Yeraltı mezarlarının girişini açacağım. Anahtarı aldığında, fabrika madenlerin yanında. Acele et, her saniye önemli." +"Something inhuman, eh?, great.",TXT_RPLY0_SCRIPT23_D25772_SOMET,〃,,,"Něco nelidského, co? Skvělý.","Noget umenneskeligt, hva'?, fantastisk.",Irgendetwas unmenschliches? Na großartig.,,"Nehomaĵo, ĉu? Bonege.","Algo inhumano, ¿eh? Genial.",,"Jotain epäinhimillistä, vai? Hienoa.","Quelque chose d'inhumain, hein? Parfait.","Valami nem emberi, mi? Csodás.","Qualcosa di inumano, eh? Fantastico.",非人道的な何か?流石だな。,비인간적인 녀석인가요? 좋군요.,"Iets onmenselijks, eh?, geweldig.","Noe umenneskelig, hva? Flott!","Coś nieludzkiego, ech, świetnie.","Algo não-humano, é? Que ótimo.",,"Ceva inuman, ei? Grozav.",Что-то иное? Просто отлично.,,"Något omänskligt, va?, bra.","İnsanlık dışı bir şey, ha? Harika." +You're wasting time and lives! Move!,TXT_DLG_SCRIPT23_D27288_YOURE,〃,,,Plýtváš časem i životy! Jdi!,Du spilder tid og liv! Af sted!,Du verschwendest Zeit und Leben! Beweg dich!,,Vi perdas tempon kaj vivojn! Agu!,¡Estás perdiendo tiempo y vidas! ¡Muévete!,,Haaskaat aikaa ja henkiä! Liikkuu jo!,Vous perdez votre temps et des vies! Bougez!,Időt és életeket pazarolsz! Mozgás!,"Stai sprecando tempo, e vite. Sbrigati!","こうしてる間にも君は時間と人命を +無駄にしている。行け!",시간과 생명이 위협받고 있다고! 서두르세요!!,Je verspilt tijd en levens! Vooruit!,Du kaster bort tid og liv! Skynd dere!,Marnujesz czas i życie! Ruszać się!,Você está desperdiçando tempo e vidas! Ande logo!,,"Pierzi timp și vieți, mișcă-te!",Ты тратишь время и жизни! Вперёд!,,Du slösar bort tid och liv! Flytta på dig!,Zamanınızı ve hayatlarınızı boşa harcıyorsunuz! Çekilin! +"The master doesn't like visitors. He likes all of his work to remain undisturbed. I've got to go get fresh parts from the storage room. I think he said a leg and an arm. Oh, well no time to talk anymore. I'd leave before he finds you.",TXT_DLG_SCRIPT27_D0_THEMA,MAP27: Peasant → Northeastern room (after the lift).,,,"Pán nemá rád návštěvy. Má rád, když ho nic neruší od práce. Musím dojít pro čerstvé části ze skladu. Myslím, že chtěl nohu a ruku. Tak, na mluvení není čas. Být tebou, odešel bych dřív, než tě najde.","Mesteren kan ikke lide besøgende. Han kan lide, at alt hans arbejde forbliver uforstyrret. Jeg skal hente nye dele fra lagerrummet. Jeg tror, han sagde et ben og en arm. Nå, men vi har ikke tid til at snakke mere. Jeg ville gå, før han finder dig.","Der Meister mag keine Besucher. Er hat es gern, wenn er bei der Arbeit nicht gestört wird. Ich muss gehen und neue Teile aus dem Lagerraum holen. Ich glaube er sagte ein Bein und eine Arm. Naja, keine Zeit mehr zum Reden. Du solltest gehen, bevor er dich findet.",,"La majstro ne ŝatas vizitantojn; li ŝatas, ke ĉiu laboro estu seninterrompa. Mi devas serĉi freŝajn partojn en la deponejo: kruron kaj brakon laŭ tio, kion mi memoras. Ho, bone, ne estas tempo paroli. Se mi estus vi, mi forirus por ne esti trovita.","Al maestro no le gustan las visitas; le gusta que su trabajo permanezca ininterrumpido. Tengo que ir a buscar partes frescas al almacén: una pierna y un brazo, creo que ha dicho. Ah, bueno, no hay tiempo para hablar. Yo que tú me iría antes de que te encuentre.","Al maestro no le gustan las visitas; le gusta que su trabajo permanezca ininterrumpido. Tengo que ir a buscar partes frescas al almacén: una pierna y un brazo, creo que dijo. Ah, bueno, no hay tiempo para hablar. Yo que tú me iría antes de que te encuentre.","Mestari ei pidä vieraista. Hän haluaa kaikkien töittensä säilyä koskemattomina. Minun on mentävä noutamaan tuoreita osia varastosta. Hän taisi puhua jalasta ja käsivarresta. No, ei enempää aikaa puhua. Sinuna lähtisin, ennen kuin hän löytää sinut.","Le Maître n'aime pas les visiteurs. Il préfère que son travail se déroule dans le calme. Il faut que j'aille chercher des pièces dans la salle de stockage. Il m'a demandé une jambe et un bras, je crois. Bon, plus de temps pour parler. Je partirais si j'étais vous.","A gazda nem szereti a látogatókat. Úgy szereti, ha nem zavarja senki a munkájában. Mennem kell új darabokért a tárolóba. Azt hiszem egy lábat és egy kart említett. Hát, sajnos nincs időm beszélgetni már. A helyedben elmennék, mielőtt megtalál.","Al padrone non piacciono i visitatori. Vuole che tutto il suo lavoro rimanga indisturbato. Ho qua le parti nuove dal magazzino. Mi pare abbia detto una gamba e un braccio. Ah, non ho più tempo per parlare. Io me ne andrei prima che si accorga che tu sei qui.","マスターは訪問者ヲ嫌っている。 彼ハ自分ノ仕事ヲ邪魔されないノガ良いからダ。 私ハこれカラ倉庫に新品の部品を取りに行かねば 腕と足だったカナ。オット、モウ話ス時間ハ無イ -マスターが君を見つける前ニ出発しなけれバ。","주인님은 방문자들을 싫어해. 반대로 그는 남들의 방해 없이 혼자서 일을 하는 걸 아주 좋아하지. 저장고에서 재료를 꺼내서 가져다주는 나 같은 사람들을 제외하면. 한 쌍의 팔다리가 필요하다고 들었는데... 오, 이런. 이제 이야기할 시간도 없어졌네. 그가 널 찾기 전에 도망치는 게 좋을걸?","De meester houdt niet van bezoekers. Hij houdt ervan dat al zijn werk ongestoord blijft. Ik moet verse onderdelen uit de opslagruimte halen. Ik denk dat hij een been en een arm zei. Oh, nou geen tijd meer om te praten. Ik zou weggaan voordat hij je vindt.",Mesteren liker ikke besøkende. Han vil ha arbeidet sitt uforstyrret. Jeg må gå og hente nye deler fra lageret. Jeg tror han sa et bein og en arm. Jeg har ikke tid til å prate mer. Jeg ville dratt før han finner deg.,"Mistrz nie lubi gości. Lubi, gdy cała jego praca pozostaje niezakłócona. Muszę iść po świeże części z magazynu. Chyba powiedział noga i ręka. Nie ma czasu na gadanie. Wyszedłbym, zanim cię znajdzie.","O mestre não gosta de visitantes. Ele gosta que seu trabalho não seja perturbado. Tenho que ir buscar peças novas no depósito. Bom, não tenho mais tempo para conversa. Eu iria embora antes que ele te ache.",,"Stăpânului nu îi plac vizitatorii. Îi place ca toată muncă să fie nederanjată. Trebuie să aduc părți noi din depozit. Cred că a zis un braț și un picior. Of, nu mai e timp de vorbă. O să plec înainte să te găsească.","Хранитель не любит гостей — он предпочитает, чтобы его никто не отвлекал от работы. Он послал меня на склад за свежими частями. Рукой и ногой, кажется... Ох, нет времени на разговоры. Лучше бы тебе уйти, пока он не вернулся.",,Efendi ziyaretçileri sevmez. Tüm çalışmalarının rahatsız edilmeden kalmasını ister. Gidip depodan yeni parçalar almalıyım. Sanırım bir bacak ve bir kol dedi. Artık konuşacak vakit yok. Ben olsam o seni bulmadan giderdim. -Why's that.,TXT_RPLY0_SCRIPT27_D0_WHYST,,,,A proč?,Hvorfor det?,Wieo das?,,,¿Por qué?,,Miksi?,Pourquoi donc?,Miért tennék olyat?,E perché mai?,何故そんなことを。,그건 왜지?,Waarom is dat.,Hvorfor det?,Dlaczego tak jest?,Por quê?,,De ce.,Почему так?,,Nedenmiş o? -"Because, I told you he doesn't like visitors!",TXT_RYES0_SCRIPT27_D0_BECAU,,,,"Protože, jak už jsem řekl, nemá rád návštěvy!","Fordi jeg sagde jo, at han ikke kan lide besøgende!","Ich habe dir doch gesagt, dass er keine Besucher mag!",,,¡Porque te he dicho que no le gustan las visitas!,¡Te estoy diciendo que no le gustan las visitas!,"Koska minähän sanoin, ettei hän pidä vieraista!","Je vous ai dit, il n'aime pas les visiteurs!","Most mondtam, hogy nem szereti a látogatókat!","Perché, come ti ho appena detto, non gli piacciono i visitatori!",ナゼなら、マスターは訪問されたくナイからダ!,"왜냐하면, 그가 방문자들을 싫어한다고 내가 말했으니까!","Omdat hij niet van bezoekers houdt, zei ik toch!",Jeg sa jo at han ikke liker besøk!,"Bo mówiłem ci, że nie lubi gości!","Porque, como eu já te falei, ele não gosta de visitantes!",,"Pentru că, ți-am spus, nu-i plac vizitatorii!","Потому что, как я уже сказал тебе, он не любит посетителей!",,Çünkü sana ziyaretçileri sevmediğini söylemiştim! -"You know, you're about the right size for one of the acolyte's uniforms.",TXT_DLG_SCRIPT27_D1516_YOUKN,,,,"Hele, ty vypadáš, že by ti dobře sedla unforma akolytů.",Du har den rette størrelse til en af acolyternes uniformer.,"Weißt du, du hast genau die richtige Größe für die Uniform eines Missionars.",,,"Sabes, tienes la talla justa para uno de los uniformes de acólito.",,"Hei kuules, olet suurin piirtein sopivan kokoinen akoluutin univormuun.","Vous savez, vous avez juste la taille qu'il faut pour un uniforme d'acolyte.","Tudod-e, hogy ránézésre pont jó rád a ministráns egyenruha.","Sai che ti dico, sei proprio della taglia perfetta per una delle uniforme degli accoliti.","知ッテるハズだ、アンタに合う -アコライトの制服一着のサイズについてサ。","어디보자... 당신의 치수, 경비 전투복 크기에 적당히 딱 맞는 것 같군!","Weet je, je bent ongeveer de juiste maat voor een van de uniformen van de acoliet.","Vet du, du har omtrent riktig størrelse for en av akolyttenes uniformer.","Wiesz, masz odpowiedni rozmiar na jeden z mundurków akolitów.","Sabe, você tem a altura perfeita para um dos uniformes de acólito.",,"Știi, eși marimea potrivită pentru o uniformă de acolit.","Знаешь, тебе бы как раз впору пошла униформа служителя.",,"Biliyor musun, yardımcı üniformalarından biri için doğru bedensin." -"Oh no, I'm not the real Programmer, he's hiding. Continue past the guard training area, very tough. If you survive, you might be able to talk to him. Or kill him.",TXT_DLG_SCRIPT31_D0_OHNOI,MAP31,,,"Kdepak, já nejsem skutečný Programátor. Ten se schovává. Ale pokračuj skrz tréninkovou oblast, je velmi obtížná. Jestli přežiješ, mohl by sis s ním i promluvit. Nebo ho zabít.","Åh nej, jeg er ikke den rigtige programmør. Han gemmer sig. Fortsæt forbi vagttræningsområdet, meget hårdt. Hvis du overlever, kan du måske tale med ham. Eller slå ham ihjel.","O nein, ich bin nicht der echte Programmierer. Er versteckt sich. Ich glaube irgendwo jenseits des Trainingsbereichs für die Wächter. verdammt schwierig. Wenn du überlebst könntest du in finden. Oder töten.",,,"Eh no, no soy el verdadero Programador; está escondido. Continúa a traves del área de entrenamiento de guardias. Muy difícil. Si sobrevives, tal vez puedas hablar con él. O matarlo.",,"Ehei, en ole oikea Ohjelmoitsija; hän piilottelee. Jatka vartijoiden koulutusalueen läpi; tulee olemaan haastavaa. Jos selviydyt, saatat ehkä pystyä puhumaan hänen kanssaan; tai tappaa hänet.","Oh non, je ne suis pas le vrai Programmeur. Il se cache. Continuez après la zone d'entraînement des gardes. C'est dangereux, mais si vous y arrivez, vous devriez pouvoir lui parler.. Ou le tuer.","Oh dehogy, nem Én vagyok az igazi Programozó, Ő most elbújt. Ha túléled az őrképző részleget, akkor rögtön utána megtalálod őt. Vagy éppen meg is ölheted.","Oh no, io non sono il vero Programmatore, lui si sta nascondendo. Procedi oltre l'area di addestramento delle guardie, molto tosta. Se sopravvivi, potresti riuscire a parlargli. O magari ad ucciderlo.","イヤイヤ、私ハ真ノプログラマーではない、 +マスターが君を見つける前ニ出発しなけれバ。","주인님은 방문자들을 싫어해. 반대로 그는 남들의 방해 없이 혼자서 일을 하는 걸 아주 좋아하지. 저장고에서 재료를 꺼내서 가져다주는 나 같은 사람들을 제외하면. 한 쌍의 팔다리가 필요하다고 들었는데... 오, 이런. 이제 이야기할 시간도 없어졌네. 그가 널 찾기 전에 도망치는 게 좋을걸?","De meester houdt niet van bezoekers. Hij houdt ervan dat al zijn werk ongestoord blijft. Ik moet verse onderdelen uit de opslagruimte halen. Ik denk dat hij een been en een arm zei. Oh, nou geen tijd meer om te praten. Ik zou weggaan voordat hij je vindt.",Mesteren liker ikke besøkende. Han vil ha arbeidet sitt uforstyrret. Jeg må gå og hente nye deler fra lageret. Jeg tror han sa et bein og en arm. Jeg har ikke tid til å prate mer. Jeg ville dratt før han finner deg.,"Mistrz nie lubi gości. Lubi, gdy cała jego praca pozostaje niezakłócona. Muszę iść po świeże części z magazynu. Chyba powiedział noga i ręka. Nie ma czasu na gadanie. Wyszedłbym, zanim cię znajdzie.","O mestre não gosta de visitantes. Ele gosta que seu trabalho não seja perturbado. Tenho que ir buscar peças novas no depósito. Bom, não tenho mais tempo para conversa. Eu iria embora antes que ele te ache.",,"Stăpânului nu îi plac vizitatorii. Îi place ca toată muncă să fie nederanjată. Trebuie să aduc părți noi din depozit. Cred că a zis un braț și un picior. Of, nu mai e timp de vorbă. O să plec înainte să te găsească.","Хранитель не любит гостей — он предпочитает, чтобы его никто не отвлекал от работы. Он послал меня на склад за свежими частями. Рукой и ногой, кажется... Ох, нет времени на разговоры. Лучше бы тебе уйти, пока он не вернулся.",,Mästaren gillar inte besökare. Han vill att allt arbete ska förbli ostört. Jag måste hämta nya delar från lagret. Jag tror att han sa ett ben och en arm. Vi har inte tid att prata längre. Jag skulle gå innan han hittar dig.,Efendi ziyaretçileri sevmez. Tüm çalışmalarının rahatsız edilmeden kalmasını ister. Gidip depodan yeni parçalar almalıyım. Sanırım bir bacak ve bir kol dedi. Artık konuşacak vakit yok. Ben olsam o seni bulmadan giderdim. +Why's that.,TXT_RPLY0_SCRIPT27_D0_WHYST,〃,,,A proč?,Hvorfor det?,Wieo das?,,Kial mi forirus?,¿Irme por qué?,,Miksi?,Pourquoi donc?,Miért tennék olyat?,E perché mai?,何故そんなことを。,그건 왜지?,Waarom is dat.,Hvorfor det?,Dlaczego tak jest?,Por quê?,,De ce.,Почему так?,,Varför det?,Nedenmiş o? +"Because, I told you he doesn't like visitors!",TXT_RYES0_SCRIPT27_D0_BECAU,〃,,,"Protože, jak už jsem řekl, nemá rád návštěvy!","Fordi jeg sagde jo, at han ikke kan lide besøgende!","Ich habe dir doch gesagt, dass er keine Besucher mag!",,"Mi diris, ke li +ne ŝatas vizitantojn!","¡He dicho que no +le gustan las visitas!","¡Te estoy diciendo que +no le gustan las visitas!","Koska minähän sanoin, ettei hän pidä vieraista!","Je vous ai dit, il n'aime pas les visiteurs!","Most mondtam, hogy nem szereti a látogatókat!","Perché, come ti ho appena detto, non gli piacciono i visitatori!",ナゼなら、マスターは訪問されたくナイからダ!,"왜냐하면, 그가 방문자들을 싫어한다고 내가 말했으니까!","Omdat hij niet van bezoekers houdt, zei ik toch!",Jeg sa jo at han ikke liker besøk!,"Bo mówiłem ci, że nie lubi gości!","Porque, como eu já te falei, ele não gosta de visitantes!",,"Pentru că, ți-am spus, nu-i plac vizitatorii!","Потому что, как я уже сказал тебе, он не любит посетителей!",,För att jag sa ju att han inte gillar besökare!,Çünkü sana ziyaretçileri sevmediğini söylemiştim! +"You know, you're about the right size for one of the acolyte's uniforms.",TXT_DLG_SCRIPT27_D1516_YOUKN,〃,,,"Hele, ty vypadáš, že by ti dobře sedla unforma akolytů.",Du har den rette størrelse til en af acolyternes uniformer.,"Weißt du, du hast genau die richtige Größe für die Uniform eines Missionars.",,"Interese, vi havas la ĝustan talion por surhavi akolitan uniformon.",¿Sabes? Tienes la talla justa para alguno de los uniformes de acólito.,¿Sabes? Tienes el talle justo para alguno de los uniformes de acólito.,"Hei kuules, olet suurin piirtein sopivan kokoinen akoluutin univormuun.","Vous savez, vous avez juste la taille qu'il faut pour un uniforme d'acolyte.","Tudod-e, hogy ránézésre pont jó rád a ministráns egyenruha.","Sai che ti dico, sei proprio della taglia perfetta per una delle uniforme degli accoliti.","知ッテるハズだ、アンタに合う +アコライトの制服一着のサイズについてサ。","어디보자... 당신의 치수, 경비 전투복 크기에 적당히 딱 맞는 것 같군!","Weet je, je bent ongeveer de juiste maat voor een van de uniformen van de acoliet.","Vet du, du har omtrent riktig størrelse for en av akolyttenes uniformer.","Wiesz, masz odpowiedni rozmiar na jeden z mundurków akolitów.","Sabe, você tem a altura perfeita para um dos uniformes de acólito.",,"Știi, eși marimea potrivită pentru o uniformă de acolit.","Знаешь, тебе бы как раз впору пошла униформа служителя.",,"Du vet, du är ungefär rätt storlek för en av akolyternas uniformer.","Biliyor musun, yardımcı üniformalarından biri için doğru bedensin." +"Oh no, I'm not the real Programmer, he's hiding. Continue past the guard training area, very tough. If you survive, you might be able to talk to him. Or kill him.",TXT_DLG_SCRIPT31_D0_OHNOI,MAP31: Programmer.,,,"Kdepak, já nejsem skutečný Programátor. Ten se schovává. Ale pokračuj skrz tréninkovou oblast, je velmi obtížná. Jestli přežiješ, mohl by sis s ním i promluvit. Nebo ho zabít.","Åh nej, jeg er ikke den rigtige programmør. Han gemmer sig. Fortsæt forbi vagttræningsområdet, meget hårdt. Hvis du overlever, kan du måske tale med ham. Eller slå ham ihjel.","O nein, ich bin nicht der echte Programmierer. Er versteckt sich. Ich glaube irgendwo jenseits des Trainingsbereichs für die Wächter. verdammt schwierig. Wenn du überlebst könntest du in finden. Oder töten.",,"Ha ha! Ne, mi ne estas la Programisto; la reala estas kaŝita. Daŭrigu trans la trejnejo por gardistoj; tre malfacila. Se vi supervivos, vi eble povos paroli kun li... aŭ mortigi lin.","¡Je, je! No, no soy el Programador; el verdadero está escondido. Continúa a traves del área de entrenamiento de guardias; muy difícil. Si sobrevives, tal vez puedas hablar con él... o matarlo.",,"Ehei, en ole oikea Ohjelmoitsija; hän piilottelee. Jatka vartijoiden koulutusalueen läpi; tulee olemaan haastavaa. Jos selviydyt, saatat ehkä pystyä puhumaan hänen kanssaan; tai tappaa hänet.","Oh non, je ne suis pas le vrai Programmeur. Il se cache. Continuez après la zone d'entraînement des gardes. C'est dangereux, mais si vous y arrivez, vous devriez pouvoir lui parler.. Ou le tuer.","Oh dehogy, nem Én vagyok az igazi Programozó, Ő most elbújt. Ha túléled az őrképző részleget, akkor rögtön utána megtalálod őt. Vagy éppen meg is ölheted.","Oh no, io non sono il vero Programmatore, lui si sta nascondendo. Procedi oltre l'area di addestramento delle guardie, molto tosta. Se sopravvivi, potresti riuscire a parlargli. O magari ad ucciderlo.","イヤイヤ、私ハ真ノプログラマーではない、 彼ハ隠れている。非常ニタフなガードノ 訓練場にダ、もし生き残れたら会えるだろう 或いハ彼を殺せるだろう。","하하. 아, 난 프로그래머님이 아니야. 그는 지금 숨고 있어. 경비 훈련소를 한번 체험해봐. 어렵겠지만, 한번 통과하면 너에게 말을 걸어줄지도 몰라. 아니면 널 죽이던가! - \cy내가 사람들 죽이는 걸 지겨워할 것 같지만, 이 일이 모두 끝나면 아마 그리워할 거야.","Oh nee, ik ben niet de echte programmeur, hij verstopt zich. Ga verder langs de bewakingsopleiding, heel moeilijk. Als je het overleeft, kun je misschien met hem praten. Of dood hem.","Å nei, jeg er ikke den ekte programmereren. Han gjemmer seg. Fortsett forbi vaktenes treningsområde, veldig tøft. Hvis du overlever, kan du kanskje snakke med ham. Eller drepe ham.","O nie, nie jestem prawdziwym Programistą, on się ukrywa. Kontynuuj obok obszaru szkolenia strażników, bardzo trudnego. Jeśli przeżyjesz, może uda ci się z nim porozmawiać. Albo go zabić.","Ah não, eu não sou o verdadeiro Programador. Ele está escondido. Continue pela área de treinamento de guardas. É bem difícil. Se você sobreviver, talvez você possa falar com ele. Ou matar ele.",,"Oh nu, nu sunt adevăratul Programator. Continuă până dincolo de câmpul de antrenament. Dacă supraviețuiești, vei putea vorbi cu el. Sau să îl omori.","О, нет. Я не настоящий Программист. Он прячется. На твоём пути лежит зона тренировки стражи. Пройти её очень непросто. Если уцелеешь, то сможешь поговорить с ним... или убить его.",,"Oh hayır, ben gerçek Programcı değilim, o saklanıyor. Muhafız eğitim alanını geçmeye devam et, çok zorlu. Eğer hayatta kalırsan, onunla konuşabilirsin. Ya da onu öldürebilirsin." -Who are you?,TXT_RPLY0_SCRIPT31_D0_WHOAR,〃,,,Kdo jsi?,Hvem er du?,Wer bist du?,,Kiu vi estas?,¿Quién eres?,,Kuka sinä olet?,Qui êtes vous?,Ki vagy te?,E tu chi sei?,お前は誰だ?,당신은 누구죠?,Wie ben jij?,Hvem er du?,Kim jesteś?,Quem é você?,,Cine ești?,Кто ты?,,Kimsin sen? -You'll never find anything if you hang around here.,TXT_DLG_SCRIPT31_D1516_YOULL,〃,,,"Nic nenajdeš, když se tu budeš potloukat.","Du finder aldrig noget, hvis du bliver hængende her.","Du wirst niemals etwas finden, wenn du hier herumhängst.",,,Nunca encontrarás nada si permaneces aquí.,,"Et saa ikinä mitään selville, jos jäät tänne oleilemaan.",Vous ne découvrerez rien si vous traînez ici.,"Nem fogsz semmit se találni, ha csak itt bóklászol.",Non troverai nulla se rimani fermo qui.,アンタがここをふらついても何も無いよ。,여기에 계속 머무르고 있으면 다 알지도 못할걸.,Je zult nooit iets vinden als je hier rondhangt.,Du finner aldri noe hvis du blir her.,"Nic nie znajdziesz, jeśli będziesz się tu kręcił.",Você nunca vai descobrir nada se ficar por aqui.,,N-o să aflii nimic dacă pierzi timpul aici.,"Ты ничего не добьёшься, если будешь ошиваться тут.",,Buralarda takılırsan asla bir şey bulamazsın. -Piss off peasant!,TXT_DLG_SCRIPT32_D0_PISSO,〃,,,"Odprejskni, poddaný!",Pis af bonde!,"Verpiss dich, du Bauer!",,,"¡Esfúmate, campesino!",,"Suksi suohon, maallikko!","Dégage, paysan!",Takarodj a színem elől paraszt!,"Fuori dai piedi, cittadino!",イラつかせるな、田吾作が!,"저리 꺼져라, 시민!",Boer boer kwaad maken!,"Dra til helvete, bonde!",Odwal się chłopie!,"Suma daqui, plebeu!",,"Valea, sărmanule!","Вали отсюда, рабочий!",,Defol köylü! -Die little man!,TXT_DLG_SCRIPT32_D1516_DIELI,"Appears in MAP32 and is supposed to be spoken by the AcolyteRust actor (named “Interrogator”). However, no such actor is spawned in the map, rendering this line unused.",,,"Zemři, mužíčku!","Dø, lille mand!","Stirb, kleiner Mann!",,"Mortu, nano!","¡Muere, enano!",,"Kuole, pikku mies!","Meurs, petite frappe!",,"Muori, piccolo uomo!",,죽어라. 나약한 것!,Sterf kleine man!,"Dø, lille mann!",Giń mały człowieku!,"Morra, insignificante!",,"Mori, mititelule!","Сдохни, человечишка!",,Geber küçük adam! -Finally I can get out of this cell.,TXT_DLG_SCRIPT32_D3032_FINAL,MAP32: Cell.,,,Konečně se můžu z téhle cely dostat.,Endelig kan jeg komme ud af denne celle.,Endlich kann ich aus dieser Zelle raus.,,Mi finfine estas libera.,Por fin puedo salir de esta celda.,,"Vihdoinkin, voin päästä pois tästä sellistä.","Enfin, je peux sortir de cette cellule.",Végre kiszabadulhatok ebből a cellából.,Finalmente posso uscire da questa cella.,遂に、この独房から抜け出せる。,드디어 이 감옥에서 벗어나는구나...,Eindelijk kan ik uit deze cel komen.,Endelig kan jeg komme ut av denne cella.,Wreszcie mogę się wydostać z tej celi.,Finalmente eu posso sair desta cela.,,În sfârșit pot părăsi celula asta.,Наконец-то я могу сбежать из этой камеры!,,Sonunda bu hücreden çıkabilirim. -Why are you in here?,TXT_RPLY0_SCRIPT32_D3032_WHYAR,〃,,,Proč tu jsi?,Hvorfor er du herinde?,Warum bist du da drin?,,Kial vi estas ĉi tie?,¿Por que estás aquí?,,Miksi olet täällä?,Pourquoi êtes vous ici?,Miért vagy itt bent?,Perché ti trovi qui?,何でここにいる?,너가 왜 여기있지?,Waarom ben je hier binnen?,Hvorfor er du her?,Dlaczego tu jesteś?,Por que você está aqui?,,De ce ești închis?,Как ты здесь оказался?,,Sen neden buradasın? -I was framed.,TXT_RYES0_SCRIPT32_D3032_IWASF,〃,,,Podvedli mě.,Jeg er blevet snydt.,Ich wurde hereingelegt.,,Mi estis akuzita.,Fui incriminado.,,Minut lavastettiin.,J'ai été victime d'un coup monté.,Meggyanúsítottak.,Mi hanno incastrato.,私は無実だ。,저는 누명을 썼어요.,Ik werd erin geluisd.,Jeg ble lurt i en felle.,Zostałem wrobiony.,Eu caí numa cilada.,,Am fost înscenat.,Меня подставили.,,Bana komplo kuruldu. -Harris said that I was plotting to kill the Governor. I would never harm a soul.,TXT_DLG_SCRIPT32_D4548_HARRI,〃,,,"Harris řekl, že jsem prý měl v plánu zavraždit guvernéra. Ani mouše bych neublížil.","Harris sagde, at jeg planlagde at dræbe guvernøren. Jeg ville aldrig skade nogen.","Harris hat erzählt, das ich plante den Gouverneur zu ermorden. Ich könnte keiner Menschenseele etwas antun.",,"Harris diris, ke mi planas mortigi la registon. Mi neniam vundus iun.",Harris dijo que yo estaba planeando matar al gobernador. Y yo no podría hacerle nada a nadie.,,Harris väitti minun juonineen kuvernöörin salamurhaa. En ikinä satuttaisi ketään.,Harris a dit que j'avais un plan pour tuer le gouverneur. Je ne ferais pas de mal à qui que ce soit.,"Harris azt nyilatkozta, hogy a kormányzó életére akarok törni. Egy légynek sem ártanék.",Harris ha detto che progettavo di uccidere il governatore. Ma io non farei mai del male a nessuno.,"ハリスに知事の暗殺を企てていると言われた。 -そんなこと心にも思ったことは無いのに。","해리스가 말하길, 제가 총독 암살을 꾀했데요. 난 파리 한마리도 못 죽이는데...",Harris zei dat ik van plan was om de gouverneur te vermoorden. Ik zou nooit een ziel kwaad doen.,Harris sa at jeg planla å drepe guvernøren. Jeg ville aldri skade noen.,"Harris powiedział, że spiskowałem, by zabić gubernatora. Nigdy nie skrzywdziłbym żadnej duszy.",O Harris disse que eu estava planejando matar o Governador. Eu nunca faria mal a qualquer pessoa.,,Harris a spus că plănuiam să-l omor pe Guvernator. N-aș răni un suflet niciodată.,"Харрис сказал, что я замышлял убийство губернатора. А я и мухи не обижу!",,"Harris, Vali'yi öldürmeyi planladığımı söyledi. Kimseye zarar vermem." -Be careful out there.,TXT_DLG_SCRIPT33_D0_BECAR,,,,Buď tam venku opatrný.,Vær forsigtig derude.,Sei vorsichtig dort draußen.,,,Ten cuidado ahí fuera.,,Pidä itsestäsi huoli.,Faites attention à vous.,Légy óvatos odakint.,Stai attento là fuori.,外は気をつけろ。,조심해.,Wees voorzichtig daarbuiten.,Vær forsiktig der ute.,Bądź ostrożny.,Tome cuidado por aí.,,Ai grijă pe-acolo.,Будь поосторожнее.,,Dışarıda dikkatli ol. + \cy내가 사람들 죽이는 걸 지겨워할 것 같지만, 이 일이 모두 끝나면 아마 그리워할 거야.","Oh nee, ik ben niet de echte programmeur, hij verstopt zich. Ga verder langs de bewakingsopleiding, heel moeilijk. Als je het overleeft, kun je misschien met hem praten. Of dood hem.","Å nei, jeg er ikke den ekte programmereren. Han gjemmer seg. Fortsett forbi vaktenes treningsområde, veldig tøft. Hvis du overlever, kan du kanskje snakke med ham. Eller drepe ham.","O nie, nie jestem prawdziwym Programistą, on się ukrywa. Kontynuuj obok obszaru szkolenia strażników, bardzo trudnego. Jeśli przeżyjesz, może uda ci się z nim porozmawiać. Albo go zabić.","Ah não, eu não sou o verdadeiro Programador. Ele está escondido. Continue pela área de treinamento de guardas. É bem difícil. Se você sobreviver, talvez você possa falar com ele. Ou matar ele.",,"Oh nu, nu sunt adevăratul Programator. Continuă până dincolo de câmpul de antrenament. Dacă supraviețuiești, vei putea vorbi cu el. Sau să îl omori.","О, нет. Я не настоящий Программист. Он прячется. На твоём пути лежит зона тренировки стражи. Пройти её очень непросто. Если уцелеешь, то сможешь поговорить с ним... или убить его.",,"Åh nej, jag är inte den riktiga programmeraren, han gömmer sig. Fortsätt förbi vakternas träningsområde, mycket tufft. Om du överlever kanske du kan prata med honom. Eller döda honom.","Oh hayır, ben gerçek Programcı değilim, o saklanıyor. Muhafız eğitim alanını geçmeye devam et, çok zorlu. Eğer hayatta kalırsan, onunla konuşabilirsin. Ya da onu öldürebilirsin." +Who are you?,TXT_RPLY0_SCRIPT31_D0_WHOAR,〃,,,Kdo jsi?,Hvem er du?,Wer bist du?,,Kiu vi estas?,¿Quién eres?,,Kuka sinä olet?,Qui êtes vous?,Ki vagy te?,E tu chi sei?,お前は誰だ?,당신은 누구죠?,Wie ben jij?,Hvem er du?,Kim jesteś?,Quem é você?,,Cine ești?,Кто ты?,,Vem är du?,Kimsin sen? +You'll never find anything if you hang around here.,TXT_DLG_SCRIPT31_D1516_YOULL,〃,,,"Nic nenajdeš, když se tu budeš potloukat.","Du finder aldrig noget, hvis du bliver hængende her.","Du wirst niemals etwas finden, wenn du hier herumhängst.",,Vi trovos nenion se vi restas ĉi tie.,No encontrarás nada si sigues aquí.,No vas a encontrar nada si sigues aquí.,"Et saa ikinä mitään selville, jos jäät tänne oleilemaan.",Vous ne découvrerez rien si vous traînez ici.,"Nem fogsz semmit se találni, ha csak itt bóklászol.",Non troverai nulla se rimani fermo qui.,アンタがここをふらついても何も無いよ。,여기에 계속 머무르고 있으면 다 알지도 못할걸.,Je zult nooit iets vinden als je hier rondhangt.,Du finner aldri noe hvis du blir her.,"Nic nie znajdziesz, jeśli będziesz się tu kręcił.",Você nunca vai descobrir nada se ficar por aqui.,,N-o să aflii nimic dacă pierzi timpul aici.,"Ты ничего не добьёшься, если будешь ошиваться тут.",,Du kommer aldrig att hitta något om du hänger kvar här.,Buralarda takılırsan asla bir şey bulamazsın. +Piss off peasant!,TXT_DLG_SCRIPT32_D0_PISSO,MAP32: Red acolyte.,,,"Odprejskni, poddaný!",Pis af bonde!,"Verpiss dich, du Bauer!",,"Foriru, kampulo!","¡Esfúmate, campesino!",,"Suksi suohon, maallikko!","Dégage, paysan!",Takarodj a színem elől paraszt!,"Fuori dai piedi, cittadino!",イラつかせるな、田吾作が!,"저리 꺼져라, 시민!",Boer boer kwaad maken!,"Dra til helvete, bonde!",Odwal się chłopie!,"Suma daqui, plebeu!",,"Valea, sărmanule!","Вали отсюда, рабочий!",,Dra åt helvete bonde!,Defol köylü! +Die little man!,TXT_DLG_SCRIPT32_D1516_DIELI,"Appears in MAP32 and is supposed to be spoken by the AcolyteRust actor (named “Interrogator”). However, no such actor is spawned in the map, rendering this line unused.",,,"Zemři, mužíčku!","Dø, lille mand!","Stirb, kleiner Mann!",,"Mortu, nano!","¡Muere, enano!",,"Kuole, pikku mies!","Meurs, petite frappe!","Halál rád, te jöttment!","Muori, piccolo uomo!",,죽어라. 나약한 것!,Sterf kleine man!,"Dø, lille mann!",Giń mały człowieku!,"Morra, insignificante!",,"Mori, mititelule!","Сдохни, человечишка!",,"Dö, lilla man!",Geber küçük adam! +Finally I can get out of this cell.,TXT_DLG_SCRIPT32_D3032_FINAL,MAP32: Cell.,,,Konečně se můžu z téhle cely dostat.,Endelig kan jeg komme ud af denne celle.,Endlich kann ich aus dieser Zelle raus.,,Mi finfine estas libera.,Por fin puedo salir de esta celda.,,"Vihdoinkin, voin päästä pois tästä sellistä.","Enfin, je peux sortir de cette cellule.",Végre kiszabadulhatok ebből a cellából.,Finalmente posso uscire da questa cella.,遂に、この独房から抜け出せる。,드디어 이 감옥에서 벗어나는구나...,Eindelijk kan ik uit deze cel komen.,Endelig kan jeg komme ut av denne cella.,Wreszcie mogę się wydostać z tej celi.,Finalmente eu posso sair desta cela.,,În sfârșit pot părăsi celula asta.,Наконец-то я могу сбежать из этой камеры!,,Äntligen kan jag komma ut ur den här cellen.,Sonunda bu hücreden çıkabilirim. +Why are you in here?,TXT_RPLY0_SCRIPT32_D3032_WHYAR,〃,,,Proč tu jsi?,Hvorfor er du herinde?,Warum bist du da drin?,,Kial vi estas ĉi tie?,¿Y por que estás aquí?,,Miksi olet täällä?,Pourquoi êtes vous ici?,Miért vagy itt bent?,Perché ti trovi qui?,何でここにいる?,너가 왜 여기있지?,Waarom ben je hier binnen?,Hvorfor er du her?,Dlaczego tu jesteś?,Por que você está aqui?,,De ce ești închis?,Как ты здесь оказался?,,Varför är du här inne?,Sen neden buradasın? +I was framed.,TXT_RYES0_SCRIPT32_D3032_IWASF,〃,,,Podvedli mě.,Jeg er blevet snydt.,Ich wurde hereingelegt.,,Mi estis akuzita.,Me incriminaron.,,Minut lavastettiin.,J'ai été victime d'un coup monté.,Meggyanúsítottak.,Mi hanno incastrato.,私は無実だ。,저는 누명을 썼어요.,Ik werd erin geluisd.,Jeg ble lurt i en felle.,Zostałem wrobiony.,Eu caí numa cilada.,,Am fost înscenat.,Меня подставили.,,Jag blev lurad.,Bana komplo kuruldu. +Harris said that I was plotting to kill the Governor. I would never harm a soul.,TXT_DLG_SCRIPT32_D4548_HARRI,〃,,,"Harris řekl, že jsem prý měl v plánu zavraždit guvernéra. Ani mouše bych neublížil.","Harris sagde, at jeg planlagde at dræbe guvernøren. Jeg ville aldrig skade nogen.","Harris hat erzählt, das ich plante den Gouverneur zu ermorden. Ich könnte keiner Menschenseele etwas antun.",,"Harriso diris, ke mi planas mortigi la registon. Mi neniam vundus iun.","Harris dijo que yo estaba planeando matar al gobernador, y yo no podría hacerle nada a nadie.",,Harris väitti minun juonineen kuvernöörin salamurhaa. En ikinä satuttaisi ketään.,Harris a dit que j'avais un plan pour tuer le gouverneur. Je ne ferais pas de mal à qui que ce soit.,"Harris azt nyilatkozta, hogy a kormányzó életére akarok törni. Egy légynek sem ártanék.",Harris ha detto che progettavo di uccidere il governatore. Ma io non farei mai del male a nessuno.,"ハリスに知事の暗殺を企てていると言われた。 +そんなこと心にも思ったことは無いのに。","해리스가 말하길, 제가 총독 암살을 꾀했데요. 난 파리 한마리도 못 죽이는데...",Harris zei dat ik van plan was om de gouverneur te vermoorden. Ik zou nooit een ziel kwaad doen.,Harris sa at jeg planla å drepe guvernøren. Jeg ville aldri skade noen.,"Harris powiedział, że spiskowałem, by zabić gubernatora. Nigdy nie skrzywdziłbym żadnej duszy.",O Harris disse que eu estava planejando matar o Governador. Eu nunca faria mal a qualquer pessoa.,,Harris a spus că plănuiam să-l omor pe Guvernator. N-aș răni un suflet niciodată.,"Харрис сказал, что я замышлял убийство губернатора. А я и мухи не обижу!",,Harris sa att jag planerade att döda guvernören. Jag skulle aldrig skada en själ.,"Harris, Vali'yi öldürmeyi planladığımı söyledi. Kimseye zarar vermem." +Be careful out there.,TXT_DLG_SCRIPT33_D0_BECAR,,,,Buď tam venku opatrný.,Vær forsigtig derude.,Sei vorsichtig dort draußen.,,Agu singarde tie ekstere.,Ten cuidado ahí fuera.,Ten cuidado ahí afuera.,Pidä itsestäsi huoli.,Faites attention à vous.,Légy óvatos odakint.,Stai attento là fuori.,外は気をつけろ。,조심해.,Wees voorzichtig daarbuiten.,Vær forsiktig der ute.,Bądź ostrożny.,Tome cuidado por aí.,,Ai grijă pe-acolo.,Будь поосторожнее.,,Var försiktig där ute.,Dışarıda dikkatli ol. "Say friend, I'll help you, if you help me. Give me 5 gold and I'll tell you what I know.",TXT_DLG_SCRIPT33_D1516_SAYFR,MAP33: Guy next to Norwall Prison.,,,"Poslyš, příteli, pomůžu ti, když ti pomůžeš mě. Dej mi pět zlatých a já ti řeknu, co vím.","Sig ven, jeg vil hjælpe dig, hvis du hjælper mig. Giv mig 5 guld, så fortæller jeg dig, hvad jeg ved.","Sag, mein Freund. Ich helfe dir, wenn du mir hilst. Gib mir 5 Gold und ich sage dir was ich weiß.",,"Nu, amiko, mi helpos vin se vi helpas min. Donu 5 da oro kaj mi diros tion, kion mi scias.","A ver, amigo, te ayudo si tú me ayudas. Dame 5 de oro y te digo lo que sé.",,"Hei kuule; voin auttaa sinua, jos autat minua. Viidestä kultakolikosta kerron sinulle, mitä tiedän.","Dites, l'ami. Je vous aide si vous m'aidez. Donnez moi 5 pièces et je vous dirais ce que je sais.","Figyelj barátom, segítek rajtad ha te is segítesz. Adj szépen 5 aranyat és elárulom amit tudok.","Senti qua, amico, io aiuterò te se tu aiuterai me. Dammi 5 pezzi d'oro e ti dirò tutto quello che so.","助けてくれるなら援助する。 -5ゴールドで知っている情報を全て教えよう","친구, 나는 너를 도와주고 싶어. 그러기 전에 나에게 5 골드를 줘. 그럼 내가 아는 걸 알려줄게.","Zeg vriend, ik zal je helpen, als je me helpt. Geef me 5 goud en ik zal je vertellen wat ik weet.","Jeg skal hjelpe deg, hvis du hjelper meg. Gi meg fem gull, så forteller jeg hva jeg vet.","Powiedz przyjacielu, pomogę ci, jeśli ty pomożesz mi. Daj mi 5 złotych, a powiem ci, co wiem.","Que tal, eu te ajudo se você me ajudar. Me dê 5 moedas de ouro e eu te digo o que eu sei.",,"Să zicem prietene, că te ajut, dacă și tu m-ajuți. Dă-mi 5 monezi și îți voi spune ce știu.","Дружище, я помогу тебе, если ты поможешь мне. Пять золотых, и я расскажу тебе всё, что знаю!",,"Dostum, sen bana yardım edersen ben de sana yardım ederim. Bana 5 altın ver, ben de sana bildiklerimi anlatayım." -Here's the gold.,TXT_RPLY0_SCRIPT33_D1516_HERES,〃,,,Tady máš to zlato.,Her er guldet.,Hier ist das Gold.,,Jen la oro.,Aquí tienes el oro.,,Tässä kulta.,Voilà votre argent.,Itt az arany.,Ecco l'oro.,金はこれだ。,여기 골드입니다.,Hier is het goud.,Her er gullet.,Oto złoto.,Tome estas moedas.,,Aici e aurul.,Вот монеты.,,İşte altın. +5ゴールドで知っている情報を全て教えよう","친구, 나는 너를 도와주고 싶어. 그러기 전에 나에게 5 골드를 줘. 그럼 내가 아는 걸 알려줄게.","Zeg vriend, ik zal je helpen, als je me helpt. Geef me 5 goud en ik zal je vertellen wat ik weet.","Jeg skal hjelpe deg, hvis du hjelper meg. Gi meg fem gull, så forteller jeg hva jeg vet.","Powiedz przyjacielu, pomogę ci, jeśli ty pomożesz mi. Daj mi 5 złotych, a powiem ci, co wiem.","Que tal, eu te ajudo se você me ajudar. Me dê 5 moedas de ouro e eu te digo o que eu sei.",,"Să zicem prietene, că te ajut, dacă și tu m-ajuți. Dă-mi 5 monezi și îți voi spune ce știu.","Дружище, я помогу тебе, если ты поможешь мне. Пять золотых, и я расскажу тебе всё, что знаю!",,"Säg vän, jag hjälper dig om du hjälper mig. Ge mig fem guld så berättar jag vad jag vet.","Dostum, sen bana yardım edersen ben de sana yardım ederim. Bana 5 altın ver, ben de sana bildiklerimi anlatayım." +Here's the gold.,TXT_RPLY0_SCRIPT33_D1516_HERES,〃,,,Tady máš to zlato.,Her er guldet.,Hier ist das Gold.,,Jen la oro.,Aquí tienes el oro.,,Tässä kulta.,Voilà votre argent.,Itt az arany.,Ecco l'oro.,金はこれだ。,여기 골드입니다.,Hier is het goud.,Her er gullet.,Oto złoto.,Tome estas moedas.,,Aici e aurul.,Вот монеты.,,Här är guldet.,İşte altın. "If you punch someone, you won't set off the alarms.",TXT_RYES0_SCRIPT33_D1516_IFYOU,〃,,,"Když někoho praštíš, nespustíš alarmy.","Hvis du slår nogen, vil du ikke udløse alarmen.","Wenn du jemanden schlägst, wirst du keinen Alarm auslösen.",,Piki iun ne ekagigas alarmojn.,"Acuchillar a alguien -no activa las alarmas.",,"Jos lyöt jotakuta nyrkillä, et laukaise hälyttimiä.","Si vous plantez quelqu'un avec votre dague de poing, vous n'activez pas les alarmes.","Ha behúzol valakinek, még nem indul be a riasztó.","Se usi i pugni, non attiverai l'allarme.",パンチならアラームを鳴らせることはない。,"만약 네가 누군가를 주먹으로 때린다면, 알람은 울리지 않을 거야.","Als je iemand slaat, zal je het alarm niet afgaan.","Hvis du slår noen, utløser du ikke alarmen.","Jeśli kogoś uderzysz, nie uruchomisz alarmów.","Se você der um soco em alguém, você não ativará os alarmes.",,"Dacă îi tragi un pumn cuiva, nu vei declanșa alarma.","Убивай холодным оружием, тогда ты не поднимешь тревогу.",,"Eğer birine yumruk atarsan, alarmları çalıştırmazsın." -I won't tell you anything for free!,TXT_RNO0_SCRIPT33_D1516_IWONT,〃,,,Zadarmo ti nic říkat nebudu!,Jeg vil ikke fortælle dig noget gratis!,Umsonst werde ich dir nichts sagen.,,Mi diros nenion senpage!,¡No te diré nada gratis!,¡No te voy a decir nada gratis!,En kerro mitään ilmaiseksi!,Je ne vous dirai rien gratuitement!,Nem árulok el ingyen semmit se!,Non ti dirò nulla se prima non vedo l'oro!,タダでは教えられないな!,무료로는 말 못 해!,Ik zal je niets gratis vertellen!,Jeg forteller deg ikke noe gratis!,Nie powiem ci nic za darmo!,Não te direi nada de graça!,,Nu-ți voi spune nimic pe gratis.,Бесплатно я не скажу ничего!,,Sana bedavaya bir şey söylemeyeceğim! -I've already told you what I know.,TXT_DLG_SCRIPT33_D3032_IVEAL,〃,,,"Už jsem ti řekl, co vím.","Jeg har allerede fortalt dig, hvad jeg ved.","Ich habe dir alles gesagt, was ich weiß.",,"Mi jam diris tion, kion mi scias.",Ya te he dicho lo que sé.,Ya te dije lo que sé.,"Olen jo kertonut sinulle, mitä tiedän.",Je vous ai dit tout ce que je sais.,Már elmondtam amit tudtam.,Ti ho già detto ciò che so.,俺が知っていることはこれで全部だ。,난 이미 내가 아는 걸 말해 줬어!,Ik heb je al verteld wat ik weet.,Jeg har allerede fortalt deg det jeg vet.,"Już ci powiedziałem, co wiem.",Já te disse o que eu sei.,,Ți-am spus deja tot ce știu.,"Я уже сказал тебе всё, что знал.",,Sana bildiklerimi anlattım zaten. -Hello friend. What can I get for you?,TXT_DLG_SCRIPT33_D4548_HELLO,MAP33: Weapons.,,,"Zdravím, příteli, co ti mohu nabídnout?","Hej, min ven. Hvad kan jeg få for dig?","Hallo, Freund, was kann ich dir geben?",,"Saluton, amiko. Kion mi donu al vi?","Hola, amigo. ¿Qué puedo ofrecerte?",,"Terve, ystävä; miten voin olla avuksi?","Bonjour, l'ami, que puis-je pour vous?",Üdvözöllek barátom. Mit tehetek érted?,"Salve, amico. Cosa posso procurarti?",どうも同士よ。何か必要か?,"안녕하십니까, 친구여. 구매하고 싶은 게 있습니까?",Hallo vriend. Wat kan ik voor je halen?,"Hei, min venn. Hva vil du ha?",Witaj przyjacielu. Co mogę dla ciebie zdobyć?,"Olá amigo, como posso te ajudar?",,"Bună prietene, ce pot să-ți aduc?",Здравствуй. Что-нибудь интересует?,,Merhaba dostum. Senin için ne yapabilirim? -Electric bolts,TXT_RPLY0_SCRIPT33_D4548_ELECT,〃,,,Elektrické šípy,Elektriske bolte,Elektrische Pfeile,,,Flechas eléctricas,,Sähkönuolia,Carreaux électriques.,Elektromos nyilak,Dardi elettrificati ,エレクトリック ボルト,전격 볼트,Elektrische bouten,Elektriske bolter.,Elektryczne śruby.,Setas elétricas,,Bolțuri electrice,Электрические болты,,Elektrikli cıvata. -One quarrel it is.,TXT_RYES0_SCRIPT33_D4548_ONEQU,〃,,,Jeden toulec.,Et skænderi bliver det.,Hier hast du sie.,,,Marchando unas flechas.,,"Tässä, olkaa hyvä.",Un carquois pour vous.,Itt is van.,Eccoli qua.,クォーレル一本だ。,잔소리 없이 주겠습니다.,Eén ruzie is het.,En krangel blir det.,Jedna kłótnia to jest.,Está na mão.,,Aici sunt.,Один колчан.,,Tek bir tartışma. -You're broke!,TXT_RNO0_SCRIPT33_D4548_YOURE,〃,,,Jseš švorc!,Du er flad!,Du bist pleite!,,Vi ne havas monon!,¡Estás sin blanca!,¡Estás quebrado!,Olet peeaa!,Vous êtes à sec!,Nincs is nálad pénz!,Sei sul lastrico!,スッカラカンじゃないか!,돈이 한 푼도 없는 것 같은데.,Je bent blut!,Du er blakk!,Jesteście spłukani!,Você está sem grana!,,Ești falit!,"Друг, да ты на мели!",,Beş parasızsın! -Clip of bullets,TXT_RPLY1_SCRIPT33_D4548_10ROU,〃,,,Zásobník s náboji,Et patron-klip,10-Kugeln-Magazin,,Magazenon,Un cargador,,Luotilipas,Chargeur de 10 cartouches.,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler,Klips z kulami.,Carregador de balas,,Cartuș de gloanțe,Обойма патронов,,Mermi şarjörü -Here's your ammo,TXT_RYES1_SCRIPT33_D4548_HERES,〃,,,Tady je tvá munice.,Her er din ammunition,Hier ist deine Munition.,,,Aquí tienes tu munición.,,Tässä panoksesi.,Voilà vos balles.,Itt a töltényed.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 탄약입니다.,Hier is je munitie....,Her er ammunisjonen din,Oto twoja amunicja.,Aqui está a sua munição.,,Aici e.,Вот твои патроны.,,İşte cephaneniz. -"Sorry, no money, no bullets.",TXT_RNO1_SCRIPT33_D4548_SORRY,〃,,,"Promiň. Žádné peníze, žádné náboje.","Beklager, ingen penge, ingen kugler.","Tut mir leid. Kein Geld, keine Munition.",,Pardonon. Sen mono ne estas kugloj.,"Lo siento, sin dinero, no hay balas.",,"Valitan, ei rahaa, ei luoteja.","Désolé, pas d'argent, pas de munitions.","Ha nincs pénz, nincs töltény.","Mi spiace, niente soldi, niente munizioni.",悪いが、金が無ければブツも無しだ。,돈 없으면 거래 못 합니다.,"Sorry, geen geld, geen kogels.","Beklager, ingen penger, ingen kuler.","Niestety, nie ma pieniędzy, nie ma naboi.","Desculpe. Sem grana, sem balas.",,"Scuze, niciun ban, niciun glonț.","Извини, нет денег — нет патронов!",,"Üzgünüm, para yoksa mermi de yok." -Ammo box,TXT_RPLY2_SCRIPT33_D4548_50ROU,〃,,,Krabici nábojů,Ammo kasse,50-Kugeln-Schachtel,,Municikesto,Caja de municiones,,Luotilaatikko,Boîte de 50 balles.,Töltény doboz,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitiedoos,Ammunisjonsboks,Skrzynka z amunicją.,Caixa de munição,,Cutie cu muniție,Коробка патронов,,Cephane kutusu -Here you go,TXT_RYES2_SCRIPT33_D4548_HEREY,〃,,,Tu máš.,Værsgo.,Bitteschön.,,Jen,Aquí tienes,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,どうぞ。,거래 감사드립니다.,Alsjeblieft,Vær så god.,Proszę bardzo.,Aqui está,,Aici este,Держи.,,Al bakalım. -You don't have enough gold!,TXT_RNO2_SCRIPT33_D4548_YOUDO,〃,,,Nemáš dost zlaťáků!,Du har ikke nok guld!,Du hast nicht genug Gold.,,Vi ne havas sufiĉe da oro!,¡No tienes suficiente oro!,,Sinulla ei ole riittävästi kultaa!,Vous n'avez pas assez d'argent.,Nincs elég aranyad.,Non hai abbastanza oro!,十分な額じゃない,골드가 충분치 않군요!,Je hebt niet genoeg goud!,Du har ikke nok gull!,Nie masz wystarczająco dużo złota!,Você não tem ouro suficiente!,,Nu ai suficient aur!,У тебя недостаточно золота!,,Yeterince altının yok! -Ammo satchel,TXT_RPLY3_SCRIPT33_D4548_AMMOS,〃,,,Brašnu na munici,Ammotaske,Munitionstasche.,,,Mochila de municiones,,Ammuslaukku,Sacoche de munitions.,Lőszeres hátizsák,Sacca di munizioni,弾薬鞄,탄약 배낭,Munitie tasje,Ammunisjonsveske,Torba na amunicję,Mochila de munição,,Sac cu muniție,Ранец для боеприпасов,,Cephane çantası -"Thank you, anything else?",TXT_RYES3_SCRIPT33_D4548_THANK,〃,,,Děkuji. Něco dalšího?,"Tak, er der andet?","Danke, sonst noch was?",,,Gracias. ¿Algo más?,,Kiitos; vielä jotain muuta?,"Merci, quelque chose d'autre?","Köszönöm, még valami esetleg?","Grazie, serve qualcos'altro?",ありがとう。 他に何か?,좋습니다! 더 필요한 거라도?,"Bedankt, nog iets anders?","Takk, noe mer?","Dziękuję, coś jeszcze?",Obrigado. Mais alguma coisa?,,"Merci, altceva?",Благодарю. Что-нибудь ещё?,,"Teşekkürler, başka bir şey var mı?" -"You can't afford that, good day.",TXT_RNO3_SCRIPT33_D4548_YOUCA,〃,,,"To si nemůžeš dovolit, přeji hezký den.","Det har du ikke råd til, god dag.",Das kannst du dir nicht leisten. Guten Tag.,,,"No te alcanza. -¡Ten un buen día!",,Sinulla ei ole siihen varaa; hyvää päivänjatkoa.,Vous ne pouvez pas l'acheter. Au revoir.,"Erre neked nem tellik, szép napot.","Non te la puoi permettere, buona giornata.",それを買える余裕は無い、また今度。,제공할 수 없습니다. 유감이군요.,"Dat kan je je niet betalen, goede dag.",Det har du ikke råd til. Adjø.,"Nie stać cię na to, dzień dobry.",Você não pode comprar isto. Tenha um bom dia.,,"Nu ai bani, ziua bună.",У тебя не хватает денег. Всего доброго!,,"Bunu karşılayamazsın, iyi günler." -Welcome. What may I show you?,TXT_DLG_SCRIPT33_D6064_WELCO,MAP33: Armory,,,Vítej. Co bych ti mohl nabídnout?,Velkommen. Hvad må jeg vise dig?,Willkommen. Was darf ich dir zeigen?,,Bonvenon. Kion mi montru al vi?,Bienvenido. ¿Qué puedo mostrarte?,,Tervetuloa. Mitä voin teille esitellä?,"Bienvenue, comment puis-je vous servir?",Üdvözöllek barátom. Mit tehetek érted?,Benvenuto. Cosa posso farti vedere?,ようこそ、何を見ていきますか?,어서 오세요! 무엇이 필요한지?,Welkom. Wat kan ik je laten zien?,Velkommen. Hva kan jeg vise deg?,Witam. Co mogę ci pokazać?,Seja bem-vindo. O que posso lhe mostrar?,,Bună. Cu ce te pot ajuta?,Здравствуй. Что-нибудь интересует?,,Hoş geldiniz. Size ne gösterebilirim? -Environmental suit,TXT_RPLY0_SCRIPT33_D6064_ENVIR,〃,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje de protección ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védő ruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Miljødrakt,Kombinezon ekologiczny,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитный костюм,,Çevre kıyafeti. -Here you are.,TXT_RYES0_SCRIPT33_D6064_HEREY,〃,,,"Tak, tady to je.",Værsgo.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Parancsolj.,Ecco a te.,はい、これをどうぞ。,받으세요!,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici e.,"Хорошо, бери.",,Al bakalım. -You don't have enough money for that.,TXT_RNO0_SCRIPT33_D6064_YOUDO,〃,,,Na to nemáš dost peněz.,Du har ikke penge nok til det.,Dafür hast du nicht genug Geld.,,Vi ne havas sufiĉe da mono.,No tienes suficiente dinero.,,Teillä ei ole tarpeeksi rahaa sitä varten.,Vous n'avez pas assez d'argent.,"Sajnálom, de Önnek nem áll módjában kifizetni ezt.",Non hai abbastanza soldi per questo.,すみませんが、貴方は十分なお金を持っていません。,돈이 충분치 않아요.,Daar heb je niet genoeg geld voor.,Du har ikke nok penger til det.,Nie masz na to pieniędzy.,Você não tem dinheiro o suficiente para isto.,,N-ai suficienți bani.,"Извини, но у тебя не хватает денег.",,Bunun için yeterli paran yok. -Leather armor.,TXT_RPLY1_SCRIPT33_D6064_LEATH,〃,,Leather armour,Kožené brnění,Læder rustning.,Lederrüstung,,Ledan armaĵon.,Armadura de cuero.,,Nahkasuojus,Armure de cuir.,Bőr vért.,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Lær rustning,Skórzana zbroja.,Armadura de couro.,,Armură de piele.,Кожаная броня,,Deri zırh. -Here you are.,TXT_RYES1_SCRIPT33_D6064_HEREY,〃,,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Aquí tienes.,,Olkaa hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,これをどうぞ。,딱 맞는 치수의 갑옷이죠.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici e.,Держи.,,Al bakalım. -Perhaps some other time?,TXT_RNO1_SCRIPT33_D6064_PERHA,〃,,,Možná někdy jindy?,Måske en anden gang?,Vielleicht ein anderes Mal?,,Ĉu eble alian fojon?,¿Quizás en otra ocasión?,¿Tal vez en otra ocasión?,Ehkä jokin toinen kerta?,Peut être une autre fois?,Talán később?,Magari un'altra volta?,また別の機会に?,아마 나중에 사야겠는데요?,Misschien een andere keer?,Kanskje en annen gang?,Może innym razem?,Talvez outra hora?,,Poate altădată?,"Может, в следующий раз?",,Belki başka bir zaman? -Metal armor,TXT_RPLY2_SCRIPT33_D6064_METAL,〃,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metallrustning.,Metalowa zbroja,Armadura de metal,,Armură de metal,Металлическая броня,,Metal zırh. -Wear it in good health.,TXT_RYES2_SCRIPT33_D6064_WEARI,〃,,,Nos ho ve zdraví.,Bær den ved godt helbred.,Trage sie und bleib gesund.,,Ĝuu ĝin.,Disfrútala.,,Pitäköön asu teidät terveenä.,Portez-la en bonne santé.,Használd egészséggel.,Che possa esserti utile!,着ると安心しますよ。,건강하게 착용하십시오.,Draag het in goede gezondheid.,Bruk den ved god helse.,Noś ją w dobrym zdrowiu.,Vista com orgulho.,,Să o porți sănătos.,Носи на здоровье.,,Sağlıkla giy. +no activa las alarmas.",,"Jos lyöt jotakuta nyrkillä, et laukaise hälyttimiä.","Si vous plantez quelqu'un avec votre dague de poing, vous n'activez pas les alarmes.","Ha behúzol valakinek, még nem indul be a riasztó.","Se usi i pugni, non attiverai l'allarme.",パンチならアラームを鳴らせることはない。,"만약 네가 누군가를 주먹으로 때린다면, 알람은 울리지 않을 거야.","Als je iemand slaat, zal je het alarm niet afgaan.","Hvis du slår noen, utløser du ikke alarmen.","Jeśli kogoś uderzysz, nie uruchomisz alarmów.","Se você der um soco em alguém, você não ativará os alarmes.",,"Dacă îi tragi un pumn cuiva, nu vei declanșa alarma.","Убивай холодным оружием, тогда ты не поднимешь тревогу.",,Om du slår någon så kommer du inte att utlösa larmet.,"Eğer birine yumruk atarsan, alarmları çalıştırmazsın." +I won't tell you anything for free!,TXT_RNO0_SCRIPT33_D1516_IWONT,〃,,,Zadarmo ti nic říkat nebudu!,Jeg vil ikke fortælle dig noget gratis!,Umsonst werde ich dir nichts sagen.,,Mi diros nenion senpage!,¡No te diré nada gratis!,¡No te voy a decir nada gratis!,En kerro mitään ilmaiseksi!,Je ne vous dirai rien gratuitement!,Nem árulok el ingyen semmit se!,Non ti dirò nulla se prima non vedo l'oro!,タダでは教えられないな!,무료로는 말 못 해!,Ik zal je niets gratis vertellen!,Jeg forteller deg ikke noe gratis!,Nie powiem ci nic za darmo!,Não te direi nada de graça!,,Nu-ți voi spune nimic pe gratis.,Бесплатно я не скажу ничего!,,Jag kommer inte att berätta något gratis!,Sana bedavaya bir şey söylemeyeceğim! +I've already told you what I know.,TXT_DLG_SCRIPT33_D3032_IVEAL,〃,,,"Už jsem ti řekl, co vím.","Jeg har allerede fortalt dig, hvad jeg ved.","Ich habe dir alles gesagt, was ich weiß.",,"Mi jam diris tion, kion mi scias.",Ya te he dicho lo que sé.,Ya te dije lo que sé.,"Olen jo kertonut sinulle, mitä tiedän.",Je vous ai dit tout ce que je sais.,Már elmondtam amit tudtam.,Ti ho già detto ciò che so.,俺が知っていることはこれで全部だ。,난 이미 내가 아는 걸 말해 줬어!,Ik heb je al verteld wat ik weet.,Jeg har allerede fortalt deg det jeg vet.,"Już ci powiedziałem, co wiem.",Já te disse o que eu sei.,,Ți-am spus deja tot ce știu.,"Я уже сказал тебе всё, что знал.",,Jag har redan berättat vad jag vet.,Sana bildiklerimi anlattım zaten. +Hello friend. What can I get for you?,TXT_DLG_SCRIPT33_D4548_HELLO,MAP33: Weapons.,,,"Zdravím, příteli, co ti mohu nabídnout?","Hej, min ven. Hvad kan jeg få for dig?","Hallo, Freund, was kann ich dir geben?",,"Saluton, amiko. Kion mi donu al vi?","Hola, amigo. ¿Qué puedo ofrecerte?",,"Terve, ystävä; miten voin olla avuksi?","Bonjour, l'ami, que puis-je pour vous?",Üdvözöllek barátom. Mit tehetek érted?,"Salve, amico. Cosa posso procurarti?",どうも同士よ。何か必要か?,"안녕하십니까, 친구여. 구매하고 싶은 게 있습니까?",Hallo vriend. Wat kan ik voor je halen?,"Hei, min venn. Hva vil du ha?",Witaj przyjacielu. Co mogę dla ciebie zdobyć?,"Olá amigo, como posso te ajudar?",,"Bună prietene, ce pot să-ți aduc?",Здравствуй. Что-нибудь интересует?,,"Hej, min vän. Vad kan jag få för dig?",Merhaba dostum. Senin için ne yapabilirim? +Electric bolts,TXT_RPLY0_SCRIPT33_D4548_ELECT,〃,,,Elektrické šípy,Elektriske bolte,Elektrische Pfeile,,Elektrajn sagojn,Flechas eléctricas,,Sähkönuolia,Carreaux électriques.,Elektromos nyilak,Dardi elettrificati ,エレクトリック ボルト,전격 볼트,Elektrische bouten,Elektriske bolter.,Elektryczne śruby.,Setas elétricas,,Bolțuri electrice,Электрические болты,,Elektriska bultar,Elektrikli cıvata. +One quarrel it is.,TXT_RYES0_SCRIPT33_D4548_ONEQU,〃,,,Jeden toulec.,Et skænderi bliver det.,Hier hast du sie.,,Jen sagoj.,Salen unas flechas.,,"Tässä, olkaa hyvä.",Un carquois pour vous.,Itt is van.,Eccoli qua.,クォーレル一本だ。,잔소리 없이 주겠습니다.,Eén ruzie is het.,En krangel blir det.,Jedna kłótnia to jest.,Está na mão.,,Aici sunt.,Один колчан.,,Ett gräl blir det.,Tek bir tartışma. +You're broke!,TXT_RNO0_SCRIPT33_D4548_YOURE,〃,,,Jseš švorc!,Du er flad!,Du bist pleite!,,Vi ne havas monon!,¡Estás sin blanca!,¡No traes dinero!,Olet peeaa!,Vous êtes à sec!,Nincs is nálad pénz!,Sei sul lastrico!,スッカラカンじゃないか!,돈이 한 푼도 없는 것 같은데.,Je bent blut!,Du er blakk!,Jesteście spłukani!,Você está sem grana!,,Ești falit!,"Друг, да ты на мели!",,Du är pank!,Beş parasızsın! +Clip of bullets,TXT_RPLY1_SCRIPT33_D4548_10ROU,〃,,,Zásobník s náboji,Et patron-klip,10-Kugeln-Magazin,,Magazenon,Un cargador,,Luotilipas,Chargeur de 10 cartouches.,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Et magasin med kuler,Klips z kulami.,Carregador de balas,,Cartuș de gloanțe,Обойма патронов,,Klockan med kulor.,Mermi şarjörü +Here's your ammo,TXT_RYES1_SCRIPT33_D4548_HERES,〃,,,Tady je tvá munice.,Her er din ammunition,Hier ist deine Munition.,,Jen via municio.,Aquí tienes tu munición.,,Tässä panoksesi.,Voilà vos balles.,Itt a töltényed.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 탄약입니다.,Hier is je munitie....,Her er ammunisjonen din,Oto twoja amunicja.,Aqui está a sua munição.,,Aici e.,Вот твои патроны.,,Här är din ammunition.,İşte cephaneniz. +"Sorry, no money, no bullets.",TXT_RNO1_SCRIPT33_D4548_SORRY,〃,,,"Promiň. Žádné peníze, žádné náboje.","Beklager, ingen penge, ingen kugler.","Tut mir leid. Kein Geld, keine Munition.",,"Pardonon. Sen mono +ne estas kugloj.","Lo siento, sin dinero +no hay balas.",,"Valitan, ei rahaa, ei luoteja.","Désolé, pas d'argent, pas de munitions.","Ha nincs pénz, nincs töltény.","Mi spiace, niente soldi, niente munizioni.",悪いが、金が無ければブツも無しだ。,돈 없으면 거래 못 합니다.,"Sorry, geen geld, geen kogels.","Beklager, ingen penger, ingen kuler.","Niestety, nie ma pieniędzy, nie ma naboi.","Desculpe. Sem grana, sem balas.",,"Scuze, niciun ban, niciun glonț.","Извини, нет денег — нет патронов!",,"Tyvärr, inga pengar, inga kulor.","Üzgünüm, para yoksa mermi de yok." +Ammo box,TXT_RPLY2_SCRIPT33_D4548_50ROU,〃,,,Krabici nábojů,Ammo kasse,50-Kugeln-Schachtel,,Munici-keston,Caja de municiones,,Luotilaatikko,Boîte de 50 balles.,Töltény doboz,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitiedoos,Ammunisjonsboks,Skrzynka z amunicją.,Caixa de munição,,Cutie cu muniție,Коробка патронов,,Ammunitionslåda,Cephane kutusu +Here you go,TXT_RYES2_SCRIPT33_D4548_HEREY,〃,,,Tu máš.,Værsgo.,Bitteschön.,,Jen,Aquí tienes,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,どうぞ。,거래 감사드립니다.,Alsjeblieft,Vær så god.,Proszę bardzo.,Aqui está,,Aici este,Держи.,,Varsågod.,Al bakalım. +You don't have enough gold!,TXT_RNO2_SCRIPT33_D4548_YOUDO,〃,,,Nemáš dost zlaťáků!,Du har ikke nok guld!,Du hast nicht genug Gold.,,Vi ne havas sufiĉe da oro!,¡No tienes suficiente oro!,,Sinulla ei ole riittävästi kultaa!,Vous n'avez pas assez d'argent.,Nincs elég aranyad.,Non hai abbastanza oro!,十分な額じゃない,골드가 충분치 않군요!,Je hebt niet genoeg goud!,Du har ikke nok gull!,Nie masz wystarczająco dużo złota!,Você não tem ouro suficiente!,,Nu ai suficient aur!,У тебя недостаточно золота!,,Du har inte tillräckligt med guld!,Yeterince altının yok! +Ammo satchel,TXT_RPLY3_SCRIPT33_D4548_AMMOS,〃,,,Brašnu na munici,Ammotaske,Munitionstasche.,,Munici-sakon,Mochila de municiones,,Ammuslaukku,Sacoche de munitions.,Lőszeres hátizsák,Sacca di munizioni,弾薬鞄,탄약 배낭,Munitie tasje,Ammunisjonsveske,Torba na amunicję,Mochila de munição,,Sac cu muniție,Ранец боеприпасов,,Ammunitionsväska,Cephane çantası +"Thank you, anything else?",TXT_RYES3_SCRIPT33_D4548_THANK,〃,,,Děkuji. Něco dalšího?,"Tak, er der andet?","Danke, sonst noch was?",,Dankon. Ĉu ion alian?,Gracias. ¿Algo más?,,Kiitos; vielä jotain muuta?,"Merci, quelque chose d'autre?","Köszönöm, még valami esetleg?","Grazie, serve qualcos'altro?",ありがとう。 他に何か?,좋습니다! 더 필요한 거라도?,"Bedankt, nog iets anders?","Takk, noe mer?","Dziękuję, coś jeszcze?",Obrigado. Mais alguma coisa?,,"Merci, altceva?",Благодарю. Что-нибудь ещё?,,"Tack, något annat?","Teşekkürler, başka bir şey var mı?" +"You can't afford that, good day.",TXT_RNO3_SCRIPT33_D4548_YOUCA,〃,,,"To si nemůžeš dovolit, přeji hezký den.","Det har du ikke råd til, god dag.",Das kannst du dir nicht leisten. Guten Tag.,,"Vi ne povas sen mono. +Havu bonan tagon!","No te alcanza. +¡Ten un buen día!",,Sinulla ei ole siihen varaa; hyvää päivänjatkoa.,Vous ne pouvez pas l'acheter. Au revoir.,"Erre neked nem tellik, szép napot.","Non te la puoi permettere, buona giornata.",それを買える余裕は無い、また今度。,제공할 수 없습니다. 유감이군요.,"Dat kan je je niet betalen, goede dag.",Det har du ikke råd til. Adjø.,"Nie stać cię na to, dzień dobry.",Você não pode comprar isto. Tenha um bom dia.,,"Nu ai bani, ziua bună.",У тебя не хватает денег. Всего доброго!,,"Du har inte råd med det, god dag.","Bunu karşılayamazsın, iyi günler." +Welcome. What may I show you?,TXT_DLG_SCRIPT33_D6064_WELCO,MAP33: Armory,,,Vítej. Co bych ti mohl nabídnout?,Velkommen. Hvad må jeg vise dig?,Willkommen. Was darf ich dir zeigen?,,Bonvenon. Kion mi montru al vi?,Bienvenido. ¿Qué puedo mostrarte?,,Tervetuloa. Mitä voin teille esitellä?,"Bienvenue, comment puis-je vous servir?",Üdvözöllek barátom. Mit tehetek érted?,Benvenuto. Cosa posso farti vedere?,ようこそ、何を見ていきますか?,어서 오세요! 무엇이 필요한지?,Welkom. Wat kan ik je laten zien?,Velkommen. Hva kan jeg vise deg?,Witam. Co mogę ci pokazać?,Seja bem-vindo. O que posso lhe mostrar?,,Bună. Cu ce te pot ajuta?,Здравствуй. Что-нибудь интересует?,,Välkommen. Vad får jag visa dig?,Hoş geldiniz. Size ne gösterebilirim? +Environmental suit,TXT_RPLY0_SCRIPT33_D6064_ENVIR,〃,,,Ochranný oblek,Miljødragt,Schutzanzug.,,Medi-ŝirman veston,Traje NBQ,,Ympäristösuojapuku,Combinaison Hazmat.,Védő ruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Miljødrakt,Kombinezon ekologiczny,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитный костюм,,Miljödräkt,Çevre kıyafeti. +Here you are.,TXT_RYES0_SCRIPT33_D6064_HEREY,〃,,,"Tak, tady to je.",Værsgo.,Bitteschön.,,Jen.,Toma.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Parancsolj.,Ecco a te.,はい、これをどうぞ。,받으세요!,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici e.,"Хорошо, бери.",,Varsågod.,Al bakalım. +You don't have enough money for that.,TXT_RNO0_SCRIPT33_D6064_YOUDO,〃,,,Na to nemáš dost peněz.,Du har ikke penge nok til det.,Dafür hast du nicht genug Geld.,,Vi ne havas sufiĉe da mono.,No tienes suficiente dinero.,,Teillä ei ole tarpeeksi rahaa sitä varten.,Vous n'avez pas assez d'argent.,"Sajnálom, de Önnek nem áll módjában kifizetni ezt.",Non hai abbastanza soldi per questo.,すみませんが、貴方は十分なお金を持っていません。,돈이 충분치 않아요.,Daar heb je niet genoeg geld voor.,Du har ikke nok penger til det.,Nie masz na to pieniędzy.,Você não tem dinheiro o suficiente para isto.,,N-ai suficienți bani.,"Извини, но у тебя не хватает денег.",,Du har inte tillräckligt med pengar för det.,Bunun için yeterli paran yok. +Leather armor.,TXT_RPLY1_SCRIPT33_D6064_LEATH,〃,,Leather armour,Kožené brnění,Læder rustning.,Lederrüstung,,Ledan armaĵon.,Armadura de cuero.,,Nahkasuojus,Armure de cuir.,Bőr vért.,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Lær rustning,Skórzana zbroja.,Armadura de couro.,,Armură de piele.,Кожаная броня,,Läderrustning.,Deri zırh. +Here you are.,TXT_RYES1_SCRIPT33_D6064_HEREY,〃,,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Toma.,,Olkaa hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,これをどうぞ。,딱 맞는 치수의 갑옷이죠.,Hier ben je dan.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici e.,Держи.,,Här är den.,Al bakalım. +Perhaps some other time?,TXT_RNO1_SCRIPT33_D6064_PERHA,〃,,,Možná někdy jindy?,Måske en anden gang?,Vielleicht ein anderes Mal?,,Ĉu eble alian fojon?,¿Quizás en otra ocasión?,¿Tal vez en otra ocasión?,Ehkä jokin toinen kerta?,Peut être une autre fois?,Talán később?,Magari un'altra volta?,また別の機会に?,아마 나중에 사야겠는데요?,Misschien een andere keer?,Kanskje en annen gang?,Może innym razem?,Talvez outra hora?,,Poate altădată?,"Может, в следующий раз?",,Kanske en annan gång?,Belki başka bir zaman? +Metal armor,TXT_RPLY2_SCRIPT33_D6064_METAL,〃,,Metal armour,Kovové brnění,Metal rustning,Metallrüstung,,Metalan armaĵon,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metallrustning.,Metalowa zbroja,Armadura de metal,,Armură de metal,Металлическая броня,,Metallrustning.,Metal zırh. +Wear it in good health.,TXT_RYES2_SCRIPT33_D6064_WEARI,〃,,,Nos ho ve zdraví.,Bær den ved godt helbred.,Trage sie und bleib gesund.,,Ĝuu ĝin.,Disfrútala.,,Pitäköön asu teidät terveenä.,Portez-la en bonne santé.,Használd egészséggel.,Che possa esserti utile!,着ると安心しますよ。,건강하게 착용하십시오.,Draag het in goede gezondheid.,Bruk den ved god helse.,Noś ją w dobrym zdrowiu.,Vista com orgulho.,,Să o porți sănătos.,Носи на здоровье.,,Bär den vid god hälsa.,Sağlıkla giy. Come back when you can afford it.,TXT_RNO2_SCRIPT33_D6064_COMEB,〃,,,"Vrať se, až si to budeš moct dovolit.","Kom tilbage, når du har råd til det.","Komme wieder, wenn du dir sie leisten kannst.",,"Revenu kiam vi povos aĉeti ĝin.","Vuelve cuando -puedas comprarla.",,"Palataan asiaa, kun teillä on siihen varaa.",Revenez quand vous pouvez l'acheter.,Gyere vissza ha tellik rá.,Ritorna quando potrai permettertela.,余裕がある時にまた。,돈이 좀 있을때 다시 찾아와주세요.,Kom terug wanneer je het je kunt veroorloven.,Kom tilbake når du har råd.,"Wróć, gdy będzie cię na to stać.",Volte quando puder comprar.,,Întoarce-te când ai destui bani!,"Вернёшься, когда поднакопишь на то, что хочешь!",,Paranız yettiğinde geri gelin. -How may I assist you?,TXT_DLG_SCRIPT33_D7580_HOWMA,MAP33: Hospital,,,Jak ti mohu pomoci?,Hvordan kan jeg hjælpe dig?,Womit kann ich dienen?,,Kiel mi helpu vin?,¿Cómo puedo ayudarte?,,Miten voin teitä avustaa?,Comment puis-je vous aider aujourd'hui?,Miben lehetek a segítségedre?,Come posso aiutarti?,何かお困りですか?,반갑습니다. 어떻게 도와드릴까요?,Hoe kan ik u helpen?,Hvordan kan jeg hjelpe deg?,Jak mogę ci pomóc?,Como posso ajudá-lo?,,Cu ce te pot ajuta?,Чем могу помочь?,,Size nasıl yardımcı olabilirim? -Med patch,TXT_RPLY0_SCRIPT33_D7580_MEDPA,〃,,,Obvazy,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekääre,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster,Bandaż,Compressa médica,,Bandaj medical,Бинтами,,Tıbbi yama -Here's your patch kit.,TXT_RYES0_SCRIPT33_D7580_HERES,〃,,,Tady je tvůj obvaz.,Her er dit patch-kit.,Hier ist deine Bandage.,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä käärepakettisi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これをどうぞ。,저렴한 가격의 의료 붕대입니다.,Hier is je patch.,Her er lappesettet ditt.,Oto twój bandaż.,Aqui está a sua compressa,,Aici este.,Вот они.,,İşte yama setiniz. -You need 10 gold for that.,TXT_RNO0_SCRIPT33_D7580_YOUNE,〃,,,Na ty potřebuješ deset zlatých.,Du skal bruge 10 guld for det.,Dafür brauchst du 10 Gold.,,Vi bezonas 10 da oro.,Necesitas 10 de oro.,,Tarvitset sitä varten 10 kolikkoa.,Il vous faut 10 pièces pour ça.,10 aranyba kerül.,Ti servono 10 pezzi d'oro per quello.,10 ゴールド必要です。,10 골드입니다. 설마 이 만한 양의 돈이 없으신가요?,Daar heb je 10 goud voor nodig.,Du trenger 10 gull for det.,Potrzebujesz na to 10 złota.,Você precisa de 10 moedas para isto.,,Ai nevoie de 10 monezi pentru aia.,Тебе не хватает 10 золотых.,,Bunun için 10 altına ihtiyacın var. -Field surgery kit,TXT_RPLY1_SCRIPT33_D7580_FIELD,〃,,,Lékárničku,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Kirurgisett,Zestaw do chirurgii polowej,Kit de cirurgia,,Kit chirurgical de teren.,Аптечкой,,Saha ameliyat kiti -Thank you.,TXT_RYES1_SCRIPT33_D7580_THANK,〃,,,Děkuji.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitoksia,Merci.,Köszönöm.,Grazie.,ありがとうございます。,말 없이 주겠습니다. 거래 고마워요!,Bedankt.,Takk skal du ha.,Dziękuję.,Obrigado.,,Merci.,Спасибо.,,Teşekkür ederim. +puedas comprarla.",,"Palataan asiaa, kun teillä on siihen varaa.",Revenez quand vous pouvez l'acheter.,Gyere vissza ha tellik rá.,Ritorna quando potrai permettertela.,余裕がある時にまた。,돈이 좀 있을때 다시 찾아와주세요.,Kom terug wanneer je het je kunt veroorloven.,Kom tilbake når du har råd.,"Wróć, gdy będzie cię na to stać.",Volte quando puder comprar.,,Întoarce-te când ai destui bani!,"Вернёшься, когда поднакопишь на то, что хочешь!",,Kom tillbaka när du har råd.,Paranız yettiğinde geri gelin. +How may I assist you?,TXT_DLG_SCRIPT33_D7580_HOWMA,MAP33: Hospital,,,Jak ti mohu pomoci?,Hvordan kan jeg hjælpe dig?,Womit kann ich dienen?,,Kiel mi helpu vin?,¿Cómo puedo ayudarte?,,Miten voin teitä avustaa?,Comment puis-je vous aider aujourd'hui?,Miben lehetek a segítségedre?,Come posso aiutarti?,何かお困りですか?,반갑습니다. 어떻게 도와드릴까요?,Hoe kan ik u helpen?,Hvordan kan jeg hjelpe deg?,Jak mogę ci pomóc?,Como posso ajudá-lo?,,Cu ce te pot ajuta?,Чем могу помочь?,,Hur kan jag hjälpa dig?,Size nasıl yardımcı olabilirim? +Med patch,TXT_RPLY0_SCRIPT33_D7580_MEDPA,〃,,,Obvazy,Medicinsk plaster,Medizinische Bandage,,Kuracbendoj,Tiritas,Curitas,Sidekääre,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Medisinplaster,Bandaż,Compressa médica,,Bandaj medical,Бинтами,,Medicinsk plåster,Tıbbi yama +Here's your patch kit.,TXT_RYES0_SCRIPT33_D7580_HERES,〃,,,Tady je tvůj obvaz.,Her er dit patch-kit.,Hier ist deine Bandage.,,Jen viaj kuracbendoj,Aquí tienes tus tiritas.,Aquí tienes tus curitas.,Tässä käärepakettisi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これをどうぞ。,저렴한 가격의 의료 붕대입니다.,Hier is je patch.,Her er lappesettet ditt.,Oto twój bandaż.,Aqui está a sua compressa,,Aici este.,Вот они.,,Her er dit plaster.,İşte yama setiniz. +You need 10 gold for that.,TXT_RNO0_SCRIPT33_D7580_YOUNE,〃,,,Na ty potřebuješ deset zlatých.,Du skal bruge 10 guld for det.,Dafür brauchst du 10 Gold.,,Vi bezonas dek da oro.,Necesitas diez de oro.,,Tarvitset sitä varten 10 kolikkoa.,Il vous faut 10 pièces pour ça.,10 aranyba kerül.,Ti servono 10 pezzi d'oro per quello.,10 ゴールド必要です。,10 골드입니다. 설마 이 만한 양의 돈이 없으신가요?,Daar heb je 10 goud voor nodig.,Du trenger 10 gull for det.,Potrzebujesz na to 10 złota.,Você precisa de 10 moedas para isto.,,Ai nevoie de 10 monezi pentru aia.,Тебе не хватает 10 золотых.,,Du behöver 10 guld för den.,Bunun için 10 altına ihtiyacın var. +Field surgery kit,TXT_RPLY1_SCRIPT33_D7580_FIELD,〃,,,Lékárničku,Kirurgisæt,Erste-Hilfe-Kasten,,Kirurgia kesto,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Kirurgisett,Zestaw do chirurgii polowej,Kit de cirurgia,,Kit chirurgical de teren.,Аптечкой,,Fältkirurgisk utrustning,Saha ameliyat kiti +Thank you.,TXT_RYES1_SCRIPT33_D7580_THANK,〃,,,Děkuji.,Tak.,Danke.,,Dankon.,Gracias.,,Kiitoksia,Merci.,Köszönöm.,Grazie.,ありがとうございます。,말 없이 주겠습니다. 거래 고마워요!,Bedankt.,Takk skal du ha.,Dziękuję.,Obrigado.,,Merci.,Спасибо.,,Tack.,Teşekkür ederim. "I wish I could give them away, but they cost 25 gold.",TXT_RNO1_SCRIPT33_D7580_IWISH,〃,,,"Přál bych si je dávat zadarmo, ale stojí 25 zlatých.","Jeg ville ønske, jeg kunne give dem væk, men de koster 25 guld.","Ich wünschte, ich könnte sie verschenken, aber sie kosten 25 Gold.",,"Mi donacus ĝin, sed ĝi kostas 25 da oro.","Ojalá pudiera regalarlo, -pero cuesta 25 de oro.",,"Kunpa voisinkin antaa niitä lahjaksi, mutta ne maksavat 25 kolikkoa.","J'adorerais les donner gratuitement, mais non, ça coûte 25 pièces.","Bárcsak ingyen osztogathatnám, de 25 aranyba kerül.","Mi piacerebbe darli via, ma costano 25 pezzi d'oro.",譲渡したい所ですが、25 ゴールド必要です。,25 골드만 있으면 잔소리 말고 주겠습니다.,"Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.","Jeg skulle ønske jeg kunne gi dem bort, men de koster 25 gull.","Chciałbym móc je rozdać, ale kosztują 25 złota.","Bem que eu queria doar de graça, mas custa 25 moedas de ouro.",,"Aș vrea să le pot da pe gratis, dar costă 25 de monezi.","С радостью бы отдал, но они по 25 золотых.",,Keşke onları verebilseydim ama 25 altına mal oluyorlar. -Healing,TXT_RPLY2_SCRIPT33_D7580_HEALI,〃,,,Ošetření,Healing,Heilung,,Kuracado,Curación,,Sairaanhoitoa,Des soins.,Gyógyítás,Ho bisogno di essere curato.,治療だ,치료 중.,Genezing,Helbredelse,Uzdrawianie,Cura,,Vindecă-mă.,Медкомплектом,,Şifa -There you go. Take care now.,TXT_RYES2_SCRIPT33_D7580_THERE,〃,,,A je to. Buď opatrný.,Værsgo. Pas godt på dig selv nu.,Bitteschön. Aber sei vorsichtiger.,,Jen. Estu atenta.,Aquí tienes. Cuídate.,,Olkaa hyvä. Pitäkäähän nyt huoli itsestänne.,"Voilà pour vous, portez-vous-bien.",Meg is oldottam. Vigyázz magadra.,"Ecco fatto, stammi bene.",こちらになります、お気をつけて。,치료가 끝났어. 몸 조심하라고.,Daar ga je. Pas goed op jezelf.,Vær så god. Ta vare på deg selv.,No i proszę. Dbaj o siebie.,Pronto. Se cuida.,,Gata. Ai grijă acum.,Пожалуйста. Береги себя!,,Al bakalım. Kendine iyi bak. +pero cuesta 25 de oro.",,"Kunpa voisinkin antaa niitä lahjaksi, mutta ne maksavat 25 kolikkoa.","J'adorerais les donner gratuitement, mais non, ça coûte 25 pièces.","Bárcsak ingyen osztogathatnám, de 25 aranyba kerül.","Mi piacerebbe darli via, ma costano 25 pezzi d'oro.",譲渡したい所ですが、25 ゴールド必要です。,25 골드만 있으면 잔소리 말고 주겠습니다.,"Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.","Jeg skulle ønske jeg kunne gi dem bort, men de koster 25 gull.","Chciałbym móc je rozdać, ale kosztują 25 złota.","Bem que eu queria doar de graça, mas custa 25 moedas de ouro.",,"Aș vrea să le pot da pe gratis, dar costă 25 de monezi.","С радостью бы отдал, но они по 25 золотых.",,"Jag önskar att jag kunde ge bort dem, men de kostar 25 guld.",Keşke onları verebilseydim ama 25 altına mal oluyorlar. +Healing,TXT_RPLY2_SCRIPT33_D7580_HEALI,〃,,,Ošetření,Healing,Heilung,,Kuracado,Curación,,Sairaanhoitoa,Des soins.,Gyógyítás,Ho bisogno di essere curato.,治療だ,치료 중.,Genezing,Helbredelse,Uzdrawianie,Cura,,Vindecă-mă.,Медкомплектом,,Helande,Şifa +There you go. Take care now.,TXT_RYES2_SCRIPT33_D7580_THERE,〃,,,A je to. Buď opatrný.,Værsgo. Pas godt på dig selv nu.,Bitteschön. Aber sei vorsichtiger.,,Jen. Estu atenta.,Toma. Cuídate.,,Olkaa hyvä. Pitäkäähän nyt huoli itsestänne.,"Voilà pour vous, portez-vous-bien.",Meg is oldottam. Vigyázz magadra.,"Ecco fatto, stammi bene.",こちらになります、お気をつけて。,치료가 끝났어. 몸 조심하라고.,Daar ga je. Pas goed op jezelf.,Vær så god. Ta vare på deg selv.,No i proszę. Dbaj o siebie.,Pronto. Se cuida.,,Gata. Ai grijă acum.,Пожалуйста. Береги себя!,,Här har du. Ta hand om dig nu.,Al bakalım. Kendine iyi bak. "Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT33_D7580_WELLM,〃,,,Možná si můžeš dovolit nějaké obvazy?,Måske har du råd til nogle medicinske plastre?,"Naja, vielleicht kannst du dir ein paar Bandagen leisten?",,"Nu, ĉu vi eble povas aĉeti kuracbendojn?","Bueno, ¿quizás tengas para comprar tiritas?","Bueno, ¿tal vez tengas -para comprar curitas?",Ehkä teillä olisi kuitenkin sidekääreisiin varaa?,"Eh bien, peut être pouvez-vous vous acheter quelques pansements?",Talán tellik pár tapaszra is?,"Beh, forse puoi permetterti delle bende?",ところで、医薬パッチを買う余裕はありますか?,의료 붕대는 어떠신가요? 이 건 저렴한데.,"Nou ja, misschien kunt u zich wat medische patches veroorloven?",Kanskje du har råd til noen medisinplaster?,Może stać cię na plastry?,"Bem, talvez você possa comprar algumas compressas?",,"Păi, poate îți permiți niște truse medicale?","Тогда, может быть, купишь несколько бинтов?",,Belki birkaç ilaç yamasını karşılayabilirsin? -"Hello friend, I haven't seen you around here before. All I can say is that I'd be careful if I were you, there's a lot going on and it's better if you don't get in the way.",TXT_DLG_SCRIPT33_D9096_HELLO,MAP33: Barkeep.,,,"Ahoj, příteli, ještě jsem tě tady neviděl. Jediné, co můžu říct, je: Být tebou, byl bych opatrný. Děje se toho hodně a je lepší neplést se věcem do cesty.","Hej ven, jeg har ikke set dig her før. Alt jeg kan sige er, at jeg ville være forsigtig, hvis jeg var dig, der sker meget, og det er bedre, hvis du ikke kommer i vejen.","Hallo, Freund, ich habe dich hier noch nicht gesehen. Ich kann nur sagen, sei vorsichtig und wenn ich du wäre, würde ich es vorziehen, niemandem im Weg zu stehen.",,,"Hola amigo, no te he visto antes por aquí. Todo lo que puedo decir es que tendría cuidado si fuera tú, están pasando muchas cosas y es mejor que no te entrometas.",,"Tervehdys. En ole teitä täällä ennen nähnytkään. Teidän saappaissanne olisin varuillani. Paljon on meneillään, ja on parempi pysyä poissa tieltä.","Bienvenue, l'ami. Je ne vous ai pas vu ici avant. Tout ce que peux vous dire, c'est de faire attention à vous. Il se passe beaucoup de choses ici, et je pense que vous ne voulez pas vous en mêler.","Szervusz barátom, nem láttalak még itt eddig. Csak annyi jó tanácsot tudok adni, hogy légy óvatos. Felpörögtek az események az utóbbi időben, és a helydben nem keverednék bele.","Salve amico, non ti ho mai visto da queste parti prima. Posso solo dirti che farei molta attenzione se fossi in te. Stanno succedendo diverse cose, ed è meglio non immischiarsi.","どうも余所者、この辺では見かけない顔だな。 +para comprar curitas?",Ehkä teillä olisi kuitenkin sidekääreisiin varaa?,"Eh bien, peut être pouvez-vous vous acheter quelques pansements?",Talán tellik pár tapaszra is?,"Beh, forse puoi permetterti delle bende?",ところで、医薬パッチを買う余裕はありますか?,의료 붕대는 어떠신가요? 이 건 저렴한데.,"Nou ja, misschien kunt u zich wat medische patches veroorloven?",Kanskje du har råd til noen medisinplaster?,Może stać cię na plastry?,"Bem, talvez você possa comprar algumas compressas?",,"Păi, poate îți permiți niște truse medicale?","Тогда, может быть, купишь несколько бинтов?",,Du kanske har råd med några medicinska plåster?,Belki birkaç ilaç yamasını karşılayabilirsin? +"Hello friend, I haven't seen you around here before. All I can say is that I'd be careful if I were you, there's a lot going on and it's better if you don't get in the way.",TXT_DLG_SCRIPT33_D9096_HELLO,MAP33: Barkeep.,,,"Ahoj, příteli, ještě jsem tě tady neviděl. Jediné, co můžu říct, je: Být tebou, byl bych opatrný. Děje se toho hodně a je lepší neplést se věcem do cesty.","Hej ven, jeg har ikke set dig her før. Alt jeg kan sige er, at jeg ville være forsigtig, hvis jeg var dig, der sker meget, og det er bedre, hvis du ikke kommer i vejen.","Hallo, Freund, ich habe dich hier noch nicht gesehen. Ich kann nur sagen, sei vorsichtig und wenn ich du wäre, würde ich es vorziehen, niemandem im Weg zu stehen.",,"Saluton, amiko, mi ne vidis vin ĉi tie antaŭe. Mi povas nur diri, ke mi estus atenta se mi estus vi: okazas multaj aferoj kaj estas pli bone, ke vi ne miksu vin.","Hola, amigo, no te he visto por aquí antes. Todo lo que puedo decir es que tendría cuidado si fuera tú: están pasando muchas cosas y es mejor que no te entrometas.","Hola, amigo, es la primera vez que te veo por aquí. Todo lo que puedo decir es que tendría cuidado si fuera tú: están pasando muchas cosas y es mejor que no te entrometas.","Tervehdys. En ole teitä täällä ennen nähnytkään. Teidän saappaissanne olisin varuillani. Paljon on meneillään, ja on parempi pysyä poissa tieltä.","Bienvenue, l'ami. Je ne vous ai pas vu ici avant. Tout ce que peux vous dire, c'est de faire attention à vous. Il se passe beaucoup de choses ici, et je pense que vous ne voulez pas vous en mêler.","Szervusz barátom, nem láttalak még itt eddig. Csak annyi jó tanácsot tudok adni, hogy légy óvatos. Felpörögtek az események az utóbbi időben, és a helydben nem keverednék bele.","Salve amico, non ti ho mai visto da queste parti prima. Posso solo dirti che farei molta attenzione se fossi in te. Stanno succedendo diverse cose, ed è meglio non immischiarsi.","どうも余所者、この辺では見かけない顔だな。 では一杯アドバイスをおごろう。 この付近が自由な発言を 許さないからって下手な真似をするなよ。 -オーダーという自警団がすぐに駆けつけてくるぞ。","반갑네, 친구. 낯선 사람인 것 같은데, 조심하고 걸어 다니게나. 지금 이곳에서 꽤 많은 일이 일어났거든. 내가 하는 말을 들으면 이해가 될 걸세.","Hallo vriend, ik heb je hier nog niet eerder gezien. Ik kan alleen maar zeggen dat ik voorzichtig zou zijn als ik jou was, er is veel aan de hand en het is beter als je niet in de weg staat.","Hei, min venn. Jeg har ikke sett deg her tidligere. Alt jeg kan si er at jeg ville vært forsiktig hvis jeg var deg, det er mye som skjer, og det er bedre om du ikke kommer i veien.","Witaj przyjacielu, nie widziałem cię tu wcześniej. Mogę tylko powiedzieć, że na twoim miejscu uważałbym, dużo się dzieje i lepiej, żebyś nie wchodził w drogę.",Olá amigo. Acho que não te vi por aqui antes. Tudo o que posso dizer é que eu tomaria cuidado se eu fosse você. Há muita coisa acontecendo e é melhor não se envolver.,,"Bună prietene, nu te-am mai văzut pe-aici. Tot ce spune e că aș avea grijă pe unde merg, se întâmplă multe prin jur și e mai bine să nu te amesteci.","Привет, дружище. Что-то я не видел тебя тут раньше. Дам тебе один совет: я бы на твоём месте был поосторожнее. Сейчас здесь такое творится, что лучше не высовываться.",,"Merhaba dostum, seni daha önce buralarda görmemiştim. Tek söyleyebileceğim, yerinde olsam dikkatli olurdum, çok şey oluyor ve yoluna çıkmazsan daha iyi olur." -Information,TXT_RPLY0_SCRIPT33_D9096_INFOR,〃,,,Informace,Information,Informationen,,Informoj,Información,,Tietoa.,Des infos.,Információ.,Informazioni,情報,정보를 줘.,Informatie,Informasjon,Informacje,Informações,,Informație,Есть новости?,,Bilgi -The sewers hold more than just rats and robots.,TXT_RYES0_SCRIPT33_D9096_THESE,〃,,,Stoky ukrývají víc než jen krysy a roboty.,Kloakkerne rummer mere end bare rotter og robotter.,Die Kanalisation hat mehr zu bieten als Ratten und Roboter.,,"En la kloakoj ne estas +オーダーという自警団がすぐに駆けつけてくるぞ。","반갑네, 친구. 낯선 사람인 것 같은데, 조심하고 걸어 다니게나. 지금 이곳에서 꽤 많은 일이 일어났거든. 내가 하는 말을 들으면 이해가 될 걸세.","Hallo vriend, ik heb je hier nog niet eerder gezien. Ik kan alleen maar zeggen dat ik voorzichtig zou zijn als ik jou was, er is veel aan de hand en het is beter als je niet in de weg staat.","Hei, min venn. Jeg har ikke sett deg her tidligere. Alt jeg kan si er at jeg ville vært forsiktig hvis jeg var deg, det er mye som skjer, og det er bedre om du ikke kommer i veien.","Witaj przyjacielu, nie widziałem cię tu wcześniej. Mogę tylko powiedzieć, że na twoim miejscu uważałbym, dużo się dzieje i lepiej, żebyś nie wchodził w drogę.",Olá amigo. Acho que não te vi por aqui antes. Tudo o que posso dizer é que eu tomaria cuidado se eu fosse você. Há muita coisa acontecendo e é melhor não se envolver.,,"Bună prietene, nu te-am mai văzut pe-aici. Tot ce spune e că aș avea grijă pe unde merg, se întâmplă multe prin jur și e mai bine să nu te amesteci.","Привет, дружище. Что-то я не видел тебя тут раньше. Дам тебе один совет: я бы на твоём месте был поосторожнее. Сейчас здесь такое творится, что лучше не высовываться.",,"Hej vän, jag har inte sett dig här förut. Allt jag kan säga är att jag skulle vara försiktig om jag var du, det är mycket på gång och det är bättre om du inte kommer i vägen.","Merhaba dostum, seni daha önce buralarda görmemiştim. Tek söyleyebileceğim, yerinde olsam dikkatli olurdum, çok şey oluyor ve yoluna çıkmazsan daha iyi olur." +Information,TXT_RPLY0_SCRIPT33_D9096_INFOR,〃,,,Informace,,Informationen,,Informoj,Información,,Tietoa.,Des infos.,Információ.,Informazioni,情報,정보를 줘.,Informatie,Informasjon,Informacje,Informações,,Informație,Есть новости?,,,Bilgi +The sewers hold more than just rats and robots.,TXT_RYES0_SCRIPT33_D9096_THESE,〃,,,Stoky ukrývají víc než jen krysy a roboty.,Kloakkerne rummer mere end bare rotter og robotter.,Die Kanalisation hat mehr zu bieten als Ratten und Roboter.,,"En la kloako ne estas nur ratoj kaj robotoj.","En las alcantarillas hay más -que solo ratas y robots.",,Viemärit pitävät sisällään muutakin kuin vain rottia ja robotteja.,Les égouts contiennent plus que des rats et des robots.,A kanális nem csak patkányokat és robotokat rejteget.,Le fogne contengono molto di più che ratti e robot.,他は...下水道には鼠やロボが沢山だ。,"하수도엔 쥐도 있고, 오물도 있고, 그 중 위험한 로봇들도 있다네.",In het riool zijn meer dan alleen ratten en robots te vinden.,Kloakken rommer mer enn bare rotter og roboter.,Kanały kryją w sobie coś więcej niż tylko szczury i roboty.,Os esgotos abrigam mais do que ratos e robôs.,,Canalele găzduiesc mai mult decât roboți și șobolani.,В канализации водятся не только крысы и роботы.,,Lağımlarda fareler ve robotlardan daha fazlası var. -Hey a guy's got to make some money. You think these jokers tip well?,TXT_RNO0_SCRIPT33_D9096_HEYAG,〃,,,"Hele, nějak si vydělávat musím. Myslíš, že tihle šašci dávají dobré spropitné?","Hey en fyr skal jo tjene nogle penge. Tror du, at de spassere giver gode drikkepenge?","Hey, mann muss auch sein Auskommen haben, glaubst du, diese Witzbolde geben einem Trinkgeld?",,,Hey un servidor tiene que ganar algo de dinero. ¿Crees que estos payasos dan buena propina?,,"Hei, jollakin tavalla sitä pitää leipänsä ansaita. Luuletko, että nämä pellet antavat hyvin juomarahaa?","Hé, j'ai besoin de me faire de l'argent, vous savez? Vous croyez que ces salauds me paient bien?","Figyelj, nekem is élni kell valamiből. Azt hiszed ezek a pacákok sok borravalót hagynak itt?","Ehi, devo pure riuscire a mettere qualcosa da parte. Pensi che i clienti qua diano laute mance?","ちょっと男はお金を稼ぐんだ。 +que solo ratas y robots.",,Viemärit pitävät sisällään muutakin kuin vain rottia ja robotteja.,Les égouts contiennent plus que des rats et des robots.,A kanális nem csak patkányokat és robotokat rejteget.,Le fogne contengono molto di più che ratti e robot.,他は...下水道には鼠やロボが沢山だ。,"하수도엔 쥐도 있고, 오물도 있고, 그 중 위험한 로봇들도 있다네.",In het riool zijn meer dan alleen ratten en robots te vinden.,Kloakken rommer mer enn bare rotter og roboter.,Kanały kryją w sobie coś więcej niż tylko szczury i roboty.,Os esgotos abrigam mais do que ratos e robôs.,,Canalele găzduiesc mai mult decât roboți și șobolani.,В канализации водятся не только крысы и роботы.,,Kloakerna rymmer mer än bara råttor och robotar.,Lağımlarda fareler ve robotlardan daha fazlası var. +Hey a guy's got to make some money. You think these jokers tip well?,TXT_RNO0_SCRIPT33_D9096_HEYAG,〃,,,"Hele, nějak si vydělávat musím. Myslíš, že tihle šašci dávají dobré spropitné?","Hey en fyr skal jo tjene nogle penge. Tror du, at de spassere giver gode drikkepenge?","Hey, mann muss auch sein Auskommen haben, glaubst du, diese Witzbolde geben einem Trinkgeld?",,"Homoj bezonas monon. +Ĉu vi atendas bonajn +trinkmonojn el ĉi tiaj klaŭnoj?","La gente tiene que comer, +¿o acaso crees que estos +bufones dan buena propina?",,"Hei, jollakin tavalla sitä pitää leipänsä ansaita. Luuletko, että nämä pellet antavat hyvin juomarahaa?","Hé, j'ai besoin de me faire de l'argent, vous savez? Vous croyez que ces salauds me paient bien?","Figyelj, nekem is élni kell valamiből. Azt hiszed ezek a pacákok sok borravalót hagynak itt?","Ehi, devo pure riuscire a mettere qualcosa da parte. Pensi che i clienti qua diano laute mance?","ちょっと男はお金を稼ぐんだ。 あなたはこれらのジョーカーがうまく傾くと -思いますか?",먹고 살려면 돈이 필요하다네. 이 손님들은 팁도 안 준다니까!,"Hé, een man moet wat geld verdienen. Denk je dat deze grappenmakers een goede fooi geven?","Hei, en fyr må tjene litt penger. Tror du disse jokerne gir bra med tips?","Hej facet musi zarobić trochę pieniędzy. Myślisz, że ci żartownisie dobrze dają napiwki?","Ei, preciso ganhar uma grana. Você acha que esses palhaços dão bastante gorjeta?",,Hei un om are nevoie și de bani. Crezi că glumeții ăștia au sfaturi bune?,"Заработай немного денег, парень. Или ты думаешь, что все эти шутники щедро платят?",,"Hey, bir adam biraz para kazanmalı. Bu şakacıların iyi bahşiş verdiğini mi düşünüyorsun?" -"Back again huh? Well, at least you know enough to keep your own skin intact. What can I do for you now?",TXT_DLG_SCRIPT33_D10612_BACKA,〃,,,"Zase zpátky, co? No, aspoň víš, jak si udržet kožich netknutý. Co pro tebe mohu udělat?","Tilbage igen, hva'? I det mindste ved du nok til at holde din egen hud intakt. Hvad kan jeg gøre for dig nu?","Schon wieder zurück, was? Na, wenigstens weißt du inzwischen, wie du das mit heiler Haut hinkriegst. Was kann ich jetzt für dich tun?",,,"¿De vuelta otra vez, eh? Bueno, al menos sabes suficiente para mantener tu pellejo intacto. ¿Qué puedo ofrecerte ahora?",,"Kas, tulit takaisin? Näköjään sen verran älliä päässä, että kykenet itsesi hengissä pitämään. Mutta mitä saisi nyt olla?","Déjà de retour, hein? Au moins vous savez sauver votre peau. Que puis-je faire pour vous?","Már visszatértél, mi? Legalább tudsz vigyázni az irhádra. Mit tehetek érted?","Già di ritorno, eh? Beh, almeno ciò che sai ti sta tornando utile per rimanere vivo. Cosa posso fare per te ora?","また戻ってね? +思いますか?",먹고 살려면 돈이 필요하다네. 이 손님들은 팁도 안 준다니까!,"Hé, een man moet wat geld verdienen. Denk je dat deze grappenmakers een goede fooi geven?","Hei, en fyr må tjene litt penger. Tror du disse jokerne gir bra med tips?","Hej facet musi zarobić trochę pieniędzy. Myślisz, że ci żartownisie dobrze dają napiwki?","Ei, preciso ganhar uma grana. Você acha que esses palhaços dão bastante gorjeta?",,Hei un om are nevoie și de bani. Crezi că glumeții ăștia au sfaturi bune?,"Заработай немного денег, парень. Или ты думаешь, что все эти шутники щедро платят?",,Hej en kille måste ju tjäna lite pengar. Tror du att de här skojarna ger bra dricks?,"Hey, bir adam biraz para kazanmalı. Bu şakacıların iyi bahşiş verdiğini mi düşünüyorsun?" +"Back again huh? Well, at least you know enough to keep your own skin intact. What can I do for you now?",TXT_DLG_SCRIPT33_D10612_BACKA,〃,,,"Zase zpátky, co? No, aspoň víš, jak si udržet kožich netknutý. Co pro tebe mohu udělat?","Tilbage igen, hva'? I det mindste ved du nok til at holde din egen hud intakt. Hvad kan jeg gøre for dig nu?","Schon wieder zurück, was? Na, wenigstens weißt du inzwischen, wie du das mit heiler Haut hinkriegst. Was kann ich jetzt für dich tun?",,"Do vi revenis. Nu, vi almenaŭ scias sufiĉe por eviti, ke vi estu vundita. Kion mi nun faru por vi?","De vuelta otra vez, ¿eh? Bueno, al menos sabes lo suficiente para mantener tu pellejo intacto. ¿Qué puedo ofrecerte ahora?",,"Kas, tulit takaisin? Näköjään sen verran älliä päässä, että kykenet itsesi hengissä pitämään. Mutta mitä saisi nyt olla?","Déjà de retour, hein? Au moins vous savez sauver votre peau. Que puis-je faire pour vous?","Már visszatértél, mi? Legalább tudsz vigyázni az irhádra. Mit tehetek érted?","Già di ritorno, eh? Beh, almeno ciò che sai ti sta tornando utile per rimanere vivo. Cosa posso fare per te ora?","また戻ってね? まあ、少なくともあなたは自分の肌を 損なわないようにするのに十分知っています。 -私は今あなたのために何ができますか?","다시 돌아온 건가? 뭐, 자기 몸 간수 잘하고 살아 돌아왔기에 망정이지. 뭘 원하나?","Weer terug, hè? Nou ja, je weet tenminste genoeg om je eigen huid intact te houden. Wat kan ik nu voor je doen?","Tilbake igjen, hva? Du vet i det minste nok til å holde ditt eget skinn intakt. Hva kan jeg gjøre for deg nå?","Znowu to samo? Przynajmniej wiesz wystarczająco dużo, aby zachować własną skórę w nienaruszonym stanie. Co mogę dla ciebie zrobić?","Já voltou, é? Bom, pelo menos você sabe o suficiente para manter sua pele intacta. O que mais posso fazer por você?",,"Te-ai întors din nou, hă? Păi, măcar cunoști destule cât să rămâi întreg. Ce pot face pentru tine?","Снова ты? Ну что ж, ты хотя бы знаешь, как шкуру сберечь. Что я могу тебе предложить?",,Yine mi döndün? En azından kendi derini sağlam tutacak kadar biliyorsun. Şimdi senin için ne yapabilirim? -More info,TXT_RPLY0_SCRIPT33_D10612_MOREI,〃,,,Další informace,Mere info,Mehr Informationen.,,Pliaj informoj,Más información,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,話のネタ。,그 외의 정보를 줘.,Meer info,Mer info,Więcej informacji,Mais informações.,,Mai multă informație,Расскажи больше,,Daha fazla bilgi -The Governor is a simple reminder of the Order's influence.,TXT_RYES0_SCRIPT33_D10612_THEGO,〃,,,Guvernér je jednoduchou připomínkou vlivu Řádu.,Guvernøren er en simpel påmindelse om Ordenens indflydelse.,Der Gouverneur ist eine einfache Erinnering an die Macht des Ordens.,,,El gobernador es un simple recordatorio de la influencia de La Orden,,Kuvernööri on selvä muistutus Veljeskunnan vaikutusvallasta.,Le gouverneur d'est qu'un rappel de l'influence de l'ordre.,A Kormányzó csak a Rend hatalmának bábja.,Il governatore è solo un simbolo dell'influenza dell'Ordine.,知事は俺達に自由はないと思い出させる象徴さ。,모렐 총독은 부정하고 짜증 나는 오더의 정권의 예야.,De gouverneur is een eenvoudige herinnering aan de invloed van de Orde.,Guvernøren er en enkel påminnelse om ordenens innflytelse.,Gubernator to proste przypomnienie o wpływach Zakonu.,O governador é um simples lembrete da influência da Ordem.,,Guvernatorul e o simplă reamintire a influenței Ordinului.,Губернатор — живое напоминание о власти Ордена.,,"Vali, Tarikat'ın etkisinin basit bir hatırlatıcısıdır." -Come back if you change your mind.,TXT_RNO0_SCRIPT33_D10612_COMEB,〃,,,"Vrať se, pokud změníš názor.","Kom tilbage, hvis du skifter mening.","Komm zurück, wenn du deine Meinung geändert hast.",,,Vuelve si cambias de idea.,,"Puhutaan taas, jos tulet toisiin aatoksiin.",Revenez si vous changez d'avis.,Gyere vissza ha változik a véleményed.,Torna pure se cambi idea.,気が変わったら戻ってきな。,마음이 바뀌면 돌아와주게나.,Kom terug als u van gedachten verandert.,Kom tilbake hvis du ombestemmer deg.,"Wróć, jeśli zmienisz zdanie.",Volte quando mudar de idéia.,,Întoarce-te dacă te răzgândești.,Передумаешь — возвращайся.,,Fikrini değiştirirsen geri gel. -"Well, you're sure asking a lot of questions for someone who's lived this long. That's ok though, I'd rather talk to someone like you than most of this lot.",TXT_DLG_SCRIPT33_D12128_WELLY,〃,,,"Na někoho, kdo přežil takhle dlouho, se ptáš docela hodně. To je v pořádku, radši bych se bavil s tebou než s většinou těhle lidí.","Du stiller virkelig mange spørgsmål af en, der har levet så længe. Det er dog ok, jeg vil hellere tale med en som dig end med de fleste af dem her.","Du stellst eine Menge Fragen für jemanden, der schon so lange überlebt hat. Das ist ok, ich rede lieber mit jemandem wie dir als mit dem Rest der Typen da.",,,"Bueno, ciertamente estás haciendo muchas preguntas para alguien que ha vivido tanto. Aunque eso es bueno, preferiría hablar con alquien como tú que con la mayoría de esta gente.",,"No, kyllläpä paljon kyselet sellaiseksi, joka näin pitkään on hengissä säilynyt. Mutta ei se mitään; mieluummin puhun jonkun sinun kaltaisesi kuin suurimman osan kanssa tätä porukkaa.","Vous posez beacoup de questions pour quelqu'un qui a survécu aussi longtemps. Ca me convient, je préfère parler à quelqu'un comme vous qu'a la majorité de ces idiots.","Ahhoz képest, hogy eddig éltél, elég sok kédést teszel fel. Igazából nem probléma, szívesebben beszélek veled mint mással itt.","Beh, fai davvero tante domande, per uno che è ancora vivo. Ma a me sta bene, molto meglio parlare con te rispetto agli altri che stanno qui...","所で、アンタは死に行かない人達に +私は今あなたのために何ができますか?","다시 돌아온 건가? 뭐, 자기 몸 간수 잘하고 살아 돌아왔기에 망정이지. 뭘 원하나?","Weer terug, hè? Nou ja, je weet tenminste genoeg om je eigen huid intact te houden. Wat kan ik nu voor je doen?","Tilbake igjen, hva? Du vet i det minste nok til å holde ditt eget skinn intakt. Hva kan jeg gjøre for deg nå?","Znowu to samo? Przynajmniej wiesz wystarczająco dużo, aby zachować własną skórę w nienaruszonym stanie. Co mogę dla ciebie zrobić?","Já voltou, é? Bom, pelo menos você sabe o suficiente para manter sua pele intacta. O que mais posso fazer por você?",,"Te-ai întors din nou, hă? Păi, măcar cunoști destule cât să rămâi întreg. Ce pot face pentru tine?","Снова ты? Ну что ж, ты хотя бы знаешь, как шкуру сберечь. Что я могу тебе предложить?",,"Tillbaka igen, va? Du vet åtminstone tillräckligt för att hålla ditt eget skinn intakt. Vad kan jag göra för dig nu?",Yine mi döndün? En azından kendi derini sağlam tutacak kadar biliyorsun. Şimdi senin için ne yapabilirim? +More info,TXT_RPLY0_SCRIPT33_D10612_MOREI,〃,,,Další informace,Mere info,Mehr Informationen.,,Pliaj informoj,Más información,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,話のネタ。,그 외의 정보를 줘.,Meer info,Mer info,Więcej informacji,Mais informações.,,Mai multă informație,Расскажи больше,,Mer information,Daha fazla bilgi +The Governor is a simple reminder of the Order's influence.,TXT_RYES0_SCRIPT33_D10612_THEGO,〃,,,Guvernér je jednoduchou připomínkou vlivu Řádu.,Guvernøren er en simpel påmindelse om Ordenens indflydelse.,Der Gouverneur ist eine einfache Erinnering an die Macht des Ordens.,,"La registo estas nur simbolo +pri la influo de La Ordeno.","El gobernador solo es un +símbolo de la influencia +de La Orden.",,Kuvernööri on selvä muistutus Veljeskunnan vaikutusvallasta.,Le gouverneur d'est qu'un rappel de l'influence de l'ordre.,A Kormányzó csak a Rend hatalmának bábja.,Il governatore è solo un simbolo dell'influenza dell'Ordine.,知事は俺達に自由はないと思い出させる象徴さ。,모렐 총독은 부정하고 짜증 나는 오더의 정권의 예야.,De gouverneur is een eenvoudige herinnering aan de invloed van de Orde.,Guvernøren er en enkel påminnelse om ordenens innflytelse.,Gubernator to proste przypomnienie o wpływach Zakonu.,O governador é um simples lembrete da influência da Ordem.,,Guvernatorul e o simplă reamintire a influenței Ordinului.,Губернатор — живое напоминание о власти Ордена.,,Guvernören är en enkel påminnelse om ordens inflytande.,"Vali, Tarikat'ın etkisinin basit bir hatırlatıcısıdır." +Come back if you change your mind.,TXT_RNO0_SCRIPT33_D10612_COMEB,〃,,,"Vrať se, pokud změníš názor.","Kom tilbage, hvis du skifter mening.","Komm zurück, wenn du deine Meinung geändert hast.",,"Revenu kiam +vi ŝanĝos ideon.",Vuelve si cambias de idea.,,"Puhutaan taas, jos tulet toisiin aatoksiin.",Revenez si vous changez d'avis.,Gyere vissza ha változik a véleményed.,Torna pure se cambi idea.,気が変わったら戻ってきな。,마음이 바뀌면 돌아와주게나.,Kom terug als u van gedachten verandert.,Kom tilbake hvis du ombestemmer deg.,"Wróć, jeśli zmienisz zdanie.",Volte quando mudar de idéia.,,Întoarce-te dacă te răzgândești.,Передумаешь — возвращайся.,,Kom tillbaka om du ändrar dig.,Fikrini değiştirirsen geri gel. +"Well, you're sure asking a lot of questions for someone who's lived this long. That's ok though, I'd rather talk to someone like you than most of this lot.",TXT_DLG_SCRIPT33_D12128_WELLY,〃,,,"Na někoho, kdo přežil takhle dlouho, se ptáš docela hodně. To je v pořádku, radši bych se bavil s tebou než s většinou těhle lidí.","Du stiller virkelig mange spørgsmål af en, der har levet så længe. Det er dog ok, jeg vil hellere tale med en som dig end med de fleste af dem her.","Du stellst eine Menge Fragen für jemanden, der schon so lange überlebt hat. Das ist ok, ich rede lieber mit jemandem wie dir als mit dem Rest der Typen da.",,"Nu, vi sendube faras multe da demandoj, kvankam vi vivis tiel longe. Mi ne plendas, mi preferus paroli kun iu kiel vi anstataŭ la ĉi-tiea plimulto.","Bueno, ciertamente estás haciendo muchas preguntas para alguien que ha vivido tanto. Aunque eso es bueno, preferiría hablar con alquien como tú que con la mayoría de esta gente.",,"No, kyllläpä paljon kyselet sellaiseksi, joka näin pitkään on hengissä säilynyt. Mutta ei se mitään; mieluummin puhun jonkun sinun kaltaisesi kuin suurimman osan kanssa tätä porukkaa.","Vous posez beacoup de questions pour quelqu'un qui a survécu aussi longtemps. Ca me convient, je préfère parler à quelqu'un comme vous qu'a la majorité de ces idiots.","Ahhoz képest, hogy eddig éltél, elég sok kédést teszel fel. Igazából nem probléma, szívesebben beszélek veled mint mással itt.","Beh, fai davvero tante domande, per uno che è ancora vivo. Ma a me sta bene, molto meglio parlare con te rispetto agli altri che stanno qui...","所で、アンタは死に行かない人達に 聞き回ってる様だが。悪いことは言わねえ、 -あんまし死に急ぐんじゃねえぞ。","아주 오래 살아서 배짱이 두둑한가, 다시 돌아와 줬구먼! 나야말로 괜찮다네. 이 주정부리들 보다 자네랑 대화하는 게 그나마 낫지.","Nou, je stelt zeker veel vragen aan iemand die zo lang heeft geleefd. Maar dat is niet erg, ik praat liever met iemand zoals jij dan met de meeste van deze mensen.","Du stiller mange spørsmål til å være en som har levd så lenge. Men det er greit, jeg vil heller snakke med en som deg enn de fleste av disse.","Zadajesz dużo pytań jak na kogoś, kto żyje tak długo. W porządku. Wolę rozmawiać z kimś takim jak ty niż z większością tych ludzi.","Bem, para alguém que conseguiu viver bastante você certamente faz muitas perguntas. Mas tudo bem, eu prefiro conversar com alguém como você do que com a maioria destes caras.",,"Păi, cu sigranță pui multe întrebări pentru cineva care a trăit atât. E în regulă însă, prefer să vorbesc cu cineva ca tine decât cu grămada asta.","Да, для человека, который прожил так долго, ты задаёшь многовато вопросов. Впрочем, это неплохо: я бы скорее предпочёл говорить с кем-то вроде тебя, чем с местными.",,"Bu kadar uzun yaşamış biri için çok fazla soru soruyorsun. Yine de sorun değil, buradakilerin çoğuyla konuşmaktansa senin gibi biriyle konuşmayı tercih ederim." -More info.,TXT_RPLY0_SCRIPT33_D12128_MOREI,〃,,,Další informace,Mere info.,Mehr Informationen.,,Pliaj informoj.,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,話のネタ。,더 많은 정보를 줘.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multă informație.,Говори дальше.,,Daha fazla bilgi. -There's more to the Order than what goes on around here.,TXT_RYES0_SCRIPT33_D12128_THERE,〃,,,"Za Řádem se toho skrývá víc, než tady vidíš.","Der er mere i Ordenen end det, der foregår her.","Hinter dem Orden steckt mehr, als es den Anschein hat.",,,Hay más de La Orden que lo que pasa por aquí.,,"Veljeskunnan toiminta ei rajoitu vain siihen, mitä täällä tapahtuu.",L'Ordre cache beaucoup plus que ce qui ne se passe ici.,"A Rend mögött több áll, mint amit az emberek pletykálnak.",C'è sotto molto di più sull'Ordine rispetto a quello che succede qua.,オーダーは見えてる以上に強大だ。,여기저기 퍼지는 소문보다 오더가 지키는 비밀이 더 깊숙하다네.,De Orde heeft meer te bieden dan wat er hier gebeurt.,Ordenen er mer enn bare det som foregår her.,"Zakon to coś więcej niż to, co dzieje się tutaj.",Há mais sobre a Ordem do que acontece por aqui.,,Sunt mai multe lucruri care țin de Ordin decât ceea ce se petrece în jur.,"Орден — нечто большее, чем кажется.",,Tarikat'ta burada olanlardan daha fazlası var. -Come back if you change your mind.,TXT_RNO0_SCRIPT33_D12128_COMEB,〃,,,"Vrať se, pokud změníš názor.","Kom tilbage, hvis du skifter mening.","Komm zurück, wenn du deine Meinung geändert hast.",,,Vuelve si cambias de idea.,,"Jos muutat mielesi, palataan asiaan.",Revenez si vous changez d'avis.,"Gyere vissza, ha meggondoltad magad.",Ritorna semmai cambi idea.,気が変わったら戻ってきな。,생각이 바뀌면 다시 돌아오게나.,Kom terug als je van gedachten verandert.,Kom tilbake hvis du ombestemmer deg.,"Wróć, jeśli zmienisz zdanie.",Volte quando mudar de idéia.,,Întoarce-te dacă te răzgândești.,Передумаешь — возвращайся.,,Fikrini değiştirirsen geri gel. -"That's it friend, the well of knowledge has been tapped. I've told you more than I should have anyway.",TXT_DLG_SCRIPT33_D13644_THATS,〃,,,"A to je vše, příteli, studnice mé moudrosti vyschla. Stejně jsem ti řekl víc, než jsem měl.","Det var det, min ven, vidensbrønden er blevet tappet. Jeg har alligevel fortalt dig mere, end jeg burde have gjort.","Das ist es, Freund, der Brunnen des Wissens ist versiegt. Ich habe dir schon mehr gesagt, als ich eigentlich sollte.",,,"Ya está amigo, el pozo del conocimiento se ha secado. Te he dicho más de lo que debería, de todos modos.",,"Siinä kaikki, ystävä. Tiedon lähde on ehtynyt. Olen kertonut sinulle joka tapauksessa enemmän kuin olisi pitänytkään.","C'est tout, mon ami. Le puits de la sagesse s'est tari. Je vous en ai trop dit de toutes manières.","Ennyi volt barátom, a tudás forrása elapadt. Már így is többet mondtam a kelleténél.","È tutto, amico, ho esaurito le cose che avevo da dirti. Ti ho già detto più di quanto avrei dovuto.","これはこれは親友、心得の瓶は切らしてるぞ。 -とにかく俺が知ってる話はこれで全部だ。",이게 다일세. 내가 친히 줄 수 있는 조언이라는 이름의 술은 다 줬다네.,"Dat is het vriend, de bron van kennis is aangeboord. Ik heb je meer verteld dan ik toch al zou moeten hebben.","Det var det, min venn. Kunnskapens brønn er tappet. Jeg har fortalt deg mer enn jeg burde uansett.","To wszystko przyjacielu, studnia wiedzy została wyczerpana. I tak powiedziałem ci więcej niż powinienem.","É isso, amigo. O poço de conhecimento já secou. Já te contei mais do que eu deveria, de qualquer forma.",,"Gata prietene, fântâna a secat. Ți-am spus mai multe decât ar fi trebuit oricum.","Это всё, дружище. Кладезь мудрости исчерпан. Я и так рассказал тебе больше, чем следовало.",,"Bu kadar dostum, bilgi kuyusu doldu. Zaten sana söylemem gerekenden fazlasını söyledim." -Hard to shop for new toys... when you're broke. Run a little errand for me and you'll get more than you could ever spend. I'll make you a rich man.,TXT_DLG_SCRIPT33_D15160_HARDT,MAP33: Harris.,,,"Nové hračky se shánějí jen těžko... když jsi švorc. Udělej pro mě malou prácičku a dostaneš víc, než kolik bys mohl kdy utratit. Udělám z tebe boháče.","Det er svært at købe nyt legetøj, når man er flad. Gør et lille ærinde for mig, og du vil få mere, end du nogensinde vil kunne bruge. Jeg vil gøre dig til en rig mand.","Ist es nicht schwierig, an neue Sachen zu kommen, wenn du pleite bist? Tu mir einen Gefallen und du kannst mehr Gold kriegen, als du jemals ausgeben kannst. Ich mache dich reich.",,,Difícil comprarse nuevos juguetes... cuando estás sin blanca. Haz algunos recados para mí y conseguirás más de lo que puedas gastarte. Te haré un hombre rico.,Difícil comprarse nuevos juguetes... cuando estás quebrado. Haz algunos encargos para mí y conseguirás más de lo que puedas gastarte. Te voy a hacer un hombre rico.,"Vaikea ostaa uusia leluja, kun on peeaa. Käytkö hoitamassa minulle yhden asian, niin tienaat enemmän kuin pystyt ikinä kuluttamaan. Teen sinusta kroisoksen.",Difficile de s'acheter de nouveaux joujous quand on n'a plus de sous. Faites-moi une petite course et vous aurez plus que vous ne pourrez jamais dépenser. Je vous rendrai riche.,"Nehéz úgy új játékszereket beszerezni, ha ennyire nincs pénzed. Viszont ha megteszel nekem egy szívességet, annyi pénzed lesz amit el se tudsz költeni. Gazdaggá teszlek.","È difficile comprare nuovi giocattoli... quando non hai la grana. Se fai un piccolo favore per me, potrai avere così tanti soldi da non sapere come spenderli. Ti renderò un uomo molto ricco.","新しい玩具も買えないぐらい...貧しそうだな +あんまし死に急ぐんじゃねえぞ。","아주 오래 살아서 배짱이 두둑한가, 다시 돌아와 줬구먼! 나야말로 괜찮다네. 이 주정부리들 보다 자네랑 대화하는 게 그나마 낫지.","Nou, je stelt zeker veel vragen aan iemand die zo lang heeft geleefd. Maar dat is niet erg, ik praat liever met iemand zoals jij dan met de meeste van deze mensen.","Du stiller mange spørsmål til å være en som har levd så lenge. Men det er greit, jeg vil heller snakke med en som deg enn de fleste av disse.","Zadajesz dużo pytań jak na kogoś, kto żyje tak długo. W porządku. Wolę rozmawiać z kimś takim jak ty niż z większością tych ludzi.","Bem, para alguém que conseguiu viver bastante você certamente faz muitas perguntas. Mas tudo bem, eu prefiro conversar com alguém como você do que com a maioria destes caras.",,"Păi, cu sigranță pui multe întrebări pentru cineva care a trăit atât. E în regulă însă, prefer să vorbesc cu cineva ca tine decât cu grămada asta.","Да, для человека, который прожил так долго, ты задаёшь многовато вопросов. Впрочем, это неплохо: я бы скорее предпочёл говорить с кем-то вроде тебя, чем с местными.",,"Du ställer verkligen många frågor för någon som har levt så här länge. Men det är okej, jag pratar hellre med någon som dig än med de flesta av de här.","Bu kadar uzun yaşamış biri için çok fazla soru soruyorsun. Yine de sorun değil, buradakilerin çoğuyla konuşmaktansa senin gibi biriyle konuşmayı tercih ederim." +More info.,TXT_RPLY0_SCRIPT33_D12128_MOREI,〃,,,Další informace,Mere info.,Mehr Informationen.,,Pliaj informoj.,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,話のネタ。,더 많은 정보를 줘.,Meer info.,Mer informasjon.,Więcej informacji.,Mais informações.,,Mai multă informație.,Говори дальше.,,Mer information.,Daha fazla bilgi. +There's more to the Order than what goes on around here.,TXT_RYES0_SCRIPT33_D12128_THERE,〃,,,"Za Řádem se toho skrývá víc, než tady vidíš.","Der er mere i Ordenen end det, der foregår her.","Hinter dem Orden steckt mehr, als es den Anschein hat.",,"Estas pli pri La Ordeno +ol tio, kio okazas ĉi tie.","Hay más de La Orden +que lo que pasa por aquí.",,"Veljeskunnan toiminta ei rajoitu vain siihen, mitä täällä tapahtuu.",L'Ordre cache beaucoup plus que ce qui ne se passe ici.,"A Rend mögött több áll, mint amit az emberek pletykálnak.",C'è sotto molto di più sull'Ordine rispetto a quello che succede qua.,オーダーは見えてる以上に強大だ。,여기저기 퍼지는 소문보다 오더가 지키는 비밀이 더 깊숙하다네.,De Orde heeft meer te bieden dan wat er hier gebeurt.,Ordenen er mer enn bare det som foregår her.,"Zakon to coś więcej niż to, co dzieje się tutaj.",Há mais sobre a Ordem do que acontece por aqui.,,Sunt mai multe lucruri care țin de Ordin decât ceea ce se petrece în jur.,"Орден — нечто большее, чем кажется.",,Det finns mer i Orden än vad som händer här.,Tarikat'ta burada olanlardan daha fazlası var. +Come back if you change your mind.,TXT_RNO0_SCRIPT33_D12128_COMEB,〃,,,"Vrať se, pokud změníš názor.","Kom tilbage, hvis du skifter mening.","Komm zurück, wenn du deine Meinung geändert hast.",,"Revenu kiam +vi ŝanĝos ideon.",Vuelve si cambias de idea.,,"Jos muutat mielesi, palataan asiaan.",Revenez si vous changez d'avis.,"Gyere vissza, ha meggondoltad magad.",Ritorna semmai cambi idea.,気が変わったら戻ってきな。,생각이 바뀌면 다시 돌아오게나.,Kom terug als je van gedachten verandert.,Kom tilbake hvis du ombestemmer deg.,"Wróć, jeśli zmienisz zdanie.",Volte quando mudar de idéia.,,Întoarce-te dacă te răzgândești.,Передумаешь — возвращайся.,,Kom tillbaka om du ändrar dig.,Fikrini değiştirirsen geri gel. +"That's it friend, the well of knowledge has been tapped. I've told you more than I should have anyway.",TXT_DLG_SCRIPT33_D13644_THATS,〃,,,"A to je vše, příteli, studnice mé moudrosti vyschla. Stejně jsem ti řekl víc, než jsem měl.","Det var det, min ven, vidensbrønden er blevet tappet. Jeg har alligevel fortalt dig mere, end jeg burde have gjort.","Das ist es, Freund, der Brunnen des Wissens ist versiegt. Ich habe dir schon mehr gesagt, als ich eigentlich sollte.",,"Jen ĉio, amiko, la fonto de scio sekiĝis. Malgraŭ tio, mi diris al vi pli ol tiom, kiom mi devus.","Ya está, amigo, el pozo del conocimiento ya se ha secado. De todas formas ya te he dicho más de lo que debería.","Ya está, amigo, el pozo del conocimiento ya se secó. De todas formas ya te dije más de lo que debería.","Siinä kaikki, ystävä. Tiedon lähde on ehtynyt. Olen kertonut sinulle joka tapauksessa enemmän kuin olisi pitänytkään.","C'est tout, mon ami. Le puits de la sagesse s'est tari. Je vous en ai trop dit de toutes manières.","Ennyi volt barátom, a tudás forrása elapadt. Már így is többet mondtam a kelleténél.","È tutto, amico, ho esaurito le cose che avevo da dirti. Ti ho già detto più di quanto avrei dovuto.","これはこれは親友、心得の瓶は切らしてるぞ。 +とにかく俺が知ってる話はこれで全部だ。",이게 다일세. 내가 친히 줄 수 있는 조언이라는 이름의 술은 다 줬다네.,"Dat is het vriend, de bron van kennis is aangeboord. Ik heb je meer verteld dan ik toch al zou moeten hebben.","Det var det, min venn. Kunnskapens brønn er tappet. Jeg har fortalt deg mer enn jeg burde uansett.","To wszystko przyjacielu, studnia wiedzy została wyczerpana. I tak powiedziałem ci więcej niż powinienem.","É isso, amigo. O poço de conhecimento já secou. Já te contei mais do que eu deveria, de qualquer forma.",,"Gata prietene, fântâna a secat. Ți-am spus mai multe decât ar fi trebuit oricum.","Это всё, дружище. Кладезь мудрости исчерпан. Я и так рассказал тебе больше, чем следовало.",,"Det var allt, min vän, kunskapens källa har blivit tömd. Jag har berättat mer än jag borde ha gjort i alla fall.","Bu kadar dostum, bilgi kuyusu doldu. Zaten sana söylemem gerekenden fazlasını söyledim." +Hard to shop for new toys... when you're broke. Run a little errand for me and you'll get more than you could ever spend. I'll make you a rich man.,TXT_DLG_SCRIPT33_D15160_HARDT,MAP33: Harris (beginning).,,,"Nové hračky se shánějí jen těžko... když jsi švorc. Udělej pro mě malou prácičku a dostaneš víc, než kolik bys mohl kdy utratit. Udělám z tebe boháče.","Det er svært at købe nyt legetøj, når man er flad. Gør et lille ærinde for mig, og du vil få mere, end du nogensinde vil kunne bruge. Jeg vil gøre dig til en rig mand.","Ist es nicht schwierig, an neue Sachen zu kommen, wenn du pleite bist? Tu mir einen Gefallen und du kannst mehr Gold kriegen, als du jemals ausgeben kannst. Ich mache dich reich.",,"Estas malfacile aĉeti novajn ludilojn... kiam oni estas senmona. Plenumu simplan komision por mi kaj vi gajnos pli ol tiom, kiom oni povus eĉ elspezi: mi faros vin riĉulo.",Difícil comprarse nuevos juguetes... cuando se está sin blanca. Haz un recado para mí y ganarás más de lo que puedas gastarte: te haré un hombre rico.,Difícil comprarse nuevos juguetes... cuando se está pobre. Haz un encargo para mí y vas a ganar más de lo que puedas gastarte: te voy a hacer un hombre rico.,"Vaikea ostaa uusia leluja, kun on peeaa. Käytkö hoitamassa minulle yhden asian, niin tienaat enemmän kuin pystyt ikinä kuluttamaan. Teen sinusta kroisoksen.",Difficile de s'acheter de nouveaux joujous quand on n'a plus de sous. Faites-moi une petite course et vous aurez plus que vous ne pourrez jamais dépenser. Je vous rendrai riche.,"Nehéz úgy új játékszereket beszerezni, ha ennyire nincs pénzed. Viszont ha megteszel nekem egy szívességet, annyi pénzed lesz amit el se tudsz költeni. Gazdaggá teszlek.","È difficile comprare nuovi giocattoli... quando non hai la grana. Se fai un piccolo favore per me, potrai avere così tanti soldi da non sapere come spenderli. Ti renderò un uomo molto ricco.","新しい玩具も買えないぐらい...貧しそうだな アンタ。良い儲け話があるぜ。 -俺のちょっとした仕事でガッポガポだぞ。",여기저기 장난감을 살려면 돈이 필요하지. 세상에 공짜가 어디 있나? 내 심부름을 좀 하다 보면 용돈도 생기고 부자가 될 걸세. 어떤가?,Moeilijk om nieuw speelgoed te kopen.... als je blut bent. Doe een kleine boodschap voor me en je krijgt meer dan je ooit zou kunnen uitgeven. Ik zal je een rijk man maken.,"Vanskelig å kjøpe nye leker... når man er blakk. Gjør et lite ærend for meg, så får du mer enn du kan bruke. Jeg skal gjøre deg rik.","Trudno jest kupować nowe zabawki... kiedy jest się spłukanym. Zrób dla mnie małe zlecenie, a dostaniesz więcej niż mógłbyś kiedykolwiek wydać. Zrobię z ciebie bogatego człowieka.","É difícil comprar brinquedos novos... quando você está duro. Se você fizer um favor pra mim, você vai ganhar mais do que jamais conseguiria gastar. Vou fazer de você um homem rico.",,Greu să cumperi jucarii noi... când ești falit. Dar faci o mică treabă pentru mine și o să fii putred de bogat.,"Трудновато покупать игрушки, когда нет и гроша за душой... Выполни одно заданьице для меня, и ты заработаешь столько, сколько в твоих карманах сроду не водилось. Ты будешь богатым!",,"Beş parasızken yeni oyuncaklar için alışveriş yapmak zor. Benim için ufak bir iş yaparsan, harcayabileceğinden fazlasını alırsın. Seni zengin bir adam yapacağım." -I got nothing better to do.,TXT_RPLY0_SCRIPT33_D15160_IGOTN,〃,,,Nemám nic lepšího na práci.,Jeg har intet bedre at lave.,Ich habe nichts besseres zu tun.,,Mi havas nenian farindaĵon.,No tengo nada mejor que hacer.,,Ei minulla parempaakaan tekemistä ole.,Je n'ai rien de mieux à faire.,Nincs jobb dolgom úgy sem.,Non ho di meglio da fare.,何もしないよりはいいか。,저는 할 것이 아무것도 없어요.,Ik heb niets beters te doen.,Jeg har ikke noe bedre å gjøre.,Nie mam nic lepszego do roboty.,Não tenho nada melhor pra fazer.,,N-am nimic mai bun de făcut.,Заманчивое предложение.,,Yapacak daha iyi bir işim yok. -No thanks.,TXT_RPLY1_SCRIPT33_D15160_NOTHA,〃,,,"Ne, díky.",Nej tak.,"Nein, danke.",,"Ne, dankon.","No, gracias.",,Ei kiitos.,Non merci.,Nem kösz.,No grazie.,いらない。,아뇨 괜찮습니다.,"Nee, bedankt.",Ellers takk.,"Nie, dziękuję.","Não, obrigado.",,Nu merci.,"Нет, спасибо.",,"Hayır, teşekkürler." -Nobody walks away from me!,TXT_RYES1_SCRIPT33_D15160_NOBOD,〃,,,Ode mě nikdo neodchází!,Ingen går væk fra mig!,Niemand sagt Nein zu mir.,,,¡Nadie pasa de mí!,,Kukaan ei käännä selkäänsä minulle!,Personne ne se barre après mon offre!,Senki sem sétál el előlem!,Nessuno fa l'impertinente con me!,俺から逃げられると思ってるのか!,그 누구도 나를 거절할 수 없어!,Niemand loopt weg van mij!,Ingen går fra meg!,Nikt ode mnie nie odchodzi!,Ninguém me ignora!,,Nimeni nu scapă de mine!,От меня ещё никто не уходил!,,Kimse benden kaçamaz! -"Good choice. The Order's sanctuary by the river is their unofficial torture chamber. Hidden inside there's a golden chalice. You swipe it, you meet me at the tavern, and reap your reward.",TXT_DLG_SCRIPT33_D16676_GOODC,〃,,,"Dobrá volba. Svatyně Řádu u řeky je jejich neoficiální mučírna. Uvnitř je skrytý zlatý kalich. Sebereš ho, sejdeš se se mnou v taverně a vyzvedneš si svou odměnu.","Godt valg. Ordenens fristed ved floden er deres uofficielle torturkammer. Der er en gylden bæger gemt derinde. Du tager den, du møder mig på kroen og høster din belønning.",Gute Wahl. Das Heiligtum des Ordens bei dem Fluss ist ihre inoffiziele Folterkammer. Darin versteckt ist ein goldener Kelch. Du klaust ihn und erntest deinen Lohn.,,,"Buena elección. El santuario de la Orden junto al río es su cámara de tortura no oficial. Oculto adentro hay un cáliz de oro. Lo robas, me vienes a ver a la taberna y consigues tu recompensa.",,"Viisas päätös. Veljeskunnan pyhäkkö joen varrella on heidän epävirallinen kidutuskammionsa, jonka kätköissä piilee kultakalkki. Kähvellä se ja saat vaivannäöstäsi palkan.",Bon choix. Le sanctuaire de l'ordre près de la rivière est leur chambre torture.. officieusement. A l'intérieur se trouve un calice en or. Récupérez le et venez prendre votre récompense.,"Jó választás. A Rend folyó melletti szentélye valójában a nem hivatalos kínzó kamrájuk. Elrejtve belül található egy arany serleg. Csend el szépen, és a kocsmánál találkozunk, lepasszolom a jutalmad.",Ottima scelta. Il santuario dell'Ordine vicino al fiume è la loro camera della tortura. Vi è un calice d'oro nascosto là dentro. Prendilo e avrai una lauta ricompensa.,"良い判断だ。川沿いにある オーダーの聖域 は +俺のちょっとした仕事でガッポガポだぞ。",여기저기 장난감을 살려면 돈이 필요하지. 세상에 공짜가 어디 있나? 내 심부름을 좀 하다 보면 용돈도 생기고 부자가 될 걸세. 어떤가?,Moeilijk om nieuw speelgoed te kopen.... als je blut bent. Doe een kleine boodschap voor me en je krijgt meer dan je ooit zou kunnen uitgeven. Ik zal je een rijk man maken.,"Vanskelig å kjøpe nye leker... når man er blakk. Gjør et lite ærend for meg, så får du mer enn du kan bruke. Jeg skal gjøre deg rik.","Trudno jest kupować nowe zabawki... kiedy jest się spłukanym. Zrób dla mnie małe zlecenie, a dostaniesz więcej niż mógłbyś kiedykolwiek wydać. Zrobię z ciebie bogatego człowieka.","É difícil comprar brinquedos novos... quando você está duro. Se você fizer um favor pra mim, você vai ganhar mais do que jamais conseguiria gastar. Vou fazer de você um homem rico.",,Greu să cumperi jucarii noi... când ești falit. Dar faci o mică treabă pentru mine și o să fii putred de bogat.,"Трудновато покупать игрушки, когда нет и гроша за душой... Выполни одно заданьице для меня, и ты заработаешь столько, сколько в твоих карманах сроду не водилось. Ты будешь богатым!",,Svårt att handla nya leksaker när man är pank. Gör ett litet ärende åt mig och du får mer än du någonsin kan spendera. Jag gör dig till en rik man.,"Beş parasızken yeni oyuncaklar için alışveriş yapmak zor. Benim için ufak bir iş yaparsan, harcayabileceğinden fazlasını alırsın. Seni zengin bir adam yapacağım." +I got nothing better to do.,TXT_RPLY0_SCRIPT33_D15160_IGOTN,〃,,,Nemám nic lepšího na práci.,Jeg har intet bedre at lave.,Ich habe nichts besseres zu tun.,,Mi havas nenian farindaĵon.,No tengo nada mejor que hacer.,,Ei minulla parempaakaan tekemistä ole.,Je n'ai rien de mieux à faire.,Nincs jobb dolgom úgy sem.,Non ho di meglio da fare.,何もしないよりはいいか。,저는 할 것이 아무것도 없어요.,Ik heb niets beters te doen.,Jeg har ikke noe bedre å gjøre.,Nie mam nic lepszego do roboty.,Não tenho nada melhor pra fazer.,,N-am nimic mai bun de făcut.,Заманчивое предложение.,,Jag har inget bättre att göra.,Yapacak daha iyi bir işim yok. +No thanks.,TXT_RPLY1_SCRIPT33_D15160_NOTHA,〃,,,"Ne, díky.",Nej tak.,"Nein, danke.",,"Ne, dankon.","No, gracias.",,Ei kiitos.,Non merci.,Nem kösz.,No grazie.,いらない。,아뇨 괜찮습니다.,"Nee, bedankt.",Ellers takk.,"Nie, dziękuję.","Não, obrigado.",,Nu merci.,"Нет, спасибо.",,Jag har inget bättre för mig.,"Hayır, teşekkürler." +Nobody walks away from me!,TXT_RYES1_SCRIPT33_D15160_NOBOD,〃,,,Ode mě nikdo neodchází!,Ingen går væk fra mig!,Niemand sagt Nein zu mir.,,Neniu preterpasas min!,¡Nadie pasa de mí!,,Kukaan ei käännä selkäänsä minulle!,Personne ne se barre après mon offre!,Senki sem sétál el előlem!,Nessuno fa l'impertinente con me!,俺から逃げられると思ってるのか!,그 누구도 나를 거절할 수 없어!,Niemand loopt weg van mij!,Ingen går fra meg!,Nikt ode mnie nie odchodzi!,Ninguém me ignora!,,Nimeni nu scapă de mine!,От меня ещё никто не уходил!,,Ingen går ifrån mig!,Kimse benden kaçamaz! +"Good choice. The Order's sanctuary by the river is their unofficial torture chamber. Hidden inside there's a golden chalice. You swipe it, you meet me at the tavern, and reap your reward.",TXT_DLG_SCRIPT33_D16676_GOODC,〃,,,"Dobrá volba. Svatyně Řádu u řeky je jejich neoficiální mučírna. Uvnitř je skrytý zlatý kalich. Sebereš ho, sejdeš se se mnou v taverně a vyzvedneš si svou odměnu.","Godt valg. Ordenens fristed ved floden er deres uofficielle torturkammer. Der er en gylden bæger gemt derinde. Du tager den, du møder mig på kroen og høster din belønning.",Gute Wahl. Das Heiligtum des Ordens bei dem Fluss ist ihre inoffiziele Folterkammer. Darin versteckt ist ein goldener Kelch. Du klaust ihn und erntest deinen Lohn.,,Bona elekto. La sanktejo de La Ordeno ĉe la rojo estas ĝia neoficiala torturejo. En ĝi estas kaŝita ora kaliko. Portu ĝin al mi en la taverno kaj vi havos rekompencon.,"Buena elección. El santuario de La Orden junto al arroyo es su cámara de tortura extraoficial. Dentro hay un cáliz dorado escondido. Cógelo, llévamelo a la taberna y tendrás tu recompensa.","Buena elección. El santuario de La Orden junto al río es su cámara de tortura extraoficial. Adentro hay un cáliz dorado escondido. Si lo tomas y me lo llevas a la taberna, tu recompensa.","Viisas päätös. Veljeskunnan pyhäkkö joen varrella on heidän epävirallinen kidutuskammionsa, jonka kätköissä piilee kultakalkki. Kähvellä se ja saat vaivannäöstäsi palkan.",Bon choix. Le sanctuaire de l'ordre près de la rivière est leur chambre torture.. officieusement. A l'intérieur se trouve un calice en or. Récupérez le et venez prendre votre récompense.,"Jó választás. A Rend folyó melletti szentélye valójában a nem hivatalos kínzó kamrájuk. Elrejtve belül található egy arany serleg. Csend el szépen, és a kocsmánál találkozunk, lepasszolom a jutalmad.",Ottima scelta. Il santuario dell'Ordine vicino al fiume è la loro camera della tortura. Vi è un calice d'oro nascosto là dentro. Prendilo e avrai una lauta ricompensa.,"良い判断だ。川沿いにある オーダーの聖域 は あいつらの非公式の拷問室だ。 中には黄金の聖杯が隠してある。 そいつを持ってくれば報酬をやるぜ。 -",좋은 선택이야. 강가 근처에 있는 성소가 바로 오더의 비공식적인 고문실이야. 그리고 그 안에는 숨겨진 금색 성배가 있지. 넌 그것을 훔치고 여기 선술집으로 와서 보상을 받으면 돼.,"Goede keuze. Het heiligdom van de Orde bij de rivier is hun onofficiële martelkamer. Verborgen in de kelk zit een gouden kelk. Je haalt hem weg, je komt me tegen in de herberg, en plukt je beloning.","Godt valg. Ordenens helligdom ved elven er deres uoffisielle torturkammer. Gjemt der inne er det et gyllent beger. Du stjeler det, møter meg på vertshuset og høster belønningen din.","Dobry wybór. Sanktuarium Zakonu nad rzeką jest ich nieoficjalną salą tortur. W środku jest ukryty złoty kielich. Machniesz nim, spotkasz się ze mną w tawernie i odbierzesz swoją nagrodę.","Boa escolha. O santuário da Ordem próximo ao rio é a câmara de tortura não oficial deles. Dentro dele há um cálice dourado. Pegue-o, me encontre na taverna e pegue sua recompensa.",,"Bună alegere. Sanctuarul Ordinului de lângă râu e lagărul lor neoficial. Ascuns înăuntru e un potir. Îl înșfaci, mă găsești la tavernă, și îți iei răsplata.","Правильный выбор. В святилище Ордена у реки — там у них негласная камера пыток — спрятана золотая чаша. Ты крадёшь её, возвращаешься ко мне в таверну и получаешь свою награду.",,"İyi seçim. Tarikat'ın nehir kenarındaki sığınağı onların gayri resmi işkence odası. İçinde altın bir kadeh saklı. Onu çalacaksın, benimle tavernada buluşacaksın ve ödülünü alacaksın." -How am I supposed to do that?,TXT_RPLY0_SCRIPT33_D16676_HOWAM,〃,,,Jak to mám udělat?,Hvordan skal jeg gøre det?,Wie soll ich das anstellen?,,Kiel mi faru tion?,¿Cómo se supone que haga eso?,,Miten minä muka sen teen?,Comment est-ce que je suis sensé faire ça?,Hogyan kéne ezt véghezvinnem?,E come posso fare tutto ciò?,どうすればいいんだ?,어떻게 하면 되나요?,Hoe moet ik dat doen?,Hvordan skal jeg gjøre det?,Jak mam to zrobić?,Como vou conseguir fazer isso?,,Cum ar trebui să fac asta?,Как мне это сделать?,,Bunu nasıl yapacağım? -Let me think about it.,TXT_RPLY1_SCRIPT33_D16676_LETME,〃,,,Nech mě o tom popřemýšlet.,Lad mig tænke over det.,Lass mich darüber nachdenken.,,Mi pensu.,Déjame pensarlo.,,Anna minun pohtia asiaa.,Laissez-moi y réfléchir.,Hadd gondolkozzak.,Ci penso un pò su e poi ti farò sapere.,ちょっと考えとく。,좀 생각해 보겠습니다.,Laat me erover nadenken.,La meg tenke på det.,Pozwól mi się zastanowić.,Vou pensar sobre isso.,,Lasă-mă să mă gândesc.,Я подумаю над твоим предложением.,,Bir düşüneyim. -"Sorry, no second chances. Oh, guards, kill him!",TXT_RYES1_SCRIPT33_D16676_SORRY,〃,,,"Promiň, žádné druhé šance. A, stráže, zabte ho!","Beklager, ingen anden chance. Åh, vagter, dræb ham!","Keine zweite Chance. Oh Wachen, tötet ihn.",,,"Lo siento, no hay segundas oportunidades. ¡Guardias, matadlo!","Lo siento, no hay segundas oportunidades. ¡Guardias, mátenlo!","Pahoittelut, ei toista mahdollisuutta. Vartijat, tappakaa hänet.","Pas de deuxième chance. Gardes, tuez-le.","Bocs, de második esély már nincs. Őrök, végezzétek ki!","Nessuna seconda chance. Guardie, uccidetelo.","残念、次はねえよ。おぅガードの旦那、 -やっちゃってくだせえ。","유감. 두 번째 기회는 없어. 경비원, 저놈을 죽여.","Sorry, geen tweede kans. Oh, bewakers, dood hem!","Beklager, ingen nye sjanser. Vakter, drep ham!","Przykro mi, nie ma drugiej szansy. Och, strażnicy, zabijcie go!","Sinto muito, nada de segundas chances. Ah, guardas, matem-no!",,"Oh, nicio altă șansă. Gardienilor, omorâți-l.","Нет, никакого второго шанса. Эй, стража, убейте его.",,"Üzgünüm, ikinci bir şans yok. Muhafızlar, öldürün onu!" -"Here's a crossbow, just aim straight and -- splat!--. Remember, grab the fancy cup and meet me at the tavern.",TXT_DLG_SCRIPT33_D18192_HERES,〃,,,"Tady je kuše, prostě rovně zamiř a --plesk!--. Nezapomeň, vem fešný hrnek a najdi mě v taverně.","Her er en armbrøst, bare sigt lige ud og -- splat!--. Husk, tag den fine kop og mød mig på kroen.","Hier ist eine Armbust, einfach gerade zielen und --Platsch--. Denk dran, schnapp dir den schicken Kelch und dann ab zur Taverne.",,Jen arbalesto. Vi nur celu laŭ rekta linio kaj «gut». Ne forgesu preni la belan pokalon kaj tiam renkonti min en la taverno.,Aquí tengo una ballesta. Solo apunta en línea recta y «ploc». Recuerda: toma la bonita copa y luego ve a verme a la taberna.,,"Tässä sinulle jousipyssy; tähtää vain eteenpäin ja ""pläts""! Tärkeintä vain, että muistat kahmaista fiinin maljan ja sitten palata kapakkaan.",Voilà une arbalète. Vous avez juste à viser droit et paf! Souvenez-vous. Prenez le goblet et ramenez le à la taverne.,"Itt egy íj, csak célozz egyenesen és -- bumm!--. És emlékezz: hozdd el a díszes serleget nekem a kocsmába.","Ecco una balestra, basta mirare e --splat--. Ricorda, prendi il calice e ritorna alla taverna.","このクロスボウを使いな、狙いを定めて +",좋은 선택이야. 강가 근처에 있는 성소가 바로 오더의 비공식적인 고문실이야. 그리고 그 안에는 숨겨진 금색 성배가 있지. 넌 그것을 훔치고 여기 선술집으로 와서 보상을 받으면 돼.,"Goede keuze. Het heiligdom van de Orde bij de rivier is hun onofficiële martelkamer. Verborgen in de kelk zit een gouden kelk. Je haalt hem weg, je komt me tegen in de herberg, en plukt je beloning.","Godt valg. Ordenens helligdom ved elven er deres uoffisielle torturkammer. Gjemt der inne er det et gyllent beger. Du stjeler det, møter meg på vertshuset og høster belønningen din.","Dobry wybór. Sanktuarium Zakonu nad rzeką jest ich nieoficjalną salą tortur. W środku jest ukryty złoty kielich. Machniesz nim, spotkasz się ze mną w tawernie i odbierzesz swoją nagrodę.","Boa escolha. O santuário da Ordem próximo ao rio é a câmara de tortura não oficial deles. Dentro dele há um cálice dourado. Pegue-o, me encontre na taverna e pegue sua recompensa.",,"Bună alegere. Sanctuarul Ordinului de lângă râu e lagărul lor neoficial. Ascuns înăuntru e un potir. Îl înșfaci, mă găsești la tavernă, și îți iei răsplata.","Правильный выбор. В святилище Ордена у реки — там у них негласная камера пыток — спрятана золотая чаша. Ты крадёшь её, возвращаешься ко мне в таверну и получаешь свою награду.",,"Bra val. Ordens helgedom vid floden är deras inofficiella tortyrkammare. Gömd inuti finns en gyllene bägare. Du tar den, möter mig på tavernan och skördar din belöning.","İyi seçim. Tarikat'ın nehir kenarındaki sığınağı onların gayri resmi işkence odası. İçinde altın bir kadeh saklı. Onu çalacaksın, benimle tavernada buluşacaksın ve ödülünü alacaksın." +How am I supposed to do that?,TXT_RPLY0_SCRIPT33_D16676_HOWAM,〃,,,Jak to mám udělat?,Hvordan skal jeg gøre det?,Wie soll ich das anstellen?,,Kiel mi supozeble faru tion?,¿Cómo se supone que debo hacer eso?,,Miten minä muka sen teen?,Comment est-ce que je suis sensé faire ça?,Hogyan kéne ezt véghezvinnem?,E come posso fare tutto ciò?,どうすればいいんだ?,어떻게 하면 되나요?,Hoe moet ik dat doen?,Hvordan skal jeg gjøre det?,Jak mam to zrobić?,Como vou conseguir fazer isso?,,Cum ar trebui să fac asta?,Как мне это сделать?,,Hur ska jag göra det?,Bunu nasıl yapacağım? +Let me think about it.,TXT_RPLY1_SCRIPT33_D16676_LETME,〃,,,Nech mě o tom popřemýšlet.,Lad mig tænke over det.,Lass mich darüber nachdenken.,,Mi pensu.,Déjame pensarlo.,,Anna minun pohtia asiaa.,Laissez-moi y réfléchir.,Hadd gondolkozzak.,Ci penso un po' su e poi ti farò sapere.,ちょっと考えとく。,좀 생각해 보겠습니다.,Laat me erover nadenken.,La meg tenke på det.,Pozwól mi się zastanowić.,Vou pensar sobre isso.,,Lasă-mă să mă gândesc.,Я подумаю над твоим предложением.,,Låt mig tänka på det.,Bir düşüneyim. +"Sorry, no second chances. Oh, guards, kill him!",TXT_RYES1_SCRIPT33_D16676_SORRY,〃,,,"Promiň, žádné druhé šance. A, stráže, zabte ho!","Beklager, ingen anden chance. Åh, vagter, dræb ham!","Keine zweite Chance. Oh Wachen, tötet ihn.",,"Pardonon, ne estas alia ŝanco. Gardistoj, mortigu lin!","Lo siento, no hay otra oportunidad. ¡Guardias, matadlo!","Lo siento, no hay otra oportunidad. ¡Guardias, mátenlo!","Pahoittelut, ei toista mahdollisuutta. Vartijat, tappakaa hänet.","Pas de deuxième chance. Gardes, tuez-le.","Bocs, de második esély már nincs. Őrök, végezzétek ki!","Nessuna seconda chance. Guardie, uccidetelo.","残念、次はねえよ。おぅガードの旦那、 +やっちゃってくだせえ。","유감. 두 번째 기회는 없어. 경비원, 저놈을 죽여.","Sorry, geen tweede kans. Oh, bewakers, dood hem!","Beklager, ingen nye sjanser. Vakter, drep ham!","Przykro mi, nie ma drugiej szansy. Och, strażnicy, zabijcie go!","Sinto muito, nada de segundas chances. Ah, guardas, matem-no!",,"Oh, nicio altă șansă. Gardienilor, omorâți-l.","Нет, никакого второго шанса. Эй, стража, убейте его.",,"Tyvärr, inga andra chanser. Vakter, döda honom!","Üzgünüm, ikinci bir şans yok. Muhafızlar, öldürün onu!" +"Here's a crossbow, just aim straight and -- splat!--. Remember, grab the fancy cup and meet me at the tavern.",TXT_DLG_SCRIPT33_D18192_HERES,〃,,,"Tady je kuše, prostě rovně zamiř a --plesk!--. Nezapomeň, vem fešný hrnek a najdi mě v taverně.","Her er en armbrøst, bare sigt lige ud og -- splat!--. Husk, tag den fine kop og mød mig på kroen.","Hier ist eine Armbust, einfach gerade zielen und --Platsch--. Denk dran, schnapp dir den schicken Kelch und dann ab zur Taverne.",,Jen arbalesto. Vi nur celu laŭ rekta linio kaj «pum». Ne forgesu preni la belan pokalon kaj tiam renkonti min en la taverno.,Aquí tengo una ballesta. Solo apunta en línea recta y «plaf». Recuerda: toma la bonita copa y luego ve a verme a la taberna.,,"Tässä sinulle jousipyssy; tähtää vain eteenpäin ja ""pläts""! Tärkeintä vain, että muistat kahmaista fiinin maljan ja sitten palata kapakkaan.",Voilà une arbalète. Vous avez juste à viser droit et paf! Souvenez-vous. Prenez le goblet et ramenez le à la taverne.,"Itt egy íj, csak célozz egyenesen és -- bumm!--. És emlékezz: hozdd el a díszes serleget nekem a kocsmába.","Ecco una balestra, basta mirare e --splat--. Ricorda, prendi il calice e ritorna alla taverna.","このクロスボウを使いな、狙いを定めて --シュッとな。覚えておけ、 -ファンシーなカップを持ってここに戻ってくると。","여기 석궁이야, 똑바로 겨냥해, 그리고... '철퍼덕'. 기억해, 멋진 컵을 들고 이 곳으로 다시 와.","Hier is een kruisboog, richt gewoon recht en -- splat! --. Vergeet niet, pak de mooie beker en ontmoet me in de herberg.","Her er en armbrøst, bare sikt rett og... plask! Husk, ta den fine koppen og møt meg på tavernaen.","Tu jest kusza, wyceluj prosto i... splat! Pamiętajcie, weźcie elegancki puchar i spotkajmy się w tawernie.","Pegue esta besta. Só mirar direito e splat! Lembre-se, pegue o copo bonitinho e me encontre na taverna.",,"Aici e o arbaletă, doar țintești și -- pleoșc! --. Ține minte, pune mâna pe potir și găsește-mă la tavernă.",Вот арбалет — просто прицеливаешься и «шлеп!» Запомни — хватаешь чашку и возвращаешься в таверну.,,"İşte yaylı tüfek. Düz nişan al ve patlat! Unutma, süslü kupayı al ve benimle tavernada buluş." -I'll see you there.,TXT_RPLY0_SCRIPT33_D18192_ILLSE,〃,,,Uvidíme se tam.,Vi ses der.,Wir sehen uns dort.,,Mi estos tie.,Allí estaré.,Ahí voy a estar.,Tapaan sinut siellä.,Je vous y verrais.,Ott találkozunk.,Ci vediamo lì.,また会おう。,거기서 보자고.,Ik zie je daar.,Vi ses der.,Do zobaczenia.,Te vejo lá.,,Ne vedem acolo.,Я вернусь с чашей.,,Orada görüşürüz. -"What are you waiting for? Don't worry, I'll clean up the bodies, just bring me that chalice!",TXT_DLG_SCRIPT33_D19708_WHATA,〃,,,"Na co čekáš? Neboj, mrtvol se zbavím já, prostě mi přines ten kalich!","Hvad venter du på? Bare rolig, jeg skal nok rydde op efter ligene, bare giv mig bægeret!","Worauf wartest du noch? Keine Sorge, ich kümmere mich um die Leichen. Bring mir den Kelch.",,,"¿A qué estás esperando? Yo me deshago de los cuerpos, así que tranquilo. ¡Tú solo tráeme ese cáliz!","¿Qué estás esperando? Yo me deshago de los cuerpos, así que tranquilo. ¡Tú solo tráeme ese cáliz!","Mitä oikein odottelet? Älä huoli, siivoan kyllä ruumiit. Tuo vaan minulle se kalkki.","Qu'attendez vous? Je m'occuperai des corps, ne vous inquiétez pas. Apportez-moi le calice!","Mire vársz? Ne aggódj, majd feltakarítom a hullákat, csak hozdd el a serleget.","Che cosa stai aspettando? Non ti preoccupare, ci penserò io a far sparire i corpi, tu pensa solo a portarmi quel calice!","何ボーっとしてんだ? 心配すんな、 -チャッチャと片付けて聖杯を持ってこい!","뭘 기다리는 거야? 걱정하지 마, 내가 시체들을 치워줄 테니. 그냥 성배를 가져와!","Waar wacht je nog op? Maak je geen zorgen, ik ruim de lichamen op, breng me gewoon die kelk!","Hva venter du på? Slapp av, jeg skal rydde opp i likene, bare gi meg begeret!","Na co czekasz? Nie martw się, posprzątam ciała, tylko przynieś mi ten kielich!","O que está esperando? Não se preocupe, eu limpo os corpos. Apenas me traga aquele cálice!",,"Ce mai aștepți? Nu te teme, voi curăța eu cadavrele, tu doar adu-mi potirul.",Чего ты ждёшь? Не беспокойся: я сам избавлюсь от трупов. Просто принеси мне чашу!,,"Neyi bekliyorsun? Merak etme, cesetleri temizleyeceğim, sadece kadehi bana getir!" -Guards! Kill the traitor!,TXT_DLG_SCRIPT33_D21224_GUARD,〃,,,Stráže! Zabte toho zrádce!,Vagter! Dræb forræderen!,Wächter! Tötet den Verräter!,,,¡Guardias! ¡Matad al traidor!,¡Guardias! ¡Maten al traidor!,Vartijat! Tappakaa petturi!,Gardes! Tuez ce traître!,Őrök! Öljétek meg az árulót!,Guardie! Uccidete il traditore!,ガード! 裏切者を殺せ!,경비! 반역자를 죽여라!,Bewakers! Dood de verrader!,Vakter! Drep forræderen!,Strażnicy! Zabić zdrajcę!,Guardas! Matem esse traidor!,,"Gardieni, omorâți trădătorul!",Стража! Убейте предателя!,,Muhafızlar! Haini öldürün! -"Hey, I know what you're thinking, kinda looks like a setup, I would never do that to such a killing machine, I mean it. Whew, all this fuss over a cup, weird. Now get ready, gold and glory, like I promised. Take this key and the Governor himself will reward you.",TXT_DLG_SCRIPT33_D22740_HEYIK,〃,,,"Hej, vím co si myslíš, tohle vypadá jako bouda. Takovému stroji na zabíjení bych nic takového neudělal, vážně! Páni, takový povyk kvůli hrnečku, divný. Tak teď se připrav, zlato a sláva, jak jsem slíbil. Vem si tenhle klíč a sám guvernér tě odmění.","Hey, jeg ved hvad du tænker, det ligner en fælde, jeg ville aldrig gøre det mod sådan en dræbermaskine, jeg mener det. Alt dette postyr over en kop, underligt. Gør dig klar, guld og ære, som jeg lovede. Tag denne nøgle, og guvernøren selv vil belønne dig.","Hey, ich weiß, es sieht anscheinend wie eine Falle aus, aber so etwas würde ich einer so großeartigen Tötungsmaschine nicht antun. Hast du ddas Ding? Großartig! Nun mach dich bereit, Geld und Ruhm, genau wie ich es dir versprochen habe. Nimm diesen Schlüssel und der Gouverneur wird dich belohnen.",,,"Hey, sé lo que estás pensando, parece un timo, pero nunca haría algo así a tal máquina de matar, lo juro. Uf, todo este lío por una copa, que raro. Ahora prepárate, oro y gloria, tal y como prometí. Toma esta llave y el mismísimo gobernador te recompensará.",,"Joo joo, tiedän, mitä ajattelet: vähän tuntuu väijytykseltä. En kuitenkaan ikinä tekisi sellaista niin kovalle tappokoneelle. Tarkoitan sitä. Huhhuh, kaikki tämä vouhotus yhdestä kupista; kummallista. No niin, valmistaudu kultaan ja kunniaan, niin kuin lupasinkin. Ota tämä avain ja itse kuvernööri palkitsee sinut.","Hé, je sais que ça à l'air d'être un coup monté, mais je ne ferais jamais ça à une aussi bonne machine à tuer. Tellement de bruit pour une coupe, franchement.. Préparez vous, l'or et la gloire vous attend, comme promis. Prenez cette clé et le gouverneur vous récompensera.","Tudom mire gondolsz, olyan ez mintha egy csapda lenne, de esküszöm soha nemm tennék ilyet egy jó gyilkológéppel. Nahát, ennyi hűhó egy francos serleg miatt. Node, állj aztán készen, eljön az a bizonyos pénz és hírnév mint ahogy ígértem. Tedd el ezt a kulcsot, és maga a kormányzó fog megjutalmazni.","Ehi, so che può sembrare una trappola. Ma io non tradirei mai a un killer abile come te. Mah, tutto questo per una coppa, che strano. Adesso preparati, oro e gloria, come ti avevo promesso. Prendi questa chiave e il governatore in persona ti ricompenserà.","よう。アンタが何を考えてるかわかるぜ、 +ファンシーなカップを持ってここに戻ってくると。","여기 석궁이야, 똑바로 겨냥해, 그리고... '철퍼덕'. 기억해, 멋진 컵을 들고 이 곳으로 다시 와.","Hier is een kruisboog, richt gewoon recht en -- splat! --. Vergeet niet, pak de mooie beker en ontmoet me in de herberg.","Her er en armbrøst, bare sikt rett og... plask! Husk, ta den fine koppen og møt meg på tavernaen.","Tu jest kusza, wyceluj prosto i... splat! Pamiętajcie, weźcie elegancki puchar i spotkajmy się w tawernie.","Pegue esta besta. Só mirar direito e splat! Lembre-se, pegue o copo bonitinho e me encontre na taverna.",,"Aici e o arbaletă, doar țintești și -- pleoșc! --. Ține minte, pune mâna pe potir și găsește-mă la tavernă.",Вот арбалет — просто прицеливаешься и «шлеп!» Запомни — хватаешь чашку и возвращаешься в таверну.,,"Här är ett armborst, sikta rakt och -- splat!--. Kom ihåg, ta den fina koppen och möt mig på tavernan.","İşte yaylı tüfek. Düz nişan al ve patlat! Unutma, süslü kupayı al ve benimle tavernada buluş." +I'll see you there.,TXT_RPLY0_SCRIPT33_D18192_ILLSE,〃,,,Uvidíme se tam.,Vi ses der.,Wir sehen uns dort.,,Mi estos tie.,Allí estaré.,Ahí voy a estar.,Tapaan sinut siellä.,Je vous y verrais.,Ott találkozunk.,Ci vediamo lì.,また会おう。,거기서 보자고.,Ik zie je daar.,Vi ses der.,Do zobaczenia.,Te vejo lá.,,Ne vedem acolo.,Я вернусь с чашей.,,Vi ses där.,Orada görüşürüz. +"What are you waiting for? Don't worry, I'll clean up the bodies, just bring me that chalice!",TXT_DLG_SCRIPT33_D19708_WHATA,〃,,,"Na co čekáš? Neboj, mrtvol se zbavím já, prostě mi přines ten kalich!","Hvad venter du på? Bare rolig, jeg skal nok rydde op efter ligene, bare giv mig bægeret!","Worauf wartest du noch? Keine Sorge, ich kümmere mich um die Leichen. Bring mir den Kelch.",,Kion vi atendas? Mi mem kaŝos la kadavrojn. Vi nur alportu tiun kalikon!,"¿A qué estás esperando? Yo me deshago de los cuerpos, así que tranquilo. ¡Tú solo tráeme ese cáliz!","¿Qué estás esperando? Yo me deshago de los cuerpos, así que tranquilo. ¡Tú solo tráeme ese cáliz!","Mitä oikein odottelet? Älä huoli, siivoan kyllä ruumiit. Tuo vaan minulle se kalkki.","Qu'attendez vous? Je m'occuperai des corps, ne vous inquiétez pas. Apportez-moi le calice!","Mire vársz? Ne aggódj, majd feltakarítom a hullákat, csak hozdd el a serleget.","Che cosa stai aspettando? Non ti preoccupare, ci penserò io a far sparire i corpi, tu pensa solo a portarmi quel calice!","何ボーっとしてんだ? 心配すんな、 +チャッチャと片付けて聖杯を持ってこい!","뭘 기다리는 거야? 걱정하지 마, 내가 시체들을 치워줄 테니. 그냥 성배를 가져와!","Waar wacht je nog op? Maak je geen zorgen, ik ruim de lichamen op, breng me gewoon die kelk!","Hva venter du på? Slapp av, jeg skal rydde opp i likene, bare gi meg begeret!","Na co czekasz? Nie martw się, posprzątam ciała, tylko przynieś mi ten kielich!","O que está esperando? Não se preocupe, eu limpo os corpos. Apenas me traga aquele cálice!",,"Ce mai aștepți? Nu te teme, voi curăța eu cadavrele, tu doar adu-mi potirul.",Чего ты ждёшь? Не беспокойся: я сам избавлюсь от трупов. Просто принеси мне чашу!,,"Vad väntar du på? Oroa dig inte, jag städar upp kropparna, ge mig bara kalken!","Neyi bekliyorsun? Merak etme, cesetleri temizleyeceğim, sadece kadehi bana getir!" +Guards! Kill the traitor!,TXT_DLG_SCRIPT33_D21224_GUARD,〃,,,Stráže! Zabte toho zrádce!,Vagter! Dræb forræderen!,Wächter! Tötet den Verräter!,,Gardistoj! Mortigu la perfidulon!,¡Guardias! ¡Matad al traidor!,¡Guardias! ¡Maten al traidor!,Vartijat! Tappakaa petturi!,Gardes! Tuez ce traître!,Őrök! Öljétek meg az árulót!,Guardie! Uccidete il traditore!,ガード! 裏切者を殺せ!,경비! 반역자를 죽여라!,Bewakers! Dood de verrader!,Vakter! Drep forræderen!,Strażnicy! Zabić zdrajcę!,Guardas! Matem esse traidor!,,"Gardieni, omorâți trădătorul!",Стража! Убейте предателя!,,Vakter! Döda förrädaren!,Muhafızlar! Haini öldürün! +"Hey, I know what you're thinking, kinda looks like a setup, I would never do that to such a killing machine, I mean it. Whew, all this fuss over a cup, weird. Now get ready, gold and glory, like I promised. Take this key and the Governor himself will reward you.",TXT_DLG_SCRIPT33_D22740_HEYIK,MAP33: Harris (tavern).,,,"Hej, vím co si myslíš, tohle vypadá jako bouda. Takovému stroji na zabíjení bych nic takového neudělal, vážně! Páni, takový povyk kvůli hrnečku, divný. Tak teď se připrav, zlato a sláva, jak jsem slíbil. Vem si tenhle klíč a sám guvernér tě odmění.","Hey, jeg ved hvad du tænker, det ligner en fælde, jeg ville aldrig gøre det mod sådan en dræbermaskine, jeg mener det. Alt dette postyr over en kop, underligt. Gør dig klar, guld og ære, som jeg lovede. Tag denne nøgle, og guvernøren selv vil belønne dig.","Hey, ich weiß, es sieht anscheinend wie eine Falle aus, aber so etwas würde ich einer so großeartigen Tötungsmaschine nicht antun. Hast du ddas Ding? Großartig! Nun mach dich bereit, Geld und Ruhm, genau wie ich es dir versprochen habe. Nimm diesen Schlüssel und der Gouverneur wird dich belohnen.",,"Jes, mi scias, vi certe pensas, ke ĉi tio estas trompo, sed mi neniam farus tion al bonega mortig-maŝino, mi ĵuras tion. Ve, ĉi tiom da malordo pro pokalo, strange. Vi nun pretiĝu: oro kaj gloro, tiel, kiel mi promesis. Prenu ĉi tiun ŝlosilon kaj la registo mem rekompencos vin.","Sí, sé lo que estás pensando: esto parece un timo, pero nunca le haría eso una tal máquina de matar, lo juro. Uf, todo este lío por una copa, qué raro. Ahora prepárate: oro y gloria, tal y como he prometido. Toma esta llave y el mismísimo gobernador te recompensará.","Sí, sé lo que estás pensando: esto parece una estafa, pero nunca le haría eso una tal máquina de matar, lo juro. Uf, todo este lío por una copa, que raro. Ahora prepárate: oro y gloria, tal y como prometí. Toma esta llave y el mismísimo gobernador te va a recompensar.","Joo joo, tiedän, mitä ajattelet: vähän tuntuu väijytykseltä. En kuitenkaan ikinä tekisi sellaista niin kovalle tappokoneelle. Tarkoitan sitä. Huhhuh, kaikki tämä vouhotus yhdestä kupista; kummallista. No niin, valmistaudu kultaan ja kunniaan, niin kuin lupasinkin. Ota tämä avain ja itse kuvernööri palkitsee sinut.","Hé, je sais que ça à l'air d'être un coup monté, mais je ne ferais jamais ça à une aussi bonne machine à tuer. Tellement de bruit pour une coupe, franchement.. Préparez vous, l'or et la gloire vous attend, comme promis. Prenez cette clé et le gouverneur vous récompensera.","Tudom mire gondolsz, olyan ez mintha egy csapda lenne, de esküszöm soha nemm tennék ilyet egy jó gyilkológéppel. Nahát, ennyi hűhó egy francos serleg miatt. Node, állj aztán készen, eljön az a bizonyos pénz és hírnév mint ahogy ígértem. Tedd el ezt a kulcsot, és maga a kormányzó fog megjutalmazni.","Ehi, so che può sembrare una trappola. Ma io non tradirei mai a un killer abile come te. Mah, tutto questo per una coppa, che strano. Adesso preparati, oro e gloria, come ti avevo promesso. Prendi questa chiave e il governatore in persona ti ricompenserà.","よう。アンタが何を考えてるかわかるぜ、 まるで罠だと。 俺には暴れん坊みたいな芸当出来ねえしな。 おう、カップを巡って大騒ぎだろうなこりゃ、 怖い怖い。 だったら準備しな、金と名誉は、約束通り。 -この鍵を取ったら知事が報酬を与えるだろうな。","이봐, 무슨 생각을 하는지 알겠어. 확실히 뭔가 꾸며 놓은 것 같다는 거. 난 훌륭한 학살 기계에게 그런 짓을 할 사람이 아니야. 휴... 그깟 컵 가지고. 이상해. 아무튼 준비해, 골드와 영광을. 이 열쇠를 총독에게 가져다주면 보상해 줄 거야.","Hé, ik weet wat je denkt, het lijkt een beetje op een valstrik, dat zou ik nooit met zo'n moordmachine doen, ik meen het. Whew, al deze ophef over een kopje, vreemd. Maak je nu klaar, goud en glorie, zoals ik heb beloofd. Neem deze sleutel en de Gouverneur zelf zal je belonen.","Jeg vet hva du tenker. Det ser ut som en felle. Jeg ville aldri gjort det mot en slik drapsmaskin. Alt dette oppstyret for en kopp. Merkelig. Gjør deg klar, gull og ære, som jeg lovet. Ta denne nøkkelen, så vil guvernøren selv belønne deg.","Hej, wiem co myślisz, wygląda to na ustawkę, nigdy nie zrobiłbym tego takiej maszynie do zabijania, mówię poważnie. Całe to zamieszanie z powodu kubka, dziwne. A teraz przygotuj się, złoto i chwała, jak obiecałem. Weź ten klucz, a sam gubernator cię nagrodzi.","Olha, eu sei o que você está pensando, que parece uma cilada. Eu nunca faria isso com uma máquina mortífera como você, sério mesmo. Nossa, todo esse escândalo por causa de um cálice, que esquisito. Agora se prepare, ouro e glória conforme prometido. Pegue esta chave e o governador vai te recompensar.",,"Hei, știu la ce te gândești, pare o capcană, dar nu aș face asta niciodată unei mașini ucigașe, serios. Atâta harababură pentru un potir, . Acum pregătește-te, aur și glorie, dupa cum ți-am promis. Ia cheia asta și însuși Guvernatorul te va răsplătii.","Слушай, я знаю, о чём ты думаешь. Ты думаешь, что это подстава. Но я бы никогда не сделал этого с такой машиной для убийств, как ты, правда-правда. Тем более, ради какой-то чаши. А теперь, тебя ждут золото и слава, как я и обещал. Возьми этот ключ, губернатор лично наградит тебя.",,"Hey, ne düşündüğünü biliyorum, biraz tuzak gibi görünüyor, böyle bir ölüm makinesine bunu asla yapmam, ciddiyim. Tüm bu yaygara bir fincan için, garip. Şimdi hazır ol, altın ve şan, söz verdiğim gibi. Bu anahtarı al ve Vali'nin kendisi seni ödüllendirecek." -"Great, I can't wait!",TXT_RPLY0_SCRIPT33_D22740_GREAT,〃,,,"Skvělý, nemůžu se dočkat!","Fedt, jeg kan ikke vente!","Toll, ich kann es kaum erwarten!",,,"Genial, ¡no puedo esperar!",,"Mahtavaa, en malta odottaa!","Parfait, je ne peux pas attendre!","Remek, már alig várom!","Ottimo, non vedo l'ora!",そりゃいいな、待ち遠しい!,좋았어! 기다릴 수 없는걸?,"Geweldig, ik kan niet wachten!","Flott, jeg gleder meg!","Świetnie, nie mogę się doczekać!","Ótimo, mal posso esperar!",,"Grozav, abia aștept.",Прекрасно. Мне уже не терпится!,,"Harika, sabırsızlanıyorum!" -"No chalice, no money!",TXT_RNO0_SCRIPT33_D22740_NOCHA,〃,,,"Žádný kalich, žádný prachy!","Ingen bæger, ingen penge!","Kein Kelch, kein Geld.",,,¡Sin cáliz no hay dinero!,,"Ei kalkkia, ei rahaa!","Pas de calice, pas d'argent!","Ha nincs serleg, nincs pénz!","Niente calice, niente soldi!",聖杯が無いなら、金も無しだ!,성배가 없다면 돈도 없어!,"Geen kelk, geen geld!","Ingen kalk, ingen penger!","Nie ma kielicha, nie ma pieniędzy!","Sem cálice, sem dinheiro!",,"Niciun potir, niciun ban!",Нет чаши — нет денег!,,Kadeh yoksa para da yok! -"I'll keep the chalice, thanks.",TXT_RPLY1_SCRIPT33_D22740_ILLKE,〃,,,"Nechám si ten kalich, díky.","Jeg beholder bægeret, tak.","Ich behalte den Kelch, danke.",,,Me quedaré el cáliz. Gracias.,,"Pidän kalkin, kiitos.","Je le garde, merci.","Inkább megtartom a serleget, kösz.","Il calice lo terrò io, grazie.",聖杯は頂く、じゃあな。,"내가 성배를 가지고 있을게, 고마워.","Ik bewaar de kelk, bedankt.","Jeg beholder begeret, takk.","Zatrzymam kielich, dzięki.","Vou ficar com o cálice, obrigado.",,"Păstrez potirul, merci.","Спасибо, но я оставлю чашу себе.",,"Kadeh bende kalsın, teşekkürler." -Keep it? I think not!,TXT_RYES1_SCRIPT33_D22740_KEEPI,〃,,,Necháš? Nemyslím si!,Beholde den? Det tror jeg ikke!,"Behalten? Ich glaube, nicht.",,,¿Quedártelo? ¡Me parece que no!,,Pidät sen? Enpä usko!,Le garder? Je ne pense pas!,Megtartod? Nem hinném öreg!,Davvero intendi tenerlo tu? Mi spiace ma non funziona così!,頂く? 有り得ねえな!,가지고 있겠다고? 내 생각은 아닌데?,Bewaren? Ik denk van niet!,Beholde det? Jeg tror ikke det!,Zatrzymać? Chyba nie!,Ficar com o cálice? Acho que não!,,Păstrezi? Ba nu cred!,Оставишь себе? Ещё чего!,,Saklamak mı? Hiç sanmıyorum! -What are you waiting for? The governor himself will reward you.,TXT_DLG_SCRIPT33_D24256_WHATA,〃,,,Na co čekáš? Sám guvernér tě odmění.,Hvad venter du på? Guvernøren selv vil belønne dig.,Worauf wartest du? Der Gouverneur wird dich belohnen.,,,¿Qué estás esperando? El mismísimo gobernador te recompensará.,,Mitä oikein odotat? Kuvernööri itse palkitsee sinut.,Qu'attendez-vous? Le gouverneur vous récompensera lui même.,Mire vársz? Maga a kormányzó fog megjutalmazni.,Che cosa stai aspettando? Il governatore in persona ti ricompenserà.,何突っ立ってんだ? 知事に報酬を受けて来いよ。,꾸물거리지 말고 총독을 만나. 그가 너를 보답해줄 거야.,Waar wacht je nog op? De gouverneur zelf zal je belonen.,Hva venter du på? Guvernøren selv vil belønne deg.,Na co czekasz? Sam gubernator cię nagrodzi.,O que você está esperando? O governador em pessoa vai te recompensar.,,Ce mai aștepți? Guvernatorul însuși te va răsplătii.,Чего ты ждёшь? Губернатор лично наградит тебя.,,Neyi bekliyorsun? Valinin kendisi seni ödüllendirecek. -Die traitor! ,TXT_DLG_SCRIPT33_D25772_DIETR,,,,"Zemři, zrádče!","Dø, forræder!","Stirb, Verräter!",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,くたばれ裏切者が!,죽어라. 배신자!,Sterf de verrader!,"Dø, forræder!",Giń zdrajco!,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!",,Geber hain! -So you're the fool who stole the chalice? I'm going to have you arrested as a rebel thief... Thereby enhancing my position with the Order. How does it feel to be an unwitting pawn? ,TXT_DLG_SCRIPT33_D27288_SOYOU,,,,"Tak ty jsi ten blázen, který ukradl kalich? Teď tě nechám zatknout jako rebelského zloděj... a tím si upevním svou pozici s Řádem. Jaký je to pocit, být bezděčnou figurkou?","Så du er det fjols, der stjal bægeret? Jeg vil få dig arresteret som en oprørsk tyv... og derved forbedre min position i ordenen. Hvordan føles det at være en uvidende brik?","So, du bist also der Narr der den Kelch gestohlen hat? Ich werde dich als Dieb der Rebellen verhaften lassen und dadurch meine Position im Orden verbessern. Wie fühlt es sich an als ahnungslose Schachfigur?",,,¿Así que tú eres el necio que robó el cáliz? Voy a arrestarte como ladrón rebelde... Mejorando así mí posición con la Orden. ¿Cómo se siente ser un inconsciente peón?,,"Vai sinä olet se houkka, joka varasti kalkin? Pidätytän sinut kapinallisvarkaana, siten parantaen asemaani Veljeskunnassa. Miltäpä tuntuu olla tahaton pelinappula?","Vous êtes l'abruti qui a volé le calice? Maintenant il faut que je vous arrète comme voleur rebelle.. Ca va aider ma position dans l'Ordre. Comment ça fait d'être un pion ignorant? Petite idée, ça va faire mal.",Szóval te vagy az isten barma aki ellopta a kelyhet? Jól letartóztatlak mint lázadó tolvaj...ezzel megerősítve a pozíciómat a Rendben. Milyen érzés egy tudatlan parasztnak lenni?,Quindi sei tu il folle che ha rubato il calice? Ti farò arrestare come un ladro ribelle... E così facendo salirò nei ranghi dell'Ordine. Come ci si sente ad essere un'inconsapevole pedina?,"それで、お前が聖杯を盗んだ愚か者か? +この鍵を取ったら知事が報酬を与えるだろうな。","이봐, 무슨 생각을 하는지 알겠어. 확실히 뭔가 꾸며 놓은 것 같다는 거. 난 훌륭한 학살 기계에게 그런 짓을 할 사람이 아니야. 휴... 그깟 컵 가지고. 이상해. 아무튼 준비해, 골드와 영광을. 이 열쇠를 총독에게 가져다주면 보상해 줄 거야.","Hé, ik weet wat je denkt, het lijkt een beetje op een valstrik, dat zou ik nooit met zo'n moordmachine doen, ik meen het. Whew, al deze ophef over een kopje, vreemd. Maak je nu klaar, goud en glorie, zoals ik heb beloofd. Neem deze sleutel en de Gouverneur zelf zal je belonen.","Jeg vet hva du tenker. Det ser ut som en felle. Jeg ville aldri gjort det mot en slik drapsmaskin. Alt dette oppstyret for en kopp. Merkelig. Gjør deg klar, gull og ære, som jeg lovet. Ta denne nøkkelen, så vil guvernøren selv belønne deg.","Hej, wiem co myślisz, wygląda to na ustawkę, nigdy nie zrobiłbym tego takiej maszynie do zabijania, mówię poważnie. Całe to zamieszanie z powodu kubka, dziwne. A teraz przygotuj się, złoto i chwała, jak obiecałem. Weź ten klucz, a sam gubernator cię nagrodzi.","Olha, eu sei o que você está pensando, que parece uma cilada. Eu nunca faria isso com uma máquina mortífera como você, sério mesmo. Nossa, todo esse escândalo por causa de um cálice, que esquisito. Agora se prepare, ouro e glória conforme prometido. Pegue esta chave e o governador vai te recompensar.",,"Hei, știu la ce te gândești, pare o capcană, dar nu aș face asta niciodată unei mașini ucigașe, serios. Atâta harababură pentru un potir, . Acum pregătește-te, aur și glorie, dupa cum ți-am promis. Ia cheia asta și însuși Guvernatorul te va răsplătii.","Слушай, я знаю, о чём ты думаешь. Ты думаешь, что это подстава. Но я бы никогда не сделал этого с такой машиной для убийств, как ты, правда-правда. Тем более, ради какой-то чаши. А теперь, тебя ждут золото и слава, как я и обещал. Возьми этот ключ, губернатор лично наградит тебя.",,"Jag vet vad du tänker, det ser ut som en fälla, jag skulle aldrig göra det mot en sådan dödsmaskin, jag menar det. Allt detta ståhej för en kopp, konstigt. Gör dig nu redo, guld och ära, som jag lovade. Ta den här nyckeln och guvernören själv kommer att belöna dig.","Hey, ne düşündüğünü biliyorum, biraz tuzak gibi görünüyor, böyle bir ölüm makinesine bunu asla yapmam, ciddiyim. Tüm bu yaygara bir fincan için, garip. Şimdi hazır ol, altın ve şan, söz verdiğim gibi. Bu anahtarı al ve Vali'nin kendisi seni ödüllendirecek." +"Great, I can't wait!",TXT_RPLY0_SCRIPT33_D22740_GREAT,〃,,,"Skvělý, nemůžu se dočkat!","Fedt, jeg kan ikke vente!","Toll, ich kann es kaum erwarten!",,"Bonege, mi sopire atendas!","Genial, ¡no puedo esperar!",,"Mahtavaa, en malta odottaa!","Parfait, je ne peux pas attendre!","Remek, már alig várom!","Ottimo, non vedo l'ora!",そりゃいいな、待ち遠しい!,좋았어! 기다릴 수 없는걸?,"Geweldig, ik kan niet wachten!","Flott, jeg gleder meg!","Świetnie, nie mogę się doczekać!","Ótimo, mal posso esperar!",,"Grozav, abia aștept.",Прекрасно. Мне уже не терпится!,,"Toppen, jag kan inte vänta!","Harika, sabırsızlanıyorum!" +"No chalice, no money!",TXT_RNO0_SCRIPT33_D22740_NOCHA,〃 (if accepting without having the chalice),,,"Žádný kalich, žádný prachy!","Ingen bæger, ingen penge!","Kein Kelch, kein Geld.",,Sen kaliko ne estas mono!,¡Sin cáliz no hay dinero!,,"Ei kalkkia, ei rahaa!","Pas de calice, pas d'argent!","Ha nincs serleg, nincs pénz!","Niente calice, niente soldi!",聖杯が無いなら、金も無しだ!,성배가 없다면 돈도 없어!,"Geen kelk, geen geld!","Ingen kalk, ingen penger!","Nie ma kielicha, nie ma pieniędzy!","Sem cálice, sem dinheiro!",,"Niciun potir, niciun ban!",Нет чаши — нет денег!,,"Ingen bägare, inga pengar!",Kadeh yoksa para da yok! +"I'll keep the chalice, thanks.",TXT_RPLY1_SCRIPT33_D22740_ILLKE,〃,,,"Nechám si ten kalich, díky.","Jeg beholder bægeret, tak.","Ich behalte den Kelch, danke.",,Mi konservos la kalikon. Dankon.,Me quedo con el cáliz. Gracias.,,"Pidän kalkin, kiitos.","Je le garde, merci.","Inkább megtartom a serleget, kösz.","Il calice lo terrò io, grazie.",聖杯は頂く、じゃあな。,"내가 성배를 가지고 있을게, 고마워.","Ik bewaar de kelk, bedankt.","Jeg beholder begeret, takk.","Zatrzymam kielich, dzięki.","Vou ficar com o cálice, obrigado.",,"Păstrez potirul, merci.","Спасибо, но я оставлю чашу себе.",,"Jag behåller bägaren, tack.","Kadeh bende kalsın, teşekkürler." +Keep it? I think not!,TXT_RYES1_SCRIPT33_D22740_KEEPI,〃,,,Necháš? Nemyslím si!,Beholde den? Det tror jeg ikke!,"Behalten? Ich glaube, nicht.",,"Ĉu konservi ĝin? +Mi kredas, ke ne!","¿Quedártelo? +¡Me parece que no!",,Pidät sen? Enpä usko!,Le garder? Je ne pense pas!,Megtartod? Nem hinném öreg!,Davvero intendi tenerlo tu? Mi spiace ma non funziona così!,頂く? 有り得ねえな!,가지고 있겠다고? 내 생각은 아닌데?,Bewaren? Ik denk van niet!,Beholde det? Jeg tror ikke det!,Zatrzymać? Chyba nie!,Ficar com o cálice? Acho que não!,,Păstrezi? Ba nu cred!,Оставишь себе? Ещё чего!,,Behålla den? Jag tror inte det!,Saklamak mı? Hiç sanmıyorum! +What are you waiting for? The governor himself will reward you.,TXT_DLG_SCRIPT33_D24256_WHATA,〃,,,Na co čekáš? Sám guvernér tě odmění.,Hvad venter du på? Guvernøren selv vil belønne dig.,Worauf wartest du? Der Gouverneur wird dich belohnen.,,Kion vi atendas? La registo mem rekompencos vin.,¿A qué estás esperando? El mismísimo gobernador te recompensará.,¿Qué estás esperando? El mismísimo gobernador te va a recompensar.,Mitä oikein odotat? Kuvernööri itse palkitsee sinut.,Qu'attendez-vous? Le gouverneur vous récompensera lui même.,Mire vársz? Maga a kormányzó fog megjutalmazni.,Che cosa stai aspettando? Il governatore in persona ti ricompenserà.,何突っ立ってんだ? 知事に報酬を受けて来いよ。,꾸물거리지 말고 총독을 만나. 그가 너를 보답해줄 거야.,Waar wacht je nog op? De gouverneur zelf zal je belonen.,Hva venter du på? Guvernøren selv vil belønne deg.,Na co czekasz? Sam gubernator cię nagrodzi.,O que você está esperando? O governador em pessoa vai te recompensar.,,Ce mai aștepți? Guvernatorul însuși te va răsplătii.,Чего ты ждёшь? Губернатор лично наградит тебя.,,Vad väntar du på? Guvernören själv kommer att belöna dig.,Neyi bekliyorsun? Valinin kendisi seni ödüllendirecek. +Die traitor! ,TXT_DLG_SCRIPT33_D25772_DIETR,〃,,,"Zemři, zrádče!","Dø, forræder!","Stirb, Verräter!",,"Mortu, perfidulo!","¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,くたばれ裏切者が!,죽어라. 배신자!,Sterf de verrader!,"Dø, forræder!",Giń zdrajco!,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!",,Dö förrädare!,Geber hain! +So you're the fool who stole the chalice? I'm going to have you arrested as a rebel thief... Thereby enhancing my position with the Order. How does it feel to be an unwitting pawn? ,TXT_DLG_SCRIPT33_D27288_SOYOU,MAP33: Mourel.,,,"Tak ty jsi ten blázen, který ukradl kalich? Teď tě nechám zatknout jako rebelského zloděj... a tím si upevním svou pozici s Řádem. Jaký je to pocit, být bezděčnou figurkou?","Så du er det fjols, der stjal bægeret? Jeg vil få dig arresteret som en oprørsk tyv... og derved forbedre min position i ordenen. Hvordan føles det at være en uvidende brik?","So, du bist also der Narr der den Kelch gestohlen hat? Ich werde dich als Dieb der Rebellen verhaften lassen und dadurch meine Position im Orden verbessern. Wie fühlt es sich an als ahnungslose Schachfigur?",,"Vi do estas la stultulo, kiu ŝtelis la kalikon, ĉu? Mi kaptos vin kiel ribelan ŝteliston, tiel mi plibonigos mian statuson kun La Ordeno. Kiel vi sentas, ke vi estas nevola marioneto?","¿Así que tú eres el necio que ha robado el cáliz? Te capturaré como ladrón rebelde, mejorando así mi posición con La Orden. ¿Qué se siente ser un peón involuntario?","¿Así que tú eres el tonto que se robó el cáliz? Te voy a capturar como ladrón rebelde, mejorando así mi posición con La Orden. ¿Qué se siente ser un peón involuntario?","Vai sinä olet se houkka, joka varasti kalkin? Pidätytän sinut kapinallisvarkaana, siten parantaen asemaani Veljeskunnassa. Miltäpä tuntuu olla tahaton pelinappula?","Vous êtes l'abruti qui a volé le calice? Maintenant il faut que je vous arrète comme voleur rebelle.. Ca va aider ma position dans l'Ordre. Comment ça fait d'être un pion ignorant? Petite idée, ça va faire mal.",Szóval te vagy az isten barma aki ellopta a kelyhet? Jól letartóztatlak mint lázadó tolvaj...ezzel megerősítve a pozíciómat a Rendben. Milyen érzés egy tudatlan parasztnak lenni?,Quindi sei tu il folle che ha rubato il calice? Ti farò arrestare come un ladro ribelle... E così facendo salirò nei ranghi dell'Ordine. Come ci si sente ad essere un'inconsapevole pedina?,"それで、お前が聖杯を盗んだ愚か者か? 私は反賊としてお前を逮捕するつもりだ... そうすればオーダーでの地位が上がる。 無意味な駒だと思うか? -",그래서 네가 그 성배를 훔친 바보로군? 반군 절도범으로 체포해주지... 오더에서의 내 위치도 올리는 겸. 모르는 사이에 장물아비가 된 기분이 어떤가?,Dus jij bent de dwaas die de kelk heeft gestolen? Ik ga je laten arresteren als rebelse dief.... Daardoor verbeter ik mijn positie bij de Orde. Hoe voelt het om een onwetende pion te zijn?,Så du er tosken som stjal begeret? Jeg skal få deg arrestert som en opprørsk tyv... Og dermed styrke min posisjon i Ordenen. Hvordan føles det å være en uvitende brikke?,"Więc to ty jesteś tym głupcem, który ukradł kielich? Każę cię aresztować jako buntowniczego złodzieja... Tym samym wzmocnię swoją pozycję w Zakonie. Jakie to uczucie być nieświadomym pionkiem?",Então você é o idiota que roubou o cálice? Eu vou prender você por ser um ladrão rebelde... E assim vou melhorar minha posição com a Ordem. Como se sente sendo um plebeu ignorante?,,Deci tu ești tolomacul care a furat potirul? Am să te arestez drept un hoț rebel... Prin urmare crescând in rangurile Ordinului. Cum e să fii un pion?,"Так это ты тот недоумок, что украл чашу? Я передам тебя Ордену, как вора повстанцев... Это укрепит мои отношения с ним. Каково чувствовать себя безмозглой пешкой?",,Demek kadehi çalan aptal sensin? Seni asi bir hırsız olarak tutuklatacağım. Böylece Tarikat'taki konumumu güçlendireceğim. Farkında olmadan bir piyon olmak nasıl bir duygu? -It sucks!,TXT_RPLY0_SCRIPT33_D27288_ITSUC,,,,Je to na hovno!,Det stinker!,Scheiße!,,Ĝi aĉas!,¡Apesta!,,Ihan perseestä!,Quelle merde!,Ez szopás!,È uno schifo!,クソが!,기분이 아주 좆같아.,Het is klote!,Det suger!,Do dupy!,É uma merda!,,Nașpa!,Чтоб ты сдох!,,Berbat! -For you it does.,TXT_RYES0_SCRIPT33_D27288_FORYO,,,,Pro tebe určitě.,For dig gør det.,Du steckst ganz tief drin.,,,"Para ti, sí.",,"Kyllä, sinun tilanteesi.","Pour vous, en effet.",...és a bráner rossz végén vagy.,Ti faccio vedere io!,私もそう思う。,더한 기분이 들게 해주지.,Voor jou wel.,For deg gjør det det.,Dla ciebie tak.,"Pra você, é mesmo.",,"Pentru tine, într-adevăr este.",Скоро сдохнешь ты.,,Senin için öyle. -Harris promised me money!,TXT_RPLY1_SCRIPT33_D27288_HARRI,,,,Harris mi slíbil peníze!,Harris lovede mig penge!,Harris hat mir Geld versprochen!,,,¡Harris me prometió dinero!,,Harris lupasi minulle rahaa!,Harris m'a promis de l'argent!,Harris pénzt ígért nekem.,Harris mi ha promesso dei soldi!,ハリスは俺に金を渡すと約束したのに!,해리스가 날 배신했어... 이 새끼!,Harris beloofde me geld!,Harris lovet meg penger!,Harris obiecał mi pieniądze!,O Harris prometeu me pagar!,,Harris mi-a promis bani!,Харрис обещал мне деньги!,,Harris bana para sözü verdi! -Too bad. The only thing you're getting is death!,TXT_RYES1_SCRIPT33_D27288_TOOBA,,,,"Smůla. Jediné, co dostaneš, je smrt!","Det var ærgerligt. Det eneste, du får, er døden!",Jammerschade. Das Einzige was du bekommen wirst ist der Tod!,,,Una pena. ¡Lo único que tendrás es la muerte!,,"Voi voi. Sen kyllä voin sinulle luvata, että kuolet!","Dommage. Tout ce que vous allez recevoir, c'est votre mort!","Így jártál. Az egyetlen dolog amit kapsz, az a halál.",Peccato. L'unica cosa che otterrai è la morte.,残念だな、お前にやれるものは死のみだ!,안됐네. 넌 여기서 죽게 될테니까!,Jammer. Het enige wat je krijgt is de dood!,"Synd for deg. Det eneste du får, er døden!",Szkoda. Jedyne co dostaniesz to śmierć!,Que pena. A única coisa que você vai receber é a morte!,,Păcat. Tot ce vei primi e moarte!,"Увы. Всё, что ты получишь, — это смерть!",,Çok yazık. Alacağın tek şey ölüm! -We're going to kill you!,TXT_DLG_SCRIPT33_D28804_WEREG,,,,Zabijeme tě!,Vi slår dig ihjel!,Wir werden euch töten!,,,¡Vamos a matarte!,,Tapamme sinut!,On va te buter!,Megölünk!,Adesso ti ammazziamo!,お前をぶっ殺す!,우린 널 죽일 거야!,We gaan je vermoorden!,Vi skal drepe deg!,Zabijemy cię!,Nós vamos te matar!,,Te vom omorâ!,Готовься к смерти!,,Seni öldüreceğiz! -Get out of here!,TXT_DLG_SCRIPT33_D30320_GETOU,,,,Vypadni odsud!,Forsvind herfra!,Verschwinde von hier!,,,¡Sal de aquí!,,Häivy täältä!,Sortez de là!,Pusztulj innen!,Fuori di qui!,ここから立ち去れ!,여길 나가!,Maak dat je hier wegkomt!,Forsvinn herfra!,Wynoś się stąd!,Saia daqui!,,Valea!,Убирайся отсюда!,,Defolun buradan! -We're going to kill you!,TXT_DLG_SCRIPT33_D31836_WEREG,,,,Zabijeme tě!,Vi slår dig ihjel!,Wir werden euch töten!,,,¡Vamos a matarte!,,Tapamme sinut!,On va te buter!,Megölünk!,Adesso ti ammazziamo!,お前をぶっ殺す!,널 죽이는걸 즐길테다.,We gaan je vermoorden!,Vi skal drepe deg!,Zabijemy cię!,Nós vamos te matar!,,Te vom omorâ!,Готовься к смерти!,,Seni öldüreceğiz! -Get out of here!,TXT_DLG_SCRIPT33_D33352_GETOU,,,,Vypadni odsud!,Kom ud herfra!,Verschwinde von hier!,,,¡Sal de aquí!,,Häivy täältä!,Sortez de là!,Pusztulj innen!,Fuori di qui!,ここから立ち去れ!,여기서 뭐하는 거야? 꺼져!,Maak dat je wegkomt!,Forsvinn herfra!,Wynoś się stąd!,Saia daqui!,,Valea!,Убирайся отсюда!,,Defolun buradan! -"What a perfect place for us, under the old town hall. The Order thinks they've wiped us out, but all it was is a reminder to us of what can happen when you become careless. ",TXT_DLG_SCRIPT34_D0_WHATA,MAP34: Barracks,,,"Tady pod starou radnicí to je pro nás ideální místo. Řád si myslí, že nás vyhladil, ale pouze nám připomněl, co se může stát, když jsi neopatrný.","Sikke et perfekt sted for os, under det gamle rådhus. Ordenen tror, at de har udryddet os, men det var blot en påmindelse til os om, hvad der kan ske, når man bliver uforsigtig.","Was für ein Perfekter Ort für uns, unter dem alten Rathaus. Der Orden glaubt, er hätte uns vernichtet, aber es war nur ein Denkzettel für uns, was passieren kann wenn man unaufmerksam ist.",,,"Que lugar tan perfecto para nosotros, bajo el antiguo ayuntamiento. La Orden cree que nos ha aniquilado, pero todo lo que ha sido es un recordatorio para nosotros de lo que puede pasar cuando te descuidas.",,"Tämähän on täydellinen paikka meille, vanhan kaupungintalon alla. Veljeskunta luulee hävittäneensä meidät, mutta se toimi meille ainoastaan muistutuksena siitä, mitä voi tapahtua, kun tulee varomattomaksi.","Quel endroit parafait pour nous, sous la mairie. L'Ordre pense qu'ils nous ont tous tués, mais ça leur servira de leçon, ils verront se qu'il se passe quand on ne fait pas attention..","A városháza alatt, micsoda tökéletes hely. A Rend azt hiszi kiírtott mindőnket, de ez csak egy emlékeztető volt arra, hogy mi történik ha felelőtlenek vagyunk.","È davvero un posto perfetto per noi, sotto il vecchio municipio. L'Ordine pensa di averci spazzato via, ma è stato solo un avvertimento di cosa può succederci se siamo troppo incauti.","旧市庁舎の下で、 +",그래서 네가 그 성배를 훔친 바보로군? 반군 절도범으로 체포해주지... 오더에서의 내 위치도 올리는 겸. 모르는 사이에 장물아비가 된 기분이 어떤가?,Dus jij bent de dwaas die de kelk heeft gestolen? Ik ga je laten arresteren als rebelse dief.... Daardoor verbeter ik mijn positie bij de Orde. Hoe voelt het om een onwetende pion te zijn?,Så du er tosken som stjal begeret? Jeg skal få deg arrestert som en opprørsk tyv... Og dermed styrke min posisjon i Ordenen. Hvordan føles det å være en uvitende brikke?,"Więc to ty jesteś tym głupcem, który ukradł kielich? Każę cię aresztować jako buntowniczego złodzieja... Tym samym wzmocnię swoją pozycję w Zakonie. Jakie to uczucie być nieświadomym pionkiem?",Então você é o idiota que roubou o cálice? Eu vou prender você por ser um ladrão rebelde... E assim vou melhorar minha posição com a Ordem. Como se sente sendo um plebeu ignorante?,,Deci tu ești tolomacul care a furat potirul? Am să te arestez drept un hoț rebel... Prin urmare crescând in rangurile Ordinului. Cum e să fii un pion?,"Так это ты тот недоумок, что украл чашу? Я передам тебя Ордену, как вора повстанцев... Это укрепит мои отношения с ним. Каково чувствовать себя безмозглой пешкой?",,Så du är dåren som stal kalken? Jag kommer att låta arrestera dig som en upprorisk tjuv... och därmed förbättra min ställning i orden. Hur känns det att vara en ovetande bricka?,Demek kadehi çalan aptal sensin? Seni asi bir hırsız olarak tutuklatacağım. Böylece Tarikat'taki konumumu güçlendireceğim. Farkında olmadan bir piyon olmak nasıl bir duygu? +It sucks!,TXT_RPLY0_SCRIPT33_D27288_ITSUC,〃,,,Je to na hovno!,Det stinker!,Scheiße!,,Tio estas aĉa!,¡Apesta!,,Ihan perseestä!,Quelle merde!,Ez szopás!,È uno schifo!,クソが!,기분이 아주 좆같아.,Het is klote!,Det suger!,Do dupy!,É uma merda!,,Nașpa!,Чтоб ты сдох!,,Det suger!,Berbat! +For you it does.,TXT_RYES0_SCRIPT33_D27288_FORYO,〃,,,Pro tebe určitě.,For dig gør det.,Du steckst ganz tief drin.,,Por vi ja.,Para ti sí.,,"Kyllä, sinun tilanteesi.","Pour vous, en effet.",...és a bráner rossz végén vagy.,Ti faccio vedere io!,私もそう思う。,더한 기분이 들게 해주지.,Voor jou wel.,For deg gjør det det.,Dla ciebie tak.,"Pra você, é mesmo.",,"Pentru tine, într-adevăr este.",Скоро сдохнешь ты.,,För dig gör det det.,Senin için öyle. +Harris promised me money!,TXT_RPLY1_SCRIPT33_D27288_HARRI,〃,,,Harris mi slíbil peníze!,Harris lovede mig penge!,Harris hat mir Geld versprochen!,,Harris promesis monon al mi!,¡Harris me prometió dinero!,,Harris lupasi minulle rahaa!,Harris m'a promis de l'argent!,Harris pénzt ígért nekem.,Harris mi ha promesso dei soldi!,ハリスは俺に金を渡すと約束したのに!,해리스가 날 배신했어... 이 새끼!,Harris beloofde me geld!,Harris lovet meg penger!,Harris obiecał mi pieniądze!,O Harris prometeu me pagar!,,Harris mi-a promis bani!,Харрис обещал мне деньги!,,Harris lovade mig pengar!,Harris bana para sözü verdi! +Too bad. The only thing you're getting is death!,TXT_RYES1_SCRIPT33_D27288_TOOBA,〃,,,"Smůla. Jediné, co dostaneš, je smrt!","Det var ærgerligt. Det eneste, du får, er døden!",Jammerschade. Das Einzige was du bekommen wirst ist der Tod!,,"Kiel domaĝe. Ĉio, kion +vi havos estas morto!","Qué mal. ¡Lo único que +tendrás es la muerte!","Qué mal. ¡Lo único que +vas a tener es la muerte!","Voi voi. Sen kyllä voin sinulle luvata, että kuolet!","Dommage. Tout ce que vous allez recevoir, c'est votre mort!","Így jártál. Az egyetlen dolog amit kapsz, az a halál.",Peccato. L'unica cosa che otterrai è la morte.,残念だな、お前にやれるものは死のみだ!,안됐네. 넌 여기서 죽게 될테니까!,Jammer. Het enige wat je krijgt is de dood!,"Synd for deg. Det eneste du får, er døden!",Szkoda. Jedyne co dostaniesz to śmierć!,Que pena. A única coisa que você vai receber é a morte!,,Păcat. Tot ce vei primi e moarte!,"Увы. Всё, что ты получишь, — это смерть!",,Det var synd. Det enda du får är döden!,Çok yazık. Alacağın tek şey ölüm! +We're going to kill you!,TXT_DLG_SCRIPT33_D28804_WEREG,,,,Zabijeme tě!,Vi slår dig ihjel!,Wir werden euch töten!,,Ni mortigos vin!,¡Te vamos a matar!,,Tapamme sinut!,On va te buter!,Megölünk!,Adesso ti ammazziamo!,お前をぶっ殺す!,우린 널 죽일 거야!,We gaan je vermoorden!,Vi skal drepe deg!,Zabijemy cię!,Nós vamos te matar!,,Te vom omorâ!,Готовься к смерти!,,Vi ska döda dig!,Seni öldüreceğiz! +Get out of here!,TXT_DLG_SCRIPT33_D30320_GETOU,,,,Vypadni odsud!,Forsvind herfra!,Verschwinde von hier!,,Foriru!,¡Sal de aquí!,,Häivy täältä!,Sortez de là!,Pusztulj innen!,Fuori di qui!,ここから立ち去れ!,여길 나가!,Maak dat je hier wegkomt!,Forsvinn herfra!,Wynoś się stąd!,Saia daqui!,,Valea!,Убирайся отсюда!,,Stick härifrån!,Defolun buradan! +We're going to kill you!,TXT_DLG_SCRIPT33_D31836_WEREG,MAP33: Green acolytes (beginning).,,,Zabijeme tě!,Vi slår dig ihjel!,Wir werden euch töten!,,Ni mortigos vin!,¡Te vamos a matar!,,Tapamme sinut!,On va te buter!,Megölünk!,Adesso ti ammazziamo!,お前をぶっ殺す!,널 죽이는걸 즐길테다.,We gaan je vermoorden!,Vi skal drepe deg!,Zabijemy cię!,Nós vamos te matar!,,Te vom omorâ!,Готовься к смерти!,,Vi ska döda dig!,Seni öldüreceğiz! +Get out of here!,TXT_DLG_SCRIPT33_D33352_GETOU,MAP33: Yellow acolytes.,,,Vypadni odsud!,Kom ud herfra!,Verschwinde von hier!,,Foriru!,¡Sal de aquí!,,Häivy täältä!,Sortez de là!,Pusztulj innen!,Fuori di qui!,ここから立ち去れ!,여기서 뭐하는 거야? 꺼져!,Maak dat je wegkomt!,Forsvinn herfra!,Wynoś się stąd!,Saia daqui!,,Valea!,Убирайся отсюда!,,Stick härifrån!,Defolun buradan! +"What a perfect place for us, under the old town hall. The Order thinks they've wiped us out, but all it was is a reminder to us of what can happen when you become careless. ",TXT_DLG_SCRIPT34_D0_WHATA,MAP34: Barracks.,,,"Tady pod starou radnicí to je pro nás ideální místo. Řád si myslí, že nás vyhladil, ale pouze nám připomněl, co se může stát, když jsi neopatrný.","Sikke et perfekt sted for os, under det gamle rådhus. Ordenen tror, at de har udryddet os, men det var blot en påmindelse til os om, hvad der kan ske, når man bliver uforsigtig.","Was für ein Perfekter Ort für uns, unter dem alten Rathaus. Der Orden glaubt, er hätte uns vernichtet, aber es war nur ein Denkzettel für uns, was passieren kann wenn man unaufmerksam ist.",,"Kia perfekta kaŝejo por ni: sub la antikva urbodomo. La Ordeno kredas, ke ĝi ekstermis nin, sed ĉi tio estis nur memoraĵo pri tio, kio povas okazi kiam ni estas senatentaj.","Qué lugar tan perfecto para nosotros: bajo el antiguo ayuntamiento. La Orden cree habernos aniquilado, pero solo ha sido un recordatorio de lo que puede pasar al descuidarnos.",,"Tämähän on täydellinen paikka meille, vanhan kaupungintalon alla. Veljeskunta luulee hävittäneensä meidät, mutta se toimi meille ainoastaan muistutuksena siitä, mitä voi tapahtua, kun tulee varomattomaksi.","Quel endroit parafait pour nous, sous la mairie. L'Ordre pense qu'ils nous ont tous tués, mais ça leur servira de leçon, ils verront se qu'il se passe quand on ne fait pas attention..","A városháza alatt, micsoda tökéletes hely. A Rend azt hiszi kiírtott mindőnket, de ez csak egy emlékeztető volt arra, hogy mi történik ha felelőtlenek vagyunk.","È davvero un posto perfetto per noi, sotto il vecchio municipio. L'Ordine pensa di averci spazzato via, ma è stato solo un avvertimento di cosa può succederci se siamo troppo incauti.","旧市庁舎の下で、 私たちにとって何という完璧な場所です。 秩序は彼らが私たちを消滅させたと考 えていますが、それがすべてだったのは あなたが不注意になったときに起こり得ることを -私たちに思い出させるものです。","정말 경치 좋지? 이 박살 난 시청 주변에서. 오더 놈들이 우리들을 전멸했다고 자랑하는데, 우리들이 힘을 모아서 복수하기 전까진 그렇게 놓아두는 게 좋을 것 같아.","Wat een perfecte plek voor ons, onder het oude stadhuis. De Orde denkt dat ze ons hebben weggevaagd, maar het enige wat ons eraan herinnert is wat er kan gebeuren als je onzorgvuldig wordt.","For et perfekt sted for oss, under det gamle rådhuset. Ordenen tror de har utslettet oss, men det var bare en påminnelse om hva som kan skje når man er uforsiktig.","Co za idealne miejsce dla nas, pod starym ratuszem. Zakon myśli, że nas wymazał, ale to było tylko przypomnienie nam, co może się stać, gdy staniesz się nieostrożny.","Que lugar perfeito para nós, abaixo da antiga prefeitura. A Ordem pensa que nos aniquilou, mas aquilo tudo foi para lembrarmos do que pode acontecer quando você não é cauteloso.",,"Ce loc perfect pentru noi, exact sub vechea hală a orașului. Oridnul crede că ne-a ras pe toți, dar a fost doar o amintire pentru ceea ce se poate întâmpla când devi neglijent.","Здесь, под городской ратушей, такое чудесное место для нашей базы! Орден думает, что мы разгромлены, но мы всего лишь усвоили урок о цене беспечности.",,"Bizim için ne mükemmel bir yer, eski belediye binasının altı. Tarikat bizi yok ettiklerini sanıyor ama bu bize dikkatsiz davrandığımızda neler olabileceğini hatırlattı." -"Talk to Macil, he'll be able to help you.",TXT_DLG_SCRIPT34_D1516_TALKT,MAP34,,,Promluv si s Macilem. On ti pomůže.,"Tal med Macil, han vil kunne hjælpe dig.",Rede mit Macil. Er kann dir helfen.,,,"Habla con Macil, él podrá ayudarte.",,Puhu Macilille. Hän pystyy auttamaan sinua.,Parlez à Macil. Il pourra vous aider.,"Beszélj Macillal, majd ő segít.","Parla con Macil, lui sarà in grado di aiutarti.",マシルと話すんだ。彼から援助が得られるはず。,"마실 사령관님에게 말해, 그가 널 도울 수 있을 거야.","Praat met Macil, hij zal je kunnen helpen.",Snakk med Macil. Han kan hjelpe deg.,"Porozmawiaj z Macil, on będzie w stanie ci pomóc.",Fale com o Macil. Ele vai poder te ajudar.,,"Vorbește cu Macil, el te poate ajuta.",Обратись к Мэйсилу. Он поможет тебе.,,"Macil'le konuş, sana yardım edebilir." -I've heard that Macil's going to start something again soon. We need a big hit after the last fiasco. One more like that and we'll be too weak to continue.,TXT_DLG_SCRIPT34_D3032_IVEHE,MAP34: Barracks,,,"Slyšel jsem, že Macil má v plánu brzy něco znovu podniknout. Potřebujeme něco velkého po posledním fiasku. Ještě jednou něco takového a budeme příliš slabí pokračovat.","Jeg har hørt, at Macil snart vil starte noget igen. Vi har brug for et stort hit efter den sidste fiasko. En mere af den slags, og vi vil være for svage til at fortsætte.","Ich habe gehört, Macil hätte einen Plan um den Orden zu unterwandern. Ich hoffe mal, er taugt was. Noch ein Fehlschlag und wir können uns gleich begraben lassen.",,,He oído que Macil va a empezar algo nuevo pronto. Necesitamos un buen golpe después del último fiasco. Uno más como ese y seremos demasiado débiles para continuar.,,"Kuulin, että Macil alkaa taas viritellä jotain. Tarvitsemme jättionnistumisen edellisen fiaskon jälkeen. Vielä yksikin samanlainen, ja olemme liian heikkoja jatkamaan.",J'entends que Macil va essayer de faire quelque chose bientôt. Il nous faut frapper un grand coup après le dernier fiasco. Encore un comme celui-ci et on sera trop affaibli pour continuer.,"Az a hír járja, hogy Macil újra készül valamire. Kell egy nagy fogás a múltkori fiaskó után. Még egy ilyen, és túl gyengék leszünk a folytatáshoz.",Ho sentito che Macil ha intenzione di partire all'attacco molto presto. Abbiamo bisogno di un grosso colpo dopo l'ultimo disastro. Se subiamo un'altra sconfitta del genere saremo troppo deboli per continuare.,"私はマシルがオーダーを転覆させる計画を +私たちに思い出させるものです。","정말 경치 좋지? 이 박살 난 시청 주변에서. 오더 놈들이 우리들을 전멸했다고 자랑하는데, 우리들이 힘을 모아서 복수하기 전까진 그렇게 놓아두는 게 좋을 것 같아.","Wat een perfecte plek voor ons, onder het oude stadhuis. De Orde denkt dat ze ons hebben weggevaagd, maar het enige wat ons eraan herinnert is wat er kan gebeuren als je onzorgvuldig wordt.","For et perfekt sted for oss, under det gamle rådhuset. Ordenen tror de har utslettet oss, men det var bare en påminnelse om hva som kan skje når man er uforsiktig.","Co za idealne miejsce dla nas, pod starym ratuszem. Zakon myśli, że nas wymazał, ale to było tylko przypomnienie nam, co może się stać, gdy staniesz się nieostrożny.","Que lugar perfeito para nós, abaixo da antiga prefeitura. A Ordem pensa que nos aniquilou, mas aquilo tudo foi para lembrarmos do que pode acontecer quando você não é cauteloso.",,"Ce loc perfect pentru noi, exact sub vechea hală a orașului. Oridnul crede că ne-a ras pe toți, dar a fost doar o amintire pentru ceea ce se poate întâmpla când devi neglijent.","Здесь, под городской ратушей, такое чудесное место для нашей базы! Орден думает, что мы разгромлены, но мы всего лишь усвоили урок о цене беспечности.",,"Vilken perfekt plats för oss, under det gamla stadshuset. Orden tror att de har utplånat oss, men det var bara en påminnelse för oss om vad som kan hända när man blir oförsiktig.","Bizim için ne mükemmel bir yer, eski belediye binasının altı. Tarikat bizi yok ettiklerini sanıyor ama bu bize dikkatsiz davrandığımızda neler olabileceğini hatırlattı." +"Talk to Macil, he'll be able to help you.",TXT_DLG_SCRIPT34_D1516_TALKT,MAP34,,,Promluv si s Macilem. On ti pomůže.,"Tal med Macil, han vil kunne hjælpe dig.",Rede mit Macil. Er kann dir helfen.,,Parolu kun Macil. Li povos helpi vin.,Habla con Macil. Él te podrá ayudar.,Habla con Macil. Él te va a poder ayudar.,Puhu Macilille. Hän pystyy auttamaan sinua.,Parlez à Macil. Il pourra vous aider.,"Beszélj Macillal, majd ő segít.","Parla con Macil, lui sarà in grado di aiutarti.",マシルと話すんだ。彼から援助が得られるはず。,"마실 사령관님에게 말해, 그가 널 도울 수 있을 거야.","Praat met Macil, hij zal je kunnen helpen.",Snakk med Macil. Han kan hjelpe deg.,"Porozmawiaj z Macil, on będzie w stanie ci pomóc.",Fale com o Macil. Ele vai poder te ajudar.,,"Vorbește cu Macil, el te poate ajuta.",Обратись к Мэйсилу. Он поможет тебе.,,"Prata med Macil, han kommer att kunna hjälpa dig.","Macil'le konuş, sana yardım edebilir." +I've heard that Macil's going to start something again soon. We need a big hit after the last fiasco. One more like that and we'll be too weak to continue.,TXT_DLG_SCRIPT34_D3032_IVEHE,MAP34: Barracks.,,,"Slyšel jsem, že Macil má v plánu brzy něco znovu podniknout. Potřebujeme něco velkého po posledním fiasku. Ještě jednou něco takového a budeme příliš slabí pokračovat.","Jeg har hørt, at Macil snart vil starte noget igen. Vi har brug for et stort hit efter den sidste fiasko. En mere af den slags, og vi vil være for svage til at fortsætte.","Ich habe gehört, Macil hätte einen Plan um den Orden zu unterwandern. Ich hoffe mal, er taugt was. Noch ein Fehlschlag und wir können uns gleich begraben lassen.",,"Mi aŭdis, ke Macil baldaŭ komencos ion novan. Ni bezonas grandan trafon post la lasta fiasko: ankoraŭ unu kaj ni estos sufiĉe malfortaj por daŭrigi.",He oído que Macil va a empezar algo nuevo pronto. Necesitamos algo bueno después del último fiasco: uno más así y seremos demasiado débiles para continuar.,Oí que Macil va a empezar algo nuevo pronto. Necesitamos algo bueno después del último fracaso: uno más así y vamos a ser demasiado débiles para continuar.,"Kuulin, että Macil alkaa taas viritellä jotain. Tarvitsemme jättionnistumisen edellisen fiaskon jälkeen. Vielä yksikin samanlainen, ja olemme liian heikkoja jatkamaan.",J'entends que Macil va essayer de faire quelque chose bientôt. Il nous faut frapper un grand coup après le dernier fiasco. Encore un comme celui-ci et on sera trop affaibli pour continuer.,"Az a hír járja, hogy Macil újra készül valamire. Kell egy nagy fogás a múltkori fiaskó után. Még egy ilyen, és túl gyengék leszünk a folytatáshoz.",Ho sentito che Macil ha intenzione di partire all'attacco molto presto. Abbiamo bisogno di un grosso colpo dopo l'ultimo disastro. Se subiamo un'altra sconfitta del genere saremo troppo deboli per continuare.,"私はマシルがオーダーを転覆させる計画を 持っていると聞いた。そうだと良かったが。 -我々は一度大敗し全滅しかけた。",마실 사령관이 또 다른 작전을 준비한데. 그전에 일어났던 대참사보다 훨씬 나은 작전이었으면 좋겠는데. 운이 나쁘면 많은 병력을 잃어버릴 것 같아.,Ik heb gehoord dat Macil binnenkort weer met iets gaat beginnen. We hebben een grote hit nodig na het laatste fiasco. Nog zo'n hit en dan zijn we te zwak om verder te gaan.,"Jeg har hørt at Macil skal starte noe igjen snart. Vi trenger en stor hit etter den siste fiaskoen. En til, så er vi for svake til å fortsette.","Słyszałem, że Macil ma zamiar wkrótce znowu coś zacząć. Potrzebujemy dużego uderzenia po ostatnim fiasku. Jeszcze jedno takie i będziemy zbyt słabi, by kontynuować.",Fiquei sabendo que o Macil planeja começar algo logo. Precisamos acertar um grande golpe depois do último fiasco. Se aquilo se repetir nós não teremos força para continuar.,,Am auzit că Macil va începe ceva curând. Trebuie să dăm lovitura după ultimul fiasco. Încă unul și vom fi prea slabi să continuăm.,"Я слышал, что Мэйсил готовит новую операцию после провала предыдущей. Она должна быть крайне успешной. После второго такого провала мы уже не оправимся.",,Macil'in yakında yeniden bir şeyler başlatacağını duydum. Son fiyaskodan sonra büyük bir vuruşa ihtiyacımız var. Bir daha böyle bir şey olursa devam edemeyecek kadar zayıf düşeriz. -A few of these barrels dumped into their water supply should even the odds a little. ,TXT_DLG_SCRIPT34_D4548_AFEWO,〃,,,Pár těhle sudů v jejich zásobách vody by nám mělo alespoň trochu pomoct.,Et par af disse tønder dumpet i deres vandforsyning burde udligne oddsene lidt.,"Wenn wir ein paar von diesen Fässern in die Wasserversorgung kippen, sollte das unsere Chancen etwas verbessern.",,,Unos cuantos de estos barriles arrojados a su suministro de agua debería igualar las probabilidades un poco.,,Muutaman tällaisen tynnyrin kaataminen heidän vedenjakeluunsa varmaankin hieman tasoittaisi tilannetta.,Quelques tonneaux vidés dans leur réserve d'eau devrait aplanir le terrain de jeu.,Kicsit kiegyenlíti az erőviszonyokat ha ezt a pár hordót beleöntjük a víztározójukba.,Un paio di questi barili rovesciati dentro la loro fornitura d'acqua dovrebbero bilanciare un pò le cose.,"ここの樽は捨てられていた物で -彼らの給水を補っている。","놈들의 상수도에서 내려온 이 통들, 이상하지 않아? 뭔가 승산이 있을 것 같아.","Een paar van deze vaten die in hun watertoevoer gedumpt worden, zullen de kans op een beetje gelijk zijn.",Et par av disse tønnene dumpet i vannforsyningen deres burde jevne ut oddsene litt.,Kilka tych beczek wrzuconych do ich wodociągów powinno trochę wyrównać szanse.,Alguns desses barris despejados no estoque de água deles deve melhorar um pouco as nossas chances.,,Câteva butoaie aruncate în rezerva lor de apă ar trebui să egaleze șansele.,"Несколько таких бочек, сброшенных в их водоснабжение, причинят немало неприятностей.",,Bu varillerden birkaçını su kaynaklarına boşaltmak olasılıkları biraz olsun eşitler. +我々は一度大敗し全滅しかけた。",마실 사령관이 또 다른 작전을 준비한데. 그전에 일어났던 대참사보다 훨씬 나은 작전이었으면 좋겠는데. 운이 나쁘면 많은 병력을 잃어버릴 것 같아.,Ik heb gehoord dat Macil binnenkort weer met iets gaat beginnen. We hebben een grote hit nodig na het laatste fiasco. Nog zo'n hit en dan zijn we te zwak om verder te gaan.,"Jeg har hørt at Macil skal starte noe igjen snart. Vi trenger en stor hit etter den siste fiaskoen. En til, så er vi for svake til å fortsette.","Słyszałem, że Macil ma zamiar wkrótce znowu coś zacząć. Potrzebujemy dużego uderzenia po ostatnim fiasku. Jeszcze jedno takie i będziemy zbyt słabi, by kontynuować.",Fiquei sabendo que o Macil planeja começar algo logo. Precisamos acertar um grande golpe depois do último fiasco. Se aquilo se repetir nós não teremos força para continuar.,,Am auzit că Macil va începe ceva curând. Trebuie să dăm lovitura după ultimul fiasco. Încă unul și vom fi prea slabi să continuăm.,"Я слышал, что Мэйсил готовит новую операцию после провала предыдущей. Она должна быть крайне успешной. После второго такого провала мы уже не оправимся.",,Jag har hört att Macil snart ska starta något igen. Vi behöver en stor succé efter det senaste fiaskot. En sån där till och vi blir för svaga för att fortsätta.,Macil'in yakında yeniden bir şeyler başlatacağını duydum. Son fiyaskodan sonra büyük bir vuruşa ihtiyacımız var. Bir daha böyle bir şey olursa devam edemeyecek kadar zayıf düşeriz. +A few of these barrels dumped into their water supply should even the odds a little. ,TXT_DLG_SCRIPT34_D4548_AFEWO,〃,,,Pár těhle sudů v jejich zásobách vody by nám mělo alespoň trochu pomoct.,Et par af disse tønder dumpet i deres vandforsyning burde udligne oddsene lidt.,"Wenn wir ein paar von diesen Fässern in die Wasserversorgung kippen, sollte das unsere Chancen etwas verbessern.",,Ĵeti kelkajn el ĉi tiuj bareloj en ilian akvo-provizadon devus egaligi iomete la eblojn.,Tirar unos cuantos de estos barriles a su suministro de agua debería igualar un poco las probabilidades.,,Muutaman tällaisen tynnyrin kaataminen heidän vedenjakeluunsa varmaankin hieman tasoittaisi tilannetta.,Quelques tonneaux vidés dans leur réserve d'eau devrait aplanir le terrain de jeu.,Kicsit kiegyenlíti az erőviszonyokat ha ezt a pár hordót beleöntjük a víztározójukba.,Un paio di questi barili rovesciati dentro la loro fornitura d'acqua dovrebbero bilanciare un po' le cose.,"ここの樽は捨てられていた物で +彼らの給水を補っている。","놈들의 상수도에서 내려온 이 통들, 이상하지 않아? 뭔가 승산이 있을 것 같아.","Een paar van deze vaten die in hun watertoevoer gedumpt worden, zullen de kans op een beetje gelijk zijn.",Et par av disse tønnene dumpet i vannforsyningen deres burde jevne ut oddsene litt.,Kilka tych beczek wrzuconych do ich wodociągów powinno trochę wyrównać szanse.,Alguns desses barris despejados no estoque de água deles deve melhorar um pouco as nossas chances.,,Câteva butoaie aruncate în rezerva lor de apă ar trebui să egaleze șansele.,"Несколько таких бочек, сброшенных в их водоснабжение, причинят немало неприятностей.",,Några av de här tunnorna dumpade i deras vattenförsörjning borde jämna ut oddsen lite.,Bu varillerden birkaçını su kaynaklarına boşaltmak olasılıkları biraz olsun eşitler. I'm working on something that will give us an edge. It will increase your stamina and completely jack you up. I've almost got all the bugs worked out. Can I do something for you? ,TXT_DLG_SCRIPT34_D6064_IMWOR,"MAP34: Gerald. -(Except for row 1335, everything in rows 1323-1343 is identical to 725-745)",,,"Pracuju na něčem, co by nám mělo pomoci. Přidá ti to výdrž a naprosto tě to napumpuje. Už jsem skoro vychytal všechny mouchy. Co pro tebe mohu udělat?","Jeg arbejder på noget, der vil give os en fordel. Det vil øge din udholdenhed og gøre dig helt oppe at køre. Jeg har næsten fået styr på alle fejlene. Må jeg gøre noget for dig?","Ich arbeite an etwas, das uns einen Vorteil verschaffen kann. Es würde deine Ausdauer erhöhen und dir Superkräfte verleihen. Kann ich was für dich tun?",,"Mi laboras super io, kio donos avantaĝon al ni: ĝi pliigos vian energion kaj korpan forton. Mi jam korektis la plimulton de la difektoj. Ĉu mi povas fari ion por vi?",Estoy trabajando en algo que nos dará una ventaja: aumentará tu aguante y fuerza física. Ya casi tengo todos los fallos corregidos. ¿Puedo hacer algo por ti?,Estoy trabajando en algo que nos va a dar una ventaja: va a aumentar tu aguante y fuerza física. Ya casi tengo todos los fallos corregidos. ¿Puedo hacer algo por ti?,"Olen paraikaa työstämässä jotain, joka antaa meille etulyöntiaseman. Se kasvattaa kuntoasi ja täydellisesti virittää lihaksesi. Olen melkein saanut hiottua kaikki viat. Voinko olla jotenkin avuksi?",Je travaille sur quelque chose qui nous donnera un peu d'avance. Ca devrait augmenter votre endurance et vous donner un sacré coup de jus. Je crois que j'ai corrigé presque tous les bugs. Je peux vous aider?,"Dolgozok valamin, ami egy jelentősebb előnyhöz juttat minket. Megerősíti az állóképességedet és teljesen felpumpálja a tested. Már majdnem kiküszöböltem a hibákat. Amúgy tudok valamiben segíteni?",Sto lavorando a qualcosa che ci darà un notevole vantaggio. Aumenterà la tua resistenza e ti farà sentire molto più forte. Ho quasi risolto tutti gli effetti collaterali. Posso fare qualcosa per te?,"私は研究にも取り組んでいる。貴方のスタミナを +(Except for row 1335, everything in rows 1323-1343 is identical to 725-745)",,,"Pracuju na něčem, co by nám mělo pomoci. Přidá ti to výdrž a naprosto tě to napumpuje. Už jsem skoro vychytal všechny mouchy. Co pro tebe mohu udělat?","Jeg arbejder på noget, der vil give os en fordel. Det vil øge din udholdenhed og gøre dig helt oppe at køre. Jeg har næsten fået styr på alle fejlene. Må jeg gøre noget for dig?","Ich arbeite an etwas, das uns einen Vorteil verschaffen kann. Es würde deine Ausdauer erhöhen und dir Superkräfte verleihen. Kann ich was für dich tun?",,"Mi laboras super io, kio donos avantaĝon al ni: ĝi pliigos vian energion kaj korpan forton. Mi jam korektis la plimulton de la cimoj. Ĉu mi povas fari ion por vi?",Estoy trabajando en algo que nos dará una ventaja: aumentará tu aguante y fuerza física. Ya casi tengo todos los fallos corregidos. ¿Puedo hacer algo por ti?,Estoy trabajando en algo que nos va a dar una ventaja: va a aumentar tu aguante y fuerza física. Ya casi tengo todos los fallos corregidos. ¿Puedo hacer algo por ti?,"Olen paraikaa työstämässä jotain, joka antaa meille etulyöntiaseman. Se kasvattaa kuntoasi ja täydellisesti virittää lihaksesi. Olen melkein saanut hiottua kaikki viat. Voinko olla jotenkin avuksi?",Je travaille sur quelque chose qui nous donnera un peu d'avance. Ca devrait augmenter votre endurance et vous donner un sacré coup de jus. Je crois que j'ai corrigé presque tous les bugs. Je peux vous aider?,"Dolgozok valamin, ami egy jelentősebb előnyhöz juttat minket. Megerősíti az állóképességedet és teljesen felpumpálja a tested. Már majdnem kiküszöböltem a hibákat. Amúgy tudok valamiben segíteni?",Sto lavorando a qualcosa che ci darà un notevole vantaggio. Aumenterà la tua resistenza e ti farà sentire molto più forte. Ho quasi risolto tutti gli effetti collaterali. Posso fare qualcosa per te?,"私は研究にも取り組んでいる。貴方のスタミナを 増強し完璧な体にすることも可能だ。 そのインプラントのバグも殆ど取り除かれている -ところで何か必要かい?","아주 유용하고 승패를 가릴 수 있는 비장의 카드를 연구 중입니다. 바로 지구력 향상 이식 칩이죠. 이것만 있으면 체력과 힘을 증가시킵니다. 거의 완성되었어요. 이제, 뭘 도와드릴까요?",Ik werk aan iets dat ons een voorsprong geeft. Het zal je uithoudingsvermogen verhogen en je helemaal opkrikken. Ik heb bijna alle bugs uitgewerkt. Kan ik iets voor u doen?,Jeg jobber med noe som vil gi oss en fordel. Det vil øke utholdenheten din og løfte deg helt opp. Jeg har nesten løst alle problemene. Kan jeg gjøre noe for deg?,"Pracuję nad czymś, co da nam przewagę. Zwiększy to twoją wytrzymałość i całkowicie cię podnieci. Mam już prawie dopracowane wszystkie błędy. Mogę coś dla ciebie zrobić?",Estou trabalhando em algo que vai nos dar um impulso. É algo que vai aumentar sua resistência e te deixar bem mais forte. Estou com quase todos os bugs resolvidos. Posso te ajudar com algo?,,Lucrez la ceva ce ne va da un avantaj. Îți va crește rezistența și forța. Am rezolvat aproape toate problemele. Pot să te ajut cu ceva acum?,"Я работаю кое над чем, что может нам пригодиться. Оно увеличит твою выносливость и улучшит самочувствие. Я уже исправил почти все дефекты. Или тебе нужно что-то ещё?",,Bize avantaj sağlayacak bir şey üzerinde çalışıyorum. Dayanıklılığınızı arttıracak ve sizi tamamen güçlendirecek. Neredeyse tüm hataları çözdüm. Senin için bir şey yapabilir miyim? -Patch me up.,TXT_RPLY0_SCRIPT34_D6064_PATCH,〃,,,Dej mě do hromady.,Løs mig op.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Hoida minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lappe meg sammen.,Załataj mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня.,,Beni yamala. +ところで何か必要かい?","아주 유용하고 승패를 가릴 수 있는 비장의 카드를 연구 중입니다. 바로 지구력 향상 이식 칩이죠. 이것만 있으면 체력과 힘을 증가시킵니다. 거의 완성되었어요. 이제, 뭘 도와드릴까요?",Ik werk aan iets dat ons een voorsprong geeft. Het zal je uithoudingsvermogen verhogen en je helemaal opkrikken. Ik heb bijna alle bugs uitgewerkt. Kan ik iets voor u doen?,Jeg jobber med noe som vil gi oss en fordel. Det vil øke utholdenheten din og løfte deg helt opp. Jeg har nesten løst alle problemene. Kan jeg gjøre noe for deg?,"Pracuję nad czymś, co da nam przewagę. Zwiększy to twoją wytrzymałość i całkowicie cię podnieci. Mam już prawie dopracowane wszystkie błędy. Mogę coś dla ciebie zrobić?",Estou trabalhando em algo que vai nos dar um impulso. É algo que vai aumentar sua resistência e te deixar bem mais forte. Estou com quase todos os bugs resolvidos. Posso te ajudar com algo?,,Lucrez la ceva ce ne va da un avantaj. Îți va crește rezistența și forța. Am rezolvat aproape toate problemele. Pot să te ajut cu ceva acum?,"Я работаю кое над чем, что может нам пригодиться. Оно увеличит твою выносливость и улучшит самочувствие. Я уже исправил почти все дефекты. Или тебе нужно что-то ещё?",,Jag arbetar på något som kommer att ge oss en fördel. Det kommer att öka din uthållighet och göra dig helt upprymd. Jag har nästan löst alla buggar. Kan jag göra något för dig?,Bize avantaj sağlayacak bir şey üzerinde çalışıyorum. Dayanıklılığınızı arttıracak ve sizi tamamen güçlendirecek. Neredeyse tüm hataları çözdüm. Senin için bir şey yapabilir miyim? +Patch me up.,TXT_RPLY0_SCRIPT34_D6064_PATCH,〃,,,Dej mě do hromady.,Løs mig op.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Hoida minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lappe meg sammen.,Załataj mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня.,,Laga mig.,Beni yamala. "Boy, you're a real mess. I'll see what I can do.",TXT_RYES0_SCRIPT34_D6064_BOYYO,〃,,,"Tebe teda zřídili, kluku. Uvidím, co s tebou.","Mand, du er et rigtigt rod. Jeg skal se, hvad jeg kan gøre.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,"Ulo, vi estas iomege en malordo. Mi vidos tion, kion mi faru.","Tío, estás hecho un desastre. A ver qué puedo hacer.","Chico, estás hecho un desastre. -A ver qué puedo hacer.","Voi pojat, oletpa hajalla. Katsotaan, mihin pystyn.","Mon petit, vous êtes dans un sale état. Je vais voir ce que je peux faire.","Öregem, elég ramaty állapotban vagy. Megnézem mit tehetek.","Ragazzo, sei messo proprio male. Vediamo cosa posso fare.",君、滅茶苦茶だな。なんとかしよう。,가능한 한 아프지 않게 치료하겠습니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","Jøss, du ser forferdelig ut. Jeg skal se hva jeg kan gjøre.","Chłopcze, jesteś w niezłym stanie. Zobaczę, co da się zrobić.","Rapaz, você está arrebentado. Verei o que posso fazer.",,"Băiete, ești un dezastru. O să văd ce pot face.","Ты просто месиво. Посмотрим, что я смогу сделать.",,"Evlat, gerçekten berbat durumdasın. Ne yapabileceğime bir bakayım." -Stamina implant?,TXT_RPLY1_SCRIPT34_D6064_STAMI,〃,,,Implantát pro výdrž?,Udholdenhedsimplantat?,Ausdauerimplantat?,,Ĉu energidona enplantaĵo?,¿Implante de aguante?,,Kuntoistute?,Implant d'endurance?,Állóképesség implantátum?,Impianto stamina?,スタミナインプラント?,지구력 향상 이식?,Stamina implantaat?,Utholdenhetsimplantat?,Implant wytrzymałościowy?,Implante de resistência?,,Implant de rezistență?,Выносливостный имплант?,,Dayanıklılık implantı mı? +A ver qué puedo hacer.","Voi pojat, oletpa hajalla. Katsotaan, mihin pystyn.","Mon petit, vous êtes dans un sale état. Je vais voir ce que je peux faire.","Öregem, elég ramaty állapotban vagy. Megnézem mit tehetek.","Ragazzo, sei messo proprio male. Vediamo cosa posso fare.",君、滅茶苦茶だな。なんとかしよう。,가능한 한 아프지 않게 치료하겠습니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","Jøss, du ser forferdelig ut. Jeg skal se hva jeg kan gjøre.","Chłopcze, jesteś w niezłym stanie. Zobaczę, co da się zrobić.","Rapaz, você está arrebentado. Verei o que posso fazer.",,"Băiete, ești un dezastru. O să văd ce pot face.","Ты просто месиво. Посмотрим, что я смогу сделать.",,Du är en riktig röra. Jag ska se vad jag kan göra.,"Evlat, gerçekten berbat durumdasın. Ne yapabileceğime bir bakayım." +Stamina implant?,TXT_RPLY1_SCRIPT34_D6064_STAMI,〃,,,Implantát pro výdrž?,Udholdenhedsimplantat?,Ausdauerimplantat?,,Ĉu energidona enplantaĵo?,¿Implante de aguante?,,Kuntoistute?,Implant d'endurance?,Állóképesség implantátum?,Impianto stamina?,スタミナインプラント?,지구력 향상 이식?,Stamina implantaat?,Utholdenhetsimplantat?,Implant wytrzymałościowy?,Implante de resistência?,,Implant de rezistență?,Выносливостный имплант?,,Ett uthållighetsimplantat?,Dayanıklılık implantı mı? "All right, this won't take but a moment.",TXT_RYES1_SCRIPT34_D6064_ALLRI,〃,,,"Dobře, tohle potrvá jen chvilku.","Okay, det tager kun et øjeblik.","Alles klar, das haben wir sofort.",,"Bonege, ĉi tio estos rapidega.","Muy bien, solo tomará un momento.","Muy bien, solo va a -tomar un momento.","Hyvä on, tähän ei mene hetkeä pidempään.","Pas de problème, ça ne prendra qu'un moment.","Rendben, nem vesz igénybe többet pár másodpercnél.","Va bene, ci vorrà solo un momento.",大丈夫、すぐ終わります。,많이 걸리진 않을거에요...,"Oké, dit duurt maar een momentje.",Dette tar bare et øyeblikk.,"Dobra, to zajmie tylko chwilę.","Ok, isso não vai demorar.",,"În regulă, va dura doar un moment.","Отлично, это займёт всего пару секунд.",,"Pekala, bu bir dakikadan fazla sürmez." +tomar un momento.","Hyvä on, tähän ei mene hetkeä pidempään.","Pas de problème, ça ne prendra qu'un moment.","Rendben, nem vesz igénybe többet pár másodpercnél.","Va bene, ci vorrà solo un momento.",大丈夫、すぐ終わります。,많이 걸리진 않을거에요...,"Oké, dit duurt maar een momentje.",Dette tar bare et øyeblikk.,"Dobra, to zajmie tylko chwilę.","Ok, isso não vai demorar.",,"În regulă, va dura doar un moment.","Отлично, это займёт всего пару секунд.",,"Okej, det här tar bara ett ögonblick.","Pekala, bu bir dakikadan fazla sürmez." It's not done yet.,TXT_RNO1_SCRIPT34_D6064_ITSNO,〃,,,Ještě není hotový.,Det er ikke færdigt endnu.,Es ist noch nicht soweit.,,"Mi ankoraŭ -prilaboras ĝin.",Aún no está listo.,,Se ei ole valmis vielä.,Ce n'est pas encore terminé.,Még nincs kész.,Non è ancora pronto.,まだ完成していません。,연구가 진행중입니다. 나중에.,Het is nog niet klaar.,Det er ikke ferdig ennå.,Jeszcze nie skończyłem.,Ainda não terminei.,,Încă nu e gata.,Он ещё не готов.,,Henüz bitmedi. +prilaboras ĝin.",Aún no está listo.,,Se ei ole valmis vielä.,Ce n'est pas encore terminé.,Még nincs kész.,Non è ancora pronto.,まだ完成していません。,연구가 진행중입니다. 나중에.,Het is nog niet klaar.,Det er ikke ferdig ennå.,Jeszcze nie skończyłem.,Ainda não terminei.,,Încă nu e gata.,Он ещё не готов.,,Det är inte klart än.,Henüz bitmedi. "Hey, I'm working on an updated version of your implant. Is there anything else I can do?",TXT_DLG_SCRIPT34_D7580_HEYIM,〃,,,"Hej, pracuju na vylepšené verzi tvého implantátu. Můžu pro tebe udělat něco jiného?","Jeg arbejder på en opdateret version af dit implantat. Er der andet, jeg kan gøre?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,"Mi laboras super plibonigita versio de via enplantaĵo. Ĉu estas io alia, kion mi povas fari por vi?",Estoy trabajando en una versión mejorada de tu implante. ¿Hay algo más que pueda hacer?,,"Hei, olen työstämässä päivitettyä versiota istutteestasi. Voinko olla muuten avuksi?","Hé, je travaille sur une version améliorée de l'implant. Qu'est-ce que je peux faire pour vous?",Az implantátum újabb verzióján dolgozok. Tudok még valamiben segíteni?,"Ehi, sto lavorando ad un aggiornamento per l'impianto stamina. Posso fare qualcos'altro per te?","どうも、私は今最新版のインプラントに -取り組んでいる。何か用かな?","여어! 이식 칩을 향상할 개조를 받고 싶으신가요? 아니라면, 뭐가 필요합니까?","Hé, ik ben bezig met een bijgewerkte versie van je implantaat. Is er nog iets anders dat ik kan doen?",Jeg jobber med en oppdatert versjon av implantatet ditt. Er det noe annet jeg kan gjøre?,"Hej, pracuję nad unowocześnioną wersją twojego implantu. Czy mogę zrobić coś jeszcze?",E aí. Estou trabalhando numa versão aprimorada do seu implante. Posso te ajudar com mais alguma coisa?,,"Hei, lucrez la o variantă îmbunătățită a implantului tău. E ceva cu care pot să te ajut?","Я работаю над улучшенной версией твоего импланта. А пока, что-нибудь ещё?",,"Hey, implantının güncellenmiş bir versiyonu üzerinde çalışıyorum. Yapabileceğim başka bir şey var mı?" -Patch me up.,TXT_RPLY0_SCRIPT34_D7580_PATCH,〃,,,Dej mě do hromady.,Gør mig klar.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Pistä minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lappe meg sammen.,Załataj mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня.,,Bana yama yap. +取り組んでいる。何か用かな?","여어! 이식 칩을 향상할 개조를 받고 싶으신가요? 아니라면, 뭐가 필요합니까?","Hé, ik ben bezig met een bijgewerkte versie van je implantaat. Is er nog iets anders dat ik kan doen?",Jeg jobber med en oppdatert versjon av implantatet ditt. Er det noe annet jeg kan gjøre?,"Hej, pracuję nad unowocześnioną wersją twojego implantu. Czy mogę zrobić coś jeszcze?",E aí. Estou trabalhando numa versão aprimorada do seu implante. Posso te ajudar com mais alguma coisa?,,"Hei, lucrez la o variantă îmbunătățită a implantului tău. E ceva cu care pot să te ajut?","Я работаю над улучшенной версией твоего импланта. А пока, что-нибудь ещё?",,Jag jobbar på en uppdaterad version av ditt implantat. Finns det något annat jag kan göra?,"Hey, implantının güncellenmiş bir versiyonu üzerinde çalışıyorum. Yapabileceğim başka bir şey var mı?" +Patch me up.,TXT_RPLY0_SCRIPT34_D7580_PATCH,〃,,,Dej mě do hromady.,Gør mig klar.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Pistä minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lappe meg sammen.,Załataj mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня.,,Laga mig.,Bana yama yap. Well at least you're seeing action.,TXT_RYES0_SCRIPT34_D7580_WELLA,〃,,,"No, alespoň jsi v akci.",I det mindste er du i gang.,"Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,"Nu, almenaŭ vi ne havas -enuigajn misiojn.","Bueno, al menos estás -teniendo algo de acción.",,"No, ainakin näet toimintaa.","Eh bien, au moins vous en voyez, de l'action.",Legalább ér valami izgalom.,"Beh, almeno ti stai dando da fare.",少なくとも行動を起こしているのです。,이제 마음껏 움직여보세요.,"Nou ja, je ziet in ieder geval actie.",Det skjer i det minste noe.,"Przynajmniej widzisz, że coś się dzieje.","Bem, pelo menos está tendo um pouco de ação.",,"Pă, măcar tu ai parte de niște acțiune.","Что ж, зато ты участвуешь в операциях.",,En azından hareket görüyorsun. -Implant upgrade?,TXT_RPLY1_SCRIPT34_D7580_IMPLA,〃,,,Vylepšení implantátu?,Implantatopgradering?,Implantatsupgrade?,,Ĉu plibonigo de enplantaĵo?,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Implantatoppgradering?,Aktualizacja implantu?,Versão aprimorada do implante?,,Upgrade la implant?,Улучшение импланта?,,İmplant güncellemesi mi? +enuigajn komisiojn.","Bueno, al menos estás +teniendo algo de acción.",,"No, ainakin näet toimintaa.","Eh bien, au moins vous en voyez, de l'action.",Legalább ér valami izgalom.,"Beh, almeno ti stai dando da fare.",少なくとも行動を起こしているのです。,이제 마음껏 움직여보세요.,"Nou ja, je ziet in ieder geval actie.",Det skjer i det minste noe.,"Przynajmniej widzisz, że coś się dzieje.","Bem, pelo menos está tendo um pouco de ação.",,"Pă, măcar tu ai parte de niște acțiune.","Что ж, зато ты участвуешь в операциях.",,Du ser åtminstone till att det händer något.,En azından hareket görüyorsun. +Implant upgrade?,TXT_RPLY1_SCRIPT34_D7580_IMPLA,〃,,,Vylepšení implantátu?,Implantatopgradering?,Implantatsupgrade?,,Ĉu plibonigo de enplantaĵo?,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Implantatoppgradering?,Aktualizacja implantu?,Versão aprimorada do implante?,,Upgrade la implant?,Улучшение импланта?,,Implantatuppgradering?,İmplant güncellemesi mi? "Good thing, never can be too safe.",TXT_RYES1_SCRIPT34_D7580_GOODT,〃,,,"Dobrá věcička, nikdy si nemůžeš být moc jistý.","Godt, man kan aldrig være for sikker.","Alles klar, das haben wir sofort.",,"Bone. Neniam estas sufiĉe da sekureco.","Bien. Nunca se puede -estar del todo seguro.",,"Hyvä, koskaan ei voi olla liian turvallista.",Bonne idée. On ne peut jamais être trop sûr.,"Még jó, soha nem lehetsz túl nagy biztonságban.","Ottimo, non si può mai essere troppo al sicuro.",良いことだ、安全すぎることはない。,위험 할 때도 있으니 지금 고치겠습니다.,"Goede zaak, kan nooit te veilig zijn.","Bra, man kan aldri være for sikker.","To dobrze, nigdy nie można być zbyt bezpiecznym.",Boa ideia. Segurança nunca é demais.,,"Bine zis, nu poți fi niciodată prea sigur.","Очень советую, ни в чём нельзя быть уверенным до конца.",,"İyi bir şey, asla çok güvenli olamaz." +estar del todo seguro.",,"Hyvä, koskaan ei voi olla liian turvallista.",Bonne idée. On ne peut jamais être trop sûr.,"Még jó, soha nem lehetsz túl nagy biztonságban.","Ottimo, non si può mai essere troppo al sicuro.",良いことだ、安全すぎることはない。,위험 할 때도 있으니 지금 고치겠습니다.,"Goede zaak, kan nooit te veilig zijn.","Bra, man kan aldri være for sikker.","To dobrze, nigdy nie można być zbyt bezpiecznym.",Boa ideia. Segurança nunca é demais.,,"Bine zis, nu poți fi niciodată prea sigur.","Очень советую, ни в чём нельзя быть уверенным до конца.",,"Bra, man kan aldrig vara för säker.","İyi bir şey, asla çok güvenli olamaz." "I'm almost finished, but not quite.",TXT_RNO1_SCRIPT34_D7580_IMALM,〃,,,"Už je skoro hotový, ale ne úplně.","Jeg er næsten færdig, men ikke helt.",Es ist noch nicht soweit.,,"Mi preskaŭ finis, sed ne tute.","Casi he terminado, -pero no del todo.",,"Olen melkein valmis, mutten ihan vielä.","Presque fini, mais pas encore.","Majdnem végeztem, de még nem teljesen","Ho quasi finito, ma non ancora.",もうすぐ出来上がる、それほど掛からない。,거의 완성했는데... 아마도 다음 시간에?,"Ik ben bijna klaar, maar niet helemaal.","Jeg er nesten ferdig, men ikke helt.","Prawie skończyłem, ale nie do końca.",Está quase pronto.,,"Sunt aproape gata, dar nu chiar.",Я почти закончил. Ещё немного.,,Neredeyse bitirdim ama tam değil. +pero no del todo.",,"Olen melkein valmis, mutten ihan vielä.","Presque fini, mais pas encore.","Majdnem végeztem, de még nem teljesen","Ho quasi finito, ma non ancora.",もうすぐ出来上がる、それほど掛からない。,거의 완성했는데... 아마도 다음 시간에?,"Ik ben bijna klaar, maar niet helemaal.","Jeg er nesten ferdig, men ikke helt.","Prawie skończyłem, ale nie do końca.",Está quase pronto.,,"Sunt aproape gata, dar nu chiar.",Я почти закончил. Ещё немного.,,"Jag är nästan klar, men inte riktigt.",Neredeyse bitirdim ama tam değil. "All right, this is it. I've almost got everything working perfectly. There were a few problems left to fix, do you need anything else? ",TXT_DLG_SCRIPT34_D9096_ALLRI,〃,,,"Tak dobře, už mi skoro všechno perfektně funguje. Ještě tam bylo pár problémů. Potřebuješ ještě něco?","Okay, det er det. Jeg har næsten fået det hele til at fungere perfekt. Der var et par problemer tilbage at løse, har du brug for andet?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,"Bone, jen ĉio; preskaŭ ĉio funkcias perfekte. Restis nur kelkaj korektindaj problemoj. Ĉu vi bezonas ion alian?","Muy bien, ya está; tengo casi todo funcionando a la perfección. Solo quedaban algunos problemas que corregir. ¿Necesitas algo más?",,"No niin, olen melkein saanut kaiken toimimaan täydellisesti. Vain muutamia vikoja oli enää jäljellä. Tarvitsetko mitään muuta?","Très bien, je crois que j'ai réussi à tout faire marcher parfaitement. Il y avait quelques problèmes dont je devais me débarrasser. Vous voulez quelque chose?","Rendben, ez lesz az. Már majdnem mindent tökéletesre kidolgoztam. Már csak pár lehetőség van hátra, kell még valami esetleg?","Allora, sono riuscito a far funzionare quasi tutto benissimo. C'erano giusto un paio di problemi rimasti da risolvere. Ti serve qualcos'altro?","大丈夫、全て順調だ。残っていた問題も -全て取り除かれた。他に何が必要かな?","정말 힘든 시간이었어요. 이식 칩의 문제들의 거의 다 고쳐가고 있습니다. 기다리는 동안, 무엇을 도와드릴까요?","Goed, dit is het. Ik heb bijna alles perfect werkend. Er waren nog een paar problemen op te lossen, heb je nog iets anders nodig?","Greit, nå gjelder det. Jeg har nesten fått alt til å fungere perfekt. Det var noen problemer igjen å fikse, trenger du noe mer?","W porządku, to jest to. Prawie wszystko działa idealnie. Zostało kilka problemów do naprawienia, potrzebujesz czegoś jeszcze?","Ok, é isso aí. Está quase tudo funcionando perfeitamente. Faltavam alguns problemas pra consertar. Precisa de mais algo?",,"În regulă, asta e tot. Acum aproape totul merge perfect. Au mai fost câteva probleme de rezolvat, mai ai nevoie de ceva?","Итак, тут оставалась пара проблем, но теперь всё работает почти идеально. Что-нибудь ещё?",,"Pekala, işte bu. Neredeyse her şey mükemmel çalışıyor. Düzeltmem gereken birkaç sorun kaldı, başka bir şeye ihtiyacın var mı?" -Patch me up.,TXT_RPLY0_SCRIPT34_D9096_PATCH,〃,,,Dej mě do hromady.,Lav mig om.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Paikkaa minut.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lapp meg sammen.,Załataj mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня.,,Beni yamala. +全て取り除かれた。他に何が必要かな?","정말 힘든 시간이었어요. 이식 칩의 문제들의 거의 다 고쳐가고 있습니다. 기다리는 동안, 무엇을 도와드릴까요?","Goed, dit is het. Ik heb bijna alles perfect werkend. Er waren nog een paar problemen op te lossen, heb je nog iets anders nodig?","Greit, nå gjelder det. Jeg har nesten fått alt til å fungere perfekt. Det var noen problemer igjen å fikse, trenger du noe mer?","W porządku, to jest to. Prawie wszystko działa idealnie. Zostało kilka problemów do naprawienia, potrzebujesz czegoś jeszcze?","Ok, é isso aí. Está quase tudo funcionando perfeitamente. Faltavam alguns problemas pra consertar. Precisa de mais algo?",,"În regulă, asta e tot. Acum aproape totul merge perfect. Au mai fost câteva probleme de rezolvat, mai ai nevoie de ceva?","Итак, тут оставалась пара проблем, но теперь всё работает почти идеально. Что-нибудь ещё?",,"Okej, nu är det dags. Jag har nästan fått allt att fungera perfekt. Det fanns några problem kvar att fixa, behöver du något mer?","Pekala, işte bu. Neredeyse her şey mükemmel çalışıyor. Düzeltmem gereken birkaç sorun kaldı, başka bir şeye ihtiyacın var mı?" +Patch me up.,TXT_RPLY0_SCRIPT34_D9096_PATCH,〃,,,Dej mě do hromady.,Lav mig om.,Flick mich zusammen.,,Kuracu min.,Cúrame.,,Paikkaa minut.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Lapp meg sammen.,Załataj mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня.,,Laga mig.,Beni yamala. What have you been trying to do? Go head to head with a Crusader?,TXT_RYES0_SCRIPT34_D9096_WHATH,〃,,,Co jsi dělal? Šel zmlátit Křižáka?,Hvad har du forsøgt at gøre? Gå hoved mod hoved med en korsfarer?,"Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,"Kion vi intencis fari? Ĉu piki Kruciston?","¿Qué has intentado hacer? ¿Ir cara a cara con un Cruzado?","¿Qué anduviste haciendo? ¿Ir cara a cara con un Cruzado?",Mitä olet oikein yrittänyt tehdä? Mennä nokittain ristiretkeläisen kanssa?,Qu'est-ce que vous avez fait? Vous avez essayé de faire ami avec un Croisé?,Mit akartál tenni? Nekimenni egymagad egy keresztesnek?,Ma cosa hai cercato di fare? Lottare da solo contro un Crociato?,"今度は何を始めるんだ? -クルセイダーと向かい合うのか?",아콜라이트와 근접전을 펼친 것 같군요... 아마도.,Wat heb je geprobeerd te doen? Hoofd aan hoofd gaan met een kruisvaarder?,Hva har du prøvd å gjøre? Kjempe mot en korsfarer?,Co próbowałeś zrobić? Walczyć łeb w łeb z Crusaderem?,O que andou tentando fazer? Sair na porrada com um Cruzado?,,Ce ai încercat să faci? Dai cap în cap cu un Cruciat?,"Ты что, бился один на один с крестоносцем?",,Ne yapmaya çalışıyordun? Bir Crusader ile kafa kafaya mı? -Implant upgrade?,TXT_RPLY1_SCRIPT34_D9096_IMPLA,〃,,,Vylepšení implantátu?,Implantatopgradering?,Implantatsupgrade?,,Ĉu plibonigo de enplantaĵo?,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?.,Implantatoppgradering?,Ulepszenie implantu?,Aprimoramento de implante?,,Upgrade la implant?,Улучшение импланта?,,İmplant yükseltmesi mi? -That should do it for you.,TXT_RYES1_SCRIPT34_D9096_THATS,〃,,,Tohle by mělo fungovat.,Det burde gøre det for dig.,"Alles klar, das haben wir sofort.",,Ĉi tio devus esti sufiĉa.,Con esto debería estar.,,Eiköhän tällä ala tepsiä.,Ca devrait faire l'affaire.,Ez szerintem megteszi.,Questo dovrebbe andare.,今取り掛かっている。,도움이 좀 될 거에요.,Dat zou het voor je moeten doen.,Det burde gjøre det for deg.,To powinno ci wystarczyć.,Isso deve funcionar pra você.,,Asta ar trebui să fie suficient.,Вот оно.,,Bu senin işini görür. +クルセイダーと向かい合うのか?",아콜라이트와 근접전을 펼친 것 같군요... 아마도.,Wat heb je geprobeerd te doen? Hoofd aan hoofd gaan met een kruisvaarder?,Hva har du prøvd å gjøre? Kjempe mot en korsfarer?,Co ty próbowałeś zrobić? Walczyć oko w oko z Krzyżowcem?,O que andou tentando fazer? Sair na porrada com um Cruzado?,,Ce ai încercat să faci? Dai cap în cap cu un Cruciat?,"Ты что, бился один на один с крестоносцем?",,Vad har du försökt göra? Gå mot en korsriddare?,Ne yapmaya çalışıyordun? Bir Haçlı ile kafa kafaya mı? +Implant upgrade?,TXT_RPLY1_SCRIPT34_D9096_IMPLA,〃,,,Vylepšení implantátu?,Implantatopgradering?,Implantatsupgrade?,,Ĉu plibonigo de enplantaĵo?,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?.,Implantatoppgradering?,Ulepszenie implantu?,Aprimoramento de implante?,,Upgrade la implant?,Улучшение импланта?,,Implantatuppgradering?,İmplant yükseltmesi mi? +That should do it for you.,TXT_RYES1_SCRIPT34_D9096_THATS,〃,,,Tohle by mělo fungovat.,Det burde gøre det for dig.,"Alles klar, das haben wir sofort.",,Ĉi tio devus esti sufiĉa.,Con esto debería estar.,,Eiköhän tällä ala tepsiä.,Ca devrait faire l'affaire.,Ez szerintem megteszi.,Questo dovrebbe andare.,今取り掛かっている。,도움이 좀 될 거에요.,Dat zou het voor je moeten doen.,Det burde gjøre det for deg.,To powinno ci wystarczyć.,Isso deve funcionar pra você.,,Asta ar trebui să fie suficient.,Вот оно.,,Det borde göra det för dig.,Bu senin işini görür. Let me run some more tests first.,TXT_RNO1_SCRIPT34_D9096_LETME,〃,,,Ještě ho musím dál otestovat.,Lad mig køre nogle flere tests først.,Es ist noch nicht soweit.,,"Unue mi faru kelkajn provojn.","Déjame hacer algunas -pruebas primero.",,Anna minun ajaa muutamia kokeita ensin.,Laissez moi faire quelques tests d'abord.,Hadd futtassak pár tesztet.,Devo fare ancora qualche test.,もう少しテストしてからにしよう。,시험단계를 좀 거치고 예기할게요.,Laat me eerst nog wat testen doen.,La meg kjøre noen flere tester først.,Pozwól mi najpierw przeprowadzić kilka testów.,Só deixa eu fazer mais alguns testes.,,Lasă-mă să fac niște teste mai întâi.,Дай мне ещё времени на тесты.,,Önce birkaç test daha yapayım. +pruebas primero.",,Anna minun ajaa muutamia kokeita ensin.,Laissez moi faire quelques tests d'abord.,Hadd futtassak pár tesztet.,Devo fare ancora qualche test.,もう少しテストしてからにしよう。,시험단계를 좀 거치고 예기할게요.,Laat me eerst nog wat testen doen.,La meg kjøre noen flere tester først.,Pozwól mi najpierw przeprowadzić kilka testów.,Só deixa eu fazer mais alguns testes.,,Lasă-mă să fac niște teste mai întâi.,Дай мне ещё времени на тесты.,,Låt mig köra några fler tester först.,Önce birkaç test daha yapayım. That's all I can do on the implant right now. Maybe some healing?,TXT_DLG_SCRIPT34_D10612_THATS,〃,,,"Tak, to je všechno co teď můžu s tím implantátem udělat. Potřebuješ léčení?","Det er alt, hvad jeg kan gøre på implantatet lige nu. Måske noget healing?","Das ist alles, was ich im Moment mit dem Implantat machen kann. Vielleicht etwas medizinische Versorgung?",,"Tio estas ĉio, kion mi momente povas fari super la enplantaĵo. Ĉu vi bezonas kuracon?",Eso es todo lo que puedo hacer con el implante por ahora. ¿Necesitas curarte?,,Tätä enempää en voi istutteelle enää juuri nyt tehdä. Mutta oletko hoidon tarpeessa?,C'est tout ce que je peux faire pour l'implant. Vous voulez que je vous soigne?,Ennyit tudtam kezdeni most az implantátummal. Esetleg valami gyógyítás?,È tutto per quanto riguarda l'impianto. Però posso sempre curarti.,"インプラントはこれ以上ない程完成した。 -それとも治療か?",이식 칩에 관한 모든 걸 해줬습니다. 더 필요한 게 있나요?,Dat is alles wat ik nu kan doen op het implantaat. Misschien wat genezing?,Det er alt jeg kan gjøre med implantatet akkurat nå. Kanskje litt helbredelse?,"To wszystko, co mogę zrobić z implantem w tej chwili. Może trochę uzdrowienia?",Isso é tudo o que posso fazer com o implante no momento. Vai uma cura aí?,,Asta e tot ce pot face implantului acum. Poate niște bandaje?,Пока что я больше ничего не могу сделать с имплантом. Как насчёт лечения?,,Şu anda implant üzerinde yapabileceğim tek şey bu. Belki biraz iyileşme? -Yeah.,TXT_RPLY0_SCRIPT34_D10612_YEAH,〃,,,Jo.,Ja.,Ja.,,Jes.,Sí.,,Kyllä.,Ouais.,Igen.,Sì.,ああ。,그래.,Ja.,Ja.,Tak.,Sim.,,Da.,Давай.,,Evet. +それとも治療か?",이식 칩에 관한 모든 걸 해줬습니다. 더 필요한 게 있나요?,Dat is alles wat ik nu kan doen op het implantaat. Misschien wat genezing?,Det er alt jeg kan gjøre med implantatet akkurat nå. Kanskje litt helbredelse?,"To wszystko, co mogę zrobić z implantem w tej chwili. Może trochę uzdrowienia?",Isso é tudo o que posso fazer com o implante no momento. Vai uma cura aí?,,Asta e tot ce pot face implantului acum. Poate niște bandaje?,Пока что я больше ничего не могу сделать с имплантом. Как насчёт лечения?,,Det är allt jag kan göra med implantatet just nu. Kanske lite läkning?,Şu anda implant üzerinde yapabileceğim tek şey bu. Belki biraz iyileşme? +Yeah.,TXT_RPLY0_SCRIPT34_D10612_YEAH,〃,,,Jo.,Ja.,Ja.,,Jes.,Sí.,,Kyllä.,Ouais.,Igen.,Sì.,ああ。,그래.,Ja.,Ja.,Tak.,Sim.,,Da.,Давай.,,"Ja, det är det.",Evet. "Boy, you're a real mess. I'll see what I can do.",TXT_RYES0_SCRIPT34_D10612_BOYYO,〃,,,"Tebe teda zřídili, kluku. Uvidím, co s tebou.","Mand, du er et rigtigt rod. Jeg skal se, hvad jeg kan gøre.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,"Ulo, vi estas iomege en malordo. Mi vidos tion, kion mi faru.","Tío, estás hecho un desastre. A ver qué puedo hacer.","Chico, estás hecho un desastre. -A ver qué puedo hacer.","Kylläpä olet huonossa jamassa. Katsotaan, mitä voin tehdä.","Mon petit, vous êtes dans un sale état. Je vais voir ce que je peux faire.","Öregem, elég ramaty állapotban vagy. Megnézem mit tehetek.","Ragazzo, sei messo proprio male. Vediamo cosa posso fare.",君、滅茶苦茶だな。なんとかしよう。,치료가 다 끝났습니다. 다 의료기술 덕입니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","Jøss, du er et skikkelig rot. Jeg skal se hva jeg kan gjøre.","Chłopcze, masz niezły bałagan. Zobaczę, co da się zrobić.","Rapaz, você está arrebentado. Verei o que posso fazer.",,"Băiete, ești un dezastru. O să văd ce pot face.","Ты просто месиво. Посмотрим, что я смогу сделать.",,Gerçekten berbat durumdasın. Ne yapabileceğime bakacağım. -What can I do for you?,TXT_DLG_SCRIPT34_D12128_WHATC,"MAP34: Feris (identical to rows 746-768, except for row 1357).",,,Co pro tebe můžu udělat?,Hvad kan jeg gøre for dig?,Was kann ich für dich tun?,,Kion mi faru por vi?,¿Qué puedo hacer por ti?,,Mitä voin tehdä sinulle?,Que puis-je faire pour vous?,Mit tehetek érted?,Cosa posso fare per te?,それで何か用か?,무엇을 도와줄까.,Wat kan ik voor je doen?,Hva kan jeg gjøre for deg?,Co mogę zrobić dla ciebie?,Como posso te ajudar?,,Ce pot face pentru tine?,Чем я могу тебе помочь?,,Senin için ne yapabilirim? -I'm out of bullets.,TXT_RPLY0_SCRIPT34_D12128_IMOUT,〃,,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi estas sen kugloj.,No me quedan balas.,,Minulta on luodit loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się naboje.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны.,,Mermim bitti. +A ver qué puedo hacer.","Kylläpä olet huonossa jamassa. Katsotaan, mitä voin tehdä.","Mon petit, vous êtes dans un sale état. Je vais voir ce que je peux faire.","Öregem, elég ramaty állapotban vagy. Megnézem mit tehetek.","Ragazzo, sei messo proprio male. Vediamo cosa posso fare.",君、滅茶苦茶だな。なんとかしよう。,치료가 다 끝났습니다. 다 의료기술 덕입니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","Jøss, du er et skikkelig rot. Jeg skal se hva jeg kan gjøre.","Chłopcze, masz niezły bałagan. Zobaczę, co da się zrobić.","Rapaz, você está arrebentado. Verei o que posso fazer.",,"Băiete, ești un dezastru. O să văd ce pot face.","Ты просто месиво. Посмотрим, что я смогу сделать.",,Du är en riktig röra. Jag ska se vad jag kan göra.,Gerçekten berbat durumdasın. Ne yapabileceğime bakacağım. +What can I do for you?,TXT_DLG_SCRIPT34_D12128_WHATC,"MAP34: Feris (identical to rows 746-768, except for row 1357).",,,Co pro tebe můžu udělat?,Hvad kan jeg gøre for dig?,Was kann ich für dich tun?,,Kion mi faru por vi?,¿Qué puedo hacer por ti?,,Mitä voin tehdä sinulle?,Que puis-je faire pour vous?,Mit tehetek érted?,Cosa posso fare per te?,それで何か用か?,무엇을 도와줄까.,Wat kan ik voor je doen?,Hva kan jeg gjøre for deg?,Co mogę zrobić dla ciebie?,Como posso te ajudar?,,Ce pot face pentru tine?,Чем я могу тебе помочь?,,Vad kan jag göra för dig?,Senin için ne yapabilirim? +I'm out of bullets.,TXT_RPLY0_SCRIPT34_D12128_IMOUT,〃,,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi ne havas kuglojn.,No me quedan balas.,,Minulta on luodit loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się naboje.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны.,,Jag har slut på kulor.,Mermim bitti. Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D12128_HERES,〃,,,"Tady máš nějakou munici, neplýtvej s ní.",Her er lidt ammunition til dig. Spild det ikke.,Hier hast du welche. Verschwende sie nicht.,,"Jen iom da municio. Ne malŝparu ĝin.","Aquí tienes algo de munición. -No la desperdicies.",,Tässä sinulle panoksia. Älä tuhlaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van valamennyi lőszer. Ne pazarold el.,Ecco un pò di munizioni per te. Non sprecarle.,無駄遣いするなよ。,조금만 주겠습니다. 재고가 모자라거든요.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Tu jest trochę amunicji dla ciebie. Nie marnuj jej.,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну.,,Al sana biraz mermi. Boşa harcama. -Teach me.,TXT_RPLY1_SCRIPT34_D12128_TEACH,〃,,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. +No la desperdicies.",,Tässä sinulle panoksia. Älä tuhlaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van valamennyi lőszer. Ne pazarold el.,Ecco un po' di munizioni per te. Non sprecarle.,無駄遣いするなよ。,조금만 주겠습니다. 재고가 모자라거든요.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Tu jest trochę amunicji dla ciebie. Nie marnuj jej.,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну.,,Här är lite ammunition till dig. Slösa inte bort den.,Al sana biraz mermi. Boşa harcama. +Teach me.,TXT_RPLY1_SCRIPT34_D12128_TEACH,〃,,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. "All right, I'll just show you a few little pointers.",TXT_RYES1_SCRIPT34_D12128_ALLRI,〃,,,"Dobře, ukážu ti pár rad.","Okay, jeg vil bare vise dig et par små tips.","Alles klar, ich zeige dir ein paar Kniffe.",,"Bone, jen kelkaj konsiletoj...","Muy bien, aquí van -un par de consejos...",,"Hyvä on, annan sinulle vain muutamia pikkuvinkkejä.",Pas de problème. Laissez moi vous montrer quelques trucs.,Akkor addok pár hasznos tanácsot.,"Va bene, ti darò un paio di dritte molto utili.",わかった、幾つかやり方を教えよう。,좋습니다. 움직이는 과녁을 쏘세요!,"Oké, ik zal je gewoon een paar kleine tips laten zien.","Greit, jeg skal bare vise deg noen små tips.","W porządku, pokażę ci tylko kilka małych wskazówek.","Ok, vou te dar algumas dicas.",,"În regulă, am să-ți arăt niște repere.",Хорошо. Покажу тебе пару приёмов.,,"Pekala, sana birkaç küçük ipucu göstereceğim." +un par de consejos...",,"Hyvä on, annan sinulle vain muutamia pikkuvinkkejä.",Pas de problème. Laissez moi vous montrer quelques trucs.,Akkor addok pár hasznos tanácsot.,"Va bene, ti darò un paio di dritte molto utili.",わかった、幾つかやり方を教えよう。,좋습니다. 움직이는 과녁을 쏘세요!,"Oké, ik zal je gewoon een paar kleine tips laten zien.","Greit, jeg skal bare vise deg noen små tips.","W porządku, pokażę ci tylko kilka małych wskazówek.","Ok, vou te dar algumas dicas.",,"În regulă, am să-ți arăt niște repere.",Хорошо. Покажу тебе пару приёмов.,,"Okej, jag ska bara visa dig några små tips.","Pekala, sana birkaç küçük ipucu göstereceğim." You're not ready yet.,TXT_RNO1_SCRIPT34_D12128_YOURE,〃,,,Ještě nejsi připravený.,Du er ikke klar endnu.,Du bist noch nicht so weit.,,"Vi ankoraŭ -ne estas preta.",Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,そっちの準備がまだ整ってないようだな。,당신은 아직 준비가 안됐어요.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze gotowy.,Você não está preparado ainda.,,Nu ești pregătit încă.,Ты ещё не готов.,,Henüz hazır değilsin. -Back again? What do you need?,TXT_DLG_SCRIPT34_D13644_BACKA,〃,,,Zase zpátky? Co potřebuješ?,Tilbage igen? Hvad har du brug for?,Scxhon zurück? Was brauchst du?,,Do vi revenis. Kion vi bezonas?,¿Ya de vuelta? ¿Qué necesitas?,,Täällä taas? Mitä tarvitset?,Déjà de retour? De quoi avez-vous besoin?,Már vissza is tértél? Mire van szükséged?,Già di ritorno? Che cosa ti serve?,もう戻ったか?何が必要だ?,다시 왔군요. 무엇이 필요하죠?,Weer terug? Wat heb je nodig?,Tilbake igjen? Hva trenger du?,Znowu? Czego potrzebujesz?,Já voltou? O que precisa?,,Te-ai întors? Ce mai dorești?,Ты вернулся? Что тебе нужно?,,Yine mi? Neye ihtiyacın var? -I'm out of bullets.,TXT_RPLY0_SCRIPT34_D13644_IMOUT,〃,,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi estas sen kugloj.,No me quedan balas.,,Minulta on ammukset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się naboje.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны.,,Mermim bitti. +ne estas preta.",Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,Non sei ancora pronto.,そっちの準備がまだ整ってないようだな。,당신은 아직 준비가 안됐어요.,Je bent nog niet klaar.,Du er ikke klar ennå.,Nie jesteś jeszcze gotowy.,Você não está preparado ainda.,,Nu ești pregătit încă.,Ты ещё не готов.,,Du är inte redo än.,Henüz hazır değilsin. +Back again? What do you need?,TXT_DLG_SCRIPT34_D13644_BACKA,〃,,,Zase zpátky? Co potřebuješ?,Tilbage igen? Hvad har du brug for?,Scxhon zurück? Was brauchst du?,,Do vi revenis. Kion vi bezonas?,¿Ya de vuelta? ¿Qué necesitas?,,Täällä taas? Mitä tarvitset?,Déjà de retour? De quoi avez-vous besoin?,Már vissza is tértél? Mire van szükséged?,Già di ritorno? Che cosa ti serve?,もう戻ったか?何が必要だ?,다시 왔군요. 무엇이 필요하죠?,Weer terug? Wat heb je nodig?,Tilbake igjen? Hva trenger du?,Znowu? Czego potrzebujesz?,Já voltou? O que precisa?,,Te-ai întors? Ce mai dorești?,Ты вернулся? Что тебе нужно?,,Tillbaka igen? Vad behöver du?,Yine mi? Neye ihtiyacın var? +I'm out of bullets.,TXT_RPLY0_SCRIPT34_D13644_IMOUT,〃,,,Došly mi náboje.,Jeg er løbet tør for kugler.,Ich habe keine Munition mehr.,,Mi ne havas kuglojn.,No me quedan balas.,,Minulta on ammukset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Jeg er tom for kuler.,Skończyły mi się naboje.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны.,,Jag har slut på kulor.,Mermim bitti. Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D13644_HERES,〃,,,"Tady máš nějakou munici, neplýtvej s ní.",Her er lidt ammunition til dig. Spild det ikke.,Hier hast du welche. Verschwende sie nicht.,,"Jen iom da municio. Ne malŝparu ĝin.","Aquí tienes algo de munición. -No la desperdicies.",,Tässä vähän lisää. Älä haaskaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van valamennyi lőszer. Ne pazarold el.,Ecco un pò di munizioni per te. Non sprecarle.,この弾を使え、無駄遣いするなよ。,"적을 사살하려면, 역시 탄약을 소진해야만 하죠. 여기 탄약입니다.",Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Tu jest trochę amunicji dla ciebie. Nie marnuj jej.,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну.,,İşte sana biraz cephane. Boşa harcama. -You've got enough ammo.,TXT_RNO0_SCRIPT34_D13644_YOUVE,〃,,,Vždyť jich máš dost.,Du har ammunition nok.,Du hast genug.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ma veramente ne hai a sufficienza.,もう十分に弾を持ってるようだぞ。,충분한 탄약을 가졌어. 다 소진하고 찾아오세요.,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai suficientă muniție.,У тебя их достаточно.,,Yeterince mermin var. -Teach me.,TXT_RPLY1_SCRIPT34_D13644_TEACH,〃,,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. +No la desperdicies.",,Tässä vähän lisää. Älä haaskaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van valamennyi lőszer. Ne pazarold el.,Ecco un po' di munizioni per te. Non sprecarle.,この弾を使え、無駄遣いするなよ。,"적을 사살하려면, 역시 탄약을 소진해야만 하죠. 여기 탄약입니다.",Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Tu jest trochę amunicji dla ciebie. Nie marnuj jej.,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну.,,Här är lite ammunition till dig. Slösa inte bort den.,İşte sana biraz cephane. Boşa harcama. +You've got enough ammo.,TXT_RNO0_SCRIPT34_D13644_YOUVE,〃,,,Vždyť jich máš dost.,Du har ammunition nok.,Du hast genug.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ma veramente ne hai a sufficienza.,もう十分に弾を持ってるようだぞ。,충분한 탄약을 가졌어. 다 소진하고 찾아오세요.,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai suficientă muniție.,У тебя их достаточно.,,Du har tillräckligt med ammunition.,Yeterince mermin var. +Teach me.,TXT_RPLY1_SCRIPT34_D13644_TEACH,〃,,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. "All right, this should keep you going for a while.",TXT_RYES1_SCRIPT34_D13644_ALLRI,〃,,,"Dobře, tohle by ti mělo pomoct.","Okay, det her burde holde dig i gang et stykke tid.","Alles klar, das sollte fürs erste reichen.",,"Bone, ĉi tio devus esti sufiĉe utila nuntempe.","Muy bien, esto debería -servirte por el momento.",,"Selvä on, tällä sinun pitäisi pötkiä aika pitkälle.","Bien, ça devrait vous suffir pour un bon moment.","Rendben van, ezzel el leszel egy darabig.","Va bene, con questo dovresti andare sul sicuro per un pò.",わかった、これで長くやり合えるだろう。,"여기, 적병 일부를 충분히 죽일 수 있을 만큼의 탄약입니다.","Oké, dit zou je een tijdje op de been moeten houden.","Greit, dette burde holde deg gående en stund.","W porządku, to powinno ci wystarczyć na jakiś czas.","Ok, isso deve te ajudar por enquanto.",,"Bine, asta ar trebui să te ajute o vreme.","Хорошо, это не раз спасёт тебе жизнь.",,"Pekala, bu seni bir süre idare eder." +servirte por el momento.",,"Selvä on, tällä sinun pitäisi pötkiä aika pitkälle.","Bien, ça devrait vous suffir pour un bon moment.","Rendben van, ezzel el leszel egy darabig.","Va bene, con questo dovresti andare sul sicuro per un po'.",わかった、これで長くやり合えるだろう。,"여기, 적병 일부를 충분히 죽일 수 있을 만큼의 탄약입니다.","Oké, dit zou je een tijdje op de been moeten houden.","Greit, dette burde holde deg gående en stund.","W porządku, to powinno ci wystarczyć na jakiś czas.","Ok, isso deve te ajudar por enquanto.",,"Bine, asta ar trebui să te ajute o vreme.","Хорошо, это не раз спасёт тебе жизнь.",,"Okej, det här borde hålla dig igång ett tag.","Pekala, bu seni bir süre idare eder." "Sorry, can't. I'm just following Macil's orders.",TXT_RNO1_SCRIPT34_D13644_SORRY,〃,,,"Promiň, nemůžu. Řídím se rozkazy od Macila.","Beklager, jeg kan ikke. Jeg følger bare Macils ordrer.","Tut mir leid, aber ich kann nicht. Ich folge nur Macils Befehlen.",,"Pardonon, mi ne rajtas. Mi nur observas Macil-on.","Lo siento, no puedo. -Solo sigo órdenes de Macil.",,Valitettavasti en voi. Noudatan vain Macilin käskyjä.,"Désolé, pas possible. Je ne fais que suivre les ordres de Macil.","Sajnálom, de nem tehetem. Macil utasítása.","Mi spiace, ma non posso. Ordini dall'alto.",すまないが、できない。マシルの命令だ。,마실 사령관님의 명령입니다. 그럴 수는 없어요.,"Sorry, dat kan niet. Ik volg gewoon de orders van Macil op.","Beklager, jeg kan ikke. Jeg følger bare Macils ordre.","Przepraszam, nie mogę. Wykonuję tylko rozkazy Macila.",Desculpe mas não posso. Só estou seguindo as ordens do Macil.,,"Scuze, nu pot. Eu doar umez ordinele lui Macil.","Увы, не могу. Я подчиняюсь Мэйсилу.",,"Üzgünüm, yapamam. Macil'in emirlerini uyguluyorum." -"Well which is it, bullets or training? I can't wait to get my hands on those new weapons we captured. Once I get done with them, I'll be able to begin training everyone else.",TXT_DLG_SCRIPT34_D15160_WELLW,〃,,,"Tak co to bude, náboje nebo trénink? Nemůžu se dočkat, až se dostanu k těm novým zbraním, které jsme zabavili. Trocha cvičení a pak hodně odplaty.","Nå, hvad er det, kugler eller træning? Jeg kan ikke vente med at få fingrene i de nye våben, vi har taget til fange. Når jeg er færdig med dem, kan jeg begynde at træne alle de andre.","Also, was willst du? Munition oder Training? Ich kann kaum erwarten, diese neuen Waffen, die wir erbeutet haben, in die Finger zu kriegen. ein bisschen Training und dann jede Menge Vergeltung.",,"Nu, ĉu kugloj aŭ trejnado ĉi-foje? Mi sopire atendas provi tiujn novajn kaptitajn armilojn. Fininte tion, mi povos ektrejni la aliajn.","Bueno, ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a poner mis manos en esas nuevas armas que hemos capturado. En cuanto termine, podré empezar a entrenar al resto.","Bueno, ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a poner mis manos en esas nuevas armas que capturamos. En cuanto termine, voy a poder empezar a entrenar al resto.","No niin, kumpaa saisi olla: luoteja vai koulutusta? En voi malttaa olla tarttumasta vasta kaappaamiimme aseisiin. Hieman perehdytystä, ja sitten paljon kostamista.","Qu'est-ce qu'il vous faut? Des munitions ou de l'entraînement? J'ai hâte d'essayer ces nouvelles armes que l'on a capturé. Quand j'en aurai fini avec elles, je pourrai entraîner tout le monde.","Akkor mi lesz, ólom vagy tréning? Már alig várom, hogy kipróbáljam az újonnan zsákmányolt fegyvereket. Ha végeztem velük, mindenki mást is fel tudok készíteni.","Bene, che cosa ti serve, munizioni o addestramento? Non vedo l'ora di mettere le mani su quelle nuove armi che abbiamo preso. Un pò di addestramento e poi molta vendetta.","弾薬と訓練、どっちの用件だ? +Solo sigo órdenes de Macil.",,Valitettavasti en voi. Noudatan vain Macilin käskyjä.,"Désolé, pas possible. Je ne fais que suivre les ordres de Macil.","Sajnálom, de nem tehetem. Macil utasítása.","Mi spiace, ma non posso. Ordini dall'alto.",すまないが、できない。マシルの命令だ。,마실 사령관님의 명령입니다. 그럴 수는 없어요.,"Sorry, dat kan niet. Ik volg gewoon de orders van Macil op.","Beklager, jeg kan ikke. Jeg følger bare Macils ordre.","Przepraszam, nie mogę. Wykonuję tylko rozkazy Macila.",Desculpe mas não posso. Só estou seguindo as ordens do Macil.,,"Scuze, nu pot. Eu doar umez ordinele lui Macil.","Увы, не могу. Я подчиняюсь Мэйсилу.",,"Tyvärr, jag kan inte. Jag följer bara Macils order.","Üzgünüm, yapamam. Macil'in emirlerini uyguluyorum." +"Well which is it, bullets or training? I can't wait to get my hands on those new weapons we captured. Once I get done with them, I'll be able to begin training everyone else.",TXT_DLG_SCRIPT34_D15160_WELLW,〃,,,"Tak co to bude, náboje nebo trénink? Nemůžu se dočkat, až se dostanu k těm novým zbraním, které jsme zabavili. Trocha cvičení a pak hodně odplaty.","Nå, hvad er det, kugler eller træning? Jeg kan ikke vente med at få fingrene i de nye våben, vi har taget til fange. Når jeg er færdig med dem, kan jeg begynde at træne alle de andre.","Also, was willst du? Munition oder Training? Ich kann kaum erwarten, diese neuen Waffen, die wir erbeutet haben, in die Finger zu kriegen. ein bisschen Training und dann jede Menge Vergeltung.",,"Nu, ĉu kugloj aŭ trejnado ĉi-foje? Mi sopire atendas provi tiujn novajn kaptitajn armilojn. Fininte tion, mi povos ektrejni la aliajn.","Bueno, ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a poner mis manos en esas nuevas armas que hemos capturado. En cuanto termine, podré empezar a entrenar al resto.","Bueno, ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a poner mis manos en esas nuevas armas que capturamos. En cuanto termine, voy a poder empezar a entrenar al resto.","No niin, kumpaa saisi olla: luoteja vai koulutusta? En voi malttaa olla tarttumasta vasta kaappaamiimme aseisiin. Hieman perehdytystä, ja sitten paljon kostamista.","Qu'est-ce qu'il vous faut? Des munitions ou de l'entraînement? J'ai hâte d'essayer ces nouvelles armes que l'on a capturé. Quand j'en aurai fini avec elles, je pourrai entraîner tout le monde.","Akkor mi lesz, ólom vagy tréning? Már alig várom, hogy kipróbáljam az újonnan zsákmányolt fegyvereket. Ha végeztem velük, mindenki mást is fel tudok készíteni.","Bene, che cosa ti serve, munizioni o addestramento? Non vedo l'ora di mettere le mani su quelle nuove armi che abbiamo preso. Un po' di addestramento e poi molta vendetta.","弾薬と訓練、どっちの用件だ? 奪った新しい武器が届くのを待ち切れないです。 -少しの訓練でデカい復讐を。",탄약보급? 훈련? 가능하면 모두 다 가능합니다! 그리고 방금 수송된 무기들을 만져보고 싶습니다. 조사가 끝난 뒤에는 모두가 특수 훈련을 받을 수 있을 거에요.,"Wat is het dan wel, kogels of training? Ik kan niet wachten om die nieuwe wapens in handen te krijgen die we gevangen genomen hebben. Als ik er klaar mee ben, kan ik beginnen met het trainen van alle anderen.","Hva er det, kuler eller trening? Jeg gleder meg til å få tak i de nye våpnene vi tok. Når jeg er ferdig med dem, kan jeg begynne å trene alle de andre.","Więc co to jest, kule czy trening? Nie mogę się doczekać, aż dostanę w swoje ręce tę nową broń, którą zdobyliśmy. Jak już się z nimi uporam, będę mógł zacząć szkolić wszystkich innych.","Bem, o que vai ser? Munição ou treinamento? Mal posso esperar pra pegar nessas novas armas que capturamos. Depois que eu terminar com eles, vou poder começar a treinar todo o pessoal.",,"Deci care e, gloanțe sau instruire? Abia aștept să pun mâna pe armele pe care le-am capturat. Odată ce termin cu ele îi voi putea instrui și pe ceilalți.","Что теперь, патроны или тренировка? Мне не терпится опробовать это новое трофейное оружие. Чуть-чуть тренировки, и они за всё заплатят.",,"Hangisi, mermi mi eğitim mi? Yakaladığımız şu yeni silahları elime almak için sabırsızlanıyorum. Onlarla işim bittiğinde, diğer herkesi eğitmeye başlayabileceğim." -I'm out of ammo.,TXT_RPLY0_SCRIPT34_D15160_IMOUT,〃,,,Došly mi náboje.,Jeg er løbet tør for ammunition.,Ich habe keine Munition mehr.,,Mi estas sen municio.,No me queda munición.,,Minulta on panokset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 떨어졌어요.,Ik heb geen munitie meer.,Jeg er tom for ammunisjon.,Skończyła mi się amunicja.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились боеприпасы.,,Mermim bitti. +少しの訓練でデカい復讐を。",탄약보급? 훈련? 가능하면 모두 다 가능합니다! 그리고 방금 수송된 무기들을 만져보고 싶습니다. 조사가 끝난 뒤에는 모두가 특수 훈련을 받을 수 있을 거에요.,"Wat is het dan wel, kogels of training? Ik kan niet wachten om die nieuwe wapens in handen te krijgen die we gevangen genomen hebben. Als ik er klaar mee ben, kan ik beginnen met het trainen van alle anderen.","Hva er det, kuler eller trening? Jeg gleder meg til å få tak i de nye våpnene vi tok. Når jeg er ferdig med dem, kan jeg begynne å trene alle de andre.","Więc co to jest, kule czy trening? Nie mogę się doczekać, aż dostanę w swoje ręce tę nową broń, którą zdobyliśmy. Jak już się z nimi uporam, będę mógł zacząć szkolić wszystkich innych.","Bem, o que vai ser? Munição ou treinamento? Mal posso esperar pra pegar nessas novas armas que capturamos. Depois que eu terminar com eles, vou poder começar a treinar todo o pessoal.",,"Deci care e, gloanțe sau instruire? Abia aștept să pun mâna pe armele pe care le-am capturat. Odată ce termin cu ele îi voi putea instrui și pe ceilalți.","Что теперь, патроны или тренировка? Мне не терпится опробовать это новое трофейное оружие. Чуть-чуть тренировки, и они за всё заплатят.",,"Vad är det, kulor eller träning? Jag kan inte vänta på att få ta del av de nya vapnen som vi tog till fånga. När jag är klar med dem kan jag börja träna alla andra.","Hangisi, mermi mi eğitim mi? Yakaladığımız şu yeni silahları elime almak için sabırsızlanıyorum. Onlarla işim bittiğinde, diğer herkesi eğitmeye başlayabileceğim." +I'm out of ammo.,TXT_RPLY0_SCRIPT34_D15160_IMOUT,〃,,,Došly mi náboje.,Jeg er løbet tør for ammunition.,Ich habe keine Munition mehr.,,Mi estas sen municio.,No me queda munición.,,Minulta on panokset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 떨어졌어요.,Ik heb geen munitie meer.,Jeg er tom for ammunisjon.,Skończyła mi się amunicja.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились боеприпасы.,,Jag har slut på ammunition.,Mermim bitti. Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D15160_HERES,〃,,,"Tady máš nějakou munici, neplýtvej s ní.",Her er noget ammunition til dig. Spild det ikke.,Hier hast du welche. Verschwende sie nicht.,,"Jen iom da municio. Ne malŝparu ĝin.","Aquí tienes algo de munición. -No la desperdicies.",,Tässä ammuksia. Älä tuhlaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van valamennyi lőszer. Ne pazarold el.,Ecco un pò di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,조금 나눠주도록 하겠습니다. 부디 낭비하지 마시길.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Tu jest trochę amunicji dla ciebie. Nie marnuj jej.,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну.,,Al sana biraz cephane. Boşa harcama. -You've got enough ammo.,TXT_RNO0_SCRIPT34_D15160_YOUVE,〃,,,Vždyť jich máš dost.,Du har ammunition nok.,Du hast genug.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ma veramente ne hai a sufficienza.,もう十分に弾を持ってるようだぞ。,충분한 탄약을 가졌군...,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczającą ilość amunicji.,Você já tem munição suficiente.,,Ai suficientă muniție.,У тебя хватает патронов.,,Yeterince cephanen var. -Teach me.,TXT_RPLY1_SCRIPT34_D15160_TEACH,〃,,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Öğret bana. +No la desperdicies.",,Tässä ammuksia. Älä tuhlaa niitä.,"En voilà pour vous, ne les gaspillez pas.",Itt van valamennyi lőszer. Ne pazarold el.,Ecco un po' di munizioni per te. Non sprecarle.,この弾をどうぞ、無駄遣いしないように。,조금 나눠주도록 하겠습니다. 부디 낭비하지 마시길.,Hier is wat munitie voor je. Verspil het niet.,Her er litt ammunisjon til deg. Ikke sløs den bort.,Tu jest trochę amunicji dla ciebie. Nie marnuj jej.,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну.,,Här är lite ammunition till dig. Slösa inte bort den.,Al sana biraz cephane. Boşa harcama. +You've got enough ammo.,TXT_RNO0_SCRIPT34_D15160_YOUVE,〃,,,Vždyť jich máš dost.,Du har ammunition nok.,Du hast genug.,,Vi havas sufiĉe da municio.,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,Ma veramente ne hai a sufficienza.,もう十分に弾を持ってるようだぞ。,충분한 탄약을 가졌군...,Je hebt genoeg munitie.,Du har nok ammunisjon.,Masz wystarczającą ilość amunicji.,Você já tem munição suficiente.,,Ai suficientă muniție.,У тебя хватает патронов.,,Du har tillräckligt med ammunition.,Yeterince cephanen var. +Teach me.,TXT_RPLY1_SCRIPT34_D15160_TEACH,〃,,,Uč mě.,Lær mig det.,Unterrichte mich.,,Trejnu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Lær meg det.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня.,,Lär mig.,Öğret bana. O.K. Take what you've learned and show those Order bastards the way to hell.,TXT_RYES1_SCRIPT34_D15160_OKTAK,〃,,,"Oukej. Pamatuj, co ses tady naučil, a ukaž těm hajzlům z Řádu cestu do pekla.",O.K. Tag det du har lært og vis de ordens-svin vejen til helvede.,"OK. Nutze, was du hier gelernt hast um diesen Tölpeln vom Orden den Weg in die Hölle zu zeigen.",,"Bone. Uzu ĉi tion por gvidi tiujn -aĉulojn de La Ordono al la infero.","Bien. Usa lo aprendido para guiar a esos +aĉulojn de La Ordeno al la infero.","Bien. Usa lo aprendido para guiar a esos majaderos de La Orden al infierno.","Bien. Usa lo aprendido para guiar a esos desgraciados de La Orden al infierno.","OK. Hyödynnä täällä oppimaasi, ja näytä niille Veljeskunnan valopäille tie helvettiin.",OK. Utilisez ce que vous avez appris et envoyez ces abrutis de l'Ordre en enfer.,"Rendben is vagyunk, mutasd meg a Rend kutyáknak a pokolba vezető utat!",O.K. Usa ciò che hai imparato qua per mostrare all'Ordine la via dell'Inferno.,"オーケー、ここで学んだ事を生かして -オーダー共を地獄に送って上げなさい。",이제 당신은 더 똑똑해졌습니다. 저 멍청한 오더 놈들에게 쓴맛을 보여주세요!,"Oké, neem wat je geleerd hebt en laat die ordeklootzakken de weg naar de hel zien.",OK. Ta det du har lært og vis de jævlene fra Ordenen veien til helvete.,"Weź to, czego się nauczyłeś i pokaż tym draniom z Zakonu drogę do piekła.",Ok. Use o que você aprendeu e mostre o caminho pro inferno para esses desgraçados da Ordem.,,"O.K. Cu ceea ce ai învățat, trimite-i pe nemernicii Ordinului către infern.","Запоминай внимательно, покажешь этим прихвостням Ордена быструю дорогу в ад.",,Tamam. Öğrendiklerini al ve o Tarikat piçlerine cehennemin yolunu göster. +オーダー共を地獄に送って上げなさい。",이제 당신은 더 똑똑해졌습니다. 저 멍청한 오더 놈들에게 쓴맛을 보여주세요!,"Oké, neem wat je geleerd hebt en laat die ordeklootzakken de weg naar de hel zien.",OK. Ta det du har lært og vis de jævlene fra Ordenen veien til helvete.,"Weź to, czego się nauczyłeś i pokaż tym draniom z Zakonu drogę do piekła.",Ok. Use o que você aprendeu e mostre o caminho pro inferno para esses desgraçados da Ordem.,,"O.K. Cu ceea ce ai învățat, trimite-i pe nemernicii Ordinului către infern.","Запоминай внимательно, покажешь этим прихвостням Ордена быструю дорогу в ад.",,Okej. Ta det du lärt dig och visa de där orderjävlarna vägen till helvetet.,Tamam. Öğrendiklerini al ve o Tarikat piçlerine cehennemin yolunu göster. "Come back later, when Macil says it's time.",TXT_RNO1_SCRIPT34_D15160_COMEB,〃,,,"Přijď někdy jindy, až řekne Macil.","Kom tilbage senere, når Macil siger, det er tid.","Komm wieder, wenn Macil dir Bescheid gibt.",,"Revenu post kiam Macil ordonis tion.","Vuelve más tarde cuando -Macil diga que ya es la hora.",,"Palaa asiaan myöhemmin, kun Macil näyttää vihreää valoa.",Revenez plus tard quand Macil décide qu'il est temps.,"Gyere vissza akkor, ha azt mondja Macil hogy ideje van.","Ritorna più tardi, quando Macil dirà che è il momento.",マシルの命令を受けてから、また来い。,마실 사령관님이 준비되었다고 말했을 때 와주세요.,"Kom later terug, als Macil zegt dat het tijd is.","Kom tilbake senere, når Macil sier det er på tide.","Wróć później, kiedy Macil powie, że już czas.","Volte mais tarde, quando o Macil disser que é hora.",,"Revin-o mai încolo, când Macil zice că e timpul.","Приходи позже, когда прикажет Мэйсил.",,Macil zamanı geldiğini söylediğinde geri gel. -I've taught you everything I can right now. Give me some time to put the new weapons through their paces. That is unless you're out of bullets.,TXT_DLG_SCRIPT34_D16676_IVETA,〃,,,"Naučil jsem tě vše, co teď můžu. Dej mi nějaký čas, abych vyzkoušel ty nové zbraně. Jedině, že bys potřeboval náboje.","Jeg har lært dig alt, hvad jeg kan lige nu. Giv mig lidt tid til at sætte de nye våben på prøve. Medmindre du er løbet tør for kugler.","Ich habe dir alles gezeigt, was ich momentan kann. Gib mir etwas Zeit um die neuen Waffen zu testen. Munition kriegst du natürlich auch so.",,"Mi instruis al vi ĉion, kion mi povas. Donu tempon al mi por elprovi la novajn armilojn... krom se vi nur bezonas pliajn kuglojn.","Te he enseñado todo lo que puedo por ahora. Dame tiempo para probar al 100% las nuevas armas... a menos que solo necesites más balas, claro.","Ya te enseñé todo lo que puedo por ahora. Dame tiempo para probar al 100% las nuevas armas... a menos que solo necesites más balas, claro.","Olen opettanut sinulle kaiken, mitä itse juuri nyt osaan. Anna minulle vähän aikaa käydä läpi uusien aseiden askelkuvioita. Ellei sinulla sitten ole luodit lopussa.","Je vous ai enseigné tout ce que je sais. Laissez moi un peu de temps pour tester ces nouvelles armes. Sauf si vous n'avez plus de munitions, bien sûr.","Megtanítottam mindent amit jelenleg tudtam. Adj egy kis időt, hogy leteszteljem a fegyvereket. Kivétel persze ha lőszer kell.",Ti ho insegnato tutto quello che potevo per ora. Dammi dell'altro tempo per mettere le nuove armi alla prova. A meno che non ti servano altre munizioni.,"私が教えられる事はもう無い。 +Macil diga que ya es la hora.",,"Palaa asiaan myöhemmin, kun Macil näyttää vihreää valoa.",Revenez plus tard quand Macil décide qu'il est temps.,"Gyere vissza akkor, ha azt mondja Macil hogy ideje van.","Ritorna più tardi, quando Macil dirà che è il momento.",マシルの命令を受けてから、また来い。,마실 사령관님이 준비되었다고 말했을 때 와주세요.,"Kom later terug, als Macil zegt dat het tijd is.","Kom tilbake senere, når Macil sier det er på tide.","Wróć później, kiedy Macil powie, że już czas.","Volte mais tarde, quando o Macil disser que é hora.",,"Revin-o mai încolo, când Macil zice că e timpul.","Приходи позже, когда прикажет Мэйсил.",,"Kom tillbaka senare, när Macil säger att det är dags.",Macil zamanı geldiğini söylediğinde geri gel. +I've taught you everything I can right now. Give me some time to put the new weapons through their paces. That is unless you're out of bullets.,TXT_DLG_SCRIPT34_D16676_IVETA,〃,,,"Naučil jsem tě vše, co teď můžu. Dej mi nějaký čas, abych vyzkoušel ty nové zbraně. Jedině, že bys potřeboval náboje.","Jeg har lært dig alt, hvad jeg kan lige nu. Giv mig lidt tid til at sætte de nye våben på prøve. Medmindre du er løbet tør for kugler.","Ich habe dir alles gezeigt, was ich momentan kann. Gib mir etwas Zeit um die neuen Waffen zu testen. Munition kriegst du natürlich auch so.",,"Mi instruis al vi ĉion, kion mi ĉi-momente povas. Donu tempon al mi por elprovi la novajn armilojn... krom se vi nur bezonas pliajn kuglojn.","Te he enseñado todo lo que puedo por ahora. Dame tiempo para probar al 100% las nuevas armas... a menos que solo necesites más balas, claro.","Ya te enseñé todo lo que puedo por ahora. Dame tiempo para probar al 100% las nuevas armas... a menos que solo necesites más balas, claro.","Olen opettanut sinulle kaiken, mitä itse juuri nyt osaan. Anna minulle vähän aikaa käydä läpi uusien aseiden askelkuvioita. Ellei sinulla sitten ole luodit lopussa.","Je vous ai enseigné tout ce que je sais. Laissez moi un peu de temps pour tester ces nouvelles armes. Sauf si vous n'avez plus de munitions, bien sûr.","Megtanítottam mindent amit jelenleg tudtam. Adj egy kis időt, hogy leteszteljem a fegyvereket. Kivétel persze ha lőszer kell.",Ti ho insegnato tutto quello che potevo per ora. Dammi dell'altro tempo per mettere le nuove armi alla prova. A meno che non ti servano altre munizioni.,"私が教えられる事はもう無い。 今後新しい武器は時間が掛かるが 自分のペースで学んだ方がいい。 -弾切れでなければの話だが。","배울 수 있는 모든 것들을 배우셨습니다. 이제 보급할 시간을 좀 주세요. 말이 나와서 하는 말인데, 탄약이 필요하십니까?",Ik heb je alles geleerd wat ik nu kan. Geef me wat tijd om de nieuwe wapens op de proef te stellen. Tenzij je geen kogels meer hebt.,Jeg har lært deg alt jeg kan for øyeblikket. Gi meg litt tid til å teste de nye våpnene. Med mindre du er tom for kuler.,"Nauczyłem cię wszystkiego, co mogę teraz. Dajcie mi trochę czasu, żeby przetestować nową broń. Chyba, że skończyły ci się naboje.",Te ensinei tudo o que eu posso no momento. Me dê um tempo para testar as novas armas. A não ser que você esteja sem munição.,,Te-am învâțat tot ce știu. Dă-mi niște timp să învăț noile arme. Asta în cazul în care nu ai nevoie de gloanțe.,Пока что я не могу научить тебя ничему новому. Дай мне время разобраться в этом новом оружии. Или у тебя закончились патроны?,,Şu anda sana öğretebileceğim her şeyi öğrettim. Yeni silahları denemem için bana biraz zaman ver. Tabii mermin bitmediyse. -Yes I am.,TXT_RPLY0_SCRIPT34_D16676_YESIA,〃,,,"Ano, potřebuju.","Ja, det er jeg.","Ja, bin ich.",,Ĝuste.,Eso mismo.,,Kyllä on.,"En effet, je le suis.",Igen.,Sì che mi servono.,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.","Jo, det har jeg.",Tak.,"Sim, eu estou.",,Da sunt.,"Да, закончились.",,"Evet, bitti." -Here you go.,TXT_RYES0_SCRIPT34_D16676_HEREY,〃,,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Ecco qua.,どうぞ。,여기요!,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici sunt.,Держи.,,Al bakalım. +弾切れでなければの話だが。","배울 수 있는 모든 것들을 배우셨습니다. 이제 보급할 시간을 좀 주세요. 말이 나와서 하는 말인데, 탄약이 필요하십니까?",Ik heb je alles geleerd wat ik nu kan. Geef me wat tijd om de nieuwe wapens op de proef te stellen. Tenzij je geen kogels meer hebt.,Jeg har lært deg alt jeg kan for øyeblikket. Gi meg litt tid til å teste de nye våpnene. Med mindre du er tom for kuler.,"Nauczyłem cię wszystkiego, co mogę teraz. Dajcie mi trochę czasu, żeby przetestować nową broń. Chyba, że skończyły ci się naboje.",Te ensinei tudo o que eu posso no momento. Me dê um tempo para testar as novas armas. A não ser que você esteja sem munição.,,Te-am învâțat tot ce știu. Dă-mi niște timp să învăț noile arme. Asta în cazul în care nu ai nevoie de gloanțe.,Пока что я не могу научить тебя ничему новому. Дай мне время разобраться в этом новом оружии. Или у тебя закончились патроны?,,Jag har lärt dig allt jag kan just nu. Ge mig lite tid att sätta de nya vapnen på prov. Det vill säga om du inte har slut på kulor.,Şu anda sana öğretebileceğim her şeyi öğrettim. Yeni silahları denemem için bana biraz zaman ver. Tabii mermin bitmediyse. +Yes I am.,TXT_RPLY0_SCRIPT34_D16676_YESIA,〃,,,"Ano, potřebuju.","Ja, det er jeg.","Ja, bin ich.",,Ĝuste.,Eso mismo.,,Kyllä on.,"En effet, je le suis.",Igen.,Sì che mi servono.,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.","Jo, det har jeg.",Tak.,"Sim, eu estou.",,Da sunt.,"Да, закончились.",,"Ja, det är jag.","Evet, bitti." +Here you go.,TXT_RYES0_SCRIPT34_D16676_HEREY,〃,,,Tady máš.,Værsgo.,Bitteschön.,,Jen.,Toma.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Ecco qua.,どうぞ。,여기요!,Alsjeblieft.,Vær så god.,Proszę bardzo.,Aqui está.,,Aici sunt.,Держи.,,Här har du.,Al bakalım. "Don't get trigger happy in the town, you'll set off the alarm and they will start sending in guards from the castle.",TXT_DLG_SCRIPT34_D18192_DONTG,"MAP34: Upstairs. (Identical to row 769)",,,Ať tě nenapadne střílet ve městě. Spustil bys poplach a přivolal stráže z hradu.,"Bliv ikke skydeglad i byen, du vil udløse alarmen, og de vil begynde at sende vagter ind fra slottet.","Fang nicht an, hier in der Stadt herumzuballern. Wenn du hier den Alarm auslöst, senden sie gleich die Truppen aus der Burg.",,Ne uzu pafilon en la urbo; vi ekagigus la alarmon kaj ili eksendus gardistojn el la kastelo.,"No te líes a tiros en el pueblo, que activarás la alarma y empezarán a enviar guardias desde el castillo.","No andes a los tiros en el pueblo, que vas a activar la alarma y van a empezar a mandar guardias desde el castillo.","Älä ala turhan liipaisinherkäksi kaupungilla. Aiheutat vielä hälytyksen, ja ne alkavat lähettää linnasta vartijoita.",Ne tirez pas partout en ville. Vous risquez de déclencher l'alarme et ils enverront tous les gardes du château à vos trousses.,"Ne keresd a bajt a városban. Beindítod a riasztót, és kiküldik érted a kastély őröket.",Non ti consiglio di avere il grilletto facile in città. Finiresti per attivare l'allarme e inizierebbero a mandare guardie dal castello.,"街の中で銃をバンバン撃ったりするんじゃないぞ 警報を鳴らしてしまえば、奴等が衛兵共を -城から送り込んでくるぞ。",무턱대고 마을에서 총질하지 마세요. 경보가 울림과 동시에 당신을 잡기 위해서 모든 병력을 보낼 겁니다.,"Laat de trekker niet gelukkig worden in de stad, je laat de wekker afgaan en ze sturen bewakers van het kasteel naar binnen.","Ikke bli skyteglad i byen, da går alarmen, og de sender inn vakter fra slottet.","Nie daj się sprowokować w mieście, bo podniesiesz alarm i zaczną wysyłać strażników z zamku.","Não saia atirando pela cidade, você vai ativar o alarme e vão mandar os guardas do castelo.",,"Nu deveni prea entuziasmat în oraș, vei declanșa alarma și vor trimite gardieni din castel.","Когда будешь в городе, не стреляй направо и налево. Если ты поднимешь тревогу, они вызовут подкрепление из замка.",,"Kasabada tetiğe basma, alarmı çalıştırırsın ve kaleden muhafızlar göndermeye başlarlar." +城から送り込んでくるぞ。",무턱대고 마을에서 총질하지 마세요. 경보가 울림과 동시에 당신을 잡기 위해서 모든 병력을 보낼 겁니다.,"Laat de trekker niet gelukkig worden in de stad, je laat de wekker afgaan en ze sturen bewakers van het kasteel naar binnen.","Ikke bli skyteglad i byen, da går alarmen, og de sender inn vakter fra slottet.","Nie daj się sprowokować w mieście, bo podniesiesz alarm i zaczną wysyłać strażników z zamku.","Não saia atirando pela cidade, você vai ativar o alarme e vão mandar os guardas do castelo.",,"Nu deveni prea entuziasmat în oraș, vei declanșa alarma și vor trimite gardieni din castel.","Когда будешь в городе, не стреляй направо и налево. Если ты поднимешь тревогу, они вызовут подкрепление из замка.",,"Bli inte skjutglad i staden, du sätter igång larmet och de börjar skicka in vakter från slottet.","Kasabada tetiğe basma, alarmı çalıştırırsın ve kaleden muhafızlar göndermeye başlarlar." "Welcome, we can always use more help.",TXT_DLG_SCRIPT34_D19708_WELCO,"〃 -(Identical to row 770)",,,"Vítej, pomoc se nám vždycky hodí.","Velkommen, vi kan altid bruge mere hjælp.","Willkommen, wir können immer etwas Hilfe gebrauchen.",,Bonvenon. Plia helpo ĉiam estas utilega.,"Bienvenido, siempre nos viene bien algo más de ayuda.",,Tervetuloa; voisimme aina kaivata lisää apua.,Bienvenue. Nous apprécions toute l'aide que nous pouvons recevoir.,"Üdv nálunk, mindig jól jön a segítség.","Benvenuto, ci serve tutto l'aiuto che possiamo ottenere.",ようこそ、我々が貴方の助けに成ります。,어서 오세요. 당신 같은 사람에게는 많은 도움이 필요합니다!,"Welkom, we kunnen altijd meer hulp gebruiken.","Velkommen, vi kan alltid trenge mer hjelp.","Witamy, zawsze przyda nam się więcej pomocy.",Seja bem-vindo. Qualquer ajuda também é sempre bem-vinda.,,"Bun-venit, ajutorul e bine-venit oricând.",Добро пожаловать. Нам всегда пригодится помощь.,,"Hoş geldiniz, her zaman daha fazla yardıma ihtiyacımız olabilir." +(Identical to row 770)",,,"Vítej, pomoc se nám vždycky hodí.","Velkommen, vi kan altid bruge mere hjælp.","Willkommen, wir können immer etwas Hilfe gebrauchen.",,Bonvenon. Plia helpo ĉiam estas utilega.,"Bienvenido, siempre nos viene bien algo más de ayuda.",,Tervetuloa; voisimme aina kaivata lisää apua.,Bienvenue. Nous apprécions toute l'aide que nous pouvons recevoir.,"Üdv nálunk, mindig jól jön a segítség.","Benvenuto, ci serve tutto l'aiuto che possiamo ottenere.",ようこそ、我々が貴方の助けに成ります。,어서 오세요. 당신 같은 사람에게는 많은 도움이 필요합니다!,"Welkom, we kunnen altijd meer hulp gebruiken.","Velkommen, vi kan alltid trenge mer hjelp.","Witamy, zawsze przyda nam się więcej pomocy.",Seja bem-vindo. Qualquer ajuda também é sempre bem-vinda.,,"Bun-venit, ajutorul e bine-venit oricând.",Добро пожаловать. Нам всегда пригодится помощь.,,"Välkommen, vi kan alltid behöva mer hjälp.","Hoş geldiniz, her zaman daha fazla yardıma ihtiyacımız olabilir." "When I was still in action we had the chance to examine an acolyte before the reinforcements arrived, they're not human I tell you.",TXT_DLG_SCRIPT34_D21224_WHENI,"〃 (Similar to row 771)",,,"Když jsem byl ještě v akci, měli jsme možnost prozkoumat mrtvého akolytu předtím, než přišly posily. Poslouchej, nejsou to lidé.","Da jeg stadig var i aktion havde vi mulighed for at undersøge en akolyt før forstærkningerne ankom, de er ikke menneskelige siger jeg jer.","Als ich noch aktiv war, hatten wir mal die Möglichkeit, einen der Ministranten zu untersuchen, bevor Verstärkung eintraf. Hör zu, sie sind nicht menschlich!",,"Kiam mi ankoraŭ estis en misio, ni havis okazon ekzameni akoliton antaŭ ol pliaj malamikoj alvenis, kaj ni malkovris, ke ili ne estas homoj.",Cuando aún estaba en acción tuvimos la oportunidad de examinar a un acólito antes de que llegaran los refuerzos y te digo que no son humanos.,,"Kun itse olin vielä mukana taistelemassa, saimme tilaisuuden tutkia akoluuttia ennen lisäjoukkojen saapumista. Ja kuule tarkkaan, ne eivät ole ihmisiä.","Quand j'étais encore en service, j'ai eu l'opportunité d'examiner un acolyte avant que les renforts n'arrivent. Vous savez, ils ne sont pas humains.","Amikor épp harcoltunk, alkalmunk adódott megvizsgálni egy ministránst amíg az erősítés meg nem érkezett volna. Bizony mondom neked, ezek nem emberek.","Quando ero ancora sul campo di battaglia, abbiamo avuto l'occasione di esaminare uno degli accoliti prima che arrivassero i rinforzi. Ascoltami, non sono umani.","私がまだ活動していた時、我々が増援に 囲まれる前にアコライトを調べる機会が あったんだ。聞いてくれ、奴等は人間では -なかったんだ。",제가 밖에서 근무했을 때 사살한 아콜라이트들을 자세히 들여다본 적이 있었어요. 그 들은 인간이 아니었습니다. 기억하세요.,"Toen ik nog in actie was hadden we de kans om een acoliet te onderzoeken voordat de versterkingen arriveerden, ze zijn niet menselijk, zeg ik je.","Da jeg fortsatt var i aksjon, fikk vi sjansen til å undersøke en akolytt før forsterkningene ankom. De er ikke menneskelige, sier jeg.","Kiedy byłem jeszcze w akcji, mieliśmy okazję zbadać akolitę przed przybyciem posiłków, nie są ludźmi, mówię wam.","Quando eu ainda estava na ativa nós tivemos a oportunidade de examinar um acólito antes dos reforços chegarem. Vai por mim, eles não são humanos.",,"Când încă luam parte la acțiune am avut ocazia să examinez un acolit. înaintă să ajungă întăririle, nu sunt umani.","Пока я был в оперативной группе, нам удалось вскрыть одного из служителей, прежде чем прибыло подкрепление. Так вот, они не люди.",,"Ben hala görevdeyken, takviye kuvvetler gelmeden önce bir yardımcı kişiyi inceleme şansımız oldu, size söylüyorum onlar insan değil." +なかったんだ。",제가 밖에서 근무했을 때 사살한 아콜라이트들을 자세히 들여다본 적이 있었어요. 그 들은 인간이 아니었습니다. 기억하세요.,"Toen ik nog in actie was hadden we de kans om een acoliet te onderzoeken voordat de versterkingen arriveerden, ze zijn niet menselijk, zeg ik je.","Da jeg fortsatt var i aksjon, fikk vi sjansen til å undersøke en akolytt før forsterkningene ankom. De er ikke menneskelige, sier jeg.","Kiedy byłem jeszcze w akcji, mieliśmy okazję zbadać akolitę przed przybyciem posiłków, nie są ludźmi, mówię wam.","Quando eu ainda estava na ativa nós tivemos a oportunidade de examinar um acólito antes dos reforços chegarem. Vai por mim, eles não são humanos.",,"Când încă luam parte la acțiune am avut ocazia să examinez un acolit. înaintă să ajungă întăririle, nu sunt umani.","Пока я был в оперативной группе, нам удалось вскрыть одного из служителей, прежде чем прибыло подкрепление. Так вот, они не люди.",,"När jag fortfarande var i aktion hade vi chansen att undersöka en akolyt innan förstärkningarna kom, de är inte mänskliga säger jag er.","Ben hala görevdeyken, takviye kuvvetler gelmeden önce bir yardımcı kişiyi inceleme şansımız oldu, size söylüyorum onlar insan değil." "We're trying to find where the castle gate mechanisms are, but so far we've had no luck.",TXT_DLG_SCRIPT34_D22740_WERET,"MAP34: Downstairs. -(Identical to row 772)",,,"Snažíme se zjistit, kde jsou mechanismy hradní brány, ale zatím jsme nic nenašli.","Vi prøver at finde ud af hvor slottets portmekanismer er, men indtil videre har vi ikke haft held.","Wir versuchen herauszufinden, von wo das Burgtor kontrolliert wird, aber bisher hatten wir kein Glück.",,"Ni provas malkovri, kie troviĝas la mekanismoj de la kastelpordo, sed ni ankoraŭ ne sukcesis.","Estamos intentando descubrir la ubicación de los mecanismos de la puerta del castillo, pero de momento no ha habido suerte.","Estamos tratando de descubrir la ubicación de los mecanismos de la puerta del castillo, pero por ahora no hubo suerte.","Yritämme löytää linnanportin koneistoa, mutta toistaiseksi laihoin tuloksin.","On essaie de trouver où se trouvent les contrôles de la porte du château, mais pour l'instant, on les a pas encore localisés.","Próbáljuk megtalálni a kastély kapu irányító mechanikáját, de eddig nem jártunk sikerrel.","Stiamo cercando di capire dove si trovano i meccanismi di apertura dell'entrata del castello, ma ancora niente.","我々は城門のメカニズムが何処にあるか +(Identical to row 772)",,,"Snažíme se zjistit, kde jsou mechanismy hradní brány, ale zatím jsme nic nenašli.","Vi prøver at finde ud af hvor slottets portmekanismer er, men indtil videre har vi ikke haft held.","Wir versuchen herauszufinden, von wo das Burgtor kontrolliert wird, aber bisher hatten wir kein Glück.",,"Ni provas malkovri, kie troviĝas la mekanismoj de la pordo de la kastelo, sed ni ankoraŭ ne sukcesis.","Estamos intentando descubrir la ubicación de los mecanismos de la puerta del castillo, pero de momento no ha habido suerte.","Estamos tratando de descubrir la ubicación de los mecanismos de la puerta del castillo, pero por ahora no hubo suerte.","Yritämme löytää linnanportin koneistoa, mutta toistaiseksi laihoin tuloksin.","On essaie de trouver où se trouvent les contrôles de la porte du château, mais pour l'instant, on les a pas encore localisés.","Próbáljuk megtalálni a kastély kapu irányító mechanikáját, de eddig nem jártunk sikerrel.","Stiamo cercando di capire dove si trovano i meccanismi di apertura dell'entrata del castello, ma ancora niente.","我々は城門のメカニズムが何処にあるか 探し続けているが、あまり良い結果は出ていない","성문을 열려고 열심히 분석을 해보았습니다만, 결국엔 해답을 찾지 못했습니다.","We proberen te vinden waar de mechanismen van de kasteelpoort zich bevinden, maar tot nu toe hebben we geen geluk gehad.","Vi prøver å finne ut hvor slottets portmekanismer er, men så langt har vi ikke hatt noe hell.","Próbujemy znaleźć gdzie są mechanizmy bramy zamkowej, ale jak na razie nie mamy szczęścia.","Estamos tentando localizar os mecanismos do portão do castelo, mas até agora não tivemos sorte.",,"Încercăm să găsim unde sunt mecanismele castelului, dar n-am avut noroc până acum.","Мы пытаемся найти механизм управления воротами замка, но пока безуспешно. -",,Kale kapısı mekanizmalarının nerede olduğunu bulmaya çalışıyoruz ama şu ana kadar şansımız yaver gitmedi. +",,"Vi försöker ta reda på var mekanismerna för slottets portar finns, men hittills har vi inte haft någon tur.",Kale kapısı mekanizmalarının nerede olduğunu bulmaya çalışıyoruz ama şu ana kadar şansımız yaver gitmedi. "Don't get caught. I've heard horror stories about what they do to our people after they're imprisoned. They just disappear, no traces, nothing. ",TXT_DLG_SCRIPT34_D24256_DONTG,"〃 (Similar to row 773)",,,"Nenech se chytit. Slyšel jsem děsivé příběhy o tom, co dělají našim lidem, když je uvězní. Prostě zmizí... beze stopy.","Bliv ikke fanget. Jeg har hørt skrækhistorier om, hvad de gør ved vores folk, efter de er blevet fængslet. De forsvinder bare, ingen spor, ingenting.","Lass dich nicht erwischen. Ich habe Horrorgeschichten darüber gehört, was sie unseren Leuten antun, die sie gefangengenommen haben. Sie verschwinden einfach... ohne jede Spur.",,"Oni ne kaptu vin. Mi aŭdis terurajn historiojn pri tio, kio okazas al niaj homoj post ilia aresto: ili simple malaperas, nek restaĵoj nek io ajn.",Que no te atrapen. He oído historias terroríficas de lo que hacen con nuestros hombres una vez detenidos: simplemente desaparecen sin rastros ni nada.,,"Älä jää kiinni. Olen kuullut kauhukertomuksia siitä, mitä ne tekevät meidän omillemme, kun he jäävät vangiksi. He yksinkertaisesti katoavat, jälkeä jättämättä.",Ne vous faites pas avoir. J'ai entendu des choses horribles sur ce qu'ils font à ceux qu'ils emprisonnent. Ils disparaîssent... Sans laisser de trace.,"Csak ne kapjanak el. Borzasztó történeteket hallottam azokról akiket bebörtönöztek. Csak úgy nyomuk vész, semmi nyom, konkrétan semmi.","Non farti prendere. Ho sentito storie orribili su quello che fanno alle persone dopo che le catturano. Spariscono completamente, senza tracce, niente di niente.","決して捕まるな。投獄されると奴等が 何をしでかすか怪談として聞く程だ。 -跡形もなく...消される。",오더에게 잡혀가면 절대로 안 됩니다. 수감자들에게 온갖 끔찍한 짓을 저지른다는 이야기를 들은 적이 있었으니까요. 흔적없이 조용히 끌고 간다네요...,"Laat je niet vangen. Ik heb horrorverhalen gehoord over wat ze onze mensen na hun gevangenschap aandoen. Ze verdwijnen gewoon, geen sporen, niets.","Ikke bli tatt. Jeg har hørt skrekkhistorier om hva de gjør med folket vårt etter at de blir fengslet. De bare forsvinner, ingen spor, ingenting.","Nie daj się złapać. Słyszałem przerażające historie o tym, co robią z naszymi ludźmi po uwięzieniu. Po prostu znikają, żadnych śladów, nic.","Não deixe eles te pegarem. Ouvi histórias de terror sobre o que eles fazem com o nosso pessoal depois que são aprisionados. Eles desaparecem, sem deixar rastros.",,Nu fii prins. Am auzit povești de groază legate de ce tratament primesc oamenii odată ce sunt închiși. Pur și simplu dispar fără niciun fel de urmă.,"Не дай себя схватить. Я слышал ужасные истории о том, что они делают с арестованными. Те просто исчезают... без следа.",,"Sakın yakalanmayın. Hapsedildikten sonra insanlarımıza ne yaptıklarına dair korku hikayeleri duydum. Öylece ortadan kayboluyorlar, ne bir iz ne de başka bir şey." +跡形もなく...消される。",오더에게 잡혀가면 절대로 안 됩니다. 수감자들에게 온갖 끔찍한 짓을 저지른다는 이야기를 들은 적이 있었으니까요. 흔적없이 조용히 끌고 간다네요...,"Laat je niet vangen. Ik heb horrorverhalen gehoord over wat ze onze mensen na hun gevangenschap aandoen. Ze verdwijnen gewoon, geen sporen, niets.","Ikke bli tatt. Jeg har hørt skrekkhistorier om hva de gjør med folket vårt etter at de blir fengslet. De bare forsvinner, ingen spor, ingenting.","Nie daj się złapać. Słyszałem przerażające historie o tym, co robią z naszymi ludźmi po uwięzieniu. Po prostu znikają, żadnych śladów, nic.","Não deixe eles te pegarem. Ouvi histórias de terror sobre o que eles fazem com o nosso pessoal depois que são aprisionados. Eles desaparecem, sem deixar rastros.",,Nu fii prins. Am auzit povești de groază legate de ce tratament primesc oamenii odată ce sunt închiși. Pur și simplu dispar fără niciun fel de urmă.,"Не дай себя схватить. Я слышал ужасные истории о том, что они делают с арестованными. Те просто исчезают... без следа.",,"Bli inte ertappad. Jag har hört skräckhistorier om vad de gör med vårt folk efter att de blivit fängslade. De bara försvinner, inga spår, ingenting.","Sakın yakalanmayın. Hapsedildikten sonra insanlarımıza ne yaptıklarına dair korku hikayeleri duydum. Öylece ortadan kayboluyorlar, ne bir iz ne de başka bir şey." "Here's some advice, if you ever see any of the Order's tin soldiers, run the other way. I especially don't like the Reavers, those things are just damned fast!",TXT_DLG_SCRIPT34_D25772_HERES,"〃 -(Similar to row 774)",,,"Dám ti radu: Jestli někdy uvidíš jednoho z plecháčků Řádu, otoč se a jdi. Jsou rychlí a suroví.","Her er et godt råd: Hvis du nogensinde ser nogen af Ordenens tinsoldater, så løb den anden vej. Jeg kan især ikke lide Reavers, de er bare forbandet hurtige!","Hier ist ein guter Rat, falls du jemals einen dieser Zinnsoldaten des Ordens vorbeigehen siehst. Sie sind schnell und brutal. ",,"Jen konsilo: estu ĉiam fore de la artefaritaj soldatoj de La Ordono. Mi plej malŝatas Lertajn Robotojn, ili estas rapidegaj!",Un consejo: mantente siempre alejado de los soldados artificiales de La Orden. Los Saqueadores son los peores; ¡esas cosas son jodidamente rápidas!,Un consejo: mantente siempre alejado de los soldados artificiales de La Orden. Los Saqueadores son los peores; ¡esos desgraciados son rápidos!,"Annan pienen vinkin: Jos koskaan näet Veljeskunnan tinasotilaita, juokse toiseen suuntaan. Inhoan varsinkin raastajia; ne ovat vaan niin pirun nopeita!","Voilà un conseil. Si vous voyez un des soldats mécanisés de l'Ordre, retournez vous et courez. Ils sont rapides et brutaux. J'aime surtout pas les Reavers, ces satanés trucs vont trop vite!","Az a tanácsom számodra, hogy ha meglátod a Rend ólomkatonáit, vedd az utad az ellentétes irányba. Különösen igaz ez a fosztogatókra, piszkosul gyorsak.","Ecco un consiglio. Se vedi uno dei soldatini di latta dell'Ordine, vai nella direzione opposta. In particolare temo i Reaver, quei dannati robot sono davvero veloci!","伝えておく、オーダーの錫兵は +(Similar to row 774)",,,"Dám ti radu: Jestli někdy uvidíš jednoho z plecháčků Řádu, otoč se a jdi. Jsou rychlí a suroví.","Her er et godt råd: Hvis du nogensinde ser nogen af Ordenens tinsoldater, så løb den anden vej. Jeg kan især ikke lide Reavers, de er bare forbandet hurtige!","Hier ist ein guter Rat, falls du jemals einen dieser Zinnsoldaten des Ordens vorbeigehen siehst. Sie sind schnell und brutal. ",,Jen konsilo: estu ĉiam fore de la artefaritaj soldatoj de La Ordeno. Mi plej malŝatas Lertulojn; ili estas rapidegaj!,Un consejo: mantente siempre alejado de los soldados artificiales de La Orden. Los Saqueadores son los peores; ¡esas cosas son jodidamente rápidas!,Un consejo: mantente siempre alejado de los soldados artificiales de La Orden. Los Saqueadores son los peores; ¡esos desgraciados son rápidos!,"Annan pienen vinkin: Jos koskaan näet Veljeskunnan tinasotilaita, juokse toiseen suuntaan. Inhoan varsinkin raastajia; ne ovat vaan niin pirun nopeita!","Voilà un conseil. Si vous voyez un des soldats mécanisés de l'Ordre, retournez vous et courez. Ils sont rapides et brutaux. J'aime surtout pas les Reavers, ces satanés trucs vont trop vite!","Az a tanácsom számodra, hogy ha meglátod a Rend ólomkatonáit, vedd az utad az ellentétes irányba. Különösen igaz ez a fosztogatókra, piszkosul gyorsak.","Ecco un consiglio. Se vedi uno dei soldatini di latta dell'Ordine, vai nella direzione opposta. In particolare temo i Reaver, quei dannati robot sono davvero veloci!","伝えておく、オーダーの錫兵は 他方から呼び出され押し寄せてくる。 -奴等は素早く残忍だ。","충고 하나 해주죠. 오더의 로봇 병사들을 발견한다면, 조용히 피해가세요. 특히나 성가신 놈 중 하나가 리버인데, 그놈의 산탄총은 장난 아니에요!","Hier is een advies, als je ooit een van de tinnen soldaten van de Orde ziet, ren dan de andere kant op. Ik hou vooral niet van de Reavers, die dingen zijn gewoon verdomd snel!","Hvis du ser noen av Ordenens tinnsoldater, så løp den andre veien. Jeg liker spesielt ikke Reavers, de er så jævla raske!","Oto rada, jeśli kiedykolwiek zobaczysz któregoś z blaszanych żołnierzy Zakonu, uciekaj w drugą stronę. Szczególnie nie lubię Łupieżców, te rzeczy są cholernie szybkie!","Um conselho pra você: se você ver algum desses soldados de lata da Ordem, fuja para o lado oposto. Eu particularmente detesto os Saqueadores. Eles são rapidos pra caramba!",,"Iată un sfat, dacă vezi vreodată un soldat al Ordinului, fugi în direcția opusă. Îmi displac mai ales Războinicii, ăștia sunt pur și simplu rapizi!","Небольшой совет: если увидишь «оловянных солдатиков» Ордена, сворачивай в другую сторону. Я особенно не люблю похитителей — эти твари довольно быстрые!",,"Size bir tavsiye, Tarikat'ın teneke askerlerinden birini görürseniz, diğer tarafa kaçın. Özellikle Yağmacıları sevmiyorum, o şeyler çok hızlı!" -"Welcome to the last flicker of hope. Only we have the free will to oppose the Order. We have the sharpest scientific minds, and many able bodies. But we lack that one real problem solver, who will give us the edge we need.",TXT_DLG_SCRIPT34_D27288_WELCO,MAP34: Macil.,,,"Vítej u posledního plamínku naděje. Jen my máme svobodnou vůli vzdorovat Řádu. Máme sice nejčilejší vědecké génie a mnoho schopných vojáků, ale chybí nám ten jeden řešitel problémů, který by nás posunul vpřed.","Velkommen til det sidste lille håb. Kun vi har den frie vilje til at modsætte os Ordenen. Vi har de skarpeste videnskabelige hjerner og mange dygtige kroppe. Men vi mangler den ene rigtige problemløser, som vil give os den fordel, vi har brug for.","Wilkommen beim letzten Hoffnungsschimmer. Nur wir haben noch den freien Willen, um gegen den Orden zu arbeiten. Wir haben die besten Wissenschaftler und viele fähige Kämpfer aber was uns fehlt ist ein spezieller Problemlöser, der uns den nötigen Vorteil verschafft.",,,"Bienvenido al último destello de esperanza. Solo nosotros tenemos el libre albedrío para oponernos a la Orden. Tenemos las mentes científicas más brillantes, y muchos cuerpos capaces. Pero nos falta un verdadero solucionador de problemas, alguien que nos dé la ventaja que necesitamos.",,"Tervetuloa viimeisen toivonpilkahduksen äärelle. Ainoastaan meillä on vapaa tahto vastustaa Veljeskuntaa. Meillä on tieteen terävimmät mielet ja monia ruumiiltaan vahvoja, mutta meiltä puuttuu se yksi todellinen ongelmanratkoja, joka antaisi meille kaipaamamme etulyöntiaseman.","Bienvenue au dernier lieu d'espoir. Nous seuls avons la liberté d'esprit pour opposer l'Ordre. Nous avons les esprits scientifiques les plus aiguisés et de nombreux hommes habiles et sains.. Mais il nous manque quelqu'un qui pourrait.. résoudre nos problèmes. Nous donner un peu d'aide, nous permettre de prendre l'avantage.","Köszöntelek a remény utolsó pislákoló fényénél. Már csak mi merünk szembeszállni a Renddel. Itt vannak a legélesebb elmék, életerős emberek, de hiányzik egy igazi...probléma megoldó, aki előnyt szerez számunkra. Segíts nekünk!","Benenuto nell'ultimo barlume di speranza. Noi siamo i soli ad avere la determinazione per combattere l'Ordine. Abbiamo brillanti scienziati e molti soldati capaci, ma ci manca quel vero e proprio risolutore di problemi, che ci può dare quel vantaggio che cerchiamo.","ようこそ、ここは我々の僅かな希望が集まる +奴等は素早く残忍だ。","충고 하나 해주죠. 오더의 로봇 병사들을 발견한다면, 조용히 피해가세요. 특히나 성가신 놈 중 하나가 리버인데, 그놈의 산탄총은 장난 아니에요!","Hier is een advies, als je ooit een van de tinnen soldaten van de Orde ziet, ren dan de andere kant op. Ik hou vooral niet van de Reavers, die dingen zijn gewoon verdomd snel!","Hvis du ser noen av Ordenens tinnsoldater, så løp den andre veien. Jeg liker spesielt ikke Reavers, de er så jævla raske!","Oto rada, jeśli kiedykolwiek zobaczysz któregoś z blaszanych żołnierzy Zakonu, uciekaj w drugą stronę. Szczególnie nie lubię Łupieżców, te rzeczy są cholernie szybkie!","Um conselho pra você: se você ver algum desses soldados de lata da Ordem, fuja para o lado oposto. Eu particularmente detesto os Saqueadores. Eles são rapidos pra caramba!",,"Iată un sfat, dacă vezi vreodată un soldat al Ordinului, fugi în direcția opusă. Îmi displac mai ales Războinicii, ăștia sunt pur și simplu rapizi!","Небольшой совет: если увидишь «оловянных солдатиков» Ордена, сворачивай в другую сторону. Я особенно не люблю похитителей — эти твари довольно быстрые!",,"Här är ett råd, om du någonsin ser någon av ordens tennsoldater, spring åt andra hållet. Jag gillar särskilt inte Reavers, de där sakerna är förbannat snabba!","Size bir tavsiye, Tarikat'ın teneke askerlerinden birini görürseniz, diğer tarafa kaçın. Özellikle Yağmacıları sevmiyorum, o şeyler çok hızlı!" +"Welcome to the last flicker of hope. Only we have the free will to oppose the Order. We have the sharpest scientific minds, and many able bodies. But we lack that one real problem solver, who will give us the edge we need.",TXT_DLG_SCRIPT34_D27288_WELCO,MAP34: Macil.,,,"Vítej u posledního plamínku naděje. Jen my máme svobodnou vůli vzdorovat Řádu. Máme sice nejčilejší vědecké génie a mnoho schopných vojáků, ale chybí nám ten jeden řešitel problémů, který by nás posunul vpřed.","Velkommen til det sidste lille håb. Kun vi har den frie vilje til at modsætte os Ordenen. Vi har de skarpeste videnskabelige hjerner og mange dygtige kroppe. Men vi mangler den ene rigtige problemløser, som vil give os den fordel, vi har brug for.","Wilkommen beim letzten Hoffnungsschimmer. Nur wir haben noch den freien Willen, um gegen den Orden zu arbeiten. Wir haben die besten Wissenschaftler und viele fähige Kämpfer aber was uns fehlt ist ein spezieller Problemlöser, der uns den nötigen Vorteil verschafft.",,"Bonvenon en la lasta fajrero da espero. Nur ni havas liberan volon por kontraŭstari al La Ordeno. Ni havas la plej inteligentajn mensojn kaj multe da kapablaj homoj, sed mankas tiu... tiu, kiu estus vera problem-solvanto, por ke li donu al ni la necesan avantaĝon.","Bienvenido al último destello de esperanza. Solo nosotros tenemos el libre albedrío para oponernos a La Orden. Tenemos las mentes científicas más brillantes y muchas personas capaces, pero nos falta el que... el que sería todo un solucionador de problemas para que nos dé la ventaja que necesitamos.",,"Tervetuloa viimeisen toivonpilkahduksen äärelle. Ainoastaan meillä on vapaa tahto vastustaa Veljeskuntaa. Meillä on tieteen terävimmät mielet ja monia ruumiiltaan vahvoja, mutta meiltä puuttuu se yksi todellinen ongelmanratkoja, joka antaisi meille kaipaamamme etulyöntiaseman.","Bienvenue au dernier lieu d'espoir. Nous seuls avons la liberté d'esprit pour opposer l'Ordre. Nous avons les esprits scientifiques les plus aiguisés et de nombreux hommes habiles et sains.. Mais il nous manque quelqu'un qui pourrait.. résoudre nos problèmes. Nous donner un peu d'aide, nous permettre de prendre l'avantage.","Köszöntelek a remény utolsó pislákoló fényénél. Már csak mi merünk szembeszállni a Renddel. Itt vannak a legélesebb elmék, életerős emberek, de hiányzik egy igazi...probléma megoldó, aki előnyt szerez számunkra. Segíts nekünk!","Benenuto nell'ultimo barlume di speranza. Noi siamo i soli ad avere la determinazione per combattere l'Ordine. Abbiamo brillanti scienziati e molti soldati capaci, ma ci manca quel vero e proprio risolutore di problemi, che ci può dare quel vantaggio che cerchiamo.","ようこそ、ここは我々の僅かな希望が集まる 最後の場所だ。オーダーへと立ち向かう意思を 持っているのは我々くらいだ。 ここには素晴らしい頭脳を持つ学者たち、 そして丈夫な体を持った戦士たちがいる。 だがしかし、我々には問題解決に優れた者、 つまり私達の力となる者が足りていないんだ。 -我々に手を貸してくれ。","희미한 희망에 빛에 온 것을 환영합니다. 우리만이 오더를 처치할 자유의지를 가지고 있지요. 우수한 과학력에, 뛰어난 실력을 소유한 부대도 있으니까 말입니다. 하지만, 우리들에게도 부족한 게 하나 있습니다. 바로 시련을 해결해 줄 해결사죠. 부디 도와주세요.","Welkom bij het laatste sprankje hoop. Alleen wij hebben de vrije wil om ons te verzetten tegen de Orde. We hebben de scherpste wetenschappelijke geesten en veel bekwame lichamen. Maar we missen die ene echte probleemoplosser, die ons de voorsprong zal geven die we nodig hebben.","Velkommen til det siste glimt av håp. Bare vi har den frie viljen til å motsette oss Ordenen. Vi har de skarpeste vitenskapelige hodene, og mange dyktige kropper. Men vi mangler den ene virkelige problemløseren, som vil gi oss det forspranget vi trenger.","Witamy w ostatniej iskierce nadziei. Tylko my mamy wolną wolę, by przeciwstawić się Zakonowi. Mamy najbystrzejsze umysły naukowe i wiele sprawnych ciał. Ale brakuje nam tego jednego prawdziwego rozwiązania problemu, które da nam przewagę, której potrzebujemy.","Seja bem-vindo à última ponta de esperança. Somos os únicos que têm o livre arbítrio para combater a Ordem. Temos as mentes científicas mais afiadas e muitas pessoas capazes. Mas ainda nos falta aquele verdadeiro quebra-galho, que nos dará o impulso que precisamos.",,"Bun-venit la ultima speranță. Numai noi avem voința de a ne opune Ordinului. Avem cele mai strălucite minți științifice și multe corpuri capabile. Dar ne lipsește acea persoană capabilă să rezolve probleme, care o să ne dea avantajul de care avem nevoie.","Добро пожаловать в последний оплот надежды. Только мы обладаем свободной волей, чтобы противостоять Ордену. С нами лучшие учёные умы, и у нас есть много толковых людей, но нам не хватает одного-единственного, э... «разрешителя проблем», который поможет нам получить необходимое преимущество.",,Son umut ışığına hoş geldiniz. Tarikat'a karşı çıkacak özgür irade sadece bizde var. En keskin bilimsel zihinlere ve birçok yetenekli bedene sahibiz. Ama bize ihtiyacımız olan avantajı sağlayacak gerçek bir sorun çözücüden yoksunuz. -What will I need to do? ,TXT_RPLY0_SCRIPT34_D27288_WHATW,〃,,,Co budu muset udělat?,Hvad skal jeg gøre?,Was muss ich tun?,,,¿Qué necesito hacer?,,Mitä minun tarvitsee tehdä?,Que dois-je faire?,Mit kell tennem?,Che cosa devo fare?,何をしたらいい?,무엇을 해야하죠?,Wat moet ik doen?,Hva må jeg gjøre?,Co będę musiał zrobić?,O que preciso fazer?,,Ce trebuie să fac?,Что я должен сделать?,,Ne yapmam gerekecek? -Help us. Help us steal their technology. Free our comrades. Fight these twisted psychopaths to the death. I'm asking you to risk your life for the truth.,TXT_DLG_SCRIPT34_D28804_HELPU,〃,,,Pomoz nám. Pomoz nám ukrást jejich technologie. Osvobodit naše druhy. Bojovat s těmi šílenými psychopaty na smrt. Chci po tobě riskovat svůj život kvůli pravdě.,Hjælp os. Hjælp os med at stjæle deres teknologi. Befri vores kammerater. Bekæmp disse forvredne psykopater til døden. Jeg beder dig om at sætte dit liv på spil for sandheden.,"Hilf uns. Hilf uns ihre Technologie zu stehlen. Befreie unsere Kameraden. Bekämpfe diese verwirrten Psychopathen bis zum Tod. Ich bitte dich, dein Leben zu riskieren um die Wahrheit zu verteidigen.",,,Ayúdanos. Ayúdanos a robar su tecnología. Libera a nuestros camaradas. Lucha contra estos retorcidos psicópatas hasta la muerte. Te estoy pidiendo que arriesgues tu vida por la verdad.,,Auta meitä. Auta meitä kaappaamaan heidän teknologiaansa. Vapauta meidän toverimme. Taistele näitä kieroituneita psykopaatteja vastaan kuoloon asti. Pyydän sinua antamaan henkesi alttiiksi totuuden nimessä.,Aidez nous. Aidez nous à voler leur technologie. Libérer nos camarades. Combattre ces psychopathes jusqu'à la mort. Je vous demande de risquer votre vie pour la vérité.,"Segíts nekünk. Abban, hogy ellophassuk a technológiájukat. Kiszabadítani a társainkat. Halálunkig harcolni ezek a pszihopaták ellen. Azt kell kérjem tőled, hogy tedd kockára az életed az igazságérrt.",Aiutaci. Aiutaci a rubare la loro tecnologia. Libera i nostri compagni. Combatti questi maledetti psicopatici fino alla morte. Ti sto chiedendo di rischiare la tua vita per la verità.,"我々の援護だ。我々が奴等のテクノロジーを +我々に手を貸してくれ。","희미한 희망에 빛에 온 것을 환영합니다. 우리만이 오더를 처치할 자유의지를 가지고 있지요. 우수한 과학력에, 뛰어난 실력을 소유한 부대도 있으니까 말입니다. 하지만, 우리들에게도 부족한 게 하나 있습니다. 바로 시련을 해결해 줄 해결사죠. 부디 도와주세요.","Welkom bij het laatste sprankje hoop. Alleen wij hebben de vrije wil om ons te verzetten tegen de Orde. We hebben de scherpste wetenschappelijke geesten en veel bekwame lichamen. Maar we missen die ene echte probleemoplosser, die ons de voorsprong zal geven die we nodig hebben.","Velkommen til det siste glimt av håp. Bare vi har den frie viljen til å motsette oss Ordenen. Vi har de skarpeste vitenskapelige hodene, og mange dyktige kropper. Men vi mangler den ene virkelige problemløseren, som vil gi oss det forspranget vi trenger.","Witamy w ostatniej iskierce nadziei. Tylko my mamy wolną wolę, by przeciwstawić się Zakonowi. Mamy najbystrzejsze umysły naukowe i wiele sprawnych ciał. Ale brakuje nam tego jednego prawdziwego rozwiązania problemu, które da nam przewagę, której potrzebujemy.","Seja bem-vindo à última ponta de esperança. Somos os únicos que têm o livre arbítrio para combater a Ordem. Temos as mentes científicas mais afiadas e muitas pessoas capazes. Mas ainda nos falta aquele verdadeiro quebra-galho, que nos dará o impulso que precisamos.",,"Bun-venit la ultima speranță. Numai noi avem voința de a ne opune Ordinului. Avem cele mai strălucite minți științifice și multe corpuri capabile. Dar ne lipsește acea persoană capabilă să rezolve probleme, care o să ne dea avantajul de care avem nevoie.","Добро пожаловать в последний оплот надежды. Только мы обладаем свободной волей, чтобы противостоять Ордену. С нами лучшие учёные умы, и у нас есть много толковых людей, но нам не хватает одного-единственного, э... «разрешителя проблем», который поможет нам получить необходимое преимущество.",,Välkommen till den sista gnistan av hopp. Endast vi har den fria viljan att motsätta oss Orden. Vi har de skarpaste vetenskapliga hjärnorna och många dugliga kroppar. Men vi saknar en riktig problemlösare som kan ge oss det övertag vi behöver.,Son umut ışığına hoş geldiniz. Tarikat'a karşı çıkacak özgür irade sadece bizde var. En keskin bilimsel zihinlere ve birçok yetenekli bedene sahibiz. Ama bize ihtiyacımız olan avantajı sağlayacak gerçek bir sorun çözücüden yoksunuz. +What will I need to do? ,TXT_RPLY0_SCRIPT34_D27288_WHATW,〃,,,Co budu muset udělat?,Hvad skal jeg gøre?,Was muss ich tun?,,Kion mi bezonas fari?,¿Qué necesito hacer?,,Mitä minun tarvitsee tehdä?,Que dois-je faire?,Mit kell tennem?,Che cosa devo fare?,何をしたらいい?,무엇을 해야하죠?,Wat moet ik doen?,Hva må jeg gjøre?,Co będę musiał zrobić?,O que preciso fazer?,,Ce trebuie să fac?,Что я должен сделать?,,Vad måste jag göra?,Ne yapmam gerekecek? +Help us. Help us steal their technology. Free our comrades. Fight these twisted psychopaths to the death. I'm asking you to risk your life for the truth.,TXT_DLG_SCRIPT34_D28804_HELPU,〃,,,Pomoz nám. Pomoz nám ukrást jejich technologie. Osvobodit naše druhy. Bojovat s těmi šílenými psychopaty na smrt. Chci po tobě riskovat svůj život kvůli pravdě.,Hjælp os. Hjælp os med at stjæle deres teknologi. Befri vores kammerater. Bekæmp disse forvredne psykopater til døden. Jeg beder dig om at sætte dit liv på spil for sandheden.,"Hilf uns. Hilf uns ihre Technologie zu stehlen. Befreie unsere Kameraden. Bekämpfe diese verwirrten Psychopathen bis zum Tod. Ich bitte dich, dein Leben zu riskieren um die Wahrheit zu verteidigen.",,"Helpu nin: helpu al ni ŝteli ilian teknologion, liberigu niajn kamaradojn, bataladu ĝismorte kontraŭ tiuj malicaj psikopatoj. Mi petas, ke vi risku vian vivon pro la vero.","Ayúdanos: ayúdanos a robar su tecnología, libera a nuestros camaradas, pelea contra esos retorcidos psicopáticos hasta la muerte. Te estoy pidiendo que arriesgues la vida por la verdad.",,Auta meitä. Auta meitä kaappaamaan heidän teknologiaansa. Vapauta meidän toverimme. Taistele näitä kieroituneita psykopaatteja vastaan kuoloon asti. Pyydän sinua antamaan henkesi alttiiksi totuuden nimessä.,Aidez nous. Aidez nous à voler leur technologie. Libérer nos camarades. Combattre ces psychopathes jusqu'à la mort. Je vous demande de risquer votre vie pour la vérité.,"Segíts nekünk. Abban, hogy ellophassuk a technológiájukat. Kiszabadítani a társainkat. Halálunkig harcolni ezek a pszihopaták ellen. Azt kell kérjem tőled, hogy tedd kockára az életed az igazságérrt.",Aiutaci. Aiutaci a rubare la loro tecnologia. Libera i nostri compagni. Combatti questi maledetti psicopatici fino alla morte. Ti sto chiedendo di rischiare la tua vita per la verità.,"我々の援護だ。我々が奴等のテクノロジーを 盗むのを手伝って欲しい。同胞の解放の為だ。 イカレた奴等と戦闘する必要がある。 正義を取り戻すため君には危険の伴う任務を -受けてほしいのだ。","우릴 도와주세요. 놈들의 기술을 훔치고, 붙잡힌 동료들을 구출하고, 오더의 미치광이들을 타도하기 위해서 말이죠. 그리고 진실 어린 희망을 위해서 이렇게 묻는 겁니다.",Help ons. Help ons hun technologie te stelen. Bevrijd onze kameraden. Bestrijd deze verdraaide psychopaten tot de dood toe. Ik vraag je om je leven te riskeren voor de waarheid.,Hjelpe oss. Hjelp oss med å stjele teknologien deres. Befri kameratene våre. Kjemp mot disse forskrudde psykopatene til døden. Jeg ber deg om å risikere livet for sannheten.,"Pomóc nam. Pomóż nam wykraść ich technologię. Uwolnić naszych towarzyszy. Walczyć z tymi pokręconymi psychopatami na śmierć. Proszę cię, abyś zaryzykował swoje życie dla prawdy.",Nos ajudar. Ajude-nos a roubar a tecnologia deles. Liberte nossos companheiros. Lute contra esses psicopatas insanos até a morte. Estou te pedindo para arriscar a sua vida pela verdade.,,Ajută-ne. Ajută-ne să le furăm tehnologia. Să ne eliberăm compatrioții. Să luptăm cu acești psihopați suciți până la moarte. Îți cer să îți riști viața pentru adevăr.,Помочь нам. Помочь нам украсть их технологии. Освободить наших товарищей. Сразиться с этими извращёнными психопатами и убить их. Рискнуть своей жизнью ради правого дела.,,Bize yardım et. Teknolojilerini çalmamıza yardım et. Yoldaşlarımızı serbest bırak. Bu sapkın psikopatlarla ölümüne savaş. Senden gerçek için hayatını riske atmanı istiyorum. -I'm with you!,TXT_RPLY0_SCRIPT34_D28804_IMWIT,〃,,,Jsem s tebou!,Jeg er med dig!,Ich bin dabei.,,,¡Estoy contigo!,,Olen kanssanne!,Je suis avec vous!,Veletek vagyok!,Sono con te!,同意した!,함께 하겠습니다!,Ik sta achter je!,Jeg er med deg!,Jestem z tobą!,Estou com vocês!,,Sunt cu tine!,Хорошо! Я с вами!,,Seninleyim! -"Good. Blackbird will continue to be your guide. She's taken quite a shine to you. Together, you've got to unlock the secrets of the Order and their inhuman servants. There's a presence that lurks just outside our understanding which guides their terror. Get inside and take them down. ",TXT_DLG_SCRIPT34_D30320_GOODB,〃,,,"Dobře, Straka ti bude dále dávat pokyny. Docela ses jí zalíbil. Společně budete muset odkrýt tajemství Řádu a jeho nelidských služebníků. Někde mimo naše chápání je něco, co ovládá jejich řádění. Pronikněte dovnitř a sejměte je.","Jeg er med dig. Blackbird vil fortsat være din guide. Hun er blevet ret glad for dig. Sammen skal I løse hemmelighederne om Ordenen og deres umenneskelige tjenere. Der er en tilstedeværelse, der lurer lige uden for vores forståelse, som styrer deres terror. Kom ind og nedkæmp dem.","Gut so! Blackbird wird weiter deine Leiterin sein, sie scheint dich zu mögen. Zusammen müsst ihr die Geheimnisse des Ordens und ihrer unmenschlichen Diener ergründen. Dann haben wir eine Chance, sie niederzuringen. Da ist eine Präsenz außerhalb unseres Vorstellungsvermögens, das diesen Terror leitet. Wir müssen sie unterwandern und dann vernichten.",,,"Bien. Blackbird continuará siendo tu guía. Le caes bastante bien. Juntos, teneis que desvelar los secretos de la Orden y sus sirvientes inhumanos. Hay una presencia que acecha más allá de nuestro conocimiento que guía su terror. Adéntrate y derríbalos.","Bien. Blackbird continuará siendo tu guía. Le caes bastante bien. Juntos, deberán desvelar los secretos de la Orden y sus sirvientes inhumanos. Hay una presencia que acecha más allá de nuestro conocimiento que guía su terror. Adéntrate y derríbalos.","Hyvä; Blackbird jatkaa opastajanasi. Hän vaikuttaa pitävän sinusta. Teidän on yhdessä paljastettava Veljeskunnan ja heidän epäinhimillisten palvelijoinsa salat. Heidän hirmuvaltaansa ohjaa läsnäolo, joka ylittää ymmärryksemme. Murtaudu sisään ja aja heidät alas.","Parfait. Blackbird continuera à être votre guide. Elle semble vous apprécier. Ensemble, vous allez découvrir les secrets de l'Ordre et leurs servants inhumains. Il existe une présece qui rôde juste au dehors de notre compréhension qui guide cette terreur. Infiltrez-les et détruisez-les.","Helyes, Feketerigó továbbra is az irányítód lesz. Eléggé megtetszettél neki. Együtt meg fogjátok fejteni a Rend és kegyetlen szolgáinak titkait. Egyfajta emberi ésszel fel nem fogható jelenlét kényszeríti őket a terrorizálásra. Hatoljatok be és intézzétek el őket.","Bene. Blackbird continuerà ad essere la tua guida. Sembra ti abbia preso in simpatia. Insieme dovrete scoprire i segreti dell'Ordine e dei loro servi inumani. C'è qualcosa di malefico, oltre la nostra comprensione, che guida il loro terrore. Bisognerà infiltrarlo e distruggerlo.","いいぞ、今後もブラックバードが君のガイドを +受けてほしいのだ。","우릴 도와주세요. 놈들의 기술을 훔치고, 붙잡힌 동료들을 구출하고, 오더의 미치광이들을 타도하기 위해서 말이죠. 그리고 진실 어린 희망을 위해서 이렇게 묻는 겁니다.",Help ons. Help ons hun technologie te stelen. Bevrijd onze kameraden. Bestrijd deze verdraaide psychopaten tot de dood toe. Ik vraag je om je leven te riskeren voor de waarheid.,Hjelpe oss. Hjelp oss med å stjele teknologien deres. Befri kameratene våre. Kjemp mot disse forskrudde psykopatene til døden. Jeg ber deg om å risikere livet for sannheten.,"Pomóc nam. Pomóż nam wykraść ich technologię. Uwolnić naszych towarzyszy. Walczyć z tymi pokręconymi psychopatami na śmierć. Proszę cię, abyś zaryzykował swoje życie dla prawdy.",Nos ajudar. Ajude-nos a roubar a tecnologia deles. Liberte nossos companheiros. Lute contra esses psicopatas insanos até a morte. Estou te pedindo para arriscar a sua vida pela verdade.,,Ajută-ne. Ajută-ne să le furăm tehnologia. Să ne eliberăm compatrioții. Să luptăm cu acești psihopați suciți până la moarte. Îți cer să îți riști viața pentru adevăr.,Помочь нам. Помочь нам украсть их технологии. Освободить наших товарищей. Сразиться с этими извращёнными психопатами и убить их. Рискнуть своей жизнью ради правого дела.,,Hjälp oss. Hjälp oss att stjäla deras teknologi. Befria våra kamrater. Kämpa mot de här förvridna psykopaterna in i döden. Jag ber dig riskera ditt liv för sanningen.,Bize yardım et. Teknolojilerini çalmamıza yardım et. Yoldaşlarımızı serbest bırak. Bu sapkın psikopatlarla ölümüne savaş. Senden gerçek için hayatını riske atmanı istiyorum. +I'm with you!,TXT_RPLY0_SCRIPT34_D28804_IMWIT,〃,,,Jsem s tebou!,Jeg er med dig!,Ich bin dabei.,,Mi aliĝos al vi!,¡Estoy contigo!,,Olen kanssanne!,Je suis avec vous!,Veletek vagyok!,Sono con te!,同意した!,함께 하겠습니다!,Ik sta achter je!,Jeg er med deg!,Jestem z tobą!,Estou com vocês!,,Sunt cu tine!,Хорошо! Я с вами!,,Jag är med dig!,Seninleyim! +"Good. Blackbird will continue to be your guide. She's taken quite a shine to you. Together, you've got to unlock the secrets of the Order and their inhuman servants. There's a presence that lurks just outside our understanding which guides their terror. Get inside and take them down. ",TXT_DLG_SCRIPT34_D30320_GOODB,〃,,,"Dobře, Straka ti bude dále dávat pokyny. Docela ses jí zalíbil. Společně budete muset odkrýt tajemství Řádu a jeho nelidských služebníků. Někde mimo naše chápání je něco, co ovládá jejich řádění. Pronikněte dovnitř a sejměte je.","Jeg er med dig. Blackbird vil fortsat være din guide. Hun er blevet ret glad for dig. Sammen skal I løse hemmelighederne om Ordenen og deres umenneskelige tjenere. Der er en tilstedeværelse, der lurer lige uden for vores forståelse, som styrer deres terror. Kom ind og nedkæmp dem.","Gut so! Blackbird wird weiter deine Leiterin sein, sie scheint dich zu mögen. Zusammen müsst ihr die Geheimnisse des Ordens und ihrer unmenschlichen Diener ergründen. Dann haben wir eine Chance, sie niederzuringen. Da ist eine Präsenz außerhalb unseres Vorstellungsvermögens, das diesen Terror leitet. Wir müssen sie unterwandern und dann vernichten.",,"Bone. Merlo plue estos via gvidanto; ŝajnas, ke ŝi jam simpatias vin. Vi kune devas malkaŝi la sekretojn de La Ordeno kaj de ĝiaj nehomaj servantoj. Estas estaĵo trans homa kompreno, kiu gvatas kaj gvidas iliajn teruraĵojn. Enŝoviĝu kaj detruu ilin.",Bien. Blackbird seguirá siendo tu guía; parece que ya le caes bien. Juntos debéis descubrir los secretos de La Orden y de sus sirvientes inhumanos. Hay una presencia ultramundana observando y guiando su terror desde las sombras. Infiltraos y acabad con ellos.,Bien. Blackbird va a seguir siendo tu guía; parece que ya le caes bien. Juntos deben descubrir los secretos de La Orden y de sus sirvientes inhumanos. Hay una presencia ultramundana observando y guiando su terror desde las sombras. Infíltrense y destrúyanlos.,"Hyvä; Blackbird jatkaa opastajanasi. Hän vaikuttaa pitävän sinusta. Teidän on yhdessä paljastettava Veljeskunnan ja heidän epäinhimillisten palvelijoinsa salat. Heidän hirmuvaltaansa ohjaa läsnäolo, joka ylittää ymmärryksemme. Murtaudu sisään ja aja heidät alas.","Parfait. Blackbird continuera à être votre guide. Elle semble vous apprécier. Ensemble, vous allez découvrir les secrets de l'Ordre et leurs servants inhumains. Il existe une présece qui rôde juste au dehors de notre compréhension qui guide cette terreur. Infiltrez-les et détruisez-les.","Helyes, Feketerigó továbbra is az irányítód lesz. Eléggé megtetszettél neki. Együtt meg fogjátok fejteni a Rend és kegyetlen szolgáinak titkait. Egyfajta emberi ésszel fel nem fogható jelenlét kényszeríti őket a terrorizálásra. Hatoljatok be és intézzétek el őket.","Bene. Blackbird continuerà ad essere la tua guida. Sembra ti abbia preso in simpatia. Insieme dovrete scoprire i segreti dell'Ordine e dei loro servi inumani. C'è qualcosa di malefico, oltre la nostra comprensione, che guida il loro terrore. Bisognerà infiltrarlo e distruggerlo.","いいぞ、今後もブラックバードが君のガイドを 務める。彼女は君に感心しているようだぞ。 君たちの二人で、オーダーと その人間離れした手下たちが持っている秘密を 暴いてもらいたい。 -奴等の基地に潜り込んで、倒すんだ。","감사드립니다! 블랙버드가 당신을 위해 계속 안내를 할 것입니다. 같이 행동한다면 오더의 흉측한 비밀들을 밝혀내고, 그들의 잔혹한 존재들을 응징할 수 있을 겁니다. 우리들의 이해심 밑에 공포를 인도하는 그들의 숨겨진 존재가 있죠. 그곳으로 들어가서, 물리치세요.",Goed. Blackbird zal je gids blijven. Ze heeft je een behoorlijke glans gegeven. Samen moeten jullie de geheimen van de Orde en hun onmenselijke dienaren ontrafelen. Er is een aanwezigheid die net buiten ons begrip schuilt en die hun angst leidt. Ga naar binnen en neem ze mee naar beneden.,Bra. Blackbird vil fortsette å være din guide. Hun har blitt ganske betatt av deg. Sammen må dere avsløre hemmelighetene til Ordenen og deres umenneskelige tjenere. Det er en tilstedeværelse som lurer like utenfor vår forståelse som styrer deres terror. Gå inn og ta dem.,"Dobrze. Blackbird nadal będzie twoim przewodnikiem. Polubiła cię. Razem musicie odkryć tajemnice Zakonu i ich nieludzkich sług. Istnieje obecność, która czai się poza naszym rozumieniem, która kieruje ich terrorem. Dostań się do środka i zdejmij ich.","Ótimo. Blackbird continuará sendo a sua guia. Ela parece que vai com a sua cara. Juntos, vocês desvendarão os segredos da Ordem e seus discípulos desumanos. Há uma presença que está além do nosso entendimento que guia todo esse terror. Vá infiltrar a Ordem e elimine-os.",,"Bun. Blackbird va continua să fie ghidul tău. A început să ia un interes asupra ta. Împreună, va trebui să aflați secretele Ordinului și servitorilor lor inumani. Există o prezență care se târăște la marginea capacității noastre de înțelegere care le ghidează teroarea. Infiltrează-te și pune-i la pământ.",Хорошо. «Чёрный дрозд» останется твоим проводником. Она тебе несколько симпатизирует. Вместе вы раскроете секреты Ордена и его бесчеловечных слуг. За этим ужасом стоит нечто лежащее далеко за пределами нашего понимания. Проникни на их территорию и ударь по ним как следует!,,Güzel. Karatavuk rehberin olmaya devam edecek. Senden oldukça hoşlandı. Birlikte Tarikat'ın ve insanlık dışı hizmetkârlarının sırlarını açığa çıkarmalısınız. Anlayışımızın hemen dışında gizlenen ve onların terörüne rehberlik eden bir varlık var. İçeri gir ve onları alaşağı et. -Let me at 'em!,TXT_RPLY0_SCRIPT34_D30320_LETME,〃,,,Pusť mě na ně!,Lad mig tage dem!,Lass mich das nur machen.,,,¡Voy a por ellos!,¡Voy por ellos!,Päästä minut heidän kimppuunsa!,Laissez moi m'en occuper!,Szétcincálom mind!,Lasciali a me!,任せろ!,저만 믿으세요!,Laat me naar ze toe!,La meg ta dem!,Pozwól mi na nich!,Pode deixar!,,Lasă-mă să pun mâna pe ei!,Я им покажу!,,Bırakın ben halledeyim! -That's the spirit.,TXT_RYES0_SCRIPT34_D30320_THATS,〃,,,Tak se mi to líbí.,Sådan er ånden.,Das ist die richtige Einstellung.,,,Ese es el espíritu.,,Niin sitä pitää.,J'aime entendre ça.,Ez a beszéd!,Questo è lo spirito giusto.,良い心掛けだ。,좋은 마음가짐입니다.,Dat is de geest.,Sånn skal det låte.,To jest duch.,Esse é o espírito.,,Ăsta e spiritul.,Правильный настрой.,,İşte ruh bu. -Welcome friend!,TXT_DLG_SCRIPT34_D31836_WELCO,〃,,,"Vítej, příteli!","Velkommen, min ven!","Wilkommen, Freund.",,"Bonvenon, amiko!","¡Bienvenido, amigo!",,"Tervetuloa, ystävä!","Bievenue, notre ami!",Üdvözöllek barátom.,Benvenuto amico!,よく来た、同志!,"어서오세요, 친구여!",Welkom vriend!,"Velkommen, min venn!",Witaj przyjacielu!,"Seja bem-vindo, amigo!",,Bun-venit prietene!,"Добро пожаловать, друг!",,Hoş geldin dostum! -,,Random dialogue,,,,,,,,,,,,,,,,,,,,,,,, -Please don't hurt me.,TXT_RANDOM_PEASANT_01,,,,"Neubližuj mi, prosím.",Du må ikke gøre mig noget.,Bitte tu mir nicht weh.,,Bonvolu ne vundi min.,"No me hagas nada, por favor.",,"Pyydän, älä vahingoita minua.","S'il vous plaît, laissez-moi tranquille.",Kérlek ne bánts!,"Ti prego, non farmi del male.",私を傷つけないでくれ。,목숨만은 살려줘.,Doe me alsjeblieft geen pijn.,"Vær så snill, ikke skad meg.","Proszę, nie rób mi krzywdy.","Por favor, não me machuque.",,Te rog nu mă răni.,"Пожалуйста, не трогай меня.",,Lütfen bana zarar verme. -"If you're looking to hurt me, I'm not really worth the effort.",TXT_RANDOM_PEASANT_02,,,,"Jestli mi chceš ublížit, fakt za to nestojím.","Hvis du er ude på at såre mig, er jeg ikke rigtig besværet værd.","Falls du mir was antun willst, ich bin den Aufwand nicht wert.",,"Se vi intencas vundi min, vi vere gajnos nenion.","Si estás tratando de hacerme algo, no vale la pena realmente.",,"Jos aikomuksenasi on vahingoittaa minua, en todellakaan ole sen vaivan väärti.","Si vous cherchez à me faire mal, Je n'en mérite pas l'effort.","Ha bántani akarsz, nem éri meg a fáradozást.","Se hai intenzione di farmi del male, ti assicuro che non ne valgo la pena.","もしお前が私に暴力を振るいたいなら間違いだ、 -私を殴る価値はないから。","날 괴롭히려고 여기까지 왔다면, 넌 헛수고를 한 거야.","Als je me pijn wilt doen, ben ik de moeite niet echt waard.","Hvis du er ute etter å skade meg, er jeg ikke verdt det.","Jeśli chcesz mnie skrzywdzić, nie jestem wart wysiłku.","Se pretende me machucar, te digo que não valerá a pena.",,"Dacă vrei să mă rănești, nu merit efortul.","Если ты хочешь ударить меня, то я не стою твоих усилий.",,"Eğer beni incitmek istiyorsan, bu çabaya değmem." -I don't know anything.,TXT_RANDOM_PEASANT_03,,,,O ničem nevím.,Jeg ved ikke noget.,Ich weiß nichts.,,Mi scias nenion.,No sé nada.,,En tiedä mitään.,Je ne sais rien.,Én semmit sem tudok.,Non so niente.,私は何も知らないんだ。,난 정말 아무것도 몰라.,Ik weet niets.,Jeg vet ingenting.,Nic nie wiem.,Eu não sei de nada.,,Nu știu nimic.,Я ничего не знаю.,,Ben bir şey bilmiyorum. -Go away or I'll call the guards!,TXT_RANDOM_PEASANT_04,,,,"Jdi pryč, nebo zavolám stráže!","Gå væk, eller jeg tilkalder vagterne!",Hau ab oder ich rufe die Wachen!,,Foriru aŭ mi vokos la gardistojn!,¡Vete o llamaré a los guardias!,¡Vete o llamo a los guardias!,"Mene pois, tai kutsun vartijat!",Allez vous en ou j'appelle les gardes!,"Tűnj innen, vagy hívom az őröket!",Vattene o chiamo le guardie!,離れろ、さもなくば衛兵を呼ぶぞ!,경비병 부르기 전에 얼른 사라져!,Ga weg of ik roep de bewakers!,"Gå vekk, ellers tilkaller jeg vaktene!",Odejdź albo zawołam strażników!,Vá embora antes que eu chame os guardas!,,Pleacă sau voi chema gardienii!,"Уходи, или я позову стражу!",,Git buradan yoksa muhafızları çağırırım! -I wish sometimes that all these rebels would just learn their place and stop this nonsense.,TXT_RANDOM_PEASANT_05,,,,"Občas si přeju, aby si ti rebelové uvědomili, kde jsou, a skončili s těmi svými nesmysly.","Nogle gange ville jeg ønske, at alle disse oprørere bare ville lære deres plads og stoppe dette nonsens.","Manchmal wünsche ich mir, dass diese Rebellen ihren Unsinn stoppen würden.",,"Mi iufoje deziras, ke ĉiu ribelanto simple lernu vivi kaj haltigu tiun absurdon.",A veces deseo que todos los rebeldes simplemente aprendieran a vivir y se dejaran de tonterías.,A veces deseo que todos los rebeldes simplemente aprendan a vivir y que paren con esa idiotez.,Kunpa joskus kaikki nämä kapinalliset vain oppisivat paikkansa ja lopettaisivat tämän mielettömyyden.,"Je voudrais qu'a un moment, ces rebelles apprennent quelle est leur place et arrètent cette idiotie.","Néha azt kívánom, hogy ezek a lázadók bár megtanulnák, hol a helyük, és felhagynának ezzel az eszeveszett dologgal.",A volte vorrei solo che i ribelli imparassero a stare al loro posto e la smettessero con tutte queste follie.,"反乱軍がこんな出鱈目な状態をひっくり返すのを -切に願うよ。",저 저항군들이 가망이 없다는 걸 빨리 눈치챘으면 정말 좋겠군.,Ik wou soms dat al die rebellen gewoon hun plaats zouden leren kennen en deze onzin zouden stoppen.,Noen ganger skulle jeg ønske at alle disse opprørerne kunne lære seg sin plass og slutte med dette tullet.,"Chciałbym czasem, żeby ci wszyscy buntownicy nauczyli się, gdzie ich miejsce i skończyli z tymi bzdurami.",Às vezes eu queria que esses rebeldes cuidassem de suas próprias vidas e parassem com esse absurdo.,,Uneori îmi doresc ca rebelii ăștia să își vadă de treaba lor și să înceteze cu tâmpeniile.,"Иногда мне хочется, чтобы все эти повстанцы просто поняли своё место и прекратили эту пустую возню.",,Bazen tüm bu isyancıların hadlerini bilmelerini ve bu saçmalığa bir son vermelerini diliyorum. -"Just leave me alone, OK?",TXT_RANDOM_PEASANT_06,,,,"Prostě mě nech být, jasný?","Bare lad mig være i fred, okay?","Lass mich bitte in Ruhe, ok?",,"Ne proksimiĝu al mi, ĉu?","Déjame en paz, ¿vale?","Déjame en paz, ¿sí?","Jätä minut vain rauhaan, onko selvä?","Laissez moi seul, OK?","Csak hagyj magamra, jó?","Lasciami in pace e basta, OK?",私に構わないでくれよ、頼むぞ?,그냥 날 내버려 둬. 부탁이야.,"Laat me gewoon met rust, oké?","Bare la meg være i fred, OK?","Zostaw mnie w spokoju, dobrze?","Apenas me deixe em paz, ok?",,"Doar lasă-mă în pace, OK?","Просто оставь меня в покое, хорошо?",,"Beni yalnız bırak, tamam mı?" -"I'm not sure, but sometimes I think that I know some of the acolytes.",TXT_RANDOM_PEASANT_07,,,,"Nejsem si jistý, ale občas se mi zdá, že znám některé z akolytů.","Jeg er ikke sikker, men nogle gange tror jeg, at jeg kender nogle af akolytterne.","Ich bin nicht ganz sicher, aber manchmal kommt es mir vor, als kenne ich diese Ministranten.",,"Mi ne estas certa, sed mi iufoje kredas, ke mi konas iujn el la akolitoj.","No estoy seguro, pero a veces creo que reconozco a algunos de los acólitos.","No estoy seguro, pero a veces creo que ya conozco a algunos de los acólitos.","En ole varma, mutta toisinaan jotkut akoluutit vaikuttavat tutuilta.","Je ne suis pas sûr, mais quelque fois je pense reconnaître certains des acolytes.","Nem vagyok benne bizonyos, de néha mintha ismerném némelyik ministránst.","Non ne sono sicuro, ma volte mi sembra di conoscere alcuni degli accoliti.","何か、アコライトの中で見覚えのある顔したのが -いたんだが。","자세히는 모르지만, 내가 본 아콜라이트들 중에 아는 사람이 있는 것 같아.","Ik weet het niet zeker, maar soms denk ik dat ik sommige van de acolieten ken.","Jeg er ikke sikker, men noen ganger tror jeg at jeg kjenner noen av akolyttene.","Nie jestem pewien, ale czasem wydaje mi się, że znam niektórych akolitów.","Eu não tenho bem certeza, mas acho que conheco alguns dos acólitos.",,"Nu sunt sigur, dar uneori am impresia că cunosc pe unii acoliți.","Я не уверен, но порой мне кажется, что я узнаю некоторых служителей.",,Emin değilim ama bazen bazı yardımcıları tanıdığımı düşünüyorum. -The Order's got everything around here pretty well locked up tight.,TXT_RANDOM_PEASANT_08,,,,Řád to tu má všechno pod hodně přísným dohledem.,Ordenen har alting her omkring temmelig godt låst godt inde.,Der Orden hat hier alles ziemlich gut unter Kontrolle.,,La Ordono havas ĉion tie ĉi sufiĉe bone blokata.,La Orden tiene todo por aquí fuertemente bloqueado.,,Veljeskunnalla on täällä aika lailla kaikki tiukassa otteessaan.,L'ordre maintient la sûreté aux alentours.,A Rend mindent jól elzárt előlünk.,L'Ordine si è dato parecchio da fare per chiudere e sbarrare un po' tutto qui in giro.,オーダー達はここいらを厳しく取り締まってる。,오더가 치안유지도 그렇고 단속을 아주 실감 나게 잘하던데?,De Orde heeft alles hier in de buurt vrij goed afgesloten.,Ordenen har alt her ganske godt låst.,Zakon ma tu wszystko pod ścisłą kontrolą.,A Ordem mantém tudo trancado a sete chaves.,,Ordinul a încuiat cam tot ce se poate pe aici.,Орден держит тут всё под замком.,,Tarikat buradaki her şeyi oldukça iyi kilitlemiş. -There's no way that this is just a security force.,TXT_RANDOM_PEASANT_09,,,,"Není možné, aby tohle byly jen bezpečnostní složky.","Det er umuligt, at det bare er en sikkerhedsstyrke.",Das sind niemals nur Sicherheitskräfte.,,"Ne estas maniero, ke ĉi tio estas nur «sekureca forto».",No hay manera de que esto sea solo una fuerza de seguridad.,,Ei tämä mitenkään voi olla pelkkä turvallisuusjoukko.,Ca ne peut pas être juste une escouade de sécurité...,Na ez már tutira nem lehet csak a biztonsági szolgálat.,"E' impossibile che questa sia solo una ""forza di sicurezza"".",お前がただの警備兵なんてことはなさそうだな。,저 녀석들은 단순히 치안을 유지하기 위해 온 게 아니라고 생각해.,Er is geen sprake van dat dit gewoon een veiligheidsdienst is.,Det er ikke mulig at dette bare er en sikkerhetsstyrke.,"Nie ma mowy, żeby to była tylko ochrona.",Não tem como isso ser apenas um força de segurança.,,Sub nicio formă nu e asta doar o forță de securitate.,Без разрешения стражей порядка и шагу ступить нельзя.,,Bunun sadece bir güvenlik gücü olmasına imkan yok. -I've heard that the Order is really nervous about the Front's actions around here.,TXT_RANDOM_PEASANT_10,,,,"Slyšel jsem, že je Řád prý dost nervózní z toho, co tu Fronta dělá.","Jeg har hørt, at Ordenen er meget nervøs over Frontens handlinger her.","Ich habe gehört, dass der Orden sehr beunruhigt über die Aktionen der Front ist.",,"Mi aŭdis, ke La Ordono estas tre nervoza pro la agoj de la ĉirkaŭa Fronto.",He oído que La Orden está realmente nerviosa por las acciones del Frente en los alrededores.,,Veljeskunta on kuulemma tosi huolissaan Rintaman toimista täällä.,J'ai entendu dire que l'ordre était sur les nerfs à cause des actions du front.,Úgy hírlik A Rend nagyon ideges a Front munkálkodásai miatt mostanság.,Ho sentito che l'Ordine è parecchio nervoso riguardo le azioni del Fronte nei dintorni.,"私はオーダーがこの辺での反乱軍の行動を -本当に厄介がってると聞いたぞ。",오더가 프론트 저항군의 공작에 정말 불안해하고 있더라고.,Ik heb gehoord dat de Orde echt nerveus is over de acties van het Front hier in de buurt.,Jeg har hørt at Ordenen er veldig nervøs for Frontens handlinger her.,"Słyszałem, że Zakon jest bardzo zdenerwowany działaniami Frontu w tym miejscu.",Ouvi falar que a Ordem anda bem nervosa por causa das ações da Frente por aqui.,,Am auzit că Ordinul e destul de stresat dorită acțiunilor Frontului pe-aici.,"Я слыхал, что Орден серьёзно обеспокоен действиями повстанцев в этом районе.",,Tarikat'ın Cephe'nin buradaki eylemleri konusunda gerçekten gergin olduğunu duydum. -There's no way the Order will stand against us.,TXT_RANDOM_REBEL_01,,,,Řád se nám v žádném případě nemůže postavit.,Ordenen vil på ingen måde stå imod os.,Niemals wird sich der Orden gegen uns stellen!,,La Ordono neniel povos rezisti al ni.,No hay forma de que La Orden aguante contra nosotros.,,Veljeskunta ei voi millään kestää meitä vastaan.,L'ordre n'a aucune chance contre nous.,A Rend labdába sem rúghat ellenünk!,Non è possibile che l'Ordine possa mettersi contro di noi.,オーダーが私達に立ち向かえるはずはない。,오더 녀석들이 우리를 이길 가능성은 전혀 없어.,De Orde zal op geen enkele manier tegen ons ingaan.,Det er ingen sjanse for at Ordenen vil gå imot oss.,"Nie ma mowy, by Zakon stanął przeciwko nam.",Nao ha como a Ordem ficar contra a gente.,,Nicio șansă ca Ordinul să ni se opună.,Ордену никак не устоять против нас.,,Düzen'in bize karşı durmasına imkan yok. -We're almost ready to strike. Macil's plans are falling in place.,TXT_RANDOM_REBEL_02,,,,Jsme téměř připraveni zaútočit. Macilovy plány do sebe začínají zapadat.,Vi er næsten klar til at slå til. Macils planer er ved at falde på plads.,Wir sind zum großen Schlag bereit. Macils Plane werden bald umgesetzt.,,Ni estas preskaŭ pretaj por ekataki. La planoj de Macil sukcesas perfekte.,Estamos casi listos para atacar. Los planes de Macil están saliendo a la perfección.,,Olemme melkein valmiit hyökkäämään. Macilin suunnitelmat loksahtavat paikalleen.,Nous sommes presque prêts à agir. Les plans de Macil se déroulent comme prévu.,"Már majdnem készen állunk, hogy lecsapjunk. Macil tervei kezdenek bejönni.",Siamo quasi pronti a colpire. I piani di Macil stanno andando lisci come l'olio.,"攻撃の準備は殆ど整った。 -マシルの計画は所定の位置に下す。",반격할 준비가 거의 다 돼가고 있어. 마실 사령관님의 계획이 잘 진행되고 있으니까.,We zijn bijna klaar om toe te slaan. Macil's plannen vallen op zijn plaats.,Vi er nesten klare til å slå til. Macils planer faller på plass.,Jesteśmy prawie gotowi do uderzenia. Plany Macila są coraz lepsze.,Estamos quase prontos para o ataque. Os planos de Macil estão fazendo efeito.,,Suntem aproape gata să dăm lovitura. Planurile lui Macil încep să se lege.,Мы почти готовы атаковать. Планы Мэйсила становятся ясны.,,Saldırmaya neredeyse hazırız. Macil'in planları yerine oturuyor. -"We're all behind you, don't worry.",TXT_RANDOM_REBEL_03,,,,"Všichni stojíme za tebou, neboj.","Vi står alle bag dig, bare rolig.","Wir stehen zu dir, keine Sorge.",,"Ni protektos vin dorse, vi do estu trankvila.","Nosotros te cubrimos la espalda, así que tranquilo.",,"Olemme kaikki tukenasi, älä huoli.","On couvre tes arrières, t'inquiète pas.","Mind itt vagyunk mögötted, ne aggódj!","Non preoccuparti, noi tutti ti copriamo le spalle.",後ろは見ているぞ、気にするな。,걱정 마. 무슨 일이 있어도 우리가 지켜줄게!,"We staan allemaal achter je, maak je geen zorgen.","Vi står bak deg, ikke vær redd.","Wszyscy jesteśmy za tobą, nie martw się.","Estamos todos te protegendo, não se preocupe.",,"Suntem toți în spatele tău, nu te teme.",Не беспокойся. Мы сразу за тобой.,,"Hepimiz arkandayız, merak etme." -Don't get too close to any of those big robots. They'll melt you down for scrap!,TXT_RANDOM_REBEL_04,,,,Nepřibližuj se k těm velkým robotům. Usmaží tě na kaši!,Kom ikke for tæt på nogen af de store robotter. De vil smelte dig ned til skrot!,Komm diesen großen Robotern nicht zu nahe. Die schmelzen dich zu Schrott ein.,,Ne proksimiĝu tiel multe al tiuj robotegoj. Ili povus disigi vin je rubo!,No te acerques tanto a uno de esos robots grandes. ¡Podrían convertirían en chatarra!,,Älä mene liian lähelle mitään noista isoista roboteista. Ne sulattavat sinut kuonaksi.,Ne vous approchez pas trop des gros robots. Ils vous brûleront jusqu'à l'os!,Azokhoz a nagy robotokhoz ne nagyon menj közel. Felaprítanak tüzifának!,Non avvicinarti troppo a uno di quei grossi robot. Ti ridurrebbero in rottami!,"デカブツには近づくなよ。スクラップみたいに -踏みつぶされるぞ!",저 커다란 로봇들에게 다가갈 생각은 하지 마. 너를 완전 발끝까지 녹여버릴 거라고.,Kom niet te dicht bij een van die grote robots. Ze zullen je laten smelten voor de schroothoop!,Ikke kom for nær noen av de store robotene. De smelter deg om til skrap!,Nie zbliżaj się zbytnio do tych wielkich robotów. Przetopią cię na złom!,Nem pense em ficar perto daqueles robôs. Vão te transformar em ferro velho num instante!,,Nu te apropia de roboți. Te vor topii!,Держись подальше от этих больших роботов. Они и мокрого места от тебя не оставят!,,O büyük robotlara fazla yaklaşma. Sizi hurda için eritirler! -"The day of our glory will soon come, and those who oppose us will be crushed!",TXT_RANDOM_REBEL_05,,,,"Naše dny slávy brzy nadejdou a ti, kdo se nám postaví, budou rozdrceni!","Vores storhedsdag vil snart komme, og de, der modsætter sig os, vil blive knust!","Der Tag des Triumphes ist nahe, und die, die gegen uns sind, werden vernichtet.",,,¡El día de nuestra gloria llegará pronto y aquellos que se opusieron a nosotros serán destruidos!,¡El día de nuestra gloria va a llegar pronto y aquellos que se opusieron a nosotros van a ser destruidos!,"Kunnian päivämme häämöttää, ja kaikki meitä vastustavat vihittäkööt tuhon omiksi!","Le jour de gloire arrivera bientôt, et ceux qui s'opposeront a nous seront écrasés!","Dicsőségünk napja hamarosan eljön, és akik ellenünk szegülnek, elkárhoznak.","Il giorno della nostra gloria verrà presto, e quelli che si oppongono a noi verranno schiacciati!","栄光の日は我々に訪れる、 -そして反逆する者達は潰す!",영광스러운 새벽이 오고있어. 우리를 탄압한 녀석들에게 징벌을 내릴 새벽이!,"De dag van onze glorie zal snel komen, en degenen die zich tegen ons verzetten zullen worden verpletterd!","Dagen for vår herlighet vil snart komme, og de som motsetter seg oss vil bli knust!","Dzień naszej chwały wkrótce nadejdzie, a ci, którzy się nam sprzeciwią, zostaną zmiażdżeni!","O dia de nossa glória chegará, e aqueles que se opuserem contra nós serão destruídos!",,Ziua în care noi vom avea gloria va veni curând și toti vor fi striviți.,Близок день нашего триумфа. Скоро наши враги будут уничтожены!,,Zafer günümüz yakında gelecek ve bize karşı çıkanlar ezilecek! -Don't get too comfortable. We've still got our work cut out for us.,TXT_RANDOM_REBEL_06,,,,"Neusínej na vavřínech, stále máme před sebou hodně práce.",Lad være med at sætte dig for godt til rette. Vi har stadig vores arbejde foran os.,"Werd nicht leichtsinnig, es gibt noch eine Menge zu tun.",,,No te pongas muy cómodo. Ya tenemos nuestro propio trabajo asignado a cada uno.,,Ei parane levätä laakereillaan; meillä on vielä paljon työsarkaa edessämme.,Ne vous reposez pas sur vos lauriers. Du travail nous attend encore.,Annyira azért ne érezd otthon magad. Nekünk még van némi munka kiosztva idelenn.,Non prendertela troppo comoda. Abbiamo ancora un sacco di lavoro da fare.,"あまり気楽でいるな。 -我々にはまだやるべき事があるんだ。",게으름 피울 생각하지는 마. 아직 일이 잘 안 풀렸으니까.,Maak het je niet al te comfortabel. We hebben nog steeds werk voor de boeg.,Ikke bli for komfortabel. Vi har fortsatt en jobb å gjøre.,Nie czuj się zbyt komfortowo. Wciąż mamy przed sobą zadanie do wykonania.,Não fique muito confortável. Ainda temos trabalho a fazer.,,Nu te fă prea comfortabil. Încă mai avem treabă de făcut.,Не расслабляйся. У нас по-прежнему хватает дел.,,Fazla rahatlamayın. İşimiz hala bizim için biçilmiş kaftan. +奴等の基地に潜り込んで、倒すんだ。","감사드립니다! 블랙버드가 당신을 위해 계속 안내를 할 것입니다. 같이 행동한다면 오더의 흉측한 비밀들을 밝혀내고, 그들의 잔혹한 존재들을 응징할 수 있을 겁니다. 우리들의 이해심 밑에 공포를 인도하는 그들의 숨겨진 존재가 있죠. 그곳으로 들어가서, 물리치세요.",Goed. Blackbird zal je gids blijven. Ze heeft je een behoorlijke glans gegeven. Samen moeten jullie de geheimen van de Orde en hun onmenselijke dienaren ontrafelen. Er is een aanwezigheid die net buiten ons begrip schuilt en die hun angst leidt. Ga naar binnen en neem ze mee naar beneden.,Bra. Blackbird vil fortsette å være din guide. Hun har blitt ganske betatt av deg. Sammen må dere avsløre hemmelighetene til Ordenen og deres umenneskelige tjenere. Det er en tilstedeværelse som lurer like utenfor vår forståelse som styrer deres terror. Gå inn og ta dem.,"Dobrze. Blackbird nadal będzie twoim przewodnikiem. Polubiła cię. Razem musicie odkryć tajemnice Zakonu i ich nieludzkich sług. Istnieje obecność, która czai się poza naszym rozumieniem, która kieruje ich terrorem. Dostań się do środka i zdejmij ich.","Ótimo. Blackbird continuará sendo a sua guia. Ela parece que vai com a sua cara. Juntos, vocês desvendarão os segredos da Ordem e seus discípulos desumanos. Há uma presença que está além do nosso entendimento que guia todo esse terror. Vá infiltrar a Ordem e elimine-os.",,"Bun. Blackbird va continua să fie ghidul tău. A început să ia un interes asupra ta. Împreună, va trebui să aflați secretele Ordinului și servitorilor lor inumani. Există o prezență care se târăște la marginea capacității noastre de înțelegere care le ghidează teroarea. Infiltrează-te și pune-i la pământ.",Хорошо. «Чёрный дрозд» останется твоим проводником. Она тебе несколько симпатизирует. Вместе вы раскроете секреты Ордена и его бесчеловечных слуг. За этим ужасом стоит нечто лежащее далеко за пределами нашего понимания. Проникни на их территорию и ударь по ним как следует!,,Jag är med dig. Blackbird kommer att fortsätta att vara din guide. Hon har blivit ganska förtjust i dig. Tillsammans måste ni avslöja hemligheterna om Orden och deras omänskliga tjänare. Det finns en närvaro som lurar utanför vår förståelse och som styr deras terror. Ta dig in och ta ner dem.,Güzel. Karatavuk rehberin olmaya devam edecek. Senden oldukça hoşlandı. Birlikte Tarikat'ın ve insanlık dışı hizmetkârlarının sırlarını açığa çıkarmalısınız. Anlayışımızın hemen dışında gizlenen ve onların terörüne rehberlik eden bir varlık var. İçeri gir ve onları alaşağı et. +Let me at 'em!,TXT_RPLY0_SCRIPT34_D30320_LETME,〃,,,Pusť mě na ně!,Lad mig tage dem!,Lass mich das nur machen.,,Mi faros tion!,¡Voy a por ellos!,¡Voy por ellos!,Päästä minut heidän kimppuunsa!,Laissez moi m'en occuper!,Szétcincálom mind!,Lasciali a me!,任せろ!,저만 믿으세요!,Laat me naar ze toe!,La meg ta dem!,Pozwól mi na nich!,Pode deixar!,,Lasă-mă să pun mâna pe ei!,Я им покажу!,,Låt mig ta dem!,Bırakın ben halledeyim! +That's the spirit.,TXT_RYES0_SCRIPT34_D30320_THATS,〃,,,Tak se mi to líbí.,Sådan er ånden.,Das ist die richtige Einstellung.,,Tiu estas la spirito.,Ese es el espíritu.,,Niin sitä pitää.,J'aime entendre ça.,Ez a beszéd!,Questo è lo spirito giusto.,良い心掛けだ。,좋은 마음가짐입니다.,Dat is de geest.,Sånn skal det låte.,To jest duch.,Esse é o espírito.,,Ăsta e spiritul.,Правильный настрой.,,Så ska det låta.,İşte ruh bu. +Welcome friend!,TXT_DLG_SCRIPT34_D31836_WELCO,〃,,,"Vítej, příteli!","Velkommen, min ven!","Wilkommen, Freund.",,"Bonvenon, amiko!","¡Bienvenido, amigo!",,"Tervetuloa, ystävä!","Bievenue, notre ami!",Üdvözöllek barátom.,Benvenuto amico!,よく来た、同志!,"어서오세요, 친구여!",Welkom vriend!,"Velkommen, min venn!",Witaj przyjacielu!,"Seja bem-vindo, amigo!",,Bun-venit prietene!,"Добро пожаловать, друг!",,"Välkommen, min vän!",Hoş geldin dostum! +,,Random dialogue,,,,,,,,,,,,,,,,,,,,,,,,, +Please don't hurt me.,TXT_RANDOM_PEASANT_01,,,,"Neubližuj mi, prosím.",Du må ikke gøre mig noget.,Bitte tu mir nicht weh.,,Bonvolu ne vundi min.,"No me hagas nada, por favor.",,"Pyydän, älä vahingoita minua.","S'il vous plaît, laissez-moi tranquille.",Kérlek ne bánts!,"Ti prego, non farmi del male.",私を傷つけないでくれ。,목숨만은 살려줘.,Doe me alsjeblieft geen pijn.,"Vær så snill, ikke skad meg.","Proszę, nie rób mi krzywdy.","Por favor, não me machuque.",,Te rog nu mă răni.,"Пожалуйста, не трогай меня.",,"Snälla, gör mig inte illa.",Lütfen bana zarar verme. +"If you're looking to hurt me, I'm not really worth the effort.",TXT_RANDOM_PEASANT_02,,,,"Jestli mi chceš ublížit, fakt za to nestojím.","Hvis du er ude på at såre mig, er jeg ikke rigtig besværet værd.","Falls du mir was antun willst, ich bin den Aufwand nicht wert.",,"Se vi intencas vundi min, vi vere gajnos nenion.","Si estás tratando de hacerme algo, no valdrá la pena, la verdad.","Si estás tratando de hacerme algo, no va a valer la pena, la verdad.","Jos aikomuksenasi on vahingoittaa minua, en todellakaan ole sen vaivan väärti.","Si vous cherchez à me faire mal, Je n'en mérite pas l'effort.","Ha bántani akarsz, nem éri meg a fáradozást.","Se hai intenzione di farmi del male, ti assicuro che non ne valgo la pena.","もしお前が私に暴力を振るいたいなら間違いだ、 +私を殴る価値はないから。","날 괴롭히려고 여기까지 왔다면, 넌 헛수고를 한 거야.","Als je me pijn wilt doen, ben ik de moeite niet echt waard.","Hvis du er ute etter å skade meg, er jeg ikke verdt det.","Jeśli chcesz mnie skrzywdzić, nie jestem wart wysiłku.","Se pretende me machucar, te digo que não valerá a pena.",,"Dacă vrei să mă rănești, nu merit efortul.","Если ты хочешь ударить меня, то я не стою твоих усилий.",,Om du är ute efter att skada mig är jag inte värd besväret.,"Eğer beni incitmek istiyorsan, bu çabaya değmem." +I don't know anything.,TXT_RANDOM_PEASANT_03,,,,O ničem nevím.,Jeg ved ikke noget.,Ich weiß nichts.,,Mi scias nenion.,No sé nada.,,En tiedä mitään.,Je ne sais rien.,Én semmit sem tudok.,Non so niente.,私は何も知らないんだ。,난 정말 아무것도 몰라.,Ik weet niets.,Jeg vet ingenting.,Nic nie wiem.,Eu não sei de nada.,,Nu știu nimic.,Я ничего не знаю.,,Jag vet ingenting.,Ben bir şey bilmiyorum. +Go away or I'll call the guards!,TXT_RANDOM_PEASANT_04,,,,"Jdi pryč, nebo zavolám stráže!","Gå væk, eller jeg tilkalder vagterne!",Hau ab oder ich rufe die Wachen!,,Foriĝu aŭ mi vokos la gardistojn!,¡Vete o llamo a los guardias!,,"Mene pois, tai kutsun vartijat!",Allez vous en ou j'appelle les gardes!,"Tűnj innen, vagy hívom az őröket!",Vattene o chiamo le guardie!,離れろ、さもなくば衛兵を呼ぶぞ!,경비병 부르기 전에 얼른 사라져!,Ga weg of ik roep de bewakers!,"Gå vekk, ellers tilkaller jeg vaktene!",Odejdź albo zawołam strażników!,Vá embora antes que eu chame os guardas!,,Pleacă sau voi chema gardienii!,"Уходи, или я позову стражу!",,Gå härifrån eller så kallar jag på vakterna!,Git buradan yoksa muhafızları çağırırım! +I wish sometimes that all these rebels would just learn their place and stop this nonsense.,TXT_RANDOM_PEASANT_05,,,,"Občas si přeju, aby si ti rebelové uvědomili, kde jsou, a skončili s těmi svými nesmysly.","Nogle gange ville jeg ønske, at alle disse oprørere bare ville lære deres plads og stoppe dette nonsens.","Manchmal wünsche ich mir, dass diese Rebellen ihren Unsinn stoppen würden.",,"Mi iufoje deziras, ke ĉiu ribelanto simple lernu vivi kaj haltigu sian absurdon.",A veces deseo que todos los rebeldes simplemente aprendan a vivir y que paren con sus estupideces.,,Kunpa joskus kaikki nämä kapinalliset vain oppisivat paikkansa ja lopettaisivat tämän mielettömyyden.,"Je voudrais qu'a un moment, ces rebelles apprennent quelle est leur place et arrètent cette idiotie.","Néha azt kívánom, hogy ezek a lázadók bár megtanulnák, hol a helyük, és felhagynának ezzel az eszeveszett dologgal.",A volte vorrei solo che i ribelli imparassero a stare al loro posto e la smettessero con tutte queste follie.,"反乱軍がこんな出鱈目な状態をひっくり返すのを +切に願うよ。",저 저항군들이 가망이 없다는 걸 빨리 눈치챘으면 정말 좋겠군.,Ik wou soms dat al die rebellen gewoon hun plaats zouden leren kennen en deze onzin zouden stoppen.,Noen ganger skulle jeg ønske at alle disse opprørerne kunne lære seg sin plass og slutte med dette tullet.,"Chciałbym czasem, żeby ci wszyscy buntownicy nauczyli się, gdzie ich miejsce i skończyli z tymi bzdurami.",Às vezes eu queria que esses rebeldes cuidassem de suas próprias vidas e parassem com esse absurdo.,,Uneori îmi doresc ca rebelii ăștia să își vadă de treaba lor și să înceteze cu tâmpeniile.,"Иногда мне хочется, чтобы все эти повстанцы просто поняли своё место и прекратили эту пустую возню.",,Jag önskar ibland att alla dessa rebeller bara skulle lära sig sin plats och sluta med detta nonsens.,Bazen tüm bu isyancıların hadlerini bilmelerini ve bu saçmalığa bir son vermelerini diliyorum. +"Just leave me alone, OK?",TXT_RANDOM_PEASANT_06,,,,"Prostě mě nech být, jasný?","Bare lad mig være i fred, okay?","Lass mich bitte in Ruhe, ok?",,"Lasu min sola, ĉu?","Déjame en paz, ¿vale?","Déjame en paz, ¿sí?","Jätä minut vain rauhaan, onko selvä?","Laissez moi seul, OK?","Csak hagyj magamra, jó?","Lasciami in pace e basta, OK?",私に構わないでくれよ、頼むぞ?,그냥 날 내버려 둬. 부탁이야.,"Laat me gewoon met rust, oké?","Bare la meg være i fred, OK?","Zostaw mnie w spokoju, dobrze?","Apenas me deixe em paz, ok?",,"Doar lasă-mă în pace, OK?","Просто оставь меня в покое, хорошо?",,"Lämna mig bara ifred, okej?","Beni yalnız bırak, tamam mı?" +"I'm not sure, but sometimes I think that I know some of the acolytes.",TXT_RANDOM_PEASANT_07,,,,"Nejsem si jistý, ale občas se mi zdá, že znám některé z akolytů.","Jeg er ikke sikker, men nogle gange tror jeg, at jeg kender nogle af akolytterne.","Ich bin nicht ganz sicher, aber manchmal kommt es mir vor, als kenne ich diese Ministranten.",,"Mi ne estas certa, sed mi iufoje sentas, ke mi konas iujn el la akolitoj.","No estoy seguro, pero a veces siento que ya conozco a algunos de los acólitos.",,"En ole varma, mutta toisinaan jotkut akoluutit vaikuttavat tutuilta.","Je ne suis pas sûr, mais quelque fois je pense reconnaître certains des acolytes.","Nem vagyok benne bizonyos, de néha mintha ismerném némelyik ministránst.","Non ne sono sicuro, ma volte mi sembra di conoscere alcuni degli accoliti.","何か、アコライトの中で見覚えのある顔したのが +いたんだが。","자세히는 모르지만, 내가 본 아콜라이트들 중에 아는 사람이 있는 것 같아.","Ik weet het niet zeker, maar soms denk ik dat ik sommige van de acolieten ken.","Jeg er ikke sikker, men noen ganger tror jeg at jeg kjenner noen av akolyttene.","Nie jestem pewien, ale czasem wydaje mi się, że znam niektórych akolitów.","Eu não tenho bem certeza, mas acho que conheco alguns dos acólitos.",,"Nu sunt sigur, dar uneori am impresia că cunosc pe unii acoliți.","Я не уверен, но порой мне кажется, что я узнаю некоторых служителей.",,"Jag är inte säker, men ibland tror jag att jag känner några av akoliterna.",Emin değilim ama bazen bazı yardımcıları tanıdığımı düşünüyorum. +The Order's got everything around here pretty well locked up tight.,TXT_RANDOM_PEASANT_08,,,,Řád to tu má všechno pod hodně přísným dohledem.,Ordenen har alting her omkring temmelig godt låst godt inde.,Der Orden hat hier alles ziemlich gut unter Kontrolle.,,La Ordeno havas ĉion tie ĉi sufiĉe bone blokita.,La Orden tiene todo por aquí fuertemente bloqueado.,,Veljeskunnalla on täällä aika lailla kaikki tiukassa otteessaan.,L'ordre maintient la sûreté aux alentours.,A Rend mindent jól elzárt előlünk.,L'Ordine si è dato parecchio da fare per chiudere e sbarrare un po' tutto qui in giro.,オーダー達はここいらを厳しく取り締まってる。,오더가 치안유지도 그렇고 단속을 아주 실감 나게 잘하던데?,De Orde heeft alles hier in de buurt vrij goed afgesloten.,Ordenen har alt her ganske godt låst.,Zakon ma tu wszystko pod ścisłą kontrolą.,A Ordem mantém tudo trancado a sete chaves.,,Ordinul a încuiat cam tot ce se poate pe aici.,Орден держит тут всё под замком.,,Ordern har allting här omkring ganska väl låst in ordentligt.,Tarikat buradaki her şeyi oldukça iyi kilitlemiş. +There's no way that this is just a security force.,TXT_RANDOM_PEASANT_09,,,,"Není možné, aby tohle byly jen bezpečnostní složky.","Det er umuligt, at det bare er en sikkerhedsstyrke.",Das sind niemals nur Sicherheitskräfte.,,"Ne estas maniero, ke ĉi tio estas nur «sekureca forto».",No hay manera de que esto sea solo una fuerza de seguridad.,,Ei tämä mitenkään voi olla pelkkä turvallisuusjoukko.,Ca ne peut pas être juste une escouade de sécurité...,Na ez már tutira nem lehet csak a biztonsági szolgálat.,"E' impossibile che questa sia solo una ""forza di sicurezza"".",お前がただの警備兵なんてことはなさそうだな。,저 녀석들은 단순히 치안을 유지하기 위해 온 게 아니라고 생각해.,Er is geen sprake van dat dit gewoon een veiligheidsdienst is.,Det er ikke mulig at dette bare er en sikkerhetsstyrke.,"Nie ma mowy, żeby to była tylko ochrona.",Não tem como isso ser apenas um força de segurança.,,Sub nicio formă nu e asta doar o forță de securitate.,Без разрешения стражей порядка и шагу ступить нельзя.,,Det är inte möjligt att det här bara är en säkerhetsstyrka.,Bunun sadece bir güvenlik gücü olmasına imkan yok. +I've heard that the Order is really nervous about the Front's actions around here.,TXT_RANDOM_PEASANT_10,,,,"Slyšel jsem, že je Řád prý dost nervózní z toho, co tu Fronta dělá.","Jeg har hørt, at Ordenen er meget nervøs over Frontens handlinger her.","Ich habe gehört, dass der Orden sehr beunruhigt über die Aktionen der Front ist.",,"Mi aŭdis, ke La Ordeno estas tre nervoza pro la agoj de la ĉirkaŭa Fronto.",He oído que La Orden está realmente nerviosa por las acciones del Frente en los alrededores.,,Veljeskunta on kuulemma tosi huolissaan Rintaman toimista täällä.,J'ai entendu dire que l'ordre était sur les nerfs à cause des actions du front.,Úgy hírlik A Rend nagyon ideges a Front munkálkodásai miatt mostanság.,Ho sentito che l'Ordine è parecchio nervoso riguardo le azioni del Fronte nei dintorni.,"私はオーダーがこの辺での反乱軍の行動を +本当に厄介がってると聞いたぞ。",오더가 프론트 저항군의 공작에 정말 불안해하고 있더라고.,Ik heb gehoord dat de Orde echt nerveus is over de acties van het Front hier in de buurt.,Jeg har hørt at Ordenen er veldig nervøs for Frontens handlinger her.,"Słyszałem, że Zakon jest bardzo zdenerwowany działaniami Frontu w tym miejscu.",Ouvi falar que a Ordem anda bem nervosa por causa das ações da Frente por aqui.,,Am auzit că Ordinul e destul de stresat dorită acțiunilor Frontului pe-aici.,"Я слыхал, что Орден серьёзно обеспокоен действиями повстанцев в этом районе.",,Jag har hört att Orden är riktigt nervös över Fronts agerande här.,Tarikat'ın Cephe'nin buradaki eylemleri konusunda gerçekten gergin olduğunu duydum. +There's no way the Order will stand against us.,TXT_RANDOM_REBEL_01,,,,Řád se nám v žádném případě nemůže postavit.,Ordenen vil på ingen måde stå imod os.,Niemals wird sich der Orden gegen uns stellen!,,La Ordeno neniel povos rezisti al ni.,No hay forma de que La Orden aguante contra nosotros.,,Veljeskunta ei voi millään kestää meitä vastaan.,L'ordre n'a aucune chance contre nous.,A Rend labdába sem rúghat ellenünk!,Non è possibile che l'Ordine possa mettersi contro di noi.,オーダーが私達に立ち向かえるはずはない。,오더 녀석들이 우리를 이길 가능성은 전혀 없어.,De Orde zal op geen enkele manier tegen ons ingaan.,Det er ingen sjanse for at Ordenen vil gå imot oss.,"Nie ma mowy, by Zakon stanął przeciwko nam.",Nao ha como a Ordem ficar contra a gente.,,Nicio șansă ca Ordinul să ni se opună.,Ордену никак не устоять против нас.,,Det finns inte en chans att Orden kommer att stå emot oss.,Düzen'in bize karşı durmasına imkan yok. +We're almost ready to strike. Macil's plans are falling in place.,TXT_RANDOM_REBEL_02,,,,Jsme téměř připraveni zaútočit. Macilovy plány do sebe začínají zapadat.,Vi er næsten klar til at slå til. Macils planer er ved at falde på plads.,Wir sind zum großen Schlag bereit. Macils Plane werden bald umgesetzt.,,Ni estas preskaŭ pretaj ekataki. La planoj de Macil sukcesas perfekte.,Estamos casi listos para atacar. Los planes de Macil están saliendo a la perfección.,,Olemme melkein valmiit hyökkäämään. Macilin suunnitelmat loksahtavat paikalleen.,Nous sommes presque prêts à agir. Les plans de Macil se déroulent comme prévu.,"Már majdnem készen állunk, hogy lecsapjunk. Macil tervei kezdenek bejönni.",Siamo quasi pronti a colpire. I piani di Macil stanno andando lisci come l'olio.,"攻撃の準備は殆ど整った。 +マシルの計画は所定の位置に下す。",반격할 준비가 거의 다 돼가고 있어. 마실 사령관님의 계획이 잘 진행되고 있으니까.,We zijn bijna klaar om toe te slaan. Macil's plannen vallen op zijn plaats.,Vi er nesten klare til å slå til. Macils planer faller på plass.,Jesteśmy prawie gotowi do uderzenia. Plany Macila są coraz lepsze.,Estamos quase prontos para o ataque. Os planos de Macil estão fazendo efeito.,,Suntem aproape gata să dăm lovitura. Planurile lui Macil încep să se lege.,Мы почти готовы атаковать. Планы Мэйсила становятся ясны.,,Vi är nästan redo att slå till. Macils planer faller på plats.,Saldırmaya neredeyse hazırız. Macil'in planları yerine oturuyor. +"We're all behind you, don't worry.",TXT_RANDOM_REBEL_03,,,,"Všichni stojíme za tebou, neboj.","Vi står alle bag dig, bare rolig.","Wir stehen zu dir, keine Sorge.",,"Ni gardos vin dorse, vi do estu trankvila.","Nosotros te cubrimos la espalda, así que tranquilo.",,"Olemme kaikki tukenasi, älä huoli.","On couvre tes arrières, t'inquiète pas.","Mind itt vagyunk mögötted, ne aggódj!","Non preoccuparti, noi tutti ti copriamo le spalle.",後ろは見ているぞ、気にするな。,걱정 마. 무슨 일이 있어도 우리가 지켜줄게!,"We staan allemaal achter je, maak je geen zorgen.","Vi står bak deg, ikke vær redd.","Wszyscy jesteśmy za tobą, nie martw się.","Estamos todos te protegendo, não se preocupe.",,"Suntem toți în spatele tău, nu te teme.",Не беспокойся. Мы сразу за тобой.,,"Vi står alla bakom dig, oroa dig inte.","Hepimiz arkandayız, merak etme." +Don't get too close to any of those big robots. They'll melt you down for scrap!,TXT_RANDOM_REBEL_04,,,,Nepřibližuj se k těm velkým robotům. Usmaží tě na kaši!,Kom ikke for tæt på nogen af de store robotter. De vil smelte dig ned til skrot!,Komm diesen großen Robotern nicht zu nahe. Die schmelzen dich zu Schrott ein.,,Ne proksimiĝu tiel multe al tiuj robotegoj. Ili povus disigi vin je rubo!,No te acerques tanto a uno de esos robots grandes. ¡Podrían convertirte en chatarra!,,Älä mene liian lähelle mitään noista isoista roboteista. Ne sulattavat sinut kuonaksi.,Ne vous approchez pas trop des gros robots. Ils vous brûleront jusqu'à l'os!,Azokhoz a nagy robotokhoz ne nagyon menj közel. Felaprítanak tüzifának!,Non avvicinarti troppo a uno di quei grossi robot. Ti ridurrebbero in rottami!,"デカブツには近づくなよ。スクラップみたいに +踏みつぶされるぞ!",저 커다란 로봇들에게 다가갈 생각은 하지 마. 너를 완전 발끝까지 녹여버릴 거라고.,Kom niet te dicht bij een van die grote robots. Ze zullen je laten smelten voor de schroothoop!,Ikke kom for nær noen av de store robotene. De smelter deg om til skrap!,Nie zbliżaj się zbytnio do tych wielkich robotów. Przetopią cię na złom!,Nem pense em ficar perto daqueles robôs. Vão te transformar em ferro velho num instante!,,Nu te apropia de roboți. Te vor topii!,Держись подальше от этих больших роботов. Они и мокрого места от тебя не оставят!,,Kom inte för nära någon av de stora robotarna. De kommer att smälta ner dig till skrot!,O büyük robotlara fazla yaklaşma. Sizi hurda için eritirler! +"The day of our glory will soon come, and those who oppose us will be crushed!",TXT_RANDOM_REBEL_05,,,,"Naše dny slávy brzy nadejdou a ti, kdo se nám postaví, budou rozdrceni!","Vores storhedsdag vil snart komme, og de, der modsætter sig os, vil blive knust!","Der Tag des Triumphes ist nahe, und die, die gegen uns sind, werden vernichtet.",,Nia glora tago baldaŭ alvenos kaj niaj kontraŭstarantoj estos detruitaj!,¡El día de nuestra gloria llegará pronto y aquellos que se opusieron a nosotros serán destruidos!,¡El día de nuestra gloria va a llegar pronto y aquellos que se opusieron a nosotros van a ser destruidos!,"Kunnian päivämme häämöttää, ja kaikki meitä vastustavat vihittäkööt tuhon omiksi!","Le jour de gloire arrivera bientôt, et ceux qui s'opposeront a nous seront écrasés!","Dicsőségünk napja hamarosan eljön, és akik ellenünk szegülnek, elkárhoznak.","Il giorno della nostra gloria verrà presto, e quelli che si oppongono a noi verranno schiacciati!","栄光の日は我々に訪れる、 +そして反逆する者達は潰す!",영광스러운 새벽이 오고있어. 우리를 탄압한 녀석들에게 징벌을 내릴 새벽이!,"De dag van onze glorie zal snel komen, en degenen die zich tegen ons verzetten zullen worden verpletterd!","Dagen for vår herlighet vil snart komme, og de som motsetter seg oss vil bli knust!","Dzień naszej chwały wkrótce nadejdzie, a ci, którzy się nam sprzeciwią, zostaną zmiażdżeni!","O dia de nossa glória chegará, e aqueles que se opuserem contra nós serão destruídos!",,Ziua în care noi vom avea gloria va veni curând și toti vor fi striviți.,Близок день нашего триумфа. Скоро наши враги будут уничтожены!,,"Vår härlighets dag kommer snart, och de som motsätter sig oss kommer att krossas!",Zafer günümüz yakında gelecek ve bize karşı çıkanlar ezilecek! +Don't get too comfortable. We've still got our work cut out for us.,TXT_RANDOM_REBEL_06,,,,"Neusínej na vavřínech, stále máme před sebou hodně práce.",Lad være med at sætte dig for godt til rette. Vi har stadig vores arbejde foran os.,"Werd nicht leichtsinnig, es gibt noch eine Menge zu tun.",,"Ne agu tre pigre, ni ankoraŭ havas multe da laboro.","No te pongas muy cómodo, que aún queda un montón por hacer.",,Ei parane levätä laakereillaan; meillä on vielä paljon työsarkaa edessämme.,Ne vous reposez pas sur vos lauriers. Du travail nous attend encore.,Annyira azért ne érezd otthon magad. Nekünk még van némi munka kiosztva idelenn.,Non prendertela troppo comoda. Abbiamo ancora un sacco di lavoro da fare.,"あまり気楽でいるな。 +我々にはまだやるべき事があるんだ。",게으름 피울 생각하지는 마. 아직 일이 잘 안 풀렸으니까.,Maak het je niet al te comfortabel. We hebben nog steeds werk voor de boeg.,Ikke bli for komfortabel. Vi har fortsatt en jobb å gjøre.,Nie czuj się zbyt komfortowo. Wciąż mamy przed sobą zadanie do wykonania.,Não fique muito confortável. Ainda temos trabalho a fazer.,,Nu te fă prea comfortabil. Încă mai avem treabă de făcut.,Не расслабляйся. У нас по-прежнему хватает дел.,,Gör det inte för bekvämt. Vi har fortfarande vårt arbete framför oss.,Fazla rahatlamayın. İşimiz hala bizim için biçilmiş kaftan. Macil says that you're the new hope. Bear that in mind.,TXT_RANDOM_REBEL_07,,,,"Macil říká, že jsi naše nová naděje. Pamatuj na to.","Macil siger, at du er det nye håb. Husk det.",Macil nennt dich unsere neue Hoffnung. Vergiss das nicht.,,"Macil diras, ke vi estas la nova espero. Memoru tion.",Macil dice que eres la nueva esperanza. Ten eso en mente.,,Macil sanoo sinun olevan uusi toivomme. Pidä se mielessäsi.,Macil nous dit que tu es notre nouvel espoir. Garde ça à l'esprit.,Macil szerint te vagy az új reményünk. Ezt sose feledd!,Macil dice che tu sei la nuova speranza. Tienilo a mente.,"マシルは貴方が新しい希望だと言っている。 -心に留めておいてくれ。",마실 사령관님이 말하기를 네가 우리들의 유일한 희망이래. 명심해 둬.,Macil zegt dat jij de nieuwe hoop bent. Houd dat in gedachten.,Macil sier at du er det nye håpet. Husk det.,"Macil mówi, że jesteś nową nadzieją. Pamiętajcie o tym.",Macil disse que você é a nova esperança. Lembre-se disso.,,Macil spune că tu ești speranța. Ține minte asta.,"Мэйсил говорит, что на тебя сейчас вся надежда. Имей это в виду.",,Macil senin yeni umut olduğunu söylüyor. Bunu aklınızdan çıkarmayın. -"Once we've taken these charlatans down, we'll be able to rebuild this world as it should be.",TXT_RANDOM_REBEL_08,,,,"Jakmile sesadíme ty šarlatány, budeme moci znovu vybudovat svět tak, jaký by měl být.","Når vi først har nedlagt disse charlataner, vil vi kunne genopbygge denne verden, som den skal være.","Wenn wir diese Scharlatane entmachtet haben, können wir unsere Welt endlich neu aufbauen.",,,"Una vez que hayamos eliminado a esos charlatanes, podremos reconstruir este mundo como debe ser.","Una vez eliminados esos charlatanes, vamos a poder reconstruir este mundo como debe ser.","Sen jälkeen, kun olemme nujertaneet nämä puoskarit, voimme jälleenrakentaa tämän maailman sellaiseksi kuin pitääkin.","Une fois que nous nous serons débarassés de ces charlatans, nous serons capable de rebâtir le monde tel qu'il devrait être.","Amint lenyomtuk ezeket a sarlatánokat, végre újjáépíthetjük ezt a világot olyanra, amilyennek lennie kéne.","Una volta eliminati questi ciarlatani, potremo ricostruire questo mondo per come dovrebbe essere.","我々が一度こんな酷いハッタリを負かせば、 -世界を本来の状態に建て直せるだろう。","저 허풍쟁이들을 다 물리칠 수만 있다면, 우리가 바랬던 평화로운 세상을 재건할 수 있을 거야.","Als we deze charlatans eenmaal hebben verwijderd, kunnen we deze wereld weer opbouwen zoals het hoort.","Når vi har tatt disse sjarlatanene, kan vi gjenoppbygge verden slik den burde være.","Kiedy obalimy tych szarlatanów, będziemy mogli odbudować ten świat tak, jak powinien być.","Assim que derrubarmos esses charlatões, poderemos reconstruir o mundo do jeito certo.",,"Dupa ce îi vom răpune pe șarlatanii ăștia, vom putea reconstrui lumea în ceea ce trebuie să fie.","Когда мы свергнем этих шарлатанов, то сможем воссоздать этот мир таким, каким он должен быть.",,"Bu şarlatanları alaşağı ettikten sonra, bu dünyayı olması gerektiği gibi yeniden inşa edebileceğiz." -"Remember that you aren't fighting just for yourself, but for everyone here and outside.",TXT_RANDOM_REBEL_09,,,,"Nezapomeň, že nebojuješ jen kvůli sobě, ale kvůli všem tady a tam venku.","Husk, at du ikke kun kæmper for dig selv, men for alle her og udenfor.","Vergiß nicht, dass du nicht nur für dich selbst kämpfst, sondern für alle von uns da draußen.",,,"Recuerda que no estás peleando solo por ti, sino por todos aquí y fuera.","Recuerda que no estás peleando solo por ti, sino por todos aquí y afuera.","Muista, ettet taistele vain itsesi, vaan kaikkien täällä olevien sekä ulkopuolisten puolesta.","Souviens-toi, tu ne te bats pas seulement pour toi, mais pour tous le monde ici et ailleurs.","Ne feledd, nem csak magadért harcolsz, hanem mindnyájunkért idebent, és odakint.","Ricordati che non stai combattendo solo per te stesso, ma per tutti quelli che sono qui e fuori.","貴方は自分自身だけでなく、 -国中の人の為に戦っている事を忘れないでくれよ。",너 혼자 위해서 싸우는 게 아니라 인류를 위해서 싸우고 있다는 걸 잊지 마.,"Onthoud dat je niet alleen voor jezelf vecht, maar voor iedereen hier en daarbuiten.","Husk at du ikke bare kjemper for deg selv, men for alle her og utenfor.","Pamiętaj, że nie walczysz tylko dla siebie, ale dla wszystkich tu i na zewnątrz.","Lembre-se que você não está lutando só por si mesmo, mas por todos nós.",,"Ține minte că nu lupți doar pentru tine, ci pentru toți de aici și de afară.","Помни, ты сражаешься не только за себя, но и за каждого здесь и снаружи.",,"Sadece kendiniz için değil, buradaki ve dışarıdaki herkes için savaştığınızı unutmayın." -"As long as one of us still stands, we will win.",TXT_RANDOM_REBEL_10,,,,"Dokud je alespoň jeden z nás na nohou, vyhrajeme!","Så længe en af os stadig står tilbage, vil vi vinde.","Solange nur einer von uns steht, werden wir gewinnen.",,"Dum iu ajn el ni ankoraŭ povos stari, ni venkos.","Mientras uno de nosotros siga en pie, ganaremos.","Mientras uno de nosotros siga en pie, vamos a ganar.","Niin kauan kuin yksikin meistä vielä seisoo, voitto on meidän.","Aussi longtemps qu'un de nous est vivant, nous vaincrons.","Ha csak egy is marad meg közülünk, nyerni fogunk.","Finché uno di noi rimarrà in piedi, vinceremo.",我々が一人でも立っていれば、それが勝利。,"우리 중 한 명이 남아있는 한, 이길 수 있어.","Zolang één van ons nog staat, zullen we winnen.","Så lenge en av oss fortsatt står, vil vi vinne.","Tak długo jak jeden z nas nadal będzie stał, tak długo będziemy wygrywać.","Enquanto um de nós ainda estiver de pé, teremos chance de vencer.",,"Atâta timp cât unul din noi trăiește, vom triumfa.","Пока хотя бы один из нас ещё дышит, мы непобедимы.",,İçimizden biri ayakta kaldığı sürece kazanacağız. -"Move along, peasant.",TXT_RANDOM_AGUARD_01,,,,"Jdi dál, poddaný.","Gå videre, bonde.","Beweg dich, Bauer!",,"Ne haltu, kampulo.","No te detengas, campesino.",,"Jatka matkaa, maallikko.","Barre-toi, paysan!","Mozgás, paraszt. Egy kettő.","Muoviti, cittadino.",立ち去れ、百姓。,"어서 움직여, 이 자식아.","Ga verder, boer.","Gå videre, bonde.","Ruszaj w drogę, chłopie.","Continue andando, plebeu.",,"Mișcă, sărmanule.","Проходи, рабочий.",,İlerle köylü. -"Follow the true faith, only then will you begin to understand.",TXT_RANDOM_AGUARD_02,,,,"Následuj pravou víru, jen tak začneš chápat.","Følg den sande tro, først da vil du begynde at forstå.",Folge dem wahren Glauben und du wirst verstehen.,,"Sekvu la veran kredon, nur tiel vi ekkomprenos.","Sigue la fe verdadera, solo entonces empezarás a entender.","Sigue la fe verdadera, solo así vas a entender.",Seuraa totista uskoa; vasta silloin alat käsittää.,"Suis la vraie foi, tu commençeras a comprendre.","Csak ha az igaz hitet követed, csakis akkor kezded majd megérteni.","Segui la vera fede, solo allora comincerai a capire.",真の信仰を求めよ、それしか理解に至る道はない。,참된 신앙이야말로 자기 자신을 깨우칠 수 있지.,"Volg het ware geloof, pas dan zul je het begrijpen.","Følg den sanne troen, først da vil du begynne å forstå.","Podążaj za prawdziwą wiarą, tylko wtedy zaczniesz rozumieć.",Siga a verdadeira fé. Só então você começará a entender.,,"Urmează crezul adevărat, doar atunci vei începe să înțelegi.",Следуй истинной вере. Только тогда ты начнёшь понимать.,,"Gerçek inancı takip et, ancak o zaman anlamaya başlarsın." -Only through death can one be truly reborn.,TXT_RANDOM_AGUARD_03,,,,Pouze skrz smrt lze dosáhnout znovuzrození.,Kun gennem døden kan man virkelig blive genfødt.,Nur durch den Tod kann man wirklich wiedergeboren werden.,,Nur per morto oni povas vere renaskiĝi.,Solo a través de la muerte uno puede realmente renacer.,,Vain kuoleman kautta voi totisesti uudestisyntyä.,C'est seulement a travers la mort que quelqu'un peut renaître.,Csak a halál útján lehet igazán újjászületni.,Solo attraverso la morte uno può rinascere per davvero.,人が真の意味で生まれ変われる方法は、死のみだ,죽음을 통해서만이 진정하게 환생할 수 있는 거다.,Alleen door de dood kan men echt herboren worden.,Bare gjennom døden kan man virkelig bli gjenfødt.,Tylko przez śmierć można się naprawdę odrodzić.,Somente através da morte que alguem poderá renascer de verdade.,,Doar prin moarte poate cineva să fie renăscut cu adevărat.,Истинное перерождение возможно только через смерть.,,İnsan ancak ölümle gerçekten yeniden doğabilir. -I'm not interested in your useless drivel.,TXT_RANDOM_AGUARD_04,,,,Nezajímají mě tvoje žvásty.,Jeg er ikke interesseret i dit ubrugelige sludder.,Dein nutzloses Geschwafel interessiert mich nicht.,,Ne interesas min aŭdi viajn sensencaĵojn.,No me interesa tu charlatanería.,No me interesa oír tus estupideces.,Joutava hölynpölysi ei minua kiinnosta.,Je ne suis pas intéressé par tes idioties inutiles.,Nem érdekel az értelmetlen hablatyolásod.,Non sono interessato alle tue ciance inutili.,お前の無益な戯言なぞ興味は無い。,네 잡담 따위는 듣고 싶지 않아.,Ik ben niet geïnteresseerd in je nutteloze gewauwel.,Jeg er ikke interessert i det unyttige vrøvlet ditt.,Nie interesują mnie twoje bezużyteczne brednie.,Não estou interessado em ouvir as suas bobagens inúteis.,,Nu sunt interesat de lipsa ta de sens.,Мне неинтересна твоя пустая болтовня.,,İşe yaramaz saçmalıklarınla ilgilenmiyorum. -If I had wanted to talk to you I would have told you so.,TXT_RANDOM_AGUARD_05,,,,"Kdybych s tebou chtěl mluvit, nařídil bych ti to.","Hvis jeg havde ønsket at tale med dig, ville jeg have sagt det til dig.","Wenn ich mich mit dir unterhalten wollte, hätte ich dir das gesagt.",,"Se mi volus paroli kun vi, mi unue dirus tion al vi.",Si quisiera hablar contigo te lo hubiera dicho.,,"Jos olisin halunnut puhua kanssasi, olisin sen sinulle ilmaissut.",Si j'avais voulu te parler je te l'aurais dit.,"Ha beszélni akartam volna veled, azt mondtam volna.","Se avessi voluto parlarti, te lo avrei detto.",話があったらこちらからする。,대화하고 싶었으면 내가 먼저 말을 걸었겠지. 안 그래?,"Als ik met je had willen praten, had ik je dat gezegd.","Hadde jeg villet snakke med deg, hadde jeg sagt det.","Gdybym chciał z tobą rozmawiać, powiedziałbym ci to.","Se eu quisesse falar com você, eu teria te dito.",,Dacă voiam să vorbim ți-aș fi spus.,"Если бы я хотел поговорить с тобой, то сказал бы об этом.",,"Seninle konuşmak isteseydim, bunu sana söylerdim." -Go and annoy someone else!,TXT_RANDOM_AGUARD_06,,,,Jdi otravovat někoho jiného!,Gå ud og irriter en anden!,Bitte nerve jemand anderen.,,Ĝenu aliulon!,¡Ve a molestar a otro!,,Mene ärsyttämään jotakuta toista!,Va ennuyer quelqu'un d'autre!,Menj és idegesíts valaki mást!,Vai a scocciare qualcun altro!,あまりイライラさせるな!,귀찮게 하지 말고 가서 딴 녀석이랑 놀아!,Ga iemand anders irriteren!,Gå og plag noen andre!,Idź i denerwuj kogoś innego!,Vá incomodar outra pessoa!,,Du-te și enervează pe altul.,Иди и надоедай кому-нибудь другому!,,Git ve başkasını rahatsız et! -Keep moving!,TXT_RANDOM_AGUARD_07,,,,Nezastavuj se!,Fortsæt med at bevæge dig!,Beweg dich!,,Plue piediru!,¡Sigue caminando!,,Ala laputtaa!,Bouge!,Mozgás!,Continua a muoverti!,立ち去れ!,여어 움직여라!,Blijf in beweging!,Gå videre!,Ruszaj się!,Continue andando!,,Continuă să mergi!,Иди куда шёл!,,Yürümeye devam et! -"If the alarm goes off, just stay out of our way!",TXT_RANDOM_AGUARD_08,,,,"Jestli je vyhlášen poplach, jdi nám z cesty!","Hvis alarmen går i gang, så hold dig bare væk fra os!","Wenn der Alarm losgeht, steh uns nicht im Weg!",,,"¡Si la alarma se activa, solo quítate de nuestro camino!",,"Jos hälytys laukeaa, pysy vain pois meidät tieltämme!","Si l'alarme s'enclenche, reste en dehors de notre chemin!","Ha beindul a riasztó, csak ne állj az utunkba.","Se scatta l'allarme, stattene fuori dai piedi!",警報を鳴らされたくないなら、邪魔をするな!,"만약 알람이 작동된다면, 기도하고 도망치기나 해!","Als het alarm afgaat, blijf dan gewoon uit de weg!","Hvis alarmen går, bare hold deg unna oss!","Jeśli włączy się alarm, po prostu zejdź nam z drogi!","Se o alarme disparar, não fique no nosso caminho!",,"Dacă alarma e declanșată, pur și simplu nu ne sta în cale.","Если поднимется тревога, не попадайся нам под ноги!",,"Alarm çalarsa, yolumuzdan çekilin!" -The Order will cleanse the world and usher it into the new era.,TXT_RANDOM_AGUARD_09,,,,Řád pročistí náš svět a navede ho do nového věku.,Ordenen vil rense verden og føre den ind i den nye æra.,Der Orden wird die Welt läutern und in eine neue Ära führen.,,,La Orden limpiará el mundo y marcará el inicio de la nueva era.,La Orden va a limpiar el mundo y marcar el inicio de la nueva era.,Veljeskunta puhdistaa tämän maailman ja johdattaa sen uudelle aikakaudelle.,L'ordre nettoira le monde et le conduira dans une nouvelle ère.,"A Rend megtisztítja a világot, és egy új korszakba vezeti.",L'ordine ripulirà questo mondo e lo porterà verso una nuova era.,"オーダーは世界を浄化し、 +心に留めておいてくれ。",마실 사령관님이 말하기를 네가 우리들의 유일한 희망이래. 명심해 둬.,Macil zegt dat jij de nieuwe hoop bent. Houd dat in gedachten.,Macil sier at du er det nye håpet. Husk det.,"Macil mówi, że jesteś nową nadzieją. Pamiętajcie o tym.",Macil disse que você é a nova esperança. Lembre-se disso.,,Macil spune că tu ești speranța. Ține minte asta.,"Мэйсил говорит, что на тебя сейчас вся надежда. Имей это в виду.",,Macil säger att du är det nya hoppet. Tänk på det.,Macil senin yeni umut olduğunu söylüyor. Bunu aklınızdan çıkarmayın. +"Once we've taken these charlatans down, we'll be able to rebuild this world as it should be.",TXT_RANDOM_REBEL_08,,,,"Jakmile sesadíme ty šarlatány, budeme moci znovu vybudovat svět tak, jaký by měl být.","Når vi først har nedlagt disse charlataner, vil vi kunne genopbygge denne verden, som den skal være.","Wenn wir diese Scharlatane entmachtet haben, können wir unsere Welt endlich neu aufbauen.",,"Foriginte tiujn ridindulojn, ni povos ĝuste rekonstrui ĉi tiun mondon.","Una vez eliminados esos charlatanes, podremos reconstruir este mundo como debe ser.","Una vez eliminados esos charlatanes, vamos a poder reconstruir este mundo como debe ser.","Sen jälkeen, kun olemme nujertaneet nämä puoskarit, voimme jälleenrakentaa tämän maailman sellaiseksi kuin pitääkin.","Une fois que nous nous serons débarassés de ces charlatans, nous serons capable de rebâtir le monde tel qu'il devrait être.","Amint lenyomtuk ezeket a sarlatánokat, végre újjáépíthetjük ezt a világot olyanra, amilyennek lennie kéne.","Una volta eliminati questi ciarlatani, potremo ricostruire questo mondo per come dovrebbe essere.","我々が一度こんな酷いハッタリを負かせば、 +世界を本来の状態に建て直せるだろう。","저 허풍쟁이들을 다 물리칠 수만 있다면, 우리가 바랬던 평화로운 세상을 재건할 수 있을 거야.","Als we deze charlatans eenmaal hebben verwijderd, kunnen we deze wereld weer opbouwen zoals het hoort.","Når vi har tatt disse sjarlatanene, kan vi gjenoppbygge verden slik den burde være.","Kiedy obalimy tych szarlatanów, będziemy mogli odbudować ten świat tak, jak powinien być.","Assim que derrubarmos esses charlatões, poderemos reconstruir o mundo do jeito certo.",,"Dupa ce îi vom răpune pe șarlatanii ăștia, vom putea reconstrui lumea în ceea ce trebuie să fie.","Когда мы свергнем этих шарлатанов, то сможем воссоздать этот мир таким, каким он должен быть.",,När vi väl har slagit ner dessa charlataner kommer vi att kunna återuppbygga den här världen som den borde vara.,"Bu şarlatanları alaşağı ettikten sonra, bu dünyayı olması gerektiği gibi yeniden inşa edebileceğiz." +"Remember that you aren't fighting just for yourself, but for everyone here and outside.",TXT_RANDOM_REBEL_09,,,,"Nezapomeň, že nebojuješ jen kvůli sobě, ale kvůli všem tady a tam venku.","Husk, at du ikke kun kæmper for dig selv, men for alle her og udenfor.","Vergiß nicht, dass du nicht nur für dich selbst kämpfst, sondern für alle von uns da draußen.",,"Memoru, ke vi ne batalas nur por vi, sed por ĉiuj ĉi-ene kaj ele.","Recuerda que no estás peleando solo por ti, sino por todos aquí y fuera.","Recuerda que no estás peleando solo por ti, sino por todos aquí y afuera.","Muista, ettet taistele vain itsesi, vaan kaikkien täällä olevien sekä ulkopuolisten puolesta.","Souviens-toi, tu ne te bats pas seulement pour toi, mais pour tous le monde ici et ailleurs.","Ne feledd, nem csak magadért harcolsz, hanem mindnyájunkért idebent, és odakint.","Ricordati che non stai combattendo solo per te stesso, ma per tutti quelli che sono qui e fuori.","貴方は自分自身だけでなく、 +国中の人の為に戦っている事を忘れないでくれよ。",너 혼자 위해서 싸우는 게 아니라 인류를 위해서 싸우고 있다는 걸 잊지 마.,"Onthoud dat je niet alleen voor jezelf vecht, maar voor iedereen hier en daarbuiten.","Husk at du ikke bare kjemper for deg selv, men for alle her og utenfor.","Pamiętaj, że nie walczysz tylko dla siebie, ale dla wszystkich tu i na zewnątrz.","Lembre-se que você não está lutando só por si mesmo, mas por todos nós.",,"Ține minte că nu lupți doar pentru tine, ci pentru toți de aici și de afară.","Помни, ты сражаешься не только за себя, но и за каждого здесь и снаружи.",,"Kom ihåg att du inte bara kämpar för dig själv, utan för alla här och utanför.","Sadece kendiniz için değil, buradaki ve dışarıdaki herkes için savaştığınızı unutmayın." +"As long as one of us still stands, we will win.",TXT_RANDOM_REBEL_10,,,,"Dokud je alespoň jeden z nás na nohou, vyhrajeme!","Så længe en af os stadig står tilbage, vil vi vinde.","Solange nur einer von uns steht, werden wir gewinnen.",,"Dum iu ajn el ni ankoraŭ povos stari, ni venkos.","Mientras uno de nosotros siga en pie, ganaremos.","Mientras uno de nosotros siga en pie, vamos a ganar.","Niin kauan kuin yksikin meistä vielä seisoo, voitto on meidän.","Aussi longtemps qu'un de nous est vivant, nous vaincrons.","Ha csak egy is marad meg közülünk, nyerni fogunk.","Finché uno di noi rimarrà in piedi, vinceremo.",我々が一人でも立っていれば、それが勝利。,"우리 중 한 명이 남아있는 한, 이길 수 있어.","Zolang één van ons nog staat, zullen we winnen.","Så lenge en av oss fortsatt står, vil vi vinne.","Tak długo jak jeden z nas nadal będzie stał, tak długo będziemy wygrywać.","Enquanto um de nós ainda estiver de pé, teremos chance de vencer.",,"Atâta timp cât unul din noi trăiește, vom triumfa.","Пока хотя бы один из нас ещё дышит, мы непобедимы.",,Så länge en av oss fortfarande står kvar kommer vi att vinna.,İçimizden biri ayakta kaldığı sürece kazanacağız. +"Move along, peasant.",TXT_RANDOM_AGUARD_01,,,,"Jdi dál, poddaný.","Gå videre, bonde.","Beweg dich, Bauer!",,"Ne haltu, kampulo.","No te detengas, campesino.",,"Jatka matkaa, maallikko.","Barre-toi, paysan!","Mozgás, paraszt. Egy kettő.","Muoviti, cittadino.",立ち去れ、百姓。,"어서 움직여, 이 자식아.","Ga verder, boer.","Gå videre, bonde.","Ruszaj w drogę, chłopie.","Continue andando, plebeu.",,"Mișcă, sărmanule.","Проходи, рабочий.",,"Gå vidare, bonde.",İlerle köylü. +"Follow the true faith, only then will you begin to understand.",TXT_RANDOM_AGUARD_02,,,,"Následuj pravou víru, jen tak začneš chápat.","Følg den sande tro, først da vil du begynde at forstå.",Folge dem wahren Glauben und du wirst verstehen.,,"Sekvu la veran kredon, nur tiel vi ekkomprenos.","Sigue la fe verdadera, solo entonces empezarás a entender.","Sigue la fe verdadera, solo así vas a entender.",Seuraa totista uskoa; vasta silloin alat käsittää.,"Suis la vraie foi, tu commençeras a comprendre.","Csak ha az igaz hitet követed, csakis akkor kezded majd megérteni.","Segui la vera fede, solo allora comincerai a capire.",真の信仰を求めよ、それしか理解に至る道はない。,참된 신앙이야말로 자기 자신을 깨우칠 수 있지.,"Volg het ware geloof, pas dan zul je het begrijpen.","Følg den sanne troen, først da vil du begynne å forstå.","Podążaj za prawdziwą wiarą, tylko wtedy zaczniesz rozumieć.",Siga a verdadeira fé. Só então você começará a entender.,,"Urmează crezul adevărat, doar atunci vei începe să înțelegi.",Следуй истинной вере. Только тогда ты начнёшь понимать.,,"Följ den sanna tron, först då kommer du att börja förstå.","Gerçek inancı takip et, ancak o zaman anlamaya başlarsın." +Only through death can one be truly reborn.,TXT_RANDOM_AGUARD_03,,,,Pouze skrz smrt lze dosáhnout znovuzrození.,Kun gennem døden kan man virkelig blive genfødt.,Nur durch den Tod kann man wirklich wiedergeboren werden.,,Nur per morto oni povas vere renaskiĝi.,Solo a través de la muerte uno puede realmente renacer.,,Vain kuoleman kautta voi totisesti uudestisyntyä.,C'est seulement a travers la mort que quelqu'un peut renaître.,Csak a halál útján lehet igazán újjászületni.,Solo attraverso la morte uno può rinascere per davvero.,人が真の意味で生まれ変われる方法は、死のみだ,죽음을 통해서만이 진정하게 환생할 수 있는 거다.,Alleen door de dood kan men echt herboren worden.,Bare gjennom døden kan man virkelig bli gjenfødt.,Tylko przez śmierć można się naprawdę odrodzić.,Somente através da morte que alguem poderá renascer de verdade.,,Doar prin moarte poate cineva să fie renăscut cu adevărat.,Истинное перерождение возможно только через смерть.,,Endast genom döden kan man verkligen återfödas.,İnsan ancak ölümle gerçekten yeniden doğabilir. +I'm not interested in your useless drivel.,TXT_RANDOM_AGUARD_04,,,,Nezajímají mě tvoje žvásty.,Jeg er ikke interesseret i dit ubrugelige sludder.,Dein nutzloses Geschwafel interessiert mich nicht.,,Ne interesas min aŭdi viajn sensencaĵojn.,No me interesa tu charlatanería.,No me interesa oír tus estupideces.,Joutava hölynpölysi ei minua kiinnosta.,Je ne suis pas intéressé par tes idioties inutiles.,Nem érdekel az értelmetlen hablatyolásod.,Non sono interessato alle tue ciance inutili.,お前の無益な戯言なぞ興味は無い。,네 잡담 따위는 듣고 싶지 않아.,Ik ben niet geïnteresseerd in je nutteloze gewauwel.,Jeg er ikke interessert i det unyttige vrøvlet ditt.,Nie interesują mnie twoje bezużyteczne brednie.,Não estou interessado em ouvir as suas bobagens inúteis.,,Nu sunt interesat de lipsa ta de sens.,Мне неинтересна твоя пустая болтовня.,,Jag är inte intresserad av ditt värdelösa dravel.,İşe yaramaz saçmalıklarınla ilgilenmiyorum. +If I had wanted to talk to you I would have told you so.,TXT_RANDOM_AGUARD_05,,,,"Kdybych s tebou chtěl mluvit, nařídil bych ti to.","Hvis jeg havde ønsket at tale med dig, ville jeg have sagt det til dig.","Wenn ich mich mit dir unterhalten wollte, hätte ich dir das gesagt.",,"Se mi volus paroli kun vi, mi unue dirus tion al vi.",Si quisiera hablar contigo te lo hubiera dicho.,,"Jos olisin halunnut puhua kanssasi, olisin sen sinulle ilmaissut.",Si j'avais voulu te parler je te l'aurais dit.,"Ha beszélni akartam volna veled, azt mondtam volna.","Se avessi voluto parlarti, te lo avrei detto.",話があったらこちらからする。,대화하고 싶었으면 내가 먼저 말을 걸었겠지. 안 그래?,"Als ik met je had willen praten, had ik je dat gezegd.","Hadde jeg villet snakke med deg, hadde jeg sagt det.","Gdybym chciał z tobą rozmawiać, powiedziałbym ci to.","Se eu quisesse falar com você, eu teria te dito.",,Dacă voiam să vorbim ți-aș fi spus.,"Если бы я хотел поговорить с тобой, то сказал бы об этом.",,Om jag hade velat prata med dig hade jag sagt det till dig.,"Seninle konuşmak isteseydim, bunu sana söylerdim." +Go and annoy someone else!,TXT_RANDOM_AGUARD_06,,,,Jdi otravovat někoho jiného!,Gå ud og irriter en anden!,Bitte nerve jemand anderen.,,Ĝenu aliulon!,¡Ve a molestar a otro!,,Mene ärsyttämään jotakuta toista!,Va ennuyer quelqu'un d'autre!,Menj és idegesíts valaki mást!,Vai a scocciare qualcun altro!,あまりイライラさせるな!,귀찮게 하지 말고 가서 딴 녀석이랑 놀아!,Ga iemand anders irriteren!,Gå og plag noen andre!,Idź i denerwuj kogoś innego!,Vá incomodar outra pessoa!,,Du-te și enervează pe altul.,Иди и надоедай кому-нибудь другому!,,Gå och irriter någon annan!,Git ve başkasını rahatsız et! +Keep moving!,TXT_RANDOM_AGUARD_07,,,,Nezastavuj se!,Fortsæt med at bevæge dig!,Beweg dich!,,Plue piediru!,¡Sigue caminando!,,Ala laputtaa!,Bouge!,Mozgás!,Continua a muoverti!,立ち去れ!,여어 움직여라!,Blijf in beweging!,Gå videre!,Ruszaj się!,Continue andando!,,Continuă să mergi!,Иди куда шёл!,,Fortsätt att röra på dig!,Yürümeye devam et! +"If the alarm goes off, just stay out of our way!",TXT_RANDOM_AGUARD_08,,,,"Jestli je vyhlášen poplach, jdi nám z cesty!","Hvis alarmen går i gang, så hold dig bare væk fra os!","Wenn der Alarm losgeht, steh uns nicht im Weg!",,"Se la alarmo eksonas, vi nur foriĝu de antaŭ ni!","¡Si la alarma se activa, solo quítate de nuestra vista!",,"Jos hälytys laukeaa, pysy vain pois meidät tieltämme!","Si l'alarme s'enclenche, reste en dehors de notre chemin!","Ha beindul a riasztó, csak ne állj az utunkba.","Se scatta l'allarme, stattene fuori dai piedi!",警報を鳴らされたくないなら、邪魔をするな!,"만약 알람이 작동된다면, 기도하고 도망치기나 해!","Als het alarm afgaat, blijf dan gewoon uit de weg!","Hvis alarmen går, bare hold deg unna oss!","Jeśli włączy się alarm, po prostu zejdź nam z drogi!","Se o alarme disparar, não fique no nosso caminho!",,"Dacă alarma e declanșată, pur și simplu nu ne sta în cale.","Если поднимется тревога, не попадайся нам под ноги!",,"Om larmet går, håll dig bara ur vägen!","Alarm çalarsa, yolumuzdan çekilin!" +The Order will cleanse the world and usher it into the new era.,TXT_RANDOM_AGUARD_09,,,,Řád pročistí náš svět a navede ho do nového věku.,Ordenen vil rense verden og føre den ind i den nye æra.,Der Orden wird die Welt läutern und in eine neue Ära führen.,,La Ordeno elpurigos la mondon kaj gvidos ĝin al la nova epoko.,La Orden limpiará el mundo y marcará el inicio de la nueva era.,La Orden va a limpiar el mundo y marcar el inicio de la nueva era.,Veljeskunta puhdistaa tämän maailman ja johdattaa sen uudelle aikakaudelle.,L'ordre nettoira le monde et le conduira dans une nouvelle ère.,"A Rend megtisztítja a világot, és egy új korszakba vezeti.",L'ordine ripulirà questo mondo e lo porterà verso una nuova era.,"オーダーは世界を浄化し、 我々を新しい時代へ導いてくれる。",우리 오더는 언젠간 이 세상을 정화하고 새로운 시대를 만들 것이다.,De orde zal de wereld zuiveren en het nieuwe tijdperk inluiden.,Ordenen vil rense verden og føre den inn i en ny æra.,Zakon oczyści świat i wprowadzi go w nową erę.,A Ordem purificará o mundo e o conduzirá para a nova era.,,Ordinul va curăța lumea și ne va propulsa într-o nouă eră.,"Орден очистит этот мир и положит начало новой эре! -",,Tarikat dünyayı temizleyecek ve yeni bir çağ başlatacak. -"Problem? No, I thought not.",TXT_RANDOM_AGUARD_10,,,,"Nějaký problém? Ne, není.","Problemer? Nej, det troede jeg ikke.","Hast du Probleme? Nein, ich glaube nicht.",,"Ĉu ia problemo? Ne, tiel, kiel mi jam pensis.","¿Algún problema? No, como ya me imaginaba.",,"Jokin ongelma? Ei, niin arvelinkin.",Un problème? Je pense que non.,Baj van? Nem? Én is így gondoltam.,"Qualche problema? No, come pensavo.",問題か? そうは思わないが。,문제가 있다고? 자. 이제 없지?,"Probleem? Nee, ik dacht van niet.","Problemer? Nei, jeg trodde ikke det.","Problem? Nie, nie sądziłem.",Algum problema? Imaginei que não.,,"Probleme? Nu, așa credeam și eu.",Что-то не так? Нет? Я так и думал.,,"Sorun mu var? Hayır, ben de öyle düşünmüştüm." -Alms for the poor?,TXT_RANDOM_BEGGAR_01,,,,Almužnu pro chudáka?,Almisser til de fattige?,Almosen für die Armen.,,Ĉu vi havas almozon por malriĉuloj?,¿Limosnas para los pobres?,,Almuja köyhälle?,L'aumône pour les pauvres?,Alamizsna a szegényeknek?,Elemosina per i poveri?,貧民に何か恵んでくれるのか?,부디 빈민에게 구호를...,Aalmoezen voor de armen?,Almisser til de fattige?,Jałmużna dla biednych?,Uma ajuda para os pobres?,,Ceva pentru ce-i sărmani?,У тебя не найдётся мелочи для бедняка?,,Fakirler için sadaka mı? -"What are you looking at, surfacer?",TXT_RANDOM_BEGGAR_02,,,,"Na co koukáš, nadzemníku?","Hvad kigger du på, overfladeklipper?","Wonach suchst du, Oberflächler?",,,"¿Que estás mirando, prejuicioso?",,"Mitä tuijotat, maanpintalainen?","Tu regarde qui, habitant de la surface?","Mit nézel, felszínlakó?","Cosa stai guardando, abitante della superficie?",何ジロジロ見てる、地上人。,"어딜 보고 있는 겁니까, 지상인씨?","Waar kijk je naar, oppervlaktebewoner? ","Hva glor du på, overflatebehandler?","Na co się patrzysz, surferze?","Tá olhando o quê, habitante da superfície?",,La ce te uiți?,"Что уставился, незнакомец?",,"Neye bakıyorsun, sörfçü?" -"You wouldn't have any extra food, would you?",TXT_RANDOM_BEGGAR_03,,,,Neměl bys náhodou něco navíc k snědku?,"Du har vel ikke noget ekstra mad, vel?","Du hast nichts zu Essen übrig, oder?",,"Vi ne havas iom da restaj manĝaĵoj, ĉu?","No tendrás algo de comida que te sobre, ¿no?",,Ei sinulla sattuisi olemaan ylimääräistä ruokaa?,Aurais-tu de la nourriture en trop sur toi?,"Nincs egy kis felesleges ételed, ugye?",Tu non avresti del cibo avanzato da darci?,余ってる食べ物とかはないよな?,남은 식량 가지고 있습니까? 부디 있다고 말해주세요... 제발...,"Je zou toch geen extra eten hebben, of wel?",Du har vel ikke noe ekstra mat?,"Nie mielibyście żadnego dodatkowego jedzenia, prawda?","Por acaso você não tem comida sobrando, tem?",,"Nu ai mâncare în plus, nu-i așa?",У тебя случайно не найдётся немного лишней еды?,,"Fazladan yiyeceğin olmazdı, değil mi?" -You surface people will never understand us.,TXT_RANDOM_BEGGAR_04,,,,Vy lidi z povrchu nás nikdy nepochopíte.,I overflademennesker vil aldrig forstå os.,Ihr Oberflächenleute werdet uns nie verstehen.,,"Vi, surfaco-loĝantoj, neniam komprenos nin.","Vosotros, gente de la superficie, nunca nos entenderéis.","Ustedes, gente de la superficie, jamás nos van a entender.",Te maanpinnan asukit ette meitä koskaan tule ymmärtämään.,"Vous, les gens de la surface, vous ne comprendrez jamais.",Ti felszíniek sosem fogtok megérteni minket.,Voi abitanti della superficie non ci comprenderete mai.,"お前みたいな地上の連中には俺らのことなんて -わかりゃしない。",당신 같은 지상인들은 우리를 아예 도와주지도 않죠. 그렇지 않나요?,Je zult mensen ons nooit begrijpen.,Dere overflatefolk vil aldri forstå oss.,"Wy, ludzie powierzchni, nigdy nas nie zrozumiecie.",Vocês da superfície nunca nos entenderão.,,Voi oamenii de la suprafață nu veți înțelege niciodată.,"Вы, люди с поверхности, никогда не поймёте нас.",,Siz yüzey insanları bizi asla anlamayacaksınız. -"Ha, the guards can't find us. Those idiots don't even know we exist.",TXT_RANDOM_BEGGAR_05,,,,"Ha, stráže nás nenajdou. Ti idioti ani neví, že existujeme.","Ha, vagterne kan ikke finde os. De idioter ved ikke engang, at vi eksisterer.","Ha, die Wächter können uns nicht finden. Die Idioten ahnen nicht mal, dass wir existieren.",,,"Ja, los guardias no nos encontrarán. Esos idiotas ni siquiera saben que existimos.",,"Hah, vartijat eivät pysty löytämään meitä. Ne idiootit eivät edes tiedä olemassaolostamme.","Ha, les gardes ne nous trouveront jamais, ces idiots ne savent même pas qu'on existe!","Ha! Az őrök az életben nem találnak meg minket. Azok a barmok azt sem tudják, hogy létezünk.","Ha, le guardie non ci trovano. Quegli idioti non sanno neppure della nostra esistenza.","衛兵共は俺らを見つけられない。 +",,Orden kommer att rena världen och föra in den i den nya eran.,Tarikat dünyayı temizleyecek ve yeni bir çağ başlatacak. +"Problem? No, I thought not.",TXT_RANDOM_AGUARD_10,,,,"Nějaký problém? Ne, není.","Problemer? Nej, det troede jeg ikke.","Hast du Probleme? Nein, ich glaube nicht.",,"Ĉu ia problemo? Ne, tiel, kiel mi jam pensis.","¿Algún problema? No, como ya me imaginaba.",,"Jokin ongelma? Ei, niin arvelinkin.",Un problème? Je pense que non.,Baj van? Nem? Én is így gondoltam.,"Qualche problema? No, come pensavo.",問題か? そうは思わないが。,문제가 있다고? 자. 이제 없지?,"Probleem? Nee, ik dacht van niet.","Problemer? Nei, jeg trodde ikke det.","Problem? Nie, nie sądziłem.",Algum problema? Imaginei que não.,,"Probleme? Nu, așa credeam și eu.",Что-то не так? Нет? Я так и думал.,,"Problem? Nej, det trodde jag inte.","Sorun mu var? Hayır, ben de öyle düşünmüştüm." +Alms for the poor?,TXT_RANDOM_BEGGAR_01,,,,Almužnu pro chudáka?,Almisser til de fattige?,Almosen für die Armen.,,Ĉu vi havas almozon por malriĉuloj?,¿Limosna para los pobres?,,Almuja köyhälle?,L'aumône pour les pauvres?,Alamizsna a szegényeknek?,Elemosina per i poveri?,貧民に何か恵んでくれるのか?,부디 빈민에게 구호를...,Aalmoezen voor de armen?,Almisser til de fattige?,Jałmużna dla biednych?,Uma ajuda para os pobres?,,Ceva pentru ce-i sărmani?,У тебя не найдётся мелочи для бедняка?,,Almosor till de fattiga?,Fakirler için sadaka mı? +"What are you looking at, surfacer?",TXT_RANDOM_BEGGAR_02,,,,"Na co koukáš, nadzemníku?","Hvad kigger du på, overfladeklipper?","Wonach suchst du, Oberflächler?",,"Kion vi rigardas, surfaco-loĝanto?","¿Que estás mirando, habitante de la superficie?",,"Mitä tuijotat, maanpintalainen?","Tu regarde qui, habitant de la surface?","Mit nézel, felszínlakó?","Cosa stai guardando, abitante della superficie?",何ジロジロ見てる、地上人。,"어딜 보고 있는 겁니까, 지상인씨?","Waar kijk je naar, oppervlaktebewoner? ","Hva glor du på, overflatebehandler?","Na co się patrzysz, surferze?","Tá olhando o quê, habitante da superfície?",,La ce te uiți?,"Что уставился, незнакомец?",,"Vad tittar du på, ytmänniska?","Neye bakıyorsun, sörfçü?" +"You wouldn't have any extra food, would you?",TXT_RANDOM_BEGGAR_03,,,,Neměl bys náhodou něco navíc k snědku?,"Du har vel ikke noget ekstra mad, vel?","Du hast nichts zu Essen übrig, oder?",,"Vi ne havas iom da restaj manĝaĵoj, ĉu?","No tendrás algo de comida que te sobre, ¿no?",,Ei sinulla sattuisi olemaan ylimääräistä ruokaa?,Aurais-tu de la nourriture en trop sur toi?,"Nincs egy kis felesleges ételed, ugye?",Tu non avresti del cibo avanzato da darci?,余ってる食べ物とかはないよな?,남은 식량 가지고 있습니까? 부디 있다고 말해주세요... 제발...,"Je zou toch geen extra eten hebben, of wel?",Du har vel ikke noe ekstra mat?,"Nie mielibyście żadnego dodatkowego jedzenia, prawda?","Por acaso você não tem comida sobrando, tem?",,"Nu ai mâncare în plus, nu-i așa?",У тебя случайно не найдётся немного лишней еды?,,"Du skulle inte ha någon extra mat, eller hur?","Fazladan yiyeceğin olmazdı, değil mi?" +You surface people will never understand us.,TXT_RANDOM_BEGGAR_04,,,,Vy lidi z povrchu nás nikdy nepochopíte.,I overflademennesker vil aldrig forstå os.,Ihr Oberflächenleute werdet uns nie verstehen.,,"Vi, surfaco-loĝantoj, neniam komprenos nin.","Vosotros, gente de la superficie, jamás nos entenderéis.","Ustedes, gente de la superficie, jamás nos van a entender.",Te maanpinnan asukit ette meitä koskaan tule ymmärtämään.,"Vous, les gens de la surface, vous ne comprendrez jamais.",Ti felszíniek sosem fogtok megérteni minket.,Voi abitanti della superficie non ci comprenderete mai.,"お前みたいな地上の連中には俺らのことなんて +わかりゃしない。",당신 같은 지상인들은 우리를 아예 도와주지도 않죠. 그렇지 않나요?,Je zult mensen ons nooit begrijpen.,Dere overflatefolk vil aldri forstå oss.,"Wy, ludzie powierzchni, nigdy nas nie zrozumiecie.",Vocês da superfície nunca nos entenderão.,,Voi oamenii de la suprafață nu veți înțelege niciodată.,"Вы, люди с поверхности, никогда не поймёте нас.",,Ni ytliga människor kommer aldrig att förstå oss.,Siz yüzey insanları bizi asla anlamayacaksınız. +"Ha, the guards can't find us. Those idiots don't even know we exist.",TXT_RANDOM_BEGGAR_05,,,,"Ha, stráže nás nenajdou. Ti idioti ani neví, že existujeme.","Ha, vagterne kan ikke finde os. De idioter ved ikke engang, at vi eksisterer.","Ha, die Wächter können uns nicht finden. Die Idioten ahnen nicht mal, dass wir existieren.",,"Ha, gardistoj ne trovas nin. Tiuj stultuloj eĉ ne scias, ke ni ekzistas.","Ja, los guardias no nos encuentran. Esos idiotas ni siquiera saben que existimos.",,"Hah, vartijat eivät pysty löytämään meitä. Ne idiootit eivät edes tiedä olemassaolostamme.","Ha, les gardes ne nous trouveront jamais, ces idiots ne savent même pas qu'on existe!","Ha! Az őrök az életben nem találnak meg minket. Azok a barmok azt sem tudják, hogy létezünk.","Ha, le guardie non ci trovano. Quegli idioti non sanno neppure della nostra esistenza.","衛兵共は俺らを見つけられない。 あのバカどもは俺らがここに居ることすら -知らないんだぞ。","하, 저 멍청한 경비들은 우리가 이 밑에 숨어있다는 걸 모르죠!","Ha, de bewakers kunnen ons niet vinden. Die idioten weten niet eens dat we bestaan.",Vaktene kan ikke finne oss. De idiotene vet ikke engang at vi eksisterer.,"Strażnicy nie mogą nas znaleźć. Ci idioci nawet nie wiedzą, że istniejemy.","Hah, os guardas não conseguem nos achar. Esses idiotas nem sabem que a gente existe.",,"Ha, gardienii nu ne pot găsi. Idioții ăștia nici măcar nu știu de existența noastră.","Ха! Эта глупая стража никогда не найдёт нас. Они даже не знают, что мы существуем.",,"Ha, muhafızlar bizi bulamaz. O aptallar varlığımızdan bile haberdar değiller." -One day everyone but those who serve the Order will be forced to join us.,TXT_RANDOM_BEGGAR_06,,,,"Jednoho dne se všichni, kdo neslouží Řádu, budou muset přidat k nám.","En dag vil alle undtagen dem, der tjener ordenen, blive tvunget til at slutte sig til os.","Eines Tages werden alle, die nicht dem Orden dienen, sich uns anschließen.",,"Iun tagon ĉiuj, krom la servantoj de La Ordono, estos devigataj aliĝi al ni.","Algún día todos, excepto aquellos que sirven a La Orden, serán forzados a unirse a nosotros.","Algún día todos, menos aquellos que le sirven a La Orden, se van a ver obligados a unirse a nosotros.",Jonain päivänä kaikkien paitsi Veljeskuntaa palvelevien on liityttävä meihin.,"Un jour, tous sauf les membres de l'ordre seront forcés de nous rejoindre.","Egy nap mindenki, kivéve a Rend szolgálói arra kényszerülnek majd, hogy hozzánk tartozzanak.","Un giorno tutti, salvo chi serve l'Ordine, sarà costretto ad unirsi a noi.","そのうち、オーダーに仕える者を除いて +知らないんだぞ。","하, 저 멍청한 경비들은 우리가 이 밑에 숨어있다는 걸 모르죠!","Ha, de bewakers kunnen ons niet vinden. Die idioten weten niet eens dat we bestaan.",Vaktene kan ikke finne oss. De idiotene vet ikke engang at vi eksisterer.,"Strażnicy nie mogą nas znaleźć. Ci idioci nawet nie wiedzą, że istniejemy.","Hah, os guardas não conseguem nos achar. Esses idiotas nem sabem que a gente existe.",,"Ha, gardienii nu ne pot găsi. Idioții ăștia nici măcar nu știu de existența noastră.","Ха! Эта глупая стража никогда не найдёт нас. Они даже не знают, что мы существуем.",,"Ha, vakterna kan inte hitta oss. De idioterna vet inte ens att vi finns.","Ha, muhafızlar bizi bulamaz. O aptallar varlığımızdan bile haberdar değiller." +One day everyone but those who serve the Order will be forced to join us.,TXT_RANDOM_BEGGAR_06,,,,"Jednoho dne se všichni, kdo neslouží Řádu, budou muset přidat k nám.","En dag vil alle undtagen dem, der tjener ordenen, blive tvunget til at slutte sig til os.","Eines Tages werden alle, die nicht dem Orden dienen, sich uns anschließen.",,"Ian tagon ĉiuj, krom la servantoj de La Ordeno, estos devigataj aliĝi al ni.","Algún día todos, excepto aquellos que sirven a La Orden, se verán forzados a unirse a nosotros.","Algún día todos, menos aquellos que le sirven a La Orden, se van a ver obligados a unirse a nosotros.",Jonain päivänä kaikkien paitsi Veljeskuntaa palvelevien on liityttävä meihin.,"Un jour, tous sauf les membres de l'ordre seront forcés de nous rejoindre.","Egy nap mindenki, kivéve a Rend szolgálói arra kényszerülnek majd, hogy hozzánk tartozzanak.","Un giorno tutti, salvo chi serve l'Ordine, sarà costretto ad unirsi a noi.","そのうち、オーダーに仕える者を除いて 全ての人間が私達のようになることを -強いられるだろう。",언젠가는 순종하는 사람들을 제외하고는 모두가 오더에 강제병합될지도 몰라요...,"Op een dag zal iedereen, behalve degenen die de Orde dienen, gedwongen worden om zich bij ons aan te sluiten.",En dag vil alle unntatt de som tjener Ordenen bli tvunget til å slutte seg til oss.,"Pewnego dnia wszyscy poza tymi, którzy służą Zakonowi, będą zmuszeni do przyłączenia się do nas.",Um dia todos exceto aqueles que servem à Ordem serão forçados a se juntarem a nós.,,Într-o bună zi toți în afară de cei care slujesc Ordinul vor fi nevoiți să ni se alăture.,"Однажды всем, кто не служит Ордену, придётся присоединиться к нам.",,Bir gün Tarikat'a hizmet edenler dışında herkes bize katılmak zorunda kalacak. -"Stare now, but you know that this will be your own face one day.",TXT_RANDOM_BEGGAR_07,,,,"Teď zíráš, ale věz, že tohle bude jednou tvá tvář.","Stir nu, men du ved, at dette vil være dit eget ansigt en dag.","Glotz nur, aber irgendwann wirst du auch so aussehen.",,,"Observa ahora, pero ya sabes que esta será tu propia cara algún día.",,"Tuijotat nyt, mutta tiedä, että jonain päivänä nämä ovat sinun kasvosi.","Moque nous si tu veux, mais tu sais que ceci sera aussi ton sort un jour.","Bámulj csak, de tudd, hogy egy nap ez az arc a sajátod lesz.","Osservaci pure, ma tu sai bene che un giorno questa sarà la tua faccia.","今ジロジロ見てたみたいだが、 -お前もいつかこんな顔になるだろうな。",배꼽 잡고 웃으시구려. 결국엔 당신도 이 모양 이 꼴이 될 테니까.,"Staar nu, maar je weet dat dit op een dag je eigen gezicht zal zijn.","Stirr nå, men du vet at dette vil bli ditt eget ansikt en dag.","Gap się teraz, ale wiesz, że to będzie kiedyś twoja własna twarz.","Pode ficar olhando, mas você sabe que este será o seu próprio rosto um dia.",,"Te holbezi acum, dar asta va fi soarta ta într-o zi.","Смотри сколько влезет, но знай, что когда-нибудь так будет выглядеть и твоё лицо.",,"Şimdi bak, ama biliyorsun ki bu bir gün senin de yüzün olacak." -There's nothing more annoying than a surfacer with an attitude!,TXT_RANDOM_BEGGAR_08,,,,Není nic otravnějšího než nadzemník s dobrou náladou!,Der er intet mere irriterende end en surfacer med en attitude!,Es gibt nichts nervigeres als einen Oberflächler mit Gesinnung.,,,¡No hay nada más irritante que una persona de la superficie con mala actitud!,,Ei ole mitään ärsyttävämpää kuin töykeä maanpintalainen!,Il n'y rien de plus barbant qu'un type de la surface et son orgeuil!,Nincs bosszantóbb egy felszíninél ilyen hozzáállással.,Non c'è nulla di più seccante di un abitante della superficie saccente!,腹立たしい地上人の態度は悩みの種だ!,버릇없는 지상인 보다 더 짜증 나는 건 없을 거예요!,Er is niets vervelender dan een verharder met een houding!,Det er ikke noe mer irriterende enn en overflatebehandler med en holdning!,Nie ma nic bardziej irytującego niż surfer z nastawieniem!,Não há nada mais irritante do que alguém da superfície cheio de si!,,Nu e nimic mai enervant decât o persoană de la suprafață cu fițe!,"Ничто так не выводит из себя, как болтун с поверхности!",,Tavırlı bir sörfçüden daha sinir bozucu bir şey yoktur! -The Order will make short work of your pathetic Front.,TXT_RANDOM_BEGGAR_09,,,,Řád s tou vaší patetickou Frontou udělá krátký proces.,Ordenen vil gøre kort proces med din patetiske front.,Der Orden wird eure armselige Front auseinandernehmen.,,La Ordono detruos senprobleme vian ridindan Fronton.,La Orden acabará fácilmente con vuestro patético Frente.,La Orden va a destruir como si nada su patético Frente.,Veljeskunta tekee nopeasti selvän säälittävästä Rintamastanne.,L'ordre se débarrassera de vos soldats pathétiques.,A Rendnek gyerekjáték lesz a szánalmas kis Frontotok.,L'Ordine farà facilmente fuori il vostro patetico Fronte.,"オーダーはアンタの哀れなフロントに近付いてる -ってさ。",오더가 당신을 비롯한 한심한 프론트 저항군을 싹슬이할 겁니다.,De Orde zal kort werk maken van je zielige Front.,Ordenen vil gjøre kort prosess med din patetiske Front.,Zakon szybko rozprawi się z twoim żałosnym frontem.,A Ordem vai dar um jeito em vocês da Frente.,,Ordinul va face preș din Frontul tău.,Орден быстро расправится с твоим бессильным сопротивлением.,,Tarikat senin acınası cepheni kısa sürede halledecektir. -"Watch yourself, surfacer. We know our enemies!",TXT_RANDOM_BEGGAR_10,,,,"Dávej si pozor, nadzemníku. Známe své nepřátele!","Pas på dig selv, surfacer. Vi kender vores fjender!","Pass nur auf, Oberflächler. Wir kennen unsere Feinde.",,"Atentu, surfaco-loĝanto. Ni konas niajn malamikojn!","Cuidado, habitante de la superficie. ¡Nosotros conocemos a nuestros enemigos!",,"Pidä varasi, maanpintalainen. Tunnemme vihollisemme!","Prend guarde a toi, habitant de la surface. Nous connaîssons nos ennemis!","Óvakodj, felszíni! Ismerjük az ellenségeinket!","Stai attento, abitante della superficie. Conosciamo i nostri nemici!",気を付けろ、地上人。敵はアンタを知ってるぞ。,"조심하시오, 지상인. 우리는 적이 누군지 알고 있으니!","Let op jezelf, surfacer. Wij kennen onze vijanden!","Pass deg, overflatebehandler. Vi kjenner våre fiender!","Uważaj na siebie, surferze. Znamy naszych wrogów!","Cuidado, ô da superficie. Nós sabemos quem são os nossos inimigos!",,"Ai grijă, omule de la suprafață! Ne cunoaștem inamicii.","Поосторожнее, человек с поверхности. Мы знаем, кто наш враг!",,"Kendine dikkat et, sörfçü. Düşmanlarımızı tanıyoruz!" -We are the hands of fate. To earn our wrath is to find oblivion!,TXT_RANDOM_PGUARD_01,,,,Jsme rukama osudu. Získat si náš hněv je jako upadnout v zapomnění!,Vi er skæbnens hænder. At gøre sig fortjent til vores vrede er at finde glemsel!,Wir sind die Hände des Schicksals. Wer sich unseren Zorn verdient wird vernichtet!,,,Somos las manos del destino. ¡Encontrar nuestra ira es encontrar el olvido!,,"Olemme kohtalon käsi. Joka yllyttää meidät vihaan, etsii turmiotaan.",Nous sommes les mains du destin. Apprendre notre colère est l'égal de trouver l'oubli!,"Mi vagyunk a sors keze. Kárhozatra ítéltetett, ki haragunkat elnyeri.",Siamo le mani del destino. Farci infuriare significa trovare l'oblio!,"運命は我々の手の中だ。 -あまり歯向かわない方がいいぞ。","우리는 긍휼의 손길이며, 불신자들을 심판하는 검일지니!",Wij zijn de handen van het lot. Om onze toorn te verdienen is het vinden van de vergetelheid!,Vi er i skjebnens hender. Å fortjene vår vrede er å finne glemsel!,Jesteśmy rękami losu. Zasłużyć na nasz gniew to znaleźć zapomnienie!,Somos as mãos do destino. Quem despertar a nossa ira será destruído!,,Suntem mâinile destinului. Să ne câștigi furia e să găsești vidul!,Мы длани судьбы. Прогневить нас означает встретить забвение!,,"Bizler kaderin elleriyiz. Gazabımızı kazanmak, unutulmayı bulmaktır!" -The Order will cleanse the world of the weak and corrupt!,TXT_RANDOM_PGUARD_02,,,,Řád vyčistí svět od slabých a zkažených!,Ordenen vil rense verden for de svage og korrupte!,Der Orden wird die Welt von allem Schwachen und Korrupten säubern.,,,¡La Orden limpiará el mundo de los débiles y los corruptos!,,Veljeskunta puhdistaa tämän maailman sen heikoista ja turmeltuneista!,L'ordre nettoira le monde des faibles et corrompus!,A Rend megtisztítja a világot a gyengéktől és a korruptaktól!,"L'Ordine ripulirà il mondo dai deboli e corrotti! +強いられるだろう。",언젠가는 순종하는 사람들을 제외하고는 모두가 오더에 강제병합될지도 몰라요...,"Op een dag zal iedereen, behalve degenen die de Orde dienen, gedwongen worden om zich bij ons aan te sluiten.",En dag vil alle unntatt de som tjener Ordenen bli tvunget til å slutte seg til oss.,"Pewnego dnia wszyscy poza tymi, którzy służą Zakonowi, będą zmuszeni do przyłączenia się do nas.",Um dia todos exceto aqueles que servem à Ordem serão forçados a se juntarem a nós.,,Într-o bună zi toți în afară de cei care slujesc Ordinul vor fi nevoiți să ni se alăture.,"Однажды всем, кто не служит Ордену, придётся присоединиться к нам.",,En dag kommer alla utom de som tjänar Orden att tvingas ansluta sig till oss.,Bir gün Tarikat'a hizmet edenler dışında herkes bize katılmak zorunda kalacak. +"Stare now, but you know that this will be your own face one day.",TXT_RANDOM_BEGGAR_07,,,,"Teď zíráš, ale věz, že tohle bude jednou tvá tvář.","Stir nu, men du ved, at dette vil være dit eget ansigt en dag.","Glotz nur, aber irgendwann wirst du auch so aussehen.",,"Rigardu nun, sed vi scias, ke iam ĉi tiu estos via propra vizaĝo.","Observa ahora, pero ya sabes que esta será tu propia cara algún día.","Observa ahora, pero ya sabes que esta va a ser tu propia cara algún día.","Tuijotat nyt, mutta tiedä, että jonain päivänä nämä ovat sinun kasvosi.","Moque nous si tu veux, mais tu sais que ceci sera aussi ton sort un jour.","Bámulj csak, de tudd, hogy egy nap ez az arc a sajátod lesz.","Osservaci pure, ma tu sai bene che un giorno questa sarà la tua faccia.","今ジロジロ見てたみたいだが、 +お前もいつかこんな顔になるだろうな。",배꼽 잡고 웃으시구려. 결국엔 당신도 이 모양 이 꼴이 될 테니까.,"Staar nu, maar je weet dat dit op een dag je eigen gezicht zal zijn.","Stirr nå, men du vet at dette vil bli ditt eget ansikt en dag.","Gap się teraz, ale wiesz, że to będzie kiedyś twoja własna twarz.","Pode ficar olhando, mas você sabe que este será o seu próprio rosto um dia.",,"Te holbezi acum, dar asta va fi soarta ta într-o zi.","Смотри сколько влезет, но знай, что когда-нибудь так будет выглядеть и твоё лицо.",,"Stirra nu, men du vet att detta kommer att vara ditt eget ansikte en dag.","Şimdi bak, ama biliyorsun ki bu bir gün senin de yüzün olacak." +There's nothing more annoying than a surfacer with an attitude!,TXT_RANDOM_BEGGAR_08,,,,Není nic otravnějšího než nadzemník s dobrou náladou!,Der er ikke noget mere irriterende end en overfladebeboer med en attitude!,Es gibt nichts nervigeres als einen Oberflächler mit Gesinnung.,,Estas nenio pli malagrabla ol surfaco-loĝanto kun tia sintenado!,¡No hay nada más irritante que una persona de la superficie con mala actitud!,,Ei ole mitään ärsyttävämpää kuin töykeä maanpintalainen!,Il n'y rien de plus barbant qu'un type de la surface et son orgeuil!,Nincs bosszantóbb egy felszíninél ilyen hozzáállással.,Non c'è nulla di più seccante di un abitante della superficie saccente!,腹立たしい地上人の態度は悩みの種だ!,버릇없는 지상인 보다 더 짜증 나는 건 없을 거예요!,Er is niets vervelender dan een verharder met een houding!,Det er ikke noe mer irriterende enn en overflatebehandler med en holdning!,Nie ma nic bardziej irytującego niż surfer z nastawieniem!,Não há nada mais irritante do que alguém da superfície cheio de si!,,Nu e nimic mai enervant decât o persoană de la suprafață cu fițe!,"Ничто так не выводит из себя, как болтун с поверхности!",,Det finns inget mer irriterande än en ytmänniska med attityd!,Tavırlı bir sörfçüden daha sinir bozucu bir şey yoktur! +The Order will make short work of your pathetic Front.,TXT_RANDOM_BEGGAR_09,,,,Řád s tou vaší patetickou Frontou udělá krátký proces.,Ordenen vil gøre kort proces med din patetiske front.,Der Orden wird eure armselige Front auseinandernehmen.,,La Ordeno detruos senprobleme vian ridindan Fronton.,La Orden acabará fácilmente con vuestro patético Frente.,La Orden va a destruir como si nada su patético Frente.,Veljeskunta tekee nopeasti selvän säälittävästä Rintamastanne.,L'ordre se débarrassera de vos soldats pathétiques.,A Rendnek gyerekjáték lesz a szánalmas kis Frontotok.,L'Ordine farà facilmente fuori il vostro patetico Fronte.,"オーダーはアンタの哀れなフロントに近付いてる +ってさ。",오더가 당신을 비롯한 한심한 프론트 저항군을 싹슬이할 겁니다.,De Orde zal kort werk maken van je zielige Front.,Ordenen vil gjøre kort prosess med din patetiske Front.,Zakon szybko rozprawi się z twoim żałosnym frontem.,A Ordem vai dar um jeito em vocês da Frente.,,Ordinul va face preș din Frontul tău.,Орден быстро расправится с твоим бессильным сопротивлением.,,Orden kommer att göra processen kort med din patetiska front.,Tarikat senin acınası cepheni kısa sürede halledecektir. +"Watch yourself, surfacer. We know our enemies!",TXT_RANDOM_BEGGAR_10,,,,"Dávej si pozor, nadzemníku. Známe své nepřátele!","Pas på dig selv, overfladebeboer. Vi kender vores fjender!","Pass nur auf, Oberflächler. Wir kennen unsere Feinde.",,"Atentu, surfaco-loĝanto. Ni konas niajn malamikojn!","Cuidado, habitante de la superficie. ¡Nosotros conocemos a nuestros enemigos!",,"Pidä varasi, maanpintalainen. Tunnemme vihollisemme!","Prend guarde a toi, habitant de la surface. Nous connaîssons nos ennemis!","Óvakodj, felszíni! Ismerjük az ellenségeinket!","Stai attento, abitante della superficie. Conosciamo i nostri nemici!",気を付けろ、地上人。敵はアンタを知ってるぞ。,"조심하시오, 지상인. 우리는 적이 누군지 알고 있으니!","Pas op, oppervlaktebewoner. We kennen onze vijanden!","Pass deg, overflatebehandler. Vi kjenner våre fiender!","Uważaj na siebie, surferze. Znamy naszych wrogów!","Cuidado, ô da superficie. Nós sabemos quem são os nossos inimigos!",,"Ai grijă, omule de la suprafață! Ne cunoaștem inamicii.","Поосторожнее, человек с поверхности. Мы знаем, кто наш враг!",,"Se upp, ytmänniska. Vi känner våra fiender!","Kendine dikkat et, sörfçü. Düşmanlarımızı tanıyoruz!" +We are the hands of fate. To earn our wrath is to find oblivion!,TXT_RANDOM_PGUARD_01,,,,Jsme rukama osudu. Získat si náš hněv je jako upadnout v zapomnění!,Vi er skæbnens hænder. At gøre sig fortjent til vores vrede er at finde glemsel!,Wir sind die Hände des Schicksals. Wer sich unseren Zorn verdient wird vernichtet!,,Ni estas la manoj de la destino. Furiozigi nin estas trovi forgeson!,Somos las manos del destino. ¡Despertar nuestra ira es encontrar el olvido!,,"Olemme kohtalon käsi. Joka yllyttää meidät vihaan, etsii turmiotaan.",Nous sommes les mains du destin. Apprendre notre colère est l'égal de trouver l'oubli!,"Mi vagyunk a sors keze. Kárhozatra ítéltetett, ki haragunkat elnyeri.",Siamo le mani del destino. Farci infuriare significa trovare l'oblio!,"運命は我々の手の中だ。 +あまり歯向かわない方がいいぞ。","우리는 긍휼의 손길이며, 불신자들을 심판하는 검일지니!",Wij zijn de handen van het lot. Om onze toorn te verdienen is het vinden van de vergetelheid!,Vi er i skjebnens hender. Å fortjene vår vrede er å finne glemsel!,Jesteśmy rękami losu. Zasłużyć na nasz gniew to znaleźć zapomnienie!,Somos as mãos do destino. Quem despertar a nossa ira será destruído!,,Suntem mâinile destinului. Să ne câștigi furia e să găsești vidul!,Мы длани судьбы. Прогневить нас означает встретить забвение!,,Vi är ödets händer. Att förtjäna vår vrede är att finna glömska!,"Bizler kaderin elleriyiz. Gazabımızı kazanmak, unutulmayı bulmaktır!" +The Order will cleanse the world of the weak and corrupt!,TXT_RANDOM_PGUARD_02,,,,Řád vyčistí svět od slabých a zkažených!,Ordenen vil rense verden for de svage og korrupte!,Der Orden wird die Welt von allem Schwachen und Korrupten säubern.,,La Ordeno elpurigos la mondon je malfortuloj kaj koruptitoj!,¡La Orden limpiará el mundo de los débiles y los corruptos!,,Veljeskunta puhdistaa tämän maailman sen heikoista ja turmeltuneista!,L'ordre nettoira le monde des faibles et corrompus!,A Rend megtisztítja a világot a gyengéktől és a korruptaktól!,"L'Ordine ripulirà il mondo dai deboli e corrotti! ","オーダーは浅ましく腐敗した世界を -浄化するだろう!",유일신님은 반드시 이 나약하고 부패한 세상을 정화할 것이니라!,De Orde zal de wereld zuiveren van de zwakken en corrupten!,Ordenen vil rense verden for de svake og korrupte!,Zakon oczyści świat ze słabych i skorumpowanych!,A Ordem purificará o mundo dos fracos e corruptos!,,Ordinul va curăța lumea de slabi și corupți!,Орден очистит мир от слабых и порочных!,,"Düzen, dünyayı zayıf ve yozlaşmış olanlardan temizleyecek!" -Obey the will of the masters!,TXT_RANDOM_PGUARD_03,,,,Podrob se vůli svých pánů!,Adlyd mændenes vilje!,Gehorche dem Willen der Meister.,,,¡Obedece la voluntad de los maestros!,,Tottele mestareiden tahtoa!,Obéissez à la volonté de vos maîtres!,Engedelmeskedj mestereink akaratának!,Obbedisci al volere dei maestri!,主の意志に従うのだ。,스승님들께서 너희에게 명령하신 도를 행하라!,Gehoorzaam de wil van de meesters!,Adlyd mesternes vilje!,Bądźcie posłuszni woli mistrzów!,Obedeça a lei dos mestres!,,Supune-te voinței stăpânilor!,Подчинись воле хозяев!,,Efendilerin iradesine itaat edin! -Long life to the brothers of the Order!,TXT_RANDOM_PGUARD_04,,,,Nechť žijí naši bratři Řádu!,Langt liv til ordenens brødre!,Lang lebe die Brüder des Ordens.,,,¡Vivan los hermanos de La Orden!,,Pitkä ikä Veljeskunnan veljille!,Longue vie aux membres de l'Ordre!,Éljenek sokáig a Rend testvérei!,Lunga vita ai fratelli dell'Ordine.,オーダーの友に永久の命を!,"오더와 그의 동포들을 따르라, 그럼 영생을 얻을 지니!",Een lang leven voor de broeders van de Orde!,Lenge leve ordenens brødre!,Niech żyją bracia Zakonu!,Vida longa aos irmãos da Ordem!,,Viață lungă fraților Ordinului!,Да здравствуют братья Ордена!,,Tarikat'ın kardeşlerine uzun ömürler! -Free will is an illusion that binds the weak minded.,TXT_RANDOM_PGUARD_05,,,,"Svobodná vůle je jen iluze, která váže ruce slabomyslným.","Den frie vilje er en illusion, der binder de svage sind.",Freier Wille ist eine Illusion die die Schwachen fesselt.,,,El libre albedrio es una ilusión que une a los débiles de mente.,,"Vapaa tahto on harha, joka sitoo heikkomieliset.",La liberté de penser est l'illusion qui aveugle les faibles d'esprit.,"A Szabad akarat egy illúzió, ami csupán a gyengéknek mentsvára.",Il libero arbitrio è un'illusione che tiene legati i deboli di mente.,自由意志など、弱者を縛る幻想に過ぎぬ。,"자유의지는 나약함의 상징이요, 필멸의 꾐이라.",De vrije wil is een illusie die de zwakkeren bindt.,Fri vilje er en illusjon som binder de svake.,"Wolna wola to iluzja, która wiąże słabe umysły.",Livre arbítrio é uma ilusão para os fracos.,,Voința liberă e o iluzie care leagă mințile slabe.,"Свободная воля — лишь иллюзия, созданная для управления слабыми духом.",,"Özgür irade, zayıf zihinleri bağlayan bir yanılsamadır." -Power is the path to glory. To follow the Order is to walk that path!,TXT_RANDOM_PGUARD_06,,,,Moc je cesta ke slávě. Následovat Řád je chodit po té cestě!,Magt er vejen til ære. At følge Ordenen er at gå denne vej!,"Macht ist der Weg zum Ruhm. Dem Orden zu folgen bedeutet, diesen Weg zu gehen.",,,El poder es el camino a la gloria. ¡Seguir a La Orden es alcanzar ese camino!,,Valta on tie kunniaan. Veljeskunnan seuraaminen on vaeltaa sitä tietä!,le pouvoir est le chemin de la gloire. Suivre l'ordre c'est suivre ce chemin!,"A dicsőéghez vezető út az erő. Aki A Rendet követi, ezt az utat járja.",Il potere è il percorso verso la gloria. Seguire l'Ordine è come attraversare quel percorso!,"力は栄光への道だ。 -オーダーに従えばその道を歩めるだろう。","힘은 영광이자 희망이며, 이를 간구함으로써 축복받을지어다!",Macht is de weg naar glorie. De Orde volgen is dat pad bewandelen!,Makt er veien til ære. Å følge Ordenen er å gå den veien!,Władza jest drogą do chwały. Podążanie za Zakonem to podążanie tą ścieżką!,O poder é o caminho para a glória. Siga a Ordem e andará por esse caminho!,,Puterea e calea spre glorie. Să urmezi Ordinul e să urmezi acea cale!,Сила — путь к величию. Вступить в ряды Ордена означает пойти этим путём!,,"Güç, zafere giden yoldur. Tarikat'ı takip etmek o yolda yürümektir!" -"Take your place among the righteous, join us!",TXT_RANDOM_PGUARD_07,,,,"Najdi své místo mezi spravedlivými, přidej se k nám!","Tag din plads blandt de retfærdige, slut dig til os!",Nimm deinen Platz unter den Gerechten ein. ,,,Toma tu lugar entre los justos. ¡Únete a nosotros!,,Ota paikkasi hurskaitten joukossa; liity meihin!,"Prend ta place parmi les justes, rejoins nous!","Foglalj helyet az igazak között, csatlakozz hozzánk!","Prendi il tuo posto tra i giusti, unisciti a noi!",正義は我等と共に在る、参加せよ!,"우리는 참됐으며 구원을 받았느니라, 함께 기도하면 두려울 것이 없을지니!","Neem je plaats in tussen de rechtvaardigen, sluit je aan bij ons!","Ta din plass blant de rettferdige, bli med oss!","Zajmij swoje miejsce wśród sprawiedliwych, dołącz do nas!",Tenha o seu lugar entre os justos. Junte-se a nós!,,Alătură-te celor drepți!,Займи своё место среди праведных. Присоединись к нам!,,"Doğruların arasında yerinizi alın, bize katılın!" -The Order protects its own.,TXT_RANDOM_PGUARD_08,,,,Řád si své lidi chrání.,Ordenen beskytter sine egne.,Der Orden beschützt seine Jünger.,,,La Orden protege a los suyos.,,Veljeskunta puolustaa omiaan.,L'ordre protège les siens.,A Rend a magáét védi.,L'Ordine protegge i suoi.,オーダーは我々を守護している。,오더는 신들을 향한 기도로 거룩하여짐이니라.,De Orde beschermt zijn discipelen. ,Ordenen beskytter sine egne.,Zakon chroni swoich.,A Ordem protege os seus discípulos.,,Ordinul îi protejează pe cei loiali.,Орден защищает своих.,,Tarikat kendine ait olanları korur. -Acolytes? They have yet to see the full glory of the Order.,TXT_RANDOM_PGUARD_09,,,,Akolyté? Ti ještě neviděli Řád v celé své kráse.,Acolytes? De har endnu ikke set Ordenens fulde herlighed.,Ministranten? Die müssen erst noch die volle Macht des Ordens erfahren.,,Ĉu akolitoj? Ili ankoraŭ ne vidis la tutan gloron de La Ordono.,¿Acólitos? Aún no han visto toda la gloria de La Orden.,¿Acólitos? Aún no vieron toda la gloria de La Orden.,Akoluutit? He eivät ole vielä nähneet Veljeskunnan täyttä kirkkautta.,Les Acolytes? Ils n'ont pas encore été témoins de la vraie gloire de l'ordre.,Ministránsok? Még nem látták A Rend igazi dicsőségét.,Gli accoliti? Devono ancora conoscere la vera gloria dell'Ordine.,"アコライト? -奴等はオーダーの爛漫なる未来を見ていない。",아콜라이트들이라... 애석하게도 이 들은 믿음이 아직 부족하다고 생각함이라.,Acolieten? Zij moeten de volle glorie van de Orde nog zien.,Akolytter? De har ennå ikke sett Ordenens fulle herlighet.,Akolitów? Oni jeszcze nie widzieli pełnej chwały Zakonu.,Acólitos? Eles ainda não viram toda a glória da Ordem.,,Acoliți? Încă nu au văzut gloria Ordinului.,Служители? Им ещё только предстоит узреть подлинное величие Ордена.,,Yardımcıları mı? Henüz Tarikat'ın tüm ihtişamını görmediler. -"If there is any honor inside that pathetic shell of a body, you'll enter into the arms of the Order.",TXT_RANDOM_PGUARD_10,,,"If there is any honour inside that pathetic shell of a body, you'll enter into the arms of the Order.","Jestli ta tvoje žalostná tělesná schránka má v sobě kousek cti, dáš se do rukou Řádu.","Hvis der er nogen ære inden i denne ynkelige skal af en krop, vil du gå ind i Ordenens arme.","Wenn du noch einen Hauch von Ehre hast, wirst du dem Orden beitreten.",,,"Si hay algo de honor dentro de ese patético cascarón llamado «cuerpo», La Orden te espera con los brazos abiertos.",,"Jos tuon säälittävän ruumiinhylyn sisällä on yhtään kunniakkuutta, otat itsesi Veljeskunnan huomaan.","Si il y a une once de gloire dans ce corps pathétique, ceux de l'ordre te prendront parmi les leurs.","Ha csak egy csipetnyi becsület is van testednek szánalmas páncéljában, A Rend katonáinak sorába fogsz beállni.","Se c'è un pò di onore rimasto dentro quel guscio patetico che chiami corpo, entrerai nelle braccia dell'Ordine.","その哀れな肉体の殻でも名誉の為ならば、 -オーダーの兵器を携える事が出来るだろう。",육체라는 나약한 껍질에 갇힌 운명을 참회하는 자들이야말로 오더와 함께할 수 있을지어다. ,"Als er enige eer in dat zielige omhulsel van een lichaam zit, zul je in de armen van de Orde binnengaan.","Hvis det er noe ære i det patetiske skallet av en kropp, vil du gå inn i Ordenens armer.","Jeśli w tej żałosnej skorupie ciała jest choć odrobina honoru, wejdziesz w ramiona Zakonu.","Se ainda existe honra dentro da sua carne patética, você entrará para os braços da Ordem.",,"Dacă e o fărâmă de onoare în acel corp jalnic, vei putea intra în brațele Ordinului.","Если внутри этой бренной телесной оболочки есть хоть капля чести, ты присоединишься к Ордену.",,"Eğer o zavallı bedenin içinde biraz onur varsa, Tarikat'ın kollarına gireceksin." -Bye!,TXT_RANDOMGOODBYE_1,,,,Tak ahoj!,Farvel!,Tschüss!,,Ĝis!,¡Adiós!,,Näkemiin!,Au revoir!,Szervusz!,Ciao!,じゃあな!,안녕!,Dag!,Adjø!,Pa!,Tchau!,,Pa!,Пока!,,Güle güle! -"Thanks, bye!",TXT_RANDOMGOODBYE_2,,,,"Díky, ahoj!","Tak, farvel!","Danke, tschüss!",,Dankon. Ĝis!,Gracias. ¡Adiós!,,"Kiitos, hei!","Merci, au revoir!","Köszi, szia!","Grazie, ciao!",どうも、じゃあ!,그렇군요. 그럼 안녕히!,"Bedankt, tot ziens!","Takk, ha det!","Dzięki, pa!",Obrigado. Até mais!,,"Merci, pa!","Спасибо, пока!",,"Teşekkürler, güle güle!" -See you later!,TXT_RANDOMGOODBYE_3,,,,Uvidíme se později!,Vi ses senere!,Bis später!,,Ĝis la revido!,¡Nos vemos!,,Nähdään!,A plus tard!,Később találkozunk!,Ci vediamo dopo!,また今度!,다음에 봐요!,Tot ziens!,Vi ses senere!,Do zobaczenia później!,Até logo!,,Ne vedem mai încolo!,До встречи!,,Sonra görüşürüz! -,,Strife logs,,,,,,,,,,,,,,,,,,,,,,,, -"Hello? Command, a com unit has just been activated... Am receiving visuals and sound from... somebody... Hey you, get out of there now... and drop the chalice!",TXT_ILOG1,,,,"Haló? Velení, právě byl aktivován komunikátor... příjimám obraz a zvuk od... někoho... Hej, ty, dostaň se odtaď... a zahoď ten kalich!","Hallo? Kommando, en kommunikationsenhed er lige blevet aktiveret... Jeg modtager billeder og lyd fra... en eller anden... Hey du, kom ud derfra nu... og smid bægeret!","Hallo, Kommandozentrale, eine Kommunikationseinheit wurde gerade aktiviert.... Ich empfange Bilder und Ton von... irgend jemandem... Hey, du, verschwinde da sofort... Und schmeiß den Kelch weg!",,,"¿Hola? Comando, una unidad de comunicación acaba de ser activada... Recibo visuales y sonido de... Alguien... Eh tú, sal de ahí ahora mismo... ¡Y tira el cáliz!",,"Haloo? Komentokeskus, äsken juuri kytkettiin päälle viestintälaite... Poimin... jonkun... videota ja ääntä... Hei sinä, häivy täältä heti paikalla... ja pudota kalkki!","Allô? Central, un communicateur à été activé.. Je recois visuel et son de.. quelqu'un.. Hé, vous, sortez de là! Et lâchez le calice!","Haló Központ! Egy jeladót aktiváltak...kép és hang jeleket veszek...valakitől...Hé Te ott, húzz ki onnan...és rakd le a serleget!","Pronto? Comando, un'unità di comunicazione è appena stata attivata... Sto ricevendo segnali audiovisivi da... qualcuno... Hey, tu, esci da là subito, e lascia stare quel calice!","もしもし? 司令部、comユニットが起動されました。 +浄化するだろう!",유일신님은 반드시 이 나약하고 부패한 세상을 정화할 것이니라!,De Orde zal de wereld zuiveren van de zwakken en corrupten!,Ordenen vil rense verden for de svake og korrupte!,Zakon oczyści świat ze słabych i skorumpowanych!,A Ordem purificará o mundo dos fracos e corruptos!,,Ordinul va curăța lumea de slabi și corupți!,Орден очистит мир от слабых и порочных!,,Orden kommer att rensa världen från de svaga och korrupta!,"Düzen, dünyayı zayıf ve yozlaşmış olanlardan temizleyecek!" +Obey the will of the masters!,TXT_RANDOM_PGUARD_03,,,,Podrob se vůli svých pánů!,Adlyd mændenes vilje!,Gehorche dem Willen der Meister.,,Obeu la volon de la mastroj!,¡Obedece la voluntad de los maestros!,,Tottele mestareiden tahtoa!,Obéissez à la volonté de vos maîtres!,Engedelmeskedj mestereink akaratának!,Obbedisci al volere dei maestri!,主の意志に従うのだ。,스승님들께서 너희에게 명령하신 도를 행하라!,Gehoorzaam de wil van de meesters!,Adlyd mesternes vilje!,Bądźcie posłuszni woli mistrzów!,Obedeça a lei dos mestres!,,Supune-te voinței stăpânilor!,Подчинись воле хозяев!,,Lyd mästarnas vilja!,Efendilerin iradesine itaat edin! +Long life to the brothers of the Order!,TXT_RANDOM_PGUARD_04,,,,Nechť žijí naši bratři Řádu!,Langt liv til ordenens brødre!,Lang lebe die Brüder des Ordens.,,Vivu la fratoj de La Ordeno!,¡Vivan los hermanos de La Orden!,,Pitkä ikä Veljeskunnan veljille!,Longue vie aux membres de l'Ordre!,Éljenek sokáig a Rend testvérei!,Lunga vita ai fratelli dell'Ordine.,オーダーの友に永久の命を!,"오더와 그의 동포들을 따르라, 그럼 영생을 얻을 지니!",Een lang leven voor de broeders van de Orde!,Lenge leve ordenens brødre!,Niech żyją bracia Zakonu!,Vida longa aos irmãos da Ordem!,,Viață lungă fraților Ordinului!,Да здравствуют братья Ордена!,,Länge liv till ordensbröderna!,Tarikat'ın kardeşlerine uzun ömürler! +Free will is an illusion that binds the weak minded.,TXT_RANDOM_PGUARD_05,,,,"Svobodná vůle je jen iluze, která váže ruce slabomyslným.","Den frie vilje er en illusion, der binder de svage sind.",Freier Wille ist eine Illusion die die Schwachen fesselt.,,"Libera volo estas iluzio, kiu ligas debiluloj.",El libre albedrío es una ilusión que une a los débiles de mente.,,"Vapaa tahto on harha, joka sitoo heikkomieliset.",La liberté de penser est l'illusion qui aveugle les faibles d'esprit.,"A Szabad akarat egy illúzió, ami csupán a gyengéknek mentsvára.",Il libero arbitrio è un'illusione che tiene legati i deboli di mente.,自由意志など、弱者を縛る幻想に過ぎぬ。,"자유의지는 나약함의 상징이요, 필멸의 꾐이라.",De vrije wil is een illusie die de zwakkeren bindt.,Fri vilje er en illusjon som binder de svake.,"Wolna wola to iluzja, która wiąże słabe umysły.",Livre arbítrio é uma ilusão para os fracos.,,Voința liberă e o iluzie care leagă mințile slabe.,"Свободная воля — лишь иллюзия, созданная для управления слабыми духом.",,Fri vilja är en illusion som binder de svaga sinnena.,"Özgür irade, zayıf zihinleri bağlayan bir yanılsamadır." +Power is the path to glory. To follow the Order is to walk that path!,TXT_RANDOM_PGUARD_06,,,,Moc je cesta ke slávě. Následovat Řád je chodit po té cestě!,Magt er vejen til ære. At følge Ordenen er at gå denne vej!,"Macht ist der Weg zum Ruhm. Dem Orden zu folgen bedeutet, diesen Weg zu gehen.",,Povo estas la vojo al gloro. Sekvi La Ordenon estas iri laŭ tiu vojo!,El poder es el camino a la gloria. ¡Seguir a La Orden es alcanzar ese camino!,,Valta on tie kunniaan. Veljeskunnan seuraaminen on vaeltaa sitä tietä!,le pouvoir est le chemin de la gloire. Suivre l'ordre c'est suivre ce chemin!,"A dicsőéghez vezető út az erő. Aki A Rendet követi, ezt az utat járja.",Il potere è il percorso verso la gloria. Seguire l'Ordine è come attraversare quel percorso!,"力は栄光への道だ。 +オーダーに従えばその道を歩めるだろう。","힘은 영광이자 희망이며, 이를 간구함으로써 축복받을지어다!",Macht is de weg naar glorie. De Orde volgen is dat pad bewandelen!,Makt er veien til ære. Å følge Ordenen er å gå den veien!,Władza jest drogą do chwały. Podążanie za Zakonem to podążanie tą ścieżką!,O poder é o caminho para a glória. Siga a Ordem e andará por esse caminho!,,Puterea e calea spre glorie. Să urmezi Ordinul e să urmezi acea cale!,Сила — путь к величию. Вступить в ряды Ордена означает пойти этим путём!,,Makt är vägen till ära. Att följa Orden är att gå den vägen!,"Güç, zafere giden yoldur. Tarikat'ı takip etmek o yolda yürümektir!" +"Take your place among the righteous, join us!",TXT_RANDOM_PGUARD_07,,,,"Najdi své místo mezi spravedlivými, přidej se k nám!","Tag din plads blandt de retfærdige, slut dig til os!",Nimm deinen Platz unter den Gerechten ein. ,,Havu vian postenon inter ĝustuloj. Aliĝu al ni!,Toma tu lugar entre los justos. ¡Únete a nosotros!,,Ota paikkasi hurskaitten joukossa; liity meihin!,"Prend ta place parmi les justes, rejoins nous!","Foglalj helyet az igazak között, csatlakozz hozzánk!","Prendi il tuo posto tra i giusti, unisciti a noi!",正義は我等と共に在る、参加せよ!,"우리는 참됐으며 구원을 받았느니라, 함께 기도하면 두려울 것이 없을지니!","Neem je plaats in tussen de rechtvaardigen, sluit je aan bij ons!","Ta din plass blant de rettferdige, bli med oss!","Zajmij swoje miejsce wśród sprawiedliwych, dołącz do nas!",Tenha o seu lugar entre os justos. Junte-se a nós!,,Alătură-te celor drepți!,Займи своё место среди праведных. Присоединись к нам!,,"Ta din plats bland de rättfärdiga, anslut dig till oss!","Doğruların arasında yerinizi alın, bize katılın!" +The Order protects its own.,TXT_RANDOM_PGUARD_08,,,,Řád si své lidi chrání.,Ordenen beskytter sine egne.,Der Orden beschützt seine Jünger.,,La Ordeno defendas siajn anojn.,La Orden defiende a los suyos.,,Veljeskunta puolustaa omiaan.,L'ordre protège les siens.,A Rend a magáét védi.,L'Ordine protegge i suoi.,オーダーは我々を守護している。,오더는 신들을 향한 기도로 거룩하여짐이니라.,De Orde beschermt zijn discipelen. ,Ordenen beskytter sine egne.,Zakon chroni swoich.,A Ordem protege os seus discípulos.,,Ordinul îi protejează pe cei loiali.,Орден защищает своих.,,Orden skyddar sina egna.,Tarikat kendine ait olanları korur. +Acolytes? They have yet to see the full glory of the Order.,TXT_RANDOM_PGUARD_09,,,,Akolyté? Ti ještě neviděli Řád v celé své kráse.,Acolytes? De har endnu ikke set Ordenens fulde herlighed.,Ministranten? Die müssen erst noch die volle Macht des Ordens erfahren.,,Ĉu akolitoj? Ili ankoraŭ ne vidis la tutan gloron de La Ordeno.,¿Acólitos? Aún no han visto toda la gloria de La Orden.,¿Acólitos? Aún no vieron toda la gloria de La Orden.,Akoluutit? He eivät ole vielä nähneet Veljeskunnan täyttä kirkkautta.,Les Acolytes? Ils n'ont pas encore été témoins de la vraie gloire de l'ordre.,Ministránsok? Még nem látták A Rend igazi dicsőségét.,Gli accoliti? Devono ancora conoscere la vera gloria dell'Ordine.,"アコライト? +奴等はオーダーの爛漫なる未来を見ていない。",아콜라이트들이라... 애석하게도 이 들은 믿음이 아직 부족하다고 생각함이라.,Acolieten? Zij moeten de volle glorie van de Orde nog zien.,Akolytter? De har ennå ikke sett Ordenens fulle herlighet.,Akolitów? Oni jeszcze nie widzieli pełnej chwały Zakonu.,Acólitos? Eles ainda não viram toda a glória da Ordem.,,Acoliți? Încă nu au văzut gloria Ordinului.,Служители? Им ещё только предстоит узреть подлинное величие Ордена.,,Acolytes? De har ännu inte sett ordens fulla ära.,Yardımcıları mı? Henüz Tarikat'ın tüm ihtişamını görmediler. +"If there is any honor inside that pathetic shell of a body, you'll enter into the arms of the Order.",TXT_RANDOM_PGUARD_10,,,"If there is any honour inside that pathetic shell of a body, you'll enter into the arms of the Order.","Jestli ta tvoje žalostná tělesná schránka má v sobě kousek cti, dáš se do rukou Řádu.","Hvis der er nogen ære inden i denne ynkelige skal af en krop, vil du gå ind i Ordenens arme.","Wenn du noch einen Hauch von Ehre hast, wirst du dem Orden beitreten.",,"Se restas iom da honoro en tiu ridinda ŝelo nomata «korpo», vi iĝos unu el la brakoj de La Ordeno.","Si hay algo de honor dentro de ese patético cascarón llamado «cuerpo», La Orden te espera con los brazos abiertos.",,"Jos tuon säälittävän ruumiinhylyn sisällä on yhtään kunniakkuutta, otat itsesi Veljeskunnan huomaan.","Si il y a une once de gloire dans ce corps pathétique, ceux de l'ordre te prendront parmi les leurs.","Ha csak egy csipetnyi becsület is van testednek szánalmas páncéljában, A Rend katonáinak sorába fogsz beállni.","Se c'è un po' di onore rimasto dentro quel guscio patetico che chiami corpo, entrerai nelle braccia dell'Ordine.","その哀れな肉体の殻でも名誉の為ならば、 +オーダーの兵器を携える事が出来るだろう。",육체라는 나약한 껍질에 갇힌 운명을 참회하는 자들이야말로 오더와 함께할 수 있을지어다. ,"Als er enige eer in dat zielige omhulsel van een lichaam zit, zul je in de armen van de Orde binnengaan.","Hvis det er noe ære i det patetiske skallet av en kropp, vil du gå inn i Ordenens armer.","Jeśli w tej żałosnej skorupie ciała jest choć odrobina honoru, wejdziesz w ramiona Zakonu.","Se ainda existe honra dentro da sua carne patética, você entrará para os braços da Ordem.",,"Dacă e o fărâmă de onoare în acel corp jalnic, vei putea intra în brațele Ordinului.","Если внутри этой бренной телесной оболочки есть хоть капля чести, ты присоединишься к Ордену.",,"Om det finns någon heder i det patetiska skalet av en kropp, kommer du att gå in i Ordens armar.","Eğer o zavallı bedenin içinde biraz onur varsa, Tarikat'ın kollarına gireceksin." +Bye!,TXT_RANDOMGOODBYE_1,,,,Tak ahoj!,Farvel!,Tschüss!,,Ĝis!,¡Adiós!,,Näkemiin!,Au revoir!,Szervusz!,Ciao!,じゃあな!,안녕!,Dag!,Adjø!,Pa!,Tchau!,,Pa!,Пока!,,Hej då!,Güle güle! +"Thanks, bye!",TXT_RANDOMGOODBYE_2,,,,"Díky, ahoj!","Tak, farvel!","Danke, tschüss!",,Dankon. Ĝis!,Gracias. ¡Adiós!,,"Kiitos, hei!","Merci, au revoir!","Köszi, szia!","Grazie, ciao!",どうも、じゃあ!,그렇군요. 그럼 안녕히!,"Bedankt, tot ziens!","Takk, ha det!","Dzięki, pa!",Obrigado. Até mais!,,"Merci, pa!","Спасибо, пока!",,"Tack, hej då!","Teşekkürler, güle güle!" +See you later!,TXT_RANDOMGOODBYE_3,,,,Uvidíme se později!,Vi ses senere!,Bis später!,,Ĝis la revido!,¡Nos vemos!,,Nähdään!,A plus tard!,Később találkozunk!,Ci vediamo dopo!,また今度!,다음에 봐요!,Tot ziens!,Vi ses senere!,Do zobaczenia później!,Até logo!,,Ne vedem mai încolo!,До встречи!,,Vi ses senare!,Sonra görüşürüz! +,,Strife logs,,,,,,,,,,,,,,,,,,,,,,,,, +"Hello? Command, a com unit has just been activated... Am receiving visuals and sound from... somebody... Hey you, get out of there now... and drop the chalice!",TXT_ILOG1,MAP33: After getting the hidden com unit in the tavern.,,,"Haló? Velení, právě byl aktivován komunikátor... příjimám obraz a zvuk od... někoho... Hej, ty, dostaň se odtaď... a zahoď ten kalich!","Hallo? Kommando, en kommunikationsenhed er lige blevet aktiveret... Jeg modtager billeder og lyd fra... en eller anden... Hey du, kom ud derfra nu... og smid bægeret!","Hallo, Kommandozentrale, eine Kommunikationseinheit wurde gerade aktiviert.... Ich empfange Bilder und Ton von... irgend jemandem... Hey, du, verschwinde da sofort... Und schmeiß den Kelch weg!",,Saluton?... Komandanto! Interfono ekagiĝis: mi ricevas bildojn kaj sonon el... iu. Hola! Eliru tuj el tie... kaj forĵetu la kalikon!,"¿Hola?... Comando, un intercomunicador acaba de ser activado: recibo imágenes y sonido de... alguien. Eh, tú, sal de ahí ahora mismo... ¡Y tira ese cáliz!",,"Haloo? Komentokeskus, äsken juuri kytkettiin päälle viestintälaite... Poimin... jonkun... videota ja ääntä... Hei sinä, häivy täältä heti paikalla... ja pudota kalkki!","Allô? Central, un communicateur à été activé.. Je recois visuel et son de.. quelqu'un.. Hé, vous, sortez de là! Et lâchez le calice!","Haló Központ! Egy jeladót aktiváltak...kép és hang jeleket veszek...valakitől...Hé Te ott, húzz ki onnan...és rakd le a serleget!","Pronto? Comando, un'unità di comunicazione è appena stata attivata... Sto ricevendo segnali audiovisivi da... qualcuno... Hey, tu, esci da là subito, e lascia stare quel calice!","もしもし? 司令部、comユニットが起動されました。 ...からビジュアルとサウンドを受け取っています ...誰かが...ちょっと、今そこから出て行ってください -...そして聖杯を捨ててください!","여보세요? 본부, 통신기가 막 작동되기 시작했다... 지금 어떤... 사람의 모습이 보이는데... 이봐, 거기서 당장 나와... 그리고 성배를 버려!","Hallo? Commando, een com-unit is zojuist geactiveerd.... Ontvang ik beelden en geluid van.... iemand... Hé jij, ga daar nu weg.... en laat de kelk vallen!","Hallo? Kommando, en kommunikasjonsenhet har nettopp blitt aktivert... Mottar bilder og lyd fra... noen... Hei du, kom deg ut derfra nå... og slipp begeret!","Halo? Dowództwo, jednostka komunikacyjna właśnie została aktywowana... Odbieram obraz i dźwięk od... kogoś... Hej ty, uciekaj stamtąd natychmiast... i rzuć kielich!","Alô? Comando, um comunicador acabou de ser ativado... Estou recebendo imagens e som de... alguém... Ei você, saia daí agora... e solte o cálice!",,"Alo? Centrul de comandă, o unitate tocmai a fost activată.... Primesc imagini și audio de la... cineva... Hei tu,pleacă de acolo și lasă potirul!","Алло? Штаб, передатчик только что включился... Я принимаю звук и картинку от... кого-то... Эй, ты, беги оттуда, сейчас же... и брось чашу!",,"Alo? Komuta, bir iletişim birimi az önce aktive edildi. Birinden görüntü ve ses alıyorum. Hey sen, hemen oradan çık... ve kadehi bırak!" -"Listen, this com unit tells me that you're 100% human. I've been ordered to bring you in, we're talking trust here. Betray me and pay. Oh, and by the way, you can call me Blackbird.",TXT_ILOG2,MAP02: After getting the com unit from Rowan and leaving his room.,,,"Poslyš, tento komunikátor mi říká, že jsi na sto procent člověkem. Dostala jsem rozkaz přivést tě k nám, jde o důvěryhodnou záležitost. Zraď mě a zaplatíš. Jo, a mimochodem, můžeš mi říkat Straka.","Hør, denne com-enhed fortæller mig, at du er 100% menneskelig. Jeg er blevet beordret til at bringe dig ind. Vi taler om tillid her. Forråd mig og betal. Åh, og forresten, du kan kalde mig Blackbird.","Hör zu, dieser Kommunikator sagt mit, dass du noch 100% menschlich bist. Mir wurde aufgetragen, dich zu unserer Zentrale zu führen. Wir reden über Vertrauen, wenn du mich verrätst, wirst du bezahlen. Übrigens, du kannst mich Blackbird nennen.",,,"Escucha, este intercomunicador me dice que eres 100% humano. Se me ha ordenado dejarte entrar, así que hablamos en confianza. Traicióname y pagarás. Ah, por cierto, puedes llamarme BlackBird.","Escucha, este intercomunicador me dice que eres 100% humano. Se ordenadó dejarte entrar, así que hablamos en confianza. Traicióname y te vas a arrepentir. Ah, por cierto, puedes llamarme BlackBird.","Kuule, tämä viestintälaite ilmaisee sinun olevan sataprosenttisesti ihminen. Minut on määrätty tuomaan sinut meidän joukkoomme; puhumme luottamuksellisesti. Petä minut ja saat luvan maksaa. Ja muuten, voit kutsua minua Blackbirdiksi.","Ecoute, ce communicateur me dit que tu est 100% humain. On m'a ordonnée de te ramener, c'est une question de confiance. Trahis-moi et tu paieras. Oh, et tu peux m'appeler Blackbird.","Figyelj, azt jelzi a jeladó, hogy 100%-ban ember vagy. Azt az utasítást kaptam ,hogy vigyelek be, de a bizalmammal játszol. Átversz és megfizetsz. Ja, és hívhatsz feketerigónak.","Ascolta, questa unità di comunicazione mi dice che sei 100% umano. Ho l'ordine di farti arrivare da noi, e quindi stiamo parlando di fiducia. Se mi tradisci la pagherai cara. Comunque, mi puoi chiamare Blackbird.","聞こえるか、この無線機がアナタは100%人間だと判断した。 +...そして聖杯を捨ててください!","여보세요? 본부, 통신기가 막 작동되기 시작했다... 지금 어떤... 사람의 모습이 보이는데... 이봐, 거기서 당장 나와... 그리고 성배를 버려!","Hallo? Commando, een com-unit is zojuist geactiveerd.... Ontvang ik beelden en geluid van.... iemand... Hé jij, ga daar nu weg.... en laat de kelk vallen!","Hallo? Kommando, en kommunikasjonsenhet har nettopp blitt aktivert... Mottar bilder og lyd fra... noen... Hei du, kom deg ut derfra nå... og slipp begeret!","Halo? Dowództwo, jednostka komunikacyjna właśnie została aktywowana... Odbieram obraz i dźwięk od... kogoś... Hej ty, uciekaj stamtąd natychmiast... i rzuć kielich!","Alô? Comando, um comunicador acabou de ser ativado... Estou recebendo imagens e som de... alguém... Ei você, saia daí agora... e solte o cálice!",,"Alo? Centrul de comandă, o unitate tocmai a fost activată.... Primesc imagini și audio de la... cineva... Hei tu,pleacă de acolo și lasă potirul!","Алло? Штаб, передатчик только что включился... Я принимаю звук и картинку от... кого-то... Эй, ты, беги оттуда, сейчас же... и брось чашу!",,"Hallå? Kommando, en kom-enhet har just aktiverats... Får bild och ljud från... någon... Hallå där, kom ut därifrån nu... och släpp kalken!","Alo? Komuta, bir iletişim birimi az önce aktive edildi. Birinden görüntü ve ses alıyorum. Hey sen, hemen oradan çık... ve kadehi bırak!" +"Listen, this com unit tells me that you're 100% human. I've been ordered to bring you in, we're talking trust here. Betray me and pay. Oh, and by the way, you can call me Blackbird.",TXT_ILOG2,MAP02: After getting the com unit from Rowan and leaving his room.,,,"Poslyš, tento komunikátor mi říká, že jsi na sto procent člověkem. Dostala jsem rozkaz přivést tě k nám, jde o důvěryhodnou záležitost. Zraď mě a zaplatíš. Jo, a mimochodem, můžeš mi říkat Straka.","Hør, denne com-enhed fortæller mig, at du er 100% menneskelig. Jeg er blevet beordret til at bringe dig ind. Vi taler om tillid her. Forråd mig og betal. Åh, og forresten, du kan kalde mig Blackbird.","Hör zu, dieser Kommunikator sagt mit, dass du noch 100% menschlich bist. Mir wurde aufgetragen, dich zu unserer Zentrale zu führen. Wir reden über Vertrauen, wenn du mich verrätst, wirst du bezahlen. Übrigens, du kannst mich Blackbird nennen.",,"Nu, ĉi tiu interfono diras, ke vi estas centelcente homa. Mi estis ordonita lasi vin eniri, mi do fidos vin. Se vi perfidos min, vi pentos. Ha, parenteze, vi rajtas nomi min Merlo.","A ver, este intercomunicador me dice que eres 100% humano. Se me ha ordenado dejarte entrar, así que hablamos con confianza. Traicióname y te arrepentirás. Ah, por cierto, puedes llamarme Blackbird (Mirlo).","A ver, este intercomunicador me dice que eres 100% humano. Se ordenadó dejarte entrar, así que hablamos con confianza. Traicióname y te vas a arrepentir. Ah, por cierto, puedes llamarme Blackbird (Mirlo).","Kuule, tämä viestintälaite ilmaisee sinun olevan sataprosenttisesti ihminen. Minut on määrätty tuomaan sinut meidän joukkoomme; puhumme luottamuksellisesti. Petä minut ja saat luvan maksaa. Ja muuten, voit kutsua minua Blackbirdiksi.","Ecoute, ce communicateur me dit que tu est 100% humain. On m'a ordonnée de te ramener, c'est une question de confiance. Trahis-moi et tu paieras. Oh, et tu peux m'appeler Blackbird.","Figyelj, azt jelzi a jeladó, hogy 100%-ban ember vagy. Azt az utasítást kaptam ,hogy vigyelek be, de a bizalmammal játszol. Átversz és megfizetsz. Ja, és hívhatsz feketerigónak.","Ascolta, questa unità di comunicazione mi dice che sei 100% umano. Ho l'ordine di farti arrivare da noi, e quindi stiamo parlando di fiducia. Se mi tradisci la pagherai cara. Comunque, mi puoi chiamare Blackbird.","聞こえるか、この無線機がアナタは100%人間だと判断した。 私はアナタを信頼して良いとみて連れて来るよう命じられた、 -反乱への報酬は期待して良いわ。ああ、それと、私の名はブラックバードよ。","잘 들어, 이 통신기에 따르면 넌 100% 인간이야. 너를 믿어도 될 거 같으니 우리 편으로 끌어모으라는 지시를 받았어. 배신했다간 대가를 치를 거야. 아, 그리고, 날 블랙버드라고 불러줘.","Luister, deze com-unit vertelt me dat je 100% menselijk bent. Ik heb opdracht gekregen om je binnen te halen, we hebben het hier over vertrouwen. Verraad me en betaal. Oh, en trouwens, je mag me Blackbird noemen.","Hør her, denne kommunikasjonsenheten forteller meg at du er 100% menneskelig. Jeg har fått ordre om å hente deg inn, vi snakker om tillit her. Forråd meg og betal. Og forresten, du kan kalle meg Blackbird.","Słuchaj, to urządzenie mówi mi, że jesteś w 100% człowiekiem. Dostałem rozkaz, żeby cię sprowadzić, mówimy tu o zaufaniu. Zdradź mnie i zapłać. Aha, i przy okazji, możesz mi mówić Blackbird.","Ouça, este comunicador me diz que você é 100% humano. Recebi ordens para te trazer até aqui. É melhor você ser de confiança. Se você me trair, você me paga. Ah, a propósito, pode me chamar de Blackbird.",,"Ascultă, unitatea asta îmi spune că ești 100% uman. Am primit ordin să te arestez. Trădează-mă și plătești. Oh, apropo, îmi poți spune Blackbird.","Слушай — судя по этому передатчику, ты на сто процентов человек. Я получила приказ показать тебе дорогу к нам. Как видишь, тебе доверяют, но если предашь меня — пожалеешь. И да, обращайся ко мне «Чёрный дрозд». ",,"Dinle, bu iletişim ünitesi bana senin %100 insan olduğunu söylüyor. Seni buraya getirmem emredildi, burada güvenden bahsediyoruz. Bana ihanet edersen bedelini ödersin. Bu arada, bana Karatavuk diyebilirsin." -"Listen, this com-unit tells me that you're 100% human. You might be one of us, and maybe we can try and trust each other. Consider this test, there's a flamethrower in the Governor's mansion. Get it, and I'll lead you to us.",TXT_ILOG2,,strifeteaser,,"Poslyš, tento komunikátor mi říká, že jsi na sto procent člověkem. Mohl bys být jedním z nás a možná se můžeme pokusit navzájem si věřit. Ber tohle jako test: V guvernérově sídle je plamenomet. Najdi ho a zavedu tě k nám.","Hør, denne com-enhed fortæller mig, at du er 100% menneskelig. Du er måske en af os, og måske kan vi prøve at stole på hinanden. Overvej denne test: Der er en flammekaster i guvernørens palæ. Hent den, så fører jeg dig til os.","Hör zu, dieser Kommunikator sagt mit, dass du noch 100% menschlich bist. Du magst einer von uns sein und vielleicht können wir einander vertrauen. Betrachte dies als einen Test, da ist ein Flammenwerfer in der Villa des Gouverneurs. Hole ihn und ich führe dich zu uns.",,,"Escucha, esta unidad de comunicación me dice que eres 100% humano. Podrías ser uno de nosotros, y tal vez podamos intentar confiar el uno en el otro. Considera esto una prueba, hay un lanzallamas en la mansión del gobernador. Tómalo, y te llevará a nosotros",,"Kuule, tämä viestintälaite ilmaisee sinun olevan sataprosenttisesti ihminen. Saatat olla yksi meistä, ja ehkä voimme yrittää luottaa toisiimme. Voit pitää tätä testinä: Kuvernöörin kartanossa on liekinheitin. Hanki se, ja johdatan sinut luoksemme.","Ecoute, ce communicateur me dit que tu est 100% humain. Il se peut que tu est l'un des nôtres, on pourrait se faire confiance. Considère cela comme un test. Il y a un lance-flammes dans le manoir du gouverneur. Récupère le et je te mènerai à nous.","Figyelj, azt jelzi a jeladó, hogy 100%-ban ember vagy. Talán tényleg egy vagy közülünk, és megpróbálhatunk bízni egymásban. Vedd a következőt tesztnek: kapj fel egy lángszórót a Kormányzó kúriájából. Ha megszerzed, elvezetlek hozzánk.","Ascolta, questa unità di comunicazione mi dice che sei 100% umano. Potresti essere uno di noi, e forse possiamo fidarci l'uno dell'altro. Ti metterò alla prova, c'è un lanciafiamme nel palazzo del governatore. Prendilo, e ti condurrò da noi.","聞いて、このcom-unitはあなたが100%人間だということを教えてくれます。 +反乱への報酬は期待して良いわ。ああ、それと、私の名はブラックバードよ。","잘 들어, 이 통신기에 따르면 넌 100% 인간이야. 너를 믿어도 될 거 같으니 우리 편으로 끌어모으라는 지시를 받았어. 배신했다간 대가를 치를 거야. 아, 그리고, 날 블랙버드라고 불러줘.","Luister, deze com-unit vertelt me dat je 100% menselijk bent. Ik heb opdracht gekregen om je binnen te halen, we hebben het hier over vertrouwen. Verraad me en betaal. Oh, en trouwens, je mag me Blackbird noemen.","Hør her, denne kommunikasjonsenheten forteller meg at du er 100% menneskelig. Jeg har fått ordre om å hente deg inn, vi snakker om tillit her. Forråd meg og betal. Og forresten, du kan kalle meg Blackbird.","Słuchaj, to urządzenie mówi mi, że jesteś w 100% człowiekiem. Dostałem rozkaz, żeby cię sprowadzić, mówimy tu o zaufaniu. Zdradź mnie i zapłać. Aha, i przy okazji, możesz mi mówić Blackbird.","Ouça, este comunicador me diz que você é 100% humano. Recebi ordens para te trazer até aqui. É melhor você ser de confiança. Se você me trair, você me paga. Ah, a propósito, pode me chamar de Blackbird.",,"Ascultă, unitatea asta îmi spune că ești 100% uman. Am primit ordin să te arestez. Trădează-mă și plătești. Oh, apropo, îmi poți spune Blackbird.","Слушай — судя по этому передатчику, ты на сто процентов человек. Я получила приказ показать тебе дорогу к нам. Как видишь, тебе доверяют, но если предашь меня — пожалеешь. И да, обращайся ко мне «Чёрный дрозд». ",,"Lyssna, den här kommunikationsenheten säger mig att du är 100% mänsklig. Jag har blivit beordrad att ta in dig, vi pratar om förtroende här. Förråda mig och betala. Och förresten, du kan kalla mig Blackbird.","Dinle, bu iletişim ünitesi bana senin %100 insan olduğunu söylüyor. Seni buraya getirmem emredildi, burada güvenden bahsediyoruz. Bana ihanet edersen bedelini ödersin. Bu arada, bana Karatavuk diyebilirsin." +"Listen, this com-unit tells me that you're 100% human. You might be one of us, and maybe we can try and trust each other. Consider this test, there's a flamethrower in the Governor's mansion. Get it, and I'll lead you to us.",TXT_ILOG2,MAP33: After getting the hidden com unit in the tavern.,strifeteaser,,"Poslyš, tento komunikátor mi říká, že jsi na sto procent člověkem. Mohl bys být jedním z nás a možná se můžeme pokusit navzájem si věřit. Ber tohle jako test: V guvernérově sídle je plamenomet. Najdi ho a zavedu tě k nám.","Hør, denne com-enhed fortæller mig, at du er 100% menneskelig. Du er måske en af os, og måske kan vi prøve at stole på hinanden. Overvej denne test: Der er en flammekaster i guvernørens palæ. Hent den, så fører jeg dig til os.","Hör zu, dieser Kommunikator sagt mit, dass du noch 100% menschlich bist. Du magst einer von uns sein und vielleicht können wir einander vertrauen. Betrachte dies als einen Test, da ist ein Flammenwerfer in der Villa des Gouverneurs. Hole ihn und ich führe dich zu uns.",,"Nu, ĉi tiu interfono diras, ke vi estas centelcente homa. Vi eble estas unu el ni, tial ni povus fidi nin reciproke. Mi provos vin: estas flamĵetilo en la domego de la registo; prenu ĝin kaj mi gvidos vin al ni.","A ver, este intercomunicador me dice que eres 100% humano. Podrías ser uno de nosotros y tal vez podamos intentar confiar el uno en el otro. Te pondré a prueba: hay un lanzallamas en la mansión del gobernador; cógelo y te guiaré a nosotros.","A ver, este intercomunicador me dice que eres 100% humano. Podrías ser uno de nosotros y tal vez podamos intentar confiar el uno en el otro. Te pongo a prueba: hay un lanzallamas en la mansión del gobernador; agárralo y te voy a guiar a nosotros.","Kuule, tämä viestintälaite ilmaisee sinun olevan sataprosenttisesti ihminen. Saatat olla yksi meistä, ja ehkä voimme yrittää luottaa toisiimme. Voit pitää tätä testinä: Kuvernöörin kartanossa on liekinheitin. Hanki se, ja johdatan sinut luoksemme.","Ecoute, ce communicateur me dit que tu est 100% humain. Il se peut que tu est l'un des nôtres, on pourrait se faire confiance. Considère cela comme un test. Il y a un lance-flammes dans le manoir du gouverneur. Récupère le et je te mènerai à nous.","Figyelj, azt jelzi a jeladó, hogy 100%-ban ember vagy. Talán tényleg egy vagy közülünk, és megpróbálhatunk bízni egymásban. Vedd a következőt tesztnek: kapj fel egy lángszórót a Kormányzó kúriájából. Ha megszerzed, elvezetlek hozzánk.","Ascolta, questa unità di comunicazione mi dice che sei 100% umano. Potresti essere uno di noi, e forse possiamo fidarci l'uno dell'altro. Ti metterò alla prova, c'è un lanciafiamme nel palazzo del governatore. Prendilo, e ti condurrò da noi.","聞いて、このcom-unitはあなたが100%人間だということを教えてくれます。 あなたは私たちのうちの一人であるかもしれません、 そしておそらく私たちは互いに試みて信頼することができます。 このテストを考えてください、知事の邸宅に火炎放射器があります。 -それを手に入れてください","잘 들어, 이 통신기에 따르면 넌 100% 인간이야. 우리들은 너를 적극적으로 믿으니까 너도 같이 이해하고 신뢰했으면 좋겠어. 그러기 위해선 시험을 치러야 하는데, 총독의 건물 안에 화염방사기가 있어. 얻으면 우리들이 있는 곳을 알려줄게. ","Luister, deze com-unit vertelt me dat je 100% menselijk bent. Misschien bent u een van ons, en misschien kunnen we elkaar proberen te vertrouwen. Overweeg deze test, er is een vlammenwerper in het landhuis van de gouverneur. Haal het, en ik zal je naar ons toe leiden....","Denne kommunikasjonsenheten forteller meg at du er 100 % menneskelig. Du kan være en av oss, og kanskje vi kan prøve å stole på hverandre. Tenk på denne testen, det er en flammekaster i guvernørens hus. Ta den, så fører jeg deg til oss.","Słuchaj, ta jednostka mówi mi, że jesteś w 100% człowiekiem. Może jesteś jednym z nas i możemy spróbować sobie zaufać. Rozważ ten test, w rezydencji gubernatora jest miotacz ognia. Weź go, a zaprowadzę cię do nas.","Ouça, este comunicador me diz que você é 100% humano. Pode ser que você seja um de nós e talvez possamos tentar confiar um no outro. Considere isto um teste, há um lança-chamas na mansão do Governador. Entre lá e eu te guiarei até nós.",,"Ascultă, unitatea asta îmi spune că ești 100% uman. Poate putem avea încredere unii în ceilalți. Consideră acest test, e un aruncător de flăcări în complexul Guvernatorului. Ia-l, te va duce la noi.","Слушай — судя по этому передатчику, ты на сто процентов человек. Ты можешь присоединиться к нам, и мы должны доверять друг другу. Небольшое тебе испытание: в особняке губернатора есть огнемёт. Достань его, и я покажу тебе дорогу к нам.",,"Dinle, bu iletişim birimi bana senin %100 insan olduğunu söylüyor. Bizden biri olabilirsin ve belki birbirimize güvenmeyi deneyebiliriz. Bu testi düşün, Vali'nin malikanesinde bir alev makinesi var. Onu al, ben de seni bize götüreyim." -Head over to the old town hall. Macil had a tunnel built that lets us get in and out without the acolytes' knowledge.,TXT_ILOG3,MAP02: On the bridge with the com unit.,,,"Zamiř ke staré radnici. Macil nechal postavit tunel, který nám dovoluje se dostat dovnitř a ven bez vědomí akolytů.","Gå over til det gamle rådhus. Macil har fået bygget en tunnel, der lader os komme ind og ud uden acolytes' viden.","Geh zum alten Rathaus. Macil hat einen Tunnel bauen lassen, durch den wir dort reinkommen, ohne dass die Ministranten das mitbekommen.",,,Dirígete al antiguo ayuntamiento. Macil hizo construir un túnel que nos permite entrar y salir sin que los acólitos lo sepan.,,"Suuntaa kohti vanhaa kaupungintaloa. Macil oli rakennuttanut tunnelin, jonka avulla voimme päästä sisään ja ulos akoluuttien tietämättä.",Dirige-toi vers l'ancienne mairie. Macil a fait construire un tunnel qui nous permet d'y entrer sans que l'Ordre nous remarque.,"Vedd az utad a régi városfalhoz. Macil épített egy föld alatti alagutat, amin keresztül a ministránsok tudta nélkül tudunk ki és be járkálni.",Raggiungi il vecchio Municipio. Macil ha fatto costruire un tunnel che ci fa entrare ed uscire senza che gli accoliti lo sappiano.,"旧市庁舎に入る。そこにはマシルがアコライトに関わる者を欺く為の -抜け道を用意している。",구 시청으로 향해. 오더가 이곳을 폭격한 후에 마실이 그곳에 아콜라이트들이 모르는 통행로를 만들어놨어.,Ga naar het oude stadhuis. Macil heeft een tunnel laten bouwen die ons zonder medeweten van de acolieten in en uit kan stappen.,Gå til det gamle rådhuset. Macil fikk bygget en tunnel som lar oss komme inn og ut uten at akolyttene vet om det.,"Udaj się do starego ratusza. Macil kazał wybudować tunel, który pozwoli nam wejść i wyjść bez wiedzy akolitów.",Vá até a antiga prefeitura. Macil construiu um túnel que permite que a gente entre e saia sem os acólitos perceberem.,,Du-te în vechia hală a orașului. Macil a construit un tunel care ne permite să ne deplasăm fără ca acoliții să știe.,"Отправляйся к старой ратуше. Мэйсил построил там туннель, который позволяет нам входить и выходить без ведома служителей.",,"Eski belediye binasına gidin. Macil, yardımcıların haberi olmadan girip çıkmamızı sağlayan bir tünel inşa ettirdi." -"Go through the door on your left, then the one on the right. The guard's name is Geoff. Tell him you need gold.",TXT_ILOG4,MAP02: In hall town with the com unit.,,,"Projdi dveřmi nalevo a pak napravo. Hlídač se jmenuje Geoff. Řekni mu, že potřebuješ zlato.","Gå gennem døren til venstre og derefter gennem den til højre. Vagtens navn er Geoff. Sig til ham, at du har brug for guld.","Geh durch die linke Tür, dann durch die rechte. Der Wächter heißt Geoff. Sag ihm du brauchst Gold.",,"Iru tra la maldekstra pordo kaj poste tra la dekstra. La nomo de la gardisto estas Geoff; diru al li, ke vi bezonas oron.",Ve por la puerta izquierda y luego por la derecha. El guardia se llama Geoff; dile que necesitas oro.,,"Kulje sinusta katsottuna vasemmalla puolella olevan oven läpi, sitten oikeanpuoleisesta ovesta. Vartijan nimi on Geoff. Kerro hänelle tarvitsevasi kultaa.",Passe par la porte à gauche puis celle à droite. Le garde s'appelle Geoff. Dis-lui que tu as besoin d'argent.,"Menj át a bal oldali ajtón, majd a jobb oldalin. Az őr neve Geoff. Mondd neki, hogy aranyra van szükséged.","Vai oltre la porta alla tua sinistra, e poi la porta alla tua destra. Il nome della guardia è Geoff. Digli che ti serve dell'oro.","すぐ左のドアを通り、右のドアから小部屋に入るんだ。 -見張りの名はジェフ。金が必要だ と言えば通じる。","네 왼쪽의 문으로 들어간 후, 다시 오른쪽의 문으로 가. 경비의 이름은 제프야. 그에게 골드가 필요하다고 얘기해.","Ga door de deur links van je, dan de deur rechts. De bewaker heet Geoff. Zeg hem dat je goud nodig hebt.","Gå gjennom døren til venstre, så den til høyre. Vakten heter Geoff. Si at du trenger gull.","Przejdź przez drzwi po lewej, a następnie te po prawej. Strażnik ma na imię Geoff. Powiedz mu, że potrzebujesz złota.",Vá pela porta à sua esquerda e depois a da direita. O nome do guarda é Geoff. Diga a ele que você precisa de ouro.,,"Intră pe ușa din stânga, apoi cea din dreapta. Numele paznicului e Geoff. Spune-i că-ți trebuie aur.","Пройди за левую дверь, затем иди направо. Стражника зовут Джефф. Скажи ему, что тебе нужно золото.",,"Solundaki kapıdan geç, sonra sağdakinden. Muhafızın adı Geoff. Ona altına ihtiyacın olduğunu söyle." -"Don't enter the town hall. It's not safe anymore, our cover's been blown. Kill all the big robots, the ""Crusaders"" and I'll guide you to us.",TXT_ILOG5,,strifeteaser,,"Nechoď do radnice, už není bezpečná. Byli jsme odhaleni. Zabij všechny ty velké roboty, Křižáky, a pak tě nasměruju k Macilovi.","Gå ikke ind på rådhuset. Det er ikke sikkert længere, vores dække er blevet afsløret. Dræb alle de store robotter, ""Crusaders"", og jeg vil guide dig til os.","Geh nicht ins Rathaus. Da ist es nicht mehr sicher, unsere Tarnung ist aufgeflogen. Erledige die großen Roboter, die „Ordensritter“ und ich führe dich zu uns.",,,"No entres en el ayuntamiento: nos han descubierto, o sea que ya no es seguro. Mata a todos los robots grandes, los «Cruzados» y te guiaré a nosotros.",,"Älä mene kaupungintaloon. Se ei ole enää turvallista; olemme paljastuneet. Tuhoa kaikki isot robotit, ""ristiretkeläiset"", ja opastan sinut luoksemme.","N'entre pas dans la mairie, ce n'est plus sûr. Notre couverture ne marche plus. Détruis tous les gros robots, les « Croisés » et je te mènerai à nous.","Ne menj be a városházába. Már nem biztonságos, lelepleződtünk. Öldd meg az összes nagy robotot, a Kereszteseket, és elvezetlek hozzánk.","Non entrare nel municipio. Non è più sicuro, la nostra copertura è saltata. Distruggi tutti i grossi robot, i ""Crociati"", e ti condurrò a noi.","町にいるフロントへの武器供給者であるイラールの元を訪ねる。 -彼は武器屋の隣のドアに居る。それで、知事と会う為にマシルから貰ったキーを使う。",아직 시청으로 가지 마. 우리가 발각된 상태라 위험하다고. 거대한 '크루세이더' 로봇들을 먼저 처리해. 그다음에 내가 안내해줄게.,"Ga het stadhuis niet binnen. Het is niet meer veilig, onze dekmantel is opgeblazen. Dood alle grote robots, de ""Kruisvaarders"" en ik zal je naar ons toe leiden.","Ikke gå inn i rådhuset. Det er ikke trygt lenger. Vi er avslørt. Drep alle de store robotene, ""korsfarerne"", så skal jeg lede dere til oss.","Nie wchodź do ratusza. To już nie jest bezpieczne, nasza przykrywka została zdmuchnięta. Zabij wszystkie duże roboty, ""Crusaders"", a ja zaprowadzę cię do nas.","Não entre na prefeitura. Não é mais seguro, fomos descobertos. Mate esses robozões, os ""Cruzados"" e eu te guiarei até nós.",,"Nu intra în hala orașului. Nu mai e sigură, s-a dus acoperirea noastră. Distruge toți roboții mari, Cruciații te vor conduce la noi.","Не ходи к ратуше. Наше убежище было разгромлено, теперь там небезопасно. Перебей этих больших роботов, «крестоносцев», и я покажу тебе дорогу к нам. ",,"Belediye binasına girme. Artık güvenli değil, kimliğimiz açığa çıktı. Bütün büyük robotları, ""Haçlıları"" öldürün, ben de sizi bize yönlendireyim." -"The door next to the weapons shop will open once all the Crusaders are dead. Inside the store room there's a teleporter, use it, and it'll bring you to us",TXT_ILOG6,,strifeteaser,,"Dveře vedle obchodu se zbraněmi se otevřou když budou všichni Křižáci zničeni. Uvnitř je teleportér, použij ho a dostaneš se k nám.","Døren ved siden af våbenbutikken vil åbne sig, når alle Crusaders er døde. Inde i lagerrummet er der en teleporter, brug den, og den vil føre dig til os","Die Tür neben dem Waffengeschäft wird sich öffnen, wenn alle Ordensritter tot sind. Dahinter ist ein Teleporter. Benutze ihn, er bringt dich zu uns.",,,"La puerta junto a la tienda de armas se abrirá en cuanto todos los cruzados estén muertos. Dentro del almacén hay un teletransporte, úsalo, y te traerá a nosotros.","La puerta junto a la tienda de armamento se abrirá una vez que todos los cruzados estén muertos. Adentro hay un teleporte, úsalo y te traerá a nosotros","Asekaupan viereinen ovi aukeaa, kun kaikki ristiretkeläiset on tuhottu. Varastohuoneessa on kaukosiirrin. Sitä käyttämällä pääset luoksemme.","La porte à côté du magasin d'armes s'ouvrira quand tous les croisés seront détruits. A l'intérieur de la salle de stockage se trouve un téléporteur, utilise-le pour nous rejoindre.","A fegyverbolt melletti ajtó ki fog nyílni, miután az összes Kresztes meghalt. Találsz a raktáron belül egy teleportot, ami ide fog hozni hozzánk.","La porta accanto al negozio delle armi si aprirà non appena tutti i Crociati sono distrutti. Oltre quella porta c'è un teletrasporto, usalo e ti porterà da noi.","私が知事について知っていることは、町の中央で双方を遊ばせてる様だ。 -ソイツがここいらを'マンション'と呼んでいる。",크루세이더들을 전부 처리하면 무기상 옆의 문이 열릴 거야. 그 안에 우리 기지로 통하는 텔레포터가 있으니 그걸 타.,"De deur naast de wapenwinkel gaat open als alle kruisvaarders dood zijn. In de opslagruimte staat een teleporter, gebruik die, en die brengt je naar ons toe.","Døren ved siden av våpenbutikken åpnes når alle korsfarerne er døde. Inne i lagerrommet er det en teleporter, bruk den, og den vil føre deg til oss...","Drzwi obok sklepu z bronią otworzą się, gdy wszyscy Crusaders będą martwi. Wewnątrz pomieszczenia ze sklepem jest teleporter, użyj go, a zaprowadzi cię do nas",A porta próxima à loja de armas abrirá assim que todos os Cruzados estiverem mortos. Dentro do depósito tem um teletransportador. Entre nele e ele o levará até nós.,,"Ușa de lângă magazinul de arme se va deschide odată ce toți Cruciații sunt morți. Înăuntru e un teleportor, ia-l, te va duce la noi.","Дверь возле оружейного магазина откроется, когда все крестоносцы будут уничтожены. На складе ты найдёшь телепорт. Используй его — он доставит тебя к нам.",,"Tüm Haçlılar öldüğünde silah dükkanının yanındaki kapı açılacak. Dükkanın içinde bir ışınlayıcı var, onu kullan ve seni bize getirecek" -"The door next to the weapons shop will open once all the Crusaders are dead. Inside the store room there's a teleporter, use it, and it'll bring you to us.",TXT_ILOG7,,strifeteaser,,"Dveře vedle obchodu se zbraněmi se otevřou když budou všichni Křižáci zničeni. Uvnitř je teleportér, použij ho a dostaneš se k nám.","Døren ved siden af våbenbutikken åbnes, når alle korsfarerne er døde. Inde i lagerrummet er der en teleporter, brug den, og den vil bringe dig til os.","Die Tür neben dem Waffengeschäft wird sich öffnen, wenn alle Ordensritter tot sind. Dahinter ist ein Teleporter. Benutze ihn, er bringt dich zu uns.",,,"La puerta junto a la tienda de armas se abrirá en cuanto todos los cruzados estén muertos. Dentro del almacén hay un teletransporte, úsalo, y te traerá a nosotros.","La puerta junto a la tienda de armamento se abrirá una vez que todos los cruzados estén muertos. Adentro hay un teleporte, úsalo y te traerá a nosotros","Asekaupan viereinen ovi aukeaa, kun kaikki ristiretkeläiset on tuhottu. Varastohuoneessa on kaukosiirrin. Sitä käyttämällä pääset luoksemme.","La porte à côté du magasin d'armes s'ouvrira quand tous les croisés seront détruits. A l'intérieur de la salle de stockage se trouve un téléporteur, utilise-le pour nous rejoindre.","A fegyverbolt melletti ajtó ki fog nyílni, miután az összes Kresztes meghalt. Találsz a raktáron belül egy teleportot, ami ide fog hozni hozzánk.","La porta accanto al negozio delle armi si aprirà non appena tutti i Crociati sono distrutti. Oltre quella porta c'è un teletrasporto, usalo e ti porterà da noi.","私が知事について知っていることは、町の中央で双方を遊ばせてる様だ。 -ソイツがここいらを'マンション'と呼んでいる。",크루세이더들을 전부 처리하면 무기상 옆의 문이 열릴 거야. 그 안에 우리 기지로 통하는 텔레포터가 있으니 그걸 타.,"De deur naast de wapenwinkel gaat open als alle kruisvaarders dood zijn. In de opslagruimte staat een teleporter, gebruik die, en die brengt je naar ons toe.","Døren ved siden av våpenbutikken åpnes når alle korsfarerne er døde. Inne i lagerrommet er det en teleporter, bruk den, og den vil bringe deg til oss.","Drzwi obok sklepu z bronią otworzą się po śmierci wszystkich krzyżowców. Wewnątrz pomieszczenia sklepowego znajduje się teleporter, użyj go, a przeniesie cię do nas.",A porta próxima à loja de armas abrirá assim que todos os Cruzados estiverem mortos. Dentro do depósito tem um teletransportador. Entre nele e ele o levará até nós.,,"Ușa de lângă magazinul de arme se va deschide odată ce toți Cruciații sunt morți. Înăuntru e un teleportor, ia-l, te va duce la noi.","Дверь возле оружейного магазина откроется, когда все крестоносцы будут уничтожены. На складе ты найдёшь телепорт. Используй его — он доставит тебя к нам.",,"Tüm Haçlılar öldüğünde silah dükkanının yanındaki kapı açılacak. Dükkanın içinde bir ışınlayıcı var, onu kullanın ve sizi bize getirecek." -"Kill as many of the big robots, Crusaders, as you can. When you're done, I'll guide you to Macil",TXT_ILOG8,,strifeteaser,,"Znič tolik těch velkých robotů, Křižáků, kolik dokážeš. Až budeš hotov, dovedu tě k Macilovi.","Dræb så mange af de store robotter, Crusaders, som du kan. Når du er færdig, vil jeg guide dig til Macil","Erledige so viele von den großen Robotern - „Ordensrittern“, wie möglich. Wann das erledigt ist, führe ich dich zu Macil.",,,"Mata a tantos de los robots grandes, los cruzados, que puedas. Cuando termines, te guiaré hasta Macil.","Mata a tantos robots gigantes como puedas. Cuando termines, te guiaré a Macil","Tuhoa jättiroboteista, ristiretkeläisistä, niin monta kuin pystyt. Kun olet valmis, opastan sinut Macilin luokse.","Détruis autant des gros robots, les croisés, que tu peux, et je te mènerai à Macil.","Ölj meg annyi nagy robotot és keresztest amennyit csak tudsz. Ha kész vagy, elvezetlek Macilhoz.","Distruggi tutti i Crociati che vedi. Non appena hai finito, ti condurrò da Macil.",,"저 거대한 '크루세이더' 로봇들을 최대한 처리해. 상황이 정리되면, 내가 너를 마실에게 데려다줄게.","Dood zoveel mogelijk van de grote robots, kruisvaarders, als je kunt. Als je klaar bent, begeleid ik je naar Macil...","Drep så mange av de store robotene, korsfarerne, som du kan. Når du er ferdig, skal jeg vise deg veien til Macil.","Zabij jak najwięcej dużych robotów, Crusaders, jak tylko możesz. Gdy skończysz, zaprowadzę cię do Macila","Mate o máximo desses robos possível. Quando terminar, eu te guiarei ao Macil.",,"Distruge cât mai mulți roboți, Cruciați, pe cât poți. Când ești gata, te voi duce la Macil.","Убей столько больших роботов, — крестоносцев, — сколько сможешь. Когда закончишь, я приведу тебя к Мэйсилу.",,"Büyük robotlardan, Haçlılardan, öldürebildiğin kadarını öldür. İşiniz bittiğinde, sizi Macil'e götüreceğim." -"Go through the door, and talk to Macil.",TXT_ILOG9,,strifeteaser,,Projdi dveřmi a promluv si s Macilem.,"Gå gennem døren, og tal med Macil.",Geh durch die Tür und rede mit Macil.,,,Ve por la puerta y habla con Macil.,,Kulje ovesta ja puhu Macilille.,Traverse cette porte et va parler à Macil.,"Az ajtó mögött már vár Macil, beszélj vele.","Attraversa la porta, e vai a parlare con Macil.",ダーウィンを始末したら耳を知事に渡す。,저 문을 지나서 마실하고 대화를 해봐.,"Ga door de deur, en praat met Macil.",Gå gjennom døren og snakk med Macil.,Przejdź przez drzwi i porozmawiaj z Macil.,Passe pela porta e fale com o Macil.,,Intră pe ușă și du-te la Macil.,Обратись к Мэйсилу. Он за этой дверью.,,Kapıdan geçin ve Macil ile konuşun. -"Find the power tap on the mains, and shut it off. Bring something back to the Governor as proof. Find MacGuffin, and talk to him.",TXT_ILOG10,"MAP02: After accepting ""messy"" chore and leaving Mourel's room.",,,Najdi stáčedlo energie na elektrické síti a vypni jej. Přines něco guvernérovi jako důkaz. Najdi MacGuffina a promluv s ním.,"Find strømhanen på hovedledningen, og luk den. Tag noget med tilbage til guvernøren som bevis. Find MacGuffin, og tal med ham.",Finde die Stromanzapfung und schalte sie ab. Bringe einen Beweis zum Gouverneur. Finde MacGuffin und rede mit ihm. ,,,Encuentra la intervención en la red eléctrica y destrúyela. Llévale algo al gobernador como prueba. Encuentra a MacGuffin y habla con él.,,Etsi verkkovirran piilokytkentä ja katkaise se. Tuo kuvernöörille jotain todisteeksi. Etsi MacGuffin ja puhu hänen kanssaan.,Trouve la connection pirate sur le transformateur et désactive la. Amène quelque chose au gouverneur comme preuve. Trouve MacGuffin et parle-lui.,"Keresd meg a fővonalon az áramkapcsolót, és kapcsold ki. Hozz vissza valamit a kormányzótól bizonyítékként. Keresd meg MacGuffint, és beszélj vele.","Trova l'aggeggio che sta venendo usato per rubare energia alla rete, e distruggilo. Porta dei resti al governatore come prova. Trova e parla con MacGuffin.","電力盗用の場所を見つけ、それを止める。 -知事に渡す証拠も必要だ。マクガフィンと話をつける。",주 동력선 어딘가에 있는 추출기를 처리해. 총독에게 전할 증거물도 챙기고. 맥거핀을 찾아서 대화해 봐.,Zoek het stopcontact op het lichtnet en zet het uit. Breng iets terug naar de gouverneur als bewijs. Zoek MacGuffin en praat met hem.,"Finn strømkranen på strømnettet, og slå den av. Ta med noe tilbake til guvernøren som bevis. Finn MacGuffin, og snakk med ham.",Znajdź kurek z prądem w sieci i wyłącz go. Przynieś coś gubernatorowi jako dowód. Znajdź MacGuffina i porozmawiaj z nim.,Encontre a ligação pirata no transformador e desligue ela. Traga algo de volta para o Governador como prova. Encontre o MacGuffin e fale com ele.,,"Găsește comutatorul de energie, și oprește-l. Du ceva înapoi la Guvernator drept dovadă. Găsește-l pe MacGuffin, și vorbește cu el.",Найди нелегальное подключение к линии электропередачи и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства. Найди Макгаффина и поговори с ним.,,Şebekedeki güç musluğunu bulun ve kapatın. Kanıt olarak Vali'ye bir şey getirin. MacGuffin'i bul ve onunla konuş. -"Find the power tap on the mains, and shut it off. Bring something back to the Governor as proof. Find MacGuffin, and talk to him. He's up by the sewage treatment plant, in the ""bum hole"", down the stairs.",TXT_ILOG11,"MAP02: After accepting ""messy"" chore and leaving Mourel's mansion.",,,"Najdi stáčedlo energie na elektrické síti a vypni jej. Přines něco guvernérovi jako důkaz. Najdi MacGuffina a promluv s ním. Je u čističky, v „zadnici“ pod schody.","Find strømhanen på hovedledningen, og luk den. Tag noget med tilbage til guvernøren som bevis. Find MacGuffin, og tal med ham. Han er oppe ved rensningsanlægget, i ""bum-hullet"", nede ad trappen.","Finde die Stromanzapfung und schalte sie ab. Bringe einen Beweis zum Gouverneur. Finde MacGuffin und rede mit ihm. Er ist in der Nähe der Kläranlage im „Pennerloch“, die Treppe runter.",,,"¡Idiota! Has apagado la energía de los circuitos de interferencia que usamos para ocultarle nuestra base a La Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ya! Luego vuelve con el gobernador y dale el acoplador roto.",,"Etsi verkkovirran piilokytkentä ja katkaise se. Tuo kuvernöörille jotain todisteeksi. Etsi MacGuffin ja puhu hänen kanssaan. Hän majailee jätelaitoksella ""pepunreiässä"" rappuset alas.","Trouve la connection pirate sur le transformateur et désactive la. Amène quelque chose au gouverneur comme preuve. Trouve MacGuffin et parle-lui. Il se trouve dans la centrale de traitement des eaux, dans le « trou à rats » en bas des escaliers.","Keresd meg a fővonalon az áramkapcsolót, és kapcsold ki. Hozz vissza valamit a kormányzótól bizonyítékként. Keresd fel MacGuffint és beszélj vele. Ott van a szennyvíz tisztítónál, ha lemész a lépcsőn, lent a ""kotorékban"".","Trova il marchingegno che sta venendo usato per rubare energia alla rete, e distruggilo. Porta dei resti al governatore come prova. Trova e parla con MacGuffin. Lui bazzica dalle parti dell'impianto fognario, oltre delle scale.","電力盗用の場所を見つけ、それを止める。 +それを手に入れてください","잘 들어, 이 통신기에 따르면 넌 100% 인간이야. 우리들은 너를 적극적으로 믿으니까 너도 같이 이해하고 신뢰했으면 좋겠어. 그러기 위해선 시험을 치러야 하는데, 총독의 건물 안에 화염방사기가 있어. 얻으면 우리들이 있는 곳을 알려줄게. ","Luister, deze com-unit vertelt me dat je 100% menselijk bent. Misschien bent u een van ons, en misschien kunnen we elkaar proberen te vertrouwen. Overweeg deze test, er is een vlammenwerper in het landhuis van de gouverneur. Haal het, en ik zal je naar ons toe leiden....","Denne kommunikasjonsenheten forteller meg at du er 100 % menneskelig. Du kan være en av oss, og kanskje vi kan prøve å stole på hverandre. Tenk på denne testen, det er en flammekaster i guvernørens hus. Ta den, så fører jeg deg til oss.","Słuchaj, ta jednostka mówi mi, że jesteś w 100% człowiekiem. Może jesteś jednym z nas i możemy spróbować sobie zaufać. Rozważ ten test, w rezydencji gubernatora jest miotacz ognia. Weź go, a zaprowadzę cię do nas.","Ouça, este comunicador me diz que você é 100% humano. Pode ser que você seja um de nós e talvez possamos tentar confiar um no outro. Considere isto um teste, há um lança-chamas na mansão do Governador. Entre lá e eu te guiarei até nós.",,"Ascultă, unitatea asta îmi spune că ești 100% uman. Poate putem avea încredere unii în ceilalți. Consideră acest test, e un aruncător de flăcări în complexul Guvernatorului. Ia-l, te va duce la noi.","Слушай — судя по этому передатчику, ты на сто процентов человек. Ты можешь присоединиться к нам, и мы должны доверять друг другу. Небольшое тебе испытание: в особняке губернатора есть огнемёт. Достань его, и я покажу тебе дорогу к нам.",,"Den här kommunikationsenheten säger mig att du är 100 procent mänsklig. Du kanske är en av oss och vi kanske kan försöka lita på varandra. Tänk på det här testet: Det finns en flamkastare i guvernörens herrgård. Hämta den, så leder jag dig till oss.","Dinle, bu iletişim birimi bana senin %100 insan olduğunu söylüyor. Bizden biri olabilirsin ve belki birbirimize güvenmeyi deneyebiliriz. Bu testi düşün, Vali'nin malikanesinde bir alev makinesi var. Onu al, ben de seni bize götüreyim." +Head over to the old town hall. Macil had a tunnel built that lets us get in and out without the acolytes' knowledge.,TXT_ILOG3,MAP02: On the bridge with the com unit.,,,"Zamiř ke staré radnici. Macil nechal postavit tunel, který nám dovoluje se dostat dovnitř a ven bez vědomí akolytů.","Gå over til det gamle rådhus. Macil har fået bygget en tunnel, der lader os komme ind og ud uden acolytes' viden.","Geh zum alten Rathaus. Macil hat einen Tunnel bauen lassen, durch den wir dort reinkommen, ohne dass die Ministranten das mitbekommen.",,Iru al la antikva urbodomo (Town Hall): Macil ordonis konstrui tunelon por kaj eniri kaj eliri senscie de la akolitoj.,Dirígete al antiguo ayuntamiento (Town Hall): Macil hizo construir un túnel para entrar y salir sin que los acólitos se enteren.,,"Suuntaa kohti vanhaa kaupungintaloa. Macil oli rakennuttanut tunnelin, jonka avulla voimme päästä sisään ja ulos akoluuttien tietämättä.",Dirige-toi vers l'ancienne mairie. Macil a fait construire un tunnel qui nous permet d'y entrer sans que l'Ordre nous remarque.,"Vedd az utad a régi városfalhoz. Macil épített egy föld alatti alagutat, amin keresztül a ministránsok tudta nélkül tudunk ki és be járkálni.",Raggiungi il vecchio Municipio. Macil ha fatto costruire un tunnel che ci fa entrare ed uscire senza che gli accoliti lo sappiano.,"旧市庁舎に入る。そこにはマシルがアコライトに関わる者を欺く為の +抜け道を用意している。",구 시청으로 향해. 오더가 이곳을 폭격한 후에 마실이 그곳에 아콜라이트들이 모르는 통행로를 만들어놨어.,Ga naar het oude stadhuis. Macil heeft een tunnel laten bouwen die ons zonder medeweten van de acolieten in en uit kan stappen.,Gå til det gamle rådhuset. Macil fikk bygget en tunnel som lar oss komme inn og ut uten at akolyttene vet om det.,"Udaj się do starego ratusza. Macil kazał wybudować tunel, który pozwoli nam wejść i wyjść bez wiedzy akolitów.",Vá até a antiga prefeitura. Macil construiu um túnel que permite que a gente entre e saia sem os acólitos perceberem.,,Du-te în vechia hală a orașului. Macil a construit un tunel care ne permite să ne deplasăm fără ca acoliții să știe.,"Отправляйся к старой ратуше. Мэйсил построил там туннель, который позволяет нам входить и выходить без ведома служителей.",,Gå till det gamla stadshuset. Macil lät bygga en tunnel som gör att vi kan ta oss in och ut utan acolytternas vetskap.,"Eski belediye binasına gidin. Macil, yardımcıların haberi olmadan girip çıkmamızı sağlayan bir tünel inşa ettirdi." +"Go through the door on your left, then the one on the right. The guard's name is Geoff. Tell him you need gold.",TXT_ILOG4,MAP02: In town hall with the com unit.,,,"Projdi dveřmi nalevo a pak napravo. Hlídač se jmenuje Geoff. Řekni mu, že potřebuješ zlato.","Gå gennem døren til venstre og derefter gennem den til højre. Vagtens navn er Geoff. Sig til ham, at du har brug for guld.","Geh durch die linke Tür, dann durch die rechte. Der Wächter heißt Geoff. Sag ihm du brauchst Gold.",,"Iru tra la maldekstra pordo kaj poste tra la dekstra. La nomo de la gardisto estas Geoff; diru al li, ke vi bezonas oron.",Ve por la puerta izquierda y luego por la derecha. El guardia se llama Geoff; dile que necesitas oro.,,"Kulje sinusta katsottuna vasemmalla puolella olevan oven läpi, sitten oikeanpuoleisesta ovesta. Vartijan nimi on Geoff. Kerro hänelle tarvitsevasi kultaa.",Passe par la porte à gauche puis celle à droite. Le garde s'appelle Geoff. Dis-lui que tu as besoin d'argent.,"Menj át a bal oldali ajtón, majd a jobb oldalin. Az őr neve Geoff. Mondd neki, hogy aranyra van szükséged.","Vai oltre la porta alla tua sinistra, e poi la porta alla tua destra. Il nome della guardia è Geoff. Digli che ti serve dell'oro.","すぐ左のドアを通り、右のドアから小部屋に入るんだ。 +見張りの名はジェフ。金が必要だ と言えば通じる。","네 왼쪽의 문으로 들어간 후, 다시 오른쪽의 문으로 가. 경비의 이름은 제프야. 그에게 골드가 필요하다고 얘기해.","Ga door de deur links van je, dan de deur rechts. De bewaker heet Geoff. Zeg hem dat je goud nodig hebt.","Gå gjennom døren til venstre, så den til høyre. Vakten heter Geoff. Si at du trenger gull.","Przejdź przez drzwi po lewej, a następnie te po prawej. Strażnik ma na imię Geoff. Powiedz mu, że potrzebujesz złota.",Vá pela porta à sua esquerda e depois a da direita. O nome do guarda é Geoff. Diga a ele que você precisa de ouro.,,"Intră pe ușa din stânga, apoi cea din dreapta. Numele paznicului e Geoff. Spune-i că-ți trebuie aur.","Пройди за левую дверь, затем иди направо. Стражника зовут Джефф. Скажи ему, что тебе нужно золото.",,Gå genom dörren till vänster och sedan genom dörren till höger. Vaktens namn är Geoff. Säg till honom att du behöver guld.,"Solundaki kapıdan geç, sonra sağdakinden. Muhafızın adı Geoff. Ona altına ihtiyacın olduğunu söyle." +"Don't enter the town hall. It's not safe anymore, our cover's been blown. Kill all the big robots, the ""Crusaders"" and I'll guide you to us.",TXT_ILOG5,,strifeteaser,,"Nechoď do radnice, už není bezpečná. Byli jsme odhaleni. Zabij všechny ty velké roboty, Křižáky, a pak tě nasměruju k Macilovi.","Gå ikke ind på rådhuset. Det er ikke sikkert længere, vores dække er blevet afsløret. Dræb alle de store robotter, ""korsfarerne"", så viser jeg dig vej til os.","Geh nicht ins Rathaus. Da ist es nicht mehr sicher, unsere Tarnung ist aufgeflogen. Erledige die großen Roboter, die „Ordensritter“ und ich führe dich zu uns.",,"Ne eniru la urbodomon: ili detruis niajn kovrilojn, ĝi do ne plu estas sekura. Detruu ĉiujn robotegojn, alinome Krucistojn, kaj mi gvidos vin al ni.","No entres en el ayuntamiento: nos han descubierto, o sea que ya no es seguro. Mata a todos los robots grandes, o sea, a los Cruzados, y te guiaré a nosotros.","No entres al ayuntamiento: nos descubrieron, o sea que ya no es seguro. Mata a todos los robots grandes, o sea, a los Cruzados, y te guío a nosotros.","Älä mene kaupungintaloon. Se ei ole enää turvallista; olemme paljastuneet. Tuhoa kaikki isot robotit, ""ristiretkeläiset"", ja opastan sinut luoksemme.","N'entre pas dans la mairie, ce n'est plus sûr. Notre couverture ne marche plus. Détruis tous les gros robots, les « Croisés » et je te mènerai à nous.","Ne menj be a városházába. Már nem biztonságos, lelepleződtünk. Öldd meg az összes nagy robotot, a Kereszteseket, és elvezetlek hozzánk.","Non entrare nel municipio. Non è più sicuro, la nostra copertura è saltata. Distruggi tutti i grossi robot, i ""Crociati"", e ti condurrò a noi.","町にいるフロントへの武器供給者であるイラールの元を訪ねる。 +彼は武器屋の隣のドアに居る。それで、知事と会う為にマシルから貰ったキーを使う。",아직 시청으로 가지 마. 우리가 발각된 상태라 위험하다고. 거대한 '크루세이더' 로봇들을 먼저 처리해. 그다음에 내가 안내해줄게.,"Ga het stadhuis niet binnen. Het is niet meer veilig, onze dekmantel is opgeblazen. Dood alle grote robots, de ""Kruisvaarders"" en ik zal je naar ons toe leiden.","Ikke gå inn i rådhuset. Det er ikke trygt lenger. Vi er avslørt. Drep alle de store robotene, ""korsfarerne"", så skal jeg lede dere til oss.","Nie wchodź do ratusza. To już nie jest bezpieczne, nasza przykrywka została zdmuchnięta. Zabij wszystkie duże roboty, ""krzyżowców"", a ja zaprowadzę cię do nas.","Não entre na prefeitura. Não é mais seguro, fomos descobertos. Mate esses robozões, os ""Cruzados"" e eu te guiarei até nós.",,"Nu intra în hala orașului. Nu mai e sigură, s-a dus acoperirea noastră. Distruge toți roboții mari, Cruciații te vor conduce la noi.","Не ходи к ратуше. Наше убежище было разгромлено, теперь там небезопасно. Перебей этих больших роботов, «крестоносцев», и я покажу тебе дорогу к нам. ",,"Gå inte in i stadshuset. Det är inte säkert längre, vår täckmantel har avslöjats. Döda alla stora robotar, ""Korsriddarna"", så ska jag guida dig till oss.","Belediye binasına girme. Artık güvenli değil, kimliğimiz açığa çıktı. Bütün büyük robotları, ""Haçlıları"" öldürün, ben de sizi bize yönlendireyim." +"The door next to the weapons shop will open once all the Crusaders are dead. Inside the store room there's a teleporter, use it, and it'll bring you to us",TXT_ILOG6,"MAP33: In front of ""Irale's shop"" with the com unit and the Crusaders dead.",strifeteaser,,"Dveře vedle obchodu se zbraněmi se otevřou když budou všichni Křižáci zničeni. Uvnitř je teleportér, použij ho a dostaneš se k nám.","Døren ved siden af våbenbutikken vil åbne sig, når alle korsfarerne er døde. Inde i lagerrummet er der en teleporter, brug den, og den vil føre dig til os.","Die Tür neben dem Waffengeschäft wird sich öffnen, wenn alle Ordensritter tot sind. Dahinter ist ein Teleporter. Benutze ihn, er bringt dich zu uns.",,Detrui la Krucistojn malfermis la pordon apud la armilvendejo. Estas teleportilo en tiu stokejo; uzu ĝin.,La puerta junto a la armería se ha abierto al matar a los cruzados. Dentro de ese almacén hay un teletransporte; úsalo.,La puerta junto a la armería se abrió al matar a los cruzados. Adentro de ese almacén hay un teletransporte; úsalo.,"Asekaupan viereinen ovi aukeaa, kun kaikki ristiretkeläiset on tuhottu. Varastohuoneessa on kaukosiirrin. Sitä käyttämällä pääset luoksemme.","La porte à côté du magasin d'armes s'ouvrira quand tous les croisés seront détruits. A l'intérieur de la salle de stockage se trouve un téléporteur, utilise-le pour nous rejoindre.","A fegyverbolt melletti ajtó ki fog nyílni, miután az összes Kresztes meghalt. Találsz a raktáron belül egy teleportot, ami ide fog hozni hozzánk.","La porta accanto al negozio delle armi si aprirà non appena tutti i Crociati sono distrutti. Oltre quella porta c'è un teletrasporto, usalo e ti porterà da noi.","私が知事について知っていることは、町の中央で双方を遊ばせてる様だ。 +ソイツがここいらを'マンション'と呼んでいる。",크루세이더들을 전부 처리하면 무기상 옆의 문이 열릴 거야. 그 안에 우리 기지로 통하는 텔레포터가 있으니 그걸 타.,"De deur naast de wapenwinkel gaat open als alle kruisvaarders dood zijn. In de opslagruimte staat een teleporter, gebruik die, en die brengt je naar ons toe.","Døren ved siden av våpenbutikken åpnes når alle korsfarerne er døde. Inne i lagerrommet er det en teleporter, bruk den, og den vil føre deg til oss...","Drzwi obok sklepu z bronią otworzą się, gdy wszyscy krzyżowcy będą martwi. Wewnątrz pomieszczenia ze sklepem jest teleporter, użyj go, a zaprowadzi cię do nas",A porta próxima à loja de armas abrirá assim que todos os Cruzados estiverem mortos. Dentro do depósito tem um teletransportador. Entre nele e ele o levará até nós.,,"Ușa de lângă magazinul de arme se va deschide odată ce toți Cruciații sunt morți. Înăuntru e un teleportor, ia-l, te va duce la noi.","Дверь возле оружейного магазина откроется, когда все крестоносцы будут уничтожены. На складе ты найдёшь телепорт. Используй его — он доставит тебя к нам.",,"Dörren bredvid vapenbutiken öppnas när alla korsriddare är döda. Inne i butiksrummet finns det en teleporter, använd den och den för dig till oss.","Tüm Haçlılar öldüğünde silah dükkanının yanındaki kapı açılacak. Dükkanın içinde bir ışınlayıcı var, onu kullan ve seni bize getirecek" +"The door next to the weapons shop will open once all the Crusaders are dead. Inside the store room there's a teleporter, use it, and it'll bring you to us.",TXT_ILOG7,"MAP33: In front of ""Irale's shop"" with the com unit and the Crusaders alive.",strifeteaser,,"Dveře vedle obchodu se zbraněmi se otevřou když budou všichni Křižáci zničeni. Uvnitř je teleportér, použij ho a dostaneš se k nám.","Døren ved siden af våbenbutikken åbnes, når alle korsfarerne er døde. Inde i lagerrummet er der en teleporter, brug den, og den vil bringe dig til os.","Die Tür neben dem Waffengeschäft wird sich öffnen, wenn alle Ordensritter tot sind. Dahinter ist ein Teleporter. Benutze ihn, er bringt dich zu uns.",,Detrui la Krucistojn malfermos la pordon apud la armilvendejo. Estas teleportilo en tiu stokejo; uzu ĝin.,La puerta junto a la armería se abrirá al matar a los cruzados. Dentro de ese almacén hay un teletransporte; úsalo.,La puerta junto a la armería se va a abrir al matar a los cruzados. Adentro de ese almacén hay un teletransporte; úsalo.,"Asekaupan viereinen ovi aukeaa, kun kaikki ristiretkeläiset on tuhottu. Varastohuoneessa on kaukosiirrin. Sitä käyttämällä pääset luoksemme.","La porte à côté du magasin d'armes s'ouvrira quand tous les croisés seront détruits. A l'intérieur de la salle de stockage se trouve un téléporteur, utilise-le pour nous rejoindre.","A fegyverbolt melletti ajtó ki fog nyílni, miután az összes Kresztes meghalt. Találsz a raktáron belül egy teleportot, ami ide fog hozni hozzánk.","La porta accanto al negozio delle armi si aprirà non appena tutti i Crociati sono distrutti. Oltre quella porta c'è un teletrasporto, usalo e ti porterà da noi.","私が知事について知っていることは、町の中央で双方を遊ばせてる様だ。 +ソイツがここいらを'マンション'と呼んでいる。",크루세이더들을 전부 처리하면 무기상 옆의 문이 열릴 거야. 그 안에 우리 기지로 통하는 텔레포터가 있으니 그걸 타.,"De deur naast de wapenwinkel gaat open als alle kruisvaarders dood zijn. In de opslagruimte staat een teleporter, gebruik die, en die brengt je naar ons toe.","Døren ved siden av våpenbutikken åpnes når alle korsfarerne er døde. Inne i lagerrommet er det en teleporter, bruk den, og den vil bringe deg til oss.","Drzwi obok sklepu z bronią otworzą się po śmierci wszystkich krzyżowców. Wewnątrz pomieszczenia sklepowego znajduje się teleporter, użyj go, a przeniesie cię do nas.",A porta próxima à loja de armas abrirá assim que todos os Cruzados estiverem mortos. Dentro do depósito tem um teletransportador. Entre nele e ele o levará até nós.,,"Ușa de lângă magazinul de arme se va deschide odată ce toți Cruciații sunt morți. Înăuntru e un teleportor, ia-l, te va duce la noi.","Дверь возле оружейного магазина откроется, когда все крестоносцы будут уничтожены. На складе ты найдёшь телепорт. Используй его — он доставит тебя к нам.",,"Dörren bredvid vapenbutiken öppnas när alla korsfarare är döda. Inne i butiksrummet finns en teleporter, använd den och den tar dig till oss.","Tüm Haçlılar öldüğünde silah dükkanının yanındaki kapı açılacak. Dükkanın içinde bir ışınlayıcı var, onu kullanın ve sizi bize getirecek." +"Kill as many of the big robots, Crusaders, as you can. When you're done, I'll guide you to Macil",TXT_ILOG8,MAP33: Room with the flamethrower.,strifeteaser,,"Znič tolik těch velkých robotů, Křižáků, kolik dokážeš. Až budeš hotov, dovedu tě k Macilovi.","Dræb så mange af de store robotter, korsfarerne, som du kan. Når du er færdig, vil jeg guide dig til Macil","Erledige so viele von den großen Robotern - „Ordensrittern“, wie möglich. Wann das erledigt ist, führe ich dich zu Macil.",,"Detruu tiom da robotegoj, alinome Krucistoj, kiom vi povas. Tiam mi gvidos vin al Macil.","Mata a tantos de los robots grandes, o sea, a los Cruzados, como puedas. Cuando termines, te guiaré hasta Macil.","Mata a tantos de los robots grandes, o sea, a los Cruzados, como puedas. Cuando termines, te guío hasta Macil.","Tuhoa jättiroboteista, ristiretkeläisistä, niin monta kuin pystyt. Kun olet valmis, opastan sinut Macilin luokse.","Détruis autant des gros robots, les croisés, que tu peux, et je te mènerai à Macil.","Ölj meg annyi nagy robotot és keresztest amennyit csak tudsz. Ha kész vagy, elvezetlek Macilhoz.","Distruggi tutti i Crociati che vedi. Non appena hai finito, ti condurrò da Macil.",,"저 거대한 '크루세이더' 로봇들을 최대한 처리해. 상황이 정리되면, 내가 너를 마실에게 데려다줄게.","Dood zoveel mogelijk van de grote robots, kruisvaarders, als je kunt. Als je klaar bent, begeleid ik je naar Macil...","Drep så mange av de store robotene, korsfarerne, som du kan. Når du er ferdig, skal jeg vise deg veien til Macil.","Zabij jak najwięcej dużych robotów, ""krzyżowców"", jak tylko możesz. Gdy skończysz, zaprowadzę cię do Macila","Mate o máximo desses robos possível. Quando terminar, eu te guiarei ao Macil.",,"Distruge cât mai mulți roboți, Cruciați, pe cât poți. Când ești gata, te voi duce la Macil.","Убей столько больших роботов, — крестоносцев, — сколько сможешь. Когда закончишь, я приведу тебя к Мэйсилу.",,"Döda så många av de stora robotarna, korsriddarna, som du kan. När du är klar kommer jag att guida dig till Macil.","Büyük robotlardan, Haçlılardan, öldürebildiğin kadarını öldür. İşiniz bittiğinde, sizi Macil'e götüreceğim." +"Go through the door, and talk to Macil.",TXT_ILOG9,MAP34: After leaving the teleporter.,strifeteaser,,Projdi dveřmi a promluv si s Macilem.,"Gå gennem døren, og tal med Macil.",Geh durch die Tür und rede mit Macil.,,Iru tra la pordo kaj parolu kun Macil.,Ve por la puerta y habla con Macil.,,Kulje ovesta ja puhu Macilille.,Traverse cette porte et va parler à Macil.,"Az ajtó mögött már vár Macil, beszélj vele.","Attraversa la porta, e vai a parlare con Macil.",ダーウィンを始末したら耳を知事に渡す。,저 문을 지나서 마실하고 대화를 해봐.,"Ga door de deur, en praat met Macil.",Gå gjennom døren og snakk med Macil.,Przejdź przez drzwi i porozmawiaj z Macil.,Passe pela porta e fale com o Macil.,,Intră pe ușă și du-te la Macil.,Обратись к Мэйсилу. Он за этой дверью.,,Gå in genom dörren och prata med Macil.,Kapıdan geçin ve Macil ile konuşun. +"Find the power tap on the mains, and shut it off. Bring something back to the Governor as proof. Find MacGuffin, and talk to him.",TXT_ILOG10,"MAP02: After accepting ""messy"" chore and leaving Mourel's room.",,,Najdi stáčedlo energie na elektrické síti a vypni jej. Přines něco guvernérovi jako důkaz. Najdi MacGuffina a promluv s ním.,"Find strømhanen på hovedledningen, og luk den. Tag noget med tilbage til guvernøren som bevis. Find MacGuffin, og tal med ham.",Finde die Stromanzapfung und schalte sie ab. Bringe einen Beweis zum Gouverneur. Finde MacGuffin und rede mit ihm. ,,"Trovu la konektilon en la elektriza sistemo, detruu ĝin kaj portu pruvon al la registo. Konsilo: Trovu Makgufinon kaj parolu kun li.","Encuentra la toma en la red eléctrica, destrúyela y llévale algo al gobernador como prueba. Para eso encuentra a MacGuffin y habla con él.",,Etsi verkkovirran piilokytkentä ja katkaise se. Tuo kuvernöörille jotain todisteeksi. Etsi MacGuffin ja puhu hänen kanssaan.,Trouve la connection pirate sur le transformateur et désactive la. Amène quelque chose au gouverneur comme preuve. Trouve MacGuffin et parle-lui.,"Keresd meg a fővonalon az áramkapcsolót, és kapcsold ki. Hozz vissza valamit a kormányzótól bizonyítékként. Keresd meg MacGuffint, és beszélj vele.","Trova l'aggeggio che sta venendo usato per rubare energia alla rete, e distruggilo. Porta dei resti al governatore come prova. Trova e parla con MacGuffin.","電力盗用の場所を見つけ、それを止める。 +知事に渡す証拠も必要だ。マクガフィンと話をつける。",주 동력선 어딘가에 있는 추출기를 처리해. 총독에게 전할 증거물도 챙기고. 맥거핀을 찾아서 대화해 봐.,Zoek het stopcontact op het lichtnet en zet het uit. Breng iets terug naar de gouverneur als bewijs. Zoek MacGuffin en praat met hem.,"Finn strømkranen på strømnettet, og slå den av. Ta med noe tilbake til guvernøren som bevis. Finn MacGuffin, og snakk med ham.",Znajdź kurek z prądem w sieci i wyłącz go. Przynieś coś gubernatorowi jako dowód. Znajdź MacGuffina i porozmawiaj z nim.,Encontre a ligação pirata no transformador e desligue ela. Traga algo de volta para o Governador como prova. Encontre o MacGuffin e fale com ele.,,"Găsește comutatorul de energie, și oprește-l. Du ceva înapoi la Guvernator drept dovadă. Găsește-l pe MacGuffin, și vorbește cu el.",Найди нелегальное подключение к линии электропередачи и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства. Найди Макгаффина и поговори с ним.,,Leta reda på strömkranen på elnätet och stäng av den. Ta med dig något tillbaka till guvernören som bevis. Hitta MacGuffin och prata med honom.,Şebekedeki güç musluğunu bulun ve kapatın. Kanıt olarak Vali'ye bir şey getirin. MacGuffin'i bul ve onunla konuş. +"Find the power tap on the mains, and shut it off. Bring something back to the Governor as proof. Find MacGuffin, and talk to him. He's up by the sewage treatment plant, in the ""bum hole"", down the stairs.",TXT_ILOG11,"MAP02: After accepting ""messy"" chore and leaving Mourel's mansion.",,,"Najdi stáčedlo energie na elektrické síti a vypni jej. Přines něco guvernérovi jako důkaz. Najdi MacGuffina a promluv s ním. Je u čističky, v „zadnici“ pod schody.","Find strømhanen på hovedledningen, og luk den. Tag noget med tilbage til guvernøren som bevis. Find MacGuffin, og tal med ham. Han er oppe ved rensningsanlægget, i ""bum-hullet"", nede ad trappen.","Finde die Stromanzapfung und schalte sie ab. Bringe einen Beweis zum Gouverneur. Finde MacGuffin und rede mit ihm. Er ist in der Nähe der Kläranlage im „Pennerloch“, die Treppe runter.",,"Trovu la konektilon en la elektriza sistemo, detruu ĝin kaj portu pruvon al la registo. Konsilo: Trovu Makgufinon kaj parolu kun li. Li estas malsupre laŭ ŝtuparo en «la groto de la vagulo» en la purigejo de kloaka akvo.","Encuentra la toma en la red eléctrica, destrúyela y llévale algo al gobernador como prueba. Para eso encuentra a MacGuffin y habla con él. Está donde se depuran las aguas residuales en «la cueva del vagabundo» bajando unas escaleras.",,"Etsi verkkovirran piilokytkentä ja katkaise se. Tuo kuvernöörille jotain todisteeksi. Etsi MacGuffin ja puhu hänen kanssaan. Hän majailee jätelaitoksella ""pepunreiässä"" rappuset alas.","Trouve la connection pirate sur le transformateur et désactive la. Amène quelque chose au gouverneur comme preuve. Trouve MacGuffin et parle-lui. Il se trouve dans la centrale de traitement des eaux, dans le « trou à rats » en bas des escaliers.","Keresd meg a fővonalon az áramkapcsolót, és kapcsold ki. Hozz vissza valamit a kormányzótól bizonyítékként. Keresd fel MacGuffint és beszélj vele. Ott van a szennyvíz tisztítónál, ha lemész a lépcsőn, lent a ""kotorékban"".","Trova il marchingegno che sta venendo usato per rubare energia alla rete, e distruggilo. Porta dei resti al governatore come prova. Trova e parla con MacGuffin. Lui bazzica dalle parti dell'impianto fognario, oltre delle scale.","電力盗用の場所を見つけ、それを止める。 知事に渡す証拠も必要だ。マクガフィンと話をつける。 -彼は下水処理場の傍にある'物乞いの巣'と呼ばれる場所にいる。",주 동력선 어딘가에 있는 추출기를 처리해. 총독에게 전할 증거물도 챙기고. 맥거핀을 찾아서 대화해 봐. 그는 하수처리장 근처 계단 밑 개구멍에 있어.,"Zoek het stopcontact op het lichtnet en zet het uit. Breng iets terug naar de gouverneur als bewijs. Zoek MacGuffin en praat met hem. Hij is boven bij de rioolwaterzuiveringsinstallatie, in het ""zwerfgat"", de trap af.","Finn strømbryteren på strømnettet, og slå den av. Ta med noe tilbake til guvernøren som bevis. Finn MacGuffin og snakk med ham. Han er oppe ved kloakkrenseanlegget, i ""rumpehullet"", ned trappen.","Znajdź kurek z prądem w sieci i wyłącz go. Zanieś coś gubernatorowi jako dowód. Znajdź MacGuffina i porozmawiaj z nim. Jest przy oczyszczalni ścieków, w ""dziurze"", po schodach.","Encontre a ligação pirata no transformador e desligue ela. Traga algo de volta para o Governador como prova. Encontre o MacGuffin e fale com ele. Ele está na usina de tratamento, na ""toca de rato"" descendo as escadas.",,"Găsește comutatorul de energie, și oprește-l. Du ceva înapoi la Guvernator drept dovadă. Găsește-l pe MacGuffin, și vorbește cu el, e lângă fabrica de tratament, în josul scărilor.","Найди нелегальное подключение к линии электропередачи и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства. Найди Макгаффина и поговори с ним. Он возле очистного сооружения, в «бомжевой норе», вниз по лестнице.",,"Şebekedeki güç musluğunu bulun ve kapatın. Kanıt olarak Vali'ye bir şey getir. MacGuffin'i bul ve onunla konuş. Kanalizasyon arıtma tesisinin yanında, merdivenlerin aşağısındaki ""serseri deliğinde""." -"You idiot! You've shut off the power to the jamming circuits we use to conceal our base from the Order. Head to the town hall and take out the scanning crew, now! Then, go back to the Governor and give him the broken coupling.",TXT_ILOG13,MAP02: After destroying Front's power coupling.,,,"Ty debile! Odstřihnul jsi přívod proudu do rušiček, které používáme, abychom ukryli naší základnu před Řádem. Okamžitě si to zamiř k radnici a vybij průzkumnou četu! Pak se vrať ke guvernérovi a dej mu rozbitou spojku.","Din idiot! Du har slukket for strømmen til de støjkredsløb, som vi bruger til at skjule vores base for Ordenen. Gå hen til rådhuset og udryd scanningsholdet, nu! Gå derefter tilbage til guvernøren og giv ham den ødelagte kobling.","Du Idiot! Du hast die Energie für unsere Störsender unterbrochen, mit denen wir unsere Basis vor dem Orden verborgen haben. Geh schnell zum Rathaus und schalte den Suchtrupp aus. Geh danach zum Gouverneur und gib ihm den zerstörten Stromabnehmer.",,,"¡Idiota! Has apagado la energía de los circuitos de interferencia que usamos para ocultarle nuestra base a La Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ya! Luego vuelve con el gobernador y dale el acoplador roto.","¡Idiota! Apagaste la energía de los circuitos de interferencia que usamos para ocultarle nuestra base a La Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ya! Luego vuelve con el gobernador y dale el acoplador roto.","Sinä idiootti! Olet katkaissut virran häirintäpiireihin, joilla piilotamme sijaintimme Veljeskunnalta. Suuntaa kaupungintalolle ja hoitele tiedusteluryhmä, heti paikalla! Palaa sitten kuvernöörin luo ja anna rikkinäinen virtaliitin hänelle.",Idiot! Tu as désactivé les circuits brouilleurs qui cachaient notre base des senseurs de l'Ordre. Retourne vite à la mairie et tue l'équipe de scan maintenant! Retourne ensuite au gouverneur et donne lui le coupleur cassé.,"Te idióta! Leállítottad a zavaró áramellátását, amivel lerejtjük magunkat a Rend elől. Menj azonnal a városházára, és iktasd ki a felderítő brigádot! Aztán menj vissza a kormányzóhoz, és add át az elrontott kapcsolóművet.","Idiota! Hai interrotto il flusso di energia dei circuiti che usavamo per nascondere la nostra base dall'Ordine. Ritorna subito al municipio e fai fuori il gruppo venuto a perlustare la zona, ora! Poi, torna dal governatore e dagli questo pezzo di ferraglia.","馬鹿者! お前はオーダーから我々の基地を隠す妨害回路を +彼は下水処理場の傍にある'物乞いの巣'と呼ばれる場所にいる。",주 동력선 어딘가에 있는 추출기를 처리해. 총독에게 전할 증거물도 챙기고. 맥거핀을 찾아서 대화해 봐. 그는 하수처리장 근처 계단 밑 개구멍에 있어.,"Zoek het stopcontact op het lichtnet en zet het uit. Breng iets terug naar de gouverneur als bewijs. Zoek MacGuffin en praat met hem. Hij is boven bij de rioolwaterzuiveringsinstallatie, in het ""zwerfgat"", de trap af.","Finn strømbryteren på strømnettet, og slå den av. Ta med noe tilbake til guvernøren som bevis. Finn MacGuffin og snakk med ham. Han er oppe ved kloakkrenseanlegget, i ""rumpehullet"", ned trappen.","Znajdź kurek z prądem w sieci i wyłącz go. Zanieś coś gubernatorowi jako dowód. Znajdź MacGuffina i porozmawiaj z nim. Jest przy oczyszczalni ścieków, w ""dziurze"", po schodach.","Encontre a ligação pirata no transformador e desligue ela. Traga algo de volta para o Governador como prova. Encontre o MacGuffin e fale com ele. Ele está na usina de tratamento, na ""toca de rato"" descendo as escadas.",,"Găsește comutatorul de energie, și oprește-l. Du ceva înapoi la Guvernator drept dovadă. Găsește-l pe MacGuffin, și vorbește cu el, e lângă fabrica de tratament, în josul scărilor.","Найди нелегальное подключение к линии электропередачи и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства. Найди Макгаффина и поговори с ним. Он возле очистного сооружения, в «бомжевой норе», вниз по лестнице.",,"Leta reda på eluttaget på elnätet och stäng av det. Ta med dig något tillbaka till guvernören som bevis. Hitta MacGuffin och prata med honom. Han är uppe vid reningsverket, i ""bum-hålet"", nerför trappan.","Şebekedeki güç musluğunu bulun ve kapatın. Kanıt olarak Vali'ye bir şey getir. MacGuffin'i bul ve onunla konuş. Kanalizasyon arıtma tesisinin yanında, merdivenlerin aşağısındaki ""serseri deliğinde""." +"You idiot! You've shut off the power to the jamming circuits we use to conceal our base from the Order. Head to the town hall and take out the scanning crew, now! Then, go back to the Governor and give him the broken coupling.",TXT_ILOG13,MAP02: After destroying Front's power coupling.,,,"Ty debile! Odstřihnul jsi přívod proudu do rušiček, které používáme, abychom ukryli naší základnu před Řádem. Okamžitě si to zamiř k radnici a vybij průzkumnou četu! Pak se vrať ke guvernérovi a dej mu rozbitou spojku.","Din idiot! Du har slukket for strømmen til de støjkredsløb, som vi bruger til at skjule vores base for Ordenen. Gå hen til rådhuset og udryd scanningsholdet, nu! Gå derefter tilbage til guvernøren og giv ham den ødelagte kobling.","Du Idiot! Du hast die Energie für unsere Störsender unterbrochen, mit denen wir unsere Basis vor dem Orden verborgen haben. Geh schnell zum Rathaus und schalte den Suchtrupp aus. Geh danach zum Gouverneur und gib ihm den zerstörten Stromabnehmer.",,"Vi rompis la kuplilon, kiu kaŝis nian bazon de La Ordeno. Reiru al la urbodomo kaj mortigu la skoltojn. Tiam reiru ĉe la registo kaj donu al li la kuplilon, kiun vi rompis.",Has roto el acoplador que le ocultaba nuestra base a La Orden. Dirígete al ayuntamiento y elimina a la tropa de reconocimiento. Luego vuelve con el gobernador y dale el acoplador que has roto.,Rompiste el acoplador que le ocultaba nuestra base a La Orden. Dirígete al ayuntamiento y elimina a la tropa de reconocimiento. Luego vuelve con el gobernador y dale el acoplador que rompiste.,"Sinä idiootti! Olet katkaissut virran häirintäpiireihin, joilla piilotamme sijaintimme Veljeskunnalta. Suuntaa kaupungintalolle ja hoitele tiedusteluryhmä, heti paikalla! Palaa sitten kuvernöörin luo ja anna rikkinäinen virtaliitin hänelle.",Idiot! Tu as désactivé les circuits brouilleurs qui cachaient notre base des senseurs de l'Ordre. Retourne vite à la mairie et tue l'équipe de scan maintenant! Retourne ensuite au gouverneur et donne lui le coupleur cassé.,"Te idióta! Leállítottad a zavaró áramellátását, amivel lerejtjük magunkat a Rend elől. Menj azonnal a városházára, és iktasd ki a felderítő brigádot! Aztán menj vissza a kormányzóhoz, és add át az elrontott kapcsolóművet.","Idiota! Hai interrotto il flusso di energia dei circuiti che usavamo per nascondere la nostra base dall'Ordine. Ritorna subito al municipio e fai fuori il gruppo venuto a perlustare la zona, ora! Poi, torna dal governatore e dagli questo pezzo di ferraglia.","馬鹿者! お前はオーダーから我々の基地を隠す妨害回路を 壊してしまった!市庁舎に調査隊が向かった、今すぐ片付けろ! -",이 멍청이야! 우리 기지를 오더로부터 은폐시켜주는 교란 장치의 동력을 끊어버렸잖아. 당장 시청으로 가서 탐색반들을 쓸어버려! 그다음에 총독에게 부서진 장치를 전해줘.,Idioot! Je hebt de stroom naar de stoorcircuits die we gebruiken om onze basis te verbergen voor de orde uitgeschakeld. Ga naar het stadhuis en haal de scanploeg er nu uit! Ga dan terug naar de Gouverneur en geef hem de kapotte koppeling.,"Din idiot! Du har slått av strømmen til blokkeringskretsene vi bruker for å skjule basen vår for Ordenen. Dra til rådhuset og drep skannermannskapet, nå! Gå tilbake til guvernøren og gi ham den ødelagte koblingen.","Ty idioto! Wyłączyłeś zasilanie obwodów zagłuszających, których używamy do ukrycia naszej bazy przed Zakonem. Idź do ratusza i zlikwiduj ekipę skanującą, natychmiast! Potem wróć do gubernatora i daj mu zepsute złącze.",Seu idiota! Você desligou a energia para os circuitos de interferência que usamos para esconder a nossa base dos sensores da Ordem. Vá até a prefeitura e tire a equipe de busca de lá imediatamente! Depois disso volte para o Governador e passe pra ele a conexão quebrada.,,"Idiotule! Ai oprit curentul circuitelor noastre care ne mascau prezența. Du-te în hala orașului și elimină echipajul! Apoi, du-te la Guvernator și dă-i cuplajul!","Идиот! Ты обесточил генератор радиопомех, с помощью которого мы скрывали местоположение нашей базы от Ордена. Возвращайся к ратуше и уничтожь разведывательную группу как можно скорее! Затем вернись к губернатору и отдай ему повреждённую муфту.",,"Seni aptal! Üssümüzü Tarikat'tan gizlemek için kullandığımız sinyal bozucu devrelerin gücünü kestin. Belediye binasına git ve tarama ekibini yok et, hemen! Sonra Vali'ye geri dön ve ona kırık bağlantıyı ver." -"OK, ""Trust no one"" is the name of the game! Let's get that prison pass from the Governor. Take the broken coupling to him.",TXT_ILOG14,MAP02: After destroying Front's power coupling and killing all blue acolytes in the town hall.,,,"Dobře, „Nevěř nikomu“ je motto hry! Pojďme od guvernéra dostat tu propustku a osvoboďme ty vězně. Přines mu rozbitou spojku.","Okay, ""Stol ikke på nogen"" er spillets navn! Lad os få det fængselskort fra guvernøren. Tag den ødelagte kobling med til ham.","Ok, „Trau keinem“ heißt dieses Spiel. Lass uns den Gefängnispass vom Gouverneur holen. Bring ihm den Stromabnehmer.",,,"Vale, ¡«No te fies de nadie» se llama el juego! Ya es hora de conseguir el pase a la prisión. Llévale el acoplador roto al Gobernador.","Bueno, ¡«No confíes en nadie» se llama el juego! Ya es hora de conseguir el pase a la prisión. Llévale el acoplador roto al Gobernador.","Selvä, ""Älä luota kehenkään"" on näköjään pelin nimi! Hankitaan vankilan pääsylupa kuvernööriltä. Vie rikkinäinen virtaliitin hänelle.","Ok, « ne fais confiance à personne » est notre nouveau slogan. On va récupérer le passe de la prison chez le gouverneur. Amène lui le coupleur cassé.","Készülj fel, hogy senkiben sem bízhatsz. Gyerünk, szerezzük meg a kormányzótól a börtön belépőt. Vidd el hozzá az elrontott kapcsolóművet.","OK, ""Non fidarti di nessuno"" è il gioco che stiamo giocando qua! Prendiamo quel pass per la prigione dal governatore. Portagli quel pezzo di ferraglia.","よし、'信用しない'のが最も重要なことだ! -壊れた配電機を渡して刑務所の許可証を知事から貰うんだ。","좋아, '아무도 믿지 말라'가 이 게임의 이름이겠군! 어서 총독에게 감옥 통행증이나 받자. 이 부서진 장치를 그에게 전해줘.","OK, ""Vertrouw niemand"" is de naam van het spel! Laten we die gevangenispas van de Gouverneur halen. Pak de kapotte koppeling naar hem toe.","OK, ""Stol ikke på noen"" er navnet på spillet! La oss få fengselspasset fra guvernøren. Gi ham den ødelagte koblingen.","OK, ""Nie ufaj nikomu"" to nazwa gry! Zdobądźmy tę przepustkę od Gubernatora. Zanieś mu zepsute złącze.","Ok, ""não confie em ninguém"" é o nome do jogo! Vamos pegar do Governador aquele passe da prisão. Leve a conexão quebrada a ele.",,"OK, 'Încrede-te în nimeni' e numele jocului. Să luam permisul închisorii de la Guvernator. Ia cuplajul defect și du-l lui.","Что ж, эта игра называется «не верь никому»! Давай получим у губернатора пропуск в тюрьму. Отнеси ему повреждённую муфту.",,"Tamam, ""Kimseye güvenme"" oyunun adı! Vali'den şu hapishane kartını alalım. Kırık bağlantıyı ona götür." -Good move! The Governor is a liar. That's our power coupling. We're using it to hide the base from the Order. Take this broken coupling back to him and let's get that pass.,TXT_ILOG15,MAP02: After finding the broken power coupling.,,,"Dobrý tah! Guvernér je lhář, tohle je naše spojka. Používáme ji k ukrytí základny před Řádem. Přines mu tuhle rozbitou spojku a vezmi si od něj tu propustku.","Godt træk! Guvernøren er en løgner. Det er vores kraftkobling. Vi bruger den til at skjule basen for Ordenen. Tag den ødelagte kobling med tilbage til ham, og lad os få det pas.",Das war klasse! Der Gouverneur ist ein verdammter Lügner. Das war unsere Anzapfung. Wir benutzen sie um unsere Basis vor dem Orden zu verstecken. Und nun bring ihm den Stromabnehmer und hol den Gefängnispass.,,,¡Buen ojo! El gobernador es un mentiroso: ese era el acoplador de energía que el Frente está usando para ocultarle la base a La Orden. Llévale el acoplador roto para conseguir ese pase.,,"Hyvä veto! Kuvernööri on valehtelija. Se on meidän virtaliittimemme. Käytämme sitä piillottamaan tukikohtamme Veljeskunnalta. Toimita tämä rikkinäinen virtaliitin takaisin hänelle, ja hankitaan se pääsylupa.",Bonne idée! Le gouverneur est un menteur. Voilà notre coupleur. On l'utilise pour dissimuler notre présence à l'Ordre. Amène ce coupleur cassé à lui et récupère le passe.,"Ügyes lépés! A kormányzó egy hazug senkiházi. Ez a mi kapcsolóművünk. Arra használjuk, hogy elrejtsük a bázisunkat a Rend elől. Vidd vissza neki a tönkrevágott kapcsolóművet, és irány megszerezni a belépőt.","Ottima mossa! Il governatore è un bugiardo. Eravamo noi a utilizzare questo marchingegno collegato alla rete. Lo stiamo usando per nascondere la posizione della nostra base dall'Ordine. Prendi quest'altro rotto e vecchio e portalo da lui, e prendiamoci quel pass.","良い判断だ! 知事は嘘を付いている。 +",이 멍청이야! 우리 기지를 오더로부터 은폐시켜주는 교란 장치의 동력을 끊어버렸잖아. 당장 시청으로 가서 탐색반들을 쓸어버려! 그다음에 총독에게 부서진 장치를 전해줘.,Idioot! Je hebt de stroom naar de stoorcircuits die we gebruiken om onze basis te verbergen voor de orde uitgeschakeld. Ga naar het stadhuis en haal de scanploeg er nu uit! Ga dan terug naar de Gouverneur en geef hem de kapotte koppeling.,"Din idiot! Du har slått av strømmen til blokkeringskretsene vi bruker for å skjule basen vår for Ordenen. Dra til rådhuset og drep skannermannskapet, nå! Gå tilbake til guvernøren og gi ham den ødelagte koblingen.","Ty idioto! Wyłączyłeś zasilanie obwodów zagłuszających, których używamy do ukrycia naszej bazy przed Zakonem. Idź do ratusza i zlikwiduj ekipę skanującą, natychmiast! Potem wróć do gubernatora i daj mu zepsute złącze.",Seu idiota! Você desligou a energia para os circuitos de interferência que usamos para esconder a nossa base dos sensores da Ordem. Vá até a prefeitura e tire a equipe de busca de lá imediatamente! Depois disso volte para o Governador e passe pra ele a conexão quebrada.,,"Idiotule! Ai oprit curentul circuitelor noastre care ne mascau prezența. Du-te în hala orașului și elimină echipajul! Apoi, du-te la Guvernator și dă-i cuplajul!","Идиот! Ты обесточил генератор радиопомех, с помощью которого мы скрывали местоположение нашей базы от Ордена. Возвращайся к ратуше и уничтожь разведывательную группу как можно скорее! Затем вернись к губернатору и отдай ему повреждённую муфту.",,"Din idiot! Du har stängt av strömmen till de störningskretsar som vi använder för att dölja vår bas för Orden. Gå till stadshuset och ta ut skanningspersonalen, nu! Gå sedan tillbaka till guvernören och ge honom den trasiga kopplingen.","Seni aptal! Üssümüzü Tarikat'tan gizlemek için kullandığımız sinyal bozucu devrelerin gücünü kestin. Belediye binasına git ve tarama ekibini yok et, hemen! Sonra Vali'ye geri dön ve ona kırık bağlantıyı ver." +"OK, ""Trust no one"" is the name of the game! Let's get that prison pass from the Governor. Take the broken coupling to him.",TXT_ILOG14,MAP02: After destroying Front's power coupling and killing all blue acolytes in the town hall.,,,"Dobře, „Nevěř nikomu“ je motto hry! Pojďme od guvernéra dostat tu propustku a osvoboďme ty vězně. Přines mu rozbitou spojku.","Okay, ""Stol ikke på nogen"" er spillets navn! Lad os få det fængselskort fra guvernøren. Tag den ødelagte kobling med til ham.","Ok, „Trau keinem“ heißt dieses Spiel. Lass uns den Gefängnispass vom Gouverneur holen. Bring ihm den Stromabnehmer.",,"Bone, la ludo estas «Fidu neniun»! Ni akiru la enirpermeson al la malliberejo: donu la rompitan kuplilon al la registo.","Vale, ¡«No te fies de nadie» se llama el juego! Ya es hora de conseguir el pase a la prisión: llévale el acoplador roto al gobernador.","Bueno, ¡«No confíes en nadie» se llama el juego! Ya es hora de conseguir el pase a la prisión: llévale el acoplador roto al gobernador.","Selvä, ""Älä luota kehenkään"" on näköjään pelin nimi! Hankitaan vankilan pääsylupa kuvernööriltä. Vie rikkinäinen virtaliitin hänelle.","Ok, « ne fais confiance à personne » est notre nouveau slogan. On va récupérer le passe de la prison chez le gouverneur. Amène lui le coupleur cassé.","Készülj fel, hogy senkiben sem bízhatsz. Gyerünk, szerezzük meg a kormányzótól a börtön belépőt. Vidd el hozzá az elrontott kapcsolóművet.","OK, ""Non fidarti di nessuno"" è il gioco che stiamo giocando qua! Prendiamo quel pass per la prigione dal governatore. Portagli quel pezzo di ferraglia.","よし、'信用しない'のが最も重要なことだ! +壊れた配電機を渡して刑務所の許可証を知事から貰うんだ。","좋아, '아무도 믿지 말라'가 이 게임의 이름이겠군! 어서 총독에게 감옥 통행증이나 받자. 이 부서진 장치를 그에게 전해줘.","OK, ""Vertrouw niemand"" is de naam van het spel! Laten we die gevangenispas van de Gouverneur halen. Pak de kapotte koppeling naar hem toe.","OK, ""Stol ikke på noen"" er navnet på spillet! La oss få fengselspasset fra guvernøren. Gi ham den ødelagte koblingen.","OK, ""Nie ufaj nikomu"" to nazwa gry! Zdobądźmy tę przepustkę od Gubernatora. Zanieś mu zepsute złącze.","Ok, ""não confie em ninguém"" é o nome do jogo! Vamos pegar do Governador aquele passe da prisão. Leve a conexão quebrada a ele.",,"OK, 'Încrede-te în nimeni' e numele jocului. Să luam permisul închisorii de la Guvernator. Ia cuplajul defect și du-l lui.","Что ж, эта игра называется «не верь никому»! Давай получим у губернатора пропуск в тюрьму. Отнеси ему повреждённую муфту.",,"Okej, ""Lita inte på någon"" är vad som gäller! Låt oss få fängelsepasset från guvernören. Ta den trasiga kopplingen till honom.","Tamam, ""Kimseye güvenme"" oyunun adı! Vali'den şu hapishane kartını alalım. Kırık bağlantıyı ona götür." +Good move! The Governor is a liar. That's our power coupling. We're using it to hide the base from the Order. Take this broken coupling back to him and let's get that pass.,TXT_ILOG15,MAP02: After finding the broken power coupling.,,,"Dobrý tah! Guvernér je lhář, tohle je naše spojka. Používáme ji k ukrytí základny před Řádem. Přines mu tuhle rozbitou spojku a vezmi si od něj tu propustku.","Godt træk! Guvernøren er en løgner. Det er vores kraftkobling. Vi bruger den til at skjule basen for Ordenen. Tag den ødelagte kobling med tilbage til ham, og lad os få det pas.",Das war klasse! Der Gouverneur ist ein verdammter Lügner. Das war unsere Anzapfung. Wir benutzen sie um unsere Basis vor dem Orden zu verstecken. Und nun bring ihm den Stromabnehmer und hol den Gefängnispass.,,"La registo estas mensogema: tiu estis la kuplilo, kiu kaŝas nian bazon de La Ordeno. Donu al li la rompitan kuplilon por akiri la enirpermeson.",El gobernador es un mentiroso: ese era el acoplador de energía que le oculta nuestra base a La Orden. Llévale el acoplador roto para conseguir ese pase.,,"Hyvä veto! Kuvernööri on valehtelija. Se on meidän virtaliittimemme. Käytämme sitä piillottamaan tukikohtamme Veljeskunnalta. Toimita tämä rikkinäinen virtaliitin takaisin hänelle, ja hankitaan se pääsylupa.",Bonne idée! Le gouverneur est un menteur. Voilà notre coupleur. On l'utilise pour dissimuler notre présence à l'Ordre. Amène ce coupleur cassé à lui et récupère le passe.,"Ügyes lépés! A kormányzó egy hazug senkiházi. Ez a mi kapcsolóművünk. Arra használjuk, hogy elrejtsük a bázisunkat a Rend elől. Vidd vissza neki a tönkrevágott kapcsolóművet, és irány megszerezni a belépőt.","Ottima mossa! Il governatore è un bugiardo. Eravamo noi a utilizzare questo marchingegno collegato alla rete. Lo stiamo usando per nascondere la posizione della nostra base dall'Ordine. Prendi quest'altro rotto e vecchio e portalo da lui, e prendiamoci quel pass.","良い判断だ! 知事は嘘を付いている。 あれはオーダーから基地を隠す為に使用している我々の配電機だ。 -この壊れた配電機を渡して奴を騙し返せ。",참 잘했어! 총독이 거짓말을 했군. 이건 우리의 동력 장치야. 이걸 써서 우리 기지를 오더로부터 은폐시켜주지. 여기 있는 고장 난 장치를 전해주고 통행증이나 받자.,Goede zet! De Gouverneur is een leugenaar. Dat is onze stroomkoppeling. We gebruiken het om de basis te verbergen voor de Orde. Neem deze kapotte koppeling terug naar hem en laten we die pass pakken.,Godt trekk! Guvernøren er en løgner. Det er kraftkoblingen vår. Vi bruker den til å skjule basen for Ordenen. Ta denne ødelagte koblingen tilbake til ham og la oss få det passet.,"Dobry ruch! Gubernator to kłamca. To jest nasze sprzęgło mocy. Używamy go, by ukryć bazę przed Zakonem. Zabierz mu to zepsute sprzęgło i zdobądźmy tę przepustkę.",Boa! O Governador é um mentiroso . Essa é a nossa conexão. Vamos usá-la para esconder a base da Ordem. Leve esta conexão danificada de volta a ele e vamos pegar o passe.,,"Bună mutare! Guvernatorul e un mincins. Acela e cuplajul nostru. Îl folosim pentru a ne ascunde baza de Ordin. Ia cuplajul ăsta defect și du-l înapoi lui, să luăm permisul.","Отличный ход! Губернатор — лжец. Это наше подключение к силовой линии. Мы используем его, чтобы скрывать местоположение нашей базы от Ордена. Отнеси повреждённую муфту губернатору и получи пропуск.",,İyi hamle! Vali bir yalancı. Bu bizim güç bağlantımız. Üssü Tarikat'tan saklamak için kullanıyoruz. Bu kırık bağlantıyı ona geri götür ve şu geçiş iznini alalım. -Use the Warden's key to get into the prison cell blocks and find a way to free the prisoners.,TXT_ILOG18,MAP05: After crossing the alarm green door.,,,"Použij dozorcův klíč k dostání se do bloku s celami a najdi způsob, jak osvobodit vězně.",Brug fængselsdirektørens nøgle til at komme ind i fængselscelleblokkene og find en måde at befri fangerne på.,"Benutze den Schlüssel des Direktors um in die Zellenblöcke zu kommen und finde heraus, wie man die Gefangenen befreien kann.",,,Usa la llave del Carcelero para entrar en los bloques de celdas y encuentra una forma de liberar a los prisioneros.,Usa la llave del Carcelero para entrar a los bloques de celdas y encuentra una forma de liberar a los prisioneros.,Käytä vankilanjohtajan avainta päästäksesi vankilan selliosastoille ja keksi keino vapauttaa vangit.,Utilise la clé du gardien pour entrer dans le bloc de cellules et trouver une manière de libérer les prisonniers.,"Használd az igazgató kulcsát, hogy bejuss a börtön részlegbe, és kiszíbadíts mindenkit.",Usa la chiave del direttore per entrare nella sezione delle celle e trovare un modo per liberare i prigionieri.,"ワーデンの鍵で刑務所の独房区域に入って -囚人を解放する方法を見つける。","간수장의 열쇠를 써서 감옥 안으로 진입하고, 수감자들을 풀어줄 방법을 찾아봐.",Gebruik de sleutel van de bewaker om in de celblokken van de gevangenis te komen en een manier te vinden om de gevangenen te bevrijden.,Bruk direktørens nøkkel til å komme inn i fengselsblokkene og finn en måte å befri fangene på.,"Użyj klucza naczelnika, aby dostać się do bloków więziennych i znajdź sposób na uwolnienie więźniów.",Use a chave do Carcereiro para entrar nos blocos de celas e ache uma maneira de libertar os prisioneiros.,,Folosește cheia Directorului pentru a intra în blocurile celulelor și găsește o cale să eliberezi prizonierii.,"Используй ключ тюремщика, чтобы пройти к камерам. Найди способ освободить пленников.",,Hapishane hücre bloklarına girmek için Müdür'ün anahtarını kullan ve mahkumları serbest bırakmanın bir yolunu bul. -Find a way to free the prisoners. Find a way to open the hand scanner switch.,TXT_ILOG19,MAP05: After getting to Main Control.,,,"Najdi způsob, jak osvobodit vězně. Najdi způsob, jak aktivovat skener otisků ruky.",Find en måde at befri fangerne på. Find en måde at åbne håndscannerkontakten.,"Finde heraus, wie man die Gefangenen befreien kann und wie du den Handscanner umgehen kannst.",,,Encuentra una forma de liberar a los prisioneros. Encuentra una forma de operar los sensores de escáner de mano.,,Etsi keino vapauttaa vangit. Ratkaise tapa avata kädenjälkilukijan lukitus.,Trouve un moyen de libérer les prisonniers. Trouve une manière d'activer le scanner à empreinte digitale.,"Találd meg a módját, hogyan szabadíthatjuk ki a rabokat, és hogyan játszhatjuk ki a kézlenyomat olvasót.",Trova un modo per liberare i prigionieri. Trova un modo per attivare lo scanner della mano.,"囚人を解放する方法を見つける。 - ハンドスキャナーを開く方法を見つける。",수감자들을 풀어줄 방법을 찾자. 지문인식장치를 통과할 방법을 찾아봐.,Zoek een manier om de gevangenen te bevrijden. Zoek een manier om de handscanner schakelaar te openen.,Finn en måte å befri fangene på. Finn en måte å åpne håndskannerbryteren på.,Znajdź sposób na uwolnienie więźniów. Znajdź sposób na otwarcie przełącznika skanera ręcznego.,Encontre uma maneira de libertar os prisioneiros. Ache uma maneira de abrir o scanner de mão.,,Găsește o cale să eliberezi prizonierii. Găsește o cale să deschizi comutatorul scanner-ului de mâini.,Найди способ освободить пленников. Найди способ открыть замок со сканером отпечатка руки.,,Mahkûmları serbest bırakmanın bir yolunu bul. El tarayıcı anahtarını açmanın bir yolunu bulun. -Find a way to free the prisoners. Use the judge's hand to operate the hand scanner switch.,TXT_ILOG20,MAP05: After cutting Wolenick's hand off.,,,"Najdi způsob, jak osvobodit vězně. Použij soudcovu ruku k aktivaci skeneru otisků ruky.",Find en måde at befri fangerne på. Brug dommerens hånd til at betjene håndscannerkontakten.,"Finde heraus, wie man die Gefangenen befreien kann. Benutze die Hand des Richters um den Handscannerschalter zu betätigen.",,,Encuentra una forma de liberar a los prisioneros. Usa la mano del juez para operar los sensores de escáner de mano.,,Etsi keino vapauttaa vangit. Käytä tuomarin kättä kädenjälkilukijaan.,Trouve un moyen de libérer les prisonniers. Utilise la main du juge pour activer le scanner à empreinte digitale.,"Találd meg a módját, hogyan szabadíthatjuk ki a rabokat, használd a bíró kezét a kézleolvasóhoz.",Trova un modo per liberare i prigionieri. Usa la mano del giudice per operare lo scanner.,"囚人を解放する方法を見つける。 -裁判官の手を使用してハンドスキャナースイッチを操作する。",수감자들을 풀어줄 방법을 찾자. 판사의 손을 써서 지문인식장치를 통과하는 거야.,Zoek een manier om de gevangenen te bevrijden. Gebruik de hand van de rechter om de handscanner schakelaar te bedienen.,Finn en måte å befri fangene på. Bruk dommerens hånd til å betjene håndskannerbryteren.,"Znajdź sposób na uwolnienie więźniów. Użyj ręki sędziego, aby uruchomić przełącznik skanera ręcznego.",Encontre uma maneira de libertar os prisioneiros. Use a mão do juiz para operar o scanner.,,Găsește o cale să eliberezi prizonierii. Folosește mâna judecătorului să operezi scanner-ul de mâini.,"Найди способ освободить пленников. Используй руку судьи, чтобы открыть замок со сканером отпечатка руки.",,Mahkûmları serbest bırakmanın bir yolunu bulun. El tarayıcı anahtarını çalıştırmak için yargıcın elini kullan. -Way to go my friend. Good work freeing the prisoners. Jump on one of the teleporters and it will bring you back to base.,TXT_ILOG21,MAP05: After setting the prisoners free.,,,"Jen tak dál, příteli, dobrá práce. Skoč na teleportér, dostane tě to zpět na základnu.","Godt gået, min ven. Godt arbejde med at befri fangerne. Hop på en af teleportørerne, så kommer du tilbage til basen.","Das war gute Arbeit, wie du die Gefangenen befreit hast. Benutze einen der Teleporter um zur Basis zurückzugelangen.",,,"Así se hace, amigo. Buen trabajo liberando a los prisioneros. Ponte en uno de los teletransportes y te traerá de vuelta a la base.",,"Niin sitä pitää, ystäväni. Hyvin toimittu vankien vapauttamisessa. Hyppää johonkin kaukosiirtimistä, ja se tuo sinut takaisin tukikohtaan.",Bien joué mon ami! Bon travail avec ces prisonniers. Utilise l'un des téléporteurs pour revenir à la base.,"Remek volt. Szép munka volt a rabok kiszabadítása. Ugorj be valamelyik teleportba, és visszavisz a bázisba.","Ottimo lavoro, amico. Grazie a te i prigionieri sono stati liberati. Prendi uno dei teletrasporti e ti riporteremo alla base.","よくやった相棒。囚人を解放できたのは良い働きだ。 -いずれかのテレポーターに飛び込むと基地に戻る。","잘했어, 친구. 수감자들을 풀어주느라 고생했어. 저 텔레포터들 중 하나를 타면 우리 기지로 복귀할 수 있을 거야.","Goed gedaan, mijn vriend. Goed werk om de gevangenen te bevrijden. Spring op een van de teleporters en die brengt je terug naar de basis.","Sånn skal det gjøres, min venn. Godt jobbet med å befri fangene. Hopp på en av teleporterne, så kommer du tilbake til basen.","Brawo mój przyjacielu. Dobra robota z uwolnieniem więźniów. Wskocz na jeden z teleporterów, a przeniesie cię on z powrotem do bazy.","Boa, meu amigo. Bom trabalho ao libertar os prisioneiros. Entre num desses teletransportadores e você voltará pra base.",,Bună treabă prietene. Sari într-un teleportor și te va duce la baza noastră.,"Так держать, дружище. Ты отлично поработал и освободил пленников. Прыгай в любой телепорт, и он вернёт тебя на базу.",,Aferin dostum. Mahkûmları serbest bırakarak iyi iş çıkardın. Işınlayıcılardan birine atla ve seni üsse geri getirsin. -"Destroy the power crystal that runs the power grid which drives the Order's shields. Go visit Worner, a spy we recruited in the warehouse of the power station.",TXT_ILOG22,,,,"Znič energetický krystal, který napájí elektrickou síť, kterou jsou poháněné štíty Řádu. Jdi navštívit Wornera, špióna, kterého jsme najali ve skladu elektrárny.","Ødelæg energikrystallen, der driver det strømnet, som driver Ordenens skjolde. Besøg Worner, en spion, som vi rekrutterede i lageret på kraftværket.","Zerstöre den Energiekristall der die Energieversorgung für die Kraftschilde kontrolliert. Suche Worner auf, einen Spion, den wir im Lagerhaus des Kraftwerks rekrutiert haben. ",,,"Destruye el cristal de poder que impulsa la red eléctrica que alimenta los escudos de La Orden. Busca a Worner, un espía que reclutamos en el almacén de la central eléctrica.",,"Tuhoa kaupungin sähköverkon voimanlähteenä toimiva voimakristalli, jonka voimaa Veljeskunnan kilvet käyttävät. Mene tapaamaan Worneria, vakoojaa, jonka värväsimme voimalaitoksen varastolta.","Détruis le cristal qui contrôle la grille énergétique des boucliers de l'Ordre. Va voir Worner, un espion que l'on a recruté dans l'entrepôt de la centrale.","Semmisítsd meg az erő kristályt, ami a Rend külső védőpajzsát hajtja az elektromos hálózaton keresztül. Keresd fel az erőműtől betoborzott kémünket, Wornert.","Distruggi il cristallo che fornisce energia agli scudi dell'Ordine. Trova Worner, una spia che abbiamo reclutato nel magazzino della centrale energetica.","送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止めろ。 -発電所の倉庫に潜らせたスパイ、ワーナーを訪ねよ。","오더의 방어막을 유지하는 동력 망의 전력원인 수정체를 파괴하자. 우선, 발전소 창고에 있는 우리 쪽 첩자인 워너에게 찾아가 보자.","Vernietig het energiekristal dat het stroomnet dat de schilden van de Orde aandrijft. Ga op bezoek bij Worner, een spion die we gerekruteerd hebben in het magazijn van de centrale.","Ødelegg kraftkrystallen som driver kraftnettet som driver Ordenens skjold. Besøk Worner, en spion vi rekrutterte i kraftstasjonens lager.","Zniszcz kryształ mocy, który zasila sieć energetyczną napędzającą tarcze Zakonu. Idź odwiedzić Wornera, szpiega, którego zwerbowaliśmy w magazynie elektrowni.","Destrua o cristal de energia que alimenta a rede elétrica por trás dos escudos da Ordem. Visite o Worner, um espião que recrutamos no depósito da usina de energia.",,"Distruge cristalul de energie care alimentează scuturile Ordinului. Vizitează-l pe Worner, un spion recrutat în depozitul stației de energie.","Уничтожь кристалл, питающий энергосеть Ордена, от которой работают их щиты. Встреться с Уорнэром, нашим шпионом, на складе электростанции.",,Tarikat'ın kalkanlarını çalıştıran güç şebekesini çalıştıran güç kristalini yok edin. Güç istasyonunun deposunda işe aldığımız casus Worner'ı ziyaret et. -Let's get lost. There's more fun to come.,TXT_ILOG24,MAP04: After leaving Reactor Core.,,,"Ztraťme se, za chvíli tu bude víc srandy.",Lad os fare vild. Der er mere sjov på vej.,Lass uns verschwinden. Hier wird's gleich ungemütlich.,,,Hay que irse. La central está alerta.,,Häivytään. Lisää hupia on luvassa.,"Partons d'ici, il y a encore de quoi s'amuser.",Húzzunk innen. Most jön még az izgi rész.,Leviamoci di torno. C'è ancora da divertirsi.,迷子になったら、もっと楽しめるぞ。,어서 여길 떠나자. 녀석들이 오기 전에 말이야.,Laten we verdwalen. Er komt nog meer plezier.,La oss stikke. Det er mer moro i vente.,Zgubmy się. Czeka nas jeszcze więcej zabawy.,Então se manda. Tem mais diversão por vir.,,Să ne pierdem. O să mai fie distracții.,Давай-ка исчезнем отсюда. Скоро начнётся веселье.,,Hadi kaybolalım. Daha çok eğlence var. -"One more adventure before command feels it's safe to attack the castle. Macil's arranged for Irale to give you gold and some training. After you visit him, see the medic in town for strength.",TXT_ILOG25,MAP02: After destroying the crystal in the Power Station.,,,"Ještě jedno dobrodružství, než se velení rozhodne zaútočit. Macil sjednal u Iraleho zlato a trénink. Pak navštiv městského lékaře pro sílu.","Et eventyr mere, før kommandoen føler, at det er sikkert at angribe slottet. Macil har sørget for, at Irale giver dig guld og noget træning. Når du har besøgt ham, skal du gå til lægen i byen for at få styrke.","Eine weitere Aufgabe noch, bevor Macil es für sicher hält, die Burg anzugreifen. Macil hat Irale gebeten, dir Gold zu geben und Training zu organisieren. Nachdem du bei ihm warst, lass dir vom Sanitäter in der Stadt deine Ausdauer erhöhen.",,,"Una aventura más antes de que el comando sienta que es seguro atacar el castillo. Macil ha acordado con Irale que te dé oro y algo de entrenamiento. Después de visitarlo, ve al médico en el pueblo para ganar fuerza.",,"Vielä yksi seikkailu, ennen kuin komentokeskus katsoo tilanteen hyväksi hyökätä linnaa vastaan. Macil on järjestänyt Iralen antamaan sinulle kultaa ja koulutusta. Kun olet tavannut häntä, tapaa kaupungilla lääkintämiestä vahvistusta varten.","Encore une aventure avant que le commandement ne pense qu'il soit bon temps d'attaquer le château. Macil s'est arrangé pour qu'Irale te donne de l'argent et qu'il t'entraîne. Une fois que tu en as fini avec lui, va visiter le médecin en ville pour qu'il te rende des forces.","Még egy kaland, mielőtt az irányítás hatékony támadást indíthat a kastély ellen. Macil elintézte, hogy Irale ellásson arannyal és kiképzéssel. Utána keresd fel a szanitécet, hogy kicsit kipofozzon.","Un'ultima avventura prima dell'assedio al castello. Macil ha parlato ad Irale per farti avere dell'oro e un pò di addestramento. Dopo che gli hai fatto visita, parla anche dal medico in città per una marcia in più.","もう一つの任務をこなす前に戦力の増強が必要と考えられる。 +この壊れた配電機を渡して奴を騙し返せ。",참 잘했어! 총독이 거짓말을 했군. 이건 우리의 동력 장치야. 이걸 써서 우리 기지를 오더로부터 은폐시켜주지. 여기 있는 고장 난 장치를 전해주고 통행증이나 받자.,Goede zet! De Gouverneur is een leugenaar. Dat is onze stroomkoppeling. We gebruiken het om de basis te verbergen voor de Orde. Neem deze kapotte koppeling terug naar hem en laten we die pass pakken.,Godt trekk! Guvernøren er en løgner. Det er kraftkoblingen vår. Vi bruker den til å skjule basen for Ordenen. Ta denne ødelagte koblingen tilbake til ham og la oss få det passet.,"Dobry ruch! Gubernator to kłamca. To jest nasze sprzęgło mocy. Używamy go, by ukryć bazę przed Zakonem. Zabierz mu to zepsute sprzęgło i zdobądźmy tę przepustkę.",Boa! O Governador é um mentiroso . Essa é a nossa conexão. Vamos usá-la para esconder a base da Ordem. Leve esta conexão danificada de volta a ele e vamos pegar o passe.,,"Bună mutare! Guvernatorul e un mincins. Acela e cuplajul nostru. Îl folosim pentru a ne ascunde baza de Ordin. Ia cuplajul ăsta defect și du-l înapoi lui, să luăm permisul.","Отличный ход! Губернатор — лжец. Это наше подключение к силовой линии. Мы используем его, чтобы скрывать местоположение нашей базы от Ордена. Отнеси повреждённую муфту губернатору и получи пропуск.",,Bra gjort! Guvernören är en lögnare. Det är vår kraftkoppling. Vi använder den för att dölja basen för orden. Ta tillbaka den trasiga kopplingen till honom och låt oss få det där passet.,İyi hamle! Vali bir yalancı. Bu bizim güç bağlantımız. Üssü Tarikat'tan saklamak için kullanıyoruz. Bu kırık bağlantıyı ona geri götür ve şu geçiş iznini alalım. +Use the Warden's key to get into the prison cell blocks and find a way to free the prisoners.,TXT_ILOG18,MAP05: After crossing the alarm green door.,,,"Použij dozorcův klíč k dostání se do bloku s celami a najdi způsob, jak osvobodit vězně.",Brug fængselsdirektørens nøgle til at komme ind i fængselscelleblokkene og find en måde at befri fangerne på.,"Benutze den Schlüssel des Direktors um in die Zellenblöcke zu kommen und finde heraus, wie man die Gefangenen befreien kann.",,Uzu la ŝlosilon de la provoso por atingi la ĉelaron kaj trovu manieron liberigi la kaptitojn.,Usa la llave del carcelero para llegar a la galería y encuentra una forma de liberar a los prisioneros.,,Käytä vankilanjohtajan avainta päästäksesi vankilan selliosastoille ja keksi keino vapauttaa vangit.,Utilise la clé du gardien pour entrer dans le bloc de cellules et trouver une manière de libérer les prisonniers.,"Használd az igazgató kulcsát, hogy bejuss a börtön részlegbe, és kiszíbadíts mindenkit.",Usa la chiave del direttore per entrare nella sezione delle celle e trovare un modo per liberare i prigionieri.,"ワーデンの鍵で刑務所の独房区域に入って +囚人を解放する方法を見つける。","간수장의 열쇠를 써서 감옥 안으로 진입하고, 수감자들을 풀어줄 방법을 찾아봐.",Gebruik de sleutel van de bewaker om in de celblokken van de gevangenis te komen en een manier te vinden om de gevangenen te bevrijden.,Bruk direktørens nøkkel til å komme inn i fengselsblokkene og finn en måte å befri fangene på.,"Użyj klucza naczelnika, aby dostać się do bloków więziennych i znajdź sposób na uwolnienie więźniów.",Use a chave do Carcereiro para entrar nos blocos de celas e ache uma maneira de libertar os prisioneiros.,,Folosește cheia Directorului pentru a intra în blocurile celulelor și găsește o cale să eliberezi prizonierii.,"Используй ключ тюремщика, чтобы пройти к камерам. Найди способ освободить пленников.",,Använd direktörens nyckel för att ta dig in i fängelsecellblocken och hitta ett sätt att befria fångarna.,Hapishane hücre bloklarına girmek için Müdür'ün anahtarını kullan ve mahkumları serbest bırakmanın bir yolunu bul. +Find a way to free the prisoners. Find a way to open the hand scanner switch.,TXT_ILOG19,MAP05: After getting to Main Control.,,,"Najdi způsob, jak osvobodit vězně. Najdi způsob, jak aktivovat skener otisků ruky.",Find en måde at befri fangerne på. Find en måde at åbne håndscannerkontakten.,"Finde heraus, wie man die Gefangenen befreien kann und wie du den Handscanner umgehen kannst.",,Trovu manieron agigi la manskanilon por liberigi la kaptitojn.,Encuentra como activar el escáner de mano para liberar a los prisioneros.,,Etsi keino vapauttaa vangit. Ratkaise tapa avata kädenjälkilukijan lukitus.,Trouve un moyen de libérer les prisonniers. Trouve une manière d'activer le scanner à empreinte digitale.,"Találd meg a módját, hogyan szabadíthatjuk ki a rabokat, és hogyan játszhatjuk ki a kézlenyomat olvasót.",Trova un modo per liberare i prigionieri. Trova un modo per attivare lo scanner della mano.,"囚人を解放する方法を見つける。 + ハンドスキャナーを開く方法を見つける。",수감자들을 풀어줄 방법을 찾자. 지문인식장치를 통과할 방법을 찾아봐.,Zoek een manier om de gevangenen te bevrijden. Zoek een manier om de handscanner schakelaar te openen.,Finn en måte å befri fangene på. Finn en måte å åpne håndskannerbryteren på.,Znajdź sposób na uwolnienie więźniów. Znajdź sposób na otwarcie przełącznika skanera ręcznego.,Encontre uma maneira de libertar os prisioneiros. Ache uma maneira de abrir o scanner de mão.,,Găsește o cale să eliberezi prizonierii. Găsește o cale să deschizi comutatorul scanner-ului de mâini.,Найди способ освободить пленников. Найди способ открыть замок со сканером отпечатка руки.,,Hitta ett sätt att befria fångarna. Hitta ett sätt att öppna handskanneromkopplaren.,Mahkûmları serbest bırakmanın bir yolunu bul. El tarayıcı anahtarını açmanın bir yolunu bulun. +Find a way to free the prisoners. Use the judge's hand to operate the hand scanner switch.,TXT_ILOG20,MAP05: After cutting Wolenick's hand off.,,,"Najdi způsob, jak osvobodit vězně. Použij soudcovu ruku k aktivaci skeneru otisků ruky.",Find en måde at befri fangerne på. Brug dommerens hånd til at betjene håndscannerkontakten.,"Finde heraus, wie man die Gefangenen befreien kann. Benutze die Hand des Richters um den Handscannerschalter zu betätigen.",,Uzu la manon de la juĝisto por agigi la skanilon kaj liberigi la kaptitojn.,Usa la mano del juez para activar el escáner y liberar a los prisioneros.,,Etsi keino vapauttaa vangit. Käytä tuomarin kättä kädenjälkilukijaan.,Trouve un moyen de libérer les prisonniers. Utilise la main du juge pour activer le scanner à empreinte digitale.,"Találd meg a módját, hogyan szabadíthatjuk ki a rabokat, használd a bíró kezét a kézleolvasóhoz.",Trova un modo per liberare i prigionieri. Usa la mano del giudice per operare lo scanner.,"囚人を解放する方法を見つける。 +裁判官の手を使用してハンドスキャナースイッチを操作する。",수감자들을 풀어줄 방법을 찾자. 판사의 손을 써서 지문인식장치를 통과하는 거야.,Zoek een manier om de gevangenen te bevrijden. Gebruik de hand van de rechter om de handscanner schakelaar te bedienen.,Finn en måte å befri fangene på. Bruk dommerens hånd til å betjene håndskannerbryteren.,"Znajdź sposób na uwolnienie więźniów. Użyj ręki sędziego, aby uruchomić przełącznik skanera ręcznego.",Encontre uma maneira de libertar os prisioneiros. Use a mão do juiz para operar o scanner.,,Găsește o cale să eliberezi prizonierii. Folosește mâna judecătorului să operezi scanner-ul de mâini.,"Найди способ освободить пленников. Используй руку судьи, чтобы открыть замок со сканером отпечатка руки.",,Hitta ett sätt att befria fångarna. Använd domarens hand för att använda handskannern.,Mahkûmları serbest bırakmanın bir yolunu bulun. El tarayıcı anahtarını çalıştırmak için yargıcın elini kullan. +Way to go my friend. Good work freeing the prisoners. Jump on one of the teleporters and it will bring you back to base.,TXT_ILOG21,MAP05: After setting the prisoners free.,,,"Jen tak dál, příteli, dobrá práce. Skoč na teleportér, dostane tě to zpět na základnu.","Godt gået, min ven. Godt arbejde med at befri fangerne. Hop på en af teleportørerne, så kommer du tilbage til basen.","Das war gute Arbeit, wie du die Gefangenen befreit hast. Benutze einen der Teleporter um zur Basis zurückzugelangen.",,Danke al vi niaj kamaradoj estas liberaj. Uzu la teleportilon en la ĉelaro por reiri al la bazo.,Buen trabajo liberando a los prisioneros. Usa el teletransportador de la galería para volver a la base.,,"Niin sitä pitää, ystäväni. Hyvin toimittu vankien vapauttamisessa. Hyppää johonkin kaukosiirtimistä, ja se tuo sinut takaisin tukikohtaan.",Bien joué mon ami! Bon travail avec ces prisonniers. Utilise l'un des téléporteurs pour revenir à la base.,"Remek volt. Szép munka volt a rabok kiszabadítása. Ugorj be valamelyik teleportba, és visszavisz a bázisba.","Ottimo lavoro, amico. Grazie a te i prigionieri sono stati liberati. Prendi uno dei teletrasporti e ti riporteremo alla base.","よくやった相棒。囚人を解放できたのは良い働きだ。 +いずれかのテレポーターに飛び込むと基地に戻る。","잘했어, 친구. 수감자들을 풀어주느라 고생했어. 저 텔레포터들 중 하나를 타면 우리 기지로 복귀할 수 있을 거야.","Goed gedaan, mijn vriend. Goed werk om de gevangenen te bevrijden. Spring op een van de teleporters en die brengt je terug naar de basis.","Sånn skal det gjøres, min venn. Godt jobbet med å befri fangene. Hopp på en av teleporterne, så kommer du tilbake til basen.","Brawo mój przyjacielu. Dobra robota z uwolnieniem więźniów. Wskocz na jeden z teleporterów, a przeniesie cię on z powrotem do bazy.","Boa, meu amigo. Bom trabalho ao libertar os prisioneiros. Entre num desses teletransportadores e você voltará pra base.",,Bună treabă prietene. Sari într-un teleportor și te va duce la baza noastră.,"Так держать, дружище. Ты отлично поработал и освободил пленников. Прыгай в любой телепорт, и он вернёт тебя на базу.",,"Bra jobbat, min vän. Bra jobbat med att befria fångarna. Hoppa på en av teleporterna så tar den dig tillbaka till basen.",Aferin dostum. Mahkûmları serbest bırakarak iyi iş çıkardın. Işınlayıcılardan birine atla ve seni üsse geri getirsin. +"Destroy the power crystal that runs the power grid which drives the Order's shields. Go visit Worner, a spy we recruited in the warehouse of the power station.",TXT_ILOG22,,,,"Znič energetický krystal, který napájí elektrickou síť, kterou jsou poháněné štíty Řádu. Jdi navštívit Wornera, špióna, kterého jsme najali ve skladu elektrárny.","Ødelæg energikrystallen, der driver det strømnet, som driver Ordenens skjolde. Besøg Worner, en spion, som vi rekrutterede i lageret på kraftværket.","Zerstöre den Energiekristall der die Energieversorgung für die Kraftschilde kontrolliert. Suche Worner auf, einen Spion, den wir im Lagerhaus des Kraftwerks rekrutiert haben. ",,"Detruu la energian kristalon, kiu impulsas la elektrizan sistemon, kiu tenas la ŝildon de la kastelo. Renkontu nian spionon Worner en la magazeno (Warehouse) de la centralo (Power Station).","Destruye el cristal de poder que impulsa la red eléctrica que mantiene los escudos del castillo. Busca a Worner, un espía nuestro, en el almacén (Warehouse) de la central eléctrica (Power Station).",,"Tuhoa kaupungin sähköverkon voimanlähteenä toimiva voimakristalli, jonka voimaa Veljeskunnan kilvet käyttävät. Mene tapaamaan Worneria, vakoojaa, jonka värväsimme voimalaitoksen varastolta.","Détruis le cristal qui contrôle la grille énergétique des boucliers de l'Ordre. Va voir Worner, un espion que l'on a recruté dans l'entrepôt de la centrale.","Semmisítsd meg az erő kristályt, ami a Rend külső védőpajzsát hajtja az elektromos hálózaton keresztül. Keresd fel az erőműtől betoborzott kémünket, Wornert.","Distruggi il cristallo che fornisce energia agli scudi dell'Ordine. Trova Worner, una spia che abbiamo reclutato nel magazzino della centrale energetica.","送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止めろ。 +発電所の倉庫に潜らせたスパイ、ワーナーを訪ねよ。","오더의 방어막을 유지하는 동력 망의 전력원인 수정체를 파괴하자. 우선, 발전소 창고에 있는 우리 쪽 첩자인 워너에게 찾아가 보자.","Vernietig het energiekristal dat het stroomnet dat de schilden van de Orde aandrijft. Ga op bezoek bij Worner, een spion die we gerekruteerd hebben in het magazijn van de centrale.","Ødelegg kraftkrystallen som driver kraftnettet som driver Ordenens skjold. Besøk Worner, en spion vi rekrutterte i kraftstasjonens lager.","Zniszcz kryształ mocy, który zasila sieć energetyczną napędzającą tarcze Zakonu. Idź odwiedzić Wornera, szpiega, którego zwerbowaliśmy w magazynie elektrowni.","Destrua o cristal de energia que alimenta a rede elétrica por trás dos escudos da Ordem. Visite o Worner, um espião que recrutamos no depósito da usina de energia.",,"Distruge cristalul de energie care alimentează scuturile Ordinului. Vizitează-l pe Worner, un spion recrutat în depozitul stației de energie.","Уничтожь кристалл, питающий энергосеть Ордена, от которой работают их щиты. Встреться с Уорнэром, нашим шпионом, на складе электростанции.",,"Förstör kraftkristallen som driver kraftnätet som driver Ordens sköldar. Gå och besök Worner, en spion som vi rekryterade i kraftverkets lager.",Tarikat'ın kalkanlarını çalıştıran güç şebekesini çalıştıran güç kristalini yok edin. Güç istasyonunun deposunda işe aldığımız casus Worner'ı ziyaret et. +Let's get lost. There's more fun to come.,TXT_ILOG24,MAP04: After leaving Reactor Core.,,,"Ztraťme se, za chvíli tu bude víc srandy.",Lad os fare vild. Der er mere sjov på vej.,Lass uns verschwinden. Hier wird's gleich ungemütlich.,,Ni devas eliri: la alarmo eksonis.,Hay que irse: la central está alerta.,,Häivytään. Lisää hupia on luvassa.,"Partons d'ici, il y a encore de quoi s'amuser.",Húzzunk innen. Most jön még az izgi rész.,Leviamoci di torno. C'è ancora da divertirsi.,迷子になったら、もっと楽しめるぞ。,어서 여길 떠나자. 녀석들이 오기 전에 말이야.,Laten we verdwalen. Er komt nog meer plezier.,La oss stikke. Det er mer moro i vente.,Zgubmy się. Czeka nas jeszcze więcej zabawy.,Então se manda. Tem mais diversão por vir.,,Să ne pierdem. O să mai fie distracții.,Давай-ка исчезнем отсюда. Скоро начнётся веселье.,,Låt oss gå vilse. Det finns mer kul att göra.,Hadi kaybolalım. Daha çok eğlence var. +"One more adventure before command feels it's safe to attack the castle. Macil's arranged for Irale to give you gold and some training. After you visit him, see the medic in town for strength.",TXT_ILOG25,MAP02: After destroying the crystal in the Power Station.,,,"Ještě jedno dobrodružství, než se velení rozhodne zaútočit. Macil sjednal u Iraleho zlato a trénink. Pak navštiv městského lékaře pro sílu.","Et eventyr mere, før kommandoen føler, at det er sikkert at angribe slottet. Macil har sørget for, at Irale giver dig guld og noget træning. Når du har besøgt ham, skal du gå til lægen i byen for at få styrke.","Eine weitere Aufgabe noch, bevor Macil es für sicher hält, die Burg anzugreifen. Macil hat Irale gebeten, dir Gold zu geben und Training zu organisieren. Nachdem du bei ihm warst, lass dir vom Sanitäter in der Stadt deine Ausdauer erhöhen.",,"Ankoraŭ unu komisio por ke la Fronto sentu, ke sturmi la kastelon estas sekure. Macil diris al Irale, ke li donu oron kaj trejnadon al vi. Post tio, iru ĉe la kuracisto (Hospital) de la urbo pro la enplantaĵo.","Una misión más para que el comando sienta que es seguro asaltar el castillo. Macil le ha dicho a Irale que te dé oro y entrenamiento. Tras visitarlo, ve con el médico del pueblo para cambiar el implante.","Una misión más para que el comando sienta que es seguro asaltar el castillo. Macil le dijo a Irale que te dé oro y entrenamiento. Tras visitarlo, ve con el médico del pueblo para cambiar el implante.","Vielä yksi seikkailu, ennen kuin komentokeskus katsoo tilanteen hyväksi hyökätä linnaa vastaan. Macil on järjestänyt Iralen antamaan sinulle kultaa ja koulutusta. Kun olet tavannut häntä, tapaa kaupungilla lääkintämiestä vahvistusta varten.","Encore une aventure avant que le commandement ne pense qu'il soit bon temps d'attaquer le château. Macil s'est arrangé pour qu'Irale te donne de l'argent et qu'il t'entraîne. Une fois que tu en as fini avec lui, va visiter le médecin en ville pour qu'il te rende des forces.","Még egy kaland, mielőtt az irányítás hatékony támadást indíthat a kastély ellen. Macil elintézte, hogy Irale ellásson arannyal és kiképzéssel. Utána keresd fel a szanitécet, hogy kicsit kipofozzon.","Un'ultima avventura prima dell'assedio al castello. Macil ha parlato ad Irale per farti avere dell'oro e un po' di addestramento. Dopo che gli hai fatto visita, parla anche dal medico in città per una marcia in più.","もう一つの任務をこなす前に戦力の増強が必要と考えられる。 マシルがイラールを介して資金と訓練の手配をしてくれるので会いなさい。 -それと近所のメディックも支援してくれるわ。",본부가 공성전을 진행하기 전에 한 가지 해야 할 일이 있어. 마실이 이롤리에게 골드랑 훈련을 제공해달라고 부탁했대. 그리고 마을 병원에 가서 근력을 키워달라고 해.,"Nog een avontuur voor het commando het gevoel heeft dat het veilig is om het kasteel aan te vallen. Macil heeft geregeld dat Irale je goud en wat training geeft. Nadat je hem hebt bezocht, ga je naar de dokter in de stad voor kracht.","Ett eventyr til før kommandoen mener det er trygt å angripe slottet. Macil har sørget for at Irale gir deg gull og litt trening. Etter at du har besøkt ham, gå til legen i byen for å få styrke.","Jeszcze jedna przygoda, zanim dowództwo uzna, że można bezpiecznie zaatakować zamek. Macil umówił się z Irale, że da ci złoto i trochę treningu. Po wizycie u niego, udaj się do medyka w mieście po siłę.","Mais uma aventura antes que o comando ache que é seguro o bastante para atacar o castelo. Macil instruiu Irale a te passar ouro e treinamento. Após visitá-lo, vá ao médico para te dar uma força.",,"Încă o aventură până ce comanda e încrezătoare în atacarea castelului. Macil a aranjat ca Irale să îți ofere bani și antrenament. Dupa ce îț vizitezi, mergi la medicul din oraș pentru forță.","Ещё одно приключение, и штаб будет уверен в успешности атаки на замок. Мэйсил поручил Ирэйлу выплатить тебе награду и дать пару уроков. После встречи с ним, посети городского медика.",,"Komutanlık kaleye saldırmanın güvenli olduğunu düşünmeden önce bir macera daha. Macil, İrale'nin sana altın ve biraz eğitim vermesini ayarladı. Onu ziyaret ettikten sonra, güç için kasabadaki doktoru gör." -"Visit Irale and the medic in town for gold and training, then find the sewers. Head along the river across from the Governor's mansion.",TXT_ILOG26,〃,,,"Navštiv Iraleho a doktora pro zlato a trénink, pak najdi stoky. Jdi podél řeky naproti guvernérově sídlu.","Besøg Irale og lægen i byen for at få guld og træning, og find derefter kloakkerne. Gå langs floden over for guvernørens palæ.","Geh zu Irale und dem Sanitäter in der Stadt, um etwas Gold und Training zu bekommen, dann finde die Kanalisation. Folge dem Fluss auf der gegenüberliegenden Seite der Villa des Gouverneurs.",,,"Visita a Irale y al médico en el pueblo para oro y entrenamiento, luego encuentra las alcantarillas. Dirígete a través del río junto a la mansión del gobernador.",,"Tapaa Iralea ja lääkintämiestä kaupungilla kultaa ja koulutusta varten, minkä jälkeen löydä viemärit. Kulje joen vartta kuvernöörin kartanoa vastapäätä.","Visite Irale et le médecin en ville pour de l'argent et de l'entraînement, puis trouve l'entrée des égouts. Descend le long de la rivière de l'autre côté du manoir du gouverneur.","Keresd fel Iralet és a szanitécet a városban egy kis aranyért és kiképzésért, aztán irány a kanáris. Menj a folyón ami átszeli a kormányzó kúriáját.","Visita Irale e il medico in città per oro e addestramento, dopodiché trova le fogne. Vi puoi accedere dal fiume vicino alla dimora del governatore.","イラールとメディックを尋ねて資金と訓練を受け、下水道に向かうんだ。 -入り口は知事のマンションの川を挟んだ向かい側だ。","이롤리와 마을 의무관에게 가서 골드와 훈련을 받고, 하수구를 찾아. 총독의 관저 건너편의 강을 따라서 가봐.","Bezoek Irale en de dokter in de stad voor goud en training, en zoek dan de riolen. Loop langs de rivier tegenover het landhuis van de gouverneur.","Besøk Irale og legen i byen for gull og trening, og finn deretter kloakken. Gå langs elven overfor guvernørens hus.","Odwiedź Irale i medyka w mieście po złoto i trening, a następnie znajdź kanały. Skieruj się wzdłuż rzeki naprzeciwko rezydencji gubernatora.",Visite o Irale e o médico na cidade para ouro e treinamento. Depois encontre o esgoto. Vá para o rio do outro lado da mansão do Governador.,,"Vizitează pe Irale și medicul din oraș pentru aur și antrenament, apoi găsește canalele. Urmează râul de lângă complexul Guvernatorului.","Зайди к Ирэйлу и городскому медику за золотом и обучением, потом спустись в канализацию. Иди вдоль берега реки, спуск прямо напротив особняка губернатора.",,"Altın ve eğitim için İrale'yi ve kasabadaki doktoru ziyaret edin, ardından kanalizasyonları bulun. Valinin konağının karşısındaki nehir boyunca ilerleyin." -"We're looking for Weran, who calls himself the Rat King. I'm sure it's descriptive as well as colorful.",TXT_ILOG28,MAP06: Entrance.,,,"Hledáma Werana, který si říká Krysí král. Jsem si jistá, že to je jak barvité, tak přesné.","Vi leder efter Weran, som kalder sig selv Rottekongen. Det er sikkert både beskrivende og farverigt.","Wir suchen Weran, den man auch den Rattenkönig nennt. Ich bin sicher, dass dies ihn sehr anschaulich beschreibt.",,,"Estamos buscando a Weran, quien se autoproclama el Rey de las Ratas. Estoy segura de que es tanto descriptivo como vistoso.",,"Etsimme Werania, joka kutsuu itseään Rottakuninkaaksi. Varmastikin kuvaava titteli, mutta myös väritetty.","Cherche Weran, il se fait appeler le Roi des Rats. Je suis sur que c'est aussi descriptif que flatteur.","Werant keressük, aki magát csak a Patkány Királyként emlegeti. Biztos vagyok, hogy nem csak színes név, de valszeg hasonlít is hozzá.","Stiamo cercando Weran, che si fa chiamare il Re dei Ratti. Sono sicura che lo descrive appieno.","誰が呼んだかラットキングのウェランを探すんだ。 -それが叙述的でもあり派手な呼び名なのも定かだ。",우리는 자신을 시궁쥐 왕이라고 부르는 워렌을 찾아야 해. 알록달록해서 눈에 잘 띌 것 같은데 말이야.,"We zijn op zoek naar Weran, die zichzelf de rattenkoning noemt. Ik weet zeker dat het zowel beschrijvend als kleurrijk is.","Vi leter etter Weran, som kaller seg Rottekongen. Det er sikkert både beskrivende og fargerikt.","Szukamy Werana, który nazywa siebie Królem Szczurów. Na pewno jest to opisowe, jak i barwne.","Estamos procurando pelo Weran, que se autodenomina o Rato Rei. Imagino que isso seja tão descritivo quanto gracioso.",,"Îl căutam pe Weran, care ăși spune Regele Șobolanilor. Sunt sigur că e descriptiv și colorat.","Нам нужен Уэран — он называет себя Крысиным королём. Уверена, прозвище так же емко, как и красочно.",,Kendisine Fare Kral diyen Weran'ı arıyoruz. Renkli olduğu kadar açıklayıcı da olduğuna eminim. -"Take the flamethrower parts to Irale. Drain the reclamation tank. At the bottom is a hidden entrance to the sewers. The gate controls are down there, somewhere. Destroy them.",TXT_ILOG33,MAP06: After giving the guard's uniform to Weran.,,,Vezmi části plamenometu k Iralemu. Vypusť obnovovací nádrž. Na dně je skrytý vchod do stok. Někde tam je ovládání bran. Znič jej.,Tag flammekasterdelene med til Irale. Tøm genvindingstanken. I bunden er der en skjult indgang til kloakkerne. Kontrolelementerne til porten er dernede et sted. Ødelæg dem.,Bringe dir Flammenwerferteile zu Irale. Leere den Sammeltank. Am Boden ist ein versteckter Eingang zur Kanalisation. Dort ist die Steuerung für die Tore. Zerstöre sie.,,,"Llévale las partes de lanzallamas a Irale. Drena el tanque de recuperación del castillo: al fondo hay una entrada secreta a las alcantarillas. Los controles de la puerta están por ahí, en algún lugar. Destrúyelos.",,Toimita liekinheittimen osat Iralelle. Tyhjennä nesteentalteenottoallas. Sen pohjalla on viemärin salainen sisäänkäynti. Portin ohjaimet sijaitsevat jossakin siellä. Tuhoa ne.,Amène les pièces du lance-flamme à Irale. Fais vider le réservoir de recyclage. Au fond se trouve une entrée cachée vers les égouts. Les contrôles de la porte s'y trouvent. Détruis-les.,Vidd a lángszóró darabokat Iralehez. Ereszd le a szárító tartályt. Az alján megtalálod a titkos lejáratot a kanárisba. A kapu vezérlése ott van lent valahol. Semmisítsd meg őket.,"Porta i pezzi del lanciafiamme da Irale. Svuota la vasca di recupero fluidi. Nel fondo c'è un'entrata nascosta per le fogne. I controlli dei cancelli sono laggiù, da qualche parte. Distruggili.","火炎放射器の部品をイラールに持っていく。 +それと近所のメディックも支援してくれるわ。",본부가 공성전을 진행하기 전에 한 가지 해야 할 일이 있어. 마실이 이롤리에게 골드랑 훈련을 제공해달라고 부탁했대. 그리고 마을 병원에 가서 근력을 키워달라고 해.,"Nog een avontuur voor het commando het gevoel heeft dat het veilig is om het kasteel aan te vallen. Macil heeft geregeld dat Irale je goud en wat training geeft. Nadat je hem hebt bezocht, ga je naar de dokter in de stad voor kracht.","Ett eventyr til før kommandoen mener det er trygt å angripe slottet. Macil har sørget for at Irale gir deg gull og litt trening. Etter at du har besøkt ham, gå til legen i byen for å få styrke.","Jeszcze jedna przygoda, zanim dowództwo uzna, że można bezpiecznie zaatakować zamek. Macil umówił się z Irale, że da ci złoto i trochę treningu. Po wizycie u niego, udaj się do medyka w mieście po siłę.","Mais uma aventura antes que o comando ache que é seguro o bastante para atacar o castelo. Macil instruiu Irale a te passar ouro e treinamento. Após visitá-lo, vá ao médico para te dar uma força.",,"Încă o aventură până ce comanda e încrezătoare în atacarea castelului. Macil a aranjat ca Irale să îți ofere bani și antrenament. Dupa ce îț vizitezi, mergi la medicul din oraș pentru forță.","Ещё одно приключение, и штаб будет уверен в успешности атаки на замок. Мэйсил поручил Ирэйлу выплатить тебе награду и дать пару уроков. После встречи с ним, посети городского медика.",,Ett äventyr till innan kommandot känner att det är säkert att attackera slottet. Macil har ordnat så att Irale ger dig guld och lite träning. Efter att du besökt honom ska du gå till läkaren i staden för att få styrka.,"Komutanlık kaleye saldırmanın güvenli olduğunu düşünmeden önce bir macera daha. Macil, İrale'nin sana altın ve biraz eğitim vermesini ayarladı. Onu ziyaret ettikten sonra, güç için kasabadaki doktoru gör." +"Visit Irale and the medic in town for gold and training, then find the sewers. Head along the river across from the Governor's mansion.",TXT_ILOG26,〃,,,"Navštiv Iraleho a doktora pro zlato a trénink, pak najdi stoky. Jdi podél řeky naproti guvernérově sídlu.","Besøg Irale og lægen i byen for at få guld og træning, og find derefter kloakkerne. Gå langs floden over for guvernørens palæ.","Geh zu Irale und dem Sanitäter in der Stadt, um etwas Gold und Training zu bekommen, dann finde die Kanalisation. Folge dem Fluss auf der gegenüberliegenden Seite der Villa des Gouverneurs.",,"Iru ĉe Irale kaj ĉe la kuracisto (Hospital) de la urbo, tiam trovu la kloakon: serĉu enirejon inter la rojo kaj la urbodomo.","Visita a Irale y al médico del pueblo, luego encuentra las alcantarillas: busca una entrada entre el arroyo y el ayuntamiento.",,"Tapaa Iralea ja lääkintämiestä kaupungilla kultaa ja koulutusta varten, minkä jälkeen löydä viemärit. Kulje joen vartta kuvernöörin kartanoa vastapäätä.","Visite Irale et le médecin en ville pour de l'argent et de l'entraînement, puis trouve l'entrée des égouts. Descend le long de la rivière de l'autre côté du manoir du gouverneur.","Keresd fel Iralet és a szanitécet a városban egy kis aranyért és kiképzésért, aztán irány a kanáris. Menj a folyón ami átszeli a kormányzó kúriáját.","Visita Irale e il medico in città per oro e addestramento, dopodiché trova le fogne. Vi puoi accedere dal fiume vicino alla dimora del governatore.","イラールとメディックを尋ねて資金と訓練を受け、下水道に向かうんだ。 +入り口は知事のマンションの川を挟んだ向かい側だ。","이롤리와 마을 의무관에게 가서 골드와 훈련을 받고, 하수구를 찾아. 총독의 관저 건너편의 강을 따라서 가봐.","Bezoek Irale en de dokter in de stad voor goud en training, en zoek dan de riolen. Loop langs de rivier tegenover het landhuis van de gouverneur.","Besøk Irale og legen i byen for gull og trening, og finn deretter kloakken. Gå langs elven overfor guvernørens hus.","Odwiedź Irale i medyka w mieście po złoto i trening, a następnie znajdź kanały. Skieruj się wzdłuż rzeki naprzeciwko rezydencji gubernatora.",Visite o Irale e o médico na cidade para ouro e treinamento. Depois encontre o esgoto. Vá para o rio do outro lado da mansão do Governador.,,"Vizitează pe Irale și medicul din oraș pentru aur și antrenament, apoi găsește canalele. Urmează râul de lângă complexul Guvernatorului.","Зайди к Ирэйлу и городскому медику за золотом и обучением, потом спустись в канализацию. Иди вдоль берега реки, спуск прямо напротив особняка губернатора.",,Besök Irale och läkaren i staden för att få guld och träning och hitta sedan kloakerna. Gå längs floden mittemot guvernörens herrgård.,"Altın ve eğitim için İrale'yi ve kasabadaki doktoru ziyaret edin, ardından kanalizasyonları bulun. Valinin konağının karşısındaki nehir boyunca ilerleyin." +"We're looking for Weran, who calls himself the Rat King. I'm sure it's descriptive as well as colorful.",TXT_ILOG28,MAP06: Entrance.,,,"Hledáma Werana, který si říká Krysí král. Jsem si jistá, že to je jak barvité, tak přesné.","Vi leder efter Weran, som kalder sig selv Rottekongen. Det er sikkert både beskrivende og farverigt.","Wir suchen Weran, den man auch den Rattenkönig nennt. Ich bin sicher, dass dies ihn sehr anschaulich beschreibt.",,"Ni serĉas Weran-on, kiu proklamas sin mem la Rat-reĝo. Mi estas certa, ke tio estas tre fidela priskribo.","Estamos buscando a Weran, quien se autoproclama el Rey de las Ratas. Estoy segura de que es fielmente descriptivo.",,"Etsimme Werania, joka kutsuu itseään Rottakuninkaaksi. Varmastikin kuvaava titteli, mutta myös väritetty.","Cherche Weran, il se fait appeler le Roi des Rats. Je suis sur que c'est aussi descriptif que flatteur.","Werant keressük, aki magát csak a Patkány Királyként emlegeti. Biztos vagyok, hogy nem csak színes név, de valszeg hasonlít is hozzá.","Stiamo cercando Weran, che si fa chiamare il Re dei Ratti. Sono sicura che lo descrive appieno.","誰が呼んだかラットキングのウェランを探すんだ。 +それが叙述的でもあり派手な呼び名なのも定かだ。",우리는 자신을 시궁쥐 왕이라고 부르는 워렌을 찾아야 해. 알록달록해서 눈에 잘 띌 것 같은데 말이야.,"We zijn op zoek naar Weran, die zichzelf de rattenkoning noemt. Ik weet zeker dat het zowel beschrijvend als kleurrijk is.","Vi leter etter Weran, som kaller seg Rottekongen. Det er sikkert både beskrivende og fargerikt.","Szukamy Werana, który nazywa siebie Królem Szczurów. Na pewno jest to opisowe, jak i barwne.","Estamos procurando pelo Weran, que se autodenomina o Rato Rei. Imagino que isso seja tão descritivo quanto gracioso.",,"Îl căutam pe Weran, care ăși spune Regele Șobolanilor. Sunt sigur că e descriptiv și colorat.","Нам нужен Уэран — он называет себя Крысиным королём. Уверена, прозвище так же емко, как и красочно.",,Vi letar efter Weran som kallar sig för råttkungen. Jag är säker på att det är både beskrivande och färgstarkt.,Kendisine Fare Kral diyen Weran'ı arıyoruz. Renkli olduğu kadar açıklayıcı da olduğuna eminim. +"Take the flamethrower parts to Irale. Drain the reclamation tank. At the bottom is a hidden entrance to the sewers. The gate controls are down there, somewhere. Destroy them.",TXT_ILOG33,MAP06: After giving the guard's uniform to Weran.,,,Vezmi části plamenometu k Iralemu. Vypusť obnovovací nádrž. Na dně je skrytý vchod do stok. Někde tam je ovládání bran. Znič jej.,Tag flammekasterdelene med til Irale. Tøm genvindingstanken. I bunden er der en skjult indgang til kloakkerne. Kontrolelementerne til porten er dernede et sted. Ødelæg dem.,Bringe dir Flammenwerferteile zu Irale. Leere den Sammeltank. Am Boden ist ein versteckter Eingang zur Kanalisation. Dort ist die Steuerung für die Tore. Zerstöre sie.,,"Portu la partojn de la flamĵetilo al Irale. Drenu la rezervujon en la kastelo: en ĝia fundo estas kaŝita enirejo al la kloako, kaj ie tie estas la regilo de la pordo; detruu ĝin.",Llévale las partes del lanzallamas a Irale. Drena el tanque de recuperación del castillo: al fondo hay una entrada secreta a las alcantarillas y por ahí mismo el control de la puerta; destrúyelo.,,Toimita liekinheittimen osat Iralelle. Tyhjennä nesteentalteenottoallas. Sen pohjalla on viemärin salainen sisäänkäynti. Portin ohjaimet sijaitsevat jossakin siellä. Tuhoa ne.,Amène les pièces du lance-flamme à Irale. Fais vider le réservoir de recyclage. Au fond se trouve une entrée cachée vers les égouts. Les contrôles de la porte s'y trouvent. Détruis-les.,Vidd a lángszóró darabokat Iralehez. Ereszd le a szárító tartályt. Az alján megtalálod a titkos lejáratot a kanárisba. A kapu vezérlése ott van lent valahol. Semmisítsd meg őket.,"Porta i pezzi del lanciafiamme da Irale. Svuota la vasca di recupero fluidi. Nel fondo c'è un'entrata nascosta per le fogne. I controlli dei cancelli sono laggiù, da qualche parte. Distruggili.","火炎放射器の部品をイラールに持っていく。 浄化タンクを排水せよ。その下層に下水道への隠された入り口がある。 -ゲートコントロールを探し出し、破壊せよ。",이 화염방사기 부품을 가지고 이롤리에게 말 걸어봐. 수조에 있는 물을 비우면 밑에 하수도로 향하는 비밀 입구가 보일 거야. 성문의 관리 장치가 여기 어딘가에 있을 거야. 찾으면 파괴해.,"Neem de vlammenwerperonderdelen mee naar Irale. Laat de terugwinnings tank leeglopen. Onderaan is een verborgen ingang naar de riolering. De poortbediening is daar beneden, ergens. Vernietig ze.","Ta flammekasterdelene til Irale. Tøm utvinningstanken. Nederst er det en skjult inngang til kloakken. Portkontrollene er der nede, et sted. Ødelegg dem.",Zabierz części miotacza ognia do Irale. Opróżnij zbiornik rekultywacyjny. Na dole jest ukryte wejście do kanałów. Sterowniki bramy są gdzieś tam na dole. Zniszcz je.,Leve as peças do lança-chamas ao Irale. Drene o tanque de recuperação. No fundo há uma entrada oculta para o esgoto. Os controles do portão estão lá embaixo em algum lugar. Destrua-os.,,"Du bucățiile aruncătorului la Irale. Drenează rezervorul recuperării. La fund e o intrare secretă către canale. Controlul porții e jos, undeva. Distruge-l.","Отнеси детали огнемёта Ирэйлу. Слей жидкость из бака для переработки. На его дне скрытый вход в канализацию. Механизм управления воротами где-то там, внизу. Сломай его.",,Alev makinesi parçalarını İrale'ye götür. Islah tankını boşaltın. En altta kanalizasyona gizli bir giriş var. Kapı kontrolleri aşağıda bir yerde. Onları yok et. -"Command, he's done it! The gates are open. Send in the shock troops and tell Macil we're coming in! Let's get back to the Front base.",TXT_ILOG37,MAP06: After destroying the gate controls.,,,"Velení, dokázal to! Brány jsou otevřené. Pošlete tam úderníky a řekněte Macilovi, že přicházíme! Vrať se na základnu Fronty.","Kommando, han har gjort det! Portene er åbne. Send choktropperne ind og fortæl Macil, at vi kommer ind! Lad os komme tilbage til frontbasen.",Kommandozentrale: Er hat's geschafft! Die Tore sind offen. Schickt die Schocktruppen hinein und sagt Macil das wir auf dem Weg sind! Lass uns zur Frontbasis zurückkehren.,,,"¡Comando, lo ha conseguido! Las puertas ya están abiertas. ¡Enviad a las tropas de choque y decidle a Macil que ya es hora de entrar! Volvamos a la base del Frente.","Comando, ¡Lo ha hecho! Las puertas están abiertas. ¡Envíen las tropas de choque y díganel a Macil que estamos entrando! Regresemos a la base del Frente.","Komentokeskus, hän teki sen! Portit ovat auki; lähettäkää iskujoukot ja kertokaa Macilille, että vyörymme sisään! Palataan Rintaman tukikohtaan.","C'est bon, commandement, il a réussi! Les portes sont ouvertes, envoyez les soldats de choc et dites à Macil que l'on arrive! Retournons à la base du Front.","Irányítás, megcsinálta! A kpuk kinyíltak. Küldjétek be az elektromos egységeket, és értesítsd Macilt hogy jövünk! Irány vissza a homlokfronthoz.","Comando, ce l'ha fatta! I cancelli sono aperti. Mandate avanti le truppe e dite a Macil che stiamo arrivando! Torniamo alla base del Fronte.","司令官、彼はやったぞ! -ゲートが開いた。突撃部隊を送って我々も続くとマシルに伝えてくれ!",본부! 그가 해냈습니다! 성문이 열렸습니다. 공습부대를 성문으로 이동시키고 사령관님께 우리들도 따라올 거라고 전해주세요. 이제 프론트 기지로 돌아가!,"Commando, hij heeft het gedaan! De poorten zijn open. Stuur de stoottroepen naar binnen en zeg Macil dat we binnenkomen! Laten we teruggaan naar de voorste basis.","Kommando, han har klart det! Portene er åpne. Send inn sjokktroppene og si til Macil at vi kommer inn! La oss dra tilbake til frontbasen.","Dowództwo, udało mu się! Wrota są otwarte. Wyślij oddziały uderzeniowe i powiedz Macilowi, że wchodzimy! Wracajmy do bazy frontowej.","Comando, ele conseguiu! Os portões estão abertos. Mande as tropas de choque e diga ao Macil que estamos entrando! Vamos voltar pra base da Frente.",,"Comandă, a reușit! Porțile sunt deschise. Trimite trupele de șoc și spune-i lui Macil că intrăm! Să ne întoarcem la baza Frontului.","Штаб, он выполнил задание! Ворота открыты. Посылайте ударный отряд и доложите Мэйсилу, что мы пробились! Возвращайся на базу Сопротивления.",,"Komuta, başardı! Kapılar açıldı. Şok birliklerini gönderin ve Macil'e geldiğimizi söyleyin! Cephe üssüne geri dönelim." -"Join the assault on the castle. Find and take out the Programmer. We have conflicting reports about his location. One says he in a computer room, another hiding in a sub-level temple, and yet another at the end of a long hallway.",TXT_ILOG38,MAP03: After destroying the gate controls and talking to Macil.,,,"Připoj se k útoku na hrad. Najdi a zabij Programátora. Informace o jeho pozici se různí. Jedna mluví o místnosti s počítači, druhá o podzemním chrámu a třetí o konci dlouhé chodby.","Deltag i angrebet på slottet. Find og udslæt programmøren. Vi har modstridende rapporter om hans placering. En siger, at han er i et computerrum, en anden, at han gemmer sig i et tempel på et underliggende niveau, og endnu en anden for enden af en lang korridor.","Schließe dich dem Angriff auf die Burg an. Finde den Programmierer und schalte ihn aus. Wir haben widersprüchliche Angaben über seinen Aufenthaltsort. Eine sagt, in einem Computerraum, ein anderer, dass er sich in einem Tempelkeller versteckt und noch ein anderer sagt was vom Ende eines langen Flurs.",,,"Únete al asalto en el castillo. Encuentra y elimina al Programador. Tenemos informes contradictorios sobre su ubicación. Uno dice que está en una sala de computadoras, otro que se esconde en un templo en el subnivel, y también otro que al final de un largo pasillo.",,"Osallistu hyökkäykseen linnaa vastaan. Etsi ja kukista Ohjelmoitsija. Meillä on hänen sijainnistaan eriäviä tietoja: Yhden mukaan hän on tietokonehuoneessa, toisen mukaan maanalaisessa temppelissä ja vielä kolmannen mukaan pitkän käytävän päässä.","Rejoins l'assaut sur le château. Trouve et élimine le Programmeur. On a des rapports en conflit sur sa position. L'un d'entre eux nous dit qu'il se trouve dans la salle des ordinateurs, l'autre nous dit qu'il se cache dans un temple en sous sol, et un autre encore au bout d'un long couloir.","Csatlakozz a kastély ostromához. Keresd meg és iktasd ki a Programozót. Ellentmondó információink vannak a hollétéről. Az egyik szerint a számítógép szobában van, másik szerint egy föld alatti templomban, harmadik szerint egy hosszú folyosó végén.","Unisciti all'assalto sul castello. Trova e fai fuori il Programmatore. I rapporti che abbiamo sulla sua posizione si contraddicono. Uno lo piazza in una stanza di computer, un altro in un tempio di sottolivello, e un altro ancora alla fine di un lungo corridoio.","城に向かう突撃部隊に参加してプログラマーを探し出せ。 +ゲートコントロールを探し出し、破壊せよ。",이 화염방사기 부품을 가지고 이롤리에게 말 걸어봐. 수조에 있는 물을 비우면 밑에 하수도로 향하는 비밀 입구가 보일 거야. 성문의 관리 장치가 여기 어딘가에 있을 거야. 찾으면 파괴해.,"Neem de vlammenwerperonderdelen mee naar Irale. Laat de terugwinnings tank leeglopen. Onderaan is een verborgen ingang naar de riolering. De poortbediening is daar beneden, ergens. Vernietig ze.","Ta flammekasterdelene til Irale. Tøm utvinningstanken. Nederst er det en skjult inngang til kloakken. Portkontrollene er der nede, et sted. Ødelegg dem.",Zabierz części miotacza ognia do Irale. Opróżnij zbiornik rekultywacyjny. Na dole jest ukryte wejście do kanałów. Sterowniki bramy są gdzieś tam na dole. Zniszcz je.,Leve as peças do lança-chamas ao Irale. Drene o tanque de recuperação. No fundo há uma entrada oculta para o esgoto. Os controles do portão estão lá embaixo em algum lugar. Destrua-os.,,"Du bucățiile aruncătorului la Irale. Drenează rezervorul recuperării. La fund e o intrare secretă către canale. Controlul porții e jos, undeva. Distruge-l.","Отнеси детали огнемёта Ирэйлу. Слей жидкость из бака для переработки. На его дне скрытый вход в канализацию. Механизм управления воротами где-то там, внизу. Сломай его.",,Ta med dig flamethrowerdelarna till Irale. Töm återvinningstanken. I botten finns en dold ingång till kloakerna. Grindkontrollerna finns där nere någonstans. Förstör dem.,Alev makinesi parçalarını İrale'ye götür. Islah tankını boşaltın. En altta kanalizasyona gizli bir giriş var. Kapı kontrolleri aşağıda bir yerde. Onları yok et. +"Command, he's done it! The gates are open. Send in the shock troops and tell Macil we're coming in! Let's get back to the Front base.",TXT_ILOG37,MAP06: After destroying the gate controls.,,,"Velení, dokázal to! Brány jsou otevřené. Pošlete tam úderníky a řekněte Macilovi, že přicházíme! Vrať se na základnu Fronty.","Kommando, han har gjort det! Portene er åbne. Send choktropperne ind og fortæl Macil, at vi kommer ind! Lad os komme tilbage til frontbasen.",Kommandozentrale: Er hat's geschafft! Die Tore sind offen. Schickt die Schocktruppen hinein und sagt Macil das wir auf dem Weg sind! Lass uns zur Frontbasis zurückkehren.,,"Fronto, li sukcesis! Li malfermis la pordojn. Sendu la sturmantojn kaj diru al Macil, ke estas tempo eniri! Ni reiru al la bazo de la Fronto.","¡Comando, lo ha conseguido! Las puertas ya están abiertas. ¡Enviad a las tropas de choque y decidle a Macil que ya es hora de entrar! Volvamos a la base del Frente.","¡Comando, lo logró! Las puertas ya están abiertas. ¡Manden a las tropas de choque y díganle a Macil que ya es hora de entrar! Volvamos a la base del Frente.","Komentokeskus, hän teki sen! Portit ovat auki; lähettäkää iskujoukot ja kertokaa Macilille, että vyörymme sisään! Palataan Rintaman tukikohtaan.","C'est bon, commandement, il a réussi! Les portes sont ouvertes, envoyez les soldats de choc et dites à Macil que l'on arrive! Retournons à la base du Front.","Irányítás, megcsinálta! A kpuk kinyíltak. Küldjétek be az elektromos egységeket, és értesítsd Macilt hogy jövünk! Irány vissza a homlokfronthoz.","Comando, ce l'ha fatta! I cancelli sono aperti. Mandate avanti le truppe e dite a Macil che stiamo arrivando! Torniamo alla base del Fronte.","司令官、彼はやったぞ! +ゲートが開いた。突撃部隊を送って我々も続くとマシルに伝えてくれ!",본부! 그가 해냈습니다! 성문이 열렸습니다. 공습부대를 성문으로 이동시키고 사령관님께 우리들도 따라올 거라고 전해주세요. 이제 프론트 기지로 돌아가!,"Commando, hij heeft het gedaan! De poorten zijn open. Stuur de stoottroepen naar binnen en zeg Macil dat we binnenkomen! Laten we teruggaan naar de voorste basis.","Kommando, han har klart det! Portene er åpne. Send inn sjokktroppene og si til Macil at vi kommer inn! La oss dra tilbake til frontbasen.","Dowództwo, udało mu się! Wrota są otwarte. Wyślij oddziały uderzeniowe i powiedz Macilowi, że wchodzimy! Wracajmy do bazy frontowej.","Comando, ele conseguiu! Os portões estão abertos. Mande as tropas de choque e diga ao Macil que estamos entrando! Vamos voltar pra base da Frente.",,"Comandă, a reușit! Porțile sunt deschise. Trimite trupele de șoc și spune-i lui Macil că intrăm! Să ne întoarcem la baza Frontului.","Штаб, он выполнил задание! Ворота открыты. Посылайте ударный отряд и доложите Мэйсилу, что мы пробились! Возвращайся на базу Сопротивления.",,"Kommando, han har gjort det! Portarna är öppna. Skicka in chocktrupperna och säg till Macil att vi kommer in! Låt oss återvända till Frontbasen.","Komuta, başardı! Kapılar açıldı. Şok birliklerini gönderin ve Macil'e geldiğimizi söyleyin! Cephe üssüne geri dönelim." +"Join the assault on the castle. Find and take out the Programmer. We have conflicting reports about his location. One says he in a computer room, another hiding in a sub-level temple, and yet another at the end of a long hallway.",TXT_ILOG38,MAP07: Entrace.,,,"Připoj se k útoku na hrad. Najdi a zabij Programátora. Informace o jeho pozici se různí. Jedna mluví o místnosti s počítači, druhá o podzemním chrámu a třetí o konci dlouhé chodby.","Deltag i angrebet på slottet. Find og udslæt programmøren. Vi har modstridende rapporter om hans placering. En siger, at han er i et computerrum, en anden, at han gemmer sig i et tempel på et underliggende niveau, og endnu en anden for enden af en lang korridor.","Schließe dich dem Angriff auf die Burg an. Finde den Programmierer und schalte ihn aus. Wir haben widersprüchliche Angaben über seinen Aufenthaltsort. Eine sagt, in einem Computerraum, ein anderer, dass er sich in einem Tempelkeller versteckt und noch ein anderer sagt was vom Ende eines langen Flurs.",,Trovu kaj mortigu la Programiston. Estas kontraŭdiraj informoj pri lia pozicio: en komputila ĉambro aŭ en la subtera etaĝo de templo aŭ ĉe la fundo de longa koridoro.,"Encuentra y elimina al Programador. Tenemos informes contradictorios sobre su ubicación: uno que está en una sala de ordenadores, otro en el sótano de un templo y otro al final de un largo pasillo.","Encuentra y elimina al Programador. Tenemos informes contradictorios sobre su ubicación: uno que está en una sala de computadoras, otro en el sótano de un templo y otro al final de un largo pasillo.","Osallistu hyökkäykseen linnaa vastaan. Etsi ja kukista Ohjelmoitsija. Meillä on hänen sijainnistaan eriäviä tietoja: Yhden mukaan hän on tietokonehuoneessa, toisen mukaan maanalaisessa temppelissä ja vielä kolmannen mukaan pitkän käytävän päässä.","Rejoins l'assaut sur le château. Trouve et élimine le Programmeur. On a des rapports en conflit sur sa position. L'un d'entre eux nous dit qu'il se trouve dans la salle des ordinateurs, l'autre nous dit qu'il se cache dans un temple en sous sol, et un autre encore au bout d'un long couloir.","Csatlakozz a kastély ostromához. Keresd meg és iktasd ki a Programozót. Ellentmondó információink vannak a hollétéről. Az egyik szerint a számítógép szobában van, másik szerint egy föld alatti templomban, harmadik szerint egy hosszú folyosó végén.","Unisciti all'assalto sul castello. Trova e fai fuori il Programmatore. I rapporti che abbiamo sulla sua posizione si contraddicono. Uno lo piazza in una stanza di computer, un altro in un tempio di sottolivello, e un altro ancora alla fine di un lungo corridoio.","城に向かう突撃部隊に参加してプログラマーを探し出せ。 プログラマーの居場所について矛盾する報告もある。 ある人はコンピューター室にいる、別の人は保管室にいる、 -また別の人は長い廊下にいるとも言っていた。","성을 공략할 공성전에 참여해. 침투해서 프로그래머를 죽일 수 있게. 그의 장소와 관련된 보고들이 뭔가 혼란스러운데, 컴퓨터실에 있다고 하고, 낮은 층 신전에 숨어 있다고 하고, 다른 한 명은 긴 복도 맨 끝에 서 있대.","Doe mee aan de aanval op het kasteel. Zoek en schakel de Programmeur uit. We hebben tegenstrijdige berichten over zijn locatie. De ene zegt dat hij in een computerkamer zit, de andere verstopt zich in een tempel op subniveau, en nog een andere aan het einde van een lange gang.","Bli med på angrepet på slottet. Finn og drep programmereren. Vi har motstridende rapporter om hvor han befinner seg. En sier at han er i et datarom, en annen at han gjemmer seg i et underjordisk tempel, og en tredje at han er i enden av en lang gang.","Dołącz do szturmu na zamek. Znajdźcie i zlikwidujcie Programistę. Mamy sprzeczne raporty na temat jego lokalizacji. Jeden mówi, że w sali komputerowej, inny, że ukrywa się w podpoziomowej świątyni, a jeszcze inny, że na końcu długiego korytarza.","Junte-se ao ataque no castelo. Ache e elimine o Programador. Temos relatos conflitantes sobre onde ele se encontra. Um deles diz que ele está na sala de informática, outro que ele está escondido num templo no subsolo e mais outro diz que ele está no fim de um longo corredor.",,"Alăturăte asaltului asupra castelului. Găsește-l și elimină-l pe Programator. Avem rapoarte diferite în ceea ce privește locația lui. Unul spune că e într-o sală de calculatoare, iar altul că se ascunde într-un subnivel al templului, și încă unul care spune că e în capătul unui coridor lung.","Присоединись к атаке на замок. Найди и уничтожь Программиста. Наши сведения о его местонахождении противоречивы. Одни говорят, что он в компьютерной комнате, другие — что он укрывается в подземном храме, а третьи — что он в конце длинного коридора.",,"Kaleye yapılan saldırıya katılın. Programcıyı bulup çıkarın. Yeri hakkında çelişkili raporlarımız var. Biri bilgisayar odasında, diğeri alt kattaki bir tapınakta, bir başkası da uzun bir koridorun sonunda saklandığını söylüyor." -Find the Programmer and kill him.,TXT_ILOG45,MAP09: Entrance.,,,Najdi Programátora a zabij ho.,Find programmøren og dræb ham.,Finde den Programmierer und töte ihn.,,,Encuentra al Programador y mátalo.,,Etsi ja tapa Ohjelmoitsija.,Trouve le Programmeur et tue-le.,Keresd meg a Programozót és öld meg.,Trova il Programmatore e fallo fuori.,プログラマーを見つけて殺せ。,프로그래머를 찾아서 죽여.,Zoek de Programmeur en vermoord hem.,Finn programmereren og drep ham.,Znajdź Programistę i zabij go.,Encontre o Programador e mate-o.,,Găsește Programatorul și ucide-l.,Найди Программиста и убей его.,,Programcıyı bulun ve öldürün. -"Seek out the Oracle and ask it about the other Sigil pieces. The Oracle resides in the borderlands, just outside of town. Cross the river, head towards the castle and go left through the archway.",TXT_ILOG46,,,,"Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Věštec přebývá v pohraničí, hned za městem. Překroč řeku, zamiř k hradu a jdi vlevo pod obloukem.","Opsøg Oraklet og spørg det om de andre Sigil-stykker. Oraklet befinder sig i grænselandet, lige uden for byen. Kryds floden, gå mod slottet og gå til venstre gennem buegangen.","Suche das Orakel auf und befrage es bezüglich der anderen Teile des Sigils. Das Orakel ist in den Grenzgebieten zu finden, außerhalb der Stadt. Überquere den Fluss, gehe zur Burg und dann links durch das Tor.",,,"Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. El Oráculo reside en las fronteras, justo fuera del pueblo. Cruza el río, dirígete hacia el castillo y gira a la izquierda a través del arco.","Busca al Oráculo y pregúntale acerca de las otras piezas del Emblema. El Oráculo reside en las fronteras, en las afueras de la ciudad. Cruza el río, dirígete hacia el castillo y gira a la izquierda a través del arco.","Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Oraakkeli asuu rajamailla aivan kaupungin liepeillä. Ylitä joki, kulje kohti linnaa ja mene vasemmalle kaarikäytävän läpi.","Trouve l'Oracle et demande lui où se trouvent les autres pièces du Sigil. L'Oracle se trouve dans les terrains vagues à l'extérieur de la ville. Traverse la rivière, va vers le château puis à gauche après l'arche.","Keresd fel az Orákulumot, és kérdezd ki a többi pecsét darabról. Az Orákulum a peremvidéken lakik, rögtön a város után. Elhagyva a folyót, vedd az utad a kastély felé, és balra a boltíves folyosónál.","Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. L'Oracolo risiede nelle terre di confine, subito dopo la città. Attraversa il fiume, vai nella direzione del castello e poi a sinistra oltre l'arco.","オラクルに会いシジルの欠片の場所を尋ねろ。 +また別の人は長い廊下にいるとも言っていた。","성을 공략할 공성전에 참여해. 침투해서 프로그래머를 죽일 수 있게. 그의 장소와 관련된 보고들이 뭔가 혼란스러운데, 컴퓨터실에 있다고 하고, 낮은 층 신전에 숨어 있다고 하고, 다른 한 명은 긴 복도 맨 끝에 서 있대.","Doe mee aan de aanval op het kasteel. Zoek en schakel de Programmeur uit. We hebben tegenstrijdige berichten over zijn locatie. De ene zegt dat hij in een computerkamer zit, de andere verstopt zich in een tempel op subniveau, en nog een andere aan het einde van een lange gang.","Bli med på angrepet på slottet. Finn og drep programmereren. Vi har motstridende rapporter om hvor han befinner seg. En sier at han er i et datarom, en annen at han gjemmer seg i et underjordisk tempel, og en tredje at han er i enden av en lang gang.","Dołącz do szturmu na zamek. Znajdźcie i zlikwidujcie Programistę. Mamy sprzeczne raporty na temat jego lokalizacji. Jeden mówi, że w sali komputerowej, inny, że ukrywa się w podpoziomowej świątyni, a jeszcze inny, że na końcu długiego korytarza.","Junte-se ao ataque no castelo. Ache e elimine o Programador. Temos relatos conflitantes sobre onde ele se encontra. Um deles diz que ele está na sala de informática, outro que ele está escondido num templo no subsolo e mais outro diz que ele está no fim de um longo corredor.",,"Alăturăte asaltului asupra castelului. Găsește-l și elimină-l pe Programator. Avem rapoarte diferite în ceea ce privește locația lui. Unul spune că e într-o sală de calculatoare, iar altul că se ascunde într-un subnivel al templului, și încă unul care spune că e în capătul unui coridor lung.","Присоединись к атаке на замок. Найди и уничтожь Программиста. Наши сведения о его местонахождении противоречивы. Одни говорят, что он в компьютерной комнате, другие — что он укрывается в подземном храме, а третьи — что он в конце длинного коридора.",,"Gå med i anfallet mot slottet. Hitta och ta ut programmeraren. Vi har motstridiga rapporter om var han befinner sig. En säger att han befinner sig i ett datorrum, en annan gömmer sig i ett tempel på en underliggande nivå och ytterligare en annan i slutet av en lång korridor.","Kaleye yapılan saldırıya katılın. Programcıyı bulup çıkarın. Yeri hakkında çelişkili raporlarımız var. Biri bilgisayar odasında, diğeri alt kattaki bir tapınakta, bir başkası da uzun bir koridorun sonunda saklandığını söylüyor." +Find the Programmer and kill him.,TXT_ILOG45,MAP09: Entrance.,,,Najdi Programátora a zabij ho.,Find programmøren og dræb ham.,Finde den Programmierer und töte ihn.,,Trovu la Programiston kaj mortigu lin.,Encuentra al Programador y mátalo.,,Etsi ja tapa Ohjelmoitsija.,Trouve le Programmeur et tue-le.,Keresd meg a Programozót és öld meg.,Trova il Programmatore e fallo fuori.,プログラマーを見つけて殺せ。,프로그래머를 찾아서 죽여.,Zoek de Programmeur en vermoord hem.,Finn programmereren og drep ham.,Znajdź Programistę i zabij go.,Encontre o Programador e mate-o.,,Găsește Programatorul și ucide-l.,Найди Программиста и убей его.,,Hitta programmeraren och döda honom.,Programcıyı bulun ve öldürün. +"Seek out the Oracle and ask it about the other Sigil pieces. The Oracle resides in the borderlands, just outside of town. Cross the river, head towards the castle and go left through the archway.",TXT_ILOG46,,,,"Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Věštec přebývá v pohraničí, hned za městem. Překroč řeku, zamiř k hradu a jdi vlevo pod obloukem.","Opsøg Oraklet og spørg det om de andre Sigil-stykker. Oraklet befinder sig i grænselandet, lige uden for byen. Kryds floden, gå mod slottet og gå til venstre gennem buegangen.","Suche das Orakel auf und befrage es bezüglich der anderen Teile des Sigils. Das Orakel ist in den Grenzgebieten zu finden, außerhalb der Stadt. Überquere den Fluss, gehe zur Burg und dann links durch das Tor.",,Serĉu la Orakolon kaj demandu al li pri la aliaj pecoj de la Sigelo. Li loĝas ekster la urbo en la limlando; ĝi estas apud la pordo de la kastelo.,Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Reside fuera del pueblo en las tierras fronterizas que están justo al lado de la puerta del castillo.,Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Reside afuera del pueblo en las tierras fronterizas que están justo al lado de la puerta del castillo.,"Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Oraakkeli asuu rajamailla aivan kaupungin liepeillä. Ylitä joki, kulje kohti linnaa ja mene vasemmalle kaarikäytävän läpi.","Trouve l'Oracle et demande lui où se trouvent les autres pièces du Sigil. L'Oracle se trouve dans les terrains vagues à l'extérieur de la ville. Traverse la rivière, va vers le château puis à gauche après l'arche.","Keresd fel az Orákulumot, és kérdezd ki a többi pecsét darabról. Az Orákulum a peremvidéken lakik, rögtön a város után. Elhagyva a folyót, vedd az utad a kastély felé, és balra a boltíves folyosónál.","Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. L'Oracolo risiede nelle terre di confine, subito dopo la città. Attraversa il fiume, vai nella direzione del castello e poi a sinistra oltre l'arco.","オラクルに会いシジルの欠片の場所を尋ねろ。 オラクルは町外れの国境地帯にいる。 -川の向こうにある城を目指しアーチウェイを左に曲がるのだ。","오라클을 찾아서 다른 시질 조각이 어디에 있는지 물어봐. 오라클은 도시 외곽에 있는 접경지 근처에 있어. 강을 넘은 뒤, 성 쪽으로 향하고 아치 밑의 통로를 통해 왼쪽으로 이동해.","Zoek het Orakel op en vraag het over de andere Sigil stukken. Het Orakel woont in de grensgebieden, net buiten de stad. Steek de rivier over, loop naar het kasteel en ga linksaf door de poort.","Oppsøk Orakelet og spør det om de andre Sigil-brikkene. Oraklet holder til i grenselandet, like utenfor byen. Kryss elven, gå mot slottet og gå til venstre gjennom buegangen.","Poszukaj Wyroczni i zapytaj ją o pozostałe kawałki Sigila. Wyrocznia rezyduje na pograniczu, tuż za miastem. Przejdź przez rzekę, skieruj się w stronę zamku i przejdź w lewo przez łuki.","Procure pelo Oráculo e pergunte a ele sobre as outras peças do Sigilo. O Oráculo mora nas fronteiras, no lado de fora da cidade. Atravesse o rio, vá em direção ao castelo e vá pela esquerda através do arco.",,"Găsește Oracolul și întreabă-l de piesele Sigiliului. Oracolul are reședința în mărginime, chiar la ieșirea din oraș. Trece râul, du-te spre castel și ia-o la stânga prin arcadă.","Найди Оракула и спроси его про другие фрагменты Печати. Резиденция Оракула находится в пограничье, сразу за городской чертой. Пересеки реку, иди в сторону крепости и сверни налево, пройдя через арку.",,"Kahin'i bulun ve ona diğer Sigil parçalarını sorun. Kahin, şehrin hemen dışındaki sınır bölgelerinde bulunur. Nehri geçin, kaleye doğru gidin ve kemerden sola dönün." -"Seek out the Oracle and ask it about the other Sigil pieces. The Oracle's temple is in the borderlands, on the outskirts of town.",TXT_ILOG47,,,,"Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Věštcův chrám je v pohraničí, na okraji města.","Opsøg Oraklet og spørg det om de andre Sigil stykker. Oraklets tempel ligger i grænselandet, i udkanten af byen.","Suche das Orakel auf und befrage es bezüglich der anderen Teile des Sigils. Der Tempel des Orakels ist in den Grenzgebieten zu finden, in den Außenbezirken der Stadt.",,,Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. El templo del Oráculo está en las fronteras en las afueras del pueblo.,,Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Oraakkelin temppeli sijaitsee rajaseudulla kaupungin laitamilla.,Trouve l'Oracle et demande lui où se trouvent les autres pièces du Sigil. Le temple de l'Oracle se trouve dans les terrains vagues à l'extérieur de la ville. ,"Keresd fel az Orákulumot, és kérdezd ki a többi pecsét darabról. Az Orákulum a peremvidéken lakik, rögtön a város után.","Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. Il tempio dell'Oracolo è nelle terre di confine, fuori città.","オラクルに会いシジルの欠片の場所を尋ねろ。 -オラクルは町外れの国境地帯にいる。",오라클을 찾고 다른 시질 조각에 관해 물어봐. 오라클의 신전은 도시 외곽의 접경지 근처에 있어.,"Zoek het Orakel op en vraag het over de andere Sigil stukken. De tempel van het Orakel ligt in het grensgebied, aan de rand van de stad.","Oppsøk oraklet og spør det om de andre Sigil-brikkene. Orakelets tempel ligger i grenselandet, i utkanten av byen.","Odszukaj Wyrocznię i zapytaj ją o inne kawałki Sigila. Świątynia Wyroczni znajduje się na pograniczu, na obrzeżach miasta.","Procure pelo Oráculo e pergunte a ele sobre as outras peças do Sigilo. Seu tempo está nas fronteiras, no lado de fora da cidade.",,"Găsește Oracolul și întreabă-l de piesele Sigiliului. Oracolul are reședința în mărginime, la ieșirea din oraș.","Найди Оракула и спроси его про другие фрагменты Печати. Храм Оракула расположен в пограничье, на окраине города.",,"Kahin'i bul ve ona diğer Sigil parçalarını sor. Kahin'in tapınağı sınır bölgelerinde, şehrin eteklerinde." -"Seek out the Oracle and ask it about the other Sigil pieces. Take your reward and go across to the medic and weapons trainer for health and training. The Oracle's temple is in the borderlands, on the outskirts of town.",TXT_ILOG48,MAP10: After talking to Macil and moving a bit.,,,"Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Převezmi si svou odměnu a navštiv zdravotníka a učitele střelby pro zdraví a výcvik. Věštcův chrám je v pohraničí, na okraji města.","Opsøg Oraklet og spørg det om de andre Sigilstykker. Tag din belønning og gå over til lægen og våbentræneren for at få sundhed og træning. Oraklets tempel ligger i grænselandet, i udkanten af byen.","Suche das Orakel auf und befrage es bezüglich der anderen Teile des Sigils. Nimm deine Belohnung und suche den Sanitäter und den Waffentrainer auf. Der Tempel des Orakels ist in den Grenzgebieten zu finden, in den Außenbezirken der Stadt.",,,"Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Toma tu recompensa, ve al médico y al entrenador de armas para salud y entrenamiento. El templo del Oráculo está en las fronteras en las afueras del pueblo.",,Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Kerää palkkiosi ja hakeudu lääkintämiehen ja asekouluttajan luo terveydenhoitoa ja koulutusta varten. Oraakkelin temppeli sijaitsee rajaseudulla kaupungin laitamilla.,Trouve l'Oracle et demande lui où se trouvent les autres pièces du Sigil. Va chercher ta récompense chez le médecin et le maître d'armes pour de la santé et de l'entraînement. Le temple de l'Oracle se trouve dans les terrains vagues à l'extérieur de la ville. ,"Keresd fel az Orákulumot, és kérdezd ki a többi pecsét darabról. Vedd fel a jutalmad, majd ugorj át a szanitéchez és kiképzőhöz. Az Orákulum temploma a peremvidéken található, a város külvárosában.","Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. Prendi la tua ricompensa e visita il dottore e l'addestratore di armi. Il tempio dell'Oracolo è nelle terre di confine, fuori città.","オラクルに会いシジルの欠片の場所を尋ねろ。 +川の向こうにある城を目指しアーチウェイを左に曲がるのだ。","오라클을 찾아서 다른 시질 조각이 어디에 있는지 물어봐. 오라클은 도시 외곽에 있는 접경지 근처에 있어. 강을 넘은 뒤, 성 쪽으로 향하고 아치 밑의 통로를 통해 왼쪽으로 이동해.","Zoek het Orakel op en vraag het over de andere Sigil stukken. Het Orakel woont in de grensgebieden, net buiten de stad. Steek de rivier over, loop naar het kasteel en ga linksaf door de poort.","Oppsøk Orakelet og spør det om de andre Sigil-brikkene. Oraklet holder til i grenselandet, like utenfor byen. Kryss elven, gå mot slottet og gå til venstre gjennom buegangen.","Poszukaj Wyroczni i zapytaj ją o pozostałe kawałki Sigila. Wyrocznia rezyduje na pograniczu, tuż za miastem. Przejdź przez rzekę, skieruj się w stronę zamku i przejdź w lewo przez łuki.","Procure pelo Oráculo e pergunte a ele sobre as outras peças do Sigilo. O Oráculo mora nas fronteiras, no lado de fora da cidade. Atravesse o rio, vá em direção ao castelo e vá pela esquerda através do arco.",,"Găsește Oracolul și întreabă-l de piesele Sigiliului. Oracolul are reședința în mărginime, chiar la ieșirea din oraș. Trece râul, du-te spre castel și ia-o la stânga prin arcadă.","Найди Оракула и спроси его про другие фрагменты Печати. Резиденция Оракула находится в пограничье, сразу за городской чертой. Пересеки реку, иди в сторону крепости и сверни налево, пройдя через арку.",,"Sök upp Oraklet och fråga det om de andra Sigilbitarna. Oraklet befinner sig i gränslandet, strax utanför staden. Korsa floden, gå mot slottet och gå till vänster genom valvet.","Kahin'i bulun ve ona diğer Sigil parçalarını sorun. Kahin, şehrin hemen dışındaki sınır bölgelerinde bulunur. Nehri geçin, kaleye doğru gidin ve kemerden sola dönün." +"Seek out the Oracle and ask it about the other Sigil pieces. The Oracle's temple is in the borderlands, on the outskirts of town.",TXT_ILOG47,,,,"Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Věštcův chrám je v pohraničí, na okraji města.","Opsøg Oraklet og spørg det om de andre Sigil stykker. Oraklets tempel ligger i grænselandet, i udkanten af byen.","Suche das Orakel auf und befrage es bezüglich der anderen Teile des Sigils. Der Tempel des Orakels ist in den Grenzgebieten zu finden, in den Außenbezirken der Stadt.",,Serĉu la Orakolon kaj demandu al li pri la aliaj pecoj de la Sigelo. Li loĝas ekster la urbo en la limlando; ĝi estas apud la pordo de la kastelo.,Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Reside fuera del pueblo en las tierras fronterizas que están justo al lado de la puerta del castillo.,Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Reside afuera del pueblo en las tierras fronterizas que están justo al lado de la puerta del castillo.,Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Oraakkelin temppeli sijaitsee rajaseudulla kaupungin laitamilla.,Trouve l'Oracle et demande lui où se trouvent les autres pièces du Sigil. Le temple de l'Oracle se trouve dans les terrains vagues à l'extérieur de la ville. ,"Keresd fel az Orákulumot, és kérdezd ki a többi pecsét darabról. Az Orákulum a peremvidéken lakik, rögtön a város után.","Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. Il tempio dell'Oracolo è nelle terre di confine, fuori città.","オラクルに会いシジルの欠片の場所を尋ねろ。 +オラクルは町外れの国境地帯にいる。",오라클을 찾고 다른 시질 조각에 관해 물어봐. 오라클의 신전은 도시 외곽의 접경지 근처에 있어.,"Zoek het Orakel op en vraag het over de andere Sigil stukken. De tempel van het Orakel ligt in het grensgebied, aan de rand van de stad.","Oppsøk oraklet og spør det om de andre Sigil-brikkene. Orakelets tempel ligger i grenselandet, i utkanten av byen.","Odszukaj Wyrocznię i zapytaj ją o inne kawałki Sigila. Świątynia Wyroczni znajduje się na pograniczu, na obrzeżach miasta.","Procure pelo Oráculo e pergunte a ele sobre as outras peças do Sigilo. Seu tempo está nas fronteiras, no lado de fora da cidade.",,"Găsește Oracolul și întreabă-l de piesele Sigiliului. Oracolul are reședința în mărginime, la ieșirea din oraș.","Найди Оракула и спроси его про другие фрагменты Печати. Храм Оракула расположен в пограничье, на окраине города.",,"Sök upp Oraklet och fråga det om de andra Sigilbitarna. Oraklets tempel ligger i gränslandet, i utkanten av staden.","Kahin'i bul ve ona diğer Sigil parçalarını sor. Kahin'in tapınağı sınır bölgelerinde, şehrin eteklerinde." +"Seek out the Oracle and ask it about the other Sigil pieces. Take your reward and go across to the medic and weapons trainer for health and training. The Oracle's temple is in the borderlands, on the outskirts of town.",TXT_ILOG48,"MAP10: After killing the Programmer, talking to Macil and moving a bit.",,,"Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Převezmi si svou odměnu a navštiv zdravotníka a učitele střelby pro zdraví a výcvik. Věštcův chrám je v pohraničí, na okraji města.","Opsøg Oraklet og spørg det om de andre Sigilstykker. Tag din belønning og gå over til lægen og våbentræneren for at få sundhed og træning. Oraklets tempel ligger i grænselandet, i udkanten af byen.","Suche das Orakel auf und befrage es bezüglich der anderen Teile des Sigils. Nimm deine Belohnung und suche den Sanitäter und den Waffentrainer auf. Der Tempel des Orakels ist in den Grenzgebieten zu finden, in den Außenbezirken der Stadt.",,Parolu kun la kuracisto kaj la armila trejnisto en la malsanulejo (Hospital). Serĉu la Orakolon kaj demandu al li pri la aliaj pecoj de la Sigelo: lia templo estas ekster la urbo en la limlando.,Habla con el médico y el entrenador de armas en el hospital. Busca al Oráculo y pregúntale sobre las otras piezas del Emblema: su templo está fuera del pueblo en las tierras fronterizas.,,Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Kerää palkkiosi ja hakeudu lääkintämiehen ja asekouluttajan luo terveydenhoitoa ja koulutusta varten. Oraakkelin temppeli sijaitsee rajaseudulla kaupungin laitamilla.,Trouve l'Oracle et demande lui où se trouvent les autres pièces du Sigil. Va chercher ta récompense chez le médecin et le maître d'armes pour de la santé et de l'entraînement. Le temple de l'Oracle se trouve dans les terrains vagues à l'extérieur de la ville. ,"Keresd fel az Orákulumot, és kérdezd ki a többi pecsét darabról. Vedd fel a jutalmad, majd ugorj át a szanitéchez és kiképzőhöz. Az Orákulum temploma a peremvidéken található, a város külvárosában.","Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. Prendi la tua ricompensa e visita il dottore e l'addestratore di armi. Il tempio dell'Oracolo è nelle terre di confine, fuori città.","オラクルに会いシジルの欠片の場所を尋ねろ。 メディックと武器トレーナーに会い訓練と体力を強化せよ。 -オラクルは町外れの国境地帯にいる。",오라클을 찾아서 다른 시질 조각이 어디에 있는지 물어봐. 보상을 받고 치료와 훈련을 위해 의무관과 무기 담당관에게로 가. 오라클은 도시 외곽에 있는 접경지 근처에 있어.,"Zoek het Orakel op en vraag het over de andere Sigil stukken. Pak je beloning en ga naar de dokter en wapentrainer voor gezondheid en training. De tempel van het Orakel staat in de grensgebieden, aan de rand van de stad.","Oppsøk oraklet og spør det om de andre Sigil-brikkene. Ta belønningen din og gå over til medisineren og våpentreneren for helse og trening. Orakelets tempel ligger i grenselandet, i utkanten av byen.","Poszukaj Wyroczni i zapytaj ją o inne kawałki Sigila. Weź nagrodę i udaj się do medyka i trenera broni po zdrowie i trening. Świątynia Wyroczni znajduje się na pograniczu, na obrzeżach miasta.","Procure pelo Oráculo e pergunte a ele sobre as outras peças do Sigilo. Pegue a sua recompensa e visite o médico e o treinador de armas para saúde e treinamento. O templo do Oráculo se encontra nas fronteiras, do lado de fora da cidade.",,Găsește Oracolul și întreabă-l de piesele Sigiliului. Ia-ți recompensa ți du-te la medic și antrenorul de arme. Templul Oracolului e în mărginimea orașului.,"Найди Оракула и спроси его про другие фрагменты Печати. Возьми свою награду и зайди к медику и инструктору по стрельбе. Храм Оракула находится в пограничье, на окраине города.",,"Kahin'i bul ve ona diğer Sigil parçalarını sor. Ödülünüzü alın ve sağlık ve eğitim için sıhhiyeciye ve silah eğitmenine gidin. Kahin'in tapınağı sınır bölgelerinde, kasabanın eteklerinde." -Seek out the Oracle's temple and ask it about the other Sigil pieces. Here it is. I'm recording everything. It's not that I don't have faith that you'll survive. It's just that we can't let the Order control the Sigil.,TXT_ILOG50,MAP11: Entrance to cave.,,,"Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Tady to je. Nahrávám všechno, ne že bych neměla důvěru v tvé přežití, ale prostě nemůžeme dovolit Řádu ovládat Pečeť.","Søg ud til Oraklets tempel og spørg det om de andre Sigil stykker. Her er det. Jeg optager alt. Det er ikke fordi jeg ikke tror på, at du vil overleve. Vi kan bare ikke lade Ordenen kontrollere Sigil.","Suche das Orakel auf und befrage es bezüglich der anderen Teile des Sigils. Ich protokolliere alles. Ich glaube zwar schon daran, dass du überleben wirst, aber wir können es halt nicht zulassen, dass der Orden das Sigil kontrolliert.",,,Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Aquí está. Lo estoy grabando todo. No es que no tenga fe en tu supervivencia. Es solo que no podemos dejar que la Orden controle el Emblema.,,"Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Tässä se on. Tallennan kaiken. Tässä ei ole kyse siitä, etteikö minulla olisi täysi luotto, että selviäisit. Emme vain voi antaa Veljeskunnan hallita Sinettiä.","Trouve l'Oracle et demande lui où se trouvent les autres pièces du Sigil. Le voilà. J'enregistre tout, ce n'est pas que je n'ai pas confiance en ta capacité de survie, c'est juste que je ne peux pas laisser l'Ordre contrôler le Sigil.","Keresd fel az Orákulumot a templomában, és kérdezd meg a pecsét többi darabjáról. Itt is van. Felveszek mindent. Nem mintha nem bíznék meg benned, csak nem akarom, hogy a Rend kezébe kerüljön a pecsét.",Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. Ecco qua. Sto registrando tutto. Non è che non penso che sopravviverai. È solo che non possiamo lasciare che l'Ordine controlli il Sigillo.,"オラクルに会いシジルの欠片の場所を尋ねろ。 +オラクルは町外れの国境地帯にいる。",오라클을 찾아서 다른 시질 조각이 어디에 있는지 물어봐. 보상을 받고 치료와 훈련을 위해 의무관과 무기 담당관에게로 가. 오라클은 도시 외곽에 있는 접경지 근처에 있어.,"Zoek het Orakel op en vraag het over de andere Sigil stukken. Pak je beloning en ga naar de dokter en wapentrainer voor gezondheid en training. De tempel van het Orakel staat in de grensgebieden, aan de rand van de stad.","Oppsøk oraklet og spør det om de andre Sigil-brikkene. Ta belønningen din og gå over til medisineren og våpentreneren for helse og trening. Orakelets tempel ligger i grenselandet, i utkanten av byen.","Poszukaj Wyroczni i zapytaj ją o inne kawałki Sigila. Weź nagrodę i udaj się do medyka i trenera broni po zdrowie i trening. Świątynia Wyroczni znajduje się na pograniczu, na obrzeżach miasta.","Procure pelo Oráculo e pergunte a ele sobre as outras peças do Sigilo. Pegue a sua recompensa e visite o médico e o treinador de armas para saúde e treinamento. O templo do Oráculo se encontra nas fronteiras, do lado de fora da cidade.",,Găsește Oracolul și întreabă-l de piesele Sigiliului. Ia-ți recompensa ți du-te la medic și antrenorul de arme. Templul Oracolului e în mărginimea orașului.,"Найди Оракула и спроси его про другие фрагменты Печати. Возьми свою награду и зайди к медику и инструктору по стрельбе. Храм Оракула находится в пограничье, на окраине города.",,"Sök upp Oraklet och fråga det om de andra Sigilbitarna. Ta din belöning och gå över till läkaren och vapentränaren för hälsa och träning. Oraklets tempel ligger i gränslandet, i utkanten av staden.","Kahin'i bul ve ona diğer Sigil parçalarını sor. Ödülünüzü alın ve sağlık ve eğitim için sıhhiyeciye ve silah eğitmenine gidin. Kahin'in tapınağı sınır bölgelerinde, kasabanın eteklerinde." +Seek out the Oracle's temple and ask it about the other Sigil pieces. Here it is. I'm recording everything. It's not that I don't have faith that you'll survive. It's just that we can't let the Order control the Sigil.,TXT_ILOG50,MAP11: Entrance to cave.,,,"Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Tady to je. Nahrávám všechno, ne že bych neměla důvěru v tvé přežití, ale prostě nemůžeme dovolit Řádu ovládat Pečeť.","Søg ud til Oraklets tempel og spørg det om de andre Sigil stykker. Her er det. Jeg optager alt. Det er ikke fordi jeg ikke tror på, at du vil overleve. Vi kan bare ikke lade Ordenen kontrollere Sigil.","Suche das Orakel auf und befrage es bezüglich der anderen Teile des Sigils. Ich protokolliere alles. Ich glaube zwar schon daran, dass du überleben wirst, aber wir können es halt nicht zulassen, dass der Orden das Sigil kontrolliert.",,"Serĉu la Orakolon kaj demandu al li pri la aliaj pecoj de la Sigelo. Jen la enirejo. Mi videoregistras ĉion; mi ne malfidas pri via supervivado, sed ni ne devas ebligi, ke La Ordeno regu la Sigelon.","Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Aquí está la entrada. Lo estoy grabando todo; no es que no tenga fe en tu supervivencia, es solo que no podemos dejar que La Orden controle el Emblema.",,"Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Tässä se on. Tallennan kaiken. Tässä ei ole kyse siitä, etteikö minulla olisi täysi luotto, että selviäisit. Emme vain voi antaa Veljeskunnan hallita Sinettiä.","Trouve l'Oracle et demande lui où se trouvent les autres pièces du Sigil. Le voilà. J'enregistre tout, ce n'est pas que je n'ai pas confiance en ta capacité de survie, c'est juste que je ne peux pas laisser l'Ordre contrôler le Sigil.","Keresd fel az Orákulumot a templomában, és kérdezd meg a pecsét többi darabjáról. Itt is van. Felveszek mindent. Nem mintha nem bíznék meg benned, csak nem akarom, hogy a Rend kezébe kerüljön a pecsét.",Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. Ecco qua. Sto registrando tutto. Non è che non penso che sopravviverai. È solo che non possiamo lasciare che l'Ordine controlli il Sigillo.,"オラクルに会いシジルの欠片の場所を尋ねろ。 オラクルはこの場所にいる。私は全部記録している。 私は貴方が生き残る確証がないというわけではなく、 オーダーはシジルを操る事が出来ないというだけだ。 -","오라클의 신전을 찾아서 시질 조각이 어디에 있는지 물어봐. 그리고 지금 난 모든 걸 녹음하고 있어. 네가 살아남을 거라는 믿음을 버린게 아니라, 오더가 시질을 손에 잡게 내버려 둘 수가 없어서 말이야.",Zoek de tempel van het Orakel op en vraag het over de andere Sigil stukken. Hier is het. Ik ben alles aan het opnemen. Niet dat ik er niet op vertrouw dat je het zult overleven. Het is gewoon dat we de Orde de Sigil niet kunnen laten controleren door de Orde.,Oppsøk Orakelets tempel og spør det om de andre seglbitene. Her er det. Jeg tar opp alt. Det er ikke det at jeg ikke har tro på at du overlever. Men vi kan ikke la Ordenen kontrollere seglet.,"Poszukaj świątyni Wyroczni i zapytaj ją o inne kawałki Sigila. Oto on. Nagrywam wszystko. Nie chodzi o to, że nie wierzę, że przeżyjesz. Po prostu nie możemy pozwolić Zakonowi kontrolować Sigilu.","Procure pelo Oráculo e pergunte a ele sobre as outras peças do Sigilo. Certo, estou gravando tudo. Não é que eu não tenha fé de que você vá sobreviver. É só que não podemos deixar a Ordem controlar o Sigilo.",,"Găsește Oracolul și întreabă de celelalte piese ale Sigiliului. Aici este. Înregistrez totul. Nu e vorba că nu am încredere că vei supraviețui, dar nu putem lăsa Ordinul ca ia Sigiliul.","Найди храм Оракула и спроси его про другие фрагменты Печати. Так. Я всё записываю на плёнку. Это не потому, что я не верю, что ты уцелеешь. Просто мы не можем позволить Ордену заполучить Печать.",,Kahin'in tapınağını bulun ve ona diğer Sigil parçalarını sorun. İşte burada. Her şeyi kaydediyorum. Hayatta kalacağınıza inanmadığımdan değil. Sadece Düzen'in Sigil'i kontrol etmesine izin veremeyiz. -The second piece lies at the heart of the crimson and obsidian tower. There you will find the Bishop. The Bishop is the Order's military leader. We off him and we score twice. Take the Oracle's token to the key master in the borderlands.,TXT_ILOG56,MAP12: After talking to the Oracle.,,,"Druhý díl leží v srdci věže karmínoobsidiánové. Tam najdeš Biskupa. Biskup je armádní vůdce Řádu. Plánuje jejich taktiky, velí jejich špiónům a má za úkol ovládat nás. Odděláme ho a zaskórujeme dvakrát.","Den anden del ligger i hjertet af det purpurfarvede og obsidianske tårn. Der vil du finde biskoppen. Biskoppen er ordenens militære leder. Hvis vi dræber ham, scorer vi to gange. Tag Oraklets token til nøglemesteren i grænselandet.","Das zweite Stück liegt im Zentrum des Turms aus Purpur und Obsidian. Dort wirst du den Bischof, den militärischen Anführer des Ordens, finden. Wenn wir ihn kalt machen, können wir zwei Fliegen mit einer Klappe schlagen. Nimm das Zeichen des Orakels und bringe es zum Schlüsselmeister in den Grenzgebieten.",,,"La segunda pieza está en el corazón de la torre carmesí y obsidiana. Ahí encontrarás al Obispo, el líder militar de la Orden. Nos lo cargamos y marcamos dos puntos. Lleva el vale del Oráculo al amo de llaves en las fronteras.","La segunda pieza está en el corazón de la torre carmesí y obsidiana. Ahí se encuentra el Obispo, el líder militar de la Orden. Lo matamos y premios dobles. Llévale el vale del Oráculo al amo de llaves en las fronteras.","Toinen osanen piilee purppuranpunaisen laavalasisen tornin sydämessä. Löydät sieltä Piispan, Veljeskunnan sotapäällikön. Teemme hänestä lopun ja pokkaamme kaksi pistettä. Toimita Oraakkelin merkki avainmestarille rajaseudulla.","La deuxième pièce se trouve au cœur de la tour d'obsidienne et d'écarlate. Tu y trouvera l'évêque. L'évêque est le chef militaire de l'Ordre. Si on le tue, on marque deux points. Prends le jeton de l'Oracle et amène le au Mâitre des Clés dans les terrains vagues. ","A második darab a karmazsin és obszidián torony szívében található. Ott fogod megtalálni a Püspököt. A Püspök a Rend katonai vezetője. Ha kiiktatjuk, duplán nyerünk. Vidd az Orákulum zálogát a kulcsmesterhez, aki a peremvidéken van.",Il secondo pezzo si trova nel cuore della torre cremisina e ossidiana. Lì troverai il Vescovo. Il Vescovo è il capo militare dell'Ordine. Farlo fuori sarebbe un enorme vantaggio. Raggiungi il mastro delle chiavi nelle terre di confine con il pass che ti ha dato l'Oracolo.,"二つ目の欠片は深紅と黒曜石の塔にある。そこでビショップを見つけろ。 +","오라클의 신전을 찾아서 시질 조각이 어디에 있는지 물어봐. 그리고 지금 난 모든 걸 녹음하고 있어. 네가 살아남을 거라는 믿음을 버린게 아니라, 오더가 시질을 손에 잡게 내버려 둘 수가 없어서 말이야.",Zoek de tempel van het Orakel op en vraag het over de andere Sigil stukken. Hier is het. Ik ben alles aan het opnemen. Niet dat ik er niet op vertrouw dat je het zult overleven. Het is gewoon dat we de Orde de Sigil niet kunnen laten controleren door de Orde.,Oppsøk Orakelets tempel og spør det om de andre seglbitene. Her er det. Jeg tar opp alt. Det er ikke det at jeg ikke har tro på at du overlever. Men vi kan ikke la Ordenen kontrollere seglet.,"Poszukaj świątyni Wyroczni i zapytaj ją o inne kawałki Sigila. Oto on. Nagrywam wszystko. Nie chodzi o to, że nie wierzę, że przeżyjesz. Po prostu nie możemy pozwolić Zakonowi kontrolować Sigilu.","Procure pelo Oráculo e pergunte a ele sobre as outras peças do Sigilo. Certo, estou gravando tudo. Não é que eu não tenha fé de que você vá sobreviver. É só que não podemos deixar a Ordem controlar o Sigilo.",,"Găsește Oracolul și întreabă de celelalte piese ale Sigiliului. Aici este. Înregistrez totul. Nu e vorba că nu am încredere că vei supraviețui, dar nu putem lăsa Ordinul ca ia Sigiliul.","Найди храм Оракула и спроси его про другие фрагменты Печати. Так. Я всё записываю на плёнку. Это не потому, что я не верю, что ты уцелеешь. Просто мы не можем позволить Ордену заполучить Печать.",,Sök upp Orakelns tempel och fråga det om de andra Sigillbitarna. Här är den. Jag spelar in allting. Det är inte så att jag inte tror att du kommer att överleva. Det är bara det att vi inte kan låta Orden kontrollera Sigillet.,Kahin'in tapınağını bulun ve ona diğer Sigil parçalarını sorun. İşte burada. Her şeyi kaydediyorum. Hayatta kalacağınıza inanmadığımdan değil. Sadece Düzen'in Sigil'i kontrol etmesine izin veremeyiz. +The second piece lies at the heart of the crimson and obsidian tower. There you will find the Bishop. The Bishop is the Order's military leader. We off him and we score twice. Take the Oracle's token to the key master in the borderlands.,TXT_ILOG56,MAP12: After talking to the Oracle.,,,"Druhý díl leží v srdci věže karmínoobsidiánové. Tam najdeš Biskupa. Biskup je armádní vůdce Řádu. Plánuje jejich taktiky, velí jejich špiónům a má za úkol ovládat nás. Odděláme ho a zaskórujeme dvakrát.","Den anden del ligger i hjertet af det purpurfarvede og obsidianske tårn. Der vil du finde biskoppen. Biskoppen er ordenens militære leder. Hvis vi dræber ham, scorer vi to gange. Tag Oraklets token til nøglemesteren i grænselandet.","Das zweite Stück liegt im Zentrum des Turms aus Purpur und Obsidian. Dort wirst du den Bischof, den militärischen Anführer des Ordens, finden. Wenn wir ihn kalt machen, können wir zwei Fliegen mit einer Klappe schlagen. Nimm das Zeichen des Orakels und bringe es zum Schlüsselmeister in den Grenzgebieten.",,La dua peco situas en la koro de la turo karmezina kaj obsidiankolora: tie estas la Episkopo la militestro. Ni mortigu lin: du poentojn. Portu la paspermeson de la Orakolo al la ŝlosilestro en la limlando.,La segunda pieza está en el corazón de la torre carmesí y obsidiana: allí está el Obispo el líder militar de La Orden. Nos lo cargamos y marcamos dos puntos. Lleva el pase del Oráculo al amo de llaves en las tierras fronterizas.,La segunda pieza está en el corazón de la torre carmesí y obsidiana: allá está el Obispo el líder militar de La Orden. Lo matamos y premios dobles. Llévale el pase del Oráculo al amo de llaves en las tierras fronterizas.,"Toinen osanen piilee purppuranpunaisen laavalasisen tornin sydämessä. Löydät sieltä Piispan, Veljeskunnan sotapäällikön. Teemme hänestä lopun ja pokkaamme kaksi pistettä. Toimita Oraakkelin merkki avainmestarille rajaseudulla.","La deuxième pièce se trouve au cœur de la tour d'obsidienne et d'écarlate. Tu y trouvera l'évêque. L'évêque est le chef militaire de l'Ordre. Si on le tue, on marque deux points. Prends le jeton de l'Oracle et amène le au Mâitre des Clés dans les terrains vagues. ","A második darab a karmazsin és obszidián torony szívében található. Ott fogod megtalálni a Püspököt. A Püspök a Rend katonai vezetője. Ha kiiktatjuk, duplán nyerünk. Vidd az Orákulum zálogát a kulcsmesterhez, aki a peremvidéken van.",Il secondo pezzo si trova nel cuore della torre cremisina e ossidiana. Lì troverai il Vescovo. Il Vescovo è il capo militare dell'Ordine. Farlo fuori sarebbe un enorme vantaggio. Raggiungi il mastro delle chiavi nelle terre di confine con il pass che ti ha dato l'Oracolo.,"二つ目の欠片は深紅と黒曜石の塔にある。そこでビショップを見つけろ。 ビショップはオーダーの軍事指揮官だ。奴を討ち破り欠片を手に入れろ。 -国境地帯のキーマスターにオラクルのトークンを見せよ。",두 번째 시질 조각은 진홍빛 흑요석 탑에 숨어있는 비숍에게 있어. 비숍은 그들의 잔혹한 군사 지도자이지. 거기에 녀석이 있을 거야. 그를 죽이면 두 배로 이득이 갈 거야. 이 통행증을 들고 접경지 안의 열쇠지기에게로 가봐.,Het tweede stuk ligt in het hart van de karmozijnrode en obsidiaan toren. Daar vindt u de bisschop. De bisschop is de militaire leider van de Orde. We gaan van hem af en we scoren twee keer. Neem de orakels van de Orakel mee naar de sleutelmeester in de grensgebieden.,"Den andre biten ligger i hjertet av det purpurfargede og obsidianske tårnet. Der finner du biskopen. Biskopen er Ordenens militære leder. Dreper vi ham, scorer vi to ganger. Ta oraklets symbol til nøkkelmesteren i grenselandene.",Drugi kawałek leży w sercu karmazynowej i obsydianowej wieży. Znajdziesz tam Biskupa. Biskup jest przywódcą wojskowym Zakonu. Wyłączamy go i zdobywamy dwa razy punkty. Zabierz żeton Wyroczni do mistrza kluczy na pograniczu.,A segunda peça está no coração da torre carmesin e obsidiana. Lá você encontrará o Bispo. Ele é o líder militar da Ordem. Nós apagamos ele e serão dois coelhos numa tacada só. Leve o emblema do Oráculo para o mestre das chaves nas fronteiras.,,A doua piesă e în inima turnului stăveziu din obsidian. Episcopul e liderul miltar ar Ordinului. Îl omorâm și înscriem de două ori. Ia semnul Oracolului la stăpânul cheii în mărginime.,Второй фрагмент лежит в сердце багрово-обсидиановой башни. Там ты сразишься с Епископом. Епископ — военный лидер Ордена. От его убийства мы выигрываем вдвойне. Отнеси жетон Оракула ключнику в пограничье.,,İkinci parça kızıl ve obsidyen kulenin kalbinde yatıyor. Orada Piskopos'u bulacaksın. Piskopos Tarikat'ın askeri lideri. Onu yok edersek iki puan alırız. Kahin'in simgesini sınır bölgelerindeki anahtar ustasına götürün. -"The Bishop is going to be heavily guarded, so why don't we swipe a uniform and blend in? Locate the Bishop. Once you have destroyed him, return to the Oracle.",TXT_ILOG57,MAP11: Officer's uniform room.,,,"Biskup bude silně strážen, co takhle sebrat uniformu a splynout s davem? Najdi Biskupa. Až ho zabiješ, vrať se k Věštci.","Biskoppen vil være stærkt bevogtet, så hvorfor stjæler vi ikke en uniform og blander os i mængden? Find biskoppen. Når du har udslettet ham, vender du tilbage til Oraklet.","Der Bischof wird schwer bewacht sein, also warum besorgen wir uns nicht eine Uniform und mischen uns unter seine Leute? Finde den Bischof. Wenn du ihn vernichtet hast, kehre zum Orakel zurück.",,,"El Obispo estará fuertemente protegido, así que ¿por qué no robamos un uniforme y nos mezclamos? Localiza al Obispo. Una vez lo hayas destruído, vuelve con el Oráculo.",,"Piispa on tarkoin vartioitu, joten kähvellettäisiinkö univormu ja sulauduttaisiin joukkoon? Paikallista Piispa. Tuhottuasi hänet palaa Oraakkelin luo.","L'évêque sera lourdement protégé. Pourquoi ne pas faire une entrée discrète avec un uniforme? Trouve l'évêque, une fois qu'il est mort, retourne à l'Oracle.","A Püspököt elég erősen védik, ezért ajánlott, hogy szerválj magadnak egy uniformist a beolvadás végett. Találd meg a Püspököt. Ha megölted, térj vissza az Orákulumhoz.","Il Vescovo sarà sicuramente ben protetto, quindi perché non camuffarsi con un'uniforme? Trova il Vescovo. Dopo averlo distrutto, ritorna dall'Oracolo.","ビショップのいる場所の警備は厳重なので、 +国境地帯のキーマスターにオラクルのトークンを見せよ。",두 번째 시질 조각은 진홍빛 흑요석 탑에 숨어있는 비숍에게 있어. 비숍은 그들의 잔혹한 군사 지도자이지. 거기에 녀석이 있을 거야. 그를 죽이면 두 배로 이득이 갈 거야. 이 통행증을 들고 접경지 안의 열쇠지기에게로 가봐.,Het tweede stuk ligt in het hart van de karmozijnrode en obsidiaan toren. Daar vindt u de bisschop. De bisschop is de militaire leider van de Orde. We gaan van hem af en we scoren twee keer. Neem de orakels van de Orakel mee naar de sleutelmeester in de grensgebieden.,"Den andre biten ligger i hjertet av det purpurfargede og obsidianske tårnet. Der finner du biskopen. Biskopen er Ordenens militære leder. Dreper vi ham, scorer vi to ganger. Ta oraklets symbol til nøkkelmesteren i grenselandene.",Drugi kawałek leży w sercu karmazynowej i obsydianowej wieży. Znajdziesz tam Biskupa. Biskup jest przywódcą wojskowym Zakonu. Wyłączamy go i zdobywamy dwa razy punkty. Zabierz żeton Wyroczni do mistrza kluczy na pograniczu.,A segunda peça está no coração da torre carmesin e obsidiana. Lá você encontrará o Bispo. Ele é o líder militar da Ordem. Nós apagamos ele e serão dois coelhos numa tacada só. Leve o emblema do Oráculo para o mestre das chaves nas fronteiras.,,A doua piesă e în inima turnului stăveziu din obsidian. Episcopul e liderul miltar ar Ordinului. Îl omorâm și înscriem de două ori. Ia semnul Oracolului la stăpânul cheii în mărginime.,Второй фрагмент лежит в сердце багрово-обсидиановой башни. Там ты сразишься с Епископом. Епископ — военный лидер Ордена. От его убийства мы выигрываем вдвойне. Отнеси жетон Оракула ключнику в пограничье.,,Den andra delen ligger i hjärtat av det karmosinröda och obsidianska tornet. Där hittar du biskopen. Biskopen är ordens militära ledare. Om vi dödar honom gör vi två poäng. Ta Orakelns token till nyckelmästaren i gränslandet.,İkinci parça kızıl ve obsidyen kulenin kalbinde yatıyor. Orada Piskopos'u bulacaksın. Piskopos Tarikat'ın askeri lideri. Onu yok edersek iki puan alırız. Kahin'in simgesini sınır bölgelerindeki anahtar ustasına götürün. +"The Bishop is going to be heavily guarded, so why don't we swipe a uniform and blend in? Locate the Bishop. Once you have destroyed him, return to the Oracle.",TXT_ILOG57,MAP11: Officer's uniform room.,,,"Biskup bude silně strážen, co takhle sebrat uniformu a splynout s davem? Najdi Biskupa. Až ho zabiješ, vrať se k Věštci.","Biskoppen vil være stærkt bevogtet, så hvorfor stjæler vi ikke en uniform og blander os i mængden? Find biskoppen. Når du har udslettet ham, vender du tilbage til Oraklet.","Der Bischof wird schwer bewacht sein, also warum besorgen wir uns nicht eine Uniform und mischen uns unter seine Leute? Finde den Bischof. Wenn du ihn vernichtet hast, kehre zum Orakel zurück.",,"La Episkopo havas multe da sekureco. Kio pri ŝteli uniformon kaj miksiĝi? Trovu la Episkopon, mortigu lin kaj reiru al la Orakolo.","El Obispo tiene mucha seguridad. ¿Y si robamos un uniforme y nos mezclamos? Encuentra al Obispo, mátalo y vuelve con el Oráculo.",,"Piispa on tarkoin vartioitu, joten kähvellettäisiinkö univormu ja sulauduttaisiin joukkoon? Paikallista Piispa. Tuhottuasi hänet palaa Oraakkelin luo.","L'évêque sera lourdement protégé. Pourquoi ne pas faire une entrée discrète avec un uniforme? Trouve l'évêque, une fois qu'il est mort, retourne à l'Oracle.","A Püspököt elég erősen védik, ezért ajánlott, hogy szerválj magadnak egy uniformist a beolvadás végett. Találd meg a Püspököt. Ha megölted, térj vissza az Orákulumhoz.","Il Vescovo sarà sicuramente ben protetto, quindi perché non camuffarsi con un'uniforme? Trova il Vescovo. Dopo averlo distrutto, ritorna dall'Oracolo.","ビショップのいる場所の警備は厳重なので、 奴等の制服を盗み紛れ込む方が良いのでは? -ビショップを探し、始末したらオラクルの元へ戻ろう。","비숍은 군사 지도자니까, 삼엄한 경비에 의해 지켜질 거야. 그러니 전투복을 입고 잠입하는 게 어때? 비숍을 찾아서, 그를 파괴하고 오라클에게 찾아가 봐.","De bisschop zal zwaar bewaakt worden, dus waarom vegen we er niet een uniform overheen en mengen we ons in de bisschop? Zoek de bisschop. Als je hem hebt vernietigd, keer je terug naar het Orakel.","Biskopen kommer til å være tungt bevoktet, så hvorfor tar vi ikke en uniform og smelter inn? Finn biskopen. Når du har tilintetgjort ham, gå tilbake til oraklet.","Biskup będzie pilnie strzeżony, więc może weźmiemy mundur i wtopimy się w tłum? Zlokalizuj Bishopa. Kiedy już go zniszczysz, wróć do Wyroczni.","O Bispo estará protegido por vários guardas, então que tal roubar um uniforme e se mesclar a eles? Localize o Bispo. Assim que você destruí-lo, volte ao Oráculo.",,"Episcopul o să fie extrem de bine înarmat, deci de ce nu strecurăm o uniformă ca să ne camuflăm? Găsește Episcopul. Odată ce l-ai distrus, întoarce-te la Oracol.","Похоже, что Епископа неплохо охраняют, так что почему бы нам не стянуть униформу и прокрасться внутрь? Найди Епископа. После того, как ты уничтожишь его, возвращайся к Оракулу.",,"Piskopos çok sıkı korunuyor olacak, o yüzden neden bir üniforma çalıp aralarına karışmıyoruz? Piskoposu bulun. Onu yok ettikten sonra Kahin'e dönün." -"I just got word that we have an informer inside the fortress. Let's head for the hospital. He works there. After that, locate the Bishop and destroy him. Once he's dead return to the Oracle.",TXT_ILOG59,MAP17: Bailey → Upstairs.,,,"Právě jsem dostala zprávu, že máme v pevnosti informátora. Měli bychom zamířit k nemocnici, pracuje tam. Poté najdi Biskupa. Až ho zabiješ, vrať se k Věštci.","Jeg har lige fået at vide, at vi har en stikker inde i fæstningen. Lad os tage til hospitalet. Han arbejder der. Derefter skal du finde biskoppen og ødelægge ham. Når han er død, skal du vende tilbage til Oraklet.","Mir ist gerade zu Ohren gekommen, dass wir einen Informanten in der Festung haben. Lasst uns zum Krankenhaus gehen, er arbeitet dort. Danach finde den Bischof unz vernichte ihn. Sobald er tot ist kehre zum Orakel zurück.",,,"Acaban de decirme que tenemos un informante dentro de la fortaleza; vayamos al hospital, que es donde trabaja. Luego localiza al Obispo y destrúyelo. Una vez muerto, vuelve con el Oráculo.","Acaban de decirme que tenemos un informante adentro de la fortaleza; vayamos al hospital, que es donde trabaja. Luego localiza al Obispo y destrúyelo. Una vez muerto, vuelve con el Oráculo.","Sain juuri tiedon ilmiantajasta linnoituksessa. Matkataan sairaalaan; hän työskentelee siellä. Sen jälkeen löydä Piispa ja tuhoa hänet. Kun hän on kuollut, palaa Oraakkelin luo.","Je viens d'avoir vent que l'on a un informant dans la forteresse. Allons à l'hôpital, il y travaille. Après ça, trouve l'évêque et tue-le, puis retourne à l'Oracle.","Most kaptam a hírt, hogy van egy belső emberünk az erődítményben. Menjünk a kórházba. Ott dolgozik. Azután találd meg a Püspököt, és öld meg. Ha meghalt, menj az Orákulumhoz.","Ho appena scoperto che abbiamo un informatore dentro la fortezza. Rechiamoci all'ospedale. Lui lavora là. Dopodiché, trova il Vescovo e distruggilo. Non appena è morto, torna dall'Oracolo.","要塞の中に情報提供者がいるという話を聞いた。 -奴等が病院と呼んでいる場所に勤めているので向かいましょう。","요새 안에 우리들을 도울 정보원이 있다는 보고를 들었어. 그는 병원 안에 있는데, 그곳으로 찾아가 봐. 만난 뒤엔 비숍을 찾은 뒤 그를 파괴하고 오라클에게 찾아가 봐.","Ik heb net vernomen dat we een informant in het fort hebben. Laten we naar het ziekenhuis gaan. Hij werkt daar. Zoek daarna de bisschop en vernietig hem. Als hij dood is, ga dan terug naar het Orakel.","Jeg fikk nettopp beskjed om at vi har en informant inne i festningen. La oss dra til sykehuset. Han jobber der. Etter det, finn biskopen og drep ham. Når han er død, gå tilbake til Orakelet.","Właśnie dostałem wiadomość, że mamy informatora w twierdzy. Jedźmy do szpitala. On tam pracuje. Po tym zlokalizuj Bishopa i zniszcz go. Gdy będzie martwy, wróć do Wyroczni.","Acabei de saber que temos um informante dentro da fortaleza. Vamos ao hospital. Ele trabalha lá. Após isso, localize o Bispo e destrua-o. Assim que ele morrer retorne ao Oráculo.",,"Tocmai am primit informație că avem un informator în fortăreață. Să mergem către spital. Acolo lucrează. După aceea, să îl găsim pe Episcop și să-l eliminăm. Odată ce e mort întoarce-te la Oracol.","Мне только что сказали, что у нас есть информатор внутри крепости. Идём к госпиталю — он работает там. Затем найди Епископа и убей его. После его смерти вернись к Оракулу.",,"Az önce kalenin içinde bir muhbirimiz olduğu haberini aldım. Hastaneye gidelim. Orada çalışıyor. Ondan sonra, Piskoposu bulun ve onu yok edin. O öldükten sonra Kahin'e dönün." -"Don't give up. This is it. Straight ahead. Jump on the teleporter to central administration and destroy the computer core. This will kill the force field on the entrance to the Bishop's tower. Once he's dead, return to the Oracle.",TXT_ILOG64,MAP19: Last room (southwestern).,,,"Nevzdávej se, tohle je ono. Jdi rovně. Skoč na teleportér do centrálního velení a znič počítačové jádro. To zruší silové pole u vchodu do Biskupovy věže. Až ho zabiješ, vrať se k Věštci.","Du må ikke give op. Nu gælder det. Lige fremad. Hop på teleporteren til centraladministrationen og ødelæg computerkernen. Dette vil dræbe kraftfeltet ved indgangen til Bishop's tårn. Når han er død, skal du vende tilbage til Oraklet.",Nicht aufgeben. Da ist es. Direkt voraus. Springe auf den Teleporter zur Zentralverwaltung und zerstöre den Kern des Computers. Das wird das Kraftfeld zum Eingang des Turms des Bischofs lahmlegen. Sobald er tot ist kehre zum Orakel zurück.,,,"No te rindas. Aquí es. Justo de frente. Entra al teletransporte a la administración central y destruye el núcleo de la computadora. Esto apagará el campo de fuerza en la entrada a la torre del Obispo. Una vez muerto, vuelve con el Oráculo.","No re rindas. Aquí está. Justo enfrente. Entra al teleporte a la Administración Central y destruye el núcleo de la computadora. Esto quitará el campo de fuerza a la entrada de la torre del Obispo. Cuando esté muerto, regresa con el Oráculo.","Älä luovuta. Se on nyt tässä, suoraan edessä. Astu keskushallintoon johtavaan kaukosiirtimeen ja tuhoa keskustietokone. Se sammuttaa Piispan tornin voimakentän. Kun hän on kuollut, palaa Oraakkelin luo.","N'abandonne pas, on y est bientôt. Utilise le téléporteur vers le centre d'administration et détruis le cœur informatique. Cela désactivera le champ de force et l'entrée vers la tour de l'évêque. Une fois qu'il est mort, retourne voir l'Oracle.","Ne add fel. Már a célegyenesben vagyunk, rögtön előttünk van. A teleportot használva menj a központi irányításhoz és semmisítsd meg a számítógép magot. Ez majd kikapcsolja a Püspök tornyának bejárati erőpajzsát. Ha megölted, térj vissza az Orákulumhoz.","Non arrenderti. Siamo arrivati. Dritto in fronte a te. Entra in questo teletrasporto per l'amministrazione centrale e distruggi il nucleo del computer. Questo disattiverà il campo di forza per l'ingresso della torre del Vescovo. Non appena è morto, torna dall'Oracolo","諦めないで。これでいいんだ。真っ直ぐ行こう。 +ビショップを探し、始末したらオラクルの元へ戻ろう。","비숍은 군사 지도자니까, 삼엄한 경비에 의해 지켜질 거야. 그러니 전투복을 입고 잠입하는 게 어때? 비숍을 찾아서, 그를 파괴하고 오라클에게 찾아가 봐.","De bisschop zal zwaar bewaakt worden, dus waarom vegen we er niet een uniform overheen en mengen we ons in de bisschop? Zoek de bisschop. Als je hem hebt vernietigd, keer je terug naar het Orakel.","Biskopen kommer til å være tungt bevoktet, så hvorfor tar vi ikke en uniform og smelter inn? Finn biskopen. Når du har tilintetgjort ham, gå tilbake til oraklet.","Biskup będzie pilnie strzeżony, więc może weźmiemy mundur i wtopimy się w tłum? Zlokalizuj Bishopa. Kiedy już go zniszczysz, wróć do Wyroczni.","O Bispo estará protegido por vários guardas, então que tal roubar um uniforme e se mesclar a eles? Localize o Bispo. Assim que você destruí-lo, volte ao Oráculo.",,"Episcopul o să fie extrem de bine înarmat, deci de ce nu strecurăm o uniformă ca să ne camuflăm? Găsește Episcopul. Odată ce l-ai distrus, întoarce-te la Oracol.","Похоже, что Епископа неплохо охраняют, так что почему бы нам не стянуть униформу и прокрасться внутрь? Найди Епископа. После того, как ты уничтожишь его, возвращайся к Оракулу.",,"Biskopen kommer att vara tungt bevakad, så varför inte sno en uniform och smälta in? Leta upp biskopen. När du har förintat honom återvänder du till oraklet.","Piskopos çok sıkı korunuyor olacak, o yüzden neden bir üniforma çalıp aralarına karışmıyoruz? Piskoposu bulun. Onu yok ettikten sonra Kahin'e dönün." +"I just got word that we have an informer inside the fortress. Let's head for the hospital. He works there. After that, locate the Bishop and destroy him. Once he's dead return to the Oracle.",TXT_ILOG59,MAP17: Bailey → Upstairs.,,,"Právě jsem dostala zprávu, že máme v pevnosti informátora. Měli bychom zamířit k nemocnici, pracuje tam. Poté najdi Biskupa. Až ho zabiješ, vrať se k Věštci.","Jeg har lige fået at vide, at vi har en stikker inde i fæstningen. Lad os tage til hospitalet. Han arbejder der. Derefter skal du finde biskoppen og ødelægge ham. Når han er død, skal du vende tilbage til Oraklet.","Mir ist gerade zu Ohren gekommen, dass wir einen Informanten in der Festung haben. Lasst uns zum Krankenhaus gehen, er arbeitet dort. Danach finde den Bischof unz vernichte ihn. Sobald er tot ist kehre zum Orakel zurück.",,"Mi ĵus estis sciigita, ke ni havas informanton en la fortreso: ni iru al la malsanulejo (Hospital) lia laborejo. Vi tiam trovu la Episkopon, mortigu lin kaj reiru al la Orakolo.","Acaban de decirme que tenemos un informante dentro de la fortaleza: vayamos al hospital, que es donde trabaja. Luego encuentra al Obispo, mátalo y vuelve con el Oráculo.","Acaban de decirme que tenemos un informante adentro de la fortaleza: vayamos al hospital, que es donde trabaja. Luego encuentra al Obispo, mátalo y vuelve con el Oráculo.","Sain juuri tiedon ilmiantajasta linnoituksessa. Matkataan sairaalaan; hän työskentelee siellä. Sen jälkeen löydä Piispa ja tuhoa hänet. Kun hän on kuollut, palaa Oraakkelin luo.","Je viens d'avoir vent que l'on a un informant dans la forteresse. Allons à l'hôpital, il y travaille. Après ça, trouve l'évêque et tue-le, puis retourne à l'Oracle.","Most kaptam a hírt, hogy van egy belső emberünk az erődítményben. Menjünk a kórházba. Ott dolgozik. Azután találd meg a Püspököt, és öld meg. Ha meghalt, menj az Orákulumhoz.","Ho appena scoperto che abbiamo un informatore dentro la fortezza. Rechiamoci all'ospedale. Lui lavora là. Dopodiché, trova il Vescovo e distruggilo. Non appena è morto, torna dall'Oracolo.","要塞の中に情報提供者がいるという話を聞いた。 +奴等が病院と呼んでいる場所に勤めているので向かいましょう。","요새 안에 우리들을 도울 정보원이 있다는 보고를 들었어. 그는 병원 안에 있는데, 그곳으로 찾아가 봐. 만난 뒤엔 비숍을 찾은 뒤 그를 파괴하고 오라클에게 찾아가 봐.","Ik heb net vernomen dat we een informant in het fort hebben. Laten we naar het ziekenhuis gaan. Hij werkt daar. Zoek daarna de bisschop en vernietig hem. Als hij dood is, ga dan terug naar het Orakel.","Jeg fikk nettopp beskjed om at vi har en informant inne i festningen. La oss dra til sykehuset. Han jobber der. Etter det, finn biskopen og drep ham. Når han er død, gå tilbake til Orakelet.","Właśnie dostałem wiadomość, że mamy informatora w twierdzy. Jedźmy do szpitala. On tam pracuje. Po tym zlokalizuj Bishopa i zniszcz go. Gdy będzie martwy, wróć do Wyroczni.","Acabei de saber que temos um informante dentro da fortaleza. Vamos ao hospital. Ele trabalha lá. Após isso, localize o Bispo e destrua-o. Assim que ele morrer retorne ao Oráculo.",,"Tocmai am primit informație că avem un informator în fortăreață. Să mergem către spital. Acolo lucrează. După aceea, să îl găsim pe Episcop și să-l eliminăm. Odată ce e mort întoarce-te la Oracol.","Мне только что сказали, что у нас есть информатор внутри крепости. Идём к госпиталю — он работает там. Затем найди Епископа и убей его. После его смерти вернись к Оракулу.",,Jag fick just veta att vi har en informatör inne i fästningen. Vi går till sjukhuset. Han jobbar där. Efter det ska du lokalisera biskopen och förgöra honom. När han är död återvänder du till oraklet.,"Az önce kalenin içinde bir muhbirimiz olduğu haberini aldım. Hastaneye gidelim. Orada çalışıyor. Ondan sonra, Piskoposu bulun ve onu yok edin. O öldükten sonra Kahin'e dönün." +"Don't give up. This is it. Straight ahead. Jump on the teleporter to central administration and destroy the computer core. This will kill the force field on the entrance to the Bishop's tower. Once he's dead, return to the Oracle.",TXT_ILOG64,MAP19: Last room (southwestern).,,,"Nevzdávej se, tohle je ono. Jdi rovně. Skoč na teleportér do centrálního velení a znič počítačové jádro. To zruší silové pole u vchodu do Biskupovy věže. Až ho zabiješ, vrať se k Věštci.","Du må ikke give op. Nu gælder det. Lige fremad. Hop på teleporteren til centraladministrationen og ødelæg computerkernen. Dette vil dræbe kraftfeltet ved indgangen til Bishop's tårn. Når han er død, skal du vende tilbage til Oraklet.",Nicht aufgeben. Da ist es. Direkt voraus. Springe auf den Teleporter zur Zentralverwaltung und zerstöre den Kern des Computers. Das wird das Kraftfeld zum Eingang des Turms des Bischofs lahmlegen. Sobald er tot ist kehre zum Orakel zurück.,,"Uzu la teleportilon al la centra administrejo kaj detruu la kernon de la komputilo, kiu tenas la fortokampon ĉe la enirejo de la turo de la Episkopo. Mortiginte lin, reiru al la Orakolo.","Entra en el teletransportador a la administración central y destruye el núcleo del ordenador que mantiene el campo de fuerza en la entrada de la torre del Obispo. Una vez muerto, vuelve con el Oráculo.","Entra al teletransportador a la administración central y destruye el núcleo de la computadora que mantiene el campo de fuerza en la entrada de la torre del Obispo. Una vez muerto, vuelve con el Oráculo.","Älä luovuta. Se on nyt tässä, suoraan edessä. Astu keskushallintoon johtavaan kaukosiirtimeen ja tuhoa keskustietokone. Se sammuttaa Piispan tornin voimakentän. Kun hän on kuollut, palaa Oraakkelin luo.","N'abandonne pas, on y est bientôt. Utilise le téléporteur vers le centre d'administration et détruis le cœur informatique. Cela désactivera le champ de force et l'entrée vers la tour de l'évêque. Une fois qu'il est mort, retourne voir l'Oracle.","Ne add fel. Már a célegyenesben vagyunk, rögtön előttünk van. A teleportot használva menj a központi irányításhoz és semmisítsd meg a számítógép magot. Ez majd kikapcsolja a Püspök tornyának bejárati erőpajzsát. Ha megölted, térj vissza az Orákulumhoz.","Non arrenderti. Siamo arrivati. Dritto in fronte a te. Entra in questo teletrasporto per l'amministrazione centrale e distruggi il nucleo del computer. Questo disattiverà il campo di forza per l'ingresso della torre del Vescovo. Non appena è morto, torna dall'Oracolo","諦めないで。これでいいんだ。真っ直ぐ行こう。 中央管理室のテレポーターに入りコンピューターコアを破壊せよ。 それはビショップのフォースフィールドを殺せる。 -ビショップも殺したらオラクルの元へ戻れ。",포기하지 마. 이제 거의 다 왔어. 저 텔레포터를 올라타서 관리소로 가서 컴퓨터 중심부를 파괴해. 방어막을 완전히 꺼버리고 비숍을 죽일 수 있을 거야. 그를 파괴하고 오라클에게 찾아가 봐.,"Geef niet op. Dit is het. Rechtdoor. Spring op de teleporter naar de centrale administratie en vernietig de computerkern. Dit zal het krachtveld op de ingang van de Bisschopstoren doden. Als hij dood is, keer je terug naar het Orakel.","Ikke gi opp. Her er det. Rett frem. Hopp på teleporteren til sentraladministrasjonen og ødelegg datakjernen. Dette vil drepe kraftfeltet ved inngangen til biskopens tårn. Når han er død, gå tilbake til Oraklet.","Nie poddawaj się. To jest to. Prosto przed siebie. Wskocz na teleporter do centralnej administracji i zniszcz rdzeń komputera. To zabije pole siłowe przy wejściu do wieży biskupa. Gdy będzie już martwy, wróć do Oracle.",Não desista. A hora é agora. Siga reto adiante. Entre no teletransportador para a administração central e destrua o núcleo de computação. Isso vai derrubar o campo de força na entrada da torre do Bispo. Assim que ele morrer retorne ao Oráculo.,,"Nu te da bătut. Drept în față. Sari pe teleportorul către administrația centrală și distruge nucleul calculatoarelor. Asta va distruge câmpul de forță la intrarea în turnul Episcopului. Odată ce e mort, întoarce-te la Oracol.","Не падай духом. Вот оно. Прямо впереди. Прыгай в телепорт к центральной администрации и уничтожь центральный компьютер. Это отключит силовое поле на входе в башню Епископа. После его смерти, возвращайся к Оракулу.",,"Sakın pes etmeyin. İşte burası. Dümdüz ilerleyin. Merkezi yönetime giden ışınlayıcıya atla ve bilgisayar çekirdeğini yok et. Bu, Piskopos'un kulesinin girişindeki güç alanını yok edecek. O öldükten sonra Kahin'e dönün." -"Very impressive. Lets blow it up. That should take care of the force field. Let's get back to the bailey, then off to the tower and the Bishop.",TXT_ILOG70,MAP15: After pressing the switch to reveal the computer.,,,Velmi působivé. Co to nechat vybouchnout? To by se mělo postarat o silové pole. Vraťme se zpět do opevnění a tam do věže a k Biskupovi.,Meget imponerende. Lad os sprænge det i luften. Det burde tage sig af kraftfeltet. Lad os komme tilbage til borggården og derefter hen til tårnet og biskoppen.,"Sehr eindrucksvoll. Lass es uns in die Luft jagen. Damit sollte das Kraftfeld ausgeschaltet sein. Lass uns zum Vorhof zurückkehren, dann zum Turm und dem Bischof.",,,"Muy impresionante. Vamos a destruirlo; eso debería ocuparse del campo de fuerza. Volvamos al patio, luego derecho a la torre y al Obispo.","Muy impresionante. Vamos a destruirla; eso debería ocuparse del campo de fuerza. Volvamos al patio, luego derecho a la torre y al Obispo.","Aika vaikuttava. Posautetaan se. Sillä voimakentän pitäisi hoitua. Palataan linnanpihaan, josta sitten torniin Piispan luo.","Excellent, maintenant, faisons tout sauter. Cela devrait nous débarasser du cœur informatique. Retourne au mur d'enceinte puis rentre dans la tour de l'évêque.","Felettébb lenyűgöző. Robbantsuk is fel. Ez majd gondoskodik az erőpajzsról. Menjünk vissza a várfalhoz, majd a toronyhoz és magához a Püspökhöz.",Davvero impressionante. Facciamolo saltare in aria. Ora il campo di forza dovrebbe essere disattivato. Ora raggiungiamo la torre e facciamo fuori il Vescovo.,"あら、見事な物ね。是非とも火薬を献上しましょう。 -それでベイリーに戻ってフォースフィールドが守っていたビショップの塔へ向かおう。",아주 인상 깊은데? 어서 파괴하자고. 그러면 방어막을 끌 수 있을 거야. 그 후에 안뜰로 향해서 성으로 찾아가. 그리고 비숍을 죽여버려.,"Zeer indrukwekkend. Laten we het opblazen. Dat zou voor het krachtveld moeten zorgen. Laten we teruggaan naar de bailey, dan naar de toren en de bisschop.","Veldig imponerende. La oss sprenge det. Det burde ta seg av kraftfeltet. La oss gå tilbake til borggården, og så til tårnet og biskopen.","Bardzo efektowne. Wysadźmy ją w powietrze. To powinno załatwić sprawę pola siłowego. Wracajmy na podzamcze, a potem do wieży i biskupa.",Impressionante mesmo. Vamos detoná-lo. Isso deve dar um jeito no campo de força. Volte para a fortaleza e depois vá para a torre encontrar o Bispo.,,"Foarte impresionant. Să-l aruncăm în aer. Asta va rezolva problema câmpului de forță. Să ne întoarcem la alee, apoi către turn și Episcop.","Очень впечатляюще. Давай взорвём. Это должно избавить нас от проблем с силовым полем. Возвращаемся во внутренний двор, затем к башне и Епископу.",,"Çok etkileyici. Hadi onu havaya uçuralım. Bu güç alanının icabına bakacaktır. Dış avluya geri dönelim, sonra kuleye ve Piskopos'a gidelim." -"Bravo, another piece of the Sigil! Did you see that weird spectre that came out of the Bishop's body? Where have I seen that before? Let's get back to the Oracle.",TXT_ILOG74,,,,"Bravo, další díl Pečetě! Viděl jsi ten divný přízrak, který vyšel z Biskupova těla? Kde jsem ho jen předtím viděla? Vraťme se k Věštci.","Bravo, endnu et stykke af Sigil! Så du det underlige spøgelse, der kom ud af biskoppens krop? Hvor har jeg set det før? Lad os gå tilbage til Oraklet.","Gratulation, ein weiteres Teil des Sigils! Hast du den merkwürdigen Schemen gesehen, der aus dem Körper des Bischofs herauskam? Wo habe ich ihn bloß schon einmal gesehen? Lass uns zum Orakel zurückkehren.",,,"¡Bravo, otra pieza del Emblema! ¿Viste ese extraño espectro que salió del cuerpo del Obispo? ¿Donde he visto eso antes? Volvamos con el Oráculo.","¡Bravo, otra pieza del Emblema! ¿Viste ese extraño espectro que salió del cuerpo del Obispo? ¿Dónde he visto eso antes? Regresemos con el Oráculo.","Bravo, toinen Sinetin osanen! Näitkö tuon oudon aaveen, joka nousi Piispan ruumiista? Missä olen nähnyt sen aiemmin? Palataan Oraakkelin luokse.","Bravo, encore une pièce du Sigil! Tu a vu ce spectre étrange qui est sorti du corps de l'évêque? Je crois l'avoir vu avant, retournons à l'Oracle.","Bravó, egy újabb pecsét darab! Láttad azt a fura kísértetet ami a Püspök teteméből eltávozott? Hol is láttam hasonlót? Menjünk vissza az Orákulumhoz.","Bravo, un altro pezzo del Sigillo! Hai visto quello strano spettro che è uscito dal corpo del Vescovo? Dove l'ho già visto prima? Torniamo dall'Oracolo.","ブラボー!新たなるシジルの欠片だ! +ビショップも殺したらオラクルの元へ戻れ。",포기하지 마. 이제 거의 다 왔어. 저 텔레포터를 올라타서 관리소로 가서 컴퓨터 중심부를 파괴해. 방어막을 완전히 꺼버리고 비숍을 죽일 수 있을 거야. 그를 파괴하고 오라클에게 찾아가 봐.,"Geef niet op. Dit is het. Rechtdoor. Spring op de teleporter naar de centrale administratie en vernietig de computerkern. Dit zal het krachtveld op de ingang van de Bisschopstoren doden. Als hij dood is, keer je terug naar het Orakel.","Ikke gi opp. Her er det. Rett frem. Hopp på teleporteren til sentraladministrasjonen og ødelegg datakjernen. Dette vil drepe kraftfeltet ved inngangen til biskopens tårn. Når han er død, gå tilbake til Oraklet.","Nie poddawaj się. To jest to. Prosto przed siebie. Wskocz na teleporter do centralnej administracji i zniszcz rdzeń komputera. To zabije pole siłowe przy wejściu do wieży biskupa. Gdy będzie już martwy, wróć do Oracle.",Não desista. A hora é agora. Siga reto adiante. Entre no teletransportador para a administração central e destrua o núcleo de computação. Isso vai derrubar o campo de força na entrada da torre do Bispo. Assim que ele morrer retorne ao Oráculo.,,"Nu te da bătut. Drept în față. Sari pe teleportorul către administrația centrală și distruge nucleul calculatoarelor. Asta va distruge câmpul de forță la intrarea în turnul Episcopului. Odată ce e mort, întoarce-te la Oracol.","Не падай духом. Вот оно. Прямо впереди. Прыгай в телепорт к центральной администрации и уничтожь центральный компьютер. Это отключит силовое поле на входе в башню Епископа. После его смерти, возвращайся к Оракулу.",,Ge inte upp. Det här är det. Rakt fram. Hoppa på teleportern till centraladministrationen och förstör datorkärnan. Detta kommer att döda kraftfältet vid ingången till biskopens torn. När han är död återvänder du till oraklet.,"Sakın pes etmeyin. İşte burası. Dümdüz ilerleyin. Merkezi yönetime giden ışınlayıcıya atla ve bilgisayar çekirdeğini yok et. Bu, Piskopos'un kulesinin girişindeki güç alanını yok edecek. O öldükten sonra Kahin'e dönün." +"Very impressive. Lets blow it up. That should take care of the force field. Let's get back to the bailey, then off to the tower and the Bishop.",TXT_ILOG70,MAP15: After pressing the switch to reveal the computer.,,,Velmi působivé. Co to nechat vybouchnout? To by se mělo postarat o silové pole. Vraťme se zpět do opevnění a tam do věže a k Biskupovi.,Meget imponerende. Lad os sprænge det i luften. Det burde tage sig af kraftfeltet. Lad os komme tilbage til borggården og derefter hen til tårnet og biskoppen.,"Sehr eindrucksvoll. Lass es uns in die Luft jagen. Damit sollte das Kraftfeld ausgeschaltet sein. Lass uns zum Vorhof zurückkehren, dann zum Turm und dem Bischof.",,"Detruu la komputilon; tio devus forigi la fortokampon. Reiru al la korto, eniru la turon kaj serĉu la Episkopon.","Destruye el ordenador; eso debería deshacerse del campo de fuerza. Volvamos al patio, luego directo a la torre y al Obispo.","Destruye la computadora; eso debería deshacerse del campo de fuerza. Volvamos al patio, luego directo a la torre y al Obispo.","Aika vaikuttava. Posautetaan se. Sillä voimakentän pitäisi hoitua. Palataan linnanpihaan, josta sitten torniin Piispan luo.","Excellent, maintenant, faisons tout sauter. Cela devrait nous débarasser du cœur informatique. Retourne au mur d'enceinte puis rentre dans la tour de l'évêque.","Felettébb lenyűgöző. Robbantsuk is fel. Ez majd gondoskodik az erőpajzsról. Menjünk vissza a várfalhoz, majd a toronyhoz és magához a Püspökhöz.",Davvero impressionante. Facciamolo saltare in aria. Ora il campo di forza dovrebbe essere disattivato. Ora raggiungiamo la torre e facciamo fuori il Vescovo.,"あら、見事な物ね。是非とも火薬を献上しましょう。 +それでベイリーに戻ってフォースフィールドが守っていたビショップの塔へ向かおう。",아주 인상 깊은데? 어서 파괴하자고. 그러면 방어막을 끌 수 있을 거야. 그 후에 안뜰로 향해서 성으로 찾아가. 그리고 비숍을 죽여버려.,"Zeer indrukwekkend. Laten we het opblazen. Dat zou voor het krachtveld moeten zorgen. Laten we teruggaan naar de bailey, dan naar de toren en de bisschop.","Veldig imponerende. La oss sprenge det. Det burde ta seg av kraftfeltet. La oss gå tilbake til borggården, og så til tårnet og biskopen.","Bardzo efektowne. Wysadźmy ją w powietrze. To powinno załatwić sprawę pola siłowego. Wracajmy na podzamcze, a potem do wieży i biskupa.",Impressionante mesmo. Vamos detoná-lo. Isso deve dar um jeito no campo de força. Volte para a fortaleza e depois vá para a torre encontrar o Bispo.,,"Foarte impresionant. Să-l aruncăm în aer. Asta va rezolva problema câmpului de forță. Să ne întoarcem la alee, apoi către turn și Episcop.","Очень впечатляюще. Давай взорвём. Это должно избавить нас от проблем с силовым полем. Возвращаемся во внутренний двор, затем к башне и Епископу.",,Mycket imponerande. Låt oss spränga det i luften. Det borde ta hand om kraftfältet. Vi går tillbaka till borggården och sedan vidare till tornet och biskopen.,"Çok etkileyici. Hadi onu havaya uçuralım. Bu güç alanının icabına bakacaktır. Dış avluya geri dönelim, sonra kuleye ve Piskopos'a gidelim." +"Bravo, another piece of the Sigil! Did you see that weird spectre that came out of the Bishop's body? Where have I seen that before? Let's get back to the Oracle.",TXT_ILOG74,MAP16: After killing the Bishop.,,,"Bravo, další díl Pečetě! Viděl jsi ten divný přízrak, který vyšel z Biskupova těla? Kde jsem ho jen předtím viděla? Vraťme se k Věštci.","Bravo, endnu et stykke af Sigil! Så du det underlige spøgelse, der kom ud af biskoppens krop? Hvor har jeg set det før? Lad os gå tilbage til Oraklet.","Gratulation, ein weiteres Teil des Sigils! Hast du den merkwürdigen Schemen gesehen, der aus dem Körper des Bischofs herauskam? Wo habe ich ihn bloß schon einmal gesehen? Lass uns zum Orakel zurückkehren.",,"Brave, alia peco de la Sigelo! Kia stranga fantomo eliris el la korpo de la Episkopo. De kie ĝi ŝajnis konata al mi? Reiru al la Orakolo.","¡Bravo, otra pieza del Emblema! ¿Has visto ese extraño espectro que había salido del cuerpo del Obispo?, ¿de dónde me sonará? Volvamos con el Oráculo.","¡Bravo, otra pieza del Emblema! ¿Viste ese extraño espectro que había salido del cuerpo del Obispo?, ¿de dónde me sonará? Volvamos con el Oráculo.","Bravo, toinen Sinetin osanen! Näitkö tuon oudon aaveen, joka nousi Piispan ruumiista? Missä olen nähnyt sen aiemmin? Palataan Oraakkelin luokse.","Bravo, encore une pièce du Sigil! Tu a vu ce spectre étrange qui est sorti du corps de l'évêque? Je crois l'avoir vu avant, retournons à l'Oracle.","Bravó, egy újabb pecsét darab! Láttad azt a fura kísértetet ami a Püspök teteméből eltávozott? Hol is láttam hasonlót? Menjünk vissza az Orákulumhoz.","Bravo, un altro pezzo del Sigillo! Hai visto quello strano spettro che è uscito dal corpo del Vescovo? Dove l'ho già visto prima? Torniamo dall'Oracolo.","ブラボー!新たなるシジルの欠片だ! ビショップの体から出てきたあの奇妙な幽体を見た? -以前に何処かで見た気がするけど?",브라보! 두 번째 시질 조각을 얻었어! 그나저나 비숍 몸에서 튀어나왔던 검은 물체 봤어? 전에 본 적이 있나? 오라클에게 돌아가자.,"Bravo, nog een stukje van de Sigil! Zag je dat rare spook dat uit het lichaam van de bisschop kwam? Waar heb ik dat eerder gezien? Laten we teruggaan naar het Orakel.","Bravo, enda en bit av sigillet! Så du det rare spøkelset som kom ut av biskopens kropp? Hvor har jeg sett det før? La oss gå tilbake til oraklet.","Brawo, kolejny kawałek Sigilu! Widziałeś to dziwne widmo, które wyszło z ciała biskupa? Gdzie ja to już widziałem? Wróćmy do Wyroczni.",Bravo! Outra peça do Sigilo! Você viu aquele espectro estranho que saiu do corpo do Bispo? Onde foi que eu já vi aquilo antes? Vamos voltar para o Oráculo.,,"Bravo, încă o bucată din Sigiliu! Ai văzut spectrul ciudat ce a ieșit din corpul Episcopului? Unde am mai văzut asta oare? Să ne întoarcem la Oracol.","Браво, ещё один фрагмент Печати! Видел тот странный фантом, вышедший из тела Епископа? Где я могла видеть такое раньше? Давай вернёмся к Оракулу.",,"Bravo, Sigil'in bir parçası daha! Piskopos'un bedeninden çıkan garip hayaleti gördün mü? Bunu daha önce nerede görmüştüm? Kahin'e geri dönelim." -"I have a report that the spectral energy we found near the Bishop is also present by the Oracle, let's be careful.",TXT_ILOG76,,,,"Mám hlašení, že stejná přízračná energie, kterou jsme našli u Biskupa, se nachází také u Věštce, měli bychom být opatrní.","Jeg har en rapport om, at den spektrale energi, vi fandt nær biskoppen, også er til stede ved Oraklet, lad os være forsigtige.","Ich habe einen Report, dass die spektrale Energie, die wir beim Bischof vorfanden, auch in der Nähe des Orakels vorhanden ist. Wir sollten vorsichtig sein.",,,"Tengo un informe de que la energía espectral que encontramos cerca del Obispo también está presente junto al Oráculo, tengamos cuidado","Tengo reportes de que la energía espectral que encontramos cerca del Obispo también está presente en el Oráculo, tengamos cuidado","Sain tiedon, että aave-energiaa, jota löysimme Piispan läheltä, on läsnä myös Oraakkelin luona. Ollaan varovaisia.","Je recois un rapport que l'énergie spectrale qui possédait l'évêque se trouve aussi aux alentours de l'Oracle, fais attention.","Kaptam egy jelentést, hogy a Püspök körül érzékelt kísérteties energia észlelhető az Orákulum körül is. Vigyázzunk vele.","Ho qua un rapporto che ci informa che l'energia spettrale che abbiamo trovato vicino il Vescovo è anche presente vicino l'Oracolo, dobbiamo essere attenti.","ビショップにもあったスペクトラルエネルギーがオラクルにも宿っているという -報告があるわ、気を付けて。","지금 보고를 받았는데, 비숍을 죽인 뒤에 나온 혼령의 기운이 오라클에게도 있데. 조심하자.","Ik heb een bericht dat de spectrale energie die we in de buurt van de bisschop vonden ook aanwezig is bij het Orakel, laten we voorzichtig zijn.","Jeg har en rapport om at den spektrale energien vi fant nær biskopen også er til stede ved oraklet, la oss være forsiktige.","Mam raport, że energia widmowa, którą znaleźliśmy w pobliżu Bishopa, jest również obecna przy Wyroczni, bądźmy ostrożni.",Recebi um relatório de que a energia espectral que encontramos perto do Bispo também está presente pelo Oráculo. Precisamos tomar cuidado.,,"Am un raport care spune că energia spectrală a Episcopului a prezentă și în Oracol, s-avem grijă.","Мне доложили, что спектральная энергия, найденная нами возле Епископа, также исходит от Оракула. Будь начеку.",,"Piskoposun yanında bulduğumuz spektral enerjinin Kahin tarafından da mevcut olduğuna dair bir rapor aldım, dikkatli olalım." -Richter has taken over command of our forces. It looks like Macil has been deceiving us all along. His true allegiance was to the Order. What a snake. Let's get back to the Oracle.,TXT_ILOG79,,,,"Richter převzal velení našich sil. Zdá se, že nás Macil celou dobu klamal. Ve skutečnosti byl věrný Řádu. Slizák jeden. Vraťme se k Věštci.","Richter har overtaget kommandoen over vores styrker. Det ser ud til, at Macil har bedraget os hele tiden. Hans sande loyalitet var over for ordenen. Sikke en slange. Lad os gå tilbage til Oraklet.",Richter hat das Kommando über unsere Streitkräfte übernommen. Es scheint als hätte Macil uns die ganze Zeit über getäuscht. Sein wahre Loyalität gehörte dem Orden. Was für eine Ratte. Lass uns zum Orakel zurückkehren.,,,Richter ha tomado el mando de nuestras fuerzas. Parece que Macil nos ha estado engañando todo este tiempo. Su verdadera lealtad era a la Orden. Qué serpiente. Volvamos con el Oráculo.,Richter ha tomado el mando de nuestras fuerzas. Parece que Macil nos ha estado engañando todo el tiempo. Su verdadera lealtad fue a la Orden. Que serpiente. Volvamos con el Oráculo.,"Richter on ottanut joukkomme komentoonsa. Näyttää siltä, että Macil on pettänyt meitä alusta alkaen. Hänen todellinen uskollisuutensa on ollut Veljeskunnalle; mikä käärme. Palataan Oraakkelin luokse.","Richter a pris le contrôle de nos forces. Il semble que Macil nous a menti tout du long. Sa vraie allégiance était avec l'Ordre, quel serpent! Retournous à l'Oracle.",Richter átvette az írányítást a csapataink fölött. Úgy tűnik Macil mindvégig megtévesztett minket. Valójában mindvégig a Rend oldalán volt. micsoda kígyó. Menjünk vissza az Orákulumhoz.,Richter ha assunto il comando delle nostre forze. Sembra che Macil ci avesse ingannato fin dall'inizio. In realtà è sempre stato alleato con l'Ordine. Che serpente. Ritorniamo dall'Oracolo.,"リヒターが指揮官の任を引き継いだ。マシルはずっと私達を騙していたなんて。 -あの人がオーダーに真の忠誠を誓っていたなんて、とんだ蛇神憑きだわ。",릭터가 저항군의 새로운 지도자가 될 거야. 내 생각엔 마실이 오랫동안 우리들을 속인 것 같아... 뱀 같은 자식. 오라클에게 돌아가자.,Richter heeft het bevel over onze troepen overgenomen. Het lijkt erop dat Macil ons al die tijd heeft bedrogen. Zijn ware trouw was aan de Orde. Wat een slang. Laten we teruggaan naar het Orakel.,Richter har overtatt kommandoen over styrkene våre. Det ser ut til at Macil har lurt oss hele tiden. Hans sanne lojalitet var til Ordenen. For en slange. La oss gå tilbake til orakelet.,"Richter przejął dowodzenie nad naszymi siłami. Wygląda na to, że Macil cały czas nas zwodził. Jego prawdziwa wierność była dla Zakonu. Co za wąż. Wracajmy do Wyroczni.",O Richter assumiu o comando de nossas forças. Parece que o Macil esteve nos enganando durante todo esse tempo. Sua verdadeira lealdade era à Ordem. Que traíra! Vamos voltar para o Oráculo.,,Richter a preluat controlul asupra forțelor noastre. Se pare că Macil ne-a mințit tot timpul. A fost loial cu adevărat doar Ordinului. Ce șarpe. Să ne întoarcem la Oracol.,"Рихтер принял на себя командование нашими силами. Похоже, что Мэйсил обманывал всех нас с самого начала. На самом деле он был предан Ордену. Подлец. Давай вернёмся к Оракулу.",,Richter kuvvetlerimizin komutasını devraldı. Görünüşe göre Macil başından beri bizi kandırıyormuş. Gerçek bağlılığı Tarikat'a imiş. Ne yılan ama. Kahin'e geri dönelim. -Another Sigil piece. We are one step closer to freedom. And you are one step closer to me. Let's get back to the Oracle!,TXT_ILOG83,,,,Další díl Pečeti. Jsme o krok blíž ke svobodě. A ty jsi o krok blíž ke mě. Vraťme se k Věštci.,Endnu et Sigil-stykke. Vi er et skridt nærmere friheden. Og du er et skridt tættere på mig. Lad os komme tilbage til Oraklet!,Ein weiteres Teilstück des Sigils. Wir sind der Freiheit einen Schritt näher gekommen. Lass uns zurückgehen zum Orakel.,,,Otra pieza del Emblema. Estamos un paso más cerca de la libertad. Y estás un paso más cerca de mí. ¡Volvamos con el Oráculo!,Otra pieza del Emblema. Estamos un paso más cerca de la libertad. Y estás un paso más cerca de mí. ¡Regresemos con el Oráculo!,Jälleen uusi Sinetin osanen. Olemme taas askeleen lähempänä vapautta. Ja sinä askeleen lähempänä minua. Palataan Oraakkelin luo!,"Encore une pièce du Sigil. Nous nous rapprochons de la liberté, et tu te rapproche aussi de moi. Retournons à l'Oracle!",Még egy pecsét darab. Egy lépéssel közelebb állunk a szabadsághoz. Te pedig egy lépéssel közelebb vagy hozzám. menjünk vissza az orákulumhoz.,Un altro pezzo del Sigillo. Siamo ancora più vicini alla libertà. E tu sei ancora più vicino a me. Ritorniamo all'Oracolo!,"更なるシジルの欠片だ。私達の自由にまた一歩近づいたわ。 -そして私にも一歩近づいている。",또 다른 시질 조각이야. 자유로 향하는 길이 거의 얼마 남지 않았어. 그리고 나와 만날 순간도 얼마 남지 않았고. 오라클을 만나러 가자!,Nog een Sigil-peijsje. We zijn een stap dichter bij de vrijheid. En je bent een stap dichter bij mij. Laten we teruggaan naar het Orakel!,Enda en Sigil-brikke. Vi er ett skritt nærmere friheten. Og du er ett skritt nærmere meg. La oss gå tilbake til Orakelet!,Kolejny kawałek Sigil. Jesteśmy o krok bliżej wolności. A ty jesteś o krok bliżej mnie. Wracajmy do Wyroczni!,Outra peça do Sigilo. Estamos nos aproximando da liberdade. E você está ficando mais próximo de mim. Vamos voltar para o Oráculo!,,Altă piesă din Sigiliu. Suntem cu un pas mai aproape de libertate. Și tu ești cu un pas mai aproape de mne. Să ne întoarcem la Oracol.,Очередной фрагмент Печати. Теперь мы ещё на шаг ближе к освобождению. А ты — ещё на шаг ближе ко мне. Давай возвращаться к Оракулу!,,Başka bir Sigil parçası. Özgürlüğe bir adım daha yaklaştık. Ve sen de bana bir adım daha yaklaştın. Kahin'e geri dönelim! -You wield the power of the complete Sigil. What do you say we get some closure. Let's see what the Loremaster's been protecting.,TXT_ILOG85,,,,"Vládneš mocí složené Pečetě. Co říkáš na to, jít s tím vším skončit? Pojďme se podívat, co to Dějepisec bránil.","Du har magten af det komplette Sigil. Hvad siger du til, at vi får en afslutning? Lad os se, hvad Loremesteren har beskyttet.","Du hältst die Kraft des kompletten Sigils in deinen Händen. Meinst du nicht auch, wir sollten die Sache jetzt zu Ende bringen? Lass und nachsehen, was der Wissensmeister beschützt hat.",,,Empuñas el poder del Emblema completo. Que te parece si conseguimos algo de clausura. Vamos a ver lo que el Maestro del Conocimiento ha estado protegiendo.,Manejas el poder completo del Emblema. ¿Qué dices si conseguimos algún cierre? Veamos qué ha estado protegiendo el Maestro del Conocimiento.,"Täyden Sinetin voima on hallussasi. Mitäpä jos hakisimme päätöstä. Katsotaan, mitä Oppi-Isä oikein on varjellut.",Tu as maintenant le plein pouvoir du Sigil. Je pense qu'il est l'heure d'en finir. Allons voir ce que le Maître des Traditions cachait.,"A kompett pecsét hatalma a kezedben van. Mit szólsz ahhoz, hogy lezárjuk végleg ezt a harcot. Nézzük meg mit is védelmez a Tanmester valójában.",Hai il potere del Sigillo completo. Che ne dici di finire questa storia. Vediamo un pò cosa il Sapiente stava proteggendo.,"貴方はもはや完全なシジルの力を行使できるわけね。 -後は言いがかりでもしてここを閉鎖させましょう。",시질의 완전한 힘은 이제 네 손에 있어. 종지부를 찍을 준비 됐어? 로어마스터가 그토록 지키던 게 무엇인지 확인하자고.,Je gebruikt de kracht van de volledige Sigil. Wat zeg je ervan als we de zaak afsluiten. Laten we eens kijken wat de Kennismeester heeft beschermd.,Du har makten til hele sigillet. Hva sier du til at vi får en avslutning? La oss se hva Loremaster har beskyttet.,"Władasz mocą kompletnego Sigilu. Co powiesz na to, żebyśmy się zamknęli. Zobaczmy, co Loremaster chronił.",Você tem o poder do Sigilo completo nas suas mãos. O que acha de termos um desfecho? Vamos ver o que o Mestre do Conhecimento andou protegendo.,,Ai puterea întregului Sigiliu. Ce zici dacă avem parte de un sfârșit. Să vedem ce poate prezice Maestrul Cunoștiințelor.,"Теперь ты владеешь мощью завершённой Печати. Мы уже близко — давай покончим с этим. Посмотрим, что же охранял Хранитель мудрости.",,"Sigil'in tamamının gücüne sahipsin. Ne dersin, biraz kapanış yapalım mı? Loremaster'ın neyi koruduğunu görelim." -"Well, so much for prognostication. Hold it, Macil is calling us back. Let's get out of here in one piece.",TXT_ILOG87,,,,"No, tak to by bylo pro předpovědi. Počkej, Macil nás volá zpět. Vypadněme odsud vcelku.","Nå, så meget for prognoser. Vent, Macil kalder os tilbage. Lad os komme ud herfra i ét stykke.","Soviel zum Thema Vorhersagen. Warte, Macil ruft uns zurück. Lass uns hier heile herauskommen.",,,"Bueno, tanto por un presentimiento. Espera, Macil nos reclama. Salgamos de aquí de una pieza.","Bueno, tanto para el pronóstico. Espera, Macil nos está llamando de vuelta. Salgamos de aquí en una pieza.","No, se siitä ennustelusta. Odota, Macil kutsuu meitä takaisin. Häivytään täältä ehjin nahoin.","Bon, je pense que l'heure n'est plus au pronostics.. Attends, Macil nous appelle. Sortons d'ici en vie, si possible.","Hát, ennyit a jóslatról. Várj, Macil visszahív minket. Húzzunk innen míg egy darabban vagyunk.","Alla faccia dei prognostici... Aspetta, Macil ci sta richiamando. Meglio uscire da qua tutti interi.","まあ予言なんてそんなものでしょ。 -ちょっと待って、マシルが帰還するように言ったわ。ここから抜け出しましょう。","웃기네. 이딴 예언 따위. 잠깐만, 마실이 우리들을 부르고 있어. 이제 안전하게 기지로 돌아가자.","Nou, tot zover de prognose. Wacht even, Macil belt ons terug. Laten we hier heelhuids weggaan.","Så mye for spådommer. Vent, Macil kaller oss tilbake. La oss komme oss helskinnet ut herfra.","Cóż, to tyle jeśli chodzi o prognozowanie. Czekajcie, Macil nas wzywa. Wydostańmy się stąd w jednym kawałku.","Bem, acho que ainda não é hora de previsões. Espera, o Macil está nos chamando de volta. Vamos tentar sair daqui inteiros.",,"Atât a fost cu prognoza. Stai, Macil ne sună înapoi. Să ieșim de aici întregi.","Да, это превзошло все наши ожидания. Успокойся, Мэйсил вызывает нас назад. Давай выбираться отсюда.",,"Kehanet için çok fazla. Durun, Macil bizi geri çağırıyor. Buradan tek parça halinde çıkalım." -"The factory is next to the mines. Richter must mean the mines of Degnin. The Degnin ore is magnetic and explosive, just the thing for shutting down force fields. Let's get that key from the catacombs, and then off to the mines for some ore.",TXT_ILOG89,,,,"Továrna je vedle dolů. Richter musí mít na mysli doly degninu. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole. Pojďme z katakomb dostat ten klíč a pak do dolů pro trochu rudy.","Fabrikken ligger ved siden af minerne. Richter må mene Degnin-minerne. Degnin malmen er magnetisk og eksplosiv, lige til at lukke kraftfelter ned med. Lad os hente nøglen fra katakomberne og så til minerne efter malm.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Dasa Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten. Lass uns den Schlüssel aus den Katakomben holen, und dann ab in die Minen für etwas Erz.",,,"La fábrica está junto a las minas. Richter debe referirse a las minas de Degnin. El mineral Degnin es magnético y explosivo, justo como para apagar campos de fuerza. Obtengamos esa llave de las catacumbas y luego derechos a las minas a por algo de mineral.",,"Tehdas on kaivoksen vieressä. Richter varmastikin tarkoittaa Degninin kaivosta. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä. Noudetaan avain katakombeista ja sitten matkataan kaivokselle hakemaan malmia.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. Récupérons la clé dans les catacombes, puis partons pour les mines pour récupérer du minerai.","A gyár a bánya mellett van. Richter valószínűleg Degnin bányáira gondolt. A degnini érc mágneses és robbanékony, pont tökéletes lesz az erőpajzs kiiktatásához. Menjünk és szerezzük meg azt a kulcsot a katakombákból, és aztán a bányába egy kis ércért.","La Fabbrica si trova accanto alle miniere. Richter starà parlando delle miniere di Degnin. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza. Prendiamo quella chiave dalle catacombe, e poi andiamo alle miniere a prendere un pò di quei minerali.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +以前に何処かで見た気がするけど?",브라보! 두 번째 시질 조각을 얻었어! 그나저나 비숍 몸에서 튀어나왔던 검은 물체 봤어? 전에 본 적이 있나? 오라클에게 돌아가자.,"Bravo, nog een stukje van de Sigil! Zag je dat rare spook dat uit het lichaam van de bisschop kwam? Waar heb ik dat eerder gezien? Laten we teruggaan naar het Orakel.","Bravo, enda en bit av sigillet! Så du det rare spøkelset som kom ut av biskopens kropp? Hvor har jeg sett det før? La oss gå tilbake til oraklet.","Brawo, kolejny kawałek Sigilu! Widziałeś to dziwne widmo, które wyszło z ciała biskupa? Gdzie ja to już widziałem? Wróćmy do Wyroczni.",Bravo! Outra peça do Sigilo! Você viu aquele espectro estranho que saiu do corpo do Bispo? Onde foi que eu já vi aquilo antes? Vamos voltar para o Oráculo.,,"Bravo, încă o bucată din Sigiliu! Ai văzut spectrul ciudat ce a ieșit din corpul Episcopului? Unde am mai văzut asta oare? Să ne întoarcem la Oracol.","Браво, ещё один фрагмент Печати! Видел тот странный фантом, вышедший из тела Епископа? Где я могла видеть такое раньше? Давай вернёмся к Оракулу.",,"Bravo, ännu en del av Sigillet! Såg du det konstiga spöket som kom ut ur biskopens kropp? Var har jag sett det förut? Låt oss gå tillbaka till oraklet.","Bravo, Sigil'in bir parçası daha! Piskopos'un bedeninden çıkan garip hayaleti gördün mü? Bunu daha önce nerede görmüştüm? Kahin'e geri dönelim." +"I have a report that the spectral energy we found near the Bishop is also present by the Oracle, let's be careful.",TXT_ILOG76,MAP11: After killing the Bishop and going to MAP12's entrance.,,,"Mám hlašení, že stejná přízračná energie, kterou jsme našli u Biskupa, se nachází také u Věštce, měli bychom být opatrní.","Jeg har en rapport om, at den spektrale energi, vi fandt nær biskoppen, også er til stede ved Oraklet, lad os være forsigtige.","Ich habe einen Report, dass die spektrale Energie, die wir beim Bischof vorfanden, auch in der Nähe des Orakels vorhanden ist. Wir sollten vorsichtig sein.",,"Laŭ informo, la fantoma energio trovita proksime de la Episkopo estas ankaŭ apud la Orakolo. Ni estu atentaj.",Tengo un informe de que la energía espectral que habíamos encontrado cerca del Obispo también está junto al Oráculo. Tengamos cuidado.,,"Sain tiedon, että aave-energiaa, jota löysimme Piispan läheltä, on läsnä myös Oraakkelin luona. Ollaan varovaisia.","Je recois un rapport que l'énergie spectrale qui possédait l'évêque se trouve aussi aux alentours de l'Oracle, fais attention.","Kaptam egy jelentést, hogy a Püspök körül érzékelt kísérteties energia észlelhető az Orákulum körül is. Vigyázzunk vele.","Ho qua un rapporto che ci informa che l'energia spettrale che abbiamo trovato vicino il Vescovo è anche presente vicino l'Oracolo, dobbiamo essere attenti.","ビショップにもあったスペクトラルエネルギーがオラクルにも宿っているという +報告があるわ、気を付けて。","지금 보고를 받았는데, 비숍을 죽인 뒤에 나온 혼령의 기운이 오라클에게도 있데. 조심하자.","Ik heb een bericht dat de spectrale energie die we in de buurt van de bisschop vonden ook aanwezig is bij het Orakel, laten we voorzichtig zijn.","Jeg har en rapport om at den spektrale energien vi fant nær biskopen også er til stede ved oraklet, la oss være forsiktige.","Mam raport, że energia widmowa, którą znaleźliśmy w pobliżu Bishopa, jest również obecna przy Wyroczni, bądźmy ostrożni.",Recebi um relatório de que a energia espectral que encontramos perto do Bispo também está presente pelo Oráculo. Precisamos tomar cuidado.,,"Am un raport care spune că energia spectrală a Episcopului a prezentă și în Oracol, s-avem grijă.","Мне доложили, что спектральная энергия, найденная нами возле Епископа, также исходит от Оракула. Будь начеку.",,"Jag har en rapport om att den spektrala energin som vi hittade nära biskopen också finns vid oraklet, låt oss vara försiktiga.","Piskoposun yanında bulduğumuz spektral enerjinin Kahin tarafından da mevcut olduğuna dair bir rapor aldım, dikkatli olalım." +Richter has taken over command of our forces. It looks like Macil has been deceiving us all along. His true allegiance was to the Order. What a snake. Let's get back to the Oracle.,TXT_ILOG79,MAP10: After killing Macil (Spectre) without having destroyed the converter in MAP24.,,,"Richter převzal velení našich sil. Zdá se, že nás Macil celou dobu klamal. Ve skutečnosti byl věrný Řádu. Slizák jeden. Vraťme se k Věštci.","Richter har overtaget kommandoen over vores styrker. Det ser ud til, at Macil har bedraget os hele tiden. Hans sande loyalitet var over for ordenen. Sikke en slange. Lad os gå tilbage til Oraklet.",Richter hat das Kommando über unsere Streitkräfte übernommen. Es scheint als hätte Macil uns die ganze Zeit über getäuscht. Sein wahre Loyalität gehörte dem Orden. Was für eine Ratte. Lass uns zum Orakel zurückkehren.,,"Rikter iĝis la nova frontestro. Ŝajnas, ke Macil trompis nin de la komenco: lia vera fidelo estis al La Ordeno. Kia serpento. Reiru al la Orakolo.",Richter ha tomado el mando del Frente. Parece que Macil nos ha estado engañando todo este tiempo: su verdadera lealtad era a La Orden. Menuda víbora. Volvamos con el Oráculo.,Richter tomó el mando del Frente. Parece que Macil nos ha estado engañando todo este tiempo: su verdadera lealtad era a La Orden. Tremenda víbora. Volvamos con el Oráculo.,"Richter on ottanut joukkomme komentoonsa. Näyttää siltä, että Macil on pettänyt meitä alusta alkaen. Hänen todellinen uskollisuutensa on ollut Veljeskunnalle; mikä käärme. Palataan Oraakkelin luokse.","Richter a pris le contrôle de nos forces. Il semble que Macil nous a menti tout du long. Sa vraie allégiance était avec l'Ordre, quel serpent! Retournous à l'Oracle.",Richter átvette az írányítást a csapataink fölött. Úgy tűnik Macil mindvégig megtévesztett minket. Valójában mindvégig a Rend oldalán volt. micsoda kígyó. Menjünk vissza az Orákulumhoz.,Richter ha assunto il comando delle nostre forze. Sembra che Macil ci avesse ingannato fin dall'inizio. In realtà è sempre stato alleato con l'Ordine. Che serpente. Ritorniamo dall'Oracolo.,"リヒターが指揮官の任を引き継いだ。マシルはずっと私達を騙していたなんて。 +あの人がオーダーに真の忠誠を誓っていたなんて、とんだ蛇神憑きだわ。",릭터가 저항군의 새로운 지도자가 될 거야. 내 생각엔 마실이 오랫동안 우리들을 속인 것 같아... 뱀 같은 자식. 오라클에게 돌아가자.,Richter heeft het bevel over onze troepen overgenomen. Het lijkt erop dat Macil ons al die tijd heeft bedrogen. Zijn ware trouw was aan de Orde. Wat een slang. Laten we teruggaan naar het Orakel.,Richter har overtatt kommandoen over styrkene våre. Det ser ut til at Macil har lurt oss hele tiden. Hans sanne lojalitet var til Ordenen. For en slange. La oss gå tilbake til orakelet.,"Richter przejął dowodzenie nad naszymi siłami. Wygląda na to, że Macil cały czas nas zwodził. Jego prawdziwa wierność była dla Zakonu. Co za wąż. Wracajmy do Wyroczni.",O Richter assumiu o comando de nossas forças. Parece que o Macil esteve nos enganando durante todo esse tempo. Sua verdadeira lealdade era à Ordem. Que traíra! Vamos voltar para o Oráculo.,,Richter a preluat controlul asupra forțelor noastre. Se pare că Macil ne-a mințit tot timpul. A fost loial cu adevărat doar Ordinului. Ce șarpe. Să ne întoarcem la Oracol.,"Рихтер принял на себя командование нашими силами. Похоже, что Мэйсил обманывал всех нас с самого начала. На самом деле он был предан Ордену. Подлец. Давай вернёмся к Оракулу.",,Richter har tagit över befälet över våra styrkor. Det verkar som om Macil har lurat oss hela tiden. Hans sanna lojalitet var till Orden. Vilken orm. Låt oss gå tillbaka till Oraklet.,Richter kuvvetlerimizin komutasını devraldı. Görünüşe göre Macil başından beri bizi kandırıyormuş. Gerçek bağlılığı Tarikat'a imiş. Ne yılan ama. Kahin'e geri dönelim. +Another Sigil piece. We are one step closer to freedom. And you are one step closer to me. Let's get back to the Oracle!,TXT_ILOG83,MAP27: After killing the Loremaster with either Macil or the Oracle alive.,,,Další díl Pečeti. Jsme o krok blíž ke svobodě. A ty jsi o krok blíž ke mě. Vraťme se k Věštci.,Endnu et Sigil-stykke. Vi er et skridt nærmere friheden. Og du er et skridt tættere på mig. Lad os komme tilbage til Oraklet!,Ein weiteres Teilstück des Sigils. Wir sind der Freiheit einen Schritt näher gekommen. Lass uns zurückgehen zum Orakel.,,Alia peco de la Sigelo. Ni estas unu paŝo pli proksime de la libereco... kaj ankaŭ vi de mi. Reiru al la Orakolo!,Otra pieza del Emblema. Estamos a un paso más cerca de la libertad... y también tú de mí. ¡Volvamos con el Oráculo!,,Jälleen uusi Sinetin osanen. Olemme taas askeleen lähempänä vapautta. Ja sinä askeleen lähempänä minua. Palataan Oraakkelin luo!,"Encore une pièce du Sigil. Nous nous rapprochons de la liberté, et tu te rapproche aussi de moi. Retournons à l'Oracle!",Még egy pecsét darab. Egy lépéssel közelebb állunk a szabadsághoz. Te pedig egy lépéssel közelebb vagy hozzám. menjünk vissza az orákulumhoz.,Un altro pezzo del Sigillo. Siamo ancora più vicini alla libertà. E tu sei ancora più vicino a me. Ritorniamo all'Oracolo!,"更なるシジルの欠片だ。私達の自由にまた一歩近づいたわ。 +そして私にも一歩近づいている。",또 다른 시질 조각이야. 자유로 향하는 길이 거의 얼마 남지 않았어. 그리고 나와 만날 순간도 얼마 남지 않았고. 오라클을 만나러 가자!,Nog een Sigil-peijsje. We zijn een stap dichter bij de vrijheid. En je bent een stap dichter bij mij. Laten we teruggaan naar het Orakel!,Enda en Sigil-brikke. Vi er ett skritt nærmere friheten. Og du er ett skritt nærmere meg. La oss gå tilbake til Orakelet!,Kolejny kawałek Sigil. Jesteśmy o krok bliżej wolności. A ty jesteś o krok bliżej mnie. Wracajmy do Wyroczni!,Outra peça do Sigilo. Estamos nos aproximando da liberdade. E você está ficando mais próximo de mim. Vamos voltar para o Oráculo!,,Altă piesă din Sigiliu. Suntem cu un pas mai aproape de libertate. Și tu ești cu un pas mai aproape de mne. Să ne întoarcem la Oracol.,Очередной фрагмент Печати. Теперь мы ещё на шаг ближе к освобождению. А ты — ещё на шаг ближе ко мне. Давай возвращаться к Оракулу!,,Ännu en Sigil-bit. Vi är ett steg närmare friheten. Och du är ett steg närmare mig. Låt oss gå tillbaka till Oraklet!,Başka bir Sigil parçası. Özgürlüğe bir adım daha yaklaştık. Ve sen de bana bir adım daha yaklaştın. Kahin'e geri dönelim! +You wield the power of the complete Sigil. What do you say we get some closure. Let's see what the Loremaster's been protecting.,TXT_ILOG85,MAP27/MAP12: Remark at TXT_SUB_LOG85,,,"Vládneš mocí složené Pečetě. Co říkáš na to, jít s tím vším skončit? Pojďme se podívat, co to Dějepisec bránil.","Du har magten af det komplette Sigil. Hvad siger du til, at vi får en afslutning? Lad os se, hvad Loremesteren har beskyttet.","Du hältst die Kraft des kompletten Sigils in deinen Händen. Meinst du nicht auch, wir sollten die Sache jetzt zu Ende bringen? Lass und nachsehen, was der Wissensmeister beschützt hat.",,"Vi tenas la povon de la tuta Sigelo. Kio pri fini ĉi tiun ĉapitron? Ni vidu tion, kion la Folkloristo kaŝadis.",Empuñas el poder del Emblema completo. ¿Que te parece ponerle un cierre a todo? Vamos a ver lo que el Maestro del Conocimiento se ha estado guardando.,,"Täyden Sinetin voima on hallussasi. Mitäpä jos hakisimme päätöstä. Katsotaan, mitä Oppi-Isä oikein on varjellut.",Tu as maintenant le plein pouvoir du Sigil. Je pense qu'il est l'heure d'en finir. Allons voir ce que le Maître des Traditions cachait.,"A kompett pecsét hatalma a kezedben van. Mit szólsz ahhoz, hogy lezárjuk végleg ezt a harcot. Nézzük meg mit is védelmez a Tanmester valójában.",Hai il potere del Sigillo completo. Che ne dici di finire questa storia. Vediamo un po' cosa il Sapiente stava proteggendo.,"貴方はもはや完全なシジルの力を行使できるわけね。 +後は言いがかりでもしてここを閉鎖させましょう。",시질의 완전한 힘은 이제 네 손에 있어. 종지부를 찍을 준비 됐어? 로어마스터가 그토록 지키던 게 무엇인지 확인하자고.,Je gebruikt de kracht van de volledige Sigil. Wat zeg je ervan als we de zaak afsluiten. Laten we eens kijken wat de Kennismeester heeft beschermd.,Du har makten til hele sigillet. Hva sier du til at vi får en avslutning? La oss se hva Loremaster har beskyttet.,"Władasz mocą kompletnego Sigilu. Co powiesz na to, żebyśmy się zamknęli. Zobaczmy, co Loremaster chronił.",Você tem o poder do Sigilo completo nas suas mãos. O que acha de termos um desfecho? Vamos ver o que o Mestre do Conhecimento andou protegendo.,,Ai puterea întregului Sigiliu. Ce zici dacă avem parte de un sfârșit. Să vedem ce poate prezice Maestrul Cunoștiințelor.,"Теперь ты владеешь мощью завершённой Печати. Мы уже близко — давай покончим с этим. Посмотрим, что же охранял Хранитель мудрости.",,Du har makten över hela Sigil. Vad sägs om att vi får ett avslut. Låt oss se vad Läromästaren har skyddat.,"Sigil'in tamamının gücüne sahipsin. Ne dersin, biraz kapanış yapalım mı? Loremaster'ın neyi koruduğunu görelim." +"Well, so much for prognostication. Hold it, Macil is calling us back. Let's get out of here in one piece.",TXT_ILOG87,MAP12: After killing the Oracle with Macil alive.,,,"No, tak to by bylo pro předpovědi. Počkej, Macil nás volá zpět. Vypadněme odsud vcelku.","Nå, så meget for prognoser. Vent, Macil kalder os tilbage. Lad os komme ud herfra i ét stykke.","Soviel zum Thema Vorhersagen. Warte, Macil ruft uns zurück. Lass uns hier heile herauskommen.",,"Nu, kia antaŭsento. Atendu, Macil vokas nin; ni eliru el ĉi tie senvundaj.","Vaya con los presentimientos. Momento, Macil nos está llamando; salgamos de aquí de una pieza.",,"No, se siitä ennustelusta. Odota, Macil kutsuu meitä takaisin. Häivytään täältä ehjin nahoin.","Bon, je pense que l'heure n'est plus au pronostics.. Attends, Macil nous appelle. Sortons d'ici en vie, si possible.","Hát, ennyit a jóslatról. Várj, Macil visszahív minket. Húzzunk innen míg egy darabban vagyunk.","Alla faccia dei prognostici... Aspetta, Macil ci sta richiamando. Meglio uscire da qua tutti interi.","まあ予言なんてそんなものでしょ。 +ちょっと待って、マシルが帰還するように言ったわ。ここから抜け出しましょう。","웃기네. 이딴 예언 따위. 잠깐만, 마실이 우리들을 부르고 있어. 이제 안전하게 기지로 돌아가자.","Nou, tot zover de prognose. Wacht even, Macil belt ons terug. Laten we hier heelhuids weggaan.","Så mye for spådommer. Vent, Macil kaller oss tilbake. La oss komme oss helskinnet ut herfra.","Cóż, to tyle jeśli chodzi o prognozowanie. Czekajcie, Macil nas wzywa. Wydostańmy się stąd w jednym kawałku.","Bem, acho que ainda não é hora de previsões. Espera, o Macil está nos chamando de volta. Vamos tentar sair daqui inteiros.",,"Atât a fost cu prognoza. Stai, Macil ne sună înapoi. Să ieșim de aici întregi.","Да, это превзошло все наши ожидания. Успокойся, Мэйсил вызывает нас назад. Давай выбираться отсюда.",,"Tja, så mycket för prognoser. Vänta, Macil kallar oss tillbaka. Låt oss komma härifrån i ett stycke.","Kehanet için çok fazla. Durun, Macil bizi geri çağırıyor. Buradan tek parça halinde çıkalım." +"The factory is next to the mines. Richter must mean the mines of Degnin. The Degnin ore is magnetic and explosive, just the thing for shutting down force fields. Let's get that key from the catacombs, and then off to the mines for some ore.",TXT_ILOG89,MAP23: After talking with Richter and leaving his room.,,,"Továrna je vedle dolů. Richter musí mít na mysli doly degninu. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole. Pojďme z katakomb dostat ten klíč a pak do dolů pro trochu rudy.","Fabrikken ligger ved siden af minerne. Richter må mene Degnin-minerne. Degnin malmen er magnetisk og eksplosiv, lige til at lukke kraftfelter ned med. Lad os hente nøglen fra katakomberne og så til minerne efter malm.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Dasa Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten. Lass uns den Schlüssel aus den Katakomben holen, und dann ab in die Minen für etwas Erz.",,"La fabriko estas apud la minejo de Degnin; ĝiaj minaĵoj estas magnetaj kaj eksplodpovaj, sufiĉe por detrui fortokampojn. Ni rekuperu tiun ŝlosilon en la katakombo kaj tiam ni serĉu tiajn minaĵojn en la minejo.","La fábrica está junto a la mina de Degnin; su mineral es magnético y explosivo, justo como para destruir campos de fuerza. A recuperar esa llave en las catacumbas y luego a la mina a buscar de ese mineral.",,"Tehdas on kaivoksen vieressä. Richter varmastikin tarkoittaa Degninin kaivosta. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä. Noudetaan avain katakombeista ja sitten matkataan kaivokselle hakemaan malmia.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. Récupérons la clé dans les catacombes, puis partons pour les mines pour récupérer du minerai.","A gyár a bánya mellett van. Richter valószínűleg Degnin bányáira gondolt. A degnini érc mágneses és robbanékony, pont tökéletes lesz az erőpajzs kiiktatásához. Menjünk és szerezzük meg azt a kulcsot a katakombákból, és aztán a bányába egy kis ércért.","La Fabbrica si trova accanto alle miniere. Richter starà parlando delle miniere di Degnin. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza. Prendiamo quella chiave dalle catacombe, e poi andiamo alle miniere a prendere un po' di quei minerali.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 デグニン石は綺麗だが可燃性で、フォースフィールドを消すにはうってつけよ。 -そこへのキーを地下墓所から取り、鉱山に向かおう。","공장은 광산 옆에 있어. 아마도 릭터는 데그닌 갱도를 예기한 것 같아. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 고대 무덤에서 그 열쇠를 얻고, 광석을 얻을 광산으로 향하자.","De fabriek ligt naast de mijnen. Richter moet de mijnen van Degnin bedoelen. Het Degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden. Laten we die sleutel uit de catacomben halen, en dan naar de mijnen gaan voor wat erts.","Fabrikken ligger ved siden av gruvene. Richter må mene gruvene i Degnin. Degnin-malmen er magnetisk og eksplosiv, akkurat det som skal til for å slå ut kraftfelt. La oss hente nøkkelen fra katakombene, og så dra til gruvene etter malm.","Fabryka jest obok kopalni. Richter musi mieć na myśli kopalnie w Degnin. Ruda Degnin jest magnetyczna i wybuchowa, w sam raz do wyłączania pól siłowych. Zdobądźmy ten klucz z katakumb, a potem ruszajmy do kopalni po rudę.","A fábrica fica próxima às minas. O Richter deve estar se referindo às minas de Degnin. O minério de Degnin é magnético e explosivo, o ideal para derrubar campos de força. Vamos pegar aquela chave das catacumbas e depois vamos para as minas pegar esse minério.",,"Fabrica e lângă mine, Richter se referă la minele din Degnin. Minereul de Degni e magnetic și exploziv, exact ceea ce ne trebuie pentru a opri câmpul de forță. Să luăm cheia aceea din catacombe și să ne îndreptăm înspre mine.","Вход на фабрику — рядом со спуском в шахты. Рихтер, должно быть, имел в виду шахты Дегнина. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Достань ключ из катакомб, а потом спустись в шахты за рудой.",,"Fabrika madenlerin yanında. Richter, Degnin madenlerini kastediyor olmalı. Degnin cevheri manyetik ve patlayıcıdır, tam da güç alanlarını kapatmak için. Hadi şu anahtarı yeraltı mezarlarından alalım, sonra da biraz cevher için madenlere gidelim." -"The factory is next to the mines. The Degnin ore is magnetic and explosive, just the thing for shutting down force fields. Let's get that key from the catacombs, and then we go down for some ore. This must be the ruins Richter's agents were searching for, be careful.",TXT_ILOG93,,,,"Továrna je vedle dolů. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole. Pojďme z katakomb dostat ten klíč a pak do dolů pro trochu rudy. Tohle musí být ty ruiny, které Richterovi agenti hledali, buď opatrný.","Fabrikken ligger ved siden af minerne. Degnin-malmen er magnetisk og eksplosiv og er lige til at lukke kraftfelter ned med. Lad os hente nøglen fra katakomberne, og så går vi ned efter noget malm. Dette må være ruinerne, som Richters agenter ledte efter, vær forsigtig.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Dasa Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten. Lass uns den Schlüssel aus den Katakomben holen, und dann ab in die Minen für etwas Erz. Dies müssen die Ruinen sein, die Richters Agenten gesucht haben. Sei vorsichtig.",,,"La fábrica está junto a las minas. El mineral Degnin es magnético y explosivo, justo vomo para apagar campos de fuerza. Obtengamos esa llave de las catacumbas y luego derechos a las minas a por algo de mineral. Estas deben de ser las ruínas que los agentes de Richter estaban buscando, ten cuidado.",,"Tehdas on kaivoksen vieressä. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä. Noudetaan avain katakombeista ja mennään sitten alas hakemaan malmia. Nämä ovat varmaankin ne rauniot, joita Richterin joukot olivat etsineet; ole varovainen.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. Récupérons la clé dans les catacombes, puis partons pour les mines pour récupérer du minerai. Cela doit être les ruines que les agent de Richter cherchaient. Fais attention.","A gyár a bánya mellett van. A degnini érc mágneses és robbanékony, pont tökéletes lesz az erőpajzs kiiktatásához. Menjünk és szerezzük meg azt a kulcsot a katakombákból, és aztán a bányába egy kis ércért. Valószínű, hogy ezek azok a romok, amelyeket Richter ügynökei kerestek, légy óvatos.","La Fabbrica si trova accanto alle miniere. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza. Prendiamo quella chiave dalle catacombe, e poi andiamo alle miniere a prendere un pò di quei minerali. Devono essere queste le rovine che gli agenti di Richter stavano esplorando, fai attenzione.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +そこへのキーを地下墓所から取り、鉱山に向かおう。","공장은 광산 옆에 있어. 아마도 릭터는 데그닌 갱도를 예기한 것 같아. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 고대 무덤에서 그 열쇠를 얻고, 광석을 얻을 광산으로 향하자.","De fabriek ligt naast de mijnen. Richter moet de mijnen van Degnin bedoelen. Het Degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden. Laten we die sleutel uit de catacomben halen, en dan naar de mijnen gaan voor wat erts.","Fabrikken ligger ved siden av gruvene. Richter må mene gruvene i Degnin. Degnin-malmen er magnetisk og eksplosiv, akkurat det som skal til for å slå ut kraftfelt. La oss hente nøkkelen fra katakombene, og så dra til gruvene etter malm.","Fabryka jest obok kopalni. Richter musi mieć na myśli kopalnie w Degnin. Ruda Degnin jest magnetyczna i wybuchowa, w sam raz do wyłączania pól siłowych. Zdobądźmy ten klucz z katakumb, a potem ruszajmy do kopalni po rudę.","A fábrica fica próxima às minas. O Richter deve estar se referindo às minas de Degnin. O minério de Degnin é magnético e explosivo, o ideal para derrubar campos de força. Vamos pegar aquela chave das catacumbas e depois vamos para as minas pegar esse minério.",,"Fabrica e lângă mine, Richter se referă la minele din Degnin. Minereul de Degni e magnetic și exploziv, exact ceea ce ne trebuie pentru a opri câmpul de forță. Să luăm cheia aceea din catacombe și să ne îndreptăm înspre mine.","Вход на фабрику — рядом со спуском в шахты. Рихтер, должно быть, имел в виду шахты Дегнина. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Достань ключ из катакомб, а потом спустись в шахты за рудой.",,"Fabriken ligger bredvid gruvorna. Richter måste mena Degnins gruvor. Degninmalmen är magnetisk och explosiv, precis vad man behöver för att stänga av kraftfält. Låt oss hämta nyckeln från katakomberna och sedan iväg till gruvorna för att hämta malm.","Fabrika madenlerin yanında. Richter, Degnin madenlerini kastediyor olmalı. Degnin cevheri manyetik ve patlayıcıdır, tam da güç alanlarını kapatmak için. Hadi şu anahtarı yeraltı mezarlarından alalım, sonra da biraz cevher için madenlere gidelim." +"The factory is next to the mines. The Degnin ore is magnetic and explosive, just the thing for shutting down force fields. Let's get that key from the catacombs, and then we go down for some ore. This must be the ruins Richter's agents were searching for, be careful.",TXT_ILOG93,MAP25: Entrance.,,,"Továrna je vedle dolů. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole. Pojďme z katakomb dostat ten klíč a pak do dolů pro trochu rudy. Tohle musí být ty ruiny, které Richterovi agenti hledali, buď opatrný.","Fabrikken ligger ved siden af minerne. Degnin-malmen er magnetisk og eksplosiv og er lige til at lukke kraftfelter ned med. Lad os hente nøglen fra katakomberne, og så går vi ned efter noget malm. Dette må være ruinerne, som Richters agenter ledte efter, vær forsigtig.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Dasa Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten. Lass uns den Schlüssel aus den Katakomben holen, und dann ab in die Minen für etwas Erz. Dies müssen die Ruinen sein, die Richters Agenten gesucht haben. Sei vorsichtig.",,"La fabriko estas apud la minejo de Degnin; ĝiaj minaĵoj estas magnetaj kaj eksplodpovaj, sufiĉe por detrui fortokampojn. Ĉi tiuj verŝajne estas la ruinoj, kie malaperis la agentoj de Rikter dum ili serĉis la ŝlosilon de la minejo.","La fábrica está junto a la mina de Degnin; su mineral es magnético y explosivo, justo como para destruir campos de fuerza. Estas deben de ser las ruinas donde los agentes de Richter han desaparecido al buscar al llave de la mina.","La fábrica está junto a la mina de Degnin; su mineral es magnético y explosivo, justo como para destruir campos de fuerza. Estas deben de ser las ruinas donde los agentes de Richter desaparecieron al buscar al llave de la mina.","Tehdas on kaivoksen vieressä. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä. Noudetaan avain katakombeista ja mennään sitten alas hakemaan malmia. Nämä ovat varmaankin ne rauniot, joita Richterin joukot olivat etsineet; ole varovainen.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. Récupérons la clé dans les catacombes, puis partons pour les mines pour récupérer du minerai. Cela doit être les ruines que les agent de Richter cherchaient. Fais attention.","A gyár a bánya mellett van. A degnini érc mágneses és robbanékony, pont tökéletes lesz az erőpajzs kiiktatásához. Menjünk és szerezzük meg azt a kulcsot a katakombákból, és aztán a bányába egy kis ércért. Valószínű, hogy ezek azok a romok, amelyeket Richter ügynökei kerestek, légy óvatos.","La Fabbrica si trova accanto alle miniere. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza. Prendiamo quella chiave dalle catacombe, e poi andiamo alle miniere a prendere un po' di quei minerali. Devono essere queste le rovine che gli agenti di Richter stavano esplorando, fai attenzione.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 デグニン石は綺麗だが可燃性で、フォースフィールドを消すにはうってつけよ。 そこへのキーを地下墓所から取り、鉱山に向かおう。 -ここがリヒターのエージェントが探していた遺跡のはず。気を付けて。",공장은 광산 옆에 있어. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 고대 묘지에 가서 열쇠를 얻고 광석을 좀 구하자. 릭터의 요원들이 정찰하다 사라진 폐허인 것 같아. 조심해.,"De fabriek is naast de mijnen. Het Degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden. Laten we die sleutel uit de catacomben halen, en dan gaan we naar beneden voor wat erts. Dit moeten de ruïnes zijn waar Richter's agenten naar op zoek waren, wees voorzichtig.","Fabrikken ligger ved siden av gruvene. Degnin-malmen er magnetisk og eksplosiv, akkurat tingen for å stenge ned kraftfelt. Vi henter nøkkelen i katakombene, og så går vi ned etter malm. Dette må være ruinene Richters agenter lette etter. Vær forsiktig.","Fabryka jest obok kopalni. Ruda Degnin jest magnetyczna i wybuchowa, idealna do wyłączania pól siłowych. Zdobądźmy ten klucz z katakumb, a potem zejdźmy na dół po rudę. To muszą być ruiny, których szukali agenci Richtera, bądźcie ostrożni.","A fábrica fica próxima às minas. O minério de Degnin é magnético e explosivo, o ideal para derrubar campos de força. Vamos pegar aquela chave das catacumbas e ir atrás desse minério. Essas devem ser as ruínas que os agentes do Richter estavam procurando. Tome cuidado.",,"Fabrica e lângă mine, Richter se referă la minele din Degnin. Minereul de Degni e magnetic și exploziv, exact ceea ce ne trebuie pentru a opri câmpul de forță. Să luăm cheia aceea din catacombe și să ne îndreptăm înspre mine.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Достань ключ в катакомбах, а потом спустись за рудой. Должно быть, именно эти руины искали агенты Рихтера. Будь осторожен.",,"Fabrika madenlerin yanında. Degnin cevheri manyetik ve patlayıcıdır, güç alanlarını kapatmak için birebirdir. Hadi şu anahtarı yeraltı mezarlarından alalım, sonra da biraz cevher için aşağı inelim. Burası Richter'in ajanlarının aradığı kalıntılar olmalı, dikkatli ol." -"The factory is next to the mines. The Degnin ore is magnetic and explosive, just the thing for shutting down force fields. My friend, whatever it is we're fighting, it's more than just the Order. Back to the commons then off to the mines. We need ore.",TXT_ILOG95,,,,"Továrna je vedle dolů. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole. Příteli, ať už bojujeme s čímkoliv, jde o víc než jen Řád. Zpátky na náves a pak do dolů. Potřebujeme rudu.","Fabrikken ligger ved siden af minerne. Degnin-malmen er magnetisk og eksplosiv, lige til at lukke kraftfelter ned med. Min ven, hvad det end er, vi kæmper imod, er det mere end bare Ordenen. Tilbage til fællesrummet og så til minerne. Vi har brug for malm.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Dasa Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten. Mein Freund, was immer wir hier bekämpfen, es ist mehr als der Orden. Zurück zur Mensa, und dann ab in die Minen. Wir brauchen Erz.",,,"La fábrica está junto a las minas. El mineral Degnin es magnético y explosivo, justo como para apagar campos de fuerza. Amigo, lo que sea contra lo que estamos luchando, es más que solo La Orden. Volvamos a los comunes y luego derechos a las minas. Necesitamos mineral.",,"Tehdas on kaivoksen vieressä. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä. Ystäväni, mitä vastaan me taistelemmekaan, se on suurempi kuin pelkkä Veljeskunta. Palatkaamme messiin, josta sitten kaivokseen. Tarvitsemme malmia.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. Mon ami, c'est clair que l'on se bat contre plus que juste l'Ordre. Retournons au réfectoire puis aux mines. Il nous faut du minerai.","A gyár a bánya mellett van. A degnini érc mágneses és robbanékony, pont tökéletes lesz az erőpajzs kiiktatásához. Barátom, akármi ellen is harcolunk, több mint a Rend maga. Irány vissza a menzára, aztán a bánya. Szükségünk van ércre.","La Fabbrica si trova accanto alle miniere. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza. Amico mio, qualsiasi cosa stiamo combattendo, è molto di più del solo Ordine. Ritorniamo ai comuni e poi alle miniere. Ci serve quel minerale.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +ここがリヒターのエージェントが探していた遺跡のはず。気を付けて。",공장은 광산 옆에 있어. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 고대 묘지에 가서 열쇠를 얻고 광석을 좀 구하자. 릭터의 요원들이 정찰하다 사라진 폐허인 것 같아. 조심해.,"De fabriek is naast de mijnen. Het Degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden. Laten we die sleutel uit de catacomben halen, en dan gaan we naar beneden voor wat erts. Dit moeten de ruïnes zijn waar Richter's agenten naar op zoek waren, wees voorzichtig.","Fabrikken ligger ved siden av gruvene. Degnin-malmen er magnetisk og eksplosiv, akkurat tingen for å stenge ned kraftfelt. Vi henter nøkkelen i katakombene, og så går vi ned etter malm. Dette må være ruinene Richters agenter lette etter. Vær forsiktig.","Fabryka jest obok kopalni. Ruda Degnin jest magnetyczna i wybuchowa, idealna do wyłączania pól siłowych. Zdobądźmy ten klucz z katakumb, a potem zejdźmy na dół po rudę. To muszą być ruiny, których szukali agenci Richtera, bądźcie ostrożni.","A fábrica fica próxima às minas. O minério de Degnin é magnético e explosivo, o ideal para derrubar campos de força. Vamos pegar aquela chave das catacumbas e ir atrás desse minério. Essas devem ser as ruínas que os agentes do Richter estavam procurando. Tome cuidado.",,"Fabrica e lângă mine, Richter se referă la minele din Degnin. Minereul de Degni e magnetic și exploziv, exact ceea ce ne trebuie pentru a opri câmpul de forță. Să luăm cheia aceea din catacombe și să ne îndreptăm înspre mine.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Достань ключ в катакомбах, а потом спустись за рудой. Должно быть, именно эти руины искали агенты Рихтера. Будь осторожен.",,"Fabriken ligger bredvid gruvorna. Degninmalmen är magnetisk och explosiv, precis vad man behöver för att stänga av kraftfält. Vi hämtar nyckeln från katakomberna och går sedan ner för att hämta malm. Detta måste vara ruinerna som Richters agenter sökte efter, var försiktig.","Fabrika madenlerin yanında. Degnin cevheri manyetik ve patlayıcıdır, güç alanlarını kapatmak için birebirdir. Hadi şu anahtarı yeraltı mezarlarından alalım, sonra da biraz cevher için aşağı inelim. Burası Richter'in ajanlarının aradığı kalıntılar olmalı, dikkatli ol." +"The factory is next to the mines. The Degnin ore is magnetic and explosive, just the thing for shutting down force fields. My friend, whatever it is we're fighting, it's more than just the Order. Back to the commons then off to the mines. We need ore.",TXT_ILOG95,MAP25: After killing the Spectre.,,,"Továrna je vedle dolů. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole. Příteli, ať už bojujeme s čímkoliv, jde o víc než jen Řád. Zpátky na náves a pak do dolů. Potřebujeme rudu.","Fabrikken ligger ved siden af minerne. Degnin-malmen er magnetisk og eksplosiv, lige til at lukke kraftfelter ned med. Min ven, hvad det end er, vi kæmper imod, er det mere end bare Ordenen. Tilbage til fællesrummet og så til minerne. Vi har brug for malm.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Dasa Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten. Mein Freund, was immer wir hier bekämpfen, es ist mehr als der Orden. Zurück zur Mensa, und dann ab in die Minen. Wir brauchen Erz.",,"Tio ajn, kion ni alfrontas, es pli ol La Ordeno. La fabriko estas apud la minejo de Degnin; ĝiaj minaĵoj estas magnetaj kaj eksplodpovaj, sufiĉe por detrui fortokampojn. Ni reiru al la komunumo kaj tiam ni serĉu tiajn minaĵojn en la minejo.","Lo que sea a los que nos enfrentamos es más que solo La Orden. La fábrica está junto a la mina de Degnin; su mineral es magnético y explosivo, justo como para destruir campos de fuerza. Volvamos a la comuna y luego a la mina a buscar de ese mineral.",,"Tehdas on kaivoksen vieressä. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä. Ystäväni, mitä vastaan me taistelemmekaan, se on suurempi kuin pelkkä Veljeskunta. Palatkaamme messiin, josta sitten kaivokseen. Tarvitsemme malmia.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. Mon ami, c'est clair que l'on se bat contre plus que juste l'Ordre. Retournons au réfectoire puis aux mines. Il nous faut du minerai.","A gyár a bánya mellett van. A degnini érc mágneses és robbanékony, pont tökéletes lesz az erőpajzs kiiktatásához. Barátom, akármi ellen is harcolunk, több mint a Rend maga. Irány vissza a menzára, aztán a bánya. Szükségünk van ércre.","La Fabbrica si trova accanto alle miniere. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza. Amico mio, qualsiasi cosa stiamo combattendo, è molto di più del solo Ordine. Ritorniamo ai comuni e poi alle miniere. Ci serve quel minerale.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 デグニン石は綺麗だが可燃性で、フォースフィールドを消すにはうってつけよ。 友よ、私達が戦う相手が何であろうとも、オーダー以上のものはない。 -鉱山から離れましょう!","공장은 광산 옆에 있어. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 싸우는 상대가 무엇인지는 모르겠지만, 오더보다 더한 존재인 것 같아. 식당가로 향한 뒤 광산으로 들어가. 광석이 필요하니까.","De fabriek ligt naast de mijnen. Het Degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden. Mijn vriend, wat het ook is waar we tegen vechten, het is meer dan alleen de Orde. Terug naar de commons en dan naar de mijnen. We hebben erts nodig.","Fabrikken ligger ved siden av gruvene. Degnin-malmen er magnetisk og eksplosiv, perfekt til å slå ut kraftfelt. Min venn, hva det enn er vi kjemper mot, er det mer enn bare Ordenen. Tilbake til allmenningen, og så til gruvene. Vi trenger malm.","Fabryka znajduje się obok kopalni. Ruda Degnin jest magnetyczna i wybuchowa. Nadaje się do wyłączania pól siłowych. Mój przyjacielu, cokolwiek to jest, z czym walczymy, to nie tylko Zakon. Wracamy do komnat, a potem do kopalni. Potrzebujemy rudy.","A fábrica fica próxima às minas. O minério de Degnin é magnético e explosivo, o ideal para derrubar campos de força. Meu amigo, seja lá o que estiver combatendo, é mais do que somente a Ordem. Volte ao refeitório e depois vá para as minas. Precisamos desse minério.",,"Fabrica e lângă mine, Richter se referă la minele din Degnin. Minereul de Degni e magnetic și exploziv, exact ceea ce ne trebuie pentru a opri câmpul de forță. Prietene, orice ar fi, ne luptăm cu ceva mai mult decât Ordinul. Înapoi la comune și dupaia, mine. Ne trebuie minereu.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Друг мой, с чем бы мы не сражались, это нечто большее, чем просто Орден. Вернись назад в поселение и спустись в шахты. Нам нужна руда.",,"Fabrika madenlerin yanında. Degnin cevheri manyetik ve patlayıcıdır, tam da güç alanlarını kapatmak için. Dostum, savaştığımız şey her neyse, Düzen'den daha fazlası. Avam kamarasına dönüp madenlere gidelim. Cevhere ihtiyacımız var." -"The factory is next to the mines. The degnin ore is magnetic and explosive, just the thing for shutting down force fields. Without letting down your guard, look for deposits of ore.",TXT_ILOG96,,,,"Továrna je vedle dolů. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole. Opatrně se podívej po ložiscích rudy.","Fabrikken ligger ved siden af minerne. Degninmalmen er magnetisk og eksplosiv, lige det rigtige til at lukke kraftfelter. Uden at sænke din vagt, skal du lede efter forekomster af malm.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Dasa Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten. Lass uns nach Erz suchen, aber wir müssen vorsichtig sein.",,,"La fábrica está junto a las minas. El mineral Degnin es magnético y explosivo, justo como para apagar campos de fuerza. Sin bajar la guardia, busca depósitos de mineral.",,"Tehdas on kaivoksen vieressä. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä. Etsi malmiesiintymiä varuillasi pysyen.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. Cherche des veines de minerai, mais fais attention.","A gyár a bánya mellett van. A degnini érc mágneses és robbanékony, pont tökéletes lesz az erőpajzs kiiktatásához. Figyelj az érc lerakódásokra, de közben figyelj magadra is.","La Fabbrica si trova accanto alle miniere. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza. Senza abbassare la guardia, cerca di trovare alcuni depositi di minerali.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +鉱山から離れましょう!","공장은 광산 옆에 있어. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 싸우는 상대가 무엇인지는 모르겠지만, 오더보다 더한 존재인 것 같아. 식당가로 향한 뒤 광산으로 들어가. 광석이 필요하니까.","De fabriek ligt naast de mijnen. Het Degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden. Mijn vriend, wat het ook is waar we tegen vechten, het is meer dan alleen de Orde. Terug naar de commons en dan naar de mijnen. We hebben erts nodig.","Fabrikken ligger ved siden av gruvene. Degnin-malmen er magnetisk og eksplosiv, perfekt til å slå ut kraftfelt. Min venn, hva det enn er vi kjemper mot, er det mer enn bare Ordenen. Tilbake til allmenningen, og så til gruvene. Vi trenger malm.","Fabryka znajduje się obok kopalni. Ruda Degnin jest magnetyczna i wybuchowa. Nadaje się do wyłączania pól siłowych. Mój przyjacielu, cokolwiek to jest, z czym walczymy, to nie tylko Zakon. Wracamy do komnat, a potem do kopalni. Potrzebujemy rudy.","A fábrica fica próxima às minas. O minério de Degnin é magnético e explosivo, o ideal para derrubar campos de força. Meu amigo, seja lá o que estiver combatendo, é mais do que somente a Ordem. Volte ao refeitório e depois vá para as minas. Precisamos desse minério.",,"Fabrica e lângă mine, Richter se referă la minele din Degnin. Minereul de Degni e magnetic și exploziv, exact ceea ce ne trebuie pentru a opri câmpul de forță. Prietene, orice ar fi, ne luptăm cu ceva mai mult decât Ordinul. Înapoi la comune și dupaia, mine. Ne trebuie minereu.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Друг мой, с чем бы мы не сражались, это нечто большее, чем просто Орден. Вернись назад в поселение и спустись в шахты. Нам нужна руда.",,"Fabriken ligger bredvid gruvorna. Degninmalmen är magnetisk och explosiv, precis vad man behöver för att stänga av kraftfält. Min vän, vad det än är vi slåss mot så är det mer än bara Orden. Tillbaka till allmänningen och sedan till gruvorna. Vi behöver malm.","Fabrika madenlerin yanında. Degnin cevheri manyetik ve patlayıcıdır, tam da güç alanlarını kapatmak için. Dostum, savaştığımız şey her neyse, Düzen'den daha fazlası. Avam kamarasına dönüp madenlere gidelim. Cevhere ihtiyacımız var." +"The factory is next to the mines. The degnin ore is magnetic and explosive, just the thing for shutting down force fields. Without letting down your guard, look for deposits of ore.",TXT_ILOG96,MAP14: Entrance.,,,"Továrna je vedle dolů. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole. Opatrně se podívej po ložiscích rudy.","Fabrikken ligger ved siden af minerne. Degninmalmen er magnetisk og eksplosiv, lige det rigtige til at lukke kraftfelter. Uden at sænke din vagt, skal du lede efter forekomster af malm.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Dasa Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten. Lass uns nach Erz suchen, aber wir müssen vorsichtig sein.",,"La fabriko estas apud la minejo de Degnin; ĝiaj minaĵoj estas magnetaj kaj eksplodpovaj, sufiĉe por detrui fortokampojn. Serĉu kolektojn de tiaj minaĵoj.","La fábrica está junto a la mina de Degnin; su mineral es magnético y explosivo, justo como para destruir campos de fuerza. Busca depósitos de ese mineral.",,"Tehdas on kaivoksen vieressä. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä. Etsi malmiesiintymiä varuillasi pysyen.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. Cherche des veines de minerai, mais fais attention.","A gyár a bánya mellett van. A degnini érc mágneses és robbanékony, pont tökéletes lesz az erőpajzs kiiktatásához. Figyelj az érc lerakódásokra, de közben figyelj magadra is.","La Fabbrica si trova accanto alle miniere. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza. Senza abbassare la guardia, cerca di trovare alcuni depositi di minerali.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 デグニン石は綺麗だが可燃性で、フォースフィールドを消すにはうってつけよ。 -警戒を緩めることなく、鉱石の堆積所を探しましょう。","공장은 광산 옆에 있어. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 자신을 지킬 준비 단단히 하고, 캔 광석을 두는 곳을 찾아.","De fabriek ligt naast de mijnen. Het degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden. Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen.","Fabrikken er ved siden av gruvene. Degnin-malmen er magnetisk og eksplosiv, akkurat det vi trenger for å slå ut kraftfeltene. Uten å senke guarden, se etter forekomster av malm.","Fabryka jest obok kopalni. Ruda degnin jest magnetyczna i wybuchowa, w sam raz do wyłączania pól siłowych. Nie tracąc czujności, szukajcie złóż rudy.","A fábrica fica próxima às minas. O minério de Degnin é magnético e explosivo, o ideal para derrubar campos de força. Não baixe a sua guarda e procure pelos depósitos de minério.",,"Fabrica e lângă mine. Minereul de Degnin e magnetic și exploziv, exact ceea ce ne trebuie pentru câmpul de forță. Fără a lăsa garda jos, uită-te după depozite de minereu.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Поищи залежи руды, но не теряй бдительности!",,"Fabrika madenlerin yanında. Degnin cevheri manyetik ve patlayıcıdır, tam da güç alanlarını kapatmak için. Gardınızı düşürmeden, cevher yataklarını arayın." -"Without letting down your guard, look for deposits of ore. These poor souls are drones. Their synaptic functions are being jammed by RC implants. We destroy the transmitter, and they're free.",TXT_ILOG97,,,,"Opatrně se podívej po ložiscích rudy. Tihle chudáci jsou trubcové, jejich synaptické funkce jsou narušené na dálku ovládanými implantáty. Když zničíme vysílačku, budou svobodní!","Uden at sænke paraderne, skal du lede efter malmforekomster. Disse stakkels sjæle er droner. Deres synaptiske funktioner bliver blokeret af RC-implantater. Vi ødelægger senderen, og så er de frie.","Lass uns nach Erz suchen, aber wir müssen vorsichtig sein. Diese armen Seelen sind wie Drohnen. Ihre Gehirnfunktionen werden von Implantaten blockiert. Wir müssen den Transmitter ausschalten, dann sind sie befreit.",,,"Sin bajar la guardia, busca depósitos de mineral. Estas pobres almas son zánganos. Sus funciones sinápticas están bloqueadas por implantes de control remoto. Destruimos el transmisor, y son libres.","Sin bajar la guardia, busca depósitos de mineral. Estas pobres almas son drones. Sus funciones sinápticas están siendo bloqueadas por implantes rc. Debemos destruir el transmisor y serán libres.","Etsi malmiesiintymiä, kuitenkin valppautesi säilyttäen. Nämä sieluparat ovat kuhnureita: Heidän synaptisia toimintojaan häiritään radio-ohjattavilla istutteilla. Me tuhoamme lähettimen, ja he ovat vapaat.","Cherche des veines de minerai, mais fais attention. Ces pauvres esclaves sont des drones. Leurs fonctions synaptiques sont brouillées par des implants radiocommandés. Détruisons le transmetteur pour les libérer.","Figyelj az érc lerakódásokra, de közben figyelj magadra is. Ezek a szerencsétlen lelkek csak drónok. A szinaptikus funkcióikat zavarják távolról irányítható implantátumokkal. Szétromboljuk a jeladókat, és szabaddá vállnak.","Senza abbassare la guardia, cerca di trovare alcuni depositi di minerali. Questi poveracci sono dei droni. Le loro funzioni cerebrali stanno venendo bloccate da degli impianti. Se distruggiamo il trasmettitore, saranno liberi.","警戒を緩めることなく、鉱石の堆積所を探しましょう。 +警戒を緩めることなく、鉱石の堆積所を探しましょう。","공장은 광산 옆에 있어. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 자신을 지킬 준비 단단히 하고, 캔 광석을 두는 곳을 찾아.","De fabriek ligt naast de mijnen. Het degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden. Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen.","Fabrikken er ved siden av gruvene. Degnin-malmen er magnetisk og eksplosiv, akkurat det vi trenger for å slå ut kraftfeltene. Uten å senke guarden, se etter forekomster av malm.","Fabryka jest obok kopalni. Ruda degnin jest magnetyczna i wybuchowa, w sam raz do wyłączania pól siłowych. Nie tracąc czujności, szukajcie złóż rudy.","A fábrica fica próxima às minas. O minério de Degnin é magnético e explosivo, o ideal para derrubar campos de força. Não baixe a sua guarda e procure pelos depósitos de minério.",,"Fabrica e lângă mine. Minereul de Degnin e magnetic și exploziv, exact ceea ce ne trebuie pentru câmpul de forță. Fără a lăsa garda jos, uită-te după depozite de minereu.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Поищи залежи руды, но не теряй бдительности!",,"Fabriken ligger bredvid gruvorna. Degninmalmen är magnetisk och explosiv, precis vad vi behöver för att stänga av kraftfält. Utan att sänka garden, leta efter malmfyndigheter.","Fabrika madenlerin yanında. Degnin cevheri manyetik ve patlayıcıdır, tam da güç alanlarını kapatmak için. Gardınızı düşürmeden, cevher yataklarını arayın." +"Without letting down your guard, look for deposits of ore. These poor souls are drones. Their synaptic functions are being jammed by RC implants. We destroy the transmitter, and they're free.",TXT_ILOG97,"MAP14: After crossing the entrance yard. +(drone ≈ slave)",,,"Opatrně se podívej po ložiscích rudy. Tihle chudáci jsou trubcové, jejich synaptické funkce jsou narušené na dálku ovládanými implantáty. Když zničíme vysílačku, budou svobodní!","Uden at sænke paraderne, skal du lede efter malmforekomster. Disse stakkels sjæle er droner. Deres synaptiske funktioner bliver blokeret af RC-implantater. Vi ødelægger senderen, og så er de frie.","Lass uns nach Erz suchen, aber wir müssen vorsichtig sein. Diese armen Seelen sind wie Drohnen. Ihre Gehirnfunktionen werden von Implantaten blockiert. Wir müssen den Transmitter ausschalten, dann sind sie befreit.",,Serĉu kolektojn de degninaj minaĵoj. Estas sklavigitaj elfosantoj kun siaj sinapsoj barataj de teleregataj enplantaĵoj. Detrui la transmisiilon liberigos ilin.,Busca depósitos del mineral de Degnin. Hay mineros esclavizados con sus funciones sinápticas bloqueadas con implantes por mando a distancia. Destruir el transmisor los liberará.,Busca depósitos del mineral de Degnin. Hay mineros esclavizados con sus funciones sinápticas bloqueadas con implantes a control remoto. Destruir el transmisor los va a liberar.,"Etsi malmiesiintymiä, kuitenkin valppautesi säilyttäen. Nämä sieluparat ovat kuhnureita: Heidän synaptisia toimintojaan häiritään radio-ohjattavilla istutteilla. Me tuhoamme lähettimen, ja he ovat vapaat.","Cherche des veines de minerai, mais fais attention. Ces pauvres esclaves sont des drones. Leurs fonctions synaptiques sont brouillées par des implants radiocommandés. Détruisons le transmetteur pour les libérer.","Figyelj az érc lerakódásokra, de közben figyelj magadra is. Ezek a szerencsétlen lelkek csak drónok. A szinaptikus funkcióikat zavarják távolról irányítható implantátumokkal. Szétromboljuk a jeladókat, és szabaddá vállnak.","Senza abbassare la guardia, cerca di trovare alcuni depositi di minerali. Questi poveracci sono degli schiavi. Le loro funzioni cerebrali stanno venendo bloccate da degli impianti. Se distruggiamo il trasmettitore, saranno liberi.","警戒を緩めることなく、鉱石の堆積所を探しましょう。 ここの精神の乏しい労働者達は、RCインプラントでシナプス機能を妨害している。 -私達が送信機を破壊し、皆を解放しよう。","자신을 지킬 준비 단단히 하고, 캔 광석을 두는 곳을 찾아. 저 사람들은 불쌍한 광산의 노예들이야. 오더가 이식한 세뇌 장치 때문에 정상적인 뇌 기능을 잃었지. 전송기만 파괴한다면, 그들은 자유를 되찾을 수 있을 거야.","Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen. Deze arme zielen zijn drones. Hun synaptische functies worden geblokkeerd door RC-implantaten. We vernietigen de zender en ze zijn vrij.","Uten å senke guarden, se etter malmforekomster. Disse stakkarene er droner. Deres synaptiske funksjoner blokkeres av RC-implantater. Vi ødelegger senderen, og de er fri.","Nie opuszczając gardy, szukaj złóż rudy. Te biedne dusze to drony. Ich funkcje synaptyczne są zagłuszane przez implanty RC. Zniszczymy nadajnik, a oni będą wolni.",Não baixe a sua guarda e procure por depósitos de minério. Esses pobres coitados são zangões. Suas funções sinápticas estão sendo bloqueadas por implantes de controle remoto. Se destruirmos o transmissor eles estarão livres.,,"Fără a lăsa garda jos, uită-te după minereu. Sufletele ăstea sărmane sunt drone. Funcțiile lor sinaptice primesc interferență de la implanturile RC. Distrugem transmițătoarele și sunt libere.","Поищи залежи руды, но не теряй бдительности. Эти несчастные души — дроны. Сигнал, поступающий на импланты, полностью подавляет их сознание. Если мы уничтожим передатчик, они свободны.",,"Gardınızı düşürmeden, cevher yataklarını arayın. Bu zavallı ruhlar dron. Sinaptik fonksiyonları RC implantları tarafından engelleniyor. Vericiyi yok edersek özgür kalırlar." -"The factory is next to the mines. Without letting down your guard, look for deposits of ore. My suggestion is, toss the ore at the force field and then blast it, the resulting compression should create a magnetic blanket and turn off the lights.",TXT_ILOG99,,,,"Továrna je vedle dolů. Opatrně se podívej po ložiscích rudy. Můj návrh je, hoď rudu na to silové pole a pak ji odstřel. Výsledná komprese by měla vytvořit magnetický povlak a vypnout pole.","Fabrikken ligger ved siden af minerne. Uden at sænke din vagt, skal du lede efter malmforekomster. Mit forslag er, at kaste malmen mod kraftfeltet og derefter sprænge det, den resulterende kompression skulle skabe et magnetisk tæppe og slukke lyset.","Die Fabrik liegt neben den Minen. Lass uns nach Erz suchen, aber wir müssen vorsichtig sein. Ich schlage vor, wir werfen das Erz vor das Krsftfeld und sprengen es dann. Die Druckwelle sollte einen Magnetpuls erzeugen, und die Lichter ausschalten.",,,"La fábrica está junto a las minas. Sin bajar la guardia, busca depósitos de mineral. Mi sugerencia es tirar el mineral hacia el campo de fuerza y luego reventarlo; la presión resultante debería crear un manto magnético y apagar las luces.",,"Tehdas on kaivoksen vieressä. Etsi malmiesiintymiä, kuitenkin valppautesi säilyttäen. Ehdotukseni on, että heität malmin voimakentään ja sitten posautat sen. Syntyvän paineaallon pitäisi muodostaa magneettinen peitto ja sammuttaa valot.","L'usine est près des mines. Cherche des veines de minerai, mais fais attention. Je suggère que tu lance du minerai sur le champ de force et que tu tire dessus. Le champ magnétique que l'explosion causera désactivera les lumières.","A gyár a bánya mellett van. Figyelj az érc lerakódásokra, de közben figyelj magadra is. Azt javaslom, hogy dobd az ércet az erőpajzsra, és robbantsd fel. A robbanástól létrejött kompresszió létre kell hogy hozzon egy mágneses palástot, és ezáltal kikapcsolja a lámpákat.","La Fabbrica si trova accanto alle miniere. Senza abbassare la guardia, cerca di trovare alcuni depositi di minerali. Il mio consiglio è, lancia uno dei minerali al campo di forza e poi fallo saltare in aria. Questo dovrebbe sprigionare l'energia sufficiente a disattivare il campo di forza.","工場は鉱山の隣にあるわ。警戒を緩めることなく、鉱石の堆積所を探しましょう。 +私達が送信機を破壊し、皆を解放しよう。","자신을 지킬 준비 단단히 하고, 캔 광석을 두는 곳을 찾아. 저 사람들은 불쌍한 광산의 노예들이야. 오더가 이식한 세뇌 장치 때문에 정상적인 뇌 기능을 잃었지. 전송기만 파괴한다면, 그들은 자유를 되찾을 수 있을 거야.","Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen. Deze arme zielen zijn drones. Hun synaptische functies worden geblokkeerd door RC-implantaten. We vernietigen de zender en ze zijn vrij.","Uten å senke guarden, se etter malmforekomster. Disse stakkarene er droner. Deres synaptiske funksjoner blokkeres av RC-implantater. Vi ødelegger senderen, og de er fri.","Nie opuszczając gardy, szukaj złóż rudy. Te biedne dusze to drony. Ich funkcje synaptyczne są zagłuszane przez implanty RC. Zniszczymy nadajnik, a oni będą wolni.",Não baixe a sua guarda e procure por depósitos de minério. Esses pobres coitados são escravos. Suas funções sinápticas estão sendo bloqueadas por implantes de controle remoto. Se destruirmos o transmissor eles estarão livres.,,"Fără a lăsa garda jos, uită-te după minereu. Sufletele ăstea sărmane sunt drone. Funcțiile lor sinaptice primesc interferență de la implanturile RC. Distrugem transmițătoarele și sunt libere.","Поищи залежи руды, но не теряй бдительности. Эти несчастные души — дроны. Сигнал, поступающий на импланты, полностью подавляет их сознание. Если мы уничтожим передатчик, они свободны.",,Utan att sänka garden letar du efter malmfyndigheter. Dessa stackars själar är drönare. Deras synaptiska funktioner blockeras av RC-implantat. Vi förstör sändaren och de är fria.,"Gardınızı düşürmeden, cevher yataklarını arayın. Bu zavallı ruhlar dron. Sinaptik fonksiyonları RC implantları tarafından engelleniyor. Vericiyi yok edersek özgür kalırlar." +"The factory is next to the mines. Without letting down your guard, look for deposits of ore. My suggestion is, toss the ore at the force field and then blast it, the resulting compression should create a magnetic blanket and turn off the lights.",TXT_ILOG99,MAP14: After James's room.,,,"Továrna je vedle dolů. Opatrně se podívej po ložiscích rudy. Můj návrh je, hoď rudu na to silové pole a pak ji odstřel. Výsledná komprese by měla vytvořit magnetický povlak a vypnout pole.","Fabrikken ligger ved siden af minerne. Uden at sænke din vagt, skal du lede efter malmforekomster. Mit forslag er, at kaste malmen mod kraftfeltet og derefter sprænge det, den resulterende kompression skulle skabe et magnetisk tæppe og slukke lyset.","Die Fabrik liegt neben den Minen. Lass uns nach Erz suchen, aber wir müssen vorsichtig sein. Ich schlage vor, wir werfen das Erz vor das Krsftfeld und sprengen es dann. Die Druckwelle sollte einen Magnetpuls erzeugen, und die Lichter ausschalten.",,Serĉu kolektojn de degninaj minaĵoj. Mi sugestus meti minaĵon ĉe la fortokampo kaj tiam pafi al ĝi: la rezultinta premo devus krei magnetan kampon kaj malŝalti ĝin.,Busca depósitos del mineral de Degnin. Yo diría de poner un mineral junto al campo de fuerza y luego dispararle: la presión resultante debería crear un campo magnético que lo desactive.,,"Tehdas on kaivoksen vieressä. Etsi malmiesiintymiä, kuitenkin valppautesi säilyttäen. Ehdotukseni on, että heität malmin voimakentään ja sitten posautat sen. Syntyvän paineaallon pitäisi muodostaa magneettinen peitto ja sammuttaa valot.","L'usine est près des mines. Cherche des veines de minerai, mais fais attention. Je suggère que tu lance du minerai sur le champ de force et que tu tire dessus. Le champ magnétique que l'explosion causera désactivera les lumières.","A gyár a bánya mellett van. Figyelj az érc lerakódásokra, de közben figyelj magadra is. Azt javaslom, hogy dobd az ércet az erőpajzsra, és robbantsd fel. A robbanástól létrejött kompresszió létre kell hogy hozzon egy mágneses palástot, és ezáltal kikapcsolja a lámpákat.","La Fabbrica si trova accanto alle miniere. Senza abbassare la guardia, cerca di trovare alcuni depositi di minerali. Il mio consiglio è, lancia uno dei minerali al campo di forza e poi fallo saltare in aria. Questo dovrebbe sprigionare l'energia sufficiente a disattivare il campo di forza.","工場は鉱山の隣にあるわ。警戒を緩めることなく、鉱石の堆積所を探しましょう。 私の案はフォースフィールドの近くに鉱石を置き撃って爆発させる方法よ。 -その結果、圧縮されていた磁場の反動で光を打ち消すわ。","공장은 광산 옆에 있어. 자신을 지킬 준비 단단히 하고, 캔 광석을 두는 곳을 찾아. 조언을 찾는다면, 광석을 방어막에 가까이 놔둔 뒤 쏴봐. 광석이 커다란 자기장을 만들 테고, 방어막을 완전히 무력화 시킬 거야.","De fabriek ligt naast de mijnen. Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen. Mijn suggestie is om het erts naar het krachtveld te gooien en het vervolgens op te blazen, de resulterende compressie zou een magnetische deken moeten creëren en de lichten uit moeten doen.","Fabrikken ligger ved siden av gruvene. Uten å senke garden, se etter malmforekomster. Mitt forslag er å kaste malmen mot kraftfeltet og deretter sprenge den, den resulterende kompresjonen bør skape et magnetisk teppe og slå av lysene.","Fabryka jest obok kopalni. Nie spuszczając gardy, szukajcie złóż rudy. Moja propozycja to, podrzuć rudę na pole siłowe, a następnie wysadź je, powstała kompresja powinna stworzyć koc magnetyczny i wyłączyć światła.",A fábrica fica próxima às minas. Não baixe a sua guarda e procure pelos depósitos de minério. Sugiro que você arremesse o minério ao campo de força e detone ele. A explosão deve gerar um campo magnético que vai apagar as luzes.,,"Fabrica e lăngă mine. Fără a lăsa garda jos uită-te dupa depozite de minereu. Sugestia mea e, aruncă minereul la câmpul de forță și aruncă-l în aer, comprimarea ce va rezulta în urma ei ar trebui să creeze o încărcătură magnetică care va distruge luminile.","Вход на фабрику — рядом со спуском в шахты. Поищи залежи руды, но не теряй бдительности. Мой план: бросить руду поближе к силовому полю и взорвать её. Взрыв создаст магнитное поле, которое накроет электронику и отрубит её.",,"Fabrika madenlerin yanında. Gardınızı düşürmeden, cevher yataklarını arayın. Benim önerim, cevheri güç alanına fırlatın ve sonra patlatın, ortaya çıkan sıkıştırma manyetik bir örtü oluşturmalı ve ışıkları kapatmalıdır." -Now on to the factory. Exit the mines and you can't miss it. Let's find that machine and shut it down!,TXT_ILOG100,,,,A teď do továrny. Vyjdi z dolů a nemůžeš to minout. Pojďme najít ten stroj a vypnout ho!,"Nu videre til fabrikken. Forlad minerne, og du kan ikke undgå at se den. Lad os finde den maskine og lukke den ned!","Und jetzt zur Fabrik. Verlasse die Minen, du kannst sie nicht verpassen. Lass uns die Maschine finden und abschalten.",,,Ahora vamos a la fábrica. Sal de las minas y no puedes perderlo. ¡Encontremos esa máquina y desactivémosla!,,"Nyt sitten tehtaaseen. Poistu kaivoksesta, ja löydät sen varmasti. Etsitään ja sammutetaan se kone!","C'est parti pour l'usine. Sors des mines, tu ne peux pas la rater. Trouvons cette machine et détruisons-la!","Most pedig a gyár. Rögtön szembe van veled ahogy kilépsz a bányából, nem tudod eltéveszteni. Keressük meg azt a gépet, és állítsuk le!",Ora entriamo nella Fabbrica. Uscendo dalle miniere non puoi sbagliare. Troviamo quella macchina e disattiviamola!,"工場へ今すぐ入ろう。鉱山の出口はすぐわかる。 -機械を探してシャットダウンさせろ!",이제 공장으로 향하자. 광산을 나가봐. 이 순간을 놓치면 안 돼. 얼른 그 기계를 찾아서 작동을 멈추자!,Nu naar de fabriek. Verlaat de mijnen en je kunt het niet missen. Laten we die machine vinden en hem uitschakelen!,"Nå videre til fabrikken. Gå ut av gruvene, og du kan ikke gå glipp av den. La oss finne den maskinen og slå den av!",Teraz przejdź do fabryki. Wyjdź z kopalni i nie możesz jej przegapić. Znajdźmy tę maszynę i wyłączmy ją!,"Agora vá para a fábrica. Ao sair das minas você vai encontrá-la, não tem como errar. Vamos achar essa máquina e desligá-la de vez!",,"Acum înspre fabrică. Ieși din mine, nu o poți rata. Să găsim mașina aia și să o oprim!","Теперь — на фабрику. Выйди из шахты, и ты сразу увидишь вход. Найди эту машину и останови её!",,Şimdi fabrikaya gidelim. Madenlerden çıkın ve onu kaçırmayın. Hadi şu makineyi bulup kapatalım! -I'm reading massive neural wave distortions from straight ahead. I think we've found it. Let's get in there and shut it down!,TXT_ILOG102,,,,"Detekuju obří rušení nervových vln přímo před námi. Myslím, že jsme to našli. Pojďme tam a vypněme to!","Jeg kan se massive neurale bølgeforvrængninger lige forude. Jeg tror, vi har fundet den. Lad os komme ind og lukke den ned!","Ich empfange massive neurale Verzerrungen direkt voraus. Ich denke, wir haben sie gefunden. Lass uns reingehen und sie abschalten.",,,Estoy leyendo distorsiones de ondas neuronales masivas adelante. Creo que la hemos encontrado. ¡Entremos ahí y destruyámosla!,,Havaitsen massivisia hermoaaltovääristymiä suoraan edessä. Luulen löytäneemme sen. Mennään sisään ja sammutetaan se!,Je recois des distorsions neurales colossales devant nous. Je crois que nous l'avons trouvé. Détruisons-la!,Erős ideghullám zavaró jeleket fogok. Azt hiszem megtaláltuk. Menjünk be és állítsuk le!,Sto ricevendo potenti segnali distorti proprio davanti a te. Penso che l'abbiamo trovata. Entriamo e spegnamo questa macchina!,重い神経波歪曲が直に届いたわ。私達はそれを見つけたという事よ。,앞쪽에서 거대한 신경교란 파장이 감지되고 있어. 우리가 찾아낸 것 같아. 어서 들어가서 꺼버리자!,Ik lees enorme neurale golfvervormingen van rechtdoor. Ik denk dat we hem gevonden hebben. Laten we naar binnen gaan en de machine stilleggen!,Jeg leser massive nevrale bølgeforvrengninger rett fram. Jeg tror vi har funnet den. La oss gå inn og slå den av!,Odczytuję potężne zniekształcenia fal neuronowych z prostej drogi. Chyba ją znaleźliśmy. Wejdźmy tam i wyłączmy ją!,Estou vendo distorções enormes de ondas neurais. Acho que encontramos. Vamos entrar lá e desligar!,,"Citesc distorsiune neurale masive drept din față, cred că am găsit-o. Să intrăm și să o oprim.","Я вижу мощный источник помех прямо по курсу. Похоже, мы нашли конвертер. Войди и останови его!",,Tam karşıdan büyük sinir dalgası bozulmaları okuyorum. Sanırım onu bulduk. Oraya girelim ve onu kapatalım! -Just when I think we've seen it all! They go in human and come out... I dont even want to think about it. Destroy this horror!,TXT_ILOG103,,,,"Zrovna, když jsem myslela, že jsme to všechno viděli! Dovnitř jdou jako lidé a vyjdou... ani na to nechci myslet. Znič tu hrůzu!","Lige når jeg tror, vi har set det hele! De går ind i et menneske og kommer ud... Jeg vil ikke engang tænke på det. Ødelæg denne rædsel!","Und da denkt man, man hätte schon alles gesehen. Die kommen als Menschen rein und kommen raus als... Ich möchte gar nicht drüber nachdenken. Zerstöre diesen Horror.",,,¡Justo cuando creía haberlo visto todo! Entran humanos y salen... No quiero ni pensarlo. ¡Destruye este horror!,,Juuri kun luulen nähneemme kaiken! He menevät sisään ihmisinä ja tulevat ulos... En halua edes ajatellakaan sitä. Tuhoa tämä kauhistus!,"Et quand je pense avoir tout vu.. Des humains entrent, et puis.. Non, je ne veux pas y penser. Détruis cette horreur!","Amikor azt hittem, hogy mindent láttunk. Emberként mennek be, és úgy jönnek ki mint egy...nem is akarok rá gondolni. Semmisítsd meg ezt a horrort!",E io che pensavo di averle viste tutte! Entrano umani ed escono fuori... Non ci voglio neanche pensare. Distruggi questo orrore!,"今まで見てきたことについて考えている! +その結果、圧縮されていた磁場の反動で光を打ち消すわ。","공장은 광산 옆에 있어. 자신을 지킬 준비 단단히 하고, 캔 광석을 두는 곳을 찾아. 조언을 찾는다면, 광석을 방어막에 가까이 놔둔 뒤 쏴봐. 광석이 커다란 자기장을 만들 테고, 방어막을 완전히 무력화 시킬 거야.","De fabriek ligt naast de mijnen. Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen. Mijn suggestie is om het erts naar het krachtveld te gooien en het vervolgens op te blazen, de resulterende compressie zou een magnetische deken moeten creëren en de lichten uit moeten doen.","Fabrikken ligger ved siden av gruvene. Uten å senke garden, se etter malmforekomster. Mitt forslag er å kaste malmen mot kraftfeltet og deretter sprenge den, den resulterende kompresjonen bør skape et magnetisk teppe og slå av lysene.","Fabryka jest obok kopalni. Nie spuszczając gardy, szukajcie złóż rudy. Moja propozycja to, podrzuć rudę na pole siłowe, a następnie wysadź je, powstała kompresja powinna stworzyć koc magnetyczny i wyłączyć światła.",A fábrica fica próxima às minas. Não baixe a sua guarda e procure pelos depósitos de minério. Sugiro que você arremesse o minério ao campo de força e detone ele. A explosão deve gerar um campo magnético que vai apagar as luzes.,,"Fabrica e lăngă mine. Fără a lăsa garda jos uită-te dupa depozite de minereu. Sugestia mea e, aruncă minereul la câmpul de forță și aruncă-l în aer, comprimarea ce va rezulta în urma ei ar trebui să creeze o încărcătură magnetică care va distruge luminile.","Вход на фабрику — рядом со спуском в шахты. Поищи залежи руды, но не теряй бдительности. Мой план: бросить руду поближе к силовому полю и взорвать её. Взрыв создаст магнитное поле, которое накроет электронику и отрубит её.",,"Fabriken ligger bredvid gruvorna. Utan att sänka garden, leta efter malmfyndigheter. Mitt förslag är att kasta malmen mot kraftfältet och sedan spränga det, den resulterande kompressionen bör skapa en magnetisk filt och släcka ljuset.","Fabrika madenlerin yanında. Gardınızı düşürmeden, cevher yataklarını arayın. Benim önerim, cevheri güç alanına fırlatın ve sonra patlatın, ortaya çıkan sıkıştırma manyetik bir örtü oluşturmalı ve ışıkları kapatmalıdır." +Now on to the factory. Exit the mines and you can't miss it. Let's find that machine and shut it down!,TXT_ILOG100,MAP14: After destroying the transmitter.,,,A teď do továrny. Vyjdi z dolů a nemůžeš to minout. Pojďme najít ten stroj a vypnout ho!,"Nu videre til fabrikken. Forlad minerne, og du kan ikke undgå at se den. Lad os finde den maskine og lukke den ned!","Und jetzt zur Fabrik. Verlasse die Minen, du kannst sie nicht verpassen. Lass uns die Maschine finden und abschalten.",,"Nun al la fabriko, tuj tra la elirejo de la minejo. Trovu kaj malŝaltu tiun maŝinon!","Ahora a la fábrica, justo saliendo de la mina. ¡Encontremos esa máquina y apaguémosla!",,"Nyt sitten tehtaaseen. Poistu kaivoksesta, ja löydät sen varmasti. Etsitään ja sammutetaan se kone!","C'est parti pour l'usine. Sors des mines, tu ne peux pas la rater. Trouvons cette machine et détruisons-la!","Most pedig a gyár. Rögtön szembe van veled ahogy kilépsz a bányából, nem tudod eltéveszteni. Keressük meg azt a gépet, és állítsuk le!",Ora entriamo nella Fabbrica. Uscendo dalle miniere non puoi sbagliare. Troviamo quella macchina e disattiviamola!,"工場へ今すぐ入ろう。鉱山の出口はすぐわかる。 +機械を探してシャットダウンさせろ!",이제 공장으로 향하자. 광산을 나가봐. 이 순간을 놓치면 안 돼. 얼른 그 기계를 찾아서 작동을 멈추자!,Nu naar de fabriek. Verlaat de mijnen en je kunt het niet missen. Laten we die machine vinden en hem uitschakelen!,"Nå videre til fabrikken. Gå ut av gruvene, og du kan ikke gå glipp av den. La oss finne den maskinen og slå den av!",Teraz przejdź do fabryki. Wyjdź z kopalni i nie możesz jej przegapić. Znajdźmy tę maszynę i wyłączmy ją!,"Agora vá para a fábrica. Ao sair das minas você vai encontrá-la, não tem como errar. Vamos achar essa máquina e desligá-la de vez!",,"Acum înspre fabrică. Ieși din mine, nu o poți rata. Să găsim mașina aia și să o oprim!","Теперь — на фабрику. Выйди из шахты, и ты сразу увидишь вход. Найди эту машину и останови её!",,Nu fortsätter vi till fabriken. Gå ut ur gruvorna och du kan inte missa den. Låt oss hitta den där maskinen och stänga av den!,Şimdi fabrikaya gidelim. Madenlerden çıkın ve onu kaçırmayın. Hadi şu makineyi bulup kapatalım! +I'm reading massive neural wave distortions from straight ahead. I think we've found it. Let's get in there and shut it down!,TXT_ILOG102,"MAP20: Path to Conversion Chapel (MAP24). +(""neural oscillation"" or ""brainwave"")",,,"Detekuju obří rušení nervových vln přímo před námi. Myslím, že jsme to našli. Pojďme tam a vypněme to!","Jeg kan se massive neurale bølgeforvrængninger lige forude. Jeg tror, vi har fundet den. Lad os komme ind og lukke den ned!","Ich empfange massive neurale Verzerrungen direkt voraus. Ich denke, wir haben sie gefunden. Lass uns reingehen und sie abschalten.",,"Mi legas amasajn distordojn de cerbaj ondoj antaŭ vi. Ŝajnas, ke ni trovis ĝin. Ni eniru kaj malŝaltu ĝin!",Estoy leyendo distorsiones masivas de ondas cerebrales delante. Parece que la hemos encontrado. ¡Entremos ahí y apaguémosla!,Estoy leyendo distorsiones masivas de ondas cerebrales adelante. Parece que la encontramos. ¡Entremos ahí y apaguémosla!,Havaitsen massivisia hermoaaltovääristymiä suoraan edessä. Luulen löytäneemme sen. Mennään sisään ja sammutetaan se!,Je recois des distorsions neurales colossales devant nous. Je crois que nous l'avons trouvé. Détruisons-la!,Erős ideghullám zavaró jeleket fogok. Azt hiszem megtaláltuk. Menjünk be és állítsuk le!,Sto ricevendo potenti segnali distorti proprio davanti a te. Penso che l'abbiamo trovata. Entriamo e spegnamo questa macchina!,重い神経波歪曲が直に届いたわ。私達はそれを見つけたという事よ。,앞쪽에서 거대한 신경교란 파장이 감지되고 있어. 우리가 찾아낸 것 같아. 어서 들어가서 꺼버리자!,Ik lees enorme neurale golfvervormingen van rechtdoor. Ik denk dat we hem gevonden hebben. Laten we naar binnen gaan en de machine stilleggen!,Jeg leser massive nevrale bølgeforvrengninger rett fram. Jeg tror vi har funnet den. La oss gå inn og slå den av!,Odczytuję potężne zniekształcenia fal neuronowych z prostej drogi. Chyba ją znaleźliśmy. Wejdźmy tam i wyłączmy ją!,Estou vendo distorções enormes de ondas neurais. Acho que encontramos. Vamos entrar lá e desligar!,,"Citesc distorsiune neurale masive drept din față, cred că am găsit-o. Să intrăm și să o oprim.","Я вижу мощный источник помех прямо по курсу. Похоже, мы нашли конвертер. Войди и останови его!",,Jag läser massiva neurala vågförvrängningar från rakt fram. Jag tror att vi har hittat den. Låt oss gå in där och stänga av den!,Tam karşıdan büyük sinir dalgası bozulmaları okuyorum. Sanırım onu bulduk. Oraya girelim ve onu kapatalım! +Just when I think we've seen it all! They go in human and come out... I dont even want to think about it. Destroy this horror!,TXT_ILOG103,MAP24: Converter room.,,Just when I think we've seen it all! They go in human and come out... I don't even want to think about it. Destroy this horror!,"Zrovna, když jsem myslela, že jsme to všechno viděli! Dovnitř jdou jako lidé a vyjdou... ani na to nechci myslet. Znič tu hrůzu!","Lige når jeg tror, vi har set det hele! De går ind i et menneske og kommer ud... Jeg vil ikke engang tænke på det. Ødelæg denne rædsel!","Und da denkt man, man hätte schon alles gesehen. Die kommen als Menschen rein und kommen raus als... Ich möchte gar nicht drüber nachdenken. Zerstöre diesen Horror.",,"Kaj mi kredis, ke mi jam vidis ĉiajn aferojn! Ili eniras kiel homojn kaj eliras... Mi eĉ ne volas pensi pri tio. Haltigu ĉi tiun teruraĵon!",¡Justo cuando creía haberlo visto todo! Entran humanos y salen... No quiero ni pensarlo. ¡Detén este horror!,,Juuri kun luulen nähneemme kaiken! He menevät sisään ihmisinä ja tulevat ulos... En halua edes ajatellakaan sitä. Tuhoa tämä kauhistus!,"Et quand je pense avoir tout vu.. Des humains entrent, et puis.. Non, je ne veux pas y penser. Détruis cette horreur!","Amikor azt hittem, hogy mindent láttunk. Emberként mennek be, és úgy jönnek ki mint egy...nem is akarok rá gondolni. Semmisítsd meg ezt a horrort!",E io che pensavo di averle viste tutte! Entrano umani ed escono fuori... Non ci voglio neanche pensare. Distruggi questo orrore!,"今まで見てきたことについて考えている! 奴は人の内部から出てくる...それについて考えたくないわ。 -この恐怖を打ち消すんだ!",이렇게 끔찍한 모습을 보게 되다니! 멀쩡한 사람이 저곳에 들어갔다 나온 모습을... 차마 생각하기도 싫어. 저 경악스러운 것을 파괴해!,Net nu ik denk dat we alles hebben gezien! Ze gaan menselijk naar binnen en komen eruit.... Ik wil er niet eens over nadenken. Vernietig deze verschrikking!,Akkurat når jeg tror vi har sett alt! De går inn som mennesker og kommer ut... Jeg vil ikke engang tenke på det. Ødelegg denne grusomheten!,"Właśnie wtedy, gdy myślę, że widzieliśmy już wszystko! Wchodzą w człowieka i wychodzą... Nie chcę nawet o tym myśleć. Zniszczyć ten horror!",E eu pensei que já tinha visto de tudo! Eles entram humanos e saem... Eu não quero nem pensar nisso. Destrua essa coisa horripilante!,,Exact când credeam că am văzut tot. Intră oameni și ies...Nici nu vreau să mă gândesc. Distruge-o!,"А я-то думала, что хуже уже не будет! Они входят людьми, а выходят... Не хочу даже думать об этом. Покончи с этим кошмаром!",,Tam da her şeyi gördüğümüzü düşündüğüm anda! İnsana giriyorlar ve çıkıyorlar. Bunu düşünmek bile istemiyorum. Bu dehşeti yok edin! -Macil's gone nuts. He just knowingly sent 200 men to their deaths. I want vengeance! For the dead and for the living dead! Let's get back and find out what's going on.,TXT_ILOG104,,,,"Macil zešílel. Jen tak poslal dvě stě mužů na smrt. Chci odplatu - za mrtvé i živé mrtvé! Vraťme se a pojďme zjistit, co se stalo.","Macil er blevet skør. Han har lige bevidst sendt 200 mænd i døden. Jeg vil have hævn! For de døde og for de levende døde! Lad os tage tilbage og finde ud af, hvad der foregår.","Macil hat den Verstand verloren. Er hat gerade absichtlich 200 unserer Leute in den Tod geschickt. Ich will Rache! Für die Toten und für die lebenden Toten. Lass uns zurückgehen und herausfinden, was da los ist.",,,Macil se ha vuelto loco. Conscientemente ha enviado 200 hombres a su muerte. ¡Quiero venganza! ¡Por los muertos y los muertos vivientes! Regresemos y descubramos que está pasando.,Macil se ha vuelto loco. Conscientemente envió a 200 hombres a su muerte. ¡Quiero venganza! Por los muertos y por los muertos vivientes! Regresemos y veamos que está pasando.,"Macil on tullut hulluksi: Hän juuri lähetti tietoisesti 200 miestä surmaansa. Vaadin kostoa, sekä kuolleitten että elävien kuolleitten puolesta! Palataan ja selvitetään, mitä oikein on meneillään.","Macil a complètement perdu les pédales! Il a envoyé 200 hommes se faire tuer, et il le savait! Il faut les venger, pour eux et pour leurs camarades! On retourne à la base et on va trouver ce qu'il se passe.","Macil megőrült. 200 embert küldött a halálába szándékosan. Bosszút akarok! A halottakért, és az élőhalottakért! Húzzunk vissza és derítsük ki mi folyik.",Macil deve essere impazzito. Ha mandato consciamente 200 uomini verso la morte. Voglio vendetta! Per i morti e per i morti viventi! Ritorniamo alla base e scopriamo cosa sta succedendo.,"オラクルが正しかった。マシルはイカれていたなんて。 +この恐怖を打ち消すんだ!",이렇게 끔찍한 모습을 보게 되다니! 멀쩡한 사람이 저곳에 들어갔다 나온 모습을... 차마 생각하기도 싫어. 저 경악스러운 것을 파괴해!,Net nu ik denk dat we alles hebben gezien! Ze gaan menselijk naar binnen en komen eruit.... Ik wil er niet eens over nadenken. Vernietig deze verschrikking!,Akkurat når jeg tror vi har sett alt! De går inn som mennesker og kommer ut... Jeg vil ikke engang tenke på det. Ødelegg denne grusomheten!,"Właśnie wtedy, gdy myślę, że widzieliśmy już wszystko! Wchodzą w człowieka i wychodzą... Nie chcę nawet o tym myśleć. Zniszczyć ten horror!",E eu pensei que já tinha visto de tudo! Eles entram humanos e saem... Eu não quero nem pensar nisso. Destrua essa coisa horripilante!,,Exact când credeam că am văzut tot. Intră oameni și ies...Nici nu vreau să mă gândesc. Distruge-o!,"А я-то думала, что хуже уже не будет! Они входят людьми, а выходят... Не хочу даже думать об этом. Покончи с этим кошмаром!",,Precis när jag tror att vi har sett allt! De går in som människor och kommer ut... Jag vill inte ens tänka på det. Förstör denna skräck!,Tam da her şeyi gördüğümüzü düşündüğüm anda! İnsana giriyorlar ve çıkıyorlar. Bunu düşünmek bile istemiyorum. Bu dehşeti yok edin! +Macil's gone nuts. He just knowingly sent 200 men to their deaths. I want vengeance! For the dead and for the living dead! Let's get back and find out what's going on.,TXT_ILOG104,MAP24: After destroying the converter.,,,"Macil zešílel. Jen tak poslal dvě stě mužů na smrt. Chci odplatu - za mrtvé i živé mrtvé! Vraťme se a pojďme zjistit, co se stalo.","Macil er blevet skør. Han har lige bevidst sendt 200 mænd i døden. Jeg vil have hævn! For de døde og for de levende døde! Lad os tage tilbage og finde ud af, hvad der foregår.","Macil hat den Verstand verloren. Er hat gerade absichtlich 200 unserer Leute in den Tod geschickt. Ich will Rache! Für die Toten und für die lebenden Toten. Lass uns zurückgehen und herausfinden, was da los ist.",,Macil freneziĝis: li intence sendis 200 homojn al la morto. Reiru al li por malkaŝi la veron.,Macil se ha vuelto loco: ha enviado intencionalmente a 200 hombres directo a la muerte. Regresemos a ver que está pasando.,Macil se volvió loco: mandó intencionalmente a 200 hombres directo a la muerte. Regresemos a ver qué está pasando.,"Macil on tullut hulluksi: Hän juuri lähetti tietoisesti 200 miestä surmaansa. Vaadin kostoa, sekä kuolleitten että elävien kuolleitten puolesta! Palataan ja selvitetään, mitä oikein on meneillään.","Macil a complètement perdu les pédales! Il a envoyé 200 hommes se faire tuer, et il le savait! Il faut les venger, pour eux et pour leurs camarades! On retourne à la base et on va trouver ce qu'il se passe.","Macil megőrült. 200 embert küldött a halálába szándékosan. Bosszút akarok! A halottakért, és az élőhalottakért! Húzzunk vissza és derítsük ki mi folyik.",Macil deve essere impazzito. Ha mandato consciamente 200 uomini verso la morte. Voglio vendetta! Per i morti e per i morti viventi! Ritorniamo alla base e scopriamo cosa sta succedendo.,"オラクルが正しかった。マシルはイカれていたなんて。 彼は故意に200人以上の人々を死に追いやっていた。 復讐しなくては。死んだ人達の為、そして今生きている人達の為にも! -戻って何が起きているかも調べるんだ。",마실이 정신 나갔나 봐. 모든 것을 알면서도 200 명이나 되는 병력을 보내서 죽게 했어. 과부들과 망령들을 위한 복수를 할 시간이야! 기지로 돌아가서 한번 그에게 여쭤봐.,Macil is gek geworden. Hij heeft net bewust 200 mannen naar hun dood gestuurd. Ik wil wraak! Voor de doden en voor de levende doden! Laten we teruggaan en uitzoeken wat er aan de hand is.,Macil har gått fra vettet. Han sendte 200 menn i døden med viten og vilje. Jeg vil ha hevn! For de døde og for de levende døde! La oss dra tilbake og finne ut hva som foregår.,"Macilowi odbiło. Właśnie świadomie wysłał 200 ludzi na śmierć. Chcę zemsty! Za zmarłych i za żywych zmarłych! Wracajmy i dowiedzmy się, co się dzieje.",O Macil enlouqueceu. Ele acabou de mandar 200 homens para as suas mortes e ele sabia disso. Eu quero vingança! Pelos mortos e pelos mortos-vivos! Vamos voltar e descobrir o que está acontecendo.,,Macil a înnebunit. A trimis intenționat 200 oameni la moarte. Vreau răzbunare! Pentru morți și morții vii! Să ne întoarcem și să vedem despre ce e vorba.,"Мэйсил озверел. Он намеренно послал двести человек на верную смерть. Я жажду мести! За убитых и за живых мертвецов! Давай вернёмся и выясним, что происходит.",,Macil çıldırdı. Bile bile 200 adamı ölüme gönderdi. İntikam istiyorum! Ölüler ve yaşayan ölüler için! Geri dönüp neler olduğunu öğrenelim. -"The factory leads to a ""lab"", and they're getting a Sigil piece power signature from within. Back to the factory and our next step to freedom.",TXT_ILOG106,,,,"Továrna vede do „laboratoře“, a z ní detekují energii Pečeťe. Zpátky do továrny a našemu dalšímu kroku ke svobodě.","Fabrikken fører til et ""laboratorium"", og de får en signatur af en Sigil-styks kraft fra det indre. Tilbage til fabrikken og vores næste skridt mod frihed.","In der Fabrik gibt es ein „Labor“, und dort gibt es eine Sigil-Signatur. Zurück zur Fabrik und dem nächsten Schritt zu unserer Freiheit.",,,"La fábrica conduce a un 'laboratorio', y están obteniendo una señal de poder del Emblema desde dentro. De vuelta a la fábrica y nuestro siguiente paso a la libertad.",La Fábrica conduce a un Laboratorio y tiene una firma de poder del Emblema desde adentro. Regresemos a la Fábrica y a nuestro siguiente paso a la libertad.,"Tehdas johtaa ""laboratorioon"", ja he lukevat sisältä Sinettiosasen energiajälkiä. Takaisin tehtaaseen ja kohti seuraavaa askeltamme vapauteen.","L'usine mène à un « laboratoire », et je reçois le signal d'une pièce du Sigil à l'intérieur. Retournons à l'usine pour prendre le prochain pas vers la liberté.","A gyár egy laboratúriumba vezet, és pecsét erő sugárzást észlelünk belülről. Forduljunk vissza a gyárhoz, ezzel közelebb kerülve a szabadsághoz.","La Fabbrica porta a un ""laboratorio"", ed al suo interno è stato identificato un segnale di un pezzo del Sigillo. Ritorniamo alla fabbrica e il nostro prossimo passo per la libertà.","リヒターの報告では我々が破壊した工場は'研究所'に繋がっていて、 -奴等はシジルの調印を内部から得ている。工場に戻って自由への次の段階に進みましょう",이 공장은 '연구소'로 연결돼. 그리고 지금 오더가 그 안에서 시질의 힘을 빌릴 조짐이 보여. 공장으로 돌아가서 자유 투쟁을 계속 진행해!,"De fabriek leidt naar een ""lab"", en ze krijgen een Sigil stuk macht handtekening van binnenuit. Terug naar de fabriek en onze volgende stap naar vrijheid.","Fabrikken fører til et ""laboratorium"", og de får en Sigil-kraftsignatur fra innsiden. Tilbake til fabrikken og vårt neste skritt mot frihet.","Fabryka prowadzi do ""laboratorium"", a z jego wnętrza wydobywa się sygnatura mocy kawałka Sigil. Powrót do fabryki i nasz kolejny krok do wolności.","A fábrica leva a um ""laboratório"" e é de lá de onde eles estão recebendo um sinal da energia de uma peça do Sigilo. De volta à fábrica e ao próximo passo à liberdade.",,"Fabrica duce înspre un laborator, și primesc putere de la o piesă din Sigiliu. Înapoi la fabrică și încă un pas spre libertate.","За фабрикой находится «лаборатория», и мы засекли характерную энергию фрагмента Печати, исходящую оттуда. Вернись на фабрику и сделай ещё один шаг к нашему освобождению.",,"Fabrika bir ""laboratuvara"" açılıyor ve içeriden bir Sigil parçası güç imzası alıyorlar. Fabrikaya geri dönelim ve özgürlüğe bir sonraki adımımızı atalım." -"Find the Bishop and destroy him! Once he's dead, return to the Oracle.",TXT_ILOG120,MAP16: Entrance → Central door.,,,"Najdi Biskupa a znič ho! Až ho zabiješ, vrať se k Věštci.","Find biskoppen og ødelæg ham! Når han er død, skal du vende tilbage til Oraklet.","Finde den Bischof und vernichte ihn. Sobald er tot ist, kehre zum Orakel zurück.",,,"¡Encuentra al Obispo y destrúyelo! En cuanto esté muerto, regresa con el Oráculo.",,"Löydä Piispa ja tuhoa hänet! Kun hän on kuollut, palaa Oraakkelin luokse.","Trouve l'évêque et tues-le! Une fois qu'il est mort, retourne à l'Oracle.","Találd meg a Püspököt és öld meg! Ha meghalt, menj az Orákulumhoz.","Trova il Vescovo e distruggilo! Una volta ucciso, ritorna dall'Oracolo.",ビショップを見つけて殺したらオラクルの元へ戻れ。,비숍을 찾아서 그를 파괴해! 시질 조각을 얻은 뒤 오라클에게 돌아가.,"Vind de bisschop en vernietig hem! Als hij dood is, keer je terug naar het Orakel.","Finn biskopen og tilintetgjør ham! Når han er død, gå tilbake til Oraklet.","Znajdź Bishopa i zniszcz go! Gdy już będzie martwy, wróć do Oracle.",Encontre o Bispo e destrua ele! Assim que ele morrer volte ao Oráculo.,,"Găsește Episcopul și distruge-l! Odată ce e mort, întoarce-te la Oracol.","Найди Епископа и уничтожь его! После, вернись к Оракулу.",,Piskoposu bulun ve onu yok edin! O öldükten sonra Kahin'e dönün. -The Loremaster's lab is beyond the teleporter that just opened. Let's go find out what he was just yapping about. And our next step to freedom.,TXT_ILOG122,,,,"Dějepiscova laboratoř je za teleportérem, který se právě otevřel. Pojďme se podívat, o čem to blábolil. A k našemu dalšímu kroku ke svobodě.","Loremesterens laboratorium ligger bag teleporteren, der lige er åbnet. Lad os finde ud af, hvad han lige pludrede om. Og vores næste skridt til frihed.","Das Labor des Wissensmeisters ist jenseits des Teleporters, der gerade geöffnet wurde. Lass uns herausfinden, worüber er da gerade geschwafelt hat. Und zum nächsten Schritt für unsere Freiheit.",,,El laboratorio del Maestro del Conocimiento está al otro lado del teletransporte que acaba de abrirse. Vayamos a ver de qué tanto parloteaba. Y nuestro siguiente paso a la libertad.,El laboratorio del Maestro del Conocimiento está más allá del teleporte que se ha abierto. Vamos a encontrar de qué tanto balbucea. Y nuestro siguiente paso a la libertad.,"Oppi-Isän laboratorio on juuri avautuneen kaukosiirtimen tuolla puolen. Mennään ottamaan selvää, mistä hän juuri oikein pälätti, ja kohti seuraavaa askeltamme vapauteen.","Le laboratoire du Maître des Traditions est de l'autre côté du téléporteur que nous venons d'ouvrir. Allons voir pourquoi il était en train de brailler, et prendre le prochain pas vers la liberté.",A Tanmester laborja a most megnyílt teleport túloldalán van. Derítsük ki miről is hadovált az imént. Még egy lépés a szabadság irányába.,Il laboratorio del Sapiente si trova giusto oltre questo teletrasporto. Andiamo a vedere di cosa stava blaterando. E verso il nostro prossimo passo per la libertà.,"ロアマスター研究所は開いたばかりのテレポーターを越えた先だ。 -奴が何をやらかしているか調べろ。次の自由を解放するために。",로어마스터의 연구소는 방금 열린 텔레포터를 통해서 입장이 가능해. 어떤 예언을 지껄이는지 한번 확인하러 가봐. 그리고 자유 투쟁을 계속 진행해!,Het lab van de Kennismeester is voorbij de teleporter die net geopend is. Laten we gaan uitzoeken waar hij net over aan het zeuren was. En onze volgende stap naar vrijheid.,Loremesterens laboratorium er bortenfor teleporteren som nettopp åpnet seg. La oss finne ut hva han snakket om. Og vårt neste skritt mot frihet.,"Laboratorium Loremastera jest za teleporterem, który właśnie się otworzył. Dowiedzmy się, o czym on właśnie gadał. I nasz następny krok do wolności.",O laboratório do Mestre do Conhecimento está depois desse teletransportador que acaba de abrir. Vamos lá descobrir sobre o que ele estava tagarelando. E ao nosso próximo passo à liberdade.,,Laboratorul Maestrului Cunoștiințelor e dincolo de teleportorul care tocmai s-a deschis. Să mergem și să vedem despre ce tot bolborosea. Și următorul nostru pas spre libertate.,"Телепорт, который ты нашёл, приведёт тебя в лабораторию Хранителя мудрости. Давай узнаем, о чём он там бормотал, и сделаем ещё один шаг к освобождению.",,Loremaster'ın laboratuvarı az önce açılan ışınlayıcının ötesinde. Gidip neden bahsettiğini öğrenelim. Ve özgürlüğe giden bir sonraki adımımızı. -"Come on, let's get the hell out of here. The force field is down, off to the Bishop's tower. Once he's dead, get back to the Oracle.",TXT_ILOG211,MAP15: Computer destroyed + Room 1,,,"No tak, dostaňme se sakra odsud. Silové pole je kaput, jdeme do Biskupovy věže. Až ho zabiješ, vrať se k Věštci.","Kom nu, lad os komme væk herfra. Kraftfeltet er nede, af sted til biskoppens tårn. Når han er død, så gå tilbage til Oraklet.","Komm schon, lass uns von hier verschwinden. Das Kraftfeld ist abgeschaltet, also ab zum Turm des Bischofs. Sobald er tot ist, geht es zurück zum Orakel",,,"Venga, larguémonos de aquí. El campo de fuerza está desactivado, derechos a la torre del Obispo. En cuanto esté muerto, regresa con el Oráculo.","Vamos, larguémonos de aquí. El campo de fuerza fue desactivado, vamos a la torre del Obispo. Cuando esté muerto, regresa con el Oráculo.","Mennään, häivytään täältä hittoon. Voimakenttä on nurin; suunnatkaamme siis kohti Piispan tornia. Kun hän on kuollut, palaa Oraakkelin luokse.","Allez, il faut qu'on se barre d'ici. Le champ de force est hors-ligne. Entre dans la tour de l'évêque. Quand il sera mort, retourne à l'Oracle.","Na gyerünk, húzzunk innen. Az erőpajzs deaktiválva, irány a Püspök tornya. Ha meghalt menj vissza az Orákulumhoz.","Avanti, andiamo via da qui. Il campo di forza è disattivato, quindi andiamo alla torre del Vescovo. Una volta che è morto, ritorna dall'Oracolo.","頼むからこんな所さっさと出よう。 +戻って何が起きているかも調べるんだ。",마실이 정신 나갔나 봐. 모든 것을 알면서도 200 명이나 되는 병력을 보내서 죽게 했어. 과부들과 망령들을 위한 복수를 할 시간이야! 기지로 돌아가서 한번 그에게 여쭤봐.,Macil is gek geworden. Hij heeft net bewust 200 mannen naar hun dood gestuurd. Ik wil wraak! Voor de doden en voor de levende doden! Laten we teruggaan en uitzoeken wat er aan de hand is.,Macil har gått fra vettet. Han sendte 200 menn i døden med viten og vilje. Jeg vil ha hevn! For de døde og for de levende døde! La oss dra tilbake og finne ut hva som foregår.,"Macilowi odbiło. Właśnie świadomie wysłał 200 ludzi na śmierć. Chcę zemsty! Za zmarłych i za żywych zmarłych! Wracajmy i dowiedzmy się, co się dzieje.",O Macil enlouqueceu. Ele acabou de mandar 200 homens para as suas mortes e ele sabia disso. Eu quero vingança! Pelos mortos e pelos mortos-vivos! Vamos voltar e descobrir o que está acontecendo.,,Macil a înnebunit. A trimis intenționat 200 oameni la moarte. Vreau răzbunare! Pentru morți și morții vii! Să ne întoarcem și să vedem despre ce e vorba.,"Мэйсил озверел. Он намеренно послал двести человек на верную смерть. Я жажду мести! За убитых и за живых мертвецов! Давай вернёмся и выясним, что происходит.",,Macil har blivit galen. Han skickade just medvetet 200 män i döden. Jag vill ha hämnd! För de döda och för de levande döda! Låt oss återvända och ta reda på vad som pågår.,Macil çıldırdı. Bile bile 200 adamı ölüme gönderdi. İntikam istiyorum! Ölüler ve yaşayan ölüler için! Geri dönüp neler olduğunu öğrenelim. +"The factory leads to a ""lab"", and they're getting a Sigil piece power signature from within. Back to the factory and our next step to freedom.",TXT_ILOG106,MAP10: After killing Macil while having destroyed the converter in MAP24.,,,"Továrna vede do „laboratoře“, a z ní detekují energii Pečeťe. Zpátky do továrny a našemu dalšímu kroku ke svobodě.","Fabrikken fører til et ""laboratorium"", og de får en signatur af en Sigil-styks kraft fra det indre. Tilbage til fabrikken og vores næste skridt mod frihed.","In der Fabrik gibt es ein „Labor“, und dort gibt es eine Sigil-Signatur. Zurück zur Fabrik und dem nächsten Schritt zu unserer Freiheit.",,"La fabriko kondukas al «laboratorio» de kie ni malkovris signon de la povo de la Sigelo. Reiru al la fabriko, nia sekva paŝo al la libereco.","La fábrica lleva a un «laboratorio» en donde detectamos una señal del poder del Emblema. De vuelta a la fábrica, nuestro siguiente paso a la libertad.",,"Tehdas johtaa ""laboratorioon"", ja he lukevat sisältä Sinettiosasen energiajälkiä. Takaisin tehtaaseen ja kohti seuraavaa askeltamme vapauteen.","L'usine mène à un « laboratoire », et je reçois le signal d'une pièce du Sigil à l'intérieur. Retournons à l'usine pour prendre le prochain pas vers la liberté.","A gyár egy laboratúriumba vezet, és pecsét erő sugárzást észlelünk belülről. Forduljunk vissza a gyárhoz, ezzel közelebb kerülve a szabadsághoz.","La Fabbrica porta a un ""laboratorio"", ed al suo interno è stato identificato un segnale di un pezzo del Sigillo. Ritorniamo alla fabbrica e il nostro prossimo passo per la libertà.","リヒターの報告では我々が破壊した工場は'研究所'に繋がっていて、 +奴等はシジルの調印を内部から得ている。工場に戻って自由への次の段階に進みましょう",이 공장은 '연구소'로 연결돼. 그리고 지금 오더가 그 안에서 시질의 힘을 빌릴 조짐이 보여. 공장으로 돌아가서 자유 투쟁을 계속 진행해!,"De fabriek leidt naar een ""lab"", en ze krijgen een Sigil stuk macht handtekening van binnenuit. Terug naar de fabriek en onze volgende stap naar vrijheid.","Fabrikken fører til et ""laboratorium"", og de får en Sigil-kraftsignatur fra innsiden. Tilbake til fabrikken og vårt neste skritt mot frihet.","Fabryka prowadzi do ""laboratorium"", a z jego wnętrza wydobywa się sygnatura mocy kawałka Sigil. Powrót do fabryki i nasz kolejny krok do wolności.","A fábrica leva a um ""laboratório"" e é de lá de onde eles estão recebendo um sinal da energia de uma peça do Sigilo. De volta à fábrica e ao próximo passo à liberdade.",,"Fabrica duce înspre un laborator, și primesc putere de la o piesă din Sigiliu. Înapoi la fabrică și încă un pas spre libertate.","За фабрикой находится «лаборатория», и мы засекли характерную энергию фрагмента Печати, исходящую оттуда. Вернись на фабрику и сделай ещё один шаг к нашему освобождению.",,"Fabriken leder till ett ""labb"", och de får en Sigil piece power signatur inifrån. Tillbaka till fabriken och vårt nästa steg mot frihet.","Fabrika bir ""laboratuvara"" açılıyor ve içeriden bir Sigil parçası güç imzası alıyorlar. Fabrikaya geri dönelim ve özgürlüğe bir sonraki adımımızı atalım." +"Find the Bishop and destroy him! Once he's dead, return to the Oracle.",TXT_ILOG120,MAP16: Entrance → Central door.,,,"Najdi Biskupa a znič ho! Až ho zabiješ, vrať se k Věštci.","Find biskoppen og ødelæg ham! Når han er død, skal du vende tilbage til Oraklet.","Finde den Bischof und vernichte ihn. Sobald er tot ist, kehre zum Orakel zurück.",,Trovu kaj mortigu la Episkopon! Tiam reiru al la Orakolo.,¡Encuentra al Obispo y mátalo! Luego regresa con el Oráculo.,,"Löydä Piispa ja tuhoa hänet! Kun hän on kuollut, palaa Oraakkelin luokse.","Trouve l'évêque et tues-le! Une fois qu'il est mort, retourne à l'Oracle.","Találd meg a Püspököt és öld meg! Ha meghalt, menj az Orákulumhoz.","Trova il Vescovo e distruggilo! Una volta ucciso, ritorna dall'Oracolo.",ビショップを見つけて殺したらオラクルの元へ戻れ。,비숍을 찾아서 그를 파괴해! 시질 조각을 얻은 뒤 오라클에게 돌아가.,"Vind de bisschop en vernietig hem! Als hij dood is, keer je terug naar het Orakel.","Finn biskopen og tilintetgjør ham! Når han er død, gå tilbake til Oraklet.","Znajdź Bishopa i zniszcz go! Gdy już będzie martwy, wróć do Oracle.",Encontre o Bispo e destrua ele! Assim que ele morrer volte ao Oráculo.,,"Găsește Episcopul și distruge-l! Odată ce e mort, întoarce-te la Oracol.","Найди Епископа и уничтожь его! После, вернись к Оракулу.",,Hitta biskopen och förgöra honom! När han är död återvänder du till oraklet.,Piskoposu bulun ve onu yok edin! O öldükten sonra Kahin'e dönün. +The Loremaster's lab is beyond the teleporter that just opened. Let's go find out what he was just yapping about. And our next step to freedom.,TXT_ILOG122,MAP12?,,,"Dějepiscova laboratoř je za teleportérem, který se právě otevřel. Pojďme se podívat, o čem to blábolil. A k našemu dalšímu kroku ke svobodě.","Loremesterens laboratorium ligger bag teleporteren, der lige er åbnet. Lad os finde ud af, hvad han lige pludrede om. Og vores næste skridt til frihed.","Das Labor des Wissensmeisters ist jenseits des Teleporters, der gerade geöffnet wurde. Lass uns herausfinden, worüber er da gerade geschwafelt hat. Und zum nächsten Schritt für unsere Freiheit.",,"La ĵus malfermiĝinta teleportilo kondukas al la laboratorio de la Folkloristo. Ni iru malkaŝi tion, pri kio li blablais.",El teletransportador que acaba de abrirse lleva al laboratorio del Maestro del Conocimiento. Vayamos a ver de qué tanto parloteaba.,,"Oppi-Isän laboratorio on juuri avautuneen kaukosiirtimen tuolla puolen. Mennään ottamaan selvää, mistä hän juuri oikein pälätti, ja kohti seuraavaa askeltamme vapauteen.","Le laboratoire du Maître des Traditions est de l'autre côté du téléporteur que nous venons d'ouvrir. Allons voir pourquoi il était en train de brailler, et prendre le prochain pas vers la liberté.",A Tanmester laborja a most megnyílt teleport túloldalán van. Derítsük ki miről is hadovált az imént. Még egy lépés a szabadság irányába.,Il laboratorio del Sapiente si trova giusto oltre questo teletrasporto. Andiamo a vedere di cosa stava blaterando. E verso il nostro prossimo passo per la libertà.,"ロアマスター研究所は開いたばかりのテレポーターを越えた先だ。 +奴が何をやらかしているか調べろ。次の自由を解放するために。",로어마스터의 연구소는 방금 열린 텔레포터를 통해서 입장이 가능해. 어떤 예언을 지껄이는지 한번 확인하러 가봐. 그리고 자유 투쟁을 계속 진행해!,Het lab van de Kennismeester is voorbij de teleporter die net geopend is. Laten we gaan uitzoeken waar hij net over aan het zeuren was. En onze volgende stap naar vrijheid.,Loremesterens laboratorium er bortenfor teleporteren som nettopp åpnet seg. La oss finne ut hva han snakket om. Og vårt neste skritt mot frihet.,"Laboratorium Loremastera jest za teleporterem, który właśnie się otworzył. Dowiedzmy się, o czym on właśnie gadał. I nasz następny krok do wolności.",O laboratório do Mestre do Conhecimento está depois desse teletransportador que acaba de abrir. Vamos lá descobrir sobre o que ele estava tagarelando. E ao nosso próximo passo à liberdade.,,Laboratorul Maestrului Cunoștiințelor e dincolo de teleportorul care tocmai s-a deschis. Să mergem și să vedem despre ce tot bolborosea. Și următorul nostru pas spre libertate.,"Телепорт, который ты нашёл, приведёт тебя в лабораторию Хранителя мудрости. Давай узнаем, о чём он там бормотал, и сделаем ещё один шаг к освобождению.",,Läromästarens labb ligger bortom teleportern som just öppnades. Nu går vi och tar reda på vad han just babblade om. Och vårt nästa steg till frihet.,Loremaster'ın laboratuvarı az önce açılan ışınlayıcının ötesinde. Gidip neden bahsettiğini öğrenelim. Ve özgürlüğe giden bir sonraki adımımızı. +"Come on, let's get the hell out of here. The force field is down, off to the Bishop's tower. Once he's dead, get back to the Oracle.",TXT_ILOG211,MAP15: Computer destroyed + Room 1,,,"No tak, dostaňme se sakra odsud. Silové pole je kaput, jdeme do Biskupovy věže. Až ho zabiješ, vrať se k Věštci.","Kom nu, lad os komme væk herfra. Kraftfeltet er nede, af sted til biskoppens tårn. Når han er død, så gå tilbage til Oraklet.","Komm schon, lass uns von hier verschwinden. Das Kraftfeld ist abgeschaltet, also ab zum Turm des Bischofs. Sobald er tot ist, geht es zurück zum Orakel",,"Nu, ni eliru. Vi malŝaltis la fortokampon ĉe la turo de la Episkopo. Mortiginte lin, reiru al la Orakolo.","Venga, larguémonos de aquí. Ya se ha desactivado el campo de fuerza en la torre del Obispo. En cuanto lo mates, vuelve con el Oráculo.","Vamos, salgamos de aquí. Ya se desactivó el campo de fuerza en la torre del Obispo. En cuanto lo mates, vuelve con el Oráculo.","Mennään, häivytään täältä hittoon. Voimakenttä on nurin; suunnatkaamme siis kohti Piispan tornia. Kun hän on kuollut, palaa Oraakkelin luokse.","Allez, il faut qu'on se barre d'ici. Le champ de force est hors-ligne. Entre dans la tour de l'évêque. Quand il sera mort, retourne à l'Oracle.","Na gyerünk, húzzunk innen. Az erőpajzs deaktiválva, irány a Püspök tornya. Ha meghalt menj vissza az Orákulumhoz.","Avanti, andiamo via da qui. Il campo di forza è disattivato, quindi andiamo alla torre del Vescovo. Una volta che è morto, ritorna dall'Oracolo.","頼むからこんな所さっさと出よう。 フォースフィールドは切った、ビショップの塔へ向かおう。 ビショップを殺したらオラクルの元へ戻れ。 -","이제 이곳을 당장 떠나. 방어막이 꺼졌으니! 비숍의 성으로 이동해서 비숍을 죽이고, 오라클을 만나러 가.","Kom op, laten we hier als de sodemieter weggaan. Het krachtveld is naar beneden, op weg naar de bisschopstoren. Als hij dood is, ga dan terug naar het Orakel.","Kom igjen, la oss komme oss vekk herfra. Kraftfeltet er nede, av gårde til biskopens tårn. Når han er død, gå tilbake til oraklet.","Chodź, wynośmy się stąd. Pole siłowe wyłączone, idziemy do wieży biskupa. Kiedy będzie martwy, wróć do Wyroczni.","Vamos dar o fora daqui. O campo de força está desligado. Vamos para a torre do Bispo. Assim que ele morrer, volte ao oráculo.",,"Hai, să ieșim de aici. Câmpul de forță e la pământ, către turnul Episcopului. Odată ce e mort, întoarce-te la Oracol.","Ну же, двигаем отсюда. Силовое поле отключено, пора двигаться к башне Епископа. Когда он умрёт, возвращайся к Оракулу.",,"Hadi, buradan defolup gidelim. Güç alanı kapandı, Piskopos'un kulesine gidiyoruz. O öldüğünde, Kahin'e geri dönün." -Find the sanctuary by the river. Steal the chalice from inside. Bring it to Harris in the tavern.,TXT_ILOG1001,,,,Najdi svatyni u řeky. Zevnitř ukradni kalich. Přines ho Harrisovi do taverny.,Find helligdommen ved floden. Stjæl bægeret indefra. Bring den til Harris på tavernaen.,"Finde das Heiligtum am Fluss. Stehle den Kelch, der dort aufbewahrt wird und bringe ihn zu Harris in der Taverne.",,,Encuentra el santuario junto al río. Roba el cáliz de dentro. Tráeselo a Harris en la taberna.,Encuentra el santuario junto al río. Roba el cáliz de adentro. Tráeselo a Harris a la taberna.,Löydä pyhäkkö joen varrella. Varasta kalkki sisältä. Vie se Harrisille kapakkaan.,Trouve le sanctuaire près de la rivière. Prends le Calice qui s'y trouve et amène le à Harris dans la taverne.,A szentély a folyó mellett van. Lopd el a serleget bentről. Vidd travishez a kocsmába.,Trova il santuario accanto al fiume. Ruba il calice al suo interno. Portalo ad Harris nella taverna.,"川沿いの 聖域 を探し、中にある聖杯を盗む。 -酒場にいるハリスに渡す。",강 근처에 있는 성소를 찾아서 안에 보관되어있는 성배를 훔치고 선술집으로 향해.,Zoek het heiligdom bij de rivier. Steel de kelk van binnenuit. Breng het naar Harris in de herberg.,Finn helligdommen ved elven. Stjel begeret fra innsiden. Ta det med til Harris i vertshuset.,Znajdź sanktuarium nad rzeką. Ukradnij ze środka kielich. Zanieś go Harrisowi w tawernie.,Encontre o santuário perto do rio. Roube o cálice que está lá dentro. Leve-o para o Harris na taverna.,,Găsește sanctuarul de lângă râu. Fură potirul din interior. Du-l la Harris în tavernă.,Найди святилище возле реки. Проникни туда и выкради чашу. Принеси её Харрису в таверну.,,Nehir kenarındaki tapınağı bulun. İçeriden kadehi çalın. Tavernadaki Harris'e götür. -Find the Governor. Talk to him about your reward.,TXT_ILOG1002,,,,Najdi guvernéra. Promluv si s ním o své odměně.,Find guvernøren. Tal med ham om din belønning.,Finde den Gouverneur. Rede mit ihm über deine Belohnung.,,,Encuentra al Gobernador. Háblale sobre tu recompensa.,Encuentra al Gobernador. Háblale de tu recompensa.,Löydä kuvernööri. Puhu hänen kanssaan palkkiostasi.,Trouve le gouverneur et demande ta récompense.,Keresd meg a Kormányzót. Beszélj vele a jutalomról.,Trova il governatore. Parlargli della tua ricompensa.,知事を探せ。彼と話して報酬を貰う。,총독을 만나서 보상에 대해 예기해.,Vind de Gouverneur. Spreek met hem over je beloning.,Finn guvernøren. Snakk med ham om belønningen din.,Znajdź gubernatora. Porozmawiaj z nim o swojej nagrodzie.,Encontre o Governador. Fale com ele sobre a sua recompensa.,,Găsește Guvernatorul. Vorbește cu el despre recompensa ta.,Найди губернатора. Обсуди с ним свою награду.,,Vali'yi bul. Onunla ödülün hakkında konuş. -"Find the sanctuary by the river. Inside someone called Beldin is being held. Shut him up, and bring his ring back to Rowan as proof.",TXT_ILOG1003,MAP02: After accepting Rowan's chore.,,,Najdi svatyni u řeky. Uvnitř je držen jakýsi Beldin. Umlč ho a přines Rowanovi jeho prsten jako důkaz.,"Find helligdommen ved floden. Indenfor bliver en person ved navn Beldin holdt fanget. Få ham til at lukke munden på ham, og giv Rowan hans ring tilbage som bevis.",Finde das Heiligtum am Fluss. Dort drinnen wird jemand namens Beldin festgehalten. Bringe ihn zum Schweigen und gebe Rowan seinen Ring als Beweis.,,Trovu la sanktejo proksime de la rivero. Iu nomata Beldin estas retenita en ĝi. Silentigu lin kaj alportu lian ringon kiel pruvon al Rowan.,Encuentra el santuario junto al río. Dentro alguien llamado Beldin está retenido. Siléncialo y trae de vuelta su anillo a Rowan como prueba.,Encuentra el santuario junto al río. Adentro alguien llamado Beldin está retenido. Siléncialo y tráele su anillo a Rowan como prueba.,"Löydä pyhäkkö joen varrella. Sisällä on vangittuna joku nimeltään Beldin. Vaienna hänet, ja tuo hänen sormuksensa takaisin Rowanille todisteena.","Trouve le sanctuaire près de la rivière. Quelqu'un qui s'appelle Beldin s'y trouve emprisonné. Cloue-lui le bec, et ramène son anneau à Rowan comme preuve.","Megtalálod a szentélyt a folyó mellett. Egy Beldin nevű figurát tartanak fogva. Halgattasd el örökre, és hozd vissza a gyűrűjét Rowannak bizonyítékként.","Trova il santuario accanto al fiume. Dentro, qualcuno chiamato Beldin è sotto chiave. Fallo tacere per sempre, e riporta il suo anello a Rowan come prova.","川沿いの 聖域 を探せ。中にいるベルディンと +","이제 이곳을 당장 떠나. 방어막이 꺼졌으니! 비숍의 성으로 이동해서 비숍을 죽이고, 오라클을 만나러 가.","Kom op, laten we hier als de sodemieter weggaan. Het krachtveld is naar beneden, op weg naar de bisschopstoren. Als hij dood is, ga dan terug naar het Orakel.","Kom igjen, la oss komme oss vekk herfra. Kraftfeltet er nede, av gårde til biskopens tårn. Når han er død, gå tilbake til oraklet.","Chodź, wynośmy się stąd. Pole siłowe wyłączone, idziemy do wieży biskupa. Kiedy będzie martwy, wróć do Wyroczni.","Vamos dar o fora daqui. O campo de força está desligado. Vamos para a torre do Bispo. Assim que ele morrer, volte ao oráculo.",,"Hai, să ieșim de aici. Câmpul de forță e la pământ, către turnul Episcopului. Odată ce e mort, întoarce-te la Oracol.","Ну же, двигаем отсюда. Силовое поле отключено, пора двигаться к башне Епископа. Когда он умрёт, возвращайся к Оракулу.",,"Kom igen, vi sticker härifrån. Kraftfältet är nere, vi går till biskopens torn. När han är död, återvänder vi till Oraklet.","Hadi, buradan defolup gidelim. Güç alanı kapandı, Piskopos'un kulesine gidiyoruz. O öldüğünde, Kahin'e geri dönün." +Find the sanctuary by the river. Steal the chalice from inside. Bring it to Harris in the tavern.,TXT_ILOG1001,MAP33?,,,Najdi svatyni u řeky. Zevnitř ukradni kalich. Přines ho Harrisovi do taverny.,Find helligdommen ved floden. Stjæl bægeret indefra. Bring den til Harris på tavernaen.,"Finde das Heiligtum am Fluss. Stehle den Kelch, der dort aufbewahrt wird und bringe ihn zu Harris in der Taverne.",,"Trovu la sanktejon apud la rojo, ŝtelu la kalikon kaj portu ĝin al Harriso en la taverno.","Encuentra el santuario junto al arroyo, roba el cáliz de dentro y llévaselo a Harris en la taberna (Tavern).","Encuentra el santuario junto al arroyo, roba el cáliz de adentro y llévaselo a Harris a la taberna (Tavern).",Löydä pyhäkkö joen varrella. Varasta kalkki sisältä. Vie se Harrisille kapakkaan.,Trouve le sanctuaire près de la rivière. Prends le Calice qui s'y trouve et amène le à Harris dans la taverne.,A szentély a folyó mellett van. Lopd el a serleget bentről. Vidd travishez a kocsmába.,Trova il santuario accanto al fiume. Ruba il calice al suo interno. Portalo ad Harris nella taverna.,"川沿いの 聖域 を探し、中にある聖杯を盗む。 +酒場にいるハリスに渡す。",강 근처에 있는 성소를 찾아서 안에 보관되어있는 성배를 훔치고 선술집으로 향해.,Zoek het heiligdom bij de rivier. Steel de kelk van binnenuit. Breng het naar Harris in de herberg.,Finn helligdommen ved elven. Stjel begeret fra innsiden. Ta det med til Harris i vertshuset.,Znajdź sanktuarium nad rzeką. Ukradnij ze środka kielich. Zanieś go Harrisowi w tawernie.,Encontre o santuário perto do rio. Roube o cálice que está lá dentro. Leve-o para o Harris na taverna.,,Găsește sanctuarul de lângă râu. Fură potirul din interior. Du-l la Harris în tavernă.,Найди святилище возле реки. Проникни туда и выкради чашу. Принеси её Харрису в таверну.,,Hitta helgedomen vid floden. Stjäl kalken från insidan. Ta med den till Harris i tavernan.,Nehir kenarındaki tapınağı bulun. İçeriden kadehi çalın. Tavernadaki Harris'e götür. +Find the Governor. Talk to him about your reward.,TXT_ILOG1002,MAP33?,,,Najdi guvernéra. Promluv si s ním o své odměně.,Find guvernøren. Tal med ham om din belønning.,Finde den Gouverneur. Rede mit ihm über deine Belohnung.,,Trovu la registon kaj parolu al li pri via rekompenco.,Encuentra al Gobernador y háblale de tu recompensa.,,Löydä kuvernööri. Puhu hänen kanssaan palkkiostasi.,Trouve le gouverneur et demande ta récompense.,Keresd meg a Kormányzót. Beszélj vele a jutalomról.,Trova il governatore. Parlargli della tua ricompensa.,知事を探せ。彼と話して報酬を貰う。,총독을 만나서 보상에 대해 예기해.,Vind de Gouverneur. Spreek met hem over je beloning.,Finn guvernøren. Snakk med ham om belønningen din.,Znajdź gubernatora. Porozmawiaj z nim o swojej nagrodzie.,Encontre o Governador. Fale com ele sobre a sua recompensa.,,Găsește Guvernatorul. Vorbește cu el despre recompensa ta.,Найди губернатора. Обсуди с ним свою награду.,,Hitta guvernören. Prata med honom om din belöning.,Vali'yi bul. Onunla ödülün hakkında konuş. +"Find the sanctuary by the river. Inside someone called Beldin is being held. Shut him up, and bring his ring back to Rowan as proof.",TXT_ILOG1003,MAP02: After accepting Rowan's chore.,,,Najdi svatyni u řeky. Uvnitř je držen jakýsi Beldin. Umlč ho a přines Rowanovi jeho prsten jako důkaz.,"Find helligdommen ved floden. Indenfor bliver en person ved navn Beldin holdt fanget. Få ham til at lukke munden på ham, og giv Rowan hans ring tilbage som bevis.",Finde das Heiligtum am Fluss. Dort drinnen wird jemand namens Beldin festgehalten. Bringe ihn zum Schweigen und gebe Rowan seinen Ring als Beweis.,,Trovu la sanktejon apud la rojo. Iu nomata Beldin estas retenita en ĝi. Silentigu lin kaj donu lian ringon kiel pruvon al Rowan.,Encuentra el santuario junto al arroyo. Alguien llamado Beldin está retenido dentro. Siléncialo y dale su anillo a Rowan como prueba.,Encuentra el santuario junto al arroyo. Alguien llamado Beldin está retenido adentro. Siléncialo y dale su anillo a Rowan como prueba.,"Löydä pyhäkkö joen varrella. Sisällä on vangittuna joku nimeltään Beldin. Vaienna hänet, ja tuo hänen sormuksensa takaisin Rowanille todisteena.","Trouve le sanctuaire près de la rivière. Quelqu'un qui s'appelle Beldin s'y trouve emprisonné. Cloue-lui le bec, et ramène son anneau à Rowan comme preuve.","Megtalálod a szentélyt a folyó mellett. Egy Beldin nevű figurát tartanak fogva. Halgattasd el örökre, és hozd vissza a gyűrűjét Rowannak bizonyítékként.","Trova il santuario accanto al fiume. Dentro, qualcuno chiamato Beldin è sotto chiave. Fallo tacere per sempre, e riporta il suo anello a Rowan come prova.","川沿いの 聖域 を探せ。中にいるベルディンと 呼ばれている捕獲された者を見つけ彼を黙らせる。 -指輪をロワンに渡す。","강 근처에 있는 성소를 찾아서 벨딘이라는 사람을 찾고, 입을 다물게 해. 그 후에 그의 반지를 얻어서 로완에게 그를 죽였다고 증명해.","Zoek het heiligdom bij de rivier. Binnenin wordt iemand met de naam Beldin vastgehouden. Laat hem zwijgen, en breng zijn ring terug naar Rowan als bewijs.","Finn helligdommen ved elven. Der inne holdes en som heter Beldin fanget. Få ham til å holde kjeft, og ta med ringen hans tilbake til Rowan som bevis.",Znajdź sanktuarium nad rzeką. W środku przetrzymywany jest ktoś o imieniu Beldin. Ucisz go i przynieś jego pierścień Rowanowi jako dowód.,Encontre o santuário perto do rio. Dentro há alguém chamado Beldin sendo detido. Cale a boca dele e traga o seu anel de volta ao Rowan como prova.,,Găsește sanctuarul de lângă râu. Înăuntru cineva numit Beldin e reținut. Redu-l la tăcere și întoarce-te cu inelul la Rowan drept dovadă.,"Найди святилище возле реки. Внутри содержится пленник по имени Белдин. Заставь его замолчать, и принеси его кольцо Роуэну в качестве доказательства.",,Nehir kenarındaki sığınağı bul. İçeride Beldin adında biri tutuluyor. Onu susturun ve yüzüğünü kanıt olarak Rowan'a geri getirin. -Find the location of the Front and talk to Macil.,TXT_ILOG1004,MAP02: After getting the com unit from Rowan.,,,Najdi umístění Fronty a promluv si s Macilem.,Find placeringen af fronten og tal med Macil.,Finde die Basis der Front und rede mit Macil.,,,Encuentra la localización del Frente y habla con Macil.,,Löydä Rintaman olinpaikka ja keskustele Macilin kanssa.,Trouve où se cache le Front et parle à Macil.,"Keresd meg a Front központját, és beszélj Macillal.",Trova il quartier generale del Fronte e parla a Macil.,フロントの場所を見つけ、マシルと会話する。,프론트의 기지를 찾아서 마실과 대화해봐.,Zoek de locatie van het Front en praat met Macil.,Finn plasseringen til Fronten og snakk med Macil.,Znajdź lokalizację Frontu i porozmawiaj z Macil.,Ache a localização da Frente e fale com o Macil.,,Găsește locația Frontului și vorbește cu Macil.,Найди базу Сопротивления и поговори с Мэйсилом.,,Cephe'nin yerini bulun ve Macil ile konuşun. -"Go down the stairs, find and talk to Macil.",TXT_ILOG1005,,,,Jdi dolů po schodech a najdi a promluv si s Macilem.,"Gå ned ad trappen, find og tal med Macil.",Geh die Treppe runter und rede mit Macil.,,,Baja por las escaleras. Encuentra y habla con Macil.,,"Kulje portaat alas, löydä Macil ja keskustele hänen kanssaan.","Descends les escaliers, trouve et parle à Macil.","Menj le a lépcsőn, és keresd meg Macilt.","Scendi le scale, e trova e parla con Macil.",階段を降り、マシルと会話する。,계단 밑으로 내려가서 마실과 대화해봐.,"Ga de trap af, zoek en praat met Macil.","Gå ned trappene, finn og snakk med Macil.","Zejdź na dół po schodach, znajdź i porozmawiaj z Macil.","Desça as escadas, encontre e fale com o Macil.",,"Du-te în josul scărilor, găsește-l și vorbește cu Macil.","Спустись на этаж ниже, найди Мэйсила и поговори с ним.",,"Merdivenlerden aşağı inin, Macil'i bulun ve onunla konuşun." +指輪をロワンに渡す。","강 근처에 있는 성소를 찾아서 벨딘이라는 사람을 찾고, 입을 다물게 해. 그 후에 그의 반지를 얻어서 로완에게 그를 죽였다고 증명해.","Zoek het heiligdom bij de rivier. Binnenin wordt iemand met de naam Beldin vastgehouden. Laat hem zwijgen, en breng zijn ring terug naar Rowan als bewijs.","Finn helligdommen ved elven. Der inne holdes en som heter Beldin fanget. Få ham til å holde kjeft, og ta med ringen hans tilbake til Rowan som bevis.",Znajdź sanktuarium nad rzeką. W środku przetrzymywany jest ktoś o imieniu Beldin. Ucisz go i przynieś jego pierścień Rowanowi jako dowód.,Encontre o santuário perto do rio. Dentro há alguém chamado Beldin sendo detido. Cale a boca dele e traga o seu anel de volta ao Rowan como prova.,,Găsește sanctuarul de lângă râu. Înăuntru cineva numit Beldin e reținut. Redu-l la tăcere și întoarce-te cu inelul la Rowan drept dovadă.,"Найди святилище возле реки. Внутри содержится пленник по имени Белдин. Заставь его замолчать, и принеси его кольцо Роуэну в качестве доказательства.",,Hitta helgedomen vid floden. Där inne hålls någon som heter Beldin fången. Få tyst på honom och ta med dig hans ring tillbaka till Rowan som bevis.,Nehir kenarındaki sığınağı bul. İçeride Beldin adında biri tutuluyor. Onu susturun ve yüzüğünü kanıt olarak Rowan'a geri getirin. +Find the location of the Front and talk to Macil.,TXT_ILOG1004,MAP02: After getting the com unit from Rowan.,,,Najdi umístění Fronty a promluv si s Macilem.,Find placeringen af fronten og tal med Macil.,Finde die Basis der Front und rede mit Macil.,,,Encuentra la localización del Frente y habla con Macil.,,Löydä Rintaman olinpaikka ja keskustele Macilin kanssa.,Trouve où se cache le Front et parle à Macil.,"Keresd meg a Front központját, és beszélj Macillal.",Trova il quartier generale del Fronte e parla a Macil.,フロントの場所を見つけ、マシルと会話する。,프론트의 기지를 찾아서 마실과 대화해봐.,Zoek de locatie van het Front en praat met Macil.,Finn plasseringen til Fronten og snakk med Macil.,Znajdź lokalizację Frontu i porozmawiaj z Macil.,Ache a localização da Frente e fale com o Macil.,,Găsește locația Frontului și vorbește cu Macil.,Найди базу Сопротивления и поговори с Мэйсилом.,,Hitta platsen för fronten och prata med Macil.,Cephe'nin yerini bulun ve Macil ile konuşun. +"Go down the stairs, find and talk to Macil.",TXT_ILOG1005,MAP02?,,,Jdi dolů po schodech a najdi a promluv si s Macilem.,"Gå ned ad trappen, find og tal med Macil.",Geh die Treppe runter und rede mit Macil.,,,Baja por las escaleras. Encuentra y habla con Macil.,,"Kulje portaat alas, löydä Macil ja keskustele hänen kanssaan.","Descends les escaliers, trouve et parle à Macil.","Menj le a lépcsőn, és keresd meg Macilt.","Scendi le scale, e trova e parla con Macil.",階段を降り、マシルと会話する。,계단 밑으로 내려가서 마실과 대화해봐.,"Ga de trap af, zoek en praat met Macil.","Gå ned trappene, finn og snakk med Macil.","Zejdź na dół po schodach, znajdź i porozmawiaj z Macil.","Desça as escadas, encontre e fale com o Macil.",,"Du-te în josul scărilor, găsește-l și vorbește cu Macil.","Спустись на этаж ниже, найди Мэйсила и поговори с ним.",,"Gå ner för trapporna, hitta och prata med Macil.","Merdivenlerden aşağı inin, Macil'i bulun ve onunla konuşun." "Visit Irale, the Front's weapons supplier in town. He's behind the door next to the weapons shop. Then, use the key Macil gave you to talk to the Governor.",TXT_ILOG1006,MAP03: After joining the Front.,,,"Navštiv Iraleho, dodavatele zbraní pro Frontu ve městě. Je za dveřmi vedle obchodu se zbraněmi. Pak použij klíč od Macila, aby sis promluvil s guvernérem.","Besøg Irale, Frontens våbenleverandør i byen. Han befinder sig bag døren ved siden af våbenbutikken. Brug derefter den nøgle, som Macil gav dig, til at tale med guvernøren.","Suche Irale auf, den Waffenbeschaffer der Front in der Stadr. Er hält sich in dem Gebäude neben dem Waffengeschäft auf. Danach benutze den Schlüssel, den Macil dir gegeben hat, um mit dem Gouverneur zu reden",,,"Visita a Irale, el proveedor de armamento del Frente; está pasando la puerta junto a la tienda de armas (Weapons). Luego usa la llave que te dio Macil para hablar con el Gobernador.",,"Tapaa Iralea, joka on Rintaman asetoimittaja kaupungissa. Hän on asekaupan viereisen oven takana. Käytä sen jälkeen Macilin antamaa avainta puhuaksesi kuvernöörin kanssa.","Va voir Irale, le chef de l'arsenal du Front, en ville. Il se trouve derrière la porte à côté du marchand d'armes. Utilise la clé que Macil t'a donné pour parler au gouverneur.","Keresd fel Iralet, a Front fegyver beszállítóját a városban. A fegyverbolt melletti ajtó mögött vár rád. Utána használd a maciltól kapott kulcsot, hogy tudj beszélni a Kormányzóval.","Visita Irale, il fornitore di armi del Fronte in città. Si trova dietro la porta accanto al negozio di armi. Dopodiché, usa la chiave che Macil ti ha dato per andare a parlare al governatore.","町にいるフロントへの武器供給者であるイラールの元を訪ねる。 -彼は武器屋の隣のドアに居る。それで、知事と会う為にマシルから貰ったキーを使う。","프론트의 무기상인 이롤리를 마을에서 찾아. 무기 상점 근처에 문이 있을 거야. 마실이 준 열쇠로 문을 열고 방문한 뒤, 총독과 대화해.","Bezoek Irale, de wapenleverancier van het Front in de stad. Hij zit achter de deur naast de wapenwinkel. Gebruik dan de sleutel die Macil je gaf om met de Gouverneur te praten.","Besøk Irale, Frontens våpenleverandør i byen. Han er bak døren ved siden av våpenbutikken. Bruk nøkkelen Macil ga deg til å snakke med guvernøren.","Odwiedź w mieście Irale, dostawcę broni dla Frontu. Jest on za drzwiami obok sklepu z bronią. Następnie użyj klucza, który dał ci Macil, by porozmawiać z gubernatorem.","Visite o Irale, o fornecedor de armas da Frente. Ele está atrás da porta perto da loja de armas. Depois, use a chave que o Macil te deu para falar com o Governador.",,"Vizitează pe Irale, distribuitorul de arme alFrontului în oraș. E dincolo de ușa de lângă magazinul de arme. Apoi, folosește cheia pe care Macil ți-a dat-o și vorbește cu Guvernatorul.","Посети Ирэйла, поставщика оружия Сопротивления в городе. Он за следующей после оружейного магазина дверью. Затем, воспользуйся ключом, который тебе дал Мэйсил, чтобы поговорить с губернатором.",,"Kasabada Cephe'nin silah tedarikçisi İrale'yi ziyaret edin. Silah dükkanının yanındaki kapının arkasında. Sonra, Vali ile konuşmak için Macil'in size verdiği anahtarı kullanın." +彼は武器屋の隣のドアに居る。それで、知事と会う為にマシルから貰ったキーを使う。","프론트의 무기상인 이롤리를 마을에서 찾아. 무기 상점 근처에 문이 있을 거야. 마실이 준 열쇠로 문을 열고 방문한 뒤, 총독과 대화해.","Bezoek Irale, de wapenleverancier van het Front in de stad. Hij zit achter de deur naast de wapenwinkel. Gebruik dan de sleutel die Macil je gaf om met de Gouverneur te praten.","Besøk Irale, Frontens våpenleverandør i byen. Han er bak døren ved siden av våpenbutikken. Bruk nøkkelen Macil ga deg til å snakke med guvernøren.","Odwiedź w mieście Irale, dostawcę broni dla Frontu. Jest on za drzwiami obok sklepu z bronią. Następnie użyj klucza, który dał ci Macil, by porozmawiać z gubernatorem.","Visite o Irale, o fornecedor de armas da Frente. Ele está atrás da porta perto da loja de armas. Depois, use a chave que o Macil te deu para falar com o Governador.",,"Vizitează pe Irale, distribuitorul de arme alFrontului în oraș. E dincolo de ușa de lângă magazinul de arme. Apoi, folosește cheia pe care Macil ți-a dat-o și vorbește cu Guvernatorul.","Посети Ирэйла, поставщика оружия Сопротивления в городе. Он за следующей после оружейного магазина дверью. Затем, воспользуйся ключом, который тебе дал Мэйсил, чтобы поговорить с губернатором.",,"Besök Irale, frontens vapenleverantör i staden. Han befinner sig bakom dörren bredvid vapenbutiken. Använd sedan nyckeln som Macil gav dig för att prata med guvernören.","Kasabada Cephe'nin silah tedarikçisi İrale'yi ziyaret edin. Silah dükkanının yanındaki kapının arkasında. Sonra, Vali ile konuşmak için Macil'in size verdiği anahtarı kullanın." "Find the power tap on the mains, and shut it off. Bring something back to the Governor as proof.",TXT_ILOG1007,"MAP02: After accepting ""messy"" chore.",,,Najdi stáčedlo energie na síti a vypni jej. Přines guvernérovi něco zpět jako důkaz.,"Find elhanen på hovedledningen, og luk den. Tag noget med tilbage til guvernøren som bevis.",Finde die Energieanzapfung und schalte sie aus. Bringe dem Gouverneur irgend etwas als Beweis.,,,Encuentra la toma en la red eléctrica y destrúyela. Tráele algo al Gobernador como prueba.,,Etsi verkkovirran piilokytkentä ja katkaise se. Tuo kuvernöörille jotain todisteeksi.,Trouve la connection pirate sur le transformateur et enlève la. Amène quelque chose au gouverneur comme preuve.,"Keresd meg a fővonalon az áramkapcsolót, és kapcsold ki. Hozz vissza valamit a kormányzótól bizonyítékként.","Trova il marchingegno che sta venendo usato per rubare energia alla rete, e distruggilo. Porta dei resti al governatore come prova.","電力盗用の場所を見つけ、それを止める。 -知事に渡す証拠も必要だ。",주 동력선 어딘가에 있는 추출기를 처리해. 그 잔해를 총독에게 들고 가서 증명해.,"Zoek het kraantje op het lichtnet, en zet het uit. Breng iets terug naar de Gouverneur als bewijs.","Finn strømbryteren på strømnettet, og slå den av. Ta med noe tilbake til guvernøren som bevis.",Znajdź kurek z prądem w sieci i wyłącz go. Przynieś coś gubernatorowi jako dowód.,Encontre a ligação clandestina no transformador e desligue-a. Traga algo de volta para o Governador como prova.,,Găsește cuplul de putere și oprește-l. Adu ceva drept dovadă Guvernatorului.,Найди нелегальное подключение к энергосети и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства.,,Şebekedeki güç musluğunu bulun ve kapatın. Kanıt olarak Vali'ye bir şey getirin. +知事に渡す証拠も必要だ。",주 동력선 어딘가에 있는 추출기를 처리해. 그 잔해를 총독에게 들고 가서 증명해.,"Zoek het kraantje op het lichtnet, en zet het uit. Breng iets terug naar de Gouverneur als bewijs.","Finn strømbryteren på strømnettet, og slå den av. Ta med noe tilbake til guvernøren som bevis.",Znajdź kurek z prądem w sieci i wyłącz go. Przynieś coś gubernatorowi jako dowód.,Encontre a ligação clandestina no transformador e desligue-a. Traga algo de volta para o Governador como prova.,,Găsește cuplul de putere și oprește-l. Adu ceva drept dovadă Guvernatorului.,Найди нелегальное подключение к энергосети и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства.,,Leta reda på strömkranen på elnätet och stäng av den. Ta med dig något tillbaka till guvernören som bevis.,Şebekedeki güç musluğunu bulun ve kapatın. Kanıt olarak Vali'ye bir şey getirin. "Find Derwin in the warehouse of the power station. Kill him, and bring Mourel his ear.",TXT_ILOG1008,"MAP02: After accepting ""bloody"" chore.",,,Najdi Derwina ve skladu elektrárny. Zabij ho a přines Mourelovi jeho ucho.,"Find Derwin i lageret på kraftværket. Dræb ham, og giv Mourel hans øre.",Finde Derwin im Lagerhaus des Kraftwerks. Töte ihn und bringe Mourel sein Ohr.,,,Encuentra a Derwin en el almacén (Warehouse) de la central eléctrica (Power Station). Mátalo y llévale su oreja a Mourel.,,"Etsi Derwin voimalaitoksen varastolta. Tapa hänet, ja tuo Mourelille hänen korvansa.","Trouve Derwin dans l'entrepôt de la centrale électrique. Tue-le, et amène son oreille à Mourel.","Keresd meg Derwint az erőmű raktárjában. öld meg, és vidd vissza Mourelnek a fülét.","Trova Derwin nel magazzino della centrale energetica. Uccidilo, e porta il suo orecchio a Mourel.","発電所の倉庫にいるダーウィンを見つける。 -始末したら、そいつの耳をモーレルに渡す。",발전소 창고 주변에 있는 더윈을 찾아. 그를 죽인 뒤 귀를 뜯어서 모렐 총독에게 건네줘.,"Vind Derwin in het magazijn van de centrale. Dood hem, en breng Mourel zijn oor.","Finn Derwin i lageret på kraftstasjonen. Drep ham, og gi Mourel øret hans.",Znajdź Derwina w magazynie elektrowni. Zabij go i przynieś Mourelowi jego ucho.,Encontre o Derwin no depósito da usina elétrica. Mate-o e leve a sua orelha para o Mourel.,,Găsește-l pe Derwin în depozit. Omoară-l și adu-i urechea lui Mourel.,Найди Дервина на складе электростанции. Убей его и принеси Морелу его ухо.,,Elektrik santralinin deposunda Derwin'i bulun. Onu öldürün ve Mourel'e kulağını getirin. +始末したら、そいつの耳をモーレルに渡す。",발전소 창고 주변에 있는 더윈을 찾아. 그를 죽인 뒤 귀를 뜯어서 모렐 총독에게 건네줘.,"Vind Derwin in het magazijn van de centrale. Dood hem, en breng Mourel zijn oor.","Finn Derwin i lageret på kraftstasjonen. Drep ham, og gi Mourel øret hans.",Znajdź Derwina w magazynie elektrowni. Zabij go i przynieś Mourelowi jego ucho.,Encontre o Derwin no depósito da usina elétrica. Mate-o e leve a sua orelha para o Mourel.,,Găsește-l pe Derwin în depozit. Omoară-l și adu-i urechea lui Mourel.,Найди Дервина на складе электростанции. Убей его и принеси Морелу его ухо.,,Hitta Derwin i lagret i kraftverket. Döda honom och ge Mourel hans öra.,Elektrik santralinin deposunda Derwin'i bulun. Onu öldürün ve Mourel'e kulağını getirin. "Use the pass Mourel gave you to get into the prison. Once inside, talk to Warden Montag. Find a way to free the prisoners.",TXT_ILOG1009,MAP03: After completing Mourel's chore.,,,"Použij propustku od Mourela pro vstup do vězení. Uvnitř si promluv s dozorčím Montagem. Najdi způsob, jak vysvobodit vězně.","Brug det adgangskort, som Mourel gav dig, til at komme ind i fængslet. Når du er inde, skal du tale med direktør Montag. Find en måde at befri fangerne på.","Benutze den Pass, den Mourel dir gegeben hat um in das Gefängnis hereinzukommen. Wenn du drin bist, rede mit Direktor Montag. Finde einen Weg um die Gefangenen zu befreien.",,,"Usa el pase que Mourel te dió para entrar en la prisión. Una vez dentro, habla con el Carcelero Montag. Encuentra una forma de liberar a los prisioneros.",,Käytä Mourelin antamaa pääsylupaa päästäksesi vankilaan. Päästyäsi sisälle puhu vankilanjohtaja Montagin kanssa. Keksi keino vapauttaa vangit.,"Utilise le passe que Mourel t'a donné pour entrer dans la prison. Une fois à l'intérieur, parle au gardien Montag. Trouve un moyen de libérer les prisonniers.","Használd a Mourel által adott belépőt, hogy bejuss a börtönbe. Ha bent vagy, beszélj Montag börtön igazgatóval. Találd meg a módját, hogy kiszabadítsd a rabokat.","Usa il tesserino che Mourel ti ha dato per entrare nella prigione. Una volta dentro, parla con il direttore Montag. Trova un modo per liberare i prigionieri.","モーレルからもらった刑務所の許可証を使って入る。 入ったらモンターグと話し、囚人を解放する方法を探す。 -",총독이 준 감옥 통행증을 이용해서 감옥으로 들어가. 들어간 후에 수감자들을 해방하기 위해 몬탕 간수장과 대화해. ,"Gebruik de pas die Mourel je gaf om in de gevangenis te komen. Eenmaal binnen, praat je met Warden Montag. Zoek een manier om de gevangenen te bevrijden.","Bruk passet Mourel ga deg for å komme inn i fengselet. Når du er inne, snakk med fengselsdirektør Montag. Finn en måte å befri fangene på.","Użyj przepustki, którą dał ci Mourel, aby dostać się do więzienia. Po wejściu do środka porozmawiaj z naczelnikiem Montagiem. Znajdź sposób na uwolnienie więźniów.","Use o passe que o Mourel te deu para entrar na prisão. Após entrar, fale com o Carcereiro Montag. Encontre uma maneira de libertar os prisioneiros.",,"Folosește parola pe care ți-a dat-o Mourel pentru a intra în închisoare. Odată înăuntru, vorbește cu Directorul Montag. Găsește o cale să eliberezi prizonierii.","Используй пропуск, полученный у Морела, чтобы пройти в тюрьму. Когда ты будешь внутри, поговори с тюремщиком Монтагом. Найди способ освободить пленников.",,Hapishaneye girmek için Mourel'in size verdiği kartı kullanın. İçeri girdikten sonra Müdür Montag ile konuşun. Mahkûmları serbest bırakmanın bir yolunu bulun. -Use the Warden's key to get into the prison cell blocks and find a way to free the prisoners.,TXT_ILOG1010,MAP05,,,"Použij dozorčího klíč k dostání se do vězeňského bloku s celami a najdi způsob, jak vysvobodit vězně.",Brug fængselsdirektørens nøgle til at komme ind i fængselscelleblokkene og find en måde at befri fangerne på.,"Benutze den Schlüssel des Direktors um in die Zellenblöcke zu kommen und finde heraus, wie man die Gefangenen befreien kann.",,,Usa la llave del Carcelero para entrar en los bloques de celdas y encuentra una forma de liberar a los prisioneros.,Usa la llave del Carcelero para entrar a los bloques de celdas y encuentra una forma de liberar a los prisioneros.,Käytä vankilanjohtajan avainta päästäksesi vankilan selliosastoille ja keksi keino vapauttaa vangit.,Utilisé la clé du Gardien pour entrer dans les blocs de cellules et trouve un moyen de libérer les prisonners.,"Használd a börtön igazgató kulcsát, hogy bejuss a cella blokkba, és szabadítsd ki a foglyokat.",Usa la chiave del direttore per entrare nella sezione delle celle e trovare un modo per liberare i prigionieri.,ワーデンから鍵を奪って内部に入れ。,"간수장의 열쇠를 써서 감옥 안으로 진입하고, 수감자들을 풀어줄 방법을 찾아봐.",Gebruik de sleutel van de bewaker om in de celblokken van de gevangenis te komen en een manier te vinden om de gevangenen te bevrijden.,Bruk fengselsdirektørens nøkkel for å komme deg inn i fengselsblokkene og finn en måte å befri fangene på.,"Użyj klucza naczelnika, aby dostać się do bloków więziennych i znajdź sposób na uwolnienie więźniów.",Use a chave do Carcereiro para entrar nos blocos de celas e ache uma maneira de libertar os prisioneiros.,,Folosește cheia pe care ți-a dat-o Guvernatorul și găsește o cale să eliberezi prizonierii.,"Используй ключ тюремщика, чтобы пройти к камерам, и найди способ освободить пленников.",,Hapishane hücre bloklarına girmek için Müdürün anahtarını kullanın ve mahkûmları serbest bırakmanın bir yolunu bulun. +",총독이 준 감옥 통행증을 이용해서 감옥으로 들어가. 들어간 후에 수감자들을 해방하기 위해 몬탕 간수장과 대화해. ,"Gebruik de pas die Mourel je gaf om in de gevangenis te komen. Eenmaal binnen, praat je met Warden Montag. Zoek een manier om de gevangenen te bevrijden.","Bruk passet Mourel ga deg for å komme inn i fengselet. Når du er inne, snakk med fengselsdirektør Montag. Finn en måte å befri fangene på.","Użyj przepustki, którą dał ci Mourel, aby dostać się do więzienia. Po wejściu do środka porozmawiaj z naczelnikiem Montagiem. Znajdź sposób na uwolnienie więźniów.","Use o passe que o Mourel te deu para entrar na prisão. Após entrar, fale com o Carcereiro Montag. Encontre uma maneira de libertar os prisioneiros.",,"Folosește parola pe care ți-a dat-o Mourel pentru a intra în închisoare. Odată înăuntru, vorbește cu Directorul Montag. Găsește o cale să eliberezi prizonierii.","Используй пропуск, полученный у Морела, чтобы пройти в тюрьму. Когда ты будешь внутри, поговори с тюремщиком Монтагом. Найди способ освободить пленников.",,Använd passet som Mourel gav dig för att komma in i fängelset. När du väl är inne pratar du med fängelsedirektör Montag. Hitta ett sätt att befria fångarna.,Hapishaneye girmek için Mourel'in size verdiği kartı kullanın. İçeri girdikten sonra Müdür Montag ile konuşun. Mahkûmları serbest bırakmanın bir yolunu bulun. +Use the Warden's key to get into the prison cell blocks and find a way to free the prisoners.,TXT_ILOG1010,MAP05,,,"Použij dozorčího klíč k dostání se do vězeňského bloku s celami a najdi způsob, jak vysvobodit vězně.",Brug fængselsdirektørens nøgle til at komme ind i fængselscelleblokkene og find en måde at befri fangerne på.,"Benutze den Schlüssel des Direktors um in die Zellenblöcke zu kommen und finde heraus, wie man die Gefangenen befreien kann.",,,Usa la llave del Carcelero para entrar en los bloques de celdas y encuentra una forma de liberar a los prisioneros.,Usa la llave del Carcelero para entrar a los bloques de celdas y encuentra una forma de liberar a los prisioneros.,Käytä vankilanjohtajan avainta päästäksesi vankilan selliosastoille ja keksi keino vapauttaa vangit.,Utilisé la clé du Gardien pour entrer dans les blocs de cellules et trouve un moyen de libérer les prisonners.,"Használd a börtön igazgató kulcsát, hogy bejuss a cella blokkba, és szabadítsd ki a foglyokat.",Usa la chiave del direttore per entrare nella sezione delle celle e trovare un modo per liberare i prigionieri.,ワーデンから鍵を奪って内部に入れ。,"간수장의 열쇠를 써서 감옥 안으로 진입하고, 수감자들을 풀어줄 방법을 찾아봐.",Gebruik de sleutel van de bewaker om in de celblokken van de gevangenis te komen en een manier te vinden om de gevangenen te bevrijden.,Bruk fengselsdirektørens nøkkel for å komme deg inn i fengselsblokkene og finn en måte å befri fangene på.,"Użyj klucza naczelnika, aby dostać się do bloków więziennych i znajdź sposób na uwolnienie więźniów.",Use a chave do Carcereiro para entrar nos blocos de celas e ache uma maneira de libertar os prisioneiros.,,Folosește cheia pe care ți-a dat-o Guvernatorul și găsește o cale să eliberezi prizonierii.,"Используй ключ тюремщика, чтобы пройти к камерам, и найди способ освободить пленников.",,Använd fängelsedirektörens nyckel för att ta dig in i fängelsets cellblock och hitta ett sätt att befria fångarna.,Hapishane hücre bloklarına girmek için Müdürün anahtarını kullanın ve mahkûmları serbest bırakmanın bir yolunu bulun. "Destroy the power crystal that runs the power grid which drives the Order's shields. Go visit Worner, a spy we recruited in the warehouse of the power station. Don't forget to visit the medic and the weapons trainer before you go.",TXT_ILOG1011,MAP03: After accepting Macil's second mission.,,,"Znič energetický krystal, který napájí elektrickou síť, kterou jsou poháněné štíty Řádu. Jdi navštívit Wornera, špióna, kterého jsme najali ve skladu elektrárny. Nezapomeň navštívit zdravotníka a učitele střelby, než půjdeš.","Ødelæg energikrystallen, der driver det strømnet, som driver Ordenens skjolde. Besøg Worner, en spion, som vi rekrutterede i lageret på kraftværket. Glem ikke at besøge lægen og våbentræneren, før du går.","Zerstöre den Energiekristall der die Energieversorgung für die Kraftschilde kontrolliert. Suche Worner auf, einen Spion, den wir im Lagerhaus des Kraftwerks rekrutiert haben. Vergiß nicht, den Sanitäter und den Waffentrainer aufzusuchen, bevor du gehst.",,,"Destruye el cristal de poder que impulsa la red eléctrica que alimenta los escudos de La Orden. Busca a Worner, un espía que reclutamos en el almacén de la central eléctrica. Recuerda visitar al médico y al entrenador de armas.",,"Tuhoa kaupungin sähköverkon voimanlähteenä toimiva voimakristalli, jonka voimaa Veljeskunnan kilvet käyttävät. Mene tapaamaan Worneria, vakoojaa, jonka värväsimme voimalaitoksen varastolta. Älä unohda vierailla lääkintämiehen ja asekouluttajan luona, ennen kuin lähdet.","Détruis le cristal qui alimente la grille énergétique des boucliers de l'Ordre. Va voir Worner, un espion que nous avons recruté dans l'entrepôt de la centrale éléctrique. N'oublie pas d'aller voir le maître d'armes et le médecin avant d'y aller.","Semmisítsd meg az erő kristályt, ami a Rend külső védőpajzsát hajtja az elektromos hálózaton keresztül. Keresd fel az erőműtől betoborzott kémünket, Wornert. Ne felejtsd el meglátogatni a szanitécet és a fegyvermestert mielőtt nekiindulsz.","Distruggi il cristallo che fornisce energia agli scudi dell'Ordine. Trova Worner, una spia che abbiamo reclutato nel magazzino della centrale energetica. Non scordarti di passare dal medico e dall'addestratore di armi prima di andare.","送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止める。 発電所の倉庫に潜らせたスパイ、ワーナーを訪ねる。 -その前にメディックと武器トレーナーに会うのを忘れるな。","오더의 방어막을 유지하는 동력 망의 전력원인 수정체를 파괴하자. 우선, 발전소 창고에 있는 우리 쪽 첩자인 워너에게 찾아가 보자. 가기 전에 의무관이랑 무기 담당관을 만나는 것도 잊지 말고!","Vernietig het energiekristal dat het stroomnet dat de schilden van de Orde aandrijft. Ga naar Worner, een spion die we in het magazijn van de centrale hebben gerekruteerd. Vergeet niet om de dokter en de wapentrainer te bezoeken voor je vertrekt.","Ødelegg kraftkrystallen som driver kraftnettet som driver ordenens skjold. Besøk Worner, en spion vi rekrutterte i lageret til kraftstasjonen. Ikke glem å besøke medisineren og våpentreneren før du går.","Zniszcz kryształ mocy, który zasila sieć energetyczną napędzającą tarcze Zakonu. Idź odwiedzić Wornera, szpiega, którego zwerbowaliśmy w magazynie elektrowni. Nie zapomnij przed wyjściem odwiedzić medyka i trenera broni.","Destrua o cristal de energia que alimenta a rede elétrica por trás dos escudos da Ordem. Visite o Worner, um espião que recrutamos no depósito da usina de energia. Não se esqueça de visitar o médico e o treinador de armas antes de ir.",,"Distruge cristalul de nergie care alimentează câmpurile Ordinului. Vizitează pe Worner, un spion recrutat în depozitul stației. Nu uita să vorbești cu medicul și antrenorul de arme înainte.","Уничтожь кристалл, питающий энергосеть, от которой работают щиты Ордена. Поговори с Уорнэром, шпионом Сопротивления, на складе электростанции. Не забудь перед уходом посетить медика и инструктора по стрельбе.",,Tarikat'ın kalkanlarını çalıştıran güç şebekesini çalıştıran güç kristalini yok edin. Güç istasyonunun deposunda işe aldığımız casus Worner'ı ziyaret edin. Gitmeden önce sıhhiyeciyi ve silah eğitmenini ziyaret etmeyi unutmayın. +その前にメディックと武器トレーナーに会うのを忘れるな。","오더의 방어막을 유지하는 동력 망의 전력원인 수정체를 파괴하자. 우선, 발전소 창고에 있는 우리 쪽 첩자인 워너에게 찾아가 보자. 가기 전에 의무관이랑 무기 담당관을 만나는 것도 잊지 말고!","Vernietig het energiekristal dat het stroomnet dat de schilden van de Orde aandrijft. Ga naar Worner, een spion die we in het magazijn van de centrale hebben gerekruteerd. Vergeet niet om de dokter en de wapentrainer te bezoeken voor je vertrekt.","Ødelegg kraftkrystallen som driver kraftnettet som driver ordenens skjold. Besøk Worner, en spion vi rekrutterte i lageret til kraftstasjonen. Ikke glem å besøke medisineren og våpentreneren før du går.","Zniszcz kryształ mocy, który zasila sieć energetyczną napędzającą tarcze Zakonu. Idź odwiedzić Wornera, szpiega, którego zwerbowaliśmy w magazynie elektrowni. Nie zapomnij przed wyjściem odwiedzić medyka i trenera broni.","Destrua o cristal de energia que alimenta a rede elétrica por trás dos escudos da Ordem. Visite o Worner, um espião que recrutamos no depósito da usina de energia. Não se esqueça de visitar o médico e o treinador de armas antes de ir.",,"Distruge cristalul de nergie care alimentează câmpurile Ordinului. Vizitează pe Worner, un spion recrutat în depozitul stației. Nu uita să vorbești cu medicul și antrenorul de arme înainte.","Уничтожь кристалл, питающий энергосеть, от которой работают щиты Ордена. Поговори с Уорнэром, шпионом Сопротивления, на складе электростанции. Не забудь перед уходом посетить медика и инструктора по стрельбе.",,"Förstör kraftkristallen som driver kraftnätet som driver ordens sköldar. Gå och besök Worner, en spion som vi rekryterade i kraftverkets lager. Glöm inte att besöka läkaren och vapentränaren innan du går.",Tarikat'ın kalkanlarını çalıştıran güç şebekesini çalıştıran güç kristalini yok edin. Güç istasyonunun deposunda işe aldığımız casus Worner'ı ziyaret edin. Gitmeden önce sıhhiyeciyi ve silah eğitmenini ziyaret etmeyi unutmayın. Destroy the power crystal that runs the power grid which drives the Order's shields. Use the I.D. to get into the power station. You may want to check out the storeroom above Worner.,TXT_ILOG1012,MAP04: After talking to Worner.,,,"Znič energetický krystal, který napájí elektrickou síť, kterou jsou poháněné štíty Řádu. Použij získanou legitimaci pro přístup do elektrárny. Možná by stálo za to podívat se do skladištní místnosti nad Wornerem.","Ødelæg energikrystallen, der driver det kraftnet, som driver Ordenens skjolde. Brug identifikationskortet til at komme ind i kraftværket. Du kan tjekke lagerrummet over Worner.",Zerstöre den Energiekristall der die Energieversorgung für die Kraftschilde kontrolliert. Benutze die Identitätskarte. um in das Kraftwerk zu gelangen. Du solltest den Abstellraum beim Lagerhaus mal inspizieren.,,,Destruye el cristal de poder que impulsa la red eléctrica que alimenta los escudos de La Orden. Usa la identificación para entrar a la central eléctrica. Quizás quieras revisar el cuarto de almacenamiento encima de Worner.,,"Tuhoa kaupungin sähköverkon voimanlähteenä toimiva voimakristalli, jonka voimaa Veljeskunnan kilvet käyttävät. Käytä henkilötunnistetta päästäksesi voimalaitokselle. Saatat haluta vilkaista varastohuonetta Wornerin yläpuolella.",Détruis le cristal qui alimente la grille énergétique des boucliers de l'Ordre. Utilise la carte d'identité pour entrer dans la centrale. Il faudrait que tu aille voir la salle de stockage au dessus de Worner.,"Semmisítsd meg az erő kristályt, ami a Rend külső védőpajzsát hajtja az elektromos hálózaton keresztül. Használd az igazolványt, hogy bejuss az erőműbe. Jobban jársz, ha benézel a Worner fölötti tárolószobába.",Distruggi il cristallo che fornisce energia agli scudi dell'Ordine. Usa il tesserino d'identificazione per entrare nella centrale energetica. Ti conviene controllare il deposito che si trova sopra Worner.,"送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止める。 手に入れたI.D.を使って発電所に入る。 -ワーナーの言う上階の部屋も余裕があったら調べる。",오더의 방어막을 유지하는 동력 망의 전력원인 수정체를 파괴하자. 신분증을 이용해서 발전소 안으로 들어가. 그리고 워너 위에 창고도 확인하는 거 잊지 마!,Vernietig het energiekristal dat het elektriciteitsnet dat de schilden van de Orde aandrijft. Gebruik de I.D. om in de centrale te komen. Je kunt het magazijn boven Worner bekijken.,Ødelegg kraftkrystallen som driver kraftnettet som driver Ordenens skjold. Bruk I.D. for å komme inn i kraftstasjonen. Det kan være lurt å sjekke ut lagerrommet over Worner.,"Zniszcz kryształ mocy, który zasila sieć energetyczną napędzającą tarcze Zakonu. Użyj I.D., aby dostać się do elektrowni. Możesz chcieć sprawdzić magazyn nad Wornerem.",Destrua o cristal de energia que alimenta a rede elétrica por trás dos escudos da Ordem. Use a identificação para infiltrar a usina de energia. Você pode querer dar uma olhada no depósito acima do Worner.,,Distruge critalul energetic care alimentează scuturile Ordinului. Folosește cardul pentru a intra în stația de alimentare. Ai putea verifica și depozitul de deasupra lui Worner.,"Уничтожь кристалл, питающий энергосеть, от которой работают щиты Ордена. Пройди на электростанцию по удостоверению. Возможно, ты захочешь проверить склад на втором этаже, о котором говорил Уорнэр.",,Tarikat'ın kalkanlarını çalıştıran güç şebekesini çalıştıran güç kristalini yok edin. Güç istasyonuna girmek için kimliği kullanın. Worner'ın üstündeki depoyu kontrol etmek isteyebilirsiniz. +ワーナーの言う上階の部屋も余裕があったら調べる。",오더의 방어막을 유지하는 동력 망의 전력원인 수정체를 파괴하자. 신분증을 이용해서 발전소 안으로 들어가. 그리고 워너 위에 창고도 확인하는 거 잊지 마!,Vernietig het energiekristal dat het elektriciteitsnet dat de schilden van de Orde aandrijft. Gebruik de I.D. om in de centrale te komen. Je kunt het magazijn boven Worner bekijken.,Ødelegg kraftkrystallen som driver kraftnettet som driver Ordenens skjold. Bruk I.D. for å komme inn i kraftstasjonen. Det kan være lurt å sjekke ut lagerrommet over Worner.,"Zniszcz kryształ mocy, który zasila sieć energetyczną napędzającą tarcze Zakonu. Użyj I.D., aby dostać się do elektrowni. Możesz chcieć sprawdzić magazyn nad Wornerem.",Destrua o cristal de energia que alimenta a rede elétrica por trás dos escudos da Ordem. Use a identificação para infiltrar a usina de energia. Você pode querer dar uma olhada no depósito acima do Worner.,,Distruge critalul energetic care alimentează scuturile Ordinului. Folosește cardul pentru a intra în stația de alimentare. Ai putea verifica și depozitul de deasupra lui Worner.,"Уничтожь кристалл, питающий энергосеть, от которой работают щиты Ордена. Пройди на электростанцию по удостоверению. Возможно, ты захочешь проверить склад на втором этаже, о котором говорил Уорнэр.",,Förstör kraftkristallen som driver kraftnätet som driver Ordens sköldar. Använd ID-kortet för att ta dig in i kraftstationen. Du kanske vill kolla in förrådet ovanför Worner.,Tarikat'ın kalkanlarını çalıştıran güç şebekesini çalıştıran güç kristalini yok edin. Güç istasyonuna girmek için kimliği kullanın. Worner'ın üstündeki depoyu kontrol etmek isteyebilirsiniz. Destroy the power crystal that runs the power grid which drives the Order's shields. Go talk to Ketrick in the core area.,TXT_ILOG1013,"MAP04: After talking to ""Mr. Crispy"".",,,"Znič energetický krystal, který napájí elektrickou síť, kterou jsou poháněné štíty Řádu. Jdi za Ketrickem u jádra.","Ødelæg kraftkrystallen, der driver det kraftnet, som driver Ordenens skjolde. Gå hen og tal med Ketrick i kerneområdet.","Zerstöre den Energiekristall der die Energieversorgung für die Kraftschilde kontrolliert. Suche Worner auf, einen Spion, den wir im Lagerhaus des Kraftwerks rekrutiert haben. Vergiß nicht, den Sanitäter und den Waffentrainer aufzusuchen, bevor du gehst.",,,Destruye el cristal de poder que impulsa la red eléctrica que alimenta los escudos de La Orden. Habla con Ketrick en el área del núcleo.,,"Tuhoa kaupungin sähköverkon voimanlähteenä toimiva voimakristalli, jonka voimaa Veljeskunnan kilvet käyttävät. Puhu Ketrickin kanssa reaktorisydämen alueella.",Détruis le cristal qui alimente la grille énergétique des boucliers de l'Ordre. Va parler à Ketrick dans la zone du cœur.,"Semmisítsd meg az erő kristályt, ami a Rend külső védőpajzsát hajtja az elektromos hálózaton keresztül. Megleled Ketricket a mag térségben.",Distruggi il cristallo che fornisce energia agli scudi dell'Ordine. Vai a parlare con Ketrick nell'area del nucleo.,"送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止める。 -コアエリアでケトリックと話す。",오더의 방어막을 유지하는 동력 망의 전력원인 수정체를 파괴하자. 중심부에 있는 케트릭과 대화해.,Vernietig het energiekristal dat het elektriciteitsnet dat de schilden van de Orde aandrijft. Ga in het kerngebied met Ketrick praten.,Ødelegg kraftkrystallen som driver kraftnettet som driver Ordenens skjold. Snakk med Ketrick i kjerneområdet.,"Zniszcz kryształ mocy, który uruchamia sieć energetyczną napędzającą tarcze Zakonu. Idź porozmawiać z Ketrickiem w obszarze rdzenia.",Destrua o cristal de energia que alimenta a rede elétrica por trás dos escudos da Ordem. Fale com o Ketrick na área do núcleo.,,Distruge cristalul de energie care alimentează scuturile Ordinului. Vorbește cu Ketrick în zona nucleului.,"Уничтожь кристалл, питающий энергосеть Ордена и их щиты. Поговори с Кетриком возле реактора.",,Tarikat'ın kalkanlarını çalıştıran güç şebekesini çalıştıran güç kristalini yok edin. Çekirdek alanda Ketrick ile konuş. +コアエリアでケトリックと話す。",오더의 방어막을 유지하는 동력 망의 전력원인 수정체를 파괴하자. 중심부에 있는 케트릭과 대화해.,Vernietig het energiekristal dat het elektriciteitsnet dat de schilden van de Orde aandrijft. Ga in het kerngebied met Ketrick praten.,Ødelegg kraftkrystallen som driver kraftnettet som driver Ordenens skjold. Snakk med Ketrick i kjerneområdet.,"Zniszcz kryształ mocy, który uruchamia sieć energetyczną napędzającą tarcze Zakonu. Idź porozmawiać z Ketrickiem w obszarze rdzenia.",Destrua o cristal de energia que alimenta a rede elétrica por trás dos escudos da Ordem. Fale com o Ketrick na área do núcleo.,,Distruge cristalul de energie care alimentează scuturile Ordinului. Vorbește cu Ketrick în zona nucleului.,"Уничтожь кристалл, питающий энергосеть Ордена и их щиты. Поговори с Кетриком возле реактора.",,Förstör kraftkristallen som driver kraftnätet som driver ordens sköldar. Gå och prata med Ketrick i kärnområdet.,Tarikat'ın kalkanlarını çalıştıran güç şebekesini çalıştıran güç kristalini yok edin. Çekirdek alanda Ketrick ile konuş. "Destroy the power crystal. Go talk to Ketrick, bring the walkway up using the switches, then use this id for the elevator.",TXT_ILOG1014,MAP04: After talking to Sammis.,,,"Znič energetický krystal, který napájí elektrickou síť, kterou jsou poháněné štíty Řádu. Jdi si promluvit s Ketrickem, vyzvedni schodiště pomocí tlačítek a pak ve výtahu použij tuhle kartu.","Ødelæg kraftkrystallen. Gå hen og tal med Ketrick, bring gangbroen op ved hjælp af kontakterne, og brug derefter dette id til elevatoren.",Zerstöre den Energiekristall der die Energieversorgung für die Kraftschilde kontrolliert. Gehe zu Ketrick im Reaktorkern.,,,"Destruye el cristal de poder. Habla con Ketrick, alza la pasarela usando los interruptores, luego usa esta identificación para el ascensor.",,Tuhoa voimakristalli. Mene puhumaan Ketrickin kanssa. Tuo kulkusilta vivuilla ylös ja sitten käytä tätä tunnistetta hissiin.,"Détruis le cristal. Va parler à Ketrick. Fais monter la coursive en utilisant les boutons, puis utilise ta carte d'identité pour accéder à l'ascenseur.","Semmisítsd meg az erő kristályt. Menj és beszélj Kedrickkel, a kapcsolóval emeld meg a hidat, aztán használd az igazolványt a lifthez.","Distruggi il cristallo. Parla con Ketrick, fai alzare la passerella con i pulsanti, e poi usa questo tesserino per l'ascensore.","パワークリスタルを破壊してオーダーのシールドを止める。 -ケトリックと話し、スイッチを動かし通路を上げ、エレベーターにIDを使う。",수정체를 파괴해. 케트릭과 대화하고 나서 스위치를 눌러서 진입로를 작동시켜. 그리고 이 신분증을 이용해서 승강기를 올라타.,"Vernietig het energiekristal. Ga met Ketrick praten, breng de gang naar boven met behulp van de schakelaars, gebruik dan deze id voor de lift.","Ødelegg kraftkrystallen. Snakk med Ketrick, få gangbroen opp ved hjelp av bryterne, og bruk denne id-en til heisen.","Zniszcz kryształ mocy. Idź porozmawiać z Ketrickiem, podnieś chodnik używając przełączników, a następnie użyj tego id do windy.","Destrua o cristal de energia. Fale com o Ketrick, faça a passarela subir usando os interruptores e depois use esta identificação para o elevador.",,"Distruge cristalul energetic. Vorbește cu Ketrick, redă pasarela folosind butoanele, apoi folosește cardul pentru lift.","Уничтожь кристалл. Поговори с Кетриком, пройди наверх с помощью переключателей, затем используй удостоверение для доступа к лифту.",,"Güç kristalini yok et. Ketrick ile konuşun, anahtarları kullanarak geçidi yukarı getirin, sonra asansör için bu kimliği kullanın." +ケトリックと話し、スイッチを動かし通路を上げ、エレベーターにIDを使う。",수정체를 파괴해. 케트릭과 대화하고 나서 스위치를 눌러서 진입로를 작동시켜. 그리고 이 신분증을 이용해서 승강기를 올라타.,"Vernietig het energiekristal. Ga met Ketrick praten, breng de gang naar boven met behulp van de schakelaars, gebruik dan deze id voor de lift.","Ødelegg kraftkrystallen. Snakk med Ketrick, få gangbroen opp ved hjelp av bryterne, og bruk denne id-en til heisen.","Zniszcz kryształ mocy. Idź porozmawiać z Ketrickiem, podnieś chodnik używając przełączników, a następnie użyj tego id do windy.","Destrua o cristal de energia. Fale com o Ketrick, faça a passarela subir usando os interruptores e depois use esta identificação para o elevador.",,"Distruge cristalul energetic. Vorbește cu Ketrick, redă pasarela folosind butoanele, apoi folosește cardul pentru lift.","Уничтожь кристалл. Поговори с Кетриком, пройди наверх с помощью переключателей, затем используй удостоверение для доступа к лифту.",,"Förstör kraftkristallen. Gå och prata med Ketrick, ta upp gångvägen med hjälp av brytarna och använd sedan denna id för hissen.","Güç kristalini yok et. Ketrick ile konuşun, anahtarları kullanarak geçidi yukarı getirin, sonra asansör için bu kimliği kullanın." Find the town entrance that the Order has guarded. Open the door and bring the guard's uniform back to Weran.,TXT_ILOG1015,,,,"Najdi vchod do města, který Řád hlídá. Otevři dveře a přines hlídačovu uniformu Weranovi.","Find byens indgang, som Ordenen har bevogtet. Åbn døren og bring vagtens uniform tilbage til Weran.","Finde den Ausgang zur Stadt, der vom Orden bewacht wird. Öffne dir Tür und bringe die Uniform des Wächters zu Weran.",,,Encuentra la entrada al pueblo que La Orden tiene guardada. Abre la puerta y tráele de vuelta a Weran el uniforme del guardia.,,Löydä Veljeskunnan vartioima kaupungin sisäänkäynti. Avaa ovi ja tuo vartijan univormu Weranille.,Trouve l'entrée de la ville que L'Ordre garde fermée. Ouvre-la et amène l'uniforme du garde à Weran.,"Keresd meg a város bejáratot, amit a Rend őrzött. Nyisd ki az ajtót, és vidd vissza az uniformist Weranhoz.",Trova l'entrata verso la città che l'Ordine ha chiuso. Apri l'ingresso e riporta l'uniforme della guardia a Weran.,"オーダーが封鎖している町への入り口を見つける。 -ドアを開け、ガードの制服をウェランに持って帰る。",오더의 경비가 지키고 있는 마을의 입구를 찾아. 문을 연 뒤 그 경비의 전투복을 챙겨서 워렌에게 전해줘.,Zoek de stadstoegang die de Orde heeft bewaakt. Open de deur en breng het uniform van de bewaker terug naar Weran.,Finn inngangen til byen som Ordenen har bevoktet. Åpne døren og ta med vaktens uniform tilbake til Weran.,"Znajdź wejście do miasta, którego pilnuje Zakon. Otwórz drzwi i przynieś Weranowi mundur strażnika.",Encontre a entrada da cidade que a Ordem está vigiando. Abra a porta e leve o uniforme do guarda de volta para o Weran.,,Găsește intrarea orașului pe care Ordinul a păzit-o. Deschide ușa și du uniforma paznicului la Weran.,"Найди выход в город, охраняемый Орденом. Открой дверь и принеси униформу стражника Уэрану.",,Tarikatın koruduğu kasaba girişini bulun. Kapıyı açın ve muhafız üniformasını Weran'a geri getirin. +ドアを開け、ガードの制服をウェランに持って帰る。",오더의 경비가 지키고 있는 마을의 입구를 찾아. 문을 연 뒤 그 경비의 전투복을 챙겨서 워렌에게 전해줘.,Zoek de stadstoegang die de Orde heeft bewaakt. Open de deur en breng het uniform van de bewaker terug naar Weran.,Finn inngangen til byen som Ordenen har bevoktet. Åpne døren og ta med vaktens uniform tilbake til Weran.,"Znajdź wejście do miasta, którego pilnuje Zakon. Otwórz drzwi i przynieś Weranowi mundur strażnika.",Encontre a entrada da cidade que a Ordem está vigiando. Abra a porta e leve o uniforme do guarda de volta para o Weran.,,Găsește intrarea orașului pe care Ordinul a păzit-o. Deschide ușa și du uniforma paznicului la Weran.,"Найди выход в город, охраняемый Орденом. Открой дверь и принеси униформу стражника Уэрану.",,Hitta stadens ingång som ordern har bevakat. Öppna dörren och ta med dig vaktuniformen tillbaka till Weran.,Tarikatın koruduğu kasaba girişini bulun. Kapıyı açın ve muhafız üniformasını Weran'a geri getirin. "Take the flamethrower parts to Irale. Find the sewer maintenance door. Find and drain the reclamation tank inside the castle. At the bottom is a hidden entrance to the sewers. Down that entrance is where the gate controls are, somewhere.",TXT_ILOG1016,,,,Přines součásti plamenometu k Iralemu. Najdi kanálové údržbové dveře. Najdi a vypusť vodní nádrž uvnitř hradu. Na dně je skrytý vchod do dalších stok. Někde uvnitř je ovládání bran.,"Tag flammekasterens dele med til Irale. Find døren til vedligeholdelse af kloakken. Find og tøm genvindingstanken inde på slottet. I bunden er der en skjult indgang til kloakkerne. Nede ved denne indgang er der et sted, hvor kontrolelementerne til porten er.",Bringe dir Flammenwerferteile zu Irale. Finde die Wartungstür in der Kanalisation. Finde und leere den Sammeltank in der Burg. Am Boden ist ein versteckter Eingang zur Kanalisation. Dort ist die Steuerung für die Tore. Zerstöre sie.,,,"Llévale las partes de lanzallamas a Irale. Encuentra la puerta de mantenimiento de las alcantarillas. Encuentra y drena el tanque de reclamación dentro del castillo. Al fondo hay una entrada oculta a las alcantarillas. Bajando por esa entrada es donde se encuentran los controles de la puerta, en algún lugar.","Llévale las partes del lanzallamas a Irale. Encuentra la puerta de mantenimiento de la alcantarilla. Encuentra y drena el tanque de recuperación adentro del castillo. En el fondo de esa entrada están los controles de las puertas, en algún lugar.","Toimita liekinheittimen osat Iralelle. Etsi viemärin huolto-ovi. Etsi ja tyhjennä nesteentalteenottoallas linnan sisällä. Sen pohjalla on viemärin salainen sisäänkäynti, jonka sisältä portin ohjaimet jostakin löytyvät.",Amène les pièces du lance-flamme à Irale. Trouve l'entrée de maintenance des égouts. Fais vider le réservoir de recyclage du château. Au fond se trouve une entrée cachée vers les égouts. Les contrôles de la porte s'y trouvent.,Vidd a lángszóró darabokat Iralehez. Keresd meg a kanális szervíz ajtaját. Keresd meg a lefolyót és szárító tartályt a kastélyban. Az alján található egy titkos bejárat a kanálishoz. Túl ezen a bejáraton fogod megtalálni a kapu irányítópultot.,"Porta i pezzi del lanciafiamme da Irale. Trova l'entrata di manutenzione per le fogne. Svuota la vasca di recupero fluidi. Nel fondo c'è un'entrata nascosta per le fogne. I controlli dei cancelli sono laggiù, da qualche parte.","火炎放射器の部品をイラールに持っていく。 下水道のメンテナンス室を見つけ、 城内の貯水タンクを見つけて排水。 -その下には下水道への隠された入り口があり、その奥にゲートコントロールがある。","이 화염방사기 부품을 들고 이롤리에게 가져가. 하수도 정비소로 향하는 문을 찾은 뒤, 성안에 있는 수조를 찾고 내용물을 배출해. 그 밑에는 하수도로 향하는 숨겨진 통로가 있어. 그 안에는 분명히 성문 관리 장치가 있을 거야.","Neem de vlammenwerper delen naar Irale. Zoek de deur voor het rioolonderhoud. Zoek en laat de inpolderingstank in het kasteel leeglopen. Onderin is een verborgen ingang naar de riolering. Onderaan die ingang is waar de poortbediening is, ergens.","Ta flammekasterdelene til Irale. Finn vedlikeholdsdøren til kloakken. Finn og tøm gjenvinningstanken inne i slottet. Nederst er det en skjult inngang til kloakken. Ned den inngangen er hvor portkontrollene er, et eller annet sted.",Zabierz części miotacza ognia do Irale. Znajdź drzwi do konserwacji kanałów. Znajdź i osusz zbiornik rekultywacyjny wewnątrz zamku. Na dole jest ukryte wejście do kanałów. Na dole tego wejścia jest gdzieś sterowanie bramą.,Leve as peças do lança-chamas ao Irale. Ache a porta de manutenção do esgoto. Encontre e drene o tanque de recuperação dentro do castelo. No fundo há uma entrada oculta para o esgoto. Entre lá e encontre os controles do portão.,,"Du bucățiile aruncătorului de flăcări la Irale. Găsește ușa de mentenanță de la canale. Găsește și drenează rezervorul de recuperare din interiorul castelului. La fund e o intrare secretă către canale. Jos, se pot acționa porțiile, de undeva.",Отнеси детали огнемёта Ирэйлу. Найди дверь техобслуживания канализации. Найди бак для переработки и слей из него жидкость. На его дне находится потайной вход в стоки. Где-то за ним находится механизм управления воротами.,,Alev makinesi parçalarını İrale'ye götürün. Kanalizasyon bakım kapısını bulun. Kalenin içindeki ıslah tankını bulun ve boşaltın. En altta kanalizasyona giden gizli bir giriş var. O girişin aşağısında kapı kontrollerinin olduğu yer var. -Join the assault on the castle. Find and take out the Programmer. See the medic and the weapons trainer. Spend everything you've got. This is going to be a hell of a fight.,TXT_ILOG1017,,,,"Připoj se k útoku na hrad. Najdi a zabij Programátora. Zajdi si ke zdravotníkovi a učiteli střelby. Utrať vše, co máš. Tohle bude tvrdý boj.","Deltag i angrebet på slottet. Find og dræb programmøren. Se lægen og våbentræneren. Brug alt, hvad du har. Dette bliver en helvedes kamp.","Schließe dich dem Angriff auf die Burg an. Finde den Programmierer und schalte ihn aus. Suche den Sanitäter und den Waffentrainer auf. Kaufe was immer du kannst, das wird ein höllischer Kampf.",,,Únete al asalto en el castillo. Encuentra y elimina al Programador. Ve a ver al médico y entrenador de armas. Gasta todo lo que tengas. Esto va a ser una batalla tremenda.,Únete al asalto en el castillo. Encuentra y elimina al Programador. Ve al médico y al entrenador de armas. Gasta todo lo que tengas. Esta será una tremenda batalla.,Osallistu hyökkäykseen linnaa vastaan. Etsi ja kukista Ohjelmoitsija. Tapaa lääkintämiestä ja asekouluttajaa. Käytä kaikki varasi; tästä tulee hitonmoinen taistelu.,"Rejoins l'assaut sur le château. Trouve et tue le Programmeur. Va voir le médecin et le maître d'armes. Dépense tout ce que tu as, ça va être un sacré bain de sang!",Csatlakozz a kastély ostromához. Keresd meg és iktasd ki a Programozót. Menj a szanitéchoz és a fegyver kiképzőhöz. Költs el mindent amit csak tudsz. Gigászi csata előtt állunk.,"Unisciti all'assalto sul castello. Trova e fai fuori il Programmatore. Passa dal medico e dall'addestratore di armi. Ti conviene spendere più che puoi, sarà una dura battaglia.","城内への突撃部隊に加入し、プログラマーを探す。 +その下には下水道への隠された入り口があり、その奥にゲートコントロールがある。","이 화염방사기 부품을 들고 이롤리에게 가져가. 하수도 정비소로 향하는 문을 찾은 뒤, 성안에 있는 수조를 찾고 내용물을 배출해. 그 밑에는 하수도로 향하는 숨겨진 통로가 있어. 그 안에는 분명히 성문 관리 장치가 있을 거야.","Neem de vlammenwerper delen naar Irale. Zoek de deur voor het rioolonderhoud. Zoek en laat de inpolderingstank in het kasteel leeglopen. Onderin is een verborgen ingang naar de riolering. Onderaan die ingang is waar de poortbediening is, ergens.","Ta flammekasterdelene til Irale. Finn vedlikeholdsdøren til kloakken. Finn og tøm gjenvinningstanken inne i slottet. Nederst er det en skjult inngang til kloakken. Ned den inngangen er hvor portkontrollene er, et eller annet sted.",Zabierz części miotacza ognia do Irale. Znajdź drzwi do konserwacji kanałów. Znajdź i osusz zbiornik rekultywacyjny wewnątrz zamku. Na dole jest ukryte wejście do kanałów. Na dole tego wejścia jest gdzieś sterowanie bramą.,Leve as peças do lança-chamas ao Irale. Ache a porta de manutenção do esgoto. Encontre e drene o tanque de recuperação dentro do castelo. No fundo há uma entrada oculta para o esgoto. Entre lá e encontre os controles do portão.,,"Du bucățiile aruncătorului de flăcări la Irale. Găsește ușa de mentenanță de la canale. Găsește și drenează rezervorul de recuperare din interiorul castelului. La fund e o intrare secretă către canale. Jos, se pot acționa porțiile, de undeva.",Отнеси детали огнемёта Ирэйлу. Найди дверь техобслуживания канализации. Найди бак для переработки и слей из него жидкость. На его дне находится потайной вход в стоки. Где-то за ним находится механизм управления воротами.,,Ta med dig flamethrowerdelarna till Irale. Hitta dörren till underhållet av kloakerna. Hitta och töm återvinningstanken inne i slottet. I botten finns en dold ingång till avloppen. Nere vid den ingången finns portkontrollerna någonstans.,Alev makinesi parçalarını İrale'ye götürün. Kanalizasyon bakım kapısını bulun. Kalenin içindeki ıslah tankını bulun ve boşaltın. En altta kanalizasyona giden gizli bir giriş var. O girişin aşağısında kapı kontrollerinin olduğu yer var. +Join the assault on the castle. Find and take out the Programmer. See the medic and the weapons trainer. Spend everything you've got. This is going to be a hell of a fight.,TXT_ILOG1017,MAP03: After destroying the gate controls and talking to Macil.,,,"Připoj se k útoku na hrad. Najdi a zabij Programátora. Zajdi si ke zdravotníkovi a učiteli střelby. Utrať vše, co máš. Tohle bude tvrdý boj.","Deltag i angrebet på slottet. Find og dræb programmøren. Se lægen og våbentræneren. Brug alt, hvad du har. Dette bliver en helvedes kamp.","Schließe dich dem Angriff auf die Burg an. Finde den Programmierer und schalte ihn aus. Suche den Sanitäter und den Waffentrainer auf. Kaufe was immer du kannst, das wird ein höllischer Kampf.",,,Únete al asalto en el castillo. Encuentra y elimina al Programador. Ve a ver al médico y entrenador de armas. Gasta todo lo que tengas. Esto va a ser una batalla tremenda.,Únete al asalto en el castillo. Encuentra y elimina al Programador. Ve al médico y al entrenador de armas. Gasta todo lo que tengas. Esta será una tremenda batalla.,Osallistu hyökkäykseen linnaa vastaan. Etsi ja kukista Ohjelmoitsija. Tapaa lääkintämiestä ja asekouluttajaa. Käytä kaikki varasi; tästä tulee hitonmoinen taistelu.,"Rejoins l'assaut sur le château. Trouve et tue le Programmeur. Va voir le médecin et le maître d'armes. Dépense tout ce que tu as, ça va être un sacré bain de sang!",Csatlakozz a kastély ostromához. Keresd meg és iktasd ki a Programozót. Menj a szanitéchoz és a fegyver kiképzőhöz. Költs el mindent amit csak tudsz. Gigászi csata előtt állunk.,"Unisciti all'assalto sul castello. Trova e fai fuori il Programmatore. Passa dal medico e dall'addestratore di armi. Ti conviene spendere più che puoi, sarà una dura battaglia.","城内への突撃部隊に加入し、プログラマーを探す。 メディックと武器トレーナーに会っておく。 -この戦いは激しいものになるだろう、使えるものは全て使うつもりで行け。",성을 공략할 공성전에 참여해. 침투해서 프로그래머를 죽일 수 있게. 의무관이랑 무기 담당관을 만나고 네가 살 수 있는 걸 충분히 사. 왜냐하면 이 교전은 끔찍할 테니까.,Doe mee aan de aanval op het kasteel. Zoek en haal de Programmeur eruit. Zie de dokter en de wapentrainer. Geef alles uit wat je hebt. Dit wordt een hels gevecht.,Bli med i angrepet på slottet. Finn og drep programmereren. Gå til legen og våpentreneren. Bruk alt du har. Dette kommer til å bli litt av en kamp.,"Dołącz do szturmu na zamek. Znajdź i zlikwiduj Programistę. Zobacz medyka i trenera broni. Wydaj wszystko, co masz. To będzie piekielnie trudna walka.",Junte-se ao ataque no castelo. Ache e elimine o Programador. Visite o médico e o treinador de armas. Gaste tudo o que você tem. Essa vai ser uma briga das grandes.,,Alătură-te asaltului asupra castelului. Vezi medicul și antrenorul de arme. Cheltuie tot ce ai. O să fie o luptă pe cnste.,Присоединись к атаке на замок. Найди и убей Программиста. Посети медика и инструктора по стрельбе. Не жалей золота: битва будет чертовски жаркой.,,Kaleye yapılan saldırıya katıl. Programcıyı bul ve etkisiz hale getir. Sıhhiyeciyi ve silah eğitmenini gör. Elinizdeki her şeyi harcayın. Bu cehennem gibi bir savaş olacak. +この戦いは激しいものになるだろう、使えるものは全て使うつもりで行け。",성을 공략할 공성전에 참여해. 침투해서 프로그래머를 죽일 수 있게. 의무관이랑 무기 담당관을 만나고 네가 살 수 있는 걸 충분히 사. 왜냐하면 이 교전은 끔찍할 테니까.,Doe mee aan de aanval op het kasteel. Zoek en haal de Programmeur eruit. Zie de dokter en de wapentrainer. Geef alles uit wat je hebt. Dit wordt een hels gevecht.,Bli med i angrepet på slottet. Finn og drep programmereren. Gå til legen og våpentreneren. Bruk alt du har. Dette kommer til å bli litt av en kamp.,"Dołącz do szturmu na zamek. Znajdź i zlikwiduj Programistę. Zobacz medyka i trenera broni. Wydaj wszystko, co masz. To będzie piekielnie trudna walka.",Junte-se ao ataque no castelo. Ache e elimine o Programador. Visite o médico e o treinador de armas. Gaste tudo o que você tem. Essa vai ser uma briga das grandes.,,Alătură-te asaltului asupra castelului. Vezi medicul și antrenorul de arme. Cheltuie tot ce ai. O să fie o luptă pe cnste.,Присоединись к атаке на замок. Найди и убей Программиста. Посети медика и инструктора по стрельбе. Не жалей золота: битва будет чертовски жаркой.,,Gå med i anfallet mot slottet. Hitta och ta ut programmeraren. Se till sjukvårdaren och vapentränaren. Spendera allt du har. Det här kommer att bli en jäkla kamp.,Kaleye yapılan saldırıya katıl. Programcıyı bul ve etkisiz hale getir. Sıhhiyeciyi ve silah eğitmenini gör. Elinizdeki her şeyi harcayın. Bu cehennem gibi bir savaş olacak. Use the key the false Programmer gave you to open an entrance to the Programmer's keep. It has to be where he's hiding. Find the Programmer and kill him.,TXT_ILOG1018,,,,Použij klíč od falešného Programátora pro otevření vchodu do Programátorova doupěte. Tam se musí nacházet. Najdi Programátora a zabij ho.,"Brug den nøgle, som den falske programmør gav dig, til at åbne en indgang til programmørens tårn. Det må være der, hvor han gemmer sig. Find programmøren og dræb ham.","Benutze den Schlüssel des falschen Programmierers um in die Unterkunft des Programmierers einzudringen. Das ist der Ort, wo er sich verstecken dürfte. Finde und töte ihn.",,,Usa la llave que el falso Programador te dió para abrir una entrada a la guarida del Programador. Tiene que ser ahí donde se oculta. Encuentra al Programador y mátalo.,Usa la llave que el falso Programador te dió para abrir la entrada a la güarida del Programador. Debe ser donde está escondido. Encuentra al Programador y mátalo.,Käytä Valeohjelmoitsijan antamaa avainta avataksesi sisäänkäynnin Ohjelmoitsijan linnakkeeseen. Siellä hän varmastikin piilottelee. Etsi Ohjelmoitsija ja tapa hänet.,Utilise la clé que le faux Programmeur t'a donné pour entrer dans le donjon du Programmeur. Il doit s'y cacher. Trouve-le et tues-le.,"Használd az ál-programozótól kapott kulcsot, hogy bejuss a Programozó tornyába. Minden bizonnyal ott bújkál. Keresd meg a Programozót, és öld meg.",Usa la chiave che il falso Programmatore ti ha dato per entrare nella fortezza del Programmatore. Deve essere là che si nasconde. Trova il Programmatore e uccidilo.,"偽プログラマーから貰ったキーを使って本物がいるはずの砦を開く。 -奴はそこに隠れなければならないはず。プログラマーを見つけて殺す。","프로그래머 더미가 준 열쇠를 이용해서 프로그래머의 거주지로 향하는 문을 열어. 안에는 분명히 그가 있을 거야. 프로그래머를 찾으면, 일이 더 나빠지기 전에 죽여.",Gebruik de sleutel die de valse Programmer je gaf om een ingang te openen naar de wacht van de Programmeur. Het moet zijn waar hij zich verbergt. Zoek de Programmeur en vermoord hem.,Bruk nøkkelen den falske programmereren ga deg til å åpne en inngang til programmererens borg. Det må være der han gjemmer seg. Finn programmereren og drep ham.,"Użyj klucza, który dał ci fałszywy Programista, aby otworzyć wejście do kryjówki Programisty. To musi być miejsce, gdzie on się ukrywa. Znajdź Programistę i zabij go.",Use a chave que o falso Programador te deu para abrir uma entrada à fortaleza do Programador. Tem que ser onde ele está escondido. Encontre o Programador e mate-o.,,Folosește cheia pe care Programator fals ți-a dat-o pentru a deschide intrarea către curtea Programatorului. Trebuie să fie locul în care se ascunde. Găsește Programatorul și ucide-l.,"Используй ключ, полученный от фальшивого Программиста, чтобы открыть вход в цитадель. Скорее всего, именно там прячется настоящий Программист. Найди и убей его.",,Sahte Programcı'nın size verdiği anahtarı kullanarak Programcı'nın kalesine bir giriş açın. Saklandığı yer orası olmalı. Programcıyı bul ve öldür. -Seek out the Oracle and ask it about the other Sigil pieces. Take your reward and go across to the medic and weapons trainer for health and training.,TXT_ILOG1019,MAP10: After talking to Macil.,,,Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Převezmi si svou odměnu a navštiv zdravotníka a učitele střelby pro zdraví a výcvik.,Opsøg Oraklet og spørg det om de andre Sigil stykker. Tag din belønning og gå over til lægen og våbentræneren for at få sundhed og træning.,Suche das Orakel auf und frage es nach den anderen Sigil-Teilen. Nimm deine Belohnung und suche den Sanitäter und den Waffentrainer auf.,,,Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Toma tu recompensa y ve al médico y al entrenador de armas para salud y entrenamiento.,Busca al Oráculo y pregúntale acerca de las otras piezas del Emblema. Toma tú recompensa y dirígete con el médico y el entrenador de armas por salúd y entrenamiento.,Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Vastaanota palkkiosi ja käy lääkintämiehen ja asekouluttajan luona terveydenhoitoa ja koulutusta varten.,"Trouve l'Oracle et demande lui où se trouve les autres pièces du Sigil. Récupère ta récompense, et va voir le médecin et le maître d'armes pour te soigner et t'entraîner.","Kutasd fel az Orákulumot, és érdeklődj a Pecsét további darabjairól. Zsebeld be a jutalmad, és költsd is el szépen a szanitécnál és a fegyvermesternél.",Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. Prendi la tua ricompensa e visita il dottore e l'addestratore di armi.,"オラクルに会いシジルの欠片について尋ねる。 -強化のためメディックと武器トレーナーに会っておく。",오라클을 찾아서 다른 시질 조각이 어디에 있는지 물어봐. 보상을 받고 치료와 훈련을 위해 의무관과 무기 담당관에게로 가.,Zoek het Orakel op en vraag het over de andere Sigil stukken. Pak je beloning en ga naar de dokter en wapentrainer voor gezondheid en training.,Oppsøk oraklet og spør det om de andre sigil-brikke. Ta belønningen din og gå over til medisineren og våpentreneren for helse og trening.,Poszukaj Wyroczni i zapytaj ją o pozostałe kawałki Sigila. Odbierz nagrodę i przejdź do medyka i trenera broni po zdrowie i trening.,Procure o Oráculo e pergunte o sobre as outras peças do Sigilo. Pegue a sua recompensa e visite o médico e o treinador de armas para recuperar saúde e receber treinamento.,,Caută Oracolul și întreabă de celelalte piese de Sigiliu. Ia-ți recompensa și du-te la medic și antrenorul de arme.,Найди Оракула и спроси у него про другие фрагменты Печати. Возьми свою награду и посети медика и инструктора по стрельбе.,,Kahin'i bulun ve ona diğer Sigil parçalarını sorun. Ödülünüzü alın ve sağlık ve eğitim için sıhhiyeciye ve silah eğitmenine gidin. +奴はそこに隠れなければならないはず。プログラマーを見つけて殺す。","프로그래머 더미가 준 열쇠를 이용해서 프로그래머의 거주지로 향하는 문을 열어. 안에는 분명히 그가 있을 거야. 프로그래머를 찾으면, 일이 더 나빠지기 전에 죽여.",Gebruik de sleutel die de valse Programmer je gaf om een ingang te openen naar de wacht van de Programmeur. Het moet zijn waar hij zich verbergt. Zoek de Programmeur en vermoord hem.,Bruk nøkkelen den falske programmereren ga deg til å åpne en inngang til programmererens borg. Det må være der han gjemmer seg. Finn programmereren og drep ham.,"Użyj klucza, który dał ci fałszywy Programista, aby otworzyć wejście do kryjówki Programisty. To musi być miejsce, gdzie on się ukrywa. Znajdź Programistę i zabij go.",Use a chave que o falso Programador te deu para abrir uma entrada à fortaleza do Programador. Tem que ser onde ele está escondido. Encontre o Programador e mate-o.,,Folosește cheia pe care Programator fals ți-a dat-o pentru a deschide intrarea către curtea Programatorului. Trebuie să fie locul în care se ascunde. Găsește Programatorul și ucide-l.,"Используй ключ, полученный от фальшивого Программиста, чтобы открыть вход в цитадель. Скорее всего, именно там прячется настоящий Программист. Найди и убей его.",,Använd nyckeln som den falska programmeraren gav dig för att öppna en ingång till programmerarens borg. Det måste vara där han gömmer sig. Hitta Programmeraren och döda honom.,Sahte Programcı'nın size verdiği anahtarı kullanarak Programcı'nın kalesine bir giriş açın. Saklandığı yer orası olmalı. Programcıyı bul ve öldür. +Seek out the Oracle and ask it about the other Sigil pieces. Take your reward and go across to the medic and weapons trainer for health and training.,TXT_ILOG1019,MAP10: After killing the Programmer and talking to Macil.,,,Najdi Věštce a zeptej se ho na ostatní díly Pečetě. Převezmi si svou odměnu a navštiv zdravotníka a učitele střelby pro zdraví a výcvik.,Opsøg Oraklet og spørg det om de andre Sigil stykker. Tag din belønning og gå over til lægen og våbentræneren for at få sundhed og træning.,Suche das Orakel auf und frage es nach den anderen Sigil-Teilen. Nimm deine Belohnung und suche den Sanitäter und den Waffentrainer auf.,,,Busca al Oráculo y pregúntale sobre las otras piezas del Emblema. Ve al médico y al entrenador de armas para salud y entrenamiento.,,Etsi Oraakkeli ja kysy häneltä muista Sinetin osista. Vastaanota palkkiosi ja käy lääkintämiehen ja asekouluttajan luona terveydenhoitoa ja koulutusta varten.,"Trouve l'Oracle et demande lui où se trouve les autres pièces du Sigil. Récupère ta récompense, et va voir le médecin et le maître d'armes pour te soigner et t'entraîner.","Kutasd fel az Orákulumot, és érdeklődj a Pecsét további darabjairól. Zsebeld be a jutalmad, és költsd is el szépen a szanitécnál és a fegyvermesternél.",Raggiungi l'Oracolo e chiedigli degli altri pezzi del Sigillo. Prendi la tua ricompensa e visita il dottore e l'addestratore di armi.,"オラクルに会いシジルの欠片について尋ねる。 +強化のためメディックと武器トレーナーに会っておく。",오라클을 찾아서 다른 시질 조각이 어디에 있는지 물어봐. 보상을 받고 치료와 훈련을 위해 의무관과 무기 담당관에게로 가.,Zoek het Orakel op en vraag het over de andere Sigil stukken. Pak je beloning en ga naar de dokter en wapentrainer voor gezondheid en training.,Oppsøk oraklet og spør det om de andre sigil-brikke. Ta belønningen din og gå over til medisineren og våpentreneren for helse og trening.,Poszukaj Wyroczni i zapytaj ją o pozostałe kawałki Sigila. Odbierz nagrodę i przejdź do medyka i trenera broni po zdrowie i trening.,Procure o Oráculo e pergunte o sobre as outras peças do Sigilo. Pegue a sua recompensa e visite o médico e o treinador de armas para recuperar saúde e receber treinamento.,,Caută Oracolul și întreabă de celelalte piese de Sigiliu. Ia-ți recompensa și du-te la medic și antrenorul de arme.,Найди Оракула и спроси у него про другие фрагменты Печати. Возьми свою награду и посети медика и инструктора по стрельбе.,,Sök upp Oraklet och fråga det om de andra Sigilbitarna. Ta din belöning och gå över till läkaren och vapentränaren för hälsa och träning.,Kahin'i bulun ve ona diğer Sigil parçalarını sorun. Ödülünüzü alın ve sağlık ve eğitim için sıhhiyeciye ve silah eğitmenine gidin. "The second piece lies at the heart of the crimson and obsidian tower. There you must find the Bishop, who awaits you. Take the Oracle's token to the key master in the borderlands. Once you have destroyed the Bishop, return to the Oracle.",TXT_ILOG1020,,,,"Druhý díl leží v srdci věže karmíno-obsidiánové. Tam musíš najít Biskupa, který tě očekává. Vezmi Věštcův pas ke klíčníkovi v pohraničí. Až zabiješ Biskupa, vrať se k Věštci.","Den anden brik ligger i hjertet af det purpurfarvede og obsidianske tårn. Der skal du finde biskoppen, som venter på dig. Tag Oraklets token til nøglemesteren i grænselandet. Når du har udslettet biskoppen, skal du vende tilbage til Oraklet.","Das zweite Teilstück befindet sich im Turm aus Purpur und Obsidian. Dort musst du den Bischof finden, der dich erwartet. Bringe das Symbol des Orakels zum Schlüsselmeister in den Grenzgebieten. Wenn der Bischof ausgeschaltet ist, kehre zum Orakel zurück.",,,"La segunda pieza se encuentra en el corazón e la torre carmesí y obsidiana. Ahí debes encontrar al Obispo, quien espera por ti. Lleva el vale del Oráculo al amo de llaves en las fronteras. En cuanto hayas destruido al Obispo, regresa con el Oráculo.","La segunda pieza está en el corazón de la torre carmesí y obsidiana. Ahí deberás encontrar al Obispo, que te está esperando. Lleva el símbolo del Oráculo al Amo de Llaves en las fronteras. Cuando hayas destruido al Obispo, regresa con el Oráculo.","Toinen osanen piilee purppuranpunaisen laavalasisen tornin sydämessä. Sieltä sinun on löydettävä Piispa, joka odottaa sinua. Toimita Oraakkelin merkki avainmestarille rajaseudulla. Tuhottuasi Piispan palaa Oraakkelin luokse.","La deuxième pièce se trouve au cœur de la tour d'obsidienne et d'écarlate. Tu y trouveras l'évêque, qui t'attend. Amène le jeton de l'Oracle au maître des clés dans les terrains vagues. Quand tu as tué l'évêque, retourne voir l'Oracle.","A második darab a karmazsin és obszidián torony szívében található. Ott fogsz találkozni a már rád váró Püspökre. Vidd az Orákulum zálogát a peremvidéken élő kulcsmesterhez. Amint megölted a Püspököt, irány vissza az orákulumhoz.","Il secondo pezzo si trova nel cuore della torre cremisina e ossidiana. Lì troverai il Vescovo, che ti sta aspettando. Raggiungi il mastro delle chiavi nelle terre di confine. Quando hai distrutto il Vescovo, ritorna dall'Oracolo.","二つ目の欠片は深紅と黒曜石の塔の中心部にある。そこのビショップを討伐せよ。 国境地帯のコモンズ側にいるキーマスターにオラクルのトークンを見せる。 -ビショップを仕留めたらオラクルの元に戻る。","두 번째 시질 조각은 진홍빛 흑요석 탑에 숨어있는 비숍에게 있어. 거기에서 너를 기다리고 있는 비숍을 찾아내야만 해. 오라클의 통행증을 들고 접경지 안의 열쇠지기에게로 가봐. 비숍을 파괴했다면, 오라클에게 돌아가.","Het tweede stuk ligt in het hart van de karmozijnrode en obsidiaan toren. Daar moet je de bisschop vinden, die op je wacht. Breng de orakels naar de belangrijkste meester in de grensgebieden. Als je de bisschop hebt vernietigd, keer je terug naar het Orakel.","Den andre brikken ligger i hjertet av det purpurfargede og obsidianske tårnet. Der må du finne biskopen, som venter på deg. Ta orakelets symbol til nøkkelmesteren i grenselandene. Når du har tilintetgjort biskopen, gå tilbake til oraklet.","Drugi kawałek leży w sercu karmazynowej i obsydianowej wieży. Musisz tam odnaleźć biskupa, który czeka na Ciebie. Zabierz żeton wyroczni do mistrza kluczy na pograniczu. Po zniszczeniu Biskupa wróć do Wyroczni.","A segunda peça está no coração da torre carmesim e obsidiana. Lá você encontrará o Bispo, que está te aguardando. Leve o emblema do Oráculo para o mestre das chaves nas fronteiras. Após destruir o Bispo, volte ao Oráculo.",,A doua piesă e în inima turnului stăveziu din obsidian. Episcopul te va aștepta. Ia semnul Oracolului la stăpânul cheii în mărginime. După ce ai eliminat Episcopul întoarce-te la Oracol.,"Второй фрагмент лежит в сердце багрово-обсидиановой башни. Там ты встретишь Епископа, который ожидает тебя. Отнеси жетон Оракула ключнику в пограничье. Когда уничтожишь Епископа, возвращайся к Оракулу.",,İkinci parça kızıl ve obsidyen kulenin kalbinde yatıyor. Orada sizi bekleyen Piskopos'u bulmalısınız. Kahin'in jetonunu sınır bölgelerindeki anahtar ustasına götürün. Piskoposu yok ettikten sonra Kahin'e geri dönün. +ビショップを仕留めたらオラクルの元に戻る。","두 번째 시질 조각은 진홍빛 흑요석 탑에 숨어있는 비숍에게 있어. 거기에서 너를 기다리고 있는 비숍을 찾아내야만 해. 오라클의 통행증을 들고 접경지 안의 열쇠지기에게로 가봐. 비숍을 파괴했다면, 오라클에게 돌아가.","Het tweede stuk ligt in het hart van de karmozijnrode en obsidiaan toren. Daar moet je de bisschop vinden, die op je wacht. Breng de orakels naar de belangrijkste meester in de grensgebieden. Als je de bisschop hebt vernietigd, keer je terug naar het Orakel.","Den andre brikken ligger i hjertet av det purpurfargede og obsidianske tårnet. Der må du finne biskopen, som venter på deg. Ta orakelets symbol til nøkkelmesteren i grenselandene. Når du har tilintetgjort biskopen, gå tilbake til oraklet.","Drugi kawałek leży w sercu karmazynowej i obsydianowej wieży. Musisz tam odnaleźć biskupa, który czeka na Ciebie. Zabierz żeton wyroczni do mistrza kluczy na pograniczu. Po zniszczeniu Biskupa wróć do Wyroczni.","A segunda peça está no coração da torre carmesim e obsidiana. Lá você encontrará o Bispo, que está te aguardando. Leve o emblema do Oráculo para o mestre das chaves nas fronteiras. Após destruir o Bispo, volte ao Oráculo.",,A doua piesă e în inima turnului stăveziu din obsidian. Episcopul te va aștepta. Ia semnul Oracolului la stăpânul cheii în mărginime. După ce ai eliminat Episcopul întoarce-te la Oracol.,"Второй фрагмент лежит в сердце багрово-обсидиановой башни. Там ты встретишь Епископа, который ожидает тебя. Отнеси жетон Оракула ключнику в пограничье. Когда уничтожишь Епископа, возвращайся к Оракулу.",,Den andra biten finns i hjärtat av det karmosinröda och obsidianiska tornet. Där måste du hitta biskopen som väntar på dig. Ta Orakelns token till nyckelmästaren i gränslandet. När du har förintat biskopen ska du återvända till oraklet.,İkinci parça kızıl ve obsidyen kulenin kalbinde yatıyor. Orada sizi bekleyen Piskopos'u bulmalısınız. Kahin'in jetonunu sınır bölgelerindeki anahtar ustasına götürün. Piskoposu yok ettikten sonra Kahin'e geri dönün. "Find the crimson and obsidian tower. Use the id key the key master gave you to enter the tower. Once inside you must locate the Bishop. Once you have destroyed the Bishop, return to the Oracle.",TXT_ILOG1021,MAP11: After getting the Military ID from the keymaster.,,,"Najdi karmíno-obsidiánovou věž. Použij legitimaci, kterou ti dal klíčník, pro vstup do věže. Uvnitř musíš najít Biskupa. Až zabiješ Biskupa, vrať se k Věštci.","Find det purpurfarvede og obsidianske tårn. Brug den id-nøgle, som nøglemesteren gav dig, til at komme ind i tårnet. Når du er inde, skal du finde biskoppen. Når du har ødelagt biskoppen, skal du vende tilbage til Oracle.","Finde den Turm aus Purpur und Obsidian. Benutze den Schlüssel des Schlüsselmeisters um in den Turm hereinzukommen. In seinem Inneren musst du den Bischof finden. Wenn er ausgeschaltet ist, kehre zum Orakel zurück.",,,"Encuentra la torre carmesí y obsidiana. Usa la llabe que te dio el amo de llaves para entrar en la torre. Una vez dentro debes localizar al Obispo. Una vez hayas destruido al Obispo, regresa con el Oráculo.","Encuentra la torre carmesí y obsidiana. Usa la llave que te dio el Amo de Llaves para entrar en la torre. Una vez adentro localiza al Obispo. Una vez destruido el Obispo, regresa con el Oráculo.",Löydä purppuranpunainen laavalasinen torni. Käytä avainmestarin luovuttamaa tunnusta päästäksesi torniin. Sisään päästyäsi sinun on paikallistettava Piispa. Tuhottuasi hänet palaa Oraakkelin luokse.,"Trouve la tour d'obsidienne et d'écarlate. Utilise la carte magnétique que le maître des clés t'a donnée pour y entrer. A l'intérieur, trouve et tue l'évêque, puis retourne à l'Oracle.","Keresd fel a karamzsin és obszidián tornyot. A bejutáshoz használd az igazolványt amit a kulcsmester adott. Ha bejutottál, kutasd fel a Püspököt. Ha kiiktattad a Püspököt, menj vissza az Orákulumhoz.","Trova la torre cremisina e ossidiana. Con la chiave che ti ha dato il mastro delle chiavi, entra nella torre. Quando sei dentro, devi trovare il Vescovo. Dopo averlo distrutto, ritorna dall'Oracolo.","二つ目の欠片は深紅と黒曜石の塔の中心部にある。そこのビショップを討伐せよ。 キーマスターから貰ったIDキーを使って塔に入る。 -ビショップを仕留めたらオラクルの元に戻る。","진홍빛 흑요석 탑을 찾아. 열쇠지기가 준 신분증을 이용해서 탑으로 들어가. 탑 안으로 들어가서 비숍을 찾아야 해. 비숍을 파괴했다면, 오라클에게 돌아가.","Vind de karmozijnrode en obsidiaan toren. Gebruik de id-toets die de sleutelmeester je gaf om de toren te betreden. Eenmaal binnen moet je de bisschop lokaliseren. Als je de bisschop hebt vernietigd, ga je terug naar het Orakel.","Finn det purpurfargede og obsidianske tårnet. Bruk id-nøkkelen nøkkelmesteren ga deg for å komme inn i tårnet. Når du er inne, må du finne biskopen. Når du har ødelagt biskopen, gå tilbake til oraklet.","Znajdź wieżę z karmazynu i obsydianu. Użyj klucza id, który dał ci mistrz kluczy, aby wejść do wieży. Po wejściu do środka musisz zlokalizować Bishopa. Po zniszczeniu Bishopa wróć do Oracle.","Encontre a torre carmesim e obsidiana. Use a chave de identificação que o mestre da chaves te deu para entrar na torre. Após entrar, você deve localizar o Bispo. Após destruir o Bispo, volte ao Oráculo.",,"Găsește turnul străveziu din obsidian. Folosește cardul pe care ți l-a dat stăpânul cheilor pentru a intra. După aceea, găsește-l pe Episcop. Odată ce l-ai distrus, întoarce-te la Oracol.","Найди багрово-обсидиановую башню. Используй пропуск, полученный у ключника, чтобы войти внутрь. Там ты должен найти Епископа. Когда уничтожишь его, возвращайся к Оракулу.",,Kızıl ve obsidyen kuleyi bulun. Kuleye girmek için anahtar ustasının size verdiği kimlik anahtarını kullanın. İçeri girdikten sonra Piskoposu bulmalısınız. Piskoposu yok ettikten sonra Kahin'e geri dönün. +ビショップを仕留めたらオラクルの元に戻る。","진홍빛 흑요석 탑을 찾아. 열쇠지기가 준 신분증을 이용해서 탑으로 들어가. 탑 안으로 들어가서 비숍을 찾아야 해. 비숍을 파괴했다면, 오라클에게 돌아가.","Vind de karmozijnrode en obsidiaan toren. Gebruik de id-toets die de sleutelmeester je gaf om de toren te betreden. Eenmaal binnen moet je de bisschop lokaliseren. Als je de bisschop hebt vernietigd, ga je terug naar het Orakel.","Finn det purpurfargede og obsidianske tårnet. Bruk id-nøkkelen nøkkelmesteren ga deg for å komme inn i tårnet. Når du er inne, må du finne biskopen. Når du har ødelagt biskopen, gå tilbake til oraklet.","Znajdź wieżę z karmazynu i obsydianu. Użyj klucza id, który dał ci mistrz kluczy, aby wejść do wieży. Po wejściu do środka musisz zlokalizować Bishopa. Po zniszczeniu Bishopa wróć do Oracle.","Encontre a torre carmesim e obsidiana. Use a chave de identificação que o mestre da chaves te deu para entrar na torre. Após entrar, você deve localizar o Bispo. Após destruir o Bispo, volte ao Oráculo.",,"Găsește turnul străveziu din obsidian. Folosește cardul pe care ți l-a dat stăpânul cheilor pentru a intra. După aceea, găsește-l pe Episcop. Odată ce l-ai distrus, întoarce-te la Oracol.","Найди багрово-обсидиановую башню. Используй пропуск, полученный у ключника, чтобы войти внутрь. Там ты должен найти Епископа. Когда уничтожишь его, возвращайся к Оракулу.",,Hitta det karmosinröda och obsidianska tornet. Använd id-nyckeln som nyckelmästaren gav dig för att komma in i tornet. När du väl är inne måste du lokalisera biskopen. När du har förstört biskopen återvänder du till oraklet.,Kızıl ve obsidyen kuleyi bulun. Kuleye girmek için anahtar ustasının size verdiği kimlik anahtarını kullanın. İçeri girdikten sonra Piskoposu bulmalısınız. Piskoposu yok ettikten sonra Kahin'e geri dönün. "Find the security complex, fight through there and use the teleporter to central administration. Destroy the computer core in central administration. This will kill the force field on the Bishop's tower. Once the Bishop's dead, return to the Oracle.",TXT_ILOG1022,MAP17: After talking to Quincy.,,,"Najdi bezpečnostní komplex, probij se skrz a použij teleportér do ústřední administrace. Znič počítačové jádro v ústřední administraci. To zničí silové pole v Biskupově věži. Až zabiješ Biskupa, vrať se k Věštci.","Find sikkerhedskomplekset, kæmp dig igennem der og brug teleporteren til centraladministrationen. Ødelæg computerkernen i centraladministrationen. Dette vil dræbe kraftfeltet på Bishop's tårn. Når biskoppen er død, skal du vende tilbage til Oracle.","Finde den Sicherheitskomplex, kämpfe dich durch und benutze den Teleporter zur Zentralverwaltung. Zerstöre den Computer in der Verwaltung. Das wird alle Kraftfelder am Turm des Bischofs ausschalten. Wenn der Bischof ausgeschaltet ist, kehre zum Orakel zurück.",,,"Encuentra el complejo de seguridad, pelea a través de ahí y usa el teletransporte a administración central. Destruye el núcleo de la computadora en administración central. Esto apagará el campo de fuerza en la torre del Obispo. En cuanto el Obispo esté muerto, regresa con el Oráculo.",,"Löydä turvallisuuskeskus, taistele sen läpi ja kulje kaukosiirtimellä keskushallintoon. Tuhoa siellä keskustietokone. Se sammuttaa Piispan tornin voimakentän. Kun Piispa on kuollut, palaa Oraakkelin luo.","Trouve le complexe de sécurité. Bats-toi pour atteindre le téléporteur vers le centre d'administration. Détruis le cœur informatique qui s'y trouve. Cela désactivera le chap de force de la tour de l'évêque. Un fois qu'il est mort, retourne voir l'Oracle.","Keresd meg a biztonsági központot, harcold magad keresztül rajta, és használd a teleportot a központi adminisztrációhoz. Semmisítsd meg a számítógép magot a központi adminisztrációnál. Ez majd deaktiválja a Püspök tornyának az erőpajzsát. Ha meghalt a Püspök térj vissza az Orákulumhoz.","Trova il complesso di sicurezza, elimina chiunque ti sbarri la strada e trova il teletrasporto per l'amministrazione centrale. Distruggi il nucleo del computer nell'amministrazione centrale. Questo disattiverà il campo di forza nella torre del Vescovo. Quando il Vescovo sarà morto, ritorna dall'Oracolo.","複合警備所を見つけ、そこを制圧し中央管理所へのテレポーターを使う。 そして管理所のコンピューターコアを破壊する。 そうすればビショップの塔へのフォースフィールドを消せる。 -ビショップを仕留めたらオラクルの元に戻る。","보안 담당 기지를 찾고, 경비와 싸워가면서 중앙 처리 본부로 향하는 텔레포터를 사용해. 그곳에서 컴퓨터 중심부를 파괴해. 그러면 비숍의 탑의 보호막을 끌 수 있을 거야. 비숍을 죽이면, 오라클에게 돌아가.","Vind het veiligheidscomplex, vecht daar doorheen en gebruik de teleporter om de centrale administratie te besturen. Vernietig de computerkern in de centrale administratie. Dit zal het krachtveld op de Bisschopstoren doden. Zodra de bisschop dood is, keer je terug naar het Orakel.","Finn sikkerhetskomplekset, kjemp deg gjennom der og bruk teleporteren til sentraladministrasjonen. Ødelegg datakjernen i sentraladministrasjonen. Dette vil drepe kraftfeltet på biskopens tårn. Når biskopen er død, gå tilbake til Orakelet.","Znajdź kompleks bezpieczeństwa, walcz tam i użyj teleportera do centralnej administracji. Zniszcz rdzeń komputera w centralnej administracji. To zabije pole siłowe na wieży Bishopa. Gdy Bishop będzie już martwy, wróć do Oracle.","Encontre o complexo de segurança, lute através de lá e use o teletransportador na administração central. Destrua o núcleo de computação na administração central. Isso vai derrubar o campo de força na torre do Bispo. Após matar o Bispo, volte ao Oráculo.",,"Găsește complexul de securitate, intră în luptă, și folosește teleportorul către administrația centrală. Distruge nucleul calculatorului. Asta va distruge scutul din turnul Episcopului. Odată ce e mort, întoarce-te la Oracol.","Найди охранный комлекс, пробейся внутрь и используй телепорт до центральной администрации. Уничтожь компьютер. Это должно отключить силовое поле башни Епископа. Когда убьёшь Епископа, возвращайся к Оракулу.",,"Güvenlik kompleksini bulun, orada savaşın ve merkezi yönetime giden ışınlayıcıyı kullanın. Merkezi yönetimdeki bilgisayar çekirdeğini yok edin. Bu, Piskopos'un kulesindeki güç alanını öldürecektir. Piskopos öldükten sonra Kahin'e geri dönün." +ビショップを仕留めたらオラクルの元に戻る。","보안 담당 기지를 찾고, 경비와 싸워가면서 중앙 처리 본부로 향하는 텔레포터를 사용해. 그곳에서 컴퓨터 중심부를 파괴해. 그러면 비숍의 탑의 보호막을 끌 수 있을 거야. 비숍을 죽이면, 오라클에게 돌아가.","Vind het veiligheidscomplex, vecht daar doorheen en gebruik de teleporter om de centrale administratie te besturen. Vernietig de computerkern in de centrale administratie. Dit zal het krachtveld op de Bisschopstoren doden. Zodra de bisschop dood is, keer je terug naar het Orakel.","Finn sikkerhetskomplekset, kjemp deg gjennom der og bruk teleporteren til sentraladministrasjonen. Ødelegg datakjernen i sentraladministrasjonen. Dette vil drepe kraftfeltet på biskopens tårn. Når biskopen er død, gå tilbake til Orakelet.","Znajdź kompleks bezpieczeństwa, walcz tam i użyj teleportera do centralnej administracji. Zniszcz rdzeń komputera w centralnej administracji. To zabije pole siłowe na wieży Bishopa. Gdy Bishop będzie już martwy, wróć do Oracle.","Encontre o complexo de segurança, lute através de lá e use o teletransportador na administração central. Destrua o núcleo de computação na administração central. Isso vai derrubar o campo de força na torre do Bispo. Após matar o Bispo, volte ao Oráculo.",,"Găsește complexul de securitate, intră în luptă, și folosește teleportorul către administrația centrală. Distruge nucleul calculatorului. Asta va distruge scutul din turnul Episcopului. Odată ce e mort, întoarce-te la Oracol.","Найди охранный комлекс, пробейся внутрь и используй телепорт до центральной администрации. Уничтожь компьютер. Это должно отключить силовое поле башни Епископа. Когда убьёшь Епископа, возвращайся к Оракулу.",,"Hitta säkerhetskomplexet, kämpa dig igenom där och använd teleportern till centraladministrationen. Förstör datorkärnan i centralförvaltningen. Detta kommer att döda kraftfältet på biskopens torn. När biskopen är död återvänder du till oraklet.","Güvenlik kompleksini bulun, orada savaşın ve merkezi yönetime giden ışınlayıcıyı kullanın. Merkezi yönetimdeki bilgisayar çekirdeğini yok edin. Bu, Piskopos'un kulesindeki güç alanını öldürecektir. Piskopos öldükten sonra Kahin'e geri dönün." Your next challenge will test your spirit. The third piece is held by your own leader. He is the same as that which he sends you to kill. Confront him and resolve your fate.,TXT_ILOG1023,,,,"Tvá další výzva pokusí tvou vůli. Třetí díl je držen tvým vlastním vůdcem. Je stejný, jako ti, které tě posílá zabít. Postav se mu a rozhodni svůj osud.","Din næste udfordring vil teste din ånd. Den tredje brik holdes af din egen leder. Han er den samme som den, som han sender dig til at dræbe. Konfronter ham og løser din skæbne.","Die nächste Herausforderung wird deinen Geist prüfen. Das dritte Teilstück wird von deinem eigenen Anführer, Macil, gehalten. Er ist das Gleiche, was er dich töten lässt. Konfrontiere ihn und kläre dein Schicksal.",,,Tu siguiente desafío pondrá a prueba tu espíritu. La tercera pieza está en manos de tu propio líder. Él es lo mismo que te envía a matar. Confróntalo y resuelve tu destino.,Tú siguiente desafío probará tú espíritu. La tercera pieza la tiene tú propio líder. Él es igual que aquello que te envía a matar. Confróntalo y resuelve tú destino.,"Seuraava haasteesi koettelee sinua henkisesti. Kolmatta osasta pitää hallussaan oma päämiehesi. Hän on sama kuin se, jonka hän lähettää sinut surmaamaan. Kohtaa hänet ja päätä kohtalosi.",Le prochain défi testera votre esprit. Le troisième fragment est possédé par votre leader. Il est le même que celui qu'il vous a envoyé tuer. Confrontez-le et faites face à votre destinée.,"A következő próbatétel próbára teszi a lelkedet. A harmadik darab a saját vezérednél található. Egy és ugyanazon személy akit meg akar öletni veled. Szembesítsd vele, és dönts a sorsod felett.",La tua prossima sfida metterà alla prova il tuo spirito. Il terzo frammento è posseduto dal tuo stesso capo. Lui è uguale a quelli che ti manda ad uccidere. Affrontalo e risolvi il tuo destino.,"次の挑戦は己の精神が試される。三つ目の欠片は我々のリーダーが保持している。 -彼は貴方を殺すために送ったのと同等だと。彼に立ち向かい、己の運命を決断せよ。",다음 도전은 너의 정신을 시험할 거야. 세 번째 조각은 바로 우리의 지도자가 가지고 있어. 그는 너를 시켜서 죽였던 괴물들과 마찬가지인 존재지.,Je volgende uitdaging zal je geest testen. Het derde stuk wordt vastgehouden door je eigen leider. Hij is dezelfde die hij je stuurt om te doden. Confronteer hem en los je lot op.,Din neste utfordring vil sette din ånd på prøve. Den tredje brikken holdes av din egen leder. Han er den samme som han sender deg for å drepe. Konfronter ham og avgjør skjebnen din.,"Twoje kolejne wyzwanie przetestuje twojego ducha. Trzeci element jest w posiadaniu twojego własnego przywódcy. Jest on taki sam jak ten, którego wysyła do zabicia. Zmierz się z nim i rozstrzygnij swój los.",Seu próximo desafio testará o seu espírito. A terceira peça está com o seu próprio líder. Ele é a mesma pessoa que ele quer que você mate. Confronte-o e resolva o seu destino.,,Următoarea provocare îți va testa spiritul. A treia pieșă e ținută de propriul vostru lider. E același ca cel care vă trimite să ucideți. Înfruntă-l și împlinește-ți destinul.,"Следующее задание испытает силу твоего духа. Третий фрагмент у вашего лидера. Он сам — один из тех, кого вы убиваете по его приказу. Сразись с ним и исполни своё предназначение.",,Bir sonraki göreviniz ruhunuzu sınayacak. Üçüncü parça kendi lideriniz tarafından tutuluyor. Sizi öldürmeniz için gönderdiği kişiyle aynı. Onunla yüzleşin ve kaderinizi belirleyin. -"It is the Oracle who holds the third piece. There's your traitor. Return to the Oracle, and take him down. Return to me when it's dead.",TXT_ILOG1024,,,,"Věštec je ten, kdo má u sebe třetí díl. On je ten zrádce. Vrať se k němu a zabij ho. Vrať se ke mě, až bude mrtvý.","Det er Oraklet, der har den tredje brik. Der er din forræder. Vend tilbage til Oraklet, og nedlæg ham. Vend tilbage til mig, når det er dødt.","Es ist das Orakel, das das dritte Teilstück besitzt. Es ist der Verräter. Kehre zu ihm zurück und schalte es aus. Kehre zurück, wenn es tot ist.",,,Es el Oráculo quien tiene la tercera pieza. Ahí está tu traidor. Regresa al Oráculo y acaba con él. Regresa a mí cuando esté muerto.,Es el Oráculo el que tiene la tercera pieza. Ahí está tú traidor. Regresa con el Oráculo y acaba con él. Regresa a mí cuando esté muerto.,Kolmas osanen on Oraakkelin hallussa. Siinä on petturisi. Palaa Oraakkelin luo ja poista hänet päiväjärjestyksestä. Palaa luokseni hänen kuoltuaan.,"C'est l'Oracle qui détient la troisième pièce, est c'est lui qui est le traître. Retourne le voir et détruis-le. Retourne à la base quand il est mort.","Az Orákulumnál található a harmadik darab. Ő lesz az árulód. Térj vissza az Orákulumhoz, és tedd el láb alól. Ha megtörtént, gyere vissza.","È l'Oracolo che tiene il terzo pezzo. Ecco chi è il traditore. Ritorna dall'Oracolo, e fallo fuori. Ritorna da me quando lo hai ucciso.","三つ目の欠片を持つのはオラクルだ。あいつが裏切者だ。 -オラクルの所に戻り討ち倒せ。終わったらマシルの元に戻る。",오라클이 세 번째 조각을 가지고 있어. 그가 배신자야! 오라클을 찾아서 혼쭐을 낸 뒤 마실에게 돌아와.,"Het is het Orakel dat het derde deel vasthoudt. Daar is je verrader. Ga terug naar het Orakel, en neem hem mee naar beneden. Keer terug naar mij als het dood is.",Det er oraklet som har den tredje brikken. Der er forræderen din. Gå tilbake til oraklet og drep ham. Kom tilbake til meg når den er død.,"To Wyrocznia jest w posiadaniu trzeciego kawałka. Oto twój zdrajca. Wróć do Wyroczni i załatw go. Wróć do mnie, gdy będzie martwy.",É o Oráculo que possui a terceira peça. Esse é o seu traidor. Volte ao Oráculo e elimine-o. Volte para mim quando ele estiver morto.,,"E Oracolul cel care deține ultima piesă. Acolo e trădătorul. Întoarce-te la Oracol, și răpune-l. Întoarce-te la mine când ai terminat.",Третий фрагмент хранится у Оракула. Так и кто же из нас предатель? Вернись к Оракулу и расправься с ним. Доложи мне о его смерть.,,Üçüncü parçayı elinde tutan Kahin. İşte haininiz. Kahin'e dön ve onu indir. Öldüğünde bana geri dön. +彼は貴方を殺すために送ったのと同等だと。彼に立ち向かい、己の運命を決断せよ。",다음 도전은 너의 정신을 시험할 거야. 세 번째 조각은 바로 우리의 지도자가 가지고 있어. 그는 너를 시켜서 죽였던 괴물들과 마찬가지인 존재지.,Je volgende uitdaging zal je geest testen. Het derde stuk wordt vastgehouden door je eigen leider. Hij is dezelfde die hij je stuurt om te doden. Confronteer hem en los je lot op.,Din neste utfordring vil sette din ånd på prøve. Den tredje brikken holdes av din egen leder. Han er den samme som han sender deg for å drepe. Konfronter ham og avgjør skjebnen din.,"Twoje kolejne wyzwanie przetestuje twojego ducha. Trzeci element jest w posiadaniu twojego własnego przywódcy. Jest on taki sam jak ten, którego wysyła do zabicia. Zmierz się z nim i rozstrzygnij swój los.",Seu próximo desafio testará o seu espírito. A terceira peça está com o seu próprio líder. Ele é a mesma pessoa que ele quer que você mate. Confronte-o e resolva o seu destino.,,Următoarea provocare îți va testa spiritul. A treia pieșă e ținută de propriul vostru lider. E același ca cel care vă trimite să ucideți. Înfruntă-l și împlinește-ți destinul.,"Следующее задание испытает силу твоего духа. Третий фрагмент у вашего лидера. Он сам — один из тех, кого вы убиваете по его приказу. Сразись с ним и исполни своё предназначение.",,Din nästa utmaning kommer att sätta din anda på prov. Den tredje biten innehas av din egen ledare. Han är densamma som den som han skickar dig att döda. Konfrontera honom och lös ditt öde.,Bir sonraki göreviniz ruhunuzu sınayacak. Üçüncü parça kendi lideriniz tarafından tutuluyor. Sizi öldürmeniz için gönderdiği kişiyle aynı. Onunla yüzleşin ve kaderinizi belirleyin. +"It is the Oracle who holds the third piece. There's your traitor. Return to the Oracle, and take him down. Return to me when it's dead.",TXT_ILOG1024,MAP10: You chose to kill the Oracle.,,,"Věštec je ten, kdo má u sebe třetí díl. On je ten zrádce. Vrať se k němu a zabij ho. Vrať se ke mě, až bude mrtvý.","Det er Oraklet, der har den tredje brik. Der er din forræder. Vend tilbage til Oraklet, og nedlæg ham. Vend tilbage til mig, når det er dødt.","Es ist das Orakel, das das dritte Teilstück besitzt. Es ist der Verräter. Kehre zu ihm zurück und schalte es aus. Kehre zurück, wenn es tot ist.",,,Es el Oráculo quien tiene la tercera pieza. Ahí está tu traidor. Regresa al Oráculo y acaba con él. Regresa a mí cuando esté muerto.,,Kolmas osanen on Oraakkelin hallussa. Siinä on petturisi. Palaa Oraakkelin luo ja poista hänet päiväjärjestyksestä. Palaa luokseni hänen kuoltuaan.,"C'est l'Oracle qui détient la troisième pièce, est c'est lui qui est le traître. Retourne le voir et détruis-le. Retourne à la base quand il est mort.","Az Orákulumnál található a harmadik darab. Ő lesz az árulód. Térj vissza az Orákulumhoz, és tedd el láb alól. Ha megtörtént, gyere vissza.","È l'Oracolo che tiene il terzo pezzo. Ecco chi è il traditore. Ritorna dall'Oracolo, e fallo fuori. Ritorna da me quando lo hai ucciso.","三つ目の欠片を持つのはオラクルだ。あいつが裏切者だ。 +オラクルの所に戻り討ち倒せ。終わったらマシルの元に戻る。",오라클이 세 번째 조각을 가지고 있어. 그가 배신자야! 오라클을 찾아서 혼쭐을 낸 뒤 마실에게 돌아와.,"Het is het Orakel dat het derde deel vasthoudt. Daar is je verrader. Ga terug naar het Orakel, en neem hem mee naar beneden. Keer terug naar mij als het dood is.",Det er oraklet som har den tredje brikken. Der er forræderen din. Gå tilbake til oraklet og drep ham. Kom tilbake til meg når den er død.,"To Wyrocznia jest w posiadaniu trzeciego kawałka. Oto twój zdrajca. Wróć do Wyroczni i załatw go. Wróć do mnie, gdy będzie martwy.",É o Oráculo que possui a terceira peça. Esse é o seu traidor. Volte ao Oráculo e elimine-o. Volte para mim quando ele estiver morto.,,"E Oracolul cel care deține ultima piesă. Acolo e trădătorul. Întoarce-te la Oracol, și răpune-l. Întoarce-te la mine când ai terminat.",Третий фрагмент хранится у Оракула. Так и кто же из нас предатель? Вернись к Оракулу и расправься с ним. Доложи мне о его смерть.,,Det är oraklet som innehar den tredje biten. Där har du din förrädare. Återvänd till Oraklet och ta ner honom. Återvänd till mig när den är död.,Üçüncü parçayı elinde tutan Kahin. İşte haininiz. Kahin'e dön ve onu indir. Öldüğünde bana geri dön. "You have cut the cancer from your body, but your heart still beats. Next you must find the surgeon who butchers and controls your people.... The Loremaster. Stop him, and the next piece will be yours.",TXT_ILOG1025,,,,"Vyřízl jsi rakovinu ze svého těla, tvé srdce však stále bije. Dále musíš najít doktora, jenž vraždí a ovládá tvé druhy, Dějepisce. Učiň mu přítrž a další díl bude tvůj.","Du har fjernet kræften fra din krop, men dit hjerte slår stadig. Nu skal du finde den kirurg, der slagter og kontrollerer dit folk.... Loremesteren. Stop ham, og det næste stykke vil blive dit.","Du hast das Geschwür aus deinem Körper entferrnt, aber dein Herz schlägt noch. Als Nächstes musst du den Wissensmeister finden, der deine Leute kontrolliert und abschlachtet. Stoppe ihn und das nächste Teilstück ist Dein.",,,"Has cortado el cáncer de tu cuerpo, pero tu corazón aún late. Ahora debes encontrar al cirujano que destroza y controla a tu gente... El Maestro del Conocimiento. Detenlo, y la siguiente pieza será tuya.","Haz cortado el cáncer de tu cuerpo, pero tú corazón todavía late. Ahora debes encontrar al cirujano que encarniza y controla a tú gente... El Maestro del Conocimiento. Deténlo y la siguiente pieza será tuya.","Olet erottanut syövän ruumiistasi, mutta sydämesi silti sykkii. Seuraavaksi pitää sinun löytämän kirugin, joka teurastaa ja hallitsee kansaasi: Oppi-Isän. Pysäytä hänet, ja seuraava osanen on oleva sinun.","Vous avez arraché le cancer de votre corps, mais le cœur bat encore. Vous devez maintenant trouver le chirurgien qui massacre votre peuple, le Maître des traditions. Arrètez-le, et le fragment suivant sera le vôtre.","Kivágtad a rákos részt a szívedből, de az még mindig ver. A következő lépés, hogy felkutatod a sebészt aki lemészárolja és irányítja a néped...a Tanmestert. Állítsd meg , és a következő darab a tied.","Hai eliminato il cancro dal tuo corpo, ma il tuo cuore batte ancora. Adesso devi trovare il chirurgo che macella e controlla la tua gente, il Sapiente. Fermalo e il prossimo pezzo sarà tuo.","己の癌は切除したが動揺は隠せないままだ。 次の欠片は人々を虐殺で支配する外科医... -ロアマスターが所持している。奴を止め、欠片を自分の物にする。","네 몸 안의 암 덩어리를 잘라냈지만, 심장은 여전히 뛰고 있네. 다음은 우리를 향한 도살과 지배를 책임졌던 과학자, 로어마스터를 찾아내야 해. 그를 막아내면, 다음 조각을 얻을 수 있을 거야.","Je hebt de kanker uit je lichaam gesneden, maar je hart klopt nog steeds. Vervolgens moet je de chirurg vinden die je mensen afmaakt en controleert....... De Kennismeester. Stop hem, en het volgende stuk zal van jou zijn.","Du har fjernet kreften fra kroppen din, men hjertet ditt slår fortsatt. Nå må du finne kirurgen som slakter og kontrollerer folket ditt...... .... Loremesteren. Stopp ham, og det neste stykket blir ditt.","Wyciąłeś raka ze swojego ciała, ale twoje serce wciąż bije. Następnie musisz znaleźć chirurga, który rzeźbi i kontroluje twoich ludzi.... Loremaster. Powstrzymaj go, a następny kawałek będzie twój.","Você arrancou o câncer do seu corpo, mas seu coração ainda bate. Agora você deve encontrar o cirurgião que mutila e controla o seu povo... o Mestre do Conhecimento. Detenha-o e a próxima peça será sua.",,"Ai tăiat cancerul din corp, dar inima ta încă bate. Mai departe trebuie să găsești pe chirurgul care vă masacrează oamenii.... Maestrul Cunoștiințelor. Oprește-l, și următoarea piesă va fii a ta.","Ты вырезал опухоль из своего тела, но твоё сердце всё ещё бьётся. Теперь тебе предстоит найти вивисектора, который вскрывает твоих людей и управляет ими — Хранителя мудрости. Останови его, и следующий фрагмент твой.",,"Kanseri vücudundan attın ama kalbin hala atıyor. Şimdi insanlarını kesen ve kontrol eden cerrahı bulmalısın.... Loremaster. Onu durdurursan, bir sonraki parça senin olacak." +ロアマスターが所持している。奴を止め、欠片を自分の物にする。","네 몸 안의 암 덩어리를 잘라냈지만, 심장은 여전히 뛰고 있네. 다음은 우리를 향한 도살과 지배를 책임졌던 과학자, 로어마스터를 찾아내야 해. 그를 막아내면, 다음 조각을 얻을 수 있을 거야.","Je hebt de kanker uit je lichaam gesneden, maar je hart klopt nog steeds. Vervolgens moet je de chirurg vinden die je mensen afmaakt en controleert....... De Kennismeester. Stop hem, en het volgende stuk zal van jou zijn.","Du har fjernet kreften fra kroppen din, men hjertet ditt slår fortsatt. Nå må du finne kirurgen som slakter og kontrollerer folket ditt...... .... Loremesteren. Stopp ham, og det neste stykket blir ditt.","Wyciąłeś raka ze swojego ciała, ale twoje serce wciąż bije. Następnie musisz znaleźć chirurga, który rzeźbi i kontroluje twoich ludzi.... Loremaster. Powstrzymaj go, a następny kawałek będzie twój.","Você arrancou o câncer do seu corpo, mas seu coração ainda bate. Agora você deve encontrar o cirurgião que mutila e controla o seu povo... o Mestre do Conhecimento. Detenha-o e a próxima peça será sua.",,"Ai tăiat cancerul din corp, dar inima ta încă bate. Mai departe trebuie să găsești pe chirurgul care vă masacrează oamenii.... Maestrul Cunoștiințelor. Oprește-l, și următoarea piesă va fii a ta.","Ты вырезал опухоль из своего тела, но твоё сердце всё ещё бьётся. Теперь тебе предстоит найти вивисектора, который вскрывает твоих людей и управляет ими — Хранителя мудрости. Останови его, и следующий фрагмент твой.",,"Du har skurit bort cancern från din kropp, men ditt hjärta slår fortfarande. Nu måste du hitta kirurgen som slaktar och kontrollerar ditt folk.... Läromästaren. Stoppa honom och nästa del blir din.","Kanseri vücudundan attın ama kalbin hala atıyor. Şimdi insanlarını kesen ve kontrol eden cerrahı bulmalısın.... Loremaster. Onu durdurursan, bir sonraki parça senin olacak." "Next you must find the surgeon who butchers and controls your people.... The Loremaster. Stop him, and the next piece will be yours. Use the teleporter I opened to reach him. When he's dead, use the same device to return to me.",TXT_ILOG1026,,,,"Vyřízl jsi rakovinu ze svého těla, tvé srdce však stále bije. Dále musíš najít doktora, jenž vraždí a ovládá tvé druhy, Dějepisce. Učiň mu přítrž a další díl bude tvůj. Použij teleportér, který jsem otevřel, aby ses k němu dostal. Když je mrtev, použij stejné zařízení k návratu ke mě.","Dernæst skal du finde den kirurg, der slagter og kontrollerer dit folk.... Loremesteren. Stop ham, og den næste del bliver din. Brug teleporteren, som jeg åbnede for at nå ham. Når han er død, skal du bruge den samme anordning til at vende tilbage til mig.","Als Nächstes musst du den Wissensmeister finden, der deine Leute kontrolliert und abschlachtet. Stoppe ihn und das nächste Teilstück ist Dein. Benutze den Teleporter, den ich geöffnet habe, um zu ihm zu gelangen. Wenn er tot ist kehre auf dem gleichen Weg zurück.",,,"Ahora debes encontrar al cirujano que destroza y controla a tu gente... El Maestro del Conocimiento. Detenlo, y la siguiente pieza será tuya. Usa el teletransporte que he abierto para alcanzarlo. Cuando esté muerto, usa el mismo dispositivo para regresar a mí.","Ahora debes encontrar al cirujano que encarniza y controla a tú gente... El Maestro del Conocimiento. Deténlo y la siguiente pieza será tuya. Usa el teleporte que he abierto para alcanzarlo. Cuando esté muerto, usa el mismo dispositivo para regresar conmigo.","Seuraavaksi pitää sinun löytämän kirugin, joka teurastaa ja hallitsee kansaasi: Oppi-Isän. Pysäytä hänet, ja seuraava osanen on oleva sinun. Käytä avaamaani kaukosiirrintä tavoittaaksesi hänet. Kun hän on kuollut, käytä samaa laitetta palataksesi tyköni.","Vous devez maintenant trouver le chirurgien qui massacre votre peuple, le Maître des traditions. Arrètez-le, et le fragment suivant sera le vôtre. Utilisez le téléporter qui s'est ouvert pour l'atteindre. Quand il est mort, utilisez le même téléporteur pour retourner à l'Oracle.","A következő lépés, hogy felkutatod a sebészt aki lemészárolja és irányítja a néped...a Tanmestert. Állítsd meg és a következő darab a tied. Most nyitottam ki ezt a teleportot, használd hogy eljuss hozzá. Ha meghalt, használd ugyanezt a visszaútra is.","Adesso devi trovare il chirurgo che macella e controlla la tua gente, il Sapiente. Fermalo e il prossimo pezzo sarà tuo. Usa il teletrasporto che ho sbloccato per raggiungere il Sapiente. Quando è morto, usa lo stesso teletrasporto per tornare da me.","次の欠片は人々を虐殺で支配する外科医... ロアマスターが所持している。奴を止め、欠片を自分の物にする。 -近辺へのテレポーターを使い、奴が死んだら再びテレポーターから戻る。","우리를 향한 도살과 지배를 책임졌던 과학자, 로어마스터를 찾아내야 해. 그를 막아내면, 다음 조각을 얻을 수 있을 거야. 오라클이 열어준 텔레포터를 이용해서 그를 찾아. 그가 죽으면 같은 장치를 이용해서 오라클에게 돌아와.","Vervolgens moet u de chirurg vinden die uw mensen afslacht en onder controle heeft....... De Kennismeester. Stop hem, en het volgende stuk zal van jou zijn. Gebruik de teleporter die ik geopend heb om hem te bereiken. Als hij dood is, gebruik dan hetzelfde apparaat om terug te keren naar mij.","Deretter må du finne kirurgen som slakter og kontrollerer folket ditt.... Loremesteren. Stopp ham, og den neste brikken blir din. Bruk teleporteren jeg åpnet for å nå ham. Når han er død, bruk samme apparat for å komme tilbake til meg.","Następnie musisz znaleźć chirurga, który rzeźbi i kontroluje twoich ludzi.... Loremaster. Zatrzymaj go, a następny kawałek będzie twój. Użyj teleportera, który otworzyłem, aby do niego dotrzeć. Gdy będzie martwy, użyj tego samego urządzenia, by wrócić do mnie.","Agora você deve encontrar o cirurgião que mutila e controla o seu povo... o Mestre do Conhecimento. Detenha-o e a próxima peça será sua. Use o teletransportador que eu abri para chegar até ele. Quando ele estiver morto, use o mesmo dispositivo e volte até mim.",,"Mai departe trebuie să găsești chirurgul care vă masacrează oameni.... Maestrul Cunoștiințelor. Oprește-l, și următoarea piesă va fii a ta.","Тебе предстоит найти вивисектора, который вскрывает твоих людей и управляет ими — Хранителя мудрости. Останови его, и следующий фрагмент твой. Используй открытый мной телепорт, чтобы добраться до него. Когда он умрёт, найди другой телепорт и вернись ко мне.",,"Şimdi halkını katleden ve kontrol eden cerrahı bulmalısın.... Loremaster. Onu durdurun ve bir sonraki parça sizin olsun. Ona ulaşmak için açtığım ışınlayıcıyı kullan. O öldüğünde, bana dönmek için aynı cihazı kullan." -You have chosen wisely. The third piece is held by your own leader. Destroy that which hides within your heart and return to me.,TXT_ILOG1027,,,,"Rozhodl ses moudře. Třetí díl je držen tvým vlastním vůdcem. Znič to, co se skrývá v tvém srdci, a vrať se ke mně.","Du har truffet et klogt valg. Den tredje brik er i hænderne på din egen leder. Ødelæg det, der gemmer sig i dit hjerte, og vend tilbage til mig.","Du hast weise entschieden. as dritte Teilstück wird von deinem eigenen Anführer, Macil, gehalten. Vernichte, was sich in eurem Herzen versteckt und kehre zu mir zurück.",,,Has elegido sabiamente. La tercera pieza está en manos de tu propio líder. Destroye lo que se esconde en tu corazón y regresa a mí.,Haz escogido sabiamente. La tercera pieza la tiene tú propio líder. Destruye aquello que se oculta en tú corazón y regresa conmigo.,"Olet valinnut viisaasti. Kolmatta osasta pitää hallussaan oma päämiehesi. Tuhoa se, mikä piilee sisällä sydämessäsi ja palaa tyköni.",Vous avez sagement choisi. La troisième pièce est détenue par votre propre leader. Détruisez ce qui se tapit dans son cœur et revenez à moi.,"Bölcsen döntöttél. A harmadik darab a saját vezérednél található. Semmisítsd meg a szíved mélyén megbúvó sötétséget, és térj vissza.",Hai fatto la scelta giusta. Il terzo pezzo è in possesso del tuo stesso capo. Distruggi ciò che si nasconde dentro il tuo cuore e ritorna da me.,"貴方は賢い判断をした。三つ目の欠片は我々のリーダーが保持している。 +近辺へのテレポーターを使い、奴が死んだら再びテレポーターから戻る。","우리를 향한 도살과 지배를 책임졌던 과학자, 로어마스터를 찾아내야 해. 그를 막아내면, 다음 조각을 얻을 수 있을 거야. 오라클이 열어준 텔레포터를 이용해서 그를 찾아. 그가 죽으면 같은 장치를 이용해서 오라클에게 돌아와.","Vervolgens moet u de chirurg vinden die uw mensen afslacht en onder controle heeft....... De Kennismeester. Stop hem, en het volgende stuk zal van jou zijn. Gebruik de teleporter die ik geopend heb om hem te bereiken. Als hij dood is, gebruik dan hetzelfde apparaat om terug te keren naar mij.","Deretter må du finne kirurgen som slakter og kontrollerer folket ditt.... Loremesteren. Stopp ham, og den neste brikken blir din. Bruk teleporteren jeg åpnet for å nå ham. Når han er død, bruk samme apparat for å komme tilbake til meg.","Następnie musisz znaleźć chirurga, który rzeźbi i kontroluje twoich ludzi.... Loremaster. Zatrzymaj go, a następny kawałek będzie twój. Użyj teleportera, który otworzyłem, aby do niego dotrzeć. Gdy będzie martwy, użyj tego samego urządzenia, by wrócić do mnie.","Agora você deve encontrar o cirurgião que mutila e controla o seu povo... o Mestre do Conhecimento. Detenha-o e a próxima peça será sua. Use o teletransportador que eu abri para chegar até ele. Quando ele estiver morto, use o mesmo dispositivo e volte até mim.",,"Mai departe trebuie să găsești chirurgul care vă masacrează oameni.... Maestrul Cunoștiințelor. Oprește-l, și următoarea piesă va fii a ta.","Тебе предстоит найти вивисектора, который вскрывает твоих людей и управляет ими — Хранителя мудрости. Останови его, и следующий фрагмент твой. Используй открытый мной телепорт, чтобы добраться до него. Когда он умрёт, найди другой телепорт и вернись ко мне.",,Nästa steg är att hitta kirurgen som slaktar och kontrollerar ditt folk.... Läromästaren. Stoppa honom och nästa del blir din. Använd teleportern som jag öppnade för att nå honom. När han är död använder du samma apparat för att återvända till mig.,"Şimdi halkını katleden ve kontrol eden cerrahı bulmalısın.... Loremaster. Onu durdurun ve bir sonraki parça sizin olsun. Ona ulaşmak için açtığım ışınlayıcıyı kullan. O öldüğünde, bana dönmek için aynı cihazı kullan." +You have chosen wisely. The third piece is held by your own leader. Destroy that which hides within your heart and return to me.,TXT_ILOG1027,MAP12: You chose to kill Macil.,,,"Rozhodl ses moudře. Třetí díl je držen tvým vlastním vůdcem. Znič to, co se skrývá v tvém srdci, a vrať se ke mně.","Du har truffet et klogt valg. Den tredje brik er i hænderne på din egen leder. Ødelæg det, der gemmer sig i dit hjerte, og vend tilbage til mig.","Du hast weise entschieden. as dritte Teilstück wird von deinem eigenen Anführer, Macil, gehalten. Vernichte, was sich in eurem Herzen versteckt und kehre zu mir zurück.",,,Has elegido sabiamente. La tercera pieza está en manos de tu propio líder. Destroye lo que se esconde en tu corazón y regresa a mí.,,"Olet valinnut viisaasti. Kolmatta osasta pitää hallussaan oma päämiehesi. Tuhoa se, mikä piilee sisällä sydämessäsi ja palaa tyköni.",Vous avez sagement choisi. La troisième pièce est détenue par votre propre leader. Détruisez ce qui se tapit dans son cœur et revenez à moi.,"Bölcsen döntöttél. A harmadik darab a saját vezérednél található. Semmisítsd meg a szíved mélyén megbúvó sötétséget, és térj vissza.",Hai fatto la scelta giusta. Il terzo pezzo è in possesso del tuo stesso capo. Distruggi ciò che si nasconde dentro il tuo cuore e ritorna da me.,"貴方は賢い判断をした。三つ目の欠片は我々のリーダーが保持している。 貴方の胸中に隠れているものを払い彼の元に戻る。 -",좋은 판단이야. 세 번째 시질 조각은 마실이 가지고 있어. 그를 죽여서 조각을 얻은 뒤 오라클에게 돌아와.,Je hebt verstandig gekozen. Het derde stuk wordt vastgehouden door je eigen leider. Vernietig datgene wat zich in je hart verbergt en keer terug naar mij.,"Du har valgt klokt. Den tredje brikken holdes av din egen leder. Ødelegg det som skjuler seg i hjertet ditt, og vend tilbake til meg.","Mądrze wybrałeś. Trzeci kawałek jest w posiadaniu twojego własnego przywódcy. Zniszcz to, co kryje się w twoim sercu i wróć do mnie.",Você escolheu sabiamente. A terceira peça está com o seu próprio líder. Destrua aquilo que se esconde em seu coração e volte a mim.,,Ai ales înțelept. A treia piesă e deținută de liderul vostru. Distruge ceea ce se ascunde în inima ta și întoarce-te la mine.,"Мудрый выбор. Третий фрагмент у вашего лидера. Уничтожь то, что закралось в твоё сердце, и возвращайся ко мне.",,Akıllıca bir seçim yaptın. Üçüncü parça kendi liderinizin elinde. Kalbinde sakladığın şeyi yok et ve bana dön. -"We've found out that the Order is transforming our people into bio-mechanical soldiers. Find the facility where this is being done and close it, permanently! Find Richter in the commons, near the waterfall and he'll tell you how to stop this atrocity.",TXT_ILOG1028,,,,"Zjistili jsme, že Řád přeměňuje naše lidi na biomechanické vojáky. Najdi továrnu, kde se tohle odehrává, a zavři ji, natrvalo. Najdi Richtera na návsi u vodopádů. Řekne ti, jak zastavit tuto ohavnost.","Vi har fundet ud af, at Ordenen forvandler vores folk til biomekaniske soldater. Find det sted, hvor det sker, og luk det for altid! Find Richter i fællesarealerne, nær vandfaldet, og han vil fortælle dig, hvordan du kan stoppe denne grusomhed.","Wir haben herausgefunden, dass der Orden unsere Leute nicht tötet, sondern sie transformiert - int biomechanische Soldaten.Finde die Einrichtung, wo dies passiert und schließe sie - endgültig. Suche Richter beim Wasserfall bei der Mensa. Er wird dir sagen, wie du diese Abscheulichkeit abschaklten kannst.",,,"Hemos descubierto que la Orden está transformando a nuestra gente en soldados biomecánicos. Encuentra la instalación donde esto se está haciendo y ciérrala, ¡Permanentemente! Encuentra a Richter en los comunes, junto a la cascada y te dirá como detener esta atrocidad.","Hemos descubierto que la Orden está transformando a nuestra gente en soldado bio-mecánicos. ¡Encuentra la facilidad donde se está realizando esto y cierrala permanentemente! Encuentra a Richter en los comunes, cerca de la cascada y él te dirá como detener esta atrocidad.","Olemme saaneet selville, että Veljeskunta muuntelee meidän omiamme biomekaanisiksi sotilaiksi. Etsi laitos, jossa tätä tehdään, ja lakkauta se, pysyvästi! Etsi Richter messistä vesiputouksen läheltä, ja hän kertoo sinulle, miten lopettaa tämä kauhistus.",Nous avons découvert que l'Ordre transforme notre peuple en soldats biomécaniques. Trouve l'usine où cela se déroule et détruis-la pour toujours! Trouve Richter dans le Réfectoire près de la cascade et il t'expliquera comment stopper cette atrocité.,"Kiderítettük, hogy a Rend bio-mechanikus katonákká alakítja az embertársainkat. Keresd meg a létesítményt ahol ezt csinálják, és zárd be örökre! Keresd fel Richtert a vízesés melletti étkezdénél, Ő majd elmondja hogyan tudod megállítani ezt a borzalmat.","Abbiamo scoperto che l'Ordine sta trasformando la nostra gente in soldati bio-meccanici. Trova lo stabilimento dove questo sta avvenendo e chiuderlo, permanentemente. Trova Richter nei comuni, accanto alla cascata, e ti spiegherà come fermare questa atrocità.","我等はオーダーが人々をサイボーグ兵に改造しつつある事を発見した。 +",좋은 판단이야. 세 번째 시질 조각은 마실이 가지고 있어. 그를 죽여서 조각을 얻은 뒤 오라클에게 돌아와.,Je hebt verstandig gekozen. Het derde stuk wordt vastgehouden door je eigen leider. Vernietig datgene wat zich in je hart verbergt en keer terug naar mij.,"Du har valgt klokt. Den tredje brikken holdes av din egen leder. Ødelegg det som skjuler seg i hjertet ditt, og vend tilbake til meg.","Mądrze wybrałeś. Trzeci kawałek jest w posiadaniu twojego własnego przywódcy. Zniszcz to, co kryje się w twoim sercu i wróć do mnie.",Você escolheu sabiamente. A terceira peça está com o seu próprio líder. Destrua aquilo que se esconde em seu coração e volte a mim.,,Ai ales înțelept. A treia piesă e deținută de liderul vostru. Distruge ceea ce se ascunde în inima ta și întoarce-te la mine.,"Мудрый выбор. Третий фрагмент у вашего лидера. Уничтожь то, что закралось в твоё сердце, и возвращайся ко мне.",,Du har valt klokt. Den tredje biten innehas av din egen ledare. Förstör det som gömmer sig i ditt hjärta och återvänd till mig.,Akıllıca bir seçim yaptın. Üçüncü parça kendi liderinizin elinde. Kalbinde sakladığın şeyi yok et ve bana dön. +"We've found out that the Order is transforming our people into bio-mechanical soldiers. Find the facility where this is being done and close it, permanently! Find Richter in the commons, near the waterfall and he'll tell you how to stop this atrocity.",TXT_ILOG1028,MAP10: After killing the Oracle and talking to Macil.,,,"Zjistili jsme, že Řád přeměňuje naše lidi na biomechanické vojáky. Najdi továrnu, kde se tohle odehrává, a zavři ji, natrvalo. Najdi Richtera na návsi u vodopádů. Řekne ti, jak zastavit tuto ohavnost.","Vi har fundet ud af, at Ordenen forvandler vores folk til biomekaniske soldater. Find det sted, hvor det sker, og luk det for altid! Find Richter i fællesarealerne, nær vandfaldet, og han vil fortælle dig, hvordan du kan stoppe denne grusomhed.","Wir haben herausgefunden, dass der Orden unsere Leute nicht tötet, sondern sie transformiert - int biomechanische Soldaten.Finde die Einrichtung, wo dies passiert und schließe sie - endgültig. Suche Richter beim Wasserfall bei der Mensa. Er wird dir sagen, wie du diese Abscheulichkeit abschaklten kannst.",,,"Hemos descubierto que la Orden está transformando a nuestra gente en soldados biomecánicos. Encuentra la instalación donde esto se está haciendo y ciérrala, ¡Permanentemente! Encuentra a Richter en los comunes, junto a la cascada y te dirá como detener esta atrocidad.",,"Olemme saaneet selville, että Veljeskunta muuntelee meidän omiamme biomekaanisiksi sotilaiksi. Etsi laitos, jossa tätä tehdään, ja lakkauta se, pysyvästi! Etsi Richter messistä vesiputouksen läheltä, ja hän kertoo sinulle, miten lopettaa tämä kauhistus.",Nous avons découvert que l'Ordre transforme notre peuple en soldats biomécaniques. Trouve l'usine où cela se déroule et détruis-la pour toujours! Trouve Richter dans le Réfectoire près de la cascade et il t'expliquera comment stopper cette atrocité.,"Kiderítettük, hogy a Rend bio-mechanikus katonákká alakítja az embertársainkat. Keresd meg a létesítményt ahol ezt csinálják, és zárd be örökre! Keresd fel Richtert a vízesés melletti étkezdénél, Ő majd elmondja hogyan tudod megállítani ezt a borzalmat.","Abbiamo scoperto che l'Ordine sta trasformando la nostra gente in soldati bio-meccanici. Trova lo stabilimento dove questo sta avvenendo e chiuderlo, permanentemente. Trova Richter nei comuni, accanto alla cascata, e ti spiegherà come fermare questa atrocità.","我等はオーダーが人々をサイボーグ兵に改造しつつある事を発見した。 これが行われている施設を見つけ永久に停止させる。 -コモンズの滝近くにいるリヒターに会い、この残虐な行為を止める方法を聞く。","오더가 우리 사람들을 생체병기로 개조한다는 사실을 알았어. 끔찍한 일이 일어나는 이 시설을 찾아서 작동을 중단시켜, 영원히! 폭포와 가까운 식당가에 있는 릭터를 찾아서 어떻게 하면 중단시킬 수 있는지를 물어봐.","We hebben ontdekt dat de Orde onze mensen transformeert in bio-mechanische soldaten. Vind de faciliteit waar dit gebeurt en sluit deze permanent! Vind Richter in de commons, vlakbij de waterval, en hij zal je vertellen hoe je deze gruweldaad kunt stoppen.","Vi har funnet ut at Ordenen forvandler vårt folk til biomekaniske soldater. Finn anlegget der dette gjøres og steng det, permanent! Finn Richter i allmenningen, nær fossen, og han vil fortelle deg hvordan du kan stoppe denne grusomheten.","Odkryliśmy, że Zakon przekształca naszych ludzi w bio-mechanicznych żołnierzy. Znajdźcie placówkę, w której to się odbywa i zamknijcie ją, na stałe! Znajdź Richtera w komnatach, w pobliżu wodospadu, a on powie ci, jak powstrzymać to okrucieństwo.","Descobrimos que a Ordem está transformando o nosso pessoal em soldados biomecânicos. Encontre a instalação onde isso está sendo feito e feche-a, de uma vez por todas! Encontre o Richter no refeitório próximo à cascata e ele te dirá como parar com essa atrocidade.",,"Am aflat că Ordinul ne transformă oamenii în soldați bio-mecanici. Găsește fabrica unde se întâmplă asta și închide-o, permanent! Găsește-l pe Richter la comune, lângă cascadă și îți va spune cum să oprești atrocitatea.","Мы выяснили, что Орден превращает наших людей в биомеханических солдат. Найди фабрику, где это происходит, и закрой её, навсегда! Найди Рихтера в поселении Ордена, возле водопада — он расскажет тебе, как остановить эти зверства.",,"Tarikat'ın insanlarımızı biyo-mekanik askerlere dönüştürdüğünü öğrendik. Bunun yapıldığı tesisi bulun ve kalıcı olarak kapatın! Ortak alanda, şelalenin yanında Richter'i bulun ve size bu vahşeti nasıl durduracağınızı anlatsın." -"To enter the factory, you need a key. We stole one, but the agent who had it is missing in the catacombs underneath the commons. There's something down there taking our men. Whatever it is, you have to find it and retrieve the key. When you've got it, the factory is next to the mines.",TXT_ILOG1029,,,,"Aby ses dostal do továrny, potřebuješ klíč. Ten jsme ukradli, ale náš agent se ztratil v sítí katakomb pod návsí. Něco je tam dole a zabíjí to naše lidi. Ať je to cokoliv, musíme to najít a získat ten klíč. Až ho získáš, továrna je vedle dolů.","For at komme ind på fabrikken skal du bruge en nøgle. Vi stjal en, men agenten, der havde den, er forsvundet i katakomberne under fællesarealerne. Der er noget dernede, der tager vores mænd. Uanset hvad det er, skal du finde det og hente nøglen. Når du har den, er fabrikken ved siden af minerne.","Um die Fabrik zu betreten, brauchst du einen Schlüssel. Wir haben ihn gestohlen, aber unser Agent ist in den Irrwegen der Katakomben unter der Festung des Ordens verschollen. Irgendetwas ist da unten, das unsere Leute ausschaltet. Was auch immer es ist, du musst es finden und den Schlüssel zurückholen. Wenn du ihn hast - die Fabrik ist direkt neben den Minen.",,,"Para entrar en la fábrica, necesitas una llave. Robamos una, pero el agente que la tiene está perdido en las catacumbas bajo los comunes. Hay algo ahí abajo tomando a nuestros hombres. Sea lo que sea, tienes que encontrarlo y recuperar la llave. Cuando la tengas, la fábrica está junto a las minas.","Para entrar en la Fábrica, necesitas una llave. Robamos una, pero el agente que la tenía está perdido en las catacumbas debajo de los comunes. Hay algo ahí abajo que está tomando nuestros hombres. Sea lo que sea, deberás encontrarlo y recuperar la llave. Cuando la tengas, la Fábrica está junto a las minas.","Päästäksesi sisälle tehtaaseen tarvitset avaimen. Varastimme sellaisen, mutta vakooja, joka sen sai, on kadoksissa katakombeissa messin alapuolella. Jokin siellä alla vie miehiämme. Mikä ikinä se onkaan, sinun on löydettävä se ja noudettava avain. Kun se on hallussasi, tehdas on kaivoksen vieressä.","Pour entrer dans l'usine, il te faura une clé. On en a volé une, mais l'agent qui la possède a disparu dans les catacombes sous le réfectoire. Il y a quelque chose à l'intérieur qui tue nos hommes. Trouve la et récupère la clé. Quand tu l'as, l'usine est près des mines.","Ahhoz, hogy bejuss a gyárba, kell szerezned egy kulcsot. Sikerült lopnunk egyet, de az ügynökünk akinél volt eltünt az étkezde alatti katakombákban. Van valami lent, ami sorra öli a katonáinkat. Akármi is vár lent, meg kell szerezned a kulcsot. Ha végeztél a gyárat megleled a bánya mellett.","Per entrare nella fabbrica ti servirà una chiave. L'abbiamo rubata ma l'agente che l'ha presa è sparito nelle catacombe sotto i comuni. C'è qualcosa là sotto che sta prendendo i nostri uomini. Qualsiasi cosa sia, devi andare laggiù e recuperare la chiave. Quando l'hai presa, la Fabbrica si trova accanto le miniere.","工場に入るにはキーが必要だ。持っていた代理人はコモンズの地下墓所にはいない。 +コモンズの滝近くにいるリヒターに会い、この残虐な行為を止める方法を聞く。","오더가 우리 사람들을 생체병기로 개조한다는 사실을 알았어. 끔찍한 일이 일어나는 이 시설을 찾아서 작동을 중단시켜, 영원히! 폭포와 가까운 식당가에 있는 릭터를 찾아서 어떻게 하면 중단시킬 수 있는지를 물어봐.","We hebben ontdekt dat de Orde onze mensen transformeert in bio-mechanische soldaten. Vind de faciliteit waar dit gebeurt en sluit deze permanent! Vind Richter in de commons, vlakbij de waterval, en hij zal je vertellen hoe je deze gruweldaad kunt stoppen.","Vi har funnet ut at Ordenen forvandler vårt folk til biomekaniske soldater. Finn anlegget der dette gjøres og steng det, permanent! Finn Richter i allmenningen, nær fossen, og han vil fortelle deg hvordan du kan stoppe denne grusomheten.","Odkryliśmy, że Zakon przekształca naszych ludzi w bio-mechanicznych żołnierzy. Znajdźcie placówkę, w której to się odbywa i zamknijcie ją, na stałe! Znajdź Richtera w komnatach, w pobliżu wodospadu, a on powie ci, jak powstrzymać to okrucieństwo.","Descobrimos que a Ordem está transformando o nosso pessoal em soldados biomecânicos. Encontre a instalação onde isso está sendo feito e feche-a, de uma vez por todas! Encontre o Richter no refeitório próximo à cascata e ele te dirá como parar com essa atrocidade.",,"Am aflat că Ordinul ne transformă oamenii în soldați bio-mecanici. Găsește fabrica unde se întâmplă asta și închide-o, permanent! Găsește-l pe Richter la comune, lângă cascadă și îți va spune cum să oprești atrocitatea.","Мы выяснили, что Орден превращает наших людей в биомеханических солдат. Найди фабрику, где это происходит, и закрой её, навсегда! Найди Рихтера в поселении Ордена, возле водопада — он расскажет тебе, как остановить эти зверства.",,"Vi har fått reda på att Orden förvandlar vårt folk till biomekaniska soldater. Hitta anläggningen där detta görs och stäng den, för gott! Hitta Richter i allmänningen, nära vattenfallet, så berättar han hur du ska stoppa denna grymhet.","Tarikat'ın insanlarımızı biyo-mekanik askerlere dönüştürdüğünü öğrendik. Bunun yapıldığı tesisi bulun ve kalıcı olarak kapatın! Ortak alanda, şelalenin yanında Richter'i bulun ve size bu vahşeti nasıl durduracağınızı anlatsın." +"To enter the factory, you need a key. We stole one, but the agent who had it is missing in the catacombs underneath the commons. There's something down there taking our men. Whatever it is, you have to find it and retrieve the key. When you've got it, the factory is next to the mines.",TXT_ILOG1029,MAP23: After talking with Richter.,,,"Aby ses dostal do továrny, potřebuješ klíč. Ten jsme ukradli, ale náš agent se ztratil v sítí katakomb pod návsí. Něco je tam dole a zabíjí to naše lidi. Ať je to cokoliv, musíme to najít a získat ten klíč. Až ho získáš, továrna je vedle dolů.","For at komme ind på fabrikken skal du bruge en nøgle. Vi stjal en, men agenten, der havde den, er forsvundet i katakomberne under fællesarealerne. Der er noget dernede, der tager vores mænd. Uanset hvad det er, skal du finde det og hente nøglen. Når du har den, er fabrikken ved siden af minerne.","Um die Fabrik zu betreten, brauchst du einen Schlüssel. Wir haben ihn gestohlen, aber unser Agent ist in den Irrwegen der Katakomben unter der Festung des Ordens verschollen. Irgendetwas ist da unten, das unsere Leute ausschaltet. Was auch immer es ist, du musst es finden und den Schlüssel zurückholen. Wenn du ihn hast - die Fabrik ist direkt neben den Minen.",,,"Para entrar en la fábrica, necesitas una llave. Robamos una, pero el agente que la tiene está perdido en las catacumbas bajo los comunes. Hay algo ahí abajo tomando a nuestros hombres. Sea lo que sea, tienes que encontrarlo y recuperar la llave. Cuando la tengas, la fábrica está junto a las minas.",,"Päästäksesi sisälle tehtaaseen tarvitset avaimen. Varastimme sellaisen, mutta vakooja, joka sen sai, on kadoksissa katakombeissa messin alapuolella. Jokin siellä alla vie miehiämme. Mikä ikinä se onkaan, sinun on löydettävä se ja noudettava avain. Kun se on hallussasi, tehdas on kaivoksen vieressä.","Pour entrer dans l'usine, il te faura une clé. On en a volé une, mais l'agent qui la possède a disparu dans les catacombes sous le réfectoire. Il y a quelque chose à l'intérieur qui tue nos hommes. Trouve la et récupère la clé. Quand tu l'as, l'usine est près des mines.","Ahhoz, hogy bejuss a gyárba, kell szerezned egy kulcsot. Sikerült lopnunk egyet, de az ügynökünk akinél volt eltünt az étkezde alatti katakombákban. Van valami lent, ami sorra öli a katonáinkat. Akármi is vár lent, meg kell szerezned a kulcsot. Ha végeztél a gyárat megleled a bánya mellett.","Per entrare nella fabbrica ti servirà una chiave. L'abbiamo rubata ma l'agente che l'ha presa è sparito nelle catacombe sotto i comuni. C'è qualcosa là sotto che sta prendendo i nostri uomini. Qualsiasi cosa sia, devi andare laggiù e recuperare la chiave. Quando l'hai presa, la Fabbrica si trova accanto le miniere.","工場に入るにはキーが必要だ。持っていた代理人はコモンズの地下墓所にはいない。 何処かへ連れて行かれたと思われる。それが何であれキーを見つけなければならない。 -キーを手に入れたら工場の隣の鉱山に向かう。","공장으로 들어가기 위해서는 열쇠가 필요해. 열쇠를 훔치기는 했지만, 소유했던 요원이 식당가 밑 고대 무덤 안에서 행방불명 되었데. 우리 병사들을 끌고 가는 무언가가 있는 것 같아. 그게 무엇이든, 파괴해서 열쇠를 얻어. 그리고 광산 옆에 있는 공장을 열쇠로 열어서 들어가.","Om de fabriek binnen te komen, heb je een sleutel nodig. We hebben er een gestolen, maar de agent die hem had, wordt vermist in de catacomben onder de commons. Er is daar beneden iets dat onze mannen meeneemt. Wat het ook is, je moet het vinden en de sleutel ophalen. Als je hem hebt, staat de fabriek naast de mijnen.","For å komme inn i fabrikken trenger du en nøkkel. Vi stjal en, men agenten som hadde den er savnet i katakombene under allmenningen. Det er noe der nede som tar våre menn. Hva det enn er, må du finne det og hente nøkkelen. Når du har den, er fabrikken ved siden av gruvene.","Aby wejść do fabryki, potrzebujesz klucza. Ukradliśmy jeden, ale agent, który go miał, zaginął w katakumbach pod commons. Coś tam jest, co zabiera naszych ludzi. Cokolwiek to jest, musisz to znaleźć i odzyskać klucz. Gdy go zdobędziesz, fabryka znajduje się obok kopalni.","Para entrar na fábrica você precisa de uma chave. Nós roubamos uma, mas o agente que tinha ela desapareceu nas catacumbas sob o refeitório. Há algo lá embaixo que está pegando os nossos homens. Seja lá o que for, você precisa achar e recuperar a chave. Quando conseguir, a fábrica fica próxima às minas.",,"Pentru a intra în fabrică ai nevoie de cheie. Noi am furat una, dar agentul care a luat-o e undeva în caverne, sub comune. E ceva acolo care ne răpește oamenii. Orice ar fi, găsește-l și ia cheia. Când o ai, fabrica e lângă mine.","Тебе нужен ключ, чтобы проникнуть на фабрику. Мы украли один, но наш агент пропал без вести в катакомбах под поселением. Там, внизу, сидит что-то, что убивает наших людей. Что бы это ни было, тебе придётся сразиться с ним. Когда заполучишь ключ, вход на фабрику рядом со спуском в шахты.",,"Fabrikaya girmek için bir anahtara ihtiyacınız var. Bir tane çaldık, ama anahtarı alan ajan avlunun altındaki yeraltı mezarlarında kayıp. Aşağıda adamlarımızı kaçıran bir şey var. O her neyse, onu bulup anahtarı almalısın. Anahtarı aldığında, fabrika madenlerin yanında olacak." -Find the chalice in the sanctuary chapel and bring it to Harris upstairs in the tavern.,TXT_ILOG1101,,,,Najdi kalich v kapli svatyně a přines ho Harrisovi v patře taverny.,Find bægeret i helligkapellet og bring det til Harris ovenpå i tavernaen.,Finde den Kelch im Heiligtum und bringe ihn zu Harris im Obergeschoss der Taverne.,,,Encuentra el cáliz en la capilla del santuario y tráeselo a Harris arriba en la taberna.,,Löydä kalkki pyhäkön kappelista ja tuo se Harrisille kapakan yläkertaan.,Trouve le calice dans la chapelle du sanctuaire et amène la à Harris à l'étage de la taverne.,"Keresd meg a serleget a szent kápolnánál, és vidd Harrishez a kocsma emeletére.",Trova il calice nella cappella del santuario e portalo ad Harris al piano di sopra della Taverna.,聖域でチャリスを探しバーの二階にいるハリスに渡す,"성소에 있는 성배를 찾은 뒤, 선술집에 있는 헤리스에게 전달해.",Vind de kelk in de kapel van het heiligdom en breng hem naar Harris boven in de taverne.,Finn kalken i helligdomskapellet og ta den med til Harris oppe i tavernaen.,Znajdź kielich w kaplicy sanktuarium i zanieś go Harrisowi na górę w tawernie.,Encontre o cálice na capela do santuário e leve ao Harris no andar de cima da taverna.,,Găsește potirul în sanctuarul capelei și du-l lui Harris sus în tavernă.,Найди чашу в святилище и принеси её Харрису на второй этаж таверны.,,Kutsal şapeldeki kadehi bul ve tavernanın üst katındaki Harris'e getir. -Find the Governor's mansion and talk to the Governor to get your reward,TXT_ILOG1102,,,,Najdi guvernérovo sídlo a promluv si s ním pro svou odměnu.,Find guvernørens palæ og tal med guvernøren for at få din belønning,Finde die Villa des Gouverneurs und rede mit ihm über deine Belohnung.,,,Encuentra la mansión del Gobernador y habla con él para obtener tu recompensa,,Löydä kuvernöörin kartano ja puhu kuvernöörin kanssa saadaksesi palkkiosi.,Trouve le manoir du Gouverneur et parle-lui pour réclamer ta récompense.,"Keresd fel a Kormányzót a kúriájában, hogy megkapd a jutalmad.",Trova la dimora del governatore e parlagli della tua ricompensa.,知事のマンションで知事と話し報酬を得る,총독의 거주지를 찾은 뒤 총독을 만나서 보상에 대해 예기해.,Zoek het herenhuis van de Gouverneur en praat met de Gouverneur om je beloning te krijgen.,Finn guvernørens herskapshus og snakk med guvernøren for å få belønningen.,"Znajdź rezydencję gubernatora i porozmawiaj z nim, aby otrzymać nagrodę",Encontre a mansão do Governador e fale com ele para pegar a sua recompensa.,,Găsește complexul Guvernatorului și vorbește cu el pentru a-ți lua recompensa.,Пройди в особняк губернатора и обсуди с Морелом своё вознаграждение.,,Vali'nin konağını bulun ve ödülünüzü almak için Vali ile konuşun +キーを手に入れたら工場の隣の鉱山に向かう。","공장으로 들어가기 위해서는 열쇠가 필요해. 열쇠를 훔치기는 했지만, 소유했던 요원이 식당가 밑 고대 무덤 안에서 행방불명 되었데. 우리 병사들을 끌고 가는 무언가가 있는 것 같아. 그게 무엇이든, 파괴해서 열쇠를 얻어. 그리고 광산 옆에 있는 공장을 열쇠로 열어서 들어가.","Om de fabriek binnen te komen, heb je een sleutel nodig. We hebben er een gestolen, maar de agent die hem had, wordt vermist in de catacomben onder de commons. Er is daar beneden iets dat onze mannen meeneemt. Wat het ook is, je moet het vinden en de sleutel ophalen. Als je hem hebt, staat de fabriek naast de mijnen.","For å komme inn i fabrikken trenger du en nøkkel. Vi stjal en, men agenten som hadde den er savnet i katakombene under allmenningen. Det er noe der nede som tar våre menn. Hva det enn er, må du finne det og hente nøkkelen. Når du har den, er fabrikken ved siden av gruvene.","Aby wejść do fabryki, potrzebujesz klucza. Ukradliśmy jeden, ale agent, który go miał, zaginął w katakumbach pod commons. Coś tam jest, co zabiera naszych ludzi. Cokolwiek to jest, musisz to znaleźć i odzyskać klucz. Gdy go zdobędziesz, fabryka znajduje się obok kopalni.","Para entrar na fábrica você precisa de uma chave. Nós roubamos uma, mas o agente que tinha ela desapareceu nas catacumbas sob o refeitório. Há algo lá embaixo que está pegando os nossos homens. Seja lá o que for, você precisa achar e recuperar a chave. Quando conseguir, a fábrica fica próxima às minas.",,"Pentru a intra în fabrică ai nevoie de cheie. Noi am furat una, dar agentul care a luat-o e undeva în caverne, sub comune. E ceva acolo care ne răpește oamenii. Orice ar fi, găsește-l și ia cheia. Când o ai, fabrica e lângă mine.","Тебе нужен ключ, чтобы проникнуть на фабрику. Мы украли один, но наш агент пропал без вести в катакомбах под поселением. Там, внизу, сидит что-то, что убивает наших людей. Что бы это ни было, тебе придётся сразиться с ним. Когда заполучишь ключ, вход на фабрику рядом со спуском в шахты.",,"För att komma in i fabriken behöver du en nyckel. Vi stal en, men agenten som hade den är försvunnen i katakomberna under allmänningen. Det är något där nere som tar våra män. Vad det än är måste du hitta det och hämta nyckeln. När du har fått den är fabriken bredvid gruvorna.","Fabrikaya girmek için bir anahtara ihtiyacınız var. Bir tane çaldık, ama anahtarı alan ajan avlunun altındaki yeraltı mezarlarında kayıp. Aşağıda adamlarımızı kaçıran bir şey var. O her neyse, onu bulup anahtarı almalısın. Anahtarı aldığında, fabrika madenlerin yanında olacak." +Find the chalice in the sanctuary chapel and bring it to Harris upstairs in the tavern.,TXT_ILOG1101,,,,Najdi kalich v kapli svatyně a přines ho Harrisovi v patře taverny.,Find bægeret i helligkapellet og bring det til Harris ovenpå i tavernaen.,Finde den Kelch im Heiligtum und bringe ihn zu Harris im Obergeschoss der Taverne.,,,Encuentra el cáliz en la capilla del santuario y tráeselo a Harris arriba en la taberna.,,Löydä kalkki pyhäkön kappelista ja tuo se Harrisille kapakan yläkertaan.,Trouve le calice dans la chapelle du sanctuaire et amène la à Harris à l'étage de la taverne.,"Keresd meg a serleget a szent kápolnánál, és vidd Harrishez a kocsma emeletére.",Trova il calice nella cappella del santuario e portalo ad Harris al piano di sopra della Taverna.,聖域でチャリスを探しバーの二階にいるハリスに渡す,"성소에 있는 성배를 찾은 뒤, 선술집에 있는 헤리스에게 전달해.",Vind de kelk in de kapel van het heiligdom en breng hem naar Harris boven in de taverne.,Finn kalken i helligdomskapellet og ta den med til Harris oppe i tavernaen.,Znajdź kielich w kaplicy sanktuarium i zanieś go Harrisowi na górę w tawernie.,Encontre o cálice na capela do santuário e leve ao Harris no andar de cima da taverna.,,Găsește potirul în sanctuarul capelei și du-l lui Harris sus în tavernă.,Найди чашу в святилище и принеси её Харрису на второй этаж таверны.,,Hitta kalken i helgedomens kapell och ta med den till Harris uppe i tavernan.,Kutsal şapeldeki kadehi bul ve tavernanın üst katındaki Harris'e getir. +Find the Governor's mansion and talk to the Governor to get your reward,TXT_ILOG1102,,,,Najdi guvernérovo sídlo a promluv si s ním pro svou odměnu.,Find guvernørens palæ og tal med guvernøren for at få din belønning,Finde die Villa des Gouverneurs und rede mit ihm über deine Belohnung.,,,Encuentra la mansión del Gobernador y habla con él para obtener tu recompensa,,Löydä kuvernöörin kartano ja puhu kuvernöörin kanssa saadaksesi palkkiosi.,Trouve le manoir du Gouverneur et parle-lui pour réclamer ta récompense.,"Keresd fel a Kormányzót a kúriájában, hogy megkapd a jutalmad.",Trova la dimora del governatore e parlagli della tua ricompensa.,知事のマンションで知事と話し報酬を得る,총독의 거주지를 찾은 뒤 총독을 만나서 보상에 대해 예기해.,Zoek het herenhuis van de Gouverneur en praat met de Gouverneur om je beloning te krijgen.,Finn guvernørens herskapshus og snakk med guvernøren for å få belønningen.,"Znajdź rezydencję gubernatora i porozmawiaj z nim, aby otrzymać nagrodę",Encontre a mansão do Governador e fale com ele para pegar a sua recompensa.,,Găsește complexul Guvernatorului și vorbește cu el pentru a-ți lua recompensa.,Пройди в особняк губернатора и обсуди с Морелом своё вознаграждение.,,Hitta guvernörens herrgård och prata med guvernören för att få din belöning.,Vali'nin konağını bulun ve ödülünüzü almak için Vali ile konuşun Congratulations! You have earned our gratitude. Visit the medic and weapons trainer and they will get you ready for what lies ahead. Feel free to wander around within the base.,TXT_ILOG1201,,,,"Gratulujeme! Získal sis naši vděčnost. Navštiv lékaře a učitele střelby a oni tě připraví na to, co číhá dál. Klidně se potloukej po základně.","Tillykke med det! Du har fortjent vores taknemmelighed. Besøg lægen og våbentræneren, og de vil gøre dig klar til det, der venter forude. Du er velkommen til at vandre rundt i basen.","Gratulation. Du hast dir unsere Dankbarkeit verdient. Suche den Sanitäter und den Waffentrainer auf, sie werden dich auf das was vor dir liegt, vorbereiten. Wenn du willst, schau dich in der Basis um.",,,¡Enhorabuena! Te has ganado nuestra gratitud. Visita al médico y al entrenador de armas y te prepararán para lo que viene en adelante. Sé libre de dar un paseo por la base.,¡Felicitaciones! Te ganaste nuestra gratitud. Visita al médico y al entrenador de armas y ellos te dejarán listo para lo que sigue. Sientete libre de andar através de la base.,"Onneksi olkoon! Olet ansainnut kiitollisuutemme. Vieraile lääkintämiehen ja asekouluttajan luona, ja he valmistavat sinut tuleviin koitoksiin. Saat vapaasti kulkea tukikohdan sisällä.",Félicitations! Vous méritez notre gratitude. Allez voir le médecin et le maître d'armes et ils pourront vous préparer pour ce qu'il va suivre. Vous pouvez faire le tour de la base si vous le souhaitez.,"Gratulálok! Kiérdemled a hálánkat! keresd fel a szanitécet és a fegyvermestert, és felkészítenek az előtted álló harcra. Nyugodtan nézz körbe a bázisban.",Congratulazioni! Meriti appieno la nostra gratitudine. Visita il medico e l'addestratore di armi e ti prepareranno per ciò che ci aspetta. Sii anche libero di andare in giro per la base.,"おめでとう!私達は貴方に感謝している。 メディックと武器トレーナーに訪れれば手助けを施せる。 -基地内部も自由に回ってよい。",축하해! 우리 모두 너에게 고마워하고 있어. 의무관과 무기 담당관을 찾아가면 너에게 보답을 할 준비를 할 거야. 그 후엔 기지를 마음껏 돌아다녀 봐!,Gefeliciteerd! Je hebt onze dankbaarheid verdiend. Bezoek de medicus- en wapentrainer en zij zullen je klaarstomen voor wat je te wachten staat. Voel je vrij om rond te dwalen in de basis.,"Gratulerer! Du har fortjent vår takknemlighet. Besøk medisineren og våpentreneren, og de vil gjøre deg klar for det som ligger foran deg. Føl deg fri til å vandre rundt i basen.","Gratulacje!!! Zasłużyłeś na naszą wdzięczność. Odwiedź medyka i trenera broni, a oni przygotują Cię na to, co Cię czeka. Możesz swobodnie poruszać się po bazie.",Parabéns! Você conquistou a nossa gratidão. Visite o médico e o treinador de armas e eles vão te preparar para o que vem adiante. Sinta-se livre para passear pela base.,,Felicitări! Ne-ai câștigat recunoștiința. Vizitează medicul și antrenorul de arme și te vor pregătii pentru ceea ce urmează mai departe. Simte-te liber să te plimbi prin bază.,"Поздравляем! Ты заслужил нашу благодарность. Зайди к медику и инструктору по стрельбе, и они подготовят тебя к тому, что ждёт тебя впереди. Теперь ты можешь свободно передвигаться по нашей базе.",,"Tebrikler! Minnettarlığımızı kazandınız. Sıhhiyeyi ve silah eğitmenini ziyaret edin, onlar sizi ileride olacaklara hazırlayacaktır. Üs içinde dolaşmaktan çekinmeyin." -,,Strife characters,,,,,,,,,,,,,,,,,,,,,,,, -Order Sergeant,TXT_SPEAKER_ORDER_SERGEANT,,,,Seržant Řádu,Ordenens sergent,Soldat des Ordens,,,Sargento de La Orden,,Veljeskunnan kersantti,Sergeant de l'Ordre,Rendi Törzsőrmester,Sergente dell'Ordine,オーダー軍曹,오더 장교,Soldaat van de orde,Ordenssersjant,Sierżant Zakonu,Sargento da Ordem,,Sergent al Ordinului,Сержант Ордена,,Emir Çavuşu -Rowan,TXT_SPEAKER_ROWAN,,,,,,,,,,,,,,,ロワン,로언,,,,,,,Роуэн,,Rowan -Feris,TXT_SPEAKER_FERIS,,,,,,,,,,,,,,,フェリス,페리스,,,,,,,Ферис,,Feris -Prison Guard,TXT_SPEAKER_PRISON_GUARD,,,,Vězeňská stráž,Fængselsbetjent,Gefängniswache,,,Guardia de la Prisión,,Vanginvartija,Garde de la Prison,Börtönőr,Guardia della Prigione,刑務官,간수,Gevangenisbewaker,Fengselsvakt,Strażnik Więzienny,Guarda da Prisão,,Gardian Închisoare,"Страж тюрьмы -",,Hapishane Gardiyanı -Justin,TXT_SPEAKER_JUSTIN,,,,,,,,,,,,,,,ジャスティン,저스틴,,,,,,,Джастин,,Justin -Macil,TXT_SPEAKER_MACIL,,,,,,,,,,,,,,,マシル,마실,,,,,,,Мэйсил,,Macil -Assistant,TXT_SPEAKER_ASSISTANT,,,,Asistent,Assistent,Assistent,,,Asistente,,Avustaja,,Asszisztens,Assistente,アシスタント,조수,Assistent,Assistent,Asystent,Assistente,,Asistent,Ассистент,,Asistan -Key Master,TXT_SPEAKER_KEY_MASTER,,,,Klíčník,Nøglemester,Schlüsselmeister,,,Amo de Llaves,,Avainmestari,Maître des Clés,Kulcsmester,Mastro delle chiavi,キーマスター,열쇠지기,Zeer belangrijke Meester,Nøkkelmester,Klucznik,Mestre das Chaves,,Stăpân al Cheilor,Ключник,,Anahtar Ustası -Bodyguard,TXT_SPEAKER_BODYGUARD,,,,Osobní stráž,Livvagt,Leibwächter,,,Guardaespaldas,,Henkivartija,Garde du corps,Testőr,Guardia del corpo,ボディガード,경호원,Lijfwacht,Livvakt,Ochroniarz,Guarda-costas,,Gardă de Corp,Телохранитель,,Bodyguard -Interrogator,TXT_SPEAKER_INTERROGATOR,"Intended to appear in MAP01 of the Strife teaser, but does not spawn.",,,Vyslýchač,Forhørsleder,Befrager,,,Interrogador,,Kuulustelija,Interrogateur,Kihallgató,Interrogatore,,심문자,Ondervrager,Avhører,Śledczy,Interrogador,,Interogator,Дознаватель,,Sorgulayıcı -Warden Montag,TXT_SPEAKER_WARDEN_MONTAG,,,,Dozorce Montag,Direktør Montag,Direktor Montag,,,Carcelero Montag,,Vankilanjohtaja Montag,Gardien Montag,Montag börtönigazgató,Direttore Montag,モンターグ刑務所長,몬탕 간수장,Directeur Montag,Direktør Montag,Naczelnik Montag,Carcereiro Montag,,Directorul Montag,Тюремщик Монтаг,,Müdür Montag -Richter,TXT_SPEAKER_RICHTER,,,,,,,,,,,,,,,リヒター,릭터,,,,,,,Рихтер,,Richter -Macil's Advisor,TXT_SPEAKER_MACIL_S_ADVISOR,,,,Macilův rádce,Macils rådgiver,Macils Berater,,,Consejero de Macil,,Macilin neuvonantaja,Conseiller de Macil,Macil tanácsosa,Consigliere di Macil,マシルの補佐官,마실의 조언자,Macil's adviseur,Macils rådgiver,Doradca Macila,Conselheiro de Macil,,Sfetnicul lui Macil,Советник Мэйсила,,Macil'in Danışmanı -Judge Wolenick,TXT_SPEAKER_JUDGE_WOLENICK,,,,Soudce Wolenick,Dommer Wolenick,Richter Wolenick,,,Juez Wolenick,,Tuomari Wolenick,Juge Wolenick,Wolenick bíró,Giudice Wolenick,ウォレニック裁判官,울레닉 판사,Rechter Wolenick,Dommer Wolenick,Sędzia Wolenick,Juiz Wolenick,,Judecătorul Wolenick,Судья Уолник,,Yargıç Wolenick -Tevick,TXT_SPEAKER_TEVICK,,,,,,,,,,,,,,,テビック,테빅,,,,,,,Тевик,,Tevak -Harris,TXT_SPEAKER_HARRIS,,,,,,,,,,,,,,,ハリス,해리스,,,,,,,Харрис,,Harris -Foreman,TXT_SPEAKER_FOREMAN,,,,Předák,Formand,Vormann,,,Capataz,,Työnjohtaja,Contremaître,Művezető,Caposquadra,フォアマン,감시원,Voorman,Formann,Brygadzista,Capataz,,,Бригадир,,Ustabaşı -Prisoner,TXT_SPEAKER_PRISONER,,,,Vězeň,Fange,Gefangener,,Kaptito,Prisionero,,Vanki,Prisonnier,Rab,Prigioniero,囚人,죄수,Gevangene,Fange,Więzień,Prisioneiro,,Prizonier,Пленник,,Mahkum -Sammis,TXT_SPEAKER_SAMMIS,,,,,,,,,,,,,,,サムミス,새미스,,,,,,,Сэммис,,Sammis -Weapon Smith,TXT_SPEAKER_WEAPON_SMITH,,,,Zbrojíř,Våbensmed,Waffenschmied,,Armilforĝisto,Forjador de Armas,,Aseseppä,Armurier,Fegyverkovács,Fabbro d'Armi,武器工,무기제조인,Wapen Smith,Våpensmed,Wytwórca Broni,Armeiro,,Făurar Arme,Оружейник,,Silah Ustası -Reactor Guard,TXT_SPEAKER_REACTOR_GUARD,,,,Stráž reaktoru,Reaktorvagt,Reaktorwache,,,Guardia del Reactor,,Reaktorinvartija,Garde du réacteur,Reaktor Őr,Guardia del Reattore,リアクターガード,발전소 경비원,Reactor bewaker,Reaktorvakt,Strażnik Reaktora,Guarda do Reator,,Gardian Reactor,Страж реактора,,Reaktör Muhafızı -Apprentice,TXT_SPEAKER_APPRENTICE,,,,Učeň,Lærling,Lehrling,,,Aprendiz,,Kisälli,Apprenti,Tanonc,Apprendista,見習い,도제,Leerling,Lærling,Uczeń,Aprendiz,,Ucenic,Подмастерье,,Çırak -Door Guard,TXT_SPEAKER_DOOR_GUARD,,,,Dveřní stráž,Dørvagt,Türwache,,,Guarda de la Puerta,,Ovenvartija,Garde de la porte,Ajtónálló,Guardia della Porta,ドアガード,문지기,Deurwacht,Dørvakt,Strażnik Drzwi,Guarda da Porta,,Paznic,Страж входа,,Kapı Koruması -Master Smithy,TXT_SPEAKER_MASTER_SMITHY,,,,Mistr Smithy,Mester Smithy,Meister Smithy,,,Maestro Smithy,,Pajamestari,Maîre Smithy,Smithy mester,Maestro Smithy,マスター スミシー,스미시 제조장관,Meester Smithy,Mester Smithy,Mistrz Smithy,Mestre Smithy,,Maestrul Smithy,Мастер-кузнец,,Demirci Usta -Warehouse Guard,TXT_SPEAKER_WAREHOUSE_GUARD,,,,Stráž skladu,Lagervagt,Lagerhaus-Wache,,,Guardia del Almacén,,Varastonvartija,Garde de l'entrepôt,Raktár Őr,Guardia del Magazzino,倉庫のガード,격납고 감시장,Magazijnwachter,Lagervakt,Strażnik Magazynu,Guarda do Depósito,,Paznic Depozit,Охранник склада,,Depo Görevlisi -Barkeep,TXT_SPEAKER_BARKEEP,,,,Barman,Bartender,Wirt,,Trinkejisto,Tabernero,Barman,Baarimikko,Barman,Bárpultos,Barman,バーテンダー,바텐더,Barman,Bartender,Barman,Taberneiro,,Barman,Хозяин таверны,,Barmen -Timothy,TXT_SPEAKER_TIMOTHY,,,,,,,,,,,,,,,ティモシー,티모시,,,,,,Timotei,Тимоти,,Timothy -James,TXT_SPEAKER_JAMES,,,,,,,,,,,,,,,ジェームス,제임스,,,,,,,Джеймс,,James -Worner,TXT_SPEAKER_WORNER,,,,,,,,,,,,,,,ワーナー,워너,,,,,,,Уорнэр,,Worner -Bailey Guard,TXT_SPEAKER_BAILEY_GUARD,,,,Stráž opevnění,Bailey-vagt,Vorhof-Wache,,,Guardia de la Muralla,,Ulkomuurinvartija,Garde d'enceinte,Várfal Őr,Guardia del Bastione,ベイリー ガード,외벽 파수병,Bailey Guard,Borggården vakt,Strażnik Murów,Guarda da Fortaleza,,Gardian Bailey,Страж крепости,,Dış avlu bekçisi -Drone,TXT_SPEAKER_DRONE,,,,Trubec,,Drohne,,,Dron,,Kuhnuri,,Drón,,労働者,노예,Drone,,Dron,Zangão,,Dronă,Дрон,,Drone -Front Guard,TXT_SPEAKER_FRONT_GUARD,,,,Stráž Fronty,Front vagt,Frontwache,,,Guardia del Frente,,Rintaman vartija,Garde du Front,Front Őr,Guardia del Fronte,フロント ガード,프론트 파수꾼,Voorwacht,Front Guard,Strażnik Frontu,Guarda da Frente,,Gandian Front,Повстанец,,Ön Koruma -Quincy,TXT_SPEAKER_QUINCY,,,,,,,,,,,,,,,クインシー,퀸시,,,,,,,Куинси,,Quincy -Sergeant,TXT_SPEAKER_SERGEANT,,,,Seržant,Sergent,Feldwebel,,,Sargento,,Kersantti,Sergeant,Törzsőrmester,Sergente,軍曹,하사관,Sergeant,Sersjant,Sierżant,Sargento,,Sergent,Сержант,,Çavuş -Temple Guard,TXT_SPEAKER_TEMPLE_GUARD,,,,Stráž chrámu,Tempelvagt,Tempelwache,,,Guardia del Templo,,Temppelinvartija,Garde du Temple,Templom Őr,Guardia del Tempio,テンプル ガード,신전 파수병,Tempelwacht,Tempelvakten,Strażnik Świątyni,Guarda do Templo,,Gardian Templu,Страж храма,,Tapınak Muhafızı -Oracle,TXT_SPEAKER_ORACLE,,,,Věštec,Orakel,Orakel,,Orakolo,Oráculo,,Oraakkeli,,Orákulum,Oracolo,オラクル,오라클,Orakel,Orakel,Wyrocznia,Oráculo,,Oracol,Оракул,,Kahin -Ulaine,TXT_SPEAKER_ULAINE,,,,,,,,,,,,,,,ウレーヌ,울레인,,,,,,,Улейн,,Ulane -Front Soldier,TXT_SPEAKER_FRONT_SOLDIER,,,,Voják Fronty,Frontsoldat,Front-Soldat,,,Soldado del Frente,,Rintaman sotilas,Soldat du Front,Front Katona,Soldato del Fronte,フロント ソルジャー,프론트 저항군,Front Soldier,Frontsoldat,Żołnierz Frontu,Soldado da Frente,,Soldat Front,Повстанец,,Ön Asker -Programmer,TXT_SPEAKER_PROGRAMMER,,,,Programátor,Programmør,Programmierer,,Programisto,Programador,,Ohjelmoitsija,Programmeur,Programozó,Programmatore,プログラマー,프로그래머,Programmeur,Programmerer,Programista,Programador,,Programator,Программист,,Programcı -Medic,TXT_SPEAKER_MEDIC,,,,Zdravotník,Læge,Sanitäter,,Kuracisto,Médico,,Lääkintämies,Médecin,Szanitéc,Medico,メディック,의무병,Paramedicus,Sanitetssoldat,Medyk,Médico,,,Медик,,Medic -Watchman,TXT_SPEAKER_WATCHMAN,,,,Hlídač,Vagtmand,Wächter,,,Celador,,Vahti,Vigie,Őrszem,Vigilante,警備員,감시병,Waker,Vaktmann,Stróż,Vigia,,Străjer,Караульный,,Bekçi -Ketrick,TXT_SPEAKER_KETRICK,,,,,,,,,,,,,,,ケトリック,케트릭,,,,,,,Кетрик,,Ketrick -Weran,TXT_SPEAKER_WERAN,,,,,,,,,,,,,,,ウェラン,워렌,,,,,,,Уэран,,Weran -Advisor,TXT_SPEAKER_ADVISOR,,,,Rádce,Rådgiver,Berater,,,Consejero,,Neuvonantaja,Conseiller,Tanácsadó,Consigliere,補佐官,조언자,Adviseur,Rådgiver,Doradca,Conselheiro,,Sfetnic,Советник,,Danışman -Geoff,TXT_SPEAKER_GEOFF,,,,,,,,,,,,,,,ジェフ,제프,,,,,,,Джефф,,Geoff -Overseer,TXT_SPEAKER_OVERSEER,,,,Dozorčí,Tilsynsførende,Aufseher,,,Superintendente,,Valvoja,Superviseur,Munkavezető,Supervisore,監視人,현장 감독,Opziener,Oppsynsmann,Nadzorca,Supervisor,,Supraveghetor,Надсмотрщик,,Gözetmen +基地内部も自由に回ってよい。",축하해! 우리 모두 너에게 고마워하고 있어. 의무관과 무기 담당관을 찾아가면 너에게 보답을 할 준비를 할 거야. 그 후엔 기지를 마음껏 돌아다녀 봐!,Gefeliciteerd! Je hebt onze dankbaarheid verdiend. Bezoek de medicus- en wapentrainer en zij zullen je klaarstomen voor wat je te wachten staat. Voel je vrij om rond te dwalen in de basis.,"Gratulerer! Du har fortjent vår takknemlighet. Besøk medisineren og våpentreneren, og de vil gjøre deg klar for det som ligger foran deg. Føl deg fri til å vandre rundt i basen.","Gratulacje!!! Zasłużyłeś na naszą wdzięczność. Odwiedź medyka i trenera broni, a oni przygotują Cię na to, co Cię czeka. Możesz swobodnie poruszać się po bazie.",Parabéns! Você conquistou a nossa gratidão. Visite o médico e o treinador de armas e eles vão te preparar para o que vem adiante. Sinta-se livre para passear pela base.,,Felicitări! Ne-ai câștigat recunoștiința. Vizitează medicul și antrenorul de arme și te vor pregătii pentru ceea ce urmează mai departe. Simte-te liber să te plimbi prin bază.,"Поздравляем! Ты заслужил нашу благодарность. Зайди к медику и инструктору по стрельбе, и они подготовят тебя к тому, что ждёт тебя впереди. Теперь ты можешь свободно передвигаться по нашей базе.",,Gratulerar! Du har förtjänat vår tacksamhet. Besök sjukvårdaren och vapentränaren och de kommer att göra dig redo för vad som väntar dig. Du får gärna vandra runt i basen.,"Tebrikler! Minnettarlığımızı kazandınız. Sıhhiyeyi ve silah eğitmenini ziyaret edin, onlar sizi ileride olacaklara hazırlayacaktır. Üs içinde dolaşmaktan çekinmeyin." +,,Strife characters,,,,,,,,,,,,,,,,,,,,,,,,, +Order Sergeant,TXT_SPEAKER_ORDER_SERGEANT,,,,Seržant Řádu,Ordenens sergent,Soldat des Ordens,,Serĝento de La Ordeno,Sargento de La Orden,,Veljeskunnan kersantti,Sergeant de l'Ordre,Rendi Törzsőrmester,Sergente dell'Ordine,オーダー軍曹,오더 장교,Soldaat van de orde,Ordenssersjant,Sierżant Zakonu,Sargento da Ordem,,Sergent al Ordinului,Сержант Ордена,,Sergeant på orden,Emir Çavuşu +Rowan,TXT_SPEAKER_ROWAN,,,,,,,,,,,,,,,ロワン,로언,,,,,,,Роуэн,,, +Feris,TXT_SPEAKER_FERIS,,,,,,,,Feriso,,,,,,,フェリス,페리스,,,,,,,Ферис,,, +Prison Guard,TXT_SPEAKER_PRISON_GUARD,,,,Vězeňská stráž,Fængselsbetjent,Gefängniswache,,Mallibereja gardisto,Guardia de la prisión,,Vanginvartija,Garde de la Prison,Börtönőr,Guardia della Prigione,刑務官,간수,Gevangenisbewaker,Fengselsvakt,Strażnik Więzienny,Guarda da Prisão,,Gardian Închisoare,"Страж тюрьмы +",,Fångvakt,Hapishane Gardiyanı +Justin,TXT_SPEAKER_JUSTIN,,,,,,,,,,,,,,,ジャスティン,저스틴,,,,,,,Джастин,,, +Macil,TXT_SPEAKER_MACIL,,,,,,,,,,,,,,,マシル,마실,,,,,,,Мэйсил,,, +Assistant,TXT_SPEAKER_ASSISTANT,,,,Asistent,Assistent,Assistent,,Asistanto,Asistente,,Avustaja,,Asszisztens,Assistente,アシスタント,조수,Assistent,Assistent,Asystent,Assistente,,Asistent,Ассистент,,Assistent,Asistan +Key Master,TXT_SPEAKER_KEY_MASTER,,,,Klíčník,Nøglemester,Schlüsselmeister,,Ŝlosilestro,Amo de llaves,,Avainmestari,Maître des Clés,Kulcsmester,Mastro delle chiavi,キーマスター,열쇠지기,Zeer belangrijke Meester,Nøkkelmester,Klucznik,Mestre das Chaves,,Stăpân al Cheilor,Ключник,,Nyckelmästare,Anahtar Ustası +Bodyguard,TXT_SPEAKER_BODYGUARD,,,,Osobní stráž,Livvagt,Leibwächter,,Korpogardisto,Guardaespaldas,,Henkivartija,Garde du corps,Testőr,Guardia del corpo,ボディガード,경호원,Lijfwacht,Livvakt,Ochroniarz,Guarda-costas,,Gardă de Corp,Телохранитель,,Livvakt, +Interrogator,TXT_SPEAKER_INTERROGATOR,"Intended to appear in MAP01 of the Strife teaser, but does not spawn.",,,Vyslýchač,Forhørsleder,Befrager,,Pridemandisto,Interrogador,,Kuulustelija,Interrogateur,Kihallgató,Interrogatore,,심문자,Ondervrager,Avhører,Śledczy,Interrogador,,Interogator,Дознаватель,,Förhörsledare,Sorgulayıcı +Warden Montag,TXT_SPEAKER_WARDEN_MONTAG,,,,Dozorce Montag,Direktør Montag,Direktor Montag,,Provoso Montag,Carcelero Montag,,Vankilanjohtaja Montag,Gardien Montag,Montag börtönigazgató,Direttore Montag,モンターグ刑務所長,몬탕 간수장,Directeur Montag,Direktør Montag,Naczelnik Montag,Carcereiro Montag,,Directorul Montag,Тюремщик Монтаг,,Direktör Montag,Müdür Montag +Richter,TXT_SPEAKER_RICHTER,,,,,,,,Rikter,,,,,,,リヒター,릭터,,,,,,,Рихтер,,, +Macil's Advisor,TXT_SPEAKER_MACIL_S_ADVISOR,,,Macil's Adviser,Macilův rádce,Macils rådgiver,Macils Berater,,Konsilisto de Macil,Consejero de Macil,,Macilin neuvonantaja,Conseiller de Macil,Macil tanácsosa,Consigliere di Macil,マシルの補佐官,마실의 조언자,Macil's adviseur,Macils rådgiver,Doradca Macila,Conselheiro de Macil,,Sfetnicul lui Macil,Советник Мэйсила,,Macils rådgivare,Macil'in Danışmanı +Judge Wolenick,TXT_SPEAKER_JUDGE_WOLENICK,,,,Soudce Wolenick,Dommer Wolenick,Richter Wolenick,,Juĝisto Wolenick,Juez Wolenick,,Tuomari Wolenick,Juge Wolenick,Wolenick bíró,Giudice Wolenick,ウォレニック裁判官,울레닉 판사,Rechter Wolenick,Dommer Wolenick,Sędzia Wolenick,Juiz Wolenick,,Judecătorul Wolenick,Судья Уолник,,Domare Wolenick,Yargıç Wolenick +Tevick,TXT_SPEAKER_TEVICK,,,,,,,,,,,,,,,テビック,테빅,,,,,,,Тевик,,,Tevak +Harris,TXT_SPEAKER_HARRIS,,,,,,,,Harriso,,,,,,,ハリス,해리스,,,,,,,Харрис,,, +Foreman,TXT_SPEAKER_FOREMAN,,,,Předák,Formand,Vormann,,Submastro,Capataz,,Työnjohtaja,Contremaître,Művezető,Caposquadra,フォアマン,감시원,Voorman,Formann,Brygadzista,Capataz,,,Бригадир,,Förman,Ustabaşı +Prisoner,TXT_SPEAKER_PRISONER,,,,Vězeň,Fange,Gefangener,,Kaptito,Prisionero,,Vanki,Prisonnier,Rab,Prigioniero,囚人,죄수,Gevangene,Fange,Więzień,Prisioneiro,,Prizonier,Пленник,,Fånge,Mahkum +Sammis,TXT_SPEAKER_SAMMIS,,,,,,,,,,,,,,,サムミス,새미스,,,,,,,Сэммис,,, +Weapon Smith,TXT_SPEAKER_WEAPON_SMITH,,,,Zbrojíř,Våbensmed,Waffenschmied,,Armilforĝisto,Forjador de armas,,Aseseppä,Armurier,Fegyverkovács,Fabbro d'Armi,武器工,무기제조인,Wapen Smith,Våpensmed,Wytwórca Broni,Armeiro,,Făurar Arme,Оружейник,,Vapen Smith,Silah Ustası +Reactor Guard,TXT_SPEAKER_REACTOR_GUARD,,,,Stráž reaktoru,Reaktorvagt,Reaktorwache,,Reaktora gardisto,Guardia del reactor,,Reaktorinvartija,Garde du réacteur,Reaktor Őr,Guardia del Reattore,リアクターガード,발전소 경비원,Reactor bewaker,Reaktorvakt,Strażnik Reaktora,Guarda do Reator,,Gardian Reactor,Страж реактора,,Reaktorvakt,Reaktör Muhafızı +Apprentice,TXT_SPEAKER_APPRENTICE,,,,Učeň,Lærling,Lehrling,,Komencanto,Aprendiz,,Kisälli,Apprenti,Tanonc,Apprendista,見習い,도제,Leerling,Lærling,Uczeń,Aprendiz,,Ucenic,Подмастерье,,Lärling,Çırak +Door Guard,TXT_SPEAKER_DOOR_GUARD,,,,Dveřní stráž,Dørvagt,Türwache,,Pordisto,Portero,,Ovenvartija,Garde de la porte,Ajtónálló,Guardia della Porta,ドアガード,문지기,Deurwacht,Dørvakt,Strażnik Drzwi,Guarda da Porta,,Paznic,Страж входа,,Dörrvakt,Kapı Koruması +Master Smithy,TXT_SPEAKER_MASTER_SMITHY,,,,Mistr Smithy,Mester Smithy,Meister Smithy,,Majstro Smithy,Maestro Smithy,,Pajamestari,Maître Forgeron,Smithy mester,Maestro Smithy,マスター スミシー,스미시 제조장관,Meester Smithy,Mester Smithy,Mistrz Smithy,Mestre Smithy,,Maestrul Smithy,Мастер-кузнец,,Mästersmeden,Demirci Usta +Warehouse Guard,TXT_SPEAKER_WAREHOUSE_GUARD,,,,Stráž skladu,Lagervagt,Lagerhaus-Wache,,Magazena gardisto,Guardia del almacén,,Varastonvartija,Garde de l'entrepôt,Raktár Őr,Guardia del Magazzino,倉庫のガード,격납고 감시장,Magazijnwachter,Lagervakt,Strażnik Magazynu,Guarda do Depósito,,Paznic Depozit,Охранник склада,,Lagervakt,Depo Görevlisi +Barkeep,TXT_SPEAKER_BARKEEP,,,,Barman,Bartender,Wirt,,Drinkejestro,Tabernero,,Baarimikko,Barman,Bárpultos,Barman,バーテンダー,바텐더,Barman,Bartender,Barman,Taberneiro,,Barman,Хозяин таверны,,Bartender,Barmen +Timothy,TXT_SPEAKER_TIMOTHY,,,,,,,,Timoteo,,,,,,,ティモシー,티모시,,,,,,Timotei,Тимоти,,,Timothy +James,TXT_SPEAKER_JAMES,,,,,,,,,,,,,,,ジェームス,제임스,,,,,,,Джеймс,,, +Worner,TXT_SPEAKER_WORNER,,,,,,,,,,,,,,,ワーナー,워너,,,,,,,Уорнэр,,, +Bailey Guard,TXT_SPEAKER_BAILEY_GUARD,,,,Stráž opevnění,Bailey-vagt,Vorhof-Wache,,Gardisto de la fortresa korto,Guardia del patio cerrado,,Ulkomuurinvartija,Garde d'enceinte,Várfal Őr,Guardia del Bastione,ベイリー ガード,외벽 파수병,,Borggården vakt,Strażnik Murów,Guarda da Fortaleza,,Gardian Bailey,Страж крепости,,Bailey-vakt,Dış avlu bekçisi +Drone,TXT_SPEAKER_DRONE,drone ≈ slave,,,Trubec,,Drohne,,Sklavo,Esclavo,,Kuhnuri,,Drón,Schiavo,労働者,노예,,,Dron,Escravo,,Dronă,Дрон,,Drönare, +Front Guard,TXT_SPEAKER_FRONT_GUARD,,,,Stráž Fronty,Front vagt,Frontwache,,Gardisto de la Fronto,Guardia del Frente,,Rintaman vartija,Garde du Front,Front Őr,Guardia del Fronte,フロント ガード,프론트 파수꾼,Voorwacht,,Strażnik Frontu,Guarda da Frente,,Gandian Front,Повстанец,,Frontvakt,Ön Koruma +Quincy,TXT_SPEAKER_QUINCY,,,,,,,,Kvincio,,,,,,,クインシー,퀸시,,,,,,,Куинси,,,Quincy +Sergeant,TXT_SPEAKER_SERGEANT,,,,Seržant,Sergent,Feldwebel,,Serĝento,Sargento,,Kersantti,,Törzsőrmester,Sergente,軍曹,하사관,,Sersjant,Sierżant,Sargento,,Sergent,Сержант,,Sergeant,Çavuş +Temple Guard,TXT_SPEAKER_TEMPLE_GUARD,,,,Stráž chrámu,Tempelvagt,Tempelwache,,Gardisto de la templo,Guardia del templo,,Temppelinvartija,Garde du Temple,Templom Őr,Guardia del Tempio,テンプル ガード,신전 파수병,Tempelwacht,Tempelvakten,Strażnik Świątyni,Guarda do Templo,,Gardian Templu,Страж храма,,Tempelvakt,Tapınak Muhafızı +Oracle,TXT_SPEAKER_ORACLE,,,,Věštec,Orakel,Orakel,,Orakolo,Oráculo,,Oraakkeli,,Orákulum,Oracolo,オラクル,오라클,Orakel,Orakel,Wyrocznia,Oráculo,,Oracol,Оракул,,Orakel,Kahin +Ulaine,TXT_SPEAKER_ULAINE,,,,,,,,,,,,,,,ウレーヌ,울레인,,,,,,,Улейн,,,Ulane +Front Soldier,TXT_SPEAKER_FRONT_SOLDIER,,,,Voják Fronty,Frontsoldat,Front-Soldat,,Soldato de la Fronto,Soldado del Frente,,Rintaman sotilas,Soldat du Front,Front Katona,Soldato del Fronte,フロント ソルジャー,프론트 저항군,,Frontsoldat,Żołnierz Frontu,Soldado da Frente,,Soldat Front,Повстанец,,Frontsoldat,Ön Asker +Programmer,TXT_SPEAKER_PROGRAMMER,,,,Programátor,Programmør,Programmierer,,Programisto,Programador,,Ohjelmoitsija,Programmeur,Programozó,Programmatore,プログラマー,프로그래머,Programmeur,Programmerer,Programista,Programador,,Programator,Программист,,Programmerare,Programcı +Medic,TXT_SPEAKER_MEDIC,,,,Zdravotník,Læge,Sanitäter,,Kuracisto,Médico,,Lääkintämies,Médecin,Szanitéc,Medico,メディック,의무병,Paramedicus,Sanitetssoldat,Medyk,Médico,,,Медик,,Sjukvårdare, +Watchman,TXT_SPEAKER_WATCHMAN,,,,Hlídač,Vagtmand,Wächter,,Gardisto,Guardia,,Vahti,Vigie,Őrszem,Vigilante,警備員,감시병,Waker,Vaktmann,Stróż,Vigia,,Străjer,Караульный,,Väktare,Bekçi +Ketrick,TXT_SPEAKER_KETRICK,,,,,,,,,,,,,,,ケトリック,케트릭,,,,,,,Кетрик,,, +Weran,TXT_SPEAKER_WERAN,,,,,,,,,,,,,,,ウェラン,워렌,,,,,,,Уэран,,, +Advisor,TXT_SPEAKER_ADVISOR,,,Adviser,Rádce,Rådgiver,Berater,,Konsilisto,Consejero,,Neuvonantaja,Conseiller,Tanácsadó,Consigliere,補佐官,조언자,Adviseur,Rådgiver,Doradca,Conselheiro,,Sfetnic,Советник,,Rådgivare,Danışman +Geoff,TXT_SPEAKER_GEOFF,,,,,,,,,,,,,,,ジェフ,제프,,,,,,,Джефф,,,Geoff +Overseer,TXT_SPEAKER_OVERSEER,,,,Dozorčí,Tilsynsførende,Aufseher,,Inspektisto,Supervisor,,Valvoja,Superviseur,Munkavezető,Supervisore,監視人,현장 감독,Opziener,Oppsynsmann,Nadzorca,Supervisor,,Supraveghetor,Надсмотрщик,,Övervakare,Gözetmen Security Comple,TXT_SPEAKER_SECURITY_COMPLE,"Intended to appear in MAP19, but does not spawn. -",,,,Sikkerhedskomplet,Wache,,,Vigía,,Turvamies,Sécurité,,Guardia del Complesso di Sicurezza,,경비원,Bewaker,Security Comple,Ochroniarz Kompleksu,Vigia,,Paznic Complex de Securitate,Охранник комплекса,,Güvenlik Comple -Computer Tech,TXT_SPEAKER_COMPUTER_TECH,,,,Počítačový technik,,Computertechniker,,,Ingeniero Informático,,Tietokoneteknikko,Technicien Informatique,Számítógép Tech,Tecnico Informatico,機械技術者,컴퓨터 기술자,Computertechniek,Datatekniker,Technik Komputerowy,Técnico de Informática,,Tehnician Calculatoare,Компьютерный техник,,Bilgisayar Teknolojisi -MacGuffin,TXT_SPEAKER_MACGUFFIN,,,,,,,,,,,,,,,マクガフィン,맥거핀,,,,,,,Макгаффин,,MacGuffin -Arion,TXT_SPEAKER_ARION,,,,,,,,,,,,,,,アリオン,아리온,,,,,,,Арион,,Aron -Dock Worker,TXT_SPEAKER_DOCK_WORKER,,,,Přístavní dělník,Dokarbejder,Dockarbeiter,,,Trabajador del Muelle,,Ahtaaja,Docker,Dokk munkás,Operaio Portuale,港湾労働者,항구 일꾼,Dokwerker,Havnearbeider,Pracownik Doku,Operário da Doca,,Muncitor Docuri,Рабочий дока,,Liman İşçisi -Irale,TXT_SPEAKER_IRALE,,,,,,,,,,,,,,,イラール,이롤리,,,,,,,Ирэйл,,İrale -Core Guard,TXT_SPEAKER_CORE_GUARD,,,,Stráž jádra,Kernevagt,Wache,,,Guardia del Núcleo,,Ytimenvartija,Garde du cœur,Mag Őr,Guardia del Cuore,コア ガード,코어 경비병,Kernwacht,Kjernevakt,Strażnik Rdzenia,Guarda do Núcleo,,Gardian Nucleu,Страж ядра,,Çekirdek Koruma -Sewer Guard,TXT_SPEAKER_SEWER_GUARD,,,,Kanální stráž,Kloakvagt,Kanalisationswächter,,,Guardia de la Alcantarilla,,Viemärinvartija,Garde des égouts,Kanális Őr,Guardia della Fogna,下水道ガード,하수도 보초병,Rioolwacht,Kloakkvakt,Strażnik Kanałów,Guarda do Esgoto,,Gardian Canal,Страж канализации,,Kanalizasyon Görevlisi -Technician,TXT_SPEAKER_TECHNICIAN,,,,Technik,Tekniker,Techniker,,,Técnico,,Teknikko,Technicien,Technikus,Tecnico,技術者,기술자,Technicus,Tekniker,Technik,Técnico,,Tehnician,Техник,,Teknisyen -Guard,TXT_SPEAKER_GUARD,,,,Stráž,Vagt,Wache,,Gardisto,Guardia,,Vartija,Garde,Őr,Guardia,ガード,경비병,Bewaker,Vakt,Strażnik,Guarda,,Gardian,Стражник,,Muhafız -Peasant,TXT_SPEAKER_PEASANT,,,,Rolník,Bonde,Einwohner,,Kamparano,Campesino,,Maallikko,Paysan,Jobbágy,Cittadino,庶民,민간인,Boer,Bonde,Kmiot,Cidadão,,Sărman,Работник,,Köylü -Armorer,TXT_SPEAKER_ARMORER,,,Armourer,Kovář,Våbenmekaniker,Waffenmeister,,Armilisto,Armero,,Asemestari,Armurier,Fegyverkovács,Armiere,兵器係,병기공,Pantser,Væpner,Płatnerz,Forjador de Armaduras,,Armurier,Бронник,,Zırhçı -Beldin,TXT_SPEAKER_BELDIN,,,,,,,,,,,,,,,ベルディン,벨딘,,,,,,,Белдин,,Beldin -Gerard,TXT_SPEAKER_GERARD,,,,,,,,,,,,,,,ジェラルド,제랄드,,,,,,,Джерард,,Gerard -Governor Mourel,TXT_SPEAKER_GOVERNOR_MOUREL,,,,Guvernér Mourel,Guvernør Mourel,Gouverneur Mourel,,,Gobernador Mourel,,Kuvernööri Mourel,Gouverneur Mourel,Mourel kormányzó,Governatore Mourel,モーレル知事,모렐 총독,Gouverneur Mourel,Guvernør Mourel,Gubernator Mourel,Governador Mourel,,Guvernatorul Mourel,Губернатор Морел,,Vali Mourel -Bowyer,TXT_SPEAKER_BOWYER,,,,,,,,,,,,,,,ボウヤー,보여,,,,,,,Лучник,,Bowyer -Derwin,TXT_SPEAKER_DERWIN,,,,,,,,,,,,,,,ダーウィン,더윈,,,,,,,Дервин,,Derwin -,,Strife subtitles,,,,,,,,,,,,,,,,,,,,,,,, -The comet struck our planet without warning. We lost our paradise in a single violent stroke.,TXT_SUB_INTRO1,Menu's intro.,,,"Kometa bez varování narazila do naší planety. Jediným, brutálním úderem jsme přišli o náš ráj.",Kometen ramte vores planet uden varsel. Vi mistede vores paradis i et enkelt voldsomt slag.,Der Komet hat unsen Planeten ohne Vorwarnung getroffen. Wir haben unser Paradies in einem einzelnen brutalen Schlag verloren.,,,El cometa se estrelló en nuestro planeta sin previo aviso. Perdimos nuestro paraíso en un único y violento golpe.,,Komeetta iski planeettaamme varoittamatta. Menetimme paratiisimme rajulla kertarysäyksellä.,"La comète frappa notre monde sans prévenir. En un seul moment de violence, nous avons perdu notre paradis.",Egy üstökös csapódott be a bolygónkba minden előjel nélkül. Egy heves vágással elveszítettük az addigi paradicsomi életünket.,"La cometa colpì il nostro pianeta senza preavviso. Perdemmo il nostro paradiso, in un solo violento colpo.",彗星がこの星に突然衝突した。私達の楽園はこの一撃で失われた。,혜성 하나가 아무런 경고도 없이 우리 행성에 충돌했다. 그 강력한 한 방으로 우리의 낙원을 잃어버렸다.,De komeet raakte onze planeet zonder waarschuwing. We verloren ons paradijs in een enkele gewelddadige beroerte.,Kometen traff planeten vår uten forvarsel. Vi mistet paradiset vårt med ett voldsomt slag.,Kometa uderzyła w naszą planetę bez ostrzeżenia. Straciliśmy nasz raj w jednym gwałtownym uderzeniu.,"O cometa atingiu o nosso planeta sem aviso prévio. Num único e violento golpe, nós perdemos o nosso paraíso.",,Cometa ne-a izbit planeta în mod violent. Ne-am pierdut paradisul într-o clipă.,"Никто не ожидал, что на нашу планету обрушится метеорит. Земной рай был разрушен единственным безжалостным ударом.",,Kuyruklu yıldız gezegenimize uyarı vermeden çarptı. Cennetimizi tek bir şiddetli darbeyle kaybettik. +",,,,Sikkerhedskomplet,Wache,,Gardisto de la sekurkomplekso,Guardia del complejo,,Turvamies,Sécurité,Védelmi Kvártély,Guardia del Complesso di Sicurezza,,경비원,Bewaker,Security Comple,Ochroniarz Kompleksu,Vigia,,Paznic Complex de Securitate,Охранник комплекса,,Säkerhetskompetens,Güvenlik Comple +Computer Tech,TXT_SPEAKER_COMPUTER_TECH,,,,Počítačový technik,,Computertechniker,,Komputilisto,Técnico de sistemas,,Tietokoneteknikko,Technicien Informatique,Számítógép Tech,Tecnico Informatico,機械技術者,컴퓨터 기술자,Computertechniek,Datatekniker,Technik Komputerowy,Técnico de Informática,,Tehnician Calculatoare,Компьютерный техник,,Datortekniker,Bilgisayar Teknolojisi +MacGuffin,TXT_SPEAKER_MACGUFFIN,,,,,,,,Makgufino,,,,,,,マクガフィン,맥거핀,,,,,,,Макгаффин,,, +Arion,TXT_SPEAKER_ARION,,,,,,,,,,,,,,,アリオン,아리온,,,,,,,Арион,,,Aron +Dock Worker,TXT_SPEAKER_DOCK_WORKER,,,,Přístavní dělník,Dokarbejder,Dockarbeiter,,Stivisto,Estibador,,Ahtaaja,Docker,Dokk munkás,Operaio Portuale,港湾労働者,항구 일꾼,Dokwerker,Havnearbeider,Pracownik Doku,Operário da Doca,,Muncitor Docuri,Рабочий дока,,Hamnarbetare,Liman İşçisi +Irale,TXT_SPEAKER_IRALE,,,,,,,,,,,,,,,イラール,이롤리,,,,,,,Ирэйл,,,İrale +Core Guard,TXT_SPEAKER_CORE_GUARD,,,,Stráž jádra,Kernevagt,Wache,,Gardisto de la kerno,Guardia del núcleo,,Ytimenvartija,Garde du cœur,Mag Őr,Guardia del Cuore,コア ガード,코어 경비병,Kernwacht,Kjernevakt,Strażnik Rdzenia,Guarda do Núcleo,,Gardian Nucleu,Страж ядра,,Kärnvårdsvakt,Çekirdek Koruma +Sewer Guard,TXT_SPEAKER_SEWER_GUARD,,,,Kanální stráž,Kloakvagt,Kanalisationswächter,,Gardisto de la kloako,Guardia de las alcantarillas,,Viemärinvartija,Garde des égouts,Kanális Őr,Guardia della Fogna,下水道ガード,하수도 보초병,Rioolwacht,Kloakkvakt,Strażnik Kanałów,Guarda do Esgoto,,Gardian Canal,Страж канализации,,Avloppsvakt,Kanalizasyon Görevlisi +Technician,TXT_SPEAKER_TECHNICIAN,,,,Technik,Tekniker,Techniker,,Teknikisto,Técnico,,Teknikko,Technicien,Technikus,Tecnico,技術者,기술자,Technicus,Tekniker,Technik,Técnico,,Tehnician,Техник,,Tekniker,Teknisyen +Guard,TXT_SPEAKER_GUARD,,,,Stráž,Vagt,Wache,,Gardisto,Guardia,,Vartija,Garde,Őr,Guardia,ガード,경비병,Bewaker,Vakt,Strażnik,Guarda,,Gardian,Стражник,,Väktare,Muhafız +Peasant,TXT_SPEAKER_PEASANT,,,,Rolník,Bonde,Einwohner,,Kamparano,Campesino,,Maallikko,Paysan,Jobbágy,Cittadino,庶民,민간인,Boer,Bonde,Kmiot,Cidadão,,Sărman,Работник,,Bonde,Köylü +Armorer,TXT_SPEAKER_ARMORER,,,Armourer,Kovář,Våbenmekaniker,Waffenmeister,,Armilisto,Armero,,Asemestari,Armurier,Fegyverkovács,Armiere,兵器係,병기공,Pantser,Væpner,Płatnerz,Forjador de Armaduras,,Armurier,Бронник,,Rusthållare,Zırhçı +Beldin,TXT_SPEAKER_BELDIN,,,,,,,,,,,,,,,ベルディン,벨딘,,,,,,,Белдин,,, +Gerard,TXT_SPEAKER_GERARD,,,,,,,,Gerardo,,,,,,,ジェラルド,제랄드,,,,,,,Джерард,,, +Governor Mourel,TXT_SPEAKER_GOVERNOR_MOUREL,,,,Guvernér Mourel,Guvernør Mourel,Gouverneur Mourel,,Registo Mourel,Gobernador Mourel,,Kuvernööri Mourel,Gouverneur Mourel,Mourel kormányzó,Governatore Mourel,モーレル知事,모렐 총독,Gouverneur Mourel,Guvernør Mourel,Gubernator Mourel,Governador Mourel,,Guvernatorul Mourel,Губернатор Морел,,Guvernör Mourel,Vali Mourel +Bowyer,TXT_SPEAKER_BOWYER,,,,,,,,,,,,,,,ボウヤー,보여,,,,,,,Лучник,,, +Derwin,TXT_SPEAKER_DERWIN,,,,,,,,,,,,,,,ダーウィン,더윈,,,,,,,Дервин,,, +,,Strife subtitles,,,,,,,,,,,,,,,,,,,,,,,,, +The comet struck our planet without warning. We lost our paradise in a single violent stroke.,TXT_SUB_INTRO1,Menu's intro.,,,"Kometa bez varování narazila do naší planety. Jediným, brutálním úderem jsme přišli o náš ráj.",Kometen ramte vores planet uden varsel. Vi mistede vores paradis i et enkelt voldsomt slag.,Der Komet hat unsen Planeten ohne Vorwarnung getroffen. Wir haben unser Paradies in einem einzelnen brutalen Schlag verloren.,,,El cometa se estrelló en nuestro planeta sin previo aviso. Perdimos nuestro paraíso en un único y violento golpe.,,Komeetta iski planeettaamme varoittamatta. Menetimme paratiisimme rajulla kertarysäyksellä.,"La comète frappa notre monde sans prévenir. En un seul moment de violence, nous avons perdu notre paradis.",Egy üstökös csapódott be a bolygónkba minden előjel nélkül. Egy heves vágással elveszítettük az addigi paradicsomi életünket.,"La cometa colpì il nostro pianeta senza preavviso. Perdemmo il nostro paradiso, in un solo violento colpo.",彗星がこの星に突然衝突した。私達の楽園はこの一撃で失われた。,혜성 하나가 아무런 경고도 없이 우리 행성에 충돌했다. 그 강력한 한 방으로 우리의 낙원을 잃어버렸다.,De komeet raakte onze planeet zonder waarschuwing. We verloren ons paradijs in een enkele gewelddadige beroerte.,Kometen traff planeten vår uten forvarsel. Vi mistet paradiset vårt med ett voldsomt slag.,Kometa uderzyła w naszą planetę bez ostrzeżenia. Straciliśmy nasz raj w jednym gwałtownym uderzeniu.,"O cometa atingiu o nosso planeta sem aviso prévio. Num único e violento golpe, nós perdemos o nosso paraíso.",,Cometa ne-a izbit planeta în mod violent. Ne-am pierdut paradisul într-o clipă.,"Никто не ожидал, что на нашу планету обрушится метеорит. Земной рай был разрушен единственным безжалостным ударом.",,Kometen träffade vår planet utan förvarning. Vi förlorade vårt paradis i ett enda våldsamt slag.,Kuyruklu yıldız gezegenimize uyarı vermeden çarptı. Cennetimizi tek bir şiddetli darbeyle kaybettik. "The impact released a virus, which swept through the land and killed millions. They turned out to be the lucky ones.",TXT_SUB_INTRO2,〃,,,"Náraz vypustil virus, který se začal šířit krajem a zabil miliony lidí. Ukázalo se, že to byli ti šťastnější.","Sammenstødet frigjorde en virus, som fejede gennem landet og dræbte millioner af mennesker. De viste sig at være de heldige.","Der Einschlag setzte einen Virus frei, der durch das Land fegte und Millionen tötete. Sie hatten Glück.",,,"El impacto liberó un virus, el cual barrió la tierra y mató a millones. Resultaron ser los más afortunados.",,"Törmäys päästi valloilleen viruksen, joka pyyhkäisi halki maan ja tappoi miljoonia. He osoittautuivat kuuluneensa onnekkaiden joukkoon.","L'impact libéra un virus, qui traversa les contrées et tua des millions. Ceux qui moururent furent les plus chanceux.","A becsapódás egy vírust eresztett a világra, mely milliókat ölt meg. Ők voltak a szerencsésebbek.","L'impatto rilasciò un virus, spargendosi ovunque e uccidendo milioni. Quelli che morirono furono i più fortunati.","彗星の衝突によりウィルスが世界中に放たれ、数えきれないほどの人々が死んだ。 -今から考えれば、彼らはまだ運がいい方だった。","충돌의 여파로 바이러스가 사방에 퍼졌고, 이로 인해 수백만명이 목숨을 잃었다. 죽은 자들은 운이 좋은 자들이었다.","Door de inslag kwam er een virus vrij, dat door het land veegde en miljoenen doden veroorzaakte. Zij bleken de gelukkigen te zijn.",Nedslaget utløste et virus som feide gjennom landet og drepte millioner. De viste seg å være de heldige.,"Uderzenie uwolniło wirusa, który przetoczył się przez ziemię i zabił miliony. Okazało się, że byli to ci, którzy mieli szczęście.","O impacto liberou um vírus, que se espalhou pela terra e matou milhões. Esses foram os que tiveram sorte.",,"Impactul a lansat un virus, care a măturat pământul și omorât milioane. Aparent ei au fost cei norocoși.","Удар метеорита выпустил вирус, который пронёсся по землям и истребил миллионы людей. Умершие оказались счастливчиками.",,Çarpışmanın etkisiyle bir virüs salındı ve bu virüs tüm dünyayı kasıp kavurarak milyonları öldürdü. Onlar şanslı olanlardı. +今から考えれば、彼らはまだ運がいい方だった。","충돌의 여파로 바이러스가 사방에 퍼졌고, 이로 인해 수백만명이 목숨을 잃었다. 죽은 자들은 운이 좋은 자들이었다.","Door de inslag kwam er een virus vrij, dat door het land veegde en miljoenen doden veroorzaakte. Zij bleken de gelukkigen te zijn.",Nedslaget utløste et virus som feide gjennom landet og drepte millioner. De viste seg å være de heldige.,"Uderzenie uwolniło wirusa, który przetoczył się przez ziemię i zabił miliony. Okazało się, że byli to ci, którzy mieli szczęście.","O impacto liberou um vírus, que se espalhou pela terra e matou milhões. Esses foram os que tiveram sorte.",,"Impactul a lansat un virus, care a măturat pământul și omorât milioane. Aparent ei au fost cei norocoși.","Удар метеорита выпустил вирус, который пронёсся по землям и истребил миллионы людей. Умершие оказались счастливчиками.",,Genom nedslaget frigjordes ett virus som svepte genom landet och dödade miljontals människor. De visade sig vara de lyckligt lottade.,Çarpışmanın etkisiyle bir virüs salındı ve bu virüs tüm dünyayı kasıp kavurarak milyonları öldürdü. Onlar şanslı olanlardı. "For those who did not die became mutations of humanity. Some became fanatics who heard the voice of a malignant god in their heads and called themselves ""the Order"".",TXT_SUB_INTRO3,〃,,,"Ti, kteří nezemřeli, se totiž stali lidskými mutanty. Někteří se proměnili ve fanatiky, kteří v hlavě začali slyšet hlas zlého boha, a začali si říkat „Řád“.","For de, der ikke døde, blev til mutationer af menneskeheden. Nogle blev fanatikere, der hørte en ondskabsfuld guds stemme i deres hoveder og kaldte sig selv ""Ordenen"".","Diejenigen, die nicht starben, wurden zu Mutanten der Menschheit. Einige wurden Fanatiker, die die Stimme eines bösartigen Gottes in ihrem Kopf hörten und sie nannten sich „Der Orden“.",,,"Ya que aquellos que no murieron se convirtieron en mutaciones de humanidad. Algunos se volvieron fanáticos que oían la voz de un dios maligno en sus cabezas y se hicieron llamar ""la Orden"".",,"Sillä niistä, jotka eivät kuolleet, tuli ihmiskunnan mutaatioita. Joistakin tuli kiihkoilijoita, jotka kuulivat päässään pahansuovan jumalan äänen ja kutsuivat itseään ""Veljeskunnaksi"".","Ceux qui survécurent devinrent les mutants de l'humanité. Certains devinrent des fanatiques qui écoutent la voix d'un dieu maléfique dans leur tête, et se nommèrent « L'Ordre ».","Akik nem haltak meg, emberi mutánsokká válltak. Voltak akik fanatikussá válltak, fejükbe hallották egy gonosz isten szavait, és a ""Rend"" néven hívták magukat.","Coloro che sopravvissero divennero i mutanti dell'umanità. Alcuni sono diventati fanatici che hanno ascoltato la voce di un dio malvagio nelle loro teste e si sono fatti chiamare ""L'Ordine"".","死ななかった人々は、人間から変異して別の物となった。 一部の人々は、頭の中に邪悪な神の声を伝えられた狂信者となり、 -自らの集団を'オーダー'と呼んだ。","죽지 않은 자들에겐 큰 변화가 일어났다. 몇몇은 머릿속으로 악독한 신의 목소리를 듣기 시작했고, 이 광신도들은 그들 자신을 “오더”라고 지칭했다.","Voor degenen die niet stierven werden mutaties van de mensheid. Sommigen werden fanatiekelingen die de stem van een kwaadaardige god in hun hoofd hoorden en zichzelf ""de Orde"" noemden.","For de som ikke døde, ble mutasjoner av menneskeheten. Noen ble fanatikere som hørte stemmen til en ondartet gud i hodet og kalte seg ""Ordenen"".","Ci bowiem, którzy nie zginęli, stali się mutacjami ludzkości. Niektórzy stali się fanatykami, którzy słyszeli w swoich głowach głos złośliwego boga i nazywali siebie ""Zakonem"".","Aqueles que sobreviveram se tornaram mutações de humanidade. Alguns se tornaram fanáticos que ouviam em suas cabeças a voz de um deus malígno e passaram a se chamar ""a Ordem"".",,"Pentru că cei care nu au murit au ajuns mutanți. Unii au devenit fanatici care au auzit vocea unui zeu perfid în capul lor și s-au numit ""Ordinul"".","Выжившие сформировали уродливое подобие прежнего общества. Некоторые услышали голос зловещего бога и стали фанатиками, называющими себя «Орденом».",,"Ölmeyenler ise insanlığın mutasyonları oldular. Bazıları kafalarının içinde kötücül bir tanrının sesini duyan ve kendilerine ""Düzen"" diyen fanatikler haline geldi." -Those of us who are deaf to this voice suffer horribly and are forced to serve these ruthless psychotics who wield weapons more powerful than anything we can muster.,TXT_SUB_INTRO4,〃,,,"Ti z nás, kdo jsou vůči tomuto hlasu hluší, příšerně trpí a jsou nuceni sloužit těmto bezcitným šílencům, kteří vládnou zbraněmi, proti kterým nemáme šanci se bránit.","De af os, der er døve for denne stemme, lider forfærdeligt og er tvunget til at tjene disse hensynsløse psykopater, der svinger våben, der er stærkere end alt, hvad vi kan mønstre.","Jene, die dieser Stimme gegenüber taub sind, leiden schrecklich und sind gezwungen diesen unbarmherzigen Irren zu dienen. Sie haben Waffen die stärker sind als das, was wir aufbringen können.",,,Aquellos de nosotros sordos a esta voz sufrimos horriblemente y somos forzados a servir a estos psicópatas despiadados que poseen armas más poderosas que cualesquiera que podamos conseguir.,,"Meistä ne, jotka ovat kuuroja tälle äänelle, kärsivät valtavasti ja joutuvat palvelemaan näitä häikäilemättömiä sekopäitä, jotka pitävät hallussaan voimakkaampia aseita kuin me ikinä kykenemme käsiimme saamaan.",Ceux sourds à sa voix souffrent horriblement et sont forcés à vivre au services de ces vicieux psychopathes qui utilisent des armes plus puissantes que tout ce que nous avons.,"Azok akik nem hallják ezeket a hangokat megszenvedik azt, és arra vannak kárhoztatva, hogy ezeket az isten feletti fegyverekkel rendelkező kegyetlen elmebetegeket szolgálják.",Quelli sordi alla sua voce soffrono orribilmente e sono costretti a vivere al servizio di questi malvagi psicopatici che usano armi più potenti di ogni cosa che noi abbiamo.,"その神の声を聞き取れなかった私達は苦しんだ挙げ句、 +自らの集団を'オーダー'と呼んだ。","죽지 않은 자들에겐 큰 변화가 일어났다. 몇몇은 머릿속으로 악독한 신의 목소리를 듣기 시작했고, 이 광신도들은 그들 자신을 “오더”라고 지칭했다.","Voor degenen die niet stierven werden mutaties van de mensheid. Sommigen werden fanatiekelingen die de stem van een kwaadaardige god in hun hoofd hoorden en zichzelf ""de Orde"" noemden.","For de som ikke døde, ble mutasjoner av menneskeheten. Noen ble fanatikere som hørte stemmen til en ondartet gud i hodet og kalte seg ""Ordenen"".","Ci bowiem, którzy nie zginęli, stali się mutacjami ludzkości. Niektórzy stali się fanatykami, którzy słyszeli w swoich głowach głos złośliwego boga i nazywali siebie ""Zakonem"".","Aqueles que sobreviveram se tornaram mutações de humanidade. Alguns se tornaram fanáticos que ouviam em suas cabeças a voz de um deus malígno e passaram a se chamar ""a Ordem"".",,"Pentru că cei care nu au murit au ajuns mutanți. Unii au devenit fanatici care au auzit vocea unui zeu perfid în capul lor și s-au numit ""Ordinul"".","Выжившие сформировали уродливое подобие прежнего общества. Некоторые услышали голос зловещего бога и стали фанатиками, называющими себя «Орденом».",,"För de som inte dog blev mutationer av mänskligheten. Några blev fanatiker som hörde en ondskefull guds röst i sina huvuden och kallade sig själva för ""Orden"".","Ölmeyenler ise insanlığın mutasyonları oldular. Bazıları kafalarının içinde kötücül bir tanrının sesini duyan ve kendilerine ""Düzen"" diyen fanatikler haline geldi." +Those of us who are deaf to this voice suffer horribly and are forced to serve these ruthless psychotics who wield weapons more powerful than anything we can muster.,TXT_SUB_INTRO4,〃,,,"Ti z nás, kdo jsou vůči tomuto hlasu hluší, příšerně trpí a jsou nuceni sloužit těmto bezcitným šílencům, kteří vládnou zbraněmi, proti kterým nemáme šanci se bránit.","De af os, der er døve for denne stemme, lider forfærdeligt og er tvunget til at tjene disse hensynsløse psykopater, der svinger våben, der er stærkere end alt, hvad vi kan mønstre.","Jene, die dieser Stimme gegenüber taub sind, leiden schrecklich und sind gezwungen diesen unbarmherzigen Irren zu dienen. Sie haben Waffen die stärker sind als das, was wir aufbringen können.",,,Aquellos incapaces de oír esa voz sufrimos horriblemente y somos forzados a servir a estos psicopáticos despiadados que poseen armas más poderosas que cualesquiera que podamos conseguir.,,"Meistä ne, jotka ovat kuuroja tälle äänelle, kärsivät valtavasti ja joutuvat palvelemaan näitä häikäilemättömiä sekopäitä, jotka pitävät hallussaan voimakkaampia aseita kuin me ikinä kykenemme käsiimme saamaan.",Ceux sourds à sa voix souffrent horriblement et sont forcés à vivre au services de ces vicieux psychopathes qui utilisent des armes plus puissantes que tout ce que nous avons.,"Azok akik nem hallják ezeket a hangokat megszenvedik azt, és arra vannak kárhoztatva, hogy ezeket az isten feletti fegyverekkel rendelkező kegyetlen elmebetegeket szolgálják.",Quelli sordi alla sua voce soffrono orribilmente e sono costretti a vivere al servizio di questi malvagi psicopatici che usano armi più potenti di ogni cosa che noi abbiamo.,"その神の声を聞き取れなかった私達は苦しんだ挙げ句、 この無慈悲な狂人どもに仕えるのを強いられた。 -そして奴等は、私達のどんな武器とも比べ物にならないほど強力な兵器を持っているのだ。","신의 목소리를 듣지 못하는 자들은 끔찍한 고통에 시달렸고, 우리가 가진 어떤 무기들보다 강력한 무장을 한 이 무자비한 광신도들을 강제로 섬기게 되었다.","Degenen onder ons die doof zijn voor deze stem lijden vreselijk en worden gedwongen om deze meedogenloze psychoten te dienen, die wapens gebruiken die krachtiger zijn dan alles wat we kunnen verzamelen.","De av oss som er døve for denne stemmen, lider forferdelig og er tvunget til å tjene disse hensynsløse psykotiske som bruker våpen som er kraftigere enn noe vi kan mønstre.","Ci z nas, którzy są głusi na ten głos, cierpią okropnie i są zmuszeni służyć tym bezwzględnym psychotom, którzy władają bronią potężniejszą niż wszystko, co jesteśmy w stanie zebrać.",Nós que não ouvimos essa voz sofremos terrívelmente e somos forçados a servir a esses psicopatas impiedosos que possuem armas mais poderosas do que qualquer coisa ao nosso alcance.,,Noi cei care suntem surzi și nu auzim vocea suferim oribil și suntem forțați să servin pe acești psihopați care cârmuie arme mai puternice decat orice avem.,"Другие — те, кто не слышал этого голоса, — терпели лишения. Их заставили прислуживать этим безжалостным психопатам, чьё оружие превосходило любое наше.",,Bu sese kulaklarını tıkayan bizler ise korkunç acılar çekiyor ve ellerinde toplayabileceğimiz her şeyden daha güçlü silahlar olan bu acımasız psikopatlara hizmet etmek zorunda kalıyoruz. +そして奴等は、私達のどんな武器とも比べ物にならないほど強力な兵器を持っているのだ。","신의 목소리를 듣지 못하는 자들은 끔찍한 고통에 시달렸고, 우리가 가진 어떤 무기들보다 강력한 무장을 한 이 무자비한 광신도들을 강제로 섬기게 되었다.","Degenen onder ons die doof zijn voor deze stem lijden vreselijk en worden gedwongen om deze meedogenloze psychoten te dienen, die wapens gebruiken die krachtiger zijn dan alles wat we kunnen verzamelen.","De av oss som er døve for denne stemmen, lider forferdelig og er tvunget til å tjene disse hensynsløse psykotiske som bruker våpen som er kraftigere enn noe vi kan mønstre.","Ci z nas, którzy są głusi na ten głos, cierpią okropnie i są zmuszeni służyć tym bezwzględnym psychotom, którzy władają bronią potężniejszą niż wszystko, co jesteśmy w stanie zebrać.",Nós que não ouvimos essa voz sofremos terrívelmente e somos forçados a servir a esses psicopatas impiedosos que possuem armas mais poderosas do que qualquer coisa ao nosso alcance.,,Noi cei care suntem surzi și nu auzim vocea suferim oribil și suntem forțați să servin pe acești psihopați care cârmuie arme mai puternice decat orice avem.,"Другие — те, кто не слышал этого голоса, — терпели лишения. Их заставили прислуживать этим безжалостным психопатам, чьё оружие превосходило любое наше.",,De av oss som är döva för denna röst lider fruktansvärt och tvingas tjäna dessa hänsynslösa psykopater som svingar vapen som är kraftfullare än allt vi kan uppbåda.,Bu sese kulaklarını tıkayan bizler ise korkunç acılar çekiyor ve ellerinde toplayabileceğimiz her şeyden daha güçlü silahlar olan bu acımasız psikopatlara hizmet etmek zorunda kalıyoruz. They destroy our women and children so that we must hide them underground and live like animals in constant fear for our lives.,TXT_SUB_INTRO5,〃,,,"Zabíjí naše ženy a děti, takže je musíme ukrývat v podzemí a nechávat je žít jako zvířata v neutrvajícím strachu o naše životy.","De ødelægger vores kvinder og børn, så vi må gemme dem under jorden og leve som dyr i konstant frygt for vores liv.","Sie zerstören unsere Frauen und Kinder, sodass wir uns im Untergrund verstecken müssen, wie die Tiere leben und ständig um unser Leben zu bangen.",,,Destruyen a nuestras mujeres y niños por lo que debemos esconderlos bajo tierra y vivir como animales temiendo constantemente por nuestras vidas.,,"He tuhoavat naisemme ja lapsemme, niin että joudumme kätkemään heidät maan alle ja elämään kuin elukat jatkuvassa pelossa henkemme puolesta.","Ils ont anéanti nos femmes et nos enfants et nous ont forcés à vivre sous terre comme des animaux, terrifiés de perdre nos vies.","Megölik a nőinket és gyermekeinket, ezért a föld alatt kell rejtegetnünk őket, és úgy kell élnünk mint az életét féltő állatoknak.","Distruggono le nostre donne e bambini, per cui li dobbiamo nascondere nel sottosuolo e vivere come animali in una paura costante per le nostre vite.","奴等は女性や子供を殺害していくため、私達はそういった人々を地下に隠さなければならなかった。 -我々は動物のように暮らすのを強いられ、命は常に危険に晒されている。","그들은 우리의 여자와 아이들을 죽였고, 우리는 살아남은 자들을 지하로 대피시켜 죽음의 공포 속에서 짐승처럼 살아가야 했다.",Ze vernietigen onze vrouwen en kinderen zodat we ze ondergronds moeten verbergen en als dieren moeten leven in voortdurende angst voor ons leven.,De ødelegger våre kvinner og barn slik at vi må gjemme dem under jorden og leve som dyr i konstant frykt for våre liv.,"Niszczą nasze kobiety i dzieci tak, że musimy ukrywać je pod ziemią i żyć jak zwierzęta w ciągłym strachu o nasze życie.","Eles destroem nossas mulheres e crianças e por isso nós temos que escondê-las no subterrâneo e viver como animais, temendo constantemente por nossas vidas.",,"Ne distrug femeile și copiii pentru ca noi să ne ascundem sub pământ și să trăim ca animalele, constant în teamă pentru virțiile noastre.","Они истребляют наших женщин и детей, и нам приходится прятать их в подземелье. Мы живём в постоянном страхе за свою жизнь, как животные.",,"Kadınlarımızı ve çocuklarımızı yok ediyorlar, böylece onları yeraltına saklamak ve hayatlarımız için sürekli korku içinde hayvanlar gibi yaşamak zorunda kalıyoruz." +我々は動物のように暮らすのを強いられ、命は常に危険に晒されている。","그들은 우리의 여자와 아이들을 죽였고, 우리는 살아남은 자들을 지하로 대피시켜 죽음의 공포 속에서 짐승처럼 살아가야 했다.",Ze vernietigen onze vrouwen en kinderen zodat we ze ondergronds moeten verbergen en als dieren moeten leven in voortdurende angst voor ons leven.,De ødelegger våre kvinner og barn slik at vi må gjemme dem under jorden og leve som dyr i konstant frykt for våre liv.,"Niszczą nasze kobiety i dzieci tak, że musimy ukrywać je pod ziemią i żyć jak zwierzęta w ciągłym strachu o nasze życie.","Eles destroem nossas mulheres e crianças e por isso nós temos que escondê-las no subterrâneo e viver como animais, temendo constantemente por nossas vidas.",,"Ne distrug femeile și copiii pentru ca noi să ne ascundem sub pământ și să trăim ca animalele, constant în teamă pentru virțiile noastre.","Они истребляют наших женщин и детей, и нам приходится прятать их в подземелье. Мы живём в постоянном страхе за свою жизнь, как животные.",,De förstör våra kvinnor och barn så att vi måste gömma dem under jorden och leva som djur i ständig rädsla för våra liv.,"Kadınlarımızı ve çocuklarımızı yok ediyorlar, böylece onları yeraltına saklamak ve hayatlarımız için sürekli korku içinde hayvanlar gibi yaşamak zorunda kalıyoruz." "But there are whispers of discontent. If we organize, can we defeat our masters? Weapons are being stolen, soldiers are being trained. A movement is born: born of lifelong strife!",TXT_SUB_INTRO6,〃,,,"Vynořují se však nesouhlasná šeptání. Pokud se seskupíme, můžeme porazit naše pány? Kradou se zbraně, cvičí se vojáci. Zrodilo se hnutí, zrozené z věčného sváru!","Men der er hvisken af utilfredshed. Hvis vi organiserer os, kan vi så besejre vores herrer? Våben bliver stjålet, soldater bliver uddannet. En bevægelse er født: født af livslange stridigheder!","Aber es gibt Zeichen der Unzufriedenheit. Wenn wir uns organisieren, können wir unsere Meister besiegen? Waffen werden gestohlen, Soldaten ausgebildet. Eine Bewegung wurde geboren: Geboren aus dem ewigen Konflikt!",,,"Pero hay susurros de descontento. Si nos organizamos, ¿podemos derrotar a nuestros maestros? Se están robando armas, se entrenan soldados. Un movimiento nace - ¡nacido de una lucha de por vida!",,"Mutta tyytymättömyyden äänet kuiskailevat. Jos järjestäydymme, kykenemmekö päihittämään valtiaamme? Aseita anastetaan, sotilaita koulutetaan. Liike on syntynyt, syntynyt elinikäisestä taistelusta!","Mais il y a des murmures de colère qui subsistent. Si nous nous organisons, pouvons nous nous défaire de nos maîtres? Des armes sont volées, des soldats entraînés. Un mouvement est né, né d'un combat sans fin!","Azonban zúgolódó sutyorgásokat hallani. Ha összefogunk vajon legyőzhetjük elnyomóinkat? Fegyvereket lopkodunk, katonákat képzünk. Egy mozgalom születik: az emberöltőnyi küzdelem születik!","Ma ci sono voci di discontento. Se ci organizzassimo, potremmo sconfiggere i nostri padroni? Vengono rubate le armi, vengono addestrati i soldati. È nato un movimento: nato da un eterno conflitto!","だが不満のささやきは常にある。もし私達が力を合わせれば、 支配者たちを倒すことができるだろうか? 奴等の武器は盗まれ続けていて、 我らの兵士たちは訓練され続けている。 -革命への動きは生まれたのだ- 終わりなき闘争(Strife)から!","그러나 불만의 목소리가 커졌다. 우리가 단결하면, 우리의 주인을 물리칠 수 있을까? 그들의 무기를 훔치고, 병사들을 훈련해서 우리의 평생을 바칠 투쟁이 시작된 것이다!","Maar er wordt gefluisterd van ontevredenheid. Als we ons organiseren, kunnen we dan onze meesters verslaan? Wapens worden gestolen, soldaten worden getraind. Een beweging is geboren: geboren uit levenslange strijd!","Men det hviskes om misnøye. Hvis vi organiserer oss, kan vi beseire våre herrer? Våpen blir stjålet, soldater blir trent. En bevegelse er født: født av livslang strid!","Ale są szepty niezadowolenia. Jeśli się zorganizujemy, czy uda nam się pokonać naszych panów? Broń jest kradziona, żołnierze są szkoleni. Rodzi się ruch: zrodzony z życiowej walki!","Mas há sussurros de descontentamento. Se nós nos organizarmos, será que podemos derrotar os nossos mestres? Armas estão sendo roubadas, soldados estão sendo treinados. Um movimento está nascendo. Nascendo por meio de um conflito sem fim!",,"Dar există șoapte ale neliniștii. Dacă ne organizam, am putea să ne înfrângem stăpânii? Armele sunt furate, soldații antrenați. O mișcare se naște: născută din suferința de o viață!","Но шёпот недовольства растёт. Сможем ли мы свергнуть их господство, если объединимся? Мы крадём их оружие, и наши бойцы проходят подготовку. Движение родилось — родилось из борьбы длиною в жизнь!",,"Ama hoşnutsuzluk fısıltıları var. Eğer örgütlenirsek, efendilerimizi yenebilir miyiz? Silahlar çalınıyor, askerler eğitiliyor. Bir hareket doğuyor: yaşam boyu süren mücadeleden doğuyor!" -"Attention, all troops of the Front: he's done it! It's over. Blackbird's soldier has killed the Evil. The Order is no more. Blackbird, do you read me?",TXT_SUB_GOOD1,,,,"Pozor, všechny jednotky Fronty: On to dokázal! Je konec. Straččin voják zabil Zlo. Řád už není. Strako, slyšíš mě?","Hør efter, alle fronttropper: Han har gjort det! Det er slut. Blackbird's soldat har dræbt Ondskaben. Ordenen er ikke mere. Blackbird, kan du høre mig?","Achtung, alle Truppen der Front: Er hat es getan! Es ist vorbei.Blackbirds Soldat hat das Böse vernichtet. Den Orden gibt es nicht mehr. Blackbird, kannst du mich hören?",,,"Atención, todas las tropas del Frente: ¡lo ha hecho! Se acabó. El soldado de Blackbird ha matado al Mal. Es el fin de la Orden. Blackbird, ¿me recibes?",,"Huomio, kaikki Rintaman joukot: Hän teki sen! Se on ohi; Blackbirdin sotilas on tappanut Pahan. Veljeskuntaa ei enää ole. Blackbird, kuuletko minua?","Attention à toutes les troupes du Front: Nous avons réussi! C'est fini, le soldat de Blackbird a anéanti le mal. L'Ordre est sur le point de s'effondrer. Blackbird, me recevez-vous?","Figyelem a Front összes katonájának: megcsinálta! Vége van. Feketerigó katonája megölte magát a gonoszt. A rend nincs többé. Feketerigó, veszed az adást?","Attenzione a tutte le truppe del Fronte: ce l'ha fatta! È finita. Il soldato di Blackbird ha ucciso il Male. L'Ordine non esiste più. Blackbird, mi senti?","フロントの兵士たちよ、聞きたまえ! 彼がすべてを終わらせたのだ。 +革命への動きは生まれたのだ- 終わりなき闘争(Strife)から!","그러나 불만의 목소리가 커졌다. 우리가 단결하면, 우리의 주인을 물리칠 수 있을까? 그들의 무기를 훔치고, 병사들을 훈련해서 우리의 평생을 바칠 투쟁이 시작된 것이다!","Maar er wordt gefluisterd van ontevredenheid. Als we ons organiseren, kunnen we dan onze meesters verslaan? Wapens worden gestolen, soldaten worden getraind. Een beweging is geboren: geboren uit levenslange strijd!","Men det hviskes om misnøye. Hvis vi organiserer oss, kan vi beseire våre herrer? Våpen blir stjålet, soldater blir trent. En bevegelse er født: født av livslang strid!","Ale są szepty niezadowolenia. Jeśli się zorganizujemy, czy uda nam się pokonać naszych panów? Broń jest kradziona, żołnierze są szkoleni. Rodzi się ruch: zrodzony z życiowej walki!","Mas há sussurros de descontentamento. Se nós nos organizarmos, será que podemos derrotar os nossos mestres? Armas estão sendo roubadas, soldados estão sendo treinados. Um movimento está nascendo. Nascendo por meio de um conflito sem fim!",,"Dar există șoapte ale neliniștii. Dacă ne organizam, am putea să ne înfrângem stăpânii? Armele sunt furate, soldații antrenați. O mișcare se naște: născută din suferința de o viață!","Но шёпот недовольства растёт. Сможем ли мы свергнуть их господство, если объединимся? Мы крадём их оружие, и наши бойцы проходят подготовку. Движение родилось — родилось из борьбы длиною в жизнь!",,"Men det finns viskningar av missnöje. Om vi organiserar oss kan vi besegra våra herrar? Vapen stjäls, soldater utbildas. En rörelse är född: född av livslång strid!","Ama hoşnutsuzluk fısıltıları var. Eğer örgütlenirsek, efendilerimizi yenebilir miyiz? Silahlar çalınıyor, askerler eğitiliyor. Bir hareket doğuyor: yaşam boyu süren mücadeleden doğuyor!" +"Attention, all troops of the Front: he's done it! It's over. Blackbird's soldier has killed the Evil. The Order is no more. Blackbird, do you read me?",TXT_SUB_GOOD1,Best ending.,,,"Pozor, všechny jednotky Fronty: On to dokázal! Je konec. Straččin voják zabil Zlo. Řád už není. Strako, slyšíš mě?","Hør efter, alle fronttropper: Han har gjort det! Det er slut. Blackbird's soldat har dræbt Ondskaben. Ordenen er ikke mere. Blackbird, kan du høre mig?","Achtung, alle Truppen der Front: Er hat es getan! Es ist vorbei.Blackbirds Soldat hat das Böse vernichtet. Den Orden gibt es nicht mehr. Blackbird, kannst du mich hören?",,,"Atención, todas las tropas del Frente: ¡lo ha hecho! Se acabó. El soldado de Blackbird ha matado al Mal. Es el fin de la Orden. Blackbird, ¿me recibes?",,"Huomio, kaikki Rintaman joukot: Hän teki sen! Se on ohi; Blackbirdin sotilas on tappanut Pahan. Veljeskuntaa ei enää ole. Blackbird, kuuletko minua?","Attention à toutes les troupes du Front: Nous avons réussi! C'est fini, le soldat de Blackbird a anéanti le mal. L'Ordre est sur le point de s'effondrer. Blackbird, me recevez-vous?","Figyelem a Front összes katonájának: megcsinálta! Vége van. Feketerigó katonája megölte magát a gonoszt. A rend nincs többé. Feketerigó, veszed az adást?","Attenzione a tutte le truppe del Fronte: ce l'ha fatta! È finita. Il soldato di Blackbird ha ucciso il Male. L'Ordine non esiste più. Blackbird, mi senti?","フロントの兵士たちよ、聞きたまえ! 彼がすべてを終わらせたのだ。 もうこれで何もかも終わりだ。ブラックバードの兵士が悪を滅ぼしたのだ。 -オーダーはもう存在しない。ブラックバード、聞こえるか?","프론트의 모든 병사는 주목하라. 그가 해냈다! 모든 것이 끝났다. 블랙버드의 병사가 악을 물리치고, 오더는 끝장이 났다. 블랙버드, 내 말 듣고 있나?","Opgelet, alle troepen van het Front: hij heeft het gedaan! Het is voorbij. Blackbird's soldaat heeft het Kwaad gedood. De Orde is niet meer. Blackbird, hoort jou mij?","Oppmerksomhet, alle tropper fra fronten: han har gjort det! Det er over. Blackbirds soldat har drept Ondskapen. Ordenen eksisterer ikke lenger. Blackbird, hører du meg?","Uwaga, wszystkie oddziały Frontu: udało mu się! To już koniec. Żołnierz Blackbird zabił Zło. Nie ma już Zakonu. Blackbird, czy mnie słyszysz?","Atenção, todas as tropas da Frente: ele conseguiu! Está tudo acabado. O soldado de Blackbird matou o Mal. A Ordem não existe mais. Blackbird, consegue me ouvir?",,"Atenție, toate trupele Frontului: e gata! S-a terminat. Soldatul lui Blackbird a distrus Răul. Ordinul nu mai există. Blackbird, m-auzi?","Внимание, всем войскам Фронта! Он справился! Всё кончено! Солдат «Чёрного дрозда» покончил со злом! Ордена больше нет! «Чёрный дрозд», как слышите?",,"Cephe'nin tüm askerlerinin dikkatine: Başardı! Her şey bitti. Karabatak'ın askeri Şeytan'ı öldürdü. Tarikat artık yok. Karatavuk, beni duyuyor musun?" -"I knew you would win, my gallant hero. All fighting has stopped. Your victory will allow us to create a vaccine to purge the virus from our bodies.",TXT_SUB_GOOD2,,,,"Já věděla, že vyhraješ, můj statečný hrdino. Všechen boj ustal. Tvé vítězství nám umožní vyrobit vakcínu, která naše těla vyčistí od viru.","Jeg vidste, du ville vinde, min tapper helt. Alle kampe er stoppet. Din sejr vil give os mulighed for at skabe en vaccine, der kan rense vores kroppe for virussen.","Ich wusste, dass du gewinnen würdest, mein edler Held. Die Kämpfe haben aufgehört. Dein Sieg wird es uns erlauben einen Impfstoff herzustellen, mit dem wir den Virus in unseren Körper bekämpfen können.",,,"Sabía que ganarías, my valiente héroe. La lucha ha terminado. Tu victoria nos permitirá crear una vacuna para purgar el virus de nuestros cuerpos.",,"Tiesin, että voittaisit, uljas sankarini. Kaikki taistelu on tauonnut. Voittosi myötä meidän on mahdollista luoda rokote viruksen poistamiseksi kehoistamme.","Je savais que tu gagnerais, mon vaillant héros. Les combats ont cessé, ta victoire nous permettrera de créer un vaccin et purger le virus de nos corps.","Tudtam, hogy nyerni fogsz vitéz hősöm. Megszűntek a csaták. A győzelmed lehetővé fogja tenni, hogy egy vakcinával kiírtsuk a testünkből ezt a vírust.","Lo sapevo che potevi vincere, mio galante eroe. Tutto il combattimento è cessato. La tua vittoria ci consentirà di creare un vaccino per estirpare il virus dai nostri corpi.","あなたが勝つことは分かっていたわ、私の勇敢なヒーロー。 +オーダーはもう存在しない。ブラックバード、聞こえるか?","프론트의 모든 병사는 주목하라. 그가 해냈다! 모든 것이 끝났다. 블랙버드의 병사가 악을 물리치고, 오더는 끝장이 났다. 블랙버드, 내 말 듣고 있나?","Opgelet, alle troepen van het Front: hij heeft het gedaan! Het is voorbij. Blackbird's soldaat heeft het Kwaad gedood. De Orde is niet meer. Blackbird, hoort jou mij?","Oppmerksomhet, alle tropper fra fronten: han har gjort det! Det er over. Blackbirds soldat har drept Ondskapen. Ordenen eksisterer ikke lenger. Blackbird, hører du meg?","Uwaga, wszystkie oddziały Frontu: udało mu się! To już koniec. Żołnierz Blackbird zabił Zło. Nie ma już Zakonu. Blackbird, czy mnie słyszysz?","Atenção, todas as tropas da Frente: ele conseguiu! Está tudo acabado. O soldado de Blackbird matou o Mal. A Ordem não existe mais. Blackbird, consegue me ouvir?",,"Atenție, toate trupele Frontului: e gata! S-a terminat. Soldatul lui Blackbird a distrus Răul. Ordinul nu mai există. Blackbird, m-auzi?","Внимание, всем войскам Фронта! Он справился! Всё кончено! Солдат «Чёрного дрозда» покончил со злом! Ордена больше нет! «Чёрный дрозд», как слышите?",,"Lystring, alla fronttrupper: han har gjort det! Det är över. Blackbirds soldat har dödat ondskan. Orden finns inte längre. Blackbird, hör du mig?","Cephe'nin tüm askerlerinin dikkatine: Başardı! Her şey bitti. Karabatak'ın askeri Şeytan'ı öldürdü. Tarikat artık yok. Karatavuk, beni duyuyor musun?" +"I knew you would win, my gallant hero. All fighting has stopped. Your victory will allow us to create a vaccine to purge the virus from our bodies.",TXT_SUB_GOOD2,〃,,,"Já věděla, že vyhraješ, můj statečný hrdino. Všechen boj ustal. Tvé vítězství nám umožní vyrobit vakcínu, která naše těla vyčistí od viru.","Jeg vidste, du ville vinde, min tapper helt. Alle kampe er stoppet. Din sejr vil give os mulighed for at skabe en vaccine, der kan rense vores kroppe for virussen.","Ich wusste, dass du gewinnen würdest, mein edler Held. Die Kämpfe haben aufgehört. Dein Sieg wird es uns erlauben einen Impfstoff herzustellen, mit dem wir den Virus in unseren Körper bekämpfen können.",,,"Sabía que ganarías, mi valiente héroe. La lucha ha terminado. Tu victoria nos permitirá crear una vacuna para purgar el virus de nuestros cuerpos.",,"Tiesin, että voittaisit, uljas sankarini. Kaikki taistelu on tauonnut. Voittosi myötä meidän on mahdollista luoda rokote viruksen poistamiseksi kehoistamme.","Je savais que tu gagnerais, mon vaillant héros. Les combats ont cessé, ta victoire nous permettrera de créer un vaccin et purger le virus de nos corps.","Tudtam, hogy nyerni fogsz vitéz hősöm. Megszűntek a csaták. A győzelmed lehetővé fogja tenni, hogy egy vakcinával kiírtsuk a testünkből ezt a vírust.","Lo sapevo che potevi vincere, mio galante eroe. Tutto il combattimento è cessato. La tua vittoria ci consentirà di creare un vaccino per estirpare il virus dai nostri corpi.","あなたが勝つことは分かっていたわ、私の勇敢なヒーロー。 全ての戦いは終結した。あなたがもたらした勝利のおかげで、 -私達の体からウィルスを根絶するためのワクチンを作ることができる。","나의 용감한 영웅이 이길 줄 알았어. 모든 싸움이 끝이 났고, 당신의 승리 덕분에 우리 몸에 남은 바이러스를 퇴치할 백신을 만들 수 있을 거야.","Ik wist dat je zou winnen, mijn dappere held. Alle gevechten zijn gestopt. Uw overwinning zal ons in staat stellen om een vaccin te creëren om het virus uit ons lichaam te zuiveren.","Jeg visste at du ville vinne, min tapre helt. Alle kampene er over. Din seier vil tillate oss å lage en vaksine for å fjerne viruset fra kroppene våre.","Wiedziałem, że wygrasz, mój dzielny bohaterze. Wszystkie walki zostały przerwane. Twoje zwycięstwo pozwoli nam stworzyć szczepionkę, która usunie wirusa z naszych ciał.","Eu sabia que você conseguiria vencer, meu herói valente. Todo esse conflito chegou ao fim. Sua vitória nos permitirá que criemos uma vacina para eliminar o vírus de nossos corpos.",,"Știam că vei câștiga, eroul meu galant. Lupta a încetat. Vitoria ta ne permite să creăm un vaccin care va elimina virusul din corpul nostru.","Я знала, что ты победишь, мой отважный герой. Война окончена. Твоя победа позволила нам создать вакцину против вируса.",,"Kazanacağını biliyordum, benim cesur kahramanım. Tüm savaşlar durdu. Zaferin, virüsü vücutlarımızdan temizlemek için bir aşı yaratmamızı sağlayacak." -"You have saved our planet and set us free. Now I'd like to thank you... personally. Oh, and by the way: the name is Shauna.",TXT_SUB_GOOD3,,,,Zachránil jsi naši planetu a osvobodil nás. Teď bych ti chtěla poděkovat... osobně. A mimochodem: Mé jméno je Shauna.,"Du har reddet vores planet og befriet os. Nu vil jeg gerne takke dig... personligt. Åh, og forresten: Navnet er Shauna.","Du hast unseren Planeten gerettet und uns befreit. Nun würde ich mich gerne bei dir bedanken... persönlich. Oh, so nebenbei: Mein Name ist Shauna.",,,"Has salvado nuestro planeta y nos has hecho libres. Ahora me gustaría agradecértelo... personalmente. Oh, y por cierto: mi nombre es Shauna.",,"Olet pelastanut planeettamme ja vapauttanut meidät. Tahtoisin nyt kiittää sinua... henkilökohtaisesti. Ja muuten, nimeni on Shauna.","Tu as sauvé notre planète et tu nous as tous libérés. Je veux te récompenser.. Personellement. Oh, et je m'appelle Shauna.","Megmentetted a bolygót, és felszabadítottál minket. Meg akarom ezt köszönni...személyesen. Ja, és a nevem Shauna.","Hai salvato il nostro pianeta e ci hai reso liberi. Ora vorrei ringraziarti ... di persona. Ah, comunque: mi chiamo Shauna.","あなたはこの星を救い、そして自由を取り戻した。さあ、 +私達の体からウィルスを根絶するためのワクチンを作ることができる。","나의 용감한 영웅이 이길 줄 알았어. 모든 싸움이 끝이 났고, 당신의 승리 덕분에 우리 몸에 남은 바이러스를 퇴치할 백신을 만들 수 있을 거야.","Ik wist dat je zou winnen, mijn dappere held. Alle gevechten zijn gestopt. Uw overwinning zal ons in staat stellen om een vaccin te creëren om het virus uit ons lichaam te zuiveren.","Jeg visste at du ville vinne, min tapre helt. Alle kampene er over. Din seier vil tillate oss å lage en vaksine for å fjerne viruset fra kroppene våre.","Wiedziałem, że wygrasz, mój dzielny bohaterze. Wszystkie walki zostały przerwane. Twoje zwycięstwo pozwoli nam stworzyć szczepionkę, która usunie wirusa z naszych ciał.","Eu sabia que você conseguiria vencer, meu herói valente. Todo esse conflito chegou ao fim. Sua vitória nos permitirá que criemos uma vacina para eliminar o vírus de nossos corpos.",,"Știam că vei câștiga, eroul meu galant. Lupta a încetat. Vitoria ta ne permite să creăm un vaccin care va elimina virusul din corpul nostru.","Я знала, что ты победишь, мой отважный герой. Война окончена. Твоя победа позволила нам создать вакцину против вируса.",,"Jag visste att du skulle vinna, min tappre hjälte. Alla strider har upphört. Din seger kommer att göra det möjligt för oss att skapa ett vaccin för att rensa ut viruset från våra kroppar.","Kazanacağını biliyordum, benim cesur kahramanım. Tüm savaşlar durdu. Zaferin, virüsü vücutlarımızdan temizlemek için bir aşı yaratmamızı sağlayacak." +"You have saved our planet and set us free. Now I'd like to thank you... personally. Oh, and by the way: the name is Shauna.",TXT_SUB_GOOD3,〃,,,Zachránil jsi naši planetu a osvobodil nás. Teď bych ti chtěla poděkovat... osobně. A mimochodem: Mé jméno je Shauna.,"Du har reddet vores planet og befriet os. Nu vil jeg gerne takke dig... personligt. Åh, og forresten: Navnet er Shauna.","Du hast unseren Planeten gerettet und uns befreit. Nun würde ich mich gerne bei dir bedanken... persönlich. Oh, so nebenbei: Mein Name ist Shauna.",,,"Has salvado nuestro planeta y nos has hecho libres. Ahora me gustaría agradecértelo... personalmente. Oh, y por cierto: mi nombre es Shauna.",,"Olet pelastanut planeettamme ja vapauttanut meidät. Tahtoisin nyt kiittää sinua... henkilökohtaisesti. Ja muuten, nimeni on Shauna.","Tu as sauvé notre planète et tu nous as tous libérés. Je veux te récompenser.. Personellement. Oh, et je m'appelle Shauna.","Megmentetted a bolygót, és felszabadítottál minket. Meg akarom ezt köszönni...személyesen. Ja, és a nevem Shauna.","Hai salvato il nostro pianeta e ci hai reso liberi. Ora vorrei ringraziarti ... di persona. Ah, comunque: mi chiamo Shauna.","あなたはこの星を救い、そして自由を取り戻した。さあ、 あなたにお礼をするときが来たわね、個人的な意味で... -ああ、それはそうと、私の本名はシャウナよ。","당신이 우리의 행성을 구하고 우리를 자유롭게 해줬어. 이제... 개인적으로 당신에게 감사하고 싶어. 아, 그리고... 내 이름은 샤나야.","Jullie hebben onze planeet gered en ons bevrijd. Nu wil ik je persoonlijk bedanken.... persoonlijk. Oh, en trouwens: de naam is Shauna.",Du har reddet planeten vår og satt oss fri. Nå vil jeg takke deg... personlig. Og forresten: navnet er Shauna.,"Uratowałeś naszą planetę i uwolniłeś nas. Teraz chciałbym ci podziękować... osobiście. Aha, i przy okazji: mam na imię Shauna.","Você salvou o nosso planeta e nos libertou. Agora, eu gostaria de te agradecer...pessoalmente. Ah, a propósito: meu nome é Shauna.",,"Ai salvat planeta și ne-ai eliberat. Aș vrea să îți mulțumesc, personal... Oh, și apropo: numele e Shauna.","Ты спас нашу планету и освободил нас. Так что я бы хотела поблагодарить тебя... лично. Кстати, меня зовут Шона.",,Gezegenimizi kurtardın ve bizi özgür bıraktın. Şimdi size şahsen teşekkür etmek istiyorum. Bu arada adım Shauna. -"Yes, the evil was gone, but our future was uncertain and clouded with doubt.",TXT_SUB_SAD1,,,,"Ano, zlo bylo pryč, ale naše budoucnost byla nejistá a zahalená pochybami.","Ja, ondskaben var væk, men vores fremtid var usikker og omgærdet af tvivl.","Ja, das Böse war fort, aber unsere Zukunft war ungewiss und von Zweifeln getrübt.",,,"Sí, el mal desapareció, pero nuestro futuro fue incierto y oscurecido por dudas.",,"Niin, paha oli kyllä mennyttä, mutta tulevaisuutemme oli epävarma ja hämärän peitossa.","Oui, le mal a disparu, mais notre futur reste incertain et le doute pèse sur nous.","Habár a gonosz eltávozott, a jövőnk mégis bizonytalan és ködös.","Si, il male fu sconfitto, ma il nostro futuro fu incerto e offuscato dal dubbio.","ええ、悪は消え去ったわ。だけども私達の未来は -まだ不安と疑念に満ちている。","그래, 악은 이제 사라졌어. 하지만 우리의 불확실한 앞날은 여전히 근심의 먹구름으로 가득 찼지.","Ja, het kwaad was weg, maar onze toekomst was onzeker en vertroebeld met twijfel.","Ja, ondskapen var borte, men fremtiden vår var usikker og full av tvil.","Tak, zło zniknęło, ale nasza przyszłość była niepewna i spowita wątpliwościami.","Sim, o mal se foi, mas o nosso futuro ainda era incerto e coberto de dúvidas.",,"Da, răul s-a dus dar viitorul nostru era în ceață și neclar.","Да, зло было повержено, но наше будущее было туманно и омрачено тенью сомнений...",,"Evet, kötülük gitmişti ama geleceğimiz belirsizdi ve şüpheyle doluydu." -It would take generations to purge the virus from our people. If we survived that long.,TXT_SUB_SAD2,,,,"Trvalo by to věky, než bychom virus z našeho lidu vypudili. Pokud bychom tak dlouho přežili.",Det ville tage generationer at udrense virussen fra vores folk. Hvis vi overlevede så længe.,"Es würde Generationen dauern, bis wir unser Volk von dem Virus befreien können. Wenn wir so lange überleben...",,,Llevaría generaciones purgar el virus de nuestra gente. Si sobrevivieramos tanto tiempo.,,"Kestäisi sukupolvia hävittää virus keskuudestamme, jos selviäisimme niin pitkälle.","Il faudra des générations pour purger le virus de nos corps, si nous survivons suffisament longtemps.","Generációkba fog kerülni, hogy teljesen kiírtsuk a vírust. Márha élünk addig.",Ci sarebbero volute generazioni per eliminare il virus dalle nostre persone. Se fossimo sopravvissuti così a lungo.,"人間たちからウィルスを根絶するには、あと何世代もかかって -しまうはず。私達がそこまで生き延びられたとしても。",우리 몸속의 바이러스를 퇴치하려면 수 세대의 시간이 걸릴 거야. 우리가 그때까지 살아남는다면.,Het zou generaties vergen om het virus uit ons volk te zuiveren. Als we het zo lang zouden overleven.,Det ville ta generasjoner å fjerne viruset fra folket vårt. Hvis vi overlevde så lenge.,"Potrzeba było pokoleń, by oczyścić nasz lud z wirusa. Jeśli przeżyjemy tak długo.",Levaria gerações para eliminar o vírus de nosso povo. Se sobrevivessemos por todo esse tempo.,,Va dura generații până vom elimina virusul din oamenii noștri. Dacă vom trăi suficient.,"Десятилетия потребуются, чтобы исцелить наших людей от вируса... если нам удастся просуществовать так долго.",,Virüsü insanlarımızdan temizlemek nesiller alacaktı. Tabii o kadar uzun süre hayatta kalabilirsek. -"Whatever the evil wanted, it drained from us the one thing we needed: it left us without hope.",TXT_SUB_SAD3,,,,"Ať chtělo zlo cokoliv, vysálo z nás tu jednu věc, kterou jsme potřebovali: Nechalo nás bez naděje.","Uanset hvad ondskaben ville, drænede den os for den eneste ting, vi havde brug for: den efterlod os uden håb.","Was auch immer das Böse wollte, es hat uns das genommen, was wir am meisten brauchten: Es hat uns ohne Hoffnung gelassen.",,,"Sea lo que sea que quisiera el mal, nos despojó de aquello que necesitábamos: nos dejó sin esperanza.",,"Mitä tahansa paha halusikaan, se riisti meiltä sen yhden ainoan asian, jota tarvitsimme: se jätti meidät ilman toivoa.","Quel que soit ce que le mal voulait de nous, il a tout de même pris la dernière chose qui nous restait: notre espoir.",A gonosz megkaparintotta amit akart: megfosztott minket a reményünktől.,"Qualunque cosa il male volesse, ci ha drenato dell'unica cosa di cui avevamo bisogno: ci ha lasciato senza speranza.","あの邪悪な存在が何を求めていたかはともかく、 -奴は人間たちから一番大切な物、希望を奪い去った。","악이 원한 것이 무엇이었든, 그들은 우리에게 필요한 한 가지를 뺏어갔어: 희망이라는 미래지...","Wat het kwaad ook wilde, het heeft ons datgene ontnomen wat we nodig hadden: het heeft ons zonder hoop achtergelaten.","Uansett hva ondskapen ville, tok den fra oss det eneste vi trengte: Den etterlot oss uten håp.","Cokolwiek chciało zło, wyssało z nas jedyną rzecz, której potrzebowaliśmy: pozostawiło nas bez nadziei.","Seja lá o que o mal queria, conseguiu tirar de nós algo que precisávamos: nossas esperanças.",,"Orice ar fi vrut răul, ne-a stors de ceea ce am avut cea mai mare nevoie: speranță.","Чего бы зло ни желало, оно отняло у нас то, в чём мы нуждались больше всего — оно лишило нас надежды.",,"Kötülük her ne istediyse, ihtiyacımız olan tek şeyi bizden çekip aldı: bizi umutsuz bıraktı." -"The sentient virus hit us like a tidal wave, driving us all mad. We heard the siren's song of death and we danced.",TXT_SUB_BAD1,,,,"Žijící virus nás ochromil jako povodeň, ze které jsme všichni zešíleli. Uslyšeli jsme siréninu píseň smrti a začali tančit.","Den følende virus ramte os som en flodbølge og drev os alle til vanvid. Vi hørte sirenens sang om døden, og vi dansede.",Der Virus traf uns wie eine Flutwelle und machte uns verrückt. Wir hörten den Sirenengesang des Todes - und wir tanzten.,,,"El virus consciente nos golpeó como una marea, volviéndonos a todos locos. Escuchamos la canción de sirena de la muerte y bailamos.",,Tietoinen virus iski meihin kuin hyökyaalto syösten meidät hulluuteen. Kuulimme seireenin kuoleman veisuun ja tanssimme sen tahtiin.,"Le virus devenu intelligent nous a emporté comme un tsunami, nous plongeant dans la folie. Entendant le doux chant de la mort, nous dancions en choeur.","A tudatára ébredt vírus hullámként verte le népünket és őrjített meg minket. Hallottuk a szirének tébolyító halál énekét, és táncolni kezdtünk.","Il virus intelligente ci ha colpito come uno tsunami, immergendoci nella follia. Sentimmo il canto delle sirene della morte, e ci misimo a ballare.","センティエント・ウィルスは私達を津波のように襲い、 +ああ、それはそうと、私の本名はシャウナよ。","당신이 우리의 행성을 구하고 우리를 자유롭게 해줬어. 이제... 개인적으로 당신에게 감사하고 싶어. 아, 그리고... 내 이름은 샤나야.","Jullie hebben onze planeet gered en ons bevrijd. Nu wil ik je persoonlijk bedanken.... persoonlijk. Oh, en trouwens: de naam is Shauna.",Du har reddet planeten vår og satt oss fri. Nå vil jeg takke deg... personlig. Og forresten: navnet er Shauna.,"Uratowałeś naszą planetę i uwolniłeś nas. Teraz chciałbym ci podziękować... osobiście. Aha, i przy okazji: mam na imię Shauna.","Você salvou o nosso planeta e nos libertou. Agora, eu gostaria de te agradecer...pessoalmente. Ah, a propósito: meu nome é Shauna.",,"Ai salvat planeta și ne-ai eliberat. Aș vrea să îți mulțumesc, personal... Oh, și apropo: numele e Shauna.","Ты спас нашу планету и освободил нас. Так что я бы хотела поблагодарить тебя... лично. Кстати, меня зовут Шона.",,"Du har räddat vår planet och befriat oss. Nu vill jag tacka dig... personligen. Åh, och förresten: namnet är Shauna.",Gezegenimizi kurtardın ve bizi özgür bıraktın. Şimdi size şahsen teşekkür etmek istiyorum. Bu arada adım Shauna. +"Yes, the evil was gone, but our future was uncertain and clouded with doubt.",TXT_SUB_SAD1,Sad ending.,,,"Ano, zlo bylo pryč, ale naše budoucnost byla nejistá a zahalená pochybami.","Ja, ondskaben var væk, men vores fremtid var usikker og omgærdet af tvivl.","Ja, das Böse war fort, aber unsere Zukunft war ungewiss und von Zweifeln getrübt.",,,"Sí, el mal desapareció, pero nuestro futuro fue incierto y oscurecido por dudas.",,"Niin, paha oli kyllä mennyttä, mutta tulevaisuutemme oli epävarma ja hämärän peitossa.","Oui, le mal a disparu, mais notre futur reste incertain et le doute pèse sur nous.","Habár a gonosz eltávozott, a jövőnk mégis bizonytalan és ködös.","Si, il male fu sconfitto, ma il nostro futuro fu incerto e offuscato dal dubbio.","ええ、悪は消え去ったわ。だけども私達の未来は +まだ不安と疑念に満ちている。","그래, 악은 이제 사라졌어. 하지만 우리의 불확실한 앞날은 여전히 근심의 먹구름으로 가득 찼지.","Ja, het kwaad was weg, maar onze toekomst was onzeker en vertroebeld met twijfel.","Ja, ondskapen var borte, men fremtiden vår var usikker og full av tvil.","Tak, zło zniknęło, ale nasza przyszłość była niepewna i spowita wątpliwościami.","Sim, o mal se foi, mas o nosso futuro ainda era incerto e coberto de dúvidas.",,"Da, răul s-a dus dar viitorul nostru era în ceață și neclar.","Да, зло было повержено, но наше будущее было туманно и омрачено тенью сомнений...",,"Ja, ondskan var borta, men vår framtid var osäker och grumlad av tvivel.","Evet, kötülük gitmişti ama geleceğimiz belirsizdi ve şüpheyle doluydu." +It would take generations to purge the virus from our people. If we survived that long.,TXT_SUB_SAD2,〃,,,"Trvalo by to věky, než bychom virus z našeho lidu vypudili. Pokud bychom tak dlouho přežili.",Det ville tage generationer at udrense virussen fra vores folk. Hvis vi overlevede så længe.,"Es würde Generationen dauern, bis wir unser Volk von dem Virus befreien können. Wenn wir so lange überleben...",,,Llevaría generaciones purgar el virus de nuestra gente. Si sobrevivieramos tanto tiempo.,,"Kestäisi sukupolvia hävittää virus keskuudestamme, jos selviäisimme niin pitkälle.","Il faudra des générations pour purger le virus de nos corps, si nous survivons suffisament longtemps.","Generációkba fog kerülni, hogy teljesen kiírtsuk a vírust. Márha élünk addig.",Ci sarebbero volute generazioni per eliminare il virus dalle nostre persone. Se fossimo sopravvissuti così a lungo.,"人間たちからウィルスを根絶するには、あと何世代もかかって +しまうはず。私達がそこまで生き延びられたとしても。",우리 몸속의 바이러스를 퇴치하려면 수 세대의 시간이 걸릴 거야. 우리가 그때까지 살아남는다면.,Het zou generaties vergen om het virus uit ons volk te zuiveren. Als we het zo lang zouden overleven.,Det ville ta generasjoner å fjerne viruset fra folket vårt. Hvis vi overlevde så lenge.,"Potrzeba było pokoleń, by oczyścić nasz lud z wirusa. Jeśli przeżyjemy tak długo.",Levaria gerações para eliminar o vírus de nosso povo. Se sobrevivessemos por todo esse tempo.,,Va dura generații până vom elimina virusul din oamenii noștri. Dacă vom trăi suficient.,"Десятилетия потребуются, чтобы исцелить наших людей от вируса... если нам удастся просуществовать так долго.",,Det skulle ta generationer att rensa ut viruset från vårt folk. Om vi överlevde så länge.,Virüsü insanlarımızdan temizlemek nesiller alacaktı. Tabii o kadar uzun süre hayatta kalabilirsek. +"Whatever the evil wanted, it drained from us the one thing we needed: it left us without hope.",TXT_SUB_SAD3,〃,,,"Ať chtělo zlo cokoliv, vysálo z nás tu jednu věc, kterou jsme potřebovali: Nechalo nás bez naděje.","Uanset hvad ondskaben ville, drænede den os for den eneste ting, vi havde brug for: den efterlod os uden håb.","Was auch immer das Böse wollte, es hat uns das genommen, was wir am meisten brauchten: Es hat uns ohne Hoffnung gelassen.",,,"Sea lo que sea que quisiera el mal, nos despojó de aquello que necesitábamos: la esperanza.",,"Mitä tahansa paha halusikaan, se riisti meiltä sen yhden ainoan asian, jota tarvitsimme: se jätti meidät ilman toivoa.","Quel que soit ce que le mal voulait de nous, il a tout de même pris la dernière chose qui nous restait: notre espoir.",A gonosz megkaparintotta amit akart: megfosztott minket a reményünktől.,"Qualunque cosa il male volesse, ci ha drenato dell'unica cosa di cui avevamo bisogno: ci ha lasciato senza speranza.","あの邪悪な存在が何を求めていたかはともかく、 +奴は人間たちから一番大切な物、希望を奪い去った。","악이 원한 것이 무엇이었든, 그들은 우리에게 필요한 한 가지를 뺏어갔어: 희망이라는 미래지...","Wat het kwaad ook wilde, het heeft ons datgene ontnomen wat we nodig hadden: het heeft ons zonder hoop achtergelaten.","Uansett hva ondskapen ville, tok den fra oss det eneste vi trengte: Den etterlot oss uten håp.","Cokolwiek chciało zło, wyssało z nas jedyną rzecz, której potrzebowaliśmy: pozostawiło nas bez nadziei.","Seja lá o que o mal queria, conseguiu tirar de nós algo que precisávamos: nossas esperanças.",,"Orice ar fi vrut răul, ne-a stors de ceea ce am avut cea mai mare nevoie: speranță.","Чего бы зло ни желало, оно отняло у нас то, в чём мы нуждались больше всего — оно лишило нас надежды.",,Vad ondskan än ville så tog den från oss det enda vi behövde: den lämnade oss utan hopp.,"Kötülük her ne istediyse, ihtiyacımız olan tek şeyi bizden çekip aldı: bizi umutsuz bıraktı." +"The sentient virus hit us like a tidal wave, driving us all mad. We heard the siren's song of death and we danced.",TXT_SUB_BAD1,Worst ending.,,,"Žijící virus nás ochromil jako povodeň, ze které jsme všichni zešíleli. Uslyšeli jsme siréninu píseň smrti a začali tančit.","Den følende virus ramte os som en flodbølge og drev os alle til vanvid. Vi hørte sirenens sang om døden, og vi dansede.",Der Virus traf uns wie eine Flutwelle und machte uns verrückt. Wir hörten den Sirenengesang des Todes - und wir tanzten.,,,"El virus consciente nos golpeó como una marea, volviéndonos a todos locos. Escuchamos la canción de sirena de la muerte y bailamos.",,Tietoinen virus iski meihin kuin hyökyaalto syösten meidät hulluuteen. Kuulimme seireenin kuoleman veisuun ja tanssimme sen tahtiin.,"Le virus devenu intelligent nous a emporté comme un tsunami, nous plongeant dans la folie. Entendant le doux chant de la mort, nous dancions en choeur.","A tudatára ébredt vírus hullámként verte le népünket és őrjített meg minket. Hallottuk a szirének tébolyító halál énekét, és táncolni kezdtünk.","Il virus intelligente ci ha colpito come uno tsunami, immergendoci nella follia. Sentimmo il canto delle sirene della morte, e ci misimo a ballare.","センティエント・ウィルスは私達を津波のように襲い、 全ての人間を狂気に陥れた。セイレーンの死の歌声を聞いたように -なり、死ぬまで踊り続けたのだ。","자각심을 가진 바이러스가 온 땅을 휩쓸었고, 우리 모두를 미치게 했다. 우리는 악이 들려주는 죽음의 노래에 맞춰 춤을 추었다.","Het virus met gevoel raakte ons als een vloedgolf, waardoor we allemaal gek werden. We hoorden het lied van de sirene van de dood en we dansten.",Det følende viruset traff oss som en flodbølge og gjorde oss alle gale. Vi hørte sirenenes dødssang og vi danset.,"Czujący wirus uderzył w nas jak fala pływowa, doprowadzając nas wszystkich do szaleństwa. Słyszeliśmy syreni śpiew śmierci i tańczyliśmy.","O vírus senciente nos atingiu como uma onda gigante, deixando todos nós loucos. Ouviamos a canção da morte da sirene e dançávamos.",,"Virusul viu ne-a lovit ca un val, făcându-ne să o luăm razna. Am auzit cântecul de moarte al sirenelor și am dansat.","Эпидемия захлестнула нас подобно гигантской волне, лишив рассудка каждого. Мы услышали сладкую песнь смерти и подчинились ей.",,Duyarlı virüs bizi bir gelgit dalgası gibi vurdu ve hepimizi delirtti. Sirenin ölüm şarkısını duyduk ve dans ettik. -"This evil drained us of all human life and, scornful of procreation, recycled our families.",TXT_SUB_BAD2,,,,"Toto zlo z nás vysálo všechen život a, bez možnosti se rozmnožovat, vyhladilo naše rodiny.","Denne ondskab drænede os for alt menneskeligt liv, og foragtede for forplantning og genbrugte vores familier.",Das Böse entzog uns alles menschliche und als Verhöhnung der Fortpflanzung recycelte es unsere Familien.,,,"Este mal nos despojó de nuestra humanidad y despreciando la procreación, recicló nuestras familias.",,Paha imi meistä kaiken ihmiselämän ja lisääntymistä ylenkatsoen kierrätti perheemme.,"La mal nous a drainé de toute vie et haïssant toute procréation, recycla nos familles.","Ez a gonosz tömegével csapolta le az emberi életeket, és egyfajta gúnyos teremtőként újrahasznosította családainkat.","Questo male ci ha drenato di tutta la vita umana e, sprezzante della procreazione, riciclò le nostre famiglie.","この邪悪な存在は人間たちの命と繁殖能力を奪い去り、 -我々の家族を再利用した。","악은 우리에게서 인간적인 삶을 빼앗았고, 우리 인류를 유지해온 생식을 억제했다.","Dit kwaad heeft ons van alle mensenlevens ontdaan en, verachtelijk van voortplanting, onze families gerecycled.",Denne ondskapen tømte oss for alt menneskelig liv og resirkulerte familiene våre med forakt for forplantning.,"To zło pozbawiało nas wszelkiego ludzkiego życia, a gardząc prokreacją, utylizowało nasze rodziny.","O mal tirou de nós toda a vida humana e, deprezando a procriação, reciclou nossas famílias.",,"Acest rău ne-a stors de toată viața umană, detestând procreerea, reciclandu-ne familiile.","Зло истребляло в нас всё человеческое. Не задумываясь о завтрашнем дне, оно перерабатывало целые семьи.",,Bu kötülük bizi tüm insan yaşamından mahrum bıraktı ve üremeyi küçümseyerek ailelerimizi geri dönüştürdü. -"Then one day, the evil left. There was simply nothing for it to feed on. We were extinct.",TXT_SUB_BAD3,,,,"A pak, jednoho dne, zlo odešlo. Nemělo se prostě už na čem pást. Vyhynuli jsme.",Så en dag forlod ondskaben os. Der var simpelthen ikke noget for den at spise. Vi var uddøde.,"Dann, eines Tages, war das Böse fort. Es war nichts mehr da, wovon es zehren konnte. Wir waren ausgestorben.",,,"Entonces un día, el mal se fue. Simplemente no quedaba nada con que alimentarse. Nos extinguimos.",,"Sitten eräänä päivänä paha kaikkosi; mitään yksinkertaisesti ei enää ollut, mistä elää. Olimme kuolleet sukupuuttoon.","Puis, un jour, le mal disparut. Il ne restait plus rien d'utile pour lui, nous nous sommes éteints.",Egy napon a gonosz eltűnt. Nem tudott már min táplálkozni. Kipusztultunk.,"Così un giorno, il male se ne andò. Semplicemente non rimase nulla su cui cibarsi. Noi siamo estinti.","そしてある時、邪悪な存在はこの星を後にした。単に、 -奴の糧となる者が一人もいなくなったからだ。我々は滅びたのだ。","그리고 어느 날, 악은 사라졌다. 그들에게 먹을 것이 없었기 때문이다. 우리들이 멸종했기에...",Op een dag vertrok het kwaad. Er was gewoonweg niets om zich op te voeden. We waren uitgestorven.,Så en dag forsvant ondskapen. Det fantes rett og slett ikke noe å livnære seg på. Vi var utryddet.,"Pewnego dnia, zło odeszło. Nie było nic, czym mogłoby się żywić. Wyginęliśmy.","E então um dia, o mal foi embora. Não sobrou mais nada para ele consumir. Estávamos extintos.",,"Apoi, într-o zi, răul a plecat. Pur și simplu nu a mai rămas nimic din care să se hrănească. Eram dispăruți.","Настал день, когда зло ушло. Не осталось ничего, чем оно могло бы питаться. Мы вымерли.",,"Sonra bir gün, kötülük gitti. Beslenebileceği hiçbir şey kalmamıştı. Neslimiz tükenmişti." +なり、死ぬまで踊り続けたのだ。","자각심을 가진 바이러스가 온 땅을 휩쓸었고, 우리 모두를 미치게 했다. 우리는 악이 들려주는 죽음의 노래에 맞춰 춤을 추었다.","Het virus met gevoel raakte ons als een vloedgolf, waardoor we allemaal gek werden. We hoorden het lied van de sirene van de dood en we dansten.",Det følende viruset traff oss som en flodbølge og gjorde oss alle gale. Vi hørte sirenenes dødssang og vi danset.,"Czujący wirus uderzył w nas jak fala pływowa, doprowadzając nas wszystkich do szaleństwa. Słyszeliśmy syreni śpiew śmierci i tańczyliśmy.","O vírus senciente nos atingiu como uma onda gigante, deixando todos nós loucos. Ouviamos a canção da morte da sirene e dançávamos.",,"Virusul viu ne-a lovit ca un val, făcându-ne să o luăm razna. Am auzit cântecul de moarte al sirenelor și am dansat.","Эпидемия захлестнула нас подобно гигантской волне, лишив рассудка каждого. Мы услышали сладкую песнь смерти и подчинились ей.",,Det kännande viruset drabbade oss som en flodvåg och drev oss alla till vansinne. Vi hörde sirenens sång av döden och vi dansade.,Duyarlı virüs bizi bir gelgit dalgası gibi vurdu ve hepimizi delirtti. Sirenin ölüm şarkısını duyduk ve dans ettik. +"This evil drained us of all human life and, scornful of procreation, recycled our families.",TXT_SUB_BAD2,〃,,,"Toto zlo z nás vysálo všechen život a, bez možnosti se rozmnožovat, vyhladilo naše rodiny.","Denne ondskab drænede os for alt menneskeligt liv, og foragtede for forplantning og genbrugte vores familier.",Das Böse entzog uns alles menschliche und als Verhöhnung der Fortpflanzung recycelte es unsere Familien.,,,"Este mal nos despojó de nuestra humanidad y despreciando la procreación, recicló nuestras familias.",,Paha imi meistä kaiken ihmiselämän ja lisääntymistä ylenkatsoen kierrätti perheemme.,"La mal nous a drainé de toute vie et haïssant toute procréation, recycla nos familles.","Ez a gonosz tömegével csapolta le az emberi életeket, és egyfajta gúnyos teremtőként újrahasznosította családainkat.","Questo male ci ha drenato di tutta la vita umana e, sprezzante della procreazione, riciclò le nostre famiglie.","この邪悪な存在は人間たちの命と繁殖能力を奪い去り、 +我々の家族を再利用した。","악은 우리에게서 인간적인 삶을 빼앗았고, 우리 인류를 유지해온 생식을 억제했다.","Dit kwaad heeft ons van alle mensenlevens ontdaan en, verachtelijk van voortplanting, onze families gerecycled.",Denne ondskapen tømte oss for alt menneskelig liv og resirkulerte familiene våre med forakt for forplantning.,"To zło pozbawiało nas wszelkiego ludzkiego życia, a gardząc prokreacją, utylizowało nasze rodziny.","O mal tirou de nós toda a vida humana e, deprezando a procriação, reciclou nossas famílias.",,"Acest rău ne-a stors de toată viața umană, detestând procreerea, reciclandu-ne familiile.","Зло истребляло в нас всё человеческое. Не задумываясь о завтрашнем дне, оно перерабатывало целые семьи.",,"Denna ondska tömde oss på allt mänskligt liv och, med förakt för fortplantning, återanvände våra familjer.",Bu kötülük bizi tüm insan yaşamından mahrum bıraktı ve üremeyi küçümseyerek ailelerimizi geri dönüştürdü. +"Then one day, the evil left. There was simply nothing for it to feed on. We were extinct.",TXT_SUB_BAD3,〃,,,"A pak, jednoho dne, zlo odešlo. Nemělo se prostě už na čem pást. Vyhynuli jsme.",Så en dag forlod ondskaben os. Der var simpelthen ikke noget for den at spise. Vi var uddøde.,"Dann, eines Tages, war das Böse fort. Es war nichts mehr da, wovon es zehren konnte. Wir waren ausgestorben.",,,"Entonces un día, el mal se fue. Simplemente ya no quedaba nada con que alimentarse: nos extinguimos.",,"Sitten eräänä päivänä paha kaikkosi; mitään yksinkertaisesti ei enää ollut, mistä elää. Olimme kuolleet sukupuuttoon.","Puis, un jour, le mal disparut. Il ne restait plus rien d'utile pour lui, nous nous sommes éteints.",Egy napon a gonosz eltűnt. Nem tudott már min táplálkozni. Kipusztultunk.,"Così un giorno, il male se ne andò. Semplicemente non rimase nulla su cui cibarsi. Noi siamo estinti.","そしてある時、邪悪な存在はこの星を後にした。単に、 +奴の糧となる者が一人もいなくなったからだ。我々は滅びたのだ。","그리고 어느 날, 악은 사라졌다. 그들에게 먹을 것이 없었기 때문이다. 우리들이 멸종했기에...",Op een dag vertrok het kwaad. Er was gewoonweg niets om zich op te voeden. We waren uitgestorven.,Så en dag forsvant ondskapen. Det fantes rett og slett ikke noe å livnære seg på. Vi var utryddet.,"Pewnego dnia, zło odeszło. Nie było nic, czym mogłoby się żywić. Wyginęliśmy.","E então um dia, o mal foi embora. Não sobrou mais nada para ele consumir. Estávamos extintos.",,"Apoi, într-o zi, răul a plecat. Pur și simplu nu a mai rămas nimic din care să se hrănească. Eram dispăruți.","Настал день, когда зло ушло. Не осталось ничего, чем оно могло бы питаться. Мы вымерли.",,En dag lämnade ondskan oss. Det fanns helt enkelt ingenting för den att livnära sig på. Vi var utdöda.,"Sonra bir gün, kötülük gitti. Beslenebileceği hiçbir şey kalmamıştı. Neslimiz tükenmişti." "The genetic mutations caused by the virus not only warped the psyches of the Order, but caused their bodies to decay.",TXT_SUB_MAP03_1,MAP03: After destroying the gate controls.,,,"Genetické mutace způsobené virem nejenže pokřivily mysli Řádu, ale také způsobily rozklad jejich těl.","De genetiske mutationer forårsaget af virussen forvrængede ikke kun ordensmændenes psyke, men fik også deres kroppe til at forfalde.","Die genetischen Mutationen, die durch den Virus verursacht wurden, haben nicht nur die Psyche des Ordens beeinflusst, sondern brachten auch ihre Körper zum Verfallen.",,,"Las mutaciones genéticas causadas por el virus no solo retorcieron las mentes de la Orden, sino que también causaron el deterioro de sus cuerpos.",,Viruksen aiheuttamat geneettiset mutaatiot eivät vain vääristäneet Veljeskunnan mieliä vaan myös rappeuttivat heidän ruumiitaan.,"Les mutations géntiques du virus ont non seulement tordu l'esprit de L'Ordre, mais a aussi rendu leur corps invivables.","A vírus genetikai mutációi nem csak a Rend tagjainak elméjét rontotta meg, de testüket is bomlásnak indította.","Le mutazioni genetiche causate dal virus non solo turbavano la psiche dei seguaci dell'Ordine, ma portava i loro corpi a decomporre.","ウィルスからもたらされた遺伝子変異はオーダーの者たちの精神だけではなく、 -肉体すらも蝕んだ。","바이러스로 인한 유전적 변화는 오더의 광신도들을 만들었을 뿐만 아니라, 그들의 육신을 썩어 문드러지게 했습니다.","De genetische mutaties die door het virus werden veroorzaakt, vervormden niet alleen de psyche van de Orde, maar veroorzaakten ook het verval van hun lichaam.","De genetiske mutasjonene forårsaket av viruset forvrengte ikke bare ordenens psyke, men fikk kroppene deres til å forfalle.","Mutacje genetyczne spowodowane przez wirusa nie tylko wypaczyły psychikę Zakonu, ale spowodowały rozkład ich ciał.","As mutações genéticas causadas pelo vírus não somente distorceu as mentes da Ordem, mas também deterioraram nossos corpos.",,"Mutațiile genetice nu numai că au sucit psihicul Ordinului, dar le-a făcut corpul să se deterioreze.","Генетические мутации, которые возникали из-за вируса, не только извращали психику членов Ордена, но и вызывали гниение их тел.",,"Virüsün neden olduğu genetik mutasyonlar sadece Tarikat'ın psikolojisini bozmakla kalmadı, aynı zamanda bedenlerinin de çürümesine neden oldu." +肉体すらも蝕んだ。","바이러스로 인한 유전적 변화는 오더의 광신도들을 만들었을 뿐만 아니라, 그들의 육신을 썩어 문드러지게 했습니다.","De genetische mutaties die door het virus werden veroorzaakt, vervormden niet alleen de psyche van de Orde, maar veroorzaakten ook het verval van hun lichaam.","De genetiske mutasjonene forårsaket av viruset forvrengte ikke bare ordenens psyke, men fikk kroppene deres til å forfalle.","Mutacje genetyczne spowodowane przez wirusa nie tylko wypaczyły psychikę Zakonu, ale spowodowały rozkład ich ciał.","As mutações genéticas causadas pelo vírus não somente distorceu as mentes da Ordem, mas também deterioraram nossos corpos.",,"Mutațiile genetice nu numai că au sucit psihicul Ordinului, dar le-a făcut corpul să se deterioreze.","Генетические мутации, которые возникали из-за вируса, не только извращали психику членов Ордена, но и вызывали гниение их тел.",,"De genetiska mutationer som viruset orsakade förvrängde inte bara ordens psykiska tillstånd, utan fick deras kroppar att förfalla.","Virüsün neden olduğu genetik mutasyonlar sadece Tarikat'ın psikolojisini bozmakla kalmadı, aynı zamanda bedenlerinin de çürümesine neden oldu." "Without procreation, the Order found that biomechanical enhancements were the only way to maintain their strengths and numbers.",TXT_SUB_MAP03_2,〃,,,"Řádu došlo, že bez rozmnožování jsou biomechanická vylepšení jediná možnost, jak zachovat své počty a sílu.","Uden forplantning fandt Ordenen ud af, at biomekaniske forbedringer var den eneste måde at bevare deres styrke og antal på.","Ohne die Möglichkeit der Fortpflanzung fand der Orden heraus, dass biomechanische Erweiterungen der einzige Weg waren, um ihre Kräfe und eine hohe Anzahl beizubehalten.",,,"Sin procreación, la Orden se encontró con que las mejoras biomecánicas eran la única forma de mantener sus fuerzas y números.",,Ilman lisääntymistä Veljeskunta katsoi biomekaanisen parantelun ainoaksi tavakseen ylläpitää vahvuuttaan.,"Sans procréation, l'Ordre découvrirent que les modifications bioméchaniques était leur seule chance de conserver leur force et leur nombre.",A szaporodás nélkül a Rendnek csak egyetlen esélye volt az erejük és számuk megtartására: a biomechanikus testi tuningolás.,"Senza la procreazione, l'Ordine trovò che gli apparati biomeccanici erano l'unico modo per mantenere la loro forza e i loro numeri.","繁殖行為という選択肢がないオーダーは、 -彼らのパワーと数を保つには生体工学による人体改造しかないと判断したのだ。","생식능력이 사라지자, 오더에게 남은 존속 방법은 생체에 기계를 접목한 기술을 발전시키는 것 뿐이었죠.","Zonder voortplanting, vond de Orde dat biomechanische verbeteringen de enige manier waren om hun sterke punten en aantallen te behouden.",Uten forplantning fant ordenen ut at biomekaniske forbedringer var den eneste måten å opprettholde sin styrke og antall på.,"Bez prokreacji Zakon odkrył, że biomechaniczne ulepszenia są jedynym sposobem na utrzymanie siły i liczebności.","Sem procriação, a Ordem descobriu que as modificações biomecânicas eram a única maneira de manter sua força e seus números.",,"Fără procreere, Ordinul a descoperit că îmbunătățirile lor bio-mecanice erau tot ce îi ținea.","Орден обнаружил, что биомеханические улучшения — единственный способ поддержания их численного превосходства при отсутствии деторождения.",,"Üreme olmadan, Düzen güçlerini ve sayılarını korumanın tek yolunun biyomekanik geliştirmeler olduğunu gördü." +彼らのパワーと数を保つには生体工学による人体改造しかないと判断したのだ。","생식능력이 사라지자, 오더에게 남은 존속 방법은 생체에 기계를 접목한 기술을 발전시키는 것 뿐이었죠.","Zonder voortplanting, vond de Orde dat biomechanische verbeteringen de enige manier waren om hun sterke punten en aantallen te behouden.",Uten forplantning fant ordenen ut at biomekaniske forbedringer var den eneste måten å opprettholde sin styrke og antall på.,"Bez prokreacji Zakon odkrył, że biomechaniczne ulepszenia są jedynym sposobem na utrzymanie siły i liczebności.","Sem procriação, a Ordem descobriu que as modificações biomecânicas eram a única maneira de manter sua força e seus números.",,"Fără procreere, Ordinul a descoperit că îmbunătățirile lor bio-mecanice erau tot ce îi ținea.","Орден обнаружил, что биомеханические улучшения — единственный способ поддержания их численного превосходства при отсутствии деторождения.",,Utan fortplantning fann orden att biomekaniska förbättringar var det enda sättet att behålla sin styrka och sitt antal.,"Üreme olmadan, Düzen güçlerini ve sayılarını korumanın tek yolunun biyomekanik geliştirmeler olduğunu gördü." The decay has advanced so that most of the troops we face are more machine than man but we believe that their collective consciousness is controlled by one source...,TXT_SUB_MAP03_3,〃,,,"Rozklad pokročil tak daleko, že většina nepřátel, kterým čelíme, jsou spíše stroje než lidé, ale věříme, že jejich kolektivní vědomí je řízené z jednoho zdroje...","Forfaldet er fremskredet, så de fleste af de tropper, vi står over for, er mere maskiner end mennesker, men vi tror, at deres kollektive bevidsthed styres af én kilde...","Der Verfall ist so weit fortgeschritten, dass die meisten Truppen, denen wir begegnen mehr Maschine als Mensch sind, aber wir glauben, dass ihr kollektives Bewusstsein von einer Quelle kontrolliert wird...",,,El deterioro ha avanzado tanto que la mayoría de tropas a las que nos enfrentamos son más máquina que hombre pero creemos que su consciencia colectiva es controlada por una única fuente...,,"Rappeutuminen on edennyt niin pitkälle, että suurin osa kohtaamistamme joukoista on enemmän koneita kuin ihmisiä, mutta me uskomme, että heidän yhteistä tietoisuuttaan ohjaa yksi lähde...","Les dégradations étaient si avancées que les troupes auxquelles nous faisions face étaient plus machine qu'humains, mais nous pensons que leur conscience collective est contrôlée par une seule source..","A bomlás annyira előrehaladott, hogy a harctéren látott egységek nagyobb részben robotok mint emberek, de úgy gondoljuk hogy az elméjüket egy központi tudat irányítja...","La decomposizione è avanzata a tal punto che molte delle truppe che vediamo sono più macchine che uomini, ma noi crediamo che la loro coscienza collettiva sia controllata da un'unica fonte...","彼らの肉体へのダメージは深刻で、我らが遭遇した兵士たちは人間と言うよりは もはや機械に近いと言える。だが、彼らの集合意識はたった一人によってコントロールされていると -我々は考えている。","부패가 많이 진행되었기에 우리는 사람보다 기계에 가까운 적들과 싸웠고, 우리는 그들의 집단의식이 어떤 하나의 존재가 통제하는 것이라고 생각하고 있습니다...","Het verval is zo ver gevorderd dat de meeste van de troepen die we tegenkomen meer machine zijn dan de mens, maar we geloven dat hun collectieve bewustzijn wordt gecontroleerd door één bron....","Forfallet har gått så langt at de fleste av troppene vi står overfor er mer maskin enn menneske, men vi tror at deres kollektive bevissthet styres av én kilde...","Rozkład postępuje tak, że większość oddziałów, z którymi mamy do czynienia, to bardziej maszyny niż ludzie, ale wierzymy, że ich zbiorowa świadomość jest kontrolowana przez jedno źródło...",A deterioração avançou de tal forma que a maioria dos soldados que enfrentamos são mais máquina do que humano. Mas acreditamos que a consciência coletiva deles é controlada por uma só fonte... ,,Deteriorarea a avansat în așa fel încăt majoritatea soldațiilor pe care îi înfruntăm să fie mai mult mașini decât oameni dar credem că subconștientul lor colectiv e controlat de o singură sursă...,"Гниение распространялось, поэтому большинство их солдат скорее машины, чем люди. Но мы полагаем, что их коллективное сознание управляется из единого центра...",,"Çürüme o kadar ilerledi ki, karşılaştığımız birliklerin çoğu insandan çok makine ama biz onların kolektif bilincinin tek bir kaynak tarafından kontrol edildiğine inanıyoruz..." +我々は考えている。","부패가 많이 진행되었기에 우리는 사람보다 기계에 가까운 적들과 싸웠고, 우리는 그들의 집단의식이 어떤 하나의 존재가 통제하는 것이라고 생각하고 있습니다...","Het verval is zo ver gevorderd dat de meeste van de troepen die we tegenkomen meer machine zijn dan de mens, maar we geloven dat hun collectieve bewustzijn wordt gecontroleerd door één bron....","Forfallet har gått så langt at de fleste av troppene vi står overfor er mer maskin enn menneske, men vi tror at deres kollektive bevissthet styres av én kilde...","Rozkład postępuje tak, że większość oddziałów, z którymi mamy do czynienia, to bardziej maszyny niż ludzie, ale wierzymy, że ich zbiorowa świadomość jest kontrolowana przez jedno źródło...",A deterioração avançou de tal forma que a maioria dos soldados que enfrentamos são mais máquina do que humano. Mas acreditamos que a consciência coletiva deles é controlada por uma só fonte... ,,Deteriorarea a avansat în așa fel încăt majoritatea soldațiilor pe care îi înfruntăm să fie mai mult mașini decât oameni dar credem că subconștientul lor colectiv e controlat de o singură sursă...,"Гниение распространялось, поэтому большинство их солдат скорее машины, чем люди. Но мы полагаем, что их коллективное сознание управляется из единого центра...",,"Förfallet har gått framåt så att de flesta av de trupper vi möter är mer maskiner än människor, men vi tror att deras kollektiva medvetande styrs av en enda källa...","Çürüme o kadar ilerledi ki, karşılaştığımız birliklerin çoğu insandan çok makine ama biz onların kolektif bilincinin tek bir kaynak tarafından kontrol edildiğine inanıyoruz..." "...the Programmer: creator of the AI which controls the Acolytes. Destroy the Programmer, and we may cripple the Order's troops with a single blow. But caution: we have reports he can vaporize attackers.",TXT_SUB_MAP03_4,〃,,,"...Programátor: tvůrce umělé inteligence, která ovládá akolyty. Znič Programátora a dost možná zasadíme vojskům Řádu mocnou ránu. Ale buď opatrný: Máme zprávy, že umí nechat své útočníky vypařit.","...programmøren: Skaberen af den AI, der styrer akolytterne. Hvis vi ødelægger programmøren, kan vi lamme ordenens tropper med et enkelt slag. Men pas på: Vi har rapporter om, at han kan fordampe angribere.","...der Programmierer: Entwickler der KI, die die Ministranten kontrolliert. Vernichte den Programmierer, und wir könnten die Truppen des Ordens mit einem einzigen Schlag lahmlegen. Aber sieh dich vor. Wir haben Meldungen, dass er Angreifer vaporisieren kann.",,,... el Programador - creador de la IA que controla a los Acólitos. Destruye al Programador y podremos herir a las tropas de la Orden de un solo golpe. Pero cuidado: tenemos informes de que puede vaporizar a atacantes.,,"Ohjelmoitsija: akoluutteja ohjaavan tekoälyn luoja. Tuhoa Ohjelmoitsija, ja saatamme rampauttaa Veljeskunnan joukot yhdellä iskulla. Mutta ole varovainen: tietojemme mukaan hän kykenee haihduttamaan vastustajansa.",Le Programmeur: Créateur de l'IA qui contrôle les Acolytes. Détruisez le Programmeur et nous pourrons paralyser les troupes de l'Ordre d'un seul coup. Faites attentions: des rapports nous disent qu'il peut vaporiser ceux qui l'attaquent.,...maga a Programozó: a ministránsokat irányító MI megalkotója. A Programozót megölve megbéníthatjuk a Rend seregét egy csapással. Azonban vigyázz: a jelentések szerint instant el tudja porlasztani támadóit.,"...il Programmatore: creatore dell'Intelligenza Artificiale che controlla gli Accoliti. Distruggi il Programmatore, e noi potremmo rendere inefficienti i soldati dell'Ordine con un colpo solo. Ma attento: i nostri rapporti indicano che può vaporizzare gli aggressori.","その者の名はプログラマーだ。 彼はアコライト達を操作している人工知能の作成者だ。 プログラマーを殺害すれば、それによってオーダーの兵士たちを無力化できるはずだ。 -だが気をつけておけ、ヤツは熱で敵を蒸発させられるとの報告があるからな。","... 프로그래머: 아콜라이트들을 통제하는 인공지능의 창조자 말입니다. 그를 파괴하면 일격으로 오더의 군대를 무력화시킬 수 있을 겁니다. 하지만 조심하세요, 보고에 의하면 그는 자기 상대를 가루로 만들어 버린다는군요.","...de programmeur: maker van de AI die de Acolieten bestuurt. Vernietig de programmeur, en we kunnen de troepen van de Orde met een enkele klap verlammen. Maar opgelet: we hebben meldingen dat hij aanvallers kan verdampen.","...programmereren: skaperen av AI-en som kontrollerer akolyttene. Ødelegger vi Programmereren, kan vi lamme Ordenens tropper med ett slag. Men forsiktighet: Vi har rapporter om at han kan pulverisere angripere.","...Programista: twórca SI, która kontroluje Akolitów. Zniszcz Programistę, a możemy sparaliżować wojska Zakonu jednym uderzeniem. Ale uwaga: mamy doniesienia, że potrafi on wyparować napastników.","...o Programador: o criador da inteligência artificial que controla os Acólitos. Destrua o programador e, assim, poderemos prejudicar as tropas da Ordem com um único golpe. Mas cuidado: temos relatos de que ele pode vaporizar aqueles que atacam.",,"...Programatorul: creatorul inteligenței artificiale care controlează Acoliții. Distruge-l, și vom nimicii trupele Ordinului cu o singură lovitură: avem rapoarte care spun că poate vaporiza atacatorii.","...Программистом — создателем ИИ, контролирующего служителей. Уничтожь Программиста, и мы разделаемся с войсками Ордена одним ударом. Но осторожнее — нам докладывали, что он умеет... испепелять нападающих.",,"...Programcı: Yardımcıları kontrol eden yapay zekanın yaratıcısı. Programcı'yı yok edersek, Tarikat'ın birliklerini tek bir darbeyle etkisiz hale getirebiliriz. Ama dikkat: Saldırganları buharlaştırabildiğine dair raporlarımız var." +だが気をつけておけ、ヤツは熱で敵を蒸発させられるとの報告があるからな。","... 프로그래머: 아콜라이트들을 통제하는 인공지능의 창조자 말입니다. 그를 파괴하면 일격으로 오더의 군대를 무력화시킬 수 있을 겁니다. 하지만 조심하세요, 보고에 의하면 그는 자기 상대를 가루로 만들어 버린다는군요.","...de programmeur: maker van de AI die de Acolieten bestuurt. Vernietig de programmeur, en we kunnen de troepen van de Orde met een enkele klap verlammen. Maar opgelet: we hebben meldingen dat hij aanvallers kan verdampen.","...programmereren: skaperen av AI-en som kontrollerer akolyttene. Ødelegger vi Programmereren, kan vi lamme Ordenens tropper med ett slag. Men forsiktighet: Vi har rapporter om at han kan pulverisere angripere.","...Programista: twórca SI, która kontroluje Akolitów. Zniszcz Programistę, a możemy sparaliżować wojska Zakonu jednym uderzeniem. Ale uwaga: mamy doniesienia, że potrafi on wyparować napastników.","...o Programador: o criador da inteligência artificial que controla os Acólitos. Destrua o programador e, assim, poderemos prejudicar as tropas da Ordem com um único golpe. Mas cuidado: temos relatos de que ele pode vaporizar aqueles que atacam.",,"...Programatorul: creatorul inteligenței artificiale care controlează Acoliții. Distruge-l, și vom nimicii trupele Ordinului cu o singură lovitură: avem rapoarte care spun că poate vaporiza atacatorii.","...Программистом — создателем ИИ, контролирующего служителей. Уничтожь Программиста, и мы разделаемся с войсками Ордена одним ударом. Но осторожнее — нам докладывали, что он умеет... испепелять нападающих.",,...Programmeraren: skaparen av den intelligenta intelligens som kontrollerar akoliterna. Förstör Programmeraren och vi kan lamslå ordens trupper med ett enda slag. Men var försiktig: vi har rapporterat att han kan förånga angripare.,"...Programcı: Yardımcıları kontrol eden yapay zekanın yaratıcısı. Programcı'yı yok edersek, Tarikat'ın birliklerini tek bir darbeyle etkisiz hale getirebiliriz. Ama dikkat: Saldırganları buharlaştırabildiğine dair raporlarımız var." "Fragments assembled from the Programmers files tell us that the Order is worshipping an intelligent weapon. They call it ""the Sigil"".",TXT_SUB_MAP10_1,MAP10: Macil.,,,"Útržky poskládané z Programátorových souborů nám říkají, že Řád uctívá inteligentní zbraň. Říkají jí „Pečeť“.","Fragmenter, der er samlet fra Programmerens filer, fortæller os, at Ordenen tilbeder et intelligent våben. De kalder det ""Sigil"".","Fragmente, zusammengestellt aus den Dateien des Programmierers, sagen uns, dass der Orden eine intelligente Waffe verehrt. Sie nennen sie „Das Sigil“.",,,"Fragmentos reunidos de los archivos del Programador nos dicen que la Orden adora un arma inteligente. La llaman ""el Emblema"".",,Ohjelmoitsijan tiedostoista kerättyjen pirstaleiden mukaan Veljeskunta palvoo älykästä asetta. He kutsuvat sitä Sinetiksi.,"Des fragments des fichiers du Programmeur que nous avons assemblés nous disent que l'Ordre vénère une arme intelligente. Ils l'appelent le ""Sigil"".","A Programozó fájljainak töredékeiből kiderítettük, hogy a Rend egy intelligens fegyverhez imádkozik. Csak ""Pecsét"" néven említik.","Frammenti dei file del Programmatore che abbiamo assemblato ci dicono che l'Ordine venera un'arma intelligente. La chiamano ""il Sigillo"".","プログラマーの資料を要約するとその欠片はオーダー達が崇拝する知性を持った武器、 -'シジル'だ。","프로그래머의 파괴된 기록들을 복원해보니, 오더가 자아를 가진 한 무기를 숭배하고 있다는군요. 그들은 이걸 “시질”이라고 부릅니다.","Fragmenten uit de Programmers bestanden vertellen ons dat de Orde een intelligent wapen aanbidt. Ze noemen het ""de Sigil"".","Fragmenter fra Programmererens filer forteller oss at Ordenen tilber et intelligent våpen. De kaller det ""Sigil"".","Fragmenty zebrane z akt Programistów mówią nam, że Zakon czci inteligentną broń. Nazywają ją ""Sigil"".","Os fragmentos dos relatórios sobre o Programador que conseguimos juntar dizem que a Ordem está venerando uma arma inteligente. Eles a chamam de ""Sigilo"".",,"Fragmentele asamblate din fișierele Programatorului ne spun că Ordinul venerează o armă inteligentă. O numesc ""Sigiliul"".","Мы собирали информацию по крупицам из обрывков файлов Программиста и выяснили, что Орден поклоняется разумному оружию. Они называют его «Печатью».",,"Programcıların dosyalarından toplanan parçalar bize Tarikat'ın akıllı bir silaha taptığını söylüyor. Ona ""Sigil"" diyorlar." +'シジル'だ。","프로그래머의 파괴된 기록들을 복원해보니, 오더가 자아를 가진 한 무기를 숭배하고 있다는군요. 그들은 이걸 “시질”이라고 부릅니다.","Fragmenten uit de Programmers bestanden vertellen ons dat de Orde een intelligent wapen aanbidt. Ze noemen het ""de Sigil"".","Fragmenter fra Programmererens filer forteller oss at Ordenen tilber et intelligent våpen. De kaller det ""Sigil"".","Fragmenty zebrane z akt Programistów mówią nam, że Zakon czci inteligentną broń. Nazywają ją ""Sigil"".","Os fragmentos dos relatórios sobre o Programador que conseguimos juntar dizem que a Ordem está venerando uma arma inteligente. Eles a chamam de ""Sigilo"".",,"Fragmentele asamblate din fișierele Programatorului ne spun că Ordinul venerează o armă inteligentă. O numesc ""Sigiliul"".","Мы собирали информацию по крупицам из обрывков файлов Программиста и выяснили, что Орден поклоняется разумному оружию. Они называют его «Печатью».",,"Fragment som samlats ihop från Programmerarens filer säger oss att Orden dyrkar ett intelligent vapen. De kallar det ""Sigil"".","Programcıların dosyalarından toplanan parçalar bize Tarikat'ın akıllı bir silaha taptığını söylüyor. Ona ""Sigil"" diyorlar." "The piece you touched and recovered is one of five. It wields power drawn from the user's own life force. While you live, you control its power.",TXT_SUB_MAP10_2,〃,,,"Díl, kterého jsi se dotknul a ponechal si je jeden z pěti. Mocní se silou, napájenou ze životní energie jejího majitele. Dokud žiješ, ovládáš jeho sílu.","Det stykke, du rørte og fandt, er et af fem. Det udøver kraft fra brugerens egen livskraft. Mens du lever, kontrollerer du dens kraft.","Das Teil, das du berührt und gefunden hast, ist eines von fünf. Es bezieht die Kraft von der Lebensenergie des Benutzers. So lange du lebst, kontrollierst du seine Kraft.",,,"La pieza que has tocado y recuperado es una de cinco. Esgrime poder tomado de la propia fuerza de vida del usuario. Mientras vivas, controlas su poder.",,"Koskettamasi osanen, jonka otit talteen, on yksi viidestä. Se saa voimansa käyttäjänsä omasta elämänvoimasta. Niin kauan kuin sinä elät, hallitset sen voimaa.","La pièce que vous avez touché et récupéré n'est qu'une parmi cinq. Elle utilise la force vitale de son utilisateur. Tant que vous êtes en vie, vous son pouvoir sous votre contrôle.","A darabka amit megérintettél és visszaszereztél csak egy az ötből. Erejét a hordozója életerejéből meríti. Amíg tehát élsz, tudod irányítani.","Il pezzo che hai toccato e recuperato è solo uno di cinque. Utilizza la forza vitale dell'utilizzatore. Finchè sei vivo, hai il potere sotto il tuo controllo.","君が欠片を取り戻したがそれは5つある内の1つだ。 使用者の生命を吸い上げ激しい力を引き出す。 -ただ制御下におけるのは生きている間だけだ。","당신이 건져낸 조각은 다섯 개의 조각 중 하나입니다. 이것은 사용자의 생명력을 빨아들여 위력을 발휘합니다. 당신이 살아있는 동안, 녀석의 힘은 당신의 것입니다.","Het stuk dat je hebt aangeraakt en teruggevonden is een van de vijf. Het heeft kracht die getrokken wordt uit de eigen levenskracht van de gebruiker. Terwijl je leeft, heb je de macht ervan in handen.","Brikken du berørte og gjenopprettet er en av fem. Den har kraft hentet fra brukerens egen livskraft. Mens du lever, kontrollerer du dens kraft.","Kawałek, który dotknąłeś i odzyskałeś, jest jednym z pięciu. Włada mocą czerpaną z własnej siły życiowej użytkownika. Póki żyjesz, kontrolujesz jego moc.","A peça que você tocou e recuperou é uma das cinco peças. Seu poder vem da própria energia de vida de quem a usa. Enquanto você viver, você controla o poder dela.",,"Piesa pe care ai atins-o și recuperat-o e una din cinci. Își trage puterea din deținător. Cât trăiești, o controlezi.","Тот фрагмент, что ты подобрал и активировал, — один из пяти. Он использует мощь, которую черпает из жизненных сил владельца. Пока ты жив, она подвластна тебе.",,"Dokunduğunuz ve kurtardığınız parça beş taneden biri. Kullanıcının kendi yaşam gücünden alınan gücü kullanıyor. Yaşadığın sürece, onun gücünü kontrol ediyorsun." +ただ制御下におけるのは生きている間だけだ。","당신이 건져낸 조각은 다섯 개의 조각 중 하나입니다. 이것은 사용자의 생명력을 빨아들여 위력을 발휘합니다. 당신이 살아있는 동안, 녀석의 힘은 당신의 것입니다.","Het stuk dat je hebt aangeraakt en teruggevonden is een van de vijf. Het heeft kracht die getrokken wordt uit de eigen levenskracht van de gebruiker. Terwijl je leeft, heb je de macht ervan in handen.","Brikken du berørte og gjenopprettet er en av fem. Den har kraft hentet fra brukerens egen livskraft. Mens du lever, kontrollerer du dens kraft.","Kawałek, który dotknąłeś i odzyskałeś, jest jednym z pięciu. Włada mocą czerpaną z własnej siły życiowej użytkownika. Póki żyjesz, kontrolujesz jego moc.","A peça que você tocou e recuperou é uma das cinco peças. Seu poder vem da própria energia de vida de quem a usa. Enquanto você viver, você controla o poder dela.",,"Piesa pe care ai atins-o și recuperat-o e una din cinci. Își trage puterea din deținător. Cât trăiești, o controlezi.","Тот фрагмент, что ты подобрал и активировал, — один из пяти. Он использует мощь, которую черпает из жизненных сил владельца. Пока ты жив, она подвластна тебе.",,Den bit som du rörde vid och återfann är en av fem. Den använder kraft som hämtas från användarens egen livskraft. Så länge du lever kontrollerar du dess kraft.,"Dokunduğunuz ve kurtardığınız parça beş taneden biri. Kullanıcının kendi yaşam gücünden alınan gücü kullanıyor. Yaşadığın sürece, onun gücünü kontrol ediyorsun." "The shock which knocked you out was the Sigil piece tuning itself to you, your pulse and brain waves. You can wield it, but at a cost: it will drain you dry.",TXT_SUB_MAP10_3,〃,,,"Ránu, která tě uspala, způsobil ten díl Pečeti, ladící sám sebe k tobě, tvému pulzu a mozkovým vlnám. Můžeš jej používat, ale za určitou cenu: Bude tě vysilovat.","Det chok, der slog dig bevidstløs, var Sigilstykket, der indstillede sig på dig, din puls og dine hjernebølger. Du kan bruge det, men det har en pris: det vil dræne dig for energi.","Der Schock, durch den du das Bewusstsein verloren hast, wurde verursacht, als das Sigilteil sich auf dich, deinen Puls und deine Gehirnwellen eingestellt hat. Du kannst es benutzen, aber es wird dich austrocknen.",,,"El choque que te derribó fue la pieza del Emblema sintonizándose contigo, con tu pulso y ondas cerebrales. Puedes empuñarla, pero con un precio: Te dejará seco.",,"Kokemasi sysäys, joka tyrmäsi sinut, oli Sinetin virittäytymistä sinuun, sinun sykkeeseesi ja aivoaaltoihisi. Hallitset sitä, mutta sillä hinnalla, että se imee sinut kuiviin.","Le choc qui vous a rendu inconscient venait de la pièce du Sigil qui s'est alignée sur votre énergie vitale, votre pouls et vos ondes cérébrales. Vous pouvez l'utiliser, mais au coût de votre vie.","A sokk ami kiütött nem volt más, mint maga a Pecsét ráhangolódása a pulzusodra és agyhullámodra. Forgathatod mint egy kardot, de ára van: kiszívja az életerődet.","Lo schock che ti ha fatto perdere i sensi era un pezzo del Sigillo che si è allineato con la tua energia vitale, il tuo polso e le tue onde cerebrali. Puoi utilizzarlo, ma ad un costo: ti prosciugherà in pieno.","君を気絶させた衝撃は、シジルの欠片が脈拍と脳波を同期させた際に起こした様だ。 -それを振り回す時は気を付けろ、代償で体が干上がってしまうらしい。","당신을 기절시킨 충격은 시질이 당신의 심박과 뇌파와 반응하면서 비롯되었습니다. 이 무기를 써도 되지만, 조심하세요: 당신을 말려 죽일 수도 있으니까.","De schok die je bewusteloos maakte, was de Sigil die zich op jou, je pols en hersengolven, afstemde. Je kunt het gebruiken, maar tegen een prijs: het zal je droog laten vallen.","Sjokket som slo deg ut var Sigil-brikken som innstilte seg på deg, pulsen din og hjernebølgene dine. Du kan bruke det, men det koster: det vil tappe deg for krefter.","Wstrząs, który cię znokautował, to kawałek Sigilu, który dostroił się do ciebie, twojego pulsu i fal mózgowych. Możesz nim władać, ale za pewną cenę: wyczerpie cię do cna.","O choque que te derrubou foi da peça do Sigilo se calibrando a você, com o seu pulso e suas ondas cerebrais. Você pode usá-la, mas tem um custo: ela vai te drenar por completo.",,"Șocul care te-a lăsat inconștient a fost piesa care s-a întors asupra ta. O controlezi, dar cu un preț: o să te sece.","Ты потерял сознание, потому что фрагмент Печати подстраивался под тебя, под твоё сердцебиение и мозговые ритмы. Теперь ты сможешь им пользоваться, но он будет взымать свою плату, иссушая тебя.",,"Sizi bayıltan şok, Sigil parçasının kendisini size, nabzınıza ve beyin dalgalarınıza göre ayarlamasıydı. Onu kullanabilirsin ama bir bedeli var: Seni kurutacak." +それを振り回す時は気を付けろ、代償で体が干上がってしまうらしい。","당신을 기절시킨 충격은 시질이 당신의 심박과 뇌파와 반응하면서 비롯되었습니다. 이 무기를 써도 되지만, 조심하세요: 당신을 말려 죽일 수도 있으니까.","De schok die je bewusteloos maakte, was de Sigil die zich op jou, je pols en hersengolven, afstemde. Je kunt het gebruiken, maar tegen een prijs: het zal je droog laten vallen.","Sjokket som slo deg ut var Sigil-brikken som innstilte seg på deg, pulsen din og hjernebølgene dine. Du kan bruke det, men det koster: det vil tappe deg for krefter.","Wstrząs, który cię znokautował, to kawałek Sigilu, który dostroił się do ciebie, twojego pulsu i fal mózgowych. Możesz nim władać, ale za pewną cenę: wyczerpie cię do cna.","O choque que te derrubou foi da peça do Sigilo se calibrando a você, com o seu pulso e suas ondas cerebrais. Você pode usá-la, mas tem um custo: ela vai te drenar por completo.",,"Șocul care te-a lăsat inconștient a fost piesa care s-a întors asupra ta. O controlezi, dar cu un preț: o să te sece.","Ты потерял сознание, потому что фрагмент Печати подстраивался под тебя, под твоё сердцебиение и мозговые ритмы. Теперь ты сможешь им пользоваться, но он будет взымать свою плату, иссушая тебя.",,"Den chock som slog dig medvetslös var att Sigilstycket anpassade sig till dig, din puls och dina hjärnvågor. Du kan använda den, men till ett pris: den kommer att tömma dig på vatten.","Sizi bayıltan şok, Sigil parçasının kendisini size, nabzınıza ve beyin dalgalarınıza göre ayarlamasıydı. Onu kullanabilirsin ama bir bedeli var: Seni kurutacak." One piece constitutes awesome power. Possession of all five pieces would be devastating and would give the user total control of the planet.,TXT_SUB_MAP10_4,〃,,,Jen jeden díl obsahuje ohromnou sílu. Vlastnictví všech pěti dílů by bylo devastující a jeho majitel by byl schopen ovládat celou planetu.,Et stykke udgør en fantastisk kraft. Besiddelse af alle fem stykker ville være ødelæggende og ville give brugeren total kontrol over planeten.,"Ein Teil stellt große Macht dar. Der Besitz aller fünf Teile wäre verheerend, und der Nutzer hätte die totale Kontrolle über den Planeten.",,,"Una pieza constituye un poder impresionante, poseer las cinco piezas sería devastador y daría al usuario control total del planeta.",,Jo yhdessä osasessa piilee valtava mahti. Kaikkien viiden osasen hallitseminen olisi tuhoisaa ja antaisi käyttäjälleen täydellisen otteen planeetasta.,Une pièce représente un pouvoir phénoménal. Posséder toutes les cinq serait dévastateur: cela donnerait à l'utilisateur le contrôle total sur la planète.,"Egy darab nagy hatalmat biztosít hordozójának. Azonban mind az öt darabka együtt emberfeletti erővel ruházná fel, és az egész bolygó felett átvenné a hatalmat.",Un pezzo costituisce un potere fenomenale. Il possesso di tutti i cinque pezzi sarebbe devastante: darebbe all'utilizzatore il controllo totale sul pianeta.,"だがたった一つでも相当な力を放つ。 -それが5つ揃った時は圧倒的な力で世界をも支配下に置けるだろう。","하나의 조각으로도 엄청난 위력을 가지게 되고, 다섯 조각 모두를 얻으면 이 세상을 평정할 만큼 강력한 위력을 발휘할 것입니다.",Een stuk vormt ontzagwekkende kracht. Het bezit van alle vijf de stukken zou verwoestend zijn en zou de gebruiker de volledige controle over de planeet geven.,Ett stykke utgjør en fantastisk kraft. Besittelse av alle fem brikkene ville være ødeleggende og gi brukeren total kontroll over planeten.,Jeden kawałek stanowi niesamowitą moc. Posiadanie wszystkich pięciu kawałków byłoby niszczące i dałoby użytkownikowi całkowitą kontrolę nad planetą.,Uma das peças possui um poder tremendo. Possuir todas as cinco peças seria devastador e daria controle total do planeta ao utilizador.,,O piesă constituie putere uimitoare. Posesiunea tuturor pieselor ar fi devastatore și ar da deținătorului control asupra întregii planete.,Один фрагмент — уже немалая сила. Пять фрагментов будут опустошающей силой. Их владелец получит полную власть над планетой.,,Tek bir parça müthiş bir güç demektir. Beş parçaya birden sahip olmak yıkıcı olur ve kullanıcıya gezegenin kontrolünü tamamen verir. +それが5つ揃った時は圧倒的な力で世界をも支配下に置けるだろう。","하나의 조각으로도 엄청난 위력을 가지게 되고, 다섯 조각 모두를 얻으면 이 세상을 평정할 만큼 강력한 위력을 발휘할 것입니다.",Een stuk vormt ontzagwekkende kracht. Het bezit van alle vijf de stukken zou verwoestend zijn en zou de gebruiker de volledige controle over de planeet geven.,Ett stykke utgjør en fantastisk kraft. Besittelse av alle fem brikkene ville være ødeleggende og gi brukeren total kontroll over planeten.,Jeden kawałek stanowi niesamowitą moc. Posiadanie wszystkich pięciu kawałków byłoby niszczące i dałoby użytkownikowi całkowitą kontrolę nad planetą.,Uma das peças possui um poder tremendo. Possuir todas as cinco peças seria devastador e daria controle total do planeta ao utilizador.,,O piesă constituie putere uimitoare. Posesiunea tuturor pieselor ar fi devastatore și ar da deținătorului control asupra întregii planete.,Один фрагмент — уже немалая сила. Пять фрагментов будут опустошающей силой. Их владелец получит полную власть над планетой.,,Ett stycke utgör en fantastisk kraft. Att äga alla fem delar skulle vara förödande och ge användaren total kontroll över planeten.,Tek bir parça müthiş bir güç demektir. Beş parçaya birden sahip olmak yıkıcı olur ve kullanıcıya gezegenin kontrolünü tamamen verir. "Listen, this com unit tells me that you're 100% human. I've been ordered to bring you in, we're talking trust here. Betray me and pay. Oh, and by the way, you can call me Blackbird.",TXT_SUB_LOG2,MAP02: After getting the com unit from Rowan and leaving his room.,,,"Poslyš, tento komunikátor mi říká, že jsi na sto procent člověkem. Dostala jsem rozkaz tě přivést tě k nám; jde o důvěryhodnou záležitost - zraď mě a zaplatíš. Jo, a mimochodem, můžeš mi říkat Straka.","Hør, denne com-enhed fortæller mig, at du er 100 % menneskelig. Jeg er blevet beordret til at bringe dig ind, vi taler om tillid her. Forråd mig og betal. Og forresten, du kan kalde mig Blackbird.","Hör zu, dieser Kommunikator sagt mit, dass du noch 100% menschlich bist. Mir wurde aufgetragen, dich zu unserer Zentrale zu führen. Wir reden über Vertrauen, wenn du mich verrätst, wirst du bezahlen. Übrigens, du kannst mich Blackbird nennen.",,,"Escucha, este intercomunicador me dice que eres 100% humano. Se me ha ordenado dejarte entrar, así que hablamos en confianza. Traicióname y pagarás. Ah, por cierto, puedes llamarme BlackBird.","Escucha, este intercomunicador me dice que eres 100% humano. Se ordenadó dejarte entrar, así que hablamos en confianza. Traicióname y te vas a arrepentir. Ah, por cierto, puedes llamarme BlackBird.","Kuule, tämä viestintälaite ilmaisee sinun olevan sataprosenttisesti ihminen. Minut on määrätty tuomaan sinut meidän joukkoomme; puhumme luottamuksellisesti. Petä minut ja saat luvan maksaa. Ja muuten, voit kutsua minua Blackbirdiksi.","Ecoute, ce communicateur me dit que tu est 100% humain. On m'a ordonnée de te ramener, c'est une question de confiance. Trahis-moi et tu paieras. Oh, et tu peux m'appeler Blackbird.","Figyelj csak, azt mutatja ez a kommunikációs egység hogy 100%-ban ember vagy. Azt az utasítást kaptam, hogy hozzalak be. Vakon beléd vetjük a bizalmunkat, de tudd, hogy ha elárulsz minket meglakolsz. Ja, és hívhatsz Feketerigónak.","Ascolta, questa unità di comunicazione mi dice che sei 100% umano. Ho l'ordine di farti arrivare da noi, e quindi stiamo parlando di fiducia. Se mi tradisci la pagherai cara. Comunque, mi puoi chiamare Blackbird.","聞こえるか、この無線機がアナタは100%人間だと判断した。 私はアナタを信頼して良いとみて連れて来るよう命じられた、 -反乱への報酬は期待して良いわ。ああ、それと、私の名はブラックバードよ。","잘 들어, 이 통신기에 따르면 넌 100% 인간이야. 너를 믿어도 될 거 같으니 우리 편으로 끌어모으라는 지시를 받았어. 배신했다간 대가를 치를 거야. 아, 그리고, 날 블랙버드라고 불러줘.","Luister, deze com-unit zegt me dat je 100% menselijk bent. Ik heb opdracht gekregen om je binnen te halen, we hebben het hier over vertrouwen. Verraad me en betaal. Oh, en trouwens, je mag me Blackbird noemen.","Denne kommunikasjonsenheten forteller meg at du er 100 % menneskelig. Jeg har fått ordre om å hente deg inn, vi snakker om tillit her. Forråd meg og betal. Og forresten, du kan kalle meg Blackbird.","Słuchaj, to urządzenie mówi mi, że jesteś w 100% człowiekiem. Otrzymałem rozkaz sprowadzenia cię, mówimy tu o zaufaniu. Zdradzisz mnie i zapłacisz. Aha, i przy okazji, możesz mi mówić Blackbird.","Ouça, este comunicador me diz que você é 100% humano. Recebi ordens para te trazer até aqui. É melhor você ser de confiança. Se você me trair, você me paga. Ah, a propósito, pode me chamar de Blackbird.",,"Ascultă, unitatea asta îmi spune că ești 100% uman. Am primit ordin să te aduc, vorbim de încredere aici. Trădează-mă și plătești. Oh, și apropo, îmi poți spune Blackbird.","Слушай — судя по этому передатчику, ты на сто процентов человек. Я получила приказ показать тебе дорогу к нам. Как видишь, тебе доверяют, но если предашь меня — пожалеешь. И да, обращайся ко мне «Чёрный дрозд». ",,"Dinle, bu iletişim birimi bana senin %100 insan olduğunu söylüyor. Seni getirmem emredildi, burada güvenden bahsediyoruz. Bana ihanet edersen bedelini ödersin. Bu arada bana Karatavuk diyebilirsin." +反乱への報酬は期待して良いわ。ああ、それと、私の名はブラックバードよ。","잘 들어, 이 통신기에 따르면 넌 100% 인간이야. 너를 믿어도 될 거 같으니 우리 편으로 끌어모으라는 지시를 받았어. 배신했다간 대가를 치를 거야. 아, 그리고, 날 블랙버드라고 불러줘.","Luister, deze com-unit zegt me dat je 100% menselijk bent. Ik heb opdracht gekregen om je binnen te halen, we hebben het hier over vertrouwen. Verraad me en betaal. Oh, en trouwens, je mag me Blackbird noemen.","Denne kommunikasjonsenheten forteller meg at du er 100 % menneskelig. Jeg har fått ordre om å hente deg inn, vi snakker om tillit her. Forråd meg og betal. Og forresten, du kan kalle meg Blackbird.","Słuchaj, to urządzenie mówi mi, że jesteś w 100% człowiekiem. Otrzymałem rozkaz sprowadzenia cię, mówimy tu o zaufaniu. Zdradzisz mnie i zapłacisz. Aha, i przy okazji, możesz mi mówić Blackbird.","Ouça, este comunicador me diz que você é 100% humano. Recebi ordens para te trazer até aqui. É melhor você ser de confiança. Se você me trair, você me paga. Ah, a propósito, pode me chamar de Blackbird.",,"Ascultă, unitatea asta îmi spune că ești 100% uman. Am primit ordin să te aduc, vorbim de încredere aici. Trădează-mă și plătești. Oh, și apropo, îmi poți spune Blackbird.","Слушай — судя по этому передатчику, ты на сто процентов человек. Я получила приказ показать тебе дорогу к нам. Как видишь, тебе доверяют, но если предашь меня — пожалеешь. И да, обращайся ко мне «Чёрный дрозд». ",,"Lyssna, den här kommunikationsenheten säger mig att du är 100 % mänsklig. Jag har fått order att ta in dig, vi pratar om förtroende här. Förråda mig och betala. Och förresten, du kan kalla mig Blackbird.","Dinle, bu iletişim birimi bana senin %100 insan olduğunu söylüyor. Seni getirmem emredildi, burada güvenden bahsediyoruz. Bana ihanet edersen bedelini ödersin. Bu arada bana Karatavuk diyebilirsin." "Head over to the old town hall. After the Order bombed it, Macil had a tunnel built that lets us get in and out without the acolytes' knowledge.",TXT_SUB_LOG3,MAP02: On the bridge with the com unit.,,,"Zamiř ke staré radnici. Když ji Řád vybombardoval, Macil nechal postavit tunel, který nám umožňuje bez vědomí akolytů dostat se dovnitř a ven.","Gå over til det gamle rådhus. Efter at Ordenen bombede det, fik Macil bygget en tunnel, som lader os komme ind og ud uden acolytes' viden.","Geh zum alten Rathaus. Macil hat einen Tunnel bauen lassen, durch den wir dort reinkommen, ohne dass die Ministranten das mitbekommen.",,,"Dirígete al antiguo ayuntamiento. Después de que lo bombardeara La Orden, Macil hizo construir un túnel que nos permite entrar y salir sin que los acólitos lo sepan.",,"Suuntaa kohti vanhaa kaupungintaloa. Sen jälkeen kun Veljeskunta oli pommittanut sen, Macil rakennutti tunnelin, jonka avulla voimme päästä sisään ja ulos akoluuttien tietämättä.",Dirige-toi vers l'ancienne mairie. Macil a fait construire un tunnel après que L'Ordre l'ait bombardée. Il nous permet d'y entrer sans que l'Ordre nous remarque.,"Menj a régi városközpontba. Miután a Rend lebombázta, Macil építtetett egy titkos alagutat, amin észrevétlenül tudunk ki- és bemenni a ministránsok tudta nélkül.",Raggiungi il vecchio Municipio. Macil ha fatto costruire un tunnel che ci fa entrare ed uscire senza che gli accoliti lo sappiano.,"旧市庁舎に向かうんだ。オーダーに爆撃された後 -そこにマシルがアコライトに関わる者を欺く為の抜け道を用意している。",구 시청으로 향해. 오더가 이곳을 폭격한 후에 마실이 그곳에 아콜라이트들이 모르는 통행로를 만들어놨어.,"Ga naar het oude stadhuis. Nadat de Orde het gebombardeerd had, liet Macil een tunnel bouwen die ons in en uit laat stappen zonder dat de acolieten het wisten.","Dra til det gamle rådhuset. Etter at Ordenen bombet det, fikk Macil bygget en tunnel som lar oss komme inn og ut uten at akolyttene vet om det.","Udaj się do starego ratusza. Po zbombardowaniu go przez Zakon, Macil kazał wybudować tunel, który pozwala nam wejść i wyjść bez wiedzy akolitów.","Vá até à antiga prefeitura. Depois que a Ordem a bombardeou, Macil mandou construir um túnel que nos leva e tira de lá sem os acólitos perceberem.",,"Du-te la vechea hală a orașului, Macil a construit un tunel care permite trecerea fără a fi detectat.","Отправляйся к старой ратуше. После того, как Орден взорвал её, Мэйсил построил там туннель, который позволяет нам входить и выходить без ведома служителей.",,"Eski belediye binasına git. Tarikat orayı bombaladıktan sonra Macil, yardımcıların haberi olmadan girip çıkmamızı sağlayan bir tünel inşa ettirdi." +そこにマシルがアコライトに関わる者を欺く為の抜け道を用意している。",구 시청으로 향해. 오더가 이곳을 폭격한 후에 마실이 그곳에 아콜라이트들이 모르는 통행로를 만들어놨어.,"Ga naar het oude stadhuis. Nadat de Orde het gebombardeerd had, liet Macil een tunnel bouwen die ons in en uit laat stappen zonder dat de acolieten het wisten.","Dra til det gamle rådhuset. Etter at Ordenen bombet det, fikk Macil bygget en tunnel som lar oss komme inn og ut uten at akolyttene vet om det.","Udaj się do starego ratusza. Po zbombardowaniu go przez Zakon, Macil kazał wybudować tunel, który pozwala nam wejść i wyjść bez wiedzy akolitów.","Vá até à antiga prefeitura. Depois que a Ordem a bombardeou, Macil mandou construir um túnel que nos leva e tira de lá sem os acólitos perceberem.",,"Du-te la vechea hală a orașului, Macil a construit un tunel care permite trecerea fără a fi detectat.","Отправляйся к старой ратуше. После того, как Орден взорвал её, Мэйсил построил там туннель, который позволяет нам входить и выходить без ведома служителей.",,Gå till det gamla stadshuset. Efter att Orden bombade det lät Macil bygga en tunnel som gör att vi kan ta oss in och ut utan acolytternas vetskap.,"Eski belediye binasına git. Tarikat orayı bombaladıktan sonra Macil, yardımcıların haberi olmadan girip çıkmamızı sağlayan bir tünel inşa ettirdi." "Go through the door on your left, then the one on the right. The guard's name is Geoff. Tell him you need gold.",TXT_SUB_LOG4,MAP02: In hall town with the com unit.,,,"Projdi dveřmi nalevo a pak napravo. Hlídač se jmenuje Geoff. Řekni mu, že potřebuješ zlato.","Gå gennem døren til venstre og derefter gennem den til højre. Vagtens navn er Geoff. Sig til ham, at du har brug for guld.","Geh durch die linke Tür, dann durch die rechte. Der Wächter heißt Geoff. Sag ihm du brauchst Gold.",,"Iru tra la maldekstra pordo kaj poste tra la dekstra. La nomo de la gardisto estas Geoff; diru al li «Saluton, mi bezonas oron».","Ve por la puerta izquierda y luego por la derecha. El guardia se llama Geoff; dile «Buenas, necesito oro».",,"Kulje sinusta katsottuna vasemmalla puolella olevan oven läpi, sitten oikeanpuoleisesta ovesta. Vartijan nimi on Geoff. Kerro hänelle tarvitsevasi kultaa.",Passe par la porte à gauche puis celle à droite. Le garde s'appelle Geoff. Dis-lui que tu as besoin d'argent.,"Menj át a bal oldali ajtón, majd a jobb oldalin. Az őr neve Geoff. Mond neki, hogy aranyra van szükséged.","Vai oltre la porta alla tua sinistra, e poi la porta alla tua destra. Il nome della guardia è Geoff. Digli che ti serve dell'oro.","すぐ左のドアを通り、右のドアから小部屋に入るんだ。 -見張りの名はジェフ。金が必要だ と言えば通じる。","네 왼쪽의 문으로 들어간 후, 다시 오른쪽의 문으로 가. 경비의 이름은 제프야. 그에게 골드가 필요하다고 얘기해.","Ga door de deur links van je, dan die rechts van je. De bewaker heet Geoff. Zeg hem dat je goud nodig hebt.","Gå gjennom døren til venstre, så den til høyre. Vakten heter Geoff. Si at du trenger gull.","Przejdź przez drzwi po lewej, a potem przez te po prawej. Strażnik ma na imię Geoff. Powiedz mu, że potrzebujesz złota.",Vá pela porta à sua esquerda e depois a da direita. O nome do guarda é Geoff. Diga a ele que você precisa de ouro.,,"Du-te prin ușa la stânga, apoi dreapta. Numele gardianului e Geoff. Spune-i că ai nevoie de aur.","Пройди за левую дверь, затем иди направо. Стражника зовут Джефф. Скажи ему, что тебе нужно золото.",,"Solundaki kapıdan geç, sonra sağdakinden. Muhafızın adı Geoff. Ona altına ihtiyacın olduğunu söyle." +見張りの名はジェフ。金が必要だ と言えば通じる。","네 왼쪽의 문으로 들어간 후, 다시 오른쪽의 문으로 가. 경비의 이름은 제프야. 그에게 골드가 필요하다고 얘기해.","Ga door de deur links van je, dan die rechts van je. De bewaker heet Geoff. Zeg hem dat je goud nodig hebt.","Gå gjennom døren til venstre, så den til høyre. Vakten heter Geoff. Si at du trenger gull.","Przejdź przez drzwi po lewej, a potem przez te po prawej. Strażnik ma na imię Geoff. Powiedz mu, że potrzebujesz złota.",Vá pela porta à sua esquerda e depois a da direita. O nome do guarda é Geoff. Diga a ele que você precisa de ouro.,,"Du-te prin ușa la stânga, apoi dreapta. Numele gardianului e Geoff. Spune-i că ai nevoie de aur.","Пройди за левую дверь, затем иди направо. Стражника зовут Джефф. Скажи ему, что тебе нужно золото.",,Gå genom dörren till vänster och sedan genom dörren till höger. Vaktens namn är Geoff. Säg till honom att du behöver guld.,"Solundaki kapıdan geç, sonra sağdakinden. Muhafızın adı Geoff. Ona altına ihtiyacın olduğunu söyle." "Irale is the Front's ""fixer"". He's behind the unmarked door next to the weapons shop.",TXT_SUB_LOG5,MAP03: After joining the Front.,,,Irale je „kutil“ Fronty. Je za neoznačenými dveřmi vedle obchodu se zbraněmi.,"Irale er frontens ""fixer"". Han befinder sig bag den umærkede dør ved siden af våbenbutikken.",Irale ist der „Bastler“ der Front. Er ist hinter der unmarkierten Tür neben dem Waffengeschäft.,,,Irale es el «apañador» del Frente. Está pasando la puerta sin cartel junto a la tienda de armas.,Irale es el «soluccionador» del Frente. Está pasando la puerta sin cartel junto a la tienda de armas.,"Irale on Rintaman ""järkkäri"". Hänet löytää merkkaamattoman oven takaa asekaupan vierestä.",Irale est le receleur du front. Il est derrière la porte non marquée à côté du magasin d'armes.,"Irale a Front ""ezermestere"". A jelöletlen ajtó mögött lesz a fegyverbolt mellett.",Irale è un fornitore di armi per il Fronte. Si trova dietro la porta accanto al negozio di armi.,"イラールとはフロントの'仲介者'よ。彼は武器屋の隣のマークされてないドアに居る。 -発電所に近い所だ。",이롤리는 프론트의 수리공이기도 해. 무기상점 근처에 그의 가게로 향하는 문이 있을 거야.,"Irale is de ""fixer"" van de Front. Hij zit achter de ongemarkeerde deur naast de wapenwinkel.","Irale er Frontens ""fikser"". Han er bak den umerkede døren ved siden av våpenbutikken.","Irale to ""załatwiacz"" Frontu. Jest za nieoznakowanymi drzwiami obok sklepu z bronią.","Irale é o ""quebra-galho"" da Frente. Ele está atrás da porta desmarcada próxima ao depósito de armas.",,"Irale e ""reparatorul"" Frontului. E în spatele ușii fără însemn lângă magazinul de arme.",Ирэйл — «наладчик» Сопротивления. Ты найдёшь его за дверью без вывески возле оружейного магазина.,,"İrale, Cephe'nin ""iş bitiricisi"". Silah dükkanının yanındaki işaretlenmemiş kapının arkasında." -Remember: kill with stealth instead of force. You won't set off the alarms.,TXT_SUB_LOG6,MAP02,,,Pamatuj: Zabíjej potichu. Nespustíš poplach.,Husk: Dræb med list i stedet for med magt. Du vil ikke udløse alarmen.,Denk daran: Töte lautlos und du wirst den Alarm nicht auslösen.,,,Recuerda: mata con sigilo y no con fuerza para no activar las alarmas.,,Muista: tapa huomaamattomasti voiman sijasta. Niin vältät hälytyksen.,"Souviens-toi: Tue avec discrétion, pas avec force, et tu n'activeras pas les alarmes.","Figyelj arra, hogy lopakodva ölj, ne erővel. Így nem indítod be a riasztót.",Ricorda: uccidi silenziosamente invece di usare la forza. Così facendo non attiverai gli allarmi.,覚えておいて:静かに殺す時はナイフか毒矢だ。警報を鳴らすと厄介なことになる。,기억해: 소음 없이 조용히 죽여. 그럼 경보를 울리지 않을 테니까.,Onthoud: dood met heimelijke in plaats van met geweld. Je laat de alarmen niet afgaan.,"Husk: drep i det skjulte, ikke med makt. Du vil ikke utløse alarmen.","Pamiętaj: zabijaj ukradkiem, a nie siłą. Nie uruchomisz w ten sposób alarmów.",Lembre-se: mate com cautela ao invés de força. Assim você não ativará os alarmes.,,Ține minte: ucide subtil în loc de forță brută. Nu vei declanșa alarma.,"Запомни: убивай бесшумно, не лезь на рожон, и ты не поднимешь тревогу.",,Unutmayın: güç yerine gizlilikle öldürün. Alarmları çalıştırmazsın. +発電所に近い所だ。",이롤리는 프론트의 수리공이기도 해. 무기상점 근처에 그의 가게로 향하는 문이 있을 거야.,"Irale is de ""fixer"" van de Front. Hij zit achter de ongemarkeerde deur naast de wapenwinkel.","Irale er Frontens ""fikser"". Han er bak den umerkede døren ved siden av våpenbutikken.","Irale to ""załatwiacz"" Frontu. Jest za nieoznakowanymi drzwiami obok sklepu z bronią.","Irale é o ""quebra-galho"" da Frente. Ele está atrás da porta desmarcada próxima ao depósito de armas.",,"Irale e ""reparatorul"" Frontului. E în spatele ușii fără însemn lângă magazinul de arme.",Ирэйл — «наладчик» Сопротивления. Ты найдёшь его за дверью без вывески возле оружейного магазина.,,"Irale är frontens ""fixare"". Han finns bakom den omärkta dörren bredvid vapenbutiken.","İrale, Cephe'nin ""iş bitiricisi"". Silah dükkanının yanındaki işaretlenmemiş kapının arkasında." +Remember: kill with stealth instead of force. You won't set off the alarms.,TXT_SUB_LOG6,MAP02,,,Pamatuj: Zabíjej potichu. Nespustíš poplach.,Husk: Dræb med list i stedet for med magt. Du vil ikke udløse alarmen.,Denk daran: Töte lautlos und du wirst den Alarm nicht auslösen.,,,Recuerda: mata con sigilo y no con fuerza para no activar las alarmas.,,Muista: tapa huomaamattomasti voiman sijasta. Niin vältät hälytyksen.,"Souviens-toi: Tue avec discrétion, pas avec force, et tu n'activeras pas les alarmes.","Figyelj arra, hogy lopakodva ölj, ne erővel. Így nem indítod be a riasztót.",Ricorda: uccidi silenziosamente invece di usare la forza. Così facendo non attiverai gli allarmi.,覚えておいて:静かに殺す時はナイフか毒矢だ。警報を鳴らすと厄介なことになる。,기억해: 소음 없이 조용히 죽여. 그럼 경보를 울리지 않을 테니까.,Onthoud: dood met heimelijke in plaats van met geweld. Je laat de alarmen niet afgaan.,"Husk: drep i det skjulte, ikke med makt. Du vil ikke utløse alarmen.","Pamiętaj: zabijaj ukradkiem, a nie siłą. Nie uruchomisz w ten sposób alarmów.",Lembre-se: mate com cautela ao invés de força. Assim você não ativará os alarmes.,,Ține minte: ucide subtil în loc de forță brută. Nu vei declanșa alarma.,"Запомни: убивай бесшумно, не лезь на рожон, и ты не поднимешь тревогу.",,Kom ihåg: döda med smygande i stället för med våld. Du kommer inte att utlösa larmen.,Unutmayın: güç yerine gizlilikle öldürün. Alarmları çalıştırmazsın. "All I know about the governor is that he's playing both sides to the middle. Here's his so-called ""mansion.""",TXT_SUB_LOG7,MAP03: After joining the Front and going to Mourel's mansion.,,,"O guvernérovi vím jen to, že se snaží uhrávat sympatie obou stran. Tohle je jeho rádoby „sídlo“.","Alt jeg ved om guvernøren er, at han spiller begge sider til midten. Her er hans såkaldte ""palæ"".","Vom Gouverneur weiß ich nur, dass er beide Seiten gegeneinander ausspielt. Hier ist seine sogenannte „Villa.“",,,Todo lo que sé del gobernador es que juega entre ambos bandos. Aquí está su supesta «mansión».,,"Tiedän kuvernööristä vain sen, että hän pelaa keskellä molemmilla puolilla. Tässä on hänen niin sanottu ""kartanonsa"".","Tout ce que je sais au sujet du gouverneur est qu'il est un agent double de chaque côté. Voilà son soi-disant ""manoir"".","Csak annyit tudok a kormányzóról, hogy mindenkét oldalnak dolgozik. Itt az úgynevezett ""kúriája"".",Tutto ciò che so sul governatore è che cerca di mettere gli uni contro gli altri per beneficio personale. Ecco la sua cosidetta dimora.,"私が知事について知っていることは、町の中央で双方を遊ばせてる様だ。 -ソイツがここいらを'マンション'と呼んでいる。",내가 알기로는 모렐 총독은 두 세력을 가지고 노는 걸 좋아한대. 여기는 그의 '저택'이라는 곳이야.,"Het enige wat ik van de gouverneur weet is dat hij beide kanten van de gouverneur naar het midden speelt. Hier is zijn zogenaamde ""herenhuis"".","Alt jeg vet om guvernøren, er at han spiller på begge sider. Her er hans såkalte ""herskapshus"".","O gubernatorze wiem tylko tyle, że gra na dwie strony. Oto jego tak zwana ""rezydencja"".","Tudo o que eu sei sobre o governador é que ele está jogando entre dois lados. Aqui fica a sua suposta ""mansão"".",,"Tot ce știu despre Guvernator e că plătește ambele tabere. Aici e așa-zisul lui ""complex"".","Я знаю о губернаторе только то, что он пытается подыграть обеим сторонам, оставаясь посередине. Вот его так называемый «особняк».",,"Vali hakkında bildiğim tek şey, iki tarafı da ortada oynaması. İşte onun sözde ""malikanesi""." -Ugh. The dregs of humanity have certainly found a home.,TXT_SUB_LOG8,,,,Fuj. Spodina lidstva si rozhodně našla domov.,Ugh. Menneskehedens bundfald har bestemt fundet et hjem.,Ugh. Der Bodensatz der Menschheit hat definitiv ein Zuhause gefunden.,,,Ugh. La basura humana ciertamente ha encontrado un hogar.,,"Yöh, ihmiskunnan pohjasakka on selvästikin löytänyt kodin.","Eugh, les loques de l'humanité ont trouvé leur maison, on dirait.",Fúj. Az emberiség söpredéke csak talált magának egy otthont.,Ugh. La feccia dell'umanità ha certamente trovato una casa adatta.,,"으윽, 우리 중 나쁜 놈들만 보금자리를 구한 것 같네.",Ugh. De bezinksels van de mensheid hebben zeker een thuis gevonden.,Ugh. Menneskehetens bunnfall har virkelig funnet et hjem.,Ugh. Resztki ludzkości na pewno znalazły dom.,Urgh. A escória da humanidade certamente encontrou um lar.,,Ugh. Scursurile umanității și-au găsit o casă cu siguranță.,Фу. Самое место для отбросов человечества.,,Ugh. İnsanlığın tortuları kesinlikle bir yuva bulmuş. +ソイツがここいらを'マンション'と呼んでいる。",내가 알기로는 모렐 총독은 두 세력을 가지고 노는 걸 좋아한대. 여기는 그의 '저택'이라는 곳이야.,"Het enige wat ik van de gouverneur weet is dat hij beide kanten van de gouverneur naar het midden speelt. Hier is zijn zogenaamde ""herenhuis"".","Alt jeg vet om guvernøren, er at han spiller på begge sider. Her er hans såkalte ""herskapshus"".","O gubernatorze wiem tylko tyle, że gra na dwie strony. Oto jego tak zwana ""rezydencja"".","Tudo o que eu sei sobre o governador é que ele está jogando entre dois lados. Aqui fica a sua suposta ""mansão"".",,"Tot ce știu despre Guvernator e că plătește ambele tabere. Aici e așa-zisul lui ""complex"".","Я знаю о губернаторе только то, что он пытается подыграть обеим сторонам, оставаясь посередине. Вот его так называемый «особняк».",,"Allt jag vet om guvernören är att han spelar båda sidor till mitten. Här är hans så kallade ""herrgård"".","Vali hakkında bildiğim tek şey, iki tarafı da ortada oynaması. İşte onun sözde ""malikanesi""." +Ugh. The dregs of humanity have certainly found a home.,TXT_SUB_LOG8,,,,Fuj. Spodina lidstva si rozhodně našla domov.,Ugh. Menneskehedens bundfald har bestemt fundet et hjem.,Ugh. Der Bodensatz der Menschheit hat definitiv ein Zuhause gefunden.,,,Ugh. La basura humana ciertamente ha encontrado un hogar.,,"Yöh, ihmiskunnan pohjasakka on selvästikin löytänyt kodin.","Eugh, les loques de l'humanité ont trouvé leur maison, on dirait.",Fúj. Az emberiség söpredéke csak talált magának egy otthont.,Ugh. La feccia dell'umanità ha certamente trovato una casa adatta.,,"으윽, 우리 중 나쁜 놈들만 보금자리를 구한 것 같네.",Ugh. De bezinksels van de mensheid hebben zeker een thuis gevonden.,Ugh. Menneskehetens bunnfall har virkelig funnet et hjem.,Ugh. Resztki ludzkości na pewno znalazły dom.,Urgh. A escória da humanidade certamente encontrou um lar.,,Ugh. Scursurile umanității și-au găsit o casă cu siguranță.,Фу. Самое место для отбросов человечества.,,Usch. Mänsklighetens avskum har verkligen hittat ett hem.,Ugh. İnsanlığın tortuları kesinlikle bir yuva bulmuş. Calling Mourel sleazy is paying him a compliment. He's mongrel turd on a stick.,TXT_SUB_LOG9,"MAP02: After accepting ""bloody"" chore.",,,"Nazývat Mourela slizákem by mu lichotilo, svinský parchant jeden prohnilý.",At kalde Mourel sleazy er at give ham en kompliment. Han er en mongolsk lort på en pind.,"Mourel als 'verschlagen' zu bezeichnen wäre, ihm ein Kompliment zu machen. Er ist ein Haufen Hundescheiße.",,,Decirle «sucio» a Mourel es un halago. Es mierda de perro callejero en un palo.,,"Viheliäiseksi nimitteleminen olisi Mourelille vain kohteliaisuus. Hän on kapinen koira, iljettävä paskiainen.",Appeler Mourel un rat serait être gentil. Il est une sacrée brochette de merde.,Mourelt mocskosnak hívni egyfajta bók. Én egy alávaló pálcára húzott szarnak hívnám.,Chiamare Mourel squallido significa fargli un complimento. È uno stronzo bastardo su un palo.,"モーレルにとって汚職議員は誉め言葉だ。 -ソイツはクソを漏らした'駄犬'でしかないからな。",모렐에게 행실이 지저분하다고 말하는 건 칭찬에 불과해. 저놈은 이기적인 똥개새끼라고.,Mourel slordig noemen is een compliment voor hem. Hij is een bastaard op een stokje.,Å kalle Mourel snuskete er å gi ham en kompliment. Han er en kjøterbæsj på en pinne.,Nazwanie Mourela obskurnym to komplement. On jest kundlem na patyku.,Chamar o Mourel de picareta é elogio. Ele é um total desgraçado de merda.,,Numindu-l pe Mourel zgârcit e un compliment. E o corcitură de rahat pe băț.,"Назвать Моурела подлым, значит сделать ему комплимент. Кусок дерьма на палочке...",,Mourel'e adi demek ona iltifat etmektir. O bir sopa üzerindeki melez bok. +ソイツはクソを漏らした'駄犬'でしかないからな。",모렐에게 행실이 지저분하다고 말하는 건 칭찬에 불과해. 저놈은 이기적인 똥개새끼라고.,Mourel slordig noemen is een compliment voor hem. Hij is een bastaard op een stokje.,Å kalle Mourel snuskete er å gi ham en kompliment. Han er en kjøterbæsj på en pinne.,Nazwanie Mourela obskurnym to komplement. On jest kundlem na patyku.,Chamar o Mourel de picareta é elogio. Ele é um total desgraçado de merda.,,Numindu-l pe Mourel zgârcit e un compliment. E o corcitură de rahat pe băț.,"Назвать Моурела подлым, значит сделать ему комплимент. Кусок дерьма на палочке...",,Att kalla Mourel sliskig är en komplimang. Han är en mongolisk skit på en pinne.,Mourel'e adi demek ona iltifat etmektir. O bir sopa üzerindeki melez bok. We need to speak with someone who knows the old town and where this coupling is. Command says: find MacGuffin. ,TXT_SUB_LOG10,"MAP02: After accepting ""messy"" chore and leaving Mourel's room.",,,"Musíme si promluvit s někým, kdo zná staré město a ví, kde se tahle spojka nalézá. Vedení říká najít MacGuffina.","Vi må tale med nogen, der kender den gamle by og ved, hvor denne kobling er. Kommandoen siger: Find MacGuffin.","Wir müssen mit jemandem reden, der die alte Stadt kennt und weiß, wo diese Anzapfung it. Die Kommandozentrale sagt, finde MacGuffin.",,,Necesitamos hablar con alguien que conozca el viejo pueblo y donde se encuentra el acoplamiento. El Comando dice: encuentra a MacGuffin.,,"Meidän täytyy puhua jollekulle, joka tietää vanhan kaupungin ja missä tämä liitin on. Komentokeskus käskee etsiä MacGuffinia.",On doit parler à quelqu'un qui connaît la vieille ville et où se trouve le coupleur. Le commandement me dit qu'il faut trouver MacGuffin.,"Beszélnünk kell valakivel aki ismeri a régi várost, és tudja hol ez az elágazás. A központ szerint fel kell keresnünk MacGuffin-t.",Dobbiamo parlare con qualcuno che conosce la vecchia città e sa dove poter trovare questo aggeggio. Il comando dice: trovate MacGuffin.,"我々は何処にあるかについてはオールドタウンに知っている者がいる。 -指令が言うには マクガフィンに会え。",동력선의 위치를 알 수 있을 만한 토박이 주민과 이야기해봐. 본부가 말하길: 맥거핀을 찾으래.,We moeten met iemand spreken die de oude stad kent en waar deze koppeling is. Het commando zegt: zoek MacGuffin.,Vi må snakke med noen som kjenner gamlebyen og vet hvor koblingen er. Kommandoen sier: Finn MacGuffin.,"Musimy porozmawiać z kimś, kto zna stare miasto i wie, gdzie jest to sprzęgło. Rozkaz mówi: znaleźć MacGuffina.",Precisamos falar com alguém que conheça a velha cidade e onde fica essa conexão. O comando diz: encontre MacGuffin.,,Avem nevoie să vorbim cu cineva care cunoaște vechiul oraș și unde e cuplajul. Centrul de comandă zice: găsește-l pe MacGuffin.,"Нам нужен кто-то, кто знает старый город и может подсказать, где эта муфта. В штабе говорят, что тебе поможет Макгаффин.",,Eski şehri ve bu kuplajın nerede olduğunu bilen biriyle konuşmalıyız. Komuta diyor ki: MacGuffin'i bulun. +指令が言うには マクガフィンに会え。",동력선의 위치를 알 수 있을 만한 토박이 주민과 이야기해봐. 본부가 말하길: 맥거핀을 찾으래.,We moeten met iemand spreken die de oude stad kent en waar deze koppeling is. Het commando zegt: zoek MacGuffin.,Vi må snakke med noen som kjenner gamlebyen og vet hvor koblingen er. Kommandoen sier: Finn MacGuffin.,"Musimy porozmawiać z kimś, kto zna stare miasto i wie, gdzie jest to sprzęgło. Rozkaz mówi: znaleźć MacGuffina.",Precisamos falar com alguém que conheça a velha cidade e onde fica essa conexão. O comando diz: encontre MacGuffin.,,Avem nevoie să vorbim cu cineva care cunoaște vechiul oraș și unde e cuplajul. Centrul de comandă zice: găsește-l pe MacGuffin.,"Нам нужен кто-то, кто знает старый город и может подсказать, где эта муфта. В штабе говорят, что тебе поможет Макгаффин.",,Vi måste tala med någon som känner till den gamla staden och vet var den här kopplingen finns. Kommandot säger: hitta MacGuffin.,Eski şehri ve bu kuplajın nerede olduğunu bilen biriyle konuşmalıyız. Komuta diyor ki: MacGuffin'i bulun. "He's in what's politely called the ""bum hole"". Take the walkway by the sewage plant and head down the stairs.",TXT_SUB_LOG11,"MAP02: After accepting ""messy"" chore and leaving Mourel's mansion.",,,"Najdeš ho na místě, kterému zdvořile říkají „zadnice“. Jdi přes chodník u čističky a sejdi schody.","Han er i det, der høfligt kaldes ""bumshullet"". Tag gangen ved kloakanlægget og gå ned ad trappen.","Er ist, was höflich gesagt, das „Pennerloch“ genannt wird. Gehe zum Weg zur Kläranlage und von dort die Treppe herunter.",,,Está en lo que se conoce educadamente como «la cueva del vagabundo». Toma la pasarela junto a la planta de aguas residuales y baja por las escaleras.,,"Hän majailee kiltisti sanottuna ""pepunreiässä"". Kulje jätelaitoksen viereistä kulkukäytävää pitkin ja portaat alas.","Il se trouve dans ce qu'on appelle poliment le ""trou à rats"", suis la coursive près de la centrale de traitement des égouts et descend les escaliers.","Ott van az udvariasan csak ""kotoréknak"" nevezett helyen. Gyalogolj végig a szennyvíz tisztító hídján, majd le a lépcsőkön.","Si trova in quello che viene affeziosamente chiamato ""il buco dei barboni"". Prendi la passerella dell'impianto fognario e vai sotto le scale.","彼は行儀よく'バムホール'と呼ばれる場所に居る。 -下水処理場の側の階段を下りた小さい部屋だ。",겸손하게 말하자면 그는 “노숙자 굴”에 살아. 하수도에서 보도를 지나간 뒤 계단을 건너.,"Hij zit in wat beleefd het ""kontje"" wordt genoemd. Neem de loopbrug bij de rioolwaterzuiveringsinstallatie en ga de trap af.","Han er i det som høflig kalles ""rumpehullet"". Ta gangveien ved kloakkanlegget og gå ned trappene.","Jest w miejscu, które grzecznie nazywa się ""bum hole"". Skorzystaj z przejścia przy oczyszczalni ścieków i skieruj się w dół po schodach.","Ele está num lugar chamado ""toca de rato"". Vá pela passarela perto da usina de tratamento e desça as escadas.",,"E în ceea ce se cheamă politicos ""groapa de ardere"". Ia pasarela de lângă fabrica de deșeuri și coboară scările.","Он в том месте, что вежливо называют «бомжевая нора». Пройди к очистным сооружениям и спустись по лестнице.",,"Kibarca ""serseri deliği"" denilen yerde. Lağım tesisinin yanındaki geçidi kullanın ve merdivenlerden aşağı inin." -Take your time with this mission. I can't get intel on this from Command.,TXT_SUB_LOG12,"MAP02: During ""messy"" chore.",,,Dej si s touhle misí na čas. Nemůžu z velení dostat žádné informace.,Tag dig god tid med denne mission. Jeg kan ikke få oplysninger om dette fra Command.,Nimm dir Zeit für diese Mission. Ich erhalte keine Informationen aus der Kommandozentrale.,,,Tómate tu tiempo en esta misión. No consigo información de esto con el Comando.,,Ei mitään kiirettä tämän tehtävän kanssa; komentokeskuksella ei ole antaa tiedustelutietoja.,"Prends ton temps, le commandement n'a rien à me donner au niveau informations.",Ne siesd el a küldetést. Nem tudtam kideríteni semmi érdemlegeset az Irányítástól.,Prenditi il tempo che ti serve per questa missione. Non mi stanno dando molte informazioni dal comando.,この任務は時間が掛かりそうだ。私は司令部からこれ以上の情報は得る事は出来ない。,느긋하게 수행해도 좋아. 본부에도 이 정보를 모으는 데 문제가 있데.,Neem je tijd met deze missie. Ik kan hier geen informatie over krijgen van de Commandant.,Ta deg god tid med dette oppdraget. Jeg kan ikke få informasjon om dette fra kommandoen.,Nie spiesz się z tą misją. Nie mogę uzyskać informacji na ten temat od dowództwa.,Não tenha pressa nesta missão. Não estou conseguindo obter inteligência sobre isso pelo Comando.,,Poți să petreci mai mult timp cu misiunea. Nu pot găsi mai multe informații de la Centru.,Не торопись с выполнением этого задания. Я не могу получить разведданные от штаба.,,Bu görevde acele etmeyin. Komuta'dan bu konuda bilgi alamıyorum. +下水処理場の側の階段を下りた小さい部屋だ。",겸손하게 말하자면 그는 “노숙자 굴”에 살아. 하수도에서 보도를 지나간 뒤 계단을 건너.,"Hij zit in wat beleefd het ""kontje"" wordt genoemd. Neem de loopbrug bij de rioolwaterzuiveringsinstallatie en ga de trap af.","Han er i det som høflig kalles ""rumpehullet"". Ta gangveien ved kloakkanlegget og gå ned trappene.","Jest w miejscu, które grzecznie nazywa się ""bum hole"". Skorzystaj z przejścia przy oczyszczalni ścieków i skieruj się w dół po schodach.","Ele está num lugar chamado ""toca de rato"". Vá pela passarela perto da usina de tratamento e desça as escadas.",,"E în ceea ce se cheamă politicos ""groapa de ardere"". Ia pasarela de lângă fabrica de deșeuri și coboară scările.","Он в том месте, что вежливо называют «бомжевая нора». Пройди к очистным сооружениям и спустись по лестнице.",,"Han är i det som artigt kallas ""bum-hålet"". Ta gången vid avloppsanläggningen och gå ner för trapporna.","Kibarca ""serseri deliği"" denilen yerde. Lağım tesisinin yanındaki geçidi kullanın ve merdivenlerden aşağı inin." +Take your time with this mission. I can't get intel on this from Command.,TXT_SUB_LOG12,"MAP02: During ""messy"" chore.",,,Dej si s touhle misí na čas. Nemůžu z velení dostat žádné informace.,Tag dig god tid med denne mission. Jeg kan ikke få oplysninger om dette fra Command.,Nimm dir Zeit für diese Mission. Ich erhalte keine Informationen aus der Kommandozentrale.,,,Tómate tu tiempo en esta misión. No consigo información de esto con el Comando.,,Ei mitään kiirettä tämän tehtävän kanssa; komentokeskuksella ei ole antaa tiedustelutietoja.,"Prends ton temps, le commandement n'a rien à me donner au niveau informations.",Ne siesd el a küldetést. Nem tudtam kideríteni semmi érdemlegeset az Irányítástól.,Prenditi il tempo che ti serve per questa missione. Non mi stanno dando molte informazioni dal comando.,この任務は時間が掛かりそうだ。私は司令部からこれ以上の情報は得る事は出来ない。,느긋하게 수행해도 좋아. 본부에도 이 정보를 모으는 데 문제가 있데.,Neem je tijd met deze missie. Ik kan hier geen informatie over krijgen van de Commandant.,Ta deg god tid med dette oppdraget. Jeg kan ikke få informasjon om dette fra kommandoen.,Nie spiesz się z tą misją. Nie mogę uzyskać informacji na ten temat od dowództwa.,Não tenha pressa nesta missão. Não estou conseguindo obter inteligência sobre isso pelo Comando.,,Poți să petreci mai mult timp cu misiunea. Nu pot găsi mai multe informații de la Centru.,Не торопись с выполнением этого задания. Я не могу получить разведданные от штаба.,,Ta god tid på dig med det här uppdraget. Jag kan inte få information om detta från kommandot.,Bu görevde acele etmeyin. Komuta'dan bu konuda bilgi alamıyorum. "You idiot! You've shut off the power to the jamming circuits we use to conceal our base from the Order. Head over to the town hall and take out the scanning crew, now!",TXT_SUB_LOG13,MAP02: After destroying Front's power coupling.,,,"Ty debile! Odstřihnul jsi přívod proudu do rušiček, které používáme, abychom ukryli naší základnu před Řádem. Okamžitě si to zamiř k radnici a vybij průzkumnou četu!","Din idiot! Du har slukket for strømmen til de jamming-kredsløb, vi bruger til at skjule vores base for Ordenen. Gå over til rådhuset og udryd scanningsholdet, nu!","Du Idiot! Du hast die Energie für unsere Störsender unterbrochen, mit denen wir unsere Basis vor dem Orden verborgen haben. Geh schnell zum Rathaus und schalte den Suchtrupp aus. ",,,"¡Idiota! Has apagado la energía de los circuitos de interferencia que usamos para ocultarle nuestra base a La Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ya!","¡Idiota! Apagaste la energía de los circuitos de interferencia que usamos para ocultarle nuestra base a La Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ya!","Sinä idiootti! Olet katkaissut virran häirintäpiireihin, joilla piilotamme sijaintimme Veljeskunnalta. Suuntaa kaupungintalolle ja hoitele tiedusteluryhmä, heti paikalla!",Idiot! Tu as désactivé les circuits brouilleurs qui cachaient notre base des senseurs de l'Ordre. Retourne vite à la mairie et tue l'équipe de scan maintenant!,"Te idióta! Lelőtted az áramot a zavaró áramkörökhöz, amivel a Rend elől rejtettük el a bázist. Menj a városházára, és iktasd ki a szkennelő legénységet azonnal!","Idiota! Hai interrotto il flusso di energia dei circuiti che usavamo per nascondere la nostra base dall'Ordine. Ritorna subito al municipio e fai fuori il gruppo venuto a perlustare la zona, ora!","馬鹿者!お前はオーダーから我々の基地を隠す妨害回路を壊してしまった! -市庁舎に調査隊が向かった、今すぐ片付けろ!",이 멍청이야! 우리 기지를 오더로부터 은폐시켜주는 교란 장치의 동력을 끊어버렸잖아. 당장 시청으로 가서 탐색반들을 쓸어버려! 그다음에 총독에게 부서진 장치를 전해. 당장!,"Idioot! Je hebt de stroom naar de stoorcircuits die we gebruiken om onze basis te verbergen voor de Orde uitgeschakeld. Ga naar het stadhuis en haal de scannende bemanning eruit, nu!","Din idiot! Du har slått av strømmen til blokkeringskretsene vi bruker for å skjule basen vår for Ordenen. Dra til rådhuset og drep skannerne, nå!","Ty idioto! Wyłączyłeś zasilanie obwodów zagłuszających, których używamy do ukrycia naszej bazy przed Zakonem. Idź do ratusza i zdejmij ekipę skanującą, natychmiast!",Seu idiota! Você desligou a energia para os circuitos de interferência que usamos para esconder a nossa base dos sensores da Ordem. Vá até a prefeitura e tire a equipe de busca de lá imediatamente!,,"Idiotule! Ai oprit energia către circuitele noastre care ne permiteau să ne ascundem de Ordin. Du-te în hala vechiului oraș și elimină echipajul, acum!","Идиот! Ты обесточил генератор радиопомех, с помощью которого мы скрывали местоположение нашей базы от Ордена. Возвращайся к ратуше и уничтожь разведывательную группу как можно скорее!",,"Seni salak! Üssümüzü Düzen'den gizlemek için kullandığımız sinyal bozucu devrelerin gücünü kesmişsin. Belediye binasına git ve tarama ekibini indir, hemen!" -"OK, ""Trust no one"" is the name of the game! Let's get that pass from the Governor and free those prisoners.",TXT_SUB_LOG14,MAP02: After destroying Front's power coupling and killing all blue acolytes in the town hall.,,,"Dobře, „Nevěř nikomu“ je motto hry! Pojďme od guvernéra dostat tu propustku a osvoboďme ty vězně.","Okay, ""Stol ikke på nogen"" er det, der gælder! Lad os få den tilladelse fra guvernøren og befri de fanger.","Ok, „Trau keinem“ heißt dieses Spiel. Lass uns den Gefängnispass vom Gouverneur holen und die Gefangenen befreien.",,,"Vale, ¡«No te fies de nadie» se llama el juego! Ya es hora de conseguir ese pase del Gobernador y liberar a esos prisioneros.","Bueno, ¡«No confíes en nadie» se llama el juego! Ya es hora de conseguir ese pase del Gobernador y liberar a esos prisioneros.","Selvä, ""Älä luota kehenkään"" on näköjään pelin nimi! Hankitaan pääsylupa kuvernööriltä ja vapautetaan ne vangit.","Ok, ""ne fais confiance à personne"" est le thème du jour. Récupérons le passe du gouverneur et libérons les prisonniers.","Rendben, a ""ne bízz senkiben"" elv szerint játszunk. Akkor vegyük el a kormányzótól a belépőt, és szabadítsuk ki a rabokat.","OK, ""Non fidarti di nessuno"" è il gioco che stiamo giocando qua! Prendiamo quel pass per la prigione dal governatore.",よし、'信用しない'のが最も重要なことだ!壊れた配電機を渡して囚人を解放するんだ。,"좋아, '아무도 믿지 말라'가 이 게임의 이름이겠군! 그냥 총독과 대화하고 수감자들을 구출하자.","OK, ""Vertrouw niemand"" is de naam van het spel! Laten we die pas van de gouverneur halen en die gevangenen vrijlaten.","OK, ""Stol ikke på noen"" er navnet på spillet! La oss få det passet fra guvernøren og befri fangene.","OK, ""Nie ufaj nikomu"" to nazwa gry! Zdobądźmy tę przepustkę od gubernatora i uwolnijmy tych więźniów.","Ok, ""não confie em ninguém"" é o nome do jogo! Vamos pegar aquele passe do Governador e libertar esses prisioneiros.",,"OK, ""N-ai încredere în nimeni"" e numele jocului. Să luăm acea parolă de la guvernator și să eliberăm prizonierii.","Что ж, эта игра называется «не верь никому»! Давай получим у губернатора пропуск в тюрьму и освободим пленников.",,"Tamam, ""Kimseye güvenme"" oyunun adı! Vali'den o izni alalım ve mahkumları serbest bırakalım." +市庁舎に調査隊が向かった、今すぐ片付けろ!",이 멍청이야! 우리 기지를 오더로부터 은폐시켜주는 교란 장치의 동력을 끊어버렸잖아. 당장 시청으로 가서 탐색반들을 쓸어버려! 그다음에 총독에게 부서진 장치를 전해. 당장!,"Idioot! Je hebt de stroom naar de stoorcircuits die we gebruiken om onze basis te verbergen voor de Orde uitgeschakeld. Ga naar het stadhuis en haal de scannende bemanning eruit, nu!","Din idiot! Du har slått av strømmen til blokkeringskretsene vi bruker for å skjule basen vår for Ordenen. Dra til rådhuset og drep skannerne, nå!","Ty idioto! Wyłączyłeś zasilanie obwodów zagłuszających, których używamy do ukrycia naszej bazy przed Zakonem. Idź do ratusza i zdejmij ekipę skanującą, natychmiast!",Seu idiota! Você desligou a energia para os circuitos de interferência que usamos para esconder a nossa base dos sensores da Ordem. Vá até a prefeitura e tire a equipe de busca de lá imediatamente!,,"Idiotule! Ai oprit energia către circuitele noastre care ne permiteau să ne ascundem de Ordin. Du-te în hala vechiului oraș și elimină echipajul, acum!","Идиот! Ты обесточил генератор радиопомех, с помощью которого мы скрывали местоположение нашей базы от Ордена. Возвращайся к ратуше и уничтожь разведывательную группу как можно скорее!",,"Din idiot! Du har stängt av strömmen till störningskretsarna som vi använder för att dölja vår bas för Orden. Gå över till stadshuset och ta ut skanningspersonalen, nu!","Seni salak! Üssümüzü Düzen'den gizlemek için kullandığımız sinyal bozucu devrelerin gücünü kesmişsin. Belediye binasına git ve tarama ekibini indir, hemen!" +"OK, ""Trust no one"" is the name of the game! Let's get that pass from the Governor and free those prisoners.",TXT_SUB_LOG14,MAP02: After destroying Front's power coupling and killing all blue acolytes in the town hall.,,,"Dobře, „Nevěř nikomu“ je motto hry! Pojďme od guvernéra dostat tu propustku a osvoboďme ty vězně.","Okay, ""Stol ikke på nogen"" er det, der gælder! Lad os få den tilladelse fra guvernøren og befri de fanger.","Ok, „Trau keinem“ heißt dieses Spiel. Lass uns den Gefängnispass vom Gouverneur holen und die Gefangenen befreien.",,,"Vale, ¡«No te fies de nadie» se llama el juego! Ya es hora de conseguir ese pase del Gobernador y liberar a esos prisioneros.","Bueno, ¡«No confíes en nadie» se llama el juego! Ya es hora de conseguir ese pase del Gobernador y liberar a esos prisioneros.","Selvä, ""Älä luota kehenkään"" on näköjään pelin nimi! Hankitaan pääsylupa kuvernööriltä ja vapautetaan ne vangit.","Ok, ""ne fais confiance à personne"" est le thème du jour. Récupérons le passe du gouverneur et libérons les prisonniers.","Rendben, a ""ne bízz senkiben"" elv szerint játszunk. Akkor vegyük el a kormányzótól a belépőt, és szabadítsuk ki a rabokat.","OK, ""Non fidarti di nessuno"" è il gioco che stiamo giocando qua! Prendiamo quel pass per la prigione dal governatore.",よし、'信用しない'のが最も重要なことだ!壊れた配電機を渡して囚人を解放するんだ。,"좋아, '아무도 믿지 말라'가 이 게임의 이름이겠군! 그냥 총독과 대화하고 수감자들을 구출하자.","OK, ""Vertrouw niemand"" is de naam van het spel! Laten we die pas van de gouverneur halen en die gevangenen vrijlaten.","OK, ""Stol ikke på noen"" er navnet på spillet! La oss få det passet fra guvernøren og befri fangene.","OK, ""Nie ufaj nikomu"" to nazwa gry! Zdobądźmy tę przepustkę od gubernatora i uwolnijmy tych więźniów.","Ok, ""não confie em ninguém"" é o nome do jogo! Vamos pegar aquele passe do Governador e libertar esses prisioneiros.",,"OK, ""N-ai încredere în nimeni"" e numele jocului. Să luăm acea parolă de la guvernator și să eliberăm prizonierii.","Что ж, эта игра называется «не верь никому»! Давай получим у губернатора пропуск в тюрьму и освободим пленников.",,"Okej, ""Lita inte på någon"" är vad som gäller! Låt oss få det där passet från guvernören och befria fångarna.","Tamam, ""Kimseye güvenme"" oyunun adı! Vali'den o izni alalım ve mahkumları serbest bırakalım." Good move! The Governor is a lousy liar. That's our power coupling. Now let's get that pass.,TXT_SUB_LOG15,MAP02: After finding the broken power coupling.,,,"Dobrý tah! Guvernér je mizerný lhář, tohle je naše spojka. Tak si pojďme pro tu propustku.",Godt gået! Guvernøren er en elendig løgner. Det er vores kraftkobling. Lad os nu få fat i det pas.,Das war klasse! Der Gouverneur ist ein lausiger Lügner. Das war unsere Anzapfung. Nun lass uns den Pass holen.,,,¡Buen ojo! El gobernador es un mentiroso: ese era nuestro acoplador de energía. Ahora consigamos ese pase.,,Hyvä veto! Kuvernööri on surkea valehtelija. Se on meidän virtaliittimemme. Nyt sitten hankitaan se pääsylupa.,Bien joué! Le gouverneur est un menteur. Voilà notre coupleur. Allons récupérer le passe.,Jól tetted! A Kormányzó egy hazug disznó. Az a mi áramcsatolónk. Most pedig irány a belépő.,Ottima mossa! Il governatore è un bugiardo. Eravamo noi a utilizzare questo marchingegno collegato alla rete. Ora andiamo a prendere quel pass.,"良い判断よ!知事は粗末な嘘を付いている。 あれはオーダーから基地を隠す為に使用している我々の配電機だ。 -この壊れた配電機を渡して彼を騙し返そう。",참 잘했어! 총독이 거짓말을 했군. 이건 우리의 동력 장치야. 어서 전해주자!,Goede zet! De Gouverneur is een slechte leugenaar. Dat is onze krachtkoppeling. Laten we nu die pas pakken.,Godt trekk! Guvernøren er en elendig løgner. Det er kraftkoblingen vår. La oss få tak i passet.,Dobry ruch! Gubernator to kiepski kłamca. To nasze połączenie sił. Teraz zdobądźmy tę przepustkę.,"Boa! O Governador é um mentiroso desgraçado. Esse é a nossa conexão. Agora, vamos pegar aquele passe.",,Bună mutare! Gvuvernatorul e un mincinos prost. Acela e cuplajul nostru. Acum să luăm parola.,Отличный ход! Губернатор — мерзкий лжец. Это наше подключение к силовой линии. Теперь получи пропуск.,,İyi hamle! Vali berbat bir yalancı. Bu bizim güç birleşimimiz. Şimdi şu izni alalım. -The warehouse is in the power station. Let's make this short and sweet.,TXT_SUB_LOG16,"MAP02: After accepting ""bloody"" chore.",,,"Skladiště je uvnitř elektrárny. Pojďme na to, ať to máme rychle za sebou.",Lageret er i kraftværket. Lad os gøre det kort og godt.,Das Lagerhaus ist im Kraftwerk. Lass uns das schnell erledigen.,,,El almacén está en la central eléctrica. Hagamos esto bien rápido.,,Varasto on voimalaitoksella. Hoidetaan tämä nätisti ja pikaisesti.,L'entrepôt se trouve dans la centrale électrique. On va faire ça rapidement et proprement.,A raktár egy erőmű. Oldjuk meg gyorsan és hatékonyan.,Il magazzino si trova nella centrale energetica. Cerchiamo di essere rapidi e puliti.,倉庫は発電所にある。さっさと済ませよう。,창고는 발전소 근처에 있어. 어서 신속하고 죽여주게 끝내자.,Het magazijn is in de energiecentrale. Laten we dit kort en bondig houden.,Lageret er i kraftstasjonen. La oss gjøre det kort og godt.,Magazyn jest w elektrowni. Niech to będzie krótkie i słodkie.,O depósito fica na usina de energia. Vamos fazer isso bem rápido.,,Depozitul e în stația de energie. Scurt și dulce.,Речь идёт о складе в электростанции. Давай сделаем это быстро и с огоньком.,,Depo elektrik santralinde. Bunu kısa ve tatlı tutalım. -I never thought I'd break into prison...,TXT_SUB_LOG17,MAP02: About to enter Norwall Prison.,,,"Nikdy by mě nenapadlo, že se budu vkrádat do vězení...","Jeg troede aldrig, at jeg skulle bryde ind i et fængsel...","Ich hätte nie gedacht, in ein Gefängnis einzubrechen...",,"Mi neniam pensis, ke mi invadus malliberejon...",Nunca imaginé que irrumpiría en una prisión...,,En olisi ikinä uskonut murtautuvani vankilaan...,J'aurais jamais cru entrer de force dans une prison..,"Sosem gondoltam volna, hogy betörök egy börtönbe...",Non avrei mai pensato di entrare in prigione...,刑務所にお勤めになるなぞ考えた事もないぞ...,"감옥을 뚫고 들어가다니, 생각도 못 했는데?",Ik had nooit gedacht dat ik zou inbreken in de gevangenis....,Jeg trodde aldri jeg skulle bryte meg inn i et fengsel...,"Nigdy nie sądziłem, że włamię się do więzienia...",Nunca achei que eu invadiria uma prisão...,,N-am crezut că o să intru într-o închisoare...,"Никогда не думала, что приду в тюрьму добровольно...",,Hapishaneye gireceğimi hiç düşünmemiştim. -Guess there's no free lunch. Time to lock and load.,TXT_SUB_LOG18,MAP05: After crossing the alarm green door.,,,Holt nic není zadarmo. Nabij zbraň a jdi do toho.,Der er vist ingen gratis frokost. Tid til at låse og læsse.,Es gibt wohl keine freie Mahlzeit. Ran an die Action.,,,Supongo que no hay comida gratis. Hora de la acción.,,Ilmaista lounasta ei kai olekaan. Aika laittaa kovat piippuun.,"On dirait qu'il n'y a pas de repas gratuit, il est temps de se préparer au combat.",Úgy néz ki nincs ingyen ebéd. Akkor idő felfegyverkezni.,Immagino non ci sia del pranzo gratuito. È ora di dargli una lezione.,まあタダでは済まないか。派手に暴れてやれ。,급식 먹을 시간은 없겠네. 요리할 시간이야.,Ik denk dat er geen gratis lunch is. Tijd om te sluiten en te laden.,Man får visst ikke noe gratis. På tide å låse og laste.,Chyba nie ma darmowego lunchu. Czas zamknąć i załadować.,Parece que não existe almoço grátis. É hora da ação.,,Presupun că nu e niciun prânz gratuit. Timpul să ne pregătim.,"Что ж, бесплатный сыр бывает только в мышеловке. Оружие к бою! ",,Sanırım bedava öğle yemeği yok. Kilitleme ve yükleme zamanı. -"OK. You've pleased the Governor, splattered the Warden... Now it looks like we got to have to do a little surgery.",TXT_SUB_LOG19,MAP05: After getting to Main Control.,,,"Dobrá. Uspokojil jsi guvernéra, rozmetal dozorčího... Vypadá to, že teď budeme muset provést menší operaci.","OKAY. Du har tilfredsstillet guvernøren, plettet fængselsinspektøren... Nu ser det ud til, at vi må foretage en lille operation.","Ok, du hast den Gouverneur zufriedengestellt, den Direktor abgemetzelt... Und jetzt sieht es aus als ob eine kleine Operation nötig ist.",,,"Bueno, has satisfecho al Gobernador, despedazado al Carcelero... Y ahora parece que tendremos que hacer algo de cirugía.",,"No niin, olet tehnyt kuvernöörille mieliksi: suolannut vankilanjohtajan... Mutta näyttää siltä, että meidän täytyy harrastaa vähän kirurgiaa.","OK. Le gouverneur est satisfait, le gardien est en bouillie... Maintenant il va falloir faire un peu de chirurgie.","Ok. Elégedetté tetted a Kormányzót, kiloccsantottad az Igazgató fejét...Úgy tűnik ideje végezni egy kis műtétet.","OK. Hai reso il governatore contento, hai fatto a pezzi il direttore... Adesso sembra che ci toccherà fare un pò di chirurgia.","よし、知事は喜ばせ刑務所長はぶちのめした... -私達が少々手術を施す必要が出来たわ。","좋아, 총독과 놀았고, 간수장도 죽었으니... 이제 관련 인간을 손 좀 봐 줘야겠네!","Oké. Je hebt de gouverneur tevreden gesteld, de directeur verpletterd... Nu lijkt het erop dat we een kleine operatie moeten doen.","GREIT. Du har tilfredsstilt guvernøren, skjemt ut direktøren... Nå ser det ut til at vi må gjøre en liten operasjon.","W PORZĄDKU. Zadowoliłeś gubernatora, sponiewierałeś naczelnika... Teraz wygląda na to, że będziemy musieli przeprowadzić małą operację.","Ok, você agradou o Governador, estourou os miolos do carcereiro... Agora parece que temos que fazer uma pequena cirurgia.",,"OK. L-ai mulțumit pe Guvernator, împrăștiat pe Director... acum se pare că trebuie să faci niște chirurgie.","Хорошо. Ты доставил удовольствие губернатору, забрызгал стены мозгами тюремщика... Теперь нам предстоит небольшое хирургическое вмешательство.",,"TAMAMDIR. Vali'yi memnun ettiniz, Müdür'ün canına okudunuz. Şimdi küçük bir ameliyat yapmamız gerekecek gibi görünüyor." +この壊れた配電機を渡して彼を騙し返そう。",참 잘했어! 총독이 거짓말을 했군. 이건 우리의 동력 장치야. 어서 전해주자!,Goede zet! De Gouverneur is een slechte leugenaar. Dat is onze krachtkoppeling. Laten we nu die pas pakken.,Godt trekk! Guvernøren er en elendig løgner. Det er kraftkoblingen vår. La oss få tak i passet.,Dobry ruch! Gubernator to kiepski kłamca. To nasze połączenie sił. Teraz zdobądźmy tę przepustkę.,"Boa! O Governador é um mentiroso desgraçado. Esse é a nossa conexão. Agora, vamos pegar aquele passe.",,Bună mutare! Gvuvernatorul e un mincinos prost. Acela e cuplajul nostru. Acum să luăm parola.,Отличный ход! Губернатор — мерзкий лжец. Это наше подключение к силовой линии. Теперь получи пропуск.,,Bra gjort! Guvernören är en usel lögnare. Det är vår maktkoppling. Nu ska vi få det där passet.,İyi hamle! Vali berbat bir yalancı. Bu bizim güç birleşimimiz. Şimdi şu izni alalım. +The warehouse is in the power station. Let's make this short and sweet.,TXT_SUB_LOG16,"MAP02: After accepting ""bloody"" chore.",,,"Skladiště je uvnitř elektrárny. Pojďme na to, ať to máme rychle za sebou.",Lageret er i kraftværket. Lad os gøre det kort og godt.,Das Lagerhaus ist im Kraftwerk. Lass uns das schnell erledigen.,,,El almacén está en la central eléctrica. Hagamos esto bien rápido.,,Varasto on voimalaitoksella. Hoidetaan tämä nätisti ja pikaisesti.,L'entrepôt se trouve dans la centrale électrique. On va faire ça rapidement et proprement.,A raktár egy erőmű. Oldjuk meg gyorsan és hatékonyan.,Il magazzino si trova nella centrale energetica. Cerchiamo di essere rapidi e puliti.,倉庫は発電所にある。さっさと済ませよう。,창고는 발전소 근처에 있어. 어서 신속하고 죽여주게 끝내자.,Het magazijn is in de energiecentrale. Laten we dit kort en bondig houden.,Lageret er i kraftstasjonen. La oss gjøre det kort og godt.,Magazyn jest w elektrowni. Niech to będzie krótkie i słodkie.,O depósito fica na usina de energia. Vamos fazer isso bem rápido.,,Depozitul e în stația de energie. Scurt și dulce.,Речь идёт о складе в электростанции. Давай сделаем это быстро и с огоньком.,,Magasinet finns i kraftstationen. Låt oss göra det här kort och gott.,Depo elektrik santralinde. Bunu kısa ve tatlı tutalım. +I never thought I'd break into prison...,TXT_SUB_LOG17,MAP02: About to enter Norwall Prison.,,,"Nikdy by mě nenapadlo, že se budu vkrádat do vězení...","Jeg troede aldrig, at jeg skulle bryde ind i et fængsel...","Ich hätte nie gedacht, in ein Gefängnis einzubrechen...",,"Mi neniam pensis, ke mi invadus malliberejon...",Nunca imaginé que irrumpiría en una prisión...,,En olisi ikinä uskonut murtautuvani vankilaan...,J'aurais jamais cru entrer de force dans une prison..,"Sosem gondoltam volna, hogy betörök egy börtönbe...",Non avrei mai pensato di entrare in prigione...,刑務所にお勤めになるなぞ考えた事もないぞ...,"감옥을 뚫고 들어가다니, 생각도 못 했는데?",Ik had nooit gedacht dat ik zou inbreken in de gevangenis....,Jeg trodde aldri jeg skulle bryte meg inn i et fengsel...,"Nigdy nie sądziłem, że włamię się do więzienia...",Nunca achei que eu invadiria uma prisão...,,N-am crezut că o să intru într-o închisoare...,"Никогда не думала, что приду в тюрьму добровольно...",,Jag trodde aldrig att jag skulle bryta mig in i ett fängelse...,Hapishaneye gireceğimi hiç düşünmemiştim. +Guess there's no free lunch. Time to lock and load.,TXT_SUB_LOG18,MAP05: After crossing the alarm green door.,,,Holt nic není zadarmo. Nabij zbraň a jdi do toho.,Der er vist ingen gratis frokost. Tid til at låse og læsse.,Es gibt wohl keine freie Mahlzeit. Ran an die Action.,,,Supongo que no hay comida gratis. Hora de la acción.,,Ilmaista lounasta ei kai olekaan. Aika laittaa kovat piippuun.,"On dirait qu'il n'y a pas de repas gratuit, il est temps de se préparer au combat.",Úgy néz ki nincs ingyen ebéd. Akkor idő felfegyverkezni.,Immagino non ci sia del pranzo gratuito. È ora di dargli una lezione.,まあタダでは済まないか。派手に暴れてやれ。,급식 먹을 시간은 없겠네. 요리할 시간이야.,Ik denk dat er geen gratis lunch is. Tijd om te sluiten en te laden.,Man får visst ikke noe gratis. På tide å låse og laste.,Chyba nie ma darmowego lunchu. Czas zamknąć i załadować.,Parece que não existe almoço grátis. É hora da ação.,,Presupun că nu e niciun prânz gratuit. Timpul să ne pregătim.,"Что ж, бесплатный сыр бывает только в мышеловке. Оружие к бою! ",,Det finns ingen gratis lunch. Dags att låsa och ladda.,Sanırım bedava öğle yemeği yok. Kilitleme ve yükleme zamanı. +"OK. You've pleased the Governor, splattered the Warden... Now it looks like we got to have to do a little surgery.",TXT_SUB_LOG19,MAP05: After getting to Main Control.,,,"Dobrá. Uspokojil jsi guvernéra, rozmetal dozorčího... Vypadá to, že teď budeme muset provést menší operaci.","OKAY. Du har tilfredsstillet guvernøren, plettet fængselsinspektøren... Nu ser det ud til, at vi må foretage en lille operation.","Ok, du hast den Gouverneur zufriedengestellt, den Direktor abgemetzelt... Und jetzt sieht es aus als ob eine kleine Operation nötig ist.",,,"Bueno, has satisfecho al Gobernador, despedazado al Carcelero... Y ahora parece que tendremos que hacer algo de cirugía.",,"No niin, olet tehnyt kuvernöörille mieliksi: suolannut vankilanjohtajan... Mutta näyttää siltä, että meidän täytyy harrastaa vähän kirurgiaa.","OK. Le gouverneur est satisfait, le gardien est en bouillie... Maintenant il va falloir faire un peu de chirurgie.","Ok. Elégedetté tetted a Kormányzót, kiloccsantottad az Igazgató fejét...Úgy tűnik ideje végezni egy kis műtétet.","OK. Hai reso il governatore contento, hai fatto a pezzi il direttore... Adesso sembra che ci toccherà fare un po' di chirurgia.","よし、知事は喜ばせ刑務所長はぶちのめした... +私達が少々手術を施す必要が出来たわ。","좋아, 총독과 놀았고, 간수장도 죽었으니... 이제 관련 인간을 손 좀 봐 줘야겠네!","Oké. Je hebt de gouverneur tevreden gesteld, de directeur verpletterd... Nu lijkt het erop dat we een kleine operatie moeten doen.","GREIT. Du har tilfredsstilt guvernøren, skjemt ut direktøren... Nå ser det ut til at vi må gjøre en liten operasjon.","W PORZĄDKU. Zadowoliłeś gubernatora, sponiewierałeś naczelnika... Teraz wygląda na to, że będziemy musieli przeprowadzić małą operację.","Ok, você agradou o Governador, estourou os miolos do carcereiro... Agora parece que temos que fazer uma pequena cirurgia.",,"OK. L-ai mulțumit pe Guvernator, împrăștiat pe Director... acum se pare că trebuie să faci niște chirurgie.","Хорошо. Ты доставил удовольствие губернатору, забрызгал стены мозгами тюремщика... Теперь нам предстоит небольшое хирургическое вмешательство.",,"OKEJ, DÅ ÄR DET DAGS ATT LÅSA OCH LÅSA. Du har nöjt guvernören, kladdat på fängelsedirektören... Nu ser det ut som om vi måste göra en liten operation.","TAMAMDIR. Vali'yi memnun ettiniz, Müdür'ün canına okudunuz. Şimdi küçük bir ameliyat yapmamız gerekecek gibi görünüyor." Oh you cut off his hand! And I thought you were a nice guy... kinda. Let's go.,TXT_SUB_LOG20,MAP05: After cutting Wolenick's hand off.,,,"Oh, tys mu uříznul ruku! A já myslela že jsi hodný chlap... jakž takž. Pojďme.","Du skar hans hånd af! Og jeg troede, du var en flink fyr... på en måde. Lad os gå.","Oh, du hast seine Hand abgeschnitten! Und ich dachte du wärest ein netter Typ... oder so. Lass uns gehen.",,,"¡Uh, le cortaste la mano! Y yo pensaba que eras un buen tío... más o menos. Bueno, vamos.","¡Uh, le cortaste la mano! Y yo creía que eras una buena persona... más o menos. Bueno, vamos.","Jaa, sinä katkaisit hänen kätensä! Ja minä kun luulin, että olit kiva kundi... jokseenkin. Mennään.","Oh, tu a coupé sa main? Je croyais que tu étais un type sympa.. Plus où moins. Allons-y.","Oh, levágtad a kezét! És azt hittem egy jó fiú vagy...vagy olyasmi. Na menjünk.","Ah, gli hai tagliato la mano! E io che pensavo fossi un bravo ragazzo... più o meno. Andiamo.","おいおい手を切り取ったのかよ! -ただのナイスガイってわけじゃないのね...まあいい、行こうか。","손을 뜯어버리다니! 아주 좋은 사람인 줄 알았는데... 귀엽네! 후훗, 가자구.","Oh, je hebt zijn hand eraf gesneden! En ik vond je een aardige kerel.... een beetje. Laten we gaan.",Du kappet av ham hånden! Og jeg som trodde du var en hyggelig fyr... på en måte. La oss gå.,"Odciąłeś mu rękę! A ja myślałam, że jesteś miłym facetem... w pewnym sensie. Chodźmy.","Ai, você cortou fora a mão dele! Eu achava que você era um cara bonzinho... talvez. Vamos lá.",,Oh i-ai tăiat mâna! Și credeam că ești de treabă... oarecum. Să mergem.,"О ч-чёрт, ты отрезал ему руку! Я думала, ты добрый парень... в некотором роде. Ладно, не бери в голову.",,Elini kesmişsin! Ben de senin iyi bir adam olduğunu sanıyordum. Hadi gidelim. -"Way to go, my friend. Jump on one of the teleporters and it will bring you back to base.",TXT_SUB_LOG21,MAP05: After setting the prisoners free.,,,"Jen tak dál, příteli. Skoč na teleportér, dostane tě zpět na základnu.","Godt gået, min ven. Hop på en af teleportørerne, og den bringer dig tilbage til basen.",Das war gute Arbeit. Benutze einen der Teleporter um zur Basis zurückzugelangen.,,,Así se hace amigo. Ponte en uno de los teletransportes y te traerá de vuelta a la base.,,"Niin sitä pitää, ystäväni. Hyppää johonkin kaukosiirtimistä, ja se tuo sinut takaisin tukikohtaan.",Bien joué mon ami! Utilise l'un des téléporteurs pour revenir à la base.,"Szép munka barátom. Ugorj bele az egyik teleportba, és visszavisz a bázisra.","Ben fatto, amico mio. Recati in uno dei teletrasporti e ti riporterà alla base.",行きましょう、相棒。牢屋奥のテレポーターに飛び込めば基地にすぐ着くわ。,"정말 잘했어, 친구. 저 텔레포터들 중 하나를 타면 기지로 복귀할 수 있을 거야.","Goed gedaan, mijn vriend. Spring op een van de teleporters en het brengt je terug naar de basis.","Sånn skal det gjøres, min venn. Hopp på en av teleporterne, så kommer du tilbake til basen.","Dobra robota, przyjacielu. Wskocz na jeden z teleporterów, a przeniesie cię do bazy.","Boa, meu amigo. Entre num desses teletransportadores e você voltará para a base.",,Bună treabă prietene. Sari într-unul din teleportoare și ne vom întoarce acasă.,"Так держать, дружище. Прыгай в любой телепорт, и он вернёт тебя на базу.",,"Aferin dostum. Işınlayıcılardan birine atla, seni üsse geri getirecek." -Worner is a spy we recruited in the warehouse of the power station.,TXT_SUB_LOG22,,,,"Worner je špión, kterého jsme najali ve skladišti elektrárny.","Worner er en spion, som vi rekrutterede i lageret på kraftværket.","Worner ist ein Spion, den wir im Lagerhaus des Kraftwerks rekrutiert haben.",,,Worner es un espía que reclutamos en el almacén de la estación eléctrica.,,Worner on värväämämme vakooja voimalaitoksen varastolta.,Worner est un espion que nous avons recruté dans l'entrepôt de la centrale éléctrique.,Worner egy spion akit az erőmű raktárjában toboroztunk.,Worner è una spia che abbiamo reclutato nel magazzino della centrale energetica.,,워너는 우리가 모집한 첩자야. 그는 발전소 창고에 있어.,Worner is een spion die we in het magazijn van de centrale hebben gerekruteerd.,Worner er en spion vi rekrutterte i lageret på kraftstasjonen.,"Worner to szpieg, którego zwerbowaliśmy w magazynie elektrowni.",Worner é um espião que recrutamos no depósito da usina de energia.,,Worner e un spion pe care l-am recrutat în depozitul stației de energie.,"Уорнэр — шпион, которого мы завербовали на складе электростанции.",,"Worner, güç istasyonunun deposunda işe aldığımız bir casus." +ただのナイスガイってわけじゃないのね...まあいい、行こうか。","손을 뜯어버리다니! 아주 좋은 사람인 줄 알았는데... 귀엽네! 후훗, 가자구.","Oh, je hebt zijn hand eraf gesneden! En ik vond je een aardige kerel.... een beetje. Laten we gaan.",Du kappet av ham hånden! Og jeg som trodde du var en hyggelig fyr... på en måte. La oss gå.,"Odciąłeś mu rękę! A ja myślałam, że jesteś miłym facetem... w pewnym sensie. Chodźmy.","Ai, você cortou fora a mão dele! Eu achava que você era um cara bonzinho... talvez. Vamos lá.",,Oh i-ai tăiat mâna! Și credeam că ești de treabă... oarecum. Să mergem.,"О ч-чёрт, ты отрезал ему руку! Я думала, ты добрый парень... в некотором роде. Ладно, не бери в голову.",,"Åh, du skar av hans hand! Och jag som trodde att du var en trevlig kille... typ. Nu går vi.",Elini kesmişsin! Ben de senin iyi bir adam olduğunu sanıyordum. Hadi gidelim. +"Way to go, my friend. Jump on one of the teleporters and it will bring you back to base.",TXT_SUB_LOG21,MAP05: After setting the prisoners free.,,,"Jen tak dál, příteli. Skoč na teleportér, dostane tě zpět na základnu.","Godt gået, min ven. Hop på en af teleportørerne, og den bringer dig tilbage til basen.",Das war gute Arbeit. Benutze einen der Teleporter um zur Basis zurückzugelangen.,,,Así se hace amigo. Ponte en uno de los teletransportes y te traerá de vuelta a la base.,,"Niin sitä pitää, ystäväni. Hyppää johonkin kaukosiirtimistä, ja se tuo sinut takaisin tukikohtaan.",Bien joué mon ami! Utilise l'un des téléporteurs pour revenir à la base.,"Szép munka barátom. Ugorj bele az egyik teleportba, és visszavisz a bázisra.","Ben fatto, amico mio. Recati in uno dei teletrasporti e ti riporterà alla base.",行きましょう、相棒。牢屋奥のテレポーターに飛び込めば基地にすぐ着くわ。,"정말 잘했어, 친구. 저 텔레포터들 중 하나를 타면 기지로 복귀할 수 있을 거야.","Goed gedaan, mijn vriend. Spring op een van de teleporters en het brengt je terug naar de basis.","Sånn skal det gjøres, min venn. Hopp på en av teleporterne, så kommer du tilbake til basen.","Dobra robota, przyjacielu. Wskocz na jeden z teleporterów, a przeniesie cię do bazy.","Boa, meu amigo. Entre num desses teletransportadores e você voltará para a base.",,Bună treabă prietene. Sari într-unul din teleportoare și ne vom întoarce acasă.,"Так держать, дружище. Прыгай в любой телепорт, и он вернёт тебя на базу.",,"Bra jobbat, min vän. Hoppa på en av teleporterna så kommer du tillbaka till basen.","Aferin dostum. Işınlayıcılardan birine atla, seni üsse geri getirecek." +Worner is a spy we recruited in the warehouse of the power station.,TXT_SUB_LOG22,,,,"Worner je špión, kterého jsme najali ve skladišti elektrárny.","Worner er en spion, som vi rekrutterede i lageret på kraftværket.","Worner ist ein Spion, den wir im Lagerhaus des Kraftwerks rekrutiert haben.",,,Worner es un espía que reclutamos en el almacén de la estación eléctrica.,,Worner on värväämämme vakooja voimalaitoksen varastolta.,Worner est un espion que nous avons recruté dans l'entrepôt de la centrale éléctrique.,Worner egy spion akit az erőmű raktárjában toboroztunk.,Worner è una spia che abbiamo reclutato nel magazzino della centrale energetica.,,워너는 우리가 모집한 첩자야. 그는 발전소 창고에 있어.,Worner is een spion die we in het magazijn van de centrale hebben gerekruteerd.,Worner er en spion vi rekrutterte i lageret på kraftstasjonen.,"Worner to szpieg, którego zwerbowaliśmy w magazynie elektrowni.",Worner é um espião que recrutamos no depósito da usina de energia.,,Worner e un spion pe care l-am recrutat în depozitul stației de energie.,"Уорнэр — шпион, которого мы завербовали на складе электростанции.",,Worner är en spion som vi rekryterade i kraftverkets lager.,"Worner, güç istasyonunun deposunda işe aldığımız bir casus." "Word from the boss is stand back when you whack the crystal, or else you'll end up mesquite-flavored too.",TXT_SUB_LOG23,MAP04: After entering Ketrick's room.,,,"Velení radí, aby ses držel dál až rozbiješ krystal, jinak taky skončíš jako pečínka.","Ordet fra chefen er, at du skal holde dig tilbage, når du slår krystallen, ellers ender du også som mesquite-flavored.","Der Ratschlag vom Boss ist, in Deckung zu gehen, wenn du den Kristall plattmachst. Andernfalls könntest du als Omelett enden.",,,"Dice el jefe que te eches atrás cuando le des al cristal, o si no también acabaras frito.",,"Viesti pomolta, että pysy loitolla, kun suolaat kristallin, tai muuten alat itse maistua suolalta.","Le boss me raconte que tu as intérêt à prendre tes distances avant de péter le cristal, sinon tu va aussi te retrouver cuit à la sauce barbecue au plasma.","Ha hihetünk a főnök szavainak, akkor érdemes tisztes távolból szétverni a kristályt, ha nem akarunk elszenesedni.","Il capo dice di tenersi lontani quando fai esplodere il cristallo, altrimenti rischi di saltare in aria pure tu.","上司が言うには、クリスタルを破壊する瞬間には隠れる必要があるな、 -でないと唐揚げになるわ。",대장 말로는 수정체를 부술 때 멀리 피해있으라고 했어. 너도 노릇노릇하게 구워지기 싫다면 말이지.,"Het woord van de baas is een stapje terug als je het kristal slaat, of anders kom je ook nog eens met een mesquite-smaakje terecht.","Ordet fra sjefen er stå tilbake når du slår krystallen, ellers vil du også ende opp med mesquite-smak.","Szef powiedział, żebyś się odsunął, gdy będziesz walił w kryształ, bo inaczej też skończysz z mesquitem.","A chefe me contou que você deve manter distância quando você arrebentar o cristal, senão você vira churrasco.",,"Vorba de la șef e să stai deoparte când spargi cristalul, altfel o să te faci terci.","Босс говорит, чтобы ты держался подальше от кристалла, когда он рванёт. Иначе тебя тоже прожарит до хрустящей корочки.",,"Patronun söylediğine göre kristale vururken geri çekilin, yoksa siz de mesquite aromalı olursunuz." -One more adventure before command feels it's safe to attack. Macil's arranged for Irale to give you gold and some training. And visit the medic for strength.,TXT_SUB_LOG25,MAP02: After destroying the crystal in the Power Station.,,,"Ještě jedno dobrodružství, než se velení rozhodne zaútočit. Macil sjednal u Iraleho zlato a trénink. Taky navštiv lékaře nabrat síly.","Et eventyr mere, før kommandoen føler, at det er sikkert at angribe. Macil har sørget for, at Irale giver dig guld og noget træning. Og besøg lægen for at få styrke.","Eine weitere Aufgabe noch, bevor Macil es für sicher hält, anzugreifen. Macil hat Irale gebeten, dir Gold zu geben und Training zu organisieren. Und lass dir vom Sanitäter deine Ausdauer erhöhen.",,,Una aventura más antes de que el comando sienta que es seguro atacar el castillo. Macil ha acordado con Irale que te dé oro y algo de entrenamiento. Y ver al médico en el pueblo para ganar fuerza.,,"Vielä yksi seikkailu, ennen kuin komentokeskus katsoo tilanteen hyväksi hyökätä. Macil on järjestänyt Iralen antamaan sinulle kultaa ja koulutusta. Ja tapaa lääkintämiestä vahvistusta varten.",Encore une aventure avant le commandement pense qu'il soit l'heure d'attaquer. Macil s'est arrangé pour qu'Irale te donne de l'argent et un peu d'entraînement en plus. Va voir le médecin pour plus de forces.,"Még egy kaland mielőtt az irányítás biztonságosnak érzi az tusoló rohamot. Macil elintézte, hogy kapj Iraletől aranyat és kiképzést. Keresd fel a szanitácet is, hogy felgyógyítson.","Un'ultima avventura prima dell'assedio al castello. Macil ha parlato ad Irale per farti avere dell'oro e un pò di addestramento. Dopo che gli hai fatto visita, parla anche dal medico in città per una marcia in più.","もう一つの任務をこなす前に戦力の増強が必要と考えられる。 +でないと唐揚げになるわ。",대장 말로는 수정체를 부술 때 멀리 피해있으라고 했어. 너도 노릇노릇하게 구워지기 싫다면 말이지.,"Het woord van de baas is een stapje terug als je het kristal slaat, of anders kom je ook nog eens met een mesquite-smaakje terecht.","Ordet fra sjefen er stå tilbake når du slår krystallen, ellers vil du også ende opp med mesquite-smak.","Szef powiedział, żebyś się odsunął, gdy będziesz walił w kryształ, bo inaczej też skończysz z mesquitem.","A chefe me contou que você deve manter distância quando você arrebentar o cristal, senão você vira churrasco.",,"Vorba de la șef e să stai deoparte când spargi cristalul, altfel o să te faci terci.","Босс говорит, чтобы ты держался подальше от кристалла, когда он рванёт. Иначе тебя тоже прожарит до хрустящей корочки.",,"Ord från chefen är att hålla sig undan när du slår kristallen, annars slutar du också med mesquite-smak.","Patronun söylediğine göre kristale vururken geri çekilin, yoksa siz de mesquite aromalı olursunuz." +One more adventure before command feels it's safe to attack. Macil's arranged for Irale to give you gold and some training. And visit the medic for strength.,TXT_SUB_LOG25,MAP02: After destroying the crystal in the Power Station.,,,"Ještě jedno dobrodružství, než se velení rozhodne zaútočit. Macil sjednal u Iraleho zlato a trénink. Taky navštiv lékaře nabrat síly.","Et eventyr mere, før kommandoen føler, at det er sikkert at angribe. Macil har sørget for, at Irale giver dig guld og noget træning. Og besøg lægen for at få styrke.","Eine weitere Aufgabe noch, bevor Macil es für sicher hält, anzugreifen. Macil hat Irale gebeten, dir Gold zu geben und Training zu organisieren. Und lass dir vom Sanitäter deine Ausdauer erhöhen.",,,Una aventura más antes de que el comando sienta que es seguro atacar el castillo. Macil ha acordado con Irale que te dé oro y algo de entrenamiento. Y ver al médico en el pueblo para ganar fuerza.,,"Vielä yksi seikkailu, ennen kuin komentokeskus katsoo tilanteen hyväksi hyökätä. Macil on järjestänyt Iralen antamaan sinulle kultaa ja koulutusta. Ja tapaa lääkintämiestä vahvistusta varten.",Encore une aventure avant le commandement pense qu'il soit l'heure d'attaquer. Macil s'est arrangé pour qu'Irale te donne de l'argent et un peu d'entraînement en plus. Va voir le médecin pour plus de forces.,"Még egy kaland mielőtt az irányítás biztonságosnak érzi az tusoló rohamot. Macil elintézte, hogy kapj Iraletől aranyat és kiképzést. Keresd fel a szanitácet is, hogy felgyógyítson.","Un'ultima avventura prima dell'assedio al castello. Macil ha parlato ad Irale per farti avere dell'oro e un po' di addestramento. Dopo che gli hai fatto visita, parla anche dal medico in città per una marcia in più.","もう一つの任務をこなす前に戦力の増強が必要と考えられる。 マシルがイラールを介して資金と訓練の手配をしてくれるので会いなさい。 -それと近所のメディックも支援してくれるわ。","본부가 공성전을 진행하기 전에 한 가지 해야 할 일이 있어. 마실이 이롤리에게 골드랑 훈련을 제공해달라고 부탁했대. 그다음에는, 마을 병원에 가서 근력을 키워달라고 해.",Nog één avontuur voordat het commando het gevoel heeft dat het veilig is om aan te vallen. Macil heeft ervoor gezorgd dat Irale je goud en wat training kan geven. En bezoek de dokter voor kracht.,Ett eventyr til før kommandoen mener det er trygt å angripe. Macil har sørget for at Irale gir deg gull og litt trening. Og besøk legen for å få styrke.,"Jeszcze jedna przygoda, zanim dowództwo uzna, że można bezpiecznie zaatakować. Macil załatwił, że Irale da ci złoto i trochę treningu. I odwiedź medyka, żeby nabrać sił.",Mais uma aventura antes do comando achar que é seguro o suficiente para atacar. Macil deu instruções para o Irale te passar ouro e um pouco de treinamento. E visite o médico para te dar uma força.,,Încă o aventură înainte de atacarea centrului de comandă. Macil a aranjat cu Irale ca tu să primești aur și niște antrenament. Și vizitează medicul pentru forță.,"Ещё одно приключение, и штаб будет уверен в успешности атаки на замок. Мэйсил поручил Ирэйлу выплатить тебе награду и дать пару уроков. И зайди на всякий случай к медику.",,"Komuta saldırmanın güvenli olduğunu düşünmeden önce bir macera daha. Macil, İrale'nin sana altın ve biraz eğitim vermesini ayarladı. Ve güç için doktoru ziyaret et." +それと近所のメディックも支援してくれるわ。","본부가 공성전을 진행하기 전에 한 가지 해야 할 일이 있어. 마실이 이롤리에게 골드랑 훈련을 제공해달라고 부탁했대. 그다음에는, 마을 병원에 가서 근력을 키워달라고 해.",Nog één avontuur voordat het commando het gevoel heeft dat het veilig is om aan te vallen. Macil heeft ervoor gezorgd dat Irale je goud en wat training kan geven. En bezoek de dokter voor kracht.,Ett eventyr til før kommandoen mener det er trygt å angripe. Macil har sørget for at Irale gir deg gull og litt trening. Og besøk legen for å få styrke.,"Jeszcze jedna przygoda, zanim dowództwo uzna, że można bezpiecznie zaatakować. Macil załatwił, że Irale da ci złoto i trochę treningu. I odwiedź medyka, żeby nabrać sił.",Mais uma aventura antes do comando achar que é seguro o suficiente para atacar. Macil deu instruções para o Irale te passar ouro e um pouco de treinamento. E visite o médico para te dar uma força.,,Încă o aventură înainte de atacarea centrului de comandă. Macil a aranjat cu Irale ca tu să primești aur și niște antrenament. Și vizitează medicul pentru forță.,"Ещё одно приключение, и штаб будет уверен в успешности атаки на замок. Мэйсил поручил Ирэйлу выплатить тебе награду и дать пару уроков. И зайди на всякий случай к медику.",,Ett äventyr till innan befälet känner att det är säkert att attackera. Macil har ordnat så att Irale ger dig guld och lite träning. Och besök läkaren för att få styrka.,"Komuta saldırmanın güvenli olduğunu düşünmeden önce bir macera daha. Macil, İrale'nin sana altın ve biraz eğitim vermesini ayarladı. Ve güç için doktoru ziyaret et." "The Order thinks it's secure in its castle. Wrong! If you open the gates, they'll be easy pickings. And for that, you'll have to go down into the sewers. Head along the river across the Governor's mansion. ",TXT_SUB_LOG26,〃,,,"Řád si myslí, že je uvnitř hradu v bezpečí. Špatně! Pokud otevřeš brány, nebudou proti nám mít šanci. A kvůli tomu musíme do stok. Zamiř si to podél řeky naproti guvernérově sídlu.","Ordenen tror, at den er sikker i sit slot. Det er forkert! Hvis du åbner portene, bliver de et let bytte. Og til det skal du ned i kloakkerne. Gå langs floden over for guvernørens palæ.","Der Orden glaubt, er sei in seiner Burg sicher. Falsch! Wenn du die Tore öffnest werden sie ein leichtes Ziel sein. Und dafür müssen wir in die Kanalisation runter. Geh runter zum Fluss, auf der anderen Seite von der Villa des Gouverneurs.",,,"La Orden cree que está segura en su castillo. ¡Se equivocan! Si abres las puertas, serán cosecha fácil. Y para eso, tienes que bajar a las alcantarillas. Dirígete por el río al lado de la mansión del Gobernador.",,"Veljeskunta luulee olevansa turvassa linnassaan. Väärin! Jos avaat portit, he ovat helppoa saalista. Ja sitä varten sinun on mentävä alas viemäreihin. Kulje joen vartta kuvernöörin kartanoa vastapäätä.","L'Ordre se pense en sécurité dans son château, faux! Si tu ouvre les portes, il seront faciles à flinguer. Oh, et pour ça il faut que tu descende dans les égouts. Suis la rivière de l'autre côté du manoir du gouverneur.",A Rend azt hiszi biztonságban vannak a kastélyban. Tévedés! Ha sikerül kinyitni a kaput könnyen le tudjuk őket szedni. Ezért azonban le kell menni a kanálisba. Menj a folyó nyomán a kormányzó kúriájával szemben.,"L'Ordine pensa di essere al sicuro dentro il suo castello. Sbagliato! Se apri i cancelli, saranno facili bersagli. E per aprirli, dovremo scendere nelle fogne. L'ingresso si trova vicino al fiume verso dove c'è la dimora del governatore.","オーダーは封鎖した城内が安全だと思っている。大した自信だな! 容易く侵入を許すとも知らずに。それでゲートを開けるには下水道を通る必要がある。 -知事邸の川を挟んだ所にその入り口がある。","오더는 성안 쪽에 지켜져 있는 거로 알겠지만, 틀렸어! 성문을 열기만 한다면 나머지는 쉬운 일일 거야. 일단 그러려면, 하수구 아래로 내려가야 해. 총독 관저 너머의 강을 지나가 봐.","De Orde denkt dat het veilig is in zijn kasteel. Fout! Als je de poorten opent, zijn het gemakkelijke keuzes. En daarvoor moet je de riolering in. Loop langs de rivier over het landhuis van de gouverneur.","Ordenen tror den er trygg i sitt slott. Feil! Hvis du åpner portene, blir de et lett bytte. Og da må du gå ned i kloakken. Gå langs elven på den andre siden av guvernørens hus.","Zakon myśli, że jest bezpieczny w swoim zamku. Mylisz się! Jeśli otworzysz bramy, będą łatwym łupem. A w tym celu będziesz musiał zejść do kanałów. Kieruj się wzdłuż rzeki, naprzeciwko rezydencji gubernatora.","A Ordem acha que está segura dentro do castelo. Se enganaram! Se você abrir os portões, vai ser fácil pegá-los. E, para isso, você terá que ir até o esgoto. Vá pelo rio do outro lado da mansão do Governador.",,"Ordinul crede că e în siguranță în castel. Greșit! Dacă deschizi porțile, vor fi victime ușoare. Pentru asta, va trebui să mergi în canale. Urmează râul până la complexul Guvernatorului.","Орден думает, что замок неприступен. Большая ошибка! Он будет лёгкой добычей, когда ты откроешь врата. Спустись в канализацию, чтобы найти механизм. Иди вдоль берега реки — спуск прямо напротив особняка губернатора.",,"Tarikat kalesinde güvende olduğunu düşünüyor. Yanılıyorlar! Eğer kapıları açarsanız, kolay lokma olacaklar. Bunun için de kanalizasyona inmeniz gerekecek. Valinin konağının karşısındaki nehir boyunca ilerleyin." +知事邸の川を挟んだ所にその入り口がある。","오더는 성안 쪽에 지켜져 있는 거로 알겠지만, 틀렸어! 성문을 열기만 한다면 나머지는 쉬운 일일 거야. 일단 그러려면, 하수구 아래로 내려가야 해. 총독 관저 너머의 강을 지나가 봐.","De Orde denkt dat het veilig is in zijn kasteel. Fout! Als je de poorten opent, zijn het gemakkelijke keuzes. En daarvoor moet je de riolering in. Loop langs de rivier over het landhuis van de gouverneur.","Ordenen tror den er trygg i sitt slott. Feil! Hvis du åpner portene, blir de et lett bytte. Og da må du gå ned i kloakken. Gå langs elven på den andre siden av guvernørens hus.","Zakon myśli, że jest bezpieczny w swoim zamku. Mylisz się! Jeśli otworzysz bramy, będą łatwym łupem. A w tym celu będziesz musiał zejść do kanałów. Kieruj się wzdłuż rzeki, naprzeciwko rezydencji gubernatora.","A Ordem acha que está segura dentro do castelo. Se enganaram! Se você abrir os portões, vai ser fácil pegá-los. E, para isso, você terá que ir até o esgoto. Vá pelo rio do outro lado da mansão do Governador.",,"Ordinul crede că e în siguranță în castel. Greșit! Dacă deschizi porțile, vor fi victime ușoare. Pentru asta, va trebui să mergi în canale. Urmează râul până la complexul Guvernatorului.","Орден думает, что замок неприступен. Большая ошибка! Он будет лёгкой добычей, когда ты откроешь врата. Спустись в канализацию, чтобы найти механизм. Иди вдоль берега реки — спуск прямо напротив особняка губернатора.",,Orden tror att den är säker i sitt slott. Fel! Om du öppnar portarna blir de lätta att plocka. Och för det måste du gå ner i kloakerna. Gå längs floden över guvernörens herrgård.,"Tarikat kalesinde güvende olduğunu düşünüyor. Yanılıyorlar! Eğer kapıları açarsanız, kolay lokma olacaklar. Bunun için de kanalizasyona inmeniz gerekecek. Valinin konağının karşısındaki nehir boyunca ilerleyin." "OK, duck in here. The sewer dwellers are horrible mutants, but their network of tunnels gives them access to secrets. Hold your nose... We're going down.",TXT_SUB_LOG27,〃,,,"Dobře, zalez sem. Obyvatelé kanálů jsou příšerní mutanti, ale pomocí své sítě tunelů mají přístup k informacím. Drž si nos... Jdeme dolů.","OK, duk dig herind. Kloakbeboerne er forfærdelige mutanter, men deres netværk af tunneler giver dem adgang til hemmeligheder. Hold dig for næsen... Vi går ned.","OK, kriech hier rein. Die Kanalisationsbewohner sind fürchterliche Mutanten, aber ihr Tunnelnetzwerk gibt ihnen Zugang zu Geheimräumen. Halt die Nase zu, wir gehen runter.",,,"Hay un interrumptor por aquí abajo. La gente de las alcantarillas son mutantes horribles, pero su red de túneles les da acceso a secretos. Tápate la nariz... Vamos abajo.",,"No niin, kumarru tässä. Viemärin asukit ovat kauhistuttavia mutantteja, mutta heidän tunneliverkkonsa antaa heille pääsyn salaisiin paikkoihin. Pidä kiinni nenästäsi, menemme alas.","Ok, accroupis-toi ici. Les habitants des égouts sont d'affreux mutants mais leur réseau de tunnels leur donne accès à beaucoup de secrets. Retient ton souffle, par contre.. On va descendre.","Ok, gugolj itt le. A kanális lakók szörnyű mutánsok, de az általuk kiépített alagút hálózat mindenféle titokhoz hozzásegíti őket. Fogd be az orrod...lemerülünk.","OK, entra qua dentro. Gli abitanti delle fogne sono orribili mutanti, ma la serie di tunnel che gestiscono permette di raggiungere diversi segreti. Tappati il naso... Stiamo scendendo.","下水道の住民は恐ろしい変異体だ。だが彼らのトンネル網には秘密の通路も含まれる。 -良し、ここから降りる前に鼻はつまんどけよ...","좋아, 바로 여기야. 하수구 거주민들은 끔찍한 돌연변이들이지만, 그들의 땅굴 망이 숨겨진 장소들로 인도할 거야. 숨 잘 참아... 아래로 내려간다.","Oké, bukken hier naar binnen. De rioolbewoners zijn verschrikkelijke mutanten, maar hun netwerk van tunnels geeft hen toegang tot geheimen. Hou je neus vast.... We gaan naar beneden.","OK, dukk her inne. Kloakkboerne er fæle mutanter, men deres nettverk av tunneler gir dem tilgang til hemmeligheter. Hold for nesen... Vi går ned.","Dobra, schowaj się tutaj. Mieszkańcy kanałów to straszne mutanty, ale ich sieć tuneli daje im dostęp do sekretów. Trzymaj się... Schodzimy na dół.","Ok, fique abaixado aqui. Os habitantes do esgoto são mutantes horríveis, mas a sua rede de túneis os dá acesso para áreas secretas. Segure a respiração... Vamos descer.",,"OK, ghemuiește-te aici. Locuitorii canalelor sunt mutanți oribili, dar rețeaua lor de tunele le dă acces la secrete.... Mergem înăuntru.","Да, это здесь. Обитатели канализации — жуткие уроды, но они знают все секреты благодаря своим системам туннелей. Зажми нос — мы спускаемся!",,"Tamam, buraya gir. Lağım sakinleri korkunç mutantlardır, ama tünel ağları onlara sırlara erişim sağlar. Burnunu tut. Aşağı iniyoruz." +良し、ここから降りる前に鼻はつまんどけよ...","좋아, 바로 여기야. 하수구 거주민들은 끔찍한 돌연변이들이지만, 그들의 땅굴 망이 숨겨진 장소들로 인도할 거야. 숨 잘 참아... 아래로 내려간다.","Oké, bukken hier naar binnen. De rioolbewoners zijn verschrikkelijke mutanten, maar hun netwerk van tunnels geeft hen toegang tot geheimen. Hou je neus vast.... We gaan naar beneden.","OK, dukk her inne. Kloakkboerne er fæle mutanter, men deres nettverk av tunneler gir dem tilgang til hemmeligheter. Hold for nesen... Vi går ned.","Dobra, schowaj się tutaj. Mieszkańcy kanałów to straszne mutanty, ale ich sieć tuneli daje im dostęp do sekretów. Trzymaj się... Schodzimy na dół.","Ok, fique abaixado aqui. Os habitantes do esgoto são mutantes horríveis, mas a sua rede de túneis os dá acesso para áreas secretas. Segure a respiração... Vamos descer.",,"OK, ghemuiește-te aici. Locuitorii canalelor sunt mutanți oribili, dar rețeaua lor de tunele le dă acces la secrete.... Mergem înăuntru.","Да, это здесь. Обитатели канализации — жуткие уроды, но они знают все секреты благодаря своим системам туннелей. Зажми нос — мы спускаемся!",,"Okej, ducka in här. Kloakborna är hemska mutanter, men deras nätverk av tunnlar ger dem tillgång till hemligheter. Håll dig för näsan... Vi går ner.","Tamam, buraya gir. Lağım sakinleri korkunç mutantlardır, ama tünel ağları onlara sırlara erişim sağlar. Burnunu tut. Aşağı iniyoruz." "We're looking for Weran, who calls himself the Rat King. I'm sure it's descriptive as well as colorful.",TXT_SUB_LOG28,MAP06: Entrance.,,,"Hledáma Werana, který si říká Krysí král. Jsem si jistá, že je to jak barvité, tak přesné.","Vi leder efter Weran, som kalder sig rottekongen. Jeg er sikker på, at det er både beskrivende og farverigt.",,,,"Estamos buscando a Weran, quien se autoproclama el Rey de las Ratas. Estoy segura de que es tanto descriptivo como vistoso.",,"Etsimme Werania, joka kutsuu itseään Rottakuninkaaksi. Varmastikin kuvaava titteli, mutta myös väritetty.",,"Werant keressük, aki csak Patkány Királyként emlegeti magát. Minden bizonnyal találó a név.","Stiamo cercando Weran, che si fa chiamare il Re dei Ratti. Sono sicura che lo descrive appieno.","ウェランを探すんだ、誰が呼んだかラットキングでもある。 -私はそれが叙述的でもあり派手な呼び名なのも定かだ。",우리는 자신을 시궁쥐 왕이라고 부르는 워렌을 찾아야 해. 알록달록해서 눈에 잘 띌 것 같은데 말이야.,"We zijn op zoek naar Weran, die zichzelf de rattenkoning noemt. Ik weet zeker dat het zowel beschrijvend als kleurrijk is.","Vi leter etter Weran, som kaller seg Rottekongen. Det er sikkert både beskrivende og fargerikt.","Szukamy Werana, który nazywa siebie Królem Szczurów. Jestem pewien, że jest to opisowe jak i barwne.","Estamos procurando pelo Weran, que se autodenomina o Rato Rei. Imagino que isso seja tão descritivo quanto gracioso.",,"Îl căutăm pe Weran, care-și spune Regele Sobolanilor. Sunt sigur că e și descripti și colorat.","Нам нужен Уэран — он называет себя Крысиным королём. Уверена, прозвище так же емко, как и красочно.",,Kendine Fare Kral diyen Weran'ı arıyoruz. Renkli olduğu kadar açıklayıcı da olduğuna eminim. -"Oh, yuck. I don't even want to think about what you are stepping in!",TXT_SUB_LOG29,MAP06: Down → Left.,,,"Ó, fuj, nechci ani pomýšlet na to, do čeho teď šlapeš!","Åh, føj. Jeg vil ikke engang tænke på, hvad du træder i!","Igitt! Ich möchte gar nicht darüber nachdenken, wo du gerade durchwatest.",,,"Oh, puaj. ¡No quiero ni pensar en lo que estás pisando!",,"Äh, yäk. En halua edes kuvitella, missä oikein astelet!","Oh, beurk! J'ai pas envie de savoir dans quoi tu marche!","Oh, fúj. Nem is akarom tudni miben lépkedsz.","Oh, dannazione... Non voglio neanche pensare a cosa stai calpestando!",オェッ。君が足を踏み入れてるモノの事など考えたくないわ!,웩. 네가 밟고 있는 게 뭔지 상상조차 하기 싫어!,"Oh, ja. Ik wil er niet eens aan denken wat je doet!","Å, æsj. Jeg vil ikke engang tenke på hva du tråkker i!","Oh, fuj. Nawet nie chcę myśleć, w co wdepniesz!","Argh, eca. Não quero nem saber no que você está pisando!",,"Oh, yuck. Nu vreau să știu în ce calci!","Ох, фу. Даже знать не хочу, во что ты наступил!",,"Oh, iğrenç. Neye bastığınızı düşünmek bile istemiyorum!" -Just what I need. More brown goo!,TXT_SUB_LOG30,MAP06: Down → Left → Upstairs → Left.,,,"Přesně, co potřebuju. Další hnědá břečka!",Lige hvad jeg har brug for. Mere brunt klamphug!,"Genau das, was ich brauchte. Mehr brauner Schlamm!",,,Justo lo que necesito. ¡Más lodo marrón!,,"Juuri, mitä tarvitsen: lisää ruskeaa mönjää!","Juste ce qu'il me fallait, encore de la crasse marron!",Pont ez hiányzott. Még több barna trutymák.,Proprio quello che volevo vedere. Altro liquido marrone!,万事休すだ。更に茶色いモノだ!,"또 시궁창이라니, 정말 보기 좋네!",Precies wat ik nodig heb. Meer bruine drab!,Akkurat det jeg trenger. Mer brunt gjørme!,Właśnie tego mi trzeba. Więcej brązowej mazi!,Justo o que eu precisava. Mais meleca marrom!,,Exact ce îmi trebuie. Mai multă mâzgă maro!,"То, что надо. Ещё больше коричневой жижи!",,Tam da ihtiyacım olan şey. Daha fazla kahverengi yapışkan! -"Hey, look! I think that's the door Weran wants ajar!",TXT_SUB_LOG31,,,,"Hele, podívej! Myslím, že to jsou ty dveře, které chce Weran nechat otevřené!","Hey, se! Jeg tror, det er døren, som Weran vil have på klem!","Sieh dort! Ich glaube, das ist die Tür, die Weran geöffnet haben möchte.",,,"¡Eh, mira! ¡Creo que esa es la puerta que Weran quiere entreabierta!",,"Hei, katso! Tuo on varmaankin se ovi, jonka Weran haluaa raolleen!","Hé, regarde! On dirait que c'est la porte que Weran veut qu'on coince!",Nézz oda! Azt hiszem ez az az ajtó amit félig ki akar nyitni Weran.,"Ehi, guarda! Credo quella sia la porta che Weran vuole aprire!",,저기야! 저게 워렌이 열어줬으면 하는 문일 거야.,"Hé, kijk! Ik denk dat dat de deur is die Weran op een kier wil hebben!","Hei, se! Jeg tror det er døra Weran vil ha på gløtt!","Hej, patrzcie! To chyba te drzwi, które Weran chce uchylić!",Olha! Acho que essa é a porta que o Weran quer que fique aberta!,,"Hei, uite! Acolo cred că e ușa pe care o vrea Weran!","О, смотри! Похоже, это та самая дверь, которую хочет приоткрыть Уэран!",,"Hey, bakın! Sanırım Weran'ın aralık kalmasını istediği kapı bu!" -"Shut your eyes! I don't wanna see! Oh, too late... Yuck. That doesn't look like a human body. What has the Order done? I gotta report this to command.",TXT_SUB_LOG32,,,,"Zavři oči! Nechci to vidět! Ah, moc pozdě... Fuj. To ani nevypadá jako lidské tělo. Co to Řád provedl? Musím tohle nahlásit velení.","Luk øjnene! Jeg vil ikke se! Åh, for sent... Yuck. Det ligner ikke et menneskeligt lig. Hvad har Ordenen gjort? Jeg må rapportere det til kommandoen.","Mach die Augen zu! Ich will das nicht sehen. Zu spät... Igitt, das sieht gar nicht aus wie ein menschlicher Körper. Was hat der Orden getan? Ich muss das an die Kommandozentrale weitergeben.",,,"¡Cierra los ojos! ¡No quiero ver! Oh, demasiado tarde... Puaj. Eso no parece un cuerpo humano. ¿Que ha hecho la Orden? Tengo que reportar esto al comando.",,"Sulje silmäsi! En halua nähdä! Äh, myöhäistä... yäk. Tuo ei näytä ihmisruumiilta. Mitä Veljeskunta oikein on tehnyt? Minun on ilmoitettava tästä komentokeskukselle.","Ferme tes yeux, je ne veux pas voire ça! Oh, trop tard.. Beurk, on dirait pas un corps humain, qu'est-ce que l'ordre à fait? Il faut que je rapporte ça au commandement.",Csukd be a szemed! Nem akarom látni! Ó túl késő...fúj. Ez nem úgy néz ki mint egy emberi tetem. Mit tett a Rend? Ezt jeleznem kell az irányításnak.,"Chiudi gli occhi! Non voglio vedere! Ah, troppo tardi... Non sembra un corpo umano. Che cosa ha fatto l'Ordine? Devo riportare questo al comando.",,"눈 감아! 보고 싶지 않아! 오, 너무 늦었네... 역겨워. 전혀 사람 몸 같지 않던데, 대체 오더가 무슨 짓을 한 거지? 본부에 이걸 보고해야겠어.","Sluit je ogen! Ik wil het niet zien! Oh, te laat.... Yuck. Dat ziet er niet uit als een menselijk lichaam. Wat heeft de Orde gedaan? Ik moet dit aan het commando melden.","Lukk øynene! Jeg vil ikke se! Å, for sent... Æsj. Det ser ikke ut som en menneskekropp. Hva har Ordenen gjort? Jeg må rapportere dette til kommandoen.","Zamknij oczy! Nie chcę widzieć! Och, za późno... Fuj. To nie wygląda jak ludzkie ciało. Co zrobił Zakon? Muszę to zgłosić do dowództwa.","Feche os olhos! Eu não quero ver! Ai, tarde demais... Eca. Isso não parece um corpo humano. O que foi que a Ordem fez? Preciso relatar isso ao comando.",,Închide ochii! Nu vreau să văd! Oh... prea târziu... Yuck. Nu pare un cadavru uman. Ce a făcut Ordinul? Trebuie să raportez asta.,"Зажмурься! Я не хочу это видеть! Ох, уже поздно... Какая дрянь. Это даже не выглядит как человеческое тело. Что творит этот Орден! Я немедленно доложу в штаб.",,"Kapa gözlerini! Görmek istemiyorum! Oh, çok geç... İğrenç. Bu bir insan vücuduna benzemiyor. Tarikat ne yaptı? Bunu komutaya rapor etmeliyim." -Why can't we do a mission in a field of flowers for once?,TXT_SUB_LOG33,MAP06: After giving the guard's uniform.,,,Nemůžeme někdy mít misi na poli plném kvítí?,Hvorfor kan vi ikke for en gangs skyld udføre en mission i en blomstermark?,Warum können wir nicht mal eine Mission in einem Blumenfeld haben? ,,,¿Por que no podemos hacer una misión en un campo de flores por una vez?,,Miksei meillä kerrankin voisi olla tehtävä kukkakedolla?,"Pourquoi est-ce qu'on ne peut pas avoir une mission dans un champ de fleurs, pour une fois?",Miért nem mehetünk legalább egyszer egy virágmezős misszióra?,Perché non possiamo fare una missione in un campo di fiori per una volta?,どうして私達は綺麗な場所で一度でも任務遂行が出来ないんだ?,왜 우리는 딱 한 번이라도 꽃밭에서 작전을 수행할 수 없는 걸까?,Waarom kunnen we niet een keer een missie doen in een bloemenveld?,Hvorfor kan vi ikke gjøre et oppdrag i en blomstereng for en gangs skyld?,Dlaczego nie możemy choć raz wykonać misji na polu kwiatów?,Por que é que a gente não faz uma missão num campo florido pelo menos uma vez?,,De ce nu putem avea o misiune pe un câmp de flori măcar odată?,Ну почему наши задания не могут разворачиваться на цветочном лугу?,,Neden bir kez olsun çiçek tarlasında görev yapamıyoruz? +私はそれが叙述的でもあり派手な呼び名なのも定かだ。",우리는 자신을 시궁쥐 왕이라고 부르는 워렌을 찾아야 해. 알록달록해서 눈에 잘 띌 것 같은데 말이야.,"We zijn op zoek naar Weran, die zichzelf de rattenkoning noemt. Ik weet zeker dat het zowel beschrijvend als kleurrijk is.","Vi leter etter Weran, som kaller seg Rottekongen. Det er sikkert både beskrivende og fargerikt.","Szukamy Werana, który nazywa siebie Królem Szczurów. Jestem pewien, że jest to opisowe jak i barwne.","Estamos procurando pelo Weran, que se autodenomina o Rato Rei. Imagino que isso seja tão descritivo quanto gracioso.",,"Îl căutăm pe Weran, care-și spune Regele Sobolanilor. Sunt sigur că e și descripti și colorat.","Нам нужен Уэран — он называет себя Крысиным королём. Уверена, прозвище так же емко, как и красочно.",,"Vi letar efter Weran, som kallar sig för råttkungen. Jag är säker på att det är både beskrivande och färgstarkt.",Kendine Fare Kral diyen Weran'ı arıyoruz. Renkli olduğu kadar açıklayıcı da olduğuna eminim. +"Oh, yuck. I don't even want to think about what you are stepping in!",TXT_SUB_LOG29,MAP06: Down → Left.,,,"Ó, fuj, nechci ani pomýšlet na to, do čeho teď šlapeš!","Åh, føj. Jeg vil ikke engang tænke på, hvad du træder i!","Igitt! Ich möchte gar nicht darüber nachdenken, wo du gerade durchwatest.",,,"Oh, puaj. ¡No quiero ni pensar en lo que estás pisando!",,"Äh, yäk. En halua edes kuvitella, missä oikein astelet!","Oh, beurk! J'ai pas envie de savoir dans quoi tu marche!","Oh, fúj. Nem is akarom tudni miben lépkedsz.","Oh, dannazione... Non voglio neanche pensare a cosa stai calpestando!",オェッ。君が足を踏み入れてるモノの事など考えたくないわ!,웩. 네가 밟고 있는 게 뭔지 상상조차 하기 싫어!,"Oh, ja. Ik wil er niet eens aan denken wat je doet!","Å, æsj. Jeg vil ikke engang tenke på hva du tråkker i!","Oh, fuj. Nawet nie chcę myśleć, w co wdepniesz!","Argh, eca. Não quero nem saber no que você está pisando!",,"Oh, yuck. Nu vreau să știu în ce calci!","Ох, фу. Даже знать не хочу, во что ты наступил!",,"Åh, äckligt. Jag vill inte ens tänka på vad du trampar i!","Oh, iğrenç. Neye bastığınızı düşünmek bile istemiyorum!" +Just what I need. More brown goo!,TXT_SUB_LOG30,MAP06: Down → Left → Upstairs → Left.,,,"Přesně, co potřebuju. Další hnědá břečka!",Lige hvad jeg har brug for. Mere brunt klamphug!,"Genau das, was ich brauchte. Mehr brauner Schlamm!",,,Justo lo que necesito. ¡Más lodo marrón!,,"Juuri, mitä tarvitsen: lisää ruskeaa mönjää!","Juste ce qu'il me fallait, encore de la crasse marron!",Pont ez hiányzott. Még több barna trutymák.,Proprio quello che volevo vedere. Altro liquido marrone!,万事休すだ。更に茶色いモノだ!,"또 시궁창이라니, 정말 보기 좋네!",Precies wat ik nodig heb. Meer bruine drab!,Akkurat det jeg trenger. Mer brunt gjørme!,Właśnie tego mi trzeba. Więcej brązowej mazi!,Justo o que eu precisava. Mais meleca marrom!,,Exact ce îmi trebuie. Mai multă mâzgă maro!,"То, что надо. Ещё больше коричневой жижи!",,Precis vad jag behöver. Mer brunt kladd!,Tam da ihtiyacım olan şey. Daha fazla kahverengi yapışkan! +"Hey, look! I think that's the door Weran wants ajar!",TXT_SUB_LOG31,,,,"Hele, podívej! Myslím, že to jsou ty dveře, které chce Weran nechat otevřené!","Hey, se! Jeg tror, det er døren, som Weran vil have på klem!","Sieh dort! Ich glaube, das ist die Tür, die Weran geöffnet haben möchte.",,,"¡Eh, mira! ¡Creo que esa es la puerta que Weran quiere entreabierta!",,"Hei, katso! Tuo on varmaankin se ovi, jonka Weran haluaa raolleen!","Hé, regarde! On dirait que c'est la porte que Weran veut qu'on coince!",Nézz oda! Azt hiszem ez az az ajtó amit félig ki akar nyitni Weran.,"Ehi, guarda! Credo quella sia la porta che Weran vuole aprire!",,저기야! 저게 워렌이 열어줬으면 하는 문일 거야.,"Hé, kijk! Ik denk dat dat de deur is die Weran op een kier wil hebben!","Hei, se! Jeg tror det er døra Weran vil ha på gløtt!","Hej, patrzcie! To chyba te drzwi, które Weran chce uchylić!",Olha! Acho que essa é a porta que o Weran quer que fique aberta!,,"Hei, uite! Acolo cred că e ușa pe care o vrea Weran!","О, смотри! Похоже, это та самая дверь, которую хочет приоткрыть Уэран!",,Titta! Jag tror att det är dörren som Weran vill ha på glänt!,"Hey, bakın! Sanırım Weran'ın aralık kalmasını istediği kapı bu!" +"Shut your eyes! I don't wanna see! Oh, too late... Yuck. That doesn't look like a human body. What has the Order done? I gotta report this to command.",TXT_SUB_LOG32,,,,"Zavři oči! Nechci to vidět! Ah, moc pozdě... Fuj. To ani nevypadá jako lidské tělo. Co to Řád provedl? Musím tohle nahlásit velení.","Luk øjnene! Jeg vil ikke se! Åh, for sent... Yuck. Det ligner ikke et menneskeligt lig. Hvad har Ordenen gjort? Jeg må rapportere det til kommandoen.","Mach die Augen zu! Ich will das nicht sehen. Zu spät... Igitt, das sieht gar nicht aus wie ein menschlicher Körper. Was hat der Orden getan? Ich muss das an die Kommandozentrale weitergeben.",,,"¡Cierra los ojos! ¡No quiero ver! Oh, demasiado tarde... Puaj. Eso no parece un cuerpo humano. ¿Que ha hecho la Orden? Tengo que reportar esto al comando.",,"Sulje silmäsi! En halua nähdä! Äh, myöhäistä... yäk. Tuo ei näytä ihmisruumiilta. Mitä Veljeskunta oikein on tehnyt? Minun on ilmoitettava tästä komentokeskukselle.","Ferme tes yeux, je ne veux pas voire ça! Oh, trop tard.. Beurk, on dirait pas un corps humain, qu'est-ce que l'ordre à fait? Il faut que je rapporte ça au commandement.",Csukd be a szemed! Nem akarom látni! Ó túl késő...fúj. Ez nem úgy néz ki mint egy emberi tetem. Mit tett a Rend? Ezt jeleznem kell az irányításnak.,"Chiudi gli occhi! Non voglio vedere! Ah, troppo tardi... Non sembra un corpo umano. Che cosa ha fatto l'Ordine? Devo riportare questo al comando.",,"눈 감아! 보고 싶지 않아! 오, 너무 늦었네... 역겨워. 전혀 사람 몸 같지 않던데, 대체 오더가 무슨 짓을 한 거지? 본부에 이걸 보고해야겠어.","Sluit je ogen! Ik wil het niet zien! Oh, te laat.... Yuck. Dat ziet er niet uit als een menselijk lichaam. Wat heeft de Orde gedaan? Ik moet dit aan het commando melden.","Lukk øynene! Jeg vil ikke se! Å, for sent... Æsj. Det ser ikke ut som en menneskekropp. Hva har Ordenen gjort? Jeg må rapportere dette til kommandoen.","Zamknij oczy! Nie chcę widzieć! Och, za późno... Fuj. To nie wygląda jak ludzkie ciało. Co zrobił Zakon? Muszę to zgłosić do dowództwa.","Feche os olhos! Eu não quero ver! Ai, tarde demais... Eca. Isso não parece um corpo humano. O que foi que a Ordem fez? Preciso relatar isso ao comando.",,Închide ochii! Nu vreau să văd! Oh... prea târziu... Yuck. Nu pare un cadavru uman. Ce a făcut Ordinul? Trebuie să raportez asta.,"Зажмурься! Я не хочу это видеть! Ох, уже поздно... Какая дрянь. Это даже не выглядит как человеческое тело. Что творит этот Орден! Я немедленно доложу в штаб.",,"Håll ögonen! Jag vill inte se! Åh, för sent... Usch. Det ser inte ut som en människokropp. Vad har Orden gjort? Jag måste rapportera det här till befälet.","Kapa gözlerini! Görmek istemiyorum! Oh, çok geç... İğrenç. Bu bir insan vücuduna benzemiyor. Tarikat ne yaptı? Bunu komutaya rapor etmeliyim." +Why can't we do a mission in a field of flowers for once?,TXT_SUB_LOG33,MAP06: After giving the guard's uniform.,,,Nemůžeme někdy mít misi na poli plném kvítí?,Hvorfor kan vi ikke for en gangs skyld udføre en mission i en blomstermark?,Warum können wir nicht mal eine Mission in einem Blumenfeld haben? ,,,¿Por que no podemos hacer una misión en un campo de flores por una vez?,,Miksei meillä kerrankin voisi olla tehtävä kukkakedolla?,"Pourquoi est-ce qu'on ne peut pas avoir une mission dans un champ de fleurs, pour une fois?",Miért nem mehetünk legalább egyszer egy virágmezős misszióra?,Perché non possiamo fare una missione in un campo di fiori per una volta?,どうして私達は綺麗な場所で一度でも任務遂行が出来ないんだ?,왜 우리는 딱 한 번이라도 꽃밭에서 작전을 수행할 수 없는 걸까?,Waarom kunnen we niet een keer een missie doen in een bloemenveld?,Hvorfor kan vi ikke gjøre et oppdrag i en blomstereng for en gangs skyld?,Dlaczego nie możemy choć raz wykonać misji na polu kwiatów?,Por que é que a gente não faz uma missão num campo florido pelo menos uma vez?,,De ce nu putem avea o misiune pe un câmp de flori măcar odată?,Ну почему наши задания не могут разворачиваться на цветочном лугу?,,Varför kan vi inte göra ett uppdrag på ett blomsterfält för en gångs skull?,Neden bir kez olsun çiçek tarlasında görev yapamıyoruz? I hate to say it but this reminds me of home. I'm underground not that far from here.,TXT_SUB_LOG34,MAP06: Weran's hideout.,,,"Říká se mi to těžko, ale tohle mi připomíná domov. Jsem v podzemí ne tak daleko odsud.","Jeg hader at sige det, men det her minder mig om mit hjem. Jeg er under jorden ikke så langt herfra.","Ich sage es nicht gerne, aber das erinnert mich an Zuhause. Ich bin auch im Untergrund, nicht weit von hier.",,,Odio decirlo pero esto me recuerda a mi hogar. Estoy bajo tierra no muy lejos de aquí.,,"Inhottaa sanoa, mutta tästä tulee koti mieleen: Olen maan alla, en niin kaukana täältä.","J'ai vraiment pas envie de l'admettre, mais ça me rappelle ma maison.. Je suis sous terre pas loin d'ici.","Nem szívesen mondom ezt, de ez az otthonomra emlékeztet. Föld alatt van az is nem túl messze innen.","Mi duole dirlo, ma tutto ciò mi ricorda casa. Anche io mi trovo sottoterra, non troppo lontano da qui.","言いたくないが私の家の事を思い出させるわ。 -私はこの地下から遠くない場所にいたのよ。","말하긴 싫지만, 여긴 꼭 내 집을 보는 것 같아... 난 여기서 멀지 않은 지하에 있어.","Ik haat het om het te zeggen, maar dit doet me denken aan thuis. Ik ben niet zo ver van hier ondergronds.","Jeg hater å si det, men dette minner meg om hjemme. Jeg er under jorden ikke så langt herfra.","Nie chcę tego mówić, ale to przypomina mi dom. Jestem pod ziemią, nie tak daleko stąd.",Odeio dizer isso mas isso lembra a minha casa. Estou sob o solo não muito longe daqui.,,Îmi pare rău s-o spun dar asta îmi aduce aminte de casă. Stau sub pământ nu departe de aici.,"Не хотела говорить, но это место напоминает мне о доме. Сейчас я в подземелье, которое не так уж далеко отсюда.",,"Bunu söylemekten nefret ediyorum ama bu bana evimi hatırlatıyor. Yeraltındayım, buradan çok uzakta değilim." -"Don't ask me where we are. I'm lost, too. Sorry.",TXT_SUB_LOG35,MAP06: Exit of the secret entrance.,,,"Neptej se mě, kde jsme. Taky jsem ztracená. Promiň.","Spørg mig ikke, hvor vi er. Jeg er også faret vild. Jeg er også fortabt. Undskyld.","Frag mich nicht, wo wir sind, ich habe keine Ahnung. Tut mir leid.",,,"No me preguntes en dónde estamos, que yo también estoy perdida. Perdón.",,"Älä kysy minulta, missä olemme. Olen myös eksyksissä; pahoittelut.","Me demande pas où on est, je suis aussi perdue que toi, désolée..","Ne kérdezd hol vagyunk. Én is el vagyok veszve, sajnálom.",Non chiedermi dove siamo. Mi sono persa anche io. Mi spiace...,今いる場所について私に聞かないでくれ。私も迷った。すまない。,"여기가 어딘지 묻지 마. 나도 길을 잃었거든, 미안해.",Vraag me niet waar we zijn. Ik ben ook verdwaald. Sorry.,Ikke spør meg hvor vi er. Jeg har også gått meg vill. Unnskyld meg.,"Nie pytaj mnie, gdzie jesteśmy. Ja też się zgubiłem. Przepraszam.",Não me pergunte onde estamos. Já me perdi. Desculpe.,,"Numă întreba unde suntem, și eu sunt pierdut. Scuze.","Даже не спрашивай, где мы. Я сама не знаю, извини.",,Bana nerede olduğumuzu sorma. Ben de kayboldum. Özür dilerim. -That brick... Didn't we pass that brick? No...,TXT_SUB_LOG36,MAP06: Secret entrance from the castle.,,,Ta cihla... Neminuli jsme tamtu cihlu? Ne...,Den mursten... Har vi ikke passeret den mursten? Nej...,Der Stein... Sind wir nicht an dem Stein vorbeigekommen? Nein...,,,"Ese ladrillo... ¿No habíamos pasado ya por ese ladrillo? Ah, no...",,Tuo tiilenmurikka... Emmekö jo menneet sen ohitse? Ei kun...,Cette brique.. On n'a pas passé cette brique avant? Non..,Az a tégla...Nem hagytuk már el azt a téglát egyszer? Nem...,Quel mattone... Abbiamo già superato quel mattone? No...,あの煉瓦...前通ったレンガか?いや...,저 벽... 아까 저 벽을 지나가지 않았던가? 아닌데...,Die steen.... Hebben we die steen niet gepasseerd? Nee....,Den mursteinen... Passerte vi ikke den mursteinen? Nei...,Ta cegła... Czy nie minęliśmy tej cegły? Nie...,Aquele tijolo... Já não passamos daquele tijolo? Não...,,Cărpmida aceea... Nu am trecut de ea? Nu...,Этот кирпич... Разве мы здесь не были? Нет...,,Şu tuğla. O tuğlayı geçmemiş miydik? Hayır. -"Command, he's done it! The gates are open. Send in the shock troops and tell Macil we're coming in! ",TXT_SUB_LOG37,MAP06: After destroying the gate controls.,,,"Velení, dokázal to! Brány jsou otevřené. Pošlete tam úderníky a řekněte Macilovi, že přicházíme!","Kommando, han har gjort det! Portene er åbne. Send choktropperne ind og fortæl Macil, at vi kommer ind!",Kommandozentrale: Er hat's geschafft! Die Tore sind offen. Schickt die Schocktruppen hinein und sagt Macil das wir auf dem Weg sind! Lass uns zur Frontbasis zurückkehren.,,,"Comando, ¡Lo ha hecho! Las puertas están abiertas. ¡Enviad a las tropas de choque y decidle a Macil que venimos adentro!","Comando, ¡Lo ha hecho! Las puertas están abiertas. ¡Envíen las tropas de choque y díganle a Macil que estamos entrando!","Komentokeskus, hän teki sen! Portit ovat auki; lähettäkää iskujoukot ja kertokaa Macilille, että vyörymme sisään!","C'est bon, commandement, il a réussi! Les portes sont ouvertes, envoyez les soldats de choc et dites à Macil que l'on arrive!","Irányítás, sikerült neki! A kapuk nyitva állnak. Küldjétek be a sokkolós egységeket, és mondjátok meg Macilnak, hogy behatolunk!","Comando, ce l'ha fatta! I cancelli sono aperti. Mandate avanti le truppe e dite a Macil che stiamo arrivando!","司令官、彼はやったぞ! -ゲートが開いた。突撃部隊を送って我々も続くとマシルに伝えてくれ!","본부, 그가 해냈습니다! 성문이 열렸습니다. 공습부대를 성문으로 이동시키고 사령관님께 우리들도 따라올 거라고 전해주세요.","Commando, hij heeft het gedaan! De poorten zijn open. Stuur de stoottroepen naar binnen en zeg Macil dat we binnenkomen!","Kommando, han har klart det! Portene er åpne. Send inn sjokktroppene og si til Macil at vi kommer inn!","Dowództwo, on to zrobił! Brama jest otwarta. Wyślijcie oddziały uderzeniowe i powiedzcie Macilowi, że wchodzimy!","Comando, ele conseguiu! Os portões estão abertos. Enviem as tropas de choque e digam ao Macil que estamos entrando!",,"Centru, am reușit! Porțile sunt deschise. Trimite trupele de șoc si spune-i lui Macil că intrăm!","Штаб, он выполнил задание! Ворота открыты. Посылайте ударный отряд и доложите Мэйсилу, что мы пробились!",,"Komuta, başardı! Kapılar açıldı. Şok birliklerini gönderin ve Macil'e geldiğimizi söyleyin!" +私はこの地下から遠くない場所にいたのよ。","말하긴 싫지만, 여긴 꼭 내 집을 보는 것 같아... 난 여기서 멀지 않은 지하에 있어.","Ik haat het om het te zeggen, maar dit doet me denken aan thuis. Ik ben niet zo ver van hier ondergronds.","Jeg hater å si det, men dette minner meg om hjemme. Jeg er under jorden ikke så langt herfra.","Nie chcę tego mówić, ale to przypomina mi dom. Jestem pod ziemią, nie tak daleko stąd.",Odeio dizer isso mas isso lembra a minha casa. Estou sob o solo não muito longe daqui.,,Îmi pare rău s-o spun dar asta îmi aduce aminte de casă. Stau sub pământ nu departe de aici.,"Не хотела говорить, но это место напоминает мне о доме. Сейчас я в подземелье, которое не так уж далеко отсюда.",,"Jag hatar att säga det, men det här påminner mig om mitt hem. Jag är underjordisk inte så långt härifrån.","Bunu söylemekten nefret ediyorum ama bu bana evimi hatırlatıyor. Yeraltındayım, buradan çok uzakta değilim." +"Don't ask me where we are. I'm lost, too. Sorry.",TXT_SUB_LOG35,MAP06: Exit of the secret entrance.,,,"Neptej se mě, kde jsme. Taky jsem ztracená. Promiň.","Spørg mig ikke, hvor vi er. Jeg er også faret vild. Jeg er også fortabt. Undskyld.","Frag mich nicht, wo wir sind, ich habe keine Ahnung. Tut mir leid.",,,"No me preguntes en dónde estamos, que yo también estoy perdida. Perdón.",,"Älä kysy minulta, missä olemme. Olen myös eksyksissä; pahoittelut.","Me demande pas où on est, je suis aussi perdue que toi, désolée..","Ne kérdezd hol vagyunk. Én is el vagyok veszve, sajnálom.",Non chiedermi dove siamo. Mi sono persa anche io. Mi spiace...,今いる場所について私に聞かないでくれ。私も迷った。すまない。,"여기가 어딘지 묻지 마. 나도 길을 잃었거든, 미안해.",Vraag me niet waar we zijn. Ik ben ook verdwaald. Sorry.,Ikke spør meg hvor vi er. Jeg har også gått meg vill. Unnskyld meg.,"Nie pytaj mnie, gdzie jesteśmy. Ja też się zgubiłem. Przepraszam.",Não me pergunte onde estamos. Já me perdi. Desculpe.,,"Numă întreba unde suntem, și eu sunt pierdut. Scuze.","Даже не спрашивай, где мы. Я сама не знаю, извини.",,Fråga mig inte var vi är. Jag är också vilse. Jag är också vilse.,Bana nerede olduğumuzu sorma. Ben de kayboldum. Özür dilerim. +That brick... Didn't we pass that brick? No...,TXT_SUB_LOG36,MAP06: Secret entrance from the castle.,,,Ta cihla... Neminuli jsme tamtu cihlu? Ne...,Den mursten... Har vi ikke passeret den mursten? Nej...,Der Stein... Sind wir nicht an dem Stein vorbeigekommen? Nein...,,,"Ese ladrillo... ¿No habíamos pasado ya por ese ladrillo? Ah, no...",,Tuo tiilenmurikka... Emmekö jo menneet sen ohitse? Ei kun...,Cette brique.. On n'a pas passé cette brique avant? Non..,Az a tégla...Nem hagytuk már el azt a téglát egyszer? Nem...,Quel mattone... Abbiamo già superato quel mattone? No...,あの煉瓦...前通ったレンガか?いや...,저 벽... 아까 저 벽을 지나가지 않았던가? 아닌데...,Die steen.... Hebben we die steen niet gepasseerd? Nee....,Den mursteinen... Passerte vi ikke den mursteinen? Nei...,Ta cegła... Czy nie minęliśmy tej cegły? Nie...,Aquele tijolo... Já não passamos daquele tijolo? Não...,,Cărpmida aceea... Nu am trecut de ea? Nu...,Этот кирпич... Разве мы здесь не были? Нет...,,Den där tegelstenen... Passerade vi inte den stenen? Nej...,Şu tuğla. O tuğlayı geçmemiş miydik? Hayır. +"Command, he's done it! The gates are open. Send in the shock troops and tell Macil we're coming in! ",TXT_SUB_LOG37,MAP06: After destroying the gate controls.,,,"Velení, dokázal to! Brány jsou otevřené. Pošlete tam úderníky a řekněte Macilovi, že přicházíme!","Kommando, han har gjort det! Portene er åbne. Send choktropperne ind og fortæl Macil, at vi kommer ind!",Kommandozentrale: Er hat's geschafft! Die Tore sind offen. Schickt die Schocktruppen hinein und sagt Macil das wir auf dem Weg sind! Lass uns zur Frontbasis zurückkehren.,,"Fronto, li sukcesis! Li malfermis la pordojn. Sendu la sturmantojn kaj diru al Macil, ke estas tempo eniri!","¡Comando, lo ha conseguido! Las puertas ya están abiertas. ¡Enviad a las tropas de choque y decidle a Macil que ya es hora de entrar!","¡Comando, lo logró! Las puertas ya están abiertas. ¡Manden a las tropas de choque y díganle a Macil que ya es hora de entrar!","Komentokeskus, hän teki sen! Portit ovat auki; lähettäkää iskujoukot ja kertokaa Macilille, että vyörymme sisään!","C'est bon, commandement, il a réussi! Les portes sont ouvertes, envoyez les soldats de choc et dites à Macil que l'on arrive!","Irányítás, sikerült neki! A kapuk nyitva állnak. Küldjétek be a sokkolós egységeket, és mondjátok meg Macilnak, hogy behatolunk!","Comando, ce l'ha fatta! I cancelli sono aperti. Mandate avanti le truppe e dite a Macil che stiamo arrivando!","司令官、彼はやったぞ! +ゲートが開いた。突撃部隊を送って我々も続くとマシルに伝えてくれ!","본부, 그가 해냈습니다! 성문이 열렸습니다. 공습부대를 성문으로 이동시키고 사령관님께 우리들도 따라올 거라고 전해주세요.","Commando, hij heeft het gedaan! De poorten zijn open. Stuur de stoottroepen naar binnen en zeg Macil dat we binnenkomen!","Kommando, han har klart det! Portene er åpne. Send inn sjokktroppene og si til Macil at vi kommer inn!","Dowództwo, on to zrobił! Brama jest otwarta. Wyślijcie oddziały uderzeniowe i powiedzcie Macilowi, że wchodzimy!","Comando, ele conseguiu! Os portões estão abertos. Enviem as tropas de choque e digam ao Macil que estamos entrando!",,"Centru, am reușit! Porțile sunt deschise. Trimite trupele de șoc si spune-i lui Macil că intrăm!","Штаб, он выполнил задание! Ворота открыты. Посылайте ударный отряд и доложите Мэйсилу, что мы пробились!",,"Kommando, han har gjort det! Portarna är öppna. Skicka in chocktrupperna och säg till Macil att vi kommer in!","Komuta, başardı! Kapılar açıldı. Şok birliklerini gönderin ve Macil'e geldiğimizi söyleyin!" "We have conflicting reports about the Programmer's location. One say he's in a computer room, another that he's in a keep and yet another that mentions a long hallway. Sorry. ",TXT_SUB_LOG38,MAP07: Entrace.,,,"Máme rozcházející se zprávy o Programátorově pozici. Jedna mluví o místnosti s počítači, druhá, že je v nějaké pevnosti a třetí zmiňuje dlouhou chodbu. Promiň.","Vi har modstridende rapporter om programmørens placering. En siger, at han er i et computerrum, en anden, at han er i et tårn og endnu en anden, der nævner en lang gang. Undskyld.","Wir haben widersprüchliche Angaben über seinen Aufenthaltsort. Eine sagt, in einem Computerraum, ein anderer, dass er sich in einem Tempelkeller versteckt und noch ein anderer sagt was vom Ende eines langen Flurs.",,,"Tenemos informes contradictorios sobre la ubicación del Programador: uno dice que está en una sala de ordenadores, otro que está en un torreón y otro más menciona un pasillo largo. Perdón.","Tenemos informes contradictorios sobre la ubicación del Programador: uno dice que está en una sala de computadoras, otro que está en un torreón y otro más menciona un pasillo largo. Perdón.","Meillä eriäviä tietoja Ohjelmoitsijan sijainnista: Yhden mukaan hän on tietokonehuoneessa, toisen mukaan linnakkeessa ja vielä kolmas, joka mainitsee pitkän käytävän. Valitan.","On a des rapports contradictoires au sujet d'où se trouve le programmeur. On me dit d'un côté qu'il est dans une salle des ordinateurs, un autre me dit qu'il est dans un donjon, et un autre me dit qu'il est dans un long couloir.. Désolé.","Ellentmondásos jelentéseink vannak a Programozó hollétéről. Egy szerint a számítógép szobában van, másik szerint a vártoronyban, harmadik egy hosszú folyosót említ. Sajnálom.","I rapporti che abbiamo sulla sua posizione si contraddicono. Uno lo piazza in una stanza di computer, un altro in un tempio di sottolivello, e un altro ancora alla fine di un lungo corridoio.","プログラマーの居場所について矛盾する報告もあるわ。 ある人はコンピューター室にいる、別の人は保管室にいる、 -また別の人は長い廊下にいるとも言っていたわ。何とも言えない。","프로그래머의 위치에 관한 보고들이 전부 제각각이야. 하나는 컴퓨터실에, 또 하나는 성채에, 다른 하나는 긴 복도에 있대. 정말 유감이야.","We hebben tegenstrijdige berichten over de locatie van de programmeur. De een zegt dat hij in een computerkamer is, de ander dat hij in een donjon zit en weer een ander die een lange gang noemt. Sorry.","Vi har motstridende rapporter om hvor programmereren befinner seg. En sier at han er i et datarom, en annen at han er i en borg og en tredje nevner en lang korridor. Unnskyld.","Mamy sprzeczne raporty na temat lokalizacji Programisty. Jeden mówi, że jest w sali komputerowej, inny, że w magazynie, a jeszcze inny, że wspomina o długim korytarzu. Przepraszam.","Temos relatos conflitantes sobre onde o Programador se encontra. Um deles diz que ele está na sala de informática, outro que ele está na fortaleza e outro diz que ele está no fim de um longo corredor. Desculpe.",,"Avem rapoarte conflictuale în privința locației Programatorului. Unul zice că e într-o sală de calculatoare, altul într-o curte, iar altul că e intr-un hol lung. Scuze.","Наши сведения о местонахождении Программиста противоречивы. Одни говорят, что он в компьютерной комнате, другие, что он укрывается в цитадели, а третьи, что он в конце длинного коридора. Извини.",,"Programcının yeri hakkında çelişkili raporlarımız var. Biri bir bilgisayar odasında olduğunu söylüyor, diğeri bir mahzende ve bir başkası da uzun bir koridordan bahsediyor. Özür dilerim." -"Ah, it's good to be on the offensive again. Give 'em hell, guys!",TXT_SUB_LOG39,MAP07: Near the crusaders.,,,"Á, je to fajn být zase na straně ofenzívy. Jen jim dejte, chlapi!","Ah, det er godt at være i offensiven igen. Giv dem en røvfuld, gutter!","Ah, es ist gut, wieder in der Offensive zu sein. Macht sie fertig, Leute!",,,"Ah, sienta bien estar a la ofensiva de nuevo. ¡Dadles caña, chicos!",,"Aah, tekeepä hyvää olla taas vaihteeksi hyökkäävänä osapuolena. Hakkaa päälle, pojat!","Ah, ça fait du bien d'être sur l'offensive une fois de plus! Foutez leur la misère, les gars!","Áh, jó újra támadásba lendülni. Leckéztessétek meg őket!","Ah, che bello essere di nuovo all'offensiva! Mostrategli la via per l'inferno, ragazzi!",再襲撃するには良い機会だ。地獄に送ってやれ、皆!,"아, 이렇게 다시 공격적으로 나가니 좋다. 맛 좀 보여줘, 얘들아!","Ah, het is goed om weer in de aanval te zijn. Geef ze de hel, jongens!","Ah, det er godt å være på offensiven igjen. Gi dem helvete, folkens!","Dobrze jest być znowu w ofensywie. Zróbcie im piekło, chłopaki!","Ah, é bom estar na ofensiva mais uma vez. Chumbo neles, pessoal!",,"Ah, e bine că mă regăsesc din nou pe partea ofensivă. Dați-le bătaie!","Наконец-то, мы снова переходим в наступление! Всыпьте им как следует, парни!",,Tekrar saldırıya geçmek güzel. Canlarına okuyun çocuklar! +また別の人は長い廊下にいるとも言っていたわ。何とも言えない。","프로그래머의 위치에 관한 보고들이 전부 제각각이야. 하나는 컴퓨터실에, 또 하나는 성채에, 다른 하나는 긴 복도에 있대. 정말 유감이야.","We hebben tegenstrijdige berichten over de locatie van de programmeur. De een zegt dat hij in een computerkamer is, de ander dat hij in een donjon zit en weer een ander die een lange gang noemt. Sorry.","Vi har motstridende rapporter om hvor programmereren befinner seg. En sier at han er i et datarom, en annen at han er i en borg og en tredje nevner en lang korridor. Unnskyld.","Mamy sprzeczne raporty na temat lokalizacji Programisty. Jeden mówi, że jest w sali komputerowej, inny, że w magazynie, a jeszcze inny, że wspomina o długim korytarzu. Przepraszam.","Temos relatos conflitantes sobre onde o Programador se encontra. Um deles diz que ele está na sala de informática, outro que ele está na fortaleza e outro diz que ele está no fim de um longo corredor. Desculpe.",,"Avem rapoarte conflictuale în privința locației Programatorului. Unul zice că e într-o sală de calculatoare, altul într-o curte, iar altul că e intr-un hol lung. Scuze.","Наши сведения о местонахождении Программиста противоречивы. Одни говорят, что он в компьютерной комнате, другие, что он укрывается в цитадели, а третьи, что он в конце длинного коридора. Извини.",,"Vi har motstridiga rapporter om var programmeraren befinner sig. En säger att han är i ett datorrum, en annan att han är i ett torn och ytterligare en annan nämner en lång korridor. Jag är ledsen.","Programcının yeri hakkında çelişkili raporlarımız var. Biri bir bilgisayar odasında olduğunu söylüyor, diğeri bir mahzende ve bir başkası da uzun bir koridordan bahsediyor. Özür dilerim." +"Ah, it's good to be on the offensive again. Give 'em hell, guys!",TXT_SUB_LOG39,MAP07: Near the crusaders.,,,"Á, je to fajn být zase na straně ofenzívy. Jen jim dejte, chlapi!","Ah, det er godt at være i offensiven igen. Giv dem en røvfuld, gutter!","Ah, es ist gut, wieder in der Offensive zu sein. Macht sie fertig, Leute!",,,"Ah, sienta bien estar a la ofensiva de nuevo. ¡Dadles caña, chicos!",,"Aah, tekeepä hyvää olla taas vaihteeksi hyökkäävänä osapuolena. Hakkaa päälle, pojat!","Ah, ça fait du bien d'être sur l'offensive une fois de plus! Foutez leur la misère, les gars!","Áh, jó újra támadásba lendülni. Leckéztessétek meg őket!","Ah, che bello essere di nuovo all'offensiva! Mostrategli la via per l'inferno, ragazzi!",再襲撃するには良い機会だ。地獄に送ってやれ、皆!,"아, 이렇게 다시 공격적으로 나가니 좋다. 맛 좀 보여줘, 얘들아!","Ah, het is goed om weer in de aanval te zijn. Geef ze de hel, jongens!","Ah, det er godt å være på offensiven igjen. Gi dem helvete, folkens!","Dobrze jest być znowu w ofensywie. Zróbcie im piekło, chłopaki!","Ah, é bom estar na ofensiva mais uma vez. Chumbo neles, pessoal!",,"Ah, e bine că mă regăsesc din nou pe partea ofensivă. Dați-le bătaie!","Наконец-то, мы снова переходим в наступление! Всыпьте им как следует, парни!",,"Ah, det är skönt att vara på offensiven igen. Ge dem ett helvete, killar!",Tekrar saldırıya geçmek güzel. Canlarına okuyun çocuklar! This looks good. Computers... Programmer... What do you think?,TXT_SUB_LOG40,MAP07: Computer room.,,,Tohle vypadá dobře. Počítače... Programátor... Co myslíš?,Det ser godt ud. Computere... Programmør... Hvad synes du?,Das sieht gut aus. Computer... Programmierer... Was denkst du?,,,Esto pinta bien. Computadoras... Programador... ¿Tú que crees?,,"Tämä näyttää hyvältä. Tietokoneita, ohjelmoitsija... Mitä tuumit?","Tout à l'air bien. Ordinateurs, Programmeur, tu en pense quoi?",Ez jól néz ki. Számítógépek... Programozó... Mit gondolsz?,Promette bene. Computer... Programmatore... Che ne pensi?,"これは良い。コンピューター... -プログラマー...アンタはどう思う?",이거 괜찮아 보이네. 컴퓨터들과... 프로그래머... 어떻게 생각해?,Dit ziet er goed uit. Computers.... Programmeur.... Wat vind je ervan?,Dette ser bra ut. Datamaskiner... Programmerer... Hva syns du?,To wygląda dobrze. Komputery... Programista... Co o tym sądzisz?,Isto parece bom. Computadores... Programador... O que você acha?,,Arată bine. Calculatoare... Programator... Ce zici?,"Похоже, это здесь. Компьютеры... Программист... Что скажешь?",,Bu iyi görünüyor. Bilgisayarlar. Programcı. Ne düşünüyorsun? -This must be the long hallway. Either that or my sense of scale is shot to hell.,TXT_SUB_LOG41,MAP07: Building before the brigde.,,,"Tohle musí být ta dlouhá chodba. Buď, a nebo už špatně vidím.","Dette må være den lange gang. Enten det, eller også er min fornemmelse for skalaer skudt ad helvede til.","Das muss der lange Flur sein. Entweder das, oder mein Sinn für Größe ist nicht in Ordnung.",,,Este debe ser el pasillo largo. O es eso o mi sentido de la escala está fastidiado.,,"Tämä on varmaankin se pitkä käytävä. Joko niin, tai sitten olen ihan pihalla mittasuhteista.","Ca doit être le long couloir, ça où ma perception des choses est un peu foutue..","Ez lehet a hosszú folyosó. Vagy ez, vagy a térérzékem tropára ment.",Questo deve essere il lungo corridoio. Oppure il mio senso della prospettiva è proprio andato a farsi benedire.,この長い廊下に違いない。それか私のスケール感とどちらかが撃ち落されるな。,"여기가 바로 긴 복도겠네. 아주 길다고 생각해, 아니면 내 머리가 이상하겠지.",Dit moet de lange gang zijn. Of dat of mijn gevoel voor schaalvergroting is naar de hel geschoten.,"Dette må være den lange gangen. Enten det, eller så er målestokkfølelsen min ødelagt.","To musi być ten długi korytarz. Albo to, albo moje wyczucie skali jest do dupy.",Esse deve ser o longo corredor. Ou isso ou o meu senso de escala foi pro saco.,,"Ăsta trebuie să fie holul lung. Fie asta, fie capacitatea mea de a aprecia scara e varză.","Должно быть, длинный коридор — это здесь. Ну или у меня всё плохо с глазомером.",,Burası uzun koridor olmalı. Ya öyle ya da benim ölçek algım cehenneme döndü. +プログラマー...アンタはどう思う?",이거 괜찮아 보이네. 컴퓨터들과... 프로그래머... 어떻게 생각해?,Dit ziet er goed uit. Computers.... Programmeur.... Wat vind je ervan?,Dette ser bra ut. Datamaskiner... Programmerer... Hva syns du?,To wygląda dobrze. Komputery... Programista... Co o tym sądzisz?,Isto parece bom. Computadores... Programador... O que você acha?,,Arată bine. Calculatoare... Programator... Ce zici?,"Похоже, это здесь. Компьютеры... Программист... Что скажешь?",,Det här ser bra ut. Datorer... Programmerare... Vad tycker du?,Bu iyi görünüyor. Bilgisayarlar. Programcı. Ne düşünüyorsun? +This must be the long hallway. Either that or my sense of scale is shot to hell.,TXT_SUB_LOG41,MAP07: Building before the brigde.,,,"Tohle musí být ta dlouhá chodba. Buď, a nebo už špatně vidím.","Dette må være den lange gang. Enten det, eller også er min fornemmelse for skalaer skudt ad helvede til.","Das muss der lange Flur sein. Entweder das, oder mein Sinn für Größe ist nicht in Ordnung.",,,Este debe ser el pasillo largo. O es eso o mi sentido de la escala está fastidiado.,,"Tämä on varmaankin se pitkä käytävä. Joko niin, tai sitten olen ihan pihalla mittasuhteista.","Ca doit être le long couloir, ça où ma perception des choses est un peu foutue..","Ez lehet a hosszú folyosó. Vagy ez, vagy a térérzékem tropára ment.",Questo deve essere il lungo corridoio. Oppure il mio senso della prospettiva è proprio andato a farsi benedire.,この長い廊下に違いない。それか私のスケール感とどちらかが撃ち落されるな。,"여기가 바로 긴 복도겠네. 아주 길다고 생각해, 아니면 내 머리가 이상하겠지.",Dit moet de lange gang zijn. Of dat of mijn gevoel voor schaalvergroting is naar de hel geschoten.,"Dette må være den lange gangen. Enten det, eller så er målestokkfølelsen min ødelagt.","To musi być ten długi korytarz. Albo to, albo moje wyczucie skali jest do dupy.",Esse deve ser o longo corredor. Ou isso ou o meu senso de escala foi pro saco.,,"Ăsta trebuie să fie holul lung. Fie asta, fie capacitatea mea de a aprecia scara e varză.","Должно быть, длинный коридор — это здесь. Ну или у меня всё плохо с глазомером.",,Det här måste vara den långa korridoren. Antingen det eller så är min skalförståelse helt borta.,Burası uzun koridor olmalı. Ya öyle ya da benim ölçek algım cehenneme döndü. "This is all the hallmarks of a temple of evil. Severe architecture, big banner... I'd say bingo!",TXT_SUB_LOG42,MAP07: Northeast bulding.,,,"Tohle jsou všechno puncy chrámu zla - hrubá architektura, velký prapor... řekla bych, že bingo!","Dette er alle kendetegnene på et ondskabens tempel. Alvorlig arkitektur, stort banner... Jeg ville sige bingo!","Das sind alles die Zeichen für einen Tempel des Bösen. Strenge Architektur, große Banner... Ich würde sagen: „Bingo!“",,,"Esto tiene toda la pinta de un templo maligno. Arquitectura austera, gran estandarte... ¡Yo diría bingo!",,"Tämä täyttää pahuuden temppelin kaikki tunnusmerkit: tuima arkkitehtuuri, suuri tunnuslippu... Sanoisin, että bingo!","Ca a le décor d'un temple maléfique.. Architecture sinistre, énorme bannière, je dis bingo!","Ha gonosz templom lennék, így néznék ki. Kimért architektúra, óriási lobogó... amondó vagyok megleltük.","Questo ha proprio tutti i tratti di un tempio del male. Architettura minacciosa, grosso stemma... Io direi che abbiamo fatto centro!","これら全部悪の神殿の特徴だ。重苦しい建築物、デカいバナー... -ビンゴだわ!","악당 같은 요소가 모인 건물이네! 엄격한 건물 구조, 커다란 기... 완전 만장일치야.","Dit zijn alle kenmerken van een tempel van het kwaad. Strenge architectuur, grote spandoeken.... Ik zou zeggen bingo!","Dette er alle kjennetegnene på et ondskapens tempel. Streng arkitektur, stort banner... Jeg vil si bingo!","To wszystko ma znamiona świątyni zła. Surowa architektura, wielki baner... Powiedziałbym, że bingo!","Isso tem bem cara de templo malígno. Arquitetura sinístra, estandarte grande... Acho que acertamos na mosca!",,"Ăsta e însemnul unui templu malefic. Arhitectura, steagurile... Eu zic bingo!","Всё это очень похоже на зловещий храм. Строгая архитектура, огромное знамя... Да, это определённо он!",,"Burası bir şeytan tapınağının tüm özelliklerini taşıyor. Sert mimari, büyük afiş. Bingo derdim!" -This is the almighty Programmer? No way!,TXT_SUB_LOG43,,,,Tohle je ten všemocný Programátor? To není možné!,Er dette den almægtige programmør? Det kan ikke passe!,Das ist der allmächtige Programmierer? Niemals!,,,¿Este es el todopoderoso Programador? ¡Ni hablar!,,Tämäkö muka kaikkivoipa Ohjelmoitsija? Ei todellakaan!,Ca c'est le surpuissant Programmeur? Vraiment?,Ez a hírhedt Progamozó? Nincs az az isten!,Sarebbe questo il potente Programmatore? Non è possibile!,,저게 위대한 프로그래머라고? 말도 안 돼!,Dit is de almachtige programmeur? Echt niet!,Er dette den allmektige programmereren? Aldri i livet!,To jest wszechmocny Programista? Nie ma mowy!,Esse é o Programador todo-poderoso? Tá de sacanagem comigo!,,Ăsta e marele Programator? Nici vorbă!,Вот это — всемогущий Программист? Быть не может!,,Bu yüce Programcı mı? Yok artık! -"I don't know what to believe anymore. The only thing that says ""keep"" to me is that huge monstrosity to the left. But I have no idea how to get in. ",TXT_SUB_LOG44,,,,"Už nevím, čemu věřit. Jediné, co mi říká „pevnost“, je tamta obří hrůza nalevo. Ale nemám tušení, jak se dostat dovnitř.","Jeg ved ikke længere, hvad jeg skal tro. Det eneste, der siger mig ""beholde"", er det store uhyre til venstre. Men jeg har ingen idé om, hvordan jeg kommer ind.","Ich weiß nicht mehr, was ich glauben soll. Das einzige, was ein „Tempel“ sein könnte, ist diese riesige Monströsität da drüben links. Aber ich wüßte nicht wie wir da rein kämen. ",,,"Ya no sé qué creer. Lo único que me dice ""torreón"" es esa monstruosidad enorme a la izquierda. Pero no tengo ni idea de como entrar.",,"En tiedä enää, mitä uskoa. Ainoa asia, joka näyttäytyy minulle ""linnakkeena"", on tuo valtava rumilus vasemmalla. Mutta minulla ei ole aavistustakaan, miten päästä sisään.","Je ne sais pas quoi penser maintenant. Le seul truc qui sonne comme ""donjon"" pour moi c'est l'énorme monstrosité à gauche, mais je ne sais pas comment y entrer.",Nem tudom mit kéne hinnem már. Az egyetlen vártorony szerűség a bal oldalt levő szörnyűség. Ötletem sincs hogy juthatnánk be.,"Non so più a cosa credere. L'unica cosa che mi dice ""fortezza"" è quell'enorme mostruosità alla sinistra, ma non so come entrarvi.",,이젠 누가 맞는 건지 생각이 전혀 안나. “성채”라고 말하는 곳은 분명히 저 왼쪽에 있는 커다란 건물일 거야. 그런데 그곳으로 어떻게 들어가야 하지?,"Ik weet niet meer wat ik moet geloven. Het enige dat tegen mij zegt ""houd"" is dat grote gedrocht aan de linkerkant. Maar ik heb geen idee hoe ik binnen kan komen.","Jeg vet ikke hva jeg skal tro lenger. Det eneste som sier ""hold"" til meg er den enorme monstrøsiteten til venstre. Men jeg aner ikke hvordan jeg skal komme meg inn.","Już nie wiem, w co wierzyć. Jedyne co mówi mi ""trzymaj"" to ta ogromna potworność po lewej stronie. Ale nie mam pojęcia, jak się tam dostać.",Eu não sei mais no que acreditar. A única coisa que parece uma fortaleza pra mim é aquela monstrosidade à esquerda. Mas não faço a menor idéia de como entrar.,,"Nu știu ce să mai cred. Singurul lucru care îmi spune ""curte"" e acea monstruozitate la stânga. Dar n-am idee cum să intrăm.","Не знаю, кому и верить. По-моему, «Цитаделью» можно назвать только ту уродливую громадину слева. Но как туда попасть, я понятия не имею.",,"Artık neye inanacağımı bilmiyorum. Bana ""kalsın"" diyen tek şey soldaki devasa canavar. Ama nasıl gireceğimi bilmiyorum." +ビンゴだわ!","악당 같은 요소가 모인 건물이네! 엄격한 건물 구조, 커다란 기... 완전 만장일치야.","Dit zijn alle kenmerken van een tempel van het kwaad. Strenge architectuur, grote spandoeken.... Ik zou zeggen bingo!","Dette er alle kjennetegnene på et ondskapens tempel. Streng arkitektur, stort banner... Jeg vil si bingo!","To wszystko ma znamiona świątyni zła. Surowa architektura, wielki baner... Powiedziałbym, że bingo!","Isso tem bem cara de templo malígno. Arquitetura sinístra, estandarte grande... Acho que acertamos na mosca!",,"Ăsta e însemnul unui templu malefic. Arhitectura, steagurile... Eu zic bingo!","Всё это очень похоже на зловещий храм. Строгая архитектура, огромное знамя... Да, это определённо он!",,"Det här har alla kännetecken på ett ondskans tempel. Stark arkitektur, stora banderoller... Jag skulle säga bingo!","Burası bir şeytan tapınağının tüm özelliklerini taşıyor. Sert mimari, büyük afiş. Bingo derdim!" +This is the almighty Programmer? No way!,TXT_SUB_LOG43,,,,Tohle je ten všemocný Programátor? To není možné!,Er dette den almægtige programmør? Det kan ikke passe!,Das ist der allmächtige Programmierer? Niemals!,,,¿Este es el todopoderoso Programador? ¡Ni hablar!,,Tämäkö muka kaikkivoipa Ohjelmoitsija? Ei todellakaan!,Ca c'est le surpuissant Programmeur? Vraiment?,Ez a hírhedt Progamozó? Nincs az az isten!,Sarebbe questo il potente Programmatore? Non è possibile!,,저게 위대한 프로그래머라고? 말도 안 돼!,Dit is de almachtige programmeur? Echt niet!,Er dette den allmektige programmereren? Aldri i livet!,To jest wszechmocny Programista? Nie ma mowy!,Esse é o Programador todo-poderoso? Tá de sacanagem comigo!,,Ăsta e marele Programator? Nici vorbă!,Вот это — всемогущий Программист? Быть не может!,,Är detta den allsmäktige programmeraren? Inte en chans!,Bu yüce Programcı mı? Yok artık! +"I don't know what to believe anymore. The only thing that says ""keep"" to me is that huge monstrosity to the left. But I have no idea how to get in. ",TXT_SUB_LOG44,,,,"Už nevím, čemu věřit. Jediné, co mi říká „pevnost“, je tamta obří hrůza nalevo. Ale nemám tušení, jak se dostat dovnitř.","Jeg ved ikke længere, hvad jeg skal tro. Det eneste, der siger mig ""beholde"", er det store uhyre til venstre. Men jeg har ingen idé om, hvordan jeg kommer ind.","Ich weiß nicht mehr, was ich glauben soll. Das einzige, was ein „Tempel“ sein könnte, ist diese riesige Monströsität da drüben links. Aber ich wüßte nicht wie wir da rein kämen. ",,,"Ya no sé qué creer. Lo único que me dice ""torreón"" es esa monstruosidad enorme a la izquierda. Pero no tengo ni idea de como entrar.",,"En tiedä enää, mitä uskoa. Ainoa asia, joka näyttäytyy minulle ""linnakkeena"", on tuo valtava rumilus vasemmalla. Mutta minulla ei ole aavistustakaan, miten päästä sisään.","Je ne sais pas quoi penser maintenant. Le seul truc qui sonne comme ""donjon"" pour moi c'est l'énorme monstrosité à gauche, mais je ne sais pas comment y entrer.",Nem tudom mit kéne hinnem már. Az egyetlen vártorony szerűség a bal oldalt levő szörnyűség. Ötletem sincs hogy juthatnánk be.,"Non so più a cosa credere. L'unica cosa che mi dice ""fortezza"" è quell'enorme mostruosità alla sinistra, ma non so come entrarvi.",,이젠 누가 맞는 건지 생각이 전혀 안나. “성채”라고 말하는 곳은 분명히 저 왼쪽에 있는 커다란 건물일 거야. 그런데 그곳으로 어떻게 들어가야 하지?,"Ik weet niet meer wat ik moet geloven. Het enige dat tegen mij zegt ""houd"" is dat grote gedrocht aan de linkerkant. Maar ik heb geen idee hoe ik binnen kan komen.","Jeg vet ikke hva jeg skal tro lenger. Det eneste som sier ""hold"" til meg er den enorme monstrøsiteten til venstre. Men jeg aner ikke hvordan jeg skal komme meg inn.","Już nie wiem, w co wierzyć. Jedyne co mówi mi ""trzymaj"" to ta ogromna potworność po lewej stronie. Ale nie mam pojęcia, jak się tam dostać.",Eu não sei mais no que acreditar. A única coisa que parece uma fortaleza pra mim é aquela monstrosidade à esquerda. Mas não faço a menor idéia de como entrar.,,"Nu știu ce să mai cred. Singurul lucru care îmi spune ""curte"" e acea monstruozitate la stânga. Dar n-am idee cum să intrăm.","Не знаю, кому и верить. По-моему, «Цитаделью» можно назвать только ту уродливую громадину слева. Но как туда попасть, я понятия не имею.",,"Jag vet inte vad jag ska tro längre. Det enda som säger ""behåll"" för mig är det enorma monstret till vänster. Men jag har ingen aning om hur jag ska ta mig in.","Artık neye inanacağımı bilmiyorum. Bana ""kalsın"" diyen tek şey soldaki devasa canavar. Ama nasıl gireceğimi bilmiyorum." "When the going gets weird, the weird get going. Watch yourself.",TXT_SUB_LOG45,"MAP09: Entrance. -(Probably a reference to Hunter S. Thompson’s quote, “When the going gets weird, the weird turn pro.”)",,,Divné klima lahodí podivínům. Dávej si na sebe pozor.,"Når det bliver mærkeligt, så bliver det mærkelige også mærkeligt. Pas på dig selv.",Die ganze Sache kommt mir spanisch vor. Pass auf dich auf.,,,La cosa se está poniendo fea. Ten cuidado.,Esto se va a poner feo. Ve con cuidado.,"Kun meininki muuttuu kummaksi, kummat alkavat meinata. Pidä varasi.","Quand les choses tournent au pire, le pire se tourne vers nous.. Fais attention à toi.",Egy fura világban furának kell lenned. Vigyázz magadra.,"Quando il gioco si fa strano, quelli strani si mettono in gioco. Fai attenzione.",怪しい状況では怪しい影が映る。気を付けて。,"상황이 이상해지면, 이상한 일이 계속 일어난다니까... 부디 조심해.","Als het gaat raar wordt, gaat het vreemde aan de slag. Kijk uit.","Når det blir merkelig, blir det merkelige merkelig. Vær forsiktig.","Kiedy robi się dziwnie, dziwacy zaczynają się ruszać. Uważaj na siebie.",A coisa tá ficando feia. Toma cuidado.,,"Cand lucrurile devin ciudate, ai grija.","Если видишь, что что-то не так, остановись и подумай. Будь осторожен.",,"İşler garipleştiğinde, garipler de gider. Kendine dikkat et." -"The Oracle resides in the borderlands, just outside of town. Cross the river, head towards the castle and go left through the archway.",TXT_SUB_LOG46,,,,"Věštec přebývá v pohraničí, hned za městem. Překroč řeku, zamiř k hradu a jdi vlevo pod obloukem.","Oraklet befinder sig i grænselandet, lige uden for byen. Kryds floden, gå mod slottet og gå til venstre gennem buegangen.","Das Orakel hält sich in den Grenzgebieten auf, direkt vor der Stadt. Überquere den Fluss, gehe in Richtung Burg und dann links durchs Tor.",,,"El Oráculo reside en las fronteras, justo fuera del pueblo. Cruza el río, dirígete al castillo y ve a la izquierda a través del arco.",,"Oraakkeli asuu rajamailla aivan kaupungin liepeillä. Ylitä joki, kulje kohti linnaa ja mene vasemmalle kaarikäytävän läpi.","L'Oracle se trouve dans les terrains vagues, à l'extérieur de la ville. Traverse la rivière, va vers le château et à gauche à travers l'arche.","Az Orákulum a peremvidéken tartózkodik, rögtön a városhatárokon túl. Elhagyva a folyót, menj a kastély irányába és fordulj balra a boltívnél.","L'Oracolo risiede nelle terre di confine, subito dopo la città. Attraversa il fiume, vai nella direzione del castello e poi a sinistra oltre l'arco.",,"오라클은 도시 외곽에 있는 접경지 근처에 있어. 강을 넘은 뒤, 성 쪽으로 향하고 아치 밑의 통로를 통해 왼쪽으로 이동해.","Het Orakel woont in de grensgebieden, net buiten de stad. Steek de rivier over, ga naar het kasteel en ga linksaf door de poort.","Orakelet ligger i grenselandet, like utenfor byen. Kryss elven, gå mot slottet og gå til venstre gjennom buegangen.","Wyrocznia mieszka na pograniczu, tuż za miastem. Przejdź przez rzekę, skieruj się w stronę zamku i przejdź w lewo przez łuki.","O Oráculo reside nas fronteiras do lado de fora da cidade. Atravesse o rio, vá em direção ao catelo e vá para a esquerda através do arco.",,"Oracolul locuiește în mărginime, chiar la ieșirea orașului. Treci râul, du-te spre castle, și treci prin arcadă.","Резиденция Оракула находится в пограничье, сразу за городской чертой. Пересеки реку, иди в сторону крепости и сверни налево, пройдя через арку.",,"Kahin, kasabanın hemen dışındaki sınır bölgesinde bulunuyor. Nehri geç, kaleye doğru git ve kemerden sola dön." -The Oracle is a supposedly sympathetic high priest who operates outside the Order.,TXT_SUB_LOG47,MAP02: Castle's entrance (MAP10).,,,"Věštec je údajně sympatizující velekněz, operující mimo samotný Řád.","Oraklet er en formodet sympatisk ypperstepræst, der opererer uden for ordenen.","Das Orakel ist ein angeblich verständnisvoller Hohepriester, der außerhalb des Ordens tätig ist.",,,El Oráculo es supuestamente un amable alto sacerdote que opera fuera de la Orden.,,"Oraakkeli on tiettävästi aatteellemme myötämielinen ylipappi, joka toimii Veljeskunnan vaikutuspiirin ulkopuolella.",L'Oracle est supposément un grand prêtre bienveillant qui opère hors du domaine de l'Ordre.,"Az Orákulum állítólag egy megértő főpap, aki nem tartozik a Rend rendjéhez.",L'Oracolo è un alto sacerdote apparentemente approciabile che opera al di fuori dell'Ordine.,オラクルはオーダーとは別の活動をしている同情的な大司祭よ。,"오라클은 인류에 동정을 가지고 있다고 하고, 오더의 바깥에서 활동하는 대사제야.",Het Orakel is een zogenaamd sympathieke hogepriester die buiten de Orde opereert.,Oraklet er en angivelig sympatisk yppersteprest som opererer utenfor ordenen.,"Wyrocznia jest rzekomo sympatycznym arcykapłanem, który działa poza Zakonem.",O Oráculo é supostamente um grande sacerdote benevolente que opera fora da Ordem.,,"Oracolul e un preot care simpatizează cu noi, și care se spune că operează din afara Ordinului.","Похоже, этот Оракул — сочувствующий Сопротивлению верховный жрец, который действует без ведома Ордена.",,"Kahin, Düzen'in dışında faaliyet gösteren sözde sempatik bir baş rahiptir." -"The Oracle's temple is in the Borderlands, on the outskirts of town.",TXT_SUB_LOG48,MAP10: After talking to Macil and moving a bit.,,,"Věštcův chrám je v pohraničí, na okraji města.","Oraklets tempel ligger i grænselandet, i udkanten af byen.","Der Tempel des Orakels ist in den Grenzgebieten, direkt vor der Stadt.",,,"El templo del Oráculo está en las Fronteras, a las afueras del pueblo.",,Oraakkelin temppeli sijaitsee rajaseudulla kaupungin laitamilla.,Le temple de l'Oracle se trouve dans les terrains vagues à l'extérieur de la ville.,Az Orákulum temploma a határvidéken található a külvárosban.,"Il tempio dell'Oracolo è nelle terre di confine, fuori città.",オラクルの寺院は町の郊外にある国境地帯の西側にあるわ。,오라클은 도시 외곽에 있는 접경지 근처에 있어.,"De tempel van het Orakel staat in de grensstreek van Nederland, aan de rand van de stad.","Orakelets tempel ligger i Grenselandene, i utkanten av byen.","Świątynia Wyroczni znajduje się na Kresach, na obrzeżach miasta.","O tempo do Oráculo está nas fronteiras, fora da cidade.",,"Templul Oracolului e în Mărginime, la ieșirea din oraș.","Храм Оракула находится в пограничье, на окраине города.",,"Kahin'in tapınağı Sınır Toprakları'nda, şehrin eteklerinde." -The Order has taken our beautiful planet and turned it into a dump.,TXT_SUB_LOG49,MAP11: Entrance.,,,Řád vzal naši krásnou planetu a proměnil ji ve skládku.,Ordenen har taget vores smukke planet og forvandlet den til en losseplads.,Der Orden hat unseren schönen Planeten in einen Müllplatz verwandelt.,,,La Orden ha tomado nuestro bello planeta y lo ha convertido en un vertedero.,,Veljeskunta on riistänyt planeettamme ja tehnyt siitä kaatopaikan.,L'Ordre a pris notre belle planète et la transformée en dépotoir.,"A Rend kizsigerelte ezt a gyönyörű bolygót, és egy lepratelepet csinált belőle.",L'Ordine ha preso il nostro bellissimo pianeta e l'ha trasformato in una discarica.,オーダーは我々の立つこの惑星を奪い、それをゴミへと変えた。,오더가 이 이쁘고 푸른 행성을 완전 쓰레기장으로 만들어버렸어...,De Orde heeft onze mooie planeet in beslag genomen en er een vuilnisbelt van gemaakt.,Ordenen har tatt vår vakre planet og gjort den til en søppelplass.,Zakon zabrał naszą piękną planetę i zamienił ją w wysypisko śmieci.,A Ordem transformou este lindo planeta em um depósito de lixo.,,Ordinul ne-a luat planeta minunată și a transformat-o într-o groapă de gunoi.,Орден превратил нашу прекрасную планету в помойку.,,Tarikat güzel gezegenimizi aldı ve onu bir çöplüğe çevirdi. +(Probably a reference to Hunter S. Thompson’s quote, “When the going gets weird, the weird turn pro.”)",,,Divné klima lahodí podivínům. Dávej si na sebe pozor.,"Når det bliver mærkeligt, så bliver det mærkelige også mærkeligt. Pas på dig selv.",Die ganze Sache kommt mir spanisch vor. Pass auf dich auf.,,,La cosa se está poniendo fea. Ten cuidado.,Esto se va a poner feo. Ve con cuidado.,"Kun meininki muuttuu kummaksi, kummat alkavat meinata. Pidä varasi.","Quand les choses tournent au pire, le pire se tourne vers nous.. Fais attention à toi.",Egy fura világban furának kell lenned. Vigyázz magadra.,"Quando il gioco si fa strano, quelli strani si mettono in gioco. Fai attenzione.",怪しい状況では怪しい影が映る。気を付けて。,"상황이 이상해지면, 이상한 일이 계속 일어난다니까... 부디 조심해.","Als het gaat raar wordt, gaat het vreemde aan de slag. Kijk uit.","Når det blir merkelig, blir det merkelige merkelig. Vær forsiktig.","Kiedy robi się dziwnie, dziwacy zaczynają się ruszać. Uważaj na siebie.",A coisa tá ficando feia. Toma cuidado.,,"Cand lucrurile devin ciudate, ai grija.","Если видишь, что что-то не так, остановись и подумай. Будь осторожен.",,"När det blir konstigt, blir det konstiga som går. Se upp för dig själv.","İşler garipleştiğinde, garipler de gider. Kendine dikkat et." +"The Oracle resides in the borderlands, just outside of town. Cross the river, head towards the castle and go left through the archway.",TXT_SUB_LOG46,,,,"Věštec přebývá v pohraničí, hned za městem. Překroč řeku, zamiř k hradu a jdi vlevo pod obloukem.","Oraklet befinder sig i grænselandet, lige uden for byen. Kryds floden, gå mod slottet og gå til venstre gennem buegangen.","Das Orakel hält sich in den Grenzgebieten auf, direkt vor der Stadt. Überquere den Fluss, gehe in Richtung Burg und dann links durchs Tor.",,,"El Oráculo reside en las fronteras, justo fuera del pueblo. Cruza el río, dirígete al castillo y ve a la izquierda a través del arco.",,"Oraakkeli asuu rajamailla aivan kaupungin liepeillä. Ylitä joki, kulje kohti linnaa ja mene vasemmalle kaarikäytävän läpi.","L'Oracle se trouve dans les terrains vagues, à l'extérieur de la ville. Traverse la rivière, va vers le château et à gauche à travers l'arche.","Az Orákulum a peremvidéken tartózkodik, rögtön a városhatárokon túl. Elhagyva a folyót, menj a kastély irányába és fordulj balra a boltívnél.","L'Oracolo risiede nelle terre di confine, subito dopo la città. Attraversa il fiume, vai nella direzione del castello e poi a sinistra oltre l'arco.",,"오라클은 도시 외곽에 있는 접경지 근처에 있어. 강을 넘은 뒤, 성 쪽으로 향하고 아치 밑의 통로를 통해 왼쪽으로 이동해.","Het Orakel woont in de grensgebieden, net buiten de stad. Steek de rivier over, ga naar het kasteel en ga linksaf door de poort.","Orakelet ligger i grenselandet, like utenfor byen. Kryss elven, gå mot slottet og gå til venstre gjennom buegangen.","Wyrocznia mieszka na pograniczu, tuż za miastem. Przejdź przez rzekę, skieruj się w stronę zamku i przejdź w lewo przez łuki.","O Oráculo reside nas fronteiras do lado de fora da cidade. Atravesse o rio, vá em direção ao catelo e vá para a esquerda através do arco.",,"Oracolul locuiește în mărginime, chiar la ieșirea orașului. Treci râul, du-te spre castle, și treci prin arcadă.","Резиденция Оракула находится в пограничье, сразу за городской чертой. Пересеки реку, иди в сторону крепости и сверни налево, пройдя через арку.",,"Oraklet bor i gränslandet, strax utanför staden. Korsa floden, gå mot slottet och gå till vänster genom valvet.","Kahin, kasabanın hemen dışındaki sınır bölgesinde bulunuyor. Nehri geç, kaleye doğru git ve kemerden sola dön." +The Oracle is a supposedly sympathetic high priest who operates outside the Order.,TXT_SUB_LOG47,MAP02: Castle's entrance (MAP10).,,,"Věštec je údajně sympatizující velekněz, operující mimo samotný Řád.","Oraklet er en formodet sympatisk ypperstepræst, der opererer uden for ordenen.","Das Orakel ist ein angeblich verständnisvoller Hohepriester, der außerhalb des Ordens tätig ist.",,,El Oráculo es supuestamente un amable alto sacerdote que opera fuera de la Orden.,,"Oraakkeli on tiettävästi aatteellemme myötämielinen ylipappi, joka toimii Veljeskunnan vaikutuspiirin ulkopuolella.",L'Oracle est supposément un grand prêtre bienveillant qui opère hors du domaine de l'Ordre.,"Az Orákulum állítólag egy megértő főpap, aki nem tartozik a Rend rendjéhez.",L'Oracolo è un alto sacerdote apparentemente approciabile che opera al di fuori dell'Ordine.,オラクルはオーダーとは別の活動をしている同情的な大司祭よ。,"오라클은 인류에 동정을 가지고 있다고 하고, 오더의 바깥에서 활동하는 대사제야.",Het Orakel is een zogenaamd sympathieke hogepriester die buiten de Orde opereert.,Oraklet er en angivelig sympatisk yppersteprest som opererer utenfor ordenen.,"Wyrocznia jest rzekomo sympatycznym arcykapłanem, który działa poza Zakonem.",O Oráculo é supostamente um grande sacerdote benevolente que opera fora da Ordem.,,"Oracolul e un preot care simpatizează cu noi, și care se spune că operează din afara Ordinului.","Похоже, этот Оракул — сочувствующий Сопротивлению верховный жрец, который действует без ведома Ордена.",,Oraklet är en förmodat sympatisk överstepräst som verkar utanför orden.,"Kahin, Düzen'in dışında faaliyet gösteren sözde sempatik bir baş rahiptir." +"The Oracle's temple is in the Borderlands, on the outskirts of town.",TXT_SUB_LOG48,MAP10: After talking to Macil and moving a bit.,,,"Věštcův chrám je v pohraničí, na okraji města.","Oraklets tempel ligger i grænselandet, i udkanten af byen.","Der Tempel des Orakels ist in den Grenzgebieten, direkt vor der Stadt.",,,"El templo del Oráculo está en las Fronteras, a las afueras del pueblo.",,Oraakkelin temppeli sijaitsee rajaseudulla kaupungin laitamilla.,Le temple de l'Oracle se trouve dans les terrains vagues à l'extérieur de la ville.,Az Orákulum temploma a határvidéken található a külvárosban.,"Il tempio dell'Oracolo è nelle terre di confine, fuori città.",オラクルの寺院は町の郊外にある国境地帯の西側にあるわ。,오라클은 도시 외곽에 있는 접경지 근처에 있어.,"De tempel van het Orakel staat in de grensstreek van Nederland, aan de rand van de stad.","Orakelets tempel ligger i Grenselandene, i utkanten av byen.","Świątynia Wyroczni znajduje się na Kresach, na obrzeżach miasta.","O tempo do Oráculo está nas fronteiras, fora da cidade.",,"Templul Oracolului e în Mărginime, la ieșirea din oraș.","Храм Оракула находится в пограничье, на окраине города.",,"Oraklets tempel ligger i gränslandet, i utkanten av staden.","Kahin'in tapınağı Sınır Toprakları'nda, şehrin eteklerinde." +The Order has taken our beautiful planet and turned it into a dump.,TXT_SUB_LOG49,MAP11: Entrance.,,,Řád vzal naši krásnou planetu a proměnil ji ve skládku.,Ordenen har taget vores smukke planet og forvandlet den til en losseplads.,Der Orden hat unseren schönen Planeten in einen Müllplatz verwandelt.,,,La Orden ha tomado nuestro bello planeta y lo ha convertido en un vertedero.,,Veljeskunta on riistänyt planeettamme ja tehnyt siitä kaatopaikan.,L'Ordre a pris notre belle planète et la transformée en dépotoir.,"A Rend kizsigerelte ezt a gyönyörű bolygót, és egy lepratelepet csinált belőle.",L'Ordine ha preso il nostro bellissimo pianeta e l'ha trasformato in una discarica.,オーダーは我々の立つこの惑星を奪い、それをゴミへと変えた。,오더가 이 이쁘고 푸른 행성을 완전 쓰레기장으로 만들어버렸어...,De Orde heeft onze mooie planeet in beslag genomen en er een vuilnisbelt van gemaakt.,Ordenen har tatt vår vakre planet og gjort den til en søppelplass.,Zakon zabrał naszą piękną planetę i zamienił ją w wysypisko śmieci.,A Ordem transformou este lindo planeta em um depósito de lixo.,,Ordinul ne-a luat planeta minunată și a transformat-o într-o groapă de gunoi.,Орден превратил нашу прекрасную планету в помойку.,,Orden har tagit vår vackra planet och förvandlat den till en soptipp.,Tarikat güzel gezegenimizi aldı ve onu bir çöplüğe çevirdi. "Here it is. I'm recording everything, it's not that I don't have faith that you'll survive, it's just that we can't let the Order control the Sigil.",TXT_SUB_LOG50,MAP11: Entrance to cave.,,,"Tady to je. Všechno nahrávám, ne že bych neměla důvěru v tvé přežití, ale prostě nemůžeme dovolit Řádu ovládat Pečeť.","Her er den. Jeg optager alt, det er ikke fordi jeg ikke tror på, at I vil overleve, men vi kan ikke lade Ordenen kontrollere Sigil.","Hier ist es. Ich zeichne alles auf, nicht dass ich kein Vertrauen in dich habe, aber wir können nicht erlauben, dass der Orden das Sigil kontrolliert.",,,"Aquí está. Lo estoy grabando todo, no es que tenga fe en que sobrevivas, es solo que no puedo dejar que la Orden controle el Emblema.",,"Tässä se on. Tallennan kaiken. Tässä ei ole kyse siitä, etteikö minulla olisi täysi luotto, että selviäisit. Emme vain voi antaa Veljeskunnan hallita Sinettiä.","Voilà, j'enregistre tout. C'est pas qu'on a pas confiance en toi, c'est juste que on ne peut pas laisser l'Ordre contrôler le Sigil.","Itt is van. Minden felveszek, nem azért mert nem bíznék benned, csak ne kerüljön a Rend kezébe a pecsét.",Ecco qua. Sto registrando tutto. Non è che non penso che sopravviverai. È solo che non possiamo lasciare che l'Ordine controlli il Sigillo.,"ここよ。私は全て記録している、貴方が生き残れる可能性が無いわけではなく、 -オーダー如きにシジルを制御できるわけがないという事だ。","여기야. 난 지금 모든 걸 녹음하고 있어. 네가 살아남을 거라는 믿음을 버린게 아니라, 오더가 시질을 손에 잡게 내버려 둘 수가 없어서 말이야.","Hier is het. Ik ben alles aan het opnemen, het is niet dat ik geen vertrouwen heb dat je het zult overleven, maar het is gewoon dat we de Orde de Sigil niet kunnen laten controleren door de Orde.","Her er det. Jeg tar opp alt, det er ikke det at jeg ikke har tro på at du vil overleve, men vi kan ikke la Ordenen kontrollere sigillet.","Oto ona. Nagrywam wszystko, to nie tak, że nie mam wiary, że przeżyjesz, po prostu nie możemy pozwolić, by Zakon kontrolował Sigil.","Certo, estou gravando tudo. Não é que eu não tenha fé de que você vá sobreviver, mas não podemos deixar a Ordem controlar o Sigilo.",,"Aici e. Înregistrez totul. Nu e vorba c nu vei supraviețui, dar nu putem permite Ordinului să controleze Sigiliul.","Так. Я всё записываю на плёнку. Это не потому, что я не верю, что ты уцелеешь. Просто мы не можем позволить Ордену заполучить Печать.",,"İşte burası. Her şeyi kaydediyorum, hayatta kalacağınıza inanmadığımdan değil, sadece Düzen'in Sigil'i kontrol etmesine izin veremeyiz." -"You are brave, my comrade. I'm proud to be along for the ride.",TXT_SUB_LOG51,MAP12: Bridge to sanctum's normal entrance.,,,"Jsi statečný, můj příteli. Jsem pyšná, že u tohohle můžu být.","Du er modig, min kammerat. Jeg er stolt af at være med på turen.","Du bist tapfer, mein Kamerad. Ich bin stolz darauf, mit von der Partie zu sein.",,,"Eres valiente, mi camarada. Estoy orgullosa de acompañarte.",,"Olet urhea, toverini. Olen ylpeä, että saan olla matkassa mukana.","Tu est courageux, mon camarade, je suis fière de te suivre.","Felettébb bátor vagy bajtárs. Büszke vagyok, hogy veled harcolhatok.","Sei coraggioso, compagno. Sono orgogliosa di essere insieme a te in questo viaggio.",貴方は勇敢で、私の同志。貴方に就けた事を私は誇りに思ってるわ。,"넌 정말 용맹해, 동지. 너랑 같이 일할 수 있는 게 정말 자랑스러워.","Je bent dapper, mijn kameraad. Ik ben er trots op dat ik meega voor de rit.","Du er modig, min kamerat. Jeg er stolt over å være med på turen.","Jesteś odważny, mój towarzyszu. Jestem dumny, że mogę być przy tobie.","Você é corajoso, meu companheiro. Tenho orgulho de estar junto com você.",,"Ești viteaz, soldatul meu. Sunt mândru să lupt alături de tne.","Я хотела сказать тебе, что ты очень храбрый. Я так счастлива, что мне с тобой по пути.",,"Cesursun, yoldaşım. Seninle birlikte olmaktan gurur duyuyorum." +オーダー如きにシジルを制御できるわけがないという事だ。","여기야. 난 지금 모든 걸 녹음하고 있어. 네가 살아남을 거라는 믿음을 버린게 아니라, 오더가 시질을 손에 잡게 내버려 둘 수가 없어서 말이야.","Hier is het. Ik ben alles aan het opnemen, het is niet dat ik geen vertrouwen heb dat je het zult overleven, maar het is gewoon dat we de Orde de Sigil niet kunnen laten controleren door de Orde.","Her er det. Jeg tar opp alt, det er ikke det at jeg ikke har tro på at du vil overleve, men vi kan ikke la Ordenen kontrollere sigillet.","Oto ona. Nagrywam wszystko, to nie tak, że nie mam wiary, że przeżyjesz, po prostu nie możemy pozwolić, by Zakon kontrolował Sigil.","Certo, estou gravando tudo. Não é que eu não tenha fé de que você vá sobreviver, mas não podemos deixar a Ordem controlar o Sigilo.",,"Aici e. Înregistrez totul. Nu e vorba c nu vei supraviețui, dar nu putem permite Ordinului să controleze Sigiliul.","Так. Я всё записываю на плёнку. Это не потому, что я не верю, что ты уцелеешь. Просто мы не можем позволить Ордену заполучить Печать.",,"Här är den. Jag spelar in allting, det är inte så att jag inte tror på att du kommer att överleva, det är bara det att vi inte kan låta Orden kontrollera Sigil.","İşte burası. Her şeyi kaydediyorum, hayatta kalacağınıza inanmadığımdan değil, sadece Düzen'in Sigil'i kontrol etmesine izin veremeyiz." +"You are brave, my comrade. I'm proud to be along for the ride.",TXT_SUB_LOG51,MAP12: Bridge to sanctum's normal entrance.,,,"Jsi statečný, můj příteli. Jsem pyšná, že u tohohle můžu být.","Du er modig, min kammerat. Jeg er stolt af at være med på turen.","Du bist tapfer, mein Kamerad. Ich bin stolz darauf, mit von der Partie zu sein.",,,"Eres valiente, mi camarada. Estoy orgullosa de acompañarte.",,"Olet urhea, toverini. Olen ylpeä, että saan olla matkassa mukana.","Tu est courageux, mon camarade, je suis fière de te suivre.","Felettébb bátor vagy bajtárs. Büszke vagyok, hogy veled harcolhatok.","Sei coraggioso, compagno. Sono orgogliosa di essere insieme a te in questo viaggio.",貴方は勇敢で、私の同志。貴方に就けた事を私は誇りに思ってるわ。,"넌 정말 용맹해, 동지. 너랑 같이 일할 수 있는 게 정말 자랑스러워.","Je bent dapper, mijn kameraad. Ik ben er trots op dat ik meega voor de rit.","Du er modig, min kamerat. Jeg er stolt over å være med på turen.","Jesteś odważny, mój towarzyszu. Jestem dumny, że mogę być przy tobie.","Você é corajoso, meu companheiro. Tenho orgulho de estar junto com você.",,"Ești viteaz, soldatul meu. Sunt mândru să lupt alături de tne.","Я хотела сказать тебе, что ты очень храбрый. Я так счастлива, что мне с тобой по пути.",,"Du är modig, min kamrat. Jag är stolt över att vara med på resan.","Cesursun, yoldaşım. Seninle birlikte olmaktan gurur duyuyorum." Could you pause for a second? I'm getting a little sick.,TXT_SUB_LOG52,"(Strife: Veteran Edition) -Random comment when the player dies with Classic Mode turned off",,,Mohl by ses na chvíli zastavit? Bude mi zle.,Kan du holde en pause et øjeblik? Jeg er ved at få det lidt dårligt.,Kannst du mal kurz warten? Mir wird etwas übel.,,,¿Puedes parar un segundo? Que me estoy mareando.,,Voisitko pysähtyä hetkeksi? Alan voida hieman pahoin.,Tu peux t'arrêter pour un moment? J'ai l'impression d'avoir la nausée.,Meg tudnál állni egy pillanatra? Elég rosszul vagyok.,Puoi fermarti per un secondo? Mi sento un pò nauseata.,ちょっと待ってもらえる?少しばかりうんざりしてるわ。,잠깐만 멈춰줄래? 속이 울렁거려...,Kun je even pauzeren? Ik word een beetje ziek.,Kan du ta en pause? Jeg begynner å bli litt kvalm.,Możesz się zatrzymać na chwilę? Robi mi się trochę niedobrze.,Pode parar por um minuto? Estou ficando com enjôo.,,Poți să te opreși un moment? Mi se face rău.,Мы можем остановиться на секунду? Что-то мне дурно.,,Bir saniye durabilir misin? Biraz midem bulanıyor. -Why do we have to spend so much time underground? I've seen underground.,TXT_SUB_LOG53,MAP12: Downstairs.,,,Proč musíme tolik času strávit v podzemí? Podzemí jsem viděla.,Hvorfor skal vi tilbringe så meget tid under jorden? Jeg har set under jorden.,Warum müssen wir so viel Zeit im Untergrund verbringen.? Ich kenne den Untergrund.,,,¿Por que tenemos que pasar tanto tiempo bajo tierra? Ya lo tengo muy visto.,,Miksi olemme niin paljon maan alla? Nähty juttu.,Pourquoi on passe tout notre temps sous terre? J'ai déja tout vu sous terre.,Miért kell ilyen sok időt föld alatt töltenünk? Már láttam elég föld alatti részt.,Ma perché passiamo così tanto tempo sotto terra? Già conosco molto bene posti come questo.,何故私達は地下に長居せねばならないの?地下はもうわかったから。,왜 지하에서 시간을 낭비해야 되는 거지? 난 이미 지하에 있다고.,Waarom moeten we zoveel tijd onder de grond doorbrengen? Ik heb ondergronds gezien.,Hvorfor må vi tilbringe så mye tid under jorden? Jeg har sett undergrunnen.,Dlaczego musimy spędzać tyle czasu pod ziemią? Widziałem już podziemia.,Por que a gente tem que ficar tanto tempo no subterrâneo? Já vi bastante do subterrâneo.,,De ce trebuie să petrecem atâta timp sub pământ? Am văzut subteranul.,Почему нам приходится проводить кучу времени под землёй? Я на десять лет вперед насмотрелась на подземелья.,,Neden yeraltında bu kadar çok vakit geçirmek zorundayız? Yeraltını gördüm. -Are we really supposed to trust a guy whose inner sanctum is green?,TXT_SUB_LOG54,MAP12: Sanctum's normal entrance.,,,"Fakt máme věřit chlápkovi, jehož svatyně je zelená?","Skal vi virkelig stole på en fyr, hvis indre helligdom er grøn?","Sollen wir wirklich einem Typen vertrauen, dessen Räume grün sind?",,"Ĉu ni vere devas fidi al iu, kies sekreta templo estas verda?",¿En serio hay que fiarse de un tipo cuyo templo secreto es verde?,¿En serio hay que confiar en un tipo cuyo templo secreto es verde?,"Tuleeko meidän todella luottaa kaveriin, jolla on vihreä pyhäkkö?",On est vraiment obligé de faire confiance à un type qui a un sanctuaire peint en vert?,"Egy olyan ürgében kéne megbíznunk, akinek zöld színű a szentélye?",Davvero dovremmo fidarci di qualcuno che ha un santuario verde?,聖域内部と全身が緑色の者を信用するべきなの?,성소가 더럽게 초록색인데 이 녀석을 정말 믿어야 해?,Moeten we echt vertrouwen hebben in een man wiens innerlijke heiligdom groen is?,Skal vi virkelig stole på en fyr hvis indre er grønt?,"Czy naprawdę mamy ufać facetowi, którego wewnętrzne sanktuarium jest zielone?",Será que a gente deve mesmo confiar num cara cujo grande santuário é verde?,,Chiar ar trebui să avem încredere în cineva în cineva al cărui sanctuar e verde?,"Мы точно можем доверять парню, чьи внутренние покои зелёного цвета?",,Kutsal alanı yeşil olan bir adama gerçekten güvenmemiz mi gerekiyor? -Crimson and Obsidian? Why can't he say red and black.,TXT_SUB_LOG55,MAP12: After talking to the Oracle.,,,Karmíno-obsidiánová? Proč nemůže říct červeno-černá?,Purpur og Obsidian? Hvorfor kan han ikke sige rød og sort.,Purpur und Obsidian? Warum kann er nicht Rot und Schwarz sagen?,,Ĉu «karmezina kaj obsidiankolora»? Kial li ne diras «ruĝa kaj nigra»?,"¿«Carmesí y obsidiana»?, ¿tanto le cuesta decir «roja y negra»?",,Purppuranpunainen ja laavalasinen? Miksei hän voi sanoa punainen ja musta?,Cramoisi et obsidienne? Il peut pas dire juste rouge et noir?,"Karmazsin és obszidián? Miért nem tudja azt mondani, hogy piros és fekete.",Cremisina e ossidiana? Non bastava dire rossa e nera?,深紅と黒曜石?何故彼は赤と黒と言わないの。,진홍빛 흑요석? 빨간 검은색이라고 말하면 어디 덧나나?,Crimson en Obsidian? Waarom kan hij niet rood en zwart zeggen.,Purpur og Obsidian? Hvorfor kan han ikke si rødt og svart?,Karmazyn i Obsydian? Dlaczego nie może powiedzieć: czerwony i czarny.,Carmesim e Obsidiana? Por que ele não diz logo vermelho e preto?,,Străveziu și Obsidian? De ce nu poate spune roșu și negru.,Багрово-обсидиановая? Почему бы не сказать просто — «красно-чёрная»!,,Crimson ve Obsidian? Neden kırmızı ve siyah diyemiyor? +Random comment when the player dies with Classic Mode turned off",,,Mohl by ses na chvíli zastavit? Bude mi zle.,Kan du holde en pause et øjeblik? Jeg er ved at få det lidt dårligt.,Kannst du mal kurz warten? Mir wird etwas übel.,,,¿Puedes parar un segundo? Que me estoy mareando.,,Voisitko pysähtyä hetkeksi? Alan voida hieman pahoin.,Tu peux t'arrêter pour un moment? J'ai l'impression d'avoir la nausée.,Meg tudnál állni egy pillanatra? Elég rosszul vagyok.,Puoi fermarti per un secondo? Mi sento un po' nauseata.,ちょっと待ってもらえる?少しばかりうんざりしてるわ。,잠깐만 멈춰줄래? 속이 울렁거려...,Kun je even pauzeren? Ik word een beetje ziek.,Kan du ta en pause? Jeg begynner å bli litt kvalm.,Możesz się zatrzymać na chwilę? Robi mi się trochę niedobrze.,Pode parar por um minuto? Estou ficando com enjôo.,,Poți să te opreși un moment? Mi se face rău.,Мы можем остановиться на секунду? Что-то мне дурно.,,Kan du stanna upp en stund? Jag börjar bli lite sjuk.,Bir saniye durabilir misin? Biraz midem bulanıyor. +Why do we have to spend so much time underground? I've seen underground.,TXT_SUB_LOG53,MAP12: Downstairs.,,,Proč musíme tolik času strávit v podzemí? Podzemí jsem viděla.,Hvorfor skal vi tilbringe så meget tid under jorden? Jeg har set under jorden.,Warum müssen wir so viel Zeit im Untergrund verbringen.? Ich kenne den Untergrund.,,,¿Por que tenemos que pasar tanto tiempo bajo tierra? Ya lo tengo muy visto.,,Miksi olemme niin paljon maan alla? Nähty juttu.,Pourquoi on passe tout notre temps sous terre? J'ai déja tout vu sous terre.,Miért kell ilyen sok időt föld alatt töltenünk? Már láttam elég föld alatti részt.,Ma perché passiamo così tanto tempo sotto terra? Già conosco molto bene posti come questo.,何故私達は地下に長居せねばならないの?地下はもうわかったから。,왜 지하에서 시간을 낭비해야 되는 거지? 난 이미 지하에 있다고.,Waarom moeten we zoveel tijd onder de grond doorbrengen? Ik heb ondergronds gezien.,Hvorfor må vi tilbringe så mye tid under jorden? Jeg har sett undergrunnen.,Dlaczego musimy spędzać tyle czasu pod ziemią? Widziałem już podziemia.,Por que a gente tem que ficar tanto tempo no subterrâneo? Já vi bastante do subterrâneo.,,De ce trebuie să petrecem atâta timp sub pământ? Am văzut subteranul.,Почему нам приходится проводить кучу времени под землёй? Я на десять лет вперед насмотрелась на подземелья.,,Varför måste vi tillbringa så mycket tid under jord? Jag har sett underjorden.,Neden yeraltında bu kadar çok vakit geçirmek zorundayız? Yeraltını gördüm. +Are we really supposed to trust a guy whose inner sanctum is green?,TXT_SUB_LOG54,MAP12: Sanctum's normal entrance.,,,"Fakt máme věřit chlápkovi, jehož svatyně je zelená?","Skal vi virkelig stole på en fyr, hvis indre helligdom er grøn?","Sollen wir wirklich einem Typen vertrauen, dessen Räume grün sind?",,"Ĉu ni vere devas fidi al iu, kies sekreta templo estas verda?",¿En serio hay que fiarse de un tío cuyo templo secreto es verde?,¿En serio hay que confiar en un tipo cuyo templo secreto es verde?,"Tuleeko meidän todella luottaa kaveriin, jolla on vihreä pyhäkkö?",On est vraiment obligé de faire confiance à un type qui a un sanctuaire peint en vert?,"Egy olyan ürgében kéne megbíznunk, akinek zöld színű a szentélye?",Davvero dovremmo fidarci di qualcuno che ha un santuario verde?,聖域内部と全身が緑色の者を信用するべきなの?,성소가 더럽게 초록색인데 이 녀석을 정말 믿어야 해?,Moeten we echt vertrouwen hebben in een man wiens innerlijke heiligdom groen is?,Skal vi virkelig stole på en fyr hvis indre er grønt?,"Czy naprawdę mamy ufać facetowi, którego wewnętrzne sanktuarium jest zielone?",Será que a gente deve mesmo confiar num cara cujo grande santuário é verde?,,Chiar ar trebui să avem încredere în cineva în cineva al cărui sanctuar e verde?,"Мы точно можем доверять парню, чьи внутренние покои зелёного цвета?",,Är det verkligen meningen att vi ska lita på en kille vars inre helgedom är grön?,Kutsal alanı yeşil olan bir adama gerçekten güvenmemiz mi gerekiyor? +Crimson and Obsidian? Why can't he say red and black.,TXT_SUB_LOG55,MAP12: After talking to the Oracle.,,,Karmíno-obsidiánová? Proč nemůže říct červeno-černá?,Purpur og Obsidian? Hvorfor kan han ikke sige rød og sort.,Purpur und Obsidian? Warum kann er nicht Rot und Schwarz sagen?,,Ĉu «karmezina kaj obsidiankolora»? Ĉu li ne scias diri «ruĝa kaj nigra»?,"¿«Carmesí y obsidiana»?, ¿tanto le cuesta decir «roja y negra»?",,Purppuranpunainen ja laavalasinen? Miksei hän voi sanoa punainen ja musta?,Cramoisi et obsidienne? Il peut pas dire juste rouge et noir?,"Karmazsin és obszidián? Miért nem tudja azt mondani, hogy piros és fekete.",Cremisina e ossidiana? Non bastava dire rossa e nera?,深紅と黒曜石?何故彼は赤と黒と言わないの。,진홍빛 흑요석? 빨간 검은색이라고 말하면 어디 덧나나?,Crimson en Obsidian? Waarom kan hij niet rood en zwart zeggen.,Purpur og Obsidian? Hvorfor kan han ikke si rødt og svart?,Karmazyn i Obsydian? Dlaczego nie może powiedzieć: czerwony i czarny.,Carmesim e Obsidiana? Por que ele não diz logo vermelho e preto?,,Străveziu și Obsidian? De ce nu poate spune roșu și negru.,Багрово-обсидиановая? Почему бы не сказать просто — «красно-чёрная»!,,Karminrött och Obsidian? Varför kan han inte säga röd och svart.,Crimson ve Obsidian? Neden kırmızı ve siyah diyemiyor? "The Bishop is the Order's military leader. He plots their tactics, runs their spies and is charged with controlling us. We off him and we score twice.",TXT_SUB_LOG56,MAP11: Afther talking to the Oracle and leaving the cave.,,,"Biskup velí armádě Řádu. Plánuje jejich taktiky, velí jejich špiónům a má za úkol ovládat nás. Odděláme ho a zabodujeme dvakrát.","Biskoppen er ordenens militære leder. Han udtænker deres taktik, leder deres spioner og har til opgave at kontrollere os. Hvis vi dræber ham, scorer vi to gange.","Der Bischof ist der militärische Anführer des Ordens. Er plant die Strategien, beaufsichtigt die Spione und ist beauftragt, uns zu kontrollieren. Wenn wir ihn ausschalten, gewinnen wir doppelt.",,,"El Obispo es el líder militar de La Orden: planea sus tácticas, maneja a sus espías y está al cargo de controlarnos. Nos lo cargamos y ganamos dos puntos.","El Obispo es el líder militar de La Orden: planea sus tácticas, maneja a sus espías y está al cargo de controlarnos. Lo matamos y premios dobles.","Piispa on Veljeskunnan sotapäällikkö. Hän laatii heidän taktiikkansa, johtaa heidän vakoojiaan ja vastaa meidän hallinnasta. Teemme hänestä lopun ja pokkaamme kaksi pistettä. ","L'évèque est le leader militaire de l'Ordre. C'est lui qui s'occupe de leur tactiques, gère leurs espions, et est en charge de nous contrôler. On l'élimine, on marque deux points.","A Püspök a Rend katonai vezetője. Ő agyalja ki a taktikákat, irányítja a kémeket, és rá van bízva a mi irányításunk is. A kiiktatásával két legyet ütünk egy csapásra.",Il Vescovo è il capo militare dell'Ordine. È lui a pianificare le loro tattiche e gestire le loro spie al fine di controllarci tutti. Farlo fuori sarebbe un enorme vantaggio.,"ビショップはオーダーの軍事指揮官よ。 奴等の戦術を企てスパイを駆り立て私達の支配が管轄だ。 -奴を仕留めれば得点は倍額でしょう。","비숍은 그들의 잔혹한 군사 지도자이지. 그는 전술을 획책하고, 첩자를 부리고, 우리들을 통제하고 있어. 그를 죽이면 두 배로 이득이 갈 거야.","De bisschop is de militaire leider van de Orde. Hij zet hun tactiek uit, leidt hun spionnen en heeft de opdracht ons te controleren. We gaan van hem af en we scoren twee keer.","Biskopen er ordenens militære leder. Han planlegger taktikken deres, styrer spionene deres og har ansvaret for å kontrollere oss. Dreper vi ham, scorer vi to ganger.","Biskup jest przywódcą wojskowym Zakonu. Tworzy ich taktykę, prowadzi ich szpiegów i ma za zadanie kontrolować nas. Zdejmiemy go i zdobędziemy dwa punkty.","O Bispo é o líder militar da Ordem. Ele planeja suas táticas, comanda seus espiões e é encarregado de nos controlar. Eliminamos ele e é dois coelhos numa tacada só.",,"Episcopul e liderul militar al Ordinului. Le planifică schemele, tacticile, spionează, și ne controlează. Îl eliminăm și înscriem de două ori.","Епископ — военный лидер Ордена. Он обучает их тактике, управляет их шпионами и жаждет контроля над нами. От его убийства мы выигрываем вдвойне.",,"Piskopos, Tarikat'ın askeri lideridir. Taktiklerini planlar, casuslarını yönetir ve bizi kontrol etmekle görevlidir. Ondan kurtulursak iki kere kazanırız." -The Bishop is going to be heavily guarded so why don't we swipe a uniform and blend in?,TXT_SUB_LOG57,MAP11: Officer's uniform room.,,,"Biskup bude silně strážen, co takhle sebrat uniformu a splynout s davem?","Biskoppen vil være stærkt bevogtet, så hvorfor tager vi ikke en uniform og falder ind i mængden?","Der Bischof wird schwer bewacht sein, so warum stibitzen wir nicht eine Uniform um uns besser anzupassen?",,,El Obispo estará bien guardado asi que ¿por que no pillamos un uniforme y nos mezclamos?,,"Piispa on taatusti tarkoin vartioitu, joten miksemme kähveltäisi univormua ja sulautuisi joukkoon?","L'évèque sera lourdement protégé, pourquoi ne pas trouver un uniforme et se mêler à la foule?","A Püspök elég izmos védelmet élvez, érdemes lesz lopnunk egy uniformist a beilleszkedés jegyében.","Il Vescovo sarà sicuramente ben protetto, quindi perché non camuffarsi con un'uniforme?",ビショップのいる場所の警備は厳重なので、奴等の制服を盗み紛れ込む方が良いのでは?,"비숍은 군사 지도자니까, 삼엄한 경비에 의해 지켜질 거야. 그러니 전투복을 입고 잠입하는 게 어때?","De bisschop zal zwaar bewaakt worden, dus waarom vegen we er niet een uniform overheen en mengen we ons in de bisschop?","Biskopen kommer til å være tungt bevoktet, så hvorfor tar vi ikke en uniform og smelter inn?","Biskup będzie pilnie strzeżony, więc czemu nie weźmiemy munduru i nie wtopimy się w tłum?","O Bispo está protegido por vários guardas, então que tal roubar um uniforme e se mesclar?",,Episcopul o să fie extrem de bine păzit deci de ce nu luăm o uniformă și ne camuflăm?,"Похоже, что Епископа неплохо охраняют. Предлагаю стянуть униформу и прокрасться внутрь.",,"Piskopos çok sıkı korunuyor olacak, neden bir üniforma çalıp aralarına karışmıyoruz?" -"Remind me, we win this thing and I'll call in a decorator.",TXT_SUB_LOG58,,,,"Připomeň mi až vyhrajeme, abych zavolala malíře.","Mind mig om, at hvis vi vinder det her, så tilkalder jeg en dekoratør.","Bitte erinnere mich daran, dass wir einen Dekorateur bestellen, nachdem wir gewonnen haben.",,,"Recuérdame, nos ganamos esto y llamo a un decorador.",,"Muistuta minua, että jos voitamme tämän, niin kutsun paikalle sisustussuunnittelijan.","Rappelle-moi, quand on a fini, il faut que j'appelle un décorateur.","Emlékeztess rá, hogy ha túlvagyunk ezen hívjak egy szobafestőt.","Ricordamelo, appena vinciamo questa battaglia bisogna chiamare qualcuno per ridecorare.",,"우리가 이길 수만 있다면, 축제 분위기 나게 장식할 사람을 부를 거야.","Herinner me eraan, we winnen dit ding en ik zal een decorateur inschakelen.","Minn meg på at hvis vi vinner, ringer jeg etter en dekoratør.","Przypomnij mi, że jak wygramy to wezwę dekoratora.","Não deixa eu esquecer, depois de vencermos vou chamar um decorador.",,"Adu-mi aminte, câștigăm și chem să ne decoreze.","Напомни мне позвать декоратора после того, как мы победим.",,"Hatırlat bana, bu şeyi kazanırsak bir dekoratör çağıracağım." -"I just got word we got an informer inside the fortress. Let's head toward what they call the hospital, he works there.",TXT_SUB_LOG59,MAP17: Bailey → Upstairs.,,,"Právě jsem dostala zprávu, že máme v pevnosti informátora. Měli bychom zamířit k nemocnici, pracuje tam.","Jeg har lige hørt, at vi har en stikker inde i fæstningen. Lad os gå mod det, de kalder hospitalet. Han arbejder der.","Ich habe gerade gehört, dass wir einen Informanten in der Festung haben. Geh rüber um Hospital, dort arbeitet er.",,"Mi ĵus estis sciigita, ke ni havas informanton en la fortreso. Ni iru al tio, kion ili nomas «la malsanulejo», lia laborejo.","Acaban de decirme que tenemos un informante dentro de la fortaleza. Vayamos a lo que llaman «el hospital», que es donde trabaja.","Acaban de decirme que tenemos un informante adentro de la fortaleza. Vayamos a lo que le dicen «el hospital», que es donde trabaja.","Sain juuri tiedon ilmiantajasta linnoituksessa. Suunnataan kohti paikkaa, jota he kutsuvat sairaalaksi; hän työskentelee siellä.","J'entends qu'un de nos informants se trouve dans la forteresse. Allons dans ce qu'ils appellent l'hôpital, il y travaille.","Most kaptam a hírt, hogy van egy besúgónk az erődítményben. Menjünk a kórháznak nevezett részlegbe, ott dolgozik.","Ho appena scoperto che abbiamo un informatore dentro la fortezza. Rechiamoci verso ciò che chiamano l'ospedale, lui lavora là.","要塞の中に情報提供者がいるという話を聞いた。 -奴等が病院と呼んでいる場所に勤めているので向かいましょう。","요새 안에 우리들을 도울 정보원이 있다는 보고를 들었어. 그는 오더가 병원이라고 부르는 곳 안에 있는데, 그곳으로 찾아가 봐.","Ik heb net gehoord dat we een informant in het fort hebben. Laten we naar wat ze het ziekenhuis noemen gaan, hij werkt daar.",Jeg hørte nettopp at vi har en informant inne i festningen. La oss dra til det de kaller sykehuset. Han jobber der.,"Właśnie dostałem wiadomość, że mamy informatora w twierdzy. Kierujmy się w stronę tego, co nazywają szpitalem, on tam pracuje.","Acabei de receber a informação de que temos um informante dentro da fortaleza. Vamos para onde eles chamam de ""hospital"". Ele trabalha lá.",,"Tocmai am primit ceva de la un informator din interiorul fortăreței. Să merge înspre ceea ce ei numesc spital, lucrează acolo.","Мне только что сказали, что у нас есть информатор внутри крепости. Нам нужно место, которое они называют госпиталем — он работает там.",,"Az önce kalenin içinde bir muhbirimiz olduğu haberini aldım. Hastane dedikleri yere doğru gidelim, orada çalışıyor." -"Grab the plans and knock out the computer, ok?",TXT_SUB_LOG60,MAP17: Security Complex,,,"Seber plány a znič počítač, dobře?","Tag tegningerne og slå computeren ud, okay?","Nimm die Plane und schalte den Computer aus, ok?",,,"Coge los planos y destruye el ordenador, ¿sí?","Toma los planos y destruye la computadora, ¿sí?","Nappaa suunnitelmat ja hajota tietokone, eikö niin?","Récupère les plans et détruis l'ordinateur, ok?","Kapd fel a terveket, és nyírd ki a számítógépet, rendben?","Prendi i piani e distruggi il computer, ok?",計画を奪いにコンピューターを破壊する、いけるわね?,계획서를 집고 컴퓨터를 파괴해. 간단하지?,"Pak de plannen en sla de computer eruit, oké?","Ta tegningene og slå ut datamaskinen, ok?","Weź plany i wywal komputer, ok?","Pegue os planos e destrua o computador, ok?",,"Ia planurile și distruge calculatorul, ok?","Хватаем планы и ломаем компьютер, лады?",,"Planları al ve bilgisayarı devre dışı bırak, tamam mı?" +奴を仕留めれば得点は倍額でしょう。","비숍은 그들의 잔혹한 군사 지도자이지. 그는 전술을 획책하고, 첩자를 부리고, 우리들을 통제하고 있어. 그를 죽이면 두 배로 이득이 갈 거야.","De bisschop is de militaire leider van de Orde. Hij zet hun tactiek uit, leidt hun spionnen en heeft de opdracht ons te controleren. We gaan van hem af en we scoren twee keer.","Biskopen er ordenens militære leder. Han planlegger taktikken deres, styrer spionene deres og har ansvaret for å kontrollere oss. Dreper vi ham, scorer vi to ganger.","Biskup jest przywódcą wojskowym Zakonu. Tworzy ich taktykę, prowadzi ich szpiegów i ma za zadanie kontrolować nas. Zdejmiemy go i zdobędziemy dwa punkty.","O Bispo é o líder militar da Ordem. Ele planeja suas táticas, comanda seus espiões e é encarregado de nos controlar. Eliminamos ele e é dois coelhos numa tacada só.",,"Episcopul e liderul militar al Ordinului. Le planifică schemele, tacticile, spionează, și ne controlează. Îl eliminăm și înscriem de două ori.","Епископ — военный лидер Ордена. Он обучает их тактике, управляет их шпионами и жаждет контроля над нами. От его убийства мы выигрываем вдвойне.",,"Biskopen är ordens militära ledare. Han planerar deras taktik, leder deras spioner och har till uppgift att kontrollera oss. Om vi dödar honom får vi två poäng.","Piskopos, Tarikat'ın askeri lideridir. Taktiklerini planlar, casuslarını yönetir ve bizi kontrol etmekle görevlidir. Ondan kurtulursak iki kere kazanırız." +The Bishop is going to be heavily guarded so why don't we swipe a uniform and blend in?,TXT_SUB_LOG57,MAP11: Officer's uniform room.,,,"Biskup bude silně strážen, co takhle sebrat uniformu a splynout s davem?","Biskoppen vil være stærkt bevogtet, så hvorfor tager vi ikke en uniform og falder ind i mængden?","Der Bischof wird schwer bewacht sein, so warum stibitzen wir nicht eine Uniform um uns besser anzupassen?",,,El Obispo estará bien guardado asi que ¿por que no pillamos un uniforme y nos mezclamos?,,"Piispa on taatusti tarkoin vartioitu, joten miksemme kähveltäisi univormua ja sulautuisi joukkoon?","L'évèque sera lourdement protégé, pourquoi ne pas trouver un uniforme et se mêler à la foule?","A Püspök elég izmos védelmet élvez, érdemes lesz lopnunk egy uniformist a beilleszkedés jegyében.","Il Vescovo sarà sicuramente ben protetto, quindi perché non camuffarsi con un'uniforme?",ビショップのいる場所の警備は厳重なので、奴等の制服を盗み紛れ込む方が良いのでは?,"비숍은 군사 지도자니까, 삼엄한 경비에 의해 지켜질 거야. 그러니 전투복을 입고 잠입하는 게 어때?","De bisschop zal zwaar bewaakt worden, dus waarom vegen we er niet een uniform overheen en mengen we ons in de bisschop?","Biskopen kommer til å være tungt bevoktet, så hvorfor tar vi ikke en uniform og smelter inn?","Biskup będzie pilnie strzeżony, więc czemu nie weźmiemy munduru i nie wtopimy się w tłum?","O Bispo está protegido por vários guardas, então que tal roubar um uniforme e se mesclar?",,Episcopul o să fie extrem de bine păzit deci de ce nu luăm o uniformă și ne camuflăm?,"Похоже, что Епископа неплохо охраняют. Предлагаю стянуть униформу и прокрасться внутрь.",,Biskopen kommer att vara tungt bevakad så varför tar vi inte en uniform och smälter in?,"Piskopos çok sıkı korunuyor olacak, neden bir üniforma çalıp aralarına karışmıyoruz?" +"Remind me, we win this thing and I'll call in a decorator.",TXT_SUB_LOG58,,,,"Připomeň mi až vyhrajeme, abych zavolala malíře.","Mind mig om, at hvis vi vinder det her, så tilkalder jeg en dekoratør.","Bitte erinnere mich daran, dass wir einen Dekorateur bestellen, nachdem wir gewonnen haben.",,,"Recuérdame, nos ganamos esto y llamo a un decorador.",,"Muistuta minua, että jos voitamme tämän, niin kutsun paikalle sisustussuunnittelijan.","Rappelle-moi, quand on a fini, il faut que j'appelle un décorateur.","Emlékeztess rá, hogy ha túlvagyunk ezen hívjak egy szobafestőt.","Ricordamelo, appena vinciamo questa battaglia bisogna chiamare qualcuno per ridecorare.",,"우리가 이길 수만 있다면, 축제 분위기 나게 장식할 사람을 부를 거야.","Herinner me eraan, we winnen dit ding en ik zal een decorateur inschakelen.","Minn meg på at hvis vi vinner, ringer jeg etter en dekoratør.","Przypomnij mi, że jak wygramy to wezwę dekoratora.","Não deixa eu esquecer, depois de vencermos vou chamar um decorador.",,"Adu-mi aminte, câștigăm și chem să ne decoreze.","Напомни мне позвать декоратора после того, как мы победим.",,Påminn mig om att om vi vinner det här så ska jag kalla in en dekoratör.,"Hatırlat bana, bu şeyi kazanırsak bir dekoratör çağıracağım." +"I just got word we got an informer inside the fortress. Let's head toward what they call the hospital, he works there.",TXT_SUB_LOG59,MAP17: Bailey → Upstairs.,,,"Právě jsem dostala zprávu, že máme v pevnosti informátora. Měli bychom zamířit k nemocnici, pracuje tam.","Jeg har lige hørt, at vi har en stikker inde i fæstningen. Lad os gå mod det, de kalder hospitalet. Han arbejder der.","Ich habe gerade gehört, dass wir einen Informanten in der Festung haben. Geh rüber um Hospital, dort arbeitet er.",,"Mi ĵus estis sciigita, ke ni havas informanton en la fortreso. Ni iru al tio, kion ili nomas «la malsanulejo» lia laborejo.","Acaban de decirme que tenemos un informante dentro de la fortaleza. Vayamos a lo que llaman «el hospital», que es donde trabaja.","Acaban de decirme que tenemos un informante adentro de la fortaleza. Vayamos a lo que le dicen «el hospital», que es donde trabaja.","Sain juuri tiedon ilmiantajasta linnoituksessa. Suunnataan kohti paikkaa, jota he kutsuvat sairaalaksi; hän työskentelee siellä.","J'entends qu'un de nos informants se trouve dans la forteresse. Allons dans ce qu'ils appellent l'hôpital, il y travaille.","Most kaptam a hírt, hogy van egy besúgónk az erődítményben. Menjünk a kórháznak nevezett részlegbe, ott dolgozik.","Ho appena scoperto che abbiamo un informatore dentro la fortezza. Rechiamoci verso ciò che chiamano l'ospedale, lui lavora là.","要塞の中に情報提供者がいるという話を聞いた。 +奴等が病院と呼んでいる場所に勤めているので向かいましょう。","요새 안에 우리들을 도울 정보원이 있다는 보고를 들었어. 그는 오더가 병원이라고 부르는 곳 안에 있는데, 그곳으로 찾아가 봐.","Ik heb net gehoord dat we een informant in het fort hebben. Laten we naar wat ze het ziekenhuis noemen gaan, hij werkt daar.",Jeg hørte nettopp at vi har en informant inne i festningen. La oss dra til det de kaller sykehuset. Han jobber der.,"Właśnie dostałem wiadomość, że mamy informatora w twierdzy. Kierujmy się w stronę tego, co nazywają szpitalem, on tam pracuje.","Acabei de receber a informação de que temos um informante dentro da fortaleza. Vamos para onde eles chamam de ""hospital"". Ele trabalha lá.",,"Tocmai am primit ceva de la un informator din interiorul fortăreței. Să merge înspre ceea ce ei numesc spital, lucrează acolo.","Мне только что сказали, что у нас есть информатор внутри крепости. Нам нужно место, которое они называют госпиталем — он работает там.",,"Jag fick just höra att vi har en informatör inne i fästningen. Vi går mot det som de kallar sjukhuset, han arbetar där.","Az önce kalenin içinde bir muhbirimiz olduğu haberini aldım. Hastane dedikleri yere doğru gidelim, orada çalışıyor." +"Grab the plans and knock out the computer, ok?",TXT_SUB_LOG60,MAP17: Security Complex,,,"Seber plány a znič počítač, dobře?","Tag tegningerne og slå computeren ud, okay?","Nimm die Plane und schalte den Computer aus, ok?",,,"Coge los planos y destruye el ordenador, ¿sí?","Toma los planos y destruye la computadora, ¿sí?","Nappaa suunnitelmat ja hajota tietokone, eikö niin?","Récupère les plans et détruis l'ordinateur, ok?","Kapd fel a terveket, és nyírd ki a számítógépet, rendben?","Prendi i piani e distruggi il computer, ok?",計画を奪いにコンピューターを破壊する、いけるわね?,계획서를 집고 컴퓨터를 파괴해. 간단하지?,"Pak de plannen en sla de computer eruit, oké?","Ta tegningene og slå ut datamaskinen, ok?","Weź plany i wywal komputer, ok?","Pegue os planos e destrua o computador, ok?",,"Ia planurile și distruge calculatorul, ok?","Хватаем планы и ломаем компьютер, лады?",,"Ta ritningarna och slå ut datorn, okej?","Planları al ve bilgisayarı devre dışı bırak, tamam mı?" "Alright, I'm not complaining, but next time we might try the way that isn't buckets of blood.",TXT_SUB_LOG61,"(Strife: Veteran Edition) -Random comment when the player dies with Classic Mode turned off",,,"Dobře, nestěžuju si, ale příště bychom mohli zkusit způsob, po kterém nezůstanou kýble krve.","Okay, jeg klager ikke, men næste gang kan vi måske prøve den måde, der ikke er spandevis af blod.","Ok, ich will nicht meckern, aber beim nächsten Mal sollte das mit weniger Blutvergießen vonstatten gehen.",,,"Muy bien, no me quejo, pero la próxima vez deberíamos probar el método que no sea una masacre.",,"Hyvä on, en minä mitään valita, mutta ensi kerralla voisimme kokeilla tapaa, joka ei sisällä ämpärikaupalla verta.","Bon, je ne me plains pas, mais la prochaine fois, essayons de faire sans foutre du sang partout?","Igazából nem akarok panaszkodni, de legközelebb próbáljunk meg egy kevsébé véres módszert.","Va bene, non che voglia lamentarmi, ma magari la prossima volta ",大丈夫、次は血のバケツをぶち撒けない方法を試した方がいい。,"이런... 비꼬는 건 아닌데, 다음번엔 유혈사태를 일으키지 않고 일을 해결해보자.","Oké, ik klaag niet, maar de volgende keer kunnen we misschien de manier proberen waarop dat geen emmers bloed is.","Greit, jeg klager ikke, men neste gang kan vi prøve en vei som ikke er bøtter med blod.","Dobra, nie narzekam, ale następnym razem może spróbujemy drogi, która nie jest wiadrami krwi.","Tá bem, não estou reclamando. Mas da próxima vez vamos tentar de um jeito que não seja sangue jorrando pra tudo que é lado.",,"În regulă, nu mă plâng, dar data viitoare încercăm calea care nu duce la găleți de sânge.","Я не жалуюсь, но, может, в следующий раз попробуем не проливать реки крови?",,"Pekala, şikayet etmiyorum ama bir dahaki sefere kova kova kan olmayan yolu deneyebiliriz." +Random comment when the player dies with Classic Mode turned off",,,"Dobře, nestěžuju si, ale příště bychom mohli zkusit způsob, po kterém nezůstanou kýble krve.","Okay, jeg klager ikke, men næste gang kan vi måske prøve den måde, der ikke er spandevis af blod.","Ok, ich will nicht meckern, aber beim nächsten Mal sollte das mit weniger Blutvergießen vonstatten gehen.",,,"Muy bien, no me quejo, pero la próxima vez deberíamos probar el método que no sea una masacre.",,"Hyvä on, en minä mitään valita, mutta ensi kerralla voisimme kokeilla tapaa, joka ei sisällä ämpärikaupalla verta.","Bon, je ne me plains pas, mais la prochaine fois, essayons de faire sans foutre du sang partout?","Igazából nem akarok panaszkodni, de legközelebb próbáljunk meg egy kevsébé véres módszert.","Va bene, non che voglia lamentarmi, ma magari la prossima volta ",大丈夫、次は血のバケツをぶち撒けない方法を試した方がいい。,"이런... 비꼬는 건 아닌데, 다음번엔 유혈사태를 일으키지 않고 일을 해결해보자.","Oké, ik klaag niet, maar de volgende keer kunnen we misschien de manier proberen waarop dat geen emmers bloed is.","Greit, jeg klager ikke, men neste gang kan vi prøve en vei som ikke er bøtter med blod.","Dobra, nie narzekam, ale następnym razem może spróbujemy drogi, która nie jest wiadrami krwi.","Tá bem, não estou reclamando. Mas da próxima vez vamos tentar de um jeito que não seja sangue jorrando pra tudo que é lado.",,"În regulă, nu mă plâng, dar data viitoare încercăm calea care nu duce la găleți de sânge.","Я не жалуюсь, но, может, в следующий раз попробуем не проливать реки крови?",,"Okej, jag klagar inte, men nästa gång kanske vi ska försöka på det sätt som inte innebär hinkar med blod.","Pekala, şikayet etmiyorum ama bir dahaki sefere kova kova kan olmayan yolu deneyebiliriz." "We've been through endless hallways before, but I swear, these walls are moving as we pass.",TXT_SUB_LOG62,MAP19: Cross-shaped room at the beginning.,,,"Už jsme předtím byli v nekonečných chodbách, ale přísahám, že tyhle stěny se hýbou.","Vi har været igennem endeløse gange før, men jeg sværger, at disse vægge bevæger sig, mens vi passerer.","Wir sind ja schon durch endlose Flure gegangen, aber ich könnte schwören, dass sich die Wände hier bewegen.",,,"Ya hemos pasado por pasillos sin fin otras veces, pero juro que estas paredes se están moviendo a nuestro paso.",,"Olemme ennenkin kulkeneet loputtomia käytäviä pitkin, mutta voisin melkein vannoa näiden seinien liikkuvan sitä mukaa kun läpi käymme.","J'ai déja fais un tour dans un couloir sans fin comme ça, mais je jure que les murs bougent avec nous.","Volt már dolgunk végtelen hosszú folyosóval, de esküszöm olyan érzésem van, mintha velünk együtt mozognának a falak.","Abbiamo superato chissà quanti corridoi fino ad ora, ma ti giuro, questi muri si muovono mentre camminiamo.","以前に私達は無限へ通じる玄関を通ったかと思うが、誓おう、 -通り過ぎた時に壁が動いていたからだと。","난감한 곳들을 다녀갔지만, 여기는 뭔가 새로워. 걸어갈 때마다 벽이 움직이는 것 같거든...","We zijn al eens door eindeloze gangen geweest, maar ik zweer het, deze muren bewegen zich in de loop van de tijd.","Vi har gått gjennom endeløse korridorer før, men disse veggene beveger seg når vi går forbi.","Przechodziliśmy już przez nieskończone korytarze, ale przysięgam, że te ściany się ruszają, gdy przechodzimy.","Já passamos por inúmeros corredores antes, mas eu juro, essas paredes ficam se mexendo enquanto a gente passa.",,Am mai fost prin holuri nesfârșite dar jur că zidurile ăstea se mișcă odată cu noi.,"Мы уже повидали достаточно бесконечных коридоров, но я готова поклясться: эти стены передвигаются, когда мы на них не смотрим.",,"Daha önce de sonsuz koridorlardan geçtik, ama yemin ederim, bu duvarlar biz geçerken hareket ediyor." -"Well, you gotta figure. Military leader equals lots of bad guys.",TXT_SUB_LOG63,MAP16,,,"No, dává to smysl. Armádní vůdce rovná se hodně padouchů.",Det må man regne ud. Militær leder er lig med masser af skurke.,Das war ja klar. Militärischer Anführer bedeutet jede Menge Bösewichte.,,"Nu, ĉi tio estis divenebla: «Militestro» estas egala al multaj malbonuloj.","Bueno, era de imaginar: «Líder militar» equivale a muchos tipos malos.",,Mietipä sitä; sotapäällikkö vastaa monta pahista.,"Bon, fallait y penser. Chef militaire, ça veut dire beaucoup de types armés.","Ki gondolta volna, hogy egy katonai vezetőt egy rakás rossz fiú fog védeni.","Beh, c'era da aspettarselo. Capo militare significa un sacco di cattivi.",さて、貴方はフィギュアを得た。軍隊指揮者は大勢の悪人に匹敵するわ。,이거 정말 뻔하네. 군대 우두머리의 심복들은 다 난폭하고 둔하지.,"Nou ja, je moet het wel beseffen. Militair leider is gelijk aan veel slechteriken.","Vel, du må skjønne. Militærleder er lik mange skurker.","No cóż, trzeba to sobie wyobrazić. Przywódca wojskowy równa się wielu złym ludziom.","Olha só, quem diria. Líder militar é igual a um monte de caras malvados.",,"Ei, dă-ți seama. Lider militar înseamnă mulți băieți răi.",Сам понимаешь. Военный лидер — всё равно что куча плохих парней.,,Bunu anlamalısın. Askeri lider eşittir bir sürü kötü adam. -Don't give up. This is it. Straight ahead.,TXT_SUB_LOG64,MAP19: Last room (southwestern).,,,"Nevzdávej se, tohle je ono. Jdi rovně.",Du må ikke give op. Det er nu. Lige fremad.,Gib nicht auf. Direkt voraus.,,,No te rindas. Vas bien: justo adelante.,,"Älä luovuta. So nyt tässä, suoraan edessä.","Abandonne pas, on y est. Juste devant.",Ne add fel. Ez lesz az. Éppen előttünk.,Non arrenderti. Siamo arrivati. Dritto in fronte a te.,諦めないで。これでいいんだ。真っ直ぐ行こう。,포기하지 마. 거의 다 왔어. 가까이 왔다고.,Geef niet op. Dit is het. Rechtdoor.,Ikke gi opp. Her er det. Rett fram.,Nie poddawaj się. To jest to. Prosto przed siebie.,Não desista. Esta é a hora. Siga reto adiante.,,Nu te da bătut. Asta e. Drept înainte.,Не падай духом. Вот оно. Впереди.,,Sakın pes etme. İşte burası. Dümdüz ilerle. -"Next time, we stop at a gas station and ask for directions.",TXT_SUB_LOG65,,,,Příště se zastavíme na benzince a zeptáme se na cestu.,Næste gang stopper vi ved en tankstation og spørger om vej.,Nächstes Mal halten wir an einer Tankstelle und fragen nach der Richtung.,,,A la próxima paramos en una gasolinera y preguntamos la dirección.,,Ensi kerralla pysähdytään huoltoasemalle kysymään suuntaneuvoja.,"La prochaine fois, on s'arrète à une station-service et on demande notre chemin.","Legközelebb amikor megállunk egy benzinkútnál, körbekérdezünk az irányzékkal kapcsolatban.","La prossima volta, ci fermiamo ad una stazione di servizio per chiedere indicazioni.",,다음엔 편의점 같은 건물에 들러서 그냥 방향을 묻자.,De volgende keer stoppen we bij een tankstation en vragen we de weg.,Neste gang stopper vi på en bensinstasjon og spør om veien.,Następnym razem zatrzymamy się na stacji benzynowej i zapytamy o drogę.,Da próxima vez vamos parar num posto de gasolina e perguntar onde fica.,,Data viitoare ne oprim la o benzinărie și întrebăm despre repere.,В следующий раз остановимся на заправке и спросим дорогу.,,Bir dahaki sefere benzin istasyonunda durup yol sorarız. -Oh no! More bells and whistles and nasty guys chasing us.,TXT_SUB_LOG66,MAP19: After coming across an alarm green door.,,,"Ale ne! Další fešné vymoženosti a zmetci, co nás pronásledují.","Åh nej! Flere klokker og fløjter og grimme fyre, der jagter os.",Oh nein. Noch mehr Lärm und Bösewichte auf unseren Fersen.,,,¡No puede ser! Más bombos y platillos y tipos malos persiguiéndonos.,,Voi ei! Lisää härpäkkeitä ja pahiksia jahtaamassa meitä.,Oh non! Encore des trucs et des choses et des sales types qui nous prennent en chasse.,"Jaj ne! Még több csicsás rész, és még annál is több gonosz a nyomunkban.",Oh no! Campane e fischietti e altri cattivi che ci inseguono.,あーらら!鐘と笛で更に厄介な奴等を呼び込んできたな。,"오, 안 돼! 삼엄한 경비에 피할 수도 없는 선택지라니.",Oh nee! Nog meer toeters en bellen en vervelende jongens die ons achterna zitten.,"Å, nei! Flere bjeller og fløyter og ekle fyrer som jager oss.","O nie! Więcej dzwonków i gwizdków i wrednych facetów, którzy nas gonią.",Ai não! Mais bugigangas e capangas vindo atrás de nós.,,Oh nu! Mai mulți băieți răi ne urmăresc!,"О, нет! Ещё больше свистелок, перделок и плохих парней, которые за нами гонятся.",,Olamaz! Daha fazla zil ve düdük ve bizi kovalayan kötü adamlar. -"You know, from the outside, this place looks tiny.",TXT_SUB_LOG67,MAP15: After using a big lift next to a Reaver.,,,Zvenku tohle místo vypadalo drobounké.,Udefra ser det her sted lille ud.,Von außen sieht das hier irgendwie mickrig aus.,,"Nu, ĉi tiu loko aspektis malgranda de ekstere.","O sea, este lugar se veía enano desde fuera.","O sea, este lugar se veía enano desde afuera.","Oletko muuten huomannut, että ulkopuolelta katsottuna tämä paikka näyttää tosi pieneltä.","Tu sais, de l'extérieur, cet endroit à l'air super petit.","Azt hinné az ember, hogy sokkal kisebb ez a hely a kinti kinézet alapján.","Lo sai, da fuori, questo posto sembra piccolo.",外から見ると、此処は小さいみたいね。,"궁금한 게 있는데, 왜 안에 들어가면 커지는 걸까?","Weet je, van buitenaf ziet deze plek er klein uit.","Du vet, fra utsiden ser dette stedet lite ut.","Wiesz, z zewnątrz to miejsce wygląda na malutkie.","Sabe, vendo de longe esse lugar parece minúsculo.",,"Știi, din afară, locul ăsta arată mărunt.","Знаешь, снаружи это место кажется крошечным.",,Dışarıdan bakınca burası çok küçük görünüyor. -"I'm getting a new enemy reading. Don't stop and stare, just waste 'em.",TXT_SUB_LOG68,,,,Zaznamenávám nového nepřítele. Nestůj tam a znič ho!,"Jeg får en ny fjendeudlæsning. Lad være med at stoppe op og stirre, bare smadr dem.","Ich habe eine neue Feindortung. Warum wartest du, mach sie alle!",,,"Tengo señales de un nuevo enemigo. No te pares a mirar, solo cárgatelo.",,Saan uuden lukeman vihollisista. Älä siihen jää töllöttämään; listi ne!,"J'ai un ping ennemi sur mon radar. Ne t'arrète pas, flingue-les.","Új ellenséget észlelek. Ne állj meg nézelődni, hanem nyírd ki őket.","Sto ricevendo segnali di altri nemici. Non fermarti a guardare, distruggili.",,네 주변에 적이 포착됐어. 그냥 쳐다보지 말고 어떻게든 해봐.,"Ik krijg een nieuwe vijandelijke lezing. Niet stoppen en staren, maar ze gewoon verspillen.","Jeg får en ny fiende på skjermen. Ikke stopp og stir, bare skyt dem.","Dostaję nowy odczyt wroga. Nie zatrzymuj się i nie gap, po prostu je zmarnuj.","Estou recebendo sinais de um novo inimigo. Nâo fique parado olhando, mete bala neles.",,"Citesc inamici în apropiere. Nu te oprii și holba, fă-i bucăți.","Вижу врагов. Не стой столбом, мочи их!",,"Yeni bir düşman okuması alıyorum. Durup bakma, sadece harca onları." -"I hate these forcefields. Look for the shut-off switch, it's gotta be nearby.",TXT_SUB_LOG69,STRIFE1.WAD: MAP15,,,"Nesnáším tahle silová pole. Porozhlédni se po nějakém vypínači, měl by být nablízku.",Jeg hader disse kraftfelter. Se efter slukkontakten. Den må være i nærheden.,"Ich hasse diese Kraftfelder. Such nach einem Schalter, er müsste in der Nähe sein.",,,"Odio estos campos de fuerza. Busca el interruptor de apagado, tiene que estar cerca.",,Vihaan näitä voimakenttiä. Etsi virtakatkaisinta; sen on pakko olla jossain lähettyvillä.,"Je déteste les champs de force. Trouve leur commandes, elles ne doivent pas être loin.","Utálom ezket az erőpajzsokat. Keresd egy kikapcsoló gombot, itt kell lennie valahol.","Odio questi campi di forza. Cerca il pulsante per disattivarlo, deve essere vicino.",私はフォースフィールドが憎いわ。遮断させるスイッチが近くにあるはずだわ。,이런 방어막들 정말 싫다니까. 저걸 끌 스위치를 찾아봐. 가까이에 있을 거야.,"Ik haat deze krachtvelden. Zoek naar de afsluitschakelaar, die moet in de buurt zijn.",Jeg hater disse kraftfeltene. Se etter bryteren. Den må være i nærheten.,"Nienawidzę tych pól siłowych. Szukajcie wyłącznika, musi być w pobliżu.","Odeio esses campos de força. Procure pelo interruptor de desligar, deve estar por perto.",,"Urăsc compurile de forță. Uită-te după un buton de oprire, trebuie să fie în apropiere.","Ненавижу эти силовые поля. Поищи выключатель, он где-то неподалёку.",,"Bu güç alanlarından nefret ediyorum. Kapatma düğmesini ara, yakında olmalı." -"Ooh, very impressive. Let's blow it up!",TXT_SUB_LOG70,MAP15: After pressing the switch to reveal the computer.,,,"Ó, velmi působivé. Co to nechat vybouchnout?",Meget imponerende. Lad os sprænge den i luften!,"Oh, sehr imposant. Jag ihn hoch!",,,Muy impresionante. ¡Destruyámoslo!,Muy impresionante. ¡Vamos a destruirla!,"Oo, aika vaikuttava. Posautetaan se!","Oooh, très impressionant! Faisons tout péter!",Felettébb lenyűgöző. Robbantsuk is fel!,"Aah, molto impressionante! Facciamolo saltare in aria!",あら、見事な物ね。是非とも火薬を献上しましょう。,"오우, 정말 이쁘네! 이제 터뜨리자!","Ooh, heel indrukwekkend. Laten we hem opblazen!",Veldig imponerende. La oss sprenge den!,"Ooh, bardzo imponujące. Wysadźmy to w powietrze!","Oohh, que impressionante! Vamos detoná-lo.",,"ooh, foarte impresionant. Să-l aruncăm în aer!",Очень впечатляюще. Давай взорвём!,,"Ooh, çok etkileyici. Hadi havaya uçuralım!" -"Jump on the teleporter, let's blow this pop stand.",TXT_SUB_LOG71,,,,Skoč na teleportér a odpalme tenhle stánek se zmrzlinou.,"Hop på teleporteren, lad os sprænge denne popstand.",Spring in den Teleporter und jag das Ding hoch.,,,"Súbete al teletransporte, carguémonos este tinglado.",,Loikkaa kaukosiirtimelle; häivytään tästä mestasta.,"Saute dans le téléporteur, cassons nous d'ici.","Ugrás a teleportba, és robbantsuk az égig ezt a kuplerájt.","Salta sul teletrasporto, facciamo esplodere questo mortorio.",,텔레포터를 타고 이 놀이터를 벗어나자.,"Spring op de teleporter, laten we deze popstandaard opblazen.","Hopp på teleporteren, la oss sprenge denne kiosken.","Wskakuj do teleportera, wysadźmy to stoisko z popem.","Entre no teletransportador, vamos explodir este muquifo.",,"Sari în teleportor, să aruncăm în aer totul.",Прыгай в телепорт. Пора валить отсюда.,,"Işınlayıcıya atla, hadi şu pop standını havaya uçuralım." +通り過ぎた時に壁が動いていたからだと。","난감한 곳들을 다녀갔지만, 여기는 뭔가 새로워. 걸어갈 때마다 벽이 움직이는 것 같거든...","We zijn al eens door eindeloze gangen geweest, maar ik zweer het, deze muren bewegen zich in de loop van de tijd.","Vi har gått gjennom endeløse korridorer før, men disse veggene beveger seg når vi går forbi.","Przechodziliśmy już przez nieskończone korytarze, ale przysięgam, że te ściany się ruszają, gdy przechodzimy.","Já passamos por inúmeros corredores antes, mas eu juro, essas paredes ficam se mexendo enquanto a gente passa.",,Am mai fost prin holuri nesfârșite dar jur că zidurile ăstea se mișcă odată cu noi.,"Мы уже повидали достаточно бесконечных коридоров, но я готова поклясться: эти стены передвигаются, когда мы на них не смотрим.",,"Vi har gått igenom ändlösa korridorer förut, men jag svär att de här väggarna rör sig när vi passerar.","Daha önce de sonsuz koridorlardan geçtik, ama yemin ederim, bu duvarlar biz geçerken hareket ediyor." +"Well, you gotta figure. Military leader equals lots of bad guys.",TXT_SUB_LOG63,MAP16,,,"No, dává to smysl. Armádní vůdce rovná se hodně padouchů.",Det må man regne ud. Militær leder er lig med masser af skurke.,Das war ja klar. Militärischer Anführer bedeutet jede Menge Bösewichte.,,"Nu, ĉi tio estis divenebla: «Militestro» estas egala al multaj malbonuloj.","Bueno, era de imaginar: «Líder militar» equivale a muchos tipos malos.",,Mietipä sitä; sotapäällikkö vastaa monta pahista.,"Bon, fallait y penser. Chef militaire, ça veut dire beaucoup de types armés.","Ki gondolta volna, hogy egy katonai vezetőt egy rakás rossz fiú fog védeni.","Beh, c'era da aspettarselo. Capo militare significa un sacco di cattivi.",さて、貴方はフィギュアを得た。軍隊指揮者は大勢の悪人に匹敵するわ。,이거 정말 뻔하네. 군대 우두머리의 심복들은 다 난폭하고 둔하지.,"Nou ja, je moet het wel beseffen. Militair leider is gelijk aan veel slechteriken.","Vel, du må skjønne. Militærleder er lik mange skurker.","No cóż, trzeba to sobie wyobrazić. Przywódca wojskowy równa się wielu złym ludziom.","Olha só, quem diria. Líder militar é igual a um monte de caras malvados.",,"Ei, dă-ți seama. Lider militar înseamnă mulți băieți răi.",Сам понимаешь. Военный лидер — всё равно что куча плохих парней.,,Det måste man räkna ut. Militär ledare är lika med många skurkar.,Bunu anlamalısın. Askeri lider eşittir bir sürü kötü adam. +Don't give up. This is it. Straight ahead.,TXT_SUB_LOG64,MAP19: Last room (southwestern).,,,"Nevzdávej se, tohle je ono. Jdi rovně.",Du må ikke give op. Det er nu. Lige fremad.,Gib nicht auf. Direkt voraus.,,,No te rindas. Vas bien: justo adelante.,,"Älä luovuta. So nyt tässä, suoraan edessä.","Abandonne pas, on y est. Juste devant.",Ne add fel. Ez lesz az. Éppen előttünk.,Non arrenderti. Siamo arrivati. Dritto in fronte a te.,諦めないで。これでいいんだ。真っ直ぐ行こう。,포기하지 마. 거의 다 왔어. 가까이 왔다고.,Geef niet op. Dit is het. Rechtdoor.,Ikke gi opp. Her er det. Rett fram.,Nie poddawaj się. To jest to. Prosto przed siebie.,Não desista. Esta é a hora. Siga reto adiante.,,Nu te da bătut. Asta e. Drept înainte.,Не падай духом. Вот оно. Впереди.,,Ge inte upp. Det här är det. Rakt fram.,Sakın pes etme. İşte burası. Dümdüz ilerle. +"Next time, we stop at a gas station and ask for directions.",TXT_SUB_LOG65,,,,Příště se zastavíme na benzince a zeptáme se na cestu.,Næste gang stopper vi ved en tankstation og spørger om vej.,Nächstes Mal halten wir an einer Tankstelle und fragen nach der Richtung.,,,A la próxima paramos en una gasolinera y preguntamos la dirección.,,Ensi kerralla pysähdytään huoltoasemalle kysymään suuntaneuvoja.,"La prochaine fois, on s'arrète à une station-service et on demande notre chemin.","Legközelebb amikor megállunk egy benzinkútnál, körbekérdezünk az irányzékkal kapcsolatban.","La prossima volta, ci fermiamo ad una stazione di servizio per chiedere indicazioni.",,다음엔 편의점 같은 건물에 들러서 그냥 방향을 묻자.,De volgende keer stoppen we bij een tankstation en vragen we de weg.,Neste gang stopper vi på en bensinstasjon og spør om veien.,Następnym razem zatrzymamy się na stacji benzynowej i zapytamy o drogę.,Da próxima vez vamos parar num posto de gasolina e perguntar onde fica.,,Data viitoare ne oprim la o benzinărie și întrebăm despre repere.,В следующий раз остановимся на заправке и спросим дорогу.,,Nästa gång stannar vi vid en bensinstation och frågar efter vägen.,Bir dahaki sefere benzin istasyonunda durup yol sorarız. +Oh no! More bells and whistles and nasty guys chasing us.,TXT_SUB_LOG66,MAP19: After coming across an alarm green door.,,,"Ale ne! Další fešné vymoženosti a zmetci, co nás pronásledují.","Åh nej! Flere klokker og fløjter og grimme fyre, der jagter os.",Oh nein. Noch mehr Lärm und Bösewichte auf unseren Fersen.,,,¡No puede ser! Más bombos y platillos y tipos malos persiguiéndonos.,,Voi ei! Lisää härpäkkeitä ja pahiksia jahtaamassa meitä.,Oh non! Encore des trucs et des choses et des sales types qui nous prennent en chasse.,"Jaj ne! Még több csicsás rész, és még annál is több gonosz a nyomunkban.",Oh no! Campane e fischietti e altri cattivi che ci inseguono.,あーらら!鐘と笛で更に厄介な奴等を呼び込んできたな。,"오, 안 돼! 삼엄한 경비에 피할 수도 없는 선택지라니.",Oh nee! Nog meer toeters en bellen en vervelende jongens die ons achterna zitten.,"Å, nei! Flere bjeller og fløyter og ekle fyrer som jager oss.","O nie! Więcej dzwonków i gwizdków i wrednych facetów, którzy nas gonią.",Ai não! Mais bugigangas e capangas vindo atrás de nós.,,Oh nu! Mai mulți băieți răi ne urmăresc!,"О, нет! Ещё больше свистелок, перделок и плохих парней, которые за нами гонятся.",,Åh nej! Fler klockor och visselpipor och otäcka killar som jagar oss.,Olamaz! Daha fazla zil ve düdük ve bizi kovalayan kötü adamlar. +"You know, from the outside, this place looks tiny.",TXT_SUB_LOG67,MAP15: After using a big lift next to a Reaver.,,,Zvenku tohle místo vypadalo drobounké.,Udefra ser det her sted lille ud.,Von außen sieht das hier irgendwie mickrig aus.,,"Nu, ĉi tiu loko aspektis malgranda de ekstere.","O sea, este lugar se veía enano desde fuera.","O sea, este lugar se veía enano desde afuera.","Oletko muuten huomannut, että ulkopuolelta katsottuna tämä paikka näyttää tosi pieneltä.","Tu sais, de l'extérieur, cet endroit à l'air super petit.","Azt hinné az ember, hogy sokkal kisebb ez a hely a kinti kinézet alapján.","Lo sai, da fuori, questo posto sembra piccolo.",外から見ると、此処は小さいみたいね。,"궁금한 게 있는데, 왜 안에 들어가면 커지는 걸까?","Weet je, van buitenaf ziet deze plek er klein uit.","Du vet, fra utsiden ser dette stedet lite ut.","Wiesz, z zewnątrz to miejsce wygląda na malutkie.","Sabe, vendo de longe esse lugar parece minúsculo.",,"Știi, din afară, locul ăsta arată mărunt.","Знаешь, снаружи это место кажется крошечным.",,"Du vet, från utsidan ser det här stället pyttelitet ut.",Dışarıdan bakınca burası çok küçük görünüyor. +"I'm getting a new enemy reading. Don't stop and stare, just waste 'em.",TXT_SUB_LOG68,,,,Zaznamenávám nového nepřítele. Nestůj tam a znič ho!,"Jeg får en ny fjendeudlæsning. Lad være med at stoppe op og stirre, bare smadr dem.","Ich habe eine neue Feindortung. Warum wartest du, mach sie alle!",,,"Tengo señales de un nuevo enemigo. No te pares a mirar, solo cárgatelo.",,Saan uuden lukeman vihollisista. Älä siihen jää töllöttämään; listi ne!,"J'ai un ping ennemi sur mon radar. Ne t'arrète pas, flingue-les.","Új ellenséget észlelek. Ne állj meg nézelődni, hanem nyírd ki őket.","Sto ricevendo segnali di altri nemici. Non fermarti a guardare, distruggili.",,네 주변에 적이 포착됐어. 그냥 쳐다보지 말고 어떻게든 해봐.,"Ik krijg een nieuwe vijandelijke lezing. Niet stoppen en staren, maar ze gewoon verspillen.","Jeg får en ny fiende på skjermen. Ikke stopp og stir, bare skyt dem.","Dostaję nowy odczyt wroga. Nie zatrzymuj się i nie gap, po prostu je zmarnuj.","Estou recebendo sinais de um novo inimigo. Nâo fique parado olhando, mete bala neles.",,"Citesc inamici în apropiere. Nu te oprii și holba, fă-i bucăți.","Вижу врагов. Не стой столбом, мочи их!",,"Jag får en ny fiende som läser av. Stanna inte och stirra, bara döda dem.","Yeni bir düşman okuması alıyorum. Durup bakma, sadece harca onları." +"I hate these forcefields. Look for the shut-off switch, it's gotta be nearby.",TXT_SUB_LOG69,STRIFE1.WAD: MAP15,,,"Nesnáším tahle silová pole. Porozhlédni se po nějakém vypínači, měl by být nablízku.",Jeg hader disse kraftfelter. Se efter slukkontakten. Den må være i nærheden.,"Ich hasse diese Kraftfelder. Such nach einem Schalter, er müsste in der Nähe sein.",,,"Odio estos campos de fuerza. Busca el interruptor de apagado, tiene que estar cerca.",,Vihaan näitä voimakenttiä. Etsi virtakatkaisinta; sen on pakko olla jossain lähettyvillä.,"Je déteste les champs de force. Trouve leur commandes, elles ne doivent pas être loin.","Utálom ezket az erőpajzsokat. Keresd egy kikapcsoló gombot, itt kell lennie valahol.","Odio questi campi di forza. Cerca il pulsante per disattivarlo, deve essere vicino.",私はフォースフィールドが憎いわ。遮断させるスイッチが近くにあるはずだわ。,이런 방어막들 정말 싫다니까. 저걸 끌 스위치를 찾아봐. 가까이에 있을 거야.,"Ik haat deze krachtvelden. Zoek naar de afsluitschakelaar, die moet in de buurt zijn.",Jeg hater disse kraftfeltene. Se etter bryteren. Den må være i nærheten.,"Nienawidzę tych pól siłowych. Szukajcie wyłącznika, musi być w pobliżu.","Odeio esses campos de força. Procure pelo interruptor de desligar, deve estar por perto.",,"Urăsc compurile de forță. Uită-te după un buton de oprire, trebuie să fie în apropiere.","Ненавижу эти силовые поля. Поищи выключатель, он где-то неподалёку.",,"Jag hatar de här kraftfälten. Leta efter avstängningsknappen, den måste vara i närheten.","Bu güç alanlarından nefret ediyorum. Kapatma düğmesini ara, yakında olmalı." +"Ooh, very impressive. Let's blow it up!",TXT_SUB_LOG70,MAP15: Pressing the switch to reveal the PC.,,,"Ó, velmi působivé. Co to nechat vybouchnout?",Meget imponerende. Lad os sprænge den i luften!,"Oh, sehr imposant. Jag ihn hoch!",,,Muy impresionante. ¡Destruyámoslo!,Muy impresionante. ¡Vamos a destruirla!,"Oo, aika vaikuttava. Posautetaan se!","Oooh, très impressionant! Faisons tout péter!",Felettébb lenyűgöző. Robbantsuk is fel!,"Aah, molto impressionante! Facciamolo saltare in aria!",あら、見事な物ね。是非とも火薬を献上しましょう。,"오우, 정말 이쁘네! 이제 터뜨리자!","Ooh, heel indrukwekkend. Laten we hem opblazen!",Veldig imponerende. La oss sprenge den!,"Ooh, bardzo imponujące. Wysadźmy to w powietrze!","Oohh, que impressionante! Vamos detoná-lo.",,"ooh, foarte impresionant. Să-l aruncăm în aer!",Очень впечатляюще. Давай взорвём!,,"Ooh, väldigt imponerande. Vi spränger den!","Ooh, çok etkileyici. Hadi havaya uçuralım!" +"Jump on the teleporter, let's blow this pop stand.",TXT_SUB_LOG71,,,,Skoč na teleportér a odpalme tenhle stánek se zmrzlinou.,"Hop på teleporteren, lad os sprænge denne popstand.",Spring in den Teleporter und jag das Ding hoch.,,,"Súbete al teletransporte, carguémonos este tinglado.",,Loikkaa kaukosiirtimelle; häivytään tästä mestasta.,"Saute dans le téléporteur, cassons nous d'ici.","Ugrás a teleportba, és robbantsuk az égig ezt a kuplerájt.","Salta sul teletrasporto, facciamo esplodere questo mortorio.",,텔레포터를 타고 이 놀이터를 벗어나자.,"Spring op de teleporter, laten we deze popstandaard opblazen.","Hopp på teleporteren, la oss sprenge denne kiosken.","Wskakuj do teleportera, wysadźmy to stoisko z popem.","Entre no teletransportador, vamos explodir este muquifo.",,"Sari în teleportor, să aruncăm în aer totul.",Прыгай в телепорт. Пора валить отсюда.,,"Hoppa på teleportern, låt oss spränga det här popståndet.","Işınlayıcıya atla, hadi şu pop standını havaya uçuralım." "Wait, the Oracle said we would know him by his symbol of power. Are you thinking what I'm thinking?",TXT_SUB_LOG72,MAP16: Entrance.,,,"Počkat, Věštec říkal, že ho poznáme podle jeho symbolu moci. Myslíš na to samé, co já?","Vent, Oraklet sagde, at vi ville kende ham på hans kraftsymbol. Tænker du det samme som mig?","Warte, das Orakel sagte wir würden ihn an seinem Machtsymbol erkennen. Denkst du, was ich denke?",,,"Momento, el Oráculo ha dicho que lo reconoceríamos por su símbolo de poder. ¿Estás pensando lo mismo que yo?","Momento, el Oráculo dijo que lo reconoceríamos por su símbolo de poder. ¿Estás pensando lo mismo que yo?","Odota; Oraakkeli sanoi, että tunnistaisimme hänet hänen valtansa merkistä. Mietitkö samaa mitä minäkin?","Attend, l'Oracle nous a dit qu'on le reconnaitrerait de par son symbole de pouvoir.. Tu pense à la même chose que moi?","Várjunk csak, azt mondta az Orákulum, hogy felismerjük a jeléről. Te is arra gondolsz amire Én?","Aspetta, l'Oracolo aveva detto che lo avremmo riconosciuto tramite il suo simbolo del potere. Stai pensando quello che penso io?","ちょっと待って、オラクルは私達に彼のシンボルを辿ればわかると述べたか。 -貴方今、私と同じ事考えてる?","잠깐, 오라클이 전에 권력을 상징하는 문양을 따라가면 만날 수 있다고 했지? 너 나랑 같은 생각 하고 있지?","Wacht, het Orakel zei dat we hem zouden kennen aan zijn machtssymbool. Denk jij wat ik denk?","Vent, oraklet sa at vi ville kjenne ham igjen på maktsymbolet hans. Tenker du det samme som meg?","Czekaj, Wyrocznia powiedziała, że poznamy go po symbolu mocy. Myślisz o tym, co ja myślę?","Peraí, o Oráculo disse que reconheceríamos ele pelo seu símbolo de poder. Você está pensando o mesmo que eu?",,"Stai, Oracolul zicea că îl vom cunoaște după însemnul lui. Te gândeștila același lucru?","Подожди — Оракул сказал, что мы найдём его по символу власти. Ты думаешь о том же, о чём и я?",,"Bekle, Kahin onu güç sembolünden tanıyacağımızı söylemişti. Sen de benim düşündüğümü mü düşünüyorsun?" -"These guys got a decorating idea that works, and they just beat it to death.",TXT_SUB_LOG73,,,,Tihle lidi dostali dobrý nápad na výzdobu a pak ho zadupali do země.,"Disse fyre har en dekorativ idé, som virker, og de slår den bare ihjel.","Diese Typen haben ein Design das funktioniert, aber sie haben es total übertrieben.",,,"Estos tipos tuvieron una idea de decoración que funciona, y la han matado a palos.",,"Näille tyypeille välähti yksi toimiva sisustusidea, ja he vain kuluttivat sen loppuun.",Cest types avaient une super bonne idée déco et ils ont fait n'importe quoi avec.,"Ezeknek az embereknek volt egy jó dekorációs ötlete, csak némileg túlzásba vitték.","Questi qua hanno avuto una buona idea di come decorare, e poi ci sono andati ben troppo oltre.",,"저놈들은 도움이 되는 생각을 가지고 있기는 한데, 다 쓸데없이 망치고 있어.","Deze jongens hebben een decoratief idee dat werkt, en ze hebben het gewoon doodgeslagen.","De har en dekorasjonsidé som funker, og så slår de den i hjel.","Ci kolesie mają pomysł na wystrój, który działa, a oni go po prostu zepsuli na śmierć.",Esses caras tinham uma idéia de decoração que funcionava e depois mandaram tudo pro saco.,,Tipii ăștia au o idee despre decorații în aplicare.,"У этих ребят была отличная идея декора, но они загубили её на корню.",,Bu adamların işe yarayan bir dekorasyon fikri var ve onu öldüresiye dövüyorlar. -Did you see that weird spectre that came out of the Bishop's body? Where have I seen that before?,TXT_SUB_LOG74,"STRIFE1.WAD: MAP16 - -(After defeating the Bishop)",,,"Viděl jsi ten divný přízrak, který vyšel z Biskupova těla? Kde jsem ho jen předtím viděla?","Så du det underlige spøgelse, der kom ud af biskoppens krop? Hvor har jeg set det før?","Hast du diesen seltsamen Schemen gesehen, der aus seinem Körper herauskam? Wo haben wir das schonmal gesehen?",,,¿Viste ese extraño espectro que salió del cuerpo del Obispo? ¿Donde lo he visto antes?,,"Näitkö tuon oudon aaveen, joka nousi Piispan ruumiista? Missä olen nähnyt sen aiemmin?",Tu a vu ce spectre bizarre qui est sorti du corps de l'évèque? On a pas vu ça quelque part avant?,Láttad azt a fura szellemet ami kijött a Püspök teteméből? Hol láttam én már azt?,Hai visto quello strano spettro che è uscito dal corpo del Vescovo? Dove l'ho già visto prima?,"ビショップの体から出てきたあの奇妙な幽体を見た? -以前に何処かで見た気がするけど?",그나저나 비숍 몸에서 튀어나왔던 검은 물체 봤어? 전에 본 적이 있나?,Zag je dat rare spook dat uit het lichaam van de bisschop kwam? Waar heb ik dat eerder gezien?,Så du det rare spøkelset som kom ut av biskopens kropp? Hvor har jeg sett det før?,"Widziałeś to dziwne widmo, które wyszło z ciała biskupa? Gdzie ja to już widziałem?",Você viu aquele espectro estranho que saiu do corpo do BIspo? Onde foi que eu já vi isso antes?,,Ai văzut acel spectru ieșind din Episcop? Unde am mai văzut asta?,"Видел тот странный фантом, вышедший из тела Епископа? Где я могла видеть такое раньше?",,Piskoposun bedeninden çıkan o garip hayaleti gördün mü? Bunu daha önce nerede görmüştüm? -Judgment call time. Now that we got two pieces we might wanna return to base. What does your instinct tell you?,TXT_SUB_LOG75,,,,"Čas se rozhodnout. Teď, když máme dva díly, bychom se možná měli vrátit na základnu. Co ti říká intuice?","Det er tid til at dømme. Nu hvor vi har to stykker, bør vi måske vende tilbage til basen. Hvad siger dit instinkt dig?","Zeit für eine Gewissensentscheidung. Jetzt wo wir zwei Teile haben, sollten wir zur Basis zurückkehren. Was denkst du?",,,Hora del Juicio. Ahora que tienes dos piezas podríamos regresar a la base. ¿Qué te dice tú instinto?,,"Aika tehdä päätös: Nyt, kun meillä on kaksi osasta, saattaisimme haluta palata tukikohtaan. Mitä vaistosi sanoo?","C'est l'heure du jugement, on a deux pièce, il est temps de retourner à la base. Que te dit ton instinct?","Kupaktanács. Most, hogy megszereztün két darabot, vissza is térhetünk a bázisba. mit mond az ösztönöd?",È l'ora di decidere. Adesso che abbiamo due pezzi sarebbe il caso di tornare alla base. Cosa dice il tuo istinto?,,심판의 시간이야. 시질 두 조각을 모았으니 본부로 돌아가자. 이제 너의 본능은 무슨 해답을 내놓을까?,"Oordeel roep tijd. Nu we twee stukken hebben, willen we misschien terug naar de basis. Wat zegt je instinct je?","Tid for domsavsigelse. Nå som vi har to stykker, bør vi kanskje dra tilbake til basen. Hva sier instinktet ditt?","Czas na osąd. Teraz, kiedy mamy dwa kawałki, możemy chcieć wrócić do bazy. Co mówi ci twój instynkt?","Hora do julgamento. Agora que temos duas peças, talvez a gente queira voltar pra base. O que o seu instinto diz?",,Timpul să judecăm. Acum că avem două piese ne putem întoarce la bază. Ce-ți zice instinctul?,"Время решать. Теперь, когда у нас есть две части, мы можем вернуться на базу. Что твоя интуиция подсказывает тебе?",,Karar verme zamanı. Elimizde iki parça olduğuna göre üsse dönmek isteyebiliriz. İçgüdülerin sana ne söylüyor? -"I have a report that the spectral energy we found near the Bishop is also present by the Oracle, let's be careful.",TXT_SUB_LOG76,STRIFE1.WAD: MAP11,,,"Mám hlášení, že stejná přízračná energie, kterou jsme našli u Biskupa, se nachází také u Věštce. Měli bychom být opatrní.","Jeg har en rapport om, at den spektrale energi, vi fandt i nærheden af biskoppen, også er til stede ved oraklet, så lad os være forsigtige.","Ich habe einen Report, dass die spektrale Energie, die wir beim Bischof gefunden haben, auch beim Orakel präsent ist. Sei vorsichtig.",,,"Tengo un informe de que la energía espectral que encontramos cerca del Obispo también está presente junto al Oráculo, vayamos con cuidado",,"Sain tiedon, että aave-energiaa, jota löysimme Piispan läheltä, on läsnä myös Oraakkelin luona. Ollaan varovaisia.",J'ai un rapport que l'énergie spectrale que l'on a trouvé près de l'évèque est aussi près de l'Oracle. Faisons attention.,Egy beszámoló szerint az Orákulum körülötti lelki színkép megegyezik a Püspökével. Legyünk tehát óvatosak.,"Ho qua un rapporto che ci informa che l'energia spettrale che abbiamo trovato vicino il Vescovo è anche presente vicino l'Oracolo, dobbiamo essere attenti.","ビショップにもあったスペクトラルエネルギーがオラクルにも宿っているという -報告があるわ、気を付けて。","지금 보고를 받았는데, 비숍을 죽인 뒤에 나온 혼령의 기운이 오라클에게도 있데. 조심하자.","Ik heb een verslag dat de spectrale energie die we in de buurt van de bisschop vonden ook aanwezig is bij het Orakel, laten we voorzichtig zijn.","Jeg har en rapport om at den spektrale energien vi fant nær biskopen også er til stede ved oraklet, la oss være forsiktige.","Mam raport, że energia widmowa, którą znaleźliśmy przy Bishopie, jest również obecna przy Wyroczni. Bądźmy ostrożni.",Tenho relatos de que a energia espectral que encontramos perto do Bispo também está presente pelo Oráculo. Vamos com cuidado.,,"Am un raport care spune că energia spectrală a Episcopului e aceeași de pe Oracol, să fim atenți.","Мне доложили, что от Оракула исходит та же энергия, что и от того фантома, которого мы видели у Епископа. Будь начеку!",,"Piskopos'un yanında bulduğumuz spektral enerjinin Kahin'de de olduğuna dair bir rapor aldım, dikkatli olalım." -Macil? Part of this mess? I don't know what to think. I hope you make the right decision.,TXT_SUB_LOG77,,,,"Macil? Částí tohohle bordelu? Nevím, co si o tom mám myslet. Doufám, že se rozhodneš správně.","Macil? En del af dette rod? Jeg ved ikke, hvad jeg skal tro. Jeg håber, du træffer den rigtige beslutning.","Macil? Ein Teil dieser Schweinerei? Ich weiß nicht, was ich denken soll. Hoffentlich triffst du die richtige Entscheidung.",,,¿Macil? ¿Parte de este lío? No sé que pensar. Espero que tomes la decisión correcta.,,"Macil osa tätä sotkua? En tiedä, mitä ajatella. Toivon, että teet oikean päätöksen.","Macil fait partie de tout ce bordel? Je ne sais pas quoi penser, j'espère que tu feras le bon choix..",Macil? Benne lenne ebben a zűrzavarban? nem tudom mit higgyek. Remélem a jó döntést fogod hozni.,Macil? Parte di questa follia? Non so cosa pensare. Spero farai la decisione giusta.,,마실? 이 문제의 장본인 중 한 명이라고? 정말이지 모르겠어. 부디 현명한 판단을 내리길 바래.,Macil? Een deel van deze puinhoop? Ik weet niet wat ik moet denken. Ik hoop dat je de juiste beslissing neemt.,Macil? En del av dette rotet? Jeg vet ikke hva jeg skal tro. Jeg håper du tar den rette avgjørelsen.,"Macil? Część tego bałaganu? Nie wiem, co myśleć. Mam nadzieję, że podejmiesz właściwą decyzję.",O Macil? Fazendo parte dessa confusão toda? Eu não sei o que pensar. Espero que você tome a decisão certa.,,Macil? Parte la dezastrul ăsta? Nu știu ce să cred. Sper să iei decizia bună.,"Мэйсил? Замешан в этом дерьме? Я даже не знаю, что и думать. Я надеюсь, ты сделаешь правильный выбор.",,Macil mi? Bu karmaşanın bir parçası mı? Ne düşüneceğimi bilmiyorum. Umarım doğru kararı verirsiniz. -"Do I trust Macil, who has risked his life for the Front, or some ugly spook? I don't know. But you I trust.",TXT_SUB_LOG78,,,,"Mám věřit Macilovi, který riskoval svůj život kvůli Frontě, nebo nějakému ošklivovi? Já nevím. Ale tobě věřím.","Skal jeg stole på Macil, som har risikeret sit liv for fronten, eller på en grim spøgelse? Jeg ved det ikke. Men jeg stoler på dig.","Ob ich Macil vertraue, der sein Leben für die Front riskiert hat, oder einer hässlichen Schreckgestalt? Ich weiß nicht - aber dir vertraue ich. ",,,"¿Confío en Macil, que ha arriesgado su vida por el Frente, o en un espectro feo? No lo sé. Pero en ti sí confío.",,"Luotanko Maciliin, joka on antanut henkensä alttiiksi Rintamalle, vai johonkin rumaan kummitukseen? En tiedä. Mutta sinuun minä luotan.","Et ce que je fais confiance à Macil qui a risqué sa vie pour le Front, où un affreux jojo? J'en sais rien, mais je fais confiance à toi.","Macilnak hiszek aki kockára tette az életét a Frontért, vagy egy semmirekellőnek? Nem is tudom...de neked biztosan hiszek.","Di chi mi posso fidare, di Macil, che ha rischiato la vita per il Fronte, o di questo essere spettrale? Non lo so. Ma di te mi fido.",,"마실은 프론트를 위해 싸워온 사람이라 의심할 수가 없어. 저 못난이가 거짓말을 하는 걸까? 모르지만, 난 너 만을 믿어.","Vertrouw ik Macil, die zijn leven heeft geriskeerd voor het Front, of een lelijke spook? Ik weet het niet. Maar jij vertrouw ik.","Stoler jeg på Macil, som har risikert livet for Fronten, eller et stygt spøkelse? Jeg vet ikke. Men deg stoler jeg på.","Czy ufać Macilowi, który ryzykował życie dla Frontu, czy jakiemuś brzydkiemu upiorowi? Nie wiem. Ale tobie ufam.","Se eu confio no Macil, que arriscou a sua vida pela Frente, ou num fantasma horroroso? Eu não sei, mas eu você eu confio.",,"Dacă îl cred pe Macil, care și-a riscat viața pentru Front, sau un tip în armură? Nu știu. Dar în tine, cred.","Кому верить: Мэйсилу, который не щадил своей жизни ради Сопротивления, или какому-то уродливому пугалу? Не знаю. Но я доверяю тебе. ",,"Cephe için hayatını riske atan Macil'e mi güveneyim, yoksa çirkin bir hortlağa mı? Bilmiyorum. Ama sana güveniyorum." -Richter has taken over command of our forces. It looks like Macil has been deceiving us all along. His true allegiance was to the Order. What a snake.,TXT_SUB_LOG79,"STRIFE1.WAD: MAP10 - -(After killing Macil without having destroyed the converter in MAP24)",,,"Richter převzal velení našich sil. Zdá se, že nás Macil celou dobu klamal. Ve skutečnosti byl věrný Řádu. Slizák jeden.","Richter har overtaget kommandoen over vores styrker. Det ser ud til, at Macil har bedraget os hele tiden. Hans sande loyalitet var over for Ordenen. Sikke en slange.","Richter hat das Kommando über unsere Truppen übernommen. Es sieh aus, als ob Macil uns alle hintergangen hat und die ganze Zeit für den Orden arbeitete. Was für eine Ratte.",,,Richter ha tomado el mando de nuestras fuerzas. Parece que Macil nos ha estado engañando todo este tiempo. Su verdadera lealtad era a la Orden. Menuda serpiente.,,"Richter on ottanut joukkomme komentoonsa. Näyttää siltä, että Macil on pettänyt meitä alusta alkaen. Hänen todellinen uskollisuutensa on ollut Veljeskunnalle; mikä käärme.","Richter à pris le contrôle de nos forces. Il semble que Macil nous a trompé tout ce temps. Sa vraie allégiance appartenait à l'Ordre, quel ordure..",Richter átvette az irányítást az egységeink felett. Úgy néz ki Macil mindvégig átvert minket. Igazából a Rend embere volt. Micsoda álnok kígyó.,Richter ha assunto il comando delle nostre forze. Sembra che Macil ci avesse ingannato fin dall'inizio. In realtà è sempre stato alleato con l'Ordine. Che serpente.,"リヒターが指揮官の任を引き継いだ。マシルはずっと私達を騙していたなんて。 -あの人がオーダーに真の忠誠を誓っていたなんて、とんだ蛇神憑きだわ。",릭터가 저항군의 새로운 지도자가 될 거야. 내 생각엔 마실이 오랫동안 우리들을 속인 것 같아... 뱀 같은 자식.,Richter heeft het bevel over onze troepen overgenomen. Het lijkt erop dat Macil ons de hele tijd heeft bedrogen. Zijn ware trouw was aan de Orde. Wat een slang.,Richter har overtatt kommandoen over styrkene våre. Det ser ut til at Macil har lurt oss hele tiden. Hans sanne lojalitet var til Ordenen. For en slange.,"Richter przejął dowodzenie nad naszymi siłami. Wygląda na to, że Macil cały czas nas zwodził. Jego prawdziwa wierność była dla Zakonu. Co za wąż.",O Richter assumiu o comando de nossas forças. Parece que o Macil nos enganou esse tempo todo. Sua verdadeira lealdade era à Ordem. Que traíra!,,Richter a preluat controlul asupra forțelor noastre. Se pare că Macil ne-a înșelat în tot acest timp. Aderărata lui loialitate era față de Ordin. Ce șarpe.,"Рихтер принял на себя командование нашими силами. Похоже, что Мэйсил обманывал всех нас с самого начала. На самом деле он был предан Ордену. Подлец.",,Richter kuvvetlerimizin komutasını devraldı. Görünüşe göre Macil başından beri bizi kandırıyormuş. Onun gerçek bağlılığı Tarikat'a imiş. Ne yılan ama. -Damned impressing entranceway. But what we are searching for is on another level. Head down.,TXT_SUB_LOG80,STRIFE1.WAD: MAP26,,,"Zatraceně působivý vchod. Ale to, co hledáme, je na jiném patře. Jdi dolů.","Forbandede imponerende indgang. Men det, vi leder efter, er på et andet niveau. Hovedet nedad.",Verdammt eindrucksvoller Eingang. Aber was wir suchen ist woanders. Lass uns runtergehen.,,,Una entrada tremendamente impresionante. Pero lo que buscamos está en otro nivel. Ve abajo.,,Pahuksen vaikuttava sisäänkäynti. Mutta etsimämme on eri kerroksessa. Suuntaa alas.,"Une entrée sérieusement impressionante. Ce que l'on cherche est à un autre étage, descends.","Elég menő bejárat. Azonban másik emeleten van, amit keresünk. Irány lefelé.",Come ingresso è davvero notevole. Ma quello che cerchiamo si trova su un altro piano. Vai giù.,威風堂々とした玄関ね。でも私達が調べるのは別の階よ。慎重にね。,또 전형적인 멋진 입구네. 하지만 우리가 찾는 것은 또 다른 구역에 있어. 밑으로 향해.,Vervloekt indrukwekkende toegangsweg. Maar wat we zoeken is op een ander niveau. Hoofd naar beneden.,Imponerende inngangsparti. Men det vi leter etter er på et annet nivå. Ned med hodet.,"Cholernie imponujące wejście. Ale to, czego szukamy, jest na innym poziomie. Głowa w dół.",Que entrada bem impressionante. Mas o que procuramos está em outro nível. Desça.,,Impresionantă intrare. Dar ceea ce căutăm e la alt nivel. Mergi jos.,Этот чёртов фасад впечатляет! Но нам нужно на другой этаж. Не высовывайся!,,Etkileyici bir giriş yolu. Ama aradığımız şey başka bir seviyede. Baş aşağı. -What a shame. Our technology is being wasted on torture instead of life.,TXT_SUB_LOG81,STRIFE1.WAD: MAP24,,,Taková škoda. Naše technologie je plýtvána na mučení místo života.,Sikke en skam. Vores teknologi bliver spildt på tortur i stedet for liv.,Was für eine Schande. Unsere Technologie wird für Folter anstatt für Leben verschwendet.,,,Que pena. Nuestra tecnología se está desperdiciando en tortura en vez de vida.,,"Mikä häpeä: Teknologiaamme tuhlataan kidutukseen, sen sijaan että parantaisimme elämää.","C'est tellement dommage. Notre technologie est gâchée, utilisée pour la torture plutôt que sauver des vies.",Milyen kár. A technológiánkat kínzásra pazarolják az élet helyett.,Che peccato. La nostra tecnologia viene sprecata per la tortura invece che per la vita.,残念だな。我々の技術が拷問の為だけに浪費されるとは。,비극적이야. 우리 기술이 생명을 살리는 데 쓰이기는 커녕 고문하는 데 쓰이고 있잖아.,Wat jammer. Onze technologie wordt verspild aan marteling in plaats van leven.,For en skam. Teknologien vår kastes bort på tortur i stedet for liv.,Co za wstyd. Nasza technologia jest marnowana na tortury zamiast na życie.,É uma pena. Nossa tecnologia sendo desperdiçada com tortura ao invés de salvar vidas.,,Ce rușine. Tehnologia noastră e risipită pentru tortură în loc de a crea viață.,"Какой кошмар. Наша технология используется для пыток, а не для жизни.",,Ne utanç verici. Teknolojimiz yaşam yerine işkence için harcanıyor. -"Being vain as hell, they mark their temples with big banners.",TXT_SUB_LOG82,STRIFE1.WAD: MAP21,,,"S takovou ješitností není divu, že si své chrámy značí velkými prapory.","Fordi de er forfængelige som helvede, markerer de deres templer med store bannere.","Eitel wie sie sind, markieren sie ihre Tempel mit riesigen Bannern.",,,"Siendo tan malditamente engreídos, marcan sus templos con grandes estandartes.",,"Läpeensä turhamaisia kun ovat, he vuoraavat temppelinsä suurin tunnuslipuin.","Avec leur orgeuil à la noix, je me ne doutais pas un instant qu'ils allaient mettre d'énormes bannières partout.","Miután felettébb hiúk, ezért hatalmas zászlókkal díszítik a templomaikat.","Essendo vanitosi come pochi, marchiano i loro templi con degli stemmi.",うぬぼれが酷いな、あいつらの寺院はデカいバナーが目に付く。,"고통을 더하자면, 자기네 신전에 커다란 기를 세웠어.","Tevergeefs als de hel, markeren ze hun tempels met grote spandoeken.","Forfengelige som faen, markerer de templene sine med store bannere.","Próżni jak diabli, oznaczają swoje świątynie wielkimi transparentami.",Esses caras são vaidosos pra caramba. Eles marcam os seus templos com esses grandes estandartes.,,"Vanitate la maxim, își marchează templele cu steaguri imense.","Они спесивы до ужаса, раз украшают свои храмы большими флагами.",,"Cehennem kadar kibirli oldukları için, tapınaklarını büyük pankartlarla işaretliyorlar." -Another Sigil piece. We are one step closer to freedom. And you are one step closer to me.,TXT_SUB_LOG83,"STRIFE1.WAD: MAP27 - -(After defeating the Loremaster and collecting the fourth Sigil piece with either Macil or the Oracle alive)",,,Další díl Pečeti. Jsme o krok blíž ke svobodě. A ty jsi o krok blíž ke mě.,Endnu et Sigil-stykke. Vi er et skridt nærmere friheden. Og du er et skridt tættere på mig.,Noch ein Sigil-Teil. Wir sind der Freiheit einen Schritt näher. Und du bist mir einen Schritt näher.,,,Otra pieza del emblema. Estamos un paso más cerca de la libertad. Y tú un paso más cerca de mí.,,Jälleen uusi Sinetin osanen. Olemme taas askeleen lähempänä vapautta. Ja sinä askeleen lähempänä minua.,"Encore une pièce du Sigil. Un pas de plus vers la liberté, et un pas de plus vers moi.",Egy másik pecsét darab. Egy lépéssel közelebb vagyunk a szabadsághoz. Te pedig egy lépéssel közelebb hozzám.,Un altro pezzo del Sigillo. Siamo ancora più vicini alla libertà. E tu sei ancora più vicino a me.,"更なるシジルの欠片だ。私達の自由にまた一歩近づいたわ。 -そして私にも一歩近づいている。",또 다른 시질 조각이야. 자유를 향한 길이 거의 얼마 안 남았어. 나와 만나는 길도 얼마 안 남았고.,Nog een Sigil stuk. We zijn een stap dichter bij de vrijheid. En jij bent een stap dichter bij mij.,Enda en Sigil-brikke. Vi er ett skritt nærmere friheten. Og du er ett skritt nærmere meg.,Kolejny kawałek Sigil. Jesteśmy o krok bliżej wolności. A ty jesteś o krok bliżej mnie.,Mais uma peça do Sigilo. Estamos cada vez mais próximos da liberdade. E você cada vez mais próximo de mim.,,Altă piesă de Sigiul. Suntem cu un pas mai aproape de libertate. Și tu ești cu un pas mai aproape de mine.,Очередной фрагмент Печати. Теперь мы ещё на шаг ближе к освобождению. А ты — ещё на шаг ближе ко мне.,,Başka bir Sigil parçası. Özgürlüğe bir adım daha yaklaştık. Ve sen de bana bir adım daha yaklaştın. -"From the looks of it, we need the full Sigil to unlock this puppy. Something tells me this is the end of the rainbow.",TXT_SUB_LOG84,STRIFE1.WAD: MAP27,,,"Vypadá to, že tohohle mazlíčka jde otevřít pouze s úplnou Pečetí. Něco mi říká, že jsme našli konec duhy.","Som det ser ud nu, skal vi bruge hele Sigil'en for at låse denne hvalp op. Noget siger mig, at dette er enden af regnbuen.","Wie es aussieht brauchen wir das komplette Sigil um das Ding hier zu öffnen. Etwas sagt mir, dass wir am Ende unserer Reise angekommen sind.",,,Parece que necesitamos el Emblema completo para abrir este pequeñín. Algo me dice que este es el final del arcoiris.,,"Näyttää siltä, että tarvitsemme täyden Sinetin tämän veijarin avaamiseksi. Jotenkin tuntuu siltä, että sateenkaari päätyy tänne.",On dirait qu'il nous faut toutes les pièces du Sigil pour ouvrir ce joujou. Quelque chose me dit que c'est là que l'arc-en-ciel finit.,"Úgy néz ki az egész pecsét kell, hogy bejussunk itt. Azt sugallja nekem, hogy ez lesz valószínűleg a végkifejlett.","Da quel che sembra, abbiamo bisogno del Sigillo intero per accedere qua. Qualcosa mi dice che siamo alla fine del tunnel.","この形状を見た所、解除するには完成したシジルを持って、ちっこい台座に乗るんだわ。 -誰もが雨上がりの虹を見るために。","열쇠 구멍의 모습을 보아하니, 완성된 시질이 있어야만 열 수 있는 것 같아. 이 모든 모험의 도착지점인 것 같기도 하고.","Zoals het er nu uitziet, hebben we de volledige Sigil nodig om deze pup te ontgrendelen. Iets zegt me dat dit het einde van de regenboog is.",Det ser ut til at vi trenger hele sigillet for å låse opp denne valpen. Noe sier meg at dette er enden på regnbuen.,"Wygląda na to, że potrzebujemy pełnego Sigilu, aby odblokować tego szczeniaka. Coś mi mówi, że to koniec tęczy.","Pelo que parece, precisamos do Sigilo completo para destrancar essa belezinha. Algo me diz que este é o fim do arco-íris.",,"Din câte se pare, aven nevoie de întreg Sigiliul pentru a deschide puiul. Ceva îmi spune că ăsta e capătul curcubeului.","Судя по всему, открыть этот замок сможет только завершённая Печать. Что-то мне подсказывает, что мы достигли конца радуги!",,"Görünüşe göre, bu yavruyu açmak için Sigil'in tamamına ihtiyacımız var. İçimden bir ses bunun gökkuşağının sonu olduğunu söylüyor." +貴方今、私と同じ事考えてる?","잠깐, 오라클이 전에 권력을 상징하는 문양을 따라가면 만날 수 있다고 했지? 너 나랑 같은 생각 하고 있지?","Wacht, het Orakel zei dat we hem zouden kennen aan zijn machtssymbool. Denk jij wat ik denk?","Vent, oraklet sa at vi ville kjenne ham igjen på maktsymbolet hans. Tenker du det samme som meg?","Czekaj, Wyrocznia powiedziała, że poznamy go po symbolu mocy. Myślisz o tym, co ja myślę?","Peraí, o Oráculo disse que reconheceríamos ele pelo seu símbolo de poder. Você está pensando o mesmo que eu?",,"Stai, Oracolul zicea că îl vom cunoaște după însemnul lui. Te gândeștila același lucru?","Подожди — Оракул сказал, что мы найдём его по символу власти. Ты думаешь о том же, о чём и я?",,"Vänta, Oraklet sa att vi skulle känna igen honom på hans kraftsymbol. Tänker du samma sak som jag?","Bekle, Kahin onu güç sembolünden tanıyacağımızı söylemişti. Sen de benim düşündüğümü mü düşünüyorsun?" +"These guys got a decorating idea that works, and they just beat it to death.",TXT_SUB_LOG73,,,,Tihle lidi dostali dobrý nápad na výzdobu a pak ho zadupali do země.,"Disse fyre har en dekorativ idé, som virker, og de slår den bare ihjel.","Diese Typen haben ein Design das funktioniert, aber sie haben es total übertrieben.",,,"Estos tipos tuvieron una idea de decoración que funciona, y la han matado a palos.",,"Näille tyypeille välähti yksi toimiva sisustusidea, ja he vain kuluttivat sen loppuun.",Cest types avaient une super bonne idée déco et ils ont fait n'importe quoi avec.,"Ezeknek az embereknek volt egy jó dekorációs ötlete, csak némileg túlzásba vitték.","Questi qua hanno avuto una buona idea di come decorare, e poi ci sono andati ben troppo oltre.",,"저놈들은 도움이 되는 생각을 가지고 있기는 한데, 다 쓸데없이 망치고 있어.","Deze jongens hebben een decoratief idee dat werkt, en ze hebben het gewoon doodgeslagen.","De har en dekorasjonsidé som funker, og så slår de den i hjel.","Ci kolesie mają pomysł na wystrój, który działa, a oni go po prostu zepsuli na śmierć.",Esses caras tinham uma idéia de decoração que funcionava e depois mandaram tudo pro saco.,,Tipii ăștia au o idee despre decorații în aplicare.,"У этих ребят была отличная идея декора, но они загубили её на корню.",,"De här killarna har en dekorationsidé som fungerar, och de bara slår ihjäl den.",Bu adamların işe yarayan bir dekorasyon fikri var ve onu öldüresiye dövüyorlar. +Did you see that weird spectre that came out of the Bishop's body? Where have I seen that before?,TXT_SUB_LOG74,MAP16: After killing the Bishop,,,"Viděl jsi ten divný přízrak, který vyšel z Biskupova těla? Kde jsem ho jen předtím viděla?","Så du det underlige spøgelse, der kom ud af biskoppens krop? Hvor har jeg set det før?","Hast du diesen seltsamen Schemen gesehen, der aus seinem Körper herauskam? Wo haben wir das schonmal gesehen?",,,¿Viste ese extraño espectro que salió del cuerpo del Obispo? ¿Donde lo he visto antes?,,"Näitkö tuon oudon aaveen, joka nousi Piispan ruumiista? Missä olen nähnyt sen aiemmin?",Tu a vu ce spectre bizarre qui est sorti du corps de l'évèque? On a pas vu ça quelque part avant?,Láttad azt a fura szellemet ami kijött a Püspök teteméből? Hol láttam én már azt?,Hai visto quello strano spettro che è uscito dal corpo del Vescovo? Dove l'ho già visto prima?,"ビショップの体から出てきたあの奇妙な幽体を見た? +以前に何処かで見た気がするけど?",그나저나 비숍 몸에서 튀어나왔던 검은 물체 봤어? 전에 본 적이 있나?,Zag je dat rare spook dat uit het lichaam van de bisschop kwam? Waar heb ik dat eerder gezien?,Så du det rare spøkelset som kom ut av biskopens kropp? Hvor har jeg sett det før?,"Widziałeś to dziwne widmo, które wyszło z ciała biskupa? Gdzie ja to już widziałem?",Você viu aquele espectro estranho que saiu do corpo do BIspo? Onde foi que eu já vi isso antes?,,Ai văzut acel spectru ieșind din Episcop? Unde am mai văzut asta?,"Видел тот странный фантом, вышедший из тела Епископа? Где я могла видеть такое раньше?",,Såg du det konstiga spöket som kom ut ur biskopens kropp? Var har jag sett det förut?,Piskoposun bedeninden çıkan o garip hayaleti gördün mü? Bunu daha önce nerede görmüştüm? +Judgment call time. Now that we got two pieces we might wanna return to base. What does your instinct tell you?,TXT_SUB_LOG75,,,,"Čas se rozhodnout. Teď, když máme dva díly, bychom se možná měli vrátit na základnu. Co ti říká intuice?","Det er tid til at dømme. Nu hvor vi har to stykker, bør vi måske vende tilbage til basen. Hvad siger dit instinkt dig?","Zeit für eine Gewissensentscheidung. Jetzt wo wir zwei Teile haben, sollten wir zur Basis zurückkehren. Was denkst du?",,,Hora del Juicio. Ahora que tienes dos piezas podríamos regresar a la base. ¿Qué te dice tú instinto?,,"Aika tehdä päätös: Nyt, kun meillä on kaksi osasta, saattaisimme haluta palata tukikohtaan. Mitä vaistosi sanoo?","C'est l'heure du jugement, on a deux pièce, il est temps de retourner à la base. Que te dit ton instinct?","Kupaktanács. Most, hogy megszereztün két darabot, vissza is térhetünk a bázisba. mit mond az ösztönöd?",È l'ora di decidere. Adesso che abbiamo due pezzi sarebbe il caso di tornare alla base. Cosa dice il tuo istinto?,,심판의 시간이야. 시질 두 조각을 모았으니 본부로 돌아가자. 이제 너의 본능은 무슨 해답을 내놓을까?,"Oordeel roep tijd. Nu we twee stukken hebben, willen we misschien terug naar de basis. Wat zegt je instinct je?","Tid for domsavsigelse. Nå som vi har to stykker, bør vi kanskje dra tilbake til basen. Hva sier instinktet ditt?","Czas na osąd. Teraz, kiedy mamy dwa kawałki, możemy chcieć wrócić do bazy. Co mówi ci twój instynkt?","Hora do julgamento. Agora que temos duas peças, talvez a gente queira voltar pra base. O que o seu instinto diz?",,Timpul să judecăm. Acum că avem două piese ne putem întoarce la bază. Ce-ți zice instinctul?,"Время решать. Теперь, когда у нас есть две части, мы можем вернуться на базу. Что твоя интуиция подсказывает тебе?",,Det är dags att döma. Nu när vi har två delar kanske vi borde återvända till basen. Vad säger din instinkt dig?,Karar verme zamanı. Elimizde iki parça olduğuna göre üsse dönmek isteyebiliriz. İçgüdülerin sana ne söylüyor? +"I have a report that the spectral energy we found near the Bishop is also present by the Oracle, let's be careful.",TXT_SUB_LOG76,MAP11: After killing the Bishop and going to MAP12's entrance,,,"Mám hlášení, že stejná přízračná energie, kterou jsme našli u Biskupa, se nachází také u Věštce. Měli bychom být opatrní.","Jeg har en rapport om, at den spektrale energi, vi fandt i nærheden af biskoppen, også er til stede ved oraklet, så lad os være forsigtige.","Ich habe einen Report, dass die spektrale Energie, die wir beim Bischof gefunden haben, auch beim Orakel präsent ist. Sei vorsichtig.",,,"Tengo un informe de que la energía espectral que encontramos cerca del Obispo también está presente junto al Oráculo, vayamos con cuidado",,"Sain tiedon, että aave-energiaa, jota löysimme Piispan läheltä, on läsnä myös Oraakkelin luona. Ollaan varovaisia.",J'ai un rapport que l'énergie spectrale que l'on a trouvé près de l'évèque est aussi près de l'Oracle. Faisons attention.,Egy beszámoló szerint az Orákulum körülötti lelki színkép megegyezik a Püspökével. Legyünk tehát óvatosak.,"Ho qua un rapporto che ci informa che l'energia spettrale che abbiamo trovato vicino il Vescovo è anche presente vicino l'Oracolo, dobbiamo essere attenti.","ビショップにもあったスペクトラルエネルギーがオラクルにも宿っているという +報告があるわ、気を付けて。","지금 보고를 받았는데, 비숍을 죽인 뒤에 나온 혼령의 기운이 오라클에게도 있데. 조심하자.","Ik heb een verslag dat de spectrale energie die we in de buurt van de bisschop vonden ook aanwezig is bij het Orakel, laten we voorzichtig zijn.","Jeg har en rapport om at den spektrale energien vi fant nær biskopen også er til stede ved oraklet, la oss være forsiktige.","Mam raport, że energia widmowa, którą znaleźliśmy przy Bishopie, jest również obecna przy Wyroczni. Bądźmy ostrożni.",Tenho relatos de que a energia espectral que encontramos perto do Bispo também está presente pelo Oráculo. Vamos com cuidado.,,"Am un raport care spune că energia spectrală a Episcopului e aceeași de pe Oracol, să fim atenți.","Мне доложили, что от Оракула исходит та же энергия, что и от того фантома, которого мы видели у Епископа. Будь начеку!",,"Jag har en rapport om att den spektrala energin som vi hittade nära biskopen också finns hos oraklet, vi måste vara försiktiga.","Piskopos'un yanında bulduğumuz spektral enerjinin Kahin'de de olduğuna dair bir rapor aldım, dikkatli olalım." +Macil? Part of this mess? I don't know what to think. I hope you make the right decision.,TXT_SUB_LOG77,,,,"Macil? Částí tohohle bordelu? Nevím, co si o tom mám myslet. Doufám, že se rozhodneš správně.","Macil? En del af dette rod? Jeg ved ikke, hvad jeg skal tro. Jeg håber, du træffer den rigtige beslutning.","Macil? Ein Teil dieser Schweinerei? Ich weiß nicht, was ich denken soll. Hoffentlich triffst du die richtige Entscheidung.",,,¿Macil? ¿Parte de este lío? No sé que pensar. Espero que tomes la decisión correcta.,,"Macil osa tätä sotkua? En tiedä, mitä ajatella. Toivon, että teet oikean päätöksen.","Macil fait partie de tout ce bordel? Je ne sais pas quoi penser, j'espère que tu feras le bon choix..",Macil? Benne lenne ebben a zűrzavarban? nem tudom mit higgyek. Remélem a jó döntést fogod hozni.,Macil? Parte di questa follia? Non so cosa pensare. Spero farai la decisione giusta.,,마실? 이 문제의 장본인 중 한 명이라고? 정말이지 모르겠어. 부디 현명한 판단을 내리길 바래.,Macil? Een deel van deze puinhoop? Ik weet niet wat ik moet denken. Ik hoop dat je de juiste beslissing neemt.,Macil? En del av dette rotet? Jeg vet ikke hva jeg skal tro. Jeg håper du tar den rette avgjørelsen.,"Macil? Część tego bałaganu? Nie wiem, co myśleć. Mam nadzieję, że podejmiesz właściwą decyzję.",O Macil? Fazendo parte dessa confusão toda? Eu não sei o que pensar. Espero que você tome a decisão certa.,,Macil? Parte la dezastrul ăsta? Nu știu ce să cred. Sper să iei decizia bună.,"Мэйсил? Замешан в этом дерьме? Я даже не знаю, что и думать. Я надеюсь, ты сделаешь правильный выбор.",,Macil? En del av den här röran? Jag vet inte vad jag ska tro. Jag hoppas att du fattar rätt beslut.,Macil mi? Bu karmaşanın bir parçası mı? Ne düşüneceğimi bilmiyorum. Umarım doğru kararı verirsiniz. +"Do I trust Macil, who has risked his life for the Front, or some ugly spook? I don't know. But you I trust.",TXT_SUB_LOG78,,,,"Mám věřit Macilovi, který riskoval svůj život kvůli Frontě, nebo nějakému ošklivovi? Já nevím. Ale tobě věřím.","Skal jeg stole på Macil, som har risikeret sit liv for fronten, eller på en grim spøgelse? Jeg ved det ikke. Men jeg stoler på dig.","Ob ich Macil vertraue, der sein Leben für die Front riskiert hat, oder einer hässlichen Schreckgestalt? Ich weiß nicht - aber dir vertraue ich. ",,,"¿Confío en Macil, que ha arriesgado su vida por el Frente, o en un espectro feo? No lo sé. Pero en ti sí confío.",,"Luotanko Maciliin, joka on antanut henkensä alttiiksi Rintamalle, vai johonkin rumaan kummitukseen? En tiedä. Mutta sinuun minä luotan.","Et ce que je fais confiance à Macil qui a risqué sa vie pour le Front, où un affreux jojo? J'en sais rien, mais je fais confiance à toi.","Macilnak hiszek aki kockára tette az életét a Frontért, vagy egy semmirekellőnek? Nem is tudom...de neked biztosan hiszek.","Di chi mi posso fidare, di Macil, che ha rischiato la vita per il Fronte, o di questo essere spettrale? Non lo so. Ma di te mi fido.",,"마실은 프론트를 위해 싸워온 사람이라 의심할 수가 없어. 저 못난이가 거짓말을 하는 걸까? 모르지만, 난 너 만을 믿어.","Vertrouw ik Macil, die zijn leven heeft geriskeerd voor het Front, of een lelijke spook? Ik weet het niet. Maar jij vertrouw ik.","Stoler jeg på Macil, som har risikert livet for Fronten, eller et stygt spøkelse? Jeg vet ikke. Men deg stoler jeg på.","Czy ufać Macilowi, który ryzykował życie dla Frontu, czy jakiemuś brzydkiemu upiorowi? Nie wiem. Ale tobie ufam.","Se eu confio no Macil, que arriscou a sua vida pela Frente, ou num fantasma horroroso? Eu não sei, mas eu você eu confio.",,"Dacă îl cred pe Macil, care și-a riscat viața pentru Front, sau un tip în armură? Nu știu. Dar în tine, cred.","Кому верить: Мэйсилу, который не щадил своей жизни ради Сопротивления, или какому-то уродливому пугалу? Не знаю. Но я доверяю тебе. ",,"Ska jag lita på Macil, som har riskerat sitt liv för fronten, eller på något fult spöke? Jag vet inte. Men dig litar jag på.","Cephe için hayatını riske atan Macil'e mi güveneyim, yoksa çirkin bir hortlağa mı? Bilmiyorum. Ama sana güveniyorum." +Richter has taken over command of our forces. It looks like Macil has been deceiving us all along. His true allegiance was to the Order. What a snake.,TXT_SUB_LOG79,MAP10: After killing Macil (Spectre) without having destroyed the converter in MAP24.,,,"Richter převzal velení našich sil. Zdá se, že nás Macil celou dobu klamal. Ve skutečnosti byl věrný Řádu. Slizák jeden.","Richter har overtaget kommandoen over vores styrker. Det ser ud til, at Macil har bedraget os hele tiden. Hans sande loyalitet var over for Ordenen. Sikke en slange.","Richter hat das Kommando über unsere Truppen übernommen. Es sieh aus, als ob Macil uns alle hintergangen hat und die ganze Zeit für den Orden arbeitete. Was für eine Ratte.",,,Richter ha tomado el mando de nuestras fuerzas. Parece que Macil nos ha estado engañando todo este tiempo. Su verdadera lealtad era a la Orden. Menuda víbora.,,"Richter on ottanut joukkomme komentoonsa. Näyttää siltä, että Macil on pettänyt meitä alusta alkaen. Hänen todellinen uskollisuutensa on ollut Veljeskunnalle; mikä käärme.","Richter à pris le contrôle de nos forces. Il semble que Macil nous a trompé tout ce temps. Sa vraie allégiance appartenait à l'Ordre, quel ordure..",Richter átvette az irányítást az egységeink felett. Úgy néz ki Macil mindvégig átvert minket. Igazából a Rend embere volt. Micsoda álnok kígyó.,Richter ha assunto il comando delle nostre forze. Sembra che Macil ci avesse ingannato fin dall'inizio. In realtà è sempre stato alleato con l'Ordine. Che serpente.,"リヒターが指揮官の任を引き継いだ。マシルはずっと私達を騙していたなんて。 +あの人がオーダーに真の忠誠を誓っていたなんて、とんだ蛇神憑きだわ。",릭터가 저항군의 새로운 지도자가 될 거야. 내 생각엔 마실이 오랫동안 우리들을 속인 것 같아... 뱀 같은 자식.,Richter heeft het bevel over onze troepen overgenomen. Het lijkt erop dat Macil ons de hele tijd heeft bedrogen. Zijn ware trouw was aan de Orde. Wat een slang.,Richter har overtatt kommandoen over styrkene våre. Det ser ut til at Macil har lurt oss hele tiden. Hans sanne lojalitet var til Ordenen. For en slange.,"Richter przejął dowodzenie nad naszymi siłami. Wygląda na to, że Macil cały czas nas zwodził. Jego prawdziwa wierność była dla Zakonu. Co za wąż.",O Richter assumiu o comando de nossas forças. Parece que o Macil nos enganou esse tempo todo. Sua verdadeira lealdade era à Ordem. Que traíra!,,Richter a preluat controlul asupra forțelor noastre. Se pare că Macil ne-a înșelat în tot acest timp. Aderărata lui loialitate era față de Ordin. Ce șarpe.,"Рихтер принял на себя командование нашими силами. Похоже, что Мэйсил обманывал всех нас с самого начала. На самом деле он был предан Ордену. Подлец.",,Richter har tagit över befälet över våra styrkor. Det verkar som om Macil har lurat oss hela tiden. Hans sanna lojalitet var till Orden. Vilken orm.,Richter kuvvetlerimizin komutasını devraldı. Görünüşe göre Macil başından beri bizi kandırıyormuş. Onun gerçek bağlılığı Tarikat'a imiş. Ne yılan ama. +Damned impressing entranceway. But what we are searching for is on another level. Head down.,TXT_SUB_LOG80,MAP26: Entrance.,,,"Zatraceně působivý vchod. Ale to, co hledáme, je na jiném patře. Jdi dolů.","Forbandede imponerende indgang. Men det, vi leder efter, er på et andet niveau. Hovedet nedad.",Verdammt eindrucksvoller Eingang. Aber was wir suchen ist woanders. Lass uns runtergehen.,,,Una entrada tremendamente impresionante. Pero lo que buscamos está en otro nivel. Ve abajo.,,Pahuksen vaikuttava sisäänkäynti. Mutta etsimämme on eri kerroksessa. Suuntaa alas.,"Une entrée sérieusement impressionante. Ce que l'on cherche est à un autre étage, descends.","Elég menő bejárat. Azonban másik emeleten van, amit keresünk. Irány lefelé.",Come ingresso è davvero notevole. Ma quello che cerchiamo si trova su un altro piano. Vai giù.,威風堂々とした玄関ね。でも私達が調べるのは別の階よ。慎重にね。,또 전형적인 멋진 입구네. 하지만 우리가 찾는 것은 또 다른 구역에 있어. 밑으로 향해.,Vervloekt indrukwekkende toegangsweg. Maar wat we zoeken is op een ander niveau. Hoofd naar beneden.,Imponerende inngangsparti. Men det vi leter etter er på et annet nivå. Ned med hodet.,"Cholernie imponujące wejście. Ale to, czego szukamy, jest na innym poziomie. Głowa w dół.",Que entrada bem impressionante. Mas o que procuramos está em outro nível. Desça.,,Impresionantă intrare. Dar ceea ce căutăm e la alt nivel. Mergi jos.,Этот чёртов фасад впечатляет! Но нам нужно на другой этаж. Не высовывайся!,,Jävligt imponerande entré. Men det vi söker är på en annan nivå. Huvudet neråt.,Etkileyici bir giriş yolu. Ama aradığımız şey başka bir seviyede. Baş aşağı. +What a shame. Our technology is being wasted on torture instead of life.,TXT_SUB_LOG81,MAP24: Hall to converter room.,,,Taková škoda. Naše technologie je plýtvána na mučení místo života.,Sikke en skam. Vores teknologi bliver spildt på tortur i stedet for liv.,Was für eine Schande. Unsere Technologie wird für Folter anstatt für Leben verschwendet.,,,Que pena. Nuestra tecnología se está desperdiciando en tortura en vez de vida.,,"Mikä häpeä: Teknologiaamme tuhlataan kidutukseen, sen sijaan että parantaisimme elämää.","C'est tellement dommage. Notre technologie est gâchée, utilisée pour la torture plutôt que sauver des vies.",Milyen kár. A technológiánkat kínzásra pazarolják az élet helyett.,Che peccato. La nostra tecnologia viene sprecata per la tortura invece che per la vita.,残念だな。我々の技術が拷問の為だけに浪費されるとは。,비극적이야. 우리 기술이 생명을 살리는 데 쓰이기는 커녕 고문하는 데 쓰이고 있잖아.,Wat jammer. Onze technologie wordt verspild aan marteling in plaats van leven.,For en skam. Teknologien vår kastes bort på tortur i stedet for liv.,Co za wstyd. Nasza technologia jest marnowana na tortury zamiast na życie.,É uma pena. Nossa tecnologia sendo desperdiçada com tortura ao invés de salvar vidas.,,Ce rușine. Tehnologia noastră e risipită pentru tortură în loc de a crea viață.,"Какой кошмар. Наша технология используется для пыток, а не для жизни.",,Vilken skam. Vår teknik slösas bort på tortyr i stället för liv.,Ne utanç verici. Teknolojimiz yaşam yerine işkence için harcanıyor. +"Being vain as hell, they mark their temples with big banners.",TXT_SUB_LOG82,MAP21: Entrance to MAP26 near to an Inquisitor's banner.,,,"S takovou ješitností není divu, že si své chrámy značí velkými prapory.","Fordi de er forfængelige som helvede, markerer de deres templer med store bannere.","Eitel wie sie sind, markieren sie ihre Tempel mit riesigen Bannern.",,,"Siendo tan malditamente engreídos, marcan sus templos con grandes estandartes.",,"Läpeensä turhamaisia kun ovat, he vuoraavat temppelinsä suurin tunnuslipuin.","Avec leur orgeuil à la noix, je me ne doutais pas un instant qu'ils allaient mettre d'énormes bannières partout.","Miután felettébb hiúk, ezért hatalmas zászlókkal díszítik a templomaikat.","Essendo vanitosi come pochi, marchiano i loro templi con degli stemmi.",うぬぼれが酷いな、あいつらの寺院はデカいバナーが目に付く。,"고통을 더하자면, 자기네 신전에 커다란 기를 세웠어.","Tevergeefs als de hel, markeren ze hun tempels met grote spandoeken.","Forfengelige som faen, markerer de templene sine med store bannere.","Próżni jak diabli, oznaczają swoje świątynie wielkimi transparentami.",Esses caras são vaidosos pra caramba. Eles marcam os seus templos com esses grandes estandartes.,,"Vanitate la maxim, își marchează templele cu steaguri imense.","Они спесивы до ужаса, раз украшают свои храмы большими флагами.",,Eftersom de är fåfänga som fan markerar de sina tempel med stora banderoller.,"Cehennem kadar kibirli oldukları için, tapınaklarını büyük pankartlarla işaretliyorlar." +Another Sigil piece. We are one step closer to freedom. And you are one step closer to me.,TXT_SUB_LOG83,MAP27: After killing the Loremaster with either Macil or the Oracle alive.,,,Další díl Pečeti. Jsme o krok blíž ke svobodě. A ty jsi o krok blíž ke mě.,Endnu et Sigil-stykke. Vi er et skridt nærmere friheden. Og du er et skridt tættere på mig.,Noch ein Sigil-Teil. Wir sind der Freiheit einen Schritt näher. Und du bist mir einen Schritt näher.,,,Otra pieza del emblema. Estamos un paso más cerca de la libertad. Y tú un paso más cerca de mí.,,Jälleen uusi Sinetin osanen. Olemme taas askeleen lähempänä vapautta. Ja sinä askeleen lähempänä minua.,"Encore une pièce du Sigil. Un pas de plus vers la liberté, et un pas de plus vers moi.",Egy másik pecsét darab. Egy lépéssel közelebb vagyunk a szabadsághoz. Te pedig egy lépéssel közelebb hozzám.,Un altro pezzo del Sigillo. Siamo ancora più vicini alla libertà. E tu sei ancora più vicino a me.,"更なるシジルの欠片だ。私達の自由にまた一歩近づいたわ。 +そして私にも一歩近づいている。",또 다른 시질 조각이야. 자유를 향한 길이 거의 얼마 안 남았어. 나와 만나는 길도 얼마 안 남았고.,Nog een Sigil stuk. We zijn een stap dichter bij de vrijheid. En jij bent een stap dichter bij mij.,Enda en Sigil-brikke. Vi er ett skritt nærmere friheten. Og du er ett skritt nærmere meg.,Kolejny kawałek Sigil. Jesteśmy o krok bliżej wolności. A ty jesteś o krok bliżej mnie.,Mais uma peça do Sigilo. Estamos cada vez mais próximos da liberdade. E você cada vez mais próximo de mim.,,Altă piesă de Sigiul. Suntem cu un pas mai aproape de libertate. Și tu ești cu un pas mai aproape de mine.,Очередной фрагмент Печати. Теперь мы ещё на шаг ближе к освобождению. А ты — ещё на шаг ближе ко мне.,,Ännu ett Sigil-stycke. Vi är ett steg närmare friheten. Och du är ett steg närmare mig.,Başka bir Sigil parçası. Özgürlüğe bir adım daha yaklaştık. Ve sen de bana bir adım daha yaklaştın. +"From the looks of it, we need the full Sigil to unlock this puppy. Something tells me this is the end of the rainbow.",TXT_SUB_LOG84,MAP27: Button to MAP28.,,,"Vypadá to, že tohohle mazlíčka jde otevřít pouze s úplnou Pečetí. Něco mi říká, že jsme našli konec duhy.","Som det ser ud nu, skal vi bruge hele Sigil'en for at låse denne hvalp op. Noget siger mig, at dette er enden af regnbuen.","Wie es aussieht brauchen wir das komplette Sigil um das Ding hier zu öffnen. Etwas sagt mir, dass wir am Ende unserer Reise angekommen sind.",,,Parece que necesitamos el Emblema completo para abrir este pequeñín. Algo me dice que este es el final del arcoiris.,,"Näyttää siltä, että tarvitsemme täyden Sinetin tämän veijarin avaamiseksi. Jotenkin tuntuu siltä, että sateenkaari päätyy tänne.",On dirait qu'il nous faut toutes les pièces du Sigil pour ouvrir ce joujou. Quelque chose me dit que c'est là que l'arc-en-ciel finit.,"Úgy néz ki az egész pecsét kell, hogy bejussunk itt. Azt sugallja nekem, hogy ez lesz valószínűleg a végkifejlett.","Da quel che sembra, abbiamo bisogno del Sigillo intero per accedere qua. Qualcosa mi dice che siamo alla fine del tunnel.","この形状を見た所、解除するには完成したシジルを持って、ちっこい台座に乗るんだわ。 +誰もが雨上がりの虹を見るために。","열쇠 구멍의 모습을 보아하니, 완성된 시질이 있어야만 열 수 있는 것 같아. 이 모든 모험의 도착지점인 것 같기도 하고.","Zoals het er nu uitziet, hebben we de volledige Sigil nodig om deze pup te ontgrendelen. Iets zegt me dat dit het einde van de regenboog is.",Det ser ut til at vi trenger hele sigillet for å låse opp denne valpen. Noe sier meg at dette er enden på regnbuen.,"Wygląda na to, że potrzebujemy pełnego Sigilu, aby odblokować tego szczeniaka. Coś mi mówi, że to koniec tęczy.","Pelo que parece, precisamos do Sigilo completo para destrancar essa belezinha. Algo me diz que este é o fim do arco-íris.",,"Din câte se pare, aven nevoie de întreg Sigiliul pentru a deschide puiul. Ceva îmi spune că ăsta e capătul curcubeului.","Судя по всему, открыть этот замок сможет только завершённая Печать. Что-то мне подсказывает, что мы достигли конца радуги!",,Som det ser ut nu behöver vi hela Sigil för att låsa upp den här valpen. Något säger mig att det här är slutet på regnbågen.,"Görünüşe göre, bu yavruyu açmak için Sigil'in tamamına ihtiyacımız var. İçimden bir ses bunun gökkuşağının sonu olduğunu söylüyor." You wield the power of the complete Sigil. What do you say we go get some closure.,TXT_SUB_LOG85,"STRIFE1.WAD: MAP12 (After killing the Oracle and collecting the final Sigil piece with both Macil and the Loremaster dead) @@ -12133,52 +12746,47 @@ MAP27 (After defeating the Loremaster and collecting the final Sigil piece with Macil and the Oracle dead)",,,"Vládneš mocí složené Pečetě. Co říkáš na to, završit to tady?","Du har magten af det komplette sigil. Hvad siger du til, at vi får en afslutning?","Du hast die Macht des kompletten Sigils. Was hälst du davon, wenn wir das hier beenden?",,,Empuñas el poder del Emblema completo. Que te parece si conseguimos algo de clausura.,,Täyden Sinetin voima on hallussasi. Mitäpä jos hakisimme päätöstä. ,Tu possède le pouvoir du Sigil complet. Ca te dit qu'on aille finir tout ça?,"Tied a Pecsét teljes ereje. Mit szólnál ahhoz, ha rövidre zárnánk a dolgokat.",Hai il potere del Sigillo completo. Che ne dici di mettere fine a questa faccenda.,"貴方はもはや完全なシジルの力を行使できるわけね。 後は言いがかりでもしてここを閉鎖させましょう。 -",시질의 완전한 힘은 이제 네 손에 있어. 종지부를 찍을 준비 됐어?,Je gebruikt de kracht van de hele Sigil. Wat zeg je ervan als we de zaak gaan afsluiten.,"Du har kraften til hele sigillet, og du kan bruke det. Hva sier du til å få en avslutning?","Władasz mocą kompletnego Sigilu. Co powiesz na to, żebyśmy się zamknęli.",Você tem o poder do Sigilo completo em suas mãos. Que tal a gente ir atrás de um desfecho?,,Ai puterea întregului Sigiliu. Ce zici dacă primim o încheiere?,Теперь ты владеешь мощью завершённой Печати. Мы уже близко — давай покончим с этим.,,"Sigil'in tamamının gücüne sahipsin. Ne dersin, gidip biraz kapanış yapalım mı?" -"High noon, my hero. Prepare to embrace glory.",TXT_SUB_LOG86,,,,"Souboj v pravé poledne, můj hrdino. Připrav se přijmout slávu.","Klokken tolv, min helt. Gør dig klar til at omfavne æren.","Die Stunde ist gekommen, mein Held. Bereite dich auf Ruhm vor.",,,"Es la hora final, mi héroe. Prepárate para la gloria.",,"Ratkaisun hetki, sankarini. Valmistaudu pukeutumaan kunniaan.","Le soleil est au zénith, mon héros. Prépare toi à rencontrer ta gloire.",Eljött az idő hősöm. Ragadd meg a lehetőséget.,"Mezzogiorno di fuoco, mio eroe. Preparati ad abbracciare la gloria.",いい気分でしょ、私の英雄。栄光を受け入れる準備をしなさい。,"석양이 지고 있어, 나의 영웅. 영광을 누릴 준비해!","Hoog middaguur, mijn held. Bereid je voor om de glorie te omarmen.","Klokka er tolv, min helt. Forbered deg på å omfavne æren.","W samo południe, mój bohaterze. Przygotuj się na przyjęcie chwały.","Chegou a hora, meu herói. Se prepare para abraçar a glória.",,"Timpul pentru glorie, eroul meu.","Самое время, мой герой! Ты будешь купаться в славе.",,"Öğle vakti, kahramanım. Zaferi kucaklamaya hazırlan." -"Well, so much for prognostication. Hold it, Macil is calling us back. Let's get out of here in one piece.",TXT_SUB_LOG87,"STRIFE1.WAD: MAP12 - -(After killing the Oracle with Macil alive)",,,"No, to by bylo pro prorokování. Počkat, Macil nás volá zpět. Vypadněme odsud vcelku.","Så meget for prognoser. Vent, Macil kalder os tilbage. Lad os komme ud herfra i ét stykke.","Nun, so viel zu Vorraussagungen. Moment, Macil ruft uns zurück. Lass uns hier heile heraus kommen.",,,"Bueno, tanto por un presentimiento. Espera, Macil nos reclama. Salgamos de aquí de una pieza.",,"No, se siitä ennustelusta. Odota, Macil kutsuu meitä takaisin. Häivytään täältä ehjin nahoin.","Bon, tant pis pour les pronostics. Attends, Macil nous demande de revenir. Rentrons un seul morceau.","Ennyit az előrejelzésről. Várj, Macil visszahív minket. Húzzunk el, míg egy darabban vagyunk.","Alla faccia dei prognostici... Aspetta, Macil ci sta richiamando. Meglio uscire da qua tutti interi.","まあ予言なんてそんなものでしょ。 -ちょっと待って、マシルが帰還するように言ったわ。ここから抜け出しましょう。","웃기네. 이딴 예언 따위. 잠깐만, 마실이 우리들을 부르고 있어. 이제 여기를 나가자.","Nou, tot zover de prognose. Wacht even, Macil roept ons terug. Laten we hier heelhuids weggaan.","Så mye for spådommer. Vent, Macil kaller oss tilbake. La oss komme oss helskinnet ut herfra.","Cóż, to tyle jeśli chodzi o prognozowanie. Czekajcie, Macil nas wzywa. Wynośmy się stąd w jednym kawałku.","Bem, parece que não é hora de previsões. Peraí, o Macil está nos chamando de volta. Vamos tentar sair daqui inteiros.",,"Atât a fost cu prognosticul. Stai, Macil ne sună înapoi. Să ieșim întregi de aici.","Да, это превзошло все наши ожидания. Подожди — Мэйсил вызывает нас назад. Давай выбираться отсюда.",,"Kehanet buraya kadarmış. Durun, Macil bizi geri çağırıyor. Buradan tek parça halinde çıkalım." -"I'm sorry, after up to my hips in blood I can't think of anything witty to say right now. Let's get back to Macil.",TXT_SUB_LOG88,,,,"Je mi líto; když jsem po boky v krvi, nemám nic co vtipného říct. Vraťme se k Macilovi.","Jeg er ked af det, men efter at have stået op til hofterne i blod kan jeg ikke finde på noget vittigt at sige lige nu. Lad os gå tilbage til Macil.","Tut mir leid, aber bei so viel Blut fällt mir nicht Flapsiges mehr ein. Lass uns zu Macil zurückgehen.",,,,,Anteeksi; oltuani lanteitani myöten veressä en keksi juuri nyt mitään nokkelaa sanottavaa. Palataan Macilin luokse.,"Désolée, après m'être retrouvée jusqu'au hanches dans le sang, je n'ai rien de malin à dire. Rentrons voir Macil.","Bocs, de miután nyakig vérben úsztam, semmi szellemes nem jut az eszembe. Irány vissza Macilhoz.","Mi spiace, ma dopo essere nel sangue fino alle caviglie non ho in mente nulla di interessante di dire al momento. Ritorniamo da Macil.",,미안. 피칠갑을 한 너의 모습을 보느라 할 말을 잃었어. 그냥 마실에게로 돌아가자.,"Het spijt me, na tot aan mijn heupen in bloed kan ik nu niets geestigs bedenken om te zeggen. Laten we teruggaan naar Macil.","Beklager, etter å ha stått i blod til hoftene kommer jeg ikke på noe vittig å si akkurat nå. La oss gå tilbake til Macil.","Przepraszam, ale po tym, jak jestem po biodra we krwi, nie mam teraz nic dowcipnego do powiedzenia. Wracajmy do Macil.",Desculpa. Após ficar coberta de sangue não consigo pensar em nada interessante pra dizer agora. Vamos voltar pro Macil.,,"Îmi pare rău, dar nu mă pot gândi să zic nimic acum. Să ne întoarcem la Macil.","Извини, после того, как я по бёдра в крови, я не могу придумать ничего остроумного, чтобы сказать сейчас. Давай вернёмся к Мэйсилу.",,"Üzgünüm, kalçalarıma kadar kana bulandıktan sonra şu anda söyleyecek esprili bir şey bulamıyorum. Macil'e geri dönelim." -"The factory is next to the mines. Richter must mean the mines of Degnin. The Degnin ore is magnetic and explosive, just the thing for shutting down force fields.",TXT_SUB_LOG89,STRIFE1.WAD: MAP23,,,"Továrna je vedle dolů. Richter musí mít na mysli doly degninu. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole.","Fabrikken ligger ved siden af minerne. Richter må mene Degnin-minerne. Degnin-malmen er magnetisk og eksplosiv, lige til at lukke kraftfelter ned med.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Das Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten.",,,"La fábrica está junto a las minas. Richter debe referirse a las minas de Degnin. El mineral Degnin es magnético y explosivo, justo para apagar campos de fuerza. ",,"Tehdas on kaivoksen vieressä. Richter varmastikin tarkoittaa Degninin kaivosta. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. ","A gyár a bánya mellett van. Richter valószínűleg a Degnin bányákra utalt. A degnini érc mágneses és robbanékony, egy tökéletes megoldás az erőpajzs kiiktatására.","La Fabbrica si trova accanto alle miniere. Richter starà parlando delle miniere di Degnin. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 -デグニン石は綺麗だが可燃性で、フォースフィールドを消すにはうってつけよ。",공장은 광산 옆에 있어. 릭터가 데그닌 광산을 이야기한 것 같아. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지.,"De fabriek ligt naast de mijnen. Richter moet de mijnen van Degnin bedoelen. Het Degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden.","Fabrikken ligger ved siden av gruvene. Richter må mene gruvene i Degnin. Degnin-malmen er magnetisk og eksplosiv, som skapt for å slå ut kraftfelt.","Fabryka jest obok kopalni. Richter musi mieć na myśli kopalnie w Degnin. Ruda Degnin jest magnetyczna i wybuchowa, w sam raz do wyłączania pól siłowych.","A fábrica fica próxima às minas. O Richter provavelmente se refere às minas de Degnin. O minério de Degnin é magnético e explosivo, perfeito para derrubar os campos de força.",,"Fabrica e lângă mine. Richter probabil s-a referit la minele de Degnin. Mineralul de Degnin e magnetic și exploziv, exact ce ne trebuie pentru scuturi.","Вход на фабрику — рядом со спуском в шахты. Рихтер, должно быть, имел в виду шахты Дегнина. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. ",,"Fabrika madenlerin yanında. Richter, Degnin madenlerini kastediyor olmalı. Degnin cevheri manyetik ve patlayıcıdır, tam da güç alanlarını kapatmak için." -"Mines, catacombs, sewers... What a first date!",TXT_SUB_LOG90,STRIFE1.WAD: MAP13,,,"Doly, kobky, stoky... skvělé první rande!","Minerne, katakomberne, kloakkerne... Sikke en første date!","Minen, Katakomben, Kanalisationen... was für ein erstes Date!",,,"Minas, catacumbas, alcantarillas... ¡Menuda primera cita!",,"Kaivoksia, katakombeja, viemäreitä... Mitkä ensitreffit!","Mines, catacombes, égouts.. Super premier rendez-vous!","Bányák, katakombák, kanálisok... Micsoda első randi!","Miniere, catacombe, fogne... Che primo appuntamento!",鉱山、地下墓所、下水道...とんだ初デートだな!,"광산, 고대 묘지, 하수도. 데이트하기엔 딱 맞는 장소들이네!","Mijnen, catacomben, rioleringen.... Wat een eerste afspraakje!","Gruver, katakomber, kloakker... For en første date!","Kopalnie, katakumby, kanały... Co za pierwsza randka!","Minas, catacumbas, esgotos... Que belo primeiro encontro!",,"Mine, catacombe, canale... Ce întâlnire!","Шахты, катакомбы, канализации... Замечательное первое свидание!",,"Madenler, yeraltı mezarları, kanalizasyonlar. Ne ilk randevu ama!" -"I wish Richter had been a touch more specific. Hm, let's try over here.",TXT_SUB_LOG91,STRIFE1.WAD: MAP13,,,"Přála bych si, aby byl Richter trochu přesnější. Hm, zkusme to tadyhle.","Jeg ville ønske, Richter havde været lidt mere specifik. Hm, lad os prøve herovre.","Ich wünschte mir, dass Richter etwas präziser gewesen wäre. Hmm, lass es uns mal hier versuchen.",,,"Ojalá Richter hubiera sido un pelín más específico. Hm, probemos por aquí.",,"Kunpa Richter olisi ollut hivenen tarkempi. Hm, kokeillaan täältä.",J'aurais bien voulu que Richter soit un peu plus spécifique. Hm.. Essayons ici.,"Nem bántam volna, ha Richter egy csöppnyivel pontosabb leírást ad. Hm, próbáljuk meg itt.","Vorrei che Richter fosse stato un poco più preciso. Mh, vediamo di là.","リヒターがもっと具体的な部分に触れてくれて欲しいが。 -あー、私らが試してみようか。","릭터가 좀 더 자세히 설명해 줬으면 좋았을 텐데. 흠, 여기서 해보자.","Ik wou dat Richter een beetje specifieker was geweest. Hm, laten we het hier eens proberen.","Skulle ønske Richter hadde vært litt mer spesifikk. Hm, la oss prøve her borte.","Szkoda, że Richter nie był bardziej konkretny. Hm, spróbujmy tutaj.","Bem que o Richter podia ter sido um pouco mais específico. Hmm, vamos tentar por alí.",,Îmi doresc ca Richter să fii fost mai specific. Să încercăm acolo.,"Я надеялась, что Рихтер будет чуть более конкретным. Ладно, давай посмотрим, что там.",,Keşke Richter biraz daha spesifik olsaydı. Şurayı deneyelim. -"I think we're... Oh, crap. I have no idea where we are.",TXT_SUB_LOG92,STRIFE1.WAD: MAP13,,,"Myslím, že jsme... sakra. Nemám tušení, kde jsme.","Jeg tror, vi er... Åh, pis. Jeg har ingen idé om, hvor vi er.","Ich glaube wir sind... Oh, Mist. Ich habe keine Ahnung wo wir sind.",,,"Creo que estamos... Oh, mierda. No tengo ni idea de donde estamos.",,"Luulen, että olemme... Perhana, minulla ei ole aavistustakaan, missä olemme.","Je crois que.. Non, merde, j'ai aucune idée d'où on est!","Azt hiszem éppen...Oh, franc. Ötletem sincs hol vagyunk.","Credo che siamo... Ah, merda, non ne ho proprio idea.","私が思うに...ああ、クソ。 -何処にあるかさっぱりわからないわ。",우리는 지금... 이런 제길. 여기가 어딘지 모르겠어.,"Ik denk dat we.... Oh, shit. Ik heb geen idee waar we zijn.","Jeg tror vi... Å, pokker. Jeg aner ikke hvor vi er.","Chyba jesteśmy... O, cholera. Nie mam pojęcia, gdzie jesteśmy.","Acho que estamos... Ah, merda. Não faço a menor idéia onde estamos.",,"Cred că suntem... Oh, la naiba. Nu știu unde suntem.","Я думаю, мы... О, чёрт. Я понятия не имею, где мы.",,"Sanırım biz... Oh, kahretsin. Nerede olduğumuz hakkında hiçbir fikrim yok." -"This must be the ruins Richter's agents were searching for. Oh, watch out! Crusaders!",TXT_SUB_LOG93,STRIFE1.WAD: MAP25,,,"Tohle musí být ty ruiny, které Richterovi agenti hledali. A, bacha! Křižáci!","Det må være ruinerne, som Richters agenter ledte efter. Åh, pas på! Korsfarere!","Dies müssen die Ruinen sein, die Richters Agent gesucht hat. Oh, aufpassen! Ordensritter!",,,"Estas deben ser las ruinas que el agente de Richter estaba buscando. Oh, ¡cuidado! ¡Cruzados!",,"Nämä ovat varmaankin ne rauniot, joita Richterin joukot olivat etsineet. Oho, varo: ristiretkeläisiä!","Ca doit être les ruines que les agents de Richter cherchaient. Attention, des croisés!","Ezek lehetnek a romok, amit Richter ügynökei kerestek. Vigyázz! Keresztesek!","Queste devono essere le rovine che gli agenti di Richter stavano cercando. Ah, attento! Crociati!","ここがリヒターのエージェントが探していた遺跡のはず。 -あっと、気を付けて!クルセイダーよ!","릭터의 요원이 수색하던 유적지인가봐... 잠깐, 조심해! 크루세이더야!","Dit moet de ruïnes zijn waar de agenten van Richter naar op zoek waren. Oh, kijk uit! Kruisvaarders!",Dette må være ruinene Richters agenter lette etter. Se opp! Korsfarere!,"To muszą być ruiny, których szukali agenci Richtera. Och, uważaj! Krzyżowcy!","Estas devem ser as ruínas que o agente de Richter estava procurando. Ah, cuidado! Cruzados!",,Ăstea ar trebui să fie ruinele pe care le căutau agenții lui Richter. Ai grijă! Cruciați!,"Возможно, это те самые руины, которые искали агенты Рихтера... Осторожно! Крестоносцы!",,"Richter'in ajanlarının aradığı harabeler burası olmalı. Oh, dikkat et! Haçlılar!" -"Ugh, it's trying to regenerate. Blast it before I throw up!",TXT_SUB_LOG94,,,,"Fuj, snaží se to oživit. Odstřel to, než začnu zvracet!","Ugh, den prøver at regenerere. Skyd den, før jeg kaster op!","Ugh, es versucht, sich zu regenerieren. Mach es fertig, bevor ich anfange zu kotzen.",,,"Ugh, está intentando regenerarse. ¡Reviéntalo antes de que vomite!",,"Yöh, se yrittää uusiutua. Posauta se, ennen kuin laattaan!","Beurk, il essaie de se régénérer, incinère le avant que je ne vomisse!","Fúj, regenerálódni próbál. Lődd szét mielőtt ide hányok!","Dannazione, sta cercando di rigenerarsi! Distruggilo prima che mi venga da vomitare.",,"으윽, 이게 재생하기 시작했어. 내가 토하기 전에 파괴해!","Ugh, het probeert te regenereren. Blast het voordat ik overgeven!",Den prøver å regenerere. Spreng den før jeg spyr!,"Ugh, próbuje się zregenerować. Rozwal to, zanim zwymiotuję!","Argh, está tentando se regenerar. Detona essa coisa antes que eu vomite!",,"Ugh, încearcă să se regenereze. Aruncă-l în aer înainte să vomit.","О-о, оно пытается восстановиться. Добей его, пока меня не стошнило!",,Yenilenmeye çalışıyor. Kusmadan önce patlat şunu! -"My friend, whatever it is we're fighting, it's more than the Order. Off to the mines!",TXT_SUB_LOG95,STRIFE1.WAD: MAP25,,,"Příteli, ať už bojujeme s čímkoliv, jde o víc než jen Řád. Do dolů!","Min ven, hvad det end er, vi kæmper imod, er det mere end Ordenen. Af sted til minerne!","Mein Freund, was auch immer es ist, dass wir bekämpfen, es ist mehr als der Orden. Ab zu den Minen!",,,"Amigo mío, lo que sea contra que estemos luchando, es más que la Orden. ¡A las minas!",,"Ystäväni, mitä vastaan me taistelemmekaan, se on suurempi kuin Veljeskunta. Matkatkaamme kaivokselle!","Mon ami, je ne sais ce contre quoi on se bat, mais c'est plus que l'Ordre. Allons dans les mines!","Nos barátom, bármivel is állunk szemben, több az mint maga a Rend. Irány a bánya!","Amico mio, qualsiasi cosa stiamo combattendo, è molto più dell'Ordine. Alle miniere!","友よ、私達が戦う相手が何であろうとも、オーダー以上のものはない。 -鉱山から離れましょう!","친구야, 우리가 싸우는 상대가 무엇인지는 모르겠지만, 오더보다 더한 존재인 것 같아. 광산으로 향하자!","Mijn vriend, wat het ook is waar we tegen vechten, het is meer dan de Orde. Naar de mijnen!","Min venn, hva det enn er vi kjemper mot, så er det mer enn Ordenen. Av sted til gruvene!","Mój przyjacielu, cokolwiek to jest, z czym walczymy, to coś więcej niż Zakon. Do kopalni!","Meu amigo, seja lá o que estamos combatendo, é mais do que somente a Ordem. Vamos para as minas!",,"Prietene, orice ar fi ceea ce înfruntăm, e mai mult decât Ordinul. Către mine!","Друг мой, с чем бы мы ни сражались, это нечто большее, чем просто Орден. К шахтам!",,"Dostum, savaştığımız şey her neyse, Tarikat'tan daha fazlası. Madenlere!" -"Without letting down your guard, look for deposits of ore.",TXT_SUB_LOG96,STRIFE1.WAD: MAP14,,,Opatrně se zkus podívat po ložiscích rudy.,"Uden at sænke din vagt, skal du lede efter malmforekomster.",Sei vorsichtig und halte Ausschau nach Erzvorkommen.,,,"Sin bajar la guardia, busca depósitos de mineral.",,"Etsi malmiesiintymiä, kuitenkin valppautesi säilyttäen.","Sans arrêter de faire attention, cherche des veines de minerai.","Keress érceket, de figyelj a hátad mögé közben.","Senza abbassare la guardia, cerca di trovare alcuni depositi di minerali.",警戒を緩めることなく、鉱石の堆積所を探しましょう。,"조심해가면서, 그들이 캔 광석을 두는 곳을 찾아.","Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen.","Uten å senke garden, let etter malmforekomster.","Nie spuszczając gardy, szukajcie złóż rudy.",Não baixe a sua guarda. Vamos procurar por depósitos de minério.,,"Fără a lăsa garda jos, uită-te dupa depozite de minereu.","Поищи залежи руды, но не теряй бдительности!",,"Gardınızı düşürmeden, maden yataklarını arayın." -"These poor souls are drones, their synaptic functions are jammed by RC implants. We destroy the transmitter and they are free!",TXT_SUB_LOG97,STRIFE1.WAD: MAP14,,,"Tihle chudáci jsou trubci, jejich synaptické funkce jsou narušené na dálku ovládanými implantáty. Když zničíme vysílačku, budou svobodní!","Disse stakkels sjæle er droner, deres synaptiske funktioner er blokeret af RC-implantater. Vi ødelægger senderen, og de er frie!","Diese armen Seelen sind Drohnen, ihre synaptischen Funktionen werden von Implantaten blockiert. Wenn wir den Transmitter zerstören, sind sie frei.",,,"Estas pobres almas son zánganos. Sus funciones sinápticas están bloqueadas por implantes de control remoto. ¡Destruimos el transmisor, y son libres!",,"Nämä sieluparat ovat kuhnureita: Heidän synaptisia toimintojaan häiritään radio-ohjattavilla istutteilla. Me tuhoamme lähettimen, ja he ovat vapaat!","Ces pauvres âmes sont des drones, leurs fonctions synaptiques sont brouillées par des implants radiocommandés. On détruit le transmetteur et ils sont libres!","Ezek a szerencsétlen lelkek csak drónok. A szinaptikus funkcióikat zavarják távolról irányítható implantátumokkal. Szétromboljuk a jeladókat, és szabaddá vállnak.","Questi poveracci sono dei droni. Le loro funzioni cerebrali stanno venendo bloccate da degli impianti. Se distruggiamo il trasmettitore, saranno liberi!","これら精神の乏しい労働者達は、シナプス機能をRCインプラントで妨害している。 -私達が送信機を破壊し皆を解放するんだ!","저 사람들은 불쌍한 광산의 노예들이야. 오더가 이식한 세뇌 장치 때문에 정상적인 뇌 기능을 잃었지. 전송기만 파괴한다면, 그들은 자유를 되찾을 수 있을 거야!","Deze arme zielen zijn drones, hun synaptische functies worden verstoord door RC-implantaten. We vernietigen de zender en ze zijn vrij!","Disse stakkarene er droner, deres synaptiske funksjoner er blokkert av RC-implantater. Vi ødelegger senderen, og de er fri!","Te biedne dusze są dronami, ich funkcje synaptyczne są zagłuszane przez implanty RC. Zniszczymy nadajnik i są wolne!",Esses pobres coitados são zangões. Suas funções sinápticas estão sendo bloqueadas por implantes de controle remoto. Se destruirmos o transmissor eles estarão livres!,,Sufletele ăstea sărmane sunt drone. Funcțiile lor sinaptice sunt întrerupte de implanturi RC. Distrugem transmițătorul și sunt libere!,"Эти несчастные души — дроны. Сигнал, поступающий на импланты, полностью подавляет их сознание. Давай уничтожим передатчик и освободим их!",,"Bu zavallı ruhlar dron, sinaptik fonksiyonları RC implantları tarafından engellenmiş. Vericiyi yok edersek özgür kalırlar!" -"Command says the transmitter is shielded by a force field. So two birds, one stone, free the drones and practice with the ore.",TXT_SUB_LOG98,STRIFE1.WAD: MAP14,,,"Velení říká, že vysílačka je chráněná silovým polem. Dvě mouchy jednou ranou: osvobodíme vězně a vyzkoušíme si, jak s tou rudou.","Kommandocentralen siger, at senderen er beskyttet af et kraftfelt. Så to fluer i et smæk, befri dronerne og øv dig med malmen.","Die Kommandozentale sagt, der Transmitter sei von einem Kraftfeld geschützt. So, zwei Fliegen, eine Klatsche, befreie die Drohnen und übe mit dem Erz.",,,"El Comando dice que el transmisor está protegido por un campo de fuerza. Dos pájaros de un tiro, libera a los zánganos y practica con el mineral.",,"Komentokeskus sanoo, että lähetin on voimakentän suojaama. Siispä kaksi kärpästä yhdellä iskulla: vapautamme kuhnurit ja samalla harjoittelemme malmilla.","La commandement me dit que le transmetteur est protégé par un champ de force. Ca fait d'une pierre de coups. On libère les drones, et on s'entraîne avec le minerai.",Az irányítás szerint a jeladó el van szeparálva egy erőpajzzsal. Tehát két légy és egy csapás: szabadítsuk ki a drónokat és gyakoroljunk az érccel.,"Il comando dice che il trasmettitore è protetto da un campo di forza. Quindi, due piccioni con una fava. Liberiamo i droni e facciamo pratica con il minerale.","司令官は送信機がフォースフィールドに守られていると言っていた。 -そこを潰せば鉱山と労働者を解放、一石二鳥だな。",본부가 말하길 전송기는 방어막에 의해 보호받고 있대. 광석을 사용하는 방법을 연습하면서 노예들을 해방한다면 일석이조일 거야.,"Het commando zegt dat de zender is afgeschermd door een krachtveld. Dus twee vogels, een steen, bevrijden de drones en oefenen met het erts.","Kommandoen sier at senderen er beskyttet av et kraftfelt. Så to fluer i en smekk, frigjør dronene og øv med malmen.","Dowództwo mówi, że nadajnik jest osłonięty przez pole siłowe. Więc dwie pieczenie na jednym ogniu, uwolnić drony i poćwiczyć z rudą.",O comando diz que o transmissor está protegido por um campo de força. Dois coelhos numa tacada só. Liberte os zangões e teste o minério.,,"Centrul de comandă e prtejat de un câmp de forță. Deci, două păsări, o piatră.","Штаб говорит, что передатчик защищён силовым полем. Ты освободишь дронов и испытаешь руду — одним выстрелом двух зайцев!",,"Komuta vericinin bir güç alanı tarafından korunduğunu söylüyor. Yani bir taşla iki kuş, dronları serbest bırak ve cevherle pratik yap." -"My suggestion is, toss the ore at the forcefield and then blast it. The resulting compression should create a magnetic blanket and turn off the lights.",TXT_SUB_LOG99,STRIFE1.WAD: MAP14,,,"Můj návrh je, hoď rudu na to silové pole a pak ji odstřel. Výsledná komprese by měla vytvořit magnetický povlak a vypnout pole.","Mit forslag er, at kaste malmen mod kraftfeltet og derefter sprænge det. Den resulterende kompression skulle skabe et magnetisk tæppe og slukke lyset.","Mein Vorschlag wäre, das Erz vor das Kraftfeld zu legen und dann explodieren zu lassen. Die resultierende Kompression sollte ein Magnetfeld erzeugen und die Lichter ausgehen lassen.",,,"Mi sugerencia es, tirar el mineral hacia el campo de fuerza y luego reventarlo, la presión resultante debería crear un manto magnético y apagar las luces.",,"Ehdotukseni on, että heität malmin voimakentään ja sitten posautat sen. Syntyvän paineaallon pitäisi muodostaa magneettinen peitto ja sammuttaa valot.",Ma suggestion: jette le minerai sur le champ de force puis tire dessus. La compression qui en résulte devrait créer un champ magnétique qui va désactiver les lumières.,"Az a tanácsom, hogy dobd az ércet az erőpajzsra, és robbantsd fel. A keletkező kompresszió egy mágneses takarót kéne hogy képezzen, így kikapcsolva a fényeket.","Il mio consiglio è, lancia uno dei minerali al campo di forza e poi fallo saltare in aria. Questo dovrebbe sprigionare l'energia sufficiente a disattivare il campo di forza.","私の案はフォースフィールドの近くに鉱石を置き撃って爆発させる方法よ。 -その結果、圧縮されていた磁場の反動で光を打ち消すわ。","조언을 찾는다면, 광석을 방어막에 가까이 놔둔 뒤 쏴봐. 광석이 커다란 자기장을 만들 테고, 방어막을 완전히 무력화 시킬 거야. 불 끄는거지!",Mijn suggestie is om het erts naar het krachtveld te gooien en het vervolgens op te blazen. De resulterende compressie zou een magnetische deken moeten creëren en de lichten moeten doven.,Mitt forslag er å kaste malmen mot kraftfeltet og sprenge det. Den resulterende kompresjonen bør skape et magnetisk teppe og slå av lysene.,Proponuję rzucić rudę w pole siłowe i wysadzić je. Powstała kompresja powinna stworzyć koc magnetyczny i wyłączyć światła.,Minha sugestão é que você arremesse o minério no campo de força e o detone. A explosão vai criar um campo magnético e apagar as luzes.,,"Sugstia mea e, aruncă minereul în scut și aruncă-l în aer. Comprimarea rezultată ar trebui să creeze un câmp magnetic care sp oprească luminile.","Мой план: бросить руду поближе к силовому полю и взорвать её. Взрыв создаст магнитное поле, которое накроет электронику и отрубит её.",,"Benim önerim, cevheri güç alanına fırlatın ve sonra patlatın. Ortaya çıkan sıkıştırma manyetik bir örtü oluşturmalı ve ışıkları kapatmalı." -Now on to the factory. Exit the mines and you can't miss it!,TXT_SUB_LOG100,STRIFE1.WAD: MAP16,,,A teď do továrny. Vyjdi z dolů a nemůžeš to minout.,"Nu videre til fabrikken. Gå ud af minerne, og du kan ikke undgå at se den!",Und nun zur Fabrik. Verlasse die Minen und du kannst sie nicht verpassen.,,,Ahora vamos a la fábrica. ¡Sal de las minas y no puedes perderlo!,,"Nyt sitten tehtaaseen. Poistu kaivoksesta, ja löydät sen varmasti!","Bon, maintenant, l'usine! Sors des mines et tu peux pas la rater!",Most pedig irány a gyár. Kilépve a bányából nem tudod eltéveszteni.,Ora entriamo nella Fabbrica. Uscendo dalle miniere non puoi sbagliare.,今すぐ工場へ向かおう。鉱山を出たら見逃すなよ!,이제 공장으로 향하자. 광산을 나가면 더 재밌는 모험이 펼쳐질 거야!,Nu naar de fabriek. Verlaat de mijnen en je kunt het niet missen!,"Nå videre til fabrikken. Gå ut av gruvene, og du kan ikke gå glipp av den!",Teraz przejdź do fabryki. Wyjdź z kopalni i nie możesz jej przegapić!,"Agora, para a fábrica. Saia das minas e não vai ter como errar.",,Acum către fabrică. Ieși din mine și nu o poți rata.,"Теперь — на фабрику. Выйди из шахты, и ты сразу увидишь вход!",,Şimdi fabrikaya gidelim. Madenlerden çıkın ve onu kaçırmayın! -"Sorry, hero, this is all new to me.",TXT_SUB_LOG101,STRIFE1.WAD: MAP20,,,"Promiň, hrdino, tohle všechno je pro mě nové.","Undskyld, helt, det er alt sammen nyt for mig.","Entschuldigung, mein Held, das ist alles neu für mich.",,,"Lo siento, héroe, esto es nuevo para mí.",,"Pahoittelut, sankari; tämä kaikki on uutta minulle.","Désolé, héros, tout cela est nouveau pour moi.","Sajnálom hősöm, ez mind rendkívűl új számomra.","Mi spiace, eroe, ma tutto ciò è nuovo per me.",ごめんなさい、これは初耳なの。,"미안, 영웅 친구... 이런 곳은 처음 봐.","Sorry, held, dit is allemaal nieuw voor mij.","Beklager, helt, dette er nytt for meg.","Wybacz, bohaterze, to wszystko jest dla mnie nowe.","Foi mal, meu herói, tudo isso é novo pra mim.",,"Scuze, eroule, asta e nou pentru mine.","Извини, герой. Для меня это всё в новинку.",,"Üzgünüm kahraman, bunların hepsi benim için yeni." -I'm reading massive neural wave distortions from straight ahead. I think we've found it.,TXT_SUB_LOG102,STRIFE1.WAD: MAP20,,,"Detekuju obří rušení nervových vln přímo před námi. Myslím, že jsme to našli.","Jeg læser massive neurale bølgeforvridninger lige forude. Jeg tror, vi har fundet det.","Ich empfange massive neurale Verzerrungen direkt voraus. Ich denke, wir haben sie gefunden.",,,Estoy leyendo distorsiones de ondas neuronales masivas adelante. Creo que la hemos encontrado.,Estoy leyendo distorsiones neuronales masivas adelante. Creo que la hemos encontrado.,Havaitsen massivisia hermoaaltovääristymiä suoraan edessä. Luulen löytäneemme sen.,Je recois des distorsions neurales colossales devant nous. Je crois que nous l'avons trouvé. ,Erős ideghullám zavaró jeleket fogok. Azt hiszem megtaláltuk.,Sto ricevendo potenti segnali distorti proprio davanti a te. Penso che l'abbiamo trovata.,重い神経波の歪曲が直に届いたわ。私達はそれを見つけたという事よ。,앞쪽에서 거대한 신경교란 파장이 감지되고 있어. 우리가 찾아낸 것 같아.,Ik lees enorme neurale golfvervormingen van rechtdoor. Ik denk dat we het gevonden hebben.,Jeg leser massive nevrale bølgeforvrengninger rett fram. Jeg tror vi har funnet den.,Odczytuję masywne zakłócenia fal neuronowych z prostej drogi. Chyba to znaleźliśmy.,Estou captando enormes distorções de rede neural mais adiante. Acho que encontramos.,,Citesc distorsiuni neurale masive drept din față. Cred că am găsit-o.,"Я вижу мощный источник помех прямо по курсу. Похоже, мы нашли конвертер.",,Tam karşıdan büyük sinirsel dalga bozulmaları okuyorum. Sanırım onu bulduk. -Just when I think we've seen it all! They go in human and come out... I dont even want to think about it.,TXT_SUB_LOG103,STRIFE1.WAD: MAP24,,,"Zrovna, když jsem myslela, že jsme už viděli všechno! Dovnitř jdou jako lidé a ven vyjdou... ani na to nechci myslet.","Lige når jeg tror, vi har set det hele! De går ind i et menneske og kommer ud... Jeg vil ikke engang tænke på det.","Und da denkt man, man hätte schon alles gesehen. Die kommen als Menschen rein und kommen raus als... Ich möchte gar nicht drüber nachdenken.",,,¡Justo cuando creía haberlo visto todo! Entran humanos y salen... No quiero ni pensarlo. ,¡Justo cuando creía haberlo visto todo! Entran humanos y salen... No quiero ni pensarlo.,Juuri kun luulen nähneemme kaiken! He menevät sisään ihmisinä ja tulevat ulos... En halua edes ajatellakaan sitä.,"Et quand je pense avoir tout vu.. Des humains entrent, et puis.. Non, je ne veux pas y penser. ","Amikor azt hittem, hogy mindent láttunk. Emberként mennek be, és úgy jönnek ki mint egy...nem is akarok rá gondolni.",E io che pensavo di averle viste tutte! Entrano umani ed escono fuori... Non ci voglio neanche pensare.,"今まで見てきたことについて考えている! -奴は人の内部から出てくる...それについて考えたくないわ。",이렇게 끔찍한 모습을 보게 되다니! 멀쩡한 사람이 저곳에 들어갔다 나온 모습을... 차마 생각하기도 싫어.,Net nu ik denk dat we het allemaal hebben gezien! Ze gaan in de mens en komen eruit.... Ik wil er niet eens over nadenken.,Akkurat når jeg tror vi har sett alt! De går inn som mennesker og kommer ut... Jeg vil ikke engang tenke på det.,"Właśnie wtedy, gdy myślałem, że widzieliśmy już wszystko! Wchodzą w człowieka i wychodzą... Nawet nie chcę o tym myśleć.",E eu achei que já tinha visto de tudo! Eles entram humanos e saem... eu não quero nem pensar nisso.,,Tocmai când credeam că am văzut tot! Intră oameni și ies... nici nu vreau să mă gândesc.,"А я-то думала, что хуже уже не будет! Они входят людьми, а выходят... Не хочу даже думать об этом.",,Tam da her şeyi gördüğümüzü düşündüğüm anda! İnsana giriyorlar ve çıkıyorlar. Bunu düşünmek bile istemiyorum. -The Oracle was right. Macil's gone nuts. He just knowingly sent 200 men to their death. I want vengeance. For the dead and for the living dead!,TXT_SUB_LOG104,STRIFE1.WAD: MAP24,,,Věštec měl pravdu. Macil zešílel. Vědomě poslal dvě stě mužů na smrt. Chci odplatu - za mrtvé i živé mrtvé!,Oraklet havde ret. Macil er blevet skør. Han har lige bevidst sendt 200 mænd i døden. Jeg vil have hævn. For de døde og for de levende døde!,Das Orakel hatte Recht. Macil hat den Verstand verloren. Er hat gerade absichtlich 200 unserer Leute in den Tod geschickt. Ich will Rache! Für die Toten und für die lebenden Toten.,,,Macil se ha vuelto loco. Conscientemente ha enviado 200 hombres a su muerte. ¡Quiero venganza! ¡Por los muertos y los muertos vivientes!,Macil se ha vuelto loco. Conscientemente envió a 200 hombres a su muerte. ¡Quiero venganza! Por los muertos y por los muertos vivientes!,"Oraakkeli oli oikeassa: Macil on tullut hulluksi. Hän juuri lähetti tietoisesti 200 miestä surmaansa. Vaadin kostoa, sekä kuolleitten että elävien kuolleitten puolesta!","Macil a complètement perdu les pédales! Il a envoyé 200 hommes se faire tuer, et il le savait! Il faut les venger, pour eux et pour leurs camarades!",Az Orákulumnak igaza volt. macil megőrült. Szándékosan küldött 200 emberünket a halálába. Meg akarom bosszúlni a halottak és az élő halottak nevében!,L'Oracolo aveva ragione. Macil deve essere impazzito. Ha mandato consciamente 200 uomini verso la morte. Voglio vendetta! Per i morti e per i morti viventi!,"オラクルが正しかった。マシルはイカれていたなんて。 +",시질의 완전한 힘은 이제 네 손에 있어. 종지부를 찍을 준비 됐어?,Je gebruikt de kracht van de hele Sigil. Wat zeg je ervan als we de zaak gaan afsluiten.,"Du har kraften til hele sigillet, og du kan bruke det. Hva sier du til å få en avslutning?","Władasz mocą kompletnego Sigilu. Co powiesz na to, żebyśmy się zamknęli.",Você tem o poder do Sigilo completo em suas mãos. Que tal a gente ir atrás de um desfecho?,,Ai puterea întregului Sigiliu. Ce zici dacă primim o încheiere?,Теперь ты владеешь мощью завершённой Печати. Мы уже близко — давай покончим с этим.,,Du har makten över hela Sigil. Vad sägs om att vi går och avslutar det hela.,"Sigil'in tamamının gücüne sahipsin. Ne dersin, gidip biraz kapanış yapalım mı?" +"High noon, my hero. Prepare to embrace glory.",TXT_SUB_LOG86,,,,"Souboj v pravé poledne, můj hrdino. Připrav se přijmout slávu.","Klokken tolv, min helt. Gør dig klar til at omfavne æren.","Die Stunde ist gekommen, mein Held. Bereite dich auf Ruhm vor.",,,"Es la hora final, mi héroe. Prepárate para la gloria.",,"Ratkaisun hetki, sankarini. Valmistaudu pukeutumaan kunniaan.","Le soleil est au zénith, mon héros. Prépare toi à rencontrer ta gloire.",Eljött az idő hősöm. Ragadd meg a lehetőséget.,"Mezzogiorno di fuoco, mio eroe. Preparati ad abbracciare la gloria.",いい気分でしょ、私の英雄。栄光を受け入れる準備をしなさい。,"석양이 지고 있어, 나의 영웅. 영광을 누릴 준비해!","Hoog middaguur, mijn held. Bereid je voor om de glorie te omarmen.","Klokka er tolv, min helt. Forbered deg på å omfavne æren.","W samo południe, mój bohaterze. Przygotuj się na przyjęcie chwały.","Chegou a hora, meu herói. Se prepare para abraçar a glória.",,"Timpul pentru glorie, eroul meu.","Самое время, мой герой! Ты будешь купаться в славе.",,"Klockan tolv, min hjälte. Förbered dig på att omfamna ära.","Öğle vakti, kahramanım. Zaferi kucaklamaya hazırlan." +"Well, so much for prognostication. Hold it, Macil is calling us back. Let's get out of here in one piece.",TXT_SUB_LOG87,MAP12: After killing the Oracle with Macil alive.,,,"No, to by bylo pro prorokování. Počkat, Macil nás volá zpět. Vypadněme odsud vcelku.","Så meget for prognoser. Vent, Macil kalder os tilbage. Lad os komme ud herfra i ét stykke.","Nun, so viel zu Vorraussagungen. Moment, Macil ruft uns zurück. Lass uns hier heile heraus kommen.",,,"Bueno, tanto por un presentimiento. Espera, Macil nos reclama. Salgamos de aquí de una pieza.",,"No, se siitä ennustelusta. Odota, Macil kutsuu meitä takaisin. Häivytään täältä ehjin nahoin.","Bon, tant pis pour les pronostics. Attends, Macil nous demande de revenir. Rentrons un seul morceau.","Ennyit az előrejelzésről. Várj, Macil visszahív minket. Húzzunk el, míg egy darabban vagyunk.","Alla faccia dei prognostici... Aspetta, Macil ci sta richiamando. Meglio uscire da qua tutti interi.","まあ予言なんてそんなものでしょ。 +ちょっと待って、マシルが帰還するように言ったわ。ここから抜け出しましょう。","웃기네. 이딴 예언 따위. 잠깐만, 마실이 우리들을 부르고 있어. 이제 여기를 나가자.","Nou, tot zover de prognose. Wacht even, Macil roept ons terug. Laten we hier heelhuids weggaan.","Så mye for spådommer. Vent, Macil kaller oss tilbake. La oss komme oss helskinnet ut herfra.","Cóż, to tyle jeśli chodzi o prognozowanie. Czekajcie, Macil nas wzywa. Wynośmy się stąd w jednym kawałku.","Bem, parece que não é hora de previsões. Peraí, o Macil está nos chamando de volta. Vamos tentar sair daqui inteiros.",,"Atât a fost cu prognosticul. Stai, Macil ne sună înapoi. Să ieșim întregi de aici.","Да, это превзошло все наши ожидания. Подожди — Мэйсил вызывает нас назад. Давай выбираться отсюда.",,"Så mycket för prognoser. Vänta, Macil kallar oss tillbaka. Låt oss komma härifrån i ett stycke.","Kehanet buraya kadarmış. Durun, Macil bizi geri çağırıyor. Buradan tek parça halinde çıkalım." +"I'm sorry, after up to my hips in blood I can't think of anything witty to say right now. Let's get back to Macil.",TXT_SUB_LOG88,,,,"Je mi líto; když jsem po boky v krvi, nemám nic co vtipného říct. Vraťme se k Macilovi.","Jeg er ked af det, men efter at have stået op til hofterne i blod kan jeg ikke finde på noget vittigt at sige lige nu. Lad os gå tilbage til Macil.","Tut mir leid, aber bei so viel Blut fällt mir nicht Flapsiges mehr ein. Lass uns zu Macil zurückgehen.",,,,,Anteeksi; oltuani lanteitani myöten veressä en keksi juuri nyt mitään nokkelaa sanottavaa. Palataan Macilin luokse.,"Désolée, après m'être retrouvée jusqu'au hanches dans le sang, je n'ai rien de malin à dire. Rentrons voir Macil.","Bocs, de miután nyakig vérben úsztam, semmi szellemes nem jut az eszembe. Irány vissza Macilhoz.","Mi spiace, ma dopo essere nel sangue fino alle caviglie non ho in mente nulla di interessante di dire al momento. Ritorniamo da Macil.",,미안. 피칠갑을 한 너의 모습을 보느라 할 말을 잃었어. 그냥 마실에게로 돌아가자.,"Het spijt me, na tot aan mijn heupen in bloed kan ik nu niets geestigs bedenken om te zeggen. Laten we teruggaan naar Macil.","Beklager, etter å ha stått i blod til hoftene kommer jeg ikke på noe vittig å si akkurat nå. La oss gå tilbake til Macil.","Przepraszam, ale po tym, jak jestem po biodra we krwi, nie mam teraz nic dowcipnego do powiedzenia. Wracajmy do Macil.",Desculpa. Após ficar coberta de sangue não consigo pensar em nada interessante pra dizer agora. Vamos voltar pro Macil.,,"Îmi pare rău, dar nu mă pot gândi să zic nimic acum. Să ne întoarcem la Macil.","Извини, после того, как я по бёдра в крови, я не могу придумать ничего остроумного, чтобы сказать сейчас. Давай вернёмся к Мэйсилу.",,"Jag är ledsen, men efter att ha varit upp till höfterna i blod kan jag inte komma på något roligt att säga just nu. Vi återvänder till Macil.","Üzgünüm, kalçalarıma kadar kana bulandıktan sonra şu anda söyleyecek esprili bir şey bulamıyorum. Macil'e geri dönelim." +"The factory is next to the mines. Richter must mean the mines of Degnin. The Degnin ore is magnetic and explosive, just the thing for shutting down force fields.",TXT_SUB_LOG89,MAP23: After talking with Richter and leaving his room.,,,"Továrna je vedle dolů. Richter musí mít na mysli doly degninu. Degninská ruda je magnetická a výbušná, perfektní pro vypnutí silového pole.","Fabrikken ligger ved siden af minerne. Richter må mene Degnin-minerne. Degnin-malmen er magnetisk og eksplosiv, lige til at lukke kraftfelter ned med.","Die Fabrik liegt neben den Minen. Richter muss von den Degnin-Minen reden. Das Degnin-Erz ist magnetisch und explosiv., genau das, was wir brauchen, um die Kraftfelder auszuschalten.",,,"La fábrica está junto a las minas. Richter debe referirse a las minas de Degnin. El mineral Degnin es magnético y explosivo, justo para apagar campos de fuerza. ",,"Tehdas on kaivoksen vieressä. Richter varmastikin tarkoittaa Degninin kaivosta. Degnin-malmi on magneettista ja räjähdysherkkää, juuri omiaan purkamaan voimakenttiä.","L'usine est près des mines. Richter doit parler des mines de degnin. Le minérai de degnin est magnétisé et explosif, c'est parfait pour désactiver les champs de force. ","A gyár a bánya mellett van. Richter valószínűleg a Degnin bányákra utalt. A degnini érc mágneses és robbanékony, egy tökéletes megoldás az erőpajzs kiiktatására.","La Fabbrica si trova accanto alle miniere. Richter starà parlando delle miniere di Degnin. I minerali di Degnin sono magnetici ed esplosivi, giusto ciò che ci serve per disattivare i campi di forza.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +デグニン石は綺麗だが可燃性で、フォースフィールドを消すにはうってつけよ。",공장은 광산 옆에 있어. 릭터가 데그닌 광산을 이야기한 것 같아. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지.,"De fabriek ligt naast de mijnen. Richter moet de mijnen van Degnin bedoelen. Het Degnin-erts is magnetisch en explosief, precies het ding voor het afsluiten van krachtvelden.","Fabrikken ligger ved siden av gruvene. Richter må mene gruvene i Degnin. Degnin-malmen er magnetisk og eksplosiv, som skapt for å slå ut kraftfelt.","Fabryka jest obok kopalni. Richter musi mieć na myśli kopalnie w Degnin. Ruda Degnin jest magnetyczna i wybuchowa, w sam raz do wyłączania pól siłowych.","A fábrica fica próxima às minas. O Richter provavelmente se refere às minas de Degnin. O minério de Degnin é magnético e explosivo, perfeito para derrubar os campos de força.",,"Fabrica e lângă mine. Richter probabil s-a referit la minele de Degnin. Mineralul de Degnin e magnetic și exploziv, exact ce ne trebuie pentru scuturi.","Вход на фабрику — рядом со спуском в шахты. Рихтер, должно быть, имел в виду шахты Дегнина. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. ",,"Fabriken ligger bredvid gruvorna. Richter måste mena Degnins gruvor. Degninmalmen är magnetisk och explosiv, precis vad man behöver för att stänga av kraftfält.","Fabrika madenlerin yanında. Richter, Degnin madenlerini kastediyor olmalı. Degnin cevheri manyetik ve patlayıcıdır, tam da güç alanlarını kapatmak için." +"Mines, catacombs, sewers... What a first date!",TXT_SUB_LOG90,MAP13: Entrance.,,,"Doly, kobky, stoky... skvělé první rande!","Minerne, katakomberne, kloakkerne... Sikke en første date!","Minen, Katakomben, Kanalisationen... was für ein erstes Date!",,,"Minas, catacumbas, alcantarillas... ¡Menuda primera cita!",,"Kaivoksia, katakombeja, viemäreitä... Mitkä ensitreffit!","Mines, catacombes, égouts.. Super premier rendez-vous!","Bányák, katakombák, kanálisok... Micsoda első randi!","Miniere, catacombe, fogne... Che primo appuntamento!",鉱山、地下墓所、下水道...とんだ初デートだな!,"광산, 고대 묘지, 하수도. 데이트하기엔 딱 맞는 장소들이네!","Mijnen, catacomben, rioleringen.... Wat een eerste afspraakje!","Gruver, katakomber, kloakker... For en første date!","Kopalnie, katakumby, kanały... Co za pierwsza randka!","Minas, catacumbas, esgotos... Que belo primeiro encontro!",,"Mine, catacombe, canale... Ce întâlnire!","Шахты, катакомбы, канализации... Замечательное первое свидание!",,"Gruvor, katakomber, kloaker... Vilken första träff!","Madenler, yeraltı mezarları, kanalizasyonlar. Ne ilk randevu ama!" +"I wish Richter had been a touch more specific. Hm, let's try over here.",TXT_SUB_LOG91,MAP13: West (entrance with parkour to the northwest).,,,"Přála bych si, aby byl Richter trochu přesnější. Hm, zkusme to tadyhle.","Jeg ville ønske, Richter havde været lidt mere specifik. Hm, lad os prøve herovre.","Ich wünschte mir, dass Richter etwas präziser gewesen wäre. Hmm, lass es uns mal hier versuchen.",,,"Ojalá Richter hubiera sido un pelín más específico. Hm, probemos por aquí.",,"Kunpa Richter olisi ollut hivenen tarkempi. Hm, kokeillaan täältä.",J'aurais bien voulu que Richter soit un peu plus spécifique. Hm.. Essayons ici.,"Nem bántam volna, ha Richter egy csöppnyivel pontosabb leírást ad. Hm, próbáljuk meg itt.","Vorrei che Richter fosse stato un poco più preciso. Mh, vediamo di là.","リヒターがもっと具体的な部分に触れてくれて欲しいが。 +あー、私らが試してみようか。","릭터가 좀 더 자세히 설명해 줬으면 좋았을 텐데. 흠, 여기서 해보자.","Ik wou dat Richter een beetje specifieker was geweest. Hm, laten we het hier eens proberen.","Skulle ønske Richter hadde vært litt mer spesifikk. Hm, la oss prøve her borte.","Szkoda, że Richter nie był bardziej konkretny. Hm, spróbujmy tutaj.","Bem que o Richter podia ter sido um pouco mais específico. Hmm, vamos tentar por alí.",,Îmi doresc ca Richter să fii fost mai specific. Să încercăm acolo.,"Я надеялась, что Рихтер будет чуть более конкретным. Ладно, давай посмотрим, что там.",,"Jag önskar att Richter hade varit lite mer specifik. Hm, vi försöker här borta.",Keşke Richter biraz daha spesifik olsaydı. Şurayı deneyelim. +"I think we're... Oh, crap. I have no idea where we are.",TXT_SUB_LOG92,MAP13: Northwest (hall to the parkour room).,,,"Myslím, že jsme... sakra. Nemám tušení, kde jsme.","Jeg tror, vi er... Åh, pis. Jeg har ingen idé om, hvor vi er.","Ich glaube wir sind... Oh, Mist. Ich habe keine Ahnung wo wir sind.",,,"Creo que estamos... Oh, mierda. No tengo ni idea de donde estamos.",,"Luulen, että olemme... Perhana, minulla ei ole aavistustakaan, missä olemme.","Je crois que.. Non, merde, j'ai aucune idée d'où on est!","Azt hiszem éppen...Oh, franc. Ötletem sincs hol vagyunk.","Credo che siamo... Ah, merda, non ne ho proprio idea.","私が思うに...ああ、クソ。 +何処にあるかさっぱりわからないわ。",우리는 지금... 이런 제길. 여기가 어딘지 모르겠어.,"Ik denk dat we.... Oh, shit. Ik heb geen idee waar we zijn.","Jeg tror vi... Å, pokker. Jeg aner ikke hvor vi er.","Chyba jesteśmy... O, cholera. Nie mam pojęcia, gdzie jesteśmy.","Acho que estamos... Ah, merda. Não faço a menor idéia onde estamos.",,"Cred că suntem... Oh, la naiba. Nu știu unde suntem.","Я думаю, мы... О, чёрт. Я понятия не имею, где мы.",,"Jag tror att vi är... Åh, skit. Jag har ingen aning om var vi är.","Sanırım biz... Oh, kahretsin. Nerede olduğumuz hakkında hiçbir fikrim yok." +"This must be the ruins Richter's agents were searching for. Oh, watch out! Crusaders!",TXT_SUB_LOG93,MAP25: Entrance.,,,"Tohle musí být ty ruiny, které Richterovi agenti hledali. A, bacha! Křižáci!","Det må være ruinerne, som Richters agenter ledte efter. Åh, pas på! Korsfarere!","Dies müssen die Ruinen sein, die Richters Agent gesucht hat. Oh, aufpassen! Ordensritter!",,,"Estas deben ser las ruinas que el agente de Richter estaba buscando. Oh, ¡cuidado! ¡Cruzados!",,"Nämä ovat varmaankin ne rauniot, joita Richterin joukot olivat etsineet. Oho, varo: ristiretkeläisiä!","Ca doit être les ruines que les agents de Richter cherchaient. Attention, des croisés!","Ezek lehetnek a romok, amit Richter ügynökei kerestek. Vigyázz! Keresztesek!","Queste devono essere le rovine che gli agenti di Richter stavano cercando. Ah, attento! Crociati!","ここがリヒターのエージェントが探していた遺跡のはず。 +あっと、気を付けて!クルセイダーよ!","릭터의 요원이 수색하던 유적지인가봐... 잠깐, 조심해! 크루세이더야!","Dit moet de ruïnes zijn waar de agenten van Richter naar op zoek waren. Oh, kijk uit! Kruisvaarders!",Dette må være ruinene Richters agenter lette etter. Se opp! Korsfarere!,"To muszą być ruiny, których szukali agenci Richtera. Och, uważaj! Krzyżowcy!","Estas devem ser as ruínas que o agente de Richter estava procurando. Ah, cuidado! Cruzados!",,Ăstea ar trebui să fie ruinele pe care le căutau agenții lui Richter. Ai grijă! Cruciați!,"Возможно, это те самые руины, которые искали агенты Рихтера... Осторожно! Крестоносцы!",,"Det här måste vara ruinerna som Richters agenter sökte efter. Åh, se upp! Korsfarare!","Richter'in ajanlarının aradığı harabeler burası olmalı. Oh, dikkat et! Haçlılar!" +"Ugh, it's trying to regenerate. Blast it before I throw up!",TXT_SUB_LOG94,,,,"Fuj, snaží se to oživit. Odstřel to, než začnu zvracet!","Ugh, den prøver at regenerere. Skyd den, før jeg kaster op!","Ugh, es versucht, sich zu regenerieren. Mach es fertig, bevor ich anfange zu kotzen.",,,"Ugh, está intentando regenerarse. ¡Reviéntalo antes de que vomite!",,"Yöh, se yrittää uusiutua. Posauta se, ennen kuin laattaan!","Beurk, il essaie de se régénérer, incinère le avant que je ne vomisse!","Fúj, regenerálódni próbál. Lődd szét mielőtt ide hányok!","Dannazione, sta cercando di rigenerarsi! Distruggilo prima che mi venga da vomitare.",,"으윽, 이게 재생하기 시작했어. 내가 토하기 전에 파괴해!","Ugh, het probeert te regenereren. Blast het voordat ik overgeven!",Den prøver å regenerere. Spreng den før jeg spyr!,"Ugh, próbuje się zregenerować. Rozwal to, zanim zwymiotuję!","Argh, está tentando se regenerar. Detona essa coisa antes que eu vomite!",,"Ugh, încearcă să se regenereze. Aruncă-l în aer înainte să vomit.","О-о, оно пытается восстановиться. Добей его, пока меня не стошнило!",,"Ugh, den försöker att regenerera. Skjut den innan jag spyr!",Yenilenmeye çalışıyor. Kusmadan önce patlat şunu! +"My friend, whatever it is we're fighting, it's more than the Order. Off to the mines!",TXT_SUB_LOG95,MAP25: After killing the Spectre.,,,"Příteli, ať už bojujeme s čímkoliv, jde o víc než jen Řád. Do dolů!","Min ven, hvad det end er, vi kæmper imod, er det mere end Ordenen. Af sted til minerne!","Mein Freund, was auch immer es ist, dass wir bekämpfen, es ist mehr als der Orden. Ab zu den Minen!",,,"Amigo mío, lo que sea contra que estemos luchando, es más que la Orden. ¡A las minas!",,"Ystäväni, mitä vastaan me taistelemmekaan, se on suurempi kuin Veljeskunta. Matkatkaamme kaivokselle!","Mon ami, je ne sais ce contre quoi on se bat, mais c'est plus que l'Ordre. Allons dans les mines!","Nos barátom, bármivel is állunk szemben, több az mint maga a Rend. Irány a bánya!","Amico mio, qualsiasi cosa stiamo combattendo, è molto più dell'Ordine. Alle miniere!","友よ、私達が戦う相手が何であろうとも、オーダー以上のものはない。 +鉱山から離れましょう!","친구야, 우리가 싸우는 상대가 무엇인지는 모르겠지만, 오더보다 더한 존재인 것 같아. 광산으로 향하자!","Mijn vriend, wat het ook is waar we tegen vechten, het is meer dan de Orde. Naar de mijnen!","Min venn, hva det enn er vi kjemper mot, så er det mer enn Ordenen. Av sted til gruvene!","Mój przyjacielu, cokolwiek to jest, z czym walczymy, to coś więcej niż Zakon. Do kopalni!","Meu amigo, seja lá o que estamos combatendo, é mais do que somente a Ordem. Vamos para as minas!",,"Prietene, orice ar fi ceea ce înfruntăm, e mai mult decât Ordinul. Către mine!","Друг мой, с чем бы мы ни сражались, это нечто большее, чем просто Орден. К шахтам!",,"Min vän, vad det än är vi slåss mot, så är det mer än Orden. Iväg till gruvorna!","Dostum, savaştığımız şey her neyse, Tarikat'tan daha fazlası. Madenlere!" +"Without letting down your guard, look for deposits of ore.",TXT_SUB_LOG96,MAP14: Entrance.,,,Opatrně se zkus podívat po ložiscích rudy.,"Uden at sænke din vagt, skal du lede efter malmforekomster.",Sei vorsichtig und halte Ausschau nach Erzvorkommen.,,,"Sin bajar la guardia, busca depósitos de mineral.",,"Etsi malmiesiintymiä, kuitenkin valppautesi säilyttäen.","Sans arrêter de faire attention, cherche des veines de minerai.","Keress érceket, de figyelj a hátad mögé közben.","Senza abbassare la guardia, cerca di trovare alcuni depositi di minerali.",警戒を緩めることなく、鉱石の堆積所を探しましょう。,"조심해가면서, 그들이 캔 광석을 두는 곳을 찾아.","Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen.","Uten å senke garden, let etter malmforekomster.","Nie spuszczając gardy, szukajcie złóż rudy.",Não baixe a sua guarda. Vamos procurar por depósitos de minério.,,"Fără a lăsa garda jos, uită-te dupa depozite de minereu.","Поищи залежи руды, но не теряй бдительности!",,"Utan att sänka garden, leta efter malmfyndigheter.","Gardınızı düşürmeden, maden yataklarını arayın." +"These poor souls are drones, their synaptic functions are jammed by RC implants. We destroy the transmitter and they are free!",TXT_SUB_LOG97,MAP14: After crossing the entrance's yard.,,,"Tihle chudáci jsou trubci, jejich synaptické funkce jsou narušené na dálku ovládanými implantáty. Když zničíme vysílačku, budou svobodní!","Disse stakkels sjæle er droner, deres synaptiske funktioner er blokeret af RC-implantater. Vi ødelægger senderen, og de er frie!","Diese armen Seelen sind Drohnen, ihre synaptischen Funktionen werden von Implantaten blockiert. Wenn wir den Transmitter zerstören, sind sie frei.",,,"Estas pobres almas son zánganos. Sus funciones sinápticas están bloqueadas por implantes de control remoto. ¡Destruimos el transmisor, y son libres!",,"Nämä sieluparat ovat kuhnureita: Heidän synaptisia toimintojaan häiritään radio-ohjattavilla istutteilla. Me tuhoamme lähettimen, ja he ovat vapaat!","Ces pauvres âmes sont des drones, leurs fonctions synaptiques sont brouillées par des implants radiocommandés. On détruit le transmetteur et ils sont libres!","Ezek a szerencsétlen lelkek csak drónok. A szinaptikus funkcióikat zavarják távolról irányítható implantátumokkal. Szétromboljuk a jeladókat, és szabaddá vállnak.","Questi poveracci sono degli schiavi. Le loro funzioni cerebrali stanno venendo bloccate da degli impianti. Se distruggiamo il trasmettitore, saranno liberi!","これら精神の乏しい労働者達は、シナプス機能をRCインプラントで妨害している。 +私達が送信機を破壊し皆を解放するんだ!","저 사람들은 불쌍한 광산의 노예들이야. 오더가 이식한 세뇌 장치 때문에 정상적인 뇌 기능을 잃었지. 전송기만 파괴한다면, 그들은 자유를 되찾을 수 있을 거야!","Deze arme zielen zijn drones, hun synaptische functies worden verstoord door RC-implantaten. We vernietigen de zender en ze zijn vrij!","Disse stakkarene er droner, deres synaptiske funksjoner er blokkert av RC-implantater. Vi ødelegger senderen, og de er fri!","Te biedne dusze są dronami, ich funkcje synaptyczne są zagłuszane przez implanty RC. Zniszczymy nadajnik i są wolne!",Esses pobres coitados são escravos. Suas funções sinápticas estão sendo bloqueadas por implantes de controle remoto. Se destruirmos o transmissor eles estarão livres!,,Sufletele ăstea sărmane sunt drone. Funcțiile lor sinaptice sunt întrerupte de implanturi RC. Distrugem transmițătorul și sunt libere!,"Эти несчастные души — дроны. Сигнал, поступающий на импланты, полностью подавляет их сознание. Давай уничтожим передатчик и освободим их!",,"Dessa stackars själar är drönare, deras synaptiska funktioner är blockerade av RC-implantat. Vi förstör sändaren och de är fria!","Bu zavallı ruhlar dron, sinaptik fonksiyonları RC implantları tarafından engellenmiş. Vericiyi yok edersek özgür kalırlar!" +"Command says the transmitter is shielded by a force field. So two birds, one stone, free the drones and practice with the ore.",TXT_SUB_LOG98,MAP14: After the entrance's yard and before going down.,,,"Velení říká, že vysílačka je chráněná silovým polem. Dvě mouchy jednou ranou: osvobodíme vězně a vyzkoušíme si, jak s tou rudou.","Kommandocentralen siger, at senderen er beskyttet af et kraftfelt. Så to fluer i et smæk, befri dronerne og øv dig med malmen.","Die Kommandozentale sagt, der Transmitter sei von einem Kraftfeld geschützt. So, zwei Fliegen, eine Klatsche, befreie die Drohnen und übe mit dem Erz.",,,"El Comando dice que el transmisor está protegido por un campo de fuerza. Dos pájaros de un tiro, libera a los zánganos y practica con el mineral.",,"Komentokeskus sanoo, että lähetin on voimakentän suojaama. Siispä kaksi kärpästä yhdellä iskulla: vapautamme kuhnurit ja samalla harjoittelemme malmilla.","La commandement me dit que le transmetteur est protégé par un champ de force. Ca fait d'une pierre de coups. On libère les drones, et on s'entraîne avec le minerai.",Az irányítás szerint a jeladó el van szeparálva egy erőpajzzsal. Tehát két légy és egy csapás: szabadítsuk ki a drónokat és gyakoroljunk az érccel.,"Il comando dice che il trasmettitore è protetto da un campo di forza. Quindi, due piccioni con una fava. Liberiamo gli schiavi e facciamo pratica con il minerale.","司令官は送信機がフォースフィールドに守られていると言っていた。 +そこを潰せば鉱山と労働者を解放、一石二鳥だな。",본부가 말하길 전송기는 방어막에 의해 보호받고 있대. 광석을 사용하는 방법을 연습하면서 노예들을 해방한다면 일석이조일 거야.,"Het commando zegt dat de zender is afgeschermd door een krachtveld. Dus twee vogels, een steen, bevrijden de drones en oefenen met het erts.","Kommandoen sier at senderen er beskyttet av et kraftfelt. Så to fluer i en smekk, frigjør dronene og øv med malmen.","Dowództwo mówi, że nadajnik jest osłonięty przez pole siłowe. Więc dwie pieczenie na jednym ogniu, uwolnić drony i poćwiczyć z rudą.",O comando diz que o transmissor está protegido por um campo de força. Dois coelhos numa tacada só. Liberte os escravos e teste o minério.,,"Centrul de comandă e prtejat de un câmp de forță. Deci, două păsări, o piatră.","Штаб говорит, что передатчик защищён силовым полем. Ты освободишь дронов и испытаешь руду — одним выстрелом двух зайцев!",,"Ledningen säger att sändaren är skyddad av ett kraftfält. Så två flugor i en smäll, frigör drönarna och öva med malmen.","Komuta vericinin bir güç alanı tarafından korunduğunu söylüyor. Yani bir taşla iki kuş, dronları serbest bırak ve cevherle pratik yap." +"My suggestion is, toss the ore at the forcefield and then blast it. The resulting compression should create a magnetic blanket and turn off the lights.",TXT_SUB_LOG99,MAP14: After James's room.,,,"Můj návrh je, hoď rudu na to silové pole a pak ji odstřel. Výsledná komprese by měla vytvořit magnetický povlak a vypnout pole.","Mit forslag er, at kaste malmen mod kraftfeltet og derefter sprænge det. Den resulterende kompression skulle skabe et magnetisk tæppe og slukke lyset.","Mein Vorschlag wäre, das Erz vor das Kraftfeld zu legen und dann explodieren zu lassen. Die resultierende Kompression sollte ein Magnetfeld erzeugen und die Lichter ausgehen lassen.",,,"Mi sugerencia es, tirar el mineral hacia el campo de fuerza y luego reventarlo, la presión resultante debería crear un manto magnético y apagar las luces.",,"Ehdotukseni on, että heität malmin voimakentään ja sitten posautat sen. Syntyvän paineaallon pitäisi muodostaa magneettinen peitto ja sammuttaa valot.",Ma suggestion: jette le minerai sur le champ de force puis tire dessus. La compression qui en résulte devrait créer un champ magnétique qui va désactiver les lumières.,"Az a tanácsom, hogy dobd az ércet az erőpajzsra, és robbantsd fel. A keletkező kompresszió egy mágneses takarót kéne hogy képezzen, így kikapcsolva a fényeket.","Il mio consiglio è, lancia uno dei minerali al campo di forza e poi fallo saltare in aria. Questo dovrebbe sprigionare l'energia sufficiente a disattivare il campo di forza.","私の案はフォースフィールドの近くに鉱石を置き撃って爆発させる方法よ。 +その結果、圧縮されていた磁場の反動で光を打ち消すわ。","조언을 찾는다면, 광석을 방어막에 가까이 놔둔 뒤 쏴봐. 광석이 커다란 자기장을 만들 테고, 방어막을 완전히 무력화 시킬 거야. 불 끄는거지!",Mijn suggestie is om het erts naar het krachtveld te gooien en het vervolgens op te blazen. De resulterende compressie zou een magnetische deken moeten creëren en de lichten moeten doven.,Mitt forslag er å kaste malmen mot kraftfeltet og sprenge det. Den resulterende kompresjonen bør skape et magnetisk teppe og slå av lysene.,Proponuję rzucić rudę w pole siłowe i wysadzić je. Powstała kompresja powinna stworzyć koc magnetyczny i wyłączyć światła.,Minha sugestão é que você arremesse o minério no campo de força e o detone. A explosão vai criar um campo magnético e apagar as luzes.,,"Sugstia mea e, aruncă minereul în scut și aruncă-l în aer. Comprimarea rezultată ar trebui să creeze un câmp magnetic care sp oprească luminile.","Мой план: бросить руду поближе к силовому полю и взорвать её. Взрыв создаст магнитное поле, которое накроет электронику и отрубит её.",,Mitt förslag är att kasta malmen mot kraftfältet och sedan spränga det. Den resulterande kompressionen bör skapa ett magnetiskt täcke och släcka ljuset.,"Benim önerim, cevheri güç alanına fırlatın ve sonra patlatın. Ortaya çıkan sıkıştırma manyetik bir örtü oluşturmalı ve ışıkları kapatmalı." +Now on to the factory. Exit the mines and you can't miss it!,TXT_SUB_LOG100,MAP14: After destroying the transmitter.,,,A teď do továrny. Vyjdi z dolů a nemůžeš to minout.,"Nu videre til fabrikken. Gå ud af minerne, og du kan ikke undgå at se den!",Und nun zur Fabrik. Verlasse die Minen und du kannst sie nicht verpassen.,,,Ahora vamos a la fábrica. ¡Sal de las minas y no puedes perderlo!,,"Nyt sitten tehtaaseen. Poistu kaivoksesta, ja löydät sen varmasti!","Bon, maintenant, l'usine! Sors des mines et tu peux pas la rater!",Most pedig irány a gyár. Kilépve a bányából nem tudod eltéveszteni.,Ora entriamo nella Fabbrica. Uscendo dalle miniere non puoi sbagliare.,今すぐ工場へ向かおう。鉱山を出たら見逃すなよ!,이제 공장으로 향하자. 광산을 나가면 더 재밌는 모험이 펼쳐질 거야!,Nu naar de fabriek. Verlaat de mijnen en je kunt het niet missen!,"Nå videre til fabrikken. Gå ut av gruvene, og du kan ikke gå glipp av den!",Teraz przejdź do fabryki. Wyjdź z kopalni i nie możesz jej przegapić!,"Agora, para a fábrica. Saia das minas e não vai ter como errar.",,Acum către fabrică. Ieși din mine și nu o poți rata.,"Теперь — на фабрику. Выйди из шахты, и ты сразу увидишь вход!",,Nu till fabriken. Gå ut ur gruvorna och du kan inte missa den!,Şimdi fabrikaya gidelim. Madenlerden çıkın ve onu kaçırmayın! +"Sorry, hero, this is all new to me.",TXT_SUB_LOG101,MAP20: Exit to Commons (MAP23).,,,"Promiň, hrdino, tohle všechno je pro mě nové.","Undskyld, helt, det er alt sammen nyt for mig.","Entschuldigung, mein Held, das ist alles neu für mich.",,,"Lo siento, héroe, esto es nuevo para mí.",,"Pahoittelut, sankari; tämä kaikki on uutta minulle.","Désolé, héros, tout cela est nouveau pour moi.","Sajnálom hősöm, ez mind rendkívűl új számomra.","Mi spiace, eroe, ma tutto ciò è nuovo per me.",ごめんなさい、これは初耳なの。,"미안, 영웅 친구... 이런 곳은 처음 봐.","Sorry, held, dit is allemaal nieuw voor mij.","Beklager, helt, dette er nytt for meg.","Wybacz, bohaterze, to wszystko jest dla mnie nowe.","Foi mal, meu herói, tudo isso é novo pra mim.","Desculpa, meu herói, tudo isto é novo para mim.","Scuze, eroule, asta e nou pentru mine.","Извини, герой. Для меня это всё в новинку.",,"Ledsen, hjälte, allt detta är nytt för mig.","Üzgünüm kahraman, bunların hepsi benim için yeni." +I'm reading massive neural wave distortions from straight ahead. I think we've found it.,TXT_SUB_LOG102,MAP20: Path to Conversion Chapel (MAP24).,,,"Detekuju obří rušení nervových vln přímo před námi. Myslím, že jsme to našli.","Jeg læser massive neurale bølgeforvridninger lige forude. Jeg tror, vi har fundet det.","Ich empfange massive neurale Verzerrungen direkt voraus. Ich denke, wir haben sie gefunden.",,,Estoy leyendo distorsiones de ondas neuronales masivas adelante. Creo que la hemos encontrado.,Estoy leyendo distorsiones neuronales masivas adelante. Creo que la hemos encontrado.,Havaitsen massivisia hermoaaltovääristymiä suoraan edessä. Luulen löytäneemme sen.,Je recois des distorsions neurales colossales devant nous. Je crois que nous l'avons trouvé. ,Erős ideghullám zavaró jeleket fogok. Azt hiszem megtaláltuk.,Sto ricevendo potenti segnali distorti proprio davanti a te. Penso che l'abbiamo trovata.,重い神経波の歪曲が直に届いたわ。私達はそれを見つけたという事よ。,앞쪽에서 거대한 신경교란 파장이 감지되고 있어. 우리가 찾아낸 것 같아.,Ik lees enorme neurale golfvervormingen van rechtdoor. Ik denk dat we het gevonden hebben.,Jeg leser massive nevrale bølgeforvrengninger rett fram. Jeg tror vi har funnet den.,Odczytuję masywne zakłócenia fal neuronowych z prostej drogi. Chyba to znaleźliśmy.,Estou captando enormes distorções de rede neural mais adiante. Acho que encontramos.,,Citesc distorsiuni neurale masive drept din față. Cred că am găsit-o.,"Я вижу мощный источник помех прямо по курсу. Похоже, мы нашли конвертер.",,Jag läser massiva neurala vågförvrängningar rakt fram. Jag tror att vi har hittat den.,Tam karşıdan büyük sinirsel dalga bozulmaları okuyorum. Sanırım onu bulduk. +Just when I think we've seen it all! They go in human and come out... I dont even want to think about it.,TXT_SUB_LOG103,MAP24: Converter room.,,,"Zrovna, když jsem myslela, že jsme už viděli všechno! Dovnitř jdou jako lidé a ven vyjdou... ani na to nechci myslet.","Lige når jeg tror, vi har set det hele! De går ind i et menneske og kommer ud... Jeg vil ikke engang tænke på det.","Und da denkt man, man hätte schon alles gesehen. Die kommen als Menschen rein und kommen raus als... Ich möchte gar nicht drüber nachdenken.",,,¡Justo cuando creía haberlo visto todo! Entran humanos y salen... No quiero ni pensarlo. ,,Juuri kun luulen nähneemme kaiken! He menevät sisään ihmisinä ja tulevat ulos... En halua edes ajatellakaan sitä.,"Et quand je pense avoir tout vu.. Des humains entrent, et puis.. Non, je ne veux pas y penser. ","Amikor azt hittem, hogy mindent láttunk. Emberként mennek be, és úgy jönnek ki mint egy...nem is akarok rá gondolni.",E io che pensavo di averle viste tutte! Entrano umani ed escono fuori... Non ci voglio neanche pensare.,"今まで見てきたことについて考えている! +奴は人の内部から出てくる...それについて考えたくないわ。",이렇게 끔찍한 모습을 보게 되다니! 멀쩡한 사람이 저곳에 들어갔다 나온 모습을... 차마 생각하기도 싫어.,Net nu ik denk dat we het allemaal hebben gezien! Ze gaan in de mens en komen eruit.... Ik wil er niet eens over nadenken.,Akkurat når jeg tror vi har sett alt! De går inn som mennesker og kommer ut... Jeg vil ikke engang tenke på det.,"Właśnie wtedy, gdy myślałem, że widzieliśmy już wszystko! Wchodzą w człowieka i wychodzą... Nawet nie chcę o tym myśleć.",E eu achei que já tinha visto de tudo! Eles entram humanos e saem... eu não quero nem pensar nisso.,,Tocmai când credeam că am văzut tot! Intră oameni și ies... nici nu vreau să mă gândesc.,"А я-то думала, что хуже уже не будет! Они входят людьми, а выходят... Не хочу даже думать об этом.",,Precis när jag tror att vi har sett allt! De går in i en människa och kommer ut... Jag vill inte ens tänka på det.,Tam da her şeyi gördüğümüzü düşündüğüm anda! İnsana giriyorlar ve çıkıyorlar. Bunu düşünmek bile istemiyorum. +The Oracle was right. Macil's gone nuts. He just knowingly sent 200 men to their death. I want vengeance. For the dead and for the living dead!,TXT_SUB_LOG104,MAP24: After destroying the converter.,,,Věštec měl pravdu. Macil zešílel. Vědomě poslal dvě stě mužů na smrt. Chci odplatu - za mrtvé i živé mrtvé!,Oraklet havde ret. Macil er blevet skør. Han har lige bevidst sendt 200 mænd i døden. Jeg vil have hævn. For de døde og for de levende døde!,Das Orakel hatte Recht. Macil hat den Verstand verloren. Er hat gerade absichtlich 200 unserer Leute in den Tod geschickt. Ich will Rache! Für die Toten und für die lebenden Toten.,,,"El Oráculo tenía razón. Macil se ha vuelto loco: ha enviado intencionalmente a 200 hombres directo a la muerte. Quiero venganza, ¡por los muertos y los muertos vivientes!","El Oráculo tenía razón. Macil se volvió loco: mandó intencionalmente a 200 hombres directo a la muerte. Quiero venganza, ¡por los muertos y los muertos vivientes!","Oraakkeli oli oikeassa: Macil on tullut hulluksi. Hän juuri lähetti tietoisesti 200 miestä surmaansa. Vaadin kostoa, sekä kuolleitten että elävien kuolleitten puolesta!","Macil a complètement perdu les pédales! Il a envoyé 200 hommes se faire tuer, et il le savait! Il faut les venger, pour eux et pour leurs camarades!",Az Orákulumnak igaza volt. macil megőrült. Szándékosan küldött 200 emberünket a halálába. Meg akarom bosszúlni a halottak és az élő halottak nevében!,L'Oracolo aveva ragione. Macil deve essere impazzito. Ha mandato consciamente 200 uomini verso la morte. Voglio vendetta! Per i morti e per i morti viventi!,"オラクルが正しかった。マシルはイカれていたなんて。 彼は故意に200人以上の人々を死に追いやっていた。 -復讐しなくては。死んだ人達の為、そして今生きている人達の為にも!",마실이 정신 나갔나 봐. 모든 것을 알면서도 200 명이나 되는 병력을 보내서 죽게 했어. 과부들과 망령들을 위한 복수를 할 시간이야!,Het Orakel had gelijk. Macil is gek geworden. Hij stuurde gewoon bewust 200 mannen naar hun dood. Ik wil wraak. Voor de doden en voor de levende doden!,Oraklet hadde rett. Macil har gått fra vettet. Han sendte 200 menn i døden med viten og vilje. Jeg vil ha hevn. For de døde og for de levende døde!,Wyrocznia miała rację. Macilowi odbiło. Właśnie świadomie wysłał 200 ludzi na śmierć. Chcę zemsty. Za zmarłych i za żywych zmarłych!,O Oráculo estava certo. O Macil enlouqueceu. Ele mandou 200 homens para as suas mortes sabendo disso. Eu quero vingança. Pelos mortos e pelos mortos-vivos!,,Oracolul avea dreptate. Macil a înnebunit. A trimis în mod voit 200 oameni la moarte. Vreau răzbunare! Pentru morți și morții vii!,Оракул сказал правду: Мэйсил озверел. Он намеренно послал двести человек на верную смерть. Я жажду мести! За убитых и за живых мертвецов!,,Kahin haklıydı. Macil delirmiş. Bile bile 200 adamı ölüme gönderdi. İntikam istiyorum. Ölüler ve yaşayan ölüler için! -"Macil? Infected and with a Sigil piece. All these years of believing in him, in the cause. And for what?",TXT_SUB_LOG105,,,,"Macil? Nakažený a s dílem Pečeti? Všechny ty roky, kdy jsme mu a naší věci důvěřovali. A k čemu?","Macil? Inficeret og med et Sigil stykke. I alle disse år har jeg troet på ham, på sagen. Og for hvad?","Macil? Infiziert und mit einen Sigli-Teil? All diese Jahre, die ich an ihn geglaubt habe - an die Sache. Und für was?",,,"¿Macil? Infectado con una pieza del Emblema. Todos estos años de creer en el, en la causa. ¿Y para que?",,"Macil, tartunnan saanut ja pitää hallussaan Sinetin osasta? Kaikki nämä vuodet uskoen häneen, aatteeseen. Ja minkä tähden?",Macil? Infecté par une pièce du Sigil. Toutes ces années où je lui ai fait confiance.. à la cause.. Et pour quoi à la fin?,"Macil? Meg van fertőzve, és van nála egy Pecsét darab is. Én pedig hittem neki évekig, hittem az ügyben. És miért?","Macil? Infettato e con un pezzo del Sigillo. Tutti questi anni passati a credere in lui, e alla causa. E per cosa?",,마실? 시질 조각에 의해 오염됬어. 수 년 동안 믿어온 우리가 바보인가? 아니면 이 운명을 피할 수 없었던 걸까?,"Macil? Geïnfecteerd en met een Sigil stuk. Al die jaren van geloof in hem, in de oorzaak. En waarvoor?","Macil? Infisert og med en Sigil-brikke. I alle disse årene har jeg trodd på ham, på saken... Og for hva?","Macil? Zainfekowany i z kawałkiem Sigil. Przez te wszystkie lata wierzyłem w niego, w sprawę. I po co?","Macil? Infectado e com uma peça do Sigilo. Todos esses anos acreditando nele, acreditando na causa. E pra quê?",,"Macil? Infectat și cu o bucată de Sigiliu. Toți anii crezând în cauza lui, și pentru ce?","Мэйсил? Заражённый... И у него фрагмент Печати. Все эти годы я верила ему, верила в нашу миссию. А теперь?",,"Macil mi? Enfekte olmuş ve bir Sigil parçasıyla. Bunca yıl ona inandım, davaya inandım. Peki ne için?" -"Richter reports that the factory we destroyed leads to a ""lab"", and they're getting a Sigil power signature from within. Back to the factory and our next step to freedom.",TXT_SUB_LOG106,"STRIFE1.WAD: MAP10 - -(After killing Macil while having destroyed the converter in MAP24)",,,"Richter hlásí, že továrna, kterou jsme zničili, vede do „laboratoře“ a detekují z ní energii Pečetě. Zpátky do továrny a našemu dalšímu kroku ke svobodě.","Richter rapporterer, at den fabrik, vi ødelagde, fører til et ""laboratorium"", og at de får en Sigil-kraftsignatur derindefra. Tilbage til fabrikken og vores næste skridt mod frihed.","Richter sagt, in der Fabrik, die wir zerstört haben, gäbe es ein „Labor“, und dort gibt es eine Sigil-Signatur. Zurück zur Fabrik und dem nächsten Schritt zu unserer Freiheit.",,,"Richter informa de que la fábrica que destruimos conduce a un ""laboratorio"", y están recibiendo una señal de poder del Emblema de adentro. De vuelta a la fábrica y nuestro siguiente paso a la libertad.",,"Richter ilmoittaa, että tuhoamamme tehdas johtaa ""laboratorioon"", ja he lukevat sisältä Sinettiosasen energiajälkiä. Takaisin tehtaaseen ja kohti seuraavaa askeltamme vapauteen.","Richter rapporte que l'usine que l'on a détruit mène à un ""laboratoire"" et qu'il s'y trouve une signature de pièce du Sigil à l'intérieur. Retourne à l'usine et on fera un autre pas vers la liberté.","Richter jelentése szerint a felrobbantott gyár egy ""laboratóriumba"" vezet, és a Pecsét jelét sugározza belülről. Tehát a szabadságunk felé teendő következő lépés a gyárnál kezdődik.","Richter ci comunica che la Fabbrica che abbiamo distrutto porta a un ""laboratorio"", ed al suo interno è stato identificato un segnale di un pezzo del Sigillo. Ritorniamo alla fabbrica e il nostro prossimo passo per la libertà.","リヒターの報告では我々が破壊した工場は'研究所'に繋がっていて、 -奴等はシジルの調印を内部から得ている。工場に戻って自由への次の段階に進みましょう",릭터가 말하길 우리가 파괴한 공장은 연구소로 향하는 길이 있대. 그리고 그곳에는 시질 특유의 힘이 감지됐어. 공장으로 돌아가서 자유를 위해 계속 투쟁을 하자.,"Richter meldt dat de fabriek die we vernietigd hebben, leidt naar een ""lab"", en ze krijgen een Sigil power signatuur van binnenuit. Terug naar de fabriek en onze volgende stap naar vrijheid.","Richter rapporterer at fabrikken vi ødela fører til en ""lab"", og at de får en Sigil-kraftsignatur innenfra. Tilbake til fabrikken og vårt neste skritt mot frihet.","Richter donosi, że zniszczona przez nas fabryka prowadzi do ""laboratorium"", a oni otrzymują z niego sygnaturę mocy Sigil. Wracamy do fabryki i naszego kolejnego kroku do wolności.","O Richter disse que a fábrica que destruímos leva a um ""laboratório"" e eles estão captando um sinal de energia lá de dentro. De volta à fábrica e ao nosso próximo passo à liberdade.",,"Richter raportează că fabrica duce către un laborator, și sunt alimentați e puterea unui Sigiliu din interior. Înapoi la fabrică și următorul pas spre libertate.","Рихтер сообщает, что за разрушенной нами фабрикой лежит «лаборатория», и мы засекли характерную энергию фрагмента Печати, исходящую оттуда. Возвращайся на фабрику — сделаем ещё один шаг к нашему освобождению.",,"Richter, yok ettiğimiz fabrikanın bir laboratuvara çıktığını ve oradan Sigil gücü sinyali aldıklarını bildirdi. Fabrikaya ve özgürlüğe giden bir sonraki adımımıza dönelim." +復讐しなくては。死んだ人達の為、そして今生きている人達の為にも!",마실이 정신 나갔나 봐. 모든 것을 알면서도 200 명이나 되는 병력을 보내서 죽게 했어. 과부들과 망령들을 위한 복수를 할 시간이야!,Het Orakel had gelijk. Macil is gek geworden. Hij stuurde gewoon bewust 200 mannen naar hun dood. Ik wil wraak. Voor de doden en voor de levende doden!,Oraklet hadde rett. Macil har gått fra vettet. Han sendte 200 menn i døden med viten og vilje. Jeg vil ha hevn. For de døde og for de levende døde!,Wyrocznia miała rację. Macilowi odbiło. Właśnie świadomie wysłał 200 ludzi na śmierć. Chcę zemsty. Za zmarłych i za żywych zmarłych!,O Oráculo estava certo. O Macil enlouqueceu. Ele mandou 200 homens para as suas mortes sabendo disso. Eu quero vingança. Pelos mortos e pelos mortos-vivos!,,Oracolul avea dreptate. Macil a înnebunit. A trimis în mod voit 200 oameni la moarte. Vreau răzbunare! Pentru morți și morții vii!,Оракул сказал правду: Мэйсил озверел. Он намеренно послал двести человек на верную смерть. Я жажду мести! За убитых и за живых мертвецов!,,Oraklet hade rätt. Macil har blivit galen. Han skickade just medvetet 200 män i döden. Jag vill ha hämnd. För de döda och för de levande döda!,Kahin haklıydı. Macil delirmiş. Bile bile 200 adamı ölüme gönderdi. İntikam istiyorum. Ölüler ve yaşayan ölüler için! +"Macil? Infected and with a Sigil piece. All these years of believing in him, in the cause. And for what?",TXT_SUB_LOG105,,,,"Macil? Nakažený a s dílem Pečeti? Všechny ty roky, kdy jsme mu a naší věci důvěřovali. A k čemu?","Macil? Inficeret og med et Sigil stykke. I alle disse år har jeg troet på ham, på sagen. Og for hvad?","Macil? Infiziert und mit einen Sigli-Teil? All diese Jahre, die ich an ihn geglaubt habe - an die Sache. Und für was?",,,¿Macil infectado con una pieza del Emblema? Y todos estos años de creer en el... en la causa... ¿Y todo para qué?,,"Macil, tartunnan saanut ja pitää hallussaan Sinetin osasta? Kaikki nämä vuodet uskoen häneen, aatteeseen. Ja minkä tähden?",Macil? Infecté par une pièce du Sigil. Toutes ces années où je lui ai fait confiance.. à la cause.. Et pour quoi à la fin?,"Macil? Meg van fertőzve, és van nála egy Pecsét darab is. Én pedig hittem neki évekig, hittem az ügyben. És miért?","Macil? Infettato e con un pezzo del Sigillo. Tutti questi anni passati a credere in lui, e alla causa. E per cosa?",,마실? 시질 조각에 의해 오염됬어. 수 년 동안 믿어온 우리가 바보인가? 아니면 이 운명을 피할 수 없었던 걸까?,"Macil? Geïnfecteerd en met een Sigil stuk. Al die jaren van geloof in hem, in de oorzaak. En waarvoor?","Macil? Infisert og med en Sigil-brikke. I alle disse årene har jeg trodd på ham, på saken... Og for hva?","Macil? Zainfekowany i z kawałkiem Sigil. Przez te wszystkie lata wierzyłem w niego, w sprawę. I po co?","Macil? Infectado e com uma peça do Sigilo. Todos esses anos acreditando nele, acreditando na causa. E pra quê?",,"Macil? Infectat și cu o bucată de Sigiliu. Toți anii crezând în cauza lui, și pentru ce?","Мэйсил? Заражённый... И у него фрагмент Печати. Все эти годы я верила ему, верила в нашу миссию. А теперь?",,"Macil? Infekterad och med en Sigil-bit. Under alla dessa år har jag trott på honom, på saken. Och för vad?","Macil mi? Enfekte olmuş ve bir Sigil parçasıyla. Bunca yıl ona inandım, davaya inandım. Peki ne için?" +"Richter reports that the factory we destroyed leads to a ""lab"", and they're getting a Sigil power signature from within. Back to the factory and our next step to freedom.",TXT_SUB_LOG106,MAP10: After killing Macil while having destroyed the converter in MAP24.,,,"Richter hlásí, že továrna, kterou jsme zničili, vede do „laboratoře“ a detekují z ní energii Pečetě. Zpátky do továrny a našemu dalšímu kroku ke svobodě.","Richter rapporterer, at den fabrik, vi ødelagde, fører til et ""laboratorium"", og at de får en Sigil-kraftsignatur derindefra. Tilbage til fabrikken og vores næste skridt mod frihed.","Richter sagt, in der Fabrik, die wir zerstört haben, gäbe es ein „Labor“, und dort gibt es eine Sigil-Signatur. Zurück zur Fabrik und dem nächsten Schritt zu unserer Freiheit.",,,"Richter informa de que la fábrica que destruimos conduce a un ""laboratorio"", y están recibiendo una señal de poder del Emblema de adentro. De vuelta a la fábrica y nuestro siguiente paso a la libertad.",,"Richter ilmoittaa, että tuhoamamme tehdas johtaa ""laboratorioon"", ja he lukevat sisältä Sinettiosasen energiajälkiä. Takaisin tehtaaseen ja kohti seuraavaa askeltamme vapauteen.","Richter rapporte que l'usine que l'on a détruit mène à un ""laboratoire"" et qu'il s'y trouve une signature de pièce du Sigil à l'intérieur. Retourne à l'usine et on fera un autre pas vers la liberté.","Richter jelentése szerint a felrobbantott gyár egy ""laboratóriumba"" vezet, és a Pecsét jelét sugározza belülről. Tehát a szabadságunk felé teendő következő lépés a gyárnál kezdődik.","Richter ci comunica che la Fabbrica che abbiamo distrutto porta a un ""laboratorio"", ed al suo interno è stato identificato un segnale di un pezzo del Sigillo. Ritorniamo alla fabbrica e il nostro prossimo passo per la libertà.","リヒターの報告では我々が破壊した工場は'研究所'に繋がっていて、 +奴等はシジルの調印を内部から得ている。工場に戻って自由への次の段階に進みましょう",릭터가 말하길 우리가 파괴한 공장은 연구소로 향하는 길이 있대. 그리고 그곳에는 시질 특유의 힘이 감지됐어. 공장으로 돌아가서 자유를 위해 계속 투쟁을 하자.,"Richter meldt dat de fabriek die we vernietigd hebben, leidt naar een ""lab"", en ze krijgen een Sigil power signatuur van binnenuit. Terug naar de fabriek en onze volgende stap naar vrijheid.","Richter rapporterer at fabrikken vi ødela fører til en ""lab"", og at de får en Sigil-kraftsignatur innenfra. Tilbake til fabrikken og vårt neste skritt mot frihet.","Richter donosi, że zniszczona przez nas fabryka prowadzi do ""laboratorium"", a oni otrzymują z niego sygnaturę mocy Sigil. Wracamy do fabryki i naszego kolejnego kroku do wolności.","O Richter disse que a fábrica que destruímos leva a um ""laboratório"" e eles estão captando um sinal de energia lá de dentro. De volta à fábrica e ao nosso próximo passo à liberdade.",,"Richter raportează că fabrica duce către un laborator, și sunt alimentați e puterea unui Sigiliu din interior. Înapoi la fabrică și următorul pas spre libertate.","Рихтер сообщает, что за разрушенной нами фабрикой лежит «лаборатория», и мы засекли характерную энергию фрагмента Печати, исходящую оттуда. Возвращайся на фабрику — сделаем ещё один шаг к нашему освобождению.",,"Richter rapporterar att fabriken som vi förstörde leder till ett ""labb"" och att de får en Sigil-kraftsignatur därifrån. Tillbaka till fabriken och vårt nästa steg mot frihet.","Richter, yok ettiğimiz fabrikanın bir laboratuvara çıktığını ve oradan Sigil gücü sinyali aldıklarını bildirdi. Fabrikaya ve özgürlüğe giden bir sonraki adımımıza dönelim." Who dares to defy me and enter my fortress? A worthless human? Face me and die!,TXT_SUB_LOG120,MAP16: Entrance → Central door.,,,Kdo se to opovažuje mi vzdorovat a vkročit do mé pevnosti? Bezcenný člověk? Postav se mi a zemři!,Hvem vover at trodse mig og gå ind i min fæstning? Et værdiløst menneske? Se mig i øjnene og dø!,Wer wagt es mir zu trotzen und meine Festung zu betreten? Ein wertloser Mensch? Stelle dich mir und stirb!,,,¿Quién se atreve a desafiarme y entrar en mi fortaleza? ¿Un insignificante humano? ¡Enfréntate a mí y muere!,¿Quién se atreve a desafiarme y entrar a mi fortaleza? ¿Un insignificante humano? ¡Enfréntate a mí y muere!,Kuka kehtaa uhmata minua ja astua sisään linnoitukseeni? Arvoton ihminen? Kohtaa minut ja kuole!,Qui ose me défier et pénétrer ma forteresse? Un humain sans valeur? Faites face à moi et mourrez!,"Ki mer belépni az erődítményebe és ellenszegülni nekem? Egy jelentéktelen ember? Gyere állj ki ellenem, had szedjelek szét!",Chi osa sfidarmi ed entrare nella mia fortezza? Un inutile umano? Affrontami e muori!,"我に歯向かう為に敢えて私の要塞に来たのか?無価値な人間よ? -死をくれてやろう!",감히 어떤 자가 이 몸을 반역하고 요새를 침입한 것이더냐? 나약한 인간이구나. 이 몸의 의해 소멸당해라.,Wie durft mij uit te dagen en mijn vesting binnen te gaan? Een waardeloos mens? Kijk me aan en sterf!,Hvem våger å trosse meg og gå inn i festningen min? Et verdiløst menneske? Møt meg og dø!,Kto ośmieli się przeciwstawić mi i wejść do mojej twierdzy? Bezwartościowy człowiek? Zmierz się ze mną i zgiń!,Quem ousa me desafiar e entrar na minha fortaleza? Um humano insignificante? Enfrente-me e morra!,,Cine îndrăznește să mă înfrunte? Un om jalnic? Înfruntă-mă și mori!,Кто смеет бросать мне вызов и вторгаться в мою крепость? Жалкий человечишка? Сразись со мной и умри!,,Kim bana meydan okuyup kaleme girmeye cüret eder? Değersiz bir insan mı? Benimle yüzleş ve öl! -You cannot kill me. You are just human. And I am more than human.,TXT_SUB_LOG121,STRIFE1.WAD: MAP16,,,Nemůžeš mě zabít. Jsi jen člověk a já jsem víc než člověk.,Du kan ikke dræbe mig. Du er bare et menneske. Og jeg er mere end et menneske.,Du kannst mich nicht töten. Du bist nur ein Mensch. Und ich bin mehr als das.,,,No puedes matarme. Eres solo humano. Y yo soy más que humano.,,"Et voi tappaa minua. Sinä olet vain ihminen, ja minä olen enemmän kuin ihminen.",Vous ne pouvez me tuer. Vous n'êtes qu'un humain. Je suis plus qu'un humain.,Nem tudsz megölni. Csak egy ember vagy. Én pedig már több vagyok mint ember.,Non puoi uccidermi. Tu sei solo umano. E io sono più che umano.,我を殺すことはできまい。貴様は人間。そして私は人間を超えし者だ。,"이 몸은 너에게 사살 당할 수 없다. 이 몸은 초월한 존재, 인간 따위를 넘었기에!",Je kunt me niet doden. Je bent gewoon een mens. En ik ben meer dan een mens.,Du kan ikke drepe meg. Du er bare et menneske. Og jeg er mer enn et menneske.,Nie możesz mnie zabić. Jesteś tylko człowiekiem. A ja jestem czymś więcej niż człowiekiem.,Você não pode me matar. Você é apenas humano. E eu sou mais do que humano.,,"Nu mă poți ucide. Ești doar un om, iar eu sunt mai mult decât atât.","Тебе не убить меня. Ты всего лишь человек. А я нечто большее, чем человек!",,Beni öldüremezsin. Sen sadece insansın. Ve ben insandan daha fazlasıyım. +死をくれてやろう!",감히 어떤 자가 이 몸을 반역하고 요새를 침입한 것이더냐? 나약한 인간이구나. 이 몸의 의해 소멸당해라.,Wie durft mij uit te dagen en mijn vesting binnen te gaan? Een waardeloos mens? Kijk me aan en sterf!,Hvem våger å trosse meg og gå inn i festningen min? Et verdiløst menneske? Møt meg og dø!,Kto ośmieli się przeciwstawić mi i wejść do mojej twierdzy? Bezwartościowy człowiek? Zmierz się ze mną i zgiń!,Quem ousa me desafiar e entrar na minha fortaleza? Um humano insignificante? Enfrente-me e morra!,,Cine îndrăznește să mă înfrunte? Un om jalnic? Înfruntă-mă și mori!,Кто смеет бросать мне вызов и вторгаться в мою крепость? Жалкий человечишка? Сразись со мной и умри!,,Vem vågar trotsa mig och gå in i min fästning? En värdelös människa? Ställ dig inför mig och dö!,Kim bana meydan okuyup kaleme girmeye cüret eder? Değersiz bir insan mı? Benimle yüzleş ve öl! +You cannot kill me. You are just human. And I am more than human.,TXT_SUB_LOG121,MAP16: Boss room unlocked → Bishop,,,Nemůžeš mě zabít. Jsi jen člověk a já jsem víc než člověk.,Du kan ikke dræbe mig. Du er bare et menneske. Og jeg er mere end et menneske.,Du kannst mich nicht töten. Du bist nur ein Mensch. Und ich bin mehr als das.,,,No puedes matarme. Eres solo humano. Y yo soy más que humano.,,"Et voi tappaa minua. Sinä olet vain ihminen, ja minä olen enemmän kuin ihminen.",Vous ne pouvez me tuer. Vous n'êtes qu'un humain. Je suis plus qu'un humain.,Nem tudsz megölni. Csak egy ember vagy. Én pedig már több vagyok mint ember.,Non puoi uccidermi. Tu sei solo umano. E io sono più che umano.,我を殺すことはできまい。貴様は人間。そして私は人間を超えし者だ。,"이 몸은 너에게 사살 당할 수 없다. 이 몸은 초월한 존재, 인간 따위를 넘었기에!",Je kunt me niet doden. Je bent gewoon een mens. En ik ben meer dan een mens.,Du kan ikke drepe meg. Du er bare et menneske. Og jeg er mer enn et menneske.,Nie możesz mnie zabić. Jesteś tylko człowiekiem. A ja jestem czymś więcej niż człowiekiem.,Você não pode me matar. Você é apenas humano. E eu sou mais do que humano.,,"Nu mă poți ucide. Ești doar un om, iar eu sunt mai mult decât atât.","Тебе не убить меня. Ты всего лишь человек. А я нечто большее, чем человек!",,Du kan inte döda mig. Du är bara en människa. Och jag är mer än människa.,Beni öldüremezsin. Sen sadece insansın. Ve ben insandan daha fazlasıyım. "No death, eternal life and more. Much more! This is my task: cyborgs, half flesh, half steel, all to serve the One God. You do not serve? You die! -This putz has another piece of the Sigil.",TXT_SUB_LOG122,"Strife: Veteran Edition: MAP12 - -(If the player first kills Macil and then the Oracle’s spectre before killing the Loremaster with Classic Mode turned off)",,,"- Žádná smrt, nekonečný život a více, mnohem více! To je mé poslání: kyborgové, napůl tělo, napůl ocel, obojí sloužící Jednomu bohu. Nesloužíš? Zemřeš! +This putz has another piece of the Sigil.",TXT_SUB_LOG122,"SVE.WAD +MAP12: If the player first kills Macil and then the Oracle's spectre before killing the Loremaster with Classic Mode turned off. It talks the Loremaster and BlackBird.",,,"- Žádná smrt, nekonečný život a více, mnohem více! To je mé poslání: kyborgové, napůl tělo, napůl ocel, obojí sloužící Jednomu bohu. Nesloužíš? Zemřeš! - Ten hajzl má další díl Pečeti.","Ingen død, evigt liv og mere. Meget mere! Dette er min opgave: Cyborgs, halvt kød, halvt stål, alt sammen for at tjene den ene Gud. Du tjener ikke? Du dør! Denne idiot har endnu et stykke af sigilet.","Kein Tod, ewiges Leben und mehr. Viel mehr! Dies ist meine Aufgabe: Cyborgs, halb Fleisch, halb Stahl, alle um einen Gott zu dienen. Du dienst nicht? Du stirbst! Dieser Idiot hat ein weiteres Teil des Sigils.",,,"No muerte, vida eterna y más. ¡Mucho más! Esta es mi tarea: cyborgs, mitad carne, mitad acero, todo para servir al Dios Único. ¿Tú no lo sirves? ¡Tú mueres! Este zoquete tiene otra pieza del emblema.",,"Ei kuolemaa, vaan ikuinen elämä ja enemmän, paljon enemmän! Tämä on tehtäväni: Kyborgit, puoliksi lihaa, puoliksi terästä; kaikkien tehtävänä palvellla Yhtä Jumalaa. Et palvele? Kuolet! @@ -12191,16 +12799,15 @@ Denne tosken har enda en bit av sigillet.","Nie ma śmierci, życie wieczne i je Ten pajac ma kolejny kawałek Sigilu.","Nada de morte. Vida eterna e mais, muito mais! Essa é a minha tarefa: cibórgues, metade carne, metade aço, todos servindo ao Deus Único. Se você não serve, você morre! Esse imbecil possui outra peça do Sigilo.",,"Nu moarte, viață eternă, și mai mult decât atât. Mult mai mult! Asta e misiunea mea: oameni cibernetici, jumătate oțel, jumătate carne, toți servind Adevăratul Zeu. Nu serviți? Muriți! Am altă bucată de Sigiliu.","— Никакой смерти. Вечная жизнь, и не только. Гораздо большее. И всё это — моя работа. Киборги — наполовину из плоти, наполовину из стали — всецело служат Единому Богу. Следуй истинной вере или умри! — У этого мудака следующий фрагмент Печати. -",,"Ölüm yok, sonsuz yaşam ve daha fazlası. Çok daha fazlası! Benim görevim bu: Cyborglar, yarı et, yarı çelik, hepsi Tek Tanrı'ya hizmet etmek için. Hizmet etmiyor musun? Ölürsünüz! +",,"Ingen död, evigt liv och mycket mer. Mycket mer! Detta är min uppgift: cyborgs, halvt kött, halvt stål, allt för att tjäna den ende Guden. Du tjänar inte? Du dör! +Den här idioten har ytterligare en bit av Sigillet.","Ölüm yok, sonsuz yaşam ve daha fazlası. Çok daha fazlası! Benim görevim bu: Cyborglar, yarı et, yarı çelik, hepsi Tek Tanrı'ya hizmet etmek için. Hizmet etmiyor musun? Ölürsünüz! Bu salakta Sigil'in bir parçası daha var." -"Ha ha! Welcome. I have waited for this moment. I have waited for a fool like you to bring me my freedom. Your tiny planet is mine, and you will wish you were never born! ",TXT_SUB_LOG128,"STRIFE1.WAD: MAP29 - -(If the player is progressing through the mediocre ending)",,,"Ha há! Vítej. Čekala jsem na tento okamžik. Čekala jsem na blázna jako ty, který by mi přinesl svobodu. Tvá drobná planeta je moje a ty si budeš přát, že ses nikdy nenarodil!","Ha ha! Velkommen. Jeg har ventet på dette øjeblik. Jeg har ventet på at et fjols som dig skulle bringe mig min frihed. Din lille planet er min, og du vil ønske, at du aldrig var blevet født!","Ha ha! Willkommen. Ich habe auf diesen Moment gewartet, dass ein Narr wie du mir meine Freiheit bringt. Dein kleiner Planet ist mein, und du wirst dir wünschen nie geboren worden zu sein!",,,"¡Ha ha! Bienvenido. He estado esperando este momento. He estado esperando a un necio como tú para traerme mi libertad. ¡Tu pequeño planeta es mío, y desearás no haber nacido!",,"Hahaa! Tervetuloa, olen odottanut tätä hetkeä. Olen odottanut kaltaistasi hölmöä tuomaan minulle minun vapauteni. Pikkuinen planeettanne on minun, ja tulet toivomaan, ettet olisi ikinä syntynytkään!","Ha ha! Bienvenue, j'ai attendu ce moment. J'ai attendu qu'un idiot comme vous me rende ma liberté. Votre pathétique planète m'appartient, et bientôt, vous allez tous regretter d'être nés!","Há há! Nincs mit. Erre a pillanatra vágytam. Arra vártom, hogy egy bolond elhozza nekem a szabadságot. A kicsike bolygód immáron az enyém, és azt fogod kívánni hogy bárcsak meg se születtél volna.","Ha ha! Benvenuto. Ho aspettato questo momento. Ho aspettato uno stolto come te per ridarmi la libertà. Il tuo patetico pianeta è nelle mie mani, e tu presto rimpiangerai di essere nato.","ハッハッハ!ようこそ。私はこの瞬間を待ってイタ。 +"Ha ha! Welcome. I have waited for this moment. I have waited for a fool like you to bring me my freedom. Your tiny planet is mine, and you will wish you were never born! ",TXT_SUB_LOG128,MAP29: Entity (If the player is progressing through the mediocre ending),,,"Ha há! Vítej. Čekala jsem na tento okamžik. Čekala jsem na blázna jako ty, který by mi přinesl svobodu. Tvá drobná planeta je moje a ty si budeš přát, že ses nikdy nenarodil!","Ha ha! Velkommen. Jeg har ventet på dette øjeblik. Jeg har ventet på at et fjols som dig skulle bringe mig min frihed. Din lille planet er min, og du vil ønske, at du aldrig var blevet født!","Ha ha! Willkommen. Ich habe auf diesen Moment gewartet, dass ein Narr wie du mir meine Freiheit bringt. Dein kleiner Planet ist mein, und du wirst dir wünschen nie geboren worden zu sein!",,,"¡Ha ha! Bienvenido. He estado esperando este momento. He estado esperando a un necio como tú para traerme mi libertad. ¡Tu pequeño planeta es mío, y desearás no haber nacido!",,"Hahaa! Tervetuloa, olen odottanut tätä hetkeä. Olen odottanut kaltaistasi hölmöä tuomaan minulle minun vapauteni. Pikkuinen planeettanne on minun, ja tulet toivomaan, ettet olisi ikinä syntynytkään!","Ha ha! Bienvenue, j'ai attendu ce moment. J'ai attendu qu'un idiot comme vous me rende ma liberté. Votre pathétique planète m'appartient, et bientôt, vous allez tous regretter d'être nés!","Há há! Nincs mit. Erre a pillanatra vágytam. Arra vártom, hogy egy bolond elhozza nekem a szabadságot. A kicsike bolygód immáron az enyém, és azt fogod kívánni hogy bárcsak meg se születtél volna.","Ha ha! Benvenuto. Ho aspettato questo momento. Ho aspettato uno stolto come te per ridarmi la libertà. Il tuo patetico pianeta è nelle mie mani, e tu presto rimpiangerai di essere nato.","ハッハッハ!ようこそ。私はこの瞬間を待ってイタ。 自由を得る為、アンタの様な愚か者を待っていたノダ。 キサマのワクセイはワタシのモノだ、ソシテ生マレタコトニ後悔スルデアロウ。 -","하하, 이 순간만을 기다리고 있었노라. 그대와 같은 어리석은 자가 짐을 풀어줄 순간을. 그대의 조그만 행성은 이제 짐의 것이고, 그대는 태어난 것을 후회하게 될 것이니라!","Ha ha! Welkom. Ik heb op dit moment gewacht. Ik heb gewacht op een dwaas als jij om mij mijn vrijheid te brengen. Jouw kleine planeet is de mijne, en je zult wensen dat je nooit geboren was!","Ha ha! Velkommen. Jeg har ventet på dette øyeblikket. Jeg har ventet på dette øyeblikket. Jeg har ventet på at en tosk som deg skulle gi meg min frihet. Din lille planet er min, og du vil ønske at du aldri ble født!","Ha ha! Witam. Czekałem na tę chwilę. Czekałem, aż taki głupiec jak ty przyniesie mi wolność. Twoja mała planeta jest moja, a ty będziesz żałował, że się nie urodziłeś!",Ha ha! Bem-vindo. Eu esperei por este momento. Esperei por um tolo como você trazer a minha liberdade. O seu planeta insignificante é meu e você vai desejar nunca ter nascido!,,"Ha ha! Bun-venit. Am așteptat momentul. Am așteptat pentru un prost ca tine să îmi aducă libertatea. Planeta la minusculă e a mea, și tu îți vei dori să nu te fii născut!","Ха-ха! Приветствую. Я так долго ждала! Я ждала, что идиот вроде тебя освободит меня. Эта крошечная планета моя, и сейчас ты пожалеешь, что родился на свет!",,Ha ha! Hoş geldiniz. Bu anı bekledim. Senin gibi bir aptalın bana özgürlüğümü getirmesini bekledim. Küçük gezegenin benim olacak ve sen hiç doğmamış olmayı dileyeceksin! +","하하, 이 순간만을 기다리고 있었노라. 그대와 같은 어리석은 자가 짐을 풀어줄 순간을. 그대의 조그만 행성은 이제 짐의 것이고, 그대는 태어난 것을 후회하게 될 것이니라!","Ha ha! Welkom. Ik heb op dit moment gewacht. Ik heb gewacht op een dwaas als jij om mij mijn vrijheid te brengen. Jouw kleine planeet is de mijne, en je zult wensen dat je nooit geboren was!","Ha ha! Velkommen. Jeg har ventet på dette øyeblikket. Jeg har ventet på dette øyeblikket. Jeg har ventet på at en tosk som deg skulle gi meg min frihet. Din lille planet er min, og du vil ønske at du aldri ble født!","Ha ha! Witam. Czekałem na tę chwilę. Czekałem, aż taki głupiec jak ty przyniesie mi wolność. Twoja mała planeta jest moja, a ty będziesz żałował, że się nie urodziłeś!",Ha ha! Bem-vindo. Eu esperei por este momento. Esperei por um tolo como você trazer a minha liberdade. O seu planeta insignificante é meu e você vai desejar nunca ter nascido!,,"Ha ha! Bun-venit. Am așteptat momentul. Am așteptat pentru un prost ca tine să îmi aducă libertatea. Planeta la minusculă e a mea, și tu îți vei dori să nu te fii născut!","Ха-ха! Приветствую. Я так долго ждала! Я ждала, что идиот вроде тебя освободит меня. Эта крошечная планета моя, и сейчас ты пожалеешь, что родился на свет!",,"Ha ha! Välkommen. Jag har väntat på det här ögonblicket. Jag har väntat på att en idiot som du ska ge mig min frihet. Din lilla planet är min, och du kommer att önska att du aldrig föddes!",Ha ha! Hoş geldiniz. Bu anı bekledim. Senin gibi bir aptalın bana özgürlüğümü getirmesini bekledim. Küçük gezegenin benim olacak ve sen hiç doğmamış olmayı dileyeceksin! "The truth can only be found in universal will. You will fall on your knees in front of the True God, the One Light. Join me and I will complete the Sigil. -I'm sick of this mystical double talk.",TXT_SUB_LOG129,STRIFE1.WAD: MAP27,,,"- Pravda může být nalezena jedině v přání jsoucna. Padneš na kolena před Pravým bohem, Jedním světlem. Připoj se ke mě a já složím Pečeť. +I'm sick of this mystical double talk.",TXT_SUB_LOG129,MAP27: Entrance (It talks the Loremaster and BlackBird).,,,"- Pravda může být nalezena jedině v přání jsoucna. Padneš na kolena před Pravým bohem, Jedním světlem. Připoj se ke mě a já složím Pečeť. - Tenhle tajemný dvojhlas už mi leze krkem.","Sandheden kan kun findes i den universelle vilje. Du vil falde på knæ foran den sande Gud, det ene lys. Slut dig til mig, og jeg vil fuldende sigilet. Jeg er træt af denne mystiske dobbelttale.","Die Warheit kann nur universell gefunden werden. Du wirst im Angesicht des Einen Gottes, des Einen Lichtes auf die Knie fallen. Folge mir und ich werde das Sigil komplettieren. Ich habe genug von diesem mystischen Rumgeschwafel.",,,"La verdad solo puede ser encontrada en la voluntad universal. Te arrodillarás en frente del Dios Único, la Luz Única. Únete a mi y completaré el Emblema. @@ -12215,113 +12822,115 @@ Ik ben deze mystieke dubbelzinnigheid beu.","Sannheten kan bare finnes i den uni Jeg er lei av denne mystiske dobbeltkommunikasjonen.","Prawda może być znaleziona tylko w powszechnej woli. Padniesz na kolana przed Prawdziwym Bogiem, Jedynym Światłem. Dołącz do mnie, a ja uzupełnię Sigil. Mam dość tego mistycznego gadania.","A verdade só pode ser encontrada na vontade universal. Você cairá de joelhos na frente do Deus Único, a Luz Única. Junte-se a mim e completarei o Sigilo. Já estou cansada de toda essa ladainha mística.",,"Adevărul poate fi găsit doar în voința universală. Vei cădea în genunchi în fața Adevăratului Zeu, Singura Lumină. Alătură-mi-te și voi completa Sigiliul. M-am săturat de vorbitul ăsta mistic duplicitar.","— Истина одна — она в единой воле. Ты упадёшь на колени пред Истинным Богом, единым светом. Присоединись ко мне, и я соберу Печать! -— Меня тошнит от этой таинственной двуличной болтовни!",,"Gerçek sadece evrensel iradede bulunabilir. Gerçek Tanrı'nın, Tek Işık'ın önünde diz çökeceksin. Bana katılın ve ben de Sigil'i tamamlayayım. +— Меня тошнит от этой таинственной двуличной болтовни!",,"Sanningen kan bara hittas i den universella viljan. Ni kommer att falla på knä framför den sanna guden, det enda ljuset. Gör mig sällskap och jag kommer att fullborda Sigillet. +Jag är trött på detta mystiska dubbelprat.","Gerçek sadece evrensel iradede bulunabilir. Gerçek Tanrı'nın, Tek Işık'ın önünde diz çökeceksin. Bana katılın ve ben de Sigil'i tamamlayayım. Bu mistik ikili konuşmalardan bıktım." -"You... You have crushed my Order, torn through my ruses and threatened centuries of desire. But I will prevail, I will infect you and twist you to my will...",TXT_SUB_LOG130,"STRIFE1.WAD: MAP29 - -(If the player is progressing through the good ending)",,,"Ty... Tys rozdrtil můj Řád, proskočil mými lstmi a ohrozil staletí chtíče. Ale já přetrvám. Já tě nakazím a zkazím, tak, jak chci...","Du... Du har knust min orden, revet mine kneb igennem og truet århundreders begær. Men jeg vil sejre, jeg vil inficere dig og dreje dig til min vilje...","Du... du hast meinen Orden zerstört, meine Fallen überwunden und jahrelange Wünsche gefährdet. Aber ich werde siegen, ich werde dich infizieren und dich meinem Willen beugen...",,,"Tú... Tú has aplastado mi Orden, destrozado mis engaños y amenazado siglos de deseo. Pero yo prevareceré, te infectaré y retorceré a mi voluntad...",,"Sinä... Sinä olet murskannut Veljeskuntani, tunkenut läpi ansojeni ja uhannut vuosisatoja palanutta halua. Mutta olen vielä voittava; tartutan sinut ja väännän sinut tahtooni...","Vous.. Vous avez anéanti mon Ordre, percé à travers le voile de mes ruses et menacé des siècle de désirs. Mais je gagnerai, je vous infecterai et vous plierai à ma volonté...","Te...Te voltál aki szétmorzsolta a Rendemet, letépted a trükkök palástyát, és évszázadok kívánatát borítottad fel. Akkor is győzedelmeskedni fogok, megferzőzlek és az akaratomnak megfelelően foglak torzítani...","Tu... hai schiacciato il mio Ordine, hai rovinato i miei piani e minacciato secoli di desideri. Ma io vincerò, ti infetterò e ti piegherò alla mia volontà...","キサマ...キサマハ我ガオーダーヲ破壊シニシタ、 +"You... You have crushed my Order, torn through my ruses and threatened centuries of desire. But I will prevail, I will infect you and twist you to my will...",TXT_SUB_LOG130,MAP29: Entity (If the player is progressing through the good ending),,,"Ty... Tys rozdrtil můj Řád, proskočil mými lstmi a ohrozil staletí chtíče. Ale já přetrvám. Já tě nakazím a zkazím, tak, jak chci...","Du... Du har knust min orden, revet mine kneb igennem og truet århundreders begær. Men jeg vil sejre, jeg vil inficere dig og dreje dig til min vilje...","Du... du hast meinen Orden zerstört, meine Fallen überwunden und jahrelange Wünsche gefährdet. Aber ich werde siegen, ich werde dich infizieren und dich meinem Willen beugen...",,,"Tú... Tú has aplastado mi Orden, destrozado mis engaños y amenazado siglos de deseo. Pero yo prevareceré, te infectaré y retorceré a mi voluntad...",,"Sinä... Sinä olet murskannut Veljeskuntani, tunkenut läpi ansojeni ja uhannut vuosisatoja palanutta halua. Mutta olen vielä voittava; tartutan sinut ja väännän sinut tahtooni...","Vous.. Vous avez anéanti mon Ordre, percé à travers le voile de mes ruses et menacé des siècle de désirs. Mais je gagnerai, je vous infecterai et vous plierai à ma volonté...","Te...Te voltál aki szétmorzsolta a Rendemet, letépted a trükkök palástyát, és évszázadok kívánatát borítottad fel. Akkor is győzedelmeskedni fogok, megferzőzlek és az akaratomnak megfelelően foglak torzítani...","Tu... hai schiacciato il mio Ordine, hai rovinato i miei piani e minacciato secoli di desideri. Ma io vincerò, ti infetterò e ti piegherò alla mia volontà...","キサマ...キサマハ我ガオーダーヲ破壊シニシタ、 我ノ詭謀ヲ截チ何世紀ニモワタル望ミヲ脅カシタ。 ダガマダ終ワリデハナイ、キサマニ憑キ意志ヲヒネリ出セバ... -","그대... 짐의 명령을 거부하고, 많은 것을 빼앗았고, 수 백 년 동안의 욕망을 위협했느니라. 그러나 짐은, 그대를 침식하여 짐의 의지에 복종하도록 만들 것이니라...","Jullie hebben mijn Orde verpletterd, door mijn listen heen gescheurd en eeuwen van verlangen bedreigd. Maar ik zal zegevieren, ik zal je besmetten en je naar mijn wil draaien....","Du... Du har knust min Orden, gjennomskuet mine knep og truet århundrer av begjær. Men jeg vil seire, jeg vil infisere deg og vri deg til min vilje...","Ty... Zmiażdżyłeś mój Zakon, przedarłeś się przez moje podstępy i zagroziłeś wiekom pożądania. Ale ja zwyciężę, zainfekuję cię i zmienię na swoją wolę...","Você... você destruiu a minha Ordem, destroçou meus truques e ameaçou séculos de desejo. Mas eu vou prevalecer. Infectarei você e vou manipulá-lo à minha vontade...",,"Tu... Tu mi-ai strivit Ordinul, și mi-ai amenințat secole de dorință. Dar voi învinge, te voi infecta și îți voi pervertii voința...","Ты... Ты разгромил мой Орден, прорвался через мои ловушки и сделал столетия ожидания напрасными. Но тебе не победить — я заражу тебя и подчиню своей воле!",,"Sen... Düzenimi yıktın, hilelerimi parçaladın ve yüzyıllardır süren arzularımı tehdit ettin. Ama ben galip geleceğim, sana bulaşacağım ve seni kendi isteğime dönüştüreceğim." -"Sounds like a dream job, doesn't it?",TXT_SUB_LOG200,,,,"Zní jako práce snů, ne?","Det lyder som et drømmejob, ikke sandt?","Hört sich wie ein Traumjob an, nicht wahr?",,,"Suena a un trabajo ideal, ¿no?",,Eikö kuulostakin unelmapestiltä?,"Le job de vos rêves, non?","Úgy tűnik mint egy álam meló, ugye?","Sembra un lavoro da sogno, no?",,바라던 일 같네. 그렇지 않아?,"Klinkt als een droombaan, nietwaar?","Høres ut som en drømmejobb, ikke sant?","Brzmi jak praca marzeń, prawda?","Parece ser o emprego ideal, não é mesmo?",,"Sună a vis, nu?","Звучит как работа мечты, не так ли?",,"Rüya gibi bir iş, değil mi?" -"You've seen too much. Ice him, Macil!",TXT_SUB_LOG201,,,,"Viděl jsi moc. Zab ho, Macile!","Du har set for meget. Islæg ham, Macil!","Du hast genug gesehen. Mach ihn kalt, Macil!",,,"Has visto demasiado. ¡Acaba con él, Macil!",,"Olet nähnyt liikaa. Murskaa hänet, Macil!","Vous en avez trop vu. Descend-le, Macil!",Túl sokat láttál. öld meg Macil!,"Hai visto troppo. Fallo fuori, Macil!",,"넌 많은 걸 봤어. 얼려버려, 마실!","Je hebt te veel gezien. Ijs hem, Macil!","Du har sett for mye. Legg ham på is, Macil!","Widziałeś już zbyt wiele. Lód, Macil!","Você já viu demais. Acaba com ele, Macil!",,"Ai văzut prea mult. Îngheață-l, Macil!","Ты слишком много видел. Заморозь его, Мэйсил!",,"Çok fazla şey gördün. Buzla onu, Macil!" +","그대... 짐의 명령을 거부하고, 많은 것을 빼앗았고, 수 백 년 동안의 욕망을 위협했느니라. 그러나 짐은, 그대를 침식하여 짐의 의지에 복종하도록 만들 것이니라...","Jullie hebben mijn Orde verpletterd, door mijn listen heen gescheurd en eeuwen van verlangen bedreigd. Maar ik zal zegevieren, ik zal je besmetten en je naar mijn wil draaien....","Du... Du har knust min Orden, gjennomskuet mine knep og truet århundrer av begjær. Men jeg vil seire, jeg vil infisere deg og vri deg til min vilje...","Ty... Zmiażdżyłeś mój Zakon, przedarłeś się przez moje podstępy i zagroziłeś wiekom pożądania. Ale ja zwyciężę, zainfekuję cię i zmienię na swoją wolę...","Você... você destruiu a minha Ordem, destroçou meus truques e ameaçou séculos de desejo. Mas eu vou prevalecer. Infectarei você e vou manipulá-lo à minha vontade...",,"Tu... Tu mi-ai strivit Ordinul, și mi-ai amenințat secole de dorință. Dar voi învinge, te voi infecta și îți voi pervertii voința...","Ты... Ты разгромил мой Орден, прорвался через мои ловушки и сделал столетия ожидания напрасными. Но тебе не победить — я заражу тебя и подчиню своей воле!",,"Du... Du har krossat min ordning, slitit igenom mina knep och hotat århundraden av begär. Men jag kommer att segra, jag kommer att infektera dig och vrida dig till min vilja...","Sen... Düzenimi yıktın, hilelerimi parçaladın ve yüzyıllardır süren arzularımı tehdit ettin. Ama ben galip geleceğim, sana bulaşacağım ve seni kendi isteğime dönüştüreceğim." +"Sounds like a dream job, doesn't it?",TXT_SUB_LOG200,,,,"Zní jako práce snů, ne?","Det lyder som et drømmejob, ikke sandt?","Hört sich wie ein Traumjob an, nicht wahr?",,,"Suena a un trabajo ideal, ¿no?",,Eikö kuulostakin unelmapestiltä?,"Le job de vos rêves, non?","Úgy tűnik mint egy álam meló, ugye?","Sembra un lavoro da sogno, no?",,바라던 일 같네. 그렇지 않아?,"Klinkt als een droombaan, nietwaar?","Høres ut som en drømmejobb, ikke sant?","Brzmi jak praca marzeń, prawda?","Parece ser o emprego ideal, não é mesmo?",,"Sună a vis, nu?","Звучит как работа мечты, не так ли?",,"Låter som ett drömjobb, eller hur?","Rüya gibi bir iş, değil mi?" +"You've seen too much. Ice him, Macil!",TXT_SUB_LOG201,,,,"Viděl jsi moc. Zab ho, Macile!","Du har set for meget. Islæg ham, Macil!","Du hast genug gesehen. Mach ihn kalt, Macil!",,,"Has visto demasiado. ¡Acaba con él, Macil!",,"Olet nähnyt liikaa. Murskaa hänet, Macil!","Vous en avez trop vu. Descend-le, Macil!",Túl sokat láttál. öld meg Macil!,"Hai visto troppo. Fallo fuori, Macil!",,"넌 많은 걸 봤어. 얼려버려, 마실!","Je hebt te veel gezien. Ijs hem, Macil!","Du har sett for mye. Legg ham på is, Macil!","Widziałeś już zbyt wiele. Lód, Macil!","Você já viu demais. Acaba com ele, Macil!",,"Ai văzut prea mult. Îngheață-l, Macil!","Ты слишком много видел. Заморозь его, Мэйсил!",,"Du har sett för mycket. Isa honom, Macil!","Çok fazla şey gördün. Buzla onu, Macil!" "Next time, you'll listen to me.",TXT_SUB_LOG202,"(Strife: Veteran Edition) -Random comment when the player dies with Classic Mode turned off",,,Příště budeš poslouchat mě.,Næste gang vil du lytte til mig.,Nächstes Mal hörst du auf mich.,,,"La próxima vez, me harás caso.",,Ensi kerralla saat luvan kuunnella minua.,"La prochaine fois, tu m'écouteras.",Majd legközelebb hallgatsz rám.,"La prossima volta, mi ascolterai.",今度は、私の言う事を聞きなさいよ。,"다음번엔, 내 말을 좀 들어. ",Volgende keer luister je naar me.,Neste gang hører du på meg.,Następnym razem mnie posłuchasz.,"Da próxima vez, você vai me ouvir.",,"Data viitoare, o să mă asculți.","Будешь знать, как меня не слушать.",,Bir dahaki sefere beni dinlersin. -"Ugh, these post-apocalyptic prices...",TXT_SUB_LOG203,,,,"Uf, tyhle postapokalyptické ceny...",Disse post-apokalyptiske priser...,"Ugh, diese postapokalyptischen Preise...",,,"Ugh, estos precios post-apocalípticos...",,"Ääh, näitä maailmanlopun jälkeisiä hintoja...","Eugh, ces prix post-apocalyptiques..","Fú, ezek az apokalipszis utáni árak...","Ugh, questi prezzi post-apocalittici...",,"으윽, 세기말 가격이네.","Ugh, deze post-apocalyptische prijzen....",Disse postapokalyptiske prisene...,"Ugh, te postapokaliptyczne ceny...","Urgh, esses preços pós-apocalípticos...",,"Ugh, prețurile ăstea post-apocaliptice...","Ух, эти цены после апокалипсиса...",,Bu kıyamet sonrası fiyatları. -Take the big one. He won't stop you.,TXT_SUB_LOG204,,,,Rozdej si to s tím velkým. Nezastaví tě.,Tag den store. Han vil ikke stoppe dig.,"Nimm das große, Er wird dich nicht stoppen.",,,Toma el grande. No te detendrá.,,Ota iso. Hän ei estä sinua.,"Prends le gros, il ne t'arrètera pas.",Vidd el a nagyot. Nem fog beléd kötni.,Prendi quello più grande. Non ti fermerà.,,커다란 놈을 막아. 둔하니까.,Neem de grote. Hij zal je niet tegenhouden.,Ta den store. Han vil ikke stoppe deg.,Weź dużą. Nie zatrzyma cię.,Leve o grandão. Ele não vai te deter.,,"Ia-l pe cel mare, nu te va opri.",Бери самую крупную. Он тебя не остановит.,,Büyük olanı al. Seni durdurmayacak. -Don't dawdle. Straight ahead!,TXT_SUB_LOG205,,,,Neloudej se. Jdi rovně!,Du skal ikke tøve. Lige fremad!,Trödel nicht rum. Direkt voraus!,,,No te pares. ¡Sigue adelante!,,Älä vitkastele. Suoraan eteenpäin!,"Ne traîne pas, tout devant!",Ne vesztegesd az időt. Csak egyenesen!,Non indulgiare. Vai avanti!,,꾸물거리지 말고 빨리 움직여야 해! ,Niet treuzelen. Rechtdoor!,Ikke somle. Rett fram!,Nie ociągaj się. Prosto przed siebie!,Não pare. Siga adiante!,,Nu te lenevi. Drept în față!,Не мешкай. Прямо вперёд!,,Oyalanma. Dümdüz ilerle! -You ever notice how these corridors look the same?,TXT_SUB_LOG206,,,,"Všimnul sis, jak všechny to chodby vypadají stejně?","Har du nogensinde lagt mærke til, at disse korridorer ser ens ud?","Ist dir schon mal aufgefallen, dass diese Flure alle gleich aussehen?",,,¿Alguna vez te has fijado en como estos pasillos parecen iguales?,,"Oletko koskaan huomannut, miten samanlaisilta nämä käyttävät näyttävät?",T'as pas l'impression que ces couloirs ont tous la même tête?,"Feltűnt, hogy minden folyosó ugyanúgy néz ki?",Ti sei mai accorto come tutti questi corridoi si assomiglino?,,갈 때마다 보이는 복도가 다 똑같다고 생각해본 적 있어? ,Heb je ooit gemerkt hoe deze gangen er hetzelfde uitzien?,Har du lagt merke til at korridorene ser like ut?,"Zauważyłeś, że te korytarze wyglądają tak samo?",Você já reparou como esses corredores parecem todos iguais?,,Nu observi cum coridoarele ăstea arată mereu la fel?,"Ты когда-нибудь замечал, что эти коридоры выглядят одинаково?",,Bu koridorların nasıl aynı göründüğünü hiç fark ettin mi? -"Hey, sometimes I have to guess too!",TXT_SUB_LOG207,,,,"Hej, já taky musím někdy hádat!",Nogle gange er jeg også nødt til at gætte!,"Hey, manchmal muss auch ich raten!",,,"¡Eh, a veces tambien tengo que adivinar!",,"Hei, joskus minunkin täytyy arvata!","Hé, il y a des fois où il faut aussi que je devine!",Nekem is néha találgatnom kell.,"Ehi, a volte anche io devo tirare a indovinare!",,"야, 어쩔 때는 나도 추측을 해본다고! ","Hé, soms moet ik ook raden!",Noen ganger må jeg også gjette!,"Hej, czasami ja też muszę zgadywać!","Ei, as vezes tenho que adivinhar também!",,"Hei, uneori și eu ghicesc!","Эй, иногда мне тоже приходится угадывать!",,"Hey, bazen ben de tahmin etmek zorunda kalıyorum!" -"Oh, and watch out for the alarm.",TXT_SUB_LOG208,,,,"Oh, a dávej pozor na alarm.","Åh, og pas på alarmen.","Oh, und achte auf den Alarm.",,,"Ah, y ten cuidado con la alarma.",,"Ja muuten, varo hälytystä.","Oh, et fais attention à l'alarme.","Ja, és vigyázz a riasztóval.","Oh, e fai attenzione all'allarme.",,"오, 그리고 경보를 조심해.","Oh, en kijk uit voor het alarm.",Se opp for alarmen.,"Aha, i uważaj na alarm.","Ah, e cuidado com o alarme.",,"Oh, și ai grijă la alarmă!",И остерегайся сигнализации.,,"Oh, ve alarma dikkat et." +Random comment when the player dies with Classic Mode turned off",,,Příště budeš poslouchat mě.,Næste gang vil du lytte til mig.,Nächstes Mal hörst du auf mich.,,,"La próxima vez, me harás caso.",,Ensi kerralla saat luvan kuunnella minua.,"La prochaine fois, tu m'écouteras.",Majd legközelebb hallgatsz rám.,"La prossima volta, mi ascolterai.",今度は、私の言う事を聞きなさいよ。,"다음번엔, 내 말을 좀 들어. ",Volgende keer luister je naar me.,Neste gang hører du på meg.,Następnym razem mnie posłuchasz.,"Da próxima vez, você vai me ouvir.",,"Data viitoare, o să mă asculți.","Будешь знать, как меня не слушать.",,Nästa gång lyssnar du på mig.,Bir dahaki sefere beni dinlersin. +"Ugh, these post-apocalyptic prices...",TXT_SUB_LOG203,,,,"Uf, tyhle postapokalyptické ceny...",Disse post-apokalyptiske priser...,"Ugh, diese postapokalyptischen Preise...",,,"Ugh, estos precios post-apocalípticos...",,"Ääh, näitä maailmanlopun jälkeisiä hintoja...","Eugh, ces prix post-apocalyptiques..","Fú, ezek az apokalipszis utáni árak...","Ugh, questi prezzi post-apocalittici...",,"으윽, 세기말 가격이네.","Ugh, deze post-apocalyptische prijzen....",Disse postapokalyptiske prisene...,"Ugh, te postapokaliptyczne ceny...","Urgh, esses preços pós-apocalípticos...",,"Ugh, prețurile ăstea post-apocaliptice...","Ух, эти цены после апокалипсиса...",,De här postapokalyptiska priserna...,Bu kıyamet sonrası fiyatları. +Take the big one. He won't stop you.,TXT_SUB_LOG204,,,,Rozdej si to s tím velkým. Nezastaví tě.,Tag den store. Han vil ikke stoppe dig.,"Nimm das große, Er wird dich nicht stoppen.",,,Toma el grande. No te detendrá.,,Ota iso. Hän ei estä sinua.,"Prends le gros, il ne t'arrètera pas.",Vidd el a nagyot. Nem fog beléd kötni.,Prendi quello più grande. Non ti fermerà.,,커다란 놈을 막아. 둔하니까.,Neem de grote. Hij zal je niet tegenhouden.,Ta den store. Han vil ikke stoppe deg.,Weź dużą. Nie zatrzyma cię.,Leve o grandão. Ele não vai te deter.,,"Ia-l pe cel mare, nu te va opri.",Бери самую крупную. Он тебя не остановит.,,Ta den stora. Han kommer inte att stoppa dig.,Büyük olanı al. Seni durdurmayacak. +Don't dawdle. Straight ahead!,TXT_SUB_LOG205,,,,Neloudej se. Jdi rovně!,Du skal ikke tøve. Lige fremad!,Trödel nicht rum. Direkt voraus!,,,No te pares. ¡Sigue adelante!,,Älä vitkastele. Suoraan eteenpäin!,"Ne traîne pas, tout devant!",Ne vesztegesd az időt. Csak egyenesen!,Non indulgiare. Vai avanti!,,꾸물거리지 말고 빨리 움직여야 해! ,Niet treuzelen. Rechtdoor!,Ikke somle. Rett fram!,Nie ociągaj się. Prosto przed siebie!,Não pare. Siga adiante!,,Nu te lenevi. Drept în față!,Не мешкай. Прямо вперёд!,,Tröna inte. Rakt fram!,Oyalanma. Dümdüz ilerle! +You ever notice how these corridors look the same?,TXT_SUB_LOG206,,,,"Všimnul sis, jak všechny to chodby vypadají stejně?","Har du nogensinde lagt mærke til, at disse korridorer ser ens ud?","Ist dir schon mal aufgefallen, dass diese Flure alle gleich aussehen?",,,¿Alguna vez te has fijado en como estos pasillos parecen iguales?,,"Oletko koskaan huomannut, miten samanlaisilta nämä käyttävät näyttävät?",T'as pas l'impression que ces couloirs ont tous la même tête?,"Feltűnt, hogy minden folyosó ugyanúgy néz ki?",Ti sei mai accorto come tutti questi corridoi si assomiglino?,,갈 때마다 보이는 복도가 다 똑같다고 생각해본 적 있어? ,Heb je ooit gemerkt hoe deze gangen er hetzelfde uitzien?,Har du lagt merke til at korridorene ser like ut?,"Zauważyłeś, że te korytarze wyglądają tak samo?",Você já reparou como esses corredores parecem todos iguais?,,Nu observi cum coridoarele ăstea arată mereu la fel?,"Ты когда-нибудь замечал, что эти коридоры выглядят одинаково?",,Har du någonsin lagt märke till att korridorerna ser likadana ut?,Bu koridorların nasıl aynı göründüğünü hiç fark ettin mi? +"Hey, sometimes I have to guess too!",TXT_SUB_LOG207,,,,"Hej, já taky musím někdy hádat!",Nogle gange er jeg også nødt til at gætte!,"Hey, manchmal muss auch ich raten!",,,"¡Eh, a veces tambien tengo que adivinar!",,"Hei, joskus minunkin täytyy arvata!","Hé, il y a des fois où il faut aussi que je devine!",Nekem is néha találgatnom kell.,"Ehi, a volte anche io devo tirare a indovinare!",,"야, 어쩔 때는 나도 추측을 해본다고! ","Hé, soms moet ik ook raden!",Noen ganger må jeg også gjette!,"Hej, czasami ja też muszę zgadywać!","Ei, as vezes tenho que adivinhar também!",,"Hei, uneori și eu ghicesc!","Эй, иногда мне тоже приходится угадывать!",,Ibland måste jag också gissa!,"Hey, bazen ben de tahmin etmek zorunda kalıyorum!" +"Oh, and watch out for the alarm.",TXT_SUB_LOG208,,,,"Oh, a dávej pozor na alarm.","Åh, og pas på alarmen.","Oh, und achte auf den Alarm.",,,"Ah, y ten cuidado con la alarma.",,"Ja muuten, varo hälytystä.","Oh, et fais attention à l'alarme.","Ja, és vigyázz a riasztóval.","Oh, e fai attenzione all'allarme.",,"오, 그리고 경보를 조심해.","Oh, en kijk uit voor het alarm.",Se opp for alarmen.,"Aha, i uważaj na alarm.","Ah, e cuidado com o alarme.",,"Oh, și ai grijă la alarmă!",И остерегайся сигнализации.,,"Åh, och se upp för larmet.","Oh, ve alarma dikkat et." "Oh, jeez. Now look what you've done!",TXT_SUB_LOG209,"(Strife: Veteran Edition) -Random comment when the player dies with Classic Mode turned off",,,"No sakra. Koukej, cos udělal!","Åh, for pokker. Se nu, hvad du har gjort!","Oh je. Sieh nur, was du getan hast.",,,Joder. ¡Mira lo que has hecho!,Dios. ¡Mira lo que hiciste!,"Voi hemmetti. Katso nyt, mitä olet tehnyt!","Oh, zut, regarde ce que tu as fait!","Jézusom, nézd mit műveltél!","Ah, dannazione. Guarda che cosa hai fatto!",ああ、そうね。今貴方の仕出かした事を見直しなさい。,"맙소사, 무슨 짓을 저질렀는지 알기나 해?","Oh, jeez. Kijk nu wat je hebt gedaan!","Å, jøss. Se hva du har gjort!","Oh, jeezu. Zobacz, co zrobiłeś!","Ai, caramba. Olha só o que você fez!",,"Oh, vai. Ia uite ce ai făcut.","Ну блин. Только посмотри, что ты наделал!",,"Oh, Tanrım. Bak ne yaptın!" +Random comment when the player dies with Classic Mode turned off",,,"No sakra. Koukej, cos udělal!","Åh, for pokker. Se nu, hvad du har gjort!","Oh je. Sieh nur, was du getan hast.",,,Joder. ¡Mira lo que has hecho!,Dios. ¡Mira lo que hiciste!,"Voi hemmetti. Katso nyt, mitä olet tehnyt!","Oh, zut, regarde ce que tu as fait!","Jézusom, nézd mit műveltél!","Ah, dannazione. Guarda che cosa hai fatto!",ああ、そうね。今貴方の仕出かした事を見直しなさい。,"맙소사, 무슨 짓을 저질렀는지 알기나 해?","Oh, jeez. Kijk nu wat je hebt gedaan!","Å, jøss. Se hva du har gjort!","Oh, jeezu. Zobacz, co zrobiłeś!","Ai, caramba. Olha só o que você fez!",,"Oh, vai. Ia uite ce ai făcut.","Ну блин. Только посмотри, что ты наделал!",,"Åh, herregud. Se vad du har gjort!","Oh, Tanrım. Bak ne yaptın!" Shit. Now you've blown it!,TXT_SUB_LOG210,"(Strife: Veteran Edition) -Random comment when the player dies with Classic Mode turned off",,,Do prdele. Teď jsi to podělal!,Pis. Nu har du ødelagt det!,"Mist, du hast es verbockt.",,,Mierda. ¡Ya la has liado!,Carajo. ¡Ya metiste la pata!,"Vittu, nyt meni ihan reisille!","Merde, t'as vraiment tout foutu en l'air!",Francba. Lebuktattál minket!,Merda. Ora hai davvero rovinato tutto!,クソが。アンタ今、台無しにしたぞ!,"제길, 다 망쳐 놓았네!",Shit. Nu heb je het verpest!,Pokker... Nå har du ødelagt det!,Cholera. Teraz to spieprzyłeś!,Merda. Agora você ferrou tudo!,,Rahat. Acum ai distrus totul!,"Чёрт, ты всё испортил!",,Kahretsin. Şimdi de sen mahvettin! -Come on! Let's get the hell out of here.,TXT_SUB_LOG211,MAP15: Computer destroyed + Room 1,,,No tak! Dostaňme se sakra odsud.,Kom nu! Lad os komme væk herfra.,Komm schon! Lass uns auf der Stelle von hier verschwinden.,,,¡Venga! Larguémonos de aquí.,¡Vamos! Vayámonos de aquí.,Mennään! Häivytään täältä hittoon.,Allez! Sortons d'ici!,Gyerünk húzzunk innen a francba!,Avanti! Andiamocene da qui!,頼むぞ!こっからとっとと失せろ!,빨리! 여길 어서 벗어나야 해!,Kom op! Laten we hier als de sodemieter weggaan.,Nå har du ødelagt det! Kom igjen! La oss komme oss til helvete ut herfra.,No dalej! Wynośmy się stąd.,Vem! Vamos vazar daqui.,,"Haide, să ieșim de aici.",Ну же! Двигаем отсюда!,,"Hadi, hadi! Buradan defolup gidelim." -Ooh. You don't mess around.,TXT_SUB_LOG212,,,,"Hmm, ty se nepáráš.",Ooh. Du laver ikke sjov.,Oh. Du lässt nichts anbrennen.,,,Ooh. No pierdes el tiempo.,,"Ooh, et turhia pelleile.","Oooh, tu n'y va pas de main morte.","Ajaj, látom nem tökölsz.",Ooh. Non sei uno che scherza.,,"오, 너 이 일에 정말 진지하구나?",Ooh. Je rotzooit niet.,Ooh. Du tuller ikke.,Ooh. Nie wygłupiaj się.,Oooh. Você não perde tempo mesmo.,,Ooh. Nu te joci.,Ооо. Ты знаешь своё дело.,,Ooh. Hiç oyalanmıyorsun. -You're going to mount them on the wall! Keep going!,TXT_SUB_LOG213,,,,Takhle je přišpendlíš ke zdi! Pokračuj a jdi dál!,Du skal montere dem på væggen! Fortsæt!,Willst du sie an der Wand anmontieren? Geh weiter!,,,¡Vas a montarlos en la pared! ¡Sigue!,,Ripustat heidät seinälle! Jatka vain!,Tu vas les clouer au mur! Continue!,Majd szépen kirakod a fejüket trófeának. Csak így tovább!,Li incollerai al muro! Continua così!,,저 녀석들을 모두 벽에 처박아놓자. 힘내! ,Je gaat ze aan de muur bevestigen! Ga door!,Du skal montere dem på veggen! Fortsett!,Zamierzasz je zamontować na ścianie! Dalej!,Você vai montá-los na parede! Continua!,,O să le pună pe zid! Continuă să mergi!,Тебе нужно закрепить их на стене! Продолжай в том же духе!,,Onları duvara monte edeceksin! Devam et! -Mm. You are a brute.,TXT_SUB_LOG214,,,,"Mhm, ty jsi ale surovec.",Mm. Du er en brutal mand.,Hm. Du bist aber ein Rohling.,,,Mm. Eres un bruto.,,"Mm, olet julma peto.","Mm, tu est une brute.",Hm. Egy állat vagy.,Mm. Sei un bruto.,,"음, 넌 괴물이야.",Mm. Je bent een bruut.,Mm. Du er et råskinn.,Mm. Jesteś brutalem.,"Hmm, seu brutamontes.",,Mm. Ești o brută.,Мм. Ты грубиян.,,Mm. Sen bir hayvansın. -Got a nice rhythm going here.,TXT_SUB_LOG215,,,,Máme tu teď hezký rytmus.,Du har en god rytme her.,Wir haben hier einen netten Rhythmus drauf.,,,Estás siguiendo un buen ritmo.,,Ehti kiva rytmi muodostua.,On a un bon rythme là.,Jó ütemben haladunk.,Siamo entrati in un bel ritmo qua.,,생각보다 박자가 잘 맞는데?,Ik heb hier een mooi ritme.,Har en fin rytme her.,Mamy tu ładny rytm.,Tá rolando um rítmo bom.,,Mișto ritm.,У тебя хороший ритм.,,Burada güzel bir ritim var. -Ooh. Love that boom-boom stick.,TXT_SUB_LOG216,,,,"Oh, pěkná brokáda.",Ooh. Jeg elsker den boom-boom-pind.,Ooh. Tolles Schießeisen.,,,Ooh. Me encanta.,,"Ooh, rakastan tuota tussaria.","Ooh, j'adore ce truc qui fait boum.","Áhh, imádom a söri-sörétest.",Ooh. Adoro quel fucile.,,저 빵야-빵야 막대기 너무나도 좋은걸? ,Ooh. Ik hou van die boom-boom stok.,Ooh. Elsker den boom-boom pinnen.,Ooh. Kocham ten boom-boom stick.,"Oooh, adoro.",,Ooh. Îmi place arma aceea nimicitoare.,О. Обожаю эту палку-взрывалку.,,Ooh. Bu bum-bum sopasını seviyorum. -Mm. I like the way you carry yourself.,TXT_SUB_LOG217,,,,"Mhm, líbí se mi, jak se neseš.","Jeg elsker denne boom-boom-boom. Jeg kan godt lide den måde, du bærer dig selv på.","Hm. Ich finde es toll, wie du dich präsentierst.",,,Mm. Me gusta como te lo montas.,,"Mm, pidän käytöksestäsi.","Mm, j'aime comment tu te porte.",Hm. Tetszik a magabiztosságod.,Mi piace il modo in cui ti comporti.,,너 스스로 챙기는 모습이 정말 보기 좋아. ,Mm. Ik hou van de manier waarop je jezelf draagt.,Mm. Jeg liker måten du bærer deg selv på.,"Mm. Lubię sposób, w jaki się nosisz.","Hmm, estou gostando de como você está indo.",,Ooh. Îmi place cum te descuri.,"Мм. Мне нравится, как ты ведёшь дело.",,Mm. Kendini taşıma şeklini seviyorum. -Blast away! They're not human!,TXT_SUB_LOG218,,,,Jen střílej! Nejsou to lidé!,Blast away! De er ikke menneskelige!,Mach sie alle! Das sind keine Menschen!,,,¡Reviéntalos! ¡No son humanos!,,Antaa palaa! Ne eivät ole ihmisiä!,"Eclate-les, ils ne sont pas humains!",Meghalsz! Nem is vagy ember!,Falli fuori! Non sono umani!,,날려버려! 저놈들은 인간이 아니야! ,Blast away! Ze zijn niet menselijk!,Skyt i vei! De er ikke mennesker!,Do dzieła! To nie są ludzie!,Arrebenta neles! Eles não são humanos!,,La naiba! Nu sunt umane!,Взрывай! Они не люди!,,Patlat! Onlar insan değil! +Random comment when the player dies with Classic Mode turned off",,,Do prdele. Teď jsi to podělal!,Pis. Nu har du ødelagt det!,"Mist, du hast es verbockt.",,,Mierda. ¡Ya la has liado!,Carajo. ¡Ya metiste la pata!,"Vittu, nyt meni ihan reisille!","Merde, t'as vraiment tout foutu en l'air!",Francba. Lebuktattál minket!,Merda. Ora hai davvero rovinato tutto!,クソが。アンタ今、台無しにしたぞ!,"제길, 다 망쳐 놓았네!",Shit. Nu heb je het verpest!,Pokker... Nå har du ødelagt det!,Cholera. Teraz to spieprzyłeś!,Merda. Agora você ferrou tudo!,,Rahat. Acum ai distrus totul!,"Чёрт, ты всё испортил!",,Fan också. Nu har du förstört det!,Kahretsin. Şimdi de sen mahvettin! +Come on! Let's get the hell out of here.,TXT_SUB_LOG211,MAP15: Computer destroyed + Room 1,,,No tak! Dostaňme se sakra odsud.,Kom nu! Lad os komme væk herfra.,Komm schon! Lass uns auf der Stelle von hier verschwinden.,,,¡Venga! Larguémonos de aquí.,¡Vamos! Vayámonos de aquí.,Mennään! Häivytään täältä hittoon.,Allez! Sortons d'ici!,Gyerünk húzzunk innen a francba!,Avanti! Andiamocene da qui!,頼むぞ!こっからとっとと失せろ!,빨리! 여길 어서 벗어나야 해!,Kom op! Laten we hier als de sodemieter weggaan.,Nå har du ødelagt det! Kom igjen! La oss komme oss til helvete ut herfra.,No dalej! Wynośmy się stąd.,Vem! Vamos vazar daqui.,,"Haide, să ieșim de aici.",Ну же! Двигаем отсюда!,,Kom igen! Nu sticker vi härifrån.,"Hadi, hadi! Buradan defolup gidelim." +Ooh. You don't mess around.,TXT_SUB_LOG212,,,,"Hmm, ty se nepáráš.",Ooh. Du laver ikke sjov.,Oh. Du lässt nichts anbrennen.,,,Ooh. No pierdes el tiempo.,,"Ooh, et turhia pelleile.","Oooh, tu n'y va pas de main morte.","Ajaj, látom nem tökölsz.",Ooh. Non sei uno che scherza.,,"오, 너 이 일에 정말 진지하구나?",Ooh. Je rotzooit niet.,Ooh. Du tuller ikke.,Ooh. Nie wygłupiaj się.,Oooh. Você não perde tempo mesmo.,,Ooh. Nu te joci.,Ооо. Ты знаешь своё дело.,,Ooh. Du är inte en sån jävel.,Ooh. Hiç oyalanmıyorsun. +You're going to mount them on the wall! Keep going!,TXT_SUB_LOG213,,,,Takhle je přišpendlíš ke zdi! Pokračuj a jdi dál!,Du skal montere dem på væggen! Fortsæt!,Willst du sie an der Wand anmontieren? Geh weiter!,,,¡Vas a montarlos en la pared! ¡Sigue!,,Ripustat heidät seinälle! Jatka vain!,Tu vas les clouer au mur! Continue!,Majd szépen kirakod a fejüket trófeának. Csak így tovább!,Li incollerai al muro! Continua così!,,저 녀석들을 모두 벽에 처박아놓자. 힘내! ,Je gaat ze aan de muur bevestigen! Ga door!,Du skal montere dem på veggen! Fortsett!,Zamierzasz je zamontować na ścianie! Dalej!,Você vai montá-los na parede! Continua!,,O să le pună pe zid! Continuă să mergi!,Тебе нужно закрепить их на стене! Продолжай в том же духе!,,Du ska montera dem på väggen! Fortsätt!,Onları duvara monte edeceksin! Devam et! +Mm. You are a brute.,TXT_SUB_LOG214,,,,"Mhm, ty jsi ale surovec.",Mm. Du er en brutal mand.,Hm. Du bist aber ein Rohling.,,,Mm. Eres un bruto.,,"Mm, olet julma peto.","Mm, tu est une brute.",Hm. Egy állat vagy.,Mm. Sei un bruto.,,"음, 넌 괴물이야.",Mm. Je bent een bruut.,Mm. Du er et råskinn.,Mm. Jesteś brutalem.,"Hmm, seu brutamontes.",,Mm. Ești o brută.,Мм. Ты грубиян.,,Mm. Du är ett vilddjur.,Mm. Sen bir hayvansın. +Got a nice rhythm going here.,TXT_SUB_LOG215,,,,Máme tu teď hezký rytmus.,Du har en god rytme her.,Wir haben hier einen netten Rhythmus drauf.,,,Estás siguiendo un buen ritmo.,,Ehti kiva rytmi muodostua.,On a un bon rythme là.,Jó ütemben haladunk.,Siamo entrati in un bel ritmo qua.,,생각보다 박자가 잘 맞는데?,Ik heb hier een mooi ritme.,Har en fin rytme her.,Mamy tu ładny rytm.,Tá rolando um rítmo bom.,,Mișto ritm.,У тебя хороший ритм.,,Du har en bra rytm.,Burada güzel bir ritim var. +Ooh. Love that boom-boom stick.,TXT_SUB_LOG216,,,,"Oh, pěkná brokáda.",Ooh. Jeg elsker den boom-boom-pind.,Ooh. Tolles Schießeisen.,,,Ooh. Me encanta.,,"Ooh, rakastan tuota tussaria.","Ooh, j'adore ce truc qui fait boum.","Áhh, imádom a söri-sörétest.",Ooh. Adoro quel fucile.,,저 빵야-빵야 막대기 너무나도 좋은걸? ,Ooh. Ik hou van die boom-boom stok.,Ooh. Elsker den boom-boom pinnen.,Ooh. Kocham ten boom-boom stick.,"Oooh, adoro.",,Ooh. Îmi place arma aceea nimicitoare.,О. Обожаю эту палку-взрывалку.,,Ooh. Jag älskar den där boom-boom-pinnen.,Ooh. Bu bum-bum sopasını seviyorum. +Mm. I like the way you carry yourself.,TXT_SUB_LOG217,,,,"Mhm, líbí se mi, jak se neseš.","Jeg elsker denne boom-boom-boom. Jeg kan godt lide den måde, du bærer dig selv på.","Hm. Ich finde es toll, wie du dich präsentierst.",,,Mm. Me gusta como te lo montas.,,"Mm, pidän käytöksestäsi.","Mm, j'aime comment tu te porte.",Hm. Tetszik a magabiztosságod.,Mi piace il modo in cui ti comporti.,,너 스스로 챙기는 모습이 정말 보기 좋아. ,Mm. Ik hou van de manier waarop je jezelf draagt.,Mm. Jeg liker måten du bærer deg selv på.,"Mm. Lubię sposób, w jaki się nosisz.","Hmm, estou gostando de como você está indo.",,Ooh. Îmi place cum te descuri.,"Мм. Мне нравится, как ты ведёшь дело.",,Jag gillar den här bommen. Jag gillar ditt sätt att bära dig själv.,Mm. Kendini taşıma şeklini seviyorum. +Blast away! They're not human!,TXT_SUB_LOG218,,,,Jen střílej! Nejsou to lidé!,Blast away! De er ikke menneskelige!,Mach sie alle! Das sind keine Menschen!,,,¡Reviéntalos! ¡No son humanos!,,Antaa palaa! Ne eivät ole ihmisiä!,"Eclate-les, ils ne sont pas humains!",Meghalsz! Nem is vagy ember!,Falli fuori! Non sono umani!,,날려버려! 저놈들은 인간이 아니야! ,Blast away! Ze zijn niet menselijk!,Skyt i vei! De er ikke mennesker!,Do dzieła! To nie są ludzie!,Arrebenta neles! Eles não são humanos!,,La naiba! Nu sunt umane!,Взрывай! Они не люди!,,Blast away! De är inte mänskliga!,Patlat! Onlar insan değil! Wow! Blackened Acolyte! The new taste sensation...,TXT_SUB_LOG219,"(Strife: Veteran Edition) -When obtaining the “Spontaneous Combustion” achievement",,,Wow! Zčernalý akolyta! Nové kulinářské šílenství...,Wow! Sorte Acolyt! Den nye smagsoplevelse...,Wow! Geschmorter Ministrant! Neue Geschmackssensation...,,,¡Guau! ¡Acólito ennegrecido! La nueva sensación de sabor...,,Vau! Mustaa akoluuttia! Uutuusmakuelämys!,Wow! Acolyte noirci! Goûte à la nouvelle saveur sensationelle!,Wow! Pörkölt ministráns! A szezon új íze...,Wow! Accolito scuro! Il nuovo sensazionale sapore!,うぉう!黒ずんだアコライト!新しい趣味に目覚めそうだわ...,숯 빛깔 아콜라이트라! 맛과 감각을 잘 살렸는데? ,Wow! Zwarte acoliet! De nieuwe smaaksensatie....,Jøss! Svertet akolytt! Den nye smakssensasjonen...,Wow! Czarnoskóry akolita! Nowe doznanie smakowe...,Uau! Acólito assado! Uma nova sensação de sabor...,,"Wow, Acolit Înegrit! Noua senzație...","Ух ты, обугленный служитель! Совсем другое ощущение...",,Vay canına! Karartılmış yardımcı! Yeni tat hissi... -Keep doing that and you'll go blind... but I like it.,TXT_SUB_LOG220,,,,Pokračuj s tím a oslepneš... ale líbí se mi to.,"Bliv ved med det, og du bliver blind... men jeg kan lide det.",Mach so weiter und du wirst blind... aber ich finde es toll.,,,Sigue haciendo eso y te quedarás ciego... pero me gusta.,,Jatka tuota samaan malliin ja sokeudut... mutta pidän siitä.,Continue et tu vas te rendre aveugle.. j'aime bien par contre.,Ha tovább csinálod megvakulsz...mondjuk bejön.,Se continui così diventerai cieco... ma a me piace.,,이 걸 하다보면 네 눈이 좀 멀겠지만... 아찔하고 재밌는 것 같아.,Blijf dat doen en je wordt blind.... maar ik vind het leuk.,"Fortsett med det, og du blir blind... men jeg liker det.","Rób tak dalej, a oślepniesz... ale mi się podoba.",Continua fazendo isso e você ficará cego... mas eu gosto.,,Continuă să faci asta și o să orbești... dar îmi place.,Продолжай в том же духе и ты ослепнешь... но мне это нравится.,,Bunu yapmaya devam edersen kör olacaksın... ama hoşuma gitti. -Guess they won't be inviting us back to dinner!,TXT_SUB_LOG221,,,,"Hádám, že tihle nás už na večeři zvát nebudou!","Jeg tror ikke, de inviterer os tilbage til middag!","Ich glaube nicht, dass sie uns nochmal einladen werden...",,,¡Supongo que no nos invitarán a cenar!,,Eivät varmaankaan kutsu meitä takaisin illalliselle!,Je pense qu'ils ne vont pas nous inviter à diner!,Szerintem nem hívnak vissza vacsorára.,Mi sa che non ci riinviteranno per cena!,,보답으로 저녁에 초대하지 않을 것 같아서 아쉽네! ,Ik denk dat ze ons niet meer zullen uitnodigen om terug te komen eten!,Antar de ikke vil invitere oss på middag igjen!,Chyba nie zaproszą nas z powrotem na kolację!,Acho que não vão nos convidar para jantar!,,Cred că n-o să ne invite la cină!,"Думаю, они не пригласят нас на ужин!",,Sanırım bizi tekrar yemeğe davet etmeyecekler! -We need to get to the top floor.,TXT_SUB_LOG222,,,,Musíme se dostat na vrchní podlaží.,Vi må op på øverste etage.,Wir müssen in die oberste Etage gelangen.,,,Necesitamos llegar a la planta más alta.,,Meidän tarvitsee päästä ylimmälle kerrokselle.,Il faut que l'on aille au dernier étage.,Fel kell jutnunk a legfelső szintre.,Dobbiamo andare al piano di sopra.,,최상층으로 올라가야 해. ,We moeten naar de bovenste verdieping.,Vi må komme oss til øverste etasje.,Musimy dostać się na ostatnie piętro.,Precisamos chegar até o último andar.,,Trebuie să ajungem la ultimul etaj.,Нам нужно попасть на верхний этаж.,,En üst kata çıkmalıyız. -Wait... This looks interesting. Check it out.,TXT_SUB_LOG223,,,,Počkej... Tohle vypadá zajímavě. Pojďme to omrknout.,Vent... Det her ser interessant ud. Tjek det ud.,Warte... Das sieht interessant aus. Sieh mal nach.,,,Espera... Esto parece interesante. Échale un vistazo.,,Odota... Tämä näyttää mielenkiintoiselta. Vilkaisepa.,"Attends.. Ca à l'air intéressant, va voir.",Várjunk csak... érdekesen néz ki. Nézd csak meg.,Aspetta... Questo sembra interessante. Guarda qua.,,잠깐... 저거 뭔가 흥미로워. 확인해보자.,Wacht..... Dit ziet er interessant uit. Kijk maar eens.,Vent litt... Dette ser interessant ut. Sjekk det ut.,Czekaj... To wygląda ciekawie. Sprawdźcie to.,Peraí.... Isso parece interessante. Dá só uma olhada.,,"Stai, asta pare interesant. Ia uite.",Подожди... Выглядит интересно. Проверь.,,Bekle. Bu ilginç görünüyor. Şuna bir bak. -Ugh. That guy gives me the creeps. Let's steer clear.,TXT_SUB_LOG224,,,,"Brr, z toho chlápka mi mrazí v zádech. Radši se mu vyhněme.",Ugh. Den fyr giver mig myrekryb. Lad os holde os væk.,Ugh. da kriegt man ja 'ne Gänsehaut. ,,,Ugh. Ese tipo me da mala espina. Alejémonos.,,"Yöh, onpa puistattava kaveri. Pysytään loitolla.","Eugh, ce type me fout les jetons. Evite le.",Rámjön a frász attól az ürgétől. Húzzunk innen.,Ugh. Quel tizio mi fa venire la pelle d'oca. Stiamogli alla larga.,,"윽, 정말 혐오스러운 녀석들. 청소할 준비를 하자.",Ugh. Die kerel geeft me de kriebels. Laten we wegblijven.,Æsj. Den fyren gir meg frysninger. La oss holde oss unna.,Ugh. Ten facet przyprawia mnie o dreszcze. Odsuńmy się od niego.,Urgh. Esse cara me dá arrepios. Vamos passar longe.,,Ugh. Tipul ăla mă sperie.,Ух. У меня от этого парня мурашки по коже. Давай держаться от него подальше.,,Ugh. Bu adam beni ürpertiyor. Uzak duralım. -"Left! Turn left!... Oh, other left!",TXT_SUB_LOG225,,,,"Doleva! Jdi doleva...! Aha, další doleva!","Til venstre! Drej til venstre!... Åh, anden venstre!",Links! Geh nach links... Zur anderen Seite - links!,,,"¡Izquierda! ¡Gira a la izquierda!... Oh, ¡la otra izquierda!",,"Vasemmalle! Käänny vasemmalle! Aa, toinen vasen!",Gauche! A Gauche... L'autre gauche!,"Balra! Fordulj balra!... Áh, a másik balra!","Sinistra! Vai a sinistra!... Oh, l'altra sinistra!",,"왼쪽! 왼쪽으로 이동해!... 잠깐, 다른 왼쪽!","Links! Sla linksaf!...... Oh, andere links!","Til venstre! Sving til venstre!... Å, andre venstre!","W lewo! Skręć w lewo!... Och, inna lewa!","Esquerda! Vira à esquerda!... Ai, a outra esquerda!",,"Stânga! Stânga!... Oh, cealaltă stânga!","Налево! Поверни налево!... Ой, другое лево!",,"Sola dön! Sola dön!... Oh, diğer sol!" -Typical stubborn pig-headed male!... Unless you're a girl.,TXT_SUB_LOG226,,,,"Typický, tvrdohlavý, paličatý muž! ...Leda že bys byla holka.","Typisk stædig, stædig mand!... Medmindre du er en pige.",Typischer sturer Mann... Sofern du kein Mädchen bist.,,,Típico hombre cabezotan con cara de cerdo!... A menos que seas chica.,,Tyypillinen itsepäinen uppiniskainen mies! Ellet sitten ole tyttö.,"Typique d'un mec borné comme un porc- Sauf si tu est une fille, bien entendu.",Tipikus csökönyös férfi!... Kivétel ha nő vagy.,Tipico testardo maschio dalla testa di maiale!... A meno che tu non sia una ragazza.,,"뻔뻔한 고집불통 남충 놈!... 걱정 마, 너 말고.",Typisch koppig koppig mannetje!...... Tenzij je een meisje bent.,Typisk sta og sta mann!.... Med mindre du er en jente.,"Typowy uparty świniopas!... Chyba, że jesteś dziewczyną.",Típico macho teimoso com cara de porco!... A não ser que você seja menina.,,Bărbat încăpățânat tipic... Asta dacă nu ești femeie.,Типичный упрямый свинопас!... Если только ты не девушка.,,Tipik inatçı domuz kafalı erkek!... Tabii kız değilsen. -"Strong, brutal and silent. My kind of partner.",TXT_SUB_LOG227,,,,"Silný, hrubý a tichý. Přesně můj typ.","Stærk, brutal og tavs. Min type partner.","Stark, brutal und leise. Mein Typ von Partner.",,,"Fuerte, brutal y callado. Mi tipo de compañero.",,"Vahva, raaka ja hiljainen. Mieleiseni kumppani.","Fort, brutal et silencieux. Mon type préféré.","Erős , brutális és csendes. Nekem való partner.","Forte, brutale e silenzioso. Il mio tipo di partner.",,"크고, 아름답고, 과묵하네. 같이 있고 싶은 타입이야.","Sterk, wreed en stil. Mijn soort partner.","Sterk, brutal og stille. Min type partner.","Silny, brutalny i milczący. Mój typ partnera.","Forte, bruto e silencioso. Meu tipo de parceiro.",,"Puternic, brutal și silențios. Genul meu de partener.","Сильный, брутальный и молчаливый. Мой типаж.",,"Güçlü, acımasız ve sessiz. Tam bana göre bir partner." -Okay! I was wrong!,TXT_SUB_LOG228,,,,Dobře! Mýlila jsem se!,Okay! Jeg tog fejl!,"Ok, ich habe mich geirrt.",,,¡OK! ¡Estaba equivocada!,,"Okei, olin väärässä!","Ok, j'avais tort!",Jólvan na! Tévedtem!,Okay! Mi sbagliavo!,,아마도 아니었던 것 같네! ,Oké! Ik had het mis!,Okay! Jeg tok feil!,Dobra! Myliłem się!,Ok! Eu estava errada!,,Bine! Am greșit!,Хорошо! Я была неправа!,,"Tamam, tamam! Yanılmışım!" +When obtaining the “Spontaneous Combustion” achievement",,,Wow! Zčernalý akolyta! Nové kulinářské šílenství...,Wow! Sorte Acolyt! Den nye smagsoplevelse...,Wow! Geschmorter Ministrant! Neue Geschmackssensation...,,,¡Guau! ¡Acólito ennegrecido! La nueva sensación de sabor...,,Vau! Mustaa akoluuttia! Uutuusmakuelämys!,Wow! Acolyte noirci! Goûte à la nouvelle saveur sensationelle!,Wow! Pörkölt ministráns! A szezon új íze...,Wow! Accolito scuro! Il nuovo sensazionale sapore!,うぉう!黒ずんだアコライト!新しい趣味に目覚めそうだわ...,숯 빛깔 아콜라이트라! 맛과 감각을 잘 살렸는데? ,Wow! Zwarte acoliet! De nieuwe smaaksensatie....,Jøss! Svertet akolytt! Den nye smakssensasjonen...,Wow! Czarnoskóry akolita! Nowe doznanie smakowe...,Uau! Acólito assado! Uma nova sensação de sabor...,,"Wow, Acolit Înegrit! Noua senzație...","Ух ты, обугленный служитель! Совсем другое ощущение...",,Wow! Svartklädd akolyt! Den nya smaksensationen...,Vay canına! Karartılmış yardımcı! Yeni tat hissi... +Keep doing that and you'll go blind... but I like it.,TXT_SUB_LOG220,,,,Pokračuj s tím a oslepneš... ale líbí se mi to.,"Bliv ved med det, og du bliver blind... men jeg kan lide det.",Mach so weiter und du wirst blind... aber ich finde es toll.,,,Sigue haciendo eso y te quedarás ciego... pero me gusta.,,Jatka tuota samaan malliin ja sokeudut... mutta pidän siitä.,Continue et tu vas te rendre aveugle.. j'aime bien par contre.,Ha tovább csinálod megvakulsz...mondjuk bejön.,Se continui così diventerai cieco... ma a me piace.,,이 걸 하다보면 네 눈이 좀 멀겠지만... 아찔하고 재밌는 것 같아.,Blijf dat doen en je wordt blind.... maar ik vind het leuk.,"Fortsett med det, og du blir blind... men jeg liker det.","Rób tak dalej, a oślepniesz... ale mi się podoba.",Continua fazendo isso e você ficará cego... mas eu gosto.,,Continuă să faci asta și o să orbești... dar îmi place.,Продолжай в том же духе и ты ослепнешь... но мне это нравится.,,Fortsätt med det där och du blir blind... men jag gillar det.,Bunu yapmaya devam edersen kör olacaksın... ama hoşuma gitti. +Guess they won't be inviting us back to dinner!,TXT_SUB_LOG221,,,,"Hádám, že tihle nás už na večeři zvát nebudou!","Jeg tror ikke, de inviterer os tilbage til middag!","Ich glaube nicht, dass sie uns nochmal einladen werden...",,,¡Supongo que no nos invitarán a cenar!,,Eivät varmaankaan kutsu meitä takaisin illalliselle!,Je pense qu'ils ne vont pas nous inviter à diner!,Szerintem nem hívnak vissza vacsorára.,Mi sa che non ci riinviteranno per cena!,,보답으로 저녁에 초대하지 않을 것 같아서 아쉽네! ,Ik denk dat ze ons niet meer zullen uitnodigen om terug te komen eten!,Antar de ikke vil invitere oss på middag igjen!,Chyba nie zaproszą nas z powrotem na kolację!,Acho que não vão nos convidar para jantar!,,Cred că n-o să ne invite la cină!,"Думаю, они не пригласят нас на ужин!",,Jag antar att de inte kommer att bjuda oss på middag igen!,Sanırım bizi tekrar yemeğe davet etmeyecekler! +We need to get to the top floor.,TXT_SUB_LOG222,,,,Musíme se dostat na vrchní podlaží.,Vi må op på øverste etage.,Wir müssen in die oberste Etage gelangen.,,,Necesitamos llegar a la planta más alta.,,Meidän tarvitsee päästä ylimmälle kerrokselle.,Il faut que l'on aille au dernier étage.,Fel kell jutnunk a legfelső szintre.,Dobbiamo andare al piano di sopra.,,최상층으로 올라가야 해. ,We moeten naar de bovenste verdieping.,Vi må komme oss til øverste etasje.,Musimy dostać się na ostatnie piętro.,Precisamos chegar até o último andar.,,Trebuie să ajungem la ultimul etaj.,Нам нужно попасть на верхний этаж.,,Vi måste ta oss till översta våningen.,En üst kata çıkmalıyız. +Wait... This looks interesting. Check it out.,TXT_SUB_LOG223,,,,Počkej... Tohle vypadá zajímavě. Pojďme to omrknout.,Vent... Det her ser interessant ud. Tjek det ud.,Warte... Das sieht interessant aus. Sieh mal nach.,,,Espera... Esto parece interesante. Échale un vistazo.,,Odota... Tämä näyttää mielenkiintoiselta. Vilkaisepa.,"Attends.. Ca à l'air intéressant, va voir.",Várjunk csak... érdekesen néz ki. Nézd csak meg.,Aspetta... Questo sembra interessante. Guarda qua.,,잠깐... 저거 뭔가 흥미로워. 확인해보자.,Wacht..... Dit ziet er interessant uit. Kijk maar eens.,Vent litt... Dette ser interessant ut. Sjekk det ut.,Czekaj... To wygląda ciekawie. Sprawdźcie to.,Peraí.... Isso parece interessante. Dá só uma olhada.,,"Stai, asta pare interesant. Ia uite.",Подожди... Выглядит интересно. Проверь.,,Vänta lite... Det här ser intressant ut. Kolla in det.,Bekle. Bu ilginç görünüyor. Şuna bir bak. +Ugh. That guy gives me the creeps. Let's steer clear.,TXT_SUB_LOG224,,,,"Brr, z toho chlápka mi mrazí v zádech. Radši se mu vyhněme.",Ugh. Den fyr giver mig myrekryb. Lad os holde os væk.,Ugh. da kriegt man ja 'ne Gänsehaut. ,,,Ugh. Ese tipo me da mala espina. Alejémonos.,,"Yöh, onpa puistattava kaveri. Pysytään loitolla.","Eugh, ce type me fout les jetons. Evite le.",Rámjön a frász attól az ürgétől. Húzzunk innen.,Ugh. Quel tizio mi fa venire la pelle d'oca. Stiamogli alla larga.,,"윽, 정말 혐오스러운 녀석들. 청소할 준비를 하자.",Ugh. Die kerel geeft me de kriebels. Laten we wegblijven.,Æsj. Den fyren gir meg frysninger. La oss holde oss unna.,Ugh. Ten facet przyprawia mnie o dreszcze. Odsuńmy się od niego.,Urgh. Esse cara me dá arrepios. Vamos passar longe.,,Ugh. Tipul ăla mă sperie.,Ух. У меня от этого парня мурашки по коже. Давай держаться от него подальше.,,Usch. Den killen ger mig kalla kårar. Vi håller oss undan.,Ugh. Bu adam beni ürpertiyor. Uzak duralım. +"Left! Turn left!... Oh, other left!",TXT_SUB_LOG225,,,,"Doleva! Jdi doleva...! Aha, další doleva!","Til venstre! Drej til venstre!... Åh, anden venstre!",Links! Geh nach links... Zur anderen Seite - links!,,,"¡Izquierda! ¡Gira a la izquierda!... Oh, ¡la otra izquierda!",,"Vasemmalle! Käänny vasemmalle! Aa, toinen vasen!",Gauche! A Gauche... L'autre gauche!,"Balra! Fordulj balra!... Áh, a másik balra!","Sinistra! Vai a sinistra!... Oh, l'altra sinistra!",,"왼쪽! 왼쪽으로 이동해!... 잠깐, 다른 왼쪽!","Links! Sla linksaf!...... Oh, andere links!","Til venstre! Sving til venstre!... Å, andre venstre!","W lewo! Skręć w lewo!... Och, inna lewa!","Esquerda! Vira à esquerda!... Ai, a outra esquerda!",,"Stânga! Stânga!... Oh, cealaltă stânga!","Налево! Поверни налево!... Ой, другое лево!",,"Vänster! Sväng vänster!... Åh, en annan vänster!","Sola dön! Sola dön!... Oh, diğer sol!" +Typical stubborn pig-headed male!... Unless you're a girl.,TXT_SUB_LOG226,,,,"Typický, tvrdohlavý, paličatý muž! ...Leda že bys byla holka.","Typisk stædig, stædig mand!... Medmindre du er en pige.",Typischer sturer Mann... Sofern du kein Mädchen bist.,,,Típico hombre cabezotan con cara de cerdo!... A menos que seas chica.,,Tyypillinen itsepäinen uppiniskainen mies! Ellet sitten ole tyttö.,"Typique d'un mec borné comme un porc- Sauf si tu est une fille, bien entendu.",Tipikus csökönyös férfi!... Kivétel ha nő vagy.,Tipico testardo maschio dalla testa di maiale!... A meno che tu non sia una ragazza.,,"뻔뻔한 고집불통 남충 놈!... 걱정 마, 너 말고.",Typisch koppig koppig mannetje!...... Tenzij je een meisje bent.,Typisk sta og sta mann!.... Med mindre du er en jente.,"Typowy uparty świniopas!... Chyba, że jesteś dziewczyną.",Típico macho teimoso com cara de porco!... A não ser que você seja menina.,,Bărbat încăpățânat tipic... Asta dacă nu ești femeie.,Типичный упрямый свинопас!... Если только ты не девушка.,,Typiskt en envis svinhuvudman!... Om du inte är en tjej.,Tipik inatçı domuz kafalı erkek!... Tabii kız değilsen. +"Strong, brutal and silent. My kind of partner.",TXT_SUB_LOG227,,,,"Silný, hrubý a tichý. Přesně můj typ.","Stærk, brutal og tavs. Min type partner.","Stark, brutal und leise. Mein Typ von Partner.",,,"Fuerte, brutal y callado. Mi tipo de compañero.",,"Vahva, raaka ja hiljainen. Mieleiseni kumppani.","Fort, brutal et silencieux. Mon type préféré.","Erős , brutális és csendes. Nekem való partner.","Forte, brutale e silenzioso. Il mio tipo di partner.",,"크고, 아름답고, 과묵하네. 같이 있고 싶은 타입이야.","Sterk, wreed en stil. Mijn soort partner.","Sterk, brutal og stille. Min type partner.","Silny, brutalny i milczący. Mój typ partnera.","Forte, bruto e silencioso. Meu tipo de parceiro.",,"Puternic, brutal și silențios. Genul meu de partener.","Сильный, брутальный и молчаливый. Мой типаж.",,"Stark, brutal och tyst. Min typ av partner.","Güçlü, acımasız ve sessiz. Tam bana göre bir partner." +Okay! I was wrong!,TXT_SUB_LOG228,,,,Dobře! Mýlila jsem se!,Okay! Jeg tog fejl!,"Ok, ich habe mich geirrt.",,,¡OK! ¡Estaba equivocada!,,"Okei, olin väärässä!","Ok, j'avais tort!",Jólvan na! Tévedtem!,Okay! Mi sbagliavo!,,아마도 아니었던 것 같네! ,Oké! Ik had het mis!,Okay! Jeg tok feil!,Dobra! Myliłem się!,Ok! Eu estava errada!,,Bine! Am greșit!,Хорошо! Я была неправа!,,Okej! Jag hade fel!,"Tamam, tamam! Yanılmışım!" Too bad we never met... face-to-face.,TXT_SUB_LOG229,"(Strife: Veteran Edition) -Random comment when the player dies with Classic Mode turned off",,,"Škoda, že jsme se nikdy nepotkali... tváří v tvář.",Ærgerligt at vi aldrig mødtes... ansigt til ansigt.,"Schade, dass wir uns noch nie begegnet sind...",,,Una pena que nunca nos conocieramos... cara a cara.,,"Sääli, ettemme koskaan tavanneet... kasvokkain.",C'est dommage qu'on s'est jamais rencontré.. En face à face.,"Kár, hogy sohasem találkoztunk... szemtől szembe.",Peccato che non ci siamo mai incontrati... faccia a faccia.,私達はもう会えなくなったわ...面と向かって。,만나지 못한 게 유감스럽네... 가까이서. ,Jammer dat we elkaar nooit ontmoet hebben..... persoonlijk.,Synd vi aldri møttes... ansikt til ansikt.,"Szkoda, że nigdy nie spotkaliśmy się... twarzą w twarz.",Pena que nunca nos encontramos... cara a cara.,,Păcat că nu ne-am întâlnit... față în față.,"Жаль, мы раньше не встречались... лицом к лицу.",,Hiç tanışmamış olmamız çok kötü... yüz yüze. +Random comment when the player dies with Classic Mode turned off",,,"Škoda, že jsme se nikdy nepotkali... tváří v tvář.",Ærgerligt at vi aldrig mødtes... ansigt til ansigt.,"Schade, dass wir uns noch nie begegnet sind...",,,Una pena que nunca nos conocieramos... cara a cara.,,"Sääli, ettemme koskaan tavanneet... kasvokkain.",C'est dommage qu'on s'est jamais rencontré.. En face à face.,"Kár, hogy sohasem találkoztunk... szemtől szembe.",Peccato che non ci siamo mai incontrati... faccia a faccia.,私達はもう会えなくなったわ...面と向かって。,만나지 못한 게 유감스럽네... 가까이서. ,Jammer dat we elkaar nooit ontmoet hebben..... persoonlijk.,Synd vi aldri møttes... ansikt til ansikt.,"Szkoda, że nigdy nie spotkaliśmy się... twarzą w twarz.",Pena que nunca nos encontramos... cara a cara.,,Păcat că nu ne-am întâlnit... față în față.,"Жаль, мы раньше не встречались... лицом к лицу.",,Synd att vi aldrig träffades... ansikte mot ansikte.,Hiç tanışmamış olmamız çok kötü... yüz yüze. I had dreams for you... Tough shit.,TXT_SUB_LOG230,"(Strife: Veteran Edition) -Random comment when the player dies with Classic Mode turned off",,,Snila jsem o tobě... Kurva.,Jeg havde drømme om dig... Det er sgu hårdt.,Ich hatte Träume für dich. Scheiße.,,,Tenía sueños para ti... Lástima.,,Elättelin toiveita sinusta... Paska mäihä.,J'avais des grands rêves pour toi.. Franchement dommage.,Álmodtam számodra valamit... Szar ügy.,Ho fatto sogni per te... Che peccato.,私は貴方に希望を抱いていた...クソ世知辛いわ。,너를 꿈꿔왔어... 꿈은 꿈이였나봐.,Ik had dromen voor je.... Moeilijke shit.,Jeg hadde drømmer for deg... Synd for deg.,Miałem dla ciebie marzenia... Twarde gówno.,Eu tinha uma grande expectativa sobre você... Que merda.,,Aveam visuri pentru tine... Rahatule...,Я так надеялся на тебя... Упрямый засранец.,,Senin için hayallerim vardı. Zor iş. -"No. Don't enter the town hall. It's not safe anymore. Our cover's been blown. That's why it's raining heavy metal. Kill as many of those big boys as you can. They're called ""Crusaders"". When you're done, I'll guide you to Macil.",TXT_SUB_LOG231,,,,"Ne. Nechoď do radnice, už není bezpečná. Byli jsme odhaleni, proto nám prší olovo na hlavu. Zabij kolik těch velkých kluků můžeš. Říká se jim Křižáci. Když jsi hotový, nasměruju tě k Macilovi.","Nej. Du må ikke gå ind på rådhuset. Det er ikke sikkert længere. Vores dække er blevet afsløret. Det er derfor, det regner heavy metal. Dræb så mange af de store drenge, som du kan. De kaldes ""Crusaders"". Når I er færdige, fører jeg jer til Macil.","Nein, betrete das Rathaus nicht. Es ist nicht mehr sicher. Unsere Tarnung ist aufgeflogen. Darum regnet es Schwermetall. Erledige so viele von den großen Robotern, wie du kannst. Sie werden „Ordensritter“ genannt. Wenn du das erledigt hast führe ich dich zu Macil.",,,"No. No entres en el ayuntamiento. Ya no es seguro. Nuestra tapadera ha sido descubierta. Por eso está lloviendo metal. Mata a tantos de esos grandotes como puedas. Se llaman ""Cruzados"". Cuando hayas terminado, te guiaré hasta Macil.",,"Ei, älä mene kaupungintaloon. Se ei ole enää turvallista; olemme paljastuneet. Sen takia sataa metallia. Tapa noita isoja poikia niin monta kuin pysyt. Niitä kutsutaan ""ristiretkeläisiksi"". Kun olet valmis, johdatan sinut Macilin luokse.","Non, n'entre pas dans la mairie, notre couverture est foutue. C'est pour ça que tout est en train de péter. Détruis tous les gros machins que tu croise, on les appelle les ""Croisés"". Quand tu as fini, je te dirais où se trouve Macil.","Ne menj be a városházára. Már nem biztonságos. Lelepleződtünk. Ezért ennyire sűrű az ólomeső. Ölj meg annyi nagy fiút, amennyit csak tudsz. ""Keresztes"" névre hallgatnak. Ha kész vagy, elvezetlek macilhoz.","No. Non entrare nel municipio. Non è più sicuro. La nostra copertura è saltata. È per questo che sta piovendo piombo. Distruggi più di questi grossi robot che puoi. Si chiamano ""Crociati"". Quando hai finito, di guiderò da Macil.",,"잠깐, 시청으로 가지 마. 이미 발각되어서 이젠 안전하지 않아. 아마도 총알의 비가 내리는 유일한 이유일 거야. 최선을 다해서 저 커다란 친구들을 격파해봐. 저놈들은 ""크루세이더"" 라고 해. 이 일을 끝마치면, 마실이 있는 곳으로 안내해줄게. ","Nee. Ga het stadhuis niet binnen. Het is niet meer veilig. Onze dekmantel is opgeblazen. Daarom regent het zwaar metaal. Dood zoveel mogelijk van die grote jongens als je kunt. Ze worden ""Kruisvaarders"" genoemd. Als je klaar bent, begeleid ik je naar Macil.","Nei. Ikke gå inn i rådhuset. Det er ikke trygt lenger. Vi er avslørt. Det er derfor det regner heavy metal. Drep så mange av de store gutta du kan. De kalles ""korsfarere"". Når du er ferdig, viser jeg deg veien til Macil.","Nie. Nie wchodź do ratusza. To już nie jest bezpieczne. Nasza przykrywka została zdmuchnięta. To dlatego pada heavy metal. Zabij jak najwięcej tych wielkich chłopców. Nazywają się ""Crusaders"". Kiedy skończysz, zaprowadzę cię do Macil.","Não. Não entre na prefeitura. Não é mais seguro. Fomos descobertos. É por isso que está vindo chumbo grosso pra todo lado. Mate o máximo possível desses grandalhões. São chamados de ""Cruzados"". Quando você terminar, eu te levo pro Macil.",,"Nu. Nu intra în oraș. Ni s-a dus acoperirea. De asta plouă cu metale grele. Omoară cât de mulți băieți duri poți. Se cheamă ""Cruciați"". Când ești gata o să te îndrum spre Macil.","Нет. Не входи в ратушу. Там небезопасно. Наше прикрытие сорвано. Вот почему идёт дождь из тяжёлого металла. Убей как можно больше этих здоровяков. Они называются «Крестоносцы». Когда закончишь, я отведу тебя к Мэйсилу.",,"Hayır. Belediye binasına girme. Artık güvenli değil. Kimliğimiz açığa çıktı. Bu yüzden heavy metal yağıyor. O koca oğlanlardan öldürebildiğiniz kadarını öldürün. Onlara ""Haçlılar"" deniyor. İşiniz bittiğinde, sizi Macil'e götüreceğim." -"Good work, friend! It's time to bring you inside.",TXT_SUB_LOG232,,,,"Dobrá práce, kamaráde! Je čas přivést tě dovnitř.","Godt arbejde, min ven! Det er tid til at bringe dig indenfor.","Gute Arbeit, mein Freund. Es ist Zeit dich hereinzubringen.",,,"¡Buen trabajo, amigo! Es hora de traerte adentro.",,"Hyvää työtä, ystävä! On aika tuoda sinut sisälle.","Bien joué, mon ami! Il est temps de te faire rentrer.",Szép munka barátom! Ideje bevinnelek.,"Ottimo lavoro, amico! È ora di farti entrare.",,"건투를 빌어, 친구! 안으로 들여보내 줄게. ","Goed werk, vriend! Het is tijd om je binnen te brengen.","Godt jobbet, min venn! Det er på tide å få deg inn.","Dobra robota, przyjacielu! Czas wprowadzić cię do środka.","Bom trabalho, amigo! Hora de trazê-lo pra dentro.",,"Bună treabă, prietene! E timpul să te aduc înăuntru!","Хорошая работа, друг! Пришло время впустить тебя внутрь.",,"İyi iş, dostum! Seni içeri götürme vakti geldi." -"Watch out for those Crusaders. They're big, hunking robots, and mean as hell. We don't know jack about their weapons, but odds are... you're outmatched. Careful.",TXT_SUB_LOG233,,,,"Pozor na ty Křižáky. Jsou to velcí, mohutní roboti a zatraceně zlí. Nevíme nic o jejich zbraních. Vypadá to že... jsou v přesile. Opatrně.","Pas på de korsfarere. De er store, store robotter, og onde som bare fanden. Vi ved ikke noget om deres våben, men oddsene er... at I er underlegne. Pas på.",Sieh dich vor den Ordensrittern vor. Das sind große und mächtige Roboter und höllisch gefährlich. Wir wissen nichts über ihre Waffen aber sie übertreffen deine bei weitem. Vorsicht!,,,"Ten cuidado con esos Cruzados. Son unos robots enormes y despiadados. No sabemos nada sobre sus armas, pero lo probable es... que te lleven ventaja. Cuidado.",,"Varo noita ristiretkeläisiä. Ne ovat isoja järkälemäisiä robotteja ja helvetin häijyjä. Emme tiedä yhtikäs mitään niiden aseista, mutta todennäköisyys on... että olet heikoilla. Varovaisesti.","Fais attention aux croisés, ce sont des sacrément grosses machines, et salement méchantes, aussi. On ne sait pas quelles armes ils utilisent, mais il est probable qu'ils en ont.. Plus que toi. Fais attention.","Vigyázz azokkal a keresztesekkel. Nagy, testes robotok, és morcosok is. nem sokat tudunk a fegyvereikről, de az esélyied... nem túl fényesek. Vigyázz magadra.","Attento a questi Crociati. Sono grossi, potenti robot e davvero pericolosi. Non sappiamo nulla sulle loro armi ma è molto probabile... che tu sia surclassato. Attento.",,"크루세이더를 조심해. 저놈들은 커다랗고 강력한 기동 병기야. 난폭하기도 하지. 놈들의 무장이 뭔지 모르지만, 중요한 점은 넌 포위됐다는 거지. 조심해. ","Kijk uit voor die kruisvaarders. Het zijn grote, hangende robots, en gemeen als de hel. We weten niet hoe het met hun wapens zit, maar de kans is groot dat je niet bij elkaar past. Voorzichtig.","Se opp for korsfarerne. De er store, kjekke roboter, og slemme som faen. Vi vet ingenting om våpnene deres, men det er sannsynlig at dere er underlegne. Forsiktig.","Uważaj na tych Krzyżowców. To wielkie, potężne roboty i wredne jak diabli. Nie wiemy nic o ich broni, ale prawdopodobnie... nie macie szans. Ostrożnie.","Cuidado com esses Cruzados. São robôs grandes e perigosos pra caramba. Não sabemos merda nenhuma sobre as suas armas, mas as chances são de que... você está em desvantagem. Cuidado.",,"Ai grijă la Cruciați. Sunt roboți imenși, și duri ca naiba. Nu știm absolut nimic despre armamentul lor, dar șansele sunt... nu ești pe măsura lor. Grijă.","Остерегайся крестоносцев. Они большие, громадные роботы, и чертовски злые. Мы не знаем ничего об их оружии, но, скорее всего... ты не справишься. Будь осторожен.",,"Şu Haçlılara dikkat et. Onlar büyük, iri robotlar ve çok acımasızlar. Silahları hakkında bir şey bilmiyoruz, ama ihtimaller... rakibiniz yok. Dikkatli olun." -"Great job. You're my idea of a good time. Now, without anyone seeing you, go through the door on the right, head on upstairs and meet the man.",TXT_SUB_LOG234,,,,"Skvělá práce. Vypadáš jako člověk do nepohody. A teď, bez toho, aby tě někdo uviděl, projdi dveřmi napravo, jdi po schodech nahoru a setkej se s ním.","Godt gået. Du er min idé om en god tid. Gå nu, uden at nogen ser dig, gennem døren til højre, gå op ad trappen og mød manden.","Gute Arbeit. Das macht mir richtig Freude. Nun gehe - ohne dass man dich sieht - durch die Tür da rechts, und treffe den Mann.",,,"Buen trabajo. Eres mi idea de una buena juerga. Ahora, sin que te vean, ve por la puerta a la derecha, sube las escaleras y conoce al hombre.",,"Hyvää työtä. Vastaat mielikuvaani hyvästä ajanvietteestä. Mene nyt kenenkään näkemättä oikeanpuoleisen oven läpi, kulje yläkertaan ja tapaa mies.","Bien joué, tu connaîs bien mon idée d'une bonne fête. Maintenant, sans que personne ne te voie, passe par la porte à droite, monte à l'étage et rencontre le type.","Remek munka. Te vagy a jól eltöltött idő definíciója. Most pedig anélkül, hogy bárki meglátna, menj a jobb oldalon levő ajtóhoz, majd az emeleten találkozz az emberünkkel.","Ottimo lavoro. Tu si che mi fai divertire. Ora, senza che nessuno ti veda, attraversa la porta alla tua destra, vai di sopra e incontralo.",,"잘 싸웠어. 내가 생각지도 못한 기발한 생각을 많이 하네. 이제, 모두가 너를 보지 않는 동안 오른쪽 문으로 들어가서 계단을 올라가고 남자를 만나.","Goed werk. Jij bent mijn idee van een goede tijd. Nu, zonder dat iemand je ziet, ga door de deur aan de rechterkant, ga naar boven en ontmoet de man.","Bra jobbet. Du er min idé om en god tid. Nå, uten at noen ser deg, gå gjennom døren til høyre, gå ovenpå og møt mannen.","Świetna robota. Jesteś moim pomysłem na dobrą zabawę. Przejdź przez drzwi po prawej, wejdź na górę i spotkaj się z tym człowiekiem.","Muito bom. Você sabe mesmo como entreter alguém. Agora, sem ninguém te ver, entre pela porta à direita, suba as escadas e encontre o cara.",,"Bună treabă. Acum, fără nimeni care să te vadă, du-te prin ușa de la dreapta, la etaj, și întâlnește-l.","Отличная работа. Ты - мой способ хорошо провести время. Теперь, чтобы никто тебя не увидел, пройди через дверь справа, поднимись наверх и встреться с мужчиной.",,"İyi iş çıkardın. Sen benim iyi vakit geçirme anlayışımsın. Şimdi, kimse seni görmeden, sağdaki kapıdan geç, yukarı çık ve adamla buluş." -"You let anyone see you, we'll have your head.",TXT_SUB_LOG235,,,,"Dovolíš, aby tě někdo uviděl, a budeme mít tvou hlavu.","Hvis du lader nogen se dig, får vi dit hoved.","Wenn man dich sieht, machen wir dich alle.",,,"Si dejas que te vean, tomaremos tu cabeza.",,"Jos annat kenenkään nähdä sinut, pääsi on vadilla.","Si qui que ce soit te voit, on aura ta tête.","Ha bárki meglát, levesszük a fejed.","Se ti vede qualcuno, avremo la tua testa.",,결국엔 사람들이 너를 보았네. 사적인 건 아니지만 넌 죽어줘야겠어. ,"Als je iemand je laat zien, hebben we je hoofd.","Hvis noen ser deg, tar vi hodet ditt.","Jeśli ktoś cię zobaczy, dostaniesz głowę.","Se você deixar alguém te ver, a sua cabeça é nossa.",,Lași pe cineva să te vadă și-ți luăm capul.,"Если ты позволишь кому-нибудь увидеть себя, мы получим твою голову.",,"Birinin seni görmesine izin verirsen, kelleni alırız." -"You stupid, stumbling, club-footed hunchback imbecile! You've given us away!",TXT_SUB_LOG236,,,,"Ty hloupý, klopýtavý, těžkopádný idiotský hrbáči! Prozradils nás!","Din dumme, snublende, klumpfodede, pukkelryggede idiot! Du har afsløret os!","Du dummer, ungeschickter, klumpfüßiger, buckliger Trottel. Du hast uns verraten.",,,¡Estúpido patán! ¡Nos has traicionado!,,"Sinä typerä, kömpelö, kampurajalkainen imbesilli! Olet paljastanut meidät!","Espèce d'abruti, crétin bossu pas foutu de marcher droit! Tu fait foirer notre couverture!",Te hülye botladozó kétballábú púpos állat! Észrevettek minket miattad!,"Stupido, impiastro, gobbo imbecille! Ci hai fatto scoprire!",,"이 어리석은, 멍청한, 짜리몽땅한 말미잘 얼간이! 우리 곁을 떠나다니!","Jij stomme, struikelende, knotsvoetige bochelende imbeciel! Je hebt ons weggegeven!","Din dumme, klumpfotete, pukkelryggede idiot! Du har avslørt oss!","Ty głupi, potykający się, garbaty imbecylu! Wydałeś nas!",Seu imbecil idiota estúpido duma figa! Você nos entregou!,,Imbecilule! Ne-ai dat de gol!,"Ты тупой, неуклюжий, косолапый горбатый имбецил! Ты нас выдал!",,"Seni aptal, tökezleyen, sopa ayaklı, kambur embesil! Bizi ele verdin!" -"I wish I was waiting for you behind that door... but I've got to stay underground. It's time for you to meet our leader, Macil.",TXT_SUB_LOG237,,,,"Přála bych si, abych to byla já, kdo bude čekat za těmi dveřmi... ale musím zůstat v podzemí. Je čas setkat se s naším vůdcem, Macilem.","Jeg ville ønske, jeg ventede på dig bag den dør ... men jeg må blive under jorden. Det er tid til at du skal møde vores leder, Macil.","Ich wünschte, ich würde hinter der Tür dort warten... aber ich muss im Untergrund bleiben. Es ist Zeit, unseren Anführer, Macil, zu treffen.",,,"Ojalá fuera yo esperando tras esa puerta... Pero debo mantenerme bajo tierra. Es hora de que conozcas a nuestro lider, Macil.",,"Kunpa olisin voinut olla sinua ovella vastassa, mutta minun on pysyttävä maan alla. Sinun on aika tavata johtajamme, Macilin.","J'aurais adoré être de l'autre côté de cette porte.. Mais il faut que je reste sous terre. Il est temps que tu rencontre notre leader, Macil.","Bárcsak Én várhatnálak az ajtó mögött... de a föld alatt kell maradnom. Itt az ideje, hogy megismerd a vezetőnket, Macilt.","Vorrei esserci io ad attenderti dietro la porta... ma devo rimanere sottoterra. È tempo per te di incontrare il nostro leader, Macil.",,저 문 앞에서 내가 기다리고 있었으면 얼마나 좋을까... 하지만 난 지하에서 임무를 수행해야 해. 마실 사령관을 만날 준비를 해.,Ik wou dat ik achter die deur op je zat te wachten.... maar ik moet ondergronds blijven. Het is tijd om onze leider Macil te ontmoeten.,"Jeg skulle ønske jeg ventet på deg bak den døra, men jeg må holde meg under jorden. Det er på tide at du møter lederen vår, Macil.","Chciałbym czekać na ciebie za tymi drzwiami... ale muszę zostać pod ziemią. Czas, byś poznał naszego przywódcę, Macila.","Eu queria estar te esperando por trás daquela porta... mas eu tenho que ficar no subterrâneo. É hora de você conhecer o nosso líder, Macil.",,"Speram ca eu să te aștept în spatele ușii... dar trebuie să rămân în subteran. E timpul să ne cunoști liderul, Macil.","Хотела бы я ждать тебя за этой дверью... но я должна оставаться под землёй. Пришло время познакомить тебя с нашим лидером, Мэйсилом.",,Keşke o kapının arkasında seni bekliyor olsaydım... ama yeraltında kalmalıyım. Liderimiz Macil ile tanışma vaktin geldi. -,,Blackbird's remarks embedded in other conversations,,,,,,,,,,,,,,,,,,,,,,,, -"Bloated pig. I know nothing about this so-called power coupling, so let's go slow.",TXT_BBSUB_SCRIPT02_D57608_IFIKN,MAP02: Mourel.,,,"Prohnilá svině. O téhle jakési spojce nic nevím, tak na to pojďme pomalu.","Oppustet gris. Jeg ved intet om denne såkaldte kraftkobling, så lad os gå langsomt frem.",Aufgeblasener Mistkerl. Ich weiß nichts über diese sogenannte Anzapfung so lass uns vorsichtig sein.,,,"Cerdo hinchado. No sé nada sobre ese supuesto acoplamiento de energía, así que vayamos con calma.",,"Pöhöttynyt sika. En tiedä mitään tästä niin sanotusta virtaliittimestä, joten otetaan rauhallisesti.","Quel porc. Je ne sais rien sur ce coupleur énergétique, allons-y doucement.","Te dagadt disznó. Nem tudok semmit erről az úgynevezett áramelosztóról, szóval menjünk csak lassan.","Che pallone gonfiato. Non so nulla su questo aggeggio, quindi andiamoci piano.","慢心してた。私はこの配電機と言われている物について何も知らない。 -まあゆっくりやろう。",배부른 돼지 같은 녀석. 난 이 추출기에 대해서 아무것도 몰라. 일단 성급하지 말자.,"Opgeblazen varken. Ik weet niets van deze zogenaamde stroomkoppeling, dus laten we langzaam gaan.","Oppblåste gris. Jeg vet ingenting om denne såkalte kraftkoblingen, så la oss ta det rolig.","Nadęta świnia. Nie wiem nic o tym tak zwanym sprzężeniu mocy, więc chodźmy powoli.","Que porco nojento. Eu não sei nada sobre essa tal ligação de energia, então vamos devagar.",,"Porcule. Nu știu nimic despre așa-zisul cuplaj de putere, așa că să mergem încet.",Жирная свинья. Я ничего не знаю об этой «соединительной муфте». Давай не будем торопиться.,,"Şişirilmiş domuz. Bu sözde güç birleşmesi hakkında hiçbir şey bilmiyorum, o yüzden yavaş gidelim." -"Sounds like a dream job, doesn't it?",TXT_BBSUB_SCRIPT03_D4548_GOODB,MAP03: Macil.,,,"To zní jako práce snů, ne?","Det lyder som et drømmejob, ikke sandt?","Hört sich an wie ein Traumjob, nicht wahr?",,,"Suena a un trabajo ideal, ¿no?",,Eikö kuulostakin unelmapestiltä?,"On dirait que c'est le boulot idéal, non?","Olyan mint egy álom meló, ugye?","Sembra un lavoro da sogno, no?",夢の様な仕事ね、そう思わない?,"듣기만 해도 꿈에 그리던 일만 같네, 그렇지?","Klinkt als een droombaan, nietwaar?","Høres ut som en drømmejobb, ikke sant?","Brzmi jak praca marzeń, prawda?","Parece ser o emprego dos sonhos, não é mesmo?",,"Sună ca un vis, nu?","Это же работа мечты, разве нет?",,"Rüya gibi bir iş, değil mi?" -And I'll be right there with you.,TXT_BBSUB_SCRIPT03_D7580_TAKET,〃,,,A já tam budu s tebou.,Og jeg vil være lige der sammen med dig.,Und ich werde bei deiner Seite sein.,,,Y estaré justo ahí contigo.,,Ja olen kanssasi koko ajan.,Et je serais là pour toi.,Mindig ott leszek neked.,E io sarò lì con te.,それで貴方のすぐ傍にいるわ。,그리고 내가 너와 함께 있어 줄께.,En ik zal er zo bij je zijn.,Og jeg blir med deg.,A ja będę tam z tobą.,E eu vou estar bem alí do seu lado.,,O să fie alături de tine.,А я буду рядом с тобой.,,Ben de senin yanında olacağım. -Worner's a spy we recruited in the warehouse of the power station.,TXT_BBSUB_SCRIPT03_D12128_ASING,〃,,,"Worner je špión, kterého jsme najali ve skladišti elektrárny.","Worner er en spion, som vi rekrutterede i lageret på kraftværket.","Worner ist ein Spion, den wir im Lagerhaus des Kraftwerks rekrutiert haben.",,,Worner es un espía que reclutamos en el almacén de la central eléctrica.,,Worner on värväämämme vakooja voimalaitoksen varastolta.,Worner est un espion que l'on a recruté dans l'entrepôt de la centrale électrique.,"Worner egy spion, akit átállítottunk az oldalunkra az erőmű raktárjában.",Worner è una spia che noi avevamo reclutato nel magazzino della centrale elettrica.,ワーナーは発電所の倉庫に送った我々のスパイよ。,워너는 우리가 모집한 첩자야. 그는 발전소 창고에 있어.,Worner is een spion die we in het magazijn van de centrale hebben gerekruteerd.,Worner er en spion vi rekrutterte på lageret til kraftstasjonen.,"Worner to szpieg, którego zwerbowaliśmy w magazynie elektrowni.",O Worner é um espião que recrutamos no depósito da usina elétrica.,,Worner e un spion pe care l-am recrutat în depozitul stației de energie.,"Уорнэр — шпион, которого мы завербовали на складе электростанции.",,"Worner, güç istasyonunun deposunda işe aldığımız bir casus." +Random comment when the player dies with Classic Mode turned off",,,Snila jsem o tobě... Kurva.,Jeg havde drømme om dig... Det er sgu hårdt.,Ich hatte Träume für dich. Scheiße.,,,Tenía sueños para ti... Lástima.,,Elättelin toiveita sinusta... Paska mäihä.,J'avais des grands rêves pour toi.. Franchement dommage.,Álmodtam számodra valamit... Szar ügy.,Ho fatto sogni per te... Che peccato.,私は貴方に希望を抱いていた...クソ世知辛いわ。,너를 꿈꿔왔어... 꿈은 꿈이였나봐.,Ik had dromen voor je.... Moeilijke shit.,Jeg hadde drømmer for deg... Synd for deg.,Miałem dla ciebie marzenia... Twarde gówno.,Eu tinha uma grande expectativa sobre você... Que merda.,,Aveam visuri pentru tine... Rahatule...,Я так надеялся на тебя... Упрямый засранец.,,Jag hade drömmar om dig... Det är jobbigt.,Senin için hayallerim vardı. Zor iş. +"No. Don't enter the town hall. It's not safe anymore. Our cover's been blown. That's why it's raining heavy metal. Kill as many of those big boys as you can. They're called ""Crusaders"". When you're done, I'll guide you to Macil.",TXT_SUB_LOG231,,,,"Ne. Nechoď do radnice, už není bezpečná. Byli jsme odhaleni, proto nám prší olovo na hlavu. Zabij kolik těch velkých kluků můžeš. Říká se jim Křižáci. Když jsi hotový, nasměruju tě k Macilovi.","Nej. Du må ikke gå ind på rådhuset. Det er ikke sikkert længere. Vores dække er blevet afsløret. Det er derfor, det regner heavy metal. Dræb så mange af de store drenge, som du kan. De kaldes ""korsfarere"". Når I er færdige, fører jeg jer til Macil.","Nein, betrete das Rathaus nicht. Es ist nicht mehr sicher. Unsere Tarnung ist aufgeflogen. Darum regnet es Schwermetall. Erledige so viele von den großen Robotern, wie du kannst. Sie werden „Ordensritter“ genannt. Wenn du das erledigt hast führe ich dich zu Macil.",,,"No. No entres en el ayuntamiento. Ya no es seguro. Nuestra tapadera ha sido descubierta. Por eso está lloviendo metal. Mata a tantos de esos grandotes como puedas. Se llaman ""Cruzados"". Cuando hayas terminado, te guiaré hasta Macil.",,"Ei, älä mene kaupungintaloon. Se ei ole enää turvallista; olemme paljastuneet. Sen takia sataa metallia. Tapa noita isoja poikia niin monta kuin pysyt. Niitä kutsutaan ""ristiretkeläisiksi"". Kun olet valmis, johdatan sinut Macilin luokse.","Non, n'entre pas dans la mairie, notre couverture est foutue. C'est pour ça que tout est en train de péter. Détruis tous les gros machins que tu croise, on les appelle les ""Croisés"". Quand tu as fini, je te dirais où se trouve Macil.","Ne menj be a városházára. Már nem biztonságos. Lelepleződtünk. Ezért ennyire sűrű az ólomeső. Ölj meg annyi nagy fiút, amennyit csak tudsz. ""Keresztes"" névre hallgatnak. Ha kész vagy, elvezetlek macilhoz.","No. Non entrare nel municipio. Non è più sicuro. La nostra copertura è saltata. È per questo che sta piovendo piombo. Distruggi più di questi grossi robot che puoi. Si chiamano ""Crociati"". Quando hai finito, di guiderò da Macil.",,"잠깐, 시청으로 가지 마. 이미 발각되어서 이젠 안전하지 않아. 아마도 총알의 비가 내리는 유일한 이유일 거야. 최선을 다해서 저 커다란 친구들을 격파해봐. 저놈들은 ""크루세이더"" 라고 해. 이 일을 끝마치면, 마실이 있는 곳으로 안내해줄게. ","Nee. Ga het stadhuis niet binnen. Het is niet meer veilig. Onze dekmantel is opgeblazen. Daarom regent het zwaar metaal. Dood zoveel mogelijk van die grote jongens als je kunt. Ze worden ""Kruisvaarders"" genoemd. Als je klaar bent, begeleid ik je naar Macil.","Nei. Ikke gå inn i rådhuset. Det er ikke trygt lenger. Vi er avslørt. Det er derfor det regner heavy metal. Drep så mange av de store gutta du kan. De kalles ""korsfarere"". Når du er ferdig, viser jeg deg veien til Macil.","Nie. Nie wchodź do ratusza. To już nie jest bezpieczne. Nasza przykrywka została zdmuchnięta. To dlatego pada heavy metal. Zabij jak najwięcej tych wielkich chłopców. Nazywają się ""krzyżowcami"". Kiedy skończysz, zaprowadzę cię do Macil.","Não. Não entre na prefeitura. Não é mais seguro. Fomos descobertos. É por isso que está vindo chumbo grosso pra todo lado. Mate o máximo possível desses grandalhões. São chamados de ""Cruzados"". Quando você terminar, eu te levo pro Macil.",,"Nu. Nu intra în oraș. Ni s-a dus acoperirea. De asta plouă cu metale grele. Omoară cât de mulți băieți duri poți. Se cheamă ""Cruciați"". Când ești gata o să te îndrum spre Macil.","Нет. Не входи в ратушу. Там небезопасно. Наше прикрытие сорвано. Вот почему идёт дождь из тяжёлого металла. Убей как можно больше этих здоровяков. Они называются «Крестоносцы». Когда закончишь, я отведу тебя к Мэйсилу.",,"Nej. Gå inte in i stadshuset. Det är inte säkert längre. Vår täckmantel är avslöjad. Det är därför det regnar heavy metal. Döda så många av de stora pojkarna som du kan. De kallas ""korsfarare"". När du är klar guidar jag dig till Macil.","Hayır. Belediye binasına girme. Artık güvenli değil. Kimliğimiz açığa çıktı. Bu yüzden heavy metal yağıyor. O koca oğlanlardan öldürebildiğiniz kadarını öldürün. Onlara ""Haçlılar"" deniyor. İşiniz bittiğinde, sizi Macil'e götüreceğim." +"Good work, friend! It's time to bring you inside.",TXT_SUB_LOG232,,,,"Dobrá práce, kamaráde! Je čas přivést tě dovnitř.","Godt arbejde, min ven! Det er tid til at bringe dig indenfor.","Gute Arbeit, mein Freund. Es ist Zeit dich hereinzubringen.",,,"¡Buen trabajo, amigo! Es hora de traerte adentro.",,"Hyvää työtä, ystävä! On aika tuoda sinut sisälle.","Bien joué, mon ami! Il est temps de te faire rentrer.",Szép munka barátom! Ideje bevinnelek.,"Ottimo lavoro, amico! È ora di farti entrare.",,"건투를 빌어, 친구! 안으로 들여보내 줄게. ","Goed werk, vriend! Het is tijd om je binnen te brengen.","Godt jobbet, min venn! Det er på tide å få deg inn.","Dobra robota, przyjacielu! Czas wprowadzić cię do środka.","Bom trabalho, amigo! Hora de trazê-lo pra dentro.",,"Bună treabă, prietene! E timpul să te aduc înăuntru!","Хорошая работа, друг! Пришло время впустить тебя внутрь.",,"Bra jobbat, min vän! Det är dags att ta in dig.","İyi iş, dostum! Seni içeri götürme vakti geldi." +"Watch out for those Crusaders. They're big, hunking robots, and mean as hell. We don't know jack about their weapons, but odds are... you're outmatched. Careful.",TXT_SUB_LOG233,,,,"Pozor na ty Křižáky. Jsou to velcí, mohutní roboti a zatraceně zlí. Nevíme nic o jejich zbraních. Vypadá to že... jsou v přesile. Opatrně.","Pas på de korsfarere. De er store, store robotter, og onde som bare fanden. Vi ved ikke noget om deres våben, men oddsene er... at I er underlegne. Pas på.",Sieh dich vor den Ordensrittern vor. Das sind große und mächtige Roboter und höllisch gefährlich. Wir wissen nichts über ihre Waffen aber sie übertreffen deine bei weitem. Vorsicht!,,,"Ten cuidado con esos Cruzados. Son unos robots enormes y despiadados. No sabemos nada sobre sus armas, pero lo probable es... que te lleven ventaja. Cuidado.",,"Varo noita ristiretkeläisiä. Ne ovat isoja järkälemäisiä robotteja ja helvetin häijyjä. Emme tiedä yhtikäs mitään niiden aseista, mutta todennäköisyys on... että olet heikoilla. Varovaisesti.","Fais attention aux croisés, ce sont des sacrément grosses machines, et salement méchantes, aussi. On ne sait pas quelles armes ils utilisent, mais il est probable qu'ils en ont.. Plus que toi. Fais attention.","Vigyázz azokkal a keresztesekkel. Nagy, testes robotok, és morcosok is. nem sokat tudunk a fegyvereikről, de az esélyied... nem túl fényesek. Vigyázz magadra.","Attento a questi Crociati. Sono grossi, potenti robot e davvero pericolosi. Non sappiamo nulla sulle loro armi ma è molto probabile... che tu sia surclassato. Attento.",,"크루세이더를 조심해. 저놈들은 커다랗고 강력한 기동 병기야. 난폭하기도 하지. 놈들의 무장이 뭔지 모르지만, 중요한 점은 넌 포위됐다는 거지. 조심해. ","Kijk uit voor die kruisvaarders. Het zijn grote, hangende robots, en gemeen als de hel. We weten niet hoe het met hun wapens zit, maar de kans is groot dat je niet bij elkaar past. Voorzichtig.","Se opp for korsfarerne. De er store, kjekke roboter, og slemme som faen. Vi vet ingenting om våpnene deres, men det er sannsynlig at dere er underlegne. Forsiktig.","Uważaj na tych Krzyżowców. To wielkie, potężne roboty i wredne jak diabli. Nie wiemy nic o ich broni, ale prawdopodobnie... nie macie szans. Ostrożnie.","Cuidado com esses Cruzados. São robôs grandes e perigosos pra caramba. Não sabemos merda nenhuma sobre as suas armas, mas as chances são de que... você está em desvantagem. Cuidado.",,"Ai grijă la Cruciați. Sunt roboți imenși, și duri ca naiba. Nu știm absolut nimic despre armamentul lor, dar șansele sunt... nu ești pe măsura lor. Grijă.","Остерегайся крестоносцев. Они большие, громадные роботы, и чертовски злые. Мы не знаем ничего об их оружии, но, скорее всего... ты не справишься. Будь осторожен.",,"Se upp för de där korsfararna. De är stora, jättelika robotar och elaka som fan. Vi vet inget om deras vapen, men oddsen är... att ni är underlägsna. Var försiktig.","Şu Haçlılara dikkat et. Onlar büyük, iri robotlar ve çok acımasızlar. Silahları hakkında bir şey bilmiyoruz, ama ihtimaller... rakibiniz yok. Dikkatli olun." +"Great job. You're my idea of a good time. Now, without anyone seeing you, go through the door on the right, head on upstairs and meet the man.",TXT_SUB_LOG234,,,,"Skvělá práce. Vypadáš jako člověk do nepohody. A teď, bez toho, aby tě někdo uviděl, projdi dveřmi napravo, jdi po schodech nahoru a setkej se s ním.","Godt gået. Du er min idé om en god tid. Gå nu, uden at nogen ser dig, gennem døren til højre, gå op ad trappen og mød manden.","Gute Arbeit. Das macht mir richtig Freude. Nun gehe - ohne dass man dich sieht - durch die Tür da rechts, und treffe den Mann.",,,"Buen trabajo. Eres mi idea de una buena juerga. Ahora, sin que te vean, ve por la puerta a la derecha, sube las escaleras y conoce al hombre.",,"Hyvää työtä. Vastaat mielikuvaani hyvästä ajanvietteestä. Mene nyt kenenkään näkemättä oikeanpuoleisen oven läpi, kulje yläkertaan ja tapaa mies.","Bien joué, tu connaîs bien mon idée d'une bonne fête. Maintenant, sans que personne ne te voie, passe par la porte à droite, monte à l'étage et rencontre le type.","Remek munka. Te vagy a jól eltöltött idő definíciója. Most pedig anélkül, hogy bárki meglátna, menj a jobb oldalon levő ajtóhoz, majd az emeleten találkozz az emberünkkel.","Ottimo lavoro. Tu si che mi fai divertire. Ora, senza che nessuno ti veda, attraversa la porta alla tua destra, vai di sopra e incontralo.",,"잘 싸웠어. 내가 생각지도 못한 기발한 생각을 많이 하네. 이제, 모두가 너를 보지 않는 동안 오른쪽 문으로 들어가서 계단을 올라가고 남자를 만나.","Goed werk. Jij bent mijn idee van een goede tijd. Nu, zonder dat iemand je ziet, ga door de deur aan de rechterkant, ga naar boven en ontmoet de man.","Bra jobbet. Du er min idé om en god tid. Nå, uten at noen ser deg, gå gjennom døren til høyre, gå ovenpå og møt mannen.","Świetna robota. Jesteś moim pomysłem na dobrą zabawę. Przejdź przez drzwi po prawej, wejdź na górę i spotkaj się z tym człowiekiem.","Muito bom. Você sabe mesmo como entreter alguém. Agora, sem ninguém te ver, entre pela porta à direita, suba as escadas e encontre o cara.",,"Bună treabă. Acum, fără nimeni care să te vadă, du-te prin ușa de la dreapta, la etaj, și întâlnește-l.","Отличная работа. Ты - мой способ хорошо провести время. Теперь, чтобы никто тебя не увидел, пройди через дверь справа, поднимись наверх и встреться с мужчиной.",,"Bra jobbat. Du är min idé om att ha roligt. Nu, utan att någon ser dig, gå genom dörren till höger, gå upp på övervåningen och möt mannen.","İyi iş çıkardın. Sen benim iyi vakit geçirme anlayışımsın. Şimdi, kimse seni görmeden, sağdaki kapıdan geç, yukarı çık ve adamla buluş." +"You let anyone see you, we'll have your head.",TXT_SUB_LOG235,,,,"Dovolíš, aby tě někdo uviděl, a budeme mít tvou hlavu.","Hvis du lader nogen se dig, får vi dit hoved.","Wenn man dich sieht, machen wir dich alle.",,,"Si dejas que te vean, tomaremos tu cabeza.",,"Jos annat kenenkään nähdä sinut, pääsi on vadilla.","Si qui que ce soit te voit, on aura ta tête.","Ha bárki meglát, levesszük a fejed.","Se ti vede qualcuno, avremo la tua testa.",,결국엔 사람들이 너를 보았네. 사적인 건 아니지만 넌 죽어줘야겠어. ,"Als je iemand je laat zien, hebben we je hoofd.","Hvis noen ser deg, tar vi hodet ditt.","Jeśli ktoś cię zobaczy, dostaniesz głowę.","Se você deixar alguém te ver, a sua cabeça é nossa.",,Lași pe cineva să te vadă și-ți luăm capul.,"Если ты позволишь кому-нибудь увидеть себя, мы получим твою голову.",,"Om någon ser dig, så tar vi ditt huvud.","Birinin seni görmesine izin verirsen, kelleni alırız." +"You stupid, stumbling, club-footed hunchback imbecile! You've given us away!",TXT_SUB_LOG236,,,,"Ty hloupý, klopýtavý, těžkopádný idiotský hrbáči! Prozradils nás!","Din dumme, snublende, klumpfodede, pukkelryggede idiot! Du har afsløret os!","Du dummer, ungeschickter, klumpfüßiger, buckliger Trottel. Du hast uns verraten.",,,¡Estúpido patán! ¡Nos has traicionado!,,"Sinä typerä, kömpelö, kampurajalkainen imbesilli! Olet paljastanut meidät!","Espèce d'abruti, crétin bossu pas foutu de marcher droit! Tu fait foirer notre couverture!",Te hülye botladozó kétballábú púpos állat! Észrevettek minket miattad!,"Stupido, impiastro, gobbo imbecille! Ci hai fatto scoprire!",,"이 어리석은, 멍청한, 짜리몽땅한 말미잘 얼간이! 우리 곁을 떠나다니!","Jij stomme, struikelende, knotsvoetige bochelende imbeciel! Je hebt ons weggegeven!","Din dumme, klumpfotete, pukkelryggede idiot! Du har avslørt oss!","Ty głupi, potykający się, garbaty imbecylu! Wydałeś nas!",Seu imbecil idiota estúpido duma figa! Você nos entregou!,,Imbecilule! Ne-ai dat de gol!,"Ты тупой, неуклюжий, косолапый горбатый имбецил! Ты нас выдал!",,"Din dumma, snubblande, klumpfotade puckelryggiga idiot! Du har avslöjat oss!","Seni aptal, tökezleyen, sopa ayaklı, kambur embesil! Bizi ele verdin!" +"I wish I was waiting for you behind that door... but I've got to stay underground. It's time for you to meet our leader, Macil.",TXT_SUB_LOG237,,,,"Přála bych si, abych to byla já, kdo bude čekat za těmi dveřmi... ale musím zůstat v podzemí. Je čas setkat se s naším vůdcem, Macilem.","Jeg ville ønske, jeg ventede på dig bag den dør ... men jeg må blive under jorden. Det er tid til at du skal møde vores leder, Macil.","Ich wünschte, ich würde hinter der Tür dort warten... aber ich muss im Untergrund bleiben. Es ist Zeit, unseren Anführer, Macil, zu treffen.",,,"Ojalá fuera yo esperando tras esa puerta... Pero debo mantenerme bajo tierra. Es hora de que conozcas a nuestro lider, Macil.",,"Kunpa olisin voinut olla sinua ovella vastassa, mutta minun on pysyttävä maan alla. Sinun on aika tavata johtajamme, Macilin.","J'aurais adoré être de l'autre côté de cette porte.. Mais il faut que je reste sous terre. Il est temps que tu rencontre notre leader, Macil.","Bárcsak Én várhatnálak az ajtó mögött... de a föld alatt kell maradnom. Itt az ideje, hogy megismerd a vezetőnket, Macilt.","Vorrei esserci io ad attenderti dietro la porta... ma devo rimanere sottoterra. È tempo per te di incontrare il nostro leader, Macil.",,저 문 앞에서 내가 기다리고 있었으면 얼마나 좋을까... 하지만 난 지하에서 임무를 수행해야 해. 마실 사령관을 만날 준비를 해.,Ik wou dat ik achter die deur op je zat te wachten.... maar ik moet ondergronds blijven. Het is tijd om onze leider Macil te ontmoeten.,"Jeg skulle ønske jeg ventet på deg bak den døra, men jeg må holde meg under jorden. Det er på tide at du møter lederen vår, Macil.","Chciałbym czekać na ciebie za tymi drzwiami... ale muszę zostać pod ziemią. Czas, byś poznał naszego przywódcę, Macila.","Eu queria estar te esperando por trás daquela porta... mas eu tenho que ficar no subterrâneo. É hora de você conhecer o nosso líder, Macil.",,"Speram ca eu să te aștept în spatele ușii... dar trebuie să rămân în subteran. E timpul să ne cunoști liderul, Macil.","Хотела бы я ждать тебя за этой дверью... но я должна оставаться под землёй. Пришло время познакомить тебя с нашим лидером, Мэйсилом.",,"Jag önskar att jag väntade på er bakom den dörren... men jag måste stanna under jorden. Det är dags för dig att träffa vår ledare, Macil.",Keşke o kapının arkasında seni bekliyor olsaydım... ama yeraltında kalmalıyım. Liderimiz Macil ile tanışma vaktin geldi. +,,Blackbird's remarks embedded in other conversations,,,,,,,,,,,,,,,,,,,,,,,,, +"Bloated pig. I know nothing about this so-called power coupling, so let's go slow.",TXT_BBSUB_SCRIPT02_D57608_IFIKN,MAP02: Mourel.,,,"Prohnilá svině. O téhle jakési spojce nic nevím, tak na to pojďme pomalu.","Oppustet gris. Jeg ved intet om denne såkaldte kraftkobling, så lad os gå langsomt frem.",Aufgeblasener Mistkerl. Ich weiß nichts über diese sogenannte Anzapfung so lass uns vorsichtig sein.,,,"Qué cerdo hinchado. No sé nada sobre ese supuesto acoplamiento de energía, así que vayamos con calma.",,"Pöhöttynyt sika. En tiedä mitään tästä niin sanotusta virtaliittimestä, joten otetaan rauhallisesti.","Quel porc. Je ne sais rien sur ce coupleur énergétique, allons-y doucement.","Te dagadt disznó. Nem tudok semmit erről az úgynevezett áramelosztóról, szóval menjünk csak lassan.","Che pallone gonfiato. Non so nulla su questo aggeggio, quindi andiamoci piano.","慢心してた。私はこの配電機と言われている物について何も知らない。 +まあゆっくりやろう。",배부른 돼지 같은 녀석. 난 이 추출기에 대해서 아무것도 몰라. 일단 성급하지 말자.,"Opgeblazen varken. Ik weet niets van deze zogenaamde stroomkoppeling, dus laten we langzaam gaan.","Oppblåste gris. Jeg vet ingenting om denne såkalte kraftkoblingen, så la oss ta det rolig.","Nadęta świnia. Nie wiem nic o tym tak zwanym sprzężeniu mocy, więc chodźmy powoli.","Que porco nojento. Eu não sei nada sobre essa tal ligação de energia, então vamos devagar.",,"Porcule. Nu știu nimic despre așa-zisul cuplaj de putere, așa că să mergem încet.",Жирная свинья. Я ничего не знаю об этой «соединительной муфте». Давай не будем торопиться.,,"Uppblåsta gris. Jag vet inget om den här så kallade maktkopplingen, så vi går långsamt fram.","Şişirilmiş domuz. Bu sözde güç birleşmesi hakkında hiçbir şey bilmiyorum, o yüzden yavaş gidelim." +"Sounds like a dream job, doesn't it?",TXT_BBSUB_SCRIPT03_D4548_GOODB,MAP03: Macil.,,,"To zní jako práce snů, ne?","Det lyder som et drømmejob, ikke sandt?","Hört sich an wie ein Traumjob, nicht wahr?",,,"Suena a un trabajo ideal, ¿no?",,Eikö kuulostakin unelmapestiltä?,"On dirait que c'est le boulot idéal, non?","Olyan mint egy álom meló, ugye?","Sembra un lavoro da sogno, no?",夢の様な仕事ね、そう思わない?,"듣기만 해도 꿈에 그리던 일만 같네, 그렇지?","Klinkt als een droombaan, nietwaar?","Høres ut som en drømmejobb, ikke sant?","Brzmi jak praca marzeń, prawda?","Parece ser o emprego dos sonhos, não é mesmo?",,"Sună ca un vis, nu?","Это же работа мечты, разве нет?",,"Låter som ett drömjobb, eller hur?","Rüya gibi bir iş, değil mi?" +And I'll be right there with you.,TXT_BBSUB_SCRIPT03_D7580_TAKET,〃,,,A já tam budu s tebou.,Og jeg vil være lige der sammen med dig.,Und ich werde bei deiner Seite sein.,,,Y estaré justo ahí contigo.,,Ja olen kanssasi koko ajan.,Et je serais là pour toi.,Mindig ott leszek neked.,E io sarò lì con te.,それで貴方のすぐ傍にいるわ。,그리고 내가 너와 함께 있어 줄께.,En ik zal er zo bij je zijn.,Og jeg blir med deg.,A ja będę tam z tobą.,E eu vou estar bem alí do seu lado.,,O să fie alături de tine.,А я буду рядом с тобой.,,Och jag kommer att vara där med dig.,Ben de senin yanında olacağım. +Worner's a spy we recruited in the warehouse of the power station.,TXT_BBSUB_SCRIPT03_D12128_ASING,〃,,,"Worner je špión, kterého jsme najali ve skladišti elektrárny.","Worner er en spion, som vi rekrutterede i lageret på kraftværket.","Worner ist ein Spion, den wir im Lagerhaus des Kraftwerks rekrutiert haben.",,,Worner es un espía que reclutamos en el almacén de la central eléctrica.,,Worner on värväämämme vakooja voimalaitoksen varastolta.,Worner est un espion que l'on a recruté dans l'entrepôt de la centrale électrique.,"Worner egy spion, akit átállítottunk az oldalunkra az erőmű raktárjában.",Worner è una spia che noi avevamo reclutato nel magazzino della centrale elettrica.,ワーナーは発電所の倉庫に送った我々のスパイよ。,워너는 우리가 모집한 첩자야. 그는 발전소 창고에 있어.,Worner is een spion die we in het magazijn van de centrale hebben gerekruteerd.,Worner er en spion vi rekrutterte på lageret til kraftstasjonen.,"Worner to szpieg, którego zwerbowaliśmy w magazynie elektrowni.",O Worner é um espião que recrutamos no depósito da usina elétrica.,,Worner e un spion pe care l-am recrutat în depozitul stației de energie.,"Уорнэр — шпион, которого мы завербовали на складе электростанции.",,Worner är en spion som vi rekryterade i kraftverkets lager.,"Worner, güç istasyonunun deposunda işe aldığımız bir casus." Make sure you're ready for the fight of your life. No scrimping. Spend everything you've got.,TXT_BBSUB_SCRIPT03_D16676_THEPR,〃,,,"Ujisti se, že jsi připraven na souboj svého života. Žádné škudlení. Utrať všechno, co máš.","Sørg for, at du er klar til dit livs kamp. Ingen spareøvelser. Brug alt, hvad du har.","Bereite dich auf den Kampf deines Lebens vor. Kein falsche Sparsamkeit, benutze alles, was du hast.",,,Asegúrate de estar preparado para la pelea de tu vida. No escatimes. Gástate todo lo que tengas.,,"Pidä huoli, että olet valmis taisteluun elämästäsi. Ei pihistelyä, käytä kaikki varasi.","Sois sûr que tu est prêt pour le combat le plus brutal de ta vie. Pas d'avarice, dépense tout ce que tu as.","Remélem készen állsz életed harcára. Ne kicsinyeskedj, költsd el minden pénzed.",Preparati per la lotta della tua vita. Non risparmiare. Spendi tutto ciò che hai.,"己の命の為に戦う準備が出来ているか確認して。 -ケチケチせずに。持ってる物全て使うのよ。",일생일대의 격전에 대비해. 돈 아끼지 말고 있는 대로 다 써.,Zorg ervoor dat je klaar bent voor de strijd van je leven. Geen krassen. Besteed alles wat je hebt.,Sørg for at du er klar for ditt livs kamp. Ikke spar på noe. Bruk alt du har.,"Upewnij się, że jesteś gotowy na walkę swojego życia. Nie oszczędzaj. Wydajcie wszystko, co macie.",Tenha certeza de que você estará preparado para lutar pela sua vida. Não poupa nada. Vai com tudo.,,Pregătește-te pentru lupta vieții tale. Cheltuie tot ce ai.,Приготовься к главному бою в своей жизни. Не скупись. Потрать на подготовку всё золото.,,Hayatının savaşına hazır olduğundan emin ol. Cimrilik yok. Sahip olduğun her şeyi harca. -"Excuse me, I'm gonna be sick.",TXT_BBSUB_SCRIPT04_D21224_BUSIN,MAP04: Derwin.,,,"Omluv mě, budu zvracet.","Undskyld mig, jeg bliver syg.","Entschuldige, aber mir wird übel.",,,"Disculpa, pero me voy a poner mala.","Disculpa, pero me voy a enfermar.","Suo anteeksi, kohta lentää laatta.","Pardon, je crois que je vais vomir.","Bocs, de mindjárt rosszul leszek.","Scusami, sto per sentirmi male.",失礼ながら、しゃくに障るわ。,"실례지만, 이거 좀 골때리겠는데?","Excuseer me, ik word ziek.","Unnskyld meg, jeg må kaste opp.","Przepraszam, będę chory.","Desculpa, estou passando mal.",,"Scuză-mă, o să mi se facă rău.","Прости, меня сейчас вырвет.",,"Affedersiniz, hasta olacağım." -Mmm. Sounds like weapons. We can always use more firepower.,TXT_BBSUB_SCRIPT04_D25772_TELLW,MAP04: Worner.,,,"Mhmm, to zní jako zbraně. Palebná síla se nám vždycky hodí.",Jeg er syg. Lyder som våben. Vi kan altid bruge mere ildkraft.,Hm... Klingt wie Waffen. Mehr Feuerkraft können wir immer gebrauchen.,,,Mmm. Suena a armas. Siempre nos viene bien más potencia de fuego.,,"Mmm, kuulostaa aseilta. Lisätulivoima aina kelpaa.",Mmmh. On dirait des armes. On peut toujours faire avec plus de puissance de feu.,Hmmm. Még több fegyvernek hangzik. Sosem lehet elég fegyverünk.,Mm. Sembrano delle armi. Ci fanno sempre comodo armi pesanti.,フーム。聞く限り武器の様ね。いつも以上の火力を出せそうだ。,으음. 왠지 무기 같은데. 화력이야 더 많으면 좋지.,Mmm. Klinkt als wapens. We kunnen altijd meer vuurkracht gebruiken.,Mmm. Høres ut som våpen. Vi kan alltids bruke mer ildkraft.,Mmm. Brzmi jak broń. Zawsze możemy użyć więcej siły ognia.,Hmmm. Sinto cheiro de armas. Poder de fogo a mais é sempre bem-vindo.,,Mmm. Sună a arme. Putem folosi mai multă putere de foc oricând.,"М-м-м. Похоже, там оружие. Лишняя огневая мощь не помешает.",,Mmm. Silahlara benziyor. Her zaman daha fazla ateş gücü kullanabiliriz. -"This sounds too easy, but let's give it a shot.",TXT_BBSUB_SCRIPT04_D31836_WHATD,MAP04: Reactor Core → Northern alarm door,,,"To zní až moc snadně, ale zkusme to.","Det lyder for nemt, men lad os prøve.","Das klingt zu einfach, aber lass es uns versuchen.",,,"Esto suena muy fácil, pero intentémoslo.",,"Kuulostaa liian helpolta, mutta yritetään.",Ca à l'air trop facile mais ça vaut le coup d'essayer.,"Túl könnyűnek hangzik, de próbálkozzunk meg vele.","Sembra troppo facile, ma proviamoci.",簡単すぎるけど、一発かましてみましょうか。,"쉬운 일 같지만, 일단 한번 해보자고.","Dit klinkt te gemakkelijk, maar laten we het eens proberen.","Dette høres for enkelt ut, men la oss prøve.","To brzmi zbyt łatwo, ale spróbujmy.","Tá parecendo fácil demais, mas vamos tentar.",,"Sună ușor, dar să încercăm.",Слишком уж заманчиво. Хотя давай попытаемся.,,Kulağa çok kolay geliyor ama bir deneyelim. -Who cares. Nobody listens to programmers anyway.,TXT_BBSUB_SCRIPT04_D40932_LETME,MAP04: Reactor Core → Southern alarm door,,,"Koho to zajímá, programátory stejně nikdo neposlouchá.",Det er ligegyldigt. Ingen lytter til programmører alligevel.,Egal! Wer hört schon auf Programmierer.,,,¿A quién le importa? Si nadie escucha a los programadores.,,Mitä väliä. Kukaan ei muutenkaan kuuntele ohjelmoijia.,"On s'en fout, personne n'écoute les programmeurs de toute manières.",Kit érdekel. Senki sem hallgat a programozókra.,A chi importa. Tanto nessuno sta a sentire i programmatori.,面倒ね。プログラマーについて知ってるのは誰もいないわ。,어쩌라고. 아무도 프로그래머들 이야기는 안 듣는데.,Wat maakt het uit. Niemand luistert sowieso naar programmeurs.,Hvem bryr seg? Ingen hører på programmerere uansett.,Kogo to obchodzi. I tak nikt nie słucha programistów.,Quem liga? Ninguém dá bola pros programadores mesmo.,,Cui îi pasă. Nimeni nu ascultă de programatori oricum.,Какая разница? Программистов всё равно никто не слушает.,,Kimin umurunda. Kimse programcıları dinlemiyor zaten. -"Ooh. Glad I'm in hiding, if you know what I mean.",TXT_BBSUB_SCRIPT04_D54576_ITSAS,〃,,,"Ou, jsem ráda, že se schovávám, jestli víš, co tím myslím.","Ooh. Jeg er glad for, at jeg gemmer mig, hvis du forstår, hvad jeg mener.","Uh. Wie gut, dass ich mich verstecke - du weißt schon was ich meine.",,,"Ooh. Menos mal que estoy escondida, si sabes a lo que me refiero.",,"Oo, onneksi olen piilossa, tiedätkö.","Ooh, je suis contente d'être cachée, si tu vois ce que je veux dire.","Óh. Még jó hogy ebújtam, már ha érted mire gondolok.","Ooh. Per fortuna che sono nascosta, se capisci cosa intendo.",オオゥ。私が言わなくてもわかるけど、隠れた方がいいわね。,"오, 내가 숨어있어서 다행이야. 무슨 뜻인지 알겠지?","Ooh. Blij dat ik ondergedoken zit, als je begrijpt wat ik bedoel.","Ooh. Jeg er glad jeg er i skjul, hvis du skjønner hva jeg mener.","Ooh. Cieszę się, że się ukrywam, jeśli wiesz, co mam na myśli.","Oooh. Ainda bem que estou escondida, se é que você me entende.",,"Ooh. Mă bucur că mă ascund, dacă știi ce zic.","Ой. Хорошо, что я в укрытии, если ты понимаешь, о чём я.",,"Ooh. Saklandığıma sevindim, ne demek istediğimi anlıyorsan." -What a grouch. I hope you get to kill him later.,TXT_BBSUB_SCRIPT05_D1516_OKBUT,MAP05: Door Guard.,,,"Takový mrzout. Doufám, že ho pak zabijeme.","Sikke en gnavpot. Jeg håber, du får lov til at dræbe ham senere.",Was für ein Ekel. Hoffentlich kannst du ihn später mal erledigen.,,"Kiel grumblema. Mi esperas, ke vi mortigos lin poste.",Qué gruñón. Espero que lo mates luego.,,Mikä hapannaama. Toivottavasti pääset tappamaan hänet myöhemmin.,Quel grincheux. J'espère qu'on va le buter plus tard.,Micsoda mogorva barom. Remélem később lehetőséged lesz megölni.,Che brontolone. Spero che ti ritrovi a ucciderlo dopo.,なに拗ねてるの。後で彼を殺すのを期待してるわ。,뭐가 이리 불만이야. 나중에 얘 좀 꼭 처리해줘.,Wat een humeur. Ik hoop dat je hem later kunt vermoorden.,For en grinebiter. Jeg håper du får drepe ham senere.,"Co za zrzęda. Mam nadzieję, że będziesz mógł go później zabić.",Que rabugento! Espero que você mate ele depois.,,Ce dobitoc. Sper să îl omori mai târziu.,"Ну и зануда. Надеюсь, ты потом вернёшься и снесёшь ему башку.",,Ne huysuz. Umarım onu daha sonra öldürürsün. -"""This area's off limits!"" Pompous so-and-so.",TXT_BBSUB_SCRIPT05_D3032_DOILO,〃,,,„Do této oblasti je vstup zakázán!“ Pompézní hajzl.,Dette område er forbudt område! Opblæste sådan-og-så.,„Zutritt verboten!“ Elendiger Wichtigtuer.,,,«Istí firi di lis límitis». Qué estirado.,«Istí firi di lis límitis». Pero qué creído.,"""Alueeseen on pääsy kielletty!"" Tärkeilevä mitäänsanomattomuus.","""Cette zone est à accès restreint!"" Pompeux anonyme, va.","""Tiltott a belépés!"" Persze már.","""Quest'area è ad accesso riservato!"" Pomposo miserabile.",この区域は立入禁止!'そんなワザとらしい。,“이곳은 통행 금지야!” 웃기고 앉아있네.,Dit gebied is verboden terrein! Pompous zo-en-zo.,Dette området er forbudt område! Pompøse så-og-så.,Ten teren jest niedostępny! Nadęty taki i taki.,"""Proibido entrar nessa área!"" Que miserável prepotente.",,"""Zona asta e interzisă!"" Pompos așa-și-așa.",«Здесь закрытая территория!» Надутый индюк.,,Burası yasak bölge! Kendini beğenmiş herif. -What an up guy.,TXT_BBSUB_SCRIPT05_D4548_THEOR,MAP05: Prison Guard.,,,Takový veselý chlapík!,Sikke en opblæst fyr.,Was für ein Blödmann.,,,Menudo idiota.,Qué «agradable» sujeto.,Mikä höhlä.,Quel type honnête.,De egy hülye.,Che idiota.,あら、いい男。,아주 들떠있는 녀석이네.,Wat een geweldige kerel.,For en oppblåst fyr.,Co za gość.,Que imbecil.,,Ce tip.,Какой хороший мальчик!,,Ne adam ama. -"Maybe it's because you didn't say ""please"".",TXT_BBSUB_SCRIPT05_D7580_OVERM,MAP05: Montag.,,,"Možná to je tím, žes neřekl „prosím“.","Måske er det fordi du ikke sagde ""tak"".",Vielleicht hättest du „Bitte“ sagen sollen.,,Eble ĉar vi ne diris «bonvolu».,Habrá sido porque no has dicho «por favor».,Habrá sido porque no dijiste «por favor».,"Ehkä, koska et pyytänyt riittävän nätisi.","Peut être, c'est parce que tu n'a pas dit ""s'il vous plaît.""","Lehet mert nem mondtad hogy ""kérem szépen"".","Forse perché non hai detto ""per favore"".",多分貴方が'お願いします'と言わなかったからよ。,아마 네가 “부탁”을 안 해서 이러나 봐.,"Misschien is het omdat je niet ""alsjeblieft"" hebt gezegd.","Kanskje det er fordi du ikke sa ""vær så snill""?","Może to dlatego, że nie powiedziałeś ""proszę"".","Deve ser porque você não disse ""por favor"".",,"Poate pentru nu ai spus ""te rog"".","Наверное, ты забыл сказать «пожалуйста»?",,"Belki de ""lütfen"" demediğin içindir." +ケチケチせずに。持ってる物全て使うのよ。",일생일대의 격전에 대비해. 돈 아끼지 말고 있는 대로 다 써.,Zorg ervoor dat je klaar bent voor de strijd van je leven. Geen krassen. Besteed alles wat je hebt.,Sørg for at du er klar for ditt livs kamp. Ikke spar på noe. Bruk alt du har.,"Upewnij się, że jesteś gotowy na walkę swojego życia. Nie oszczędzaj. Wydajcie wszystko, co macie.",Tenha certeza de que você estará preparado para lutar pela sua vida. Não poupa nada. Vai com tudo.,,Pregătește-te pentru lupta vieții tale. Cheltuie tot ce ai.,Приготовься к главному бою в своей жизни. Не скупись. Потрать на подготовку всё золото.,,Se till att du är redo för ditt livs kamp. Ingen snålhet. Spendera allt du har.,Hayatının savaşına hazır olduğundan emin ol. Cimrilik yok. Sahip olduğun her şeyi harca. +"Excuse me, I'm gonna be sick.",TXT_BBSUB_SCRIPT04_D21224_BUSIN,MAP04: Derwin.,,,"Omluv mě, budu zvracet.","Undskyld mig, jeg bliver syg.","Entschuldige, aber mir wird übel.",,,"Disculpa, pero me voy a poner mala.","Disculpa, pero me voy a enfermar.","Suo anteeksi, kohta lentää laatta.","Pardon, je crois que je vais vomir.","Bocs, de mindjárt rosszul leszek.","Scusami, sto per sentirmi male.",失礼ながら、しゃくに障るわ。,"실례지만, 이거 좀 골때리겠는데?","Excuseer me, ik word ziek.","Unnskyld meg, jeg må kaste opp.","Przepraszam, będę chory.","Desculpa, estou passando mal.",,"Scuză-mă, o să mi se facă rău.","Прости, меня сейчас вырвет.",,"Ursäkta mig, jag måste spy.","Affedersiniz, hasta olacağım." +Mmm. Sounds like weapons. We can always use more firepower.,TXT_BBSUB_SCRIPT04_D25772_TELLW,MAP04: Worner.,,,"Mhmm, to zní jako zbraně. Palebná síla se nám vždycky hodí.",Jeg er syg. Lyder som våben. Vi kan altid bruge mere ildkraft.,Hm... Klingt wie Waffen. Mehr Feuerkraft können wir immer gebrauchen.,,,Mmm. Suena a armas. Siempre nos viene bien más potencia de fuego.,,"Mmm, kuulostaa aseilta. Lisätulivoima aina kelpaa.",Mmmh. On dirait des armes. On peut toujours faire avec plus de puissance de feu.,Hmmm. Még több fegyvernek hangzik. Sosem lehet elég fegyverünk.,Mm. Sembrano delle armi. Ci fanno sempre comodo armi pesanti.,フーム。聞く限り武器の様ね。いつも以上の火力を出せそうだ。,으음. 왠지 무기 같은데. 화력이야 더 많으면 좋지.,Mmm. Klinkt als wapens. We kunnen altijd meer vuurkracht gebruiken.,Mmm. Høres ut som våpen. Vi kan alltids bruke mer ildkraft.,Mmm. Brzmi jak broń. Zawsze możemy użyć więcej siły ognia.,Hmmm. Sinto cheiro de armas. Poder de fogo a mais é sempre bem-vindo.,,Mmm. Sună a arme. Putem folosi mai multă putere de foc oricând.,"М-м-м. Похоже, там оружие. Лишняя огневая мощь не помешает.",,"Jag är sjuk, jag måste bli sjuk. Låter som vapen. Vi kan alltid behöva mer eldkraft.",Mmm. Silahlara benziyor. Her zaman daha fazla ateş gücü kullanabiliriz. +"This sounds too easy, but let's give it a shot.",TXT_BBSUB_SCRIPT04_D31836_WHATD,MAP04: Reactor Core → Northern alarm door,,,"To zní až moc snadně, ale zkusme to.","Det lyder for nemt, men lad os prøve.","Das klingt zu einfach, aber lass es uns versuchen.",,,"Esto suena muy fácil, pero intentémoslo.",,"Kuulostaa liian helpolta, mutta yritetään.",Ca à l'air trop facile mais ça vaut le coup d'essayer.,"Túl könnyűnek hangzik, de próbálkozzunk meg vele.","Sembra troppo facile, ma proviamoci.",簡単すぎるけど、一発かましてみましょうか。,"쉬운 일 같지만, 일단 한번 해보자고.","Dit klinkt te gemakkelijk, maar laten we het eens proberen.","Dette høres for enkelt ut, men la oss prøve.","To brzmi zbyt łatwo, ale spróbujmy.","Tá parecendo fácil demais, mas vamos tentar.",,"Sună ușor, dar să încercăm.",Слишком уж заманчиво. Хотя давай попытаемся.,,"Det här låter för enkelt, men vi gör ett försök.",Kulağa çok kolay geliyor ama bir deneyelim. +Who cares. Nobody listens to programmers anyway.,TXT_BBSUB_SCRIPT04_D40932_LETME,MAP04: Reactor Core → Southern alarm door,,,"Koho to zajímá, programátory stejně nikdo neposlouchá.",Det er ligegyldigt. Ingen lytter til programmører alligevel.,Egal! Wer hört schon auf Programmierer.,,,¿A quién le importa? Si nadie escucha a los programadores.,,Mitä väliä. Kukaan ei muutenkaan kuuntele ohjelmoijia.,"On s'en fout, personne n'écoute les programmeurs de toute manières.",Kit érdekel. Senki sem hallgat a programozókra.,A chi importa. Tanto nessuno sta a sentire i programmatori.,面倒ね。プログラマーについて知ってるのは誰もいないわ。,어쩌라고. 아무도 프로그래머들 이야기는 안 듣는데.,Wat maakt het uit. Niemand luistert sowieso naar programmeurs.,Hvem bryr seg? Ingen hører på programmerere uansett.,Kogo to obchodzi. I tak nikt nie słucha programistów.,Quem liga? Ninguém dá bola pros programadores mesmo.,,Cui îi pasă. Nimeni nu ascultă de programatori oricum.,Какая разница? Программистов всё равно никто не слушает.,,Vem bryr sig? Ingen lyssnar på programmerare ändå.,Kimin umurunda. Kimse programcıları dinlemiyor zaten. +"Ooh. Glad I'm in hiding, if you know what I mean.",TXT_BBSUB_SCRIPT04_D54576_ITSAS,〃,,,"Ou, jsem ráda, že se schovávám, jestli víš, co tím myslím.","Ooh. Jeg er glad for, at jeg gemmer mig, hvis du forstår, hvad jeg mener.","Uh. Wie gut, dass ich mich verstecke - du weißt schon was ich meine.",,,"Ooh. Menos mal que estoy escondida, si sabes a lo que me refiero.",,"Oo, onneksi olen piilossa, tiedätkö.","Ooh, je suis contente d'être cachée, si tu vois ce que je veux dire.","Óh. Még jó hogy ebújtam, már ha érted mire gondolok.","Ooh. Per fortuna che sono nascosta, se capisci cosa intendo.",オオゥ。私が言わなくてもわかるけど、隠れた方がいいわね。,"오, 내가 숨어있어서 다행이야. 무슨 뜻인지 알겠지?","Ooh. Blij dat ik ondergedoken zit, als je begrijpt wat ik bedoel.","Ooh. Jeg er glad jeg er i skjul, hvis du skjønner hva jeg mener.","Ooh. Cieszę się, że się ukrywam, jeśli wiesz, co mam na myśli.","Oooh. Ainda bem que estou escondida, se é que você me entende.",,"Ooh. Mă bucur că mă ascund, dacă știi ce zic.","Ой. Хорошо, что я в укрытии, если ты понимаешь, о чём я.",,"Ooh. Jag är glad att jag gömmer mig, om du förstår vad jag menar.","Ooh. Saklandığıma sevindim, ne demek istediğimi anlıyorsan." +What a grouch. I hope you get to kill him later.,TXT_BBSUB_SCRIPT05_D1516_OKBUT,MAP05: Door Guard.,,,"Takový mrzout. Doufám, že ho pak zabijeme.","Sikke en gnavpot. Jeg håber, du får lov til at dræbe ham senere.",Was für ein Ekel. Hoffentlich kannst du ihn später mal erledigen.,,"Kiel grumblema. Mi esperas, ke vi mortigos lin poste.",Qué gruñón. Espero que lo mates luego.,,Mikä hapannaama. Toivottavasti pääset tappamaan hänet myöhemmin.,Quel grincheux. J'espère qu'on va le buter plus tard.,Micsoda mogorva barom. Remélem később lehetőséged lesz megölni.,Che brontolone. Spero che ti ritrovi a ucciderlo dopo.,なに拗ねてるの。後で彼を殺すのを期待してるわ。,뭐가 이리 불만이야. 나중에 얘 좀 꼭 처리해줘.,Wat een humeur. Ik hoop dat je hem later kunt vermoorden.,For en grinebiter. Jeg håper du får drepe ham senere.,"Co za zrzęda. Mam nadzieję, że będziesz mógł go później zabić.",Que rabugento! Espero que você mate ele depois.,,Ce dobitoc. Sper să îl omori mai târziu.,"Ну и зануда. Надеюсь, ты потом вернёшься и снесёшь ему башку.",,Vilken gnällspik. Jag hoppas att du får döda honom senare.,Ne huysuz. Umarım onu daha sonra öldürürsün. +"""This area's off limits!"" Pompous so-and-so.",TXT_BBSUB_SCRIPT05_D3032_DOILO,〃,,,„Do této oblasti je vstup zakázán!“ Pompézní hajzl.,Dette område er forbudt område! Opblæste sådan-og-så.,„Zutritt verboten!“ Elendiger Wichtigtuer.,,,«Istí firi di lis límitis». Pero qué estirado.,«Istí firi di lis límitis». Pero qué creído.,"""Alueeseen on pääsy kielletty!"" Tärkeilevä mitäänsanomattomuus.","""Cette zone est à accès restreint!"" Pompeux anonyme, va.","""Tiltott a belépés!"" Persze már.","""Quest'area è ad accesso riservato!"" Pomposo miserabile.",この区域は立入禁止!'そんなワザとらしい。,“이곳은 통행 금지야!” 웃기고 앉아있네.,Dit gebied is verboden terrein! Pompous zo-en-zo.,Dette området er forbudt område! Pompøse så-og-så.,Ten teren jest niedostępny! Nadęty taki i taki.,"""Proibido entrar nessa área!"" Que miserável prepotente.",,"""Zona asta e interzisă!"" Pompos așa-și-așa.",«Здесь закрытая территория!» Надутый индюк.,,Det här området är förbjudet område! Pompösa sån och sån.,Burası yasak bölge! Kendini beğenmiş herif. +What an up guy.,TXT_BBSUB_SCRIPT05_D4548_THEOR,MAP05: Prison Guard.,,,Takový veselý chlapík!,Sikke en opblæst fyr.,Was für ein Blödmann.,,,Menudo idiota.,Qué «agradable» sujeto.,Mikä höhlä.,Quel type honnête.,De egy hülye.,Che idiota.,あら、いい男。,아주 들떠있는 녀석이네.,Wat een geweldige kerel.,For en oppblåst fyr.,Co za gość.,Que imbecil.,,Ce tip.,Какой хороший мальчик!,,Vilken uppkäftig kille.,Ne adam ama. +"Maybe it's because you didn't say ""please"".",TXT_BBSUB_SCRIPT05_D7580_OVERM,MAP05: Montag.,,,"Možná to je tím, žes neřekl „prosím“.","Måske er det fordi du ikke sagde ""tak"".",Vielleicht hättest du „Bitte“ sagen sollen.,,Eble ĉar vi ne diris «bonvole».,Habrá sido porque no has dicho «por favor».,Habrá sido porque no dijiste «por favor».,"Ehkä, koska et pyytänyt riittävän nätisi.","Peut être, c'est parce que tu n'a pas dit ""s'il vous plaît.""","Lehet mert nem mondtad hogy ""kérem szépen"".","Forse perché non hai detto ""per favore"".",多分貴方が'お願いします'と言わなかったからよ。,아마 네가 “부탁”을 안 해서 이러나 봐.,"Misschien is het omdat je niet ""alsjeblieft"" hebt gezegd.","Kanskje det er fordi du ikke sa ""vær så snill""?","Może to dlatego, że nie powiedziałeś ""proszę"".","Deve ser porque você não disse ""por favor"".",,"Poate pentru nu ai spus ""te rog"".","Наверное, ты забыл сказать «пожалуйста»?",,"Kanske är det för att du inte sa ""snälla"".","Belki de ""lütfen"" demediğin içindir." "Everybody is so needy. ",TXT_BBSUB_SCRIPT06_D1516_DOMYF,MAP06: Weran.,,,Každý toho tolik potřebuje.,"Alle er så trængende. -",Jeder hier ist so bedürftig!,,,Todo el mundo es tan necesitado.,,Kylläpä sitä nyt ollaan niin kaiken tarpeessa.,Tout le monde est tellement demandant.,Mindenkinek kell valami.,Tutti sono così bisognosi.,誰もがとても貧しいのよ。,다들 참 궁색하게 사네.,Iedereen is zo behoeftig.,"Alle er så trengende. +",Jeder hier ist so bedürftig!,,Ĉiuj estas tiel tropetemaj.,Cuánta gente interesada.,,Kylläpä sitä nyt ollaan niin kaiken tarpeessa.,Tout le monde est tellement demandant.,Mindenkinek kell valami.,Tutti sono così bisognosi.,誰もがとても貧しいのよ。,다들 참 궁색하게 사네.,Iedereen is zo behoeftig.,"Alle er så trengende. ","Wszyscy są tacy potrzebujący. -",Por que todo mundo é tão mimimizento?,,Toată lumea e așa neajutorată!,Тут все такие нуждающиеся!,,"Herkes çok muhtaç. +",Por que todo mundo é tão mimimizento?,,Toată lumea e așa neajutorată!,Тут все такие нуждающиеся!,,"Alla är så behövande. +","Herkes çok muhtaç. " -Great. Now we're shopping for the Rat King.,TXT_BBSUB_SCRIPT06_D3032_BRING,〃,,,"Super, teď máme nakupovat pro Krysího krále.",Alle er så trængende. Nu skal vi købe ind til rottekongen.,"Klasse, jetzt machen wir die Arbeit für den Rattenkönig.",,,Genial. Ahora vamos de compras para el Rey de las Ratas.,,"Loistavaa, hoidamme nyt Rottakuninkaan ostoksia.","Parfait, maintenant on fait du shopping pour le roi des rats.",Kiváló. A Patkány Király bevásárlói lettünk.,Grandioso. Adesso stiamo facendo shopping con il re dei ratti.,素敵ね。私達がラットキングのために買い物とか。,끝내준다. 이제 시궁쥐 왕의 심부름도 해야 한다니.,Geweldig. Nu zijn we aan het winkelen voor de rattenkoning.,Flott. Nå handler vi til Rottekongen.,Świetnie. Teraz robimy zakupy dla Króla Szczurów.,Que beleza. Agora estamos fazendo comprinhas pro Rato-Rei.,,Grozav. Acum facem cumpărături pentru Regele Șobolanilor.,Классно. Мы идём за покупками для Крысиного короля.,,Harika. Şimdi de Fare Kral için alışveriş yapıyoruz. -"I bet this guy smells really bad, too.",TXT_BBSUB_SCRIPT06_D4548_OPENT,〃,,,"Hádám, že tenhle chlápek taky pěkně smrdí.","Jeg vil vædde med, at han også lugter rigtig dårligt.","Ich wette, dieser Kerl riecht auch übel.",,,"Apuesto a que este tipo huele muy mal, también.",,"Lyön vetoa, että tämä tyyppi myös haisee tosi pahalta.","Je parie que ce type sent salement mauvais, aussi.","Le merném fogadni, hogy ez a pacák is büdös.",Scommetto che questo tizio ha pure un cattivo odore.,この男も酷い悪臭がすると賭けるわ。,얘도 분명 냄새 하나는 죽여줄 거야.,Ik durf te wedden dat deze kerel ook heel erg stinkt.,Jeg vedder på at denne fyren også lukter fælt.,"Założę się, że ten facet też bardzo śmierdzi.",Aposto que esse cara fede pra caramba também.,,Pun pariu că tipul ăsta mai și pute.,"Уверена, этот парень воняет особенно ужасно.",,Eminim bu adam da çok kötü kokuyordur. -More sewers... Great. Wonder what lives down there.,TXT_BBSUB_SCRIPT06_D9096_YOUHA,〃,,,"Další stoky... skvělý. Zajímalo by mě, co tam dole žije.",Flere kloakker... Fedt. Gad vide hvad der bor dernede.,"Mehr Kanäle, toll... Ich frage mich, was da unten lebt.",,,Más alcantarillas... Genial. Me pregunto qué vivirá ahí abajo.,,Lisää viemäreitä... Mahtavaa. Kukakohan elää täällä alhaalla.,Plus d'égouts.. Youpi. Je me demande qui vit là dedans.,Még több kanális... kiváló. Mi lakhat odalent?,Altre fogne... fantastico. Mi domando cosa vive qua giù.,更なる下水道...ヤッバ。下に何が住んでるのか不思議に思うわ。,또 하수도라... 끝내준다. 저 아래에 또 뭐가 살고 있을까?,Meer riolering.... Geweldig. Ik vraag me af wat daar beneden leeft.,Mer kloakk... Flott. Lurer på hva som bor der nede.,Więcej kanałów... Świetnie. Ciekawe co tam mieszka.,Mais esgotos... Que legal. O que será que vive lá embaixo?,,Mai multe canale... Grozav. Mă întreb ce-o mai trăi jos aici.,"Снова канализация... Замечательно. Интересно, кого мы там встретим?",,Daha fazla kanalizasyon. Harika. Acaba orada ne yaşıyor? -Dead end here. We'd better keep looking.,TXT_BBSUB_SCRIPT07_D6064_PROGR,MAP07: Computer room.,,,Tudy cesta nevede. Měli bychom se podívat dál.,Det er en blindgyde her. Vi må hellere lede videre.,Sackgasse. Wir sollten es woanders versuchen.,,,Un callejón sin salida. Deberíamos seguir buscando.,,Umpikuja tässä. Parasta jatkaa etsintää.,"Une impasse. Bon, on continue de chercher.",Zsákutca. Folytatnunk kell a keresést.,Qui c'è un vicolo cieco. Meglio continuare a guardare.,行き止まりだ。私達はまだこの景色を楽しめるわ。,여기가 아닌가 봐. 다른 곳을 찾아봐야겠어.,Doodlopend hier. We kunnen maar beter blijven zoeken.,Blindvei her. Vi får lete videre.,Tu jest ślepy zaułek. Lepiej szukajmy dalej.,Sem saída aqui. Melhor seguirmos procurando.,,Capăt de linie. Mai bine ne mai uităm împrejur.,Тупик. Давай продолжать поиски.,,Burası çıkmaz sokak. Aramaya devam etsek iyi olur. +Great. Now we're shopping for the Rat King.,TXT_BBSUB_SCRIPT06_D3032_BRING,〃,,,"Super, teď máme nakupovat pro Krysího krále.",Alle er så trængende. Nu skal vi købe ind til rottekongen.,"Klasse, jetzt machen wir die Arbeit für den Rattenkönig.",,,Genial. Ahora vamos de compras para el Rey de las Ratas.,,"Loistavaa, hoidamme nyt Rottakuninkaan ostoksia.","Parfait, maintenant on fait du shopping pour le roi des rats.",Kiváló. A Patkány Király bevásárlói lettünk.,Grandioso. Adesso stiamo facendo shopping con il re dei ratti.,素敵ね。私達がラットキングのために買い物とか。,끝내준다. 이제 시궁쥐 왕의 심부름도 해야 한다니.,Geweldig. Nu zijn we aan het winkelen voor de rattenkoning.,Flott. Nå handler vi til Rottekongen.,Świetnie. Teraz robimy zakupy dla Króla Szczurów.,Que beleza. Agora estamos fazendo comprinhas pro Rato-Rei.,,Grozav. Acum facem cumpărături pentru Regele Șobolanilor.,Классно. Мы идём за покупками для Крысиного короля.,,Toppen. Nu ska vi shoppa för råttkungen.,Harika. Şimdi de Fare Kral için alışveriş yapıyoruz. +"I bet this guy smells really bad, too.",TXT_BBSUB_SCRIPT06_D4548_OPENT,〃,,,"Hádám, že tenhle chlápek taky pěkně smrdí.","Jeg vil vædde med, at han også lugter rigtig dårligt.","Ich wette, dieser Kerl riecht auch übel.",,,"Apuesto a que este tipo huele muy mal, también.",,"Lyön vetoa, että tämä tyyppi myös haisee tosi pahalta.","Je parie que ce type sent salement mauvais, aussi.","Le merném fogadni, hogy ez a pacák is büdös.",Scommetto che questo tizio ha pure un cattivo odore.,この男も酷い悪臭がすると賭けるわ。,얘도 분명 냄새 하나는 죽여줄 거야.,Ik durf te wedden dat deze kerel ook heel erg stinkt.,Jeg vedder på at denne fyren også lukter fælt.,"Założę się, że ten facet też bardzo śmierdzi.",Aposto que esse cara fede pra caramba também.,,Pun pariu că tipul ăsta mai și pute.,"Уверена, этот парень воняет особенно ужасно.",,Jag slår vad om att den här killen luktar riktigt illa också.,Eminim bu adam da çok kötü kokuyordur. +More sewers... Great. Wonder what lives down there.,TXT_BBSUB_SCRIPT06_D9096_YOUHA,〃,,,"Další stoky... skvělý. Zajímalo by mě, co tam dole žije.",Flere kloakker... Fedt. Gad vide hvad der bor dernede.,"Mehr Kanäle, toll... Ich frage mich, was da unten lebt.",,,Más alcantarillas... Genial. Me pregunto qué vivirá ahí abajo.,,Lisää viemäreitä... Mahtavaa. Kukakohan elää täällä alhaalla.,Plus d'égouts.. Youpi. Je me demande qui vit là dedans.,Még több kanális... kiváló. Mi lakhat odalent?,Altre fogne... fantastico. Mi domando cosa vive qua giù.,更なる下水道...ヤッバ。下に何が住んでるのか不思議に思うわ。,또 하수도라... 끝내준다. 저 아래에 또 뭐가 살고 있을까?,Meer riolering.... Geweldig. Ik vraag me af wat daar beneden leeft.,Mer kloakk... Flott. Lurer på hva som bor der nede.,Więcej kanałów... Świetnie. Ciekawe co tam mieszka.,Mais esgotos... Que legal. O que será que vive lá embaixo?,,Mai multe canale... Grozav. Mă întreb ce-o mai trăi jos aici.,"Снова канализация... Замечательно. Интересно, кого мы там встретим?",,Mer kloaker... Toppen. Undrar vad som bor där nere.,Daha fazla kanalizasyon. Harika. Acaba orada ne yaşıyor? +Dead end here. We'd better keep looking.,TXT_BBSUB_SCRIPT07_D6064_PROGR,MAP07: Computer room.,,,Tudy cesta nevede. Měli bychom se podívat dál.,Det er en blindgyde her. Vi må hellere lede videre.,Sackgasse. Wir sollten es woanders versuchen.,,,Un callejón sin salida. Deberíamos seguir buscando.,,Umpikuja tässä. Parasta jatkaa etsintää.,"Une impasse. Bon, on continue de chercher.",Zsákutca. Folytatnunk kell a keresést.,Qui c'è un vicolo cieco. Meglio continuare a guardare.,行き止まりだ。私達はまだこの景色を楽しめるわ。,여기가 아닌가 봐. 다른 곳을 찾아봐야겠어.,Doodlopend hier. We kunnen maar beter blijven zoeken.,Blindvei her. Vi får lete videre.,Tu jest ślepy zaułek. Lepiej szukajmy dalej.,Sem saída aqui. Melhor seguirmos procurando.,,Capăt de linie. Mai bine ne mai uităm împrejur.,Тупик. Давай продолжать поиски.,,Det är en återvändsgränd här. Det är bäst att fortsätta leta.,Burası çıkmaz sokak. Aramaya devam etsek iyi olur. "Onward, my champion. Let's make Mr. Ugly twist and shout. -",TXT_BBSUB_SCRIPT10_D10612_YOUHA,,,,"Kupředu, můj šampióne. Pojďme pana Ošklivu hezky nakopat.","Fremad, min mester. Lad os få hr. Grimme til at vride sig og skrige. -",Und weiter gehts. Lass die Hackfresse zittern!,,,"Adelante, mi campeón. Hagamos al Sr. Feo retorcerse y gritar.",,"Eteenpäin, sotaurhoni. Pannaan Herra Rumilus vääntelehtimään ja huutamaan.",Allons-y mon champion. Allons tordre de douleur Monsieur Sale-geule.,Gyerünk bajnokom. Ne várakoztassuk meg Ocsmány urat.,"Vai avanti, mio campione. Facciamo agitare e urlare il signor Brutto.",進み出よ、わがチャンピオン。ミスター生塵を捻りつぶしてやれ。,"어서 가자, 나의 영웅. 그 못생긴 녀석에게 본때를 보여주자고.","Vooruit, mijn kampioen. Laten we Mr. Ugly aan het draaien en schreeuwen zetten.","Fremad, min mester. La oss få Mr. Ugly til å vri seg og rope. -","Naprzód, mój mistrzu. Sprawmy, by Pan Brzydki skręcał się i krzyczał. -","Vai em frente, meu campeão. Vamos fazer o Sr. Feioso soltar a franga.",,"Drept în față, campionul meu. Să-l facem pe dl. Urât să țipe.","Вперёд, мой защитник. Заставим Г-на Урода сплясать и спеть.",,"İleri, şampiyonum. Bay Çirkin'i döndürelim ve bağırtalım. +",TXT_BBSUB_SCRIPT10_D10612_YOUHA,MAP10: Macil (Possible reference to a song of The Beatles).,,,"Kupředu, můj šampióne. Pojďme pana Ošklivu hezky nakopat.","Fremad, min mester. Lad os få hr. Grimme til at vride sig og skrige. +",Und weiter gehts. Lass die Hackfresse zittern!,,,"Adelante, mi campeón. Hagamos al Sr. Feo retorcerse y gritar.",,"Eteenpäin, sotaurhoni. Pannaan Herra Rumilus vääntelehtimään ja huutamaan.",Allons-y mon champion. Allons tordre de douleur Monsieur Sale-geule.,Gyerünk bajnokom. Ne várakoztassuk meg Ocsmány urat.,"Vai avanti, mio campione. Facciamo agitare e urlare il signor Brutto.",進み出よ、わがチャンピオン。ミスター生塵を捻りつぶしてやれ。,"어서 가자, 나의 영웅. 그 못생긴 녀석에게 본때를 보여주자고.","Voorwaarts, mijn kampioen. Laten we Mr Lelijk laten draaien en schreeuwen.","Fremad, min mester. La oss få herr Stygg til å vri seg og rope.","Naprzód, mój mistrzu. Sprawmy, by Pan Brzydki skręcał się i krzyczał. +","Vai em frente, meu campeão. Vamos fazer o Sr. Feioso soltar a franga.",,"Drept în față, campionul meu. Să-l facem pe dl. Urât să țipe.","Вперёд, мой защитник. Заставим Г-на Урода сплясать и спеть.",,"Framåt, min mästare. Låt oss få herr Ful att vrida sig och skrika.","İleri, şampiyonum. Bay Çirkin'i döndürelim ve bağırtalım. " "Biomechanical? Well, that explains their seemingly endless supply of troops! And their bad attitude. ",TXT_BBSUB_SCRIPT10_D12128_THERE,,,,Biomechanické? Tak to vysvětluje jejich zdánlivě nekonečné zásoby vojáků! A jejich špatnou náladu.,"Biomekanisk? Nå, det forklarer deres tilsyneladende uendelige forsyning af tropper! Og deres dårlige indstilling. -",Biomechanisch? Das erklärt ihren anscheinend endlosen Nachschub an Truppen. Und ihre miese Gesinnung.,,,"¿Biomecánico? Bueno, ¡eso explica su aparentemente infinito suministro de tropas! Y su mala actitud.",,Biomekaanisia? No se selittää heidän joukkojensa näennäisen ehtymättömän lähteen! Ja heidän pahan asenteensa.,"Biomécanique? Et bien, ça explique pourquoi ils en ont une infinité, de troupes! Ca, et leur sale heumeur.","Biomechanikus? Nos, ez megmagyarázza a majdnem végtelen számukat. És a viselkedésüket is.","Biomeccanici? Beh, questo spiegherebbe la fornitura apparentemente infinita di truppe! Ed il loro brutto carattere.","生体工学'?どうやら奴等は軍隊を無限供給しているという訳だ! +",Biomechanisch? Das erklärt ihren anscheinend endlosen Nachschub an Truppen. Und ihre miese Gesinnung.,,,"¿Biomecánicos? Bueno, ¡eso explicaría su suministro de tropas aparentemente infinito! Y su mal carácter.",,Biomekaanisia? No se selittää heidän joukkojensa näennäisen ehtymättömän lähteen! Ja heidän pahan asenteensa.,"Biomécanique? Et bien, ça explique pourquoi ils en ont une infinité, de troupes! Ca, et leur sale heumeur.","Biomechanikus? Nos, ez megmagyarázza a majdnem végtelen számukat. És a viselkedésüket is.","Biomeccanici? Beh, questo spiegherebbe la fornitura apparentemente infinita di truppe! Ed il loro brutto carattere.","生体工学'?どうやら奴等は軍隊を無限供給しているという訳だ! それと態度が悪いことも。 ","인간개조? 음, 이거 때문에 녀석들이 끊임없이 나오는 거였어! 녀석들 성질 더러운 것도 그렇고.","Biomechanisch? Nou, dat verklaart hun schijnbaar eindeloze voorraad aan troepen! En hun slechte houding.","Biomekanisk? Vel, det forklarer deres tilsynelatende endeløse tilførsel av tropper! Og den dårlige holdningen deres. ","Biomechaniczne? To wyjaśnia ich pozornie nieskończoną ilość żołnierzy! I ich złe nastawienie. -","Biomecânicos? Bom, deve ser por isso que o número de soldados parece não ter fim! Deve explicar os péssimos comportamentos também.",,Biomecanic? Asta explică rezerva lor de trupe aproape infinită! Și atitudinea lor oribilă.,"Биомеханических? Что ж, теперь ясно, почему их солдаты не заканчиваются! И почему они так отвратительно себя ведут.",,"Biyomekanik mi? Bu onların görünüşte sonsuz asker kaynağını açıklıyor! Ve kötü tutumlarını. +","Biomecânicos? Bom, deve ser por isso que o número de soldados parece não ter fim! Deve explicar os péssimos comportamentos também.",,Biomecanic? Asta explică rezerva lor de trupe aproape infinită! Și atitudinea lor oribilă.,"Биомеханических? Что ж, теперь ясно, почему их солдаты не заканчиваются! И почему они так отвратительно себя ведут.",,"Biomekaniskt? Det förklarar deras till synes oändliga tillgång på trupper! Och deras dåliga attityd. +","Biyomekanik mi? Bu onların görünüşte sonsuz asker kaynağını açıklıyor! Ve kötü tutumlarını. " -Sick fuck... Waste him!,TXT_BBSUB_SCRIPT10_D16676_IAMTH,,,,Podlý sráč... Zab ho!,Syge svin... Smid ham ud!,Der Typ ist doch krank. Mach ihn alle.,,,Maldito enfermo... ¡Cárgatelo!,,Sairas kusipää... Listi hänet!,"Quel salaud, bute le!",Beteg állat... Nyírd ki!,È malato marcio... Fallo fuori!,クソ腹立つ...!野郎を消せ!,역겨운 자식... 죽여버려!,Zieke klootzakken.... Verspil hem!,Syke jævel... Drep ham!,Chory skurwiel... Zmarnuj go!,Doente do caralho... Acaba com ele!,,Dobitoc bolnav... Nimicește-l!,Больной ублюдок... Мочи его!,,Hasta herif. Harca onu! -"He may be ugly, but it seems like he's on our side.",TXT_BBSUB_SCRIPT12_D12128_USETH,,,,"Možná je ošklivý, ale zdá se, že je na naší straně.","Han er måske grim, men det ser ud til, at han er på vores side.","Er mag ja hässlich sein, aber es sieht aus als ob er auf unserer Seite sei.",,,"Puede que sea feo, pero parece que está de nuestro lado.",,"Hän on ehkä ruma, mutta hän vaikuttaa olevan meidän puolellamme.","Il est hideux, mais il semble qu'il soit de notre côté.","Lehet hogy igen ronda szegény, de legalább a mi oldalunkon áll.","Può essere brutto, ma sembra che sia dalla nostra parte.",彼は醜いだろうが、我々に味方している。,"이 양반 못생기긴 했어도, 우리 편인 것 같네.","Hij is misschien lelijk, maar het lijkt erop dat hij aan onze kant staat.","Han er kanskje stygg, men det virker som om han er på vår side.","Może i jest brzydki, ale wygląda na to, że jest po naszej stronie.","Ele pode ser feio, mas parece que ele está no nosso lado.",,"O fi urât, dar pare să fie de partea noastră.","Пусть он и урод, но, похоже, он на нашей стороне.",,Çirkin olabilir ama bizim tarafımızda gibi görünüyor. -"Judging by recent history, I guess stealth is out.",TXT_BBSUB_SCRIPT17_D10612_OHSUR,,,,"Soudě podle naší nedávné historie hádám, že pokradmu to nepůjde.","At dømme ud fra den seneste historie, så er det vist ikke muligt at gå i smug.","Nach den jüngsten Geschehnissen zu urteilen, ist Tarnung nicht drin.",,,"Juzgando por nuestro historial reciente, supongo que el sigilo queda descartado.",,Lähimenneisyyden perusteella hiiviskely ei varmaankaan tule kysymykseen.,"En se basant sur ce qui vient de se passer, je pense que la discrétion n'est pas une option.",A rövidmúltból kiindulva a lopakodás nem lehetőség.,"A giudicare dalla storia recente, suppongo che essere furtivi sia da scartare.",最近の記録から判断すると、秘密は公になると私は思う。,"최근 상황을 보건대, 잠입 작전은 힘들 것 같아.","Te oordelen naar de recente geschiedenis, denk ik dat heimelijkheid uit is.","Å dømme etter det som har skjedd, er det visst slutt på å snike.","Sądząc po ostatniej historii, chyba nie ma mowy o ukrywaniu się.","Julgando pelo nosso histórico recente, acho que cautela está fora de questão.",,"Uitându-ne la istoria recentă, cred că silențiozitatea iese din ecuație.","Судя по недавним событиям, можно больше не прятаться.",,"Yakın geçmişe bakılırsa, sanırım gizlilik devre dışı." +Sick fuck... Waste him!,TXT_BBSUB_SCRIPT10_D16676_IAMTH,,,,Podlý sráč... Zab ho!,Syge svin... Smid ham ud!,Der Typ ist doch krank. Mach ihn alle.,,,Maldito enfermo... ¡Cárgatelo!,,Sairas kusipää... Listi hänet!,"Quel salaud, bute le!",Beteg állat... Nyírd ki!,È malato marcio... Fallo fuori!,クソ腹立つ...!野郎を消せ!,역겨운 자식... 죽여버려!,Zieke klootzakken.... Verspil hem!,Syke jævel... Drep ham!,Chory skurwiel... Zmarnuj go!,Doente do caralho... Acaba com ele!,,Dobitoc bolnav... Nimicește-l!,Больной ублюдок... Мочи его!,,Sjuka jävlar... Slå honom ihjäl!,Hasta herif. Harca onu! +"He may be ugly, but it seems like he's on our side.",TXT_BBSUB_SCRIPT12_D12128_USETH,,,,"Možná je ošklivý, ale zdá se, že je na naší straně.","Han er måske grim, men det ser ud til, at han er på vores side.","Er mag ja hässlich sein, aber es sieht aus als ob er auf unserer Seite sei.",,,"Podrá ser feo, pero parece estar de nuestro lado.",,"Hän on ehkä ruma, mutta hän vaikuttaa olevan meidän puolellamme.","Il est hideux, mais il semble qu'il soit de notre côté.","Lehet hogy igen ronda szegény, de legalább a mi oldalunkon áll.","Può essere brutto, ma sembra che sia dalla nostra parte.",彼は醜いだろうが、我々に味方している。,"이 양반 못생기긴 했어도, 우리 편인 것 같네.","Hij is misschien lelijk, maar het lijkt erop dat hij aan onze kant staat.","Han er kanskje stygg, men det virker som om han er på vår side.","Może i jest brzydki, ale wygląda na to, że jest po naszej stronie.","Ele pode ser feio, mas parece que ele está no nosso lado.",,"O fi urât, dar pare să fie de partea noastră.","Пусть он и урод, но, похоже, он на нашей стороне.",,"Han må vara ful, men det verkar som om han är på vår sida.",Çirkin olabilir ama bizim tarafımızda gibi görünüyor. +"Judging by recent history, I guess stealth is out.",TXT_BBSUB_SCRIPT17_D10612_OHSUR,,,,"Soudě podle naší nedávné historie hádám, že pokradmu to nepůjde.","At dømme ud fra den seneste historie, så er det vist ikke muligt at gå i smug.","Nach den jüngsten Geschehnissen zu urteilen, ist Tarnung nicht drin.",,,"Juzgando nuestro historial reciente, supongo que el sigilo queda descartado.",,Lähimenneisyyden perusteella hiiviskely ei varmaankaan tule kysymykseen.,"En se basant sur ce qui vient de se passer, je pense que la discrétion n'est pas une option.",A rövidmúltból kiindulva a lopakodás nem lehetőség.,"A giudicare dalla storia recente, suppongo che essere furtivi sia da scartare.",最近の記録から判断すると、秘密は公になると私は思う。,"최근 상황을 보건대, 잠입 작전은 힘들 것 같아.","Te oordelen naar de recente geschiedenis, denk ik dat heimelijkheid uit is.","Å dømme etter det som har skjedd, er det visst slutt på å snike.","Sądząc po ostatniej historii, chyba nie ma mowy o ukrywaniu się.","Julgando pelo nosso histórico recente, acho que cautela está fora de questão.",,"Uitându-ne la istoria recentă, cred că silențiozitatea iese din ecuație.","Судя по недавним событиям, можно больше не прятаться.",,"Att döma av den senaste historien, antar jag att smygande är uteslutet.","Yakın geçmişe bakılırsa, sanırım gizlilik devre dışı." "Hmm. No fuss, no muss, nothing for mom to clean up... Get me one, please. ",TXT_BBSUB_SCRIPT17_D13644_OHWEL,This remark is for information about the maulers in the warehouse.,,,"Hmm. Žádný rámus, žádný bordel, maminka nemusí nic uklízet... Taky mi jeden vem, prosím!","Hmm. Ingen ballade, ingen ballade, intet for mor at rydde op... Giv mig en, tak. -",Hmm. Lass nichts anbrennen. Hol mir bitte so ein Ding.,,,"Hmm. Sin dejar restos, nada que mamá tenga que limpiar... Dame uno, por favor.",,"Hmm, pulinat pois, ei jätetä äidille mitään siivottavaa... Saisinko yhden, kiitos.","Hmm. Pas de boucan, pas de bordel, rien que maman à besoin de nettoyer après.. Récupère en un pour moi, s'il te plaît.",Hmm. Könnyen ment mint az ágybavizelés... Hozz nekem egyet kérlek.,"Mm. Non protesta, fa zero residui, nulla da far pulire a mamma... Dammene uno, per favore.","うーむ。慌てず、騒がず、ママの掃除も無し... +",Hmm. Lass nichts anbrennen. Hol mir bitte so ein Ding.,,,"Hmm. Sin dejar restos, nada que mamá tenga que limpiar... Dame uno, por favor.",,"Hmm, pulinat pois, ei jätetä äidille mitään siivottavaa... Saisinko yhden, kiitos.","Hmm. Pas de boucan, pas de bordel, rien que maman ait besoin de nettoyer après.. Récupère en un pour moi, s'il te plaît.",Hmm. Könnyen ment mint az ágybavizelés... Hozz nekem egyet kérlek.,"Mm. Non protesta, fa zero residui, nulla da far pulire a mamma... Dammene uno, per favore.","うーむ。慌てず、騒がず、ママの掃除も無し... 何か一杯お願い。",흠. 이유 없이 그런 소문이 났을 리는 없을 테고... 나도 그 무기 하나만 가져다줘.,"Hmm. Geen gedoe, geen muss, niets voor mama om op te ruimen... Haal me er een, alsjeblieft.","Ikke noe oppstyr, ikke noe for mamma å rydde opp... Gi meg en, er du snill. ","Hmm. Żadnego zamieszania, żadnego bałaganu, nic dla mamy do sprzątania... Daj mi jeden, proszę. -","Hmm. Sem choradeira, nem sujeira, nada pra mamãe ter que limpar... Pega um pra mim, por favor.",,"Hmm. Nu-i deranj, nu mizerie, nu nimic... Adu-mi unul, te rog.","Хм-м. Ни шума, ни пыли, мама не заставит убираться... Достань мне одно такое, пожалуйста!",,"Hmm. Yaygara yok, karışıklık yok, annemin temizleyeceği bir şey yok... Bana bir tane getir, lütfen. +","Hmm. Sem choradeira, nem sujeira, nada pra mamãe ter que limpar... Pega um pra mim, por favor.",,"Hmm. Nu-i deranj, nu mizerie, nu nimic... Adu-mi unul, te rog.","Хм-м. Ни шума, ни пыли, мама не заставит убираться... Достань мне одно такое, пожалуйста!",,"Hmm. Inget krångel, inget krångel, inget för mamma att städa upp... Ge mig en, tack. +","Hmm. Yaygara yok, karışıklık yok, annemin temizleyeceği bir şey yok... Bana bir tane getir, lütfen. " "You think I'd get tired of all this killing everyone stuff, but I know I'm going to miss it when it's over. ",TXT_BBSUB_SCRIPT31_D0_OHNOI,MAP31,,,"Řekl bys, že by mě všechno tohle zabíjení začalo unavovat, ale stejně vím, že mi to bude chybět, až tohle všechno skončí.","Man skulle tro, at jeg ville blive træt af alt det her med at dræbe alle, men jeg ved, at jeg kommer til at savne det, når det er slut. ","Man könnte denken, dass man von dieser „alle töten“-Sache müde wird, aber ich weiß, ich werde es vermissen, wenn alles vorbei ist.",,,"Pensarás que me cansaría de esto de matar a todo el mundo, pero sé que lo echaré de menos cuando se acabe.",,"Sitä luulisi, että kyllästyisin tähän ""tapan kaikki""-touhuun, mutta tiedän, että jään kaipaamaan sitä, kun tämä on ohi.","On pensrai que j'en aurai marre de cette routine de ""tue tout le monde"", mais je crois que ça va me manquer quand on en aura fini.","Azt hinné az ember, hogy belefáradok ebbe a gyilkolászósdiba, de tudom hogy hiányozni fog ha mind ennek vége.","Potresti pensare che io mi stia stancando di questa routine di ""uccidere tutti"", ma so già che mi mancherà quando tutto sarà finito.","貴方は全ての人々が殺害される事にうんざりしていると思うわ、 でも私は全てが終わったら見逃すと知っている。","내가 사람들 죽이는 걸 지겨워할 것 같지만, 이 일이 모두 끝나면 아마 그리워할 거야.","Je denkt dat ik moe zou worden van al deze moorden, maar ik weet dat ik het ga missen als het voorbij is.","Man skulle tro jeg ville bli lei av å drepe alle, men jeg kommer til å savne det når det er over. ","Myślisz, że znudzi mnie to całe zabijanie wszystkich, ale wiem, że będzie mi tego brakowało, kiedy to się skończy. -","Você deve achar que fico cansada de toda essa matança, mas sei que vou sentir falta disso quando acabar.",,"Crezi că m-am săturat de toată chestia asta de a ucide totul, dar îmi va lipsi odată ce totul se va termina.","Ты думаешь, что я устану от всех этих убийств? Нет, на самом деле мне их будет не хватать.",,"Tüm bu herkesi öldürme işinden yorulacağımı sanıyorsunuz ama bittiğinde özleyeceğimi biliyorum. +","Você deve achar que fico cansada de toda essa matança, mas sei que vou sentir falta disso quando acabar.",,"Crezi că m-am săturat de toată chestia asta de a ucide totul, dar îmi va lipsi odată ce totul se va termina.","Ты думаешь, что я устану от всех этих убийств? Нет, на самом деле мне их будет не хватать.",,"Man tror att jag skulle tröttna på allt det här med att döda alla, men jag vet att jag kommer att sakna det när det är över. +","Tüm bu herkesi öldürme işinden yorulacağımı sanıyorsunuz ama bittiğinde özleyeceğimi biliyorum. " \ No newline at end of file diff --git a/wadsrc_lights/CMakeLists.txt b/wadsrc_lights/CMakeLists.txt index 4f9d87d7cd..57a493dcdd 100644 --- a/wadsrc_lights/CMakeLists.txt +++ b/wadsrc_lights/CMakeLists.txt @@ -1,3 +1 @@ -cmake_minimum_required( VERSION 3.1.0 ) - add_pk3(lights.pk3 ${CMAKE_CURRENT_SOURCE_DIR}/static) diff --git a/wadsrc_lights/static/filter/doom.freedoom/gldefs.txt b/wadsrc_lights/static/filter/doom.freedoom/gldefs.txt index 6e9bb13364..9cf9bc45fa 100644 --- a/wadsrc_lights/static/filter/doom.freedoom/gldefs.txt +++ b/wadsrc_lights/static/filter/doom.freedoom/gldefs.txt @@ -365,19 +365,36 @@ object TechLamp2 } // Tall tech lamp -pulselight BIGLAMP +pointlight BIGLAMP1 { - color 1.0 0.4 0.4 + color 1.0 0.9 0.4 size 100 - secondarySize 80 - interval 0.4 + offset 0 72 0 + attenuate 1 +} + +pointlight BIGLAMP2 +{ + color 0.97 0.87 0.37 + size 99 + offset 0 72 0 + attenuate 1 +} + +pointlight BIGLAMP3 +{ + color 0.94 0.84 0.34 + size 98 offset 0 72 0 attenuate 1 } object TechLamp { - frame TLMP { light BIGLAMP } + frame TLMPA { light BIGLAMP1 } + frame TLMPB { light BIGLAMP2 } + frame TLMPC { light BIGLAMP3 } + frame TLMPD { light BIGLAMP2 } } // Tall red torch @@ -522,6 +539,21 @@ object Candlestick frame CAND { light CANDLE } } +// Floating Skull Rock +pulselight SKULLROCK +{ + color 0.5 0.4 0.1 + offset 0 5 0 + size 60 + secondarysize 40 + interval 0.6 + attenuate 1 +} +object FloatingSkull +{ + frame FSKU { light SKULLROCK } +} + // ---------------- // -- Doom Items -- // ---------------- @@ -575,12 +607,15 @@ object InvulnerabilitySphere } // Blur Sphere -pointlight BLURSPHERE1 +pulselight BLURSPHERE1 { - color 0.5 0.5 0.5 - size 60 + color 0.6 0.6 0.6 + size 40 + secondarysize 35 offset 0 16 0 + subtractive 1 attenuate 1 + interval 0.3 } object BlurSphere @@ -670,20 +705,36 @@ object RedSkull // Both armor pickups have a big red blinking light in the middle pointlight GREENARMOR2 { - color 0.4 0.0 0.0 + color 0.1 0.2 0.0 size 40 attenuate 1 offset 0 10 0 } +pointlight REDARMOR +{ + color 0.2 0.0 0.0 + size 40 + attenuate 1 + offset 0 10 0 +} +pointlight ARMORLITE +{ + color 0.4 0.0 0.0 + size 10 + attenuate 1 + offset 0 20 0 +} object GreenArmor { - frame ARM1B { light GREENARMOR2 } + frame ARM1 { light GREENARMOR2 } + frame ARM1B { light ARMORLITE } } object BlueArmor { - frame ARM2B { light GREENARMOR2 } + frame ARM2 { light REDARMOR } + frame ARM2B { light ARMORLITE } } diff --git a/wadsrc_widepix/CMakeLists.txt b/wadsrc_widepix/CMakeLists.txt index 83ed458e3f..8151a60d3d 100644 --- a/wadsrc_widepix/CMakeLists.txt +++ b/wadsrc_widepix/CMakeLists.txt @@ -1,3 +1 @@ -cmake_minimum_required( VERSION 3.1.0 ) - add_pk3(game_widescreen_gfx.pk3 ${CMAKE_CURRENT_SOURCE_DIR}/static)